Import Cobalt 10.58719
diff --git a/src/cobalt/audio/audio_node.cc b/src/cobalt/audio/audio_node.cc
index 1f561ee..387ef83 100644
--- a/src/cobalt/audio/audio_node.cc
+++ b/src/cobalt/audio/audio_node.cc
@@ -34,6 +34,10 @@
   RemoveAllOutputs();
 }
 
+scoped_refptr<AudioContext> AudioNode::context() const {
+  return audio_context_;
+}
+
 void AudioNode::set_channel_count(uint32 channel_count,
                                   script::ExceptionState* exception_state) {
   AudioLock::AutoLock lock(audio_lock());
diff --git a/src/cobalt/audio/audio_node.h b/src/cobalt/audio/audio_node.h
index b956d30..5e5f8e3 100644
--- a/src/cobalt/audio/audio_node.h
+++ b/src/cobalt/audio/audio_node.h
@@ -62,7 +62,7 @@
   // Web API: AudioNode
   //
   // The AudioContext which owns this AudioNode.
-  AudioContext* context() const { return audio_context_; }
+  scoped_refptr<AudioContext> context() const;
 
   // The number of inputs feeding into the AudioNode. For source nodes, this
   // will be 0.
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 765245a..5c3231b 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -34,6 +34,8 @@
 #include "cobalt/base/localized_strings.h"
 #include "cobalt/base/user_log.h"
 #include "cobalt/browser/memory_settings/auto_mem.h"
+#include "cobalt/browser/memory_settings/checker.h"
+#include "cobalt/browser/memory_settings/pretty_print.h"
 #include "cobalt/browser/memory_tracker/tool.h"
 #include "cobalt/browser/switches.h"
 #include "cobalt/loader/image/image_decoder.h"
@@ -328,7 +330,8 @@
 void ApplyAutoMemSettings(const memory_settings::AutoMem& auto_mem,
                           BrowserModule::Options* options) {
   std::stringstream ss;
-  ss << "\n\n" << auto_mem.ToPrettyPrintString() << "\n\n";
+  const bool enable_color = SbLogIsTty();
+  ss << "\n\n" << auto_mem.ToPrettyPrintString(enable_color) << "\n\n";
   SB_LOG(INFO) << ss.str();
 
   options->web_module_options.image_cache_capacity =
@@ -419,9 +422,13 @@
     options.web_module_options.javascript_options.disable_jit = true;
   }
 
-  memory_settings::AutoMem auto_mem(window_size, *command_line,
-                                    memory_settings::GetDefaultBuildSettings());
-  ApplyAutoMemSettings(auto_mem, &options);
+  auto_mem_.reset(
+      new memory_settings::AutoMem(
+          window_size,
+          *command_line,
+          memory_settings::GetDefaultBuildSettings()));
+
+  ApplyAutoMemSettings(*auto_mem_, &options);
 
 #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   if (command_line->HasSwitch(browser::switches::kNullSavegame)) {
@@ -807,45 +814,25 @@
 
 void Application::UpdatePeriodicStats() {
   TRACE_EVENT0("cobalt::browser", "Application::UpdatePeriodicStats()");
-#if defined(__LB_SHELL__)
-  bool memory_stats_updated = false;
-#if !defined(__LB_SHELL__FOR_RELEASE__)
-  if (LB::Memory::IsCountEnabled()) {
-    memory_stats_updated = true;
-
-    LB::Memory::Info memory_info;
-    lb_memory_get_info(&memory_info);
-
-    available_memory_ = memory_info.free_memory;
-    c_val_stats_.free_cpu_memory =
-        static_cast<size_t>(memory_info.free_memory);
-    c_val_stats_.used_cpu_memory =
-        static_cast<size_t>(memory_info.application_memory);
-    c_val_stats_.exe_memory = static_cast<size_t>(memory_info.executable_size);
-  }
-#endif  // defined(__LB_SHELL__FOR_RELEASE__)
-  // If the memory stats have not been updated yet, then simply use the
-  // unallocated memory as the available memory.
-  if (!memory_stats_updated) {
-    available_memory_ = lb_get_unallocated_memory();
-    c_val_stats_.free_cpu_memory = static_cast<size_t>(available_memory_);
-    c_val_stats_.used_cpu_memory =
-        lb_get_total_system_memory() - lb_get_unallocated_memory();
-  }
-#elif defined(OS_STARBOARD)
   int64_t used_cpu_memory = SbSystemGetUsedCPUMemory();
+  base::optional<int64_t> used_gpu_memory;
+  if (SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats)) {
+    used_gpu_memory = SbSystemGetUsedGPUMemory();
+  }
+
   available_memory_ =
       static_cast<ssize_t>(SbSystemGetTotalCPUMemory() - used_cpu_memory);
   c_val_stats_.free_cpu_memory = available_memory_;
   c_val_stats_.used_cpu_memory = used_cpu_memory;
 
-  if (SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats)) {
-    int64_t used_gpu_memory = SbSystemGetUsedGPUMemory();
+  if (used_gpu_memory) {
     *c_val_stats_.free_gpu_memory =
-        SbSystemGetTotalGPUMemory() - used_gpu_memory;
-    *c_val_stats_.used_gpu_memory = used_gpu_memory;
+        SbSystemGetTotalGPUMemory() - *used_gpu_memory;
+    *c_val_stats_.used_gpu_memory = *used_gpu_memory;
   }
-#endif
+
+  memory_settings_checker_.RunChecks(
+      *auto_mem_, used_cpu_memory, used_gpu_memory);
 }
 
 }  // namespace browser
diff --git a/src/cobalt/browser/application.h b/src/cobalt/browser/application.h
index 6c1ac47..47da7ec 100644
--- a/src/cobalt/browser/application.h
+++ b/src/cobalt/browser/application.h
@@ -22,6 +22,8 @@
 #include "cobalt/account/account_manager.h"
 #include "cobalt/base/event_dispatcher.h"
 #include "cobalt/browser/browser_module.h"
+#include "cobalt/browser/memory_settings/auto_mem.h"
+#include "cobalt/browser/memory_settings/checker.h"
 #include "cobalt/browser/memory_tracker/tool.h"
 #include "cobalt/system_window/system_window.h"
 
@@ -173,6 +175,13 @@
   base::Timer lite_stats_update_timer_;
 
   scoped_ptr<memory_tracker::Tool> memory_tracker_tool_;
+
+  // Memory configuration tool.
+  scoped_ptr<memory_settings::AutoMem> auto_mem_;
+
+  // Fires memory warning once when memory exceeds specified max cpu/gpu
+  // memory.
+  memory_settings::Checker memory_settings_checker_;
 };
 
 // Factory method for creating an application.  It should be implemented
diff --git a/src/cobalt/browser/browser.gyp b/src/cobalt/browser/browser.gyp
index 61b714e..fb7ef5e 100644
--- a/src/cobalt/browser/browser.gyp
+++ b/src/cobalt/browser/browser.gyp
@@ -35,7 +35,13 @@
         'memory_settings/build_settings.h',
         'memory_settings/calculations.cc',
         'memory_settings/calculations.h',
+        'memory_settings/checker.cc',
+        'memory_settings/checker.h',
         'memory_settings/constants.h',
+        'memory_settings/constrainer.cc',
+        'memory_settings/constrainer.h',
+        'memory_settings/scaling_function.cc',
+        'memory_settings/scaling_function.h',
         'memory_settings/memory_settings.cc',
         'memory_settings/memory_settings.h',
         'memory_settings/pretty_print.cc',
@@ -213,6 +219,7 @@
         'storage_upgrade_handler_test.cc',
         'memory_settings/auto_mem_test.cc',
         'memory_settings/calculations_test.cc',
+        'memory_settings/constrainer_test.cc',
         'memory_settings/pretty_print_test.cc',
         'memory_settings/memory_settings_test.cc',
         'memory_settings/table_printer_test.cc',
diff --git a/src/cobalt/browser/memory_settings/auto_mem.cc b/src/cobalt/browser/memory_settings/auto_mem.cc
index 5743645..582c49e 100644
--- a/src/cobalt/browser/memory_settings/auto_mem.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem.cc
@@ -21,14 +21,17 @@
 #include <vector>
 
 #include "base/optional.h"
+#include "base/stl_util.h"
 #include "base/string_number_conversions.h"
 #include "base/string_split.h"
 #include "base/stringprintf.h"
 #include "cobalt/browser/memory_settings/build_settings.h"
 #include "cobalt/browser/memory_settings/calculations.h"
 #include "cobalt/browser/memory_settings/constants.h"
+#include "cobalt/browser/memory_settings/constrainer.h"
 #include "cobalt/browser/memory_settings/memory_settings.h"
 #include "cobalt/browser/memory_settings/pretty_print.h"
+#include "cobalt/browser/memory_settings/scaling_function.h"
 #include "cobalt/browser/switches.h"
 #include "nb/lexical_cast.h"
 
@@ -48,15 +51,13 @@
   return is_autoset;
 }
 
-// Creates the specified memory setting type and binds it to (1) command line
-// or else (2) build setting or else (3) an auto_set value.
 template <typename MemorySettingType, typename ValueType>
-scoped_ptr<MemorySettingType> CreateMemorySetting(
-    const char* setting_name,
+void SetMemorySetting(
     const CommandLine& cmd_line,  // Optional.
     const base::optional<ValueType>& build_setting,
-    const ValueType& autoset_value) {
-  scoped_ptr<MemorySettingType> output(new MemorySettingType(setting_name));
+    const ValueType& autoset_value,
+    MemorySettingType* setting) {
+  const std::string setting_name = setting->name();
 
   // True when the command line explicitly requests the variable to be autoset.
   bool force_autoset = false;
@@ -68,19 +69,31 @@
     std::string value = cmd_line.GetSwitchValueNative(setting_name);
     if (StringValueSignalsAutoset(value)) {
       force_autoset = true;
-    } else if (output->TryParseValue(MemorySetting::kCmdLine, value)) {
-      return output.Pass();
+    } else if (setting->TryParseValue(MemorySetting::kCmdLine, value)) {
+      return;
     }
   }
 
   // 2) Is there a build setting? Then set to build_setting, unless the command
   //    line specifies that it should be autoset.
   if (build_setting && !force_autoset) {
-    output->set_value(MemorySetting::kBuildSetting, *build_setting);
+    setting->set_value(MemorySetting::kBuildSetting, *build_setting);
   } else {
     // 3) Otherwise bind to the autoset_value.
-    output->set_value(MemorySetting::kAutoSet, autoset_value);
+    setting->set_value(MemorySetting::kAutoSet, autoset_value);
   }
+}
+
+// Creates the specified memory setting type and binds it to (1) command line
+// or else (2) build setting or else (3) an auto_set value.
+template <typename MemorySettingType, typename ValueType>
+scoped_ptr<MemorySettingType> CreateMemorySetting(
+    const char* setting_name,
+    const CommandLine& cmd_line,  // Optional.
+    const base::optional<ValueType>& build_setting,
+    const ValueType& autoset_value) {
+  scoped_ptr<MemorySettingType> output(new MemorySettingType(setting_name));
+  SetMemorySetting(cmd_line, build_setting, autoset_value, output.get());
   return output.Pass();
 }
 
@@ -187,7 +200,7 @@
                                         const BuildSettings& build_settings) {
   scoped_ptr<IntSetting> cpu_setting =
       CreateSystemMemorySetting(
-          switches::kMaxCobaltGpuUsage,
+          switches::kMaxCobaltCpuUsage,
           MemorySetting::kCPU,
           command_line,
           build_settings.max_cpu_in_bytes,
@@ -197,11 +210,158 @@
   return cpu_setting.Pass();
 }
 
+void CheckConstrainingValues(const MemorySetting& memory_setting) {
+  const size_t kNumTestPoints = 10;
+
+  std::vector<double> values;
+  for (size_t i = 0; i < kNumTestPoints; ++i) {
+    const double requested_constraining_value =
+        static_cast<double>(i) / static_cast<double>(kNumTestPoints - 1);
+
+    const double actual_constraining_value =
+        memory_setting.ComputeAbsoluteMemoryScale(
+            requested_constraining_value);
+
+    values.push_back(actual_constraining_value);
+  }
+
+  DCHECK(base::STLIsSorted(values))
+      << "Constrainer in " << memory_setting.name() << " does not produce "
+         "monotonically decreasing values as input goes from 1.0 -> 0.0";
+}
+
 }  // namespace
 
 AutoMem::AutoMem(const math::Size& ui_resolution,
                  const CommandLine& command_line,
                  const BuildSettings& build_settings) {
+  ConstructSettings(ui_resolution, command_line, build_settings);
+  std::vector<MemorySetting*> memory_settings = AllMemorySettingsMutable();
+  ConstrainToMemoryLimits(max_cpu_bytes_->value(),
+                          max_gpu_bytes_->optional_value(),
+                          &memory_settings,
+                          &error_msgs_);
+}
+
+AutoMem::~AutoMem() {}
+
+const IntSetting* AutoMem::misc_cobalt_cpu_size_in_bytes() const {
+  return misc_cobalt_cpu_size_in_bytes_.get();
+}
+
+const IntSetting* AutoMem::misc_cobalt_gpu_size_in_bytes() const {
+  return misc_cobalt_gpu_size_in_bytes_.get();
+}
+
+const IntSetting* AutoMem::remote_typeface_cache_size_in_bytes() const {
+  return remote_typeface_cache_size_in_bytes_.get();
+}
+
+const IntSetting* AutoMem::image_cache_size_in_bytes() const {
+  return image_cache_size_in_bytes_.get();
+}
+
+const IntSetting* AutoMem::javascript_gc_threshold_in_bytes() const {
+  return javascript_gc_threshold_in_bytes_.get();
+}
+
+const DimensionSetting* AutoMem::skia_atlas_texture_dimensions() const {
+  return skia_atlas_texture_dimensions_.get();
+}
+
+const IntSetting* AutoMem::skia_cache_size_in_bytes() const {
+  return skia_cache_size_in_bytes_.get();
+}
+
+const IntSetting* AutoMem::software_surface_cache_size_in_bytes() const {
+  return software_surface_cache_size_in_bytes_.get();
+}
+
+const IntSetting* AutoMem::max_cpu_bytes() const {
+  return max_cpu_bytes_.get();
+}
+
+const IntSetting* AutoMem::max_gpu_bytes() const {
+  return max_gpu_bytes_.get();
+}
+
+std::vector<const MemorySetting*> AutoMem::AllMemorySettings() const {
+  AutoMem* this_unconst = const_cast<AutoMem*>(this);
+  std::vector<MemorySetting*> all_settings_mutable =
+      this_unconst->AllMemorySettingsMutable();
+
+  std::vector<const MemorySetting*> all_settings;
+  all_settings.assign(all_settings_mutable.begin(),
+                      all_settings_mutable.end());
+  return all_settings;
+}
+
+// Make sure that this is the same as AllMemorySettings().
+std::vector<MemorySetting*> AutoMem::AllMemorySettingsMutable() {
+  std::vector<MemorySetting*> all_settings;
+  // Keep these in alphabetical order.
+  all_settings.push_back(image_cache_size_in_bytes_.get());
+  all_settings.push_back(javascript_gc_threshold_in_bytes_.get());
+  all_settings.push_back(misc_cobalt_cpu_size_in_bytes_.get());
+  all_settings.push_back(misc_cobalt_gpu_size_in_bytes_.get());
+  all_settings.push_back(remote_typeface_cache_size_in_bytes_.get());
+  all_settings.push_back(skia_atlas_texture_dimensions_.get());
+  all_settings.push_back(skia_cache_size_in_bytes_.get());
+  all_settings.push_back(software_surface_cache_size_in_bytes_.get());
+  return all_settings;
+}
+
+std::string AutoMem::ToPrettyPrintString(bool use_color_ascii) const {
+  std::stringstream ss;
+
+  ss << "AutoMem:\n\n";
+  std::vector<const MemorySetting*> all_settings = AllMemorySettings();
+  ss << GeneratePrettyPrintTable(use_color_ascii, all_settings) << "\n";
+
+  int64_t cpu_consumption =
+      SumMemoryConsumption(MemorySetting::kCPU, all_settings);
+  int64_t gpu_consumption =
+      SumMemoryConsumption(MemorySetting::kGPU, all_settings);
+
+  ss << GenerateMemoryTable(use_color_ascii,
+                            *max_cpu_bytes_, *max_gpu_bytes_,
+                            cpu_consumption, gpu_consumption);
+
+  // Copy strings and optionally add more.
+  std::vector<std::string> error_msgs = error_msgs_;
+
+  if (max_cpu_bytes_->value() <= 0) {
+    error_msgs.push_back("ERROR - max_cobalt_cpu_usage WAS 0 BYTES.");
+  } else if (cpu_consumption > max_cpu_bytes_->value()) {
+    error_msgs.push_back("ERROR - CPU CONSUMED WAS MORE THAN AVAILABLE.");
+  }
+
+  if (max_gpu_bytes_->value() <= 0) {
+    error_msgs.push_back("ERROR - max_cobalt_gpu_usage WAS 0 BYTES.");
+  } else if (gpu_consumption > max_gpu_bytes_->value()) {
+    error_msgs.push_back("ERROR - GPU CONSUMED WAS MORE THAN AVAILABLE.");
+  }
+
+  // Stringify error messages.
+  if (!error_msgs.empty()) {
+    std::stringstream ss_error;
+    ss_error << "AutoMem had errors:\n";
+    for (size_t i = 0; i < error_msgs.size(); ++i) {
+      ss_error << "   " << error_msgs[i] << "\n";
+    }
+    ss_error << "\nPlease see cobalt/docs/memory_tuning.md "
+                "for more information.";
+    ss << MakeBorder(ss_error.str(), '*');
+  }
+
+  std::string output_str = ss.str();
+  return output_str;
+}
+
+void AutoMem::ConstructSettings(
+    const math::Size& ui_resolution,
+    const CommandLine& command_line,
+    const BuildSettings& build_settings) {
   max_cpu_bytes_ = CreateCpuSetting(command_line, build_settings);
   max_gpu_bytes_ = CreateGpuSetting(command_line, build_settings);
 
@@ -213,20 +373,35 @@
       CalculateImageCacheSize(ui_resolution));
   EnsureValuePositive(image_cache_size_in_bytes_.get());
   image_cache_size_in_bytes_->set_memory_type(MemorySetting::kGPU);
+  // ImageCache releases memory linearly until a progress value of 75%, then
+  // it will not reduce memory any more. It will also clamp at 100% and won't
+  // be increased beyond that.
+  image_cache_size_in_bytes_->set_memory_scaling_function(
+      MakeLinearMemoryScaler(.75, 1.0));
 
   // Set javascript gc threshold
-  javascript_gc_threshold_in_bytes_ = CreateMemorySetting<IntSetting, int64_t>(
-      switches::kJavaScriptGcThresholdInBytes,
+  JavaScriptGcThresholdSetting* js_setting = new JavaScriptGcThresholdSetting;
+  SetMemorySetting<IntSetting, int64_t>(
       command_line,
       build_settings.javascript_garbage_collection_threshold_in_bytes,
-      kDefaultJsGarbageCollectionThresholdSize);
-  EnsureValuePositive(javascript_gc_threshold_in_bytes_.get());
+      kDefaultJsGarbageCollectionThresholdSize,
+      js_setting);
+  EnsureValuePositive(js_setting);
+  js_setting->PostInit();
+  javascript_gc_threshold_in_bytes_.reset(js_setting);
 
   // Set the misc cobalt size to a specific size.
   misc_cobalt_cpu_size_in_bytes_.reset(
       new IntSetting("misc_cobalt_cpu_size_in_bytes"));
   misc_cobalt_cpu_size_in_bytes_->set_value(
-      MemorySetting::kAutoSet, kMiscCobaltSizeInBytes);
+      MemorySetting::kAutoSet, kMiscCobaltCpuSizeInBytes);
+
+  // Set the misc cobalt size to a specific size.
+  misc_cobalt_gpu_size_in_bytes_.reset(
+      new IntSetting("misc_cobalt_gpu_size_in_bytes"));
+  misc_cobalt_gpu_size_in_bytes_->set_memory_type(MemorySetting::kGPU);
+  misc_cobalt_gpu_size_in_bytes_->set_value(
+      MemorySetting::kAutoSet, CalculateMiscCobaltGpuSize(ui_resolution));
 
   // Set remote_type_face_cache size.
   remote_typeface_cache_size_in_bytes_ =
@@ -237,13 +412,14 @@
         kDefaultRemoteTypeFaceCacheSize);
   EnsureValuePositive(remote_typeface_cache_size_in_bytes_.get());
 
-  // Set skia_atlas_texture_dimensions
-  skia_atlas_texture_dimensions_ =
-      CreateMemorySetting<DimensionSetting, TextureDimensions>(
-          switches::kSkiaTextureAtlasDimensions,
-          command_line,
-          build_settings.skia_texture_atlas_dimensions,
-          CalculateSkiaGlyphAtlasTextureSize(ui_resolution));
+  // Skia atlas texture dimensions.
+  skia_atlas_texture_dimensions_.reset(new SkiaGlyphAtlasTextureSetting());
+  SetMemorySetting(command_line,
+                   build_settings.skia_texture_atlas_dimensions,
+                   CalculateSkiaGlyphAtlasTextureSize(ui_resolution),
+                   skia_atlas_texture_dimensions_.get());
+  EnsureValuePositive(skia_atlas_texture_dimensions_.get());
+
   // Not available for non-blitter platforms.
   if (build_settings.has_blitter) {
     skia_atlas_texture_dimensions_->set_memory_type(
@@ -283,78 +459,14 @@
         MemorySetting::kNotApplicable);
   }
   EnsureValuePositive(software_surface_cache_size_in_bytes_.get());
-}
 
-AutoMem::~AutoMem() {}
-
-const IntSetting* AutoMem::misc_engine_cpu_size_in_bytes() const {
-  return misc_cobalt_cpu_size_in_bytes_.get();
-}
-
-const IntSetting* AutoMem::remote_typeface_cache_size_in_bytes() const {
-  return remote_typeface_cache_size_in_bytes_.get();
-}
-
-const IntSetting* AutoMem::image_cache_size_in_bytes() const {
-  return image_cache_size_in_bytes_.get();
-}
-
-const IntSetting* AutoMem::javascript_gc_threshold_in_bytes() const {
-  return javascript_gc_threshold_in_bytes_.get();
-}
-
-const DimensionSetting* AutoMem::skia_atlas_texture_dimensions() const {
-  return skia_atlas_texture_dimensions_.get();
-}
-
-const IntSetting* AutoMem::skia_cache_size_in_bytes() const {
-  return skia_cache_size_in_bytes_.get();
-}
-
-const IntSetting* AutoMem::software_surface_cache_size_in_bytes() const {
-  return software_surface_cache_size_in_bytes_.get();
-}
-
-std::vector<const MemorySetting*> AutoMem::AllMemorySettings() const {
-  AutoMem* this_unconst = const_cast<AutoMem*>(this);
-  std::vector<MemorySetting*> all_settings_mutable =
-      this_unconst->AllMemorySettingsMutable();
-
-  std::vector<const MemorySetting*> all_settings;
-  all_settings.assign(all_settings_mutable.begin(),
-                      all_settings_mutable.end());
-  return all_settings;
-}
-
-// Make sure that this is the same as AllMemorySettings().
-std::vector<MemorySetting*> AutoMem::AllMemorySettingsMutable() {
-  std::vector<MemorySetting*> all_settings;
-  // Keep these in alphabetical order.
-  all_settings.push_back(image_cache_size_in_bytes_.get());
-  all_settings.push_back(javascript_gc_threshold_in_bytes_.get());
-  all_settings.push_back(misc_cobalt_cpu_size_in_bytes_.get());
-  all_settings.push_back(remote_typeface_cache_size_in_bytes_.get());
-  all_settings.push_back(skia_atlas_texture_dimensions_.get());
-  all_settings.push_back(skia_cache_size_in_bytes_.get());
-  all_settings.push_back(software_surface_cache_size_in_bytes_.get());
-  return all_settings;
-}
-
-std::string AutoMem::ToPrettyPrintString() const {
-  std::stringstream ss;
-  std::vector<const MemorySetting*> all_settings = AllMemorySettings();
-  ss << GeneratePrettyPrintTable(all_settings) << "\n";
-
-  int64_t cpu_consumption =
-      SumMemoryConsumption(MemorySetting::kCPU, all_settings);
-  int64_t gpu_consumption =
-      SumMemoryConsumption(MemorySetting::kGPU, all_settings);
-
-  ss << GenerateMemoryTable(*max_cpu_bytes_, *max_gpu_bytes_,
-                            cpu_consumption, gpu_consumption);
-
-  std::string output_str = ss.str();
-  return output_str;
+  // Final stage: Check that all constraining functions are monotonically
+  // increasing.
+  const std::vector<const MemorySetting*> all_memory_settings =
+      AllMemorySettings();
+  for (size_t i = 0; i < all_memory_settings.size(); ++i) {
+    CheckConstrainingValues(*all_memory_settings[i]);
+  }
 }
 
 }  // namespace memory_settings
diff --git a/src/cobalt/browser/memory_settings/auto_mem.h b/src/cobalt/browser/memory_settings/auto_mem.h
index ad3e143..c018aec 100644
--- a/src/cobalt/browser/memory_settings/auto_mem.h
+++ b/src/cobalt/browser/memory_settings/auto_mem.h
@@ -27,6 +27,7 @@
 #include "cobalt/browser/memory_settings/build_settings.h"
 #include "cobalt/browser/memory_settings/memory_settings.h"
 #include "cobalt/math/size.h"
+#include "testing/gtest/include/gtest/gtest_prod.h"
 
 namespace cobalt {
 namespace browser {
@@ -44,25 +45,39 @@
 
   const IntSetting* image_cache_size_in_bytes() const;
   const IntSetting* javascript_gc_threshold_in_bytes() const;
-  const IntSetting* misc_engine_cpu_size_in_bytes() const;
+  // This setting represents all others cpu-memory consuming systems within
+  // the engine. This value has been hard coded.
+  const IntSetting* misc_cobalt_cpu_size_in_bytes() const;
+  const IntSetting* misc_cobalt_gpu_size_in_bytes() const;
   const IntSetting* remote_typeface_cache_size_in_bytes() const;
   const DimensionSetting* skia_atlas_texture_dimensions() const;
   const IntSetting* skia_cache_size_in_bytes() const;
   const IntSetting* software_surface_cache_size_in_bytes() const;
 
-  // AllMemorySettings - does not include cpu & gpu max memory.
-  std::vector<const MemorySetting*> AllMemorySettings() const;
-  std::vector<MemorySetting*> AllMemorySettingsMutable();
+  // max_cpu/gpu_bytes represents the maximum amount of memory that should
+  // be consumed by the engine. These values can be set by the command line
+  // or else they are set automatically.
+  const IntSetting* max_cpu_bytes() const;
+  const IntSetting* max_gpu_bytes() const;
 
   // Generates a string table of the memory settings and available memory for
   // cpu and gpu. This is used during startup to display memory configuration
   // information.
-  std::string ToPrettyPrintString() const;
+  std::string ToPrettyPrintString(bool use_color_ascii) const;
 
  private:
+  void ConstructSettings(const math::Size& ui_resolution,
+                         const CommandLine& command_line,
+                         const BuildSettings& build_settings);
+
+  // AllMemorySettings - does not include cpu & gpu max memory.
+  std::vector<const MemorySetting*> AllMemorySettings() const;
+  std::vector<MemorySetting*> AllMemorySettingsMutable();
+
   scoped_ptr<IntSetting> image_cache_size_in_bytes_;
   scoped_ptr<IntSetting> javascript_gc_threshold_in_bytes_;
   scoped_ptr<IntSetting> misc_cobalt_cpu_size_in_bytes_;
+  scoped_ptr<IntSetting> misc_cobalt_gpu_size_in_bytes_;
   scoped_ptr<IntSetting> remote_typeface_cache_size_in_bytes_;
   scoped_ptr<DimensionSetting> skia_atlas_texture_dimensions_;
   scoped_ptr<IntSetting> skia_cache_size_in_bytes_;
@@ -71,6 +86,11 @@
   // These settings are used for constraining the memory.
   scoped_ptr<IntSetting> max_cpu_bytes_;
   scoped_ptr<IntSetting> max_gpu_bytes_;
+  std::vector<std::string> error_msgs_;
+
+  FRIEND_TEST(AutoMem, AllMemorySettingsAreOrderedByName);
+  FRIEND_TEST(AutoMem, ConstrainedCPUEnvironment);
+  FRIEND_TEST(AutoMem, ConstrainedGPUEnvironment);
 };
 
 }  // namespace memory_settings
diff --git a/src/cobalt/browser/memory_settings/auto_mem_test.cc b/src/cobalt/browser/memory_settings/auto_mem_test.cc
index b5a2ba5..5a17825 100644
--- a/src/cobalt/browser/memory_settings/auto_mem_test.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem_test.cc
@@ -121,7 +121,7 @@
 
 // Tests that skia atlas texture will be bind to the built in value, iff it has
 // been set.
-TEST(AutoMem, SkiaAtlasTextureAtlasSize) {
+TEST(AutoMem, SkiaGlyphAtlasTextureSize) {
   CommandLine empty_command_line(CommandLine::NO_PROGRAM);
   BuildSettings builtin_settings;
   BuildSettings builtin_settings_with_default;
@@ -209,6 +209,37 @@
   }
 }
 
+// Tests the expectation that constraining the CPU memory to 130MB will result
+// in AutoMem reducing the the memory footprint.
+TEST(AutoMem, ConstrainedCPUEnvironment) {
+  CommandLine empty_command_line(CommandLine::NO_PROGRAM);
+  BuildSettings builtin_settings;
+  builtin_settings.max_cpu_in_bytes = 130 * 1024 * 1024;
+
+  AutoMem auto_mem(kResolution1080p, empty_command_line, builtin_settings);
+
+  std::vector<const MemorySetting*> settings = auto_mem.AllMemorySettings();
+
+  const int64_t cpu_memory_consumption =
+      SumMemoryConsumption(MemorySetting::kCPU, settings);
+
+  EXPECT_LE(cpu_memory_consumption, 130 * 1024 * 1024);
+}
+
+// Tests the expectation that constraining the CPU memory to 40MB will result
+// in AutoMem reducing the the memory footprint.
+TEST(AutoMem, ConstrainedGPUEnvironment) {
+  CommandLine empty_command_line(CommandLine::NO_PROGRAM);
+  BuildSettings builtin_settings;
+  builtin_settings.max_gpu_in_bytes = 57 * 1024 * 1024;
+  AutoMem auto_mem(kResolution1080p, empty_command_line, builtin_settings);
+
+  std::vector<const MemorySetting*> settings = auto_mem.AllMemorySettings();
+  const int64_t gpu_memory_consumption =
+      SumMemoryConsumption(MemorySetting::kGPU, settings);
+  EXPECT_LE(gpu_memory_consumption, 57 * 1024 * 1024);
+}
+
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/calculations.cc b/src/cobalt/browser/memory_settings/calculations.cc
index 7da7d3e..8474f65 100644
--- a/src/cobalt/browser/memory_settings/calculations.cc
+++ b/src/cobalt/browser/memory_settings/calculations.cc
@@ -20,6 +20,7 @@
 
 #include "cobalt/browser/memory_settings/build_settings.h"
 #include "cobalt/browser/memory_settings/constants.h"
+#include "cobalt/math/clamp.h"
 #include "cobalt/math/size.h"
 
 namespace cobalt {
@@ -27,11 +28,6 @@
 namespace memory_settings {
 namespace {
 
-template <typename T>
-T ClampValue(const T& input, const T& minimum, const T& maximum) {
-  return std::max<T>(minimum, std::min<T>(maximum, input));
-}
-
 double DisplayScaleTo1080p(const math::Size& dimensions) {
   static const double kNumReferencePixels = 1920. * 1080.;
   const double num_pixels = static_cast<double>(dimensions.width()) *
@@ -39,8 +35,8 @@
   return num_pixels / kNumReferencePixels;
 }
 
-// LinearRemap is a type of linear interpolation which maps a value from
-// one number line to a corresponding value on another number line.
+// LinearRemap maps a value from one number line to a corresponding value on
+// another number line.
 // Example:
 //  LinearRemap linear_remap(0, 1, 5, 10);
 //  EXPECT_EQ(5.0f, linear_remap.Map(0));
@@ -49,7 +45,9 @@
 class LinearRemap {
  public:
   LinearRemap(double amin, double amax, double bmin, double bmax)
-      : amin_(amin), amax_(amax), bmin_(bmin), bmax_(bmax) {}
+      : amin_(amin), amax_(amax), bmin_(bmin), bmax_(bmax) {
+    DCHECK_NE(amax_, amin_);
+  }
 
   // Maps the value from the number line [amin,amax] to [bmin,bmax]. For
   // example:
@@ -58,8 +56,8 @@
   //   Map((amax+amin)/2) -> (bmax+bmin)/2.
   double Map(double value) const {
     value -= amin_;
-    value /= (amax_ - amin_);
     value *= (bmax_ - bmin_);
+    value /= (amax_ - amin_);
     value += bmin_;
     return value;
   }
@@ -93,8 +91,8 @@
   static const int64_t kReferenceSize1080p = 32 * 1024 * 1024;
   double output_bytes = kReferenceSize1080p * display_scale;
 
-  return ClampValue<int64_t>(static_cast<int64_t>(output_bytes),
-                             kMinImageCacheSize, kMaxImageCacheSize);
+  return math::Clamp<int64_t>(static_cast<int64_t>(output_bytes),
+                              kMinImageCacheSize, kMaxImageCacheSize);
 }
 
 TextureDimensions CalculateSkiaGlyphAtlasTextureSize(
@@ -130,7 +128,7 @@
   // LinearRemap defines a mapping function which will map the number
   // of ui_resolution pixels to the number of surface texture cache such:
   // 720p (1280x720)   => maps to => 4MB &
-  // 1080p (1920x1200) => maps to => 9MB
+  // 1080p (1920x1080) => maps to => 9MB
   LinearRemap remap(1280 * 720, 1920 * 1080, 4 * 1024 * 1024, 9 * 1024 * 1024);
 
   int64_t surface_cache_size_in_bytes =
@@ -146,6 +144,16 @@
   return std::max<int64_t>(output, kMinSkiaCacheSize);
 }
 
+int64_t CalculateMiscCobaltGpuSize(const math::Size& ui_resolution) {
+  // LinearRemap defines a mapping function which will map the number
+  // of ui_resolution pixels to the misc memory of the GPU. This mapping
+  // is linear such that:
+  // 1080p (1920x1080) => maps to => 24MB
+  LinearRemap remap(0, 1920 * 1080, 0, 24 * 1024 * 1024);
+
+  return static_cast<int64_t>(remap.Map(ui_resolution.GetArea()));
+}
+
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/calculations.h b/src/cobalt/browser/memory_settings/calculations.h
index cbb3afb..bc4a65a 100644
--- a/src/cobalt/browser/memory_settings/calculations.h
+++ b/src/cobalt/browser/memory_settings/calculations.h
@@ -33,7 +33,7 @@
 // The return ranges from [kMinImageCacheSize, kMaxImageCacheSize].
 int64_t CalculateImageCacheSize(const math::Size& dimensions);
 
-// Calculates the SkiaAtlasTextureSize.
+// Calculates the SkiaAtlasGlyphTextureSize.
 // When the ui resolution is 1920x1080, then the returned atlas texture size
 // will be 8192x4096. The texture will scale up and down, by powers of two,
 // in relation to the input ui_resolution. The returned value will be clamped
@@ -53,6 +53,10 @@
 // to be 4MB @ 1080p and scales accordingly.
 int64_t CalculateSkiaCacheSize(const math::Size& ui_resolution);
 
+// Calculates the GPU usage of the app to un-accounted systems. Scales linearly
+// with ui_resolution.
+int64_t CalculateMiscCobaltGpuSize(const math::Size& ui_resolution);
+
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/calculations_test.cc b/src/cobalt/browser/memory_settings/calculations_test.cc
index 1d82f58..3b7f62c 100644
--- a/src/cobalt/browser/memory_settings/calculations_test.cc
+++ b/src/cobalt/browser/memory_settings/calculations_test.cc
@@ -110,7 +110,7 @@
   EXPECT_EQ(kMaxImageCacheSize, CalculateImageCacheSize(GetDimensions(k8k)));
 }
 
-// Tests the expectation that CalculateSkiaAtlasTextureSize() is a pure
+// Tests the expectation that CalculateSkiaGlyphAtlasTextureSize() is a pure
 // function (side effect free) and will produce expected results.
 TEST(MemoryCalculations, CalculateSkiaGlyphAtlasTextureSize) {
   math::Size ui_dimensions;
@@ -156,6 +156,12 @@
             CalculateSoftwareSurfaceCacheSizeInBytes(ui_resolution));
 }
 
+TEST(MemoryCalculations, CalculateMiscCobaltGpuSize) {
+  math::Size ui_resolution = GetDimensions(k1080p);
+  EXPECT_EQ(24 * 1024 * 1024,
+            CalculateMiscCobaltGpuSize(ui_resolution));
+}
+
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/checker.cc b/src/cobalt/browser/memory_settings/checker.cc
new file mode 100644
index 0000000..a5ef859
--- /dev/null
+++ b/src/cobalt/browser/memory_settings/checker.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/browser/memory_settings/checker.h"
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+#include "cobalt/browser/memory_settings/pretty_print.h"
+#include "starboard/types.h"
+
+namespace cobalt {
+namespace browser {
+namespace memory_settings {
+namespace {
+
+std::string GenerateErrorMessage(const std::string& memory_type,
+                                 const IntSetting& max_memory_setting,
+                                 int64_t current_memory_usage) {
+  std::string max_memory_str = ToMegabyteString(max_memory_setting.value(), 2);
+  std::string used_memory_str = ToMegabyteString(current_memory_usage, 2);
+  std::string source_str = StringifySourceType(max_memory_setting);
+
+  std::stringstream ss;
+  ss << memory_type << " MEMORY USAGE EXCEEDED!\n"
+     << "  Max Available: " << max_memory_str << "\n"
+     << "  Used:          " << used_memory_str << "\n"
+     << "  Source:        " << source_str << "\n\n"
+     << "  Please see cobalt/doc/memory_tuning.md for more information";
+
+  return MakeBorder(ss.str(), '*');
+}
+
+void DoCheck(const char* memory_type_str,
+             int64_t curr_memory_consumption,
+             const IntSetting& max_memory_limit,
+             bool* fired_once_flag) {
+  if (*fired_once_flag || (max_memory_limit.value() > 0)) {
+    return;
+  }
+  const int64_t max_memory_value = max_memory_limit.value();
+
+  if (curr_memory_consumption > max_memory_value) {
+    std::string error_msg = GenerateErrorMessage(memory_type_str,
+                                                 max_memory_limit,
+                                                 curr_memory_consumption);
+    LOG(ERROR) << error_msg;
+    *fired_once_flag = true;
+  }
+}
+
+}  // namespace.
+
+Checker::Checker() : cpu_memory_warning_fired_(false),
+                     gpu_memory_warning_fired_(false) {
+}
+
+void Checker::RunChecks(const AutoMem& auto_mem,
+                        int64_t curr_cpu_memory_usage,
+                        base::optional<int64_t> curr_gpu_memory_usage) {
+  DoCheck("CPU",
+          curr_cpu_memory_usage,
+          *auto_mem.max_cpu_bytes(),
+          &cpu_memory_warning_fired_);
+
+  if (curr_gpu_memory_usage) {
+    DoCheck("GPU",
+            *curr_gpu_memory_usage,
+            *auto_mem.max_gpu_bytes(),
+            &gpu_memory_warning_fired_);
+  }
+}
+
+}  // namespace memory_settings
+}  // namespace browser
+}  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/checker.h b/src/cobalt/browser/memory_settings/checker.h
new file mode 100644
index 0000000..f749621
--- /dev/null
+++ b/src/cobalt/browser/memory_settings/checker.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_BROWSER_MEMORY_SETTINGS_CHECKER_H_
+#define COBALT_BROWSER_MEMORY_SETTINGS_CHECKER_H_
+
+#include <string>
+
+#include "base/optional.h"
+#include "cobalt/browser/memory_settings/auto_mem.h"
+#include "starboard/types.h"
+
+namespace cobalt {
+namespace browser {
+namespace memory_settings {
+
+// This class is responsible for holding the logic necessary to check
+// whether the memory limit has been exceeded. If so then a error
+// message is fired once.
+class Checker {
+ public:
+  Checker();
+  void RunChecks(const AutoMem& auto_mem,
+                 int64_t curr_cpu_memory_usage,
+                 base::optional<int64_t> curr_gpu_memory_usage);
+
+ private:
+  bool cpu_memory_warning_fired_;
+  bool gpu_memory_warning_fired_;
+};
+
+}  // namespace memory_settings
+}  // namespace browser
+}  // namespace cobalt
+
+#endif  // COBALT_BROWSER_MEMORY_SETTINGS_CHECKER_H_
diff --git a/src/cobalt/browser/memory_settings/constants.h b/src/cobalt/browser/memory_settings/constants.h
index 9f397eb..aa1bdc8 100644
--- a/src/cobalt/browser/memory_settings/constants.h
+++ b/src/cobalt/browser/memory_settings/constants.h
@@ -23,8 +23,9 @@
 
 // These internal values are exposed for testing.
 enum MemorySizes {
-  // Size of the engine, minus all caches.
-  kMiscCobaltSizeInBytes = 32 * 1024 * 1024,
+  // Size of the engine + unaccounted caches.
+  // This was experimentally selected.
+  kMiscCobaltCpuSizeInBytes = 119 * 1024 * 1024,
 
   kMinImageCacheSize = 20 * 1024 * 1024,  // 20mb.
   kMaxImageCacheSize = 64 * 1024 * 1024,  // 64mb
@@ -33,7 +34,7 @@
   kMinSkiaGlyphTextureAtlasHeight = 2048,
   kSkiaGlyphAtlasTextureBytesPerPixel = 2,
   kDefaultRemoteTypeFaceCacheSize = 4 * 1024 * 1024,  // 4mb.
-  kDefaultJsGarbageCollectionThresholdSize = 1 * 1024 * 1024,  // 1mb
+  kDefaultJsGarbageCollectionThresholdSize = 8 * 1024 * 1024,  // 8mb
 
   kMinSkiaCacheSize = 4 * 1024 * 1024,  // 4mb.
 };
diff --git a/src/cobalt/browser/memory_settings/constrainer.cc b/src/cobalt/browser/memory_settings/constrainer.cc
new file mode 100644
index 0000000..f4a9e54
--- /dev/null
+++ b/src/cobalt/browser/memory_settings/constrainer.cc
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/browser/memory_settings/constrainer.h"
+
+#include <algorithm>
+#include <iterator>
+#include <vector>
+
+#include "cobalt/browser/memory_settings/memory_settings.h"
+#include "starboard/configuration.h"
+
+namespace cobalt {
+namespace browser {
+namespace memory_settings {
+namespace {
+
+// Any memory setting that matches the MemoryType and is an AutoSet type is
+// passed to the output.
+std::vector<MemorySetting*> FilterSettings(
+    MemorySetting::MemoryType memory_type,
+    const std::vector<MemorySetting*>& settings) {
+  std::vector<MemorySetting*> output;
+  for (size_t i = 0; i < settings.size(); ++i) {
+    MemorySetting* setting = settings[i];
+    if (setting->memory_type() == memory_type) {
+      output.push_back(setting);
+    }
+  }
+  return output;
+}
+
+// Sums the memory consumption at the given global_constraining_value. The
+// settings variable is read buy not modified (despite the non-const
+// declaration). If constrained_values_out is non-null, then the computed
+// constraining values are stored in this vector.
+// Returns: The amount of memory in bytes that the memory settings vector will
+//          consume at the given global_constraining_factor.
+int64_t SumMemoryConsumption(
+    double global_constraining_factor,
+    const std::vector<MemorySetting*>& memory_settings,
+    std::vector<double>* constrained_values_out) {
+
+  if (constrained_values_out) {
+    constrained_values_out->clear();
+  }
+
+  int64_t sum = 0;
+
+  // Iterates through the MemorySettings and determines the total memory
+  // consumption at the current global_constraining_value.
+  for (size_t i = 0; i < memory_settings.size(); ++i) {
+    const MemorySetting* setting = memory_settings[i];
+
+    const int64_t requested_consumption = setting->MemoryConsumption();
+    double local_constraining_value = 1.0;
+    if (setting->source_type() == MemorySetting::kAutoSet) {
+      local_constraining_value =
+          setting->ComputeAbsoluteMemoryScale(global_constraining_factor);
+    }
+
+    const int64_t new_consumption_value =
+        static_cast<int64_t>(local_constraining_value * requested_consumption);
+
+    if (constrained_values_out) {
+      constrained_values_out->push_back(local_constraining_value);
+    }
+
+    sum += new_consumption_value;
+  }
+
+  return sum;
+}
+
+void CheckMemoryChange(const std::string& setting_name,
+                       int64_t old_memory_consumption,
+                       int64_t new_memory_consumption,
+                       double constraining_value) {
+  // Represents 1% allowed difference.
+  static const double kErrorThreshold = 0.01;
+
+  const double actual_constraining_value =
+      static_cast<double>(new_memory_consumption) /
+      static_cast<double>(old_memory_consumption);
+
+  double diff = constraining_value - actual_constraining_value;
+  if (diff < 0.0) {
+    diff = -diff;
+  }
+
+  DCHECK_LE(diff, kErrorThreshold)
+      << "MemorySetting " << setting_name << " did not change it's memory by "
+      << "the expected value.\n"
+      << "  Expected Change: " << (constraining_value * 100) << "%\n"
+      << "  Actual Change: " << (diff * 100) << "%\n"
+      << "  Original memory consumption (bytes): " << old_memory_consumption
+      << "  New memory consumption (bytes):      " << new_memory_consumption
+      << "\n";
+}
+
+void ConstrainToMemoryLimit(int64_t memory_limit,
+                            std::vector<MemorySetting*>* memory_settings) {
+  if (memory_settings->empty()) {
+    return;
+  }
+
+  // If the memory consumed is already under the memory limit then no further
+  // work needs to be done.
+  if (SumMemoryConsumption(1.0, *memory_settings, NULL) <= memory_limit) {
+    return;
+  }
+
+  // Iterate by small steps the constraining value from 1.0 (100%) toward
+  // 0.0.
+  static const double kStep = 0.0001;  // .01% change per iteration.
+  std::vector<double> constrained_sizes;
+  // 1-1 mapping.
+  constrained_sizes.resize(memory_settings->size());
+  for (double global_constraining_factor = 1.0;
+       global_constraining_factor >= 0.0;
+       global_constraining_factor -= kStep) {
+    global_constraining_factor = std::max(0.0, global_constraining_factor);
+    const int64_t new_global_memory_consumption =
+        SumMemoryConsumption(global_constraining_factor, *memory_settings,
+                             &constrained_sizes);
+
+    const bool finished =
+        (global_constraining_factor == 0.0) ||
+        (new_global_memory_consumption <= memory_limit);
+
+    if (finished) {
+      break;
+    }
+  }
+  DCHECK_EQ(memory_settings->size(), constrained_sizes.size());
+  for (size_t i = 0; i < memory_settings->size(); ++i) {
+    const double local_constraining_factor = constrained_sizes[i];
+    MemorySetting* setting = memory_settings->at(i);
+    if (local_constraining_factor != 1.0) {
+      const int64_t old_memory_consumption = setting->MemoryConsumption();
+      DCHECK_EQ(setting->source_type(), MemorySetting::kAutoSet);
+      setting->ScaleMemory(local_constraining_factor);
+      const int64_t new_memory_consumption = setting->MemoryConsumption();
+
+      // If the memory doesn't actually change as predicted by the constraining
+      // value then this check will catch it here.
+      CheckMemoryChange(setting->name(),
+                        old_memory_consumption, new_memory_consumption,
+                        local_constraining_factor);
+    }
+  }
+}
+
+}  // namespace.
+
+void ConstrainToMemoryLimits(
+    const int64_t& max_cpu_memory,
+    const base::optional<int64_t>& max_gpu_memory,
+    std::vector<MemorySetting*>* memory_settings,
+    std::vector<std::string>* error_msgs) {
+
+  // Some platforms may just return 0 for the max_cpu memory, in this case
+  // we don't want to constrain the memory.
+  if (max_cpu_memory > 0) {
+    std::vector<MemorySetting*> cpu_memory_settings =
+        FilterSettings(MemorySetting::kCPU, *memory_settings);
+    ConstrainToMemoryLimit(max_cpu_memory, &cpu_memory_settings);
+  } else {
+    error_msgs->push_back(
+        "ERROR - COULD NOT CONSTRAIN CPU MEMORY "
+        "BECAUSE max_cobalt_cpu_usage WAS 0.");
+  }
+
+  // Some platforms may just return 0 for the max_gpu memory, in this case
+  // we don't want to constrain the memory.
+  if (max_gpu_memory) {
+    if (*max_gpu_memory > 0) {
+      std::vector<MemorySetting*> gpu_memory_settings =
+          FilterSettings(MemorySetting::kGPU, *memory_settings);
+      ConstrainToMemoryLimit(*max_gpu_memory, &gpu_memory_settings);
+    } else {
+      error_msgs->push_back(
+          "ERROR - COULD NOT CONSTRAIN GPU MEMORY "
+          "BECAUSE max_cobalt_gpu_usage WAS 0.");
+    }
+  }
+}
+
+}  // namespace memory_settings
+}  // namespace browser
+}  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/constrainer.h b/src/cobalt/browser/memory_settings/constrainer.h
new file mode 100644
index 0000000..3c22193
--- /dev/null
+++ b/src/cobalt/browser/memory_settings/constrainer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_BROWSER_MEMORY_SETTINGS_CONSTRAINER_H_
+#define COBALT_BROWSER_MEMORY_SETTINGS_CONSTRAINER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "cobalt/browser/memory_settings/memory_settings.h"
+#include "starboard/types.h"
+
+namespace cobalt {
+namespace browser {
+namespace memory_settings {
+
+// Constrains the memory in the memmory_settings vector so that the target is
+// such that the sum of memory consumption is below max_cpu_memory and
+// max_gpu_memory.
+//
+// How the memory settings will reduce their memory usage is dependent on
+// the ConstrainerFunction they contain. It's possible that the memory
+// settings won't be able to match the target memory.
+//
+// The output variable error_msgs will be populated with any error messages
+// that result from this function call.
+void ConstrainToMemoryLimits(
+    const int64_t& max_cpu_memory,
+    const base::optional<int64_t>& max_gpu_memory,
+    std::vector<MemorySetting*>* memory_settings,
+    std::vector<std::string>* error_msgs);
+
+}  // namespace memory_settings
+}  // namespace browser
+}  // namespace cobalt
+
+#endif  // COBALT_BROWSER_MEMORY_SETTINGS_CONSTRAINER_H_
diff --git a/src/cobalt/browser/memory_settings/constrainer_test.cc b/src/cobalt/browser/memory_settings/constrainer_test.cc
new file mode 100644
index 0000000..7a5e3d5
--- /dev/null
+++ b/src/cobalt/browser/memory_settings/constrainer_test.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "cobalt/browser/memory_settings/constrainer.h"
+#include "cobalt/browser/memory_settings/memory_settings.h"
+#include "cobalt/browser/memory_settings/test_common.h"
+#include "starboard/configuration.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cobalt {
+namespace browser {
+namespace memory_settings {
+namespace {
+const int64_t kOneMegabyte = 1 * 1024 * 1024;
+const int64_t kTwoMegabytes = 2 * 1024 * 1024;
+const int64_t kFiveMegabytes = 5 * 1024 * 1024;
+const base::optional<int64_t> kNoGpuMemory;
+
+ScalingFunction MakeLinearConstrainer() {
+  // Linearly scale, but clamp between 0 and 1.
+  return MakeLinearMemoryScaler(0.0, 1.0);
+}
+
+}  // namespace.
+
+// Tests the expectation that given one IntSetting which occupies 2MB of
+// the available memory, and max_cpu_setting of 1MB, that
+// ConstrainToMemoryLimits() function will reduce the memory setting
+// down 1MB.
+TEST(ConstrainToMemoryLimits, ConstrainCpuMemoryWithOneSetting) {
+  IntSetting int_setting("dummy_cpu_setting");
+  int_setting.set_memory_type(MemorySetting::kCPU);
+  int_setting.set_value(MemorySetting::kAutoSet, kTwoMegabytes);
+
+  ScalingFunction constrainer(MakeLinearConstrainer());
+
+  int_setting.set_memory_scaling_function(constrainer);
+
+  std::vector<MemorySetting*> settings;
+  settings.push_back(&int_setting);
+
+  std::vector<std::string> error_msgs;
+
+  // Will reduce the memory usage of the IntSetting.
+  ConstrainToMemoryLimits(kOneMegabyte, kNoGpuMemory, &settings, &error_msgs);
+  EXPECT_EQ(kOneMegabyte, int_setting.MemoryConsumption());
+  EXPECT_TRUE(error_msgs.empty());
+}
+
+// Tests the expectation that given two IntSettings, one that was AutoSet and
+// one that was set by the command line and one set by the build system, that
+// only the AutoSet IntSetting will be constrained.
+TEST(ConstrainToMemoryLimits, ConstrainerIgnoresNonAutosetVariables) {
+  IntSetting int_setting_autoset("autoset_cpu_setting");
+  int_setting_autoset.set_memory_type(MemorySetting::kCPU);
+  int_setting_autoset.set_value(MemorySetting::kAutoSet, kTwoMegabytes);
+  int_setting_autoset.set_memory_scaling_function(MakeLinearConstrainer());
+
+  IntSetting int_setting_cmdline("cmdline_cpu_setting");
+  int_setting_cmdline.set_memory_type(MemorySetting::kCPU);
+  int_setting_cmdline.set_value(MemorySetting::kCmdLine, kTwoMegabytes);
+  int_setting_cmdline.set_memory_scaling_function(MakeLinearConstrainer());
+
+  IntSetting int_setting_builtin("builtin_cpu_setting");
+  int_setting_builtin.set_memory_type(MemorySetting::kCPU);
+  int_setting_builtin.set_value(MemorySetting::kBuildSetting, kTwoMegabytes);
+  int_setting_builtin.set_memory_scaling_function(MakeLinearConstrainer());
+
+  std::vector<MemorySetting*> settings;
+  settings.push_back(&int_setting_autoset);
+  settings.push_back(&int_setting_cmdline);
+  settings.push_back(&int_setting_builtin);
+
+  std::vector<std::string> error_msgs;
+
+  // Right now we need to shave off 1MB, but this can only come from the
+  // MemorySetting that was autoset.
+  ConstrainToMemoryLimits(kFiveMegabytes, kNoGpuMemory, &settings,
+                          &error_msgs);
+
+  EXPECT_EQ(kOneMegabyte, int_setting_autoset.MemoryConsumption());
+  EXPECT_EQ(kTwoMegabytes, int_setting_cmdline.MemoryConsumption());
+  EXPECT_EQ(kTwoMegabytes, int_setting_builtin.MemoryConsumption());
+
+  EXPECT_TRUE(error_msgs.empty());
+}
+
+}  // namespace memory_settings
+}  // namespace browser
+}  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/memory_settings.cc b/src/cobalt/browser/memory_settings/memory_settings.cc
index b71735b..5da12a6 100644
--- a/src/cobalt/browser/memory_settings/memory_settings.cc
+++ b/src/cobalt/browser/memory_settings/memory_settings.cc
@@ -20,6 +20,7 @@
 #include <string>
 #include <vector>
 
+#include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/string_number_conversions.h"
@@ -28,6 +29,7 @@
 #include "cobalt/browser/memory_settings/build_settings.h"
 #include "cobalt/browser/memory_settings/constants.h"
 #include "cobalt/browser/switches.h"
+#include "cobalt/math/linear_interpolator.h"
 #include "nb/lexical_cast.h"
 
 namespace cobalt {
@@ -43,8 +45,12 @@
   int value_;
   bool error_;  // true if there was a parse error.
 };
+
 // Parses a string like "1234x5678" to vector of parsed int values.
-std::vector<ParsedIntValue> ParseDimensions(const std::string& value_str) {
+std::vector<ParsedIntValue> ParseDimensions(const std::string& input) {
+  std::string value_str = input;
+  std::transform(value_str.begin(), value_str.end(),
+                 value_str.begin(), ::tolower);
   std::vector<ParsedIntValue> output;
 
   std::vector<std::string> lengths;
@@ -58,8 +64,57 @@
   return output;
 }
 
+bool StringEndsWith(const std::string& value, const std::string& ending) {
+  if (ending.size() > value.size()) {
+    return false;
+  }
+  // Reverse search through the back of the string.
+  return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
+}
+
+// Handles bytes: "12435"
+// Handles kilobytes: "128KB"
+// Handles megabytes: "64MB"
+// Handles gigabytes: "1GB"
+// Handles fractional units for kilo/mega/gigabytes
+int64_t ParseMemoryValue(const std::string& value, bool* parse_ok) {
+  // nb::lexical_cast<> will parse out the number but it will ignore the
+  // unit part, such as "kb" or "mb".
+  double numerical_value = nb::lexical_cast<double>(value, parse_ok);
+  if (!(*parse_ok)) {
+    return static_cast<int64_t>(numerical_value);
+  }
+
+  // Lowercasing the string makes the units easier to detect.
+  std::string value_lower_case = value;
+  std::transform(value_lower_case.begin(), value_lower_case.end(),
+                 value_lower_case.begin(),
+                 ::tolower);
+
+  if (StringEndsWith(value_lower_case, "kb")) {
+    numerical_value *= 1024;  // convert kb -> bytes.
+  } else if (StringEndsWith(value_lower_case, "mb")) {
+    numerical_value *= 1024 * 1024;  // convert mb -> bytes.
+  } else if (StringEndsWith(value_lower_case, "gb")) {
+    numerical_value *= 1024 * 1024 * 1024;  // convert gb -> bytes.
+  }
+  return static_cast<int64_t>(numerical_value);
+}
 }  // namespace
 
+void MemorySetting::set_memory_scaling_function(ScalingFunction function) {
+  memory_scaling_function_ = function;
+}
+
+double MemorySetting::ComputeAbsoluteMemoryScale(
+    double requested_memory_scale) const {
+  if (memory_scaling_function_.is_null()) {
+    return 1.0;
+  } else {
+    return memory_scaling_function_.Run(requested_memory_scale);
+  }
+}
+
 MemorySetting::MemorySetting(ClassType type, const std::string& name)
     : class_type_(type),
       name_(name),
@@ -77,10 +132,18 @@
 
 int64_t IntSetting::MemoryConsumption() const { return value(); }
 
+void IntSetting::ScaleMemory(double memory_scale) {
+  DCHECK_LE(0.0, memory_scale);
+  DCHECK_LE(memory_scale, 1.0);
+
+  const int64_t new_value = static_cast<int64_t>(value() * memory_scale);
+  set_value(MemorySetting::kAutosetConstrained, new_value);
+}
+
 bool IntSetting::TryParseValue(SourceType source_type,
                                const std::string& string_value) {
   bool parse_ok = false;
-  int64_t int_value = nb::lexical_cast<int64_t>(string_value, &parse_ok);
+  int64_t int_value = ParseMemoryValue(string_value, &parse_ok);
 
   if (parse_ok) {
     set_value(source_type, int_value);
@@ -133,6 +196,87 @@
   return true;
 }
 
+SkiaGlyphAtlasTextureSetting::SkiaGlyphAtlasTextureSetting()
+    : DimensionSetting(switches::kSkiaTextureAtlasDimensions) {
+  set_memory_scaling_function(MakeSkiaGlyphAtlasMemoryScaler());
+}
+
+void SkiaGlyphAtlasTextureSetting::ScaleMemory(double memory_scale) {
+  DCHECK_LE(0.0, memory_scale);
+  DCHECK_LE(memory_scale, 1.0);
+
+  if (!valid()) {
+    return;
+  }
+  const size_t number_of_reductions = NumberOfReductions(memory_scale);
+  if (number_of_reductions == 0) {
+    return;
+  }
+
+  TextureDimensions texture_dims = value();
+  DCHECK_LT(0, texture_dims.width());
+  DCHECK_LT(0, texture_dims.height());
+
+  for (size_t i = 0; i < number_of_reductions; ++i) {
+    if (texture_dims.width() <= 1 && texture_dims.height() <=1) {
+      break;
+    }
+    if (texture_dims.width() > texture_dims.height()) {
+      texture_dims.set_width(texture_dims.width() / 2);
+    } else {
+      texture_dims.set_height(texture_dims.height() / 2);
+    }
+  }
+
+  set_value(MemorySetting::kAutosetConstrained, texture_dims);
+}
+
+size_t SkiaGlyphAtlasTextureSetting::NumberOfReductions(
+    double reduction_factor) {
+  size_t num_of_reductions = 0;
+  while (reduction_factor <= 0.5f) {
+    ++num_of_reductions;
+    reduction_factor *= 2.0;
+  }
+  return num_of_reductions;
+}
+
+JavaScriptGcThresholdSetting::JavaScriptGcThresholdSetting()
+    : IntSetting(switches::kJavaScriptGcThresholdInBytes) {
+}
+
+void JavaScriptGcThresholdSetting::PostInit() {
+  const int64_t normal_memory_consumption = MemoryConsumption();
+  const int64_t min_memory_consumption =
+      std::min<int64_t>(normal_memory_consumption, 1 * 1024 * 1024);
+
+  ScalingFunction function =
+      MakeJavaScriptGCScaler(min_memory_consumption,
+                             normal_memory_consumption);
+  set_memory_scaling_function(function);
+}
+
+int64_t SumMemoryConsumption(
+    base::optional<MemorySetting::MemoryType> memory_type_filter,
+    const std::vector<const MemorySetting*>& memory_settings) {
+  int64_t sum = 0;
+  for (size_t i = 0; i < memory_settings.size(); ++i) {
+    const MemorySetting* setting = memory_settings[i];
+    if (!memory_type_filter || memory_type_filter == setting->memory_type()) {
+      sum += setting->MemoryConsumption();
+    }
+  }
+  return sum;
+}
+
+int64_t SumMemoryConsumption(
+    base::optional<MemorySetting::MemoryType> memory_type_filter,
+    const std::vector<MemorySetting*>& memory_settings) {
+  const std::vector<const MemorySetting*> const_vector(
+      memory_settings.begin(), memory_settings.end());
+  return SumMemoryConsumption(memory_type_filter, const_vector);
+}
+
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/memory_settings.h b/src/cobalt/browser/memory_settings/memory_settings.h
index 6d27358..2635c99 100644
--- a/src/cobalt/browser/memory_settings/memory_settings.h
+++ b/src/cobalt/browser/memory_settings/memory_settings.h
@@ -19,9 +19,13 @@
 
 #include <map>
 #include <string>
+#include <vector>
 
+#include "base/callback.h"
 #include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/optional.h"
+#include "cobalt/browser/memory_settings/scaling_function.h"
 #include "cobalt/browser/memory_settings/texture_dimensions.h"
 #include "cobalt/math/size.h"
 #include "starboard/configuration.h"
@@ -39,28 +43,54 @@
   // SourceType defines the location where the setting was set from.
   // kNotApplicable means the setting is not supported on the current system
   // configuration.
-  enum SourceType { kUnset, kStarboardAPI, kBuildSetting, kCmdLine, kAutoSet };
+  enum SourceType { kUnset, kStarboardAPI, kBuildSetting, kCmdLine, kAutoSet,
+                    kAutosetConstrained };
   enum ClassType { kInt, kDimensions };
   enum MemoryType { kCPU, kGPU, kNotApplicable };
 
+  // Stringify's the value of this memory setting.
   virtual std::string ValueToString() const = 0;
   // Returns true if the TryParseValue() succeeded when converting the string
   // into the internal value. If false, then the object should not be changed.
   virtual bool TryParseValue(SourceType source_type,
                              const std::string& string_value) = 0;
 
+  // Returns the memory consumption (in bytes) that the memory setting will
+  // be allocated.
   virtual int64_t MemoryConsumption() const = 0;
 
+  // Sets the memory scaling function. This will control whether this
+  // MemorySetting will allow it's memory to be adjusted. If this is not
+  // set then ComputeAbsoluteMemoryScale(...) will return 1.0 for all inputs
+  // values, indicating that it can't be adjusted.
+  void set_memory_scaling_function(ScalingFunction function);
+
+  // Computes the absolute memory scale value from the requested_memory_scale.
+  // The absolute memory scale can be multiplied against MemoryConsumption()
+  // to predict the new memory consumption. This prediction should match the
+  // actual memory consumption after ScaleMemory(memory_scale) is called.
+  double ComputeAbsoluteMemoryScale(double requested_memory_scale) const;
+
+  // Adjusts the memory by the percentage passed in. Note that the base value
+  // is adjusted and repeatedly calling this function will repeatedly adjust
+  // this value. For example, calling AdjustMemory(.5) twice will reduce the
+  // memory by 25%.
+  //
+  // Calling this function will automatically set the source_type to
+  // kAutosetConstrained.
+  //
+  // Note that the expectation here is that the memory scale passed in was
+  // generated from ComputeAbsoluteMemoryScale().
+  virtual void ScaleMemory(double memory_scale) = 0;
+
   // Setting kNotApplicable will invalidate the MemorySetting.
   void set_memory_type(MemoryType memory_type) { memory_type_ = memory_type; }
-
   const std::string& name() const { return name_; }
   SourceType source_type() const { return source_type_; }
   ClassType class_type() const { return class_type_; }
   MemoryType memory_type() const { return memory_type_; }
 
   bool valid() const { return kNotApplicable != memory_type_; }
-
  protected:
   MemorySetting(ClassType type, const std::string& name);
 
@@ -68,6 +98,7 @@
   const std::string name_;
   SourceType source_type_;
   MemoryType memory_type_;  // Defaults to kCPU.
+  ScalingFunction memory_scaling_function_;
 
  private:
   // Default constructor for MemorySetting is forbidden. Do not use it.
@@ -82,6 +113,7 @@
 
   std::string ValueToString() const OVERRIDE;
   virtual int64_t MemoryConsumption() const OVERRIDE;
+  virtual void ScaleMemory(double absolute_constraining_value) OVERRIDE;
 
   int64_t value() const { return valid() ? value_ : 0; }
   base::optional<int64_t> optional_value() const {
@@ -95,7 +127,6 @@
   }
   bool TryParseValue(SourceType source_type,
                      const std::string& string_value) OVERRIDE;
-
  private:
   int64_t value_;
 
@@ -133,6 +164,29 @@
   SB_DISALLOW_COPY_AND_ASSIGN(DimensionSetting);
 };
 
+class SkiaGlyphAtlasTextureSetting : public DimensionSetting {
+ public:
+  SkiaGlyphAtlasTextureSetting();
+  virtual void ScaleMemory(double absolute_constraining_value) OVERRIDE;
+
+ private:
+  static size_t NumberOfReductions(double reduction_factor);
+};
+
+class JavaScriptGcThresholdSetting : public IntSetting {
+ public:
+  JavaScriptGcThresholdSetting();
+  void PostInit();
+};
+
+int64_t SumMemoryConsumption(
+    base::optional<MemorySetting::MemoryType> memory_type_filter,
+    const std::vector<const MemorySetting*>& memory_settings);
+
+int64_t SumMemoryConsumption(
+    base::optional<MemorySetting::MemoryType> memory_type_filter,
+    const std::vector<MemorySetting*>& memory_settings);
+
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/memory_settings_test.cc b/src/cobalt/browser/memory_settings/memory_settings_test.cc
index 956965f..2ca54ea 100644
--- a/src/cobalt/browser/memory_settings/memory_settings_test.cc
+++ b/src/cobalt/browser/memory_settings/memory_settings_test.cc
@@ -28,6 +28,13 @@
 namespace cobalt {
 namespace browser {
 namespace memory_settings {
+namespace {
+int64_t TestIntSettingParse(const std::string& value) {
+  IntSetting int_setting("dummy");
+  EXPECT_TRUE(int_setting.TryParseValue(MemorySetting::kCmdLine, value));
+  return int_setting.value();
+}
+}  // namespace
 
 TEST(IntSetting, ParseFromString) {
   scoped_ptr<IntSetting> int_setting(new IntSetting("dummy"));
@@ -38,8 +45,50 @@
   EXPECT_EQ(std::string("123"), int_setting->ValueToString());
 }
 
+// Tests the expectation that numerous string variations (whole numbers vs
+// fractions vs units) parse correctly.
+TEST(IntSetting, ParseFromStrings) {
+  // Bytes.
+  EXPECT_EQ(1, TestIntSettingParse("1"));
+  EXPECT_EQ(1, TestIntSettingParse("1B"));
+  EXPECT_EQ(1, TestIntSettingParse("1b"));
+  EXPECT_EQ(1, TestIntSettingParse("1B"));
+  EXPECT_EQ(1, TestIntSettingParse("1b"));
+
+  // Kilobytes and fractional amounts.
+  EXPECT_EQ(1024, TestIntSettingParse("1KB"));
+  EXPECT_EQ(1024, TestIntSettingParse("1Kb"));
+  EXPECT_EQ(1024, TestIntSettingParse("1kB"));
+  EXPECT_EQ(1024, TestIntSettingParse("1kb"));
+
+  EXPECT_EQ(512, TestIntSettingParse(".5kb"));
+  EXPECT_EQ(512, TestIntSettingParse("0.5kb"));
+  EXPECT_EQ(1536, TestIntSettingParse("1.5kb"));
+  EXPECT_EQ(1536, TestIntSettingParse("1.50kb"));
+
+  // Megabytes and fractional amounts.
+  EXPECT_EQ(1024*1024, TestIntSettingParse("1MB"));
+  EXPECT_EQ(1024*1024, TestIntSettingParse("1Mb"));
+  EXPECT_EQ(1024*1024, TestIntSettingParse("1mB"));
+  EXPECT_EQ(1024*1024, TestIntSettingParse("1mb"));
+
+  EXPECT_EQ(512*1024, TestIntSettingParse(".5mb"));
+  EXPECT_EQ(512*1024, TestIntSettingParse("0.5mb"));
+  EXPECT_EQ(1536*1024, TestIntSettingParse("1.5mb"));
+  EXPECT_EQ(1536*1024, TestIntSettingParse("1.50mb"));
+
+  // Gigabytes and fractional amounts.
+  EXPECT_EQ(1024*1024*1024, TestIntSettingParse("1GB"));
+  EXPECT_EQ(1024*1024*1024, TestIntSettingParse("1Gb"));
+  EXPECT_EQ(1024*1024*1024, TestIntSettingParse("1gB"));
+  EXPECT_EQ(1024*1024*1024, TestIntSettingParse("1gb"));
+
+  EXPECT_EQ(512*1024*1024, TestIntSettingParse(".5gb"));
+  EXPECT_EQ(1536*1024*1024, TestIntSettingParse("1.50gb"));
+}
+
 TEST(DimensionSetting, ParseFromString) {
-  scoped_ptr<DimensionSetting> rect_setting(new DimensionSetting("dummy"));
+  scoped_ptr<DimensionSetting> rect_setting(new TestDimensionSetting("dummy"));
   ASSERT_TRUE(
       rect_setting->TryParseValue(MemorySetting::kCmdLine, "1234x5678"));
   EXPECT_EQ(TextureDimensions(1234, 5678, 2), rect_setting->value());
@@ -47,8 +96,17 @@
   EXPECT_EQ(std::string("1234x5678x2"), rect_setting->ValueToString());
 }
 
+TEST(DimensionSetting, ParseFromStringCaseInsensitive) {
+  scoped_ptr<DimensionSetting> rect_setting(new TestDimensionSetting("dummy"));
+  ASSERT_TRUE(
+      rect_setting->TryParseValue(MemorySetting::kCmdLine, "1234X5678"));
+  EXPECT_EQ(TextureDimensions(1234, 5678, 2), rect_setting->value());
+  EXPECT_EQ(MemorySetting::kCmdLine, rect_setting->source_type());
+  EXPECT_EQ(std::string("1234x5678x2"), rect_setting->ValueToString());
+}
+
 TEST(DimensionSetting, ParseFromStringWithBytesPerPixel) {
-  scoped_ptr<DimensionSetting> rect_setting(new DimensionSetting("dummy"));
+  scoped_ptr<DimensionSetting> rect_setting(new TestDimensionSetting("dummy"));
   ASSERT_TRUE(
       rect_setting->TryParseValue(MemorySetting::kCmdLine, "1234x5678x12"));
   EXPECT_EQ(TextureDimensions(1234, 5678, 12), rect_setting->value());
diff --git a/src/cobalt/browser/memory_settings/pretty_print.cc b/src/cobalt/browser/memory_settings/pretty_print.cc
index c8fef61..41c278c 100644
--- a/src/cobalt/browser/memory_settings/pretty_print.cc
+++ b/src/cobalt/browser/memory_settings/pretty_print.cc
@@ -20,6 +20,7 @@
 #include <string>
 #include <vector>
 
+#include "base/string_split.h"
 #include "cobalt/browser/memory_settings/memory_settings.h"
 #include "cobalt/browser/memory_settings/table_printer.h"
 #include "starboard/log.h"
@@ -30,36 +31,8 @@
 namespace memory_settings {
 namespace {
 
-std::string StringifySourceType(const MemorySetting* setting) {
-  if (!setting->valid()) {
-    return "N/A";
-  }
-
-  switch (setting->source_type()) {
-    case MemorySetting::kUnset: {
-      return "Unset";
-    }
-    case MemorySetting::kStarboardAPI: {
-      return "Starboard API";
-    }
-    case MemorySetting::kBuildSetting: {
-      return "Build";
-    }
-    case MemorySetting::kCmdLine: {
-      return "CmdLine";
-    }
-    case MemorySetting::kAutoSet: {
-      return "AutoSet";
-    }
-  }
-
-  SB_NOTIMPLEMENTED() << "Unimplemented string for type: "
-                      << setting->source_type();
-  return "UNKNOWN";
-}
-
-std::string StringifyMemoryType(const MemorySetting* setting) {
-  switch (setting->memory_type()) {
+std::string StringifyMemoryType(const MemorySetting& setting) {
+  switch (setting.memory_type()) {
     case MemorySetting::kCPU: {
       return "CPU";
     }
@@ -72,7 +45,7 @@
   }
 
   SB_NOTIMPLEMENTED() << "Unimplemented string for memory type: "
-                      << setting->memory_type();
+                      << setting.memory_type();
   return "UNKNOWN";
 }
 
@@ -83,21 +56,21 @@
   return setting->ValueToString();
 }
 
-std::string ToMegabyteString(int64_t bytes) {
-  float megabytes = bytes / (1024.0f * 1024.0f);
-
-  char buff[128];
-  SbStringFormatF(buff, sizeof(buff), "%.1f MB", megabytes);
-  // Use 16
-  return std::string(buff);
+void FillStream(size_t count, const char fill_ch, std::stringstream* ss) {
+  for (size_t i = 0; i < count; ++i) {
+    (*ss) << fill_ch;
+  }
 }
 
 }  // namespace
 
 std::string GeneratePrettyPrintTable(
+    bool use_color_ascii,
     const std::vector<const MemorySetting*>& settings) {
   TablePrinter printer;
-
+  if (use_color_ascii) {
+    printer.set_text_color(TablePrinter::kGreen);
+  }
   std::vector<std::string> header;
   header.push_back("SETTING NAME");
   header.push_back("VALUE");
@@ -113,12 +86,12 @@
     row.push_back(setting->name());
     row.push_back(StringifyValue(setting));
     if (setting->valid()) {
-      row.push_back(ToMegabyteString(setting->MemoryConsumption()));
+      row.push_back(ToMegabyteString(setting->MemoryConsumption(), 1));
     } else {
       row.push_back("N/A");
     }
-    row.push_back(StringifyMemoryType(setting));
-    row.push_back(StringifySourceType(setting));
+    row.push_back(StringifyMemoryType(*setting));
+    row.push_back(StringifySourceType(*setting));
     printer.AddRow(row);
   }
 
@@ -126,11 +99,15 @@
   return table_string;
 }
 
-std::string GenerateMemoryTable(const IntSetting& total_cpu_memory,
+std::string GenerateMemoryTable(bool use_color_ascii,
+                                const IntSetting& total_cpu_memory,
                                 const IntSetting& total_gpu_memory,
                                 int64_t settings_cpu_consumption,
                                 int64_t settings_gpu_consumption) {
   TablePrinter printer;
+  if (use_color_ascii) {
+    printer.set_text_color(TablePrinter::kGreen);
+  }
   std::vector<std::string> header;
   header.push_back("MEMORY");
   header.push_back("SOURCE");
@@ -140,29 +117,102 @@
 
   std::vector<std::string> data_row;
   data_row.push_back(total_cpu_memory.name());
-  data_row.push_back(StringifySourceType(&total_cpu_memory));
-  data_row.push_back(ToMegabyteString(total_cpu_memory.value()));
-  data_row.push_back(ToMegabyteString(settings_cpu_consumption));
+  data_row.push_back(StringifySourceType(total_cpu_memory));
+  data_row.push_back(ToMegabyteString(total_cpu_memory.value(), 1));
+  data_row.push_back(ToMegabyteString(settings_cpu_consumption, 1));
   printer.AddRow(data_row);
   data_row.clear();
 
   data_row.push_back(total_gpu_memory.name());
-  data_row.push_back(StringifySourceType(&total_gpu_memory));
+  data_row.push_back(StringifySourceType(total_gpu_memory));
   std::string total_gpu_consumption_str;
-  if (total_gpu_memory.value() <= 0) {
+
+  const bool available_gpu_settings_invalid = (total_gpu_memory.value() <= 0);
+
+  if (available_gpu_settings_invalid) {
     total_gpu_consumption_str = "<UNKNOWN>";
   } else {
-    total_gpu_consumption_str = ToMegabyteString(total_gpu_memory.value());
+    total_gpu_consumption_str = ToMegabyteString(total_gpu_memory.value(), 1);
   }
 
   data_row.push_back(total_gpu_consumption_str);
-  data_row.push_back(ToMegabyteString(settings_gpu_consumption));
+  data_row.push_back(ToMegabyteString(settings_gpu_consumption, 1));
   printer.AddRow(data_row);
   data_row.clear();
-
   return printer.ToString();
 }
 
+std::string ToMegabyteString(int64_t bytes, int decimal_places) {
+  float megabytes = bytes / (1024.0f * 1024.0f);
+
+  std::stringstream ss_fmt;
+  // e.g. "%.1f MB"
+  ss_fmt << "%." << decimal_places << "f MB";
+
+  char buff[128];
+  SbStringFormatF(buff, sizeof(buff), ss_fmt.str().c_str(), megabytes);
+  // Use 16
+  return std::string(buff);
+}
+
+std::string MakeBorder(const std::string& body, const char border_ch) {
+  std::vector<std::string> lines;
+  base::SplitStringDontTrim(body, '\n', &lines);
+
+  size_t max_span = 0;
+  for (size_t i = 0; i < lines.size(); ++i) {
+    max_span = std::max(max_span, lines[i].size());
+  }
+
+  std::stringstream ss;
+  ss << "\n\n";
+
+  FillStream(max_span + 4, border_ch, &ss);
+  ss << "\n";
+  for (size_t i = 0; i < lines.size(); ++i) {
+    const std::string& line = lines[i];
+
+    ss << border_ch << ' ' << line;
+    FillStream(max_span - line.size() + 1, ' ', &ss);
+    ss << border_ch;
+    ss << "\n";
+  }
+  FillStream(max_span + 4, border_ch, &ss);
+  ss << "\n\n";
+  return ss.str();
+}
+
+std::string StringifySourceType(const MemorySetting& setting) {
+  if (!setting.valid()) {
+    return "N/A";
+  }
+
+  switch (setting.source_type()) {
+    case MemorySetting::kUnset: {
+      return "Unset";
+    }
+    case MemorySetting::kStarboardAPI: {
+      return "Starboard API";
+    }
+    case MemorySetting::kBuildSetting: {
+      return "Build";
+    }
+    case MemorySetting::kCmdLine: {
+      return "CmdLine";
+    }
+    case MemorySetting::kAutoSet: {
+      return "AutoSet";
+    }
+    case MemorySetting::kAutosetConstrained: {
+      return "AutoSet (Constrained)";
+    }
+  }
+
+  SB_NOTIMPLEMENTED() << "Unimplemented string for type: "
+                      << setting.source_type();
+  return "UNKNOWN";
+}
+
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/pretty_print.h b/src/cobalt/browser/memory_settings/pretty_print.h
index 1960e75..de355c2 100644
--- a/src/cobalt/browser/memory_settings/pretty_print.h
+++ b/src/cobalt/browser/memory_settings/pretty_print.h
@@ -50,6 +50,7 @@
 //  | software_surface_cache_size_in_bytes |         N/A |     N/A |  N/A |     N/A |
 //  |______________________________________|_____________|_________|______|_________|
 std::string GeneratePrettyPrintTable(
+    bool use_color_ascii,
     const std::vector<const MemorySetting*>& memory_settings);
 
 // Generates a table, ie:
@@ -64,11 +65,29 @@
 //  |______|__________|__________|
 // When optional total_gpu_memory is null then the the value in the output
 // table will be <UNKNOWN>.
-std::string GenerateMemoryTable(const IntSetting& total_cpu_memory,
+std::string GenerateMemoryTable(bool use_color_ascii,
+                                const IntSetting& total_cpu_memory,
                                 const IntSetting& total_gpu_memory,
                                 int64_t settings_cpu_consumption,
                                 int64_t settings_gpu_consumption);
 
+// Example:
+//   ToMegabyteString(1 * 1024 * 1024, 1)
+// Returns: "1.0MB".
+std::string ToMegabyteString(int64_t bytes, int decimal_places);
+
+// Takes in a body such as "aaaabbbb" and generates a border around it:
+// MakeBoarder("aaaabbbb", '*')
+// Returns:
+//   ************
+//   * aaaabbbb *
+//   ************
+// Works with multiple lines.
+std::string MakeBorder(const std::string& body, const char border_ch);
+
+// Stringify's the MemorySetting::source_type() to a readable string value.
+std::string StringifySourceType(const MemorySetting& setting);
+
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/pretty_print_test.cc b/src/cobalt/browser/memory_settings/pretty_print_test.cc
index f0bffb5..7f3db73 100644
--- a/src/cobalt/browser/memory_settings/pretty_print_test.cc
+++ b/src/cobalt/browser/memory_settings/pretty_print_test.cc
@@ -26,6 +26,7 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "cobalt/browser/memory_settings/memory_settings.h"
+#include "cobalt/browser/memory_settings/test_common.h"
 #include "cobalt/browser/switches.h"
 #include "starboard/log.h"
 #include "starboard/memory.h"
@@ -37,93 +38,11 @@
 namespace browser {
 namespace memory_settings {
 
-class TestSettingGroup {
- public:
-  TestSettingGroup() {}
-
-  void LoadDefault() {
-    MakeSetting(MemorySetting::kInt, MemorySetting::kCmdLine,
-                MemorySetting::kGPU, switches::kImageCacheSizeInBytes, "1234");
-
-    MakeSetting(MemorySetting::kInt, MemorySetting::kAutoSet,
-                MemorySetting::kCPU, switches::kJavaScriptGcThresholdInBytes,
-                "1112");
-
-    MakeSetting(MemorySetting::kDimensions, MemorySetting::kCmdLine,
-                MemorySetting::kGPU, switches::kSkiaTextureAtlasDimensions,
-                "1234x4567");
-
-    MakeSetting(MemorySetting::kInt, MemorySetting::kCmdLine,
-                MemorySetting::kGPU, switches::kSkiaCacheSizeInBytes,
-                "12345678");
-
-    MakeSetting(MemorySetting::kInt, MemorySetting::kBuildSetting,
-                MemorySetting::kNotApplicable,
-                switches::kSoftwareSurfaceCacheSizeInBytes, "8910");
-  }
-
-  ~TestSettingGroup() {
-    for (ConstIter it = map_.begin(); it != map_.end(); ++it) {
-      delete it->second;
-    }
-  }
-
-  // The memory setting is owned internally.
-  void MakeSetting(MemorySetting::ClassType class_type,
-                   MemorySetting::SourceType source_type,
-                   MemorySetting::MemoryType memory_type,
-                   const std::string& name, const std::string& value) {
-   const bool found = (map_.find(name) !=  map_.end());
-
-    ASSERT_FALSE(found);
-    map_[name] =
-        CreateMemorySetting(class_type, source_type, memory_type, name, value);
-  }
-
-  std::vector<const MemorySetting*> AsConstVector() const {
-    std::vector<const MemorySetting*> output;
-    for (ConstIter it = map_.begin(); it != map_.end(); ++it) {
-      output.push_back(it->second);
-    }
-    return output;
-  }
-
- private:
-  static MemorySetting* CreateMemorySetting(
-      MemorySetting::ClassType class_type,
-      MemorySetting::SourceType source_type,
-      MemorySetting::MemoryType memory_type, const std::string& name,
-      const std::string& value) {
-    MemorySetting* memory_setting = NULL;
-    switch (class_type) {
-      case MemorySetting::kInt: {
-        memory_setting = new IntSetting(name);
-        break;
-      }
-      case MemorySetting::kDimensions: {
-        memory_setting = new DimensionSetting(name);
-        break;
-      }
-      default: {
-        EXPECT_TRUE(false) << "Unexpected type " << class_type;
-        memory_setting = new IntSetting(name);
-        break;
-      }
-    }
-    EXPECT_TRUE(memory_setting->TryParseValue(source_type, value));
-    memory_setting->set_memory_type(memory_type);
-    return memory_setting;
-  }
-
-  typedef std::map<std::string, MemorySetting*>::const_iterator ConstIter;
-  std::map<std::string, MemorySetting*> map_;
-};
-
 TEST(MemorySettingsPrettyPrint, GeneratePrettyPrintTable) {
   TestSettingGroup setting_group;
   setting_group.LoadDefault();
   std::string actual_string =
-      GeneratePrettyPrintTable(setting_group.AsConstVector());
+      GeneratePrettyPrintTable(false, setting_group.AsConstVector());
 
   const char* expected_string =
       " SETTING NAME                           VALUE                   TYPE   SOURCE    \n"
@@ -154,7 +73,8 @@
   IntSetting gpu_memory_setting("max_gpu_memory");
 
   std::string actual_output =
-      GenerateMemoryTable(cpu_memory_setting,  // 256 MB CPU available
+      GenerateMemoryTable(false,               // No color.
+                          cpu_memory_setting,  // 256 MB CPU available
                           gpu_memory_setting,
                           128 * 1024 * 1024,  // 128 MB CPU consumption
                           0);                 // 0 MB GPU consumption.
@@ -181,7 +101,8 @@
       MemorySetting::kBuildSetting, 64 * 1024 * 1024);
 
   std::string actual_output =
-      GenerateMemoryTable(cpu_memory_setting,  // 256 MB CPU available.
+      GenerateMemoryTable(false,               // No color.
+                          cpu_memory_setting,  // 256 MB CPU available.
                           gpu_memory_setting,   // 64 MB GPU available.
                           128 * 1024 * 1024,  // 128 MB CPU consumption.
                           23592960);          // 22.5 MB GPU consumption.
@@ -204,6 +125,7 @@
   test_setting_group.LoadDefault();
 
   std::string actual_string = GeneratePrettyPrintTable(
+      false,  // No color.
       test_setting_group.AsConstVector());
 
   const char* expected_string =
@@ -237,6 +159,7 @@
 
   const base::optional<int64_t> no_gpu_memory;
   std::string actual_output = GenerateMemoryTable(
+      false,               // No color.
       cpu_memory_setting,  // 256 MB CPU available.
       gpu_memory_setting,  // Signals that no gpu memory is available
                            //   on this system.
diff --git a/src/cobalt/browser/memory_settings/scaling_function.cc b/src/cobalt/browser/memory_settings/scaling_function.cc
new file mode 100644
index 0000000..81cbb87
--- /dev/null
+++ b/src/cobalt/browser/memory_settings/scaling_function.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/browser/memory_settings/scaling_function.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "cobalt/math/clamp.h"
+#include "cobalt/math/linear_interpolator.h"
+
+namespace cobalt {
+namespace browser {
+namespace memory_settings {
+namespace {
+
+class JavaScriptGCMemoryScaler {
+ public:
+  JavaScriptGCMemoryScaler(int64_t min_memory, int64_t max_memory) {
+    DCHECK_LE(min_memory, max_memory);
+    min_memory = std::min(min_memory, max_memory);
+    const double min_factor = static_cast<double>(min_memory) /
+                              static_cast<double>(max_memory);
+    // From 95% -> 0%, the memory will stay the same. This effectivly
+    // clamps the minimum value.
+    interp_table_.Add(0.0, min_factor);
+
+    // At 95% memory, the memory falls to the min_factor. The rationale here
+    // is that most of the memory for JavaScript can be eliminated without
+    // a large performance penalty, so it's quickly reduced.
+    interp_table_.Add(.95, min_factor);
+
+    // At 100% we have 100% of memory.
+    interp_table_.Add(1.0, 1.0);
+  }
+  double Factor(double requested_memory_scale) const {
+    return interp_table_.Map(requested_memory_scale);
+  }
+
+ private:
+  math::LinearInterpolator<double, double> interp_table_;
+};
+
+double LinearFunctionWithClampValue(double min_clamp_value,
+                                    double max_clamp_value,
+                                    double requested_memory_scale) {
+  return math::Clamp(requested_memory_scale,
+                     min_clamp_value, max_clamp_value);
+}
+
+double SkiaAtlasGlyphTextureConstrainer(double requested_memory_scale) {
+  if (requested_memory_scale > 0.5f) {
+    return 1.0f;
+  } else {
+    return 0.5f;
+  }
+}
+
+}  // namespace.
+
+ScalingFunction MakeLinearMemoryScaler(double min_clamp_value,
+                                       double max_clamp_value) {
+  ScalingFunction function =
+      base::Bind(&LinearFunctionWithClampValue,
+                  min_clamp_value, max_clamp_value);
+  return function;
+}
+
+ScalingFunction MakeJavaScriptGCScaler(
+    int64_t min_consumption, int64_t max_consumption) {
+  JavaScriptGCMemoryScaler* constrainer =
+      new JavaScriptGCMemoryScaler(min_consumption, max_consumption);
+  // Note that Bind() will implicitly ref-count the constrainer pointer.
+  return base::Bind(&JavaScriptGCMemoryScaler::Factor,
+                    base::Owned(constrainer));
+}
+
+ScalingFunction MakeSkiaGlyphAtlasMemoryScaler() {
+  ScalingFunction function = base::Bind(&SkiaAtlasGlyphTextureConstrainer);
+  return function;
+}
+
+}  // namespace memory_settings
+}  // namespace browser
+}  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/scaling_function.h b/src/cobalt/browser/memory_settings/scaling_function.h
new file mode 100644
index 0000000..86191e7
--- /dev/null
+++ b/src/cobalt/browser/memory_settings/scaling_function.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_BROWSER_MEMORY_SETTINGS_SCALING_FUNCTION_H_
+#define COBALT_BROWSER_MEMORY_SETTINGS_SCALING_FUNCTION_H_
+
+#include <algorithm>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "starboard/types.h"
+
+namespace cobalt {
+namespace browser {
+namespace memory_settings {
+
+typedef base::Callback<double(double)> ScalingFunction;
+
+// The ConstrainerFunction generates constraining values which are used to
+// to adjust the memory settings from an input "requested_memory_scale".
+//
+// "requested_memory_scale" requests memory be scaled by a certain amount
+// percentage where 0.0 means "eliminate all memory please" and 1.0 is
+// "don't change" and 2.0 means "expand your memory consumption by 2x".
+//
+// A ScalingFunction works by remapping the input
+// "requested_memory_scale" value to an output "memory scaling factor" which
+// indicates how much memory will actually be reduced at the current scale.
+// This output ranges from ranges from 1.0 (no scaling - 100% of memory is
+// retained) to 0.0 (all memory is eliminated from this setting).
+//
+// Another way to understand the memory_scale value is by the
+// following analogy:
+//  when (1.0 > input => .9) => "Please reduce memory a little"
+//  when (.9 > input >= .5)  => "Please reduce memory - serious!"
+//  when (.5 > input >= .25) => "Please reduce memory - super serious!!"
+//  when (.25 > input >= .0) => "Please reduce memory - last chances!!!"
+//
+// Similarly:
+//  when (2.0 > input >= 1) => "Please expand memory by a lot.".
+//
+// Output "memory scaling factor" value represents the amount of memory that
+// will be scaled at the current requested_memory_scale value. This
+// "memory scaling factor" is an absolute value, such that 0.5 means that
+// the memory consumption will be reduced by 50%.
+//
+// EXAMPLE:
+//   Function(.9) => Returns => 0.1
+//   Means: "You asked me to reduce memory a little, but I can go ahead and
+//          free up 90% of my memory."
+//
+//   Function(.5) => Returns => 1.0
+//   Means: "You asked me to reduce memory and were serious, but I am refusing
+//          to reduce memory consumption."
+//
+//   Function(.25) => Returns => .9
+//   Means: "You are at the final stages of asking me to reduce memory and
+//          I can go ahead and reduce my memory foot print by 10%."
+//
+// More information:
+//
+// Low Priority Memory Settings should respond quickly to constraining
+// situations by quickly shedding memory:
+//
+//    1 *+--------+---------+---------+---------+--------++
+//      +*        +         +         +         +         +
+//      | *                                               |
+//      |  *                                              |
+//  0.8 ++  *                                            ++
+//      |    *                                            |
+//      |     *                                           |
+//      |      **                                         |
+//  0.6 ++      **     y=x*x*x                           ++
+//      |        **                                       |
+//      |          **                                     |
+//  0.4 ++          **                                   ++
+//      |             **                                  |
+//      |              ***                                |
+//      |                ***                              |
+//  0.2 ++                 ***                           ++
+//      |                     ***                         |
+//      |                        ****                     |
+//      +         +         +        *******    +         +
+//    0 ++--------+---------+---------+----****************
+//      1        0.8       0.6       0.4       0.2        0
+//
+//
+// This is a curve of a high priority setting: one which is resistant to giving
+// up memory.
+//    1 ******----+---------+---------+---------+--------++
+//      +     *********     +         +         +         +
+//      |             ********                            |
+//      |                     *******                     |
+//  0.8 ++                          ******               ++
+//      |               y=sqrt(sqrt(x))  *****            |
+//      |                                    ****         |
+//      |                                        ***      |
+//  0.6 ++                                         ***   ++
+//      |                                            **   |
+//      |                                              ** |
+//  0.4 ++                                              *++
+//      |                                                *|
+//      |                                                *|
+//      |                                                 *
+//  0.2 ++                                               +*
+//      |                                                 *
+//      |                                                 *
+//      +         +         +         +         +         *
+//    0 ++--------+---------+---------+---------+--------+*
+//      1        0.8       0.6       0.4       0.2        0
+//
+// While the following graph will refuse to give up any memory whatsoever.
+// For example.
+//                                 y=1
+//    1.0 *************************************************
+//        +         +        +         +        +       * +
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//    0.5 |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        |                                               |
+//        +         +        +         +        +         +
+//   0.0  ++--------+--------+---------+--------+--------++
+//        1        0.8      0.6       0.4      0.2        0
+//
+
+// Generates a functor that will lower the memory consumption linearly with
+// the progress of the input, but will clamp at the input level.
+// Example:
+//   ConstrainerFunction fun = MakeLinearConstrainerFunction(.75);
+//   EXPECT_EQ(.9, fun(.9));
+//   EXPECT_EQ(.75, fun(.75));
+//   EXPECT_EQ(.75, fun(.5));
+//   EXPECT_EQ(.75, fun(0));
+ScalingFunction MakeLinearMemoryScaler(
+    double min_clamp_value,
+    double max_clamp_value);
+
+// Generates a functor that will shed most of the memory of the JavaScriptGC
+// very quickly.
+ScalingFunction MakeJavaScriptGCScaler(
+    int64_t min_consumption, int64_t max_consumption);
+
+// Generates a functor that will shed 50% of memory when the requested
+// memory scale is .5 or less, otherwise no memory is reduced.
+ScalingFunction MakeSkiaGlyphAtlasMemoryScaler();
+
+}  // namespace memory_settings
+}  // namespace browser
+}  // namespace cobalt
+
+#endif  // COBALT_BROWSER_MEMORY_SETTINGS_SCALING_FUNCTION_H_
diff --git a/src/cobalt/browser/memory_settings/table_printer.cc b/src/cobalt/browser/memory_settings/table_printer.cc
index ee85579..69b9612 100644
--- a/src/cobalt/browser/memory_settings/table_printer.cc
+++ b/src/cobalt/browser/memory_settings/table_printer.cc
@@ -22,6 +22,7 @@
 #include <string>
 
 #include "base/logging.h"
+#include "starboard/log.h"
 
 namespace cobalt {
 namespace browser {
@@ -58,6 +59,14 @@
   return ss.str();
 }
 
+std::string MakeFill(const char* str, size_t n) {
+  std::stringstream ss;
+  for (size_t i = 0; i < n; ++i) {
+    ss << str;
+  }
+  return ss.str();
+}
+
 class TablePrinterImpl {
  public:
   // First row is the header.
@@ -200,35 +209,41 @@
     }
   }
   ss << " ";
-  std::string output = AddColor(text_color_, ss.str());
-  return output;
+  return ss.str();
 }
 
 std::string TablePrinterImpl::MakeDataRow(const Row& row) const {
-  std::stringstream output_ss;
+  // Safe integer math for creating a fill size. Because this size is based on
+  // subtraction of size_t values, it's possible that an empty string could
+  // cause a rollover of size_t as an input to string creation, causing
+  // a crash.
+  // This math is made safe by doing the integer calculations in int64_t and
+  // then clamping to positive values.
+  struct F {
+    static size_t CreateFillSize(size_t col_size, size_t element_size) {
+      int64_t value = static_cast<int64_t>(col_size) -
+                      static_cast<int64_t>(element_size) - 1;
+      value = std::max<int64_t>(0, value);
+      return static_cast<size_t>(value);
+    }
+  };
 
+  std::stringstream output_ss;
   const std::string vertical_bar = AddColor(table_color_, "|");
 
   for (size_t i = 0; i < row.size(); ++i) {
-    std::stringstream token_ss;
-    token_ss << " ";  // Padding
-    token_ss << row[i];
-    token_ss << " ";
-
-    std::string token = token_ss.str();
+    std::string token = AddColor(text_color_, row[i]);
 
     std::stringstream row_ss;
     const int col_size = static_cast<int>(column_sizes_[i]);
     row_ss << vertical_bar;
-    row_ss << std::setfill(' ');
-    row_ss << std::setw(col_size);
+    const size_t fill_size = F::CreateFillSize(col_size, row[i].size());
     if (i == 0) {
-      row_ss << std::left;  // Left justification for first column.
+      row_ss << " " << token << MakeFill(" ", fill_size);
     } else {
-      row_ss << std::right;  // Right justification for all other columns.
+      row_ss << MakeFill(" ", fill_size) << token << " ";
     }
 
-    row_ss << AddColor(text_color_, token);
     output_ss << row_ss.str();
   }
   output_ss << vertical_bar;
@@ -284,6 +299,10 @@
 
 }  // namespace.
 
+bool TablePrinter::SystemSupportsColor() {
+  return SbLogIsTty();
+}
+
 TablePrinter::TablePrinter() : text_color_(kDefault), table_color_(kDefault) {
 }
 
diff --git a/src/cobalt/browser/memory_settings/table_printer.h b/src/cobalt/browser/memory_settings/table_printer.h
index 29d1d0f..8795f51 100644
--- a/src/cobalt/browser/memory_settings/table_printer.h
+++ b/src/cobalt/browser/memory_settings/table_printer.h
@@ -39,6 +39,8 @@
 //      "+--------+--------+\n";
 class TablePrinter {
  public:
+  static bool SystemSupportsColor();
+
   enum Color {
     kDefault,
     kRed,
diff --git a/src/cobalt/browser/memory_settings/table_printer_test.cc b/src/cobalt/browser/memory_settings/table_printer_test.cc
index f03250f..a6de9ad 100644
--- a/src/cobalt/browser/memory_settings/table_printer_test.cc
+++ b/src/cobalt/browser/memory_settings/table_printer_test.cc
@@ -69,10 +69,10 @@
 
   std::string table_str = table.ToString();
   std::string expected_table_str =
-      R(" col1     col2     ") "\n"
+      " col1     col2     \n"
       G(" _________________ ") "\n"
       G("|        |        |") "\n"
-      G("|") R(" value1 ") G("|") R(" value2 ") G("|") "\n"
+      G("|") " " R("value1") " " G("|") " " R("value2") " " G("|") "\n"
       G("|________|________|") "\n";
 
 #undef R
diff --git a/src/cobalt/browser/memory_settings/test_common.h b/src/cobalt/browser/memory_settings/test_common.h
index 7e489ff..9078573 100644
--- a/src/cobalt/browser/memory_settings/test_common.h
+++ b/src/cobalt/browser/memory_settings/test_common.h
@@ -17,15 +17,21 @@
 #ifndef COBALT_BROWSER_MEMORY_SETTINGS_TEST_COMMON_H_
 #define COBALT_BROWSER_MEMORY_SETTINGS_TEST_COMMON_H_
 
+#include <map>
 #include <sstream>
 #include <string>
+#include <vector>
 
+#include "base/compiler_specific.h"
+#include "cobalt/browser/memory_settings/memory_settings.h"
 #include "cobalt/browser/memory_settings/texture_dimensions.h"
+#include "cobalt/browser/switches.h"
 #include "cobalt/math/size.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 // PrintToString() provides the proper functionality to pretty print custom
 // types.
+
 namespace testing {
 
 template <>
@@ -46,4 +52,114 @@
 
 }  // namespace testing
 
+namespace cobalt {
+namespace browser {
+namespace memory_settings {
+
+class TestDimensionSetting : public DimensionSetting {
+ public:
+  explicit TestDimensionSetting(const std::string& name)
+      : DimensionSetting(name) {}
+  virtual void ScaleMemory(double absolute_constraining_value) {
+    UNREFERENCED_PARAMETER(absolute_constraining_value);
+  }
+};
+
+class TestSettingGroup {
+ public:
+  TestSettingGroup() {}
+
+  void LoadDefault() {
+    MakeSetting(MemorySetting::kInt, MemorySetting::kCmdLine,
+                MemorySetting::kGPU, switches::kImageCacheSizeInBytes,
+                "1234");
+
+    MakeSetting(MemorySetting::kInt, MemorySetting::kAutoSet,
+                MemorySetting::kCPU, switches::kJavaScriptGcThresholdInBytes,
+                "1112");
+
+    MakeSetting(MemorySetting::kDimensions, MemorySetting::kCmdLine,
+                MemorySetting::kGPU, switches::kSkiaTextureAtlasDimensions,
+                "1234x4567");
+
+    MakeSetting(MemorySetting::kInt, MemorySetting::kCmdLine,
+                MemorySetting::kGPU, switches::kSkiaCacheSizeInBytes,
+                "12345678");
+
+    MakeSetting(MemorySetting::kInt, MemorySetting::kBuildSetting,
+                MemorySetting::kNotApplicable,
+                switches::kSoftwareSurfaceCacheSizeInBytes,
+                "8910");
+  }
+
+  ~TestSettingGroup() {
+    for (MemoryMap::const_iterator it = map_.begin(); it != map_.end(); ++it) {
+      delete it->second;
+    }
+  }
+
+  // The memory setting is owned internally.
+  void MakeSetting(
+      MemorySetting::ClassType class_type,
+      MemorySetting::SourceType source_type,
+      MemorySetting::MemoryType memory_type,
+      const std::string& name, const std::string& value) {
+    const bool found = (map_.find(name) !=  map_.end());
+
+    ASSERT_FALSE(found);
+    map_[name] =
+        CreateMemorySetting(class_type, source_type, memory_type, name, value);
+  }
+
+  std::vector<const MemorySetting*> AsConstVector() const {
+    std::vector<const MemorySetting*> output;
+    for (MemoryMap::const_iterator it = map_.begin(); it != map_.end(); ++it) {
+      output.push_back(it->second);
+    }
+    return output;
+  }
+
+  std::vector<MemorySetting*> AsMutableVector() {
+    std::vector<MemorySetting*> output;
+    for (MemoryMap::iterator it = map_.begin(); it != map_.end(); ++it) {
+      output.push_back(it->second);
+    }
+    return output;
+  }
+
+ private:
+  static MemorySetting* CreateMemorySetting(
+      MemorySetting::ClassType class_type,
+      MemorySetting::SourceType source_type,
+      MemorySetting::MemoryType memory_type, const std::string& name,
+      const std::string& value) {
+    MemorySetting* memory_setting = NULL;
+    switch (class_type) {
+      case MemorySetting::kInt: {
+        memory_setting = new IntSetting(name);
+        break;
+      }
+      case MemorySetting::kDimensions: {
+        memory_setting = new TestDimensionSetting(name);
+        break;
+      }
+      default: {
+        EXPECT_TRUE(false) << "Unexpected type " << class_type;
+        memory_setting = new IntSetting(name);
+        break;
+      }
+    }
+    EXPECT_TRUE(memory_setting->TryParseValue(source_type, value));
+    memory_setting->set_memory_type(memory_type);
+    return memory_setting;
+  }
+
+  typedef std::map<std::string, MemorySetting*> MemoryMap;
+  MemoryMap map_;
+};
+
+}  // namespace memory_settings
+}  // namespace browser
+}  // namespace cobalt
+
 #endif  // COBALT_BROWSER_MEMORY_SETTINGS_TEST_COMMON_H_
diff --git a/src/cobalt/browser/memory_tracker/tool/malloc_stats_tool.cc b/src/cobalt/browser/memory_tracker/tool/malloc_stats_tool.cc
index 5c77791..c06d98a 100644
--- a/src/cobalt/browser/memory_tracker/tool/malloc_stats_tool.cc
+++ b/src/cobalt/browser/memory_tracker/tool/malloc_stats_tool.cc
@@ -55,8 +55,7 @@
 }
 
 void MallocStatsTool::Run(Params* params) {
-  // Run function does almost nothing.
-  params->logger()->Output("MallocStatsTool running...");
+  params->logger()->Output("MallocStatsTool running...\n");
 
   Timer output_timer(base::TimeDelta::FromSeconds(30));
   Timer sample_timer(base::TimeDelta::FromMilliseconds(50));
@@ -102,7 +101,8 @@
       // By double the sampling time this keeps the table linear with
       // respect to time. If sampling time was not doubled then there
       // would be time distortion in the graph.
-      sample_timer.ScaleTimerAndReset(2.0);
+      sample_timer.ScaleTriggerTime(2.0);
+      sample_timer.Restart();
     }
   }
 }
diff --git a/src/cobalt/browser/memory_tracker/tool/util.cc b/src/cobalt/browser/memory_tracker/tool/util.cc
index b25c481..5e83b22 100644
--- a/src/cobalt/browser/memory_tracker/tool/util.cc
+++ b/src/cobalt/browser/memory_tracker/tool/util.cc
@@ -125,12 +125,11 @@
   }
 }
 
-void Timer::ScaleTimerAndReset(double scale) {
+void Timer::ScaleTriggerTime(double scale) {
   int64_t old_dt = time_before_expiration_.InMicroseconds();
   int64_t new_dt =
       static_cast<int64_t>(static_cast<double>(old_dt) * scale);
   time_before_expiration_ = base::TimeDelta::FromMicroseconds(new_dt);
-  Restart();
 }
 
 const char* BaseNameFast(const char* file_name) {
diff --git a/src/cobalt/browser/memory_tracker/tool/util.h b/src/cobalt/browser/memory_tracker/tool/util.h
index 02f2ca8..00cb0ff 100644
--- a/src/cobalt/browser/memory_tracker/tool/util.h
+++ b/src/cobalt/browser/memory_tracker/tool/util.h
@@ -72,7 +72,7 @@
   v->erase(write_it, v->end());
 }
 
-// Simple timer class that fires periodically after dt time has elapsed.
+// Simple timer class that fires periodically after time has elapsed.
 class Timer {
  public:
   typedef base::Callback<base::TimeTicks(void)> TimeFunctor;
@@ -82,7 +82,7 @@
 
   void Restart();
   bool UpdateAndIsExpired();  // Returns true if the expiration was triggered.
-  void ScaleTimerAndReset(double scale);
+  void ScaleTriggerTime(double scale);
 
  private:
   base::TimeTicks Now();
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index fcddd62..e4dae06 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-56829
\ No newline at end of file
+58719
\ No newline at end of file
diff --git a/src/cobalt/build/gyp_utils.py b/src/cobalt/build/gyp_utils.py
index 3f1ac0b..4931087 100644
--- a/src/cobalt/build/gyp_utils.py
+++ b/src/cobalt/build/gyp_utils.py
@@ -38,8 +38,9 @@
 
 # The list of directories, relative to "src/", to search through for ports.
 _PORT_SEARCH_PATH = [
-    'third_party/starboard',
     'starboard',
+    os.path.join('starboard', 'port'),
+    os.path.join('third_party', 'starboard'),
 ]
 
 # The path to the build.id file that preserves a build ID.
@@ -279,22 +280,28 @@
 def _FindThirdPartyPlatforms():
   """Workhorse for GetThirdPartyPlatforms().
 
-  Search through directories listed in _PORT_SEARCH_PATH to find valid ports, so
-  that they can be added to the VALID_PLATFORMS list. This allows gyp_cobalt to
-  register new ports without needing to modify code in src/cobalt/.
+  Search through directories listed in _PORT_SEARCH_PATH to find valid
+  ports, so that they can be added to the VALID_PLATFORMS list. This
+  allows gyp_cobalt to register new ports without needing to modify
+  code in src/cobalt/.
 
   Returns:
     A dictionary of name->absolute paths to the port directory.
+
   """
 
   result = {}
-  for path_element in _PORT_SEARCH_PATH:
-    root = os.path.join(paths.REPOSITORY_ROOT, path_element)
-    if not os.path.isdir(root):
-      logging.warning('Port search path directory not found: %s', path_element)
+  search_path = [os.path.realpath(os.path.join(paths.REPOSITORY_ROOT, x))
+                 for x in _PORT_SEARCH_PATH]
+
+  # Ignore search path directories inside other search path directories.
+  exclusion_set = set(search_path)
+
+  for entry in search_path:
+    if not os.path.isdir(entry):
       continue
-    root = os.path.realpath(root)
-    for platform_info in platform.PlatformInfo.EnumeratePorts(root):
+    for platform_info in platform.PlatformInfo.EnumeratePorts(entry,
+                                                              exclusion_set):
       if platform_info.port_name in result:
         logging.error('Found duplicate port name "%s" at "%s" and "%s"',
                       platform_info.port_name, result[platform_info.port_name],
diff --git a/src/cobalt/doc/spherical_video.md b/src/cobalt/doc/spherical_video.md
index f117617..c38da9f 100644
--- a/src/cobalt/doc/spherical_video.md
+++ b/src/cobalt/doc/spherical_video.md
@@ -36,5 +36,42 @@
 }
 ```
 
-Finally, it is required that your platform provides
+It is required that your platform provides
 [decode-to-texture support](../../starboard/doc/howto_decode_to_texture.md).
+
+## Input
+
+Cobalt currently supports input mappings from the following keys (defined in [starboard/key.h](../../starboard/key.h)):
+
+ - `kSbKeyLeft`
+ - `kSbKeyUp`
+ - `kSbKeyRight`
+ - `kSbKeyDown`
+ - `kSbKeyGamepadDPadUp`
+ - `kSbKeyGamepadDPadDown`
+ - `kSbKeyGamepadDPadLeft`
+ - `kSbKeyGamepadDPadRight`
+ - `kSbKeyGamepadLeftStickUp`
+ - `kSbKeyGamepadLeftStickDown`
+ - `kSbKeyGamepadLeftStickLeft`
+ - `kSbKeyGamepadLeftStickRight`
+ - `kSbKeyGamepadRightStickUp`
+ - `kSbKeyGamepadRightStickDown`
+ - `kSbKeyGamepadRightStickLeft`
+ - `kSbKeyGamepadRightStickRight`
+
+Additionally, if your platform generates `kSbInputEventTypeMove` (from
+[starboard/input.h](../../starboard/input.h)) events with
+`SbInputData::position` set to values in the range `[-1, 1]`, for the following
+keys,
+
+ - `kSbKeyGamepadLeftStickUp`
+ - `kSbKeyGamepadLeftStickDown`
+ - `kSbKeyGamepadLeftStickLeft`
+ - `kSbKeyGamepadLeftStickRight`
+ - `kSbKeyGamepadRightStickUp`
+ - `kSbKeyGamepadRightStickDown`
+ - `kSbKeyGamepadRightStickLeft`
+ - `kSbKeyGamepadRightStickRight`
+
+then they will be treated as analog inputs when controlling the camera.
diff --git a/src/cobalt/dom/document.cc b/src/cobalt/dom/document.cc
index 32d5f9e..f42ff0b 100644
--- a/src/cobalt/dom/document.cc
+++ b/src/cobalt/dom/document.cc
@@ -590,10 +590,15 @@
   }
 }
 
-void Document::UpdateComputedStyleOnElementAndAncestor(HTMLElement* element) {
-  if (!element || element->node_document() != this ||
-      !is_computed_style_dirty_) {
-    return;
+bool Document::UpdateComputedStyleOnElementAndAncestor(HTMLElement* element) {
+  TRACE_EVENT0(
+      "cobalt::dom", "Document::UpdateComputedStyleOnElementAndAncestor");
+  if (!element || element->node_document() != this) {
+    return false;
+  }
+
+  if (!is_computed_style_dirty_) {
+    return true;
   }
 
   UpdateSelectorTree();
@@ -607,16 +612,16 @@
   std::vector<HTMLElement*> ancestors;
   while (true) {
     ancestors.push_back(element);
-    if (element->parent_node() == dynamic_cast<Node*>(this)) {
+    if (element->parent_node() == static_cast<Node*>(this)) {
       break;
     }
     Element* parent_element = element->parent_element();
     if (!parent_element) {
-      return;
+      return false;
     }
     element = parent_element->AsHTMLElement();
     if (!element) {
-      return;
+      return false;
     }
   }
 
@@ -640,6 +645,8 @@
     previous_element = current_element;
     ancestors_were_valid = is_valid;
   }
+
+  return true;
 }
 
 void Document::SampleTimelineTime() { default_timeline_->Sample(); }
diff --git a/src/cobalt/dom/document.h b/src/cobalt/dom/document.h
index fd9602c..5c049cf 100644
--- a/src/cobalt/dom/document.h
+++ b/src/cobalt/dom/document.h
@@ -294,7 +294,8 @@
 
   // Updates the computed styles of the element and all its ancestors.
   // Matching rules, media rules, font faces and key frames are also updated.
-  void UpdateComputedStyleOnElementAndAncestor(HTMLElement* element);
+  // Returns whether the computed style is valid after the call.
+  bool UpdateComputedStyleOnElementAndAncestor(HTMLElement* element);
 
   // Manages the clock used by Web Animations.
   //     https://www.w3.org/TR/web-animations
diff --git a/src/cobalt/dom/dom.gyp b/src/cobalt/dom/dom.gyp
index 9e4437d..a1d6fbb 100644
--- a/src/cobalt/dom/dom.gyp
+++ b/src/cobalt/dom/dom.gyp
@@ -321,6 +321,9 @@
             '<(DEPTH)/cobalt/media/media.gyp:media',
           ],
         }],
+        ['enable_map_to_mesh == 1', {
+          'defines' : ['ENABLE_MAP_TO_MESH'],
+        }],
       ],
       # This target doesn't generate any headers, but it exposes generated
       # header files (for idl dictionaries) through this module's public header
diff --git a/src/cobalt/dom/event.cc b/src/cobalt/dom/event.cc
index 2484c59..a3623e9 100644
--- a/src/cobalt/dom/event.cc
+++ b/src/cobalt/dom/event.cc
@@ -76,11 +76,6 @@
 }
 
 void Event::InitEvent(const std::string& type, bool bubbles, bool cancelable) {
-  // Our event is for single use only.
-  DCHECK(!IsBeingDispatched());
-  DCHECK(!target());
-  DCHECK(!current_target());
-
   if (IsBeingDispatched() || target() || current_target()) {
     return;
   }
diff --git a/src/cobalt/dom/html_element.cc b/src/cobalt/dom/html_element.cc
index af05c42..93a6f9f 100644
--- a/src/cobalt/dom/html_element.cc
+++ b/src/cobalt/dom/html_element.cc
@@ -818,7 +818,10 @@
     return false;
   }
 
-  document->UpdateComputedStyleOnElementAndAncestor(this);
+  if (!document->UpdateComputedStyleOnElementAndAncestor(this)) {
+    return false;
+  }
+  DCHECK(computed_style());
 
   return computed_style()->display() != cssom::KeywordValue::GetNone() &&
          computed_style()->visibility() == cssom::KeywordValue::GetVisible();
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc
index 51edf3e..954999f 100644
--- a/src/cobalt/dom/html_media_element.cc
+++ b/src/cobalt/dom/html_media_element.cc
@@ -1614,8 +1614,22 @@
   return media_source_url_.spec();
 }
 
-bool HTMLMediaElement::PreferDecodeToTexture() const {
+bool HTMLMediaElement::PreferDecodeToTexture() {
+  TRACE_EVENT0("cobalt::dom", "HTMLMediaElement::PreferDecodeToTexture");
+
+#if defined(ENABLE_MAP_TO_MESH)
+  if (!node_document()->UpdateComputedStyleOnElementAndAncestor(this)) {
+    LOG(WARNING) << "Could not update computed style.";
+    NOTREACHED();
+    return false;
+  }
+
   if (!computed_style()) {
+    // This has been found to occur when HTMLMediaElement::OnLoadTimer() is on
+    // the callstack, though the visual inspection of the display shows that
+    // we are in the settings menu.
+    LOG(WARNING) << "PreferDecodeToTexture() could not get the computed style.";
+    NOTREACHED();
     return false;
   }
 
@@ -1624,6 +1638,10 @@
           computed_style()->filter());
 
   return map_to_mesh_filter;
+#else  // defined(ENABLE_MAP_TO_MESH)
+  // If map-to-mesh is disabled, we never prefer decode-to-texture.
+  return false;
+#endif  // defined(ENABLE_MAP_TO_MESH)
 }
 
 #if defined(COBALT_MEDIA_SOURCE_2016)
diff --git a/src/cobalt/dom/html_media_element.h b/src/cobalt/dom/html_media_element.h
index 154d73c..9001872 100644
--- a/src/cobalt/dom/html_media_element.h
+++ b/src/cobalt/dom/html_media_element.h
@@ -242,7 +242,7 @@
   void SourceOpened() OVERRIDE;
 #endif  // defined(COBALT_MEDIA_SOURCE_2016)
   std::string SourceURL() const OVERRIDE;
-  bool PreferDecodeToTexture() const OVERRIDE;
+  bool PreferDecodeToTexture() OVERRIDE;
 #if defined(COBALT_MEDIA_SOURCE_2016)
   void EncryptedMediaInitDataEncountered(
       media::EmeInitDataType init_data_type, const unsigned char* init_data,
diff --git a/src/cobalt/fetch/embedded_scripts/fetch.js b/src/cobalt/fetch/embedded_scripts/fetch.js
new file mode 100644
index 0000000..884fabb
--- /dev/null
+++ b/src/cobalt/fetch/embedded_scripts/fetch.js
@@ -0,0 +1,16 @@
+'use strict';(function(g){function p(a){"string"!==typeof a&&(a=String(a));if(/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(a))throw new h("Invalid character in header field name");return a.toLowerCase()}function v(a){"string"!==typeof a&&(a=String(a));var b,d;for(b=0;b<a.length;b++){var c=a.charCodeAt(b);if(9!==c&&10!==c&&13!==c&&32!==c)break}for(d=a.length-1;d>b&&(c=a.charCodeAt(d),9===c||10===c||13===c||32===c);d--);a=a.substring(b,d+1);for(b=0;b<a.length;b++)if(c=a.charCodeAt(b),256<=c||0===c||10===c||13===
+c)throw new h("Invalid character in header field value");return a}function e(a){this.map=new q;if(void 0!==a){if(null===a||"object"!==typeof a)throw new h("Constructing Headers with invalid parameters");a instanceof e?a.forEach(function(a,d){this.append(d,a)},this):m.isArray(a)?a.forEach(function(a){if(2!==a.length)throw new h("Constructing Headers with invalid parameters");this.append(a[0],a[1])},this):Object.getOwnPropertyNames(a).forEach(function(b){this.append(b,a[b])},this)}}function t(a){if(a.bodyUsed)return Promise.reject(new h("Already read"));
+a.bodyUsed=!0}function w(a){return new Promise(function(b,d){a.onload=function(){b(a.result)};a.onerror=function(){d(a.error)}})}function z(a){var b=new FileReader,d=w(b);b.readAsArrayBuffer(a);return d}function A(a){a=new Uint8Array(a);for(var b=new m(a.length),d=0;d<a.length;d++)b[d]=String.fromCharCode(a[d]);return b.join("")}function x(a){if(a.slice)return a.slice(0);var b=new Uint8Array(a.byteLength);b.set(new Uint8Array(a));return b.buffer}function y(){this.bodyUsed=!1;this._initBody=function(a){if(this._bodyInit=
+a)if("string"===typeof a)this._bodyText=a;else if(k.blob&&Blob.prototype.isPrototypeOf(a))this._bodyBlob=a;else if(k.formData&&FormData.prototype.isPrototypeOf(a))this._bodyFormData=a;else if(k.searchParams&&URLSearchParams.prototype.isPrototypeOf(a))this._bodyText=a.toString();else if(k.arrayBuffer&&k.blob&&B(a))this._bodyArrayBuffer=x(a.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer]);else if(k.arrayBuffer&&(ArrayBuffer.prototype.isPrototypeOf(a)||C(a)))this._bodyArrayBuffer=x(a);else throw new u("unsupported BodyInit type");
+else this._bodyText="";this.headers.get("content-type")||("string"===typeof a?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):k.searchParams&&URLSearchParams.prototype.isPrototypeOf(a)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))};k.blob&&(this.blob=function(){var a=t(this);if(a)return a;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));
+if(this._bodyFormData)throw new u("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?t(this)||Promise.resolve(this._bodyArrayBuffer):this.blob().then(z)});this.text=function(){var a=t(this);if(a)return a;if(this._bodyBlob){var a=this._bodyBlob,b=new FileReader,d=w(b);b.readAsText(a);return d}if(this._bodyArrayBuffer)return Promise.resolve(A(this._bodyArrayBuffer));if(this._bodyFormData)throw new u("could not read FormData body as text");
+return Promise.resolve(this._bodyText)};k.formData&&(this.formData=function(){return this.text().then(D)});this.json=function(){return this.text().then(JSON.parse)};return this}function n(a,b){b=b||{};var d=b.body;if(a instanceof n){if(a.bodyUsed)throw new h("Already read");this.url=a.url;this.credentials=a.credentials;b.headers||(this.headers=new e(a.headers));this.method=a.method;this.mode=a.mode;d||null==a._bodyInit||(d=a._bodyInit,a.bodyUsed=!0)}else this.url=String(a);this.credentials=b.credentials||
+this.credentials||"omit";if(b.headers||!this.headers)this.headers=new e(b.headers);a=b.method||this.method||"GET";var c=a.toUpperCase();this.method=-1<E.indexOf(c)?c:a;this.mode=b.mode||this.mode||null;this.referrer=null;if(("GET"===this.method||"HEAD"===this.method)&&d)throw new h("Body not allowed for GET or HEAD requests");this._initBody(d)}function D(a){var b=new FormData;a.trim().split("&").forEach(function(a){if(a){var c=a.split("=");a=c.shift().replace(/\+/g," ");c=c.join("=").replace(/\+/g,
+" ");b.append(decodeURIComponent(a),decodeURIComponent(c))}});return b}function F(a){var b=new e;a.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach(function(a){var c=a.split(":");if(a=c.shift().trim())c=c.join(":").trim(),b.append(a,c)});return b}function l(a,b){b||(b={});this.type="default";this.status="status"in b?b.status:200;this.ok=200<=this.status&&300>this.status;this.statusText="statusText"in b?b.statusText:"OK";this.headers=new e(b.headers);this.url=b.url||"";this._initBody(a)}if(!g.fetch){var m=
+g.Array,u=g.Error,q=g.Map,G=g.RangeError,h=g.TypeError,r;if(r="FileReader"in g&&"Blob"in g)try{new Blob,r=!0}catch(a){r=!1}var k={searchParams:"URLSearchParams"in g,blob:r,formData:"FormData"in g,arrayBuffer:"ArrayBuffer"in g};if(k.arrayBuffer){var H="[object Int8Array];[object Uint8Array];[object Uint8ClampedArray];[object Int16Array];[object Uint16Array];[object Int32Array];[object Uint32Array];[object Float32Array];[object Float64Array]".split(";");var B=function(a){return a&&DataView.prototype.isPrototypeOf(a)};
+var C=ArrayBuffer.isView||function(a){return a&&-1<H.indexOf(Object.prototype.toString.call(a))}}e.prototype.append=function(a,b){if(2!==arguments.length)throw h("Invalid parameters to append");a=p(a);b=v(b);this.map.has(a)?this.map.set(a,this.map.get(a)+", "+b):this.map.set(a,b)};e.prototype["delete"]=function(a){if(1!==arguments.length)throw h("Invalid parameters to delete");this.map.delete(p(a))};e.prototype.get=function(a){if(1!==arguments.length)throw h("Invalid parameters to get");a=p(a);var b=
+this.map.get(a);return void 0!==b?b:null};e.prototype.has=function(a){if(1!==arguments.length)throw h("Invalid parameters to has");return this.map.has(p(a))};e.prototype.set=function(a,b){if(2!==arguments.length)throw h("Invalid parameters to set");this.map.set(p(a),v(b))};e.prototype.forEach=function(a,b){var d=this;m.from(this.map.entries()).sort().forEach(function(c){a.call(b,c[1],c[0],d)})};e.prototype.keys=function(){return(new q(m.from(this.map.entries()).sort())).keys()};e.prototype.values=
+function(){return(new q(m.from(this.map.entries()).sort())).values()};e.prototype.entries=function(){return(new q(m.from(this.map.entries()).sort())).entries()};e.prototype[Symbol.iterator]=e.prototype.entries;var E="DELETE GET HEAD OPTIONS POST PUT".split(" ");n.prototype.clone=function(){return new n(this,{body:this._bodyInit})};y.call(n.prototype);y.call(l.prototype);l.prototype.clone=function(){return new l(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new e(this.headers),
+url:this.url})};l.error=function(){var a=new l(null,{status:0,statusText:""});a.type="error";return a};var I=[301,302,303,307,308];l.redirect=function(a,b){if(-1===I.indexOf(b))throw new G("Invalid status code");return new l(null,{status:b,headers:{location:a}})};g.Headers=e;g.Request=n;g.Response=l;g.fetch=function(a,b){return new Promise(function(d,c){var e=new n(a,b),f=new XMLHttpRequest;f.onload=function(){var a={status:f.status,statusText:f.statusText,headers:F(f.getAllResponseHeaders()||"")};
+a.url="responseURL"in f?f.responseURL:a.headers.get("X-Request-URL");d(new l("response"in f?f.response:f.responseText,a))};f.onerror=function(){c(new h("Network request failed"))};f.ontimeout=function(){c(new h("Network request failed"))};f.open(e.method,e.url,!0);"include"===e.credentials&&(f.withCredentials=!0);"responseType"in f&&k.blob&&(f.responseType="blob");e.headers.forEach(function(a,b){f.setRequestHeader(b,a)});f.send("undefined"===typeof e._bodyInit?null:e._bodyInit)})};g.fetch.polyfill=
+!0}})(this);
\ No newline at end of file
diff --git a/src/cobalt/fetch/fetch.js b/src/cobalt/fetch/fetch.js
new file mode 100644
index 0000000..b01d35f
--- /dev/null
+++ b/src/cobalt/fetch/fetch.js
@@ -0,0 +1,537 @@
+// ==ClosureCompiler==
+// @output_file_name fetch.js
+// @compilation_level SIMPLE_OPTIMIZATIONS
+// @language_out ES5_STRICT
+// ==/ClosureCompiler==
+
+// Copyright (c) 2014-2016 GitHub, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// Contact GitHub API Training Shop Blog About
+
+// Fetch API: https://fetch.spec.whatwg.org/
+
+(function(self) {
+  'use strict';
+
+  if (self.fetch) {
+    return
+  }
+
+  var Array = self.Array;
+  var Error = self.Error;
+  var Map = self.Map;
+  var RangeError = self.RangeError;
+  var TypeError = self.TypeError;
+
+  var err_InvalidHeadersInit = 'Constructing Headers with invalid parameters'
+
+  var support = {
+    searchParams: 'URLSearchParams' in self,
+    blob: 'FileReader' in self && 'Blob' in self && (function() {
+      try {
+        new Blob()
+        return true
+      } catch(e) {
+        return false
+      }
+    })(),
+    formData: 'FormData' in self,
+    arrayBuffer: 'ArrayBuffer' in self
+  }
+
+  if (support.arrayBuffer) {
+    var viewClasses = [
+      '[object Int8Array]',
+      '[object Uint8Array]',
+      '[object Uint8ClampedArray]',
+      '[object Int16Array]',
+      '[object Uint16Array]',
+      '[object Int32Array]',
+      '[object Uint32Array]',
+      '[object Float32Array]',
+      '[object Float64Array]'
+    ]
+
+    var isDataView = function(obj) {
+      return obj && DataView.prototype.isPrototypeOf(obj)
+    }
+
+    var isArrayBufferView = ArrayBuffer.isView || function(obj) {
+      return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
+    }
+  }
+
+  function normalizeName(name) {
+    if (typeof name !== 'string') {
+      name = String(name)
+    }
+    if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
+      throw new TypeError('Invalid character in header field name')
+    }
+    return name.toLowerCase()
+  }
+
+  function normalizeValue(value) {
+    if (typeof value !== 'string') {
+      value = String(value)
+    }
+
+    // https://fetch.spec.whatwg.org/#concept-header-value
+    // The web platform tests don't quite abide by the current spec. Use a
+    // permissive approach that passes the tests while following the spirit
+    // of the spec. Essentially, leading & trailing HTTP whitespace bytes
+    // are trimmed first before checking validity.
+    var c, first, last, i
+
+    //value = value.replace(/^[ \t\n\r]+|[ \t\n\r]+$/g, '')
+    for (first = 0; first < value.length; first++) {
+      c = value.charCodeAt(first)
+      if (c !== 9 && c !== 10 && c !== 13 && c !== 32) {
+        break
+      }
+    }
+    for (last = value.length - 1; last > first; last--) {
+      c = value.charCodeAt(last)
+      if (c !== 9 && c !== 10 && c !== 13 && c !== 32) {
+        break
+      }
+    }
+    value = value.substring(first, last + 1)
+
+    // Follow the chromium implementation of IsValidHTTPHeaderValue(). This
+    // should be updated once the web platform test abides by the fetch spec.
+    for (i = 0; i < value.length; i++) {
+      c = value.charCodeAt(i)
+      if (c >= 256 || c === 0 || c === 10 || c === 13) {
+        throw new TypeError('Invalid character in header field value')
+      }
+    }
+    return value
+  }
+
+  function Headers(headers) {
+    this.map = new Map();
+
+    if (headers === undefined) {
+      return
+    } else if (headers === null || typeof headers !== 'object') {
+      throw new TypeError(err_InvalidHeadersInit)
+    } else if (headers instanceof Headers) {
+      // Should use for..of in case |headers| has a custom Symbol.iterator.
+      // However, this results in the ClosureCompiler polyfilling Symbol.
+      headers.forEach(function(value, name) {
+        this.append(name, value)
+      }, this)
+    } else if (Array.isArray(headers)) {
+      headers.forEach(function(header) {
+        if (header.length !== 2) {
+          throw new TypeError(err_InvalidHeadersInit)
+        }
+        this.append(header[0], header[1])
+      }, this)
+    } else {
+      Object.getOwnPropertyNames(headers).forEach(function(name) {
+        this.append(name, headers[name])
+      }, this)
+    }
+  }
+
+  Headers.prototype.append = function(name, value) {
+    if (arguments.length !== 2) {
+      throw TypeError('Invalid parameters to append')
+    }
+    name = normalizeName(name)
+    value = normalizeValue(value)
+    if (this.map.has(name)) {
+      this.map.set(name, this.map.get(name) + ', ' + value)
+    } else {
+      this.map.set(name, value)
+    }
+  }
+
+  Headers.prototype['delete'] = function(name) {
+    if (arguments.length !== 1) {
+      throw TypeError('Invalid parameters to delete')
+    }
+    this.map.delete(normalizeName(name))
+  }
+
+  Headers.prototype.get = function(name) {
+    if (arguments.length !== 1) {
+      throw TypeError('Invalid parameters to get')
+    }
+    name = normalizeName(name)
+    var value = this.map.get(name)
+    return value !== undefined ? value : null
+  }
+
+  Headers.prototype.has = function(name) {
+    if (arguments.length !== 1) {
+      throw TypeError('Invalid parameters to has')
+    }
+    return this.map.has(normalizeName(name))
+  }
+
+  Headers.prototype.set = function(name, value) {
+    if (arguments.length !== 2) {
+      throw TypeError('Invalid parameters to set')
+    }
+    this.map.set(normalizeName(name), normalizeValue(value))
+  }
+
+  Headers.prototype.forEach = function(callback, thisArg) {
+    var sorted_array = Array.from(this.map.entries()).sort()
+    var that = this
+    sorted_array.forEach(function(value) {
+      callback.call(thisArg, value[1], value[0], that)
+    })
+  }
+
+  Headers.prototype.keys = function() {
+    var sorted_map = new Map(Array.from(this.map.entries()).sort())
+    return sorted_map.keys()
+  }
+
+  Headers.prototype.values = function() {
+    var sorted_map = new Map(Array.from(this.map.entries()).sort())
+    return sorted_map.values()
+  }
+
+  Headers.prototype.entries = function() {
+    var sorted_map = new Map(Array.from(this.map.entries()).sort())
+    return sorted_map.entries()
+  }
+
+  Headers.prototype[Symbol.iterator] = Headers.prototype.entries
+
+  function consumed(body) {
+    if (body.bodyUsed) {
+      return Promise.reject(new TypeError('Already read'))
+    }
+    body.bodyUsed = true
+  }
+
+  function fileReaderReady(reader) {
+    return new Promise(function(resolve, reject) {
+      reader.onload = function() {
+        resolve(reader.result)
+      }
+      reader.onerror = function() {
+        reject(reader.error)
+      }
+    })
+  }
+
+  function readBlobAsArrayBuffer(blob) {
+    var reader = new FileReader()
+    var promise = fileReaderReady(reader)
+    reader.readAsArrayBuffer(blob)
+    return promise
+  }
+
+  function readBlobAsText(blob) {
+    var reader = new FileReader()
+    var promise = fileReaderReady(reader)
+    reader.readAsText(blob)
+    return promise
+  }
+
+  function readArrayBufferAsText(buf) {
+    var view = new Uint8Array(buf)
+    var chars = new Array(view.length)
+
+    for (var i = 0; i < view.length; i++) {
+      chars[i] = String.fromCharCode(view[i])
+    }
+    return chars.join('')
+  }
+
+  function bufferClone(buf) {
+    if (buf.slice) {
+      return buf.slice(0)
+    } else {
+      var view = new Uint8Array(buf.byteLength)
+      view.set(new Uint8Array(buf))
+      return view.buffer
+    }
+  }
+
+  function Body() {
+    this.bodyUsed = false
+
+    this._initBody = function(body) {
+      this._bodyInit = body
+      if (!body) {
+        this._bodyText = ''
+      } else if (typeof body === 'string') {
+        this._bodyText = body
+      } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
+        this._bodyBlob = body
+      } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
+        this._bodyFormData = body
+      } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
+        this._bodyText = body.toString()
+      } else if (support.arrayBuffer && support.blob && isDataView(body)) {
+        this._bodyArrayBuffer = bufferClone(body.buffer)
+        // IE 10-11 can't handle a DataView body.
+        this._bodyInit = new Blob([this._bodyArrayBuffer])
+      } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
+        this._bodyArrayBuffer = bufferClone(body)
+      } else {
+        throw new Error('unsupported BodyInit type')
+      }
+
+      if (!this.headers.get('content-type')) {
+        if (typeof body === 'string') {
+          this.headers.set('content-type', 'text/plain;charset=UTF-8')
+        } else if (this._bodyBlob && this._bodyBlob.type) {
+          this.headers.set('content-type', this._bodyBlob.type)
+        } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
+          this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
+        }
+      }
+    }
+
+    if (support.blob) {
+      this.blob = function() {
+        var rejected = consumed(this)
+        if (rejected) {
+          return rejected
+        }
+
+        if (this._bodyBlob) {
+          return Promise.resolve(this._bodyBlob)
+        } else if (this._bodyArrayBuffer) {
+          return Promise.resolve(new Blob([this._bodyArrayBuffer]))
+        } else if (this._bodyFormData) {
+          throw new Error('could not read FormData body as blob')
+        } else {
+          return Promise.resolve(new Blob([this._bodyText]))
+        }
+      }
+
+      this.arrayBuffer = function() {
+        if (this._bodyArrayBuffer) {
+          return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
+        } else {
+          return this.blob().then(readBlobAsArrayBuffer)
+        }
+      }
+    }
+
+    this.text = function() {
+      var rejected = consumed(this)
+      if (rejected) {
+        return rejected
+      }
+
+      if (this._bodyBlob) {
+        return readBlobAsText(this._bodyBlob)
+      } else if (this._bodyArrayBuffer) {
+        return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
+      } else if (this._bodyFormData) {
+        throw new Error('could not read FormData body as text')
+      } else {
+        return Promise.resolve(this._bodyText)
+      }
+    }
+
+    if (support.formData) {
+      this.formData = function() {
+        return this.text().then(decode)
+      }
+    }
+
+    this.json = function() {
+      return this.text().then(JSON.parse)
+    }
+
+    return this
+  }
+
+  // HTTP methods whose capitalization should be normalized
+  var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
+
+  function normalizeMethod(method) {
+    var upcased = method.toUpperCase()
+    return (methods.indexOf(upcased) > -1) ? upcased : method
+  }
+
+  function Request(input, options) {
+    options = options || {}
+    var body = options.body
+
+    if (input instanceof Request) {
+      if (input.bodyUsed) {
+        throw new TypeError('Already read')
+      }
+      this.url = input.url
+      this.credentials = input.credentials
+      if (!options.headers) {
+        this.headers = new Headers(input.headers)
+      }
+      this.method = input.method
+      this.mode = input.mode
+      if (!body && input._bodyInit != null) {
+        body = input._bodyInit
+        input.bodyUsed = true
+      }
+    } else {
+      this.url = String(input)
+    }
+
+    this.credentials = options.credentials || this.credentials || 'omit'
+    if (options.headers || !this.headers) {
+      this.headers = new Headers(options.headers)
+    }
+    this.method = normalizeMethod(options.method || this.method || 'GET')
+    this.mode = options.mode || this.mode || null
+    this.referrer = null
+
+    if ((this.method === 'GET' || this.method === 'HEAD') && body) {
+      throw new TypeError('Body not allowed for GET or HEAD requests')
+    }
+    this._initBody(body)
+  }
+
+  Request.prototype.clone = function() {
+    return new Request(this, { body: this._bodyInit })
+  }
+
+  function decode(body) {
+    var form = new FormData()
+    body.trim().split('&').forEach(function(bytes) {
+      if (bytes) {
+        var split = bytes.split('=')
+        var name = split.shift().replace(/\+/g, ' ')
+        var value = split.join('=').replace(/\+/g, ' ')
+        form.append(decodeURIComponent(name), decodeURIComponent(value))
+      }
+    })
+    return form
+  }
+
+  function parseHeaders(rawHeaders) {
+    var headers = new Headers()
+    // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
+    // https://tools.ietf.org/html/rfc7230#section-3.2
+    var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ')
+    preProcessedHeaders.split(/\r?\n/).forEach(function(line) {
+      var parts = line.split(':')
+      var key = parts.shift().trim()
+      if (key) {
+        var value = parts.join(':').trim()
+        headers.append(key, value)
+      }
+    })
+    return headers
+  }
+
+  Body.call(Request.prototype)
+
+  function Response(bodyInit, options) {
+    if (!options) {
+      options = {}
+    }
+
+    this.type = 'default'
+    this.status = 'status' in options ? options.status : 200
+    this.ok = this.status >= 200 && this.status < 300
+    this.statusText = 'statusText' in options ? options.statusText : 'OK'
+    this.headers = new Headers(options.headers)
+    this.url = options.url || ''
+    this._initBody(bodyInit)
+  }
+
+  Body.call(Response.prototype)
+
+  Response.prototype.clone = function() {
+    return new Response(this._bodyInit, {
+      status: this.status,
+      statusText: this.statusText,
+      headers: new Headers(this.headers),
+      url: this.url
+    })
+  }
+
+  Response.error = function() {
+    var response = new Response(null, {status: 0, statusText: ''})
+    response.type = 'error'
+    return response
+  }
+
+  var redirectStatuses = [301, 302, 303, 307, 308]
+
+  Response.redirect = function(url, status) {
+    if (redirectStatuses.indexOf(status) === -1) {
+      throw new RangeError('Invalid status code')
+    }
+
+    return new Response(null, {status: status, headers: {location: url}})
+  }
+
+  self.Headers = Headers
+  self.Request = Request
+  self.Response = Response
+
+  self.fetch = function(input, init) {
+    return new Promise(function(resolve, reject) {
+      var request = new Request(input, init)
+      var xhr = new XMLHttpRequest()
+
+      xhr.onload = function() {
+        var options = {
+          status: xhr.status,
+          statusText: xhr.statusText,
+          headers: parseHeaders(xhr.getAllResponseHeaders() || '')
+        }
+        options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
+        var body = 'response' in xhr ? xhr.response : xhr.responseText
+        resolve(new Response(body, options))
+      }
+
+      xhr.onerror = function() {
+        reject(new TypeError('Network request failed'))
+      }
+
+      xhr.ontimeout = function() {
+        reject(new TypeError('Network request failed'))
+      }
+
+      xhr.open(request.method, request.url, true)
+
+      if (request.credentials === 'include') {
+        xhr.withCredentials = true
+      }
+
+      if ('responseType' in xhr && support.blob) {
+        xhr.responseType = 'blob'
+      }
+
+      request.headers.forEach(function(value, name) {
+        xhr.setRequestHeader(name, value)
+      })
+
+      xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
+    })
+  }
+  self.fetch.polyfill = true
+})(this);
diff --git a/src/cobalt/math/clamp.h b/src/cobalt/math/clamp.h
new file mode 100644
index 0000000..94d706e
--- /dev/null
+++ b/src/cobalt/math/clamp.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_MATH_CLAMP_H_
+#define COBALT_MATH_CLAMP_H_
+
+#include <algorithm>
+
+namespace cobalt {
+namespace math {
+
+template <typename T>
+T Clamp(const T& input, const T& minimum, const T& maximum) {
+  return std::max<T>(minimum, std::min<T>(maximum, input));
+}
+
+}  // namespace math.
+}  // namespace cobalt.
+
+#endif  // COBALT_MATH_CLAMP_H_
diff --git a/src/cobalt/math/linear_interpolator.h b/src/cobalt/math/linear_interpolator.h
index 728f70f..a1de492 100644
--- a/src/cobalt/math/linear_interpolator.h
+++ b/src/cobalt/math/linear_interpolator.h
@@ -17,6 +17,7 @@
 #ifndef COBALT_MATH_LINEAR_INTERPOLATOR_H_
 #define COBALT_MATH_LINEAR_INTERPOLATOR_H_
 
+#include <iterator>
 #include <utility>
 #include <vector>
 
@@ -41,7 +42,7 @@
 //
 // Discontinuous values:
 //  This table supports discontinuous values. To enable this feature, insert a
-//  pair of duplicate keys, each with a different value. See example below. 
+//  pair of duplicate keys, each with a different value. See example below.
 //
 // Example (continuous):
 //  LinearInterpolator<float, float> interp;
diff --git a/src/cobalt/math/math.gyp b/src/cobalt/math/math.gyp
index f457fdd..a281754 100644
--- a/src/cobalt/math/math.gyp
+++ b/src/cobalt/math/math.gyp
@@ -11,6 +11,7 @@
       'sources': [
         'box_f.cc',
         'box_f.h',
+        'clamp.h',
         'cubic_bezier.cc',
         'cubic_bezier.h',
         'insets.cc',
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc
index e4ce5be..4723e68 100644
--- a/src/cobalt/media/base/starboard_player.cc
+++ b/src/cobalt/media/base/starboard_player.cc
@@ -292,6 +292,10 @@
     return;
   }
 
+  if (seek_pending_) {
+    return;
+  }
+
 #if SB_API_VERSION < 4
   SbPlayerSetPause(player_, playback_rate == 0.0);
 #else   // SB_API_VERSION < 4
diff --git a/src/cobalt/media/base/video_codecs.cc b/src/cobalt/media/base/video_codecs.cc
index 89a9264..a82e041 100644
--- a/src/cobalt/media/base/video_codecs.cc
+++ b/src/cobalt/media/base/video_codecs.cc
@@ -290,7 +290,10 @@
   uint8_t level = 0;
   if (ParseAVCCodecId(codec_id, &profile, &level)) return kCodecH264;
   if (codec_id == "vp8" || codec_id == "vp8.0") return kCodecVP8;
-  if (codec_id == "vp9" || codec_id == "vp9.0") return kCodecVP9;
+  if (codec_id == "vp9" || codec_id == "vp9.0" || codec_id == "vp9.1" ||
+      codec_id == "vp9.2") {
+    return kCodecVP9;
+  }
   if (codec_id == "theora") return kCodecTheora;
   if (ParseHEVCCodecId(codec_id, &profile, &level)) return kCodecHEVC;
 
diff --git a/src/cobalt/media/decoder_buffer_allocator.cc b/src/cobalt/media/decoder_buffer_allocator.cc
index 70858e5..bd53da4 100644
--- a/src/cobalt/media/decoder_buffer_allocator.cc
+++ b/src/cobalt/media/decoder_buffer_allocator.cc
@@ -14,6 +14,7 @@
 
 #include "cobalt/media/decoder_buffer_allocator.h"
 
+#include "nb/memory_scope.h"
 #include "starboard/common/scoped_ptr.h"
 #include "starboard/configuration.h"
 #include "starboard/memory.h"
@@ -26,6 +27,7 @@
 }  // namespace
 
 DecoderBufferAllocator::DecoderBufferAllocator() : memory_block_(NULL) {
+  TRACK_MEMORY_SCOPE("Media");
   if (COBALT_MEDIA_BUFFER_INITIAL_CAPACITY > 0) {
     memory_block_ = SbMemoryAllocateAligned(
         DecoderBuffer::kAlignmentSize, COBALT_MEDIA_BUFFER_INITIAL_CAPACITY);
@@ -52,6 +54,7 @@
 
 void* DecoderBufferAllocator::Allocate(Type type, size_t size,
                                        size_t alignment) {
+  TRACK_MEMORY_SCOPE("Media");
   UNREFERENCED_PARAMETER(type);
   if (memory_pool_.is_valid()) {
     return memory_pool_->Allocate(size, alignment);
diff --git a/src/cobalt/media/filters/shell_demuxer.cc b/src/cobalt/media/filters/shell_demuxer.cc
index 5f9e0b8..9909244 100644
--- a/src/cobalt/media/filters/shell_demuxer.cc
+++ b/src/cobalt/media/filters/shell_demuxer.cc
@@ -517,14 +517,15 @@
     return;
   }
   // if both streams had finished downloading, we need to restart the request
-  if (audio_reached_eos_ && video_reached_eos_) {
-    DLOG(INFO) << "restarting stopped request loop";
-    Request(DemuxerStream::AUDIO);
-  }
+  bool issue_new_request = audio_reached_eos_ && video_reached_eos_;
   audio_reached_eos_ = false;
   video_reached_eos_ = false;
   flushing_ = true;
   cb.Run(PIPELINE_OK);
+  if (issue_new_request) {
+    DLOG(INFO) << "restarting stopped request loop";
+    Request(DemuxerStream::AUDIO);
+  }
 }
 
 DemuxerStream* ShellDemuxer::GetStream(media::DemuxerStream::Type type) {
diff --git a/src/cobalt/media/player/web_media_player.h b/src/cobalt/media/player/web_media_player.h
index f81d2ad..94e372d 100644
--- a/src/cobalt/media/player/web_media_player.h
+++ b/src/cobalt/media/player/web_media_player.h
@@ -208,7 +208,7 @@
   // the preferred output mode is not supported, the player will fallback to
   // one that is.  This can be used to indicate that, say, for spherical video
   // playback, we would like a decode-to-texture output mode.
-  virtual bool PreferDecodeToTexture() const { return false; }
+  virtual bool PreferDecodeToTexture() { return false; }
   // Notifies the client that a video is encrypted. Client is supposed to call
   // |WebMediaPlayer::SetDrmSystem| as soon as possible to avoid stalling
   // playback.
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc
index 9741314..d145b6a 100644
--- a/src/cobalt/media/player/web_media_player_impl.cc
+++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -127,7 +127,8 @@
       drm_system_(NULL) {
   TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::WebMediaPlayerImpl");
 
-  DCHECK(!s_instance);
+  DLOG_IF(ERROR, s_instance)
+      << "More than one WebMediaPlayerImpl has been created.";
   s_instance = this;
 
   DCHECK(buffer_allocator_);
@@ -151,7 +152,8 @@
 
   DCHECK(!main_loop_ || main_loop_ == MessageLoop::current());
 
-  DCHECK_EQ(s_instance, this);
+  DLOG_IF(ERROR, s_instance != this)
+      << "More than one WebMediaPlayerImpl has been created.";
   s_instance = NULL;
 
   if (delegate_) {
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.cc b/src/cobalt/renderer/backend/egl/graphics_context.cc
index 1211584..c7708af 100644
--- a/src/cobalt/renderer/backend/egl/graphics_context.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_context.cc
@@ -501,16 +501,9 @@
 }
 
 void GraphicsContextEGL::SecurityClear() {
-#if defined(COBALT_SECURITY_SCREEN_CLEAR_TO_UGLY_COLOR)
-  // Clear the screen to a color that is bright and gross to exaggerate that
-  // this is a problem if it is witnessed.
-  GL_CALL(glClearColor(1.0f, 0.4f, 1.0f, 1.0f));
-#else
-  // In release builds we certainly still want to perform this security
-  // clear, but should a poor user actually encounter it, we don't need
-  // to shock them with an ugly pink color.
-  GL_CALL(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
-#endif  // defined(COBALT_SECURITY_SCREEN_CLEAR_TO_UGLY_COLOR)
+  // Explicitly clear the screen to transparent to ensure that data from a
+  // previous use of the surface is not visible.
+  GL_CALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
   GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
 }
 
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_rrect.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_rrect.glsl
index 411e72a..7fc1677 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_rrect.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_rrect.glsl
@@ -2,6 +2,7 @@
 precision mediump float;

 uniform vec4 uinnerRect_Stage1;

 uniform float uRTHeight;

+uniform vec2 uscale_Stage1;

 uniform vec2 uinvRadiiXY_Stage1;

 varying vec4 vColor;

 varying vec2 vEllipseOffsets_Stage0;

@@ -27,11 +28,13 @@
 		vec2 dxy0 = uinnerRect_Stage1.xy - fragCoordYDown.xy;

 		vec2 dxy1 = fragCoordYDown.xy - uinnerRect_Stage1.zw;

 		vec2 dxy = max(max(dxy0, dxy1), 0.0);

+		dxy *= uscale_Stage1.y;

 		vec2 Z = dxy * uinvRadiiXY_Stage1;

 		float implicit = dot(Z, dxy) - 1.0;

 		float grad_dot = 4.0 * dot(Z, Z);

 		grad_dot = max(grad_dot, 1.0e-4);

 		float approx_dist = implicit * inversesqrt(grad_dot);

+		approx_dist *= uscale_Stage1.x;

 		float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);

 		output_Stage1 = (output_Stage0 * alpha);

 	}

diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture.glsl
index b35a8f4..2f78d28 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture.glsl
@@ -1,6 +1,7 @@
 #version 100

 precision mediump float;

 uniform sampler2D uSampler0_Stage0;

+uniform vec2 uscale_Stage1;

 uniform vec4 uellipse_Stage1;

 uniform float uRTHeight;

 varying vec4 vColor;

@@ -20,11 +21,13 @@
   {

     // Stage 1: Ellipse

     vec2 d = fragCoordYDown.xy - uellipse_Stage1.xy;

+    d *= uscale_Stage1.y;

     vec2 Z = d * uellipse_Stage1.zw;

     float implicit = dot(Z, d) - 1.0;

     float grad_dot = 4.0 * dot(Z, Z);

     grad_dot = max(grad_dot, 1.0e-4);

     float approx_dist = implicit * inversesqrt(grad_dot);

+    approx_dist *= uscale_Stage1.x;

     float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);

     output_Stage1 = (output_Stage0 * alpha);

   }

diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture_domain.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture_domain.glsl
index d8be84d..6279c47 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture_domain.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture_domain.glsl
@@ -2,6 +2,7 @@
 precision mediump float;

 uniform sampler2D uSampler0_Stage0;

 uniform vec4 uTexDom_Stage0;

+uniform vec2 uscale_Stage1;

 uniform vec4 uellipse_Stage1;

 uniform float uRTHeight;

 varying vec4 vColor;

@@ -22,11 +23,13 @@
   {

     // Stage 1: Ellipse

     vec2 d = fragCoordYDown.xy - uellipse_Stage1.xy;

+    d *= uscale_Stage1.y;

     vec2 Z = d * uellipse_Stage1.zw;

     float implicit = dot(Z, d) - 1.0;

     float grad_dot = 4.0 * dot(Z, Z);

     grad_dot = max(grad_dot, 1.0e-4);

     float approx_dist = implicit * inversesqrt(grad_dot);

+    approx_dist *= uscale_Stage1.x;

     float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);

     output_Stage1 = (output_Stage0 * alpha);

   }

diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture_negative.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture_negative.glsl
index 0c57707..d65609f 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture_negative.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_masked_texture_negative.glsl
@@ -1,6 +1,7 @@
 #version 100

 precision mediump float;

 uniform sampler2D uSampler0_Stage0;

+uniform vec2 uscale_Stage1;

 uniform vec4 uellipse_Stage1;

 uniform float uRTHeight;

 varying vec4 vColor;

@@ -20,11 +21,13 @@
   {

     // Stage 1: Ellipse

     vec2 d = fragCoordYDown.xy - uellipse_Stage1.xy;

+    d *= uscale_Stage1.y;

     vec2 Z = d * uellipse_Stage1.zw;

     float implicit = dot(Z, d) - 1.0;

     float grad_dot = 4.0 * dot(Z, Z);

     grad_dot = max(grad_dot, 1.0e-4);

     float approx_dist = implicit * inversesqrt(grad_dot);

+    approx_dist *= uscale_Stage1.x;

     float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);

     output_Stage1 = (output_Stage0 * alpha);

   }

diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_outside_masked_ellipse.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_outside_masked_ellipse.glsl
index 3b86ee8..034729d 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_outside_masked_ellipse.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_outside_masked_ellipse.glsl
@@ -1,6 +1,7 @@
 #version 100

 #extension GL_OES_standard_derivatives: require

 precision mediump float;

+uniform vec2 uscale_Stage1;

 uniform vec4 uellipse_Stage1;

 uniform float uRTHeight;

 varying vec4 vColor;

@@ -34,11 +35,13 @@
 	{

 		// Stage 1: Ellipse

 		vec2 d = fragCoordYDown.xy - uellipse_Stage1.xy;

+		d *= uscale_Stage1.y;

 		vec2 Z = d * uellipse_Stage1.zw;

 		float implicit = dot(Z, d) - 1.0;

 		float grad_dot = 4.0 * dot(Z, Z);

 		grad_dot = max(grad_dot, 1.0e-4);

 		float approx_dist = implicit * inversesqrt(grad_dot);

+		approx_dist *= uscale_Stage1.x;

 		float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);

 		output_Stage1 = (output_Stage0 * alpha);

 	}

diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_ring_masked_color.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_ring_masked_color.glsl
index 6616121..740a6ee 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_ring_masked_color.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_ellipse_ring_masked_color.glsl
@@ -1,7 +1,9 @@
 #version 100

 precision mediump float;

+uniform vec2 uscale_Stage1;

 uniform vec4 uellipse_Stage1;

 uniform float uRTHeight;

+uniform vec2 uscale_Stage2;

 uniform vec4 uellipse_Stage2;

 varying vec4 vColor;

 varying vec2 vEllipseOffsets_Stage0;

@@ -25,11 +27,13 @@
 	{

 		// Stage 1: Ellipse

 		vec2 d = fragCoordYDown.xy - uellipse_Stage1.xy;

+		d *= uscale_Stage1.y;

 		vec2 Z = d * uellipse_Stage1.zw;

 		float implicit = dot(Z, d) - 1.0;

 		float grad_dot = 4.0 * dot(Z, Z);

 		grad_dot = max(grad_dot, 1.0e-4);

 		float approx_dist = implicit * inversesqrt(grad_dot);

+		approx_dist *= uscale_Stage1.x;

 		float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);

 		output_Stage1 = (output_Stage0 * alpha);

 	}

@@ -37,11 +41,13 @@
 	{

 		// Stage 2: Ellipse

 		vec2 d = fragCoordYDown.xy - uellipse_Stage2.xy;

+		d *= uscale_Stage2.y;

 		vec2 Z = d * uellipse_Stage2.zw;

 		float implicit = dot(Z, d) - 1.0;

 		float grad_dot = 4.0 * dot(Z, Z);

 		grad_dot = max(grad_dot, 1.0e-4);

 		float approx_dist = implicit * inversesqrt(grad_dot);

+		approx_dist *= uscale_Stage2.x;

 		float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);

 		output_Stage2 = (output_Stage1 * alpha);

 	}

diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rect_edge_masked_ellipse.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rect_edge_masked_ellipse.glsl
index 054570a..0b82ab9 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rect_edge_masked_ellipse.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rect_edge_masked_ellipse.glsl
@@ -4,6 +4,7 @@
 uniform float uRTHeight;

 uniform vec4 urect_Stage1;

 uniform vec4 uinnerRect_Stage2;

+uniform vec2 uscale_Stage2;

 uniform vec2 uinvRadiiXY_Stage2;

 varying vec4 vColor;

 void main() 

@@ -38,11 +39,13 @@
 		vec2 dxy0 = uinnerRect_Stage2.xy - fragCoordYDown.xy;

 		vec2 dxy1 = fragCoordYDown.xy - uinnerRect_Stage2.zw;

 		vec2 dxy = max(max(dxy0, dxy1), 0.0);

+		dxy *= uscale_Stage2.y;

 		vec2 Z = dxy * uinvRadiiXY_Stage2;

 		float implicit = dot(Z, dxy) - 1.0;

 		float grad_dot = 4.0 * dot(Z, Z);

 		grad_dot = max(grad_dot, 1.0e-4);

 		float approx_dist = implicit * inversesqrt(grad_dot);

+		approx_dist *= uscale_Stage2.x;

 		float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);

 		output_Stage2 = (output_Stage1 * alpha);

 	}

diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_masked_texture.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_masked_texture.glsl
index 2a2574d..13b93f2 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_masked_texture.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_masked_texture.glsl
@@ -3,6 +3,7 @@
 uniform sampler2D uSampler0_Stage0;

 uniform vec4 uinnerRect_Stage1;

 uniform float uRTHeight;

+uniform vec2 uscale_Stage1;

 uniform vec2 uinvRadiiXY_Stage1;

 varying vec4 vColor;

 varying vec2 vMatrixCoord_Stage0;

@@ -20,11 +21,13 @@
 		vec2 dxy0 = uinnerRect_Stage1.xy - fragCoordYDown.xy;

 		vec2 dxy1 = fragCoordYDown.xy - uinnerRect_Stage1.zw;

 		vec2 dxy = max(max(dxy0, dxy1), 0.0);

+		dxy *= uscale_Stage1.y;

 		vec2 Z = dxy * uinvRadiiXY_Stage1;

 		float implicit = dot(Z, dxy) - 1.0;

 		float grad_dot = 4.0 * dot(Z, Z);

 		grad_dot = max(grad_dot, 1.0e-4);

 		float approx_dist = implicit * inversesqrt(grad_dot);

+		approx_dist *= uscale_Stage1.x;

 		float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);

 		output_Stage1 = (output_Stage0 * alpha);

 	}

diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_masked_texture_negative.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_masked_texture_negative.glsl
index b2f1111..90d5a4d 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_masked_texture_negative.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_masked_texture_negative.glsl
@@ -3,6 +3,7 @@
 uniform sampler2D uSampler0_Stage0;

 uniform vec4 uinnerRect_Stage1;

 uniform float uRTHeight;

+uniform vec2 uscale_Stage1;

 uniform vec2 uinvRadiiXY_Stage1;

 varying vec4 vColor;

 varying vec2 vMatrixCoord_Stage0;

@@ -20,11 +21,13 @@
 		vec2 dxy0 = uinnerRect_Stage1.xy - fragCoordYDown.xy;

 		vec2 dxy1 = fragCoordYDown.xy - uinnerRect_Stage1.zw;

 		vec2 dxy = max(max(dxy0, dxy1), 0.0);

+		dxy *= uscale_Stage1.y;

 		vec2 Z = dxy * uinvRadiiXY_Stage1;

 		float implicit = dot(Z, dxy) - 1.0;

 		float grad_dot = 4.0 * dot(Z, Z);

 		grad_dot = max(grad_dot, 1.0e-4);

 		float approx_dist = implicit * inversesqrt(grad_dot);

+		approx_dist *= uscale_Stage1.x;

 		float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);

 		output_Stage1 = (output_Stage0 * alpha);

 	}

diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_ring_masked_ellipse_edge.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_ring_masked_ellipse_edge.glsl
index 97428cf..cd21c5e 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_ring_masked_ellipse_edge.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_rrect_ring_masked_ellipse_edge.glsl
@@ -2,8 +2,10 @@
 precision mediump float;

 uniform vec4 uinnerRect_Stage1;

 uniform float uRTHeight;

+uniform vec2 uscale_Stage1;

 uniform vec2 uinvRadiiXY_Stage1;

 uniform vec4 uinnerRect_Stage2;

+uniform vec2 uscale_Stage2;

 uniform vec2 uinvRadiiXY_Stage2;

 varying vec4 vColor;

 varying vec2 vEllipseOffsets_Stage0;

@@ -29,11 +31,13 @@
 		vec2 dxy0 = uinnerRect_Stage1.xy - fragCoordYDown.xy;

 		vec2 dxy1 = fragCoordYDown.xy - uinnerRect_Stage1.zw;

 		vec2 dxy = max(max(dxy0, dxy1), 0.0);

+		dxy *= uscale_Stage1.y;

 		vec2 Z = dxy * uinvRadiiXY_Stage1;

 		float implicit = dot(Z, dxy) - 1.0;

 		float grad_dot = 4.0 * dot(Z, Z);

 		grad_dot = max(grad_dot, 1.0e-4);

 		float approx_dist = implicit * inversesqrt(grad_dot);

+		approx_dist *= uscale_Stage1.x;

 		float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);

 		output_Stage1 = (output_Stage0 * alpha);

 	}

@@ -43,11 +47,13 @@
 		vec2 dxy0 = uinnerRect_Stage2.xy - fragCoordYDown.xy;

 		vec2 dxy1 = fragCoordYDown.xy - uinnerRect_Stage2.zw;

 		vec2 dxy = max(max(dxy0, dxy1), 0.0);

+		dxy *= uscale_Stage2.y;

 		vec2 Z = dxy * uinvRadiiXY_Stage2;

 		float implicit = dot(Z, dxy) - 1.0;

 		float grad_dot = 4.0 * dot(Z, Z);

 		grad_dot = max(grad_dot, 1.0e-4);

 		float approx_dist = implicit * inversesqrt(grad_dot);

+		approx_dist *= uscale_Stage2.x;

 		float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);

 		output_Stage2 = (output_Stage1 * alpha);

 	}

diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
index 2ed5599..cdd0f00 100644
--- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
@@ -270,14 +270,19 @@
       render_target_blitter->GetSbRenderTarget();
   CHECK(SbBlitterSetRenderTarget(context, visitor_render_target));
 
-  BoundsStack start_bounds(context_->GetSbBlitterContext(),
-                           math::Rect(render_target_blitter->GetSize()));
+  math::Size size(render_target_blitter->GetSize());
+  BoundsStack start_bounds(context, math::Rect(size));
 
   RenderState initial_render_state(visitor_render_target, Transform(),
                                    start_bounds);
 
+  CHECK(SbBlitterSetBlending(context, false));
+  CHECK(SbBlitterSetColor(context, SbBlitterColorFromRGBA(0, 0, 0, 0)));
+  CHECK(SbBlitterFillRect(
+      context, SbBlitterMakeRect(0, 0, size.width(), size.height())));
+
   RenderTreeNodeVisitor visitor(
-      context_->GetSbBlitterDevice(), context_->GetSbBlitterContext(),
+      context_->GetSbBlitterDevice(), context,
       initial_render_state, NULL, NULL, NULL, NULL, NULL);
   render_tree->Accept(&visitor);
 
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc
index 16b0c2a..cc16d83 100644
--- a/src/cobalt/renderer/rasterizer/pixel_test.cc
+++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -1740,6 +1740,18 @@
       new ImageNode(image)));
 }
 
+TEST_F(PixelTest, LargeEllipticalViewportOverImage) {
+  // This image has rounded corners that are just large enough to result in
+  // older skia implementations using uniform values that overflow 16-bit float
+  // exponents.
+  scoped_refptr<Image> image =
+      CreateColoredCheckersImage(GetResourceProvider(), math::Size(300, 100));
+
+  TestTree(new FilterNode(
+      ViewportFilter(RectF(0, 0, 300, 100), RoundedCorners(150, 50)),
+      new ImageNode(image)));
+}
+
 TEST_F(PixelTest, EllipticalViewportOverWrappingImage) {
   scoped_refptr<Image> image =
       CreateColoredCheckersImage(GetResourceProvider(), output_surface_size());
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
index b90a09a..1fe1492 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
@@ -520,6 +520,8 @@
       CreateSkiaRenderTargetSurface(skia_render_target);
   SkCanvas* canvas = sk_output_surface->getCanvas();
 
+  canvas->clear(SkColorSetARGB(0, 0, 0, 0));
+
   // Render to the canvas and clean up.
   RasterizeRenderTreeToCanvas(render_tree, canvas);
   canvas->flush();
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkAtomics_cobalt.h b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkAtomics_cobalt.h
index 9464ed3..de8c187 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkAtomics_cobalt.h
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkAtomics_cobalt.h
@@ -18,7 +18,9 @@
 #include "base/atomicops.h"
 #include "cobalt/renderer/rasterizer/skia/skia/src/ports/atomic_type_conversions.h"
 
-#if defined(ARCH_CPU_64_BITS) || defined(__LB_XB360__)
+#if defined(STARBOARD)
+/* Don't undefine MemoryBarrier */
+#elif defined(ARCH_CPU_64_BITS) || defined(__LB_XB360__)
 // windows.h #defines this (only on x64). This causes problems because the
 // public API also uses MemoryBarrier at the public name for this fence.
 #undef MemoryBarrier
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkBarriers_cobalt.h b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkBarriers_cobalt.h
index acdd630..00b666f 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkBarriers_cobalt.h
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkBarriers_cobalt.h
@@ -18,7 +18,9 @@
 #include "base/atomicops.h"
 #include "cobalt/renderer/rasterizer/skia/skia/src/ports/atomic_type_conversions.h"
 
-#if defined(ARCH_CPU_64_BITS) || defined(__LB_XB360__) || defined(__LB_XB1__)
+#if defined(STARBOARD)
+/* Don't undefine MemoryBarrier */
+#elif defined(ARCH_CPU_64_BITS) || defined(__LB_XB360__) || defined(__LB_XB1__)
 // windows.h #defines this (only on x64). This causes problems because the
 // public API also uses MemoryBarrier at the public name for this fence.
 #undef MemoryBarrier
diff --git a/src/cobalt/renderer/rasterizer/testdata/LargeEllipticalViewportOverImage-expected.png b/src/cobalt/renderer/rasterizer/testdata/LargeEllipticalViewportOverImage-expected.png
new file mode 100644
index 0000000..f15606a
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/LargeEllipticalViewportOverImage-expected.png
Binary files differ
diff --git a/src/cobalt/script/mozjs-45/mozjs-45.gyp b/src/cobalt/script/mozjs-45/mozjs-45.gyp
index 2a38204..c26b64e 100644
--- a/src/cobalt/script/mozjs-45/mozjs-45.gyp
+++ b/src/cobalt/script/mozjs-45/mozjs-45.gyp
@@ -89,10 +89,11 @@
         'output_path': '<(SHARED_INTERMEDIATE_DIR)/cobalt/script/mozjs-45/embedded_resources.h',
       },
       'sources': [
-        '<(DEPTH)/third_party/promise-polyfill/promise.min.js',
+        '<(DEPTH)/cobalt/fetch/embedded_scripts/fetch.js',
         '<(DEPTH)/cobalt/streams/embedded_scripts/byte_length_queuing_strategy.js',
         '<(DEPTH)/cobalt/streams/embedded_scripts/count_queuing_strategy.js',
         '<(DEPTH)/cobalt/streams/embedded_scripts/readable_stream.js',
+        '<(DEPTH)/third_party/promise-polyfill/promise.min.js',
       ],
       'actions': [
         {
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
index 32cf999..ba7b7eb 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
@@ -378,6 +378,10 @@
       MozjsEmbeddedResources::readable_stream_js,
       sizeof(MozjsEmbeddedResources::readable_stream_js),
       "readable_stream.js");
+  EvaluateEmbeddedScript(
+      MozjsEmbeddedResources::fetch_js,
+      sizeof(MozjsEmbeddedResources::fetch_js),
+      "fetch.js");
 }
 
 InterfaceData* MozjsGlobalEnvironment::GetInterfaceData(intptr_t key) {
diff --git a/src/cobalt/script/mozjs-45/proxy_handler.cc b/src/cobalt/script/mozjs-45/proxy_handler.cc
index 6e0cbb2..5794038 100644
--- a/src/cobalt/script/mozjs-45/proxy_handler.cc
+++ b/src/cobalt/script/mozjs-45/proxy_handler.cc
@@ -92,7 +92,8 @@
 bool ProxyHandler::delete_(JSContext* context, JS::HandleObject proxy,
                            JS::HandleId id, JS::ObjectOpResult& result) const {
   // https://www.w3.org/TR/WebIDL/#delete
-  if (supports_named_properties() || supports_indexed_properties()) {
+  if (!JSID_IS_SYMBOL(id) &&
+      (supports_named_properties() || supports_indexed_properties())) {
     // Convert the id to a JSValue, so we can easily convert it to Uint32 and
     // JSString.
     JS::RootedValue id_value(context);
@@ -163,7 +164,8 @@
 bool ProxyHandler::LegacyPlatformObjectGetOwnPropertyDescriptor(
     JSContext* context, JS::HandleObject proxy, JS::HandleId id,
     JS::MutableHandle<JSPropertyDescriptor> descriptor) const {
-  if (supports_named_properties() || supports_indexed_properties()) {
+  if (!JSID_IS_SYMBOL(id) &&
+      (supports_named_properties() || supports_indexed_properties())) {
     // Convert the id to a JSValue, so we can easily convert it to Uint32 and
     // JSString.
     JS::RootedValue id_value(context);
@@ -221,6 +223,9 @@
                                             uint32_t* out_index) const {
   // https://www.w3.org/TR/WebIDL/#dfn-array-index-property-name
   // 1. Let i be ToUint32(P).
+  if (property_value.isSymbol()) {
+    return false;
+  }
   uint32_t index;
   if (!JS::ToUint32(context, property_value, &index)) {
     return false;
diff --git a/src/cobalt/websocket/buffered_amount_tracker.cc b/src/cobalt/websocket/buffered_amount_tracker.cc
index 708efc0..b02cab2 100644
--- a/src/cobalt/websocket/buffered_amount_tracker.cc
+++ b/src/cobalt/websocket/buffered_amount_tracker.cc
@@ -28,6 +28,10 @@
     Entry& entry(entries_[0]);
 
     std::size_t potential_payload_delta = 0;
+
+    // Cache this variable in case we do a |pop_front|.
+    const bool is_user_payload = entry.is_user_payload_;
+
     if (entry.message_size_ > size_left_pop) {
       potential_payload_delta = size_left_pop;
       entry.message_size_ -= size_left_pop;
@@ -36,7 +40,7 @@
       entries_.pop_front();
     }
 
-    if (entry.is_user_payload_) {
+    if (is_user_payload) {
       payload_amount += potential_payload_delta;
     }
 
diff --git a/src/media/base/starboard_player.cc b/src/media/base/starboard_player.cc
index f8a838e..07799db 100644
--- a/src/media/base/starboard_player.cc
+++ b/src/media/base/starboard_player.cc
@@ -14,6 +14,12 @@
 
 #include "media/base/starboard_player.h"
 
+#error This implementation of StarboardPlayer is deprecated and will be removed
+#error in the next release.  You should upgrade to Starboard version 4 and
+#error Cobalt 9 to use the StarboardPlayer implementation in cobalt/media.
+#error Please contact us *immediately* if the upcoming removal of this file
+#error will break your port.
+
 #include <algorithm>
 
 #include "base/bind.h"
@@ -229,6 +235,11 @@
   DCHECK(SbPlayerIsValid(player_));
 
   playback_rate_ = playback_rate;
+
+  if (seek_pending_) {
+    return;
+  }
+
 #if SB_API_VERSION < 4
   SbPlayerSetPause(player_, playback_rate == 0.0);
 #else   // SB_API_VERSION < 4
diff --git a/src/media/player/web_media_player.h b/src/media/player/web_media_player.h
index 26a2742..6ab6c02 100644
--- a/src/media/player/web_media_player.h
+++ b/src/media/player/web_media_player.h
@@ -244,7 +244,7 @@
   // the preferred output mode is not supported, the player will fallback to
   // one that is.  This can be used to indicate that, say, for spherical video
   // playback, we would like a decode-to-texture output mode.
-  virtual bool PreferDecodeToTexture() const { return false; }
+  virtual bool PreferDecodeToTexture() { return false; }
   // TODO: Make the EME related functions pure virtual again once
   // we have proper EME implementation. Currently empty implementation are
   // provided to make media temporarily work.
diff --git a/src/media/player/web_media_player_impl.cc b/src/media/player/web_media_player_impl.cc
index d6d920d..f22efba 100644
--- a/src/media/player/web_media_player_impl.cc
+++ b/src/media/player/web_media_player_impl.cc
@@ -139,7 +139,8 @@
       is_local_source_(false),
       supports_save_(true),
       suppress_destruction_errors_(false) {
-  DCHECK(!s_instance);
+  DLOG_IF(ERROR, s_instance)
+      << "More than one WebMediaPlayerImpl has been created.";
   s_instance = this;
 
   media_log_->AddEvent(
@@ -186,7 +187,8 @@
 WebMediaPlayerImpl::~WebMediaPlayerImpl() {
   DCHECK(!main_loop_ || main_loop_ == MessageLoop::current());
 
-  DCHECK_EQ(s_instance, this);
+  DLOG_IF(ERROR, s_instance != this)
+      << "More than one WebMediaPlayerImpl has been created.";
   s_instance = NULL;
 
   if (delegate_) {
diff --git a/src/starboard/client_porting/walk_dir.py b/src/starboard/client_porting/walk_dir.py
new file mode 100644
index 0000000..1ebc6f3
--- /dev/null
+++ b/src/starboard/client_porting/walk_dir.py
@@ -0,0 +1,310 @@
+#
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""A directory walker framework that filter and process files.
+
+It filters file name against filter functions and process filtered files using
+processor function.
+"""
+
+import os
+
+# All filter functions
+
+
+def CppSourceCodeFilter(filename):
+  """Filter function returns true for C++ source code files."""
+  return (filename[-3:] == '.cc' or filename[-4:] == '.cpp' or
+          filename[-2:] == '.h' or filename[-4:] == '.hpp')
+
+
+def SourceCodeFilter(filename):
+  """Filter function returns true for general source code files."""
+  return (filename[-3:] == '.cc' or filename[-4:] == '.cpp' or
+          filename[-2:] == '.h' or filename[-4:] == '.hpp' or
+          filename[-4:] == '.idl' or filename[-11:] == '.h.template' or
+          filename[-12:] == '.cc.template' or filename[-2:] == '.y' or
+          filename[-7:] == '.h.pump' or filename[-3:] == '.js')
+
+
+# All processor functions
+
+
+def AddInvalidSpace(pathname):
+  """Add a space in the very beginning of the file."""
+  with open(pathname, 'r') as f:
+    content = f.read()
+  content = ' ' + content
+  with open(pathname, 'w') as f:
+    f.write(content)
+
+
+def ReplaceLicenseHeader(pathname):
+  """Replace license headers in /* ... */ to // ...."""
+  with open(pathname, 'r') as f:
+    lines = f.readlines()
+  # Guestimate the copyright header
+  for i in range(0, len(lines)):
+    if (len(lines[i]) == 3 and lines[i][:2] == '/*' and
+        lines[i + 1].find('opyright') != -1 and
+        lines[i + 1].find('Google') != -1):
+      del lines[i]
+      for j in range(i, len(lines)):
+        if lines[j].find('*/') != -1:
+          del lines[j]
+          break
+
+        if lines[j][0] == ' ':
+          line_without_star = lines[j][2:]
+        else:
+          line_without_star = lines[j][1:]
+        lines[j] = '//' + line_without_star
+    if i >= len(lines) - 1:
+      break
+  with open(pathname, 'w') as f:
+    f.writelines(lines)
+
+
+def ReplaceMediaNamespace(pathname):
+  """Move namespace media into namespace cobalt."""
+  with open(pathname, 'r') as f:
+    source_lines = f.readlines()
+  target_lines = []
+  for i in range(0, len(source_lines)):
+    if source_lines[i].find('namespace media {') != -1:
+      if i == 0 or source_lines[i - 1].find('namespace cobalt {') == -1:
+        target_lines.append('namespace cobalt {\n')
+    target_lines.append(source_lines[i])
+    if source_lines[i].find('}  // namespace media') != -1:
+      if i == len(source_lines) - 1 or source_lines[i + 1].find(
+          '}  // namespace cobalt') == -1:
+        target_lines.append('}  // namespace cobalt\n')
+
+  with open(pathname, 'w') as f:
+    f.writelines(target_lines)
+
+
+C_FUNCTION_LIST = """
+assert,isalnum,isalpha,iscntrl,isdigit,isgraph,islower,isprint,ispunct,isspace,
+isupper,isxdigit,toupper,tolower,errno,setlocale,acos,asin,atan,atan2,ceil,cos,
+cosh,exp,fabs,floor,fmod,frexp,ldexp,log,log10,modf,pow,sin,sinh,sqrt,tan,tanh,
+setjmp,longjmp,signal,raise,va_start,va_arg,va_end,clearerr,fclose,feof,fflush,
+fgetc,fgetpos,fgets,fopen,fprintf,fputc,fputs,fread,freopen,fscanf,fseek,
+fsetpos,ftell,fwrite,getc,getchar,gets,perror,printf,putchar,puts,remove,rewind,
+scanf,setbuf,setvbuf,sprintf,sscanf,tmpfile,tmpnam,ungetc,vfprintf,vprintf,
+vsprintf,abort,abs,atexit,atof,atoi,atol,bsearch,calloc,div,exit,getenv,free,
+labs,ldiv,malloc,mblen,mbstowcs,mbtowc,qsort,rand,realloc,strtod,strtol,strtoul,
+srand,system,wctomb,wcstombs,memchr,memcmp,memcpy,memmove,memset,strcat,strchr,
+strcmp,strcoll,strcpy,strcspn,strerror,strlen,strncat,strncmp,strncpy,strpbrk,
+strrchr,strspn,strstr,strtok,strxfrm,asctime,clock,ctime,difftime,gmtime,
+localtime,mktime,strftime,time,opendir,closedir,readdir,rewinddir,scandir,
+seekdir,telldir,access,alarm,chdir,chown,close,chroot,ctermid,cuserid,dup,dup2,
+execl,execle,execlp,execv,execve,execvp,fchdir,fork,fpathconf,getegid,geteuid,
+gethostname,getopt,getgid,getgroups,getlogin,getpgrp,getpid,getppid,getuid,
+isatty,link,lseek,mkdir,open,pathconf,pause,pipe,read,rename,rmdir,setgid,
+setpgid,setsid,setuid,sleep,sysconf,tcgetpgrp,tcsetpgrp,ttyname,unlink,write,
+clrscr,getch,getche,statfs,endpwent,fgetpwent,getpw,getpwent,getpwnam,getpwuid,
+getuidx,putpwent,pclose,popen,putenv,setenv,setpwent,setreuid,stat,uname,
+unsetenv,setuidx,setegid,setrgid,seteuid,setruid,getruid
+"""
+
+SB_CHARACTER_REPLACEMENT_DICT = {
+    'isdigit': 'SbCharacterIsDigit',
+    'isspace': 'SbCharacterIsSpace',
+}
+
+SB_MEMORY_REPLACEMENT_DICT = {
+    'free': 'SbMemoryFree',
+    'malloc': 'SbMemoryAllocate',
+    'memchr': 'SbMemoryFindByte',
+    'memcmp': 'SbMemoryCompare',
+    'memcpy': 'SbMemoryCopy',
+    'memmove': 'SbMemoryMove',
+    'memset': 'SbMemorySet',
+    'realloc': 'SbMemoryReallocate'
+}
+
+SB_STRING_REPLACEMENT_DICT = {
+    'atoi': 'SbStringAToI',
+    'strcpy': 'SbStringCopyUnsafe',
+    'strlen': 'SbStringGetLength',
+    'strncpy': 'SbStringCopy',
+}
+
+c_function_list = []
+
+
+def AddProjectHeader(lines, header):
+  """Add a new project header into lines which takes order into account."""
+  assert header.find('.h') != -1 and header.find('/') != -1
+
+  include_statement = '#include "' + header + '"\n'
+
+  last_c_header = -1
+  last_cpp_header = -1
+  last_project_header = -1
+
+  for i in range(0, len(lines)):
+    line = lines[i]
+    if line.find('#include <') != -1:
+      if line.find('.h') != -1:
+        last_c_header = i
+      else:
+        last_cpp_header = i
+    elif line.find('#include "') != -1:
+      if line.find(header) != -1:
+        return
+      last_project_header = i
+
+  if (last_project_header < last_cpp_header or
+      last_project_header < last_c_header):
+    # There is no project header at all, add after last cpp or c header
+    if last_cpp_header != -1:
+      lines.insert(last_cpp_header + 1, include_statement)
+      lines.insert(last_cpp_header + 1, '\n')
+    else:
+      # In the case that there is no C header as well, this will be added to the
+      # first line, maybe before the copyrights, and hopefully will be caught
+      # during code review.
+      lines.insert(last_c_header + 1, include_statement)
+      lines.insert(last_c_header + 1, '\n')
+    return
+
+  # Now we have to add into the project include section with proper ordering
+  while last_project_header > 0:
+    if include_statement > lines[last_project_header]:
+      lines.insert(last_project_header + 1, include_statement)
+      return
+    last_project_header -= 1
+
+  lines.insert(0, include_statement)
+
+
+def RemoveHeader(lines, header):
+  for i in range(0, len(lines)):
+    if lines[i].find('#include') != -1 and lines[i].find(header) != -1:
+      del lines[i]
+      if (lines[i] == '\n' and lines[i + 1] == '\n' or
+          lines[i - 1] == '\n' and lines[i] == '\n'):
+        del lines[i]
+      return
+
+
+def DumpCHeadersAndFunctions(pathname):
+  """Print out C headers included and C functions used."""
+  global c_function_list
+  if not c_function_list:
+    c_function_list = [
+        x for x in C_FUNCTION_LIST.replace('\n', '').split(',') if x
+    ]
+  with open(pathname, 'r') as f:
+    source_lines = f.readlines()
+  first = True
+
+  add_starboard_character_h = False
+  add_starboard_memory_h = False
+  add_starboard_string_h = False
+  add_starboard_types_h = False
+
+  for i in range(0, len(source_lines)):
+    if source_lines[i].find('#include <') != -1 and source_lines[i].find(
+        '.h>') != -1:
+      if source_lines[i].find('stddef.h') or source_lines[i].find('stdint.h'):
+        add_starboard_types_h = True
+        continue  # We can fix this, no need to dump
+
+      if first:
+        print pathname
+        first = False
+      print '    => line ', i + 1, '\t', source_lines[i][:-1]
+    for j in range(0, len(c_function_list)):
+      index = source_lines[i].find(c_function_list[j] + '(')
+      if index == -1:
+        continue
+      if (source_lines[i].find('//') != -1 and
+          source_lines[i].find('//') < index):
+        continue
+      if index == 0 or (not source_lines[i][index - 1].isalpha() and
+                        source_lines[i][index - 1] != '_' and
+                        source_lines[i][index - 1] != ':' and
+                        source_lines[i][index - 1] != '>' and
+                        source_lines[i][index - 1] != '.'):
+        if c_function_list[j] in SB_CHARACTER_REPLACEMENT_DICT:
+          source_lines[i] = source_lines[i].replace(
+              c_function_list[j],
+              SB_CHARACTER_REPLACEMENT_DICT[c_function_list[j]])
+          add_starboard_character_h = True
+          continue  # We fixed this, no need to dump
+        if c_function_list[j] in SB_MEMORY_REPLACEMENT_DICT:
+          source_lines[i] = source_lines[i].replace(
+              c_function_list[j],
+              SB_MEMORY_REPLACEMENT_DICT[c_function_list[j]])
+          add_starboard_memory_h = True
+          continue  # We fixed this, no need to dump
+        if c_function_list[j] in SB_STRING_REPLACEMENT_DICT:
+          source_lines[i] = source_lines[i].replace(
+              c_function_list[j],
+              SB_STRING_REPLACEMENT_DICT[c_function_list[j]])
+          add_starboard_string_h = True
+          continue  # We fixed this, no need to dump
+        if first:
+          print pathname
+          first = False
+        print '    => line ', i + 1, '\t', source_lines[
+            i][:-1], 'contains', c_function_list[j]
+
+  if add_starboard_character_h:
+    AddProjectHeader(source_lines, 'starboard/character.h')
+
+  if add_starboard_memory_h:
+    AddProjectHeader(source_lines, 'starboard/memory.h')
+
+  if add_starboard_string_h:
+    AddProjectHeader(source_lines, 'starboard/string.h')
+
+  if add_starboard_types_h:
+    RemoveHeader(source_lines, 'stddef.h')
+    RemoveHeader(source_lines, 'stdint.h')
+    AddProjectHeader(source_lines, 'starboard/types.h')
+
+  with open(pathname, 'w') as f:
+    f.writelines(source_lines)
+
+
+def CollectFilesInDirectory(root, file_filter=None):
+  """Traverse the folder and call filters."""
+  result = []
+  for current_dir, _, files in os.walk(root):
+    for f in files:
+      pathname = current_dir + '/' + f
+      if file_filter and not file_filter(pathname):
+        continue
+      result.append(pathname)
+  return result
+
+
+def ProcessFiles(pathnames, processor):
+  for pathname in pathnames:
+    processor(pathname)
+
+
+# ProcessFiles(CollectFilesInDirectory('.', CppSourceCodeFilter),
+#                                      AddInvalidSpace)
+# ProcessFiles(CollectFilesInDirectory('.', SourceCodeFilter),
+#                                      ReplaceLicenseHeader)
+# ProcessFiles(CollectFilesInDirectory('.', SourceCodeFilter),
+#                                      ReplaceMediaNamespace)
+ProcessFiles(
+    CollectFilesInDirectory('.', CppSourceCodeFilter), DumpCHeadersAndFunctions)
diff --git a/src/starboard/common/flat_map.h b/src/starboard/common/flat_map.h
index 2e04d60..a232b24 100644
--- a/src/starboard/common/flat_map.h
+++ b/src/starboard/common/flat_map.h
@@ -154,7 +154,9 @@
 
     vector_.erase(new_end, vector_.end());
 
-    return std::distance(vector_.begin() + partition_idx, new_end);
+    // partition_idx was the previous size of the vector_.
+    const size_t num_elements_added = vector_.size() - partition_idx;
+    return num_elements_added;
   }
 
   std::pair<iterator, bool> insert(const value_type& entry) {
diff --git a/src/starboard/egl_and_gles/egl_and_gles_angle.gyp b/src/starboard/egl_and_gles/egl_and_gles_angle.gyp
index 2bcc9b2..8812c25 100644
--- a/src/starboard/egl_and_gles/egl_and_gles_angle.gyp
+++ b/src/starboard/egl_and_gles/egl_and_gles_angle.gyp
@@ -19,8 +19,8 @@
       'type': 'none',
 
       'dependencies': [
-        '<(DEPTH)/third_party/angle/src/build_angle.gyp:libEGL',
-        '<(DEPTH)/third_party/angle/src/build_angle.gyp:libGLESv2',
+        '<(DEPTH)/third_party/angle/angle.gyp:libEGL',
+        '<(DEPTH)/third_party/angle/angle.gyp:libGLESv2',
       ],
       'direct_dependent_settings': {
         'include_dirs': [
diff --git a/src/starboard/linux/shared/compiler_flags.gypi b/src/starboard/linux/shared/compiler_flags.gypi
index 931779b..762dfa7 100644
--- a/src/starboard/linux/shared/compiler_flags.gypi
+++ b/src/starboard/linux/shared/compiler_flags.gypi
@@ -69,6 +69,11 @@
           '-Wno-unnamed-type-template-args',
           # Triggered by the COMPILE_ASSERT macro.
           '-Wno-unused-local-typedef',
+          # Do not warn if a function or variable cannot be implicitly
+          # instantiated.
+          '-Wno-undefined-var-template',
+          # Do not warn about an implicit exception spec mismatch.
+          '-Wno-implicit-exception-spec-mismatch',
         ],
       }],
       ['cobalt_fastbuild==0', {
@@ -126,6 +131,7 @@
           '-Wno-shift-negative-value',
           # Width of bit-field exceeds width of its type- value will be truncated
           '-Wno-bitfield-width',
+          '-Wno-undefined-var-template',
         ],
       }],
       ['use_asan==1', {
diff --git a/src/starboard/linux/x64directfb/gyp_configuration.gypi b/src/starboard/linux/x64directfb/gyp_configuration.gypi
index 1fbc03e..98b7048 100644
--- a/src/starboard/linux/x64directfb/gyp_configuration.gypi
+++ b/src/starboard/linux/x64directfb/gyp_configuration.gypi
@@ -27,8 +27,8 @@
 
     # This should have a default value in cobalt/base.gypi. See the comment
     # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs',
-    'cobalt_enable_jit': 1,
+    'javascript_engine': 'mozjs-45',
+    'cobalt_enable_jit': 0,
   },
 
   'target_defaults': {
diff --git a/src/starboard/linux/x64x11/clang/3.3/compiler_flags.gypi b/src/starboard/linux/x64x11/clang/3.3/compiler_flags.gypi
index b11221f..a6629b0 100644
--- a/src/starboard/linux/x64x11/clang/3.3/compiler_flags.gypi
+++ b/src/starboard/linux/x64x11/clang/3.3/compiler_flags.gypi
@@ -106,10 +106,6 @@
       '-std=c99',
     ],
     'cflags_cc': [
-      # Limit to gnu++98. This allows Linux to be a canary build for any
-      # C++11 features that are not supported on some platforms' compilers.
-      # We do allow ourselves GNU extensions, which are assumed to exist
-      # by Chromium code.
       '-std=gnu++98',
     ],
     'target_conditions': [
diff --git a/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.gypi b/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.gypi
index df35330..05d38d0 100644
--- a/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.gypi
@@ -13,6 +13,12 @@
 # limitations under the License.
 
 {
+  'variables': {
+    # This should have a default value in cobalt/base.gypi. See the comment
+    # there for acceptable values for this variable.
+    'javascript_engine': 'mozjs',
+    'cobalt_enable_jit': 1,
+  },
   'target_defaults': {
     'default_configuration': 'linux-x64x11-clang-3-3_debug',
     'configurations': {
diff --git a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.gypi b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.gypi
index 4b85d62..f1961e0 100644
--- a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.gypi
@@ -14,6 +14,10 @@
 
 {
   'variables': {
+    # This should have a default value in cobalt/base.gypi. See the comment
+    # there for acceptable values for this variable.
+    'javascript_engine': 'mozjs-45',
+    'cobalt_enable_jit': 0,
     'linker_flags!': [
             '-Wl,--wrap=malloc',
             '-Wl,--wrap=free',
diff --git a/src/starboard/linux/x64x11/clang/gyp_configuration.gypi b/src/starboard/linux/x64x11/clang/gyp_configuration.gypi
index 0df5d5f..2ede477 100644
--- a/src/starboard/linux/x64x11/clang/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/clang/gyp_configuration.gypi
@@ -13,12 +13,6 @@
 # limitations under the License.
 
 {
-  'variables': {
-    # This should have a default value in cobalt/base.gypi. See the comment
-    # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs',
-    'cobalt_enable_jit': 1,
-  },
   'includes': [
     '../libraries.gypi',
     '../../shared/gyp_configuration.gypi',
diff --git a/src/starboard/linux/x64x11/cpp11/compiler_flags.gypi b/src/starboard/linux/x64x11/cpp11/compiler_flags.gypi
index 3bd32d7..a59e9c6 100644
--- a/src/starboard/linux/x64x11/cpp11/compiler_flags.gypi
+++ b/src/starboard/linux/x64x11/cpp11/compiler_flags.gypi
@@ -128,6 +128,8 @@
           '-Wno-shift-negative-value',
           # Width of bit-field exceeds width of its type- value will be truncated
           '-Wno-bitfield-width',
+          # Do not warn if a function or variable cannot be implicitly
+          # instantiated.
           '-Wno-undefined-var-template',
         ],
       }],
diff --git a/src/starboard/linux/x64x11/gcc/4.2/compiler_flags.gypi b/src/starboard/linux/x64x11/gcc/4.2/compiler_flags.gypi
index 7870304..cbc3aeb 100644
--- a/src/starboard/linux/x64x11/gcc/4.2/compiler_flags.gypi
+++ b/src/starboard/linux/x64x11/gcc/4.2/compiler_flags.gypi
@@ -93,10 +93,6 @@
       '-std=c99',
     ],
     'cflags_cc': [
-      # Limit to gnu++98. This allows Linux to be a canary build for any
-      # C++11 features that are not supported on some platforms' compilers.
-      # We do allow ourselves GNU extensions, which are assumed to exist
-      # by Chromium code.
       '-std=gnu++98',
       # Don't warn for invalid access to non-static data member of NULL object.
       '-Wno-invalid-offsetof',
diff --git a/src/starboard/linux/x64x11/gcc/4.2/gyp_configuration.gypi b/src/starboard/linux/x64x11/gcc/4.2/gyp_configuration.gypi
index f5c5ee5..b8a22da 100644
--- a/src/starboard/linux/x64x11/gcc/4.2/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/gcc/4.2/gyp_configuration.gypi
@@ -13,6 +13,12 @@
 # limitations under the License.
 
 {
+  'variables': {
+    # This should have a default value in cobalt/base.gypi. See the comment
+    # there for acceptable values for this variable.
+    'javascript_engine': 'mozjs',
+    'cobalt_enable_jit': 1,
+  },
   'target_defaults': {
     'default_configuration': 'linux-x64x11-gcc-4-2_debug',
     'configurations': {
diff --git a/src/starboard/linux/x64x11/gcc/4.4/compiler_flags.gypi b/src/starboard/linux/x64x11/gcc/4.4/compiler_flags.gypi
index 9fc908e..7af753c 100644
--- a/src/starboard/linux/x64x11/gcc/4.4/compiler_flags.gypi
+++ b/src/starboard/linux/x64x11/gcc/4.4/compiler_flags.gypi
@@ -89,10 +89,6 @@
       '-std=c99',
     ],
     'cflags_cc': [
-      # Limit to gnu++98. This allows Linux to be a canary build for any
-      # C++11 features that are not supported on some platforms' compilers.
-      # We do allow ourselves GNU extensions, which are assumed to exist
-      # by Chromium code.
       '-std=gnu++98',
       # Don't warn for invalid access to non-static data member of NULL object.
       '-Wno-invalid-offsetof',
diff --git a/src/starboard/linux/x64x11/gcc/4.4/gyp_configuration.gypi b/src/starboard/linux/x64x11/gcc/4.4/gyp_configuration.gypi
index 5749404..322ade0 100644
--- a/src/starboard/linux/x64x11/gcc/4.4/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/gcc/4.4/gyp_configuration.gypi
@@ -13,6 +13,12 @@
 # limitations under the License.
 
 {
+  'variables': {
+    # This should have a default value in cobalt/base.gypi. See the comment
+    # there for acceptable values for this variable.
+    'javascript_engine': 'mozjs',
+    'cobalt_enable_jit': 1,
+  },
   'target_defaults': {
     'default_configuration': 'linux-x64x11-gcc-4-4_debug',
     'configurations': {
diff --git a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.gypi b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.gypi
index dc9ec62..e781887 100644
--- a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.gypi
@@ -13,6 +13,12 @@
 # limitations under the License.
 
 {
+  'variables': {
+    # This should have a default value in cobalt/base.gypi. See the comment
+    # there for acceptable values for this variable.
+    'javascript_engine': 'mozjs-45',
+    'cobalt_enable_jit': 0,
+  },
   'target_defaults': {
     'default_configuration': 'linux-x64x11-gcc-6-3_debug',
     'configurations': {
diff --git a/src/starboard/linux/x64x11/gcc/gyp_configuration.gypi b/src/starboard/linux/x64x11/gcc/gyp_configuration.gypi
index 0df5d5f..6fe92c5 100644
--- a/src/starboard/linux/x64x11/gcc/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/gcc/gyp_configuration.gypi
@@ -14,10 +14,7 @@
 
 {
   'variables': {
-    # This should have a default value in cobalt/base.gypi. See the comment
-    # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs',
-    'cobalt_enable_jit': 1,
+
   },
   'includes': [
     '../libraries.gypi',
diff --git a/src/starboard/linux/x64x11/gyp_configuration.gypi b/src/starboard/linux/x64x11/gyp_configuration.gypi
index 1203c9d..948e2b7 100644
--- a/src/starboard/linux/x64x11/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/gyp_configuration.gypi
@@ -16,8 +16,8 @@
   'variables': {
     # This should have a default value in cobalt/base.gypi. See the comment
     # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs',
-    'cobalt_enable_jit': 1,
+    'javascript_engine': 'mozjs-45',
+    'cobalt_enable_jit': 0,
   },
   'target_defaults': {
     'default_configuration': 'linux-x64x11_debug',
diff --git a/src/starboard/nplb/cryptography_helpers.cc b/src/starboard/nplb/cryptography_helpers.cc
new file mode 100644
index 0000000..ccdba66
--- /dev/null
+++ b/src/starboard/nplb/cryptography_helpers.cc
@@ -0,0 +1,145 @@
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ==================================================================== */
+
+// Modifications Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/nplb/cryptography_helpers.h"
+
+#include <string>
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/log.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+
+namespace {
+int FromHex(uint8_t* out, char in) {
+  if (in >= '0' && in <= '9') {
+    *out = in - '0';
+    return 1;
+  }
+  if (in >= 'a' && in <= 'f') {
+    *out = in - 'a' + 10;
+    return 1;
+  }
+  if (in >= 'A' && in <= 'F') {
+    *out = in - 'A' + 10;
+    return 1;
+  }
+
+  return 0;
+}
+}  // namespace
+
+void DecodeHex(scoped_array<uint8_t>* out,
+               int* out_len,
+               const char* in,
+               int test_num,
+               const char* description) {
+  if (in == NULL) {
+    out->reset();
+    *out_len = 0;
+    return;
+  }
+
+  size_t len = SbStringGetLength(in);
+  if (len & 1) {
+    ADD_FAILURE() << description << ": Odd length.";
+    return;
+  }
+
+  scoped_array<uint8_t> buf(new uint8_t[len / 2]);
+  if (!buf) {
+    ADD_FAILURE() << description << ": Memory fail.";
+    return;
+  }
+
+  for (size_t i = 0; i < len; i += 2) {
+    uint8_t v, v2;
+    bool result = FromHex(&v, in[i]) && FromHex(&v2, in[i + 1]);
+    if (!result) {
+      ADD_FAILURE() << description << ": Invalid character at " << i << ".";
+      continue;
+    }
+
+    buf[i / 2] = (v << 4) | v2;
+  }
+
+  *out = buf.Pass();
+  *out_len = static_cast<int>(len / 2);
+}
+
+std::string HexDump(const void* in, int len) {
+  const uint8_t* data = reinterpret_cast<const uint8_t*>(in);
+
+  std::string result;
+  for (size_t i = 0; i < len; i++) {
+    char hex[3] = {0};
+    SbStringFormatF(hex, 3, "%02x", data[i]);
+    result += hex;
+  }
+
+  return result;
+}
+
+}  // namespace nplb
+}  // namespace starboard
diff --git a/src/starboard/nplb/cryptography_helpers.h b/src/starboard/nplb/cryptography_helpers.h
new file mode 100644
index 0000000..fdadcd5
--- /dev/null
+++ b/src/starboard/nplb/cryptography_helpers.h
@@ -0,0 +1,85 @@
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ==================================================================== */
+
+// Modifications Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_NPLB_CRYPTOGRAPHY_HELPERS_H_
+#define STARBOARD_NPLB_CRYPTOGRAPHY_HELPERS_H_
+
+#include <string>
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/log.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+
+void DecodeHex(scoped_array<uint8_t>* out,
+               int* out_len,
+               const char* in,
+               int test_num,
+               const char* description);
+std::string HexDump(const void* in, int len);
+
+}  // namespace nplb
+}  // namespace starboard
+
+#endif  // STARBOARD_NPLB_CRYPTOGRAPHY_HELPERS_H_
diff --git a/src/starboard/nplb/cryptography_transform_gcm_test.cc b/src/starboard/nplb/cryptography_transform_gcm_test.cc
index d2674a4..6f42daa 100644
--- a/src/starboard/nplb/cryptography_transform_gcm_test.cc
+++ b/src/starboard/nplb/cryptography_transform_gcm_test.cc
@@ -66,6 +66,7 @@
 
 #include "starboard/common/scoped_ptr.h"
 #include "starboard/log.h"
+#include "starboard/nplb/cryptography_helpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -108,34 +109,43 @@
   },
   {
     "feffe9928665731c6d6a8f9467308308",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
     NULL,
     "cafebabefacedbaddecaf888",
-    "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985",
+    "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b254"
+    "66931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985",
     "4d5c2af327cd64a62cf35abd2ba6fab4",
   },
   {
     "feffe9928665731c6d6a8f9467308308",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
     "cafebabefacedbaddecaf888",
-    "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091",
+    "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b254"
+    "66931c7d8f6a5aac84aa051ba30b396a0aac973d58e091",
     "5bc94fbc3221a5db94fae95ae7121a47",
   },
   {
     "feffe9928665731c6d6a8f9467308308",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
     "cafebabefacedbad",
-    "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598",
+    "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e4"
+    "9f24b22b097544d4896b424989b5e1ebac0f07c23f4598",
     "3612d2e79e3b0785561be14aaca2fccb",
   },
   {
     "feffe9928665731c6d6a8f9467308308",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
-    "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
-    "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5",
+    "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156"
+    "809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+    "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fb"
+    "a43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5",
     "619cc5aefffe0bfa462af43c1699d050",
   },
   {
@@ -156,42 +166,53 @@
   },
   {
     "feffe9928665731c6d6a8f9467308308feffe9928665731c",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
     NULL,
     "cafebabefacedbaddecaf888",
-    "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256",
+    "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c1"
+    "44c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256",
     "9924a7c8587336bfb118024db8674a14",
   },
   {
     "feffe9928665731c6d6a8f9467308308feffe9928665731c",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
     "cafebabefacedbaddecaf888",
-    "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710",
+    "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c1"
+    "44c525ac619d18c84a3f4718e2448b2fe324d9ccda2710",
     "2519498e80f1478f37ba55bd6d27618c",
   },
   {
     "feffe9928665731c6d6a8f9467308308feffe9928665731c",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
     "cafebabefacedbad",
-    "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
+    "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a"
+    "471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
     "65dcc57fcf623a24094fcca40d3533f8",
   },
   {
     "feffe9928665731c6d6a8f9467308308feffe9928665731c",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
     "cafebabefacedbad",
-    "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
+    "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a"
+    "471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
     "65dcc57fcf623a24094fcca40d3533f8",
   },
   {
     "feffe9928665731c6d6a8f9467308308feffe9928665731c",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
-    "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
-    "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b",
+    "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156"
+    "809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+    "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af"
+    "34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b",
     "dcf566ff291c25bbb8568fc3d376a6d9",
   },
   {
@@ -212,120 +233,82 @@
   },
   {
     "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
     NULL,
     "cafebabefacedbaddecaf888",
-    "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
+    "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e4859"
+    "0dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
     "b094dac5d93471bdec1a502270e3cc6c",
   },
   {
     "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
     "cafebabefacedbaddecaf888",
-    "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662",
+    "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e4859"
+    "0dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662",
     "76fc6ece0f4e1768cddf8853bb2d551b",
   },
   {
     "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
     "cafebabefacedbad",
-    "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f",
+    "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d339"
+    "34a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f",
     "3a337dbf46a792c45e454913fe2ea8f2",
   },
   {
     "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
     "feedfacedeadbeeffeedfacedeadbeefabaddad2",
-    "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
-    "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f",
+    "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156"
+    "809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+    "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780"
+    "f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f",
     "a44a8266ee1c8eb0c8b5d4cf5ae9f19a",
   },
   {
     "00000000000000000000000000000000",
     NULL,
-    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
+    "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9595"
+    "6809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f"
+    "37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b10568288"
+    "38c5f61e6393ba7a0abcc9f662898015ad",
     "000000000000000000000000",
     NULL,
     "5fea793a2d6f974d37e68e0cb8ff9492",
   },
   {
     "00000000000000000000000000000000",
-    "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+    "00000000000000000000000000000000000000000000000000000000000000000000000000"
+    "00000000000000000000000000000000000000000000000000000000000000000000000000"
+    "00000000000000000000000000000000000000000000000000000000000000000000000000"
+    "00000000000000000000000000000000000000000000000000000000000000000000000000"
+    "00000000000000000000000000000000000000000000000000000000000000000000000000"
+    "00000000000000000000000000000000000000000000000000000000000000000000000000"
+    "00000000000000000000000000000000000000000000000000000000000000000000000000"
+    "0000000000000000000000000000000000000000000000000000000000",
     NULL,
     /* This nonce results in 0xfff in counter LSB. */
-    "ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
-    "56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c",
+    "ffffffff000000000000000000000000000000000000000000000000000000000000000000"
+    "000000000000000000000000000000000000000000000000000000",
+    "56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48c"
+    "f7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0"
+    "b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e5015112213"
+    "76a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880"
+    "dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b10"
+    "70bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dc"
+    "f3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a43"
+    "9c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c",
     "8b307f6b33286d0ab026a9ed3fe1e85f",
   },
 };
 
-int from_hex(uint8_t *out, char in) {
-  if (in >= '0' && in <= '9') {
-    *out = in - '0';
-    return 1;
-  }
-  if (in >= 'a' && in <= 'f') {
-    *out = in - 'a' + 10;
-    return 1;
-  }
-  if (in >= 'A' && in <= 'F') {
-    *out = in - 'A' + 10;
-    return 1;
-  }
-
-  return 0;
-}
-
-void decode_hex(scoped_array<uint8_t> *out, int *out_len, const char *in,
-                int test_num, const char *description) {
-  if (in == NULL) {
-    out->reset();
-    *out_len = 0;
-    return;
-  }
-
-  size_t len = SbStringGetLength(in);
-  if (len & 1) {
-    ADD_FAILURE() << description << ": Odd length.";
-    return;
-  }
-
-  scoped_array<uint8_t> buf(new uint8_t[len / 2]);
-  if (!buf) {
-    ADD_FAILURE() << description << ": Memory fail.";
-    return;
-  }
-
-  for (size_t i = 0; i < len; i += 2) {
-    uint8_t v, v2;
-    bool result = from_hex(&v, in[i]) && from_hex(&v2, in[i + 1]);
-    if (!result) {
-      ADD_FAILURE() << description << ": Invalid character at " << i << ".";
-      continue;
-    }
-
-    buf[i / 2] = (v << 4) | v2;
-  }
-
-  *out = buf.Pass();
-  *out_len = static_cast<int>(len / 2);
-}
-
-std::string hexdump(const void *in, int len) {
-  const uint8_t* data = reinterpret_cast<const uint8_t*>(in);
-
-  std::string result;
-  for (size_t i = 0; i < len; i++) {
-    char hex[3] = {0};
-    SbStringFormatF(hex, 3, "%02x", data[i]);
-    result += hex;
-  }
-
-  return result;
-}
-
 class Gcm
     : public ::testing::TestWithParam<int> {
  public:
@@ -350,15 +333,15 @@
   scoped_array<uint8_t> tag;
   scoped_array<uint8_t> out;
 
-  decode_hex(&key, &key_len, test->key, test_num, "key");
-  decode_hex(&plaintext, &plaintext_len, test->plaintext, test_num,
+  DecodeHex(&key, &key_len, test->key, test_num, "key");
+  DecodeHex(&plaintext, &plaintext_len, test->plaintext, test_num,
              "plaintext");
-  decode_hex(&additional_data, &additional_data_len,
+  DecodeHex(&additional_data, &additional_data_len,
              test->additional_data, test_num, "additional_data");
-  decode_hex(&nonce, &nonce_len, test->nonce, test_num, "nonce");
-  decode_hex(&ciphertext, &ciphertext_len, test->ciphertext, test_num,
+  DecodeHex(&nonce, &nonce_len, test->nonce, test_num, "nonce");
+  DecodeHex(&ciphertext, &ciphertext_len, test->ciphertext, test_num,
              "ciphertext");
-  decode_hex(&tag, &tag_len, test->tag, test_num, "tag");
+  DecodeHex(&tag, &tag_len, test->tag, test_num, "tag");
 
   if (plaintext_len != ciphertext_len) {
     FAIL() << "Plaintext and ciphertext have differing lengths.";
@@ -407,13 +390,13 @@
   SbMemorySet(actual_tag.get(), 0, tag_len);
   SbCryptographyGetTag(encrypter, actual_tag.get(), tag_len);
   if (tag) {
-    EXPECT_STREQ(hexdump(tag.get(), tag_len).c_str(),
-                 hexdump(actual_tag.get(), tag_len).c_str());
+    EXPECT_STREQ(HexDump(tag.get(), tag_len).c_str(),
+                 HexDump(actual_tag.get(), tag_len).c_str());
   }
 
   if (ciphertext) {
-    EXPECT_STREQ(hexdump(ciphertext.get(), plaintext_len).c_str(),
-                 hexdump(out.get(), plaintext_len).c_str());
+    EXPECT_STREQ(HexDump(ciphertext.get(), plaintext_len).c_str(),
+                 HexDump(out.get(), plaintext_len).c_str());
   }
 
   SbCryptographyDestroyTransformer(encrypter);
@@ -443,13 +426,13 @@
   SbMemorySet(actual_tag.get(), 0, tag_len);
   SbCryptographyGetTag(decrypter, actual_tag.get(), tag_len);
   if (tag) {
-    EXPECT_STREQ(hexdump(tag.get(), tag_len).c_str(),
-                 hexdump(actual_tag.get(), tag_len).c_str());
+    EXPECT_STREQ(HexDump(tag.get(), tag_len).c_str(),
+                 HexDump(actual_tag.get(), tag_len).c_str());
   }
 
   if (plaintext) {
-    EXPECT_STREQ(hexdump(plaintext.get(), plaintext_len).c_str(),
-                 hexdump(out.get(), plaintext_len).c_str());
+    EXPECT_STREQ(HexDump(plaintext.get(), plaintext_len).c_str(),
+                 HexDump(out.get(), plaintext_len).c_str());
   }
   SbCryptographyDestroyTransformer(decrypter);
 }
diff --git a/src/starboard/nplb/cryptography_transform_test.cc b/src/starboard/nplb/cryptography_transform_test.cc
index fc44126..1b5770f 100644
--- a/src/starboard/nplb/cryptography_transform_test.cc
+++ b/src/starboard/nplb/cryptography_transform_test.cc
@@ -14,7 +14,9 @@
 
 #include "starboard/cryptography.h"
 
+#include "starboard/common/scoped_ptr.h"
 #include "starboard/log.h"
+#include "starboard/nplb/cryptography_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if SB_API_VERSION >= 4
@@ -23,50 +25,183 @@
 namespace nplb {
 namespace {
 
+class Aes : public ::testing::TestWithParam<SbCryptographyBlockCipherMode> {
+ protected:
+  SbCryptographyBlockCipherMode GetMode() { return GetParam(); }
+
+  bool ShouldSetIvAtInitialization() {
+    return GetIvMode() == kIvModeSetAtInitialization ||
+           GetIvMode() == kIvModeSetAnyTime;
+  }
+
+  bool ShouldSetIvAfterInitialization() {
+    return GetIvMode() == kIvModeSetAfterInitialization ||
+           GetIvMode() == kIvModeSetAnyTime;
+  }
+
+  bool ShouldSetAuthenticatedData() {
+    switch (GetMode()) {
+      case kSbCryptographyBlockCipherModeGcm:
+        return true;
+      case kSbCryptographyBlockCipherModeEcb:
+      case kSbCryptographyBlockCipherModeCtr:
+      case kSbCryptographyBlockCipherModeCbc:
+      case kSbCryptographyBlockCipherModeCfb:
+      case kSbCryptographyBlockCipherModeOfb:
+        return false;
+      default:
+        ADD_FAILURE() << "Unrecognized SbCryptographyBlockCipherMode "
+                      << GetMode();
+        return false;
+    }
+  }
+
+  const char* GetExpectedEncryptedValueHex() {
+    switch (GetMode()) {
+      case kSbCryptographyBlockCipherModeGcm:
+        return "6a7b6e871f851db21a29f6aef579cfb77238d34b2f099404f20bb44c6b2d4d2"
+               "0a2788f8ffc0a36eba4cd8e69ee95e973b5eb52d1e218ee991ccc0ee1ba2fa7"
+               "d1dc83a5d2e3c317e5637b67c2524bd073ec6fe547edf6044111e2e16c239ed"
+               "e845d4b7b235f24fbdb2673dbdd1c5d5c46d7b69059ff4b1566b01bec4f4ca6"
+               "a4c500";
+
+      case kSbCryptographyBlockCipherModeEcb:
+        return "36aa40499dccc9f25bb3c1abcf4b73cf5993dc6127c534e7491a31a54f09bc4"
+               "8e9fc157e380ca1457dedac9147e158be1c8eba2ec679d6bdc54cb2878cd2ab"
+               "6736aa40499dccc9f25bb3c1abcf4b73cf5993dc6127c534e7491a31a54f09b"
+               "c48e9fc157e380ca1457dedac9147e158beae602e043e0572ed2f71acf5438c"
+               "e78200";
+
+      case kSbCryptographyBlockCipherModeCtr:
+        return "f32f8a813cea30e0f4c6e2efeab52ab92976cc06fa5f69409c3358ef2f3782d"
+               "daff201f56acd9b61fea4c3e4739deab176ad764da16d1248d59337962c7ab0"
+               "f2cd4c292ed34ae4125d8fb142344b2d2fc4ff533b80f5e8e311cde700ceaed"
+               "a613c6f27f72a0602e6e4891e6b4f5a0a64e795998a40544d88363d124d5294"
+               "c91700";
+
+      case kSbCryptographyBlockCipherModeCbc:
+        return "eaa929d637cde55115d43257e920ff8d39d1dec8240255a5db79a0cf79501a1"
+               "4bc62c4d16fc45dd7fa9d15b3346a74301260dfeb96e22259787344d7e47047"
+               "3eb4187eeac16a74afd1c5fdc67fb145cc494667ea4b16dccc83cc1cc1b2c36"
+               "2f2a03e90d6c3a9adbf53c4cb8e4987719928ef7c47c4403f0cfe5a0ff77325"
+               "6eaa00";
+
+      case kSbCryptographyBlockCipherModeCfb:
+      case kSbCryptographyBlockCipherModeOfb:
+        ADD_FAILURE() << "Unsupported SbCryptographyBlockCipherMode "
+                      << GetMode();
+        return "";
+      default:
+        ADD_FAILURE() << "Unrecognized SbCryptographyBlockCipherMode "
+                      << GetMode();
+        return "";
+    }
+  }
+
+ private:
+  enum IvMode {
+    kIvModeNotUsed,
+    kIvModeSetAtInitialization,
+    kIvModeSetAfterInitialization,
+    kIvModeSetAnyTime,
+  };
+
+  IvMode GetIvMode() {
+    switch (GetMode()) {
+      case kSbCryptographyBlockCipherModeEcb:
+        return kIvModeNotUsed;
+      case kSbCryptographyBlockCipherModeGcm:
+        return kIvModeSetAfterInitialization;
+      case kSbCryptographyBlockCipherModeCtr:
+        return kIvModeSetAnyTime;
+      case kSbCryptographyBlockCipherModeCbc:
+      case kSbCryptographyBlockCipherModeCfb:
+      case kSbCryptographyBlockCipherModeOfb:
+        return kIvModeSetAtInitialization;
+      default:
+        ADD_FAILURE() << "Unrecognized SbCryptographyBlockCipherMode "
+                      << GetMode();
+        return kIvModeNotUsed;
+    }
+  }
+};
+
 const int kBlockSizeBits = 128;
 const int kBlockSizeBytes = kBlockSizeBits / 8;
 
-TEST(SbCryptographyTransform, SunnyDay) {
-  char initialization_vector[kBlockSizeBytes + 1] = "0123456789ABCDEF";
-  char key[kBlockSizeBytes + 1] = "RijndaelRijndael";
-  const char kClearText[] =
-      "This test text is designed to be a multiple of "
-      "128 bits, huzzah.";
+const char kClearText[] =
+    "This test text is designed to be a multiple of 128 bits, huzzah-"
+    "This test text is designed to be a multiple of 128 bits, huzzah!";
+const char kAdditionalDataString[] = "000000000000000000000000";
+const char kInitializationVector[kBlockSizeBytes + 1] = "0123456789ABCDEF";
+const char kKey[kBlockSizeBytes + 1] = "Rijndael";
 
-  // Try to create a transformer for the most likely algorithm to be supported:
-  // AES-128-CBC
-  SbCryptographyTransformer transformer = SbCryptographyCreateTransformer(
+TEST_P(Aes, SunnyDayIdentity) {
+  SbCryptographyBlockCipherMode mode = GetMode();
+
+  SbCryptographyTransformer encrypter = SbCryptographyCreateTransformer(
       kSbCryptographyAlgorithmAes, kBlockSizeBits,
-      kSbCryptographyDirectionEncode, kSbCryptographyBlockCipherModeCbc,
-      initialization_vector, kBlockSizeBytes, key, kBlockSizeBytes);
+      kSbCryptographyDirectionEncode, mode,
+      ShouldSetIvAtInitialization() ? kInitializationVector : NULL,
+      ShouldSetIvAtInitialization() ? kBlockSizeBytes : 0, kKey,
+      kBlockSizeBytes);
 
-  if (!SbCryptographyIsTransformerValid(transformer)) {
+  if (!SbCryptographyIsTransformerValid(encrypter)) {
+    SB_LOG(WARNING) << "Skipping test, as there is no implementation.";
     // Test over if there's no implementation.
     return;
   }
 
+  if (ShouldSetIvAfterInitialization()) {
+    SbCryptographySetInitializationVector(encrypter, kInitializationVector,
+                                          kBlockSizeBytes);
+  }
+
+  if (ShouldSetAuthenticatedData()) {
+    scoped_array<uint8_t> aad;
+    int aad_len = 0;
+    DecodeHex(&aad, &aad_len, kAdditionalDataString, GetMode(), "aad");
+    SbCryptographySetAuthenticatedData(encrypter, aad.get(), aad_len);
+  }
+
   const int kInputSize = static_cast<int>(SbStringGetLength(kClearText));
   const int kBufferSize = static_cast<int>(sizeof(kClearText));
   char* cipher_text = new char[kBufferSize];
   SbMemorySet(cipher_text, 0, kBufferSize);
-  int count = SbCryptographyTransform(transformer, kClearText, kInputSize,
-                                      cipher_text);
+  int count =
+      SbCryptographyTransform(encrypter, kClearText, kInputSize, cipher_text);
   EXPECT_EQ(kInputSize, count);
   EXPECT_NE(0, SbStringCompare(kClearText, cipher_text, kBufferSize));
 
-  SbCryptographyTransformer decode_transformer =
-      SbCryptographyCreateTransformer(
-          kSbCryptographyAlgorithmAes, kBlockSizeBits,
-          kSbCryptographyDirectionDecode, kSbCryptographyBlockCipherModeCbc,
-          initialization_vector, kBlockSizeBytes, key, kBlockSizeBytes);
+  EXPECT_STREQ(GetExpectedEncryptedValueHex(),
+               HexDump(cipher_text, kBufferSize).c_str());
 
-  ASSERT_TRUE(SbCryptographyIsTransformerValid(decode_transformer));
+  SbCryptographyTransformer decrypter = SbCryptographyCreateTransformer(
+      kSbCryptographyAlgorithmAes, kBlockSizeBits,
+      kSbCryptographyDirectionDecode, mode,
+      ShouldSetIvAtInitialization() ? kInitializationVector : NULL,
+      ShouldSetIvAtInitialization() ? kBlockSizeBytes : 0, kKey,
+      kBlockSizeBytes);
+
+  ASSERT_TRUE(SbCryptographyIsTransformerValid(decrypter))
+      << "Cryptographic support for a set of parameters must be symmetrical.";
+
+  if (ShouldSetIvAfterInitialization()) {
+    SbCryptographySetInitializationVector(decrypter, kInitializationVector,
+                                          kBlockSizeBytes);
+  }
+
+  if (ShouldSetAuthenticatedData()) {
+    scoped_array<uint8_t> aad;
+    int aad_len = 0;
+    DecodeHex(&aad, &aad_len, kAdditionalDataString, GetMode(), "aad");
+    SbCryptographySetAuthenticatedData(decrypter, aad.get(), aad_len);
+  }
 
   char* decrypted_text = new char[kBufferSize];
   SbMemorySet(decrypted_text, 0, kBufferSize);
-  count =
-      SbCryptographyTransform(decode_transformer, cipher_text, kInputSize,
-                              decrypted_text);
+  count = SbCryptographyTransform(decrypter, cipher_text, kInputSize,
+                                  decrypted_text);
 
   EXPECT_EQ(kInputSize, count);
   EXPECT_EQ(kInputSize, SbStringGetLength(decrypted_text));
@@ -74,10 +209,19 @@
 
   delete[] decrypted_text;
   delete[] cipher_text;
-  SbCryptographyDestroyTransformer(decode_transformer);
-  SbCryptographyDestroyTransformer(transformer);
+  SbCryptographyDestroyTransformer(decrypter);
+  SbCryptographyDestroyTransformer(encrypter);
 }
 
+INSTANTIATE_TEST_CASE_P(SbCryptographyTransform,
+                        Aes,
+                        ::testing::Values(kSbCryptographyBlockCipherModeCbc,
+                                          kSbCryptographyBlockCipherModeCfb,
+                                          kSbCryptographyBlockCipherModeCtr,
+                                          kSbCryptographyBlockCipherModeEcb,
+                                          kSbCryptographyBlockCipherModeOfb,
+                                          kSbCryptographyBlockCipherModeGcm));
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/memory_reporter_test.cc b/src/starboard/nplb/memory_reporter_test.cc
index e225324..d60e010 100644
--- a/src/starboard/nplb/memory_reporter_test.cc
+++ b/src/starboard/nplb/memory_reporter_test.cc
@@ -328,7 +328,7 @@
     return;
   }
   const int64_t kMemSize = 4096;
-  const int kFlags = 0;
+  const int kFlags = kSbMemoryMapProtectReadWrite;
   EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
   void* mem_chunk = SbMemoryMap(kMemSize, kFlags, "TestMemMap");
   EXPECT_EQ_NO_TRACKING(1, mem_reporter()->number_allocs());
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index 782c729..174b062 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -82,6 +82,8 @@
         'condition_variable_wait_timed_test.cc',
         'configuration_test.cc',
         'cryptography_create_transformer_test.cc',
+        'cryptography_helpers.cc',
+        'cryptography_helpers.h',
         'cryptography_transform_test.cc',
         'cryptography_transform_gcm_test.cc',
         'decode_target_create_test.cc',
@@ -153,6 +155,7 @@
         'socket_connect_test.cc',
         'socket_create_test.cc',
         'socket_destroy_test.cc',
+        'socket_get_interface_address_test.cc',
         'socket_get_last_error_test.cc',
         'socket_get_local_address_test.cc',
         'socket_get_local_interface_address_test.cc',
diff --git a/src/starboard/nplb/socket_get_interface_address_test.cc b/src/starboard/nplb/socket_get_interface_address_test.cc
new file mode 100644
index 0000000..a9d3f5a
--- /dev/null
+++ b/src/starboard/nplb/socket_get_interface_address_test.cc
@@ -0,0 +1,197 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/nplb/socket_helpers.h"
+#include "starboard/socket.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const unsigned char kInvalidByte = 0xFE;
+
+}  // namespace
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+#if SB_API_VERSION >= 4
+class SbSocketGetInterfaceAddressTest
+    : public ::testing::TestWithParam<SbSocketAddressType> {
+ public:
+  SbSocketAddressType GetAddressType() { return GetParam(); }
+};
+
+TEST(SbSocketGetInterfaceAddressTest, SunnyDay) {
+  SbSocketAddress invalid_address;
+  SbSocketAddress address;
+
+  // Initialize to something invalid.
+  SbMemorySet(&address, kInvalidByte, sizeof(address));
+  SbMemorySet(&invalid_address, kInvalidByte, sizeof(invalid_address));
+
+  EXPECT_TRUE(SbSocketGetInterfaceAddress(NULL, &address, NULL));
+  EXPECT_EQ(0, address.port);
+  EXPECT_FALSE(IsUnspecified(&address));
+  EXPECT_FALSE(IsLocalhost(&address));
+  EXPECT_NE(0, SbMemoryCompare(address.address, invalid_address.address,
+                               SB_ARRAY_SIZE(address.address)));
+}
+
+TEST(SbSocketGetInterfaceAddressTest, RainyDayNull) {
+  EXPECT_FALSE(SbSocketGetInterfaceAddress(NULL, NULL, NULL));
+}
+
+TEST(SbSocketGetInterfaceAddressTest, SunnyDayNullDestination) {
+  SbSocketAddress netmask;
+  SbSocketAddress source;
+
+  SbMemorySet(&netmask, kInvalidByte, sizeof(netmask));
+  SbMemorySet(&source, kInvalidByte, sizeof(source));
+
+  // If destination address is NULL, then any IP address that is valid for
+  // |destination| set to 0.0.0.0 (IPv4) or :: (IPv6) can be returned.
+
+  EXPECT_TRUE(SbSocketGetInterfaceAddress(NULL, &source, NULL));
+  EXPECT_TRUE(source.type == kSbSocketAddressTypeIpv4 ||
+              source.type == kSbSocketAddressTypeIpv6);
+
+  EXPECT_TRUE(SbSocketGetInterfaceAddress(NULL, &source, &netmask));
+  // A netmask that starts with 0 is likely incorrect.
+  EXPECT_TRUE(netmask.address[0] & 0x8);
+  EXPECT_TRUE(source.type == kSbSocketAddressTypeIpv4 ||
+              source.type == kSbSocketAddressTypeIpv6);
+  EXPECT_TRUE(netmask.type == kSbSocketAddressTypeIpv4 ||
+              netmask.type == kSbSocketAddressTypeIpv6);
+}
+
+TEST_P(SbSocketGetInterfaceAddressTest, SunnyDayDestination) {
+  SbSocketAddress destination = {0};
+  destination.type = GetAddressType();
+
+  SbSocketAddress netmask;
+  SbSocketAddress source;
+
+  // Initialize to something invalid.
+  SbMemorySet(&netmask, kInvalidByte, sizeof(netmask));
+  SbMemorySet(&source, kInvalidByte, sizeof(source));
+
+  EXPECT_TRUE(SbSocketGetInterfaceAddress(&destination, &source, NULL));
+  EXPECT_TRUE(source.type == GetAddressType());
+  EXPECT_TRUE(SbSocketGetInterfaceAddress(&destination, &source, &netmask));
+
+  EXPECT_FALSE(IsLocalhost(&source));
+
+  // A netmask that starts with 0 is likely incorrect.
+  EXPECT_TRUE(netmask.address[0] & 0x8);
+  EXPECT_EQ(source.type, GetAddressType());
+  EXPECT_EQ(netmask.type, GetAddressType());
+  EXPECT_EQ(source.port, 0);
+}
+
+TEST_P(SbSocketGetInterfaceAddressTest, SunnyDaySourceForDestination) {
+  const char kTestHostName[] = "www.example.com";
+
+  SbSocketResolveFilter resolve_filter = kSbSocketResolveFilterNone;
+  switch (GetAddressType()) {
+    case kSbSocketAddressTypeIpv4:
+      resolve_filter = kSbSocketResolveFilterIpv4;
+      break;
+    case kSbSocketAddressTypeIpv6:
+      resolve_filter = kSbSocketResolveFilterIpv6;
+      break;
+    default:
+      FAIL() << "Invalid address type " << GetAddressType();
+  }
+  SbSocketResolution* resolution =
+      SbSocketResolve(kTestHostName, resolve_filter);
+
+  // TODO: Switch to nullptr, when C++11 is available.
+  ASSERT_NE(resolution, reinterpret_cast<SbSocketResolution*>(NULL));
+  ASSERT_NE(resolution->address_count, 0);
+  SbSocketAddress& destination_address = resolution->addresses[0];
+
+  SbSocketAddress source;
+  SbSocketAddress netmask;
+  SbSocketAddress invalid_address;
+  SbMemorySet(&netmask, kInvalidByte, sizeof(netmask));
+  SbMemorySet(&source, kInvalidByte, sizeof(source));
+  SbMemorySet(&invalid_address, kInvalidByte, sizeof(source));
+  SbSocketGetInterfaceAddress(&destination_address, &source, &netmask);
+
+  EXPECT_TRUE(source.type == GetAddressType());
+  EXPECT_NE(source.port, 0);
+  // A netmask that starts with 0 is likely incorrect.
+  EXPECT_TRUE(netmask.address[0] & 0x8);
+  EXPECT_EQ(netmask.type, GetAddressType());
+  EXPECT_NE(0, SbMemoryCompare(source.address, invalid_address.address,
+                               SB_ARRAY_SIZE(source.address)));
+  EXPECT_NE(0, SbMemoryCompare(netmask.address, invalid_address.address,
+                               SB_ARRAY_SIZE(netmask.address)));
+
+  SbSocketFreeResolution(resolution);
+}
+
+TEST_P(SbSocketGetInterfaceAddressTest, SunnyDaySourceNotLoopback) {
+  SbSocketAddress destination = {0};
+  destination.type = GetAddressType();
+
+  // If the destination address is 0.0.0.0, and its |type| is
+  // |kSbSocketAddressTypeIpv4|, then any IPv4 local interface that is up and
+  // not a loopback interface is a valid return value.
+  //
+  // If the destination address is ::, and its |type| is
+  // |kSbSocketAddressTypeIpv6| then any IPv6 local interface that is up and
+  // not loopback or a link-local IP is a valid return value.  However, in the
+  // case of IPv6, the address with the biggest scope must be returned.  E.g., a
+  // globally scoped and routable IP is prefered over a unique local address
+  // (ULA). Also, the IP address that is returned must be permanent.
+
+  SbSocketAddress netmask;
+  SbSocketAddress source;
+  SbSocketAddress invalid_address;
+
+  // Initialize to something invalid.
+  SbMemorySet(&netmask, kInvalidByte, sizeof(netmask));
+  SbMemorySet(&source, kInvalidByte, sizeof(source));
+  SbMemorySet(&invalid_address, kInvalidByte, sizeof(invalid_address));
+
+  EXPECT_TRUE(SbSocketGetInterfaceAddress(&destination, &source, NULL));
+  EXPECT_EQ(source.type, GetAddressType());
+  EXPECT_TRUE(SbSocketGetInterfaceAddress(&destination, &source, &netmask));
+  EXPECT_FALSE(IsLocalhost(&source));
+  EXPECT_FALSE(IsUnspecified(&source));
+
+  EXPECT_NE(0, SbMemoryCompare(netmask.address, invalid_address.address,
+                               SB_ARRAY_SIZE(netmask.address)));
+  EXPECT_NE(0, SbMemoryCompare(source.address, invalid_address.address,
+                               SB_ARRAY_SIZE(source.address)));
+}
+
+#if SB_HAS(IPV6)
+INSTANTIATE_TEST_CASE_P(SbSocketAddressTypes,
+                        SbSocketGetInterfaceAddressTest,
+                        ::testing::Values(kSbSocketAddressTypeIpv4,
+                                          kSbSocketAddressTypeIpv6));
+#else
+INSTANTIATE_TEST_CASE_P(SbSocketAddressTypes,
+                        SbSocketGetInterfaceAddressTest,
+                        ::testing::Values(kSbSocketAddressTypeIpv4));
+#endif  // SB_HAS(IPV6)
+
+#endif  // SB_API_VERSION >= 4
+
+}  // namespace
+}  // namespace nplb
+}  // namespace starboard
diff --git a/src/starboard/nplb/socket_get_local_interface_address_test.cc b/src/starboard/nplb/socket_get_local_interface_address_test.cc
index a282f61..db8e0eb 100644
--- a/src/starboard/nplb/socket_get_local_interface_address_test.cc
+++ b/src/starboard/nplb/socket_get_local_interface_address_test.cc
@@ -20,28 +20,24 @@
 namespace nplb {
 namespace {
 
+#if SB_API_VERSION < 4
+
 TEST(SbSocketGetLocalInterfaceAddressTest, SunnyDay) {
   SbSocketAddress address;
   // Initialize to something invalid.
   SbMemorySet(&address, 0xFE, sizeof(address));
-#if SB_API_VERSION < 4
   EXPECT_TRUE(SbSocketGetLocalInterfaceAddress(&address));
-#else
-  EXPECT_TRUE(SbSocketGetInterfaceAddress(NULL, &address, NULL));
-#endif  // SB_API_VERSION < 4
   EXPECT_EQ(0, address.port);
   EXPECT_FALSE(IsUnspecified(&address));
   EXPECT_FALSE(IsLocalhost(&address));
 }
 
 TEST(SbSocketGetLocalInterfaceAddressTest, RainyDayNull) {
-#if SB_API_VERSION < 4
   EXPECT_FALSE(SbSocketGetLocalInterfaceAddress(NULL));
-#else
-  EXPECT_FALSE(SbSocketGetInterfaceAddress(NULL, NULL, NULL));
-#endif  // SB_API_VERSION < 4
 }
 
+#endif  // SB_API_VERSION < 4
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/socket_set_options_test.cc b/src/starboard/nplb/socket_set_options_test.cc
index a6557a8..b7825df 100644
--- a/src/starboard/nplb/socket_set_options_test.cc
+++ b/src/starboard/nplb/socket_set_options_test.cc
@@ -27,10 +27,9 @@
   SbSocketAddressType GetAddressType() { return GetParam(); }
 };
 
-TEST_P(SbSocketSetOptionsTest, TryThemAll) {
+TEST_P(SbSocketSetOptionsTest, TryThemAllTCP) {
   SbSocket socket = SbSocketCreate(GetAddressType(), kSbSocketProtocolTcp);
 
-  EXPECT_TRUE(SbSocketSetBroadcast(socket, true));
   EXPECT_TRUE(SbSocketSetReuseAddress(socket, true));
   EXPECT_TRUE(SbSocketSetReceiveBufferSize(socket, 16 * 1024));
   EXPECT_TRUE(SbSocketSetSendBufferSize(socket, 16 * 1024));
@@ -44,6 +43,17 @@
   EXPECT_TRUE(SbSocketDestroy(socket));
 }
 
+TEST_P(SbSocketSetOptionsTest, TryThemAllUDP) {
+  SbSocket socket = SbSocketCreate(GetAddressType(), kSbSocketProtocolUdp);
+
+  EXPECT_TRUE(SbSocketSetBroadcast(socket, true));
+  EXPECT_TRUE(SbSocketSetReuseAddress(socket, true));
+  EXPECT_TRUE(SbSocketSetReceiveBufferSize(socket, 16 * 1024));
+  EXPECT_TRUE(SbSocketSetSendBufferSize(socket, 16 * 1024));
+
+  EXPECT_TRUE(SbSocketDestroy(socket));
+}
+
 // TODO: Come up with some way to test the effects of these options.
 
 #if SB_HAS(IPV6)
diff --git a/src/starboard/shared/linux/socket_get_interface_address.cc b/src/starboard/shared/linux/socket_get_interface_address.cc
index 923e4c0..b9bd9c4 100644
--- a/src/starboard/shared/linux/socket_get_interface_address.cc
+++ b/src/starboard/shared/linux/socket_get_interface_address.cc
@@ -96,7 +96,8 @@
 template <typename in_addr_type>
 bool GetNetmaskForInterfaceAddress(const SbSocketAddress& interface_address,
                                    SbSocketAddress* out_netmask) {
-  SB_DCHECK(interface_address.type == kSbSocketAddressTypeIpv4);
+  SB_DCHECK((interface_address.type == kSbSocketAddressTypeIpv4) ||
+            (interface_address.type == kSbSocketAddressTypeIpv6));
   struct ifaddrs* interface_addrs = NULL;
 
   int retval = getifaddrs(&interface_addrs);
@@ -125,7 +126,7 @@
     }
 
     sbposix::SockAddr sock_addr;
-    sock_addr.FromSockaddr(interface->ifa_addr);
+    sock_addr.FromSockaddr(interface->ifa_netmask);
     if (sock_addr.ToSbSocketAddress(out_netmask)) {
       found_netmask = true;
       break;
@@ -137,29 +138,18 @@
   return found_netmask;
 }
 
-bool GetNetMaskForIPv4InterfaceAddress(const SbSocketAddress& interface_address,
-                                       SbSocketAddress* out_netmask) {
-  return GetNetmaskForInterfaceAddress<in_addr>(interface_address, out_netmask);
-}
-
-#if SB_HAS(IPV6)
-bool GetNetMaskForIPv6InterfaceAddress(const SbSocketAddress& interface_address,
-                                       SbSocketAddress* out_netmask) {
-  return GetNetmaskForInterfaceAddress<in6_addr>(interface_address,
-                                                 out_netmask);
-}
-#endif
-
 bool GetNetMaskForInterfaceAddress(const SbSocketAddress& interface_address,
                                    SbSocketAddress* out_netmask) {
   SB_DCHECK(out_netmask);
 
   switch (interface_address.type) {
     case kSbSocketAddressTypeIpv4:
-      return GetNetMaskForIPv4InterfaceAddress(interface_address, out_netmask);
+      return GetNetmaskForInterfaceAddress<in_addr>(interface_address,
+                                                    out_netmask);
 #if SB_HAS(IPV6)
     case kSbSocketAddressTypeIpv6:
-      return GetNetMaskForIPv6InterfaceAddress(interface_address, out_netmask);
+      return GetNetmaskForInterfaceAddress<in6_addr>(interface_address,
+                                                     out_netmask);
 #endif
     default:
       SB_NOTREACHED() << "Invalid address type " << interface_address.type;
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc b/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc
index f38eea8..19c286d 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc
@@ -94,7 +94,6 @@
   int result = -1;
   if (direction == kSbCryptographyDirectionDecode &&
       mode != kSbCryptographyBlockCipherModeCtr &&
-      mode != kSbCryptographyBlockCipherModeEcb &&
       mode != kSbCryptographyBlockCipherModeGcm) {
     result = AES_set_decrypt_key(key, key_size * 8, &aeskey);
   } else {
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_transform.cc b/src/starboard/shared/starboard/cryptography/cryptography_transform.cc
index bc78761..fc297c4 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_transform.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_transform.cc
@@ -32,6 +32,16 @@
 using starboard::shared::starboard::cryptography::kAlgorithmAes128Ecb;
 using starboard::shared::starboard::cryptography::kAlgorithmAes128Gcm;
 
+namespace {
+inline void* AddPtr(void* pointer, int value) {
+  return reinterpret_cast<char*>(pointer) + value;
+}
+
+inline const void* AddPtr(const void* pointer, int value) {
+  return reinterpret_cast<const char*>(pointer) + value;
+}
+}  // namespace
+
 int SbCryptographyTransform(SbCryptographyTransformer transformer,
                             const void* in_data,
                             int in_data_size,
@@ -65,9 +75,21 @@
       }
 
       if (transformer->direction == kSbCryptographyDirectionEncode) {
-        AES_encrypt(in_data, out_data, &transformer->key);
+        const void* in = in_data;
+        void* out = out_data;
+        for (int i = 0, blocks = in_data_size / 16; i < blocks; ++i) {
+          AES_encrypt(in, out, &transformer->key);
+          in = AddPtr(in, 16);
+          out = AddPtr(out, 16);
+        }
       } else if (transformer->direction == kSbCryptographyDirectionDecode) {
-        AES_decrypt(in_data, out_data, &transformer->key);
+        const void* in = in_data;
+        void* out = out_data;
+        for (int i = 0, blocks = in_data_size / 16; i < blocks; ++i) {
+          AES_decrypt(in, out, &transformer->key);
+          in = AddPtr(in, 16);
+          out = AddPtr(out, 16);
+        }
       } else {
         SB_NOTREACHED();
       }
diff --git a/src/starboard/shared/starboard/log_message.cc b/src/starboard/shared/starboard/log_message.cc
index 444bcd6..5e267b2 100644
--- a/src/starboard/shared/starboard/log_message.cc
+++ b/src/starboard/shared/starboard/log_message.cc
@@ -14,10 +14,12 @@
 
 #include "starboard/log.h"
 
+#include <algorithm>
 #include <iomanip>
 #include <sstream>
 #include <string>
 
+#include "starboard/client_porting/poem/string_poem.h"
 #include "starboard/mutex.h"
 #include "starboard/system.h"
 #include "starboard/thread.h"
@@ -124,7 +126,11 @@
     // Ensure the first characters of the string are on the stack so they
     // are contained in minidumps for diagnostic purposes.
     char str_stack[1024];
-    str_newline.copy(str_stack, SB_ARRAY_SIZE(str_stack));
+    const size_t copy_bytes =
+        std::min(SB_ARRAY_SIZE(str_stack), str_newline.length() + 1);
+    PoemStringCopyN(str_stack, str_newline.c_str(),
+                    static_cast<int>(copy_bytes));
+
     Alias(str_stack);
     Break();
   }
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
index 96e38a7..7041009 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
@@ -26,6 +26,12 @@
 namespace player {
 namespace filter {
 
+namespace {
+
+const SbTime kEndOfStreamWrittenUpdateInterval = 5 * kSbTimeMillisecond;
+
+}  // namespace
+
 AudioRendererImpl::AudioRendererImpl(JobQueue* job_queue,
                                      scoped_ptr<AudioDecoder> decoder,
                                      const SbMediaAudioHeader& audio_header)
@@ -46,7 +52,9 @@
       end_of_stream_written_(false),
       end_of_stream_decoded_(false),
       decoder_(decoder.Pass()),
-      audio_sink_(kSbAudioSinkInvalid) {
+      audio_sink_(kSbAudioSinkInvalid),
+      decoder_needs_full_reset_(false),
+      buffers_in_decoder_(0) {
   SB_DCHECK(job_queue != NULL);
   SB_DCHECK(decoder_ != NULL);
   SB_DCHECK(job_queue_->BelongsToCurrentThread());
@@ -96,6 +104,8 @@
   decoder_->Decode(input_buffer);
 
   ScopedLock lock(mutex_);
+  buffers_in_decoder_++;
+  decoder_needs_full_reset_ = true;
   if (!read_from_decoder_closure_.is_valid()) {
     read_from_decoder_closure_ =
         Bind(&AudioRendererImpl::ReadFromDecoder, this);
@@ -111,10 +121,13 @@
   if (end_of_stream_written_) {
     return;
   }
+
   decoder_->WriteEndOfStream();
 
   ScopedLock lock(mutex_);
+  buffers_in_decoder_++;
   end_of_stream_written_ = true;
+  decoder_needs_full_reset_ = true;
   // If we are seeking, we consider the seek is finished if end of stream is
   // reached as there won't be any audio data in future.
   if (seeking_) {
@@ -166,8 +179,12 @@
   end_of_stream_written_ = false;
   end_of_stream_decoded_ = false;
   pending_decoded_audio_ = NULL;
+  buffers_in_decoder_ = 0;
 
-  decoder_->Reset();
+  if (decoder_needs_full_reset_) {
+    decoder_->Reset();
+    decoder_needs_full_reset_ = false;
+  }
 }
 
 bool AudioRendererImpl::IsEndOfStreamPlayed() const {
@@ -184,7 +201,7 @@
   if (end_of_stream_written_) {
     return false;
   }
-  return pending_decoded_audio_ == NULL;
+  return buffers_in_decoder_ < kMaxbuffersInDecoder;
 }
 
 bool AudioRendererImpl::IsSeekingInProgress() const {
@@ -211,6 +228,16 @@
 
   *is_eos_reached = end_of_stream_decoded_;
 
+  if (!end_of_stream_decoded_ && !read_from_decoder_closure_.is_valid()) {
+    read_from_decoder_closure_ =
+        Bind(&AudioRendererImpl::ReadFromDecoder, this);
+    if (paused_ || seeking_) {
+      job_queue_->Schedule(read_from_decoder_closure_, 10 * kSbTimeMillisecond);
+    } else {
+      job_queue_->Schedule(read_from_decoder_closure_);
+    }
+  }
+
   if (paused_ || seeking_) {
     *is_playing = false;
     *frames_in_buffer = *offset_in_frames = 0;
@@ -220,12 +247,6 @@
   *is_playing = true;
   *frames_in_buffer = frames_in_buffer_;
   *offset_in_frames = offset_in_frames_;
-
-  if (!end_of_stream_decoded_ && !read_from_decoder_closure_.is_valid()) {
-    read_from_decoder_closure_ =
-        Bind(&AudioRendererImpl::ReadFromDecoder, this);
-    job_queue_->Schedule(read_from_decoder_closure_);
-  }
 }
 
 void AudioRendererImpl::ConsumeFrames(int frames_consumed) {
@@ -263,8 +284,34 @@
   SB_DCHECK(read_from_decoder_closure_.is_valid());
   read_from_decoder_closure_.reset();
 
-  scoped_refptr<DecodedAudio> decoded_audio =
-      pending_decoded_audio_ ? pending_decoded_audio_ : decoder_->Read();
+  // Create the audio sink if it is the first incoming AU after seeking.
+  if (audio_sink_ == kSbAudioSinkInvalid) {
+    int sample_rate = decoder_->GetSamplesPerSecond();
+    // TODO: Implement resampler.
+    SB_DCHECK(sample_rate ==
+              SbAudioSinkGetNearestSupportedSampleFrequency(sample_rate));
+    // TODO: Handle sink creation failure.
+    audio_sink_ = SbAudioSinkCreate(
+        channels_, sample_rate, decoder_->GetSampleType(),
+        kSbMediaAudioFrameStorageTypeInterleaved,
+        reinterpret_cast<SbAudioSinkFrameBuffers>(frame_buffers_),
+        kMaxCachedFrames, &AudioRendererImpl::UpdateSourceStatusFunc,
+        &AudioRendererImpl::ConsumeFramesFunc, this);
+#if SB_API_VERSION >= 4
+    audio_sink_->SetPlaybackRate(playback_rate_);
+#endif  // SB_API_VERSION >= 4
+  }
+
+  scoped_refptr<DecodedAudio> decoded_audio;
+  if (pending_decoded_audio_) {
+    decoded_audio = pending_decoded_audio_;
+  } else {
+    decoded_audio = decoder_->Read();
+    if (decoded_audio) {
+      SB_DCHECK(buffers_in_decoder_ > 0);
+      buffers_in_decoder_--;
+    }
+  }
   pending_decoded_audio_ = NULL;
   if (!decoded_audio) {
     return;
@@ -291,24 +338,6 @@
   if (seeking_ && frame_buffer_.size() > kPrerollFrames * bytes_per_frame_) {
     seeking_ = false;
   }
-
-  // Create the audio sink if it is the first incoming AU after seeking.
-  if (audio_sink_ == kSbAudioSinkInvalid) {
-    int sample_rate = decoder_->GetSamplesPerSecond();
-    // TODO: Implement resampler.
-    SB_DCHECK(sample_rate ==
-              SbAudioSinkGetNearestSupportedSampleFrequency(sample_rate));
-    // TODO: Handle sink creation failure.
-    audio_sink_ = SbAudioSinkCreate(
-        channels_, sample_rate, decoder_->GetSampleType(),
-        kSbMediaAudioFrameStorageTypeInterleaved,
-        reinterpret_cast<SbAudioSinkFrameBuffers>(frame_buffers_),
-        kMaxCachedFrames, &AudioRendererImpl::UpdateSourceStatusFunc,
-        &AudioRendererImpl::ConsumeFramesFunc, this);
-#if SB_API_VERSION >= 4
-    audio_sink_->SetPlaybackRate(playback_rate_);
-#endif  // SB_API_VERSION >= 4
-  }
 }
 
 // TODO: This function should be executed when lock is not acquired as it copies
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
index 70915f6..3e50194 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
@@ -73,6 +73,9 @@
   // 2. Have the audio cache full to simulate the state that the renderer can
   //    no longer accept more data.
   static const size_t kMaxCachedFrames = 256 * 1024;
+  // When there are more than |kMaxBuffersInDecoder| buffers inside the audio
+  // decoder, the renderer won't accept more data.
+  static const int kMaxbuffersInDecoder = 32;
 
   void UpdateSourceStatus(int* frames_in_buffer,
                           int* offset_in_frames,
@@ -119,6 +122,15 @@
   SbAudioSink audio_sink_;
   scoped_refptr<DecodedAudio> pending_decoded_audio_;
   Closure read_from_decoder_closure_;
+
+  // Our owner will attempt to seek to pts 0 when playback begins.  In
+  // general, seeking could require a full reset of the underlying decoder on
+  // some platforms, so we make an effort to improve playback startup
+  // performance by keeping track of whether we already have a fresh decoder,
+  // and can thus avoid doing a full reset.
+  bool decoder_needs_full_reset_;
+
+  int buffers_in_decoder_;
 };
 
 }  // namespace filter
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
index 810f5d2..78ab565 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
@@ -28,7 +28,8 @@
       end_of_stream_written_(false),
       need_more_input_(true),
       dropped_frames_(0),
-      decoder_(decoder.Pass()) {
+      decoder_(decoder.Pass()),
+      decoder_needs_full_reset_(false) {
   SB_DCHECK(decoder_ != NULL);
   decoder_->SetHost(this);
 }
@@ -48,6 +49,7 @@
   }
 
   decoder_->WriteInputBuffer(input_buffer);
+  decoder_needs_full_reset_ = true;
 }
 
 void VideoRendererImpl::WriteEndOfStream() {
@@ -60,13 +62,17 @@
   }
   end_of_stream_written_ = true;
   decoder_->WriteEndOfStream();
+  decoder_needs_full_reset_ = true;
 }
 
 void VideoRendererImpl::Seek(SbMediaTime seek_to_pts) {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
   SB_DCHECK(seek_to_pts >= 0);
 
-  decoder_->Reset();
+  if (decoder_needs_full_reset_) {
+    decoder_->Reset();
+    decoder_needs_full_reset_ = false;
+  }
 
   ScopedLock lock(mutex_);
 
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
index e56051d..2a35283 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
@@ -97,6 +97,13 @@
   int dropped_frames_;
 
   scoped_ptr<HostedVideoDecoder> decoder_;
+
+  // Our owner will attempt to seek to pts 0 when playback begins.  In
+  // general, seeking could require a full reset of the underlying decoder on
+  // some platforms, so we make an effort to improve playback startup
+  // performance by keeping track of whether we already have a fresh decoder,
+  // and can thus avoid doing a full reset.
+  bool decoder_needs_full_reset_;
 };
 
 }  // namespace filter
diff --git a/src/starboard/shared/win32/gyp_configuration.py b/src/starboard/shared/win32/gyp_configuration.py
new file mode 100644
index 0000000..46fa1a7
--- /dev/null
+++ b/src/starboard/shared/win32/gyp_configuration.py
@@ -0,0 +1,141 @@
+# Copyright 2016 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import logging
+import os
+
+import config.starboard
+import gyp_utils
+
+required_sdk_version = '10.0.15063.0'
+
+# Default Windows SDK bin directory.
+windows_sdk_bin_dir = 'C:\\Program Files (x86)\\Windows Kits\\10\\bin'
+
+# Maybe override Windows SDK bin directory with environment variable.
+windows_sdk_bin_var = 'WindowsSdkBinPath'
+if windows_sdk_bin_var in os.environ:
+  windows_sdk_bin_dir = os.environ[windows_sdk_bin_var]
+elif not os.path.exists(windows_sdk_bin_dir):
+  # If the above fails, this is our last guess.
+  windows_sdk_bin_dir = windows_sdk_bin_dir.replace('Program Files (x86)',
+                                                    'mappedProgramFiles')
+
+# Default Visual Studio Install directory.
+vs_install_dir = ('C:\\Program Files (x86)\\Microsoft Visual Studio'
+                  + '\\2017\\Professional')
+# Maybe override Visual Studio install directory with environment variable.
+vs_install_dir_var = 'VSINSTALLDIR'
+if vs_install_dir_var in os.environ:
+  vs_install_dir = os.environ[vs_install_dir_var]
+elif not os.path.exists(vs_install_dir):
+  # If the above fails, this is our last guess.
+  vs_install_dir = vs_install_dir.replace('Program Files (x86)',
+                                          'mappedProgramFiles')
+
+
+vs_install_dir_with_version = (vs_install_dir + '\\VC\\Tools\\MSVC'
+                               + '\\14.10.25017')
+vs_cl_path = vs_install_dir_with_version + '\\bin\\HostX64\\x64'
+
+
+
+def _CheckVisualStudioVersion():
+  if os.path.exists(vs_cl_path):
+    return True
+  logging.critical('Expected Visual Studio path \"%s\" not found.',
+                   vs_cl_path)
+
+def _QuotePath(path):
+  return '"' + path + '"'
+
+def _CheckWindowsSdkVersion():
+  required_sdk_bin_dir = os.path.join(windows_sdk_bin_dir,
+                                      required_sdk_version)
+  if os.path.exists(required_sdk_bin_dir):
+    return True
+
+  if os.path.exists(windows_sdk_bin_dir):
+    contents = os.listdir(windows_sdk_bin_dir)
+    contents = [content for content in contents
+                if os.path.isdir(os.path.join(windows_sdk_bin_dir, content))]
+    non_sdk_dirs = ['arm', 'arm64', 'x64', 'x86']
+    installed_sdks = [content for content in contents
+                      if content not in non_sdk_dirs]
+    logging.critical('Windows SDK versions \"%s\" found." \"%s\" required.',
+                     installed_sdks, required_sdk_version)
+  else:
+    logging.critical('Windows SDK versions \"%s\" required.',
+                     required_sdk_version)
+  return False
+
+
+class PlatformConfig(config.starboard.PlatformConfigStarboard):
+  """Starboard Microsoft Windows platform configuration."""
+
+  def __init__(self, platform):
+    super(PlatformConfig, self).__init__(platform)
+    _CheckWindowsSdkVersion()
+    _CheckVisualStudioVersion()
+
+  def GetVariables(self, configuration):
+    variables = super(PlatformConfig, self).GetVariables(configuration)
+    windows_sdk_path = os.path.abspath(os.path.join(windows_sdk_bin_dir,
+                                                    os.pardir))
+    variables.update({
+      'visual_studio_install_path': vs_install_dir_with_version,
+      'windows_sdk_path': windows_sdk_path,
+      'windows_sdk_version': required_sdk_version,
+      })
+    return variables
+
+  def GetEnvironmentVariables(self):
+    cl = _QuotePath(os.path.join(vs_cl_path, 'cl.exe'))
+    lib = _QuotePath(os.path.join(vs_cl_path, 'lib.exe'))
+    link = _QuotePath(os.path.join(vs_cl_path, 'link.exe'))
+    rc = _QuotePath(os.path.join(windows_sdk_bin_dir, required_sdk_version,
+                                 'x64', 'rc.exe'))
+    env_variables = {
+        'AR' : lib,
+        'AR_HOST' : lib,
+        'CC': cl,
+        'CXX': cl,
+        'LD': link,
+        'RC': rc,
+        'VS_INSTALL_DIR': vs_install_dir,
+        'CC_HOST': cl,
+        'CXX_HOST': cl,
+        'LD_HOST': link,
+        'ARFLAGS_HOST': 'rcs',
+        'ARTHINFLAGS_HOST': 'rcsT',
+    }
+    return env_variables
+
+  def GetBuildFormat(self):
+    """Returns the desired build format."""
+    # The comma means that ninja, msvs_makefile, will be chained and use the
+    # same input information so that .gyp files will only have to be parsed
+    # once.
+    return 'ninja,msvs_makefile'
+
+  def GetGeneratorVariables(self, configuration):
+    """Returns a dict of generator variables for the given configuration."""
+    _ = configuration
+    generator_variables = {
+        'msvs_version': 2017,
+        'msvs_platform': 'x64',
+        'msvs_template_prefix': 'win/',
+        'msvs_deploy_dir': '',
+        'qtcreator_session_name_prefix': 'cobalt',
+    }
+    return generator_variables
diff --git a/src/starboard/shared/win32/socket_accept.cc b/src/starboard/shared/win32/socket_accept.cc
index 08be946..dfc68db 100644
--- a/src/starboard/shared/win32/socket_accept.cc
+++ b/src/starboard/shared/win32/socket_accept.cc
@@ -47,5 +47,6 @@
 
   // Adopt the newly accepted socket.
   return new SbSocketPrivate(socket->address_type, socket->protocol,
-                             socket_handle);
+                             socket_handle,
+                             SbSocketPrivate::BindTarget::kAccepted);
 }
diff --git a/src/starboard/shared/win32/socket_bind.cc b/src/starboard/shared/win32/socket_bind.cc
index 9bc2afe..100c8e1 100644
--- a/src/starboard/shared/win32/socket_bind.cc
+++ b/src/starboard/shared/win32/socket_bind.cc
@@ -27,6 +27,9 @@
 bool IsIpv6InaddrAny(const SbSocketAddress* local_address) {
   return SbMemoryIsZero(local_address->address, sbwin32::kAddressLengthIpv6);
 }
+bool IsIpv4InaddrAny(const SbSocketAddress* local_address) {
+  return SbMemoryIsZero(local_address->address, sbwin32::kAddressLengthIpv4);
+}
 
 }  // namespace
 
@@ -51,16 +54,30 @@
     return (socket->error = sbwin32::TranslateSocketErrorStatus(EAFNOSUPPORT));
   }
 
-  // When binding to the IPV6 any address, ensure that the IPV6_V6ONLY flag is
-  // off to allow incoming IPV4 connections on the same socket.
-  // See https://www.ietf.org/rfc/rfc3493.txt for details.
-  if (local_address && (local_address->type == kSbSocketAddressTypeIpv6) &&
-      IsIpv6InaddrAny(local_address)) {
-    if (!sbwin32::SetBooleanSocketOption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
-                                         "IPV6_V6ONLY", false)) {
-      // Silently ignore errors, assume the default behavior is as expected.
-      socket->error = kSbSocketOk;
+  switch (local_address->type) {
+    case kSbSocketAddressTypeIpv6:
+      if (!IsIpv6InaddrAny(local_address)) {
+        socket->bound_to = SbSocketPrivate::BindTarget::kOther;
+        break;
+      }
+
+      socket->bound_to = SbSocketPrivate::BindTarget::kAny;
+
+      // When binding to the IPV6 any address, ensure that the IPV6_V6ONLY flag
+      // is off to allow incoming IPV4 connections on the same socket.
+      // See https://www.ietf.org/rfc/rfc3493.txt for details.
+      if (!sbwin32::SetBooleanSocketOption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
+                                           "IPV6_V6ONLY", false)) {
+        // Silently ignore errors, assume the default behavior is as expected.
+        socket->error = kSbSocketOk;
     }
+
+    break;
+    case kSbSocketAddressTypeIpv4:
+      socket->bound_to = IsIpv4InaddrAny(local_address)
+                             ? SbSocketPrivate::BindTarget::kAny
+                             : SbSocketPrivate::BindTarget::kOther;
+      break;
   }
 
   int result =
diff --git a/src/starboard/shared/win32/socket_connect.cc b/src/starboard/shared/win32/socket_connect.cc
index 4287d48..4c33768 100644
--- a/src/starboard/shared/win32/socket_connect.cc
+++ b/src/starboard/shared/win32/socket_connect.cc
@@ -44,11 +44,13 @@
       connect(socket->socket_handle, sock_addr.sockaddr(), sock_addr.length);
 
   if (result != SOCKET_ERROR) {
+    socket->bound_to = SbSocketPrivate::BindTarget::kAny;
     return (socket->error = kSbSocketOk);
   }
 
   const int last_error = WSAGetLastError();
   if (last_error == WSAEWOULDBLOCK) {
+    socket->bound_to = SbSocketPrivate::BindTarget::kAny;
     return (socket->error = kSbSocketPending);
   }
 
diff --git a/src/starboard/shared/win32/socket_create.cc b/src/starboard/shared/win32/socket_create.cc
index bc3a89c..561967f 100644
--- a/src/starboard/shared/win32/socket_create.cc
+++ b/src/starboard/shared/win32/socket_create.cc
@@ -114,5 +114,6 @@
     return kSbSocketInvalid;
   }
 
-  return new SbSocketPrivate(address_type, protocol, socket_handle);
+  return new SbSocketPrivate(address_type, protocol, socket_handle,
+                             SbSocketPrivate::BindTarget::kUnbound);
 }
diff --git a/src/starboard/shared/win32/socket_get_interface_address.cc b/src/starboard/shared/win32/socket_get_interface_address.cc
index a8f8b04..7b4118a 100644
--- a/src/starboard/shared/win32/socket_get_interface_address.cc
+++ b/src/starboard/shared/win32/socket_get_interface_address.cc
@@ -135,7 +135,7 @@
       address_length_bytes = sbwin32::kAddressLengthIpv6;
       break;
     default:
-      SB_NOTREACHED() << "Invalid address type.";
+      SB_NOTREACHED() << "Invalid address type: " << address_type;
       return false;
   }
 
diff --git a/src/starboard/shared/win32/socket_get_local_address.cc b/src/starboard/shared/win32/socket_get_local_address.cc
index d49d5b0..e4a1bf9 100644
--- a/src/starboard/shared/win32/socket_get_local_address.cc
+++ b/src/starboard/shared/win32/socket_get_local_address.cc
@@ -17,6 +17,7 @@
 #include <winsock2.h>
 
 #include "starboard/log.h"
+#include "starboard/memory.h"
 #include "starboard/shared/win32/socket_internal.h"
 
 namespace sbwin32 = starboard::shared::win32;
@@ -26,6 +27,25 @@
     return false;
   }
 
+  // winsock2 considers calling getsockname() on unbound sockets to be an error.
+  // Therefore, SbSocketListen() will call SbSocketBind().
+  if (socket->bound_to == SbSocketPrivate::BindTarget::kUnbound) {
+    out_address->type = socket->address_type;
+    switch (socket->address_type) {
+      case kSbSocketAddressTypeIpv4:
+        SbMemorySet(out_address->address, 0, sbwin32::kAddressLengthIpv4);
+        out_address->port = 0;
+        return true;
+      case kSbSocketAddressTypeIpv6:
+        SbMemorySet(out_address->address, 0, sbwin32::kAddressLengthIpv6);
+        out_address->port = 0;
+        return true;
+      default:
+        SB_NOTREACHED() << "Invalid address type: " << socket->address_type;
+        return false;
+    }
+  }
+
   SB_DCHECK(socket->socket_handle != INVALID_SOCKET);
   sbwin32::SockAddr sock_addr;
   int result = getsockname(socket->socket_handle, sock_addr.sockaddr(),
diff --git a/src/starboard/shared/win32/socket_internal.h b/src/starboard/shared/win32/socket_internal.h
index 3a92e18..ce32fcf 100644
--- a/src/starboard/shared/win32/socket_internal.h
+++ b/src/starboard/shared/win32/socket_internal.h
@@ -24,14 +24,23 @@
 #include "starboard/types.h"
 
 struct SbSocketPrivate {
+  enum struct BindTarget {
+    kUnbound = 0,
+    kAny = 1,
+    kOther = 2,
+    kAccepted = 3,
+  };
+
   SbSocketPrivate(SbSocketAddressType address_type,
                   SbSocketProtocol protocol,
-                  SOCKET fd)
+                  SOCKET handle,
+                  BindTarget bound_to)
       : address_type(address_type),
         protocol(protocol),
-        socket_handle(fd),
+        socket_handle(handle),
         error(kSbSocketOk),
-        waiter(kSbSocketWaiterInvalid) {}
+        waiter(kSbSocketWaiterInvalid),
+        bound_to(bound_to) {}
   ~SbSocketPrivate() {}
 
   // The address domain of this socket, IPv4 or IPv6.
@@ -48,6 +57,8 @@
 
   // The waiter this socket is registered with, or kSbSocketWaiterInvalid.
   SbSocketWaiter waiter;
+
+  BindTarget bound_to;
 };
 
 namespace starboard {
diff --git a/src/starboard/shared/win32/socket_listen.cc b/src/starboard/shared/win32/socket_listen.cc
index fb8de43..96f28fb 100644
--- a/src/starboard/shared/win32/socket_listen.cc
+++ b/src/starboard/shared/win32/socket_listen.cc
@@ -27,12 +27,28 @@
   }
 
   SB_DCHECK(socket->socket_handle != INVALID_SOCKET);
+
+  // Under winsock, a socket must be bound before we can listen on it.
+  if (socket->bound_to == SbSocketPrivate::BindTarget::kUnbound) {
+    // By listening on ::, we can accept both IPv4 and IPv6 connections.
+    SbSocketAddress any_address = {0};
+    any_address.type = socket->address_type;
+    if (SbSocketBind(socket, &any_address) != kSbSocketOk) {
+      SB_DLOG(ERROR) << "Unable to bind a socket during SbListen.";
+      return (socket->error = kSbSocketErrorFailed);
+    }
+
+    socket->bound_to = SbSocketPrivate::BindTarget::kAny;
+  }
+
   // TODO: Determine if we need to specify a > 0 backlog. It can go up to
   // SOMAXCONN according to the documentation. Several places in chromium
   // specify the literal "10" with the comment "maybe dont allow any backlog?"
   int result = listen(socket->socket_handle, 0);
   if (result == SOCKET_ERROR) {
-    return (socket->error = sbwin32::TranslateSocketErrorStatus(result));
+    int last_error = WSAGetLastError();
+    SB_LOG(ERROR) << "listen() failed with last_error = " << last_error;
+    return (socket->error = sbwin32::TranslateSocketErrorStatus(last_error));
   }
 
   return (socket->error = kSbSocketOk);
diff --git a/src/starboard/shared/win32/thread_create.cc b/src/starboard/shared/win32/thread_create.cc
index 5220aad..a579c0b 100644
--- a/src/starboard/shared/win32/thread_create.cc
+++ b/src/starboard/shared/win32/thread_create.cc
@@ -20,13 +20,43 @@
 #include "starboard/log.h"
 #include "starboard/once.h"
 #include "starboard/shared/win32/thread_private.h"
+#include "starboard/shared/win32/wchar_utils.h"
 
 using starboard::shared::win32::GetThreadSubsystemSingleton;
 using starboard::shared::win32::SbThreadPrivate;
 using starboard::shared::win32::ThreadSubsystemSingleton;
+using starboard::shared::win32::wchar_tToUTF8;
 
 namespace {
 
+void ResetWinError() {
+  SetLastError(0);
+}
+
+// Checks for system errors and logs a human-readable error if GetLastError()
+// returns an error code. Noops on non-debug builds.
+void DebugLogWinError() {
+#if defined(_DEBUG)
+  DWORD error_code = GetLastError();
+  if (!error_code)
+    return;
+
+  LPWSTR error_message;
+  HRESULT hresult = HRESULT_FROM_WIN32(error_code);
+  int message_size = FormatMessage(
+      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
+          FORMAT_MESSAGE_IGNORE_INSERTS,
+      nullptr,  // Unused with FORMAT_MESSAGE_FROM_SYSTEM.
+      hresult, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+      (LPTSTR)&error_message,
+      0,  // Minimum size for output buffer.
+      nullptr);
+  SB_DCHECK(message_size);
+  SB_LOG(ERROR) << wchar_tToUTF8(error_message);
+  LocalFree(error_message);
+#endif  // defined(_DEBUG)
+}
+
 class ThreadCreateInfo {
  public:
   SbThreadPrivate thread_private_;
@@ -83,11 +113,29 @@
   return 0;
 }
 
+int SbThreadPriorityToWin32Priority(SbThreadPriority priority) {
+  switch (priority) {
+    case kSbThreadPriorityLowest:
+      return THREAD_PRIORITY_LOWEST;
+    case kSbThreadPriorityLow:
+      return THREAD_PRIORITY_BELOW_NORMAL;
+    case kSbThreadPriorityNormal:
+    case kSbThreadNoPriority:
+      return THREAD_PRIORITY_NORMAL;
+    case kSbThreadPriorityHigh:
+      return THREAD_PRIORITY_ABOVE_NORMAL;
+    case kSbThreadPriorityHighest:
+    case kSbThreadPriorityRealTime:
+      return THREAD_PRIORITY_HIGHEST;
+  }
+  SB_NOTREACHED() << "Invalid priority " << priority;
+  return 0;
+}
 }  // namespace
 
 SbThread SbThreadCreate(int64_t stack_size,
-                        SbThreadPriority /*priority*/,
-                        SbThreadAffinity /*affinity*/,
+                        SbThreadPriority priority,
+                        SbThreadAffinity affinity,
                         bool joinable,
                         const char* name,
                         SbThreadEntryPoint entry_point,
@@ -110,8 +158,26 @@
   uintptr_t handle =
       _beginthreadex(NULL, static_cast<unsigned int>(stack_size),
                      ThreadTrampoline, info, CREATE_SUSPENDED, NULL);
-
+  SB_DCHECK(handle);
   info->thread_private_.handle_ = reinterpret_cast<HANDLE>(handle);
+  ResetWinError();
+  if (affinity != kSbThreadNoAffinity &&
+      !SetThreadAffinityMask(info->thread_private_.handle_,
+                             static_cast<DWORD_PTR>(affinity)) &&
+      !GetLastError()) {
+    SB_LOG(ERROR) << "Failed to set affinity for thread " << (name ? name : "")
+                  << ". Attempted to set affinity to: " << affinity;
+    DebugLogWinError();
+  }
+  ResetWinError();
+  if (priority != kSbThreadNoPriority &&
+      !SetThreadPriority(info->thread_private_.handle_,
+                         SbThreadPriorityToWin32Priority(priority)) &&
+      !GetLastError()) {
+    SB_LOG(ERROR) << "Failed to set priority for thread " << (name ? name : "")
+                  << " to " << priority;
+    DebugLogWinError();
+  }
 
   ResumeThread(info->thread_private_.handle_);
 
diff --git a/src/starboard/shared/win32/thread_private.h b/src/starboard/shared/win32/thread_private.h
index 4bacbd8..9bdf0d6 100644
--- a/src/starboard/shared/win32/thread_private.h
+++ b/src/starboard/shared/win32/thread_private.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef STARBOARD_WIN32_THREAD_PRIVATE_H_
-#define STARBOARD_WIN32_THREAD_PRIVATE_H_
+#ifndef STARBOARD_SHARED_WIN32_THREAD_PRIVATE_H_
+#define STARBOARD_SHARED_WIN32_THREAD_PRIVATE_H_
 
 #include <windows.h>
 #include <string>
@@ -106,4 +106,4 @@
 }  // namespace shared
 }  // namespace starboard
 
-#endif  // STARBOARD_WIN32_THREAD_PRIVATE_H_
+#endif  // STARBOARD_SHARED_WIN32_THREAD_PRIVATE_H_
diff --git a/src/starboard/thread.h b/src/starboard/thread.h
index f642f28..c6d17ab 100644
--- a/src/starboard/thread.h
+++ b/src/starboard/thread.h
@@ -65,7 +65,7 @@
   //
   // For platforms where that is not offered, or otherwise not meaningful, this
   // will just be the highest priority available in the platform's scheme, which
-  // may be the same as kThreadPriority_Highest.
+  // may be the same as kSbThreadPriorityHighest.
   kSbThreadPriorityRealTime,
 
   // Well-defined constant value to mean "no priority."  This means to use the
diff --git a/src/starboard/tools/platform.py b/src/starboard/tools/platform.py
index e763abe..7c760f8 100644
--- a/src/starboard/tools/platform.py
+++ b/src/starboard/tools/platform.py
@@ -65,9 +65,15 @@
   """Information about a specific starboard port."""
 
   @classmethod
-  def EnumeratePorts(cls, root_path):
+  def EnumeratePorts(cls, root_path, exclusion_set = None):
     """Generator that iterates over starboard ports found under |path|."""
-    for current_path, _, filenames in os.walk(root_path):
+    if not exclusion_set:
+      exclusion_set = set()
+    for current_path, directories, filenames in os.walk(root_path):
+      # Don't walk into any directories in the exclusion set.
+      directories[:] = (x for x in directories
+                        if os.path.join(current_path, x) not in exclusion_set)
+      # Determine if the current directory is a valid port directory.
       if _IsValidPortFilenameList(current_path, filenames):
         if current_path == root_path:
           logging.warning('Found port at search path root: %s', current_path)
diff --git a/src/starboard/win/console/atomic_public.h b/src/starboard/win/console/atomic_public.h
new file mode 100644
index 0000000..51f81a1
--- /dev/null
+++ b/src/starboard/win/console/atomic_public.h
@@ -0,0 +1,20 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_WIN_CONSOLE_ATOMIC_PUBLIC_H_
+#define STARBOARD_WIN_CONSOLE_ATOMIC_PUBLIC_H_
+
+#include "starboard/shared/win32/atomic_public.h"
+
+#endif  // STARBOARD_WIN_CONSOLE_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/win/console/configuration_public.h b/src/starboard/win/console/configuration_public.h
new file mode 100644
index 0000000..324627f
--- /dev/null
+++ b/src/starboard/win/console/configuration_public.h
@@ -0,0 +1,23 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Other source files should never include this header directly, but should
+// include the generic "starboard/configuration.h" instead.
+
+#ifndef STARBOARD_WIN_CONSOLE_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_WIN_CONSOLE_CONFIGURATION_PUBLIC_H_
+
+#include "starboard/win/shared/configuration_public.h"
+
+#endif  // STARBOARD_WIN_CONSOLE_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/win/console/gyp_configuration.gypi b/src/starboard/win/console/gyp_configuration.gypi
new file mode 100644
index 0000000..ef90ebd
--- /dev/null
+++ b/src/starboard/win/console/gyp_configuration.gypi
@@ -0,0 +1,94 @@
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+  'variables': {
+    'javascript_engine': 'mozjs',
+    'cobalt_enable_jit': 0,
+  },
+  'includes': [
+    '../shared/gyp_configuration.gypi',
+  ],
+  'target_defaults': {
+    'default_configuration': 'win-console_debug',
+    'configurations': {
+      'win-console_debug': {
+        'inherit_from': ['debug_base', 'msvs_base'],
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'Optimization': '0',
+            'BasicRuntimeChecks': '3', # Check stack frame validity and check for uninitialized variables at run time.
+            'AdditionalOptions': [
+              '/MDd', # Use debug multithreaded library.
+              '/GS',
+            ],
+          },
+          'VCLinkerTool': {
+            'AdditionalDependencies': ['dbghelp.lib'],
+            'LinkIncremental': '2',  # INCREMENTAL:YES
+          },
+        },
+      },
+      'win-console_devel': {
+        'inherit_from': ['devel_base', 'msvs_base'],
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'Optimization': '2',
+            'AdditionalOptions': [
+              '/MDd', # Use debug multithreaded library.
+              '/GS',
+            ],
+          },
+          'VCLinkerTool': {
+            'AdditionalDependencies': ['dbghelp.lib'],
+            'LinkIncremental': '2',  # INCREMENTAL:YES
+          },
+        },
+      },
+      'win-console_qa': {
+        'inherit_from': ['qa_base', 'msvs_base'],
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'Optimization': '2',
+            'AdditionalOptions': [
+              '/MD', # Use release multithreaded library.
+            ],
+          },
+          'VCLinkerTool': {
+            'AdditionalDependencies': ['dbghelp.lib'],
+            'LinkIncremental': '1',  # INCREMENTAL:NO
+            'OptimizeReferences' : '2',  # OPT:REF
+            'EnableCOMDATFolding' : '2',  # OPT:ICF
+          },
+        },
+      },
+      'win-console_gold': {
+        'inherit_from': ['gold_base', 'msvs_base'],
+         'msvs_settings': {
+          'VCCLCompilerTool': {
+            'Optimization': '2',
+            'AdditionalOptions': [
+              '/MD', # Use release multithreaded library.
+            ],
+          },
+          'VCLinkerTool': {
+            'LinkIncremental': '1',  # INCREMENTAL:NO
+            'OptimizeReferences' : '2',  # OPT:REF
+            'EnableCOMDATFolding' : '2',  # OPT:ICF
+          },
+        },
+      },
+    },  # end of configurations
+  },
+}
diff --git a/src/starboard/win/console/gyp_configuration.py b/src/starboard/win/console/gyp_configuration.py
new file mode 100644
index 0000000..68f835a
--- /dev/null
+++ b/src/starboard/win/console/gyp_configuration.py
@@ -0,0 +1,33 @@
+# Copyright 2016 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+import os
+import sys
+
+# Import the shared win platform configuration.
+sys.path.append(
+    os.path.realpath(
+        os.path.join(
+            os.path.dirname(__file__), os.pardir,
+            os.pardir, 'shared', 'win32')))
+import gyp_configuration
+
+
+def CreatePlatformConfig():
+  try:
+    return gyp_configuration.PlatformConfig('win-console')
+  except RuntimeError as e:
+    logging.critical(e)
+    return None
diff --git a/src/starboard/win/console/starboard_platform.gyp b/src/starboard/win/console/starboard_platform.gyp
new file mode 100644
index 0000000..bcfd1cb
--- /dev/null
+++ b/src/starboard/win/console/starboard_platform.gyp
@@ -0,0 +1,26 @@
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+{
+  'includes': [ '../shared/starboard_platform.gypi' ],
+  'sources': [
+    'atomic_public.h',
+    'configuration_public.h',
+    'thread_types_public.h',
+  ],
+  'variables': {
+    'starboard_platform_dependent_sources': [
+      '../shared/system_get_path.cc',
+    ],
+  },
+}
diff --git a/src/starboard/win/console/starboard_platform_tests.gyp b/src/starboard/win/console/starboard_platform_tests.gyp
new file mode 100644
index 0000000..93f812b
--- /dev/null
+++ b/src/starboard/win/console/starboard_platform_tests.gyp
@@ -0,0 +1,41 @@
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+{
+  'targets': [
+    {
+      'target_name': 'starboard_platform_tests',
+      'type': '<(gtest_target_type)',
+      'sources': [
+        '<(DEPTH)/starboard/common/test_main.cc',
+        '<(DEPTH)/starboard/shared/starboard/media/mime_type_test.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/starboard/starboard.gyp:starboard',
+        '<(DEPTH)/testing/gmock.gyp:gmock',
+        '<(DEPTH)/testing/gtest.gyp:gtest',
+      ],
+    },
+    {
+      'target_name': 'starboard_platform_tests_deploy',
+      'type': 'none',
+      'dependencies': [
+        '<(DEPTH)/<(starboard_path)/starboard_platform_tests.gyp:starboard_platform_tests',
+      ],
+      'variables': {
+        'executable_name': 'starboard_platform_tests',
+      },
+      'includes': [ '../../build/deploy.gypi' ],
+    },
+  ],
+}
diff --git a/src/starboard/win/console/thread_types_public.h b/src/starboard/win/console/thread_types_public.h
new file mode 100644
index 0000000..b8cc69e
--- /dev/null
+++ b/src/starboard/win/console/thread_types_public.h
@@ -0,0 +1,22 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Includes threading primitive types and initializers.
+
+#ifndef STARBOARD_WIN_CONSOLE_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_WIN_CONSOLE_THREAD_TYPES_PUBLIC_H_
+
+#include "starboard/shared/win32/thread_types_public.h"
+
+#endif  // STARBOARD_WIN_CONSOLE_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/win/shared/configuration_public.h b/src/starboard/win/shared/configuration_public.h
new file mode 100644
index 0000000..94eb71c
--- /dev/null
+++ b/src/starboard/win/shared/configuration_public.h
@@ -0,0 +1,466 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Other source files should never include this header directly, but should
+// include the generic "starboard/configuration.h" instead.
+
+#ifndef STARBOARD_WIN_SHARED_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_WIN_SHARED_CONFIGURATION_PUBLIC_H_
+
+// The API version implemented by this platform. This will generally be set to
+// the current value of SB_MAXIMUM_API_VERSION at the time of implementation.
+#define SB_API_VERSION SB_EXPERIMENTAL_API_VERSION
+
+// --- Architecture Configuration --------------------------------------------
+
+// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be
+// automatically set based on this.
+#define SB_IS_BIG_ENDIAN 0
+
+// Whether the current platform is an ARM architecture.
+#define SB_IS_ARCH_ARM 0
+
+// Whether the current platform is a MIPS architecture.
+#define SB_IS_ARCH_MIPS 0
+
+// Whether the current platform is a PPC architecture.
+#define SB_IS_ARCH_PPC 0
+
+// Whether the current platform is an x86 architecture.
+#define SB_IS_ARCH_X86 1
+
+#define SB_IS_32_BIT 0
+#define SB_IS_64_BIT 1
+
+#define SB_HAS_32_BIT_LONG 1
+#define SB_HAS_32_BIT_POINTERS 0
+
+#define SB_HAS_64_BIT_LONG 0
+#define SB_HAS_64_BIT_POINTERS 1
+
+// Configuration parameters that allow the application to make some general
+// compile-time decisions with respect to the the number of cores likely to be
+// available on this platform. For a definitive measure, the application should
+// still call SbSystemGetNumberOfProcessors at runtime.
+
+// Whether the current platform is expected to have many cores (> 6), or a
+// wildly varying number of cores.
+#define SB_HAS_MANY_CORES 0
+
+// Whether the current platform is expected to have exactly 1 core.
+#define SB_HAS_1_CORE 0
+
+// Whether the current platform is expected to have exactly 2 cores.
+#define SB_HAS_2_CORES 0
+
+// Whether the current platform is expected to have exactly 4 cores.
+#define SB_HAS_4_CORES 1
+
+// Whether the current platform is expected to have exactly 6 cores.
+#define SB_HAS_6_CORES 0
+
+// Whether the current platform supports thread priorities.
+#define SB_HAS_THREAD_PRIORITY_SUPPORT 1
+
+// Whether the current platform's thread scheduler will automatically balance
+// threads between cores, as opposed to systems where threads will only ever run
+// on the specifically pinned core.
+#define SB_HAS_CROSS_CORE_SCHEDULER 1
+
+// Some platforms will not align variables on the stack with an alignment
+// greater than 16 bytes. Platforms where this is the case should define the
+// following quirk.
+#undef SB_HAS_QUIRK_DOES_NOT_STACK_ALIGN_OVER_16_BYTES
+
+// --- System Header Configuration -------------------------------------------
+
+// Any system headers listed here that are not provided by the platform will be
+// emulated in starboard/types.h.
+
+// Whether the current platform provides the standard header stdarg.h.
+#define SB_HAS_STDARG_H 0
+
+// Whether the current platform provides the standard header stdbool.h.
+#define SB_HAS_STDBOOL_H 0
+
+// Whether the current platform provides the standard header stddef.h.
+#define SB_HAS_STDDEF_H 1
+
+// Whether the current platform provides the standard header stdint.h.
+#define SB_HAS_STDINT_H 1
+
+// Whether the current platform provides the standard header inttypes.h.
+#define SB_HAS_INTTYPES_H 1
+
+// Whether the current platform provides the standard header wchar.h.
+#define SB_HAS_WCHAR_H 1
+
+// Whether the current platform provides the standard header limits.h.
+#define SB_HAS_LIMITS_H 1
+
+// Whether the current platform provides the standard header float.h.
+#define SB_HAS_FLOAT_H 1
+
+// Whether the current platform provides ssize_t.
+#define SB_HAS_SSIZE_T 0
+
+// Whether the current platform has microphone supported.
+#define SB_HAS_MICROPHONE 0
+
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
+// Whether the current platform has speech recognizer.
+#define SB_HAS_SPEECH_RECOGNIZER 0
+
+#if !defined(__WCHAR_MAX__)
+#include <wchar.h>
+#define __WCHAR_MAX__ WCHAR_MAX
+#endif
+
+// Type detection for wchar_t.
+#if defined(__WCHAR_MAX__) && \
+    (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
+#define SB_IS_WCHAR_T_UTF32 1
+#elif defined(__WCHAR_MAX__) && \
+    (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
+#define SB_IS_WCHAR_T_UTF16 1
+#endif
+
+// Chrome only defines these two if ARMEL or MIPSEL are defined.
+#if defined(__ARMEL__)
+// Chrome has an exclusion for iOS here, we should too when we support iOS.
+#define SB_IS_WCHAR_T_UNSIGNED 1
+#elif defined(__MIPSEL__)
+#define SB_IS_WCHAR_T_SIGNED 1
+#endif
+
+// --- Compiler Configuration ------------------------------------------------
+
+// The platform's annotation for forcing a C function to be inlined.
+//   https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx#Anchor_1
+#define SB_C_FORCE_INLINE __forceinline
+
+// The platform's annotation for marking a C function as suggested to be
+// inlined.
+#define SB_C_INLINE inline
+
+// The platform's annotation for marking a C function as forcibly not
+// inlined.
+#define SB_C_NOINLINE __declspec(noinline)
+
+// The platform's annotation for marking a symbol as exported outside of the
+// current shared library.
+#define SB_EXPORT_PLATFORM __attribute__((visibility("default")))
+
+// The platform's annotation for marking a symbol as imported from outside of
+// the current linking unit.
+#define SB_IMPORT_PLATFORM
+
+// On some platforms the __GNUC__ is defined even though parts of the
+// functionality are missing. Setting this to non-zero allows disabling missing
+// functionality encountered.
+#undef SB_HAS_QUIRK_COMPILER_SAYS_GNUC_BUT_ISNT
+
+// On some compilers, the frontend has a quirk such that #ifdef cannot
+// correctly detect __has_feature is defined, and an example error you get is:
+#undef SB_HAS_QUIRK_HASFEATURE_NOT_DEFINED_BUT_IT_IS
+
+// --- Extensions Configuration ----------------------------------------------
+
+// GCC/Clang doesn't define a long long hash function, except for Android and
+// Game consoles.
+#define SB_HAS_LONG_LONG_HASH 1
+
+// GCC/Clang doesn't define a string hash function, except for Game Consoles.
+#define SB_HAS_STRING_HASH 1
+
+// Desktop Linux needs a using statement for the hash functions.
+#define SB_HAS_HASH_USING 1
+
+// Set this to 1 if hash functions for custom types can be defined as a
+// hash_value() function. Otherwise, they need to be placed inside a
+// partially-specified hash struct template with an operator().
+#define SB_HAS_HASH_VALUE 1
+
+// Set this to 1 if use of hash_map or hash_set causes a deprecation warning
+// (which then breaks the build).
+#define SB_HAS_HASH_WARNING 1
+#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
+
+// The location to include hash_map on this platform.
+#define SB_HASH_MAP_INCLUDE <hash_map>
+
+// C++'s hash_map and hash_set are often found in different namespaces depending
+// on the compiler.
+#define SB_HASH_NAMESPACE stdext
+
+// The location to include hash_set on this platform.
+#define SB_HASH_SET_INCLUDE <hash_set>
+
+// Define this to how this platform copies varargs blocks.
+#define SB_VA_COPY(dest, source) va_copy(dest, source)
+
+// --- Filesystem Configuration ----------------------------------------------
+
+// The current platform's maximum length of the name of a single directory
+// entry, not including the absolute path.
+#define SB_FILE_MAX_NAME 260
+
+// The current platform's maximum length of an absolute path.
+#define SB_FILE_MAX_PATH 4096
+
+// The current platform's maximum number of files that can be opened at the
+// same time by one process.
+#define SB_FILE_MAX_OPEN 64
+
+// The current platform's file path component separator character. This is the
+// character that appears after a directory in a file path. For example, the
+// absolute canonical path of the file "/path/to/a/file.txt" uses '/' as a path
+// component separator character.
+#define SB_FILE_SEP_CHAR '\\'
+
+// The current platform's alternate file path component separator character.
+// This is like SB_FILE_SEP_CHAR, except if your platform supports an alternate
+// character, then you can place that here. For example, on windows machines,
+// the primary separator character is probably '\', but the alternate is '/'.
+#define SB_FILE_ALT_SEP_CHAR '/'
+
+// The current platform's search path component separator character. When
+// specifying an ordered list of absolute paths of directories to search for a
+// given reason, this is the character that appears between entries. For
+// example, the search path of "/etc/search/first:/etc/search/second" uses ':'
+// as a search path component separator character.
+#define SB_PATH_SEP_CHAR ':'
+
+// The string form of SB_FILE_SEP_CHAR.
+#define SB_FILE_SEP_STRING "\\"
+
+// The string form of SB_FILE_ALT_SEP_CHAR.
+#define SB_FILE_ALT_SEP_STRING "/"
+
+// The string form of SB_PATH_SEP_CHAR.
+#define SB_PATH_SEP_STRING ":"
+
+// On some platforms the file system stores access times at a coarser
+// granularity than other times. When this quirk is defined, we assume the
+// access time is of 1 day precision.
+#undef SB_HAS_QUIRK_FILESYSTEM_COARSE_ACCESS_TIME
+
+// --- Memory Configuration --------------------------------------------------
+
+// The memory page size, which controls the size of chunks on memory that
+// allocators deal with, and the alignment of those chunks. This doesn't have to
+// be the hardware-defined physical page size, but it should be a multiple of
+// it.
+#define SB_MEMORY_PAGE_SIZE 4096
+
+// Whether this platform has and should use an MMAP function to map physical
+// memory to the virtual address space.
+#define SB_HAS_MMAP 1
+
+// Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is
+// required for platforms that want to JIT.
+#define SB_CAN_MAP_EXECUTABLE_MEMORY 0
+
+// Whether this platform has and should use an growable heap (e.g. with sbrk())
+// to map physical memory to the virtual address space.
+#define SB_HAS_VIRTUAL_REGIONS 0
+
+// Specifies the alignment for IO Buffers, in bytes. Some low-level network APIs
+// may require buffers to have a specific alignment, and this is the place to
+// specify that.
+#define SB_NETWORK_IO_BUFFER_ALIGNMENT 16
+
+// Determines the alignment that allocations should have on this platform.
+#define SB_MALLOC_ALIGNMENT ((size_t)16U)
+
+// Determines the threshhold of allocation size that should be done with mmap
+// (if available), rather than allocated within the core heap.
+#define SB_DEFAULT_MMAP_THRESHOLD ((size_t)(256 * 1024U))
+
+// Defines the path where memory debugging logs should be written to.
+#define SB_MEMORY_LOG_PATH "/tmp/starboard"
+
+// --- Thread Configuration --------------------------------------------------
+
+// Defines the maximum number of simultaneous threads for this platform. Some
+// platforms require sharing thread handles with other kinds of system handles,
+// like mutexes, so we want to keep this managable.
+#define SB_MAX_THREADS 90
+
+// The maximum number of thread local storage keys supported by this platform.
+#define SB_MAX_THREAD_LOCAL_KEYS 512
+
+// The maximum length of the name for a thread, including the NULL-terminator.
+#define SB_MAX_THREAD_NAME_LENGTH 16;
+
+// --- Graphics Configuration ------------------------------------------------
+
+// Specifies whether this platform supports a performant accelerated blitter
+// API. The basic requirement is a scaled, clipped, alpha-blended blit.
+#define SB_HAS_BLITTER 0
+
+// Specifies the preferred byte order of color channels in a pixel. Refer to
+// starboard/configuration.h for the possible values. EGL/GLES platforms should
+// generally prefer a byte order of RGBA, regardless of endianness.
+#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_RGBA
+
+// Indicates whether or not the given platform supports bilinear filtering.
+// This can be checked to enable/disable renderer tests that verify that this is
+// working properly.
+#define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
+
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 0
+
+// Whether the current platform should frequently flip its display buffer.  If
+// this is not required (i.e. SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is set to
+// 0), then optimizations are enabled so the display buffer is not flipped if
+// the scene hasn't changed.
+#define SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER 0
+
+#define SB_HAS_VIRTUAL_REALITY 0
+
+// --- Media Configuration ---------------------------------------------------
+
+// Specifies whether this platform has support for a possibly-decrypting
+// elementary stream player for at least H.264/AAC (and AES-128-CTR, if
+// decrypting). A player is responsible for ingesting an audio and video
+// elementary stream, optionally-encrypted, and ultimately producing
+// synchronized audio/video. If a player is defined, it must choose one of the
+// supported composition methods below.
+#define SB_HAS_PLAYER 1
+
+#if SB_API_VERSION < 4
+// Specifies whether this platform's player will produce an OpenGL texture that
+// the client must draw every frame with its graphics rendering. It may be that
+// we get a texture handle, but cannot perform operations like GlReadPixels on
+// it if it is DRM-protected.
+#define SB_IS_PLAYER_PRODUCING_TEXTURE 0
+
+// Specifies whether this platform's player is composited with a formal
+// compositor, where the client must specify how video is to be composited into
+// the graphicals scene.
+#define SB_IS_PLAYER_COMPOSITED 0
+
+// Specifies whether this platform's player uses a "punch-out" model, where
+// video is rendered to the far background, and the graphics plane is
+// automatically composited on top of the video by the platform. The client must
+// punch an alpha hole out of the graphics plane for video to show through.  In
+// this case, changing the video bounds must be tightly synchronized between the
+// player and the graphics plane.
+#define SB_IS_PLAYER_PUNCHED_OUT 1
+#endif  // SB_API_VERSION < 4
+
+// After a seek is triggerred, the default behavior is to append video frames
+// from the last key frame before the seek time and append audio frames from the
+// seek time because usually all audio frames are key frames.  On platforms that
+// cannot decode video frames without displaying them, this will cause the video
+// being played without audio for several seconds after seeking.  When the
+// following macro is defined, the app will append audio frames start from the
+// timestamp that is before the timestamp of the video key frame being appended.
+#undef SB_HAS_QUIRK_SEEK_TO_KEYFRAME
+
+// dlmalloc will use the ffs intrinsic if available.  Platforms on which this is
+// not available should define the following quirk.
+#undef SB_HAS_QUIRK_NO_FFS
+
+#if SB_API_VERSION >= 4
+
+// The maximum audio bitrate the platform can decode.  The following value
+// equals to 5M bytes per seconds which is more than enough for compressed
+// audio.
+#define SB_MEDIA_MAX_AUDIO_BITRATE_IN_BITS_PER_SECOND (40 * 1024 * 1024)
+
+// The maximum video bitrate the platform can decode.  The following value
+// equals to 25M bytes per seconds which is more than enough for compressed
+// video.
+#define SB_MEDIA_MAX_VIDEO_BITRATE_IN_BITS_PER_SECOND (200 * 1024 * 1024)
+
+#endif  // SB_API_VERSION >= 4
+
+// Specifies whether this platform has webm/vp9 support.  This should be set to
+// non-zero on platforms with webm/vp9 support.
+#define SB_HAS_MEDIA_WEBM_VP9_SUPPORT 0
+
+// Specifies the stack size for threads created inside media stack.  Set to 0 to
+// use the default thread stack size.  Set to non-zero to explicitly set the
+// stack size for media stack threads.
+#define SB_MEDIA_THREAD_STACK_SIZE 0U
+
+// --- Decoder-only Params ---
+
+// Specifies how media buffers must be aligned on this platform as some
+// decoders may have special requirement on the alignment of buffers being
+// decoded.
+#define SB_MEDIA_BUFFER_ALIGNMENT 128U
+
+// Specifies how video frame buffers must be aligned on this platform.
+#define SB_MEDIA_VIDEO_FRAME_ALIGNMENT 256U
+
+// The encoded video frames are compressed in different ways, so their decoding
+// time can vary a lot.  Occasionally a single frame can take longer time to
+// decode than the average time per frame.  The player has to cache some frames
+// to account for such inconsistency.  The number of frames being cached are
+// controlled by SB_MEDIA_MAXIMUM_VIDEO_PREROLL_FRAMES and
+// SB_MEDIA_MAXIMUM_VIDEO_FRAMES.
+//
+// Specify the number of video frames to be cached before the playback starts.
+// Note that setting this value too large may increase the playback start delay.
+#define SB_MEDIA_MAXIMUM_VIDEO_PREROLL_FRAMES 4
+
+// Specify the number of video frames to be cached during playback.  A large
+// value leads to more stable fps but also causes the app to use more memory.
+#define SB_MEDIA_MAXIMUM_VIDEO_FRAMES 12
+
+// --- Network Configuration -------------------------------------------------
+
+// Specifies whether this platform supports IPV6.
+#define SB_HAS_IPV6 1
+
+// Specifies whether this platform supports pipe.
+#define SB_HAS_PIPE 1
+
+// --- Tuneable Parameters ---------------------------------------------------
+
+// Specifies the network receive buffer size in bytes, set via
+// SbSocketSetReceiveBufferSize().
+//
+// Setting this to 0 indicates that SbSocketSetReceiveBufferSize() should
+// not be called. Use this for OSs (such as Linux) where receive buffer
+// auto-tuning is better.
+//
+// On some platforms, this may affect max TCP window size which may
+// dramatically affect throughput in the presence of latency.
+//
+// If your platform does not have a good TCP auto-tuning mechanism,
+// a setting of (128 * 1024) here is recommended.
+#define SB_NETWORK_RECEIVE_BUFFER_SIZE (0)
+
+// --- User Configuration ----------------------------------------------------
+
+// The maximum number of users that can be signed in at the same time.
+#define SB_USER_MAX_SIGNED_IN 1
+
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 0
+
+// --- Platform Specific Audits ----------------------------------------------
+
+#endif  // STARBOARD_WIN_SHARED_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/win/shared/gyp_configuration.gypi b/src/starboard/win/shared/gyp_configuration.gypi
new file mode 100644
index 0000000..b9fa447
--- /dev/null
+++ b/src/starboard/win/shared/gyp_configuration.gypi
@@ -0,0 +1,286 @@
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+{
+  'variables': {
+    'target_arch': 'x64',
+    'target_os': 'win',
+
+    # Use a stub rasterizer and graphical setup.
+    'rasterizer_type': 'stub',
+
+    # Link with angle
+    'gl_type': 'angle',
+
+    'cobalt_media_source_2016': 1,
+
+    # Define platform specific compiler and linker flags.
+    # Refer to base.gypi for a list of all available variables.
+    'compiler_flags_host': [
+      '-O2',
+    ],
+    'compiler_flags': [
+      # We'll pretend not to be Linux, but Starboard instead.
+      '-U__linux__',
+    ],
+    'linker_flags': [
+    ],
+    'compiler_flags_debug': [
+      '-frtti',
+      '-O0',
+    ],
+    'compiler_flags_devel': [
+      '-frtti',
+      '-O2',
+    ],
+    'compiler_flags_qa': [
+      '-fno-rtti',
+      '-O2',
+      '-gline-tables-only',
+    ],
+    'compiler_flags_gold': [
+      '-fno-rtti',
+      '-O2',
+      '-gline-tables-only',
+    ],
+    'conditions': [
+      ['cobalt_fastbuild==0', {
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'DebugInformationFormat': '3',
+          },
+          'VCLinkerTool': {
+            'GenerateDebugInformation': 'true',
+          },
+        }
+        }],
+    ],
+  },
+
+  'target_defaults': {
+    'configurations': {
+      'msvs_base': {
+        'abstract': 1,
+        'msvs_configuration_attributes': {
+          'OutputDirectory': '<(DEPTH)\\build\\<(build_dir_prefix)$(ConfigurationName)',
+          'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
+          'CharacterSet': '1',
+        },
+        'msvs_system_include_dirs': [
+          '<(windows_sdk_path)/include/<(windows_sdk_version)/shared',
+          '<(windows_sdk_path)/include/<(windows_sdk_version)/ucrt',
+          '<(windows_sdk_path)/include/<(windows_sdk_version)/um',
+          '<(windows_sdk_path)/include/<(windows_sdk_version)/winrt',
+          '<(windows_sdk_path)/include/<(windows_sdk_version)',
+          '<(visual_studio_install_path)/include',
+          '<(visual_studio_install_path)/atlmfc/include',
+        ],
+        'msvs_settings': {
+          'VCLinkerTool': {
+            'AdditionalDependencies': [
+              'windowsapp.lib',
+            ],
+            'AdditionalLibraryDirectories!': [
+              '<(windows_sdk_path)/lib/<(windows_sdk_version)/ucrt/x86',
+              '<(windows_sdk_path)/lib/<(windows_sdk_version)/um/x86',
+              ],
+            'AdditionalLibraryDirectories': [
+              '<(windows_sdk_path)/lib/<(windows_sdk_version)/ucrt/x64',
+              '<(windows_sdk_path)/lib/<(windows_sdk_version)/um/x64',
+              '<(visual_studio_install_path)/lib/x64',
+              ],
+          },
+          'VCLibrarianTool': {
+            'AdditionalLibraryDirectories!': [
+              '<(windows_sdk_path)/lib/<(windows_sdk_version)/ucrt/x86',
+              '<(windows_sdk_path)/lib/<(windows_sdk_version)/um/x86',
+              ],
+            'AdditionalLibraryDirectories': [
+              '<(windows_sdk_path)/lib/<(windows_sdk_version)/ucrt/x64',
+              '<(windows_sdk_path)/lib/<(windows_sdk_version)/um/x64',
+              '<(visual_studio_install_path)/lib/x64',
+              ],
+          },
+        },
+        'msvs_target_platform': 'x64',
+        # Add the default import libs.
+        'conditions': [
+          ['cobalt_fastbuild==0', {
+            'msvs_settings': {
+              'VCCLCompilerTool': {
+                'DebugInformationFormat': '3',
+                'AdditionalOptions': [
+                '/FS',
+                ],
+              },
+              'VCLinkerTool': {
+                'GenerateDebugInformation': 'true',
+              },
+            },
+          }],
+        ],
+      },
+    },
+    'defines': [
+      # Disable suggestions to switch to Microsoft-specific secure CRT.
+      '_CRT_SECURE_NO_WARNINGS',
+      # Disable support for exceptions in STL in order to detect their use
+      # (the use of exceptions is forbidden by Google C++ style guide).
+      '_HAS_EXCEPTIONS=0',
+      '__STDC_FORMAT_MACROS', # so that we get PRI*
+      # Enable GNU extensions to get prototypes like ffsl.
+      #'_GNU_SOURCE=1',
+      'WIN32_LEAN_AND_MEAN',
+      # By defining this, M_PI will get #defined.
+      '_USE_MATH_DEFINES',
+      # min and max collide with std::min and std::max
+      'NOMINMAX',
+      # Conform with C99 spec.
+      '_CRT_STDIO_ISO_WIDE_SPECIFIERS',
+    ],
+    'msvs_settings': {
+      'VCCLCompilerTool': {
+        'ForcedIncludeFiles': [],
+        # Check for buffer overruns.
+        'BufferSecurityCheck': 'true',
+        'Conformance': [
+          # "for" loop's initializer go out of scope after the for loop.
+          'forScope',
+          # wchar_t is treated as a built-in type.
+          'wchar_t',
+        ],
+        # Check for 64-bit portability issues.
+        'Detect64BitPortabilityProblems': 'true',
+        # Disable Microsoft-specific header dependency tracking.
+        # Incremental linker does not support the Windows metadata included
+        # in .obj files compiled with C++/CX support (/ZW).
+        'MinimalRebuild': 'false',
+        # Treat warnings as errors.
+        'WarnAsError': 'false',
+        # Enable some warnings, even those that are disabled by default.
+        # See https://msdn.microsoft.com/en-us/library/23k5d385.aspx
+        'WarningLevel': '3',
+
+        'AdditionalOptions': [
+          '/errorReport:none', # don't send error reports to MS.
+          '/permissive-', # Visual C++ conformance mode.
+          '/FS', # Force sync PDB updates for parallel compile.
+        ],
+      },
+      'VCLinkerTool': {
+        'RandomizedBaseAddress': '2', # /DYNAMICBASE
+        # TODO: SubSystem is hardcoded in
+        # win\sources_template.vcxproj. This will have the exe behave in the
+        # expected way in MSVS: when it's run without debug (Ctrl+F5), it
+        # will pause after finish; when debugging (F5) it will not pause
+        # before the cmd window disappears.
+        # Currently the value is ignored by msvs_makefile.py which generates
+        # the MSVS project files (it's in "data" in GenerateOutput()). Fix
+        # it if we ever need to change SubSystem.
+        'SubSystem': '1', # CONSOLE
+        'TargetMachine': '17', # x86 - 64
+        'AdditionalOptions': [
+          '/WINMD:NO', # Do not generate a WinMD file.
+          '/errorReport:none', # don't send error reports to MS.
+        ],
+      },
+      'VCLibrarianTool': {
+        'AdditionalOptions': [
+          # Linking statically with C++/CX library is not recommended.
+          # TODO: Remove after removing ComponentExtensions
+          '/ignore:4264',
+        ],
+      },
+    },
+    'msvs_disabled_warnings': [
+      # Conditional expression is constant.
+      # Triggers in many legitimate cases, like branching on a constant declared
+      # in type traits.
+      4127,
+      # Class has virtual functions, but destructor is not virtual.
+      # Far less useful than in GCC because doesn't take into account the fact
+      # that destructor is not public.
+      4265,
+      # no function prototype given: converting '()' to '(void)'.
+      # We do not care.
+      4255,
+      # cast truncates constant value.
+      # We do not care.
+      4310,
+      # An rvalue cannot be bound to a non-const reference.
+      # In previous versions of Visual C++, it was possible to bind an rvalue
+      # to a non-const reference in a direct initialization. This warning
+      # is useless as it simply describes proper C++ behavior.
+      4350,
+      # layout of class may have changed from a previous version of
+      # the compiler due to better packing of member. We don't care about
+      # binary compatibility with other compiler versions.
+      4371,
+      # relative include path contains '..'.
+      # This occurs in a lot third party libraries and we don't care.
+      4464,
+      # decorated name length exceeded, name was truncated.
+      4503,
+      # assignment operator could not be generated.
+      # This is expected for structs with const members.
+      4512,
+      # Unreferenced inline function has been removed.
+      # While detection of dead code is good, this warning triggers in
+      # third-party libraries which renders it useless.
+      4514,
+      # Expression before comma has no effect.
+      # Cannot be used because Microsoft uses _ASSERTE(("message", 0)) trick
+      # in malloc.h which is included pretty much everywhere.
+      4548,
+      # Copy constructor could not be generated because a base class copy
+      # constructor is inaccessible.
+      # This is an expected consequence of using DISALLOW_COPY_AND_ASSIGN().
+      4625,
+      # Assignment operator could not be generated because a base class
+      # assignment operator is inaccessible.
+      # This is an expected consequence of using DISALLOW_COPY_AND_ASSIGN().
+      4626,
+      # Digraphs not supported.
+      # Thanks god!
+      4628,
+      # Symbol is not defined as a preprocessor macro, replacing with '0'.
+      # Seems like common practice, used in Windows SDK and gtest.
+      4668,
+      # Function not inlined.
+      # It's up to the compiler to decide what to inline.
+      4710,
+      # Function selected for inline expansion.
+      # It's up to the compiler to decide what to inline.
+      4711,
+      # The type and order of elements caused the compiler to add padding
+      # to the end of a struct.
+      # Unsurprisingly, most of the structs become larger because of padding
+      # but it's a universally acceptable price for better performance.
+      4820,
+      # Disable static analyzer warning for std::min and std::max with
+      # objects.
+      # https://connect.microsoft.com/VisualStudio/feedback/details/783808/static-analyzer-warning-c28285-for-std-min-and-std-max
+      28285,
+    ],
+    'target_conditions': [
+      ['cobalt_code==1', {
+        'cflags': [
+          '-Wall',
+          '-Wextra',
+          '-Wunreachable-code',
+        ],
+      },
+      ],
+    ],
+  }, # end of target_defaults
+}
diff --git a/src/starboard/win/shared/main.cc b/src/starboard/win/shared/main.cc
new file mode 100644
index 0000000..928cd84
--- /dev/null
+++ b/src/starboard/win/shared/main.cc
@@ -0,0 +1,69 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <windows.h>
+
+#include <WinSock2.h>
+
+#include <string>
+#include <vector>
+
+#include "starboard/configuration.h"
+#include "starboard/shared/uwp/application_uwp.h"
+#include "starboard/shared/win32/thread_private.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+using starboard::shared::win32::wchar_tToUTF8;
+
+int main(Platform::Array<Platform::String^>^ args) {
+  if (!IsDebuggerPresent()) {
+    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+  }
+
+  const int kWinSockVersionMajor = 2;
+  const int kWinSockVersionMinor = 2;
+  WSAData wsaData;
+  int init_result = WSAStartup(
+      MAKEWORD(kWinSockVersionMajor, kWinSockVersionMajor), &wsaData);
+
+  SB_CHECK(init_result == 0);
+  // WSAStartup returns the highest version that is supported up to the version
+  // we request.
+  SB_CHECK(LOBYTE(wsaData.wVersion) == kWinSockVersionMajor &&
+           HIBYTE(wsaData.wVersion) == kWinSockVersionMinor);
+
+  starboard::shared::win32::RegisterMainThread();
+
+  std::vector<std::string> string_args;
+  for (auto it = args->begin(); it != args->end(); ++it) {
+    Platform::String^ s = *it;
+    string_args.push_back(wchar_tToUTF8(s->Data(), s->Length()));
+  }
+
+  std::vector<const char*> utf8_args;
+  for (auto it = string_args.begin(); it != string_args.end(); ++it) {
+    utf8_args.push_back(it->data());
+  }
+
+  starboard::shared::uwp::ApplicationUwp application;
+  int return_value = application.Run(static_cast<int>(utf8_args.size()),
+                                     const_cast<char**>(utf8_args.data()));
+
+  WSACleanup();
+
+  return return_value;
+}
diff --git a/src/starboard/win/shared/starboard_platform.gypi b/src/starboard/win/shared/starboard_platform.gypi
new file mode 100644
index 0000000..c059193
--- /dev/null
+++ b/src/starboard/win/shared/starboard_platform.gypi
@@ -0,0 +1,299 @@
+# Copyright 2016 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+{
+  'targets': [
+    {
+      'target_name': 'starboard_platform',
+      'type': 'static_library',
+      'msvs_settings': {
+        'VCCLCompilerTool': {
+          'AdditionalOptions': [
+            '/ZW',  # Windows Runtime (Needed for UWP)
+            '/EHsx', # C++ exceptions (required with /ZW)
+            # For 'platform.winmd'. Note that replacing x86 with
+            # x64 here does not work.
+            '/AI"<(visual_studio_install_path)/lib/x86/store/references"',
+            # For 'Windows.winmd'
+            '/AI"<(windows_sdk_path)/UnionMetadata/<(windows_sdk_version)"',
+          ]
+        }
+      },
+      'sources': [
+        '<(DEPTH)/starboard/shared/iso/character_is_alphanumeric.cc',
+        '<(DEPTH)/starboard/shared/iso/character_is_digit.cc',
+        '<(DEPTH)/starboard/shared/iso/character_is_hex_digit.cc',
+        '<(DEPTH)/starboard/shared/iso/character_is_space.cc',
+        '<(DEPTH)/starboard/shared/iso/character_is_upper.cc',
+        '<(DEPTH)/starboard/shared/iso/character_to_lower.cc',
+        '<(DEPTH)/starboard/shared/iso/character_to_upper.cc',
+        '<(DEPTH)/starboard/shared/iso/double_absolute.cc',
+        '<(DEPTH)/starboard/shared/iso/double_exponent.cc',
+        '<(DEPTH)/starboard/shared/iso/double_floor.cc',
+        '<(DEPTH)/starboard/shared/iso/double_is_finite.cc',
+        '<(DEPTH)/starboard/shared/iso/double_is_nan.cc',
+        '<(DEPTH)/starboard/shared/iso/memory_compare.cc',
+        '<(DEPTH)/starboard/shared/iso/memory_copy.cc',
+        '<(DEPTH)/starboard/shared/iso/memory_find_byte.cc',
+        '<(DEPTH)/starboard/shared/iso/memory_move.cc',
+        '<(DEPTH)/starboard/shared/iso/memory_set.cc',
+        '<(DEPTH)/starboard/shared/iso/string_compare.cc',
+        '<(DEPTH)/starboard/shared/iso/string_compare_all.cc',
+        '<(DEPTH)/starboard/shared/iso/string_find_character.cc',
+        '<(DEPTH)/starboard/shared/iso/string_find_last_character.cc',
+        '<(DEPTH)/starboard/shared/iso/string_find_string.cc',
+        '<(DEPTH)/starboard/shared/iso/string_get_length.cc',
+        '<(DEPTH)/starboard/shared/iso/string_get_length_wide.cc',
+        '<(DEPTH)/starboard/shared/iso/string_parse_double.cc',
+        '<(DEPTH)/starboard/shared/iso/string_parse_signed_integer.cc',
+        '<(DEPTH)/starboard/shared/iso/string_parse_uint64.cc',
+        '<(DEPTH)/starboard/shared/iso/string_parse_unsigned_integer.cc',
+        '<(DEPTH)/starboard/shared/iso/string_scan.cc',
+        '<(DEPTH)/starboard/shared/starboard/application.cc',
+        '<(DEPTH)/starboard/shared/starboard/command_line.cc',
+        '<(DEPTH)/starboard/shared/starboard/command_line.h',
+        '<(DEPTH)/starboard/shared/starboard/event_cancel.cc',
+        '<(DEPTH)/starboard/shared/starboard/event_schedule.cc',
+        '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc',
+        '<(DEPTH)/starboard/shared/starboard/log_message.cc',
+        '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc',
+        '<(DEPTH)/starboard/shared/starboard/media/mime_type.h',
+        '<(DEPTH)/starboard/shared/starboard/string_concat.cc',
+        '<(DEPTH)/starboard/shared/starboard/string_concat_wide.cc',
+        '<(DEPTH)/starboard/shared/starboard/string_copy.cc',
+        '<(DEPTH)/starboard/shared/starboard/string_copy_wide.cc',
+        '<(DEPTH)/starboard/shared/starboard/string_duplicate.cc',
+        '<(DEPTH)/starboard/shared/starboard/queue_application.cc',
+        '<(DEPTH)/starboard/shared/stub/accessibility_get_display_settings.cc',
+        '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc',
+        '<(DEPTH)/starboard/shared/stub/audio_sink_create.cc',
+        '<(DEPTH)/starboard/shared/stub/audio_sink_destroy.cc',
+        '<(DEPTH)/starboard/shared/stub/audio_sink_get_max_channels.cc',
+        '<(DEPTH)/starboard/shared/stub/audio_sink_get_nearest_supported_sample_frequency.cc',
+        '<(DEPTH)/starboard/shared/stub/audio_sink_is_audio_frame_storage_type_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/audio_sink_is_audio_sample_type_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/audio_sink_is_valid.cc',
+        '<(DEPTH)/starboard/shared/stub/cryptography_create_transformer.cc',
+        '<(DEPTH)/starboard/shared/stub/cryptography_destroy_transformer.cc',
+        '<(DEPTH)/starboard/shared/stub/cryptography_get_tag.cc',
+        '<(DEPTH)/starboard/shared/stub/cryptography_set_authenticated_data.cc',
+        '<(DEPTH)/starboard/shared/stub/cryptography_set_initialization_vector.cc',
+        '<(DEPTH)/starboard/shared/stub/cryptography_transform.cc',
+        '<(DEPTH)/starboard/shared/stub/decode_target_release.cc',
+        '<(DEPTH)/starboard/shared/stub/drm_close_session.cc',
+        '<(DEPTH)/starboard/shared/stub/drm_create_system.cc',
+        '<(DEPTH)/starboard/shared/stub/drm_destroy_system.cc',
+        '<(DEPTH)/starboard/shared/stub/drm_generate_session_update_request.cc',
+        '<(DEPTH)/starboard/shared/stub/drm_system_internal.h',
+        '<(DEPTH)/starboard/shared/stub/drm_update_session.cc',
+        '<(DEPTH)/starboard/shared/stub/image_decode.cc',
+        '<(DEPTH)/starboard/shared/stub/image_is_decode_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/media_can_play_mime_and_key_system.cc',
+        '<(DEPTH)/starboard/shared/stub/media_get_audio_configuration.cc',
+        '<(DEPTH)/starboard/shared/stub/media_get_audio_output_count.cc',
+        '<(DEPTH)/starboard/shared/stub/media_is_audio_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/media_is_output_protected.cc',
+        '<(DEPTH)/starboard/shared/stub/media_is_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/media_is_video_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/media_set_output_protection.cc',
+        '<(DEPTH)/starboard/shared/stub/microphone_close.cc',
+        '<(DEPTH)/starboard/shared/stub/microphone_create.cc',
+        '<(DEPTH)/starboard/shared/stub/microphone_destroy.cc',
+        '<(DEPTH)/starboard/shared/stub/microphone_get_available.cc',
+        '<(DEPTH)/starboard/shared/stub/microphone_is_sample_rate_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/microphone_open.cc',
+        '<(DEPTH)/starboard/shared/stub/microphone_read.cc',
+        '<(DEPTH)/starboard/shared/stub/player_create.cc',
+        '<(DEPTH)/starboard/shared/stub/player_destroy.cc',
+        '<(DEPTH)/starboard/shared/stub/player_get_current_frame.cc',
+        '<(DEPTH)/starboard/shared/stub/player_get_info.cc',
+        '<(DEPTH)/starboard/shared/stub/player_output_mode_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/player_seek.cc',
+        '<(DEPTH)/starboard/shared/stub/player_set_bounds.cc',
+        '<(DEPTH)/starboard/shared/stub/player_set_pause.cc',
+        '<(DEPTH)/starboard/shared/stub/player_set_playback_rate.cc',
+        '<(DEPTH)/starboard/shared/stub/player_set_volume.cc',
+        '<(DEPTH)/starboard/shared/stub/player_write_end_of_stream.cc',
+        '<(DEPTH)/starboard/shared/stub/player_write_sample.cc',
+        '<(DEPTH)/starboard/shared/stub/socket_waiter_add.cc',
+        '<(DEPTH)/starboard/shared/stub/socket_waiter_create.cc',
+        '<(DEPTH)/starboard/shared/stub/socket_waiter_destroy.cc',
+        '<(DEPTH)/starboard/shared/stub/socket_waiter_remove.cc',
+        '<(DEPTH)/starboard/shared/stub/socket_waiter_wait.cc',
+        '<(DEPTH)/starboard/shared/stub/socket_waiter_wait_timed.cc',
+        '<(DEPTH)/starboard/shared/stub/socket_waiter_wake_up.cc',
+        '<(DEPTH)/starboard/shared/stub/storage_close_record.cc',
+        '<(DEPTH)/starboard/shared/stub/storage_delete_record.cc',
+        '<(DEPTH)/starboard/shared/stub/storage_get_record_size.cc',
+        '<(DEPTH)/starboard/shared/stub/storage_open_record.cc',
+        '<(DEPTH)/starboard/shared/stub/storage_read_record.cc',
+        '<(DEPTH)/starboard/shared/stub/storage_write_record.cc',
+        '<(DEPTH)/starboard/shared/stub/system_binary_search.cc',
+        '<(DEPTH)/starboard/shared/stub/system_clear_last_error.cc',
+        '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_connection_type.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_device_type.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_error_string.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_last_error.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_locale_id.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_number_of_processors.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_property.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_random_data.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_stack.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_total_cpu_memory.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_total_gpu_memory.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_used_cpu_memory.cc',
+        '<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc',
+        '<(DEPTH)/starboard/shared/stub/system_has_capability.cc',
+        '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc',
+        '<(DEPTH)/starboard/shared/stub/system_is_debugger_attached.cc',
+        '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_pause.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_stop.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_suspend.cc',
+        '<(DEPTH)/starboard/shared/stub/system_request_unpause.cc',
+        '<(DEPTH)/starboard/shared/stub/system_sort.cc',
+        '<(DEPTH)/starboard/shared/stub/system_symbolize.cc',
+        '<(DEPTH)/starboard/shared/stub/time_zone_get_dst_name.cc',
+        '<(DEPTH)/starboard/shared/stub/time_zone_get_name.cc',
+        '<(DEPTH)/starboard/shared/stub/user_get_current.cc',
+        '<(DEPTH)/starboard/shared/stub/user_get_property.cc',
+        '<(DEPTH)/starboard/shared/stub/user_get_signed_in.cc',
+        '<(DEPTH)/starboard/shared/stub/window_create.cc',
+        '<(DEPTH)/starboard/shared/stub/window_destroy.cc',
+        '<(DEPTH)/starboard/shared/stub/window_get_platform_handle.cc',
+        '<(DEPTH)/starboard/shared/stub/window_get_size.cc',
+        '<(DEPTH)/starboard/shared/stub/window_set_default_options.cc',
+        '<(DEPTH)/starboard/shared/win32/atomic_public.h',
+        '<(DEPTH)/starboard/shared/win32/byte_swap.cc',
+        '<(DEPTH)/starboard/shared/win32/condition_variable_broadcast.cc',
+        '<(DEPTH)/starboard/shared/win32/condition_variable_create.cc',
+        '<(DEPTH)/starboard/shared/win32/condition_variable_destroy.cc',
+        '<(DEPTH)/starboard/shared/win32/condition_variable_signal.cc',
+        '<(DEPTH)/starboard/shared/win32/condition_variable_wait.cc',
+        '<(DEPTH)/starboard/shared/win32/condition_variable_wait_timed.cc',
+        '<(DEPTH)/starboard/shared/win32/directory_can_open.cc',
+        '<(DEPTH)/starboard/shared/win32/directory_close.cc',
+        '<(DEPTH)/starboard/shared/win32/directory_create.cc',
+        '<(DEPTH)/starboard/shared/win32/directory_get_next.cc',
+        '<(DEPTH)/starboard/shared/win32/directory_internal.h',
+        '<(DEPTH)/starboard/shared/win32/directory_open.cc',
+        '<(DEPTH)/starboard/shared/win32/file_can_open.cc',
+        '<(DEPTH)/starboard/shared/win32/file_close.cc',
+        '<(DEPTH)/starboard/shared/win32/file_delete.cc',
+        '<(DEPTH)/starboard/shared/win32/file_exists.cc',
+        '<(DEPTH)/starboard/shared/win32/file_flush.cc',
+        '<(DEPTH)/starboard/shared/win32/file_get_info.cc',
+        '<(DEPTH)/starboard/shared/win32/file_get_path_info.cc',
+        '<(DEPTH)/starboard/shared/win32/file_internal.cc',
+        '<(DEPTH)/starboard/shared/win32/file_internal.h',
+        '<(DEPTH)/starboard/shared/win32/file_open.cc',
+        '<(DEPTH)/starboard/shared/win32/file_read.cc',
+        '<(DEPTH)/starboard/shared/win32/file_seek.cc',
+        '<(DEPTH)/starboard/shared/win32/file_truncate.cc',
+        '<(DEPTH)/starboard/shared/win32/file_write.cc',
+        '<(DEPTH)/starboard/shared/win32/log.cc',
+        '<(DEPTH)/starboard/shared/win32/log_flush.cc',
+        '<(DEPTH)/starboard/shared/win32/log_format.cc',
+        '<(DEPTH)/starboard/shared/win32/log_is_tty.cc',
+        '<(DEPTH)/starboard/shared/win32/log_raw.cc',
+        '<(DEPTH)/starboard/shared/win32/log_raw_dump_stack.cc',
+        '<(DEPTH)/starboard/shared/win32/log_raw_format.cc',
+        '<(DEPTH)/starboard/shared/win32/memory_allocate_aligned_unchecked.cc',
+        '<(DEPTH)/starboard/shared/win32/memory_allocate_unchecked.cc',
+        '<(DEPTH)/starboard/shared/win32/memory_free.cc',
+        '<(DEPTH)/starboard/shared/win32/memory_free_aligned.cc',
+        '<(DEPTH)/starboard/shared/win32/memory_get_stack_bounds.cc',
+        '<(DEPTH)/starboard/shared/win32/memory_map.cc',
+        '<(DEPTH)/starboard/shared/win32/memory_reallocate_unchecked.cc',
+        '<(DEPTH)/starboard/shared/win32/memory_unmap.cc',
+        '<(DEPTH)/starboard/shared/win32/mutex_acquire.cc',
+        '<(DEPTH)/starboard/shared/win32/mutex_acquire_try.cc',
+        '<(DEPTH)/starboard/shared/win32/mutex_create.cc',
+        '<(DEPTH)/starboard/shared/win32/mutex_destroy.cc',
+        '<(DEPTH)/starboard/shared/win32/mutex_release.cc',
+        '<(DEPTH)/starboard/shared/win32/once.cc',
+        '<(DEPTH)/starboard/shared/win32/set_non_blocking_internal.cc',
+        '<(DEPTH)/starboard/shared/win32/set_non_blocking_internal.h',
+        '<(DEPTH)/starboard/shared/win32/socket_accept.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_bind.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_clear_last_error.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_connect.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_create.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_destroy.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_free_resolution.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_get_last_error.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_get_local_address.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_get_interface_address.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_internal.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_internal.h',
+        '<(DEPTH)/starboard/shared/win32/socket_is_connected.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_is_connected_and_idle.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_join_multicast_group.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_listen.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_receive_from.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_resolve.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_send_to.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_set_broadcast.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_set_receive_buffer_size.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_set_reuse_address.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_set_send_buffer_size.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_set_tcp_keep_alive.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_set_tcp_no_delay.cc',
+        '<(DEPTH)/starboard/shared/win32/socket_set_tcp_window_scaling.cc',
+        '<(DEPTH)/starboard/shared/win32/string_compare_no_case.cc',
+        '<(DEPTH)/starboard/shared/win32/string_compare_no_case_n.cc',
+        '<(DEPTH)/starboard/shared/win32/string_compare_wide.cc',
+        '<(DEPTH)/starboard/shared/win32/string_format.cc',
+        '<(DEPTH)/starboard/shared/win32/string_format_wide.cc',
+        '<(DEPTH)/starboard/shared/win32/system_break_into_debugger.cc',
+        '<(DEPTH)/starboard/shared/win32/system_get_random_uint64.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_create.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_create_local_key.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_detach.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_destroy_local_key.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_get_current.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_get_id.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_get_local_value.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_get_name.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_is_equal.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_join.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_private.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_private.h',
+        '<(DEPTH)/starboard/shared/win32/thread_set_local_value.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_set_name.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_sleep.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_types_public.h',
+        '<(DEPTH)/starboard/shared/win32/thread_yield.cc',
+        '<(DEPTH)/starboard/shared/win32/thread_yield.h',
+        '<(DEPTH)/starboard/shared/win32/time_get_monotonic_now.cc',
+        '<(DEPTH)/starboard/shared/win32/time_get_now.cc',
+        '<(DEPTH)/starboard/shared/win32/time_zone_get_current.cc',
+        '<(DEPTH)/starboard/shared/win32/time_utils.h',
+        '<(DEPTH)/starboard/shared/win32/wchar_utils.h',
+        '<(DEPTH)/starboard/shared/uwp/application_uwp.cc',
+        '<(DEPTH)/starboard/shared/uwp/application_uwp.h',
+        'configuration_public.h',
+        'main.cc',
+        # Include private stubs, if present.
+        '<!@(python "<(DEPTH)/starboard/tools/find_private_files.py" "<(DEPTH)" "shared/stub/*.cc")',
+        '<@(starboard_platform_dependent_sources)',
+      ],
+      'defines': [
+        # This must be defined when building Starboard, and must not when
+        # building Starboard client code.
+        'STARBOARD_IMPLEMENTATION',
+      ],
+    },
+  ],
+}
diff --git a/src/starboard/win/shared/system_get_path.cc b/src/starboard/win/shared/system_get_path.cc
new file mode 100644
index 0000000..fdc35c2
--- /dev/null
+++ b/src/starboard/win/shared/system_get_path.cc
@@ -0,0 +1,112 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include <windows.h>
+#include <codecvt>
+#include <cstring>
+#include <locale>
+
+#include "Pathcch.h"
+
+#include "starboard/directory.h"
+#include "starboard/log.h"
+#include "starboard/shared/win32/directory_internal.h"
+#include "starboard/shared/win32/wchar_utils.h"
+#include "starboard/string.h"
+
+bool GetExecutablePath(char* out_path, int path_size) {
+  if (!out_path || !path_size) {
+    return false;
+  }
+
+  static const int kPathSize = SB_FILE_MAX_PATH;
+
+  wchar_t w_file_path[SB_FILE_MAX_PATH];
+  DWORD characters_written =
+      GetModuleFileName(NULL, w_file_path, SB_FILE_MAX_PATH);
+  if (characters_written == 0) {
+    return false;
+  }
+  PathCchRemoveFileSpec(w_file_path, SB_FILE_MAX_PATH);
+  std::string utf8_string =
+      starboard::shared::win32::wchar_tToUTF8(w_file_path, SB_FILE_MAX_PATH);
+  return SbStringCopy(out_path, utf8_string.c_str(), SB_FILE_MAX_PATH);
+}
+
+// Note: This function is only minimally implemented to allow tests to run.
+bool SbSystemGetPath(SbSystemPathId path_id, char* out_path, int path_size) {
+  if (!out_path || !path_size) {
+    return false;
+  }
+
+  static const int kPathSize = SB_FILE_MAX_PATH;
+
+  char file_path[kPathSize];
+  file_path[0] = '\0';
+
+  switch (path_id) {
+    case kSbSystemPathContentDirectory: {
+      if (!GetExecutablePath(file_path, kPathSize)) {
+        return false;
+      }
+      if (SbStringConcat(file_path, "/content/data", kPathSize) >= kPathSize) {
+        return false;
+      }
+      SbStringCopy(out_path, file_path, path_size);
+      break;
+    }
+    case kSbSystemPathTempDirectory: {
+      wchar_t w_file_path[kPathSize];
+      w_file_path[0] = '\0';
+
+      DWORD characters_written = GetTempPathW(kPathSize, w_file_path);
+      if (characters_written >= (kPathSize - 1)) {
+        return false;
+      }
+
+      if (characters_written < 1) {
+        return false;
+      }
+      // Remove the last slash, to match other Starboard implementations.
+      w_file_path[characters_written - 1] = L'\0';
+
+      std::string utf8_string =
+          starboard::shared::win32::wchar_tToUTF8(w_file_path);
+
+      if (SbStringCopy(file_path, utf8_string.c_str(), kPathSize) >=
+          kPathSize) {
+        return false;
+      }
+      SbDirectoryCreate(file_path);
+
+      size_t length = SbStringGetLength(file_path);
+      if (length < 1 || length > path_size) {
+        return false;
+      }
+
+      SbStringCopy(out_path, file_path, path_size);
+      break;
+    }
+    case kSbSystemPathExecutableFile: {
+      return GetExecutablePath(out_path, path_size);
+    }
+    // TODO: implement all the other cases.
+    default:
+      SB_NOTIMPLEMENTED();
+      return false;
+  }
+  return true;
+}
diff --git a/src/third_party/angle/.clang-format b/src/third_party/angle/.clang-format
new file mode 100644
index 0000000..9b4c96a
--- /dev/null
+++ b/src/third_party/angle/.clang-format
@@ -0,0 +1,35 @@
+# Defines the ANGLE style for automatic reformatting.
+# https://code.google.com/p/angleproject/wiki/CodingStandard
+# See Clang docs: http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Chromium
+
+# Allow double brackets such as std::vector<std::vector<int>>.
+Standard: Cpp11
+
+# Indent 4 spaces at a time.
+IndentWidth: 4
+
+# Keep lines under 100 columns long.
+ColumnLimit: 100
+
+# Always break before braces
+BreakBeforeBraces: Allman
+
+# Indent case labels.
+IndentCaseLabels: true
+
+# Right-align pointers and references
+PointerAlignment: Right
+
+# ANGLE likes to align things as much as possible.
+AlignOperands: true
+AlignConsecutiveAssignments: true
+
+# Use 2 space negative offset for access modifiers
+AccessModifierOffset: -2
+
+# TODO(jmadill): Decide if we want this on. Doesn't have an "all or none" mode.
+AllowShortCaseLabelsOnASingleLine: false
+
+# Useful for spacing out functions in classes
+KeepEmptyLinesAtTheStartOfBlocks: true
diff --git a/src/third_party/angle/AUTHORS b/src/third_party/angle/AUTHORS
index a2ce915..9830cce 100644
--- a/src/third_party/angle/AUTHORS
+++ b/src/third_party/angle/AUTHORS
@@ -1,4 +1,4 @@
-# This is the official list of The ANGLE Project Authors
+# This is the official list of The ANGLE Project Authors
 # for copyright purposes.
 # This file is distinct from the CONTRIBUTORS files.
 # See the latter for an explanation.
@@ -13,15 +13,26 @@
 
 Adobe Systems Inc.
 Autodesk, Inc.
+BlackBerry Limited
+Cable Television Laboratories, Inc.
 Cloud Party, Inc.
+Imagination Technologies Ltd.
 Intel Corporation
 Mozilla Corporation
 Turbulenz
 Klarälvdalens Datakonsult AB
+Microsoft Corporation
+Microsoft Open Technologies, Inc.
+NVIDIA Corporation
+Opera Software ASA
+The Qt Company Ltd.
+Advanced Micro Devices, Inc.
 
 Jacek Caban
 Mark Callow
 Ginn Chen
+Tibor den Ouden
+Régis Fénéon
 James Hauxwell
 Sam Hocevar
 Pierre Leveille
@@ -30,3 +41,10 @@
 Aitor Moreno
 Yuri O'Donnell
 Josh Soref
+Maks Naumov
+Jinyoung Hur
+Sebastian Bergstein
+James Ross-Gowan
+Nickolay Artamonov
+Ihsan Akmal
+Andrei Volykhin
diff --git a/src/third_party/angle/BUILD.gn b/src/third_party/angle/BUILD.gn
new file mode 100644
index 0000000..dca6a20
--- /dev/null
+++ b/src/third_party/angle/BUILD.gn
@@ -0,0 +1,745 @@
+# Copyright 2014-2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# import the use_x11 variable
+import("//build/config/dcheck_always_on.gni")
+import("//build/config/linux/pkg_config.gni")
+import("//build/config/ui.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
+import("//third_party/angle/gni/angle.gni")
+import("//ui/ozone/ozone.gni")
+
+declare_args() {
+  # Use the PCI lib to collect GPU information on Linux.
+  use_libpci = is_linux && (!is_chromecast || is_cast_desktop_build) &&
+               (use_x11 || use_ozone)
+}
+
+if (ozone_platform_gbm) {
+  pkg_config("libdrm") {
+    packages = [ "libdrm" ]
+  }
+}
+
+angle_git_is_present = exec_script("src/commit_id.py",
+                                   [
+                                     "check",
+                                     rebase_path(".", root_build_dir),
+                                   ],
+                                   "value")
+
+angle_use_commit_id = angle_git_is_present == 1
+
+gles_gypi = exec_script("//build/gypi_to_gn.py",
+                        [ rebase_path("src/libGLESv2.gypi") ],
+                        "scope",
+                        [ "src/libGLESv2.gypi" ])
+
+compiler_gypi = exec_script("//build/gypi_to_gn.py",
+                            [ rebase_path("src/compiler.gypi") ],
+                            "scope",
+                            [ "src/compiler.gypi" ])
+
+# This config is exported to dependent targets (and also applied to internal
+# ones).
+config("external_config") {
+  include_dirs = [ "include" ]
+}
+
+# This config is applied to internal Angle targets (not pushed to dependents).
+config("internal_config") {
+  include_dirs = [
+    "include",
+    "src",
+  ]
+
+  # Prevent the GL headers from redeclaring ANGLE entry points.
+  defines = [
+    "GL_GLEXT_PROTOTYPES",
+    "EGL_EGLEXT_PROTOTYPES",
+  ]
+
+  if (target_cpu == "x86") {
+    defines += [ "ANGLE_X86_CPU" ]
+  }
+  if (target_cpu == "x64") {
+    defines += [ "ANGLE_X64_CPU" ]
+  }
+}
+
+config("extra_warnings") {
+  # Enable more default warnings on Windows.
+  if (is_win) {
+    cflags = [
+      "/we4244",  # Conversion: possible loss of data.
+      "/we4456",  # Variable shadowing.
+      "/we4458",  # declaration hides class member.
+    ]
+  }
+}
+
+if (is_win) {
+  copy("copy_compiler_dll") {
+    sources = [
+      "$windows_sdk_path/Redist/D3D/$target_cpu/d3dcompiler_47.dll",
+    ]
+    outputs = [
+      "$root_out_dir/d3dcompiler_47.dll",
+    ]
+  }
+}
+
+angle_undefine_configs = [ "//build/config/compiler:default_include_dirs" ]
+
+# 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",
+    "include/GLES2/gl2.h",
+    "include/GLES2/gl2ext.h",
+    "include/GLES2/gl2platform.h",
+    "include/GLES3/gl3.h",
+    "include/GLES3/gl31.h",
+    "include/GLES3/gl32.h",
+    "include/GLES3/gl3platform.h",
+    "include/GLSLANG/ShaderLang.h",
+    "include/KHR/khrplatform.h",
+  ]
+}
+
+static_library("preprocessor") {
+  sources = rebase_path(compiler_gypi.angle_preprocessor_sources, ".", "src")
+
+  configs -= angle_undefine_configs
+  configs += [ ":internal_config" ]
+
+  public_deps = [
+    ":angle_common",
+  ]
+}
+
+config("translator_disable_pool_alloc") {
+  defines = [ "ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC" ]
+}
+
+config("debug_annotations_config") {
+  if (is_debug) {
+    defines = [ "ANGLE_ENABLE_DEBUG_ANNOTATIONS" ]
+  }
+}
+
+config("angle_release_asserts_config") {
+  if (dcheck_always_on) {
+    defines = [ "ANGLE_ENABLE_RELEASE_ASSERTS" ]
+  }
+}
+
+config("angle_common_config") {
+  include_dirs = [ "src/common/third_party/numerics" ]
+}
+
+static_library("angle_common") {
+  sources = rebase_path(gles_gypi.libangle_common_sources, ".", "src")
+
+  if (is_linux || is_android) {
+    sources += rebase_path(gles_gypi.libangle_common_linux_sources, ".", "src")
+  }
+
+  if (is_mac) {
+    sources += rebase_path(gles_gypi.libangle_common_mac_sources, ".", "src")
+  }
+
+  if (is_win) {
+    sources += rebase_path(gles_gypi.libangle_common_win_sources, ".", "src")
+  }
+
+  configs -= angle_undefine_configs
+  configs += [
+    ":angle_common_config",
+    ":debug_annotations_config",
+    ":extra_warnings",
+    ":internal_config",
+  ]
+
+  public_deps = [
+    ":commit_id",
+  ]
+  public_configs = [ ":angle_common_config" ]
+  all_dependent_configs = [ ":angle_release_asserts_config" ]
+}
+
+config("angle_image_util_config") {
+  include_dirs = [
+    "include",
+    "src",
+  ]
+}
+
+static_library("angle_image_util") {
+  sources = rebase_path(gles_gypi.libangle_image_util_sources, ".", "src")
+
+  configs -= angle_undefine_configs
+  configs += [
+    ":internal_config",
+    ":extra_warnings",
+  ]
+
+  public_configs = [ ":angle_image_util_config" ]
+
+  public_deps = [
+    ":angle_common",
+  ]
+}
+
+config("angle_gpu_info_util_config") {
+  include_dirs = [
+    "include",
+    "src",
+  ]
+}
+
+static_library("angle_gpu_info_util") {
+  configs -= angle_undefine_configs
+  configs += [
+    ":internal_config",
+    ":extra_warnings",
+  ]
+
+  public_configs = [ ":angle_gpu_info_util_config" ]
+
+  public_deps = [
+    ":angle_common",
+  ]
+
+  sources = rebase_path(gles_gypi.libangle_gpu_info_util_sources, ".", "src")
+  deps = []
+  libs = []
+  defines = []
+
+  if (is_win) {
+    sources +=
+        rebase_path(gles_gypi.libangle_gpu_info_util_win_sources, ".", "src")
+    libs += [ "setupapi.lib" ]
+    defines += [ "GPU_INFO_USE_SETUPAPI" ]
+  }
+
+  if (is_linux) {
+    sources +=
+        rebase_path(gles_gypi.libangle_gpu_info_util_linux_sources, ".", "src")
+
+    if (use_x11) {
+      sources +=
+          rebase_path(gles_gypi.libangle_gpu_info_util_x11_sources, ".", "src")
+      deps += [ "src/third_party/libXNVCtrl:libXNVCtrl" ]
+      defines += [ "GPU_INFO_USE_X11" ]
+      libs += [
+        "X11",
+        "Xi",
+        "Xext",
+      ]
+    }
+  }
+
+  if (use_libpci) {
+    sources +=
+        rebase_path(gles_gypi.libangle_gpu_info_util_libpci_sources, ".", "src")
+    defines += [ "GPU_INFO_USE_LIBPCI" ]
+    libs += [ "pci" ]
+  }
+
+  if (is_mac) {
+    sources +=
+        rebase_path(gles_gypi.libangle_gpu_info_util_mac_sources, ".", "src")
+    libs += [
+      "IOKit.framework",
+      "CoreFoundation.framework",
+    ]
+  }
+}
+
+static_library("translator") {
+  sources = rebase_path(compiler_gypi.angle_translator_sources, ".", "src")
+  defines = []
+
+  if (angle_enable_essl || use_libfuzzer) {
+    sources +=
+        rebase_path(compiler_gypi.angle_translator_essl_sources, ".", "src")
+    defines += [ "ANGLE_ENABLE_ESSL" ]
+  }
+
+  if (angle_enable_glsl || use_libfuzzer) {
+    sources +=
+        rebase_path(compiler_gypi.angle_translator_glsl_sources, ".", "src")
+    defines += [ "ANGLE_ENABLE_GLSL" ]
+  }
+
+  if (angle_enable_hlsl || use_libfuzzer) {
+    sources +=
+        rebase_path(compiler_gypi.angle_translator_hlsl_sources, ".", "src")
+    defines += [ "ANGLE_ENABLE_HLSL" ]
+  }
+
+  if (angle_enable_vulkan || use_libfuzzer) {
+    sources += rebase_path(compiler_gypi.angle_translator_lib_vulkan_sources,
+                           ".",
+                           "src")
+    defines += [ "ANGLE_ENABLE_VULKAN" ]
+  }
+
+  configs -= angle_undefine_configs
+  configs += [ ":internal_config" ]
+  public_configs = [ ":external_config" ]
+  if (use_libfuzzer) {
+    all_dependent_configs = [ ":translator_disable_pool_alloc" ]
+  }
+
+  deps = [
+    ":includes",
+    ":preprocessor",
+  ]
+
+  public_deps = [
+    ":angle_common",
+  ]
+
+  if (is_win) {
+    # Necessary to suppress some system header xtree warnigns in Release.
+    # For some reason this warning doesn't get triggered in Chromium
+    cflags = [ "/wd4718" ]
+  }
+}
+
+source_set("translator_fuzzer") {
+  sources = [
+    "src/compiler/fuzz/translator_fuzzer.cpp",
+  ]
+
+  include_dirs = [
+    "include",
+    "src",
+  ]
+
+  deps = [
+    ":translator",
+  ]
+}
+
+config("commit_id_config") {
+  include_dirs = [ "$root_gen_dir/angle" ]
+}
+
+commit_id_output_file = "$root_gen_dir/angle/id/commit.h"
+if (angle_use_commit_id) {
+  action("commit_id") {
+    script = "src/commit_id.py"
+    outputs = [
+      commit_id_output_file,
+    ]
+
+    args = [
+      "gen",
+      rebase_path(".", root_build_dir),
+      rebase_path(commit_id_output_file, root_build_dir),
+    ]
+
+    public_configs = [ ":commit_id_config" ]
+  }
+} else {
+  copy("commit_id") {
+    sources = [
+      "src/commit.h",
+    ]
+    outputs = [
+      commit_id_output_file,
+    ]
+    public_configs = [ ":commit_id_config" ]
+  }
+}
+
+config("libANGLE_config") {
+  cflags = []
+  defines = []
+  if (angle_enable_d3d9) {
+    defines += [ "ANGLE_ENABLE_D3D9" ]
+  }
+  if (angle_enable_d3d11) {
+    defines += [ "ANGLE_ENABLE_D3D11" ]
+  }
+  if (angle_enable_gl) {
+    defines += [ "ANGLE_ENABLE_OPENGL" ]
+    if (use_x11) {
+      defines += [ "ANGLE_USE_X11" ]
+    }
+  }
+  if (angle_enable_vulkan) {
+    defines += [ "ANGLE_ENABLE_VULKAN" ]
+  }
+  if (angle_enable_null) {
+    defines += [ "ANGLE_ENABLE_NULL" ]
+  }
+  defines += [ "LIBANGLE_IMPLEMENTATION" ]
+
+  if (is_win) {
+    cflags += [ "/wd4530" ]  # C++ exception handler used, but unwind semantics are not enabled.
+  }
+}
+
+static_library("libANGLE") {
+  sources = rebase_path(gles_gypi.libangle_sources, ".", "src")
+
+  include_dirs = []
+  libs = []
+  defines = []
+  public_deps = [
+    ":angle_common",
+  ]
+  deps = [
+    ":angle_gpu_info_util",
+    ":angle_image_util",
+    ":commit_id",
+    ":includes",
+    ":translator",
+  ]
+
+  # Shared D3D sources.
+  if (angle_enable_d3d9 || angle_enable_d3d11) {
+    sources += rebase_path(gles_gypi.libangle_d3d_shared_sources, ".", "src")
+
+    defines += [ "ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " + "\"d3dcompiler_47.dll\", \"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }" ]
+  }
+
+  if (angle_enable_d3d9) {
+    sources += rebase_path(gles_gypi.libangle_d3d9_sources, ".", "src")
+    libs += [ "d3d9.lib" ]
+  }
+
+  if (angle_enable_d3d11) {
+    sources += rebase_path(gles_gypi.libangle_d3d11_sources, ".", "src")
+    sources += rebase_path(gles_gypi.libangle_d3d11_win32_sources, ".", "src")
+    libs += [ "dxguid.lib" ]
+  }
+
+  if (angle_enable_gl) {
+    sources += rebase_path(gles_gypi.libangle_gl_sources, ".", "src")
+    include_dirs += [ "src/third_party/khronos" ]
+
+    if (is_win) {
+      sources += rebase_path(gles_gypi.libangle_gl_wgl_sources, ".", "src")
+    }
+    if (use_x11) {
+      sources += rebase_path(gles_gypi.libangle_gl_glx_sources, ".", "src")
+      deps += [ "src/third_party/libXNVCtrl:libXNVCtrl" ]
+      libs += [
+        "X11",
+        "Xi",
+        "Xext",
+      ]
+    }
+    if (is_mac) {
+      sources += rebase_path(gles_gypi.libangle_gl_cgl_sources, ".", "src")
+      libs += [
+        "Cocoa.framework",
+        "IOSurface.framework",
+        "OpenGL.framework",
+        "QuartzCore.framework",
+      ]
+    }
+    if (is_android) {
+      sources += rebase_path(gles_gypi.libangle_gl_egl_sources, ".", "src")
+      sources += rebase_path(gles_gypi.libangle_gl_egl_dl_sources, ".", "src")
+      sources +=
+          rebase_path(gles_gypi.libangle_gl_egl_android_sources, ".", "src")
+      libs += [
+        "android",
+        "log",
+      ]
+    }
+    if (ozone_platform_gbm) {
+      configs += [ ":libdrm" ]
+      defines += [ "ANGLE_USE_OZONE" ]
+      deps += [ "//third_party/minigbm" ]
+      sources += rebase_path(gles_gypi.libangle_gl_egl_sources, ".", "src")
+      sources += rebase_path(gles_gypi.libangle_gl_egl_dl_sources, ".", "src")
+      sources += rebase_path(gles_gypi.libangle_gl_ozone_sources, ".", "src")
+    }
+  }
+
+  if (angle_enable_vulkan) {
+    sources += rebase_path(gles_gypi.libangle_vulkan_sources, ".", "src")
+    if (is_win) {
+      sources +=
+          rebase_path(gles_gypi.libangle_vulkan_win32_sources, ".", "src")
+    }
+    if (is_linux) {
+      sources += rebase_path(gles_gypi.libangle_vulkan_xcb_sources, ".", "src")
+    }
+    deps += [ "//third_party/angle/src/vulkan_support:angle_vulkan" ]
+  }
+
+  if (angle_enable_null) {
+    sources += rebase_path(gles_gypi.libangle_null_sources, ".", "src")
+  }
+
+  if (is_debug) {
+    defines += [ "ANGLE_GENERATE_SHADER_DEBUG_INFO" ]
+  }
+
+  configs -= angle_undefine_configs
+
+  configs += [
+    ":commit_id_config",
+    ":debug_annotations_config",
+    ":extra_warnings",
+    ":internal_config",
+  ]
+
+  public_configs = [ ":libANGLE_config" ]
+
+  if (is_win) {
+    data_deps = [
+      ":copy_compiler_dll",
+    ]
+  }
+}
+
+config("shared_library_public_config") {
+  if (is_mac && !is_component_build) {
+    # Executable targets that depend on the shared libraries below need to have
+    # the rpath setup in non-component build configurations.
+    ldflags = [
+      "-rpath",
+      "@executable_path/",
+    ]
+  }
+}
+
+# This config controls export definitions on ANGLE API calls.
+config("angle_static") {
+  defines = [
+    "ANGLE_EXPORT=",
+    "EGLAPI=",
+    "GL_APICALL=",
+  ]
+}
+
+shared_library("libGLESv2") {
+  sources = rebase_path(gles_gypi.libglesv2_sources, ".", "src")
+
+  if (is_android) {
+    configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
+  }
+
+  if (is_win) {
+    ldflags =
+        [ "/DEF:" + rebase_path("src/libGLESv2/libGLESv2.def", root_build_dir) ]
+  }
+
+  if (is_mac && !is_component_build) {
+    ldflags = [
+      "-install_name",
+      "@rpath/${target_name}.dylib",
+    ]
+    public_configs = [ ":shared_library_public_config" ]
+  }
+
+  configs -= angle_undefine_configs
+  configs += [
+    ":commit_id_config",
+    ":debug_annotations_config",
+    ":internal_config",
+  ]
+
+  defines = [ "LIBGLESV2_IMPLEMENTATION" ]
+  if (is_win) {
+    defines += [ "GL_APICALL=" ]
+  } else {
+    defines += [ "GL_APICALL=__attribute__((visibility(\"default\")))" ]
+  }
+
+  deps = [
+    ":includes",
+    ":libANGLE",
+  ]
+}
+
+static_library("libGLESv2_static") {
+  sources = rebase_path(gles_gypi.libglesv2_sources, ".", "src")
+
+  configs -= angle_undefine_configs
+  configs += [
+    ":commit_id_config",
+    ":debug_annotations_config",
+    ":internal_config",
+  ]
+
+  public_configs = [ ":angle_static" ]
+
+  deps = [
+    ":includes",
+    ":libANGLE",
+  ]
+}
+
+shared_library("libEGL") {
+  sources = rebase_path(gles_gypi.libegl_sources, ".", "src")
+
+  if (is_android) {
+    configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
+  }
+  configs -= angle_undefine_configs
+  configs += [
+    ":commit_id_config",
+    ":debug_annotations_config",
+    ":extra_warnings",
+    ":internal_config",
+  ]
+
+  defines = [ "LIBEGL_IMPLEMENTATION" ]
+  if (is_win) {
+    defines += [ "EGLAPI=" ]
+  } else {
+    defines += [ "EGLAPI=__attribute__((visibility(\"default\")))" ]
+  }
+
+  if (is_win) {
+    ldflags = [ "/DEF:" + rebase_path("src/libEGL/libEGL.def", root_build_dir) ]
+  }
+
+  if (is_mac && !is_component_build) {
+    ldflags = [
+      "-install_name",
+      "@rpath/${target_name}.dylib",
+    ]
+    public_configs = [ ":shared_library_public_config" ]
+  }
+
+  deps = [
+    ":includes",
+    ":libGLESv2",
+  ]
+}
+
+static_library("libEGL_static") {
+  sources = rebase_path(gles_gypi.libegl_sources, ".", "src")
+
+  configs -= angle_undefine_configs
+  configs += [
+    ":commit_id_config",
+    ":debug_annotations_config",
+    ":extra_warnings",
+    ":internal_config",
+  ]
+
+  public_configs = [ ":angle_static" ]
+
+  deps = [
+    ":includes",
+    ":libGLESv2_static",
+  ]
+}
+
+util_gypi = exec_script("//build/gypi_to_gn.py",
+                        [ rebase_path("util/util.gyp") ],
+                        "scope",
+                        [ "util/util.gyp" ])
+
+config("angle_util_config") {
+  include_dirs = [ "util" ]
+  if (is_linux && use_x11) {
+    libs = [ "X11" ]
+  }
+}
+
+foreach(is_shared_library,
+        [
+          true,
+          false,
+        ]) {
+  if (is_shared_library) {
+    library_type = "shared_library"
+    library_name = "angle_util"
+    dep_suffix = ""
+  } else {
+    library_type = "static_library"
+    library_name = "angle_util_static"
+    dep_suffix = "_static"
+  }
+
+  target(library_type, library_name) {
+    sources = rebase_path(util_gypi.util_sources, ".", "util")
+
+    if (is_win) {
+      sources += rebase_path(util_gypi.util_win32_sources, ".", "util")
+    }
+
+    if (is_linux) {
+      sources += rebase_path(util_gypi.util_linux_sources, ".", "util")
+      libs = [
+        "rt",
+        "dl",
+      ]
+    }
+
+    if (is_mac) {
+      sources += rebase_path(util_gypi.util_osx_sources, ".", "util")
+      libs = [
+        "AppKit.framework",
+        "QuartzCore.framework",
+      ]
+    }
+
+    if (use_x11) {
+      sources += rebase_path(util_gypi.util_x11_sources, ".", "util")
+    }
+
+    if (is_android) {
+      if (is_shared_library) {
+        configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
+      }
+
+      # To prevent linux sources filtering on android
+      set_sources_assignment_filter([])
+      sources += rebase_path(util_gypi.util_linux_sources, ".", "util")
+      sources += rebase_path(util_gypi.util_android_sources, ".", "util")
+      libs = [
+        "android",
+        "log",
+      ]
+    }
+
+    if (use_ozone) {
+      sources += rebase_path(util_gypi.util_ozone_sources, ".", "util")
+    }
+
+    configs += [
+      ":debug_annotations_config",
+      ":extra_warnings",
+    ]
+
+    public_configs = [
+      ":angle_util_config",
+      ":internal_config",
+    ]
+
+    deps = [
+      ":angle_common",
+      ":libEGL${dep_suffix}",
+      ":libGLESv2${dep_suffix}",
+    ]
+
+    if (is_shared_library) {
+      defines = [ "LIBANGLE_UTIL_IMPLEMENTATION" ]
+
+      if (is_mac && !is_component_build) {
+        ldflags = [
+          "-install_name",
+          "@rpath/lib${target_name}.dylib",
+        ]
+        public_configs += [ ":shared_library_public_config" ]
+      }
+    }
+  }
+}
diff --git a/src/third_party/angle/CONTRIBUTORS b/src/third_party/angle/CONTRIBUTORS
index 00ebe7c..3692682 100644
--- a/src/third_party/angle/CONTRIBUTORS
+++ b/src/third_party/angle/CONTRIBUTORS
@@ -1,76 +1,124 @@
-# This is the official list of people who can contribute

-# (and who have contributed) code to the ANGLE project

-# repository.

-# The AUTHORS file lists the copyright holders; this file

-# lists people.  For example, Google employees are listed here

-# but not in AUTHORS, because Google holds the copyright.

-#

-

-TransGaming Inc.

- Nicolas Capens

- Daniel Koch

- Geoff Lang

- Andrew Lewycky

- Jamie Madill

- Gavriel State

- Shannon Woods

-

-Google Inc.

- Brent Austin

- Michael Bai

- John Bauman

- Peter Beverloo

- Steve Block

- Rachel Blum

- Eric Boren

- Henry Bridge

- Nat Duca

- Peter Kasting

- Vangelis Kokkevis

- Zhenyao Mo

- Daniel Nicoara

- Alastair Patrick

- Alok Priyadarshi

- Kenneth Russell

- Brian Salomon

- Gregg Tavares

- Jeff Timanus

- Ben Vanik

- Adrienne Walker

- thestig@chromium.org

- Justin Schuh

-

-Adobe Systems Inc.

- Alexandru Chiculita

- Steve Minns

- Max Vujovic

-

-Autodesk, Inc.

- Ranger Harke

-

-Cloud Party, Inc.

- Conor Dickinson

-

-Intel Corporation

- Jin Yang

- Andy Chen

- Josh Triplett

-

-Klarälvdalens Datakonsult AB

- Milian Wolff

-

-Mozilla Corp.

- Ehsan Akhgari

- Jeff Gilbert

- Mike Hommey

- Benoit Jacob

- Makoto Kato

- Vladimir Vukicevic

-

-Turbulenz

- Michael Braithwaite

-

-Ulrik Persson (ddefrostt)

-Mark Banner (standard8mbp)

-David Kilzer

-

+# This is the official list of people who can contribute
+# (and who have contributed) code to the ANGLE project
+# repository.
+# The AUTHORS file lists the copyright holders; this file
+# lists people.  For example, Google employees are listed here
+# but not in AUTHORS, because Google holds the copyright.
+#
+
+TransGaming Inc.
+ Nicolas Capens
+ Daniel Koch
+ Geoff Lang
+ Andrew Lewycky
+ Jamie Madill
+ Gavriel State
+ Shannon Woods
+
+Google Inc.
+ Brent Austin
+ Michael Bai
+ John Bauman
+ Peter Beverloo
+ Steve Block
+ Rachel Blum
+ Eric Boren
+ Henry Bridge
+ Nat Duca
+ Peter Kasting
+ Vangelis Kokkevis
+ Zhenyao Mo
+ Daniel Nicoara
+ Alastair Patrick
+ Alok Priyadarshi
+ Kenneth Russell
+ Brian Salomon
+ Gregg Tavares
+ Jeff Timanus
+ Ben Vanik
+ Adrienne Walker
+ thestig@chromium.org
+ Justin Schuh
+ Scott Graham
+ Corentin Wallez
+
+Adobe Systems Inc.
+ Alexandru Chiculita
+ Steve Minns
+ Max Vujovic
+
+Autodesk, Inc.
+ Ranger Harke
+
+Cloud Party, Inc.
+ Conor Dickinson
+
+The Qt Company Ltd.
+ Andrew Knight
+
+Imagination Technologies Ltd.
+ Gregoire Payen de La Garanderie
+
+Intel Corporation
+ Jin Yang
+ Andy Chen
+ Josh Triplett
+ Sudarsana Nagineni
+ Jiajia Qin
+ Jiawei Shao
+ Jie Chen
+ Qiankun Miao
+ Bryan Bernhart
+ Yunchao He
+ Xinghua Cao
+
+Klarälvdalens Datakonsult AB
+ Milian Wolff
+
+Mozilla Corp.
+ Ehsan Akhgari
+ Edwin Flores
+ Jeff Gilbert
+ Mike Hommey
+ Benoit Jacob
+ Makoto Kato
+ Vladimir Vukicevic
+
+Turbulenz
+ Michael Braithwaite
+
+Ulrik Persson (ddefrostt)
+Mark Banner (standard8mbp)
+David Kilzer
+Jacek Caban
+Tibor den Ouden
+Régis Fénéon
+Sebastian Bergstein
+James Ross-Gowan
+Andrei Volykhin
+
+Microsoft Corporation
+ Cooper Partin
+ Austin Kinross
+ Minmin Gong
+ Shawn Hargreaves
+
+Microsoft Open Technologies, Inc.
+ Cooper Partin
+ Austin Kinross
+
+NVIDIA Corporation
+ Olli Etuaho
+ Arun Patole
+ Qingqing Deng
+ Kimmo Kinnunen
+ Sami Väisänen
+ Martin Radev
+
+Opera Software ASA
+ Daniel Bratell
+ Tomasz Moniuszko
+ David Landell
+
+Advanced Micro Devices, Inc.
+ Russ Lind
diff --git a/src/third_party/angle/DEPS.chromium b/src/third_party/angle/DEPS.chromium
new file mode 100644
index 0000000..5678485
--- /dev/null
+++ b/src/third_party/angle/DEPS.chromium
@@ -0,0 +1,64 @@
+# This file is used to manage the ANGLE's dependencies in the Chromium src repo. It is
+# used by gclient to determine what version of each dependency to check out, and
+# where.
+#
+# These deps are duplicated in ANGLE's DEPS file which we use for the standalone
+# build. The dual file setup is necessary because Chromium can only recurse into
+# a single file and we do not want to import all of ANGLE's standalone DEPS.
+#
+# If you make a change to one of these dependencies please also update the
+# standalone DEPS file.
+
+vars = {
+  'android_git': 'https://android.googlesource.com',
+
+  # Current revision of dEQP.
+  'deqp_revision': '455d82c60b096e7bd83b6a2f5ed70c61e4bfa759',
+
+  # Current revision of glslang, the Khronos SPIRV compiler.
+  'glslang_revision': '1e275c8486325aaab34734ad9a650c0121c5efdb',
+
+  # Current revision fo the SPIRV-Headers Vulkan support library.
+  'spirv_headers_revision': 'c470b68225a04965bf87d35e143ae92f831e8110',
+
+  # Current revision of SPIRV-Tools for Vulkan.
+  'spirv_tools_revision': '68c5f0436f1d4f1f137e608780190865d0b193ca',
+
+  # Current revision of the Vulkan Validation Layers SDK.
+  'vulkan_revision': 'f47c534fee2f26f6b783209d56e0ade48e30eb8d',
+}
+
+deps_os = {
+  'win': {
+    'src/third_party/deqp/src':
+      Var('android_git') + '/platform/external/deqp@' + Var('deqp_revision'),
+
+    'src/third_party/glslang-angle/src':
+      Var('android_git') + '/platform/external/shaderc/glslang@' + Var('glslang_revision'),
+
+    'src/third_party/spirv-headers/src':
+      Var('android_git') + '/platform/external/shaderc/spirv-headers@' + Var('spirv_headers_revision'),
+
+    'src/third_party/spirv-tools-angle/src':
+      Var('android_git') + '/platform/external/shaderc/spirv-tools@' + Var('spirv_tools_revision'),
+
+    'src/third_party/vulkan-validation-layers/src':
+      Var('android_git') + '/platform/external/vulkan-validation-layers@' + Var('vulkan_revision'),
+  },
+  'unix': {
+    'src/third_party/deqp/src':
+      Var('android_git') + '/platform/external/deqp@' + Var('deqp_revision'),
+
+    'src/third_party/glslang-angle/src':
+      Var('android_git') + '/platform/external/shaderc/glslang@' + Var('glslang_revision'),
+
+    'src/third_party/spirv-headers/src':
+      Var('android_git') + '/platform/external/shaderc/spirv-headers@' + Var('spirv_headers_revision'),
+
+    'src/third_party/spirv-tools-angle/src':
+      Var('android_git') + '/platform/external/shaderc/spirv-tools@' + Var('spirv_tools_revision'),
+
+    'src/third_party/vulkan-validation-layers/src':
+      Var('android_git') + '/platform/external/vulkan-validation-layers@' + Var('vulkan_revision'),
+  },
+}
diff --git a/src/third_party/angle/README.md b/src/third_party/angle/README.md
new file mode 100644
index 0000000..91a4744
--- /dev/null
+++ b/src/third_party/angle/README.md
@@ -0,0 +1,75 @@
+# ANGLE - Almost Native Graphics Layer Engine
+
+The goal of ANGLE is to allow users of multiple operating systems to seamlessly run WebGL and other
+OpenGL ES content by translating OpenGL ES API calls to one of the hardware-supported APIs available
+for that platform. ANGLE currently provides translation from OpenGL ES 2.0 and 3.0 to desktop
+OpenGL, OpenGL ES, Direct3D 9, and Direct3D 11. Support for translation from OpenGL ES to Vulkan is
+underway, and future plans include compute shader support (ES 3.1) and MacOS support.
+
+### Level of OpenGL ES support via backing renderers
+
+|                |  Direct3D 9   |  Direct3D 11     |   Desktop GL   |    GL ES      |    Vulkan     |
+|----------------|:-------------:|:----------------:|:--------------:|:-------------:|:-------------:|
+| OpenGL ES 2.0  |    complete   |    complete      |    complete    |   complete    |  in progress  |
+| OpenGL ES 3.0  |               |    complete      |    complete    |  in progress  |  not started  |
+| OpenGL ES 3.1  |               |   not started    |   in progress  |  in progress  |  not started  |
+
+### Platform support via backing renderers
+
+|             |    Direct3D 9  |   Direct3D 11  |   Desktop GL  |    GL ES    |   Vulkan    |
+|------------:|:--------------:|:--------------:|:-------------:|:-----------:|:-----------:|
+| Windows     |    complete    |    complete    |   complete    |   complete  | in progress |
+| Linux       |                |                |   complete    |             |   planned   |
+| Mac OS X    |                |                |   in progress |             |             |
+| Chrome OS   |                |                |               |   complete  |   planned   |
+| Android     |                |                |               |   complete  |   planned   |
+
+ANGLE v1.0.772 was certified compliant by passing the ES 2.0.3 conformance tests in October 2011.
+ANGLE also provides an implementation of the EGL 1.4 specification.
+
+ANGLE is used as the default WebGL backend for both Google Chrome and Mozilla Firefox on Windows
+platforms. Chrome uses ANGLE for all graphics rendering on Windows, including the accelerated
+Canvas2D implementation and the Native Client sandbox environment.
+
+Portions of the ANGLE shader compiler are used as a shader validator and translator by WebGL
+implementations across multiple platforms. It is used on Mac OS X, Linux, and in mobile variants of
+the browsers. Having one shader validator helps to ensure that a consistent set of GLSL ES shaders
+are accepted across browsers and platforms. The shader translator can be used to translate shaders
+to other shading languages, and to optionally apply shader modifications to work around bugs or
+quirks in the native graphics drivers. The translator targets Desktop GLSL, Direct3D HLSL, and even
+ESSL for native GLES2 platforms.
+
+## Sources
+
+ANGLE repository is hosted by Chromium project and can be
+[browsed online](https://chromium.googlesource.com/angle/angle) or cloned with
+
+    git clone https://chromium.googlesource.com/angle/angle
+
+
+## Building
+
+View the [Dev setup instructions](doc/DevSetup.md). For generating a Windows Store version of ANGLE view the [Windows Store instructions](doc/BuildingAngleForWindowsStore.md)
+
+## Contributing
+
+* Join our [Google group](https://groups.google.com/group/angleproject) to keep up to date.
+* Join us on IRC in the #ANGLEproject channel on FreeNode.
+* File bugs in the [issue tracker](http://code.google.com/p/angleproject/issues/list) (preferably with an isolated test-case).
+* [Choose an ANGLE branch](doc/ChoosingANGLEBranch.md) to track in your own project.
+
+
+* Read ANGLE development [documentation](doc).
+* Look at [pending](https://chromium-review.googlesource.com/#/q/project:angle/angle+status:open)
+  and [merged](https://chromium-review.googlesource.com/#/q/project:angle/angle+status:merged) changes.
+* Become a [code contributor](doc/ContributingCode.md).
+* Use ANGLE's [coding standard](doc/CodingStandard.md).
+* Learn how to [build ANGLE for Chromium development](doc/BuildingAngleForChromiumDevelopment.md).
+* Get help on [debugging ANGLE](doc/DebuggingTips.md).
+
+
+* Read about WebGL on the [Khronos WebGL Wiki](http://khronos.org/webgl/wiki/Main_Page).
+* Learn about implementation details in the [OpenGL Insights chapter on ANGLE](http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-ANGLE.pdf) and this [ANGLE presentation](https://drive.google.com/file/d/0Bw29oYeC09QbbHoxNE5EUFh0RGs/view?usp=sharing).
+* Learn about the past, present, and future of the ANGLE implementation in [this recent presentation](https://docs.google.com/presentation/d/1CucIsdGVDmdTWRUbg68IxLE5jXwCb2y1E9YVhQo0thg/pub?start=false&loop=false).
+* If you use ANGLE in your own project, we'd love to hear about it!
+
diff --git a/src/third_party/angle/angle.gyp b/src/third_party/angle/angle.gyp
new file mode 100644
index 0000000..3aea864
--- /dev/null
+++ b/src/third_party/angle/angle.gyp
@@ -0,0 +1,390 @@
+# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'variables':
+    {
+        'angle_code': 1,
+        'angle_gen_path': '<(SHARED_INTERMEDIATE_DIR)/angle',
+        'angle_use_commit_id%': 0,
+        'angle_enable_d3d9%': 0,
+        'angle_enable_d3d11%': 0,
+        'angle_enable_gl%': 0,
+        'angle_enable_vulkan%': 0,
+        'angle_enable_essl%': 1, # Enable this for all configs by default
+        'angle_enable_glsl%': 1, # Enable this for all configs by default
+        'angle_enable_hlsl%': 0,
+        'angle_link_glx%': 0,
+        'angle_gl_library_type%': 'static_library',
+        'dcheck_always_on%': 0,
+        'conditions':
+        [
+            ['OS=="win"',
+            {
+                'angle_enable_gl%': 1,
+                'angle_enable_d3d9%': 1,
+                'angle_enable_d3d11%': 1,
+                'angle_enable_hlsl%': 1,
+                'angle_enable_vulkan%': 1,
+            }],
+            ['OS=="linux" and use_x11==1 and chromeos==0',
+            {
+                'angle_enable_gl%': 1,
+                'angle_enable_vulkan%': 1,
+            }],
+            ['OS=="mac"',
+            {
+                'angle_enable_gl%': 1,
+            }],
+        ],
+        'angle_enable_null%': 1, # Available on all platforms
+    },
+    'includes':
+    [
+        './src/compiler.gypi',
+        './src/libGLESv2.gypi',
+        './src/libEGL.gypi',
+        './src/vulkan_support/vulkan.gypi',
+    ],
+
+    'targets':
+    [
+        {
+            'target_name': 'angle_common',
+            'type': 'static_library',
+            'includes': [ './gyp/common_defines.gypi', ],
+            'sources':
+            [
+                '<@(libangle_common_sources)',
+            ],
+            'include_dirs':
+            [
+                './include',
+                './src',
+                './src/common/third_party/numerics',
+            ],
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(DEPTH)/third_party/angle/include',
+                    '<(DEPTH)/third_party/angle/src',
+                    '<(DEPTH)/third_party/angle/src/common/third_party/numerics',
+                ],
+                'conditions':
+                [
+                    ['dcheck_always_on==1',
+                    {
+                        'configurations':
+                        {
+                            'Release_Base':
+                            {
+                                'defines':
+                                [
+                                    'ANGLE_ENABLE_RELEASE_ASSERTS',
+                                ],
+                            },
+                        },
+                    }],
+                    ['OS=="win"',
+                    {
+                        'configurations':
+                        {
+                            'Debug_Base':
+                            {
+                                'defines':
+                                [
+                                    'ANGLE_ENABLE_DEBUG_ANNOTATIONS'
+                                ],
+                            },
+                        },
+                    }],
+                ],
+            },
+            'conditions':
+            [
+                ['dcheck_always_on==1',
+                {
+                    'configurations':
+                    {
+                        'Release_Base':
+                        {
+                            'defines':
+                            [
+                                'ANGLE_ENABLE_RELEASE_ASSERTS',
+                            ],
+                        },
+                    },
+                }],
+                ['OS=="win"',
+                {
+                    'configurations':
+                    {
+                        'Debug_Base':
+                        {
+                            'defines':
+                            [
+                                'ANGLE_ENABLE_DEBUG_ANNOTATIONS'
+                            ],
+                        },
+                    },
+                    'sources':
+                    [
+                        '<@(libangle_common_win_sources)',
+                    ],
+                }],
+                ['OS=="mac"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_common_mac_sources)',
+                    ],
+                    'link_settings':
+                    {
+                        'libraries':
+                        [
+                            '$(SDKROOT)/System/Library/Frameworks/IOKit.framework',
+                            '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+                        ],
+                    },
+                }],
+                ['OS=="linux"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_common_linux_sources)',
+                    ],
+                }]
+            ],
+        },
+
+        {
+            'target_name': 'angle_image_util',
+            'type': 'static_library',
+            'includes': [ './gyp/common_defines.gypi', ],
+            'sources':
+            [
+                '<@(libangle_image_util_sources)',
+            ],
+            'include_dirs':
+            [
+                './include',
+                './src',
+            ],
+            'dependencies':
+            [
+                'angle_common',
+            ],
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(DEPTH)/third_party/angle/include',
+                    '<(DEPTH)/third_party/angle/src',
+                ],
+            },
+        },
+
+        {
+            'target_name': 'angle_gpu_info_util',
+            'type': 'static_library',
+            'includes': [ './gyp/common_defines.gypi', ],
+            'sources':
+            [
+                '<@(libangle_gpu_info_util_sources)',
+            ],
+            'include_dirs':
+            [
+                './include',
+                './src',
+            ],
+            'dependencies':
+            [
+                'angle_common',
+            ],
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(DEPTH)/third_party/angle/include',
+                    '<(DEPTH)/third_party/angle/src',
+                ],
+            },
+            'conditions':
+            [
+                ['OS=="win"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_win_sources)',
+                    ],
+                }],
+                ['OS=="win" and angle_build_winrt==0',
+                {
+                    'link_settings':
+                    {
+                        'msvs_settings':
+                        {
+                            'VCLinkerTool':
+                            {
+                                'AdditionalDependencies':
+                                [
+                                    'setupapi.lib'
+                                ]
+                            }
+                        }
+                    },
+                    'defines':
+                    [
+                        'GPU_INFO_USE_SETUPAPI',
+                    ],
+                },
+                {
+                    'link_settings':
+                    {
+                        'msvs_settings':
+                        {
+                            'VCLinkerTool':
+                            {
+                                'AdditionalDependencies':
+                                [
+                                    'dxgi.lib'
+                                ]
+                            }
+                        }
+                    },
+                    'defines':
+                    [
+                        'GPU_INFO_USE_DXGI',
+                    ],
+                }],
+                ['OS=="linux"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_linux_sources)',
+                    ],
+                }],
+                ['OS=="linux" and use_x11==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_x11_sources)',
+                    ],
+                    'defines':
+                    [
+                        'GPU_INFO_USE_X11',
+                    ],
+                    'dependencies':
+                    [
+                        '<(DEPTH)/third_party/angle/src/third_party/libXNVCtrl/libXNVCtrl.gyp:libXNVCtrl',
+                    ],
+                    'link_settings':
+                    {
+                        'ldflags':
+                        [
+                            '<!@(<(pkg-config) --libs-only-L --libs-only-other x11 xi xext)',
+                        ],
+                        'libraries':
+                        [
+                            '<!@(<(pkg-config) --libs-only-l x11 xi xext) -ldl',
+                        ],
+                    },
+                }],
+                ['OS=="linux" and use_libpci==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_libpci_sources)',
+                    ],
+                    'defines':
+                    [
+                        'GPU_INFO_USE_LIBPCI',
+                    ],
+                    'link_settings':
+                    {
+                        'ldflags':
+                        [
+                            '<!@(<(pkg-config) --libs-only-L --libs-only-other libpci)',
+                        ],
+                        'libraries':
+                        [
+                            '<!@(<(pkg-config) --libs-only-l libpci)',
+                        ],
+                    },
+                }],
+                ['OS=="mac"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_mac_sources)',
+                    ],
+                }],
+            ],
+        },
+
+        {
+            'target_name': 'copy_scripts',
+            'type': 'none',
+            'includes': [ './gyp/common_defines.gypi', ],
+            'hard_dependency': 1,
+            'copies':
+            [
+                {
+                    'destination': '<(angle_gen_path)',
+                    'files': [ 'copy_compiler_dll.bat' ],
+                },
+            ],
+            'conditions':
+            [
+                ['angle_build_winrt==1',
+                {
+                    'type' : 'shared_library',
+                }],
+            ],
+        },
+    ],
+    'conditions':
+    [
+        ['OS=="win"',
+        {
+            'targets':
+            [
+                {
+                    'target_name': 'copy_compiler_dll',
+                    'type': 'none',
+                    'dependencies': [ 'copy_scripts', ],
+                    'includes': [ './gyp/common_defines.gypi', ],
+                    'conditions':
+                    [
+                        ['angle_build_winrt==0',
+                        {
+                            'actions':
+                            [
+                                {
+                                    'action_name': 'copy_dll',
+                                    'message': 'Copying D3D Compiler DLL...',
+                                    'msvs_cygwin_shell': 0,
+                                    'inputs': [ 'copy_compiler_dll.bat' ],
+                                    'outputs': [ '<(PRODUCT_DIR)/d3dcompiler_47.dll' ],
+                                    'action':
+                                    [
+                                        "<(angle_gen_path)/copy_compiler_dll.bat",
+                                        "$(PlatformName)",
+                                        "<(windows_sdk_path)",
+                                        "<(PRODUCT_DIR)"
+                                    ],
+                                },
+                            ], #actions
+                        }],
+                        ['angle_build_winrt==1',
+                        {
+                            'type' : 'shared_library',
+                        }],
+                    ]
+                },
+            ], # targets
+        }],
+    ] # conditions
+}
diff --git a/src/third_party/angle/build/all.gyp b/src/third_party/angle/build/all.gyp
deleted file mode 100644
index fff9998..0000000
--- a/src/third_party/angle/build/all.gyp
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'targets': [
-    {
-      'target_name': 'all',
-      'type': 'none',
-      'dependencies': [
-        # TODO(alokp): build_ prefix should be removed from the gyp files
-        # as soon as we can get rid of manually-maintained sln files.
-        # Otherwise auto-generated sln files will overwrite/conflict the
-        # manually maintained ones.
-        '../samples/build_samples.gyp:*',
-        '../src/build_angle.gyp:*',
-        '../tests/build_tests.gyp:*',
-      ],
-    },
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/src/third_party/angle/build/common.gypi b/src/third_party/angle/build/common.gypi
deleted file mode 100644
index fc9f295..0000000
--- a/src/third_party/angle/build/common.gypi
+++ /dev/null
@@ -1,190 +0,0 @@
-# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'variables': {
-    'component%': 'static_library',
-    # angle_code is set to 1 for the core ANGLE targets defined in src/build_angle.gyp.
-    # angle_code is set to 0 for test code, sample code, and third party code.
-    # When angle_code is 1, we build with additional warning flags on Mac and Linux.
-    'angle_code%': 0,
-    'gcc_or_clang_warnings': [
-      '-Wall',
-      '-Wchar-subscripts',
-      '-Werror',
-      '-Wextra',
-      '-Wformat=2',
-      '-Winit-self',
-      '-Wno-sign-compare',
-      '-Wno-unused-function',
-      '-Wno-unused-parameter',
-      '-Wno-unknown-pragmas',
-      '-Wpacked',
-      '-Wpointer-arith',
-      '-Wundef',
-      '-Wwrite-strings',
-    ],
-  },
-  'target_defaults': {
-    'default_configuration': 'Debug',
-    'variables': {
-      'warn_as_error%': 1,
-    },
-    'target_conditions': [
-      ['warn_as_error == 1', {
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'WarnAsError': 'true',
-          },
-        },
-      }],
-    ],
-    'configurations': {
-      'Common': {
-        'abstract': 1,
-        'msvs_configuration_attributes': {
-          'OutputDirectory': '$(SolutionDir)$(ConfigurationName)',
-          'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
-          'CharacterSet': '1',  # UNICODE
-        },
-        'msvs_configuration_platform': 'Win32',
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'BufferSecurityCheck': 'true',
-            'DebugInformationFormat': '3',
-            # TODO(alokp): Disable exceptions before integrating with chromium.
-            #'ExceptionHandling': '0',
-            'EnableFunctionLevelLinking': 'true',
-            'MinimalRebuild': 'false',
-            'PreprocessorDefinitions': [
-              '_CRT_SECURE_NO_DEPRECATE',
-              '_HAS_EXCEPTIONS=0',
-              '_WIN32_WINNT=0x0600',
-              '_WINDOWS',
-              'NOMINMAX',
-              'WIN32',
-              'WIN32_LEAN_AND_MEAN',
-              'WINVER=0x0600',
-            ],
-            'RuntimeTypeInfo': 'false',
-            'WarningLevel': '4',
-            'DisableSpecificWarnings': [4100, 4127, 4189, 4239, 4244, 4245, 4512, 4702],
-          },
-          'VCLinkerTool': {
-            'FixedBaseAddress': '1',
-            'GenerateDebugInformation': 'true',
-            'ImportLibrary': '$(OutDir)\\lib\\$(TargetName).lib',
-            'MapFileName': '$(OutDir)\\$(TargetName).map',
-            # Most of the executables we'll ever create are tests
-            # and utilities with console output.
-            'SubSystem': '1',  # /SUBSYSTEM:CONSOLE
-            'AdditionalLibraryDirectories': [
-              '$(ProgramFiles)/Windows Kits/8.0/Lib/win8/um/x86',
-            ],
-          },
-          'VCLibrarianTool': {
-            'AdditionalLibraryDirectories': [
-              '$(ProgramFiles)/Windows Kits/8.0/Lib/win8/um/x86',
-            ],
-          },
-          'VCResourceCompilerTool': {
-            'Culture': '1033',
-          },
-        },
-        'msvs_system_include_dirs': [
-          '$(ProgramFiles)/Windows Kits/8.0/Include/shared',
-          '$(ProgramFiles)/Windows Kits/8.0/Include/um',
-        ],
-      },  # Common
-      'Debug': {
-        'inherit_from': ['Common'],
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'Optimization': '0',  # /Od
-            'PreprocessorDefinitions': ['_DEBUG'],
-            'BasicRuntimeChecks': '3',
-            'RuntimeLibrary': '1',  # /MTd (debug static)
-          },
-          'VCLinkerTool': {
-            'LinkIncremental': '2',
-          },
-        },
-        'xcode_settings': {
-          'COPY_PHASE_STRIP': 'NO',
-          'GCC_OPTIMIZATION_LEVEL': '0',
-        },
-      },  # Debug
-      'Release': {
-        'inherit_from': ['Common'],
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'Optimization': '2',  # /Os
-            'PreprocessorDefinitions': ['NDEBUG'],
-            'RuntimeLibrary': '0',  # /MT (static)
-          },
-          'VCLinkerTool': {
-            'LinkIncremental': '1',
-          },
-        },
-      },  # Release
-    },  # configurations
-    'conditions': [
-      ['component=="shared_library"', {
-        'defines': ['COMPONENT_BUILD'],
-      }],
-    ],
-  },  # target_defaults
-  'conditions': [
-    ['OS=="win"', {
-      'target_defaults': {
-        'msvs_cygwin_dirs': ['../third_party/cygwin'],
-      },
-    }],
-    ['OS!="win" and OS!="mac"', {
-      'target_defaults': {
-        'cflags': [
-          '-pthread',
-          '-fno-exceptions',
-        ],
-        'ldflags': [
-          '-pthread',
-        ],
-        'configurations': {
-          'Debug': {
-            'variables': {
-              'debug_optimize%': '0',
-            },
-            'defines': [
-              '_DEBUG',
-            ],
-            'cflags': [
-              '-O>(debug_optimize)',
-              '-g',
-            ],
-          }
-        },
-      },
-    }],
-    ['angle_code==1', {
-      'target_defaults': {
-        'conditions': [
-          ['OS=="mac"', {
-            'xcode_settings': {
-              'WARNING_CFLAGS': ['<@(gcc_or_clang_warnings)']
-            },
-          }],
-          ['OS!="win" and OS!="mac"', {
-            'cflags': ['<@(gcc_or_clang_warnings)']
-          }],
-        ]
-      }
-    }],
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/src/third_party/angle/build/gyp_angle b/src/third_party/angle/build/gyp_angle
deleted file mode 100644
index 2aa38a5..0000000
--- a/src/third_party/angle/build/gyp_angle
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This script is wrapper for ANGLE that adds some support for how GYP
-# is invoked by ANGLE beyond what can be done in the gclient hooks.
-
-import os
-import sys
-
-script_dir = os.path.dirname(__file__)
-angle_dir = os.path.normpath(os.path.join(script_dir, os.pardir))
-
-sys.path.append(os.path.join(angle_dir, 'third_party', 'gyp', 'pylib'))
-import gyp
-
-if __name__ == '__main__':
-  args = sys.argv[1:]
-
-  print 'Updating projects from gyp files...'
-  sys.stdout.flush()
-
-  # Set the depth to get the top-level Makefile generated into the
-  # correct directory. This only has an effect on Linux.
-  args.append('--depth');
-  args.append('./trunk');
-  # Add common.gypi to the include path.
-  args.append('-I' + os.path.join(script_dir, 'common.gypi'))
-  # Add all.gyp as the main gyp file to be generated.
-  args.append(os.path.join(script_dir, 'all.gyp'))
-  sys.exit(gyp.main(args))
diff --git a/src/third_party/angle/doc/64BitSafety.md b/src/third_party/angle/doc/64BitSafety.md
new file mode 100644
index 0000000..94ed064
--- /dev/null
+++ b/src/third_party/angle/doc/64BitSafety.md
@@ -0,0 +1,15 @@
+# 64-bit Safety In the Compiler
+
+An issue that has arisen recently for contributors making changes to the GLSL ES
+grammar files has been that certain versions of flex, the lexer on which ANGLE
+relies, produce outputs which are not safe in 64-bit builds.
+
+To address this issue, ANGLE has added a step to its generation scripts to apply
+64-bit safety fixes to newly regenerated outputs. This should be unnoticeable to
+developers invoking flex via the generate\_parser.sh scripts in the relevant
+compiler directories, as the fixes will be applied by the patch utility as part
+of that script.
+
+When making code contributions that affect the grammar files, please ensure that
+you've generated the outputs using the script, to make certain that the 64-bit
+safety fixes are applied.
diff --git a/src/third_party/angle/doc/BranchingAndRolling.md b/src/third_party/angle/doc/BranchingAndRolling.md
new file mode 100644
index 0000000..19e2abc
--- /dev/null
+++ b/src/third_party/angle/doc/BranchingAndRolling.md
@@ -0,0 +1,55 @@
+# How to Branch and Roll Chromium's ANGLE Dependency
+
+ANGLE provides an implementation of OpenGL ES on Windows, which Chromium relies
+upon for hardware accelerated rendering and WebGL support. Chromium specifies
+its dependency on a specific version of ANGLE in the repository; this document
+describes how to update that dependency, and, if necessary, create an ANGLE
+branch to correspond to a branched release of Chrome.
+
+## Rolling DEPS
+
+Chromium's dependency on third-party projects is tracked in [the Chromium
+repository's src/DEPS file]
+(http://src.chromium.org/viewvc/chrome/trunk/src/DEPS). To update the ANGLE
+dependency:
+
+ * Find the line in this file that defines "src/third\_party/angle"
+for deps (**not** deps\_os)
+ * Change the [git SHA-1 revision number]
+(http://git-scm.com/book/ch6-1.html) to be that of the commit on which Chromium
+should depend. Please use the full SHA-1, not a shortened version.
+ * You can
+find the SHA-1 for a particular commit with `git log` on the appropriate branch
+of the repository, or via [the public repository viewer]
+(https://chromium.googlesource.com/angle/angle).
+ * If using the public repository viewer, you will need to select the branch whose log you wish to view
+from the list on the left-hand side, and then click on the "tree" link at the
+top of the resulting page. Alternatively, you can navigate to
+`https://chromium.googlesource.com/angle/angle/+/<branch name>/` -- including
+the terminating forward slash. (e.g.
+`https://chromium.googlesource.com/angle/angle/+/master/`)
+
+## Branching ANGLE
+
+Sometimes, individual changes to ANGLE are needed for a release of Chrome which
+has already been branched. If this is the case, a branch of ANGLE should be
+created to correspond to the Chrome release version, so that Chrome may
+incorporate only these changes, and not everything that has been committed since
+the version on which Chrome depended at branch time. **Please note: Only ANGLE
+admins can create a new branch.** To create a branch of ANGLE for a branched
+Chrome release:
+
+ * Determine what the ANGLE dependency is for the Chrome release
+by checking the DEPS file for that branch.
+ * Check out this commit as a new branch in your local repository.
+    * e.g., for [the Chrome 34 release at chrome/branches/1847]
+(http://src.chromium.org/viewvc/chrome/branches/1847/src/DEPS), the ANGLE
+version is 4df02c1ed5e97dd54576b06964b1da67ea30238e. To check this commit out
+locally and create a new branch named 'mybranch' from this commit, use: ```git
+checkout -b mybranch 4df02c1ed5e97dd54576b06964b1da67ea30238e```
+ * To create this new branch in the public repository, you'll need to push the
+branch to the special Gerrit reference location, 'refs/heads/<branch name>'. You
+must be an ANGLE administrator to be able to push this new branch.
+    * e.g., to use your local 'mybranch' to create a branch in the public repository called
+'chrome\_m34', use: ```git push origin mybranch:refs/heads/chrome_m34```
+    * The naming convention that ANGLE uses for its release-dedicated branches is 'chrome\_m##'.
diff --git a/src/third_party/angle/doc/BufferImplementation.md b/src/third_party/angle/doc/BufferImplementation.md
new file mode 100644
index 0000000..99eaf00
--- /dev/null
+++ b/src/third_party/angle/doc/BufferImplementation.md
@@ -0,0 +1,122 @@
+# Introduction
+
+Since Direct3D 9 only supports buffers that either contain vertex or index data,
+and OpenGL buffers can contain both, ANGLE waits till a draw call is issued to
+determine which resources to create/update. The generic implementation 'streams'
+the data into global vertex and index buffers. This streaming buffer
+implementation works in all circumstances, but does not offer optimal
+performance. When buffer data isn't updated, there's no reason to copy the data
+again. For these cases a 'static' buffer implementation is used.
+
+The OpenGL ES 2.0 glBufferData() function allows to specify a usage hint
+parameter (GL\_STREAM\_DRAW, GL\_DYNAMIC\_DRAW or GL\_STATIC\_DRAW). Both
+GL\_STREAM\_DRAW and GL\_DYNAMIC\_DRAW use the streaming buffer implementation.
+With the GL\_STATIC\_DRAW hint, ANGLE will attempt to use the static buffer
+implementation. If you update the buffer data after it has already been used in
+a draw call, it falls back to the streaming buffer implementation, because
+updating static ones would involve creating new ones, which is slower than
+updating streaming ones (more on this later).
+
+Because some applications use GL\_STREAM\_DRAW or GL\_DYNAMIC\_DRAW even when
+the data is not or very infrequently updated, ANGLE also has a heuristic to
+promote buffers to use the static implementation.
+
+# Streaming buffers
+
+The streaming buffers implementation uses one Context-global vertex buffer
+(VertexDataManager::mStreamingBuffer) and two index buffers
+(IndexDataManager::mStreamingBufferShort and
+IndexDataManager::mStreamingBufferInt). The streaming behavior is achieved by
+writing new data behind previously written data (i.e. without overwriting old
+data). Direct3D 9 allows to efficiently update vertex and index buffers when
+you're not reading or overwriting anything (it won't stall waiting for the GPU
+finish using it).
+
+When the end of these streaming buffers is reached, they are 'recycled' by
+discarding their content. D3D9 will still keep a copy of the data that's in use,
+so this recycling efficiently renames the driver level buffers. ANGLE can then
+write new data to the beginning of the vertex or index buffer.
+
+The ArrayVertexBuffer::mWritePosition variable holds the current end position of
+the last data that was written. StreamingVertexBuffer::reserveRequiredSpace()
+allocates space to write the data, and StreamingVertexBuffer::map() actually
+locks the D3D buffer and updates the write position. Similar for index buffers.
+
+# Static buffers
+
+Each GL buffer object can have a corresponding static vertex or index buffer
+(Buffer::mVertexBuffer and Buffer::mIndexBuffer). When a GL buffer with static
+usage is used in a draw call for the first time, all of its data is converted to
+a D3D vertex or index buffer, based on the attribute or index formats
+respectively. If a subsequent draw call uses different formats, the static
+buffer is invalidated (deleted) and the streaming buffer implementation is used
+for this buffer object instead. So for optimal performance it's important to
+store only a single format of vertices or indices in a buffer. This is highly
+typical, and even when in some cases it falls back to the streaming buffer
+implementation the performance isn't bad at all.
+
+The StreamingVertexBuffer and StaticVertexBuffer classes share a common base
+class, ArrayVertexBuffer. StaticVertexBuffer also has access to the write
+position, but it's used only for the initial conversion of the data. So the
+interfaces of both classes are not that different. Static buffers have an exact
+size though, and can't be changed afterwards (streaming buffers can grow to
+handle draw calls which use more data, and avoid excessive recycling).
+StaticVertexBuffer has a lookupAttribute() method to retrieve the location of a
+certain attribute (this is also used to verify that the formats haven't changed,
+which would result in invalidating the static buffer). The descriptions of all
+the attribute formats a static buffer contains are stored in the
+StaticVertexBuffer::mCache vector.
+
+StaticIndexBuffer also caches information about what's stored in them, namely
+the minimum and maximum value for certain ranges of indices. This information is
+required by the Direct3D 9 draw calls, and is also used to know the range of
+vertices that need to be copied to the streaming vertex buffer in case it needs
+to be used (e.g. it is not uncommon to have a buffer with static vertex position
+data and a buffer with streaming texture coordinate data for skinning).
+
+# Constant attributes
+
+Aside from using array buffers to feed attribute data to the vertex shader,
+OpenGL also supports attributes which remain constant for all vertices used in a
+draw call. Direct3D 9 doesn't have a similar concept, at least not explicitly.
+
+Constant attributes are implemented using separate (static) vertex buffers,
+and uses a stride of 0 to ensure that every vertex retrieves the same data.
+Using a stride of 0 is not possible with streaming buffers because on some
+hardware it is incompatible with the D3DUSAGE\_DYNAMIC flag. We found that with
+static usage, all hardware tested so far can handle stride 0 fine.
+
+This functionality was implemented in a ConstantVertexBuffer class, and it
+integrates nicely with the rest of the static buffer implementation.
+
+# Line loops
+
+Direct3D 9 does not support the 'line loop' primitive type directly. This is
+implemented by drawing the 'closing' line segment separately, constructing a
+tiny temporary index buffer connecting the last and first vertex.
+
+# Putting it all together
+
+glDrawElements() calls IndexDataManager::prepareIndexData() to retrieve a
+Direct3D index buffer containing the necessary data. If an element array is used
+(i.e. a buffer object), it has static usage, and it hasn't been invalidated, the
+GL buffer's static D3D index buffer will be returned. Else the updated streaming
+index buffer is returned, as well as the index offset (write position) where the
+new data is located. When prepareIndexData() does find a static index buffer,
+but it's empty, it means the GL buffer's data hasn't been converted and stored
+in the D3D index buffer yet. So in the convertIndices() call it will convert the
+entire buffer. prepareIndexData() will also look up the min/max value of a range
+of indices, or computes it when not already in the static buffer or when a
+streaming buffer is used.
+
+Similarly, both glDrawElements() and glDrawArrays() both call
+VertexDataManager::prepareVertexData() to retrieve a set of Direct3D vertex
+buffers and their translated format and offset information. It's implementation
+is more complicated than prepareIndexData() because buffer objects can contain
+multiple vertex attributes, and multiple buffers can be used as input to the
+vertex shader. So first it accumulates how much storage space is required for
+each of the buffers in use. For all static non-empty buffers in use, it
+determines whether the stored attributes still match what is required by the
+draw call, and invalidates them if not (at which point more space is allocated
+in the streaming buffer). Converting the GL buffer object's data into D3D
+compatible vertex formats is still done by specialized template functions.
diff --git a/src/third_party/angle/doc/BuildingAngleForChromiumDevelopment.md b/src/third_party/angle/doc/BuildingAngleForChromiumDevelopment.md
new file mode 100644
index 0000000..a3eac3e
--- /dev/null
+++ b/src/third_party/angle/doc/BuildingAngleForChromiumDevelopment.md
@@ -0,0 +1,83 @@
+# How to build ANGLE in Chromium for dev
+
+## Introduction
+
+On Windows, Linux, and Mac ANGLE now builds most core components cross platform, including the shader validator and translator as well as the graphics API translator. These parts can be built and tested inside a Chromium checkout.
+
+Steps:
+
+  * Checkout and build [Chromium](http://dev.chromium.org/Home).
+  * You should now be able to use `ninja -C out/Debug angle_end2end_tests`, for example.
+
+## Building Standalone ANGLE inside Chromium
+
+On Mac, ANGLE doesn't yet include the dEQP tests or the API translation libraries as part of Chromium. ANGLE also includes some sample applications and a few other targets that don't build on Chromium. These steps describe how to build such targets within a Chromium checkout.
+
+Steps:
+
+  * Checkout and build [Chromium](http://dev.chromium.org/Home).
+  * To setup run these commands (note similarity to [DevSetup](DevSetup.md)):
+
+```bash
+cd src/third_party/angle
+gclient config --name . --unmanaged https://chromium.googlesource.com/angle/angle.git
+
+gclient sync
+git checkout master
+```
+
+  * To make the build files run these commands
+
+```bash
+cd src/third_party/angle
+GYP_GENERATORS=ninja gclient runhooks
+```
+
+  * To build
+
+```bash
+cd src/third_party/angle
+ninja -j 10 -k1 -C out/Debug
+```
+
+  * To build a specific target add the target at the end:
+
+```bash
+cd src/third_party/angle
+ninja -j 10 -k1 -C out/Debug angle_gles2_deqp_tests
+```
+
+  * To run
+
+```bash
+cd src/third_party/angle
+./out/Debug/hello_triangle
+```
+
+If you decide to go back to the Chromium-managed version, just remove the `.gclient` file.
+
+## Working with Top of Tree ANGLE in Chromium
+
+If you're actively developing within ANGLE in your Chromium workspace you will want to work with top of tree ANGLE. To do this do the following:
+
+  * Ignore ANGLE in your `.gclient`
+
+```python
+solutions = [
+  {
+    # ...
+    u'custom_deps':
+    {
+      "src/third_party/angle": None,
+    },
+  },
+]
+```
+
+You then have full control over your ANGLE workspace and are responsible for running all git commands (pull, rebase, etc.) for managing your branches.
+
+If you decide you need to go back to the DEPS version of ANGLE:
+
+  * Comment out the `src/third_party/angle` line in your `custom_deps`.
+  * Go into your ANGLE workspace and switch back to the master branch (ensure there are no modified or new files).
+  * `gclient sync` your Chromium workspace.
diff --git a/src/third_party/angle/doc/BuildingAngleForWindowsStore.md b/src/third_party/angle/doc/BuildingAngleForWindowsStore.md
new file mode 100644
index 0000000..35f77c2
--- /dev/null
+++ b/src/third_party/angle/doc/BuildingAngleForWindowsStore.md
@@ -0,0 +1,55 @@
+# How to build ANGLE for Windows Store
+
+ANGLE provides OpenGL ES 2.0 and EGL 1.4 libraries and dlls.  You can use these to build and run OpenGL ES 2.0 applications on Windows.
+
+## Development setup
+
+ANGLE for Windows Store uses most of the same steps found in [ANGLE Development](DevSetup.md) with a few changes.
+
+### Required Tools
+ * [Visual Studio Community 2015](http://www.visualstudio.com/downloads/download-visual-studio-vs)
+   * Required to build ANGLE on Windows and for the packaged Windows 10 SDK.
+
+
+### Getting the source
+Set the following environment variables as needed:
+
+ * `GYP_GENERATORS` to `msvs`
+ * `GYP_MSVS_VERSION` to `2015`
+ * `GYP_GENERATE_WINRT` to `1`
+
+Download the ANGLE source by running the following commands:
+
+```
+git clone https://chromium.googlesource.com/angle/angle
+python angle/scripts/bootstrap.py
+gclient sync
+git checkout master
+```
+
+Gyp will generate multiple VS2015 solution files
+ * `winrt/10/src/angle.sln` for Windows 10
+
+
+### Building ANGLE
+ 1. Open one of the ANGLE Visual Studio solution files (see [Getting the source](BuildingAngleForWindowsStore.md#Development-setup-Getting-the-source)).
+ 2. Select Build -> Configuration Manager
+ 3. In the "Active solution configuration:" drop down, select the desired configuration (eg. Release), and close the Configuration Manager.
+ 4. Select Build -> Build Solution.
+Once the build completes, the output directory for your selected configuration (eg. `Release_Win32`, located next to the solution file) will contain the required libraries and dlls to build and run an OpenGL ES 2.0 application.
+
+### To Use ANGLE in Your Application
+ 1. A template for creating a Windows Store application that uses ANGLE can be found [here](http://blogs.msdn.com/b/vcblog/archive/2015/07/30/cross-platform-code-sharing-with-visual-c.aspx).
+ 2. Configure your build environment to have access to the `include` folder to provide access to the standard Khronos EGL and GLES2 header files.
+  * For Visual C++
+     * Right-click your project in the _Solution Explorer_, and select _Properties_.
+     * Under the _Configuration Properties_ branch, click _C/C++_.
+     * Add the relative path to the Khronos EGL and GLES2 header files to _Additional Include Directories_.
+ 3. Configure your build environment to have access to `libEGL.lib` and `libGLESv2.lib` found in the build output directory (see [Building ANGLE](DevSteup.md#Building-ANGLE)).
+   * For Visual C++
+     * Right-click your project in the _Solution Explorer_, and select _Properties_.
+     * Under the _Configuration Properties_ branch, open the _Linker_ branch and click _Input_.
+     * Add the relative paths to both the `libEGL.lib` file and `libGLESv2.lib` file to _Additional Dependencies_, separated by a semicolon.
+ 4. Copy `libEGL.dll` and `libGLESv2.dll` from the build output directory (see [Building ANGLE](DevSetup.md#Building-ANGLE)) into your application folder or packages location if a ANGLE Windows Store NuGet was used.
+ 5. Code your application to the Khronos [OpenGL ES 2.0](http://www.khronos.org/registry/gles/) and [EGL 1.4](http://www.khronos.org/registry/egl/) APIs.
+
diff --git a/src/third_party/angle/doc/ChoosingANGLEBranch.md b/src/third_party/angle/doc/ChoosingANGLEBranch.md
new file mode 100644
index 0000000..c2ac1ae
--- /dev/null
+++ b/src/third_party/angle/doc/ChoosingANGLEBranch.md
@@ -0,0 +1,68 @@
+# Choosing an ANGLE branch for your project
+
+ANGLE is under continuous development, and does not create release tarballs or
+tag specific revisions as releases, which may make the process of choosing a
+point in ANGLE's history as the dependency for your project less than obvious.
+This document illustrates how to choose a branch of ANGLE which can be expected
+to be updated with critical fixes, should they be needed.
+
+## ANGLE automatic branching
+
+Branches are created automatically in ANGLE to correspond to branches created in
+Chromium. These branches are named `chromium/####`, where the number is the
+matching Chromium branch. These branches will be created from the revision which
+that Chromium branch points to as its dependency. So, for example, the
+`chromium/2013` branch point is at r28bcf4ff, because [Chromium's dependency
+file for the 2013 branch]
+(http://src.chromium.org/viewvc/chrome/branches/2013/src/DEPS?revision=272741)
+uses this ANGLE revision.
+
+It isn't necessary to be familiar with how Chromium's dependency management
+works to choose an appropriate ANGLE branch for your project. You will, however,
+likely want to make sure that you choose a branch that is used for a relatively
+stable Chromium release channel build, as those branches will be deployed with
+Chromium, and receive updates if bugs are found and fixed during release
+lifetime, while the more volatile channels will turn over quickly, and their
+branches will be short-lived.
+
+**We recommend choosing a branch corresponding to a Beta or Stable Chromium
+release** if you are pursuing periodic, not continuous, integration of ANGLE.
+
+## Matching a Chromium release to an ANGLE branch
+
+In order to determine which branches are used by Chromium releases, please use
+[the OmahaProxy tool](http://omahaproxy.appspot.com/), which lists build
+information about current Chromium releases. Find the entry for a suitable
+release channel (for now, we recommend one of the Windows desktop releases), and
+note the branch listed in the `true_branch` column. This identifies the ANGLE
+branch used by that Chromium release.
+
+## Updates to release branches
+
+If bugs (stability, security, performance, or otherwise) are discovered after a
+branch has been created, and that branch is used by a Chromium release, the
+fixes for those bugs will be applied to the ANGLE branches for uptake by
+Chromium and any other projects using that branch. You should need only to
+perform a `git pull` to check for and apply any such changes.
+
+## Cherry-picking a change to a release branch
+
+Occasionally a bug fix must be merged back to an earlier Chromium
+release branch. To do this, first look up the branch number in
+[OmahaProxy](https://omahaproxy.appspot.com/). For example, M55
+corresponds to branch number 2883.
+
+In the simple case where there are no conflicts, the merge can be done
+entirely in the Gerrit UI. Click the "Cherry pick" button and enter
+`chromium/[branch_number]` as the branch to merge to.
+
+If there are conflicts, however, follow these steps:
+
+1. `git checkout chromium/[branch_number]`
+2. `git cherry-pick [commit_hash]`
+3. Fix any merge conflicts.
+4. `git cl upload`
+
+Have the cherry-pick reviewed, and then land it. It's also OK to skip
+the review and land it yourself with TBR= in the issue description, if
+you have that ability.
diff --git a/src/third_party/angle/doc/CodeReviewProcess.md b/src/third_party/angle/doc/CodeReviewProcess.md
new file mode 100644
index 0000000..9a53e2a
--- /dev/null
+++ b/src/third_party/angle/doc/CodeReviewProcess.md
@@ -0,0 +1,57 @@
+# ANGLE's Code Review Process
+
+This page describes the review process for ANGLE reviewers and committers. For
+instructions on submitting your change list for review, please see
+[ContributingCode](ContributingCode.md).
+
+## Reviewing Changes
+
+The author of a CL may designate reviewers. Please feel free to weigh in on
+changes even if you are not a designated reviewer!
+
+1.  To review a change, you can either navigate directly to the URL for the CL,
+    or, if you are one of the designated reviewers, the change will appear in
+    your dashboard at https://chromium-review.googlesource.com/
+2.  Review the change listed by looking over the diffs listed in the most recent
+    patch set.
+    *   You may view the diffs either side-to-side, or in unified diff format.
+    *   You can comment on a specific line of code by double-clicking that line,
+        or on the file as a whole by clicking the "Add file comment" icon, which
+        appears above the diff, in the line number column.
+    *   Note that, for CLs submitted as fixes to standing bugs, style issues
+        that pre-exist the CL are not required to be addressed in the CL. As a
+        reviewer, you can request a follow-up CL to address the style issue if
+        you desire. This exception doesn't apply for CLs which implement new
+        functionality, perform refactoring, or introduce style issues
+        themselves.
+3.  Once your review is complete, click the "Review" button
+    *   If you are satisfied with the change list as it is, give a positive
+        review (Code-Review +1 or +2).
+    *   If you think the change list is a good idea, but needs changes, leave
+        comments and a neutral review. (Code-Review 0)
+    *   If you think the change list should be abandoned, give a negative
+        review. (Code-Review -1 or -2)
+    *   A +2 code review is required before landing. Only ANGLE committers may
+        provide a +2 code review.
+    *   ANGLE has a 2-reviewer policy for CLs. This means all changes should get
+        a positive review from more than one person before they are accepted.
+        This is most usually handled by reserving the +2 review for the second
+        reviewer to clear the CL.
+    *   If you made comments on the files, the draft comments will appear below
+        the cover message. These comments are not published until you click on
+        the "Publish Comments" button.
+4.  Verification and landing:
+    *   If the CL author is not an ANGLE committer, the CL should be verified
+        and landed by a committer. Once verified, the "+1 Verified" status may
+        be added, and the CL may be landed with the "Publish and Submit" button.
+        There should be no need to rebase via the "Rebase Change" button prior
+        to landing.
+    *   If the CL author is an ANGLE committer, they should verify and land the
+        CL themselves.
+    *   Please note: Verification and commit-queue workflow may be subject to
+        change in the near future.
+5.  Cherry-picking to other branches
+    *   If the change is needed on other branches, you may be able to land it
+        using the "Cherry Pick To" button on the CL page.
+    *   If this cherry pick fails, you will need to rebase the patch yourself
+        and submit a new change for review on the branch.
diff --git a/src/third_party/angle/doc/CodingStandard.md b/src/third_party/angle/doc/CodingStandard.md
new file mode 100644
index 0000000..cc43b26
--- /dev/null
+++ b/src/third_party/angle/doc/CodingStandard.md
@@ -0,0 +1,155 @@
+# Coding Standard for the ANGLE Project
+
+## Google Style Guide
+
+We generally use the [Google C++ Style Guide]
+(http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml) as a basis for
+our Coding Standard, however we will deviate from it in a few areas, as noted
+below.
+
+Items marked {DEV} indicate a deviation from the Google guidelines. Items marked
+{DO} are reiterating points from the Google guidelines.
+
+Before you upload code to Gerrit, use `git cl format` to auto-format your code.
+This will catch most of the trivial formatting errors and save you time.
+
+### [Header Files](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Header_Files)
+
+*   We will use **`.h`** for C++ headers.
+*   {DEV} #define guards should be of the form: `<PATH>_<FILE>_H_`. (Compiler
+    codebase is varied, including `<PROJECT>_` makes the names excessively
+    long).
+
+### [Scoping](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Scoping)
+
+*   {DO} avoid globally scoped variables, unless absolutely necessary.
+
+### [Classes](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Classes)
+
+*   {DEV} Inherit (privately) from angle::NonCopyable helper class (defined in
+    common/angleutils.h) to disable default copy and assignment operators.
+
+### [Other C++ Features](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Other_C++_Features)
+
+*   {DEV} all parameters passed by reference, except for STL containers (e.g.
+    std::vector, std::list), must be labeled `const`. For return parameters
+    other than STL containers, use a pointer.
+*   {DO} avoid use of default arguments.
+*   {DONT} use C++ exceptions, they are disabled in the builds and not caught.
+*   {DO} use nullptr (instead of 0 or NULL) for pointers.
+*   {DO} use size\_t for loop iterators and size values.
+*   {DO} use uint8\_t pointers instead of void pointers to denote binary data.
+*   {DO} use C++11 according to the [Chromium guide on C++11]
+    (http://chromium-cpp.appspot.com/).
+
+### [Naming ](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Naming)
+
+#### File Names
+
+*   {DEV} Filenames should be all lowercase and can include underscores (`_`).
+    If the file is an implementation of a class, the filename may be capitalized
+    the same as the major class.
+*   {DEV} We use .cpp (instead of .cc), .h and .inl (inlined files) for C++
+    files and headers.
+
+#### Directory Names
+*   Directory names should be all lowercase, unless following an externally
+    imposed capitalization (eg include/EGL, or src/libGLESv2, etc)
+
+#### Variable Names
+
+Use the following guidelines, they do deviate somewhat from the Google
+guidelines.
+
+* class and type names: start with capital letter and use CamelCase.
+* {DEV} class member variables: use an **`m`** prefix instead of trailing
+underscore and use CamelCase.
+* global variables (if they must be used): use a **`g_`** prefix.
+* {DEV} variable names: start with lower case and use CamelCase (chosen for consistency)
+* {DEV} function names: Member functions start with lower case and use CamelCase. Non-member functions start with capital letter and
+use CamelCase (chosen for consistency)
+* Constants: start with a **`k`** and use CamelCase
+* namespaces: use all lower case
+* Enum Names - use class enums, and the values should be uppercase with underscores.
+* macros: all uppercase with underscores
+* exceptions to naming: use common sense!
+
+### [Comments](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Comments)
+
+*   {DO} read and follow Google's recommendations.
+*   Each file **must** start with the following boilerplate notice:
+
+```
+//
+//  Copyright (c) 2016 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.
+//
+```
+
+### [Formatting](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Formatting)
+
+*   {DEV} Avoid excessively long lines. Please keep lines under 100 columns
+    long.
+*   Use unix-style newlines.
+*   {DO} use only spaces. No tab characters. Configure your editor to emit
+    spaces when you hit the TAB-key.
+*   {DEV} indent 4 spaces at a time.
+*   conditionals: place space outside the parenthesis. No spaces inside.
+*   switch statements: use the output of `git cl format`.
+*   class format(eg private, public, protected): indent by 2 spaces. Regular
+    4-space indent from the outer scope for declarations/definitions.
+*   pointers and references: **`*`** and **`&`** tight against the variable
+*   namespaces: are not indented.
+*   extern code blocks: are not indented.
+*   {DEV} braces should go on a separate line, except for functions defined in a
+    header file where the whole function declaration and definition fit on one
+    line.
+
+Examples:
+
+```
+if (conditional)
+{
+    stuff();
+}
+else
+{
+    otherstuff()
+}
+```
+
+```
+switch (conditional)
+{
+  case foo:
+    dostuff();
+    break;
+  case bar:
+    otherstuff();
+    break;
+  default:
+    WTFBBQ();
+}
+```
+
+```
+class MyClass : public Foo
+{
+  public:
+    MyClass();
+    ~MyClass() {};
+  private:
+    DISALLOW_COPY_AND_ASSIGN(MyClass);
+};
+```
+
+```
+char *c;
+const string &str;
+```
+
+### [Exceptions to the Rules](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Exceptions_to_the_Rules)
+
+*   If modifying pre-existing code that does not match the standard, the altered
+    portions of the code should be changed to match the standard.
diff --git a/src/third_party/angle/doc/CompilingTranslatorWithEmscripten.md b/src/third_party/angle/doc/CompilingTranslatorWithEmscripten.md
new file mode 100644
index 0000000..fc7b17f
--- /dev/null
+++ b/src/third_party/angle/doc/CompilingTranslatorWithEmscripten.md
@@ -0,0 +1,109 @@
+# Introduction
+
+There are many situations in which it's useful for WebGL applications to
+transform shaders in various ways. ANGLE's shader translator can be used for
+this purpose: compiling it with [Emscripten](http://emscripten.org/) allows it
+to be invoked from a web page. This wiki page provides some preliminary details
+about how to do this.
+
+# Details
+
+Pull top of tree ANGLE.
+
+Install the Emscripten toolchain per the [instructions]
+(http://kripken.github.io/emscripten-site/).
+
+Symlink (preferred) or copy the ANGLE directory into ...emsdk/emscripten/master.
+
+Put a shader to compile into a file (named with .vert or .frag suffix) in the
+same directory. For example, put the following shader from the [WebGL Aquarium]
+(http://webglsamples.org/aquarium/aquarium.html) into `aq-fish-nm.frag`:
+
+```
+precision mediump float;
+uniform vec4 lightColor;
+varying vec4 v_position;
+varying vec2 v_texCoord;
+varying vec3 v_tangent;  // #normalMap
+varying vec3 v_binormal;  // #normalMap
+varying vec3 v_normal;
+varying vec3 v_surfaceToLight;
+varying vec3 v_surfaceToView;
+
+uniform vec4 ambient;
+uniform sampler2D diffuse;
+uniform vec4 specular;
+uniform sampler2D normalMap;  // #normalMap
+uniform float shininess;
+uniform float specularFactor;
+// #fogUniforms
+
+vec4 lit(float l ,float h, float m) {
+  return vec4(1.0,
+              max(l, 0.0),
+              (l > 0.0) ? pow(max(0.0, h), m) : 0.0,
+              1.0);
+}
+void main() {
+  vec4 diffuseColor = texture2D(diffuse, v_texCoord);
+  mat3 tangentToWorld = mat3(v_tangent,  // #normalMap
+                             v_binormal,  // #normalMap
+                             v_normal);  // #normalMap
+  vec4 normalSpec = texture2D(normalMap, v_texCoord.xy);  // #normalMap
+  vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5);  // #normalMap
+  tangentNormal = normalize(tangentNormal + vec3(0, 0, 2));  // #normalMap
+  vec3 normal = (tangentToWorld * tangentNormal);  // #normalMap
+  normal = normalize(normal);  // #normalMap
+  vec3 surfaceToLight = normalize(v_surfaceToLight);
+  vec3 surfaceToView = normalize(v_surfaceToView);
+  vec3 halfVector = normalize(surfaceToLight + surfaceToView);
+  vec4 litR = lit(dot(normal, surfaceToLight),
+                    dot(normal, halfVector), shininess);
+  vec4 outColor = vec4(
+    (lightColor * (diffuseColor * litR.y + diffuseColor * ambient +
+                  specular * litR.z * specularFactor * normalSpec.a)).rgb,
+      diffuseColor.a);
+  // #fogCode
+  gl_FragColor = outColor;
+}
+```
+
+Compile the shader translator, the translator sample, and the shader all
+together:
+
+```
+./emcc -Iangle/include -Iangle/src angle/samples/translator/translator.cpp angle/src/compiler/preprocessor/*.cpp angle/src/compiler/translator/*.cpp angle/src/compiler/translator/timing/*.cpp angle/src/compiler/translator/depgraph/*.cpp angle/src/third_party/compiler/*.cpp angle/src/common/*.cpp -o translator.html --preload-file aq-fish-nm.frag -s NO_EXIT_RUNTIME=1
+```
+
+Serve up the resulting translator.html via `python -m SimpleHTTPServer`.
+Navigate the browser to localhost:8000.
+
+The translator sample will run, displaying its output into the text area on the
+page. Since it isn't receiving any input, it simply outputs a help message and
+exits.
+
+To invoke the translator again, processing the shader we included along with the
+source code, open the JavaScript console and type:
+
+```
+Module['callMain'](['-s=w', '-u', 'aq-fish-nm.frag'])
+```
+
+The active uniforms and their types will be printed to the text area after the
+translator sample processes the shader.
+
+# Issues and Next Steps
+
+It's clearly not useful to have to compile the shader in to the
+Emscripten-translated executable. It would be helpful to define a simple wrapper
+function which can easily be called from JavaScript and which defines enough
+parameters to pass in a shader as a string, transform it somehow or compile it
+to another language target, and return the compiled result (or other
+information). A simple JavaScript library that wraps all of the interactions
+with the Emscripten binary would be useful.
+
+It's not feasible to interact with the translator's data structures, nor
+traverse the AST from JavaScript. The code that operates upon the shader must be
+written in C++ and compiled in to the shader translator.
+
+emcc should be integrated better with ANGLE's build system.
diff --git a/src/third_party/angle/doc/ContributingCode.md b/src/third_party/angle/doc/ContributingCode.md
new file mode 100644
index 0000000..ff11143
--- /dev/null
+++ b/src/third_party/angle/doc/ContributingCode.md
@@ -0,0 +1,105 @@
+# Contributing Code
+
+## Communicate
+
+ * Whether you're writing a new feature or fixing an existing bug, it pays to get a second opinion before you get too far. If it's a new feature idea, post to the discussion group ([angleproject](https://groups.google.com/forum/?fromgroups#!forum/angleproject)) and propose it or talk with the ANGLE team on IRC in the #ANGLEproject channel on FreeNode.
+ * Not all bugs in our [bug system](https://code.google.com/p/angleproject/issues/list) are assigned, but if the one you're interested in fixing is, send a note to the person it's assigned to and ask if they would like a patch.
+ * Behavior changes and anything nontrivial (i.e. anything other than simple cleanups and style fixes) should generally be tracked in the bug system. Please [file a bug](http://anglebug.com/new) and describe what you're doing if there isn't one already.
+
+## Get your code ready
+### Code
+ 1. Must conform to the [ANGLE style](CodingStandard.md) guidelines.
+ 2. Must be tested. (see the 'Testing' section below)
+ 3.  Should be a reasonable size to review.  Giant patches are unlikely to get reviewed quickly.
+
+### Build maintenance
+ 1. If you added or removed source files:
+    * You _must_ update the gyp build scripts lists with your changes. See `src/libEGL.gypi`, `src/libGLESv2.gypi`, and `src/compiler.gypi`.
+ 2. ANGLE also now maintains a BUILD.gn script for  [Chromium's gn build](https://code.google.com/p/chromium/wiki/gn).  If you changed the gyp files other than to add or remove new files, you will also need to update BUILD.gn. Ask a project member for help with testing if you don't have a Chromium checkout.
+ 3. If you modified `glslang.y` or `glslang.l`:
+    * You _must_ update the bison-generated compiler sources. Download and install the latest 64-bit Bison and flex from official [Cygwin](https://cygwin.com/install.html) on _Windows_. From the Cygwin shell run `generate_parser.sh` in `src/compiler/translator` and update your CL. Do not edit the generated files by hand.
+    * _NOTE:_ You can ignore failing chunk messages if there are no compile errors.
+    * If you modified `ExpressionParser.y` or `Tokenizer.l`, follow the same process by running `src/compiler/preprocessor/generate_parser.sh`.
+
+### Testing
+ * ANGLE uses trybots to test on a variety of platforms. Please run your changes against our bots and check the results before landing changes or requesting reviews.
+    * Upload your change (see [Making changes](ContributingCode.md#making-changes)).
+    * To kick of a try job, use the 'CQ Dry Run' button, or set the Commit-Queue +1 label to trigger a dry run of the CQ (will not land the change).
+    * If you are not part of the `angle-committers` group, you will need to either ask to be added or ask a member of the group to submit the tryjob for you. Add jmadill or geofflang as a reviewer for assistance.
+    * Wait for the bots to report the result on the code review page. The bot results should be visible in Gerrit as yellow (in-progress), green (passed), or red (failed). This can take up to two hours for some of the debug bots. Click on the colored rectangle to open the bot log to triage failed tests.
+    * If a failure is unexpected, or seems likely unrelated to your change, ask an ANGLE project member for advice.
+    * We do not currently have the capability to run individual bots or tests in a run.
+ * Tests can also be run locally, ANGLE's main testing methods are:
+    * `angle_unittests`, `angle_end2end_tests` and `angle_white_box_tests` targets.
+    * The [Top-of-Tree WebGL Conformance tests](https://www.khronos.org/registry/webgl/sdk/tests/webgl-conformance-tests.html).
+      * If you are a Chromium developer, see [Building ANGLE for Chromium Development](BuildingAngleForChromiumDevelopment.md) for instructions on building ANGLE within Chromium.
+      * If you aren't a browser developer, you should be able to drop your compiled DLLs into a Chrome installation, in place of those distributed with Chrome, to check WebGL conformance. [Chrome Canary](https://www.google.com/chrome/browser/canary.html) is well-suited for this.
+    * If your code isn't covered by an existing test, you are *strongly encouraged* to add new test coverage. This both ensures that your code is correct and that new contributors won't break it in the future.
+    * Add new tests to `angle_end2end_tests` for OpenGL-based API tests, `angle_unittests` for cross-platform internal tests, and `angle_white_box_tests` for rendering tests which also need visibility into internal ANGLE classes.
+   * If you are submitting a performance fix, test your code with `angle_perftests` and add a new performance test if it is not covered by the existing benchmarks.
+   * The [Chromium GPU FYI bot waterfall](http://build.chromium.org/p/chromium.gpu.fyi/console) provides continuous integration for ANGLE patches that have been committed.  There may be hardware configurations that are not tested by the ANGLE trybots, if you notice breakage on this waterfall after landing a patch, please notify a project member.
+   * ANGLE also includes the [drawElements Quality Program (dEQP)](dEQP.md) for additional testing. If you're working on a new feature, there may be some extensive tests for it already written.
+
+### Legal
+ 1. You must complete the [Individual Contributor License Agreement](http://code.google.com/legal/individual-cla-v1.0.html). You can do this online, and it only takes a minute. If you are contributing on behalf of a corporation, you must fill out the [Corporate Contributor License Agreement](http://code.google.com/legal/corporate-cla-v1.0.html) and send it to Google as described on that page.
+ 2. Once you've submitted the CLA, please email the following information (as entered on the CLA) to `shannonwoods at chromium dot org` for record keeping purposes:
+    * Full Name:
+    * Email:
+    * Company (If applicable):
+ 3. If you've never submitted code before, you must add your (or your organization's) name and contact info to the [AUTHORS](../AUTHORS) file.
+ 4. *NOTE TO REVIEWERS*: Follow the [External Contributor Checklist](http://www.chromium.org/developers/contributing-code/external-contributor-checklist).
+
+## Life of a Change List
+
+### Getting started with Gerrit for ANGLE
+  1. Go to [https://chromium-review.googlesource.com/new-password](https://chromium-review.googlesource.com/new-password)
+  2. Log in with the email you use for your git commits.
+  3. Follow the directions on the new-password page to set up authentication with your Google account.
+  4. Make sure to set your real name.
+     * Visit [https://chromium-review.googlesource.com/#/settings](https://chromium-review.googlesource.com/#/settings) and check the "Full Name" field.
+  5. Check out the repository (see [DevSetup](DevSetup.md)).
+  6. Install the Gerrit `commit_msg` hook
+     * Gerrit requires a hook to append a change ID tag to each commit, so that it can associate your CL with a particular review, and track dependencies between commits.
+     * Download the hook from [https://chromium-review.googlesource.com/tools/hooks/commit-msg](https://chromium-review.googlesource.com/tools/hooks/commit-msg) and copy this file to `.git/hooks/commit-msg` within your local repository. On non-Windows, platforms, ensure that permissions are set to allow execution.
+     * *BE AWARE:* Some patch management tools, such as StGit, currently bypass git hooks. They should not currently be used with changes intended for review.
+
+### Making changes {#making-changes}
+ 1. Commit your changes locally:
+    * `git add src/../FileName.cpp`
+    * `git commit`
+    * A text editor will open. Add a description at the top of the file.
+       * If your changes are associated with an issue in the issue tracker (e.g. a fix for a reported bug), please associate the CL with that issue by adding the following line to the commit message: `BUG=angleproject:<issue number>`.
+    * Save.
+    * Close the text editor.
+    * Use `git commit --amend` to update your CL with new changes.
+    * Use `git cl format` to amend the style of your CL. This saves both your time and the reviewers'!
+ 2. Ensure your code is landed on top of latest changes
+    * `git pull --rebase`
+    * Resolve conflicts if necessary
+ 3. Upload the change list
+    * `git cl upload`
+    * The change list and modified files will be uploaded to
+      [ANGLE Gerrit](https://chromium-review.googlesource.com/#/q/project:angle/angle).
+    * Follow the generated URL to the new issue.
+    * Take a moment to perform a self-review of your code. Gerrit's viewer makes it easy to see whitespace errors, erroneous tabs, and other simple style problems.
+    * Designate reviewers-- if you don't do this, reviewers may not realize you're requesting a review!
+      * If you don't know who to use, select either `geofflang at chromium dot org` or `jmadill at chromium dot org`.
+    * Make changes, upload and repeat as necessary.
+    * Project members and others will review your code as described in the [CodeReviewProcess](CodeReviewProcess.md).
+ 5. If your change list needs revision:
+    * If you have correctly installed the commit hook from the section above, Gerrit will be able to track your changes by Change-Id.
+    * You should need only to update your commit with `git commit --amend` and re-upload with `git cl upload`.
+ 6. Landing change after it receives +2 Code Review:
+    * If you are a committer, you may submit the change yourself via the Gerrit web interface.
+    * If you are not a committer, ask your reviewer to submit the change list.
+ 7. Pull and integrate reviewed CL:
+    * `git pull --rebase`
+
+
+See also:
+
+* [ANGLE Gerrit](https://chromium-review.googlesource.com/#/q/project:angle/angle)
+* [Chromium Projects: Contributing Code](http://www.chromium.org/developers/contributing-code/)
+* [depot_tools tutorial](http://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html)
+
+
diff --git a/src/third_party/angle/doc/DebuggingTips.md b/src/third_party/angle/doc/DebuggingTips.md
new file mode 100644
index 0000000..f7bcf24
--- /dev/null
+++ b/src/third_party/angle/doc/DebuggingTips.md
@@ -0,0 +1,25 @@
+# Debugging Tips
+
+There are many ways to debug ANGLE using generic or platform-dependent tools. Here is a list of tips on how to use them.
+
+## Running ANGLE under apitrace on Linux
+
+[Apitrace](http://apitrace.github.io/) that captures traces of OpenGL commands for later analysis, allowing us to see how ANGLE translates OpenGL ES commands. In order to capture the trace, it inserts a driver shim using `LD_PRELOAD` that records the command and then forwards it to the OpenGL driver.
+
+The problem with ANGLE is that it exposes the same symbols as the OpenGL driver so apitrace captures the entry point calls intended for ANGLE and reroutes them to the OpenGL driver. In order to avoid this problem, use the following:
+
+1. Compile ANGLE as a static library so that it doesn't get shadowed by apitrace's shim using the `-D angle_gl_library_type=static_library` gyp flag.
+2. Ask apitrace to explicitly load the driver instead of using a dlsym on the current module. Otherwise apitrace will use ANGLE's symbols as the OpenGL driver entrypoint (causing infinite recursion). To do this you must point an environment variable to your GL driver. For example: `export TRACE_LIBGL=/usr/lib/libGL.so.1`. You can find your libGL with `ldconfig -p | grep libGL`.
+3. Link ANGLE against libGL instead of dlsyming the symbols at runtime; otherwise ANGLE won't use the replaced driver entry points. This can be done by adding `-D angle_link_glx=1`.
+
+If you follow these steps, apitrace will work correctly aside from a few minor bugs like not being able to figure out what the default framebuffer size is if there is no glViewport command.
+
+For example, to trace a run of `hello_triangle`, assuming you are using the ninja gyp generator and the apitrace executables are in `$PATH`:
+
+```
+./gyp/gyp_angle -D angle_link_glx=1 -D angle_gl_library_type=static_library
+ninja -C out/Debug
+export TRACE_LIBGL="/usr/lib/libGL.so.1" # may require a different path
+apitrace trace -o mytrace ./out/Debug/hello_triangle
+qapitrace mytrace
+```
diff --git a/src/third_party/angle/doc/DevSetup.md b/src/third_party/angle/doc/DevSetup.md
new file mode 100644
index 0000000..0553301
--- /dev/null
+++ b/src/third_party/angle/doc/DevSetup.md
@@ -0,0 +1,165 @@
+# ANGLE Development
+
+ANGLE provides OpenGL ES 2.0 and EGL 1.4 libraries and dlls.  You can use these to build and run OpenGL ES 2.0 applications on Windows.
+
+## Development setup
+
+### Version Control
+ANGLE uses git for version control. If you are not familiar with git, helpful documentation can be found at [http://git-scm.com/documentation](http://git-scm.com/documentation).
+
+### Required Tools
+On all platforms:
+
+ * [depot_tools](http://dev.chromium.org/developers/how-tos/install-depot-tools)
+   * Required to generate projects and build files, contribute patches, run the unit tests or build the shader compiler on non-Windows systems.
+
+On Windows:
+
+ * [Visual Studio Community 2015 Update 3](https://www.visualstudio.com/en-us/news/releasenotes/vs2015-update3-vs)
+   * Required to build ANGLE on Windows and for the packaged Windows 10 SDK. Note: Chrome is in the process of upgrading to Visual Studio 2017. ANGLE will switch over once Chrome does.
+ * [Windows 10 Standalone SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk) (recommended)
+    * Not required to build, but comes with additional features that aid ANGLE development, such as the Debug runtime for D3D11.
+ * [Cygwin's Bison, flex, and patch](https://cygwin.com/setup-x86_64.exe) (optional)
+    * This is only required if you need to modify GLSL ES grammar files (`glslang.l` and `glslang.y` under `src/compiler/translator`, or `ExpressionParser.y` and `Tokenizer.l` in `src/compiler/preprocessor`).
+     Use the latest versions of bison, flex and patch from the 64-bit cygwin distribution.
+
+On Linux:
+
+ * The GCC or Clang compilers
+ * Development packages for OpenGL, X11 and libpci
+ * Bison and flex are not needed as we only support generating the translator grammar on Windows.
+
+On MacOS:
+
+ * [XCode](https://developer.apple.com/xcode/) for Clang and development files.
+ * Bison and flex are not needed as we only support generating the translator grammar on Windows.
+
+### Getting the source
+Set the following environment variables as needed:
+
+On Windows:
+
+ * `GYP_GENERATORS` to `msvs` (other options include `ninja` and `make`)
+ * `GYP_MSVS_VERSION` to `2015`
+
+On Linux and MacOS:
+
+ * `GYP_GENERATORS` to `ninja` (defaults to 'make' that pollutes your source directory)
+
+Download the ANGLE source by running the following commands:
+
+```
+git clone https://chromium.googlesource.com/angle/angle
+cd angle
+python scripts/bootstrap.py
+gclient sync
+git checkout master
+```
+
+GYP will generate the project files, if you update ANGLE or make a change to the projects, they can be regenerated by executing `gclient runhooks`.
+
+On Windows GYP will generate the main VS2015 solution file as gyp/ANGLE.sln. For generating a Windows Store version of ANGLE view the [Windows Store instructions](doc/BuildingAngleForWindowsStore.md).
+
+On Linux and MacOS, GYP will generate the `out/Debug` and `out/Release` directories.
+
+### Building ANGLE on Windows
+ 1. Open one of the ANGLE Visual Studio solution files (see [Getting the source](DevSetup.md#Development-setup-Getting-the-source)).
+ 2. Select Build -> Configuration Manager
+ 3. In the "Active solution configuration:" drop down, select the desired configuration (eg. Release), and close the Configuration Manager.
+ 4. Select Build -> Build Solution.
+Once the build completes, the output directory for your selected configuration (eg. `Release_Win32`, located next to the solution file) will contain the required libraries and dlls to build and run an OpenGL ES 2.0 application.
+
+### Building ANGLE on Linux and MacOS
+Run `ninja -C out/Debug` or `ninja -C out/Release`. Ninja is provided by `depot_tools` so make sure you set up your `PATH` correctly.
+Once the build completes, the `out/Debug` or `out/Release` directories will contain the .so or .dylib libraries and test binaries.
+
+### Building ANGLE for Android
+Presently, it is not possible to build standalone ANGLE for Android.
+But, ANGLE for Android can be built within a Chromium checkout.
+The reason for that is a dependency on Chromium for Android toolchain and that it only supports GN.
+Also, it can only be built on Linux, as this is the only platfrom that Chromium for Android supports.
+In theory, once ANGLE supports standalone GN build, it may be possible to put Chromium for Android toolchain in `third_party` or `buildtools` to build standalone ANGLE for Android.
+
+But, for now, the steps in [Checking out and building Chromium for Android](https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md) should be followed to check out Chromium for Android and set up build environment.
+Name your output directories `out/Debug` and `out/Release`, because Chromium GPU tests look for browser binaries in these folders. Replacing `out` with other names seems to be OK when working with multiple build configurations.
+It's best to use a build configuration of some Android bot on [GPU.FYI waterfall](https://build.chromium.org/p/chromium.gpu.fyi/waterfall). Look for `generate_build_files` step output of that bot. Remove `goma_dir` flag.
+For example, these are the build flags from Nexus 5X bot:
+```
+build_angle_deqp_tests = true
+dcheck_always_on = true
+ffmpeg_branding = "Chrome"
+is_component_build = false
+is_debug = false
+proprietary_codecs = true
+symbol_level = 1
+target_cpu = "arm64"          # Nexus 5X is 64 bit, remove this on 32 bit devices
+target_os = "android"
+use_goma = true               # Remove this if you don't have goma
+```
+
+These ANGLE targets are supported:
+`ninja -C out/Release translator libEGL libGLESv2 angle_unittests angle_end2end_tests angle_white_box_tests angle_deqp_gles2_tests angle_deqp_gles3_tests angle_deqp_egl_tests`
+In order to run ANGLE tests, prepend `bin/run_` to the test name, for example: `./out/Release/bin/run_angle_unittests`.
+Additional details are in [Android Test Instructions](https://chromium.googlesource.com/chromium/src/+/master/docs/android_test_instructions.md).
+
+Note: Running the tests not using the test runner is tricky, but is necessary in order to get a complete TestResults.qpa from the dEQP tests (since the runner shards the tests, only the results of the last shard will be available when using the test runner). First, use the runner to install the APK, test data and test expectations on the device. After the tests start running, the test runner can be stopped with Ctrl+C. Then, run
+```
+adb shell am start -a android.intent.action.MAIN -n org.chromium.native_test/.NativeUnitTestNativeActivity -e org.chromium.native_test.NativeTest.StdoutFile /sdcard/chromium_tests_root/out.txt
+```
+After the tests finish, get the results with
+```
+adb pull /sdcard/chromium_tests_root/third_party/deqp/src/data/TestResults.qpa .
+```
+
+In order to run GPU telemetry tests, build `chrome_public_apk` target. Then follow [GPU Testing](http://www.chromium.org/developers/testing/gpu-testing#TOC-Running-the-GPU-Tests-Locally) doc, using `--browser=android-chromium` argument. Make sure to set your `CHROMIUM_OUT_DIR` environment variable, so that your browser is found, otherwise the stock one will run.
+
+Also, follow [How to build ANGLE in Chromium for dev](https://chromium.googlesource.com/angle/angle/+/HEAD/doc/BuildingAngleForChromiumDevelopment.md) to work with Top of Tree ANGLE in Chromium.
+
+## Application Development with ANGLE
+This sections describes how to use ANGLE to build an OpenGL ES application.
+
+### Choosing a D3D Backend
+ANGLE can use either a backing renderer which uses D3D11 on systems where it is available, or a D3D9-only renderer.
+
+ANGLE provides an EGL extension called `EGL_ANGLE_platform_angle` which allows uers to select which renderer to use at EGL initialization time by calling eglGetPlatformDisplayEXT with special enums. Details of the extension can be found in it's specification in `extensions/ANGLE_platform_angle.txt` and `extensions/ANGLE_platform_angle_d3d.txt` and examples of it's use can be seen in the ANGLE samples and tests, particularly `util/EGLWindow.cpp`.
+
+By default, ANGLE will use a D3D11 renderer. To change the default:
+
+ 1. Open `src/libANGLE/renderer/d3d/DisplayD3D.cpp`
+ 2. Locate the definition of `ANGLE_DEFAULT_D3D11` near the head of the file, and set it to your preference.
+
+### To Use ANGLE in Your Application
+On Windows:
+
+ 1. Configure your build environment to have access to the `include` folder to provide access to the standard Khronos EGL and GLES2 header files.
+  * For Visual C++
+     * Right-click your project in the _Solution Explorer_, and select _Properties_.
+     * Under the _Configuration Properties_ branch, click _C/C++_.
+     * Add the relative path to the Khronos EGL and GLES2 header files to _Additional Include Directories_.
+ 2. Configure your build environment to have access to `libEGL.lib` and `libGLESv2.lib` found in the build output directory (see [Building ANGLE](DevSteup.md#Building-ANGLE)).
+   * For Visual C++
+     * Right-click your project in the _Solution Explorer_, and select _Properties_.
+     * Under the _Configuration Properties_ branch, open the _Linker_ branch and click _Input_.
+     * Add the relative paths to both the `libEGL.lib` file and `libGLESv2.lib` file to _Additional Dependencies_, separated by a semicolon.
+ 3. Copy `libEGL.dll` and `libGLESv2.dll` from the build output directory (see [Building ANGLE](DevSetup.md#Building-ANGLE)) into your application folder.
+ 4. Code your application to the Khronos [OpenGL ES 2.0](http://www.khronos.org/registry/gles/) and [EGL 1.4](http://www.khronos.org/registry/egl/) APIs.
+
+On Linux and MacOS, either:
+
+ - Link you application against `libGLESv2` and `libEGL`
+ - Use `dlopen` to load the OpenGL ES and EGL entry points at runtime.
+
+## GLSL ES to GLSL Translator
+In addition to OpenGL ES 2.0 and EGL 1.4 libraries, ANGLE also provides a GLSL ES to GLSL translator. This is useful for implementing OpenGL ES emulators on top of desktop OpenGL.
+
+### Getting the source
+The translator code is fully independent of the rest of ANGLE code and resides in `src/compiler`.  It is cross-platform and build files for operating systems other than Windows can be generated by following the `Generating project files` steps above.
+
+### Usage
+The basic usage is shown in `essl_to_glsl` sample under `samples/translator`. To translate a GLSL ES shader, following functions need to be called in the same order:
+
+ * `ShInitialize()` initializes the translator library and must be called only once from each process using the translator.
+ * `ShContructCompiler()` creates a translator object for vertex or fragment shader.
+ * `ShCompile()` translates the given shader.
+ * `ShDestruct()` destroys the given translator.
+ * `ShFinalize()` shuts down the translator library and must be called only once from each process using the translator.
diff --git a/src/third_party/angle/doc/DynamicShaderCompilation.md b/src/third_party/angle/doc/DynamicShaderCompilation.md
new file mode 100644
index 0000000..894142f
--- /dev/null
+++ b/src/third_party/angle/doc/DynamicShaderCompilation.md
@@ -0,0 +1,24 @@
+# About
+
+Because ANGLE can only generate full HLSL programs after we known the signatures
+between the vertex and pixel stages, we can not immediately call the D3D
+compiler at GL shader compile time. Moreover, we can insert additional
+optimization code right at draw-time.
+
+ESSL 1.00 shaders treat all vertex inputs as floating point. We insert a
+conversion routine to transform un-normalized integer vertex attributes in the
+shader preamble to floating point, saving CPU conversion time.
+
+At draw-time, we also optimize out any unused render target outputs. This
+improved draw call performance significantly on lower spec and integrated
+devices. Changing render target setups may trigger a shader recompile at draw
+time.
+
+# Addendum
+
+ANGLE is not the only program to do this kind of draw-time optimization. A
+common complaint from application developers is that draw calls sometimes
+perform very slowly due to dynamic shader re-compilation. A future design
+direction for ANGLE, when targeting a more modern API, is to perform the vertex
+conversion in a separate shader pass, which would then be linked with another
+compiled shader.
diff --git a/src/third_party/angle/doc/ExtensionSupport.md b/src/third_party/angle/doc/ExtensionSupport.md
new file mode 100644
index 0000000..cda2789
--- /dev/null
+++ b/src/third_party/angle/doc/ExtensionSupport.md
@@ -0,0 +1,66 @@
+# Introduction
+
+This page details the extensions that are supported by ANGLE.
+
+Specifications for GLES extensions can be found in the [Khronos OpenGL ES API
+Registry](http://www.khronos.org/registry/gles/)
+
+Specifications for EGL extensions can be found in the [Khronos EGL API Registry]
+(http://www.khronos.org/registry/egl/)
+
+Specifications for ANGLE-specific extensions can be found in the [ANGLE
+extension registry]
+(https://code.google.com/p/angleproject/source/browse/?name=master#git%2Fextensions)
+
+# Details
+
+## GLES extensions
+
+*   GL\_OES\_element\_index\_uint (fn1)
+*   GL\_OES\_get\_program\_binary
+*   GL\_OES\_packed\_depth\_stencil
+*   GL\_OES\_rgb8\_rgba8
+*   GL\_OES\_standard\_derivatives
+*   GL\_OES\_texture\_half\_float (fn1)
+*   GL\_OES\_texture\_half\_float\_linear (fn1)
+*   GL\_OES\_texture\_float (fn1)
+*   GL\_OES\_texture\_float\_linear (fn1)
+*   GL\_OES\_texture\_npot (fn1)
+*   GL\_EXT\_occlusion\_query\_boolean (fn1)
+*   GL\_EXT\_read\_format\_bgra
+*   GL\_EXT\_robustness
+    *   reset notifications and sized queries only, no robust buffer access
+*   GL\_EXT\_texture\_compression\_dxt1 (fn1)
+*   GL\_EXT\_texture\_filter\_anisotropic (fn1)
+*   GL\_EXT\_texture\_format\_BGRA8888
+*   GL\_EXT\_texture\_storage
+*   GL\_ANGLE\_depth\_texture
+    *   requires support for INTZ and NULL surfaces in D3D9 (see
+        http://aras-p.info/texts/D3D9GPUHacks.html)
+*   GL\_ANGLE\_framebuffer\_blit
+*   GL\_ANGLE\_framebuffer\_multisample (fn1)
+*   GL\_ANGLE\_instanced\_arrays
+    *   requires SM3 support
+*   GL\_ANGLE\_pack\_reverse\_row\_order
+*   GL\_ANGLE\_texture\_compression\_dxt3 (fn1)
+*   GL\_ANGLE\_texture\_compression\_dxt5 (fn1)
+*   GL\_ANGLE\_texture\_usage
+*   GL\_ANGLE\_translated\_shader\_source
+*   GL\_NV\_fence (fn1)
+
+## EGL Extensions
+
+*   EGL\_EXT\_create\_context\_robustness
+    *   only reset notifications supported
+*   EGL\_ANGLE\_d3d\_share\_handle\_client\_buffer (fn2)
+*   EGL\_ANGLE\_query\_surface\_pointer
+*   EGL\_ANGLE\_software\_display (fn3)
+*   EGL\_ANGLE\_surface\_d3d\_texture\_2d\_share\_handle (fn2)
+*   EGL\_NV\_post\_sub\_buffer
+
+### Notes
+
+*   fn1: extensions are only exposed if underlying D3D9 device has support for
+    the required features
+*   fn2: extensions are only exposed when running on D3D9Ex (ie Win Vista/7)
+*   fn3: extension is only exposed when swiftshader is present
diff --git a/src/third_party/angle/doc/MANGLE.md b/src/third_party/angle/doc/MANGLE.md
new file mode 100644
index 0000000..2bca69b
--- /dev/null
+++ b/src/third_party/angle/doc/MANGLE.md
@@ -0,0 +1,9 @@
+# M(ulti-platform)ANGLE effort
+
+Starting in early 2014, the ANGLE team has begun work on refactoring the code
+with the goal of supporting translation to desktop OpenGL. The new purpose of
+ANGLE will be provide a consistent OpenGL ES and EGL context on as many
+platforms as possible.
+
+The design doc is available [here]
+(https://docs.google.com/document/d/17mxRfzXuEWyvGM3t2KqVY4svvfRj_GzysOEpmnDpqeo/edit?usp=sharing).
diff --git a/src/third_party/angle/doc/ResourceLimits.md b/src/third_party/angle/doc/ResourceLimits.md
new file mode 100644
index 0000000..bc44a49
--- /dev/null
+++ b/src/third_party/angle/doc/ResourceLimits.md
@@ -0,0 +1,34 @@
+# Resource Limits
+
+OpenGL ES 2.0 API is quite powerful but there are still some features that are
+optional or allow for wide variability between implementations.
+
+Applications that need more than the minimum values for these limits should
+query the capabilities of the GL device and scale their usage based on the
+device’s feature set. Failing to do so and assuming sufficient limits typically
+results in reduced portability.
+
+The various implementation dependent limits can be found in Tables 6.18 – 6.20
+of the [OpenGL ES 2.0.25 specification]
+(http://www.khronos.org/registry/gles/specs/2.0/es_full_spec_2.0.25.pdf).
+
+# Capabilities
+
+Capability                                 | ES 2.0 Minimum | ANGLE            | SM2   | SM3      | SM4+
+:----------------------------------------- | :------------- | :--------------- | :---- | :------- | :-------
+GL\_MAX\_VERTEX\_ATTRIBS                   | 8              | 16               |       |          |
+GL\_MAX\_VERTEX\_UNIFORM\_VECTORS          | 128            | 254              |       |          |
+GL\_MAX\_VERTEX\_TEXTURE\_IMAGE\_UNITS     | 0              | (fn1)            | 0     | 0        | 4
+GL\_MAX\_VARYING\_VECTORS                  | 8              | (fn1)            | 8     | 10       | 10
+GL\_MAX\_FRAGMENT\_UNIFORM\_VECTORS        | 16             | (fn1)            | 29    | 221      | 221
+GL\_MAX\_TEXTURE\_IMAGE\_UNITS             | 8              | 16               |       |          |
+GL\_MAX\_TEXTURE\_SIZE                     | 64             | 2048-16384 (fn1) |       |          |
+GL\_MAX\_CUBE\_MAP\_SIZE                   | 16             | 2048-16384 (fn1) |       |          |
+GL\_MAX\_RENDERBUFFER\_SIZE                | 1              | 2048-16384 (fn1) |       |          |
+GL\_ALIASED\_POINT\_SIZE\_RANGE (min, max) | (1, 1)         | (fn2)            | (1,1) | (1, fn2) | (1, fn2)
+GL\_ALIASED\_LINE\_WIDTH\_RANGE (min, max) | (1, 1)         | (1, 1)           |       |          |
+
+## Notes
+
+*   fn1: limits vary based on the underlying hardware capabilities
+*   fn2: on SM3 or better hardware the max point size is D3DCAPS9.MaxPointSize
diff --git a/src/third_party/angle/doc/SourceAccess.md b/src/third_party/angle/doc/SourceAccess.md
new file mode 100644
index 0000000..89a5b18
--- /dev/null
+++ b/src/third_party/angle/doc/SourceAccess.md
@@ -0,0 +1,15 @@
+# ANGLE Source Code
+
+# Browsing
+
+ANGLE's source no longer resides at code.google.com! To browse the ANGLE source,
+please visit https://chromium.googlesource.com/angle/angle
+
+# Checkout
+
+You may clone the ANGLE repository with:
+
+> `git clone https://chromium.googlesource.com/angle/angle`
+
+For full instructions on setting up your system with the necessary prerequisites
+for development with ANGLE, please see the DevSetup page.
diff --git a/src/third_party/angle/doc/Update20120704.md b/src/third_party/angle/doc/Update20120704.md
new file mode 100644
index 0000000..c3d8033
--- /dev/null
+++ b/src/third_party/angle/doc/Update20120704.md
@@ -0,0 +1,119 @@
+# ANGLE Development Update - July 4, 2012
+
+We haven't posted an update on the development status of ANGLE in quite some
+time and we'd like to provide an update on some of the new features and
+improvements that we've been working on.
+
+## Conformance
+
+As announced in the [Chromium Blog]
+(http://blog.chromium.org/2011/11/opengl-es-20-certification-for-angle.html),
+ANGLE v1.0 has passed the Khronos OpenGL ES 2.0 certification process and is now
+a [conformant](http://www.khronos.org/conformance/adopters/conformant-products/)
+OpenGL ES 2.0 implementation.
+
+## Extensions
+
+We have recently completed the implementation of depth texture support
+([ANGLE\_depth\_texture]
+(https://code.google.com/p/angleproject/source/browse/extensions/ANGLE_depth_texture.txt?name=master))
+and earlier in the year we added support for instancing via attribute array
+divisors ([ANGLE\_instanced\_arrays]
+(https://code.google.com/p/angleproject/source/browse/extensions/ANGLE_instanced_arrays.txt?name=master)).
+See ExtensionSupport for a complete list of extensions that are supported by
+ANGLE.
+
+## Shader Compiler
+
+We have also made a number of improvements in the shader compiler.
+
+* We addressed a number of defects related to scoping differences between HLSL and
+GLSL and improved the scoping support in ANGLE's compiler front-end. We also
+worked with The Khronos Group to get an ESSL spec bug fixed and several items
+clarified.
+* We addressed a number of correctness issues in the GLSL to HLSL
+translation process. We fixed some bugs related to constant propagation and
+comma conditional assignments. More importantly, we fully implemented support
+for short-circuiting boolean logic operations. In GLSL, Boolean expressions do
+short-circuit evaluation as in C, but HLSL evaluates them entirely. This only
+has an observable effect if a short-circuited operation has side effects, such
+as a function call that modifies global variables.
+* We implemented detection
+for discontinuous gradient or derivative computations inside loops and replace
+them with explicitly defined continuous behaviour. HLSL and GLSL differ in their
+specified behaviour for operations which compute gradients or derivatives.
+Gradients are computed by texture sampling functions which don't specify a
+specific mipmap LOD level, and by the OES\_standard\_derivatives built-in
+functions. To determine the gradient, the corresponding values in neighbouring
+pixels are differentiated. If neighbouring pixels execute different paths
+through the shader this can cause a discontinuity in the gradient. GLSL
+specifies that in these cases the gradient is undefined. HLSL tries to avoid the
+discontinuity in the compiler by unrolling loops so that every pixel executes
+all iterations. This can make the D3D HLSL compiler spend a long time generating
+code permutations, and possibly even fail compilation due to running out of
+instruction slots or registers. Because the GLSL specification allows undefined
+behaviour, we can define such texture sampling functions to use mipmap LOD level
+0, and have the derivatives functions return 0.0. To do this we examine the GLSL
+code's abstract syntax tree and detect whether the shader contains any loops
+with discontinuities and gradient operations. Within such loops, we generate
+HLSL code that uses explicitly defined texture LODs and derivative information.
+One additional consideration is that within these loops there can be calls to
+user-defined functions which may contain gradient operations. In this case, we
+generate variants of user-defined functions where these operations are
+explicitly defined. We use these new functions instead of the original ones in
+loops with discontinuities.
+
+These fixes result in ANGLE being able successfully compile a number of the more
+complex shaders. Unfortunately there are still some complex shaders which we
+have not yet been able to obtain solutions for. Ultimately Direct3D 9 SM3
+shaders are more restricted than what can be expressed in GLSL.  Most of the
+problematic shaders we've encountered will also not compile successfully on
+current ES 2.0 implementations.  We would only be able to achieve parity with
+Desktop GL implementations by using Direct3D 10 or above.
+
+## Texture Origin Changes
+
+We have also made a major change to ANGLE in the way the origin difference
+between D3D and OpenGL is handled. This difference is normally observable when
+using render-to-texture techniques, and if not accounted for, it would appear
+that images rendered to textures are upside down. In recent versions of ANGLE
+(r536 (on Google Code)-r1161 (on Google Code)), we have been storing surfaces
+following the D3D Y convention where (0, 0) is the top-left, rather than GL's
+bottom-left convention. This was done by vertically flipping textures on load
+and then adjusting the texture coordinates in the shaders to compensate. This
+approach worked well, but it did leave the orientation of pbuffers inverted when
+compared to native GL implementations. As of ANGLE r1162 (on Google Code), we
+have changed this back to the original way it was implemented - textures are
+loaded and stored in the GL orientation, and the final rendered scene is flipped
+when it is displayed to a window by eglSwapBuffers. This should be essentially
+transparent to applications except that orientation of pbuffers will change.  In
+addition to fixing the pbuffer orientation, this change:
+
+* eliminates
+dependent-texture look-ups in the shaders, caused by flipping the texture
+y-coordinates
+* rounding of texture coordinates (while previously within spec)
+will be more consistent with other implementations, and
+* allows potential
+faster paths for loading texture data to be implemented. The only potential
+downside to this approach is that window-based rendering may be a bit slower for
+simple scenes. The good news is that this path is not used by browser
+implementations on most versions of Windows.
+
+## Preprocessor
+
+Finally, Alok P. from Google has been working on implementing a new shader
+preprocessor for the last number of months and this effort is nearly complete.
+This new preprocessor should be more robust and much more maintainable. It also
+includes many (~5000) unit tests and passes all WebGL conformance tests. If you
+wish to try this out before it is enabled by default, define
+ANGLE\_USE\_NEW\_PREPROCESSOR=1 in your project settings for the
+translator\_common project.
+
+## Contributions
+
+As always we welcome contributions either in the bug reports (preferably with an
+isolated test-case) or in the form of code contributions. We have added a
+[ContributingCode](ContributingCode.md) wiki page documenting the preferred
+process for contributing code. We do need to ask that you sign a Contributor
+License Agreement before we can integrate your patches.
diff --git a/src/third_party/angle/doc/Update20130618.md b/src/third_party/angle/doc/Update20130618.md
new file mode 100644
index 0000000..81beafd
--- /dev/null
+++ b/src/third_party/angle/doc/Update20130618.md
@@ -0,0 +1,27 @@
+# ANGLE Development Update - June 18, 2013
+
+This week brings some significant changes to ANGLE, which we think are worth
+covering in a development update.
+
+## Migration from svn to git
+
+We've changed our backing version control system from svn to git. Projects and
+contributors pulling from the svn repository will continue to be able to do so,
+but please note that this repository is now read-only, and no further updates
+will be made there. To continue tracking new development and issue fixes, you'll
+need to watch the git repository. Instructions on checking out code from the git
+repository can be found on the [Source Checkout]
+(https://code.google.com/p/angleproject/source/checkout) page.
+
+## DirectX 11 Support
+
+ANGLE now provides both a DirectX 9 and a DirectX 11-backed renderer in the same
+code base. By default, support for the DirectX 11 renderer is disabled, but it
+can be enabled by toggling the value of ANGLE\_ENABLE\_D3D11 as described on the
+DevSetup page. On systems without DirectX 11 support, ANGLE will fall back to
+DirectX 9.
+
+This work originally appeared in our dx11proto branch, which, with the move to
+the new repository, has been promoted to master. Code previously located in the
+trunk of the svn repository will now be located in the git legacy branch, and
+active development will now move to the newly promoted master.
diff --git a/src/third_party/angle/doc/Update20131120.md b/src/third_party/angle/doc/Update20131120.md
new file mode 100644
index 0000000..6a7ba98
--- /dev/null
+++ b/src/third_party/angle/doc/Update20131120.md
@@ -0,0 +1,16 @@
+# ANGLE Development Update - November 20, 2013
+
+ANGLE has undergone a few further migrations in the past week, which we thought
+it important to mention in a front-page update.
+
+The review process for contributed code has moved from [Rietveld]
+(https://codereview.appspot.com/) to [Gerrit]
+(https://chromium-review.googlesource.com). This migration allows us to more
+easily support a Git-centric workflow, and eases the process of accepting
+changes submitted by contributors without commit access to our repositories.
+
+As a result of this change, our repository has also moved from its prior
+location at code.google.com to https://chromium.googlesource.com/angle/angle.
+The repository may still be pulled from its old location, but no further changes
+will be committed there. Updates will be made only to the repository's new
+location.
diff --git a/src/third_party/angle/doc/Update20140325.md b/src/third_party/angle/doc/Update20140325.md
new file mode 100644
index 0000000..763b539
--- /dev/null
+++ b/src/third_party/angle/doc/Update20140325.md
@@ -0,0 +1,30 @@
+# ES 3.0 Development Branch merging
+
+ANGLE will soon be merging its ES 3.0 development branch to master, to make
+available (and more visible) the changes we've been making over the past several
+months in support of ES 3.0, and to remove divergence between the master and
+development branches.
+
+The previous master branch will still be available as the es2only-legacy branch,
+and SHAs will not change, so dependencies on individual commits of ANGLE will
+continue to work as expected. However, new contributions against es2only-legacy
+will generally not be considered, and future work should be done on master.
+
+This merge doesn't signify completion of ES 3.0, as we have some features still
+left to implement there, but interested developers can explore the work in
+progress. A significant portion of 3.0 features have been implemented,
+including:
+
+* 2D array textures, 3D textures
+* Expanded texture format support
+* Uniform Buffer Objects
+* Vertex Array Objects
+* Sampler objects, expanded sampler types
+* Transform Feedback
+* Texture Swizzle
+* GLSL integer support
+
+ES 3.0 features should not yet be considered stable, even where implemented, and
+some features are present only via naive implementation so far. There is still
+quite a bit of work ahead of us before ES 3.0 support is complete, but this
+merge should provide insight to those interested in what we've been working on!
diff --git a/src/third_party/angle/doc/Update20150105.md b/src/third_party/angle/doc/Update20150105.md
new file mode 100644
index 0000000..f5615c5
--- /dev/null
+++ b/src/third_party/angle/doc/Update20150105.md
@@ -0,0 +1,46 @@
+# Multiplatform ANGLE Refactor Complete
+
+ANGLE's multiplatform refactoring effort ([described here]
+(https://code.google.com/p/angleproject/wiki/MANGLE)) is now complete, paving
+the way for additional rendering backends, allowing ANGLE to enable OpenGL ES
+not just over Direct3D 9 and 11, but also desktop OpenGL.
+
+The refactoring we've done encapsulates D3D-related assumptions and API calls at
+the renderer level, so that no D3D calls are made in the renderer-agnostic
+portions of the codebase, and D3D-specific feature implementations won't be
+included on non-D3D platforms. For example, the creation and maintenance of
+CPU-side copies of texture data, which are required to enable GL-style
+per-mip-level texture creation over D3D's entire-mipchain texture creation API,
+is contained entirely within the D3D renderers, allowing a GL implementation to
+avoid this complication.
+
+Work will now begin within ANGLE to add a desktop OpenGL renderer, and EGL
+implementations compatible with OS X and Linux.
+
+# ES 3.0 Development Status
+
+Our ES 3.0 development branch was merged into mainline ANGLE in April 2014, but
+ES 3.0 support is not yet complete. The majority of API functionality has been
+implemented; features still pending include:
+
+* ETC2/EAC support
+* primitive restart index
+* drawRangeElements
+* full GetProgramBinary support in core
+
+Additional work remains in the compiler, including:
+
+* Array .length()
+* inf/nan detection
+* math utility functions, rounding
+* VertexID/InstanceID support
+* floating point packing functions
+* operators new in ES 3.0
+* name redeclaration
+* relaxed array indexing
+* switch statement support
+* loop & iteration improvements
+
+ES 3.0 features should not be considered stable, even where implemented, and
+some features are present only via naive implementation so far, but we welcome
+bugs filed against this functionality, and thank all our contributors!
diff --git a/src/third_party/angle/doc/VTF.md b/src/third_party/angle/doc/VTF.md
new file mode 100644
index 0000000..ebf3c56
--- /dev/null
+++ b/src/third_party/angle/doc/VTF.md
@@ -0,0 +1,76 @@
+# Vertex Texture Fetch
+
+This page details the steps necessary to implement vertex texture fetch in ANGLE
+and documents some of the pitfalls that may be encountered along the way.
+
+# Details
+
+Tasks to implement vertex texture support.
+
+1.  add/enable vertex shader texture look up functions in compiler & HLSL
+    translator.
+    *   add texture2DLod, texture2DProjLod (2 variants), textureCubeLod (these
+        are **only** valid in vertex shaders)
+    *   ensure other (non-bias/non-LOD) texture functions work in vertex shaders
+    *   non-mipmapped textures use the only level available
+    *   mipmapped textures use only the base level (ie level 0).
+2.  update implementation-dependent constants in Context.h
+    *   MAX\_VERTEX\_TEXTURE\_IMAGE\_UNITS = 4
+    *   MAX\_COMBINED\_TEXTURE\_IMAGE\_UNITS =
+        MAX\_VERTEX\_TEXTURE\_IMAGE\_UNITS + MAX\_TEXTURE\_IMAGE\_UNITS (ie 20).
+    *   these limits have to change based on the d3d device characteristics. For
+        example we likely don't want to advertise vertex image units on SM2.0
+        cards (unless we end up using software vertex processing).
+    *   detection of hardware support for various formats, types, etc.
+    *   As a first pass, use the "hasVertexTextures" check that Aras suggested
+        to only enable VTF on DX10 NVIDIA and AMD parts, and SM3 Intel parts.
+    *   If this proves insufficient, there are other things we can do, but it
+        involves using software vertex processing for unsupported formats and
+        system memory copies of textures -- all stuff which is rather annoying
+        and likely to hurt performance (see point 4. below).
+3.  add support and handling for vertex textures/samplers in the API.
+    *   any textures used in a vertex shader need to get assigned to the special
+        samplers in d3d9
+    *   there are only 4 of them (D3DVERTEXTEXTURESAMPLER0..
+        D3DVERTEXTEXTURESAMPLER3)
+    *   if a texture is used in both vertex & fragment it counts twice against
+        the "MAX\_COMBINED" limit (validated in Program::validateSamplers)
+    *   there are a number of places in our code where we have arrays of size,
+        or iterate over, MAX\_TEXTURE\_IMAGE\_UNITS. These will need to be
+        changed to operate on MAX\_COMBINED\_TEXTURE\_IMAGE\_UNITS instead. A
+        (possibly incomplete & outdated) list of areas that need to be updated
+        is as follows:
+    *   Program.h - increase size of mSamplers
+    *   Context.h - increase size of samplerTexture
+    *   glActiveTexture needs accept values in the range
+        0..MAX\_COMBINED\_TEXTURE\_IMAGE\_UNITS-1
+    *   Context::~Context
+    *   GetIntegerv (2D\_BINDING, CUBE\_BINDING)
+    *   Context::applyTextures
+    *   Context::detachTexture
+    *   Program::getSamplerMapping
+    *   Program::dirtyAllSamplers
+    *   Program::applyUniform1iv
+    *   Program::unlink
+    *   Program::validateSamplers
+4.  handling the nasty corner cases: texture formats, filtering and cube
+    textures.
+    *   OpenGL doesn't provide any restrictions on what formats and/or types of
+        textures can used for vertex textures, or if filtering can be enabled,
+        whereas D3D9 does.
+    *   Reference Rasterizer / Software Vertex Processing: all formats & types
+        supported (including filtering)
+    *   ATI R500 (on Google Code) cards do not support VTF (even though they are
+        SM 3.0)
+    *   ATI R600 (on Google Code) (and later) and in theory the Intel 965+,
+        claim to support all texture formats/types we care about and some with
+        filtering
+    *   NVIDIA cards fall into two camps:
+    *   dx9 SM3 (6&7 series): only R32F & A32B32G32R32F supported for 2D and no
+        filtering, CUBE or VOL texture support
+    *   dx10 (8+ series): only float texture formats for 2D, CUBE & VOLUME. no
+        filtering (according to caps)
+        *   further info from Aras P. suggests that all formats are supported on
+            DX10 hardware, but are just not advertised.
+    *   unsure what they do on these cards under OpenGL. Need to do more
+        testing, but suspect software fallback.
diff --git a/src/third_party/angle/doc/dEQP.md b/src/third_party/angle/doc/dEQP.md
new file mode 100644
index 0000000..8a293b2
--- /dev/null
+++ b/src/third_party/angle/doc/dEQP.md
@@ -0,0 +1,62 @@
+# ANGLE + dEQP
+
+drawElements (dEQP) is a very robust and comprehensive set of open-source
+tests for GLES2, GLES3+ and EGL. They provide a huge net of coverage for
+almost every GL API feature. ANGLE by default builds dEQP testing targets for
+testing against GLES 2, GLES 3, EGL, and GLES 3.1 (on supported platforms).
+
+## How to build dEQP
+
+You should have dEQP as a target if you followed the [DevSetup](DevSetup.md)
+instructions. Current targets:
+
+  * `angle_deqp_gles2_tests` for GLES 2.0 tests
+  * `angle_deqp_gles3_tests` for GLES 3.0 tests
+  * `angle_deqp_egl_tests` for EGL 1.x tests
+  * `angle_deqp_gles31_tests` for GLES 3.1 tests (currently very experimental)
+
+## How to use dEQP
+
+The `--deqp-case` flag allows you to run individual tests, with simple
+wildcard support. For example: `--deqp-case=dEQP-
+GLES2.functional.shaders.linkage.*`.
+
+The tests lists are sourced from the Android CTS masters in
+`third_party/deqp/src/android/cts/master`. See `gles2-master.txt`,
+`gles3-master.txt`, `gles31-master.txt` and `egl-master.txt`.
+
+If you're running a full test suite, it might take very long time. Running in
+Debug is only useful to isolate and fix particular failures, Release will give
+a better sense of total passing rate.
+
+### Choosing a Renderer on Windows
+
+By default Windows ANGLE tests with D3D11. To specify the exact platform for
+ANGLE + dEQP, use the arguments:
+
+  * `--deqp-egl-display-type=angle-d3d11` for D3D11 (highest available feature level)
+  * `--deqp-egl-display-type=angle-d3d9` for D3D9
+  * `--deqp-egl-display-type=angle-d3d11-fl93` for D3D11 Feature level 9_3
+  * `--deqp-egl-display-type=angle-gl` for OpenGL Desktop (OSX, Linux and Windows)
+  * `--deqp-egl-display-type=angle-gles` for OpenGL ES (Android/ChromeOS, some Windows platforms)
+
+### Check your results
+
+If run from Visual Studio 2015, dEQP generates a test log to
+`src/tests/TestResults.qpa`. To view the test log information, you'll need to
+use the open-source GUI
+[Cherry](https://android.googlesource.com/platform/external/cherry). ANGLE
+checks out a copy of Cherry to `angle/third_party/cherry` when you sync with
+gclient. Note, if you are using ninja or another build system, the qpa file
+will be located in your working directory.
+
+See the [official Cherry README](https://android.googlesource.com/platform/ext
+ernal/cherry/+/master/README) for instructions on how to run Cherry on Linux
+or Windows.
+
+### GoogleTest, ANGLE and dEQP
+
+ANGLE also supports the same set of targets built with GoogleTest, for running
+on the bots. We don't currently recommend using these for local debugging, but
+we do maintain lists of test expectations in `src/tests/deqp_support`. When
+you fix tests, please remove the suppression(s) from the relevant files!
diff --git a/src/third_party/angle/extensions/ANGLE_client_arrays.txt b/src/third_party/angle/extensions/ANGLE_client_arrays.txt
new file mode 100644
index 0000000..1922b34
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_client_arrays.txt
@@ -0,0 +1,100 @@
+Name
+
+    ANGLE_client_arrays
+
+Name Strings
+
+    GL_ANGLE_client_arrays
+
+Contributors
+
+    Geoff Lang
+
+Contact
+
+    Geoff Lang (geofflang 'at' google.com)
+
+Notice
+
+    Copyright (c) 2016 The Khronos Group Inc. Copyright terms at
+        http://www.khronos.org/registry/speccopyright.html
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, February 13, 2016
+
+Number
+
+    OpenGL ES Extension #??
+
+Dependencies
+
+    Requires OpenGL ES 2.0
+
+    Written against the OpenGL ES 2.0 specification.
+
+Overview
+
+    This extension allows the OpenGL context to indicate if it supports drawing
+    with client-side vertex or index data.  Client-side can be very inefficient
+    and unsafe, it is convenient for some users to completely disable its usage.
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted by the <cap> parameter to IsEnabled and the <pname> parameter to
+    GetBooleanv, GetIntegerv, GetFloatv, and GetInteger64v:
+
+    CLIENT_ARRAYS_ANGLE                 0x93AA
+
+Additions to the OpenGL ES Specification
+
+    Add after paragraph 3 of section 2.8 "Vertex Arrays":
+
+    If VertexAttribPointer is called while zero is bound to the ARRAY_BUFFER
+    buffer object binding point, the pointer argument is not NULL, and
+    CLIENT_ARRAYS_ANGLE is TRUE, an INVALID_OPERATION error is generated.
+
+    Add to the end of section 2.9.1 "Vertex Arrays in Buffer Objects":
+
+    Rendering commands that draw more than 0 primitives using enabled vertex
+    attributes with no buffer bound when CLIENT_ARRAYS_ANGLE is TRUE generate
+    an INVALID_OPERATION error.
+
+    Add to the end of section 2.9.2 "Array Indices in Buffer Objects":
+
+    Rendering commands that draw more than 0 primitives using index data when
+    no buffer is bound to the ELEMENT_ARRAY_BUFFER binding point when
+    CLIENT_ARRAYS_ANGLE is TRUE generate an INVALID_OPERATION error.
+
+New State
+
+    Modify Table 6.22, Miscellaneous
+
+    Add:
+
+                                          Initial
+    Get Value            Type Get Command Value   Description
+    -------------------- ---- ----------- ------- ---------------------
+    CLIENT_ARRAYS_ANGLE  B    IsEnabled   TRUE    Client arrays enabled
+
+Conformance Tests
+
+    TBD
+
+Issues
+
+    None
+
+Revision History
+
+    Rev.    Date         Author     Changes
+    ----  -------------  ---------  ----------------------------------------
+      1   Feb 13, 2016   geofflang  Initial version
diff --git a/src/third_party/angle/extensions/ANGLE_lossy_etc_decode.txt b/src/third_party/angle/extensions/ANGLE_lossy_etc_decode.txt
new file mode 100644
index 0000000..1488192
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_lossy_etc_decode.txt
@@ -0,0 +1,159 @@
+Name
+
+    ANGLE_lossy_etc_decode
+
+Name Strings
+
+    GL_ANGLE_lossy_etc_decode
+
+Contributors
+
+    Minmin Gong  (mgong 'at' microsoft.com)
+
+Contacts
+
+    Minmin Gong  (mgong 'at' microsoft.com)
+
+Status
+
+    Draft
+
+Version
+
+    Last Modified Date: Nov 25, 2015
+    Author Revision: 1
+
+Number
+
+    TBD
+
+Dependencies
+
+    Requires OpenGL ES 3.0 for ETC2 and EAC formats, or OpenGL ES 2.0 and
+    OES_compressed_ETC1_RGB8_texture for ETC1 format.
+    The extension is written against the OpenGL ES 2.0 specification.
+
+Overview
+
+    Both the OpenGL ES 3.0 specification and OES_compressed_ETC1_RGB8_texture
+    specify that Ericsson Texture Compression (ETC) decoding must not be lossy.
+    The goal of this extension is to allow a lossy decode of
+    compressed textures in the ETC formats in OpenGL ES, for lower memory
+    and bandwidth consumption.
+
+    This extension uses the same ETC compression format as OpenGL ES 3.0
+    and OES_compressed_ETC1_RGB8_texture, with the restriction that the texture
+    dimensions must be a multiple of four (except for mip levels where the
+    dimensions are either 2 or 1). And the requirement that ETC decoding must
+    not be lossy is relaxed.
+
+    See OES_compressed_ETC1_RGB8_texture for a description of the ETC1 format.
+    Also see OpenGL ES 3.0 specification appendix C.2 (ETC Compressed Texture
+    ImageFormats) for a description of ETC2 and EAC formats.
+
+IP Status
+
+    See Ericsson's "IP Statement"
+
+New Procedures and Functions
+
+    None.
+
+New Types
+
+    None.
+
+New Tokens
+
+    Accepted by the <internalformat> parameter of CompressedTexImage2D
+    and the <format> parameter of CompressedTexSubImage2D:
+
+    ETC1_RGB8_LOSSY_DECODE_ANGLE                                  0x9690
+    COMPRESSED_R11_LOSSY_DECODE_EAC_ANGLE                         0x9691
+    COMPRESSED_SIGNED_R11_LOSSY_DECODE_EAC_ANGLE                  0x9692
+    COMPRESSED_RG11_LOSSY_DECODE_EAC_ANGLE                        0x9693
+    COMPRESSED_SIGNED_RG11_LOSSY_DECODE_EAC_ANGLE                 0x9694
+    COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE                       0x9695
+    COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE                      0x9696
+    COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE   0x9697
+    COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE  0x9698
+    COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE                  0x9699
+    COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE           0x969A
+
+Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization)
+
+    Add the following to Section 3.7.3 (Compressed Texture Images)
+    (at the end of the description of the CompressedTexImage2D command):
+
+    Compressed Internal Format                                    Base Internal Format
+    ==========================                                    ====================
+    ETC1_RGB8_LOSSY_DECODE_ANGLE                                  RGB
+    COMPRESSED_R11_LOSSY_DECODE_EAC_ANGLE                         R
+    COMPRESSED_SIGNED_R11_LOSSY_DECODE_EAC_ANGLE                  R
+    COMPRESSED_RG11_LOSSY_DECODE_EAC_ANGLE                        RG
+    COMPRESSED_SIGNED_RG11_LOSSY_DECODE_EAC_ANGLE                 RG
+    COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE                       RGB
+    COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE                      RGB
+    COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE   RGBA
+    COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE  RGBA
+    COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE                  RGBA
+    COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE           RGBA
+
+    Table 3.x: Specific Compressed Internal Formats
+
+    If <internalformat> is one of the ETC lossy decode formats listed in
+    Table 3.x, the compressed texture is stored in an unspecified compressed
+    texture format, that may introduce losses of precision in the texture data.
+    The GL and the ETC texture compression algorithm support only 2D images
+    without borders.
+
+    CompressedTexImage2D will produce the INVALID_OPERATION error when
+    <internalformat> is one of the lossy decode ETC-format values from
+    Table 3.x under the following conditions:
+
+      * <border> is non-zero.
+      * <width> is not one, two, nor a multiple of four.
+      * <height> is not one, two, nor a multiple of four.
+
+    Add the following to Section 3.7.3 (Compressed Texture Images)
+    (at the end of the description of the CompressedTexSubImage2D command):
+
+    If the internal format of the texture image being modified is an ETC-format
+    listed in Table 3.x, the compressed texture is stored in an unspecified
+    compressed texture format. The xoffset and yoffset must also be aligned to
+    4x4 texel block boundaries, since ETC encoding makes it difficult to modify
+    non-aligned regions. CompressedTexSubImage2D will result in an
+    INVALID_OPERATION error only if one of the following conditions occurs:
+
+      * <width> is not a multiple of four nor equal to TEXTURE_WIDTH.
+      * <height> is not a multiple of four nor equal to TEXTURE_HEIGHT.
+      * <xoffset> or <yoffset> is not a multiple of four.
+      * <format> does not match the internal format of the texture image
+        being modified.
+
+Errors
+
+    INVALID_OPERATION is generated by CompressedTexImage2D if
+    lossy decode ETC-format is used and <internalformat> is one of the
+    compressed internal formats from Table 3.x and any of the following apply:
+      - <border> is not equal to zero.
+      - <width> is not one, two, nor a multiple of four.
+      - <height> is not one, two, nor a multiple of four.
+
+    INVALID_OPERATION is generated by CompressedTexSubImage2D if
+    lossy decode ETC-format is used and <format> is one of the compressed
+    interal formats from Table 3.x and any of the following apply:
+      - <width> is not a multiple of four nor equal to TEXTURE_WIDTH;
+      - <height> is not a multiple of four nor equal to TEXTURE_HEIGHT;
+      - <xoffset> or <yoffset> is not a multiple of four;
+      - <format> does not match the internal format of the texture image
+      being modified.
+
+New State
+
+    None.
+
+Revision History
+
+    Revision 1, 2015/11/25 - mgong
+      - Initial revision
diff --git a/src/third_party/angle/extensions/ANGLE_platform_angle.txt b/src/third_party/angle/extensions/ANGLE_platform_angle.txt
new file mode 100644
index 0000000..b39815b
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_platform_angle.txt
@@ -0,0 +1,127 @@
+Name
+
+    ANGLE_platform_angle
+
+Name Strings
+
+    EGL_ANGLE_platform_angle
+
+Contributors
+
+    Scott Graham, Google
+    Shannon Woods, Google
+    Geoff Lang, Google
+
+Contacts
+
+    Scott Graham, Google (scottmg 'at' google 'dot' com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 3, 2014-10-20
+
+Number
+
+    EGL Extension XXX
+
+Extension Type
+
+    EGL client extension
+
+Dependencies
+
+    Requires EGL_EXT_client_extensions to query its existence without
+    a display.
+
+    Requires EGL_EXT_platform_base.
+
+    This extension is written against the wording of version 9 of the
+    EGL_EXT_platform_base specification.
+
+    ANGLE_platform_angle_d3d affects the definition of this extension.
+    ANGLE_platform_angle_opengl affects the definition of this extension.
+
+Overview
+
+    This extension defines how to create EGL resources from native resources
+    using the functions defined by EGL_EXT_platform_base.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as the <platform> argument of eglGetPlatformDisplayEXT:
+
+        EGL_PLATFORM_ANGLE_ANGLE                           0x3202
+
+    Accepted as an attribute name in the <attrib_list> argument of
+    eglGetPlatformDisplayEXT:
+
+        EGL_PLATFORM_ANGLE_TYPE_ANGLE                      0x3203
+        EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE         0x3204
+        EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE         0x3205
+
+    Accepted as values for the EGL_PLATFORM_ANGLE_TYPE_ANGLE attribute:
+
+        EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE              0x3206
+
+Additions to the EGL Specification
+
+    None.
+
+New Behavior
+
+    To determine if the EGL implementation supports this extension, clients
+    should query the EGL_EXTENSIONS string of EGL_NO_DISPLAY.
+
+    To obtain an EGLDisplay backed by a ANGLE display, call
+    eglGetPlatformDisplayEXT with <platform> set to EGL_PLATFORM_ANGLE_ANGLE.
+
+    The <native_display> parameter is of type EGLNativeDisplayType. If
+    <native_display> is EGL_DEFAULT_DISPLAY a default display is returned.
+    Multiple calls with the same <native_display> will return the same
+    EGLDisplay handle. If <platform> is set to EGL_PLATFORM_ANGLE_ANGLE and
+    the returned display is in an uninitialized state, its attributes are
+    overwritten by those provided in the <attrib_list>, if any.
+
+    If no <attrib_list> is specified, the value of
+    EGL_PLATFORM_ANGLE_TYPE_ANGLE is implicitly set to
+    EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE.
+
+    If no <attrib_list> is specified, the values of
+    EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE and
+    EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE are implicitly set to
+    EGL_DONT_CARE.
+
+    If EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE is set to EGL_DONT_CARE and
+    EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE is not set to EGL_DONT_CARE,
+    an EGL_BAD_ATTRIBUTE error is generated and EGL_NO_DISPLAY is returned.
+
+    If no display matching the requested <native_display> or of the type
+    requested by the value of EGL_PLATFORM_ANGLE_TYPE_ANGLE is available,
+    EGL_NO_DISPLAY is returned. No error condition is raised in this case.
+
+Issues
+
+    None
+
+Revision History
+
+    Version 1, 2014-02-04 (Scott Graham)
+      - Initial draft
+    Version 2, 2014-06-05 (Geoff Lang)
+      - Rename extension from ANGLE_platform_angle_d3d to ANGLE_platform_angle.
+      - Add sub-extensions for specific platforms.
+    Version 3, 2014-10-20 (Geoff Lang)
+      - Add attributes to request specific feature level and context versions.
+      - Moved descriptions of platforms to child extension specs.
diff --git a/src/third_party/angle/extensions/ANGLE_platform_angle_d3d.txt b/src/third_party/angle/extensions/ANGLE_platform_angle_d3d.txt
new file mode 100644
index 0000000..0c35005
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_platform_angle_d3d.txt
@@ -0,0 +1,140 @@
+Name
+
+    ANGLE_platform_angle_d3d
+
+Name Strings
+
+    EGL_ANGLE_platform_angle_d3d
+
+Contributors
+
+    Shannon Woods, Google
+    Geoff Lang, Google
+
+Contacts
+
+    Geoff Lang, Google (geofflang 'at' chromium 'dot' org)
+
+Status
+
+    Draft
+
+Version
+
+    Version 3, 2014-11-26
+
+Number
+
+    EGL Extension XXX
+
+Extension Type
+
+    EGL client extension
+
+Dependencies
+
+    Requires ANGLE_platform_angle.
+
+Overview
+
+    This extension enables selection of D3D display types.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as values for the EGL_PLATFORM_ANGLE_TYPE_ANGLE attribute:
+
+        EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE                 0x3207
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE                0x3208
+
+    Accepted as an attribute name in the <attrib_list> argument of
+    eglGetPlatformDisplayEXT:
+
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE               0x3209
+        EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE     0x320F
+
+    Accepted as values for the EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE attribute:
+
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE      0x320A
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE          0x320B
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE     0x320C
+
+Additions to the EGL Specification
+
+    None.
+
+New Behavior
+
+    To request a display that is backed by Direct3D resources, the value of
+    EGL_PLATFORM_ANGLE_TYPE_ANGLE should be:
+      - EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE for a D3D9 display,
+      - EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE for a D3D11 display.
+
+    To request a specific maximum feature level to be used by the D3D11
+    display, EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE and
+    EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE can be used.  Only feature
+    levels that are capable of supporting all available client APIs will be
+    used unless explicitly requested.
+    EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE and
+    EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE have no effect when requesting
+    a D3D9 display.
+
+    If no <attrib_list> is specified to eglGetPlatformDisplayEXT, the value of
+    EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE is implicitly set to
+    EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE. Otherwise, the value of
+    EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE should be:
+      - EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE to request a hardware
+        accelerated device.
+      - EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE to request an
+        optimized software rasterizer.
+      - EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE to request a
+        reference rasterizer.
+
+    If EGL_PLATFORM_ANGLE_TYPE_ANGLE is set to
+    EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, the display can automatically respond
+    to trim events from the operating system.  If the attribute
+    EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is unspecified, it is
+    implicitly set to EGL_FALSE.  Otherwise, the value of
+    EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE should be EGL_TRUE or
+    EGL_FALSE.
+
+    If EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE is set to
+    EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE and EGL_PLATFORM_ANGLE_TYPE_ANGLE
+    is not set to EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, an EGL_BAD_ATTRIBUTE
+    error is generated and EGL_NO_DISPLAY is returned.
+
+    If EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is specified when
+    EGL_PLATFORM_ANGLE_TYPE_ANGLE is not EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE
+    or a value other than EGL_TRUE or EGL_FALSE is used, an EGL_BAD_ATTRIBUTE
+    error is generated and EGL_NO_DISPLAY is returned.
+
+Issues
+
+    1) Some multithreaded applications can crash if the display automatically
+       responds to trim events while the application is rendering from another
+       thread.
+
+       RESOLVED: Added an EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE
+       enum to specify if the display should respond to trim events.
+       Applications that do multithreaded rendering should disable automatic
+       trim and handle the trim events on their own.
+
+Revision History
+
+    Version 1, 2014-06-05 (Geoff Lang)
+      - Initial draft
+    Version 2, 2014-10-27 (Geoff Lang)
+      - Separate WARP devices into a new attribute instead of a platform type.
+      - Moved descriptions of platforms and major/minor versions from
+        EGL_ANGLE_platform_angle spec to EGL_ANGLE_platform_angle_d3d.
+    Version 3, 2014-11-26 (Geoff Lang)
+      - Remove the USE_WARP bool and replace it with a DEVICE_TYPE enum.
+    Version 4, 2015-03-11 (Geoff Lang)
+      - Add the ENABLE_AUTOMATIC_TRIM enum.
diff --git a/src/third_party/angle/extensions/ANGLE_platform_angle_null.txt b/src/third_party/angle/extensions/ANGLE_platform_angle_null.txt
new file mode 100644
index 0000000..e9b8ee2
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_platform_angle_null.txt
@@ -0,0 +1,73 @@
+Name
+
+    ANGLE_platform_angle_null
+
+Name Strings
+
+    EGL_ANGLE_platform_angle_null
+
+Contributors
+
+    Geoff Lang, Google
+
+Contacts
+
+    Geoff Lang, Google (geofflang 'at' google 'dot' com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, September 23, 2016
+
+Number
+
+    EGL Extension #??
+
+Extension Type
+
+    EGL client extension
+
+Dependencies
+
+    Requires ANGLE_platform_angle.
+
+Overview
+
+    This extension enables selection of null display types which perform state
+    tracking and validation but do not render any content.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as values for the EGL_PLATFORM_ANGLE_TYPE_ANGLE attribute:
+
+        EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE               0x33AE
+
+Additions to the EGL Specification
+
+    None.
+
+New Behavior
+
+    To request a display that performs no rendering and has no platform
+    dependencies, the value of EGL_PLATFORM_ANGLE_TYPE_ANGLE should be
+    EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE.
+
+Issues
+
+    None
+
+Revision History
+
+    Version 1, 2016-09-23 (Geoff Lang)
+      - Initial draft
diff --git a/src/third_party/angle/extensions/ANGLE_platform_angle_opengl.txt b/src/third_party/angle/extensions/ANGLE_platform_angle_opengl.txt
new file mode 100644
index 0000000..9768638
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_platform_angle_opengl.txt
@@ -0,0 +1,84 @@
+Name
+
+    ANGLE_platform_angle_opengl
+
+Name Strings
+
+    EGL_ANGLE_platform_angle_opengl
+
+Contributors
+
+    Shannon Woods, Google
+    Geoff Lang, Google
+
+Contacts
+
+    Geoff Lang, Google (geofflang 'at' chromium 'dot' org)
+
+Status
+
+    Draft
+
+Version
+
+    Version 3, 2014-11-26
+
+Number
+
+    EGL Extension XXX
+
+Extension Type
+
+    EGL client extension
+
+Dependencies
+
+    Requires ANGLE_platform_angle.
+
+Overview
+
+    This extension enables selection of OpenGL display types.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as values for the EGL_PLATFORM_ANGLE_TYPE_ANGLE attribute:
+
+        EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE               0x320D
+        EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE             0x320E
+
+Additions to the EGL Specification
+
+    None.
+
+New Behavior
+
+    To request a display that translates to OpenGL or OpenGL ES, the value of
+    EGL_PLATFORM_ANGLE_TYPE_ANGLE should be:
+      - EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE for an OpenGL display,
+      - EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE for a native OpenGL ES display.
+
+    To request a specific maximum context version to use for the underlying
+    API, EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE and
+    EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE can be used.
+
+Issues
+
+    None
+
+Revision History
+
+    Version 1, 2014-06-05 (Geoff Lang)
+      - Initial draft
+    Version 2, 2014-10-27 (Geoff Lang)
+      - Moved descriptions of platforms and major/minor versions from
+        EGL_ANGLE_platform_angle spec to EGL_ANGLE_platform_angle_opengl.
+    Version 3, 2014-11-26 (Geoff Lang)
+      - Updated enum values.
diff --git a/src/third_party/angle/extensions/ANGLE_platform_angle_vulkan.txt b/src/third_party/angle/extensions/ANGLE_platform_angle_vulkan.txt
new file mode 100644
index 0000000..7c426f7
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_platform_angle_vulkan.txt
@@ -0,0 +1,110 @@
+Name
+
+    ANGLE_platform_angle_vulkan
+
+Name Strings
+
+    EGL_ANGLE_platform_angle_vulkan
+
+Contributors
+
+    Jamie Madill, Google
+
+Contacts
+
+    Jamie Madill, Google (jmadill 'at' google 'dot' com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, 2016-11-17
+
+Number
+
+    EGL Extension XXX
+
+Extension Type
+
+    EGL client extension
+
+Dependencies
+
+    Requires ANGLE_platform_angle.
+
+Overview
+
+    This extension enables selection of Vulkan display types.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as values for the EGL_PLATFORM_ANGLE_TYPE_ANGLE attribute:
+
+        EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE               0x3450
+
+    Accepted as an attribute name in the <attrib_list> argument of
+    eglGetPlatformDisplayEXT:
+
+        EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE   0x3451
+
+Additions to the EGL Specification
+
+    None.
+
+New Behavior
+
+    To request a display that is backed by a Vulkan driver, the value of
+    EGL_PLATFORM_ANGLE_TYPE_ANGLE should be
+    EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE.
+
+    If EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE is specified, it
+    controls enabling the standard Vulkan validation layers. EGL_TRUE enables
+    the validation and EGL_FALSE disables it. Any value other than these will
+    result in an error. If the flag is not specified, validation may default
+    to either enabled or disabled, depending on compile-time parameters in the
+    implementation.
+
+    If EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE and
+    EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE are not specified, the
+    implementation will decide which version of Vulkan to instantiate. If they
+    are specified, it will choose a version that is lower or equal to the
+    specified major and minor versions. The only current values accepted for
+    major and minor version are 1 for major and 0 for minor.
+
+Issues
+
+    1) Would it be better to specify validation layers individually?
+
+       RESOLVED: It would give more fined grained control, but the layers
+       are sensitive to ordering, and there may be new ones added or old ones
+       removed, this abstracts the logic into a simpler form. The validation
+       layers maintainers are also moving towards a single-layer model from
+       the current multiple layers approach.
+
+    2) Should the validation layers default to on, off, or no guarantee?
+
+       Defaulting to off offers some consistency. However, it's customary for
+       some applications like ANGLE to turn on debugging features by default
+       in Debug builds.
+
+    3) Should ANGLE always instantiate the highest available version of Vulkan?
+
+       RESOLVED: It's possible that in a future implementation of Vulkan there
+       may be driver issues present only on some version of Vulkan, and there's
+       no explicit guarantee higher versions will be more stable. Hence, we should
+       give ANGLE some flexiblity in this regard and leave this unspecified.
+
+Revision History
+
+    Version 1, 2016-11-17 (Jamie Madill)
+      - Initial draft
diff --git a/src/third_party/angle/extensions/ANGLE_request_extension.txt b/src/third_party/angle/extensions/ANGLE_request_extension.txt
new file mode 100644
index 0000000..6536035
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_request_extension.txt
@@ -0,0 +1,116 @@
+Name
+
+    ANGLE_request_extension
+
+Name Strings
+
+    GL_ANGLE_request_extension
+
+Contributors
+
+    Geoff Lang
+
+Contact
+
+    Geoff Lang (geofflang 'at' google.com)
+
+Notice
+
+    Copyright (c) 2016 The Khronos Group Inc. Copyright terms at
+        http://www.khronos.org/registry/speccopyright.html
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, November 28, 2016
+
+Number
+
+    OpenGL ES Extension #??
+
+Dependencies
+
+    Requires OpenGL ES 2.0
+
+    Written against the OpenGL ES 3.0 specification.
+
+Overview
+
+    This extension allows the client to query extensions that can be enabled and
+    explicitly request than an extension be enabled.
+
+New Procedures and Functions
+
+    void RequestExtension(const char *name)
+
+New Tokens
+
+    Accepted by the <name> parameter of GetString and GetStringi:
+
+        REQUESTABLE_EXTENSIONS_ANGLE      0x93A8
+
+    Accepted by the <value> parameter of the GetInteger* functions:
+
+        NUM_REQUESTABLE_EXTENSIONS_ANGLE  0x93A9
+
+Additions to the OpenGL ES 3.0 Specification
+
+    Add the following paragraph to the end paragraph 4 of section 6.1.6, String
+    Queries:
+
+    "REQUESTABLE_EXTENSIONS_ANGLE returns a list of extensions that can be
+    enabled at runtime by calling RequestExtension."
+
+    Change the following section of paragraph 6 of section 6.1.6, String Queries:
+
+    - "name may only be EXTENSIONS, indicating that the extension name
+    - corresponding to the indexth supported extension should be returned.
+    - <index> may range from zero to the value of NUM_EXTENSIONS minus one"
+    + "name may be EXTENSIONS or REQUESTABLE_EXTENSIONS_ANGLE, indicating that
+    + the extension name corresponding to the indexth supported or requestable
+    + extension should be returned. <index> may range from zero to the value of
+    + NUM_EXTENSIONS and NUM_REQUESTABLE_EXTENSIONS_ANGLE minus one"
+
+    The command
+
+       void RequestExtension(const char *name)
+
+    enables the requestable OpenGL ES extension named <name>. If the extension
+    was not requestable, INVALID_OPERATION is generated.
+
+New State
+
+    Add to Table 6.30 (Implementation Dependent Version and Extension Support)
+
+    Get value                        Type Get Cmd     Min Value Description                      Sec.
+    -------------------------------- ---- ----------- --------- -------------------------------- -----
+    NUM_REQUESTABLE_EXTENSIONS_ANGLE Z+   GetIntegerv -         Number of individual requestable 6.1.6
+                                                                extension names
+
+Interactions with the OpenGL ES 2.0 specification:
+
+    Remove all references to GetStringi and NUM_REQUESTABLE_EXTENSIONS_ANGLE.
+
+Issues
+
+    (1) How can the user determine which extensions can be enabled without
+        potentially generating errors?
+
+      This can be solved by:
+      a) Never generate an error in EnableExtensions, simply return false when
+         the extension is not recognized or cannot be enabled.
+      b) Add another query for the extensions that the context supports
+         enabling.
+
+      RESOLVED: Use (b) because it allows the context to explicity advertise
+      which extensions support enabling and doesn't generate errors in the
+      normal use case.
+
+Revision History
+
+    Rev.    Date         Author     Changes
+    ----  -------------  ---------  ----------------------------------------
+      1    Nov 28, 2016  geofflang  Initial version
diff --git a/src/third_party/angle/extensions/ANGLE_robust_client_memory.txt b/src/third_party/angle/extensions/ANGLE_robust_client_memory.txt
new file mode 100644
index 0000000..933deb0
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_robust_client_memory.txt
@@ -0,0 +1,180 @@
+Name
+
+    ANGLE_robust_client_memory
+
+Name Strings
+
+    GL_ANGLE_robust_client_memory
+
+Contributors
+
+    Geoff Lang, Google
+
+Contacts
+
+    Geoff Lang, Google (geofflang 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 4, March 30, 2017
+
+Number
+
+    OpenGL ES Extension #??
+
+Dependencies
+
+    OpenGL ES 2.0 is required.
+
+    This extension is written against the wording of the OpenGL ES
+    3.2 specification.
+
+    Interacts with GL_KHR_debug, GL_EXT_disjoint_timer_queries,
+    GL_KHR_robustness.
+
+Overview
+
+    This extension adds overloads of many OpenGL ES functions that read from
+    and write to client memory to ensure that all reads and writes done by the
+    OpenGL ES implementation are safe.  When the OpenGL ES API is exposed to
+    users through complex bindings such as WebGL, allowing undefined behaviour
+    that may result in crashing the implementation is not acceptable.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    void GetBooleanvRobustANGLE(enum pname, sizei bufSize, sizei *length, boolean *data)
+    void GetBufferParameterivRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetFloatvRobustANGLE(enum pname, sizei bufSize, sizei *length, float *data)
+    void GetFramebufferAttachmentParameterivRobustANGLE(enum target, enum attachment, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetIntegervRobustANGLE(enum pname, sizei bufSize, sizei *length, int *data)
+    void GetProgramivRobustANGLE(uint program, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetRenderbufferParameterivRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetShaderivRobustANGLE(uint shader, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetTexParameterfvRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, float *params)
+    void GetTexParameterivRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetUniformfvRobustANGLE(uint program, int location, sizei bufSize, sizei *length, float *params)
+    void GetUniformivRobustANGLE(uint program, int location, sizei bufSize, sizei *length, int *params)
+    void GetVertexAttribfvRobustANGLE(uint index, enum pname, sizei bufSize, sizei *length, float *params)
+    void GetVertexAttribivRobustANGLE(uint index, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetVertexAttribPointervRobustANGLE(uint index, enum pname, sizei bufSize, sizei *length, void **pointer)
+    void ReadPixelsRobustANGLE(int x, int y, sizei width, sizei height, enum format, enum type, sizei bufSize, sizei *length, sizei *columns, sizei *rows, void *pixels)
+    void TexImage2DRobustANGLE(enum target, int level, int internalformat, sizei width, sizei height, int border, enum format, enum type, sizei bufSize, const void *pixels)
+    void TexParameterfvRobustANGLE(enum target, enum pname, sizei bufSize, const GLfloat *params)
+    void TexParameterivRobustANGLE(enum target, enum pname, sizei bufSize, const GLint *params)
+    void TexSubImage2DRobustANGLE(enum target, int level, int xoffset, int yoffset, sizei width, sizei height, enum format, enum type, sizei bufSize, const void *pixels)
+    void CompressedTexImage2D(enum target, int level, enum internalformat, sizei width, sizei height, int border, sizei imageSize, sizei bufSize, const void* data)
+    void CompressedTexSubImage2D(enum target, int level, int xoffset, int yoffset, sizei width, sizei height, enum format, sizei imageSize, sizei bufSize, const void* data)
+    void CompressedTexImage3D(enum target, int level, enum internalformat, sizei width, sizei height, sizei depth, int border, sizei imageSize, sizei bufSize, const void* data)
+    void CompressedTexSubImage3D(enum target, int level, int xoffset, int yoffset, int zoffset, sizei width, sizei height, sizei depth, enum format, sizei imageSize, sizei bufSize, const void* data)
+
+    void TexImage3DRobustANGLE(enum target, int level, int internalformat, sizei width, sizei height, sizei depth, int border, enum format, enum type, sizei bufSize, const void *pixels);
+    void TexSubImage3DRobustANGLE(enum target, int level, int xoffset, int yoffset, int zoffset, sizei width, sizei height, sizei depth, enum format, enum type, sizei bufSize, const void *pixels);
+    void GetQueryivRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetQueryObjectuivRobustANGLE(uint id, enum pname, sizei bufSize, sizei *length, uint *params)
+    void GetBufferPointervRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, void **params)
+    void GetIntegeri_vRobustANGLE(enum target, uint index, sizei bufSize, sizei *length, int *data)
+    void GetInternalformativRobustANGLE(enum target, enum internalformat, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetVertexAttribIivRobustANGLE(uint index, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetVertexAttribIuivRobustANGLE(uint index, enum pname, sizei bufSize, sizei *length, uint *params)
+    void GetUniformuivRobustANGLE(uint program, int location, sizei bufSize, sizei *length, uint *params)
+    void GetActiveUniformBlockivRobustANGLE(uint program, uint uniformBlockIndex, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetInteger64vRobustANGLE(enum pname, sizei bufSize, sizei *length, int64 *data)
+    void GetInteger64i_vRobustANGLE(enum target, uint index, sizei bufSize, sizei *length, int64 *data)
+    void GetBufferParameteri64vRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, int64 *params)
+    void SamplerParameterivRobustANGLE(uint sampler, enum pname, sizei bufSize, const GLint *param)
+    void SamplerParameterfvRobustANGLE(uint sampler, enum pname, sizei bufSize, const GLfloat *param)
+    void GetSamplerParameterivRobustANGLE(uint sampler, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetSamplerParameterfvRobustANGLE(uint sampler, enum pname, sizei bufSize, sizei *length, float *params)
+
+    void GetFramebufferParameterivRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetProgramInterfaceivRobustANGLE(uint program, enum programInterface, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetBooleani_vRobustANGLE(enum target, uint index, sizei bufSize, sizei *length, boolean *data)
+    void GetMultisamplefvRobustANGLE(enum pname, uint index, sizei bufSize, sizei *length, float *val)
+    void GetTexLevelParameterivRobustANGLE(enum target, int level, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetTexLevelParameterfvRobustANGLE(enum target, int level, enum pname, sizei bufSize, sizei *length, float *params)
+
+    void GetPointervRobustANGLERobustANGLE(enum pname, sizei bufSize, sizei *length, void **params)
+    void ReadnPixelsRobustANGLE(int x, int y, sizei width, sizei height, enum format, enum type, sizei bufSize, sizei *length, sizei *columns, sizei *rows, void *data)
+    void GetnUniformfvRobustANGLE(uint program, int location, sizei bufSize, sizei *length, float *params)
+    void GetnUniformivRobustANGLE(uint program, int location, sizei bufSize, sizei *length, int *params)
+    void GetnUniformuivRobustANGLE(uint program, int location, sizei bufSize, sizei *length, uint *params)
+    void TexParameterIivRobustANGLE(enum target, enum pname, sizei bufSize, const GLint *params)
+    void TexParameterIuivRobustANGLE(enum target, enum pname, sizei bufSize, const GLuint *params)
+    void GetTexParameterIivRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetTexParameterIuivRobustANGLE(enum target, enum pname, sizei bufSize, sizei *length, uint *params)
+    void SamplerParameterIivRobustANGLE(uint sampler, enum pname, sizei bufSize, const GLint *param)
+    void SamplerParameterIuivRobustANGLE(uint sampler, enum pname, sizei bufSize, const GLuint *param)
+    void GetSamplerParameterIivRobustANGLE(uint sampler, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetSamplerParameterIuivRobustANGLE(uint sampler, enum pname, sizei bufSize, sizei *length, uint *params)
+
+    void GetQueryObjectivRobustANGLE(uint id, enum pname, sizei bufSize, sizei *length, int *params)
+    void GetQueryObjecti64vRobustANGLE(uint id, enum pname, sizei bufSize, sizei *length, int64 *params)
+    void GetQueryObjectui64vRobustANGLE(uint id, enum pname, sizei bufSize, sizei *length, uint64 *params)
+
+New Tokens
+
+    None
+
+Additions to the OpenGL ES Specification:
+
+    The xRobustANGLE entry points perform additional validation using <bufSize>
+    to indicate the maximum number of values that can be read from or written
+    to the provided buffer.  INVALID_OPERATION is generated if <bufSize> is not
+    large enough.  The optional <length> specifies an address of a variable to
+    recieve the number of values written to the buffer.  When an error is
+    generated nothing will be written to <length>.
+
+    The <columns> and <rows> parameters of ReadPixelsRobustANGLE and
+    ReadnPixelsRobustANGLE specify addresses of variables to recieve the number
+    of columns and rows of pixels written to the buffer which may be less than
+    the <width> and <height> parameters if they would have read outside of the
+    framebuffer.
+
+    Calls to "xRobustANGLE" will generate errors under the same conditions as
+    "x". Any instances of undefined behaviour in "x" will also be undefined in
+    "xRobustANGLE".  For example, it is invalid to call
+    GetPointervRobustANGLERobustANGLE without first verifying that the context
+    is at least OpenGL ES version 3.2 or the GL_KHR_debug extension is present.
+
+Issues
+
+    1) Should additional entry points be added to specify sizes of client side
+       data provided to the VertexAttribPointer functions?
+
+    2) Should <length> be allowed to be null?
+
+       RESOLVED: Yes, <length> will not be written to when it is a null
+       pointer.
+
+    3) Should <bufSize> be specified in bytes or values (uint, int, float,
+       etc)?
+
+       There is no consistancy in current entry points for this.  For example,
+       glGetnUniformuiv indicates that bufSize is in bytes while GetSynciv
+       uses values despite GetnUniformuiv having a clear value type.
+
+       RESOLOVED: <bufSize> always indicates size in values. Functions that
+       specify data by void* such as TexImage2DRobustANGLE treat the client
+       data as bytes.
+
+    4) Should <length> be written to if an error is generated?
+
+       RESOLVED: No, using the prescedent set by glGetSynciv.
+
+Revision History
+
+    Rev.    Date         Author     Changes
+    ----  -------------  ---------  -------------------------------------------
+      1   Sept 26, 2016  geofflang  Initial version
+      2   Sept 28, 2016  geofflang  Changed name from ANGLE_robust_queries to
+                                    ANGLE_robust_client_memory, added issue 3.
+      3   Oct 7, 2016    geofflang  Added and resolved issue 4.
+      4   Mar 30, 2017   geofflang  Added columns and rows to ReadPixels.
diff --git a/src/third_party/angle/extensions/ANGLE_robust_resource_initialization.txt b/src/third_party/angle/extensions/ANGLE_robust_resource_initialization.txt
new file mode 100644
index 0000000..dbe2828
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_robust_resource_initialization.txt
@@ -0,0 +1,143 @@
+Name
+
+    ANGLE_robust_resource_initialization.txt
+
+Name Strings
+
+    ANGLE_robust_resource_intialization
+
+Contributors
+
+    Geoff Lang, Google
+    Ken Russell, Google
+
+Contacts
+
+    Shannon Woods, Google (shannonwoods 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, January 7, 2015
+
+Number
+
+    OpenGL ES Extension TBD
+
+Dependencies
+
+    OpenGL ES 2.0 is required.
+
+    This extension is written against the wording of the OpenGL ES
+    3.1 specification.
+
+    EGL_ANGLE_create_context_robust_initialization is required to request a
+    context that supports this extension, and resource initialization.
+
+Overview
+
+    This extension specifies the behavior for initialization of
+    resources such as textures and buffers to default values. This
+    initialization ensures that access will not be provided by the
+    GL to previously allocated data not owned by the application.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted by the <value> parameter of GetBooleanv, GetIntegerv,
+    GetFloatv, GetDoublev, GetInteger64v, and IsEnabled:
+
+        CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE    0x93A7
+
+Additions to Chapter 6 of the OpenGL ES 3.1 Specification (Buffer
+Objects)
+
+    Replace the last sentence of the first paragraph of section 6.2
+    "BufferData":
+
+    If <data> is NULL, and robust resource initialization is enabled,
+    the contents of the buffer object's data store are set to zero.
+    Otherwise, the contents of the buffer object's data store are
+    undefined.
+
+Additions to Chapter 8 of the OpenGL ES 3.1 Specification (Textures and
+Samplers)
+
+    Replace the first two sentances of the final paragraph in section
+    8.5.3 "Texture Image Structure":
+
+    If the <data> argument of TexImage2D or TexImage3D is NULL, and the
+    pixel unpack buffer object is zero, a two- or three-dimensional
+    texel array is created with the specified <target>, <level>,
+    <internalformat>, <border>, <width>, <height>, and <depth>. If
+    robust resource initialization is enabled, the contents of the image
+    are initialized as though a zero value were provided for each
+    component of each pixel, and processed and transferred to the GL
+    as described above. The components comprising this zero-filled data
+    are determined by <internalformat>. If robust resource
+    initialization is not enabled, the image contents are undefined, and
+    no pixel processing is performed. In either case, no pixel values
+    are accessed in client memory.
+
+    Replace the first sentence of the fifth paragraph in section 8.8
+    "Multisample Textures":
+
+    Upon success, TexStorage2DMultisample deletes any existing image
+    for target. If robust resource initialization is enabled, the
+    contents of each texel are initialized as though a zero value were
+    written to each channel of each sample; otherwise the contents of
+    texels are undefined.
+
+    Add to the final paragraph of section 8.17 "Immutable-Format Texture
+    Images":
+
+    If robust resource initialization is enabled, the contents of each
+    texel is initialized as though a zero value were provided for each
+    component of each pixel, and processed and transferred to the GL
+    as for a call to the appropriate TexSubImage* call for <target>.
+    Otherwise, the contents of texels are undefined.
+
+Additions to Chapter 9 of the OpenGL ES 3.1 Specification (Framebuffers
+and Framebuffer Objects)
+
+    Replace the sentence in section 9.2.4 "Renderbuffer Objects"
+    beginning "Upon success, RenderbufferStorageMultisample":
+
+    Upon success, RenderbufferStorageMultisample deletes any existing
+    data store for the renderbuffer image. If robust resource
+    initialization is enabled, the contents of each pixel in the data
+    store are initialized as though a zero value was written to each
+    channel of each sample; otherwise, the contents of the data store
+    are undefined.
+
+Interactions with EGL_ANGLE_create_context_robust_resource_initialization
+
+    If the EGL window-system binding API is used to create a context,
+    the EGL_ANGLE_create_context_robust_initialization extension is
+    supported, and the attribute
+    EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE is set to
+    EGL_TRUE when eglCreateContext is called, the resulting context
+    will perform robust resource initialization as described above in
+    section <section>, and the
+    CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE
+    query will return GL_TRUE as described above in section 2.6.1.1.
+    Otherwise queries will return GL_FALSE.
+
+Issues
+
+    None
+
+Revision History
+
+    Version 1, 2015/01/07 - first draft.
+    Version 2, 2017/03/07 - fixed EGL naming and added IsEnabled.
diff --git a/src/third_party/angle/extensions/ANGLE_timer_query.txt b/src/third_party/angle/extensions/ANGLE_timer_query.txt
index 3cc3858..c1371ad 100644
--- a/src/third_party/angle/extensions/ANGLE_timer_query.txt
+++ b/src/third_party/angle/extensions/ANGLE_timer_query.txt
@@ -1,591 +1,591 @@
-Name

-

-    ANGLE_timer_query

-

-Name Strings

-

-    GL_ANGLE_timer_query

-

-Contributors

-

-    Contributors to ARB_occlusion_query

-    Contributors to EXT_timer_query

-    Contributors to ARB_timer_query

-    Ben Vanik, Google Inc.

-    Daniel Koch, TransGaming Inc.

-

-Contact

-

-    Ben Vanik, Google Inc. (benvanik 'at' google 'dot' com)

-

-Status

-

-    Draft

-

-Version

-

-    Last Modified Date: Apr 28, 2011

-    Author Revision: 1

-

-Number

-

-    OpenGL ES Extension #??

-

-Dependencies

-

-    OpenGL ES 2.0 is required.

-

-    The extension is written against the OpenGL ES 2.0 specification.

-

-Overview

-

-    Applications can benefit from accurate timing information in a number of

-    different ways.  During application development, timing information can

-    help identify application or driver bottlenecks.  At run time,

-    applications can use timing information to dynamically adjust the amount

-    of detail in a scene to achieve constant frame rates.  OpenGL

-    implementations have historically provided little to no useful timing

-    information.  Applications can get some idea of timing by reading timers

-    on the CPU, but these timers are not synchronized with the graphics

-    rendering pipeline.  Reading a CPU timer does not guarantee the completion

-    of a potentially large amount of graphics work accumulated before the

-    timer is read, and will thus produce wildly inaccurate results.

-    glFinish() can be used to determine when previous rendering commands have

-    been completed, but will idle the graphics pipeline and adversely affect

-    application performance.

-

-    This extension provides a query mechanism that can be used to determine

-    the amount of time it takes to fully complete a set of GL commands, and

-    without stalling the rendering pipeline.  It uses the query object

-    mechanisms first introduced in the occlusion query extension, which allow

-    time intervals to be polled asynchronously by the application.

-

-IP Status

-

-    No known IP claims.

-

-New Procedures and Functions

-

-    void GenQueriesANGLE(sizei n, uint *ids);

-    void DeleteQueriesANGLE(sizei n, const uint *ids);

-    boolean IsQueryANGLE(uint id);

-    void BeginQueryANGLE(enum target, uint id);

-    void EndQueryANGLE(enum target);

-    void QueryCounterANGLE(uint id, enum target);

-    void GetQueryivANGLE(enum target, enum pname, int *params);

-    void GetQueryObjectivANGLE(uint id, enum pname, int *params);

-    void GetQueryObjectuivANGLE(uint id, enum pname, uint *params);

-    void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params);

-    void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params);

-

-New Tokens

-

-    Accepted by the <pname> parameter of GetQueryivANGLE:

-

-        QUERY_COUNTER_BITS_ANGLE                       0x8864

-        CURRENT_QUERY_ANGLE                            0x8865

-

-    Accepted by the <pname> parameter of GetQueryObjectivANGLE,

-    GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, and

-    GetQueryObjectui64vANGLE:

-

-        QUERY_RESULT_ANGLE                             0x8866

-        QUERY_RESULT_AVAILABLE_ANGLE                   0x8867

-        

-    Accepted by the <target> parameter of BeginQueryANGLE, EndQueryANGLE, and

-    GetQueryivANGLE:

-

-        TIME_ELAPSED_ANGLE                             0x88BF

-

-    Accepted by the <target> parameter of GetQueryivANGLE and

-    QueryCounterANGLE:

-

-        TIMESTAMP_ANGLE                                0x8E28

-

-Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)

-

-    (Modify table 2.1, Correspondence of command suffix letters to GL argument)

-    Add two new types:

-    

-    Letter Corresponding GL Type

-    ------ ---------------------

-    i64    int64ANGLE

-    ui64   uint64ANGLE

-

-    (Modify table 2.2, GL data types) Add two new types:

-    

-    GL Type       Minimum Bit Width   Description

-    -------       -----------------   -----------------------------

-    int64ANGLE    64                  Signed 2's complement integer

-    uint64ANGLE   64                  Unsigned binary integer

-

-Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)

-

-    Add a new section 5.3 "Timer Queries":

-

-    "5.3  Timer Queries

-

-    Timer queries use query objects to track the amount of time needed to

-    fully complete a set of GL commands, or to determine the current time

-    of the GL.

-    

-    Timer queries are associated with query objects.  The command

-

-      void GenQueriesANGLE(sizei n, uint *ids);

-

-    returns <n> previously unused query object names in <ids>.  These

-    names are marked as used, but no object is associated with them until

-    the first time they are used by BeginQueryANGLE.  Query objects contain

-    one piece of state, an integer result value.  This result value is

-    initialized to zero when the object is created.  Any positive integer

-    except for zero (which is reserved for the GL) is a valid query

-    object name.

-

-    Query objects are deleted by calling

-

-      void DeleteQueriesANGLE(sizei n, const uint *ids);

-

-    <ids> contains <n> names of query objects to be deleted.  After a

-    query object is deleted, its name is again unused.  Unused names in

-    <ids> are silently ignored.

-    If an active query object is deleted its name immediately becomes unused,

-    but the underlying object is not deleted until it is no longer active.

-

-    A timer query can be started and finished by calling

-

-      void BeginQueryANGLE(enum target, uint id);

-      void EndQueryANGLE(enum target);

-

-    where <target> is TIME_ELAPSED_ANGLE.  If BeginQueryANGLE is called

-    with an unused <id>, that name is marked as used and associated with

-    a new query object.

-    

-    If BeginQueryANGLE is called with an <id> of zero, if the active query

-    object name for <target> is non-zero, if <id> is the name of an existing

-    query object whose type does not match <target>, or if <id> is the active

-    query object name for any query type, the error INVALID_OPERATION is

-    generated.  If EndQueryANGLE is called while no query with the same target

-    is in progress, an INVALID_OPERATION error is generated.

-

-    When BeginQueryANGLE and EndQueryANGLE are called with a <target> of

-    TIME_ELAPSED_ANGLE, the GL prepares to start and stop the timer used for

-    timer queries.  The timer is started or stopped when the effects from all

-    previous commands on the GL client and server state and the framebuffer

-    have been fully realized.  The BeginQueryANGLE and EndQueryANGLE commands

-    may return before the timer is actually started or stopped.  When the timer

-    query timer is finally stopped, the elapsed time (in nanoseconds) is

-    written to the corresponding query object as the query result value, and

-    the query result for that object is marked as available.

-

-    If the elapsed time overflows the number of bits, <n>, available to hold

-    elapsed time, its value becomes undefined.  It is recommended, but not

-    required, that implementations handle this overflow case by saturating at

-    2^n - 1.

-

-    The necessary state is a single bit indicating whether an timer

-    query is active, the identifier of the currently active timer

-    query, and a counter keeping track of the time that has passed.

-

-    When the command

-

-         void QueryCounterANGLE(uint id, enum target);

-

-    is called with <target> TIMESTAMP_ANGLE, the GL records the current time

-    into the corresponding query object. The time is recorded after all

-    previous commands on the GL client and server state and the framebuffer

-    have been fully realized. When the time is recorded, the query result for

-    that object is marked available. QueryCounterANGLE timer queries can be

-    used within a BeginQueryANGLE / EndQueryANGLE block where the <target> is

-    TIME_ELAPSED_ANGLE and it does not affect the result of that query object.

-    The error INVALID_OPERATION is generated if the <id> is already in use

-    within a BeginQueryANGLE/EndQueryANGLE block."

-

-Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State

-Requests)

-

-    Add a new section 6.1.9 "Timer Queries":

-

-    "The command

-

-      boolean IsQueryANGLE(uint id);

-

-    returns TRUE if <id> is the name of a query object.  If <id> is zero,

-    or if <id> is a non-zero value that is not the name of a query

-    object, IsQueryANGLE returns FALSE.

-

-    Information about a query target can be queried with the command

-

-      void GetQueryivANGLE(enum target, enum pname, int *params);

-

-    <target> identifies the query target and can be TIME_ELAPSED_ANGLE or

-    TIMESTAMP_ANGLE for timer queries.

-

-    If <pname> is CURRENT_QUERY_ANGLE, the name of the currently active query

-    for <target>, or zero if no query is active, will be placed in <params>.

-

-    If <pname> is QUERY_COUNTER_BITS_ANGLE, the implementation-dependent number

-    of bits used to hold the query result for <target> will be placed in

-    <params>.  The number of query counter bits may be zero, in which case

-    the counter contains no useful information.

-

-    For timer queries (TIME_ELAPSED_ANGLE and TIMESTAMP_ANGLE), if the number

-    of bits is non-zero, the minimum number of bits allowed is 30 which

-    will allow at least 1 second of timing.

-

-    The state of a query object can be queried with the commands

-

-      void GetQueryObjectivANGLE(uint id, enum pname, int *params);

-      void GetQueryObjectuivANGLE(uint id, enum pname, uint *params);

-      void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params);

-      void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params);

-

-    If <id> is not the name of a query object, or if the query object

-    named by <id> is currently active, then an INVALID_OPERATION error is

-    generated.

-

-    If <pname> is QUERY_RESULT_ANGLE, then the query object's result

-    value is returned as a single integer in <params>. If the value is so

-    large in magnitude that it cannot be represented with the requested type,

-    then the nearest value representable using the requested type is

-    returned. If the number of query counter bits for target is zero, then

-    the result is returned as a single integer with the value zero.

-    

-    There may be an indeterminate delay before the above query returns. If

-    <pname> is QUERY_RESULT_AVAILABLE_ANGLE, FALSE is returned if such a delay

-    would be required; otherwise TRUE is returned. It must always be true

-    that if any query object returns a result available of TRUE, all queries

-    of the same type issued prior to that query must also return TRUE.

-

-    Querying the state for a given timer query forces that timer query to

-    complete within a finite amount of time.

-

-    If multiple queries are issued on the same target and id prior to 

-    calling GetQueryObject[u]i[64]vANGLE, the result returned will always be

-    from the last query issued.  The results from any queries before the

-    last one will be lost if the results are not retrieved before starting

-    a new query on the same <target> and <id>."

-

-Errors

-

-    The error INVALID_VALUE is generated if GenQueriesANGLE is called where

-    <n> is negative.

-

-    The error INVALID_VALUE is generated if DeleteQueriesANGLE is called

-    where <n> is negative.

-

-    The error INVALID_OPERATION is generated if BeginQueryANGLE is called

-    when a query of the given <target> is already active.

-

-    The error INVALID_OPERATION is generated if EndQueryANGLE is called

-    when a query of the given <target> is not active.

-

-    The error INVALID_OPERATION is generated if BeginQueryANGLE is called

-    where <id> is zero.

-

-    The error INVALID_OPERATION is generated if BeginQueryANGLE is called

-    where <id> is the name of a query currently in progress.

-    

-    The error INVALID_OPERATION is generated if BeginQueryANGLE is called

-    where <id> is the name of an existing query object whose type does not

-    match <target>.

-

-    The error INVALID_ENUM is generated if BeginQueryANGLE or EndQueryANGLE

-    is called where <target> is not TIME_ELAPSED_ANGLE.

-

-    The error INVALID_ENUM is generated if GetQueryivANGLE is called where

-    <target> is not TIME_ELAPSED_ANGLE or TIMESTAMP_ANGLE.

-

-    The error INVALID_ENUM is generated if GetQueryivANGLE is called where

-    <pname> is not QUERY_COUNTER_BITS_ANGLE or CURRENT_QUERY_ANGLE.

-

-    The error INVALID_ENUM is generated if QueryCounterANGLE is called where

-    <target> is not TIMESTAMP_ANGLE.

-

-    The error INVALID_OPERATION is generated if QueryCounterANGLE is called

-    on a query object that is already in use inside a

-    BeginQueryANGLE/EndQueryANGLE.

-

-    The error INVALID_OPERATION is generated if GetQueryObjectivANGLE,

-    GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or

-    GetQueryObjectui64vANGLE is called where <id> is not the name of a query

-    object.

-

-    The error INVALID_OPERATION is generated if GetQueryObjectivANGLE,

-    GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or

-    GetQueryObjectui64vANGLE is called where <id> is the name of a currently

-    active query object.

-

-    The error INVALID_ENUM is generated if GetQueryObjectivANGLE,

-    GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or

-    GetQueryObjectui64vANGLE is called where <pname> is not

-    QUERY_RESULT_ANGLE or QUERY_RESULT_AVAILABLE_ANGLE.

-

-New State

-

-    (Add a new table 6.xx, "Query Operations")

-    

-    Get Value                      Type    Get Command              Initial Value   Description              Sec

-    ---------                      ----    -----------              -------------   -----------              ------

-    -                              B       -                        FALSE           query active             5.3

-    CURRENT_QUERY_ANGLE            Z+      GetQueryivANGLE          0               active query ID          5.3

-    QUERY_RESULT_ANGLE             Z+      GetQueryObjectuivANGLE,  0               samples-passed count     5.3

-                                           GetQueryObjectui64vANGLE

-    QUERY_RESULT_AVAILABLE_ANGLE   B       GetQueryObjectivANGLE    FALSE           query result available   5.3

-

-New Implementation Dependent State

-

-    (Add the following entry to table 6.18):

-

-    Get Value                      Type    Get Command      Minimum Value      Description           Sec

-    --------------------------     ----    -----------      -------------      ----------------      ------

-    QUERY_COUNTER_BITS_ANGLE       Z+      GetQueryivANGLE  see 6.1.9          Number of bits in     6.1.9

-                                                                               query counter

-

-Examples

-

-    (1) Here is some rough sample code that demonstrates the intended usage

-        of this extension.

-

-        GLint queries[N];

-        GLint available = 0;

-        // timer queries can contain more than 32 bits of data, so always

-        // query them using the 64 bit types to avoid overflow

-        GLuint64ANGLE timeElapsed = 0;

-

-        // Create a query object.

-        glGenQueriesANGLE(N, queries);

-

-        // Start query 1

-        glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[0]);

-

-        // Draw object 1

-        ....

-

-        // End query 1

-        glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE);

-

-        ...

-

-        // Start query N

-        glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[N-1]);

-

-        // Draw object N

-        ....

-

-        // End query N

-        glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE);

-

-        // Wait for all results to become available

-        while (!available) {

-            glGetQueryObjectivANGLE(queries[N-1], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available);

-        }

-

-        for (i = 0; i < N; i++) {

-            // See how much time the rendering of object i took in nanoseconds.

-            glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeElapsed);

-

-            // Do something useful with the time.  Note that care should be

-            // taken to use all significant bits of the result, not just the

-            // least significant 32 bits.

-            AdjustObjectLODBasedOnDrawTime(i, timeElapsed);

-        }

-

-        This example is sub-optimal in that it stalls at the end of every

-        frame to wait for query results.  Ideally, the collection of results

-        would be delayed one frame to minimize the amount of time spent

-        waiting for the GPU to finish rendering.

-        

-    (2) This example is basically the same as the example above but uses

-        QueryCounter instead.

-    

-        GLint queries[N+1];

-        GLint available = 0;

-        // timer queries can contain more than 32 bits of data, so always

-        // query them using the 64 bit types to avoid overflow

-        GLuint64ANGLE timeStart, timeEnd, timeElapsed = 0;

-

-        // Create a query object.

-        glGenQueriesANGLE(N+1, queries);

-

-        // Query current timestamp 1

-        glQueryCounterANGLE(queries[0], GL_TIMESTAMP_ANGLE);

-

-        // Draw object 1

-        ....

-

-        // Query current timestamp N

-        glQueryCounterANGLE(queries[N-1], GL_TIMESTAMP_ANGLE);

-

-        // Draw object N

-        ....

-

-        // Query current timestamp N+1

-        glQueryCounterANGLE(queries[N], GL_TIMESTAMP_ANGLE);

-

-        // Wait for all results to become available

-        while (!available) {

-            glGetQueryObjectivANGLE(queries[N], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available);

-        }

-

-        for (i = 0; i < N; i++) {

-            // See how much time the rendering of object i took in nanoseconds.

-            glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeStart);

-            glGetQueryObjectui64vANGLE(queries[i+1], GL_QUERY_RESULT_ANGLE, &timeEnd);

-            timeElapsed = timeEnd - timeStart;

-

-            // Do something useful with the time.  Note that care should be

-            // taken to use all significant bits of the result, not just the

-            // least significant 32 bits.

-            AdjustObjectLODBasedOnDrawTime(i, timeElapsed);

-        }

-

-Issues from EXT_timer_query

-

-    (1) What time interval is being measured?

-

-    RESOLVED:  The timer starts when all commands prior to BeginQuery() have

-    been fully executed.  At that point, everything that should be drawn by

-    those commands has been written to the framebuffer.  The timer stops

-    when all commands prior to EndQuery() have been fully executed.

-

-    (2) What unit of time will time intervals be returned in?

-

-    RESOLVED:  Nanoseconds (10^-9 seconds).  This unit of measurement allows

-    for reasonably accurate timing of even small blocks of rendering

-    commands.  The granularity of the timer is implementation-dependent.  A

-    32-bit query counter can express intervals of up to approximately 4

-    seconds.

-

-    (3) What should be the minimum number of counter bits for timer queries?

-

-    RESOLVED:  30 bits, which will allow timing sections that take up to 1

-    second to render.

-

-    (4) How are counter results of more than 32 bits returned?

-

-    RESOLVED:  Via two new datatypes, int64ANGLE and uint64ANGLE, and their

-    corresponding GetQueryObject entry points.  These types hold integer

-    values and have a minimum bit width of 64.

-

-    (5) Should the extension measure total time elapsed between the full

-        completion of the BeginQuery and EndQuery commands, or just time

-        spent in the graphics library?

-

-    RESOLVED:  This extension will measure the total time elapsed between

-    the full completion of these commands.  Future extensions may implement

-    a query to determine time elapsed at different stages of the graphics

-    pipeline.

-

-    (6) If multiple query types are supported, can multiple query types be

-        active simultaneously?

-

-    RESOLVED:  Yes; an application may perform a timer query and another

-    type of query simultaneously.  An application can not perform multiple

-    timer queries or multiple queries of other types simultaneously.  An

-    application also can not use the same query object for another query

-    and a timer query simultaneously.

-

-    (7) Do query objects have a query type permanently associated with them?

-

-    RESOLVED:  No.  A single query object can be used to perform different

-    types of queries, but not at the same time.

-

-    Having a fixed type for each query object simplifies some aspects of the

-    implementation -- not having to deal with queries with different result

-    sizes, for example.  It would also mean that BeginQuery() with a query

-    object of the "wrong" type would result in an INVALID_OPERATION error.

-

-    UPDATE: This resolution was relevant for EXT_timer_query and OpenGL 2.0.

-    Since EXT_transform_feedback has since been incorporated into the core,

-    the resolution is that BeginQuery will generate error INVALID_OPERATION

-    if <id> represents a query object of a different type.

-

-    (8) How predictable/repeatable are the results returned by the timer

-        query?

-

-    RESOLVED:  In general, the amount of time needed to render the same

-    primitives should be fairly constant.  But there may be many other

-    system issues (e.g., context switching on the CPU and GPU, virtual

-    memory page faults, memory cache behavior on the CPU and GPU) that can

-    cause times to vary wildly.

-

-    Note that modern GPUs are generally highly pipelined, and may be

-    processing different primitives in different pipeline stages

-    simultaneously.  In this extension, the timers start and stop when the

-    BeginQuery/EndQuery commands reach the bottom of the rendering pipeline.

-    What that means is that by the time the timer starts, the GL driver on

-    the CPU may have started work on GL commands issued after BeginQuery,

-    and the higher pipeline stages (e.g., vertex transformation) may have

-    started as well.

-

-   (9) What should the new 64 bit integer type be called?

-

-    RESOLVED: The new types will be called GLint64ANGLE/GLuint64ANGLE.  The new

-    command suffixes will be i64 and ui64.  These names clearly convey the

-    minimum size of the types.  These types are similar to the C99 standard

-    type int_least64_t, but we use names similar to the C99 optional type

-    int64_t for simplicity.

-

-Issues from ARB_timer_query

-

-   (10) What about tile-based implementations? The effects of a command are

-        not complete until the frame is completely rendered. Timing recorded

-        before the frame is complete may not be what developers expect. Also

-        the amount of time needed to render the same primitives is not

-        consistent, which conflicts with issue (8) above. The time depends on

-        how early or late in the scene it is placed.

-

-    RESOLVED: The current language supports tile-based rendering okay as it

-    is written. Developers are warned that using timers on tile-based

-    implementation may not produce results they expect since rendering is not

-    done in a linear order. Timing results are calculated when the frame is

-    completed and may depend on how early or late in the scene it is placed.

-    

-   (11) Can the GL implementation use different clocks to implement the

-        TIME_ELAPSED and TIMESTAMP queries?

-

-   RESOLVED: Yes, the implemenation can use different internal clocks to

-   implement TIME_ELAPSED and TIMESTAMP. If different clocks are

-   used it is possible there is a slight discrepancy when comparing queries

-   made from TIME_ELAPSED and TIMESTAMP; they may have slight

-   differences when both are used to measure the same sequence. However, this

-   is unlikely to affect real applications since comparing the two queries is

-   not expected to be useful.

-

-Issues

-

-    (12) What should we call this extension?

-

-    RESOLVED: ANGLE_timer_query

-

-    (13) Why is this done as a separate extension instead of just supporting

-         ARB_timer_query?

-

-    ARB_timer_query is written against OpenGL 3.2, which includes a lot of

-    the required support for dealing with query objects. None of these

-    functions or tokens exist in OpenGL ES, and as such have to be added in

-    this specification.

-

-    (14) How does this extension differ from ARB_timer_query?

-

-    This extension contains most ARB_timer_query behavior unchanged as well

-    as a subset of the query support required to use it from the core

-    OpenGL 3.2 spec. It omits the glGetInteger(TIMESTAMP) functionality used to

-    query the current time on the GPU, but the behavior for all remaining

-    functionality taken from ARB_timer_query is the same.

-    

-    (15) Are query objects shareable between multiple contexts?

-

-    RESOLVED: No.  Query objects are lightweight and we normally share 

-    large data across contexts.  Also, being able to share query objects

-    across contexts is not particularly useful.  In order to do the async 

-    query across contexts, a query on one context would have to be finished 

-    before the other context could query it. 

-

-Revision History

-

-    Revision 1, 2011/04/28

-      - copied from revision 9 of ARB_timer_query and revision 7 of

-        ARB_occlusion_query

-      - removed language that was clearly not relevant to ES2

-      - rebased changes against the OpenGL ES 2.0 specification

+Name
+
+    ANGLE_timer_query
+
+Name Strings
+
+    GL_ANGLE_timer_query
+
+Contributors
+
+    Contributors to ARB_occlusion_query
+    Contributors to EXT_timer_query
+    Contributors to ARB_timer_query
+    Ben Vanik, Google Inc.
+    Daniel Koch, TransGaming Inc.
+
+Contact
+
+    Ben Vanik, Google Inc. (benvanik 'at' google 'dot' com)
+
+Status
+
+    Draft
+
+Version
+
+    Last Modified Date: Apr 28, 2011
+    Author Revision: 1
+
+Number
+
+    OpenGL ES Extension #??
+
+Dependencies
+
+    OpenGL ES 2.0 is required.
+
+    The extension is written against the OpenGL ES 2.0 specification.
+
+Overview
+
+    Applications can benefit from accurate timing information in a number of
+    different ways.  During application development, timing information can
+    help identify application or driver bottlenecks.  At run time,
+    applications can use timing information to dynamically adjust the amount
+    of detail in a scene to achieve constant frame rates.  OpenGL
+    implementations have historically provided little to no useful timing
+    information.  Applications can get some idea of timing by reading timers
+    on the CPU, but these timers are not synchronized with the graphics
+    rendering pipeline.  Reading a CPU timer does not guarantee the completion
+    of a potentially large amount of graphics work accumulated before the
+    timer is read, and will thus produce wildly inaccurate results.
+    glFinish() can be used to determine when previous rendering commands have
+    been completed, but will idle the graphics pipeline and adversely affect
+    application performance.
+
+    This extension provides a query mechanism that can be used to determine
+    the amount of time it takes to fully complete a set of GL commands, and
+    without stalling the rendering pipeline.  It uses the query object
+    mechanisms first introduced in the occlusion query extension, which allow
+    time intervals to be polled asynchronously by the application.
+
+IP Status
+
+    No known IP claims.
+
+New Procedures and Functions
+
+    void GenQueriesANGLE(sizei n, uint *ids);
+    void DeleteQueriesANGLE(sizei n, const uint *ids);
+    boolean IsQueryANGLE(uint id);
+    void BeginQueryANGLE(enum target, uint id);
+    void EndQueryANGLE(enum target);
+    void QueryCounterANGLE(uint id, enum target);
+    void GetQueryivANGLE(enum target, enum pname, int *params);
+    void GetQueryObjectivANGLE(uint id, enum pname, int *params);
+    void GetQueryObjectuivANGLE(uint id, enum pname, uint *params);
+    void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params);
+    void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params);
+
+New Tokens
+
+    Accepted by the <pname> parameter of GetQueryivANGLE:
+
+        QUERY_COUNTER_BITS_ANGLE                       0x8864
+        CURRENT_QUERY_ANGLE                            0x8865
+
+    Accepted by the <pname> parameter of GetQueryObjectivANGLE,
+    GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, and
+    GetQueryObjectui64vANGLE:
+
+        QUERY_RESULT_ANGLE                             0x8866
+        QUERY_RESULT_AVAILABLE_ANGLE                   0x8867
+        
+    Accepted by the <target> parameter of BeginQueryANGLE, EndQueryANGLE, and
+    GetQueryivANGLE:
+
+        TIME_ELAPSED_ANGLE                             0x88BF
+
+    Accepted by the <target> parameter of GetQueryivANGLE and
+    QueryCounterANGLE:
+
+        TIMESTAMP_ANGLE                                0x8E28
+
+Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)
+
+    (Modify table 2.1, Correspondence of command suffix letters to GL argument)
+    Add two new types:
+    
+    Letter Corresponding GL Type
+    ------ ---------------------
+    i64    int64ANGLE
+    ui64   uint64ANGLE
+
+    (Modify table 2.2, GL data types) Add two new types:
+    
+    GL Type       Minimum Bit Width   Description
+    -------       -----------------   -----------------------------
+    int64ANGLE    64                  Signed 2's complement integer
+    uint64ANGLE   64                  Unsigned binary integer
+
+Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
+
+    Add a new section 5.3 "Timer Queries":
+
+    "5.3  Timer Queries
+
+    Timer queries use query objects to track the amount of time needed to
+    fully complete a set of GL commands, or to determine the current time
+    of the GL.
+    
+    Timer queries are associated with query objects.  The command
+
+      void GenQueriesANGLE(sizei n, uint *ids);
+
+    returns <n> previously unused query object names in <ids>.  These
+    names are marked as used, but no object is associated with them until
+    the first time they are used by BeginQueryANGLE.  Query objects contain
+    one piece of state, an integer result value.  This result value is
+    initialized to zero when the object is created.  Any positive integer
+    except for zero (which is reserved for the GL) is a valid query
+    object name.
+
+    Query objects are deleted by calling
+
+      void DeleteQueriesANGLE(sizei n, const uint *ids);
+
+    <ids> contains <n> names of query objects to be deleted.  After a
+    query object is deleted, its name is again unused.  Unused names in
+    <ids> are silently ignored.
+    If an active query object is deleted its name immediately becomes unused,
+    but the underlying object is not deleted until it is no longer active.
+
+    A timer query can be started and finished by calling
+
+      void BeginQueryANGLE(enum target, uint id);
+      void EndQueryANGLE(enum target);
+
+    where <target> is TIME_ELAPSED_ANGLE.  If BeginQueryANGLE is called
+    with an unused <id>, that name is marked as used and associated with
+    a new query object.
+    
+    If BeginQueryANGLE is called with an <id> of zero, if the active query
+    object name for <target> is non-zero, if <id> is the name of an existing
+    query object whose type does not match <target>, or if <id> is the active
+    query object name for any query type, the error INVALID_OPERATION is
+    generated.  If EndQueryANGLE is called while no query with the same target
+    is in progress, an INVALID_OPERATION error is generated.
+
+    When BeginQueryANGLE and EndQueryANGLE are called with a <target> of
+    TIME_ELAPSED_ANGLE, the GL prepares to start and stop the timer used for
+    timer queries.  The timer is started or stopped when the effects from all
+    previous commands on the GL client and server state and the framebuffer
+    have been fully realized.  The BeginQueryANGLE and EndQueryANGLE commands
+    may return before the timer is actually started or stopped.  When the timer
+    query timer is finally stopped, the elapsed time (in nanoseconds) is
+    written to the corresponding query object as the query result value, and
+    the query result for that object is marked as available.
+
+    If the elapsed time overflows the number of bits, <n>, available to hold
+    elapsed time, its value becomes undefined.  It is recommended, but not
+    required, that implementations handle this overflow case by saturating at
+    2^n - 1.
+
+    The necessary state is a single bit indicating whether an timer
+    query is active, the identifier of the currently active timer
+    query, and a counter keeping track of the time that has passed.
+
+    When the command
+
+         void QueryCounterANGLE(uint id, enum target);
+
+    is called with <target> TIMESTAMP_ANGLE, the GL records the current time
+    into the corresponding query object. The time is recorded after all
+    previous commands on the GL client and server state and the framebuffer
+    have been fully realized. When the time is recorded, the query result for
+    that object is marked available. QueryCounterANGLE timer queries can be
+    used within a BeginQueryANGLE / EndQueryANGLE block where the <target> is
+    TIME_ELAPSED_ANGLE and it does not affect the result of that query object.
+    The error INVALID_OPERATION is generated if the <id> is already in use
+    within a BeginQueryANGLE/EndQueryANGLE block."
+
+Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
+Requests)
+
+    Add a new section 6.1.9 "Timer Queries":
+
+    "The command
+
+      boolean IsQueryANGLE(uint id);
+
+    returns TRUE if <id> is the name of a query object.  If <id> is zero,
+    or if <id> is a non-zero value that is not the name of a query
+    object, IsQueryANGLE returns FALSE.
+
+    Information about a query target can be queried with the command
+
+      void GetQueryivANGLE(enum target, enum pname, int *params);
+
+    <target> identifies the query target and can be TIME_ELAPSED_ANGLE or
+    TIMESTAMP_ANGLE for timer queries.
+
+    If <pname> is CURRENT_QUERY_ANGLE, the name of the currently active query
+    for <target>, or zero if no query is active, will be placed in <params>.
+
+    If <pname> is QUERY_COUNTER_BITS_ANGLE, the implementation-dependent number
+    of bits used to hold the query result for <target> will be placed in
+    <params>.  The number of query counter bits may be zero, in which case
+    the counter contains no useful information.
+
+    For timer queries (TIME_ELAPSED_ANGLE and TIMESTAMP_ANGLE), if the number
+    of bits is non-zero, the minimum number of bits allowed is 30 which
+    will allow at least 1 second of timing.
+
+    The state of a query object can be queried with the commands
+
+      void GetQueryObjectivANGLE(uint id, enum pname, int *params);
+      void GetQueryObjectuivANGLE(uint id, enum pname, uint *params);
+      void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params);
+      void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params);
+
+    If <id> is not the name of a query object, or if the query object
+    named by <id> is currently active, then an INVALID_OPERATION error is
+    generated.
+
+    If <pname> is QUERY_RESULT_ANGLE, then the query object's result
+    value is returned as a single integer in <params>. If the value is so
+    large in magnitude that it cannot be represented with the requested type,
+    then the nearest value representable using the requested type is
+    returned. If the number of query counter bits for target is zero, then
+    the result is returned as a single integer with the value zero.
+    
+    There may be an indeterminate delay before the above query returns. If
+    <pname> is QUERY_RESULT_AVAILABLE_ANGLE, FALSE is returned if such a delay
+    would be required; otherwise TRUE is returned. It must always be true
+    that if any query object returns a result available of TRUE, all queries
+    of the same type issued prior to that query must also return TRUE.
+
+    Querying the state for a given timer query forces that timer query to
+    complete within a finite amount of time.
+
+    If multiple queries are issued on the same target and id prior to 
+    calling GetQueryObject[u]i[64]vANGLE, the result returned will always be
+    from the last query issued.  The results from any queries before the
+    last one will be lost if the results are not retrieved before starting
+    a new query on the same <target> and <id>."
+
+Errors
+
+    The error INVALID_VALUE is generated if GenQueriesANGLE is called where
+    <n> is negative.
+
+    The error INVALID_VALUE is generated if DeleteQueriesANGLE is called
+    where <n> is negative.
+
+    The error INVALID_OPERATION is generated if BeginQueryANGLE is called
+    when a query of the given <target> is already active.
+
+    The error INVALID_OPERATION is generated if EndQueryANGLE is called
+    when a query of the given <target> is not active.
+
+    The error INVALID_OPERATION is generated if BeginQueryANGLE is called
+    where <id> is zero.
+
+    The error INVALID_OPERATION is generated if BeginQueryANGLE is called
+    where <id> is the name of a query currently in progress.
+    
+    The error INVALID_OPERATION is generated if BeginQueryANGLE is called
+    where <id> is the name of an existing query object whose type does not
+    match <target>.
+
+    The error INVALID_ENUM is generated if BeginQueryANGLE or EndQueryANGLE
+    is called where <target> is not TIME_ELAPSED_ANGLE.
+
+    The error INVALID_ENUM is generated if GetQueryivANGLE is called where
+    <target> is not TIME_ELAPSED_ANGLE or TIMESTAMP_ANGLE.
+
+    The error INVALID_ENUM is generated if GetQueryivANGLE is called where
+    <pname> is not QUERY_COUNTER_BITS_ANGLE or CURRENT_QUERY_ANGLE.
+
+    The error INVALID_ENUM is generated if QueryCounterANGLE is called where
+    <target> is not TIMESTAMP_ANGLE.
+
+    The error INVALID_OPERATION is generated if QueryCounterANGLE is called
+    on a query object that is already in use inside a
+    BeginQueryANGLE/EndQueryANGLE.
+
+    The error INVALID_OPERATION is generated if GetQueryObjectivANGLE,
+    GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or
+    GetQueryObjectui64vANGLE is called where <id> is not the name of a query
+    object.
+
+    The error INVALID_OPERATION is generated if GetQueryObjectivANGLE,
+    GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or
+    GetQueryObjectui64vANGLE is called where <id> is the name of a currently
+    active query object.
+
+    The error INVALID_ENUM is generated if GetQueryObjectivANGLE,
+    GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or
+    GetQueryObjectui64vANGLE is called where <pname> is not
+    QUERY_RESULT_ANGLE or QUERY_RESULT_AVAILABLE_ANGLE.
+
+New State
+
+    (Add a new table 6.xx, "Query Operations")
+    
+    Get Value                      Type    Get Command              Initial Value   Description              Sec
+    ---------                      ----    -----------              -------------   -----------              ------
+    -                              B       -                        FALSE           query active             5.3
+    CURRENT_QUERY_ANGLE            Z+      GetQueryivANGLE          0               active query ID          5.3
+    QUERY_RESULT_ANGLE             Z+      GetQueryObjectuivANGLE,  0               samples-passed count     5.3
+                                           GetQueryObjectui64vANGLE
+    QUERY_RESULT_AVAILABLE_ANGLE   B       GetQueryObjectivANGLE    FALSE           query result available   5.3
+
+New Implementation Dependent State
+
+    (Add the following entry to table 6.18):
+
+    Get Value                      Type    Get Command      Minimum Value      Description           Sec
+    --------------------------     ----    -----------      -------------      ----------------      ------
+    QUERY_COUNTER_BITS_ANGLE       Z+      GetQueryivANGLE  see 6.1.9          Number of bits in     6.1.9
+                                                                               query counter
+
+Examples
+
+    (1) Here is some rough sample code that demonstrates the intended usage
+        of this extension.
+
+        GLint queries[N];
+        GLint available = 0;
+        // timer queries can contain more than 32 bits of data, so always
+        // query them using the 64 bit types to avoid overflow
+        GLuint64ANGLE timeElapsed = 0;
+
+        // Create a query object.
+        glGenQueriesANGLE(N, queries);
+
+        // Start query 1
+        glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[0]);
+
+        // Draw object 1
+        ....
+
+        // End query 1
+        glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE);
+
+        ...
+
+        // Start query N
+        glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[N-1]);
+
+        // Draw object N
+        ....
+
+        // End query N
+        glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE);
+
+        // Wait for all results to become available
+        while (!available) {
+            glGetQueryObjectivANGLE(queries[N-1], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available);
+        }
+
+        for (i = 0; i < N; i++) {
+            // See how much time the rendering of object i took in nanoseconds.
+            glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeElapsed);
+
+            // Do something useful with the time.  Note that care should be
+            // taken to use all significant bits of the result, not just the
+            // least significant 32 bits.
+            AdjustObjectLODBasedOnDrawTime(i, timeElapsed);
+        }
+
+        This example is sub-optimal in that it stalls at the end of every
+        frame to wait for query results.  Ideally, the collection of results
+        would be delayed one frame to minimize the amount of time spent
+        waiting for the GPU to finish rendering.
+        
+    (2) This example is basically the same as the example above but uses
+        QueryCounter instead.
+    
+        GLint queries[N+1];
+        GLint available = 0;
+        // timer queries can contain more than 32 bits of data, so always
+        // query them using the 64 bit types to avoid overflow
+        GLuint64ANGLE timeStart, timeEnd, timeElapsed = 0;
+
+        // Create a query object.
+        glGenQueriesANGLE(N+1, queries);
+
+        // Query current timestamp 1
+        glQueryCounterANGLE(queries[0], GL_TIMESTAMP_ANGLE);
+
+        // Draw object 1
+        ....
+
+        // Query current timestamp N
+        glQueryCounterANGLE(queries[N-1], GL_TIMESTAMP_ANGLE);
+
+        // Draw object N
+        ....
+
+        // Query current timestamp N+1
+        glQueryCounterANGLE(queries[N], GL_TIMESTAMP_ANGLE);
+
+        // Wait for all results to become available
+        while (!available) {
+            glGetQueryObjectivANGLE(queries[N], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available);
+        }
+
+        for (i = 0; i < N; i++) {
+            // See how much time the rendering of object i took in nanoseconds.
+            glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeStart);
+            glGetQueryObjectui64vANGLE(queries[i+1], GL_QUERY_RESULT_ANGLE, &timeEnd);
+            timeElapsed = timeEnd - timeStart;
+
+            // Do something useful with the time.  Note that care should be
+            // taken to use all significant bits of the result, not just the
+            // least significant 32 bits.
+            AdjustObjectLODBasedOnDrawTime(i, timeElapsed);
+        }
+
+Issues from EXT_timer_query
+
+    (1) What time interval is being measured?
+
+    RESOLVED:  The timer starts when all commands prior to BeginQuery() have
+    been fully executed.  At that point, everything that should be drawn by
+    those commands has been written to the framebuffer.  The timer stops
+    when all commands prior to EndQuery() have been fully executed.
+
+    (2) What unit of time will time intervals be returned in?
+
+    RESOLVED:  Nanoseconds (10^-9 seconds).  This unit of measurement allows
+    for reasonably accurate timing of even small blocks of rendering
+    commands.  The granularity of the timer is implementation-dependent.  A
+    32-bit query counter can express intervals of up to approximately 4
+    seconds.
+
+    (3) What should be the minimum number of counter bits for timer queries?
+
+    RESOLVED:  30 bits, which will allow timing sections that take up to 1
+    second to render.
+
+    (4) How are counter results of more than 32 bits returned?
+
+    RESOLVED:  Via two new datatypes, int64ANGLE and uint64ANGLE, and their
+    corresponding GetQueryObject entry points.  These types hold integer
+    values and have a minimum bit width of 64.
+
+    (5) Should the extension measure total time elapsed between the full
+        completion of the BeginQuery and EndQuery commands, or just time
+        spent in the graphics library?
+
+    RESOLVED:  This extension will measure the total time elapsed between
+    the full completion of these commands.  Future extensions may implement
+    a query to determine time elapsed at different stages of the graphics
+    pipeline.
+
+    (6) If multiple query types are supported, can multiple query types be
+        active simultaneously?
+
+    RESOLVED:  Yes; an application may perform a timer query and another
+    type of query simultaneously.  An application can not perform multiple
+    timer queries or multiple queries of other types simultaneously.  An
+    application also can not use the same query object for another query
+    and a timer query simultaneously.
+
+    (7) Do query objects have a query type permanently associated with them?
+
+    RESOLVED:  No.  A single query object can be used to perform different
+    types of queries, but not at the same time.
+
+    Having a fixed type for each query object simplifies some aspects of the
+    implementation -- not having to deal with queries with different result
+    sizes, for example.  It would also mean that BeginQuery() with a query
+    object of the "wrong" type would result in an INVALID_OPERATION error.
+
+    UPDATE: This resolution was relevant for EXT_timer_query and OpenGL 2.0.
+    Since EXT_transform_feedback has since been incorporated into the core,
+    the resolution is that BeginQuery will generate error INVALID_OPERATION
+    if <id> represents a query object of a different type.
+
+    (8) How predictable/repeatable are the results returned by the timer
+        query?
+
+    RESOLVED:  In general, the amount of time needed to render the same
+    primitives should be fairly constant.  But there may be many other
+    system issues (e.g., context switching on the CPU and GPU, virtual
+    memory page faults, memory cache behavior on the CPU and GPU) that can
+    cause times to vary wildly.
+
+    Note that modern GPUs are generally highly pipelined, and may be
+    processing different primitives in different pipeline stages
+    simultaneously.  In this extension, the timers start and stop when the
+    BeginQuery/EndQuery commands reach the bottom of the rendering pipeline.
+    What that means is that by the time the timer starts, the GL driver on
+    the CPU may have started work on GL commands issued after BeginQuery,
+    and the higher pipeline stages (e.g., vertex transformation) may have
+    started as well.
+
+   (9) What should the new 64 bit integer type be called?
+
+    RESOLVED: The new types will be called GLint64ANGLE/GLuint64ANGLE.  The new
+    command suffixes will be i64 and ui64.  These names clearly convey the
+    minimum size of the types.  These types are similar to the C99 standard
+    type int_least64_t, but we use names similar to the C99 optional type
+    int64_t for simplicity.
+
+Issues from ARB_timer_query
+
+   (10) What about tile-based implementations? The effects of a command are
+        not complete until the frame is completely rendered. Timing recorded
+        before the frame is complete may not be what developers expect. Also
+        the amount of time needed to render the same primitives is not
+        consistent, which conflicts with issue (8) above. The time depends on
+        how early or late in the scene it is placed.
+
+    RESOLVED: The current language supports tile-based rendering okay as it
+    is written. Developers are warned that using timers on tile-based
+    implementation may not produce results they expect since rendering is not
+    done in a linear order. Timing results are calculated when the frame is
+    completed and may depend on how early or late in the scene it is placed.
+    
+   (11) Can the GL implementation use different clocks to implement the
+        TIME_ELAPSED and TIMESTAMP queries?
+
+   RESOLVED: Yes, the implemenation can use different internal clocks to
+   implement TIME_ELAPSED and TIMESTAMP. If different clocks are
+   used it is possible there is a slight discrepancy when comparing queries
+   made from TIME_ELAPSED and TIMESTAMP; they may have slight
+   differences when both are used to measure the same sequence. However, this
+   is unlikely to affect real applications since comparing the two queries is
+   not expected to be useful.
+
+Issues
+
+    (12) What should we call this extension?
+
+    RESOLVED: ANGLE_timer_query
+
+    (13) Why is this done as a separate extension instead of just supporting
+         ARB_timer_query?
+
+    ARB_timer_query is written against OpenGL 3.2, which includes a lot of
+    the required support for dealing with query objects. None of these
+    functions or tokens exist in OpenGL ES, and as such have to be added in
+    this specification.
+
+    (14) How does this extension differ from ARB_timer_query?
+
+    This extension contains most ARB_timer_query behavior unchanged as well
+    as a subset of the query support required to use it from the core
+    OpenGL 3.2 spec. It omits the glGetInteger(TIMESTAMP) functionality used to
+    query the current time on the GPU, but the behavior for all remaining
+    functionality taken from ARB_timer_query is the same.
+    
+    (15) Are query objects shareable between multiple contexts?
+
+    RESOLVED: No.  Query objects are lightweight and we normally share 
+    large data across contexts.  Also, being able to share query objects
+    across contexts is not particularly useful.  In order to do the async 
+    query across contexts, a query on one context would have to be finished 
+    before the other context could query it. 
+
+Revision History
+
+    Revision 1, 2011/04/28
+      - copied from revision 9 of ARB_timer_query and revision 7 of
+        ARB_occlusion_query
+      - removed language that was clearly not relevant to ES2
+      - rebased changes against the OpenGL ES 2.0 specification
diff --git a/src/third_party/angle/extensions/ANGLE_webgl_compatibility.txt b/src/third_party/angle/extensions/ANGLE_webgl_compatibility.txt
new file mode 100644
index 0000000..cc01313
--- /dev/null
+++ b/src/third_party/angle/extensions/ANGLE_webgl_compatibility.txt
@@ -0,0 +1,81 @@
+Name
+
+    ANGLE_webgl_compatibility
+
+Name Strings
+
+    GL_ANGLE_webgl_compatibility
+
+Contributors
+
+    Geoff Lang
+
+Contact
+
+    Geoff Lang (geofflang 'at' google.com)
+
+Notice
+
+    Copyright (c) 2016 The Khronos Group Inc. Copyright terms at
+        http://www.khronos.org/registry/speccopyright.html
+
+Status
+
+    Draft
+
+Version
+
+    Version 2, November 28, 2016
+
+Number
+
+    OpenGL ES Extension #??
+
+Dependencies
+
+    Requires OpenGL ES 2.0
+
+    Written against the OpenGL ES 2.0 specification.
+
+    Interacts with EGL_ANGLE_create_context_webgl_compatibility (or equivalent)
+    extension.
+
+Overview
+
+    With this extension enabled, the OpenGL ES context will have additional
+    features and validation to be compatible with the WebGL specification.
+
+New Procedures and Functions
+
+    None
+
+
+New Tokens
+
+    None
+
+Additions to the OpenGL ES Specification
+
+    Additional validation will be performed according to the the sections of
+    the WebGL specification entitled "Differences Between WebGL and OpenGL ES
+    2.0" and "Differences Between WebGL and OpenGL ES 3.0".
+
+New State
+
+    None
+
+Conformance Tests
+
+    TBD
+
+Issues
+
+    None
+
+Revision History
+
+    Rev.    Date         Author     Changes
+    ----  -------------  ---------  ----------------------------------------
+      1   Sept 16, 2016  geofflang  Initial version
+      2    Nov 28, 2016  geofflang  Break the extension requests into a
+                                    separate extension.
diff --git a/src/third_party/angle/extensions/CHROMIUM_bind_generates_resource.txt b/src/third_party/angle/extensions/CHROMIUM_bind_generates_resource.txt
new file mode 100644
index 0000000..498acad
--- /dev/null
+++ b/src/third_party/angle/extensions/CHROMIUM_bind_generates_resource.txt
@@ -0,0 +1,118 @@
+Name
+
+    CHROMIUM_bind_generates_resource
+
+Name Strings
+
+    GL_CHROMIUM_bind_generates_resource
+
+Contributors
+
+    Geoff Lang
+
+Contact
+
+    Geoff Lang (geofflang 'at' google.com)
+
+Notice
+
+    Copyright (c) 2016 The Khronos Group Inc. Copyright terms at
+        http://www.khronos.org/registry/speccopyright.html
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, September 19, 2016
+
+Number
+
+    OpenGL ES Extension #??
+
+Dependencies
+
+    Requires OpenGL ES 2.0
+
+    Written against the OpenGL ES 2.0 specification.
+
+Overview
+
+    This extension allows the user to control the behaviour when binding an
+    object that has not been generated.  This functionality is useful to
+    notify the user of potential use-after-free errors or support other APIs
+    such as WebGL on top of an OpenGL ES context.
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted by the <cap> parameter to IsEnabled and the <pname> parameter to
+    GetBooleanv, GetIntegerv, GetFloatv, and GetInteger64v:
+
+    BIND_GENERATES_RESOURCE_CHROMIUM            0x9244
+
+Additions to the OpenGL ES Specification
+
+    Add to the end of Section 2.9 "Buffer Objects":
+
+    If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindBuffer fails and an
+    INVALID_OPERATION error is generated if buffer is not zero or a name
+    returned from a previous call to GenBuffers, or if such a name has since
+    been deleted with DeleteBuffers.
+
+    Add to the end of Section 3.7.13 "Texture Objects":
+
+    If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindTexture fails and an
+    INVALID_OPERATION error is generated if texture is not zero or a name
+    returned from a previous call to GenTextures, or if such a name has since
+    been deleted with DeleteTextures.
+
+    Add to the end of Section 4.4.1 "Binding and Managing Framebuffer Objects":
+
+    If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindFramebuffer fails and an
+    INVALID_OPERATION error is generated if framebuffer is not zero or a name
+    returned from a previous call to GenFramebuffers, or if such a name has
+    since been deleted with DeleteFramebuffers.
+
+    Add to the end of Section 4.4.3 "Renderbuffer Objects":
+
+    If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindRenderbuffer fails and an
+    INVALID_OPERATION error is generated if renderbuffer is not zero or a name
+    returned from a previous call to GenRenderbuffers, or if such a name has
+    since been deleted with DeleteRenderbuffers.
+
+New State
+
+    Modify Table 6.22, Miscellaneous
+
+    Add:
+
+                                                      Initial
+    Get Value                        Type Get Command Value   Description
+    -----------------------          ---- ----------- ------- --------------
+    BIND_GENERATES_RESOURCE_CHROMIUM B    IsEnabled   TRUE    Bind generates
+                                                              new resources
+
+Conformance Tests
+
+    TBD
+
+Issues
+
+    (1) Should the BIND_GENERATES_RESOURCE_CHROMIUM state be enabled at context
+        creation time or dynamically through the Enable and Disable functions?
+
+    RESOLOVED: BIND_GENERATES_RESOURCE_CHROMIUM is initialized by a context
+    creation attribute and cannot be modified.  One of the major use cases of
+    this extension is to back WebGL contexts and the end user should not be
+    allowed to modify this state.
+
+Revision History
+
+    Rev.    Date         Author     Changes
+    ----  -------------  ---------  ----------------------------------------
+      1   Sept 19, 2016  geofflang  Initial version
diff --git a/src/third_party/angle/extensions/CHROMIUM_bind_uniform_location.txt b/src/third_party/angle/extensions/CHROMIUM_bind_uniform_location.txt
new file mode 100644
index 0000000..b08c4c6
--- /dev/null
+++ b/src/third_party/angle/extensions/CHROMIUM_bind_uniform_location.txt
@@ -0,0 +1,141 @@
+Name
+
+    CHROMIUM_bind_uniform_location
+
+Name Strings
+
+    GL_CHROMIUM_bind_uniform_location
+
+Version
+
+    Last Modifed Date: September 8, 2015
+
+Dependencies
+
+    OpenGL ES 2.0 is required.
+
+Overview
+
+    This extension is simlar to glBindAttribLocation but instead
+    lets you choose a location for a uniform. This allows you
+    to not have to query the locations of uniforms.
+
+    This allows the client program to know the locations of uniforms
+    without having to wait for shaders to compile or GLSL programs to
+    link to query the locations and therefore have no blocking calls
+    when initializing programs.
+
+Issues
+
+    If a uniform is an array you can only call glBindUniformLocation
+    for the location of the first element. Other elements' locations
+    must be queried if you need them. Often this is not an issue
+    because you can set all the elements with a single gl call from
+    the first location.
+
+    Good Example:
+
+        --shader--
+        uniform float u_someArray[4];
+
+        --C--
+        GLint location = 123;
+        glBindUniformLocation(program, location, "u_someArray");
+        glLinkProgram(program);
+        glUseProgram(program);
+
+        // set all 4 floats in u_someArray
+        float values[] = { 0.1f, 0.2f, 0.3f, 0.4f, };
+        glUniform1fv(location, 4, values);
+
+    Bad example 1:
+
+        GLint location = 123;
+        glBindUniformLocation(program, location, "u_someArray");
+        glLinkProgram(program);
+        glUseProgram(program);
+
+        // set floats in u_someArray one at a time
+        glUniform1f(location, 0.1f);
+        glUniform1f(location + 1, 0.2f);  // ERROR! math not allowed on locations
+
+    Bad example 2:
+
+        GLint location0 = 123;
+        GLint location1 = 124;
+        glBindUniformLocation(program, location0, "u_someArray[0]");
+        glBindUniformLocation(program, location1, "u_someArray[1]"); // ERROR!
+        // not allowed to assign locations to array elements
+
+    If you need to set individual elements of a uniform array you must query the
+    location of the each element you wish to set.
+
+    If a uniform has its location explicitly set within the shader text and a
+    different location set via the API, the assignment in the shader text is
+    used.
+
+    If the location of a statically used uniform set via the API conflicts with
+    the location of a different uniform set in the shader text, linking must
+    fail.
+
+New Tokens
+
+    None
+
+New Procedures and Functions
+
+    void BindUniformLocationCHROMIUM (GLuint program, GLint location,
+                                      const GLhchar* name);
+
+    specifes that the uniform variable named <name> in program <program>
+    should be bound to uniform location <location> when the program is next
+    linked.  If <name> was bound previously, its assigned binding is replaced
+    with <location>. <name> must be a null terminated string.  The error
+    INVALID_VALUE is generated if <location> is equal or greater than
+
+    (MAX_VERTEX_UNIFORM_VECTORS + MAX_FRAGMENT_UNIFORM_VECTORS) * 4
+
+    or less than 0. BindUniformLocation has no effect until the program is
+    linked. In particular, it doesn't modify the bindings of active uniforms
+    variables in a program that has already been linked.
+
+    The error INVALID_OPERATION is generated if name starts with the reserved
+    "gl_" prefix. The error INVALID_VALUE is generated if name ends with
+    an array element expression other than "[0]".
+
+    When a program is linked, any active uniforms without a binding specified
+    through BindUniformLocation will be automatically be bound to locations by
+    the GL.  Such bindings can be queried using the command
+    GetUniformLocation.
+
+    BindUniformLocation may be issued before any shader objects are attached
+    to a program object.  Hence it is allowed to bind any name (except a name
+    starting with "gl_") to an index, including a name that is never used as a
+    uniform in any shader object.  Assigned bindings for uniform variables
+    that do not exist or are not active are ignored. Using such bindings
+    behaves as if passed location was -1.
+
+    It is possible for an application to bind more than one uniform name to
+    the same location.  This is referred to as aliasing.  This will only work
+    if only one of the aliased uniforms is active in the executable program,
+    or if no path through the shader consumes more than one uniform of a set
+    of uniforms aliased to the same location.  If two statically used uniforms
+    in a program are bound to the name location, link must fail.
+
+Errors
+
+    None.
+
+New State
+
+    None.
+
+Revision History
+
+    7/20/2012    Documented the extension
+    9/8/2015     Require program link to fail if two statically used uniforms
+                 are bound to the same location.
+    11/6/2015    Require inactive and non-existing, bound uniform locations
+                 to behave like location -1.
+    3/9/2017     Locations set in the shader override ones set by the binding
+                 API.
diff --git a/src/third_party/angle/extensions/CHROMIUM_compressed_copy_texture.txt b/src/third_party/angle/extensions/CHROMIUM_compressed_copy_texture.txt
new file mode 100644
index 0000000..a2cfb2c
--- /dev/null
+++ b/src/third_party/angle/extensions/CHROMIUM_compressed_copy_texture.txt
@@ -0,0 +1,88 @@
+Name
+
+    CHROMIUM_copy_compressed_texture
+
+Name Strings
+
+    GL_CHROMIUM_copy_compressed_texture
+
+Version
+
+    Last Modifed Date: August 5, 2015
+
+Dependencies
+
+    OpenGL ES 2.0 is required.
+
+    GL_AMD_compressed_ATC_texture, GL_ATI_texture_compression_atitc,
+    GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt5,
+    GL_EXT_texture_compression_s3tc and GL_OES_compressed_ETC1_RGB8_texture
+    affects the definition of this extension.
+
+Overview
+
+    This extension provides functionality for copying compressed textures. It
+    adds a new function glCompressedCopyTextureCHROMIUM that works similarily
+    to glCopyTextureCHROMIUM, but for compressed textures.
+
+    Which compressed texture formats that this extension supports depends on
+    the supported texture compression formats of the host GPU.
+
+Issues
+
+    glCompressedCopyTextureCHROMIUM will first try to copy into a compressed
+    texture of the same format as the source texture. If unsucessful, the
+    destination texture format will be changed to GL_RGBA and the texture will
+    be stored uncompressed.
+
+New Procedures and Functions
+
+    The command
+
+        void glCompressedCopyTextureCHROMIUM (GLuint source_id, GLuint dest_id)
+
+    Copies the contents of a compressed texture referred to by <source_id> to
+    <dest_id> texture.
+
+    Texture level 0 is copied from the source image to level 0 of the
+    destination texture.
+
+    The internal format of the source texture must be one of the following
+    symbolic constants: GL_ATC_RGB_AMD, GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD,
+    GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
+    GL_ETC1_RGB8_OES
+
+    The destination texture will be created or replaced with the same internal
+    format as the source texture.
+
+    INVALID_OPERATION is generated if internal format of source texture is not
+    one of the valid formats described above.
+
+    INVALID_OPERATION is generated if destination texture is immutable.
+
+    INVALID_VALUE is generated if <source_id> or <dest_id> are not valid texture
+    objects.
+
+    INVALID_VALUE is generated if textures corresponding to <dest_id> have not
+    been bound as GL_TEXTURE_2D object.
+
+    INVALID_VALUE is generated if level 0 of the source texture is not defined.
+
+Errors
+
+    None.
+
+New Tokens
+
+    None.
+
+New State
+
+    None.
+
+Revision History
+
+    15/6/2015    Documented the extension.
+    5/8/2015     Added glCompressedCopySubTextureCHROMIUM.
+    1/6/2016     Remove glCompressedCopySubTextureCHROMIUM.
+    1/8/2016     Remove <target> argument.
diff --git a/src/third_party/angle/extensions/CHROMIUM_copy_texture.txt b/src/third_party/angle/extensions/CHROMIUM_copy_texture.txt
new file mode 100644
index 0000000..5e7fad8
--- /dev/null
+++ b/src/third_party/angle/extensions/CHROMIUM_copy_texture.txt
@@ -0,0 +1,264 @@
+Name
+
+    CHROMIUM_copy_texture
+
+Name Strings
+
+    GL_CHROMIUM_copy_texture
+
+Version
+
+    Last Modifed Date: March 24, 2017
+
+Dependencies
+
+    OpenGL ES 2.0 or OpenGL ES 3.0 is required.
+
+    EXT_texture_format_BGRA8888 affects the definition of this extension.
+    ARB_texture_rg affects the definition of this extension.
+    CHROMIUM_ycbcr_422_image affects the definition of this extension.
+
+Overview
+
+    This extension expands on the functionality provided by the
+    glCopyTexImage2D command.  A new function is exported,
+    glCopyTextureCHROMIUM, that performs the same copy operation as
+    glCopyTexImage2D.
+
+    The extension also supports copying BGRA textures and copying
+    EXTERNAL_OES texture to BGRA texture, which is not explicitly
+    granted by EXT_texture_format_BGRA8888.
+
+New Procedures and Functions
+
+    void CopyTextureCHROMIUM(uint sourceId,
+                             int sourceLevel,
+                             enum destTarget,
+                             uint destId,
+                             int destLevel,
+                             int internalFormat,
+                             enum destType,
+                             boolean unpackFlipY,
+                             boolean unpackPremultiplyAlpha,
+                             boolean unpackUnmultiplyAlpha)
+
+
+    void CopySubTextureCHROMIUM(uint sourceId,
+                                int sourceLevel,
+                                enum destTarget,
+                                uint destId,
+                                int destLevel,
+                                int xoffset,
+                                int yoffset,
+                                int x,
+                                int y,
+                                sizei width,
+                                sizei height,
+                                boolean unpackFlipY,
+                                boolean unpackPremultiplyAlpha,
+                                boolean unpackUnmultiplyAlpha)
+
+Additions to the OpenGL ES 2.0 Specification
+
+    The command
+
+        CopyTextureCHROMIUM
+
+    Copies the contents of <sourceLevel> level of <sourceId> texture to
+    <destLevel> level and <destTarget> target of <destId> texture.
+
+    <destTarget> must be TEXTURE_2D,
+    TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_X,
+    TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_NEGATIVE_Y,
+    TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_Z,
+    TEXTURE_RECTANGLE_ARB.
+
+    The internal format of the destination texture is converted to that
+    specified by <internalFormat>.
+
+    When source texture doens't contain a superset of the component
+    required by <internalFormat>, fill the components by following rules.
+
+       source format           color components
+       ----------------------------------------
+       ALPHA                   (0, 0, 0, A)
+       RED                     (R, 0, 0, 1)
+       LUMINANCE               (L, L, L, 1)
+       LUMINANCE_ALPHA         (L, L, L, A)
+       RGB                     (R, G, B, 1)
+       RGB8                    (R, G, B, 1)
+       RGBA                    (R, G, B, A)
+       RGBA8                   (R, G, B, A)
+       BGRA_EXT                (R, G, B, A)
+       BGRA8_EXT               (R, G, B, A)
+       RGB_YCBCR_420V_CHROMIUM (R, G, B, 1)
+       RGB_YCBCR_422_CHROMIUM  (R, G, B, 1)
+
+    The format type of the destination texture is converted to that specified
+    by <destType>.
+
+    If <flipY> is true, vertically flip texture image data.
+
+    If <unpackPremultiplyAlpha> and <unpackUnmultiplyAlpha> are true,
+    no alpha processing occurs.  This is the equivalent of having neither flag
+    set.
+
+    When <sourceId> refers to a stream texture, the texture matrix will be
+    applied as part of the copy operation.
+
+    INVALID_OPERATION is generated if <internalFormat> is not one of the
+    formats in Table 1.0.
+
+    INVALID_OPERATION is generated if the internal format of <sourceId> is not
+    one of formats in Table 1.1.
+
+    INVALID_VALUE is generated if <sourceId> or <destId> are not valid texture
+    objects.
+
+    INVALID_ENUM is generated if <destTarget> is not one of the valid targets
+    described above.
+
+    INVALID_OPERATION is generated if the bound target of destination texture
+    does not match <target>.
+
+    INVALID_VALUE is generated if textures corresponding to <destId> have not
+    been bound as TEXTURE_2D, TEXTURE_CUBE_MAP, or
+    TEXTURE_RECTANGLE_ARB objects.
+
+    INVALID_VALUE is generated if textures corresponding to <sourceId> have not
+    been bound as TEXTURE_2D, TEXTURE_RECTANGLE_ARB or
+    TEXTURE_EXTERNAL_OES objects.
+
+    INVALID_VALUE is generated if <sourceLevel> is not 0 for ES 2.0, or if
+    <sourceLevel> or <destLevel> is less than 0 for ES 3.0.
+
+    INVALID_VALUE is generated if <sourceLevel> of the source texture is not
+    defined.
+
+    The command
+
+        CopySubTextureCHROMIUM
+
+    Copies the sub contents of texture referred to by <sourceId> to <destId>
+    texture without redefining <destId> texture.
+
+    See CopyTextureCHROMIUM for the interpretation of the <destTarget>,
+    <sourceLevel>, <destLevel>, <flipY>, <premultiplyAlpha>, and
+    <unmultiplyAlpha> arguments.
+
+    <xoffset> and <yoffset> specify a texel offset in the x and y direction
+    respectively within the destination texture.
+
+    <x> and <y> specify specify a texel offset in the x and y direction
+    respectively within the source texture.
+
+    <width> specifies the width of the texture subimage.
+
+    <height> specifies the width of the texture subimage.
+
+    INVALID_VALUE is generated if either <sourceId> texture or <destId>
+    texture is not defined.
+
+    INVALID_OPERATION is generated if the internal format of <sourceId> or
+    <destId> is not one of formats in Table 1.1.
+
+    INVALID_OPERATION is generated if the destination texture array has not
+    been defined.
+
+    INVALID_VALUE is generated if <destId> texture is not bound as
+    TEXTURE_2D or TEXTURE_RECTANGLE_ARB.
+
+    INVALID_VALUE is generated if level 0 of the source texture or
+    the destination texture is not defined.
+
+    INVALID_VALUE is generated if (<xoffset> + <width>) > destWidth,
+    or (<yoffset> + <height>) > destHeight.
+
+    Table 1.0 Valid internal formats for CopyTextureCHROMIUM:
+
+        <internalFormat>
+        ---------------
+        RGB
+        RGBA
+        RGB8
+        RGBA8
+        BGRA_EXT
+        BGRA8_EXT,
+        SRGB_EXT
+        SRGB_ALPHA_EXT
+        R8
+        R8UI
+        RG8
+        RG8UI
+        SRGB8
+        RGB565
+        RGB8UI
+        SRGB8_ALPHA8
+        RGB5_A1
+        RGBA4
+        RGBA4
+        RGBA8UI
+        RGB9_E5
+        R16F
+        R32F
+        RG16F
+        RG32F
+        RGB16F
+        RGB32F
+        RGBA16F
+        RGBA32F
+        R11F_G11F_B10F
+
+    Table 1.1 Valid source texture internal formats for CopyTextureCHROMIUM and
+    source and destination formats for CopySubTextureCHROMIUM:
+
+        internal format
+        ---------------
+        RED
+        ALPHA
+        LUMINANCE
+        LUMINANCE_ALPHA
+        RGB
+        RGBA
+        RGB8
+        RGBA8
+        BGRA_EXT
+        BGRA8_EXT
+        RGB_YCBCR_420V_CHROMIUM
+        RGB_YCBCR_422_CHROMIUM.
+
+Dependencies on ARB_texture_rg
+
+    If ARB_texture_rg is not supported:
+     * delete any reference to the R8 format.
+
+Dependencies on CHROMIUM_ycbcr_422_image
+
+    If CHROMIUM_ycbcr_422_image is not supported:
+     * delete any reference to the RGB_YCBCR_422_CHROMIUM format.
+
+Errors
+
+    None.
+
+New Tokens
+
+    None.
+
+New State
+
+    None.
+
+Revision History
+
+    8/1/2011    Documented the extension
+    7/4/2013    Add a new parameter dest_type to glCopyTextureCHROMIUM()
+    16/7/2014   Add TEXTURE_RECTANGLE_ARB as valid source_id target
+    19/6/2015   Add arguments unpack_flip_y, unpack_premultiply_alpha, and
+                unpack_unmultiply_alpha to both commands.
+    4/1/2016    Removed the argument target.
+    4/1/2016    Added TEXTURE_RECTANGLE_ARB as valid dest_id target.
+    19/12/2016  Supported more ES 3.0 formats.
+    18/1/2017   Supported source_level and dest_level.
+    19/1/2017   Added TEXTURE_CUBE_MAP as valid dest_id target.
+    24/3/2017   Clean up naming and move formats into tables.
diff --git a/src/third_party/angle/extensions/CHROMIUM_sync_query.txt b/src/third_party/angle/extensions/CHROMIUM_sync_query.txt
new file mode 100644
index 0000000..98763d0
--- /dev/null
+++ b/src/third_party/angle/extensions/CHROMIUM_sync_query.txt
@@ -0,0 +1,53 @@
+Name
+
+    CHROMIUM_sync_query
+
+Name Strings
+
+    GL_CHROMIUM_sync_query
+
+Version
+
+    Last Modifed Date: April 15, 2014
+
+Dependencies
+
+    OpenGL ES 2.0 is required.
+
+    EXT_occlusion_query_boolean is required.
+
+Overview
+
+    This extension provides a query mechanism that allow for synchronization
+    between the host CPU and the GPU, which may be accessing the same
+    resources (typically memory).
+
+    This extension is useful in conjunction with CHROMIUM_map_image to
+    determine when it is safe to access a mapped image. Once the result of
+    a COMMANDS_COMPLETED_CHROMIUM query is available, all drawing commands
+    issued before the query must have finished. This ensures that the memory
+    corresponding to the issued commands can be safely modified (assuming no
+    other outstanding drawing commands are issued subsequent to the query).
+
+New Procedures and Functions
+
+    None.
+
+Errors
+
+    None.
+
+New Tokens
+
+    Accepted by the <target> parameter of BeginQueryEXT, EndQueryEXT,
+    and GetQueryivEXT:
+
+        COMMANDS_COMPLETED_CHROMIUM                     0x84F7
+
+New State
+
+    None.
+
+Revision History
+
+    4/15/2014   Documented the extension
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_create_context_client_arrays.txt b/src/third_party/angle/extensions/EGL_ANGLE_create_context_client_arrays.txt
new file mode 100644
index 0000000..994695a
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_create_context_client_arrays.txt
@@ -0,0 +1,87 @@
+Name
+
+    ANGLE_create_context_client_arrays
+
+Name Strings
+
+    EGL_ANGLE_create_context_client_arrays
+
+Contributors
+
+    Geoff Lang
+
+Contacts
+
+    Geoff Lang (geofflang 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, February 13, 2016
+
+Number
+
+    EGL Extension #??
+
+Dependencies
+
+    Requires EGL 1.4.
+
+    Written against the EGL 1.4 specification.
+
+    An OpenGL ES implementation supporting GL_ANGLE_client_arrays or equivalent
+    functionality is required.
+
+Overview
+
+    This extension allows the creation of an OpenGL or OpenGL ES context that
+    allows or disallows drawing with client-side vertex or index data.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as an attribute name in the <*attrib_list> argument to
+    eglCreateContext:
+
+        EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452
+
+Additions to the EGL 1.4 Specification
+
+    Add the following to section 3.7.1 "Creating Rendering Contexts":
+
+    EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE indicates whether the context
+    should be created with the GL_CLIENT_ARRAYS_ANGLE state initialized to
+    GL_TRUE or GL_FALSE. The default value of
+    EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE is EGL_FALSE.
+
+Errors
+
+    None
+
+New State
+
+    None
+
+Conformance Tests
+
+    TBD
+
+Issues
+
+    None
+
+Revision History
+
+    Rev.    Date         Author     Changes
+    ----  -------------  ---------  ----------------------------------------
+      1   Feb 13, 2016   geofflang  Initial version
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_create_context_robust_resource_initialization.txt b/src/third_party/angle/extensions/EGL_ANGLE_create_context_robust_resource_initialization.txt
new file mode 100644
index 0000000..7714774
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_create_context_robust_resource_initialization.txt
@@ -0,0 +1,81 @@
+Name
+
+    EGL_ANGLE_create_context_robust_resource_initialization.txt
+
+Name Strings
+
+    EGL_ANGLE_create_context_robust_resource_initialization
+
+Contributors
+
+    Geoff Lang, Google
+    Ken Russell, Google
+
+Contacts
+
+    Shannon Woods, Google (shannonwoods 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, January 7, 2015
+
+Number
+
+    EGL Extension TBD
+
+Dependencies
+
+    This extension is written against the wording of the EGL 1.5
+    specification.
+
+    An OpenGL ES implementation supporting ANGLE_robust_resource_initialization
+    or an implementation supporting equivalent functionality is required.
+
+Overview
+
+    This extension allows creating an OpenGL ES context supporting
+    robust resource initialization.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as an attribute name in the <*attrib_list> argument to
+    eglCreateContext:
+
+        EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE    0x320F
+
+Additions to the EGL 1.5 Specification
+
+    Add a new section entitled "OpenGL ES Robust Resource Initialization"
+    to section 3.7.1:
+
+    "If the attribute EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE
+    is set to EGL_TRUE, a context supporting <robust resource initialization>
+    will be created. OpenGL ES contexts must support the
+    ANGLE_robust_resource_initialization extension, or equivalent core API
+    functionality.
+    This attribute is supported only for OpenGL ES contexts. If the
+    implementation does not support robust resource initialization,
+    context creation will fail.
+    The default value of EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE
+    is EGL_FALSE."
+
+Issues
+
+    None
+
+Revision History
+
+    Version 1, 2015/01/07 - first draft.
+    Version 2, 2017/03/01 - renamed extension and enum.
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt b/src/third_party/angle/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt
new file mode 100644
index 0000000..2e7fb82
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt
@@ -0,0 +1,88 @@
+Name
+
+    ANGLE_create_context_webgl_compatibility
+
+Name Strings
+
+    EGL_ANGLE_create_context_webgl_compatibility
+
+Contributors
+
+    Geoff Lang
+
+Contacts
+
+    Geoff Lang (geofflang 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, September 16, 2016
+
+Number
+
+    EGL Extension #??
+
+Dependencies
+
+    Requires EGL 1.4.
+
+    Written against the EGL 1.4 specification.
+
+    This spec interacts with GL_ANGLE_webgl_compatibility (or equivalent)
+    extension.
+
+Overview
+
+    This extension allows the creation of an OpenGL or OpenGL ES context that
+    provides additional WebGL features and validation.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as an attribute name in the <*attrib_list> argument to
+    eglCreateContext:
+
+        EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
+
+Additions to the EGL 1.4 Specification
+
+    Add the following to section 3.7.1 "Creating Rendering Contexts":
+
+    EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE indicates whether a WebGL mode should
+    be enabled for the OpenGL ES context.  In this mode, the OpenGL ES context
+    will provide additional features and validation to be compatible with the
+    WebGL specification. The default value of
+    EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE is EGL_FALSE.
+
+Errors
+
+    None
+
+New State
+
+    None
+
+Conformance Tests
+
+    TBD
+
+Issues
+
+    None
+
+Revision History
+
+    Rev.    Date         Author     Changes
+    ----  -------------  ---------  ----------------------------------------
+      1   Sept 16, 2016  geofflang  Initial version
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_d3d_texture_client_buffer.txt b/src/third_party/angle/extensions/EGL_ANGLE_d3d_texture_client_buffer.txt
new file mode 100644
index 0000000..df3201c
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_d3d_texture_client_buffer.txt
@@ -0,0 +1,111 @@
+Name
+
+    ANGLE_d3d_texture_client_buffer
+
+Name Strings
+
+    EGL_ANGLE_d3d_texture_client_buffer
+
+Contributors
+
+    Geoff Lang
+
+Contacts
+
+    Geoff Lang, Google Inc. (geofflang 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, Oct 5, 2016
+
+Number
+
+    EGL Extension #??
+
+Dependencies
+
+    This extension is written against the wording of the EGL 1.4
+    Specification.
+
+    References the EGL_ANGLE_device_d3d extension.
+
+Overview
+
+    This extension allows creating EGL surfaces from D3D texture objects.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted in the <buftype> parameter of eglCreatePbufferFromClientBuffer:
+
+        EGL_D3D_TEXTURE_ANGLE            0x33A3
+
+Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
+
+    Replace the last sentence of paragraph 1 of Section 3.5.3 with the
+    following text.
+    "Currently, the only client API resources which may be bound in this
+    fashion are OpenVG VGImage objects and Direct3D texture objects."
+
+    Replace the last sentence of paragraph 2 ("To bind a client API...") of
+    Section 3.5.3 with the following text.
+    "When <buftype> is EGL_OPENVG_IMAGE or EGL_D3D_TEXTURE_ANGLE, the width and
+    height of the pbuffer are determined by the width and height of <buffer>."
+
+    Replace the third paragraph of Section 3.5.3 with the following text.
+    "<buftype> specifies the type of buffer to be bound. The only allowed values
+    of <buftype> are EGL_OPENVG_IMAGE and EGL_D3D_TEXTURE_ANGLE".
+
+    Append the following text to the fourth paragraph of Section 3.5.3.
+    "When <buftype> is EGL_D3D_TEXTURE_ANGLE, <buffer> must be
+    a valid D3D texture object, cast into the type EGLClientBuffer. See table
+    egl.restrictions for acceptable texture object types and formats. If the
+    EGL_ANGLE_device_d3d extension is present, the provided D3D texture object
+    must have been created by the same D3D device queried from the display.
+    If these requirements are not met, an EGL_BAD_PARAMETER error is
+    generated."
+
+    ---------------------------------------------------------------------------
+    Resource Type      Resource Restrictions
+    ---------------------------------------------------------------------------
+    IDirect3DTexture9  Memory pool must be D3DPOOL_DEFAULT. Format must be
+                       D3DFMT_R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_A16B16G16R16F or
+                       D3DFMT_A32B32G32R32F.
+    ID3D11Texture2D    Usage flags must be D3D11_USAGE_DEFAULT. Format must be
+                       DXGI_FORMAT_R8G8B8A8_UNORM,
+                       DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                       DXGI_FORMAT_B8G8R8A8_UNORM,
+                       DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+                       DXGI_FORMAT_R16G16B16A16_FLOAT or
+                       DXGI_FORMAT_R32G32B32A32_FLOAT.
+   --------------------------------------------------------------------------
+    Table egl.restrictions - Restrictions on D3D resources that can be used
+    as a <buffer>.
+    --------------------------------------------------------------------------
+
+    Append to the end of Section 3.5.3.
+    "When a pbuffer is created with type EGL_D3D_TEXTURE_ANGLE, the contents
+    of the associcated D3D texture object are undefined while the pbuffer is
+    the current read surface, draw surface or bound to a client texture."
+
+Issues
+
+    1. What renderers allow the use of a multi-sampled texture?
+
+    PROPOSED: Mutli-sampled texture support is currently limited to D3D11. Additionally,
+    the client is responsible for resolving the texture.
+
+Revision History
+
+    Version 1, 2016/10/05 - first draft.
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_device_creation.txt b/src/third_party/angle/extensions/EGL_ANGLE_device_creation.txt
new file mode 100644
index 0000000..2401a09
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_device_creation.txt
@@ -0,0 +1,120 @@
+Name
+
+    ANGLE_device_creation
+
+Name Strings
+
+    EGL_ANGLE_device_creation
+
+Contributors
+
+    Austin Kinross  (aukinros 'at' microsoft.com)
+
+Contact
+
+    Austin Kinross  (aukinros 'at' microsoft.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, Nov 02, 2015
+
+Number
+
+    EGL Extension #XXX
+
+Extension Type
+
+    EGL client extension
+
+Dependencies
+
+    Requires EGL_EXT_device_query.
+
+    Written against the wording of EGL 1.5 as modified by EGL_EXT_device_query.
+
+Overview
+
+    Increasingly, EGL and its client APIs are being used in place of "native"
+    rendering APIs to implement the basic graphics functionality of native
+    windowing systems. This extension defines a way to create an EGL device
+    which maps to an inputted "native" rendering API device.
+
+    This extension is intended to be used with EGL_EXT_platform_device to
+    initialize a display using an existing "native" rendering device, but
+    EGL_EXT_platform_device is not required.
+
+IP Status
+
+    No known claims.
+
+New Types
+
+    None.
+
+New Procedures and Functions
+
+    EGLDeviceEXT eglCreateDeviceANGLE(EGLint device_type,
+                                      void *native_device,
+                                      cost EGLAttrib *attrib_list)
+
+    EGLBoolean eglReleaseDeviceANGLE(EGLDeviceEXT device)
+
+New Tokens
+
+    None.
+
+Changes to section 3.2 (Devices)
+
+    Add the following after the final paragraph to section 3.2 (Devices):
+
+    To create an EGL device wrapping an existing native rendering device, use:
+
+        EGLDeviceEXT eglCreateDeviceANGLE(EGLint device_type,
+                                          void *native_device,
+                                          cost EGLAttrib *attrib_list);
+
+    On success, a valid EGLDeviceEXT is returned. On failure, EGL_NO_DEVICE_EXT
+    is returned.
+
+    An EGL_BAD_ATTRIBUTE error is generated if <device_type> is not a valid
+    device type. This extension defines no valid values for <device_type>.
+
+    All attribute names in <attrib_list> are immediately followed by the
+    corresponding desired value. The list is terminated with EGL_NONE. The
+    <attrib_list> is considered empty if either <attrib_list> is NULL or if its
+    first element is EGL_NONE. This specification defines no valid attribute
+    names for inclusion in <attrib_list>. If <attrib_list> is not empty then
+    an EGL_BAD_ATTRIBUTE error is generated.
+
+    If a device is created using eglCreateDeviceANGLE then it is the
+    caller's responsibility to manage the lifetime of the device, and to call
+    eglReleaseDeviceANGLE at an appropriate time.
+
+    To release a device, use:
+
+        EGLBoolean eglReleaseDeviceANGLE(EGLDeviceEXT device);
+
+    On success, EGL_TRUE is returned. On failure, EGL_FALSE is returned.
+
+    If <device> equals EGL_NO_DEVICE_EXT then an EGL_BAD_DEVICE_EXT error is
+    generated. If <device> is not a valid device then the behavior is undefined.
+
+    <device> must have been created using eglGetDeviceANGLE. If <device> was
+    obtained by other means, such as through eglQueryDisplayAttribEXT, then an
+    EGL_BAD_DEVICE_EXT error is generated.
+
+    If eglReleaseDeviceANGLE is called on a device that is still in use by other
+    EGL objects, then the resulting behavior of those objects is undefined.
+
+Issues
+
+    None.
+
+Revision History
+
+    Version 1, Nov 2, 2015 (Austin Kinross)
+        - Initial Draft
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_device_creation_d3d11.txt b/src/third_party/angle/extensions/EGL_ANGLE_device_creation_d3d11.txt
new file mode 100644
index 0000000..6f25f53
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_device_creation_d3d11.txt
@@ -0,0 +1,92 @@
+Name
+
+    ANGLE_device_creation_d3d11
+
+Name Strings
+
+    EGL_ANGLE_device_creation_d3d11
+
+Contributors
+
+    Austin Kinross  (aukinros 'at' microsoft.com)
+
+Contact
+
+    Austin Kinross  (aukinros 'at' microsoft.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, Nov 02, 2015
+
+Number
+
+    EGL Extension #XXX
+
+Extension Type
+
+    EGL client extension
+
+Dependencies
+
+    Requires EGL_ANGLE_device_d3d and EGL_ANGLE_device_creation.
+
+    Written against the wording of EGL 1.5 as modified by EGL_ANGLE_device_d3d
+    and EGL_ANGLE_device_creation.
+
+Overview
+
+    ANGLE has the ability to run GPU commands on a native D3D device. This
+    extension defines a way to create a EGL device which maps to an inputted
+    Direct3D 11 device.
+
+    This extension is intended to be used with EGL_EXT_platform_device to
+    initialize a display using an existing Direct3D 11 device, but
+    EGL_EXT_platform_device is not required.
+
+IP Status
+
+    No known claims.
+
+New Types
+
+    None.
+
+New Procedures and Functions
+
+    None.
+
+New Tokens
+
+    None.
+
+Changes to section 3.2 (Devices)
+
+    Modify the language in section 3.2 (Devices) describing valid attribute
+    names passed into eglCreateDeviceANGLE via <device_type>:
+
+    "This specification defines one value for <device_type>:
+    EGL_D3D11_DEVICE_ANGLE. If this device type is specified then
+    <native_device> must be a valid pointer to a Direct3D 11 device. If
+    <native_device> is not a valid pointer to a Direct3D 11 device then the
+    resulting behavior is undefined."
+
+    Append the following to the end of section 3.2 (Devices):
+
+    "If a Direct3D 11 device used to create a device experiences a "lost device"
+    then all resulting behavior of the device (and any dependent EGL objects) is
+    undefined. It is the caller's responsibility to monitor for "lost device"
+    and to create a new device (and dependent EGL objects) as appropriate. For
+    more information on "lost device", see the Direct3D documentation."
+
+Issues
+
+    None.
+
+Revision History
+
+    Version 1, Nov 2, 2015 (Austin Kinross)
+        - Initial Draft
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_device_d3d.txt b/src/third_party/angle/extensions/EGL_ANGLE_device_d3d.txt
new file mode 100644
index 0000000..6e56247
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_device_d3d.txt
@@ -0,0 +1,93 @@
+Name
+
+    ANGLE_device_d3d
+
+Name Strings
+
+    EGL_ANGLE_device_d3d
+
+Contributors
+
+    Jamie Madill  (jmadill 'at' google.com)
+
+Contact
+
+    Jamie Madill  (jmadill 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, Mar 25, 2015
+
+Number
+
+    EGL Extension #XXX
+
+Extension Type
+
+    EGL device extension
+
+Dependencies
+
+    This extension is written against the language of EGL 1.5 as
+    modified by EGL_EXT_device_query.
+
+    EGL_EXT_device_query is required.
+
+Overview
+
+    ANGLE has the ability to run GPU commands on a native D3D device.
+    This extension defines a mapping from an EGL device to a D3D
+    device, after it's queried from an EGL display.
+
+IP Status
+
+    No known claims.
+
+New Types
+
+    None.
+
+New Procedures and Functions
+
+    None.
+
+New Tokens
+
+    Accepted as a queried <attribute> in eglQueryDeviceAttribEXT:
+
+        EGL_D3D9_DEVICE_ANGLE              0x33A0
+        EGL_D3D11_DEVICE_ANGLE             0x33A1
+
+Add a new section 2.1.3 (D3D Devices) after 2.1.2 (Devices)
+
+    Somewhat analogous to an EGL device, a D3D device establishes a
+    namespace for D3D operations. In the D3D APIs, such devices are
+    represented by pointers. For more details, see the D3D
+    documentation.
+
+Changes to section 3.2 (Devices)
+
+    Replace the paragraph immediately following the prototype for
+    eglQueryDeviceAttribEXT:
+
+    <attribute> may be either EGL_D3D9_DEVICE_ANGLE or EGL_D3D11_DEVICE_ANGLE.
+    On success, EGL_TRUE is returned, and a valid D3D9 or D3D11 device pointer
+    corresponding to the EGL device is returned in <value>. This handle
+    is compatible with D3D API functions. If the EGL device is not currently
+    associated with a D3D9 device and <attribute> is EGL_D3D9_DEVICE_ANGLE,
+    or if the EGL device is not currently associated with a D3D11 device and
+    <attribute> is EGL_D3D11_DEVICE_ANGLE, EGL_BAD_ATTRIBUTE is returned,
+    and <value> is left unchanged.
+
+Issues
+
+    None
+
+Revision History
+
+    Version 1, Mar 25, 2015 (Jamie Madill)
+        - Initial Draft
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_direct_composition.txt b/src/third_party/angle/extensions/EGL_ANGLE_direct_composition.txt
new file mode 100644
index 0000000..72bbfc3
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_direct_composition.txt
@@ -0,0 +1,97 @@
+Name
+
+    ANGLE_direct_composition
+
+Name Strings
+
+    EGL_ANGLE_direct_composition
+
+Contributors
+
+    John Bauman
+
+Contacts
+
+    John Bauman (jbauman 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 2, Dec 14, 2015
+
+Number
+
+    EGL Extension #??
+
+Dependencies
+
+    This extension is written against the wording of the EGL 1.5 Specification.
+
+Overview
+
+    This extension allows specifying that the contents of a window surface be
+    posted to the screen using the DirectComposition API.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted by the <attribute> parameter of eglQuerySurface and by the
+    <attrib_list> parameter of eglCreateWindowSurface and
+    eglCreatePlatformWindowSurface
+
+    EGL_DIRECT_COMPOSITION_ANGLE                         0x33A5
+
+Changes to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors)
+
+    Modify the fourth paragraph of Section 3.5.1, page 32
+    (Creating On-Screen rendering Surfaces)
+
+    "<attrib_list> specifies a list of attributes for the window. The list has
+    the same structure as described for eglChooseConfig. Attributes that can
+    be specified in <attrib_list> include EGL_DIRECT_COMPOSITION_ANGLE,
+    EGL_GL_COLORSPACE, EGL_RENDER_BUFFER, EGL_VG_COLORSPACE, and
+    EGL_VG_ALPHA_FORMAT."
+
+    Add the following between paragraphs 6 and 7 of Section 3.5.1, page 32
+    (Creating On-Screen Rendering Surfaces)
+
+    "EGL_DIRECT_COMPOSITION_ANGLE specifies whether the surface will be posted
+    to the window using DirectComposition. The default is EGL_FALSE. If
+    EGL_TRUE is specified, <native_window> must be owned by the current
+    process, and contents drawn by native APIs or EGLSurfaces with
+    EGL_DIRECT_COMPOSITION_ANGLE as EGL_FALSE will appear underneath the
+    contents of this surface."
+
+
+    Add the following entry to Table 3.5, page 44 (Queryable surface
+    attributes and types)
+
+    Attribute                    Type    Description
+    ---------------------------- ------- --------------------------------------
+    EGL_DIRECT_COMPOSITION_ANGLE boolean Surface will be posted to the window
+                                         using DirectComposition
+
+Issues
+    1. Should a surface attrib or config be used to specify that
+    DirectComposition is needed.
+
+    PROPOSED: A surface attrib would work and avoids creating
+    otherwise-duplicate configs.
+
+Revision History
+
+    Version 2, 2015/12/14
+      - Use attrib instead of config.
+
+    Version 1, 2015/12/10
+      - Initial draft.
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_display_texture_share_group.txt b/src/third_party/angle/extensions/EGL_ANGLE_display_texture_share_group.txt
new file mode 100644
index 0000000..90f75ec
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_display_texture_share_group.txt
@@ -0,0 +1,82 @@
+Name
+
+    ANGLE_display_texture_share_group
+
+Name Strings
+
+    EGL_ANGLE_display_texture_share_group
+
+Contributors
+
+    Geoff Lang, Google
+
+Contacts
+
+    Geoff Lang, Google (geofflang 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, February 7, 2017
+
+Number
+
+    EGL Extension TBD
+
+Dependencies
+
+    This extension is written against the wording of the EGL 1.5 specification.
+
+Overview
+
+    This extension allows for the creation of OpenGL ES contexts that share
+    texture objects with other contexts owned by the same display. This method
+    of sharing textures can be used in conjuction with regular share groups.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as an attribute name in the <*attrib_list> argument to
+    eglCreateContext:
+
+        EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE    0x33AF
+
+Additions to the EGL 1.5 Specification
+
+    Add a new section entitled "OpenGL ES Global Texture Share Groups"
+    to section 3.7.1:
+
+    "If the attribute EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE is set to EGL_TRUE,
+    a context that shares textures with other contexts owned by the same
+    display and created with EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE set to
+    EGL_TRUE will be created. If the share_context parameter to
+    eglCreateContext is not NULL, all contexts within the share group must have
+    been created with the same value of EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.
+    The default value of EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE is EGL_FALSE."
+
+Issues
+
+    (1) What happens to the shared textures when a context in the global share
+        group is destroyed?
+
+    RESOLOVED: When the last context in the global texture share group is
+    destroyed, all textures in the global texture share group are released. If
+    a new context is created in the global texture share group, no textures
+    will exist.
+
+    This mirrors how regular share groups work, releasing all objects when the
+    last context is destroyed.
+
+Revision History
+
+    Version 1, 2017/02/07 - first draft.
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_experimental_present_path.txt b/src/third_party/angle/extensions/EGL_ANGLE_experimental_present_path.txt
new file mode 100644
index 0000000..4f96c1f
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_experimental_present_path.txt
@@ -0,0 +1,106 @@
+Name
+
+    ANGLE_experimental_present_path
+
+Name Strings
+
+    EGL_ANGLE_experimental_present_path
+
+Contributors
+
+    Austin Kinross
+
+Contacts
+
+    Austin Kinross (aukinros 'at' microsoft 'dot' com)
+
+Status
+
+    Experimental
+
+Version
+
+    Version 1, Jan 22 2016
+
+Number
+
+    EGL Extension #XXX
+
+Extension Type
+
+    EGL display extension
+
+Dependencies
+
+    Requires ANGLE_platform_angle_d3d.
+
+    Written against the wording of EGL 1.4 as modified by
+    ANGLE_platform_angle_d3d.
+
+Overview
+
+    This extension exposes an optimized, but potentially non-conformant,
+    rendering path for ANGLE's D3D11 renderer on Windows.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as an attribute name in the <attrib_list> argument of
+    eglGetPlatformDisplayEXT:
+
+        EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE      0x33A4
+
+    Accepted as values for the EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE attribute:
+
+        EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
+        EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
+
+Additions to the EGL Specification
+
+    None.
+
+New Behavior
+
+    To request a display that enables this optimized rendering path,
+    the value of EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE should be set to
+    EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE. Setting this value may impact
+    OpenGL ES conformance (see Issue 1 below).
+
+    The only valid values for the attribute
+    EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE are
+    EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE and
+    EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE. If any other value is specified
+    then an EGL_BAD_ATTRIBUTE error is generated and EGL_NO_DISPLAY is
+    returned.
+
+    If a value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE is specified and
+    EGL_PLATFORM_ANGLE_TYPE_ANGLE is not set to
+    EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE then an EGL_BAD_ATTRIBUTE error is
+    generated and EGL_NO_DISPLAY is returned.
+
+	If the attribute EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE
+    is unspecified then it is implicitly set to
+    EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE.
+
+Issues
+
+    1) Does setting EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE to be
+       EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE maintain OpenGL ES
+       conformance?
+
+       RESOLVED: Not necessarily, that is implementation-specific. Check then
+       EGL_CONFORMANT attribute to see if the implementation supports any
+       conformant EGL configs when EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE
+       is specified.
+
+Revision History
+
+    Version 1, Jan 22 2016 (Austin Kinross)
+      - Initial draft
\ No newline at end of file
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_flexible_surface_compatibility.txt b/src/third_party/angle/extensions/EGL_ANGLE_flexible_surface_compatibility.txt
new file mode 100644
index 0000000..55d9463
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_flexible_surface_compatibility.txt
@@ -0,0 +1,154 @@
+Name
+
+    ANGLE_flexible_surface_compatibility
+
+Name Strings
+
+    EGL_ANGLE_flexible_surface_compatibility
+
+Contributors
+
+    John Bauman   (jbauman 'at' google.com)
+    Shannon Woods (shannonwoods 'at' google.com)
+
+Contact
+
+    John Bauman   (jbauman 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 3, Dec 15, 2015
+
+Number
+
+    EGL Extension #XXX
+
+Extension Type
+
+    EGL display extension
+
+Dependencies
+
+    This extension is written against the language of EGL 1.5.
+
+Overview
+
+    Some EGL implementations may allow any surface to be made current with any
+    context from the same display, without restrictions due to bit depth.
+
+IP Status
+
+    No known claims.
+
+New Types
+
+    None.
+
+New Procedures and Functions
+
+    None.
+
+New Tokens
+
+    Accepted by the <attribute> parameter of eglQuerySurface and by the
+    <attrib_list> parameter of eglCreateWindowSurface,
+    eglCreatePlatformWindowSurface, eglCreatePbufferSurface, and
+    eglCreatePbufferFromClientBuffer:
+
+    EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE  0x33A6
+
+Changes to Chapter 2 of the EGL 1.5 Specification (EGL Operation)
+
+    Replace the first paragraph of the first bulleted list item in section
+    2.2, page 4
+    (Rendering Contexts and Drawing Surfaces)
+
+    "They support the same type of color buffer (RGB or luminance), or the
+    surface has the EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE
+    attribute set to EGL_TRUE."
+
+    Replace the first paragraph of the second bulleted list item in section
+    2.2, page 4
+    (Rendering Contexts and Drawing Surfaces)
+
+    "They have color buffers and ancillary buffers of the same depth, or the
+    surface has the EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE
+    attribute set to EGL_TRUE."
+
+Changes to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors)
+
+    Modify the fourth paragraph of Section 3.5.1, page 32
+    (Creating On-Screen rendering Surfaces)
+
+    "<attrib_list> specifies a list of attributes for the window. The list has
+    the same structure as described for eglChooseConfig. Attributes that can
+    be specified in <attrib_list> include
+    EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_GL_COLORSPACE,
+    EGL_RENDER_BUFFER, EGL_VG_COLORSPACE, and EGL_VG_ALPHA_FORMAT."
+
+    Add the following between paragraphs 6 and 7 of Section 3.5.1, page 32
+    (Creating On-Screen Rendering Surfaces)
+
+    "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE specifies whether the
+    surface can be made current with a context with a config of different bit
+    depth. Its values can be EGL_TRUE, in which case that is supported, or
+    EGL_FALSE, in which case that is not supported."
+
+    Modify the fourth paragraph of Section 3.5.2, page 35
+    (Creating Off-Screen Rendering Surfaces)
+
+    "<attrib_list> specifies a list of attributes for the pbuffer. The list
+    has the same structure as described for eglChooseConfig. Attributes that
+    can be specified in <attrib_list> include EGL_WIDTH, EGL_HEIGHT,
+    EGL_LARGEST_PBUFFER, EGL_TEXTURE_FORMAT, EGL_TEXTURE_TARGET,
+    EGL_MIPMAP_TEXTURE, EGL_GL_COLORSPACE, EGL_VG_COLORSPACE,
+    EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, and
+    EGL_VG_ALPHA_FORMAT."
+
+    Modify paragraph twelve of Section 3.5.2, page 36
+
+    "EGL_GL_COLORSPACE, EGL_VG_COLORSPACE,
+    EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, and
+    EGL_VG_ALPHA_FORMAT have the same meaning and default values as when used
+    with eglCreatePlatformWindowSurface."
+
+    Modify the fifth paragraph of Section 3.5.3, page 37
+    (Binding Off-Screen Rendering Surfaces To Client Buffers)
+
+    "<attrib_list> specifies a list of attributes for the pbuffer. The list
+    has the same structure as described for eglChooseConfig. Attributes that
+    can be specified in <attrib_list> include EGL_TEXTURE_FORMAT,
+    EGL_TEXTURE_TARGET, EGL_- MIPMAP_TEXTURE, and
+    EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE. The meaning of these
+    attributes is as described above for eglCreatePbufferSurface. The
+    EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT attributes of the surface are
+    determined by the VGImageFormat of buffer."
+
+    Add the following entry to Table 3.5, page 44 (Queryable surface
+    attributes and types)
+
+    Attribute                                          Type    Description
+    -------------------------------------------------- ------- ------------------------
+    EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE boolean Surface can be made
+                                                               current with contexts
+                                                               of a different bit depth
+
+Issues
+
+    None
+
+Revision History
+
+    Version 3, Dec 15, 2015 (John Bauman)
+        - Modify EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE value.
+
+    Version 2, Dec 1, 2015 (John Bauman)
+        - Add EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE to specify
+          new behavior.
+
+    Version 1, Nov 24, 2015 (John Bauman)
+        - Initial Draft
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_keyed_mutex.txt b/src/third_party/angle/extensions/EGL_ANGLE_keyed_mutex.txt
new file mode 100644
index 0000000..647af90
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_keyed_mutex.txt
@@ -0,0 +1,75 @@
+Name
+
+    ANGLE_keyed_mutex
+
+Name Strings
+
+    EGL_ANGLE_keyed_mutex
+
+Contributors
+
+    Jeff Muizelaar
+
+Contacts
+
+    Jeff Muizelaar, Mozilla (jmuizelaar 'at' mozilla.org)
+
+Status
+
+    Implemented in ANGLE.
+
+Version
+
+    Version 1, Oct 29, 2014
+
+Number
+
+    EGL Extension #??
+
+Dependencies
+
+    Requires the EGL_ANGLE_query_surface_pointer extension.
+
+    This extension is written against the wording of the EGL 1.4
+    Specification.
+
+Overview
+
+    Some EGL implementations generate EGLSurface handles that are
+    backed by Direct3D 11 2D textures.  This extension allows
+    obtaining the IDXGIKeyedMutex for such EGL surfaces.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted in the <attribute> parameter of eglQuerySurfacePointerANGLE:
+
+        EGL_DXGI_KEYED_MUTEX_ANGLE                       0x33A2
+
+    Add to table 3.5, "Queryable surface attributes and types":
+
+        Attribute                              Type      Description
+        ---------                              ----      -----------
+        EGL_DXGI_KEYED_MUTEX_ANGLE             pointer   IDXGIKeyedMutex
+
+    Add before the last paragraph in section 3.5, "Surface attributes":
+
+        "Querying EGL_DXGI_KEYED_MUTEX_ANGLE returns a IDXGIKeyedMutex, or NULL
+        if a keyed mutex for the surface is not available.  The keyed mutex
+        must be queried using eglQuerySurfaceAttribPointerANGLE.  Keyed Mutexes
+        are only available from EGL surfaces backed by Direct3D 11 surfaces.
+        Before using the keyed mutex, ensure that all rendering to the EGLSurface
+        with EGL client APIs has completed."
+
+Issues
+
+Revision History
+
+    Version 1, 2014/10/29 - first draft.
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_stream_producer_d3d_texture_nv12.txt b/src/third_party/angle/extensions/EGL_ANGLE_stream_producer_d3d_texture_nv12.txt
new file mode 100644
index 0000000..427f800
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_stream_producer_d3d_texture_nv12.txt
@@ -0,0 +1,156 @@
+Name
+
+    ANGLE_stream_producer_d3d_texture_nv12
+
+Name Strings
+
+    EGL_ANGLE_stream_producer_d3d_texture_nv12
+
+Contributors
+
+    Ian Ewell
+    Geoff Lang
+    John Bauman
+
+Contacts
+
+    Geoff Lang, Google (geofflang ‘at’ google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, April 6, 2016
+
+Number
+
+    EGL Extension #XXX
+
+Dependencies
+
+    Requires EGL 1.5.
+    Requires OpenGL ES 2.0.
+
+    Requires the EGL_KHR_stream extension.
+    Requires the EGL_NV_stream_consumer_gltexture_yuv extension.
+    Requires the EGL_ANGLE_device_d3d extension.
+
+Overview
+
+    This extension allows D3D11 NV12 textures to be inserted into an EGL stream
+    with the expectation that the stream consumer will be a YUV GL texture
+    consumer using a two plane configuration (i.e. a Y plane and a UV plane).
+    This will act as the producer of the stream.
+
+New procedures and functions
+
+    EGLBoolean eglCreateStreamProducerD3DTextureNV12ANGLE
+                                                  (EGLDisplay dpy,
+                                                   EGLStreamKHR stream,
+                                                   const EGLAttrib *attrib_list)
+    EGLBoolean eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy,
+                                                EGLStreamKHR stream,
+                                                void *texture,
+                                                const EGLAttrib *attrib_list)
+
+New Tokens
+
+    Accepted as an <attribute> in eglStreamPostD3DTextureNV12ANGLE:
+
+        EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE 0x33AB
+
+Replace section "3.10.3.1 No way to connect producer to EGLStream" in the
+EGL_KHR_stream extension with this:
+
+    3.10.3.1 Stream Surface Producer
+
+    Call
+
+        EGLBoolean eglCreateStreamProducerD3DTextureNV12ANGLE(
+                    EGLDisplay dpy,
+                    EGLStreamKHR stream,
+                    const EGLAttrib *attrib_list)
+
+    to create a producer that accepts D3D11 NV12 textures and connect it as the
+    producer of <stream>. <attrib_list> is used to specify attributes for the
+    stream producer. Currently there are no attributes to specify, and the
+    attribute list is used as a placeholder for future additions.
+
+    On failure, eglCreateStreamProducerD3DTextureNV12ANGLE returns EGL_FALSE and
+    generates an error.
+
+        - EGL_BAD_STATE_KHR is generated if <stream> is not in the state
+          EGL_STREAM_STATE_CONNECTING_KHR.
+
+        - EGL_BAD_MATCH is generated if <stream> does not have a connected GL
+          texture YUV consumer that is configured to bind to two OpenGL
+          textures: one for the Y plane and one for the UV plane.
+
+        - EGL_BAD_STREAM_KHR is generated if <stream> is not a valid EGLStream
+          generated for <dpy>.
+
+        - EGL_BAD_DISPLAY is generated if <dpy> is not a valid, initialized
+          display.
+
+Add a section preceding "3.9.3 Posting Semantics" in the EGL specification:
+
+    3.9.x Posting to a Stream
+
+    To post a D3D11 NV12 texture to a stream, call
+
+        EGLBoolean eglStreamPostD3DTextureNV12ANGLE(
+                    EGLDisplay dpy,
+                    EGLStreamKHR stream,
+                    void *texture,
+                    const EGLAttrib *attrib_list);
+
+    If <stream> is an appropriately configured stream and <texture> points to a
+    valid ID3D11Texture2D object of the format DXGI_FORMAT_NV12 that is owned
+    by the same ID3D11Device that is queried with the EGL_ANGLE_device_d3d
+    extension, the texture will be posted to the stream and can be bound as one
+    or more OpenGL texture objects.
+
+    The parameter <attrib_list> allows for per-frame attributes to be specified
+    along with the texture. The only parameter currently available is
+    EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, which allows the subresource id of
+    the texture that will be used to be specified. If this attribute is not
+    explicitly specified, it will default to the value of 0.
+
+    It is the responsibility of the application to perform any synchronization
+    between the insertion of the frame into the stream and the use of the
+    consumer textures output by the stream. The EGL_CONSUMER_LATENCY_USEC_KHR
+    attribute will have no effect on the function of the implementation of this
+    extension, but can still be used for communication between components of
+    the application.
+
+    The implementation will hold a reference to the D3D11 texture object if the
+    insertion is successful and will release the texture object when a new frame
+    is inserted or when the stream is destroyed.
+
+    On failure, eglStreamInsertD3DTextureNV12 returns EGL_FALSE and generates an
+    error.
+
+        - EGL_BAD_STATE is generated if <stream> is not in the state
+          EGL_STREAM_STATE_EMPTY_KHR, EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR,
+          or EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR.
+
+        - EGL_BAD_MATCH is generated if the stream is not associated with a
+          D3D11 NV12 texture producer.
+
+        - EGL_BAD_PARAMETER is generated if <texture> is not owned by the
+          queried device, is not in the format DXGI_FORMAT_NV12, is not
+          compatible with the implementation, or if the specified value for
+          EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE is not a valid subresource id for
+          the texture.
+
+        - EGL_BAD_STREAM_KHR is generated if <stream> is not a valid EGLStream.
+
+        - EGL_BAD_ATTRIBUTE is generated if an attribute other than
+          EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE is specified in <attrib_list>.
+
+Revision History
+
+    #1 (April 6, 2016) Ian Ewell
+        - initial draft
\ No newline at end of file
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_surface_orientation.txt b/src/third_party/angle/extensions/EGL_ANGLE_surface_orientation.txt
new file mode 100644
index 0000000..c6e3b27
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_surface_orientation.txt
@@ -0,0 +1,133 @@
+Name
+
+    ANGLE_surface_orientation
+
+Name Strings
+
+    EGL_ANGLE_surface_orientation
+
+Contributors
+
+    Geoff Lang, Google
+
+Contacts
+
+    Geoff Lang, Google (geofflang 'at' google 'dot' com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, 2015-12-15
+
+Number
+
+    EGL Extension XXX
+
+Extension Type
+
+    EGL display extension
+
+Dependencies
+
+    Written based on the wording of the EGL 1.5 Specification
+    (August 7 2014).
+
+Overview
+
+    This extension provides a mechanism for querying the most optimal
+    orientation of a window surface and creating window sufraces with
+    non-default orientations for the most performant rendering.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    New EGLConfig bitmask attribute name:
+
+        EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
+
+    Accepted as an attribute name in the <attrib_list> argument of
+    eglCreateWindowSurface and attribute name in the <attribute>
+    argument of eglQuerySurface:
+
+        EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
+
+    Valid bitfields in the EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE bitmask
+    attribute of EGLConfig and EGL_SURFACE_ORIENTATION_ANGLE bitmask attribute
+    of eglCreateWindowSurface:
+
+        EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
+        EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
+
+Additions to the EGL Specification
+
+    Additions to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors)
+
+    Add to table 3.1 (EGLConfig Attributes)
+
+    Attribute                              Type     Notes
+    -------------------------------------  -------  ----------------------
+    EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE  bitmask  Optimal window surface
+                                                    orientation.
+
+
+    Add a paragraph to section 3.4, section Other EGLConfig Attribute
+    Descriptions.
+
+    "EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE is a mask indicating which
+    window surface orientation will provide the best performance."
+
+    Add to table 3.4 (Default values and match criteria for EGLConfig
+    attributes):
+
+    Attribute                              Default  Selection  Sort     Sort
+                                                    Criteria   Order    Priority
+    -------------------------------------  -------  ---------  -------  --------
+    EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE  0        Exact      None
+
+    Add a paragraph to section 3.5.1, section Creating On-Screen Rendering
+    Surfaces.
+
+    EGL_SURFACE_ORIENTATION_ANGLE attribute specifies how the surface's content
+    will appear on the screen. If its value contains
+    EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE then all displayed content will be
+    inverted along the vertical axis. Similarly, if its value contains
+    EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE then all displayed content will be
+    inverted along the horizontal axis.
+
+    Add to table 3.5 (Queryable surface attributes and types):
+
+    Attribute                      Type     Description
+    -----------------------------  -------  ----------------------
+    EGL_SURFACE_ORIENTATION_ANGLE  bitmask  Orientation of surface
+
+    Add a paragraph to section 3.5.6, Surface Attributes:
+
+    "Querying EGL_SURFACE_ORIENTATION_ANGLE returns the orientation of the
+    surface.  For a window surface, this is the same attribute value specified
+    when the surface was created.  For other types of surfaces, it is always
+    0."
+
+Issues
+
+    1) What about dirty regions and sub regions specified by extensions such as
+       NV_post_sub_buffer?
+
+       These regions will be applied to the same region of the window as
+       before because they are often specified based on events from the
+       operating system.  The content in these regions will be displayed
+       according to the value of EGL_SURFACE_ORIENTATION_ANGLE.
+
+Revision History
+
+    Version 1, 2015-12-15 (Geoff Lang)
+      - Initial draft
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_window_fixed_size.txt b/src/third_party/angle/extensions/EGL_ANGLE_window_fixed_size.txt
new file mode 100644
index 0000000..e4c1ac3
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_window_fixed_size.txt
@@ -0,0 +1,136 @@
+Name
+
+    ANGLE_window_fixed_size
+
+Name Strings
+
+    EGL_ANGLE_window_fixed_size
+
+Contributors
+
+    John Bauman
+    Shannon Woods
+
+Contacts
+
+    John Bauman, Google Inc. (jbauman 'at' google.com)
+
+Status
+
+    Complete
+
+Version
+
+    Version 4, February 24, 2014
+
+Number
+
+    EGL Extension #??
+
+Dependencies
+
+    This extension is written against the wording of the EGL 1.4
+    Specification.
+
+Overview
+
+    This extension allows creating a window surface with a fixed size that is
+    specified when it is created.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted by the <attribute> parameter of eglQuerySurface and by the
+    <attrib_list> parameter of eglCreateWindowSurface:
+
+    EGL_FIXED_SIZE_ANGLE        0x3201
+
+Additions to Chapter 3 of the EGL 1.4 Specification:
+
+    Modify the third paragraph of Section 3.5.1 (Creating On-Screen Rendering Surfaces)
+
+    "<attrib_list> specifies a list of attributes for the window. The list has
+    the same structure as described for eglChooseConfig.  Attributes that can
+    be specified in <attrib_list> include EGL_RENDER_BUFFER,
+    EGL_VG_COLORSPACE, EGL_VG_ALPHA_FORMAT, EGL_FIXED_SIZE_ANGLE, EGL_WIDTH,
+    and EGL_HEIGHT."
+
+    Add before the last paragraph of Section 3.5.1
+
+    "EGL_FIXED_SIZE_ANGLE specifies whether the surface must be resized by the
+    implementation when the native window is resized.  The default value is
+    EGL_FALSE.  Its value can be EGL_TRUE, in which case the size must be
+    specified when the window is created, or EGL_FALSE, in which case the size
+    is taken from the native window. Its default value is EGL_FALSE.
+
+    If the value of EGL_FIXED_SIZE_ANGLE is EGL_TRUE, the window surface's
+    size in pixels is specified by the EGL_WIDTH and EGL_HEIGHT attributes,
+    and will not change throughout the lifetime of the surface. If its value
+    is EGL_FALSE, then the values of EGL_WIDTH and EGL_HEIGHT are ignored and
+    the window surface must be resized by the implementation subsequent to the
+    native window being resized, and prior to copying its contents to the
+    native window (e.g. in eglSwapBuffers, as described in section 3.9.1.1).
+    The default values for EGL_WIDTH and EGL_HEIGHT are zero. If the value
+    specified for either of EGL_WIDTH or EGL_HEIGHT is less than zero then an
+    EGL_BAD_PARAMETER error is generated."
+
+    Add the following entry to Table 3.5
+    (Queryable surface attributes and types)
+
+    Attribute            Type    Description
+    -------------------- ------- ---------------------------------------------
+    EGL_FIXED_SIZE_ANGLE boolean Surface will not be resized with a native
+                                 window
+
+    Replace the last paragraph on page 37 in Section 3.5.6 (Surface Attributes)
+
+    "Querying EGL_WIDTH and EGL_HEIGHT returns respectively the width and
+    height, in pixels, of the surface. For a pixmap surface or window surface
+    with EGL_FIXED_SIZE_ANGLE set to EGL_FALSE, these values are initially
+    equal to the width and height of the native window or pixmap with respect
+    to which the surface was created. If the native window is resized and the
+    corresponding window surface is not fixed size, the corresponding window
+    surface will eventually be resized by the implementation to match (as
+    discussed in section 3.9.1). If there is a discrepancy because EGL has not
+    yet resized the window surface, the size returned by eglQuerySurface will
+    always be that of the EGL surface, not the corresponding native window."
+
+    Add the following paragraph to Section 3.5.6 (Surface Attributes)
+
+    "Querying EGL_FIXED_SIZE_ANGLE returns EGL_FALSE if the surface will be
+    resized to match a native window, and EGL_TRUE if the surface cannot be
+    resized."
+
+    Alter the beginning of the first paragraph of Section 3.9.1.1 (Native
+    Window Resizing)
+
+    "If <surface> does not have EGL_FIXED_SIZE_ANGLE set and the native window
+    corresponding to <surface> has been resized prior to the swap, <surface>
+    must be resized to match."
+
+Issues
+
+    1. Should there be a way to resize a window surface that had its size
+    specified initially.
+
+    RESOLVED: No. Surfaces that have their sizes specified initially must have
+    EGL_FIXED_SIZE_ANGLE set and can never be resized.
+
+Revision History
+
+    Version 4, 2014/02/24 - formatting changes.
+
+    Version 3, 2014/02/12 - ignore EGL_WIDTH and EGL_HEIGHT if
+    EGL_FIXED_SIZE_ANGLE is EGL_FALSE
+
+    Version 2, 2014/02/07 - rename to EGL_ANGLE_window_fixed_size, and add an
+    EGL_FIXED_SIZE_ANGLE token.
+
+    Version 1, 2014/02/05 - first draft.
diff --git a/src/third_party/angle/extensions/EGL_ANGLE_x11_visual.txt b/src/third_party/angle/extensions/EGL_ANGLE_x11_visual.txt
new file mode 100644
index 0000000..d77561e
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_ANGLE_x11_visual.txt
@@ -0,0 +1,106 @@
+Name
+
+    ANGLE_x11_visual
+
+Name Strings
+
+    EGL_ANGLE_x11_visual
+
+Contributors
+
+    Corentin Wallez, Google
+    Shannon Woods, Google
+    Jamie Madill, Google
+    Geoff Lang, Google
+
+Contacts
+
+    Corentin Wallez, Google (cwallez 'at' chromium 'dot' org)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, 2015-11-13
+
+Number
+
+    EGL Extension XXX
+
+Extension Type
+
+    EGL client extension
+
+Dependencies
+
+    Requires EGL_EXT_client_extensions to query its existence without
+    a display.
+
+    Requires EGL_EXT_platform_base.
+
+    This extension is written against the wording of version 9 of the
+    EGL_EXT_platform_base specification.
+
+    Written based on the wording of the EGL 1.5 Specification
+    (August 7 2014).
+
+Overview
+
+    This extension allows passing the X11 visual ID used by the native
+    EGL surface types at display creation time. This will restrict
+    EGLSurfaces to be created from native types with this visual ID,
+    which may allow the created display to be more compatible and
+    performant.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as an attribute name in the <attrib_list> argument of
+    eglGetPlatformDisplayEXT:
+
+        EGL_X11_VISUAL_ID_ANGLE 0x33A3
+
+Additions to the EGL Specification
+
+    Modify section 3.5.1 (Creating On-Screen Rendering Surfaces), p. 34
+
+    Append the following to the errors of CreateWindowSurface:
+
+    "If an X11 visual was specified at display creation time using
+    EGL_ANGLE_X11_VISUAL_ID that is not equal to the ID of the
+    native_window's visual, an EGL_BAD_MATCH error is generated and
+    EGL_NO_SURFACE is returned."
+
+New Behavior
+
+    To request a display created with a X11 visual ID, the value of
+    EGL_ANGLE_X11_VISUAL_ID should be set to a valid X11 visual ID. If
+    present, this ID will be used during display creation to make a
+    display that is more compatible and potentially more performant when
+    used with EGLsurfaces created from native types with this ID. If the
+    visual ID passed isn't a valid visual ID, eglGetPlatformDisplay will
+    return EGL_NO_DISPLAY and generate an EGL_NOT_INITIALIZED error.
+
+Issues
+
+    1) When the hint is present, should EGLsurface creation functions
+       only accept native types with the hint's visual ID?
+
+       RESOLVED: Yes, generate an error when the visual of the native
+       surface doesn't match. This will avoid having hidden performance
+       or compatibility losses when using this extension.
+
+Revision History
+
+    Version 1, 2015-11-13 (Corentin Wallez)
+      - Initial draft
+
diff --git a/src/third_party/angle/extensions/EGL_CHROMIUM_create_context_bind_generates_resource.txt b/src/third_party/angle/extensions/EGL_CHROMIUM_create_context_bind_generates_resource.txt
new file mode 100644
index 0000000..b34ce82
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_CHROMIUM_create_context_bind_generates_resource.txt
@@ -0,0 +1,87 @@
+Name
+
+    CHROMIUM_create_context_bind_generates_resource
+
+Name Strings
+
+    EGL_CHROMIUM_create_context_bind_generates_resource
+
+Contributors
+
+    Geoff Lang
+
+Contacts
+
+    Geoff Lang (geofflang 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, September 21, 2016
+
+Number
+
+    EGL Extension #??
+
+Dependencies
+
+    Requires EGL 1.4.
+
+    Written against the EGL 1.4 specification.
+
+    This spec interacts with GL_CHROMIUM_bind_generates_resource (or
+    equivalent) extension.
+
+Overview
+
+    This extension allows the creation of an OpenGL or OpenGL ES context that
+    allows or disallows implicit creation of OpenGL resources on bind.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    Accepted as an attribute name in the <*attrib_list> argument to
+    eglCreateContext:
+
+        EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
+
+Additions to the EGL 1.4 Specification
+
+    Add the following to section 3.7.1 "Creating Rendering Contexts":
+
+    EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM indicates whether the context
+    should be created with the GL_BIND_GENERATES_RESOURCE_CHROMIUM state
+    initialized to GL_TRUE or GL_FALSE. The default value of
+    EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM is EGL_TRUE.
+
+Errors
+
+    None
+
+New State
+
+    None
+
+Conformance Tests
+
+    TBD
+
+Issues
+
+    None
+
+Revision History
+
+    Rev.    Date         Author     Changes
+    ----  -------------  ---------  ----------------------------------------
+      1   Sept 21, 2016  geofflang  Initial version
diff --git a/src/third_party/angle/extensions/EGL_CHROMIUM_get_sync_values.txt b/src/third_party/angle/extensions/EGL_CHROMIUM_get_sync_values.txt
new file mode 100644
index 0000000..d95b348
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_CHROMIUM_get_sync_values.txt
@@ -0,0 +1,131 @@
+Name
+
+   CHROMIUM_get_sync_values
+
+Name Strings
+
+   EGL_CHROMIUM_get_sync_values
+
+Contact
+
+   Stéphane Marchesin, Google (marcheu 'at' google.com)
+
+Status
+
+   Draft.
+
+Version
+
+   Last Modified Date: N/A   Revision: 1.0
+
+   Based on GLX_OML_sync_control Revision 6.0
+
+Number
+
+   ???
+
+Dependencies
+
+   The extension is written against the EGL 1.2 Specification, although it
+   should work on other versions of these specifications. This extension
+   also requires an operating system which supports CLOCK_MONOTONIC.
+
+Overview
+
+   This extension provides counters which let applications know about the
+   timing of the last vertical retrace. By looking at the system clock, as
+   well as the refresh rate of the monitor, this should enable applications
+   to predict the position of future retraces so as to schedule an optimal
+   workload.
+
+   This extension incorporates the use of three counters that provide
+   the necessary synchronization. The Unadjusted System Time (or UST)
+   is the 64-bit CLOCK_MONOTONIC clock; in particular this lets the
+   application schedule future vertical retraces by querying this clock.
+   The graphics Media Stream Counter (or graphics MSC) is a counter
+   that is unique to the graphics subsystem and increments for each
+   vertical retrace that occurs. The Swap Buffer Counter (SBC) is an
+   attribute of an EGLSurface and is incremented each time a swap
+   buffer action is performed on the associated surface.
+
+   The use of these three counters allows the application to
+   synchronize graphics rendering to vertical retraces and/or swap
+   buffer actions. For example, by querying the synchronization values for
+   a given surface, the application can accurately predict the timing for
+   the next vertical retraces and schedule rendering accordingly.
+
+Issues
+
+   None.
+
+IP Status
+
+   No known issues.
+
+New Procedures and Functions
+
+   Bool eglGetSyncValuesCHROMIUM(EGLDisplay dpy,
+                                 EGLSurface surface,
+                                 int64_t* ust,
+                                 int64_t* msc,
+                                 int64_t* sbc)
+
+
+New Tokens
+
+   None
+
+Additions to the EGL 1.3 Specification
+
+   eglGetSyncValuesCHROMIUM returns the current UST/MSC/SBC triple. A UST
+   timestamp is obtained each time the graphics MSC is incremented.
+   If this value does not reflect the value of the UST at the time the
+   first scan line of the display begins passing through the video
+   output port, it will be adjusted by the graphics driver to do so
+   prior to being returned by any of the functions defined by this
+   extension.
+
+   This UST timestamp, together with the current graphics MSC and the
+   current SBC, comprise the current UST/MSC/SBC triple. The UST,
+   graphics MSC, and SBC values are not part of the render context
+   state. These values cannot be pushed or popped. The graphics MSC
+   value is initialized to 0 when the graphics device is initialized.
+   The SBC is per-surface state and is initialized to 0 when the
+   EGLSurface data structure is initialized.
+
+   The SBC value is incremented by the graphics driver at the completion
+   of each buffer swap (e.g., the pixel copy has been completed or the
+   hardware register that swaps memory banks has been written). For pixel
+   formats that do not contain a back buffer, the SBC will always be
+   returned as 0.
+
+   The graphics MSC value is incremented once for each screen refresh.
+   For a non-interlaced display, this means that the graphics MSC value
+   is incremented for each frame. For an interlaced display, it means
+   that it will be incremented for each field. For a multi-monitor
+   system, the monitor used to determine MSC is the one where the surface
+   is located. If the surface spans multiple monitors, the monitor used
+   to determine MSC is the one with the biggest coverage in pixels.
+
+   The function eglGetSyncValuesCHROMIUM will return TRUE if the function
+   completed successfully, FALSE otherwise.
+
+   Each time eglSwapBuffer succeeds, the SBC will be increased within a
+   finite time period.
+
+Errors
+
+   eglGetSyncValuesCHROMIUM will return FALSE if there is no current
+   EGLContext.
+
+New State
+
+   Get Value                 Get Command            Type    Initial Value
+   ---------                 -----------            ----    -------------
+     [UST]             eglGetSyncValuesCHROMIUM      Z      unspecified
+     [MSC]             eglGetSyncValuesCHROMIUM      Z                  0
+     [SBC]             eglGetSyncValuesCHROMIUM      Z                  0
+
+New Implementation Dependent State
+
+   None
diff --git a/src/third_party/angle/extensions/EGL_EXT_device_query.txt b/src/third_party/angle/extensions/EGL_EXT_device_query.txt
new file mode 100644
index 0000000..d92fb6d
--- /dev/null
+++ b/src/third_party/angle/extensions/EGL_EXT_device_query.txt
@@ -0,0 +1,188 @@
+Name
+
+    EXT_device_query
+
+Name Strings
+
+    EGL_EXT_device_query
+
+Contributors
+
+    James Jones, NVIDIA  (jajones 'at' nvidia.com)
+    Jamie Madill, Google  (jmadill 'at' google.com)
+
+Contacts
+
+    Jamie Madill, Google  (jmadill 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1 - Mar 25rd, 2015
+
+Number
+
+    EGL Extension #XXX
+
+Extension Type
+
+    EGL client extension
+
+Dependencies
+
+    Written against the wording of EGL 1.5.
+
+    Requires EGL 1.5 or an earlier verison of EGL with the
+    EGL_EXT_client_extensions extension.
+
+Overview
+
+    Increasingly, EGL and its client APIs are being used in place of
+    "native" rendering APIs to implement the basic graphics
+    functionality of native windowing systems.  This creates demand
+    for a method to access native GPU or device objects directly
+    rather than calling EGL or GL entry points.
+
+    This extension defines the method for an application to query
+    native device objects from an EGL Display.
+
+New Types
+
+    This is the type of a handle that represents an EGLDeviceEXT
+    object.
+
+        typedef void* EGLDeviceEXT;
+
+    If EGL 1.5 is not supported, the following type is added, as
+    defined in the EGL 1.5 specification:
+
+        typedef intptr_t EGLAttrib;
+
+New Functions
+
+    EGLBoolean eglQueryDeviceAttribEXT(EGLDeviceEXT device,
+                                       EGLint attribute,
+                                       EGLAttrib *value);
+
+    const char *eglQueryDeviceStringEXT(EGLDeviceEXT device,
+                                        EGLint name);
+
+    EGLBoolean eglQueryDisplayAttribEXT(EGLDisplay dpy,
+                                        EGLint attribute,
+                                        EGLAttrib *value);
+
+New Tokens
+
+    Functions with a return type of EGLDeviceEXT will return this
+    value on failure:
+
+        EGL_NO_DEVICE_EXT                      ((EGLDeviceEXT)0)
+
+    This error value will be generated by functions that take an
+    EGLDeviceEXT object as a parameter:
+
+        EGL_BAD_DEVICE_EXT                     0x322B
+
+    Accepted by the <attribute> parameter of
+    eglQueryDisplayAttribEXT:
+
+        EGL_DEVICE_EXT                         0x322C
+
+Add a new section "2.1.2 Devices" after "2.1.1 Scalar Types"
+
+    All EGL operations occur on an EGLDeviceEXT.  However, devices
+    themselves expose no functionality.  They are simple abstract
+    objects that exist only for the sake of enumeration and
+    defining a namespace.
+
+Modify the last sentence of section "2.1.3" Displays" to read:
+
+    Besides devices, objects are always specified by the combination
+    of an EGLDisplay parameter with a parameter representing the
+    handle of the object.
+
+Add a new extension type to the list in section "2.8 Extensions"
+
+    Device Extensions
+        A *device extension* adds functionality to an individual
+        EGLDeviceEXT.  Different instances of EGLDeviceEXT may support
+        different sets of device extensions
+
+Add a new error to section "3.1 Errors"
+
+    EGL_BAD_DEVICE_EXT
+        An EGLDeviceEXT argument does not refer to a valid
+        EGLDeviceEXT.  Any command taking an EGLDeviceEXT parameter
+        may generate this error.
+
+Add a section "3.2 Devices" after "3.1 Errors"
+
+    To query the properties of a device, use:
+
+        EGLBoolean eglQueryDeviceAttribEXT(EGLDeviceEXT device,
+                                           EGLint attribute,
+                                           EGLAttrib *value);
+
+    On success, EGL_TRUE is returned and the requested attribute value
+    is returned in <value>.  Currently there are no valid values of
+    <attribute> defined.
+
+    On failure, EGL_FALSE is returned.  An EGL_BAD_ATTRIBUTE error is
+    generated if <attribute> is not a valid attribute.  An
+    EGL_BAD_DEVICE_EXT error is generated if <device> is not a valid
+    EGLDeviceEXT.
+
+        const char *eglQueryDeviceStringEXT(EGLDeviceEXT device,
+                                            EGLint name);
+
+    returns a pointer to a static, zero-terminated string describing
+    some aspect of the specified EGLDeviceEXT.  <name> must be
+    EGL_EXTENSIONS.
+
+    The EGL_EXTENSIONS string describes which device extensions are
+    supported by <device>.  The string is of the same format specified
+    for display and client extension strings in section 3.4. Note that
+    device extensions are properties of the device, and are distinct
+    from other extension strings.
+
+    On failure, NULL is returned.  An EGL_BAD_DEVICE_EXT error is
+    generated if <device> is not a valid EGLDeviceEXT.  An
+    EGL_BAD_PARAMETER error is generated if <name> is not one of the
+    values described above.
+
+Add a section "3.4 Display Attributes" after "3.3 EGL Versioning"
+
+    To query attributes of an initialized display, use:
+
+        EGLBoolean eglQueryDisplayAttribEXT(EGLDisplay dpy,
+                                            EGLint name,
+                                            EGLAttrib *value);
+
+    On success, EGL_TRUE is returned.  If <name> is EGL_DEVICE_EXT,
+    the EGLDeviceEXT associated with <dpy> is returned in <value>.
+    All displays have an associated EGLDeviceEXT, regardless of how
+    they were created.  A successful query of EGL_DEVICE_EXT will
+    never return EGL_NO_DEVICE_EXT.
+
+    On failure, EGL_FALSE is returned.  An EGL_NOT_INITIALIZED error
+    is generated if EGL is not initialized for <dpy>.  An
+    EGL_BAD_ATTRIBUTE error is generated if <name> is not a valid
+    value.
+
+    Because the EGLDeviceEXT is a property of <dpy>, any use of an
+    associated EGLDeviceEXT after <dpy> has been terminated gives
+    undefined results. Querying an EGL_DEVICE_EXT from <dpy> after a
+    call to eglTerminate() (and subsequent re-initialization) may
+    return a different value.
+
+Issues
+
+    None.
+
+Revision History:
+
+    #1  (Mar 25rd, 2015) Jamie Madill
+        - Initial Draft based on EGL_EXT_device_base
diff --git a/src/third_party/angle/extensions/EXT_blend_func_extended.txt b/src/third_party/angle/extensions/EXT_blend_func_extended.txt
new file mode 100644
index 0000000..13f93e6
--- /dev/null
+++ b/src/third_party/angle/extensions/EXT_blend_func_extended.txt
@@ -0,0 +1,771 @@
+Name
+
+    EXT_blend_func_extended
+
+Name Strings
+
+    GL_EXT_blend_func_extended
+
+Contact
+
+    Mark Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com)
+
+Contributors
+
+    Daniel Koch, NVIDIA
+    Slawomir Grajewski, Intel
+    Chris Dalton, NVIDIA
+    Brian Salomon, Google
+
+    From ARB_blend_func_extended...
+
+    Graham Sellers, AMD
+    Mark Young, AMD
+    Nick Haemel, AMD
+    Pierre Boudier, AMD
+    Mais Alnasser, AMD
+    Jeff Bolz, NVIDIA
+    Pat Brown, NVIDIA
+    Ian Stewart, NVIDIA
+    Jon Leech, Khronos
+
+Status
+
+    Draft, almost complete
+
+Version
+
+    Last Modified Date:         July 29, 2015
+    Revision:                   5
+
+Number
+
+    XXX
+
+Dependencies
+
+    This extension is written against the OpenGL ES 3.1 (June 4, 2014)
+    specification, but can apply to earlier versions back to ES 2.0.
+
+    GLSL version 300 and 310 language is written against The OpenGL ES
+    Shading Language (July 11, 2012).
+
+    GLSL version 100 language is written against The OpenGL ES Shading
+    Language (May 12, 2009).
+
+    The NV_draw_buffers and EXT_draw_buffers extensions trivially affect
+    the definition of this extension.
+
+    The EXT_draw_buffers_indexed extension affects the definition of
+    this extension.
+
+Overview
+
+    This extension provides an ES version of the ARB_blend_func_extended
+    functionality.
+
+    Traditional OpenGL includes fixed-function blending that combines
+    source colors with the existing content of a render buffer in
+    a variety of ways.  A number of extensions have enhanced this
+    functionality by adding further sources of blending weights and
+    methods to combine them. However, the inputs to the fixed-function
+    blending units are constrained to a source color (as output from
+    fragment shading), destination color (as the current content of the
+    frame buffer) or constants that may be used in their place.
+
+    This extension adds new blending functions whereby a fragment
+    shader may output two colors, one of which is treated as the
+    source color, and the other used as a blending factor for either
+    source or destination colors.  Furthermore, this extension increases
+    orthogonality by allowing the SRC_ALPHA_SATURATE function to be used
+    as the destination weight.
+
+    Because of the limitations of the OpenGL ES 2.0 shading language,
+    new built-in variables (gl_SecondaryFragColorEXT,
+    gl_SecondaryFragDataEXT) are added to the ES 1.00 shading language
+    rather than introduce more complex features for user-defined fragment
+    outputs.  Because such built-in variable are deprecated in ES 3.0,
+    these variables are NOT available in the OpenGL ES 3.xx shading
+    language verisons.
+
+IP Status
+
+    No known IP claims.
+
+New Procedures and Functions
+
+    void BindFragDataLocationIndexedEXT(uint program, uint colorNumber,
+                                        uint index, const char * name);
+
+    int GetFragDataIndexEXT(uint program, const char * name);
+
+    void BindFragDataLocationEXT(uint program, uint colorNumber, const char * name)
+
+    int GetProgramResourceLocationIndexEXT(uint program, enum programInterface, const char *name);
+
+New Tokens
+
+    Accepted by the <src> and <dst> parameters of BlendFunc and
+    BlendFunciEXT, and by the <srcRGB>, <dstRGB>, <srcAlpha> and <dstAlpha>
+    parameters of BlendFuncSeparate and BlendFuncSeparateiEXT:
+
+        SRC1_COLOR_EXT                                  0x88F9
+        SRC1_ALPHA_EXT                                  0x8589  // OpenGL 1.5 token value
+        ONE_MINUS_SRC1_COLOR_EXT                        0x88FA
+        ONE_MINUS_SRC1_ALPHA_EXT                        0x88FB
+        SRC_ALPHA_SATURATE_EXT                          0x0308
+
+    Accepted in the <props> array of GetProgramResourceiv:
+
+        LOCATION_INDEX_EXT                              0x930F
+
+    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
+    and GetFloatv:
+
+        MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT                0x88FC
+
+Additions to Chapter 7 of the OpenGL ES 3.1 Specification (Programs and
+Shaders)
+
+   Add a row to table 7.2 "GetProgramResourceiv properties and supported
+   interfaces" (page 82):
+
+   Property            Supported Interfaces
+   ------------------  --------------------
+   LOCATION_INDEX_EXT  PROGRAM_OUTPUT
+
+   Modify section 7.3.1.1 "Naming Active Resources" subsection to include
+   after the LOCATION paragraph (page 84):
+
+   "For the property LOCATION_INDEX_EXT, a single integer identifying the
+   fragment color index of an active fragment shader output variable
+   is written to params. If the active variable is not an output for a
+   fragment shader, the value -1 will be written to params."
+
+   Modify (page 87) the paragraph introducing GetProgramResourceLocation
+   to begin:
+
+   "The commands
+
+        int GetProgramResourceLocation( uint program,
+            enum programInterface, const char *name );
+        int GetProgramResourceLocationIndexEXT( uint program,
+            enum programInterface, const char *name );
+
+    return the location or the fragment color index, respectively,
+    assigned to the variable named name in interface programInterface
+    of program object program."
+
+    Change the ending of the same paragraph to read:
+
+    "For GetProgramResourceLocationIndexEXT, programInterface must be
+    PROGRAM_OUTPUT. The value -1 will be returned by either command if
+    an error occurs, if name does not identify an active variable on
+    programInterface, or if name identifies an active variable that
+    does not have a valid location assigned, as described above. The
+    locations returned by these commands are the same locations returned
+    when querying the LOCATION and LOCATION_INDEX resource properties."
+
+    Change the next paragaph to begin:
+
+    "A string provided to GetProgramResourceLocation or
+    GetProgramResourceLocationIndexEXT is considered to match an active
+    variable if ..."
+
+    Change the last paragraph of the section (page 88) to read:
+
+    ... "If the string specifies an element of an array variable,
+    GetProgramResourceLocation and GetProgramResourceLocationIndexEXT
+    return the location or fragment color index assigned to that
+    element. If it specifies the base name of an array, it identifies
+    the resources associated with the first element of the array."
+
+Additions to Chapter 14 of the OpenGL ES 3.1 Specification (Programmable
+Fragment Processing)
+
+    Modify section 14.2.3 "Shader Outputs" subsection to include:
+
+    "The binding of a user-defined varying out variable to a fragment color number
+    can be specified explicitly. The command
+
+        void BindFragDataLocationIndexedEXT(uint program, uint colorNumber,
+                                            uint index, const char * name);
+
+    specifies that the varying out variable name in <program> should
+    be bound to fragment color <colorNumber> when the program is next
+    linked. <index> may be zero or one to specify that the color
+    be used as either the first or second color input to the blend
+    equation, respectively, as described in Section 15.1.5 (Blending).
+    If <name> was bound previously, its assigned binding is replaced
+    with colorNumber. <name> must be a null-terminated string. The error
+    INVALID_VALUE is generated if <colorNumber> is equal or greater
+    than the value of MAX_DRAW_BUFFERS and <index> is zero,
+    or if <colorNumber> is equal or greater than the value of
+    MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT and <index> is greater than or
+    equal to one.  The command
+
+        void BindFragDataLocationEXT(uint program, uint colorNumber,
+                                     const char * name)
+
+    is equivalent to calling BindFragDataLocationIndexedEXT with the
+    same values for <program>, <colorNumber> and <name>, and with <index>
+    set to zero.
+
+    When a program is linked, any varying out variables without
+    a binding specified through BindFragDataLocationIndexedEXT or
+    BindFragDataLocationEXT will automatically be bound to fragment
+    colors and indices by the GL.  All such assignments will use color
+    indices of zero.  Such bindings can be queried using the commands
+    GetFragDataLocation and GetFragDataIndexEXT.  Output binding
+    assignments will cause LinkProgram to fail:
+
+      * if the number of active outputs is greater than the value of
+        MAX_DRAW_BUFFERS_EXT;
+
+      * if the program has an active output assigned to a location greater
+        than or equal to the value of MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT
+        and has an active output assigned an index greater than or equal
+        to one;
+
+      * if more than one varying out variable is bound to the same number
+        and index; or
+
+      * if the explicit binding assignments do not leave enough space
+        for the linker to automatically assign a location for a varying
+        out array, which requires multiple contiguous locations.
+
+    BindFragDataLocationIndexedEXT may be issued before any shader objects
+    are attached to a program object. Hence it is allowed to bind any
+    name (except a name starting with gl_) to a color number and index,
+    including a name that is never used as a varying out variable in
+    any fragment shader object.  Assigned bindings for variables that
+    do not exist are ignored."
+
+    Add to end of section:
+
+    "The command
+
+        int GetFragDataIndexEXT(uint program, const char * name);
+
+    returns the index of the fragment color to which the variable <name>
+    was bound when the program object <program> was last linked. If
+    program has not been successfully linked, the error INVALID_OPERATION
+    is generated. If name is not a varying out variable, or if an error
+    occurs, -1 will be returned.  The command is equivalent to
+
+        GetProgramResourceLocationIndex(program, PROGRAM_OUTPUT, name);"
+
+Additions to Chapter 15 of the OpenGL ES 3.1 Specification (Writing
+Fragments and Samples to the Framebuffer)
+
+    Modify section 15.1.5.2 "Blend Functions":
+
+    Change the first paragraph to read:
+
+    "The weighting factors used by the blend equation are determined by
+    the blend functions. There are four possible sources for weighting
+    factors. These are the constant color (Rc, Gc, Bc, Ac) (see
+    BlendColor, p. 211), the first source color (Rs0, Gs0, Bs0, As0),
+    the second source color (Rs1, Gs1, Bs1, As1), and the destination
+    color (the existing content of the draw buffer). Additionally the
+    special constants ZERO and ONE are available as weighting factors."
+
+    Modify Table 15.2 (RGB and ALPHA source and destination blend
+    functions ...) as follows
+
+                                                            RGB Blend Factors                   Alpha Blend Factors
+        Value                                               (Sr, Sg, Sb) or (Dr, Dg, Db)        Sa or Da
+        -----                                               ----------------------------        -------------------
+        ZERO                                                (0, 0, 0)                           0
+        ONE                                                 (1, 1, 1)                           1
+        SRC_COLOR                                           (Rs0, Gs0, Bs0)                     As0
+        ONE_MINUS_SRC_COLOR                                 (1, 1, 1) - (Rs0, Gs0, Bs0)         1 - As0
+        DST_COLOR                                           (Rd, Gd, Bd)                        Ad
+        ONE_MINUS_DST_COLOR                                 (1, 1, 1) - (Rd, Gd, Bd)            1 - Ad
+        SRC_ALPHA                                           (As0, As0, As0)                     As0
+        ONE_MINUS_SRC_ALPHA                                 (1, 1, 1) - (As0, As0, As0)         1 - As0
+        DST_ALPHA                                           (Ad, Ad, Ad)                        Ad
+        ONE_MINUS_DST_ALPHA                                 (1, 1, 1) - (Ad, Ad, Ad)            1 - Ad
+        CONSTANT_COLOR                                      (Rc, Gc, Bc)                        Ac
+        ONE_MINUS_CONSTANT_COLOR                            (1, 1, 1) - (Rc, Gc, Bc)            1 - Ac
+        CONSTANT_ALPHA                                      (Ac, Ac, Ac)                        Ac
+        ONE_MINUS_CONSTANT_ALPHA                            (1, 1, 1) - (Ac, Ac, Ac)            1 - Ac
+        SRC_ALPHA_SATURATE                                  (f, f, f)                           1                       New (for ES 2.x)
+        SRC1_COLOR_EXT                                      (Rs1, Gs1, Bs1)                     As1                     New
+        ONE_MINUS_SRC1_COLOR_EXT                            (1, 1, 1) - (Rs1, Gs1, Bs1)         1 - As1                 New
+        SRC1_ALPHA_EXT                                      (As1, As1, As1)                     As1                     New
+        ONE_MINUS_SRC1_ALPHA_EXT                            (1, 1, 1) - (As1, As1, As1)         1 - As1                 New
+
+    For ES 2.0, remove table's footnote saying (ES 3.x already has this
+    removed):
+
+        SRC_ALPHA_SATURATE is valid only for source RGB and alpha
+        blending functions.
+
+    Add the following subsections to Section 5.1.5 Blending, at the end
+    of the subsection 15.1.5.2 "Blend Functions":
+
+    "15.1.5.X  Dual Source Blending and Multiple Draw Buffers
+
+    Blend functions that require the second color input, <Rs1, Gs1, Bs1,
+    As1> (SRC1_COLOR_EXT, SRC1_ALPHA_EXT, ONE_MINUS_SRC1_COLOR_EXT, or
+    ONE_MINUS_SRC1_ALPHA_EXT) may consume hardware resources that could
+    otherwise be used for rendering to multiple draw buffers. Therefore,
+    the number of draw buffers that can be attached to a frame buffer
+    may be lower when using dual-source blending.
+
+    The maximum number of draw buffers that may be attached to a
+    single frame buffer when using dual-source blending functions is
+    implementation dependent and can be queried by calling GetIntegerv
+    with the symbolic constant MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT. When
+    using dual-source blending, MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT should be
+    used in place of MAX_DRAW_BUFFERS_EXT to determine the maximum number
+    of draw buffers that may be attached to a single frame buffer. The
+    value of MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT must be at least 1. If
+    the value of MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT is 1, then dual-source
+    blending and multiple draw buffers cannot be used simultaneously.
+
+    If either blend function is set to one of the second source factors
+    (SRC1_COLOR_EXT, SRC1_ALPHA_EXT, ONE_MINUS_SRC1_COLOR_EXT, or
+    ONE_MINUS_SRC1_ALPHA_EXT) for any draw buffer and any draw buffers
+    equal to or greater than the value of MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT
+    have values other than NONE, the error INVALID_OPERATION is generated
+    by drawing commands.
+
+    15.1.5.Y  Generation of Second Color Source for Blending
+
+    Rendering using any of the blend functions that consume the second
+    input color (SRC1_COLOR_EXT, ONE_MINUS_SRC1_COLOR_EXT, SRC1_ALPHA_EXT
+    or ONE_MINUS_SRC1_ALPHA_EXT) using a shader that does not output
+    a second source color will produce undefined results.  To produce
+    input for the second source color, a shader must be used that outputs
+    a second source color.
+
+    When using a GLSL version 300 es or higher fragment shader with
+    dual-source blending functions, the color output varyings are bound
+    to the first (index 0) and second (index 1) inputs of a draw buffer
+    using BindFragDataLocationIndexedEXT as described in the "Shader
+    Outputs" subsection of Section 3.12.2 or by layout qualifiers for
+    location=/n/ and index=/m/. Data written to the first of these outputs
+    becomes the first source color input to the blender (corresponding
+    to SRC_COLOR and SRC_ALPHA). Data written to the second of these
+    outputs generates the second source color input to the blender
+    (corresponding to SRC1_COLOR_EXT and SRC1_ALPHA_EXT).
+
+    Alternatively if the GLSL version 100 fragment shader is used (where
+    user-defined color outputs are unsupported, hence a user-defined
+    color output is not available for BindFragDataLocationIndexEXT), the
+    gl_FragColor and gl_SecondaryFragColorEXT fragment outputs correspond
+    to the first and second source color respectively.  Similarly the
+    gl_FragData and gl_SecondaryFragDataEXT fragment output arrays
+    correspond to the first and second source color respectively of each
+    color buffer output.
+
+    If the second color input to the blender is not written in the
+    shader, or if no output is bound to the second input of a blender,
+    the result of the blending operation is not defined.
+
+    Other shading languages may define similar methods for producing
+    the first and second color inputs to blending equations."
+
+Additions to the OpenGL ES Shading Language 1.00 Specification
+
+    Including the following line in a shader can be used to control the
+    language features described in this extension:
+
+      #extension GL_EXT_blend_func_extended : <behavior>
+
+    where <behavior> is as specified in section 3.4.
+
+    A new preprocessor #define is added to the OpenGL ES Shading Language:
+
+      #define GL_EXT_blend_func_extended 1
+
+    Modify paragraphs in section 7.2 "Fragment Shader Special Variables" as follows:
+
+    First paragraph, second sentence:
+
+    "Fragment shaders output values to the OpenGL ES pipeline using
+    the built-in variables gl_FragColor, gl_SecondaryFragColorEXT,
+    gl_FragData, and gl_SecondaryFragDataEXT, unless the discard keyword
+    is executed."
+
+    Second paragraph, first sentence:
+
+    "It is not a requirement for the fragment shader to write to
+    either gl_FragColor, gl_SecondaryFragColorEXT, gl_FragData, or
+    gl_SecondaryFragDataEXT."
+
+    Add after the fourth paragraph:
+
+    "Writing to gl_SecondaryFragColorEXT specifies a second fragment color
+    that will be used by the subsequent fixed functionality pipeline for
+    dual source blending. If subsequent fixed functionality consumes the
+    second fragment color and an execution of a fragment shader does
+    not write a value to gl_SecondaryFragColorEXT then the secondary
+    fragment color consumed is undefined."
+
+    Add after the fifth paragraph:
+    
+    "The variable gl_SecondaryFragDataEXT is an array. Writing to
+    gl_SecondaryFragDataEXT[n] specifies the secondary fragment data that
+    will be used by the subsequent fixed functionality pipeline for data n
+    for dual source blending. If subsequent fixed functionality consumes
+    secondary fragment data and an execution of a fragment shader does
+    not write a value to it, then the secondary fragment data consumed
+    is undefined."
+
+    Modify the sixth paragraph to read:
+
+    "If a shader statically assigns a value to gl_FragColor or
+    gl_SecondaryFragColorEXT, it may not assign a value to any
+    element of gl_FragData or gl_SecondaryFragDataEXT. If a shader
+    statically writes a value to any element of gl_FragData or
+    gl_SecondaryFragDataEXT, it may not assign a value to gl_FragColor
+    or gl_SecondaryFragColorEXT. That is, a shader may assign values to
+    either the set of gl_FragColor and gl_SecondaryFragColorEXT or the
+    set of gl_FragData and gl_SecondaryFragDataEXT, but not both."
+
+    Modify the eighth paragraph to read:
+
+    "If a shader executes the discard keyword, the fragment is discarded,
+    and the values of gl_FragColor, gl_SecondaryFragColorEXT, gl_FragData,
+    and gl_SecondaryFragDataEXT become irrelevant."
+
+    Add these built-in variable to the list "accessible from a fragment shader":
+
+        mediump vec4 gl_SecondaryFragColorEXT;
+        mediump vec4 gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT];
+
+    Add to section 7.4 "Built-In Constants" the following constant:
+
+        const mediump int gl_MaxDualSourceDrawBuffersEXT = 1;
+
+Additions to the OpenGL ES Shading Language 3.00 and 3.10 Specification
+
+    Including the following line in a shader can be used to control the
+    language features described in this extension:
+
+      #extension GL_EXT_blend_func_extended : <behavior>
+
+    where <behavior> is as specified in section 3.4.
+
+    A new preprocessor #define is added to the OpenGL ES Shading Language:
+
+      #define GL_EXT_blend_func_extended 1
+
+    Modify section 4.4.2 "Output Layout Qualifiers":
+
+    Change the second paragraph to read:
+
+    "Fragment shaders allow output layout qualifiers only on the interface
+    qualifier out. The layout qualifier identifier for fragment shader
+    outputs is:
+
+        layout-qualifier-id
+            location = integer-constant
+            index = integer-constant
+
+    Each of these qualifiers may appear at most once. If index is
+    specified, location must also be specified.  If index is not
+    specified, the value 0 is used."
+
+    Add an additional example to the end of the fourth paragraph's example:
+
+    "And,
+
+        layout(location = 3, index = 1) out vec4 factor;
+
+    will establish that the fragment shader output factor is copied out
+    to fragment color 3 as the second (index one) input to the blend
+    equation."
+
+    Change the first sentence of the second to last paragraph to read:
+
+    "If there is more than one fragment output, the location must
+    be specified for all outputs unless the EXT_blend_func_extended
+    extension is enabled in which case more than one unassigned fragment
+    output locations are allowed though they must be assigned to unique
+    locations assigned with glBindFragDataLocationIndexedEXT prior to
+    linking."
+
+    Add to section 7.4 "Built-In Constants" the following constant:
+
+        const mediump int gl_MaxDualSourceDrawBuffersEXT = 1;
+
+Dependencies on OpenGL ES 3.0
+
+    If OpenGL ES 3.0 or higher is not supported (meaning OpenGL ES 2.0
+    support only), remove all references to the functions:
+
+        BindFragDataLocationIndexedEXT
+        GetFragDataIndexEXT
+        BindFragDataLocationEXT
+        GetProgramResourceLocationIndexEXT
+
+    Also ignore the additions to chapters 7 and 14 and the paragraph in
+    section 15.1.5.Y related to GLSL version 300 es or higher.
+
+    When OpenGL ES 3.0 or higher, the "Additions to the OpenGL ES
+    Shading Language 1.00 Specification" applies to the version 100
+    shading language, but not later versions.
+
+Dependencies on OpenGL ES 3.1
+
+    If OpenGL ES 3.1 or higher is not supported (meaning OpenGL ES 3.0
+    or earlier), remove all references to the function
+
+        GetProgramResourceLocationIndexEXT
+
+    because program resource queries are added by ES 3.1.  
+
+    Also ignore the additions to chapter 7.
+
+Dependencies on EXT_draw_buffers or NV_draw_buffers
+
+    Using dual-source blending functions may consume additional outputs
+    from hardware shading units and therefore can reduce the number
+    of draw buffers that may be attached to a single frame buffer when
+    dual-source blending functions are enabled. In this case, the value
+    of MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT may be less than the value of
+    MAX_DRAW_BUFFERS_EXT. If EXT_draw_buffers or NV_draw_buffers is not
+    supported then the value of MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT must
+    be 1. Furthermore, the discussion in the subsection entitled "Dual
+    Source Blending and Multiple Draw Buffers" may be discarded.
+
+Dependencies on EXT_draw_buffers_indexed
+
+    If EXT_draw_buffers_indexed is not supported, all references to
+    BlendFunciEXT and BlendFuncSeparateiEXT should be removed. In this
+    case, the blend functions for all attached draw buffers will be the
+    same.
+
+Errors
+
+    The error INVALID_OPERATION is generated by Begin or any
+    procedure that implicitly calls Begin if any draw buffer has a
+    blend function requiring the second color input (SRC1_COLOR_EXT,
+    ONE_MINUS_SRC1_COLOR_EXT, SRC1_ALPHA_EXT or ONE_MINUS_SRC1_ALPHA_EXT),
+    and a framebuffer is bound that has more than the value of
+    MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT-1 active color attachments.
+
+New State
+
+    None
+
+    While no changes to table 20.12 (Pixel Operations) are strictly
+    necessary, new enumerations are supported for the BLEND_SRC_RGB,
+    BLEND_SRC_ALPHA, BLEND_DST_RGB, and BLEND_DST_ALPHA state to support
+    SRC1_COLOR_EXT, SRC1_ALPHA_EXT, ONE_MINUS_SRC1_COLOR_EXT, and
+    ONE_MINUS_SRC1_ALPHA_EXT (and for ES 2.0, SRC_ALPHA_SATURATE_EXT).
+
+New Implementation Dependent State
+
+    Get Value                        Type  Get Command     Minimum Value    Description             Sec.
+    ---------                        ----  -----------     -------------    -------------------     ------
+    MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT Z+    GetIntegerv     1                Maximum number of       15.1.5
+                                                                            active draw buffers
+                                                                            when using dual-source
+                                                                            blending
+
+Example Use Cases
+
+    There are several potential uses for this functionality. A first
+    example is in the implementation of sub-pixel accurate font rendering
+    algorithms.  Given a known layout of pixel elements (red, green
+    and blue components), coverage may be calculated independently for
+    each element and passed to the blender in the second source color
+    as a per-channel opacity. To use this mode, use the following blend
+    functions:
+
+        glBlendFunc(GL_SRC1_COLOR_EXT, GL_ONE_MINUS_SRC1_COLOR_EXT);
+
+    As a second example, consider a partially reflective colored glass
+    window.  It will attenuate light passing through it, and reflect
+    some of the light that strikes it. Using an appropriate combination
+    of functions, this effect may be simulated in a single pass using
+    only fixed-function blending hardware. In this case, the following
+    blend functions may be used:
+
+        glBlendFunc(GL_SRC_ALPHA, GL_SRC1_COLOR_EXT);
+
+Issues
+
+    0.  What should this extension be named?
+
+    RESOLVED:  EXT_blend_func_extended, matching the name of
+    ARB_blend_func_extended upon which this extension is based but
+    providing a multi-vendor extension for ES implementations.
+
+    1.  Is this extension compatible with the ARB_blend_func_extended
+    version?
+
+    RESOLVED:  Yes.  This extension is 100% functionally identical to
+    ARB_blend_func_extended but for the ES 2.x and 3.x APIs.
+
+    The token values are _EXT suffixed but have the same values as
+    the ARB_blend_func_extended tokens.
+
+    Philosophically if this extension is going for 100% parity and
+    functionality with ARB_blend_func_extended, it should simply add
+    all the stuff in ARB_blend_func_extended...
+
+    2.  Should the next commands be EXT suffixed?
+
+    RESOLVED:  Yes.  This is not an OES extension.
+
+    This means source code coming from a desktop environment should
+    call eglGetProcAddress on function names with the EXT suffix.
+    However because extension functions are called through function
+    pointers, this is only a minor change isolated to function pointer
+    initialization.
+
+    2.  Should this extension allow ES 2.0 contexts to use
+    GL_SRC_ALPHA_SATURATE for the destination blend function?
+
+    RESOLVED:  Yes, the ARB_blend_func_extended extension adds support
+    for using GL_SRC_ALPHA_SATURATE as the destination factor as "bonus"
+    functionality.
+
+    ES 3.x already allows GL_SRC_ALPHA_SATURATE for the destination
+    factor so this additional functionality is new only to ES 2.0 contexts
+    supporting this extension.
+
+    We expect no GPU hardware capable of dual-source blending to not
+    also support GL_SRC_ALPHA_SATURATE as the destination factor.
+
+    3.  Should this extension provide the glBindFragDataLocation and
+    glBindFragDataLocationIndexed functionality?
+
+    RESOLVED:  Yes.  With EXT suffixes.
+
+    4.  Should this really be OES_blend_func_extended?
+
+    RESOLVED:  Go with EXT is for expediency.
+
+    Additionally this extension supports functionality such
+    GL_SRC_ALPHA_SATURATE that all desktop GPU hardware is assumed to
+    have.  ES-only vendors might not want this in an OES extension.
+
+    The same could be said for the glBindFragDataLocation* functionality.
+
+    5.  Does this extension need an interaction with
+    OES_blend_equation_separate?
+
+    RESOLVED:  No, that's an ES 1.1 extension.  ES 2.0 and on all support
+    separate blend functions.
+
+    6.  Are there any OpenGL ES Shading Language interactions?
+
+    RESOLVED: Yes, to use this extension, a #extension line will be needed
+    in the shader requesting the EXT_blend_func_extended functionality.
+    Example:
+
+        #extension GL_EXT_blend_func_extended : require
+
+    The ARB_blend_func_extended functionality does NOT require a special
+    #extension line to use its functionality because the ARB version
+    relies on existing GLSL functionality that allows for multiple
+    fragment outputs as part of supporting multiple render targets.
+    In the ARB version, then glBindFragDataLocationIndexed can bind
+    these unassigned locations to different source output colors.
+    But GLSL OpenGL ES 3.00 and 3.10 both explicitly preclude more than
+    one fragment shader output with an unassigned location.  Hence a
+    #extension is needed to relax this error condition.  And then this
+    extension's glBindFragDataLocationIndexedEXT must be used to assign
+    locations as necessary.
+
+    7.  Can the indexed location be assigned explicitly in the shader?
+
+    RESOLVED:  Yes, for ES 3.x shaders where the GLSL ES 3.x supports
+    layout qualifiers.  ES 2.0 does not support the layout qualifier or
+    user-defined fragment outputs.
+
+    8.  Should both the layout qualifier mechanism and the
+    glBindFragDataLocationIndexed-style API for specifying the index of
+    a user-defined fragment shader output be supported?
+
+    RESOLVED:  Yes, both should be supported.  This makes it easier
+    for existing applications to port to ES 3.0 as both mechanisms are
+    available.
+    
+    FYI: The "layout(location=0,index=1)" type syntax for dual-source
+    blending was introduced to OpenGL in GLSL 3.30 and 4.00 in
+    conjunction with OpenGL 3.3 and 4.0 respectively.  The original
+    ARB_blend_func_extended was written with respect to OpenGL 3.2 and
+    intended to support dual-source blending without the need to extend
+    the GLSL language by instead supporting assignment if the fragment
+    output index via glBindFragDataLocationIndexed.
+
+    9.  How to support OpenGL ES 2.0 where user-defined fragment shader
+    outputs are not supported?
+
+    RESOLVED:  Introduce new gl_SecondaryFragColorEXT and
+    gl_SecondaryFragDataEXT built-in variables for specifying the second
+    source color.
+
+    These built-ins are only available in the ES 1.00 shader language
+    version.
+
+    It is important to provide an ES 2.0 mechanism because WebGL 1.0 is
+    based on ES 2.0.  Chrome's internal command buffer mechanism is also
+    based around ES 2.0 and Skia intends to use this extension.
+
+    This includes adding a gl_MaxDualSourceDrawBuffersEXT
+    implementation-dependent constant.
+
+    10. Does the version 100 syntax (gl_SecondaryFragColorEXT,
+    gl_SecondaryFragDataEXT) work in an ES 3.0 context?
+
+    RESOLVED:  Yes.  For compatibility reasons, an ES 3.0 context
+    advertising EXT_blend_func_extended must support the built-ins for
+    the fragment shader secondary color outputs.
+
+    11. How many elements should be in the gl_SecondaryFragDataEXT array?
+
+    RESOLVED: The gl_SecondaryFragDataEXT array should have as
+    many elements as the GLSL built-in implementation constant
+    gl_MaxDualSourceDrawBuffersEXT which should be the value of the
+    context's GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT implementation-dependent
+    constant.
+
+    This means the number of elements in gl_SecondaryFragDataEXT is
+    different than the number of gl_FragData elements.
+
+    12. What precision should the gl_SecondaryFragColorEXT and
+    gl_SecondaryFragDataEXT be?
+
+    RESOLVED:  mediump.  This is consistent with gl_FragColor and
+    gl_FragData.
+
+    13. Should gl_MaxDualSourceDrawBuffersEXT be exposed in both ES 2.0
+    (where it sizes the gl_SecondaryFragDataEXT array) and also 3.x
+    contexts (where there is no fixed-function array)?
+
+    RESOLVED:  Implementation-wise, it is easiest to expose this
+    implementation-dependent constant for all ES contexts.
+
+    As a practical matter, we don't expect any implementations will
+    advertise any value other than 1 for this constant.
+
+    Note:  There is no implementation-dependent GLSL constant comparable
+    to gl_MaxDualSourceDrawBuffersEXT in ARB_blend_func_extended
+    (or OpenGL 3.3/4.0 introducing the ARB_blend_func_extended
+    functionality).
+
+    14. Any more issues?
+
+    RESOLVED:  See the issues in the ARB_blend_func_extended
+    specification.  This extension resolves those issues to match the
+    ARB extension version.
+
+Revision History
+
+    Rev.    Date    Author     Changes
+    ----  --------  ---------  -----------------------------------------
+     1    05/22/15  mjk        Initial revision.
+     2    07/06/15  mjk        Proper ES 2.0 interactions; complete.
+     3    07/08/15  mjk        Feedback from Brian
+     4    07/08/15  mjk        Feedback from Daniel
+     5    07/29/15  mjk        ES 3.x contexts (as well as 2.0) expose
+                               gl_MaxDualSourceDrawBuffersEXT
diff --git a/src/third_party/angle/extensions/EXT_blend_minmax.txt b/src/third_party/angle/extensions/EXT_blend_minmax.txt
new file mode 100644
index 0000000..522ac20
--- /dev/null
+++ b/src/third_party/angle/extensions/EXT_blend_minmax.txt
@@ -0,0 +1,164 @@
+Name
+
+    EXT_blend_minmax
+
+Name Strings
+
+    GL_EXT_blend_minmax
+
+Version
+
+    Last Modified Date: September 17, 2009
+    Version:            1.5
+
+Number
+
+    OpenGL Extension #37
+    OpenGL ES Extension #65
+
+Dependencies
+
+    There is an interaction with OpenGL ES.
+
+Overview
+
+    Blending capability is extended by respecifying the entire blend
+    equation.  While this document defines only two new equations, the
+    BlendEquationEXT procedure that it defines will be used by subsequent
+    extensions to define additional blending equations.
+
+    The two new equations defined by this extension produce the minimum
+    (or maximum) color components of the source and destination colors.
+    Taking the maximum is useful for applications such as maximum projection
+    in medical imaging.
+
+Issues
+
+    *   I've prefixed the ADD token with FUNC, to indicate that the blend
+        equation includes the parameters specified by BlendFunc.  (The min
+        and max equations don't.)  Is this necessary?  Is it too ugly?
+        Is there a better way to accomplish the same thing?
+    
+New Procedures and Functions
+
+    void BlendEquationEXT(enum mode);
+
+New Tokens
+
+    Accepted by the <mode> parameter of BlendEquationEXT:
+
+        FUNC_ADD_EXT                     0x8006
+        MIN_EXT                          0x8007
+        MAX_EXT                          0x8008
+
+    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
+    GetFloatv, and GetDoublev:
+
+        BLEND_EQUATION_EXT               0x8009
+
+Additions to Chapter 2 of the GL Specification (OpenGL Operation)
+
+    None
+
+Additions to Chapter 3 of the GL Specification (Rasterization)
+
+    None
+
+Additions to Chapter 4 of the GL Specification (Per-Fragment Operations
+and the Framebuffer)
+
+    The GL Specification defines a single blending equation.  This
+    extension introduces a blend equation mode that is specified by calling
+    BlendEquationEXT with one of three enumerated values.  The default
+    value FUNC_ADD_EXT specifies that the blending equation defined in
+    the GL Specification be used.  This equation is
+
+        C' = (Cs * S) + (Cd * D)
+
+             /  1.0     C' > 1.0
+        C = (
+             \   C'     C' <= 1.0
+
+    where Cs and Cd are the source and destination colors, and S and D are
+    as specified by BlendFunc.
+
+    If BlendEquationEXT is called with <mode> set to MIN_EXT, the
+    blending equation becomes
+
+        C = min (Cs, Cd)
+
+    Finally, if BlendEquationEXT is called with <mode> set to MAX_EXT, the
+    blending equation becomes
+
+        C = max (Cs, Cd)
+
+    In all cases the blending equation is evaluated separately for each
+    color component.
+
+Additions to Chapter 5 of the GL Specification (Special Functions)
+
+    None
+
+Additions to Chapter 6 of the GL Specification (State and State Requests)
+
+    None
+
+Additions to the GLX Specification
+
+    None
+
+GLX Protocol
+
+    A new GL rendering command is added. The following command is sent to the 
+    server as part of a glXRender request:
+
+        BlendEquationEXT
+            2           8               rendering command length
+            2           4097            rendering command opcode
+            4           ENUM            mode
+
+Dependencies on OpenGL ES
+
+    If the GL is OpenGL ES, only the new MIN_EXT and MAX_EXT blend equations
+    are introduced by this extension.  BlendEquationOES, FUNC_ADD_OES, and
+    BLEND_EQUATION_OES are introduced by the OES_blend_subtract extension,
+    which is required for this extension to operate.  Alternatively,
+    OpenGL ES 2.0 is required, which introduces BlendEquation, FUNC_ADD, and
+    BLEND_EQUATION without the suffixes.
+
+    MIN_EXT and MAX_EXT should be added to Table 4.blendeq described in the
+    OES_blend_subtract extension specification, and Table 4.1 of the OpenGL
+    ES 2.0 specification.
+
+    Mentions of GetDoublev, Begin/End, and GLX in this extension specification
+    can be ignored for OpenGL ES.  Also, BlendEquationEXT and FUNC_ADD_EXT
+    instead have the OES suffix courtesy of OES_blend_subtract, or no suffix
+    courtesy of core OpenGL ES 2.0.
+
+Errors
+
+    INVALID_ENUM is generated by BlendEquationEXT if its single parameter
+    is not FUNC_ADD_EXT, MIN_EXT, or MAX_EXT.
+
+    INVALID_OPERATION is generated if BlendEquationEXT is executed between
+    the execution of Begin and the corresponding execution to End.
+
+New State
+
+    Get Value           Get Command     Type    Initial Value   Attribute
+    ---------           -----------     ----    -------------   ---------
+    BLEND_EQUATION_EXT  GetIntegerv     Z3      FUNC_ADD_EXT    color-buffer
+
+New Implementation Dependent State
+
+    None
+
+Revision History
+
+    Version 1.5, September 17, 2009 (Jon Leech) -
+        Merge into OpenGL Registry version of the extension and assign
+        OpenGL ES extension number.
+    Version 1.4, May 19, 2009 (Benj Lipchak) -
+        Adapted for OpenGL ES.
+    Version 1.3, May 31, 1995 -
+        Last SGI revision.
diff --git a/src/third_party/angle/extensions/EXT_color_buffer_float.txt b/src/third_party/angle/extensions/EXT_color_buffer_float.txt
new file mode 100644
index 0000000..2eb163d
--- /dev/null
+++ b/src/third_party/angle/extensions/EXT_color_buffer_float.txt
@@ -0,0 +1,230 @@
+Name
+
+    EXT_color_buffer_float
+
+Name Strings
+
+    GL_EXT_color_buffer_float
+
+Contributors
+
+    OpenGL ES Working Group members
+
+Contact
+
+    Mark Callow, HI Corp. (callow.mark 'at' artspark.co.jp)
+
+Notice
+
+    ©2012 The Khronos Group Inc.
+
+Status
+
+    Complete
+
+IP Status
+
+    Graphics Properties Holdings (GPH, formerly SGI) owns US Patent
+    #6,650,327, issued November 18, 2003. GPH believes this patent
+    contains necessary IP for graphics systems implementing floating
+    point (FP) rasterization and FP framebuffer capabilities.
+
+    GPH will not grant Khronos royalty-free use of this IP for use
+    in OpenGL ES, but will discuss licensing on RAND terms, on an
+    individual basis with companies wishing to use this IP in the
+    context of conformant OpenGL ES implementations. GPH does not
+    plan to make any special exemption for open source
+    implementations.
+
+    See
+    https://www.khronos.org/files/ip-disclosures/opengl/SGI%20IP%20Disclosure%20Mar05_clean.pdf
+    for the full disclosure.
+
+Version
+
+    Date: January 11th, 2013
+    Revision: 5
+
+Number
+
+    OpenGL ES Extension #137
+
+Dependencies
+
+    Requires OpenGL ES 3.0.
+
+    Written based on the wording of the OpenGL ES 3.0.1 Specification
+    (January 10th, 2013).
+
+Overview
+
+    This extension allows a variety of floating point formats to be
+    rendered to via framebuffer objects.
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    None
+
+Additions to Chapter 3 of the OpenGL ES 3.0 Specification
+(Rasterization)
+
+    3.8.3 Texture Image Specification, unnumbered subsection "Required
+    Texture Formats", p. 126
+
+    Change the first two bullet items to the following:
+
+    - Texture and renderbuffer color formats (see section 4.4.2).
+      - RGBA32F, RGBA32I, RGBA32UI, RGBA16F, RGBA16I, RGBA16UI,
+        RGBA8, RGBA8I, RGBA8UI, SRGB8_ALPHA8, RGB10_A2, RGB10_-
+        A2UI, RGBA4, and RGB5_A1.
+      - RGB8 and RGB565.
+      - R11F G11F B10F.
+      - RG32F, RG32I, RG32UI, RG16F, RG16I, RG16UI, RG8, RG8I, and
+        RG8UI.
+      - R32F, R32I, R32UI, R16F, R16I, R16UI, R8, R8I, and R8UI.
+
+    - Texture-only color formats:
+      - RGBA8_SNORM.
+      - RGB32F, RGB32I, and RGB32UI.
+      - RGB16F, RGB16I, and RGB16UI.
+      - RGB8_SNORM, RGB8I, RGB8UI, and SRGB8.
+      - RGB9_E5.
+      - RG8_SNORM.
+      - R8_SNORM.
+
+    Table 3.12, p. 128 & 129
+
+    Convert the dash under 'Color-renderable' to a 'check' for the
+    following internal formats: R16F, RG16F, RGBA16F, R32F, RG32F,
+    RGBA32F and R11F_G11F_B10F.
+    
+Additions to Chapter 4 of the OpenGL ES 3.0 Specification (Per-Fragment
+Operations and the Framebuffer)
+
+    (changed lines marked with *; added lines marked with +)
+
+    Chapter 4 Introduction, p. 167
+
+    Paragraph 5, sentence 3, p 168, insert "floating point" as shown:
+        "R, G, B, and A components may be represented as unsigned
+ *      normalized fixed-point, floating point or signed or unsigned
+        integer values; ..."    ^^^^^^^^^^^^^^
+
+    4.1.7 Blending, p. 174
+
+    Modify paragraphs 3 & 4:
+    
+ *      "If the color buffer is fixed-point, the components of the
+    source and destination values and blend factors are clamped
+ *  to [0; 1] prior to evaluating the blend equation. If the color
+ +  buffer is floating-point, no clamping occurs. The resulting four
+ +  values are sent to the next operation.
+    
+        Blending applies only if the color buffer has a fixed-point or
+ *  or floating-point format. If the color buffer has an integer
+ *  format, proceed to the next operation.  Furthermore, an
+ +  INVALID_OPERATION error is generated by DrawArrays and the other
+ +  drawing commands defined in section 2.8.3 if blending is enabled
+ +  (see below) and any draw buffer has a 32-bit floating-point
+ +  format."
+
+    4.2.3 Clearing the Buffers, p. 183
+
+    Modify second paragraph, inserting "floating point":
+
+    "   void ClearColor(float r, float g, float b, float a);
+
+ *  sets the clear value for fixed- and floating-point color buffers.
+    ..."                            ^^^^^^^^^^^^^^^^^^
+
+    4.3.1 Reading Pixels, p. 186
+
+    In paragraph 4, beginning "Only two combinations of format
+    and type are accepted ...", after the sentence ending "... type
+    UNSIGNED_BYTE is accepted." insert the following sentence:
+        "For floating-point rendering surfaces, the combination
+        format RGBA and type FLOAT is accepted."
+
+    4.3.1 unnumbered subsection "Obtaining Pixels from the Framebuffer",
+    p. 188
+
+    Modify penultimate paragraph, p189, "If format is an integer ..."
+
+    "If format is an integer format and the color buffer is not an
+    integer format; if the color buffer is an integer format and
+ *  format is not an integer format; if format is an integer format
+ *  and type is FLOAT, HALF_FLOAT, or UNSIGNED_INT_10F_11F_11F_REV;
+ +  or if the color buffer is a floating-point format and type is
+ +  not FLOAT, HALF FLOAT, or UNSIGNED_INT_10F_11F_11F_REV, the error
+    INVALID_OPERATION occurs."
+
+    4.3.1 unnumbered subsection "Conversion of RGBA values", p.190
+
+    Sole paragraph, sentence 3, insert "or floating point" as shown:
+ *      "For an integer or floating point color buffer, the elements
+        are unmodified."^^^^^^^^^^^^^^^^^
+
+    4.3.2 Copying Pixels, p192
+
+    Modify first error condition, at bottom of p193, "The read buffer
+    contains ..." to encompass floating-point buffers.
+
+ *  "- The read buffer contains fixed-point or floating-point values
+ *     and any draw buffer contains neither fixed-point nor
+ *     floating-point values."
+
+    4.4.2 Attaching Images to Framebuffer Objects, p. 197, unnumbered
+    subsection "Required Renderbuffer Formats", p. 200
+
+    In the last paragraph beginning "Implementations must support
+    creation ...", modify the final phrase to
+
+ *   "with the exception of signed and unsigned integer, RGBA16F,
+ +   R32F, RG32F and RGBA32F formats.
+
+Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
+
+    None
+
+Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
+Requests)
+
+    6.1.15 Internal Format Queries, p. 237
+
+    P. 238, paragraph 8 after "Since multisampling is not supported
+    for signed and unsigned integer internal formats, the value of
+    NUM_SAMPLE_COUNTS will be zero for such formats.", insert new
+    one-sentence paragraph:
+
+        "If <internalformat> is RGBA16F, R32F, RG32F, or RGBA32F, the
+        value of NUM_SAMPLE_COUNTS may be zero, or else the maximum
+        value in SAMPLES may be less than the value of MAX_SAMPLES."
+
+New Implementation Dependent State
+
+    None
+
+Issues
+
+Revision History
+
+    Rev.  Date     Author     Changes
+    ----  -------- ---------  -----------------------------------------
+      1   10/16/12 markc      Initial version
+      2   10/18/12 markc      Referenced preliminary version of OpenGL
+                              ES 3.0.1 specification and updated page
+                              numbers.
+      3   11/21/12 markc      Corrected IP status.
+      4   01/09/13 markc      Changed date of referenced OpenGL ES
+                              3.0.1 specification. Made minor language
+                              simplification.
+      5   01/11/13 markc      Changed date to release version of
+                              OpenGL ES 3.0.1 specification.
+                              Clarified change to "Required
+                              renderbuffer formats" section.
+
+# vim:ai:ts=4:sts=4:sw=4:expandtab:textwidth=70
diff --git a/src/third_party/angle/extensions/EXT_shader_framebuffer_fetch.txt b/src/third_party/angle/extensions/EXT_shader_framebuffer_fetch.txt
new file mode 100644
index 0000000..4a9bed2
--- /dev/null
+++ b/src/third_party/angle/extensions/EXT_shader_framebuffer_fetch.txt
@@ -0,0 +1,263 @@
+Name
+
+    EXT_shader_framebuffer_fetch
+
+Name Strings
+
+    GL_EXT_shader_framebuffer_fetch
+
+Contact
+
+    Benj Lipchak, Apple (lipchak 'at' apple.com)
+
+Status
+
+    Complete
+
+Version
+
+    Last Modified Date: May 28, 2013
+    Author Revision: 4
+
+Number
+
+    OpenGL ES Extension #122
+
+Dependencies
+
+    OpenGL ES 2.0 is required.
+    
+    This specification is written against the OpenGL ES 2.0.24 specification.
+    This extension is written against the OpenGL ES Shading Language 1.0.17
+    specification.
+    
+    OpenGL ES 3.0 affects the definition of this extension.
+
+Overview
+
+    Conventional OpenGL blending provides a configurable series of operations
+    that can be used to combine the output values from a fragment shader with
+    the values already in the framebuffer. While these operations are
+    suitable for basic image compositing, other compositing operations or
+    operations that treat fragment output as something other than a color
+    (normals, for instance) may not be expressible without multiple passes or
+    render-to-texture operations.
+
+    This extension provides a mechanism whereby a fragment shader may read
+    existing framebuffer data as input. This can be used to implement
+    compositing operations that would have been inconvenient or impossible with
+    fixed-function blending. It can also be used to apply a function to the
+    framebuffer color, by writing a shader which uses the existing framebuffer
+    color as its only input.
+
+Issues
+
+    1. How is framebuffer data treated during multisample rendering?
+    
+    RESOLVED: Reading the value of gl_LastFragData produces a different
+    result for each sample. This implies that all or part of the shader be run
+    once for each sample. Input values to the shader from existing variables
+    in GLSL ES remain identical across samples.
+    
+    2. How does the use of gl_LastFragData interact with fragment discard?
+    
+    RESOLVED: Hardware may not necessarily support discarding on sample
+    granularity. Therefore, three options were considered for this
+    functionality:
+    
+        A) Allow discard based on variables calculated using the framebuffer
+           color when multisample rasterization is disabled, but disallow
+           discard in this manner when multisample rasterization is enabled.
+        
+        B) Restrict usage of the framebuffer color until it is known whether
+           or not the pixel will be discarded.
+            
+        C) Allow undefined results for fragment shaders that discard on a
+           per-sample basis on hardware that doesn't support it.
+    
+    This extension has chosen option C. Restricting orthogonality of fragment
+    shaders between single-sample and multisample rendering is undesirable, as
+    is restricting usage of the framebuffer color, which can generally only be
+    done with detailed flow-control analysis.
+    
+    3. What is the precision of gl_LastFragData in practice?
+    
+    RESOLVED: Three options were considered for this functionality:
+    
+        A) gl_LastFragData is always mediump.
+        
+        B) gl_LastFragData takes the precision most closely matching the
+           actual storage format of the framebuffer.
+        
+        C) Allow redeclaration of gl_LastFragData in order to change its
+           precision.
+    
+    This extension has chosen option C. A fixed precision per option A
+    increases the likelihood of redundant conversion operations in the shader,
+    and option B does not provide for clear behavior with regard to the
+    precision of intermediate results from calculations using the
+    framebuffer color.
+
+    4. How does this extension iteract with conventional blending?
+    
+    RESOLVED: There is no interaction.  The two remain orthogonal.  The rest
+    of the pipeline continues as usual after the fragment shader stage.
+    
+
+    5. How does this extension work in ES 3.0?
+
+    RESOLVED: Differently than in ES 2.0.
+
+    The built-in fragment outputs of ES 2.0 are replaced in #version 300 es
+    shaders by user-declared outputs, to accomodate integer and MRT 
+    framebuffers.  Three options were considered:
+
+        A) Add built-ins similar to gl_LastFragData.
+        
+        B) Add a layout to mark user-declared fragment outputs as having
+        defined content on entry to fragment shader.
+            
+        C) Allow marking user-declared fragment outputs as "inout".
+
+    This extension has chosen option C.  Adding built-ins per option A is
+    unwieldy for MRT framebuffers with mixed attachment types and precisions.  
+    Options B and C are semantically identical, but C requires fewer 
+    modifications to the specification and to user shaders.  Note that the 
+    inout qualifier is not allowed for re-declaring existing fragment outputs 
+    such as gl_FragDepth.
+
+New Procedures and Functions
+
+    None
+    
+New Tokens
+
+    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,
+    and GetDoublev:
+    
+        FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT            0x8A52
+
+New Builtin Variables
+
+    mediump vec4 gl_LastFragData[gl_MaxDrawBuffers]
+    
+Changes to the OpenGL ES 2.0.24 Specification, Chapter 3
+
+    Remove the last sentence of Paragraph 2 of Section 3.8.1, page 84 ("These
+    built-in varying variables include [...]" and add:
+    
+    These built-in varying variables include the fragment's position, eye z
+    coordinate, and front-facing flag, as well as the last data or color value
+    written to the framebuffer. When the value of SAMPLE_BUFFERS is 1 and the 
+    current framebuffer color is accessed in the fragment shader, the fragment
+    shader will be invoked separately for each covered sample and a separate 
+    value for the previous framebuffer color will be provided for each sample."
+    
+    Add a new subsection to section 3.8.2, page 87 ("Shader Execution"):
+    
+    "Discard
+    
+    Fragment shaders may conditionally abandon operations using the discard
+    keyword. However, the ability of hardware to support abandoning operations
+    on a single sample when the shader is invoked once for each covered sample
+    is implementation-dependent. This capability can be determined by calling
+    GetBooleanv with the symbolic constant 
+    FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT. If FALSE is returned, results from
+    shaders which discard based on per-sample logic are undefined."
+
+Changes to the OpenGL ES 2.0.24 Specification, Chapter 4
+
+    Replace first element of Figure 4.1, page 90 ("Fragment + Associated Data"):
+    
+    "Fragment (or sample) + Associated Data"
+
+New Implementation Dependent State
+
+    Add to table 6.19 (Implementation Dependent Values (cont.)):
+
+    Get Value                             Type  Get Command  Minimum Value  Description        Section
+    ---------                             ----  -----------  -------------  --------------     -------
+    FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT  B     GetBooleanv  -              Samples may be     3.8.2
+                                                                            discarded 
+                                                                            individually 
+
+Changes to the OpenGL ES Shading Language 1.0.17 Specification, Chapter 3
+
+    Remove Paragraph 2 of section 3.8, page 17, Identifiers ("Identifiers
+    starting with "gl_" are reserved [...]") and add:
+
+    "Identifiers starting with "gl_" are reserved for use by OpenGL ES, and
+    may not be declared in a shader as either a variable or a function.
+    However, as noted in the specification, certain predeclared "gl_" names
+    are allowed to be redeclared in a shader for the specific purpose of
+    changing their precision qualifier."
+    
+Changes to the OpenGL ES Shading Language 1.0.17 Specification, Chapter 7
+
+    Add after the last sentence of Paragraph 2 of Section 7.2, page 60,
+    Fragment Shader Special Variables ("These variables may be written to
+    more [...]"):
+    
+    "... To access the existing framebuffer values (e.g., to implement a
+    complex blend operation inside the shader), fragment shaders should use
+    the read-only input array gl_LastFragData.  gl_LastFragData returns the
+    value written by the most recent fragment at the same position.
+    
+    Access to gl_LastFragData is optional, and must be enabled by 
+    
+    #extension GL_EXT_shader_framebuffer_fetch : <behavior>
+    
+    Where <behavior> is as specified in section 3.3.
+    
+    By default, gl_LastFragData is declared with the mediump precision
+    qualifier. This can be changed by redeclaring the corresponding variables
+    with the desired precision qualifier.
+    
+    Redeclarations are done as follows
+    
+    // Redeclaration that changes nothing is allowed
+    mediump vec4 gl_LastFragData[gl_MaxDrawBuffers]; 
+    
+    // All the following are allowed redeclaration that change behavior
+    lowp vec4 gl_LastFragData[gl_MaxDrawBuffers];
+    highp vec4 gl_LastFragData[gl_MaxDrawBuffers];
+    
+    Redeclarations must not otherwise alter the declared type or array size of
+    gl_LastFragData."
+    
+Changes to the OpenGL ES Shading Language 3.00.3 Specification, Chapter 4
+
+    Modify Paragraph 2 of section 4.3.6:
+    "Except in the fragment stage, there is not an inout storage qualifier at
+    global scope for declaring a single variable name as both input and output
+    [...]"
+
+    Modify Paragraph 5 of section 4.3.6:
+    "Fragment outputs output per-fragment data and are declared using the out
+    or inout storage qualifier. It is an error to use centroid out or centroid
+    inout in a fragment shader [...]" and append new paragraph:
+
+    "Upon entry to the fragment shader, fragment outputs declared as inout will
+    contain the value written by the most recent fragment at the same position.
+    This behavior, and the ability to use the inout qualifier at global scope 
+    in a fragment shader, is optional and must be enabled by
+
+    #extension GL_EXT_shader_framebuffer_fetch : <behavior>
+    
+    Where <behavior> is as specified in section 3.4."
+
+Interactions with OES_standard_derivatives
+
+    Results from shaders which use the built-in derivative functions dFdx,
+    dFdy, and fwidth on variables calculated using the current framebuffer 
+    color are undefined.
+
+Revision History
+
+    Version 4, 2013/05/28 - Added ES3 interaction as requested in Bug 10236
+    Version 3, 2012/09/24 - Remove obsolete issue 3 about derivatives
+    Version 2, 2012/06/21 - Fix MULTISAMPLE enabled -> SAMPLE_BUFFERS = 1,
+                            recast from APPLE to multivendor EXT, clarify that
+                            gl_LastFragData reflects value written by previous
+                            pixel at same coordinates.
+    Version 1, 2012/06/01 - Conversion from ARB_sync to APPLE_sync for ES.
\ No newline at end of file
diff --git a/src/third_party/angle/extensions/EXT_texture_rg.txt b/src/third_party/angle/extensions/EXT_texture_rg.txt
new file mode 100644
index 0000000..968b28d
--- /dev/null
+++ b/src/third_party/angle/extensions/EXT_texture_rg.txt
@@ -0,0 +1,195 @@
+Name
+
+    EXT_texture_rg
+
+Name Strings
+    
+    GL_EXT_texture_rg
+
+Contributors
+
+    Contributors to ARB_texture_rg, on which this extension is based
+    Kyle Haughey
+    Richard Schreyer
+
+Contact
+
+    Benj Lipchak, Apple (lipchak 'at' apple.com)
+
+Status 
+    
+    Complete
+
+Version
+    
+    Date: July 22, 2011
+    Revision: 3
+
+Number
+
+    OpenGL ES Extension #103
+
+Dependencies
+
+    Requires OpenGL ES 2.0.
+
+    Written based on the wording of the OpenGL ES 2.0.25 Full Specification
+    (November 2, 2010).
+
+    OES_texture_float affects the definition of this extension.
+
+    OES_texture_half_float affects the definition of this extension.
+
+    APPLE_framebuffer_multisample affects the definition of this extension.
+
+Overview
+
+    Historically one- and two-component textures have been specified in OpenGL
+    ES using the luminance or luminance-alpha (L/LA) formats. With the advent
+    of programmable shaders and render-to-texture capabilities these legacy
+    formats carry some historical artifacts which are no longer useful.
+
+    For example, when sampling from such textures, the luminance values are
+    replicated across the color components. This is no longer necessary with
+    programmable shaders.
+    
+    It is also desirable to be able to render to one- and two-component format
+    textures using capabilities such as framebuffer objects (FBO), but
+    rendering to L/LA formats is under-specified (specifically how to map
+    R/G/B/A values to L/A texture channels).
+
+    This extension adds new base internal formats for one-component RED and
+    two-component RG (red green) textures as well as sized RED and RG internal
+    formats for renderbuffers. The RED and RG texture formats can be used for
+    both texturing and rendering into with framebuffer objects.
+
+New Procedures and Functions
+    
+    None
+
+New Tokens
+
+    Accepted by the <internalformat> parameter of TexImage2D and CopyTexImage2D,
+    and the <format> parameter of TexImage2D, TexSubImage2D, and ReadPixels:
+
+        RED_EXT                 0x1903
+        RG_EXT                  0x8227
+
+    Accepted by the <internalformat> parameter of RenderbufferStorage and
+    RenderbufferStorageMultisampleAPPLE:
+
+        R8_EXT                  0x8229
+        RG8_EXT                 0x822B
+
+Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)
+
+    None
+
+Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization)
+
+    (Add the following to Table 3.3: "TexImage2D and ReadPixels formats")
+
+    Format Name     Element Meaning and Order      Target Buffer
+    -----------     -------------------------      -------------
+    RED_EXT         R                              Color
+    RG_EXT          R, G                           Color
+
+    (Add the following to Table 3.4: "Valid pixel format and type combinations")
+    (as modified by OES_texture_float and OES_texture_half_float)
+
+    Format          Type                           Bytes per Pixel
+    -----------     -------------------------      ---------------
+    RED_EXT         FLOAT                          4
+    RED_EXT         HALF_FLOAT_OES                 2
+    RED_EXT         UNSIGNED_BYTE                  1
+    RG_EXT          FLOAT                          8
+    RG_EXT          HALF_FLOAT_OES                 4
+    RG_EXT          UNSIGNED_BYTE                  2
+
+    (Add the following to Table 3.8: "Conversion from RGBA and depth pixel
+    components to internal texture")
+
+    Base Internal Format     RGBA       Internal Components
+    --------------------     ------     -------------------
+    RED_EXT                  R          R
+    RG_EXT                   R,G        R,G
+
+    (Modify Table 3.9: "CopyTexImage internal format/color buffer combinations")
+
+                            Texture Format
+    Color Buffer      A  L  LA  R  RG  RGB  RGBA
+    ------------      -  -  --  -  --  ---  ----
+    A                 X
+    R                    X      X
+    RG                   X      X  X
+    RGB                  X      X  X   X
+    RGBA              X  X  X   X  X   X    X
+
+    (Add the following to Table 3.12: "Correspondence of filtered texture
+    components to texture source color components")
+
+    Texture Base        Texture source color
+    Internal Format     C_s             A_s
+    ---------------     -------------   ------
+    RED_EXT             (R_t, 0, 0)     1
+    RG_EXT              (R_t, G_t, 0)   1
+
+Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
+Operations and the Framebuffer)
+
+    In section 4.3.1 "Reading Pixels", subsection "Obtaining Pixels from the
+    Framebuffer", modify the last sentence to read:
+
+    "If the framebuffer does not support G, B, or A values then the G, B, and A
+    values that are obtained are 0.0, 0.0, and 1.0 respectively."
+
+    In section 4.4.5 "Framebuffer Completeness", modify the last sentence of
+    the second paragraph to read:
+
+    "Color-renderable formats contain red, and possibly green, blue, and alpha
+    components; depth-renderable formats contain depth components; and
+    stencil-renderable formats contain stencil components."
+
+    (Add the following to Table 4.5: "Renderbuffer image formats, showing their
+    renderable type (color-, depth-, or stencil-renderable) and the number of
+    bits each format contains for color (R, G, B, A), depth (D), and stencil
+    (S) components")
+
+    Sized Internal  Renderable Type   R bits G bits B bits A bits D bits S bits
+    Format
+    --------------  ----------------  ------ ------ ------ ------ ------ ------
+    R8_EXT        color-renderable  8
+    RG8_EXT       color-renderable  8      8
+
+Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
+
+    None
+
+Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
+Requests)
+
+    None
+
+Dependencies on OES_texture_float
+
+    If OES_texture_float is not supported, then omit the rows of
+    Table 3.4 that have Type FLOAT.
+
+Dependencies on OES_texture_half_float
+
+    If OES_texture_half_float is not supported, then omit the rows of 
+    Table 3.4 that have Type HALF_FLOAT_OES.
+
+Dependencies on APPLE_framebuffer_multisample
+
+    If APPLE_framebuffer_multisample is not supported, then all references to
+    RenderbufferStorageMultisampleAPPLE should be ignored.
+
+Revision History
+    
+    #1 February 22, 2011, khaughey
+        - initial version adapted from ARB_texture_rg.
+    #2 June 16, 2011, benj
+        - add interaction with APPLE_framebuffer_multisample
+    #3 July 22, 2011, benj
+        - rename from APPLE to EXT
diff --git a/src/third_party/angle/gni/angle.gni b/src/third_party/angle/gni/angle.gni
new file mode 100644
index 0000000..f48e753
--- /dev/null
+++ b/src/third_party/angle/gni/angle.gni
@@ -0,0 +1,36 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ui.gni")  # import the use_x11 variable
+import("//ui/ozone/ozone.gni")
+
+angle_enable_d3d9 = false
+angle_enable_d3d11 = false
+angle_enable_gl = false
+angle_enable_vulkan = false
+angle_enable_null = true
+
+if (is_win) {
+  angle_enable_d3d9 = true
+  angle_enable_d3d11 = true
+  angle_enable_gl = true
+  angle_enable_vulkan = true
+
+  import("//build/config/win/visual_studio_version.gni")
+} else if (is_linux && use_x11 && !is_chromeos) {
+  angle_enable_gl = true
+  angle_enable_vulkan = true
+} else if (is_mac || ozone_platform_gbm) {
+  angle_enable_gl = true
+} else if (is_android) {
+  angle_enable_gl = true
+}
+
+angle_enable_essl = true
+angle_enable_glsl = true
+angle_enable_hlsl = false
+
+if (angle_enable_d3d9 || angle_enable_d3d11) {
+  angle_enable_hlsl = true
+}
diff --git a/src/third_party/angle/gyp/ANGLE.gyp b/src/third_party/angle/gyp/ANGLE.gyp
new file mode 100644
index 0000000..f818713
--- /dev/null
+++ b/src/third_party/angle/gyp/ANGLE.gyp
@@ -0,0 +1,29 @@
+# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'targets':
+    [
+        {
+            'target_name': 'All',
+            'type': 'none',
+            'dependencies':
+            [
+                '../src/angle.gyp:*',
+                '../src/tests/tests.gyp:*',
+            ],
+            'conditions':
+            [
+                # Don't generate samples for WinRT
+                ['angle_build_winrt==0',
+                {
+                    'dependencies':
+                    [
+                        '../samples/samples.gyp:*',
+                    ],
+                }],
+            ],
+        },
+    ],
+}
diff --git a/src/third_party/angle/gyp/common.gypi b/src/third_party/angle/gyp/common.gypi
new file mode 100644
index 0000000..fec47d8
--- /dev/null
+++ b/src/third_party/angle/gyp/common.gypi
@@ -0,0 +1,458 @@
+# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'includes': [ 'common_defines.gypi', ],
+    'variables':
+    {
+        'angle_path': '<(DEPTH)',
+        'angle_build_winrt%': '0',
+        'angle_build_winrt_app_type_revision%': '10.0',
+        'angle_build_winrt_target_platform_ver%' : '',
+        # angle_code is set to 1 for the core ANGLE targets defined in src/build_angle.gyp.
+        # angle_code is set to 0 for test code, sample code, and third party code.
+        # When angle_code is 1, we build with additional warning flags on Mac and Linux.
+        'angle_code%': 0,
+        'release_symbols%': 'true',
+        'gcc_or_clang_warnings':
+        [
+            '-Wall',
+            '-Wchar-subscripts',
+            '-Werror',
+            '-Wextra',
+            '-Wformat=2',
+            '-Winit-self',
+            '-Wno-format-nonliteral',
+            '-Wno-unknown-pragmas',
+            '-Wno-unused-function',
+            '-Wno-unused-parameter',
+            '-Wpacked',
+            '-Wpointer-arith',
+            '-Wundef',
+            '-Wwrite-strings',
+        ],
+        'gcc_or_clang_warnings_cc':
+        [
+            '-Wnon-virtual-dtor',
+        ],
+
+        # TODO: Pull chromium's clang dep.
+        'clang%': 0,
+
+        'clang_only_warnings':
+        [
+            '-Wshorten-64-to-32',
+        ],
+    },
+    'target_defaults':
+    {
+        'default_configuration': 'Debug',
+        'variables':
+        {
+            'warn_as_error%': 1,
+        },
+        'target_conditions':
+        [
+            ['warn_as_error == 1',
+            {
+                'msvs_settings':
+                {
+                    'VCCLCompilerTool':
+                    {
+                        'WarnAsError': 'true',
+                    },
+                    'VCLinkerTool':
+                    {
+                        'TreatLinkerWarningAsErrors': 'true',
+                    },
+                },
+            }],
+        ],
+        'conditions':
+        [
+            ['angle_build_winrt==1',
+            {
+                'msvs_enable_winrt' : '1',
+                'msvs_application_type_revision' : '<(angle_build_winrt_app_type_revision)',
+                'msvs_target_platform_version' : '<(angle_build_winrt_target_platform_ver)',
+            }],
+        ],
+        'configurations':
+        {
+            'Common_Base':
+            {
+                'abstract': 1,
+                # Require the version of the Windows 10 SDK installed on the local machine.
+                'msvs_windows_sdk_version': 'v10.0',
+                'msvs_configuration_attributes':
+                {
+                    'OutputDirectory': '$(SolutionDir)$(ConfigurationName)_$(Platform)',
+                    'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
+                    'CharacterSet': '0',    # ASCII
+                },
+                'msvs_settings':
+                {
+                    'VCCLCompilerTool':
+                    {
+                        # Control Flow Guard is a security feature in Windows
+                        # 8.1 and higher designed to prevent exploitation of
+                        # indirect calls in executables.
+                        # Control Flow Guard is enabled using the /d2guard4
+                        # compiler setting in combination with the /guard:cf
+                        # linker setting.
+                        'AdditionalOptions': ['/MP', '/d2guard4'],
+                        'BufferSecurityCheck': 'true',
+                        'DebugInformationFormat': '3',
+                        'ExceptionHandling': '0',
+                        'EnableFunctionLevelLinking': 'true',
+                        'MinimalRebuild': 'false',
+                        'WarningLevel': '4',
+                        'conditions':
+                        [
+                            ['angle_build_winrt==1',
+                            {
+                                # Use '/Wv:18' to avoid WRL warnings in VS2015 Update 3
+                                # Use /Gw and /Zc:threadSafeInit to avoid
+                                # LTCG-related crashes with VS2015 Update 3
+                                'AdditionalOptions': ['/Wv:18', '/Gw', '/Zc:threadSafeInit-'],
+                            }],
+                        ],
+                    },
+                    'VCLinkerTool':
+                    {
+                        # Control Flow Guard is a security feature in Windows
+                        # 8.1 and higher designed to prevent exploitation of
+                        # indirect calls in executables.
+                        # Control Flow Guard is enabled using the /d2guard4
+                        # compiler setting in combination with the /guard:cf
+                        # linker setting.
+                        'AdditionalOptions': ['/guard:cf'],
+                        'FixedBaseAddress': '1',
+                        'ImportLibrary': '$(OutDir)\\lib\\$(TargetName).lib',
+                        'MapFileName': '$(OutDir)\\$(TargetName).map',
+                        # Most of the executables we'll ever create are tests
+                        # and utilities with console output.
+                        'SubSystem': '1',    # /SUBSYSTEM:CONSOLE
+                    },
+                    'VCResourceCompilerTool':
+                    {
+                        'Culture': '1033',
+                    },
+                },
+                'xcode_settings':
+                {
+                    'CLANG_CXX_LANGUAGE_STANDARD': 'c++11',
+                },
+            },    # Common_Base
+
+            'Debug_Base':
+            {
+                'abstract': 1,
+                'defines':
+                [
+                    '_DEBUG'
+                ],
+                'msvs_settings':
+                {
+                    'VCCLCompilerTool':
+                    {
+                        'Optimization': '0',    # /Od
+                        'BasicRuntimeChecks': '3',
+                        'RuntimeTypeInfo': 'true',
+                        'conditions':
+                        [
+                            ['angle_build_winrt==1',
+                            {
+                                # Use the dynamic C runtime to match
+                                # Windows Application Store requirements
+
+                                # The C runtime for Windows Store applications
+                                # is a framework package that is managed by
+                                # the Windows deployment model and can be
+                                # shared by multiple packages.
+
+                                'RuntimeLibrary': '3', # /MDd (debug dll)
+                            },
+                            {
+                                # Use the static C runtime to
+                                # match chromium and make sure
+                                # we don't depend on the dynamic
+                                # runtime's shared heaps
+                                'RuntimeLibrary': '1', # /MTd (debug static)
+                            }],
+                        ],
+                    },
+                    'VCLinkerTool':
+                    {
+                        'GenerateDebugInformation': 'true',
+                        'LinkIncremental': '2',
+                        'conditions':
+                        [
+                            ['angle_build_winrt==1',
+                            {
+                                'AdditionalDependencies':
+                                [
+                                    'dxgi.lib',
+                                ],
+                                'EnableCOMDATFolding': '1', # disable
+                                'OptimizeReferences': '1', # disable
+                            }],
+                        ],
+                    },
+                },
+                'xcode_settings':
+                {
+                    'COPY_PHASE_STRIP': 'NO',
+                    'GCC_OPTIMIZATION_LEVEL': '0',
+                },
+            },    # Debug_Base
+
+            'Release_Base':
+            {
+                'abstract': 1,
+                'defines':
+                [
+                    'NDEBUG'
+                ],
+                'msvs_settings':
+                {
+                    'VCCLCompilerTool':
+                    {
+                        'RuntimeTypeInfo': 'false',
+
+                        'conditions':
+                        [
+                            ['angle_build_winrt==1',
+                            {
+                                # Use Chromium's settings for 'Official' builds
+                                # to optimize WinRT release builds
+                                'Optimization': '1', # /O1, minimize size
+                                'FavorSizeOrSpeed': '2', # /Os
+                                'WholeProgramOptimization': 'true',
+
+                                # Use the dynamic C runtime to match
+                                # Windows Application Store requirements
+
+                                # The C runtime for Windows Store applications
+                                # is a framework package that is managed by
+                                # the Windows deployment model and can be
+                                # shared by multiple packages.
+                                'RuntimeLibrary': '2', # /MD (nondebug dll)
+                            },
+                            {
+                                'Optimization': '2', # /O2, maximize speed
+
+                                # Use the static C runtime to
+                                # match chromium and make sure
+                                # we don't depend on the dynamic
+                                'RuntimeLibrary': '0', # /MT (nondebug static)
+                            }],
+                        ],
+                    },
+                    'VCLinkerTool':
+                    {
+                        'GenerateDebugInformation': '<(release_symbols)',
+                        'LinkIncremental': '1',
+
+                        'conditions':
+                        [
+                            ['angle_build_winrt==1',
+                            {
+                                # Use Chromium's settings for 'Official' builds
+                                # to optimize WinRT release builds
+                                'LinkTimeCodeGeneration': '1',
+                                'AdditionalOptions': ['/cgthreads:8'],
+                            }],
+                        ],
+                    },
+                },
+            },    # Release_Base
+
+            'x86_Base':
+            {
+                'abstract': 1,
+                'msvs_configuration_platform': 'Win32',
+                'msvs_settings':
+                {
+                    'VCLinkerTool':
+                    {
+                        'TargetMachine': '1', # x86
+                    },
+                    'VCLibrarianTool':
+                    {
+                        'TargetMachine': '1', # x86
+                    },
+                },
+                'defines': [ 'ANGLE_X86_CPU' ],
+            }, # x86_Base
+
+            'x64_Base':
+            {
+                'abstract': 1,
+                'msvs_configuration_platform': 'x64',
+                'msvs_settings':
+                {
+                    'VCLinkerTool':
+                    {
+                        'TargetMachine': '17', # x86 - 64
+                    },
+                    'VCLibrarianTool':
+                    {
+                        'TargetMachine': '17', # x86 - 64
+                    },
+                },
+                'defines': [ 'ANGLE_X64_CPU' ],
+            },    # x64_Base
+
+            # Concrete configurations
+            'Debug':
+            {
+                'inherit_from': ['Common_Base', 'x86_Base', 'Debug_Base'],
+            },
+            'Release':
+            {
+                'inherit_from': ['Common_Base', 'x86_Base', 'Release_Base'],
+            },
+            'conditions':
+            [
+                ['OS == "win"',
+                {
+                    'Debug_x64':
+                    {
+                        'inherit_from': ['Common_Base', 'x64_Base', 'Debug_Base'],
+                    },
+                    'Release_x64':
+                    {
+                        'inherit_from': ['Common_Base', 'x64_Base', 'Release_Base'],
+                    },
+                }],
+                ['angle_build_winrt==1',
+                {
+                    'arm_Base':
+                    {
+                        'abstract': 1,
+                        'msvs_configuration_platform': 'ARM',
+                        'msvs_settings':
+                        {
+                            'VCLinkerTool':
+                            {
+                                'TargetMachine': '3', # ARM
+                            },
+                            'VCLibrarianTool':
+                            {
+                                'TargetMachine': '3', # ARM
+                            },
+                        },
+                    }, # arm_Base
+                    'Debug_ARM':
+                    {
+                        'inherit_from': ['Common_Base', 'arm_Base', 'Debug_Base'],
+                    },
+                    'Release_ARM':
+                    {
+                        'inherit_from': ['Common_Base', 'arm_Base', 'Release_Base'],
+                    },
+                }],
+            ],
+        },    # configurations
+    },    # target_defaults
+    'conditions':
+    [
+        ['OS == "win"',
+        {
+            'target_defaults':
+            {
+                'msvs_cygwin_dirs': ['../third_party/cygwin'],
+            },
+        },
+        { # OS != win
+            'target_defaults':
+            {
+                'cflags':
+                [
+                    '-fPIC',
+                ],
+                'cflags_cc':
+                [
+                    '-std=c++0x',
+                ],
+            },
+        }],
+        ['OS != "win" and OS != "mac"',
+        {
+            'target_defaults':
+            {
+                'cflags':
+                [
+                    '-pthread',
+                ],
+                'cflags_cc':
+                [
+                    '-fno-exceptions',
+                ],
+                'ldflags':
+                [
+                    '-pthread',
+                ],
+                'configurations':
+                {
+                    'Debug':
+                    {
+                        'variables':
+                        {
+                            'debug_optimize%': '0',
+                        },
+                        'defines':
+                        [
+                            '_DEBUG',
+                        ],
+                        'cflags':
+                        [
+                            '-O>(debug_optimize)',
+                            '-g',
+                        ],
+                    }
+                },
+            },
+        }],
+        ['angle_code==1',
+        {
+            'target_defaults':
+            {
+                'conditions':
+                [
+                    ['OS == "mac"',
+                    {
+                        'xcode_settings':
+                        {
+                            'WARNING_CFLAGS': ['<@(gcc_or_clang_warnings)']
+                        },
+                    }],
+                    ['OS != "win" and OS != "mac"',
+                    {
+                        'cflags_c':
+                        [
+                            '<@(gcc_or_clang_warnings)',
+                            '-std=c99',
+                        ],
+                        'cflags_cc':
+                        [
+                            '<@(gcc_or_clang_warnings_cc)',
+                        ],
+                        'defines':
+                        [
+                            'SYSCONFDIR="/etc"',
+                            'FALLBACK_CONFIG_DIRS="/etc/xdg"',
+                            'FALLBACK_DATA_DIRS="/usr/local/share:/usr/share"',
+                        ],
+                    }],
+                    ['clang==1',
+                    {
+                        'cflags': ['<@(clang_only_warnings)']
+                    }],
+                ]
+            }
+        }],
+    ],
+}
diff --git a/src/third_party/angle/gyp/common_defines.gypi b/src/third_party/angle/gyp/common_defines.gypi
new file mode 100644
index 0000000..bce49c4
--- /dev/null
+++ b/src/third_party/angle/gyp/common_defines.gypi
@@ -0,0 +1,158 @@
+# Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'variables':
+    {
+        'component%': 'static_library',
+        'use_libpci%': 1,
+        'windows_sdk_path%': 'C:/Program Files (x86)/Windows Kits/10',
+
+        'angle_build_winrt%': '0',
+
+        # This works like the Ozone GBM platform in Chrome:
+        # - Generic Buffer Manager (gbm) to allocate buffers
+        # - EGL_EXT_image_dma_buf_import to render into those buffers via EGLImage
+        # - Direct Rendering Manager + Kernel Mode Setting to scan out from those buffers
+        # - EGL_PLATFORM_SURFACELESS because there are no native windows
+        'use_ozone%': 0,
+
+        'conditions':
+        [
+            ['OS=="linux" and use_x11==1 and chromeos==0', {
+                'angle_use_glx%': 1,
+            },
+            {
+                'angle_use_glx%': 0,
+            }],
+        ],
+
+        # root of the OSX SDK for Chromium builds, the system root for standalone builds
+        'SDKROOT%': "",
+    },
+    'defines':
+    [
+        'ANGLE_STANDALONE_BUILD',
+    ],
+    'msvs_disabled_warnings':
+    [
+        4100, # Unreferenced formal parameter. Not interesting.
+        4127, # conditional expression is constant. Too noisy to be useful.
+        4718, # Recursive call has no side effects. Fires on xtree system header.
+        4251, # STL objects do not have DLL interface, needed by ShaderVars.h and angle_util
+    ],
+    'conditions':
+    [
+        ['use_ozone==1',
+        {
+            'defines': [ 'USE_OZONE' ],
+        }],
+        ['component=="shared_library"',
+        {
+            'defines': [ 'COMPONENT_BUILD' ],
+        }],
+    ],
+    'msvs_settings':
+    {
+        'VCCLCompilerTool':
+        {
+            'PreprocessorDefinitions':
+            [
+                '_CRT_SECURE_NO_DEPRECATE',
+                '_SCL_SECURE_NO_WARNINGS',
+                '_HAS_EXCEPTIONS=0',
+                'NOMINMAX',
+            ],
+        },
+        'VCLinkerTool':
+        {
+            'conditions':
+            [
+                ['angle_build_winrt==0',
+                {
+                    'AdditionalDependencies':
+                    [
+                        'kernel32.lib',
+                        'gdi32.lib',
+                        'winspool.lib',
+                        'comdlg32.lib',
+                        'advapi32.lib',
+                        'shell32.lib',
+                        'ole32.lib',
+                        'oleaut32.lib',
+                        'user32.lib',
+                        'uuid.lib',
+                        'odbc32.lib',
+                        'odbccp32.lib',
+                        'delayimp.lib',
+                    ],
+                }],
+                # winrt compilation is dynamic depending on the project
+                # type. AdditionalDependencies is automatically configured
+                # with the required .libs
+                ['angle_build_winrt==1',
+                {
+                    'AdditionalDependencies':
+                    [
+                        '%(AdditionalDependencies)',
+                        'uuid.lib',
+                    ],
+                }],
+            ],
+        },
+    },
+
+    # Windows SDK library directories for the configurations
+    'configurations':
+    {
+        'conditions':
+        [
+            ['angle_build_winrt==0',
+            {
+                'x86_Base':
+                {
+                    'abstract': 1,
+                    'msvs_settings':
+                    {
+                        'VCLinkerTool':
+                        {
+                            'AdditionalLibraryDirectories':
+                            [
+                                '<(windows_sdk_path)/Lib/winv6.3/um/x86',
+                            ],
+                        },
+                        'VCLibrarianTool':
+                        {
+                            'AdditionalLibraryDirectories':
+                            [
+                                '<(windows_sdk_path)/Lib/winv6.3/um/x86',
+                            ],
+                        },
+                    },
+                },
+                'x64_Base':
+                {
+                    'abstract': 1,
+                    'msvs_settings':
+                    {
+                        'VCLinkerTool':
+                        {
+                            'AdditionalLibraryDirectories':
+                            [
+                                '<(windows_sdk_path)/Lib/winv6.3/um/x64',
+                            ],
+                        },
+                        'VCLibrarianTool':
+                        {
+                            'AdditionalLibraryDirectories':
+                            [
+                                '<(windows_sdk_path)/Lib/winv6.3/um/x64',
+                            ],
+                        },
+                    },
+                },
+            }],
+        ],
+    },
+}
diff --git a/src/third_party/angle/gyp/gyp_angle b/src/third_party/angle/gyp/gyp_angle
new file mode 100755
index 0000000..b9c9c72
--- /dev/null
+++ b/src/third_party/angle/gyp/gyp_angle
@@ -0,0 +1,79 @@
+#!/usr/bin/python
+
+# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script is wrapper for ANGLE that adds some support for how GYP
+# is invoked by ANGLE beyond what can be done in the gclient hooks.
+
+import os
+import sys
+
+script_dir = os.path.dirname(__file__)
+angle_dir = os.path.normpath(os.path.join(script_dir, os.pardir))
+
+sys.path.insert(0, os.path.join(angle_dir, 'third_party', 'gyp', 'pylib'))
+import gyp
+
+def appendCommonArgs(args):
+    # Set the depth to get the top-level Makefile generated into the
+    # correct directory. This only has an effect on Linux.
+    args.append('--depth');
+    args.append('.');
+    # Add standalone.gypi to the include path to set required
+    # variables that are otherwise picked up from Chromium's gyp
+    # files.
+    args.append('-I' + os.path.join(script_dir, 'standalone.gypi'))
+    # Add common.gypi to the include path.
+    args.append('-I' + os.path.join(script_dir, 'common.gypi'))
+    args.append('--no-parallel')
+
+def generateProjects(generate_args):
+    args = generate_args
+    appendCommonArgs(args)
+    # Add all.gyp as the main gyp file to be generated.
+    args.append(os.path.join(script_dir, 'ANGLE.gyp'))
+
+    gyp.main(args)
+
+def generateWinRTProjects(generate_args, generation_dir, msvs_version, app_type_rev,
+                          target_platform_ver):
+    args = generate_args
+    appendCommonArgs(args)
+
+    args.append('--ignore-environment')
+    args.append('--generator-output=' + generation_dir)
+    args.append('--format=msvs')
+    args.append('-Gmsvs_version=' + msvs_version)
+    args.append('-Dangle_use_commit_id=1')
+    args.append('-Dangle_build_winrt=1')
+    args.append('-Dangle_build_winrt_app_type_revision=' + app_type_rev)
+    args.append('-Dangle_build_winrt_target_platform_ver=' + target_platform_ver)
+    args.append('-Dangle_enable_d3d9=0')
+    args.append('-Dangle_enable_gl=0')
+    args.append('-Dangle_enable_vulkan=0')
+    args.append('-Dangle_enable_null=0')
+    args.append('-Dangle_enable_essl=0')
+    args.append('-Dangle_enable_glsl=0')
+    # Add all.gyp as the main gyp file to be generated.
+    args.append(os.path.join(script_dir, 'ANGLE.gyp'))
+
+    print 'Generating WinRT projects to ' + generation_dir + ' from gyp files...'
+    sys.stdout.flush()
+
+    gyp.main(args)
+
+if __name__ == '__main__':
+    print 'Updating projects from gyp files...'
+    sys.stdout.flush()
+
+    # Generate projects
+    args = sys.argv[1:]
+    generateProjects(args)
+
+    # Generate WinRT projects only if configured
+    if 'GYP_GENERATE_WINRT' in os.environ:
+      # Generate Windows 10 projects
+      args = sys.argv[1:]
+      generateWinRTProjects(args, "winrt/10", "2015", "10.0", "10.0.10240.0");
diff --git a/src/third_party/angle/gyp/standalone.gypi b/src/third_party/angle/gyp/standalone.gypi
new file mode 100644
index 0000000..f18cc04
--- /dev/null
+++ b/src/third_party/angle/gyp/standalone.gypi
@@ -0,0 +1,42 @@
+# Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'variables':
+    {
+        # chromeos=1 is used in some build configurations to disable GL
+        # and GLX code because it typically wouldn't build for Chrome OS.
+        # It does not mean "enable Chrome OS code."
+        'chromeos': 0,
+
+        # Chrome OS chroot builds need a special pkg-config, so make it possible to change.
+        'pkg-config%': 'pkg-config',
+
+        # Use a nested variable trick to get use_x11 evaluated more
+        # eagerly than other conditional variables.
+        'variables':
+        {
+            'variables':
+            {
+                'use_ozone%': 0,
+            },
+            'conditions':
+            [
+                ['OS=="linux" and use_ozone==0',
+                {
+                    'use_x11': 1,
+                },
+                {
+                    'use_x11': 0,
+                }],
+            ],
+
+            # Copy conditionally-set variables out one scope.
+            'use_ozone%': '<(use_ozone)',
+        },
+
+        # Copy conditionally-set variables out one scope.
+        'use_x11%': '<(use_x11)',
+    },
+}
diff --git a/src/third_party/angle/gyp/touch_stamp.py b/src/third_party/angle/gyp/touch_stamp.py
new file mode 100644
index 0000000..162f435
--- /dev/null
+++ b/src/third_party/angle/gyp/touch_stamp.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# touch_stamp.py: similar to the Unix touch command, used to manual make
+#   stamp files when building with GYP
+
+import os
+import sys
+
+stamp_name = sys.argv[1]
+
+with open(stamp_name, 'a'):
+    os.utime(stamp_name, None)
diff --git a/src/third_party/angle/include/EGL/egl.h b/src/third_party/angle/include/EGL/egl.h
index 99ea342..29f30d9 100644
--- a/src/third_party/angle/include/EGL/egl.h
+++ b/src/third_party/angle/include/EGL/egl.h
@@ -1,11 +1,12 @@
-/* -*- mode: c; tab-width: 8; -*- */
-/* vi: set sw=4 ts=8: */
-/* Reference version of egl.h for EGL 1.4.
- * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
- */
+#ifndef __egl_h_
+#define __egl_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /*
-** Copyright (c) 2007-2009 The Khronos Group Inc.
+** Copyright (c) 2013-2017 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
@@ -26,304 +27,277 @@
 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/egl
+**
+** Khronos $Revision$ on $Date$
+*/
 
-#ifndef __egl_h_
-#define __egl_h_
-
-/* All platform-dependent types and macro boilerplate (such as EGLAPI
- * and EGLAPIENTRY) should go in eglplatform.h.
- */
 #include <EGL/eglplatform.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+/* Generated on date 20161230 */
 
-/* EGL Types */
-/* EGLint is defined in eglplatform.h */
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_VERSION_1_0
+#define EGL_VERSION_1_0 1
 typedef unsigned int EGLBoolean;
-typedef unsigned int EGLenum;
-typedef void *EGLConfig;
-typedef void *EGLContext;
 typedef void *EGLDisplay;
+#include <KHR/khrplatform.h>
+#include <EGL/eglplatform.h>
+typedef void *EGLConfig;
 typedef void *EGLSurface;
-typedef void *EGLClientBuffer;
-
-/* EGL Versioning */
-#define EGL_VERSION_1_0			1
-#define EGL_VERSION_1_1			1
-#define EGL_VERSION_1_2			1
-#define EGL_VERSION_1_3			1
-#define EGL_VERSION_1_4			1
-
-/* EGL Enumerants. Bitmasks and other exceptional cases aside, most
- * enums are assigned unique values starting at 0x3000.
- */
-
-/* EGL aliases */
-#define EGL_FALSE			0
-#define EGL_TRUE			1
-
-/* Out-of-band handle values */
-#define EGL_DEFAULT_DISPLAY		((EGLNativeDisplayType)0)
-#define EGL_NO_CONTEXT			((EGLContext)0)
-#define EGL_NO_DISPLAY			((EGLDisplay)0)
-#define EGL_NO_SURFACE			((EGLSurface)0)
-
-/* Out-of-band attribute value */
-#define EGL_DONT_CARE			((EGLint)-1)
-
-/* Errors / GetError return values */
-#define EGL_SUCCESS			0x3000
-#define EGL_NOT_INITIALIZED		0x3001
-#define EGL_BAD_ACCESS			0x3002
-#define EGL_BAD_ALLOC			0x3003
-#define EGL_BAD_ATTRIBUTE		0x3004
-#define EGL_BAD_CONFIG			0x3005
-#define EGL_BAD_CONTEXT			0x3006
-#define EGL_BAD_CURRENT_SURFACE		0x3007
-#define EGL_BAD_DISPLAY			0x3008
-#define EGL_BAD_MATCH			0x3009
-#define EGL_BAD_NATIVE_PIXMAP		0x300A
-#define EGL_BAD_NATIVE_WINDOW		0x300B
-#define EGL_BAD_PARAMETER		0x300C
-#define EGL_BAD_SURFACE			0x300D
-#define EGL_CONTEXT_LOST		0x300E	/* EGL 1.1 - IMG_power_management */
-
-/* Reserved 0x300F-0x301F for additional errors */
-
-/* Config attributes */
-#define EGL_BUFFER_SIZE			0x3020
-#define EGL_ALPHA_SIZE			0x3021
-#define EGL_BLUE_SIZE			0x3022
-#define EGL_GREEN_SIZE			0x3023
-#define EGL_RED_SIZE			0x3024
-#define EGL_DEPTH_SIZE			0x3025
-#define EGL_STENCIL_SIZE		0x3026
-#define EGL_CONFIG_CAVEAT		0x3027
-#define EGL_CONFIG_ID			0x3028
-#define EGL_LEVEL			0x3029
-#define EGL_MAX_PBUFFER_HEIGHT		0x302A
-#define EGL_MAX_PBUFFER_PIXELS		0x302B
-#define EGL_MAX_PBUFFER_WIDTH		0x302C
-#define EGL_NATIVE_RENDERABLE		0x302D
-#define EGL_NATIVE_VISUAL_ID		0x302E
-#define EGL_NATIVE_VISUAL_TYPE		0x302F
-#define EGL_SAMPLES			0x3031
-#define EGL_SAMPLE_BUFFERS		0x3032
-#define EGL_SURFACE_TYPE		0x3033
-#define EGL_TRANSPARENT_TYPE		0x3034
-#define EGL_TRANSPARENT_BLUE_VALUE	0x3035
-#define EGL_TRANSPARENT_GREEN_VALUE	0x3036
-#define EGL_TRANSPARENT_RED_VALUE	0x3037
-#define EGL_NONE			0x3038	/* Attrib list terminator */
-#define EGL_BIND_TO_TEXTURE_RGB		0x3039
-#define EGL_BIND_TO_TEXTURE_RGBA	0x303A
-#define EGL_MIN_SWAP_INTERVAL		0x303B
-#define EGL_MAX_SWAP_INTERVAL		0x303C
-#define EGL_LUMINANCE_SIZE		0x303D
-#define EGL_ALPHA_MASK_SIZE		0x303E
-#define EGL_COLOR_BUFFER_TYPE		0x303F
-#define EGL_RENDERABLE_TYPE		0x3040
-#define EGL_MATCH_NATIVE_PIXMAP		0x3041	/* Pseudo-attribute (not queryable) */
-#define EGL_CONFORMANT			0x3042
-
-/* Reserved 0x3041-0x304F for additional config attributes */
-
-/* Config attribute values */
-#define EGL_SLOW_CONFIG			0x3050	/* EGL_CONFIG_CAVEAT value */
-#define EGL_NON_CONFORMANT_CONFIG	0x3051	/* EGL_CONFIG_CAVEAT value */
-#define EGL_TRANSPARENT_RGB		0x3052	/* EGL_TRANSPARENT_TYPE value */
-#define EGL_RGB_BUFFER			0x308E	/* EGL_COLOR_BUFFER_TYPE value */
-#define EGL_LUMINANCE_BUFFER		0x308F	/* EGL_COLOR_BUFFER_TYPE value */
-
-/* More config attribute values, for EGL_TEXTURE_FORMAT */
-#define EGL_NO_TEXTURE			0x305C
-#define EGL_TEXTURE_RGB			0x305D
-#define EGL_TEXTURE_RGBA		0x305E
-#define EGL_TEXTURE_2D			0x305F
-
-/* Config attribute mask bits */
-#define EGL_PBUFFER_BIT			0x0001	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_PIXMAP_BIT			0x0002	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_WINDOW_BIT			0x0004	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_VG_COLORSPACE_LINEAR_BIT	0x0020	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_VG_ALPHA_FORMAT_PRE_BIT	0x0040	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400	/* EGL_SURFACE_TYPE mask bits */
-
-#define EGL_OPENGL_ES_BIT		0x0001	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_OPENVG_BIT			0x0002	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_OPENGL_ES2_BIT		0x0004	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_OPENGL_BIT			0x0008	/* EGL_RENDERABLE_TYPE mask bits */
-
-/* QueryString targets */
-#define EGL_VENDOR			0x3053
-#define EGL_VERSION			0x3054
-#define EGL_EXTENSIONS			0x3055
-#define EGL_CLIENT_APIS			0x308D
-
-/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */
-#define EGL_HEIGHT			0x3056
-#define EGL_WIDTH			0x3057
-#define EGL_LARGEST_PBUFFER		0x3058
-#define EGL_TEXTURE_FORMAT		0x3080
-#define EGL_TEXTURE_TARGET		0x3081
-#define EGL_MIPMAP_TEXTURE		0x3082
-#define EGL_MIPMAP_LEVEL		0x3083
-#define EGL_RENDER_BUFFER		0x3086
-#define EGL_VG_COLORSPACE		0x3087
-#define EGL_VG_ALPHA_FORMAT		0x3088
-#define EGL_HORIZONTAL_RESOLUTION	0x3090
-#define EGL_VERTICAL_RESOLUTION		0x3091
-#define EGL_PIXEL_ASPECT_RATIO		0x3092
-#define EGL_SWAP_BEHAVIOR		0x3093
-#define EGL_MULTISAMPLE_RESOLVE		0x3099
-
-/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */
-#define EGL_BACK_BUFFER			0x3084
-#define EGL_SINGLE_BUFFER		0x3085
-
-/* OpenVG color spaces */
-#define EGL_VG_COLORSPACE_sRGB		0x3089	/* EGL_VG_COLORSPACE value */
-#define EGL_VG_COLORSPACE_LINEAR	0x308A	/* EGL_VG_COLORSPACE value */
-
-/* OpenVG alpha formats */
-#define EGL_VG_ALPHA_FORMAT_NONPRE	0x308B	/* EGL_ALPHA_FORMAT value */
-#define EGL_VG_ALPHA_FORMAT_PRE		0x308C	/* EGL_ALPHA_FORMAT value */
-
-/* Constant scale factor by which fractional display resolutions &
- * aspect ratio are scaled when queried as integer values.
- */
-#define EGL_DISPLAY_SCALING		10000
-
-/* Unknown display resolution/aspect ratio */
-#define EGL_UNKNOWN			((EGLint)-1)
-
-/* Back buffer swap behaviors */
-#define EGL_BUFFER_PRESERVED		0x3094	/* EGL_SWAP_BEHAVIOR value */
-#define EGL_BUFFER_DESTROYED		0x3095	/* EGL_SWAP_BEHAVIOR value */
-
-/* CreatePbufferFromClientBuffer buffer types */
-#define EGL_OPENVG_IMAGE		0x3096
-
-/* QueryContext targets */
-#define EGL_CONTEXT_CLIENT_TYPE		0x3097
-
-/* CreateContext attributes */
-#define EGL_CONTEXT_CLIENT_VERSION	0x3098
-
-/* Multisample resolution behaviors */
-#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A	/* EGL_MULTISAMPLE_RESOLVE value */
-#define EGL_MULTISAMPLE_RESOLVE_BOX	0x309B	/* EGL_MULTISAMPLE_RESOLVE value */
-
-/* BindAPI/QueryAPI targets */
-#define EGL_OPENGL_ES_API		0x30A0
-#define EGL_OPENVG_API			0x30A1
-#define EGL_OPENGL_API			0x30A2
-
-/* GetCurrentSurface targets */
-#define EGL_DRAW			0x3059
-#define EGL_READ			0x305A
-
-/* WaitNative engines */
-#define EGL_CORE_NATIVE_ENGINE		0x305B
-
-/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */
-#define EGL_COLORSPACE			EGL_VG_COLORSPACE
-#define EGL_ALPHA_FORMAT		EGL_VG_ALPHA_FORMAT
-#define EGL_COLORSPACE_sRGB		EGL_VG_COLORSPACE_sRGB
-#define EGL_COLORSPACE_LINEAR		EGL_VG_COLORSPACE_LINEAR
-#define EGL_ALPHA_FORMAT_NONPRE		EGL_VG_ALPHA_FORMAT_NONPRE
-#define EGL_ALPHA_FORMAT_PRE		EGL_VG_ALPHA_FORMAT_PRE
-
-/* EGL extensions must request enum blocks from the Khronos
- * API Registrar, who maintains the enumerant registry. Submit
- * a bug in Khronos Bugzilla against task "Registry".
- */
-
-
-
-/* EGL Functions */
-
-EGLAPI EGLint EGLAPIENTRY eglGetError(void);
-
-EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
-EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
-EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
-
-EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
-			 EGLint config_size, EGLint *num_config);
-EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
-			   EGLConfig *configs, EGLint config_size,
-			   EGLint *num_config);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
-			      EGLint attribute, EGLint *value);
-
-EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
-				  EGLNativeWindowType win,
-				  const EGLint *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
-				   const EGLint *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
-				  EGLNativePixmapType pixmap,
-				  const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
-EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
-			   EGLint attribute, EGLint *value);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);
-EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void);
-
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
-	      EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
-	      EGLConfig config, const EGLint *attrib_list);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
-			    EGLint attribute, EGLint value);
-EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-
-
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
-
-
-EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config,
-			    EGLContext share_context,
-			    const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
-EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
-			  EGLSurface read, EGLContext ctx);
-
-EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
-EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
-EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
-			   EGLint attribute, EGLint *value);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
-EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
-			  EGLNativePixmapType target);
-
-/* This is a generic function pointer type, whose name indicates it must
- * be cast to the proper type *and calling convention* before use.
- */
+typedef void *EGLContext;
 typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+#define EGL_ALPHA_SIZE                    0x3021
+#define EGL_BAD_ACCESS                    0x3002
+#define EGL_BAD_ALLOC                     0x3003
+#define EGL_BAD_ATTRIBUTE                 0x3004
+#define EGL_BAD_CONFIG                    0x3005
+#define EGL_BAD_CONTEXT                   0x3006
+#define EGL_BAD_CURRENT_SURFACE           0x3007
+#define EGL_BAD_DISPLAY                   0x3008
+#define EGL_BAD_MATCH                     0x3009
+#define EGL_BAD_NATIVE_PIXMAP             0x300A
+#define EGL_BAD_NATIVE_WINDOW             0x300B
+#define EGL_BAD_PARAMETER                 0x300C
+#define EGL_BAD_SURFACE                   0x300D
+#define EGL_BLUE_SIZE                     0x3022
+#define EGL_BUFFER_SIZE                   0x3020
+#define EGL_CONFIG_CAVEAT                 0x3027
+#define EGL_CONFIG_ID                     0x3028
+#define EGL_CORE_NATIVE_ENGINE            0x305B
+#define EGL_DEPTH_SIZE                    0x3025
+#define EGL_DONT_CARE                     EGL_CAST(EGLint,-1)
+#define EGL_DRAW                          0x3059
+#define EGL_EXTENSIONS                    0x3055
+#define EGL_FALSE                         0
+#define EGL_GREEN_SIZE                    0x3023
+#define EGL_HEIGHT                        0x3056
+#define EGL_LARGEST_PBUFFER               0x3058
+#define EGL_LEVEL                         0x3029
+#define EGL_MAX_PBUFFER_HEIGHT            0x302A
+#define EGL_MAX_PBUFFER_PIXELS            0x302B
+#define EGL_MAX_PBUFFER_WIDTH             0x302C
+#define EGL_NATIVE_RENDERABLE             0x302D
+#define EGL_NATIVE_VISUAL_ID              0x302E
+#define EGL_NATIVE_VISUAL_TYPE            0x302F
+#define EGL_NONE                          0x3038
+#define EGL_NON_CONFORMANT_CONFIG         0x3051
+#define EGL_NOT_INITIALIZED               0x3001
+#define EGL_NO_CONTEXT                    EGL_CAST(EGLContext,0)
+#define EGL_NO_DISPLAY                    EGL_CAST(EGLDisplay,0)
+#define EGL_NO_SURFACE                    EGL_CAST(EGLSurface,0)
+#define EGL_PBUFFER_BIT                   0x0001
+#define EGL_PIXMAP_BIT                    0x0002
+#define EGL_READ                          0x305A
+#define EGL_RED_SIZE                      0x3024
+#define EGL_SAMPLES                       0x3031
+#define EGL_SAMPLE_BUFFERS                0x3032
+#define EGL_SLOW_CONFIG                   0x3050
+#define EGL_STENCIL_SIZE                  0x3026
+#define EGL_SUCCESS                       0x3000
+#define EGL_SURFACE_TYPE                  0x3033
+#define EGL_TRANSPARENT_BLUE_VALUE        0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE       0x3036
+#define EGL_TRANSPARENT_RED_VALUE         0x3037
+#define EGL_TRANSPARENT_RGB               0x3052
+#define EGL_TRANSPARENT_TYPE              0x3034
+#define EGL_TRUE                          1
+#define EGL_VENDOR                        0x3053
+#define EGL_VERSION                       0x3054
+#define EGL_WIDTH                         0x3057
+#define EGL_WINDOW_BIT                    0x0004
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id);
+EGLAPI EGLint EGLAPIENTRY eglGetError (void);
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine);
+#endif /* EGL_VERSION_1_0 */
 
-/* Now, define eglGetProcAddress using the generic function ptr. type */
-EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
-       eglGetProcAddress(const char *procname);
+#ifndef EGL_VERSION_1_1
+#define EGL_VERSION_1_1 1
+#define EGL_BACK_BUFFER                   0x3084
+#define EGL_BIND_TO_TEXTURE_RGB           0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA          0x303A
+#define EGL_CONTEXT_LOST                  0x300E
+#define EGL_MIN_SWAP_INTERVAL             0x303B
+#define EGL_MAX_SWAP_INTERVAL             0x303C
+#define EGL_MIPMAP_TEXTURE                0x3082
+#define EGL_MIPMAP_LEVEL                  0x3083
+#define EGL_NO_TEXTURE                    0x305C
+#define EGL_TEXTURE_2D                    0x305F
+#define EGL_TEXTURE_FORMAT                0x3080
+#define EGL_TEXTURE_RGB                   0x305D
+#define EGL_TEXTURE_RGBA                  0x305E
+#define EGL_TEXTURE_TARGET                0x3081
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval);
+#endif /* EGL_VERSION_1_1 */
+
+#ifndef EGL_VERSION_1_2
+#define EGL_VERSION_1_2 1
+typedef unsigned int EGLenum;
+typedef void *EGLClientBuffer;
+#define EGL_ALPHA_FORMAT                  0x3088
+#define EGL_ALPHA_FORMAT_NONPRE           0x308B
+#define EGL_ALPHA_FORMAT_PRE              0x308C
+#define EGL_ALPHA_MASK_SIZE               0x303E
+#define EGL_BUFFER_PRESERVED              0x3094
+#define EGL_BUFFER_DESTROYED              0x3095
+#define EGL_CLIENT_APIS                   0x308D
+#define EGL_COLORSPACE                    0x3087
+#define EGL_COLORSPACE_sRGB               0x3089
+#define EGL_COLORSPACE_LINEAR             0x308A
+#define EGL_COLOR_BUFFER_TYPE             0x303F
+#define EGL_CONTEXT_CLIENT_TYPE           0x3097
+#define EGL_DISPLAY_SCALING               10000
+#define EGL_HORIZONTAL_RESOLUTION         0x3090
+#define EGL_LUMINANCE_BUFFER              0x308F
+#define EGL_LUMINANCE_SIZE                0x303D
+#define EGL_OPENGL_ES_BIT                 0x0001
+#define EGL_OPENVG_BIT                    0x0002
+#define EGL_OPENGL_ES_API                 0x30A0
+#define EGL_OPENVG_API                    0x30A1
+#define EGL_OPENVG_IMAGE                  0x3096
+#define EGL_PIXEL_ASPECT_RATIO            0x3092
+#define EGL_RENDERABLE_TYPE               0x3040
+#define EGL_RENDER_BUFFER                 0x3086
+#define EGL_RGB_BUFFER                    0x308E
+#define EGL_SINGLE_BUFFER                 0x3085
+#define EGL_SWAP_BEHAVIOR                 0x3093
+#define EGL_UNKNOWN                       EGL_CAST(EGLint,-1)
+#define EGL_VERTICAL_RESOLUTION           0x3091
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api);
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void);
+#endif /* EGL_VERSION_1_2 */
+
+#ifndef EGL_VERSION_1_3
+#define EGL_VERSION_1_3 1
+#define EGL_CONFORMANT                    0x3042
+#define EGL_CONTEXT_CLIENT_VERSION        0x3098
+#define EGL_MATCH_NATIVE_PIXMAP           0x3041
+#define EGL_OPENGL_ES2_BIT                0x0004
+#define EGL_VG_ALPHA_FORMAT               0x3088
+#define EGL_VG_ALPHA_FORMAT_NONPRE        0x308B
+#define EGL_VG_ALPHA_FORMAT_PRE           0x308C
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT       0x0040
+#define EGL_VG_COLORSPACE                 0x3087
+#define EGL_VG_COLORSPACE_sRGB            0x3089
+#define EGL_VG_COLORSPACE_LINEAR          0x308A
+#define EGL_VG_COLORSPACE_LINEAR_BIT      0x0020
+#endif /* EGL_VERSION_1_3 */
+
+#ifndef EGL_VERSION_1_4
+#define EGL_VERSION_1_4 1
+#define EGL_DEFAULT_DISPLAY               EGL_CAST(EGLNativeDisplayType,0)
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT   0x0200
+#define EGL_MULTISAMPLE_RESOLVE           0x3099
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT   0x309A
+#define EGL_MULTISAMPLE_RESOLVE_BOX       0x309B
+#define EGL_OPENGL_API                    0x30A2
+#define EGL_OPENGL_BIT                    0x0008
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT   0x0400
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
+#endif /* EGL_VERSION_1_4 */
+
+#ifndef EGL_VERSION_1_5
+#define EGL_VERSION_1_5 1
+typedef void *EGLSync;
+typedef intptr_t EGLAttrib;
+typedef khronos_utime_nanoseconds_t EGLTime;
+typedef void *EGLImage;
+#define EGL_CONTEXT_MAJOR_VERSION         0x3098
+#define EGL_CONTEXT_MINOR_VERSION         0x30FB
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK   0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
+#define EGL_NO_RESET_NOTIFICATION         0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET         0x31BF
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define EGL_CONTEXT_OPENGL_DEBUG          0x31B0
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS  0x31B2
+#define EGL_OPENGL_ES3_BIT                0x00000040
+#define EGL_CL_EVENT_HANDLE               0x309C
+#define EGL_SYNC_CL_EVENT                 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE        0x30FF
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE  0x30F0
+#define EGL_SYNC_TYPE                     0x30F7
+#define EGL_SYNC_STATUS                   0x30F1
+#define EGL_SYNC_CONDITION                0x30F8
+#define EGL_SIGNALED                      0x30F2
+#define EGL_UNSIGNALED                    0x30F3
+#define EGL_SYNC_FLUSH_COMMANDS_BIT       0x0001
+#define EGL_FOREVER                       0xFFFFFFFFFFFFFFFFull
+#define EGL_TIMEOUT_EXPIRED               0x30F5
+#define EGL_CONDITION_SATISFIED           0x30F6
+#define EGL_NO_SYNC                       EGL_CAST(EGLSync,0)
+#define EGL_SYNC_FENCE                    0x30F9
+#define EGL_GL_COLORSPACE                 0x309D
+#define EGL_GL_COLORSPACE_SRGB            0x3089
+#define EGL_GL_COLORSPACE_LINEAR          0x308A
+#define EGL_GL_RENDERBUFFER               0x30B9
+#define EGL_GL_TEXTURE_2D                 0x30B1
+#define EGL_GL_TEXTURE_LEVEL              0x30BC
+#define EGL_GL_TEXTURE_3D                 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET            0x30BD
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+#define EGL_IMAGE_PRESERVED               0x30D2
+#define EGL_NO_IMAGE                      EGL_CAST(EGLImage,0)
+EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags);
+#endif /* EGL_VERSION_1_5 */
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __egl_h_ */
+#endif
diff --git a/src/third_party/angle/include/EGL/eglext.h b/src/third_party/angle/include/EGL/eglext.h
index 3f923f9..bfd4213 100644
--- a/src/third_party/angle/include/EGL/eglext.h
+++ b/src/third_party/angle/include/EGL/eglext.h
@@ -1,12 +1,12 @@
 #ifndef __eglext_h_
-#define __eglext_h_
+#define __eglext_h_ 1
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
-** Copyright (c) 2007-2012 The Khronos Group Inc.
+** Copyright (c) 2013-2017 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
@@ -27,389 +27,1279 @@
 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/egl
+**
+** Khronos $Revision$ on $Date$
+*/
 
 #include <EGL/eglplatform.h>
 
-/*************************************************************/
+#define EGL_EGLEXT_VERSION 20161230
 
-/* Header file version number */
-/* Current version at http://www.khronos.org/registry/egl/ */
-/* $Revision: 16473 $ on $Date: 2012-01-04 02:20:48 -0800 (Wed, 04 Jan 2012) $ */
-#define EGL_EGLEXT_VERSION 11
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: _nomatch_^
+ * Default extensions included: egl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_KHR_cl_event
+#define EGL_KHR_cl_event 1
+#define EGL_CL_EVENT_HANDLE_KHR           0x309C
+#define EGL_SYNC_CL_EVENT_KHR             0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE_KHR    0x30FF
+#endif /* EGL_KHR_cl_event */
+
+#ifndef EGL_KHR_cl_event2
+#define EGL_KHR_cl_event2 1
+typedef void *EGLSyncKHR;
+typedef intptr_t EGLAttribKHR;
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#endif
+#endif /* EGL_KHR_cl_event2 */
+
+#ifndef EGL_KHR_client_get_all_proc_addresses
+#define EGL_KHR_client_get_all_proc_addresses 1
+#endif /* EGL_KHR_client_get_all_proc_addresses */
 
 #ifndef EGL_KHR_config_attribs
 #define EGL_KHR_config_attribs 1
-#define EGL_CONFORMANT_KHR			0x3042	/* EGLConfig attribute */
-#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR	0x0020	/* EGL_SURFACE_TYPE bitfield */
-#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR		0x0040	/* EGL_SURFACE_TYPE bitfield */
-#endif
+#define EGL_CONFORMANT_KHR                0x3042
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR  0x0020
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR   0x0040
+#endif /* EGL_KHR_config_attribs */
 
-#ifndef EGL_KHR_lock_surface
-#define EGL_KHR_lock_surface 1
-#define EGL_READ_SURFACE_BIT_KHR		0x0001	/* EGL_LOCK_USAGE_HINT_KHR bitfield */
-#define EGL_WRITE_SURFACE_BIT_KHR		0x0002	/* EGL_LOCK_USAGE_HINT_KHR bitfield */
-#define EGL_LOCK_SURFACE_BIT_KHR		0x0080	/* EGL_SURFACE_TYPE bitfield */
-#define EGL_OPTIMAL_FORMAT_BIT_KHR		0x0100	/* EGL_SURFACE_TYPE bitfield */
-#define EGL_MATCH_FORMAT_KHR			0x3043	/* EGLConfig attribute */
-#define EGL_FORMAT_RGB_565_EXACT_KHR		0x30C0	/* EGL_MATCH_FORMAT_KHR value */
-#define EGL_FORMAT_RGB_565_KHR			0x30C1	/* EGL_MATCH_FORMAT_KHR value */
-#define EGL_FORMAT_RGBA_8888_EXACT_KHR		0x30C2	/* EGL_MATCH_FORMAT_KHR value */
-#define EGL_FORMAT_RGBA_8888_KHR		0x30C3	/* EGL_MATCH_FORMAT_KHR value */
-#define EGL_MAP_PRESERVE_PIXELS_KHR		0x30C4	/* eglLockSurfaceKHR attribute */
-#define EGL_LOCK_USAGE_HINT_KHR			0x30C5	/* eglLockSurfaceKHR attribute */
-#define EGL_BITMAP_POINTER_KHR			0x30C6	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PITCH_KHR			0x30C7	/* eglQuerySurface attribute */
-#define EGL_BITMAP_ORIGIN_KHR			0x30C8	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR		0x30C9	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR	0x30CA	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR	0x30CB	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR	0x30CC	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR	0x30CD	/* eglQuerySurface attribute */
-#define EGL_LOWER_LEFT_KHR			0x30CE	/* EGL_BITMAP_ORIGIN_KHR value */
-#define EGL_UPPER_LEFT_KHR			0x30CF	/* EGL_BITMAP_ORIGIN_KHR value */
+#ifndef EGL_KHR_context_flush_control
+#define EGL_KHR_context_flush_control 1
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR  0x2097
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
+#endif /* EGL_KHR_context_flush_control */
+
+#ifndef EGL_KHR_create_context
+#define EGL_KHR_create_context 1
+#define EGL_CONTEXT_MAJOR_VERSION_KHR     0x3098
+#define EGL_CONTEXT_MINOR_VERSION_KHR     0x30FB
+#define EGL_CONTEXT_FLAGS_KHR             0x30FC
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
+#define EGL_NO_RESET_NOTIFICATION_KHR     0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_KHR     0x31BF
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR  0x00000001
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#define EGL_OPENGL_ES3_BIT_KHR            0x00000040
+#endif /* EGL_KHR_create_context */
+
+#ifndef EGL_KHR_create_context_no_error
+#define EGL_KHR_create_context_no_error 1
+#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR   0x31B3
+#endif /* EGL_KHR_create_context_no_error */
+
+#ifndef EGL_KHR_debug
+#define EGL_KHR_debug 1
+typedef void *EGLLabelKHR;
+typedef void *EGLObjectKHR;
+typedef void (EGLAPIENTRY  *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message);
+#define EGL_OBJECT_THREAD_KHR             0x33B0
+#define EGL_OBJECT_DISPLAY_KHR            0x33B1
+#define EGL_OBJECT_CONTEXT_KHR            0x33B2
+#define EGL_OBJECT_SURFACE_KHR            0x33B3
+#define EGL_OBJECT_IMAGE_KHR              0x33B4
+#define EGL_OBJECT_SYNC_KHR               0x33B5
+#define EGL_OBJECT_STREAM_KHR             0x33B6
+#define EGL_DEBUG_MSG_CRITICAL_KHR        0x33B9
+#define EGL_DEBUG_MSG_ERROR_KHR           0x33BA
+#define EGL_DEBUG_MSG_WARN_KHR            0x33BB
+#define EGL_DEBUG_MSG_INFO_KHR            0x33BC
+#define EGL_DEBUG_CALLBACK_KHR            0x33B8
+typedef EGLint (EGLAPIENTRYP PFNEGLDEBUGMESSAGECONTROLKHRPROC) (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEBUGKHRPROC) (EGLint attribute, EGLAttrib *value);
+typedef EGLint (EGLAPIENTRYP PFNEGLLABELOBJECTKHRPROC) (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay display, EGLSurface surface);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface);
+EGLAPI EGLint EGLAPIENTRY eglDebugMessageControlKHR (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDebugKHR (EGLint attribute, EGLAttrib *value);
+EGLAPI EGLint EGLAPIENTRY eglLabelObjectKHR (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
 #endif
+#endif /* EGL_KHR_debug */
 
-#ifndef EGL_KHR_image
-#define EGL_KHR_image 1
-#define EGL_NATIVE_PIXMAP_KHR			0x30B0	/* eglCreateImageKHR target */
-typedef void *EGLImageKHR;
-#define EGL_NO_IMAGE_KHR			((EGLImageKHR)0)
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
-#endif
-
-#ifndef EGL_KHR_vg_parent_image
-#define EGL_KHR_vg_parent_image 1
-#define EGL_VG_PARENT_IMAGE_KHR			0x30BA	/* eglCreateImageKHR target */
-#endif
-
-#ifndef EGL_KHR_gl_texture_2D_image
-#define EGL_KHR_gl_texture_2D_image 1
-#define EGL_GL_TEXTURE_2D_KHR			0x30B1	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_LEVEL_KHR		0x30BC	/* eglCreateImageKHR attribute */
-#endif
-
-#ifndef EGL_KHR_gl_texture_cubemap_image
-#define EGL_KHR_gl_texture_cubemap_image 1
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR	0x30B3	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR	0x30B4	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR	0x30B5	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR	0x30B6	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR	0x30B7	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR	0x30B8	/* eglCreateImageKHR target */
-#endif
-
-#ifndef EGL_KHR_gl_texture_3D_image
-#define EGL_KHR_gl_texture_3D_image 1
-#define EGL_GL_TEXTURE_3D_KHR			0x30B2	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_ZOFFSET_KHR		0x30BD	/* eglCreateImageKHR attribute */
-#endif
-
-#ifndef EGL_KHR_gl_renderbuffer_image
-#define EGL_KHR_gl_renderbuffer_image 1
-#define EGL_GL_RENDERBUFFER_KHR			0x30B9	/* eglCreateImageKHR target */
-#endif
-
-#if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
-#ifndef EGL_KHR_reusable_sync
-#define EGL_KHR_reusable_sync 1
-
-typedef void* EGLSyncKHR;
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
 typedef khronos_utime_nanoseconds_t EGLTimeKHR;
-
-#define EGL_SYNC_STATUS_KHR			0x30F1
-#define EGL_SIGNALED_KHR			0x30F2
-#define EGL_UNSIGNALED_KHR			0x30F3
-#define EGL_TIMEOUT_EXPIRED_KHR			0x30F5
-#define EGL_CONDITION_SATISFIED_KHR		0x30F6
-#define EGL_SYNC_TYPE_KHR			0x30F7
-#define EGL_SYNC_REUSABLE_KHR			0x30FA
-#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR		0x0001	/* eglClientWaitSyncKHR <flags> bitfield */
-#define EGL_FOREVER_KHR				0xFFFFFFFFFFFFFFFFull
-#define EGL_NO_SYNC_KHR				((EGLSyncKHR)0)
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync);
-EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
-EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
-#endif /* EGL_EGLEXT_PROTOTYPES */
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define EGL_SYNC_CONDITION_KHR            0x30F8
+#define EGL_SYNC_FENCE_KHR                0x30F9
 typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
 typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
 #endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_fence_sync */
+
+#ifndef EGL_KHR_get_all_proc_addresses
+#define EGL_KHR_get_all_proc_addresses 1
+#endif /* EGL_KHR_get_all_proc_addresses */
+
+#ifndef EGL_KHR_gl_colorspace
+#define EGL_KHR_gl_colorspace 1
+#define EGL_GL_COLORSPACE_KHR             0x309D
+#define EGL_GL_COLORSPACE_SRGB_KHR        0x3089
+#define EGL_GL_COLORSPACE_LINEAR_KHR      0x308A
+#endif /* EGL_KHR_gl_colorspace */
+
+#ifndef EGL_KHR_gl_renderbuffer_image
+#define EGL_KHR_gl_renderbuffer_image 1
+#define EGL_GL_RENDERBUFFER_KHR           0x30B9
+#endif /* EGL_KHR_gl_renderbuffer_image */
+
+#ifndef EGL_KHR_gl_texture_2D_image
+#define EGL_KHR_gl_texture_2D_image 1
+#define EGL_GL_TEXTURE_2D_KHR             0x30B1
+#define EGL_GL_TEXTURE_LEVEL_KHR          0x30BC
+#endif /* EGL_KHR_gl_texture_2D_image */
+
+#ifndef EGL_KHR_gl_texture_3D_image
+#define EGL_KHR_gl_texture_3D_image 1
+#define EGL_GL_TEXTURE_3D_KHR             0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET_KHR        0x30BD
+#endif /* EGL_KHR_gl_texture_3D_image */
+
+#ifndef EGL_KHR_gl_texture_cubemap_image
+#define EGL_KHR_gl_texture_cubemap_image 1
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
+#endif /* EGL_KHR_gl_texture_cubemap_image */
+
+#ifndef EGL_KHR_image
+#define EGL_KHR_image 1
+typedef void *EGLImageKHR;
+#define EGL_NATIVE_PIXMAP_KHR             0x30B0
+#define EGL_NO_IMAGE_KHR                  EGL_CAST(EGLImageKHR,0)
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
 #endif
+#endif /* EGL_KHR_image */
 
 #ifndef EGL_KHR_image_base
 #define EGL_KHR_image_base 1
-/* Most interfaces defined by EGL_KHR_image_pixmap above */
-#define EGL_IMAGE_PRESERVED_KHR			0x30D2	/* eglCreateImageKHR attribute */
-#endif
+#define EGL_IMAGE_PRESERVED_KHR           0x30D2
+#endif /* EGL_KHR_image_base */
 
 #ifndef EGL_KHR_image_pixmap
 #define EGL_KHR_image_pixmap 1
-/* Interfaces defined by EGL_KHR_image above */
-#endif
+#endif /* EGL_KHR_image_pixmap */
 
-#ifndef EGL_IMG_context_priority
-#define EGL_IMG_context_priority 1
-#define EGL_CONTEXT_PRIORITY_LEVEL_IMG		0x3100
-#define EGL_CONTEXT_PRIORITY_HIGH_IMG		0x3101
-#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG		0x3102
-#define EGL_CONTEXT_PRIORITY_LOW_IMG		0x3103
+#ifndef EGL_KHR_lock_surface
+#define EGL_KHR_lock_surface 1
+#define EGL_READ_SURFACE_BIT_KHR          0x0001
+#define EGL_WRITE_SURFACE_BIT_KHR         0x0002
+#define EGL_LOCK_SURFACE_BIT_KHR          0x0080
+#define EGL_OPTIMAL_FORMAT_BIT_KHR        0x0100
+#define EGL_MATCH_FORMAT_KHR              0x3043
+#define EGL_FORMAT_RGB_565_EXACT_KHR      0x30C0
+#define EGL_FORMAT_RGB_565_KHR            0x30C1
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR    0x30C2
+#define EGL_FORMAT_RGBA_8888_KHR          0x30C3
+#define EGL_MAP_PRESERVE_PIXELS_KHR       0x30C4
+#define EGL_LOCK_USAGE_HINT_KHR           0x30C5
+#define EGL_BITMAP_POINTER_KHR            0x30C6
+#define EGL_BITMAP_PITCH_KHR              0x30C7
+#define EGL_BITMAP_ORIGIN_KHR             0x30C8
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR   0x30C9
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR  0x30CB
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
+#define EGL_LOWER_LEFT_KHR                0x30CE
+#define EGL_UPPER_LEFT_KHR                0x30CF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface);
 #endif
+#endif /* EGL_KHR_lock_surface */
 
 #ifndef EGL_KHR_lock_surface2
 #define EGL_KHR_lock_surface2 1
-#define EGL_BITMAP_PIXEL_SIZE_KHR		0x3110
+#define EGL_BITMAP_PIXEL_SIZE_KHR         0x3110
+#endif /* EGL_KHR_lock_surface2 */
+
+#ifndef EGL_KHR_lock_surface3
+#define EGL_KHR_lock_surface3 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
 #endif
+#endif /* EGL_KHR_lock_surface3 */
+
+#ifndef EGL_KHR_mutable_render_buffer
+#define EGL_KHR_mutable_render_buffer 1
+#define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
+#endif /* EGL_KHR_mutable_render_buffer */
+
+#ifndef EGL_KHR_no_config_context
+#define EGL_KHR_no_config_context 1
+#define EGL_NO_CONFIG_KHR                 EGL_CAST(EGLConfig,0)
+#endif /* EGL_KHR_no_config_context */
+
+#ifndef EGL_KHR_partial_update
+#define EGL_KHR_partial_update 1
+#define EGL_BUFFER_AGE_KHR                0x313D
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_partial_update */
+
+#ifndef EGL_KHR_platform_android
+#define EGL_KHR_platform_android 1
+#define EGL_PLATFORM_ANDROID_KHR          0x3141
+#endif /* EGL_KHR_platform_android */
+
+#ifndef EGL_KHR_platform_gbm
+#define EGL_KHR_platform_gbm 1
+#define EGL_PLATFORM_GBM_KHR              0x31D7
+#endif /* EGL_KHR_platform_gbm */
+
+#ifndef EGL_KHR_platform_wayland
+#define EGL_KHR_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_KHR          0x31D8
+#endif /* EGL_KHR_platform_wayland */
+
+#ifndef EGL_KHR_platform_x11
+#define EGL_KHR_platform_x11 1
+#define EGL_PLATFORM_X11_KHR              0x31D5
+#define EGL_PLATFORM_X11_SCREEN_KHR       0x31D6
+#endif /* EGL_KHR_platform_x11 */
+
+#ifndef EGL_KHR_reusable_sync
+#define EGL_KHR_reusable_sync 1
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_STATUS_KHR               0x30F1
+#define EGL_SIGNALED_KHR                  0x30F2
+#define EGL_UNSIGNALED_KHR                0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR           0x30F5
+#define EGL_CONDITION_SATISFIED_KHR       0x30F6
+#define EGL_SYNC_TYPE_KHR                 0x30F7
+#define EGL_SYNC_REUSABLE_KHR             0x30FA
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR   0x0001
+#define EGL_FOREVER_KHR                   0xFFFFFFFFFFFFFFFFull
+#define EGL_NO_SYNC_KHR                   EGL_CAST(EGLSyncKHR,0)
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_reusable_sync */
+
+#ifndef EGL_KHR_stream
+#define EGL_KHR_stream 1
+typedef void *EGLStreamKHR;
+typedef khronos_uint64_t EGLuint64KHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_NO_STREAM_KHR                 EGL_CAST(EGLStreamKHR,0)
+#define EGL_CONSUMER_LATENCY_USEC_KHR     0x3210
+#define EGL_PRODUCER_FRAME_KHR            0x3212
+#define EGL_CONSUMER_FRAME_KHR            0x3213
+#define EGL_STREAM_STATE_KHR              0x3214
+#define EGL_STREAM_STATE_CREATED_KHR      0x3215
+#define EGL_STREAM_STATE_CONNECTING_KHR   0x3216
+#define EGL_STREAM_STATE_EMPTY_KHR        0x3217
+#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
+#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
+#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
+#define EGL_BAD_STREAM_KHR                0x321B
+#define EGL_BAD_STATE_KHR                 0x321C
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_stream */
+
+#ifndef EGL_KHR_stream_attrib
+#define EGL_KHR_stream_attrib 1
+#ifdef KHRONOS_SUPPORT_INT64
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBKHRPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamAttribKHR (EGLDisplay dpy, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_stream_attrib */
+
+#ifndef EGL_KHR_stream_consumer_gltexture
+#define EGL_KHR_stream_consumer_gltexture 1
+#ifdef EGL_KHR_stream
+#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_consumer_gltexture */
+
+#ifndef EGL_KHR_stream_cross_process_fd
+#define EGL_KHR_stream_cross_process_fd 1
+typedef int EGLNativeFileDescriptorKHR;
+#ifdef EGL_KHR_stream
+#define EGL_NO_FILE_DESCRIPTOR_KHR        EGL_CAST(EGLNativeFileDescriptorKHR,-1)
+typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_cross_process_fd */
+
+#ifndef EGL_KHR_stream_fifo
+#define EGL_KHR_stream_fifo 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_FIFO_LENGTH_KHR        0x31FC
+#define EGL_STREAM_TIME_NOW_KHR           0x31FD
+#define EGL_STREAM_TIME_CONSUMER_KHR      0x31FE
+#define EGL_STREAM_TIME_PRODUCER_KHR      0x31FF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_fifo */
+
+#ifndef EGL_KHR_stream_producer_aldatalocator
+#define EGL_KHR_stream_producer_aldatalocator 1
+#ifdef EGL_KHR_stream
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_aldatalocator */
+
+#ifndef EGL_KHR_stream_producer_eglsurface
+#define EGL_KHR_stream_producer_eglsurface 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_BIT_KHR                0x0800
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_eglsurface */
+
+#ifndef EGL_KHR_surfaceless_context
+#define EGL_KHR_surfaceless_context 1
+#endif /* EGL_KHR_surfaceless_context */
+
+#ifndef EGL_KHR_swap_buffers_with_damage
+#define EGL_KHR_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_swap_buffers_with_damage */
+
+#ifndef EGL_KHR_vg_parent_image
+#define EGL_KHR_vg_parent_image 1
+#define EGL_VG_PARENT_IMAGE_KHR           0x30BA
+#endif /* EGL_KHR_vg_parent_image */
+
+#ifndef EGL_KHR_wait_sync
+#define EGL_KHR_wait_sync 1
+typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#endif
+#endif /* EGL_KHR_wait_sync */
+
+#ifndef EGL_ANDROID_blob_cache
+#define EGL_ANDROID_blob_cache 1
+typedef khronos_ssize_t EGLsizeiANDROID;
+typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
+typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
+typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#endif
+#endif /* EGL_ANDROID_blob_cache */
+
+#ifndef EGL_ANDROID_create_native_client_buffer
+#define EGL_ANDROID_create_native_client_buffer 1
+#define EGL_NATIVE_BUFFER_USAGE_ANDROID   0x3143
+#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
+#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
+typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC) (const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLClientBuffer EGLAPIENTRY eglCreateNativeClientBufferANDROID (const EGLint *attrib_list);
+#endif
+#endif /* EGL_ANDROID_create_native_client_buffer */
+
+#ifndef EGL_ANDROID_framebuffer_target
+#define EGL_ANDROID_framebuffer_target 1
+#define EGL_FRAMEBUFFER_TARGET_ANDROID    0x3147
+#endif /* EGL_ANDROID_framebuffer_target */
+
+#ifndef EGL_ANDROID_front_buffer_auto_refresh
+#define EGL_ANDROID_front_buffer_auto_refresh 1
+#define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
+#endif /* EGL_ANDROID_front_buffer_auto_refresh */
+
+#ifndef EGL_ANDROID_image_native_buffer
+#define EGL_ANDROID_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_ANDROID         0x3140
+#endif /* EGL_ANDROID_image_native_buffer */
+
+#ifndef EGL_ANDROID_native_fence_sync
+#define EGL_ANDROID_native_fence_sync 1
+#define EGL_SYNC_NATIVE_FENCE_ANDROID     0x3144
+#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID  0x3145
+#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
+#define EGL_NO_NATIVE_FENCE_FD_ANDROID    -1
+typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync);
+#endif
+#endif /* EGL_ANDROID_native_fence_sync */
+
+#ifndef EGL_ANDROID_presentation_time
+#define EGL_ANDROID_presentation_time 1
+typedef khronos_stime_nanoseconds_t EGLnsecsANDROID;
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPRESENTATIONTIMEANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPresentationTimeANDROID (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time);
+#endif
+#endif /* EGL_ANDROID_presentation_time */
+
+#ifndef EGL_ANDROID_recordable
+#define EGL_ANDROID_recordable 1
+#define EGL_RECORDABLE_ANDROID            0x3142
+#endif /* EGL_ANDROID_recordable */
+
+#ifndef EGL_ANGLE_create_context_robust_resource_initialization
+#define EGL_ANGLE_create_context_robust_resource_initialization 1
+#define EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x320F
+#endif /* EGL_ANGLE_create_context_robust_resource_initialization */
+
+#ifndef EGL_ANGLE_d3d_share_handle_client_buffer
+#define EGL_ANGLE_d3d_share_handle_client_buffer 1
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
+
+#ifndef EGL_ANGLE_device_d3d
+#define EGL_ANGLE_device_d3d 1
+#define EGL_D3D9_DEVICE_ANGLE             0x33A0
+#define EGL_D3D11_DEVICE_ANGLE            0x33A1
+#endif /* EGL_ANGLE_device_d3d */
+
+#ifndef EGL_ANGLE_keyed_mutex
+#define EGL_ANGLE_keyed_mutex 1
+#define EGL_DXGI_KEYED_MUTEX_ANGLE        0x33A2
+#endif /* EGL_ANGLE_keyed_mutex */
+
+#ifndef EGL_ANGLE_d3d_texture_client_buffer
+#define EGL_ANGLE_d3d_texture_client_buffer 1
+#define EGL_D3D_TEXTURE_ANGLE             0x33A3
+#endif /* EGL_ANGLE_d3d_texture_client_buffer */
+
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+#endif /* EGL_ANGLE_query_surface_pointer */
+
+#ifndef EGL_ANGLE_software_display
+#define EGL_ANGLE_software_display 1
+#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
+#endif /* EGL_ANGLE_software_display */
+
+#ifndef EGL_ANGLE_direct3d_display
+#define EGL_ANGLE_direct3d_display 1
+#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
+#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
+#endif /* EGL_ANGLE_direct3d_display */
+
+#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
+#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+
+#ifndef EGL_ANGLE_direct_composition
+#define EGL_ANGLE_direct_composition 1
+#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
+#endif /* EGL_ANGLE_direct_composition */
+
+#ifndef EGL_ANGLE_platform_angle
+#define EGL_ANGLE_platform_angle 1
+#define EGL_PLATFORM_ANGLE_ANGLE          0x3202
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE     0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
+#endif /* EGL_ANGLE_platform_angle */
+
+#ifndef EGL_ANGLE_platform_angle_d3d
+#define EGL_ANGLE_platform_angle_d3d 1
+#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
+#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
+#endif /* EGL_ANGLE_platform_angle_d3d */
+
+#ifndef EGL_ANGLE_platform_angle_opengl
+#define EGL_ANGLE_platform_angle_opengl 1
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
+#endif /* EGL_ANGLE_platform_angle_opengl */
+
+#ifndef EGL_ANGLE_platform_angle_null
+#define EGL_ANGLE_platform_angle_null 1
+#define EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE 0x33AE
+#endif /* EGL_ANGLE_platform_angle_null */
+
+#ifndef EGL_ANGLE_platform_angle_vulkan
+#define EGL_ANGLE_platform_angle_vulkan 1
+#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
+#define EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE 0x3451
+#endif /* EGL_ANGLE_platform_angle_vulkan */
+
+#ifndef EGL_ANGLE_window_fixed_size
+#define EGL_ANGLE_window_fixed_size 1
+#define EGL_FIXED_SIZE_ANGLE              0x3201
+#endif /* EGL_ANGLE_window_fixed_size */
+
+#ifndef EGL_ANGLE_x11_visual
+#define EGL_ANGLE_x11_visual
+#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
+#endif /* EGL_ANGLE_x11_visual */
+
+#ifndef EGL_ANGLE_flexible_surface_compatibility
+#define EGL_ANGLE_flexible_surface_compatibility 1
+#define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
+#endif /* EGL_ANGLE_flexible_surface_compatibility */
+
+#ifndef EGL_ANGLE_surface_orientation
+#define EGL_ANGLE_surface_orientation
+#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
+#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
+#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
+#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
+#endif /* EGL_ANGLE_surface_orientation */
+
+#ifndef EGL_ANGLE_experimental_present_path
+#define EGL_ANGLE_experimental_present_path
+#define EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4
+#define EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
+#define EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
+#endif /* EGL_ANGLE_experimental_present_path */
+
+#ifndef EGL_ANGLE_stream_producer_d3d_texture_nv12
+#define EGL_ANGLE_stream_producer_d3d_texture_nv12
+#define EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE 0x33AB
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERD3DTEXTURENV12ANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLSTREAMPOSTD3DTEXTURENV12ANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, void *texture, const EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglCreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy, EGLStreamKHR stream, void *texture, const EGLAttrib *attrib_list);
+#endif
+#endif /* EGL_ANGLE_stream_producer_d3d_texture_nv12 */
+
+#ifndef EGL_ANGLE_create_context_webgl_compatibility
+#define EGL_ANGLE_create_context_webgl_compatibility 1
+#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
+#endif /* EGL_ANGLE_create_context_webgl_compatibility */
+
+#ifndef EGL_ANGLE_display_texture_share_group
+#define EGL_ANGLE_display_texture_share_group 1
+#define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x3AAF
+#endif /* EGL_ANGLE_display_texture_share_group */
+
+#ifndef EGL_CHROMIUM_create_context_bind_generates_resource
+#define EGL_CHROMIUM_create_context_bind_generates_resource 1
+#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
+#endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
+
+#ifndef EGL_ANGLE_create_context_client_arrays
+#define EGL_ANGLE_create_context_client_arrays 1
+#define EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452
+#endif /* EGL_ANGLE_create_context_client_arrays */
+
+#ifndef EGL_ARM_implicit_external_sync
+#define EGL_ARM_implicit_external_sync 1
+#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
+#endif /* EGL_ARM_implicit_external_sync */
+
+#ifndef EGL_ARM_pixmap_multisample_discard
+#define EGL_ARM_pixmap_multisample_discard 1
+#define EGL_DISCARD_SAMPLES_ARM           0x3286
+#endif /* EGL_ARM_pixmap_multisample_discard */
+
+#ifndef EGL_EXT_buffer_age
+#define EGL_EXT_buffer_age 1
+#define EGL_BUFFER_AGE_EXT                0x313D
+#endif /* EGL_EXT_buffer_age */
+
+#ifndef EGL_EXT_client_extensions
+#define EGL_EXT_client_extensions 1
+#endif /* EGL_EXT_client_extensions */
+
+#ifndef EGL_EXT_create_context_robustness
+#define EGL_EXT_create_context_robustness 1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT     0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT     0x31BF
+#endif /* EGL_EXT_create_context_robustness */
+
+#ifndef EGL_EXT_device_base
+#define EGL_EXT_device_base 1
+typedef void *EGLDeviceEXT;
+#define EGL_NO_DEVICE_EXT                 EGL_CAST(EGLDeviceEXT,0)
+#define EGL_BAD_DEVICE_EXT                0x322B
+#define EGL_DEVICE_EXT                    0x322C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#endif
+#endif /* EGL_EXT_device_base */
+
+#ifndef EGL_ANGLE_device_creation
+#define EGL_ANGLE_device_creation 1
+typedef EGLDeviceEXT(EGLAPIENTRYP PFNEGLCREATEDEVICEANGLEPROC) (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLRELEASEDEVICEANGLEPROC) (EGLDeviceEXT device);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE(EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE(EGLDeviceEXT device);
+#endif
+#endif /* EGL_ANGLE_device_creation */
+
+#ifndef EGL_EXT_device_drm
+#define EGL_EXT_device_drm 1
+#define EGL_DRM_DEVICE_FILE_EXT           0x3233
+#endif /* EGL_EXT_device_drm */
+
+#ifndef EGL_EXT_device_enumeration
+#define EGL_EXT_device_enumeration 1
+#endif /* EGL_EXT_device_enumeration */
+
+#ifndef EGL_EXT_device_openwf
+#define EGL_EXT_device_openwf 1
+#define EGL_OPENWF_DEVICE_ID_EXT          0x3237
+#endif /* EGL_EXT_device_openwf */
+
+#ifndef EGL_EXT_device_query
+#define EGL_EXT_device_query 1
+#endif /* EGL_EXT_device_query */
+
+#ifndef EGL_EXT_gl_colorspace_bt2020_linear
+#define EGL_EXT_gl_colorspace_bt2020_linear 1
+#define EGL_GL_COLORSPACE_BT2020_LINEAR_EXT 0x333F
+#endif /* EGL_EXT_gl_colorspace_bt2020_linear */
+
+#ifndef EGL_EXT_gl_colorspace_bt2020_pq
+#define EGL_EXT_gl_colorspace_bt2020_pq 1
+#define EGL_GL_COLORSPACE_BT2020_PQ_EXT   0x3340
+#endif /* EGL_EXT_gl_colorspace_bt2020_pq */
+
+#ifndef EGL_EXT_gl_colorspace_scrgb_linear
+#define EGL_EXT_gl_colorspace_scrgb_linear 1
+#define EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT 0x3350
+#endif /* EGL_EXT_gl_colorspace_scrgb_linear */
+
+#ifndef EGL_EXT_image_dma_buf_import
+#define EGL_EXT_image_dma_buf_import 1
+#define EGL_LINUX_DMA_BUF_EXT             0x3270
+#define EGL_LINUX_DRM_FOURCC_EXT          0x3271
+#define EGL_DMA_BUF_PLANE0_FD_EXT         0x3272
+#define EGL_DMA_BUF_PLANE0_OFFSET_EXT     0x3273
+#define EGL_DMA_BUF_PLANE0_PITCH_EXT      0x3274
+#define EGL_DMA_BUF_PLANE1_FD_EXT         0x3275
+#define EGL_DMA_BUF_PLANE1_OFFSET_EXT     0x3276
+#define EGL_DMA_BUF_PLANE1_PITCH_EXT      0x3277
+#define EGL_DMA_BUF_PLANE2_FD_EXT         0x3278
+#define EGL_DMA_BUF_PLANE2_OFFSET_EXT     0x3279
+#define EGL_DMA_BUF_PLANE2_PITCH_EXT      0x327A
+#define EGL_YUV_COLOR_SPACE_HINT_EXT      0x327B
+#define EGL_SAMPLE_RANGE_HINT_EXT         0x327C
+#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
+#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
+#define EGL_ITU_REC601_EXT                0x327F
+#define EGL_ITU_REC709_EXT                0x3280
+#define EGL_ITU_REC2020_EXT               0x3281
+#define EGL_YUV_FULL_RANGE_EXT            0x3282
+#define EGL_YUV_NARROW_RANGE_EXT          0x3283
+#define EGL_YUV_CHROMA_SITING_0_EXT       0x3284
+#define EGL_YUV_CHROMA_SITING_0_5_EXT     0x3285
+#endif /* EGL_EXT_image_dma_buf_import */
+
+#ifndef EGL_EXT_image_dma_buf_import_modifiers
+#define EGL_EXT_image_dma_buf_import_modifiers 1
+#define EGL_DMA_BUF_PLANE3_FD_EXT         0x3440
+#define EGL_DMA_BUF_PLANE3_OFFSET_EXT     0x3441
+#define EGL_DMA_BUF_PLANE3_PITCH_EXT      0x3442
+#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
+#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
+#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
+#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
+#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
+#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
+#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
+#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufFormatsEXT (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufModifiersEXT (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
+#endif
+#endif /* EGL_EXT_image_dma_buf_import_modifiers */
+
+#ifndef EGL_EXT_multiview_window
+#define EGL_EXT_multiview_window 1
+#define EGL_MULTIVIEW_VIEW_COUNT_EXT      0x3134
+#endif /* EGL_EXT_multiview_window */
+
+#ifndef EGL_EXT_output_base
+#define EGL_EXT_output_base 1
+typedef void *EGLOutputLayerEXT;
+typedef void *EGLOutputPortEXT;
+#define EGL_NO_OUTPUT_LAYER_EXT           EGL_CAST(EGLOutputLayerEXT,0)
+#define EGL_NO_OUTPUT_PORT_EXT            EGL_CAST(EGLOutputPortEXT,0)
+#define EGL_BAD_OUTPUT_LAYER_EXT          0x322D
+#define EGL_BAD_OUTPUT_PORT_EXT           0x322E
+#define EGL_SWAP_INTERVAL_EXT             0x322F
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputLayersEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputPortsEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputLayerStringEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#endif
+#endif /* EGL_EXT_output_base */
+
+#ifndef EGL_EXT_output_drm
+#define EGL_EXT_output_drm 1
+#define EGL_DRM_CRTC_EXT                  0x3234
+#define EGL_DRM_PLANE_EXT                 0x3235
+#define EGL_DRM_CONNECTOR_EXT             0x3236
+#endif /* EGL_EXT_output_drm */
+
+#ifndef EGL_EXT_output_openwf
+#define EGL_EXT_output_openwf 1
+#define EGL_OPENWF_PIPELINE_ID_EXT        0x3238
+#define EGL_OPENWF_PORT_ID_EXT            0x3239
+#endif /* EGL_EXT_output_openwf */
+
+#ifndef EGL_EXT_pixel_format_float
+#define EGL_EXT_pixel_format_float 1
+#define EGL_COLOR_COMPONENT_TYPE_EXT      0x3339
+#define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A
+#define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT 0x333B
+#endif /* EGL_EXT_pixel_format_float */
+
+#ifndef EGL_EXT_platform_base
+#define EGL_EXT_platform_base 1
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#endif
+#endif /* EGL_EXT_platform_base */
+
+#ifndef EGL_EXT_platform_device
+#define EGL_EXT_platform_device 1
+#define EGL_PLATFORM_DEVICE_EXT           0x313F
+#endif /* EGL_EXT_platform_device */
+
+#ifndef EGL_EXT_platform_wayland
+#define EGL_EXT_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_EXT          0x31D8
+#endif /* EGL_EXT_platform_wayland */
+
+#ifndef EGL_EXT_platform_x11
+#define EGL_EXT_platform_x11 1
+#define EGL_PLATFORM_X11_EXT              0x31D5
+#define EGL_PLATFORM_X11_SCREEN_EXT       0x31D6
+#endif /* EGL_EXT_platform_x11 */
+
+#ifndef EGL_EXT_protected_content
+#define EGL_EXT_protected_content 1
+#define EGL_PROTECTED_CONTENT_EXT         0x32C0
+#endif /* EGL_EXT_protected_content */
+
+#ifndef EGL_EXT_protected_surface
+#define EGL_EXT_protected_surface 1
+#endif /* EGL_EXT_protected_surface */
+
+#ifndef EGL_EXT_stream_consumer_egloutput
+#define EGL_EXT_stream_consumer_egloutput 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#endif
+#endif /* EGL_EXT_stream_consumer_egloutput */
+
+#ifndef EGL_EXT_surface_SMPTE2086_metadata
+#define EGL_EXT_surface_SMPTE2086_metadata 1
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT 0x3341
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT 0x3342
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT 0x3343
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT 0x3344
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT 0x3345
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT 0x3346
+#define EGL_SMPTE2086_WHITE_POINT_X_EXT   0x3347
+#define EGL_SMPTE2086_WHITE_POINT_Y_EXT   0x3348
+#define EGL_SMPTE2086_MAX_LUMINANCE_EXT   0x3349
+#define EGL_SMPTE2086_MIN_LUMINANCE_EXT   0x334A
+#endif /* EGL_EXT_surface_SMPTE2086_metadata */
+
+#ifndef EGL_EXT_swap_buffers_with_damage
+#define EGL_EXT_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_EXT_swap_buffers_with_damage */
+
+#ifndef EGL_EXT_yuv_surface
+#define EGL_EXT_yuv_surface 1
+#define EGL_YUV_ORDER_EXT                 0x3301
+#define EGL_YUV_NUMBER_OF_PLANES_EXT      0x3311
+#define EGL_YUV_SUBSAMPLE_EXT             0x3312
+#define EGL_YUV_DEPTH_RANGE_EXT           0x3317
+#define EGL_YUV_CSC_STANDARD_EXT          0x330A
+#define EGL_YUV_PLANE_BPP_EXT             0x331A
+#define EGL_YUV_BUFFER_EXT                0x3300
+#define EGL_YUV_ORDER_YUV_EXT             0x3302
+#define EGL_YUV_ORDER_YVU_EXT             0x3303
+#define EGL_YUV_ORDER_YUYV_EXT            0x3304
+#define EGL_YUV_ORDER_UYVY_EXT            0x3305
+#define EGL_YUV_ORDER_YVYU_EXT            0x3306
+#define EGL_YUV_ORDER_VYUY_EXT            0x3307
+#define EGL_YUV_ORDER_AYUV_EXT            0x3308
+#define EGL_YUV_SUBSAMPLE_4_2_0_EXT       0x3313
+#define EGL_YUV_SUBSAMPLE_4_2_2_EXT       0x3314
+#define EGL_YUV_SUBSAMPLE_4_4_4_EXT       0x3315
+#define EGL_YUV_DEPTH_RANGE_LIMITED_EXT   0x3318
+#define EGL_YUV_DEPTH_RANGE_FULL_EXT      0x3319
+#define EGL_YUV_CSC_STANDARD_601_EXT      0x330B
+#define EGL_YUV_CSC_STANDARD_709_EXT      0x330C
+#define EGL_YUV_CSC_STANDARD_2020_EXT     0x330D
+#define EGL_YUV_PLANE_BPP_0_EXT           0x331B
+#define EGL_YUV_PLANE_BPP_8_EXT           0x331C
+#define EGL_YUV_PLANE_BPP_10_EXT          0x331D
+#endif /* EGL_EXT_yuv_surface */
+
+#ifndef EGL_HI_clientpixmap
+#define EGL_HI_clientpixmap 1
+struct EGLClientPixmapHI {
+    void  *pData;
+    EGLint iWidth;
+    EGLint iHeight;
+    EGLint iStride;
+};
+#define EGL_CLIENT_PIXMAP_POINTER_HI      0x8F74
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#endif
+#endif /* EGL_HI_clientpixmap */
+
+#ifndef EGL_HI_colorformats
+#define EGL_HI_colorformats 1
+#define EGL_COLOR_FORMAT_HI               0x8F70
+#define EGL_COLOR_RGB_HI                  0x8F71
+#define EGL_COLOR_RGBA_HI                 0x8F72
+#define EGL_COLOR_ARGB_HI                 0x8F73
+#endif /* EGL_HI_colorformats */
+
+#ifndef EGL_IMG_context_priority
+#define EGL_IMG_context_priority 1
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG    0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG     0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG   0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG      0x3103
+#endif /* EGL_IMG_context_priority */
+
+#ifndef EGL_IMG_image_plane_attribs
+#define EGL_IMG_image_plane_attribs 1
+#define EGL_NATIVE_BUFFER_MULTIPLANE_SEPARATE_IMG 0x3105
+#define EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG 0x3106
+#endif /* EGL_IMG_image_plane_attribs */
+
+#ifndef EGL_MESA_drm_image
+#define EGL_MESA_drm_image 1
+#define EGL_DRM_BUFFER_FORMAT_MESA        0x31D0
+#define EGL_DRM_BUFFER_USE_MESA           0x31D1
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
+#define EGL_DRM_BUFFER_MESA               0x31D3
+#define EGL_DRM_BUFFER_STRIDE_MESA        0x31D4
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA   0x00000001
+#define EGL_DRM_BUFFER_USE_SHARE_MESA     0x00000002
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+#endif /* EGL_MESA_drm_image */
+
+#ifndef EGL_MESA_image_dma_buf_export
+#define EGL_MESA_image_dma_buf_export 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#endif
+#endif /* EGL_MESA_image_dma_buf_export */
+
+#ifndef EGL_MESA_platform_gbm
+#define EGL_MESA_platform_gbm 1
+#define EGL_PLATFORM_GBM_MESA             0x31D7
+#endif /* EGL_MESA_platform_gbm */
+
+#ifndef EGL_MESA_platform_surfaceless
+#define EGL_MESA_platform_surfaceless 1
+#define EGL_PLATFORM_SURFACELESS_MESA     0x31DD
+#endif /* EGL_MESA_platform_surfaceless */
+
+#ifndef EGL_NOK_swap_region
+#define EGL_NOK_swap_region 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region */
+
+#ifndef EGL_NOK_swap_region2
+#define EGL_NOK_swap_region2 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region2 */
+
+#ifndef EGL_NOK_texture_from_pixmap
+#define EGL_NOK_texture_from_pixmap 1
+#define EGL_Y_INVERTED_NOK                0x307F
+#endif /* EGL_NOK_texture_from_pixmap */
+
+#ifndef EGL_NV_3dvision_surface
+#define EGL_NV_3dvision_surface 1
+#define EGL_AUTO_STEREO_NV                0x3136
+#endif /* EGL_NV_3dvision_surface */
 
 #ifndef EGL_NV_coverage_sample
 #define EGL_NV_coverage_sample 1
-#define EGL_COVERAGE_BUFFERS_NV			0x30E0
-#define EGL_COVERAGE_SAMPLES_NV			0x30E1
-#endif
+#define EGL_COVERAGE_BUFFERS_NV           0x30E0
+#define EGL_COVERAGE_SAMPLES_NV           0x30E1
+#endif /* EGL_NV_coverage_sample */
+
+#ifndef EGL_NV_coverage_sample_resolve
+#define EGL_NV_coverage_sample_resolve 1
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NV    0x3131
+#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
+#endif /* EGL_NV_coverage_sample_resolve */
+
+#ifndef EGL_NV_cuda_event
+#define EGL_NV_cuda_event 1
+#define EGL_CUDA_EVENT_HANDLE_NV          0x323B
+#define EGL_SYNC_CUDA_EVENT_NV            0x323C
+#define EGL_SYNC_CUDA_EVENT_COMPLETE_NV   0x323D
+#endif /* EGL_NV_cuda_event */
 
 #ifndef EGL_NV_depth_nonlinear
 #define EGL_NV_depth_nonlinear 1
-#define EGL_DEPTH_ENCODING_NV			0x30E2
-#define EGL_DEPTH_ENCODING_NONE_NV 0
-#define EGL_DEPTH_ENCODING_NONLINEAR_NV		0x30E3
-#endif
+#define EGL_DEPTH_ENCODING_NV             0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV        0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV   0x30E3
+#endif /* EGL_NV_depth_nonlinear */
 
-#if KHRONOS_SUPPORT_INT64   /* EGLTimeNV requires 64-bit uint support */
+#ifndef EGL_NV_device_cuda
+#define EGL_NV_device_cuda 1
+#define EGL_CUDA_DEVICE_NV                0x323A
+#endif /* EGL_NV_device_cuda */
+
+#ifndef EGL_NV_native_query
+#define EGL_NV_native_query 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#endif
+#endif /* EGL_NV_native_query */
+
+#ifndef EGL_NV_post_convert_rounding
+#define EGL_NV_post_convert_rounding 1
+#endif /* EGL_NV_post_convert_rounding */
+
+#ifndef EGL_NV_post_sub_buffer
+#define EGL_NV_post_sub_buffer 1
+#define EGL_POST_SUB_BUFFER_SUPPORTED_NV  0x30BE
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif
+#endif /* EGL_NV_post_sub_buffer */
+
+#ifndef EGL_NV_robustness_video_memory_purge
+#define EGL_NV_robustness_video_memory_purge 1
+#define EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C
+#endif /* EGL_NV_robustness_video_memory_purge */
+
+#ifndef EGL_NV_stream_consumer_gltexture_yuv
+#define EGL_NV_stream_consumer_gltexture_yuv 1
+#define EGL_YUV_PLANE0_TEXTURE_UNIT_NV    0x332C
+#define EGL_YUV_PLANE1_TEXTURE_UNIT_NV    0x332D
+#define EGL_YUV_PLANE2_TEXTURE_UNIT_NV    0x332E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALATTRIBSNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalAttribsNV (EGLDisplay dpy, EGLStreamKHR stream, EGLAttrib *attrib_list);
+#endif
+#endif /* EGL_NV_stream_consumer_gltexture_yuv */
+
+#ifndef EGL_NV_stream_cross_display
+#define EGL_NV_stream_cross_display 1
+#define EGL_STREAM_CROSS_DISPLAY_NV       0x334E
+#endif /* EGL_NV_stream_cross_display */
+
+#ifndef EGL_NV_stream_cross_object
+#define EGL_NV_stream_cross_object 1
+#define EGL_STREAM_CROSS_OBJECT_NV        0x334D
+#endif /* EGL_NV_stream_cross_object */
+
+#ifndef EGL_NV_stream_cross_partition
+#define EGL_NV_stream_cross_partition 1
+#define EGL_STREAM_CROSS_PARTITION_NV     0x323F
+#endif /* EGL_NV_stream_cross_partition */
+
+#ifndef EGL_NV_stream_cross_process
+#define EGL_NV_stream_cross_process 1
+#define EGL_STREAM_CROSS_PROCESS_NV       0x3245
+#endif /* EGL_NV_stream_cross_process */
+
+#ifndef EGL_NV_stream_cross_system
+#define EGL_NV_stream_cross_system 1
+#define EGL_STREAM_CROSS_SYSTEM_NV        0x334F
+#endif /* EGL_NV_stream_cross_system */
+
+#ifndef EGL_NV_stream_fifo_next
+#define EGL_NV_stream_fifo_next 1
+#define EGL_PENDING_FRAME_NV              0x3329
+#define EGL_STREAM_TIME_PENDING_NV        0x332A
+#endif /* EGL_NV_stream_fifo_next */
+
+#ifndef EGL_NV_stream_fifo_synchronous
+#define EGL_NV_stream_fifo_synchronous 1
+#define EGL_STREAM_FIFO_SYNCHRONOUS_NV    0x3336
+#endif /* EGL_NV_stream_fifo_synchronous */
+
+#ifndef EGL_NV_stream_frame_limits
+#define EGL_NV_stream_frame_limits 1
+#define EGL_PRODUCER_MAX_FRAME_HINT_NV    0x3337
+#define EGL_CONSUMER_MAX_FRAME_HINT_NV    0x3338
+#endif /* EGL_NV_stream_frame_limits */
+
+#ifndef EGL_NV_stream_metadata
+#define EGL_NV_stream_metadata 1
+#define EGL_MAX_STREAM_METADATA_BLOCKS_NV 0x3250
+#define EGL_MAX_STREAM_METADATA_BLOCK_SIZE_NV 0x3251
+#define EGL_MAX_STREAM_METADATA_TOTAL_SIZE_NV 0x3252
+#define EGL_PRODUCER_METADATA_NV          0x3253
+#define EGL_CONSUMER_METADATA_NV          0x3254
+#define EGL_PENDING_METADATA_NV           0x3328
+#define EGL_METADATA0_SIZE_NV             0x3255
+#define EGL_METADATA1_SIZE_NV             0x3256
+#define EGL_METADATA2_SIZE_NV             0x3257
+#define EGL_METADATA3_SIZE_NV             0x3258
+#define EGL_METADATA0_TYPE_NV             0x3259
+#define EGL_METADATA1_TYPE_NV             0x325A
+#define EGL_METADATA2_TYPE_NV             0x325B
+#define EGL_METADATA3_TYPE_NV             0x325C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBNVPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribNV (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
+#endif
+#endif /* EGL_NV_stream_metadata */
+
+#ifndef EGL_NV_stream_remote
+#define EGL_NV_stream_remote 1
+#define EGL_STREAM_STATE_INITIALIZING_NV  0x3240
+#define EGL_STREAM_TYPE_NV                0x3241
+#define EGL_STREAM_PROTOCOL_NV            0x3242
+#define EGL_STREAM_ENDPOINT_NV            0x3243
+#define EGL_STREAM_LOCAL_NV               0x3244
+#define EGL_STREAM_PRODUCER_NV            0x3247
+#define EGL_STREAM_CONSUMER_NV            0x3248
+#define EGL_STREAM_PROTOCOL_FD_NV         0x3246
+#endif /* EGL_NV_stream_remote */
+
+#ifndef EGL_NV_stream_reset
+#define EGL_NV_stream_reset 1
+#define EGL_SUPPORT_RESET_NV              0x3334
+#define EGL_SUPPORT_REUSE_NV              0x3335
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLRESETSTREAMNVPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglResetStreamNV (EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+#endif /* EGL_NV_stream_reset */
+
+#ifndef EGL_NV_stream_socket
+#define EGL_NV_stream_socket 1
+#define EGL_STREAM_PROTOCOL_SOCKET_NV     0x324B
+#define EGL_SOCKET_HANDLE_NV              0x324C
+#define EGL_SOCKET_TYPE_NV                0x324D
+#endif /* EGL_NV_stream_socket */
+
+#ifndef EGL_NV_stream_socket_inet
+#define EGL_NV_stream_socket_inet 1
+#define EGL_SOCKET_TYPE_INET_NV           0x324F
+#endif /* EGL_NV_stream_socket_inet */
+
+#ifndef EGL_NV_stream_socket_unix
+#define EGL_NV_stream_socket_unix 1
+#define EGL_SOCKET_TYPE_UNIX_NV           0x324E
+#endif /* EGL_NV_stream_socket_unix */
+
+#ifndef EGL_NV_stream_sync
+#define EGL_NV_stream_sync 1
+#define EGL_SYNC_NEW_FRAME_NV             0x321F
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#endif
+#endif /* EGL_NV_stream_sync */
+
 #ifndef EGL_NV_sync
 #define EGL_NV_sync 1
-#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV	0x30E6
-#define EGL_SYNC_STATUS_NV			0x30E7
-#define EGL_SIGNALED_NV				0x30E8
-#define EGL_UNSIGNALED_NV			0x30E9
-#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV		0x0001
-#define EGL_FOREVER_NV				0xFFFFFFFFFFFFFFFFull
-#define EGL_ALREADY_SIGNALED_NV			0x30EA
-#define EGL_TIMEOUT_EXPIRED_NV			0x30EB
-#define EGL_CONDITION_SATISFIED_NV		0x30EC
-#define EGL_SYNC_TYPE_NV			0x30ED
-#define EGL_SYNC_CONDITION_NV			0x30EE
-#define EGL_SYNC_FENCE_NV			0x30EF
-#define EGL_NO_SYNC_NV				((EGLSyncNV)0)
-typedef void* EGLSyncNV;
+typedef void *EGLSyncNV;
 typedef khronos_utime_nanoseconds_t EGLTimeNV;
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLSyncNV eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
-EGLBoolean eglDestroySyncNV (EGLSyncNV sync);
-EGLBoolean eglFenceNV (EGLSyncNV sync);
-EGLint eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
-EGLBoolean eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
-EGLBoolean eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
-#endif /* EGL_EGLEXT_PROTOTYPES */
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
+#define EGL_SYNC_STATUS_NV                0x30E7
+#define EGL_SIGNALED_NV                   0x30E8
+#define EGL_UNSIGNALED_NV                 0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV    0x0001
+#define EGL_FOREVER_NV                    0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV           0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV            0x30EB
+#define EGL_CONDITION_SATISFIED_NV        0x30EC
+#define EGL_SYNC_TYPE_NV                  0x30ED
+#define EGL_SYNC_CONDITION_NV             0x30EE
+#define EGL_SYNC_FENCE_NV                 0x30EF
+#define EGL_NO_SYNC_NV                    EGL_CAST(EGLSyncNV,0)
 typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
 typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
-#endif
-#endif
-
-#if KHRONOS_SUPPORT_INT64   /* Dependent on EGL_KHR_reusable_sync which requires 64-bit uint support */
-#ifndef EGL_KHR_fence_sync
-#define EGL_KHR_fence_sync 1
-/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */
-#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR	0x30F0
-#define EGL_SYNC_CONDITION_KHR			0x30F8
-#define EGL_SYNC_FENCE_KHR			0x30F9
-#endif
-#endif
-
-#ifndef EGL_HI_clientpixmap
-#define EGL_HI_clientpixmap 1
-
-/* Surface Attribute */
-#define EGL_CLIENT_PIXMAP_POINTER_HI		0x8F74
-/*
- * Structure representing a client pixmap
- * (pixmap's data is in client-space memory).
- */
-struct EGLClientPixmapHI
-{
-	void*		pData;
-	EGLint		iWidth;
-	EGLint		iHeight;
-	EGLint		iStride;
-};
-
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
-#endif	/* EGL_HI_clientpixmap */
-
-#ifndef EGL_HI_colorformats
-#define EGL_HI_colorformats 1
-/* Config Attribute */
-#define EGL_COLOR_FORMAT_HI			0x8F70
-/* Color Formats */
-#define EGL_COLOR_RGB_HI			0x8F71
-#define EGL_COLOR_RGBA_HI			0x8F72
-#define EGL_COLOR_ARGB_HI			0x8F73
-#endif /* EGL_HI_colorformats */
-
-#ifndef EGL_MESA_drm_image
-#define EGL_MESA_drm_image 1
-#define EGL_DRM_BUFFER_FORMAT_MESA		0x31D0	    /* CreateDRMImageMESA attribute */
-#define EGL_DRM_BUFFER_USE_MESA			0x31D1	    /* CreateDRMImageMESA attribute */
-#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA	0x31D2	    /* EGL_IMAGE_FORMAT_MESA attribute value */
-#define EGL_DRM_BUFFER_MESA			0x31D3	    /* eglCreateImageKHR target */
-#define EGL_DRM_BUFFER_STRIDE_MESA		0x31D4
-#define EGL_DRM_BUFFER_USE_SCANOUT_MESA		0x00000001  /* EGL_DRM_BUFFER_USE_MESA bits */
-#define EGL_DRM_BUFFER_USE_SHARE_MESA		0x00000002  /* EGL_DRM_BUFFER_USE_MESA bits */
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
+EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
 #endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_sync */
 
-#ifndef EGL_NV_post_sub_buffer
-#define EGL_NV_post_sub_buffer 1
-#define EGL_POST_SUB_BUFFER_SUPPORTED_NV	0x30BE
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
-#endif
-
-#ifndef EGL_ANGLE_query_surface_pointer
-#define EGL_ANGLE_query_surface_pointer 1
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
-#endif
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
-#endif
-
-#ifndef EGL_ANGLE_software_display
-#define EGL_ANGLE_software_display 1
-#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
-#endif
-
-#ifndef EGL_ANGLE_direct3d_display
-#define EGL_ANGLE_direct3d_display 1
-#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
-#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
-#endif
-
-#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
-#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
-#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE	0x3200
-#endif
-
-#ifndef EGL_ANGLE_query_d3d_device
-#define EGL_ANGLE_query_d3d_device 1
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean eglQueryD3DDeviceANGLE(EGLDisplay dpy, void **value);
-#endif
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYD3DDEVICEANGLEPROC) (EGLDisplay dpy, void **value);
-#endif
-
-#ifndef EGL_ANGLE_set_resource_tracker_proc
-#define EGL_ANGLE_set_resource_tracker_proc 1
-
-#define EGL_ANGLE_TRACK_OPTYPE_CREATE   1
-#define EGL_ANGLE_TRACK_OPTYPE_DESTROY  0
-
-#define EGL_ANGLE_TRACK_TYPE_TEX1D		0x200
-#define EGL_ANGLE_TRACK_TYPE_TEX2D		0x201
-#define EGL_ANGLE_TRACK_TYPE_TEX3D		0x202
-#define EGL_ANGLE_TRACK_TYPE_BUFFER		0x203
-
-#define EGL_ANGLE_TRACK_TYPE_SWAPCHAIN	0x300
-
-struct EGLResourceTrackerDataAngle
-{
-	void*		pResource;
-	EGLint		iOpType;
-	EGLint		iType;
-	EGLint		iSize;
-};
-typedef void (EGLAPIENTRYP EGLResourceTrackerProcAngle) (const EGLResourceTrackerDataAngle *data, void *user_data);
-#endif
-
-#ifndef EGL_ANGLE_set_resource_tracker
-#define EGL_ANGLE_set_resource_tracker 1
-#ifdef EGL_EGLEXT_PROTOTYPES
-// See samples/angle/Resource_Tracking/resource_tracking.cc for example usage
-EGLAPI EGLBoolean eglSetResourceTrackerANGLE(EGLDisplay dpy, EGLResourceTrackerProcAngle proc, void *user_data);
-#endif
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETRESOURCETRACKERANGLEPROC) (EGLDisplay dpy, EGLResourceTrackerProcAngle proc, void *user_data);
-#endif
-
-#ifndef EGL_NV_coverage_sample_resolve
-#define EGL_NV_coverage_sample_resolve 1
-#define EGL_COVERAGE_SAMPLE_RESOLVE_NV		0x3131
-#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV	0x3132
-#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV	0x3133
-#endif
-
-#if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
 #ifndef EGL_NV_system_time
 #define EGL_NV_system_time 1
-
 typedef khronos_utime_nanoseconds_t EGLuint64NV;
-
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void);
-EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void);
-#endif /* EGL_EGLEXT_PROTOTYPES */
+#ifdef KHRONOS_SUPPORT_INT64
 typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
 typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
 #endif
-#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_system_time */
 
-#ifndef EGL_EXT_create_context_robustness
-#define EGL_EXT_create_context_robustness 1
-#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT	0x30BF
-#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
-#define EGL_NO_RESET_NOTIFICATION_EXT		0x31BE
-#define EGL_LOSE_CONTEXT_ON_RESET_EXT		0x31BF
-#endif
+#ifndef EGL_TIZEN_image_native_buffer
+#define EGL_TIZEN_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_TIZEN           0x32A0
+#endif /* EGL_TIZEN_image_native_buffer */
 
-
-/*------------------------------------------------------------------------*
- * LBSHELL extension functions
- *------------------------------------------------------------------------*/
-
-#if defined(__LB_XB360__)
-// Sets an instance of the platform player into the rendering back-end, because
-// its use must be unfortunately intermingled with frame-swapping. Setting to a
-// value causes the render loop to work with the platform player to keep the
-// video frame texture up-to-date every call to swap. Setting to NULL causes the
-// platform AV calls to be halted.
-//
-// To get access to the video frame texture, use the glGenVideoTextureLBSHELL()
-// extension function.
-# ifndef EGL_LBSHELL_set_player
-#  define EGL_LBSHELL_set_player 1
-#  ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean eglSetPlayerLBSHELL(EGLDisplay dpy, void *value);
-#  endif
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETPLAYERLBSHELLPROC) (EGLDisplay dpy, void *value);
-# endif
-#endif
-
+#ifndef EGL_TIZEN_image_native_surface
+#define EGL_TIZEN_image_native_surface 1
+#define EGL_NATIVE_SURFACE_TIZEN          0x32A1
+#endif /* EGL_TIZEN_image_native_surface */
 
 #ifdef __cplusplus
 }
diff --git a/src/third_party/angle/include/EGL/eglplatform.h b/src/third_party/angle/include/EGL/eglplatform.h
index 8cc5765..0c70ae4 100644
--- a/src/third_party/angle/include/EGL/eglplatform.h
+++ b/src/third_party/angle/include/EGL/eglplatform.h
@@ -2,7 +2,7 @@
 #define __eglplatform_h_
 
 /*
-** Copyright (c) 2007-2009 The Khronos Group Inc.
+** Copyright (c) 2007-2016 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
@@ -25,7 +25,7 @@
 */
 
 /* Platform-specific types and definitions for egl.h
- * $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $
+ * $Revision: 30994 $ on $Date: 2015-04-30 13:36:48 -0700 (Thu, 30 Apr 2015) $
  *
  * Adopters may modify khrplatform.h and this file to suit their platform.
  * You are encouraged to submit all modifications to the Khronos group so that
@@ -46,9 +46,15 @@
  * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
  */
 
+#if defined(STARBOARD)
+// Don't trust any previous definitions of GL_APICALL. We really want nothing.
+#undef EGLAPI
+#define EGLAPI  /* nothing */
+#else
 #ifndef EGLAPI
 #define EGLAPI KHRONOS_APICALL
 #endif
+#endif  // defined(STARBOARD)
 
 #ifndef EGLAPIENTRY
 #define EGLAPIENTRY  KHRONOS_APIENTRY
@@ -73,40 +79,39 @@
 #endif
 #include <windows.h>
 
-#if defined(__LB_XB360__) || defined(COBALT_WIN)
-
-typedef HWND    EGLNativeWindowType;
 typedef HDC     EGLNativeDisplayType;
 typedef HBITMAP EGLNativePixmapType;
 
-#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_TV_APP)
-#include <Unknwn.h>
-
-typedef IUnknown* EGLNativeWindowType;
-typedef void*   EGLNativeDisplayType;
-typedef HBITMAP EGLNativePixmapType;
-
-#else
-
+#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) /* Windows Desktop */
 typedef HWND    EGLNativeWindowType;
-typedef HDC     EGLNativeDisplayType;
-typedef HBITMAP EGLNativePixmapType;
-
+#else /* Windows Store */
+#include <inspectable.h>
+typedef IInspectable* EGLNativeWindowType;
 #endif
 
-#elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */
+#elif defined(__APPLE__) || defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */
 
 typedef int   EGLNativeDisplayType;
 typedef void *EGLNativeWindowType;
 typedef void *EGLNativePixmapType;
 
-#elif defined(WL_EGL_PLATFORM)
+#elif defined(__ANDROID__) || defined(ANDROID)
 
-typedef struct wl_display     *EGLNativeDisplayType;
-typedef struct wl_egl_pixmap  *EGLNativePixmapType;
-typedef struct wl_egl_window  *EGLNativeWindowType;
+#include <android/native_window.h>
 
-#elif defined(__unix__) && !defined(ANDROID)
+struct egl_native_pixmap_t;
+
+typedef struct ANativeWindow*           EGLNativeWindowType;
+typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
+typedef void*                           EGLNativeDisplayType;
+
+#elif defined(USE_OZONE)
+
+typedef intptr_t EGLNativeDisplayType;
+typedef intptr_t EGLNativeWindowType;
+typedef intptr_t EGLNativePixmapType;
+
+#elif defined(__unix__)
 
 /* X11 (tentative)  */
 #include <X11/Xlib.h>
@@ -116,14 +121,6 @@
 typedef Pixmap   EGLNativePixmapType;
 typedef Window   EGLNativeWindowType;
 
-#elif defined(ANDROID)
-
-struct egl_native_pixmap_t;
-
-typedef struct ANativeWindow*           EGLNativeWindowType;
-typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
-typedef void*                           EGLNativeDisplayType;
-
 #else
 #error "Platform not recognized"
 #endif
@@ -143,4 +140,12 @@
  */
 typedef khronos_int32_t EGLint;
 
+
+/* C++ / C typecast macros for special EGL handle values */
+#if defined(__cplusplus)
+#define EGL_CAST(type, value) (static_cast<type>(value))
+#else
+#define EGL_CAST(type, value) ((type) (value))
+#endif
+
 #endif /* __eglplatform_h */
diff --git a/src/third_party/angle/include/GLES2/gl2.h b/src/third_party/angle/include/GLES2/gl2.h
index e1d3b87..975c3dc 100644
--- a/src/third_party/angle/include/GLES2/gl2.h
+++ b/src/third_party/angle/include/GLES2/gl2.h
@@ -1,56 +1,89 @@
 #ifndef __gl2_h_
-#define __gl2_h_
-
-/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
-
-#include <GLES2/gl2platform.h>
+#define __gl2_h_ 1
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
- * This document is licensed under the SGI Free Software B License Version
- * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+** Copyright (c) 2013-2017 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   https://github.com/KhronosGroup/OpenGL-Registry
+*/
+
+#include <GLES2/gl2platform.h>
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+#ifndef GL_GLES_PROTOTYPES
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20170325 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
  */
 
-/*-------------------------------------------------------------------------
- * Data type definitions
- *-----------------------------------------------------------------------*/
-
-typedef void             GLvoid;
-typedef char             GLchar;
-typedef unsigned int     GLenum;
-typedef unsigned char    GLboolean;
-typedef unsigned int     GLbitfield;
-typedef khronos_int8_t   GLbyte;
-typedef short            GLshort;
-typedef int              GLint;
-typedef int              GLsizei;
-typedef khronos_uint8_t  GLubyte;
-typedef unsigned short   GLushort;
-typedef unsigned int     GLuint;
-typedef khronos_float_t  GLfloat;
-typedef khronos_float_t  GLclampf;
-typedef khronos_int32_t  GLfixed;
-
-/* GL types for handling large vertex buffer objects */
+#ifndef GL_ES_VERSION_2_0
+#define GL_ES_VERSION_2_0 1
+#include <KHR/khrplatform.h>
+typedef khronos_int8_t GLbyte;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef short GLshort;
+typedef unsigned short GLushort;
+typedef void GLvoid;
+typedef struct __GLsync *GLsync;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef khronos_float_t GLfloat;
+typedef khronos_ssize_t GLsizeiptr;
 typedef khronos_intptr_t GLintptr;
-typedef khronos_ssize_t  GLsizeiptr;
-
-/* OpenGL ES core versions */
-#define GL_ES_VERSION_2_0                 1
-
-/* ClearBufferMask */
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
 #define GL_DEPTH_BUFFER_BIT               0x00000100
 #define GL_STENCIL_BUFFER_BIT             0x00000400
 #define GL_COLOR_BUFFER_BIT               0x00004000
-
-/* Boolean */
 #define GL_FALSE                          0
 #define GL_TRUE                           1
-
-/* BeginMode */
 #define GL_POINTS                         0x0000
 #define GL_LINES                          0x0001
 #define GL_LINE_LOOP                      0x0002
@@ -58,18 +91,6 @@
 #define GL_TRIANGLES                      0x0004
 #define GL_TRIANGLE_STRIP                 0x0005
 #define GL_TRIANGLE_FAN                   0x0006
-
-/* AlphaFunction (not supported in ES20) */
-/*      GL_NEVER */
-/*      GL_LESS */
-/*      GL_EQUAL */
-/*      GL_LEQUAL */
-/*      GL_GREATER */
-/*      GL_NOTEQUAL */
-/*      GL_GEQUAL */
-/*      GL_ALWAYS */
-
-/* BlendingFactorDest */
 #define GL_ZERO                           0
 #define GL_ONE                            1
 #define GL_SRC_COLOR                      0x0300
@@ -78,29 +99,15 @@
 #define GL_ONE_MINUS_SRC_ALPHA            0x0303
 #define GL_DST_ALPHA                      0x0304
 #define GL_ONE_MINUS_DST_ALPHA            0x0305
-
-/* BlendingFactorSrc */
-/*      GL_ZERO */
-/*      GL_ONE */
 #define GL_DST_COLOR                      0x0306
 #define GL_ONE_MINUS_DST_COLOR            0x0307
 #define GL_SRC_ALPHA_SATURATE             0x0308
-/*      GL_SRC_ALPHA */
-/*      GL_ONE_MINUS_SRC_ALPHA */
-/*      GL_DST_ALPHA */
-/*      GL_ONE_MINUS_DST_ALPHA */
-
-/* BlendEquationSeparate */
 #define GL_FUNC_ADD                       0x8006
 #define GL_BLEND_EQUATION                 0x8009
-#define GL_BLEND_EQUATION_RGB             0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_RGB             0x8009
 #define GL_BLEND_EQUATION_ALPHA           0x883D
-
-/* BlendSubtract */
 #define GL_FUNC_SUBTRACT                  0x800A
 #define GL_FUNC_REVERSE_SUBTRACT          0x800B
-
-/* Separate Blend Functions */
 #define GL_BLEND_DST_RGB                  0x80C8
 #define GL_BLEND_SRC_RGB                  0x80C9
 #define GL_BLEND_DST_ALPHA                0x80CA
@@ -110,38 +117,19 @@
 #define GL_CONSTANT_ALPHA                 0x8003
 #define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
 #define GL_BLEND_COLOR                    0x8005
-
-/* Buffer Objects */
 #define GL_ARRAY_BUFFER                   0x8892
 #define GL_ELEMENT_ARRAY_BUFFER           0x8893
 #define GL_ARRAY_BUFFER_BINDING           0x8894
 #define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
-
 #define GL_STREAM_DRAW                    0x88E0
 #define GL_STATIC_DRAW                    0x88E4
 #define GL_DYNAMIC_DRAW                   0x88E8
-
 #define GL_BUFFER_SIZE                    0x8764
 #define GL_BUFFER_USAGE                   0x8765
-
 #define GL_CURRENT_VERTEX_ATTRIB          0x8626
-
-/* CullFaceMode */
 #define GL_FRONT                          0x0404
 #define GL_BACK                           0x0405
 #define GL_FRONT_AND_BACK                 0x0408
-
-/* DepthFunction */
-/*      GL_NEVER */
-/*      GL_LESS */
-/*      GL_EQUAL */
-/*      GL_LEQUAL */
-/*      GL_GREATER */
-/*      GL_NOTEQUAL */
-/*      GL_GEQUAL */
-/*      GL_ALWAYS */
-
-/* EnableCap */
 #define GL_TEXTURE_2D                     0x0DE1
 #define GL_CULL_FACE                      0x0B44
 #define GL_BLEND                          0x0BE2
@@ -152,19 +140,13 @@
 #define GL_POLYGON_OFFSET_FILL            0x8037
 #define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
 #define GL_SAMPLE_COVERAGE                0x80A0
-
-/* ErrorCode */
 #define GL_NO_ERROR                       0
 #define GL_INVALID_ENUM                   0x0500
 #define GL_INVALID_VALUE                  0x0501
 #define GL_INVALID_OPERATION              0x0502
 #define GL_OUT_OF_MEMORY                  0x0505
-
-/* FrontFaceDirection */
 #define GL_CW                             0x0900
 #define GL_CCW                            0x0901
-
-/* GetPName */
 #define GL_LINE_WIDTH                     0x0B21
 #define GL_ALIASED_POINT_SIZE_RANGE       0x846D
 #define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
@@ -191,7 +173,6 @@
 #define GL_STENCIL_BACK_WRITEMASK         0x8CA5
 #define GL_VIEWPORT                       0x0BA2
 #define GL_SCISSOR_BOX                    0x0C10
-/*      GL_SCISSOR_TEST */
 #define GL_COLOR_CLEAR_VALUE              0x0C22
 #define GL_COLOR_WRITEMASK                0x0C23
 #define GL_UNPACK_ALIGNMENT               0x0CF5
@@ -206,32 +187,18 @@
 #define GL_DEPTH_BITS                     0x0D56
 #define GL_STENCIL_BITS                   0x0D57
 #define GL_POLYGON_OFFSET_UNITS           0x2A00
-/*      GL_POLYGON_OFFSET_FILL */
 #define GL_POLYGON_OFFSET_FACTOR          0x8038
 #define GL_TEXTURE_BINDING_2D             0x8069
 #define GL_SAMPLE_BUFFERS                 0x80A8
 #define GL_SAMPLES                        0x80A9
 #define GL_SAMPLE_COVERAGE_VALUE          0x80AA
 #define GL_SAMPLE_COVERAGE_INVERT         0x80AB
-
-/* GetTextureParameter */
-/*      GL_TEXTURE_MAG_FILTER */
-/*      GL_TEXTURE_MIN_FILTER */
-/*      GL_TEXTURE_WRAP_S */
-/*      GL_TEXTURE_WRAP_T */
-
 #define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
 #define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
-
-/* HintMode */
 #define GL_DONT_CARE                      0x1100
 #define GL_FASTEST                        0x1101
 #define GL_NICEST                         0x1102
-
-/* HintTarget */
-#define GL_GENERATE_MIPMAP_HINT            0x8192
-
-/* DataType */
+#define GL_GENERATE_MIPMAP_HINT           0x8192
 #define GL_BYTE                           0x1400
 #define GL_UNSIGNED_BYTE                  0x1401
 #define GL_SHORT                          0x1402
@@ -240,44 +207,35 @@
 #define GL_UNSIGNED_INT                   0x1405
 #define GL_FLOAT                          0x1406
 #define GL_FIXED                          0x140C
-
-/* PixelFormat */
 #define GL_DEPTH_COMPONENT                0x1902
 #define GL_ALPHA                          0x1906
 #define GL_RGB                            0x1907
 #define GL_RGBA                           0x1908
 #define GL_LUMINANCE                      0x1909
 #define GL_LUMINANCE_ALPHA                0x190A
-
-/* PixelType */
-/*      GL_UNSIGNED_BYTE */
 #define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
 #define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
 #define GL_UNSIGNED_SHORT_5_6_5           0x8363
-
-/* Shaders */
-#define GL_FRAGMENT_SHADER                  0x8B30
-#define GL_VERTEX_SHADER                    0x8B31
-#define GL_MAX_VERTEX_ATTRIBS               0x8869
-#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
-#define GL_MAX_VARYING_VECTORS              0x8DFC
+#define GL_FRAGMENT_SHADER                0x8B30
+#define GL_VERTEX_SHADER                  0x8B31
+#define GL_MAX_VERTEX_ATTRIBS             0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS     0x8DFB
+#define GL_MAX_VARYING_VECTORS            0x8DFC
 #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
-#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS   0x8B4C
-#define GL_MAX_TEXTURE_IMAGE_UNITS          0x8872
-#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
-#define GL_SHADER_TYPE                      0x8B4F
-#define GL_DELETE_STATUS                    0x8B80
-#define GL_LINK_STATUS                      0x8B82
-#define GL_VALIDATE_STATUS                  0x8B83
-#define GL_ATTACHED_SHADERS                 0x8B85
-#define GL_ACTIVE_UNIFORMS                  0x8B86
-#define GL_ACTIVE_UNIFORM_MAX_LENGTH        0x8B87
-#define GL_ACTIVE_ATTRIBUTES                0x8B89
-#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH      0x8B8A
-#define GL_SHADING_LANGUAGE_VERSION         0x8B8C
-#define GL_CURRENT_PROGRAM                  0x8B8D
-
-/* StencilFunction */
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS        0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS   0x8DFD
+#define GL_SHADER_TYPE                    0x8B4F
+#define GL_DELETE_STATUS                  0x8B80
+#define GL_LINK_STATUS                    0x8B82
+#define GL_VALIDATE_STATUS                0x8B83
+#define GL_ATTACHED_SHADERS               0x8B85
+#define GL_ACTIVE_UNIFORMS                0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH      0x8B87
+#define GL_ACTIVE_ATTRIBUTES              0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH    0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION       0x8B8C
+#define GL_CURRENT_PROGRAM                0x8B8D
 #define GL_NEVER                          0x0200
 #define GL_LESS                           0x0201
 #define GL_EQUAL                          0x0202
@@ -286,9 +244,6 @@
 #define GL_NOTEQUAL                       0x0205
 #define GL_GEQUAL                         0x0206
 #define GL_ALWAYS                         0x0207
-
-/* StencilOp */
-/*      GL_ZERO */
 #define GL_KEEP                           0x1E00
 #define GL_REPLACE                        0x1E01
 #define GL_INCR                           0x1E02
@@ -296,35 +251,21 @@
 #define GL_INVERT                         0x150A
 #define GL_INCR_WRAP                      0x8507
 #define GL_DECR_WRAP                      0x8508
-
-/* StringName */
 #define GL_VENDOR                         0x1F00
 #define GL_RENDERER                       0x1F01
 #define GL_VERSION                        0x1F02
 #define GL_EXTENSIONS                     0x1F03
-
-/* TextureMagFilter */
 #define GL_NEAREST                        0x2600
 #define GL_LINEAR                         0x2601
-
-/* TextureMinFilter */
-/*      GL_NEAREST */
-/*      GL_LINEAR */
 #define GL_NEAREST_MIPMAP_NEAREST         0x2700
 #define GL_LINEAR_MIPMAP_NEAREST          0x2701
 #define GL_NEAREST_MIPMAP_LINEAR          0x2702
 #define GL_LINEAR_MIPMAP_LINEAR           0x2703
-
-/* TextureParameterName */
 #define GL_TEXTURE_MAG_FILTER             0x2800
 #define GL_TEXTURE_MIN_FILTER             0x2801
 #define GL_TEXTURE_WRAP_S                 0x2802
 #define GL_TEXTURE_WRAP_T                 0x2803
-
-/* TextureTarget */
-/*      GL_TEXTURE_2D */
 #define GL_TEXTURE                        0x1702
-
 #define GL_TEXTURE_CUBE_MAP               0x8513
 #define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
 #define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
@@ -334,8 +275,6 @@
 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
 #define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
-
-/* TextureUnit */
 #define GL_TEXTURE0                       0x84C0
 #define GL_TEXTURE1                       0x84C1
 #define GL_TEXTURE2                       0x84C2
@@ -369,13 +308,9 @@
 #define GL_TEXTURE30                      0x84DE
 #define GL_TEXTURE31                      0x84DF
 #define GL_ACTIVE_TEXTURE                 0x84E0
-
-/* TextureWrapMode */
 #define GL_REPEAT                         0x2901
 #define GL_CLAMP_TO_EDGE                  0x812F
 #define GL_MIRRORED_REPEAT                0x8370
-
-/* Uniform Types */
 #define GL_FLOAT_VEC2                     0x8B50
 #define GL_FLOAT_VEC3                     0x8B51
 #define GL_FLOAT_VEC4                     0x8B52
@@ -391,49 +326,34 @@
 #define GL_FLOAT_MAT4                     0x8B5C
 #define GL_SAMPLER_2D                     0x8B5E
 #define GL_SAMPLER_CUBE                   0x8B60
-
-/* Vertex Arrays */
-#define GL_VERTEX_ATTRIB_ARRAY_ENABLED        0x8622
-#define GL_VERTEX_ATTRIB_ARRAY_SIZE           0x8623
-#define GL_VERTEX_ATTRIB_ARRAY_STRIDE         0x8624
-#define GL_VERTEX_ATTRIB_ARRAY_TYPE           0x8625
-#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED     0x886A
-#define GL_VERTEX_ATTRIB_ARRAY_POINTER        0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645
 #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
-
-/* Read Format */
-#define GL_IMPLEMENTATION_COLOR_READ_TYPE   0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
 #define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
-
-/* Shader Source */
 #define GL_COMPILE_STATUS                 0x8B81
 #define GL_INFO_LOG_LENGTH                0x8B84
 #define GL_SHADER_SOURCE_LENGTH           0x8B88
 #define GL_SHADER_COMPILER                0x8DFA
-
-/* Shader Binary */
 #define GL_SHADER_BINARY_FORMATS          0x8DF8
 #define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
-
-/* Shader Precision-Specified Types */
 #define GL_LOW_FLOAT                      0x8DF0
 #define GL_MEDIUM_FLOAT                   0x8DF1
 #define GL_HIGH_FLOAT                     0x8DF2
 #define GL_LOW_INT                        0x8DF3
 #define GL_MEDIUM_INT                     0x8DF4
 #define GL_HIGH_INT                       0x8DF5
-
-/* Framebuffer Object. */
 #define GL_FRAMEBUFFER                    0x8D40
 #define GL_RENDERBUFFER                   0x8D41
-
 #define GL_RGBA4                          0x8056
 #define GL_RGB5_A1                        0x8057
 #define GL_RGB565                         0x8D62
 #define GL_DEPTH_COMPONENT16              0x81A5
-#define GL_STENCIL_INDEX                  0x1901
 #define GL_STENCIL_INDEX8                 0x8D48
-
 #define GL_RENDERBUFFER_WIDTH             0x8D42
 #define GL_RENDERBUFFER_HEIGHT            0x8D43
 #define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
@@ -443,179 +363,313 @@
 #define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
 #define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
 #define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
-
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           0x8CD0
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME           0x8CD1
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
-
 #define GL_COLOR_ATTACHMENT0              0x8CE0
 #define GL_DEPTH_ATTACHMENT               0x8D00
 #define GL_STENCIL_ATTACHMENT             0x8D20
-
 #define GL_NONE                           0
-
-#define GL_FRAMEBUFFER_COMPLETE                      0x8CD5
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         0x8CD6
+#define GL_FRAMEBUFFER_COMPLETE           0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
 #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
-#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS         0x8CD9
-#define GL_FRAMEBUFFER_UNSUPPORTED                   0x8CDD
-
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED        0x8CDD
 #define GL_FRAMEBUFFER_BINDING            0x8CA6
 #define GL_RENDERBUFFER_BINDING           0x8CA7
 #define GL_MAX_RENDERBUFFER_SIZE          0x84E8
-
 #define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
-
-/*-------------------------------------------------------------------------
- * GL core functions.
- *-----------------------------------------------------------------------*/
-
-GL_APICALL void         GL_APIENTRY glActiveTexture (GLenum texture);
-GL_APICALL void         GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
-GL_APICALL void         GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
-GL_APICALL void         GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
-GL_APICALL void         GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
-GL_APICALL void         GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
-GL_APICALL void         GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
-GL_APICALL void         GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
-GL_APICALL void         GL_APIENTRY glBlendEquation ( GLenum mode );
-GL_APICALL void         GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
-GL_APICALL void         GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
-GL_APICALL void         GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
-GL_APICALL void         GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
-GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
-GL_APICALL GLenum       GL_APIENTRY glCheckFramebufferStatus (GLenum target);
-GL_APICALL void         GL_APIENTRY glClear (GLbitfield mask);
-GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
-GL_APICALL void         GL_APIENTRY glClearDepthf (GLclampf depth);
-GL_APICALL void         GL_APIENTRY glClearStencil (GLint s);
-GL_APICALL void         GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-GL_APICALL void         GL_APIENTRY glCompileShader (GLuint shader);
-GL_APICALL void         GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
-GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
-GL_APICALL void         GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
-GL_APICALL void         GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-GL_APICALL GLuint       GL_APIENTRY glCreateProgram (void);
-GL_APICALL GLuint       GL_APIENTRY glCreateShader (GLenum type);
-GL_APICALL void         GL_APIENTRY glCullFace (GLenum mode);
-GL_APICALL void         GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
-GL_APICALL void         GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
-GL_APICALL void         GL_APIENTRY glDeleteProgram (GLuint program);
-GL_APICALL void         GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
-GL_APICALL void         GL_APIENTRY glDeleteShader (GLuint shader);
-GL_APICALL void         GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
-GL_APICALL void         GL_APIENTRY glDepthFunc (GLenum func);
-GL_APICALL void         GL_APIENTRY glDepthMask (GLboolean flag);
-GL_APICALL void         GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
-GL_APICALL void         GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
-GL_APICALL void         GL_APIENTRY glDisable (GLenum cap);
-GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
-GL_APICALL void         GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
-GL_APICALL void         GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
-GL_APICALL void         GL_APIENTRY glEnable (GLenum cap);
-GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
-GL_APICALL void         GL_APIENTRY glFinish (void);
-GL_APICALL void         GL_APIENTRY glFlush (void);
-GL_APICALL void         GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-GL_APICALL void         GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GL_APICALL void         GL_APIENTRY glFrontFace (GLenum mode);
-GL_APICALL void         GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
-GL_APICALL void         GL_APIENTRY glGenerateMipmap (GLenum target);
-GL_APICALL void         GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
-GL_APICALL void         GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
-GL_APICALL void         GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
-GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
-GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
-GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
-GL_APICALL int          GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
-GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
-GL_APICALL void         GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
-GL_APICALL GLenum       GL_APIENTRY glGetError (void);
-GL_APICALL void         GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
-GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
-GL_APICALL void         GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
-GL_APICALL void         GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
-GL_APICALL void         GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
-GL_APICALL void         GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
-GL_APICALL void         GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
-GL_APICALL void         GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
-GL_APICALL void         GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
-GL_APICALL void         GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
-GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
-GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
-GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
-GL_APICALL void         GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
-GL_APICALL void         GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
-GL_APICALL int          GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
-GL_APICALL void         GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
-GL_APICALL void         GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
-GL_APICALL void         GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
-GL_APICALL void         GL_APIENTRY glHint (GLenum target, GLenum mode);
-GL_APICALL GLboolean    GL_APIENTRY glIsBuffer (GLuint buffer);
-GL_APICALL GLboolean    GL_APIENTRY glIsEnabled (GLenum cap);
-GL_APICALL GLboolean    GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
-GL_APICALL GLboolean    GL_APIENTRY glIsProgram (GLuint program);
-GL_APICALL GLboolean    GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
-GL_APICALL GLboolean    GL_APIENTRY glIsShader (GLuint shader);
-GL_APICALL GLboolean    GL_APIENTRY glIsTexture (GLuint texture);
-GL_APICALL void         GL_APIENTRY glLineWidth (GLfloat width);
-GL_APICALL void         GL_APIENTRY glLinkProgram (GLuint program);
-GL_APICALL void         GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
-GL_APICALL void         GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
-GL_APICALL void         GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
-GL_APICALL void         GL_APIENTRY glReleaseShaderCompiler (void);
-GL_APICALL void         GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-GL_APICALL void         GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
-GL_APICALL void         GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
-GL_APICALL void         GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
-GL_APICALL void         GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
-GL_APICALL void         GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
-GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
-GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
-GL_APICALL void         GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
-GL_APICALL void         GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
-GL_APICALL void         GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
-GL_APICALL void         GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
-GL_APICALL void         GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
-GL_APICALL void         GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
-GL_APICALL void         GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
-GL_APICALL void         GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
-GL_APICALL void         GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
-GL_APICALL void         GL_APIENTRY glUniform1f (GLint location, GLfloat x);
-GL_APICALL void         GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
-GL_APICALL void         GL_APIENTRY glUniform1i (GLint location, GLint x);
-GL_APICALL void         GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
-GL_APICALL void         GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
-GL_APICALL void         GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
-GL_APICALL void         GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
-GL_APICALL void         GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
-GL_APICALL void         GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
-GL_APICALL void         GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
-GL_APICALL void         GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
-GL_APICALL void         GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
-GL_APICALL void         GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-GL_APICALL void         GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
-GL_APICALL void         GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
-GL_APICALL void         GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
-GL_APICALL void         GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-GL_APICALL void         GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-GL_APICALL void         GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-GL_APICALL void         GL_APIENTRY glUseProgram (GLuint program);
-GL_APICALL void         GL_APIENTRY glValidateProgram (GLuint program);
-GL_APICALL void         GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
-GL_APICALL void         GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
-GL_APICALL void         GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
-GL_APICALL void         GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
-GL_APICALL void         GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
-GL_APICALL void         GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
-GL_APICALL void         GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-GL_APICALL void         GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
-GL_APICALL void         GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
-GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ES_VERSION_2_0 */
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __gl2_h_ */
+#endif
diff --git a/src/third_party/angle/include/GLES2/gl2ext.h b/src/third_party/angle/include/GLES2/gl2ext.h
index f70f026..079de71 100644
--- a/src/third_party/angle/include/GLES2/gl2ext.h
+++ b/src/third_party/angle/include/GLES2/gl2ext.h
@@ -1,1275 +1,2320 @@
 #ifndef __gl2ext_h_
-#define __gl2ext_h_
-
-/* $Revision: 16482 $ on $Date:: 2012-01-04 13:44:55 -0500 #$ */
+#define __gl2ext_h_ 1
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
- * This document is licensed under the SGI Free Software B License Version
- * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
- */
+** Copyright (c) 2013-2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/
+**
+** Khronos $Revision: 33260 $ on $Date: 2016-10-27 03:38:44 -0700 (Thu, 27 Oct 2016) $
+*/
 
 #ifndef GL_APIENTRYP
-#   define GL_APIENTRYP GL_APIENTRY*
+#define GL_APIENTRYP GL_APIENTRY*
 #endif
 
-/*------------------------------------------------------------------------*
- * OES extension tokens
- *------------------------------------------------------------------------*/
+/* Generated on date 20161027 */
 
-/* GL_OES_compressed_ETC1_RGB8_texture */
-#ifndef GL_OES_compressed_ETC1_RGB8_texture
-#define GL_ETC1_RGB8_OES                                        0x8D64
-#endif
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]
+ * Versions emitted: _nomatch_^
+ * Default extensions included: gles2
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
 
-/* GL_OES_compressed_paletted_texture */
-#ifndef GL_OES_compressed_paletted_texture
-#define GL_PALETTE4_RGB8_OES                                    0x8B90
-#define GL_PALETTE4_RGBA8_OES                                   0x8B91
-#define GL_PALETTE4_R5_G6_B5_OES                                0x8B92
-#define GL_PALETTE4_RGBA4_OES                                   0x8B93
-#define GL_PALETTE4_RGB5_A1_OES                                 0x8B94
-#define GL_PALETTE8_RGB8_OES                                    0x8B95
-#define GL_PALETTE8_RGBA8_OES                                   0x8B96
-#define GL_PALETTE8_R5_G6_B5_OES                                0x8B97
-#define GL_PALETTE8_RGBA4_OES                                   0x8B98
-#define GL_PALETTE8_RGB5_A1_OES                                 0x8B99
-#endif
+#ifndef GL_ARB_sparse_texture2
+#define GL_ARB_sparse_texture2 1
+#endif /* GL_ARB_sparse_texture2 */
 
-/* GL_OES_depth24 */
-#ifndef GL_OES_depth24
-#define GL_DEPTH_COMPONENT24_OES                                0x81A6
+#ifndef GL_KHR_blend_equation_advanced
+#define GL_KHR_blend_equation_advanced 1
+#define GL_MULTIPLY_KHR                   0x9294
+#define GL_SCREEN_KHR                     0x9295
+#define GL_OVERLAY_KHR                    0x9296
+#define GL_DARKEN_KHR                     0x9297
+#define GL_LIGHTEN_KHR                    0x9298
+#define GL_COLORDODGE_KHR                 0x9299
+#define GL_COLORBURN_KHR                  0x929A
+#define GL_HARDLIGHT_KHR                  0x929B
+#define GL_SOFTLIGHT_KHR                  0x929C
+#define GL_DIFFERENCE_KHR                 0x929E
+#define GL_EXCLUSION_KHR                  0x92A0
+#define GL_HSL_HUE_KHR                    0x92AD
+#define GL_HSL_SATURATION_KHR             0x92AE
+#define GL_HSL_COLOR_KHR                  0x92AF
+#define GL_HSL_LUMINOSITY_KHR             0x92B0
+typedef void (GL_APIENTRYP PFNGLBLENDBARRIERKHRPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlendBarrierKHR (void);
 #endif
+#endif /* GL_KHR_blend_equation_advanced */
 
-/* GL_OES_depth32 */
-#ifndef GL_OES_depth32
-#define GL_DEPTH_COMPONENT32_OES                                0x81A7
-#endif
+#ifndef GL_KHR_blend_equation_advanced_coherent
+#define GL_KHR_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_KHR    0x9285
+#endif /* GL_KHR_blend_equation_advanced_coherent */
 
-/* GL_OES_depth_texture */
-/* No new tokens introduced by this extension. */
+#ifndef GL_KHR_context_flush_control
+#define GL_KHR_context_flush_control 1
+#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR   0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC
+#endif /* GL_KHR_context_flush_control */
 
-/* GL_OES_EGL_image */
-#ifndef GL_OES_EGL_image
-typedef void* GLeglImageOES;
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+typedef void (GL_APIENTRY  *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_SAMPLER                        0x82E6
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR   0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_KHR    0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_KHR  0x8245
+#define GL_DEBUG_SOURCE_API_KHR           0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR   0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_KHR   0x824A
+#define GL_DEBUG_SOURCE_OTHER_KHR         0x824B
+#define GL_DEBUG_TYPE_ERROR_KHR           0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_KHR     0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_KHR     0x8250
+#define GL_DEBUG_TYPE_OTHER_KHR           0x8251
+#define GL_DEBUG_TYPE_MARKER_KHR          0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP_KHR      0x8269
+#define GL_DEBUG_TYPE_POP_GROUP_KHR       0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH_KHR    0x826D
+#define GL_BUFFER_KHR                     0x82E0
+#define GL_SHADER_KHR                     0x82E1
+#define GL_PROGRAM_KHR                    0x82E2
+#define GL_VERTEX_ARRAY_KHR               0x8074
+#define GL_QUERY_KHR                      0x82E3
+#define GL_PROGRAM_PIPELINE_KHR           0x82E4
+#define GL_SAMPLER_KHR                    0x82E6
+#define GL_MAX_LABEL_LENGTH_KHR           0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR   0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR  0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_KHR      0x9145
+#define GL_DEBUG_SEVERITY_HIGH_KHR        0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_KHR      0x9147
+#define GL_DEBUG_SEVERITY_LOW_KHR         0x9148
+#define GL_DEBUG_OUTPUT_KHR               0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR     0x00000002
+#define GL_STACK_OVERFLOW_KHR             0x0503
+#define GL_STACK_UNDERFLOW_KHR            0x0504
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKKHRPROC) (GLDEBUGPROCKHR callback, const void *userParam);
+typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPKHRPROC) (void);
+typedef void (GL_APIENTRYP PFNGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVKHRPROC) (GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDebugMessageControlKHR (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GL_APICALL void GL_APIENTRY glDebugMessageInsertKHR (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GL_APICALL void GL_APIENTRY glDebugMessageCallbackKHR (GLDEBUGPROCKHR callback, const void *userParam);
+GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLogKHR (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GL_APICALL void GL_APIENTRY glPushDebugGroupKHR (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GL_APICALL void GL_APIENTRY glPopDebugGroupKHR (void);
+GL_APICALL void GL_APIENTRY glObjectLabelKHR (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelKHR (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glObjectPtrLabelKHR (const void *ptr, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectPtrLabelKHR (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, void **params);
 #endif
+#endif /* GL_KHR_debug */
 
-/* GL_OES_EGL_image_external */
-#ifndef GL_OES_EGL_image_external
-/* GLeglImageOES defined in GL_OES_EGL_image already. */
-#define GL_TEXTURE_EXTERNAL_OES                                 0x8D65
-#define GL_SAMPLER_EXTERNAL_OES                                 0x8D66
-#define GL_TEXTURE_BINDING_EXTERNAL_OES                         0x8D67
-#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES                     0x8D68
-#endif
+#ifndef GL_KHR_no_error
+#define GL_KHR_no_error 1
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR  0x00000008
+#endif /* GL_KHR_no_error */
 
-/* GL_OES_element_index_uint */
-#ifndef GL_OES_element_index_uint
-#define GL_UNSIGNED_INT                                         0x1405
-#endif
+#ifndef GL_KHR_robust_buffer_access_behavior
+#define GL_KHR_robust_buffer_access_behavior 1
+#endif /* GL_KHR_robust_buffer_access_behavior */
 
-/* GL_OES_get_program_binary */
-#ifndef GL_OES_get_program_binary
-#define GL_PROGRAM_BINARY_LENGTH_OES                            0x8741
-#define GL_NUM_PROGRAM_BINARY_FORMATS_OES                       0x87FE
-#define GL_PROGRAM_BINARY_FORMATS_OES                           0x87FF
+#ifndef GL_KHR_robustness
+#define GL_KHR_robustness 1
+#define GL_CONTEXT_ROBUST_ACCESS_KHR      0x90F3
+#define GL_LOSE_CONTEXT_ON_RESET_KHR      0x8252
+#define GL_GUILTY_CONTEXT_RESET_KHR       0x8253
+#define GL_INNOCENT_CONTEXT_RESET_KHR     0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_KHR      0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256
+#define GL_NO_RESET_NOTIFICATION_KHR      0x8261
+#define GL_CONTEXT_LOST_KHR               0x0507
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsKHR (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvKHR (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivKHR (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GL_APICALL void GL_APIENTRY glGetnUniformuivKHR (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
 #endif
+#endif /* GL_KHR_robustness */
 
-/* GL_OES_mapbuffer */
-#ifndef GL_OES_mapbuffer
-#define GL_WRITE_ONLY_OES                                       0x88B9
-#define GL_BUFFER_ACCESS_OES                                    0x88BB
-#define GL_BUFFER_MAPPED_OES                                    0x88BC
-#define GL_BUFFER_MAP_POINTER_OES                               0x88BD
-#endif
+#ifndef GL_KHR_texture_compression_astc_hdr
+#define GL_KHR_texture_compression_astc_hdr 1
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR   0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR   0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR   0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR   0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR   0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR   0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR   0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR   0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR  0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR  0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR  0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif /* GL_KHR_texture_compression_astc_hdr */
 
-/* GL_OES_packed_depth_stencil */
-#ifndef GL_OES_packed_depth_stencil
-#define GL_DEPTH_STENCIL_OES                                    0x84F9
-#define GL_UNSIGNED_INT_24_8_OES                                0x84FA
-#define GL_DEPTH24_STENCIL8_OES                                 0x88F0
-#endif
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif /* GL_KHR_texture_compression_astc_ldr */
 
-/* GL_OES_rgb8_rgba8 */
-#ifndef GL_OES_rgb8_rgba8
-#define GL_RGB8_OES                                             0x8051
-#define GL_RGBA8_OES                                            0x8058
-#endif
-
-/* GL_OES_standard_derivatives */
-#ifndef GL_OES_standard_derivatives
-#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES                  0x8B8B
-#endif
-
-/* GL_OES_stencil1 */
-#ifndef GL_OES_stencil1
-#define GL_STENCIL_INDEX1_OES                                   0x8D46
-#endif
-
-/* GL_OES_stencil4 */
-#ifndef GL_OES_stencil4
-#define GL_STENCIL_INDEX4_OES                                   0x8D47
-#endif
-
-/* GL_OES_texture_3D */
-#ifndef GL_OES_texture_3D
-#define GL_TEXTURE_WRAP_R_OES                                   0x8072
-#define GL_TEXTURE_3D_OES                                       0x806F
-#define GL_TEXTURE_BINDING_3D_OES                               0x806A
-#define GL_MAX_3D_TEXTURE_SIZE_OES                              0x8073
-#define GL_SAMPLER_3D_OES                                       0x8B5F
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES        0x8CD4
-#endif
-
-/* GL_OES_texture_float */
-/* No new tokens introduced by this extension. */
-
-/* GL_OES_texture_float_linear */
-/* No new tokens introduced by this extension. */
-
-/* GL_OES_texture_half_float */
-#ifndef GL_OES_texture_half_float
-#define GL_HALF_FLOAT_OES                                       0x8D61
-#endif
-
-/* GL_OES_texture_half_float_linear */
-/* No new tokens introduced by this extension. */
-
-/* GL_OES_texture_npot */
-/* No new tokens introduced by this extension. */
-
-/* GL_OES_vertex_array_object */
-#ifndef GL_OES_vertex_array_object
-#define GL_VERTEX_ARRAY_BINDING_OES                             0x85B5
-#endif
-
-/* GL_OES_vertex_half_float */
-/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
-
-/* GL_OES_vertex_type_10_10_10_2 */
-#ifndef GL_OES_vertex_type_10_10_10_2
-#define GL_UNSIGNED_INT_10_10_10_2_OES                          0x8DF6
-#define GL_INT_10_10_10_2_OES                                   0x8DF7
-#endif
-
-/*------------------------------------------------------------------------*
- * AMD extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_AMD_compressed_3DC_texture */
-#ifndef GL_AMD_compressed_3DC_texture
-#define GL_3DC_X_AMD                                            0x87F9
-#define GL_3DC_XY_AMD                                           0x87FA
-#endif
-
-/* GL_AMD_compressed_ATC_texture */
-#ifndef GL_AMD_compressed_ATC_texture
-#define GL_ATC_RGB_AMD                                          0x8C92
-#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          0x8C93
-#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      0x87EE
-#endif
-
-/* GL_AMD_performance_monitor */
-#ifndef GL_AMD_performance_monitor
-#define GL_COUNTER_TYPE_AMD                                     0x8BC0
-#define GL_COUNTER_RANGE_AMD                                    0x8BC1
-#define GL_UNSIGNED_INT64_AMD                                   0x8BC2
-#define GL_PERCENTAGE_AMD                                       0x8BC3
-#define GL_PERFMON_RESULT_AVAILABLE_AMD                         0x8BC4
-#define GL_PERFMON_RESULT_SIZE_AMD                              0x8BC5
-#define GL_PERFMON_RESULT_AMD                                   0x8BC6
-#endif
-
-/* GL_AMD_program_binary_Z400 */
-#ifndef GL_AMD_program_binary_Z400
-#define GL_Z400_BINARY_AMD                                      0x8740
-#endif
-
-/*------------------------------------------------------------------------*
- * ANGLE extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_ANGLE_framebuffer_blit */
-#ifndef GL_ANGLE_framebuffer_blit
-#define GL_READ_FRAMEBUFFER_ANGLE                               0x8CA8
-#define GL_DRAW_FRAMEBUFFER_ANGLE                               0x8CA9
-#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE                       0x8CA6
-#define GL_READ_FRAMEBUFFER_BINDING_ANGLE                       0x8CAA
-#endif
-
-/* GL_ANGLE_framebuffer_multisample */
-#ifndef GL_ANGLE_framebuffer_multisample
-#define GL_RENDERBUFFER_SAMPLES_ANGLE                           0x8CAB
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE             0x8D56
-#define GL_MAX_SAMPLES_ANGLE                                    0x8D57
-#endif
-
-/* GL_ANGLE_pack_reverse_row_order */
-#ifndef GL_ANGLE_pack_reverse_row_order
-#define GL_PACK_REVERSE_ROW_ORDER_ANGLE                         0x93A4
-#endif
-
-/* GL_ANGLE_texture_compression_dxt3 */
-#ifndef GL_ANGLE_texture_compression_dxt3
-#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE                      0x83F2
-#endif
-
-/* GL_ANGLE_texture_compression_dxt5 */
-#ifndef GL_ANGLE_texture_compression_dxt5
-#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE                      0x83F3
-#endif
-
-/* GL_ANGLE_translated_shader_source */
-#ifndef GL_ANGLE_translated_shader_source
-#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE                0x93A0
-#endif
-
-/* GL_ANGLE_texture_usage */
-#ifndef GL_ANGLE_texture_usage
-#define GL_TEXTURE_USAGE_ANGLE                                  0x93A2
-#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE                         0x93A3
-#endif
-
-/* GL_ANGLE_instanced_arrays */
-#ifndef GL_ANGLE_instanced_arrays
-#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE                    0x88FE
-#endif
-
-/* GL_ANGLE_program_binary */
-#ifndef GL_ANGLE_program_binary
-#define GL_PROGRAM_BINARY_ANGLE                                 0x93A6
-#endif
-
-/*------------------------------------------------------------------------*
- * APPLE extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_APPLE_rgb_422 */
-#ifndef GL_APPLE_rgb_422
-#define GL_RGB_422_APPLE                                        0x8A1F
-#define GL_UNSIGNED_SHORT_8_8_APPLE                             0x85BA
-#define GL_UNSIGNED_SHORT_8_8_REV_APPLE                         0x85BB
-#endif
-
-/* GL_APPLE_framebuffer_multisample */
-#ifndef GL_APPLE_framebuffer_multisample
-#define GL_RENDERBUFFER_SAMPLES_APPLE                           0x8CAB
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE             0x8D56
-#define GL_MAX_SAMPLES_APPLE                                    0x8D57
-#define GL_READ_FRAMEBUFFER_APPLE                               0x8CA8
-#define GL_DRAW_FRAMEBUFFER_APPLE                               0x8CA9
-#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE                       0x8CA6
-#define GL_READ_FRAMEBUFFER_BINDING_APPLE                       0x8CAA
-#endif
-
-/* GL_APPLE_texture_format_BGRA8888 */
-#ifndef GL_APPLE_texture_format_BGRA8888
-#define GL_BGRA_EXT                                             0x80E1
-#endif
-
-/* GL_APPLE_texture_max_level */
-#ifndef GL_APPLE_texture_max_level
-#define GL_TEXTURE_MAX_LEVEL_APPLE                              0x813D
-#endif
-
-/*------------------------------------------------------------------------*
- * ARM extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_ARM_mali_shader_binary */
-#ifndef GL_ARM_mali_shader_binary
-#define GL_MALI_SHADER_BINARY_ARM                               0x8F60
-#endif
-
-/* GL_ARM_rgba8 */
-/* No new tokens introduced by this extension. */
-
-/*------------------------------------------------------------------------*
- * EXT extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_EXT_blend_minmax */
-#ifndef GL_EXT_blend_minmax
-#define GL_MIN_EXT                                              0x8007
-#define GL_MAX_EXT                                              0x8008
-#endif
-
-/* GL_EXT_color_buffer_half_float */
-#ifndef GL_EXT_color_buffer_half_float
-#define GL_RGBA16F_EXT                                          0x881A
-#define GL_RGB16F_EXT                                           0x881B
-#define GL_RG16F_EXT                                            0x822F
-#define GL_R16F_EXT                                             0x822D
-#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT            0x8211
-#define GL_UNSIGNED_NORMALIZED_EXT                              0x8C17
-#endif
-
-/* GL_EXT_debug_label */
-#ifndef GL_EXT_debug_label
-#define GL_PROGRAM_PIPELINE_OBJECT_EXT                          0x8A4F
-#define GL_PROGRAM_OBJECT_EXT                                   0x8B40
-#define GL_SHADER_OBJECT_EXT                                    0x8B48
-#define GL_BUFFER_OBJECT_EXT                                    0x9151
-#define GL_QUERY_OBJECT_EXT                                     0x9153
-#define GL_VERTEX_ARRAY_OBJECT_EXT                              0x9154
-#endif
-
-/* GL_EXT_debug_marker */
-/* No new tokens introduced by this extension. */
-
-/* GL_EXT_discard_framebuffer */
-#ifndef GL_EXT_discard_framebuffer
-#define GL_COLOR_EXT                                            0x1800
-#define GL_DEPTH_EXT                                            0x1801
-#define GL_STENCIL_EXT                                          0x1802
-#endif
-
-/* GL_EXT_multisampled_render_to_texture */
-#ifndef GL_EXT_multisampled_render_to_texture
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT           0x8D6C
-#define GL_RENDERBUFFER_SAMPLES_EXT                             0x9133
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x9134
-#define GL_MAX_SAMPLES_EXT                                      0x9135
-#endif
-
-/* GL_EXT_multi_draw_arrays */
-/* No new tokens introduced by this extension. */
-
-/* GL_EXT_occlusion_query_boolean */
-#ifndef GL_EXT_occlusion_query_boolean
-#define GL_ANY_SAMPLES_PASSED_EXT                               0x8C2F
-#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT                  0x8D6A
-#define GL_CURRENT_QUERY_EXT                                    0x8865
-#define GL_QUERY_RESULT_EXT                                     0x8866
-#define GL_QUERY_RESULT_AVAILABLE_EXT                           0x8867
-#endif
-
-/* GL_EXT_read_format_bgra */
-#ifndef GL_EXT_read_format_bgra
-#define GL_BGRA_EXT                                             0x80E1
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT                       0x8365
-#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT                       0x8366
-#endif
-
-/* GL_EXT_robustness */
-#ifndef GL_EXT_robustness
-/* reuse GL_NO_ERROR */
-#define GL_GUILTY_CONTEXT_RESET_EXT                             0x8253
-#define GL_INNOCENT_CONTEXT_RESET_EXT                           0x8254
-#define GL_UNKNOWN_CONTEXT_RESET_EXT                            0x8255
-#define GL_CONTEXT_ROBUST_ACCESS_EXT                            0x90F3
-#define GL_RESET_NOTIFICATION_STRATEGY_EXT                      0x8256
-#define GL_LOSE_CONTEXT_ON_RESET_EXT                            0x8252
-#define GL_NO_RESET_NOTIFICATION_EXT                            0x8261
-#endif
-
-/* GL_EXT_separate_shader_objects */
-#ifndef GL_EXT_separate_shader_objects
-#define GL_VERTEX_SHADER_BIT_EXT                                0x00000001
-#define GL_FRAGMENT_SHADER_BIT_EXT                              0x00000002
-#define GL_ALL_SHADER_BITS_EXT                                  0xFFFFFFFF
-#define GL_PROGRAM_SEPARABLE_EXT                                0x8258
-#define GL_ACTIVE_PROGRAM_EXT                                   0x8259
-#define GL_PROGRAM_PIPELINE_BINDING_EXT                         0x825A
-#endif
-
-/* GL_EXT_shader_texture_lod */
-/* No new tokens introduced by this extension. */
-
-/* GL_EXT_shadow_samplers */
-#ifndef GL_EXT_shadow_samplers
-#define GL_TEXTURE_COMPARE_MODE_EXT                             0x884C
-#define GL_TEXTURE_COMPARE_FUNC_EXT                             0x884D
-#define GL_COMPARE_REF_TO_TEXTURE_EXT                           0x884E
-#endif
-
-/* GL_EXT_sRGB */
-#ifndef GL_EXT_sRGB
-#define GL_SRGB_EXT                                             0x8C40
-#define GL_SRGB_ALPHA_EXT                                       0x8C42
-#define GL_SRGB8_ALPHA8_EXT                                     0x8C43
-#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT            0x8210
-#endif
-
-/* GL_EXT_texture_compression_dxt1 */
-#ifndef GL_EXT_texture_compression_dxt1
-#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT                         0x83F0
-#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT                        0x83F1
-#endif
-
-/* GL_EXT_texture_filter_anisotropic */
-#ifndef GL_EXT_texture_filter_anisotropic
-#define GL_TEXTURE_MAX_ANISOTROPY_EXT                           0x84FE
-#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       0x84FF
-#endif
-
-/* GL_EXT_texture_format_BGRA8888 */
-#ifndef GL_EXT_texture_format_BGRA8888
-#define GL_BGRA_EXT                                             0x80E1
-#endif
-
-/* GL_EXT_texture_rg */
-#ifndef GL_EXT_texture_rg
-#define GL_RED_EXT                                              0x1903
-#define GL_RG_EXT                                               0x8227
-#define GL_R8_EXT                                               0x8229
-#define GL_RG8_EXT                                              0x822B
-#endif
-
-/* GL_EXT_texture_storage */
-#ifndef GL_EXT_texture_storage
-#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT                         0x912F
-#define GL_ALPHA8_EXT                                           0x803C  
-#define GL_LUMINANCE8_EXT                                       0x8040
-#define GL_LUMINANCE8_ALPHA8_EXT                                0x8045
-#define GL_RGBA32F_EXT                                          0x8814  
-#define GL_RGB32F_EXT                                           0x8815
-#define GL_ALPHA32F_EXT                                         0x8816
-#define GL_LUMINANCE32F_EXT                                     0x8818
-#define GL_LUMINANCE_ALPHA32F_EXT                               0x8819
-/* reuse GL_RGBA16F_EXT */
-#define GL_RGB16F_EXT                                           0x881B
-#define GL_ALPHA16F_EXT                                         0x881C
-#define GL_LUMINANCE16F_EXT                                     0x881E
-#define GL_LUMINANCE_ALPHA16F_EXT                               0x881F
-#define GL_RGB10_A2_EXT                                         0x8059  
-#define GL_RGB10_EXT                                            0x8052
-#define GL_BGRA8_EXT                                            0x93A1
-#endif
-
-/* GL_EXT_texture_type_2_10_10_10_REV */
-#ifndef GL_EXT_texture_type_2_10_10_10_REV
-#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT                      0x8368
-#endif
-
-/* GL_EXT_unpack_subimage */
-#ifndef GL_EXT_unpack_subimage
-#define GL_UNPACK_ROW_LENGTH                                    0x0CF2
-#define GL_UNPACK_SKIP_ROWS                                     0x0CF3
-#define GL_UNPACK_SKIP_PIXELS                                   0x0CF4
-#endif
-
-/*------------------------------------------------------------------------*
- * DMP extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_DMP_shader_binary */
-#ifndef GL_DMP_shader_binary
-#define GL_SHADER_BINARY_DMP                                    0x9250
-#endif
-
-/*------------------------------------------------------------------------*
- * IMG extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_IMG_program_binary */
-#ifndef GL_IMG_program_binary
-#define GL_SGX_PROGRAM_BINARY_IMG                               0x9130
-#endif
-
-/* GL_IMG_read_format */
-#ifndef GL_IMG_read_format
-#define GL_BGRA_IMG                                             0x80E1
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG                       0x8365
-#endif
-
-/* GL_IMG_shader_binary */
-#ifndef GL_IMG_shader_binary
-#define GL_SGX_BINARY_IMG                                       0x8C0A
-#endif
-
-/* GL_IMG_texture_compression_pvrtc */
-#ifndef GL_IMG_texture_compression_pvrtc
-#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
-#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
-#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
-#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
-#endif
-
-/* GL_IMG_multisampled_render_to_texture */
-#ifndef GL_IMG_multisampled_render_to_texture
-#define GL_RENDERBUFFER_SAMPLES_IMG                             0x9133
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG               0x9134
-#define GL_MAX_SAMPLES_IMG                                      0x9135
-#define GL_TEXTURE_SAMPLES_IMG                                  0x9136
-#endif
-
-/*------------------------------------------------------------------------*
- * NV extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_NV_coverage_sample */
-#ifndef GL_NV_coverage_sample
-#define GL_COVERAGE_COMPONENT_NV                                0x8ED0
-#define GL_COVERAGE_COMPONENT4_NV                               0x8ED1
-#define GL_COVERAGE_ATTACHMENT_NV                               0x8ED2
-#define GL_COVERAGE_BUFFERS_NV                                  0x8ED3
-#define GL_COVERAGE_SAMPLES_NV                                  0x8ED4
-#define GL_COVERAGE_ALL_FRAGMENTS_NV                            0x8ED5
-#define GL_COVERAGE_EDGE_FRAGMENTS_NV                           0x8ED6
-#define GL_COVERAGE_AUTOMATIC_NV                                0x8ED7
-#define GL_COVERAGE_BUFFER_BIT_NV                               0x8000
-#endif
-
-/* GL_NV_depth_nonlinear */
-#ifndef GL_NV_depth_nonlinear
-#define GL_DEPTH_COMPONENT16_NONLINEAR_NV                       0x8E2C
-#endif
-
-/* GL_NV_draw_buffers */
-#ifndef GL_NV_draw_buffers
-#define GL_MAX_DRAW_BUFFERS_NV                                  0x8824
-#define GL_DRAW_BUFFER0_NV                                      0x8825
-#define GL_DRAW_BUFFER1_NV                                      0x8826
-#define GL_DRAW_BUFFER2_NV                                      0x8827
-#define GL_DRAW_BUFFER3_NV                                      0x8828
-#define GL_DRAW_BUFFER4_NV                                      0x8829
-#define GL_DRAW_BUFFER5_NV                                      0x882A
-#define GL_DRAW_BUFFER6_NV                                      0x882B
-#define GL_DRAW_BUFFER7_NV                                      0x882C
-#define GL_DRAW_BUFFER8_NV                                      0x882D
-#define GL_DRAW_BUFFER9_NV                                      0x882E
-#define GL_DRAW_BUFFER10_NV                                     0x882F
-#define GL_DRAW_BUFFER11_NV                                     0x8830
-#define GL_DRAW_BUFFER12_NV                                     0x8831
-#define GL_DRAW_BUFFER13_NV                                     0x8832
-#define GL_DRAW_BUFFER14_NV                                     0x8833
-#define GL_DRAW_BUFFER15_NV                                     0x8834
-#define GL_COLOR_ATTACHMENT0_NV                                 0x8CE0
-#define GL_COLOR_ATTACHMENT1_NV                                 0x8CE1
-#define GL_COLOR_ATTACHMENT2_NV                                 0x8CE2
-#define GL_COLOR_ATTACHMENT3_NV                                 0x8CE3
-#define GL_COLOR_ATTACHMENT4_NV                                 0x8CE4
-#define GL_COLOR_ATTACHMENT5_NV                                 0x8CE5
-#define GL_COLOR_ATTACHMENT6_NV                                 0x8CE6
-#define GL_COLOR_ATTACHMENT7_NV                                 0x8CE7
-#define GL_COLOR_ATTACHMENT8_NV                                 0x8CE8
-#define GL_COLOR_ATTACHMENT9_NV                                 0x8CE9
-#define GL_COLOR_ATTACHMENT10_NV                                0x8CEA
-#define GL_COLOR_ATTACHMENT11_NV                                0x8CEB
-#define GL_COLOR_ATTACHMENT12_NV                                0x8CEC
-#define GL_COLOR_ATTACHMENT13_NV                                0x8CED
-#define GL_COLOR_ATTACHMENT14_NV                                0x8CEE
-#define GL_COLOR_ATTACHMENT15_NV                                0x8CEF
-#endif
-
-/* GL_EXT_draw_buffers */
-#ifndef GL_EXT_draw_buffers
-#define GL_MAX_DRAW_BUFFERS_EXT                                  0x8824
-#define GL_DRAW_BUFFER0_EXT                                      0x8825
-#define GL_DRAW_BUFFER1_EXT                                      0x8826
-#define GL_DRAW_BUFFER2_EXT                                      0x8827
-#define GL_DRAW_BUFFER3_EXT                                      0x8828
-#define GL_DRAW_BUFFER4_EXT                                      0x8829
-#define GL_DRAW_BUFFER5_EXT                                      0x882A
-#define GL_DRAW_BUFFER6_EXT                                      0x882B
-#define GL_DRAW_BUFFER7_EXT                                      0x882C
-#define GL_DRAW_BUFFER8_EXT                                      0x882D
-#define GL_DRAW_BUFFER9_EXT                                      0x882E
-#define GL_DRAW_BUFFER10_EXT                                     0x882F
-#define GL_DRAW_BUFFER11_EXT                                     0x8830
-#define GL_DRAW_BUFFER12_EXT                                     0x8831
-#define GL_DRAW_BUFFER13_EXT                                     0x8832
-#define GL_DRAW_BUFFER14_EXT                                     0x8833
-#define GL_DRAW_BUFFER15_EXT                                     0x8834
-#define GL_COLOR_ATTACHMENT0_EXT                                 0x8CE0
-#define GL_COLOR_ATTACHMENT1_EXT                                 0x8CE1
-#define GL_COLOR_ATTACHMENT2_EXT                                 0x8CE2
-#define GL_COLOR_ATTACHMENT3_EXT                                 0x8CE3
-#define GL_COLOR_ATTACHMENT4_EXT                                 0x8CE4
-#define GL_COLOR_ATTACHMENT5_EXT                                 0x8CE5
-#define GL_COLOR_ATTACHMENT6_EXT                                 0x8CE6
-#define GL_COLOR_ATTACHMENT7_EXT                                 0x8CE7
-#define GL_COLOR_ATTACHMENT8_EXT                                 0x8CE8
-#define GL_COLOR_ATTACHMENT9_EXT                                 0x8CE9
-#define GL_COLOR_ATTACHMENT10_EXT                                0x8CEA
-#define GL_COLOR_ATTACHMENT11_EXT                                0x8CEB
-#define GL_COLOR_ATTACHMENT12_EXT                                0x8CEC
-#define GL_COLOR_ATTACHMENT13_EXT                                0x8CED
-#define GL_COLOR_ATTACHMENT14_EXT                                0x8CEE
-#define GL_COLOR_ATTACHMENT15_EXT                                0x8CEF
-#define GL_MAX_COLOR_ATTACHMENTS_EXT                             0x8CDF
-#endif
-
-/* GL_NV_fbo_color_attachments */
-#ifndef GL_NV_fbo_color_attachments
-#define GL_MAX_COLOR_ATTACHMENTS_NV                             0x8CDF
-/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */
-#endif
-
-/* GL_NV_fence */
-#ifndef GL_NV_fence
-#define GL_ALL_COMPLETED_NV                                     0x84F2
-#define GL_FENCE_STATUS_NV                                      0x84F3
-#define GL_FENCE_CONDITION_NV                                   0x84F4
-#endif
-
-/* GL_NV_read_buffer */
-#ifndef GL_NV_read_buffer
-#define GL_READ_BUFFER_NV                                       0x0C02
-#endif
-
-/* GL_NV_read_buffer_front */
-/* No new tokens introduced by this extension. */
-
-/* GL_NV_read_depth */
-/* No new tokens introduced by this extension. */
-
-/* GL_NV_read_depth_stencil */
-/* No new tokens introduced by this extension. */
-
-/* GL_NV_read_stencil */
-/* No new tokens introduced by this extension. */
-
-/* GL_NV_texture_compression_s3tc_update */
-/* No new tokens introduced by this extension. */
-
-/* GL_NV_texture_npot_2D_mipmap */
-/* No new tokens introduced by this extension. */
-
-/*------------------------------------------------------------------------*
- * QCOM extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_QCOM_alpha_test */
-#ifndef GL_QCOM_alpha_test
-#define GL_ALPHA_TEST_QCOM                                      0x0BC0
-#define GL_ALPHA_TEST_FUNC_QCOM                                 0x0BC1
-#define GL_ALPHA_TEST_REF_QCOM                                  0x0BC2
-#endif
-
-/* GL_QCOM_driver_control */
-/* No new tokens introduced by this extension. */
-
-/* GL_QCOM_extended_get */
-#ifndef GL_QCOM_extended_get
-#define GL_TEXTURE_WIDTH_QCOM                                   0x8BD2
-#define GL_TEXTURE_HEIGHT_QCOM                                  0x8BD3
-#define GL_TEXTURE_DEPTH_QCOM                                   0x8BD4
-#define GL_TEXTURE_INTERNAL_FORMAT_QCOM                         0x8BD5
-#define GL_TEXTURE_FORMAT_QCOM                                  0x8BD6
-#define GL_TEXTURE_TYPE_QCOM                                    0x8BD7
-#define GL_TEXTURE_IMAGE_VALID_QCOM                             0x8BD8
-#define GL_TEXTURE_NUM_LEVELS_QCOM                              0x8BD9
-#define GL_TEXTURE_TARGET_QCOM                                  0x8BDA
-#define GL_TEXTURE_OBJECT_VALID_QCOM                            0x8BDB
-#define GL_STATE_RESTORE                                        0x8BDC
-#endif
-
-/* GL_QCOM_extended_get2 */
-/* No new tokens introduced by this extension. */
-
-/* GL_QCOM_perfmon_global_mode */
-#ifndef GL_QCOM_perfmon_global_mode
-#define GL_PERFMON_GLOBAL_MODE_QCOM                             0x8FA0
-#endif
-
-/* GL_QCOM_writeonly_rendering */
-#ifndef GL_QCOM_writeonly_rendering
-#define GL_WRITEONLY_RENDERING_QCOM                             0x8823
-#endif
-
-/* GL_QCOM_tiled_rendering */
-#ifndef GL_QCOM_tiled_rendering
-#define GL_COLOR_BUFFER_BIT0_QCOM                               0x00000001
-#define GL_COLOR_BUFFER_BIT1_QCOM                               0x00000002
-#define GL_COLOR_BUFFER_BIT2_QCOM                               0x00000004
-#define GL_COLOR_BUFFER_BIT3_QCOM                               0x00000008
-#define GL_COLOR_BUFFER_BIT4_QCOM                               0x00000010
-#define GL_COLOR_BUFFER_BIT5_QCOM                               0x00000020
-#define GL_COLOR_BUFFER_BIT6_QCOM                               0x00000040
-#define GL_COLOR_BUFFER_BIT7_QCOM                               0x00000080
-#define GL_DEPTH_BUFFER_BIT0_QCOM                               0x00000100
-#define GL_DEPTH_BUFFER_BIT1_QCOM                               0x00000200
-#define GL_DEPTH_BUFFER_BIT2_QCOM                               0x00000400
-#define GL_DEPTH_BUFFER_BIT3_QCOM                               0x00000800
-#define GL_DEPTH_BUFFER_BIT4_QCOM                               0x00001000
-#define GL_DEPTH_BUFFER_BIT5_QCOM                               0x00002000
-#define GL_DEPTH_BUFFER_BIT6_QCOM                               0x00004000
-#define GL_DEPTH_BUFFER_BIT7_QCOM                               0x00008000
-#define GL_STENCIL_BUFFER_BIT0_QCOM                             0x00010000
-#define GL_STENCIL_BUFFER_BIT1_QCOM                             0x00020000
-#define GL_STENCIL_BUFFER_BIT2_QCOM                             0x00040000
-#define GL_STENCIL_BUFFER_BIT3_QCOM                             0x00080000
-#define GL_STENCIL_BUFFER_BIT4_QCOM                             0x00100000
-#define GL_STENCIL_BUFFER_BIT5_QCOM                             0x00200000
-#define GL_STENCIL_BUFFER_BIT6_QCOM                             0x00400000
-#define GL_STENCIL_BUFFER_BIT7_QCOM                             0x00800000
-#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM                         0x01000000
-#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM                         0x02000000
-#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM                         0x04000000
-#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM                         0x08000000
-#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM                         0x10000000
-#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM                         0x20000000
-#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM                         0x40000000
-#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM                         0x80000000
-#endif
-
-/*------------------------------------------------------------------------*
- * VIV extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_VIV_shader_binary */
-#ifndef GL_VIV_shader_binary
-#define GL_SHADER_BINARY_VIV                                    0x8FC4
-#endif
-
-/*------------------------------------------------------------------------*
- * End of extension tokens, start of corresponding extension functions
- *------------------------------------------------------------------------*/
-
-/*------------------------------------------------------------------------*
- * OES extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_OES_compressed_ETC1_RGB8_texture */
-#ifndef GL_OES_compressed_ETC1_RGB8_texture
-#define GL_OES_compressed_ETC1_RGB8_texture 1
-#endif
-
-/* GL_OES_compressed_paletted_texture */
-#ifndef GL_OES_compressed_paletted_texture
-#define GL_OES_compressed_paletted_texture 1
-#endif
-
-/* GL_OES_depth24 */
-#ifndef GL_OES_depth24
-#define GL_OES_depth24 1
-#endif
-
-/* GL_OES_depth32 */
-#ifndef GL_OES_depth32
-#define GL_OES_depth32 1
-#endif
-
-/* GL_OES_depth_texture */
-#ifndef GL_OES_depth_texture
-#define GL_OES_depth_texture 1
-#endif
+#ifndef GL_KHR_texture_compression_astc_sliced_3d
+#define GL_KHR_texture_compression_astc_sliced_3d 1
+#endif /* GL_KHR_texture_compression_astc_sliced_3d */
 
-/* GL_OES_EGL_image */
 #ifndef GL_OES_EGL_image
 #define GL_OES_EGL_image 1
+typedef void *GLeglImageOES;
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
 GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
 #endif
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
-#endif
+#endif /* GL_OES_EGL_image */
 
-/* GL_OES_EGL_image_external */
 #ifndef GL_OES_EGL_image_external
 #define GL_OES_EGL_image_external 1
-/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */
-#endif
+#define GL_TEXTURE_EXTERNAL_OES           0x8D65
+#define GL_TEXTURE_BINDING_EXTERNAL_OES   0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+#define GL_SAMPLER_EXTERNAL_OES           0x8D66
+#endif /* GL_OES_EGL_image_external */
 
-/* GL_OES_element_index_uint */
+#ifndef GL_OES_EGL_image_external_essl3
+#define GL_OES_EGL_image_external_essl3 1
+#endif /* GL_OES_EGL_image_external_essl3 */
+
+#ifndef GL_OES_compressed_ETC1_RGB8_sub_texture
+#define GL_OES_compressed_ETC1_RGB8_sub_texture 1
+#endif /* GL_OES_compressed_ETC1_RGB8_sub_texture */
+
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#define GL_ETC1_RGB8_OES                  0x8D64
+#endif /* GL_OES_compressed_ETC1_RGB8_texture */
+
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#define GL_PALETTE4_RGB8_OES              0x8B90
+#define GL_PALETTE4_RGBA8_OES             0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES          0x8B92
+#define GL_PALETTE4_RGBA4_OES             0x8B93
+#define GL_PALETTE4_RGB5_A1_OES           0x8B94
+#define GL_PALETTE8_RGB8_OES              0x8B95
+#define GL_PALETTE8_RGBA8_OES             0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES          0x8B97
+#define GL_PALETTE8_RGBA4_OES             0x8B98
+#define GL_PALETTE8_RGB5_A1_OES           0x8B99
+#endif /* GL_OES_compressed_paletted_texture */
+
+#ifndef GL_OES_copy_image
+#define GL_OES_copy_image 1
+typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAOESPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyImageSubDataOES (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#endif
+#endif /* GL_OES_copy_image */
+
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#define GL_DEPTH_COMPONENT24_OES          0x81A6
+#endif /* GL_OES_depth24 */
+
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#define GL_DEPTH_COMPONENT32_OES          0x81A7
+#endif /* GL_OES_depth32 */
+
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif /* GL_OES_depth_texture */
+
+#ifndef GL_OES_draw_buffers_indexed
+#define GL_OES_draw_buffers_indexed 1
+#define GL_MIN                            0x8007
+#define GL_MAX                            0x8008
+typedef void (GL_APIENTRYP PFNGLENABLEIOESPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEIOESPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIOESPROC) (GLuint buf, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIOESPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCIOESPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIOESPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKIOESPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIOESPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEnableiOES (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiOES (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glBlendEquationiOES (GLuint buf, GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparateiOES (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunciOES (GLuint buf, GLenum src, GLenum dst);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparateiOES (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glColorMaskiOES (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediOES (GLenum target, GLuint index);
+#endif
+#endif /* GL_OES_draw_buffers_indexed */
+
+#ifndef GL_OES_draw_elements_base_vertex
+#define GL_OES_draw_elements_base_vertex 1
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexOES (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexOES (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#endif
+#endif /* GL_OES_draw_elements_base_vertex */
+
 #ifndef GL_OES_element_index_uint
 #define GL_OES_element_index_uint 1
-#endif
+#endif /* GL_OES_element_index_uint */
 
-/* GL_OES_fbo_render_mipmap */
 #ifndef GL_OES_fbo_render_mipmap
 #define GL_OES_fbo_render_mipmap 1
-#endif
+#endif /* GL_OES_fbo_render_mipmap */
 
-/* GL_OES_fragment_precision_high */
 #ifndef GL_OES_fragment_precision_high
 #define GL_OES_fragment_precision_high 1
-#endif
+#endif /* GL_OES_fragment_precision_high */
 
-/* GL_OES_get_program_binary */
+#ifndef GL_OES_geometry_point_size
+#define GL_OES_geometry_point_size 1
+#endif /* GL_OES_geometry_point_size */
+
+#ifndef GL_OES_geometry_shader
+#define GL_OES_geometry_shader 1
+#define GL_GEOMETRY_SHADER_OES            0x8DD9
+#define GL_GEOMETRY_SHADER_BIT_OES        0x00000004
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_OES 0x8916
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_OES 0x8917
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES 0x8918
+#define GL_GEOMETRY_SHADER_INVOCATIONS_OES 0x887F
+#define GL_LAYER_PROVOKING_VERTEX_OES     0x825E
+#define GL_LINES_ADJACENCY_OES            0x000A
+#define GL_LINE_STRIP_ADJACENCY_OES       0x000B
+#define GL_TRIANGLES_ADJACENCY_OES        0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_OES   0x000D
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES 0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8A32
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES 0x8DE1
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES 0x8E5A
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES 0x8C29
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES 0x92D5
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES 0x90CD
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES 0x90D7
+#define GL_FIRST_VERTEX_CONVENTION_OES    0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_OES     0x8E4E
+#define GL_UNDEFINED_VERTEX_OES           0x8260
+#define GL_PRIMITIVES_GENERATED_OES       0x8C87
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_OES 0x9312
+#define GL_MAX_FRAMEBUFFER_LAYERS_OES     0x9317
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES 0x8DA8
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES 0x8DA7
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_OES 0x9309
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREOESPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureOES (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif
+#endif /* GL_OES_geometry_shader */
+
 #ifndef GL_OES_get_program_binary
 #define GL_OES_get_program_binary 1
+#define GL_PROGRAM_BINARY_LENGTH_OES      0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES     0x87FF
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
 #ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
-GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
 #endif
-typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
-typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
-#endif
+#endif /* GL_OES_get_program_binary */
 
-/* GL_OES_mapbuffer */
+#ifndef GL_OES_gpu_shader5
+#define GL_OES_gpu_shader5 1
+#endif /* GL_OES_gpu_shader5 */
+
 #ifndef GL_OES_mapbuffer
 #define GL_OES_mapbuffer 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
-GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
-GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid** params);
-#endif
-typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+#define GL_WRITE_ONLY_OES                 0x88B9
+#define GL_BUFFER_ACCESS_OES              0x88BB
+#define GL_BUFFER_MAPPED_OES              0x88BC
+#define GL_BUFFER_MAP_POINTER_OES         0x88BD
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
 typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
-typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid** params);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void *GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void **params);
 #endif
+#endif /* GL_OES_mapbuffer */
 
-/* GL_OES_packed_depth_stencil */
 #ifndef GL_OES_packed_depth_stencil
 #define GL_OES_packed_depth_stencil 1
-#endif
+#define GL_DEPTH_STENCIL_OES              0x84F9
+#define GL_UNSIGNED_INT_24_8_OES          0x84FA
+#define GL_DEPTH24_STENCIL8_OES           0x88F0
+#endif /* GL_OES_packed_depth_stencil */
 
-/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_primitive_bounding_box
+#define GL_OES_primitive_bounding_box 1
+#define GL_PRIMITIVE_BOUNDING_BOX_OES     0x92BE
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXOESPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxOES (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#endif
+#endif /* GL_OES_primitive_bounding_box */
+
+#ifndef GL_OES_required_internalformat
+#define GL_OES_required_internalformat 1
+#define GL_ALPHA8_OES                     0x803C
+#define GL_DEPTH_COMPONENT16_OES          0x81A5
+#define GL_LUMINANCE4_ALPHA4_OES          0x8043
+#define GL_LUMINANCE8_ALPHA8_OES          0x8045
+#define GL_LUMINANCE8_OES                 0x8040
+#define GL_RGBA4_OES                      0x8056
+#define GL_RGB5_A1_OES                    0x8057
+#define GL_RGB565_OES                     0x8D62
+#define GL_RGB8_OES                       0x8051
+#define GL_RGBA8_OES                      0x8058
+#define GL_RGB10_EXT                      0x8052
+#define GL_RGB10_A2_EXT                   0x8059
+#endif /* GL_OES_required_internalformat */
+
 #ifndef GL_OES_rgb8_rgba8
 #define GL_OES_rgb8_rgba8 1
-#endif
+#endif /* GL_OES_rgb8_rgba8 */
 
-/* GL_OES_standard_derivatives */
+#ifndef GL_OES_sample_shading
+#define GL_OES_sample_shading 1
+#define GL_SAMPLE_SHADING_OES             0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE_OES   0x8C37
+typedef void (GL_APIENTRYP PFNGLMINSAMPLESHADINGOESPROC) (GLfloat value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMinSampleShadingOES (GLfloat value);
+#endif
+#endif /* GL_OES_sample_shading */
+
+#ifndef GL_OES_sample_variables
+#define GL_OES_sample_variables 1
+#endif /* GL_OES_sample_variables */
+
+#ifndef GL_OES_shader_image_atomic
+#define GL_OES_shader_image_atomic 1
+#endif /* GL_OES_shader_image_atomic */
+
+#ifndef GL_OES_shader_io_blocks
+#define GL_OES_shader_io_blocks 1
+#endif /* GL_OES_shader_io_blocks */
+
+#ifndef GL_OES_shader_multisample_interpolation
+#define GL_OES_shader_multisample_interpolation 1
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES 0x8E5D
+#endif /* GL_OES_shader_multisample_interpolation */
+
 #ifndef GL_OES_standard_derivatives
 #define GL_OES_standard_derivatives 1
-#endif
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+#endif /* GL_OES_standard_derivatives */
 
-/* GL_OES_stencil1 */
 #ifndef GL_OES_stencil1
 #define GL_OES_stencil1 1
-#endif
+#define GL_STENCIL_INDEX1_OES             0x8D46
+#endif /* GL_OES_stencil1 */
 
-/* GL_OES_stencil4 */
 #ifndef GL_OES_stencil4
 #define GL_OES_stencil4 1
-#endif
+#define GL_STENCIL_INDEX4_OES             0x8D47
+#endif /* GL_OES_stencil4 */
 
-/* GL_OES_texture_3D */
+#ifndef GL_OES_surfaceless_context
+#define GL_OES_surfaceless_context 1
+#define GL_FRAMEBUFFER_UNDEFINED_OES      0x8219
+#endif /* GL_OES_surfaceless_context */
+
+#ifndef GL_OES_tessellation_point_size
+#define GL_OES_tessellation_point_size 1
+#endif /* GL_OES_tessellation_point_size */
+
+#ifndef GL_OES_tessellation_shader
+#define GL_OES_tessellation_shader 1
+#define GL_PATCHES_OES                    0x000E
+#define GL_PATCH_VERTICES_OES             0x8E72
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_OES 0x8E75
+#define GL_TESS_GEN_MODE_OES              0x8E76
+#define GL_TESS_GEN_SPACING_OES           0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER_OES      0x8E78
+#define GL_TESS_GEN_POINT_MODE_OES        0x8E79
+#define GL_ISOLINES_OES                   0x8E7A
+#define GL_QUADS_OES                      0x0007
+#define GL_FRACTIONAL_ODD_OES             0x8E7B
+#define GL_FRACTIONAL_EVEN_OES            0x8E7C
+#define GL_MAX_PATCH_VERTICES_OES         0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL_OES         0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS_OES  0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E1F
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES 0x92CE
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES 0x92D4
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES 0x90CC
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES 0x90D9
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES 0x8221
+#define GL_IS_PER_PATCH_OES               0x92E7
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES 0x9308
+#define GL_TESS_CONTROL_SHADER_OES        0x8E88
+#define GL_TESS_EVALUATION_SHADER_OES     0x8E87
+#define GL_TESS_CONTROL_SHADER_BIT_OES    0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT_OES 0x00000010
+typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIOESPROC) (GLenum pname, GLint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPatchParameteriOES (GLenum pname, GLint value);
+#endif
+#endif /* GL_OES_tessellation_shader */
+
 #ifndef GL_OES_texture_3D
 #define GL_OES_texture_3D 1
+#define GL_TEXTURE_WRAP_R_OES             0x8072
+#define GL_TEXTURE_3D_OES                 0x806F
+#define GL_TEXTURE_BINDING_3D_OES         0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES        0x8073
+#define GL_SAMPLER_3D_OES                 0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
 #ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
-GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
 GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
-GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
 GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
 #endif
-typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
-typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
-typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
-typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
-typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
-#endif
+#endif /* GL_OES_texture_3D */
 
-/* GL_OES_texture_float */
+#ifndef GL_OES_texture_border_clamp
+#define GL_OES_texture_border_clamp 1
+#define GL_TEXTURE_BORDER_COLOR_OES       0x1004
+#define GL_CLAMP_TO_BORDER_OES            0x812D
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexParameterIivOES (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuivOES (GLenum target, GLenum pname, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIivOES (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuivOES (GLenum target, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIivOES (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuivOES (GLuint sampler, GLenum pname, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIivOES (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivOES (GLuint sampler, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_OES_texture_border_clamp */
+
+#ifndef GL_OES_texture_buffer
+#define GL_OES_texture_buffer 1
+#define GL_TEXTURE_BUFFER_OES             0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING_OES     0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_OES    0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_OES     0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES 0x919F
+#define GL_SAMPLER_BUFFER_OES             0x8DC2
+#define GL_INT_SAMPLER_BUFFER_OES         0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_OES 0x8DD8
+#define GL_IMAGE_BUFFER_OES               0x9051
+#define GL_INT_IMAGE_BUFFER_OES           0x905C
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_OES  0x9067
+#define GL_TEXTURE_BUFFER_OFFSET_OES      0x919D
+#define GL_TEXTURE_BUFFER_SIZE_OES        0x919E
+typedef void (GL_APIENTRYP PFNGLTEXBUFFEROESPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEOESPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexBufferOES (GLenum target, GLenum internalformat, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTexBufferRangeOES (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif
+#endif /* GL_OES_texture_buffer */
+
+#ifndef GL_OES_texture_compression_astc
+#define GL_OES_texture_compression_astc 1
+#define GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0
+#define GL_COMPRESSED_RGBA_ASTC_4x3x3_OES 0x93C1
+#define GL_COMPRESSED_RGBA_ASTC_4x4x3_OES 0x93C2
+#define GL_COMPRESSED_RGBA_ASTC_4x4x4_OES 0x93C3
+#define GL_COMPRESSED_RGBA_ASTC_5x4x4_OES 0x93C4
+#define GL_COMPRESSED_RGBA_ASTC_5x5x4_OES 0x93C5
+#define GL_COMPRESSED_RGBA_ASTC_5x5x5_OES 0x93C6
+#define GL_COMPRESSED_RGBA_ASTC_6x5x5_OES 0x93C7
+#define GL_COMPRESSED_RGBA_ASTC_6x6x5_OES 0x93C8
+#define GL_COMPRESSED_RGBA_ASTC_6x6x6_OES 0x93C9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES 0x93E0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES 0x93E1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES 0x93E2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES 0x93E3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES 0x93E4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES 0x93E5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES 0x93E6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES 0x93E7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES 0x93E8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9
+#endif /* GL_OES_texture_compression_astc */
+
+#ifndef GL_OES_texture_cube_map_array
+#define GL_OES_texture_cube_map_array 1
+#define GL_TEXTURE_CUBE_MAP_ARRAY_OES     0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES 0x900A
+#define GL_SAMPLER_CUBE_MAP_ARRAY_OES     0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900F
+#define GL_IMAGE_CUBE_MAP_ARRAY_OES       0x9054
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_OES   0x905F
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x906A
+#endif /* GL_OES_texture_cube_map_array */
+
 #ifndef GL_OES_texture_float
 #define GL_OES_texture_float 1
-#endif
+#endif /* GL_OES_texture_float */
 
-/* GL_OES_texture_float_linear */
 #ifndef GL_OES_texture_float_linear
 #define GL_OES_texture_float_linear 1
-#endif
+#endif /* GL_OES_texture_float_linear */
 
-/* GL_OES_texture_half_float */
 #ifndef GL_OES_texture_half_float
 #define GL_OES_texture_half_float 1
-#endif
+#define GL_HALF_FLOAT_OES                 0x8D61
+#endif /* GL_OES_texture_half_float */
 
-/* GL_OES_texture_half_float_linear */
 #ifndef GL_OES_texture_half_float_linear
 #define GL_OES_texture_half_float_linear 1
-#endif
+#endif /* GL_OES_texture_half_float_linear */
 
-/* GL_OES_texture_npot */
 #ifndef GL_OES_texture_npot
 #define GL_OES_texture_npot 1
-#endif
+#endif /* GL_OES_texture_npot */
 
-/* GL_OES_vertex_array_object */
+#ifndef GL_OES_texture_stencil8
+#define GL_OES_texture_stencil8 1
+#define GL_STENCIL_INDEX_OES              0x1901
+#define GL_STENCIL_INDEX8_OES             0x8D48
+#endif /* GL_OES_texture_stencil8 */
+
+#ifndef GL_OES_texture_storage_multisample_2d_array
+#define GL_OES_texture_storage_multisample_2d_array 1
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES 0x9102
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES 0x9105
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910D
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexStorage3DMultisampleOES (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_OES_texture_storage_multisample_2d_array */
+
+#ifndef GL_OES_texture_view
+#define GL_OES_texture_view 1
+#define GL_TEXTURE_VIEW_MIN_LEVEL_OES     0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS_OES    0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER_OES     0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS_OES    0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
+typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWOESPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTextureViewOES (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif
+#endif /* GL_OES_texture_view */
+
 #ifndef GL_OES_vertex_array_object
 #define GL_OES_vertex_array_object 1
+#define GL_VERTEX_ARRAY_BINDING_OES       0x85B5
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array);
 GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
 GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
 GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
 #endif
-typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
-typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
-typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
-typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
-#endif
+#endif /* GL_OES_vertex_array_object */
 
-/* GL_OES_vertex_half_float */
 #ifndef GL_OES_vertex_half_float
 #define GL_OES_vertex_half_float 1
-#endif
+#endif /* GL_OES_vertex_half_float */
 
-/* GL_OES_vertex_type_10_10_10_2 */
 #ifndef GL_OES_vertex_type_10_10_10_2
 #define GL_OES_vertex_type_10_10_10_2 1
+#define GL_UNSIGNED_INT_10_10_10_2_OES    0x8DF6
+#define GL_INT_10_10_10_2_OES             0x8DF7
+#endif /* GL_OES_vertex_type_10_10_10_2 */
+
+#ifndef GL_OES_viewport_array
+#define GL_OES_viewport_array 1
+#define GL_MAX_VIEWPORTS_OES              0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS_OES     0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE_OES      0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES 0x825F
+typedef void (GL_APIENTRYP PFNGLVIEWPORTARRAYVOESPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFOESPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFVOESPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORARRAYVOESPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDOESPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDVOESPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEARRAYFVOESPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEINDEXEDFOESPROC) (GLuint index, GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLGETFLOATI_VOESPROC) (GLenum target, GLuint index, GLfloat *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportArrayvOES (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glViewportIndexedfOES (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GL_APICALL void GL_APIENTRY glViewportIndexedfvOES (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glScissorArrayvOES (GLuint first, GLsizei count, const GLint *v);
+GL_APICALL void GL_APIENTRY glScissorIndexedOES (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glScissorIndexedvOES (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glDepthRangeArrayfvOES (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glDepthRangeIndexedfOES (GLuint index, GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glGetFloati_vOES (GLenum target, GLuint index, GLfloat *data);
 #endif
+#endif /* GL_OES_viewport_array */
 
-/*------------------------------------------------------------------------*
- * AMD extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_AMD_compressed_3DC_texture */
 #ifndef GL_AMD_compressed_3DC_texture
 #define GL_AMD_compressed_3DC_texture 1
-#endif
+#define GL_3DC_X_AMD                      0x87F9
+#define GL_3DC_XY_AMD                     0x87FA
+#endif /* GL_AMD_compressed_3DC_texture */
 
-/* GL_AMD_compressed_ATC_texture */
 #ifndef GL_AMD_compressed_ATC_texture
 #define GL_AMD_compressed_ATC_texture 1
-#endif
+#define GL_ATC_RGB_AMD                    0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD    0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
+#endif /* GL_AMD_compressed_ATC_texture */
 
-/* AMD_performance_monitor */
 #ifndef GL_AMD_performance_monitor
 #define GL_AMD_performance_monitor 1
+#define GL_COUNTER_TYPE_AMD               0x8BC0
+#define GL_COUNTER_RANGE_AMD              0x8BC1
+#define GL_UNSIGNED_INT64_AMD             0x8BC2
+#define GL_PERCENTAGE_AMD                 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD   0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD        0x8BC5
+#define GL_PERFMON_RESULT_AMD             0x8BC6
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
 GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
 GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
 GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
-GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data);
 GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
 GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
-GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
 GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
 GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
 GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
 #endif
-typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
-typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
-typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
-typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
-typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
-typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
-typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
-typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
-typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
-typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
-typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
-#endif
+#endif /* GL_AMD_performance_monitor */
 
-/* GL_AMD_program_binary_Z400 */
 #ifndef GL_AMD_program_binary_Z400
 #define GL_AMD_program_binary_Z400 1
-#endif
+#define GL_Z400_BINARY_AMD                0x8740
+#endif /* GL_AMD_program_binary_Z400 */
 
-/*------------------------------------------------------------------------*
- * ANGLE extension functions
- *------------------------------------------------------------------------*/
+#ifndef GL_ANDROID_extension_pack_es31a
+#define GL_ANDROID_extension_pack_es31a 1
+#endif /* GL_ANDROID_extension_pack_es31a */
 
-/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_client_arrays
+#define GL_ANGLE_client_arrays 1
+#define GL_CLIENT_ARRAYS_ANGLE 0x93AA
+#endif /* GL_ANGLE_client_arrays */
+
+#ifndef GL_ANGLE_depth_texture
+#define GL_ANGLE_depth_texture 1
+#endif /* GL_ANGLE_depth_texture */
+
 #ifndef GL_ANGLE_framebuffer_blit
 #define GL_ANGLE_framebuffer_blit 1
+#define GL_READ_FRAMEBUFFER_ANGLE         0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE         0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
 #endif
-typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-#endif
+#endif /* GL_ANGLE_framebuffer_blit */
 
-/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_request_extension
+#define GL_ANGLE_request_extension 1
+#define GL_REQUESTABLE_EXTENSIONS_ANGLE   0x93A8
+#define GL_NUM_REQUESTABLE_EXTENSIONS_ANGLE 0x93A8
+typedef GLboolean(GL_APIENTRYP PFNGLREQUESTEXTENSIONANGLEPROC) (const GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLboolean GL_APIENTRY glRequestExtensionANGLE (const GLchar *name);
+#endif
+#endif /* GL_ANGLE_webgl_compatibility */
+
+#ifndef GL_ANGLE_robust_resource_initialization
+#define GL_ANGLE_robust_resource_initialization 1
+#define GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x93A7
+#endif /* GL_ANGLE_robust_resource_initialization */
+
+#ifndef GL_CHROMIUM_framebuffer_mixed_samples
+#define GL_CHROMIUM_frambuffer_mixed_samples 1
+#define GL_COVERAGE_MODULATION_CHROMIUM 0x9332
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONCHROMIUMPROC) (GLenum components);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components);
+#endif
+#endif /* GL_CHROMIUM_framebuffer_mixed_samples */
+
+#ifndef GL_CHROMIUM_bind_generates_resource
+#define GL_CHROMIUM_bind_generates_resource 1
+#define GL_BIND_GENERATES_RESOURCE_CHROMIUM 0x9244
+#endif /* GL_CHROMIUM_bind_generates_resource */
+
+// needed by NV_path_rendering (and thus CHROMIUM_path_rendering)
+// but CHROMIUM_path_rendering only needs MatrixLoadfEXT, MatrixLoadIdentityEXT
+#ifndef GL_EXT_direct_state_access
+#define GL_EXT_direct_state_access 1
+typedef void(GL_APIENTRYP PFNGLMATRIXLOADFEXTPROC)(GLenum matrixMode, const GLfloat *m);
+typedef void(GL_APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC)(GLenum matrixMode);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMatrixLoadfEXT(GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadIdentityEXT(GLenum matrixMode);
+#endif
+#endif /* GL_EXT_direct_state_access */
+
+#ifndef GL_CHROMIUM_path_rendering
+#define GL_CHROMIUM_path_rendering 1
+#define GL_PATH_MODELVIEW_CHROMIUM 0x1700
+#define GL_PATH_PROJECTION_CHROMIUM 0x1701
+#define GL_CLOSE_PATH_CHROMIUM 0x00
+#define GL_MOVE_TO_CHROMIUM 0x02
+#define GL_LINE_TO_CHROMIUM 0x04
+#define GL_QUADRATIC_CURVE_TO_CHROMIUM 0x0A
+#define GL_CUBIC_CURVE_TO_CHROMIUM 0x0C
+#define GL_CONIC_CURVE_TO_CHROMIUM 0x1A
+#define GL_PATH_MODELVIEW_MATRIX_CHROMIUM 0x0BA6
+#define GL_PATH_PROJECTION_MATRIX_CHROMIUM 0x0BA7
+#define GL_PATH_STROKE_WIDTH_CHROMIUM 0x9075
+#define GL_PATH_END_CAPS_CHROMIUM 0x9076
+#define GL_PATH_JOIN_STYLE_CHROMIUM 0x9079
+#define GL_PATH_MITER_LIMIT_CHROMIUM 0x907a
+#define GL_PATH_STROKE_BOUND_CHROMIUM 0x9086
+#define GL_FLAT_CHROMIUM 0x1D00
+#define GL_SQUARE_CHROMIUM 0x90a3
+#define GL_ROUND_CHROMIUM 0x90a4
+#define GL_BEVEL_CHROMIUM 0x90A6
+#define GL_MITER_REVERT_CHROMIUM 0x90A7
+#define GL_COUNT_UP_CHROMIUM 0x9088
+#define GL_COUNT_DOWN_CHROMIUM 0x9089
+#define GL_CONVEX_HULL_CHROMIUM 0x908B
+#define GL_BOUNDING_BOX_CHROMIUM 0x908D
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM 0x909C
+#define GL_EYE_LINEAR_CHROMIUM 0x2400
+#define GL_OBJECT_LINEAR_CHROMIUM 0x2401
+#define GL_CONSTANT_CHROMIUM 0x8576
+#define GL_TRANSLATE_X_CHROMIUM 0x908E
+#define GL_TRANSLATE_Y_CHROMIUM 0x908F
+#define GL_TRANSLATE_2D_CHROMIUM 0x9090
+#define GL_TRANSLATE_3D_CHROMIUM 0x9091
+#define GL_AFFINE_2D_CHROMIUM 0x9092
+#define GL_AFFINE_3D_CHROMIUM 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_CHROMIUM 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_CHROMIUM 0x9098
+typedef void(GL_APIENTRYP PFNGLMATRIXLOADFCHROMIUMPROC)(GLenum matrixMode, const GLfloat *m);
+typedef void(GL_APIENTRYP PFNGLMATRIXLOADIDENTITYCHROMIUMPROC)(GLenum matrixMode);
+typedef GLuint(GL_APIENTRYP PFNGLGENPATHSCHROMIUMPROC)(GLsizei range);
+typedef void(GL_APIENTRYP PFNGLDELETEPATHSCHROMIUMPROC)(GLuint path, GLsizei range);
+typedef GLboolean(GL_APIENTRYP PFNGLISPATHCHROMIUMPROC)(GLuint path);
+typedef void(GL_APIENTRYP PFNGLPATHCOMMANDSCHROMIUMPROC)(GLuint path,
+                                                         GLsizei numCommands,
+                                                         const GLubyte *commands,
+                                                         GLsizei numCoords,
+                                                         GLenum coordType,
+                                                         const void *coords);
+typedef void(GL_APIENTRYP PFNGLPATHPARAMETERICHROMIUMPROC)(GLuint path, GLenum pname, GLint value);
+typedef void(GL_APIENTRYP PFNGLPATHPARAMETERFCHROMIUMPROC)(GLuint path,
+                                                           GLenum pname,
+                                                           GLfloat value);
+typedef void(GL_APIENTRYP PFNGLGETPATHPARAMETERIVCHROMIUMPROC)(GLuint path,
+                                                               GLenum pname,
+                                                               GLint *value);
+typedef void(GL_APIENTRYP PFNGLGETPATHPARAMETERFVCHROMIUMPROC)(GLuint path,
+                                                               GLenum pname,
+                                                               GLfloat *value);
+typedef void(GL_APIENTRYP PFNGLPATHSTENCILFUNCCHROMIUMPROC)(GLenum func, GLint ref, GLuint mask);
+typedef void(GL_APIENTRYP PFNGLSTENCILFILLPATHCHROMIUMPROC)(GLuint path,
+                                                            GLenum fillMode,
+                                                            GLuint mask);
+typedef void(GL_APIENTRYP PFNGLSTENCILSTROKEPATHCHROMIUMPROC)(GLuint path,
+                                                              GLint reference,
+                                                              GLuint mask);
+typedef void(GL_APIENTRYP PFNGLCOVERFILLPATHCHROMIUMPROC)(GLuint path, GLenum coverMode);
+typedef void(GL_APIENTRYP PFNGLCOVERSTROKEPATHCHROMIUMPROC)(GLuint path, GLenum coverMode);
+typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMPROC)(GLuint path,
+                                                                     GLenum fillMode,
+                                                                     GLuint mask,
+                                                                     GLenum coverMode);
+typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMPROC)(GLuint path,
+                                                                       GLint reference,
+                                                                       GLuint mask,
+                                                                       GLenum coverMode);
+typedef void(GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDCHROMIUMPROC)(GLsizei numPaths,
+                                                                   GLenum pathNameType,
+                                                                   const void *paths,
+                                                                   GLuint pathBase,
+                                                                   GLenum coverMode,
+                                                                   GLenum transformType,
+                                                                   const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMPROC)(
+    GLsizei numPaths,
+    GLenum pathNameType,
+    const void *paths,
+    GLuint pathBase,
+    GLenum coverMode,
+    GLenum transformType,
+    const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMPROC)(
+    GLsizei numPaths,
+    GLenum pathNameType,
+    const void *paths,
+    GLuint pathBase,
+    GLenum fillMode,
+    GLuint mask,
+    GLenum transformType,
+    const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMPROC)(
+    GLsizei numPaths,
+    GLenum pathNameType,
+    const void *paths,
+    GLuint pathBase,
+    GLint reference,
+    GLuint mask,
+    GLenum transformType,
+    const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMPROC)(
+    GLsizei numPaths,
+    GLenum pathNameType,
+    const void *paths,
+    GLuint pathBase,
+    GLenum fillMode,
+    GLuint mask,
+    GLenum coverMode,
+    GLenum transformType,
+    const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMPROC)(
+    GLsizei numPaths,
+    GLenum pathNameType,
+    const void *paths,
+    GLuint pathBase,
+    GLint reference,
+    GLuint mask,
+    GLenum coverMode,
+    GLenum transformType,
+    const GLfloat *transformValues);
+
+typedef void(GL_APIENTRY PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMPROC)(GLuint program,
+                                                                     GLint location,
+                                                                     const GLchar *name);
+typedef void(GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMPROC)(GLuint program,
+                                                                        GLint location,
+                                                                        GLenum genMode,
+                                                                        GLint components,
+                                                                        const GLfloat *coeffs);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadIdentityCHROMIUM(GLenum matrixMode);
+GL_APICALL GLuint GL_APIENTRY glGenPathsCHROMIUM(GLsizei range);
+GL_APICALL void GL_APIENTRY glDeletePathsCHROMIUM(GLuint path, GLsizei range);
+GL_APICALL GLboolean GL_APIENTRY glIsPathCHROMIUM(GLuint path);
+GL_APICALL void GL_APIENTRY glPathCommandsCHROMIUM(GLuint path,
+                                                   GLsizei numCommands,
+                                                   const GLubyte *commands,
+                                                   GLsizei numCoords,
+                                                   GLenum coordType,
+                                                   const void *coords);
+GL_APICALL void GL_APIENTRY glPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
+GL_APICALL void GL_APIENTRY glGetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value);
+GL_APICALL void GL_APIENTRY glGetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
+GL_APICALL void GL_APIENTRY glPathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
+GL_APICALL void GL_APIENTRY glCoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathCHROMIUM(GLuint path,
+                                                               GLenum fillMode,
+                                                               GLuint mask,
+                                                               GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUM(GLuint path,
+                                                                 GLint reference,
+                                                                 GLuint mask,
+                                                                 GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                             GLenum pathNameType,
+                                                             const void *paths,
+                                                             GLuint pathBase,
+                                                             GLenum coverMode,
+                                                             GLenum transformType,
+                                                             const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                               GLenum pathNameType,
+                                                               const void *paths,
+                                                               GLuint pathBase,
+                                                               GLenum coverMode,
+                                                               GLenum transformType,
+                                                               const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                               GLenum pathNameType,
+                                                               const void *paths,
+                                                               GLuint pathBase,
+                                                               GLenum fillMode,
+                                                               GLuint mask,
+                                                               GLenum transformType,
+                                                               const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                                 GLenum pathNameType,
+                                                                 const void *paths,
+                                                                 GLuint pathBase,
+                                                                 GLint reference,
+                                                                 GLuint mask,
+                                                                 GLenum transformType,
+                                                                 const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY
+glStencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                            GLenum pathNameType,
+                                            const void *paths,
+                                            GLuint pathBase,
+                                            GLenum fillMode,
+                                            GLuint mask,
+                                            GLenum coverMode,
+                                            GLenum transformType,
+                                            const GLfloat *transformValues);
+
+GL_APICALL void GL_APIENTRY
+glStencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                              GLenum pathNameType,
+                                              const void *paths,
+                                              GLuint pathBase,
+                                              GLint reference,
+                                              GLuint mask,
+                                              GLenum coverMode,
+                                              GLenum transformType,
+                                              const GLfloat *transformValues);
+
+GL_APICALL void GL_APIENTRY glBindFragmentInputLocationCHROMIUM(GLuint program,
+                                                                GLint location,
+                                                                const GLchar *name);
+GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenCHROMIUM(GLuint program,
+                                                                  GLint location,
+                                                                  GLenum genMode,
+                                                                  GLint components,
+                                                                  const GLfloat *coeffs);
+
+#endif
+#endif /* GL_CHROMIUM_path_rendering */
+
 #ifndef GL_ANGLE_framebuffer_multisample
 #define GL_ANGLE_framebuffer_multisample 1
+#define GL_RENDERBUFFER_SAMPLES_ANGLE     0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
+#define GL_MAX_SAMPLES_ANGLE              0x8D57
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 #endif
-typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-#endif
+#endif /* GL_ANGLE_framebuffer_multisample */
 
-/* GL_ANGLE_pack_reverse_row_order */
-#ifndef GL_ANGLE_pack_reverse_row_order
-#define GL_ANGLE_pack_reverse_row_order 1
-#endif
-
-/* GL_ANGLE_texture_compression_dxt3 */
-#ifndef GL_ANGLE_texture_compression_dxt3
-#define GL_ANGLE_texture_compression_dxt3 1
-#endif
-
-/* GL_ANGLE_texture_compression_dxt5 */
-#ifndef GL_ANGLE_texture_compression_dxt5
-#define GL_ANGLE_texture_compression_dxt5 1
-#endif
-
-/* GL_ANGLE_translated_shader_source */
-#ifndef GL_ANGLE_translated_shader_source
-#define GL_ANGLE_translated_shader_source 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
-#endif
-typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
-#endif
-
-/* GL_ANGLE_texture_usage */
-#ifndef GL_ANGLE_texture_usage
-#define GL_ANGLE_texture_usage 1
-#endif
-
-/* GL_ANGLE_instanced_arrays */
 #ifndef GL_ANGLE_instanced_arrays
 #define GL_ANGLE_instanced_arrays 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor);
-GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
-#endif
-typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
 typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor);
 #endif
+#endif /* GL_ANGLE_instanced_arrays */
 
-/*------------------------------------------------------------------------*
- * APPLE extension functions
- *------------------------------------------------------------------------*/
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_ANGLE_pack_reverse_row_order 1
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE   0x93A4
+#endif /* GL_ANGLE_pack_reverse_row_order */
 
-/* GL_APPLE_rgb_422 */
-#ifndef GL_APPLE_rgb_422
-#define GL_APPLE_rgb_422 1
+#ifndef GL_ANGLE_program_binary
+#define GL_ANGLE_program_binary 1
+#define GL_PROGRAM_BINARY_ANGLE           0x93A6
+#endif /* GL_ANGLE_program_binary */
+
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_ANGLE_texture_compression_dxt3 1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#endif /* GL_ANGLE_texture_compression_dxt3 */
+
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_ANGLE_texture_compression_dxt5 1
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+#endif /* GL_ANGLE_texture_compression_dxt5 */
+
+#ifndef GL_ANGLE_texture_usage
+#define GL_ANGLE_texture_usage 1
+#define GL_TEXTURE_USAGE_ANGLE            0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE   0x93A3
+#endif /* GL_ANGLE_texture_usage */
+
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_ANGLE_translated_shader_source 1
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
+typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
 #endif
+#endif /* GL_ANGLE_translated_shader_source */
 
-/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_clip_distance
+#define GL_APPLE_clip_distance 1
+#define GL_MAX_CLIP_DISTANCES_APPLE       0x0D32
+#define GL_CLIP_DISTANCE0_APPLE           0x3000
+#define GL_CLIP_DISTANCE1_APPLE           0x3001
+#define GL_CLIP_DISTANCE2_APPLE           0x3002
+#define GL_CLIP_DISTANCE3_APPLE           0x3003
+#define GL_CLIP_DISTANCE4_APPLE           0x3004
+#define GL_CLIP_DISTANCE5_APPLE           0x3005
+#define GL_CLIP_DISTANCE6_APPLE           0x3006
+#define GL_CLIP_DISTANCE7_APPLE           0x3007
+#endif /* GL_APPLE_clip_distance */
+
+#ifndef GL_APPLE_color_buffer_packed_float
+#define GL_APPLE_color_buffer_packed_float 1
+#endif /* GL_APPLE_color_buffer_packed_float */
+
+#ifndef GL_APPLE_copy_texture_levels
+#define GL_APPLE_copy_texture_levels 1
+typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+#endif /* GL_APPLE_copy_texture_levels */
+
 #ifndef GL_APPLE_framebuffer_multisample
 #define GL_APPLE_framebuffer_multisample 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
-GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
-#endif /* GL_GLEXT_PROTOTYPES */
+#define GL_RENDERBUFFER_SAMPLES_APPLE     0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
+#define GL_MAX_SAMPLES_APPLE              0x8D57
+#define GL_READ_FRAMEBUFFER_APPLE         0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE         0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA
 typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
 #endif
+#endif /* GL_APPLE_framebuffer_multisample */
 
-/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#define GL_RGB_422_APPLE                  0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE       0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE   0x85BB
+#define GL_RGB_RAW_422_APPLE              0x8A51
+#endif /* GL_APPLE_rgb_422 */
+
+#ifndef GL_APPLE_sync
+#define GL_APPLE_sync 1
+#define GL_SYNC_OBJECT_APPLE              0x8A53
+#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE  0x9111
+#define GL_OBJECT_TYPE_APPLE              0x9112
+#define GL_SYNC_CONDITION_APPLE           0x9113
+#define GL_SYNC_STATUS_APPLE              0x9114
+#define GL_SYNC_FLAGS_APPLE               0x9115
+#define GL_SYNC_FENCE_APPLE               0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117
+#define GL_UNSIGNALED_APPLE               0x9118
+#define GL_SIGNALED_APPLE                 0x9119
+#define GL_ALREADY_SIGNALED_APPLE         0x911A
+#define GL_TIMEOUT_EXPIRED_APPLE          0x911B
+#define GL_CONDITION_SATISFIED_APPLE      0x911C
+#define GL_WAIT_FAILED_APPLE              0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE  0x00000001
+#define GL_TIMEOUT_IGNORED_APPLE          0xFFFFFFFFFFFFFFFFull
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+#endif /* GL_APPLE_sync */
+
 #ifndef GL_APPLE_texture_format_BGRA8888
 #define GL_APPLE_texture_format_BGRA8888 1
-#endif
+#define GL_BGRA_EXT                       0x80E1
+#define GL_BGRA8_EXT                      0x93A1
+#endif /* GL_APPLE_texture_format_BGRA8888 */
 
-/* GL_APPLE_texture_max_level */
 #ifndef GL_APPLE_texture_max_level
 #define GL_APPLE_texture_max_level 1
-#endif
+#define GL_TEXTURE_MAX_LEVEL_APPLE        0x813D
+#endif /* GL_APPLE_texture_max_level */
 
-/*------------------------------------------------------------------------*
- * ARM extension functions
- *------------------------------------------------------------------------*/
+#ifndef GL_APPLE_texture_packed_float
+#define GL_APPLE_texture_packed_float 1
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE 0x8C3B
+#define GL_UNSIGNED_INT_5_9_9_9_REV_APPLE 0x8C3E
+#define GL_R11F_G11F_B10F_APPLE           0x8C3A
+#define GL_RGB9_E5_APPLE                  0x8C3D
+#endif /* GL_APPLE_texture_packed_float */
 
-/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_program_binary
+#define GL_ARM_mali_program_binary 1
+#define GL_MALI_PROGRAM_BINARY_ARM        0x8F61
+#endif /* GL_ARM_mali_program_binary */
+
 #ifndef GL_ARM_mali_shader_binary
 #define GL_ARM_mali_shader_binary 1
-#endif
+#define GL_MALI_SHADER_BINARY_ARM         0x8F60
+#endif /* GL_ARM_mali_shader_binary */
 
-/* GL_ARM_rgba8 */
 #ifndef GL_ARM_rgba8
 #define GL_ARM_rgba8 1
+#endif /* GL_ARM_rgba8 */
+
+#ifndef GL_ARM_shader_framebuffer_fetch
+#define GL_ARM_shader_framebuffer_fetch 1
+#define GL_FETCH_PER_SAMPLE_ARM           0x8F65
+#define GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM 0x8F66
+#endif /* GL_ARM_shader_framebuffer_fetch */
+
+#ifndef GL_ARM_shader_framebuffer_fetch_depth_stencil
+#define GL_ARM_shader_framebuffer_fetch_depth_stencil 1
+#endif /* GL_ARM_shader_framebuffer_fetch_depth_stencil */
+
+#ifndef GL_CHROMIUM_copy_texture
+#define GL_CHROMIUM_copy_texture 1
+typedef void(GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUMPROC)(GLuint sourceId,
+                                                        GLint sourceLevel,
+                                                        GLenum destTarget,
+                                                        GLuint destId,
+                                                        GLint destLevel,
+                                                        GLint internalFormat,
+                                                        GLenum destType,
+                                                        GLboolean unpackFlipY,
+                                                        GLboolean unpackPremultiplyAlpha,
+                                                        GLboolean unpackUnmultiplyAlpha);
+typedef void(GL_APIENTRYP PFNGLCOPYSUBTEXTURECHROMIUMPROC)(GLuint sourceId,
+                                                           GLint sourceLevel,
+                                                           GLenum destTarget,
+                                                           GLuint destId,
+                                                           GLint destLevel,
+                                                           GLint xoffset,
+                                                           GLint yoffset,
+                                                           GLint x,
+                                                           GLint y,
+                                                           GLsizei width,
+                                                           GLsizei height,
+                                                           GLboolean unpackFlipY,
+                                                           GLboolean unpackPremultiplyAlpha,
+                                                           GLboolean unpackUnmultiplyAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM(GLuint sourceId,
+                                                  GLint sourceLevel,
+                                                  GLenum destTarget,
+                                                  GLuint destId,
+                                                  GLint destLevel,
+                                                  GLint internalFormat,
+                                                  GLenum destType,
+                                                  GLboolean unpackFlipY,
+                                                  GLboolean unpackPremultiplyAlpha,
+                                                  GLboolean unpackUnmultiplyAlpha);
+GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM(GLuint sourceId,
+                                                     GLint sourceLevel,
+                                                     GLenum destTarget,
+                                                     GLuint destId,
+                                                     GLint destLevel,
+                                                     GLint xoffset,
+                                                     GLint yoffset,
+                                                     GLint x,
+                                                     GLint y,
+                                                     GLsizei width,
+                                                     GLsizei height,
+                                                     GLboolean unpackFlipY,
+                                                     GLboolean unpackPremultiplyAlpha,
+                                                     GLboolean unpackUnmultiplyAlpha);
 #endif
+#endif /* GL_CHROMIUM_copy_texture */
 
-/*------------------------------------------------------------------------*
- * EXT extension functions
- *------------------------------------------------------------------------*/
+#ifndef GL_CHROMIUM_compressed_copy_texture
+#define GL_CHROMIUM_compressed_copy_texture 1
+typedef void(GL_APIENTRYP PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC)(GLuint sourceId, GLuint destId);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
+#endif
+#endif /* GL_CHROMIUM_compressed_copy_texture */
 
-/* GL_EXT_blend_minmax */
+#ifndef GL_CHROMIUM_sync_query
+#define GL_CHROMIUM_sync_query 1
+#define GL_COMMANDS_COMPLETED_CHROMIUM    0x84F7
+#endif  /* GL_CHROMIUM_sync_query */
+
+#ifndef GL_DMP_program_binary
+#define GL_DMP_program_binary 1
+#define GL_SMAPHS30_PROGRAM_BINARY_DMP    0x9251
+#define GL_SMAPHS_PROGRAM_BINARY_DMP      0x9252
+#define GL_DMP_PROGRAM_BINARY_DMP         0x9253
+#endif /* GL_DMP_program_binary */
+
+#ifndef GL_DMP_shader_binary
+#define GL_DMP_shader_binary 1
+#define GL_SHADER_BINARY_DMP              0x9250
+#endif /* GL_DMP_shader_binary */
+
+#ifndef GL_EXT_YUV_target
+#define GL_EXT_YUV_target 1
+#define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT    0x8BE7
+#endif /* GL_EXT_YUV_target */
+
+#ifndef GL_EXT_base_instance
+#define GL_EXT_base_instance 1
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedBaseInstanceEXT (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#endif
+#endif /* GL_EXT_base_instance */
+
+#ifndef GL_EXT_blend_func_extended
+#define GL_EXT_blend_func_extended 1
+#define GL_SRC1_COLOR_EXT                 0x88F9
+#define GL_SRC1_ALPHA_EXT                 0x8589
+#define GL_ONE_MINUS_SRC1_COLOR_EXT       0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA_EXT       0x88FB
+#define GL_SRC_ALPHA_SATURATE_EXT         0x0308
+#define GL_LOCATION_INDEX_EXT             0x930F
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT 0x88FC
+typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATAINDEXEXTPROC) (GLuint program, const GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindFragDataLocationIndexedEXT (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocationIndexEXT (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL GLint GL_APIENTRY glGetFragDataIndexEXT (GLuint program, const GLchar *name);
+#endif
+#endif /* GL_EXT_blend_func_extended */
+
 #ifndef GL_EXT_blend_minmax
 #define GL_EXT_blend_minmax 1
-#endif
+#define GL_MIN_EXT                        0x8007
+#define GL_MAX_EXT                        0x8008
+#endif /* GL_EXT_blend_minmax */
 
-/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_buffer_storage
+#define GL_EXT_buffer_storage 1
+#define GL_MAP_READ_BIT                   0x0001
+#define GL_MAP_WRITE_BIT                  0x0002
+#define GL_MAP_PERSISTENT_BIT_EXT         0x0040
+#define GL_MAP_COHERENT_BIT_EXT           0x0080
+#define GL_DYNAMIC_STORAGE_BIT_EXT        0x0100
+#define GL_CLIENT_STORAGE_BIT_EXT         0x0200
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
+#define GL_BUFFER_IMMUTABLE_STORAGE_EXT   0x821F
+#define GL_BUFFER_STORAGE_FLAGS_EXT       0x8220
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBufferStorageEXT (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+#endif
+#endif /* GL_EXT_buffer_storage */
+
+#ifndef GL_EXT_clear_texture
+#define GL_EXT_clear_texture 1
+typedef void (GL_APIENTRYP PFNGLCLEARTEXIMAGEEXTPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+typedef void (GL_APIENTRYP PFNGLCLEARTEXSUBIMAGEEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glClearTexImageEXT (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+GL_APICALL void GL_APIENTRY glClearTexSubImageEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+#endif
+#endif /* GL_EXT_clear_texture */
+
+#ifndef GL_EXT_clip_cull_distance
+#define GL_EXT_clip_cull_distance 1
+#define GL_MAX_CLIP_DISTANCES_EXT         0x0D32
+#define GL_MAX_CULL_DISTANCES_EXT         0x82F9
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
+#define GL_CLIP_DISTANCE0_EXT             0x3000
+#define GL_CLIP_DISTANCE1_EXT             0x3001
+#define GL_CLIP_DISTANCE2_EXT             0x3002
+#define GL_CLIP_DISTANCE3_EXT             0x3003
+#define GL_CLIP_DISTANCE4_EXT             0x3004
+#define GL_CLIP_DISTANCE5_EXT             0x3005
+#define GL_CLIP_DISTANCE6_EXT             0x3006
+#define GL_CLIP_DISTANCE7_EXT             0x3007
+#endif /* GL_EXT_clip_cull_distance */
+
+#ifndef GL_EXT_color_buffer_float
+#define GL_EXT_color_buffer_float 1
+#endif /* GL_EXT_color_buffer_float */
+
 #ifndef GL_EXT_color_buffer_half_float
 #define GL_EXT_color_buffer_half_float 1
-#endif
+#define GL_RGBA16F_EXT                    0x881A
+#define GL_RGB16F_EXT                     0x881B
+#define GL_RG16F_EXT                      0x822F
+#define GL_R16F_EXT                       0x822D
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define GL_UNSIGNED_NORMALIZED_EXT        0x8C17
+#endif /* GL_EXT_color_buffer_half_float */
 
-/* GL_EXT_debug_label */
+#ifndef GL_EXT_conservative_depth
+#define GL_EXT_conservative_depth 1
+#endif /* GL_EXT_conservative_depth */
+
+#ifndef GL_EXT_copy_image
+#define GL_EXT_copy_image 1
+typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAEXTPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyImageSubDataEXT (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#endif
+#endif /* GL_EXT_copy_image */
+
 #ifndef GL_EXT_debug_label
 #define GL_EXT_debug_label 1
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT    0x8A4F
+#define GL_PROGRAM_OBJECT_EXT             0x8B40
+#define GL_SHADER_OBJECT_EXT              0x8B48
+#define GL_BUFFER_OBJECT_EXT              0x9151
+#define GL_QUERY_OBJECT_EXT               0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT        0x9154
+#define GL_TRANSFORM_FEEDBACK             0x8E22
+typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
 GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
 #endif
-typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
-typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
-#endif
+#endif /* GL_EXT_debug_label */
 
-/* GL_EXT_debug_marker */
 #ifndef GL_EXT_debug_marker
 #define GL_EXT_debug_marker 1
+typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
 GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
 GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void);
 #endif
-typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
-typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
-typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
-#endif
+#endif /* GL_EXT_debug_marker */
 
-/* GL_EXT_discard_framebuffer */
 #ifndef GL_EXT_discard_framebuffer
 #define GL_EXT_discard_framebuffer 1
+#define GL_COLOR_EXT                      0x1800
+#define GL_DEPTH_EXT                      0x1801
+#define GL_STENCIL_EXT                    0x1802
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
 #endif
-typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
-#endif
+#endif /* GL_EXT_discard_framebuffer */
 
-/* GL_EXT_multisampled_render_to_texture */
-#ifndef GL_EXT_multisampled_render_to_texture
-#define GL_EXT_multisampled_render_to_texture 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
-GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
-#endif
-typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
-#endif
-
-#ifndef GL_EXT_multi_draw_arrays
-#define GL_EXT_multi_draw_arrays 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei);
-GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
-#endif /* GL_GLEXT_PROTOTYPES */
-typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
-typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
-#endif
-
-/* GL_EXT_occlusion_query_boolean */
-#ifndef GL_EXT_occlusion_query_boolean
-#define GL_EXT_occlusion_query_boolean 1
+#ifndef GL_EXT_disjoint_timer_query
+#define GL_EXT_disjoint_timer_query 1
+#define GL_QUERY_COUNTER_BITS_EXT         0x8864
+#define GL_CURRENT_QUERY_EXT              0x8865
+#define GL_QUERY_RESULT_EXT               0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT     0x8867
+#define GL_TIME_ELAPSED_EXT               0x88BF
+#define GL_TIMESTAMP_EXT                  0x8E28
+#define GL_GPU_DISJOINT_EXT               0x8FBB
+typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLQUERYCOUNTEREXTPROC) (GLuint id, GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVEXTPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids);
 GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids);
 GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id);
 GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id);
 GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target);
+GL_APICALL void GL_APIENTRY glQueryCounterEXT (GLuint id, GLenum target);
 GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectivEXT (GLuint id, GLenum pname, GLint *params);
 GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params);
 #endif
-typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids);
-typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids);
-typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id);
-typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
-typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target);
-typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
-typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params);
-#endif
+#endif /* GL_EXT_disjoint_timer_query */
 
-/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_draw_buffers
+#define GL_EXT_draw_buffers 1
+#define GL_MAX_COLOR_ATTACHMENTS_EXT      0x8CDF
+#define GL_MAX_DRAW_BUFFERS_EXT           0x8824
+#define GL_DRAW_BUFFER0_EXT               0x8825
+#define GL_DRAW_BUFFER1_EXT               0x8826
+#define GL_DRAW_BUFFER2_EXT               0x8827
+#define GL_DRAW_BUFFER3_EXT               0x8828
+#define GL_DRAW_BUFFER4_EXT               0x8829
+#define GL_DRAW_BUFFER5_EXT               0x882A
+#define GL_DRAW_BUFFER6_EXT               0x882B
+#define GL_DRAW_BUFFER7_EXT               0x882C
+#define GL_DRAW_BUFFER8_EXT               0x882D
+#define GL_DRAW_BUFFER9_EXT               0x882E
+#define GL_DRAW_BUFFER10_EXT              0x882F
+#define GL_DRAW_BUFFER11_EXT              0x8830
+#define GL_DRAW_BUFFER12_EXT              0x8831
+#define GL_DRAW_BUFFER13_EXT              0x8832
+#define GL_DRAW_BUFFER14_EXT              0x8833
+#define GL_DRAW_BUFFER15_EXT              0x8834
+#define GL_COLOR_ATTACHMENT0_EXT          0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT          0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT          0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT          0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT          0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT          0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT          0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT          0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT          0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT          0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT         0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT         0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT         0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT         0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT         0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT         0x8CEF
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs);
+#endif
+#endif /* GL_EXT_draw_buffers */
+
+#ifndef GL_EXT_draw_buffers_indexed
+#define GL_EXT_draw_buffers_indexed 1
+typedef void (GL_APIENTRYP PFNGLENABLEIEXTPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEIEXTPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIEXTPROC) (GLuint buf, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIEXTPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCIEXTPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIEXTPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKIEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIEXTPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEnableiEXT (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiEXT (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glBlendEquationiEXT (GLuint buf, GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparateiEXT (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunciEXT (GLuint buf, GLenum src, GLenum dst);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparateiEXT (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glColorMaskiEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediEXT (GLenum target, GLuint index);
+#endif
+#endif /* GL_EXT_draw_buffers_indexed */
+
+#ifndef GL_EXT_draw_elements_base_vertex
+#define GL_EXT_draw_elements_base_vertex 1
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#endif
+#endif /* GL_EXT_draw_elements_base_vertex */
+
+#ifndef GL_EXT_draw_instanced
+#define GL_EXT_draw_instanced 1
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_draw_instanced */
+
+#ifndef GL_EXT_draw_transform_feedback
+#define GL_EXT_draw_transform_feedback 1
+typedef void (GL_APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKEXTPROC) (GLenum mode, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC) (GLenum mode, GLuint id, GLsizei instancecount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawTransformFeedbackEXT (GLenum mode, GLuint id);
+GL_APICALL void GL_APIENTRY glDrawTransformFeedbackInstancedEXT (GLenum mode, GLuint id, GLsizei instancecount);
+#endif
+#endif /* GL_EXT_draw_transform_feedback */
+
+#ifndef GL_EXT_float_blend
+#define GL_EXT_float_blend 1
+#endif /* GL_EXT_float_blend */
+
+#ifndef GL_EXT_geometry_point_size
+#define GL_EXT_geometry_point_size 1
+#endif /* GL_EXT_geometry_point_size */
+
+#ifndef GL_EXT_geometry_shader
+#define GL_EXT_geometry_shader 1
+#define GL_GEOMETRY_SHADER_EXT            0x8DD9
+#define GL_GEOMETRY_SHADER_BIT_EXT        0x00000004
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_EXT 0x8916
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_EXT 0x8917
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT 0x8918
+#define GL_GEOMETRY_SHADER_INVOCATIONS_EXT 0x887F
+#define GL_LAYER_PROVOKING_VERTEX_EXT     0x825E
+#define GL_LINES_ADJACENCY_EXT            0x000A
+#define GL_LINE_STRIP_ADJACENCY_EXT       0x000B
+#define GL_TRIANGLES_ADJACENCY_EXT        0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT   0x000D
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8A32
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT 0x8E5A
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT 0x92D5
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT 0x90CD
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT 0x90D7
+#define GL_FIRST_VERTEX_CONVENTION_EXT    0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_EXT     0x8E4E
+#define GL_UNDEFINED_VERTEX_EXT           0x8260
+#define GL_PRIMITIVES_GENERATED_EXT       0x8C87
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT 0x9312
+#define GL_MAX_FRAMEBUFFER_LAYERS_EXT     0x9317
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_EXT 0x9309
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif
+#endif /* GL_EXT_geometry_shader */
+
+#ifndef GL_EXT_gpu_shader5
+#define GL_EXT_gpu_shader5 1
+#endif /* GL_EXT_gpu_shader5 */
+
+#ifndef GL_EXT_instanced_arrays
+#define GL_EXT_instanced_arrays 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 0x88FE
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorEXT (GLuint index, GLuint divisor);
+#endif
+#endif /* GL_EXT_instanced_arrays */
+
+#ifndef GL_EXT_map_buffer_range
+#define GL_EXT_map_buffer_range 1
+#define GL_MAP_READ_BIT_EXT               0x0001
+#define GL_MAP_WRITE_BIT_EXT              0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT   0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT  0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT     0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT     0x0020
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void *GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+#endif /* GL_EXT_map_buffer_range */
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_multi_draw_arrays */
+
+#ifndef GL_EXT_multi_draw_indirect
+#define GL_EXT_multi_draw_indirect 1
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysIndirectEXT (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsIndirectEXT (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#endif
+#endif /* GL_EXT_multi_draw_indirect */
+
+#ifndef GL_EXT_multisampled_compatibility
+#define GL_EXT_multisampled_compatibility 1
+#define GL_MULTISAMPLE_EXT                0x809D
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT        0x809F
+#endif /* GL_EXT_multisampled_compatibility */
+
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_EXT_multisampled_render_to_texture 1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+#define GL_RENDERBUFFER_SAMPLES_EXT       0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT                0x8D57
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+#endif /* GL_EXT_multisampled_render_to_texture */
+
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_EXT_multiview_draw_buffers 1
+#define GL_COLOR_ATTACHMENT_EXT           0x90F0
+#define GL_MULTIVIEW_EXT                  0x90F1
+#define GL_DRAW_BUFFER_EXT                0x0C01
+#define GL_READ_BUFFER_EXT                0x0C02
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT      0x90F2
+typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index);
+GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices);
+GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data);
+#endif
+#endif /* GL_EXT_multiview_draw_buffers */
+
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_EXT_occlusion_query_boolean 1
+#define GL_ANY_SAMPLES_PASSED_EXT         0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+#endif /* GL_EXT_occlusion_query_boolean */
+
+#ifndef GL_EXT_polygon_offset_clamp
+#define GL_EXT_polygon_offset_clamp 1
+#define GL_POLYGON_OFFSET_CLAMP_EXT       0x8E1B
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETCLAMPEXTPROC) (GLfloat factor, GLfloat units, GLfloat clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPolygonOffsetClampEXT (GLfloat factor, GLfloat units, GLfloat clamp);
+#endif
+#endif /* GL_EXT_polygon_offset_clamp */
+
+#ifndef GL_EXT_post_depth_coverage
+#define GL_EXT_post_depth_coverage 1
+#endif /* GL_EXT_post_depth_coverage */
+
+#ifndef GL_EXT_primitive_bounding_box
+#define GL_EXT_primitive_bounding_box 1
+#define GL_PRIMITIVE_BOUNDING_BOX_EXT     0x92BE
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXEXTPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxEXT (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#endif
+#endif /* GL_EXT_primitive_bounding_box */
+
+#ifndef GL_EXT_protected_textures
+#define GL_EXT_protected_textures 1
+#define GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT 0x00000010
+#define GL_TEXTURE_PROTECTED_EXT          0x8BFA
+#endif /* GL_EXT_protected_textures */
+
+#ifndef GL_EXT_pvrtc_sRGB
+#define GL_EXT_pvrtc_sRGB 1
+#define GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
+#define GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG 0x93F0
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG 0x93F1
+#endif /* GL_EXT_pvrtc_sRGB */
+
+#ifndef GL_EXT_raster_multisample
+#define GL_EXT_raster_multisample 1
+#define GL_RASTER_MULTISAMPLE_EXT         0x9327
+#define GL_RASTER_SAMPLES_EXT             0x9328
+#define GL_MAX_RASTER_SAMPLES_EXT         0x9329
+#define GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A
+#define GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B
+#define GL_EFFECTIVE_RASTER_SAMPLES_EXT   0x932C
+typedef void (GL_APIENTRYP PFNGLRASTERSAMPLESEXTPROC) (GLuint samples, GLboolean fixedsamplelocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRasterSamplesEXT (GLuint samples, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_EXT_raster_multisample */
+
 #ifndef GL_EXT_read_format_bgra
 #define GL_EXT_read_format_bgra 1
-#endif
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#endif /* GL_EXT_read_format_bgra */
 
-/* GL_EXT_robustness */
+#ifndef GL_EXT_render_snorm
+#define GL_EXT_render_snorm 1
+#define GL_R8_SNORM                       0x8F94
+#define GL_RG8_SNORM                      0x8F95
+#define GL_RGBA8_SNORM                    0x8F97
+#define GL_R16_SNORM_EXT                  0x8F98
+#define GL_RG16_SNORM_EXT                 0x8F99
+#define GL_RGBA16_SNORM_EXT               0x8F9B
+#endif /* GL_EXT_render_snorm */
+
 #ifndef GL_EXT_robustness
 #define GL_EXT_robustness 1
+#define GL_GUILTY_CONTEXT_RESET_EXT       0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT     0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT      0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT      0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT      0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT      0x8261
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
 GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
-GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, float *params);
+GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
 GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
 #endif
-typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
-typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
-typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, float *params);
-typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
-#endif
+#endif /* GL_EXT_robustness */
 
-/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_sRGB
+#define GL_EXT_sRGB 1
+#define GL_SRGB_EXT                       0x8C40
+#define GL_SRGB_ALPHA_EXT                 0x8C42
+#define GL_SRGB8_ALPHA8_EXT               0x8C43
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#endif /* GL_EXT_sRGB */
+
+#ifndef GL_EXT_sRGB_write_control
+#define GL_EXT_sRGB_write_control 1
+#define GL_FRAMEBUFFER_SRGB_EXT           0x8DB9
+#endif /* GL_EXT_sRGB_write_control */
+
 #ifndef GL_EXT_separate_shader_objects
 #define GL_EXT_separate_shader_objects 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program);
-GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program);
-GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings);
-GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline);
-GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines);
-GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines);
-GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline);
-GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
-GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params);
-GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x);
-GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y);
-GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z);
-GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
-GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x);
-GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y);
-GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
-GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
-GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
-GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
-GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
-GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
-GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
-GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
-GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
-GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline);
-GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
-#endif
-typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+#define GL_ACTIVE_PROGRAM_EXT             0x8259
+#define GL_VERTEX_SHADER_BIT_EXT          0x00000001
+#define GL_FRAGMENT_SHADER_BIT_EXT        0x00000002
+#define GL_ALL_SHADER_BITS_EXT            0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE_EXT          0x8258
+#define GL_PROGRAM_PIPELINE_BINDING_EXT   0x825A
 typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program);
-typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings);
 typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings);
 typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines);
 typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params);
 typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
 typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
-typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
-typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0);
 typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
 typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
 typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
 typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
 typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
 typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
-typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program);
+GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 #endif
+#endif /* GL_EXT_separate_shader_objects */
 
-/* GL_EXT_shader_texture_lod */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_EXT_shader_framebuffer_fetch 1
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+#endif /* GL_EXT_shader_framebuffer_fetch */
+
+#ifndef GL_EXT_shader_group_vote
+#define GL_EXT_shader_group_vote 1
+#endif /* GL_EXT_shader_group_vote */
+
+#ifndef GL_EXT_shader_implicit_conversions
+#define GL_EXT_shader_implicit_conversions 1
+#endif /* GL_EXT_shader_implicit_conversions */
+
+#ifndef GL_EXT_shader_integer_mix
+#define GL_EXT_shader_integer_mix 1
+#endif /* GL_EXT_shader_integer_mix */
+
+#ifndef GL_EXT_shader_io_blocks
+#define GL_EXT_shader_io_blocks 1
+#endif /* GL_EXT_shader_io_blocks */
+
+#ifndef GL_EXT_shader_non_constant_global_initializers
+#define GL_EXT_shader_non_constant_global_initializers 1
+#endif /* GL_EXT_shader_non_constant_global_initializers */
+
+#ifndef GL_EXT_shader_pixel_local_storage
+#define GL_EXT_shader_pixel_local_storage 1
+#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
+#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT 0x8F67
+#define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64
+#endif /* GL_EXT_shader_pixel_local_storage */
+
+#ifndef GL_EXT_shader_pixel_local_storage2
+#define GL_EXT_shader_pixel_local_storage2 1
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT 0x9650
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT 0x9651
+#define GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT 0x9652
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target, GLsizei size);
+typedef GLsizei (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target);
+typedef void (GL_APIENTRYP PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC) (GLsizei offset, GLsizei n, const GLuint *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferPixelLocalStorageSizeEXT (GLuint target, GLsizei size);
+GL_APICALL GLsizei GL_APIENTRY glGetFramebufferPixelLocalStorageSizeEXT (GLuint target);
+GL_APICALL void GL_APIENTRY glClearPixelLocalStorageuiEXT (GLsizei offset, GLsizei n, const GLuint *values);
+#endif
+#endif /* GL_EXT_shader_pixel_local_storage2 */
+
 #ifndef GL_EXT_shader_texture_lod
 #define GL_EXT_shader_texture_lod 1
-#endif
+#endif /* GL_EXT_shader_texture_lod */
 
-/* GL_EXT_shadow_samplers */
 #ifndef GL_EXT_shadow_samplers
 #define GL_EXT_shadow_samplers 1
-#endif
+#define GL_TEXTURE_COMPARE_MODE_EXT       0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT       0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT     0x884E
+#define GL_SAMPLER_2D_SHADOW_EXT          0x8B62
+#endif /* GL_EXT_shadow_samplers */
 
-/* GL_EXT_sRGB */
-#ifndef GL_EXT_sRGB
-#define GL_EXT_sRGB 1
+#ifndef GL_EXT_sparse_texture
+#define GL_EXT_sparse_texture 1
+#define GL_TEXTURE_SPARSE_EXT             0x91A6
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_EXT    0x91A7
+#define GL_NUM_SPARSE_LEVELS_EXT          0x91AA
+#define GL_NUM_VIRTUAL_PAGE_SIZES_EXT     0x91A8
+#define GL_VIRTUAL_PAGE_SIZE_X_EXT        0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_EXT        0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_EXT        0x9197
+#define GL_TEXTURE_2D_ARRAY               0x8C1A
+#define GL_TEXTURE_3D                     0x806F
+#define GL_MAX_SPARSE_TEXTURE_SIZE_EXT    0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT 0x919A
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT 0x91A9
+typedef void (GL_APIENTRYP PFNGLTEXPAGECOMMITMENTEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexPageCommitmentEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
 #endif
+#endif /* GL_EXT_sparse_texture */
 
-/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_tessellation_point_size
+#define GL_EXT_tessellation_point_size 1
+#endif /* GL_EXT_tessellation_point_size */
+
+#ifndef GL_EXT_tessellation_shader
+#define GL_EXT_tessellation_shader 1
+#define GL_PATCHES_EXT                    0x000E
+#define GL_PATCH_VERTICES_EXT             0x8E72
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_EXT 0x8E75
+#define GL_TESS_GEN_MODE_EXT              0x8E76
+#define GL_TESS_GEN_SPACING_EXT           0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER_EXT      0x8E78
+#define GL_TESS_GEN_POINT_MODE_EXT        0x8E79
+#define GL_ISOLINES_EXT                   0x8E7A
+#define GL_QUADS_EXT                      0x0007
+#define GL_FRACTIONAL_ODD_EXT             0x8E7B
+#define GL_FRACTIONAL_EVEN_EXT            0x8E7C
+#define GL_MAX_PATCH_VERTICES_EXT         0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL_EXT         0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS_EXT  0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E1F
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT 0x92CE
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT 0x92D4
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT 0x90CC
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT 0x90D9
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_IS_PER_PATCH_EXT               0x92E7
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT 0x9308
+#define GL_TESS_CONTROL_SHADER_EXT        0x8E88
+#define GL_TESS_EVALUATION_SHADER_EXT     0x8E87
+#define GL_TESS_CONTROL_SHADER_BIT_EXT    0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT_EXT 0x00000010
+typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIEXTPROC) (GLenum pname, GLint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPatchParameteriEXT (GLenum pname, GLint value);
+#endif
+#endif /* GL_EXT_tessellation_shader */
+
+#ifndef GL_EXT_texture_border_clamp
+#define GL_EXT_texture_border_clamp 1
+#define GL_TEXTURE_BORDER_COLOR_EXT       0x1004
+#define GL_CLAMP_TO_BORDER_EXT            0x812D
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIivEXT (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuivEXT (GLuint sampler, GLenum pname, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIivEXT (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivEXT (GLuint sampler, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_EXT_texture_border_clamp */
+
+#ifndef GL_EXT_texture_buffer
+#define GL_EXT_texture_buffer 1
+#define GL_TEXTURE_BUFFER_EXT             0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING_EXT     0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT    0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_EXT     0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT 0x919F
+#define GL_SAMPLER_BUFFER_EXT             0x8DC2
+#define GL_INT_SAMPLER_BUFFER_EXT         0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+#define GL_IMAGE_BUFFER_EXT               0x9051
+#define GL_INT_IMAGE_BUFFER_EXT           0x905C
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT  0x9067
+#define GL_TEXTURE_BUFFER_OFFSET_EXT      0x919D
+#define GL_TEXTURE_BUFFER_SIZE_EXT        0x919E
+typedef void (GL_APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEEXTPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif
+#endif /* GL_EXT_texture_buffer */
+
 #ifndef GL_EXT_texture_compression_dxt1
 #define GL_EXT_texture_compression_dxt1 1
-#endif
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
+#endif /* GL_EXT_texture_compression_dxt1 */
 
-/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_EXT_texture_compression_s3tc 1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
+#endif /* GL_EXT_texture_compression_s3tc */
+
+#ifndef GL_EXT_texture_compression_s3tc_srgb
+#define GL_EXT_texture_compression_s3tc_srgb 1
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT  0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#endif /* GL_EXT_texture_compression_s3tc_srgb */
+
+#ifndef GL_EXT_texture_cube_map_array
+#define GL_EXT_texture_cube_map_array 1
+#define GL_TEXTURE_CUBE_MAP_ARRAY_EXT     0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT 0x900A
+#define GL_SAMPLER_CUBE_MAP_ARRAY_EXT     0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900F
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT       0x9054
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT   0x905F
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#endif /* GL_EXT_texture_cube_map_array */
+
 #ifndef GL_EXT_texture_filter_anisotropic
 #define GL_EXT_texture_filter_anisotropic 1
-#endif
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif /* GL_EXT_texture_filter_anisotropic */
 
-/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_filter_minmax
+#define GL_EXT_texture_filter_minmax 1
+#endif /* GL_EXT_texture_filter_minmax */
+
 #ifndef GL_EXT_texture_format_BGRA8888
 #define GL_EXT_texture_format_BGRA8888 1
-#endif
+#endif /* GL_EXT_texture_format_BGRA8888 */
 
-/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_norm16
+#define GL_EXT_texture_norm16 1
+#define GL_R16_EXT                        0x822A
+#define GL_RG16_EXT                       0x822C
+#define GL_RGBA16_EXT                     0x805B
+#define GL_RGB16_EXT                      0x8054
+#define GL_RGB16_SNORM_EXT                0x8F9A
+#endif /* GL_EXT_texture_norm16 */
+
 #ifndef GL_EXT_texture_rg
 #define GL_EXT_texture_rg 1
-#endif
+#define GL_RED_EXT                        0x1903
+#define GL_RG_EXT                         0x8227
+#define GL_R8_EXT                         0x8229
+#define GL_RG8_EXT                        0x822B
+#endif /* GL_EXT_texture_rg */
 
-/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_sRGB_R8
+#define GL_EXT_texture_sRGB_R8 1
+#define GL_SR8_EXT                        0x8FBD
+#endif /* GL_EXT_texture_sRGB_R8 */
+
+#ifndef GL_EXT_texture_sRGB_RG8
+#define GL_EXT_texture_sRGB_RG8 1
+#define GL_SRG8_EXT                       0x8FBE
+#endif /* GL_EXT_texture_sRGB_RG8 */
+
+#ifndef GL_EXT_texture_sRGB_decode
+#define GL_EXT_texture_sRGB_decode 1
+#define GL_TEXTURE_SRGB_DECODE_EXT        0x8A48
+#define GL_DECODE_EXT                     0x8A49
+#define GL_SKIP_DECODE_EXT                0x8A4A
+#endif /* GL_EXT_texture_sRGB_decode */
+
 #ifndef GL_EXT_texture_storage
 #define GL_EXT_texture_storage 1
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT   0x912F
+#define GL_ALPHA8_EXT                     0x803C
+#define GL_LUMINANCE8_EXT                 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT          0x8045
+#define GL_RGBA32F_EXT                    0x8814
+#define GL_RGB32F_EXT                     0x8815
+#define GL_ALPHA32F_EXT                   0x8816
+#define GL_LUMINANCE32F_EXT               0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT         0x8819
+#define GL_ALPHA16F_EXT                   0x881C
+#define GL_LUMINANCE16F_EXT               0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT         0x881F
+#define GL_R32F_EXT                       0x822E
+#define GL_RG32F_EXT                      0x8230
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
 GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
@@ -1278,150 +2323,425 @@
 GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
 GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 #endif
-typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
-typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
-typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-#endif
+#endif /* GL_EXT_texture_storage */
 
-/* GL_EXT_texture_type_2_10_10_10_REV */
 #ifndef GL_EXT_texture_type_2_10_10_10_REV
 #define GL_EXT_texture_type_2_10_10_10_REV 1
-#endif
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+#endif /* GL_EXT_texture_type_2_10_10_10_REV */
 
-/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_texture_view
+#define GL_EXT_texture_view 1
+#define GL_TEXTURE_VIEW_MIN_LEVEL_EXT     0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS_EXT    0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER_EXT     0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS_EXT    0x82DE
+typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWEXTPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTextureViewEXT (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif
+#endif /* GL_EXT_texture_view */
+
 #ifndef GL_EXT_unpack_subimage
 #define GL_EXT_unpack_subimage 1
+#define GL_UNPACK_ROW_LENGTH_EXT          0x0CF2
+#define GL_UNPACK_SKIP_ROWS_EXT           0x0CF3
+#define GL_UNPACK_SKIP_PIXELS_EXT         0x0CF4
+#endif /* GL_EXT_unpack_subimage */
+
+#ifndef GL_EXT_window_rectangles
+#define GL_EXT_window_rectangles 1
+#define GL_INCLUSIVE_EXT                  0x8F10
+#define GL_EXCLUSIVE_EXT                  0x8F11
+#define GL_WINDOW_RECTANGLE_EXT           0x8F12
+#define GL_WINDOW_RECTANGLE_MODE_EXT      0x8F13
+#define GL_MAX_WINDOW_RECTANGLES_EXT      0x8F14
+#define GL_NUM_WINDOW_RECTANGLES_EXT      0x8F15
+typedef void (GL_APIENTRYP PFNGLWINDOWRECTANGLESEXTPROC) (GLenum mode, GLsizei count, const GLint *box);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glWindowRectanglesEXT (GLenum mode, GLsizei count, const GLint *box);
 #endif
+#endif /* GL_EXT_window_rectangles */
 
-/*------------------------------------------------------------------------*
- * DMP extension functions
- *------------------------------------------------------------------------*/
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_FJ_shader_binary_GCCSO 1
+#define GL_GCCSO_SHADER_BINARY_FJ         0x9260
+#endif /* GL_FJ_shader_binary_GCCSO */
 
-/* GL_DMP_shader_binary */
-#ifndef GL_DMP_shader_binary
-#define GL_DMP_shader_binary 1
+#ifndef GL_IMG_bindless_texture
+#define GL_IMG_bindless_texture 1
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLEIMGPROC) (GLuint texture);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEIMGPROC) (GLuint texture, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64IMGPROC) (GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64VIMGPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64IMGPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VIMGPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureHandleIMG (GLuint texture);
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureSamplerHandleIMG (GLuint texture, GLuint sampler);
+GL_APICALL void GL_APIENTRY glUniformHandleui64IMG (GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glUniformHandleui64vIMG (GLint location, GLsizei count, const GLuint64 *value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64IMG (GLuint program, GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64vIMG (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
 #endif
+#endif /* GL_IMG_bindless_texture */
 
-/*------------------------------------------------------------------------*
- * IMG extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_IMG_program_binary */
-#ifndef GL_IMG_program_binary
-#define GL_IMG_program_binary 1
+#ifndef GL_IMG_framebuffer_downsample
+#define GL_IMG_framebuffer_downsample 1
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG 0x913C
+#define GL_NUM_DOWNSAMPLE_SCALES_IMG      0x913D
+#define GL_DOWNSAMPLE_SCALES_IMG          0x913E
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG 0x913F
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DDownsampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayerDownsampleIMG (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale);
 #endif
+#endif /* GL_IMG_framebuffer_downsample */
 
-/* GL_IMG_read_format */
-#ifndef GL_IMG_read_format
-#define GL_IMG_read_format 1
-#endif
-
-/* GL_IMG_shader_binary */
-#ifndef GL_IMG_shader_binary
-#define GL_IMG_shader_binary 1
-#endif
-
-/* GL_IMG_texture_compression_pvrtc */
-#ifndef GL_IMG_texture_compression_pvrtc
-#define GL_IMG_texture_compression_pvrtc 1
-#endif
-
-/* GL_IMG_multisampled_render_to_texture */
 #ifndef GL_IMG_multisampled_render_to_texture
 #define GL_IMG_multisampled_render_to_texture 1
+#define GL_RENDERBUFFER_SAMPLES_IMG       0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG                0x9135
+#define GL_TEXTURE_SAMPLES_IMG            0x9136
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
 #ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
-GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
 #endif
-typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif /* GL_IMG_multisampled_render_to_texture */
+
+#ifndef GL_IMG_program_binary
+#define GL_IMG_program_binary 1
+#define GL_SGX_PROGRAM_BINARY_IMG         0x9130
+#endif /* GL_IMG_program_binary */
+
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#define GL_BGRA_IMG                       0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+#endif /* GL_IMG_read_format */
+
+#ifndef GL_IMG_shader_binary
+#define GL_IMG_shader_binary 1
+#define GL_SGX_BINARY_IMG                 0x8C0A
+#endif /* GL_IMG_shader_binary */
+
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+#endif /* GL_IMG_texture_compression_pvrtc */
+
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_IMG_texture_compression_pvrtc2 1
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
+#endif /* GL_IMG_texture_compression_pvrtc2 */
+
+#ifndef GL_IMG_texture_filter_cubic
+#define GL_IMG_texture_filter_cubic 1
+#define GL_CUBIC_IMG                      0x9139
+#define GL_CUBIC_MIPMAP_NEAREST_IMG       0x913A
+#define GL_CUBIC_MIPMAP_LINEAR_IMG        0x913B
+#endif /* GL_IMG_texture_filter_cubic */
+
+#ifndef GL_INTEL_conservative_rasterization
+#define GL_INTEL_conservative_rasterization 1
+#define GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE
+#endif /* GL_INTEL_conservative_rasterization */
+
+#ifndef GL_INTEL_framebuffer_CMAA
+#define GL_INTEL_framebuffer_CMAA 1
+typedef void (GL_APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void);
 #endif
+#endif /* GL_INTEL_framebuffer_CMAA */
 
-
-/*------------------------------------------------------------------------*
- * LBSHELL extension functions
- *------------------------------------------------------------------------*/
-
-#if defined(__LB_XB360__)
-// Generates a single texture name that can be used as the current video
-// frame. Only one video texture can exist at a time, and so subsequent calls
-// return the same texture name. The texture may be deleted as usual with
-// glDeleteTextures, in which case another call to glGenVideoTextureLBSHELL will
-// generate a new texture name for the single video texture.
-//
-// This may be called independently of whether a player is set with
-// eglSetPlayerLBSHELL, though the texture will be black and transparent if
-// there is no player set.
-//
-// |out_texture| is where the resulting texture name will be placed, and must
-// not be NULL.
-# ifndef GL_LBSHELL_bind_texture_to_video
-#  define GL_LBSHELL_bind_texture_to_video 1
-#  ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glBindTextureToVideoLBSHELL(GLuint texture);
-#  endif
-typedef void (GL_APIENTRYP PFNGLBINDTEXTURETOVIDEOLBSHELLPROC)(GLuint texture);
-# endif
+#ifndef GL_INTEL_performance_query
+#define GL_INTEL_performance_query 1
+#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000
+#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001
+#define GL_PERFQUERY_WAIT_INTEL           0x83FB
+#define GL_PERFQUERY_FLUSH_INTEL          0x83FA
+#define GL_PERFQUERY_DONOT_FLUSH_INTEL    0x83F9
+#define GL_PERFQUERY_COUNTER_EVENT_INTEL  0x94F0
+#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1
+#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2
+#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3
+#define GL_PERFQUERY_COUNTER_RAW_INTEL    0x94F4
+#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5
+#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8
+#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9
+#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA
+#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB
+#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC
+#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD
+#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE
+#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF
+#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500
+typedef void (GL_APIENTRYP PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (GL_APIENTRYP PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint *queryHandle);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (GL_APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (GL_APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId);
+typedef void (GL_APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId);
+typedef void (GL_APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+typedef void (GL_APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+typedef void (GL_APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId);
+typedef void (GL_APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBeginPerfQueryINTEL (GLuint queryHandle);
+GL_APICALL void GL_APIENTRY glCreatePerfQueryINTEL (GLuint queryId, GLuint *queryHandle);
+GL_APICALL void GL_APIENTRY glDeletePerfQueryINTEL (GLuint queryHandle);
+GL_APICALL void GL_APIENTRY glEndPerfQueryINTEL (GLuint queryHandle);
+GL_APICALL void GL_APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId);
+GL_APICALL void GL_APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId);
+GL_APICALL void GL_APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+GL_APICALL void GL_APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+GL_APICALL void GL_APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId);
+GL_APICALL void GL_APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
 #endif
+#endif /* GL_INTEL_performance_query */
 
+#ifndef GL_NV_bindless_texture
+#define GL_NV_bindless_texture 1
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (GL_APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureHandleNV (GLuint texture);
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler);
+GL_APICALL void GL_APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle);
+GL_APICALL void GL_APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle);
+GL_APICALL GLuint64 GL_APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GL_APICALL void GL_APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access);
+GL_APICALL void GL_APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle);
+GL_APICALL void GL_APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GL_APICALL GLboolean GL_APIENTRY glIsTextureHandleResidentNV (GLuint64 handle);
+GL_APICALL GLboolean GL_APIENTRY glIsImageHandleResidentNV (GLuint64 handle);
+#endif
+#endif /* GL_NV_bindless_texture */
 
-/*------------------------------------------------------------------------*
- * NV extension functions
- *------------------------------------------------------------------------*/
+#ifndef GL_NV_blend_equation_advanced
+#define GL_NV_blend_equation_advanced 1
+#define GL_BLEND_OVERLAP_NV               0x9281
+#define GL_BLEND_PREMULTIPLIED_SRC_NV     0x9280
+#define GL_BLUE_NV                        0x1905
+#define GL_COLORBURN_NV                   0x929A
+#define GL_COLORDODGE_NV                  0x9299
+#define GL_CONJOINT_NV                    0x9284
+#define GL_CONTRAST_NV                    0x92A1
+#define GL_DARKEN_NV                      0x9297
+#define GL_DIFFERENCE_NV                  0x929E
+#define GL_DISJOINT_NV                    0x9283
+#define GL_DST_ATOP_NV                    0x928F
+#define GL_DST_IN_NV                      0x928B
+#define GL_DST_NV                         0x9287
+#define GL_DST_OUT_NV                     0x928D
+#define GL_DST_OVER_NV                    0x9289
+#define GL_EXCLUSION_NV                   0x92A0
+#define GL_GREEN_NV                       0x1904
+#define GL_HARDLIGHT_NV                   0x929B
+#define GL_HARDMIX_NV                     0x92A9
+#define GL_HSL_COLOR_NV                   0x92AF
+#define GL_HSL_HUE_NV                     0x92AD
+#define GL_HSL_LUMINOSITY_NV              0x92B0
+#define GL_HSL_SATURATION_NV              0x92AE
+#define GL_INVERT_OVG_NV                  0x92B4
+#define GL_INVERT_RGB_NV                  0x92A3
+#define GL_LIGHTEN_NV                     0x9298
+#define GL_LINEARBURN_NV                  0x92A5
+#define GL_LINEARDODGE_NV                 0x92A4
+#define GL_LINEARLIGHT_NV                 0x92A7
+#define GL_MINUS_CLAMPED_NV               0x92B3
+#define GL_MINUS_NV                       0x929F
+#define GL_MULTIPLY_NV                    0x9294
+#define GL_OVERLAY_NV                     0x9296
+#define GL_PINLIGHT_NV                    0x92A8
+#define GL_PLUS_CLAMPED_ALPHA_NV          0x92B2
+#define GL_PLUS_CLAMPED_NV                0x92B1
+#define GL_PLUS_DARKER_NV                 0x9292
+#define GL_PLUS_NV                        0x9291
+#define GL_RED_NV                         0x1903
+#define GL_SCREEN_NV                      0x9295
+#define GL_SOFTLIGHT_NV                   0x929C
+#define GL_SRC_ATOP_NV                    0x928E
+#define GL_SRC_IN_NV                      0x928A
+#define GL_SRC_NV                         0x9286
+#define GL_SRC_OUT_NV                     0x928C
+#define GL_SRC_OVER_NV                    0x9288
+#define GL_UNCORRELATED_NV                0x9282
+#define GL_VIVIDLIGHT_NV                  0x92A6
+#define GL_XOR_NV                         0x1506
+typedef void (GL_APIENTRYP PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLBLENDBARRIERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlendParameteriNV (GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glBlendBarrierNV (void);
+#endif
+#endif /* GL_NV_blend_equation_advanced */
 
-/* GL_NV_coverage_sample */
+#ifndef GL_NV_blend_equation_advanced_coherent
+#define GL_NV_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_NV     0x9285
+#endif /* GL_NV_blend_equation_advanced_coherent */
+
+#ifndef GL_NV_conditional_render
+#define GL_NV_conditional_render 1
+#define GL_QUERY_WAIT_NV                  0x8E13
+#define GL_QUERY_NO_WAIT_NV               0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV        0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV     0x8E16
+typedef void (GL_APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode);
+GL_APICALL void GL_APIENTRY glEndConditionalRenderNV (void);
+#endif
+#endif /* GL_NV_conditional_render */
+
+#ifndef GL_NV_conservative_raster
+#define GL_NV_conservative_raster 1
+#define GL_CONSERVATIVE_RASTERIZATION_NV  0x9346
+#define GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV 0x9347
+#define GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV 0x9348
+#define GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV 0x9349
+typedef void (GL_APIENTRYP PFNGLSUBPIXELPRECISIONBIASNVPROC) (GLuint xbits, GLuint ybits);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits);
+#endif
+#endif /* GL_NV_conservative_raster */
+
+#ifndef GL_NV_conservative_raster_pre_snap_triangles
+#define GL_NV_conservative_raster_pre_snap_triangles 1
+#define GL_CONSERVATIVE_RASTER_MODE_NV    0x954D
+#define GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV 0x954E
+#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV 0x954F
+typedef void (GL_APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERINVPROC) (GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glConservativeRasterParameteriNV (GLenum pname, GLint param);
+#endif
+#endif /* GL_NV_conservative_raster_pre_snap_triangles */
+
+#ifndef GL_NV_copy_buffer
+#define GL_NV_copy_buffer 1
+#define GL_COPY_READ_BUFFER_NV            0x8F36
+#define GL_COPY_WRITE_BUFFER_NV           0x8F37
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATANVPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyBufferSubDataNV (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#endif
+#endif /* GL_NV_copy_buffer */
+
 #ifndef GL_NV_coverage_sample
 #define GL_NV_coverage_sample 1
+#define GL_COVERAGE_COMPONENT_NV          0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV         0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV         0x8ED2
+#define GL_COVERAGE_BUFFERS_NV            0x8ED3
+#define GL_COVERAGE_SAMPLES_NV            0x8ED4
+#define GL_COVERAGE_ALL_FRAGMENTS_NV      0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV     0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV          0x8ED7
+#define GL_COVERAGE_BUFFER_BIT_NV         0x00008000
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask);
 GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation);
 #endif
-typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
-typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
-#endif
+#endif /* GL_NV_coverage_sample */
 
-/* GL_NV_depth_nonlinear */
 #ifndef GL_NV_depth_nonlinear
 #define GL_NV_depth_nonlinear 1
-#endif
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C
+#endif /* GL_NV_depth_nonlinear */
 
-/* GL_NV_draw_buffers */
 #ifndef GL_NV_draw_buffers
 #define GL_NV_draw_buffers 1
+#define GL_MAX_DRAW_BUFFERS_NV            0x8824
+#define GL_DRAW_BUFFER0_NV                0x8825
+#define GL_DRAW_BUFFER1_NV                0x8826
+#define GL_DRAW_BUFFER2_NV                0x8827
+#define GL_DRAW_BUFFER3_NV                0x8828
+#define GL_DRAW_BUFFER4_NV                0x8829
+#define GL_DRAW_BUFFER5_NV                0x882A
+#define GL_DRAW_BUFFER6_NV                0x882B
+#define GL_DRAW_BUFFER7_NV                0x882C
+#define GL_DRAW_BUFFER8_NV                0x882D
+#define GL_DRAW_BUFFER9_NV                0x882E
+#define GL_DRAW_BUFFER10_NV               0x882F
+#define GL_DRAW_BUFFER11_NV               0x8830
+#define GL_DRAW_BUFFER12_NV               0x8831
+#define GL_DRAW_BUFFER13_NV               0x8832
+#define GL_DRAW_BUFFER14_NV               0x8833
+#define GL_DRAW_BUFFER15_NV               0x8834
+#define GL_COLOR_ATTACHMENT0_NV           0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV           0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV           0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV           0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV           0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV           0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV           0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV           0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV           0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV           0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV          0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV          0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV          0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV          0x8CED
+#define GL_COLOR_ATTACHMENT14_NV          0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV          0x8CEF
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs);
 #endif
-typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs);
-#endif
+#endif /* GL_NV_draw_buffers */
 
-#ifndef GL_EXT_draw_buffers
-#define GL_EXT_draw_buffers 1
+#ifndef GL_NV_draw_instanced
+#define GL_NV_draw_instanced 1
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
 #ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs);
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
 #endif
-typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs);
-#endif
+#endif /* GL_NV_draw_instanced */
 
-/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_explicit_attrib_location
+#define GL_NV_explicit_attrib_location 1
+#endif /* GL_NV_explicit_attrib_location */
+
 #ifndef GL_NV_fbo_color_attachments
 #define GL_NV_fbo_color_attachments 1
-#endif
+#define GL_MAX_COLOR_ATTACHMENTS_NV       0x8CDF
+#endif /* GL_NV_fbo_color_attachments */
 
-/* GL_NV_fence */
 #ifndef GL_NV_fence
 #define GL_NV_fence 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);
-GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *);
-GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint);
-GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint);
-GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);
-GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint);
-GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint, GLenum);
-#endif
+#define GL_ALL_COMPLETED_NV               0x84F2
+#define GL_FENCE_STATUS_NV                0x84F3
+#define GL_FENCE_CONDITION_NV             0x84F4
 typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
 typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
 typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
@@ -1429,78 +2749,764 @@
 typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
 typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
 typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
 #endif
+#endif /* GL_NV_fence */
 
-/* GL_NV_read_buffer */
+#ifndef GL_NV_fill_rectangle
+#define GL_NV_fill_rectangle 1
+#define GL_FILL_RECTANGLE_NV              0x933C
+#endif /* GL_NV_fill_rectangle */
+
+#ifndef GL_NV_fragment_coverage_to_color
+#define GL_NV_fragment_coverage_to_color 1
+#define GL_FRAGMENT_COVERAGE_TO_COLOR_NV  0x92DD
+#define GL_FRAGMENT_COVERAGE_COLOR_NV     0x92DE
+typedef void (GL_APIENTRYP PFNGLFRAGMENTCOVERAGECOLORNVPROC) (GLuint color);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFragmentCoverageColorNV (GLuint color);
+#endif
+#endif /* GL_NV_fragment_coverage_to_color */
+
+#ifndef GL_NV_fragment_shader_interlock
+#define GL_NV_fragment_shader_interlock 1
+#endif /* GL_NV_fragment_shader_interlock */
+
+#ifndef GL_NV_framebuffer_blit
+#define GL_NV_framebuffer_blit 1
+#define GL_READ_FRAMEBUFFER_NV            0x8CA8
+#define GL_DRAW_FRAMEBUFFER_NV            0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_NV    0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_NV    0x8CAA
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferNV (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+#endif /* GL_NV_framebuffer_blit */
+
+#ifndef GL_NV_framebuffer_mixed_samples
+#define GL_NV_framebuffer_mixed_samples 1
+#define GL_COVERAGE_MODULATION_TABLE_NV   0x9331
+#define GL_COLOR_SAMPLES_NV               0x8E20
+#define GL_DEPTH_SAMPLES_NV               0x932D
+#define GL_STENCIL_SAMPLES_NV             0x932E
+#define GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV 0x932F
+#define GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV 0x9330
+#define GL_COVERAGE_MODULATION_NV         0x9332
+#define GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONTABLENVPROC) (GLsizei n, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufsize, GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONNVPROC) (GLenum components);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageModulationTableNV (GLsizei n, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glGetCoverageModulationTableNV (GLsizei bufsize, GLfloat *v);
+GL_APICALL void GL_APIENTRY glCoverageModulationNV (GLenum components);
+#endif
+#endif /* GL_NV_framebuffer_mixed_samples */
+
+#ifndef GL_NV_framebuffer_multisample
+#define GL_NV_framebuffer_multisample 1
+#define GL_RENDERBUFFER_SAMPLES_NV        0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56
+#define GL_MAX_SAMPLES_NV                 0x8D57
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLENVPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_NV_framebuffer_multisample */
+
+#ifndef GL_NV_generate_mipmap_sRGB
+#define GL_NV_generate_mipmap_sRGB 1
+#endif /* GL_NV_generate_mipmap_sRGB */
+
+#ifndef GL_NV_geometry_shader_passthrough
+#define GL_NV_geometry_shader_passthrough 1
+#endif /* GL_NV_geometry_shader_passthrough */
+
+#ifndef GL_NV_gpu_shader5
+#define GL_NV_gpu_shader5 1
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64EXT;
+#define GL_INT64_NV                       0x140E
+#define GL_UNSIGNED_INT64_NV              0x140F
+#define GL_INT8_NV                        0x8FE0
+#define GL_INT8_VEC2_NV                   0x8FE1
+#define GL_INT8_VEC3_NV                   0x8FE2
+#define GL_INT8_VEC4_NV                   0x8FE3
+#define GL_INT16_NV                       0x8FE4
+#define GL_INT16_VEC2_NV                  0x8FE5
+#define GL_INT16_VEC3_NV                  0x8FE6
+#define GL_INT16_VEC4_NV                  0x8FE7
+#define GL_INT64_VEC2_NV                  0x8FE9
+#define GL_INT64_VEC3_NV                  0x8FEA
+#define GL_INT64_VEC4_NV                  0x8FEB
+#define GL_UNSIGNED_INT8_NV               0x8FEC
+#define GL_UNSIGNED_INT8_VEC2_NV          0x8FED
+#define GL_UNSIGNED_INT8_VEC3_NV          0x8FEE
+#define GL_UNSIGNED_INT8_VEC4_NV          0x8FEF
+#define GL_UNSIGNED_INT16_NV              0x8FF0
+#define GL_UNSIGNED_INT16_VEC2_NV         0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV         0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV         0x8FF3
+#define GL_UNSIGNED_INT64_VEC2_NV         0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_NV         0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_NV         0x8FF7
+#define GL_FLOAT16_NV                     0x8FF8
+#define GL_FLOAT16_VEC2_NV                0x8FF9
+#define GL_FLOAT16_VEC3_NV                0x8FFA
+#define GL_FLOAT16_VEC4_NV                0x8FFB
+#define GL_PATCHES                        0x000E
+typedef void (GL_APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUniform1i64NV (GLint location, GLint64EXT x);
+GL_APICALL void GL_APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y);
+GL_APICALL void GL_APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GL_APICALL void GL_APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GL_APICALL void GL_APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x);
+GL_APICALL void GL_APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y);
+GL_APICALL void GL_APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GL_APICALL void GL_APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GL_APICALL void GL_APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x);
+GL_APICALL void GL_APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+GL_APICALL void GL_APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GL_APICALL void GL_APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GL_APICALL void GL_APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+#endif /* GL_NV_gpu_shader5 */
+
+#ifndef GL_NV_image_formats
+#define GL_NV_image_formats 1
+#endif /* GL_NV_image_formats */
+
+#ifndef GL_NV_instanced_arrays
+#define GL_NV_instanced_arrays 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor);
+#endif
+#endif /* GL_NV_instanced_arrays */
+
+#ifndef GL_NV_internalformat_sample_query
+#define GL_NV_internalformat_sample_query 1
+#define GL_TEXTURE_2D_MULTISAMPLE         0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY   0x9102
+#define GL_MULTISAMPLES_NV                0x9371
+#define GL_SUPERSAMPLE_SCALE_X_NV         0x9372
+#define GL_SUPERSAMPLE_SCALE_Y_NV         0x9373
+#define GL_CONFORMANT_NV                  0x9374
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_NV_internalformat_sample_query */
+
+#ifndef GL_NV_non_square_matrices
+#define GL_NV_non_square_matrices 1
+#define GL_FLOAT_MAT2x3_NV                0x8B65
+#define GL_FLOAT_MAT2x4_NV                0x8B66
+#define GL_FLOAT_MAT3x2_NV                0x8B67
+#define GL_FLOAT_MAT3x4_NV                0x8B68
+#define GL_FLOAT_MAT4x2_NV                0x8B69
+#define GL_FLOAT_MAT4x3_NV                0x8B6A
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
+#endif /* GL_NV_non_square_matrices */
+
+#ifndef GL_NV_path_rendering
+#define GL_NV_path_rendering 1
+#define GL_PATH_FORMAT_SVG_NV             0x9070
+#define GL_PATH_FORMAT_PS_NV              0x9071
+#define GL_STANDARD_FONT_NAME_NV          0x9072
+#define GL_SYSTEM_FONT_NAME_NV            0x9073
+#define GL_FILE_NAME_NV                   0x9074
+#define GL_PATH_STROKE_WIDTH_NV           0x9075
+#define GL_PATH_END_CAPS_NV               0x9076
+#define GL_PATH_INITIAL_END_CAP_NV        0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV       0x9078
+#define GL_PATH_JOIN_STYLE_NV             0x9079
+#define GL_PATH_MITER_LIMIT_NV            0x907A
+#define GL_PATH_DASH_CAPS_NV              0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV       0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV      0x907D
+#define GL_PATH_DASH_OFFSET_NV            0x907E
+#define GL_PATH_CLIENT_LENGTH_NV          0x907F
+#define GL_PATH_FILL_MODE_NV              0x9080
+#define GL_PATH_FILL_MASK_NV              0x9081
+#define GL_PATH_FILL_COVER_MODE_NV        0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV      0x9083
+#define GL_PATH_STROKE_MASK_NV            0x9084
+#define GL_COUNT_UP_NV                    0x9088
+#define GL_COUNT_DOWN_NV                  0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV    0x908A
+#define GL_CONVEX_HULL_NV                 0x908B
+#define GL_BOUNDING_BOX_NV                0x908D
+#define GL_TRANSLATE_X_NV                 0x908E
+#define GL_TRANSLATE_Y_NV                 0x908F
+#define GL_TRANSLATE_2D_NV                0x9090
+#define GL_TRANSLATE_3D_NV                0x9091
+#define GL_AFFINE_2D_NV                   0x9092
+#define GL_AFFINE_3D_NV                   0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV         0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV         0x9098
+#define GL_UTF8_NV                        0x909A
+#define GL_UTF16_NV                       0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV          0x909D
+#define GL_PATH_COORD_COUNT_NV            0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV       0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV        0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV      0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV    0x90A2
+#define GL_SQUARE_NV                      0x90A3
+#define GL_ROUND_NV                       0x90A4
+#define GL_TRIANGULAR_NV                  0x90A5
+#define GL_BEVEL_NV                       0x90A6
+#define GL_MITER_REVERT_NV                0x90A7
+#define GL_MITER_TRUNCATE_NV              0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV          0x90A9
+#define GL_USE_MISSING_GLYPH_NV           0x90AA
+#define GL_PATH_ERROR_POSITION_NV         0x90AB
+#define GL_ACCUM_ADJACENT_PAIRS_NV        0x90AD
+#define GL_ADJACENT_PAIRS_NV              0x90AE
+#define GL_FIRST_TO_REST_NV               0x90AF
+#define GL_PATH_GEN_MODE_NV               0x90B0
+#define GL_PATH_GEN_COEFF_NV              0x90B1
+#define GL_PATH_GEN_COMPONENTS_NV         0x90B3
+#define GL_PATH_STENCIL_FUNC_NV           0x90B7
+#define GL_PATH_STENCIL_REF_NV            0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV     0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV       0x90BF
+#define GL_PATH_DASH_OFFSET_RESET_NV      0x90B4
+#define GL_MOVE_TO_RESETS_NV              0x90B5
+#define GL_MOVE_TO_CONTINUES_NV           0x90B6
+#define GL_CLOSE_PATH_NV                  0x00
+#define GL_MOVE_TO_NV                     0x02
+#define GL_RELATIVE_MOVE_TO_NV            0x03
+#define GL_LINE_TO_NV                     0x04
+#define GL_RELATIVE_LINE_TO_NV            0x05
+#define GL_HORIZONTAL_LINE_TO_NV          0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_VERTICAL_LINE_TO_NV            0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV   0x09
+#define GL_QUADRATIC_CURVE_TO_NV          0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV              0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV     0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV   0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV       0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV            0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV   0x13
+#define GL_SMALL_CW_ARC_TO_NV             0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV    0x15
+#define GL_LARGE_CCW_ARC_TO_NV            0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV   0x17
+#define GL_LARGE_CW_ARC_TO_NV             0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV    0x19
+#define GL_RESTART_PATH_NV                0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV    0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV     0xF4
+#define GL_RECT_NV                        0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV         0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV          0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV     0xFC
+#define GL_ARC_TO_NV                      0xFE
+#define GL_RELATIVE_ARC_TO_NV             0xFF
+#define GL_BOLD_BIT_NV                    0x01
+#define GL_ITALIC_BIT_NV                  0x02
+#define GL_GLYPH_WIDTH_BIT_NV             0x01
+#define GL_GLYPH_HEIGHT_BIT_NV            0x02
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_GLYPH_HAS_KERNING_BIT_NV       0x100
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV       0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV       0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV       0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV       0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV       0x00100000
+#define GL_FONT_ASCENDER_BIT_NV           0x00200000
+#define GL_FONT_DESCENDER_BIT_NV          0x00400000
+#define GL_FONT_HEIGHT_BIT_NV             0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV  0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV        0x10000000
+#define GL_ROUNDED_RECT_NV                0xE8
+#define GL_RELATIVE_ROUNDED_RECT_NV       0xE9
+#define GL_ROUNDED_RECT2_NV               0xEA
+#define GL_RELATIVE_ROUNDED_RECT2_NV      0xEB
+#define GL_ROUNDED_RECT4_NV               0xEC
+#define GL_RELATIVE_ROUNDED_RECT4_NV      0xED
+#define GL_ROUNDED_RECT8_NV               0xEE
+#define GL_RELATIVE_ROUNDED_RECT8_NV      0xEF
+#define GL_RELATIVE_RECT_NV               0xF7
+#define GL_FONT_GLYPHS_AVAILABLE_NV       0x9368
+#define GL_FONT_TARGET_UNAVAILABLE_NV     0x9369
+#define GL_FONT_UNAVAILABLE_NV            0x936A
+#define GL_FONT_UNINTELLIGIBLE_NV         0x936B
+#define GL_CONIC_CURVE_TO_NV              0x1A
+#define GL_RELATIVE_CONIC_CURVE_TO_NV     0x1B
+#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV  0x20000000
+#define GL_STANDARD_FONT_FORMAT_NV        0x936C
+#define GL_PATH_PROJECTION_NV             0x1701
+#define GL_PATH_MODELVIEW_NV              0x1700
+#define GL_PATH_MODELVIEW_STACK_DEPTH_NV  0x0BA3
+#define GL_PATH_MODELVIEW_MATRIX_NV       0x0BA6
+#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36
+#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3
+#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4
+#define GL_PATH_PROJECTION_MATRIX_NV      0x0BA7
+#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38
+#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4
+#define GL_FRAGMENT_INPUT_NV              0x936D
+typedef GLuint (GL_APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (GL_APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLboolean (GL_APIENTRYP PFNGLISPATHNVPROC) (GLuint path);
+typedef void (GL_APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString);
+typedef void (GL_APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+typedef void (GL_APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (GL_APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (GL_APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+typedef void (GL_APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value);
+typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands);
+typedef void (GL_APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords);
+typedef void (GL_APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray);
+typedef void (GL_APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (GL_APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+typedef void (GL_APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef GLfloat (GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef GLboolean (GL_APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef GLenum (GL_APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint GL_APIENTRY glGenPathsNV (GLsizei range);
+GL_APICALL void GL_APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
+GL_APICALL GLboolean GL_APIENTRY glIsPathNV (GLuint path);
+GL_APICALL void GL_APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString);
+GL_APICALL void GL_APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+GL_APICALL void GL_APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath);
+GL_APICALL void GL_APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+GL_APICALL void GL_APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value);
+GL_APICALL void GL_APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value);
+GL_APICALL void GL_APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathCoverDepthFuncNV (GLenum func);
+GL_APICALL void GL_APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value);
+GL_APICALL void GL_APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value);
+GL_APICALL void GL_APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands);
+GL_APICALL void GL_APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords);
+GL_APICALL void GL_APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y);
+GL_APICALL GLfloat GL_APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments);
+GL_APICALL GLboolean GL_APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL GLenum GL_APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+GL_APICALL void GL_APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#endif
+#endif /* GL_NV_path_rendering */
+
+#ifndef GL_NV_path_rendering_shared_edge
+#define GL_NV_path_rendering_shared_edge 1
+#define GL_SHARED_EDGE_NV                 0xC0
+#endif /* GL_NV_path_rendering_shared_edge */
+
+#ifndef GL_NV_polygon_mode
+#define GL_NV_polygon_mode 1
+#define GL_POLYGON_MODE_NV                0x0B40
+#define GL_POLYGON_OFFSET_POINT_NV        0x2A01
+#define GL_POLYGON_OFFSET_LINE_NV         0x2A02
+#define GL_POINT_NV                       0x1B00
+#define GL_LINE_NV                        0x1B01
+#define GL_FILL_NV                        0x1B02
+typedef void (GL_APIENTRYP PFNGLPOLYGONMODENVPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPolygonModeNV (GLenum face, GLenum mode);
+#endif
+#endif /* GL_NV_polygon_mode */
+
 #ifndef GL_NV_read_buffer
 #define GL_NV_read_buffer 1
+#define GL_READ_BUFFER_NV                 0x0C02
+typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
 #endif
-typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode);
-#endif
+#endif /* GL_NV_read_buffer */
 
-/* GL_NV_read_buffer_front */
 #ifndef GL_NV_read_buffer_front
 #define GL_NV_read_buffer_front 1
-#endif
+#endif /* GL_NV_read_buffer_front */
 
-/* GL_NV_read_depth */
 #ifndef GL_NV_read_depth
 #define GL_NV_read_depth 1
-#endif
+#endif /* GL_NV_read_depth */
 
-/* GL_NV_read_depth_stencil */
 #ifndef GL_NV_read_depth_stencil
 #define GL_NV_read_depth_stencil 1
-#endif
+#endif /* GL_NV_read_depth_stencil */
 
-/* GL_NV_read_stencil */
 #ifndef GL_NV_read_stencil
 #define GL_NV_read_stencil 1
-#endif
+#endif /* GL_NV_read_stencil */
 
-/* GL_NV_texture_compression_s3tc_update */
+#ifndef GL_NV_sRGB_formats
+#define GL_NV_sRGB_formats 1
+#define GL_SLUMINANCE_NV                  0x8C46
+#define GL_SLUMINANCE_ALPHA_NV            0x8C44
+#define GL_SRGB8_NV                       0x8C41
+#define GL_SLUMINANCE8_NV                 0x8C47
+#define GL_SLUMINANCE8_ALPHA8_NV          0x8C45
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV   0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F
+#define GL_ETC1_SRGB8_NV                  0x88EE
+#endif /* GL_NV_sRGB_formats */
+
+#ifndef GL_NV_sample_locations
+#define GL_NV_sample_locations 1
+#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV 0x933E
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV 0x933F
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV 0x9340
+#define GL_SAMPLE_LOCATION_NV             0x8E50
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9341
+#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV 0x9342
+#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV 0x9343
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLRESOLVEDEPTHVALUESNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferSampleLocationsfvNV (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glNamedFramebufferSampleLocationsfvNV (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glResolveDepthValuesNV (void);
+#endif
+#endif /* GL_NV_sample_locations */
+
+#ifndef GL_NV_sample_mask_override_coverage
+#define GL_NV_sample_mask_override_coverage 1
+#endif /* GL_NV_sample_mask_override_coverage */
+
+#ifndef GL_NV_shader_atomic_fp16_vector
+#define GL_NV_shader_atomic_fp16_vector 1
+#endif /* GL_NV_shader_atomic_fp16_vector */
+
+#ifndef GL_NV_shader_noperspective_interpolation
+#define GL_NV_shader_noperspective_interpolation 1
+#endif /* GL_NV_shader_noperspective_interpolation */
+
+#ifndef GL_NV_shadow_samplers_array
+#define GL_NV_shadow_samplers_array 1
+#define GL_SAMPLER_2D_ARRAY_SHADOW_NV     0x8DC4
+#endif /* GL_NV_shadow_samplers_array */
+
+#ifndef GL_NV_shadow_samplers_cube
+#define GL_NV_shadow_samplers_cube 1
+#define GL_SAMPLER_CUBE_SHADOW_NV         0x8DC5
+#endif /* GL_NV_shadow_samplers_cube */
+
+#ifndef GL_NV_texture_border_clamp
+#define GL_NV_texture_border_clamp 1
+#define GL_TEXTURE_BORDER_COLOR_NV        0x1004
+#define GL_CLAMP_TO_BORDER_NV             0x812D
+#endif /* GL_NV_texture_border_clamp */
+
 #ifndef GL_NV_texture_compression_s3tc_update
 #define GL_NV_texture_compression_s3tc_update 1
-#endif
+#endif /* GL_NV_texture_compression_s3tc_update */
 
-/* GL_NV_texture_npot_2D_mipmap */
 #ifndef GL_NV_texture_npot_2D_mipmap
 #define GL_NV_texture_npot_2D_mipmap 1
+#endif /* GL_NV_texture_npot_2D_mipmap */
+
+#ifndef GL_NV_viewport_array
+#define GL_NV_viewport_array 1
+#define GL_MAX_VIEWPORTS_NV               0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS_NV      0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE_NV       0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV 0x825F
+typedef void (GL_APIENTRYP PFNGLVIEWPORTARRAYVNVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDNVPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDVNVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEARRAYFVNVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEINDEXEDFNVPROC) (GLuint index, GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLGETFLOATI_VNVPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLENABLEINVPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEINVPROC) (GLenum target, GLuint index);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDINVPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportArrayvNV (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glViewportIndexedfNV (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GL_APICALL void GL_APIENTRY glViewportIndexedfvNV (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glScissorArrayvNV (GLuint first, GLsizei count, const GLint *v);
+GL_APICALL void GL_APIENTRY glScissorIndexedNV (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glScissorIndexedvNV (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glDepthRangeArrayfvNV (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glDepthRangeIndexedfNV (GLuint index, GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glGetFloati_vNV (GLenum target, GLuint index, GLfloat *data);
+GL_APICALL void GL_APIENTRY glEnableiNV (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiNV (GLenum target, GLuint index);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediNV (GLenum target, GLuint index);
 #endif
+#endif /* GL_NV_viewport_array */
 
-/*------------------------------------------------------------------------*
- * QCOM extension functions
- *------------------------------------------------------------------------*/
+#ifndef GL_NV_viewport_array2
+#define GL_NV_viewport_array2 1
+#endif /* GL_NV_viewport_array2 */
 
-/* GL_QCOM_alpha_test */
+#ifndef GL_NV_viewport_swizzle
+#define GL_NV_viewport_swizzle 1
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV 0x9350
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV 0x9351
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV 0x9352
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV 0x9353
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV 0x9354
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV 0x9355
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV 0x9356
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV 0x9357
+#define GL_VIEWPORT_SWIZZLE_X_NV          0x9358
+#define GL_VIEWPORT_SWIZZLE_Y_NV          0x9359
+#define GL_VIEWPORT_SWIZZLE_Z_NV          0x935A
+#define GL_VIEWPORT_SWIZZLE_W_NV          0x935B
+typedef void (GL_APIENTRYP PFNGLVIEWPORTSWIZZLENVPROC) (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportSwizzleNV (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew);
+#endif
+#endif /* GL_NV_viewport_swizzle */
+
+#ifndef GL_OVR_multiview
+#define GL_OVR_multiview 1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
+#define GL_MAX_VIEWS_OVR                  0x9631
+#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview */
+
+#ifndef GL_OVR_multiview2
+#define GL_OVR_multiview2 1
+#endif /* GL_OVR_multiview2 */
+
+#ifndef GL_OVR_multiview_multisampled_render_to_texture
+#define GL_OVR_multiview_multisampled_render_to_texture 1
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultisampleMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview_multisampled_render_to_texture */
+
 #ifndef GL_QCOM_alpha_test
 #define GL_QCOM_alpha_test 1
+#define GL_ALPHA_TEST_QCOM                0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM           0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM            0x0BC2
+typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref);
 #endif
-typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
-#endif
+#endif /* GL_QCOM_alpha_test */
 
-/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_binning_control
+#define GL_QCOM_binning_control 1
+#define GL_BINNING_CONTROL_HINT_QCOM      0x8FB0
+#define GL_CPU_OPTIMIZED_QCOM             0x8FB1
+#define GL_GPU_OPTIMIZED_QCOM             0x8FB2
+#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
+#endif /* GL_QCOM_binning_control */
+
 #ifndef GL_QCOM_driver_control
 #define GL_QCOM_driver_control 1
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
 GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
 GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
 GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
 #endif
-typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
-typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
-typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
-typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
-#endif
+#endif /* GL_QCOM_driver_control */
 
-/* GL_QCOM_extended_get */
 #ifndef GL_QCOM_extended_get
 #define GL_QCOM_extended_get 1
+#define GL_TEXTURE_WIDTH_QCOM             0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM            0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM             0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM   0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM            0x8BD6
+#define GL_TEXTURE_TYPE_QCOM              0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM       0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM        0x8BD9
+#define GL_TEXTURE_TARGET_QCOM            0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM      0x8BDB
+#define GL_STATE_RESTORE                  0x8BDC
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, void **params);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
 GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
@@ -1508,71 +3514,233 @@
 GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
 GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
 GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
-GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
-GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, void **params);
 #endif
-typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
-typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
-typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
-typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
-typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
-typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
-typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
-typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
-#endif
+#endif /* GL_QCOM_extended_get */
 
-/* GL_QCOM_extended_get2 */
 #ifndef GL_QCOM_extended_get2
 #define GL_QCOM_extended_get2 1
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
 GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
 GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
 GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
 #endif
-typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
-typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
-typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
-typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
-#endif
+#endif /* GL_QCOM_extended_get2 */
 
-/* GL_QCOM_perfmon_global_mode */
 #ifndef GL_QCOM_perfmon_global_mode
 #define GL_QCOM_perfmon_global_mode 1
-#endif
+#define GL_PERFMON_GLOBAL_MODE_QCOM       0x8FA0
+#endif /* GL_QCOM_perfmon_global_mode */
 
-/* GL_QCOM_writeonly_rendering */
-#ifndef GL_QCOM_writeonly_rendering
-#define GL_QCOM_writeonly_rendering 1
-#endif
-
-/* GL_QCOM_tiled_rendering */
 #ifndef GL_QCOM_tiled_rendering
 #define GL_QCOM_tiled_rendering 1
+#define GL_COLOR_BUFFER_BIT0_QCOM         0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM         0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM         0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM         0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM         0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM         0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM         0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM         0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM         0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM         0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM         0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM         0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM         0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM         0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM         0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM         0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM       0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM       0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM       0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM       0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM       0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM       0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM       0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM       0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM   0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM   0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM   0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM   0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM   0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM   0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM   0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM   0x80000000
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
 GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
 #endif
-typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
-typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
-#endif
+#endif /* GL_QCOM_tiled_rendering */
 
-/*------------------------------------------------------------------------*
- * VIV extension tokens
- *------------------------------------------------------------------------*/
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#define GL_WRITEONLY_RENDERING_QCOM       0x8823
+#endif /* GL_QCOM_writeonly_rendering */
 
-/* GL_VIV_shader_binary */
 #ifndef GL_VIV_shader_binary
 #define GL_VIV_shader_binary 1
-#endif
+#define GL_SHADER_BINARY_VIV              0x8FC4
+#endif /* GL_VIV_shader_binary */
 
-/* GL_ANGLE_program_binary */
-#ifndef GL_ANGLE_program_binary
-#define GL_ANGLE_program_binary 1
+#ifndef GL_ANGLE_lossy_etc_decode
+#define GL_ANGLE_lossy_etc_decode 1
+#define GL_ETC1_RGB8_LOSSY_DECODE_ANGLE                                  0x9690
+#define GL_COMPRESSED_R11_LOSSY_DECODE_EAC_ANGLE                         0x9691
+#define GL_COMPRESSED_SIGNED_R11_LOSSY_DECODE_EAC_ANGLE                  0x9692
+#define GL_COMPRESSED_RG11_LOSSY_DECODE_EAC_ANGLE                        0x9693
+#define GL_COMPRESSED_SIGNED_RG11_LOSSY_DECODE_EAC_ANGLE                 0x9694
+#define GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE                       0x9695
+#define GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE                      0x9696
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE   0x9697
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE  0x9698
+#define GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE                  0x9699
+#define GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE           0x969A
+#endif /* GL_ANGLE_lossy_etc_decode */
+
+#ifndef GL_ANGLE_robust_client_memory
+#define GL_ANGLE_robust_client_memory 1
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVROBUSTANGLE) (GLenum target, GLenum attachment, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVROBUSTANGLE) (GLuint program, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVROBUSTANGLE) (GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, void **pointer);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSROBUSTANGLE) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, GLsizei *rows, void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, GLsizei bufSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, GLsizei bufSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, GLsizei bufSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, GLsizei bufSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVROBUSTANGLE) (GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VROBUSTANGLE) (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data);
+typedef void (GL_APIENTRYP PFNGETINTERNALFORMATIVROBUSTANGLE) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVROBUSTANGLE) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VROBUSTANGLE) (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVROBUSTANGLE) (GLuint program, GLenum programInterface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VROBUSTANGLE) (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVROBUSTANGLE) (GLenum pname, GLuint index, GLsizei bufSize, GLsizei *length, GLfloat *val);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVROBUSTANGLE) (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVROBUSTANGLE) (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVROBUSTANGLEROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSROBUSTANGLE) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, GLsizei *rows, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVROBUSTANGLE)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VROBUSTANGLE)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VROBUSTANGLE)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint64 *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetBooleanvRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetFloatvRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameterivRobustANGLE (GLenum target, GLenum attachment, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegervRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramivRobustANGLE (GLuint program, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderivRobustANGLE (GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterfvRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfvRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfvRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribivRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointervRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, void **pointer);
+GL_APICALL void GL_APIENTRY glReadPixelsRobustANGLE (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, GLsizei *rows, void *pixels);
+GL_APICALL void GL_APIENTRY glTexImage2DRobustANGLE (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterfvRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2DRobustANGLE (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexImage3DRobustANGLE (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DRobustANGLE (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2DRobustANGLE(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, GLsizei bufSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2DRobustANGLE(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, GLsizei bufSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DRobustANGLE(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, GLsizei bufSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DRobustANGLE(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, GLsizei bufSize, const void *data);
+GL_APICALL void GL_APIENTRY glGetQueryivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuivRobustANGLE (GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetBufferPointervRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
+GL_APICALL void GL_APIENTRY glGetIntegeri_vRobustANGLE (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data);
+GL_APICALL void GL_APIENTRY glGetInternalformativRobustANGLE (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIivRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuivRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetUniformuivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockivRobustANGLE (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetInteger64vRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetInteger64i_vRobustANGLE (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64vRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfvRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLfloat *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfvRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetFramebufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInterfaceivRobustANGLE (GLuint program, GLenum programInterface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetBooleani_vRobustANGLE (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetMultisamplefvRobustANGLE (GLenum pname, GLuint index, GLsizei bufSize, GLsizei *length, GLfloat *val);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameterivRobustANGLE (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameterfvRobustANGLE (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetPointervRobustANGLERobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
+GL_APICALL void GL_APIENTRY glReadnPixelsRobustANGLE (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, GLsizei *rows, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetnUniformuivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectivRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjecti64vRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectui64vRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint64 *params);
 #endif
+#endif /* GL_ANGLE_robust_client_memory */
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __gl2ext_h_ */
+#endif
diff --git a/src/third_party/angle/include/GLES2/gl2platform.h b/src/third_party/angle/include/GLES2/gl2platform.h
index c9fa3c4..da415f1 100644
--- a/src/third_party/angle/include/GLES2/gl2platform.h
+++ b/src/third_party/angle/include/GLES2/gl2platform.h
@@ -1,7 +1,7 @@
 #ifndef __gl2platform_h_
 #define __gl2platform_h_
 
-/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
 
 /*
  * This document is licensed under the SGI Free Software B License Version
@@ -19,9 +19,15 @@
 
 #include <KHR/khrplatform.h>
 
+#if defined(STARBOARD)
+// Don't trust any previous definitions of GL_APICALL. We really want nothing.
+#undef GL_APICALL
+#define GL_APICALL  /* nothing */
+#else
 #ifndef GL_APICALL
 #define GL_APICALL  KHRONOS_APICALL
 #endif
+#endif  // defined(STARBOARD)
 
 #ifndef GL_APIENTRY
 #define GL_APIENTRY KHRONOS_APIENTRY
diff --git a/src/third_party/angle/include/GLES3/gl3.h b/src/third_party/angle/include/GLES3/gl3.h
new file mode 100644
index 0000000..53c59b8
--- /dev/null
+++ b/src/third_party/angle/include/GLES3/gl3.h
@@ -0,0 +1,1209 @@
+#ifndef __gl3_h_
+#define __gl3_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/
+**
+** Khronos $Revision: 31811 $ on $Date: 2015-08-10 00:01:11 -0700 (Mon, 10 Aug 2015) $
+*/
+
+#include <GLES3/gl3platform.h>
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/* Generated on date 20150809 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]|3\.0
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_ES_VERSION_2_0
+#define GL_ES_VERSION_2_0 1
+#include <KHR/khrplatform.h>
+typedef khronos_int8_t GLbyte;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef short GLshort;
+typedef unsigned short GLushort;
+typedef void GLvoid;
+typedef struct __GLsync *GLsync;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef khronos_float_t GLfloat;
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_intptr_t GLintptr;
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+#define GL_GENERATE_MIPMAP_HINT           0x8192
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+#define GL_FRAGMENT_SHADER                0x8B30
+#define GL_VERTEX_SHADER                  0x8B31
+#define GL_MAX_VERTEX_ATTRIBS             0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS     0x8DFB
+#define GL_MAX_VARYING_VECTORS            0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS        0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS   0x8DFD
+#define GL_SHADER_TYPE                    0x8B4F
+#define GL_DELETE_STATUS                  0x8B80
+#define GL_LINK_STATUS                    0x8B82
+#define GL_VALIDATE_STATUS                0x8B83
+#define GL_ATTACHED_SHADERS               0x8B85
+#define GL_ACTIVE_UNIFORMS                0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH      0x8B87
+#define GL_ACTIVE_ATTRIBUTES              0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH    0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION       0x8B8C
+#define GL_CURRENT_PROGRAM                0x8B8D
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+#define GL_TEXTURE                        0x1702
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX8                 0x8D48
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+#define GL_NONE                           0
+#define GL_FRAMEBUFFER_COMPLETE           0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED        0x8CDD
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ES_VERSION_2_0 */
+
+#ifndef GL_ES_VERSION_3_0
+#define GL_ES_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_READ_BUFFER                    0x0C02
+#define GL_UNPACK_ROW_LENGTH              0x0CF2
+#define GL_UNPACK_SKIP_ROWS               0x0CF3
+#define GL_UNPACK_SKIP_PIXELS             0x0CF4
+#define GL_PACK_ROW_LENGTH                0x0D02
+#define GL_PACK_SKIP_ROWS                 0x0D03
+#define GL_PACK_SKIP_PIXELS               0x0D04
+#define GL_COLOR                          0x1800
+#define GL_DEPTH                          0x1801
+#define GL_STENCIL                        0x1802
+#define GL_RED                            0x1903
+#define GL_RGB8                           0x8051
+#define GL_RGBA8                          0x8058
+#define GL_RGB10_A2                       0x8059
+#define GL_TEXTURE_BINDING_3D             0x806A
+#define GL_UNPACK_SKIP_IMAGES             0x806D
+#define GL_UNPACK_IMAGE_HEIGHT            0x806E
+#define GL_TEXTURE_3D                     0x806F
+#define GL_TEXTURE_WRAP_R                 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE            0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368
+#define GL_MAX_ELEMENTS_VERTICES          0x80E8
+#define GL_MAX_ELEMENTS_INDICES           0x80E9
+#define GL_TEXTURE_MIN_LOD                0x813A
+#define GL_TEXTURE_MAX_LOD                0x813B
+#define GL_TEXTURE_BASE_LEVEL             0x813C
+#define GL_TEXTURE_MAX_LEVEL              0x813D
+#define GL_MIN                            0x8007
+#define GL_MAX                            0x8008
+#define GL_DEPTH_COMPONENT24              0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS           0x84FD
+#define GL_TEXTURE_COMPARE_MODE           0x884C
+#define GL_TEXTURE_COMPARE_FUNC           0x884D
+#define GL_CURRENT_QUERY                  0x8865
+#define GL_QUERY_RESULT                   0x8866
+#define GL_QUERY_RESULT_AVAILABLE         0x8867
+#define GL_BUFFER_MAPPED                  0x88BC
+#define GL_BUFFER_MAP_POINTER             0x88BD
+#define GL_STREAM_READ                    0x88E1
+#define GL_STREAM_COPY                    0x88E2
+#define GL_STATIC_READ                    0x88E5
+#define GL_STATIC_COPY                    0x88E6
+#define GL_DYNAMIC_READ                   0x88E9
+#define GL_DYNAMIC_COPY                   0x88EA
+#define GL_MAX_DRAW_BUFFERS               0x8824
+#define GL_DRAW_BUFFER0                   0x8825
+#define GL_DRAW_BUFFER1                   0x8826
+#define GL_DRAW_BUFFER2                   0x8827
+#define GL_DRAW_BUFFER3                   0x8828
+#define GL_DRAW_BUFFER4                   0x8829
+#define GL_DRAW_BUFFER5                   0x882A
+#define GL_DRAW_BUFFER6                   0x882B
+#define GL_DRAW_BUFFER7                   0x882C
+#define GL_DRAW_BUFFER8                   0x882D
+#define GL_DRAW_BUFFER9                   0x882E
+#define GL_DRAW_BUFFER10                  0x882F
+#define GL_DRAW_BUFFER11                  0x8830
+#define GL_DRAW_BUFFER12                  0x8831
+#define GL_DRAW_BUFFER13                  0x8832
+#define GL_DRAW_BUFFER14                  0x8833
+#define GL_DRAW_BUFFER15                  0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS  0x8B4A
+#define GL_SAMPLER_3D                     0x8B5F
+#define GL_SAMPLER_2D_SHADOW              0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_PIXEL_PACK_BUFFER              0x88EB
+#define GL_PIXEL_UNPACK_BUFFER            0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING      0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING    0x88EF
+#define GL_FLOAT_MAT2x3                   0x8B65
+#define GL_FLOAT_MAT2x4                   0x8B66
+#define GL_FLOAT_MAT3x2                   0x8B67
+#define GL_FLOAT_MAT3x4                   0x8B68
+#define GL_FLOAT_MAT4x2                   0x8B69
+#define GL_FLOAT_MAT4x3                   0x8B6A
+#define GL_SRGB                           0x8C40
+#define GL_SRGB8                          0x8C41
+#define GL_SRGB8_ALPHA8                   0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE         0x884E
+#define GL_MAJOR_VERSION                  0x821B
+#define GL_MINOR_VERSION                  0x821C
+#define GL_NUM_EXTENSIONS                 0x821D
+#define GL_RGBA32F                        0x8814
+#define GL_RGB32F                         0x8815
+#define GL_RGBA16F                        0x881A
+#define GL_RGB16F                         0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER    0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS       0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET       0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET       0x8905
+#define GL_MAX_VARYING_COMPONENTS         0x8B4B
+#define GL_TEXTURE_2D_ARRAY               0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY       0x8C1D
+#define GL_R11F_G11F_B10F                 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV   0x8C3B
+#define GL_RGB9_E5                        0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV       0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS    0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD             0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS            0x8C8C
+#define GL_SEPARATE_ATTRIBS               0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER      0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI                       0x8D70
+#define GL_RGB32UI                        0x8D71
+#define GL_RGBA16UI                       0x8D76
+#define GL_RGB16UI                        0x8D77
+#define GL_RGBA8UI                        0x8D7C
+#define GL_RGB8UI                         0x8D7D
+#define GL_RGBA32I                        0x8D82
+#define GL_RGB32I                         0x8D83
+#define GL_RGBA16I                        0x8D88
+#define GL_RGB16I                         0x8D89
+#define GL_RGBA8I                         0x8D8E
+#define GL_RGB8I                          0x8D8F
+#define GL_RED_INTEGER                    0x8D94
+#define GL_RGB_INTEGER                    0x8D98
+#define GL_RGBA_INTEGER                   0x8D99
+#define GL_SAMPLER_2D_ARRAY               0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW        0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW            0x8DC5
+#define GL_UNSIGNED_INT_VEC2              0x8DC6
+#define GL_UNSIGNED_INT_VEC3              0x8DC7
+#define GL_UNSIGNED_INT_VEC4              0x8DC8
+#define GL_INT_SAMPLER_2D                 0x8DCA
+#define GL_INT_SAMPLER_3D                 0x8DCB
+#define GL_INT_SAMPLER_CUBE               0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY           0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D        0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D        0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE      0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY  0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS            0x911F
+#define GL_BUFFER_MAP_LENGTH              0x9120
+#define GL_BUFFER_MAP_OFFSET              0x9121
+#define GL_DEPTH_COMPONENT32F             0x8CAC
+#define GL_DEPTH32F_STENCIL8              0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT            0x8218
+#define GL_FRAMEBUFFER_UNDEFINED          0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT       0x821A
+#define GL_DEPTH_STENCIL                  0x84F9
+#define GL_UNSIGNED_INT_24_8              0x84FA
+#define GL_DEPTH24_STENCIL8               0x88F0
+#define GL_UNSIGNED_NORMALIZED            0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING       0x8CA6
+#define GL_READ_FRAMEBUFFER               0x8CA8
+#define GL_DRAW_FRAMEBUFFER               0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING       0x8CAA
+#define GL_RENDERBUFFER_SAMPLES           0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS          0x8CDF
+#define GL_COLOR_ATTACHMENT1              0x8CE1
+#define GL_COLOR_ATTACHMENT2              0x8CE2
+#define GL_COLOR_ATTACHMENT3              0x8CE3
+#define GL_COLOR_ATTACHMENT4              0x8CE4
+#define GL_COLOR_ATTACHMENT5              0x8CE5
+#define GL_COLOR_ATTACHMENT6              0x8CE6
+#define GL_COLOR_ATTACHMENT7              0x8CE7
+#define GL_COLOR_ATTACHMENT8              0x8CE8
+#define GL_COLOR_ATTACHMENT9              0x8CE9
+#define GL_COLOR_ATTACHMENT10             0x8CEA
+#define GL_COLOR_ATTACHMENT11             0x8CEB
+#define GL_COLOR_ATTACHMENT12             0x8CEC
+#define GL_COLOR_ATTACHMENT13             0x8CED
+#define GL_COLOR_ATTACHMENT14             0x8CEE
+#define GL_COLOR_ATTACHMENT15             0x8CEF
+#define GL_COLOR_ATTACHMENT16             0x8CF0
+#define GL_COLOR_ATTACHMENT17             0x8CF1
+#define GL_COLOR_ATTACHMENT18             0x8CF2
+#define GL_COLOR_ATTACHMENT19             0x8CF3
+#define GL_COLOR_ATTACHMENT20             0x8CF4
+#define GL_COLOR_ATTACHMENT21             0x8CF5
+#define GL_COLOR_ATTACHMENT22             0x8CF6
+#define GL_COLOR_ATTACHMENT23             0x8CF7
+#define GL_COLOR_ATTACHMENT24             0x8CF8
+#define GL_COLOR_ATTACHMENT25             0x8CF9
+#define GL_COLOR_ATTACHMENT26             0x8CFA
+#define GL_COLOR_ATTACHMENT27             0x8CFB
+#define GL_COLOR_ATTACHMENT28             0x8CFC
+#define GL_COLOR_ATTACHMENT29             0x8CFD
+#define GL_COLOR_ATTACHMENT30             0x8CFE
+#define GL_COLOR_ATTACHMENT31             0x8CFF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES                    0x8D57
+#define GL_HALF_FLOAT                     0x140B
+#define GL_MAP_READ_BIT                   0x0001
+#define GL_MAP_WRITE_BIT                  0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT       0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT      0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT         0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT         0x0020
+#define GL_RG                             0x8227
+#define GL_RG_INTEGER                     0x8228
+#define GL_R8                             0x8229
+#define GL_RG8                            0x822B
+#define GL_R16F                           0x822D
+#define GL_R32F                           0x822E
+#define GL_RG16F                          0x822F
+#define GL_RG32F                          0x8230
+#define GL_R8I                            0x8231
+#define GL_R8UI                           0x8232
+#define GL_R16I                           0x8233
+#define GL_R16UI                          0x8234
+#define GL_R32I                           0x8235
+#define GL_R32UI                          0x8236
+#define GL_RG8I                           0x8237
+#define GL_RG8UI                          0x8238
+#define GL_RG16I                          0x8239
+#define GL_RG16UI                         0x823A
+#define GL_RG32I                          0x823B
+#define GL_RG32UI                         0x823C
+#define GL_VERTEX_ARRAY_BINDING           0x85B5
+#define GL_R8_SNORM                       0x8F94
+#define GL_RG8_SNORM                      0x8F95
+#define GL_RGB8_SNORM                     0x8F96
+#define GL_RGBA8_SNORM                    0x8F97
+#define GL_SIGNED_NORMALIZED              0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX  0x8D69
+#define GL_COPY_READ_BUFFER               0x8F36
+#define GL_COPY_WRITE_BUFFER              0x8F37
+#define GL_COPY_READ_BUFFER_BINDING       0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING      0x8F37
+#define GL_UNIFORM_BUFFER                 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING         0x8A28
+#define GL_UNIFORM_BUFFER_START           0x8A29
+#define GL_UNIFORM_BUFFER_SIZE            0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS      0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS    0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS    0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS    0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE         0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS          0x8A36
+#define GL_UNIFORM_TYPE                   0x8A37
+#define GL_UNIFORM_SIZE                   0x8A38
+#define GL_UNIFORM_NAME_LENGTH            0x8A39
+#define GL_UNIFORM_BLOCK_INDEX            0x8A3A
+#define GL_UNIFORM_OFFSET                 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE           0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE          0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR           0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING          0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE        0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH      0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS  0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX                  0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS   0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS  0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT        0x9111
+#define GL_OBJECT_TYPE                    0x9112
+#define GL_SYNC_CONDITION                 0x9113
+#define GL_SYNC_STATUS                    0x9114
+#define GL_SYNC_FLAGS                     0x9115
+#define GL_SYNC_FENCE                     0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE     0x9117
+#define GL_UNSIGNALED                     0x9118
+#define GL_SIGNALED                       0x9119
+#define GL_ALREADY_SIGNALED               0x911A
+#define GL_TIMEOUT_EXPIRED                0x911B
+#define GL_CONDITION_SATISFIED            0x911C
+#define GL_WAIT_FAILED                    0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT        0x00000001
+#define GL_TIMEOUT_IGNORED                0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR    0x88FE
+#define GL_ANY_SAMPLES_PASSED             0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_SAMPLER_BINDING                0x8919
+#define GL_RGB10_A2UI                     0x906F
+#define GL_TEXTURE_SWIZZLE_R              0x8E42
+#define GL_TEXTURE_SWIZZLE_G              0x8E43
+#define GL_TEXTURE_SWIZZLE_B              0x8E44
+#define GL_TEXTURE_SWIZZLE_A              0x8E45
+#define GL_GREEN                          0x1904
+#define GL_BLUE                           0x1905
+#define GL_INT_2_10_10_10_REV             0x8D9F
+#define GL_TRANSFORM_FEEDBACK             0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED      0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE      0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING     0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH          0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS     0x87FE
+#define GL_PROGRAM_BINARY_FORMATS         0x87FF
+#define GL_COMPRESSED_R11_EAC             0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC      0x9271
+#define GL_COMPRESSED_RG11_EAC            0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC     0x9273
+#define GL_COMPRESSED_RGB8_ETC2           0x9274
+#define GL_COMPRESSED_SRGB8_ETC2          0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC      0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT       0x912F
+#define GL_MAX_ELEMENT_INDEX              0x8D6B
+#define GL_NUM_SAMPLE_COUNTS              0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
+typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
+GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GL_APICALL void GL_APIENTRY glEndTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler);
+GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id);
+GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_ES_VERSION_3_0 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/third_party/angle/include/GLES3/gl31.h b/src/third_party/angle/include/GLES3/gl31.h
new file mode 100644
index 0000000..26f869b
--- /dev/null
+++ b/src/third_party/angle/include/GLES3/gl31.h
@@ -0,0 +1,1524 @@
+#ifndef __gl31_h_
+#define __gl31_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/
+**
+** Khronos $Revision$ on $Date$
+*/
+
+#include <GLES3/gl3platform.h>
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/* Generated on date 20150809 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]|3\.[01]
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_ES_VERSION_2_0
+#define GL_ES_VERSION_2_0 1
+#include <KHR/khrplatform.h>
+typedef khronos_int8_t GLbyte;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef short GLshort;
+typedef unsigned short GLushort;
+typedef void GLvoid;
+typedef struct __GLsync *GLsync;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef khronos_float_t GLfloat;
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_intptr_t GLintptr;
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+#define GL_GENERATE_MIPMAP_HINT           0x8192
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+#define GL_FRAGMENT_SHADER                0x8B30
+#define GL_VERTEX_SHADER                  0x8B31
+#define GL_MAX_VERTEX_ATTRIBS             0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS     0x8DFB
+#define GL_MAX_VARYING_VECTORS            0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS        0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS   0x8DFD
+#define GL_SHADER_TYPE                    0x8B4F
+#define GL_DELETE_STATUS                  0x8B80
+#define GL_LINK_STATUS                    0x8B82
+#define GL_VALIDATE_STATUS                0x8B83
+#define GL_ATTACHED_SHADERS               0x8B85
+#define GL_ACTIVE_UNIFORMS                0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH      0x8B87
+#define GL_ACTIVE_ATTRIBUTES              0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH    0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION       0x8B8C
+#define GL_CURRENT_PROGRAM                0x8B8D
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+#define GL_TEXTURE                        0x1702
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX8                 0x8D48
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+#define GL_NONE                           0
+#define GL_FRAMEBUFFER_COMPLETE           0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED        0x8CDD
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ES_VERSION_2_0 */
+
+#ifndef GL_ES_VERSION_3_0
+#define GL_ES_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_READ_BUFFER                    0x0C02
+#define GL_UNPACK_ROW_LENGTH              0x0CF2
+#define GL_UNPACK_SKIP_ROWS               0x0CF3
+#define GL_UNPACK_SKIP_PIXELS             0x0CF4
+#define GL_PACK_ROW_LENGTH                0x0D02
+#define GL_PACK_SKIP_ROWS                 0x0D03
+#define GL_PACK_SKIP_PIXELS               0x0D04
+#define GL_COLOR                          0x1800
+#define GL_DEPTH                          0x1801
+#define GL_STENCIL                        0x1802
+#define GL_RED                            0x1903
+#define GL_RGB8                           0x8051
+#define GL_RGBA8                          0x8058
+#define GL_RGB10_A2                       0x8059
+#define GL_TEXTURE_BINDING_3D             0x806A
+#define GL_UNPACK_SKIP_IMAGES             0x806D
+#define GL_UNPACK_IMAGE_HEIGHT            0x806E
+#define GL_TEXTURE_3D                     0x806F
+#define GL_TEXTURE_WRAP_R                 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE            0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368
+#define GL_MAX_ELEMENTS_VERTICES          0x80E8
+#define GL_MAX_ELEMENTS_INDICES           0x80E9
+#define GL_TEXTURE_MIN_LOD                0x813A
+#define GL_TEXTURE_MAX_LOD                0x813B
+#define GL_TEXTURE_BASE_LEVEL             0x813C
+#define GL_TEXTURE_MAX_LEVEL              0x813D
+#define GL_MIN                            0x8007
+#define GL_MAX                            0x8008
+#define GL_DEPTH_COMPONENT24              0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS           0x84FD
+#define GL_TEXTURE_COMPARE_MODE           0x884C
+#define GL_TEXTURE_COMPARE_FUNC           0x884D
+#define GL_CURRENT_QUERY                  0x8865
+#define GL_QUERY_RESULT                   0x8866
+#define GL_QUERY_RESULT_AVAILABLE         0x8867
+#define GL_BUFFER_MAPPED                  0x88BC
+#define GL_BUFFER_MAP_POINTER             0x88BD
+#define GL_STREAM_READ                    0x88E1
+#define GL_STREAM_COPY                    0x88E2
+#define GL_STATIC_READ                    0x88E5
+#define GL_STATIC_COPY                    0x88E6
+#define GL_DYNAMIC_READ                   0x88E9
+#define GL_DYNAMIC_COPY                   0x88EA
+#define GL_MAX_DRAW_BUFFERS               0x8824
+#define GL_DRAW_BUFFER0                   0x8825
+#define GL_DRAW_BUFFER1                   0x8826
+#define GL_DRAW_BUFFER2                   0x8827
+#define GL_DRAW_BUFFER3                   0x8828
+#define GL_DRAW_BUFFER4                   0x8829
+#define GL_DRAW_BUFFER5                   0x882A
+#define GL_DRAW_BUFFER6                   0x882B
+#define GL_DRAW_BUFFER7                   0x882C
+#define GL_DRAW_BUFFER8                   0x882D
+#define GL_DRAW_BUFFER9                   0x882E
+#define GL_DRAW_BUFFER10                  0x882F
+#define GL_DRAW_BUFFER11                  0x8830
+#define GL_DRAW_BUFFER12                  0x8831
+#define GL_DRAW_BUFFER13                  0x8832
+#define GL_DRAW_BUFFER14                  0x8833
+#define GL_DRAW_BUFFER15                  0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS  0x8B4A
+#define GL_SAMPLER_3D                     0x8B5F
+#define GL_SAMPLER_2D_SHADOW              0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_PIXEL_PACK_BUFFER              0x88EB
+#define GL_PIXEL_UNPACK_BUFFER            0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING      0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING    0x88EF
+#define GL_FLOAT_MAT2x3                   0x8B65
+#define GL_FLOAT_MAT2x4                   0x8B66
+#define GL_FLOAT_MAT3x2                   0x8B67
+#define GL_FLOAT_MAT3x4                   0x8B68
+#define GL_FLOAT_MAT4x2                   0x8B69
+#define GL_FLOAT_MAT4x3                   0x8B6A
+#define GL_SRGB                           0x8C40
+#define GL_SRGB8                          0x8C41
+#define GL_SRGB8_ALPHA8                   0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE         0x884E
+#define GL_MAJOR_VERSION                  0x821B
+#define GL_MINOR_VERSION                  0x821C
+#define GL_NUM_EXTENSIONS                 0x821D
+#define GL_RGBA32F                        0x8814
+#define GL_RGB32F                         0x8815
+#define GL_RGBA16F                        0x881A
+#define GL_RGB16F                         0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER    0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS       0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET       0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET       0x8905
+#define GL_MAX_VARYING_COMPONENTS         0x8B4B
+#define GL_TEXTURE_2D_ARRAY               0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY       0x8C1D
+#define GL_R11F_G11F_B10F                 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV   0x8C3B
+#define GL_RGB9_E5                        0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV       0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS    0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD             0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS            0x8C8C
+#define GL_SEPARATE_ATTRIBS               0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER      0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI                       0x8D70
+#define GL_RGB32UI                        0x8D71
+#define GL_RGBA16UI                       0x8D76
+#define GL_RGB16UI                        0x8D77
+#define GL_RGBA8UI                        0x8D7C
+#define GL_RGB8UI                         0x8D7D
+#define GL_RGBA32I                        0x8D82
+#define GL_RGB32I                         0x8D83
+#define GL_RGBA16I                        0x8D88
+#define GL_RGB16I                         0x8D89
+#define GL_RGBA8I                         0x8D8E
+#define GL_RGB8I                          0x8D8F
+#define GL_RED_INTEGER                    0x8D94
+#define GL_RGB_INTEGER                    0x8D98
+#define GL_RGBA_INTEGER                   0x8D99
+#define GL_SAMPLER_2D_ARRAY               0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW        0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW            0x8DC5
+#define GL_UNSIGNED_INT_VEC2              0x8DC6
+#define GL_UNSIGNED_INT_VEC3              0x8DC7
+#define GL_UNSIGNED_INT_VEC4              0x8DC8
+#define GL_INT_SAMPLER_2D                 0x8DCA
+#define GL_INT_SAMPLER_3D                 0x8DCB
+#define GL_INT_SAMPLER_CUBE               0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY           0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D        0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D        0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE      0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY  0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS            0x911F
+#define GL_BUFFER_MAP_LENGTH              0x9120
+#define GL_BUFFER_MAP_OFFSET              0x9121
+#define GL_DEPTH_COMPONENT32F             0x8CAC
+#define GL_DEPTH32F_STENCIL8              0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT            0x8218
+#define GL_FRAMEBUFFER_UNDEFINED          0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT       0x821A
+#define GL_DEPTH_STENCIL                  0x84F9
+#define GL_UNSIGNED_INT_24_8              0x84FA
+#define GL_DEPTH24_STENCIL8               0x88F0
+#define GL_UNSIGNED_NORMALIZED            0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING       0x8CA6
+#define GL_READ_FRAMEBUFFER               0x8CA8
+#define GL_DRAW_FRAMEBUFFER               0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING       0x8CAA
+#define GL_RENDERBUFFER_SAMPLES           0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS          0x8CDF
+#define GL_COLOR_ATTACHMENT1              0x8CE1
+#define GL_COLOR_ATTACHMENT2              0x8CE2
+#define GL_COLOR_ATTACHMENT3              0x8CE3
+#define GL_COLOR_ATTACHMENT4              0x8CE4
+#define GL_COLOR_ATTACHMENT5              0x8CE5
+#define GL_COLOR_ATTACHMENT6              0x8CE6
+#define GL_COLOR_ATTACHMENT7              0x8CE7
+#define GL_COLOR_ATTACHMENT8              0x8CE8
+#define GL_COLOR_ATTACHMENT9              0x8CE9
+#define GL_COLOR_ATTACHMENT10             0x8CEA
+#define GL_COLOR_ATTACHMENT11             0x8CEB
+#define GL_COLOR_ATTACHMENT12             0x8CEC
+#define GL_COLOR_ATTACHMENT13             0x8CED
+#define GL_COLOR_ATTACHMENT14             0x8CEE
+#define GL_COLOR_ATTACHMENT15             0x8CEF
+#define GL_COLOR_ATTACHMENT16             0x8CF0
+#define GL_COLOR_ATTACHMENT17             0x8CF1
+#define GL_COLOR_ATTACHMENT18             0x8CF2
+#define GL_COLOR_ATTACHMENT19             0x8CF3
+#define GL_COLOR_ATTACHMENT20             0x8CF4
+#define GL_COLOR_ATTACHMENT21             0x8CF5
+#define GL_COLOR_ATTACHMENT22             0x8CF6
+#define GL_COLOR_ATTACHMENT23             0x8CF7
+#define GL_COLOR_ATTACHMENT24             0x8CF8
+#define GL_COLOR_ATTACHMENT25             0x8CF9
+#define GL_COLOR_ATTACHMENT26             0x8CFA
+#define GL_COLOR_ATTACHMENT27             0x8CFB
+#define GL_COLOR_ATTACHMENT28             0x8CFC
+#define GL_COLOR_ATTACHMENT29             0x8CFD
+#define GL_COLOR_ATTACHMENT30             0x8CFE
+#define GL_COLOR_ATTACHMENT31             0x8CFF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES                    0x8D57
+#define GL_HALF_FLOAT                     0x140B
+#define GL_MAP_READ_BIT                   0x0001
+#define GL_MAP_WRITE_BIT                  0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT       0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT      0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT         0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT         0x0020
+#define GL_RG                             0x8227
+#define GL_RG_INTEGER                     0x8228
+#define GL_R8                             0x8229
+#define GL_RG8                            0x822B
+#define GL_R16F                           0x822D
+#define GL_R32F                           0x822E
+#define GL_RG16F                          0x822F
+#define GL_RG32F                          0x8230
+#define GL_R8I                            0x8231
+#define GL_R8UI                           0x8232
+#define GL_R16I                           0x8233
+#define GL_R16UI                          0x8234
+#define GL_R32I                           0x8235
+#define GL_R32UI                          0x8236
+#define GL_RG8I                           0x8237
+#define GL_RG8UI                          0x8238
+#define GL_RG16I                          0x8239
+#define GL_RG16UI                         0x823A
+#define GL_RG32I                          0x823B
+#define GL_RG32UI                         0x823C
+#define GL_VERTEX_ARRAY_BINDING           0x85B5
+#define GL_R8_SNORM                       0x8F94
+#define GL_RG8_SNORM                      0x8F95
+#define GL_RGB8_SNORM                     0x8F96
+#define GL_RGBA8_SNORM                    0x8F97
+#define GL_SIGNED_NORMALIZED              0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX  0x8D69
+#define GL_COPY_READ_BUFFER               0x8F36
+#define GL_COPY_WRITE_BUFFER              0x8F37
+#define GL_COPY_READ_BUFFER_BINDING       0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING      0x8F37
+#define GL_UNIFORM_BUFFER                 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING         0x8A28
+#define GL_UNIFORM_BUFFER_START           0x8A29
+#define GL_UNIFORM_BUFFER_SIZE            0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS      0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS    0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS    0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS    0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE         0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS          0x8A36
+#define GL_UNIFORM_TYPE                   0x8A37
+#define GL_UNIFORM_SIZE                   0x8A38
+#define GL_UNIFORM_NAME_LENGTH            0x8A39
+#define GL_UNIFORM_BLOCK_INDEX            0x8A3A
+#define GL_UNIFORM_OFFSET                 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE           0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE          0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR           0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING          0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE        0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH      0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS  0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX                  0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS   0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS  0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT        0x9111
+#define GL_OBJECT_TYPE                    0x9112
+#define GL_SYNC_CONDITION                 0x9113
+#define GL_SYNC_STATUS                    0x9114
+#define GL_SYNC_FLAGS                     0x9115
+#define GL_SYNC_FENCE                     0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE     0x9117
+#define GL_UNSIGNALED                     0x9118
+#define GL_SIGNALED                       0x9119
+#define GL_ALREADY_SIGNALED               0x911A
+#define GL_TIMEOUT_EXPIRED                0x911B
+#define GL_CONDITION_SATISFIED            0x911C
+#define GL_WAIT_FAILED                    0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT        0x00000001
+#define GL_TIMEOUT_IGNORED                0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR    0x88FE
+#define GL_ANY_SAMPLES_PASSED             0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_SAMPLER_BINDING                0x8919
+#define GL_RGB10_A2UI                     0x906F
+#define GL_TEXTURE_SWIZZLE_R              0x8E42
+#define GL_TEXTURE_SWIZZLE_G              0x8E43
+#define GL_TEXTURE_SWIZZLE_B              0x8E44
+#define GL_TEXTURE_SWIZZLE_A              0x8E45
+#define GL_GREEN                          0x1904
+#define GL_BLUE                           0x1905
+#define GL_INT_2_10_10_10_REV             0x8D9F
+#define GL_TRANSFORM_FEEDBACK             0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED      0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE      0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING     0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH          0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS     0x87FE
+#define GL_PROGRAM_BINARY_FORMATS         0x87FF
+#define GL_COMPRESSED_R11_EAC             0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC      0x9271
+#define GL_COMPRESSED_RG11_EAC            0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC     0x9273
+#define GL_COMPRESSED_RGB8_ETC2           0x9274
+#define GL_COMPRESSED_SRGB8_ETC2          0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC      0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT       0x912F
+#define GL_MAX_ELEMENT_INDEX              0x8D6B
+#define GL_NUM_SAMPLE_COUNTS              0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
+typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
+GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GL_APICALL void GL_APIENTRY glEndTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler);
+GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id);
+GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_ES_VERSION_3_0 */
+
+#ifndef GL_ES_VERSION_3_1
+#define GL_ES_VERSION_3_1 1
+#define GL_COMPUTE_SHADER                 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS     0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS     0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS    0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT   0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE    0x91BF
+#define GL_COMPUTE_WORK_GROUP_SIZE        0x8267
+#define GL_DISPATCH_INDIRECT_BUFFER       0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER_BIT             0x00000020
+#define GL_DRAW_INDIRECT_BUFFER           0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING   0x8F43
+#define GL_MAX_UNIFORM_LOCATIONS          0x826E
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH      0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT     0x9311
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES    0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH          0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT         0x9316
+#define GL_MAX_FRAMEBUFFER_SAMPLES        0x9318
+#define GL_UNIFORM                        0x92E1
+#define GL_UNIFORM_BLOCK                  0x92E2
+#define GL_PROGRAM_INPUT                  0x92E3
+#define GL_PROGRAM_OUTPUT                 0x92E4
+#define GL_BUFFER_VARIABLE                0x92E5
+#define GL_SHADER_STORAGE_BLOCK           0x92E6
+#define GL_ATOMIC_COUNTER_BUFFER          0x92C0
+#define GL_TRANSFORM_FEEDBACK_VARYING     0x92F4
+#define GL_ACTIVE_RESOURCES               0x92F5
+#define GL_MAX_NAME_LENGTH                0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES       0x92F7
+#define GL_NAME_LENGTH                    0x92F9
+#define GL_TYPE                           0x92FA
+#define GL_ARRAY_SIZE                     0x92FB
+#define GL_OFFSET                         0x92FC
+#define GL_BLOCK_INDEX                    0x92FD
+#define GL_ARRAY_STRIDE                   0x92FE
+#define GL_MATRIX_STRIDE                  0x92FF
+#define GL_IS_ROW_MAJOR                   0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX    0x9301
+#define GL_BUFFER_BINDING                 0x9302
+#define GL_BUFFER_DATA_SIZE               0x9303
+#define GL_NUM_ACTIVE_VARIABLES           0x9304
+#define GL_ACTIVE_VARIABLES               0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER    0x9306
+#define GL_REFERENCED_BY_FRAGMENT_SHADER  0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER   0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE           0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE         0x930D
+#define GL_LOCATION                       0x930E
+#define GL_VERTEX_SHADER_BIT              0x00000001
+#define GL_FRAGMENT_SHADER_BIT            0x00000002
+#define GL_ALL_SHADER_BITS                0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE              0x8258
+#define GL_ACTIVE_PROGRAM                 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING       0x825A
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING  0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START    0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE     0x92C3
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS     0x92D2
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS   0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS   0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS  0x92D9
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER    0x92DB
+#define GL_MAX_IMAGE_UNITS                0x8F38
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS      0x90CA
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS    0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS    0x90CF
+#define GL_IMAGE_BINDING_NAME             0x8F3A
+#define GL_IMAGE_BINDING_LEVEL            0x8F3B
+#define GL_IMAGE_BINDING_LAYERED          0x8F3C
+#define GL_IMAGE_BINDING_LAYER            0x8F3D
+#define GL_IMAGE_BINDING_ACCESS           0x8F3E
+#define GL_IMAGE_BINDING_FORMAT           0x906E
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT      0x00000002
+#define GL_UNIFORM_BARRIER_BIT            0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT      0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT            0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT       0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT     0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT      0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT        0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT     0x00001000
+#define GL_ALL_BARRIER_BITS               0xFFFFFFFF
+#define GL_IMAGE_2D                       0x904D
+#define GL_IMAGE_3D                       0x904E
+#define GL_IMAGE_CUBE                     0x9050
+#define GL_IMAGE_2D_ARRAY                 0x9053
+#define GL_INT_IMAGE_2D                   0x9058
+#define GL_INT_IMAGE_3D                   0x9059
+#define GL_INT_IMAGE_CUBE                 0x905B
+#define GL_INT_IMAGE_2D_ARRAY             0x905E
+#define GL_UNSIGNED_INT_IMAGE_2D          0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D          0x9064
+#define GL_UNSIGNED_INT_IMAGE_CUBE        0x9066
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY    0x9069
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_READ_ONLY                      0x88B8
+#define GL_WRITE_ONLY                     0x88B9
+#define GL_READ_WRITE                     0x88BA
+#define GL_SHADER_STORAGE_BUFFER          0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING  0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START    0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE     0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE  0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT     0x00002000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_DEPTH_STENCIL_TEXTURE_MODE     0x90EA
+#define GL_STENCIL_INDEX                  0x1901
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_SAMPLE_POSITION                0x8E50
+#define GL_SAMPLE_MASK                    0x8E51
+#define GL_SAMPLE_MASK_VALUE              0x8E52
+#define GL_TEXTURE_2D_MULTISAMPLE         0x9100
+#define GL_MAX_SAMPLE_MASK_WORDS          0x8E59
+#define GL_MAX_COLOR_TEXTURE_SAMPLES      0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES      0x910F
+#define GL_MAX_INTEGER_SAMPLES            0x9110
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_SAMPLES                0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_WIDTH                  0x1000
+#define GL_TEXTURE_HEIGHT                 0x1001
+#define GL_TEXTURE_DEPTH                  0x8071
+#define GL_TEXTURE_INTERNAL_FORMAT        0x1003
+#define GL_TEXTURE_RED_SIZE               0x805C
+#define GL_TEXTURE_GREEN_SIZE             0x805D
+#define GL_TEXTURE_BLUE_SIZE              0x805E
+#define GL_TEXTURE_ALPHA_SIZE             0x805F
+#define GL_TEXTURE_DEPTH_SIZE             0x884A
+#define GL_TEXTURE_STENCIL_SIZE           0x88F1
+#define GL_TEXTURE_SHARED_SIZE            0x8C3F
+#define GL_TEXTURE_RED_TYPE               0x8C10
+#define GL_TEXTURE_GREEN_TYPE             0x8C11
+#define GL_TEXTURE_BLUE_TYPE              0x8C12
+#define GL_TEXTURE_ALPHA_TYPE             0x8C13
+#define GL_TEXTURE_DEPTH_TYPE             0x8C16
+#define GL_TEXTURE_COMPRESSED             0x86A1
+#define GL_SAMPLER_2D_MULTISAMPLE         0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE     0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_VERTEX_ATTRIB_BINDING          0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET  0x82D5
+#define GL_VERTEX_BINDING_DIVISOR         0x82D6
+#define GL_VERTEX_BINDING_OFFSET          0x82D7
+#define GL_VERTEX_BINDING_STRIDE          0x82D8
+#define GL_VERTEX_BINDING_BUFFER          0x8F4F
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS     0x82DA
+#define GL_MAX_VERTEX_ATTRIB_STRIDE       0x82E5
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (GL_APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
+GL_APICALL void GL_APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect);
+GL_APICALL void GL_APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GL_APICALL void GL_APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GL_APICALL void GL_APIENTRY glMemoryBarrier (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glMemoryBarrierByRegion (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GL_APICALL void GL_APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GL_APICALL void GL_APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GL_APICALL void GL_APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GL_APICALL void GL_APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+#endif
+#endif /* GL_ES_VERSION_3_1 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/third_party/angle/include/GLES3/gl32.h b/src/third_party/angle/include/GLES3/gl32.h
new file mode 100644
index 0000000..2975a6f
--- /dev/null
+++ b/src/third_party/angle/include/GLES3/gl32.h
@@ -0,0 +1,1825 @@
+#ifndef __gl32_h_
+#define __gl32_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/
+**
+** Khronos $Revision$ on $Date$
+*/
+
+#include <GLES3/gl3platform.h>
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/* Generated on date 20150809 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]|3\.[012]
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_ES_VERSION_2_0
+#define GL_ES_VERSION_2_0 1
+#include <KHR/khrplatform.h>
+typedef khronos_int8_t GLbyte;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef short GLshort;
+typedef unsigned short GLushort;
+typedef void GLvoid;
+typedef struct __GLsync *GLsync;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef khronos_float_t GLfloat;
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_intptr_t GLintptr;
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+#define GL_GENERATE_MIPMAP_HINT           0x8192
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+#define GL_FRAGMENT_SHADER                0x8B30
+#define GL_VERTEX_SHADER                  0x8B31
+#define GL_MAX_VERTEX_ATTRIBS             0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS     0x8DFB
+#define GL_MAX_VARYING_VECTORS            0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS        0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS   0x8DFD
+#define GL_SHADER_TYPE                    0x8B4F
+#define GL_DELETE_STATUS                  0x8B80
+#define GL_LINK_STATUS                    0x8B82
+#define GL_VALIDATE_STATUS                0x8B83
+#define GL_ATTACHED_SHADERS               0x8B85
+#define GL_ACTIVE_UNIFORMS                0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH      0x8B87
+#define GL_ACTIVE_ATTRIBUTES              0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH    0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION       0x8B8C
+#define GL_CURRENT_PROGRAM                0x8B8D
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+#define GL_TEXTURE                        0x1702
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX8                 0x8D48
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+#define GL_NONE                           0
+#define GL_FRAMEBUFFER_COMPLETE           0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED        0x8CDD
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ES_VERSION_2_0 */
+
+#ifndef GL_ES_VERSION_3_0
+#define GL_ES_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_READ_BUFFER                    0x0C02
+#define GL_UNPACK_ROW_LENGTH              0x0CF2
+#define GL_UNPACK_SKIP_ROWS               0x0CF3
+#define GL_UNPACK_SKIP_PIXELS             0x0CF4
+#define GL_PACK_ROW_LENGTH                0x0D02
+#define GL_PACK_SKIP_ROWS                 0x0D03
+#define GL_PACK_SKIP_PIXELS               0x0D04
+#define GL_COLOR                          0x1800
+#define GL_DEPTH                          0x1801
+#define GL_STENCIL                        0x1802
+#define GL_RED                            0x1903
+#define GL_RGB8                           0x8051
+#define GL_RGBA8                          0x8058
+#define GL_RGB10_A2                       0x8059
+#define GL_TEXTURE_BINDING_3D             0x806A
+#define GL_UNPACK_SKIP_IMAGES             0x806D
+#define GL_UNPACK_IMAGE_HEIGHT            0x806E
+#define GL_TEXTURE_3D                     0x806F
+#define GL_TEXTURE_WRAP_R                 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE            0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368
+#define GL_MAX_ELEMENTS_VERTICES          0x80E8
+#define GL_MAX_ELEMENTS_INDICES           0x80E9
+#define GL_TEXTURE_MIN_LOD                0x813A
+#define GL_TEXTURE_MAX_LOD                0x813B
+#define GL_TEXTURE_BASE_LEVEL             0x813C
+#define GL_TEXTURE_MAX_LEVEL              0x813D
+#define GL_MIN                            0x8007
+#define GL_MAX                            0x8008
+#define GL_DEPTH_COMPONENT24              0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS           0x84FD
+#define GL_TEXTURE_COMPARE_MODE           0x884C
+#define GL_TEXTURE_COMPARE_FUNC           0x884D
+#define GL_CURRENT_QUERY                  0x8865
+#define GL_QUERY_RESULT                   0x8866
+#define GL_QUERY_RESULT_AVAILABLE         0x8867
+#define GL_BUFFER_MAPPED                  0x88BC
+#define GL_BUFFER_MAP_POINTER             0x88BD
+#define GL_STREAM_READ                    0x88E1
+#define GL_STREAM_COPY                    0x88E2
+#define GL_STATIC_READ                    0x88E5
+#define GL_STATIC_COPY                    0x88E6
+#define GL_DYNAMIC_READ                   0x88E9
+#define GL_DYNAMIC_COPY                   0x88EA
+#define GL_MAX_DRAW_BUFFERS               0x8824
+#define GL_DRAW_BUFFER0                   0x8825
+#define GL_DRAW_BUFFER1                   0x8826
+#define GL_DRAW_BUFFER2                   0x8827
+#define GL_DRAW_BUFFER3                   0x8828
+#define GL_DRAW_BUFFER4                   0x8829
+#define GL_DRAW_BUFFER5                   0x882A
+#define GL_DRAW_BUFFER6                   0x882B
+#define GL_DRAW_BUFFER7                   0x882C
+#define GL_DRAW_BUFFER8                   0x882D
+#define GL_DRAW_BUFFER9                   0x882E
+#define GL_DRAW_BUFFER10                  0x882F
+#define GL_DRAW_BUFFER11                  0x8830
+#define GL_DRAW_BUFFER12                  0x8831
+#define GL_DRAW_BUFFER13                  0x8832
+#define GL_DRAW_BUFFER14                  0x8833
+#define GL_DRAW_BUFFER15                  0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS  0x8B4A
+#define GL_SAMPLER_3D                     0x8B5F
+#define GL_SAMPLER_2D_SHADOW              0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_PIXEL_PACK_BUFFER              0x88EB
+#define GL_PIXEL_UNPACK_BUFFER            0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING      0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING    0x88EF
+#define GL_FLOAT_MAT2x3                   0x8B65
+#define GL_FLOAT_MAT2x4                   0x8B66
+#define GL_FLOAT_MAT3x2                   0x8B67
+#define GL_FLOAT_MAT3x4                   0x8B68
+#define GL_FLOAT_MAT4x2                   0x8B69
+#define GL_FLOAT_MAT4x3                   0x8B6A
+#define GL_SRGB                           0x8C40
+#define GL_SRGB8                          0x8C41
+#define GL_SRGB8_ALPHA8                   0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE         0x884E
+#define GL_MAJOR_VERSION                  0x821B
+#define GL_MINOR_VERSION                  0x821C
+#define GL_NUM_EXTENSIONS                 0x821D
+#define GL_RGBA32F                        0x8814
+#define GL_RGB32F                         0x8815
+#define GL_RGBA16F                        0x881A
+#define GL_RGB16F                         0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER    0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS       0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET       0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET       0x8905
+#define GL_MAX_VARYING_COMPONENTS         0x8B4B
+#define GL_TEXTURE_2D_ARRAY               0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY       0x8C1D
+#define GL_R11F_G11F_B10F                 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV   0x8C3B
+#define GL_RGB9_E5                        0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV       0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS    0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD             0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS            0x8C8C
+#define GL_SEPARATE_ATTRIBS               0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER      0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI                       0x8D70
+#define GL_RGB32UI                        0x8D71
+#define GL_RGBA16UI                       0x8D76
+#define GL_RGB16UI                        0x8D77
+#define GL_RGBA8UI                        0x8D7C
+#define GL_RGB8UI                         0x8D7D
+#define GL_RGBA32I                        0x8D82
+#define GL_RGB32I                         0x8D83
+#define GL_RGBA16I                        0x8D88
+#define GL_RGB16I                         0x8D89
+#define GL_RGBA8I                         0x8D8E
+#define GL_RGB8I                          0x8D8F
+#define GL_RED_INTEGER                    0x8D94
+#define GL_RGB_INTEGER                    0x8D98
+#define GL_RGBA_INTEGER                   0x8D99
+#define GL_SAMPLER_2D_ARRAY               0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW        0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW            0x8DC5
+#define GL_UNSIGNED_INT_VEC2              0x8DC6
+#define GL_UNSIGNED_INT_VEC3              0x8DC7
+#define GL_UNSIGNED_INT_VEC4              0x8DC8
+#define GL_INT_SAMPLER_2D                 0x8DCA
+#define GL_INT_SAMPLER_3D                 0x8DCB
+#define GL_INT_SAMPLER_CUBE               0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY           0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D        0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D        0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE      0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY  0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS            0x911F
+#define GL_BUFFER_MAP_LENGTH              0x9120
+#define GL_BUFFER_MAP_OFFSET              0x9121
+#define GL_DEPTH_COMPONENT32F             0x8CAC
+#define GL_DEPTH32F_STENCIL8              0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT            0x8218
+#define GL_FRAMEBUFFER_UNDEFINED          0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT       0x821A
+#define GL_DEPTH_STENCIL                  0x84F9
+#define GL_UNSIGNED_INT_24_8              0x84FA
+#define GL_DEPTH24_STENCIL8               0x88F0
+#define GL_UNSIGNED_NORMALIZED            0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING       0x8CA6
+#define GL_READ_FRAMEBUFFER               0x8CA8
+#define GL_DRAW_FRAMEBUFFER               0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING       0x8CAA
+#define GL_RENDERBUFFER_SAMPLES           0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS          0x8CDF
+#define GL_COLOR_ATTACHMENT1              0x8CE1
+#define GL_COLOR_ATTACHMENT2              0x8CE2
+#define GL_COLOR_ATTACHMENT3              0x8CE3
+#define GL_COLOR_ATTACHMENT4              0x8CE4
+#define GL_COLOR_ATTACHMENT5              0x8CE5
+#define GL_COLOR_ATTACHMENT6              0x8CE6
+#define GL_COLOR_ATTACHMENT7              0x8CE7
+#define GL_COLOR_ATTACHMENT8              0x8CE8
+#define GL_COLOR_ATTACHMENT9              0x8CE9
+#define GL_COLOR_ATTACHMENT10             0x8CEA
+#define GL_COLOR_ATTACHMENT11             0x8CEB
+#define GL_COLOR_ATTACHMENT12             0x8CEC
+#define GL_COLOR_ATTACHMENT13             0x8CED
+#define GL_COLOR_ATTACHMENT14             0x8CEE
+#define GL_COLOR_ATTACHMENT15             0x8CEF
+#define GL_COLOR_ATTACHMENT16             0x8CF0
+#define GL_COLOR_ATTACHMENT17             0x8CF1
+#define GL_COLOR_ATTACHMENT18             0x8CF2
+#define GL_COLOR_ATTACHMENT19             0x8CF3
+#define GL_COLOR_ATTACHMENT20             0x8CF4
+#define GL_COLOR_ATTACHMENT21             0x8CF5
+#define GL_COLOR_ATTACHMENT22             0x8CF6
+#define GL_COLOR_ATTACHMENT23             0x8CF7
+#define GL_COLOR_ATTACHMENT24             0x8CF8
+#define GL_COLOR_ATTACHMENT25             0x8CF9
+#define GL_COLOR_ATTACHMENT26             0x8CFA
+#define GL_COLOR_ATTACHMENT27             0x8CFB
+#define GL_COLOR_ATTACHMENT28             0x8CFC
+#define GL_COLOR_ATTACHMENT29             0x8CFD
+#define GL_COLOR_ATTACHMENT30             0x8CFE
+#define GL_COLOR_ATTACHMENT31             0x8CFF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES                    0x8D57
+#define GL_HALF_FLOAT                     0x140B
+#define GL_MAP_READ_BIT                   0x0001
+#define GL_MAP_WRITE_BIT                  0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT       0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT      0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT         0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT         0x0020
+#define GL_RG                             0x8227
+#define GL_RG_INTEGER                     0x8228
+#define GL_R8                             0x8229
+#define GL_RG8                            0x822B
+#define GL_R16F                           0x822D
+#define GL_R32F                           0x822E
+#define GL_RG16F                          0x822F
+#define GL_RG32F                          0x8230
+#define GL_R8I                            0x8231
+#define GL_R8UI                           0x8232
+#define GL_R16I                           0x8233
+#define GL_R16UI                          0x8234
+#define GL_R32I                           0x8235
+#define GL_R32UI                          0x8236
+#define GL_RG8I                           0x8237
+#define GL_RG8UI                          0x8238
+#define GL_RG16I                          0x8239
+#define GL_RG16UI                         0x823A
+#define GL_RG32I                          0x823B
+#define GL_RG32UI                         0x823C
+#define GL_VERTEX_ARRAY_BINDING           0x85B5
+#define GL_R8_SNORM                       0x8F94
+#define GL_RG8_SNORM                      0x8F95
+#define GL_RGB8_SNORM                     0x8F96
+#define GL_RGBA8_SNORM                    0x8F97
+#define GL_SIGNED_NORMALIZED              0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX  0x8D69
+#define GL_COPY_READ_BUFFER               0x8F36
+#define GL_COPY_WRITE_BUFFER              0x8F37
+#define GL_COPY_READ_BUFFER_BINDING       0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING      0x8F37
+#define GL_UNIFORM_BUFFER                 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING         0x8A28
+#define GL_UNIFORM_BUFFER_START           0x8A29
+#define GL_UNIFORM_BUFFER_SIZE            0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS      0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS    0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS    0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS    0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE         0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS          0x8A36
+#define GL_UNIFORM_TYPE                   0x8A37
+#define GL_UNIFORM_SIZE                   0x8A38
+#define GL_UNIFORM_NAME_LENGTH            0x8A39
+#define GL_UNIFORM_BLOCK_INDEX            0x8A3A
+#define GL_UNIFORM_OFFSET                 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE           0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE          0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR           0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING          0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE        0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH      0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS  0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX                  0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS   0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS  0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT        0x9111
+#define GL_OBJECT_TYPE                    0x9112
+#define GL_SYNC_CONDITION                 0x9113
+#define GL_SYNC_STATUS                    0x9114
+#define GL_SYNC_FLAGS                     0x9115
+#define GL_SYNC_FENCE                     0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE     0x9117
+#define GL_UNSIGNALED                     0x9118
+#define GL_SIGNALED                       0x9119
+#define GL_ALREADY_SIGNALED               0x911A
+#define GL_TIMEOUT_EXPIRED                0x911B
+#define GL_CONDITION_SATISFIED            0x911C
+#define GL_WAIT_FAILED                    0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT        0x00000001
+#define GL_TIMEOUT_IGNORED                0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR    0x88FE
+#define GL_ANY_SAMPLES_PASSED             0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_SAMPLER_BINDING                0x8919
+#define GL_RGB10_A2UI                     0x906F
+#define GL_TEXTURE_SWIZZLE_R              0x8E42
+#define GL_TEXTURE_SWIZZLE_G              0x8E43
+#define GL_TEXTURE_SWIZZLE_B              0x8E44
+#define GL_TEXTURE_SWIZZLE_A              0x8E45
+#define GL_GREEN                          0x1904
+#define GL_BLUE                           0x1905
+#define GL_INT_2_10_10_10_REV             0x8D9F
+#define GL_TRANSFORM_FEEDBACK             0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED      0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE      0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING     0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH          0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS     0x87FE
+#define GL_PROGRAM_BINARY_FORMATS         0x87FF
+#define GL_COMPRESSED_R11_EAC             0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC      0x9271
+#define GL_COMPRESSED_RG11_EAC            0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC     0x9273
+#define GL_COMPRESSED_RGB8_ETC2           0x9274
+#define GL_COMPRESSED_SRGB8_ETC2          0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC      0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT       0x912F
+#define GL_MAX_ELEMENT_INDEX              0x8D6B
+#define GL_NUM_SAMPLE_COUNTS              0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
+typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
+GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GL_APICALL void GL_APIENTRY glEndTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler);
+GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id);
+GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_ES_VERSION_3_0 */
+
+#ifndef GL_ES_VERSION_3_1
+#define GL_ES_VERSION_3_1 1
+#define GL_COMPUTE_SHADER                 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS     0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS     0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS    0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT   0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE    0x91BF
+#define GL_COMPUTE_WORK_GROUP_SIZE        0x8267
+#define GL_DISPATCH_INDIRECT_BUFFER       0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER_BIT             0x00000020
+#define GL_DRAW_INDIRECT_BUFFER           0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING   0x8F43
+#define GL_MAX_UNIFORM_LOCATIONS          0x826E
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH      0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT     0x9311
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES    0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH          0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT         0x9316
+#define GL_MAX_FRAMEBUFFER_SAMPLES        0x9318
+#define GL_UNIFORM                        0x92E1
+#define GL_UNIFORM_BLOCK                  0x92E2
+#define GL_PROGRAM_INPUT                  0x92E3
+#define GL_PROGRAM_OUTPUT                 0x92E4
+#define GL_BUFFER_VARIABLE                0x92E5
+#define GL_SHADER_STORAGE_BLOCK           0x92E6
+#define GL_ATOMIC_COUNTER_BUFFER          0x92C0
+#define GL_TRANSFORM_FEEDBACK_VARYING     0x92F4
+#define GL_ACTIVE_RESOURCES               0x92F5
+#define GL_MAX_NAME_LENGTH                0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES       0x92F7
+#define GL_NAME_LENGTH                    0x92F9
+#define GL_TYPE                           0x92FA
+#define GL_ARRAY_SIZE                     0x92FB
+#define GL_OFFSET                         0x92FC
+#define GL_BLOCK_INDEX                    0x92FD
+#define GL_ARRAY_STRIDE                   0x92FE
+#define GL_MATRIX_STRIDE                  0x92FF
+#define GL_IS_ROW_MAJOR                   0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX    0x9301
+#define GL_BUFFER_BINDING                 0x9302
+#define GL_BUFFER_DATA_SIZE               0x9303
+#define GL_NUM_ACTIVE_VARIABLES           0x9304
+#define GL_ACTIVE_VARIABLES               0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER    0x9306
+#define GL_REFERENCED_BY_FRAGMENT_SHADER  0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER   0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE           0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE         0x930D
+#define GL_LOCATION                       0x930E
+#define GL_VERTEX_SHADER_BIT              0x00000001
+#define GL_FRAGMENT_SHADER_BIT            0x00000002
+#define GL_ALL_SHADER_BITS                0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE              0x8258
+#define GL_ACTIVE_PROGRAM                 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING       0x825A
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING  0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START    0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE     0x92C3
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS     0x92D2
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS   0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS   0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS  0x92D9
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER    0x92DB
+#define GL_MAX_IMAGE_UNITS                0x8F38
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS      0x90CA
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS    0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS    0x90CF
+#define GL_IMAGE_BINDING_NAME             0x8F3A
+#define GL_IMAGE_BINDING_LEVEL            0x8F3B
+#define GL_IMAGE_BINDING_LAYERED          0x8F3C
+#define GL_IMAGE_BINDING_LAYER            0x8F3D
+#define GL_IMAGE_BINDING_ACCESS           0x8F3E
+#define GL_IMAGE_BINDING_FORMAT           0x906E
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT      0x00000002
+#define GL_UNIFORM_BARRIER_BIT            0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT      0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT            0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT       0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT     0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT      0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT        0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT     0x00001000
+#define GL_ALL_BARRIER_BITS               0xFFFFFFFF
+#define GL_IMAGE_2D                       0x904D
+#define GL_IMAGE_3D                       0x904E
+#define GL_IMAGE_CUBE                     0x9050
+#define GL_IMAGE_2D_ARRAY                 0x9053
+#define GL_INT_IMAGE_2D                   0x9058
+#define GL_INT_IMAGE_3D                   0x9059
+#define GL_INT_IMAGE_CUBE                 0x905B
+#define GL_INT_IMAGE_2D_ARRAY             0x905E
+#define GL_UNSIGNED_INT_IMAGE_2D          0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D          0x9064
+#define GL_UNSIGNED_INT_IMAGE_CUBE        0x9066
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY    0x9069
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_READ_ONLY                      0x88B8
+#define GL_WRITE_ONLY                     0x88B9
+#define GL_READ_WRITE                     0x88BA
+#define GL_SHADER_STORAGE_BUFFER          0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING  0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START    0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE     0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE  0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT     0x00002000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_DEPTH_STENCIL_TEXTURE_MODE     0x90EA
+#define GL_STENCIL_INDEX                  0x1901
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_SAMPLE_POSITION                0x8E50
+#define GL_SAMPLE_MASK                    0x8E51
+#define GL_SAMPLE_MASK_VALUE              0x8E52
+#define GL_TEXTURE_2D_MULTISAMPLE         0x9100
+#define GL_MAX_SAMPLE_MASK_WORDS          0x8E59
+#define GL_MAX_COLOR_TEXTURE_SAMPLES      0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES      0x910F
+#define GL_MAX_INTEGER_SAMPLES            0x9110
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_SAMPLES                0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_WIDTH                  0x1000
+#define GL_TEXTURE_HEIGHT                 0x1001
+#define GL_TEXTURE_DEPTH                  0x8071
+#define GL_TEXTURE_INTERNAL_FORMAT        0x1003
+#define GL_TEXTURE_RED_SIZE               0x805C
+#define GL_TEXTURE_GREEN_SIZE             0x805D
+#define GL_TEXTURE_BLUE_SIZE              0x805E
+#define GL_TEXTURE_ALPHA_SIZE             0x805F
+#define GL_TEXTURE_DEPTH_SIZE             0x884A
+#define GL_TEXTURE_STENCIL_SIZE           0x88F1
+#define GL_TEXTURE_SHARED_SIZE            0x8C3F
+#define GL_TEXTURE_RED_TYPE               0x8C10
+#define GL_TEXTURE_GREEN_TYPE             0x8C11
+#define GL_TEXTURE_BLUE_TYPE              0x8C12
+#define GL_TEXTURE_ALPHA_TYPE             0x8C13
+#define GL_TEXTURE_DEPTH_TYPE             0x8C16
+#define GL_TEXTURE_COMPRESSED             0x86A1
+#define GL_SAMPLER_2D_MULTISAMPLE         0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE     0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_VERTEX_ATTRIB_BINDING          0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET  0x82D5
+#define GL_VERTEX_BINDING_DIVISOR         0x82D6
+#define GL_VERTEX_BINDING_OFFSET          0x82D7
+#define GL_VERTEX_BINDING_STRIDE          0x82D8
+#define GL_VERTEX_BINDING_BUFFER          0x8F4F
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS     0x82DA
+#define GL_MAX_VERTEX_ATTRIB_STRIDE       0x82E5
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (GL_APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
+GL_APICALL void GL_APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect);
+GL_APICALL void GL_APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GL_APICALL void GL_APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GL_APICALL void GL_APIENTRY glMemoryBarrier (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glMemoryBarrierByRegion (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GL_APICALL void GL_APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GL_APICALL void GL_APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GL_APICALL void GL_APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GL_APICALL void GL_APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+#endif
+#endif /* GL_ES_VERSION_3_1 */
+
+#ifndef GL_ES_VERSION_3_2
+#define GL_ES_VERSION_3_2 1
+typedef void (GL_APIENTRY  *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_MULTISAMPLE_LINE_WIDTH_RANGE   0x9381
+#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY 0x9382
+#define GL_MULTIPLY                       0x9294
+#define GL_SCREEN                         0x9295
+#define GL_OVERLAY                        0x9296
+#define GL_DARKEN                         0x9297
+#define GL_LIGHTEN                        0x9298
+#define GL_COLORDODGE                     0x9299
+#define GL_COLORBURN                      0x929A
+#define GL_HARDLIGHT                      0x929B
+#define GL_SOFTLIGHT                      0x929C
+#define GL_DIFFERENCE                     0x929E
+#define GL_EXCLUSION                      0x92A0
+#define GL_HSL_HUE                        0x92AD
+#define GL_HSL_SATURATION                 0x92AE
+#define GL_HSL_COLOR                      0x92AF
+#define GL_HSL_LUMINOSITY                 0x92B0
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS       0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION        0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM      0x8245
+#define GL_DEBUG_SOURCE_API               0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM     0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER   0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY       0x8249
+#define GL_DEBUG_SOURCE_APPLICATION       0x824A
+#define GL_DEBUG_SOURCE_OTHER             0x824B
+#define GL_DEBUG_TYPE_ERROR               0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR  0x824E
+#define GL_DEBUG_TYPE_PORTABILITY         0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE         0x8250
+#define GL_DEBUG_TYPE_OTHER               0x8251
+#define GL_DEBUG_TYPE_MARKER              0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP          0x8269
+#define GL_DEBUG_TYPE_POP_GROUP           0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION    0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH    0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH        0x826D
+#define GL_BUFFER                         0x82E0
+#define GL_SHADER                         0x82E1
+#define GL_PROGRAM                        0x82E2
+#define GL_VERTEX_ARRAY                   0x8074
+#define GL_QUERY                          0x82E3
+#define GL_PROGRAM_PIPELINE               0x82E4
+#define GL_SAMPLER                        0x82E6
+#define GL_MAX_LABEL_LENGTH               0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH       0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES      0x9144
+#define GL_DEBUG_LOGGED_MESSAGES          0x9145
+#define GL_DEBUG_SEVERITY_HIGH            0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM          0x9147
+#define GL_DEBUG_SEVERITY_LOW             0x9148
+#define GL_DEBUG_OUTPUT                   0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT         0x00000002
+#define GL_STACK_OVERFLOW                 0x0503
+#define GL_STACK_UNDERFLOW                0x0504
+#define GL_GEOMETRY_SHADER                0x8DD9
+#define GL_GEOMETRY_SHADER_BIT            0x00000004
+#define GL_GEOMETRY_VERTICES_OUT          0x8916
+#define GL_GEOMETRY_INPUT_TYPE            0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE           0x8918
+#define GL_GEOMETRY_SHADER_INVOCATIONS    0x887F
+#define GL_LAYER_PROVOKING_VERTEX         0x825E
+#define GL_LINES_ADJACENCY                0x000A
+#define GL_LINE_STRIP_ADJACENCY           0x000B
+#define GL_TRIANGLES_ADJACENCY            0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY       0x000D
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS    0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS  0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES   0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS   0x92D5
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS    0x90CD
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_FIRST_VERTEX_CONVENTION        0x8E4D
+#define GL_LAST_VERTEX_CONVENTION         0x8E4E
+#define GL_UNDEFINED_VERTEX               0x8260
+#define GL_PRIMITIVES_GENERATED           0x8C87
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS     0x9312
+#define GL_MAX_FRAMEBUFFER_LAYERS         0x9317
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_REFERENCED_BY_GEOMETRY_SHADER  0x9309
+#define GL_PRIMITIVE_BOUNDING_BOX         0x92BE
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
+#define GL_CONTEXT_FLAGS                  0x821E
+#define GL_LOSE_CONTEXT_ON_RESET          0x8252
+#define GL_GUILTY_CONTEXT_RESET           0x8253
+#define GL_INNOCENT_CONTEXT_RESET         0x8254
+#define GL_UNKNOWN_CONTEXT_RESET          0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY    0x8256
+#define GL_NO_RESET_NOTIFICATION          0x8261
+#define GL_CONTEXT_LOST                   0x0507
+#define GL_SAMPLE_SHADING                 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE       0x8C37
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_PATCHES                        0x000E
+#define GL_PATCH_VERTICES                 0x8E72
+#define GL_TESS_CONTROL_OUTPUT_VERTICES   0x8E75
+#define GL_TESS_GEN_MODE                  0x8E76
+#define GL_TESS_GEN_SPACING               0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER          0x8E78
+#define GL_TESS_GEN_POINT_MODE            0x8E79
+#define GL_ISOLINES                       0x8E7A
+#define GL_QUADS                          0x0007
+#define GL_FRACTIONAL_ODD                 0x8E7B
+#define GL_FRACTIONAL_EVEN                0x8E7C
+#define GL_MAX_PATCH_VERTICES             0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL             0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS      0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_IS_PER_PATCH                   0x92E7
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_TESS_CONTROL_SHADER            0x8E88
+#define GL_TESS_EVALUATION_SHADER         0x8E87
+#define GL_TESS_CONTROL_SHADER_BIT        0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT     0x00000010
+#define GL_TEXTURE_BORDER_COLOR           0x1004
+#define GL_CLAMP_TO_BORDER                0x812D
+#define GL_TEXTURE_BUFFER                 0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING         0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE        0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER         0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define GL_SAMPLER_BUFFER                 0x8DC2
+#define GL_INT_SAMPLER_BUFFER             0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER    0x8DD8
+#define GL_IMAGE_BUFFER                   0x9051
+#define GL_INT_IMAGE_BUFFER               0x905C
+#define GL_UNSIGNED_INT_IMAGE_BUFFER      0x9067
+#define GL_TEXTURE_BUFFER_OFFSET          0x919D
+#define GL_TEXTURE_BUFFER_SIZE            0x919E
+#define GL_COMPRESSED_RGBA_ASTC_4x4       0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4       0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5       0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5       0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6       0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5       0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6       0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8       0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5      0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6      0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8      0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10     0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10     0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12     0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 0x93DD
+#define GL_TEXTURE_CUBE_MAP_ARRAY         0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_SAMPLER_CUBE_MAP_ARRAY         0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW  0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY     0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define GL_IMAGE_CUBE_MAP_ARRAY           0x9054
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY       0x905F
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY   0x9102
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY   0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+typedef void (GL_APIENTRYP PFNGLBLENDBARRIERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value);
+typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlendBarrier (void);
+GL_APICALL void GL_APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GL_APICALL void GL_APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GL_APICALL void GL_APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GL_APICALL void GL_APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GL_APICALL void GL_APIENTRY glPopDebugGroup (void);
+GL_APICALL void GL_APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glGetPointerv (GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glEnablei (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisablei (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glBlendEquationi (GLuint buf, GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabledi (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBox (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatus (void);
+GL_APICALL void GL_APIENTRY glReadnPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfv (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformiv (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GL_APICALL void GL_APIENTRY glGetnUniformuiv (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GL_APICALL void GL_APIENTRY glMinSampleShading (GLfloat value);
+GL_APICALL void GL_APIENTRY glPatchParameteri (GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_ES_VERSION_3_2 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/third_party/angle/include/GLES3/gl3platform.h b/src/third_party/angle/include/GLES3/gl3platform.h
new file mode 100644
index 0000000..8b531c6
--- /dev/null
+++ b/src/third_party/angle/include/GLES3/gl3platform.h
@@ -0,0 +1,36 @@
+#ifndef __gl3platform_h_
+#define __gl3platform_h_
+
+/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 3.X  gl3.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#if defined(STARBOARD)
+// Don't trust any previous definitions of GL_APICALL. We really want nothing.
+#undef GL_APICALL
+#define GL_APICALL  /* nothing */
+#else
+#ifndef GL_APICALL
+#define GL_APICALL  KHRONOS_APICALL
+#endif
+#endif  // defined(STARBOARD)
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl3platform_h_ */
diff --git a/src/third_party/angle/include/GLSLANG/ShaderLang.h b/src/third_party/angle/include/GLSLANG/ShaderLang.h
index 722ac64..5e01557 100644
--- a/src/third_party/angle/include/GLSLANG/ShaderLang.h
+++ b/src/third_party/angle/include/GLSLANG/ShaderLang.h
@@ -3,204 +3,240 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-#ifndef _COMPILER_INTERFACE_INCLUDED_
-#define _COMPILER_INTERFACE_INCLUDED_
+#ifndef GLSLANG_SHADERLANG_H_
+#define GLSLANG_SHADERLANG_H_
 
-#if defined(COMPONENT_BUILD)
-#if defined(_WIN32) || defined(_WIN64)
-
-#if defined(COMPILER_IMPLEMENTATION)
-#define COMPILER_EXPORT __declspec(dllexport)
-#else
-#define COMPILER_EXPORT __declspec(dllimport)
-#endif  // defined(COMPILER_IMPLEMENTATION)
-
-#else  // defined(WIN32)
-#define COMPILER_EXPORT __attribute__((visibility("default")))
-#endif
-
-#else  // defined(COMPONENT_BUILD)
-#define COMPILER_EXPORT
-#endif
+#include <stddef.h>
 
 #include "KHR/khrplatform.h"
-#include <stddef.h>
+
+#include <array>
+#include <map>
+#include <string>
+#include <vector>
 
 //
 // This is the platform independent interface between an OGL driver
 // and the shading language compiler.
 //
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
+#include "ShaderVars.h"
 
 // Version number for shader translation API.
-// It is incremented everytime the API changes.
-#define ANGLE_SH_VERSION 110
+// It is incremented every time the API changes.
+#define ANGLE_SH_VERSION 174
 
-//
-// The names of the following enums have been derived by replacing GL prefix
-// with SH. For example, SH_INFO_LOG_LENGTH is equivalent to GL_INFO_LOG_LENGTH.
-// The enum values are also equal to the values of their GL counterpart. This
-// is done to make it easier for applications to use the shader library.
-//
-typedef enum {
-  SH_FRAGMENT_SHADER = 0x8B30,
-  SH_VERTEX_SHADER   = 0x8B31
-} ShShaderType;
+enum ShShaderSpec
+{
+    SH_GLES2_SPEC,
+    SH_WEBGL_SPEC,
 
-typedef enum {
-  SH_GLES2_SPEC = 0x8B40,
-  SH_WEBGL_SPEC = 0x8B41,
+    SH_GLES3_SPEC,
+    SH_WEBGL2_SPEC,
 
-  // The CSS Shaders spec is a subset of the WebGL spec.
-  //
-  // In both CSS vertex and fragment shaders, ANGLE:
-  // (1) Reserves the "css_" prefix.
-  // (2) Renames the main function to css_main.
-  // (3) Disables the gl_MaxDrawBuffers built-in.
-  //
-  // In CSS fragment shaders, ANGLE:
-  // (1) Disables the gl_FragColor built-in.
-  // (2) Disables the gl_FragData built-in.
-  // (3) Enables the css_MixColor built-in.
-  // (4) Enables the css_ColorMatrix built-in.
-  //
-  // After passing a CSS shader through ANGLE, the browser is expected to append
-  // a new main function to it.
-  // This new main function will call the css_main function.
-  // It may also perform additional operations like varying assignment, texture
-  // access, and gl_FragColor assignment in order to implement the CSS Shaders
-  // blend modes.
-  //
-  SH_CSS_SHADERS_SPEC = 0x8B42
-} ShShaderSpec;
+    SH_GLES3_1_SPEC,
+    SH_WEBGL3_SPEC,
+};
 
-typedef enum {
-  SH_ESSL_OUTPUT   = 0x8B45,
-  SH_GLSL_OUTPUT   = 0x8B46,
-  SH_HLSL_OUTPUT   = 0x8B47,
-  SH_HLSL9_OUTPUT  = 0x8B47,
-  SH_HLSL11_OUTPUT = 0x8B48
-} ShShaderOutput;
+enum ShShaderOutput
+{
+    // ESSL output only supported in some configurations.
+    SH_ESSL_OUTPUT = 0x8B45,
 
-typedef enum {
-  SH_NONE           = 0,
-  SH_INT            = 0x1404,
-  SH_FLOAT          = 0x1406,
-  SH_FLOAT_VEC2     = 0x8B50,
-  SH_FLOAT_VEC3     = 0x8B51,
-  SH_FLOAT_VEC4     = 0x8B52,
-  SH_INT_VEC2       = 0x8B53,
-  SH_INT_VEC3       = 0x8B54,
-  SH_INT_VEC4       = 0x8B55,
-  SH_BOOL           = 0x8B56,
-  SH_BOOL_VEC2      = 0x8B57,
-  SH_BOOL_VEC3      = 0x8B58,
-  SH_BOOL_VEC4      = 0x8B59,
-  SH_FLOAT_MAT2     = 0x8B5A,
-  SH_FLOAT_MAT3     = 0x8B5B,
-  SH_FLOAT_MAT4     = 0x8B5C,
-  SH_SAMPLER_2D     = 0x8B5E,
-  SH_SAMPLER_CUBE   = 0x8B60,
-  SH_SAMPLER_2D_RECT_ARB = 0x8B63,
-  SH_SAMPLER_EXTERNAL_OES = 0x8D66
-} ShDataType;
+    // GLSL output only supported in some configurations.
+    SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
+    // Note: GL introduced core profiles in 1.5.
+    SH_GLSL_130_OUTPUT      = 0x8B47,
+    SH_GLSL_140_OUTPUT      = 0x8B80,
+    SH_GLSL_150_CORE_OUTPUT = 0x8B81,
+    SH_GLSL_330_CORE_OUTPUT = 0x8B82,
+    SH_GLSL_400_CORE_OUTPUT = 0x8B83,
+    SH_GLSL_410_CORE_OUTPUT = 0x8B84,
+    SH_GLSL_420_CORE_OUTPUT = 0x8B85,
+    SH_GLSL_430_CORE_OUTPUT = 0x8B86,
+    SH_GLSL_440_CORE_OUTPUT = 0x8B87,
+    SH_GLSL_450_CORE_OUTPUT = 0x8B88,
 
-typedef enum {
-  SH_INFO_LOG_LENGTH             =  0x8B84,
-  SH_OBJECT_CODE_LENGTH          =  0x8B88,  // GL_SHADER_SOURCE_LENGTH
-  SH_ACTIVE_UNIFORMS             =  0x8B86,
-  SH_ACTIVE_UNIFORM_MAX_LENGTH   =  0x8B87,
-  SH_ACTIVE_ATTRIBUTES           =  0x8B89,
-  SH_ACTIVE_ATTRIBUTE_MAX_LENGTH =  0x8B8A,
-  SH_MAPPED_NAME_MAX_LENGTH      =  0x6000,
-  SH_NAME_MAX_LENGTH             =  0x6001,
-  SH_HASHED_NAME_MAX_LENGTH      =  0x6002,
-  SH_HASHED_NAMES_COUNT          =  0x6003,
-  SH_ACTIVE_UNIFORMS_ARRAY       =  0x6004
-} ShShaderInfo;
+    // Prefer using these to specify HLSL output type:
+    SH_HLSL_3_0_OUTPUT       = 0x8B48,  // D3D 9
+    SH_HLSL_4_1_OUTPUT       = 0x8B49,  // D3D 11
+    SH_HLSL_4_0_FL9_3_OUTPUT = 0x8B4A,  // D3D 11 feature level 9_3
+
+    // Output specialized GLSL to be fed to glslang for Vulkan SPIR.
+    SH_GLSL_VULKAN_OUTPUT = 0x8B4B,
+};
 
 // Compile options.
-typedef enum {
-  SH_VALIDATE                = 0,
-  SH_VALIDATE_LOOP_INDEXING  = 0x0001,
-  SH_INTERMEDIATE_TREE       = 0x0002,
-  SH_OBJECT_CODE             = 0x0004,
-  SH_ATTRIBUTES_UNIFORMS     = 0x0008,
-  SH_LINE_DIRECTIVES         = 0x0010,
-  SH_SOURCE_PATH             = 0x0020,
-  SH_MAP_LONG_VARIABLE_NAMES = 0x0040,
-  SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = 0x0080,
+// The Compile options type is defined in ShaderVars.h, to allow ANGLE to import the ShaderVars
+// header without needing the ShaderLang header. This avoids some conflicts with glslang.
 
-  // This is needed only as a workaround for certain OpenGL driver bugs.
-  SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100,
+const ShCompileOptions SH_VALIDATE                           = 0;
+const ShCompileOptions SH_VALIDATE_LOOP_INDEXING             = UINT64_C(1) << 0;
+const ShCompileOptions SH_INTERMEDIATE_TREE                  = UINT64_C(1) << 1;
+const ShCompileOptions SH_OBJECT_CODE                        = UINT64_C(1) << 2;
+const ShCompileOptions SH_VARIABLES                          = UINT64_C(1) << 3;
+const ShCompileOptions SH_LINE_DIRECTIVES                    = UINT64_C(1) << 4;
+const ShCompileOptions SH_SOURCE_PATH                        = UINT64_C(1) << 5;
 
-  // This is an experimental flag to enforce restrictions that aim to prevent 
-  // timing attacks.
-  // It generates compilation errors for shaders that could expose sensitive
-  // texture information via the timing channel.
-  // To use this flag, you must compile the shader under the WebGL spec
-  // (using the SH_WEBGL_SPEC flag).
-  SH_TIMING_RESTRICTIONS = 0x0200,
-    
-  // This flag prints the dependency graph that is used to enforce timing
-  // restrictions on fragment shaders.
-  // This flag only has an effect if all of the following are true:
-  // - The shader spec is SH_WEBGL_SPEC.
-  // - The compile options contain the SH_TIMING_RESTRICTIONS flag.
-  // - The shader type is SH_FRAGMENT_SHADER.
-  SH_DEPENDENCY_GRAPH = 0x0400,
+// This flag will keep invariant declaration for input in fragment shader for GLSL >=4.20 on AMD.
+// From GLSL >= 4.20, it's optional to add invariant for fragment input, but GPU vendors have
+// different implementations about this. Some drivers forbid invariant in fragment for GLSL>= 4.20,
+// e.g. Linux Mesa, some drivers treat that as optional, e.g. NVIDIA, some drivers require invariant
+// must match between vertex and fragment shader, e.g. AMD. The behavior on AMD is obviously wrong.
+// Remove invariant for input in fragment shader to workaround the restriction on Intel Mesa.
+// But don't remove on AMD Linux to avoid triggering the bug on AMD.
+const ShCompileOptions SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT = UINT64_C(1) << 6;
 
-  // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
-  SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
+// Due to spec difference between GLSL 4.1 or lower and ESSL3, some platforms (for example, Mac OSX
+// core profile) require a variable's "invariant"/"centroid" qualifiers to match between vertex and
+// fragment shader. A simple solution to allow such shaders to link is to omit the two qualifiers.
+// AMD driver in Linux requires invariant qualifier to match between vertex and fragment shaders,
+// while ESSL3 disallows invariant qualifier in fragment shader and GLSL >= 4.2 doesn't require
+// invariant qualifier to match between shaders. Remove invariant qualifier from vertex shader to
+// workaround AMD driver bug.
+// Note that the two flags take effect on ESSL3 input shaders translated to GLSL 4.1 or lower and to
+// GLSL 4.2 or newer on Linux AMD.
+// TODO(zmo): This is not a good long-term solution. Simply dropping these qualifiers may break some
+// developers' content. A more complex workaround of dynamically generating, compiling, and
+// re-linking shaders that use these qualifiers should be implemented.
+const ShCompileOptions SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3 = UINT64_C(1) << 7;
 
-  // This flag ensures all indirect (expression-based) array indexing
-  // is clamped to the bounds of the array. This ensures, for example,
-  // that you cannot read off the end of a uniform, whether an array
-  // vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
-  // specified in the ShBuiltInResources when constructing the
-  // compiler, selects the strategy for the clamping implementation.
-  SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000,
+// This flag works around bug in Intel Mac drivers related to abs(i) where
+// i is an integer.
+const ShCompileOptions SH_EMULATE_ABS_INT_FUNCTION = UINT64_C(1) << 8;
 
-  // This flag limits the complexity of an expression.
-  SH_LIMIT_EXPRESSION_COMPLEXITY = 0x2000,
+// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
+// This flag only enforces (and can only enforce) the packing
+// restrictions for uniform variables in both vertex and fragment
+// shaders. ShCheckVariablesWithinPackingLimits() lets embedders
+// enforce the packing restrictions for varying variables during
+// program link time.
+const ShCompileOptions SH_ENFORCE_PACKING_RESTRICTIONS = UINT64_C(1) << 9;
 
-  // This flag limits the depth of the call stack.
-  SH_LIMIT_CALL_STACK_DEPTH = 0x4000,
-} ShCompileOptions;
+// This flag ensures all indirect (expression-based) array indexing
+// is clamped to the bounds of the array. This ensures, for example,
+// that you cannot read off the end of a uniform, whether an array
+// vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
+// specified in the ShBuiltInResources when constructing the
+// compiler, selects the strategy for the clamping implementation.
+const ShCompileOptions SH_CLAMP_INDIRECT_ARRAY_BOUNDS = UINT64_C(1) << 10;
+
+// This flag limits the complexity of an expression.
+const ShCompileOptions SH_LIMIT_EXPRESSION_COMPLEXITY = UINT64_C(1) << 11;
+
+// This flag limits the depth of the call stack.
+const ShCompileOptions SH_LIMIT_CALL_STACK_DEPTH = UINT64_C(1) << 12;
+
+// This flag initializes gl_Position to vec4(0,0,0,0) at the
+// beginning of the vertex shader's main(), and has no effect in the
+// fragment shader. It is intended as a workaround for drivers which
+// incorrectly fail to link programs if gl_Position is not written.
+const ShCompileOptions SH_INIT_GL_POSITION = UINT64_C(1) << 13;
+
+// This flag replaces
+//   "a && b" with "a ? b : false",
+//   "a || b" with "a ? true : b".
+// This is to work around a MacOSX driver bug that |b| is executed
+// independent of |a|'s value.
+const ShCompileOptions SH_UNFOLD_SHORT_CIRCUIT = UINT64_C(1) << 14;
+
+// This flag initializes output variables to 0 at the beginning of main().
+// It is to avoid undefined behaviors.
+const ShCompileOptions SH_INIT_OUTPUT_VARIABLES = UINT64_C(1) << 15;
+
+// This flag scalarizes vec/ivec/bvec/mat constructor args.
+// It is intended as a workaround for Linux/Mac driver bugs.
+const ShCompileOptions SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = UINT64_C(1) << 16;
+
+// This flag overwrites a struct name with a unique prefix.
+// It is intended as a workaround for drivers that do not handle
+// struct scopes correctly, including all Mac drivers and Linux AMD.
+const ShCompileOptions SH_REGENERATE_STRUCT_NAMES = UINT64_C(1) << 17;
+
+// This flag makes the compiler not prune unused function early in the
+// compilation process. Pruning coupled with SH_LIMIT_CALL_STACK_DEPTH
+// helps avoid bad shaders causing stack overflows.
+const ShCompileOptions SH_DONT_PRUNE_UNUSED_FUNCTIONS = UINT64_C(1) << 18;
+
+// This flag works around a bug in NVIDIA 331 series drivers related
+// to pow(x, y) where y is a constant vector.
+const ShCompileOptions SH_REMOVE_POW_WITH_CONSTANT_EXPONENT = UINT64_C(1) << 19;
+
+// This flag works around bugs in Mac drivers related to do-while by
+// transforming them into an other construct.
+const ShCompileOptions SH_REWRITE_DO_WHILE_LOOPS = UINT64_C(1) << 20;
+
+// This flag works around a bug in the HLSL compiler optimizer that folds certain
+// constant pow expressions incorrectly. Only applies to the HLSL back-end. It works
+// by expanding the integer pow expressions into a series of multiplies.
+const ShCompileOptions SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS = UINT64_C(1) << 21;
+
+// Flatten "#pragma STDGL invariant(all)" into the declarations of
+// varying variables and built-in GLSL variables. This compiler
+// option is enabled automatically when needed.
+const ShCompileOptions SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL = UINT64_C(1) << 22;
+
+// Some drivers do not take into account the base level of the texture in the results of the
+// HLSL GetDimensions builtin.  This flag instructs the compiler to manually add the base level
+// offsetting.
+const ShCompileOptions SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL = UINT64_C(1) << 23;
+
+// This flag works around an issue in translating GLSL function texelFetchOffset on
+// INTEL drivers. It works by translating texelFetchOffset into texelFetch.
+const ShCompileOptions SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH = UINT64_C(1) << 24;
+
+// This flag works around condition bug of for and while loops in Intel Mac OSX drivers.
+// Condition calculation is not correct. Rewrite it from "CONDITION" to "CONDITION && true".
+const ShCompileOptions SH_ADD_AND_TRUE_TO_LOOP_CONDITION = UINT64_C(1) << 25;
+
+// This flag works around a bug in evaluating unary minus operator on integer on some INTEL
+// drivers. It works by translating -(int) into ~(int) + 1.
+const ShCompileOptions SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR = UINT64_C(1) << 26;
+
+// This flag works around a bug in evaluating isnan() on some INTEL D3D and Mac OSX drivers.
+// It works by using an expression to emulate this function.
+const ShCompileOptions SH_EMULATE_ISNAN_FLOAT_FUNCTION = UINT64_C(1) << 27;
+
+// This flag will use all uniforms of unused std140 and shared uniform blocks at the
+// beginning of the vertex/fragment shader's main(). It is intended as a workaround for Mac
+// drivers with shader version 4.10. In those drivers, they will treat unused
+// std140 and shared uniform blocks' members as inactive. However, WebGL2.0 based on
+// OpenGL ES3.0.4 requires all members of a named uniform block declared with a shared or std140
+// layout qualifier to be considered active. The uniform block itself is also considered active.
+const ShCompileOptions SH_USE_UNUSED_STANDARD_SHARED_BLOCKS = UINT64_C(1) << 28;
+
+// This flag works around a bug in unary minus operator on float numbers on Intel
+// Mac OSX 10.11 drivers. It works by translating -float into 0.0 - float.
+const ShCompileOptions SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR = UINT64_C(1) << 29;
+
+// This flag works around a bug in evaluating atan(y, x) on some NVIDIA OpenGL drivers.
+// It works by using an expression to emulate this function.
+const ShCompileOptions SH_EMULATE_ATAN2_FLOAT_FUNCTION = UINT64_C(1) << 30;
+
+// Set to 1 to translate gl_ViewID_OVR to an uniform so that the extension can be emulated.
+// "uniform highp uint webgl_angle_ViewID_OVR".
+const ShCompileOptions SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM = UINT64_C(1) << 31;
 
 // Defines alternate strategies for implementing array index clamping.
-typedef enum {
-  // Use the clamp intrinsic for array index clamping.
-  SH_CLAMP_WITH_CLAMP_INTRINSIC = 1,
+enum ShArrayIndexClampingStrategy
+{
+    // Use the clamp intrinsic for array index clamping.
+    SH_CLAMP_WITH_CLAMP_INTRINSIC = 1,
 
-  // Use a user-defined function for array index clamping.
-  SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION
-} ShArrayIndexClampingStrategy;
-
-//
-// Driver must call this first, once, before doing any other
-// compiler operations.
-// If the function succeeds, the return value is nonzero, else zero.
-//
-COMPILER_EXPORT int ShInitialize();
-//
-// Driver should call this at shutdown.
-// If the function succeeds, the return value is nonzero, else zero.
-//
-COMPILER_EXPORT int ShFinalize();
+    // Use a user-defined function for array index clamping.
+    SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION
+};
 
 // The 64 bits hash function. The first parameter is the input string; the
 // second parameter is the string length.
-typedef khronos_uint64_t (*ShHashFunction64)(const char*, size_t);
+using ShHashFunction64 = khronos_uint64_t (*)(const char *, size_t);
 
 //
 // Implementation dependent built-in resources (constants and extensions).
 // The names for these resources has been obtained by stripping gl_/GL_.
 //
-typedef struct
+struct ShBuiltInResources
 {
     // Constants.
     int MaxVertexAttribs;
@@ -216,14 +252,48 @@
     // Set to 1 to enable the extension, else 0.
     int OES_standard_derivatives;
     int OES_EGL_image_external;
+    int OES_EGL_image_external_essl3;
+    int NV_EGL_stream_consumer_external;
     int ARB_texture_rectangle;
+    int EXT_blend_func_extended;
     int EXT_draw_buffers;
     int EXT_frag_depth;
+    int EXT_shader_texture_lod;
+    int WEBGL_debug_shader_precision;
+    int EXT_shader_framebuffer_fetch;
+    int NV_shader_framebuffer_fetch;
+    int ARM_shader_framebuffer_fetch;
+    int OVR_multiview;
+    int EXT_YUV_target;
 
-    // Set to 1 if highp precision is supported in the fragment language.
+    // Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
+    // with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
+    // EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers
+    // function. This applies to Tegra K1 devices.
+    int NV_draw_buffers;
+
+    // Set to 1 if highp precision is supported in the ESSL 1.00 version of the
+    // fragment language. Does not affect versions of the language where highp
+    // support is mandatory.
     // Default is 0.
     int FragmentPrecisionHigh;
 
+    // GLSL ES 3.0 constants.
+    int MaxVertexOutputVectors;
+    int MaxFragmentInputVectors;
+    int MinProgramTexelOffset;
+    int MaxProgramTexelOffset;
+
+    // Extension constants.
+
+    // Value of GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT for OpenGL ES output context.
+    // Value of GL_MAX_DUAL_SOURCE_DRAW_BUFFERS for OpenGL output context.
+    // GLES SL version 100 gl_MaxDualSourceDrawBuffersEXT value for EXT_blend_func_extended.
+    int MaxDualSourceDrawBuffers;
+
+    // Value of GL_MAX_VIEWS_OVR.
+    int MaxViewsOVR;
+
     // Name Hashing.
     // Set a 64 bit hash function to enable user-defined name hashing.
     // Default is NULL.
@@ -233,53 +303,142 @@
     // Default is SH_CLAMP_WITH_CLAMP_INTRINSIC.
     ShArrayIndexClampingStrategy ArrayIndexClampingStrategy;
 
-    // The maximum complexity an expression can be.
+    // The maximum complexity an expression can be when SH_LIMIT_EXPRESSION_COMPLEXITY is turned on.
     int MaxExpressionComplexity;
 
     // The maximum depth a call stack can be.
     int MaxCallStackDepth;
-} ShBuiltInResources;
 
-//
-// Initialize built-in resources with minimum expected values.
-//
-COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
+    // The maximum number of parameters a function can have when SH_LIMIT_EXPRESSION_COMPLEXITY is
+    // turned on.
+    int MaxFunctionParameters;
+
+    // GLES 3.1 constants
+
+    // maximum number of available image units
+    int MaxImageUnits;
+
+    // maximum number of image uniforms in a vertex shader
+    int MaxVertexImageUniforms;
+
+    // maximum number of image uniforms in a fragment shader
+    int MaxFragmentImageUniforms;
+
+    // maximum number of image uniforms in a compute shader
+    int MaxComputeImageUniforms;
+
+    // maximum total number of image uniforms in a program
+    int MaxCombinedImageUniforms;
+
+    // maximum number of uniform locations
+    int MaxUniformLocations;
+
+    // maximum number of ssbos and images in a shader
+    int MaxCombinedShaderOutputResources;
+
+    // maximum number of groups in each dimension
+    std::array<int, 3> MaxComputeWorkGroupCount;
+    // maximum number of threads per work group in each dimension
+    std::array<int, 3> MaxComputeWorkGroupSize;
+
+    // maximum number of total uniform components
+    int MaxComputeUniformComponents;
+
+    // maximum number of texture image units in a compute shader
+    int MaxComputeTextureImageUnits;
+
+    // maximum number of atomic counters in a compute shader
+    int MaxComputeAtomicCounters;
+
+    // maximum number of atomic counter buffers in a compute shader
+    int MaxComputeAtomicCounterBuffers;
+
+    // maximum number of atomic counters in a vertex shader
+    int MaxVertexAtomicCounters;
+
+    // maximum number of atomic counters in a fragment shader
+    int MaxFragmentAtomicCounters;
+
+    // maximum number of atomic counters in a program
+    int MaxCombinedAtomicCounters;
+
+    // maximum binding for an atomic counter
+    int MaxAtomicCounterBindings;
+
+    // maximum number of atomic counter buffers in a vertex shader
+    int MaxVertexAtomicCounterBuffers;
+
+    // maximum number of atomic counter buffers in a fragment shader
+    int MaxFragmentAtomicCounterBuffers;
+
+    // maximum number of atomic counter buffers in a program
+    int MaxCombinedAtomicCounterBuffers;
+
+    // maximum number of buffer object storage in machine units
+    int MaxAtomicCounterBufferSize;
+};
 
 //
 // ShHandle held by but opaque to the driver.  It is allocated,
-// managed, and de-allocated by the compiler. It's contents 
+// managed, and de-allocated by the compiler. Its contents
 // are defined by and used by the compiler.
 //
 // If handle creation fails, 0 will be returned.
 //
-typedef void* ShHandle;
+using ShHandle = void *;
+
+namespace sh
+{
+
+//
+// Driver must call this first, once, before doing any other compiler operations.
+// If the function succeeds, the return value is true, else false.
+//
+bool Initialize();
+//
+// Driver should call this at shutdown.
+// If the function succeeds, the return value is true, else false.
+//
+bool Finalize();
+
+//
+// Initialize built-in resources with minimum expected values.
+// Parameters:
+// resources: The object to initialize. Will be comparable with memcmp.
+//
+void InitBuiltInResources(ShBuiltInResources *resources);
+
+//
+// Returns the a concatenated list of the items in ShBuiltInResources as a null-terminated string.
+// This function must be updated whenever ShBuiltInResources is changed.
+// Parameters:
+// handle: Specifies the handle of the compiler to be used.
+const std::string &GetBuiltInResourcesString(const ShHandle handle);
 
 //
 // Driver calls these to create and destroy compiler objects.
 //
-// Returns the handle of constructed compiler, null if the requested compiler is
-// not supported.
+// Returns the handle of constructed compiler, null if the requested compiler is not supported.
 // Parameters:
-// type: Specifies the type of shader - SH_FRAGMENT_SHADER or SH_VERTEX_SHADER.
-// spec: Specifies the language spec the compiler must conform to -
-//       SH_GLES2_SPEC or SH_WEBGL_SPEC.
-// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
-//         SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT.
+// type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER.
+// spec: Specifies the language spec the compiler must conform to - SH_GLES2_SPEC or SH_WEBGL_SPEC.
+// output: Specifies the output code type - for example SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
+//         SH_HLSL_3_0_OUTPUT or SH_HLSL_4_1_OUTPUT. Note: Each output type may only
+//         be supported in some configurations.
 // resources: Specifies the built-in resources.
-COMPILER_EXPORT ShHandle ShConstructCompiler(
-    ShShaderType type,
-    ShShaderSpec spec,
-    ShShaderOutput output,
-    const ShBuiltInResources* resources);
-COMPILER_EXPORT void ShDestruct(ShHandle handle);
+ShHandle ConstructCompiler(sh::GLenum type,
+                           ShShaderSpec spec,
+                           ShShaderOutput output,
+                           const ShBuiltInResources *resources);
+void Destruct(ShHandle handle);
 
 //
 // Compiles the given shader source.
-// If the function succeeds, the return value is nonzero, else zero.
+// If the function succeeds, the return value is true, else false.
 // Parameters:
 // handle: Specifies the handle of compiler to be used.
-// shaderStrings: Specifies an array of pointers to null-terminated strings
-//                containing the shader source code.
+// shaderStrings: Specifies an array of pointers to null-terminated strings containing the shader
+// source code.
 // numStrings: Specifies the number of elements in shaderStrings array.
 // compileOptions: A mask containing the following parameters:
 // SH_VALIDATE: Validates shader to ensure that it conforms to the spec
@@ -291,156 +450,81 @@
 //                            There is no need to specify this parameter when
 //                            compiling for WebGL - it is implied.
 // SH_INTERMEDIATE_TREE: Writes intermediate tree to info log.
-//                       Can be queried by calling ShGetInfoLog().
+//                       Can be queried by calling sh::GetInfoLog().
 // SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
-//                 Can be queried by calling ShGetObjectCode().
-// SH_ATTRIBUTES_UNIFORMS: Extracts attributes and uniforms.
-//                         Can be queried by calling ShGetActiveAttrib() and
-//                         ShGetActiveUniform().
+//                 Can be queried by calling sh::GetObjectCode().
+// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
+//               Can be queried by calling ShGetVariableInfo().
 //
-COMPILER_EXPORT int ShCompile(
-    const ShHandle handle,
-    const char* const shaderStrings[],
-    size_t numStrings,
-    int compileOptions
-    );
+bool Compile(const ShHandle handle,
+             const char *const shaderStrings[],
+             size_t numStrings,
+             ShCompileOptions compileOptions);
 
-// Returns a parameter from a compiled shader.
+// Clears the results from the previous compilation.
+void ClearResults(const ShHandle handle);
+
+// Return the version of the shader language.
+int GetShaderVersion(const ShHandle handle);
+
+// Return the currently set language output type.
+ShShaderOutput GetShaderOutputType(const ShHandle handle);
+
+// Returns null-terminated information log for a compiled shader.
 // Parameters:
 // handle: Specifies the compiler
-// pname: Specifies the parameter to query.
-// The following parameters are defined:
-// SH_INFO_LOG_LENGTH: the number of characters in the information log
-//                     including the null termination character.
-// SH_OBJECT_CODE_LENGTH: the number of characters in the object code
-//                        including the null termination character.
-// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables.
-// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute
-//                                 variable name including the null
-//                                 termination character.
-// SH_ACTIVE_UNIFORMS: the number of active uniform variables.
-// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
-//                               variable name including the null
-//                               termination character.
-// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
-//                            the null termination character.
-// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the
-//                     null termination character.
-// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the
-//                            null termination character.
-// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile.
-//
-// params: Requested parameter
-COMPILER_EXPORT void ShGetInfo(const ShHandle handle,
-                               ShShaderInfo pname,
-                               size_t* params);
-
-// Returns nul-terminated information log for a compiled shader.
-// Parameters:
-// handle: Specifies the compiler
-// infoLog: Specifies an array of characters that is used to return
-//          the information log. It is assumed that infoLog has enough memory
-//          to accomodate the information log. The size of the buffer required
-//          to store the returned information log can be obtained by calling
-//          ShGetInfo with SH_INFO_LOG_LENGTH.
-COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
+const std::string &GetInfoLog(const ShHandle handle);
 
 // Returns null-terminated object code for a compiled shader.
 // Parameters:
 // handle: Specifies the compiler
-// infoLog: Specifies an array of characters that is used to return
-//          the object code. It is assumed that infoLog has enough memory to
-//          accomodate the object code. The size of the buffer required to
-//          store the returned object code can be obtained by calling
-//          ShGetInfo with SH_OBJECT_CODE_LENGTH.
-COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
+const std::string &GetObjectCode(const ShHandle handle);
 
-// Returns information about an active attribute variable.
+// Returns a (original_name, hash) map containing all the user defined names in the shader,
+// including variable names, function names, struct names, and struct field names.
 // Parameters:
 // handle: Specifies the compiler
-// index: Specifies the index of the attribute variable to be queried.
-// length: Returns the number of characters actually written in the string
-//         indicated by name (excluding the null terminator) if a value other
-//         than NULL is passed.
-// size: Returns the size of the attribute variable.
-// type: Returns the data type of the attribute variable.
-// name: Returns a null terminated string containing the name of the
-//       attribute variable. It is assumed that name has enough memory to
-//       accomodate the attribute variable name. The size of the buffer
-//       required to store the attribute variable name can be obtained by
-//       calling ShGetInfo with SH_ACTIVE_ATTRIBUTE_MAX_LENGTH.
-// mappedName: Returns a null terminated string containing the mapped name of
-//             the attribute variable, It is assumed that mappedName has enough
-//             memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
-//             about the mapped name. If the name is not mapped, then name and
-//             mappedName are the same.
-COMPILER_EXPORT void ShGetActiveAttrib(const ShHandle handle,
-                                       int index,
-                                       size_t* length,
-                                       int* size,
-                                       ShDataType* type,
-                                       char* name,
-                                       char* mappedName);
+const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle);
 
-// Returns information about an active uniform variable.
+// Shader variable inspection.
+// Returns a pointer to a list of variables of the designated type.
+// (See ShaderVars.h for type definitions, included above)
+// Returns NULL on failure.
 // Parameters:
 // handle: Specifies the compiler
-// index: Specifies the index of the uniform variable to be queried.
-// length: Returns the number of characters actually written in the string
-//         indicated by name (excluding the null terminator) if a value
-//         other than NULL is passed.
-// size: Returns the size of the uniform variable.
-// type: Returns the data type of the uniform variable.
-// name: Returns a null terminated string containing the name of the
-//       uniform variable. It is assumed that name has enough memory to
-//       accomodate the uniform variable name. The size of the buffer required
-//       to store the uniform variable name can be obtained by calling
-//       ShGetInfo with SH_ACTIVE_UNIFORMS_MAX_LENGTH.
-// mappedName: Returns a null terminated string containing the mapped name of
-//             the uniform variable, It is assumed that mappedName has enough
-//             memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
-//             about the mapped name. If the name is not mapped, then name and
-//             mappedName are the same.
-COMPILER_EXPORT void ShGetActiveUniform(const ShHandle handle,
-                                        int index,
-                                        size_t* length,
-                                        int* size,
-                                        ShDataType* type,
-                                        char* name,
-                                        char* mappedName);
+const std::vector<sh::Uniform> *GetUniforms(const ShHandle handle);
+const std::vector<sh::Varying> *GetVaryings(const ShHandle handle);
+const std::vector<sh::Attribute> *GetAttributes(const ShHandle handle);
+const std::vector<sh::OutputVariable> *GetOutputVariables(const ShHandle handle);
+const std::vector<sh::InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle);
+sh::WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle);
+int GetVertexShaderNumViews(const ShHandle handle);
 
-// Returns information about a name hashing entry from the latest compile.
+// Returns true if the passed in variables pack in maxVectors followingthe packing rules from the
+// GLSL 1.017 spec, Appendix A, section 7.
+// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
+// flag above.
+// Parameters:
+// maxVectors: the available rows of registers.
+// variables: an array of variables.
+bool CheckVariablesWithinPackingLimits(int maxVectors,
+                                       const std::vector<sh::ShaderVariable> &variables);
+
+// Gives the compiler-assigned register for an interface block.
+// The method writes the value to the output variable "indexOut".
+// Returns true if it found a valid interface block, false otherwise.
 // Parameters:
 // handle: Specifies the compiler
-// index: Specifies the index of the name hashing entry to be queried.
-// name: Returns a null terminated string containing the user defined name.
-//       It is assumed that name has enough memory to accomodate the name.
-//       The size of the buffer required to store the user defined name can
-//       be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH.
-// hashedName: Returns a null terminated string containing the hashed name of
-//             the uniform variable, It is assumed that hashedName has enough
-//             memory to accomodate the name. The size of the buffer required
-//             to store the name can be obtained by calling ShGetInfo with
-//             SH_HASHED_NAME_MAX_LENGTH.
-COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle,
-                                           int index,
-                                           char* name,
-                                           char* hashedName);
+// interfaceBlockName: Specifies the interface block
+// indexOut: output variable that stores the assigned register
+bool GetInterfaceBlockRegister(const ShHandle handle,
+                               const std::string &interfaceBlockName,
+                               unsigned int *indexOut);
 
-// Returns a parameter from a compiled shader.
-// Parameters:
-// handle: Specifies the compiler
-// pname: Specifies the parameter to query.
-// The following parameters are defined:
-// SH_ACTIVE_UNIFORMS_ARRAY: an STL vector of active uniforms. Valid only for
-//                           HLSL output.
-// params: Requested parameter
-COMPILER_EXPORT void ShGetInfoPointer(const ShHandle handle,
-                                      ShShaderInfo pname,
-                                      void** params);
+// Gives a map from uniform names to compiler-assigned registers in the default interface block.
+// Note that the map contains also registers of samplers that have been extracted from structs.
+const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle);
 
-#ifdef __cplusplus
-}
-#endif
+}  // namespace sh
 
-#endif // _COMPILER_INTERFACE_INCLUDED_
+#endif // GLSLANG_SHADERLANG_H_
diff --git a/src/third_party/angle/include/GLSLANG/ShaderVars.h b/src/third_party/angle/include/GLSLANG/ShaderVars.h
new file mode 100644
index 0000000..f72b8c6
--- /dev/null
+++ b/src/third_party/angle/include/GLSLANG/ShaderVars.h
@@ -0,0 +1,251 @@
+//
+// Copyright (c) 2013-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.
+//
+// ShaderVars.h:
+//  Types to represent GL variables (varyings, uniforms, etc)
+//
+
+#ifndef GLSLANG_SHADERVARS_H_
+#define GLSLANG_SHADERVARS_H_
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+// This type is defined here to simplify ANGLE's integration with glslang for SPIRv.
+using ShCompileOptions = uint64_t;
+
+namespace sh
+{
+// GLenum alias
+typedef unsigned int GLenum;
+
+// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec
+enum InterpolationType
+{
+    INTERPOLATION_SMOOTH,
+    INTERPOLATION_CENTROID,
+    INTERPOLATION_FLAT
+};
+
+// Validate link & SSO consistency of interpolation qualifiers
+bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
+
+// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec
+enum BlockLayoutType
+{
+    BLOCKLAYOUT_STANDARD,
+    BLOCKLAYOUT_PACKED,
+    BLOCKLAYOUT_SHARED
+};
+
+// Base class for all variables defined in shaders, including Varyings, Uniforms, etc
+// Note: we must override the copy constructor and assignment operator so we can
+// work around excessive GCC binary bloating:
+// See https://code.google.com/p/angleproject/issues/detail?id=697
+struct ShaderVariable
+{
+    ShaderVariable();
+    ShaderVariable(GLenum typeIn, unsigned int arraySizeIn);
+    ~ShaderVariable();
+    ShaderVariable(const ShaderVariable &other);
+    ShaderVariable &operator=(const ShaderVariable &other);
+
+    bool isArray() const { return arraySize > 0; }
+    unsigned int elementCount() const { return std::max(1u, arraySize); }
+    bool isStruct() const { return !fields.empty(); }
+
+    // All of the shader's variables are described using nested data
+    // structures. This is needed in order to disambiguate similar looking
+    // types, such as two structs containing the same fields, but in
+    // different orders. "findInfoByMappedName" provides an easy query for
+    // users to dive into the data structure and fetch the unique variable
+    // instance corresponding to a dereferencing chain of the top-level
+    // variable.
+    // Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable
+    // that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]'
+    // in |originalName|, based on the assumption that |this| defines 'a'.
+    // If no match is found, return false.
+    bool findInfoByMappedName(const std::string &mappedFullName,
+                              const ShaderVariable **leafVar,
+                              std::string* originalFullName) const;
+
+    bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; }
+
+    GLenum type;
+    GLenum precision;
+    std::string name;
+    std::string mappedName;
+    unsigned int arraySize;
+    bool staticUse;
+    std::vector<ShaderVariable> fields;
+    std::string structName;
+
+  protected:
+    bool isSameVariableAtLinkTime(const ShaderVariable &other,
+                                  bool matchPrecision) const;
+
+    bool operator==(const ShaderVariable &other) const;
+    bool operator!=(const ShaderVariable &other) const
+    {
+        return !operator==(other);
+    }
+};
+
+// A variable with an integer location to pass back to the GL API: either uniform (can have location
+// in GLES3.1+), vertex shader input or fragment shader output.
+struct VariableWithLocation : public ShaderVariable
+{
+    VariableWithLocation();
+    ~VariableWithLocation();
+    VariableWithLocation(const VariableWithLocation &other);
+    VariableWithLocation &operator=(const VariableWithLocation &other);
+    bool operator==(const VariableWithLocation &other) const;
+    bool operator!=(const VariableWithLocation &other) const { return !operator==(other); }
+
+    int location;
+};
+
+struct Uniform : public VariableWithLocation
+{
+    Uniform();
+    ~Uniform();
+    Uniform(const Uniform &other);
+    Uniform &operator=(const Uniform &other);
+    bool operator==(const Uniform &other) const;
+    bool operator!=(const Uniform &other) const
+    {
+        return !operator==(other);
+    }
+
+    int binding;
+
+    // Decide whether two uniforms are the same at shader link time,
+    // assuming one from vertex shader and the other from fragment shader.
+    // GLSL ES Spec 3.00.3, section 4.3.5.
+    // GLSL ES Spec 3.10.4, section 4.4.5
+    bool isSameUniformAtLinkTime(const Uniform &other) const;
+};
+
+struct Attribute : public VariableWithLocation
+{
+    Attribute();
+    ~Attribute();
+    Attribute(const Attribute &other);
+    Attribute &operator=(const Attribute &other);
+    bool operator==(const Attribute &other) const;
+    bool operator!=(const Attribute &other) const { return !operator==(other); }
+};
+
+struct OutputVariable : public VariableWithLocation
+{
+    OutputVariable();
+    ~OutputVariable();
+    OutputVariable(const OutputVariable &other);
+    OutputVariable &operator=(const OutputVariable &other);
+    bool operator==(const OutputVariable &other) const;
+    bool operator!=(const OutputVariable &other) const { return !operator==(other); }
+};
+
+struct InterfaceBlockField : public ShaderVariable
+{
+    InterfaceBlockField();
+    ~InterfaceBlockField();
+    InterfaceBlockField(const InterfaceBlockField &other);
+    InterfaceBlockField &operator=(const InterfaceBlockField &other);
+    bool operator==(const InterfaceBlockField &other) const;
+    bool operator!=(const InterfaceBlockField &other) const
+    {
+        return !operator==(other);
+    }
+
+    // Decide whether two InterfaceBlock fields are the same at shader
+    // link time, assuming one from vertex shader and the other from
+    // fragment shader.
+    // See GLSL ES Spec 3.00.3, sec 4.3.7.
+    bool isSameInterfaceBlockFieldAtLinkTime(
+        const InterfaceBlockField &other) const;
+
+    bool isRowMajorLayout;
+};
+
+struct Varying : public ShaderVariable
+{
+    Varying();
+    ~Varying();
+    Varying(const Varying &otherg);
+    Varying &operator=(const Varying &other);
+    bool operator==(const Varying &other) const;
+    bool operator!=(const Varying &other) const
+    {
+        return !operator==(other);
+    }
+
+    // Decide whether two varyings are the same at shader link time,
+    // assuming one from vertex shader and the other from fragment shader.
+    // Invariance needs to match only in ESSL1. Relevant spec sections:
+    // GLSL ES 3.00.4, sections 4.6.1 and 4.3.9.
+    // GLSL ES 1.00.17, section 4.6.4.
+    bool isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const;
+
+    // Deprecated version of isSameVaryingAtLinkTime, which assumes ESSL1.
+    bool isSameVaryingAtLinkTime(const Varying &other) const;
+
+    InterpolationType interpolation;
+    bool isInvariant;
+};
+
+struct InterfaceBlock
+{
+    InterfaceBlock();
+    ~InterfaceBlock();
+    InterfaceBlock(const InterfaceBlock &other);
+    InterfaceBlock &operator=(const InterfaceBlock &other);
+
+    // Fields from blocks with non-empty instance names are prefixed with the block name.
+    std::string fieldPrefix() const;
+
+    // Decide whether two interface blocks are the same at shader link time.
+    bool isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const;
+
+    std::string name;
+    std::string mappedName;
+    std::string instanceName;
+    unsigned int arraySize;
+    BlockLayoutType layout;
+    bool isRowMajorLayout;
+    bool staticUse;
+    std::vector<InterfaceBlockField> fields;
+};
+
+struct WorkGroupSize
+{
+    void fill(int fillValue);
+    void setLocalSize(int localSizeX, int localSizeY, int localSizeZ);
+
+    int &operator[](size_t index);
+    int operator[](size_t index) const;
+    size_t size() const;
+
+    // Checks whether two work group size declarations match.
+    // Two work group size declarations are the same if the explicitly specified elements are the
+    // same or if one of them is specified as one and the other one is not specified
+    bool isWorkGroupSizeMatching(const WorkGroupSize &right) const;
+
+    // Checks whether any of the values are set.
+    bool isAnyValueSet() const;
+
+    // Checks whether all of the values are set.
+    bool isDeclared() const;
+
+    // Checks whether either all of the values are set, or none of them are.
+    bool isLocalSizeValid() const;
+
+    int localSizeQualifiers[3];
+};
+
+}  // namespace sh
+
+#endif // GLSLANG_SHADERVARS_H_
diff --git a/src/third_party/angle/include/KHR/khrplatform.h b/src/third_party/angle/include/KHR/khrplatform.h
old mode 100644
new mode 100755
index 8ec0d19..6696234
--- a/src/third_party/angle/include/KHR/khrplatform.h
+++ b/src/third_party/angle/include/KHR/khrplatform.h
@@ -26,7 +26,7 @@
 
 /* Khronos platform-specific types and definitions.
  *
- * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
+ * $Revision: 32517 $ on $Date: 2016-03-11 02:41:19 -0800 (Fri, 11 Mar 2016) $
  *
  * Adopters may modify this file to suit their platform. Adopters are
  * encouraged to submit platform specific modifications to the Khronos
@@ -97,10 +97,15 @@
  *-------------------------------------------------------------------------
  * This precedes the return type of the function in the function prototype.
  */
-#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+#if defined(STARBOARD)
+#   define KHRONOS_APICALL /* nothing */
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
 #   define KHRONOS_APICALL __declspec(dllimport)
 #elif defined (__SYMBIAN32__)
 #   define KHRONOS_APICALL IMPORT_C
+#elif defined(__ANDROID__)
+#   include <sys/cdefs.h>
+#   define KHRONOS_APICALL __attribute__((visibility("default"))) __NDK_FPABI__
 #else
 #   define KHRONOS_APICALL
 #endif
@@ -111,7 +116,9 @@
  * This follows the return type of the function  and precedes the function
  * name in the function prototype.
  */
-#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+#if defined(STARBOARD)
+#   define KHRONOS_APIENTRY /* nothing */
+#elif defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
     /* Win32 but not WinCE */
 #   define KHRONOS_APIENTRY __stdcall
 #else
@@ -221,10 +228,23 @@
 typedef unsigned char          khronos_uint8_t;
 typedef signed   short int     khronos_int16_t;
 typedef unsigned short int     khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef _WIN64
+typedef signed   long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed   long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
 typedef signed   long  int     khronos_intptr_t;
 typedef unsigned long  int     khronos_uintptr_t;
 typedef signed   long  int     khronos_ssize_t;
 typedef unsigned long  int     khronos_usize_t;
+#endif
 
 #if KHRONOS_SUPPORT_FLOAT
 /*
@@ -266,4 +286,4 @@
     KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
 } khronos_boolean_enum_t;
 
-#endif /* __khrplatform_h_ */
+#endif /* __khrplatform_h_ */
\ No newline at end of file
diff --git a/src/third_party/angle/include/angle_gl.h b/src/third_party/angle/include/angle_gl.h
new file mode 100644
index 0000000..18de80b
--- /dev/null
+++ b/src/third_party/angle/include/angle_gl.h
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_gl.h:
+//   Includes all necessary GL headers and definitions for ANGLE.
+//
+
+#ifndef ANGLEGL_H_
+#define ANGLEGL_H_
+
+#include "GLES2/gl2.h"
+#include "GLES2/gl2ext.h"
+#include "GLES3/gl3.h"
+#include "GLES3/gl31.h"
+#include "GLES3/gl32.h"
+
+// The following enum is used in ANGLE, but is from desktop GL
+#ifndef GL_SAMPLER_2D_RECT_ARB
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#endif
+
+#endif // ANGLEGL_H_
diff --git a/src/third_party/angle/include/angle_windowsstore.h b/src/third_party/angle/include/angle_windowsstore.h
new file mode 100644
index 0000000..b8f76de
--- /dev/null
+++ b/src/third_party/angle/include/angle_windowsstore.h
@@ -0,0 +1,51 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_windowsstore.h:
+
+#ifndef ANGLE_WINDOWSSTORE_H_
+#define ANGLE_WINDOWSSTORE_H_
+
+// The following properties can be set on the CoreApplication to support additional
+// ANGLE configuration options.
+//
+// The Visual Studio sample templates provided with this version of ANGLE have examples
+// of how to set these property values.
+
+//
+// Property: EGLNativeWindowTypeProperty
+// Type: IInspectable
+// Description: Set this property to specify the window type to use for creating a surface.
+//              If this property is missing, surface creation will fail.
+//
+const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
+
+//
+// Property: EGLRenderSurfaceSizeProperty
+// Type: Size
+// Description: Set this property to specify a preferred size in pixels of the render surface.
+//              The render surface size width and height must be greater than 0.
+//              If this property is set, then the render surface size is fixed.
+//              The render surface will then be scaled to the window dimensions.
+//              If this property is missing, a default behavior will be provided.
+//              The default behavior uses the window size if a CoreWindow is specified or
+//              the size of the SwapChainPanel control if one is specified.
+//
+const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty";
+
+//
+// Property: EGLRenderResolutionScaleProperty
+// Type: Single
+// Description: Use this to specify a preferred scale for the render surface compared to the window.
+//              For example, if the window is 800x480, and:
+//                - scale is set to 0.5f then the surface will be 400x240
+//                - scale is set to 1.2f then the surface will be 960x576
+//              If the window resizes or rotates then the surface will resize accordingly.
+//              EGLRenderResolutionScaleProperty and EGLRenderSurfaceSizeProperty cannot both be set.
+//              The scale factor should be > 0.0f.
+//
+const wchar_t EGLRenderResolutionScaleProperty[] = L"EGLRenderResolutionScaleProperty";
+
+#endif // ANGLE_WINDOWSSTORE_H_
diff --git a/src/third_party/angle/include/export.h b/src/third_party/angle/include/export.h
new file mode 100644
index 0000000..d32467c
--- /dev/null
+++ b/src/third_party/angle/include/export.h
@@ -0,0 +1,34 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// export.h : Defines ANGLE_EXPORT, a macro for exporting functions from the DLL
+
+#ifndef LIBGLESV2_EXPORT_H_
+#define LIBGLESV2_EXPORT_H_
+
+#if !defined(ANGLE_EXPORT)
+#if defined(STARBOARD)
+#       define ANGLE_EXPORT /* nothing */
+#elif defined(_WIN32)
+#if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) || \
+    defined(LIBANGLE_UTIL_IMPLEMENTATION)
+#       define ANGLE_EXPORT __declspec(dllexport)
+#   else
+#       define ANGLE_EXPORT __declspec(dllimport)
+#   endif
+#elif defined(__GNUC__)
+#if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) || \
+    defined(LIBANGLE_UTIL_IMPLEMENTATION)
+#       define ANGLE_EXPORT __attribute__((visibility ("default")))
+#   else
+#       define ANGLE_EXPORT
+#   endif
+#else
+#   define ANGLE_EXPORT
+#endif
+#endif  // !defined(ANGLE_EXPORT)
+
+#endif // LIBGLESV2_EXPORT_H_
diff --git a/src/third_party/angle/include/platform/Platform.h b/src/third_party/angle/include/platform/Platform.h
new file mode 100644
index 0000000..3dcb95a
--- /dev/null
+++ b/src/third_party/angle/include/platform/Platform.h
@@ -0,0 +1,274 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Platform.h: The public interface ANGLE exposes to the API layer, for
+//   doing platform-specific tasks like gathering data, or for tracing.
+
+#ifndef ANGLE_PLATFORM_H
+#define ANGLE_PLATFORM_H
+
+#include <stdint.h>
+
+#if defined(_WIN32)
+#   if !defined(LIBANGLE_IMPLEMENTATION)
+#       define ANGLE_PLATFORM_EXPORT __declspec(dllimport)
+#   endif
+#elif defined(__GNUC__)
+#   if defined(LIBANGLE_IMPLEMENTATION)
+#       define ANGLE_PLATFORM_EXPORT __attribute__((visibility ("default")))
+#   endif
+#endif
+#if !defined(ANGLE_PLATFORM_EXPORT)
+#   define ANGLE_PLATFORM_EXPORT
+#endif
+
+#if defined(_WIN32)
+#   define ANGLE_APIENTRY __stdcall
+#else
+#   define ANGLE_APIENTRY
+#endif
+
+namespace angle
+{
+struct WorkaroundsD3D;
+using TraceEventHandle = uint64_t;
+using EGLDisplayType   = void *;
+struct PlatformMethods;
+
+// Use a C-like API to not trigger undefined calling behaviour.
+
+// System --------------------------------------------------------------
+
+// Wall clock time in seconds since the epoch.
+// TODO(jmadill): investigate using an ANGLE internal time library
+inline double ANGLE_currentTime(PlatformMethods *platform)
+{
+    return 0.0;
+}
+
+// Monotonically increasing time in seconds from an arbitrary fixed point in the past.
+// This function is expected to return at least millisecond-precision values. For this reason,
+// it is recommended that the fixed point be no further in the past than the epoch.
+inline double ANGLE_monotonicallyIncreasingTime(PlatformMethods *platform)
+{
+    return 0.0;
+}
+
+// Logging ------------------------------------------------------------
+
+// Log an error message within the platform implementation.
+inline void ANGLE_logError(PlatformMethods *platform, const char *errorMessage)
+{
+}
+
+// Log a warning message within the platform implementation.
+inline void ANGLE_logWarning(PlatformMethods *platform, const char *warningMessage)
+{
+}
+
+// Log an info message within the platform implementation.
+inline void ANGLE_logInfo(PlatformMethods *platform, const char *infoMessage)
+{
+}
+
+// Tracing --------
+
+// Get a pointer to the enabled state of the given trace category. The
+// embedder can dynamically change the enabled state as trace event
+// recording is started and stopped by the application. Only long-lived
+// literal strings should be given as the category name. The implementation
+// expects the returned pointer to be held permanently in a local static. If
+// the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
+// addTraceEvent is expected to be called by the trace event macros.
+inline const unsigned char *ANGLE_getTraceCategoryEnabledFlag(PlatformMethods *platform,
+                                                              const char *categoryName)
+{
+    return nullptr;
+}
+
+//
+// Add a trace event to the platform tracing system. Depending on the actual
+// enabled state, this event may be recorded or dropped.
+// - phase specifies the type of event:
+//   - BEGIN ('B'): Marks the beginning of a scoped event.
+//   - END ('E'): Marks the end of a scoped event.
+//   - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't
+//     need a matching END event. Instead, at the end of the scope,
+//     updateTraceEventDuration() must be called with the TraceEventHandle
+//     returned from addTraceEvent().
+//   - INSTANT ('I'): Standalone, instantaneous event.
+//   - START ('S'): Marks the beginning of an asynchronous event (the end
+//     event can occur in a different scope or thread). The id parameter is
+//     used to match START/FINISH pairs.
+//   - FINISH ('F'): Marks the end of an asynchronous event.
+//   - COUNTER ('C'): Used to trace integer quantities that change over
+//     time. The argument values are expected to be of type int.
+//   - METADATA ('M'): Reserved for internal use.
+// - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag.
+// - name is the name of the event. Also used to match BEGIN/END and
+//   START/FINISH pairs.
+// - id optionally allows events of the same name to be distinguished from
+//   each other. For example, to trace the consutruction and destruction of
+//   objects, specify the pointer as the id parameter.
+// - timestamp should be a time value returned from monotonicallyIncreasingTime.
+// - numArgs specifies the number of elements in argNames, argTypes, and
+//   argValues.
+// - argNames is the array of argument names. Use long-lived literal strings
+//   or specify the COPY flag.
+// - argTypes is the array of argument types:
+//   - BOOL (1): bool
+//   - UINT (2): unsigned long long
+//   - INT (3): long long
+//   - DOUBLE (4): double
+//   - POINTER (5): void*
+//   - STRING (6): char* (long-lived null-terminated char* string)
+//   - COPY_STRING (7): char* (temporary null-terminated char* string)
+//   - CONVERTABLE (8): WebConvertableToTraceFormat
+// - argValues is the array of argument values. Each value is the unsigned
+//   long long member of a union of all supported types.
+// - flags can be 0 or one or more of the following, ORed together:
+//   - COPY (0x1): treat all strings (name, argNames and argValues of type
+//     string) as temporary so that they will be copied by addTraceEvent.
+//   - HAS_ID (0x2): use the id argument to uniquely identify the event for
+//     matching with other events of the same name.
+//   - MANGLE_ID (0x4): specify this flag if the id parameter is the value
+//     of a pointer.
+inline angle::TraceEventHandle ANGLE_addTraceEvent(PlatformMethods *platform,
+                                                   char phase,
+                                                   const unsigned char *categoryEnabledFlag,
+                                                   const char *name,
+                                                   unsigned long long id,
+                                                   double timestamp,
+                                                   int numArgs,
+                                                   const char **argNames,
+                                                   const unsigned char *argTypes,
+                                                   const unsigned long long *argValues,
+                                                   unsigned char flags)
+{
+    return 0;
+}
+
+// Set the duration field of a COMPLETE trace event.
+inline void ANGLE_updateTraceEventDuration(PlatformMethods *platform,
+                                           const unsigned char *categoryEnabledFlag,
+                                           const char *name,
+                                           angle::TraceEventHandle eventHandle)
+{
+}
+
+// Callbacks for reporting histogram data.
+// CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50
+// would do.
+inline void ANGLE_histogramCustomCounts(PlatformMethods *platform,
+                                        const char *name,
+                                        int sample,
+                                        int min,
+                                        int max,
+                                        int bucketCount)
+{
+}
+// Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample
+// value.
+inline void ANGLE_histogramEnumeration(PlatformMethods *platform,
+                                       const char *name,
+                                       int sample,
+                                       int boundaryValue)
+{
+}
+// Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
+inline void ANGLE_histogramSparse(PlatformMethods *platform, const char *name, int sample)
+{
+}
+// Boolean histograms track two-state variables.
+inline void ANGLE_histogramBoolean(PlatformMethods *platform, const char *name, bool sample)
+{
+}
+
+// Allows us to programatically override ANGLE's default workarounds for testing purposes.
+inline void ANGLE_overrideWorkaroundsD3D(PlatformMethods *platform,
+                                         angle::WorkaroundsD3D *workaroundsD3D)
+{
+}
+
+// Platform methods are enumerated here once.
+#define ANGLE_PLATFORM_OP(OP)       \
+    OP(currentTime)                 \
+    OP(monotonicallyIncreasingTime) \
+    OP(logError)                    \
+    OP(logWarning)                  \
+    OP(logInfo)                     \
+    OP(getTraceCategoryEnabledFlag) \
+    OP(addTraceEvent)               \
+    OP(updateTraceEventDuration)    \
+    OP(histogramCustomCounts)       \
+    OP(histogramEnumeration)        \
+    OP(histogramSparse)             \
+    OP(histogramBoolean)            \
+    OP(overrideWorkaroundsD3D)
+
+#define ANGLE_PLATFORM_METHOD_DEF(Name) decltype(&ANGLE_##Name) Name = ANGLE_##Name;
+
+struct PlatformMethods
+{
+    ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_DEF);
+
+    // User data pointer for any implementation specific members.
+    void *context = 0;
+};
+
+#undef ANGLE_PLATFORM_METHOD_DEF
+
+// Subtract one to account for the context pointer.
+constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1;
+
+#define ANGLE_PLATFORM_METHOD_STRING(Name) #Name
+#define ANGLE_PLATFORM_METHOD_STRING2(Name) ANGLE_PLATFORM_METHOD_STRING(Name),
+
+constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = {
+    ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)};
+
+#undef ANGLE_PLATFORM_METHOD_STRING2
+#undef ANGLE_PLATFORM_METHOD_STRING
+
+}  // namespace angle
+
+extern "C" {
+
+// Gets the platform methods on the passed-in EGL display. If the method name signature does not
+// match the compiled signature for this ANGLE, false is returned. On success true is returned.
+// The application should set any platform methods it cares about on the returned pointer.
+// If display is not valid, behaviour is undefined.
+//
+// Use a void * here to silence a sanitizer limitation with decltype.
+// TODO(jmadill): Use angle::PlatformMethods ** if UBSAN is fixed to handle decltype.
+
+ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
+                                                                  const char *const methodNames[],
+                                                                  unsigned int methodNameCount,
+                                                                  void *context,
+                                                                  void *platformMethodsOut);
+
+// Sets the platform methods back to their defaults.
+// If display is not valid, behaviour is undefined.
+ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display);
+
+}  // extern "C"
+
+namespace angle
+{
+// Use typedefs here instead of decltype to work around sanitizer limitations.
+// TODO(jmadill): Use decltype here if UBSAN is fixed.
+typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType,
+                                                     const char *const *,
+                                                     unsigned int,
+                                                     void *,
+                                                     void *);
+typedef void(ANGLE_APIENTRY *ResetDisplayPlatformFunc)(angle::EGLDisplayType);
+}  // namespace angle
+
+// This function is not exported
+angle::PlatformMethods *ANGLEPlatformCurrent();
+
+#endif // ANGLE_PLATFORM_H
diff --git a/src/third_party/angle/include/platform/WorkaroundsD3D.h b/src/third_party/angle/include/platform/WorkaroundsD3D.h
new file mode 100644
index 0000000..63ac4b9
--- /dev/null
+++ b/src/third_party/angle/include/platform/WorkaroundsD3D.h
@@ -0,0 +1,114 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WorkaroundsD3D.h: Workarounds for D3D driver bugs and other issues.
+
+#ifndef ANGLE_PLATFORM_WORKAROUNDSD3D_H_
+#define ANGLE_PLATFORM_WORKAROUNDSD3D_H_
+
+// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate
+// independent of ANGLE's renderer. Workarounds should also be accessible
+// outside of the Renderer.
+
+namespace angle
+{
+struct CompilerWorkaroundsD3D
+{
+    bool skipOptimization   = false;
+    bool useMaxOptimization = false;
+
+    // IEEE strictness needs to be enabled for NANs to work.
+    bool enableIEEEStrictness = false;
+};
+
+struct WorkaroundsD3D
+{
+    // On some systems, having extra rendertargets than necessary slows down the shader.
+    // We can fix this by optimizing those out of the shader. At the same time, we can
+    // work around a bug on some nVidia drivers that they ignore "null" render targets
+    // in D3D11, by compacting the active color attachments list to omit null entries.
+    bool mrtPerfWorkaround = false;
+
+    bool setDataFasterThanImageUpload = false;
+
+    // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level
+    // zero, and ignore the other levels). D3D11 Feature Level 10+ does this by setting MaxLOD to
+    // 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE. There is no
+    // equivalent to this in D3D11 Feature Level 9_3. This causes problems when (for example) an
+    // application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST
+    // (i.e disables mipmaps). To work around this, D3D11 FL9_3 has to create two copies of the
+    // texture. The textures' level zeros are identical, but only one texture has mips.
+    bool zeroMaxLodWorkaround = false;
+
+    // Some renderers do not support Geometry Shaders so the Geometry Shader-based PointSprite
+    // emulation will not work. To work around this, D3D11 FL9_3 has to use a different pointsprite
+    // emulation that is implemented using instanced quads.
+    bool useInstancedPointSpriteEmulation = false;
+
+    // A bug fixed in NVIDIA driver version 347.88 < x <= 368.81 triggers a TDR when using
+    // CopySubresourceRegion from a staging texture to a depth/stencil in D3D11. The workaround
+    // is to use UpdateSubresource to trigger an extra copy. We disable this workaround on newer
+    // NVIDIA driver versions because of a second driver bug present with the workaround enabled.
+    // (See: http://anglebug.com/1452)
+    bool depthStencilBlitExtraCopy = false;
+
+    // The HLSL optimizer has a bug with optimizing "pow" in certain integer-valued expressions.
+    // We can work around this by expanding the pow into a series of multiplies if we're running
+    // under the affected compiler.
+    bool expandIntegerPowExpressions = false;
+
+    // NVIDIA drivers sometimes write out-of-order results to StreamOut buffers when transform
+    // feedback is used to repeatedly write to the same buffer positions.
+    bool flushAfterEndingTransformFeedback = false;
+
+    // Some drivers (NVIDIA) do not take into account the base level of the texture in the results
+    // of the HLSL GetDimensions builtin.
+    bool getDimensionsIgnoresBaseLevel = false;
+
+    // On some Intel drivers, HLSL's function texture.Load returns 0 when the parameter Location
+    // is negative, even if the sum of Offset and Location is in range. This may cause errors when
+    // translating GLSL's function texelFetchOffset into texture.Load, as it is valid for
+    // texelFetchOffset to use negative texture coordinates as its parameter P when the sum of P
+    // and Offset is in range. To work around this, we translate texelFetchOffset into texelFetch
+    // by adding Offset directly to Location before reading the texture.
+    bool preAddTexelFetchOffsets = false;
+
+    // On some AMD drivers, 1x1 and 2x2 mips of depth/stencil textures aren't sampled correctly.
+    // We can work around this bug by doing an internal blit to a temporary single-channel texture
+    // before we sample.
+    bool emulateTinyStencilTextures = false;
+
+    // In Intel driver, the data with format DXGI_FORMAT_B5G6R5_UNORM will be parsed incorrectly.
+    // This workaroud will disable B5G6R5 support when it's Intel driver. By default, it will use
+    // R8G8B8A8 format. This bug is fixed in version 4539 on Intel drivers.
+    bool disableB5G6R5Support = false;
+
+    // On some Intel drivers, evaluating unary minus operator on integer may get wrong answer in
+    // vertex shaders. To work around this bug, we translate -(int) into ~(int)+1.
+    // This driver bug is fixed in 20.19.15.4624.
+    bool rewriteUnaryMinusOperator = false;
+
+    // On some Intel drivers, using isnan() on highp float will get wrong answer. To work around
+    // this bug, we use an expression to emulate function isnan().
+    // Tracking bug: https://crbug.com/650547
+    // This driver bug is fixed in 21.20.16.4542.
+    bool emulateIsnanFloat = false;
+
+    // On some Intel drivers, using clear() may not take effect. One of such situation is to clear
+    // a target with width or height < 16. To work around this bug, we call clear() twice on these
+    // platforms. Tracking bug: https://crbug.com/655534
+    bool callClearTwiceOnSmallTarget = false;
+
+    // On some Intel drivers, copying from staging storage to constant buffer storage does not
+    // seem to work. Work around this by keeping system memory storage as a canonical reference
+    // for buffer data.
+    // D3D11-only workaround. See http://crbug.com/593024.
+    bool useSystemMemoryForConstantBuffers = false;
+};
+
+}  // namespace angle
+
+#endif  // ANGLE_PLATFORM_WORKAROUNDSD3D_H_
diff --git a/src/third_party/angle/infra/config/README.md b/src/third_party/angle/infra/config/README.md
new file mode 100644
index 0000000..a46a2e7
--- /dev/null
+++ b/src/third_party/angle/infra/config/README.md
@@ -0,0 +1 @@
+This directory contains configuration files for chrome infrastructure services.
diff --git a/src/third_party/angle/infra/config/cq.cfg b/src/third_party/angle/infra/config/cq.cfg
new file mode 100644
index 0000000..6cffc96
--- /dev/null
+++ b/src/third_party/angle/infra/config/cq.cfg
@@ -0,0 +1,37 @@
+# See http://luci-config.appspot.com/schemas/projects/refs:cq.cfg for the
+# documentation of this file format.
+version: 1
+cq_name: "angle"
+cq_status_url: "https://chromium-cq-status.appspot.com"
+git_repo_url: "https://chromium.googlesource.com/angle/angle"
+gerrit {
+}
+verifiers {
+  gerrit_cq_ability {
+    committer_list: "project-angle-committers"
+    dry_run_access_list: "project-angle-tryjob-access"
+  }
+  try_job {
+    buckets {
+      name: "master.tryserver.chromium.angle"
+      builders { name: "android_angle_rel_ng" }
+      builders { name: "linux_angle_rel_ng" }
+      builders { name: "linux_angle_dbg_ng" }
+      builders { name: "linux_angle_chromeos_rel_ng" }
+      builders { name: "mac_angle_rel_ng" }
+      builders { name: "mac_angle_dbg_ng" }
+      builders { name: "win_angle_rel_ng" }
+      builders { name: "win_angle_dbg_ng" }
+      builders { name: "win_angle_x64_rel_ng" }
+      builders { name: "win_angle_x64_dbg_ng" }
+    }
+    buckets {
+      name: "master.tryserver.chromium.linux"
+      builders { name: "linux_chromium_chromeos_ozone_rel_ng" }
+    }
+    buckets {
+      name: "master.tryserver.chromium.win"
+      builders { name: "win_clang" }
+    }
+  }
+}
diff --git a/src/third_party/angle/samples/WindowTest/WindowTest.cpp b/src/third_party/angle/samples/WindowTest/WindowTest.cpp
new file mode 100644
index 0000000..dbde920
--- /dev/null
+++ b/src/third_party/angle/samples/WindowTest/WindowTest.cpp
@@ -0,0 +1,136 @@
+//
+// Copyright 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.
+//
+
+// WindowTest.cpp: Sample used to test various function of OSWindow
+
+#include <algorithm>
+#include <iostream>
+
+#include "OSWindow.h"
+#include "system_utils.h"
+
+int main(int argc, char *argv[])
+{
+    OSWindow *window = CreateOSWindow();
+    int width = 400;
+    int height = 400;
+    int x = 0;
+    int y = 0;
+
+    if (!window->initialize("Window Test", width, height))
+    {
+        return -1;
+    }
+    window->setVisible(true);
+    window->setPosition(x, y);
+
+    bool running = true;
+    while (running)
+    {
+        Event event;
+        while (window->popEvent(&event))
+        {
+            if (event.Type == Event::EVENT_CLOSED)
+            {
+                running = false;
+                break;
+            }
+
+            if (event.Type == Event::EVENT_KEY_PRESSED)
+            {
+                int newWidth = width;
+                int newHeight = height;
+                int newX = x;
+                int newY = y;
+                switch (event.Key.Code)
+                {
+                  case KEY_ESCAPE:
+                    running = false;
+                    break;
+
+                  case KEY_W:
+                    newWidth = std::max(0, width + (event.Key.Shift ? -20 : 20));
+                    break;
+                  case KEY_H:
+                    newHeight = std::max(0, height + (event.Key.Shift ? -20 : 20));
+                    break;
+
+                  case KEY_LEFT:
+                    newX = x - 20;
+                    break;
+                  case KEY_RIGHT:
+                    newX = x + 20;
+                    break;
+                  case KEY_UP:
+                    newY = y - 20;
+                    break;
+                  case KEY_DOWN:
+                    newY = y + 20;
+                    break;
+
+                  case KEY_C:
+                    window->setMousePosition(width / 2, height / 2);
+                    break;
+                  case KEY_T:
+                    window->signalTestEvent();
+                    window->messageLoop();
+                    if (window->didTestEventFire())
+                    {
+                        std::cout << "Test event did fire" << std::endl;
+                    }
+                    else
+                    {
+                        std::cout << "Test event did not fire" << std::endl;
+                    }
+                    break;
+                  case KEY_S:
+                    window->setVisible(false);
+                    window->messageLoop();
+                    angle::Sleep(1000);
+                    window->setVisible(true);
+                    window->messageLoop();
+                    break;
+
+                  default:
+                    break;
+                }
+
+                if (newWidth != width || newHeight != height)
+                {
+                    width = newWidth;
+                    height = newHeight;
+                    window->resize(width, height);
+                }
+                if (newX != x || newY != y)
+                {
+                    x = newX;
+                    y = newY;
+                    window->setPosition(x, y);
+                }
+
+                angle::Sleep(0);
+                window->messageLoop();
+                if (window->getWidth() != width || window->getHeight() != height)
+                {
+                    std::cout << "Discrepancy between set dimensions and retrieved dimensions" << std::endl;
+                    std::cout << "Width: " << width << " vs. " << window->getWidth() << std::endl;
+                    std::cout << "Height: " << height << " vs. " << window->getHeight() << std::endl;
+                }
+                if (window->getX() != x || window->getY() != y)
+                {
+                    std::cout << "Discrepancy between set position and retrieved position" << std::endl;
+                    std::cout << "X: " << x << " vs. " << window->getX() << std::endl;
+                    std::cout << "Y: " << y << " vs. " << window->getY() << std::endl;
+                }
+            }
+        }
+
+        angle::Sleep(0);
+        window->messageLoop();
+    }
+
+    window->destroy();
+}
diff --git a/src/third_party/angle/samples/angle/Resource_Tracking/resource_tracking.cc b/src/third_party/angle/samples/angle/Resource_Tracking/resource_tracking.cc
deleted file mode 100755
index bfcbe82..0000000
--- a/src/third_party/angle/samples/angle/Resource_Tracking/resource_tracking.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-// Note that this sample is incomplete in that it gives a snippet of code
-// that demonstrates a use case of eglSetResourceTrackerANGLE(), but does not
-// have any driving main() method.
-
-#include <assert.h>
-
-#include <iostream>
-#include <sstream>
-#include <string>
-
-#include <d3d11.h>
-#include <EGL/eglext.h>
-#include <wrl.h>
-
-EGLDisplay g_display;
-
-bool GetDebugName(ID3D11Resource* resource, std::string* name) {
-  char data[512];
-  UINT data_size = 512;
-  if (SUCCEEDED(resource->GetPrivateData(WKPDID_D3DDebugObjectName, &data_size,
-                                         data))) {
-    name->assign(data, data_size);
-    return true;
-  }
-
-  return false;
-}
-
-void GetResourceData(const EGLResourceTrackerDataAngle *data,
-                     std::stringstream *stream) {
-  const char* op = (data->iOpType == EGL_ANGLE_TRACK_OPTYPE_CREATE) ? "+" : "-";
-  (*stream) << " " << op << (data->iSize >> 10) << "KB;";
-
-  if (data->iOpType == EGL_ANGLE_TRACK_OPTYPE_DESTROY) {
-    // data->pResource should be treated as invalid during resource
-    // deallocation events
-    return;
-  }
-
-  ComPtr<IUnknown> unk(reinterpret_cast<IUnknown*>(data->pResource));
-
-  switch (data->iType) {
-    case EGL_ANGLE_TRACK_TYPE_TEX2D: {
-      ComPtr<ID3D11Texture2D> tex;
-      assert(SUCCEEDED(unk.As(&tex)));
-
-      D3D11_TEXTURE2D_DESC desc;
-      tex->GetDesc(&desc);
-
-      (*stream) << " Tex2D: " << desc.Width << "x" << desc.Height << ";";
-
-      std::string name;
-      if (GetDebugName(tex.Get(), &name))
-        (*stream) << " " << name << ";";
-
-      break;
-    }
-    case EGL_ANGLE_TRACK_TYPE_BUFFER: {
-      ComPtr<ID3D11Buffer> buf;
-      assert(SUCCEEDED(unk.As(&buf)));
-
-      D3D11_BUFFER_DESC desc;
-      buf->GetDesc(&desc);
-
-      (*stream) << " Buffer:";
-      if (desc.BindFlags & D3D11_BIND_VERTEX_BUFFER) {
-        (*stream) << " VB";
-      }
-      if (desc.BindFlags & D3D11_BIND_INDEX_BUFFER) {
-        (*stream) << " IB";
-      }
-      if (desc.BindFlags & D3D11_BIND_CONSTANT_BUFFER) {
-        (*stream) << " CB";
-      }
-
-      (*stream) << ";";
-
-      std::string name;
-      if (GetDebugName(buf.Get(), &name))
-        (*stream) << " " << name << ";";
-
-      break;
-    }
-    case EGL_ANGLE_TRACK_TYPE_SWAPCHAIN: {
-      ComPtr<IDXGISwapChain> swap_chain;
-      assert(SUCCEEDED(unk.As(&swap_chain)));
-
-      DXGI_SWAP_CHAIN_DESC desc;
-      swap_chain->GetDesc(&desc);
-
-      (*stream) << " SwapChain: "
-                << desc.BufferDesc.Width << "x" << desc.BufferDesc.Height
-                << ";";
-      break;
-    }
-    default:
-      (*stream) << " Unknown resource;";
-  }
-}
-
-void ResourceTracker(const EGLResourceTrackerDataAngle *data,
-                     void *user_data) {
-  static int mem_count;
-  static int hit_countes;
-
-  if (data->iOpType == EGL_ANGLE_TRACK_OPTYPE_CREATE) {
-    mem_count += data->iSize;
-  }
-  else {
-    mem_count -= data->iSize;
-  }
-
-  std::stringstream info;
-  GetResourceData(data, &info);
-  std::cout << "VMem: " << (mem_count >> 20) << "MB" << info.str();
-}
-
-void InitializeMemoryTracking() {
-  PFNEGLSETRESOURCETRACKERANGLEPROC eglSetResourceTrackerANGLE =
-      reinterpret_cast<PFNEGLSETRESOURCETRACKERANGLEPROC>(eglGetProcAddress(
-          "eglSetResourceTrackerANGLE"));
-
-  assert(eglSetResourceTrackerANGLE);
-
-  eglSetResourceTrackerANGLE(g_display, &ResourceTracker, this);
-}
diff --git a/src/third_party/angle/samples/angle/Simple_Instancing/Simple_Instancing.c b/src/third_party/angle/samples/angle/Simple_Instancing/Simple_Instancing.c
deleted file mode 100644
index c513c9b..0000000
--- a/src/third_party/angle/samples/angle/Simple_Instancing/Simple_Instancing.c
+++ /dev/null
@@ -1,230 +0,0 @@
-//
-// Modified from Simple_Texture2D found in:
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// Simple_Instancing.c
-//
-//    This is a simple example that draws two quads with a 2D
-//    texture image. The purpose of this example is to demonstrate 
-//    the basics of ANGLE instancing in GLESv2.
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-#include <GLES2/gl2ext.h>
-
-PFNGLVERTEXATTRIBDIVISORANGLEPROC glVertexAttribDivisorANGLE;
-PFNGLDRAWARRAYSINSTANCEDANGLEPROC glDrawArraysInstancedANGLE;
-PFNGLDRAWELEMENTSINSTANCEDANGLEPROC glDrawElementsInstancedANGLE;
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-   GLint  texCoordLoc;
-
-   // Sampler location
-   GLint samplerLoc;
-
-   // Texture handle
-   GLuint textureId;
-
-   // Instance VBO
-   GLint  instancePosLoc;
-
-} UserData;
-
-///
-// Create a simple 2x2 texture image with four different colors
-//
-GLuint CreateSimpleTexture2D( )
-{
-   // Texture object handle
-   GLuint textureId;
-   
-   // 2x2 Image, 3 bytes per pixel (R, G, B)
-   GLubyte pixels[4 * 3] =
-   {  
-      255,   0,   0, // Red
-        0, 255,   0, // Green
-        0,   0, 255, // Blue
-      255, 255,   0  // Yellow
-   };
-
-   // Use tightly packed data
-   glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
-
-   // Generate a texture object
-   glGenTextures ( 1, &textureId );
-
-   // Bind the texture object
-   glBindTexture ( GL_TEXTURE_2D, textureId );
-
-   // Load the texture
-   glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
-
-   // Set the filtering mode
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-
-   return textureId;
-
-}
-
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-    // init instancing functions
-    char *extensionString = (char*) glGetString(GL_EXTENSIONS);
-
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =  
-      "attribute vec3 a_position;   \n"
-      "attribute vec2 a_texCoord;   \n"
-      "attribute vec3 a_instancePos;\n"
-      "varying vec2 v_texCoord;     \n"
-      "void main()                  \n"
-      "{                            \n"
-      "   gl_Position = vec4(a_position.xyz + a_instancePos.xyz, 1.0); \n"
-      "   v_texCoord = a_texCoord;  \n"
-      "}                            \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                            \n"
-      "varying vec2 v_texCoord;                            \n"
-      "uniform sampler2D s_texture;                        \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  gl_FragColor = texture2D( s_texture, v_texCoord );\n"
-      "}                                                   \n";
-
-    if (strstr(extensionString, "GL_ANGLE_instanced_arrays"))
-    {
-        glVertexAttribDivisorANGLE = (PFNGLVERTEXATTRIBDIVISORANGLEPROC)eglGetProcAddress("glVertexAttribDivisorANGLE");
-        glDrawArraysInstancedANGLE = (PFNGLDRAWARRAYSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawArraysInstancedANGLE");
-        glDrawElementsInstancedANGLE = (PFNGLDRAWELEMENTSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawElementsInstancedANGLE");
-    }
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-   userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
-   userData->instancePosLoc = glGetAttribLocation ( userData->programObject, "a_instancePos" );
-   
-   // Get the sampler location
-   userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
-
-   // Load the texture
-   userData->textureId = CreateSimpleTexture2D ();
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   return TRUE;
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = (UserData*) esContext->userData;
-   GLfloat vVertices[] = { -0.2f,  0.2f, 0.0f,  // Position 0
-                            0.0f,  0.0f,        // TexCoord 0 
-                           -0.2f, -0.2f, 0.0f,  // Position 1
-                            0.0f,  1.0f,        // TexCoord 1
-                            0.2f, -0.2f, 0.0f,  // Position 2
-                            1.0f,  1.0f,        // TexCoord 2
-                            0.2f,  0.2f, 0.0f,  // Position 3
-                            1.0f,  0.0f         // TexCoord 3
-                         };
-   GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
-
-   GLfloat instanceVerts [] = { -0.3f, -0.3f, 0.0f, 0.3f, 0.3f, 0.0f };
-      
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 
-                           GL_FALSE, 5 * sizeof(GLfloat), vVertices );
-   // Load the texture coordinate
-   glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
-                           GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
-
-   // Load the instance position
-   glVertexAttribPointer ( userData->instancePosLoc, 3, GL_FLOAT, 
-                           GL_FALSE, 3 * sizeof(GLfloat), instanceVerts );
-
-   glEnableVertexAttribArray ( userData->positionLoc );
-   glEnableVertexAttribArray ( userData->texCoordLoc );
-   glEnableVertexAttribArray ( userData->instancePosLoc );
-
-   // Enable instancing
-   glVertexAttribDivisorANGLE( userData->instancePosLoc, 1 );
-
-   // Bind the texture
-   glActiveTexture ( GL_TEXTURE0 );
-   glBindTexture ( GL_TEXTURE_2D, userData->textureId );
-
-   // Set the sampler texture unit to 0
-   glUniform1i ( userData->samplerLoc, 0 );
-
-   glDrawElementsInstancedANGLE ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices, 2 );
-   
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = (UserData*) esContext->userData;
-
-   // Delete texture object
-   glDeleteTextures ( 1, &userData->textureId );
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("Simple Instancing"), 320, 240, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/angle/Simple_Instancing/Simple_Instancing.vcxproj b/src/third_party/angle/samples/angle/Simple_Instancing/Simple_Instancing.vcxproj
deleted file mode 100644
index 35ffe80..0000000
--- a/src/third_party/angle/samples/angle/Simple_Instancing/Simple_Instancing.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{EB6E138B-9DE5-41E8-A127-3675AA2BA607}</ProjectGuid>

-    <RootNamespace>Simple_Texture2D</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-    <ProjectName>Simple_Instancing</ProjectName>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../../gles2_book/Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../../gles2_book/Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="Simple_Instancing.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\..\gles2_book\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/build_samples.gyp b/src/third_party/angle/samples/build_samples.gyp
deleted file mode 100644
index a70eb04..0000000
--- a/src/third_party/angle/samples/build_samples.gyp
+++ /dev/null
@@ -1,178 +0,0 @@
-# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'targets': [
-    {
-      'target_name': 'essl_to_glsl',
-      'type': 'executable',
-      'dependencies': [
-        '../src/build_angle.gyp:translator_glsl',
-      ],
-      'include_dirs': [
-        '../include',
-      ],
-      'sources': [
-        'translator/translator.cpp',
-      ],
-    },
-  ],
-  'conditions': [
-    ['OS=="win"', {
-      'targets': [
-        {
-          'target_name': 'essl_to_hlsl',
-          'type': 'executable',
-          'dependencies': [
-            '../src/build_angle.gyp:translator_hlsl',
-          ],
-          'include_dirs': [
-            '../include',
-            '../src',
-          ],
-          'sources': [
-            'translator/translator.cpp',
-            '../src/common/debug.cpp',
-          ],
-          'msvs_settings': {
-            'VCLinkerTool': {
-              'AdditionalDependencies': ['d3d9.lib'],
-            }
-          }
-        },
-        {
-          'target_name': 'es_util',
-          'type': 'static_library',
-          'dependencies': [
-            '../src/build_angle.gyp:libEGL',
-            '../src/build_angle.gyp:libGLESv2',
-          ],
-          'include_dirs': [
-            'gles2_book/Common',
-            '../include',
-          ],
-          'sources': [
-            'gles2_book/Common/esShader.c',
-            'gles2_book/Common/esShapes.c',
-            'gles2_book/Common/esTransform.c',
-            'gles2_book/Common/esUtil.c',
-            'gles2_book/Common/esUtil.h',
-            'gles2_book/Common/esUtil_win.h',
-            'gles2_book/Common/Win32/esUtil_TGA.c',
-            'gles2_book/Common/Win32/esUtil_win32.c',
-          ],
-          'direct_dependent_settings': {
-            'include_dirs': [
-              'gles2_book/Common',
-              '../include',
-            ],
-          },
-        },
-        {
-          'target_name': 'hello_triangle',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/Hello_Triangle/Hello_Triangle.c',
-          ],
-        },
-        {
-          'target_name': 'mip_map_2d',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/MipMap2D/MipMap2D.c',
-          ],
-        },
-        {
-          'target_name': 'multi_texture',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/MultiTexture/MultiTexture.c',
-          ],
-          'copies': [
-            {
-              'destination': '<(PRODUCT_DIR)',
-              'files': [
-                'gles2_book/MultiTexture/basemap.tga',
-                'gles2_book/MultiTexture/lightmap.tga',
-              ],
-            },
-          ],
-        },
-        {
-          'target_name': 'particle_system',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/ParticleSystem/ParticleSystem.c',
-          ],
-          'copies': [
-            {
-              'destination': '<(PRODUCT_DIR)',
-              'files': [
-                'gles2_book/ParticleSystem/smoke.tga',
-              ],
-            },
-          ],
-        },
-        {
-          'target_name': 'simple_texture_2d',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/Simple_Texture2D/Simple_Texture2D.c',
-          ],
-        },
-        {
-          'target_name': 'simple_texture_cubemap',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/Simple_TextureCubemap/Simple_TextureCubemap.c',
-          ],
-        },
-        {
-          'target_name': 'simple_vertex_shader',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/Simple_VertexShader/Simple_VertexShader.c',
-          ],
-        },
-        {
-          'target_name': 'stencil_test',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/Stencil_Test/Stencil_Test.c',
-          ],
-        },
-        {
-          'target_name': 'texture_wrap',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/TextureWrap/TextureWrap.c',
-          ],
-        },
-        {
-          'target_name': 'post_sub_buffer',
-          'type': 'executable',
-          'dependencies': ['es_util'],
-          'sources': [
-            'gles2_book/PostSubBuffer/PostSubBuffer.c',
-          ],
-        },
-      ],
-    }],
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/src/third_party/angle/samples/gles2_book/Common/Win32/esUtil_TGA.c b/src/third_party/angle/samples/gles2_book/Common/Win32/esUtil_TGA.c
deleted file mode 100644
index 61d1cb1..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/Win32/esUtil_TGA.c
+++ /dev/null
@@ -1,122 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// esUtil_TGA.c
-//
-//    This file contains the Win32 implementation of a TGA image loader
-
-#include <windows.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-///
-//  Macros
-//
-#define INVERTED_BIT            (1 << 5)
-
-///
-//  Types
-//
-#pragma pack(push,x1)                            // Byte alignment (8-bit)
-#pragma pack(1)
-
-typedef struct
-{
-   unsigned char  IdSize,
-                  MapType,
-                  ImageType;
-   unsigned short PaletteStart,
-                  PaletteSize;
-   unsigned char  PaletteEntryDepth;
-   unsigned short X,
-                  Y,
-                  Width,
-                  Height;
-   unsigned char  ColorDepth,
-                  Descriptor;
-         
-} TGA_HEADER;
-
-#pragma pack(pop,x1)
-
-////////////////////////////////////////////////////////////////////////////////////
-//
-//  Private Functions
-//
-
-////////////////////////////////////////////////////////////////////////////////////
-//
-//  Public Functions
-//
-//
-
-
-///
-//  WinTGALoad()
-//
-int WinTGALoad( const char *fileName, char **buffer, int *width, int *height )
-{
-   FILE        *fp;
-   TGA_HEADER   Header;
-
-   if ( fopen_s ( &fp, fileName, "rb" ) != 0 )
-   {
-      return FALSE;
-   }
-
-   if ( fp == NULL )
-   {
-      return FALSE;
-   }
-
-   fread ( &Header, sizeof(TGA_HEADER), 1, fp );
-
-   *width = Header.Width;
-   *height = Header.Height;
-   
-   if ( Header.ColorDepth == 24 )
-   {
-      RGBTRIPLE *Buffer24;
-
-      Buffer24= (RGBTRIPLE*)malloc(sizeof(RGBTRIPLE) * (*width) * (*height));
-
-      if(Buffer24)
-      {
-         int i=0;
-         int x,
-             y;
-
-         fread(Buffer24, sizeof(RGBTRIPLE), (*width) * (*height), fp);
-
-         *buffer= (LPSTR) malloc(3 * (*width) * (*height));
-
-         for ( y = 0; y < *height; y++ )
-            for( x = 0; x < *width; x++ )
-            {
-               int Index= y * (*width) + x;
-
-               if(!(Header.Descriptor & INVERTED_BIT))
-                  Index= ((*height) - 1 - y) * (*width) + x;
-
-               (*buffer)[(i * 3)]=      Buffer24[Index].rgbtRed;
-               (*buffer)[(i * 3) + 1]=  Buffer24[Index].rgbtGreen;
-               (*buffer)[(i * 3) + 2]=  Buffer24[Index].rgbtBlue;
-        
-               i++;
-            }
-         
-         fclose(fp);
-         free(Buffer24);
-         return(TRUE);
-      }		
-   }
-
-   return(FALSE);
-}
diff --git a/src/third_party/angle/samples/gles2_book/Common/Win32/esUtil_win32.c b/src/third_party/angle/samples/gles2_book/Common/Win32/esUtil_win32.c
deleted file mode 100644
index c27131e..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/Win32/esUtil_win32.c
+++ /dev/null
@@ -1,190 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// esUtil_win32.c
-//
-//    This file contains the Win32 implementation of the windowing functions. 
-
-
-///
-// Includes
-//
-
-#include <windows.h>
-#include "esUtil.h"
-
-//////////////////////////////////////////////////////////////////
-//
-//  Private Functions
-//
-//
-
-///
-//  ESWindowProc()
-//
-//      Main window procedure
-//
-LRESULT WINAPI ESWindowProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 
-{
-   LRESULT  lRet = 1; 
-
-   switch (uMsg) 
-   { 
-      case WM_CREATE:
-         break;
-
-      case WM_SIZE:
-         {
-            ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );
-            if ( esContext ) {
-               esContext->width = LOWORD( lParam );
-               esContext->height = HIWORD( lParam );
-               InvalidateRect( esContext->hWnd, NULL, FALSE );
-            }
-         }
-
-      case WM_PAINT:
-         {
-            ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );
-            
-            if ( esContext && esContext->drawFunc )
-               esContext->drawFunc ( esContext );
-            
-            if ( esContext )
-              ValidateRect( esContext->hWnd, NULL );
-         }
-         break;
-
-      case WM_DESTROY:
-         PostQuitMessage(0);             
-         break; 
-      
-      case WM_CHAR:
-         {
-            POINT      point;
-            ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );
-            
-            GetCursorPos( &point );
-
-            if ( esContext && esContext->keyFunc )
-	            esContext->keyFunc ( esContext, (unsigned char) wParam, 
-		                             (int) point.x, (int) point.y );
-}
-         break;
-         
-      default: 
-         lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); 
-         break; 
-   } 
-
-   return lRet; 
-}
-
-//////////////////////////////////////////////////////////////////
-//
-//  Public Functions
-//
-//
-
-///
-//  WinCreate()
-//
-//      Create Win32 instance and window
-//
-GLboolean WinCreate ( ESContext *esContext, LPCTSTR title )
-{
-   WNDCLASS wndclass = {0}; 
-   DWORD    wStyle   = 0;
-   RECT     windowRect;
-   HINSTANCE hInstance = GetModuleHandle(NULL);
-   
-   wndclass.style         = CS_OWNDC;
-   wndclass.lpfnWndProc   = (WNDPROC)ESWindowProc; 
-   wndclass.hInstance     = hInstance; 
-   wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
-   wndclass.lpszClassName = TEXT("opengles2.0");
-
-   if (!RegisterClass (&wndclass) ) 
-      return FALSE; 
-
-   wStyle = WS_VISIBLE | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | WS_SIZEBOX;
-   
-   // Adjust the window rectangle so that the client area has
-   // the correct number of pixels
-   windowRect.left = 0;
-   windowRect.top = 0;
-   windowRect.right = esContext->width;
-   windowRect.bottom = esContext->height;
-
-   AdjustWindowRect ( &windowRect, wStyle, FALSE );
-
-   esContext->hWnd = CreateWindow(
-                         TEXT("opengles2.0"),
-                         title,
-                         wStyle,
-                         0,
-                         0,
-                         windowRect.right - windowRect.left,
-                         windowRect.bottom - windowRect.top,
-                         NULL,
-                         NULL,
-                         hInstance,
-                         NULL);
-
-   // Set the ESContext* to the GWL_USERDATA so that it is available to the 
-   // ESWindowProc
-   SetWindowLongPtr (  esContext->hWnd, GWL_USERDATA, (LONG) (LONG_PTR) esContext );
-
-   if ( esContext->hWnd == NULL )
-      return GL_FALSE;
-
-   ShowWindow ( esContext->hWnd, TRUE );
-
-   return GL_TRUE;
-}
-
-///
-//  winLoop()
-//
-//      Start main windows loop
-//
-void WinLoop ( ESContext *esContext )
-{
-   MSG msg = { 0 };
-   int done = 0;
-   DWORD lastTime = GetTickCount();
-   
-   while (!done)
-   {
-      int gotMsg = (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0);
-      DWORD curTime = GetTickCount();
-      float deltaTime = (float)( curTime - lastTime ) / 1000.0f;
-      lastTime = curTime;
-
-      if ( gotMsg )
-      {
-         if (msg.message==WM_QUIT)
-         {
-             done=1; 
-         }
-         else
-         {
-             TranslateMessage(&msg); 
-             DispatchMessage(&msg); 
-         }
-      }
-      else
-         SendMessage( esContext->hWnd, WM_PAINT, 0, 0 );
-
-      // Call update function if registered
-      if ( esContext->updateFunc != NULL )
-         esContext->updateFunc ( esContext, deltaTime );
-   }
-}
diff --git a/src/third_party/angle/samples/gles2_book/Common/esShader.c b/src/third_party/angle/samples/gles2_book/Common/esShader.c
deleted file mode 100644
index a2bb6e5..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/esShader.c
+++ /dev/null
@@ -1,155 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// ESShader.c
-//
-//    Utility functions for loading shaders and creating program objects.
-//
-
-///
-//  Includes
-//
-#include "esUtil.h"
-#include <stdlib.h>
-
-//////////////////////////////////////////////////////////////////
-//
-//  Private Functions
-//
-//
-
-
-
-//////////////////////////////////////////////////////////////////
-//
-//  Public Functions
-//
-//
-
-//
-///
-/// \brief Load a shader, check for compile errors, print error messages to output log
-/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
-/// \param shaderSrc Shader source string
-/// \return A new shader object on success, 0 on failure
-//
-GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc )
-{
-   GLuint shader;
-   GLint compiled;
-   
-   // Create the shader object
-   shader = glCreateShader ( type );
-
-   if ( shader == 0 )
-   	return 0;
-
-   // Load the shader source
-   glShaderSource ( shader, 1, &shaderSrc, NULL );
-   
-   // Compile the shader
-   glCompileShader ( shader );
-
-   // Check the compile status
-   glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
-
-   if ( !compiled ) 
-   {
-      GLint infoLen = 0;
-
-      glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
-      
-      if ( infoLen > 1 )
-      {
-         char* infoLog = malloc (sizeof(char) * infoLen );
-
-         glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
-         esLogMessage ( "Error compiling shader:\n%s\n", infoLog );            
-         
-         free ( infoLog );
-      }
-
-      glDeleteShader ( shader );
-      return 0;
-   }
-
-   return shader;
-
-}
-
-
-//
-///
-/// \brief Load a vertex and fragment shader, create a program object, link program.
-//         Errors output to log.
-/// \param vertShaderSrc Vertex shader source code
-/// \param fragShaderSrc Fragment shader source code
-/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
-//
-GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc )
-{
-   GLuint vertexShader;
-   GLuint fragmentShader;
-   GLuint programObject;
-   GLint linked;
-
-   // Load the vertex/fragment shaders
-   vertexShader = esLoadShader ( GL_VERTEX_SHADER, vertShaderSrc );
-   if ( vertexShader == 0 )
-      return 0;
-
-   fragmentShader = esLoadShader ( GL_FRAGMENT_SHADER, fragShaderSrc );
-   if ( fragmentShader == 0 )
-   {
-      glDeleteShader( vertexShader );
-      return 0;
-   }
-
-   // Create the program object
-   programObject = glCreateProgram ( );
-   
-   if ( programObject == 0 )
-      return 0;
-
-   glAttachShader ( programObject, vertexShader );
-   glAttachShader ( programObject, fragmentShader );
-
-   // Link the program
-   glLinkProgram ( programObject );
-
-   // Check the link status
-   glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
-
-   if ( !linked ) 
-   {
-      GLint infoLen = 0;
-
-      glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
-      
-      if ( infoLen > 1 )
-      {
-         char* infoLog = malloc (sizeof(char) * infoLen );
-
-         glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
-         esLogMessage ( "Error linking program:\n%s\n", infoLog );            
-         
-         free ( infoLog );
-      }
-
-      glDeleteProgram ( programObject );
-      return 0;
-   }
-
-   // Free up no longer needed shader resources
-   glDeleteShader ( vertexShader );
-   glDeleteShader ( fragmentShader );
-
-   return programObject;
-}
diff --git a/src/third_party/angle/samples/gles2_book/Common/esShapes.c b/src/third_party/angle/samples/gles2_book/Common/esShapes.c
deleted file mode 100644
index 6813534..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/esShapes.c
+++ /dev/null
@@ -1,279 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// ESShapes.c
-//
-//    Utility functions for generating shapes
-//
-
-///
-//  Includes
-//
-#include "esUtil.h"
-#include <stdlib.h>
-#include <math.h>
-
-///
-// Defines
-//
-#define ES_PI  (3.14159265f)
-
-//////////////////////////////////////////////////////////////////
-//
-//  Private Functions
-//
-//
-
-
-
-//////////////////////////////////////////////////////////////////
-//
-//  Public Functions
-//
-//
-
-//
-/// \brief Generates geometry for a sphere.  Allocates memory for the vertex data and stores 
-///        the results in the arrays.  Generate index list for a TRIANGLE_STRIP
-/// \param numSlices The number of slices in the sphere
-/// \param vertices If not NULL, will contain array of float3 positions
-/// \param normals If not NULL, will contain array of float3 normals
-/// \param texCoords If not NULL, will contain array of float2 texCoords
-/// \param indices If not NULL, will contain the array of indices for the triangle strip
-/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
-///         if it is not NULL ) as a GL_TRIANGLE_STRIP
-//
-int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals, 
-                             GLfloat **texCoords, GLushort **indices )
-{
-   int i;
-   int j;
-   int numParallels = numSlices / 2;
-   int numVertices = ( numParallels + 1 ) * ( numSlices + 1 );
-   int numIndices = numParallels * numSlices * 6;
-   float angleStep = (2.0f * ES_PI) / ((float) numSlices);
-
-   // Allocate memory for buffers
-   if ( vertices != NULL )
-      *vertices = malloc ( sizeof(GLfloat) * 3 * numVertices );
-   
-   if ( normals != NULL )
-      *normals = malloc ( sizeof(GLfloat) * 3 * numVertices );
-
-   if ( texCoords != NULL )
-      *texCoords = malloc ( sizeof(GLfloat) * 2 * numVertices );
-
-   if ( indices != NULL )
-      *indices = malloc ( sizeof(GLushort) * numIndices );
-
-   for ( i = 0; i < numParallels + 1; i++ )
-   {
-      for ( j = 0; j < numSlices + 1; j++ )
-      {
-         int vertex = ( i * (numSlices + 1) + j ) * 3; 
-
-         if ( vertices )
-         {
-            (*vertices)[vertex + 0] = radius * sinf ( angleStep * (float)i ) *
-                                               sinf ( angleStep * (float)j );
-            (*vertices)[vertex + 1] = radius * cosf ( angleStep * (float)i );
-            (*vertices)[vertex + 2] = radius * sinf ( angleStep * (float)i ) *
-                                               cosf ( angleStep * (float)j );
-         }
-
-         if ( normals )
-         {
-            (*normals)[vertex + 0] = (*vertices)[vertex + 0] / radius;
-            (*normals)[vertex + 1] = (*vertices)[vertex + 1] / radius;
-            (*normals)[vertex + 2] = (*vertices)[vertex + 2] / radius;
-         }
-
-         if ( texCoords )
-         {
-            int texIndex = ( i * (numSlices + 1) + j ) * 2;
-            (*texCoords)[texIndex + 0] = (float) j / (float) numSlices;
-            (*texCoords)[texIndex + 1] = ( 1.0f - (float) i ) / (float) (numParallels - 1 );
-         }
-      }
-   }
-
-   // Generate the indices
-   if ( indices != NULL )
-   {
-      GLushort *indexBuf = (*indices);
-      for ( i = 0; i < numParallels ; i++ ) 
-      {
-         for ( j = 0; j < numSlices; j++ )
-         {
-            *indexBuf++  = i * ( numSlices + 1 ) + j;
-            *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + j;
-            *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 );
-
-            *indexBuf++ = i * ( numSlices + 1 ) + j;
-            *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 );
-            *indexBuf++ = i * ( numSlices + 1 ) + ( j + 1 );
-         }
-      }
-   }
-
-   return numIndices;
-}
-
-//
-/// \brief Generates geometry for a cube.  Allocates memory for the vertex data and stores 
-///        the results in the arrays.  Generate index list for a TRIANGLES
-/// \param scale The size of the cube, use 1.0 for a unit cube.
-/// \param vertices If not NULL, will contain array of float3 positions
-/// \param normals If not NULL, will contain array of float3 normals
-/// \param texCoords If not NULL, will contain array of float2 texCoords
-/// \param indices If not NULL, will contain the array of indices for the triangle strip
-/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
-///         if it is not NULL ) as a GL_TRIANGLE_STRIP
-//
-int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals, 
-                           GLfloat **texCoords, GLushort **indices )
-{
-   int i;
-   int numVertices = 24;
-   int numIndices = 36;
-   
-   GLfloat cubeVerts[] =
-   {
-      -0.5f, -0.5f, -0.5f,
-      -0.5f, -0.5f,  0.5f,
-      0.5f, -0.5f,  0.5f,
-      0.5f, -0.5f, -0.5f,
-      -0.5f,  0.5f, -0.5f,
-      -0.5f,  0.5f,  0.5f,
-      0.5f,  0.5f,  0.5f,
-      0.5f,  0.5f, -0.5f,
-      -0.5f, -0.5f, -0.5f,
-      -0.5f,  0.5f, -0.5f,
-      0.5f,  0.5f, -0.5f,
-      0.5f, -0.5f, -0.5f,
-      -0.5f, -0.5f, 0.5f,
-      -0.5f,  0.5f, 0.5f,
-      0.5f,  0.5f, 0.5f, 
-      0.5f, -0.5f, 0.5f,
-      -0.5f, -0.5f, -0.5f,
-      -0.5f, -0.5f,  0.5f,
-      -0.5f,  0.5f,  0.5f,
-      -0.5f,  0.5f, -0.5f,
-      0.5f, -0.5f, -0.5f,
-      0.5f, -0.5f,  0.5f,
-      0.5f,  0.5f,  0.5f,
-      0.5f,  0.5f, -0.5f,
-   };
-
-   GLfloat cubeNormals[] =
-   {
-      0.0f, -1.0f, 0.0f,
-      0.0f, -1.0f, 0.0f,
-      0.0f, -1.0f, 0.0f,
-      0.0f, -1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 0.0f, -1.0f,
-      0.0f, 0.0f, -1.0f,
-      0.0f, 0.0f, -1.0f,
-      0.0f, 0.0f, -1.0f,
-      0.0f, 0.0f, 1.0f,
-      0.0f, 0.0f, 1.0f,
-      0.0f, 0.0f, 1.0f,
-      0.0f, 0.0f, 1.0f,
-      -1.0f, 0.0f, 0.0f,
-      -1.0f, 0.0f, 0.0f,
-      -1.0f, 0.0f, 0.0f,
-      -1.0f, 0.0f, 0.0f,
-      1.0f, 0.0f, 0.0f,
-      1.0f, 0.0f, 0.0f,
-      1.0f, 0.0f, 0.0f,
-      1.0f, 0.0f, 0.0f,
-   };
-
-   GLfloat cubeTex[] =
-   {
-      0.0f, 0.0f,
-      0.0f, 1.0f,
-      1.0f, 1.0f,
-      1.0f, 0.0f,
-      1.0f, 0.0f,
-      1.0f, 1.0f,
-      0.0f, 1.0f,
-      0.0f, 0.0f,
-      0.0f, 0.0f,
-      0.0f, 1.0f,
-      1.0f, 1.0f,
-      1.0f, 0.0f,
-      0.0f, 0.0f,
-      0.0f, 1.0f,
-      1.0f, 1.0f,
-      1.0f, 0.0f,
-      0.0f, 0.0f,
-      0.0f, 1.0f,
-      1.0f, 1.0f,
-      1.0f, 0.0f,
-      0.0f, 0.0f,
-      0.0f, 1.0f,
-      1.0f, 1.0f,
-      1.0f, 0.0f,
-   };
-   
-   // Allocate memory for buffers
-   if ( vertices != NULL )
-   {
-      *vertices = malloc ( sizeof(GLfloat) * 3 * numVertices );
-      memcpy( *vertices, cubeVerts, sizeof( cubeVerts ) );
-      for ( i = 0; i < numVertices; i++ )
-      {
-         (*vertices)[i] *= scale;
-      }
-   }
-
-   if ( normals != NULL )
-   {
-      *normals = malloc ( sizeof(GLfloat) * 3 * numVertices );
-      memcpy( *normals, cubeNormals, sizeof( cubeNormals ) );
-   }
-
-   if ( texCoords != NULL )
-   {
-      *texCoords = malloc ( sizeof(GLfloat) * 2 * numVertices );
-      memcpy( *texCoords, cubeTex, sizeof( cubeTex ) ) ;
-   }
-
-
-   // Generate the indices
-   if ( indices != NULL )
-   {
-      GLushort cubeIndices[] =
-      {
-         0, 2, 1,
-         0, 3, 2, 
-         4, 5, 6,
-         4, 6, 7,
-         8, 9, 10,
-         8, 10, 11, 
-         12, 15, 14,
-         12, 14, 13, 
-         16, 17, 18,
-         16, 18, 19, 
-         20, 23, 22,
-         20, 22, 21
-      };
-
-      *indices = malloc ( sizeof(GLushort) * numIndices );
-      memcpy( *indices, cubeIndices, sizeof( cubeIndices ) );
-   }
-
-   return numIndices;
-}
diff --git a/src/third_party/angle/samples/gles2_book/Common/esTransform.c b/src/third_party/angle/samples/gles2_book/Common/esTransform.c
deleted file mode 100644
index 7da8f76..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/esTransform.c
+++ /dev/null
@@ -1,212 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// ESUtil.c
-//
-//    A utility library for OpenGL ES.  This library provides a
-//    basic common framework for the example applications in the
-//    OpenGL ES 2.0 Programming Guide.
-//
-
-///
-//  Includes
-//
-#include "esUtil.h"
-#include <math.h>
-
-#define PI 3.1415926535897932384626433832795f
-
-void ESUTIL_API
-esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz)
-{
-    result->m[0][0] *= sx;
-    result->m[0][1] *= sx;
-    result->m[0][2] *= sx;
-    result->m[0][3] *= sx;
-
-    result->m[1][0] *= sy;
-    result->m[1][1] *= sy;
-    result->m[1][2] *= sy;
-    result->m[1][3] *= sy;
-
-    result->m[2][0] *= sz;
-    result->m[2][1] *= sz;
-    result->m[2][2] *= sz;
-    result->m[2][3] *= sz;
-}
-
-void ESUTIL_API
-esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz)
-{
-    result->m[3][0] += (result->m[0][0] * tx + result->m[1][0] * ty + result->m[2][0] * tz);
-    result->m[3][1] += (result->m[0][1] * tx + result->m[1][1] * ty + result->m[2][1] * tz);
-    result->m[3][2] += (result->m[0][2] * tx + result->m[1][2] * ty + result->m[2][2] * tz);
-    result->m[3][3] += (result->m[0][3] * tx + result->m[1][3] * ty + result->m[2][3] * tz);
-}
-
-void ESUTIL_API
-esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
-{
-   GLfloat sinAngle, cosAngle;
-   GLfloat mag = sqrtf(x * x + y * y + z * z);
-      
-   sinAngle = sinf ( angle * PI / 180.0f );
-   cosAngle = cosf ( angle * PI / 180.0f );
-   if ( mag > 0.0f )
-   {
-      GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;
-      GLfloat oneMinusCos;
-      ESMatrix rotMat;
-   
-      x /= mag;
-      y /= mag;
-      z /= mag;
-
-      xx = x * x;
-      yy = y * y;
-      zz = z * z;
-      xy = x * y;
-      yz = y * z;
-      zx = z * x;
-      xs = x * sinAngle;
-      ys = y * sinAngle;
-      zs = z * sinAngle;
-      oneMinusCos = 1.0f - cosAngle;
-
-      rotMat.m[0][0] = (oneMinusCos * xx) + cosAngle;
-      rotMat.m[0][1] = (oneMinusCos * xy) - zs;
-      rotMat.m[0][2] = (oneMinusCos * zx) + ys;
-      rotMat.m[0][3] = 0.0F; 
-
-      rotMat.m[1][0] = (oneMinusCos * xy) + zs;
-      rotMat.m[1][1] = (oneMinusCos * yy) + cosAngle;
-      rotMat.m[1][2] = (oneMinusCos * yz) - xs;
-      rotMat.m[1][3] = 0.0F;
-
-      rotMat.m[2][0] = (oneMinusCos * zx) - ys;
-      rotMat.m[2][1] = (oneMinusCos * yz) + xs;
-      rotMat.m[2][2] = (oneMinusCos * zz) + cosAngle;
-      rotMat.m[2][3] = 0.0F; 
-
-      rotMat.m[3][0] = 0.0F;
-      rotMat.m[3][1] = 0.0F;
-      rotMat.m[3][2] = 0.0F;
-      rotMat.m[3][3] = 1.0F;
-
-      esMatrixMultiply( result, &rotMat, result );
-   }
-}
-
-void ESUTIL_API
-esFrustum(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ)
-{
-    float       deltaX = right - left;
-    float       deltaY = top - bottom;
-    float       deltaZ = farZ - nearZ;
-    ESMatrix    frust;
-
-    if ( (nearZ <= 0.0f) || (farZ <= 0.0f) ||
-         (deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f) )
-         return;
-
-    frust.m[0][0] = 2.0f * nearZ / deltaX;
-    frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
-
-    frust.m[1][1] = 2.0f * nearZ / deltaY;
-    frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
-
-    frust.m[2][0] = (right + left) / deltaX;
-    frust.m[2][1] = (top + bottom) / deltaY;
-    frust.m[2][2] = -(nearZ + farZ) / deltaZ;
-    frust.m[2][3] = -1.0f;
-
-    frust.m[3][2] = -2.0f * nearZ * farZ / deltaZ;
-    frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
-
-    esMatrixMultiply(result, &frust, result);
-}
-
-
-void ESUTIL_API 
-esPerspective(ESMatrix *result, float fovy, float aspect, float nearZ, float farZ)
-{
-   GLfloat frustumW, frustumH;
-   
-   frustumH = tanf( fovy / 360.0f * PI ) * nearZ;
-   frustumW = frustumH * aspect;
-
-   esFrustum( result, -frustumW, frustumW, -frustumH, frustumH, nearZ, farZ );
-}
-
-void ESUTIL_API
-esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ)
-{
-    float       deltaX = right - left;
-    float       deltaY = top - bottom;
-    float       deltaZ = farZ - nearZ;
-    ESMatrix    ortho;
-
-    if ( (deltaX == 0.0f) || (deltaY == 0.0f) || (deltaZ == 0.0f) )
-        return;
-
-    esMatrixLoadIdentity(&ortho);
-    ortho.m[0][0] = 2.0f / deltaX;
-    ortho.m[3][0] = -(right + left) / deltaX;
-    ortho.m[1][1] = 2.0f / deltaY;
-    ortho.m[3][1] = -(top + bottom) / deltaY;
-    ortho.m[2][2] = -2.0f / deltaZ;
-    ortho.m[3][2] = -(nearZ + farZ) / deltaZ;
-
-    esMatrixMultiply(result, &ortho, result);
-}
-
-
-void ESUTIL_API
-esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB)
-{
-    ESMatrix    tmp = { 0.0f };
-    int         i;
-
-	for (i=0; i<4; i++)
-	{
-		tmp.m[i][0] =	(srcA->m[i][0] * srcB->m[0][0]) +
-						(srcA->m[i][1] * srcB->m[1][0]) +
-						(srcA->m[i][2] * srcB->m[2][0]) +
-						(srcA->m[i][3] * srcB->m[3][0]) ;
-
-		tmp.m[i][1] =	(srcA->m[i][0] * srcB->m[0][1]) + 
-						(srcA->m[i][1] * srcB->m[1][1]) +
-						(srcA->m[i][2] * srcB->m[2][1]) +
-						(srcA->m[i][3] * srcB->m[3][1]) ;
-
-		tmp.m[i][2] =	(srcA->m[i][0] * srcB->m[0][2]) + 
-						(srcA->m[i][1] * srcB->m[1][2]) +
-						(srcA->m[i][2] * srcB->m[2][2]) +
-						(srcA->m[i][3] * srcB->m[3][2]) ;
-
-		tmp.m[i][3] =	(srcA->m[i][0] * srcB->m[0][3]) + 
-						(srcA->m[i][1] * srcB->m[1][3]) +
-						(srcA->m[i][2] * srcB->m[2][3]) +
-						(srcA->m[i][3] * srcB->m[3][3]) ;
-	}
-    memcpy(result, &tmp, sizeof(ESMatrix));
-}
-
-
-void ESUTIL_API
-esMatrixLoadIdentity(ESMatrix *result)
-{
-    memset(result, 0x0, sizeof(ESMatrix));
-    result->m[0][0] = 1.0f;
-    result->m[1][1] = 1.0f;
-    result->m[2][2] = 1.0f;
-    result->m[3][3] = 1.0f;
-}
-
diff --git a/src/third_party/angle/samples/gles2_book/Common/esUtil.c b/src/third_party/angle/samples/gles2_book/Common/esUtil.c
deleted file mode 100644
index aeeee7f..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/esUtil.c
+++ /dev/null
@@ -1,290 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// ESUtil.c
-//
-//    A utility library for OpenGL ES.  This library provides a
-//    basic common framework for the example applications in the
-//    OpenGL ES 2.0 Programming Guide.
-//
-
-///
-//  Includes
-//
-#include <stdio.h>
-#include <stdlib.h>
-#include <GLES2/gl2.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include "esUtil.h"
-#include "esUtil_win.h"
-
-#if defined(_MSC_VER)
-#pragma warning(disable: 4204) // nonstandard extension used : non-constant aggregate initializer
-#endif
-
-///
-//  Extensions
-//
-
-PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
-PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
-
-PFNEGLPOSTSUBBUFFERNVPROC eglPostSubBufferNV;
-
-PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
-
-PFNGLDELETEFENCESNVPROC glDeleteFencesNV;
-PFNGLGENFENCESNVPROC glGenFencesNV;
-PFNGLGETFENCEIVNVPROC glGetFenceivNV;
-PFNGLISFENCENVPROC glIsFenceNV;
-PFNGLFINISHFENCENVPROC glFinishFenceNV;
-PFNGLSETFENCENVPROC glSetFenceNV;
-PFNGLTESTFENCENVPROC glTestFenceNV;
-
-///
-// CreateEGLContext()
-//
-//    Creates an EGL rendering context and all associated elements
-//
-EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
-                              EGLContext* eglContext, EGLSurface* eglSurface,
-                              EGLint* configAttribList, EGLint* surfaceAttribList)
-{
-   EGLint numConfigs;
-   EGLint majorVersion;
-   EGLint minorVersion;
-   EGLDisplay display;
-   EGLContext context;
-   EGLSurface surface;
-   EGLConfig config;
-   EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
-   
-   // Get Display
-   display = eglGetDisplay(GetDC(hWnd));
-   if ( display == EGL_NO_DISPLAY )
-   {
-      return EGL_FALSE;
-   }
-
-   // Initialize EGL
-   if ( !eglInitialize(display, &majorVersion, &minorVersion) )
-   {
-      return EGL_FALSE;
-   }
-
-   // Bind to extensions
-   eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR");
-   eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR");
-   
-   eglPostSubBufferNV = (PFNEGLPOSTSUBBUFFERNVPROC) eglGetProcAddress("eglPostSubBufferNV");
-
-   glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress("glEGLImageTargetTexture2DOES");
-   
-   glDeleteFencesNV = (PFNGLDELETEFENCESNVPROC) eglGetProcAddress("glDeleteFencesNV");
-   glGenFencesNV = (PFNGLGENFENCESNVPROC) eglGetProcAddress("glGenFencesNV");
-   glGetFenceivNV = (PFNGLGETFENCEIVNVPROC) eglGetProcAddress("glGetFenceivNV");
-   glIsFenceNV = (PFNGLISFENCENVPROC) eglGetProcAddress("glIsFenceNV");
-   glFinishFenceNV = (PFNGLFINISHFENCENVPROC) eglGetProcAddress("glFinishFenceNV");
-   glSetFenceNV = (PFNGLSETFENCENVPROC) eglGetProcAddress("glSetFenceNV");
-   glTestFenceNV = (PFNGLTESTFENCENVPROC) eglGetProcAddress("glTestFenceNV");
-
-   // Get configs
-   if ( !eglGetConfigs(display, NULL, 0, &numConfigs) )
-   {
-      return EGL_FALSE;
-   }
-
-   // Choose config
-   if ( !eglChooseConfig(display, configAttribList, &config, 1, &numConfigs) )
-   {
-      return EGL_FALSE;
-   }
-
-   // Create a surface
-   surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, surfaceAttribList);
-   if ( surface == EGL_NO_SURFACE )
-   {
-      return EGL_FALSE;
-   }
-
-   // Create a GL context
-   context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs );
-   if ( context == EGL_NO_CONTEXT )
-   {
-      return EGL_FALSE;
-   }   
-   
-   // Make the context current
-   if ( !eglMakeCurrent(display, surface, surface, context) )
-   {
-      return EGL_FALSE;
-   }
-   
-   *eglDisplay = display;
-   *eglSurface = surface;
-   *eglContext = context;
-   return EGL_TRUE;
-} 
-
-//////////////////////////////////////////////////////////////////
-//
-//  Public Functions
-//
-//
-
-///
-//  esInitContext()
-//
-//      Initialize ES utility context.  This must be called before calling any other
-//      functions.
-//
-void ESUTIL_API esInitContext ( ESContext *esContext )
-{
-   if ( esContext != NULL )
-   {
-      memset( esContext, 0, sizeof( ESContext) );
-   }
-}
-
-///
-//  esCreateWindow()
-//
-//      title - name for title bar of window
-//      width - width of window to create
-//      height - height of window to create
-//      flags  - bitwise or of window creation flags 
-//          ES_WINDOW_ALPHA       - specifies that the framebuffer should have alpha
-//          ES_WINDOW_DEPTH       - specifies that a depth buffer should be created
-//          ES_WINDOW_STENCIL     - specifies that a stencil buffer should be created
-//          ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
-//          ES_WINDOW_POST_SUB_BUFFER_SUPPORTED - specifies that EGL_POST_SUB_BUFFER_NV is supported.
-//
-GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint width, GLint height, GLuint flags )
-{
-   EGLint configAttribList[] =
-   {
-       EGL_RED_SIZE,       5,
-       EGL_GREEN_SIZE,     6,
-       EGL_BLUE_SIZE,      5,
-       EGL_ALPHA_SIZE,     (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,
-       EGL_DEPTH_SIZE,     (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,
-       EGL_STENCIL_SIZE,   (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,
-       EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,
-       EGL_NONE
-   };
-   EGLint surfaceAttribList[] =
-   {
-       EGL_POST_SUB_BUFFER_SUPPORTED_NV, flags & (ES_WINDOW_POST_SUB_BUFFER_SUPPORTED) ? EGL_TRUE : EGL_FALSE,
-       EGL_NONE, EGL_NONE
-   };
-   
-   if ( esContext == NULL )
-   {
-      return GL_FALSE;
-   }
-
-   esContext->width = width;
-   esContext->height = height;
-
-   if ( !WinCreate ( esContext, title) )
-   {
-      return GL_FALSE;
-   }
-
-  
-   if ( !CreateEGLContext ( esContext->hWnd,
-                            &esContext->eglDisplay,
-                            &esContext->eglContext,
-                            &esContext->eglSurface,
-                            configAttribList,
-                            surfaceAttribList ) )
-   {
-      return GL_FALSE;
-   }
-   
-
-   return GL_TRUE;
-}
-
-///
-//  esMainLoop()
-//
-//    Start the main loop for the OpenGL ES application
-//
-void ESUTIL_API esMainLoop ( ESContext *esContext )
-{
-   WinLoop ( esContext );
-}
-
-
-///
-//  esRegisterDrawFunc()
-//
-void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) (ESContext* ) )
-{
-   esContext->drawFunc = drawFunc;
-}
-
-
-///
-//  esRegisterUpdateFunc()
-//
-void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) )
-{
-   esContext->updateFunc = updateFunc;
-}
-
-
-///
-//  esRegisterKeyFunc()
-//
-void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext,
-                                    void (ESCALLBACK *keyFunc) (ESContext*, unsigned char, int, int ) )
-{
-   esContext->keyFunc = keyFunc;
-}
-
-
-///
-// esLogMessage()
-//
-//    Log an error message to the debug output for the platform
-//
-void ESUTIL_API esLogMessage ( const char *formatStr, ... )
-{
-    va_list params;
-    char buf[BUFSIZ];
-
-    va_start ( params, formatStr );
-    vsprintf_s ( buf, sizeof(buf),  formatStr, params );
-    
-    printf ( "%s", buf );
-    
-    va_end ( params );
-}
-
-
-///
-// esLoadTGA()
-//
-//    Loads a 24-bit TGA image from a file
-//
-char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height )
-{
-   char *buffer;
-
-   if ( WinTGALoad ( fileName, &buffer, width, height ) )
-   {
-      return buffer;
-   }
-
-   return NULL;
-}
diff --git a/src/third_party/angle/samples/gles2_book/Common/esUtil.h b/src/third_party/angle/samples/gles2_book/Common/esUtil.h
deleted file mode 100644
index 7b7595c..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/esUtil.h
+++ /dev/null
@@ -1,297 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-//
-/// \file ESUtil.h
-/// \brief A utility library for OpenGL ES.  This library provides a
-///        basic common framework for the example applications in the
-///        OpenGL ES 2.0 Programming Guide.
-//
-#ifndef ESUTIL_H
-#define ESUTIL_H
-
-///
-//  Includes
-//
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#ifdef __cplusplus
-
-extern "C" {
-#endif
-
-   
-///
-//  Macros
-//
-#define ESUTIL_API  __cdecl
-#define ESCALLBACK  __cdecl
-
-
-/// esCreateWindow flag - RGB color buffer
-#define ES_WINDOW_RGB           0
-/// esCreateWindow flag - ALPHA color buffer
-#define ES_WINDOW_ALPHA         1 
-/// esCreateWindow flag - depth buffer
-#define ES_WINDOW_DEPTH         2 
-/// esCreateWindow flag - stencil buffer
-#define ES_WINDOW_STENCIL       4
-/// esCreateWindow flag - multi-sample buffer
-#define ES_WINDOW_MULTISAMPLE   8
-/// esCreateWindow flag - EGL_POST_SUB_BUFFER_NV supported.
-#define ES_WINDOW_POST_SUB_BUFFER_SUPPORTED 16
-
-///
-// Types
-//
-
-typedef struct
-{
-    GLfloat   m[4][4];
-} ESMatrix;
-
-typedef struct
-{
-   /// Put your user data here...
-   void*       userData;
-
-   /// Window width
-   GLint       width;
-
-   /// Window height
-   GLint       height;
-
-   /// Window handle
-   EGLNativeWindowType  hWnd;
-
-   /// EGL display
-   EGLDisplay  eglDisplay;
-      
-   /// EGL context
-   EGLContext  eglContext;
-
-   /// EGL surface
-   EGLSurface  eglSurface;
-
-   /// Callbacks
-   void (ESCALLBACK *drawFunc) ( void* );
-   void (ESCALLBACK *keyFunc) ( void*, unsigned char, int, int );
-   void (ESCALLBACK *updateFunc) ( void*, float deltaTime );
-} ESContext;
-
-
-///
-//  Extensions
-//
-
-extern PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
-extern PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
-
-extern PFNEGLPOSTSUBBUFFERNVPROC eglPostSubBufferNV;
-
-extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
-
-extern PFNGLDELETEFENCESNVPROC glDeleteFencesNV;
-extern PFNGLGENFENCESNVPROC glGenFencesNV;
-extern PFNGLGETFENCEIVNVPROC glGetFenceivNV;
-extern PFNGLISFENCENVPROC glIsFenceNV;
-extern PFNGLFINISHFENCENVPROC glFinishFenceNV;
-extern PFNGLSETFENCENVPROC glSetFenceNV;
-extern PFNGLTESTFENCENVPROC glTestFenceNV;
-
-///
-//  Public Functions
-//
-
-//
-///
-/// \brief Initialize ES framework context.  This must be called before calling any other functions.
-/// \param esContext Application context
-//
-void ESUTIL_API esInitContext ( ESContext *esContext );
-
-//
-/// \brief Create a window with the specified parameters
-/// \param esContext Application context
-/// \param title Name for title bar of window
-/// \param width Width in pixels of window to create
-/// \param height Height in pixels of window to create
-/// \param flags Bitfield for the window creation flags 
-///         ES_WINDOW_RGB     - specifies that the color buffer should have R,G,B channels
-///         ES_WINDOW_ALPHA   - specifies that the color buffer should have alpha
-///         ES_WINDOW_DEPTH   - specifies that a depth buffer should be created
-///         ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
-///         ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
-///         ES_WINDOW_POST_SUB_BUFFER_SUPPORTED - specifies that EGL_POST_SUB_BUFFER_NV is supported.
-/// \return GL_TRUE if window creation is succesful, GL_FALSE otherwise
-GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint width, GLint height, GLuint flags );
-
-//
-/// \brief Start the main loop for the OpenGL ES application
-/// \param esContext Application context
-//
-void ESUTIL_API esMainLoop ( ESContext *esContext );
-
-//
-/// \brief Register a draw callback function to be used to render each frame
-/// \param esContext Application context
-/// \param drawFunc Draw callback function that will be used to render the scene
-//
-void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) ( ESContext* ) );
-
-//
-/// \brief Register an update callback function to be used to update on each time step
-/// \param esContext Application context
-/// \param updateFunc Update callback function that will be used to render the scene
-//
-void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) );
-
-//
-/// \brief Register an keyboard input processing callback function
-/// \param esContext Application context
-/// \param keyFunc Key callback function for application processing of keyboard input
-//
-void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext, 
-                                    void (ESCALLBACK *drawFunc) ( ESContext*, unsigned char, int, int ) );
-//
-/// \brief Log a message to the debug output for the platform
-/// \param formatStr Format string for error log.  
-//
-void ESUTIL_API esLogMessage ( const char *formatStr, ... );
-
-//
-///
-/// \brief Load a shader, check for compile errors, print error messages to output log
-/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
-/// \param shaderSrc Shader source string
-/// \return A new shader object on success, 0 on failure
-//
-GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc );
-
-//
-///
-/// \brief Load a vertex and fragment shader, create a program object, link program.
-///        Errors output to log.
-/// \param vertShaderSrc Vertex shader source code
-/// \param fragShaderSrc Fragment shader source code
-/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
-//
-GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc );
-
-
-//
-/// \brief Generates geometry for a sphere.  Allocates memory for the vertex data and stores 
-///        the results in the arrays.  Generate index list for a TRIANGLE_STRIP
-/// \param numSlices The number of slices in the sphere
-/// \param vertices If not NULL, will contain array of float3 positions
-/// \param normals If not NULL, will contain array of float3 normals
-/// \param texCoords If not NULL, will contain array of float2 texCoords
-/// \param indices If not NULL, will contain the array of indices for the triangle strip
-/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
-///         if it is not NULL ) as a GL_TRIANGLE_STRIP
-//
-int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals, 
-                             GLfloat **texCoords, GLushort **indices );
-
-//
-/// \brief Generates geometry for a cube.  Allocates memory for the vertex data and stores 
-///        the results in the arrays.  Generate index list for a TRIANGLES
-/// \param scale The size of the cube, use 1.0 for a unit cube.
-/// \param vertices If not NULL, will contain array of float3 positions
-/// \param normals If not NULL, will contain array of float3 normals
-/// \param texCoords If not NULL, will contain array of float2 texCoords
-/// \param indices If not NULL, will contain the array of indices for the triangle strip
-/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
-///         if it is not NULL ) as a GL_TRIANGLES
-//
-int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals, 
-                           GLfloat **texCoords, GLushort **indices );
-
-//
-/// \brief Loads a 24-bit TGA image from a file
-/// \param fileName Name of the file on disk
-/// \param width Width of loaded image in pixels
-/// \param height Height of loaded image in pixels
-///  \return Pointer to loaded image.  NULL on failure. 
-//
-char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height );
-
-
-//
-/// \brief multiply matrix specified by result with a scaling matrix and return new matrix in result
-/// \param result Specifies the input matrix.  Scaled matrix is returned in result.
-/// \param sx, sy, sz Scale factors along the x, y and z axes respectively
-//
-void ESUTIL_API esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz);
-
-//
-/// \brief multiply matrix specified by result with a translation matrix and return new matrix in result
-/// \param result Specifies the input matrix.  Translated matrix is returned in result.
-/// \param tx, ty, tz Scale factors along the x, y and z axes respectively
-//
-void ESUTIL_API esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz);
-
-//
-/// \brief multiply matrix specified by result with a rotation matrix and return new matrix in result
-/// \param result Specifies the input matrix.  Rotated matrix is returned in result.
-/// \param angle Specifies the angle of rotation, in degrees.
-/// \param x, y, z Specify the x, y and z coordinates of a vector, respectively
-//
-void ESUTIL_API esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
-
-//
-// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
-/// \param result Specifies the input matrix.  new matrix is returned in result.
-/// \param left, right Coordinates for the left and right vertical clipping planes
-/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
-/// \param nearZ, farZ Distances to the near and far depth clipping planes.  Both distances must be positive.
-//
-void ESUTIL_API esFrustum(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
-
-//
-/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
-/// \param result Specifies the input matrix.  new matrix is returned in result.
-/// \param fovy Field of view y angle in degrees
-/// \param aspect Aspect ratio of screen
-/// \param nearZ Near plane distance
-/// \param farZ Far plane distance
-//
-void ESUTIL_API esPerspective(ESMatrix *result, float fovy, float aspect, float nearZ, float farZ);
-
-//
-/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
-/// \param result Specifies the input matrix.  new matrix is returned in result.
-/// \param left, right Coordinates for the left and right vertical clipping planes
-/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
-/// \param nearZ, farZ Distances to the near and far depth clipping planes.  These values are negative if plane is behind the viewer
-//
-void ESUTIL_API esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
-
-//
-/// \brief perform the following operation - result matrix = srcA matrix * srcB matrix
-/// \param result Returns multiplied matrix
-/// \param srcA, srcB Input matrices to be multiplied
-//
-void ESUTIL_API esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB);
-
-//
-//// \brief return an indentity matrix 
-//// \param result returns identity matrix
-//
-void ESUTIL_API esMatrixLoadIdentity(ESMatrix *result);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // ESUTIL_H
diff --git a/src/third_party/angle/samples/gles2_book/Common/esUtil.vcxproj b/src/third_party/angle/samples/gles2_book/Common/esUtil.vcxproj
deleted file mode 100644
index 8619f2c..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/esUtil.vcxproj
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{47C93F52-AB4E-4FF9-8D4F-B38CD60A183F}</ProjectGuid>

-    <RootNamespace>esUtil</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>./;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>./;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="Win32\esUtil_TGA.c" />

-    <ClCompile Include="Win32\esUtil_win32.c" />

-    <ClCompile Include="esShader.c" />

-    <ClCompile Include="esShapes.c" />

-    <ClCompile Include="esTransform.c" />

-    <ClCompile Include="esUtil.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="esUtil_win.h" />

-    <ClInclude Include="esUtil.h" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\..\..\src\libEGL\libEGL.vcxproj">

-      <Project>{e746fca9-64c3-433e-85e8-9a5a67ab7ed6}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-      <Private>true</Private>

-      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>

-      <LinkLibraryDependencies>true</LinkLibraryDependencies>

-      <UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>

-    </ProjectReference>

-    <ProjectReference Include="..\..\..\src\libGLESv2\libGLESv2.vcxproj">

-      <Project>{b5871a7a-968c-42e3-a33b-981e6f448e78}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-      <Private>true</Private>

-      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>

-      <LinkLibraryDependencies>true</LinkLibraryDependencies>

-      <UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/Common/esUtil.vcxproj.filters b/src/third_party/angle/samples/gles2_book/Common/esUtil.vcxproj.filters
deleted file mode 100644
index b2eb584..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/esUtil.vcxproj.filters
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup>

-    <Filter Include="Win32">

-      <UniqueIdentifier>{8b3de51d-fe0c-4a62-aa51-feb196406ff8}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Common">

-      <UniqueIdentifier>{cdf112d8-e32a-47f8-8095-2b433bc4fc0f}</UniqueIdentifier>

-    </Filter>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="Win32\esUtil_TGA.c">

-      <Filter>Win32</Filter>

-    </ClCompile>

-    <ClCompile Include="Win32\esUtil_win32.c">

-      <Filter>Win32</Filter>

-    </ClCompile>

-    <ClCompile Include="esShader.c">

-      <Filter>Common</Filter>

-    </ClCompile>

-    <ClCompile Include="esShapes.c">

-      <Filter>Common</Filter>

-    </ClCompile>

-    <ClCompile Include="esTransform.c">

-      <Filter>Common</Filter>

-    </ClCompile>

-    <ClCompile Include="esUtil.c">

-      <Filter>Common</Filter>

-    </ClCompile>

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="esUtil_win.h">

-      <Filter>Win32</Filter>

-    </ClInclude>

-    <ClInclude Include="esUtil.h">

-      <Filter>Common</Filter>

-    </ClInclude>

-  </ItemGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/Common/esUtil_win.h b/src/third_party/angle/samples/gles2_book/Common/esUtil_win.h
deleted file mode 100644
index 8ba3406..0000000
--- a/src/third_party/angle/samples/gles2_book/Common/esUtil_win.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// esUtil_win.h
-//
-//   API-neutral interface for creating windows.  Implementation needs to be provided per-platform.
-
-#ifndef ESUTIL_WIN_H
-#define ESUTIL_WIN_H
-
-///
-//  Includes
-//
-
-#ifdef __cplusplus
-
-extern "C" {
-#endif
-
-   
-///
-//  Macros
-//
-
-///
-// Types
-//
-
-///
-//  Public Functions
-//
-
-///
-//  WinCreate()
-//
-//      Create Win32 instance and window
-//
-GLboolean WinCreate ( ESContext *esContext, LPCTSTR title );
-
-///
-//  WinLoop()
-//
-//      Start main windows loop
-//
-void WinLoop ( ESContext *esContext );
-
-///
-//  WinTGALoad()
-//    
-//      TGA loader win32 implementation
-//
-int WinTGALoad ( const char *fileName, char **buffer, int *width, int *height );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // ESUTIL_WIN_H
diff --git a/src/third_party/angle/samples/gles2_book/Hello_Triangle/Hello_Triangle.c b/src/third_party/angle/samples/gles2_book/Hello_Triangle/Hello_Triangle.c
deleted file mode 100644
index b0e3a4c..0000000
--- a/src/third_party/angle/samples/gles2_book/Hello_Triangle/Hello_Triangle.c
+++ /dev/null
@@ -1,194 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// Hello_Triangle.c
-//
-//    This is a simple example that draws a single triangle with
-//    a minimal vertex/fragment shader.  The purpose of this 
-//    example is to demonstrate the basic concepts of 
-//    OpenGL ES 2.0 rendering.
-#include <stdlib.h>
-#include "esUtil.h"
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-} UserData;
-
-///
-// Create a shader object, load the shader source, and
-// compile the shader.
-//
-GLuint LoadShader ( GLenum type, const char *shaderSrc )
-{
-   GLuint shader;
-   GLint compiled;
-   
-   // Create the shader object
-   shader = glCreateShader ( type );
-
-   if ( shader == 0 )
-   	return 0;
-
-   // Load the shader source
-   glShaderSource ( shader, 1, &shaderSrc, NULL );
-   
-   // Compile the shader
-   glCompileShader ( shader );
-
-   // Check the compile status
-   glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
-
-   if ( !compiled ) 
-   {
-      GLint infoLen = 0;
-
-      glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
-      
-      if ( infoLen > 1 )
-      {
-         char* infoLog = malloc (sizeof(char) * infoLen );
-
-         glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
-         esLogMessage ( "Error compiling shader:\n%s\n", infoLog );            
-         
-         free ( infoLog );
-      }
-
-      glDeleteShader ( shader );
-      return 0;
-   }
-
-   return shader;
-
-}
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =  
-      "attribute vec4 vPosition;    \n"
-      "void main()                  \n"
-      "{                            \n"
-      "   gl_Position = vPosition;  \n"
-      "}                            \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;\n"\
-      "void main()                                  \n"
-      "{                                            \n"
-      "  gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
-      "}                                            \n";
-
-   GLuint vertexShader;
-   GLuint fragmentShader;
-   GLuint programObject;
-   GLint linked;
-
-   // Load the vertex/fragment shaders
-   vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
-   fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
-
-   // Create the program object
-   programObject = glCreateProgram ( );
-   
-   if ( programObject == 0 )
-      return 0;
-
-   glAttachShader ( programObject, vertexShader );
-   glAttachShader ( programObject, fragmentShader );
-
-   // Bind vPosition to attribute 0   
-   glBindAttribLocation ( programObject, 0, "vPosition" );
-
-   // Link the program
-   glLinkProgram ( programObject );
-
-   // Check the link status
-   glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
-
-   if ( !linked ) 
-   {
-      GLint infoLen = 0;
-
-      glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
-      
-      if ( infoLen > 1 )
-      {
-         char* infoLog = malloc (sizeof(char) * infoLen );
-
-         glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
-         esLogMessage ( "Error linking program:\n%s\n", infoLog );            
-         
-         free ( infoLog );
-      }
-
-      glDeleteProgram ( programObject );
-      return FALSE;
-   }
-
-   // Store the program object
-   userData->programObject = programObject;
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   return TRUE;
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f, 
-                           -0.5f, -0.5f, 0.0f,
-                            0.5f, -0.5f, 0.0f };
-      
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex data
-   glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
-   glEnableVertexAttribArray ( 0 );
-
-   glDrawArrays ( GL_TRIANGLES, 0, 3 );
-
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("Hello Triangle"), 320, 240, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   
-   esMainLoop ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/Hello_Triangle/Hello_Triangle.vcxproj b/src/third_party/angle/samples/gles2_book/Hello_Triangle/Hello_Triangle.vcxproj
deleted file mode 100644
index 2267d93..0000000
--- a/src/third_party/angle/samples/gles2_book/Hello_Triangle/Hello_Triangle.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{8278251F-6C1F-4D80-8499-FA7B590FAFE6}</ProjectGuid>

-    <RootNamespace>Hello_Triangle</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="Hello_Triangle.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/MipMap2D/MipMap2D.c b/src/third_party/angle/samples/gles2_book/MipMap2D/MipMap2D.c
deleted file mode 100644
index bc70cd4..0000000
--- a/src/third_party/angle/samples/gles2_book/MipMap2D/MipMap2D.c
+++ /dev/null
@@ -1,346 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// MipMap2D.c
-//
-//    This is a simple example that demonstrates generating a mipmap chain
-//    and rendering with it
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-   GLint  texCoordLoc;
-
-   // Sampler location
-   GLint samplerLoc;
-
-   // Offset location
-   GLint offsetLoc;
-
-   // Texture handle
-   GLuint textureId;
-
-} UserData;
-
-
-///
-//  From an RGB8 source image, generate the next level mipmap
-//
-GLboolean GenMipMap2D( GLubyte *src, GLubyte **dst, int srcWidth, int srcHeight, int *dstWidth, int *dstHeight )
-{
-   int x,
-       y;
-   int texelSize = 3;
-
-   *dstWidth = srcWidth / 2;
-   if ( *dstWidth <= 0 )
-      *dstWidth = 1;
-
-   *dstHeight = srcHeight / 2;
-   if ( *dstHeight <= 0 )
-      *dstHeight = 1;
-
-   *dst = malloc ( sizeof(GLubyte) * texelSize * (*dstWidth) * (*dstHeight) );
-   if ( *dst == NULL )
-      return GL_FALSE;
-
-   for ( y = 0; y < *dstHeight; y++ )
-   {
-      for( x = 0; x < *dstWidth; x++ )
-      {
-         int srcIndex[4];
-         float r = 0.0f,
-               g = 0.0f,
-               b = 0.0f;
-         int sample;
-
-         // Compute the offsets for 2x2 grid of pixels in previous
-         // image to perform box filter
-         srcIndex[0] = 
-            (((y * 2) * srcWidth) + (x * 2)) * texelSize;
-         srcIndex[1] = 
-            (((y * 2) * srcWidth) + (x * 2 + 1)) * texelSize; 
-         srcIndex[2] = 
-            ((((y * 2) + 1) * srcWidth) + (x * 2)) * texelSize;
-         srcIndex[3] = 
-            ((((y * 2) + 1) * srcWidth) + (x * 2 + 1)) * texelSize;
-
-         // Sum all pixels
-         for ( sample = 0; sample < 4; sample++ )
-         {
-            r += src[srcIndex[sample]];
-            g += src[srcIndex[sample] + 1];
-            b += src[srcIndex[sample] + 2];
-         }
-
-         // Average results
-         r /= 4.0;
-         g /= 4.0;
-         b /= 4.0;
-
-         // Store resulting pixels
-         (*dst)[ ( y * (*dstWidth) + x ) * texelSize ] = (GLubyte)( r );
-         (*dst)[ ( y * (*dstWidth) + x ) * texelSize + 1] = (GLubyte)( g );
-         (*dst)[ ( y * (*dstWidth) + x ) * texelSize + 2] = (GLubyte)( b );
-      }
-   }
-
-   return GL_TRUE;
-}
-
-///
-//  Generate an RGB8 checkerboard image
-//
-GLubyte* GenCheckImage( int width, int height, int checkSize )
-{
-   int x,
-       y;
-   GLubyte *pixels = malloc( width * height * 3 );
-   
-   if ( pixels == NULL )
-      return NULL;
-
-   for ( y = 0; y < height; y++ )
-      for ( x = 0; x < width; x++ )
-      {
-         GLubyte rColor = 0;
-         GLubyte bColor = 0;
-
-         if ( ( x / checkSize ) % 2 == 0 )
-         {
-            rColor = 255 * ( ( y / checkSize ) % 2 );
-            bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
-         }
-         else
-         {
-            bColor = 255 * ( ( y / checkSize ) % 2 );
-            rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
-         }
-
-         pixels[(y * height + x) * 3] = rColor;
-         pixels[(y * height + x) * 3 + 1] = 0;
-         pixels[(y * height + x) * 3 + 2] = bColor; 
-      } 
-
-   return pixels;
-}
-
-///
-// Create a mipmapped 2D texture image 
-//
-GLuint CreateMipMappedTexture2D( )
-{
-   // Texture object handle
-   GLuint textureId;
-   int    width = 256,
-          height = 256;
-   int    level;
-   GLubyte *pixels;
-   GLubyte *prevImage;
-   GLubyte *newImage = NULL;
-      
-   pixels = GenCheckImage( width, height, 8 );
-   if ( pixels == NULL )
-      return 0;
-
-   // Generate a texture object
-   glGenTextures ( 1, &textureId );
-
-   // Bind the texture object
-   glBindTexture ( GL_TEXTURE_2D, textureId );
-
-   // Load mipmap level 0
-   glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 
-                  0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
-   
-   level = 1;
-   prevImage = &pixels[0];
-   
-   while ( width > 1 && height > 1 )
-   {
-      int newWidth,
-          newHeight;
-
-      // Generate the next mipmap level
-      GenMipMap2D( prevImage, &newImage, width, height, 
-                   &newWidth, &newHeight );
-
-      // Load the mipmap level
-      glTexImage2D( GL_TEXTURE_2D, level, GL_RGB, 
-                    newWidth, newHeight, 0, GL_RGB,
-                    GL_UNSIGNED_BYTE, newImage );
-
-      // Free the previous image
-      free ( prevImage );
-
-      // Set the previous image for the next iteration
-      prevImage = newImage;
-      level++;
-
-      // Half the width and height
-      width = newWidth;
-      height = newHeight;
-   }
-
-   free ( newImage );
-
-   // Set the filtering mode
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-
-   return textureId;
-
-}
-
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =
-      "uniform float u_offset;      \n"
-      "attribute vec4 a_position;   \n"
-      "attribute vec2 a_texCoord;   \n"
-      "varying vec2 v_texCoord;     \n"
-      "void main()                  \n"
-      "{                            \n"
-      "   gl_Position = a_position; \n"
-      "   gl_Position.x += u_offset;\n"
-      "   v_texCoord = a_texCoord;  \n"
-      "}                            \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                            \n"
-      "varying vec2 v_texCoord;                            \n"
-      "uniform sampler2D s_texture;                        \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  gl_FragColor = texture2D( s_texture, v_texCoord );\n"
-      "}                                                   \n";
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-   userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
-   
-   // Get the sampler location
-   userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
-
-   // Get the offset location
-   userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" );
-
-   // Load the texture
-   userData->textureId = CreateMipMappedTexture2D ();
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   return TRUE;
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLfloat vVertices[] = { -0.5f,  0.5f, 0.0f, 1.5f,  // Position 0
-                            0.0f,  0.0f,              // TexCoord 0 
-                           -0.5f, -0.5f, 0.0f, 0.75f, // Position 1
-                            0.0f,  1.0f,              // TexCoord 1
-                            0.5f, -0.5f, 0.0f, 0.75f, // Position 2
-                            1.0f,  1.0f,              // TexCoord 2
-                            0.5f,  0.5f, 0.0f, 1.5f,  // Position 3
-                            1.0f,  0.0f               // TexCoord 3
-                         };
-   GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
-      
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT, 
-                           GL_FALSE, 6 * sizeof(GLfloat), vVertices );
-   // Load the texture coordinate
-   glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
-                           GL_FALSE, 6 * sizeof(GLfloat), &vVertices[4] );
-
-   glEnableVertexAttribArray ( userData->positionLoc );
-   glEnableVertexAttribArray ( userData->texCoordLoc );
-
-   // Bind the texture
-   glActiveTexture ( GL_TEXTURE0 );
-   glBindTexture ( GL_TEXTURE_2D, userData->textureId );
-
-   // Set the sampler texture unit to 0
-   glUniform1i ( userData->samplerLoc, 0 );
-
-   // Draw quad with nearest sampling
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-   glUniform1f ( userData->offsetLoc, -0.6f );   
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   // Draw quad with trilinear filtering
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
-   glUniform1f ( userData->offsetLoc, 0.6f );
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-
-   // Delete texture object
-   glDeleteTextures ( 1, &userData->textureId );
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("MipMap 2D"), 320, 240, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/MipMap2D/MipMap2D.vcxproj b/src/third_party/angle/samples/gles2_book/MipMap2D/MipMap2D.vcxproj
deleted file mode 100644
index bc9dc4d..0000000
--- a/src/third_party/angle/samples/gles2_book/MipMap2D/MipMap2D.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{4E69AC1F-1C7A-4D58-917C-E764FBEB489A}</ProjectGuid>

-    <RootNamespace>MipMap2D</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="MipMap2D.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/MultiTexture/MultiTexture.c b/src/third_party/angle/samples/gles2_book/MultiTexture/MultiTexture.c
deleted file mode 100644
index bb2224a..0000000
--- a/src/third_party/angle/samples/gles2_book/MultiTexture/MultiTexture.c
+++ /dev/null
@@ -1,213 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// MultiTexture.c
-//
-//    This is an example that draws a quad with a basemap and
-//    lightmap to demonstrate multitexturing.
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-   GLint  texCoordLoc;
-
-   // Sampler locations
-   GLint baseMapLoc;
-   GLint lightMapLoc;
-
-   // Texture handle
-   GLuint baseMapTexId;
-   GLuint lightMapTexId;
-
-} UserData;
-
-
-///
-// Load texture from disk
-//
-GLuint LoadTexture ( char *fileName )
-{
-   int width,
-       height;
-   char *buffer = esLoadTGA ( fileName, &width, &height );
-   GLuint texId;
-
-   if ( buffer == NULL )
-   {
-      esLogMessage ( "Error loading (%s) image.\n", fileName );
-      return 0;
-   }
-
-   glGenTextures ( 1, &texId );
-   glBindTexture ( GL_TEXTURE_2D, texId );
-
-   glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
-
-   free ( buffer );
-
-   return texId;
-}
-
-
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =  
-      "attribute vec4 a_position;   \n"
-      "attribute vec2 a_texCoord;   \n"
-      "varying vec2 v_texCoord;     \n"
-      "void main()                  \n"
-      "{                            \n"
-      "   gl_Position = a_position; \n"
-      "   v_texCoord = a_texCoord;  \n"
-      "}                            \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                            \n"
-      "varying vec2 v_texCoord;                            \n"
-      "uniform sampler2D s_baseMap;                        \n"
-      "uniform sampler2D s_lightMap;                       \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  vec4 baseColor;                                   \n"
-      "  vec4 lightColor;                                  \n"
-      "                                                    \n"
-      "  baseColor = texture2D( s_baseMap, v_texCoord );   \n"
-      "  lightColor = texture2D( s_lightMap, v_texCoord ); \n"
-      "  gl_FragColor = baseColor * (lightColor + 0.25);   \n"
-      "}                                                   \n";
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-   userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
-   
-   // Get the sampler location
-   userData->baseMapLoc = glGetUniformLocation ( userData->programObject, "s_baseMap" );
-   userData->lightMapLoc = glGetUniformLocation ( userData->programObject, "s_lightMap" );
-
-   // Load the textures
-   userData->baseMapTexId = LoadTexture ( "basemap.tga" );
-   userData->lightMapTexId = LoadTexture ( "lightmap.tga" );
-
-   if ( userData->baseMapTexId == 0 || userData->lightMapTexId == 0 )
-      return FALSE;
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   return TRUE;
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLfloat vVertices[] = { -0.5f,  0.5f, 0.0f,  // Position 0
-                            0.0f,  0.0f,        // TexCoord 0 
-                           -0.5f, -0.5f, 0.0f,  // Position 1
-                            0.0f,  1.0f,        // TexCoord 1
-                            0.5f, -0.5f, 0.0f,  // Position 2
-                            1.0f,  1.0f,        // TexCoord 2
-                            0.5f,  0.5f, 0.0f,  // Position 3
-                            1.0f,  0.0f         // TexCoord 3
-                         };
-   GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
-      
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 
-                           GL_FALSE, 5 * sizeof(GLfloat), vVertices );
-   // Load the texture coordinate
-   glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
-                           GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
-
-   glEnableVertexAttribArray ( userData->positionLoc );
-   glEnableVertexAttribArray ( userData->texCoordLoc );
-
-   // Bind the base map
-   glActiveTexture ( GL_TEXTURE0 );
-   glBindTexture ( GL_TEXTURE_2D, userData->baseMapTexId );
-
-   // Set the base map sampler to texture unit to 0
-   glUniform1i ( userData->baseMapLoc, 0 );
-
-   // Bind the light map
-   glActiveTexture ( GL_TEXTURE1 );
-   glBindTexture ( GL_TEXTURE_2D, userData->lightMapTexId );
-   
-   // Set the light map sampler to texture unit 1
-   glUniform1i ( userData->lightMapLoc, 1 );
-
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-
-   // Delete texture object
-   glDeleteTextures ( 1, &userData->baseMapTexId );
-   glDeleteTextures ( 1, &userData->lightMapTexId );
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("MultiTexture"), 320, 240, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/MultiTexture/MultiTexture.vcxproj b/src/third_party/angle/samples/gles2_book/MultiTexture/MultiTexture.vcxproj
deleted file mode 100644
index b0ee09c..0000000
--- a/src/third_party/angle/samples/gles2_book/MultiTexture/MultiTexture.vcxproj
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{120CFF94-ED4B-4C5B-9587-9E40889F15F7}</ProjectGuid>

-    <RootNamespace>MultiTexture</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>xcopy /D /Y basemap.tga "$(OutDir)"

-xcopy /D /Y lightmap.tga "$(OutDir)"

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>xcopy /D /Y basemap.tga "$(OutDir)"

-xcopy /D /Y lightmap.tga "$(OutDir)"

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="MultiTexture.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/MultipleRenderTargets/MultipleRenderTargets.c b/src/third_party/angle/samples/gles2_book/MultipleRenderTargets/MultipleRenderTargets.c
deleted file mode 100644
index 0e06c29..0000000
--- a/src/third_party/angle/samples/gles2_book/MultipleRenderTargets/MultipleRenderTargets.c
+++ /dev/null
@@ -1,295 +0,0 @@
-//
-// Modified from Simple_Texture2D, found in:
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// MultipleRenderTargets.c
-//
-//    This is a simple example that shows how to use multiple render
-//    targets in GLES 2.0 using EXT_draw_buffers. The example
-//    draws to three render targets and displays
-//    them together in a final pass.
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-PFNGLDRAWBUFFERSEXTPROC glDrawBuffersEXT;
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObjectMRT;
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-   GLint  texCoordLoc;
-
-   // Sampler location
-   GLint samplerLoc;
-
-   // Texture handle
-   GLuint textureId;
-
-   // Framebuffer object handle
-   GLuint framebuffer;
-
-   // Framebuffer color attachments
-   GLuint framebufferTextures[4];
-
-} UserData;
-
-///
-// Create a simple 2x2 texture image with four different colors
-//
-GLuint CreateSimpleTexture2D( )
-{
-   // Texture object handle
-   GLuint textureId;
-   
-   // 2x2 Image, 3 bytes per pixel (R, G, B)
-   GLubyte pixels[4 * 3] =
-   {  
-      255,   0,   0, // Red
-        0, 255,   0, // Green
-        0,   0, 255, // Blue
-      255, 255,   0  // Yellow
-   };
-
-   // Use tightly packed data
-   glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
-
-   // Generate a texture object
-   glGenTextures ( 1, &textureId );
-
-   // Bind the texture object
-   glBindTexture ( GL_TEXTURE_2D, textureId );
-
-   // Load the texture
-   glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
-
-   // Set the filtering mode
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-
-   return textureId;
-
-}
-
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = (UserData*)esContext->userData;
-   GLbyte vShaderStr[] =  
-      "attribute vec4 a_position;   \n"
-      "attribute vec2 a_texCoord;   \n"
-      "varying vec2 v_texCoord;     \n"
-      "void main()                  \n"
-      "{                            \n"
-      "   gl_Position = a_position; \n"
-      "   v_texCoord = a_texCoord;  \n"
-      "}                            \n";
-   
-   GLbyte fMultiShaderStr[] =  
-      "#extension GL_EXT_draw_buffers : enable             \n"
-      "precision mediump float;                            \n"
-      "varying vec2 v_texCoord;                            \n"
-      "uniform sampler2D s_texture;                        \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  vec4 color = texture2D( s_texture, v_texCoord );  \n"
-      "  gl_FragData[0] = color;                           \n"
-      "  gl_FragData[1] = vec4(1.0, 1.0, 1.0, 1.0) - color.brga;\n"
-      "  gl_FragData[2] = vec4(0.2, 1.0, 0.5, 1.0) * color.gbra;\n"
-      "  gl_FragData[3] = color.rrra;                      \n"
-      "}                                                   \n";
-
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                            \n"
-      "varying vec2 v_texCoord;                            \n"
-      "uniform sampler2D s_texture;                        \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  vec4 color = texture2D( s_texture, v_texCoord );  \n"
-      "  gl_FragColor = color;                             \n"
-      "}                                                   \n";
-
-   int i;
-
-   // Check EXT_draw_buffers is supported
-   if (strstr(glGetString(GL_EXTENSIONS), "GL_EXT_draw_buffers") == 0)
-   {
-       return FALSE;
-   }
-
-   // Retrieve the address of glDrawBuffersEXT from EGL
-   glDrawBuffersEXT = (PFNGLDRAWBUFFERSEXTPROC)eglGetProcAddress("glDrawBuffersEXT");
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( (const char*)vShaderStr, (const char*)fShaderStr );
-
-   userData->programObjectMRT = esLoadProgram ( (const char*)vShaderStr, (const char*)fMultiShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-   userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
-   
-   // Get the sampler location
-   userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
-
-   // Load the texture
-   userData->textureId = CreateSimpleTexture2D ();
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-
-   // Initialize the user framebuffer
-   glGenFramebuffers(1, &userData->framebuffer);
-   glGenTextures(4, userData->framebufferTextures);
-
-   glBindFramebuffer(GL_FRAMEBUFFER, userData->framebuffer);
-
-   for (i = 0; i < 4; i++)
-   {
-       // Create textures for the four color attachments
-       glBindTexture(GL_TEXTURE_2D, userData->framebufferTextures[i]);
-       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, esContext->width, esContext->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, userData->framebufferTextures[i], 0); 
-   }
-
-   glBindTexture(GL_TEXTURE_2D, 0);
-   
-   return TRUE;
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = (UserData*)esContext->userData;
-   GLfloat vVertices[] = { -0.8f,  0.8f, 0.0f,  // Position 0
-                            0.0f,  0.0f,        // TexCoord 0 
-                           -0.8f, -0.8f, 0.0f,  // Position 1
-                            0.0f,  1.0f,        // TexCoord 1
-                            0.8f, -0.8f, 0.0f,  // Position 2
-                            1.0f,  1.0f,        // TexCoord 2
-                            0.8f,  0.8f, 0.0f,  // Position 3
-                            1.0f,  0.0f         // TexCoord 3
-                         };
-   GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
-
-   GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT };
-
-   // Enable drawing to the four color attachments of the user framebuffer
-   glBindFramebuffer(GL_FRAMEBUFFER, userData->framebuffer);
-   glDrawBuffersEXT(4, drawBuffers);
-
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObjectMRT );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 
-                           GL_FALSE, 5 * sizeof(GLfloat), vVertices );
-   // Load the texture coordinate
-   glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
-                           GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
-
-   glEnableVertexAttribArray ( userData->positionLoc );
-   glEnableVertexAttribArray ( userData->texCoordLoc );
-
-   // Bind the texture
-   glActiveTexture ( GL_TEXTURE0 );
-   glBindTexture ( GL_TEXTURE_2D, userData->textureId );
-
-   // Set the sampler texture unit to 0
-   glUniform1i ( userData->samplerLoc, 0 );
-
-   // Draw the textured quad to the four render targets
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   // Enable the default framebuffer and single textured drawing
-   glBindFramebuffer(GL_FRAMEBUFFER, 0);
-   glUseProgram ( userData->programObject );
-
-   // Draw the four textured quads to a separate region in the viewport
-   glBindTexture( GL_TEXTURE_2D, userData->framebufferTextures[0]);
-   glViewport ( 0, 0, esContext->width/2, esContext->height/2 );
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   glBindTexture( GL_TEXTURE_2D, userData->framebufferTextures[1]);
-   glViewport ( esContext->width/2, 0, esContext->width/2, esContext->height/2 );
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   glBindTexture( GL_TEXTURE_2D, userData->framebufferTextures[2]);
-   glViewport ( 0, esContext->height/2, esContext->width/2, esContext->height/2 );
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   glBindTexture( GL_TEXTURE_2D, userData->framebufferTextures[3]);
-   glViewport ( esContext->width/2, esContext->height/2, esContext->width/2, esContext->height/2 );
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = (UserData*)esContext->userData;
-
-   glDeleteTextures(4, userData->framebufferTextures);
-
-   glDeleteFramebuffers(1, &userData->framebuffer);
-
-   // Delete texture object
-   glDeleteTextures ( 1, &userData->textureId );
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-
-   eglDestroyContext(esContext->eglDisplay, esContext->eglContext);
-   eglDestroySurface(esContext->eglDisplay, esContext->eglSurface);
-   eglTerminate(esContext->eglDisplay);
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("Multiple Render Targets"), 320, 240, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/MultipleRenderTargets/MultipleRenderTargets.vcxproj b/src/third_party/angle/samples/gles2_book/MultipleRenderTargets/MultipleRenderTargets.vcxproj
deleted file mode 100644
index 58ea280..0000000
--- a/src/third_party/angle/samples/gles2_book/MultipleRenderTargets/MultipleRenderTargets.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{DD670DCB-2554-4FAE-B7C9-D7F0C3087C10}</ProjectGuid>

-    <RootNamespace>MultipleRenderTargets</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="MultipleRenderTargets.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/ParticleSystem/ParticleSystem.c b/src/third_party/angle/samples/gles2_book/ParticleSystem/ParticleSystem.c
deleted file mode 100644
index 2214133..0000000
--- a/src/third_party/angle/samples/gles2_book/ParticleSystem/ParticleSystem.c
+++ /dev/null
@@ -1,294 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// ParticleSystem.c
-//
-//    This is an example that demonstrates rendering a particle system
-//    using a vertex shader and point sprites.
-//
-#include <stdlib.h>
-#include <math.h>
-#include "esUtil.h"
-
-#define NUM_PARTICLES	1000
-#define PARTICLE_SIZE   7
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  lifetimeLoc;
-   GLint  startPositionLoc;
-   GLint  endPositionLoc;
-   
-   // Uniform location
-   GLint timeLoc;
-   GLint colorLoc;
-   GLint centerPositionLoc;
-   GLint samplerLoc;
-
-   // Texture handle
-   GLuint textureId;
-
-   // Particle vertex data
-   float particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
-
-   // Current time
-   float time;
-
-} UserData;
-
-///
-// Load texture from disk
-//
-GLuint LoadTexture ( char *fileName )
-{
-   int width,
-       height;
-   char *buffer = esLoadTGA ( fileName, &width, &height );
-   GLuint texId;
-
-   if ( buffer == NULL )
-   {
-      esLogMessage ( "Error loading (%s) image.\n", fileName );
-      return 0;
-   }
-
-   glGenTextures ( 1, &texId );
-   glBindTexture ( GL_TEXTURE_2D, texId );
-
-   glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
-
-   free ( buffer );
-
-   return texId;
-}
-
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   int i;
-   
-   GLbyte vShaderStr[] =
-      "uniform float u_time;		                           \n"
-      "uniform vec3 u_centerPosition;                       \n"
-      "attribute float a_lifetime;                          \n"
-      "attribute vec3 a_startPosition;                      \n"
-      "attribute vec3 a_endPosition;                        \n"
-      "varying float v_lifetime;                            \n"
-      "void main()                                          \n"
-      "{                                                    \n"
-      "  if ( u_time <= a_lifetime )                        \n"
-      "  {                                                  \n"
-      "    gl_Position.xyz = a_startPosition +              \n"
-      "                      (u_time * a_endPosition);      \n"
-      "    gl_Position.xyz += u_centerPosition;             \n"
-      "    gl_Position.w = 1.0;                             \n"
-      "  }                                                  \n"
-      "  else                                               \n"
-      "     gl_Position = vec4( -1000, -1000, 0, 0 );       \n"
-      "  v_lifetime = 1.0 - ( u_time / a_lifetime );        \n"
-      "  v_lifetime = clamp ( v_lifetime, 0.0, 1.0 );       \n"
-      "  gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n"
-      "}";
-      
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                             \n"
-      "uniform vec4 u_color;		                           \n"
-      "varying float v_lifetime;                            \n"
-      "uniform sampler2D s_texture;                         \n"
-      "void main()                                          \n"
-      "{                                                    \n"
-      "  vec4 texColor;                                     \n"
-      "  texColor = texture2D( s_texture, gl_PointCoord );  \n"
-      "  gl_FragColor = vec4( u_color ) * texColor;         \n"
-      "  gl_FragColor.a *= v_lifetime;                      \n"
-      "}                                                    \n";
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->lifetimeLoc = glGetAttribLocation ( userData->programObject, "a_lifetime" );
-   userData->startPositionLoc = glGetAttribLocation ( userData->programObject, "a_startPosition" );
-   userData->endPositionLoc = glGetAttribLocation ( userData->programObject, "a_endPosition" );
-   
-   // Get the uniform locations
-   userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" );
-   userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" );
-   userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
-   userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-
-   // Fill in particle data array
-   srand ( 0 );
-   for ( i = 0; i < NUM_PARTICLES; i++ )
-   {
-      float *particleData = &userData->particleData[i * PARTICLE_SIZE];
-   
-      // Lifetime of particle
-      (*particleData++) = ( (float)(rand() % 10000) / 10000.0f );
-
-      // End position of particle
-      (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
-      (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
-      (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
-
-      // Start position of particle
-      (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
-      (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
-      (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
-
-   }
-
-   // Initialize time to cause reset on first update
-   userData->time = 1.0f;
-
-   userData->textureId = LoadTexture ( "smoke.tga" );
-   if ( userData->textureId <= 0 )
-   {
-      return FALSE;
-   }
-   
-   return TRUE;
-}
-
-///
-//  Update time-based variables
-//
-void Update ( ESContext *esContext, float deltaTime )
-{
-   UserData *userData = esContext->userData;
-  
-   userData->time += deltaTime;
-
-   if ( userData->time >= 1.0f )
-   {
-      float centerPos[3];
-      float color[4];
-
-      userData->time = 0.0f;
-
-      // Pick a new start location and color
-      centerPos[0] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
-      centerPos[1] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
-      centerPos[2] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
-      
-      glUniform3fv ( userData->centerPositionLoc, 1, &centerPos[0] );
-
-      // Random color
-      color[0] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
-      color[1] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
-      color[2] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
-      color[3] = 0.5;
-
-      glUniform4fv ( userData->colorLoc, 1, &color[0] );
-   }
-
-   // Load uniform time variable
-   glUniform1f ( userData->timeLoc, userData->time );
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-      
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex attributes
-   glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT, 
-                           GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat), 
-                           userData->particleData );
-   
-   glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
-                           GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
-                           &userData->particleData[1] );
-
-   glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
-                           GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
-                           &userData->particleData[4] );
-
-   
-   glEnableVertexAttribArray ( userData->lifetimeLoc );
-   glEnableVertexAttribArray ( userData->endPositionLoc );
-   glEnableVertexAttribArray ( userData->startPositionLoc );
-   // Blend particles
-   glEnable ( GL_BLEND );
-   glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
-
-   // Bind the texture
-   glActiveTexture ( GL_TEXTURE0 );
-   glBindTexture ( GL_TEXTURE_2D, userData->textureId );
-   glEnable ( GL_TEXTURE_2D );
-
-   // Set the sampler texture unit to 0
-   glUniform1i ( userData->samplerLoc, 0 );
-
-   glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
-   
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-
-   // Delete texture object
-   glDeleteTextures ( 1, &userData->textureId );
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("ParticleSystem"), 640, 480, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   esRegisterUpdateFunc ( &esContext, Update );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/ParticleSystem/ParticleSystem.vcxproj b/src/third_party/angle/samples/gles2_book/ParticleSystem/ParticleSystem.vcxproj
deleted file mode 100644
index 3e07a05..0000000
--- a/src/third_party/angle/samples/gles2_book/ParticleSystem/ParticleSystem.vcxproj
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{B9E5BFFC-D843-4E0E-9D3E-23913A613473}</ProjectGuid>

-    <RootNamespace>ParticleSystem</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>xcopy /D /Y smoke.tga "$(outDir)"</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>xcopy /D /Y smoke.tga "$(outDir)"</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="ParticleSystem.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/PostSubBuffer/PostSubBuffer.c b/src/third_party/angle/samples/gles2_book/PostSubBuffer/PostSubBuffer.c
deleted file mode 100644
index 0096ec3..0000000
--- a/src/third_party/angle/samples/gles2_book/PostSubBuffer/PostSubBuffer.c
+++ /dev/null
@@ -1,204 +0,0 @@
-// Based on a sample from:
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// PostSubBuffer.c
-//
-//    This is a simple example that draws a rotating cube in perspective
-//    using a vertex shader to transform the object, posting only a subrectangle
-//    to the window surface.
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-#define WINDOW_WIDTH 320
-#define WINDOW_HEIGHT 240
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-
-   // Uniform locations
-   GLint  mvpLoc;
-   
-   // Vertex daata
-   GLfloat  *vertices;
-   GLushort   *indices;
-   int       numIndices;
-
-   // Rotation angle
-   GLfloat   angle;
-
-   // MVP matrix
-   ESMatrix  mvpMatrix;
-} UserData;
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =  
-      "uniform mat4 u_mvpMatrix;                   \n"
-      "attribute vec4 a_position;                  \n"
-      "void main()                                 \n"
-      "{                                           \n"
-      "   gl_Position = u_mvpMatrix * a_position;  \n"
-      "}                                           \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                            \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );        \n"
-      "}                                                   \n";
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-
-   // Get the uniform locations
-   userData->mvpLoc = glGetUniformLocation( userData->programObject, "u_mvpMatrix" );
-   
-   // Generate the vertex data
-   userData->numIndices = esGenCube( 1.0, &userData->vertices,
-                                     NULL, NULL, &userData->indices );
-   
-   // Starting rotation angle for the cube
-   userData->angle = 45.0f;
-
-   // Clear the whole window surface.
-   glClearColor ( 0.0f, 0.0f, 1.0f, 0.0f );
-   glClear ( GL_COLOR_BUFFER_BIT );
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   return TRUE;
-}
-
-
-///
-// Update MVP matrix based on time
-//
-void Update ( ESContext *esContext, float deltaTime )
-{
-   UserData *userData = (UserData*) esContext->userData;
-   ESMatrix perspective;
-   ESMatrix modelview;
-   float    aspect;
-   
-   // Compute a rotation angle based on time to rotate the cube
-   userData->angle += ( deltaTime * 40.0f );
-   if( userData->angle >= 360.0f )
-      userData->angle -= 360.0f;
-
-   // Compute the window aspect ratio
-   aspect = (GLfloat) esContext->width / (GLfloat) esContext->height;
-   
-   // Generate a perspective matrix with a 60 degree FOV
-   esMatrixLoadIdentity( &perspective );
-   esPerspective( &perspective, 60.0f, aspect, 1.0f, 20.0f );
-
-   // Generate a model view matrix to rotate/translate the cube
-   esMatrixLoadIdentity( &modelview );
-
-   // Translate away from the viewer
-   esTranslate( &modelview, 0.0, 0.0, -2.0 );
-
-   // Rotate the cube
-   esRotate( &modelview, userData->angle, 1.0, 0.0, 1.0 );
-   
-   // Compute the final MVP by multiplying the 
-   // modevleiw and perspective matrices together
-   esMatrixMultiply( &userData->mvpMatrix, &modelview, &perspective );
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 
-                           GL_FALSE, 3 * sizeof(GLfloat), userData->vertices );
-   
-   glEnableVertexAttribArray ( userData->positionLoc );
-   
-   
-   // Load the MVP matrix
-   glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE, (GLfloat*) &userData->mvpMatrix.m[0][0] );
-   
-   // Draw the cube
-   glDrawElements ( GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_SHORT, userData->indices );
-
-   eglPostSubBufferNV ( esContext->eglDisplay, esContext->eglSurface, 60, 60, WINDOW_WIDTH - 120, WINDOW_HEIGHT - 120 );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-
-   if ( userData->vertices != NULL )
-   {
-      free ( userData->vertices );
-   }
-
-   if ( userData->indices != NULL )
-   {
-      free ( userData->indices );
-   }
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("Simple Vertex Shader"), WINDOW_WIDTH, WINDOW_HEIGHT, ES_WINDOW_RGB | ES_WINDOW_POST_SUB_BUFFER_SUPPORTED );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   esRegisterUpdateFunc ( &esContext, Update );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/PostSubBuffer/PostSubBuffer.vcxproj b/src/third_party/angle/samples/gles2_book/PostSubBuffer/PostSubBuffer.vcxproj
deleted file mode 100644
index 488034b..0000000
--- a/src/third_party/angle/samples/gles2_book/PostSubBuffer/PostSubBuffer.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{667CE95F-5DD8-4495-8C18-5CA8A175B12D}</ProjectGuid>

-    <RootNamespace>Simple_VertexShader</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="PostSubBuffer.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/Simple_Texture2D/Simple_Texture2D.c b/src/third_party/angle/samples/gles2_book/Simple_Texture2D/Simple_Texture2D.c
deleted file mode 100644
index b074608..0000000
--- a/src/third_party/angle/samples/gles2_book/Simple_Texture2D/Simple_Texture2D.c
+++ /dev/null
@@ -1,198 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// Simple_Texture2D.c
-//
-//    This is a simple example that draws a quad with a 2D
-//    texture image. The purpose of this example is to demonstrate 
-//    the basics of 2D texturing
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-   GLint  texCoordLoc;
-
-   // Sampler location
-   GLint samplerLoc;
-
-   // Texture handle
-   GLuint textureId;
-
-} UserData;
-
-///
-// Create a simple 2x2 texture image with four different colors
-//
-GLuint CreateSimpleTexture2D( )
-{
-   // Texture object handle
-   GLuint textureId;
-   
-   // 2x2 Image, 3 bytes per pixel (R, G, B)
-   GLubyte pixels[4 * 3] =
-   {  
-      255,   0,   0, // Red
-        0, 255,   0, // Green
-        0,   0, 255, // Blue
-      255, 255,   0  // Yellow
-   };
-
-   // Use tightly packed data
-   glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
-
-   // Generate a texture object
-   glGenTextures ( 1, &textureId );
-
-   // Bind the texture object
-   glBindTexture ( GL_TEXTURE_2D, textureId );
-
-   // Load the texture
-   glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
-
-   // Set the filtering mode
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-
-   return textureId;
-
-}
-
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =  
-      "attribute vec4 a_position;   \n"
-      "attribute vec2 a_texCoord;   \n"
-      "varying vec2 v_texCoord;     \n"
-      "void main()                  \n"
-      "{                            \n"
-      "   gl_Position = a_position; \n"
-      "   v_texCoord = a_texCoord;  \n"
-      "}                            \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                            \n"
-      "varying vec2 v_texCoord;                            \n"
-      "uniform sampler2D s_texture;                        \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  gl_FragColor = texture2D( s_texture, v_texCoord );\n"
-      "}                                                   \n";
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-   userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
-   
-   // Get the sampler location
-   userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
-
-   // Load the texture
-   userData->textureId = CreateSimpleTexture2D ();
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   return TRUE;
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLfloat vVertices[] = { -0.5f,  0.5f, 0.0f,  // Position 0
-                            0.0f,  0.0f,        // TexCoord 0 
-                           -0.5f, -0.5f, 0.0f,  // Position 1
-                            0.0f,  1.0f,        // TexCoord 1
-                            0.5f, -0.5f, 0.0f,  // Position 2
-                            1.0f,  1.0f,        // TexCoord 2
-                            0.5f,  0.5f, 0.0f,  // Position 3
-                            1.0f,  0.0f         // TexCoord 3
-                         };
-   GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
-      
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 
-                           GL_FALSE, 5 * sizeof(GLfloat), vVertices );
-   // Load the texture coordinate
-   glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
-                           GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
-
-   glEnableVertexAttribArray ( userData->positionLoc );
-   glEnableVertexAttribArray ( userData->texCoordLoc );
-
-   // Bind the texture
-   glActiveTexture ( GL_TEXTURE0 );
-   glBindTexture ( GL_TEXTURE_2D, userData->textureId );
-
-   // Set the sampler texture unit to 0
-   glUniform1i ( userData->samplerLoc, 0 );
-
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-
-   // Delete texture object
-   glDeleteTextures ( 1, &userData->textureId );
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("Simple Texture 2D"), 320, 240, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/Simple_Texture2D/Simple_Texture2D.vcxproj b/src/third_party/angle/samples/gles2_book/Simple_Texture2D/Simple_Texture2D.vcxproj
deleted file mode 100644
index 2e755bb..0000000
--- a/src/third_party/angle/samples/gles2_book/Simple_Texture2D/Simple_Texture2D.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{2E54D748-781B-4DF2-A1DD-B9384A821810}</ProjectGuid>

-    <RootNamespace>Simple_Texture2D</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="Simple_Texture2D.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/Simple_TextureCubemap/Simple_TextureCubemap.c b/src/third_party/angle/samples/gles2_book/Simple_TextureCubemap/Simple_TextureCubemap.c
deleted file mode 100644
index 302d844..0000000
--- a/src/third_party/angle/samples/gles2_book/Simple_TextureCubemap/Simple_TextureCubemap.c
+++ /dev/null
@@ -1,229 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// Simple_TextureCubemap.c
-//
-//    This is a simple example that draws a sphere with a cubemap image applied.
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-   GLint  normalLoc;
-
-   // Sampler location
-   GLint samplerLoc;
-
-   // Texture handle
-   GLuint textureId;
-
-   // Vertex data
-   int      numIndices;
-   GLfloat *vertices;
-   GLfloat *normals;
-   GLushort  *indices;
-
-} UserData;
-
-///
-// Create a simple cubemap with a 1x1 face with a different
-// color for each face
-GLuint CreateSimpleTextureCubemap( )
-{
-   GLuint textureId;
-   // Six 1x1 RGB faces
-   GLubyte cubePixels[6][3] =
-   {
-      // Face 0 - Red
-      255, 0, 0,
-      // Face 1 - Green,
-      0, 255, 0, 
-      // Face 3 - Blue
-      0, 0, 255,
-      // Face 4 - Yellow
-      255, 255, 0,
-      // Face 5 - Purple
-      255, 0, 255,
-      // Face 6 - White
-      255, 255, 255
-   };
-   
-   // Generate a texture object
-   glGenTextures ( 1, &textureId );
-
-   // Bind the texture object
-   glBindTexture ( GL_TEXTURE_CUBE_MAP, textureId );
-   
-   // Load the cube face - Positive X
-   glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, 1, 1, 0, 
-                  GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[0] );
-
-   // Load the cube face - Negative X
-   glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, 1, 1, 0, 
-                  GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[1] );
-
-   // Load the cube face - Positive Y
-   glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, 1, 1, 0, 
-                  GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[2] );
-
-   // Load the cube face - Negative Y
-   glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, 1, 1, 0, 
-                  GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[3] );
-
-   // Load the cube face - Positive Z
-   glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, 1, 1, 0, 
-                  GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[4] );
-
-   // Load the cube face - Negative Z
-   glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, 1, 1, 0, 
-                  GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[5] );
-
-   // Set the filtering mode
-   glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-   glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-
-   return textureId;
-
-}
-
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =  
-      "attribute vec4 a_position;   \n"
-      "attribute vec3 a_normal;     \n"
-      "varying vec3 v_normal;       \n"
-      "void main()                  \n"
-      "{                            \n"
-      "   gl_Position = a_position; \n"
-      "   v_normal = a_normal;      \n"
-      "}                            \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                            \n"
-      "varying vec3 v_normal;                              \n"
-      "uniform samplerCube s_texture;                      \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  gl_FragColor = textureCube( s_texture, v_normal );\n"
-      "}                                                   \n";
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-   userData->normalLoc = glGetAttribLocation ( userData->programObject, "a_normal" );
-   
-   // Get the sampler locations
-   userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
-
-   // Load the texture
-   userData->textureId = CreateSimpleTextureCubemap ();
-
-   // Generate the vertex data
-   userData->numIndices = esGenSphere ( 20, 0.75f, &userData->vertices, &userData->normals, 
-                                        NULL, &userData->indices );
-
-   
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   return TRUE;
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-      
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   
-   glCullFace ( GL_BACK );
-   glEnable ( GL_CULL_FACE );
-   
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 
-                           GL_FALSE, 0, userData->vertices );
-   // Load the normal
-   glVertexAttribPointer ( userData->normalLoc, 3, GL_FLOAT,
-                           GL_FALSE, 0, userData->normals );
-
-   glEnableVertexAttribArray ( userData->positionLoc );
-   glEnableVertexAttribArray ( userData->normalLoc );
-
-   // Bind the texture
-   glActiveTexture ( GL_TEXTURE0 );
-   glBindTexture ( GL_TEXTURE_CUBE_MAP, userData->textureId );
-
-   // Set the sampler texture unit to 0
-   glUniform1i ( userData->samplerLoc, 0 );
-
-   glDrawElements ( GL_TRIANGLES, userData->numIndices, 
-                    GL_UNSIGNED_SHORT, userData->indices );
-
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-
-   // Delete texture object
-   glDeleteTextures ( 1, &userData->textureId );
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-
-   free ( userData->vertices );
-   free ( userData->normals );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("Simple Texture Cubemap"), 320, 240, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/Simple_TextureCubemap/Simple_TextureCubemap.vcxproj b/src/third_party/angle/samples/gles2_book/Simple_TextureCubemap/Simple_TextureCubemap.vcxproj
deleted file mode 100644
index df2bc01..0000000
--- a/src/third_party/angle/samples/gles2_book/Simple_TextureCubemap/Simple_TextureCubemap.vcxproj
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{5EE56061-643D-406E-B42D-4299D2411056}</ProjectGuid>

-    <RootNamespace>Simple_TextureCubemap</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <ProjectReference>

-      <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>

-    </ProjectReference>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="Simple_TextureCubemap.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/Simple_VertexShader/Simple_VertexShader.c b/src/third_party/angle/samples/gles2_book/Simple_VertexShader/Simple_VertexShader.c
deleted file mode 100644
index df5c98d..0000000
--- a/src/third_party/angle/samples/gles2_book/Simple_VertexShader/Simple_VertexShader.c
+++ /dev/null
@@ -1,194 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// Simple_VertexShader.c
-//
-//    This is a simple example that draws a rotating cube in perspective
-//    using a vertex shader to transform the object
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-
-   // Uniform locations
-   GLint  mvpLoc;
-   
-   // Vertex daata
-   GLfloat  *vertices;
-   GLushort   *indices;
-   int       numIndices;
-
-   // Rotation angle
-   GLfloat   angle;
-
-   // MVP matrix
-   ESMatrix  mvpMatrix;
-} UserData;
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =  
-      "uniform mat4 u_mvpMatrix;                   \n"
-      "attribute vec4 a_position;                  \n"
-      "void main()                                 \n"
-      "{                                           \n"
-      "   gl_Position = u_mvpMatrix * a_position;  \n"
-      "}                                           \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                            \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );        \n"
-      "}                                                   \n";
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-
-   // Get the uniform locations
-   userData->mvpLoc = glGetUniformLocation( userData->programObject, "u_mvpMatrix" );
-   
-   // Generate the vertex data
-   userData->numIndices = esGenCube( 1.0, &userData->vertices,
-                                     NULL, NULL, &userData->indices );
-   
-   // Starting rotation angle for the cube
-   userData->angle = 45.0f;
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   return TRUE;
-}
-
-
-///
-// Update MVP matrix based on time
-//
-void Update ( ESContext *esContext, float deltaTime )
-{
-   UserData *userData = (UserData*) esContext->userData;
-   ESMatrix perspective;
-   ESMatrix modelview;
-   float    aspect;
-   
-   // Compute a rotation angle based on time to rotate the cube
-   userData->angle += ( deltaTime * 40.0f );
-   if( userData->angle >= 360.0f )
-      userData->angle -= 360.0f;
-
-   // Compute the window aspect ratio
-   aspect = (GLfloat) esContext->width / (GLfloat) esContext->height;
-   
-   // Generate a perspective matrix with a 60 degree FOV
-   esMatrixLoadIdentity( &perspective );
-   esPerspective( &perspective, 60.0f, aspect, 1.0f, 20.0f );
-
-   // Generate a model view matrix to rotate/translate the cube
-   esMatrixLoadIdentity( &modelview );
-
-   // Translate away from the viewer
-   esTranslate( &modelview, 0.0, 0.0, -2.0 );
-
-   // Rotate the cube
-   esRotate( &modelview, userData->angle, 1.0, 0.0, 1.0 );
-   
-   // Compute the final MVP by multiplying the 
-   // modevleiw and perspective matrices together
-   esMatrixMultiply( &userData->mvpMatrix, &modelview, &perspective );
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 
-                           GL_FALSE, 3 * sizeof(GLfloat), userData->vertices );
-   
-   glEnableVertexAttribArray ( userData->positionLoc );
-   
-   
-   // Load the MVP matrix
-   glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE, (GLfloat*) &userData->mvpMatrix.m[0][0] );
-   
-   // Draw the cube
-   glDrawElements ( GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_SHORT, userData->indices );
-
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-
-   if ( userData->vertices != NULL )
-   {
-      free ( userData->vertices );
-   }
-
-   if ( userData->indices != NULL )
-   {
-      free ( userData->indices );
-   }
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("Simple Vertex Shader"), 320, 240, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   esRegisterUpdateFunc ( &esContext, Update );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/Simple_VertexShader/Simple_VertexShader.vcxproj b/src/third_party/angle/samples/gles2_book/Simple_VertexShader/Simple_VertexShader.vcxproj
deleted file mode 100644
index b3a2928..0000000
--- a/src/third_party/angle/samples/gles2_book/Simple_VertexShader/Simple_VertexShader.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{667CE95F-5DD8-4395-8C18-5CA8A175B12D}</ProjectGuid>

-    <RootNamespace>Simple_VertexShader</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="Simple_VertexShader.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/Stencil_Test/Stencil_Test.c b/src/third_party/angle/samples/gles2_book/Stencil_Test/Stencil_Test.c
deleted file mode 100644
index 4996ccf..0000000
--- a/src/third_party/angle/samples/gles2_book/Stencil_Test/Stencil_Test.c
+++ /dev/null
@@ -1,273 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// Stencil_Test.c
-//
-//    This example shows various stencil buffer
-//    operations.
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-
-   // Uniform locations
-   GLint  colorLoc;
-
-} UserData;
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =  
-      "attribute vec4 a_position;   \n"
-      "void main()                  \n"
-      "{                            \n"
-      "   gl_Position = a_position; \n"
-      "}                            \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;  \n"
-      "uniform vec4  u_color;    \n"
-      "void main()               \n"
-      "{                         \n"
-      "  gl_FragColor = u_color; \n"
-      "}                         \n";
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-   
-   // Get the sampler location
-   userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
-
-   // Set the clear color
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   
-   // Set the stencil clear value
-   glClearStencil ( 0x1 );
-
-   // Set the depth clear value
-   glClearDepthf( 0.75f );
-
-   // Enable the depth and stencil tests
-   glEnable( GL_DEPTH_TEST );
-   glEnable( GL_STENCIL_TEST );
-
-   return TRUE;
-}
-
-///
-// Initialize the stencil buffer values, and then use those
-//   values to control rendering
-//
-void Draw ( ESContext *esContext )
-{
-   int  i;
-
-   UserData *userData = esContext->userData;
-
-   GLfloat vVertices[] = { 
-       -0.75f,  0.25f,  0.50f, // Quad #0
-       -0.25f,  0.25f,  0.50f,
-       -0.25f,  0.75f,  0.50f,
-       -0.75f,  0.75f,  0.50f,
-	    0.25f,  0.25f,  0.90f, // Quad #1
-		0.75f,  0.25f,  0.90f,
-		0.75f,  0.75f,  0.90f,
-		0.25f,  0.75f,  0.90f,
-	   -0.75f, -0.75f,  0.50f, // Quad #2
-       -0.25f, -0.75f,  0.50f,
-       -0.25f, -0.25f,  0.50f,
-       -0.75f, -0.25f,  0.50f,
-        0.25f, -0.75f,  0.50f, // Quad #3
-        0.75f, -0.75f,  0.50f,
-        0.75f, -0.25f,  0.50f,
-        0.25f, -0.25f,  0.50f,
-       -1.00f, -1.00f,  0.00f, // Big Quad
-        1.00f, -1.00f,  0.00f,
-        1.00f,  1.00f,  0.00f,
-       -1.00f,  1.00f,  0.00f
-   };
-
-   GLubyte indices[][6] = { 
-       {  0,  1,  2,  0,  2,  3 }, // Quad #0
-       {  4,  5,  6,  4,  6,  7 }, // Quad #1
-       {  8,  9, 10,  8, 10, 11 }, // Quad #2
-       { 12, 13, 14, 12, 14, 15 }, // Quad #3
-       { 16, 17, 18, 16, 18, 19 }  // Big Quad
-   };
-   
-#define NumTests  4
-   GLfloat  colors[NumTests][4] = { 
-       { 1.0f, 0.0f, 0.0f, 1.0f },
-       { 0.0f, 1.0f, 0.0f, 1.0f },
-       { 0.0f, 0.0f, 1.0f, 1.0f },
-       { 1.0f, 1.0f, 0.0f, 0.0f }
-   };
-
-   GLint   numStencilBits;
-   GLuint  stencilValues[NumTests] = { 
-      0x7, // Result of test 0
-      0x0, // Result of test 1
-      0x2, // Result of test 2
-      0xff // Result of test 3.  We need to fill this
-           //  value in a run-time
-   };
-
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color, depth, and stencil buffers.  At this
-   //   point, the stencil buffer will be 0x1 for all pixels
-   glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 
-                           GL_FALSE, 0, vVertices );
-  
-   glEnableVertexAttribArray ( userData->positionLoc );
-
-   // Test 0:
-   //
-   // Initialize upper-left region.  In this case, the
-   //   stencil-buffer values will be replaced because the
-   //   stencil test for the rendered pixels will fail the
-   //   stencil test, which is
-   //
-   //        ref   mask   stencil  mask
-   //      ( 0x7 & 0x3 ) < ( 0x1 & 0x7 )
-   //
-   //   The value in the stencil buffer for these pixels will
-   //   be 0x7.
-   //
-   glStencilFunc( GL_LESS, 0x7, 0x3 );
-   glStencilOp( GL_REPLACE, GL_DECR, GL_DECR );
-   glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] );
- 
-   // Test 1:
-   //
-   // Initialize the upper-right region.  Here, we'll decrement
-   //   the stencil-buffer values where the stencil test passes
-   //   but the depth test fails.  The stencil test is
-   //
-   //        ref  mask    stencil  mask
-   //      ( 0x3 & 0x3 ) > ( 0x1 & 0x3 )
-   //
-   //    but where the geometry fails the depth test.  The
-   //    stencil values for these pixels will be 0x0.
-   //
-   glStencilFunc( GL_GREATER, 0x3, 0x3 );
-   glStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
-   glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] );
-
-   // Test 2:
-   //
-   // Initialize the lower-left region.  Here we'll increment 
-   //   (with saturation) the stencil value where both the
-   //   stencil and depth tests pass.  The stencil test for
-   //   these pixels will be
-   //
-   //        ref  mask     stencil  mask
-   //      ( 0x1 & 0x3 ) == ( 0x1 & 0x3 )
-   //
-   //   The stencil values for these pixels will be 0x2.
-   //
-   glStencilFunc( GL_EQUAL, 0x1, 0x3 );
-   glStencilOp( GL_KEEP, GL_INCR, GL_INCR );
-   glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] );
-
-   // Test 3:
-   //
-   // Finally, initialize the lower-right region.  We'll invert
-   //   the stencil value where the stencil tests fails.  The
-   //   stencil test for these pixels will be
-   //
-   //        ref   mask    stencil  mask
-   //      ( 0x2 & 0x1 ) == ( 0x1 & 0x1 )
-   //
-   //   The stencil value here will be set to ~((2^s-1) & 0x1),
-   //   (with the 0x1 being from the stencil clear value),
-   //   where 's' is the number of bits in the stencil buffer
-   //
-   glStencilFunc( GL_EQUAL, 0x2, 0x1 );
-   glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP );
-   glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] );
-   
-   // Since we don't know at compile time how many stecil bits are present,
-   //   we'll query, and update the value correct value in the
-   //   stencilValues arrays for the fourth tests.  We'll use this value
-   //   later in rendering.
-   glGetIntegerv( GL_STENCIL_BITS, &numStencilBits );
-   
-   stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff;
-
-   // Use the stencil buffer for controlling where rendering will
-   //   occur.  We diable writing to the stencil buffer so we
-   //   can test against them without modifying the values we
-   //   generated.
-   glStencilMask( 0x0 );
-   
-   for ( i = 0; i < NumTests; ++i )
-   {
-      glStencilFunc( GL_EQUAL, stencilValues[i], 0xff );
-      glUniform4fv( userData->colorLoc, 1, colors[i] );
-      glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] );
-   }
-
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("Stencil Test"), 320, 240,
-                    ES_WINDOW_RGB | ES_WINDOW_DEPTH | ES_WINDOW_STENCIL );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/Stencil_Test/Stencil_Test.vcxproj b/src/third_party/angle/samples/gles2_book/Stencil_Test/Stencil_Test.vcxproj
deleted file mode 100644
index 2b829a9..0000000
--- a/src/third_party/angle/samples/gles2_book/Stencil_Test/Stencil_Test.vcxproj
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{EEACE995-26BC-4D56-A8B3-3E7A9AB3EB26}</ProjectGuid>

-    <RootNamespace>Stencil_Test</RootNamespace>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>MultiByte</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="Stencil_Test.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/gles2_book/TextureWrap/TextureWrap.c b/src/third_party/angle/samples/gles2_book/TextureWrap/TextureWrap.c
deleted file mode 100644
index 3e958dd..0000000
--- a/src/third_party/angle/samples/gles2_book/TextureWrap/TextureWrap.c
+++ /dev/null
@@ -1,254 +0,0 @@
-//
-// Book:      OpenGL(R) ES 2.0 Programming Guide
-// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
-// ISBN-10:   0321502795
-// ISBN-13:   9780321502797
-// Publisher: Addison-Wesley Professional
-// URLs:      http://safari.informit.com/9780321563835
-//            http://www.opengles-book.com
-//
-
-// TextureWrap.c
-//
-//    This is an example that demonstrates the three texture
-//    wrap modes available on 2D textures
-//
-#include <stdlib.h>
-#include "esUtil.h"
-
-typedef struct
-{
-   // Handle to a program object
-   GLuint programObject;
-
-   // Attribute locations
-   GLint  positionLoc;
-   GLint  texCoordLoc;
-
-   // Sampler location
-   GLint samplerLoc;
-
-   // Offset location
-   GLint offsetLoc;
-
-   // Texture handle
-   GLuint textureId;
-
-} UserData;
-
-///
-//  Generate an RGB8 checkerboard image
-//
-GLubyte* GenCheckImage( int width, int height, int checkSize )
-{
-   int x,
-       y;
-   GLubyte *pixels = malloc( width * height * 3 );
-   
-   if ( pixels == NULL )
-      return NULL;
-
-   for ( y = 0; y < height; y++ )
-      for ( x = 0; x < width; x++ )
-      {
-         GLubyte rColor = 0;
-         GLubyte bColor = 0;
-
-         if ( ( x / checkSize ) % 2 == 0 )
-         {
-            rColor = 255 * ( ( y / checkSize ) % 2 );
-            bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
-         }
-         else
-         {
-            bColor = 255 * ( ( y / checkSize ) % 2 );
-            rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
-         }
-
-         pixels[(y * height + x) * 3] = rColor;
-         pixels[(y * height + x) * 3 + 1] = 0;
-         pixels[(y * height + x) * 3 + 2] = bColor; 
-      } 
-
-   return pixels;
-}
-
-///
-// Create a mipmapped 2D texture image 
-//
-GLuint CreateTexture2D( )
-{
-   // Texture object handle
-   GLuint textureId;
-   int    width = 256,
-          height = 256;
-   GLubyte *pixels;
-      
-   pixels = GenCheckImage( width, height, 64 );
-   if ( pixels == NULL )
-      return 0;
-
-   // Generate a texture object
-   glGenTextures ( 1, &textureId );
-
-   // Bind the texture object
-   glBindTexture ( GL_TEXTURE_2D, textureId );
-
-   // Load mipmap level 0
-   glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 
-                  0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
-   
-   // Set the filtering mode
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-
-   return textureId;
-
-}
-
-
-///
-// Initialize the shader and program object
-//
-int Init ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLbyte vShaderStr[] =
-      "uniform float u_offset;      \n"
-      "attribute vec4 a_position;   \n"
-      "attribute vec2 a_texCoord;   \n"
-      "varying vec2 v_texCoord;     \n"
-      "void main()                  \n"
-      "{                            \n"
-      "   gl_Position = a_position; \n"
-      "   gl_Position.x += u_offset;\n"
-      "   v_texCoord = a_texCoord;  \n"
-      "}                            \n";
-   
-   GLbyte fShaderStr[] =  
-      "precision mediump float;                            \n"
-      "varying vec2 v_texCoord;                            \n"
-      "uniform sampler2D s_texture;                        \n"
-      "void main()                                         \n"
-      "{                                                   \n"
-      "  gl_FragColor = texture2D( s_texture, v_texCoord );\n"
-      "}                                                   \n";
-
-   // Load the shaders and get a linked program object
-   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
-
-   // Get the attribute locations
-   userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
-   userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
-   
-   // Get the sampler location
-   userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
-
-   // Get the offset location
-   userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" );
-
-   // Load the texture
-   userData->textureId = CreateTexture2D ();
-
-   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
-   return TRUE;
-}
-
-///
-// Draw a triangle using the shader pair created in Init()
-//
-void Draw ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-   GLfloat vVertices[] = { -0.3f,  0.3f, 0.0f, 1.0f,  // Position 0
-                           -1.0f,  -1.0f,              // TexCoord 0 
-                           -0.3f, -0.3f, 0.0f, 1.0f, // Position 1
-                           -1.0f,  2.0f,              // TexCoord 1
-                            0.3f, -0.3f, 0.0f, 1.0f, // Position 2
-                            2.0f,  2.0f,              // TexCoord 2
-                            0.3f,  0.3f, 0.0f, 1.0f,  // Position 3
-                            2.0f,  -1.0f               // TexCoord 3
-                         };
-   GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
-      
-   // Set the viewport
-   glViewport ( 0, 0, esContext->width, esContext->height );
-   
-   // Clear the color buffer
-   glClear ( GL_COLOR_BUFFER_BIT );
-
-   // Use the program object
-   glUseProgram ( userData->programObject );
-
-   // Load the vertex position
-   glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT, 
-                           GL_FALSE, 6 * sizeof(GLfloat), vVertices );
-   // Load the texture coordinate
-   glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
-                           GL_FALSE, 6 * sizeof(GLfloat), &vVertices[4] );
-
-   glEnableVertexAttribArray ( userData->positionLoc );
-   glEnableVertexAttribArray ( userData->texCoordLoc );
-
-   // Bind the texture
-   glActiveTexture ( GL_TEXTURE0 );
-   glBindTexture ( GL_TEXTURE_2D, userData->textureId );
-
-   // Set the sampler texture unit to 0
-   glUniform1i ( userData->samplerLoc, 0 );
-
-   // Draw quad with repeat wrap mode
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
-   glUniform1f ( userData->offsetLoc, -0.7f );   
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   // Draw quad with clamp to edge wrap mode
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
-   glUniform1f ( userData->offsetLoc, 0.0f );
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   // Draw quad with mirrored repeat
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT );
-   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT );
-   glUniform1f ( userData->offsetLoc, 0.7f );
-   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
-
-   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
-}
-
-///
-// Cleanup
-//
-void ShutDown ( ESContext *esContext )
-{
-   UserData *userData = esContext->userData;
-
-   // Delete texture object
-   glDeleteTextures ( 1, &userData->textureId );
-
-   // Delete program object
-   glDeleteProgram ( userData->programObject );
-}
-
-
-int main ( int argc, char *argv[] )
-{
-   ESContext esContext;
-   UserData  userData;
-
-   esInitContext ( &esContext );
-   esContext.userData = &userData;
-
-   esCreateWindow ( &esContext, TEXT("Texture Wrap"), 640, 480, ES_WINDOW_RGB );
-   
-   if ( !Init ( &esContext ) )
-      return 0;
-
-   esRegisterDrawFunc ( &esContext, Draw );
-   
-   esMainLoop ( &esContext );
-
-   ShutDown ( &esContext );
-}
diff --git a/src/third_party/angle/samples/gles2_book/TextureWrap/TextureWrap.vcxproj b/src/third_party/angle/samples/gles2_book/TextureWrap/TextureWrap.vcxproj
deleted file mode 100644
index 076b8b6..0000000
--- a/src/third_party/angle/samples/gles2_book/TextureWrap/TextureWrap.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{CC1DE9A2-B456-4565-9C21-932253E969B9}</ProjectGuid>

-    <RootNamespace>TextureWrap</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <AdditionalIncludeDirectories>../Common;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <RandomizedBaseAddress>false</RandomizedBaseAddress>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="TextureWrap.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\Common\esUtil.vcxproj">

-      <Project>{47c93f52-ab4e-4ff9-8d4f-b38cd60a183f}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/hello_triangle/HelloTriangle.cpp b/src/third_party/angle/samples/hello_triangle/HelloTriangle.cpp
new file mode 100644
index 0000000..c842f16
--- /dev/null
+++ b/src/third_party/angle/samples/hello_triangle/HelloTriangle.cpp
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Hello_Triangle.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+
+class HelloTriangleSample : public SampleApplication
+{
+  public:
+    HelloTriangleSample()
+        : SampleApplication("HelloTriangle", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec4 vPosition;
+            void main()
+            {
+                gl_Position = vPosition;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            void main()
+            {
+                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+    }
+
+    virtual void draw()
+    {
+        GLfloat vertices[] =
+        {
+             0.0f,  0.5f, 0.0f,
+            -0.5f, -0.5f, 0.0f,
+             0.5f, -0.5f, 0.0f,
+        };
+
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex data
+        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
+        glEnableVertexAttribArray(0);
+
+        glDrawArrays(GL_TRIANGLES, 0, 3);
+    }
+
+  private:
+    GLuint mProgram;
+};
+
+int main(int argc, char **argv)
+{
+    HelloTriangleSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/mip_map_2d/MipMap2D.cpp b/src/third_party/angle/samples/mip_map_2d/MipMap2D.cpp
new file mode 100644
index 0000000..8703ca3
--- /dev/null
+++ b/src/third_party/angle/samples/mip_map_2d/MipMap2D.cpp
@@ -0,0 +1,169 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on MipMap2D.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+#include "texture_utils.h"
+
+class MipMap2DSample : public SampleApplication
+{
+  public:
+    MipMap2DSample()
+        : SampleApplication("MipMap2D", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            uniform float u_offset;
+            attribute vec4 a_position;
+            attribute vec2 a_texCoord;
+            varying vec2 v_texCoord;
+            void main()
+            {
+                gl_Position = a_position;
+                gl_Position.x += u_offset;
+                v_texCoord = a_texCoord;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec2 v_texCoord;
+            uniform sampler2D s_texture;
+            void main()
+            {
+                gl_FragColor = texture2D(s_texture, v_texCoord);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+        mTexCoordLoc = glGetAttribLocation(mProgram, "a_texCoord");
+
+        // Get the sampler location
+        mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
+
+        // Get the offset location
+        mOffsetLoc = glGetUniformLocation(mProgram, "u_offset");
+
+        // Load the texture
+        mTextureID = CreateMipMappedTexture2D();
+
+        // Check Anisotropy limits
+        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mMaxAnisotropy);
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+        glDeleteTextures(1, &mTextureID);
+    }
+
+    virtual void draw()
+    {
+        const GLfloat vertices[] =
+        {
+            -0.25f,  0.5f, 0.0f, 5.0f, // Position 0
+             0.0f,  0.0f,              // TexCoord 0
+            -0.25f, -0.5f, 0.0f, 1.0f, // Position 1
+             0.0f,  1.0f,              // TexCoord 1
+             0.25f, -0.5f, 0.0f, 1.0f, // Position 2
+             1.0f,  1.0f,              // TexCoord 2
+             0.25f,  0.5f, 0.0f, 5.0f, // Position 3
+             1.0f,  0.0f               // TexCoord 3
+        };
+        const GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT,  GL_FALSE, 6 * sizeof(GLfloat), vertices);
+        // Load the texture coordinate
+        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), vertices + 4);
+
+        glEnableVertexAttribArray(mPositionLoc);
+        glEnableVertexAttribArray(mTexCoordLoc);
+
+        // Bind the texture
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTextureID);
+
+        // Set the sampler texture unit to 0
+        glUniform1i(mSamplerLoc, 0);
+
+        // Draw quad with nearest sampling
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glUniform1f(mOffsetLoc, -0.6f);
+        glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+        // Draw quad with trilinear filtering
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+        glUniform1f(mOffsetLoc, 0.0f);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+        // Draw quad with anisotropic filtering
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, mMaxAnisotropy);
+        glUniform1f(mOffsetLoc, 0.6f);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mTexCoordLoc;
+
+    // Sampler location
+    GLint mSamplerLoc;
+
+    // Offset location
+    GLint mOffsetLoc;
+
+    // Texture handle
+    GLuint mTextureID;
+
+    float mMaxAnisotropy;
+};
+
+int main(int argc, char **argv)
+{
+    MipMap2DSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/multi_texture/MultiTexture.cpp b/src/third_party/angle/samples/multi_texture/MultiTexture.cpp
new file mode 100644
index 0000000..923203e
--- /dev/null
+++ b/src/third_party/angle/samples/multi_texture/MultiTexture.cpp
@@ -0,0 +1,180 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on MultiTexture.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+
+#include "shader_utils.h"
+#include "system_utils.h"
+#include "tga_utils.h"
+
+class MultiTextureSample : public SampleApplication
+{
+  public:
+    MultiTextureSample()
+        : SampleApplication("MultiTexture", 1280, 720)
+    {
+    }
+
+    GLuint loadTexture(const std::string &path)
+    {
+        TGAImage img;
+        if (!LoadTGAImageFromFile(path, &img))
+        {
+            return 0;
+        }
+
+        return LoadTextureFromTGAImage(img);
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec4 a_position;
+            attribute vec2 a_texCoord;
+            varying vec2 v_texCoord;
+            void main()
+            {
+                gl_Position = a_position;
+                v_texCoord = a_texCoord;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec2 v_texCoord;
+            uniform sampler2D s_baseMap;
+            uniform sampler2D s_lightMap;
+            void main()
+            {
+                vec4 baseColor;
+                vec4 lightColor;
+
+                baseColor = texture2D(s_baseMap, v_texCoord);
+                lightColor = texture2D(s_lightMap, v_texCoord);
+                gl_FragColor = baseColor * (lightColor + 0.25);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+        mTexCoordLoc = glGetAttribLocation(mProgram, "a_texCoord");
+
+        // Get the sampler location
+        mBaseMapLoc = glGetUniformLocation(mProgram, "s_baseMap");
+        mLightMapLoc = glGetUniformLocation(mProgram, "s_lightMap");
+
+        // Load the textures
+        std::stringstream baseStr;
+        baseStr << angle::GetExecutableDirectory() << "/basemap.tga";
+
+        std::stringstream lightStr;
+        lightStr << angle::GetExecutableDirectory() << "/lightmap.tga";
+
+        mBaseMapTexID  = loadTexture(baseStr.str());
+        mLightMapTexID = loadTexture(lightStr.str());
+        if (mBaseMapTexID == 0 || mLightMapTexID == 0)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+        glDeleteTextures(1, &mBaseMapTexID);
+        glDeleteTextures(1, &mLightMapTexID);
+    }
+
+    virtual void draw()
+    {
+        GLfloat vertices[] =
+        {
+            -0.5f,  0.5f, 0.0f,  // Position 0
+             0.0f,  0.0f,        // TexCoord 0
+            -0.5f, -0.5f, 0.0f,  // Position 1
+             0.0f,  1.0f,        // TexCoord 1
+             0.5f, -0.5f, 0.0f,  // Position 2
+             1.0f,  1.0f,        // TexCoord 2
+             0.5f,  0.5f, 0.0f,  // Position 3
+             1.0f,  0.0f         // TexCoord 3
+        };
+        GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices);
+        // Load the texture coordinate
+        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices + 3);
+
+        glEnableVertexAttribArray(mPositionLoc);
+        glEnableVertexAttribArray(mTexCoordLoc);
+
+        // Bind the base map
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mBaseMapTexID);
+
+        // Set the base map sampler to texture unit to 0
+        glUniform1i(mBaseMapLoc, 0);
+
+        // Bind the light map
+        glActiveTexture(GL_TEXTURE1);
+        glBindTexture(GL_TEXTURE_2D, mLightMapTexID);
+
+        // Set the light map sampler to texture unit 1
+        glUniform1i(mLightMapLoc, 1);
+
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mTexCoordLoc;
+
+    // Sampler locations
+    GLint mBaseMapLoc;
+    GLint mLightMapLoc;
+
+    // Texture handle
+    GLuint mBaseMapTexID;
+    GLuint mLightMapTexID;
+};
+
+int main(int argc, char **argv)
+{
+    MultiTextureSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/gles2_book/MultiTexture/basemap.tga b/src/third_party/angle/samples/multi_texture/basemap.tga
similarity index 100%
rename from src/third_party/angle/samples/gles2_book/MultiTexture/basemap.tga
rename to src/third_party/angle/samples/multi_texture/basemap.tga
Binary files differ
diff --git a/src/third_party/angle/samples/gles2_book/MultiTexture/lightmap.tga b/src/third_party/angle/samples/multi_texture/lightmap.tga
similarity index 100%
rename from src/third_party/angle/samples/gles2_book/MultiTexture/lightmap.tga
rename to src/third_party/angle/samples/multi_texture/lightmap.tga
Binary files differ
diff --git a/src/third_party/angle/samples/multi_window/MultiWindow.cpp b/src/third_party/angle/samples/multi_window/MultiWindow.cpp
new file mode 100644
index 0000000..59d6eee
--- /dev/null
+++ b/src/third_party/angle/samples/multi_window/MultiWindow.cpp
@@ -0,0 +1,202 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "SampleApplication.h"
+
+#include <cmath>
+#include <algorithm>
+#include <vector>
+
+#include "Matrix.h"
+#include "random_utils.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+class MultiWindowSample : public SampleApplication
+{
+  public:
+    MultiWindowSample()
+        : SampleApplication("MultiWindow", 256, 256)
+    {
+    }
+
+    bool initialize() override
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec4 vPosition;
+            void main()
+            {
+                gl_Position = vPosition;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            void main()
+            {
+                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Set an initial rotation
+        mRotation = 45.0f;
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        window rootWindow;
+        rootWindow.osWindow = getWindow();
+        rootWindow.surface = getSurface();
+        mWindows.push_back(rootWindow);
+
+        const size_t numWindows = 5;
+        for (size_t i = 1; i < numWindows; i++)
+        {
+            window window;
+
+            window.osWindow = CreateOSWindow();
+            if (!window.osWindow->initialize("MultiWindow", 256, 256))
+            {
+                return false;
+            }
+
+            window.surface = eglCreateWindowSurface(getDisplay(), getConfig(), window.osWindow->getNativeWindow(), nullptr);
+            if (window.surface == EGL_NO_SURFACE)
+            {
+                return false;
+            }
+
+            window.osWindow->setVisible(true);
+
+            mWindows.push_back(window);
+        }
+
+        int baseX = rootWindow.osWindow->getX();
+        int baseY = rootWindow.osWindow->getY();
+        for (auto &window : mWindows)
+        {
+            int x      = baseX + mRNG.randomIntBetween(0, 512);
+            int y      = baseY + mRNG.randomIntBetween(0, 512);
+            int width  = mRNG.randomIntBetween(128, 512);
+            int height = mRNG.randomIntBetween(128, 512);
+            window.osWindow->setPosition(x, y);
+            window.osWindow->resize(width, height);
+        }
+
+        return true;
+    }
+
+    void destroy() override { glDeleteProgram(mProgram); }
+
+    void step(float dt, double totalTime) override
+    {
+        mRotation = fmod(mRotation + (dt * 40.0f), 360.0f);
+
+        for (auto &window : mWindows)
+        {
+            window.osWindow->messageLoop();
+        }
+    }
+
+    void draw() override
+    {
+        OSWindow* rootWindow = mWindows[0].osWindow;
+        int left = rootWindow->getX();
+        int right = rootWindow->getX() + rootWindow->getWidth();
+        int top = rootWindow->getY();
+        int bottom = rootWindow->getY() + rootWindow->getHeight();
+
+        for (auto &windowRecord : mWindows)
+        {
+            OSWindow *window = windowRecord.osWindow;
+            left = std::min(left, window->getX());
+            right = std::max(right, window->getX() + window->getWidth());
+            top = std::min(top, window->getY());
+            bottom = std::max(bottom, window->getY() + window->getHeight());
+        }
+
+        float midX = (left + right) * 0.5f;
+        float midY = (top + bottom) * 0.5f;
+
+        Matrix4 modelMatrix = Matrix4::translate(Vector3(midX, midY, 0.0f)) *
+                              Matrix4::rotate(mRotation, Vector3(0.0f, 0.0f, 1.0f)) *
+                              Matrix4::translate(Vector3(-midX, -midY, 0.0f));
+        Matrix4 viewMatrix = Matrix4::identity();
+
+        for (auto &windowRecord : mWindows)
+        {
+            OSWindow *window   = windowRecord.osWindow;
+            EGLSurface surface = windowRecord.surface;
+
+            eglMakeCurrent(getDisplay(), surface, surface, getContext());
+
+            Matrix4 orthoMatrix = Matrix4::ortho(static_cast<float>(window->getX()), static_cast<float>(window->getX() + window->getWidth()),
+                                                 static_cast<float>(window->getY() + window->getHeight()), static_cast<float>(window->getY()),
+                                                 0.0f, 1.0f);
+            Matrix4 mvpMatrix = orthoMatrix * viewMatrix * modelMatrix;
+
+            Vector3 vertices[] =
+            {
+                Matrix4::transform(mvpMatrix, Vector4(midX, static_cast<float>(top), 0.0f, 1.0f)),
+                Matrix4::transform(mvpMatrix, Vector4(static_cast<float>(left), static_cast<float>(bottom), 0.0f, 1.0f)),
+                Matrix4::transform(mvpMatrix, Vector4(static_cast<float>(right), static_cast<float>(bottom), 0.0f, 1.0f)),
+            };
+
+            // Set the viewport
+            glViewport(0, 0, window->getWidth(), window->getHeight());
+
+            // Clear the color buffer
+            glClear(GL_COLOR_BUFFER_BIT);
+
+            // Use the program object
+            glUseProgram(mProgram);
+
+            // Load the vertex data
+            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices[0].data());
+            glEnableVertexAttribArray(0);
+
+            glDrawArrays(GL_TRIANGLES, 0, 3);
+
+            eglSwapBuffers(getDisplay(), surface);
+        }
+    }
+
+    // Override swap to do nothing as we already swapped the root
+    // window in draw() and swapping another time would invalidate
+    // the content of the default framebuffer.
+    void swap() override {}
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Current rotation
+    float mRotation;
+
+    // Window and surface data
+    struct window
+    {
+        OSWindow* osWindow;
+        EGLSurface surface;
+    };
+    std::vector<window> mWindows;
+
+    RNG mRNG;
+};
+
+int main(int argc, char **argv)
+{
+    MultiWindowSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/multiple_draw_buffers/MultipleDrawBuffers.cpp b/src/third_party/angle/samples/multiple_draw_buffers/MultipleDrawBuffers.cpp
new file mode 100644
index 0000000..a31e466
--- /dev/null
+++ b/src/third_party/angle/samples/multiple_draw_buffers/MultipleDrawBuffers.cpp
@@ -0,0 +1,226 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Simple_Texture2D.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+#include "system_utils.h"
+#include "texture_utils.h"
+
+#include <cstring>
+#include <iostream>
+
+class MultipleDrawBuffersSample : public SampleApplication
+{
+  public:
+    MultipleDrawBuffersSample()
+        : SampleApplication("MultipleDrawBuffers", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        // Check EXT_draw_buffers is supported
+        char *extensionString = (char*)glGetString(GL_EXTENSIONS);
+        if (strstr(extensionString, "GL_EXT_draw_buffers") != nullptr)
+        {
+            // Retrieve the address of glDrawBuffersEXT from EGL
+            mDrawBuffers = (PFNGLDRAWBUFFERSEXTPROC)eglGetProcAddress("glDrawBuffersEXT");
+        }
+        else
+        {
+            mDrawBuffers = glDrawBuffers;
+        }
+
+        if (!mDrawBuffers)
+        {
+            std::cerr << "Unable to load glDrawBuffers[EXT] entry point.";
+            return false;
+        }
+
+        std::stringstream vsStream;
+        vsStream << angle::GetExecutableDirectory() << "/multiple_draw_buffers_vs.glsl";
+
+        std::stringstream fsStream;
+        fsStream << angle::GetExecutableDirectory() << "/multiple_draw_buffers_fs.glsl";
+
+        std::stringstream copyFsStream;
+        fsStream << angle::GetExecutableDirectory() << "/multiple_draw_buffers_copy_fs.glsl";
+
+        mMRTProgram = CompileProgramFromFiles(vsStream.str(), fsStream.str());
+        if (!mMRTProgram)
+        {
+            return false;
+        }
+
+        mCopyProgram = CompileProgramFromFiles(vsStream.str(), copyFsStream.str());
+        if (!mCopyProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mCopyProgram, "a_position");
+        mTexCoordLoc = glGetAttribLocation(mCopyProgram, "a_texCoord");
+
+        // Get the sampler location
+        mSamplerLoc = glGetUniformLocation(mCopyProgram, "s_texture");
+
+        // Load the texture
+        mTexture = CreateSimpleTexture2D();
+
+        // Initialize the user framebuffer
+        glGenFramebuffers(1, &mFramebuffer);
+        glGenTextures(mFramebufferAttachmentCount, mFramebufferTextures);
+
+        glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+        for (size_t i = 0; i < mFramebufferAttachmentCount; i++)
+        {
+            // Create textures for the four color attachments
+            glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[i]);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindow()->getWidth(),
+                         getWindow()->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            glFramebufferTexture2D(GL_FRAMEBUFFER,
+                                   static_cast<GLenum>(GL_COLOR_ATTACHMENT0_EXT + i), GL_TEXTURE_2D,
+                                   mFramebufferTextures[i], 0);
+        }
+
+        glBindTexture(GL_TEXTURE_2D, 0);
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mCopyProgram);
+        glDeleteProgram(mMRTProgram);
+        glDeleteTextures(1, &mTexture);
+        glDeleteTextures(mFramebufferAttachmentCount, mFramebufferTextures);
+        glDeleteFramebuffers(1, &mFramebuffer);
+    }
+
+    virtual void draw()
+    {
+        GLfloat vertices[] =
+        {
+            -0.8f,  0.8f, 0.0f,  // Position 0
+             0.0f,  0.0f,        // TexCoord 0
+            -0.8f, -0.8f, 0.0f,  // Position 1
+             0.0f,  1.0f,        // TexCoord 1
+             0.8f, -0.8f, 0.0f,  // Position 2
+             1.0f,  1.0f,        // TexCoord 2
+             0.8f,  0.8f, 0.0f,  // Position 3
+             1.0f,  0.0f         // TexCoord 3
+        };
+        GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+        GLenum drawBuffers[mFramebufferAttachmentCount] =
+        {
+            GL_COLOR_ATTACHMENT0_EXT,
+            GL_COLOR_ATTACHMENT1_EXT,
+            GL_COLOR_ATTACHMENT2_EXT,
+            GL_COLOR_ATTACHMENT3_EXT
+        };
+
+        // Enable drawing to the four color attachments of the user framebuffer
+        glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+        mDrawBuffers(mFramebufferAttachmentCount, drawBuffers);
+
+        // Set the viewport
+        GLint width  = static_cast<GLint>(getWindow()->getWidth());
+        GLint height = static_cast<GLint>(getWindow()->getHeight());
+        glViewport(0, 0, width, height);
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mMRTProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices);
+        glEnableVertexAttribArray(mPositionLoc);
+
+        // Load the texture coordinate
+        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices + 3);
+        glEnableVertexAttribArray(mTexCoordLoc);
+
+        // Bind the texture
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+
+        // Set the sampler texture unit to 0
+        glUniform1i(mSamplerLoc, 0);
+
+        // Draw the textured quad to the four render targets
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+        // Enable the default framebuffer and single textured drawing
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glUseProgram(mCopyProgram);
+
+        // Draw the four textured quads to a separate region in the viewport
+        glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[0]);
+        glViewport(0, 0, width / 2, height / 2);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+        glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[1]);
+        glViewport(width / 2, 0, width / 2, height / 2);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+        glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[2]);
+        glViewport(0, height / 2, width / 2, height / 2);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+        glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[3]);
+        glViewport(width / 2, height / 2, width / 2, height / 2);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mMRTProgram;
+    GLuint mCopyProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mTexCoordLoc;
+
+    // Sampler location
+    GLint mSamplerLoc;
+
+    // Texture handle
+    GLuint mTexture;
+
+    // Framebuffer object handle
+    GLuint mFramebuffer;
+
+    // Framebuffer color attachments
+    static const size_t mFramebufferAttachmentCount = 4;
+    GLuint mFramebufferTextures[mFramebufferAttachmentCount];
+
+    // Loaded draw buffer entry points
+    PFNGLDRAWBUFFERSEXTPROC mDrawBuffers;
+};
+
+int main(int argc, char **argv)
+{
+    MultipleDrawBuffersSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/multiple_draw_buffers/multiple_draw_buffers_copy_fs.glsl b/src/third_party/angle/samples/multiple_draw_buffers/multiple_draw_buffers_copy_fs.glsl
new file mode 100644
index 0000000..59deb61
--- /dev/null
+++ b/src/third_party/angle/samples/multiple_draw_buffers/multiple_draw_buffers_copy_fs.glsl
@@ -0,0 +1,8 @@
+precision mediump float;
+varying vec2 v_texCoord;
+uniform sampler2D s_texture;
+void main()
+{
+    vec4 color = texture2D(s_texture, v_texCoord);
+    gl_FragColor = color;
+}
diff --git a/src/third_party/angle/samples/multiple_draw_buffers/multiple_draw_buffers_fs.glsl b/src/third_party/angle/samples/multiple_draw_buffers/multiple_draw_buffers_fs.glsl
new file mode 100644
index 0000000..d0143d5
--- /dev/null
+++ b/src/third_party/angle/samples/multiple_draw_buffers/multiple_draw_buffers_fs.glsl
@@ -0,0 +1,12 @@
+#extension GL_EXT_draw_buffers : enable
+precision mediump float;
+varying vec2 v_texCoord;
+uniform sampler2D s_texture;
+void main()
+{
+    vec4 color = texture2D(s_texture, v_texCoord);
+    gl_FragData[0] = color;
+    gl_FragData[1] = vec4(1.0, 1.0, 1.0, 1.0) - color.brga;
+    gl_FragData[2] = vec4(0.2, 1.0, 0.5, 1.0) * color.gbra;
+    gl_FragData[3] = color.rrra;
+}
diff --git a/src/third_party/angle/samples/multiple_draw_buffers/multiple_draw_buffers_vs.glsl b/src/third_party/angle/samples/multiple_draw_buffers/multiple_draw_buffers_vs.glsl
new file mode 100644
index 0000000..0978752
--- /dev/null
+++ b/src/third_party/angle/samples/multiple_draw_buffers/multiple_draw_buffers_vs.glsl
@@ -0,0 +1,8 @@
+attribute vec4 a_position;
+attribute vec2 a_texCoord;
+varying vec2 v_texCoord;
+void main()
+{
+    gl_Position = a_position;
+    v_texCoord = a_texCoord;
+}
diff --git a/src/third_party/angle/samples/particle_system/ParticleSystem.cpp b/src/third_party/angle/samples/particle_system/ParticleSystem.cpp
new file mode 100644
index 0000000..2a2b024
--- /dev/null
+++ b/src/third_party/angle/samples/particle_system/ParticleSystem.cpp
@@ -0,0 +1,233 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on ParticleSystem.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+
+#include "common/vector_utils.h"
+#include "shader_utils.h"
+#include "random_utils.h"
+#include "system_utils.h"
+#include "tga_utils.h"
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+using namespace angle;
+
+class ParticleSystemSample : public SampleApplication
+{
+  public:
+    ParticleSystemSample()
+        : SampleApplication("ParticleSystem", 1280, 720)
+    {
+    }
+
+    bool initialize() override
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            uniform float u_time;
+            uniform vec3 u_centerPosition;
+            attribute float a_lifetime;
+            attribute vec3 a_startPosition;
+            attribute vec3 a_endPosition;
+            varying float v_lifetime;
+            void main()
+            {
+                if (u_time <= a_lifetime)
+                {
+                    gl_Position.xyz = a_startPosition + (u_time * a_endPosition);
+                    gl_Position.xyz += u_centerPosition;
+                    gl_Position.w = 1.0;
+                }
+                else
+                {
+                    gl_Position = vec4(-1000, -1000, 0, 0);
+                }
+                v_lifetime = 1.0 - (u_time / a_lifetime);
+                v_lifetime = clamp(v_lifetime, 0.0, 1.0);
+                gl_PointSize = (v_lifetime * v_lifetime) * 40.0;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            uniform vec4 u_color;
+            varying float v_lifetime;
+            uniform sampler2D s_texture;
+            void main()
+            {
+                vec4 texColor;
+                texColor = texture2D(s_texture, gl_PointCoord);
+                gl_FragColor = vec4(u_color) * texColor;
+                gl_FragColor.a *= v_lifetime;
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mLifetimeLoc = glGetAttribLocation(mProgram, "a_lifetime");
+        mStartPositionLoc = glGetAttribLocation(mProgram, "a_startPosition");
+        mEndPositionLoc = glGetAttribLocation(mProgram, "a_endPosition");
+
+        // Get the uniform locations
+        mTimeLoc = glGetUniformLocation(mProgram, "u_time");
+        mCenterPositionLoc = glGetUniformLocation(mProgram, "u_centerPosition");
+        mColorLoc = glGetUniformLocation(mProgram, "u_color");
+        mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        // Fill in particle data array
+        for (size_t i = 0; i < mParticleCount; i++)
+        {
+            mParticles[i].lifetime = mRNG.randomFloatBetween(0.0f, 1.0f);
+
+            float endAngle                = mRNG.randomFloatBetween(0, 2.0f * float(M_PI));
+            float endRadius               = mRNG.randomFloatBetween(0.0f, 2.0f);
+            mParticles[i].endPosition.x() = sinf(endAngle) * endRadius;
+            mParticles[i].endPosition.y() = cosf(endAngle) * endRadius;
+            mParticles[i].endPosition.z() = 0.0f;
+
+            float startAngle                = mRNG.randomFloatBetween(0, 2.0f * float(M_PI));
+            float startRadius               = mRNG.randomFloatBetween(0.0f, 0.25f);
+            mParticles[i].startPosition.x() = sinf(startAngle) * startRadius;
+            mParticles[i].startPosition.y() = cosf(startAngle) * startRadius;
+            mParticles[i].startPosition.z() = 0.0f;
+        }
+
+        mParticleTime = 1.0f;
+
+        std::stringstream smokeStr;
+        smokeStr << angle::GetExecutableDirectory() << "/smoke.tga";
+
+        TGAImage img;
+        if (!LoadTGAImageFromFile(smokeStr.str(), &img))
+        {
+            return false;
+        }
+        mTextureID = LoadTextureFromTGAImage(img);
+        if (!mTextureID)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    void destroy() override { glDeleteProgram(mProgram); }
+
+    void step(float dt, double totalTime) override
+    {
+        // Use the program object
+        glUseProgram(mProgram);
+
+        mParticleTime += dt;
+        if (mParticleTime >= 1.0f)
+        {
+            mParticleTime = 0.0f;
+
+            // Pick a new start location and color
+            Vector3 centerPos(mRNG.randomFloatBetween(-0.5f, 0.5f),
+                              mRNG.randomFloatBetween(-0.5f, 0.5f),
+                              mRNG.randomFloatBetween(-0.5f, 0.5f));
+            glUniform3fv(mCenterPositionLoc, 1, centerPos.data());
+
+            // Random color
+            Vector4 color(mRNG.randomFloatBetween(0.0f, 1.0f), mRNG.randomFloatBetween(0.0f, 1.0f),
+                          mRNG.randomFloatBetween(0.0f, 1.0f), 0.5f);
+            glUniform4fv(mColorLoc, 1, color.data());
+        }
+
+        // Load uniform time variable
+        glUniform1f(mTimeLoc, mParticleTime);
+    }
+
+    void draw() override
+    {
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex attributes
+        glVertexAttribPointer(mLifetimeLoc, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), &mParticles[0].lifetime);
+        glVertexAttribPointer(mEndPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), &mParticles[0].endPosition);
+        glVertexAttribPointer(mStartPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), &mParticles[0].startPosition);
+
+        glEnableVertexAttribArray(mLifetimeLoc);
+        glEnableVertexAttribArray(mEndPositionLoc);
+        glEnableVertexAttribArray(mStartPositionLoc);
+
+        // Blend particles
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+
+        // Bind the texture
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTextureID);
+
+        // Set the sampler texture unit to 0
+        glUniform1i(mSamplerLoc, 0);
+
+        glDrawArrays(GL_POINTS, 0, mParticleCount);
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mLifetimeLoc;
+    GLint mStartPositionLoc;
+    GLint mEndPositionLoc;
+
+    // Uniform location
+    GLint mTimeLoc;
+    GLint mColorLoc;
+    GLint mCenterPositionLoc;
+    GLint mSamplerLoc;
+
+    // Texture handle
+    GLuint mTextureID;
+
+    // Particle vertex data
+    struct Particle
+    {
+        float lifetime;
+        Vector3 startPosition;
+        Vector3 endPosition;
+    };
+    static const size_t mParticleCount = 1024;
+    std::array<Particle, mParticleCount> mParticles;
+    float mParticleTime;
+    RNG mRNG;
+};
+
+int main(int argc, char **argv)
+{
+    ParticleSystemSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/gles2_book/ParticleSystem/smoke.tga b/src/third_party/angle/samples/particle_system/smoke.tga
similarity index 100%
rename from src/third_party/angle/samples/gles2_book/ParticleSystem/smoke.tga
rename to src/third_party/angle/samples/particle_system/smoke.tga
Binary files differ
diff --git a/src/third_party/angle/samples/post_sub_buffer/PostSubBuffer.cpp b/src/third_party/angle/samples/post_sub_buffer/PostSubBuffer.cpp
new file mode 100644
index 0000000..22bcaac
--- /dev/null
+++ b/src/third_party/angle/samples/post_sub_buffer/PostSubBuffer.cpp
@@ -0,0 +1,178 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Simple_VertexShader.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+#include "texture_utils.h"
+#include "geometry_utils.h"
+#include "Matrix.h"
+
+#include <cmath>
+#include <iostream>
+
+class PostSubBufferSample : public SampleApplication
+{
+  public:
+    PostSubBufferSample()
+        : SampleApplication("PostSubBuffer", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        mPostSubBufferNV = (PFNEGLPOSTSUBBUFFERNVPROC)eglGetProcAddress("eglPostSubBufferNV");
+        if (!mPostSubBufferNV)
+        {
+            std::cerr << "Could not load eglPostSubBufferNV.";
+            return false;
+        }
+
+        const std::string vs = SHADER_SOURCE
+        (
+            uniform mat4 u_mvpMatrix;
+            attribute vec4 a_position;
+            attribute vec2 a_texcoord;
+            varying vec2 v_texcoord;
+            void main()
+            {
+                gl_Position = u_mvpMatrix * a_position;
+                v_texcoord = a_texcoord;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec2 v_texcoord;
+            void main()
+            {
+                gl_FragColor = vec4(v_texcoord.x, v_texcoord.y, 1.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+        mTexcoordLoc = glGetAttribLocation(mProgram, "a_texcoord");
+
+        // Get the uniform locations
+        mMVPMatrixLoc = glGetUniformLocation(mProgram, "u_mvpMatrix");
+
+        // Generate the geometry data
+        GenerateCubeGeometry(0.5f, &mCube);
+
+        // Set an initial rotation
+        mRotation = 45.0f;
+
+        // Clear the whole window surface to blue.
+        glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        SampleApplication::swap();
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glCullFace(GL_BACK);
+        glEnable(GL_CULL_FACE);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+    }
+
+    virtual void step(float dt, double totalTime)
+    {
+        mRotation = fmod(mRotation + (dt * 40.0f), 360.0f);
+
+        Matrix4 perspectiveMatrix = Matrix4::perspective(60.0f, float(getWindow()->getWidth()) / getWindow()->getHeight(),
+                                                         1.0f, 20.0f);
+
+        Matrix4 modelMatrix = Matrix4::translate(angle::Vector3(0.0f, 0.0f, -2.0f)) *
+                              Matrix4::rotate(mRotation, angle::Vector3(1.0f, 0.0f, 1.0f));
+
+        Matrix4 viewMatrix = Matrix4::identity();
+
+        Matrix4 mvpMatrix = perspectiveMatrix * viewMatrix * modelMatrix;
+
+        // Load the matrices
+        glUniformMatrix4fv(mMVPMatrixLoc, 1, GL_FALSE, mvpMatrix.data);
+    }
+
+    virtual void draw()
+    {
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, mCube.positions.data());
+        glEnableVertexAttribArray(mPositionLoc);
+
+        // Load the texcoord data
+        glVertexAttribPointer(mTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, mCube.texcoords.data());
+        glEnableVertexAttribArray(mTexcoordLoc);
+
+        // Draw the cube
+        glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mCube.indices.size()), GL_UNSIGNED_SHORT,
+                       mCube.indices.data());
+    }
+
+    virtual void swap()
+    {
+        // Instead of letting the application call eglSwapBuffers, call eglPostSubBufferNV here instead
+        EGLint windowWidth  = static_cast<EGLint>(getWindow()->getWidth());
+        EGLint windowHeight = static_cast<EGLint>(getWindow()->getHeight());
+        EGLDisplay display = getDisplay();
+        EGLSurface surface = getSurface();
+        mPostSubBufferNV(display, surface, 60, 60, windowWidth - 120, windowHeight - 120);
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mTexcoordLoc;
+
+    // Uniform locations
+    GLuint mMVPMatrixLoc;
+
+    // Current rotation
+    float mRotation;
+
+    // Geometry data
+    CubeGeometry mCube;
+
+    // eglPostSubBufferNV entry point
+    PFNEGLPOSTSUBBUFFERNVPROC mPostSubBufferNV;
+};
+
+int main(int argc, char **argv)
+{
+    PostSubBufferSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/sample_util/SampleApplication.cpp b/src/third_party/angle/samples/sample_util/SampleApplication.cpp
new file mode 100644
index 0000000..0ecb11c
--- /dev/null
+++ b/src/third_party/angle/samples/sample_util/SampleApplication.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "SampleApplication.h"
+#include "EGLWindow.h"
+#include "random_utils.h"
+
+SampleApplication::SampleApplication(const std::string &name,
+                                     size_t width,
+                                     size_t height,
+                                     EGLint glesMajorVersion,
+                                     EGLint glesMinorVersion,
+                                     EGLint requestedRenderer)
+    : mName(name), mWidth(width), mHeight(height), mRunning(false)
+{
+    mEGLWindow.reset(new EGLWindow(glesMajorVersion, glesMinorVersion,
+                                   EGLPlatformParameters(requestedRenderer)));
+    mTimer.reset(CreateTimer());
+    mOSWindow.reset(CreateOSWindow());
+
+    mEGLWindow->setConfigRedBits(8);
+    mEGLWindow->setConfigGreenBits(8);
+    mEGLWindow->setConfigBlueBits(8);
+    mEGLWindow->setConfigAlphaBits(8);
+    mEGLWindow->setConfigDepthBits(24);
+    mEGLWindow->setConfigStencilBits(8);
+
+    // Disable vsync
+    mEGLWindow->setSwapInterval(0);
+}
+
+SampleApplication::~SampleApplication()
+{
+}
+
+bool SampleApplication::initialize()
+{
+    return true;
+}
+
+void SampleApplication::destroy()
+{
+}
+
+void SampleApplication::step(float dt, double totalTime)
+{
+}
+
+void SampleApplication::draw()
+{
+}
+
+void SampleApplication::swap()
+{
+    mEGLWindow->swap();
+}
+
+OSWindow *SampleApplication::getWindow() const
+{
+    return mOSWindow.get();
+}
+
+EGLConfig SampleApplication::getConfig() const
+{
+    return mEGLWindow->getConfig();
+}
+
+EGLDisplay SampleApplication::getDisplay() const
+{
+    return mEGLWindow->getDisplay();
+}
+
+EGLSurface SampleApplication::getSurface() const
+{
+    return mEGLWindow->getSurface();
+}
+
+EGLContext SampleApplication::getContext() const
+{
+    return mEGLWindow->getContext();
+}
+
+int SampleApplication::run()
+{
+    if (!mOSWindow->initialize(mName, mWidth, mHeight))
+    {
+        return -1;
+    }
+
+    mOSWindow->setVisible(true);
+
+    if (!mEGLWindow->initializeGL(mOSWindow.get()))
+    {
+        return -1;
+    }
+
+    mRunning = true;
+    int result = 0;
+
+    if (!initialize())
+    {
+        mRunning = false;
+        result = -1;
+    }
+
+    mTimer->start();
+    double prevTime = 0.0;
+
+    while (mRunning)
+    {
+        double elapsedTime = mTimer->getElapsedTime();
+        double deltaTime = elapsedTime - prevTime;
+
+        step(static_cast<float>(deltaTime), elapsedTime);
+
+        // Clear events that the application did not process from this frame
+        Event event;
+        while (popEvent(&event))
+        {
+            // If the application did not catch a close event, close now
+            if (event.Type == Event::EVENT_CLOSED)
+            {
+                exit();
+            }
+        }
+
+        if (!mRunning)
+        {
+            break;
+        }
+
+        draw();
+        swap();
+
+        mOSWindow->messageLoop();
+
+        prevTime = elapsedTime;
+    }
+
+    destroy();
+    mEGLWindow->destroyGL();
+    mOSWindow->destroy();
+
+    return result;
+}
+
+void SampleApplication::exit()
+{
+    mRunning = false;
+}
+
+bool SampleApplication::popEvent(Event *event)
+{
+    return mOSWindow->popEvent(event);
+}
diff --git a/src/third_party/angle/samples/sample_util/SampleApplication.h b/src/third_party/angle/samples/sample_util/SampleApplication.h
new file mode 100644
index 0000000..174848d
--- /dev/null
+++ b/src/third_party/angle/samples/sample_util/SampleApplication.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef SAMPLE_UTIL_SAMPLE_APPLICATION_H
+#define SAMPLE_UTIL_SAMPLE_APPLICATION_H
+
+#include <list>
+#include <memory>
+#include <stdint.h>
+#include <string>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "OSWindow.h"
+#include "Timer.h"
+
+class EGLWindow;
+
+class SampleApplication
+{
+  public:
+    SampleApplication(const std::string &name,
+                      size_t width,
+                      size_t height,
+                      EGLint glesMajorVersion  = 2,
+                      EGLint glesMinorVersion  = 0,
+                      EGLint requestedRenderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+    virtual ~SampleApplication();
+
+    virtual bool initialize();
+    virtual void destroy();
+
+    virtual void step(float dt, double totalTime);
+    virtual void draw();
+
+    virtual void swap();
+
+    OSWindow *getWindow() const;
+    EGLConfig getConfig() const;
+    EGLDisplay getDisplay() const;
+    EGLSurface getSurface() const;
+    EGLContext getContext() const;
+
+    bool popEvent(Event *event);
+
+    int run();
+    void exit();
+
+  private:
+    std::string mName;
+    size_t mWidth;
+    size_t mHeight;
+    bool mRunning;
+
+    std::unique_ptr<Timer> mTimer;
+    std::unique_ptr<EGLWindow> mEGLWindow;
+    std::unique_ptr<OSWindow> mOSWindow;
+};
+
+#endif // SAMPLE_UTIL_SAMPLE_APPLICATION_H
diff --git a/src/third_party/angle/samples/sample_util/texture_utils.cpp b/src/third_party/angle/samples/sample_util/texture_utils.cpp
new file mode 100644
index 0000000..24cc66b
--- /dev/null
+++ b/src/third_party/angle/samples/sample_util/texture_utils.cpp
@@ -0,0 +1,130 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "texture_utils.h"
+#include <array>
+
+GLuint CreateSimpleTexture2D()
+{
+    // Use tightly packed data
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+    // Generate a texture object
+    GLuint texture;
+    glGenTextures(1, &texture);
+
+    // Bind the texture object
+    glBindTexture(GL_TEXTURE_2D, texture);
+
+    // Load the texture: 2x2 Image, 3 bytes per pixel (R, G, B)
+    const size_t width = 2;
+    const size_t height = 2;
+    GLubyte pixels[width * height * 3] =
+    {
+        255,   0,   0, // Red
+          0, 255,   0, // Green
+          0,   0, 255, // Blue
+        255, 255,   0, // Yellow
+    };
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+
+    // Set the filtering mode
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    return texture;
+}
+
+GLuint CreateSimpleTextureCubemap()
+{
+    // Generate a texture object
+    GLuint texture;
+    glGenTextures(1, &texture);
+
+    // Bind the texture object
+    glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
+
+    // Load the texture faces
+    GLubyte pixels[6][3] =
+    {
+        // Face 0 - Red
+        { 255, 0, 0 },
+        // Face 1 - Green,
+        { 0, 255, 0 },
+        // Face 3 - Blue
+        { 0, 0, 255 },
+        // Face 4 - Yellow
+        { 255, 255, 0 },
+        // Face 5 - Purple
+        { 255, 0, 255 },
+        // Face 6 - White
+        { 255, 255, 255 }
+    };
+
+    for (size_t i = 0; i < 6; i++)
+    {
+        glTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i), 0, GL_RGB, 1, 1, 0,
+                     GL_RGB, GL_UNSIGNED_BYTE, &pixels[i]);
+    }
+
+    // Set the filtering mode
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    return texture;
+}
+
+GLuint CreateMipMappedTexture2D()
+{
+    // Texture object handle
+    const size_t width = 256;
+    const size_t height = 256;
+    std::array<GLubyte, width * height * 3> pixels;
+
+    const size_t checkerSize = 8;
+    for (size_t y = 0; y < height; y++)
+    {
+        for (size_t x = 0; x < width; x++)
+        {
+            GLubyte rColor = 0;
+            GLubyte bColor = 0;
+
+            if ((x / checkerSize) % 2 == 0)
+            {
+                rColor = 255 * ((y / checkerSize) % 2);
+                bColor = 255 * (1 - ((y / checkerSize) % 2));
+            }
+            else
+            {
+                bColor = 255 * ((y / checkerSize) % 2);
+                rColor = 255 * (1 - ((y / checkerSize) % 2));
+            }
+
+            pixels[(y * height + x) * 3] = rColor;
+            pixels[(y * height + x) * 3 + 1] = 0;
+            pixels[(y * height + x) * 3 + 2] = bColor;
+        }
+    }
+
+    // Generate a texture object
+    GLuint texture;
+    glGenTextures(1, &texture);
+
+    // Bind the texture object
+    glBindTexture(GL_TEXTURE_2D, texture);
+
+    // Load mipmap level 0
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
+
+    // Generate mipmaps
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    // Set the filtering mode
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    return texture;
+}
diff --git a/src/third_party/angle/samples/sample_util/texture_utils.h b/src/third_party/angle/samples/sample_util/texture_utils.h
new file mode 100644
index 0000000..6ddeb5c
--- /dev/null
+++ b/src/third_party/angle/samples/sample_util/texture_utils.h
@@ -0,0 +1,17 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef SAMPLE_UTIL_TEXTURE_UTILS_H
+#define SAMPLE_UTIL_TEXTURE_UTILS_H
+
+#include <GLES2/gl2.h>
+
+GLuint CreateSimpleTexture2D();
+GLuint CreateSimpleTextureCubemap();
+
+GLuint CreateMipMappedTexture2D();
+
+#endif // SAMPLE_UTIL_TEXTURE_UTILS_H
diff --git a/src/third_party/angle/samples/sample_util/tga_utils.cpp b/src/third_party/angle/samples/sample_util/tga_utils.cpp
new file mode 100644
index 0000000..41a6d24
--- /dev/null
+++ b/src/third_party/angle/samples/sample_util/tga_utils.cpp
@@ -0,0 +1,123 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "tga_utils.h"
+
+#include <fstream>
+#include <iostream>
+#include <limits.h>
+#include <stdint.h>
+#include <string>
+
+TGAImage::TGAImage()
+    : width(0), height(0), data(0)
+{
+}
+
+struct TGAHeader
+{
+    uint8_t idSize;
+    uint8_t mapType;
+    uint8_t imageType;
+    uint16_t paletteStart;
+    uint16_t paletteSize;
+    uint8_t paletteEntryDepth;
+    uint16_t x;
+    uint16_t y;
+    uint16_t width;
+    uint16_t height;
+    uint8_t colorDepth;
+    uint8_t descriptor;
+};
+
+#define INVERTED_BIT (1 << 5)
+
+template <typename dataType>
+void readBinary(std::ifstream &stream, dataType &item)
+{
+    stream.read(reinterpret_cast<char *>(&item), sizeof(dataType));
+}
+
+template <typename dataType>
+void readBinary(std::ifstream &stream, std::vector<dataType> &items)
+{
+    stream.read(reinterpret_cast<char *>(items.data()), sizeof(dataType) * items.size());
+}
+
+bool LoadTGAImageFromFile(const std::string &path, TGAImage *image)
+{
+    std::ifstream stream(path, std::ios::binary);
+    if (!stream)
+    {
+        std::cerr << "error opening tga file " << path << " for reading.\n";
+        return false;
+    }
+
+    TGAHeader header;
+    readBinary(stream, header.idSize);
+    readBinary(stream, header.mapType);
+    readBinary(stream, header.imageType);
+    readBinary(stream, header.paletteStart);
+    readBinary(stream, header.paletteSize);
+    readBinary(stream, header.paletteEntryDepth);
+    readBinary(stream, header.x);
+    readBinary(stream, header.y);
+    readBinary(stream, header.width);
+    readBinary(stream, header.height);
+    readBinary(stream, header.colorDepth);
+    readBinary(stream, header.descriptor);
+
+    image->width = header.width;
+    image->height = header.height;
+
+    size_t pixelComponentCount = header.colorDepth / CHAR_BIT;
+    std::vector<unsigned char> buffer(header.width * header.height * pixelComponentCount);
+    readBinary(stream, buffer);
+
+    image->data.reserve(header.width * header.height);
+
+    for (size_t y = 0; y < header.height; y++)
+    {
+        size_t rowIdx = ((header.descriptor & INVERTED_BIT) ? (header.height - 1 - y) : y) * header.width * pixelComponentCount;
+        for (size_t x = 0; x < header.width; x++)
+        {
+            size_t pixelIdx = rowIdx + x * pixelComponentCount;
+
+            Byte4 pixel;
+            pixel[0] = (pixelComponentCount > 2) ? buffer[pixelIdx + 2] : 0;
+            pixel[2] = (pixelComponentCount > 0) ? buffer[pixelIdx + 0] : 0;
+            pixel[1] = (pixelComponentCount > 1) ? buffer[pixelIdx + 1] : 0;
+            pixel[3] = (pixelComponentCount > 3) ? buffer[pixelIdx + 3] : 255;
+
+            image->data.push_back(pixel);
+        }
+    }
+
+    std::cout << "loaded image " << path << ".\n";
+
+    return true;
+}
+
+GLuint LoadTextureFromTGAImage(const TGAImage &image)
+{
+    if (image.width > 0 && image.height > 0)
+    {
+        GLuint texture;
+        glGenTextures(1, &texture);
+        glBindTexture(GL_TEXTURE_2D, texture);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(image.width), static_cast<GLsizei>(image.height), 0,
+                     GL_RGBA, GL_UNSIGNED_BYTE, image.data.data());
+        glGenerateMipmap(GL_TEXTURE_2D);
+        return texture;
+    }
+    else
+    {
+        return 0;
+    }
+}
diff --git a/src/third_party/angle/samples/sample_util/tga_utils.h b/src/third_party/angle/samples/sample_util/tga_utils.h
new file mode 100644
index 0000000..3dd27ad
--- /dev/null
+++ b/src/third_party/angle/samples/sample_util/tga_utils.h
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef SAMPLE_UTIL_TGA_UTILS_HPP
+#define SAMPLE_UTIL_TGA_UTILS_HPP
+
+#include <array>
+#include <vector>
+
+#include <GLES2/gl2.h>
+
+typedef std::array<unsigned char, 4> Byte4;
+
+struct TGAImage
+{
+    size_t width;
+    size_t height;
+    std::vector<Byte4> data;
+
+    TGAImage();
+};
+
+bool LoadTGAImageFromFile(const std::string &path, TGAImage *image);
+GLuint LoadTextureFromTGAImage(const TGAImage &image);
+
+#endif // SAMPLE_UTIL_TGA_UTILS_HPP
diff --git a/src/third_party/angle/samples/samples.gyp b/src/third_party/angle/samples/samples.gyp
new file mode 100644
index 0000000..b5c30b9
--- /dev/null
+++ b/src/third_party/angle/samples/samples.gyp
@@ -0,0 +1,224 @@
+# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'targets':
+    [
+        {
+            'target_name': 'shader_translator',
+            'type': 'executable',
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'dependencies': [ '../src/angle.gyp:translator', ],
+            'include_dirs': [ '../include', ],
+            'sources': [ 'shader_translator/shader_translator.cpp' ],
+        },
+        {
+            'target_name': 'sample_util',
+            'type': 'static_library',
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'dependencies':
+            [
+                '<(angle_path)/src/angle.gyp:angle_common',
+                '<(angle_path)/src/angle.gyp:libEGL',
+                '<(angle_path)/src/angle.gyp:libGLESv2',
+                '<(angle_path)/util/util.gyp:angle_util',
+            ],
+            'export_dependent_settings':
+            [
+                '<(angle_path)/src/angle.gyp:angle_common',
+                '<(angle_path)/util/util.gyp:angle_util',
+            ],
+            'include_dirs':
+            [
+                '<(angle_path)/include',
+                'sample_util',
+            ],
+            'sources':
+            [
+                'sample_util/SampleApplication.cpp',
+                'sample_util/SampleApplication.h',
+                'sample_util/texture_utils.cpp',
+                'sample_util/texture_utils.h',
+                'sample_util/tga_utils.cpp',
+                'sample_util/tga_utils.h',
+            ],
+            'defines':
+            [
+                'GL_GLEXT_PROTOTYPES',
+                'EGL_EGLEXT_PROTOTYPES',
+            ],
+            'msvs_disabled_warnings': [ 4201 ],
+            'direct_dependent_settings':
+            {
+                'msvs_disabled_warnings': [ 4201 ],
+                'include_dirs':
+                [
+                    'sample_util',
+                ],
+                'defines':
+                [
+                    'GL_GLEXT_PROTOTYPES',
+                    'EGL_EGLEXT_PROTOTYPES',
+                ],
+            },
+        },
+        {
+            'target_name': 'hello_triangle',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'hello_triangle/HelloTriangle.cpp', ],
+        },
+        {
+            'target_name': 'mip_map_2d',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'mip_map_2d/MipMap2D.cpp', ],
+        },
+        {
+            'target_name': 'multi_texture',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'multi_texture/MultiTexture.cpp', ],
+            'copies':
+            [
+                {
+                    'destination': '<(PRODUCT_DIR)',
+                    'files':
+                    [
+                        'multi_texture/basemap.tga',
+                        'multi_texture/lightmap.tga',
+                    ],
+                },
+            ]
+        },
+
+        {
+            'target_name': 'multi_window',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'multi_window/MultiWindow.cpp', ],
+        },
+
+        {
+            'target_name': 'multiple_draw_buffers',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'multiple_draw_buffers/MultipleDrawBuffers.cpp', ],
+            'copies':
+            [
+                {
+                    'destination': '<(PRODUCT_DIR)',
+                    'files':
+                    [
+                        'multiple_draw_buffers/multiple_draw_buffers_copy_fs.glsl',
+                        'multiple_draw_buffers/multiple_draw_buffers_fs.glsl',
+                        'multiple_draw_buffers/multiple_draw_buffers_vs.glsl',
+                    ],
+                }
+            ]
+        },
+
+        {
+            'target_name': 'particle_system',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'particle_system/ParticleSystem.cpp', ],
+            'copies':
+            [
+                {
+                    'destination': '<(PRODUCT_DIR)',
+                    'files':
+                    [
+                        'particle_system/smoke.tga',
+                    ],
+                }
+            ]
+        },
+        {
+            'target_name': 'post_sub_buffer',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'post_sub_buffer/PostSubBuffer.cpp', ],
+        },
+
+        {
+            'target_name': 'simple_instancing',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'simple_instancing/SimpleInstancing.cpp', ],
+        },
+
+        {
+            'target_name': 'simple_texture_2d',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'simple_texture_2d/SimpleTexture2D.cpp', ],
+        },
+
+        {
+            'target_name': 'simple_texture_cubemap',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'simple_texture_cubemap/SimpleTextureCubemap.cpp', ],
+        },
+
+        {
+            'target_name': 'simple_vertex_shader',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'simple_vertex_shader/SimpleVertexShader.cpp', ],
+        },
+
+        {
+            'target_name': 'stencil_operations',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'stencil_operations/StencilOperations.cpp', ],
+        },
+
+        {
+            'target_name': 'tex_redef_microbench',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'tex_redef_microbench/TexRedefMicroBench.cpp', ],
+        },
+
+        {
+            'target_name': 'texture_wrap',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'texture_wrap/TextureWrap.cpp', ],
+        },
+
+        {
+            'target_name': 'tri_fan_microbench',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'tri_fan_microbench/TriFanMicroBench.cpp', ],
+        },
+
+        {
+            'target_name': 'window_test',
+            'type': 'executable',
+            'dependencies': [ 'sample_util' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ 'WindowTest/WindowTest.cpp', ],
+        },
+    ],
+}
diff --git a/src/third_party/angle/samples/samples.sln b/src/third_party/angle/samples/samples.sln
deleted file mode 100644
index 54d5854..0000000
--- a/src/third_party/angle/samples/samples.sln
+++ /dev/null
@@ -1,177 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 11.00

-# Visual C++ Express 2010

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "esUtil", "gles2_book\Common\esUtil.vcxproj", "{47C93F52-AB4E-4FF9-8D4F-B38CD60A183F}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hello_Triangle", "gles2_book\Hello_Triangle\Hello_Triangle.vcxproj", "{8278251F-6C1F-4D80-8499-FA7B590FAFE6}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MipMap2D", "gles2_book\MipMap2D\MipMap2D.vcxproj", "{4E69AC1F-1C7A-4D58-917C-E764FBEB489A}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MultiTexture", "gles2_book\MultiTexture\MultiTexture.vcxproj", "{120CFF94-ED4B-4C5B-9587-9E40889F15F7}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ParticleSystem", "gles2_book\ParticleSystem\ParticleSystem.vcxproj", "{B9E5BFFC-D843-4E0E-9D3E-23913A613473}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Simple_Texture2D", "gles2_book\Simple_Texture2D\Simple_Texture2D.vcxproj", "{2E54D748-781B-4DF2-A1DD-B9384A821810}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Simple_TextureCubemap", "gles2_book\Simple_TextureCubemap\Simple_TextureCubemap.vcxproj", "{5EE56061-643D-406E-B42D-4299D2411056}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Simple_VertexShader", "gles2_book\Simple_VertexShader\Simple_VertexShader.vcxproj", "{667CE95F-5DD8-4395-8C18-5CA8A175B12D}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stencil_Test", "gles2_book\Stencil_Test\Stencil_Test.vcxproj", "{EEACE995-26BC-4D56-A8B3-3E7A9AB3EB26}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TextureWrap", "gles2_book\TextureWrap\TextureWrap.vcxproj", "{CC1DE9A2-B456-4565-9C21-932253E969B9}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libEGL", "..\src\libEGL\libEGL.vcxproj", "{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libGLESv2", "..\src\libGLESv2\libGLESv2.vcxproj", "{B5871A7A-968C-42E3-A33B-981E6F448E78}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "translator_hlsl", "..\src\compiler\translator_hlsl.vcxproj", "{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "essl_to_hlsl", "translator\essl_to_hlsl.vcxproj", "{E12EA115-EBC7-47C2-B651-30A0CE986025}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "translator_common", "..\src\compiler\translator_common.vcxproj", "{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PostSubBuffer", "gles2_book\PostSubBuffer\PostSubBuffer.vcxproj", "{667CE95F-5DD8-4495-8C18-5CA8A175B12D}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "preprocessor", "..\src\compiler\preprocessor\preprocessor.vcxproj", "{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Simple_Instancing", "angle\Simple_Instancing\Simple_Instancing.vcxproj", "{EB6E138B-9DE5-41E8-A127-3675AA2BA607}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MultipleRenderTargets", "gles2_book\MultipleRenderTargets\MultipleRenderTargets.vcxproj", "{DD670DCB-2554-4FAE-B7C9-D7F0C3087C10}"

-EndProject

-Global

-	GlobalSection(SolutionConfigurationPlatforms) = preSolution

-		Debug|Win32 = Debug|Win32

-		Debug|x64 = Debug|x64

-		Release|Win32 = Release|Win32

-		Release|x64 = Release|x64

-	EndGlobalSection

-	GlobalSection(ProjectConfigurationPlatforms) = postSolution

-		{47C93F52-AB4E-4FF9-8D4F-B38CD60A183F}.Debug|Win32.ActiveCfg = Debug|Win32

-		{47C93F52-AB4E-4FF9-8D4F-B38CD60A183F}.Debug|Win32.Build.0 = Debug|Win32

-		{47C93F52-AB4E-4FF9-8D4F-B38CD60A183F}.Debug|x64.ActiveCfg = Debug|Win32

-		{47C93F52-AB4E-4FF9-8D4F-B38CD60A183F}.Release|Win32.ActiveCfg = Release|Win32

-		{47C93F52-AB4E-4FF9-8D4F-B38CD60A183F}.Release|Win32.Build.0 = Release|Win32

-		{47C93F52-AB4E-4FF9-8D4F-B38CD60A183F}.Release|x64.ActiveCfg = Release|Win32

-		{8278251F-6C1F-4D80-8499-FA7B590FAFE6}.Debug|Win32.ActiveCfg = Debug|Win32

-		{8278251F-6C1F-4D80-8499-FA7B590FAFE6}.Debug|Win32.Build.0 = Debug|Win32

-		{8278251F-6C1F-4D80-8499-FA7B590FAFE6}.Debug|x64.ActiveCfg = Debug|Win32

-		{8278251F-6C1F-4D80-8499-FA7B590FAFE6}.Release|Win32.ActiveCfg = Release|Win32

-		{8278251F-6C1F-4D80-8499-FA7B590FAFE6}.Release|Win32.Build.0 = Release|Win32

-		{8278251F-6C1F-4D80-8499-FA7B590FAFE6}.Release|x64.ActiveCfg = Release|Win32

-		{4E69AC1F-1C7A-4D58-917C-E764FBEB489A}.Debug|Win32.ActiveCfg = Debug|Win32

-		{4E69AC1F-1C7A-4D58-917C-E764FBEB489A}.Debug|Win32.Build.0 = Debug|Win32

-		{4E69AC1F-1C7A-4D58-917C-E764FBEB489A}.Debug|x64.ActiveCfg = Debug|Win32

-		{4E69AC1F-1C7A-4D58-917C-E764FBEB489A}.Release|Win32.ActiveCfg = Release|Win32

-		{4E69AC1F-1C7A-4D58-917C-E764FBEB489A}.Release|Win32.Build.0 = Release|Win32

-		{4E69AC1F-1C7A-4D58-917C-E764FBEB489A}.Release|x64.ActiveCfg = Release|Win32

-		{120CFF94-ED4B-4C5B-9587-9E40889F15F7}.Debug|Win32.ActiveCfg = Debug|Win32

-		{120CFF94-ED4B-4C5B-9587-9E40889F15F7}.Debug|Win32.Build.0 = Debug|Win32

-		{120CFF94-ED4B-4C5B-9587-9E40889F15F7}.Debug|x64.ActiveCfg = Debug|Win32

-		{120CFF94-ED4B-4C5B-9587-9E40889F15F7}.Release|Win32.ActiveCfg = Release|Win32

-		{120CFF94-ED4B-4C5B-9587-9E40889F15F7}.Release|Win32.Build.0 = Release|Win32

-		{120CFF94-ED4B-4C5B-9587-9E40889F15F7}.Release|x64.ActiveCfg = Release|Win32

-		{B9E5BFFC-D843-4E0E-9D3E-23913A613473}.Debug|Win32.ActiveCfg = Debug|Win32

-		{B9E5BFFC-D843-4E0E-9D3E-23913A613473}.Debug|Win32.Build.0 = Debug|Win32

-		{B9E5BFFC-D843-4E0E-9D3E-23913A613473}.Debug|x64.ActiveCfg = Debug|Win32

-		{B9E5BFFC-D843-4E0E-9D3E-23913A613473}.Release|Win32.ActiveCfg = Release|Win32

-		{B9E5BFFC-D843-4E0E-9D3E-23913A613473}.Release|Win32.Build.0 = Release|Win32

-		{B9E5BFFC-D843-4E0E-9D3E-23913A613473}.Release|x64.ActiveCfg = Release|Win32

-		{2E54D748-781B-4DF2-A1DD-B9384A821810}.Debug|Win32.ActiveCfg = Debug|Win32

-		{2E54D748-781B-4DF2-A1DD-B9384A821810}.Debug|Win32.Build.0 = Debug|Win32

-		{2E54D748-781B-4DF2-A1DD-B9384A821810}.Debug|x64.ActiveCfg = Debug|Win32

-		{2E54D748-781B-4DF2-A1DD-B9384A821810}.Release|Win32.ActiveCfg = Release|Win32

-		{2E54D748-781B-4DF2-A1DD-B9384A821810}.Release|Win32.Build.0 = Release|Win32

-		{2E54D748-781B-4DF2-A1DD-B9384A821810}.Release|x64.ActiveCfg = Release|Win32

-		{5EE56061-643D-406E-B42D-4299D2411056}.Debug|Win32.ActiveCfg = Debug|Win32

-		{5EE56061-643D-406E-B42D-4299D2411056}.Debug|Win32.Build.0 = Debug|Win32

-		{5EE56061-643D-406E-B42D-4299D2411056}.Debug|x64.ActiveCfg = Debug|Win32

-		{5EE56061-643D-406E-B42D-4299D2411056}.Release|Win32.ActiveCfg = Release|Win32

-		{5EE56061-643D-406E-B42D-4299D2411056}.Release|Win32.Build.0 = Release|Win32

-		{5EE56061-643D-406E-B42D-4299D2411056}.Release|x64.ActiveCfg = Release|Win32

-		{667CE95F-5DD8-4395-8C18-5CA8A175B12D}.Debug|Win32.ActiveCfg = Debug|Win32

-		{667CE95F-5DD8-4395-8C18-5CA8A175B12D}.Debug|Win32.Build.0 = Debug|Win32

-		{667CE95F-5DD8-4395-8C18-5CA8A175B12D}.Debug|x64.ActiveCfg = Debug|Win32

-		{667CE95F-5DD8-4395-8C18-5CA8A175B12D}.Release|Win32.ActiveCfg = Release|Win32

-		{667CE95F-5DD8-4395-8C18-5CA8A175B12D}.Release|Win32.Build.0 = Release|Win32

-		{667CE95F-5DD8-4395-8C18-5CA8A175B12D}.Release|x64.ActiveCfg = Release|Win32

-		{EEACE995-26BC-4D56-A8B3-3E7A9AB3EB26}.Debug|Win32.ActiveCfg = Debug|Win32

-		{EEACE995-26BC-4D56-A8B3-3E7A9AB3EB26}.Debug|Win32.Build.0 = Debug|Win32

-		{EEACE995-26BC-4D56-A8B3-3E7A9AB3EB26}.Debug|x64.ActiveCfg = Debug|Win32

-		{EEACE995-26BC-4D56-A8B3-3E7A9AB3EB26}.Release|Win32.ActiveCfg = Release|Win32

-		{EEACE995-26BC-4D56-A8B3-3E7A9AB3EB26}.Release|Win32.Build.0 = Release|Win32

-		{EEACE995-26BC-4D56-A8B3-3E7A9AB3EB26}.Release|x64.ActiveCfg = Release|Win32

-		{CC1DE9A2-B456-4565-9C21-932253E969B9}.Debug|Win32.ActiveCfg = Debug|Win32

-		{CC1DE9A2-B456-4565-9C21-932253E969B9}.Debug|Win32.Build.0 = Debug|Win32

-		{CC1DE9A2-B456-4565-9C21-932253E969B9}.Debug|x64.ActiveCfg = Debug|Win32

-		{CC1DE9A2-B456-4565-9C21-932253E969B9}.Release|Win32.ActiveCfg = Release|Win32

-		{CC1DE9A2-B456-4565-9C21-932253E969B9}.Release|Win32.Build.0 = Release|Win32

-		{CC1DE9A2-B456-4565-9C21-932253E969B9}.Release|x64.ActiveCfg = Release|Win32

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|Win32.ActiveCfg = Debug|Win32

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|Win32.Build.0 = Debug|Win32

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|x64.ActiveCfg = Debug|x64

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|x64.Build.0 = Debug|x64

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|Win32.ActiveCfg = Release|Win32

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|Win32.Build.0 = Release|Win32

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|x64.ActiveCfg = Release|x64

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|x64.Build.0 = Release|x64

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|Win32.ActiveCfg = Debug|Win32

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|Win32.Build.0 = Debug|Win32

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|x64.ActiveCfg = Debug|x64

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|x64.Build.0 = Debug|x64

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|Win32.ActiveCfg = Release|Win32

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|Win32.Build.0 = Release|Win32

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|x64.ActiveCfg = Release|x64

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|x64.Build.0 = Release|x64

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|Win32.ActiveCfg = Debug|Win32

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|Win32.Build.0 = Debug|Win32

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|x64.ActiveCfg = Debug|x64

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|x64.Build.0 = Debug|x64

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|Win32.ActiveCfg = Release|Win32

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|Win32.Build.0 = Release|Win32

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|x64.ActiveCfg = Release|x64

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|x64.Build.0 = Release|x64

-		{E12EA115-EBC7-47C2-B651-30A0CE986025}.Debug|Win32.ActiveCfg = Debug|Win32

-		{E12EA115-EBC7-47C2-B651-30A0CE986025}.Debug|Win32.Build.0 = Debug|Win32

-		{E12EA115-EBC7-47C2-B651-30A0CE986025}.Debug|x64.ActiveCfg = Debug|Win32

-		{E12EA115-EBC7-47C2-B651-30A0CE986025}.Release|Win32.ActiveCfg = Release|Win32

-		{E12EA115-EBC7-47C2-B651-30A0CE986025}.Release|Win32.Build.0 = Release|Win32

-		{E12EA115-EBC7-47C2-B651-30A0CE986025}.Release|x64.ActiveCfg = Release|Win32

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.ActiveCfg = Debug|Win32

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.Build.0 = Debug|Win32

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|x64.ActiveCfg = Debug|x64

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|x64.Build.0 = Debug|x64

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.ActiveCfg = Release|Win32

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.Build.0 = Release|Win32

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|x64.ActiveCfg = Release|x64

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|x64.Build.0 = Release|x64

-		{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Debug|Win32.ActiveCfg = Debug|Win32

-		{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Debug|Win32.Build.0 = Debug|Win32

-		{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Debug|x64.ActiveCfg = Debug|Win32

-		{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Release|Win32.ActiveCfg = Release|Win32

-		{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Release|Win32.Build.0 = Release|Win32

-		{667CE95F-5DD8-4495-8C18-5CA8A175B12D}.Release|x64.ActiveCfg = Release|Win32

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|Win32.ActiveCfg = Debug|Win32

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|Win32.Build.0 = Debug|Win32

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|x64.ActiveCfg = Debug|x64

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|x64.Build.0 = Debug|x64

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|Win32.ActiveCfg = Release|Win32

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|Win32.Build.0 = Release|Win32

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|x64.ActiveCfg = Release|x64

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|x64.Build.0 = Release|x64

-		{EB6E138B-9DE5-41E8-A127-3675AA2BA607}.Debug|Win32.ActiveCfg = Debug|Win32

-		{EB6E138B-9DE5-41E8-A127-3675AA2BA607}.Debug|Win32.Build.0 = Debug|Win32

-		{EB6E138B-9DE5-41E8-A127-3675AA2BA607}.Debug|x64.ActiveCfg = Debug|Win32

-		{EB6E138B-9DE5-41E8-A127-3675AA2BA607}.Release|Win32.ActiveCfg = Release|Win32

-		{EB6E138B-9DE5-41E8-A127-3675AA2BA607}.Release|Win32.Build.0 = Release|Win32

-		{EB6E138B-9DE5-41E8-A127-3675AA2BA607}.Release|x64.ActiveCfg = Release|Win32

-		{DD670DCB-2554-4FAE-B7C9-D7F0C3087C10}.Debug|Win32.ActiveCfg = Debug|Win32

-		{DD670DCB-2554-4FAE-B7C9-D7F0C3087C10}.Debug|Win32.Build.0 = Debug|Win32

-		{DD670DCB-2554-4FAE-B7C9-D7F0C3087C10}.Debug|x64.ActiveCfg = Debug|Win32

-		{DD670DCB-2554-4FAE-B7C9-D7F0C3087C10}.Release|Win32.ActiveCfg = Release|Win32

-		{DD670DCB-2554-4FAE-B7C9-D7F0C3087C10}.Release|Win32.Build.0 = Release|Win32

-		{DD670DCB-2554-4FAE-B7C9-D7F0C3087C10}.Release|x64.ActiveCfg = Release|Win32

-	EndGlobalSection

-	GlobalSection(SolutionProperties) = preSolution

-		HideSolutionNode = FALSE

-	EndGlobalSection

-EndGlobal

diff --git a/src/third_party/angle/samples/shader_translator/shader_translator.cpp b/src/third_party/angle/samples/shader_translator/shader_translator.cpp
new file mode 100644
index 0000000..573a318
--- /dev/null
+++ b/src/third_party/angle/samples/shader_translator/shader_translator.cpp
@@ -0,0 +1,711 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sstream>
+#include <vector>
+#include "angle_gl.h"
+
+//
+// Return codes from main.
+//
+enum TFailCode
+{
+    ESuccess = 0,
+    EFailUsage,
+    EFailCompile,
+    EFailCompilerCreate,
+};
+
+static void usage();
+static sh::GLenum FindShaderType(const char *fileName);
+static bool CompileFile(char *fileName, ShHandle compiler, ShCompileOptions compileOptions);
+static void LogMsg(const char *msg, const char *name, const int num, const char *logName);
+static void PrintVariable(const std::string &prefix, size_t index, const sh::ShaderVariable &var);
+static void PrintActiveVariables(ShHandle compiler);
+
+// If NUM_SOURCE_STRINGS is set to a value > 1, the input file data is
+// broken into that many chunks. This will affect file/line numbering in
+// the preprocessor.
+const unsigned int NUM_SOURCE_STRINGS = 1;
+typedef std::vector<char *> ShaderSource;
+static bool ReadShaderSource(const char *fileName, ShaderSource &source);
+static void FreeShaderSource(ShaderSource &source);
+
+static bool ParseGLSLOutputVersion(const std::string &, ShShaderOutput *outResult);
+static bool ParseIntValue(const std::string &, int emptyDefault, int *outValue);
+
+//
+// Set up the per compile resources
+//
+void GenerateResources(ShBuiltInResources *resources)
+{
+    sh::InitBuiltInResources(resources);
+
+    resources->MaxVertexAttribs = 8;
+    resources->MaxVertexUniformVectors = 128;
+    resources->MaxVaryingVectors = 8;
+    resources->MaxVertexTextureImageUnits = 0;
+    resources->MaxCombinedTextureImageUnits = 8;
+    resources->MaxTextureImageUnits = 8;
+    resources->MaxFragmentUniformVectors = 16;
+    resources->MaxDrawBuffers = 1;
+    resources->MaxDualSourceDrawBuffers     = 1;
+
+    resources->OES_standard_derivatives = 0;
+    resources->OES_EGL_image_external = 0;
+}
+
+int main(int argc, char *argv[])
+{
+    TFailCode failCode = ESuccess;
+
+    ShCompileOptions compileOptions = 0;
+    int numCompiles = 0;
+    ShHandle vertexCompiler = 0;
+    ShHandle fragmentCompiler = 0;
+    ShHandle computeCompiler  = 0;
+    ShShaderSpec spec = SH_GLES2_SPEC;
+    ShShaderOutput output = SH_ESSL_OUTPUT;
+
+    sh::Initialize();
+
+    ShBuiltInResources resources;
+    GenerateResources(&resources);
+
+    argc--;
+    argv++;
+    for (; (argc >= 1) && (failCode == ESuccess); argc--, argv++)
+    {
+        if (argv[0][0] == '-')
+        {
+            switch (argv[0][1])
+            {
+              case 'i': compileOptions |= SH_INTERMEDIATE_TREE; break;
+              case 'o': compileOptions |= SH_OBJECT_CODE; break;
+              case 'u': compileOptions |= SH_VARIABLES; break;
+              case 'p': resources.WEBGL_debug_shader_precision = 1; break;
+              case 's':
+                if (argv[0][2] == '=')
+                {
+                    switch (argv[0][3])
+                    {
+                        case 'e':
+                            if (argv[0][4] == '3')
+                            {
+                                if (argv[0][5] == '1')
+                                {
+                                    spec = SH_GLES3_1_SPEC;
+                                }
+                                else
+                                {
+                                    spec = SH_GLES3_SPEC;
+                                }
+                            }
+                            else
+                            {
+                                spec = SH_GLES2_SPEC;
+                            }
+                            break;
+                        case 'w':
+                            if (argv[0][4] == '3')
+                            {
+                                spec = SH_WEBGL3_SPEC;
+                            }
+                            else if (argv[0][4] == '2')
+                            {
+                                spec = SH_WEBGL2_SPEC;
+                            }
+                            else
+                            {
+                                spec = SH_WEBGL_SPEC;
+                            }
+                            break;
+                        default:
+                            failCode = EFailUsage;
+                    }
+                }
+                else
+                {
+                    failCode = EFailUsage;
+                }
+                break;
+              case 'b':
+                if (argv[0][2] == '=')
+                {
+                    switch (argv[0][3])
+                    {
+                      case 'e': output = SH_ESSL_OUTPUT; break;
+                      case 'g':
+                          if (!ParseGLSLOutputVersion(&argv[0][sizeof("-b=g") - 1], &output))
+                          {
+                              failCode = EFailUsage;
+                          }
+                          break;
+                      case 'h':
+                        if (argv[0][4] == '1' && argv[0][5] == '1')
+                        {
+                            output = SH_HLSL_4_1_OUTPUT;
+                        }
+                        else
+                        {
+                            output = SH_HLSL_3_0_OUTPUT;
+                        }
+                        break;
+                      default: failCode = EFailUsage;
+                    }
+                }
+                else
+                {
+                    failCode = EFailUsage;
+                }
+                break;
+              case 'x':
+                if (argv[0][2] == '=')
+                {
+                    // clang-format off
+                    switch (argv[0][3])
+                    {
+                      case 'i': resources.OES_EGL_image_external = 1; break;
+                      case 'd': resources.OES_standard_derivatives = 1; break;
+                      case 'r': resources.ARB_texture_rectangle = 1; break;
+                      case 'b':
+                          if (ParseIntValue(&argv[0][sizeof("-x=b") - 1], 1,
+                                            &resources.MaxDualSourceDrawBuffers))
+                          {
+                              resources.EXT_blend_func_extended = 1;
+                          }
+                          else
+                          {
+                              failCode = EFailUsage;
+                          }
+                          break;
+                      case 'w':
+                          if (ParseIntValue(&argv[0][sizeof("-x=w") - 1], 1,
+                                            &resources.MaxDrawBuffers))
+                          {
+                              resources.EXT_draw_buffers = 1;
+                          }
+                          else
+                          {
+                              failCode = EFailUsage;
+                          }
+                          break;
+                      case 'g': resources.EXT_frag_depth = 1; break;
+                      case 'l': resources.EXT_shader_texture_lod = 1; break;
+                      case 'f': resources.EXT_shader_framebuffer_fetch = 1; break;
+                      case 'n': resources.NV_shader_framebuffer_fetch = 1; break;
+                      case 'a': resources.ARM_shader_framebuffer_fetch = 1; break;
+                      case 'm':
+                          resources.OVR_multiview = 1;
+                          compileOptions |= SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM;
+                          break;
+                      case 'y': resources.EXT_YUV_target = 1; break;
+                      default: failCode = EFailUsage;
+                    }
+                    // clang-format on
+                }
+                else
+                {
+                    failCode = EFailUsage;
+                }
+                break;
+              default: failCode = EFailUsage;
+            }
+        }
+        else
+        {
+            if (spec != SH_GLES2_SPEC && spec != SH_WEBGL_SPEC)
+            {
+                resources.MaxDrawBuffers = 8;
+                resources.MaxVertexTextureImageUnits = 16;
+                resources.MaxTextureImageUnits       = 16;
+            }
+            ShHandle compiler = 0;
+            switch (FindShaderType(argv[0]))
+            {
+              case GL_VERTEX_SHADER:
+                if (vertexCompiler == 0)
+                {
+                    vertexCompiler =
+                        sh::ConstructCompiler(GL_VERTEX_SHADER, spec, output, &resources);
+                }
+                compiler = vertexCompiler;
+                break;
+              case GL_FRAGMENT_SHADER:
+                if (fragmentCompiler == 0)
+                {
+                    fragmentCompiler =
+                        sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &resources);
+                }
+                compiler = fragmentCompiler;
+                break;
+              case GL_COMPUTE_SHADER:
+                  if (computeCompiler == 0)
+                  {
+                      computeCompiler =
+                          sh::ConstructCompiler(GL_COMPUTE_SHADER, spec, output, &resources);
+                  }
+                  compiler = computeCompiler;
+                  break;
+
+              default: break;
+            }
+            if (compiler)
+            {
+                bool compiled = CompileFile(argv[0], compiler, compileOptions);
+
+                LogMsg("BEGIN", "COMPILER", numCompiles, "INFO LOG");
+                std::string log = sh::GetInfoLog(compiler);
+                puts(log.c_str());
+                LogMsg("END", "COMPILER", numCompiles, "INFO LOG");
+                printf("\n\n");
+
+                if (compiled && (compileOptions & SH_OBJECT_CODE))
+                {
+                    LogMsg("BEGIN", "COMPILER", numCompiles, "OBJ CODE");
+                    std::string code = sh::GetObjectCode(compiler);
+                    puts(code.c_str());
+                    LogMsg("END", "COMPILER", numCompiles, "OBJ CODE");
+                    printf("\n\n");
+                }
+                if (compiled && (compileOptions & SH_VARIABLES))
+                {
+                    LogMsg("BEGIN", "COMPILER", numCompiles, "VARIABLES");
+                    PrintActiveVariables(compiler);
+                    LogMsg("END", "COMPILER", numCompiles, "VARIABLES");
+                    printf("\n\n");
+                }
+                if (!compiled)
+                  failCode = EFailCompile;
+                ++numCompiles;
+            }
+            else
+            {
+                failCode = EFailCompilerCreate;
+            }
+        }
+    }
+
+    if ((vertexCompiler == 0) && (fragmentCompiler == 0) && (computeCompiler == 0))
+        failCode = EFailUsage;
+    if (failCode == EFailUsage)
+        usage();
+
+    if (vertexCompiler)
+        sh::Destruct(vertexCompiler);
+    if (fragmentCompiler)
+        sh::Destruct(fragmentCompiler);
+    if (computeCompiler)
+        sh::Destruct(computeCompiler);
+
+    sh::Finalize();
+
+    return failCode;
+}
+
+//
+//   print usage to stdout
+//
+void usage()
+{
+    // clang-format off
+    printf(
+        "Usage: translate [-i -o -u -l -p -b=e -b=g -b=h9 -x=i -x=d] file1 file2 ...\n"
+        "Where: filename : filename ending in .frag or .vert\n"
+        "       -i       : print intermediate tree\n"
+        "       -o       : print translated code\n"
+        "       -u       : print active attribs, uniforms, varyings and program outputs\n"
+        "       -p       : use precision emulation\n"
+        "       -s=e2    : use GLES2 spec (this is by default)\n"
+        "       -s=e3    : use GLES3 spec (in development)\n"
+        "       -s=e31   : use GLES31 spec (in development)\n"
+        "       -s=w     : use WebGL spec\n"
+        "       -s=w2    : use WebGL 2 spec (in development)\n"
+        "       -b=e     : output GLSL ES code (this is by default)\n"
+        "       -b=g     : output GLSL code (compatibility profile)\n"
+        "       -b=g[NUM]: output GLSL code (NUM can be 130, 140, 150, 330, 400, 410, 420, 430, "
+        "440, 450)\n"
+        "       -b=h9    : output HLSL9 code\n"
+        "       -b=h11   : output HLSL11 code\n"
+        "       -x=i     : enable GL_OES_EGL_image_external\n"
+        "       -x=d     : enable GL_OES_EGL_standard_derivatives\n"
+        "       -x=r     : enable ARB_texture_rectangle\n"
+        "       -x=b[NUM]: enable EXT_blend_func_extended (NUM default 1)\n"
+        "       -x=w[NUM]: enable EXT_draw_buffers (NUM default 1)\n"
+        "       -x=g     : enable EXT_frag_depth\n"
+        "       -x=l     : enable EXT_shader_texture_lod\n"
+        "       -x=f     : enable EXT_shader_framebuffer_fetch\n"
+        "       -x=n     : enable NV_shader_framebuffer_fetch\n"
+        "       -x=a     : enable ARM_shader_framebuffer_fetch\n"
+        "       -x=m     : enable OVR_multiview\n"
+        "       -x=y     : enable YUV_target\n");
+    // clang-format on
+}
+
+//
+//   Deduce the shader type from the filename.  Files must end in one of the
+//   following extensions:
+//
+//   .frag*    = fragment shader
+//   .vert*    = vertex shader
+//
+sh::GLenum FindShaderType(const char *fileName)
+{
+    assert(fileName);
+
+    const char *ext = strrchr(fileName, '.');
+
+    if (ext && strcmp(ext, ".sl") == 0)
+        for (; ext > fileName && ext[0] != '.'; ext--);
+
+    ext = strrchr(fileName, '.');
+    if (ext)
+    {
+        if (strncmp(ext, ".frag", 5) == 0)
+            return GL_FRAGMENT_SHADER;
+        if (strncmp(ext, ".vert", 5) == 0)
+            return GL_VERTEX_SHADER;
+        if (strncmp(ext, ".comp", 5) == 0)
+            return GL_COMPUTE_SHADER;
+    }
+
+    return GL_FRAGMENT_SHADER;
+}
+
+//
+//   Read a file's data into a string, and compile it using sh::Compile
+//
+bool CompileFile(char *fileName, ShHandle compiler, ShCompileOptions compileOptions)
+{
+    ShaderSource source;
+    if (!ReadShaderSource(fileName, source))
+        return false;
+
+    int ret = sh::Compile(compiler, &source[0], source.size(), compileOptions);
+
+    FreeShaderSource(source);
+    return ret ? true : false;
+}
+
+void LogMsg(const char *msg, const char *name, const int num, const char *logName)
+{
+    printf("#### %s %s %d %s ####\n", msg, name, num, logName);
+}
+
+void PrintVariable(const std::string &prefix, size_t index, const sh::ShaderVariable &var)
+{
+    std::string typeName;
+    switch (var.type)
+    {
+      case GL_FLOAT: typeName = "GL_FLOAT"; break;
+      case GL_FLOAT_VEC2: typeName = "GL_FLOAT_VEC2"; break;
+      case GL_FLOAT_VEC3: typeName = "GL_FLOAT_VEC3"; break;
+      case GL_FLOAT_VEC4: typeName = "GL_FLOAT_VEC4"; break;
+      case GL_INT: typeName = "GL_INT"; break;
+      case GL_INT_VEC2: typeName = "GL_INT_VEC2"; break;
+      case GL_INT_VEC3: typeName = "GL_INT_VEC3"; break;
+      case GL_INT_VEC4: typeName = "GL_INT_VEC4"; break;
+      case GL_UNSIGNED_INT: typeName = "GL_UNSIGNED_INT"; break;
+      case GL_UNSIGNED_INT_VEC2: typeName = "GL_UNSIGNED_INT_VEC2"; break;
+      case GL_UNSIGNED_INT_VEC3: typeName = "GL_UNSIGNED_INT_VEC3"; break;
+      case GL_UNSIGNED_INT_VEC4: typeName = "GL_UNSIGNED_INT_VEC4"; break;
+      case GL_BOOL: typeName = "GL_BOOL"; break;
+      case GL_BOOL_VEC2: typeName = "GL_BOOL_VEC2"; break;
+      case GL_BOOL_VEC3: typeName = "GL_BOOL_VEC3"; break;
+      case GL_BOOL_VEC4: typeName = "GL_BOOL_VEC4"; break;
+      case GL_FLOAT_MAT2: typeName = "GL_FLOAT_MAT2"; break;
+      case GL_FLOAT_MAT3: typeName = "GL_FLOAT_MAT3"; break;
+      case GL_FLOAT_MAT4: typeName = "GL_FLOAT_MAT4"; break;
+      case GL_FLOAT_MAT2x3: typeName = "GL_FLOAT_MAT2x3"; break;
+      case GL_FLOAT_MAT3x2: typeName = "GL_FLOAT_MAT3x2"; break;
+      case GL_FLOAT_MAT4x2: typeName = "GL_FLOAT_MAT4x2"; break;
+      case GL_FLOAT_MAT2x4: typeName = "GL_FLOAT_MAT2x4"; break;
+      case GL_FLOAT_MAT3x4: typeName = "GL_FLOAT_MAT3x4"; break;
+      case GL_FLOAT_MAT4x3: typeName = "GL_FLOAT_MAT4x3"; break;
+
+      case GL_SAMPLER_2D: typeName = "GL_SAMPLER_2D"; break;
+      case GL_SAMPLER_3D:
+          typeName = "GL_SAMPLER_3D";
+          break;
+      case GL_SAMPLER_CUBE:
+          typeName = "GL_SAMPLER_CUBE";
+          break;
+      case GL_SAMPLER_CUBE_SHADOW:
+          typeName = "GL_SAMPLER_CUBE_SHADOW";
+          break;
+      case GL_SAMPLER_2D_SHADOW:
+          typeName = "GL_SAMPLER_2D_ARRAY_SHADOW";
+          break;
+      case GL_SAMPLER_2D_ARRAY:
+          typeName = "GL_SAMPLER_2D_ARRAY";
+          break;
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+          typeName = "GL_SAMPLER_2D_ARRAY_SHADOW";
+          break;
+      case GL_SAMPLER_2D_MULTISAMPLE:
+          typeName = "GL_SAMPLER_2D_MULTISAMPLE";
+          break;
+      case GL_IMAGE_2D:
+          typeName = "GL_IMAGE_2D";
+          break;
+      case GL_IMAGE_3D:
+          typeName = "GL_IMAGE_3D";
+          break;
+      case GL_IMAGE_CUBE:
+          typeName = "GL_IMAGE_CUBE";
+          break;
+      case GL_IMAGE_2D_ARRAY:
+          typeName = "GL_IMAGE_2D_ARRAY";
+          break;
+
+      case GL_INT_SAMPLER_2D:
+          typeName = "GL_INT_SAMPLER_2D";
+          break;
+      case GL_INT_SAMPLER_3D:
+          typeName = "GL_INT_SAMPLER_3D";
+          break;
+      case GL_INT_SAMPLER_CUBE:
+          typeName = "GL_INT_SAMPLER_CUBE";
+          break;
+      case GL_INT_SAMPLER_2D_ARRAY:
+          typeName = "GL_INT_SAMPLER_2D_ARRAY";
+          break;
+      case GL_INT_SAMPLER_2D_MULTISAMPLE:
+          typeName = "GL_INT_SAMPLER_2D_MULTISAMPLE";
+          break;
+      case GL_INT_IMAGE_2D:
+          typeName = "GL_INT_IMAGE_2D";
+          break;
+      case GL_INT_IMAGE_3D:
+          typeName = "GL_INT_IMAGE_3D";
+          break;
+      case GL_INT_IMAGE_CUBE:
+          typeName = "GL_INT_IMAGE_CUBE";
+          break;
+      case GL_INT_IMAGE_2D_ARRAY:
+          typeName = "GL_INT_IMAGE_2D_ARRAY";
+          break;
+
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+          typeName = "GL_UNSIGNED_INT_SAMPLER_2D";
+          break;
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+          typeName = "GL_UNSIGNED_INT_SAMPLER_3D";
+          break;
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+          typeName = "GL_UNSIGNED_INT_SAMPLER_CUBE";
+          break;
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+          typeName = "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY";
+          break;
+      case GL_UNSIGNED_INT_ATOMIC_COUNTER:
+          typeName = "GL_UNSIGNED_INT_ATOMIC_COUNTER";
+          break;
+      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+          typeName = "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE";
+          break;
+      case GL_UNSIGNED_INT_IMAGE_2D:
+          typeName = "GL_UNSIGNED_INT_IMAGE_2D";
+          break;
+      case GL_UNSIGNED_INT_IMAGE_3D:
+          typeName = "GL_UNSIGNED_INT_IMAGE_3D";
+          break;
+      case GL_UNSIGNED_INT_IMAGE_CUBE:
+          typeName = "GL_UNSIGNED_INT_IMAGE_CUBE";
+          break;
+      case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+          typeName = "GL_UNSIGNED_INT_IMAGE_2D_ARRAY";
+          break;
+
+      case GL_SAMPLER_EXTERNAL_OES: typeName = "GL_SAMPLER_EXTERNAL_OES"; break;
+      case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT:
+          typeName = "GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT";
+          break;
+      default: typeName = "UNKNOWN"; break;
+    }
+
+    printf("%s %u : name=%s, type=%s, arraySize=%u\n", prefix.c_str(),
+           static_cast<unsigned int>(index), var.name.c_str(), typeName.c_str(), var.arraySize);
+    if (var.fields.size())
+    {
+        std::string structPrefix;
+        for (size_t i = 0; i < prefix.size(); ++i)
+            structPrefix += ' ';
+        printf("%s  struct %s\n", structPrefix.c_str(), var.structName.c_str());
+        structPrefix += "    field";
+        for (size_t i = 0; i < var.fields.size(); ++i)
+            PrintVariable(structPrefix, i, var.fields[i]);
+    }
+}
+
+static void PrintActiveVariables(ShHandle compiler)
+{
+    const std::vector<sh::Uniform> *uniforms       = sh::GetUniforms(compiler);
+    const std::vector<sh::Varying> *varyings       = sh::GetVaryings(compiler);
+    const std::vector<sh::Attribute> *attributes   = sh::GetAttributes(compiler);
+    const std::vector<sh::OutputVariable> *outputs = sh::GetOutputVariables(compiler);
+    for (size_t varCategory = 0; varCategory < 4; ++varCategory)
+    {
+        size_t numVars = 0;
+        std::string varCategoryName;
+        if (varCategory == 0)
+        {
+            numVars = uniforms->size();
+            varCategoryName = "uniform";
+        }
+        else if (varCategory == 1)
+        {
+            numVars = varyings->size();
+            varCategoryName = "varying";
+        }
+        else if (varCategory == 2)
+        {
+            numVars = attributes->size();
+            varCategoryName = "attribute";
+        }
+        else
+        {
+            numVars         = outputs->size();
+            varCategoryName = "output";
+        }
+
+        for (size_t i = 0; i < numVars; ++i)
+        {
+            const sh::ShaderVariable *var;
+            if (varCategory == 0)
+                var = &((*uniforms)[i]);
+            else if (varCategory == 1)
+                var = &((*varyings)[i]);
+            else if (varCategory == 2)
+                var = &((*attributes)[i]);
+            else
+                var = &((*outputs)[i]);
+
+            PrintVariable(varCategoryName, i, *var);
+        }
+        printf("\n");
+    }
+}
+
+static bool ReadShaderSource(const char *fileName, ShaderSource &source)
+{
+    FILE *in = fopen(fileName, "rb");
+    if (!in)
+    {
+        printf("Error: unable to open input file: %s\n", fileName);
+        return false;
+    }
+
+    // Obtain file size.
+    fseek(in, 0, SEEK_END);
+    size_t count = ftell(in);
+    rewind(in);
+
+    int len = (int)ceil((float)count / (float)NUM_SOURCE_STRINGS);
+    source.reserve(NUM_SOURCE_STRINGS);
+    // Notice the usage of do-while instead of a while loop here.
+    // It is there to handle empty files in which case a single empty
+    // string is added to vector.
+    do
+    {
+        char *data = new char[len + 1];
+        size_t nread = fread(data, 1, len, in);
+        data[nread] = '\0';
+        source.push_back(data);
+
+        count -= nread;
+    }
+    while (count > 0);
+
+    fclose(in);
+    return true;
+}
+
+static void FreeShaderSource(ShaderSource &source)
+{
+    for (ShaderSource::size_type i = 0; i < source.size(); ++i)
+    {
+        delete [] source[i];
+    }
+    source.clear();
+}
+
+static bool ParseGLSLOutputVersion(const std::string &num, ShShaderOutput *outResult)
+{
+    if (num.length() == 0)
+    {
+        *outResult = SH_GLSL_COMPATIBILITY_OUTPUT;
+        return true;
+    }
+    std::istringstream input(num);
+    int value;
+    if (!(input >> value && input.eof()))
+    {
+        return false;
+    }
+
+    switch (value)
+    {
+        case 130:
+            *outResult = SH_GLSL_130_OUTPUT;
+            return true;
+        case 140:
+            *outResult = SH_GLSL_140_OUTPUT;
+            return true;
+        case 150:
+            *outResult = SH_GLSL_150_CORE_OUTPUT;
+            return true;
+        case 330:
+            *outResult = SH_GLSL_330_CORE_OUTPUT;
+            return true;
+        case 400:
+            *outResult = SH_GLSL_400_CORE_OUTPUT;
+            return true;
+        case 410:
+            *outResult = SH_GLSL_410_CORE_OUTPUT;
+            return true;
+        case 420:
+            *outResult = SH_GLSL_420_CORE_OUTPUT;
+            return true;
+        case 430:
+            *outResult = SH_GLSL_430_CORE_OUTPUT;
+            return true;
+        case 440:
+            *outResult = SH_GLSL_440_CORE_OUTPUT;
+            return true;
+        case 450:
+            *outResult = SH_GLSL_450_CORE_OUTPUT;
+            return true;
+        default:
+            break;
+    }
+    return false;
+}
+
+static bool ParseIntValue(const std::string &num, int emptyDefault, int *outValue)
+{
+    if (num.length() == 0)
+    {
+        *outValue = emptyDefault;
+        return true;
+    }
+
+    std::istringstream input(num);
+    int value;
+    if (!(input >> value && input.eof()))
+    {
+        return false;
+    }
+    *outValue = value;
+    return true;
+}
diff --git a/src/third_party/angle/samples/simple_instancing/SimpleInstancing.cpp b/src/third_party/angle/samples/simple_instancing/SimpleInstancing.cpp
new file mode 100644
index 0000000..bfb3e6c
--- /dev/null
+++ b/src/third_party/angle/samples/simple_instancing/SimpleInstancing.cpp
@@ -0,0 +1,206 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Simple_Texture2D.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+
+#include "common/vector_utils.h"
+#include "shader_utils.h"
+#include "texture_utils.h"
+
+#include <cstring>
+#include <iostream>
+#include <vector>
+
+using namespace angle;
+
+class SimpleInstancingSample : public SampleApplication
+{
+  public:
+    SimpleInstancingSample()
+        : SampleApplication("SimpleInstancing", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        // init instancing functions
+        char *extensionString = (char*)glGetString(GL_EXTENSIONS);
+        if (strstr(extensionString, "GL_ANGLE_instanced_arrays"))
+        {
+            mVertexAttribDivisorANGLE = (PFNGLVERTEXATTRIBDIVISORANGLEPROC)eglGetProcAddress("glVertexAttribDivisorANGLE");
+            mDrawArraysInstancedANGLE = (PFNGLDRAWARRAYSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawArraysInstancedANGLE");
+            mDrawElementsInstancedANGLE = (PFNGLDRAWELEMENTSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawElementsInstancedANGLE");
+        }
+
+        if (!mVertexAttribDivisorANGLE || !mDrawArraysInstancedANGLE || !mDrawElementsInstancedANGLE)
+        {
+            std::cerr << "Unable to load GL_ANGLE_instanced_arrays entry points.";
+            return false;
+        }
+
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec3 a_position;
+            attribute vec2 a_texCoord;
+            attribute vec3 a_instancePos;
+            varying vec2 v_texCoord;
+            void main()
+            {
+                gl_Position = vec4(a_position.xyz + a_instancePos.xyz, 1.0);
+                v_texCoord = a_texCoord;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec2 v_texCoord;
+            uniform sampler2D s_texture;
+            void main()
+            {
+                gl_FragColor = texture2D(s_texture, v_texCoord);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+        mTexCoordLoc = glGetAttribLocation(mProgram, "a_texCoord");
+        mInstancePosLoc = glGetAttribLocation(mProgram, "a_instancePos");
+
+        // Get the sampler location
+        mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
+
+        // Load the texture
+        mTextureID = CreateSimpleTexture2D();
+
+        // Initialize the vertex and index vectors
+        const GLfloat quadRadius = 0.01f;
+
+        mVertices.push_back(Vector3(-quadRadius,  quadRadius, 0.0f));
+        mVertices.push_back(Vector3(-quadRadius, -quadRadius, 0.0f));
+        mVertices.push_back(Vector3( quadRadius, -quadRadius, 0.0f));
+        mVertices.push_back(Vector3( quadRadius,  quadRadius, 0.0f));
+
+        mTexcoords.push_back(Vector2(0.0f, 0.0f));
+        mTexcoords.push_back(Vector2(0.0f, 1.0f));
+        mTexcoords.push_back(Vector2(1.0f, 1.0f));
+        mTexcoords.push_back(Vector2(1.0f, 0.0f));
+
+        mIndices.push_back(0);
+        mIndices.push_back(1);
+        mIndices.push_back(2);
+        mIndices.push_back(0);
+        mIndices.push_back(2);
+        mIndices.push_back(3);
+
+        // Tile thousands of quad instances
+        for (float y = -1.0f + quadRadius; y < 1.0f - quadRadius; y += quadRadius * 3)
+        {
+            for (float x = -1.0f + quadRadius; x < 1.0f - quadRadius; x += quadRadius * 3)
+            {
+                mInstances.push_back(Vector3(x, y, 0.0f));
+            }
+        }
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+        glDeleteTextures(1, &mTextureID);
+    }
+
+    virtual void draw()
+    {
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, mVertices.data());
+        glEnableVertexAttribArray(mPositionLoc);
+
+        // Load the texture coordinate
+        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, mTexcoords.data());
+        glEnableVertexAttribArray(mTexCoordLoc);
+
+        // Load the instance position
+        glVertexAttribPointer(mInstancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, mInstances.data());
+        glEnableVertexAttribArray(mInstancePosLoc);
+
+        // Enable instancing
+        mVertexAttribDivisorANGLE(mInstancePosLoc, 1);
+
+        // Bind the texture
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTextureID);
+
+        // Set the sampler texture unit to 0
+        glUniform1i(mSamplerLoc, 0);
+
+        // Do the instanced draw
+        mDrawElementsInstancedANGLE(GL_TRIANGLES, static_cast<GLsizei>(mIndices.size()),
+                                    GL_UNSIGNED_SHORT, mIndices.data(),
+                                    static_cast<GLsizei>(mInstances.size()));
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mTexCoordLoc;
+
+    // Sampler location
+    GLint mSamplerLoc;
+
+    // Texture handle
+    GLuint mTextureID;
+
+    // Instance VBO
+    GLint mInstancePosLoc;
+
+    // Loaded entry points
+    PFNGLVERTEXATTRIBDIVISORANGLEPROC mVertexAttribDivisorANGLE;
+    PFNGLDRAWARRAYSINSTANCEDANGLEPROC mDrawArraysInstancedANGLE;
+    PFNGLDRAWELEMENTSINSTANCEDANGLEPROC mDrawElementsInstancedANGLE;
+
+    // Vertex data
+    std::vector<Vector3> mVertices;
+    std::vector<Vector2> mTexcoords;
+    std::vector<Vector3> mInstances;
+    std::vector<GLushort> mIndices;
+};
+
+int main(int argc, char **argv)
+{
+    SimpleInstancingSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/simple_texture_2d/SimpleTexture2D.cpp b/src/third_party/angle/samples/simple_texture_2d/SimpleTexture2D.cpp
new file mode 100644
index 0000000..4d38fe6
--- /dev/null
+++ b/src/third_party/angle/samples/simple_texture_2d/SimpleTexture2D.cpp
@@ -0,0 +1,141 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Simple_Texture2D.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+#include "texture_utils.h"
+
+class SimpleTexture2DSample : public SampleApplication
+{
+  public:
+    SimpleTexture2DSample()
+        : SampleApplication("SimpleTexture2D", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec4 a_position;
+            attribute vec2 a_texCoord;
+            varying vec2 v_texCoord;
+            void main()
+            {
+                gl_Position = a_position;
+                v_texCoord = a_texCoord;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec2 v_texCoord;
+            uniform sampler2D s_texture;
+            void main()
+            {
+                gl_FragColor = texture2D(s_texture, v_texCoord);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+        mTexCoordLoc = glGetAttribLocation(mProgram, "a_texCoord");
+
+        // Get the sampler location
+        mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
+
+        // Load the texture
+        mTexture = CreateSimpleTexture2D();
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+        glDeleteTextures(1, &mTexture);
+    }
+
+    virtual void draw()
+    {
+        GLfloat vertices[] =
+        {
+            -0.5f,  0.5f, 0.0f,  // Position 0
+             0.0f,  0.0f,        // TexCoord 0
+            -0.5f, -0.5f, 0.0f,  // Position 1
+             0.0f,  1.0f,        // TexCoord 1
+             0.5f, -0.5f, 0.0f,  // Position 2
+             1.0f,  1.0f,        // TexCoord 2
+             0.5f,  0.5f, 0.0f,  // Position 3
+             1.0f,  0.0f         // TexCoord 3
+        };
+        GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices);
+        // Load the texture coordinate
+        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices + 3);
+
+        glEnableVertexAttribArray(mPositionLoc);
+        glEnableVertexAttribArray(mTexCoordLoc);
+
+        // Bind the texture
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+
+        // Set the texture sampler to texture unit to 0
+        glUniform1i(mSamplerLoc, 0);
+
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mTexCoordLoc;
+
+    // Sampler location
+    GLint mSamplerLoc;
+
+    // Texture handle
+    GLuint mTexture;
+};
+
+int main(int argc, char **argv)
+{
+    SimpleTexture2DSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/simple_texture_cubemap/SimpleTextureCubemap.cpp b/src/third_party/angle/samples/simple_texture_cubemap/SimpleTextureCubemap.cpp
new file mode 100644
index 0000000..b06c397
--- /dev/null
+++ b/src/third_party/angle/samples/simple_texture_cubemap/SimpleTextureCubemap.cpp
@@ -0,0 +1,138 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Simple_TextureCubemap.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+#include "texture_utils.h"
+#include "geometry_utils.h"
+
+class SimpleTextureCubemapSample : public SampleApplication
+{
+  public:
+    SimpleTextureCubemapSample()
+        : SampleApplication("SimpleTextureCubemap", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec4 a_position;
+            attribute vec3 a_normal;
+            varying vec3 v_normal;
+            void main()
+            {
+                gl_Position = a_position;
+                v_normal = a_normal;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec3 v_normal;
+            uniform samplerCube s_texture;
+            void main()
+            {
+                gl_FragColor = textureCube(s_texture, v_normal);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+        mNormalLoc = glGetAttribLocation(mProgram, "a_normal");
+
+        // Get the sampler locations
+        mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
+
+        // Load the texture
+        mTexture = CreateSimpleTextureCubemap();
+
+        // Generate the geometry data
+        CreateSphereGeometry(128, 0.75f, &mSphere);
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glCullFace(GL_BACK);
+        glEnable(GL_CULL_FACE);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+        glDeleteTextures(1, &mTexture);
+    }
+
+    virtual void draw()
+    {
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, mSphere.positions.data());
+        glEnableVertexAttribArray(mPositionLoc);
+
+        // Load the normal
+        glVertexAttribPointer(mNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, mSphere.normals.data());
+        glEnableVertexAttribArray(mNormalLoc);
+
+        // Bind the texture
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
+
+        // Set the texture sampler to texture unit to 0
+        glUniform1i(mSamplerLoc, 0);
+
+        glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mSphere.indices.size()),
+                       GL_UNSIGNED_SHORT, mSphere.indices.data());
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mNormalLoc;
+
+    // Sampler location
+    GLint mSamplerLoc;
+
+    // Texture handle
+    GLuint mTexture;
+
+    // Geometry data
+    SphereGeometry mSphere;
+};
+
+int main(int argc, char **argv)
+{
+    SimpleTextureCubemapSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/simple_vertex_shader/SimpleVertexShader.cpp b/src/third_party/angle/samples/simple_vertex_shader/SimpleVertexShader.cpp
new file mode 100644
index 0000000..2e92036
--- /dev/null
+++ b/src/third_party/angle/samples/simple_vertex_shader/SimpleVertexShader.cpp
@@ -0,0 +1,153 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Simple_VertexShader.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+
+#include "shader_utils.h"
+#include "texture_utils.h"
+#include "geometry_utils.h"
+#include "Matrix.h"
+
+#include <cmath>
+
+class SimpleVertexShaderSample : public SampleApplication
+{
+  public:
+    SimpleVertexShaderSample()
+        : SampleApplication("SimpleVertexShader", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            uniform mat4 u_mvpMatrix;
+            attribute vec4 a_position;
+            attribute vec2 a_texcoord;
+            varying vec2 v_texcoord;
+            void main()
+            {
+                gl_Position = u_mvpMatrix * a_position;
+                v_texcoord = a_texcoord;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec2 v_texcoord;
+            void main()
+            {
+                gl_FragColor = vec4(v_texcoord.x, v_texcoord.y, 1.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+        mTexcoordLoc = glGetAttribLocation(mProgram, "a_texcoord");
+
+        // Get the uniform locations
+        mMVPMatrixLoc = glGetUniformLocation(mProgram, "u_mvpMatrix");
+
+        // Generate the geometry data
+        GenerateCubeGeometry(0.5f, &mCube);
+
+        // Set an initial rotation
+        mRotation = 45.0f;
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glCullFace(GL_BACK);
+        glEnable(GL_CULL_FACE);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+    }
+
+    virtual void step(float dt, double totalTime)
+    {
+        mRotation = fmod(mRotation + (dt * 40.0f), 360.0f);
+
+        Matrix4 perspectiveMatrix = Matrix4::perspective(60.0f, float(getWindow()->getWidth()) / getWindow()->getHeight(),
+                                                         1.0f, 20.0f);
+
+        Matrix4 modelMatrix = Matrix4::translate(angle::Vector3(0.0f, 0.0f, -2.0f)) *
+                              Matrix4::rotate(mRotation, angle::Vector3(1.0f, 0.0f, 1.0f));
+
+        Matrix4 viewMatrix = Matrix4::identity();
+
+        Matrix4 mvpMatrix = perspectiveMatrix * viewMatrix * modelMatrix;
+
+        // Load the matrices
+        glUniformMatrix4fv(mMVPMatrixLoc, 1, GL_FALSE, mvpMatrix.data);
+    }
+
+    virtual void draw()
+    {
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, mCube.positions.data());
+        glEnableVertexAttribArray(mPositionLoc);
+
+        // Load the texcoord data
+        glVertexAttribPointer(mTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, mCube.texcoords.data());
+        glEnableVertexAttribArray(mTexcoordLoc);
+
+        // Draw the cube
+        glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mCube.indices.size()), GL_UNSIGNED_SHORT,
+                       mCube.indices.data());
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mTexcoordLoc;
+
+    // Uniform locations
+    GLuint mMVPMatrixLoc;
+
+    // Current rotation
+    float mRotation;
+
+    // Geometry data
+    CubeGeometry mCube;
+};
+
+int main(int argc, char **argv)
+{
+    SimpleVertexShaderSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/stencil_operations/StencilOperations.cpp b/src/third_party/angle/samples/stencil_operations/StencilOperations.cpp
new file mode 100644
index 0000000..98208bc
--- /dev/null
+++ b/src/third_party/angle/samples/stencil_operations/StencilOperations.cpp
@@ -0,0 +1,242 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Stencil_Test.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+
+class StencilOperationsSample : public SampleApplication
+{
+  public:
+    StencilOperationsSample()
+        : SampleApplication("StencilOperations", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec4 a_position;
+            void main()
+            {
+                gl_Position = a_position;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            uniform vec4 u_color;
+            void main()
+            {
+                gl_FragColor = u_color;
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+
+        // Get the sampler location
+        mColorLoc = glGetUniformLocation(mProgram, "u_color");
+
+        // Set the clear color
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        // Set the stencil clear value
+        glClearStencil(0x01);
+
+        // Set the depth clear value
+        glClearDepthf(0.75f);
+
+        // Enable the depth and stencil tests
+        glEnable(GL_DEPTH_TEST);
+        glEnable(GL_STENCIL_TEST);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+    }
+
+    virtual void draw()
+    {
+        GLfloat vertices[] =
+        {
+            -0.75f,  0.25f, 0.50f, // Quad #0
+            -0.25f,  0.25f, 0.50f,
+            -0.25f,  0.75f, 0.50f,
+            -0.75f,  0.75f, 0.50f,
+             0.25f,  0.25f, 0.90f, // Quad #1
+             0.75f,  0.25f, 0.90f,
+             0.75f,  0.75f, 0.90f,
+             0.25f,  0.75f, 0.90f,
+            -0.75f, -0.75f, 0.50f, // Quad #2
+            -0.25f, -0.75f, 0.50f,
+            -0.25f, -0.25f, 0.50f,
+            -0.75f, -0.25f, 0.50f,
+             0.25f, -0.75f, 0.50f, // Quad #3
+             0.75f, -0.75f, 0.50f,
+             0.75f, -0.25f, 0.50f,
+             0.25f, -0.25f, 0.50f,
+            -1.00f, -1.00f, 0.00f, // Big Quad
+             1.00f, -1.00f, 0.00f,
+             1.00f,  1.00f, 0.00f,
+            -1.00f,  1.00f, 0.00f,
+        };
+
+        GLubyte indices[][6] =
+        {
+            {  0,  1,  2,  0,  2,  3 }, // Quad #0
+            {  4,  5,  6,  4,  6,  7 }, // Quad #1
+            {  8,  9, 10,  8, 10, 11 }, // Quad #2
+            { 12, 13, 14, 12, 14, 15 }, // Quad #3
+            { 16, 17, 18, 16, 18, 19 }, // Big Quad
+        };
+
+        static const size_t testCount = 4;
+        GLfloat colors[testCount][4] =
+        {
+            { 1.0f, 0.0f, 0.0f, 1.0f },
+            { 0.0f, 1.0f, 0.0f, 1.0f },
+            { 0.0f, 0.0f, 1.0f, 1.0f },
+            { 1.0f, 1.0f, 0.0f, 0.0f },
+        };
+
+        GLuint stencilValues[testCount] =
+        {
+            0x7, // Result of test 0
+            0x0, // Result of test 1
+            0x2, // Result of test 2
+            0xff // Result of test 3.  We need to fill this value in at run-time
+        };
+
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color, depth, and stencil buffers.  At this point, the stencil
+        // buffer will be 0x1 for all pixels
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex data
+        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, vertices);
+        glEnableVertexAttribArray(mPositionLoc);
+
+        // Test 0:
+        //
+        // Initialize upper-left region.  In this case, the stencil-buffer values will
+        // be replaced because the stencil test for the rendered pixels will fail the
+        // stencil test, which is
+        //
+        //      ref   mask   stencil  mask
+        //    ( 0x7 & 0x3 ) < ( 0x1 & 0x7 )
+        //
+        // The value in the stencil buffer for these pixels will be 0x7.
+        glStencilFunc(GL_LESS, 0x7, 0x3);
+        glStencilOp(GL_REPLACE, GL_DECR, GL_DECR);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0]);
+
+        // Test 1:
+        //
+        // Initialize the upper-right region. Here, we'll decrement the stencil-buffer
+        // values where the stencil test passes but the depth test fails. The stencil test is
+        //
+        //      ref  mask    stencil  mask
+        //    ( 0x3 & 0x3 ) > ( 0x1 & 0x3 )
+        //
+        // but where the geometry fails the depth test. The stencil values for these pixels
+        // will be 0x0.
+        glStencilFunc(GL_GREATER, 0x3, 0x3);
+        glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1]);
+
+        // Test 2:
+        //
+        // Initialize the lower-left region.  Here we'll increment (with saturation) the
+        // stencil value where both the stencil and depth tests pass.  The stencil test for
+        // these pixels will be
+        //
+        //      ref  mask     stencil  mask
+        //    ( 0x1 & 0x3 ) == ( 0x1 & 0x3 )
+        //
+        // The stencil values for these pixels will be 0x2.
+        glStencilFunc(GL_EQUAL, 0x1, 0x3);
+        glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2]);
+
+        // Test 3:
+        //
+        // Finally, initialize the lower-right region.  We'll invert the stencil value
+        // where the stencil tests fails. The stencil test for these pixels will be
+        //
+        //      ref   mask    stencil  mask
+        //    ( 0x2 & 0x1 ) == ( 0x1 & 0x1 )
+        //
+        // The stencil value here will be set to ~((2^s-1) & 0x1), (with the 0x1 being
+        // from the stencil clear value), where 's' is the number of bits in the stencil
+        // buffer
+        glStencilFunc(GL_EQUAL, 0x2, 0x1);
+        glStencilOp(GL_INVERT, GL_KEEP, GL_KEEP);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3]);
+
+        // Since we don't know at compile time how many stencil bits are present, we'll
+        // query, and update the value correct value in the  stencilValues arrays for the
+        // fourth tests. We'll use this value later in rendering.
+        GLint stencilBitCount = 0;
+        glGetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
+        stencilValues[3] = ~(((1 << stencilBitCount) - 1) & 0x1) & 0xff;
+
+        // Use the stencil buffer for controlling where rendering will occur.  We disable
+        // writing to the stencil buffer so we can test against them without modifying
+        // the values we generated.
+        glStencilMask(0x0);
+
+        for (size_t i = 0; i < testCount; ++i)
+        {
+            glStencilFunc(GL_EQUAL, stencilValues[i], 0xff);
+            glUniform4fv(mColorLoc, 1, colors[i]);
+            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4]);
+        }
+
+        // Reset the stencil mask
+        glStencilMask(0xFF);
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+
+    // Uniform locations
+    GLint mColorLoc;
+};
+
+int main(int argc, char **argv)
+{
+    StencilOperationsSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/tex_redef_microbench/TexRedefMicroBench.cpp b/src/third_party/angle/samples/tex_redef_microbench/TexRedefMicroBench.cpp
new file mode 100644
index 0000000..111c2f1
--- /dev/null
+++ b/src/third_party/angle/samples/tex_redef_microbench/TexRedefMicroBench.cpp
@@ -0,0 +1,281 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Hello_Triangle.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+#include "texture_utils.h"
+
+#include <cstring>
+#include <iostream>
+
+// This sample demonstrates the differences in rendering efficiency when
+// drawing with already-created textures whose dimensions have been altered
+// versus drawing with newly created textures.
+//
+// In order to support GL's per-level texture creation semantics over the
+// D3D API in particular, which requires textures' full mip chains to be
+// created at texture object creation time, ANGLE maintains copies of the
+// constituent texture images in system memory until the texture is used in
+// a draw call, at which time, if the texture passes GL's mip completeness
+// rules, the D3D texture is created and the contents of the texture are
+// uploaded. Once the texture is created, redefinition of the dimensions or
+// format of the texture is costly-- a new D3D texture needs to be created,
+// and ANGLE may need to read the contents back into system memory.
+//
+// Creating an entirely new texture also requires that a new D3D texture be
+// created, but any overhead associated with tracking the already-present
+// texture images is eliminated, as it's a novel texture. This sample
+// demonstrates the contrast in draw call time between these two situations.
+//
+// The resizing & creation of a new texture is delayed until several frames
+// after startup, to eliminate draw time differences caused by caching of
+// rendering state subsequent to the first frame.
+
+class TexRedefBenchSample : public SampleApplication
+{
+  public:
+    TexRedefBenchSample()
+        : SampleApplication("Microbench", 1280, 1280),
+          mPixelsResize(nullptr),
+          mPixelsNewTex(nullptr),
+          mTimeFrame(false),
+          mFrameCount(0)
+    {
+    }
+
+    void defineSquareTexture2D(GLuint texId, GLsizei baseDimension, GLenum format, GLenum type, void* data)
+    {
+        glBindTexture(GL_TEXTURE_2D, texId);
+        GLsizei curDim = baseDimension;
+        GLuint level = 0;
+
+        while (curDim >= 1)
+        {
+            glTexImage2D(GL_TEXTURE_2D, level, format, curDim, curDim, 0, format, type, data);
+            curDim /= 2;
+            level++;
+        }
+    }
+
+    void createPixelData()
+    {
+        mPixelsResize = new GLubyte[512 * 512 * 4];
+        mPixelsNewTex = new GLubyte[512 * 512 * 4];
+        GLubyte *pixPtr0 = mPixelsResize;
+        GLubyte *pixPtr1 = mPixelsNewTex;
+        GLubyte zeroPix[] = { 0, 192, 192, 255 };
+        GLubyte onePix[] = { 192, 0, 0, 255 };
+        for (int i = 0; i < 512 * 512; ++i)
+        {
+            memcpy(pixPtr0, zeroPix, 4 * sizeof(GLubyte));
+            memcpy(pixPtr1, onePix, 4 * sizeof(GLubyte));
+            pixPtr0 += 4;
+            pixPtr1 += 4;
+        }
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec4 a_position;
+            attribute vec2 a_texCoord;
+            varying vec2 v_texCoord;
+            void main()
+            {
+                gl_Position = a_position;
+                v_texCoord = a_texCoord;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec2 v_texCoord;
+            uniform sampler2D s_texture;
+            void main()
+            {
+                gl_FragColor = texture2D(s_texture, v_texCoord);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+        mTexCoordLoc = glGetAttribLocation(mProgram, "a_texCoord");
+
+        // Get the sampler location
+        mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
+
+        // Generate texture IDs, and create texture 0
+        glGenTextures(3, mTextureIds);
+
+        createPixelData();
+        defineSquareTexture2D(mTextureIds[0], 256, GL_RGBA, GL_UNSIGNED_BYTE, mPixelsResize);
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        mOrigTimer = CreateTimer();
+        mResizeDrawTimer = CreateTimer();
+        mResizeDefineTimer = CreateTimer();
+        mNewTexDrawTimer = CreateTimer();
+        mNewTexDefineTimer = CreateTimer();
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+
+        delete [] mPixelsResize;
+        delete [] mPixelsNewTex;
+    }
+
+    virtual void draw()
+    {
+        GLfloat vertices[] =
+        {
+            -0.5f, 0.5f, 0.0f,  // Position 0
+            0.0f, 0.0f,        // TexCoord 0
+            -0.5f, -0.5f, 0.0f,  // Position 1
+            0.0f, 1.0f,        // TexCoord 1
+            0.5f, -0.5f, 0.0f,  // Position 2
+            1.0f, 1.0f,        // TexCoord 2
+            0.5f, 0.5f, 0.0f,  // Position 3
+            1.0f, 0.0f         // TexCoord 3
+        };
+        GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices);
+        // Load the texture coordinate
+        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices + 3);
+
+        glEnableVertexAttribArray(mPositionLoc);
+        glEnableVertexAttribArray(mTexCoordLoc);
+
+        // Bind the texture
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTextureIds[0]);
+
+        // Set the texture sampler to texture unit to 0
+        glUniform1i(mSamplerLoc, 0);
+
+        // We delay timing of texture resize/creation until after the first frame, as
+        // caching optimizations will reduce draw time for subsequent frames for reasons
+        // unreleated to texture creation. mTimeFrame is set to true on the fifth frame.
+        if (mTimeFrame)
+        {
+            mOrigTimer->start();
+        }
+
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+        
+        if (mTimeFrame)
+        { 
+            mOrigTimer->stop();
+            // This timer indicates draw time for an already-created texture resident on the GPU, which
+            // needs no updates. It will be faster than the other draws.
+            std::cout << "Original texture draw: " << mOrigTimer->getElapsedTime() * 1000 << "msec" << std::endl;
+
+            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+            // Now, change the texture dimensions of the original texture
+            mResizeDefineTimer->start();
+            defineSquareTexture2D(mTextureIds[0], 512, GL_RGBA, GL_UNSIGNED_BYTE, mPixelsResize);
+            mResizeDefineTimer->stop();
+
+            mResizeDrawTimer->start();
+            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+            mResizeDrawTimer->stop();
+            // This timer indicates draw time for a texture which has already been used in a draw, causing the
+            // underlying resource to be allocated, and then resized, requiring resource reallocation and
+            // related overhead.
+            std::cout << "Resized texture definition: " << mResizeDefineTimer->getElapsedTime() * 1000 << "msec" << std::endl;
+            std::cout << "Resized texture draw: " << mResizeDrawTimer->getElapsedTime() * 1000 << "msec" << std::endl;
+
+            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+            // Create texure at same dimensions we resized previous texture to
+            mNewTexDefineTimer->start();
+            defineSquareTexture2D(mTextureIds[1], 512, GL_RGBA, GL_UNSIGNED_BYTE, mPixelsNewTex);
+            mNewTexDefineTimer->stop();
+
+            mNewTexDrawTimer->start();
+            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+            mNewTexDrawTimer->stop();
+            // This timer indicates draw time for a texture newly created this frame. The underlying resource
+            // will need to be created, but because it has not previously been used, there is no already-resident
+            // texture object to manage. This draw is expected to be faster than the resized texture draw.
+            std::cout << "Newly created texture definition: " << mNewTexDefineTimer->getElapsedTime() * 1000 << "msec" << std::endl;
+            std::cout << "Newly created texture draw: " << mNewTexDrawTimer->getElapsedTime() * 1000 << "msec" << std::endl;
+        }
+
+        if (mFrameCount == 5)
+            mTimeFrame = true;
+        else
+            mTimeFrame = false;
+
+        mFrameCount++;
+    }
+
+  private:
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mTexCoordLoc;
+
+    // Sampler location
+    GLint mSamplerLoc;
+
+    // Texture handle
+    GLuint mTextureIds[2]; // 0: texture created, then resized
+                           // 1: texture newly created with TexImage
+
+    // Texture pixel data
+    GLubyte *mPixelsResize;
+    GLubyte *mPixelsNewTex;
+
+    Timer *mOrigTimer;
+    Timer *mResizeDrawTimer;
+    Timer *mResizeDefineTimer;
+    Timer *mNewTexDrawTimer;
+    Timer *mNewTexDefineTimer;
+    bool mTimeFrame;
+    unsigned int mFrameCount;
+};
+
+int main(int argc, char **argv)
+{
+    TexRedefBenchSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/texture_wrap/TextureWrap.cpp b/src/third_party/angle/samples/texture_wrap/TextureWrap.cpp
new file mode 100644
index 0000000..92bb31b
--- /dev/null
+++ b/src/third_party/angle/samples/texture_wrap/TextureWrap.cpp
@@ -0,0 +1,160 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on TextureWrap.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+#include "texture_utils.h"
+
+class TextureWrapSample : public SampleApplication
+{
+  public:
+    TextureWrapSample()
+        : SampleApplication("TextureWrap", 1280, 720)
+    {
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            uniform float u_offset;
+            attribute vec4 a_position;
+            attribute vec2 a_texCoord;
+            varying vec2 v_texCoord;
+            void main()
+            {
+                gl_Position = a_position;
+                gl_Position.x += u_offset;
+                v_texCoord = a_texCoord;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec2 v_texCoord;
+            uniform sampler2D s_texture;
+            void main()
+            {
+                gl_FragColor = texture2D(s_texture, v_texCoord);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        // Get the attribute locations
+        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+        mTexCoordLoc = glGetAttribLocation(mProgram, "a_texCoord");
+
+        // Get the sampler location
+        mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
+
+        // Get the offset location
+        mOffsetLoc = glGetUniformLocation(mProgram, "u_offset");
+
+        // Load the texture
+        mTexture = CreateMipMappedTexture2D();
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        glDeleteProgram(mProgram);
+    }
+
+    virtual void draw()
+    {
+        GLfloat vertices[] =
+        {
+            -0.3f,  0.3f, 0.0f, 1.0f, // Position 0
+            -1.0f, -1.0f,             // TexCoord 0 
+            -0.3f, -0.3f, 0.0f, 1.0f, // Position 1
+            -1.0f,  2.0f,             // TexCoord 1
+             0.3f, -0.3f, 0.0f, 1.0f, // Position 2
+             2.0f,  2.0f,             // TexCoord 2
+             0.3f,  0.3f, 0.0f, 1.0f, // Position 3
+             2.0f, -1.0f              // TexCoord 3
+        };
+        GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Load the vertex position
+        glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), vertices);
+        glEnableVertexAttribArray(mPositionLoc);
+
+        // Load the texture coordinate
+        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), vertices + 4);
+        glEnableVertexAttribArray(mTexCoordLoc);
+
+        // Set the sampler texture unit to 0
+        glUniform1i(mSamplerLoc, 0);
+
+        // Draw quad with repeat wrap mode
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+        glUniform1f(mOffsetLoc, -0.7f);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+        // Draw quad with clamp to edge wrap mode
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glUniform1f(mOffsetLoc, 0.0f);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+        // Draw quad with mirrored repeat
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+        glUniform1f(mOffsetLoc, 0.7f);
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+    }
+
+private:
+    // Handle to a program object
+     GLuint mProgram;
+
+     // Attribute locations
+     GLint mPositionLoc;
+     GLint mTexCoordLoc;
+
+     // Sampler location
+     GLint mSamplerLoc;
+
+     // Offset location
+     GLint mOffsetLoc;
+
+     // Texture handle
+     GLuint mTexture;
+};
+
+int main(int argc, char **argv)
+{
+    TextureWrapSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/samples/translator/essl_to_glsl.vcproj b/src/third_party/angle/samples/translator/essl_to_glsl.vcproj
deleted file mode 100644
index 0a0c097..0000000
--- a/src/third_party/angle/samples/translator/essl_to_glsl.vcproj
+++ /dev/null
@@ -1,193 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>

-<VisualStudioProject

-	ProjectType="Visual C++"

-	Version="9.00"

-	Name="essl_to_glsl"

-	ProjectGUID="{EADEBCCD-65ED-45D1-9E06-949A21EBAB9E}"

-	RootNamespace="essl_to_glsl"

-	Keyword="Win32Proj"

-	TargetFrameworkVersion="196613"

-	>

-	<Platforms>

-		<Platform

-			Name="Win32"

-		/>

-	</Platforms>

-	<ToolFiles>

-	</ToolFiles>

-	<Configurations>

-		<Configuration

-			Name="Debug|Win32"

-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

-			IntermediateDirectory="$(ConfigurationName)"

-			ConfigurationType="1"

-			CharacterSet="1"

-			>

-			<Tool

-				Name="VCPreBuildEventTool"

-			/>

-			<Tool

-				Name="VCCustomBuildTool"

-			/>

-			<Tool

-				Name="VCXMLDataGeneratorTool"

-			/>

-			<Tool

-				Name="VCWebServiceProxyGeneratorTool"

-			/>

-			<Tool

-				Name="VCMIDLTool"

-			/>

-			<Tool

-				Name="VCCLCompilerTool"

-				Optimization="0"

-				AdditionalIncludeDirectories="../../include"

-				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"

-				MinimalRebuild="true"

-				BasicRuntimeChecks="3"

-				RuntimeLibrary="1"

-				UsePrecompiledHeader="0"

-				WarningLevel="3"

-				DebugInformationFormat="4"

-			/>

-			<Tool

-				Name="VCManagedResourceCompilerTool"

-			/>

-			<Tool

-				Name="VCResourceCompilerTool"

-			/>

-			<Tool

-				Name="VCPreLinkEventTool"

-			/>

-			<Tool

-				Name="VCLinkerTool"

-				LinkIncremental="2"

-				GenerateDebugInformation="true"

-				SubSystem="1"

-				TargetMachine="1"

-			/>

-			<Tool

-				Name="VCALinkTool"

-			/>

-			<Tool

-				Name="VCManifestTool"

-			/>

-			<Tool

-				Name="VCXDCMakeTool"

-			/>

-			<Tool

-				Name="VCBscMakeTool"

-			/>

-			<Tool

-				Name="VCFxCopTool"

-			/>

-			<Tool

-				Name="VCAppVerifierTool"

-			/>

-			<Tool

-				Name="VCPostBuildEventTool"

-			/>

-		</Configuration>

-		<Configuration

-			Name="Release|Win32"

-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

-			IntermediateDirectory="$(ConfigurationName)"

-			ConfigurationType="1"

-			CharacterSet="1"

-			WholeProgramOptimization="1"

-			>

-			<Tool

-				Name="VCPreBuildEventTool"

-			/>

-			<Tool

-				Name="VCCustomBuildTool"

-			/>

-			<Tool

-				Name="VCXMLDataGeneratorTool"

-			/>

-			<Tool

-				Name="VCWebServiceProxyGeneratorTool"

-			/>

-			<Tool

-				Name="VCMIDLTool"

-			/>

-			<Tool

-				Name="VCCLCompilerTool"

-				Optimization="2"

-				EnableIntrinsicFunctions="true"

-				AdditionalIncludeDirectories="../../include"

-				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"

-				RuntimeLibrary="0"

-				EnableFunctionLevelLinking="true"

-				UsePrecompiledHeader="0"

-				WarningLevel="3"

-				DebugInformationFormat="3"

-			/>

-			<Tool

-				Name="VCManagedResourceCompilerTool"

-			/>

-			<Tool

-				Name="VCResourceCompilerTool"

-			/>

-			<Tool

-				Name="VCPreLinkEventTool"

-			/>

-			<Tool

-				Name="VCLinkerTool"

-				LinkIncremental="1"

-				GenerateDebugInformation="true"

-				SubSystem="1"

-				OptimizeReferences="2"

-				EnableCOMDATFolding="2"

-				TargetMachine="1"

-			/>

-			<Tool

-				Name="VCALinkTool"

-			/>

-			<Tool

-				Name="VCManifestTool"

-			/>

-			<Tool

-				Name="VCXDCMakeTool"

-			/>

-			<Tool

-				Name="VCBscMakeTool"

-			/>

-			<Tool

-				Name="VCFxCopTool"

-			/>

-			<Tool

-				Name="VCAppVerifierTool"

-			/>

-			<Tool

-				Name="VCPostBuildEventTool"

-			/>

-		</Configuration>

-	</Configurations>

-	<References>

-	</References>

-	<Files>

-		<Filter

-			Name="Source Files"

-			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"

-			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"

-			>

-			<File

-				RelativePath="..\..\src\common\debug.cpp"

-				>

-			</File>

-			<File

-				RelativePath=".\translator.cpp"

-				>

-			</File>

-		</Filter>

-		<Filter

-			Name="Header Files"

-			Filter="h;hpp;hxx;hm;inl;inc;xsd"

-			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"

-			>

-		</Filter>

-	</Files>

-	<Globals>

-	</Globals>

-</VisualStudioProject>

diff --git a/src/third_party/angle/samples/translator/essl_to_hlsl.vcxproj b/src/third_party/angle/samples/translator/essl_to_hlsl.vcxproj
deleted file mode 100644
index d7bbd8c..0000000
--- a/src/third_party/angle/samples/translator/essl_to_hlsl.vcxproj
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{E12EA115-EBC7-47C2-B651-30A0CE986025}</ProjectGuid>

-    <RootNamespace>essl_to_hlsl</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>../../include;../../src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-      <AdditionalIncludeDirectories>../../include;../../src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Console</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="..\..\src\common\debug.cpp" />

-    <ClCompile Include="translator.cpp" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\..\src\compiler\preprocessor\preprocessor.vcxproj">

-      <Project>{fbe32df3-0fb0-4f2f-a424-2c21bd7bc325}</Project>

-    </ProjectReference>

-    <ProjectReference Include="..\..\src\compiler\translator_common.vcxproj">

-      <Project>{5b3a6db8-1e7e-40d7-92b9-da8aae619fad}</Project>

-    </ProjectReference>

-    <ProjectReference Include="..\..\src\compiler\translator_hlsl.vcxproj">

-      <Project>{5620f0e4-6c43-49bc-a178-b804e1a0c3a7}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-      <Private>true</Private>

-      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>

-      <LinkLibraryDependencies>true</LinkLibraryDependencies>

-      <UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/translator/essl_to_hlsl.vcxproj.filters b/src/third_party/angle/samples/translator/essl_to_hlsl.vcxproj.filters
deleted file mode 100644
index b8a21af..0000000
--- a/src/third_party/angle/samples/translator/essl_to_hlsl.vcxproj.filters
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup>

-    <Filter Include="Source Files">

-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

-    </Filter>

-    <Filter Include="Header Files">

-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

-    </Filter>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="..\..\src\common\debug.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="translator.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-  </ItemGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/samples/translator/translator.cpp b/src/third_party/angle/samples/translator/translator.cpp
deleted file mode 100644
index 9822771..0000000
--- a/src/third_party/angle/samples/translator/translator.cpp
+++ /dev/null
@@ -1,387 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "GLSLANG/ShaderLang.h"
-
-#include <assert.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <vector>
-
-//
-// Return codes from main.
-//
-enum TFailCode {
-    ESuccess = 0,
-    EFailUsage,
-    EFailCompile,
-    EFailCompilerCreate,
-};
-
-static void usage();
-static ShShaderType FindShaderType(const char* fileName);
-static bool CompileFile(char* fileName, ShHandle compiler, int compileOptions);
-static void LogMsg(const char* msg, const char* name, const int num, const char* logName);
-static void PrintActiveVariables(ShHandle compiler, ShShaderInfo varType, bool mapLongVariableNames);
-
-// If NUM_SOURCE_STRINGS is set to a value > 1, the input file data is
-// broken into that many chunks.
-const unsigned int NUM_SOURCE_STRINGS = 2;
-typedef std::vector<char*> ShaderSource;
-static bool ReadShaderSource(const char* fileName, ShaderSource& source);
-static void FreeShaderSource(ShaderSource& source);
-
-//
-// Set up the per compile resources
-//
-void GenerateResources(ShBuiltInResources* resources)
-{
-    ShInitBuiltInResources(resources);
-
-    resources->MaxVertexAttribs = 8;
-    resources->MaxVertexUniformVectors = 128;
-    resources->MaxVaryingVectors = 8;
-    resources->MaxVertexTextureImageUnits = 0;
-    resources->MaxCombinedTextureImageUnits = 8;
-    resources->MaxTextureImageUnits = 8;
-    resources->MaxFragmentUniformVectors = 16;
-    resources->MaxDrawBuffers = 1;
-
-    resources->OES_standard_derivatives = 0;
-    resources->OES_EGL_image_external = 0;
-}
-
-int main(int argc, char* argv[])
-{
-    TFailCode failCode = ESuccess;
-
-    int compileOptions = 0;
-    int numCompiles = 0;
-    ShHandle vertexCompiler = 0;
-    ShHandle fragmentCompiler = 0;
-    char* buffer = 0;
-    size_t bufferLen = 0;
-    int numAttribs = 0, numUniforms = 0;
-    ShShaderSpec spec = SH_GLES2_SPEC;
-    ShShaderOutput output = SH_ESSL_OUTPUT;
-
-    ShInitialize();
-
-    ShBuiltInResources resources;
-    GenerateResources(&resources);
-
-    argc--;
-    argv++;
-    for (; (argc >= 1) && (failCode == ESuccess); argc--, argv++) {
-        if (argv[0][0] == '-') {
-            switch (argv[0][1]) {
-            case 'i': compileOptions |= SH_INTERMEDIATE_TREE; break;
-            case 'm': compileOptions |= SH_MAP_LONG_VARIABLE_NAMES; break;
-            case 'o': compileOptions |= SH_OBJECT_CODE; break;
-            case 'u': compileOptions |= SH_ATTRIBUTES_UNIFORMS; break;
-            case 'l': compileOptions |= SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX; break;
-            case 'e': compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; break;
-            case 'd': compileOptions |= SH_DEPENDENCY_GRAPH; break;
-            case 't': compileOptions |= SH_TIMING_RESTRICTIONS; break;
-            case 's':
-                if (argv[0][2] == '=') {
-                    switch (argv[0][3]) {
-                        case 'e': spec = SH_GLES2_SPEC; break;
-                        case 'w': spec = SH_WEBGL_SPEC; break;
-                        case 'c': spec = SH_CSS_SHADERS_SPEC; break;
-                        default: failCode = EFailUsage;
-                    }                    
-                } else {
-                    failCode = EFailUsage;
-                }
-                break;
-            case 'b':
-                if (argv[0][2] == '=') {
-                    switch (argv[0][3]) {
-                    case 'e': output = SH_ESSL_OUTPUT; break;
-                    case 'g': output = SH_GLSL_OUTPUT; break;
-                    case 'h':
-                        if (argv[0][4] == '1' && argv[0][5] == '1')
-                        {
-                            output = SH_HLSL11_OUTPUT;
-                        }
-                        else
-                        {
-                            output = SH_HLSL9_OUTPUT;
-                        }
-                        break;
-                    default: failCode = EFailUsage;
-                    }
-                } else {
-                    failCode = EFailUsage;
-                }
-                break;
-            case 'x':
-                if (argv[0][2] == '=') {
-                    switch (argv[0][3]) {
-                    case 'i': resources.OES_EGL_image_external = 1; break;
-                    case 'd': resources.OES_standard_derivatives = 1; break;
-                    case 'r': resources.ARB_texture_rectangle = 1; break;
-                    default: failCode = EFailUsage;
-                    }
-                } else {
-                    failCode = EFailUsage;
-                }
-                break;
-            default: failCode = EFailUsage;
-            }
-        } else {
-            ShHandle compiler = 0;
-            switch (FindShaderType(argv[0])) {
-            case SH_VERTEX_SHADER:
-                if (vertexCompiler == 0)
-                    vertexCompiler = ShConstructCompiler(
-                        SH_VERTEX_SHADER, spec, output, &resources);
-                compiler = vertexCompiler;
-                break;
-            case SH_FRAGMENT_SHADER:
-                if (fragmentCompiler == 0)
-                    fragmentCompiler = ShConstructCompiler(
-                        SH_FRAGMENT_SHADER, spec, output, &resources);
-                compiler = fragmentCompiler;
-                break;
-            default: break;
-            }
-            if (compiler) {
-              bool compiled = CompileFile(argv[0], compiler, compileOptions);
-
-              LogMsg("BEGIN", "COMPILER", numCompiles, "INFO LOG");
-              ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &bufferLen);
-              buffer = (char*) realloc(buffer, bufferLen * sizeof(char));
-              ShGetInfoLog(compiler, buffer);
-              puts(buffer);
-              LogMsg("END", "COMPILER", numCompiles, "INFO LOG");
-              printf("\n\n");
-
-              if (compiled && (compileOptions & SH_OBJECT_CODE)) {
-                  LogMsg("BEGIN", "COMPILER", numCompiles, "OBJ CODE");
-                  ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &bufferLen);
-                  buffer = (char*) realloc(buffer, bufferLen * sizeof(char));
-                  ShGetObjectCode(compiler, buffer);
-                  puts(buffer);
-                  LogMsg("END", "COMPILER", numCompiles, "OBJ CODE");
-                  printf("\n\n");
-              }
-              if (compiled && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
-                  LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE ATTRIBS");
-                  PrintActiveVariables(compiler, SH_ACTIVE_ATTRIBUTES, (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) != 0);
-                  LogMsg("END", "COMPILER", numCompiles, "ACTIVE ATTRIBS");
-                  printf("\n\n");
-
-                  LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE UNIFORMS");
-                  PrintActiveVariables(compiler, SH_ACTIVE_UNIFORMS, (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) != 0);
-                  LogMsg("END", "COMPILER", numCompiles, "ACTIVE UNIFORMS");
-                  printf("\n\n");
-              }
-              if (!compiled)
-                  failCode = EFailCompile;
-              ++numCompiles;
-            } else {
-                failCode = EFailCompilerCreate;
-            }
-        }
-    }
-
-    if ((vertexCompiler == 0) && (fragmentCompiler == 0))
-        failCode = EFailUsage;
-    if (failCode == EFailUsage)
-        usage();
-
-    if (vertexCompiler)
-        ShDestruct(vertexCompiler);
-    if (fragmentCompiler)
-        ShDestruct(fragmentCompiler);
-    if (buffer)
-        free(buffer);
-    ShFinalize();
-
-    return failCode;
-}
-
-//
-//   print usage to stdout
-//
-void usage()
-{
-    printf("Usage: translate [-i -m -o -u -l -e -b=e -b=g -b=h -x=i -x=d] file1 file2 ...\n"
-        "Where: filename : filename ending in .frag or .vert\n"
-        "       -i       : print intermediate tree\n"
-        "       -m       : map long variable names\n"
-        "       -o       : print translated code\n"
-        "       -u       : print active attribs and uniforms\n"
-        "       -l       : unroll for-loops with integer indices\n"
-        "       -e       : emulate certain built-in functions (workaround for driver bugs)\n"
-        "       -t       : enforce experimental timing restrictions\n"
-        "       -d       : print dependency graph used to enforce timing restrictions\n"
-        "       -s=e     : use GLES2 spec (this is by default)\n"
-        "       -s=w     : use WebGL spec\n"
-        "       -s=c     : use CSS Shaders spec\n"
-        "       -b=e     : output GLSL ES code (this is by default)\n"
-        "       -b=g     : output GLSL code\n"
-        "       -b=h9    : output HLSL9 code\n"
-        "       -b=h11   : output HLSL11 code\n"
-        "       -x=i     : enable GL_OES_EGL_image_external\n"
-        "       -x=d     : enable GL_OES_EGL_standard_derivatives\n"
-        "       -x=r     : enable ARB_texture_rectangle\n");
-}
-
-//
-//   Deduce the shader type from the filename.  Files must end in one of the
-//   following extensions:
-//
-//   .frag*    = fragment shader
-//   .vert*    = vertex shader
-//
-ShShaderType FindShaderType(const char* fileName)
-{
-    assert(fileName);
-
-    const char* ext = strrchr(fileName, '.');
-
-    if (ext && strcmp(ext, ".sl") == 0)
-        for (; ext > fileName && ext[0] != '.'; ext--);
-
-    ext = strrchr(fileName, '.');
-    if (ext) {
-        if (strncmp(ext, ".frag", 4) == 0) return SH_FRAGMENT_SHADER;
-        if (strncmp(ext, ".vert", 4) == 0) return SH_VERTEX_SHADER;
-    }
-
-    return SH_FRAGMENT_SHADER;
-}
-
-//
-//   Read a file's data into a string, and compile it using ShCompile
-//
-bool CompileFile(char* fileName, ShHandle compiler, int compileOptions)
-{
-    ShaderSource source;
-    if (!ReadShaderSource(fileName, source))
-        return false;
-
-    int ret = ShCompile(compiler, &source[0], source.size(), compileOptions);
-
-    FreeShaderSource(source);
-    return ret ? true : false;
-}
-
-void LogMsg(const char* msg, const char* name, const int num, const char* logName)
-{
-    printf("#### %s %s %d %s ####\n", msg, name, num, logName);
-}
-
-void PrintActiveVariables(ShHandle compiler, ShShaderInfo varType, bool mapLongVariableNames)
-{
-    size_t nameSize = 0;
-    switch (varType) {
-        case SH_ACTIVE_ATTRIBUTES:
-            ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &nameSize);
-            break;
-        case SH_ACTIVE_UNIFORMS:
-            ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &nameSize);
-            break;
-        default: assert(0);
-    }
-    if (nameSize <= 1) return;
-    char* name = new char[nameSize];
-
-    char* mappedName = NULL;
-    if (mapLongVariableNames) {
-        size_t mappedNameSize = 0;
-        ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameSize);
-        mappedName = new char[mappedNameSize];
-    }
-
-    size_t activeVars = 0;
-    int size = 0;
-    ShDataType type = SH_NONE;
-    const char* typeName = NULL;
-    ShGetInfo(compiler, varType, &activeVars);
-    for (size_t i = 0; i < activeVars; ++i) {
-        switch (varType) {
-            case SH_ACTIVE_ATTRIBUTES:
-                ShGetActiveAttrib(compiler, static_cast<int>(i), NULL, &size, &type, name, mappedName);
-                break;
-            case SH_ACTIVE_UNIFORMS:
-                ShGetActiveUniform(compiler, static_cast<int>(i), NULL, &size, &type, name, mappedName);
-                break;
-            default: assert(0);
-        }
-        switch (type) {
-            case SH_FLOAT: typeName = "GL_FLOAT"; break;
-            case SH_FLOAT_VEC2: typeName = "GL_FLOAT_VEC2"; break;
-            case SH_FLOAT_VEC3: typeName = "GL_FLOAT_VEC3"; break;
-            case SH_FLOAT_VEC4: typeName = "GL_FLOAT_VEC4"; break;
-            case SH_INT: typeName = "GL_INT"; break;
-            case SH_INT_VEC2: typeName = "GL_INT_VEC2"; break;
-            case SH_INT_VEC3: typeName = "GL_INT_VEC3"; break;
-            case SH_INT_VEC4: typeName = "GL_INT_VEC4"; break;
-            case SH_BOOL: typeName = "GL_BOOL"; break;
-            case SH_BOOL_VEC2: typeName = "GL_BOOL_VEC2"; break;
-            case SH_BOOL_VEC3: typeName = "GL_BOOL_VEC3"; break;
-            case SH_BOOL_VEC4: typeName = "GL_BOOL_VEC4"; break;
-            case SH_FLOAT_MAT2: typeName = "GL_FLOAT_MAT2"; break;
-            case SH_FLOAT_MAT3: typeName = "GL_FLOAT_MAT3"; break;
-            case SH_FLOAT_MAT4: typeName = "GL_FLOAT_MAT4"; break;
-            case SH_SAMPLER_2D: typeName = "GL_SAMPLER_2D"; break;
-            case SH_SAMPLER_CUBE: typeName = "GL_SAMPLER_CUBE"; break;
-            case SH_SAMPLER_EXTERNAL_OES: typeName = "GL_SAMPLER_EXTERNAL_OES"; break;
-            default: assert(0);
-        }
-        printf("%u: name:%s type:%s size:%d", i, name, typeName, size);
-        if (mapLongVariableNames)
-            printf(" mapped name:%s", mappedName);
-        printf("\n");
-    }
-    delete [] name;
-    if (mappedName)
-        delete [] mappedName;
-}
-
-static bool ReadShaderSource(const char* fileName, ShaderSource& source) {
-    FILE* in = fopen(fileName, "rb");
-    if (!in) {
-        printf("Error: unable to open input file: %s\n", fileName);
-        return false;
-    }
-
-    // Obtain file size.
-    fseek(in, 0, SEEK_END);
-    int count = ftell(in);
-    rewind(in);
-
-    int len = (int)ceil((float)count / (float)NUM_SOURCE_STRINGS);
-    source.reserve(NUM_SOURCE_STRINGS);
-    // Notice the usage of do-while instead of a while loop here.
-    // It is there to handle empty files in which case a single empty
-    // string is added to vector.
-    do {
-        char* data = new char[len + 1];
-        int nread = fread(data, 1, len, in);
-        data[nread] = '\0';
-        source.push_back(data);
-
-        count -= nread;
-    } while (count > 0);
-
-    fclose(in);
-    return true;
-}
-
-static void FreeShaderSource(ShaderSource& source) {
-    for (ShaderSource::size_type i = 0; i < source.size(); ++i) {
-        delete [] source[i];
-    }
-    source.clear();
-}
-
diff --git a/src/third_party/angle/samples/tri_fan_microbench/TriFanMicroBench.cpp b/src/third_party/angle/samples/tri_fan_microbench/TriFanMicroBench.cpp
new file mode 100644
index 0000000..32137bb
--- /dev/null
+++ b/src/third_party/angle/samples/tri_fan_microbench/TriFanMicroBench.cpp
@@ -0,0 +1,243 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//            Based on Hello_Triangle.c from
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+
+#include "SampleApplication.h"
+#include "shader_utils.h"
+
+#include <cstring>
+#include <iostream>
+
+// This small sample compares the per-frame render time for a series of 
+// squares drawn with TRIANGLE_FANS versus squares drawn with TRIANGLES.
+// To exacerbate differences between the two, we use a large collection
+// of short buffers with pre-translated vertex data.
+
+class TriangleFanBenchSample : public SampleApplication
+{
+  public:
+    TriangleFanBenchSample()
+        : SampleApplication("Microbench", 1280, 1280),
+          mFrameCount(0)
+    {
+    }
+
+    void createVertexBuffers()
+    {
+        const unsigned int slices = 8;
+        const unsigned int numFanVertices = slices + 2;
+        const unsigned int fanFloats = numFanVertices * 3;
+
+        mNumFanVerts = numFanVertices;
+
+        const GLfloat halfDim = 0.0625;
+        GLfloat fanVertices[] =
+            {    0.0f,     0.0f,  0.0f,  // center
+             -halfDim, -halfDim,  0.0f,  // LL
+             -halfDim,     0.0f,  0.0f,  // CL
+             -halfDim,  halfDim,  0.0f,  // UL
+                 0.0f,  halfDim,  0.0f,  // UC
+              halfDim,  halfDim,  0.0f,  // UR
+              halfDim,     0.0f,  0.0f,  // CR
+              halfDim, -halfDim,  0.0f,  // LR
+                 0.0f, -halfDim,  0.0f,  // LC
+             -halfDim, -halfDim,  0.0f   // LL (closes the fan)
+            };
+
+        const GLfloat xMin = -1.0f; // We leave viewport/worldview untransformed in this sample
+        const GLfloat xMax = 1.0f;
+        const GLfloat yMin = -1.0f;
+        //const GLfloat yMax = 1.0f;
+
+        glGenBuffers(mNumSquares, mFanBufId);
+
+        GLfloat xOffset = xMin;
+        GLfloat yOffset = yMin;
+        for (unsigned int i = 0; i < mNumSquares; ++i)
+        {
+            GLfloat tempVerts[fanFloats] = { 0 };
+            for (unsigned int j = 0; j < numFanVertices; ++j)
+            {
+                tempVerts[j * 3] = fanVertices[j * 3] + xOffset;
+                tempVerts[j * 3 + 1] = fanVertices[j * 3 + 1] + yOffset;
+                tempVerts[j * 3 + 2] = 0.0f;
+            }
+
+            glBindBuffer(GL_ARRAY_BUFFER, mFanBufId[i]);
+            glBufferData(GL_ARRAY_BUFFER, fanFloats * sizeof(GLfloat), tempVerts, GL_STATIC_DRAW);
+
+            xOffset += 2 * halfDim;
+            if (xOffset > xMax)
+            {
+                xOffset = xMin;
+                yOffset += 2 * halfDim;
+            }
+        }
+
+        const unsigned int numTriVertices = slices * 3;
+        const unsigned int triFloats = numTriVertices * 3;
+        GLfloat triVertices[triFloats];
+        GLfloat *triPointer = triVertices;
+
+        mNumTriVerts = numTriVertices;
+
+        for (unsigned int i = 0; i < slices; ++i)
+        {
+            memcpy(triPointer, fanVertices, 3 * sizeof(GLfloat)); // copy center point as first vertex for this slice
+            triPointer += 3;
+            for (unsigned int j = 1; j < 3; ++j)
+            {
+                GLfloat *vertex = &(fanVertices[(i + j) * 3]); // copy two outer vertices for this point
+                memcpy(triPointer, vertex, 3 * sizeof(GLfloat));
+                triPointer += 3;
+            }
+        }
+
+        //GLfloat triVertices2[triFloats];
+        glGenBuffers(mNumSquares, mTriBufId);
+        xOffset = xMin;
+        yOffset = yMin;
+
+        for (unsigned int i = 0; i < mNumSquares; ++i)
+        {
+            triPointer = triVertices;
+            GLfloat tempVerts[triFloats];
+            for (unsigned int j = 0; j < numTriVertices; ++j)
+            {
+                tempVerts[j * 3] = triPointer[0] + xOffset;
+                tempVerts[j * 3 + 1] = triPointer[1] + yOffset;
+                tempVerts[j * 3 + 2] = 0.0f;
+                triPointer += 3;
+            }
+
+            glBindBuffer(GL_ARRAY_BUFFER, mTriBufId[i]);
+            glBufferData(GL_ARRAY_BUFFER, triFloats * sizeof(GLfloat), tempVerts, GL_STATIC_DRAW);
+            xOffset += 2 * halfDim;
+            if (xOffset > xMax)
+            {
+                yOffset += 2 * halfDim;
+                xOffset = xMin;
+            }
+        }
+    }
+
+    virtual bool initialize()
+    {
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec4 vPosition;
+            void main()
+            {
+                gl_Position = vPosition;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            void main()
+            {
+                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        if (!mProgram)
+        {
+            return false;
+        }
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+        createVertexBuffers();
+
+        mFanTimer = CreateTimer();
+        mTriTimer = CreateTimer();
+        mFanTotalTime = 0;
+        mTriTotalTime = 0;
+
+        return true;
+    }
+
+    virtual void destroy()
+    {
+        std::cout << "Total draw time using TRIANGLE_FAN: " << mFanTotalTime << "ms (" << (float)mFanTotalTime / (float)mFrameCount << " average per frame)" << std::endl;
+        std::cout << "Total draw time using TRIANGLES: " << mTriTotalTime << "ms (" << (float)mTriTotalTime / (float)mFrameCount << " average per frame)" << std::endl;
+        glDeleteProgram(mProgram);
+    }
+
+    virtual void draw()
+    {
+        // Set the viewport
+        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+
+        // Bind the vertex data
+        glEnableVertexAttribArray(0);
+
+        // Draw using triangle fans, stored in VBO
+        mFanTimer->start();
+        for (unsigned i = 0; i < mNumSquares; ++i)
+        {
+            glBindBuffer(GL_ARRAY_BUFFER, mFanBufId[i]);
+            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+            glDrawArrays(GL_TRIANGLE_FAN, 0, mNumFanVerts);
+        }
+        mFanTimer->stop();
+
+        mFanTotalTime += static_cast<unsigned int>(mFanTimer->getElapsedTime() * 1000); // convert from usec to msec when accumulating
+
+        // Clear to eliminate driver-side gains from occlusion
+        glClear(GL_COLOR_BUFFER_BIT);
+        
+        // Draw using triangles, stored in VBO
+        mTriTimer->start();
+        for (unsigned i = 1; i < mNumSquares; ++i)
+        {
+            glBindBuffer(GL_ARRAY_BUFFER, mTriBufId[i]);
+            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+            glDrawArrays(GL_TRIANGLES, 0, mNumTriVerts);
+        }
+        mTriTimer->stop();
+
+        mTriTotalTime += static_cast<unsigned int>(mTriTimer->getElapsedTime() * 1000); // convert from usec to msec when accumulating
+
+        mFrameCount++;
+    }
+
+  private:
+    static const unsigned int mNumSquares = 289;
+    unsigned int mNumFanVerts;
+    unsigned int mNumTriVerts;
+    GLuint mProgram;
+    GLuint mFanBufId[mNumSquares];
+    GLuint mTriBufId[mNumSquares];
+
+    Timer *mFanTimer;
+    Timer *mTriTimer;
+    unsigned int mFrameCount;
+    unsigned int mTriTotalTime;
+    unsigned int mFanTotalTime;
+};
+
+int main(int argc, char **argv)
+{
+    TriangleFanBenchSample app;
+    return app.run();
+}
diff --git a/src/third_party/angle/scripts/bmp_to_nv12.py b/src/third_party/angle/scripts/bmp_to_nv12.py
new file mode 100644
index 0000000..facb43e
--- /dev/null
+++ b/src/third_party/angle/scripts/bmp_to_nv12.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+#
+# Copyright 2016 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.
+#
+# bmp_to_nv12.py:
+#   Script to convert a simple BMP file to an NV12 format. Used to create
+#   test images for the NV12 texture stream end to end tests
+
+import sys
+import struct
+
+if len(sys.argv) != 4:
+    print("Usage: bmp_to_nv12.py input output prefix")
+    exit(0)
+
+bmp_file = open(sys.argv[1], "rb")
+
+magic = bmp_file.read(2)
+if (magic != "BM"):
+    print("Invalid BMP magic")
+    exit(1)
+
+file_size, = struct.unpack("I", bmp_file.read(4))
+
+# eat reserved bytes
+bmp_file.read(4)
+
+offset, = struct.unpack("I", bmp_file.read(4))
+
+headersize, = struct.unpack("I", bmp_file.read(4))
+width, = struct.unpack("i", bmp_file.read(4))
+height, = struct.unpack("i", bmp_file.read(4))
+planes, = struct.unpack("H", bmp_file.read(2))
+bpp, = struct.unpack("H", bmp_file.read(2))
+compression, = struct.unpack("i", bmp_file.read(4))
+image_size, = struct.unpack("i", bmp_file.read(4))
+
+if (bpp != 24 or compression != 0):
+    print("Unsupported BMP file")
+    bmp_file.close()
+    exit(1)
+
+bmp_file.seek(offset, 0)
+pixels = bmp_file.read(width * height * 3)
+bmp_file.close()
+
+# convert to YUV 4:4:4
+converted_pixels = bytearray(pixels)
+for i in range(0, width * height):
+    R, = struct.unpack("B", pixels[i*3+2])
+    G, = struct.unpack("B", pixels[i*3+1])
+    B, = struct.unpack("B", pixels[i*3])
+    converted_pixels[i*3] = ((66*R + 129*G + 25*B + 128) >> 8) + 16
+    converted_pixels[i*3+1] = ((-38*R - 74*G + 112*B + 128) >> 8) + 128
+    converted_pixels[i*3+2] = ((112*R - 94*G - 18*B + 128) >> 8) + 128
+
+# downsample to packed UV buffer
+uv_buffer = bytearray(width * height / 2)
+for i in range(0, width * height / 2, 2):
+    U1 = converted_pixels[((((i / width) * 2) * width) + (i % width)) * 3 + 1]
+    U2 = converted_pixels[((((i / width) * 2) * width) + width + (i % width)) * 3 + 1]
+    V1 = converted_pixels[((((i / width) * 2) * width) + (i % width)) * 3 + 2]
+    V2 = converted_pixels[((((i / width) * 2) * width) + width + (i % width)) * 3 + 2]
+    uv_buffer[i] = (U1 + U2) / 2
+    uv_buffer[i + 1] = (V1 + V2) / 2
+
+# extract the Y buffer
+y_buffer = bytearray(width * height)
+for i in range(0, width * height):
+    y_buffer[i] = converted_pixels[i * 3]
+
+# write out the file as a C header
+nv12_file = open(sys.argv[2], "w")
+nv12_file.write("// Automatically generated from " + sys.argv[1] + "\n")
+nv12_file.write("static const size_t " + sys.argv[3] + "_width = " + str(width) + ";\n")
+nv12_file.write("static const size_t " + sys.argv[3] + "_height = " + str(height) + ";\n")
+nv12_file.write("static const unsigned char " + sys.argv[3] + "_data[] = \n{")
+for i in range(0, width * height):
+    if (i % 16) == 0:
+        nv12_file.write("\n    ")
+    nv12_file.write(str(y_buffer[i]) + ",")
+for i in range(0, width * height / 2):
+    if (i % 16) == 0:
+        nv12_file.write("\n    ")
+    nv12_file.write(str(uv_buffer[i]) + ",")
+nv12_file.write("\n};")
+nv12_file.close()
\ No newline at end of file
diff --git a/src/third_party/angle/scripts/bootstrap.py b/src/third_party/angle/scripts/bootstrap.py
new file mode 100644
index 0000000..bfeac5b
--- /dev/null
+++ b/src/third_party/angle/scripts/bootstrap.py
@@ -0,0 +1,36 @@
+# Copyright 2015 Google Inc.  All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generate .gclient file for Angle.
+
+Because gclient won't accept "--name ." use a different name then edit.
+"""
+
+import subprocess
+import sys
+
+
+def main():
+  gclient_cmd = ('gclient config --name change2dot --unmanaged '
+      'https://chromium.googlesource.com/angle/angle.git')
+  try:
+    rc = subprocess.call(gclient_cmd, shell=True)
+  except OSError:
+    print 'could not run "%s" via shell' % gclient_cmd
+    sys.exit(1)
+
+  if rc:
+    print 'failed command: "%s"' % gclient_cmd
+    sys.exit(1)
+
+  with open('.gclient') as gclient_file:
+    content = gclient_file.read()
+
+  with open('.gclient', 'w') as gclient_file:
+    gclient_file.write(content.replace('change2dot', '.'))
+
+  print 'created .gclient'
+
+if __name__ == '__main__':
+  main()
diff --git a/src/third_party/angle/scripts/generate_entry_points.py b/src/third_party/angle/scripts/generate_entry_points.py
new file mode 100644
index 0000000..875b0bd
--- /dev/null
+++ b/src/third_party/angle/scripts/generate_entry_points.py
@@ -0,0 +1,230 @@
+#!/usr/bin/python
+#
+# Copyright 2017 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.
+#
+# generate_entry_points.py:
+#   Generates the OpenGL bindings and entry point layers for ANGLE.
+
+import sys, os, pprint
+import xml.etree.ElementTree as etree
+from datetime import date
+
+def script_relative(path):
+    return os.path.join(os.path.dirname(sys.argv[0]), path)
+
+tree = etree.parse(script_relative('gl.xml'))
+root = tree.getroot()
+
+gles2_xpath = ".//feature[@name='GL_ES_VERSION_2_0']//command"
+gles2_commands = [cmd.attrib['name'] for cmd in root.findall(gles2_xpath)]
+
+template_entry_point_header = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+//
+// Copyright {year} 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.
+//
+// entry_points_gles_{major_version}_{minor_version}_autogen.h:
+//   Defines the GLES {major_version}.{minor_version} entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTSGLES{major_version}{minor_version}_AUTOGEN_H_
+#define LIBGLESV2_ENTRYPOINTSGLES{major_version}{minor_version}_AUTOGEN_H_
+
+#include <GLES2/gl{major_version}.h>
+#include <export.h>
+
+namespace gl
+{{
+{entry_points}
+}}  // namespace gl
+
+#endif  // LIBGLESV2_ENTRYPOINTSGLES{major_version}{minor_version}_AUTOGEN_H_
+"""
+
+template_entry_point_source = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+//
+// Copyright {year} 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.
+//
+// entry_points_gles_{major_version}_{minor_version}_autogen.cpp:
+//   Defines the GLES {major_version}.{minor_version} entry points.
+
+#include "libGLESv2/entry_points_gles_{major_version}_{minor_version}_autogen.h"
+
+#include "common/debug.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/validationES2.h"
+#include "libGLESv2/global_state.h"
+
+namespace gl
+{{
+{entry_points}}}  // namespace gl
+"""
+
+template_entry_points_enum_header = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+//
+// Copyright {year} 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.
+//
+// entry_points_enum_autogen.h:
+//   Defines the GLES entry points enumeration.
+
+#ifndef LIBGLESV2_ENTRYPOINTSENUM_AUTOGEN_H_
+#define LIBGLESV2_ENTRYPOINTSENUM_AUTOGEN_H_
+
+namespace gl
+{{
+enum class EntryPoint
+{{
+{entry_points_list}
+}};
+}}  // namespace gl
+#endif  // LIBGLESV2_ENTRY_POINTS_ENUM_AUTOGEN_H_
+"""
+
+template_entry_point_decl = """ANGLE_EXPORT {return_type}GL_APIENTRY {name}({params});"""
+
+template_entry_point_def = """{return_type}GL_APIENTRY {name}({params})
+{{
+    EVENT("({format_params})"{comma_if_needed}{pass_params});
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {{
+        context->gatherParams<EntryPoint::{name}>({pass_params});
+
+        if (context->skipValidation() || Validate{name}({validate_params}))
+        {{
+            {return_if_needed}context->{name_lower}({pass_params});
+        }}
+    }}
+{default_return_if_needed}}}
+"""
+
+commands = root.find(".//commands[@namespace='GL']")
+entry_point_decls_gles_2_0 = []
+entry_point_defs_gles_2_0 = []
+cmd_names = []
+
+def format_entry_point_decl(cmd_name, proto, params):
+    return template_entry_point_decl.format(
+        name = cmd_name[2:],
+        return_type = proto[:-len(cmd_name)],
+        params = ", ".join(params))
+
+def type_name_sep_index(param):
+    space = param.rfind(" ")
+    pointer = param.rfind("*")
+    return max(space, pointer)
+
+def just_the_type(param):
+    return param[:type_name_sep_index(param)]
+
+def just_the_name(param):
+    return param[type_name_sep_index(param)+1:]
+
+format_dict = {
+    "GLbitfield": "0x%X",
+    "GLboolean": "%u",
+    "GLenum": "0x%X",
+    "GLfloat": "%f",
+    "GLint": "%d",
+    "GLintptr": "%d",
+    "GLsizei": "%d",
+    "GLsizeiptr": "%d",
+    "GLuint": "%d"
+}
+
+def param_format_string(param):
+    if "*" in param:
+        return param + " = 0x%0.8p"
+    else:
+        return param + " = " + format_dict[just_the_type(param)]
+
+def default_return_value(return_type):
+    if return_type == "void":
+        return ""
+    elif return_type == "GLenum" or return_type == "GLint" or return_type == "GLuint":
+        return "0"
+    elif return_type == "GLboolean":
+        return "GL_FALSE"
+    elif "*" in return_type:
+        return "nullptr"
+    else:
+        print(return_type)
+
+def format_entry_point_def(cmd_name, proto, params):
+    pass_params = [just_the_name(param) for param in params]
+    format_params = [param_format_string(param) for param in params]
+    return_type = proto[:-len(cmd_name)]
+    default_return = default_return_value(return_type.strip())
+    return template_entry_point_def.format(
+        name = cmd_name[2:],
+        name_lower = cmd_name[2:3].lower() + cmd_name[3:],
+        return_type = return_type,
+        params = ", ".join(params),
+        pass_params = ", ".join(pass_params),
+        comma_if_needed = ", " if len(params) > 0 else "",
+        validate_params = ", ".join(["context"] + pass_params),
+        format_params = ", ".join(format_params),
+        return_if_needed = "" if default_return == "" else "return ",
+        default_return_if_needed = "" if default_return == "" else "\n    return " + default_return + ";\n")
+
+for cmd_name in gles2_commands:
+    command_xpath = "command/proto[name='" + cmd_name + "']/.."
+    command = commands.find(command_xpath)
+    params = ["".join(param.itertext()) for param in command.findall("./param")]
+    proto = "".join(command.find("./proto").itertext())
+    cmd_names += [cmd_name]
+    entry_point_decls_gles_2_0 += [format_entry_point_decl(cmd_name, proto, params)]
+    entry_point_defs_gles_2_0 += [format_entry_point_def(cmd_name, proto, params)]
+
+gles_2_0_header = template_entry_point_header.format(
+    script_name = os.path.basename(sys.argv[0]),
+    data_source_name = "gl.xml",
+    year = date.today().year,
+    major_version = 2,
+    minor_version = 0,
+    entry_points = "\n".join(entry_point_decls_gles_2_0))
+
+gles_2_0_source = template_entry_point_source.format(
+    script_name = os.path.basename(sys.argv[0]),
+    data_source_name = "gl.xml",
+    year = date.today().year,
+    major_version = 2,
+    minor_version = 0,
+    entry_points = "\n".join(entry_point_defs_gles_2_0))
+
+# TODO(jmadill): Remove manually added entry points.
+manual_cmd_names = ["Invalid"] + [cmd[2:] for cmd in cmd_names] + ["DrawElementsInstanced", "DrawRangeElements", "DrawElementsInstancedANGLE"]
+entry_points_enum = template_entry_points_enum_header.format(
+    script_name = os.path.basename(sys.argv[0]),
+    data_source_name = "gl.xml",
+    year = date.today().year,
+    entry_points_list = ",\n".join(["    " + cmd for cmd in manual_cmd_names]))
+
+def path_to(folder, file):
+    return os.path.join(script_relative(".."), "src", folder, file)
+
+gles_2_0_header_path = path_to("libGLESv2", "entry_points_gles_2_0_autogen.h")
+gles_2_0_source_path = path_to("libGLESv2", "entry_points_gles_2_0_autogen.cpp")
+entry_points_enum_header_path = path_to("libANGLE", "entry_points_enum_autogen.h")
+
+with open(gles_2_0_header_path, "w") as out:
+    out.write(gles_2_0_header)
+    out.close()
+
+with open(gles_2_0_source_path, "w") as out:
+    out.write(gles_2_0_source)
+    out.close()
+
+with open(entry_points_enum_header_path, "w") as out:
+    out.write(entry_points_enum)
+    out.close()
\ No newline at end of file
diff --git a/src/third_party/angle/scripts/generate_new_renderer.py b/src/third_party/angle/scripts/generate_new_renderer.py
new file mode 100644
index 0000000..1dc76aa
--- /dev/null
+++ b/src/third_party/angle/scripts/generate_new_renderer.py
@@ -0,0 +1,281 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# generate_new_renderer.py:
+#   Utility script to generate stubs for a new Renderer class.
+#   Usage: generate_new_renderer.py <renderer name> <renderer suffix>
+#     Renderer name is the folder for the renderer subdirectory
+#     Renderer suffix is the abbreviation to append after the class names.
+#
+# The script is fairly robust but may not work for all new methods or
+# other unexpected features. It expects that abstract methods are all
+# grouped after the public destructor or after the private
+# DISALLOW_COPY_AND_ASSIGN macro.
+
+import os, sys, re, string, datetime
+
+if len(sys.argv) < 3:
+    print('Usage: ' + sys.argv[0] + ' <renderer dir name> <renderer class suffix>')
+    sys.exit(1)
+
+renderer_name = sys.argv[1]
+renderer_suffix = sys.argv[2]
+
+# change to the renderer directory
+os.chdir(os.path.join(os.path.dirname(sys.argv[0]), "..", "src", "libANGLE", "renderer"))
+
+# ensure subdir exists
+if not os.path.isdir(renderer_name):
+    os.mkdir(renderer_name)
+
+impl_classes = [
+    'Buffer',
+    'Compiler',
+    'Context',
+    'Device',
+    'Display',
+    'FenceNV',
+    'FenceSync',
+    'Framebuffer',
+    'Image',
+    'Path',
+    'Program',
+    'Query',
+    'Renderbuffer',
+    'Sampler',
+    'Shader',
+    'Surface',
+    'Texture',
+    'TransformFeedback',
+    'VertexArray',
+]
+
+h_file_template = """//
+// Copyright 2016 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.
+//
+// $TypedImpl.h:
+//    Defines the class interface for $TypedImpl, implementing $BaseImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_${RendererNameCaps}_${TypedImplCaps}_H_
+#define LIBANGLE_RENDERER_${RendererNameCaps}_${TypedImplCaps}_H_
+
+#include "libANGLE/renderer/$BaseImpl.h"
+
+namespace rx
+{
+
+class $TypedImpl : public $BaseImpl
+{
+  public:
+    $TypedImpl($ConstructorParams);
+    ~$TypedImpl() override;
+$ImplMethodDeclarations$PrivateImplMethodDeclarations};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_${RendererNameCaps}_${TypedImplCaps}_H_
+"""
+
+cpp_file_template = """//
+// Copyright $Year 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.
+//
+// $TypedImpl.cpp:
+//    Implements the class methods for $TypedImpl.
+//
+
+#include "libANGLE/renderer/$RendererName/$TypedImpl.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+$TypedImpl::$TypedImpl($ConstructorParams) : $BaseImpl($BaseContructorArgs)
+{
+}
+
+$TypedImpl::~$TypedImpl()
+{
+}
+$ImplMethodDefinitions
+}  // namespace rx
+"""
+
+def generate_impl_declaration(impl_stub):
+    # ensure the wrapped lines are aligned vertically
+    temp = re.sub(r'\n        ', '\n', impl_stub)
+    return temp + ' override;\n'
+
+def generate_impl_definition(impl_stub, typed_impl):
+    function_signature = impl_stub.strip()
+
+    # strip comments
+    function_signature = re.sub(r'\/\/[^\n]*\n', '', function_signature).strip()
+
+    prog = re.compile(r'^(.+[ \*\&])([^ \(\*\&]+\()')
+    return_value = prog.match(function_signature).group(1)
+
+    # ensure the wrapped lines are aligned vertically
+    spaces = ' ' * len(typed_impl)
+    function_signature = re.sub(r'\n          ', '\n' + spaces, function_signature)
+
+    # add class scoping
+    function_signature = prog.sub(r'\1' + typed_impl + r'::\2', function_signature)
+    function_signature += '\n'
+
+    return_statement = ''
+    return_type = return_value.strip()
+
+    if return_type != 'void':
+        # specialized return values for Errors, pointers, etc
+        if return_type == 'gl::Error':
+            return_statement = '    return gl::Error(GL_INVALID_OPERATION);\n'
+        elif return_type == 'egl::Error':
+            return_statement = '    return egl::Error(EGL_BAD_ACCESS);\n'
+        elif return_type == 'LinkResult':
+            return_statement = '    return gl::Error(GL_INVALID_OPERATION);\n'
+        elif re.search(r'\*$', return_type):
+            return_statement = '    return static_cast<' + return_type + '>(0);\n'
+        elif re.search(r'const ([^ \&]+) \&$', return_type):
+            obj_type = re.search(r'const ([^ \&]+) \&$', return_type).group(1)
+            return_statement = '    static ' + obj_type + ' local;\n' + '    return local;\n'
+        else:
+            return_statement = '    return ' + return_type + '();\n'
+
+    body = '{\n' + '    UNIMPLEMENTED();\n' + return_statement +'}\n'
+
+    return '\n' + function_signature + body
+
+def get_constructor_args(constructor):
+    params = re.search(r'\((.*)\)', constructor).group(1)
+    args = ', '.join(re.findall(r'[^\w]?(\w+)(?:\,|$)', params))
+    return params, args
+
+def parse_impl_header(base_impl):
+    impl_h_file_path = base_impl + '.h'
+    impl_h_file = open(impl_h_file_path, 'r')
+
+    # extract impl stubs
+    copy = False
+    copy_private = False
+    impl_stubs = ''
+    private_impl_stubs = ''
+    constructor = base_impl + '() {}'
+    for line in impl_h_file:
+        clean_line = line.strip()
+
+        match = re.search(r'^(?:explicit )?(' + base_impl + r'\([^\)]*\))', clean_line);
+        if match:
+            constructor = match.group(1)
+
+        # begin capture when reading the destructor.
+        # begin capture also in the private scope (a few special cases)
+        # end capture when we reach a non-virtual function, or different scope.
+        if '~' + base_impl in clean_line:
+            copy = True
+            copy_private = False
+        elif 'private:' in clean_line:
+            copy = False
+            copy_private = True
+        elif ';' in clean_line and ' = 0' not in clean_line:
+            copy = False
+            copy_private = False
+        elif '}' in clean_line or 'protected:' in clean_line or 'private:' in clean_line:
+            copy = False
+            copy_private = False
+        elif copy:
+            impl_stubs += line
+        elif copy_private:
+            private_impl_stubs += line
+
+    impl_h_file.close()
+
+    return impl_stubs, private_impl_stubs, constructor
+
+def get_base_class(base_impl):
+    impl_h_file_path = base_impl + '.h'
+    with open(impl_h_file_path, 'r') as impl_h_file:
+        for line in impl_h_file:
+            match = re.search(r'^class ' + base_impl + r' : public (\w+)', line)
+            if match:
+                return match.group(1)
+    return False
+
+for impl_class in impl_classes:
+
+    base_impl = impl_class + 'Impl'
+    typed_impl = impl_class + renderer_suffix
+
+    h_file_path = os.path.join(renderer_name, typed_impl + '.h')
+    cpp_file_path = os.path.join(renderer_name, typed_impl + '.cpp')
+
+    h_file = open(h_file_path, 'w')
+    cpp_file = open(cpp_file_path, 'w')
+
+    # extract impl stubs
+    impl_stubs, private_impl_stubs, constructor = parse_impl_header(base_impl)
+
+    # Handle base classes, skipping angle::NonCopyable.
+    base_class = get_base_class(base_impl)
+    if base_class and base_class != 'angle':
+        base_impl_stubs, base_private_impl_stubs, base_constructor = parse_impl_header(base_class)
+        impl_stubs += base_impl_stubs
+        private_impl_stubs += base_private_impl_stubs
+
+    impl_method_declarations = ''
+    impl_method_definitions = ''
+    private_impl_method_declarations = ''
+
+    for impl_stub in impl_stubs.split(' = 0;\n'):
+        # use 'virtual' to identify the strings with functions
+        if 'virtual' in impl_stub:
+            temp = re.sub(r'virtual ', '', impl_stub)
+            impl_method_declarations += generate_impl_declaration(temp)
+            impl_method_definitions += generate_impl_definition(temp, typed_impl)
+
+    for impl_stub in private_impl_stubs.split(' = 0;\n'):
+        # use 'virtual' to identify the strings with functions
+        if 'virtual' in impl_stub:
+            temp = re.sub(r'virtual ', '', impl_stub)
+            private_impl_method_declarations += generate_impl_declaration(temp)
+            impl_method_definitions += generate_impl_definition(temp, typed_impl)
+
+    constructor_params, base_constructor_args = get_constructor_args(constructor)
+
+    if private_impl_method_declarations:
+        private_impl_method_declarations = "\n  private:\n" + private_impl_method_declarations
+
+    substitutions = {
+        'BaseImpl': base_impl,
+        'TypedImpl': typed_impl,
+        'TypedImplCaps': typed_impl.upper(),
+        'RendererName': renderer_name,
+        'RendererNameCaps': renderer_name.upper(),
+        'ImplMethodDeclarations': impl_method_declarations,
+        'ImplMethodDefinitions': impl_method_definitions,
+        'ConstructorParams': constructor_params,
+        'BaseContructorArgs': base_constructor_args,
+        'PrivateImplMethodDeclarations': private_impl_method_declarations,
+        'Year': datetime.datetime.now().year,
+    }
+
+    h_file.write(string.Template(h_file_template).substitute(substitutions))
+    cpp_file.write(string.Template(cpp_file_template).substitute(substitutions))
+
+    h_file.close()
+    cpp_file.close()
+
+# Print a block of source files to add to the GYP
+print("Generated files:")
+for impl_class in impl_classes:
+    path = "libANGLE/renderer/" + renderer_name + "/" + impl_class + renderer_suffix
+    print('\'' + path + ".cpp\',")
+    print('\'' + path + ".h\',")
diff --git a/src/third_party/angle/scripts/generate_vulkan_header.py b/src/third_party/angle/scripts/generate_vulkan_header.py
new file mode 100644
index 0000000..59ce2c4
--- /dev/null
+++ b/src/third_party/angle/scripts/generate_vulkan_header.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+#
+# Copyright 2016 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.
+#
+# generate_vulkan_header.py:
+#   Workaround problems with Windows and GYP and the Vulkan loader paths.
+
+import os, sys
+
+if len(sys.argv) < 4:
+    print("Usage: " + sys.argv[0] + " <json_source_path> <output_file> <product_dir>")
+    sys.exit(1)
+
+layers_source_path = sys.argv[1]
+output_file = sys.argv[2]
+product_dir = sys.argv[3].rstrip("\"")
+
+def fixpath(inpath):
+    return os.path.relpath(inpath, product_dir).replace('\\', '/')
+
+with open(output_file, "w") as outfile:
+    outfile.write("#define LAYERS_SOURCE_PATH \"" + fixpath(layers_source_path) + "\"\n")
+    outfile.write("#define DEFAULT_VK_LAYERS_PATH \"" + fixpath(product_dir) + "\"\n")
diff --git a/src/third_party/angle/scripts/generate_vulkan_layers_json.py b/src/third_party/angle/scripts/generate_vulkan_layers_json.py
new file mode 100644
index 0000000..77990c2
--- /dev/null
+++ b/src/third_party/angle/scripts/generate_vulkan_layers_json.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+#
+# Copyright 2016 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.
+#
+# generate_vulkan_layers_json.py:
+#   Generate copies of the Vulkan layers JSON files, with no paths, forcing
+#   Vulkan to use the default search path to look for layers.
+
+import os, sys, json, glob
+
+if len(sys.argv) != 3:
+    print("Usage: " + sys.argv[0] + " <source_dir> <target_dir>")
+    sys.exit(1)
+
+source_dir = sys.argv[1]
+target_dir = sys.argv[2]
+
+if not os.path.isdir(source_dir):
+    print(source_dir + " is not a directory.")
+    sys.exit(1)
+
+if not os.path.exists(target_dir):
+    os.makedirs(target_dir)
+
+for json_fname in glob.glob(os.path.join(source_dir, "*.json")):
+    with open(json_fname) as infile:
+        data = json.load(infile)
+
+        # update the path
+        prev_name = os.path.basename(data['layer']['library_path'])
+        data['layer']['library_path'] = prev_name
+
+        target_fname = os.path.join(target_dir, os.path.basename(json_fname))
+        with open(target_fname, "w") as outfile:
+            json.dump(data, outfile)
diff --git a/src/third_party/angle/scripts/gl.xml b/src/third_party/angle/scripts/gl.xml
new file mode 100644
index 0000000..cf4bbc2
--- /dev/null
+++ b/src/third_party/angle/scripts/gl.xml
@@ -0,0 +1,47118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<registry>
+    <comment>
+Copyright (c) 2013-2016 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Materials.
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+------------------------------------------------------------------------
+
+This file, gl.xml, is the OpenGL and OpenGL API Registry. The older
+".spec" file format has been retired and will no longer be updated with
+new extensions and API versions. The canonical version of the registry,
+together with documentation, schema, and Python generator scripts used
+to generate C header files for OpenGL and OpenGL ES, can always be found
+in the Khronos Registry at
+        http://www.opengl.org/registry/
+    </comment>
+
+    <!-- SECTION: GL type definitions. -->
+    <types>
+            <!-- These are dependencies GL types require to be declared legally -->
+        <type name="stddef">#include &lt;stddef.h&gt;</type>
+        <type name="khrplatform">#include &lt;KHR/khrplatform.h&gt;</type>
+        <type name="inttypes">#ifndef GLEXT_64_TYPES_DEFINED
+/* This code block is duplicated in glxext.h, so must be protected */
+#define GLEXT_64_TYPES_DEFINED
+/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
+/* (as used in the GL_EXT_timer_query extension). */
+#if defined(__STDC_VERSION__) &amp;&amp; __STDC_VERSION__ &gt;= 199901L
+#include &lt;inttypes.h&gt;
+#elif defined(__sun__) || defined(__digital__)
+#include &lt;inttypes.h&gt;
+#if defined(__STDC__)
+#if defined(__arch64__) || defined(_LP64)
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+#else
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#endif /* __arch64__ */
+#endif /* __STDC__ */
+#elif defined( __VMS ) || defined(__sgi)
+#include &lt;inttypes.h&gt;
+#elif defined(__SCO__) || defined(__USLC__)
+#include &lt;stdint.h&gt;
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#elif defined(_WIN32) &amp;&amp; defined(__GNUC__)
+#include &lt;stdint.h&gt;
+#elif defined(_WIN32)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+/* Fallback if nothing above works */
+#include &lt;inttypes.h&gt;
+#endif
+#endif</type>
+            <!-- These are actual GL types -->
+        <type>typedef unsigned int <name>GLenum</name>;</type>
+        <type>typedef unsigned char <name>GLboolean</name>;</type>
+        <type>typedef unsigned int <name>GLbitfield</name>;</type>
+        <type comment="Not an actual GL type, though used in headers in the past">typedef void <name>GLvoid</name>;</type>
+        <type>typedef signed char <name>GLbyte</name>;</type>
+        <type>typedef short <name>GLshort</name>;</type>
+        <type>typedef int <name>GLint</name>;</type>
+        <type>typedef int <name>GLclampx</name>;</type>
+        <type>typedef unsigned char <name>GLubyte</name>;</type>
+        <type>typedef unsigned short <name>GLushort</name>;</type>
+        <type>typedef unsigned int <name>GLuint</name>;</type>
+        <type>typedef int <name>GLsizei</name>;</type>
+        <type>typedef float <name>GLfloat</name>;</type>
+        <type>typedef float <name>GLclampf</name>;</type>
+        <type>typedef double <name>GLdouble</name>;</type>
+        <type>typedef double <name>GLclampd</name>;</type>
+        <type>typedef void *<name>GLeglImageOES</name>;</type>
+        <type>typedef char <name>GLchar</name>;</type>
+        <type>typedef char <name>GLcharARB</name>;</type>
+        <type name="GLhandleARB">#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif</type>
+        <type>typedef unsigned short <name>GLhalfARB</name>;</type>
+        <type>typedef unsigned short <name>GLhalf</name>;</type>
+        <type comment="Must be 32 bits">typedef GLint <name>GLfixed</name>;</type>
+        <type requires="stddef">typedef ptrdiff_t <name>GLintptr</name>;</type>
+        <type requires="stddef">typedef ptrdiff_t <name>GLsizeiptr</name>;</type>
+        <type requires="inttypes">typedef int64_t <name>GLint64</name>;</type>
+        <type requires="inttypes">typedef uint64_t <name>GLuint64</name>;</type>
+        <type requires="stddef">typedef ptrdiff_t <name>GLintptrARB</name>;</type>
+        <type requires="stddef">typedef ptrdiff_t <name>GLsizeiptrARB</name>;</type>
+        <type requires="inttypes">typedef int64_t <name>GLint64EXT</name>;</type>
+        <type requires="inttypes">typedef uint64_t <name>GLuint64EXT</name>;</type>
+        <type>typedef struct __GLsync *<name>GLsync</name>;</type>
+        <type comment="compatible with OpenCL cl_context"><name>struct _cl_context</name>;</type>
+        <type comment="compatible with OpenCL cl_event"><name>struct _cl_event</name>;</type>
+        <type>typedef void (<apientry/> *<name>GLDEBUGPROC</name>)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);</type>
+        <type>typedef void (<apientry/> *<name>GLDEBUGPROCARB</name>)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);</type>
+        <type>typedef void (<apientry/> *<name>GLDEBUGPROCKHR</name>)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);</type>
+            <!-- GLES 1 types -->
+        <type api="gles1" requires="khrplatform">typedef khronos_int32_t <name>GLclampx</name>;</type>
+            <!-- GLES 1/2 types (tagged for GLES 1) -->
+        <type api="gles1" requires="khrplatform">typedef khronos_int8_t <name>GLbyte</name>;</type>
+        <type api="gles1" requires="khrplatform">typedef khronos_uint8_t <name>GLubyte</name>;</type>
+        <type api="gles1" requires="khrplatform">typedef khronos_float_t <name>GLfloat</name>;</type>
+        <type api="gles1" requires="khrplatform">typedef khronos_float_t <name>GLclampf</name>;</type>
+        <type api="gles1" requires="khrplatform">typedef khronos_int32_t <name>GLfixed</name>;</type>
+        <type api="gles1" requires="khrplatform">typedef khronos_int64_t <name>GLint64</name>;</type>
+        <type api="gles1" requires="khrplatform">typedef khronos_uint64_t <name>GLuint64</name>;</type>
+        <type api="gles1" requires="khrplatform">typedef khronos_intptr_t <name>GLintptr</name>;</type>
+        <type api="gles1" requires="khrplatform">typedef khronos_ssize_t <name>GLsizeiptr</name>;</type>
+            <!-- GLES 1/2 types (tagged for GLES 2 - attribute syntax is limited) -->
+        <type api="gles2" requires="khrplatform">typedef khronos_int8_t <name>GLbyte</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_uint8_t <name>GLubyte</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_float_t <name>GLfloat</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_float_t <name>GLclampf</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_int32_t <name>GLfixed</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_int64_t <name>GLint64</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_uint64_t <name>GLuint64</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_int64_t <name>GLint64EXT</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_uint64_t <name>GLuint64EXT</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_intptr_t <name>GLintptr</name>;</type>
+        <type api="gles2" requires="khrplatform">typedef khronos_ssize_t <name>GLsizeiptr</name>;</type>
+            <!-- GLES 2 types (none currently) -->
+            <!-- GLSC 2 types -->
+        <type api="glsc2" requires="khrplatform">typedef khronos_uint8_t <name>GLubyte</name>;</type>
+        <type api="glsc2" requires="khrplatform">typedef khronos_float_t <name>GLfloat</name>;</type>
+        <type api="glsc2" requires="khrplatform">typedef khronos_intptr_t <name>GLintptr</name>;</type>
+        <type api="glsc2" requires="khrplatform">typedef khronos_ssize_t <name>GLsizeiptr</name>;</type>
+            <!-- Vendor extension types -->
+        <type>typedef void (<apientry/> *<name>GLDEBUGPROCAMD</name>)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);</type>
+        <type>typedef unsigned short <name>GLhalfNV</name>;</type>
+        <type requires="GLintptr">typedef GLintptr <name>GLvdpauSurfaceNV</name>;</type>
+    </types>
+
+    <!-- SECTION: GL parameter class type definitions. -->
+
+    <groups>
+        <group name="AccumOp">
+            <enum name="GL_ACCUM"/>
+            <enum name="GL_LOAD"/>
+            <enum name="GL_RETURN"/>
+            <enum name="GL_MULT"/>
+            <enum name="GL_ADD"/>
+        </group>
+
+        <group name="AttribMask">
+            <enum name="GL_ACCUM_BUFFER_BIT"/>
+            <enum name="GL_ALL_ATTRIB_BITS"/>
+            <enum name="GL_COLOR_BUFFER_BIT"/>
+            <enum name="GL_CURRENT_BIT"/>
+            <enum name="GL_DEPTH_BUFFER_BIT"/>
+            <enum name="GL_ENABLE_BIT"/>
+            <enum name="GL_EVAL_BIT"/>
+            <enum name="GL_FOG_BIT"/>
+            <enum name="GL_HINT_BIT"/>
+            <enum name="GL_LIGHTING_BIT"/>
+            <enum name="GL_LINE_BIT"/>
+            <enum name="GL_LIST_BIT"/>
+            <enum name="GL_MULTISAMPLE_BIT"/>
+            <enum name="GL_MULTISAMPLE_BIT_3DFX"/>
+            <enum name="GL_MULTISAMPLE_BIT_ARB"/>
+            <enum name="GL_MULTISAMPLE_BIT_EXT"/>
+            <enum name="GL_PIXEL_MODE_BIT"/>
+            <enum name="GL_POINT_BIT"/>
+            <enum name="GL_POLYGON_BIT"/>
+            <enum name="GL_POLYGON_STIPPLE_BIT"/>
+            <enum name="GL_SCISSOR_BIT"/>
+            <enum name="GL_STENCIL_BUFFER_BIT"/>
+            <enum name="GL_TEXTURE_BIT"/>
+            <enum name="GL_TRANSFORM_BIT"/>
+            <enum name="GL_VIEWPORT_BIT"/>
+        </group>
+
+        <group name="AlphaFunction">
+            <enum name="GL_ALWAYS"/>
+            <enum name="GL_EQUAL"/>
+            <enum name="GL_GEQUAL"/>
+            <enum name="GL_GREATER"/>
+            <enum name="GL_LEQUAL"/>
+            <enum name="GL_LESS"/>
+            <enum name="GL_NEVER"/>
+            <enum name="GL_NOTEQUAL"/>
+        </group>
+
+        <group name="BlendEquationModeEXT">
+            <enum name="GL_ALPHA_MAX_SGIX"/>
+            <enum name="GL_ALPHA_MIN_SGIX"/>
+            <enum name="GL_FUNC_ADD_EXT"/>
+            <enum name="GL_FUNC_REVERSE_SUBTRACT_EXT"/>
+            <enum name="GL_FUNC_SUBTRACT_EXT"/>
+            <enum name="GL_LOGIC_OP"/>
+            <enum name="GL_MAX_EXT"/>
+            <enum name="GL_MIN_EXT"/>
+        </group>
+
+        <group name="BlendingFactorDest">
+            <enum name="GL_CONSTANT_ALPHA_EXT"/>
+            <enum name="GL_CONSTANT_COLOR_EXT"/>
+            <enum name="GL_DST_ALPHA"/>
+            <enum name="GL_ONE"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_ALPHA_EXT"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_COLOR_EXT"/>
+            <enum name="GL_ONE_MINUS_DST_ALPHA"/>
+            <enum name="GL_ONE_MINUS_SRC_ALPHA"/>
+            <enum name="GL_ONE_MINUS_SRC_COLOR"/>
+            <enum name="GL_SRC_ALPHA"/>
+            <enum name="GL_SRC_COLOR"/>
+            <enum name="GL_ZERO"/>
+        </group>
+
+        <group name="BlendingFactorSrc">
+            <enum name="GL_CONSTANT_ALPHA_EXT"/>
+            <enum name="GL_CONSTANT_COLOR_EXT"/>
+            <enum name="GL_DST_ALPHA"/>
+            <enum name="GL_DST_COLOR"/>
+            <enum name="GL_ONE"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_ALPHA_EXT"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_COLOR_EXT"/>
+            <enum name="GL_ONE_MINUS_DST_ALPHA"/>
+            <enum name="GL_ONE_MINUS_DST_COLOR"/>
+            <enum name="GL_ONE_MINUS_SRC_ALPHA"/>
+            <enum name="GL_SRC_ALPHA"/>
+            <enum name="GL_SRC_ALPHA_SATURATE"/>
+            <enum name="GL_ZERO"/>
+        </group>
+
+        <group name="Boolean">
+            <enum name="GL_FALSE"/>
+            <enum name="GL_TRUE"/>
+        </group>
+
+        <group name="ClearBufferMask">
+            <enum name="GL_ACCUM_BUFFER_BIT"/>
+            <enum name="GL_COLOR_BUFFER_BIT"/>
+            <enum name="GL_COVERAGE_BUFFER_BIT_NV"/>
+            <enum name="GL_DEPTH_BUFFER_BIT"/>
+            <enum name="GL_STENCIL_BUFFER_BIT"/>
+        </group>
+
+        <group name="ClientAttribMask">
+            <enum name="GL_CLIENT_ALL_ATTRIB_BITS"/>
+            <enum name="GL_CLIENT_PIXEL_STORE_BIT"/>
+            <enum name="GL_CLIENT_VERTEX_ARRAY_BIT"/>
+        </group>
+
+        <group name="ClipPlaneName">
+            <enum name="GL_CLIP_DISTANCE0"/>
+            <enum name="GL_CLIP_DISTANCE1"/>
+            <enum name="GL_CLIP_DISTANCE2"/>
+            <enum name="GL_CLIP_DISTANCE3"/>
+            <enum name="GL_CLIP_DISTANCE4"/>
+            <enum name="GL_CLIP_DISTANCE5"/>
+            <enum name="GL_CLIP_DISTANCE6"/>
+            <enum name="GL_CLIP_DISTANCE7"/>
+            <enum name="GL_CLIP_PLANE0"/>
+            <enum name="GL_CLIP_PLANE1"/>
+            <enum name="GL_CLIP_PLANE2"/>
+            <enum name="GL_CLIP_PLANE3"/>
+            <enum name="GL_CLIP_PLANE4"/>
+            <enum name="GL_CLIP_PLANE5"/>
+        </group>
+
+        <group name="ColorMaterialFace">
+            <enum name="GL_BACK"/>
+            <enum name="GL_FRONT"/>
+            <enum name="GL_FRONT_AND_BACK"/>
+        </group>
+
+        <group name="ColorMaterialParameter">
+            <enum name="GL_AMBIENT"/>
+            <enum name="GL_AMBIENT_AND_DIFFUSE"/>
+            <enum name="GL_DIFFUSE"/>
+            <enum name="GL_EMISSION"/>
+            <enum name="GL_SPECULAR"/>
+        </group>
+
+        <group name="ColorPointerType">
+            <enum name="GL_BYTE"/>
+            <enum name="GL_DOUBLE"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_SHORT"/>
+            <enum name="GL_UNSIGNED_BYTE"/>
+            <enum name="GL_UNSIGNED_INT"/>
+            <enum name="GL_UNSIGNED_SHORT"/>
+        </group>
+
+        <group name="ColorTableParameterPNameSGI">
+            <enum name="GL_COLOR_TABLE_BIAS"/>
+            <enum name="GL_COLOR_TABLE_BIAS_SGI"/>
+            <enum name="GL_COLOR_TABLE_SCALE"/>
+            <enum name="GL_COLOR_TABLE_SCALE_SGI"/>
+        </group>
+
+        <group name="ColorTableTargetSGI">
+            <enum name="GL_COLOR_TABLE"/>
+            <enum name="GL_COLOR_TABLE_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_COLOR_TABLE"/>
+            <enum name="GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI"/>
+            <enum name="GL_POST_CONVOLUTION_COLOR_TABLE"/>
+            <enum name="GL_POST_CONVOLUTION_COLOR_TABLE_SGI"/>
+            <enum name="GL_PROXY_COLOR_TABLE"/>
+            <enum name="GL_PROXY_COLOR_TABLE_SGI"/>
+            <enum name="GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE"/>
+            <enum name="GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI"/>
+            <enum name="GL_PROXY_POST_CONVOLUTION_COLOR_TABLE"/>
+            <enum name="GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI"/>
+            <enum name="GL_PROXY_TEXTURE_COLOR_TABLE_SGI"/>
+            <enum name="GL_TEXTURE_COLOR_TABLE_SGI"/>
+        </group>
+
+        <group name="ContextFlagMask">
+            <enum name="GL_CONTEXT_FLAG_DEBUG_BIT"/>
+            <enum name="GL_CONTEXT_FLAG_DEBUG_BIT_KHR"/>
+            <enum name="GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT"/>
+            <enum name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB"/>
+            <enum name="GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT"/>
+        </group>
+
+        <group name="ContextProfileMask">
+            <enum name="GL_CONTEXT_COMPATIBILITY_PROFILE_BIT"/>
+            <enum name="GL_CONTEXT_CORE_PROFILE_BIT"/>
+        </group>
+
+        <group name="ConvolutionBorderModeEXT">
+            <enum name="GL_REDUCE"/>
+            <enum name="GL_REDUCE_EXT"/>
+        </group>
+
+        <group name="ConvolutionParameterEXT">
+            <enum name="GL_CONVOLUTION_BORDER_MODE"/>
+            <enum name="GL_CONVOLUTION_BORDER_MODE_EXT"/>
+            <enum name="GL_CONVOLUTION_FILTER_BIAS"/>
+            <enum name="GL_CONVOLUTION_FILTER_BIAS_EXT"/>
+            <enum name="GL_CONVOLUTION_FILTER_SCALE"/>
+            <enum name="GL_CONVOLUTION_FILTER_SCALE_EXT"/>
+        </group>
+
+        <group name="ConvolutionTargetEXT">
+            <enum name="GL_CONVOLUTION_1D"/>
+            <enum name="GL_CONVOLUTION_1D_EXT"/>
+            <enum name="GL_CONVOLUTION_2D"/>
+            <enum name="GL_CONVOLUTION_2D_EXT"/>
+        </group>
+
+        <group name="CullFaceMode">
+            <enum name="GL_BACK"/>
+            <enum name="GL_FRONT"/>
+            <enum name="GL_FRONT_AND_BACK"/>
+        </group>
+
+        <group name="DataType" comment="See enums block below"/>
+
+        <group name="DepthFunction">
+            <enum name="GL_ALWAYS"/>
+            <enum name="GL_EQUAL"/>
+            <enum name="GL_GEQUAL"/>
+            <enum name="GL_GREATER"/>
+            <enum name="GL_LEQUAL"/>
+            <enum name="GL_LESS"/>
+            <enum name="GL_NEVER"/>
+            <enum name="GL_NOTEQUAL"/>
+        </group>
+
+        <group name="DrawBufferMode">
+            <enum name="GL_AUX0"/>
+            <enum name="GL_AUX1"/>
+            <enum name="GL_AUX2"/>
+            <enum name="GL_AUX3"/>
+            <enum name="GL_BACK"/>
+            <enum name="GL_BACK_LEFT"/>
+            <enum name="GL_BACK_RIGHT"/>
+            <enum name="GL_FRONT"/>
+            <enum name="GL_FRONT_AND_BACK"/>
+            <enum name="GL_FRONT_LEFT"/>
+            <enum name="GL_FRONT_RIGHT"/>
+            <enum name="GL_LEFT"/>
+            <enum name="GL_NONE"/>
+            <enum name="GL_NONE_OES"/>
+            <enum name="GL_RIGHT"/>
+        </group>
+
+        <group name="EnableCap">
+            <enum name="GL_ALPHA_TEST"/>
+            <enum name="GL_ASYNC_DRAW_PIXELS_SGIX"/>
+            <enum name="GL_ASYNC_HISTOGRAM_SGIX"/>
+            <enum name="GL_ASYNC_READ_PIXELS_SGIX"/>
+            <enum name="GL_ASYNC_TEX_IMAGE_SGIX"/>
+            <enum name="GL_AUTO_NORMAL"/>
+            <enum name="GL_BLEND"/>
+            <enum name="GL_CALLIGRAPHIC_FRAGMENT_SGIX"/>
+            <enum name="GL_CLIP_PLANE0"/>
+            <enum name="GL_CLIP_PLANE1"/>
+            <enum name="GL_CLIP_PLANE2"/>
+            <enum name="GL_CLIP_PLANE3"/>
+            <enum name="GL_CLIP_PLANE4"/>
+            <enum name="GL_CLIP_PLANE5"/>
+            <enum name="GL_COLOR_ARRAY"/>
+            <enum name="GL_COLOR_LOGIC_OP"/>
+            <enum name="GL_COLOR_MATERIAL"/>
+            <enum name="GL_COLOR_TABLE_SGI"/>
+            <enum name="GL_CONVOLUTION_1D_EXT"/>
+            <enum name="GL_CONVOLUTION_2D_EXT"/>
+            <enum name="GL_CULL_FACE"/>
+            <enum name="GL_DEPTH_TEST"/>
+            <enum name="GL_DITHER"/>
+            <enum name="GL_EDGE_FLAG_ARRAY"/>
+            <enum name="GL_FOG"/>
+            <enum name="GL_FOG_OFFSET_SGIX"/>
+            <enum name="GL_FRAGMENT_COLOR_MATERIAL_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT0_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT1_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT2_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT3_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT4_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT5_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT6_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT7_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHTING_SGIX"/>
+            <enum name="GL_FRAMEZOOM_SGIX"/>
+            <enum name="GL_HISTOGRAM_EXT"/>
+            <enum name="GL_INDEX_ARRAY"/>
+            <enum name="GL_INDEX_LOGIC_OP"/>
+            <enum name="GL_INTERLACE_SGIX"/>
+            <enum name="GL_IR_INSTRUMENT1_SGIX"/>
+            <enum name="GL_LIGHT0"/>
+            <enum name="GL_LIGHT1"/>
+            <enum name="GL_LIGHT2"/>
+            <enum name="GL_LIGHT3"/>
+            <enum name="GL_LIGHT4"/>
+            <enum name="GL_LIGHT5"/>
+            <enum name="GL_LIGHT6"/>
+            <enum name="GL_LIGHT7"/>
+            <enum name="GL_LIGHTING"/>
+            <enum name="GL_LINE_SMOOTH"/>
+            <enum name="GL_LINE_STIPPLE"/>
+            <enum name="GL_MAP1_COLOR_4"/>
+            <enum name="GL_MAP1_INDEX"/>
+            <enum name="GL_MAP1_NORMAL"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP1_VERTEX_3"/>
+            <enum name="GL_MAP1_VERTEX_4"/>
+            <enum name="GL_MAP2_COLOR_4"/>
+            <enum name="GL_MAP2_INDEX"/>
+            <enum name="GL_MAP2_NORMAL"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP2_VERTEX_3"/>
+            <enum name="GL_MAP2_VERTEX_4"/>
+            <enum name="GL_MINMAX_EXT"/>
+            <enum name="GL_MULTISAMPLE_SGIS"/>
+            <enum name="GL_NORMALIZE"/>
+            <enum name="GL_NORMAL_ARRAY"/>
+            <enum name="GL_PIXEL_TEXTURE_SGIS"/>
+            <enum name="GL_PIXEL_TEX_GEN_SGIX"/>
+            <enum name="GL_POINT_SMOOTH"/>
+            <enum name="GL_POLYGON_OFFSET_FILL"/>
+            <enum name="GL_POLYGON_OFFSET_LINE"/>
+            <enum name="GL_POLYGON_OFFSET_POINT"/>
+            <enum name="GL_POLYGON_SMOOTH"/>
+            <enum name="GL_POLYGON_STIPPLE"/>
+            <enum name="GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI"/>
+            <enum name="GL_POST_CONVOLUTION_COLOR_TABLE_SGI"/>
+            <enum name="GL_REFERENCE_PLANE_SGIX"/>
+            <enum name="GL_RESCALE_NORMAL_EXT"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_MASK_SGIS"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_ONE_SGIS"/>
+            <enum name="GL_SAMPLE_MASK_SGIS"/>
+            <enum name="GL_SCISSOR_TEST"/>
+            <enum name="GL_SEPARABLE_2D_EXT"/>
+            <enum name="GL_SHARED_TEXTURE_PALETTE_EXT"/>
+            <enum name="GL_SPRITE_SGIX"/>
+            <enum name="GL_STENCIL_TEST"/>
+            <enum name="GL_TEXTURE_1D"/>
+            <enum name="GL_TEXTURE_2D"/>
+            <enum name="GL_TEXTURE_3D_EXT"/>
+            <enum name="GL_TEXTURE_4D_SGIS"/>
+            <enum name="GL_TEXTURE_COLOR_TABLE_SGI"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY"/>
+            <enum name="GL_TEXTURE_GEN_Q"/>
+            <enum name="GL_TEXTURE_GEN_R"/>
+            <enum name="GL_TEXTURE_GEN_S"/>
+            <enum name="GL_TEXTURE_GEN_T"/>
+            <enum name="GL_VERTEX_ARRAY"/>
+        </group>
+
+        <group name="ErrorCode">
+            <enum name="GL_INVALID_ENUM"/>
+            <enum name="GL_INVALID_FRAMEBUFFER_OPERATION"/>
+            <enum name="GL_INVALID_FRAMEBUFFER_OPERATION_EXT"/>
+            <enum name="GL_INVALID_FRAMEBUFFER_OPERATION_OES"/>
+            <enum name="GL_INVALID_OPERATION"/>
+            <enum name="GL_INVALID_VALUE"/>
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_OUT_OF_MEMORY"/>
+            <enum name="GL_STACK_OVERFLOW"/>
+            <enum name="GL_STACK_UNDERFLOW"/>
+            <enum name="GL_TABLE_TOO_LARGE"/>
+            <enum name="GL_TABLE_TOO_LARGE_EXT"/>
+            <enum name="GL_TEXTURE_TOO_LARGE_EXT"/>
+        </group>
+
+        <group name="FeedbackType">
+            <enum name="GL_2D"/>
+            <enum name="GL_3D"/>
+            <enum name="GL_3D_COLOR"/>
+            <enum name="GL_3D_COLOR_TEXTURE"/>
+            <enum name="GL_4D_COLOR_TEXTURE"/>
+        </group>
+
+        <group name="FeedBackToken">
+            <enum name="GL_BITMAP_TOKEN"/>
+            <enum name="GL_COPY_PIXEL_TOKEN"/>
+            <enum name="GL_DRAW_PIXEL_TOKEN"/>
+            <enum name="GL_LINE_RESET_TOKEN"/>
+            <enum name="GL_LINE_TOKEN"/>
+            <enum name="GL_PASS_THROUGH_TOKEN"/>
+            <enum name="GL_POINT_TOKEN"/>
+            <enum name="GL_POLYGON_TOKEN"/>
+        </group>
+
+        <group name="FfdMaskSGIX" comment="See enums section below. Was SGIXFfdMask"/>
+
+        <group name="FfdTargetSGIX">
+            <enum name="GL_GEOMETRY_DEFORMATION_SGIX"/>
+            <enum name="GL_TEXTURE_DEFORMATION_SGIX"/>
+        </group>
+
+        <group name="FogCoordinatePointerType">
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_DOUBLE"/>
+        </group>
+
+        <group name="FogMode">
+            <enum name="GL_EXP"/>
+            <enum name="GL_EXP2"/>
+            <enum name="GL_FOG_FUNC_SGIS"/>
+            <enum name="GL_LINEAR"/>
+        </group>
+
+        <group name="FogParameter">
+            <enum name="GL_FOG_COLOR"/>
+            <enum name="GL_FOG_DENSITY"/>
+            <enum name="GL_FOG_END"/>
+            <enum name="GL_FOG_INDEX"/>
+            <enum name="GL_FOG_MODE"/>
+            <enum name="GL_FOG_OFFSET_VALUE_SGIX"/>
+            <enum name="GL_FOG_START"/>
+        </group>
+
+        <group name="FogPointerTypeEXT">
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_DOUBLE"/>
+        </group>
+
+        <group name="FogPointerTypeIBM">
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_DOUBLE"/>
+        </group>
+
+        <group name="FragmentLightModelParameterSGIX">
+            <enum name="GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX"/>
+        </group>
+
+        <group name="FrontFaceDirection">
+            <enum name="GL_CCW"/>
+            <enum name="GL_CW"/>
+        </group>
+
+        <group name="GetColorTableParameterPNameSGI">
+            <enum name="GL_COLOR_TABLE_ALPHA_SIZE_SGI"/>
+            <enum name="GL_COLOR_TABLE_BIAS_SGI"/>
+            <enum name="GL_COLOR_TABLE_BLUE_SIZE_SGI"/>
+            <enum name="GL_COLOR_TABLE_FORMAT_SGI"/>
+            <enum name="GL_COLOR_TABLE_GREEN_SIZE_SGI"/>
+            <enum name="GL_COLOR_TABLE_INTENSITY_SIZE_SGI"/>
+            <enum name="GL_COLOR_TABLE_LUMINANCE_SIZE_SGI"/>
+            <enum name="GL_COLOR_TABLE_RED_SIZE_SGI"/>
+            <enum name="GL_COLOR_TABLE_SCALE_SGI"/>
+            <enum name="GL_COLOR_TABLE_WIDTH_SGI"/>
+        </group>
+
+        <group name="GetConvolutionParameter">
+            <enum name="GL_CONVOLUTION_BORDER_MODE_EXT"/>
+            <enum name="GL_CONVOLUTION_FILTER_BIAS_EXT"/>
+            <enum name="GL_CONVOLUTION_FILTER_SCALE_EXT"/>
+            <enum name="GL_CONVOLUTION_FORMAT_EXT"/>
+            <enum name="GL_CONVOLUTION_HEIGHT_EXT"/>
+            <enum name="GL_CONVOLUTION_WIDTH_EXT"/>
+            <enum name="GL_MAX_CONVOLUTION_HEIGHT_EXT"/>
+            <enum name="GL_MAX_CONVOLUTION_WIDTH_EXT"/>
+        </group>
+
+        <group name="GetHistogramParameterPNameEXT">
+            <enum name="GL_HISTOGRAM_ALPHA_SIZE_EXT"/>
+            <enum name="GL_HISTOGRAM_BLUE_SIZE_EXT"/>
+            <enum name="GL_HISTOGRAM_FORMAT_EXT"/>
+            <enum name="GL_HISTOGRAM_GREEN_SIZE_EXT"/>
+            <enum name="GL_HISTOGRAM_LUMINANCE_SIZE_EXT"/>
+            <enum name="GL_HISTOGRAM_RED_SIZE_EXT"/>
+            <enum name="GL_HISTOGRAM_SINK_EXT"/>
+            <enum name="GL_HISTOGRAM_WIDTH_EXT"/>
+        </group>
+
+        <group name="GetMapQuery">
+            <enum name="GL_COEFF"/>
+            <enum name="GL_DOMAIN"/>
+            <enum name="GL_ORDER"/>
+        </group>
+
+        <group name="GetMinmaxParameterPNameEXT">
+            <enum name="GL_MINMAX_FORMAT"/>
+            <enum name="GL_MINMAX_FORMAT_EXT"/>
+            <enum name="GL_MINMAX_SINK"/>
+            <enum name="GL_MINMAX_SINK_EXT"/>
+        </group>
+
+        <group name="GetPixelMap">
+            <enum name="GL_PIXEL_MAP_A_TO_A"/>
+            <enum name="GL_PIXEL_MAP_B_TO_B"/>
+            <enum name="GL_PIXEL_MAP_G_TO_G"/>
+            <enum name="GL_PIXEL_MAP_I_TO_A"/>
+            <enum name="GL_PIXEL_MAP_I_TO_B"/>
+            <enum name="GL_PIXEL_MAP_I_TO_G"/>
+            <enum name="GL_PIXEL_MAP_I_TO_I"/>
+            <enum name="GL_PIXEL_MAP_I_TO_R"/>
+            <enum name="GL_PIXEL_MAP_R_TO_R"/>
+            <enum name="GL_PIXEL_MAP_S_TO_S"/>
+        </group>
+
+        <group name="GetPName">
+            <enum name="GL_ACCUM_ALPHA_BITS"/>
+            <enum name="GL_ACCUM_BLUE_BITS"/>
+            <enum name="GL_ACCUM_CLEAR_VALUE"/>
+            <enum name="GL_ACCUM_GREEN_BITS"/>
+            <enum name="GL_ACCUM_RED_BITS"/>
+            <enum name="GL_ALIASED_LINE_WIDTH_RANGE"/>
+            <enum name="GL_ALIASED_POINT_SIZE_RANGE"/>
+            <enum name="GL_ALPHA_BIAS"/>
+            <enum name="GL_ALPHA_BITS"/>
+            <enum name="GL_ALPHA_SCALE"/>
+            <enum name="GL_ALPHA_TEST"/>
+            <enum name="GL_ALPHA_TEST_FUNC"/>
+            <enum name="GL_ALPHA_TEST_FUNC_QCOM"/>
+            <enum name="GL_ALPHA_TEST_QCOM"/>
+            <enum name="GL_ALPHA_TEST_REF"/>
+            <enum name="GL_ALPHA_TEST_REF_QCOM"/>
+            <enum name="GL_ASYNC_DRAW_PIXELS_SGIX"/>
+            <enum name="GL_ASYNC_HISTOGRAM_SGIX"/>
+            <enum name="GL_ASYNC_MARKER_SGIX"/>
+            <enum name="GL_ASYNC_READ_PIXELS_SGIX"/>
+            <enum name="GL_ASYNC_TEX_IMAGE_SGIX"/>
+            <enum name="GL_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_AUTO_NORMAL"/>
+            <enum name="GL_AUX_BUFFERS"/>
+            <enum name="GL_BLEND"/>
+            <enum name="GL_BLEND_COLOR_EXT"/>
+            <enum name="GL_BLEND_DST"/>
+            <enum name="GL_BLEND_EQUATION_EXT"/>
+            <enum name="GL_BLEND_SRC"/>
+            <enum name="GL_BLUE_BIAS"/>
+            <enum name="GL_BLUE_BITS"/>
+            <enum name="GL_BLUE_SCALE"/>
+            <enum name="GL_CALLIGRAPHIC_FRAGMENT_SGIX"/>
+            <enum name="GL_CLIENT_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_CLIP_PLANE0"/>
+            <enum name="GL_CLIP_PLANE1"/>
+            <enum name="GL_CLIP_PLANE2"/>
+            <enum name="GL_CLIP_PLANE3"/>
+            <enum name="GL_CLIP_PLANE4"/>
+            <enum name="GL_CLIP_PLANE5"/>
+            <enum name="GL_COLOR_ARRAY"/>
+            <enum name="GL_COLOR_ARRAY_COUNT_EXT"/>
+            <enum name="GL_COLOR_ARRAY_SIZE"/>
+            <enum name="GL_COLOR_ARRAY_STRIDE"/>
+            <enum name="GL_COLOR_ARRAY_TYPE"/>
+            <enum name="GL_COLOR_CLEAR_VALUE"/>
+            <enum name="GL_COLOR_LOGIC_OP"/>
+            <enum name="GL_COLOR_MATERIAL"/>
+            <enum name="GL_COLOR_MATERIAL_FACE"/>
+            <enum name="GL_COLOR_MATERIAL_PARAMETER"/>
+            <enum name="GL_COLOR_MATRIX_SGI"/>
+            <enum name="GL_COLOR_MATRIX_STACK_DEPTH_SGI"/>
+            <enum name="GL_COLOR_TABLE_SGI"/>
+            <enum name="GL_COLOR_WRITEMASK"/>
+            <enum name="GL_CONVOLUTION_1D_EXT"/>
+            <enum name="GL_CONVOLUTION_2D_EXT"/>
+            <enum name="GL_CONVOLUTION_HINT_SGIX"/>
+            <enum name="GL_CULL_FACE"/>
+            <enum name="GL_CULL_FACE_MODE"/>
+            <enum name="GL_CURRENT_COLOR"/>
+            <enum name="GL_CURRENT_INDEX"/>
+            <enum name="GL_CURRENT_NORMAL"/>
+            <enum name="GL_CURRENT_RASTER_COLOR"/>
+            <enum name="GL_CURRENT_RASTER_DISTANCE"/>
+            <enum name="GL_CURRENT_RASTER_INDEX"/>
+            <enum name="GL_CURRENT_RASTER_POSITION"/>
+            <enum name="GL_CURRENT_RASTER_POSITION_VALID"/>
+            <enum name="GL_CURRENT_RASTER_TEXTURE_COORDS"/>
+            <enum name="GL_CURRENT_TEXTURE_COORDS"/>
+            <enum name="GL_DEFORMATIONS_MASK_SGIX"/>
+            <enum name="GL_DEPTH_BIAS"/>
+            <enum name="GL_DEPTH_BITS"/>
+            <enum name="GL_DEPTH_CLEAR_VALUE"/>
+            <enum name="GL_DEPTH_FUNC"/>
+            <enum name="GL_DEPTH_RANGE"/>
+            <enum name="GL_DEPTH_SCALE"/>
+            <enum name="GL_DEPTH_TEST"/>
+            <enum name="GL_DEPTH_WRITEMASK"/>
+            <enum name="GL_DETAIL_TEXTURE_2D_BINDING_SGIS"/>
+            <enum name="GL_DISTANCE_ATTENUATION_SGIS"/>
+            <enum name="GL_DITHER"/>
+            <enum name="GL_DOUBLEBUFFER"/>
+            <enum name="GL_DRAW_BUFFER"/>
+            <enum name="GL_DRAW_BUFFER_EXT"/>
+            <enum name="GL_EDGE_FLAG"/>
+            <enum name="GL_EDGE_FLAG_ARRAY"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_COUNT_EXT"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_STRIDE"/>
+            <enum name="GL_FEEDBACK_BUFFER_SIZE"/>
+            <enum name="GL_FEEDBACK_BUFFER_TYPE"/>
+            <enum name="GL_FOG"/>
+            <enum name="GL_FOG_COLOR"/>
+            <enum name="GL_FOG_DENSITY"/>
+            <enum name="GL_FOG_END"/>
+            <enum name="GL_FOG_FUNC_POINTS_SGIS"/>
+            <enum name="GL_FOG_HINT"/>
+            <enum name="GL_FOG_INDEX"/>
+            <enum name="GL_FOG_MODE"/>
+            <enum name="GL_FOG_OFFSET_SGIX"/>
+            <enum name="GL_FOG_OFFSET_VALUE_SGIX"/>
+            <enum name="GL_FOG_START"/>
+            <enum name="GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX"/>
+            <enum name="GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX"/>
+            <enum name="GL_FRAGMENT_COLOR_MATERIAL_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT0_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHTING_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX"/>
+            <enum name="GL_FRAMEZOOM_FACTOR_SGIX"/>
+            <enum name="GL_FRAMEZOOM_SGIX"/>
+            <enum name="GL_FRONT_FACE"/>
+            <enum name="GL_GENERATE_MIPMAP_HINT_SGIS"/>
+            <enum name="GL_GREEN_BIAS"/>
+            <enum name="GL_GREEN_BITS"/>
+            <enum name="GL_GREEN_SCALE"/>
+            <enum name="GL_HISTOGRAM_EXT"/>
+            <enum name="GL_INDEX_ARRAY"/>
+            <enum name="GL_INDEX_ARRAY_COUNT_EXT"/>
+            <enum name="GL_INDEX_ARRAY_STRIDE"/>
+            <enum name="GL_INDEX_ARRAY_TYPE"/>
+            <enum name="GL_INDEX_BITS"/>
+            <enum name="GL_INDEX_CLEAR_VALUE"/>
+            <enum name="GL_INDEX_LOGIC_OP"/>
+            <enum name="GL_INDEX_MODE"/>
+            <enum name="GL_INDEX_OFFSET"/>
+            <enum name="GL_INDEX_SHIFT"/>
+            <enum name="GL_INDEX_WRITEMASK"/>
+            <enum name="GL_INSTRUMENT_MEASUREMENTS_SGIX"/>
+            <enum name="GL_INTERLACE_SGIX"/>
+            <enum name="GL_IR_INSTRUMENT1_SGIX"/>
+            <enum name="GL_LIGHT0"/>
+            <enum name="GL_LIGHT1"/>
+            <enum name="GL_LIGHT2"/>
+            <enum name="GL_LIGHT3"/>
+            <enum name="GL_LIGHT4"/>
+            <enum name="GL_LIGHT5"/>
+            <enum name="GL_LIGHT6"/>
+            <enum name="GL_LIGHT7"/>
+            <enum name="GL_LIGHTING"/>
+            <enum name="GL_LIGHT_ENV_MODE_SGIX"/>
+            <enum name="GL_LIGHT_MODEL_AMBIENT"/>
+            <enum name="GL_LIGHT_MODEL_COLOR_CONTROL"/>
+            <enum name="GL_LIGHT_MODEL_LOCAL_VIEWER"/>
+            <enum name="GL_LIGHT_MODEL_TWO_SIDE"/>
+            <enum name="GL_LINE_SMOOTH"/>
+            <enum name="GL_LINE_SMOOTH_HINT"/>
+            <enum name="GL_LINE_STIPPLE"/>
+            <enum name="GL_LINE_STIPPLE_PATTERN"/>
+            <enum name="GL_LINE_STIPPLE_REPEAT"/>
+            <enum name="GL_LINE_WIDTH"/>
+            <enum name="GL_LINE_WIDTH_GRANULARITY"/>
+            <enum name="GL_LINE_WIDTH_RANGE"/>
+            <enum name="GL_LIST_BASE"/>
+            <enum name="GL_LIST_INDEX"/>
+            <enum name="GL_LIST_MODE"/>
+            <enum name="GL_LOGIC_OP"/>
+            <enum name="GL_LOGIC_OP_MODE"/>
+            <enum name="GL_MAP1_COLOR_4"/>
+            <enum name="GL_MAP1_GRID_DOMAIN"/>
+            <enum name="GL_MAP1_GRID_SEGMENTS"/>
+            <enum name="GL_MAP1_INDEX"/>
+            <enum name="GL_MAP1_NORMAL"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP1_VERTEX_3"/>
+            <enum name="GL_MAP1_VERTEX_4"/>
+            <enum name="GL_MAP2_COLOR_4"/>
+            <enum name="GL_MAP2_GRID_DOMAIN"/>
+            <enum name="GL_MAP2_GRID_SEGMENTS"/>
+            <enum name="GL_MAP2_INDEX"/>
+            <enum name="GL_MAP2_NORMAL"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP2_VERTEX_3"/>
+            <enum name="GL_MAP2_VERTEX_4"/>
+            <enum name="GL_MAP_COLOR"/>
+            <enum name="GL_MAP_STENCIL"/>
+            <enum name="GL_MATRIX_MODE"/>
+            <enum name="GL_MAX_3D_TEXTURE_SIZE_EXT"/>
+            <enum name="GL_MAX_4D_TEXTURE_SIZE_SGIS"/>
+            <enum name="GL_MAX_ACTIVE_LIGHTS_SGIX"/>
+            <enum name="GL_MAX_ASYNC_DRAW_PIXELS_SGIX"/>
+            <enum name="GL_MAX_ASYNC_HISTOGRAM_SGIX"/>
+            <enum name="GL_MAX_ASYNC_READ_PIXELS_SGIX"/>
+            <enum name="GL_MAX_ASYNC_TEX_IMAGE_SGIX"/>
+            <enum name="GL_MAX_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_MAX_CLIENT_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_MAX_CLIPMAP_DEPTH_SGIX"/>
+            <enum name="GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX"/>
+            <enum name="GL_MAX_CLIP_DISTANCES"/>
+            <enum name="GL_MAX_CLIP_PLANES"/>
+            <enum name="GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI"/>
+            <enum name="GL_MAX_EVAL_ORDER"/>
+            <enum name="GL_MAX_FOG_FUNC_POINTS_SGIS"/>
+            <enum name="GL_MAX_FRAGMENT_LIGHTS_SGIX"/>
+            <enum name="GL_MAX_FRAMEZOOM_FACTOR_SGIX"/>
+            <enum name="GL_MAX_LIGHTS"/>
+            <enum name="GL_MAX_LIST_NESTING"/>
+            <enum name="GL_MAX_MODELVIEW_STACK_DEPTH"/>
+            <enum name="GL_MAX_NAME_STACK_DEPTH"/>
+            <enum name="GL_MAX_PIXEL_MAP_TABLE"/>
+            <enum name="GL_MAX_PROJECTION_STACK_DEPTH"/>
+            <enum name="GL_MAX_TEXTURE_SIZE"/>
+            <enum name="GL_MAX_TEXTURE_STACK_DEPTH"/>
+            <enum name="GL_MAX_VIEWPORT_DIMS"/>
+            <enum name="GL_MINMAX_EXT"/>
+            <enum name="GL_MODELVIEW0_MATRIX_EXT"/>
+            <enum name="GL_MODELVIEW0_STACK_DEPTH_EXT"/>
+            <enum name="GL_MODELVIEW_MATRIX"/>
+            <enum name="GL_MODELVIEW_STACK_DEPTH"/>
+            <enum name="GL_MULTISAMPLE_SGIS"/>
+            <enum name="GL_NAME_STACK_DEPTH"/>
+            <enum name="GL_NORMALIZE"/>
+            <enum name="GL_NORMAL_ARRAY"/>
+            <enum name="GL_NORMAL_ARRAY_COUNT_EXT"/>
+            <enum name="GL_NORMAL_ARRAY_STRIDE"/>
+            <enum name="GL_NORMAL_ARRAY_TYPE"/>
+            <enum name="GL_PACK_ALIGNMENT"/>
+            <enum name="GL_PACK_CMYK_HINT_EXT"/>
+            <enum name="GL_PACK_IMAGE_DEPTH_SGIS"/>
+            <enum name="GL_PACK_IMAGE_HEIGHT_EXT"/>
+            <enum name="GL_PACK_LSB_FIRST"/>
+            <enum name="GL_PACK_RESAMPLE_SGIX"/>
+            <enum name="GL_PACK_ROW_LENGTH"/>
+            <enum name="GL_PACK_SKIP_IMAGES_EXT"/>
+            <enum name="GL_PACK_SKIP_PIXELS"/>
+            <enum name="GL_PACK_SKIP_ROWS"/>
+            <enum name="GL_PACK_SKIP_VOLUMES_SGIS"/>
+            <enum name="GL_PACK_SUBSAMPLE_RATE_SGIX"/>
+            <enum name="GL_PACK_SWAP_BYTES"/>
+            <enum name="GL_PERSPECTIVE_CORRECTION_HINT"/>
+            <enum name="GL_PIXEL_MAP_A_TO_A_SIZE"/>
+            <enum name="GL_PIXEL_MAP_B_TO_B_SIZE"/>
+            <enum name="GL_PIXEL_MAP_G_TO_G_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_A_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_B_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_G_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_I_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_R_SIZE"/>
+            <enum name="GL_PIXEL_MAP_R_TO_R_SIZE"/>
+            <enum name="GL_PIXEL_MAP_S_TO_S_SIZE"/>
+            <enum name="GL_PIXEL_TEXTURE_SGIS"/>
+            <enum name="GL_PIXEL_TEX_GEN_MODE_SGIX"/>
+            <enum name="GL_PIXEL_TEX_GEN_SGIX"/>
+            <enum name="GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX"/>
+            <enum name="GL_PIXEL_TILE_CACHE_INCREMENT_SGIX"/>
+            <enum name="GL_PIXEL_TILE_CACHE_SIZE_SGIX"/>
+            <enum name="GL_PIXEL_TILE_GRID_DEPTH_SGIX"/>
+            <enum name="GL_PIXEL_TILE_GRID_HEIGHT_SGIX"/>
+            <enum name="GL_PIXEL_TILE_GRID_WIDTH_SGIX"/>
+            <enum name="GL_PIXEL_TILE_HEIGHT_SGIX"/>
+            <enum name="GL_PIXEL_TILE_WIDTH_SGIX"/>
+            <enum name="GL_POINT_FADE_THRESHOLD_SIZE_SGIS"/>
+            <enum name="GL_POINT_SIZE"/>
+            <enum name="GL_POINT_SIZE_GRANULARITY"/>
+            <enum name="GL_POINT_SIZE_MAX_SGIS"/>
+            <enum name="GL_POINT_SIZE_MIN_SGIS"/>
+            <enum name="GL_POINT_SIZE_RANGE"/>
+            <enum name="GL_POINT_SMOOTH"/>
+            <enum name="GL_POINT_SMOOTH_HINT"/>
+            <enum name="GL_POLYGON_MODE"/>
+            <enum name="GL_POLYGON_OFFSET_BIAS_EXT"/>
+            <enum name="GL_POLYGON_OFFSET_FACTOR"/>
+            <enum name="GL_POLYGON_OFFSET_FILL"/>
+            <enum name="GL_POLYGON_OFFSET_LINE"/>
+            <enum name="GL_POLYGON_OFFSET_POINT"/>
+            <enum name="GL_POLYGON_OFFSET_UNITS"/>
+            <enum name="GL_POLYGON_SMOOTH"/>
+            <enum name="GL_POLYGON_SMOOTH_HINT"/>
+            <enum name="GL_POLYGON_STIPPLE"/>
+            <enum name="GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_RED_BIAS_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_RED_SCALE_SGI"/>
+            <enum name="GL_POST_CONVOLUTION_ALPHA_BIAS_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_ALPHA_SCALE_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_BLUE_BIAS_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_BLUE_SCALE_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_COLOR_TABLE_SGI"/>
+            <enum name="GL_POST_CONVOLUTION_GREEN_BIAS_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_GREEN_SCALE_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_RED_BIAS_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_RED_SCALE_EXT"/>
+            <enum name="GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX"/>
+            <enum name="GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX"/>
+            <enum name="GL_PROJECTION_MATRIX"/>
+            <enum name="GL_PROJECTION_STACK_DEPTH"/>
+            <enum name="GL_READ_BUFFER"/>
+            <enum name="GL_READ_BUFFER_EXT"/>
+            <enum name="GL_READ_BUFFER_NV"/>
+            <enum name="GL_RED_BIAS"/>
+            <enum name="GL_RED_BITS"/>
+            <enum name="GL_RED_SCALE"/>
+            <enum name="GL_REFERENCE_PLANE_EQUATION_SGIX"/>
+            <enum name="GL_REFERENCE_PLANE_SGIX"/>
+            <enum name="GL_RENDER_MODE"/>
+            <enum name="GL_RESCALE_NORMAL_EXT"/>
+            <enum name="GL_RGBA_MODE"/>
+            <enum name="GL_SAMPLES_SGIS"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_MASK_SGIS"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_ONE_SGIS"/>
+            <enum name="GL_SAMPLE_BUFFERS_SGIS"/>
+            <enum name="GL_SAMPLE_MASK_INVERT_SGIS"/>
+            <enum name="GL_SAMPLE_MASK_SGIS"/>
+            <enum name="GL_SAMPLE_MASK_VALUE_SGIS"/>
+            <enum name="GL_SAMPLE_PATTERN_SGIS"/>
+            <enum name="GL_SCISSOR_BOX"/>
+            <enum name="GL_SCISSOR_TEST"/>
+            <enum name="GL_SELECTION_BUFFER_SIZE"/>
+            <enum name="GL_SEPARABLE_2D_EXT"/>
+            <enum name="GL_SHADE_MODEL"/>
+            <enum name="GL_SHARED_TEXTURE_PALETTE_EXT"/>
+            <enum name="GL_SMOOTH_LINE_WIDTH_GRANULARITY"/>
+            <enum name="GL_SMOOTH_LINE_WIDTH_RANGE"/>
+            <enum name="GL_SMOOTH_POINT_SIZE_GRANULARITY"/>
+            <enum name="GL_SMOOTH_POINT_SIZE_RANGE"/>
+            <enum name="GL_SPRITE_AXIS_SGIX"/>
+            <enum name="GL_SPRITE_MODE_SGIX"/>
+            <enum name="GL_SPRITE_SGIX"/>
+            <enum name="GL_SPRITE_TRANSLATION_SGIX"/>
+            <enum name="GL_STENCIL_BITS"/>
+            <enum name="GL_STENCIL_CLEAR_VALUE"/>
+            <enum name="GL_STENCIL_FAIL"/>
+            <enum name="GL_STENCIL_FUNC"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_FAIL"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_PASS"/>
+            <enum name="GL_STENCIL_REF"/>
+            <enum name="GL_STENCIL_TEST"/>
+            <enum name="GL_STENCIL_VALUE_MASK"/>
+            <enum name="GL_STENCIL_WRITEMASK"/>
+            <enum name="GL_STEREO"/>
+            <enum name="GL_SUBPIXEL_BITS"/>
+            <enum name="GL_TEXTURE_1D"/>
+            <enum name="GL_TEXTURE_2D"/>
+            <enum name="GL_TEXTURE_3D_BINDING_EXT"/>
+            <enum name="GL_TEXTURE_3D_EXT"/>
+            <enum name="GL_TEXTURE_4D_BINDING_SGIS"/>
+            <enum name="GL_TEXTURE_4D_SGIS"/>
+            <enum name="GL_TEXTURE_BINDING_1D"/>
+            <enum name="GL_TEXTURE_BINDING_2D"/>
+            <enum name="GL_TEXTURE_BINDING_3D"/>
+            <enum name="GL_TEXTURE_COLOR_TABLE_SGI"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_COUNT_EXT"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_SIZE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_STRIDE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_TYPE"/>
+            <enum name="GL_TEXTURE_GEN_Q"/>
+            <enum name="GL_TEXTURE_GEN_R"/>
+            <enum name="GL_TEXTURE_GEN_S"/>
+            <enum name="GL_TEXTURE_GEN_T"/>
+            <enum name="GL_TEXTURE_MATRIX"/>
+            <enum name="GL_TEXTURE_STACK_DEPTH"/>
+            <enum name="GL_UNPACK_ALIGNMENT"/>
+            <enum name="GL_UNPACK_CMYK_HINT_EXT"/>
+            <enum name="GL_UNPACK_IMAGE_DEPTH_SGIS"/>
+            <enum name="GL_UNPACK_IMAGE_HEIGHT_EXT"/>
+            <enum name="GL_UNPACK_LSB_FIRST"/>
+            <enum name="GL_UNPACK_RESAMPLE_SGIX"/>
+            <enum name="GL_UNPACK_ROW_LENGTH"/>
+            <enum name="GL_UNPACK_SKIP_IMAGES_EXT"/>
+            <enum name="GL_UNPACK_SKIP_PIXELS"/>
+            <enum name="GL_UNPACK_SKIP_ROWS"/>
+            <enum name="GL_UNPACK_SKIP_VOLUMES_SGIS"/>
+            <enum name="GL_UNPACK_SUBSAMPLE_RATE_SGIX"/>
+            <enum name="GL_UNPACK_SWAP_BYTES"/>
+            <enum name="GL_VERTEX_ARRAY"/>
+            <enum name="GL_VERTEX_ARRAY_COUNT_EXT"/>
+            <enum name="GL_VERTEX_ARRAY_SIZE"/>
+            <enum name="GL_VERTEX_ARRAY_STRIDE"/>
+            <enum name="GL_VERTEX_ARRAY_TYPE"/>
+            <enum name="GL_VERTEX_PRECLIP_HINT_SGIX"/>
+            <enum name="GL_VERTEX_PRECLIP_SGIX"/>
+            <enum name="GL_VIEWPORT"/>
+            <enum name="GL_ZOOM_X"/>
+            <enum name="GL_ZOOM_Y"/>
+        </group>
+
+        <group name="GetPointervPName">
+            <enum name="GL_COLOR_ARRAY_POINTER"/>
+            <enum name="GL_COLOR_ARRAY_POINTER_EXT"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_POINTER"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_POINTER_EXT"/>
+            <enum name="GL_FEEDBACK_BUFFER_POINTER"/>
+            <enum name="GL_INDEX_ARRAY_POINTER"/>
+            <enum name="GL_INDEX_ARRAY_POINTER_EXT"/>
+            <enum name="GL_INSTRUMENT_BUFFER_POINTER_SGIX"/>
+            <enum name="GL_NORMAL_ARRAY_POINTER"/>
+            <enum name="GL_NORMAL_ARRAY_POINTER_EXT"/>
+            <enum name="GL_SELECTION_BUFFER_POINTER"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_POINTER"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_POINTER_EXT"/>
+            <enum name="GL_VERTEX_ARRAY_POINTER"/>
+            <enum name="GL_VERTEX_ARRAY_POINTER_EXT"/>
+        </group>
+
+        <group name="GetTextureParameter">
+            <enum name="GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS"/>
+            <enum name="GL_DETAIL_TEXTURE_LEVEL_SGIS"/>
+            <enum name="GL_DETAIL_TEXTURE_MODE_SGIS"/>
+            <enum name="GL_DUAL_TEXTURE_SELECT_SGIS"/>
+            <enum name="GL_GENERATE_MIPMAP_SGIS"/>
+            <enum name="GL_POST_TEXTURE_FILTER_BIAS_SGIX"/>
+            <enum name="GL_POST_TEXTURE_FILTER_SCALE_SGIX"/>
+            <enum name="GL_QUAD_TEXTURE_SELECT_SGIS"/>
+            <enum name="GL_SHADOW_AMBIENT_SGIX"/>
+            <enum name="GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS"/>
+            <enum name="GL_TEXTURE_4DSIZE_SGIS"/>
+            <enum name="GL_TEXTURE_ALPHA_SIZE"/>
+            <enum name="GL_TEXTURE_BASE_LEVEL_SGIS"/>
+            <enum name="GL_TEXTURE_BLUE_SIZE"/>
+            <enum name="GL_TEXTURE_BORDER"/>
+            <enum name="GL_TEXTURE_BORDER_COLOR"/>
+            <enum name="GL_TEXTURE_BORDER_COLOR_NV"/>
+            <enum name="GL_TEXTURE_CLIPMAP_CENTER_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_DEPTH_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_FRAME_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_OFFSET_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX"/>
+            <enum name="GL_TEXTURE_COMPARE_OPERATOR_SGIX"/>
+            <enum name="GL_TEXTURE_COMPARE_SGIX"/>
+            <enum name="GL_TEXTURE_COMPONENTS"/>
+            <enum name="GL_TEXTURE_DEPTH_EXT"/>
+            <enum name="GL_TEXTURE_FILTER4_SIZE_SGIS"/>
+            <enum name="GL_TEXTURE_GEQUAL_R_SGIX"/>
+            <enum name="GL_TEXTURE_GREEN_SIZE"/>
+            <enum name="GL_TEXTURE_HEIGHT"/>
+            <enum name="GL_TEXTURE_INTENSITY_SIZE"/>
+            <enum name="GL_TEXTURE_INTERNAL_FORMAT"/>
+            <enum name="GL_TEXTURE_LEQUAL_R_SGIX"/>
+            <enum name="GL_TEXTURE_LOD_BIAS_R_SGIX"/>
+            <enum name="GL_TEXTURE_LOD_BIAS_S_SGIX"/>
+            <enum name="GL_TEXTURE_LOD_BIAS_T_SGIX"/>
+            <enum name="GL_TEXTURE_LUMINANCE_SIZE"/>
+            <enum name="GL_TEXTURE_MAG_FILTER"/>
+            <enum name="GL_TEXTURE_MAX_CLAMP_R_SGIX"/>
+            <enum name="GL_TEXTURE_MAX_CLAMP_S_SGIX"/>
+            <enum name="GL_TEXTURE_MAX_CLAMP_T_SGIX"/>
+            <enum name="GL_TEXTURE_MAX_LEVEL_SGIS"/>
+            <enum name="GL_TEXTURE_MAX_LOD_SGIS"/>
+            <enum name="GL_TEXTURE_MIN_FILTER"/>
+            <enum name="GL_TEXTURE_MIN_LOD_SGIS"/>
+            <enum name="GL_TEXTURE_PRIORITY"/>
+            <enum name="GL_TEXTURE_RED_SIZE"/>
+            <enum name="GL_TEXTURE_RESIDENT"/>
+            <enum name="GL_TEXTURE_WIDTH"/>
+            <enum name="GL_TEXTURE_WRAP_Q_SGIS"/>
+            <enum name="GL_TEXTURE_WRAP_R_EXT"/>
+            <enum name="GL_TEXTURE_WRAP_S"/>
+            <enum name="GL_TEXTURE_WRAP_T"/>
+        </group>
+
+        <group name="HintMode">
+            <enum name="GL_DONT_CARE"/>
+            <enum name="GL_FASTEST"/>
+            <enum name="GL_NICEST"/>
+        </group>
+
+        <group name="HintTarget">
+            <enum name="GL_ALLOW_DRAW_FRG_HINT_PGI"/>
+            <enum name="GL_ALLOW_DRAW_MEM_HINT_PGI"/>
+            <enum name="GL_ALLOW_DRAW_OBJ_HINT_PGI"/>
+            <enum name="GL_ALLOW_DRAW_WIN_HINT_PGI"/>
+            <enum name="GL_ALWAYS_FAST_HINT_PGI"/>
+            <enum name="GL_ALWAYS_SOFT_HINT_PGI"/>
+            <enum name="GL_BACK_NORMALS_HINT_PGI"/>
+            <enum name="GL_BINNING_CONTROL_HINT_QCOM"/>
+            <enum name="GL_CLIP_FAR_HINT_PGI"/>
+            <enum name="GL_CLIP_NEAR_HINT_PGI"/>
+            <enum name="GL_CLIP_VOLUME_CLIPPING_HINT_EXT"/>
+            <enum name="GL_CONSERVE_MEMORY_HINT_PGI"/>
+            <enum name="GL_CONVOLUTION_HINT_SGIX"/>
+            <enum name="GL_FOG_HINT"/>
+            <enum name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT"/>
+            <enum name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB"/>
+            <enum name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES"/>
+            <enum name="GL_FULL_STIPPLE_HINT_PGI"/>
+            <enum name="GL_GENERATE_MIPMAP_HINT"/>
+            <enum name="GL_GENERATE_MIPMAP_HINT_SGIS"/>
+            <enum name="GL_LINE_QUALITY_HINT_SGIX"/>
+            <enum name="GL_LINE_SMOOTH_HINT"/>
+            <enum name="GL_MATERIAL_SIDE_HINT_PGI"/>
+            <enum name="GL_MAX_VERTEX_HINT_PGI"/>
+            <enum name="GL_MULTISAMPLE_FILTER_HINT_NV"/>
+            <enum name="GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI"/>
+            <enum name="GL_NATIVE_GRAPHICS_END_HINT_PGI"/>
+            <enum name="GL_PACK_CMYK_HINT_EXT"/>
+            <enum name="GL_PERSPECTIVE_CORRECTION_HINT"/>
+            <enum name="GL_PHONG_HINT_WIN"/>
+            <enum name="GL_POINT_SMOOTH_HINT"/>
+            <enum name="GL_POLYGON_SMOOTH_HINT"/>
+            <enum name="GL_PREFER_DOUBLEBUFFER_HINT_PGI"/>
+            <enum name="GL_PROGRAM_BINARY_RETRIEVABLE_HINT"/>
+            <enum name="GL_RECLAIM_MEMORY_HINT_PGI"/>
+            <enum name="GL_SCALEBIAS_HINT_SGIX"/>
+            <enum name="GL_STRICT_DEPTHFUNC_HINT_PGI"/>
+            <enum name="GL_STRICT_LIGHTING_HINT_PGI"/>
+            <enum name="GL_STRICT_SCISSOR_HINT_PGI"/>
+            <enum name="GL_TEXTURE_COMPRESSION_HINT"/>
+            <enum name="GL_TEXTURE_COMPRESSION_HINT_ARB"/>
+            <enum name="GL_TEXTURE_MULTI_BUFFER_HINT_SGIX"/>
+            <enum name="GL_TEXTURE_STORAGE_HINT_APPLE"/>
+            <enum name="GL_TRANSFORM_HINT_APPLE"/>
+            <enum name="GL_UNPACK_CMYK_HINT_EXT"/>
+            <enum name="GL_VERTEX_ARRAY_STORAGE_HINT_APPLE"/>
+            <enum name="GL_VERTEX_CONSISTENT_HINT_PGI"/>
+            <enum name="GL_VERTEX_DATA_HINT_PGI"/>
+            <enum name="GL_VERTEX_PRECLIP_HINT_SGIX"/>
+            <enum name="GL_VERTEX_PRECLIP_SGIX"/>
+            <enum name="GL_WIDE_LINE_HINT_PGI"/>
+        </group>
+
+        <group name="HistogramTargetEXT">
+            <enum name="GL_HISTOGRAM"/>
+            <enum name="GL_HISTOGRAM_EXT"/>
+            <enum name="GL_PROXY_HISTOGRAM"/>
+            <enum name="GL_PROXY_HISTOGRAM_EXT"/>
+        </group>
+
+        <group name="IndexPointerType">
+            <enum name="GL_DOUBLE"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_SHORT"/>
+        </group>
+
+        <group name="InterleavedArrayFormat">
+            <enum name="GL_C3F_V3F"/>
+            <enum name="GL_C4F_N3F_V3F"/>
+            <enum name="GL_C4UB_V2F"/>
+            <enum name="GL_C4UB_V3F"/>
+            <enum name="GL_N3F_V3F"/>
+            <enum name="GL_T2F_C3F_V3F"/>
+            <enum name="GL_T2F_C4F_N3F_V3F"/>
+            <enum name="GL_T2F_C4UB_V3F"/>
+            <enum name="GL_T2F_N3F_V3F"/>
+            <enum name="GL_T2F_V3F"/>
+            <enum name="GL_T4F_C4F_N3F_V4F"/>
+            <enum name="GL_T4F_V4F"/>
+            <enum name="GL_V2F"/>
+            <enum name="GL_V3F"/>
+        </group>
+
+        <group name="LightEnvModeSGIX">
+            <enum name="GL_ADD"/>
+            <enum name="GL_MODULATE"/>
+            <enum name="GL_REPLACE"/>
+        </group>
+
+        <group name="LightEnvParameterSGIX">
+            <enum name="GL_LIGHT_ENV_MODE_SGIX"/>
+        </group>
+
+        <group name="LightModelColorControl">
+            <enum name="GL_SEPARATE_SPECULAR_COLOR"/>
+            <enum name="GL_SEPARATE_SPECULAR_COLOR_EXT"/>
+            <enum name="GL_SINGLE_COLOR"/>
+            <enum name="GL_SINGLE_COLOR_EXT"/>
+        </group>
+
+        <group name="LightModelParameter">
+            <enum name="GL_LIGHT_MODEL_AMBIENT"/>
+            <enum name="GL_LIGHT_MODEL_COLOR_CONTROL"/>
+            <enum name="GL_LIGHT_MODEL_COLOR_CONTROL_EXT"/>
+            <enum name="GL_LIGHT_MODEL_LOCAL_VIEWER"/>
+            <enum name="GL_LIGHT_MODEL_TWO_SIDE"/>
+        </group>
+
+        <group name="LightName">
+            <enum name="GL_FRAGMENT_LIGHT0_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT1_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT2_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT3_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT4_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT5_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT6_SGIX"/>
+            <enum name="GL_FRAGMENT_LIGHT7_SGIX"/>
+            <enum name="GL_LIGHT0"/>
+            <enum name="GL_LIGHT1"/>
+            <enum name="GL_LIGHT2"/>
+            <enum name="GL_LIGHT3"/>
+            <enum name="GL_LIGHT4"/>
+            <enum name="GL_LIGHT5"/>
+            <enum name="GL_LIGHT6"/>
+            <enum name="GL_LIGHT7"/>
+        </group>
+
+        <group name="LightParameter">
+            <enum name="GL_AMBIENT"/>
+            <enum name="GL_CONSTANT_ATTENUATION"/>
+            <enum name="GL_DIFFUSE"/>
+            <enum name="GL_LINEAR_ATTENUATION"/>
+            <enum name="GL_POSITION"/>
+            <enum name="GL_QUADRATIC_ATTENUATION"/>
+            <enum name="GL_SPECULAR"/>
+            <enum name="GL_SPOT_CUTOFF"/>
+            <enum name="GL_SPOT_DIRECTION"/>
+            <enum name="GL_SPOT_EXPONENT"/>
+        </group>
+
+        <group name="ListMode">
+            <enum name="GL_COMPILE"/>
+            <enum name="GL_COMPILE_AND_EXECUTE"/>
+        </group>
+
+        <group name="ListNameType">
+            <enum name="GL_2_BYTES"/>
+            <enum name="GL_3_BYTES"/>
+            <enum name="GL_4_BYTES"/>
+            <enum name="GL_BYTE"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_SHORT"/>
+            <enum name="GL_UNSIGNED_BYTE"/>
+            <enum name="GL_UNSIGNED_INT"/>
+            <enum name="GL_UNSIGNED_SHORT"/>
+        </group>
+
+        <group name="ListParameterName">
+            <enum name="GL_LIST_PRIORITY_SGIX"/>
+        </group>
+
+        <group name="LogicOp">
+            <enum name="GL_AND"/>
+            <enum name="GL_AND_INVERTED"/>
+            <enum name="GL_AND_REVERSE"/>
+            <enum name="GL_CLEAR"/>
+            <enum name="GL_COPY"/>
+            <enum name="GL_COPY_INVERTED"/>
+            <enum name="GL_EQUIV"/>
+            <enum name="GL_INVERT"/>
+            <enum name="GL_NAND"/>
+            <enum name="GL_NOOP"/>
+            <enum name="GL_NOR"/>
+            <enum name="GL_OR"/>
+            <enum name="GL_OR_INVERTED"/>
+            <enum name="GL_OR_REVERSE"/>
+            <enum name="GL_SET"/>
+            <enum name="GL_XOR"/>
+        </group>
+
+        <group name="MapBufferUsageMask">
+            <enum name="GL_CLIENT_STORAGE_BIT"/>
+            <enum name="GL_DYNAMIC_STORAGE_BIT"/>
+            <enum name="GL_MAP_COHERENT_BIT"/>
+            <enum name="GL_MAP_FLUSH_EXPLICIT_BIT"/>
+            <enum name="GL_MAP_FLUSH_EXPLICIT_BIT_EXT"/>
+            <enum name="GL_MAP_INVALIDATE_BUFFER_BIT"/>
+            <enum name="GL_MAP_INVALIDATE_BUFFER_BIT_EXT"/>
+            <enum name="GL_MAP_INVALIDATE_RANGE_BIT"/>
+            <enum name="GL_MAP_INVALIDATE_RANGE_BIT_EXT"/>
+            <enum name="GL_MAP_PERSISTENT_BIT"/>
+            <enum name="GL_MAP_READ_BIT"/>
+            <enum name="GL_MAP_READ_BIT_EXT"/>
+            <enum name="GL_MAP_UNSYNCHRONIZED_BIT"/>
+            <enum name="GL_MAP_UNSYNCHRONIZED_BIT_EXT"/>
+            <enum name="GL_MAP_WRITE_BIT"/>
+            <enum name="GL_MAP_WRITE_BIT_EXT"/>
+        </group>
+
+        <group name="MapTarget">
+            <enum name="GL_GEOMETRY_DEFORMATION_SGIX"/>
+            <enum name="GL_MAP1_COLOR_4"/>
+            <enum name="GL_MAP1_INDEX"/>
+            <enum name="GL_MAP1_NORMAL"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP1_VERTEX_3"/>
+            <enum name="GL_MAP1_VERTEX_4"/>
+            <enum name="GL_MAP2_COLOR_4"/>
+            <enum name="GL_MAP2_INDEX"/>
+            <enum name="GL_MAP2_NORMAL"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP2_VERTEX_3"/>
+            <enum name="GL_MAP2_VERTEX_4"/>
+            <enum name="GL_TEXTURE_DEFORMATION_SGIX"/>
+        </group>
+
+        <group name="MapTextureFormatINTEL">
+            <enum name="GL_LAYOUT_DEFAULT_INTEL"/>
+            <enum name="GL_LAYOUT_LINEAR_CPU_CACHED_INTEL"/>
+            <enum name="GL_LAYOUT_LINEAR_INTEL"/>
+        </group>
+
+        <group name="MaterialFace">
+            <enum name="GL_BACK"/>
+            <enum name="GL_FRONT"/>
+            <enum name="GL_FRONT_AND_BACK"/>
+        </group>
+
+        <group name="MaterialParameter">
+            <enum name="GL_AMBIENT"/>
+            <enum name="GL_AMBIENT_AND_DIFFUSE"/>
+            <enum name="GL_COLOR_INDEXES"/>
+            <enum name="GL_DIFFUSE"/>
+            <enum name="GL_EMISSION"/>
+            <enum name="GL_SHININESS"/>
+            <enum name="GL_SPECULAR"/>
+        </group>
+
+        <group name="MatrixMode">
+            <enum name="GL_MODELVIEW"/>
+            <enum name="GL_MODELVIEW0_EXT"/>
+            <enum name="GL_PROJECTION"/>
+            <enum name="GL_TEXTURE"/>
+        </group>
+
+        <group name="MemoryBarrierMask">
+            <enum name="GL_ALL_BARRIER_BITS"/>
+            <enum name="GL_ALL_BARRIER_BITS_EXT"/>
+            <enum name="GL_ATOMIC_COUNTER_BARRIER_BIT"/>
+            <enum name="GL_ATOMIC_COUNTER_BARRIER_BIT_EXT"/>
+            <enum name="GL_BUFFER_UPDATE_BARRIER_BIT"/>
+            <enum name="GL_BUFFER_UPDATE_BARRIER_BIT_EXT"/>
+            <enum name="GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT"/>
+            <enum name="GL_COMMAND_BARRIER_BIT"/>
+            <enum name="GL_COMMAND_BARRIER_BIT_EXT"/>
+            <enum name="GL_ELEMENT_ARRAY_BARRIER_BIT"/>
+            <enum name="GL_ELEMENT_ARRAY_BARRIER_BIT_EXT"/>
+            <enum name="GL_FRAMEBUFFER_BARRIER_BIT"/>
+            <enum name="GL_FRAMEBUFFER_BARRIER_BIT_EXT"/>
+            <enum name="GL_PIXEL_BUFFER_BARRIER_BIT"/>
+            <enum name="GL_PIXEL_BUFFER_BARRIER_BIT_EXT"/>
+            <enum name="GL_QUERY_BUFFER_BARRIER_BIT"/>
+            <enum name="GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV"/>
+            <enum name="GL_SHADER_IMAGE_ACCESS_BARRIER_BIT"/>
+            <enum name="GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT"/>
+            <enum name="GL_SHADER_STORAGE_BARRIER_BIT"/>
+            <enum name="GL_TEXTURE_FETCH_BARRIER_BIT"/>
+            <enum name="GL_TEXTURE_FETCH_BARRIER_BIT_EXT"/>
+            <enum name="GL_TEXTURE_UPDATE_BARRIER_BIT"/>
+            <enum name="GL_TEXTURE_UPDATE_BARRIER_BIT_EXT"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BARRIER_BIT"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT"/>
+            <enum name="GL_UNIFORM_BARRIER_BIT"/>
+            <enum name="GL_UNIFORM_BARRIER_BIT_EXT"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT"/>
+        </group>
+
+        <group name="MeshMode1">
+            <enum name="GL_LINE"/>
+            <enum name="GL_POINT"/>
+        </group>
+
+        <group name="MeshMode2">
+            <enum name="GL_FILL"/>
+            <enum name="GL_LINE"/>
+            <enum name="GL_POINT"/>
+        </group>
+
+        <group name="MinmaxTargetEXT">
+            <enum name="GL_MINMAX"/>
+            <enum name="GL_MINMAX_EXT"/>
+        </group>
+
+        <group name="NormalPointerType">
+            <enum name="GL_BYTE"/>
+            <enum name="GL_DOUBLE"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_SHORT"/>
+        </group>
+
+        <group name="PixelCopyType">
+            <enum name="GL_COLOR"/>
+            <enum name="GL_COLOR_EXT"/>
+            <enum name="GL_DEPTH"/>
+            <enum name="GL_DEPTH_EXT"/>
+            <enum name="GL_STENCIL"/>
+            <enum name="GL_STENCIL_EXT"/>
+        </group>
+
+        <group name="PixelFormat">
+            <enum name="GL_ABGR_EXT"/>
+            <enum name="GL_ALPHA"/>
+            <enum name="GL_BLUE"/>
+            <enum name="GL_CMYKA_EXT"/>
+            <enum name="GL_CMYK_EXT"/>
+            <enum name="GL_COLOR_INDEX"/>
+            <enum name="GL_DEPTH_COMPONENT"/>
+            <enum name="GL_GREEN"/>
+            <enum name="GL_LUMINANCE"/>
+            <enum name="GL_LUMINANCE_ALPHA"/>
+            <enum name="GL_RED"/>
+            <enum name="GL_RED_EXT"/>
+            <enum name="GL_RGB"/>
+            <enum name="GL_RGBA"/>
+            <enum name="GL_STENCIL_INDEX"/>
+            <enum name="GL_UNSIGNED_INT"/>
+            <enum name="GL_UNSIGNED_SHORT"/>
+            <enum name="GL_YCRCB_422_SGIX"/>
+            <enum name="GL_YCRCB_444_SGIX"/>
+        </group>
+
+        <group name="InternalFormat" comment="Was PixelInternalFormat">
+            <enum name="GL_ALPHA12"/>
+            <enum name="GL_ALPHA16"/>
+            <enum name="GL_ALPHA16_ICC_SGIX"/>
+            <enum name="GL_ALPHA4"/>
+            <enum name="GL_ALPHA8"/>
+            <enum name="GL_ALPHA_ICC_SGIX"/>
+            <enum name="GL_DEPTH_COMPONENT16_SGIX"/>
+            <enum name="GL_DEPTH_COMPONENT24_SGIX"/>
+            <enum name="GL_DEPTH_COMPONENT32_SGIX"/>
+            <enum name="GL_DUAL_ALPHA12_SGIS"/>
+            <enum name="GL_DUAL_ALPHA16_SGIS"/>
+            <enum name="GL_DUAL_ALPHA4_SGIS"/>
+            <enum name="GL_DUAL_ALPHA8_SGIS"/>
+            <enum name="GL_DUAL_INTENSITY12_SGIS"/>
+            <enum name="GL_DUAL_INTENSITY16_SGIS"/>
+            <enum name="GL_DUAL_INTENSITY4_SGIS"/>
+            <enum name="GL_DUAL_INTENSITY8_SGIS"/>
+            <enum name="GL_DUAL_LUMINANCE12_SGIS"/>
+            <enum name="GL_DUAL_LUMINANCE16_SGIS"/>
+            <enum name="GL_DUAL_LUMINANCE4_SGIS"/>
+            <enum name="GL_DUAL_LUMINANCE8_SGIS"/>
+            <enum name="GL_DUAL_LUMINANCE_ALPHA4_SGIS"/>
+            <enum name="GL_DUAL_LUMINANCE_ALPHA8_SGIS"/>
+            <enum name="GL_INTENSITY"/>
+            <enum name="GL_INTENSITY12"/>
+            <enum name="GL_INTENSITY16"/>
+            <enum name="GL_INTENSITY16_ICC_SGIX"/>
+            <enum name="GL_INTENSITY4"/>
+            <enum name="GL_INTENSITY8"/>
+            <enum name="GL_INTENSITY_ICC_SGIX"/>
+            <enum name="GL_LUMINANCE12"/>
+            <enum name="GL_LUMINANCE12_ALPHA12"/>
+            <enum name="GL_LUMINANCE12_ALPHA4"/>
+            <enum name="GL_LUMINANCE16"/>
+            <enum name="GL_LUMINANCE16_ALPHA16"/>
+            <enum name="GL_LUMINANCE16_ALPHA8_ICC_SGIX"/>
+            <enum name="GL_LUMINANCE16_ICC_SGIX"/>
+            <enum name="GL_LUMINANCE4"/>
+            <enum name="GL_LUMINANCE4_ALPHA4"/>
+            <enum name="GL_LUMINANCE6_ALPHA2"/>
+            <enum name="GL_LUMINANCE8"/>
+            <enum name="GL_LUMINANCE8_ALPHA8"/>
+            <enum name="GL_LUMINANCE_ALPHA_ICC_SGIX"/>
+            <enum name="GL_LUMINANCE_ICC_SGIX"/>
+            <enum name="GL_QUAD_ALPHA4_SGIS"/>
+            <enum name="GL_QUAD_ALPHA8_SGIS"/>
+            <enum name="GL_QUAD_INTENSITY4_SGIS"/>
+            <enum name="GL_QUAD_INTENSITY8_SGIS"/>
+            <enum name="GL_QUAD_LUMINANCE4_SGIS"/>
+            <enum name="GL_QUAD_LUMINANCE8_SGIS"/>
+            <enum name="GL_R3_G3_B2"/>
+            <enum name="GL_R5_G6_B5_A8_ICC_SGIX"/>
+            <enum name="GL_R5_G6_B5_ICC_SGIX"/>
+            <enum name="GL_RGB10"/>
+            <enum name="GL_RGB10_A2"/>
+            <enum name="GL_RGB12"/>
+            <enum name="GL_RGB16"/>
+            <enum name="GL_RGB2_EXT"/>
+            <enum name="GL_RGB4"/>
+            <enum name="GL_RGB5"/>
+            <enum name="GL_RGB5_A1"/>
+            <enum name="GL_RGB8"/>
+            <enum name="GL_RGBA12"/>
+            <enum name="GL_RGBA16"/>
+            <enum name="GL_RGBA2"/>
+            <enum name="GL_RGBA4"/>
+            <enum name="GL_RGBA8"/>
+            <enum name="GL_RGBA_ICC_SGIX"/>
+            <enum name="GL_RGB_ICC_SGIX"/>
+        </group>
+
+        <group name="PixelMap">
+            <enum name="GL_PIXEL_MAP_A_TO_A"/>
+            <enum name="GL_PIXEL_MAP_B_TO_B"/>
+            <enum name="GL_PIXEL_MAP_G_TO_G"/>
+            <enum name="GL_PIXEL_MAP_I_TO_A"/>
+            <enum name="GL_PIXEL_MAP_I_TO_B"/>
+            <enum name="GL_PIXEL_MAP_I_TO_G"/>
+            <enum name="GL_PIXEL_MAP_I_TO_I"/>
+            <enum name="GL_PIXEL_MAP_I_TO_R"/>
+            <enum name="GL_PIXEL_MAP_R_TO_R"/>
+            <enum name="GL_PIXEL_MAP_S_TO_S"/>
+        </group>
+
+        <group name="PixelStoreParameter">
+            <enum name="GL_PACK_ALIGNMENT"/>
+            <enum name="GL_PACK_IMAGE_DEPTH_SGIS"/>
+            <enum name="GL_PACK_IMAGE_HEIGHT"/>
+            <enum name="GL_PACK_IMAGE_HEIGHT_EXT"/>
+            <enum name="GL_PACK_LSB_FIRST"/>
+            <enum name="GL_PACK_RESAMPLE_OML"/>
+            <enum name="GL_PACK_RESAMPLE_SGIX"/>
+            <enum name="GL_PACK_ROW_LENGTH"/>
+            <enum name="GL_PACK_SKIP_IMAGES"/>
+            <enum name="GL_PACK_SKIP_IMAGES_EXT"/>
+            <enum name="GL_PACK_SKIP_PIXELS"/>
+            <enum name="GL_PACK_SKIP_ROWS"/>
+            <enum name="GL_PACK_SKIP_VOLUMES_SGIS"/>
+            <enum name="GL_PACK_SUBSAMPLE_RATE_SGIX"/>
+            <enum name="GL_PACK_SWAP_BYTES"/>
+            <enum name="GL_PIXEL_TILE_CACHE_SIZE_SGIX"/>
+            <enum name="GL_PIXEL_TILE_GRID_DEPTH_SGIX"/>
+            <enum name="GL_PIXEL_TILE_GRID_HEIGHT_SGIX"/>
+            <enum name="GL_PIXEL_TILE_GRID_WIDTH_SGIX"/>
+            <enum name="GL_PIXEL_TILE_HEIGHT_SGIX"/>
+            <enum name="GL_PIXEL_TILE_WIDTH_SGIX"/>
+            <enum name="GL_UNPACK_ALIGNMENT"/>
+            <enum name="GL_UNPACK_IMAGE_DEPTH_SGIS"/>
+            <enum name="GL_UNPACK_IMAGE_HEIGHT"/>
+            <enum name="GL_UNPACK_IMAGE_HEIGHT_EXT"/>
+            <enum name="GL_UNPACK_LSB_FIRST"/>
+            <enum name="GL_UNPACK_RESAMPLE_OML"/>
+            <enum name="GL_UNPACK_RESAMPLE_SGIX"/>
+            <enum name="GL_UNPACK_ROW_LENGTH"/>
+            <enum name="GL_UNPACK_ROW_LENGTH_EXT"/>
+            <enum name="GL_UNPACK_SKIP_IMAGES"/>
+            <enum name="GL_UNPACK_SKIP_IMAGES_EXT"/>
+            <enum name="GL_UNPACK_SKIP_PIXELS"/>
+            <enum name="GL_UNPACK_SKIP_PIXELS_EXT"/>
+            <enum name="GL_UNPACK_SKIP_ROWS"/>
+            <enum name="GL_UNPACK_SKIP_ROWS_EXT"/>
+            <enum name="GL_UNPACK_SKIP_VOLUMES_SGIS"/>
+            <enum name="GL_UNPACK_SUBSAMPLE_RATE_SGIX"/>
+            <enum name="GL_UNPACK_SWAP_BYTES"/>
+        </group>
+
+        <group name="PixelStoreResampleMode">
+            <enum name="GL_RESAMPLE_DECIMATE_SGIX"/>
+            <enum name="GL_RESAMPLE_REPLICATE_SGIX"/>
+            <enum name="GL_RESAMPLE_ZERO_FILL_SGIX"/>
+        </group>
+
+        <group name="PixelStoreSubsampleRate">
+            <enum name="GL_PIXEL_SUBSAMPLE_2424_SGIX"/>
+            <enum name="GL_PIXEL_SUBSAMPLE_4242_SGIX"/>
+            <enum name="GL_PIXEL_SUBSAMPLE_4444_SGIX"/>
+        </group>
+
+        <group name="PixelTexGenMode">
+            <enum name="GL_LUMINANCE"/>
+            <enum name="GL_LUMINANCE_ALPHA"/>
+            <enum name="GL_NONE"/>
+            <enum name="GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX"/>
+            <enum name="GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX"/>
+            <enum name="GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX"/>
+            <enum name="GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX"/>
+            <enum name="GL_RGB"/>
+            <enum name="GL_RGBA"/>
+        </group>
+
+        <group name="PixelTexGenParameterNameSGIS">
+            <enum name="GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS"/>
+            <enum name="GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS"/>
+        </group>
+
+        <group name="PixelTransferParameter">
+            <enum name="GL_ALPHA_BIAS"/>
+            <enum name="GL_ALPHA_SCALE"/>
+            <enum name="GL_BLUE_BIAS"/>
+            <enum name="GL_BLUE_SCALE"/>
+            <enum name="GL_DEPTH_BIAS"/>
+            <enum name="GL_DEPTH_SCALE"/>
+            <enum name="GL_GREEN_BIAS"/>
+            <enum name="GL_GREEN_SCALE"/>
+            <enum name="GL_INDEX_OFFSET"/>
+            <enum name="GL_INDEX_SHIFT"/>
+            <enum name="GL_MAP_COLOR"/>
+            <enum name="GL_MAP_STENCIL"/>
+            <enum name="GL_POST_COLOR_MATRIX_ALPHA_BIAS"/>
+            <enum name="GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_ALPHA_SCALE"/>
+            <enum name="GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_BLUE_BIAS"/>
+            <enum name="GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_BLUE_SCALE"/>
+            <enum name="GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_GREEN_BIAS"/>
+            <enum name="GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_GREEN_SCALE"/>
+            <enum name="GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_RED_BIAS"/>
+            <enum name="GL_POST_COLOR_MATRIX_RED_BIAS_SGI"/>
+            <enum name="GL_POST_COLOR_MATRIX_RED_SCALE"/>
+            <enum name="GL_POST_COLOR_MATRIX_RED_SCALE_SGI"/>
+            <enum name="GL_POST_CONVOLUTION_ALPHA_BIAS"/>
+            <enum name="GL_POST_CONVOLUTION_ALPHA_BIAS_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_ALPHA_SCALE"/>
+            <enum name="GL_POST_CONVOLUTION_ALPHA_SCALE_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_BLUE_BIAS"/>
+            <enum name="GL_POST_CONVOLUTION_BLUE_BIAS_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_BLUE_SCALE"/>
+            <enum name="GL_POST_CONVOLUTION_BLUE_SCALE_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_GREEN_BIAS"/>
+            <enum name="GL_POST_CONVOLUTION_GREEN_BIAS_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_GREEN_SCALE"/>
+            <enum name="GL_POST_CONVOLUTION_GREEN_SCALE_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_RED_BIAS"/>
+            <enum name="GL_POST_CONVOLUTION_RED_BIAS_EXT"/>
+            <enum name="GL_POST_CONVOLUTION_RED_SCALE"/>
+            <enum name="GL_POST_CONVOLUTION_RED_SCALE_EXT"/>
+            <enum name="GL_RED_BIAS"/>
+            <enum name="GL_RED_SCALE"/>
+        </group>
+
+        <group name="PixelType">
+            <enum name="GL_BITMAP"/>
+            <enum name="GL_BYTE"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_SHORT"/>
+            <enum name="GL_UNSIGNED_BYTE"/>
+            <enum name="GL_UNSIGNED_BYTE_3_3_2"/>
+            <enum name="GL_UNSIGNED_BYTE_3_3_2_EXT"/>
+            <enum name="GL_UNSIGNED_INT"/>
+            <enum name="GL_UNSIGNED_INT_10_10_10_2"/>
+            <enum name="GL_UNSIGNED_INT_10_10_10_2_EXT"/>
+            <enum name="GL_UNSIGNED_INT_8_8_8_8"/>
+            <enum name="GL_UNSIGNED_INT_8_8_8_8_EXT"/>
+            <enum name="GL_UNSIGNED_SHORT"/>
+            <enum name="GL_UNSIGNED_SHORT_4_4_4_4"/>
+            <enum name="GL_UNSIGNED_SHORT_4_4_4_4_EXT"/>
+            <enum name="GL_UNSIGNED_SHORT_5_5_5_1"/>
+            <enum name="GL_UNSIGNED_SHORT_5_5_5_1_EXT"/>
+        </group>
+
+        <group name="PointParameterNameSGIS">
+            <enum name="GL_DISTANCE_ATTENUATION_EXT"/>
+            <enum name="GL_DISTANCE_ATTENUATION_SGIS"/>
+            <enum name="GL_POINT_DISTANCE_ATTENUATION"/>
+            <enum name="GL_POINT_DISTANCE_ATTENUATION_ARB"/>
+            <enum name="GL_POINT_FADE_THRESHOLD_SIZE"/>
+            <enum name="GL_POINT_FADE_THRESHOLD_SIZE_ARB"/>
+            <enum name="GL_POINT_FADE_THRESHOLD_SIZE_EXT"/>
+            <enum name="GL_POINT_FADE_THRESHOLD_SIZE_SGIS"/>
+            <enum name="GL_POINT_SIZE_MAX"/>
+            <enum name="GL_POINT_SIZE_MAX_ARB"/>
+            <enum name="GL_POINT_SIZE_MAX_EXT"/>
+            <enum name="GL_POINT_SIZE_MAX_SGIS"/>
+            <enum name="GL_POINT_SIZE_MIN"/>
+            <enum name="GL_POINT_SIZE_MIN_ARB"/>
+            <enum name="GL_POINT_SIZE_MIN_EXT"/>
+            <enum name="GL_POINT_SIZE_MIN_SGIS"/>
+        </group>
+
+        <group name="PolygonMode">
+            <enum name="GL_FILL"/>
+            <enum name="GL_LINE"/>
+            <enum name="GL_POINT"/>
+        </group>
+
+        <group name="PrimitiveType">
+            <enum name="GL_LINES"/>
+            <enum name="GL_LINES_ADJACENCY"/>
+            <enum name="GL_LINES_ADJACENCY_ARB"/>
+            <enum name="GL_LINES_ADJACENCY_EXT"/>
+            <enum name="GL_LINE_LOOP"/>
+            <enum name="GL_LINE_STRIP"/>
+            <enum name="GL_LINE_STRIP_ADJACENCY"/>
+            <enum name="GL_LINE_STRIP_ADJACENCY_ARB"/>
+            <enum name="GL_LINE_STRIP_ADJACENCY_EXT"/>
+            <enum name="GL_PATCHES"/>
+            <enum name="GL_PATCHES_EXT"/>
+            <enum name="GL_POINTS"/>
+            <enum name="GL_POLYGON"/>
+            <enum name="GL_QUADS"/>
+            <enum name="GL_QUADS_EXT"/>
+            <enum name="GL_QUAD_STRIP"/>
+            <enum name="GL_TRIANGLES"/>
+            <enum name="GL_TRIANGLES_ADJACENCY"/>
+            <enum name="GL_TRIANGLES_ADJACENCY_ARB"/>
+            <enum name="GL_TRIANGLES_ADJACENCY_EXT"/>
+            <enum name="GL_TRIANGLE_FAN"/>
+            <enum name="GL_TRIANGLE_STRIP"/>
+            <enum name="GL_TRIANGLE_STRIP_ADJACENCY"/>
+            <enum name="GL_TRIANGLE_STRIP_ADJACENCY_ARB"/>
+            <enum name="GL_TRIANGLE_STRIP_ADJACENCY_EXT"/>
+        </group>
+
+        <group name="OcclusionQueryEventMaskAMD">
+            <enum name="GL_QUERY_DEPTH_PASS_EVENT_BIT_AMD"/>
+            <enum name="GL_QUERY_DEPTH_FAIL_EVENT_BIT_AMD"/>
+            <enum name="GL_QUERY_STENCIL_FAIL_EVENT_BIT_AMD"/>
+            <enum name="GL_QUERY_DEPTH_BOUNDS_FAIL_EVENT_BIT_AMD"/>
+            <enum name="GL_QUERY_ALL_EVENT_BITS_AMD"/>
+        </group>
+
+        <group name="ReadBufferMode">
+            <enum name="GL_AUX0"/>
+            <enum name="GL_AUX1"/>
+            <enum name="GL_AUX2"/>
+            <enum name="GL_AUX3"/>
+            <enum name="GL_BACK"/>
+            <enum name="GL_BACK_LEFT"/>
+            <enum name="GL_BACK_RIGHT"/>
+            <enum name="GL_FRONT"/>
+            <enum name="GL_FRONT_LEFT"/>
+            <enum name="GL_FRONT_RIGHT"/>
+            <enum name="GL_LEFT"/>
+            <enum name="GL_RIGHT"/>
+        </group>
+
+        <group name="RenderingMode">
+            <enum name="GL_FEEDBACK"/>
+            <enum name="GL_RENDER"/>
+            <enum name="GL_SELECT"/>
+        </group>
+
+        <group name="SamplePatternSGIS">
+            <enum name="GL_1PASS_EXT"/>
+            <enum name="GL_1PASS_SGIS"/>
+            <enum name="GL_2PASS_0_EXT"/>
+            <enum name="GL_2PASS_0_SGIS"/>
+            <enum name="GL_2PASS_1_EXT"/>
+            <enum name="GL_2PASS_1_SGIS"/>
+            <enum name="GL_4PASS_0_EXT"/>
+            <enum name="GL_4PASS_0_SGIS"/>
+            <enum name="GL_4PASS_1_EXT"/>
+            <enum name="GL_4PASS_1_SGIS"/>
+            <enum name="GL_4PASS_2_EXT"/>
+            <enum name="GL_4PASS_2_SGIS"/>
+            <enum name="GL_4PASS_3_EXT"/>
+            <enum name="GL_4PASS_3_SGIS"/>
+        </group>
+
+        <group name="SeparableTargetEXT">
+            <enum name="GL_SEPARABLE_2D"/>
+            <enum name="GL_SEPARABLE_2D_EXT"/>
+        </group>
+
+        <group name="ShadingModel">
+            <enum name="GL_FLAT"/>
+            <enum name="GL_SMOOTH"/>
+        </group>
+
+        <group name="StencilFunction">
+            <enum name="GL_ALWAYS"/>
+            <enum name="GL_EQUAL"/>
+            <enum name="GL_GEQUAL"/>
+            <enum name="GL_GREATER"/>
+            <enum name="GL_LEQUAL"/>
+            <enum name="GL_LESS"/>
+            <enum name="GL_NEVER"/>
+            <enum name="GL_NOTEQUAL"/>
+        </group>
+
+        <group name="StencilOp">
+            <enum name="GL_DECR"/>
+            <enum name="GL_INCR"/>
+            <enum name="GL_INVERT"/>
+            <enum name="GL_KEEP"/>
+            <enum name="GL_REPLACE"/>
+            <enum name="GL_ZERO"/>
+        </group>
+
+        <group name="StringName">
+            <enum name="GL_EXTENSIONS"/>
+            <enum name="GL_RENDERER"/>
+            <enum name="GL_VENDOR"/>
+            <enum name="GL_VERSION"/>
+        </group>
+
+        <group name="TexCoordPointerType">
+            <enum name="GL_DOUBLE"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_SHORT"/>
+        </group>
+
+        <group name="TextureCoordName">
+            <enum name="GL_S"/>
+            <enum name="GL_T"/>
+            <enum name="GL_R"/>
+            <enum name="GL_Q"/>
+        </group>
+
+        <group name="TextureEnvMode">
+            <enum name="GL_ADD"/>
+            <enum name="GL_BLEND"/>
+            <enum name="GL_DECAL"/>
+            <enum name="GL_MODULATE"/>
+            <enum name="GL_REPLACE_EXT"/>
+            <enum name="GL_TEXTURE_ENV_BIAS_SGIX"/>
+        </group>
+
+        <group name="TextureEnvParameter">
+            <enum name="GL_TEXTURE_ENV_COLOR"/>
+            <enum name="GL_TEXTURE_ENV_MODE"/>
+        </group>
+
+        <group name="TextureEnvTarget">
+            <enum name="GL_TEXTURE_ENV"/>
+        </group>
+
+        <group name="TextureFilterFuncSGIS">
+            <enum name="GL_FILTER4_SGIS"/>
+        </group>
+
+        <group name="TextureGenMode">
+            <enum name="GL_EYE_DISTANCE_TO_LINE_SGIS"/>
+            <enum name="GL_EYE_DISTANCE_TO_POINT_SGIS"/>
+            <enum name="GL_EYE_LINEAR"/>
+            <enum name="GL_OBJECT_DISTANCE_TO_LINE_SGIS"/>
+            <enum name="GL_OBJECT_DISTANCE_TO_POINT_SGIS"/>
+            <enum name="GL_OBJECT_LINEAR"/>
+            <enum name="GL_SPHERE_MAP"/>
+        </group>
+
+        <group name="TextureGenParameter">
+            <enum name="GL_EYE_LINE_SGIS"/>
+            <enum name="GL_EYE_PLANE"/>
+            <enum name="GL_EYE_POINT_SGIS"/>
+            <enum name="GL_OBJECT_LINE_SGIS"/>
+            <enum name="GL_OBJECT_PLANE"/>
+            <enum name="GL_OBJECT_POINT_SGIS"/>
+            <enum name="GL_TEXTURE_GEN_MODE"/>
+        </group>
+
+        <group name="TextureMagFilter">
+            <enum name="GL_FILTER4_SGIS"/>
+            <enum name="GL_LINEAR"/>
+            <enum name="GL_LINEAR_DETAIL_ALPHA_SGIS"/>
+            <enum name="GL_LINEAR_DETAIL_COLOR_SGIS"/>
+            <enum name="GL_LINEAR_DETAIL_SGIS"/>
+            <enum name="GL_LINEAR_SHARPEN_ALPHA_SGIS"/>
+            <enum name="GL_LINEAR_SHARPEN_COLOR_SGIS"/>
+            <enum name="GL_LINEAR_SHARPEN_SGIS"/>
+            <enum name="GL_NEAREST"/>
+            <enum name="GL_PIXEL_TEX_GEN_Q_CEILING_SGIX"/>
+            <enum name="GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX"/>
+            <enum name="GL_PIXEL_TEX_GEN_Q_ROUND_SGIX"/>
+        </group>
+
+        <group name="TextureMinFilter">
+            <enum name="GL_FILTER4_SGIS"/>
+            <enum name="GL_LINEAR"/>
+            <enum name="GL_LINEAR_CLIPMAP_LINEAR_SGIX"/>
+            <enum name="GL_LINEAR_CLIPMAP_NEAREST_SGIX"/>
+            <enum name="GL_LINEAR_MIPMAP_LINEAR"/>
+            <enum name="GL_LINEAR_MIPMAP_NEAREST"/>
+            <enum name="GL_NEAREST"/>
+            <enum name="GL_NEAREST_CLIPMAP_LINEAR_SGIX"/>
+            <enum name="GL_NEAREST_CLIPMAP_NEAREST_SGIX"/>
+            <enum name="GL_NEAREST_MIPMAP_LINEAR"/>
+            <enum name="GL_NEAREST_MIPMAP_NEAREST"/>
+            <enum name="GL_PIXEL_TEX_GEN_Q_CEILING_SGIX"/>
+            <enum name="GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX"/>
+            <enum name="GL_PIXEL_TEX_GEN_Q_ROUND_SGIX"/>
+        </group>
+
+        <group name="TextureParameterName">
+            <enum name="GL_DETAIL_TEXTURE_LEVEL_SGIS"/>
+            <enum name="GL_DETAIL_TEXTURE_MODE_SGIS"/>
+            <enum name="GL_DUAL_TEXTURE_SELECT_SGIS"/>
+            <enum name="GL_GENERATE_MIPMAP"/>
+            <enum name="GL_GENERATE_MIPMAP_SGIS"/>
+            <enum name="GL_POST_TEXTURE_FILTER_BIAS_SGIX"/>
+            <enum name="GL_POST_TEXTURE_FILTER_SCALE_SGIX"/>
+            <enum name="GL_QUAD_TEXTURE_SELECT_SGIS"/>
+            <enum name="GL_SHADOW_AMBIENT_SGIX"/>
+            <enum name="GL_TEXTURE_BORDER_COLOR"/>
+            <enum name="GL_TEXTURE_CLIPMAP_CENTER_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_DEPTH_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_FRAME_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_OFFSET_SGIX"/>
+            <enum name="GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX"/>
+            <enum name="GL_TEXTURE_COMPARE_SGIX"/>
+            <enum name="GL_TEXTURE_LOD_BIAS_R_SGIX"/>
+            <enum name="GL_TEXTURE_LOD_BIAS_S_SGIX"/>
+            <enum name="GL_TEXTURE_LOD_BIAS_T_SGIX"/>
+            <enum name="GL_TEXTURE_MAG_FILTER"/>
+            <enum name="GL_TEXTURE_MAX_CLAMP_R_SGIX"/>
+            <enum name="GL_TEXTURE_MAX_CLAMP_S_SGIX"/>
+            <enum name="GL_TEXTURE_MAX_CLAMP_T_SGIX"/>
+            <enum name="GL_TEXTURE_MIN_FILTER"/>
+            <enum name="GL_TEXTURE_PRIORITY"/>
+            <enum name="GL_TEXTURE_PRIORITY_EXT"/>
+            <enum name="GL_TEXTURE_WRAP_Q_SGIS"/>
+            <enum name="GL_TEXTURE_WRAP_R"/>
+            <enum name="GL_TEXTURE_WRAP_R_EXT"/>
+            <enum name="GL_TEXTURE_WRAP_R_OES"/>
+            <enum name="GL_TEXTURE_WRAP_S"/>
+            <enum name="GL_TEXTURE_WRAP_T"/>
+        </group>
+
+        <group name="TextureTarget">
+            <enum name="GL_DETAIL_TEXTURE_2D_SGIS"/>
+            <enum name="GL_PROXY_TEXTURE_1D"/>
+            <enum name="GL_PROXY_TEXTURE_1D_EXT"/>
+            <enum name="GL_PROXY_TEXTURE_2D"/>
+            <enum name="GL_PROXY_TEXTURE_2D_EXT"/>
+            <enum name="GL_PROXY_TEXTURE_3D"/>
+            <enum name="GL_PROXY_TEXTURE_3D_EXT"/>
+            <enum name="GL_PROXY_TEXTURE_4D_SGIS"/>
+            <enum name="GL_TEXTURE_1D"/>
+            <enum name="GL_TEXTURE_2D"/>
+            <enum name="GL_TEXTURE_3D"/>
+            <enum name="GL_TEXTURE_3D_EXT"/>
+            <enum name="GL_TEXTURE_3D_OES"/>
+            <enum name="GL_TEXTURE_4D_SGIS"/>
+            <enum name="GL_TEXTURE_BASE_LEVEL"/>
+            <enum name="GL_TEXTURE_BASE_LEVEL_SGIS"/>
+            <enum name="GL_TEXTURE_MAX_LEVEL"/>
+            <enum name="GL_TEXTURE_MAX_LEVEL_SGIS"/>
+            <enum name="GL_TEXTURE_MAX_LOD"/>
+            <enum name="GL_TEXTURE_MAX_LOD_SGIS"/>
+            <enum name="GL_TEXTURE_MIN_LOD"/>
+            <enum name="GL_TEXTURE_MIN_LOD_SGIS"/>
+        </group>
+
+        <group name="TextureWrapMode">
+            <enum name="GL_CLAMP"/>
+            <enum name="GL_CLAMP_TO_BORDER"/>
+            <enum name="GL_CLAMP_TO_BORDER_ARB"/>
+            <enum name="GL_CLAMP_TO_BORDER_NV"/>
+            <enum name="GL_CLAMP_TO_BORDER_SGIS"/>
+            <enum name="GL_CLAMP_TO_EDGE"/>
+            <enum name="GL_CLAMP_TO_EDGE_SGIS"/>
+            <enum name="GL_REPEAT"/>
+        </group>
+
+        <group name="UseProgramStageMask">
+            <enum name="GL_VERTEX_SHADER_BIT"/>
+            <enum name="GL_VERTEX_SHADER_BIT_EXT"/>
+            <enum name="GL_FRAGMENT_SHADER_BIT"/>
+            <enum name="GL_FRAGMENT_SHADER_BIT_EXT"/>
+            <enum name="GL_GEOMETRY_SHADER_BIT"/>
+            <enum name="GL_GEOMETRY_SHADER_BIT_EXT"/>
+            <enum name="GL_TESS_CONTROL_SHADER_BIT"/>
+            <enum name="GL_TESS_CONTROL_SHADER_BIT_EXT"/>
+            <enum name="GL_TESS_EVALUATION_SHADER_BIT"/>
+            <enum name="GL_TESS_EVALUATION_SHADER_BIT_EXT"/>
+            <enum name="GL_COMPUTE_SHADER_BIT"/>
+            <enum name="GL_ALL_SHADER_BITS"/>
+            <enum name="GL_ALL_SHADER_BITS_EXT"/>
+        </group>
+
+        <group name="VertexPointerType">
+            <enum name="GL_DOUBLE"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_SHORT"/>
+        </group>
+    </groups>
+
+    <!-- SECTION: GL enumerant (token) definitions. -->
+
+    <!-- Bitmasks each have their own namespace, although bits are
+         sometimes reused for other purposes -->
+
+    <enums namespace="GL" group="AttribMask" type="bitmask">
+        <enum value="0x00000001" name="GL_CURRENT_BIT"/>
+        <enum value="0x00000002" name="GL_POINT_BIT"/>
+        <enum value="0x00000004" name="GL_LINE_BIT"/>
+        <enum value="0x00000008" name="GL_POLYGON_BIT"/>
+        <enum value="0x00000010" name="GL_POLYGON_STIPPLE_BIT"/>
+        <enum value="0x00000020" name="GL_PIXEL_MODE_BIT"/>
+        <enum value="0x00000040" name="GL_LIGHTING_BIT"/>
+        <enum value="0x00000080" name="GL_FOG_BIT"/>
+        <enum value="0x00000100" name="GL_DEPTH_BUFFER_BIT"/>
+        <enum value="0x00000200" name="GL_ACCUM_BUFFER_BIT"/>
+        <enum value="0x00000400" name="GL_STENCIL_BUFFER_BIT"/>
+        <enum value="0x00000800" name="GL_VIEWPORT_BIT"/>
+        <enum value="0x00001000" name="GL_TRANSFORM_BIT"/>
+        <enum value="0x00002000" name="GL_ENABLE_BIT"/>
+        <enum value="0x00004000" name="GL_COLOR_BUFFER_BIT"/>
+        <enum value="0x00008000" name="GL_HINT_BIT"/>
+        <enum value="0x00010000" name="GL_EVAL_BIT"/>
+        <enum value="0x00020000" name="GL_LIST_BIT"/>
+        <enum value="0x00040000" name="GL_TEXTURE_BIT"/>
+        <enum value="0x00080000" name="GL_SCISSOR_BIT"/>
+        <enum value="0x20000000" name="GL_MULTISAMPLE_BIT"/>
+        <enum value="0x20000000" name="GL_MULTISAMPLE_BIT_ARB"/>
+        <enum value="0x20000000" name="GL_MULTISAMPLE_BIT_EXT"/>
+        <enum value="0x20000000" name="GL_MULTISAMPLE_BIT_3DFX"/>
+        <enum value="0xFFFFFFFF" name="GL_ALL_ATTRIB_BITS" comment="Guaranteed to mark all attribute groups at once"/>
+    </enums>
+
+    <enums namespace="GL" group="ClearBufferMask" type="bitmask" comment="GL_{DEPTH,ACCUM,STENCIL,COLOR}_BUFFER_BIT also lie in this namespace">
+        <enum value="0x00008000" name="GL_COVERAGE_BUFFER_BIT_NV" comment="Collides with AttribMask bit GL_HINT_BIT. OK since this token is for OpenGL ES 2, which doesn't have attribute groups."/>
+            <!-- Also used: 0x00004700 for bits reused from AttribMask above -->
+    </enums>
+
+    <enums namespace="GL" group="ClientAttribMask" type="bitmask">
+        <enum value="0x00000001" name="GL_CLIENT_PIXEL_STORE_BIT"/>
+        <enum value="0x00000002" name="GL_CLIENT_VERTEX_ARRAY_BIT"/>
+        <enum value="0xFFFFFFFF" name="GL_CLIENT_ALL_ATTRIB_BITS"/>
+    </enums>
+
+    <enums namespace="GL" group="ContextFlagMask" type="bitmask" comment="Should be shared with WGL/GLX, but aren't since the FORWARD_COMPATIBLE and DEBUG values are swapped vs. WGL/GLX.">
+        <enum value="0x00000001" name="GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT"/>
+        <enum value="0x00000002" name="GL_CONTEXT_FLAG_DEBUG_BIT"/>
+        <enum value="0x00000002" name="GL_CONTEXT_FLAG_DEBUG_BIT_KHR"/>
+        <enum value="0x00000004" name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT"/>
+        <enum value="0x00000004" name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB"/>
+        <enum value="0x00000008" name="GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR"/>
+        <enum value="0x00000010" name="GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT"/>
+    </enums>
+
+    <enums namespace="GL" group="ContextProfileMask" type="bitmask">
+        <enum value="0x00000001" name="GL_CONTEXT_CORE_PROFILE_BIT"/>
+        <enum value="0x00000002" name="GL_CONTEXT_COMPATIBILITY_PROFILE_BIT"/>
+    </enums>
+
+    <enums namespace="GL" group="MapBufferUsageMask" type="bitmask">
+        <enum value="0x0001" name="GL_MAP_READ_BIT"/>
+        <enum value="0x0001" name="GL_MAP_READ_BIT_EXT"/>
+        <enum value="0x0002" name="GL_MAP_WRITE_BIT"/>
+        <enum value="0x0002" name="GL_MAP_WRITE_BIT_EXT"/>
+        <enum value="0x0004" name="GL_MAP_INVALIDATE_RANGE_BIT"/>
+        <enum value="0x0004" name="GL_MAP_INVALIDATE_RANGE_BIT_EXT"/>
+        <enum value="0x0008" name="GL_MAP_INVALIDATE_BUFFER_BIT"/>
+        <enum value="0x0008" name="GL_MAP_INVALIDATE_BUFFER_BIT_EXT"/>
+        <enum value="0x0010" name="GL_MAP_FLUSH_EXPLICIT_BIT"/>
+        <enum value="0x0010" name="GL_MAP_FLUSH_EXPLICIT_BIT_EXT"/>
+        <enum value="0x0020" name="GL_MAP_UNSYNCHRONIZED_BIT"/>
+        <enum value="0x0020" name="GL_MAP_UNSYNCHRONIZED_BIT_EXT"/>
+        <enum value="0x0040" name="GL_MAP_PERSISTENT_BIT"/>
+        <enum value="0x0040" name="GL_MAP_PERSISTENT_BIT_EXT"/>
+        <enum value="0x0080" name="GL_MAP_COHERENT_BIT"/>
+        <enum value="0x0080" name="GL_MAP_COHERENT_BIT_EXT"/>
+        <enum value="0x0100" name="GL_DYNAMIC_STORAGE_BIT"/>
+        <enum value="0x0100" name="GL_DYNAMIC_STORAGE_BIT_EXT"/>
+        <enum value="0x0200" name="GL_CLIENT_STORAGE_BIT"/>
+        <enum value="0x0200" name="GL_CLIENT_STORAGE_BIT_EXT"/>
+        <enum value="0x0400" name="GL_SPARSE_STORAGE_BIT_ARB"/>
+            <!-- Bits 0x1000 and 0x0800 reserved for Joshua Schnarr, jschnarr@nvidia.com -->
+    </enums>
+
+    <enums namespace="GL" group="MemoryBarrierMask" type="bitmask">
+        <enum value="0x00000001" name="GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT"/>
+        <enum value="0x00000001" name="GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT"/>
+        <enum value="0x00000002" name="GL_ELEMENT_ARRAY_BARRIER_BIT"/>
+        <enum value="0x00000002" name="GL_ELEMENT_ARRAY_BARRIER_BIT_EXT"/>
+        <enum value="0x00000004" name="GL_UNIFORM_BARRIER_BIT"/>
+        <enum value="0x00000004" name="GL_UNIFORM_BARRIER_BIT_EXT"/>
+        <enum value="0x00000008" name="GL_TEXTURE_FETCH_BARRIER_BIT"/>
+        <enum value="0x00000008" name="GL_TEXTURE_FETCH_BARRIER_BIT_EXT"/>
+        <enum value="0x00000010" name="GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV"/>
+        <enum value="0x00000020" name="GL_SHADER_IMAGE_ACCESS_BARRIER_BIT"/>
+        <enum value="0x00000020" name="GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT"/>
+        <enum value="0x00000040" name="GL_COMMAND_BARRIER_BIT"/>
+        <enum value="0x00000040" name="GL_COMMAND_BARRIER_BIT_EXT"/>
+        <enum value="0x00000080" name="GL_PIXEL_BUFFER_BARRIER_BIT"/>
+        <enum value="0x00000080" name="GL_PIXEL_BUFFER_BARRIER_BIT_EXT"/>
+        <enum value="0x00000100" name="GL_TEXTURE_UPDATE_BARRIER_BIT"/>
+        <enum value="0x00000100" name="GL_TEXTURE_UPDATE_BARRIER_BIT_EXT"/>
+        <enum value="0x00000200" name="GL_BUFFER_UPDATE_BARRIER_BIT"/>
+        <enum value="0x00000200" name="GL_BUFFER_UPDATE_BARRIER_BIT_EXT"/>
+        <enum value="0x00000400" name="GL_FRAMEBUFFER_BARRIER_BIT"/>
+        <enum value="0x00000400" name="GL_FRAMEBUFFER_BARRIER_BIT_EXT"/>
+        <enum value="0x00000800" name="GL_TRANSFORM_FEEDBACK_BARRIER_BIT"/>
+        <enum value="0x00000800" name="GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT"/>
+        <enum value="0x00001000" name="GL_ATOMIC_COUNTER_BARRIER_BIT"/>
+        <enum value="0x00001000" name="GL_ATOMIC_COUNTER_BARRIER_BIT_EXT"/>
+        <enum value="0x00002000" name="GL_SHADER_STORAGE_BARRIER_BIT"/>
+        <enum value="0x00004000" name="GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT"/>
+        <enum value="0x00004000" name="GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT"/>
+        <enum value="0x00008000" name="GL_QUERY_BUFFER_BARRIER_BIT"/>
+        <enum value="0xFFFFFFFF" name="GL_ALL_BARRIER_BITS"/>
+        <enum value="0xFFFFFFFF" name="GL_ALL_BARRIER_BITS_EXT"/>
+    </enums>
+
+    <enums namespace="OcclusionQueryEventMaskAMD">
+        <enum value="0x00000001" name="GL_QUERY_DEPTH_PASS_EVENT_BIT_AMD"/>
+        <enum value="0x00000002" name="GL_QUERY_DEPTH_FAIL_EVENT_BIT_AMD"/>
+        <enum value="0x00000004" name="GL_QUERY_STENCIL_FAIL_EVENT_BIT_AMD"/>
+        <enum value="0x00000008" name="GL_QUERY_DEPTH_BOUNDS_FAIL_EVENT_BIT_AMD"/>
+        <enum value="0xFFFFFFFF" name="GL_QUERY_ALL_EVENT_BITS_AMD"/>
+    </enums>
+
+    <enums namespace="GL" group="SyncObjectMask" type="bitmask">
+        <enum value="0x00000001" name="GL_SYNC_FLUSH_COMMANDS_BIT"/>
+        <enum value="0x00000001" name="GL_SYNC_FLUSH_COMMANDS_BIT_APPLE"/>
+    </enums>
+
+    <enums namespace="GL" group="UseProgramStageMask" type="bitmask">
+        <enum value="0x00000001" name="GL_VERTEX_SHADER_BIT"/>
+        <enum value="0x00000001" name="GL_VERTEX_SHADER_BIT_EXT"/>
+        <enum value="0x00000002" name="GL_FRAGMENT_SHADER_BIT"/>
+        <enum value="0x00000002" name="GL_FRAGMENT_SHADER_BIT_EXT"/>
+        <enum value="0x00000004" name="GL_GEOMETRY_SHADER_BIT"/>
+        <enum value="0x00000004" name="GL_GEOMETRY_SHADER_BIT_EXT"/>
+        <enum value="0x00000004" name="GL_GEOMETRY_SHADER_BIT_OES"/>
+        <enum value="0x00000008" name="GL_TESS_CONTROL_SHADER_BIT"/>
+        <enum value="0x00000008" name="GL_TESS_CONTROL_SHADER_BIT_EXT"/>
+        <enum value="0x00000008" name="GL_TESS_CONTROL_SHADER_BIT_OES"/>
+        <enum value="0x00000010" name="GL_TESS_EVALUATION_SHADER_BIT"/>
+        <enum value="0x00000010" name="GL_TESS_EVALUATION_SHADER_BIT_EXT"/>
+        <enum value="0x00000010" name="GL_TESS_EVALUATION_SHADER_BIT_OES"/>
+        <enum value="0x00000020" name="GL_COMPUTE_SHADER_BIT"/>
+        <enum value="0xFFFFFFFF" name="GL_ALL_SHADER_BITS"/>
+        <enum value="0xFFFFFFFF" name="GL_ALL_SHADER_BITS_EXT"/>
+    </enums>
+
+    <!-- Bitmasks defined by vendor extensions -->
+
+    <enums namespace="GL" group="TextureStorageMaskAMD" type="bitmask">
+        <enum value="0x00000001" name="GL_TEXTURE_STORAGE_SPARSE_BIT_AMD"/>
+    </enums>
+
+    <enums namespace="GL" group="FragmentShaderDestMaskATI" type="bitmask">
+        <enum value="0x00000001" name="GL_RED_BIT_ATI"/>
+        <enum value="0x00000002" name="GL_GREEN_BIT_ATI"/>
+        <enum value="0x00000004" name="GL_BLUE_BIT_ATI"/>
+    </enums>
+
+    <enums namespace="GL" group="FragmentShaderDestModMaskATI" type="bitmask">
+        <enum value="0x00000001" name="GL_2X_BIT_ATI"/>
+        <enum value="0x00000002" name="GL_4X_BIT_ATI"/>
+        <enum value="0x00000004" name="GL_8X_BIT_ATI"/>
+        <enum value="0x00000008" name="GL_HALF_BIT_ATI"/>
+        <enum value="0x00000010" name="GL_QUARTER_BIT_ATI"/>
+        <enum value="0x00000020" name="GL_EIGHTH_BIT_ATI"/>
+        <enum value="0x00000040" name="GL_SATURATE_BIT_ATI"/>
+    </enums>
+
+    <enums namespace="GL" group="FragmentShaderColorModMaskATI" type="bitmask">
+            <!-- Also used: 0x00000001 for GL_2X_BIT_ATI reused from FragmentShaderDestModMaskAT above -->
+        <enum value="0x00000002" name="GL_COMP_BIT_ATI"/>
+        <enum value="0x00000004" name="GL_NEGATE_BIT_ATI"/>
+        <enum value="0x00000008" name="GL_BIAS_BIT_ATI"/>
+    </enums>
+
+    <enums namespace="GL" group="TraceMaskMESA" type="bitmask">
+        <enum value="0x0001" name="GL_TRACE_OPERATIONS_BIT_MESA"/>
+        <enum value="0x0002" name="GL_TRACE_PRIMITIVES_BIT_MESA"/>
+        <enum value="0x0004" name="GL_TRACE_ARRAYS_BIT_MESA"/>
+        <enum value="0x0008" name="GL_TRACE_TEXTURES_BIT_MESA"/>
+        <enum value="0x0010" name="GL_TRACE_PIXELS_BIT_MESA"/>
+        <enum value="0x0020" name="GL_TRACE_ERRORS_BIT_MESA"/>
+        <enum value="0xFFFF" name="GL_TRACE_ALL_BITS_MESA"/>
+    </enums>
+
+    <enums namespace="GL" group="PathRenderingMaskNV" type="bitmask">
+        <enum value="0x01" name="GL_BOLD_BIT_NV"/>
+        <enum value="0x02" name="GL_ITALIC_BIT_NV"/>
+        <enum value="0x01" name="GL_GLYPH_WIDTH_BIT_NV"/>
+        <enum value="0x02" name="GL_GLYPH_HEIGHT_BIT_NV"/>
+        <enum value="0x04" name="GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV"/>
+        <enum value="0x08" name="GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV"/>
+        <enum value="0x10" name="GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV"/>
+        <enum value="0x20" name="GL_GLYPH_VERTICAL_BEARING_X_BIT_NV"/>
+        <enum value="0x40" name="GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV"/>
+        <enum value="0x80" name="GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV"/>
+        <enum value="0x100" name="GL_GLYPH_HAS_KERNING_BIT_NV"/>
+        <enum value="0x00010000" name="GL_FONT_X_MIN_BOUNDS_BIT_NV"/>
+        <enum value="0x00020000" name="GL_FONT_Y_MIN_BOUNDS_BIT_NV"/>
+        <enum value="0x00040000" name="GL_FONT_X_MAX_BOUNDS_BIT_NV"/>
+        <enum value="0x00080000" name="GL_FONT_Y_MAX_BOUNDS_BIT_NV"/>
+        <enum value="0x00100000" name="GL_FONT_UNITS_PER_EM_BIT_NV"/>
+        <enum value="0x00200000" name="GL_FONT_ASCENDER_BIT_NV"/>
+        <enum value="0x00400000" name="GL_FONT_DESCENDER_BIT_NV"/>
+        <enum value="0x00800000" name="GL_FONT_HEIGHT_BIT_NV"/>
+        <enum value="0x01000000" name="GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV"/>
+        <enum value="0x02000000" name="GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV"/>
+        <enum value="0x04000000" name="GL_FONT_UNDERLINE_POSITION_BIT_NV"/>
+        <enum value="0x08000000" name="GL_FONT_UNDERLINE_THICKNESS_BIT_NV"/>
+        <enum value="0x10000000" name="GL_FONT_HAS_KERNING_BIT_NV"/>
+        <enum value="0x20000000" name="GL_FONT_NUM_GLYPH_INDICES_BIT_NV"/>
+    </enums>
+
+    <enums namespace="GL" group="PerformanceQueryCapsMaskINTEL" type="bitmask">
+        <enum value="0x00000000" name="GL_PERFQUERY_SINGLE_CONTEXT_INTEL"/>
+        <enum value="0x00000001" name="GL_PERFQUERY_GLOBAL_CONTEXT_INTEL"/>
+    </enums>
+
+    <enums namespace="GL" group="VertexHintsMaskPGI" type="bitmask">
+        <enum value="0x00000004" name="GL_VERTEX23_BIT_PGI"/>
+        <enum value="0x00000008" name="GL_VERTEX4_BIT_PGI"/>
+        <enum value="0x00010000" name="GL_COLOR3_BIT_PGI"/>
+        <enum value="0x00020000" name="GL_COLOR4_BIT_PGI"/>
+        <enum value="0x00040000" name="GL_EDGEFLAG_BIT_PGI"/>
+        <enum value="0x00080000" name="GL_INDEX_BIT_PGI"/>
+        <enum value="0x00100000" name="GL_MAT_AMBIENT_BIT_PGI"/>
+        <enum value="0x00200000" name="GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI"/>
+        <enum value="0x00400000" name="GL_MAT_DIFFUSE_BIT_PGI"/>
+        <enum value="0x00800000" name="GL_MAT_EMISSION_BIT_PGI"/>
+        <enum value="0x01000000" name="GL_MAT_COLOR_INDEXES_BIT_PGI"/>
+        <enum value="0x02000000" name="GL_MAT_SHININESS_BIT_PGI"/>
+        <enum value="0x04000000" name="GL_MAT_SPECULAR_BIT_PGI"/>
+        <enum value="0x08000000" name="GL_NORMAL_BIT_PGI"/>
+        <enum value="0x10000000" name="GL_TEXCOORD1_BIT_PGI"/>
+        <enum value="0x20000000" name="GL_TEXCOORD2_BIT_PGI"/>
+        <enum value="0x40000000" name="GL_TEXCOORD3_BIT_PGI"/>
+        <enum value="0x80000000" name="GL_TEXCOORD4_BIT_PGI"/>
+    </enums>
+
+    <enums namespace="GL" group="BufferBitQCOM" type="bitmask">
+        <enum value="0x00000001" name="GL_COLOR_BUFFER_BIT0_QCOM"/>
+        <enum value="0x00000002" name="GL_COLOR_BUFFER_BIT1_QCOM"/>
+        <enum value="0x00000004" name="GL_COLOR_BUFFER_BIT2_QCOM"/>
+        <enum value="0x00000008" name="GL_COLOR_BUFFER_BIT3_QCOM"/>
+        <enum value="0x00000010" name="GL_COLOR_BUFFER_BIT4_QCOM"/>
+        <enum value="0x00000020" name="GL_COLOR_BUFFER_BIT5_QCOM"/>
+        <enum value="0x00000040" name="GL_COLOR_BUFFER_BIT6_QCOM"/>
+        <enum value="0x00000080" name="GL_COLOR_BUFFER_BIT7_QCOM"/>
+        <enum value="0x00000100" name="GL_DEPTH_BUFFER_BIT0_QCOM"/>
+        <enum value="0x00000200" name="GL_DEPTH_BUFFER_BIT1_QCOM"/>
+        <enum value="0x00000400" name="GL_DEPTH_BUFFER_BIT2_QCOM"/>
+        <enum value="0x00000800" name="GL_DEPTH_BUFFER_BIT3_QCOM"/>
+        <enum value="0x00001000" name="GL_DEPTH_BUFFER_BIT4_QCOM"/>
+        <enum value="0x00002000" name="GL_DEPTH_BUFFER_BIT5_QCOM"/>
+        <enum value="0x00004000" name="GL_DEPTH_BUFFER_BIT6_QCOM"/>
+        <enum value="0x00008000" name="GL_DEPTH_BUFFER_BIT7_QCOM"/>
+        <enum value="0x00010000" name="GL_STENCIL_BUFFER_BIT0_QCOM"/>
+        <enum value="0x00020000" name="GL_STENCIL_BUFFER_BIT1_QCOM"/>
+        <enum value="0x00040000" name="GL_STENCIL_BUFFER_BIT2_QCOM"/>
+        <enum value="0x00080000" name="GL_STENCIL_BUFFER_BIT3_QCOM"/>
+        <enum value="0x00100000" name="GL_STENCIL_BUFFER_BIT4_QCOM"/>
+        <enum value="0x00200000" name="GL_STENCIL_BUFFER_BIT5_QCOM"/>
+        <enum value="0x00400000" name="GL_STENCIL_BUFFER_BIT6_QCOM"/>
+        <enum value="0x00800000" name="GL_STENCIL_BUFFER_BIT7_QCOM"/>
+        <enum value="0x01000000" name="GL_MULTISAMPLE_BUFFER_BIT0_QCOM"/>
+        <enum value="0x02000000" name="GL_MULTISAMPLE_BUFFER_BIT1_QCOM"/>
+        <enum value="0x04000000" name="GL_MULTISAMPLE_BUFFER_BIT2_QCOM"/>
+        <enum value="0x08000000" name="GL_MULTISAMPLE_BUFFER_BIT3_QCOM"/>
+        <enum value="0x10000000" name="GL_MULTISAMPLE_BUFFER_BIT4_QCOM"/>
+        <enum value="0x20000000" name="GL_MULTISAMPLE_BUFFER_BIT5_QCOM"/>
+        <enum value="0x40000000" name="GL_MULTISAMPLE_BUFFER_BIT6_QCOM"/>
+        <enum value="0x80000000" name="GL_MULTISAMPLE_BUFFER_BIT7_QCOM"/>
+    </enums>
+
+    <enums namespace="GL" group="FfdMaskSGIX" type="bitmask">
+        <enum value="0x00000001" name="GL_TEXTURE_DEFORMATION_BIT_SGIX"/>
+        <enum value="0x00000002" name="GL_GEOMETRY_DEFORMATION_BIT_SGIX"/>
+    </enums>
+
+    <!-- Non-bitmask enums with their own namespace. Generally small numbers
+         used for indexed access. -->
+
+    <enums namespace="GL" group="CommandOpcodesNV" vendor="NV" comment="For NV_command_list.">
+        <enum value="0x0000" name="GL_TERMINATE_SEQUENCE_COMMAND_NV"/>
+        <enum value="0x0001" name="GL_NOP_COMMAND_NV"/>
+        <enum value="0x0002" name="GL_DRAW_ELEMENTS_COMMAND_NV"/>
+        <enum value="0x0003" name="GL_DRAW_ARRAYS_COMMAND_NV"/>
+        <enum value="0x0004" name="GL_DRAW_ELEMENTS_STRIP_COMMAND_NV"/>
+        <enum value="0x0005" name="GL_DRAW_ARRAYS_STRIP_COMMAND_NV"/>
+        <enum value="0x0006" name="GL_DRAW_ELEMENTS_INSTANCED_COMMAND_NV"/>
+        <enum value="0x0007" name="GL_DRAW_ARRAYS_INSTANCED_COMMAND_NV"/>
+        <enum value="0x0008" name="GL_ELEMENT_ADDRESS_COMMAND_NV"/>
+        <enum value="0x0009" name="GL_ATTRIBUTE_ADDRESS_COMMAND_NV"/>
+        <enum value="0x000A" name="GL_UNIFORM_ADDRESS_COMMAND_NV"/>
+        <enum value="0x000B" name="GL_BLEND_COLOR_COMMAND_NV"/>
+        <enum value="0x000C" name="GL_STENCIL_REF_COMMAND_NV"/>
+        <enum value="0x000D" name="GL_LINE_WIDTH_COMMAND_NV"/>
+        <enum value="0x000E" name="GL_POLYGON_OFFSET_COMMAND_NV"/>
+        <enum value="0x000F" name="GL_ALPHA_REF_COMMAND_NV"/>
+        <enum value="0x0010" name="GL_VIEWPORT_COMMAND_NV"/>
+        <enum value="0x0011" name="GL_SCISSOR_COMMAND_NV"/>
+        <enum value="0x0012" name="GL_FRONT_FACE_COMMAND_NV"/>
+    </enums>
+
+    <enums namespace="GL" group="MapTextureFormatINTEL" vendor="INTEL" comment="Texture memory layouts for INTEL_map_texture">
+        <enum value="0" name="GL_LAYOUT_DEFAULT_INTEL"/>
+        <enum value="1" name="GL_LAYOUT_LINEAR_INTEL"/>
+        <enum value="2" name="GL_LAYOUT_LINEAR_CPU_CACHED_INTEL"/>
+    </enums>
+
+    <enums namespace="GL" group="PathRenderingTokenNV" vendor="NV">
+        <enum value="0x00" name="GL_CLOSE_PATH_NV"/>
+        <enum value="0x02" name="GL_MOVE_TO_NV"/>
+        <enum value="0x03" name="GL_RELATIVE_MOVE_TO_NV"/>
+        <enum value="0x04" name="GL_LINE_TO_NV"/>
+        <enum value="0x05" name="GL_RELATIVE_LINE_TO_NV"/>
+        <enum value="0x06" name="GL_HORIZONTAL_LINE_TO_NV"/>
+        <enum value="0x07" name="GL_RELATIVE_HORIZONTAL_LINE_TO_NV"/>
+        <enum value="0x08" name="GL_VERTICAL_LINE_TO_NV"/>
+        <enum value="0x09" name="GL_RELATIVE_VERTICAL_LINE_TO_NV"/>
+        <enum value="0x0A" name="GL_QUADRATIC_CURVE_TO_NV"/>
+        <enum value="0x0B" name="GL_RELATIVE_QUADRATIC_CURVE_TO_NV"/>
+        <enum value="0x0C" name="GL_CUBIC_CURVE_TO_NV"/>
+        <enum value="0x0D" name="GL_RELATIVE_CUBIC_CURVE_TO_NV"/>
+        <enum value="0x0E" name="GL_SMOOTH_QUADRATIC_CURVE_TO_NV"/>
+        <enum value="0x0F" name="GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV"/>
+        <enum value="0x10" name="GL_SMOOTH_CUBIC_CURVE_TO_NV"/>
+        <enum value="0x11" name="GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV"/>
+        <enum value="0x12" name="GL_SMALL_CCW_ARC_TO_NV"/>
+        <enum value="0x13" name="GL_RELATIVE_SMALL_CCW_ARC_TO_NV"/>
+        <enum value="0x14" name="GL_SMALL_CW_ARC_TO_NV"/>
+        <enum value="0x15" name="GL_RELATIVE_SMALL_CW_ARC_TO_NV"/>
+        <enum value="0x16" name="GL_LARGE_CCW_ARC_TO_NV"/>
+        <enum value="0x17" name="GL_RELATIVE_LARGE_CCW_ARC_TO_NV"/>
+        <enum value="0x18" name="GL_LARGE_CW_ARC_TO_NV"/>
+        <enum value="0x19" name="GL_RELATIVE_LARGE_CW_ARC_TO_NV"/>
+        <enum value="0x1A" name="GL_CONIC_CURVE_TO_NV"/>
+        <enum value="0x1B" name="GL_RELATIVE_CONIC_CURVE_TO_NV"/>
+            <unused start="0x1C" end="0xBF" comment="Unused for PathRenderingTokenNV"/>
+        <enum value="0xC0" name="GL_SHARED_EDGE_NV"/>
+            <unused start="0xC1" end="0xE7" comment="Unused for PathRenderingTokenNV"/>
+        <enum value="0xE8" name="GL_ROUNDED_RECT_NV"/>
+        <enum value="0xE9" name="GL_RELATIVE_ROUNDED_RECT_NV"/>
+        <enum value="0xEA" name="GL_ROUNDED_RECT2_NV"/>
+        <enum value="0xEB" name="GL_RELATIVE_ROUNDED_RECT2_NV"/>
+        <enum value="0xEC" name="GL_ROUNDED_RECT4_NV"/>
+        <enum value="0xED" name="GL_RELATIVE_ROUNDED_RECT4_NV"/>
+        <enum value="0xEE" name="GL_ROUNDED_RECT8_NV"/>
+        <enum value="0xEF" name="GL_RELATIVE_ROUNDED_RECT8_NV"/>
+        <enum value="0xF0" name="GL_RESTART_PATH_NV"/>
+        <enum value="0xF2" name="GL_DUP_FIRST_CUBIC_CURVE_TO_NV"/>
+        <enum value="0xF4" name="GL_DUP_LAST_CUBIC_CURVE_TO_NV"/>
+        <enum value="0xF6" name="GL_RECT_NV"/>
+        <enum value="0xF7" name="GL_RELATIVE_RECT_NV"/>
+        <enum value="0xF8" name="GL_CIRCULAR_CCW_ARC_TO_NV"/>
+        <enum value="0xFA" name="GL_CIRCULAR_CW_ARC_TO_NV"/>
+        <enum value="0xFC" name="GL_CIRCULAR_TANGENT_ARC_TO_NV"/>
+        <enum value="0xFE" name="GL_ARC_TO_NV"/>
+        <enum value="0xFF" name="GL_RELATIVE_ARC_TO_NV"/>
+    </enums>
+
+    <enums namespace="GL" group="TransformFeedbackTokenNV" vendor="NV" comment="For NV_transform_feedback. No clue why small negative values are used">
+        <enum value="-2" name="GL_NEXT_BUFFER_NV"/>
+        <enum value="-3" name="GL_SKIP_COMPONENTS4_NV"/>
+        <enum value="-4" name="GL_SKIP_COMPONENTS3_NV"/>
+        <enum value="-5" name="GL_SKIP_COMPONENTS2_NV"/>
+        <enum value="-6" name="GL_SKIP_COMPONENTS1_NV"/>
+    </enums>
+
+    <enums namespace="GL" group="TriangleListSUN" vendor="SUN">
+        <enum value="0x0001" name="GL_RESTART_SUN"/>
+        <enum value="0x0002" name="GL_REPLACE_MIDDLE_SUN"/>
+        <enum value="0x0003" name="GL_REPLACE_OLDEST_SUN"/>
+    </enums>
+
+    <!-- The default ("API") enum namespace starts here. While some
+         assigned values may overlap, and different parts of the
+         namespace are reserved for different purposes, it is a single
+         namespace. The "class" attribute indicates some of the reserved
+         purposes but is by no means complete (and cannot be, since many
+         tokens are reused for different purposes in different
+         extensions and API versions). -->
+
+    <enums namespace="GL" group="SpecialNumbers" vendor="ARB" comment="Tokens whose numeric value is intrinsically meaningful">
+        <enum value="0" name="GL_FALSE"/>
+        <enum value="0" name="GL_NO_ERROR"/>
+        <enum value="0" name="GL_ZERO"/>
+        <enum value="0" name="GL_NONE"/>
+        <enum value="0" name="GL_NONE_OES"/>
+        <enum value="1" name="GL_TRUE"/>
+        <enum value="1" name="GL_ONE"/>
+        <enum value="0xFFFFFFFF" name="GL_INVALID_INDEX" type="u" comment="Tagged as uint"/>
+        <enum value="0xFFFFFFFF" name="GL_ALL_PIXELS_AMD"/>
+        <enum value="0xFFFFFFFFFFFFFFFF" name="GL_TIMEOUT_IGNORED" type="ull" comment="Tagged as uint64"/>
+        <enum value="0xFFFFFFFFFFFFFFFF" name="GL_TIMEOUT_IGNORED_APPLE" type="ull" comment="Tagged as uint64"/>
+        <enum value="1" name="GL_VERSION_ES_CL_1_0" comment="Not an API enum. API definition macro for ES 1.0/1.1 headers"/>
+        <enum value="1" name="GL_VERSION_ES_CM_1_1" comment="Not an API enum. API definition macro for ES 1.0/1.1 headers"/>
+        <enum value="1" name="GL_VERSION_ES_CL_1_1" comment="Not an API enum. API definition macro for ES 1.0/1.1 headers"/>
+    </enums>
+
+    <enums namespace="GL" start="0x0000" end="0x7FFF" vendor="ARB" comment="Mostly OpenGL 1.0/1.1 enum assignments. Unused ranges should generally remain unused.">
+        <enum value="0x0000" name="GL_POINTS"/>
+        <enum value="0x0001" name="GL_LINES"/>
+        <enum value="0x0002" name="GL_LINE_LOOP"/>
+        <enum value="0x0003" name="GL_LINE_STRIP"/>
+        <enum value="0x0004" name="GL_TRIANGLES"/>
+        <enum value="0x0005" name="GL_TRIANGLE_STRIP"/>
+        <enum value="0x0006" name="GL_TRIANGLE_FAN"/>
+        <enum value="0x0007" name="GL_QUADS"/>
+        <enum value="0x0007" name="GL_QUADS_EXT"/>
+        <enum value="0x0007" name="GL_QUADS_OES"/>
+        <enum value="0x0008" name="GL_QUAD_STRIP"/>
+        <enum value="0x0009" name="GL_POLYGON"/>
+        <enum value="0x000A" name="GL_LINES_ADJACENCY"/>
+        <enum value="0x000A" name="GL_LINES_ADJACENCY_ARB"/>
+        <enum value="0x000A" name="GL_LINES_ADJACENCY_EXT"/>
+        <enum value="0x000A" name="GL_LINES_ADJACENCY_OES"/>
+        <enum value="0x000B" name="GL_LINE_STRIP_ADJACENCY"/>
+        <enum value="0x000B" name="GL_LINE_STRIP_ADJACENCY_ARB"/>
+        <enum value="0x000B" name="GL_LINE_STRIP_ADJACENCY_EXT"/>
+        <enum value="0x000B" name="GL_LINE_STRIP_ADJACENCY_OES"/>
+        <enum value="0x000C" name="GL_TRIANGLES_ADJACENCY"/>
+        <enum value="0x000C" name="GL_TRIANGLES_ADJACENCY_ARB"/>
+        <enum value="0x000C" name="GL_TRIANGLES_ADJACENCY_EXT"/>
+        <enum value="0x000C" name="GL_TRIANGLES_ADJACENCY_OES"/>
+        <enum value="0x000D" name="GL_TRIANGLE_STRIP_ADJACENCY"/>
+        <enum value="0x000D" name="GL_TRIANGLE_STRIP_ADJACENCY_ARB"/>
+        <enum value="0x000D" name="GL_TRIANGLE_STRIP_ADJACENCY_EXT"/>
+        <enum value="0x000D" name="GL_TRIANGLE_STRIP_ADJACENCY_OES"/>
+        <enum value="0x000E" name="GL_PATCHES"/>
+        <enum value="0x000E" name="GL_PATCHES_EXT"/>
+        <enum value="0x000E" name="GL_PATCHES_OES"/>
+            <unused start="0x000F" end="0x00FF" comment="Unused for PrimitiveType"/>
+        <enum value="0x0100" name="GL_ACCUM"/>
+        <enum value="0x0101" name="GL_LOAD"/>
+        <enum value="0x0102" name="GL_RETURN"/>
+        <enum value="0x0103" name="GL_MULT"/>
+        <enum value="0x0104" name="GL_ADD"/>
+            <unused start="0x0105" end="0x01FF" comment="Unused for AccumOp"/>
+        <enum value="0x0200" name="GL_NEVER"/>
+        <enum value="0x0201" name="GL_LESS"/>
+        <enum value="0x0202" name="GL_EQUAL"/>
+        <enum value="0x0203" name="GL_LEQUAL"/>
+        <enum value="0x0204" name="GL_GREATER"/>
+        <enum value="0x0205" name="GL_NOTEQUAL"/>
+        <enum value="0x0206" name="GL_GEQUAL"/>
+        <enum value="0x0207" name="GL_ALWAYS"/>
+            <unused start="0x0208" end="0x02FF" comment="Unused for AlphaFunction"/>
+        <enum value="0x0300" name="GL_SRC_COLOR"/>
+        <enum value="0x0301" name="GL_ONE_MINUS_SRC_COLOR"/>
+        <enum value="0x0302" name="GL_SRC_ALPHA"/>
+        <enum value="0x0303" name="GL_ONE_MINUS_SRC_ALPHA"/>
+        <enum value="0x0304" name="GL_DST_ALPHA"/>
+        <enum value="0x0305" name="GL_ONE_MINUS_DST_ALPHA"/>
+        <enum value="0x0306" name="GL_DST_COLOR"/>
+        <enum value="0x0307" name="GL_ONE_MINUS_DST_COLOR"/>
+        <enum value="0x0308" name="GL_SRC_ALPHA_SATURATE"/>
+        <enum value="0x0308" name="GL_SRC_ALPHA_SATURATE_EXT"/>
+            <unused start="0x0309" end="0x03FF" comment="Unused for BlendingFactor"/>
+        <enum value="0x0400" name="GL_FRONT_LEFT"/>
+        <enum value="0x0401" name="GL_FRONT_RIGHT"/>
+        <enum value="0x0402" name="GL_BACK_LEFT"/>
+        <enum value="0x0403" name="GL_BACK_RIGHT"/>
+        <enum value="0x0404" name="GL_FRONT"/>
+        <enum value="0x0405" name="GL_BACK"/>
+        <enum value="0x0406" name="GL_LEFT"/>
+        <enum value="0x0407" name="GL_RIGHT"/>
+        <enum value="0x0408" name="GL_FRONT_AND_BACK"/>
+        <enum value="0x0409" name="GL_AUX0"/>
+        <enum value="0x040A" name="GL_AUX1"/>
+        <enum value="0x040B" name="GL_AUX2"/>
+        <enum value="0x040C" name="GL_AUX3"/>
+            <unused start="0x040D" end="0x04FF" comment="Unused for DrawBufferMode"/>
+        <enum value="0x0500" name="GL_INVALID_ENUM"/>
+        <enum value="0x0501" name="GL_INVALID_VALUE"/>
+        <enum value="0x0502" name="GL_INVALID_OPERATION"/>
+        <enum value="0x0503" name="GL_STACK_OVERFLOW"/>
+        <enum value="0x0503" name="GL_STACK_OVERFLOW_KHR"/>
+        <enum value="0x0504" name="GL_STACK_UNDERFLOW"/>
+        <enum value="0x0504" name="GL_STACK_UNDERFLOW_KHR"/>
+        <enum value="0x0505" name="GL_OUT_OF_MEMORY"/>
+        <enum value="0x0506" name="GL_INVALID_FRAMEBUFFER_OPERATION"/>
+        <enum value="0x0506" name="GL_INVALID_FRAMEBUFFER_OPERATION_EXT"/>
+        <enum value="0x0506" name="GL_INVALID_FRAMEBUFFER_OPERATION_OES"/>
+        <enum value="0x0507" name="GL_CONTEXT_LOST"/>
+        <enum value="0x0507" name="GL_CONTEXT_LOST_KHR"/>
+            <unused start="0x0508" end="0x05FF" comment="Unused for ErrorCode"/>
+        <enum value="0x0600" name="GL_2D"/>
+        <enum value="0x0601" name="GL_3D"/>
+        <enum value="0x0602" name="GL_3D_COLOR"/>
+        <enum value="0x0603" name="GL_3D_COLOR_TEXTURE"/>
+        <enum value="0x0604" name="GL_4D_COLOR_TEXTURE"/>
+            <unused start="0x0605" end="0x06FF" comment="Unused for FeedbackType"/>
+        <enum value="0x0700" name="GL_PASS_THROUGH_TOKEN"/>
+        <enum value="0x0701" name="GL_POINT_TOKEN"/>
+        <enum value="0x0702" name="GL_LINE_TOKEN"/>
+        <enum value="0x0703" name="GL_POLYGON_TOKEN"/>
+        <enum value="0x0704" name="GL_BITMAP_TOKEN"/>
+        <enum value="0x0705" name="GL_DRAW_PIXEL_TOKEN"/>
+        <enum value="0x0706" name="GL_COPY_PIXEL_TOKEN"/>
+        <enum value="0x0707" name="GL_LINE_RESET_TOKEN"/>
+            <unused start="0x0708" end="0x07FF" comment="Unused for FeedbackToken"/>
+        <enum value="0x0800" name="GL_EXP"/>
+        <enum value="0x0801" name="GL_EXP2"/>
+            <unused start="0x0802" end="0x08FF" comment="Unused for FogMode"/>
+        <enum value="0x0900" name="GL_CW"/>
+        <enum value="0x0901" name="GL_CCW"/>
+            <unused start="0x0902" end="0x09FF" comment="Unused for FrontFaceDirection"/>
+        <enum value="0x0A00" name="GL_COEFF"/>
+        <enum value="0x0A01" name="GL_ORDER"/>
+        <enum value="0x0A02" name="GL_DOMAIN"/>
+            <unused start="0x0A03" end="0x0AFF" comment="Unused for GetMapQuery"/>
+        <enum value="0x0B00" name="GL_CURRENT_COLOR"/>
+        <enum value="0x0B01" name="GL_CURRENT_INDEX"/>
+        <enum value="0x0B02" name="GL_CURRENT_NORMAL"/>
+        <enum value="0x0B03" name="GL_CURRENT_TEXTURE_COORDS"/>
+        <enum value="0x0B04" name="GL_CURRENT_RASTER_COLOR"/>
+        <enum value="0x0B05" name="GL_CURRENT_RASTER_INDEX"/>
+        <enum value="0x0B06" name="GL_CURRENT_RASTER_TEXTURE_COORDS"/>
+        <enum value="0x0B07" name="GL_CURRENT_RASTER_POSITION"/>
+        <enum value="0x0B08" name="GL_CURRENT_RASTER_POSITION_VALID"/>
+        <enum value="0x0B09" name="GL_CURRENT_RASTER_DISTANCE"/>
+
+        <enum value="0x0B10" name="GL_POINT_SMOOTH"/>
+        <enum value="0x0B11" name="GL_POINT_SIZE"/>
+        <enum value="0x0B12" name="GL_POINT_SIZE_RANGE"/>
+        <enum value="0x0B12" name="GL_SMOOTH_POINT_SIZE_RANGE" alias="GL_POINT_SIZE_RANGE"/>
+        <enum value="0x0B13" name="GL_POINT_SIZE_GRANULARITY"/>
+        <enum value="0x0B13" name="GL_SMOOTH_POINT_SIZE_GRANULARITY" alias="GL_POINT_SIZE_GRANULARITY"/>
+
+        <enum value="0x0B20" name="GL_LINE_SMOOTH"/>
+        <enum value="0x0B21" name="GL_LINE_WIDTH"/>
+        <enum value="0x0B22" name="GL_LINE_WIDTH_RANGE"/>
+        <enum value="0x0B22" name="GL_SMOOTH_LINE_WIDTH_RANGE" alias="GL_LINE_WIDTH_RANGE"/>
+        <enum value="0x0B23" name="GL_LINE_WIDTH_GRANULARITY"/>
+        <enum value="0x0B23" name="GL_SMOOTH_LINE_WIDTH_GRANULARITY" alias="GL_LINE_WIDTH_GRANULARITY"/>
+        <enum value="0x0B24" name="GL_LINE_STIPPLE"/>
+        <enum value="0x0B25" name="GL_LINE_STIPPLE_PATTERN"/>
+        <enum value="0x0B26" name="GL_LINE_STIPPLE_REPEAT"/>
+
+        <enum value="0x0B30" name="GL_LIST_MODE"/>
+        <enum value="0x0B31" name="GL_MAX_LIST_NESTING"/>
+        <enum value="0x0B32" name="GL_LIST_BASE"/>
+        <enum value="0x0B33" name="GL_LIST_INDEX"/>
+
+        <enum value="0x0B40" name="GL_POLYGON_MODE"/>
+        <enum value="0x0B40" name="GL_POLYGON_MODE_NV"/>
+        <enum value="0x0B41" name="GL_POLYGON_SMOOTH"/>
+        <enum value="0x0B42" name="GL_POLYGON_STIPPLE"/>
+        <enum value="0x0B43" name="GL_EDGE_FLAG"/>
+        <enum value="0x0B44" name="GL_CULL_FACE"/>
+        <enum value="0x0B45" name="GL_CULL_FACE_MODE"/>
+        <enum value="0x0B46" name="GL_FRONT_FACE"/>
+
+        <enum value="0x0B50" name="GL_LIGHTING"/>
+        <enum value="0x0B51" name="GL_LIGHT_MODEL_LOCAL_VIEWER"/>
+        <enum value="0x0B52" name="GL_LIGHT_MODEL_TWO_SIDE"/>
+        <enum value="0x0B53" name="GL_LIGHT_MODEL_AMBIENT"/>
+        <enum value="0x0B54" name="GL_SHADE_MODEL"/>
+        <enum value="0x0B55" name="GL_COLOR_MATERIAL_FACE"/>
+        <enum value="0x0B56" name="GL_COLOR_MATERIAL_PARAMETER"/>
+        <enum value="0x0B57" name="GL_COLOR_MATERIAL"/>
+
+        <enum value="0x0B60" name="GL_FOG"/>
+        <enum value="0x0B61" name="GL_FOG_INDEX"/>
+        <enum value="0x0B62" name="GL_FOG_DENSITY"/>
+        <enum value="0x0B63" name="GL_FOG_START"/>
+        <enum value="0x0B64" name="GL_FOG_END"/>
+        <enum value="0x0B65" name="GL_FOG_MODE"/>
+        <enum value="0x0B66" name="GL_FOG_COLOR"/>
+
+        <enum value="0x0B70" name="GL_DEPTH_RANGE"/>
+        <enum value="0x0B71" name="GL_DEPTH_TEST"/>
+        <enum value="0x0B72" name="GL_DEPTH_WRITEMASK"/>
+        <enum value="0x0B73" name="GL_DEPTH_CLEAR_VALUE"/>
+        <enum value="0x0B74" name="GL_DEPTH_FUNC"/>
+
+        <enum value="0x0B80" name="GL_ACCUM_CLEAR_VALUE"/>
+
+        <enum value="0x0B90" name="GL_STENCIL_TEST"/>
+        <enum value="0x0B91" name="GL_STENCIL_CLEAR_VALUE"/>
+        <enum value="0x0B92" name="GL_STENCIL_FUNC"/>
+        <enum value="0x0B93" name="GL_STENCIL_VALUE_MASK"/>
+        <enum value="0x0B94" name="GL_STENCIL_FAIL"/>
+        <enum value="0x0B95" name="GL_STENCIL_PASS_DEPTH_FAIL"/>
+        <enum value="0x0B96" name="GL_STENCIL_PASS_DEPTH_PASS"/>
+        <enum value="0x0B97" name="GL_STENCIL_REF"/>
+        <enum value="0x0B98" name="GL_STENCIL_WRITEMASK"/>
+
+        <enum value="0x0BA0" name="GL_MATRIX_MODE"/>
+        <enum value="0x0BA1" name="GL_NORMALIZE"/>
+        <enum value="0x0BA2" name="GL_VIEWPORT"/>
+        <enum value="0x0BA3" name="GL_MODELVIEW_STACK_DEPTH"/>
+        <enum value="0x0BA3" name="GL_MODELVIEW0_STACK_DEPTH_EXT"/>
+        <enum value="0x0BA3" name="GL_PATH_MODELVIEW_STACK_DEPTH_NV"/>
+        <enum value="0x0BA4" name="GL_PROJECTION_STACK_DEPTH"/>
+        <enum value="0x0BA4" name="GL_PATH_PROJECTION_STACK_DEPTH_NV"/>
+        <enum value="0x0BA5" name="GL_TEXTURE_STACK_DEPTH"/>
+        <enum value="0x0BA6" name="GL_MODELVIEW_MATRIX"/>
+        <enum value="0x0BA6" name="GL_MODELVIEW0_MATRIX_EXT"/>
+        <enum value="0x0BA6" name="GL_PATH_MODELVIEW_MATRIX_NV"/>
+        <enum value="0x0BA7" name="GL_PROJECTION_MATRIX"/>
+        <enum value="0x0BA7" name="GL_PATH_PROJECTION_MATRIX_NV"/>
+        <enum value="0x0BA8" name="GL_TEXTURE_MATRIX"/>
+
+        <enum value="0x0BB0" name="GL_ATTRIB_STACK_DEPTH"/>
+        <enum value="0x0BB1" name="GL_CLIENT_ATTRIB_STACK_DEPTH"/>
+
+        <enum value="0x0BC0" name="GL_ALPHA_TEST"/>
+        <enum value="0x0BC0" name="GL_ALPHA_TEST_QCOM"/>
+        <enum value="0x0BC1" name="GL_ALPHA_TEST_FUNC"/>
+        <enum value="0x0BC1" name="GL_ALPHA_TEST_FUNC_QCOM"/>
+        <enum value="0x0BC2" name="GL_ALPHA_TEST_REF"/>
+        <enum value="0x0BC2" name="GL_ALPHA_TEST_REF_QCOM"/>
+
+        <enum value="0x0BD0" name="GL_DITHER"/>
+
+        <enum value="0x0BE0" name="GL_BLEND_DST"/>
+        <enum value="0x0BE1" name="GL_BLEND_SRC"/>
+        <enum value="0x0BE2" name="GL_BLEND"/>
+
+        <enum value="0x0BF0" name="GL_LOGIC_OP_MODE"/>
+        <enum value="0x0BF1" name="GL_INDEX_LOGIC_OP"/>
+        <enum value="0x0BF1" name="GL_LOGIC_OP"/>
+        <enum value="0x0BF2" name="GL_COLOR_LOGIC_OP"/>
+
+        <enum value="0x0C00" name="GL_AUX_BUFFERS"/>
+        <enum value="0x0C01" name="GL_DRAW_BUFFER"/>
+        <enum value="0x0C01" name="GL_DRAW_BUFFER_EXT"/>
+        <enum value="0x0C02" name="GL_READ_BUFFER"/>
+        <enum value="0x0C02" name="GL_READ_BUFFER_EXT"/>
+        <enum value="0x0C02" name="GL_READ_BUFFER_NV"/>
+
+        <enum value="0x0C10" name="GL_SCISSOR_BOX"/>
+        <enum value="0x0C11" name="GL_SCISSOR_TEST"/>
+
+        <enum value="0x0C20" name="GL_INDEX_CLEAR_VALUE"/>
+        <enum value="0x0C21" name="GL_INDEX_WRITEMASK"/>
+        <enum value="0x0C22" name="GL_COLOR_CLEAR_VALUE"/>
+        <enum value="0x0C23" name="GL_COLOR_WRITEMASK"/>
+
+        <enum value="0x0C30" name="GL_INDEX_MODE"/>
+        <enum value="0x0C31" name="GL_RGBA_MODE"/>
+        <enum value="0x0C32" name="GL_DOUBLEBUFFER"/>
+        <enum value="0x0C33" name="GL_STEREO"/>
+
+        <enum value="0x0C40" name="GL_RENDER_MODE"/>
+
+        <enum value="0x0C50" name="GL_PERSPECTIVE_CORRECTION_HINT"/>
+        <enum value="0x0C51" name="GL_POINT_SMOOTH_HINT"/>
+        <enum value="0x0C52" name="GL_LINE_SMOOTH_HINT"/>
+        <enum value="0x0C53" name="GL_POLYGON_SMOOTH_HINT"/>
+        <enum value="0x0C54" name="GL_FOG_HINT"/>
+
+        <enum value="0x0C60" name="GL_TEXTURE_GEN_S"/>
+        <enum value="0x0C61" name="GL_TEXTURE_GEN_T"/>
+        <enum value="0x0C62" name="GL_TEXTURE_GEN_R"/>
+        <enum value="0x0C63" name="GL_TEXTURE_GEN_Q"/>
+
+        <enum value="0x0C70" name="GL_PIXEL_MAP_I_TO_I"/>
+        <enum value="0x0C71" name="GL_PIXEL_MAP_S_TO_S"/>
+        <enum value="0x0C72" name="GL_PIXEL_MAP_I_TO_R"/>
+        <enum value="0x0C73" name="GL_PIXEL_MAP_I_TO_G"/>
+        <enum value="0x0C74" name="GL_PIXEL_MAP_I_TO_B"/>
+        <enum value="0x0C75" name="GL_PIXEL_MAP_I_TO_A"/>
+        <enum value="0x0C76" name="GL_PIXEL_MAP_R_TO_R"/>
+        <enum value="0x0C77" name="GL_PIXEL_MAP_G_TO_G"/>
+        <enum value="0x0C78" name="GL_PIXEL_MAP_B_TO_B"/>
+        <enum value="0x0C79" name="GL_PIXEL_MAP_A_TO_A"/>
+
+        <enum value="0x0CB0" name="GL_PIXEL_MAP_I_TO_I_SIZE"/>
+        <enum value="0x0CB1" name="GL_PIXEL_MAP_S_TO_S_SIZE"/>
+        <enum value="0x0CB2" name="GL_PIXEL_MAP_I_TO_R_SIZE"/>
+        <enum value="0x0CB3" name="GL_PIXEL_MAP_I_TO_G_SIZE"/>
+        <enum value="0x0CB4" name="GL_PIXEL_MAP_I_TO_B_SIZE"/>
+        <enum value="0x0CB5" name="GL_PIXEL_MAP_I_TO_A_SIZE"/>
+        <enum value="0x0CB6" name="GL_PIXEL_MAP_R_TO_R_SIZE"/>
+        <enum value="0x0CB7" name="GL_PIXEL_MAP_G_TO_G_SIZE"/>
+        <enum value="0x0CB8" name="GL_PIXEL_MAP_B_TO_B_SIZE"/>
+        <enum value="0x0CB9" name="GL_PIXEL_MAP_A_TO_A_SIZE"/>
+
+        <enum value="0x0CF0" name="GL_UNPACK_SWAP_BYTES"/>
+        <enum value="0x0CF1" name="GL_UNPACK_LSB_FIRST"/>
+        <enum value="0x0CF2" name="GL_UNPACK_ROW_LENGTH"/>
+        <enum value="0x0CF2" name="GL_UNPACK_ROW_LENGTH_EXT"/>
+        <enum value="0x0CF3" name="GL_UNPACK_SKIP_ROWS"/>
+        <enum value="0x0CF3" name="GL_UNPACK_SKIP_ROWS_EXT"/>
+        <enum value="0x0CF4" name="GL_UNPACK_SKIP_PIXELS"/>
+        <enum value="0x0CF4" name="GL_UNPACK_SKIP_PIXELS_EXT"/>
+        <enum value="0x0CF5" name="GL_UNPACK_ALIGNMENT"/>
+
+        <enum value="0x0D00" name="GL_PACK_SWAP_BYTES"/>
+        <enum value="0x0D01" name="GL_PACK_LSB_FIRST"/>
+        <enum value="0x0D02" name="GL_PACK_ROW_LENGTH"/>
+        <enum value="0x0D03" name="GL_PACK_SKIP_ROWS"/>
+        <enum value="0x0D04" name="GL_PACK_SKIP_PIXELS"/>
+        <enum value="0x0D05" name="GL_PACK_ALIGNMENT"/>
+
+        <enum value="0x0D10" name="GL_MAP_COLOR"/>
+        <enum value="0x0D11" name="GL_MAP_STENCIL"/>
+        <enum value="0x0D12" name="GL_INDEX_SHIFT"/>
+        <enum value="0x0D13" name="GL_INDEX_OFFSET"/>
+        <enum value="0x0D14" name="GL_RED_SCALE"/>
+        <enum value="0x0D15" name="GL_RED_BIAS"/>
+        <enum value="0x0D16" name="GL_ZOOM_X"/>
+        <enum value="0x0D17" name="GL_ZOOM_Y"/>
+        <enum value="0x0D18" name="GL_GREEN_SCALE"/>
+        <enum value="0x0D19" name="GL_GREEN_BIAS"/>
+        <enum value="0x0D1A" name="GL_BLUE_SCALE"/>
+        <enum value="0x0D1B" name="GL_BLUE_BIAS"/>
+        <enum value="0x0D1C" name="GL_ALPHA_SCALE"/>
+        <enum value="0x0D1D" name="GL_ALPHA_BIAS"/>
+        <enum value="0x0D1E" name="GL_DEPTH_SCALE"/>
+        <enum value="0x0D1F" name="GL_DEPTH_BIAS"/>
+
+        <enum value="0x0D30" name="GL_MAX_EVAL_ORDER"/>
+        <enum value="0x0D31" name="GL_MAX_LIGHTS"/>
+        <enum value="0x0D32" name="GL_MAX_CLIP_PLANES"/>
+        <enum value="0x0D32" name="GL_MAX_CLIP_PLANES_IMG"/>
+        <enum value="0x0D32" name="GL_MAX_CLIP_DISTANCES" alias="GL_MAX_CLIP_PLANES"/>
+        <enum value="0x0D32" name="GL_MAX_CLIP_DISTANCES_EXT" alias="GL_MAX_CLIP_PLANES"/>
+        <enum value="0x0D32" name="GL_MAX_CLIP_DISTANCES_APPLE"/>
+        <enum value="0x0D33" name="GL_MAX_TEXTURE_SIZE"/>
+        <enum value="0x0D34" name="GL_MAX_PIXEL_MAP_TABLE"/>
+        <enum value="0x0D35" name="GL_MAX_ATTRIB_STACK_DEPTH"/>
+        <enum value="0x0D36" name="GL_MAX_MODELVIEW_STACK_DEPTH"/>
+        <enum value="0x0D36" name="GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV"/>
+        <enum value="0x0D37" name="GL_MAX_NAME_STACK_DEPTH"/>
+        <enum value="0x0D38" name="GL_MAX_PROJECTION_STACK_DEPTH"/>
+        <enum value="0x0D38" name="GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV"/>
+        <enum value="0x0D39" name="GL_MAX_TEXTURE_STACK_DEPTH"/>
+        <enum value="0x0D3A" name="GL_MAX_VIEWPORT_DIMS"/>
+        <enum value="0x0D3B" name="GL_MAX_CLIENT_ATTRIB_STACK_DEPTH"/>
+
+        <enum value="0x0D50" name="GL_SUBPIXEL_BITS"/>
+        <enum value="0x0D51" name="GL_INDEX_BITS"/>
+        <enum value="0x0D52" name="GL_RED_BITS"/>
+        <enum value="0x0D53" name="GL_GREEN_BITS"/>
+        <enum value="0x0D54" name="GL_BLUE_BITS"/>
+        <enum value="0x0D55" name="GL_ALPHA_BITS"/>
+        <enum value="0x0D56" name="GL_DEPTH_BITS"/>
+        <enum value="0x0D57" name="GL_STENCIL_BITS"/>
+        <enum value="0x0D58" name="GL_ACCUM_RED_BITS"/>
+        <enum value="0x0D59" name="GL_ACCUM_GREEN_BITS"/>
+        <enum value="0x0D5A" name="GL_ACCUM_BLUE_BITS"/>
+        <enum value="0x0D5B" name="GL_ACCUM_ALPHA_BITS"/>
+
+        <enum value="0x0D70" name="GL_NAME_STACK_DEPTH"/>
+
+        <enum value="0x0D80" name="GL_AUTO_NORMAL"/>
+
+        <enum value="0x0D90" name="GL_MAP1_COLOR_4"/>
+        <enum value="0x0D91" name="GL_MAP1_INDEX"/>
+        <enum value="0x0D92" name="GL_MAP1_NORMAL"/>
+        <enum value="0x0D93" name="GL_MAP1_TEXTURE_COORD_1"/>
+        <enum value="0x0D94" name="GL_MAP1_TEXTURE_COORD_2"/>
+        <enum value="0x0D95" name="GL_MAP1_TEXTURE_COORD_3"/>
+        <enum value="0x0D96" name="GL_MAP1_TEXTURE_COORD_4"/>
+        <enum value="0x0D97" name="GL_MAP1_VERTEX_3"/>
+        <enum value="0x0D98" name="GL_MAP1_VERTEX_4"/>
+
+        <enum value="0x0DB0" name="GL_MAP2_COLOR_4"/>
+        <enum value="0x0DB1" name="GL_MAP2_INDEX"/>
+        <enum value="0x0DB2" name="GL_MAP2_NORMAL"/>
+        <enum value="0x0DB3" name="GL_MAP2_TEXTURE_COORD_1"/>
+        <enum value="0x0DB4" name="GL_MAP2_TEXTURE_COORD_2"/>
+        <enum value="0x0DB5" name="GL_MAP2_TEXTURE_COORD_3"/>
+        <enum value="0x0DB6" name="GL_MAP2_TEXTURE_COORD_4"/>
+        <enum value="0x0DB7" name="GL_MAP2_VERTEX_3"/>
+        <enum value="0x0DB8" name="GL_MAP2_VERTEX_4"/>
+
+        <enum value="0x0DD0" name="GL_MAP1_GRID_DOMAIN"/>
+        <enum value="0x0DD1" name="GL_MAP1_GRID_SEGMENTS"/>
+        <enum value="0x0DD2" name="GL_MAP2_GRID_DOMAIN"/>
+        <enum value="0x0DD3" name="GL_MAP2_GRID_SEGMENTS"/>
+
+        <enum value="0x0DE0" name="GL_TEXTURE_1D"/>
+        <enum value="0x0DE1" name="GL_TEXTURE_2D"/>
+
+        <enum value="0x0DF0" name="GL_FEEDBACK_BUFFER_POINTER"/>
+        <enum value="0x0DF1" name="GL_FEEDBACK_BUFFER_SIZE"/>
+        <enum value="0x0DF2" name="GL_FEEDBACK_BUFFER_TYPE"/>
+        <enum value="0x0DF3" name="GL_SELECTION_BUFFER_POINTER"/>
+        <enum value="0x0DF4" name="GL_SELECTION_BUFFER_SIZE"/>
+            <unused start="0x0DF5" end="0xFFFF" comment="Unused for GetPName"/>
+        <enum value="0x1000" name="GL_TEXTURE_WIDTH"/>
+        <enum value="0x1001" name="GL_TEXTURE_HEIGHT"/>
+        <enum value="0x1003" name="GL_TEXTURE_INTERNAL_FORMAT"/>
+        <enum value="0x1003" name="GL_TEXTURE_COMPONENTS"/>
+        <enum value="0x1004" name="GL_TEXTURE_BORDER_COLOR"/>
+        <enum value="0x1004" name="GL_TEXTURE_BORDER_COLOR_EXT"/>
+        <enum value="0x1004" name="GL_TEXTURE_BORDER_COLOR_NV"/>
+        <enum value="0x1004" name="GL_TEXTURE_BORDER_COLOR_OES"/>
+        <enum value="0x1005" name="GL_TEXTURE_BORDER"/>
+        <enum value="0x1006" name="GL_TEXTURE_TARGET"/>
+            <unused start="0x1007" end="0x10FF" comment="Unused for GetTextureParameter"/>
+        <enum value="0x1100" name="GL_DONT_CARE"/>
+        <enum value="0x1101" name="GL_FASTEST"/>
+        <enum value="0x1102" name="GL_NICEST"/>
+            <unused start="0x1103" end="0x11FF" comment="Unused for HintMode"/>
+        <enum value="0x1200" name="GL_AMBIENT"/>
+        <enum value="0x1201" name="GL_DIFFUSE"/>
+        <enum value="0x1202" name="GL_SPECULAR"/>
+        <enum value="0x1203" name="GL_POSITION"/>
+        <enum value="0x1204" name="GL_SPOT_DIRECTION"/>
+        <enum value="0x1205" name="GL_SPOT_EXPONENT"/>
+        <enum value="0x1206" name="GL_SPOT_CUTOFF"/>
+        <enum value="0x1207" name="GL_CONSTANT_ATTENUATION"/>
+        <enum value="0x1208" name="GL_LINEAR_ATTENUATION"/>
+        <enum value="0x1209" name="GL_QUADRATIC_ATTENUATION"/>
+            <unused start="0x1210" end="0x12FF" comment="Unused for LightParameter"/>
+        <enum value="0x1300" name="GL_COMPILE"/>
+        <enum value="0x1301" name="GL_COMPILE_AND_EXECUTE"/>
+            <unused start="0x1302" end="0x13FF" comment="Unused for ListMode"/>
+        <enum value="0x1400" name="GL_BYTE"/>
+        <enum value="0x1401" name="GL_UNSIGNED_BYTE"/>
+        <enum value="0x1402" name="GL_SHORT"/>
+        <enum value="0x1403" name="GL_UNSIGNED_SHORT"/>
+        <enum value="0x1404" name="GL_INT"/>
+        <enum value="0x1405" name="GL_UNSIGNED_INT"/>
+        <enum value="0x1406" name="GL_FLOAT"/>
+        <enum value="0x1407" name="GL_2_BYTES"/>
+        <enum value="0x1407" name="GL_2_BYTES_NV"/>
+        <enum value="0x1408" name="GL_3_BYTES"/>
+        <enum value="0x1408" name="GL_3_BYTES_NV"/>
+        <enum value="0x1409" name="GL_4_BYTES"/>
+        <enum value="0x1409" name="GL_4_BYTES_NV"/>
+        <enum value="0x140A" name="GL_DOUBLE"/>
+        <enum value="0x140A" name="GL_DOUBLE_EXT"/>
+        <enum value="0x140B" name="GL_HALF_FLOAT"/>
+        <enum value="0x140B" name="GL_HALF_FLOAT_ARB"/>
+        <enum value="0x140B" name="GL_HALF_FLOAT_NV"/>
+        <enum value="0x140B" name="GL_HALF_APPLE"/>
+        <enum value="0x140C" name="GL_FIXED"/>
+        <enum value="0x140C" name="GL_FIXED_OES"/>
+            <unused start="0x140D" comment="Leave gap to preserve even/odd int/uint token values"/>
+        <enum value="0x140E" name="GL_INT64_ARB"/>
+        <enum value="0x140E" name="GL_INT64_NV"/>
+        <enum value="0x140F" name="GL_UNSIGNED_INT64_ARB"/>
+        <enum value="0x140F" name="GL_UNSIGNED_INT64_NV"/>
+            <unused start="0x1410" end="0x14FF" comment="Unused for DataType"/>
+        <enum value="0x1500" name="GL_CLEAR"/>
+        <enum value="0x1501" name="GL_AND"/>
+        <enum value="0x1502" name="GL_AND_REVERSE"/>
+        <enum value="0x1503" name="GL_COPY"/>
+        <enum value="0x1504" name="GL_AND_INVERTED"/>
+        <enum value="0x1505" name="GL_NOOP"/>
+        <enum value="0x1506" name="GL_XOR"/>
+        <enum value="0x1506" name="GL_XOR_NV"/>
+        <enum value="0x1507" name="GL_OR"/>
+        <enum value="0x1508" name="GL_NOR"/>
+        <enum value="0x1509" name="GL_EQUIV"/>
+        <enum value="0x150A" name="GL_INVERT"/>
+        <enum value="0x150B" name="GL_OR_REVERSE"/>
+        <enum value="0x150C" name="GL_COPY_INVERTED"/>
+        <enum value="0x150D" name="GL_OR_INVERTED"/>
+        <enum value="0x150E" name="GL_NAND"/>
+        <enum value="0x150F" name="GL_SET"/>
+            <unused start="0x1510" end="0x15FF" comment="Unused for LogicOp"/>
+        <enum value="0x1600" name="GL_EMISSION"/>
+        <enum value="0x1601" name="GL_SHININESS"/>
+        <enum value="0x1602" name="GL_AMBIENT_AND_DIFFUSE"/>
+        <enum value="0x1603" name="GL_COLOR_INDEXES"/>
+            <unused start="0x1604" end="0x16FF" comment="Unused for MaterialParameter"/>
+        <enum value="0x1700" name="GL_MODELVIEW"/>
+        <enum value="0x1700" name="GL_MODELVIEW0_ARB"/>
+        <enum value="0x1700" name="GL_MODELVIEW0_EXT"/>
+        <enum value="0x1700" name="GL_PATH_MODELVIEW_NV"/>
+        <enum value="0x1701" name="GL_PROJECTION"/>
+        <enum value="0x1701" name="GL_PATH_PROJECTION_NV"/>
+        <enum value="0x1702" name="GL_TEXTURE"/>
+            <unused start="0x1703" end="0x17FF" comment="Unused for MatrixMode"/>
+        <enum value="0x1800" name="GL_COLOR"/>
+        <enum value="0x1800" name="GL_COLOR_EXT"/>
+        <enum value="0x1801" name="GL_DEPTH"/>
+        <enum value="0x1801" name="GL_DEPTH_EXT"/>
+        <enum value="0x1802" name="GL_STENCIL"/>
+        <enum value="0x1802" name="GL_STENCIL_EXT"/>
+            <unused start="0x1803" end="0x18FF" comment="Unused for PixelCopyType"/>
+        <enum value="0x1900" name="GL_COLOR_INDEX"/>
+        <enum value="0x1901" name="GL_STENCIL_INDEX"/>
+        <enum value="0x1901" name="GL_STENCIL_INDEX_OES"/>
+        <enum value="0x1902" name="GL_DEPTH_COMPONENT"/>
+        <enum value="0x1903" name="GL_RED"/>
+        <enum value="0x1903" name="GL_RED_EXT"/>
+        <enum value="0x1903" name="GL_RED_NV"/>
+        <enum value="0x1904" name="GL_GREEN"/>
+        <enum value="0x1904" name="GL_GREEN_NV"/>
+        <enum value="0x1905" name="GL_BLUE"/>
+        <enum value="0x1905" name="GL_BLUE_NV"/>
+        <enum value="0x1906" name="GL_ALPHA"/>
+        <enum value="0x1907" name="GL_RGB"/>
+        <enum value="0x1908" name="GL_RGBA"/>
+        <enum value="0x1909" name="GL_LUMINANCE"/>
+        <enum value="0x190A" name="GL_LUMINANCE_ALPHA"/>
+            <unused start="0x1910" end="0x19FF" comment="Unused for PixelFormat"/>
+        <enum value="0x1A00" name="GL_BITMAP"/>
+            <unused start="0x1A01" end="0x1AFF" comment="Unused for PixelType"/>
+        <enum value="0x1B00" name="GL_POINT"/>
+        <enum value="0x1B00" name="GL_POINT_NV"/>
+        <enum value="0x1B01" name="GL_LINE"/>
+        <enum value="0x1B01" name="GL_LINE_NV"/>
+        <enum value="0x1B02" name="GL_FILL"/>
+        <enum value="0x1B02" name="GL_FILL_NV"/>
+            <unused start="0x1B03" end="0x1BFF" comment="Unused for PolygonMode"/>
+        <enum value="0x1C00" name="GL_RENDER"/>
+        <enum value="0x1C01" name="GL_FEEDBACK"/>
+        <enum value="0x1C02" name="GL_SELECT"/>
+            <unused start="0x1C03" end="0x1CFF" comment="Unused for RenderingMode"/>
+        <enum value="0x1D00" name="GL_FLAT"/>
+        <enum value="0x1D01" name="GL_SMOOTH"/>
+            <unused start="0x1D02" end="0x1DFF" comment="Unused for ShadingModel"/>
+        <enum value="0x1E00" name="GL_KEEP"/>
+        <enum value="0x1E01" name="GL_REPLACE"/>
+        <enum value="0x1E02" name="GL_INCR"/>
+        <enum value="0x1E03" name="GL_DECR"/>
+            <unused start="0x1E04" end="0x1EFF" comment="Unused for StencilOp"/>
+        <enum value="0x1F00" name="GL_VENDOR"/>
+        <enum value="0x1F01" name="GL_RENDERER"/>
+        <enum value="0x1F02" name="GL_VERSION"/>
+        <enum value="0x1F03" name="GL_EXTENSIONS"/>
+            <unused start="0x1F04" end="0x1FFF" comment="Unused for StringName"/>
+        <enum value="0x2000" name="GL_S"/>
+        <enum value="0x2001" name="GL_T"/>
+        <enum value="0x2002" name="GL_R"/>
+        <enum value="0x2003" name="GL_Q"/>
+            <unused start="0x2004" end="0x20FF" comment="Unused for TextureCoordName"/>
+        <enum value="0x2100" name="GL_MODULATE"/>
+        <enum value="0x2101" name="GL_DECAL"/>
+            <unused start="0x2102" end="0x21FF" comment="Unused for TextureEnvMode"/>
+        <enum value="0x2200" name="GL_TEXTURE_ENV_MODE"/>
+        <enum value="0x2201" name="GL_TEXTURE_ENV_COLOR"/>
+            <unused start="0x2202" end="0x22FF" comment="Unused for TextureEnvParameter"/>
+        <enum value="0x2300" name="GL_TEXTURE_ENV"/>
+            <unused start="0x2301" end="0x23FF" comment="Unused for TextureEnvTarget"/>
+        <enum value="0x2400" name="GL_EYE_LINEAR"/>
+        <enum value="0x2400" name="GL_EYE_LINEAR_NV"/>
+        <enum value="0x2401" name="GL_OBJECT_LINEAR"/>
+        <enum value="0x2401" name="GL_OBJECT_LINEAR_NV"/>
+        <enum value="0x2402" name="GL_SPHERE_MAP"/>
+            <unused start="0x2403" end="0x24FF" comment="Unused for TextureGenMode"/>
+        <enum value="0x2500" name="GL_TEXTURE_GEN_MODE"/>
+        <enum value="0x2500" name="GL_TEXTURE_GEN_MODE_OES"/>
+        <enum value="0x2501" name="GL_OBJECT_PLANE"/>
+        <enum value="0x2502" name="GL_EYE_PLANE"/>
+            <unused start="0x2503" end="0x25FF" comment="Unused for TextureGenParameter"/>
+        <enum value="0x2600" name="GL_NEAREST"/>
+        <enum value="0x2601" name="GL_LINEAR"/>
+            <unused start="0x2602" end="0x26FF" comment="Unused for TextureMagFilter"/>
+        <enum value="0x2700" name="GL_NEAREST_MIPMAP_NEAREST"/>
+        <enum value="0x2701" name="GL_LINEAR_MIPMAP_NEAREST"/>
+        <enum value="0x2702" name="GL_NEAREST_MIPMAP_LINEAR"/>
+        <enum value="0x2703" name="GL_LINEAR_MIPMAP_LINEAR"/>
+            <unused start="0x2704" end="0x27FF" comment="Unused for TextureMinFilter"/>
+        <enum value="0x2800" name="GL_TEXTURE_MAG_FILTER"/>
+        <enum value="0x2801" name="GL_TEXTURE_MIN_FILTER"/>
+        <enum value="0x2802" name="GL_TEXTURE_WRAP_S"/>
+        <enum value="0x2803" name="GL_TEXTURE_WRAP_T"/>
+            <unused start="0x2804" end="0x28FF" comment="Unused for TextureParameterName"/>
+        <enum value="0x2900" name="GL_CLAMP"/>
+        <enum value="0x2901" name="GL_REPEAT"/>
+            <unused start="0x2902" end="0x29FF" comment="Unused for TextureWrapMode"/>
+        <enum value="0x2A00" name="GL_POLYGON_OFFSET_UNITS"/>
+        <enum value="0x2A01" name="GL_POLYGON_OFFSET_POINT"/>
+        <enum value="0x2A01" name="GL_POLYGON_OFFSET_POINT_NV"/>
+        <enum value="0x2A02" name="GL_POLYGON_OFFSET_LINE"/>
+        <enum value="0x2A02" name="GL_POLYGON_OFFSET_LINE_NV"/>
+            <unused start="0x2A03" end="0x2A09" comment="Unused for PolygonOffset"/>
+        <enum value="0x2A10" name="GL_R3_G3_B2"/>
+            <unused start="0x2A11" end="0x2A1F" comment="Unused for InternalFormat"/>
+        <enum value="0x2A20" name="GL_V2F"/>
+        <enum value="0x2A21" name="GL_V3F"/>
+        <enum value="0x2A22" name="GL_C4UB_V2F"/>
+        <enum value="0x2A23" name="GL_C4UB_V3F"/>
+        <enum value="0x2A24" name="GL_C3F_V3F"/>
+        <enum value="0x2A25" name="GL_N3F_V3F"/>
+        <enum value="0x2A26" name="GL_C4F_N3F_V3F"/>
+        <enum value="0x2A27" name="GL_T2F_V3F"/>
+        <enum value="0x2A28" name="GL_T4F_V4F"/>
+        <enum value="0x2A29" name="GL_T2F_C4UB_V3F"/>
+        <enum value="0x2A2A" name="GL_T2F_C3F_V3F"/>
+        <enum value="0x2A2B" name="GL_T2F_N3F_V3F"/>
+        <enum value="0x2A2C" name="GL_T2F_C4F_N3F_V3F"/>
+        <enum value="0x2A2D" name="GL_T4F_C4F_N3F_V4F"/>
+            <unused start="0x2A2E" end="0x2FFF" comment="Unused for InterleavedArrayFormat"/>
+        <enum value="0x3000" name="GL_CLIP_PLANE0"/>
+        <enum value="0x3000" name="GL_CLIP_PLANE0_IMG"/>
+        <enum value="0x3000" name="GL_CLIP_DISTANCE0" alias="GL_CLIP_PLANE0"/>
+        <enum value="0x3000" name="GL_CLIP_DISTANCE0_EXT" alias="GL_CLIP_PLANE0"/>
+        <enum value="0x3000" name="GL_CLIP_DISTANCE0_APPLE"/>
+        <enum value="0x3001" name="GL_CLIP_PLANE1"/>
+        <enum value="0x3001" name="GL_CLIP_PLANE1_IMG"/>
+        <enum value="0x3001" name="GL_CLIP_DISTANCE1" alias="GL_CLIP_PLANE1"/>
+        <enum value="0x3001" name="GL_CLIP_DISTANCE1_EXT" alias="GL_CLIP_PLANE1"/>
+        <enum value="0x3001" name="GL_CLIP_DISTANCE1_APPLE"/>
+        <enum value="0x3002" name="GL_CLIP_PLANE2"/>
+        <enum value="0x3002" name="GL_CLIP_PLANE2_IMG"/>
+        <enum value="0x3002" name="GL_CLIP_DISTANCE2" alias="GL_CLIP_PLANE2"/>
+        <enum value="0x3002" name="GL_CLIP_DISTANCE2_EXT" alias="GL_CLIP_PLANE2"/>
+        <enum value="0x3002" name="GL_CLIP_DISTANCE2_APPLE"/>
+        <enum value="0x3003" name="GL_CLIP_PLANE3"/>
+        <enum value="0x3003" name="GL_CLIP_PLANE3_IMG"/>
+        <enum value="0x3003" name="GL_CLIP_DISTANCE3" alias="GL_CLIP_PLANE3"/>
+        <enum value="0x3003" name="GL_CLIP_DISTANCE3_EXT" alias="GL_CLIP_PLANE3"/>
+        <enum value="0x3003" name="GL_CLIP_DISTANCE3_APPLE"/>
+        <enum value="0x3004" name="GL_CLIP_PLANE4"/>
+        <enum value="0x3004" name="GL_CLIP_PLANE4_IMG"/>
+        <enum value="0x3004" name="GL_CLIP_DISTANCE4" alias="GL_CLIP_PLANE4"/>
+        <enum value="0x3004" name="GL_CLIP_DISTANCE4_EXT" alias="GL_CLIP_PLANE4"/>
+        <enum value="0x3004" name="GL_CLIP_DISTANCE4_APPLE"/>
+        <enum value="0x3005" name="GL_CLIP_PLANE5"/>
+        <enum value="0x3005" name="GL_CLIP_PLANE5_IMG"/>
+        <enum value="0x3005" name="GL_CLIP_DISTANCE5" alias="GL_CLIP_PLANE5"/>
+        <enum value="0x3005" name="GL_CLIP_DISTANCE5_EXT" alias="GL_CLIP_PLANE5"/>
+        <enum value="0x3005" name="GL_CLIP_DISTANCE5_APPLE"/>
+        <enum value="0x3006" name="GL_CLIP_DISTANCE6"/>
+        <enum value="0x3006" name="GL_CLIP_DISTANCE6_EXT" alias="GL_CLIP_DISTANCE6"/>
+        <enum value="0x3006" name="GL_CLIP_DISTANCE6_APPLE"/>
+        <enum value="0x3007" name="GL_CLIP_DISTANCE7"/>
+        <enum value="0x3007" name="GL_CLIP_DISTANCE7_EXT" alias="GL_CLIP_DISTANCE7"/>
+        <enum value="0x3007" name="GL_CLIP_DISTANCE7_APPLE"/>
+            <unused start="0x3008" end="0x3FFF" comment="Unused for ClipPlaneName"/>
+        <enum value="0x4000" name="GL_LIGHT0"/>
+        <enum value="0x4001" name="GL_LIGHT1"/>
+        <enum value="0x4002" name="GL_LIGHT2"/>
+        <enum value="0x4003" name="GL_LIGHT3"/>
+        <enum value="0x4004" name="GL_LIGHT4"/>
+        <enum value="0x4005" name="GL_LIGHT5"/>
+        <enum value="0x4006" name="GL_LIGHT6"/>
+        <enum value="0x4007" name="GL_LIGHT7"/>
+            <unused start="0x4008" end="0x4FFF" comment="Unused for LightName"/>
+            <unused start="0x5000" end="0x5FFF" comment="Unused. Do not use."/>
+            <unused start="0x6000" end="0x6FFF" comment="Experimental (internal/test only) range. DO NOT SHIP VALUES IN THIS RANGE."/>
+            <unused start="0x7000" end="0x7FFF" comment="Unused. Do not use."/>
+    </enums>
+
+    <enums namespace="GL" start="0x8000" end="0x80BF" vendor="ARB" comment="The primary GL enumerant space begins here. All modern enum allocations are in this range. These enums are mostly assigned the default class since it's a great deal of not very useful work to be more specific">
+        <enum value="0x8000" name="GL_ABGR_EXT"/>
+        <enum value="0x8001" name="GL_CONSTANT_COLOR"/>
+        <enum value="0x8001" name="GL_CONSTANT_COLOR_EXT"/>
+        <enum value="0x8002" name="GL_ONE_MINUS_CONSTANT_COLOR"/>
+        <enum value="0x8002" name="GL_ONE_MINUS_CONSTANT_COLOR_EXT"/>
+        <enum value="0x8003" name="GL_CONSTANT_ALPHA"/>
+        <enum value="0x8003" name="GL_CONSTANT_ALPHA_EXT"/>
+        <enum value="0x8004" name="GL_ONE_MINUS_CONSTANT_ALPHA"/>
+        <enum value="0x8004" name="GL_ONE_MINUS_CONSTANT_ALPHA_EXT"/>
+        <enum value="0x8005" name="GL_BLEND_COLOR"/>
+        <enum value="0x8005" name="GL_BLEND_COLOR_EXT"/>
+        <enum value="0x8006" name="GL_FUNC_ADD"/>
+        <enum value="0x8006" name="GL_FUNC_ADD_EXT"/>
+        <enum value="0x8006" name="GL_FUNC_ADD_OES"/>
+        <enum value="0x8007" name="GL_MIN"/>
+        <enum value="0x8007" name="GL_MIN_EXT"/>
+        <enum value="0x8008" name="GL_MAX"/>
+        <enum value="0x8008" name="GL_MAX_EXT"/>
+        <enum value="0x8009" name="GL_BLEND_EQUATION"/>
+        <enum value="0x8009" name="GL_BLEND_EQUATION_EXT"/>
+        <enum value="0x8009" name="GL_BLEND_EQUATION_OES"/>
+        <enum value="0x8009" name="GL_BLEND_EQUATION_RGB"/>
+        <enum value="0x8009" name="GL_BLEND_EQUATION_RGB_EXT"/>
+        <enum value="0x8009" name="GL_BLEND_EQUATION_RGB_OES"/>
+        <enum value="0x800A" name="GL_FUNC_SUBTRACT"/>
+        <enum value="0x800A" name="GL_FUNC_SUBTRACT_EXT"/>
+        <enum value="0x800A" name="GL_FUNC_SUBTRACT_OES"/>
+        <enum value="0x800B" name="GL_FUNC_REVERSE_SUBTRACT"/>
+        <enum value="0x800B" name="GL_FUNC_REVERSE_SUBTRACT_EXT"/>
+        <enum value="0x800B" name="GL_FUNC_REVERSE_SUBTRACT_OES"/>
+        <enum value="0x800C" name="GL_CMYK_EXT"/>
+        <enum value="0x800D" name="GL_CMYKA_EXT"/>
+        <enum value="0x800E" name="GL_PACK_CMYK_HINT_EXT"/>
+        <enum value="0x800F" name="GL_UNPACK_CMYK_HINT_EXT"/>
+        <enum value="0x8010" name="GL_CONVOLUTION_1D"/>
+        <enum value="0x8010" name="GL_CONVOLUTION_1D_EXT"/>
+        <enum value="0x8011" name="GL_CONVOLUTION_2D"/>
+        <enum value="0x8011" name="GL_CONVOLUTION_2D_EXT"/>
+        <enum value="0x8012" name="GL_SEPARABLE_2D"/>
+        <enum value="0x8012" name="GL_SEPARABLE_2D_EXT"/>
+        <enum value="0x8013" name="GL_CONVOLUTION_BORDER_MODE"/>
+        <enum value="0x8013" name="GL_CONVOLUTION_BORDER_MODE_EXT"/>
+        <enum value="0x8014" name="GL_CONVOLUTION_FILTER_SCALE"/>
+        <enum value="0x8014" name="GL_CONVOLUTION_FILTER_SCALE_EXT"/>
+        <enum value="0x8015" name="GL_CONVOLUTION_FILTER_BIAS"/>
+        <enum value="0x8015" name="GL_CONVOLUTION_FILTER_BIAS_EXT"/>
+        <enum value="0x8016" name="GL_REDUCE"/>
+        <enum value="0x8016" name="GL_REDUCE_EXT"/>
+        <enum value="0x8017" name="GL_CONVOLUTION_FORMAT"/>
+        <enum value="0x8017" name="GL_CONVOLUTION_FORMAT_EXT"/>
+        <enum value="0x8018" name="GL_CONVOLUTION_WIDTH"/>
+        <enum value="0x8018" name="GL_CONVOLUTION_WIDTH_EXT"/>
+        <enum value="0x8019" name="GL_CONVOLUTION_HEIGHT"/>
+        <enum value="0x8019" name="GL_CONVOLUTION_HEIGHT_EXT"/>
+        <enum value="0x801A" name="GL_MAX_CONVOLUTION_WIDTH"/>
+        <enum value="0x801A" name="GL_MAX_CONVOLUTION_WIDTH_EXT"/>
+        <enum value="0x801B" name="GL_MAX_CONVOLUTION_HEIGHT"/>
+        <enum value="0x801B" name="GL_MAX_CONVOLUTION_HEIGHT_EXT"/>
+        <enum value="0x801C" name="GL_POST_CONVOLUTION_RED_SCALE"/>
+        <enum value="0x801C" name="GL_POST_CONVOLUTION_RED_SCALE_EXT"/>
+        <enum value="0x801D" name="GL_POST_CONVOLUTION_GREEN_SCALE"/>
+        <enum value="0x801D" name="GL_POST_CONVOLUTION_GREEN_SCALE_EXT"/>
+        <enum value="0x801E" name="GL_POST_CONVOLUTION_BLUE_SCALE"/>
+        <enum value="0x801E" name="GL_POST_CONVOLUTION_BLUE_SCALE_EXT"/>
+        <enum value="0x801F" name="GL_POST_CONVOLUTION_ALPHA_SCALE"/>
+        <enum value="0x801F" name="GL_POST_CONVOLUTION_ALPHA_SCALE_EXT"/>
+        <enum value="0x8020" name="GL_POST_CONVOLUTION_RED_BIAS"/>
+        <enum value="0x8020" name="GL_POST_CONVOLUTION_RED_BIAS_EXT"/>
+        <enum value="0x8021" name="GL_POST_CONVOLUTION_GREEN_BIAS"/>
+        <enum value="0x8021" name="GL_POST_CONVOLUTION_GREEN_BIAS_EXT"/>
+        <enum value="0x8022" name="GL_POST_CONVOLUTION_BLUE_BIAS"/>
+        <enum value="0x8022" name="GL_POST_CONVOLUTION_BLUE_BIAS_EXT"/>
+        <enum value="0x8023" name="GL_POST_CONVOLUTION_ALPHA_BIAS"/>
+        <enum value="0x8023" name="GL_POST_CONVOLUTION_ALPHA_BIAS_EXT"/>
+        <enum value="0x8024" name="GL_HISTOGRAM"/>
+        <enum value="0x8024" name="GL_HISTOGRAM_EXT"/>
+        <enum value="0x8025" name="GL_PROXY_HISTOGRAM"/>
+        <enum value="0x8025" name="GL_PROXY_HISTOGRAM_EXT"/>
+        <enum value="0x8026" name="GL_HISTOGRAM_WIDTH"/>
+        <enum value="0x8026" name="GL_HISTOGRAM_WIDTH_EXT"/>
+        <enum value="0x8027" name="GL_HISTOGRAM_FORMAT"/>
+        <enum value="0x8027" name="GL_HISTOGRAM_FORMAT_EXT"/>
+        <enum value="0x8028" name="GL_HISTOGRAM_RED_SIZE"/>
+        <enum value="0x8028" name="GL_HISTOGRAM_RED_SIZE_EXT"/>
+        <enum value="0x8029" name="GL_HISTOGRAM_GREEN_SIZE"/>
+        <enum value="0x8029" name="GL_HISTOGRAM_GREEN_SIZE_EXT"/>
+        <enum value="0x802A" name="GL_HISTOGRAM_BLUE_SIZE"/>
+        <enum value="0x802A" name="GL_HISTOGRAM_BLUE_SIZE_EXT"/>
+        <enum value="0x802B" name="GL_HISTOGRAM_ALPHA_SIZE"/>
+        <enum value="0x802B" name="GL_HISTOGRAM_ALPHA_SIZE_EXT"/>
+        <enum value="0x802C" name="GL_HISTOGRAM_LUMINANCE_SIZE"/>
+        <enum value="0x802C" name="GL_HISTOGRAM_LUMINANCE_SIZE_EXT"/>
+        <enum value="0x802D" name="GL_HISTOGRAM_SINK"/>
+        <enum value="0x802D" name="GL_HISTOGRAM_SINK_EXT"/>
+        <enum value="0x802E" name="GL_MINMAX"/>
+        <enum value="0x802E" name="GL_MINMAX_EXT"/>
+        <enum value="0x802F" name="GL_MINMAX_FORMAT"/>
+        <enum value="0x802F" name="GL_MINMAX_FORMAT_EXT"/>
+        <enum value="0x8030" name="GL_MINMAX_SINK"/>
+        <enum value="0x8030" name="GL_MINMAX_SINK_EXT"/>
+        <enum value="0x8031" name="GL_TABLE_TOO_LARGE_EXT"/>
+        <enum value="0x8031" name="GL_TABLE_TOO_LARGE"/>
+        <enum value="0x8032" name="GL_UNSIGNED_BYTE_3_3_2"/>
+        <enum value="0x8032" name="GL_UNSIGNED_BYTE_3_3_2_EXT"/>
+        <enum value="0x8033" name="GL_UNSIGNED_SHORT_4_4_4_4"/>
+        <enum value="0x8033" name="GL_UNSIGNED_SHORT_4_4_4_4_EXT"/>
+        <enum value="0x8034" name="GL_UNSIGNED_SHORT_5_5_5_1"/>
+        <enum value="0x8034" name="GL_UNSIGNED_SHORT_5_5_5_1_EXT"/>
+        <enum value="0x8035" name="GL_UNSIGNED_INT_8_8_8_8"/>
+        <enum value="0x8035" name="GL_UNSIGNED_INT_8_8_8_8_EXT"/>
+        <enum value="0x8036" name="GL_UNSIGNED_INT_10_10_10_2"/>
+        <enum value="0x8036" name="GL_UNSIGNED_INT_10_10_10_2_EXT"/>
+        <enum value="0x8037" name="GL_POLYGON_OFFSET_EXT"/>
+        <enum value="0x8037" name="GL_POLYGON_OFFSET_FILL"/>
+        <enum value="0x8038" name="GL_POLYGON_OFFSET_FACTOR"/>
+        <enum value="0x8038" name="GL_POLYGON_OFFSET_FACTOR_EXT"/>
+        <enum value="0x8039" name="GL_POLYGON_OFFSET_BIAS_EXT"/>
+        <enum value="0x803A" name="GL_RESCALE_NORMAL"/>
+        <enum value="0x803A" name="GL_RESCALE_NORMAL_EXT"/>
+        <enum value="0x803B" name="GL_ALPHA4"/>
+        <enum value="0x803B" name="GL_ALPHA4_EXT"/>
+        <enum value="0x803C" name="GL_ALPHA8"/>
+        <enum value="0x803C" name="GL_ALPHA8_EXT"/>
+        <enum value="0x803C" name="GL_ALPHA8_OES"/>
+        <enum value="0x803D" name="GL_ALPHA12"/>
+        <enum value="0x803D" name="GL_ALPHA12_EXT"/>
+        <enum value="0x803E" name="GL_ALPHA16"/>
+        <enum value="0x803E" name="GL_ALPHA16_EXT"/>
+        <enum value="0x803F" name="GL_LUMINANCE4"/>
+        <enum value="0x803F" name="GL_LUMINANCE4_EXT"/>
+        <enum value="0x8040" name="GL_LUMINANCE8"/>
+        <enum value="0x8040" name="GL_LUMINANCE8_EXT"/>
+        <enum value="0x8040" name="GL_LUMINANCE8_OES"/>
+        <enum value="0x8041" name="GL_LUMINANCE12"/>
+        <enum value="0x8041" name="GL_LUMINANCE12_EXT"/>
+        <enum value="0x8042" name="GL_LUMINANCE16"/>
+        <enum value="0x8042" name="GL_LUMINANCE16_EXT"/>
+        <enum value="0x8043" name="GL_LUMINANCE4_ALPHA4"/>
+        <enum value="0x8043" name="GL_LUMINANCE4_ALPHA4_EXT"/>
+        <enum value="0x8043" name="GL_LUMINANCE4_ALPHA4_OES"/>
+        <enum value="0x8044" name="GL_LUMINANCE6_ALPHA2"/>
+        <enum value="0x8044" name="GL_LUMINANCE6_ALPHA2_EXT"/>
+        <enum value="0x8045" name="GL_LUMINANCE8_ALPHA8"/>
+        <enum value="0x8045" name="GL_LUMINANCE8_ALPHA8_EXT"/>
+        <enum value="0x8045" name="GL_LUMINANCE8_ALPHA8_OES"/>
+        <enum value="0x8046" name="GL_LUMINANCE12_ALPHA4"/>
+        <enum value="0x8046" name="GL_LUMINANCE12_ALPHA4_EXT"/>
+        <enum value="0x8047" name="GL_LUMINANCE12_ALPHA12"/>
+        <enum value="0x8047" name="GL_LUMINANCE12_ALPHA12_EXT"/>
+        <enum value="0x8048" name="GL_LUMINANCE16_ALPHA16"/>
+        <enum value="0x8048" name="GL_LUMINANCE16_ALPHA16_EXT"/>
+        <enum value="0x8049" name="GL_INTENSITY"/>
+        <enum value="0x8049" name="GL_INTENSITY_EXT"/>
+        <enum value="0x804A" name="GL_INTENSITY4"/>
+        <enum value="0x804A" name="GL_INTENSITY4_EXT"/>
+        <enum value="0x804B" name="GL_INTENSITY8"/>
+        <enum value="0x804B" name="GL_INTENSITY8_EXT"/>
+        <enum value="0x804C" name="GL_INTENSITY12"/>
+        <enum value="0x804C" name="GL_INTENSITY12_EXT"/>
+        <enum value="0x804D" name="GL_INTENSITY16"/>
+        <enum value="0x804D" name="GL_INTENSITY16_EXT"/>
+        <enum value="0x804E" name="GL_RGB2_EXT"/>
+        <enum value="0x804F" name="GL_RGB4"/>
+        <enum value="0x804F" name="GL_RGB4_EXT"/>
+        <enum value="0x8050" name="GL_RGB5"/>
+        <enum value="0x8050" name="GL_RGB5_EXT"/>
+        <enum value="0x8051" name="GL_RGB8"/>
+        <enum value="0x8051" name="GL_RGB8_EXT"/>
+        <enum value="0x8051" name="GL_RGB8_OES"/>
+        <enum value="0x8052" name="GL_RGB10"/>
+        <enum value="0x8052" name="GL_RGB10_EXT"/>
+        <enum value="0x8053" name="GL_RGB12"/>
+        <enum value="0x8053" name="GL_RGB12_EXT"/>
+        <enum value="0x8054" name="GL_RGB16"/>
+        <enum value="0x8054" name="GL_RGB16_EXT"/>
+        <enum value="0x8055" name="GL_RGBA2"/>
+        <enum value="0x8055" name="GL_RGBA2_EXT"/>
+        <enum value="0x8056" name="GL_RGBA4"/>
+        <enum value="0x8056" name="GL_RGBA4_EXT"/>
+        <enum value="0x8056" name="GL_RGBA4_OES"/>
+        <enum value="0x8057" name="GL_RGB5_A1"/>
+        <enum value="0x8057" name="GL_RGB5_A1_EXT"/>
+        <enum value="0x8057" name="GL_RGB5_A1_OES"/>
+        <enum value="0x8058" name="GL_RGBA8"/>
+        <enum value="0x8058" name="GL_RGBA8_EXT"/>
+        <enum value="0x8058" name="GL_RGBA8_OES"/>
+        <enum value="0x8059" name="GL_RGB10_A2"/>
+        <enum value="0x8059" name="GL_RGB10_A2_EXT"/>
+        <enum value="0x805A" name="GL_RGBA12"/>
+        <enum value="0x805A" name="GL_RGBA12_EXT"/>
+        <enum value="0x805B" name="GL_RGBA16"/>
+        <enum value="0x805B" name="GL_RGBA16_EXT"/>
+        <enum value="0x805C" name="GL_TEXTURE_RED_SIZE"/>
+        <enum value="0x805C" name="GL_TEXTURE_RED_SIZE_EXT"/>
+        <enum value="0x805D" name="GL_TEXTURE_GREEN_SIZE"/>
+        <enum value="0x805D" name="GL_TEXTURE_GREEN_SIZE_EXT"/>
+        <enum value="0x805E" name="GL_TEXTURE_BLUE_SIZE"/>
+        <enum value="0x805E" name="GL_TEXTURE_BLUE_SIZE_EXT"/>
+        <enum value="0x805F" name="GL_TEXTURE_ALPHA_SIZE"/>
+        <enum value="0x805F" name="GL_TEXTURE_ALPHA_SIZE_EXT"/>
+        <enum value="0x8060" name="GL_TEXTURE_LUMINANCE_SIZE"/>
+        <enum value="0x8060" name="GL_TEXTURE_LUMINANCE_SIZE_EXT"/>
+        <enum value="0x8061" name="GL_TEXTURE_INTENSITY_SIZE"/>
+        <enum value="0x8061" name="GL_TEXTURE_INTENSITY_SIZE_EXT"/>
+        <enum value="0x8062" name="GL_REPLACE_EXT"/>
+        <enum value="0x8063" name="GL_PROXY_TEXTURE_1D"/>
+        <enum value="0x8063" name="GL_PROXY_TEXTURE_1D_EXT"/>
+        <enum value="0x8064" name="GL_PROXY_TEXTURE_2D"/>
+        <enum value="0x8064" name="GL_PROXY_TEXTURE_2D_EXT"/>
+        <enum value="0x8065" name="GL_TEXTURE_TOO_LARGE_EXT"/>
+        <enum value="0x8066" name="GL_TEXTURE_PRIORITY"/>
+        <enum value="0x8066" name="GL_TEXTURE_PRIORITY_EXT"/>
+        <enum value="0x8067" name="GL_TEXTURE_RESIDENT"/>
+        <enum value="0x8067" name="GL_TEXTURE_RESIDENT_EXT"/>
+        <enum value="0x8068" name="GL_TEXTURE_1D_BINDING_EXT"/>
+        <enum value="0x8068" name="GL_TEXTURE_BINDING_1D"/>
+        <enum value="0x8069" name="GL_TEXTURE_2D_BINDING_EXT"/>
+        <enum value="0x8069" name="GL_TEXTURE_BINDING_2D"/>
+        <enum value="0x806A" name="GL_TEXTURE_3D_BINDING_EXT"/>
+        <enum value="0x806A" name="GL_TEXTURE_3D_BINDING_OES"/>
+        <enum value="0x806A" name="GL_TEXTURE_BINDING_3D"/>
+        <enum value="0x806A" name="GL_TEXTURE_BINDING_3D_OES"/>
+        <enum value="0x806B" name="GL_PACK_SKIP_IMAGES"/>
+        <enum value="0x806B" name="GL_PACK_SKIP_IMAGES_EXT"/>
+        <enum value="0x806C" name="GL_PACK_IMAGE_HEIGHT"/>
+        <enum value="0x806C" name="GL_PACK_IMAGE_HEIGHT_EXT"/>
+        <enum value="0x806D" name="GL_UNPACK_SKIP_IMAGES"/>
+        <enum value="0x806D" name="GL_UNPACK_SKIP_IMAGES_EXT"/>
+        <enum value="0x806E" name="GL_UNPACK_IMAGE_HEIGHT"/>
+        <enum value="0x806E" name="GL_UNPACK_IMAGE_HEIGHT_EXT"/>
+        <enum value="0x806F" name="GL_TEXTURE_3D"/>
+        <enum value="0x806F" name="GL_TEXTURE_3D_EXT"/>
+        <enum value="0x806F" name="GL_TEXTURE_3D_OES"/>
+        <enum value="0x8070" name="GL_PROXY_TEXTURE_3D"/>
+        <enum value="0x8070" name="GL_PROXY_TEXTURE_3D_EXT"/>
+        <enum value="0x8071" name="GL_TEXTURE_DEPTH"/>
+        <enum value="0x8071" name="GL_TEXTURE_DEPTH_EXT"/>
+        <enum value="0x8072" name="GL_TEXTURE_WRAP_R"/>
+        <enum value="0x8072" name="GL_TEXTURE_WRAP_R_EXT"/>
+        <enum value="0x8072" name="GL_TEXTURE_WRAP_R_OES"/>
+        <enum value="0x8073" name="GL_MAX_3D_TEXTURE_SIZE"/>
+        <enum value="0x8073" name="GL_MAX_3D_TEXTURE_SIZE_EXT"/>
+        <enum value="0x8073" name="GL_MAX_3D_TEXTURE_SIZE_OES"/>
+        <enum value="0x8074" name="GL_VERTEX_ARRAY"/>
+        <enum value="0x8074" name="GL_VERTEX_ARRAY_EXT"/>
+        <enum value="0x8074" name="GL_VERTEX_ARRAY_KHR"/>
+        <enum value="0x8075" name="GL_NORMAL_ARRAY"/>
+        <enum value="0x8075" name="GL_NORMAL_ARRAY_EXT"/>
+        <enum value="0x8076" name="GL_COLOR_ARRAY"/>
+        <enum value="0x8076" name="GL_COLOR_ARRAY_EXT"/>
+        <enum value="0x8077" name="GL_INDEX_ARRAY"/>
+        <enum value="0x8077" name="GL_INDEX_ARRAY_EXT"/>
+        <enum value="0x8078" name="GL_TEXTURE_COORD_ARRAY"/>
+        <enum value="0x8078" name="GL_TEXTURE_COORD_ARRAY_EXT"/>
+        <enum value="0x8079" name="GL_EDGE_FLAG_ARRAY"/>
+        <enum value="0x8079" name="GL_EDGE_FLAG_ARRAY_EXT"/>
+        <enum value="0x807A" name="GL_VERTEX_ARRAY_SIZE"/>
+        <enum value="0x807A" name="GL_VERTEX_ARRAY_SIZE_EXT"/>
+        <enum value="0x807B" name="GL_VERTEX_ARRAY_TYPE"/>
+        <enum value="0x807B" name="GL_VERTEX_ARRAY_TYPE_EXT"/>
+        <enum value="0x807C" name="GL_VERTEX_ARRAY_STRIDE"/>
+        <enum value="0x807C" name="GL_VERTEX_ARRAY_STRIDE_EXT"/>
+        <enum value="0x807D" name="GL_VERTEX_ARRAY_COUNT_EXT"/>
+        <enum value="0x807E" name="GL_NORMAL_ARRAY_TYPE"/>
+        <enum value="0x807E" name="GL_NORMAL_ARRAY_TYPE_EXT"/>
+        <enum value="0x807F" name="GL_NORMAL_ARRAY_STRIDE"/>
+        <enum value="0x807F" name="GL_NORMAL_ARRAY_STRIDE_EXT"/>
+        <enum value="0x8080" name="GL_NORMAL_ARRAY_COUNT_EXT"/>
+        <enum value="0x8081" name="GL_COLOR_ARRAY_SIZE"/>
+        <enum value="0x8081" name="GL_COLOR_ARRAY_SIZE_EXT"/>
+        <enum value="0x8082" name="GL_COLOR_ARRAY_TYPE"/>
+        <enum value="0x8082" name="GL_COLOR_ARRAY_TYPE_EXT"/>
+        <enum value="0x8083" name="GL_COLOR_ARRAY_STRIDE"/>
+        <enum value="0x8083" name="GL_COLOR_ARRAY_STRIDE_EXT"/>
+        <enum value="0x8084" name="GL_COLOR_ARRAY_COUNT_EXT"/>
+        <enum value="0x8085" name="GL_INDEX_ARRAY_TYPE"/>
+        <enum value="0x8085" name="GL_INDEX_ARRAY_TYPE_EXT"/>
+        <enum value="0x8086" name="GL_INDEX_ARRAY_STRIDE"/>
+        <enum value="0x8086" name="GL_INDEX_ARRAY_STRIDE_EXT"/>
+        <enum value="0x8087" name="GL_INDEX_ARRAY_COUNT_EXT"/>
+        <enum value="0x8088" name="GL_TEXTURE_COORD_ARRAY_SIZE"/>
+        <enum value="0x8088" name="GL_TEXTURE_COORD_ARRAY_SIZE_EXT"/>
+        <enum value="0x8089" name="GL_TEXTURE_COORD_ARRAY_TYPE"/>
+        <enum value="0x8089" name="GL_TEXTURE_COORD_ARRAY_TYPE_EXT"/>
+        <enum value="0x808A" name="GL_TEXTURE_COORD_ARRAY_STRIDE"/>
+        <enum value="0x808A" name="GL_TEXTURE_COORD_ARRAY_STRIDE_EXT"/>
+        <enum value="0x808B" name="GL_TEXTURE_COORD_ARRAY_COUNT_EXT"/>
+        <enum value="0x808C" name="GL_EDGE_FLAG_ARRAY_STRIDE"/>
+        <enum value="0x808C" name="GL_EDGE_FLAG_ARRAY_STRIDE_EXT"/>
+        <enum value="0x808D" name="GL_EDGE_FLAG_ARRAY_COUNT_EXT"/>
+        <enum value="0x808E" name="GL_VERTEX_ARRAY_POINTER"/>
+        <enum value="0x808E" name="GL_VERTEX_ARRAY_POINTER_EXT"/>
+        <enum value="0x808F" name="GL_NORMAL_ARRAY_POINTER"/>
+        <enum value="0x808F" name="GL_NORMAL_ARRAY_POINTER_EXT"/>
+        <enum value="0x8090" name="GL_COLOR_ARRAY_POINTER"/>
+        <enum value="0x8090" name="GL_COLOR_ARRAY_POINTER_EXT"/>
+        <enum value="0x8091" name="GL_INDEX_ARRAY_POINTER"/>
+        <enum value="0x8091" name="GL_INDEX_ARRAY_POINTER_EXT"/>
+        <enum value="0x8092" name="GL_TEXTURE_COORD_ARRAY_POINTER"/>
+        <enum value="0x8092" name="GL_TEXTURE_COORD_ARRAY_POINTER_EXT"/>
+        <enum value="0x8093" name="GL_EDGE_FLAG_ARRAY_POINTER"/>
+        <enum value="0x8093" name="GL_EDGE_FLAG_ARRAY_POINTER_EXT"/>
+        <enum value="0x8094" name="GL_INTERLACE_SGIX"/>
+        <enum value="0x8095" name="GL_DETAIL_TEXTURE_2D_SGIS"/>
+        <enum value="0x8096" name="GL_DETAIL_TEXTURE_2D_BINDING_SGIS"/>
+        <enum value="0x8097" name="GL_LINEAR_DETAIL_SGIS"/>
+        <enum value="0x8098" name="GL_LINEAR_DETAIL_ALPHA_SGIS"/>
+        <enum value="0x8099" name="GL_LINEAR_DETAIL_COLOR_SGIS"/>
+        <enum value="0x809A" name="GL_DETAIL_TEXTURE_LEVEL_SGIS"/>
+        <enum value="0x809B" name="GL_DETAIL_TEXTURE_MODE_SGIS"/>
+        <enum value="0x809C" name="GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS"/>
+        <enum value="0x809D" name="GL_MULTISAMPLE"/>
+        <enum value="0x809D" name="GL_MULTISAMPLE_ARB"/>
+        <enum value="0x809D" name="GL_MULTISAMPLE_EXT"/>
+        <enum value="0x809D" name="GL_MULTISAMPLE_SGIS"/>
+        <enum value="0x809E" name="GL_SAMPLE_ALPHA_TO_COVERAGE"/>
+        <enum value="0x809E" name="GL_SAMPLE_ALPHA_TO_COVERAGE_ARB"/>
+        <enum value="0x809E" name="GL_SAMPLE_ALPHA_TO_MASK_EXT"/>
+        <enum value="0x809E" name="GL_SAMPLE_ALPHA_TO_MASK_SGIS"/>
+        <enum value="0x809F" name="GL_SAMPLE_ALPHA_TO_ONE"/>
+        <enum value="0x809F" name="GL_SAMPLE_ALPHA_TO_ONE_ARB"/>
+        <enum value="0x809F" name="GL_SAMPLE_ALPHA_TO_ONE_EXT"/>
+        <enum value="0x809F" name="GL_SAMPLE_ALPHA_TO_ONE_SGIS"/>
+        <enum value="0x80A0" name="GL_SAMPLE_COVERAGE"/>
+        <enum value="0x80A0" name="GL_SAMPLE_COVERAGE_ARB"/>
+        <enum value="0x80A0" name="GL_SAMPLE_MASK_EXT"/>
+        <enum value="0x80A0" name="GL_SAMPLE_MASK_SGIS"/>
+        <enum value="0x80A1" name="GL_1PASS_EXT"/>
+        <enum value="0x80A1" name="GL_1PASS_SGIS"/>
+        <enum value="0x80A2" name="GL_2PASS_0_EXT"/>
+        <enum value="0x80A2" name="GL_2PASS_0_SGIS"/>
+        <enum value="0x80A3" name="GL_2PASS_1_EXT"/>
+        <enum value="0x80A3" name="GL_2PASS_1_SGIS"/>
+        <enum value="0x80A4" name="GL_4PASS_0_EXT"/>
+        <enum value="0x80A4" name="GL_4PASS_0_SGIS"/>
+        <enum value="0x80A5" name="GL_4PASS_1_EXT"/>
+        <enum value="0x80A5" name="GL_4PASS_1_SGIS"/>
+        <enum value="0x80A6" name="GL_4PASS_2_EXT"/>
+        <enum value="0x80A6" name="GL_4PASS_2_SGIS"/>
+        <enum value="0x80A7" name="GL_4PASS_3_EXT"/>
+        <enum value="0x80A7" name="GL_4PASS_3_SGIS"/>
+        <enum value="0x80A8" name="GL_SAMPLE_BUFFERS"/>
+        <enum value="0x80A8" name="GL_SAMPLE_BUFFERS_ARB"/>
+        <enum value="0x80A8" name="GL_SAMPLE_BUFFERS_EXT"/>
+        <enum value="0x80A8" name="GL_SAMPLE_BUFFERS_SGIS"/>
+        <enum value="0x80A9" name="GL_SAMPLES"/>
+        <enum value="0x80A9" name="GL_SAMPLES_ARB"/>
+        <enum value="0x80A9" name="GL_SAMPLES_EXT"/>
+        <enum value="0x80A9" name="GL_SAMPLES_SGIS"/>
+        <enum value="0x80AA" name="GL_SAMPLE_COVERAGE_VALUE"/>
+        <enum value="0x80AA" name="GL_SAMPLE_COVERAGE_VALUE_ARB"/>
+        <enum value="0x80AA" name="GL_SAMPLE_MASK_VALUE_EXT"/>
+        <enum value="0x80AA" name="GL_SAMPLE_MASK_VALUE_SGIS"/>
+        <enum value="0x80AB" name="GL_SAMPLE_COVERAGE_INVERT"/>
+        <enum value="0x80AB" name="GL_SAMPLE_COVERAGE_INVERT_ARB"/>
+        <enum value="0x80AB" name="GL_SAMPLE_MASK_INVERT_EXT"/>
+        <enum value="0x80AB" name="GL_SAMPLE_MASK_INVERT_SGIS"/>
+        <enum value="0x80AC" name="GL_SAMPLE_PATTERN_EXT"/>
+        <enum value="0x80AC" name="GL_SAMPLE_PATTERN_SGIS"/>
+        <enum value="0x80AD" name="GL_LINEAR_SHARPEN_SGIS"/>
+        <enum value="0x80AE" name="GL_LINEAR_SHARPEN_ALPHA_SGIS"/>
+        <enum value="0x80AF" name="GL_LINEAR_SHARPEN_COLOR_SGIS"/>
+        <enum value="0x80B0" name="GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS"/>
+        <enum value="0x80B1" name="GL_COLOR_MATRIX"/>
+        <enum value="0x80B1" name="GL_COLOR_MATRIX_SGI"/>
+        <enum value="0x80B2" name="GL_COLOR_MATRIX_STACK_DEPTH"/>
+        <enum value="0x80B2" name="GL_COLOR_MATRIX_STACK_DEPTH_SGI"/>
+        <enum value="0x80B3" name="GL_MAX_COLOR_MATRIX_STACK_DEPTH"/>
+        <enum value="0x80B3" name="GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI"/>
+        <enum value="0x80B4" name="GL_POST_COLOR_MATRIX_RED_SCALE"/>
+        <enum value="0x80B4" name="GL_POST_COLOR_MATRIX_RED_SCALE_SGI"/>
+        <enum value="0x80B5" name="GL_POST_COLOR_MATRIX_GREEN_SCALE"/>
+        <enum value="0x80B5" name="GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI"/>
+        <enum value="0x80B6" name="GL_POST_COLOR_MATRIX_BLUE_SCALE"/>
+        <enum value="0x80B6" name="GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI"/>
+        <enum value="0x80B7" name="GL_POST_COLOR_MATRIX_ALPHA_SCALE"/>
+        <enum value="0x80B7" name="GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI"/>
+        <enum value="0x80B8" name="GL_POST_COLOR_MATRIX_RED_BIAS"/>
+        <enum value="0x80B8" name="GL_POST_COLOR_MATRIX_RED_BIAS_SGI"/>
+        <enum value="0x80B9" name="GL_POST_COLOR_MATRIX_GREEN_BIAS"/>
+        <enum value="0x80B9" name="GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI"/>
+        <enum value="0x80BA" name="GL_POST_COLOR_MATRIX_BLUE_BIAS"/>
+        <enum value="0x80BA" name="GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI"/>
+        <enum value="0x80BB" name="GL_POST_COLOR_MATRIX_ALPHA_BIAS"/>
+        <enum value="0x80BB" name="GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI"/>
+        <enum value="0x80BC" name="GL_TEXTURE_COLOR_TABLE_SGI"/>
+        <enum value="0x80BD" name="GL_PROXY_TEXTURE_COLOR_TABLE_SGI"/>
+        <enum value="0x80BE" name="GL_TEXTURE_ENV_BIAS_SGIX"/>
+        <enum value="0x80BF" name="GL_SHADOW_AMBIENT_SGIX"/>
+        <enum value="0x80BF" name="GL_TEXTURE_COMPARE_FAIL_VALUE_ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x80C0" end="0x80CF" vendor="ZiiLabs">
+            <unused start="0x80C0" end="0x80C7" vendor="ZiiLabs"/>
+        <enum value="0x80C8" name="GL_BLEND_DST_RGB"/>
+        <enum value="0x80C8" name="GL_BLEND_DST_RGB_EXT"/>
+        <enum value="0x80C8" name="GL_BLEND_DST_RGB_OES"/>
+        <enum value="0x80C9" name="GL_BLEND_SRC_RGB"/>
+        <enum value="0x80C9" name="GL_BLEND_SRC_RGB_EXT"/>
+        <enum value="0x80C9" name="GL_BLEND_SRC_RGB_OES"/>
+        <enum value="0x80CA" name="GL_BLEND_DST_ALPHA"/>
+        <enum value="0x80CA" name="GL_BLEND_DST_ALPHA_EXT"/>
+        <enum value="0x80CA" name="GL_BLEND_DST_ALPHA_OES"/>
+        <enum value="0x80CB" name="GL_BLEND_SRC_ALPHA"/>
+        <enum value="0x80CB" name="GL_BLEND_SRC_ALPHA_EXT"/>
+        <enum value="0x80CB" name="GL_BLEND_SRC_ALPHA_OES"/>
+        <enum value="0x80CC" name="GL_422_EXT"/>
+        <enum value="0x80CD" name="GL_422_REV_EXT"/>
+        <enum value="0x80CE" name="GL_422_AVERAGE_EXT"/>
+        <enum value="0x80CF" name="GL_422_REV_AVERAGE_EXT"/>
+    </enums>
+
+    <enums namespace="GL" start="0x80D0" end="0x80DF" vendor="SGI">
+        <enum value="0x80D0" name="GL_COLOR_TABLE"/>
+        <enum value="0x80D0" name="GL_COLOR_TABLE_SGI"/>
+        <enum value="0x80D1" name="GL_POST_CONVOLUTION_COLOR_TABLE"/>
+        <enum value="0x80D1" name="GL_POST_CONVOLUTION_COLOR_TABLE_SGI"/>
+        <enum value="0x80D2" name="GL_POST_COLOR_MATRIX_COLOR_TABLE"/>
+        <enum value="0x80D2" name="GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI"/>
+        <enum value="0x80D3" name="GL_PROXY_COLOR_TABLE"/>
+        <enum value="0x80D3" name="GL_PROXY_COLOR_TABLE_SGI"/>
+        <enum value="0x80D4" name="GL_PROXY_POST_CONVOLUTION_COLOR_TABLE"/>
+        <enum value="0x80D4" name="GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI"/>
+        <enum value="0x80D5" name="GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE"/>
+        <enum value="0x80D5" name="GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI"/>
+        <enum value="0x80D6" name="GL_COLOR_TABLE_SCALE"/>
+        <enum value="0x80D6" name="GL_COLOR_TABLE_SCALE_SGI"/>
+        <enum value="0x80D7" name="GL_COLOR_TABLE_BIAS"/>
+        <enum value="0x80D7" name="GL_COLOR_TABLE_BIAS_SGI"/>
+        <enum value="0x80D8" name="GL_COLOR_TABLE_FORMAT"/>
+        <enum value="0x80D8" name="GL_COLOR_TABLE_FORMAT_SGI"/>
+        <enum value="0x80D9" name="GL_COLOR_TABLE_WIDTH"/>
+        <enum value="0x80D9" name="GL_COLOR_TABLE_WIDTH_SGI"/>
+        <enum value="0x80DA" name="GL_COLOR_TABLE_RED_SIZE"/>
+        <enum value="0x80DA" name="GL_COLOR_TABLE_RED_SIZE_SGI"/>
+        <enum value="0x80DB" name="GL_COLOR_TABLE_GREEN_SIZE"/>
+        <enum value="0x80DB" name="GL_COLOR_TABLE_GREEN_SIZE_SGI"/>
+        <enum value="0x80DC" name="GL_COLOR_TABLE_BLUE_SIZE"/>
+        <enum value="0x80DC" name="GL_COLOR_TABLE_BLUE_SIZE_SGI"/>
+        <enum value="0x80DD" name="GL_COLOR_TABLE_ALPHA_SIZE"/>
+        <enum value="0x80DD" name="GL_COLOR_TABLE_ALPHA_SIZE_SGI"/>
+        <enum value="0x80DE" name="GL_COLOR_TABLE_LUMINANCE_SIZE"/>
+        <enum value="0x80DE" name="GL_COLOR_TABLE_LUMINANCE_SIZE_SGI"/>
+        <enum value="0x80DF" name="GL_COLOR_TABLE_INTENSITY_SIZE"/>
+        <enum value="0x80DF" name="GL_COLOR_TABLE_INTENSITY_SIZE_SGI"/>
+    </enums>
+
+    <enums namespace="GL" start="0x80E0" end="0x810F" vendor="MS">
+        <enum value="0x80E0" name="GL_BGR"/>
+        <enum value="0x80E0" name="GL_BGR_EXT"/>
+        <enum value="0x80E1" name="GL_BGRA"/>
+        <enum value="0x80E1" name="GL_BGRA_EXT"/>
+        <enum value="0x80E1" name="GL_BGRA_IMG"/>
+        <enum value="0x80E2" name="GL_COLOR_INDEX1_EXT"/>
+        <enum value="0x80E3" name="GL_COLOR_INDEX2_EXT"/>
+        <enum value="0x80E4" name="GL_COLOR_INDEX4_EXT"/>
+        <enum value="0x80E5" name="GL_COLOR_INDEX8_EXT"/>
+        <enum value="0x80E6" name="GL_COLOR_INDEX12_EXT"/>
+        <enum value="0x80E7" name="GL_COLOR_INDEX16_EXT"/>
+        <enum value="0x80E8" name="GL_MAX_ELEMENTS_VERTICES"/>
+        <enum value="0x80E8" name="GL_MAX_ELEMENTS_VERTICES_EXT"/>
+        <enum value="0x80E9" name="GL_MAX_ELEMENTS_INDICES"/>
+        <enum value="0x80E9" name="GL_MAX_ELEMENTS_INDICES_EXT"/>
+        <enum value="0x80EA" name="GL_PHONG_WIN"/>
+        <enum value="0x80EB" name="GL_PHONG_HINT_WIN"/>
+        <enum value="0x80EC" name="GL_FOG_SPECULAR_TEXTURE_WIN"/>
+        <enum value="0x80ED" name="GL_TEXTURE_INDEX_SIZE_EXT"/>
+        <enum value="0x80EE" name="GL_PARAMETER_BUFFER_ARB"/>
+        <enum value="0x80EF" name="GL_PARAMETER_BUFFER_BINDING_ARB"/>
+        <enum value="0x80F0" name="GL_CLIP_VOLUME_CLIPPING_HINT_EXT"/>
+            <unused start="0x80F1" end="0x810F" vendor="MS"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8110" end="0x814F" vendor="SGI">
+        <enum value="0x8110" name="GL_DUAL_ALPHA4_SGIS"/>
+        <enum value="0x8111" name="GL_DUAL_ALPHA8_SGIS"/>
+        <enum value="0x8112" name="GL_DUAL_ALPHA12_SGIS"/>
+        <enum value="0x8113" name="GL_DUAL_ALPHA16_SGIS"/>
+        <enum value="0x8114" name="GL_DUAL_LUMINANCE4_SGIS"/>
+        <enum value="0x8115" name="GL_DUAL_LUMINANCE8_SGIS"/>
+        <enum value="0x8116" name="GL_DUAL_LUMINANCE12_SGIS"/>
+        <enum value="0x8117" name="GL_DUAL_LUMINANCE16_SGIS"/>
+        <enum value="0x8118" name="GL_DUAL_INTENSITY4_SGIS"/>
+        <enum value="0x8119" name="GL_DUAL_INTENSITY8_SGIS"/>
+        <enum value="0x811A" name="GL_DUAL_INTENSITY12_SGIS"/>
+        <enum value="0x811B" name="GL_DUAL_INTENSITY16_SGIS"/>
+        <enum value="0x811C" name="GL_DUAL_LUMINANCE_ALPHA4_SGIS"/>
+        <enum value="0x811D" name="GL_DUAL_LUMINANCE_ALPHA8_SGIS"/>
+        <enum value="0x811E" name="GL_QUAD_ALPHA4_SGIS"/>
+        <enum value="0x811F" name="GL_QUAD_ALPHA8_SGIS"/>
+        <enum value="0x8120" name="GL_QUAD_LUMINANCE4_SGIS"/>
+        <enum value="0x8121" name="GL_QUAD_LUMINANCE8_SGIS"/>
+        <enum value="0x8122" name="GL_QUAD_INTENSITY4_SGIS"/>
+        <enum value="0x8123" name="GL_QUAD_INTENSITY8_SGIS"/>
+        <enum value="0x8124" name="GL_DUAL_TEXTURE_SELECT_SGIS"/>
+        <enum value="0x8125" name="GL_QUAD_TEXTURE_SELECT_SGIS"/>
+        <enum value="0x8126" name="GL_POINT_SIZE_MIN"/>
+        <enum value="0x8126" name="GL_POINT_SIZE_MIN_ARB"/>
+        <enum value="0x8126" name="GL_POINT_SIZE_MIN_EXT"/>
+        <enum value="0x8126" name="GL_POINT_SIZE_MIN_SGIS"/>
+        <enum value="0x8127" name="GL_POINT_SIZE_MAX"/>
+        <enum value="0x8127" name="GL_POINT_SIZE_MAX_ARB"/>
+        <enum value="0x8127" name="GL_POINT_SIZE_MAX_EXT"/>
+        <enum value="0x8127" name="GL_POINT_SIZE_MAX_SGIS"/>
+        <enum value="0x8128" name="GL_POINT_FADE_THRESHOLD_SIZE"/>
+        <enum value="0x8128" name="GL_POINT_FADE_THRESHOLD_SIZE_ARB"/>
+        <enum value="0x8128" name="GL_POINT_FADE_THRESHOLD_SIZE_EXT"/>
+        <enum value="0x8128" name="GL_POINT_FADE_THRESHOLD_SIZE_SGIS"/>
+        <enum value="0x8129" name="GL_DISTANCE_ATTENUATION_EXT"/>
+        <enum value="0x8129" name="GL_DISTANCE_ATTENUATION_SGIS"/>
+        <enum value="0x8129" name="GL_POINT_DISTANCE_ATTENUATION"/>
+        <enum value="0x8129" name="GL_POINT_DISTANCE_ATTENUATION_ARB"/>
+        <enum value="0x812A" name="GL_FOG_FUNC_SGIS"/>
+        <enum value="0x812B" name="GL_FOG_FUNC_POINTS_SGIS"/>
+        <enum value="0x812C" name="GL_MAX_FOG_FUNC_POINTS_SGIS"/>
+        <enum value="0x812D" name="GL_CLAMP_TO_BORDER"/>
+        <enum value="0x812D" name="GL_CLAMP_TO_BORDER_ARB"/>
+        <enum value="0x812D" name="GL_CLAMP_TO_BORDER_EXT"/>
+        <enum value="0x812D" name="GL_CLAMP_TO_BORDER_NV"/>
+        <enum value="0x812D" name="GL_CLAMP_TO_BORDER_SGIS"/>
+        <enum value="0x812D" name="GL_CLAMP_TO_BORDER_OES"/>
+        <enum value="0x812E" name="GL_TEXTURE_MULTI_BUFFER_HINT_SGIX"/>
+        <enum value="0x812F" name="GL_CLAMP_TO_EDGE"/>
+        <enum value="0x812F" name="GL_CLAMP_TO_EDGE_SGIS"/>
+        <enum value="0x8130" name="GL_PACK_SKIP_VOLUMES_SGIS"/>
+        <enum value="0x8131" name="GL_PACK_IMAGE_DEPTH_SGIS"/>
+        <enum value="0x8132" name="GL_UNPACK_SKIP_VOLUMES_SGIS"/>
+        <enum value="0x8133" name="GL_UNPACK_IMAGE_DEPTH_SGIS"/>
+        <enum value="0x8134" name="GL_TEXTURE_4D_SGIS"/>
+        <enum value="0x8135" name="GL_PROXY_TEXTURE_4D_SGIS"/>
+        <enum value="0x8136" name="GL_TEXTURE_4DSIZE_SGIS"/>
+        <enum value="0x8137" name="GL_TEXTURE_WRAP_Q_SGIS"/>
+        <enum value="0x8138" name="GL_MAX_4D_TEXTURE_SIZE_SGIS"/>
+        <enum value="0x8139" name="GL_PIXEL_TEX_GEN_SGIX"/>
+        <enum value="0x813A" name="GL_TEXTURE_MIN_LOD"/>
+        <enum value="0x813A" name="GL_TEXTURE_MIN_LOD_SGIS"/>
+        <enum value="0x813B" name="GL_TEXTURE_MAX_LOD"/>
+        <enum value="0x813B" name="GL_TEXTURE_MAX_LOD_SGIS"/>
+        <enum value="0x813C" name="GL_TEXTURE_BASE_LEVEL"/>
+        <enum value="0x813C" name="GL_TEXTURE_BASE_LEVEL_SGIS"/>
+        <enum value="0x813D" name="GL_TEXTURE_MAX_LEVEL"/>
+        <enum value="0x813D" name="GL_TEXTURE_MAX_LEVEL_APPLE"/>
+        <enum value="0x813D" name="GL_TEXTURE_MAX_LEVEL_SGIS"/>
+        <enum value="0x813E" name="GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX"/>
+        <enum value="0x813F" name="GL_PIXEL_TILE_CACHE_INCREMENT_SGIX"/>
+        <enum value="0x8140" name="GL_PIXEL_TILE_WIDTH_SGIX"/>
+        <enum value="0x8141" name="GL_PIXEL_TILE_HEIGHT_SGIX"/>
+        <enum value="0x8142" name="GL_PIXEL_TILE_GRID_WIDTH_SGIX"/>
+        <enum value="0x8143" name="GL_PIXEL_TILE_GRID_HEIGHT_SGIX"/>
+        <enum value="0x8144" name="GL_PIXEL_TILE_GRID_DEPTH_SGIX"/>
+        <enum value="0x8145" name="GL_PIXEL_TILE_CACHE_SIZE_SGIX"/>
+        <enum value="0x8146" name="GL_FILTER4_SGIS"/>
+        <enum value="0x8147" name="GL_TEXTURE_FILTER4_SIZE_SGIS"/>
+        <enum value="0x8148" name="GL_SPRITE_SGIX"/>
+        <enum value="0x8149" name="GL_SPRITE_MODE_SGIX"/>
+        <enum value="0x814A" name="GL_SPRITE_AXIS_SGIX"/>
+        <enum value="0x814B" name="GL_SPRITE_TRANSLATION_SGIX"/>
+        <enum value="0x814C" name="GL_SPRITE_AXIAL_SGIX"/>
+        <enum value="0x814D" name="GL_SPRITE_OBJECT_ALIGNED_SGIX"/>
+        <enum value="0x814E" name="GL_SPRITE_EYE_ALIGNED_SGIX"/>
+        <enum value="0x814F" name="GL_TEXTURE_4D_BINDING_SGIS"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8150" end="0x816F" vendor="HP">
+        <enum value="0x8150" name="GL_IGNORE_BORDER_HP"/>
+        <enum value="0x8151" name="GL_CONSTANT_BORDER"/>
+        <enum value="0x8151" name="GL_CONSTANT_BORDER_HP"/>
+            <unused start="0x8152" vendor="HP" comment="GL_WRAP_BORDER = 0x8152 was proposed, but not actually promoted to core"/>
+        <enum value="0x8153" name="GL_REPLICATE_BORDER"/>
+        <enum value="0x8153" name="GL_REPLICATE_BORDER_HP"/>
+        <enum value="0x8154" name="GL_CONVOLUTION_BORDER_COLOR"/>
+        <enum value="0x8154" name="GL_CONVOLUTION_BORDER_COLOR_HP"/>
+        <enum value="0x8155" name="GL_IMAGE_SCALE_X_HP"/>
+        <enum value="0x8156" name="GL_IMAGE_SCALE_Y_HP"/>
+        <enum value="0x8157" name="GL_IMAGE_TRANSLATE_X_HP"/>
+        <enum value="0x8158" name="GL_IMAGE_TRANSLATE_Y_HP"/>
+        <enum value="0x8159" name="GL_IMAGE_ROTATE_ANGLE_HP"/>
+        <enum value="0x815A" name="GL_IMAGE_ROTATE_ORIGIN_X_HP"/>
+        <enum value="0x815B" name="GL_IMAGE_ROTATE_ORIGIN_Y_HP"/>
+        <enum value="0x815C" name="GL_IMAGE_MAG_FILTER_HP"/>
+        <enum value="0x815D" name="GL_IMAGE_MIN_FILTER_HP"/>
+        <enum value="0x815E" name="GL_IMAGE_CUBIC_WEIGHT_HP"/>
+        <enum value="0x815F" name="GL_CUBIC_HP"/>
+        <enum value="0x8160" name="GL_AVERAGE_HP"/>
+        <enum value="0x8161" name="GL_IMAGE_TRANSFORM_2D_HP"/>
+        <enum value="0x8162" name="GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP"/>
+        <enum value="0x8163" name="GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP"/>
+            <unused start="0x8164" vendor="HP"/>
+        <enum value="0x8165" name="GL_OCCLUSION_TEST_HP"/>
+        <enum value="0x8166" name="GL_OCCLUSION_TEST_RESULT_HP"/>
+        <enum value="0x8167" name="GL_TEXTURE_LIGHTING_MODE_HP"/>
+        <enum value="0x8168" name="GL_TEXTURE_POST_SPECULAR_HP"/>
+        <enum value="0x8169" name="GL_TEXTURE_PRE_SPECULAR_HP"/>
+            <unused start="0x816A" end="0x816F" vendor="HP"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8170" end="0x81CF" vendor="SGI">
+        <enum value="0x8170" name="GL_LINEAR_CLIPMAP_LINEAR_SGIX"/>
+        <enum value="0x8171" name="GL_TEXTURE_CLIPMAP_CENTER_SGIX"/>
+        <enum value="0x8172" name="GL_TEXTURE_CLIPMAP_FRAME_SGIX"/>
+        <enum value="0x8173" name="GL_TEXTURE_CLIPMAP_OFFSET_SGIX"/>
+        <enum value="0x8174" name="GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX"/>
+        <enum value="0x8175" name="GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX"/>
+        <enum value="0x8176" name="GL_TEXTURE_CLIPMAP_DEPTH_SGIX"/>
+        <enum value="0x8177" name="GL_MAX_CLIPMAP_DEPTH_SGIX"/>
+        <enum value="0x8178" name="GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX"/>
+        <enum value="0x8179" name="GL_POST_TEXTURE_FILTER_BIAS_SGIX"/>
+        <enum value="0x817A" name="GL_POST_TEXTURE_FILTER_SCALE_SGIX"/>
+        <enum value="0x817B" name="GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX"/>
+        <enum value="0x817C" name="GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX"/>
+        <enum value="0x817D" name="GL_REFERENCE_PLANE_SGIX"/>
+        <enum value="0x817E" name="GL_REFERENCE_PLANE_EQUATION_SGIX"/>
+        <enum value="0x817F" name="GL_IR_INSTRUMENT1_SGIX"/>
+        <enum value="0x8180" name="GL_INSTRUMENT_BUFFER_POINTER_SGIX"/>
+        <enum value="0x8181" name="GL_INSTRUMENT_MEASUREMENTS_SGIX"/>
+        <enum value="0x8182" name="GL_LIST_PRIORITY_SGIX"/>
+        <enum value="0x8183" name="GL_CALLIGRAPHIC_FRAGMENT_SGIX"/>
+        <enum value="0x8184" name="GL_PIXEL_TEX_GEN_Q_CEILING_SGIX"/>
+        <enum value="0x8185" name="GL_PIXEL_TEX_GEN_Q_ROUND_SGIX"/>
+        <enum value="0x8186" name="GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX"/>
+        <enum value="0x8187" name="GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX"/>
+        <enum value="0x8188" name="GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX"/>
+        <enum value="0x8189" name="GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX"/>
+        <enum value="0x818A" name="GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX"/>
+        <enum value="0x818B" name="GL_FRAMEZOOM_SGIX"/>
+        <enum value="0x818C" name="GL_FRAMEZOOM_FACTOR_SGIX"/>
+        <enum value="0x818D" name="GL_MAX_FRAMEZOOM_FACTOR_SGIX"/>
+        <enum value="0x818E" name="GL_TEXTURE_LOD_BIAS_S_SGIX"/>
+        <enum value="0x818F" name="GL_TEXTURE_LOD_BIAS_T_SGIX"/>
+        <enum value="0x8190" name="GL_TEXTURE_LOD_BIAS_R_SGIX"/>
+        <enum value="0x8191" name="GL_GENERATE_MIPMAP"/>
+        <enum value="0x8191" name="GL_GENERATE_MIPMAP_SGIS"/>
+        <enum value="0x8192" name="GL_GENERATE_MIPMAP_HINT"/>
+        <enum value="0x8192" name="GL_GENERATE_MIPMAP_HINT_SGIS"/>
+            <unused start="0x8193" end="0x8193" comment="Incomplete extension SGIX_spotlight_cutoff"/>
+            <!-- <enum value="0x8193" name="GL_SPOT_CUTOFF_DELTA_SGIX"/> -->
+        <enum value="0x8194" name="GL_GEOMETRY_DEFORMATION_SGIX"/>
+        <enum value="0x8195" name="GL_TEXTURE_DEFORMATION_SGIX"/>
+        <enum value="0x8196" name="GL_DEFORMATIONS_MASK_SGIX"/>
+        <enum value="0x8197" name="GL_MAX_DEFORMATION_ORDER_SGIX"/>
+        <enum value="0x8198" name="GL_FOG_OFFSET_SGIX"/>
+        <enum value="0x8199" name="GL_FOG_OFFSET_VALUE_SGIX"/>
+        <enum value="0x819A" name="GL_TEXTURE_COMPARE_SGIX"/>
+        <enum value="0x819B" name="GL_TEXTURE_COMPARE_OPERATOR_SGIX"/>
+        <enum value="0x819C" name="GL_TEXTURE_LEQUAL_R_SGIX"/>
+        <enum value="0x819D" name="GL_TEXTURE_GEQUAL_R_SGIX"/>
+            <unused start="0x819E" end="0x81A4" comment="Private (internal) extension SGIX_igloo_interface"/>
+            <!-- <enum value="0x819E" name="GL_IGLOO_FULLSCREEN_SGIX"/> -->
+            <!-- <enum value="0x819F" name="GL_IGLOO_VIEWPORT_OFFSET_SGIX"/> -->
+            <!-- <enum value="0x81A0" name="GL_IGLOO_SWAPTMESH_SGIX"/> -->
+            <!-- <enum value="0x81A1" name="GL_IGLOO_COLORNORMAL_SGIX"/> -->
+            <!-- <enum value="0x81A2" name="GL_IGLOO_IRISGL_MODE_SGIX"/> -->
+            <!-- <enum value="0x81A3" name="GL_IGLOO_LMC_COLOR_SGIX"/> -->
+            <!-- <enum value="0x81A4" name="GL_IGLOO_TMESHMODE_SGIX"/> -->
+        <enum value="0x81A5" name="GL_DEPTH_COMPONENT16"/>
+        <enum value="0x81A5" name="GL_DEPTH_COMPONENT16_ARB"/>
+        <enum value="0x81A5" name="GL_DEPTH_COMPONENT16_OES"/>
+        <enum value="0x81A5" name="GL_DEPTH_COMPONENT16_SGIX"/>
+        <enum value="0x81A6" name="GL_DEPTH_COMPONENT24"/>
+        <enum value="0x81A6" name="GL_DEPTH_COMPONENT24_ARB"/>
+        <enum value="0x81A6" name="GL_DEPTH_COMPONENT24_OES"/>
+        <enum value="0x81A6" name="GL_DEPTH_COMPONENT24_SGIX"/>
+        <enum value="0x81A7" name="GL_DEPTH_COMPONENT32"/>
+        <enum value="0x81A7" name="GL_DEPTH_COMPONENT32_ARB"/>
+        <enum value="0x81A7" name="GL_DEPTH_COMPONENT32_OES"/>
+        <enum value="0x81A7" name="GL_DEPTH_COMPONENT32_SGIX"/>
+        <enum value="0x81A8" name="GL_ARRAY_ELEMENT_LOCK_FIRST_EXT"/>
+        <enum value="0x81A9" name="GL_ARRAY_ELEMENT_LOCK_COUNT_EXT"/>
+        <enum value="0x81AA" name="GL_CULL_VERTEX_EXT"/>
+        <enum value="0x81AB" name="GL_CULL_VERTEX_EYE_POSITION_EXT"/>
+        <enum value="0x81AC" name="GL_CULL_VERTEX_OBJECT_POSITION_EXT"/>
+        <enum value="0x81AD" name="GL_IUI_V2F_EXT"/>
+        <enum value="0x81AE" name="GL_IUI_V3F_EXT"/>
+        <enum value="0x81AF" name="GL_IUI_N3F_V2F_EXT"/>
+        <enum value="0x81B0" name="GL_IUI_N3F_V3F_EXT"/>
+        <enum value="0x81B1" name="GL_T2F_IUI_V2F_EXT"/>
+        <enum value="0x81B2" name="GL_T2F_IUI_V3F_EXT"/>
+        <enum value="0x81B3" name="GL_T2F_IUI_N3F_V2F_EXT"/>
+        <enum value="0x81B4" name="GL_T2F_IUI_N3F_V3F_EXT"/>
+        <enum value="0x81B5" name="GL_INDEX_TEST_EXT"/>
+        <enum value="0x81B6" name="GL_INDEX_TEST_FUNC_EXT"/>
+        <enum value="0x81B7" name="GL_INDEX_TEST_REF_EXT"/>
+        <enum value="0x81B8" name="GL_INDEX_MATERIAL_EXT"/>
+        <enum value="0x81B9" name="GL_INDEX_MATERIAL_PARAMETER_EXT"/>
+        <enum value="0x81BA" name="GL_INDEX_MATERIAL_FACE_EXT"/>
+        <enum value="0x81BB" name="GL_YCRCB_422_SGIX"/>
+        <enum value="0x81BC" name="GL_YCRCB_444_SGIX"/>
+            <unused start="0x81BD" end="0x81C3" comment="Incomplete extension SGI_complex_type"/>
+            <!-- <enum value="0x81BD" name="GL_COMPLEX_UNSIGNED_BYTE_SGI"/> -->
+            <!-- <enum value="0x81BE" name="GL_COMPLEX_BYTE_SGI"/> -->
+            <!-- <enum value="0x81BF" name="GL_COMPLEX_UNSIGNED_SHORT_SGI"/> -->
+            <!-- <enum value="0x81C0" name="GL_COMPLEX_SHORT_SGI"/> -->
+            <!-- <enum value="0x81C1" name="GL_COMPLEX_UNSIGNED_INT_SGI"/> -->
+            <!-- <enum value="0x81C2" name="GL_COMPLEX_INT_SGI"/> -->
+            <!-- <enum value="0x81C3" name="GL_COMPLEX_FLOAT_SGI"/> -->
+            <unused start="0x81C4" end="0x81CA" comment="Incomplete extension SGI_fft"/>
+            <!-- <enum value="0x81C4" name="GL_PIXEL_TRANSFORM_OPERATOR_SGI"/> -->
+            <!-- <enum value="0x81C5" name="GL_CONVOLUTION_SGI"/> -->
+            <!-- <enum value="0x81C6" name="GL_FFT_1D_SGI"/> -->
+            <!-- <enum value="0x81C7" name="GL_PIXEL_TRANSFORM_SGI"/> -->
+            <!-- <enum value="0x81C8" name="GL_MAX_FFT_WIDTH_SGI"/> -->
+            <!-- <enum value="0x81C9" name="GL_SORT_SGI"/> -->
+            <!-- <enum value="0x81CA" name="GL_TRANSPOSE_SGI"/> -->
+            <unused start="0x81CB" end="0x81CF" comment="Incomplete extension SGIX_nurbs_eval"/>
+            <!-- <enum value="0x81CB" name="GL_MAP1_VERTEX_3_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81CC" name="GL_MAP1_VERTEX_4_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81CD" name="GL_MAP1_INDEX_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81CE" name="GL_MAP1_COLOR_4_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81CF" name="GL_MAP1_NORMAL_NURBS_SGIX"/> -->
+    </enums>
+
+    <enums namespace="GL" start="0x81D0" end="0x81DF" vendor="SUN">
+            <unused start="0x81D0" end="0x81D1" vendor="SUN"/>
+            <unused start="0x81D2" end="0x81D3" comment="No extension spec SUNX_surface_hint"/>
+            <!-- <enum value="0x81D2" name="GL_SURFACE_SIZE_HINT_SUNX"/> -->
+            <!-- <enum value="0x81D3" name="GL_LARGE_SUNX"/> -->
+        <enum value="0x81D4" name="GL_WRAP_BORDER_SUN"/>
+        <enum value="0x81D5" name="GL_UNPACK_CONSTANT_DATA_SUNX"/>
+        <enum value="0x81D6" name="GL_TEXTURE_CONSTANT_DATA_SUNX"/>
+        <enum value="0x81D7" name="GL_TRIANGLE_LIST_SUN"/>
+        <enum value="0x81D8" name="GL_REPLACEMENT_CODE_SUN"/>
+        <enum value="0x81D9" name="GL_GLOBAL_ALPHA_SUN"/>
+        <enum value="0x81DA" name="GL_GLOBAL_ALPHA_FACTOR_SUN"/>
+            <unused start="0x81DB" end="0x81DF" vendor="SUN"/>
+    </enums>
+
+    <enums namespace="GL" start="0x81E0" end="0x81FF" vendor="SGI">
+            <unused start="0x81E0" end="0x81EE" comment="Incomplete extension SGIX_nurbs_eval"/>
+            <!-- <enum value="0x81E0" name="GL_MAP1_TEXTURE_COORD_1_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81E1" name="GL_MAP1_TEXTURE_COORD_2_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81E2" name="GL_MAP1_TEXTURE_COORD_3_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81E3" name="GL_MAP1_TEXTURE_COORD_4_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81E4" name="GL_MAP2_VERTEX_3_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81E5" name="GL_MAP2_VERTEX_4_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81E6" name="GL_MAP2_INDEX_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81E7" name="GL_MAP2_COLOR_4_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81E8" name="GL_MAP2_NORMAL_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81E9" name="GL_MAP2_TEXTURE_COORD_1_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81EA" name="GL_MAP2_TEXTURE_COORD_2_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81EB" name="GL_MAP2_TEXTURE_COORD_3_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81EC" name="GL_MAP2_TEXTURE_COORD_4_NURBS_SGIX"/> -->
+            <!-- <enum value="0x81ED" name="GL_NURBS_KNOT_COUNT_SGIX"/> -->
+            <!-- <enum value="0x81EE" name="GL_NURBS_KNOT_VECTOR_SGIX"/> -->
+        <enum value="0x81EF" name="GL_TEXTURE_COLOR_WRITEMASK_SGIS"/>
+        <enum value="0x81F0" name="GL_EYE_DISTANCE_TO_POINT_SGIS"/>
+        <enum value="0x81F1" name="GL_OBJECT_DISTANCE_TO_POINT_SGIS"/>
+        <enum value="0x81F2" name="GL_EYE_DISTANCE_TO_LINE_SGIS"/>
+        <enum value="0x81F3" name="GL_OBJECT_DISTANCE_TO_LINE_SGIS"/>
+        <enum value="0x81F4" name="GL_EYE_POINT_SGIS"/>
+        <enum value="0x81F5" name="GL_OBJECT_POINT_SGIS"/>
+        <enum value="0x81F6" name="GL_EYE_LINE_SGIS"/>
+        <enum value="0x81F7" name="GL_OBJECT_LINE_SGIS"/>
+        <enum value="0x81F8" name="GL_LIGHT_MODEL_COLOR_CONTROL"/>
+        <enum value="0x81F8" name="GL_LIGHT_MODEL_COLOR_CONTROL_EXT"/>
+        <enum value="0x81F9" name="GL_SINGLE_COLOR"/>
+        <enum value="0x81F9" name="GL_SINGLE_COLOR_EXT"/>
+        <enum value="0x81FA" name="GL_SEPARATE_SPECULAR_COLOR"/>
+        <enum value="0x81FA" name="GL_SEPARATE_SPECULAR_COLOR_EXT"/>
+        <enum value="0x81FB" name="GL_SHARED_TEXTURE_PALETTE_EXT"/>
+            <unused start="0x81FC" end="0x81FD" comment="Incomplete extension SGIX_fog_scale"/>
+            <!-- <enum value="0x81FC" name="GL_FOG_SCALE_SGIX"/> -->
+            <!-- <enum value="0x81FD" name="GL_FOG_SCALE_VALUE_SGIX"/> -->
+            <unused start="0x81FE" end="0x81FF" comment="Incomplete extension SGIX_fog_blend"/>
+            <!-- <enum value="0x81FE" name="GL_FOG_BLEND_ALPHA_SGIX"/> -->
+            <!-- <enum value="0x81FF" name="GL_FOG_BLEND_COLOR_SGIX"/> -->
+    </enums>
+
+    <enums namespace="GL" start="0x8200" end="0x820F" vendor="AMD" comment="Range released by MS 2002/9/16">
+        <enum value="0x8200" name="GL_TEXT_FRAGMENT_SHADER_ATI"/>
+            <unused start="0x8201" end="0x820F" vendor="AMD"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8210" end="0x823F" vendor="ARB">
+        <enum value="0x8210" name="GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING"/>
+        <enum value="0x8210" name="GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT"/>
+        <enum value="0x8211" name="GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"/>
+        <enum value="0x8211" name="GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT"/>
+        <enum value="0x8212" name="GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE"/>
+        <enum value="0x8213" name="GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE"/>
+        <enum value="0x8214" name="GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE"/>
+        <enum value="0x8215" name="GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE"/>
+        <enum value="0x8216" name="GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE"/>
+        <enum value="0x8217" name="GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE"/>
+        <enum value="0x8218" name="GL_FRAMEBUFFER_DEFAULT"/>
+        <enum value="0x8219" name="GL_FRAMEBUFFER_UNDEFINED"/>
+        <enum value="0x8219" name="GL_FRAMEBUFFER_UNDEFINED_OES"/>
+        <enum value="0x821A" name="GL_DEPTH_STENCIL_ATTACHMENT"/>
+        <enum value="0x821B" name="GL_MAJOR_VERSION"/>
+        <enum value="0x821C" name="GL_MINOR_VERSION"/>
+        <enum value="0x821D" name="GL_NUM_EXTENSIONS"/>
+        <enum value="0x821E" name="GL_CONTEXT_FLAGS"/>
+        <enum value="0x821F" name="GL_BUFFER_IMMUTABLE_STORAGE"/>
+        <enum value="0x821F" name="GL_BUFFER_IMMUTABLE_STORAGE_EXT"/>
+        <enum value="0x8220" name="GL_BUFFER_STORAGE_FLAGS"/>
+        <enum value="0x8220" name="GL_BUFFER_STORAGE_FLAGS_EXT"/>
+        <enum value="0x8221" name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"/>
+        <enum value="0x8221" name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES"/>
+        <enum value="0x8222" name="GL_INDEX"/>
+            <unused start="0x8223" vendor="ARB" comment="GL_DEPTH_BUFFER = 0x8223 not actually used in the API"/>
+            <unused start="0x8224" vendor="ARB" comment="GL_STENCIL_BUFFER = 0x8224 not actually used in the API"/>
+        <enum value="0x8225" name="GL_COMPRESSED_RED"/>
+        <enum value="0x8226" name="GL_COMPRESSED_RG"/>
+        <enum value="0x8227" name="GL_RG"/>
+        <enum value="0x8227" name="GL_RG_EXT"/>
+        <enum value="0x8228" name="GL_RG_INTEGER"/>
+        <enum value="0x8229" name="GL_R8"/>
+        <enum value="0x8229" name="GL_R8_EXT"/>
+        <enum value="0x822A" name="GL_R16"/>
+        <enum value="0x822A" name="GL_R16_EXT"/>
+        <enum value="0x822B" name="GL_RG8"/>
+        <enum value="0x822B" name="GL_RG8_EXT"/>
+        <enum value="0x822C" name="GL_RG16"/>
+        <enum value="0x822C" name="GL_RG16_EXT"/>
+        <enum value="0x822D" name="GL_R16F"/>
+        <enum value="0x822D" name="GL_R16F_EXT"/>
+        <enum value="0x822E" name="GL_R32F"/>
+        <enum value="0x822E" name="GL_R32F_EXT"/>
+        <enum value="0x822F" name="GL_RG16F"/>
+        <enum value="0x822F" name="GL_RG16F_EXT"/>
+        <enum value="0x8230" name="GL_RG32F"/>
+        <enum value="0x8230" name="GL_RG32F_EXT"/>
+        <enum value="0x8231" name="GL_R8I"/>
+        <enum value="0x8232" name="GL_R8UI"/>
+        <enum value="0x8233" name="GL_R16I"/>
+        <enum value="0x8234" name="GL_R16UI"/>
+        <enum value="0x8235" name="GL_R32I"/>
+        <enum value="0x8236" name="GL_R32UI"/>
+        <enum value="0x8237" name="GL_RG8I"/>
+        <enum value="0x8238" name="GL_RG8UI"/>
+        <enum value="0x8239" name="GL_RG16I"/>
+        <enum value="0x823A" name="GL_RG16UI"/>
+        <enum value="0x823B" name="GL_RG32I"/>
+        <enum value="0x823C" name="GL_RG32UI"/>
+            <unused start="0x823D" end="0x823F" vendor="ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8240" end="0x82AF" vendor="ARB" comment="Range released by MS on 2002/9/16">
+        <enum value="0x8240" name="GL_SYNC_CL_EVENT_ARB"/>
+        <enum value="0x8241" name="GL_SYNC_CL_EVENT_COMPLETE_ARB"/>
+        <enum value="0x8242" name="GL_DEBUG_OUTPUT_SYNCHRONOUS"/>
+        <enum value="0x8242" name="GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB"/>
+        <enum value="0x8242" name="GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR"/>
+        <enum value="0x8243" name="GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH"/>
+        <enum value="0x8243" name="GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB"/>
+        <enum value="0x8243" name="GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR"/>
+        <enum value="0x8244" name="GL_DEBUG_CALLBACK_FUNCTION"/>
+        <enum value="0x8244" name="GL_DEBUG_CALLBACK_FUNCTION_ARB"/>
+        <enum value="0x8244" name="GL_DEBUG_CALLBACK_FUNCTION_KHR"/>
+        <enum value="0x8245" name="GL_DEBUG_CALLBACK_USER_PARAM"/>
+        <enum value="0x8245" name="GL_DEBUG_CALLBACK_USER_PARAM_ARB"/>
+        <enum value="0x8245" name="GL_DEBUG_CALLBACK_USER_PARAM_KHR"/>
+        <enum value="0x8246" name="GL_DEBUG_SOURCE_API"/>
+        <enum value="0x8246" name="GL_DEBUG_SOURCE_API_ARB"/>
+        <enum value="0x8246" name="GL_DEBUG_SOURCE_API_KHR"/>
+        <enum value="0x8247" name="GL_DEBUG_SOURCE_WINDOW_SYSTEM"/>
+        <enum value="0x8247" name="GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB"/>
+        <enum value="0x8247" name="GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR"/>
+        <enum value="0x8248" name="GL_DEBUG_SOURCE_SHADER_COMPILER"/>
+        <enum value="0x8248" name="GL_DEBUG_SOURCE_SHADER_COMPILER_ARB"/>
+        <enum value="0x8248" name="GL_DEBUG_SOURCE_SHADER_COMPILER_KHR"/>
+        <enum value="0x8249" name="GL_DEBUG_SOURCE_THIRD_PARTY"/>
+        <enum value="0x8249" name="GL_DEBUG_SOURCE_THIRD_PARTY_ARB"/>
+        <enum value="0x8249" name="GL_DEBUG_SOURCE_THIRD_PARTY_KHR"/>
+        <enum value="0x824A" name="GL_DEBUG_SOURCE_APPLICATION"/>
+        <enum value="0x824A" name="GL_DEBUG_SOURCE_APPLICATION_ARB"/>
+        <enum value="0x824A" name="GL_DEBUG_SOURCE_APPLICATION_KHR"/>
+        <enum value="0x824B" name="GL_DEBUG_SOURCE_OTHER"/>
+        <enum value="0x824B" name="GL_DEBUG_SOURCE_OTHER_ARB"/>
+        <enum value="0x824B" name="GL_DEBUG_SOURCE_OTHER_KHR"/>
+        <enum value="0x824C" name="GL_DEBUG_TYPE_ERROR"/>
+        <enum value="0x824C" name="GL_DEBUG_TYPE_ERROR_ARB"/>
+        <enum value="0x824C" name="GL_DEBUG_TYPE_ERROR_KHR"/>
+        <enum value="0x824D" name="GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"/>
+        <enum value="0x824D" name="GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB"/>
+        <enum value="0x824D" name="GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR"/>
+        <enum value="0x824E" name="GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"/>
+        <enum value="0x824E" name="GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB"/>
+        <enum value="0x824E" name="GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR"/>
+        <enum value="0x824F" name="GL_DEBUG_TYPE_PORTABILITY"/>
+        <enum value="0x824F" name="GL_DEBUG_TYPE_PORTABILITY_ARB"/>
+        <enum value="0x824F" name="GL_DEBUG_TYPE_PORTABILITY_KHR"/>
+        <enum value="0x8250" name="GL_DEBUG_TYPE_PERFORMANCE"/>
+        <enum value="0x8250" name="GL_DEBUG_TYPE_PERFORMANCE_ARB"/>
+        <enum value="0x8250" name="GL_DEBUG_TYPE_PERFORMANCE_KHR"/>
+        <enum value="0x8251" name="GL_DEBUG_TYPE_OTHER"/>
+        <enum value="0x8251" name="GL_DEBUG_TYPE_OTHER_ARB"/>
+        <enum value="0x8251" name="GL_DEBUG_TYPE_OTHER_KHR"/>
+        <enum value="0x8252" name="GL_LOSE_CONTEXT_ON_RESET"/>
+        <enum value="0x8252" name="GL_LOSE_CONTEXT_ON_RESET_ARB"/>
+        <enum value="0x8252" name="GL_LOSE_CONTEXT_ON_RESET_EXT"/>
+        <enum value="0x8252" name="GL_LOSE_CONTEXT_ON_RESET_KHR"/>
+        <enum value="0x8253" name="GL_GUILTY_CONTEXT_RESET"/>
+        <enum value="0x8253" name="GL_GUILTY_CONTEXT_RESET_ARB"/>
+        <enum value="0x8253" name="GL_GUILTY_CONTEXT_RESET_EXT"/>
+        <enum value="0x8253" name="GL_GUILTY_CONTEXT_RESET_KHR"/>
+        <enum value="0x8254" name="GL_INNOCENT_CONTEXT_RESET"/>
+        <enum value="0x8254" name="GL_INNOCENT_CONTEXT_RESET_ARB"/>
+        <enum value="0x8254" name="GL_INNOCENT_CONTEXT_RESET_EXT"/>
+        <enum value="0x8254" name="GL_INNOCENT_CONTEXT_RESET_KHR"/>
+        <enum value="0x8255" name="GL_UNKNOWN_CONTEXT_RESET"/>
+        <enum value="0x8255" name="GL_UNKNOWN_CONTEXT_RESET_ARB"/>
+        <enum value="0x8255" name="GL_UNKNOWN_CONTEXT_RESET_EXT"/>
+        <enum value="0x8255" name="GL_UNKNOWN_CONTEXT_RESET_KHR"/>
+        <enum value="0x8256" name="GL_RESET_NOTIFICATION_STRATEGY"/>
+        <enum value="0x8256" name="GL_RESET_NOTIFICATION_STRATEGY_ARB"/>
+        <enum value="0x8256" name="GL_RESET_NOTIFICATION_STRATEGY_EXT"/>
+        <enum value="0x8256" name="GL_RESET_NOTIFICATION_STRATEGY_KHR"/>
+        <enum value="0x8257" name="GL_PROGRAM_BINARY_RETRIEVABLE_HINT"/>
+        <enum value="0x8258" name="GL_PROGRAM_SEPARABLE"/>
+        <enum value="0x8258" name="GL_PROGRAM_SEPARABLE_EXT"/>
+        <enum value="0x8259" name="GL_ACTIVE_PROGRAM"/>
+        <enum value="0x8259" api="gles2" name="GL_ACTIVE_PROGRAM_EXT" comment="For the OpenGL ES version of EXT_separate_shader_objects"/>
+        <enum value="0x825A" name="GL_PROGRAM_PIPELINE_BINDING"/>
+        <enum value="0x825A" name="GL_PROGRAM_PIPELINE_BINDING_EXT"/>
+        <enum value="0x825B" name="GL_MAX_VIEWPORTS"/>
+        <enum value="0x825B" name="GL_MAX_VIEWPORTS_NV"/>
+        <enum value="0x825B" name="GL_MAX_VIEWPORTS_OES"/>
+        <enum value="0x825C" name="GL_VIEWPORT_SUBPIXEL_BITS"/>
+        <enum value="0x825C" name="GL_VIEWPORT_SUBPIXEL_BITS_EXT"/>
+        <enum value="0x825C" name="GL_VIEWPORT_SUBPIXEL_BITS_NV"/>
+        <enum value="0x825C" name="GL_VIEWPORT_SUBPIXEL_BITS_OES"/>
+        <enum value="0x825D" name="GL_VIEWPORT_BOUNDS_RANGE"/>
+        <enum value="0x825D" name="GL_VIEWPORT_BOUNDS_RANGE_EXT"/>
+        <enum value="0x825D" name="GL_VIEWPORT_BOUNDS_RANGE_NV"/>
+        <enum value="0x825D" name="GL_VIEWPORT_BOUNDS_RANGE_OES"/>
+        <enum value="0x825E" name="GL_LAYER_PROVOKING_VERTEX"/>
+        <enum value="0x825E" name="GL_LAYER_PROVOKING_VERTEX_EXT"/>
+        <enum value="0x825E" name="GL_LAYER_PROVOKING_VERTEX_OES"/>
+        <enum value="0x825F" name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX"/>
+        <enum value="0x825F" name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX_EXT"/>
+        <enum value="0x825F" name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV"/>
+        <enum value="0x825F" name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES"/>
+        <enum value="0x8260" name="GL_UNDEFINED_VERTEX"/>
+        <enum value="0x8260" name="GL_UNDEFINED_VERTEX_EXT"/>
+        <enum value="0x8260" name="GL_UNDEFINED_VERTEX_OES"/>
+        <enum value="0x8261" name="GL_NO_RESET_NOTIFICATION"/>
+        <enum value="0x8261" name="GL_NO_RESET_NOTIFICATION_ARB"/>
+        <enum value="0x8261" name="GL_NO_RESET_NOTIFICATION_EXT"/>
+        <enum value="0x8261" name="GL_NO_RESET_NOTIFICATION_KHR"/>
+        <enum value="0x8262" name="GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"/>
+        <enum value="0x8263" name="GL_MAX_COMPUTE_UNIFORM_COMPONENTS"/>
+        <enum value="0x8264" name="GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"/>
+        <enum value="0x8265" name="GL_MAX_COMPUTE_ATOMIC_COUNTERS"/>
+        <enum value="0x8266" name="GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS"/>
+        <enum value="0x8267" name="GL_COMPUTE_WORK_GROUP_SIZE"/>
+        <enum value="0x8268" name="GL_DEBUG_TYPE_MARKER"/>
+        <enum value="0x8268" name="GL_DEBUG_TYPE_MARKER_KHR"/>
+        <enum value="0x8269" name="GL_DEBUG_TYPE_PUSH_GROUP"/>
+        <enum value="0x8269" name="GL_DEBUG_TYPE_PUSH_GROUP_KHR"/>
+        <enum value="0x826A" name="GL_DEBUG_TYPE_POP_GROUP"/>
+        <enum value="0x826A" name="GL_DEBUG_TYPE_POP_GROUP_KHR"/>
+        <enum value="0x826B" name="GL_DEBUG_SEVERITY_NOTIFICATION"/>
+        <enum value="0x826B" name="GL_DEBUG_SEVERITY_NOTIFICATION_KHR"/>
+        <enum value="0x826C" name="GL_MAX_DEBUG_GROUP_STACK_DEPTH"/>
+        <enum value="0x826C" name="GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR"/>
+        <enum value="0x826D" name="GL_DEBUG_GROUP_STACK_DEPTH"/>
+        <enum value="0x826D" name="GL_DEBUG_GROUP_STACK_DEPTH_KHR"/>
+        <enum value="0x826E" name="GL_MAX_UNIFORM_LOCATIONS"/>
+        <enum value="0x826F" name="GL_INTERNALFORMAT_SUPPORTED"/>
+        <enum value="0x8270" name="GL_INTERNALFORMAT_PREFERRED"/>
+        <enum value="0x8271" name="GL_INTERNALFORMAT_RED_SIZE"/>
+        <enum value="0x8272" name="GL_INTERNALFORMAT_GREEN_SIZE"/>
+        <enum value="0x8273" name="GL_INTERNALFORMAT_BLUE_SIZE"/>
+        <enum value="0x8274" name="GL_INTERNALFORMAT_ALPHA_SIZE"/>
+        <enum value="0x8275" name="GL_INTERNALFORMAT_DEPTH_SIZE"/>
+        <enum value="0x8276" name="GL_INTERNALFORMAT_STENCIL_SIZE"/>
+        <enum value="0x8277" name="GL_INTERNALFORMAT_SHARED_SIZE"/>
+        <enum value="0x8278" name="GL_INTERNALFORMAT_RED_TYPE"/>
+        <enum value="0x8279" name="GL_INTERNALFORMAT_GREEN_TYPE"/>
+        <enum value="0x827A" name="GL_INTERNALFORMAT_BLUE_TYPE"/>
+        <enum value="0x827B" name="GL_INTERNALFORMAT_ALPHA_TYPE"/>
+        <enum value="0x827C" name="GL_INTERNALFORMAT_DEPTH_TYPE"/>
+        <enum value="0x827D" name="GL_INTERNALFORMAT_STENCIL_TYPE"/>
+        <enum value="0x827E" name="GL_MAX_WIDTH"/>
+        <enum value="0x827F" name="GL_MAX_HEIGHT"/>
+        <enum value="0x8280" name="GL_MAX_DEPTH"/>
+        <enum value="0x8281" name="GL_MAX_LAYERS"/>
+        <enum value="0x8282" name="GL_MAX_COMBINED_DIMENSIONS"/>
+        <enum value="0x8283" name="GL_COLOR_COMPONENTS"/>
+        <enum value="0x8284" name="GL_DEPTH_COMPONENTS"/>
+        <enum value="0x8285" name="GL_STENCIL_COMPONENTS"/>
+        <enum value="0x8286" name="GL_COLOR_RENDERABLE"/>
+        <enum value="0x8287" name="GL_DEPTH_RENDERABLE"/>
+        <enum value="0x8288" name="GL_STENCIL_RENDERABLE"/>
+        <enum value="0x8289" name="GL_FRAMEBUFFER_RENDERABLE"/>
+        <enum value="0x828A" name="GL_FRAMEBUFFER_RENDERABLE_LAYERED"/>
+        <enum value="0x828B" name="GL_FRAMEBUFFER_BLEND"/>
+        <enum value="0x828C" name="GL_READ_PIXELS"/>
+        <enum value="0x828D" name="GL_READ_PIXELS_FORMAT"/>
+        <enum value="0x828E" name="GL_READ_PIXELS_TYPE"/>
+        <enum value="0x828F" name="GL_TEXTURE_IMAGE_FORMAT"/>
+        <enum value="0x8290" name="GL_TEXTURE_IMAGE_TYPE"/>
+        <enum value="0x8291" name="GL_GET_TEXTURE_IMAGE_FORMAT"/>
+        <enum value="0x8292" name="GL_GET_TEXTURE_IMAGE_TYPE"/>
+        <enum value="0x8293" name="GL_MIPMAP"/>
+        <enum value="0x8294" name="GL_MANUAL_GENERATE_MIPMAP"/>
+        <enum value="0x8295" name="GL_AUTO_GENERATE_MIPMAP" comment="Should be deprecated"/>
+        <enum value="0x8296" name="GL_COLOR_ENCODING"/>
+        <enum value="0x8297" name="GL_SRGB_READ"/>
+        <enum value="0x8298" name="GL_SRGB_WRITE"/>
+        <enum value="0x8299" name="GL_SRGB_DECODE_ARB"/>
+        <enum value="0x829A" name="GL_FILTER"/>
+        <enum value="0x829B" name="GL_VERTEX_TEXTURE"/>
+        <enum value="0x829C" name="GL_TESS_CONTROL_TEXTURE"/>
+        <enum value="0x829D" name="GL_TESS_EVALUATION_TEXTURE"/>
+        <enum value="0x829E" name="GL_GEOMETRY_TEXTURE"/>
+        <enum value="0x829F" name="GL_FRAGMENT_TEXTURE"/>
+        <enum value="0x82A0" name="GL_COMPUTE_TEXTURE"/>
+        <enum value="0x82A1" name="GL_TEXTURE_SHADOW"/>
+        <enum value="0x82A2" name="GL_TEXTURE_GATHER"/>
+        <enum value="0x82A3" name="GL_TEXTURE_GATHER_SHADOW"/>
+        <enum value="0x82A4" name="GL_SHADER_IMAGE_LOAD"/>
+        <enum value="0x82A5" name="GL_SHADER_IMAGE_STORE"/>
+        <enum value="0x82A6" name="GL_SHADER_IMAGE_ATOMIC"/>
+        <enum value="0x82A7" name="GL_IMAGE_TEXEL_SIZE"/>
+        <enum value="0x82A8" name="GL_IMAGE_COMPATIBILITY_CLASS"/>
+        <enum value="0x82A9" name="GL_IMAGE_PIXEL_FORMAT"/>
+        <enum value="0x82AA" name="GL_IMAGE_PIXEL_TYPE"/>
+            <unused start="0x82AB" vendor="ARB"/>
+        <enum value="0x82AC" name="GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST"/>
+        <enum value="0x82AD" name="GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST"/>
+        <enum value="0x82AE" name="GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE"/>
+        <enum value="0x82AF" name="GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE"/>
+    </enums>
+
+    <enums namespace="GL" start="0x82B0" end="0x830F" vendor="ARB" comment="Range reclaimed from ADD on 2012/05/10">
+            <unused start="0x82B0" vendor="ARB"/>
+        <enum value="0x82B1" name="GL_TEXTURE_COMPRESSED_BLOCK_WIDTH"/>
+        <enum value="0x82B2" name="GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT"/>
+        <enum value="0x82B3" name="GL_TEXTURE_COMPRESSED_BLOCK_SIZE"/>
+        <enum value="0x82B4" name="GL_CLEAR_BUFFER"/>
+        <enum value="0x82B5" name="GL_TEXTURE_VIEW"/>
+        <enum value="0x82B6" name="GL_VIEW_COMPATIBILITY_CLASS"/>
+        <enum value="0x82B7" name="GL_FULL_SUPPORT"/>
+        <enum value="0x82B8" name="GL_CAVEAT_SUPPORT"/>
+        <enum value="0x82B9" name="GL_IMAGE_CLASS_4_X_32"/>
+        <enum value="0x82BA" name="GL_IMAGE_CLASS_2_X_32"/>
+        <enum value="0x82BB" name="GL_IMAGE_CLASS_1_X_32"/>
+        <enum value="0x82BC" name="GL_IMAGE_CLASS_4_X_16"/>
+        <enum value="0x82BD" name="GL_IMAGE_CLASS_2_X_16"/>
+        <enum value="0x82BE" name="GL_IMAGE_CLASS_1_X_16"/>
+        <enum value="0x82BF" name="GL_IMAGE_CLASS_4_X_8"/>
+        <enum value="0x82C0" name="GL_IMAGE_CLASS_2_X_8"/>
+        <enum value="0x82C1" name="GL_IMAGE_CLASS_1_X_8"/>
+        <enum value="0x82C2" name="GL_IMAGE_CLASS_11_11_10"/>
+        <enum value="0x82C3" name="GL_IMAGE_CLASS_10_10_10_2"/>
+        <enum value="0x82C4" name="GL_VIEW_CLASS_128_BITS"/>
+        <enum value="0x82C5" name="GL_VIEW_CLASS_96_BITS"/>
+        <enum value="0x82C6" name="GL_VIEW_CLASS_64_BITS"/>
+        <enum value="0x82C7" name="GL_VIEW_CLASS_48_BITS"/>
+        <enum value="0x82C8" name="GL_VIEW_CLASS_32_BITS"/>
+        <enum value="0x82C9" name="GL_VIEW_CLASS_24_BITS"/>
+        <enum value="0x82CA" name="GL_VIEW_CLASS_16_BITS"/>
+        <enum value="0x82CB" name="GL_VIEW_CLASS_8_BITS"/>
+        <enum value="0x82CC" name="GL_VIEW_CLASS_S3TC_DXT1_RGB"/>
+        <enum value="0x82CD" name="GL_VIEW_CLASS_S3TC_DXT1_RGBA"/>
+        <enum value="0x82CE" name="GL_VIEW_CLASS_S3TC_DXT3_RGBA"/>
+        <enum value="0x82CF" name="GL_VIEW_CLASS_S3TC_DXT5_RGBA"/>
+        <enum value="0x82D0" name="GL_VIEW_CLASS_RGTC1_RED"/>
+        <enum value="0x82D1" name="GL_VIEW_CLASS_RGTC2_RG"/>
+        <enum value="0x82D2" name="GL_VIEW_CLASS_BPTC_UNORM"/>
+        <enum value="0x82D3" name="GL_VIEW_CLASS_BPTC_FLOAT"/>
+        <enum value="0x82D4" name="GL_VERTEX_ATTRIB_BINDING"/>
+        <enum value="0x82D5" name="GL_VERTEX_ATTRIB_RELATIVE_OFFSET"/>
+        <enum value="0x82D6" name="GL_VERTEX_BINDING_DIVISOR"/>
+        <enum value="0x82D7" name="GL_VERTEX_BINDING_OFFSET"/>
+        <enum value="0x82D8" name="GL_VERTEX_BINDING_STRIDE"/>
+        <enum value="0x82D9" name="GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET"/>
+        <enum value="0x82DA" name="GL_MAX_VERTEX_ATTRIB_BINDINGS"/>
+        <enum value="0x82DB" name="GL_TEXTURE_VIEW_MIN_LEVEL"/>
+        <enum value="0x82DB" name="GL_TEXTURE_VIEW_MIN_LEVEL_EXT"/>
+        <enum value="0x82DB" name="GL_TEXTURE_VIEW_MIN_LEVEL_OES"/>
+        <enum value="0x82DC" name="GL_TEXTURE_VIEW_NUM_LEVELS"/>
+        <enum value="0x82DC" name="GL_TEXTURE_VIEW_NUM_LEVELS_EXT"/>
+        <enum value="0x82DC" name="GL_TEXTURE_VIEW_NUM_LEVELS_OES"/>
+        <enum value="0x82DD" name="GL_TEXTURE_VIEW_MIN_LAYER"/>
+        <enum value="0x82DD" name="GL_TEXTURE_VIEW_MIN_LAYER_EXT"/>
+        <enum value="0x82DD" name="GL_TEXTURE_VIEW_MIN_LAYER_OES"/>
+        <enum value="0x82DE" name="GL_TEXTURE_VIEW_NUM_LAYERS"/>
+        <enum value="0x82DE" name="GL_TEXTURE_VIEW_NUM_LAYERS_EXT"/>
+        <enum value="0x82DE" name="GL_TEXTURE_VIEW_NUM_LAYERS_OES"/>
+        <enum value="0x82DF" name="GL_TEXTURE_IMMUTABLE_LEVELS"/>
+        <enum value="0x82E0" name="GL_BUFFER"/>
+        <enum value="0x82E0" name="GL_BUFFER_KHR"/>
+        <enum value="0x82E1" name="GL_SHADER"/>
+        <enum value="0x82E1" name="GL_SHADER_KHR"/>
+        <enum value="0x82E2" name="GL_PROGRAM"/>
+        <enum value="0x82E2" name="GL_PROGRAM_KHR"/>
+        <enum value="0x82E3" name="GL_QUERY"/>
+        <enum value="0x82E3" name="GL_QUERY_KHR"/>
+        <enum value="0x82E4" name="GL_PROGRAM_PIPELINE"/>
+        <enum value="0x82E4" name="GL_PROGRAM_PIPELINE_KHR"/>
+        <enum value="0x82E5" name="GL_MAX_VERTEX_ATTRIB_STRIDE"/>
+        <enum value="0x82E6" name="GL_SAMPLER"/>
+        <enum value="0x82E6" name="GL_SAMPLER_KHR"/>
+        <enum value="0x82E7" name="GL_DISPLAY_LIST"/>
+        <enum value="0x82E8" name="GL_MAX_LABEL_LENGTH"/>
+        <enum value="0x82E8" name="GL_MAX_LABEL_LENGTH_KHR"/>
+        <enum value="0x82E9" name="GL_NUM_SHADING_LANGUAGE_VERSIONS"/>
+        <enum value="0x82EA" name="GL_QUERY_TARGET"/>
+        <!-- 0x82EB = GL_TEXTURE_BINDING was removed in GL 4.5 and
+             ARB_direct_state_access in February 2015 after determining it
+             was not well defined or implementable. -->
+            <unused start="0x82EB" vendor="ARB" comment="Reserved. Formerly used for GL_TEXTURE_BINDING."/>
+        <enum value="0x82EC" name="GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB"/>
+        <enum value="0x82ED" name="GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB"/>
+        <enum value="0x82EE" name="GL_VERTICES_SUBMITTED_ARB"/>
+        <enum value="0x82EF" name="GL_PRIMITIVES_SUBMITTED_ARB"/>
+        <enum value="0x82F0" name="GL_VERTEX_SHADER_INVOCATIONS_ARB"/>
+        <enum value="0x82F1" name="GL_TESS_CONTROL_SHADER_PATCHES_ARB"/>
+        <enum value="0x82F2" name="GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB"/>
+        <enum value="0x82F3" name="GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB"/>
+        <enum value="0x82F4" name="GL_FRAGMENT_SHADER_INVOCATIONS_ARB"/>
+        <enum value="0x82F5" name="GL_COMPUTE_SHADER_INVOCATIONS_ARB"/>
+        <enum value="0x82F6" name="GL_CLIPPING_INPUT_PRIMITIVES_ARB"/>
+        <enum value="0x82F7" name="GL_CLIPPING_OUTPUT_PRIMITIVES_ARB"/>
+        <enum value="0x82F8" name="GL_SPARSE_BUFFER_PAGE_SIZE_ARB"/>
+        <enum value="0x82F9" name="GL_MAX_CULL_DISTANCES"/>
+        <enum value="0x82F9" name="GL_MAX_CULL_DISTANCES_EXT" alias="GL_MAX_CULL_DISTANCES"/>
+        <enum value="0x82FA" name="GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES"/>
+        <enum value="0x82FA" name="GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT" alias="GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES"/>
+        <enum value="0x82FB" name="GL_CONTEXT_RELEASE_BEHAVIOR"/>
+        <enum value="0x82FB" name="GL_CONTEXT_RELEASE_BEHAVIOR_KHR"/>
+        <enum value="0x82FC" name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH"/>
+        <enum value="0x82FC" name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR"/>
+            <unused start="0x82FD" end="0x830F" vendor="ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8310" end="0x832F" vendor="SGI">
+        <enum value="0x8310" name="GL_DEPTH_PASS_INSTRUMENT_SGIX"/>
+        <enum value="0x8311" name="GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX"/>
+        <enum value="0x8312" name="GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX"/>
+        <enum value="0x8313" name="GL_FRAGMENTS_INSTRUMENT_SGIX"/>
+        <enum value="0x8314" name="GL_FRAGMENTS_INSTRUMENT_COUNTERS_SGIX"/>
+        <enum value="0x8315" name="GL_FRAGMENTS_INSTRUMENT_MAX_SGIX"/>
+        <enum value="0x8316" name="GL_CONVOLUTION_HINT_SGIX"/>
+            <unused start="0x8317" comment="Incomplete extension SGIX_color_matrix_accuracy"/>
+            <!-- <enum value="0x8317" name="GL_COLOR_MATRIX_HINT"/> -->
+        <enum value="0x8318" name="GL_YCRCB_SGIX"/>
+        <enum value="0x8319" name="GL_YCRCBA_SGIX"/>
+        <enum value="0x831A" name="GL_UNPACK_COMPRESSED_SIZE_SGIX"/>
+        <enum value="0x831B" name="GL_PACK_MAX_COMPRESSED_SIZE_SGIX"/>
+        <enum value="0x831C" name="GL_PACK_COMPRESSED_SIZE_SGIX"/>
+        <enum value="0x831D" name="GL_SLIM8U_SGIX"/>
+        <enum value="0x831E" name="GL_SLIM10U_SGIX"/>
+        <enum value="0x831F" name="GL_SLIM12S_SGIX"/>
+        <enum value="0x8320" name="GL_ALPHA_MIN_SGIX"/>
+        <enum value="0x8321" name="GL_ALPHA_MAX_SGIX"/>
+        <enum value="0x8322" name="GL_SCALEBIAS_HINT_SGIX"/>
+            <unused start="0x8323" end="0x8328" comment="Incomplete extension SGIX_fog_layers"/>
+            <!-- <enum value="0x8323" name="GL_FOG_TYPE_SGIX"/> -->
+            <!-- <enum value="0x8324" name="GL_UNIFORM_SGIX"/> -->
+            <!-- <enum value="0x8325" name="GL_LAYERED_SGIX"/> -->
+            <!-- <enum value="0x8326" name="GL_FOG_GROUND_PLANE_SGIX"/> -->
+            <!-- <enum value="0x8327" name="GL_FOG_LAYERS_POINTS_SGIX"/> -->
+            <!-- <enum value="0x8328" name="GL_MAX_FOG_LAYERS_POINTS_SGIX"/> -->
+        <enum value="0x8329" name="GL_ASYNC_MARKER_SGIX"/>
+            <unused start="0x832A" comment="Incomplete extension SGIX_texture_phase"/>
+            <!-- <enum value="0x832A" name="GL_PHASE_SGIX"/> -->
+        <enum value="0x832B" name="GL_PIXEL_TEX_GEN_MODE_SGIX"/>
+        <enum value="0x832C" name="GL_ASYNC_HISTOGRAM_SGIX"/>
+        <enum value="0x832D" name="GL_MAX_ASYNC_HISTOGRAM_SGIX"/>
+            <unused start="0x832E" end="0x832F" comment="Incomplete extension SGIX_texture_mipmap_anisotropic"/>
+            <!-- <enum value="0x832E" name="GL_TEXTURE_MIPMAP_ANISOTROPY_SGIX"/> -->
+            <!-- <enum value="0x832F" name="GL_MAX_MIPMAP_ANISOTROPY_SGIX"/> -->
+    </enums>
+
+    <enums namespace="GL" start="0x8330" end="0x833F" vendor="SUN">
+        <enum value="0x8330" name="GL_PIXEL_TRANSFORM_2D_EXT"/>
+        <enum value="0x8331" name="GL_PIXEL_MAG_FILTER_EXT"/>
+        <enum value="0x8332" name="GL_PIXEL_MIN_FILTER_EXT"/>
+        <enum value="0x8333" name="GL_PIXEL_CUBIC_WEIGHT_EXT"/>
+        <enum value="0x8334" name="GL_CUBIC_EXT"/>
+        <enum value="0x8335" name="GL_AVERAGE_EXT"/>
+        <enum value="0x8336" name="GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT"/>
+        <enum value="0x8337" name="GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT"/>
+        <enum value="0x8338" name="GL_PIXEL_TRANSFORM_2D_MATRIX_EXT"/>
+            <unused start="0x8339" end="0x833F" vendor="SUN"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8340" end="0x836F" vendor="SGI">
+            <unused start="0x8340" end="0x8348" comment="Incomplete extension SGIX_cube_map"/>
+            <!-- <enum value="0x8340" name="GL_ENV_MAP_SGIX"/> -->
+            <!-- <enum value="0x8341" name="GL_CUBE_MAP_SGIX"/> -->
+            <!-- <enum value="0x8342" name="GL_CUBE_MAP_ZP_SGIX"/> -->
+            <!-- <enum value="0x8343" name="GL_CUBE_MAP_ZN_SGIX"/> -->
+            <!-- <enum value="0x8344" name="GL_CUBE_MAP_XN_SGIX"/> -->
+            <!-- <enum value="0x8345" name="GL_CUBE_MAP_XP_SGIX"/> -->
+            <!-- <enum value="0x8346" name="GL_CUBE_MAP_YN_SGIX"/> -->
+            <!-- <enum value="0x8347" name="GL_CUBE_MAP_YP_SGIX"/> -->
+            <!-- <enum value="0x8348" name="GL_CUBE_MAP_BINDING_SGIX"/> -->
+        <enum value="0x8349" name="GL_FRAGMENT_MATERIAL_EXT"/>
+        <enum value="0x834A" name="GL_FRAGMENT_NORMAL_EXT"/>
+            <!-- Unfortunately, there was a collision promoting to EXT
+                 from SGIX. Use fog_coord's value of 0x8452 instead of
+                 the old assigned FRAGMENT_DEPTH_EXT (0x834B). -->
+        <enum value="0x834C" name="GL_FRAGMENT_COLOR_EXT"/>
+        <enum value="0x834D" name="GL_ATTENUATION_EXT"/>
+        <enum value="0x834E" name="GL_SHADOW_ATTENUATION_EXT"/>
+        <enum value="0x834F" name="GL_TEXTURE_APPLICATION_MODE_EXT"/>
+        <enum value="0x8350" name="GL_TEXTURE_LIGHT_EXT"/>
+        <enum value="0x8351" name="GL_TEXTURE_MATERIAL_FACE_EXT"/>
+        <enum value="0x8352" name="GL_TEXTURE_MATERIAL_PARAMETER_EXT"/>
+        <enum value="0x8353" name="GL_PIXEL_TEXTURE_SGIS"/>
+        <enum value="0x8354" name="GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS"/>
+        <enum value="0x8355" name="GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS"/>
+        <enum value="0x8356" name="GL_PIXEL_GROUP_COLOR_SGIS"/>
+            <unused start="0x8357" end="0x8359" comment="Incomplete extension SGIX_pixel_texture_bits"/>
+            <!-- <enum value="0x8357" name="GL_COLOR_TO_TEXTURE_COORD_SGIX"/> -->
+            <!-- <enum value="0x8358" name="GL_COLOR_BIT_PATTERN_SGIX"/> -->
+            <!-- <enum value="0x8359" name="GL_COLOR_VALUE_SGIX"/> -->
+            <unused start="0x835A" comment="Incomplete extension SGIX_pixel_texture_lod"/>
+            <!-- <enum value="0x835A" name="GL_PIXEL_TEX_GEN_LAMBDA_SOURCE_SGIX"/> -->
+        <enum value="0x835B" name="GL_LINE_QUALITY_HINT_SGIX"/>
+        <enum value="0x835C" name="GL_ASYNC_TEX_IMAGE_SGIX"/>
+        <enum value="0x835D" name="GL_ASYNC_DRAW_PIXELS_SGIX"/>
+        <enum value="0x835E" name="GL_ASYNC_READ_PIXELS_SGIX"/>
+        <enum value="0x835F" name="GL_MAX_ASYNC_TEX_IMAGE_SGIX"/>
+        <enum value="0x8360" name="GL_MAX_ASYNC_DRAW_PIXELS_SGIX"/>
+        <enum value="0x8361" name="GL_MAX_ASYNC_READ_PIXELS_SGIX"/>
+        <enum value="0x8362" name="GL_UNSIGNED_BYTE_2_3_3_REV"/>
+        <enum value="0x8362" name="GL_UNSIGNED_BYTE_2_3_3_REV_EXT"/>
+        <enum value="0x8363" name="GL_UNSIGNED_SHORT_5_6_5"/>
+        <enum value="0x8363" name="GL_UNSIGNED_SHORT_5_6_5_EXT"/>
+        <enum value="0x8364" name="GL_UNSIGNED_SHORT_5_6_5_REV"/>
+        <enum value="0x8364" name="GL_UNSIGNED_SHORT_5_6_5_REV_EXT"/>
+        <enum value="0x8365" name="GL_UNSIGNED_SHORT_4_4_4_4_REV"/>
+        <enum value="0x8365" name="GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT"/>
+        <enum value="0x8365" name="GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG"/>
+        <enum value="0x8366" name="GL_UNSIGNED_SHORT_1_5_5_5_REV"/>
+        <enum value="0x8366" name="GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT"/>
+        <enum value="0x8367" name="GL_UNSIGNED_INT_8_8_8_8_REV"/>
+        <enum value="0x8367" name="GL_UNSIGNED_INT_8_8_8_8_REV_EXT"/>
+        <enum value="0x8368" name="GL_UNSIGNED_INT_2_10_10_10_REV"/>
+        <enum value="0x8368" name="GL_UNSIGNED_INT_2_10_10_10_REV_EXT"/>
+        <enum value="0x8369" name="GL_TEXTURE_MAX_CLAMP_S_SGIX"/>
+        <enum value="0x836A" name="GL_TEXTURE_MAX_CLAMP_T_SGIX"/>
+        <enum value="0x836B" name="GL_TEXTURE_MAX_CLAMP_R_SGIX"/>
+            <unused start="0x836C" end="0x836E" comment="Incomplete extension SGIX_fog_texture"/>
+            <!-- <enum value="0x836C" name="GL_FRAGMENT_FOG_SGIX"/> -->
+            <!-- <enum value="0x836D" name="GL_TEXTURE_FOG_SGIX"/> -->
+            <!-- <enum value="0x836E" name="GL_FOG_PATCHY_FACTOR_SGIX"/> -->
+            <unused start="0x836F" comment="Incomplete extension SGIX_fog_factor_to_alpha"/>
+            <!-- <enum value="0x836F" name="GL_FOG_FACTOR_TO_ALPHA_SGIX"/> -->
+    </enums>
+
+    <enums namespace="GL" start="0x8370" end="0x837F" vendor="HP">
+            <!-- NOTE: IBM is using values in this range, because of a
+                 bobble when an employee left DEC for IBM at the same
+                 time as they were assigned the range. their registry
+                 became inconsistent. It's unknown whether HP has any
+                 conflicts. They have never reported using any values in
+                 this range. Lesson: assigned ranges belong to vendors,
+                 not engineers! -->
+        <enum value="0x8370" name="GL_MIRRORED_REPEAT"/>
+        <enum value="0x8370" name="GL_MIRRORED_REPEAT_ARB"/>
+        <enum value="0x8370" name="GL_MIRRORED_REPEAT_IBM"/>
+        <enum value="0x8370" name="GL_MIRRORED_REPEAT_OES"/>
+            <unused start="0x8371" end="0x837F" vendor="HP"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8380" end="0x839F" vendor="IBM">
+            <unused start="0x8380" end="0x839F" vendor="IBM"/>
+    </enums>
+
+    <enums namespace="GL" start="0x83A0" end="0x83BF" vendor="S3">
+        <enum value="0x83A0" name="GL_RGB_S3TC"/>
+        <enum value="0x83A1" name="GL_RGB4_S3TC"/>
+        <enum value="0x83A2" name="GL_RGBA_S3TC"/>
+        <enum value="0x83A3" name="GL_RGBA4_S3TC"/>
+        <enum value="0x83A4" name="GL_RGBA_DXT5_S3TC"/>
+        <enum value="0x83A5" name="GL_RGBA4_DXT5_S3TC"/>
+            <unused start="0x83A6" end="0x83BF" vendor="S3"/>
+    </enums>
+
+    <enums namespace="GL" start="0x83C0" end="0x83EF" vendor="SGI" comment="Most of this could be reclaimed">
+            <unused start="0x83C0" end="0x83CA" comment="Withdrawn extension SGIS_multitexture"/>
+            <!-- <enum value="0x83C0" name="GL_SELECTED_TEXTURE_SGIS"/> -->
+            <!-- <enum value="0x83C1" name="GL_SELECTED_TEXTURE_COORD_SET_SGIS"/> -->
+            <!-- <enum value="0x83C2" name="GL_SELECTED_TEXTURE_TRANSFORM_SGIS"/> -->
+            <!-- <enum value="0x83C3" name="GL_MAX_TEXTURES_SGIS"/> -->
+            <!-- <enum value="0x83C4" name="GL_MAX_TEXTURE_COORD_SETS_SGIS"/> -->
+            <!-- <enum value="0x83C5" name="GL_TEXTURE_COORD_SET_INTERLEAVE_FACTOR_SGIS"/> -->
+            <!-- <enum value="0x83C6" name="GL_TEXTURE_ENV_COORD_SET_SGIS"/> -->
+            <!-- <enum value="0x83C7" name="GL_TEXTURE0_SGIS"/> -->
+            <!-- <enum value="0x83C8" name="GL_TEXTURE1_SGIS"/> -->
+            <!-- <enum value="0x83C9" name="GL_TEXTURE2_SGIS"/> -->
+            <!-- <enum value="0x83CA" name="GL_TEXTURE3_SGIS"/> -->
+            <unused start="0x83CB" end="0x83E5" vendor="SGI"/>
+            <unused start="0x83E6" end="0x83E9" comment="Incomplete extension SGIX_bali_g_instruments"/>
+            <!-- <enum value="0x83E6" name="GL_BALI_NUM_TRIS_CULLED_INSTRUMENT_SGIX"/> -->
+            <!-- <enum value="0x83E7" name="GL_BALI_NUM_PRIMS_CLIPPED_INSTRUMENT_SGIX"/> -->
+            <!-- <enum value="0x83E8" name="GL_BALI_NUM_PRIMS_REJECT_INSTRUMENT_SGIX"/> -->
+            <!-- <enum value="0x83E9" name="GL_BALI_NUM_PRIMS_CLIP_RESULT_INSTRUMENT_SGIX"/> -->
+            <unused start="0x83EA" end="0x83EC" comment="Incomplete extension SGIX_bali_r_instruments"/>
+            <!-- <enum value="0x83EA" name="GL_BALI_FRAGMENTS_GENERATED_INSTRUMENT_SGIX"/> -->
+            <!-- <enum value="0x83EB" name="GL_BALI_DEPTH_PASS_INSTRUMENT_SGIX"/> -->
+            <!-- <enum value="0x83EC" name="GL_BALI_R_CHIP_COUNT_SGIX"/> -->
+            <unused start="0x83ED" comment="Incomplete extension SGIX_occlusion_instrument"/>
+            <!-- <enum value="0x83ED" name="GL_OCCLUSION_INSTRUMENT_SGIX"/> -->
+        <enum value="0x83EE" name="GL_VERTEX_PRECLIP_SGIX"/>
+        <enum value="0x83EF" name="GL_VERTEX_PRECLIP_HINT_SGIX"/>
+    </enums>
+
+    <enums namespace="GL" start="0x83F0" end="0x83FF" vendor="INTEL">
+            <!-- This block was reclaimed from NTP, who never shipped
+                 it, and reassigned to Intel. -->
+        <enum value="0x83F0" name="GL_COMPRESSED_RGB_S3TC_DXT1_EXT"/>
+        <enum value="0x83F1" name="GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"/>
+        <enum value="0x83F2" name="GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE"/>
+        <enum value="0x83F2" name="GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"/>
+        <enum value="0x83F3" name="GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE"/>
+        <enum value="0x83F3" name="GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"/>
+        <enum value="0x83F4" name="GL_PARALLEL_ARRAYS_INTEL"/>
+        <enum value="0x83F5" name="GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL"/>
+        <enum value="0x83F6" name="GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL"/>
+        <enum value="0x83F7" name="GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL"/>
+        <enum value="0x83F8" name="GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL"/>
+        <enum value="0x83F9" name="GL_PERFQUERY_DONOT_FLUSH_INTEL"/>
+        <enum value="0x83FA" name="GL_PERFQUERY_FLUSH_INTEL"/>
+        <enum value="0x83FB" name="GL_PERFQUERY_WAIT_INTEL"/>
+            <unused start="0x83FC" end="0x83FD" vendor="INTEL"/>
+        <enum value="0x83FE" name="GL_CONSERVATIVE_RASTERIZATION_INTEL"/>
+        <enum value="0x83FF" name="GL_TEXTURE_MEMORY_LAYOUT_INTEL"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8400" end="0x846F" vendor="SGI">
+        <enum value="0x8400" name="GL_FRAGMENT_LIGHTING_SGIX"/>
+        <enum value="0x8401" name="GL_FRAGMENT_COLOR_MATERIAL_SGIX"/>
+        <enum value="0x8402" name="GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX"/>
+        <enum value="0x8403" name="GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX"/>
+        <enum value="0x8404" name="GL_MAX_FRAGMENT_LIGHTS_SGIX"/>
+        <enum value="0x8405" name="GL_MAX_ACTIVE_LIGHTS_SGIX"/>
+        <enum value="0x8406" name="GL_CURRENT_RASTER_NORMAL_SGIX"/>
+        <enum value="0x8407" name="GL_LIGHT_ENV_MODE_SGIX"/>
+        <enum value="0x8408" name="GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX"/>
+        <enum value="0x8409" name="GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX"/>
+        <enum value="0x840A" name="GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX"/>
+        <enum value="0x840B" name="GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX"/>
+        <enum value="0x840C" name="GL_FRAGMENT_LIGHT0_SGIX"/>
+        <enum value="0x840D" name="GL_FRAGMENT_LIGHT1_SGIX"/>
+        <enum value="0x840E" name="GL_FRAGMENT_LIGHT2_SGIX"/>
+        <enum value="0x840F" name="GL_FRAGMENT_LIGHT3_SGIX"/>
+        <enum value="0x8410" name="GL_FRAGMENT_LIGHT4_SGIX"/>
+        <enum value="0x8411" name="GL_FRAGMENT_LIGHT5_SGIX"/>
+        <enum value="0x8412" name="GL_FRAGMENT_LIGHT6_SGIX"/>
+        <enum value="0x8413" name="GL_FRAGMENT_LIGHT7_SGIX"/>
+            <unused start="0x8414" end="0x842D" vendor="SGI"/>
+        <enum value="0x842E" name="GL_PACK_RESAMPLE_SGIX" comment="Formerly 0x842C in SGI specfile"/>
+        <enum value="0x842F" name="GL_UNPACK_RESAMPLE_SGIX" comment="Formerly 0x842D in SGI specfile"/>
+        <enum value="0x8430" name="GL_RESAMPLE_DECIMATE_SGIX" comment="Formerly 0x8430 in SGI specfile"/>
+            <unused start="0x8431" end="0x8432" vendor="SGI"/>
+        <enum value="0x8433" name="GL_RESAMPLE_REPLICATE_SGIX" comment="Formerly 0x842E in SGI specfile"/>
+        <enum value="0x8434" name="GL_RESAMPLE_ZERO_FILL_SGIX" comment="Formerly 0x842F in SGI specfile"/>
+            <unused start="0x8435" vendor="SGI"/>
+            <!-- Incomplete extension SGIX_fragment_lighting -->
+            <!-- <enum value="0x8436"      name="GL_EYE_SPACE_SGIX"/> -->
+            <!-- <enum value="0x8437"      name="GL_TANGENT_SPACE_SGIX"/> -->
+            <!-- <enum value="0x8438"      name="GL_OBJECT_SPACE_SGIX"/> -->
+            <!-- <enum value="0x8439"      name="GL_TANGENT_ARRAY_SGIX"/> -->
+            <!-- <enum value="0x843A"      name="GL_BINORMAL_ARRAY_SGIX"/> -->
+            <!-- <enum value="0x843B"      name="GL_CURRENT_TANGENT_SGIX"/> -->
+            <!-- <enum value="0x843C"      name="GL_CURRENT_BINORMAL_SGIX"/> -->
+            <!-- <enum value="0x843D"      name="GL_FRAGMENT_LIGHT_SPACE_SGIX"/> -->
+            <!-- <enum value="0x843E"      name="GL_TANGENT_ARRAY_TYPE_SGIX"/> -->
+            <!-- <enum value="0x843F"      name="GL_TANGENT_ARRAY_STRIDE_SGIX"/> -->
+            <!-- <enum value="0x8440"      name="GL_TANGENT_ARRAY_COUNT_SGIX"/> -->
+            <!-- <enum value="0x8441"      name="GL_BINORMAL_ARRAY_TYPE_SGIX"/> -->
+            <!-- <enum value="0x8442"      name="GL_BINORMAL_ARRAY_STRIDE_SGIX"/> -->
+            <!-- <enum value="0x8443"      name="GL_BINORMAL_ARRAY_COUNT_SGIX"/> -->
+            <!-- <enum value="0x8444"      name="GL_TANGENT_ARRAY_POINTER_SGIX"/> -->
+            <!-- <enum value="0x8445"      name="GL_BINORMAL_ARRAY_POINTER_SGIX"/> -->
+            <!-- <enum value="0x8446"      name="GL_MAP1_TANGENT_SGIX"/> -->
+            <!-- <enum value="0x8447"      name="GL_MAP2_TANGENT_SGIX"/> -->
+            <!-- <enum value="0x8448"      name="GL_MAP1_BINORMAL_SGIX"/> -->
+            <!-- <enum value="0x8449"      name="GL_MAP2_BINORMAL_SGIX"/> -->
+        <enum value="0x8439" name="GL_TANGENT_ARRAY_EXT"/>
+        <enum value="0x843A" name="GL_BINORMAL_ARRAY_EXT"/>
+        <enum value="0x843B" name="GL_CURRENT_TANGENT_EXT"/>
+        <enum value="0x843C" name="GL_CURRENT_BINORMAL_EXT"/>
+            <unused start="0x844D" vendor="SGI"/>
+        <enum value="0x843E" name="GL_TANGENT_ARRAY_TYPE_EXT"/>
+        <enum value="0x843F" name="GL_TANGENT_ARRAY_STRIDE_EXT"/>
+        <enum value="0x8440" name="GL_BINORMAL_ARRAY_TYPE_EXT"/>
+        <enum value="0x8441" name="GL_BINORMAL_ARRAY_STRIDE_EXT"/>
+        <enum value="0x8442" name="GL_TANGENT_ARRAY_POINTER_EXT"/>
+        <enum value="0x8443" name="GL_BINORMAL_ARRAY_POINTER_EXT"/>
+        <enum value="0x8444" name="GL_MAP1_TANGENT_EXT"/>
+        <enum value="0x8445" name="GL_MAP2_TANGENT_EXT"/>
+        <enum value="0x8446" name="GL_MAP1_BINORMAL_EXT"/>
+        <enum value="0x8447" name="GL_MAP2_BINORMAL_EXT"/>
+            <unused start="0x8448" end="0x8449" comment="Incomplete extension SGIX_fragment_lighting"/>
+            <unused start="0x844A" end="0x844C" comment="Incomplete extension SGIX_bali_timer_instruments"/>
+            <!-- <enum value="0x844A" name="GL_BALI_GEOM_TIMER_INSTRUMENT_SGIX"/> -->
+            <!-- <enum value="0x844B" name="GL_BALI_RASTER_TIMER_INSTRUMENT_SGIX"/> -->
+            <!-- <enum value="0x844C" name="GL_BALI_INSTRUMENT_TIME_UNIT_SGIX"/> -->
+        <enum value="0x844D" name="GL_NEAREST_CLIPMAP_NEAREST_SGIX"/>
+        <enum value="0x844E" name="GL_NEAREST_CLIPMAP_LINEAR_SGIX"/>
+        <enum value="0x844F" name="GL_LINEAR_CLIPMAP_NEAREST_SGIX"/>
+            <!-- 0x8450-0x845F range brokered for Id Software -->
+        <enum value="0x8450" name="GL_FOG_COORDINATE_SOURCE"/>
+        <enum value="0x8450" name="GL_FOG_COORDINATE_SOURCE_EXT"/>
+        <enum value="0x8450" name="GL_FOG_COORD_SRC" alias="GL_FOG_COORDINATE_SOURCE"/>
+        <enum value="0x8451" name="GL_FOG_COORDINATE"/>
+        <enum value="0x8451" name="GL_FOG_COORD" alias="GL_FOG_COORDINATE"/>
+        <enum value="0x8451" name="GL_FOG_COORDINATE_EXT"/>
+        <enum value="0x8452" name="GL_FRAGMENT_DEPTH"/>
+        <enum value="0x8452" name="GL_FRAGMENT_DEPTH_EXT"/>
+        <enum value="0x8453" name="GL_CURRENT_FOG_COORDINATE"/>
+        <enum value="0x8453" name="GL_CURRENT_FOG_COORD" alias="GL_CURRENT_FOG_COORDINATE"/>
+        <enum value="0x8453" name="GL_CURRENT_FOG_COORDINATE_EXT"/>
+        <enum value="0x8454" name="GL_FOG_COORDINATE_ARRAY_TYPE"/>
+        <enum value="0x8454" name="GL_FOG_COORDINATE_ARRAY_TYPE_EXT"/>
+        <enum value="0x8454" name="GL_FOG_COORD_ARRAY_TYPE" alias="GL_FOG_COORDINATE_ARRAY_TYPE"/>
+        <enum value="0x8455" name="GL_FOG_COORDINATE_ARRAY_STRIDE"/>
+        <enum value="0x8455" name="GL_FOG_COORDINATE_ARRAY_STRIDE_EXT"/>
+        <enum value="0x8455" name="GL_FOG_COORD_ARRAY_STRIDE" alias="GL_FOG_COORDINATE_ARRAY_STRIDE"/>
+        <enum value="0x8456" name="GL_FOG_COORDINATE_ARRAY_POINTER"/>
+        <enum value="0x8456" name="GL_FOG_COORDINATE_ARRAY_POINTER_EXT"/>
+        <enum value="0x8456" name="GL_FOG_COORD_ARRAY_POINTER" alias="GL_FOG_COORDINATE_ARRAY_POINTER"/>
+        <enum value="0x8457" name="GL_FOG_COORDINATE_ARRAY"/>
+        <enum value="0x8457" name="GL_FOG_COORDINATE_ARRAY_EXT"/>
+        <enum value="0x8457" name="GL_FOG_COORD_ARRAY" alias="GL_FOG_COORDINATE_ARRAY"/>
+        <enum value="0x8458" name="GL_COLOR_SUM"/>
+        <enum value="0x8458" name="GL_COLOR_SUM_ARB"/>
+        <enum value="0x8458" name="GL_COLOR_SUM_EXT"/>
+        <enum value="0x8459" name="GL_CURRENT_SECONDARY_COLOR"/>
+        <enum value="0x8459" name="GL_CURRENT_SECONDARY_COLOR_EXT"/>
+        <enum value="0x845A" name="GL_SECONDARY_COLOR_ARRAY_SIZE"/>
+        <enum value="0x845A" name="GL_SECONDARY_COLOR_ARRAY_SIZE_EXT"/>
+        <enum value="0x845B" name="GL_SECONDARY_COLOR_ARRAY_TYPE"/>
+        <enum value="0x845B" name="GL_SECONDARY_COLOR_ARRAY_TYPE_EXT"/>
+        <enum value="0x845C" name="GL_SECONDARY_COLOR_ARRAY_STRIDE"/>
+        <enum value="0x845C" name="GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT"/>
+        <enum value="0x845D" name="GL_SECONDARY_COLOR_ARRAY_POINTER"/>
+        <enum value="0x845D" name="GL_SECONDARY_COLOR_ARRAY_POINTER_EXT"/>
+        <enum value="0x845E" name="GL_SECONDARY_COLOR_ARRAY"/>
+        <enum value="0x845E" name="GL_SECONDARY_COLOR_ARRAY_EXT"/>
+        <enum value="0x845F" name="GL_CURRENT_RASTER_SECONDARY_COLOR"/>
+            <unused start="0x8460" end="0x846B" comment="Incomplete extension SGIX_icc_texture"/>
+            <!-- <enum value="0x8460" name="GL_RGB_ICC_SGIX"/> -->
+            <!-- <enum value="0x8461" name="GL_RGBA_ICC_SGIX"/> -->
+            <!-- <enum value="0x8462" name="GL_ALPHA_ICC_SGIX"/> -->
+            <!-- <enum value="0x8463" name="GL_LUMINANCE_ICC_SGIX"/> -->
+            <!-- <enum value="0x8464" name="GL_INTENSITY_ICC_SGIX"/> -->
+            <!-- <enum value="0x8465" name="GL_LUMINANCE_ALPHA_ICC_SGIX"/> -->
+            <!-- <enum value="0x8466" name="GL_R5_G6_B5_ICC_SGIX"/> -->
+            <!-- <enum value="0x8467" name="GL_R5_G6_B5_A8_ICC_SGIX"/> -->
+            <!-- <enum value="0x8468" name="GL_ALPHA16_ICC_SGIX"/> -->
+            <!-- <enum value="0x8469" name="GL_LUMINANCE16_ICC_SGIX"/> -->
+            <!-- <enum value="0x846A" name="GL_INTENSITY16_ICC_SGIX"/> -->
+            <!-- <enum value="0x846B" name="GL_LUMINANCE16_ALPHA8_ICC_SGIX"/> -->
+            <unused start="0x846C" vendor="SGI"/>
+        <enum value="0x846D" name="GL_ALIASED_POINT_SIZE_RANGE"/>
+        <enum value="0x846E" name="GL_ALIASED_LINE_WIDTH_RANGE"/>
+            <unused start="0x846F" vendor="SGI"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8470" end="0x848F" vendor="AMD">
+            <unused start="0x8470" end="0x848F" vendor="AMD"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8490" end="0x849F" vendor="REND">
+        <enum value="0x8490" name="GL_SCREEN_COORDINATES_REND"/>
+        <enum value="0x8491" name="GL_INVERTED_SCREEN_W_REND"/>
+            <unused start="0x8492" end="0x849F" vendor="REND"/>
+    </enums>
+
+    <enums namespace="GL" start="0x84A0" end="0x84BF" vendor="AMD">
+            <unused start="0x84A0" end="0x84BF" vendor="AMD"/>
+    </enums>
+
+    <enums namespace="GL" start="0x84C0" end="0x84EF" vendor="ARB">
+        <enum value="0x84C0" name="GL_TEXTURE0"/>
+        <enum value="0x84C0" name="GL_TEXTURE0_ARB"/>
+        <enum value="0x84C1" name="GL_TEXTURE1"/>
+        <enum value="0x84C1" name="GL_TEXTURE1_ARB"/>
+        <enum value="0x84C2" name="GL_TEXTURE2"/>
+        <enum value="0x84C2" name="GL_TEXTURE2_ARB"/>
+        <enum value="0x84C3" name="GL_TEXTURE3"/>
+        <enum value="0x84C3" name="GL_TEXTURE3_ARB"/>
+        <enum value="0x84C4" name="GL_TEXTURE4"/>
+        <enum value="0x84C4" name="GL_TEXTURE4_ARB"/>
+        <enum value="0x84C5" name="GL_TEXTURE5"/>
+        <enum value="0x84C5" name="GL_TEXTURE5_ARB"/>
+        <enum value="0x84C6" name="GL_TEXTURE6"/>
+        <enum value="0x84C6" name="GL_TEXTURE6_ARB"/>
+        <enum value="0x84C7" name="GL_TEXTURE7"/>
+        <enum value="0x84C7" name="GL_TEXTURE7_ARB"/>
+        <enum value="0x84C8" name="GL_TEXTURE8"/>
+        <enum value="0x84C8" name="GL_TEXTURE8_ARB"/>
+        <enum value="0x84C9" name="GL_TEXTURE9"/>
+        <enum value="0x84C9" name="GL_TEXTURE9_ARB"/>
+        <enum value="0x84CA" name="GL_TEXTURE10"/>
+        <enum value="0x84CA" name="GL_TEXTURE10_ARB"/>
+        <enum value="0x84CB" name="GL_TEXTURE11"/>
+        <enum value="0x84CB" name="GL_TEXTURE11_ARB"/>
+        <enum value="0x84CC" name="GL_TEXTURE12"/>
+        <enum value="0x84CC" name="GL_TEXTURE12_ARB"/>
+        <enum value="0x84CD" name="GL_TEXTURE13"/>
+        <enum value="0x84CD" name="GL_TEXTURE13_ARB"/>
+        <enum value="0x84CE" name="GL_TEXTURE14"/>
+        <enum value="0x84CE" name="GL_TEXTURE14_ARB"/>
+        <enum value="0x84CF" name="GL_TEXTURE15"/>
+        <enum value="0x84CF" name="GL_TEXTURE15_ARB"/>
+        <enum value="0x84D0" name="GL_TEXTURE16"/>
+        <enum value="0x84D0" name="GL_TEXTURE16_ARB"/>
+        <enum value="0x84D1" name="GL_TEXTURE17"/>
+        <enum value="0x84D1" name="GL_TEXTURE17_ARB"/>
+        <enum value="0x84D2" name="GL_TEXTURE18"/>
+        <enum value="0x84D2" name="GL_TEXTURE18_ARB"/>
+        <enum value="0x84D3" name="GL_TEXTURE19"/>
+        <enum value="0x84D3" name="GL_TEXTURE19_ARB"/>
+        <enum value="0x84D4" name="GL_TEXTURE20"/>
+        <enum value="0x84D4" name="GL_TEXTURE20_ARB"/>
+        <enum value="0x84D5" name="GL_TEXTURE21"/>
+        <enum value="0x84D5" name="GL_TEXTURE21_ARB"/>
+        <enum value="0x84D6" name="GL_TEXTURE22"/>
+        <enum value="0x84D6" name="GL_TEXTURE22_ARB"/>
+        <enum value="0x84D7" name="GL_TEXTURE23"/>
+        <enum value="0x84D7" name="GL_TEXTURE23_ARB"/>
+        <enum value="0x84D8" name="GL_TEXTURE24"/>
+        <enum value="0x84D8" name="GL_TEXTURE24_ARB"/>
+        <enum value="0x84D9" name="GL_TEXTURE25"/>
+        <enum value="0x84D9" name="GL_TEXTURE25_ARB"/>
+        <enum value="0x84DA" name="GL_TEXTURE26"/>
+        <enum value="0x84DA" name="GL_TEXTURE26_ARB"/>
+        <enum value="0x84DB" name="GL_TEXTURE27"/>
+        <enum value="0x84DB" name="GL_TEXTURE27_ARB"/>
+        <enum value="0x84DC" name="GL_TEXTURE28"/>
+        <enum value="0x84DC" name="GL_TEXTURE28_ARB"/>
+        <enum value="0x84DD" name="GL_TEXTURE29"/>
+        <enum value="0x84DD" name="GL_TEXTURE29_ARB"/>
+        <enum value="0x84DE" name="GL_TEXTURE30"/>
+        <enum value="0x84DE" name="GL_TEXTURE30_ARB"/>
+        <enum value="0x84DF" name="GL_TEXTURE31"/>
+        <enum value="0x84DF" name="GL_TEXTURE31_ARB"/>
+        <enum value="0x84E0" name="GL_ACTIVE_TEXTURE"/>
+        <enum value="0x84E0" name="GL_ACTIVE_TEXTURE_ARB"/>
+        <enum value="0x84E1" name="GL_CLIENT_ACTIVE_TEXTURE"/>
+        <enum value="0x84E1" name="GL_CLIENT_ACTIVE_TEXTURE_ARB"/>
+        <enum value="0x84E2" name="GL_MAX_TEXTURE_UNITS"/>
+        <enum value="0x84E2" name="GL_MAX_TEXTURE_UNITS_ARB"/>
+        <enum value="0x84E3" name="GL_TRANSPOSE_MODELVIEW_MATRIX"/>
+        <enum value="0x84E3" name="GL_TRANSPOSE_MODELVIEW_MATRIX_ARB"/>
+        <enum value="0x84E3" name="GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV"/>
+        <enum value="0x84E4" name="GL_TRANSPOSE_PROJECTION_MATRIX"/>
+        <enum value="0x84E4" name="GL_TRANSPOSE_PROJECTION_MATRIX_ARB"/>
+        <enum value="0x84E4" name="GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV"/>
+        <enum value="0x84E5" name="GL_TRANSPOSE_TEXTURE_MATRIX"/>
+        <enum value="0x84E5" name="GL_TRANSPOSE_TEXTURE_MATRIX_ARB"/>
+        <enum value="0x84E6" name="GL_TRANSPOSE_COLOR_MATRIX"/>
+        <enum value="0x84E6" name="GL_TRANSPOSE_COLOR_MATRIX_ARB"/>
+        <enum value="0x84E7" name="GL_SUBTRACT"/>
+        <enum value="0x84E7" name="GL_SUBTRACT_ARB"/>
+        <enum value="0x84E8" name="GL_MAX_RENDERBUFFER_SIZE"/>
+        <enum value="0x84E8" name="GL_MAX_RENDERBUFFER_SIZE_EXT"/>
+        <enum value="0x84E8" name="GL_MAX_RENDERBUFFER_SIZE_OES"/>
+        <enum value="0x84E9" name="GL_COMPRESSED_ALPHA"/>
+        <enum value="0x84E9" name="GL_COMPRESSED_ALPHA_ARB"/>
+        <enum value="0x84EA" name="GL_COMPRESSED_LUMINANCE"/>
+        <enum value="0x84EA" name="GL_COMPRESSED_LUMINANCE_ARB"/>
+        <enum value="0x84EB" name="GL_COMPRESSED_LUMINANCE_ALPHA"/>
+        <enum value="0x84EB" name="GL_COMPRESSED_LUMINANCE_ALPHA_ARB"/>
+        <enum value="0x84EC" name="GL_COMPRESSED_INTENSITY"/>
+        <enum value="0x84EC" name="GL_COMPRESSED_INTENSITY_ARB"/>
+        <enum value="0x84ED" name="GL_COMPRESSED_RGB"/>
+        <enum value="0x84ED" name="GL_COMPRESSED_RGB_ARB"/>
+        <enum value="0x84EE" name="GL_COMPRESSED_RGBA"/>
+        <enum value="0x84EE" name="GL_COMPRESSED_RGBA_ARB"/>
+        <enum value="0x84EF" name="GL_TEXTURE_COMPRESSION_HINT"/>
+        <enum value="0x84EF" name="GL_TEXTURE_COMPRESSION_HINT_ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x84F0" end="0x855F" vendor="NV">
+        <enum value="0x84F0" name="GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+        <enum value="0x84F1" name="GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+        <enum value="0x84F2" name="GL_ALL_COMPLETED_NV"/>
+        <enum value="0x84F3" name="GL_FENCE_STATUS_NV"/>
+        <enum value="0x84F4" name="GL_FENCE_CONDITION_NV"/>
+        <enum value="0x84F5" name="GL_TEXTURE_RECTANGLE"/>
+        <enum value="0x84F5" name="GL_TEXTURE_RECTANGLE_ARB"/>
+        <enum value="0x84F5" name="GL_TEXTURE_RECTANGLE_NV"/>
+        <enum value="0x84F6" name="GL_TEXTURE_BINDING_RECTANGLE"/>
+        <enum value="0x84F6" name="GL_TEXTURE_BINDING_RECTANGLE_ARB"/>
+        <enum value="0x84F6" name="GL_TEXTURE_BINDING_RECTANGLE_NV"/>
+        <enum value="0x84F7" name="GL_PROXY_TEXTURE_RECTANGLE"/>
+        <enum value="0x84F7" name="GL_PROXY_TEXTURE_RECTANGLE_ARB"/>
+        <enum value="0x84F7" name="GL_PROXY_TEXTURE_RECTANGLE_NV"/>
+        <enum value="0x84F8" name="GL_MAX_RECTANGLE_TEXTURE_SIZE"/>
+        <enum value="0x84F8" name="GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB"/>
+        <enum value="0x84F8" name="GL_MAX_RECTANGLE_TEXTURE_SIZE_NV"/>
+        <enum value="0x84F9" name="GL_DEPTH_STENCIL"/>
+        <enum value="0x84F9" name="GL_DEPTH_STENCIL_EXT"/>
+        <enum value="0x84F9" name="GL_DEPTH_STENCIL_NV"/>
+        <enum value="0x84F9" name="GL_DEPTH_STENCIL_OES"/>
+        <enum value="0x84FA" name="GL_UNSIGNED_INT_24_8"/>
+        <enum value="0x84FA" name="GL_UNSIGNED_INT_24_8_EXT"/>
+        <enum value="0x84FA" name="GL_UNSIGNED_INT_24_8_NV"/>
+        <enum value="0x84FA" name="GL_UNSIGNED_INT_24_8_OES"/>
+            <unused start="0x84FB" end="0x84FC" vendor="NV"/>
+        <enum value="0x84FD" name="GL_MAX_TEXTURE_LOD_BIAS"/>
+        <enum value="0x84FD" name="GL_MAX_TEXTURE_LOD_BIAS_EXT"/>
+        <enum value="0x84FE" name="GL_TEXTURE_MAX_ANISOTROPY_EXT"/>
+        <enum value="0x84FF" name="GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT"/>
+        <enum value="0x8500" name="GL_TEXTURE_FILTER_CONTROL"/>
+        <enum value="0x8500" name="GL_TEXTURE_FILTER_CONTROL_EXT"/>
+        <enum value="0x8501" name="GL_TEXTURE_LOD_BIAS"/>
+        <enum value="0x8501" name="GL_TEXTURE_LOD_BIAS_EXT"/>
+        <enum value="0x8502" name="GL_MODELVIEW1_STACK_DEPTH_EXT"/>
+        <enum value="0x8503" name="GL_COMBINE4_NV"/>
+        <enum value="0x8504" name="GL_MAX_SHININESS_NV"/>
+        <enum value="0x8505" name="GL_MAX_SPOT_EXPONENT_NV"/>
+        <enum value="0x8506" name="GL_MODELVIEW1_MATRIX_EXT"/>
+        <enum value="0x8507" name="GL_INCR_WRAP"/>
+        <enum value="0x8507" name="GL_INCR_WRAP_EXT"/>
+        <enum value="0x8507" name="GL_INCR_WRAP_OES"/>
+        <enum value="0x8508" name="GL_DECR_WRAP"/>
+        <enum value="0x8508" name="GL_DECR_WRAP_EXT"/>
+        <enum value="0x8508" name="GL_DECR_WRAP_OES"/>
+        <enum value="0x8509" name="GL_VERTEX_WEIGHTING_EXT"/>
+        <enum value="0x850A" name="GL_MODELVIEW1_ARB"/>
+        <enum value="0x850A" name="GL_MODELVIEW1_EXT"/>
+        <enum value="0x850B" name="GL_CURRENT_VERTEX_WEIGHT_EXT"/>
+        <enum value="0x850C" name="GL_VERTEX_WEIGHT_ARRAY_EXT"/>
+        <enum value="0x850D" name="GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT"/>
+        <enum value="0x850E" name="GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT"/>
+        <enum value="0x850F" name="GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT"/>
+        <enum value="0x8510" name="GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT"/>
+        <enum value="0x8511" name="GL_NORMAL_MAP"/>
+        <enum value="0x8511" name="GL_NORMAL_MAP_ARB"/>
+        <enum value="0x8511" name="GL_NORMAL_MAP_EXT"/>
+        <enum value="0x8511" name="GL_NORMAL_MAP_NV"/>
+        <enum value="0x8511" name="GL_NORMAL_MAP_OES"/>
+        <enum value="0x8512" name="GL_REFLECTION_MAP"/>
+        <enum value="0x8512" name="GL_REFLECTION_MAP_ARB"/>
+        <enum value="0x8512" name="GL_REFLECTION_MAP_EXT"/>
+        <enum value="0x8512" name="GL_REFLECTION_MAP_NV"/>
+        <enum value="0x8512" name="GL_REFLECTION_MAP_OES"/>
+        <enum value="0x8513" name="GL_TEXTURE_CUBE_MAP"/>
+        <enum value="0x8513" name="GL_TEXTURE_CUBE_MAP_ARB"/>
+        <enum value="0x8513" name="GL_TEXTURE_CUBE_MAP_EXT"/>
+        <enum value="0x8513" name="GL_TEXTURE_CUBE_MAP_OES"/>
+        <enum value="0x8514" name="GL_TEXTURE_BINDING_CUBE_MAP"/>
+        <enum value="0x8514" name="GL_TEXTURE_BINDING_CUBE_MAP_ARB"/>
+        <enum value="0x8514" name="GL_TEXTURE_BINDING_CUBE_MAP_EXT"/>
+        <enum value="0x8514" name="GL_TEXTURE_BINDING_CUBE_MAP_OES"/>
+        <enum value="0x8515" name="GL_TEXTURE_CUBE_MAP_POSITIVE_X"/>
+        <enum value="0x8515" name="GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB"/>
+        <enum value="0x8515" name="GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT"/>
+        <enum value="0x8515" name="GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES"/>
+        <enum value="0x8516" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X"/>
+        <enum value="0x8516" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB"/>
+        <enum value="0x8516" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT"/>
+        <enum value="0x8516" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES"/>
+        <enum value="0x8517" name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y"/>
+        <enum value="0x8517" name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB"/>
+        <enum value="0x8517" name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT"/>
+        <enum value="0x8517" name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES"/>
+        <enum value="0x8518" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y"/>
+        <enum value="0x8518" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB"/>
+        <enum value="0x8518" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT"/>
+        <enum value="0x8518" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES"/>
+        <enum value="0x8519" name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z"/>
+        <enum value="0x8519" name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB"/>
+        <enum value="0x8519" name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT"/>
+        <enum value="0x8519" name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES"/>
+        <enum value="0x851A" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"/>
+        <enum value="0x851A" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB"/>
+        <enum value="0x851A" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT"/>
+        <enum value="0x851A" name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES"/>
+        <enum value="0x851B" name="GL_PROXY_TEXTURE_CUBE_MAP"/>
+        <enum value="0x851B" name="GL_PROXY_TEXTURE_CUBE_MAP_ARB"/>
+        <enum value="0x851B" name="GL_PROXY_TEXTURE_CUBE_MAP_EXT"/>
+        <enum value="0x851C" name="GL_MAX_CUBE_MAP_TEXTURE_SIZE"/>
+        <enum value="0x851C" name="GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB"/>
+        <enum value="0x851C" name="GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT"/>
+        <enum value="0x851C" name="GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES"/>
+        <enum value="0x851D" name="GL_VERTEX_ARRAY_RANGE_APPLE"/>
+        <enum value="0x851D" name="GL_VERTEX_ARRAY_RANGE_NV"/>
+        <enum value="0x851E" name="GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE"/>
+        <enum value="0x851E" name="GL_VERTEX_ARRAY_RANGE_LENGTH_NV"/>
+        <enum value="0x851F" name="GL_VERTEX_ARRAY_RANGE_VALID_NV"/>
+        <enum value="0x851F" name="GL_VERTEX_ARRAY_STORAGE_HINT_APPLE"/>
+        <enum value="0x8520" name="GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV"/>
+        <enum value="0x8521" name="GL_VERTEX_ARRAY_RANGE_POINTER_APPLE"/>
+        <enum value="0x8521" name="GL_VERTEX_ARRAY_RANGE_POINTER_NV"/>
+        <enum value="0x8522" name="GL_REGISTER_COMBINERS_NV"/>
+        <enum value="0x8523" name="GL_VARIABLE_A_NV"/>
+        <enum value="0x8524" name="GL_VARIABLE_B_NV"/>
+        <enum value="0x8525" name="GL_VARIABLE_C_NV"/>
+        <enum value="0x8526" name="GL_VARIABLE_D_NV"/>
+        <enum value="0x8527" name="GL_VARIABLE_E_NV"/>
+        <enum value="0x8528" name="GL_VARIABLE_F_NV"/>
+        <enum value="0x8529" name="GL_VARIABLE_G_NV"/>
+        <enum value="0x852A" name="GL_CONSTANT_COLOR0_NV"/>
+        <enum value="0x852B" name="GL_CONSTANT_COLOR1_NV"/>
+        <enum value="0x852C" name="GL_PRIMARY_COLOR_NV"/>
+        <enum value="0x852D" name="GL_SECONDARY_COLOR_NV"/>
+        <enum value="0x852E" name="GL_SPARE0_NV"/>
+        <enum value="0x852F" name="GL_SPARE1_NV"/>
+        <enum value="0x8530" name="GL_DISCARD_NV"/>
+        <enum value="0x8531" name="GL_E_TIMES_F_NV"/>
+        <enum value="0x8532" name="GL_SPARE0_PLUS_SECONDARY_COLOR_NV"/>
+        <enum value="0x8533" name="GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV"/>
+        <enum value="0x8534" name="GL_MULTISAMPLE_FILTER_HINT_NV"/>
+        <enum value="0x8535" name="GL_PER_STAGE_CONSTANTS_NV"/>
+        <enum value="0x8536" name="GL_UNSIGNED_IDENTITY_NV"/>
+        <enum value="0x8537" name="GL_UNSIGNED_INVERT_NV"/>
+        <enum value="0x8538" name="GL_EXPAND_NORMAL_NV"/>
+        <enum value="0x8539" name="GL_EXPAND_NEGATE_NV"/>
+        <enum value="0x853A" name="GL_HALF_BIAS_NORMAL_NV"/>
+        <enum value="0x853B" name="GL_HALF_BIAS_NEGATE_NV"/>
+        <enum value="0x853C" name="GL_SIGNED_IDENTITY_NV"/>
+        <enum value="0x853D" name="GL_SIGNED_NEGATE_NV"/>
+        <enum value="0x853E" name="GL_SCALE_BY_TWO_NV"/>
+        <enum value="0x853F" name="GL_SCALE_BY_FOUR_NV"/>
+        <enum value="0x8540" name="GL_SCALE_BY_ONE_HALF_NV"/>
+        <enum value="0x8541" name="GL_BIAS_BY_NEGATIVE_ONE_HALF_NV"/>
+        <enum value="0x8542" name="GL_COMBINER_INPUT_NV"/>
+        <enum value="0x8543" name="GL_COMBINER_MAPPING_NV"/>
+        <enum value="0x8544" name="GL_COMBINER_COMPONENT_USAGE_NV"/>
+        <enum value="0x8545" name="GL_COMBINER_AB_DOT_PRODUCT_NV"/>
+        <enum value="0x8546" name="GL_COMBINER_CD_DOT_PRODUCT_NV"/>
+        <enum value="0x8547" name="GL_COMBINER_MUX_SUM_NV"/>
+        <enum value="0x8548" name="GL_COMBINER_SCALE_NV"/>
+        <enum value="0x8549" name="GL_COMBINER_BIAS_NV"/>
+        <enum value="0x854A" name="GL_COMBINER_AB_OUTPUT_NV"/>
+        <enum value="0x854B" name="GL_COMBINER_CD_OUTPUT_NV"/>
+        <enum value="0x854C" name="GL_COMBINER_SUM_OUTPUT_NV"/>
+        <enum value="0x854D" name="GL_MAX_GENERAL_COMBINERS_NV"/>
+        <enum value="0x854E" name="GL_NUM_GENERAL_COMBINERS_NV"/>
+        <enum value="0x854F" name="GL_COLOR_SUM_CLAMP_NV"/>
+        <enum value="0x8550" name="GL_COMBINER0_NV"/>
+        <enum value="0x8551" name="GL_COMBINER1_NV"/>
+        <enum value="0x8552" name="GL_COMBINER2_NV"/>
+        <enum value="0x8553" name="GL_COMBINER3_NV"/>
+        <enum value="0x8554" name="GL_COMBINER4_NV"/>
+        <enum value="0x8555" name="GL_COMBINER5_NV"/>
+        <enum value="0x8556" name="GL_COMBINER6_NV"/>
+        <enum value="0x8557" name="GL_COMBINER7_NV"/>
+        <enum value="0x8558" name="GL_PRIMITIVE_RESTART_NV"/>
+        <enum value="0x8559" name="GL_PRIMITIVE_RESTART_INDEX_NV"/>
+        <enum value="0x855A" name="GL_FOG_DISTANCE_MODE_NV"/>
+        <enum value="0x855B" name="GL_EYE_RADIAL_NV"/>
+        <enum value="0x855C" name="GL_EYE_PLANE_ABSOLUTE_NV"/>
+        <enum value="0x855D" name="GL_EMBOSS_LIGHT_NV"/>
+        <enum value="0x855E" name="GL_EMBOSS_CONSTANT_NV"/>
+        <enum value="0x855F" name="GL_EMBOSS_MAP_NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8560" end="0x856F" vendor="ZiiLabs">
+        <enum value="0x8560" name="GL_RED_MIN_CLAMP_INGR"/>
+        <enum value="0x8561" name="GL_GREEN_MIN_CLAMP_INGR"/>
+        <enum value="0x8562" name="GL_BLUE_MIN_CLAMP_INGR"/>
+        <enum value="0x8563" name="GL_ALPHA_MIN_CLAMP_INGR"/>
+        <enum value="0x8564" name="GL_RED_MAX_CLAMP_INGR"/>
+        <enum value="0x8565" name="GL_GREEN_MAX_CLAMP_INGR"/>
+        <enum value="0x8566" name="GL_BLUE_MAX_CLAMP_INGR"/>
+        <enum value="0x8567" name="GL_ALPHA_MAX_CLAMP_INGR"/>
+        <enum value="0x8568" name="GL_INTERLACE_READ_INGR"/>
+            <unused start="0x8569" end="0x856F" vendor="ZiiLabs"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8570" end="0x859F" group="RegisterCombinerPname" vendor="AMD/NV">
+        <enum value="0x8570" name="GL_COMBINE"/>
+        <enum value="0x8570" name="GL_COMBINE_ARB"/>
+        <enum value="0x8570" name="GL_COMBINE_EXT"/>
+        <enum value="0x8571" name="GL_COMBINE_RGB"/>
+        <enum value="0x8571" name="GL_COMBINE_RGB_ARB"/>
+        <enum value="0x8571" name="GL_COMBINE_RGB_EXT"/>
+        <enum value="0x8572" name="GL_COMBINE_ALPHA"/>
+        <enum value="0x8572" name="GL_COMBINE_ALPHA_ARB"/>
+        <enum value="0x8572" name="GL_COMBINE_ALPHA_EXT"/>
+        <enum value="0x8573" name="GL_RGB_SCALE"/>
+        <enum value="0x8573" name="GL_RGB_SCALE_ARB"/>
+        <enum value="0x8573" name="GL_RGB_SCALE_EXT"/>
+        <enum value="0x8574" name="GL_ADD_SIGNED"/>
+        <enum value="0x8574" name="GL_ADD_SIGNED_ARB"/>
+        <enum value="0x8574" name="GL_ADD_SIGNED_EXT"/>
+        <enum value="0x8575" name="GL_INTERPOLATE"/>
+        <enum value="0x8575" name="GL_INTERPOLATE_ARB"/>
+        <enum value="0x8575" name="GL_INTERPOLATE_EXT"/>
+        <enum value="0x8576" name="GL_CONSTANT"/>
+        <enum value="0x8576" name="GL_CONSTANT_ARB"/>
+        <enum value="0x8576" name="GL_CONSTANT_EXT"/>
+        <enum value="0x8576" name="GL_CONSTANT_NV"/>
+        <enum value="0x8577" name="GL_PRIMARY_COLOR"/>
+        <enum value="0x8577" name="GL_PRIMARY_COLOR_ARB"/>
+        <enum value="0x8577" name="GL_PRIMARY_COLOR_EXT"/>
+        <enum value="0x8578" name="GL_PREVIOUS"/>
+        <enum value="0x8578" name="GL_PREVIOUS_ARB"/>
+        <enum value="0x8578" name="GL_PREVIOUS_EXT"/>
+            <unused start="0x8579" end="0x857F" comment="Additional combiner enums only"/>
+        <enum value="0x8580" name="GL_SOURCE0_RGB"/>
+        <enum value="0x8580" name="GL_SOURCE0_RGB_ARB"/>
+        <enum value="0x8580" name="GL_SOURCE0_RGB_EXT"/>
+        <enum value="0x8580" name="GL_SRC0_RGB" alias="GL_SOURCE0_RGB"/>
+        <enum value="0x8581" name="GL_SOURCE1_RGB"/>
+        <enum value="0x8581" name="GL_SOURCE1_RGB_ARB"/>
+        <enum value="0x8581" name="GL_SOURCE1_RGB_EXT"/>
+        <enum value="0x8581" name="GL_SRC1_RGB" alias="GL_SOURCE1_RGB"/>
+        <enum value="0x8582" name="GL_SOURCE2_RGB"/>
+        <enum value="0x8582" name="GL_SOURCE2_RGB_ARB"/>
+        <enum value="0x8582" name="GL_SOURCE2_RGB_EXT"/>
+        <enum value="0x8582" name="GL_SRC2_RGB" alias="GL_SOURCE2_RGB"/>
+        <enum value="0x8583" name="GL_SOURCE3_RGB_NV"/>
+            <unused start="0x8584" end="0x8587" comment="Additional combiner enums only"/>
+        <enum value="0x8588" name="GL_SOURCE0_ALPHA"/>
+        <enum value="0x8588" name="GL_SOURCE0_ALPHA_ARB"/>
+        <enum value="0x8588" name="GL_SOURCE0_ALPHA_EXT"/>
+        <enum value="0x8588" name="GL_SRC0_ALPHA" alias="GL_SOURCE0_ALPHA"/>
+        <enum value="0x8589" name="GL_SOURCE1_ALPHA"/>
+        <enum value="0x8589" name="GL_SOURCE1_ALPHA_ARB"/>
+        <enum value="0x8589" name="GL_SOURCE1_ALPHA_EXT"/>
+        <enum value="0x8589" name="GL_SRC1_ALPHA" alias="GL_SOURCE1_ALPHA"/>
+        <enum value="0x8589" name="GL_SRC1_ALPHA_EXT"/>
+        <enum value="0x858A" name="GL_SOURCE2_ALPHA"/>
+        <enum value="0x858A" name="GL_SOURCE2_ALPHA_ARB"/>
+        <enum value="0x858A" name="GL_SOURCE2_ALPHA_EXT"/>
+        <enum value="0x858A" name="GL_SRC2_ALPHA" alias="GL_SOURCE2_ALPHA"/>
+        <enum value="0x858B" name="GL_SOURCE3_ALPHA_NV"/>
+            <unused start="0x858C" end="0x858F" comment="Additional combiner enums only"/>
+        <enum value="0x8590" name="GL_OPERAND0_RGB"/>
+        <enum value="0x8590" name="GL_OPERAND0_RGB_ARB"/>
+        <enum value="0x8590" name="GL_OPERAND0_RGB_EXT"/>
+        <enum value="0x8591" name="GL_OPERAND1_RGB"/>
+        <enum value="0x8591" name="GL_OPERAND1_RGB_ARB"/>
+        <enum value="0x8591" name="GL_OPERAND1_RGB_EXT"/>
+        <enum value="0x8592" name="GL_OPERAND2_RGB"/>
+        <enum value="0x8592" name="GL_OPERAND2_RGB_ARB"/>
+        <enum value="0x8592" name="GL_OPERAND2_RGB_EXT"/>
+        <enum value="0x8593" name="GL_OPERAND3_RGB_NV"/>
+            <unused start="0x8594" end="0x8597" comment="Additional combiner enums only"/>
+        <enum value="0x8598" name="GL_OPERAND0_ALPHA"/>
+        <enum value="0x8598" name="GL_OPERAND0_ALPHA_ARB"/>
+        <enum value="0x8598" name="GL_OPERAND0_ALPHA_EXT"/>
+        <enum value="0x8599" name="GL_OPERAND1_ALPHA"/>
+        <enum value="0x8599" name="GL_OPERAND1_ALPHA_ARB"/>
+        <enum value="0x8599" name="GL_OPERAND1_ALPHA_EXT"/>
+        <enum value="0x859A" name="GL_OPERAND2_ALPHA"/>
+        <enum value="0x859A" name="GL_OPERAND2_ALPHA_ARB"/>
+        <enum value="0x859A" name="GL_OPERAND2_ALPHA_EXT"/>
+        <enum value="0x859B" name="GL_OPERAND3_ALPHA_NV"/>
+            <unused start="0x859C" end="0x859F" comment="Additional combiner enums only"/>
+    </enums>
+
+    <enums namespace="GL" start="0x85A0" end="0x85AF" vendor="SGI">
+        <enum value="0x85A0" name="GL_PACK_SUBSAMPLE_RATE_SGIX"/>
+        <enum value="0x85A1" name="GL_UNPACK_SUBSAMPLE_RATE_SGIX"/>
+        <enum value="0x85A2" name="GL_PIXEL_SUBSAMPLE_4444_SGIX"/>
+        <enum value="0x85A3" name="GL_PIXEL_SUBSAMPLE_2424_SGIX"/>
+        <enum value="0x85A4" name="GL_PIXEL_SUBSAMPLE_4242_SGIX"/>
+            <unused start="0x85A5" end="0x85AD" comment="Incomplete extension SGIS_color_range"/>
+            <!-- <enum value="0x85A5" name="GL_EXTENDED_RANGE_SGIS"/> -->
+            <!-- <enum value="0x85A6" name="GL_MIN_RED_SGIS"/> -->
+            <!-- <enum value="0x85A7" name="GL_MAX_RED_SGIS"/> -->
+            <!-- <enum value="0x85A8" name="GL_MIN_GREEN_SGIS"/> -->
+            <!-- <enum value="0x85A9" name="GL_MAX_GREEN_SGIS"/> -->
+            <!-- <enum value="0x85AA" name="GL_MIN_BLUE_SGIS"/> -->
+            <!-- <enum value="0x85AB" name="GL_MAX_BLUE_SGIS"/> -->
+            <!-- <enum value="0x85AC" name="GL_MIN_ALPHA_SGIS"/> -->
+            <!-- <enum value="0x85AD" name="GL_MAX_ALPHA_SGIS"/> -->
+        <enum value="0x85AE" name="GL_PERTURB_EXT"/>
+        <enum value="0x85AF" name="GL_TEXTURE_NORMAL_EXT"/>
+    </enums>
+
+    <enums namespace="GL" start="0x85B0" end="0x85BF" vendor="APPLE">
+        <enum value="0x85B0" name="GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE"/>
+        <enum value="0x85B1" name="GL_TRANSFORM_HINT_APPLE"/>
+        <enum value="0x85B2" name="GL_UNPACK_CLIENT_STORAGE_APPLE"/>
+        <enum value="0x85B3" name="GL_BUFFER_OBJECT_APPLE"/>
+        <enum value="0x85B4" name="GL_STORAGE_CLIENT_APPLE"/>
+        <enum value="0x85B5" name="GL_VERTEX_ARRAY_BINDING"/>
+        <enum value="0x85B5" name="GL_VERTEX_ARRAY_BINDING_APPLE"/>
+        <enum value="0x85B5" name="GL_VERTEX_ARRAY_BINDING_OES"/>
+            <unused start="0x85B6" vendor="APPLE" comment="Unknown extension (Khronos bug 632)"/>
+            <!-- <enum value="0x85B6" name="GL_TEXTURE_MINIMIZE_STORAGE_APPLE"/> -->
+        <enum value="0x85B7" name="GL_TEXTURE_RANGE_LENGTH_APPLE"/>
+        <enum value="0x85B8" name="GL_TEXTURE_RANGE_POINTER_APPLE"/>
+        <enum value="0x85B9" name="GL_YCBCR_422_APPLE"/>
+        <enum value="0x85BA" name="GL_UNSIGNED_SHORT_8_8_APPLE"/>
+        <enum value="0x85BA" name="GL_UNSIGNED_SHORT_8_8_MESA"/>
+        <enum value="0x85BB" name="GL_UNSIGNED_SHORT_8_8_REV_APPLE"/>
+        <enum value="0x85BB" name="GL_UNSIGNED_SHORT_8_8_REV_MESA"/>
+        <enum value="0x85BC" name="GL_TEXTURE_STORAGE_HINT_APPLE"/>
+        <enum value="0x85BD" name="GL_STORAGE_PRIVATE_APPLE"/>
+        <enum value="0x85BE" name="GL_STORAGE_CACHED_APPLE"/>
+        <enum value="0x85BF" name="GL_STORAGE_SHARED_APPLE"/>
+    </enums>
+
+    <enums namespace="GL" start="0x85C0" end="0x85CF" vendor="SUN">
+        <enum value="0x85C0" name="GL_REPLACEMENT_CODE_ARRAY_SUN"/>
+        <enum value="0x85C1" name="GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN"/>
+        <enum value="0x85C2" name="GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN"/>
+        <enum value="0x85C3" name="GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN"/>
+        <enum value="0x85C4" name="GL_R1UI_V3F_SUN"/>
+        <enum value="0x85C5" name="GL_R1UI_C4UB_V3F_SUN"/>
+        <enum value="0x85C6" name="GL_R1UI_C3F_V3F_SUN"/>
+        <enum value="0x85C7" name="GL_R1UI_N3F_V3F_SUN"/>
+        <enum value="0x85C8" name="GL_R1UI_C4F_N3F_V3F_SUN"/>
+        <enum value="0x85C9" name="GL_R1UI_T2F_V3F_SUN"/>
+        <enum value="0x85CA" name="GL_R1UI_T2F_N3F_V3F_SUN"/>
+        <enum value="0x85CB" name="GL_R1UI_T2F_C4F_N3F_V3F_SUN"/>
+        <enum value="0x85CC" name="GL_SLICE_ACCUM_SUN"/>
+            <unused start="0x85CD" end="0x85CF" vendor="SUN"/>
+    </enums>
+
+    <enums namespace="GL" start="0x85D0" end="0x85DF" vendor="ZiiLabs" comment="3Dlabs private extension for Autodesk">
+            <unused start="0x85D0" end="0x85D1" comment="Unknown 3Dlabs private extension for Autodesk (but we know the enum values)"/>
+            <!-- <enum value="0x85D0" name="GL_FACET_NORMAL_AUTODESK"/> -->
+            <!-- <enum value="0x85D1" name="GL_FACET_NORMAL_ARRAY_AUTODESK"/> -->
+            <unused start="0x85D2" end="0x85DF" vendor="ZiiLabs"/>
+    </enums>
+
+    <enums namespace="GL" start="0x85E0" end="0x85FF" vendor="SGI">
+            <unused start="0x85E0" end="0x85FB" comment="Incomplete extension SGIX_texture_range"/>
+            <!-- <enum value="0x85E0" name="GL_RGB_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85E1" name="GL_RGBA_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85E2" name="GL_ALPHA_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85E3" name="GL_LUMINANCE_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85E4" name="GL_INTENSITY_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85E5" name="GL_LUMINANCE_ALPHA_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85E6" name="GL_RGB16_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85E7" name="GL_RGBA16_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85E8" name="GL_ALPHA16_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85E9" name="GL_LUMINANCE16_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85EA" name="GL_INTENSITY16_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85EB" name="GL_LUMINANCE16_ALPHA16_SIGNED_SGIX"/> -->
+            <!-- <enum value="0x85EC" name="GL_RGB_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85ED" name="GL_RGBA_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85EE" name="GL_ALPHA_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85EF" name="GL_LUMINANCE_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85F0" name="GL_INTENSITY_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85F1" name="GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85F2" name="GL_RGB16_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85F3" name="GL_RGBA16_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85F4" name="GL_ALPHA16_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85F5" name="GL_LUMINANCE16_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85F6" name="GL_INTENSITY16_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85F7" name="GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX"/> -->
+            <!-- <enum value="0x85F8" name="GL_MIN_LUMINANCE_SGIS"/> -->
+            <!-- <enum value="0x85F9" name="GL_MAX_LUMINANCE_SGIS"/> -->
+            <!-- <enum value="0x85FA" name="GL_MIN_INTENSITY_SGIS"/> -->
+            <!-- <enum value="0x85FB" name="GL_MAX_INTENSITY_SGIS"/> -->
+            <unused start="0x85FC" end="0x85FF" vendor="SGI"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8600" end="0x861F" vendor="SUN">
+            <unused start="0x8600" end="0x8613" vendor="SUN"/>
+        <enum value="0x8614" name="GL_QUAD_MESH_SUN"/>
+        <enum value="0x8615" name="GL_TRIANGLE_MESH_SUN"/>
+            <unused start="0x8614" end="0x861F" vendor="SUN"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8620" end="0x867F" vendor="NV">
+        <enum value="0x8620" name="GL_VERTEX_PROGRAM_ARB"/>
+        <enum value="0x8620" name="GL_VERTEX_PROGRAM_NV"/>
+        <enum value="0x8621" name="GL_VERTEX_STATE_PROGRAM_NV"/>
+        <enum value="0x8622" name="GL_VERTEX_ATTRIB_ARRAY_ENABLED"/>
+        <enum value="0x8622" name="GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB"/>
+        <enum value="0x8623" name="GL_ATTRIB_ARRAY_SIZE_NV"/>
+        <enum value="0x8623" name="GL_VERTEX_ATTRIB_ARRAY_SIZE"/>
+        <enum value="0x8623" name="GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB"/>
+        <enum value="0x8624" name="GL_ATTRIB_ARRAY_STRIDE_NV"/>
+        <enum value="0x8624" name="GL_VERTEX_ATTRIB_ARRAY_STRIDE"/>
+        <enum value="0x8624" name="GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB"/>
+        <enum value="0x8625" name="GL_ATTRIB_ARRAY_TYPE_NV"/>
+        <enum value="0x8625" name="GL_VERTEX_ATTRIB_ARRAY_TYPE"/>
+        <enum value="0x8625" name="GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB"/>
+        <enum value="0x8626" name="GL_CURRENT_ATTRIB_NV"/>
+        <enum value="0x8626" name="GL_CURRENT_VERTEX_ATTRIB"/>
+        <enum value="0x8626" name="GL_CURRENT_VERTEX_ATTRIB_ARB"/>
+        <enum value="0x8627" name="GL_PROGRAM_LENGTH_ARB"/>
+        <enum value="0x8627" name="GL_PROGRAM_LENGTH_NV"/>
+        <enum value="0x8628" name="GL_PROGRAM_STRING_ARB"/>
+        <enum value="0x8628" name="GL_PROGRAM_STRING_NV"/>
+        <enum value="0x8629" name="GL_MODELVIEW_PROJECTION_NV"/>
+        <enum value="0x862A" name="GL_IDENTITY_NV"/>
+        <enum value="0x862B" name="GL_INVERSE_NV"/>
+        <enum value="0x862C" name="GL_TRANSPOSE_NV"/>
+        <enum value="0x862D" name="GL_INVERSE_TRANSPOSE_NV"/>
+        <enum value="0x862E" name="GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB"/>
+        <enum value="0x862E" name="GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV"/>
+        <enum value="0x862F" name="GL_MAX_PROGRAM_MATRICES_ARB"/>
+        <enum value="0x862F" name="GL_MAX_TRACK_MATRICES_NV"/>
+        <enum value="0x8630" name="GL_MATRIX0_NV"/>
+        <enum value="0x8631" name="GL_MATRIX1_NV"/>
+        <enum value="0x8632" name="GL_MATRIX2_NV"/>
+        <enum value="0x8633" name="GL_MATRIX3_NV"/>
+        <enum value="0x8634" name="GL_MATRIX4_NV"/>
+        <enum value="0x8635" name="GL_MATRIX5_NV"/>
+        <enum value="0x8636" name="GL_MATRIX6_NV"/>
+        <enum value="0x8637" name="GL_MATRIX7_NV"/>
+            <unused start="0x8638" end="0x863F" comment="Reserved for MATRIX{8-15}_NV"/>
+            <!-- <enum value="0x8638" name="GL_MATRIX8_NV"/> -->
+            <!-- <enum value="0x8639" name="GL_MATRIX9_NV"/> -->
+            <!-- <enum value="0x863A" name="GL_MATRIX10_NV"/> -->
+            <!-- <enum value="0x863B" name="GL_MATRIX11_NV"/> -->
+            <!-- <enum value="0x863C" name="GL_MATRIX12_NV"/> -->
+            <!-- <enum value="0x863D" name="GL_MATRIX13_NV"/> -->
+            <!-- <enum value="0x863E" name="GL_MATRIX14_NV"/> -->
+            <!-- <enum value="0x863F" name="GL_MATRIX15_NV"/> -->
+        <enum value="0x8640" name="GL_CURRENT_MATRIX_STACK_DEPTH_ARB"/>
+        <enum value="0x8640" name="GL_CURRENT_MATRIX_STACK_DEPTH_NV"/>
+        <enum value="0x8641" name="GL_CURRENT_MATRIX_ARB"/>
+        <enum value="0x8641" name="GL_CURRENT_MATRIX_NV"/>
+        <enum value="0x8642" name="GL_VERTEX_PROGRAM_POINT_SIZE"/>
+        <enum value="0x8642" name="GL_VERTEX_PROGRAM_POINT_SIZE_ARB"/>
+        <enum value="0x8642" name="GL_VERTEX_PROGRAM_POINT_SIZE_NV"/>
+        <enum value="0x8642" name="GL_PROGRAM_POINT_SIZE" alias="GL_VERTEX_PROGRAM_POINT_SIZE"/>
+        <enum value="0x8642" name="GL_PROGRAM_POINT_SIZE_ARB"/>
+        <enum value="0x8642" name="GL_PROGRAM_POINT_SIZE_EXT"/>
+        <enum value="0x8643" name="GL_VERTEX_PROGRAM_TWO_SIDE"/>
+        <enum value="0x8643" name="GL_VERTEX_PROGRAM_TWO_SIDE_ARB"/>
+        <enum value="0x8643" name="GL_VERTEX_PROGRAM_TWO_SIDE_NV"/>
+        <enum value="0x8644" name="GL_PROGRAM_PARAMETER_NV"/>
+        <enum value="0x8645" name="GL_ATTRIB_ARRAY_POINTER_NV"/>
+        <enum value="0x8645" name="GL_VERTEX_ATTRIB_ARRAY_POINTER"/>
+        <enum value="0x8645" name="GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB"/>
+        <enum value="0x8646" name="GL_PROGRAM_TARGET_NV"/>
+        <enum value="0x8647" name="GL_PROGRAM_RESIDENT_NV"/>
+        <enum value="0x8648" name="GL_TRACK_MATRIX_NV"/>
+        <enum value="0x8649" name="GL_TRACK_MATRIX_TRANSFORM_NV"/>
+        <enum value="0x864A" name="GL_VERTEX_PROGRAM_BINDING_NV"/>
+        <enum value="0x864B" name="GL_PROGRAM_ERROR_POSITION_ARB"/>
+        <enum value="0x864B" name="GL_PROGRAM_ERROR_POSITION_NV"/>
+        <enum value="0x864C" name="GL_OFFSET_TEXTURE_RECTANGLE_NV"/>
+        <enum value="0x864D" name="GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV"/>
+        <enum value="0x864E" name="GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV"/>
+        <enum value="0x864F" name="GL_DEPTH_CLAMP"/>
+        <enum value="0x864F" name="GL_DEPTH_CLAMP_NV"/>
+        <enum value="0x8650" name="GL_VERTEX_ATTRIB_ARRAY0_NV"/>
+        <enum value="0x8651" name="GL_VERTEX_ATTRIB_ARRAY1_NV"/>
+        <enum value="0x8652" name="GL_VERTEX_ATTRIB_ARRAY2_NV"/>
+        <enum value="0x8653" name="GL_VERTEX_ATTRIB_ARRAY3_NV"/>
+        <enum value="0x8654" name="GL_VERTEX_ATTRIB_ARRAY4_NV"/>
+        <enum value="0x8655" name="GL_VERTEX_ATTRIB_ARRAY5_NV"/>
+        <enum value="0x8656" name="GL_VERTEX_ATTRIB_ARRAY6_NV"/>
+        <enum value="0x8657" name="GL_VERTEX_ATTRIB_ARRAY7_NV"/>
+        <enum value="0x8658" name="GL_VERTEX_ATTRIB_ARRAY8_NV"/>
+        <enum value="0x8659" name="GL_VERTEX_ATTRIB_ARRAY9_NV"/>
+        <enum value="0x865A" name="GL_VERTEX_ATTRIB_ARRAY10_NV"/>
+        <enum value="0x865B" name="GL_VERTEX_ATTRIB_ARRAY11_NV"/>
+        <enum value="0x865C" name="GL_VERTEX_ATTRIB_ARRAY12_NV"/>
+        <enum value="0x865D" name="GL_VERTEX_ATTRIB_ARRAY13_NV"/>
+        <enum value="0x865E" name="GL_VERTEX_ATTRIB_ARRAY14_NV"/>
+        <enum value="0x865F" name="GL_VERTEX_ATTRIB_ARRAY15_NV"/>
+        <enum value="0x8660" name="GL_MAP1_VERTEX_ATTRIB0_4_NV"/>
+        <enum value="0x8661" name="GL_MAP1_VERTEX_ATTRIB1_4_NV"/>
+        <enum value="0x8662" name="GL_MAP1_VERTEX_ATTRIB2_4_NV"/>
+        <enum value="0x8663" name="GL_MAP1_VERTEX_ATTRIB3_4_NV"/>
+        <enum value="0x8664" name="GL_MAP1_VERTEX_ATTRIB4_4_NV"/>
+        <enum value="0x8665" name="GL_MAP1_VERTEX_ATTRIB5_4_NV"/>
+        <enum value="0x8666" name="GL_MAP1_VERTEX_ATTRIB6_4_NV"/>
+        <enum value="0x8667" name="GL_MAP1_VERTEX_ATTRIB7_4_NV"/>
+        <enum value="0x8668" name="GL_MAP1_VERTEX_ATTRIB8_4_NV"/>
+        <enum value="0x8669" name="GL_MAP1_VERTEX_ATTRIB9_4_NV"/>
+        <enum value="0x866A" name="GL_MAP1_VERTEX_ATTRIB10_4_NV"/>
+        <enum value="0x866B" name="GL_MAP1_VERTEX_ATTRIB11_4_NV"/>
+        <enum value="0x866C" name="GL_MAP1_VERTEX_ATTRIB12_4_NV"/>
+        <enum value="0x866D" name="GL_MAP1_VERTEX_ATTRIB13_4_NV"/>
+        <enum value="0x866E" name="GL_MAP1_VERTEX_ATTRIB14_4_NV"/>
+        <enum value="0x866F" name="GL_MAP1_VERTEX_ATTRIB15_4_NV"/>
+        <enum value="0x8670" name="GL_MAP2_VERTEX_ATTRIB0_4_NV"/>
+        <enum value="0x8671" name="GL_MAP2_VERTEX_ATTRIB1_4_NV"/>
+        <enum value="0x8672" name="GL_MAP2_VERTEX_ATTRIB2_4_NV"/>
+        <enum value="0x8673" name="GL_MAP2_VERTEX_ATTRIB3_4_NV"/>
+        <enum value="0x8674" name="GL_MAP2_VERTEX_ATTRIB4_4_NV"/>
+        <enum value="0x8675" name="GL_MAP2_VERTEX_ATTRIB5_4_NV"/>
+        <enum value="0x8676" name="GL_MAP2_VERTEX_ATTRIB6_4_NV"/>
+        <enum value="0x8677" name="GL_MAP2_VERTEX_ATTRIB7_4_NV"/>
+        <enum value="0x8677" name="GL_PROGRAM_BINDING_ARB" comment="NOT an alias. Accidental reuse of GL_MAP2_VERTEX_ATTRIB7_4_NV"/>
+        <enum value="0x8678" name="GL_MAP2_VERTEX_ATTRIB8_4_NV"/>
+        <enum value="0x8679" name="GL_MAP2_VERTEX_ATTRIB9_4_NV"/>
+        <enum value="0x867A" name="GL_MAP2_VERTEX_ATTRIB10_4_NV"/>
+        <enum value="0x867B" name="GL_MAP2_VERTEX_ATTRIB11_4_NV"/>
+        <enum value="0x867C" name="GL_MAP2_VERTEX_ATTRIB12_4_NV"/>
+        <enum value="0x867D" name="GL_MAP2_VERTEX_ATTRIB13_4_NV"/>
+        <enum value="0x867E" name="GL_MAP2_VERTEX_ATTRIB14_4_NV"/>
+        <enum value="0x867F" name="GL_MAP2_VERTEX_ATTRIB15_4_NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8680" end="0x869F" vendor="Pixelfusion">
+            <unused start="0x8680" end="0x869F" vendor="Pixelfusion"/>
+    </enums>
+
+    <enums namespace="GL" start="0x86A0" end="0x86AF" vendor="ARB">
+        <enum value="0x86A0" name="GL_TEXTURE_COMPRESSED_IMAGE_SIZE"/>
+        <enum value="0x86A0" name="GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB"/>
+        <enum value="0x86A1" name="GL_TEXTURE_COMPRESSED"/>
+        <enum value="0x86A1" name="GL_TEXTURE_COMPRESSED_ARB"/>
+        <enum value="0x86A2" name="GL_NUM_COMPRESSED_TEXTURE_FORMATS"/>
+        <enum value="0x86A2" name="GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB"/>
+        <enum value="0x86A3" name="GL_COMPRESSED_TEXTURE_FORMATS"/>
+        <enum value="0x86A3" name="GL_COMPRESSED_TEXTURE_FORMATS_ARB"/>
+        <enum value="0x86A4" name="GL_MAX_VERTEX_UNITS_ARB"/>
+        <enum value="0x86A4" name="GL_MAX_VERTEX_UNITS_OES"/>
+        <enum value="0x86A5" name="GL_ACTIVE_VERTEX_UNITS_ARB"/>
+        <enum value="0x86A6" name="GL_WEIGHT_SUM_UNITY_ARB"/>
+        <enum value="0x86A7" name="GL_VERTEX_BLEND_ARB"/>
+        <enum value="0x86A8" name="GL_CURRENT_WEIGHT_ARB"/>
+        <enum value="0x86A9" name="GL_WEIGHT_ARRAY_TYPE_ARB"/>
+        <enum value="0x86A9" name="GL_WEIGHT_ARRAY_TYPE_OES"/>
+        <enum value="0x86AA" name="GL_WEIGHT_ARRAY_STRIDE_ARB"/>
+        <enum value="0x86AA" name="GL_WEIGHT_ARRAY_STRIDE_OES"/>
+        <enum value="0x86AB" name="GL_WEIGHT_ARRAY_SIZE_ARB"/>
+        <enum value="0x86AB" name="GL_WEIGHT_ARRAY_SIZE_OES"/>
+        <enum value="0x86AC" name="GL_WEIGHT_ARRAY_POINTER_ARB"/>
+        <enum value="0x86AC" name="GL_WEIGHT_ARRAY_POINTER_OES"/>
+        <enum value="0x86AD" name="GL_WEIGHT_ARRAY_ARB"/>
+        <enum value="0x86AD" name="GL_WEIGHT_ARRAY_OES"/>
+        <enum value="0x86AE" name="GL_DOT3_RGB"/>
+        <enum value="0x86AE" name="GL_DOT3_RGB_ARB"/>
+        <enum value="0x86AF" name="GL_DOT3_RGBA"/>
+        <enum value="0x86AF" name="GL_DOT3_RGBA_ARB"/>
+        <enum value="0x86AF" name="GL_DOT3_RGBA_IMG"/>
+    </enums>
+
+    <enums namespace="GL" start="0x86B0" end="0x86BF" vendor="3DFX">
+        <enum value="0x86B0" name="GL_COMPRESSED_RGB_FXT1_3DFX"/>
+        <enum value="0x86B1" name="GL_COMPRESSED_RGBA_FXT1_3DFX"/>
+        <enum value="0x86B2" name="GL_MULTISAMPLE_3DFX"/>
+        <enum value="0x86B3" name="GL_SAMPLE_BUFFERS_3DFX"/>
+        <enum value="0x86B4" name="GL_SAMPLES_3DFX"/>
+            <unused start="0x86B5" end="0x86BF" vendor="3DFX"/>
+    </enums>
+
+    <enums namespace="GL" start="0x86C0" end="0x871F" vendor="NV">
+        <enum value="0x86C0" name="GL_EVAL_2D_NV"/>
+        <enum value="0x86C1" name="GL_EVAL_TRIANGULAR_2D_NV"/>
+        <enum value="0x86C2" name="GL_MAP_TESSELLATION_NV"/>
+        <enum value="0x86C3" name="GL_MAP_ATTRIB_U_ORDER_NV"/>
+        <enum value="0x86C4" name="GL_MAP_ATTRIB_V_ORDER_NV"/>
+        <enum value="0x86C5" name="GL_EVAL_FRACTIONAL_TESSELLATION_NV"/>
+        <enum value="0x86C6" name="GL_EVAL_VERTEX_ATTRIB0_NV"/>
+        <enum value="0x86C7" name="GL_EVAL_VERTEX_ATTRIB1_NV"/>
+        <enum value="0x86C8" name="GL_EVAL_VERTEX_ATTRIB2_NV"/>
+        <enum value="0x86C9" name="GL_EVAL_VERTEX_ATTRIB3_NV"/>
+        <enum value="0x86CA" name="GL_EVAL_VERTEX_ATTRIB4_NV"/>
+        <enum value="0x86CB" name="GL_EVAL_VERTEX_ATTRIB5_NV"/>
+        <enum value="0x86CC" name="GL_EVAL_VERTEX_ATTRIB6_NV"/>
+        <enum value="0x86CD" name="GL_EVAL_VERTEX_ATTRIB7_NV"/>
+        <enum value="0x86CE" name="GL_EVAL_VERTEX_ATTRIB8_NV"/>
+        <enum value="0x86CF" name="GL_EVAL_VERTEX_ATTRIB9_NV"/>
+        <enum value="0x86D0" name="GL_EVAL_VERTEX_ATTRIB10_NV"/>
+        <enum value="0x86D1" name="GL_EVAL_VERTEX_ATTRIB11_NV"/>
+        <enum value="0x86D2" name="GL_EVAL_VERTEX_ATTRIB12_NV"/>
+        <enum value="0x86D3" name="GL_EVAL_VERTEX_ATTRIB13_NV"/>
+        <enum value="0x86D4" name="GL_EVAL_VERTEX_ATTRIB14_NV"/>
+        <enum value="0x86D5" name="GL_EVAL_VERTEX_ATTRIB15_NV"/>
+        <enum value="0x86D6" name="GL_MAX_MAP_TESSELLATION_NV"/>
+        <enum value="0x86D7" name="GL_MAX_RATIONAL_EVAL_ORDER_NV"/>
+        <enum value="0x86D8" name="GL_MAX_PROGRAM_PATCH_ATTRIBS_NV"/>
+        <enum value="0x86D9" name="GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV"/>
+        <enum value="0x86DA" name="GL_UNSIGNED_INT_S8_S8_8_8_NV"/>
+        <enum value="0x86DB" name="GL_UNSIGNED_INT_8_8_S8_S8_REV_NV"/>
+        <enum value="0x86DC" name="GL_DSDT_MAG_INTENSITY_NV"/>
+        <enum value="0x86DD" name="GL_SHADER_CONSISTENT_NV"/>
+        <enum value="0x86DE" name="GL_TEXTURE_SHADER_NV"/>
+        <enum value="0x86DF" name="GL_SHADER_OPERATION_NV"/>
+        <enum value="0x86E0" name="GL_CULL_MODES_NV"/>
+        <enum value="0x86E1" name="GL_OFFSET_TEXTURE_MATRIX_NV"/>
+        <enum value="0x86E1" name="GL_OFFSET_TEXTURE_2D_MATRIX_NV" alias="GL_OFFSET_TEXTURE_MATRIX_NV"/>
+        <enum value="0x86E2" name="GL_OFFSET_TEXTURE_SCALE_NV"/>
+        <enum value="0x86E2" name="GL_OFFSET_TEXTURE_2D_SCALE_NV" alias="GL_OFFSET_TEXTURE_SCALE_NV"/>
+        <enum value="0x86E3" name="GL_OFFSET_TEXTURE_BIAS_NV"/>
+        <enum value="0x86E3" name="GL_OFFSET_TEXTURE_2D_BIAS_NV" alias="GL_OFFSET_TEXTURE_BIAS_NV"/>
+        <enum value="0x86E4" name="GL_PREVIOUS_TEXTURE_INPUT_NV"/>
+        <enum value="0x86E5" name="GL_CONST_EYE_NV"/>
+        <enum value="0x86E6" name="GL_PASS_THROUGH_NV"/>
+        <enum value="0x86E7" name="GL_CULL_FRAGMENT_NV"/>
+        <enum value="0x86E8" name="GL_OFFSET_TEXTURE_2D_NV"/>
+        <enum value="0x86E9" name="GL_DEPENDENT_AR_TEXTURE_2D_NV"/>
+        <enum value="0x86EA" name="GL_DEPENDENT_GB_TEXTURE_2D_NV"/>
+        <enum value="0x86EB" name="GL_SURFACE_STATE_NV"/>
+        <enum value="0x86EC" name="GL_DOT_PRODUCT_NV"/>
+        <enum value="0x86ED" name="GL_DOT_PRODUCT_DEPTH_REPLACE_NV"/>
+        <enum value="0x86EE" name="GL_DOT_PRODUCT_TEXTURE_2D_NV"/>
+        <enum value="0x86EF" name="GL_DOT_PRODUCT_TEXTURE_3D_NV"/>
+        <enum value="0x86F0" name="GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV"/>
+        <enum value="0x86F1" name="GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV"/>
+        <enum value="0x86F2" name="GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV"/>
+        <enum value="0x86F3" name="GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV"/>
+        <enum value="0x86F4" name="GL_HILO_NV"/>
+        <enum value="0x86F5" name="GL_DSDT_NV"/>
+        <enum value="0x86F6" name="GL_DSDT_MAG_NV"/>
+        <enum value="0x86F7" name="GL_DSDT_MAG_VIB_NV"/>
+        <enum value="0x86F8" name="GL_HILO16_NV"/>
+        <enum value="0x86F9" name="GL_SIGNED_HILO_NV"/>
+        <enum value="0x86FA" name="GL_SIGNED_HILO16_NV"/>
+        <enum value="0x86FB" name="GL_SIGNED_RGBA_NV"/>
+        <enum value="0x86FC" name="GL_SIGNED_RGBA8_NV"/>
+        <enum value="0x86FD" name="GL_SURFACE_REGISTERED_NV"/>
+        <enum value="0x86FE" name="GL_SIGNED_RGB_NV"/>
+        <enum value="0x86FF" name="GL_SIGNED_RGB8_NV"/>
+        <enum value="0x8700" name="GL_SURFACE_MAPPED_NV"/>
+        <enum value="0x8701" name="GL_SIGNED_LUMINANCE_NV"/>
+        <enum value="0x8702" name="GL_SIGNED_LUMINANCE8_NV"/>
+        <enum value="0x8703" name="GL_SIGNED_LUMINANCE_ALPHA_NV"/>
+        <enum value="0x8704" name="GL_SIGNED_LUMINANCE8_ALPHA8_NV"/>
+        <enum value="0x8705" name="GL_SIGNED_ALPHA_NV"/>
+        <enum value="0x8706" name="GL_SIGNED_ALPHA8_NV"/>
+        <enum value="0x8707" name="GL_SIGNED_INTENSITY_NV"/>
+        <enum value="0x8708" name="GL_SIGNED_INTENSITY8_NV"/>
+        <enum value="0x8709" name="GL_DSDT8_NV"/>
+        <enum value="0x870A" name="GL_DSDT8_MAG8_NV"/>
+        <enum value="0x870B" name="GL_DSDT8_MAG8_INTENSITY8_NV"/>
+        <enum value="0x870C" name="GL_SIGNED_RGB_UNSIGNED_ALPHA_NV"/>
+        <enum value="0x870D" name="GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV"/>
+        <enum value="0x870E" name="GL_HI_SCALE_NV"/>
+        <enum value="0x870F" name="GL_LO_SCALE_NV"/>
+        <enum value="0x8710" name="GL_DS_SCALE_NV"/>
+        <enum value="0x8711" name="GL_DT_SCALE_NV"/>
+        <enum value="0x8712" name="GL_MAGNITUDE_SCALE_NV"/>
+        <enum value="0x8713" name="GL_VIBRANCE_SCALE_NV"/>
+        <enum value="0x8714" name="GL_HI_BIAS_NV"/>
+        <enum value="0x8715" name="GL_LO_BIAS_NV"/>
+        <enum value="0x8716" name="GL_DS_BIAS_NV"/>
+        <enum value="0x8717" name="GL_DT_BIAS_NV"/>
+        <enum value="0x8718" name="GL_MAGNITUDE_BIAS_NV"/>
+        <enum value="0x8719" name="GL_VIBRANCE_BIAS_NV"/>
+        <enum value="0x871A" name="GL_TEXTURE_BORDER_VALUES_NV"/>
+        <enum value="0x871B" name="GL_TEXTURE_HI_SIZE_NV"/>
+        <enum value="0x871C" name="GL_TEXTURE_LO_SIZE_NV"/>
+        <enum value="0x871D" name="GL_TEXTURE_DS_SIZE_NV"/>
+        <enum value="0x871E" name="GL_TEXTURE_DT_SIZE_NV"/>
+        <enum value="0x871F" name="GL_TEXTURE_MAG_SIZE_NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8720" end="0x873F" vendor="ARB">
+            <unused start="0x8720" end="0x8721" comment="MODELVIEW0/1 already exist"/>
+        <enum value="0x8722" name="GL_MODELVIEW2_ARB"/>
+        <enum value="0x8723" name="GL_MODELVIEW3_ARB"/>
+        <enum value="0x8724" name="GL_MODELVIEW4_ARB"/>
+        <enum value="0x8725" name="GL_MODELVIEW5_ARB"/>
+        <enum value="0x8726" name="GL_MODELVIEW6_ARB"/>
+        <enum value="0x8727" name="GL_MODELVIEW7_ARB"/>
+        <enum value="0x8728" name="GL_MODELVIEW8_ARB"/>
+        <enum value="0x8729" name="GL_MODELVIEW9_ARB"/>
+        <enum value="0x872A" name="GL_MODELVIEW10_ARB"/>
+        <enum value="0x872B" name="GL_MODELVIEW11_ARB"/>
+        <enum value="0x872C" name="GL_MODELVIEW12_ARB"/>
+        <enum value="0x872D" name="GL_MODELVIEW13_ARB"/>
+        <enum value="0x872E" name="GL_MODELVIEW14_ARB"/>
+        <enum value="0x872F" name="GL_MODELVIEW15_ARB"/>
+        <enum value="0x8730" name="GL_MODELVIEW16_ARB"/>
+        <enum value="0x8731" name="GL_MODELVIEW17_ARB"/>
+        <enum value="0x8732" name="GL_MODELVIEW18_ARB"/>
+        <enum value="0x8733" name="GL_MODELVIEW19_ARB"/>
+        <enum value="0x8734" name="GL_MODELVIEW20_ARB"/>
+        <enum value="0x8735" name="GL_MODELVIEW21_ARB"/>
+        <enum value="0x8736" name="GL_MODELVIEW22_ARB"/>
+        <enum value="0x8737" name="GL_MODELVIEW23_ARB"/>
+        <enum value="0x8738" name="GL_MODELVIEW24_ARB"/>
+        <enum value="0x8739" name="GL_MODELVIEW25_ARB"/>
+        <enum value="0x873A" name="GL_MODELVIEW26_ARB"/>
+        <enum value="0x873B" name="GL_MODELVIEW27_ARB"/>
+        <enum value="0x873C" name="GL_MODELVIEW28_ARB"/>
+        <enum value="0x873D" name="GL_MODELVIEW29_ARB"/>
+        <enum value="0x873E" name="GL_MODELVIEW30_ARB"/>
+        <enum value="0x873F" name="GL_MODELVIEW31_ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8740" end="0x874F" vendor="AMD">
+        <enum value="0x8740" name="GL_DOT3_RGB_EXT"/>
+        <enum value="0x8740" name="GL_Z400_BINARY_AMD" comment="NOT an alias. Accidental reuse of GL_DOT3_RGB_EXT"/>
+        <enum value="0x8741" name="GL_DOT3_RGBA_EXT"/>
+        <enum value="0x8741" name="GL_PROGRAM_BINARY_LENGTH_OES" comment="NOT an alias. Accidental reuse of GL_DOT3_RGBA_EXT"/>
+        <enum value="0x8741" name="GL_PROGRAM_BINARY_LENGTH"/>
+        <enum value="0x8742" name="GL_MIRROR_CLAMP_ATI"/>
+        <enum value="0x8742" name="GL_MIRROR_CLAMP_EXT"/>
+        <enum value="0x8743" name="GL_MIRROR_CLAMP_TO_EDGE"/>
+        <enum value="0x8743" name="GL_MIRROR_CLAMP_TO_EDGE_ATI"/>
+        <enum value="0x8743" name="GL_MIRROR_CLAMP_TO_EDGE_EXT"/>
+        <enum value="0x8744" name="GL_MODULATE_ADD_ATI"/>
+        <enum value="0x8745" name="GL_MODULATE_SIGNED_ADD_ATI"/>
+        <enum value="0x8746" name="GL_MODULATE_SUBTRACT_ATI"/>
+            <unused start="0x8747" end="0x8749" vendor="AMD"/>
+        <enum value="0x874A" name="GL_SET_AMD"/>
+        <enum value="0x874B" name="GL_REPLACE_VALUE_AMD"/>
+        <enum value="0x874C" name="GL_STENCIL_OP_VALUE_AMD"/>
+        <enum value="0x874D" name="GL_STENCIL_BACK_OP_VALUE_AMD"/>
+        <enum value="0x874E" name="GL_VERTEX_ATTRIB_ARRAY_LONG"/>
+        <enum value="0x874F" name="GL_OCCLUSION_QUERY_EVENT_MASK_AMD"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8750" end="0x875F" vendor="MESA">
+        <enum value="0x8750" name="GL_DEPTH_STENCIL_MESA"/>
+        <enum value="0x8751" name="GL_UNSIGNED_INT_24_8_MESA"/>
+        <enum value="0x8752" name="GL_UNSIGNED_INT_8_24_REV_MESA"/>
+        <enum value="0x8753" name="GL_UNSIGNED_SHORT_15_1_MESA"/>
+        <enum value="0x8754" name="GL_UNSIGNED_SHORT_1_15_REV_MESA"/>
+        <enum value="0x8755" name="GL_TRACE_MASK_MESA"/>
+        <enum value="0x8756" name="GL_TRACE_NAME_MESA"/>
+        <enum value="0x8757" name="GL_YCBCR_MESA"/>
+        <enum value="0x8758" name="GL_PACK_INVERT_MESA"/>
+        <enum value="0x8759" name="GL_DEBUG_OBJECT_MESA" comment="NOT an alias. Accidental reuse of GL_TEXTURE_1D_STACK_MESAX"/>
+        <enum value="0x8759" name="GL_TEXTURE_1D_STACK_MESAX"/>
+        <enum value="0x875A" name="GL_DEBUG_PRINT_MESA" comment="NOT an alias. Accidental reuse of GL_TEXTURE_2D_STACK_MESAX"/>
+        <enum value="0x875A" name="GL_TEXTURE_2D_STACK_MESAX"/>
+        <enum value="0x875B" name="GL_DEBUG_ASSERT_MESA" comment="NOT an alias. Accidental reuse of GL_PROXY_TEXTURE_1D_STACK_MESAX"/>
+        <enum value="0x875B" name="GL_PROXY_TEXTURE_1D_STACK_MESAX"/>
+        <enum value="0x875C" name="GL_PROXY_TEXTURE_2D_STACK_MESAX"/>
+        <enum value="0x875D" name="GL_TEXTURE_1D_STACK_BINDING_MESAX"/>
+        <enum value="0x875E" name="GL_TEXTURE_2D_STACK_BINDING_MESAX"/>
+            <unused start="0x875F" vendor="MESA"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8760" end="0x883F" vendor="AMD">
+        <enum value="0x8760" name="GL_STATIC_ATI"/>
+        <enum value="0x8761" name="GL_DYNAMIC_ATI"/>
+        <enum value="0x8762" name="GL_PRESERVE_ATI"/>
+        <enum value="0x8763" name="GL_DISCARD_ATI"/>
+        <enum value="0x8764" name="GL_BUFFER_SIZE"/>
+        <enum value="0x8764" name="GL_BUFFER_SIZE_ARB"/>
+        <enum value="0x8764" name="GL_OBJECT_BUFFER_SIZE_ATI"/>
+        <enum value="0x8765" name="GL_BUFFER_USAGE"/>
+        <enum value="0x8765" name="GL_BUFFER_USAGE_ARB"/>
+        <enum value="0x8765" name="GL_OBJECT_BUFFER_USAGE_ATI"/>
+        <enum value="0x8766" name="GL_ARRAY_OBJECT_BUFFER_ATI"/>
+        <enum value="0x8767" name="GL_ARRAY_OBJECT_OFFSET_ATI"/>
+        <enum value="0x8768" name="GL_ELEMENT_ARRAY_ATI"/>
+        <enum value="0x8769" name="GL_ELEMENT_ARRAY_TYPE_ATI"/>
+        <enum value="0x876A" name="GL_ELEMENT_ARRAY_POINTER_ATI"/>
+        <enum value="0x876B" name="GL_MAX_VERTEX_STREAMS_ATI"/>
+        <enum value="0x876C" name="GL_VERTEX_STREAM0_ATI"/>
+        <enum value="0x876D" name="GL_VERTEX_STREAM1_ATI"/>
+        <enum value="0x876E" name="GL_VERTEX_STREAM2_ATI"/>
+        <enum value="0x876F" name="GL_VERTEX_STREAM3_ATI"/>
+        <enum value="0x8770" name="GL_VERTEX_STREAM4_ATI"/>
+        <enum value="0x8771" name="GL_VERTEX_STREAM5_ATI"/>
+        <enum value="0x8772" name="GL_VERTEX_STREAM6_ATI"/>
+        <enum value="0x8773" name="GL_VERTEX_STREAM7_ATI"/>
+        <enum value="0x8774" name="GL_VERTEX_SOURCE_ATI"/>
+        <enum value="0x8775" name="GL_BUMP_ROT_MATRIX_ATI"/>
+        <enum value="0x8776" name="GL_BUMP_ROT_MATRIX_SIZE_ATI"/>
+        <enum value="0x8777" name="GL_BUMP_NUM_TEX_UNITS_ATI"/>
+        <enum value="0x8778" name="GL_BUMP_TEX_UNITS_ATI"/>
+        <enum value="0x8779" name="GL_DUDV_ATI"/>
+        <enum value="0x877A" name="GL_DU8DV8_ATI"/>
+        <enum value="0x877B" name="GL_BUMP_ENVMAP_ATI"/>
+        <enum value="0x877C" name="GL_BUMP_TARGET_ATI"/>
+            <unused start="0x877D" end="0x877F" vendor="AMD"/>
+        <enum value="0x8780" name="GL_VERTEX_SHADER_EXT"/>
+        <enum value="0x8781" name="GL_VERTEX_SHADER_BINDING_EXT"/>
+        <enum value="0x8782" name="GL_OP_INDEX_EXT"/>
+        <enum value="0x8783" name="GL_OP_NEGATE_EXT"/>
+        <enum value="0x8784" name="GL_OP_DOT3_EXT"/>
+        <enum value="0x8785" name="GL_OP_DOT4_EXT"/>
+        <enum value="0x8786" name="GL_OP_MUL_EXT"/>
+        <enum value="0x8787" name="GL_OP_ADD_EXT"/>
+        <enum value="0x8788" name="GL_OP_MADD_EXT"/>
+        <enum value="0x8789" name="GL_OP_FRAC_EXT"/>
+        <enum value="0x878A" name="GL_OP_MAX_EXT"/>
+        <enum value="0x878B" name="GL_OP_MIN_EXT"/>
+        <enum value="0x878C" name="GL_OP_SET_GE_EXT"/>
+        <enum value="0x878D" name="GL_OP_SET_LT_EXT"/>
+        <enum value="0x878E" name="GL_OP_CLAMP_EXT"/>
+        <enum value="0x878F" name="GL_OP_FLOOR_EXT"/>
+        <enum value="0x8790" name="GL_OP_ROUND_EXT"/>
+        <enum value="0x8791" name="GL_OP_EXP_BASE_2_EXT"/>
+        <enum value="0x8792" name="GL_OP_LOG_BASE_2_EXT"/>
+        <enum value="0x8793" name="GL_OP_POWER_EXT"/>
+        <enum value="0x8794" name="GL_OP_RECIP_EXT"/>
+        <enum value="0x8795" name="GL_OP_RECIP_SQRT_EXT"/>
+        <enum value="0x8796" name="GL_OP_SUB_EXT"/>
+        <enum value="0x8797" name="GL_OP_CROSS_PRODUCT_EXT"/>
+        <enum value="0x8798" name="GL_OP_MULTIPLY_MATRIX_EXT"/>
+        <enum value="0x8799" name="GL_OP_MOV_EXT"/>
+        <enum value="0x879A" name="GL_OUTPUT_VERTEX_EXT"/>
+        <enum value="0x879B" name="GL_OUTPUT_COLOR0_EXT"/>
+        <enum value="0x879C" name="GL_OUTPUT_COLOR1_EXT"/>
+        <enum value="0x879D" name="GL_OUTPUT_TEXTURE_COORD0_EXT"/>
+        <enum value="0x879E" name="GL_OUTPUT_TEXTURE_COORD1_EXT"/>
+        <enum value="0x879F" name="GL_OUTPUT_TEXTURE_COORD2_EXT"/>
+        <enum value="0x87A0" name="GL_OUTPUT_TEXTURE_COORD3_EXT"/>
+        <enum value="0x87A1" name="GL_OUTPUT_TEXTURE_COORD4_EXT"/>
+        <enum value="0x87A2" name="GL_OUTPUT_TEXTURE_COORD5_EXT"/>
+        <enum value="0x87A3" name="GL_OUTPUT_TEXTURE_COORD6_EXT"/>
+        <enum value="0x87A4" name="GL_OUTPUT_TEXTURE_COORD7_EXT"/>
+        <enum value="0x87A5" name="GL_OUTPUT_TEXTURE_COORD8_EXT"/>
+        <enum value="0x87A6" name="GL_OUTPUT_TEXTURE_COORD9_EXT"/>
+        <enum value="0x87A7" name="GL_OUTPUT_TEXTURE_COORD10_EXT"/>
+        <enum value="0x87A8" name="GL_OUTPUT_TEXTURE_COORD11_EXT"/>
+        <enum value="0x87A9" name="GL_OUTPUT_TEXTURE_COORD12_EXT"/>
+        <enum value="0x87AA" name="GL_OUTPUT_TEXTURE_COORD13_EXT"/>
+        <enum value="0x87AB" name="GL_OUTPUT_TEXTURE_COORD14_EXT"/>
+        <enum value="0x87AC" name="GL_OUTPUT_TEXTURE_COORD15_EXT"/>
+        <enum value="0x87AD" name="GL_OUTPUT_TEXTURE_COORD16_EXT"/>
+        <enum value="0x87AE" name="GL_OUTPUT_TEXTURE_COORD17_EXT"/>
+        <enum value="0x87AF" name="GL_OUTPUT_TEXTURE_COORD18_EXT"/>
+        <enum value="0x87B0" name="GL_OUTPUT_TEXTURE_COORD19_EXT"/>
+        <enum value="0x87B1" name="GL_OUTPUT_TEXTURE_COORD20_EXT"/>
+        <enum value="0x87B2" name="GL_OUTPUT_TEXTURE_COORD21_EXT"/>
+        <enum value="0x87B3" name="GL_OUTPUT_TEXTURE_COORD22_EXT"/>
+        <enum value="0x87B4" name="GL_OUTPUT_TEXTURE_COORD23_EXT"/>
+        <enum value="0x87B5" name="GL_OUTPUT_TEXTURE_COORD24_EXT"/>
+        <enum value="0x87B6" name="GL_OUTPUT_TEXTURE_COORD25_EXT"/>
+        <enum value="0x87B7" name="GL_OUTPUT_TEXTURE_COORD26_EXT"/>
+        <enum value="0x87B8" name="GL_OUTPUT_TEXTURE_COORD27_EXT"/>
+        <enum value="0x87B9" name="GL_OUTPUT_TEXTURE_COORD28_EXT"/>
+        <enum value="0x87BA" name="GL_OUTPUT_TEXTURE_COORD29_EXT"/>
+        <enum value="0x87BB" name="GL_OUTPUT_TEXTURE_COORD30_EXT"/>
+        <enum value="0x87BC" name="GL_OUTPUT_TEXTURE_COORD31_EXT"/>
+        <enum value="0x87BD" name="GL_OUTPUT_FOG_EXT"/>
+        <enum value="0x87BE" name="GL_SCALAR_EXT"/>
+        <enum value="0x87BF" name="GL_VECTOR_EXT"/>
+        <enum value="0x87C0" name="GL_MATRIX_EXT"/>
+        <enum value="0x87C1" name="GL_VARIANT_EXT"/>
+        <enum value="0x87C2" name="GL_INVARIANT_EXT"/>
+        <enum value="0x87C3" name="GL_LOCAL_CONSTANT_EXT"/>
+        <enum value="0x87C4" name="GL_LOCAL_EXT"/>
+        <enum value="0x87C5" name="GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT"/>
+        <enum value="0x87C6" name="GL_MAX_VERTEX_SHADER_VARIANTS_EXT"/>
+        <enum value="0x87C7" name="GL_MAX_VERTEX_SHADER_INVARIANTS_EXT"/>
+        <enum value="0x87C8" name="GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT"/>
+        <enum value="0x87C9" name="GL_MAX_VERTEX_SHADER_LOCALS_EXT"/>
+        <enum value="0x87CA" name="GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT"/>
+        <enum value="0x87CB" name="GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT"/>
+        <enum value="0x87CC" name="GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT"/>
+        <enum value="0x87CD" name="GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT"/>
+        <enum value="0x87CE" name="GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT"/>
+        <enum value="0x87CF" name="GL_VERTEX_SHADER_INSTRUCTIONS_EXT"/>
+        <enum value="0x87D0" name="GL_VERTEX_SHADER_VARIANTS_EXT"/>
+        <enum value="0x87D1" name="GL_VERTEX_SHADER_INVARIANTS_EXT"/>
+        <enum value="0x87D2" name="GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT"/>
+        <enum value="0x87D3" name="GL_VERTEX_SHADER_LOCALS_EXT"/>
+        <enum value="0x87D4" name="GL_VERTEX_SHADER_OPTIMIZED_EXT"/>
+        <enum value="0x87D5" name="GL_X_EXT"/>
+        <enum value="0x87D6" name="GL_Y_EXT"/>
+        <enum value="0x87D7" name="GL_Z_EXT"/>
+        <enum value="0x87D8" name="GL_W_EXT"/>
+        <enum value="0x87D9" name="GL_NEGATIVE_X_EXT"/>
+        <enum value="0x87DA" name="GL_NEGATIVE_Y_EXT"/>
+        <enum value="0x87DB" name="GL_NEGATIVE_Z_EXT"/>
+        <enum value="0x87DC" name="GL_NEGATIVE_W_EXT"/>
+        <enum value="0x87DD" name="GL_ZERO_EXT"/>
+        <enum value="0x87DE" name="GL_ONE_EXT"/>
+        <enum value="0x87DF" name="GL_NEGATIVE_ONE_EXT"/>
+        <enum value="0x87E0" name="GL_NORMALIZED_RANGE_EXT"/>
+        <enum value="0x87E1" name="GL_FULL_RANGE_EXT"/>
+        <enum value="0x87E2" name="GL_CURRENT_VERTEX_EXT"/>
+        <enum value="0x87E3" name="GL_MVP_MATRIX_EXT"/>
+        <enum value="0x87E4" name="GL_VARIANT_VALUE_EXT"/>
+        <enum value="0x87E5" name="GL_VARIANT_DATATYPE_EXT"/>
+        <enum value="0x87E6" name="GL_VARIANT_ARRAY_STRIDE_EXT"/>
+        <enum value="0x87E7" name="GL_VARIANT_ARRAY_TYPE_EXT"/>
+        <enum value="0x87E8" name="GL_VARIANT_ARRAY_EXT"/>
+        <enum value="0x87E9" name="GL_VARIANT_ARRAY_POINTER_EXT"/>
+        <enum value="0x87EA" name="GL_INVARIANT_VALUE_EXT"/>
+        <enum value="0x87EB" name="GL_INVARIANT_DATATYPE_EXT"/>
+        <enum value="0x87EC" name="GL_LOCAL_CONSTANT_VALUE_EXT"/>
+        <enum value="0x87ED" name="GL_LOCAL_CONSTANT_DATATYPE_EXT"/>
+        <enum value="0x87EE" name="GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD"/>
+        <enum value="0x87F0" name="GL_PN_TRIANGLES_ATI"/>
+        <enum value="0x87F1" name="GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI"/>
+        <enum value="0x87F2" name="GL_PN_TRIANGLES_POINT_MODE_ATI"/>
+        <enum value="0x87F3" name="GL_PN_TRIANGLES_NORMAL_MODE_ATI"/>
+        <enum value="0x87F4" name="GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI"/>
+        <enum value="0x87F5" name="GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI"/>
+        <enum value="0x87F6" name="GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI"/>
+        <enum value="0x87F7" name="GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI"/>
+        <enum value="0x87F8" name="GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI"/>
+        <enum value="0x87F9" name="GL_3DC_X_AMD"/>
+        <enum value="0x87FA" name="GL_3DC_XY_AMD"/>
+        <enum value="0x87FB" name="GL_VBO_FREE_MEMORY_ATI"/>
+        <enum value="0x87FC" name="GL_TEXTURE_FREE_MEMORY_ATI"/>
+        <enum value="0x87FD" name="GL_RENDERBUFFER_FREE_MEMORY_ATI"/>
+        <enum value="0x87FE" name="GL_NUM_PROGRAM_BINARY_FORMATS"/>
+        <enum value="0x87FE" name="GL_NUM_PROGRAM_BINARY_FORMATS_OES"/>
+        <enum value="0x87FF" name="GL_PROGRAM_BINARY_FORMATS"/>
+        <enum value="0x87FF" name="GL_PROGRAM_BINARY_FORMATS_OES"/>
+        <enum value="0x8800" name="GL_STENCIL_BACK_FUNC"/>
+        <enum value="0x8800" name="GL_STENCIL_BACK_FUNC_ATI"/>
+        <enum value="0x8801" name="GL_STENCIL_BACK_FAIL"/>
+        <enum value="0x8801" name="GL_STENCIL_BACK_FAIL_ATI"/>
+        <enum value="0x8802" name="GL_STENCIL_BACK_PASS_DEPTH_FAIL"/>
+        <enum value="0x8802" name="GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI"/>
+        <enum value="0x8803" name="GL_STENCIL_BACK_PASS_DEPTH_PASS"/>
+        <enum value="0x8803" name="GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI"/>
+        <enum value="0x8804" name="GL_FRAGMENT_PROGRAM_ARB"/>
+        <enum value="0x8805" name="GL_PROGRAM_ALU_INSTRUCTIONS_ARB"/>
+        <enum value="0x8806" name="GL_PROGRAM_TEX_INSTRUCTIONS_ARB"/>
+        <enum value="0x8807" name="GL_PROGRAM_TEX_INDIRECTIONS_ARB"/>
+        <enum value="0x8808" name="GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB"/>
+        <enum value="0x8809" name="GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB"/>
+        <enum value="0x880A" name="GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB"/>
+        <enum value="0x880B" name="GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB"/>
+        <enum value="0x880C" name="GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB"/>
+        <enum value="0x880D" name="GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB"/>
+        <enum value="0x880E" name="GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB"/>
+        <enum value="0x880F" name="GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB"/>
+        <enum value="0x8810" name="GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB"/>
+            <unused start="0x8811" end="0x8813" vendor="AMD"/>
+        <enum value="0x8814" name="GL_RGBA32F"/>
+        <enum value="0x8814" name="GL_RGBA32F_ARB"/>
+        <enum value="0x8814" name="GL_RGBA32F_EXT"/>
+        <enum value="0x8814" name="GL_RGBA_FLOAT32_APPLE"/>
+        <enum value="0x8814" name="GL_RGBA_FLOAT32_ATI"/>
+        <enum value="0x8815" name="GL_RGB32F"/>
+        <enum value="0x8815" name="GL_RGB32F_ARB"/>
+        <enum value="0x8815" name="GL_RGB32F_EXT"/>
+        <enum value="0x8815" name="GL_RGB_FLOAT32_APPLE"/>
+        <enum value="0x8815" name="GL_RGB_FLOAT32_ATI"/>
+        <enum value="0x8816" name="GL_ALPHA32F_ARB"/>
+        <enum value="0x8816" name="GL_ALPHA32F_EXT"/>
+        <enum value="0x8816" name="GL_ALPHA_FLOAT32_APPLE"/>
+        <enum value="0x8816" name="GL_ALPHA_FLOAT32_ATI"/>
+        <enum value="0x8817" name="GL_INTENSITY32F_ARB"/>
+        <enum value="0x8817" name="GL_INTENSITY_FLOAT32_APPLE"/>
+        <enum value="0x8817" name="GL_INTENSITY_FLOAT32_ATI"/>
+        <enum value="0x8818" name="GL_LUMINANCE32F_ARB"/>
+        <enum value="0x8818" name="GL_LUMINANCE32F_EXT"/>
+        <enum value="0x8818" name="GL_LUMINANCE_FLOAT32_APPLE"/>
+        <enum value="0x8818" name="GL_LUMINANCE_FLOAT32_ATI"/>
+        <enum value="0x8819" name="GL_LUMINANCE_ALPHA32F_ARB"/>
+        <enum value="0x8819" name="GL_LUMINANCE_ALPHA32F_EXT"/>
+        <enum value="0x8819" name="GL_LUMINANCE_ALPHA_FLOAT32_APPLE"/>
+        <enum value="0x8819" name="GL_LUMINANCE_ALPHA_FLOAT32_ATI"/>
+        <enum value="0x881A" name="GL_RGBA16F"/>
+        <enum value="0x881A" name="GL_RGBA16F_ARB"/>
+        <enum value="0x881A" name="GL_RGBA16F_EXT"/>
+        <enum value="0x881A" name="GL_RGBA_FLOAT16_APPLE"/>
+        <enum value="0x881A" name="GL_RGBA_FLOAT16_ATI"/>
+        <enum value="0x881B" name="GL_RGB16F"/>
+        <enum value="0x881B" name="GL_RGB16F_ARB"/>
+        <enum value="0x881B" name="GL_RGB16F_EXT"/>
+        <enum value="0x881B" name="GL_RGB_FLOAT16_APPLE"/>
+        <enum value="0x881B" name="GL_RGB_FLOAT16_ATI"/>
+        <enum value="0x881C" name="GL_ALPHA16F_ARB"/>
+        <enum value="0x881C" name="GL_ALPHA16F_EXT"/>
+        <enum value="0x881C" name="GL_ALPHA_FLOAT16_APPLE"/>
+        <enum value="0x881C" name="GL_ALPHA_FLOAT16_ATI"/>
+        <enum value="0x881D" name="GL_INTENSITY16F_ARB"/>
+        <enum value="0x881D" name="GL_INTENSITY_FLOAT16_APPLE"/>
+        <enum value="0x881D" name="GL_INTENSITY_FLOAT16_ATI"/>
+        <enum value="0x881E" name="GL_LUMINANCE16F_ARB"/>
+        <enum value="0x881E" name="GL_LUMINANCE16F_EXT"/>
+        <enum value="0x881E" name="GL_LUMINANCE_FLOAT16_APPLE"/>
+        <enum value="0x881E" name="GL_LUMINANCE_FLOAT16_ATI"/>
+        <enum value="0x881F" name="GL_LUMINANCE_ALPHA16F_ARB"/>
+        <enum value="0x881F" name="GL_LUMINANCE_ALPHA16F_EXT"/>
+        <enum value="0x881F" name="GL_LUMINANCE_ALPHA_FLOAT16_APPLE"/>
+        <enum value="0x881F" name="GL_LUMINANCE_ALPHA_FLOAT16_ATI"/>
+            <!-- RGBA_FLOAT_MODE_ARB equivalent to TYPE_RGBA_FLOAT_ATI -->
+        <enum value="0x8820" name="GL_RGBA_FLOAT_MODE_ARB"/>
+        <enum value="0x8820" name="GL_RGBA_FLOAT_MODE_ATI"/>
+            <unused start="0x8821" end="0x8822" vendor="AMD"/>
+        <enum value="0x8823" name="GL_WRITEONLY_RENDERING_QCOM"/>
+        <enum value="0x8824" name="GL_MAX_DRAW_BUFFERS"/>
+        <enum value="0x8824" name="GL_MAX_DRAW_BUFFERS_ARB"/>
+        <enum value="0x8824" name="GL_MAX_DRAW_BUFFERS_ATI"/>
+        <enum value="0x8824" name="GL_MAX_DRAW_BUFFERS_EXT"/>
+        <enum value="0x8824" name="GL_MAX_DRAW_BUFFERS_NV"/>
+        <enum value="0x8825" name="GL_DRAW_BUFFER0"/>
+        <enum value="0x8825" name="GL_DRAW_BUFFER0_ARB"/>
+        <enum value="0x8825" name="GL_DRAW_BUFFER0_ATI"/>
+        <enum value="0x8825" name="GL_DRAW_BUFFER0_EXT"/>
+        <enum value="0x8825" name="GL_DRAW_BUFFER0_NV"/>
+        <enum value="0x8826" name="GL_DRAW_BUFFER1"/>
+        <enum value="0x8826" name="GL_DRAW_BUFFER1_ARB"/>
+        <enum value="0x8826" name="GL_DRAW_BUFFER1_ATI"/>
+        <enum value="0x8826" name="GL_DRAW_BUFFER1_EXT"/>
+        <enum value="0x8826" name="GL_DRAW_BUFFER1_NV"/>
+        <enum value="0x8827" name="GL_DRAW_BUFFER2"/>
+        <enum value="0x8827" name="GL_DRAW_BUFFER2_ARB"/>
+        <enum value="0x8827" name="GL_DRAW_BUFFER2_ATI"/>
+        <enum value="0x8827" name="GL_DRAW_BUFFER2_EXT"/>
+        <enum value="0x8827" name="GL_DRAW_BUFFER2_NV"/>
+        <enum value="0x8828" name="GL_DRAW_BUFFER3"/>
+        <enum value="0x8828" name="GL_DRAW_BUFFER3_ARB"/>
+        <enum value="0x8828" name="GL_DRAW_BUFFER3_ATI"/>
+        <enum value="0x8828" name="GL_DRAW_BUFFER3_EXT"/>
+        <enum value="0x8828" name="GL_DRAW_BUFFER3_NV"/>
+        <enum value="0x8829" name="GL_DRAW_BUFFER4"/>
+        <enum value="0x8829" name="GL_DRAW_BUFFER4_ARB"/>
+        <enum value="0x8829" name="GL_DRAW_BUFFER4_ATI"/>
+        <enum value="0x8829" name="GL_DRAW_BUFFER4_EXT"/>
+        <enum value="0x8829" name="GL_DRAW_BUFFER4_NV"/>
+        <enum value="0x882A" name="GL_DRAW_BUFFER5"/>
+        <enum value="0x882A" name="GL_DRAW_BUFFER5_ARB"/>
+        <enum value="0x882A" name="GL_DRAW_BUFFER5_ATI"/>
+        <enum value="0x882A" name="GL_DRAW_BUFFER5_EXT"/>
+        <enum value="0x882A" name="GL_DRAW_BUFFER5_NV"/>
+        <enum value="0x882B" name="GL_DRAW_BUFFER6"/>
+        <enum value="0x882B" name="GL_DRAW_BUFFER6_ARB"/>
+        <enum value="0x882B" name="GL_DRAW_BUFFER6_ATI"/>
+        <enum value="0x882B" name="GL_DRAW_BUFFER6_EXT"/>
+        <enum value="0x882B" name="GL_DRAW_BUFFER6_NV"/>
+        <enum value="0x882C" name="GL_DRAW_BUFFER7"/>
+        <enum value="0x882C" name="GL_DRAW_BUFFER7_ARB"/>
+        <enum value="0x882C" name="GL_DRAW_BUFFER7_ATI"/>
+        <enum value="0x882C" name="GL_DRAW_BUFFER7_EXT"/>
+        <enum value="0x882C" name="GL_DRAW_BUFFER7_NV"/>
+        <enum value="0x882D" name="GL_DRAW_BUFFER8"/>
+        <enum value="0x882D" name="GL_DRAW_BUFFER8_ARB"/>
+        <enum value="0x882D" name="GL_DRAW_BUFFER8_ATI"/>
+        <enum value="0x882D" name="GL_DRAW_BUFFER8_EXT"/>
+        <enum value="0x882D" name="GL_DRAW_BUFFER8_NV"/>
+        <enum value="0x882E" name="GL_DRAW_BUFFER9"/>
+        <enum value="0x882E" name="GL_DRAW_BUFFER9_ARB"/>
+        <enum value="0x882E" name="GL_DRAW_BUFFER9_ATI"/>
+        <enum value="0x882E" name="GL_DRAW_BUFFER9_EXT"/>
+        <enum value="0x882E" name="GL_DRAW_BUFFER9_NV"/>
+        <enum value="0x882F" name="GL_DRAW_BUFFER10"/>
+        <enum value="0x882F" name="GL_DRAW_BUFFER10_ARB"/>
+        <enum value="0x882F" name="GL_DRAW_BUFFER10_ATI"/>
+        <enum value="0x882F" name="GL_DRAW_BUFFER10_EXT"/>
+        <enum value="0x882F" name="GL_DRAW_BUFFER10_NV"/>
+        <enum value="0x8830" name="GL_DRAW_BUFFER11"/>
+        <enum value="0x8830" name="GL_DRAW_BUFFER11_ARB"/>
+        <enum value="0x8830" name="GL_DRAW_BUFFER11_ATI"/>
+        <enum value="0x8830" name="GL_DRAW_BUFFER11_EXT"/>
+        <enum value="0x8830" name="GL_DRAW_BUFFER11_NV"/>
+        <enum value="0x8831" name="GL_DRAW_BUFFER12"/>
+        <enum value="0x8831" name="GL_DRAW_BUFFER12_ARB"/>
+        <enum value="0x8831" name="GL_DRAW_BUFFER12_ATI"/>
+        <enum value="0x8831" name="GL_DRAW_BUFFER12_EXT"/>
+        <enum value="0x8831" name="GL_DRAW_BUFFER12_NV"/>
+        <enum value="0x8832" name="GL_DRAW_BUFFER13"/>
+        <enum value="0x8832" name="GL_DRAW_BUFFER13_ARB"/>
+        <enum value="0x8832" name="GL_DRAW_BUFFER13_ATI"/>
+        <enum value="0x8832" name="GL_DRAW_BUFFER13_EXT"/>
+        <enum value="0x8832" name="GL_DRAW_BUFFER13_NV"/>
+        <enum value="0x8833" name="GL_DRAW_BUFFER14"/>
+        <enum value="0x8833" name="GL_DRAW_BUFFER14_ARB"/>
+        <enum value="0x8833" name="GL_DRAW_BUFFER14_ATI"/>
+        <enum value="0x8833" name="GL_DRAW_BUFFER14_EXT"/>
+        <enum value="0x8833" name="GL_DRAW_BUFFER14_NV"/>
+        <enum value="0x8834" name="GL_DRAW_BUFFER15"/>
+        <enum value="0x8834" name="GL_DRAW_BUFFER15_ARB"/>
+        <enum value="0x8834" name="GL_DRAW_BUFFER15_ATI"/>
+        <enum value="0x8834" name="GL_DRAW_BUFFER15_EXT"/>
+        <enum value="0x8834" name="GL_DRAW_BUFFER15_NV"/>
+        <enum value="0x8835" name="GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI"/>
+            <unused start="0x8836" vendor="AMD"/>
+        <enum value="0x8837" name="GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI" comment="Defined by Mesa but not ATI"/>
+            <unused start="0x8838" end="0x883C" vendor="AMD"/>
+        <enum value="0x883D" name="GL_BLEND_EQUATION_ALPHA"/>
+        <enum value="0x883D" name="GL_BLEND_EQUATION_ALPHA_EXT"/>
+        <enum value="0x883D" name="GL_BLEND_EQUATION_ALPHA_OES"/>
+            <unused start="0x883E" vendor="AMD"/>
+        <enum value="0x883F" name="GL_SUBSAMPLE_DISTANCE_AMD"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8840" end="0x884F" vendor="ARB">
+        <enum value="0x8840" name="GL_MATRIX_PALETTE_ARB"/>
+        <enum value="0x8840" name="GL_MATRIX_PALETTE_OES"/>
+        <enum value="0x8841" name="GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB"/>
+        <enum value="0x8842" name="GL_MAX_PALETTE_MATRICES_ARB"/>
+        <enum value="0x8842" name="GL_MAX_PALETTE_MATRICES_OES"/>
+        <enum value="0x8843" name="GL_CURRENT_PALETTE_MATRIX_ARB"/>
+        <enum value="0x8843" name="GL_CURRENT_PALETTE_MATRIX_OES"/>
+        <enum value="0x8844" name="GL_MATRIX_INDEX_ARRAY_ARB"/>
+        <enum value="0x8844" name="GL_MATRIX_INDEX_ARRAY_OES"/>
+        <enum value="0x8845" name="GL_CURRENT_MATRIX_INDEX_ARB"/>
+        <enum value="0x8846" name="GL_MATRIX_INDEX_ARRAY_SIZE_ARB"/>
+        <enum value="0x8846" name="GL_MATRIX_INDEX_ARRAY_SIZE_OES"/>
+        <enum value="0x8847" name="GL_MATRIX_INDEX_ARRAY_TYPE_ARB"/>
+        <enum value="0x8847" name="GL_MATRIX_INDEX_ARRAY_TYPE_OES"/>
+        <enum value="0x8848" name="GL_MATRIX_INDEX_ARRAY_STRIDE_ARB"/>
+        <enum value="0x8848" name="GL_MATRIX_INDEX_ARRAY_STRIDE_OES"/>
+        <enum value="0x8849" name="GL_MATRIX_INDEX_ARRAY_POINTER_ARB"/>
+        <enum value="0x8849" name="GL_MATRIX_INDEX_ARRAY_POINTER_OES"/>
+        <enum value="0x884A" name="GL_TEXTURE_DEPTH_SIZE"/>
+        <enum value="0x884A" name="GL_TEXTURE_DEPTH_SIZE_ARB"/>
+        <enum value="0x884B" name="GL_DEPTH_TEXTURE_MODE"/>
+        <enum value="0x884B" name="GL_DEPTH_TEXTURE_MODE_ARB"/>
+        <enum value="0x884C" name="GL_TEXTURE_COMPARE_MODE"/>
+        <enum value="0x884C" name="GL_TEXTURE_COMPARE_MODE_ARB"/>
+        <enum value="0x884C" name="GL_TEXTURE_COMPARE_MODE_EXT"/>
+        <enum value="0x884D" name="GL_TEXTURE_COMPARE_FUNC"/>
+        <enum value="0x884D" name="GL_TEXTURE_COMPARE_FUNC_ARB"/>
+        <enum value="0x884D" name="GL_TEXTURE_COMPARE_FUNC_EXT"/>
+        <enum value="0x884E" name="GL_COMPARE_R_TO_TEXTURE"/>
+        <enum value="0x884E" name="GL_COMPARE_R_TO_TEXTURE_ARB"/>
+        <enum value="0x884E" name="GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT"/>
+        <enum value="0x884E" name="GL_COMPARE_REF_TO_TEXTURE" alias="GL_COMPARE_R_TO_TEXTURE"/>
+        <enum value="0x884E" name="GL_COMPARE_REF_TO_TEXTURE_EXT"/>
+        <enum value="0x884F" name="GL_TEXTURE_CUBE_MAP_SEAMLESS"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8850" end="0x891F" vendor="NV">
+        <enum value="0x8850" name="GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV"/>
+        <enum value="0x8851" name="GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV"/>
+        <enum value="0x8852" name="GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV"/>
+        <enum value="0x8853" name="GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV"/>
+        <enum value="0x8854" name="GL_OFFSET_HILO_TEXTURE_2D_NV"/>
+        <enum value="0x8855" name="GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV"/>
+        <enum value="0x8856" name="GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV"/>
+        <enum value="0x8857" name="GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV"/>
+        <enum value="0x8858" name="GL_DEPENDENT_HILO_TEXTURE_2D_NV"/>
+        <enum value="0x8859" name="GL_DEPENDENT_RGB_TEXTURE_3D_NV"/>
+        <enum value="0x885A" name="GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV"/>
+        <enum value="0x885B" name="GL_DOT_PRODUCT_PASS_THROUGH_NV"/>
+        <enum value="0x885C" name="GL_DOT_PRODUCT_TEXTURE_1D_NV"/>
+        <enum value="0x885D" name="GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV"/>
+        <enum value="0x885E" name="GL_HILO8_NV"/>
+        <enum value="0x885F" name="GL_SIGNED_HILO8_NV"/>
+        <enum value="0x8860" name="GL_FORCE_BLUE_TO_ONE_NV"/>
+        <enum value="0x8861" name="GL_POINT_SPRITE"/>
+        <enum value="0x8861" name="GL_POINT_SPRITE_ARB"/>
+        <enum value="0x8861" name="GL_POINT_SPRITE_NV"/>
+        <enum value="0x8861" name="GL_POINT_SPRITE_OES"/>
+        <enum value="0x8862" name="GL_COORD_REPLACE"/>
+        <enum value="0x8862" name="GL_COORD_REPLACE_ARB"/>
+        <enum value="0x8862" name="GL_COORD_REPLACE_NV"/>
+        <enum value="0x8862" name="GL_COORD_REPLACE_OES"/>
+        <enum value="0x8863" name="GL_POINT_SPRITE_R_MODE_NV"/>
+        <enum value="0x8864" name="GL_PIXEL_COUNTER_BITS_NV"/>
+        <enum value="0x8864" name="GL_QUERY_COUNTER_BITS"/>
+        <enum value="0x8864" name="GL_QUERY_COUNTER_BITS_ARB"/>
+        <enum value="0x8864" name="GL_QUERY_COUNTER_BITS_EXT"/>
+        <enum value="0x8865" name="GL_CURRENT_OCCLUSION_QUERY_ID_NV"/>
+        <enum value="0x8865" name="GL_CURRENT_QUERY"/>
+        <enum value="0x8865" name="GL_CURRENT_QUERY_ARB"/>
+        <enum value="0x8865" name="GL_CURRENT_QUERY_EXT"/>
+        <enum value="0x8866" name="GL_PIXEL_COUNT_NV"/>
+        <enum value="0x8866" name="GL_QUERY_RESULT"/>
+        <enum value="0x8866" name="GL_QUERY_RESULT_ARB"/>
+        <enum value="0x8866" name="GL_QUERY_RESULT_EXT"/>
+        <enum value="0x8867" name="GL_PIXEL_COUNT_AVAILABLE_NV"/>
+        <enum value="0x8867" name="GL_QUERY_RESULT_AVAILABLE"/>
+        <enum value="0x8867" name="GL_QUERY_RESULT_AVAILABLE_ARB"/>
+        <enum value="0x8867" name="GL_QUERY_RESULT_AVAILABLE_EXT"/>
+        <enum value="0x8868" name="GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV"/>
+        <enum value="0x8869" name="GL_MAX_VERTEX_ATTRIBS"/>
+        <enum value="0x8869" name="GL_MAX_VERTEX_ATTRIBS_ARB"/>
+        <enum value="0x886A" name="GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"/>
+        <enum value="0x886A" name="GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB"/>
+            <unused start="0x886B" vendor="NV"/>
+        <enum value="0x886C" name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS"/>
+        <enum value="0x886C" name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT"/>
+        <enum value="0x886C" name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES"/>
+        <enum value="0x886D" name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS"/>
+        <enum value="0x886D" name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT"/>
+        <enum value="0x886D" name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES"/>
+        <enum value="0x886E" name="GL_DEPTH_STENCIL_TO_RGBA_NV"/>
+        <enum value="0x886F" name="GL_DEPTH_STENCIL_TO_BGRA_NV"/>
+        <enum value="0x8870" name="GL_FRAGMENT_PROGRAM_NV"/>
+        <enum value="0x8871" name="GL_MAX_TEXTURE_COORDS"/>
+        <enum value="0x8871" name="GL_MAX_TEXTURE_COORDS_ARB"/>
+        <enum value="0x8871" name="GL_MAX_TEXTURE_COORDS_NV"/>
+        <enum value="0x8872" name="GL_MAX_TEXTURE_IMAGE_UNITS"/>
+        <enum value="0x8872" name="GL_MAX_TEXTURE_IMAGE_UNITS_ARB"/>
+        <enum value="0x8872" name="GL_MAX_TEXTURE_IMAGE_UNITS_NV"/>
+        <enum value="0x8873" name="GL_FRAGMENT_PROGRAM_BINDING_NV"/>
+        <enum value="0x8874" name="GL_PROGRAM_ERROR_STRING_ARB"/>
+        <enum value="0x8874" name="GL_PROGRAM_ERROR_STRING_NV"/>
+        <enum value="0x8875" name="GL_PROGRAM_FORMAT_ASCII_ARB"/>
+        <enum value="0x8876" name="GL_PROGRAM_FORMAT_ARB"/>
+            <unused start="0x8877" vendor="NV" comment="Should have been assigned to PROGRAM_BINDING_ARB"/>
+        <enum value="0x8878" name="GL_WRITE_PIXEL_DATA_RANGE_NV"/>
+        <enum value="0x8879" name="GL_READ_PIXEL_DATA_RANGE_NV"/>
+        <enum value="0x887A" name="GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV"/>
+        <enum value="0x887B" name="GL_READ_PIXEL_DATA_RANGE_LENGTH_NV"/>
+        <enum value="0x887C" name="GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV"/>
+        <enum value="0x887D" name="GL_READ_PIXEL_DATA_RANGE_POINTER_NV"/>
+            <unused start="0x887E" vendor="NV"/>
+        <enum value="0x887F" name="GL_GEOMETRY_SHADER_INVOCATIONS"/>
+        <enum value="0x887F" name="GL_GEOMETRY_SHADER_INVOCATIONS_EXT"/>
+        <enum value="0x887F" name="GL_GEOMETRY_SHADER_INVOCATIONS_OES"/>
+        <enum value="0x8880" name="GL_FLOAT_R_NV"/>
+        <enum value="0x8881" name="GL_FLOAT_RG_NV"/>
+        <enum value="0x8882" name="GL_FLOAT_RGB_NV"/>
+        <enum value="0x8883" name="GL_FLOAT_RGBA_NV"/>
+        <enum value="0x8884" name="GL_FLOAT_R16_NV"/>
+        <enum value="0x8885" name="GL_FLOAT_R32_NV"/>
+        <enum value="0x8886" name="GL_FLOAT_RG16_NV"/>
+        <enum value="0x8887" name="GL_FLOAT_RG32_NV"/>
+        <enum value="0x8888" name="GL_FLOAT_RGB16_NV"/>
+        <enum value="0x8889" name="GL_FLOAT_RGB32_NV"/>
+        <enum value="0x888A" name="GL_FLOAT_RGBA16_NV"/>
+        <enum value="0x888B" name="GL_FLOAT_RGBA32_NV"/>
+        <enum value="0x888C" name="GL_TEXTURE_FLOAT_COMPONENTS_NV"/>
+        <enum value="0x888D" name="GL_FLOAT_CLEAR_COLOR_VALUE_NV"/>
+        <enum value="0x888E" name="GL_FLOAT_RGBA_MODE_NV"/>
+        <enum value="0x888F" name="GL_TEXTURE_UNSIGNED_REMAP_MODE_NV"/>
+        <enum value="0x8890" name="GL_DEPTH_BOUNDS_TEST_EXT"/>
+        <enum value="0x8891" name="GL_DEPTH_BOUNDS_EXT"/>
+        <enum value="0x8892" name="GL_ARRAY_BUFFER"/>
+        <enum value="0x8892" name="GL_ARRAY_BUFFER_ARB"/>
+        <enum value="0x8893" name="GL_ELEMENT_ARRAY_BUFFER"/>
+        <enum value="0x8893" name="GL_ELEMENT_ARRAY_BUFFER_ARB"/>
+        <enum value="0x8894" name="GL_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x8894" name="GL_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x8895" name="GL_ELEMENT_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x8895" name="GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x8896" name="GL_VERTEX_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x8896" name="GL_VERTEX_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x8897" name="GL_NORMAL_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x8897" name="GL_NORMAL_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x8898" name="GL_COLOR_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x8898" name="GL_COLOR_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x8899" name="GL_INDEX_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x8899" name="GL_INDEX_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x889A" name="GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x889A" name="GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x889B" name="GL_EDGE_FLAG_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x889B" name="GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x889C" name="GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x889C" name="GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x889D" name="GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x889D" name="GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x889D" name="GL_FOG_COORD_ARRAY_BUFFER_BINDING" alias="GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x889E" name="GL_WEIGHT_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x889E" name="GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x889E" name="GL_WEIGHT_ARRAY_BUFFER_BINDING_OES"/>
+        <enum value="0x889F" name="GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"/>
+        <enum value="0x889F" name="GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB"/>
+        <enum value="0x88A0" name="GL_PROGRAM_INSTRUCTIONS_ARB"/>
+        <enum value="0x88A1" name="GL_MAX_PROGRAM_INSTRUCTIONS_ARB"/>
+        <enum value="0x88A2" name="GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB"/>
+        <enum value="0x88A3" name="GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB"/>
+        <enum value="0x88A4" name="GL_PROGRAM_TEMPORARIES_ARB"/>
+        <enum value="0x88A5" name="GL_MAX_PROGRAM_TEMPORARIES_ARB"/>
+        <enum value="0x88A6" name="GL_PROGRAM_NATIVE_TEMPORARIES_ARB"/>
+        <enum value="0x88A7" name="GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB"/>
+        <enum value="0x88A8" name="GL_PROGRAM_PARAMETERS_ARB"/>
+        <enum value="0x88A9" name="GL_MAX_PROGRAM_PARAMETERS_ARB"/>
+        <enum value="0x88AA" name="GL_PROGRAM_NATIVE_PARAMETERS_ARB"/>
+        <enum value="0x88AB" name="GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB"/>
+        <enum value="0x88AC" name="GL_PROGRAM_ATTRIBS_ARB"/>
+        <enum value="0x88AD" name="GL_MAX_PROGRAM_ATTRIBS_ARB"/>
+        <enum value="0x88AE" name="GL_PROGRAM_NATIVE_ATTRIBS_ARB"/>
+        <enum value="0x88AF" name="GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB"/>
+        <enum value="0x88B0" name="GL_PROGRAM_ADDRESS_REGISTERS_ARB"/>
+        <enum value="0x88B1" name="GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB"/>
+        <enum value="0x88B2" name="GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB"/>
+        <enum value="0x88B3" name="GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB"/>
+        <enum value="0x88B4" name="GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB"/>
+        <enum value="0x88B5" name="GL_MAX_PROGRAM_ENV_PARAMETERS_ARB"/>
+        <enum value="0x88B6" name="GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB"/>
+        <enum value="0x88B7" name="GL_TRANSPOSE_CURRENT_MATRIX_ARB"/>
+        <enum value="0x88B8" name="GL_READ_ONLY"/>
+        <enum value="0x88B8" name="GL_READ_ONLY_ARB"/>
+        <enum value="0x88B9" name="GL_WRITE_ONLY"/>
+        <enum value="0x88B9" name="GL_WRITE_ONLY_ARB"/>
+        <enum value="0x88B9" name="GL_WRITE_ONLY_OES"/>
+        <enum value="0x88BA" name="GL_READ_WRITE"/>
+        <enum value="0x88BA" name="GL_READ_WRITE_ARB"/>
+        <enum value="0x88BB" name="GL_BUFFER_ACCESS"/>
+        <enum value="0x88BB" name="GL_BUFFER_ACCESS_ARB"/>
+        <enum value="0x88BB" name="GL_BUFFER_ACCESS_OES"/>
+        <enum value="0x88BC" name="GL_BUFFER_MAPPED"/>
+        <enum value="0x88BC" name="GL_BUFFER_MAPPED_ARB"/>
+        <enum value="0x88BC" name="GL_BUFFER_MAPPED_OES"/>
+        <enum value="0x88BD" name="GL_BUFFER_MAP_POINTER"/>
+        <enum value="0x88BD" name="GL_BUFFER_MAP_POINTER_ARB"/>
+        <enum value="0x88BD" name="GL_BUFFER_MAP_POINTER_OES"/>
+        <enum value="0x88BE" name="GL_WRITE_DISCARD_NV"/>
+        <enum value="0x88BF" name="GL_TIME_ELAPSED"/>
+        <enum value="0x88BF" name="GL_TIME_ELAPSED_EXT"/>
+        <enum value="0x88C0" name="GL_MATRIX0_ARB"/>
+        <enum value="0x88C1" name="GL_MATRIX1_ARB"/>
+        <enum value="0x88C2" name="GL_MATRIX2_ARB"/>
+        <enum value="0x88C3" name="GL_MATRIX3_ARB"/>
+        <enum value="0x88C4" name="GL_MATRIX4_ARB"/>
+        <enum value="0x88C5" name="GL_MATRIX5_ARB"/>
+        <enum value="0x88C6" name="GL_MATRIX6_ARB"/>
+        <enum value="0x88C7" name="GL_MATRIX7_ARB"/>
+        <enum value="0x88C8" name="GL_MATRIX8_ARB"/>
+        <enum value="0x88C9" name="GL_MATRIX9_ARB"/>
+        <enum value="0x88CA" name="GL_MATRIX10_ARB"/>
+        <enum value="0x88CB" name="GL_MATRIX11_ARB"/>
+        <enum value="0x88CC" name="GL_MATRIX12_ARB"/>
+        <enum value="0x88CD" name="GL_MATRIX13_ARB"/>
+        <enum value="0x88CE" name="GL_MATRIX14_ARB"/>
+        <enum value="0x88CF" name="GL_MATRIX15_ARB"/>
+        <enum value="0x88D0" name="GL_MATRIX16_ARB"/>
+        <enum value="0x88D1" name="GL_MATRIX17_ARB"/>
+        <enum value="0x88D2" name="GL_MATRIX18_ARB"/>
+        <enum value="0x88D3" name="GL_MATRIX19_ARB"/>
+        <enum value="0x88D4" name="GL_MATRIX20_ARB"/>
+        <enum value="0x88D5" name="GL_MATRIX21_ARB"/>
+        <enum value="0x88D6" name="GL_MATRIX22_ARB"/>
+        <enum value="0x88D7" name="GL_MATRIX23_ARB"/>
+        <enum value="0x88D8" name="GL_MATRIX24_ARB"/>
+        <enum value="0x88D9" name="GL_MATRIX25_ARB"/>
+        <enum value="0x88DA" name="GL_MATRIX26_ARB"/>
+        <enum value="0x88DB" name="GL_MATRIX27_ARB"/>
+        <enum value="0x88DC" name="GL_MATRIX28_ARB"/>
+        <enum value="0x88DD" name="GL_MATRIX29_ARB"/>
+        <enum value="0x88DE" name="GL_MATRIX30_ARB"/>
+        <enum value="0x88DF" name="GL_MATRIX31_ARB"/>
+        <enum value="0x88E0" name="GL_STREAM_DRAW"/>
+        <enum value="0x88E0" name="GL_STREAM_DRAW_ARB"/>
+        <enum value="0x88E1" name="GL_STREAM_READ"/>
+        <enum value="0x88E1" name="GL_STREAM_READ_ARB"/>
+        <enum value="0x88E2" name="GL_STREAM_COPY"/>
+        <enum value="0x88E2" name="GL_STREAM_COPY_ARB"/>
+            <unused start="0x88E3" vendor="NV" comment="To extend ARB_vbo"/>
+        <enum value="0x88E4" name="GL_STATIC_DRAW"/>
+        <enum value="0x88E4" name="GL_STATIC_DRAW_ARB"/>
+        <enum value="0x88E5" name="GL_STATIC_READ"/>
+        <enum value="0x88E5" name="GL_STATIC_READ_ARB"/>
+        <enum value="0x88E6" name="GL_STATIC_COPY"/>
+        <enum value="0x88E6" name="GL_STATIC_COPY_ARB"/>
+            <unused start="0x88E7" vendor="NV" comment="To extend ARB_vbo"/>
+        <enum value="0x88E8" name="GL_DYNAMIC_DRAW"/>
+        <enum value="0x88E8" name="GL_DYNAMIC_DRAW_ARB"/>
+        <enum value="0x88E9" name="GL_DYNAMIC_READ"/>
+        <enum value="0x88E9" name="GL_DYNAMIC_READ_ARB"/>
+        <enum value="0x88EA" name="GL_DYNAMIC_COPY"/>
+        <enum value="0x88EA" name="GL_DYNAMIC_COPY_ARB"/>
+        <enum value="0x88EB" name="GL_PIXEL_PACK_BUFFER"/>
+        <enum value="0x88EB" name="GL_PIXEL_PACK_BUFFER_ARB"/>
+        <enum value="0x88EB" name="GL_PIXEL_PACK_BUFFER_EXT"/>
+        <enum value="0x88EC" name="GL_PIXEL_UNPACK_BUFFER"/>
+        <enum value="0x88EC" name="GL_PIXEL_UNPACK_BUFFER_ARB"/>
+        <enum value="0x88EC" name="GL_PIXEL_UNPACK_BUFFER_EXT"/>
+        <enum value="0x88ED" name="GL_PIXEL_PACK_BUFFER_BINDING"/>
+        <enum value="0x88ED" name="GL_PIXEL_PACK_BUFFER_BINDING_ARB"/>
+        <enum value="0x88ED" name="GL_PIXEL_PACK_BUFFER_BINDING_EXT"/>
+        <enum value="0x88EE" name="GL_ETC1_SRGB8_NV"/>
+        <enum value="0x88EF" name="GL_PIXEL_UNPACK_BUFFER_BINDING"/>
+        <enum value="0x88EF" name="GL_PIXEL_UNPACK_BUFFER_BINDING_ARB"/>
+        <enum value="0x88EF" name="GL_PIXEL_UNPACK_BUFFER_BINDING_EXT"/>
+        <enum value="0x88F0" name="GL_DEPTH24_STENCIL8"/>
+        <enum value="0x88F0" name="GL_DEPTH24_STENCIL8_EXT"/>
+        <enum value="0x88F0" name="GL_DEPTH24_STENCIL8_OES"/>
+        <enum value="0x88F1" name="GL_TEXTURE_STENCIL_SIZE"/>
+        <enum value="0x88F1" name="GL_TEXTURE_STENCIL_SIZE_EXT"/>
+        <enum value="0x88F2" name="GL_STENCIL_TAG_BITS_EXT"/>
+        <enum value="0x88F3" name="GL_STENCIL_CLEAR_TAG_VALUE_EXT"/>
+        <enum value="0x88F4" name="GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV"/>
+        <enum value="0x88F5" name="GL_MAX_PROGRAM_CALL_DEPTH_NV"/>
+        <enum value="0x88F6" name="GL_MAX_PROGRAM_IF_DEPTH_NV"/>
+        <enum value="0x88F7" name="GL_MAX_PROGRAM_LOOP_DEPTH_NV"/>
+        <enum value="0x88F8" name="GL_MAX_PROGRAM_LOOP_COUNT_NV"/>
+        <enum value="0x88F9" name="GL_SRC1_COLOR"/>
+        <enum value="0x88F9" name="GL_SRC1_COLOR_EXT"/>
+        <enum value="0x88FA" name="GL_ONE_MINUS_SRC1_COLOR"/>
+        <enum value="0x88FA" name="GL_ONE_MINUS_SRC1_COLOR_EXT"/>
+        <enum value="0x88FB" name="GL_ONE_MINUS_SRC1_ALPHA"/>
+        <enum value="0x88FB" name="GL_ONE_MINUS_SRC1_ALPHA_EXT"/>
+        <enum value="0x88FC" name="GL_MAX_DUAL_SOURCE_DRAW_BUFFERS"/>
+        <enum value="0x88FC" name="GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT"/>
+        <enum value="0x88FD" name="GL_VERTEX_ATTRIB_ARRAY_INTEGER"/>
+        <enum value="0x88FD" name="GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT"/>
+        <enum value="0x88FD" name="GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV"/>
+        <enum value="0x88FE" name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR"/>
+        <enum value="0x88FE" name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE"/>
+        <enum value="0x88FE" name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB"/>
+        <enum value="0x88FE" name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT"/>
+        <enum value="0x88FE" name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV"/>
+        <enum value="0x88FF" name="GL_MAX_ARRAY_TEXTURE_LAYERS"/>
+        <enum value="0x88FF" name="GL_MAX_ARRAY_TEXTURE_LAYERS_EXT"/>
+        <enum value="0x8904" name="GL_MIN_PROGRAM_TEXEL_OFFSET"/>
+        <enum value="0x8904" name="GL_MIN_PROGRAM_TEXEL_OFFSET_EXT"/>
+        <enum value="0x8904" name="GL_MIN_PROGRAM_TEXEL_OFFSET_NV"/>
+        <enum value="0x8905" name="GL_MAX_PROGRAM_TEXEL_OFFSET"/>
+        <enum value="0x8905" name="GL_MAX_PROGRAM_TEXEL_OFFSET_EXT"/>
+        <enum value="0x8905" name="GL_MAX_PROGRAM_TEXEL_OFFSET_NV"/>
+        <enum value="0x8906" name="GL_PROGRAM_ATTRIB_COMPONENTS_NV"/>
+        <enum value="0x8907" name="GL_PROGRAM_RESULT_COMPONENTS_NV"/>
+        <enum value="0x8908" name="GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV"/>
+        <enum value="0x8909" name="GL_MAX_PROGRAM_RESULT_COMPONENTS_NV"/>
+        <enum value="0x8910" name="GL_STENCIL_TEST_TWO_SIDE_EXT"/>
+        <enum value="0x8911" name="GL_ACTIVE_STENCIL_FACE_EXT"/>
+        <enum value="0x8912" name="GL_MIRROR_CLAMP_TO_BORDER_EXT"/>
+            <unused start="0x8913" vendor="NV"/>
+        <enum value="0x8914" name="GL_SAMPLES_PASSED"/>
+        <enum value="0x8914" name="GL_SAMPLES_PASSED_ARB"/>
+            <unused start="0x8915" vendor="NV"/>
+        <enum value="0x8916" name="GL_GEOMETRY_VERTICES_OUT"/>
+        <enum value="0x8916" name="GL_GEOMETRY_LINKED_VERTICES_OUT_EXT"/>
+        <enum value="0x8916" name="GL_GEOMETRY_LINKED_VERTICES_OUT_OES"/>
+        <enum value="0x8917" name="GL_GEOMETRY_INPUT_TYPE"/>
+        <enum value="0x8917" name="GL_GEOMETRY_LINKED_INPUT_TYPE_EXT"/>
+        <enum value="0x8917" name="GL_GEOMETRY_LINKED_INPUT_TYPE_OES"/>
+        <enum value="0x8918" name="GL_GEOMETRY_OUTPUT_TYPE"/>
+        <enum value="0x8918" name="GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT"/>
+        <enum value="0x8918" name="GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES"/>
+        <enum value="0x8919" name="GL_SAMPLER_BINDING"/>
+        <enum value="0x891A" name="GL_CLAMP_VERTEX_COLOR"/>
+        <enum value="0x891A" name="GL_CLAMP_VERTEX_COLOR_ARB"/>
+        <enum value="0x891B" name="GL_CLAMP_FRAGMENT_COLOR"/>
+        <enum value="0x891B" name="GL_CLAMP_FRAGMENT_COLOR_ARB"/>
+        <enum value="0x891C" name="GL_CLAMP_READ_COLOR"/>
+        <enum value="0x891C" name="GL_CLAMP_READ_COLOR_ARB"/>
+        <enum value="0x891D" name="GL_FIXED_ONLY"/>
+        <enum value="0x891D" name="GL_FIXED_ONLY_ARB"/>
+        <enum value="0x891E" name="GL_TESS_CONTROL_PROGRAM_NV"/>
+        <enum value="0x891F" name="GL_TESS_EVALUATION_PROGRAM_NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8920" end="0x897F" vendor="AMD">
+        <enum value="0x8920" name="GL_FRAGMENT_SHADER_ATI"/>
+        <enum value="0x8921" name="GL_REG_0_ATI"/>
+        <enum value="0x8922" name="GL_REG_1_ATI"/>
+        <enum value="0x8923" name="GL_REG_2_ATI"/>
+        <enum value="0x8924" name="GL_REG_3_ATI"/>
+        <enum value="0x8925" name="GL_REG_4_ATI"/>
+        <enum value="0x8926" name="GL_REG_5_ATI"/>
+        <enum value="0x8927" name="GL_REG_6_ATI"/>
+        <enum value="0x8928" name="GL_REG_7_ATI"/>
+        <enum value="0x8929" name="GL_REG_8_ATI"/>
+        <enum value="0x892A" name="GL_REG_9_ATI"/>
+        <enum value="0x892B" name="GL_REG_10_ATI"/>
+        <enum value="0x892C" name="GL_REG_11_ATI"/>
+        <enum value="0x892D" name="GL_REG_12_ATI"/>
+        <enum value="0x892E" name="GL_REG_13_ATI"/>
+        <enum value="0x892F" name="GL_REG_14_ATI"/>
+        <enum value="0x8930" name="GL_REG_15_ATI"/>
+        <enum value="0x8931" name="GL_REG_16_ATI"/>
+        <enum value="0x8932" name="GL_REG_17_ATI"/>
+        <enum value="0x8933" name="GL_REG_18_ATI"/>
+        <enum value="0x8934" name="GL_REG_19_ATI"/>
+        <enum value="0x8935" name="GL_REG_20_ATI"/>
+        <enum value="0x8936" name="GL_REG_21_ATI"/>
+        <enum value="0x8937" name="GL_REG_22_ATI"/>
+        <enum value="0x8938" name="GL_REG_23_ATI"/>
+        <enum value="0x8939" name="GL_REG_24_ATI"/>
+        <enum value="0x893A" name="GL_REG_25_ATI"/>
+        <enum value="0x893B" name="GL_REG_26_ATI"/>
+        <enum value="0x893C" name="GL_REG_27_ATI"/>
+        <enum value="0x893D" name="GL_REG_28_ATI"/>
+        <enum value="0x893E" name="GL_REG_29_ATI"/>
+        <enum value="0x893F" name="GL_REG_30_ATI"/>
+        <enum value="0x8940" name="GL_REG_31_ATI"/>
+        <enum value="0x8941" name="GL_CON_0_ATI"/>
+        <enum value="0x8942" name="GL_CON_1_ATI"/>
+        <enum value="0x8943" name="GL_CON_2_ATI"/>
+        <enum value="0x8944" name="GL_CON_3_ATI"/>
+        <enum value="0x8945" name="GL_CON_4_ATI"/>
+        <enum value="0x8946" name="GL_CON_5_ATI"/>
+        <enum value="0x8947" name="GL_CON_6_ATI"/>
+        <enum value="0x8948" name="GL_CON_7_ATI"/>
+        <enum value="0x8949" name="GL_CON_8_ATI"/>
+        <enum value="0x894A" name="GL_CON_9_ATI"/>
+        <enum value="0x894B" name="GL_CON_10_ATI"/>
+        <enum value="0x894C" name="GL_CON_11_ATI"/>
+        <enum value="0x894D" name="GL_CON_12_ATI"/>
+        <enum value="0x894E" name="GL_CON_13_ATI"/>
+        <enum value="0x894F" name="GL_CON_14_ATI"/>
+        <enum value="0x8950" name="GL_CON_15_ATI"/>
+        <enum value="0x8951" name="GL_CON_16_ATI"/>
+        <enum value="0x8952" name="GL_CON_17_ATI"/>
+        <enum value="0x8953" name="GL_CON_18_ATI"/>
+        <enum value="0x8954" name="GL_CON_19_ATI"/>
+        <enum value="0x8955" name="GL_CON_20_ATI"/>
+        <enum value="0x8956" name="GL_CON_21_ATI"/>
+        <enum value="0x8957" name="GL_CON_22_ATI"/>
+        <enum value="0x8958" name="GL_CON_23_ATI"/>
+        <enum value="0x8959" name="GL_CON_24_ATI"/>
+        <enum value="0x895A" name="GL_CON_25_ATI"/>
+        <enum value="0x895B" name="GL_CON_26_ATI"/>
+        <enum value="0x895C" name="GL_CON_27_ATI"/>
+        <enum value="0x895D" name="GL_CON_28_ATI"/>
+        <enum value="0x895E" name="GL_CON_29_ATI"/>
+        <enum value="0x895F" name="GL_CON_30_ATI"/>
+        <enum value="0x8960" name="GL_CON_31_ATI"/>
+        <enum value="0x8961" name="GL_MOV_ATI"/>
+        <enum value="0x8963" name="GL_ADD_ATI"/>
+        <enum value="0x8964" name="GL_MUL_ATI"/>
+        <enum value="0x8965" name="GL_SUB_ATI"/>
+        <enum value="0x8966" name="GL_DOT3_ATI"/>
+        <enum value="0x8967" name="GL_DOT4_ATI"/>
+        <enum value="0x8968" name="GL_MAD_ATI"/>
+        <enum value="0x8969" name="GL_LERP_ATI"/>
+        <enum value="0x896A" name="GL_CND_ATI"/>
+        <enum value="0x896B" name="GL_CND0_ATI"/>
+        <enum value="0x896C" name="GL_DOT2_ADD_ATI"/>
+        <enum value="0x896D" name="GL_SECONDARY_INTERPOLATOR_ATI"/>
+        <enum value="0x896E" name="GL_NUM_FRAGMENT_REGISTERS_ATI"/>
+        <enum value="0x896F" name="GL_NUM_FRAGMENT_CONSTANTS_ATI"/>
+        <enum value="0x8970" name="GL_NUM_PASSES_ATI"/>
+        <enum value="0x8971" name="GL_NUM_INSTRUCTIONS_PER_PASS_ATI"/>
+        <enum value="0x8972" name="GL_NUM_INSTRUCTIONS_TOTAL_ATI"/>
+        <enum value="0x8973" name="GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI"/>
+        <enum value="0x8974" name="GL_NUM_LOOPBACK_COMPONENTS_ATI"/>
+        <enum value="0x8975" name="GL_COLOR_ALPHA_PAIRING_ATI"/>
+        <enum value="0x8976" name="GL_SWIZZLE_STR_ATI"/>
+        <enum value="0x8977" name="GL_SWIZZLE_STQ_ATI"/>
+        <enum value="0x8978" name="GL_SWIZZLE_STR_DR_ATI"/>
+        <enum value="0x8979" name="GL_SWIZZLE_STQ_DQ_ATI"/>
+        <enum value="0x897A" name="GL_SWIZZLE_STRQ_ATI"/>
+        <enum value="0x897B" name="GL_SWIZZLE_STRQ_DQ_ATI"/>
+            <unused start="0x897C" end="0x897F" vendor="AMD"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8980" end="0x898F" vendor="OML">
+        <enum value="0x8980" name="GL_INTERLACE_OML"/>
+        <enum value="0x8981" name="GL_INTERLACE_READ_OML"/>
+        <enum value="0x8982" name="GL_FORMAT_SUBSAMPLE_24_24_OML"/>
+        <enum value="0x8983" name="GL_FORMAT_SUBSAMPLE_244_244_OML"/>
+        <enum value="0x8984" name="GL_PACK_RESAMPLE_OML"/>
+        <enum value="0x8985" name="GL_UNPACK_RESAMPLE_OML"/>
+        <enum value="0x8986" name="GL_RESAMPLE_REPLICATE_OML"/>
+        <enum value="0x8987" name="GL_RESAMPLE_ZERO_FILL_OML"/>
+        <enum value="0x8988" name="GL_RESAMPLE_AVERAGE_OML"/>
+        <enum value="0x8989" name="GL_RESAMPLE_DECIMATE_OML"/>
+        <enum value="0x898A" name="GL_POINT_SIZE_ARRAY_TYPE_OES"/>
+        <enum value="0x898B" name="GL_POINT_SIZE_ARRAY_STRIDE_OES"/>
+        <enum value="0x898C" name="GL_POINT_SIZE_ARRAY_POINTER_OES"/>
+        <enum value="0x898D" name="GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES"/>
+        <enum value="0x898E" name="GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES"/>
+        <enum value="0x898F" name="GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8990" end="0x899F" vendor="ZiiLabs">
+            <unused start="0x8990" end="0x899F" vendor="ZiiLabs"/>
+    </enums>
+
+    <enums namespace="GL" start="0x89A0" end="0x89FF" vendor="Matrox">
+            <unused start="0x89A0" end="0x89FF" vendor="Matrox"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8A00" end="0x8A7F" vendor="APPLE">
+        <enum value="0x8A00" name="GL_VERTEX_ATTRIB_MAP1_APPLE"/>
+        <enum value="0x8A01" name="GL_VERTEX_ATTRIB_MAP2_APPLE"/>
+        <enum value="0x8A02" name="GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE"/>
+        <enum value="0x8A03" name="GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE"/>
+        <enum value="0x8A04" name="GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE"/>
+        <enum value="0x8A05" name="GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE"/>
+        <enum value="0x8A06" name="GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE"/>
+        <enum value="0x8A07" name="GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE"/>
+        <enum value="0x8A08" name="GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE"/>
+        <enum value="0x8A09" name="GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE"/>
+        <enum value="0x8A0A" name="GL_DRAW_PIXELS_APPLE"/>
+        <enum value="0x8A0B" name="GL_FENCE_APPLE"/>
+        <enum value="0x8A0C" name="GL_ELEMENT_ARRAY_APPLE"/>
+        <enum value="0x8A0D" name="GL_ELEMENT_ARRAY_TYPE_APPLE"/>
+        <enum value="0x8A0E" name="GL_ELEMENT_ARRAY_POINTER_APPLE"/>
+        <enum value="0x8A0F" name="GL_COLOR_FLOAT_APPLE"/>
+            <unused start="0x8A10" vendor="APPLE" comment="Unknown extension (Khronos bug 632)"/>
+            <!-- <enum value="0x8A10" name="GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE"/> -->
+        <enum value="0x8A11" name="GL_UNIFORM_BUFFER"/>
+        <enum value="0x8A12" name="GL_BUFFER_SERIALIZED_MODIFY_APPLE"/>
+        <enum value="0x8A13" name="GL_BUFFER_FLUSHING_UNMAP_APPLE"/>
+        <enum value="0x8A14" name="GL_AUX_DEPTH_STENCIL_APPLE"/>
+        <enum value="0x8A15" name="GL_PACK_ROW_BYTES_APPLE"/>
+        <enum value="0x8A16" name="GL_UNPACK_ROW_BYTES_APPLE"/>
+            <unused start="0x8A17" end="0x8A18" vendor="APPLE"/>
+        <enum value="0x8A19" name="GL_RELEASED_APPLE"/>
+        <enum value="0x8A1A" name="GL_VOLATILE_APPLE"/>
+        <enum value="0x8A1B" name="GL_RETAINED_APPLE"/>
+        <enum value="0x8A1C" name="GL_UNDEFINED_APPLE"/>
+        <enum value="0x8A1D" name="GL_PURGEABLE_APPLE"/>
+            <unused start="0x8A1E" vendor="APPLE"/>
+        <enum value="0x8A1F" name="GL_RGB_422_APPLE"/>
+            <unused start="0x8A20" end="0x8A27" vendor="APPLE"/>
+        <enum value="0x8A28" name="GL_UNIFORM_BUFFER_BINDING"/>
+        <enum value="0x8A29" name="GL_UNIFORM_BUFFER_START"/>
+        <enum value="0x8A2A" name="GL_UNIFORM_BUFFER_SIZE"/>
+        <enum value="0x8A2B" name="GL_MAX_VERTEX_UNIFORM_BLOCKS"/>
+        <enum value="0x8A2C" name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS"/>
+        <enum value="0x8A2C" name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT"/>
+        <enum value="0x8A2C" name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES"/>
+        <enum value="0x8A2D" name="GL_MAX_FRAGMENT_UNIFORM_BLOCKS"/>
+        <enum value="0x8A2E" name="GL_MAX_COMBINED_UNIFORM_BLOCKS"/>
+        <enum value="0x8A2F" name="GL_MAX_UNIFORM_BUFFER_BINDINGS"/>
+        <enum value="0x8A30" name="GL_MAX_UNIFORM_BLOCK_SIZE"/>
+        <enum value="0x8A31" name="GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS"/>
+        <enum value="0x8A32" name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"/>
+        <enum value="0x8A32" name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8A32" name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES"/>
+        <enum value="0x8A33" name="GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS"/>
+        <enum value="0x8A34" name="GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT"/>
+        <enum value="0x8A35" name="GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH"/>
+        <enum value="0x8A36" name="GL_ACTIVE_UNIFORM_BLOCKS"/>
+        <enum value="0x8A37" name="GL_UNIFORM_TYPE"/>
+        <enum value="0x8A38" name="GL_UNIFORM_SIZE"/>
+        <enum value="0x8A39" name="GL_UNIFORM_NAME_LENGTH"/>
+        <enum value="0x8A3A" name="GL_UNIFORM_BLOCK_INDEX"/>
+        <enum value="0x8A3B" name="GL_UNIFORM_OFFSET"/>
+        <enum value="0x8A3C" name="GL_UNIFORM_ARRAY_STRIDE"/>
+        <enum value="0x8A3D" name="GL_UNIFORM_MATRIX_STRIDE"/>
+        <enum value="0x8A3E" name="GL_UNIFORM_IS_ROW_MAJOR"/>
+        <enum value="0x8A3F" name="GL_UNIFORM_BLOCK_BINDING"/>
+        <enum value="0x8A40" name="GL_UNIFORM_BLOCK_DATA_SIZE"/>
+        <enum value="0x8A41" name="GL_UNIFORM_BLOCK_NAME_LENGTH"/>
+        <enum value="0x8A42" name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS"/>
+        <enum value="0x8A43" name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES"/>
+        <enum value="0x8A44" name="GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"/>
+        <enum value="0x8A45" name="GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER"/>
+        <enum value="0x8A46" name="GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"/>
+            <unused start="0x8A47" vendor="APPLE"/>
+        <enum value="0x8A48" name="GL_TEXTURE_SRGB_DECODE_EXT"/>
+        <enum value="0x8A49" name="GL_DECODE_EXT"/>
+        <enum value="0x8A4A" name="GL_SKIP_DECODE_EXT"/>
+            <unused start="0x8A4B" end="0x8A4E" vendor="APPLE"/>
+        <enum value="0x8A4F" name="GL_PROGRAM_PIPELINE_OBJECT_EXT"/>
+            <unused start="0x8A50" vendor="APPLE"/>
+        <enum value="0x8A51" name="GL_RGB_RAW_422_APPLE"/>
+        <enum value="0x8A52" name="GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT"/>
+        <enum value="0x8A53" name="GL_SYNC_OBJECT_APPLE"/>
+        <enum value="0x8A54" name="GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT"/>
+        <enum value="0x8A55" name="GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT"/>
+        <enum value="0x8A56" name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT"/>
+        <enum value="0x8A57" name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT"/>
+            <unused start="0x8A58" end="0x8A7F" vendor="APPLE"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8A80" end="0x8AEF" vendor="Matrox">
+            <unused start="0x8A80" end="0x8AEF" vendor="Matrox"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8AF0" end="0x8B2F" vendor="Chromium" comment="For Brian Paul">
+            <unused start="0x8AF0" end="0x8B2F" vendor="Chromium"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8B30" end="0x8B3F" group="ShaderType" vendor="ARB">
+        <enum value="0x8B30" name="GL_FRAGMENT_SHADER"/>
+        <enum value="0x8B30" name="GL_FRAGMENT_SHADER_ARB"/>
+        <enum value="0x8B31" name="GL_VERTEX_SHADER"/>
+        <enum value="0x8B31" name="GL_VERTEX_SHADER_ARB"/>
+            <unused start="0x8B32" end="0x8B3F" comment="For shader types"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8B40" end="0x8B47" group="ContainerType" vendor="ARB">
+        <enum value="0x8B40" name="GL_PROGRAM_OBJECT_ARB"/>
+        <enum value="0x8B40" name="GL_PROGRAM_OBJECT_EXT"/>
+            <unused start="0x8B41" end="0x8B47" comment="For container types"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8B48" end="0x8B4F" vendor="ARB">
+        <enum value="0x8B48" name="GL_SHADER_OBJECT_ARB"/>
+        <enum value="0x8B48" name="GL_SHADER_OBJECT_EXT"/>
+        <enum value="0x8B49" name="GL_MAX_FRAGMENT_UNIFORM_COMPONENTS"/>
+        <enum value="0x8B49" name="GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB"/>
+        <enum value="0x8B4A" name="GL_MAX_VERTEX_UNIFORM_COMPONENTS"/>
+        <enum value="0x8B4A" name="GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB"/>
+        <enum value="0x8B4B" name="GL_MAX_VARYING_FLOATS"/>
+        <enum value="0x8B4B" name="GL_MAX_VARYING_COMPONENTS" alias="MAX_VARYING_FLOATS"/>
+        <enum value="0x8B4B" name="GL_MAX_VARYING_COMPONENTS_EXT"/>
+        <enum value="0x8B4B" name="GL_MAX_VARYING_FLOATS_ARB"/>
+        <enum value="0x8B4C" name="GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS"/>
+        <enum value="0x8B4C" name="GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB"/>
+        <enum value="0x8B4D" name="GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS"/>
+        <enum value="0x8B4D" name="GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB"/>
+        <enum value="0x8B4E" name="GL_OBJECT_TYPE_ARB"/>
+        <enum value="0x8B4F" name="GL_SHADER_TYPE"/>
+        <enum value="0x8B4F" name="GL_OBJECT_SUBTYPE_ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8B50" end="0x8B7F" group="AttributeType" vendor="ARB">
+        <enum value="0x8B50" name="GL_FLOAT_VEC2"/>
+        <enum value="0x8B50" name="GL_FLOAT_VEC2_ARB"/>
+        <enum value="0x8B51" name="GL_FLOAT_VEC3"/>
+        <enum value="0x8B51" name="GL_FLOAT_VEC3_ARB"/>
+        <enum value="0x8B52" name="GL_FLOAT_VEC4"/>
+        <enum value="0x8B52" name="GL_FLOAT_VEC4_ARB"/>
+        <enum value="0x8B53" name="GL_INT_VEC2"/>
+        <enum value="0x8B53" name="GL_INT_VEC2_ARB"/>
+        <enum value="0x8B54" name="GL_INT_VEC3"/>
+        <enum value="0x8B54" name="GL_INT_VEC3_ARB"/>
+        <enum value="0x8B55" name="GL_INT_VEC4"/>
+        <enum value="0x8B55" name="GL_INT_VEC4_ARB"/>
+        <enum value="0x8B56" name="GL_BOOL"/>
+        <enum value="0x8B56" name="GL_BOOL_ARB"/>
+        <enum value="0x8B57" name="GL_BOOL_VEC2"/>
+        <enum value="0x8B57" name="GL_BOOL_VEC2_ARB"/>
+        <enum value="0x8B58" name="GL_BOOL_VEC3"/>
+        <enum value="0x8B58" name="GL_BOOL_VEC3_ARB"/>
+        <enum value="0x8B59" name="GL_BOOL_VEC4"/>
+        <enum value="0x8B59" name="GL_BOOL_VEC4_ARB"/>
+        <enum value="0x8B5A" name="GL_FLOAT_MAT2"/>
+        <enum value="0x8B5A" name="GL_FLOAT_MAT2_ARB"/>
+        <enum value="0x8B5B" name="GL_FLOAT_MAT3"/>
+        <enum value="0x8B5B" name="GL_FLOAT_MAT3_ARB"/>
+        <enum value="0x8B5C" name="GL_FLOAT_MAT4"/>
+        <enum value="0x8B5C" name="GL_FLOAT_MAT4_ARB"/>
+        <enum value="0x8B5D" name="GL_SAMPLER_1D"/>
+        <enum value="0x8B5D" name="GL_SAMPLER_1D_ARB"/>
+        <enum value="0x8B5E" name="GL_SAMPLER_2D"/>
+        <enum value="0x8B5E" name="GL_SAMPLER_2D_ARB"/>
+        <enum value="0x8B5F" name="GL_SAMPLER_3D"/>
+        <enum value="0x8B5F" name="GL_SAMPLER_3D_ARB"/>
+        <enum value="0x8B5F" name="GL_SAMPLER_3D_OES"/>
+        <enum value="0x8B60" name="GL_SAMPLER_CUBE"/>
+        <enum value="0x8B60" name="GL_SAMPLER_CUBE_ARB"/>
+        <enum value="0x8B61" name="GL_SAMPLER_1D_SHADOW"/>
+        <enum value="0x8B61" name="GL_SAMPLER_1D_SHADOW_ARB"/>
+        <enum value="0x8B62" name="GL_SAMPLER_2D_SHADOW"/>
+        <enum value="0x8B62" name="GL_SAMPLER_2D_SHADOW_ARB"/>
+        <enum value="0x8B62" name="GL_SAMPLER_2D_SHADOW_EXT"/>
+        <enum value="0x8B63" name="GL_SAMPLER_2D_RECT"/>
+        <enum value="0x8B63" name="GL_SAMPLER_2D_RECT_ARB"/>
+        <enum value="0x8B64" name="GL_SAMPLER_2D_RECT_SHADOW"/>
+        <enum value="0x8B64" name="GL_SAMPLER_2D_RECT_SHADOW_ARB"/>
+        <enum value="0x8B65" name="GL_FLOAT_MAT2x3"/>
+        <enum value="0x8B65" name="GL_FLOAT_MAT2x3_NV"/>
+        <enum value="0x8B66" name="GL_FLOAT_MAT2x4"/>
+        <enum value="0x8B66" name="GL_FLOAT_MAT2x4_NV"/>
+        <enum value="0x8B67" name="GL_FLOAT_MAT3x2"/>
+        <enum value="0x8B67" name="GL_FLOAT_MAT3x2_NV"/>
+        <enum value="0x8B68" name="GL_FLOAT_MAT3x4"/>
+        <enum value="0x8B68" name="GL_FLOAT_MAT3x4_NV"/>
+        <enum value="0x8B69" name="GL_FLOAT_MAT4x2"/>
+        <enum value="0x8B69" name="GL_FLOAT_MAT4x2_NV"/>
+        <enum value="0x8B6A" name="GL_FLOAT_MAT4x3"/>
+        <enum value="0x8B6A" name="GL_FLOAT_MAT4x3_NV"/>
+            <unused start="0x8B6B" end="0x8B7F" comment="For attribute types"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8B80" end="0x8B8F" vendor="ARB">
+        <enum value="0x8B80" name="GL_DELETE_STATUS"/>
+        <enum value="0x8B80" name="GL_OBJECT_DELETE_STATUS_ARB"/>
+        <enum value="0x8B81" name="GL_COMPILE_STATUS"/>
+        <enum value="0x8B81" name="GL_OBJECT_COMPILE_STATUS_ARB"/>
+        <enum value="0x8B82" name="GL_LINK_STATUS"/>
+        <enum value="0x8B82" name="GL_OBJECT_LINK_STATUS_ARB"/>
+        <enum value="0x8B83" name="GL_VALIDATE_STATUS"/>
+        <enum value="0x8B83" name="GL_OBJECT_VALIDATE_STATUS_ARB"/>
+        <enum value="0x8B84" name="GL_INFO_LOG_LENGTH"/>
+        <enum value="0x8B84" name="GL_OBJECT_INFO_LOG_LENGTH_ARB"/>
+        <enum value="0x8B85" name="GL_ATTACHED_SHADERS"/>
+        <enum value="0x8B85" name="GL_OBJECT_ATTACHED_OBJECTS_ARB"/>
+        <enum value="0x8B86" name="GL_ACTIVE_UNIFORMS"/>
+        <enum value="0x8B86" name="GL_OBJECT_ACTIVE_UNIFORMS_ARB"/>
+        <enum value="0x8B87" name="GL_ACTIVE_UNIFORM_MAX_LENGTH"/>
+        <enum value="0x8B87" name="GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB"/>
+        <enum value="0x8B88" name="GL_SHADER_SOURCE_LENGTH"/>
+        <enum value="0x8B88" name="GL_OBJECT_SHADER_SOURCE_LENGTH_ARB"/>
+        <enum value="0x8B89" name="GL_ACTIVE_ATTRIBUTES"/>
+        <enum value="0x8B89" name="GL_OBJECT_ACTIVE_ATTRIBUTES_ARB"/>
+        <enum value="0x8B8A" name="GL_ACTIVE_ATTRIBUTE_MAX_LENGTH"/>
+        <enum value="0x8B8A" name="GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB"/>
+        <enum value="0x8B8B" name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT"/>
+        <enum value="0x8B8B" name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB"/>
+        <enum value="0x8B8B" name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES"/>
+        <enum value="0x8B8C" name="GL_SHADING_LANGUAGE_VERSION"/>
+        <enum value="0x8B8C" name="GL_SHADING_LANGUAGE_VERSION_ARB"/>
+        <enum value="0x8B8D" name="GL_CURRENT_PROGRAM"/>
+        <enum value="0x8B8D" api="gl" name="GL_ACTIVE_PROGRAM_EXT" alias="GL_CURRENT_PROGRAM" comment="For the OpenGL version of EXT_separate_shader_objects"/>
+            <unused start="0x8B8E" end="0x8B8F" vendor="ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8B90" end="0x8B9F" vendor="OES">
+        <enum value="0x8B90" name="GL_PALETTE4_RGB8_OES"/>
+        <enum value="0x8B91" name="GL_PALETTE4_RGBA8_OES"/>
+        <enum value="0x8B92" name="GL_PALETTE4_R5_G6_B5_OES"/>
+        <enum value="0x8B93" name="GL_PALETTE4_RGBA4_OES"/>
+        <enum value="0x8B94" name="GL_PALETTE4_RGB5_A1_OES"/>
+        <enum value="0x8B95" name="GL_PALETTE8_RGB8_OES"/>
+        <enum value="0x8B96" name="GL_PALETTE8_RGBA8_OES"/>
+        <enum value="0x8B97" name="GL_PALETTE8_R5_G6_B5_OES"/>
+        <enum value="0x8B98" name="GL_PALETTE8_RGBA4_OES"/>
+        <enum value="0x8B99" name="GL_PALETTE8_RGB5_A1_OES"/>
+        <enum value="0x8B9A" name="GL_IMPLEMENTATION_COLOR_READ_TYPE"/>
+        <enum value="0x8B9A" name="GL_IMPLEMENTATION_COLOR_READ_TYPE_OES"/>
+        <enum value="0x8B9B" name="GL_IMPLEMENTATION_COLOR_READ_FORMAT"/>
+        <enum value="0x8B9B" name="GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES"/>
+        <enum value="0x8B9C" name="GL_POINT_SIZE_ARRAY_OES"/>
+        <enum value="0x8B9D" name="GL_TEXTURE_CROP_RECT_OES"/>
+        <enum value="0x8B9E" name="GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES"/>
+        <enum value="0x8B9F" name="GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8BA0" end="0x8BAF" vendor="Seaweed">
+            <unused start="0x8BA0" end="0x8BAF" vendor="Seaweed"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8BB0" end="0x8BBF" vendor="MESA">
+        <enum value="0x8BB0" name="GL_FRAGMENT_PROGRAM_POSITION_MESA"/>
+        <enum value="0x8BB1" name="GL_FRAGMENT_PROGRAM_CALLBACK_MESA"/>
+        <enum value="0x8BB2" name="GL_FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA"/>
+        <enum value="0x8BB3" name="GL_FRAGMENT_PROGRAM_CALLBACK_DATA_MESA"/>
+        <enum value="0x8BB4" name="GL_VERTEX_PROGRAM_POSITION_MESA"/>
+        <enum value="0x8BB5" name="GL_VERTEX_PROGRAM_CALLBACK_MESA"/>
+        <enum value="0x8BB6" name="GL_VERTEX_PROGRAM_CALLBACK_FUNC_MESA"/>
+        <enum value="0x8BB7" name="GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8BC0" end="0x8BFF" vendor="QCOM" comment="Reassigned from AMD to QCOM">
+        <enum value="0x8BC0" name="GL_COUNTER_TYPE_AMD"/>
+        <enum value="0x8BC1" name="GL_COUNTER_RANGE_AMD"/>
+        <enum value="0x8BC2" name="GL_UNSIGNED_INT64_AMD"/>
+        <enum value="0x8BC3" name="GL_PERCENTAGE_AMD"/>
+        <enum value="0x8BC4" name="GL_PERFMON_RESULT_AVAILABLE_AMD"/>
+        <enum value="0x8BC5" name="GL_PERFMON_RESULT_SIZE_AMD"/>
+        <enum value="0x8BC6" name="GL_PERFMON_RESULT_AMD"/>
+            <unused start="0x8BC7" end="0x8BD1" vendor="QCOM"/>
+        <enum value="0x8BD2" name="GL_TEXTURE_WIDTH_QCOM"/>
+        <enum value="0x8BD3" name="GL_TEXTURE_HEIGHT_QCOM"/>
+        <enum value="0x8BD4" name="GL_TEXTURE_DEPTH_QCOM"/>
+        <enum value="0x8BD5" name="GL_TEXTURE_INTERNAL_FORMAT_QCOM"/>
+        <enum value="0x8BD6" name="GL_TEXTURE_FORMAT_QCOM"/>
+        <enum value="0x8BD7" name="GL_TEXTURE_TYPE_QCOM"/>
+        <enum value="0x8BD8" name="GL_TEXTURE_IMAGE_VALID_QCOM"/>
+        <enum value="0x8BD9" name="GL_TEXTURE_NUM_LEVELS_QCOM"/>
+        <enum value="0x8BDA" name="GL_TEXTURE_TARGET_QCOM"/>
+        <enum value="0x8BDB" name="GL_TEXTURE_OBJECT_VALID_QCOM"/>
+        <enum value="0x8BDC" name="GL_STATE_RESTORE"/>
+            <unused start="0x8BDD" end="0x8BE6" vendor="QCOM"/>
+        <enum value="0x8BE7" name="GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT"/>
+            <unused start="0x8BE8" end="0x8BEF" vendor="QCOM"/>
+        <enum value="0x8BFA" name="GL_TEXTURE_PROTECTED_EXT"/>
+            <unused start="0x8BFB" end="0x8BFF" vendor="QCOM"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8C00" end="0x8C0F" vendor="IMG">
+        <enum value="0x8C00" name="GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG"/>
+        <enum value="0x8C01" name="GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG"/>
+        <enum value="0x8C02" name="GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG"/>
+        <enum value="0x8C03" name="GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG"/>
+        <enum value="0x8C04" name="GL_MODULATE_COLOR_IMG"/>
+        <enum value="0x8C05" name="GL_RECIP_ADD_SIGNED_ALPHA_IMG"/>
+        <enum value="0x8C06" name="GL_TEXTURE_ALPHA_MODULATE_IMG"/>
+        <enum value="0x8C07" name="GL_FACTOR_ALPHA_MODULATE_IMG"/>
+        <enum value="0x8C08" name="GL_FRAGMENT_ALPHA_MODULATE_IMG"/>
+        <enum value="0x8C09" name="GL_ADD_BLEND_IMG"/>
+        <enum value="0x8C0A" name="GL_SGX_BINARY_IMG"/>
+            <unused start="0x8C0B" end="0x8C0F" vendor="IMG"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8C10" end="0x8C8F" vendor="NV" comment="For Pat Brown">
+        <enum value="0x8C10" name="GL_TEXTURE_RED_TYPE"/>
+        <enum value="0x8C10" name="GL_TEXTURE_RED_TYPE_ARB"/>
+        <enum value="0x8C11" name="GL_TEXTURE_GREEN_TYPE"/>
+        <enum value="0x8C11" name="GL_TEXTURE_GREEN_TYPE_ARB"/>
+        <enum value="0x8C12" name="GL_TEXTURE_BLUE_TYPE"/>
+        <enum value="0x8C12" name="GL_TEXTURE_BLUE_TYPE_ARB"/>
+        <enum value="0x8C13" name="GL_TEXTURE_ALPHA_TYPE"/>
+        <enum value="0x8C13" name="GL_TEXTURE_ALPHA_TYPE_ARB"/>
+        <enum value="0x8C14" name="GL_TEXTURE_LUMINANCE_TYPE"/>
+        <enum value="0x8C14" name="GL_TEXTURE_LUMINANCE_TYPE_ARB"/>
+        <enum value="0x8C15" name="GL_TEXTURE_INTENSITY_TYPE"/>
+        <enum value="0x8C15" name="GL_TEXTURE_INTENSITY_TYPE_ARB"/>
+        <enum value="0x8C16" name="GL_TEXTURE_DEPTH_TYPE"/>
+        <enum value="0x8C16" name="GL_TEXTURE_DEPTH_TYPE_ARB"/>
+        <enum value="0x8C17" name="GL_UNSIGNED_NORMALIZED"/>
+        <enum value="0x8C17" name="GL_UNSIGNED_NORMALIZED_ARB"/>
+        <enum value="0x8C17" name="GL_UNSIGNED_NORMALIZED_EXT"/>
+        <enum value="0x8C18" name="GL_TEXTURE_1D_ARRAY"/>
+        <enum value="0x8C18" name="GL_TEXTURE_1D_ARRAY_EXT"/>
+        <enum value="0x8C19" name="GL_PROXY_TEXTURE_1D_ARRAY"/>
+        <enum value="0x8C19" name="GL_PROXY_TEXTURE_1D_ARRAY_EXT"/>
+        <enum value="0x8C1A" name="GL_TEXTURE_2D_ARRAY"/>
+        <enum value="0x8C1A" name="GL_TEXTURE_2D_ARRAY_EXT"/>
+        <enum value="0x8C1B" name="GL_PROXY_TEXTURE_2D_ARRAY"/>
+        <enum value="0x8C1B" name="GL_PROXY_TEXTURE_2D_ARRAY_EXT"/>
+        <enum value="0x8C1C" name="GL_TEXTURE_BINDING_1D_ARRAY"/>
+        <enum value="0x8C1C" name="GL_TEXTURE_BINDING_1D_ARRAY_EXT"/>
+        <enum value="0x8C1D" name="GL_TEXTURE_BINDING_2D_ARRAY"/>
+        <enum value="0x8C1D" name="GL_TEXTURE_BINDING_2D_ARRAY_EXT"/>
+            <unused start="0x8C1E" end="0x8C25" vendor="NV"/>
+        <enum value="0x8C26" name="GL_GEOMETRY_PROGRAM_NV"/>
+        <enum value="0x8C27" name="GL_MAX_PROGRAM_OUTPUT_VERTICES_NV"/>
+        <enum value="0x8C28" name="GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV"/>
+        <enum value="0x8C29" name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS"/>
+        <enum value="0x8C29" name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB"/>
+        <enum value="0x8C29" name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT"/>
+        <enum value="0x8C29" name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES"/>
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER"/>
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_ARB"/>
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_EXT"/>
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_OES"/>
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_BINDING" comment="Equivalent to GL_TEXTURE_BUFFER_ARB query, but named more consistently"/>
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_BINDING_EXT"/>
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_BINDING_OES"/>
+        <enum value="0x8C2B" name="GL_MAX_TEXTURE_BUFFER_SIZE"/>
+        <enum value="0x8C2B" name="GL_MAX_TEXTURE_BUFFER_SIZE_ARB"/>
+        <enum value="0x8C2B" name="GL_MAX_TEXTURE_BUFFER_SIZE_EXT"/>
+        <enum value="0x8C2B" name="GL_MAX_TEXTURE_BUFFER_SIZE_OES"/>
+        <enum value="0x8C2C" name="GL_TEXTURE_BINDING_BUFFER"/>
+        <enum value="0x8C2C" name="GL_TEXTURE_BINDING_BUFFER_ARB"/>
+        <enum value="0x8C2C" name="GL_TEXTURE_BINDING_BUFFER_EXT"/>
+        <enum value="0x8C2C" name="GL_TEXTURE_BINDING_BUFFER_OES"/>
+        <enum value="0x8C2D" name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING"/>
+        <enum value="0x8C2D" name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB"/>
+        <enum value="0x8C2D" name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT"/>
+        <enum value="0x8C2D" name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES"/>
+        <enum value="0x8C2E" name="GL_TEXTURE_BUFFER_FORMAT_ARB"/>
+        <enum value="0x8C2E" name="GL_TEXTURE_BUFFER_FORMAT_EXT"/>
+        <enum value="0x8C2F" name="GL_ANY_SAMPLES_PASSED"/>
+        <enum value="0x8C2F" name="GL_ANY_SAMPLES_PASSED_EXT"/>
+            <unused start="0x8C30" end="0x8C35" vendor="NV"/>
+        <enum value="0x8C36" name="GL_SAMPLE_SHADING"/>
+        <enum value="0x8C36" name="GL_SAMPLE_SHADING_ARB"/>
+        <enum value="0x8C36" name="GL_SAMPLE_SHADING_OES"/>
+        <enum value="0x8C37" name="GL_MIN_SAMPLE_SHADING_VALUE"/>
+        <enum value="0x8C37" name="GL_MIN_SAMPLE_SHADING_VALUE_ARB"/>
+        <enum value="0x8C37" name="GL_MIN_SAMPLE_SHADING_VALUE_OES"/>
+            <unused start="0x8C38" end="0x8C39" vendor="NV"/>
+        <enum value="0x8C3A" name="GL_R11F_G11F_B10F"/>
+        <enum value="0x8C3A" name="GL_R11F_G11F_B10F_APPLE"/>
+        <enum value="0x8C3A" name="GL_R11F_G11F_B10F_EXT"/>
+        <enum value="0x8C3B" name="GL_UNSIGNED_INT_10F_11F_11F_REV"/>
+        <enum value="0x8C3B" name="GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE"/>
+        <enum value="0x8C3B" name="GL_UNSIGNED_INT_10F_11F_11F_REV_EXT"/>
+        <enum value="0x8C3C" name="GL_RGBA_SIGNED_COMPONENTS_EXT"/>
+        <enum value="0x8C3D" name="GL_RGB9_E5"/>
+        <enum value="0x8C3D" name="GL_RGB9_E5_APPLE"/>
+        <enum value="0x8C3D" name="GL_RGB9_E5_EXT"/>
+        <enum value="0x8C3E" name="GL_UNSIGNED_INT_5_9_9_9_REV"/>
+        <enum value="0x8C3E" name="GL_UNSIGNED_INT_5_9_9_9_REV_APPLE"/>
+        <enum value="0x8C3E" name="GL_UNSIGNED_INT_5_9_9_9_REV_EXT"/>
+        <enum value="0x8C3F" name="GL_TEXTURE_SHARED_SIZE"/>
+        <enum value="0x8C3F" name="GL_TEXTURE_SHARED_SIZE_EXT"/>
+        <enum value="0x8C40" name="GL_SRGB"/>
+        <enum value="0x8C40" name="GL_SRGB_EXT"/>
+        <enum value="0x8C41" name="GL_SRGB8"/>
+        <enum value="0x8C41" name="GL_SRGB8_EXT"/>
+        <enum value="0x8C41" name="GL_SRGB8_NV"/>
+        <enum value="0x8C42" name="GL_SRGB_ALPHA"/>
+        <enum value="0x8C42" name="GL_SRGB_ALPHA_EXT"/>
+        <enum value="0x8C43" name="GL_SRGB8_ALPHA8"/>
+        <enum value="0x8C43" name="GL_SRGB8_ALPHA8_EXT"/>
+        <enum value="0x8C44" name="GL_SLUMINANCE_ALPHA"/>
+        <enum value="0x8C44" name="GL_SLUMINANCE_ALPHA_EXT"/>
+        <enum value="0x8C44" name="GL_SLUMINANCE_ALPHA_NV"/>
+        <enum value="0x8C45" name="GL_SLUMINANCE8_ALPHA8"/>
+        <enum value="0x8C45" name="GL_SLUMINANCE8_ALPHA8_EXT"/>
+        <enum value="0x8C45" name="GL_SLUMINANCE8_ALPHA8_NV"/>
+        <enum value="0x8C46" name="GL_SLUMINANCE"/>
+        <enum value="0x8C46" name="GL_SLUMINANCE_EXT"/>
+        <enum value="0x8C46" name="GL_SLUMINANCE_NV"/>
+        <enum value="0x8C47" name="GL_SLUMINANCE8"/>
+        <enum value="0x8C47" name="GL_SLUMINANCE8_EXT"/>
+        <enum value="0x8C47" name="GL_SLUMINANCE8_NV"/>
+        <enum value="0x8C48" name="GL_COMPRESSED_SRGB"/>
+        <enum value="0x8C48" name="GL_COMPRESSED_SRGB_EXT"/>
+        <enum value="0x8C49" name="GL_COMPRESSED_SRGB_ALPHA"/>
+        <enum value="0x8C49" name="GL_COMPRESSED_SRGB_ALPHA_EXT"/>
+        <enum value="0x8C4A" name="GL_COMPRESSED_SLUMINANCE"/>
+        <enum value="0x8C4A" name="GL_COMPRESSED_SLUMINANCE_EXT"/>
+        <enum value="0x8C4B" name="GL_COMPRESSED_SLUMINANCE_ALPHA"/>
+        <enum value="0x8C4B" name="GL_COMPRESSED_SLUMINANCE_ALPHA_EXT"/>
+        <enum value="0x8C4C" name="GL_COMPRESSED_SRGB_S3TC_DXT1_EXT"/>
+        <enum value="0x8C4C" name="GL_COMPRESSED_SRGB_S3TC_DXT1_NV"/>
+        <enum value="0x8C4D" name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT"/>
+        <enum value="0x8C4D" name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV"/>
+        <enum value="0x8C4E" name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT"/>
+        <enum value="0x8C4E" name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV"/>
+        <enum value="0x8C4F" name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT"/>
+        <enum value="0x8C4F" name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV"/>
+            <unused start="0x8C50" end="0x8C6F" vendor="NV"/>
+        <enum value="0x8C70" name="GL_COMPRESSED_LUMINANCE_LATC1_EXT"/>
+        <enum value="0x8C71" name="GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT"/>
+        <enum value="0x8C72" name="GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT"/>
+        <enum value="0x8C73" name="GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT"/>
+        <enum value="0x8C74" name="GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV"/>
+        <enum value="0x8C75" name="GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV"/>
+        <enum value="0x8C76" name="GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH"/>
+        <enum value="0x8C76" name="GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT"/>
+        <enum value="0x8C77" name="GL_BACK_PRIMARY_COLOR_NV"/>
+        <enum value="0x8C78" name="GL_BACK_SECONDARY_COLOR_NV"/>
+        <enum value="0x8C79" name="GL_TEXTURE_COORD_NV"/>
+        <enum value="0x8C7A" name="GL_CLIP_DISTANCE_NV"/>
+        <enum value="0x8C7B" name="GL_VERTEX_ID_NV"/>
+        <enum value="0x8C7C" name="GL_PRIMITIVE_ID_NV"/>
+        <enum value="0x8C7D" name="GL_GENERIC_ATTRIB_NV"/>
+        <enum value="0x8C7E" name="GL_TRANSFORM_FEEDBACK_ATTRIBS_NV"/>
+        <enum value="0x8C7F" name="GL_TRANSFORM_FEEDBACK_BUFFER_MODE"/>
+        <enum value="0x8C7F" name="GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT"/>
+        <enum value="0x8C7F" name="GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV"/>
+        <enum value="0x8C80" name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS"/>
+        <enum value="0x8C80" name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT"/>
+        <enum value="0x8C80" name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV"/>
+        <enum value="0x8C81" name="GL_ACTIVE_VARYINGS_NV"/>
+        <enum value="0x8C82" name="GL_ACTIVE_VARYING_MAX_LENGTH_NV"/>
+        <enum value="0x8C83" name="GL_TRANSFORM_FEEDBACK_VARYINGS"/>
+        <enum value="0x8C83" name="GL_TRANSFORM_FEEDBACK_VARYINGS_EXT"/>
+        <enum value="0x8C83" name="GL_TRANSFORM_FEEDBACK_VARYINGS_NV"/>
+        <enum value="0x8C84" name="GL_TRANSFORM_FEEDBACK_BUFFER_START"/>
+        <enum value="0x8C84" name="GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT"/>
+        <enum value="0x8C84" name="GL_TRANSFORM_FEEDBACK_BUFFER_START_NV"/>
+        <enum value="0x8C85" name="GL_TRANSFORM_FEEDBACK_BUFFER_SIZE"/>
+        <enum value="0x8C85" name="GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT"/>
+        <enum value="0x8C85" name="GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV"/>
+        <enum value="0x8C86" name="GL_TRANSFORM_FEEDBACK_RECORD_NV"/>
+        <enum value="0x8C87" name="GL_PRIMITIVES_GENERATED"/>
+        <enum value="0x8C87" name="GL_PRIMITIVES_GENERATED_EXT"/>
+        <enum value="0x8C87" name="GL_PRIMITIVES_GENERATED_NV"/>
+        <enum value="0x8C87" name="GL_PRIMITIVES_GENERATED_OES"/>
+        <enum value="0x8C88" name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"/>
+        <enum value="0x8C88" name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT"/>
+        <enum value="0x8C88" name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV"/>
+        <enum value="0x8C89" name="GL_RASTERIZER_DISCARD"/>
+        <enum value="0x8C89" name="GL_RASTERIZER_DISCARD_EXT"/>
+        <enum value="0x8C89" name="GL_RASTERIZER_DISCARD_NV"/>
+        <enum value="0x8C8A" name="GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS"/>
+        <enum value="0x8C8A" name="GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT"/>
+        <enum value="0x8C8A" name="GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV"/>
+        <enum value="0x8C8B" name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS"/>
+        <enum value="0x8C8B" name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT"/>
+        <enum value="0x8C8B" name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV"/>
+        <enum value="0x8C8C" name="GL_INTERLEAVED_ATTRIBS"/>
+        <enum value="0x8C8C" name="GL_INTERLEAVED_ATTRIBS_EXT"/>
+        <enum value="0x8C8C" name="GL_INTERLEAVED_ATTRIBS_NV"/>
+        <enum value="0x8C8D" name="GL_SEPARATE_ATTRIBS"/>
+        <enum value="0x8C8D" name="GL_SEPARATE_ATTRIBS_EXT"/>
+        <enum value="0x8C8D" name="GL_SEPARATE_ATTRIBS_NV"/>
+        <enum value="0x8C8E" name="GL_TRANSFORM_FEEDBACK_BUFFER"/>
+        <enum value="0x8C8E" name="GL_TRANSFORM_FEEDBACK_BUFFER_EXT"/>
+        <enum value="0x8C8E" name="GL_TRANSFORM_FEEDBACK_BUFFER_NV"/>
+        <enum value="0x8C8F" name="GL_TRANSFORM_FEEDBACK_BUFFER_BINDING"/>
+        <enum value="0x8C8F" name="GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT"/>
+        <enum value="0x8C8F" name="GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8C90" end="0x8C9F" vendor="QCOM" comment="For Affie Munshi. Reassigned from AMD to QCOM (bug 5874)">
+            <unused start="0x8C90" end="0x8C91" vendor="QCOM"/>
+        <enum value="0x8C92" name="GL_ATC_RGB_AMD"/>
+        <enum value="0x8C93" name="GL_ATC_RGBA_EXPLICIT_ALPHA_AMD"/>
+            <unused start="0x8C94" end="0x8C9F" vendor="QCOM"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8CA0" end="0x8CAF" vendor="ARB">
+        <enum value="0x8CA0" name="GL_POINT_SPRITE_COORD_ORIGIN"/>
+        <enum value="0x8CA1" name="GL_LOWER_LEFT"/>
+        <enum value="0x8CA2" name="GL_UPPER_LEFT"/>
+        <enum value="0x8CA3" name="GL_STENCIL_BACK_REF"/>
+        <enum value="0x8CA4" name="GL_STENCIL_BACK_VALUE_MASK"/>
+        <enum value="0x8CA5" name="GL_STENCIL_BACK_WRITEMASK"/>
+        <enum value="0x8CA6" name="GL_DRAW_FRAMEBUFFER_BINDING"/>
+        <enum value="0x8CA6" name="GL_DRAW_FRAMEBUFFER_BINDING_ANGLE"/>
+        <enum value="0x8CA6" name="GL_DRAW_FRAMEBUFFER_BINDING_APPLE"/>
+        <enum value="0x8CA6" name="GL_DRAW_FRAMEBUFFER_BINDING_EXT"/>
+        <enum value="0x8CA6" name="GL_DRAW_FRAMEBUFFER_BINDING_NV"/>
+        <enum value="0x8CA6" name="GL_FRAMEBUFFER_BINDING"/>
+        <enum value="0x8CA6" name="GL_FRAMEBUFFER_BINDING_ANGLE"/>
+        <enum value="0x8CA6" name="GL_FRAMEBUFFER_BINDING_EXT"/>
+        <enum value="0x8CA6" name="GL_FRAMEBUFFER_BINDING_OES"/>
+        <enum value="0x8CA7" name="GL_RENDERBUFFER_BINDING"/>
+        <enum value="0x8CA7" name="GL_RENDERBUFFER_BINDING_ANGLE"/>
+        <enum value="0x8CA7" name="GL_RENDERBUFFER_BINDING_EXT"/>
+        <enum value="0x8CA7" name="GL_RENDERBUFFER_BINDING_OES"/>
+        <enum value="0x8CA8" name="GL_READ_FRAMEBUFFER"/>
+        <enum value="0x8CA8" name="GL_READ_FRAMEBUFFER_ANGLE"/>
+        <enum value="0x8CA8" name="GL_READ_FRAMEBUFFER_APPLE"/>
+        <enum value="0x8CA8" name="GL_READ_FRAMEBUFFER_EXT"/>
+        <enum value="0x8CA8" name="GL_READ_FRAMEBUFFER_NV"/>
+        <enum value="0x8CA9" name="GL_DRAW_FRAMEBUFFER"/>
+        <enum value="0x8CA9" name="GL_DRAW_FRAMEBUFFER_ANGLE"/>
+        <enum value="0x8CA9" name="GL_DRAW_FRAMEBUFFER_APPLE"/>
+        <enum value="0x8CA9" name="GL_DRAW_FRAMEBUFFER_EXT"/>
+        <enum value="0x8CA9" name="GL_DRAW_FRAMEBUFFER_NV"/>
+        <enum value="0x8CAA" name="GL_READ_FRAMEBUFFER_BINDING"/>
+        <enum value="0x8CAA" name="GL_READ_FRAMEBUFFER_BINDING_ANGLE"/>
+        <enum value="0x8CAA" name="GL_READ_FRAMEBUFFER_BINDING_APPLE"/>
+        <enum value="0x8CAA" name="GL_READ_FRAMEBUFFER_BINDING_EXT"/>
+        <enum value="0x8CAA" name="GL_READ_FRAMEBUFFER_BINDING_NV"/>
+        <enum value="0x8CAB" name="GL_RENDERBUFFER_COVERAGE_SAMPLES_NV"/>
+        <enum value="0x8CAB" name="GL_RENDERBUFFER_SAMPLES"/>
+        <enum value="0x8CAB" name="GL_RENDERBUFFER_SAMPLES_ANGLE"/>
+        <enum value="0x8CAB" name="GL_RENDERBUFFER_SAMPLES_APPLE"/>
+        <enum value="0x8CAB" name="GL_RENDERBUFFER_SAMPLES_EXT"/>
+        <enum value="0x8CAB" name="GL_RENDERBUFFER_SAMPLES_NV"/>
+        <enum value="0x8CAC" name="GL_DEPTH_COMPONENT32F"/>
+        <enum value="0x8CAD" name="GL_DEPTH32F_STENCIL8"/>
+            <unused start="0x8CAE" end="0x8CAF" vendor="ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8CB0" end="0x8CCF" vendor="ZiiLabs" comment="For Barthold Lichtenbelt 2004/12/1">
+            <unused start="0x8CB0" end="0x8CCF" vendor="ZiiLabs"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8CD0" end="0x8D5F" vendor="ARB" comment="Framebuffer object specification + headroom">
+        <enum value="0x8CD0" name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"/>
+        <enum value="0x8CD0" name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT"/>
+        <enum value="0x8CD0" name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES"/>
+        <enum value="0x8CD1" name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME"/>
+        <enum value="0x8CD1" name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT"/>
+        <enum value="0x8CD1" name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES"/>
+        <enum value="0x8CD2" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL"/>
+        <enum value="0x8CD2" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT"/>
+        <enum value="0x8CD2" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES"/>
+        <enum value="0x8CD3" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE"/>
+        <enum value="0x8CD3" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT"/>
+        <enum value="0x8CD3" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES"/>
+        <enum value="0x8CD4" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT"/>
+        <enum value="0x8CD4" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES"/>
+        <enum value="0x8CD4" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER"/>
+        <enum value="0x8CD4" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT"/>
+        <enum value="0x8CD5" name="GL_FRAMEBUFFER_COMPLETE"/>
+        <enum value="0x8CD5" name="GL_FRAMEBUFFER_COMPLETE_EXT"/>
+        <enum value="0x8CD5" name="GL_FRAMEBUFFER_COMPLETE_OES"/>
+        <enum value="0x8CD6" name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"/>
+        <enum value="0x8CD6" name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT"/>
+        <enum value="0x8CD6" name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES"/>
+        <enum value="0x8CD7" name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"/>
+        <enum value="0x8CD7" name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT"/>
+        <enum value="0x8CD7" name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES"/>
+            <unused start="0x8CD8" vendor="ARB" comment="Removed 2005/09/26 in revision #117 of the FBO extension spec"/>
+            <!-- <enum value="0x8CD8" name="GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT"/> -->
+        <enum value="0x8CD9" name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"/>
+        <enum value="0x8CD9" name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT"/>
+        <enum value="0x8CD9" name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES"/>
+        <enum value="0x8CDA" name="GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT"/>
+        <enum value="0x8CDA" name="GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES"/>
+        <enum value="0x8CDB" name="GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"/>
+        <enum value="0x8CDB" name="GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT"/>
+        <enum value="0x8CDB" name="GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES"/>
+        <enum value="0x8CDC" name="GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"/>
+        <enum value="0x8CDC" name="GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT"/>
+        <enum value="0x8CDC" name="GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES"/>
+        <enum value="0x8CDD" name="GL_FRAMEBUFFER_UNSUPPORTED"/>
+        <enum value="0x8CDD" name="GL_FRAMEBUFFER_UNSUPPORTED_EXT"/>
+        <enum value="0x8CDD" name="GL_FRAMEBUFFER_UNSUPPORTED_OES"/>
+            <unused start="0x8CDE" vendor="ARB" comment="Removed 2005/05/31 in revision #113 of the FBO extension spec"/>
+            <!-- <enum value="0x8CDE" name="GL_FRAMEBUFFER_STATUS_ERROR_EXT"/> -->
+        <enum value="0x8CDF" name="GL_MAX_COLOR_ATTACHMENTS"/>
+        <enum value="0x8CDF" name="GL_MAX_COLOR_ATTACHMENTS_EXT"/>
+        <enum value="0x8CDF" name="GL_MAX_COLOR_ATTACHMENTS_NV"/>
+        <enum value="0x8CE0" name="GL_COLOR_ATTACHMENT0"/>
+        <enum value="0x8CE0" name="GL_COLOR_ATTACHMENT0_EXT"/>
+        <enum value="0x8CE0" name="GL_COLOR_ATTACHMENT0_NV"/>
+        <enum value="0x8CE0" name="GL_COLOR_ATTACHMENT0_OES"/>
+        <enum value="0x8CE1" name="GL_COLOR_ATTACHMENT1"/>
+        <enum value="0x8CE1" name="GL_COLOR_ATTACHMENT1_EXT"/>
+        <enum value="0x8CE1" name="GL_COLOR_ATTACHMENT1_NV"/>
+        <enum value="0x8CE2" name="GL_COLOR_ATTACHMENT2"/>
+        <enum value="0x8CE2" name="GL_COLOR_ATTACHMENT2_EXT"/>
+        <enum value="0x8CE2" name="GL_COLOR_ATTACHMENT2_NV"/>
+        <enum value="0x8CE3" name="GL_COLOR_ATTACHMENT3"/>
+        <enum value="0x8CE3" name="GL_COLOR_ATTACHMENT3_EXT"/>
+        <enum value="0x8CE3" name="GL_COLOR_ATTACHMENT3_NV"/>
+        <enum value="0x8CE4" name="GL_COLOR_ATTACHMENT4"/>
+        <enum value="0x8CE4" name="GL_COLOR_ATTACHMENT4_EXT"/>
+        <enum value="0x8CE4" name="GL_COLOR_ATTACHMENT4_NV"/>
+        <enum value="0x8CE5" name="GL_COLOR_ATTACHMENT5"/>
+        <enum value="0x8CE5" name="GL_COLOR_ATTACHMENT5_EXT"/>
+        <enum value="0x8CE5" name="GL_COLOR_ATTACHMENT5_NV"/>
+        <enum value="0x8CE6" name="GL_COLOR_ATTACHMENT6"/>
+        <enum value="0x8CE6" name="GL_COLOR_ATTACHMENT6_EXT"/>
+        <enum value="0x8CE6" name="GL_COLOR_ATTACHMENT6_NV"/>
+        <enum value="0x8CE7" name="GL_COLOR_ATTACHMENT7"/>
+        <enum value="0x8CE7" name="GL_COLOR_ATTACHMENT7_EXT"/>
+        <enum value="0x8CE7" name="GL_COLOR_ATTACHMENT7_NV"/>
+        <enum value="0x8CE8" name="GL_COLOR_ATTACHMENT8"/>
+        <enum value="0x8CE8" name="GL_COLOR_ATTACHMENT8_EXT"/>
+        <enum value="0x8CE8" name="GL_COLOR_ATTACHMENT8_NV"/>
+        <enum value="0x8CE9" name="GL_COLOR_ATTACHMENT9"/>
+        <enum value="0x8CE9" name="GL_COLOR_ATTACHMENT9_EXT"/>
+        <enum value="0x8CE9" name="GL_COLOR_ATTACHMENT9_NV"/>
+        <enum value="0x8CEA" name="GL_COLOR_ATTACHMENT10"/>
+        <enum value="0x8CEA" name="GL_COLOR_ATTACHMENT10_EXT"/>
+        <enum value="0x8CEA" name="GL_COLOR_ATTACHMENT10_NV"/>
+        <enum value="0x8CEB" name="GL_COLOR_ATTACHMENT11"/>
+        <enum value="0x8CEB" name="GL_COLOR_ATTACHMENT11_EXT"/>
+        <enum value="0x8CEB" name="GL_COLOR_ATTACHMENT11_NV"/>
+        <enum value="0x8CEC" name="GL_COLOR_ATTACHMENT12"/>
+        <enum value="0x8CEC" name="GL_COLOR_ATTACHMENT12_EXT"/>
+        <enum value="0x8CEC" name="GL_COLOR_ATTACHMENT12_NV"/>
+        <enum value="0x8CED" name="GL_COLOR_ATTACHMENT13"/>
+        <enum value="0x8CED" name="GL_COLOR_ATTACHMENT13_EXT"/>
+        <enum value="0x8CED" name="GL_COLOR_ATTACHMENT13_NV"/>
+        <enum value="0x8CEE" name="GL_COLOR_ATTACHMENT14"/>
+        <enum value="0x8CEE" name="GL_COLOR_ATTACHMENT14_EXT"/>
+        <enum value="0x8CEE" name="GL_COLOR_ATTACHMENT14_NV"/>
+        <enum value="0x8CEF" name="GL_COLOR_ATTACHMENT15"/>
+        <enum value="0x8CEF" name="GL_COLOR_ATTACHMENT15_EXT"/>
+        <enum value="0x8CEF" name="GL_COLOR_ATTACHMENT15_NV"/>
+        <enum value="0x8CF0" name="GL_COLOR_ATTACHMENT16"/>
+        <enum value="0x8CF1" name="GL_COLOR_ATTACHMENT17"/>
+        <enum value="0x8CF2" name="GL_COLOR_ATTACHMENT18"/>
+        <enum value="0x8CF3" name="GL_COLOR_ATTACHMENT19"/>
+        <enum value="0x8CF4" name="GL_COLOR_ATTACHMENT20"/>
+        <enum value="0x8CF5" name="GL_COLOR_ATTACHMENT21"/>
+        <enum value="0x8CF6" name="GL_COLOR_ATTACHMENT22"/>
+        <enum value="0x8CF7" name="GL_COLOR_ATTACHMENT23"/>
+        <enum value="0x8CF8" name="GL_COLOR_ATTACHMENT24"/>
+        <enum value="0x8CF9" name="GL_COLOR_ATTACHMENT25"/>
+        <enum value="0x8CFA" name="GL_COLOR_ATTACHMENT26"/>
+        <enum value="0x8CFB" name="GL_COLOR_ATTACHMENT27"/>
+        <enum value="0x8CFC" name="GL_COLOR_ATTACHMENT28"/>
+        <enum value="0x8CFD" name="GL_COLOR_ATTACHMENT29"/>
+        <enum value="0x8CFE" name="GL_COLOR_ATTACHMENT30"/>
+        <enum value="0x8CFF" name="GL_COLOR_ATTACHMENT31"/>
+        <enum value="0x8D00" name="GL_DEPTH_ATTACHMENT"/>
+        <enum value="0x8D00" name="GL_DEPTH_ATTACHMENT_EXT"/>
+        <enum value="0x8D00" name="GL_DEPTH_ATTACHMENT_OES"/>
+            <unused start="0x8D01" end="0x8D1F" vendor="ARB" comment="For depth attachments 16-31"/>
+        <enum value="0x8D20" name="GL_STENCIL_ATTACHMENT"/>
+        <enum value="0x8D20" name="GL_STENCIL_ATTACHMENT_EXT"/>
+        <enum value="0x8D20" name="GL_STENCIL_ATTACHMENT_OES"/>
+            <unused start="0x8D21" end="0x8D3F" vendor="ARB" comment="For stencil attachments 16-31"/>
+        <enum value="0x8D40" name="GL_FRAMEBUFFER"/>
+        <enum value="0x8D40" name="GL_FRAMEBUFFER_EXT"/>
+        <enum value="0x8D40" name="GL_FRAMEBUFFER_OES"/>
+        <enum value="0x8D41" name="GL_RENDERBUFFER"/>
+        <enum value="0x8D41" name="GL_RENDERBUFFER_EXT"/>
+        <enum value="0x8D41" name="GL_RENDERBUFFER_OES"/>
+        <enum value="0x8D42" name="GL_RENDERBUFFER_WIDTH"/>
+        <enum value="0x8D42" name="GL_RENDERBUFFER_WIDTH_EXT"/>
+        <enum value="0x8D42" name="GL_RENDERBUFFER_WIDTH_OES"/>
+        <enum value="0x8D43" name="GL_RENDERBUFFER_HEIGHT"/>
+        <enum value="0x8D43" name="GL_RENDERBUFFER_HEIGHT_EXT"/>
+        <enum value="0x8D43" name="GL_RENDERBUFFER_HEIGHT_OES"/>
+        <enum value="0x8D44" name="GL_RENDERBUFFER_INTERNAL_FORMAT"/>
+        <enum value="0x8D44" name="GL_RENDERBUFFER_INTERNAL_FORMAT_EXT"/>
+        <enum value="0x8D44" name="GL_RENDERBUFFER_INTERNAL_FORMAT_OES"/>
+            <unused start="0x8D45" vendor="ARB" comment="Was for GL_STENCIL_INDEX_EXT, but now use core STENCIL_INDEX instead"/>
+        <enum value="0x8D46" name="GL_STENCIL_INDEX1"/>
+        <enum value="0x8D46" name="GL_STENCIL_INDEX1_EXT"/>
+        <enum value="0x8D46" name="GL_STENCIL_INDEX1_OES"/>
+        <enum value="0x8D47" name="GL_STENCIL_INDEX4"/>
+        <enum value="0x8D47" name="GL_STENCIL_INDEX4_EXT"/>
+        <enum value="0x8D47" name="GL_STENCIL_INDEX4_OES"/>
+        <enum value="0x8D48" name="GL_STENCIL_INDEX8"/>
+        <enum value="0x8D48" name="GL_STENCIL_INDEX8_EXT"/>
+        <enum value="0x8D48" name="GL_STENCIL_INDEX8_OES"/>
+        <enum value="0x8D49" name="GL_STENCIL_INDEX16"/>
+        <enum value="0x8D49" name="GL_STENCIL_INDEX16_EXT"/>
+            <unused start="0x8D4A" end="0x8D4F" vendor="ARB" comment="For additional stencil formats"/>
+        <enum value="0x8D50" name="GL_RENDERBUFFER_RED_SIZE"/>
+        <enum value="0x8D50" name="GL_RENDERBUFFER_RED_SIZE_EXT"/>
+        <enum value="0x8D50" name="GL_RENDERBUFFER_RED_SIZE_OES"/>
+        <enum value="0x8D51" name="GL_RENDERBUFFER_GREEN_SIZE"/>
+        <enum value="0x8D51" name="GL_RENDERBUFFER_GREEN_SIZE_EXT"/>
+        <enum value="0x8D51" name="GL_RENDERBUFFER_GREEN_SIZE_OES"/>
+        <enum value="0x8D52" name="GL_RENDERBUFFER_BLUE_SIZE"/>
+        <enum value="0x8D52" name="GL_RENDERBUFFER_BLUE_SIZE_EXT"/>
+        <enum value="0x8D52" name="GL_RENDERBUFFER_BLUE_SIZE_OES"/>
+        <enum value="0x8D53" name="GL_RENDERBUFFER_ALPHA_SIZE"/>
+        <enum value="0x8D53" name="GL_RENDERBUFFER_ALPHA_SIZE_EXT"/>
+        <enum value="0x8D53" name="GL_RENDERBUFFER_ALPHA_SIZE_OES"/>
+        <enum value="0x8D54" name="GL_RENDERBUFFER_DEPTH_SIZE"/>
+        <enum value="0x8D54" name="GL_RENDERBUFFER_DEPTH_SIZE_EXT"/>
+        <enum value="0x8D54" name="GL_RENDERBUFFER_DEPTH_SIZE_OES"/>
+        <enum value="0x8D55" name="GL_RENDERBUFFER_STENCIL_SIZE"/>
+        <enum value="0x8D55" name="GL_RENDERBUFFER_STENCIL_SIZE_EXT"/>
+        <enum value="0x8D55" name="GL_RENDERBUFFER_STENCIL_SIZE_OES"/>
+        <enum value="0x8D56" name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"/>
+        <enum value="0x8D56" name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE"/>
+        <enum value="0x8D56" name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE"/>
+        <enum value="0x8D56" name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT"/>
+        <enum value="0x8D56" name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV"/>
+        <enum value="0x8D57" name="GL_MAX_SAMPLES"/>
+        <enum value="0x8D57" name="GL_MAX_SAMPLES_ANGLE"/>
+        <enum value="0x8D57" name="GL_MAX_SAMPLES_APPLE"/>
+        <enum value="0x8D57" name="GL_MAX_SAMPLES_EXT"/>
+        <enum value="0x8D57" name="GL_MAX_SAMPLES_NV"/>
+            <unused start="0x8D58" end="0x8D5F" vendor="ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8D60" end="0x8D6F" vendor="OES">
+        <enum value="0x8D60" name="GL_TEXTURE_GEN_STR_OES"/>
+        <enum value="0x8D61" name="GL_HALF_FLOAT_OES"/>
+        <enum value="0x8D62" name="GL_RGB565_OES"/>
+        <enum value="0x8D62" name="GL_RGB565"/>
+            <unused start="0x8D63" vendor="OES" comment="Was GL_TEXTURE_IMMUTABLE_LEVELS in draft ES 3.0 spec"/>
+        <enum value="0x8D64" name="GL_ETC1_RGB8_OES"/>
+        <enum value="0x8D65" name="GL_TEXTURE_EXTERNAL_OES"/>
+        <enum value="0x8D66" name="GL_SAMPLER_EXTERNAL_OES"/>
+        <enum value="0x8D67" name="GL_TEXTURE_BINDING_EXTERNAL_OES"/>
+        <enum value="0x8D68" name="GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES"/>
+        <enum value="0x8D69" name="GL_PRIMITIVE_RESTART_FIXED_INDEX"/>
+        <enum value="0x8D6A" name="GL_ANY_SAMPLES_PASSED_CONSERVATIVE"/>
+        <enum value="0x8D6A" name="GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT"/>
+        <enum value="0x8D6B" name="GL_MAX_ELEMENT_INDEX"/>
+        <enum value="0x8D6C" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT"/>
+            <unused start="0x8D6D" end="0x8D6F" vendor="OES"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8D70" end="0x8DEF" vendor="NV" comment="For Pat Brown 2005/10/13">
+        <enum value="0x8D70" name="GL_RGBA32UI"/>
+        <enum value="0x8D70" name="GL_RGBA32UI_EXT"/>
+        <enum value="0x8D71" name="GL_RGB32UI"/>
+        <enum value="0x8D71" name="GL_RGB32UI_EXT"/>
+        <enum value="0x8D72" name="GL_ALPHA32UI_EXT"/>
+        <enum value="0x8D73" name="GL_INTENSITY32UI_EXT"/>
+        <enum value="0x8D74" name="GL_LUMINANCE32UI_EXT"/>
+        <enum value="0x8D75" name="GL_LUMINANCE_ALPHA32UI_EXT"/>
+        <enum value="0x8D76" name="GL_RGBA16UI"/>
+        <enum value="0x8D76" name="GL_RGBA16UI_EXT"/>
+        <enum value="0x8D77" name="GL_RGB16UI"/>
+        <enum value="0x8D77" name="GL_RGB16UI_EXT"/>
+        <enum value="0x8D78" name="GL_ALPHA16UI_EXT"/>
+        <enum value="0x8D79" name="GL_INTENSITY16UI_EXT"/>
+        <enum value="0x8D7A" name="GL_LUMINANCE16UI_EXT"/>
+        <enum value="0x8D7B" name="GL_LUMINANCE_ALPHA16UI_EXT"/>
+        <enum value="0x8D7C" name="GL_RGBA8UI"/>
+        <enum value="0x8D7C" name="GL_RGBA8UI_EXT"/>
+        <enum value="0x8D7D" name="GL_RGB8UI"/>
+        <enum value="0x8D7D" name="GL_RGB8UI_EXT"/>
+        <enum value="0x8D7E" name="GL_ALPHA8UI_EXT"/>
+        <enum value="0x8D7F" name="GL_INTENSITY8UI_EXT"/>
+        <enum value="0x8D80" name="GL_LUMINANCE8UI_EXT"/>
+        <enum value="0x8D81" name="GL_LUMINANCE_ALPHA8UI_EXT"/>
+        <enum value="0x8D82" name="GL_RGBA32I"/>
+        <enum value="0x8D82" name="GL_RGBA32I_EXT"/>
+        <enum value="0x8D83" name="GL_RGB32I"/>
+        <enum value="0x8D83" name="GL_RGB32I_EXT"/>
+        <enum value="0x8D84" name="GL_ALPHA32I_EXT"/>
+        <enum value="0x8D85" name="GL_INTENSITY32I_EXT"/>
+        <enum value="0x8D86" name="GL_LUMINANCE32I_EXT"/>
+        <enum value="0x8D87" name="GL_LUMINANCE_ALPHA32I_EXT"/>
+        <enum value="0x8D88" name="GL_RGBA16I"/>
+        <enum value="0x8D88" name="GL_RGBA16I_EXT"/>
+        <enum value="0x8D89" name="GL_RGB16I"/>
+        <enum value="0x8D89" name="GL_RGB16I_EXT"/>
+        <enum value="0x8D8A" name="GL_ALPHA16I_EXT"/>
+        <enum value="0x8D8B" name="GL_INTENSITY16I_EXT"/>
+        <enum value="0x8D8C" name="GL_LUMINANCE16I_EXT"/>
+        <enum value="0x8D8D" name="GL_LUMINANCE_ALPHA16I_EXT"/>
+        <enum value="0x8D8E" name="GL_RGBA8I"/>
+        <enum value="0x8D8E" name="GL_RGBA8I_EXT"/>
+        <enum value="0x8D8F" name="GL_RGB8I"/>
+        <enum value="0x8D8F" name="GL_RGB8I_EXT"/>
+        <enum value="0x8D90" name="GL_ALPHA8I_EXT"/>
+        <enum value="0x8D91" name="GL_INTENSITY8I_EXT"/>
+        <enum value="0x8D92" name="GL_LUMINANCE8I_EXT"/>
+        <enum value="0x8D93" name="GL_LUMINANCE_ALPHA8I_EXT"/>
+        <enum value="0x8D94" name="GL_RED_INTEGER"/>
+        <enum value="0x8D94" name="GL_RED_INTEGER_EXT"/>
+        <enum value="0x8D95" name="GL_GREEN_INTEGER"/>
+        <enum value="0x8D95" name="GL_GREEN_INTEGER_EXT"/>
+        <enum value="0x8D96" name="GL_BLUE_INTEGER"/>
+        <enum value="0x8D96" name="GL_BLUE_INTEGER_EXT"/>
+        <enum value="0x8D97" name="GL_ALPHA_INTEGER"/>
+        <enum value="0x8D97" name="GL_ALPHA_INTEGER_EXT"/>
+        <enum value="0x8D98" name="GL_RGB_INTEGER"/>
+        <enum value="0x8D98" name="GL_RGB_INTEGER_EXT"/>
+        <enum value="0x8D99" name="GL_RGBA_INTEGER"/>
+        <enum value="0x8D99" name="GL_RGBA_INTEGER_EXT"/>
+        <enum value="0x8D9A" name="GL_BGR_INTEGER"/>
+        <enum value="0x8D9A" name="GL_BGR_INTEGER_EXT"/>
+        <enum value="0x8D9B" name="GL_BGRA_INTEGER"/>
+        <enum value="0x8D9B" name="GL_BGRA_INTEGER_EXT"/>
+        <enum value="0x8D9C" name="GL_LUMINANCE_INTEGER_EXT"/>
+        <enum value="0x8D9D" name="GL_LUMINANCE_ALPHA_INTEGER_EXT"/>
+        <enum value="0x8D9E" name="GL_RGBA_INTEGER_MODE_EXT"/>
+        <enum value="0x8D9F" name="GL_INT_2_10_10_10_REV"/>
+        <enum value="0x8DA0" name="GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV"/>
+        <enum value="0x8DA1" name="GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV"/>
+        <enum value="0x8DA2" name="GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV"/>
+        <enum value="0x8DA3" name="GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV"/>
+        <enum value="0x8DA4" name="GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV"/>
+        <enum value="0x8DA5" name="GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV"/>
+        <enum value="0x8DA6" name="GL_MAX_PROGRAM_GENERIC_RESULTS_NV"/>
+        <enum value="0x8DA7" name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED"/>
+        <enum value="0x8DA7" name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB"/>
+        <enum value="0x8DA7" name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT"/>
+        <enum value="0x8DA7" name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES"/>
+        <enum value="0x8DA8" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"/>
+        <enum value="0x8DA8" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB"/>
+        <enum value="0x8DA8" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT"/>
+        <enum value="0x8DA8" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES"/>
+        <enum value="0x8DA9" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB"/>
+        <enum value="0x8DA9" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT"/>
+            <!-- Also see the odd namespace "NVTransformFeedbackToken" above -->
+        <enum value="0x8DAA" name="GL_LAYER_NV"/>
+        <enum value="0x8DAB" name="GL_DEPTH_COMPONENT32F_NV"/>
+        <enum value="0x8DAC" name="GL_DEPTH32F_STENCIL8_NV"/>
+        <enum value="0x8DAD" name="GL_FLOAT_32_UNSIGNED_INT_24_8_REV"/>
+        <enum value="0x8DAD" name="GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV"/>
+        <enum value="0x8DAE" name="GL_SHADER_INCLUDE_ARB"/>
+        <enum value="0x8DAF" name="GL_DEPTH_BUFFER_FLOAT_MODE_NV"/>
+            <unused start="0x8DB0" end="0x8DB8" vendor="NV"/>
+        <enum value="0x8DB9" name="GL_FRAMEBUFFER_SRGB"/>
+        <enum value="0x8DB9" name="GL_FRAMEBUFFER_SRGB_EXT"/>
+        <enum value="0x8DBA" name="GL_FRAMEBUFFER_SRGB_CAPABLE_EXT"/>
+        <enum value="0x8DBB" name="GL_COMPRESSED_RED_RGTC1"/>
+        <enum value="0x8DBB" name="GL_COMPRESSED_RED_RGTC1_EXT"/>
+        <enum value="0x8DBC" name="GL_COMPRESSED_SIGNED_RED_RGTC1"/>
+        <enum value="0x8DBC" name="GL_COMPRESSED_SIGNED_RED_RGTC1_EXT"/>
+        <enum value="0x8DBD" name="GL_COMPRESSED_RED_GREEN_RGTC2_EXT"/>
+        <enum value="0x8DBD" name="GL_COMPRESSED_RG_RGTC2"/>
+        <enum value="0x8DBE" name="GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT"/>
+        <enum value="0x8DBE" name="GL_COMPRESSED_SIGNED_RG_RGTC2"/>
+        <enum value="0x8DC0" name="GL_SAMPLER_1D_ARRAY"/>
+        <enum value="0x8DC0" name="GL_SAMPLER_1D_ARRAY_EXT"/>
+        <enum value="0x8DC1" name="GL_SAMPLER_2D_ARRAY"/>
+        <enum value="0x8DC1" name="GL_SAMPLER_2D_ARRAY_EXT"/>
+        <enum value="0x8DC2" name="GL_SAMPLER_BUFFER"/>
+        <enum value="0x8DC2" name="GL_SAMPLER_BUFFER_EXT"/>
+        <enum value="0x8DC2" name="GL_SAMPLER_BUFFER_OES"/>
+        <enum value="0x8DC3" name="GL_SAMPLER_1D_ARRAY_SHADOW"/>
+        <enum value="0x8DC3" name="GL_SAMPLER_1D_ARRAY_SHADOW_EXT"/>
+        <enum value="0x8DC4" name="GL_SAMPLER_2D_ARRAY_SHADOW"/>
+        <enum value="0x8DC4" name="GL_SAMPLER_2D_ARRAY_SHADOW_EXT"/>
+        <enum value="0x8DC4" name="GL_SAMPLER_2D_ARRAY_SHADOW_NV"/>
+        <enum value="0x8DC5" name="GL_SAMPLER_CUBE_SHADOW"/>
+        <enum value="0x8DC5" name="GL_SAMPLER_CUBE_SHADOW_EXT"/>
+        <enum value="0x8DC5" name="GL_SAMPLER_CUBE_SHADOW_NV"/>
+        <enum value="0x8DC6" name="GL_UNSIGNED_INT_VEC2"/>
+        <enum value="0x8DC6" name="GL_UNSIGNED_INT_VEC2_EXT"/>
+        <enum value="0x8DC7" name="GL_UNSIGNED_INT_VEC3"/>
+        <enum value="0x8DC7" name="GL_UNSIGNED_INT_VEC3_EXT"/>
+        <enum value="0x8DC8" name="GL_UNSIGNED_INT_VEC4"/>
+        <enum value="0x8DC8" name="GL_UNSIGNED_INT_VEC4_EXT"/>
+        <enum value="0x8DC9" name="GL_INT_SAMPLER_1D"/>
+        <enum value="0x8DC9" name="GL_INT_SAMPLER_1D_EXT"/>
+        <enum value="0x8DCA" name="GL_INT_SAMPLER_2D"/>
+        <enum value="0x8DCA" name="GL_INT_SAMPLER_2D_EXT"/>
+        <enum value="0x8DCB" name="GL_INT_SAMPLER_3D"/>
+        <enum value="0x8DCB" name="GL_INT_SAMPLER_3D_EXT"/>
+        <enum value="0x8DCC" name="GL_INT_SAMPLER_CUBE"/>
+        <enum value="0x8DCC" name="GL_INT_SAMPLER_CUBE_EXT"/>
+        <enum value="0x8DCD" name="GL_INT_SAMPLER_2D_RECT"/>
+        <enum value="0x8DCD" name="GL_INT_SAMPLER_2D_RECT_EXT"/>
+        <enum value="0x8DCE" name="GL_INT_SAMPLER_1D_ARRAY"/>
+        <enum value="0x8DCE" name="GL_INT_SAMPLER_1D_ARRAY_EXT"/>
+        <enum value="0x8DCF" name="GL_INT_SAMPLER_2D_ARRAY"/>
+        <enum value="0x8DCF" name="GL_INT_SAMPLER_2D_ARRAY_EXT"/>
+        <enum value="0x8DD0" name="GL_INT_SAMPLER_BUFFER"/>
+        <enum value="0x8DD0" name="GL_INT_SAMPLER_BUFFER_EXT"/>
+        <enum value="0x8DD0" name="GL_INT_SAMPLER_BUFFER_OES"/>
+        <enum value="0x8DD1" name="GL_UNSIGNED_INT_SAMPLER_1D"/>
+        <enum value="0x8DD1" name="GL_UNSIGNED_INT_SAMPLER_1D_EXT"/>
+        <enum value="0x8DD2" name="GL_UNSIGNED_INT_SAMPLER_2D"/>
+        <enum value="0x8DD2" name="GL_UNSIGNED_INT_SAMPLER_2D_EXT"/>
+        <enum value="0x8DD3" name="GL_UNSIGNED_INT_SAMPLER_3D"/>
+        <enum value="0x8DD3" name="GL_UNSIGNED_INT_SAMPLER_3D_EXT"/>
+        <enum value="0x8DD4" name="GL_UNSIGNED_INT_SAMPLER_CUBE"/>
+        <enum value="0x8DD4" name="GL_UNSIGNED_INT_SAMPLER_CUBE_EXT"/>
+        <enum value="0x8DD5" name="GL_UNSIGNED_INT_SAMPLER_2D_RECT"/>
+        <enum value="0x8DD5" name="GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT"/>
+        <enum value="0x8DD6" name="GL_UNSIGNED_INT_SAMPLER_1D_ARRAY"/>
+        <enum value="0x8DD6" name="GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT"/>
+        <enum value="0x8DD7" name="GL_UNSIGNED_INT_SAMPLER_2D_ARRAY"/>
+        <enum value="0x8DD7" name="GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT"/>
+        <enum value="0x8DD8" name="GL_UNSIGNED_INT_SAMPLER_BUFFER"/>
+        <enum value="0x8DD8" name="GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT"/>
+        <enum value="0x8DD8" name="GL_UNSIGNED_INT_SAMPLER_BUFFER_OES"/>
+        <enum value="0x8DD9" name="GL_GEOMETRY_SHADER"/>
+        <enum value="0x8DD9" name="GL_GEOMETRY_SHADER_ARB"/>
+        <enum value="0x8DD9" name="GL_GEOMETRY_SHADER_EXT"/>
+        <enum value="0x8DD9" name="GL_GEOMETRY_SHADER_OES"/>
+        <enum value="0x8DDA" name="GL_GEOMETRY_VERTICES_OUT_ARB"/>
+        <enum value="0x8DDA" name="GL_GEOMETRY_VERTICES_OUT_EXT"/>
+        <enum value="0x8DDB" name="GL_GEOMETRY_INPUT_TYPE_ARB"/>
+        <enum value="0x8DDB" name="GL_GEOMETRY_INPUT_TYPE_EXT"/>
+        <enum value="0x8DDC" name="GL_GEOMETRY_OUTPUT_TYPE_ARB"/>
+        <enum value="0x8DDC" name="GL_GEOMETRY_OUTPUT_TYPE_EXT"/>
+        <enum value="0x8DDD" name="GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB"/>
+        <enum value="0x8DDD" name="GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT"/>
+        <enum value="0x8DDE" name="GL_MAX_VERTEX_VARYING_COMPONENTS_ARB"/>
+        <enum value="0x8DDE" name="GL_MAX_VERTEX_VARYING_COMPONENTS_EXT"/>
+        <enum value="0x8DDF" name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS"/>
+        <enum value="0x8DDF" name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB"/>
+        <enum value="0x8DDF" name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8DDF" name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES"/>
+        <enum value="0x8DE0" name="GL_MAX_GEOMETRY_OUTPUT_VERTICES"/>
+        <enum value="0x8DE0" name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB"/>
+        <enum value="0x8DE0" name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT"/>
+        <enum value="0x8DE0" name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES"/>
+        <enum value="0x8DE1" name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS"/>
+        <enum value="0x8DE1" name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB"/>
+        <enum value="0x8DE1" name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x8DE1" name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES"/>
+        <enum value="0x8DE2" name="GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT"/>
+        <enum value="0x8DE3" name="GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT"/>
+        <enum value="0x8DE4" name="GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT"/>
+        <enum value="0x8DE5" name="GL_ACTIVE_SUBROUTINES"/>
+        <enum value="0x8DE6" name="GL_ACTIVE_SUBROUTINE_UNIFORMS"/>
+        <enum value="0x8DE7" name="GL_MAX_SUBROUTINES"/>
+        <enum value="0x8DE8" name="GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS"/>
+        <enum value="0x8DE9" name="GL_NAMED_STRING_LENGTH_ARB"/>
+        <enum value="0x8DEA" name="GL_NAMED_STRING_TYPE_ARB"/>
+            <unused start="0x8DEB" end="0x8DEC" vendor="NV"/>
+        <enum value="0x8DED" name="GL_MAX_BINDABLE_UNIFORM_SIZE_EXT"/>
+        <enum value="0x8DEE" name="GL_UNIFORM_BUFFER_EXT"/>
+        <enum value="0x8DEF" name="GL_UNIFORM_BUFFER_BINDING_EXT"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8DF0" end="0x8E0F" vendor="OES">
+        <enum value="0x8DF0" name="GL_LOW_FLOAT"/>
+        <enum value="0x8DF1" name="GL_MEDIUM_FLOAT"/>
+        <enum value="0x8DF2" name="GL_HIGH_FLOAT"/>
+        <enum value="0x8DF3" name="GL_LOW_INT"/>
+        <enum value="0x8DF4" name="GL_MEDIUM_INT"/>
+        <enum value="0x8DF5" name="GL_HIGH_INT"/>
+        <enum value="0x8DF6" name="GL_UNSIGNED_INT_10_10_10_2_OES"/>
+        <enum value="0x8DF7" name="GL_INT_10_10_10_2_OES"/>
+        <enum value="0x8DF8" name="GL_SHADER_BINARY_FORMATS"/>
+        <enum value="0x8DF9" name="GL_NUM_SHADER_BINARY_FORMATS"/>
+        <enum value="0x8DFA" name="GL_SHADER_COMPILER"/>
+        <enum value="0x8DFB" name="GL_MAX_VERTEX_UNIFORM_VECTORS"/>
+        <enum value="0x8DFC" name="GL_MAX_VARYING_VECTORS"/>
+        <enum value="0x8DFD" name="GL_MAX_FRAGMENT_UNIFORM_VECTORS"/>
+            <unused start="0x8DFE" end="0x8E0F" vendor="OES"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8E10" end="0x8E8F" vendor="NV" comment="For Michael Gold 2006/08/07">
+        <enum value="0x8E10" name="GL_RENDERBUFFER_COLOR_SAMPLES_NV"/>
+        <enum value="0x8E11" name="GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV"/>
+        <enum value="0x8E12" name="GL_MULTISAMPLE_COVERAGE_MODES_NV"/>
+        <enum value="0x8E13" name="GL_QUERY_WAIT"/>
+        <enum value="0x8E13" name="GL_QUERY_WAIT_NV"/>
+        <enum value="0x8E14" name="GL_QUERY_NO_WAIT"/>
+        <enum value="0x8E14" name="GL_QUERY_NO_WAIT_NV"/>
+        <enum value="0x8E15" name="GL_QUERY_BY_REGION_WAIT"/>
+        <enum value="0x8E15" name="GL_QUERY_BY_REGION_WAIT_NV"/>
+        <enum value="0x8E16" name="GL_QUERY_BY_REGION_NO_WAIT"/>
+        <enum value="0x8E16" name="GL_QUERY_BY_REGION_NO_WAIT_NV"/>
+        <enum value="0x8E17" name="GL_QUERY_WAIT_INVERTED"/>
+        <enum value="0x8E18" name="GL_QUERY_NO_WAIT_INVERTED"/>
+        <enum value="0x8E19" name="GL_QUERY_BY_REGION_WAIT_INVERTED"/>
+        <enum value="0x8E1A" name="GL_QUERY_BY_REGION_NO_WAIT_INVERTED"/>
+        <enum value="0x8E1B" name="GL_POLYGON_OFFSET_CLAMP_EXT"/>
+            <unused start="0x8E1C" end="0x8E1D" vendor="NV"/>
+        <enum value="0x8E1E" name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+        <enum value="0x8E1E" name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8E1E" name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES"/>
+        <enum value="0x8E1F" name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+        <enum value="0x8E1F" name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8E1F" name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES"/>
+        <enum value="0x8E20" name="GL_COLOR_SAMPLES_NV"/>
+            <unused start="0x8E21" vendor="NV"/>
+        <enum value="0x8E22" name="GL_TRANSFORM_FEEDBACK"/>
+        <enum value="0x8E22" name="GL_TRANSFORM_FEEDBACK_NV"/>
+        <enum value="0x8E23" name="GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED"/>
+        <enum value="0x8E23" name="GL_TRANSFORM_FEEDBACK_PAUSED" alias="GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED"/>
+        <enum value="0x8E23" name="GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV"/>
+        <enum value="0x8E24" name="GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE"/>
+        <enum value="0x8E24" name="GL_TRANSFORM_FEEDBACK_ACTIVE" alias="GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE"/>
+        <enum value="0x8E24" name="GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV"/>
+        <enum value="0x8E25" name="GL_TRANSFORM_FEEDBACK_BINDING"/>
+        <enum value="0x8E25" name="GL_TRANSFORM_FEEDBACK_BINDING_NV"/>
+        <enum value="0x8E26" name="GL_FRAME_NV"/>
+        <enum value="0x8E27" name="GL_FIELDS_NV"/>
+        <enum value="0x8E28" name="GL_CURRENT_TIME_NV"/>
+        <enum value="0x8E28" name="GL_TIMESTAMP"/>
+        <enum value="0x8E28" name="GL_TIMESTAMP_EXT"/>
+        <enum value="0x8E29" name="GL_NUM_FILL_STREAMS_NV"/>
+        <enum value="0x8E2A" name="GL_PRESENT_TIME_NV"/>
+        <enum value="0x8E2B" name="GL_PRESENT_DURATION_NV"/>
+        <enum value="0x8E2C" name="GL_DEPTH_COMPONENT16_NONLINEAR_NV"/>
+        <enum value="0x8E2D" name="GL_PROGRAM_MATRIX_EXT"/>
+        <enum value="0x8E2E" name="GL_TRANSPOSE_PROGRAM_MATRIX_EXT"/>
+        <enum value="0x8E2F" name="GL_PROGRAM_MATRIX_STACK_DEPTH_EXT"/>
+            <unused start="0x8E30" end="0x8E41" vendor="NV"/>
+        <enum value="0x8E42" name="GL_TEXTURE_SWIZZLE_R"/>
+        <enum value="0x8E42" name="GL_TEXTURE_SWIZZLE_R_EXT"/>
+        <enum value="0x8E43" name="GL_TEXTURE_SWIZZLE_G"/>
+        <enum value="0x8E43" name="GL_TEXTURE_SWIZZLE_G_EXT"/>
+        <enum value="0x8E44" name="GL_TEXTURE_SWIZZLE_B"/>
+        <enum value="0x8E44" name="GL_TEXTURE_SWIZZLE_B_EXT"/>
+        <enum value="0x8E45" name="GL_TEXTURE_SWIZZLE_A"/>
+        <enum value="0x8E45" name="GL_TEXTURE_SWIZZLE_A_EXT"/>
+        <enum value="0x8E46" name="GL_TEXTURE_SWIZZLE_RGBA"/>
+        <enum value="0x8E46" name="GL_TEXTURE_SWIZZLE_RGBA_EXT"/>
+        <enum value="0x8E47" name="GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"/>
+        <enum value="0x8E48" name="GL_ACTIVE_SUBROUTINE_MAX_LENGTH"/>
+        <enum value="0x8E49" name="GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"/>
+        <enum value="0x8E4A" name="GL_NUM_COMPATIBLE_SUBROUTINES"/>
+        <enum value="0x8E4B" name="GL_COMPATIBLE_SUBROUTINES"/>
+        <enum value="0x8E4C" name="GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION"/>
+        <enum value="0x8E4C" name="GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT"/>
+        <enum value="0x8E4D" name="GL_FIRST_VERTEX_CONVENTION"/>
+        <enum value="0x8E4D" name="GL_FIRST_VERTEX_CONVENTION_EXT"/>
+        <enum value="0x8E4D" name="GL_FIRST_VERTEX_CONVENTION_OES"/>
+        <enum value="0x8E4E" name="GL_LAST_VERTEX_CONVENTION"/>
+        <enum value="0x8E4E" name="GL_LAST_VERTEX_CONVENTION_EXT"/>
+        <enum value="0x8E4E" name="GL_LAST_VERTEX_CONVENTION_OES"/>
+        <enum value="0x8E4F" name="GL_PROVOKING_VERTEX"/>
+        <enum value="0x8E4F" name="GL_PROVOKING_VERTEX_EXT"/>
+        <enum value="0x8E50" name="GL_SAMPLE_POSITION"/>
+        <enum value="0x8E50" name="GL_SAMPLE_POSITION_NV"/>
+        <enum value="0x8E50" name="GL_SAMPLE_LOCATION_ARB" alias="GL_SAMPLE_POSITION"/>
+        <enum value="0x8E50" name="GL_SAMPLE_LOCATION_NV" alias="GL_SAMPLE_POSITION_NV"/>
+        <enum value="0x8E51" name="GL_SAMPLE_MASK"/>
+        <enum value="0x8E51" name="GL_SAMPLE_MASK_NV"/>
+        <enum value="0x8E52" name="GL_SAMPLE_MASK_VALUE"/>
+        <enum value="0x8E52" name="GL_SAMPLE_MASK_VALUE_NV"/>
+        <enum value="0x8E53" name="GL_TEXTURE_BINDING_RENDERBUFFER_NV"/>
+        <enum value="0x8E54" name="GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV"/>
+        <enum value="0x8E55" name="GL_TEXTURE_RENDERBUFFER_NV"/>
+        <enum value="0x8E56" name="GL_SAMPLER_RENDERBUFFER_NV"/>
+        <enum value="0x8E57" name="GL_INT_SAMPLER_RENDERBUFFER_NV"/>
+        <enum value="0x8E58" name="GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV"/>
+        <enum value="0x8E59" name="GL_MAX_SAMPLE_MASK_WORDS"/>
+        <enum value="0x8E59" name="GL_MAX_SAMPLE_MASK_WORDS_NV"/>
+        <enum value="0x8E5A" name="GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV"/>
+        <enum value="0x8E5A" name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS"/>
+        <enum value="0x8E5A" name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT"/>
+        <enum value="0x8E5A" name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES"/>
+        <enum value="0x8E5B" name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET"/>
+        <enum value="0x8E5B" name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES"/>
+        <enum value="0x8E5B" name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV"/>
+        <enum value="0x8E5C" name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET"/>
+        <enum value="0x8E5C" name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES"/>
+        <enum value="0x8E5C" name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV"/>
+        <enum value="0x8E5D" name="GL_FRAGMENT_INTERPOLATION_OFFSET_BITS"/>
+        <enum value="0x8E5D" name="GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES"/>
+        <enum value="0x8E5D" name="GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV"/>
+        <enum value="0x8E5E" name="GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET"/>
+        <enum value="0x8E5E" name="GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB"/>
+        <enum value="0x8E5E" name="GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV"/>
+        <enum value="0x8E5F" name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET"/>
+        <enum value="0x8E5F" name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB"/>
+        <enum value="0x8E5F" name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV"/>
+            <unused start="0x8E60" end="0x8E6F" vendor="NV"/>
+        <enum value="0x8E70" name="GL_MAX_TRANSFORM_FEEDBACK_BUFFERS"/>
+        <enum value="0x8E71" name="GL_MAX_VERTEX_STREAMS"/>
+        <enum value="0x8E72" name="GL_PATCH_VERTICES"/>
+        <enum value="0x8E72" name="GL_PATCH_VERTICES_EXT"/>
+        <enum value="0x8E72" name="GL_PATCH_VERTICES_OES"/>
+        <enum value="0x8E73" name="GL_PATCH_DEFAULT_INNER_LEVEL"/>
+        <enum value="0x8E73" name="GL_PATCH_DEFAULT_INNER_LEVEL_EXT"/>
+        <enum value="0x8E74" name="GL_PATCH_DEFAULT_OUTER_LEVEL"/>
+        <enum value="0x8E74" name="GL_PATCH_DEFAULT_OUTER_LEVEL_EXT"/>
+        <enum value="0x8E75" name="GL_TESS_CONTROL_OUTPUT_VERTICES"/>
+        <enum value="0x8E75" name="GL_TESS_CONTROL_OUTPUT_VERTICES_EXT"/>
+        <enum value="0x8E75" name="GL_TESS_CONTROL_OUTPUT_VERTICES_OES"/>
+        <enum value="0x8E76" name="GL_TESS_GEN_MODE"/>
+        <enum value="0x8E76" name="GL_TESS_GEN_MODE_EXT"/>
+        <enum value="0x8E76" name="GL_TESS_GEN_MODE_OES"/>
+        <enum value="0x8E77" name="GL_TESS_GEN_SPACING"/>
+        <enum value="0x8E77" name="GL_TESS_GEN_SPACING_EXT"/>
+        <enum value="0x8E77" name="GL_TESS_GEN_SPACING_OES"/>
+        <enum value="0x8E78" name="GL_TESS_GEN_VERTEX_ORDER"/>
+        <enum value="0x8E78" name="GL_TESS_GEN_VERTEX_ORDER_EXT"/>
+        <enum value="0x8E78" name="GL_TESS_GEN_VERTEX_ORDER_OES"/>
+        <enum value="0x8E79" name="GL_TESS_GEN_POINT_MODE"/>
+        <enum value="0x8E79" name="GL_TESS_GEN_POINT_MODE_EXT"/>
+        <enum value="0x8E79" name="GL_TESS_GEN_POINT_MODE_OES"/>
+        <enum value="0x8E7A" name="GL_ISOLINES"/>
+        <enum value="0x8E7A" name="GL_ISOLINES_EXT"/>
+        <enum value="0x8E7A" name="GL_ISOLINES_OES"/>
+        <enum value="0x8E7B" name="GL_FRACTIONAL_ODD"/>
+        <enum value="0x8E7B" name="GL_FRACTIONAL_ODD_EXT"/>
+        <enum value="0x8E7B" name="GL_FRACTIONAL_ODD_OES"/>
+        <enum value="0x8E7C" name="GL_FRACTIONAL_EVEN"/>
+        <enum value="0x8E7C" name="GL_FRACTIONAL_EVEN_EXT"/>
+        <enum value="0x8E7C" name="GL_FRACTIONAL_EVEN_OES"/>
+        <enum value="0x8E7D" name="GL_MAX_PATCH_VERTICES"/>
+        <enum value="0x8E7D" name="GL_MAX_PATCH_VERTICES_EXT"/>
+        <enum value="0x8E7D" name="GL_MAX_PATCH_VERTICES_OES"/>
+        <enum value="0x8E7E" name="GL_MAX_TESS_GEN_LEVEL"/>
+        <enum value="0x8E7E" name="GL_MAX_TESS_GEN_LEVEL_EXT"/>
+        <enum value="0x8E7E" name="GL_MAX_TESS_GEN_LEVEL_OES"/>
+        <enum value="0x8E7F" name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+        <enum value="0x8E7F" name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8E7F" name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES"/>
+        <enum value="0x8E80" name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+        <enum value="0x8E80" name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8E80" name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES"/>
+        <enum value="0x8E81" name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS"/>
+        <enum value="0x8E81" name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT"/>
+        <enum value="0x8E81" name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES"/>
+        <enum value="0x8E82" name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS"/>
+        <enum value="0x8E82" name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT"/>
+        <enum value="0x8E82" name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES"/>
+        <enum value="0x8E83" name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS"/>
+        <enum value="0x8E83" name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x8E83" name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES"/>
+        <enum value="0x8E84" name="GL_MAX_TESS_PATCH_COMPONENTS"/>
+        <enum value="0x8E84" name="GL_MAX_TESS_PATCH_COMPONENTS_EXT"/>
+        <enum value="0x8E84" name="GL_MAX_TESS_PATCH_COMPONENTS_OES"/>
+        <enum value="0x8E85" name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS"/>
+        <enum value="0x8E85" name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x8E85" name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES"/>
+        <enum value="0x8E86" name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS"/>
+        <enum value="0x8E86" name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x8E86" name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES"/>
+        <enum value="0x8E87" name="GL_TESS_EVALUATION_SHADER"/>
+        <enum value="0x8E87" name="GL_TESS_EVALUATION_SHADER_EXT"/>
+        <enum value="0x8E87" name="GL_TESS_EVALUATION_SHADER_OES"/>
+        <enum value="0x8E88" name="GL_TESS_CONTROL_SHADER"/>
+        <enum value="0x8E88" name="GL_TESS_CONTROL_SHADER_EXT"/>
+        <enum value="0x8E88" name="GL_TESS_CONTROL_SHADER_OES"/>
+        <enum value="0x8E89" name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS"/>
+        <enum value="0x8E89" name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT"/>
+        <enum value="0x8E89" name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES"/>
+        <enum value="0x8E8A" name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS"/>
+        <enum value="0x8E8A" name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT"/>
+        <enum value="0x8E8A" name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES"/>
+            <unused start="0x8E8B" vendor="NV"/>
+        <enum value="0x8E8C" name="GL_COMPRESSED_RGBA_BPTC_UNORM"/>
+        <enum value="0x8E8C" name="GL_COMPRESSED_RGBA_BPTC_UNORM_ARB"/>
+        <enum value="0x8E8D" name="GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM"/>
+        <enum value="0x8E8D" name="GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB"/>
+        <enum value="0x8E8E" name="GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT"/>
+        <enum value="0x8E8E" name="GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB"/>
+        <enum value="0x8E8F" name="GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT"/>
+        <enum value="0x8E8F" name="GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8E90" end="0x8E9F" vendor="QNX" comment="For QNX_texture_tiling, QNX_complex_polygon, QNX_stippled_lines (Khronos bug 696)">
+            <unused start="0x8E90" end="0x8E9F" vendor="QNX"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8EA0" end="0x8EAF" vendor="IMG">
+            <unused start="0x8EA0" end="0x8EAF" vendor="IMG"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8EB0" end="0x8EBF" vendor="OES" comment="For Affie Munshi 2007/07/20">
+            <unused start="0x8EB0" end="0x8EBF" vendor="OES"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8EC0" end="0x8ECF" vendor="Vincent">
+            <unused start="0x8EC0" end="0x8ECF" vendor="Vincent"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8ED0" end="0x8F4F" vendor="NV" comment="For Pat Brown, Khronos bug 3191">
+        <enum value="0x8ED0" name="GL_COVERAGE_COMPONENT_NV"/>
+        <enum value="0x8ED1" name="GL_COVERAGE_COMPONENT4_NV"/>
+        <enum value="0x8ED2" name="GL_COVERAGE_ATTACHMENT_NV"/>
+        <enum value="0x8ED3" name="GL_COVERAGE_BUFFERS_NV"/>
+        <enum value="0x8ED4" name="GL_COVERAGE_SAMPLES_NV"/>
+        <enum value="0x8ED5" name="GL_COVERAGE_ALL_FRAGMENTS_NV"/>
+        <enum value="0x8ED6" name="GL_COVERAGE_EDGE_FRAGMENTS_NV"/>
+        <enum value="0x8ED7" name="GL_COVERAGE_AUTOMATIC_NV"/>
+            <unused start="0x8ED8" end="0x8F0F" vendor="NV"/>
+        <enum value="0x8F10" name="GL_INCLUSIVE_EXT"/>
+        <enum value="0x8F11" name="GL_EXCLUSIVE_EXT"/>
+        <enum value="0x8F12" name="GL_WINDOW_RECTANGLE_EXT"/>
+        <enum value="0x8F13" name="GL_WINDOW_RECTANGLE_MODE_EXT"/>
+        <enum value="0x8F14" name="GL_MAX_WINDOW_RECTANGLES_EXT"/>
+        <enum value="0x8F15" name="GL_NUM_WINDOW_RECTANGLES_EXT"/>
+            <unused start="0x8F16" end="0x8F1C" vendor="NV"/>
+        <enum value="0x8F1D" name="GL_BUFFER_GPU_ADDRESS_NV"/>
+        <enum value="0x8F1E" name="GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV"/>
+        <enum value="0x8F1F" name="GL_ELEMENT_ARRAY_UNIFIED_NV"/>
+        <enum value="0x8F20" name="GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F21" name="GL_VERTEX_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F22" name="GL_NORMAL_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F23" name="GL_COLOR_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F24" name="GL_INDEX_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F25" name="GL_TEXTURE_COORD_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F26" name="GL_EDGE_FLAG_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F27" name="GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F28" name="GL_FOG_COORD_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F29" name="GL_ELEMENT_ARRAY_ADDRESS_NV"/>
+        <enum value="0x8F2A" name="GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F2B" name="GL_VERTEX_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F2C" name="GL_NORMAL_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F2D" name="GL_COLOR_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F2E" name="GL_INDEX_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F2F" name="GL_TEXTURE_COORD_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F30" name="GL_EDGE_FLAG_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F31" name="GL_SECONDARY_COLOR_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F32" name="GL_FOG_COORD_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F33" name="GL_ELEMENT_ARRAY_LENGTH_NV"/>
+        <enum value="0x8F34" name="GL_GPU_ADDRESS_NV"/>
+        <enum value="0x8F35" name="GL_MAX_SHADER_BUFFER_ADDRESS_NV"/>
+        <enum value="0x8F36" name="GL_COPY_READ_BUFFER"/>
+        <enum value="0x8F36" name="GL_COPY_READ_BUFFER_NV"/>
+        <enum value="0x8F36" name="GL_COPY_READ_BUFFER_BINDING" alias="GL_COPY_READ_BUFFER"/>
+        <enum value="0x8F37" name="GL_COPY_WRITE_BUFFER"/>
+        <enum value="0x8F37" name="GL_COPY_WRITE_BUFFER_NV"/>
+        <enum value="0x8F37" name="GL_COPY_WRITE_BUFFER_BINDING" alias="GL_COPY_WRITE_BUFFER"/>
+        <enum value="0x8F38" name="GL_MAX_IMAGE_UNITS"/>
+        <enum value="0x8F38" name="GL_MAX_IMAGE_UNITS_EXT"/>
+        <enum value="0x8F39" name="GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS"/>
+        <enum value="0x8F39" name="GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT"/>
+        <enum value="0x8F39" name="GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES" alias="GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS"/>
+        <enum value="0x8F3A" name="GL_IMAGE_BINDING_NAME"/>
+        <enum value="0x8F3A" name="GL_IMAGE_BINDING_NAME_EXT"/>
+        <enum value="0x8F3B" name="GL_IMAGE_BINDING_LEVEL"/>
+        <enum value="0x8F3B" name="GL_IMAGE_BINDING_LEVEL_EXT"/>
+        <enum value="0x8F3C" name="GL_IMAGE_BINDING_LAYERED"/>
+        <enum value="0x8F3C" name="GL_IMAGE_BINDING_LAYERED_EXT"/>
+        <enum value="0x8F3D" name="GL_IMAGE_BINDING_LAYER"/>
+        <enum value="0x8F3D" name="GL_IMAGE_BINDING_LAYER_EXT"/>
+        <enum value="0x8F3E" name="GL_IMAGE_BINDING_ACCESS"/>
+        <enum value="0x8F3E" name="GL_IMAGE_BINDING_ACCESS_EXT"/>
+        <enum value="0x8F3F" name="GL_DRAW_INDIRECT_BUFFER"/>
+        <enum value="0x8F40" name="GL_DRAW_INDIRECT_UNIFIED_NV"/>
+        <enum value="0x8F41" name="GL_DRAW_INDIRECT_ADDRESS_NV"/>
+        <enum value="0x8F42" name="GL_DRAW_INDIRECT_LENGTH_NV"/>
+        <enum value="0x8F43" name="GL_DRAW_INDIRECT_BUFFER_BINDING"/>
+        <enum value="0x8F44" name="GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV"/>
+        <enum value="0x8F45" name="GL_MAX_PROGRAM_SUBROUTINE_NUM_NV"/>
+        <enum value="0x8F46" name="GL_DOUBLE_MAT2"/>
+        <enum value="0x8F46" name="GL_DOUBLE_MAT2_EXT"/>
+        <enum value="0x8F47" name="GL_DOUBLE_MAT3"/>
+        <enum value="0x8F47" name="GL_DOUBLE_MAT3_EXT"/>
+        <enum value="0x8F48" name="GL_DOUBLE_MAT4"/>
+        <enum value="0x8F48" name="GL_DOUBLE_MAT4_EXT"/>
+        <enum value="0x8F49" name="GL_DOUBLE_MAT2x3"/>
+        <enum value="0x8F49" name="GL_DOUBLE_MAT2x3_EXT"/>
+        <enum value="0x8F4A" name="GL_DOUBLE_MAT2x4"/>
+        <enum value="0x8F4A" name="GL_DOUBLE_MAT2x4_EXT"/>
+        <enum value="0x8F4B" name="GL_DOUBLE_MAT3x2"/>
+        <enum value="0x8F4B" name="GL_DOUBLE_MAT3x2_EXT"/>
+        <enum value="0x8F4C" name="GL_DOUBLE_MAT3x4"/>
+        <enum value="0x8F4C" name="GL_DOUBLE_MAT3x4_EXT"/>
+        <enum value="0x8F4D" name="GL_DOUBLE_MAT4x2"/>
+        <enum value="0x8F4D" name="GL_DOUBLE_MAT4x2_EXT"/>
+        <enum value="0x8F4E" name="GL_DOUBLE_MAT4x3"/>
+        <enum value="0x8F4E" name="GL_DOUBLE_MAT4x3_EXT"/>
+        <enum value="0x8F4F" name="GL_VERTEX_BINDING_BUFFER"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8F50" end="0x8F5F" vendor="ZiiLabs" comment="For Jon Kennedy, Khronos public bug 75">
+            <unused start="0x8F50" end="0x8F5F" vendor="ZiiLabs"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8F60" end="0x8F6F" vendor="ARM" comment="For Remi Pedersen, Khronos bug 3745">
+        <enum value="0x8F60" name="GL_MALI_SHADER_BINARY_ARM"/>
+        <enum value="0x8F61" name="GL_MALI_PROGRAM_BINARY_ARM"/>
+            <unused start="0x8F62" vendor="ARM"/>
+        <enum value="0x8F63" name="GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT"/>
+        <enum value="0x8F64" name="GL_SHADER_PIXEL_LOCAL_STORAGE_EXT"/>
+        <enum value="0x8F65" name="GL_FETCH_PER_SAMPLE_ARM"/>
+        <enum value="0x8F66" name="GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM"/>
+        <enum value="0x8F67" name="GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT"/>
+            <unused start="0x8F68" end="0x8F6F" vendor="ARM"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8F70" end="0x8F7F" vendor="HI" comment="For Mark Callow, Khronos bug 4055. Shared with EGL.">
+            <unused start="0x8F70" end="0x8F7F" vendor="HI"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8F80" end="0x8F8F" vendor="Zebra" comment="For Mike Weiblen, public bug 910">
+            <unused start="0x8F80" end="0x8F8F" vendor="Zebra"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8F90" end="0x8F9F" vendor="ARB">
+        <enum value="0x8F90" name="GL_RED_SNORM"/>
+        <enum value="0x8F91" name="GL_RG_SNORM"/>
+        <enum value="0x8F92" name="GL_RGB_SNORM"/>
+        <enum value="0x8F93" name="GL_RGBA_SNORM"/>
+        <enum value="0x8F94" name="GL_R8_SNORM"/>
+        <enum value="0x8F95" name="GL_RG8_SNORM"/>
+        <enum value="0x8F96" name="GL_RGB8_SNORM"/>
+        <enum value="0x8F97" name="GL_RGBA8_SNORM"/>
+        <enum value="0x8F98" name="GL_R16_SNORM"/>
+        <enum value="0x8F98" name="GL_R16_SNORM_EXT"/>
+        <enum value="0x8F99" name="GL_RG16_SNORM"/>
+        <enum value="0x8F99" name="GL_RG16_SNORM_EXT"/>
+        <enum value="0x8F9A" name="GL_RGB16_SNORM"/>
+        <enum value="0x8F9A" name="GL_RGB16_SNORM_EXT"/>
+        <enum value="0x8F9B" name="GL_RGBA16_SNORM"/>
+        <enum value="0x8F9B" name="GL_RGBA16_SNORM_EXT"/>
+        <enum value="0x8F9C" name="GL_SIGNED_NORMALIZED"/>
+        <enum value="0x8F9D" name="GL_PRIMITIVE_RESTART"/>
+        <enum value="0x8F9E" name="GL_PRIMITIVE_RESTART_INDEX"/>
+        <enum value="0x8F9F" name="GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8FA0" end="0x8FBF" vendor="QCOM" comment="For Maurice Ribble, bug 4512">
+        <enum value="0x8FA0" name="GL_PERFMON_GLOBAL_MODE_QCOM"/>
+            <unused start="0x8FA1" end="0x8FAF" vendor="QCOM"/>
+        <enum value="0x8FB0" name="GL_BINNING_CONTROL_HINT_QCOM"/>
+        <enum value="0x8FB1" name="GL_CPU_OPTIMIZED_QCOM"/>
+        <enum value="0x8FB2" name="GL_GPU_OPTIMIZED_QCOM"/>
+        <enum value="0x8FB3" name="GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM"/>
+            <unused start="0x8FB4" end="0x8FBA" vendor="QCOM"/>
+        <enum value="0x8FBB" name="GL_GPU_DISJOINT_EXT"/>
+            <unused start="0x8FBC" vendor="QCOM"/>
+        <enum value="0x8FBD" name="GL_SR8_EXT"/>
+        <enum value="0x8FBE" name="GL_SRG8_EXT"/>
+            <unused start="0x8FBF" vendor="QCOM"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8FC0" end="0x8FDF" vendor="VIV" comment="For Frido Garritsen, bug 4526">
+        <enum value="0x8FC4" name="GL_SHADER_BINARY_VIV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x8FE0" end="0x8FFF" vendor="NV" comment="For Pat Brown, bug 4935">
+        <enum value="0x8FE0" name="GL_INT8_NV"/>
+        <enum value="0x8FE1" name="GL_INT8_VEC2_NV"/>
+        <enum value="0x8FE2" name="GL_INT8_VEC3_NV"/>
+        <enum value="0x8FE3" name="GL_INT8_VEC4_NV"/>
+        <enum value="0x8FE4" name="GL_INT16_NV"/>
+        <enum value="0x8FE5" name="GL_INT16_VEC2_NV"/>
+        <enum value="0x8FE6" name="GL_INT16_VEC3_NV"/>
+        <enum value="0x8FE7" name="GL_INT16_VEC4_NV"/>
+        <enum value="0x8FE9" name="GL_INT64_VEC2_ARB"/>
+        <enum value="0x8FE9" name="GL_INT64_VEC2_NV"/>
+        <enum value="0x8FEA" name="GL_INT64_VEC3_ARB"/>
+        <enum value="0x8FEA" name="GL_INT64_VEC3_NV"/>
+        <enum value="0x8FEB" name="GL_INT64_VEC4_ARB"/>
+        <enum value="0x8FEB" name="GL_INT64_VEC4_NV"/>
+        <enum value="0x8FEC" name="GL_UNSIGNED_INT8_NV"/>
+        <enum value="0x8FED" name="GL_UNSIGNED_INT8_VEC2_NV"/>
+        <enum value="0x8FEE" name="GL_UNSIGNED_INT8_VEC3_NV"/>
+        <enum value="0x8FEF" name="GL_UNSIGNED_INT8_VEC4_NV"/>
+        <enum value="0x8FF0" name="GL_UNSIGNED_INT16_NV"/>
+        <enum value="0x8FF1" name="GL_UNSIGNED_INT16_VEC2_NV"/>
+        <enum value="0x8FF2" name="GL_UNSIGNED_INT16_VEC3_NV"/>
+        <enum value="0x8FF3" name="GL_UNSIGNED_INT16_VEC4_NV"/>
+        <enum value="0x8FF5" name="GL_UNSIGNED_INT64_VEC2_ARB"/>
+        <enum value="0x8FF5" name="GL_UNSIGNED_INT64_VEC2_NV"/>
+        <enum value="0x8FF6" name="GL_UNSIGNED_INT64_VEC3_ARB"/>
+        <enum value="0x8FF6" name="GL_UNSIGNED_INT64_VEC3_NV"/>
+        <enum value="0x8FF7" name="GL_UNSIGNED_INT64_VEC4_ARB"/>
+        <enum value="0x8FF7" name="GL_UNSIGNED_INT64_VEC4_NV"/>
+        <enum value="0x8FF8" name="GL_FLOAT16_NV"/>
+        <enum value="0x8FF9" name="GL_FLOAT16_VEC2_NV"/>
+        <enum value="0x8FFA" name="GL_FLOAT16_VEC3_NV"/>
+        <enum value="0x8FFB" name="GL_FLOAT16_VEC4_NV"/>
+        <enum value="0x8FFC" name="GL_DOUBLE_VEC2"/>
+        <enum value="0x8FFC" name="GL_DOUBLE_VEC2_EXT"/>
+        <enum value="0x8FFD" name="GL_DOUBLE_VEC3"/>
+        <enum value="0x8FFD" name="GL_DOUBLE_VEC3_EXT"/>
+        <enum value="0x8FFE" name="GL_DOUBLE_VEC4"/>
+        <enum value="0x8FFE" name="GL_DOUBLE_VEC4_EXT"/>
+            <unused start="0x8FFF" vendor="NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9000" end="0x901F" vendor="AMD" comment="For Bill Licea-Kane">
+        <enum value="0x9001" name="GL_SAMPLER_BUFFER_AMD"/>
+        <enum value="0x9002" name="GL_INT_SAMPLER_BUFFER_AMD"/>
+        <enum value="0x9003" name="GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD"/>
+        <enum value="0x9004" name="GL_TESSELLATION_MODE_AMD"/>
+        <enum value="0x9005" name="GL_TESSELLATION_FACTOR_AMD"/>
+        <enum value="0x9006" name="GL_DISCRETE_AMD"/>
+        <enum value="0x9007" name="GL_CONTINUOUS_AMD"/>
+            <unused start="0x9008" vendor="AMD"/>
+        <enum value="0x9009" name="GL_TEXTURE_CUBE_MAP_ARRAY"/>
+        <enum value="0x9009" name="GL_TEXTURE_CUBE_MAP_ARRAY_ARB"/>
+        <enum value="0x9009" name="GL_TEXTURE_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x9009" name="GL_TEXTURE_CUBE_MAP_ARRAY_OES"/>
+        <enum value="0x900A" name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"/>
+        <enum value="0x900A" name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB"/>
+        <enum value="0x900A" name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x900A" name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES"/>
+        <enum value="0x900B" name="GL_PROXY_TEXTURE_CUBE_MAP_ARRAY"/>
+        <enum value="0x900B" name="GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB"/>
+        <enum value="0x900C" name="GL_SAMPLER_CUBE_MAP_ARRAY"/>
+        <enum value="0x900C" name="GL_SAMPLER_CUBE_MAP_ARRAY_ARB"/>
+        <enum value="0x900C" name="GL_SAMPLER_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x900C" name="GL_SAMPLER_CUBE_MAP_ARRAY_OES"/>
+        <enum value="0x900D" name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW"/>
+        <enum value="0x900D" name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB"/>
+        <enum value="0x900D" name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT"/>
+        <enum value="0x900D" name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES"/>
+        <enum value="0x900E" name="GL_INT_SAMPLER_CUBE_MAP_ARRAY"/>
+        <enum value="0x900E" name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB"/>
+        <enum value="0x900E" name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x900E" name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES"/>
+        <enum value="0x900F" name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY"/>
+        <enum value="0x900F" name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB"/>
+        <enum value="0x900F" name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x900F" name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES"/>
+        <enum value="0x9010" name="GL_ALPHA_SNORM"/>
+        <enum value="0x9011" name="GL_LUMINANCE_SNORM"/>
+        <enum value="0x9012" name="GL_LUMINANCE_ALPHA_SNORM"/>
+        <enum value="0x9013" name="GL_INTENSITY_SNORM"/>
+        <enum value="0x9014" name="GL_ALPHA8_SNORM"/>
+        <enum value="0x9015" name="GL_LUMINANCE8_SNORM"/>
+        <enum value="0x9016" name="GL_LUMINANCE8_ALPHA8_SNORM"/>
+        <enum value="0x9017" name="GL_INTENSITY8_SNORM"/>
+        <enum value="0x9018" name="GL_ALPHA16_SNORM"/>
+        <enum value="0x9019" name="GL_LUMINANCE16_SNORM"/>
+        <enum value="0x901A" name="GL_LUMINANCE16_ALPHA16_SNORM"/>
+        <enum value="0x901B" name="GL_INTENSITY16_SNORM"/>
+        <enum value="0x901C" name="GL_FACTOR_MIN_AMD"/>
+        <enum value="0x901D" name="GL_FACTOR_MAX_AMD"/>
+        <enum value="0x901E" name="GL_DEPTH_CLAMP_NEAR_AMD"/>
+        <enum value="0x901F" name="GL_DEPTH_CLAMP_FAR_AMD"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9020" end="0x90FF" vendor="NV" comment="For Pat Brown, bug 4935">
+        <enum value="0x9020" name="GL_VIDEO_BUFFER_NV"/>
+        <enum value="0x9021" name="GL_VIDEO_BUFFER_BINDING_NV"/>
+        <enum value="0x9022" name="GL_FIELD_UPPER_NV"/>
+        <enum value="0x9023" name="GL_FIELD_LOWER_NV"/>
+        <enum value="0x9024" name="GL_NUM_VIDEO_CAPTURE_STREAMS_NV"/>
+        <enum value="0x9025" name="GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV"/>
+        <enum value="0x9026" name="GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV"/>
+        <enum value="0x9027" name="GL_LAST_VIDEO_CAPTURE_STATUS_NV"/>
+        <enum value="0x9028" name="GL_VIDEO_BUFFER_PITCH_NV"/>
+        <enum value="0x9029" name="GL_VIDEO_COLOR_CONVERSION_MATRIX_NV"/>
+        <enum value="0x902A" name="GL_VIDEO_COLOR_CONVERSION_MAX_NV"/>
+        <enum value="0x902B" name="GL_VIDEO_COLOR_CONVERSION_MIN_NV"/>
+        <enum value="0x902C" name="GL_VIDEO_COLOR_CONVERSION_OFFSET_NV"/>
+        <enum value="0x902D" name="GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV"/>
+        <enum value="0x902E" name="GL_PARTIAL_SUCCESS_NV"/>
+        <enum value="0x902F" name="GL_SUCCESS_NV"/>
+        <enum value="0x9030" name="GL_FAILURE_NV"/>
+        <enum value="0x9031" name="GL_YCBYCR8_422_NV"/>
+        <enum value="0x9032" name="GL_YCBAYCR8A_4224_NV"/>
+        <enum value="0x9033" name="GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV"/>
+        <enum value="0x9034" name="GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV"/>
+        <enum value="0x9035" name="GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV"/>
+        <enum value="0x9036" name="GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV"/>
+        <enum value="0x9037" name="GL_Z4Y12Z4CB12Z4CR12_444_NV"/>
+        <enum value="0x9038" name="GL_VIDEO_CAPTURE_FRAME_WIDTH_NV"/>
+        <enum value="0x9039" name="GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV"/>
+        <enum value="0x903A" name="GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV"/>
+        <enum value="0x903B" name="GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV"/>
+        <enum value="0x903C" name="GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV"/>
+            <unused start="0x903D" end="0x9044" vendor="NV"/>
+        <enum value="0x9045" name="GL_TEXTURE_COVERAGE_SAMPLES_NV"/>
+        <enum value="0x9046" name="GL_TEXTURE_COLOR_SAMPLES_NV"/>
+        <enum value="0x9047" name="GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX"/>
+        <enum value="0x9048" name="GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX"/>
+        <enum value="0x9049" name="GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX"/>
+        <enum value="0x904A" name="GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX"/>
+        <enum value="0x904B" name="GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX"/>
+        <enum value="0x904C" name="GL_IMAGE_1D"/>
+        <enum value="0x904C" name="GL_IMAGE_1D_EXT"/>
+        <enum value="0x904D" name="GL_IMAGE_2D"/>
+        <enum value="0x904D" name="GL_IMAGE_2D_EXT"/>
+        <enum value="0x904E" name="GL_IMAGE_3D"/>
+        <enum value="0x904E" name="GL_IMAGE_3D_EXT"/>
+        <enum value="0x904F" name="GL_IMAGE_2D_RECT"/>
+        <enum value="0x904F" name="GL_IMAGE_2D_RECT_EXT"/>
+        <enum value="0x9050" name="GL_IMAGE_CUBE"/>
+        <enum value="0x9050" name="GL_IMAGE_CUBE_EXT"/>
+        <enum value="0x9051" name="GL_IMAGE_BUFFER"/>
+        <enum value="0x9051" name="GL_IMAGE_BUFFER_EXT"/>
+        <enum value="0x9051" name="GL_IMAGE_BUFFER_OES"/>
+        <enum value="0x9052" name="GL_IMAGE_1D_ARRAY"/>
+        <enum value="0x9052" name="GL_IMAGE_1D_ARRAY_EXT"/>
+        <enum value="0x9053" name="GL_IMAGE_2D_ARRAY"/>
+        <enum value="0x9053" name="GL_IMAGE_2D_ARRAY_EXT"/>
+        <enum value="0x9054" name="GL_IMAGE_CUBE_MAP_ARRAY"/>
+        <enum value="0x9054" name="GL_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x9054" name="GL_IMAGE_CUBE_MAP_ARRAY_OES"/>
+        <enum value="0x9055" name="GL_IMAGE_2D_MULTISAMPLE"/>
+        <enum value="0x9055" name="GL_IMAGE_2D_MULTISAMPLE_EXT"/>
+        <enum value="0x9056" name="GL_IMAGE_2D_MULTISAMPLE_ARRAY"/>
+        <enum value="0x9056" name="GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT"/>
+        <enum value="0x9057" name="GL_INT_IMAGE_1D"/>
+        <enum value="0x9057" name="GL_INT_IMAGE_1D_EXT"/>
+        <enum value="0x9058" name="GL_INT_IMAGE_2D"/>
+        <enum value="0x9058" name="GL_INT_IMAGE_2D_EXT"/>
+        <enum value="0x9059" name="GL_INT_IMAGE_3D"/>
+        <enum value="0x9059" name="GL_INT_IMAGE_3D_EXT"/>
+        <enum value="0x905A" name="GL_INT_IMAGE_2D_RECT"/>
+        <enum value="0x905A" name="GL_INT_IMAGE_2D_RECT_EXT"/>
+        <enum value="0x905B" name="GL_INT_IMAGE_CUBE"/>
+        <enum value="0x905B" name="GL_INT_IMAGE_CUBE_EXT"/>
+        <enum value="0x905C" name="GL_INT_IMAGE_BUFFER"/>
+        <enum value="0x905C" name="GL_INT_IMAGE_BUFFER_EXT"/>
+        <enum value="0x905C" name="GL_INT_IMAGE_BUFFER_OES"/>
+        <enum value="0x905D" name="GL_INT_IMAGE_1D_ARRAY"/>
+        <enum value="0x905D" name="GL_INT_IMAGE_1D_ARRAY_EXT"/>
+        <enum value="0x905E" name="GL_INT_IMAGE_2D_ARRAY"/>
+        <enum value="0x905E" name="GL_INT_IMAGE_2D_ARRAY_EXT"/>
+        <enum value="0x905F" name="GL_INT_IMAGE_CUBE_MAP_ARRAY"/>
+        <enum value="0x905F" name="GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x905F" name="GL_INT_IMAGE_CUBE_MAP_ARRAY_OES"/>
+        <enum value="0x9060" name="GL_INT_IMAGE_2D_MULTISAMPLE"/>
+        <enum value="0x9060" name="GL_INT_IMAGE_2D_MULTISAMPLE_EXT"/>
+        <enum value="0x9061" name="GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY"/>
+        <enum value="0x9061" name="GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT"/>
+        <enum value="0x9062" name="GL_UNSIGNED_INT_IMAGE_1D"/>
+        <enum value="0x9062" name="GL_UNSIGNED_INT_IMAGE_1D_EXT"/>
+        <enum value="0x9063" name="GL_UNSIGNED_INT_IMAGE_2D"/>
+        <enum value="0x9063" name="GL_UNSIGNED_INT_IMAGE_2D_EXT"/>
+        <enum value="0x9064" name="GL_UNSIGNED_INT_IMAGE_3D"/>
+        <enum value="0x9064" name="GL_UNSIGNED_INT_IMAGE_3D_EXT"/>
+        <enum value="0x9065" name="GL_UNSIGNED_INT_IMAGE_2D_RECT"/>
+        <enum value="0x9065" name="GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT"/>
+        <enum value="0x9066" name="GL_UNSIGNED_INT_IMAGE_CUBE"/>
+        <enum value="0x9066" name="GL_UNSIGNED_INT_IMAGE_CUBE_EXT"/>
+        <enum value="0x9067" name="GL_UNSIGNED_INT_IMAGE_BUFFER"/>
+        <enum value="0x9067" name="GL_UNSIGNED_INT_IMAGE_BUFFER_EXT"/>
+        <enum value="0x9067" name="GL_UNSIGNED_INT_IMAGE_BUFFER_OES"/>
+        <enum value="0x9068" name="GL_UNSIGNED_INT_IMAGE_1D_ARRAY"/>
+        <enum value="0x9068" name="GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT"/>
+        <enum value="0x9069" name="GL_UNSIGNED_INT_IMAGE_2D_ARRAY"/>
+        <enum value="0x9069" name="GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT"/>
+        <enum value="0x906A" name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY"/>
+        <enum value="0x906A" name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x906A" name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES"/>
+        <enum value="0x906B" name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE"/>
+        <enum value="0x906B" name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT"/>
+        <enum value="0x906C" name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY"/>
+        <enum value="0x906C" name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT"/>
+        <enum value="0x906D" name="GL_MAX_IMAGE_SAMPLES"/>
+        <enum value="0x906D" name="GL_MAX_IMAGE_SAMPLES_EXT"/>
+        <enum value="0x906E" name="GL_IMAGE_BINDING_FORMAT"/>
+        <enum value="0x906E" name="GL_IMAGE_BINDING_FORMAT_EXT"/>
+        <enum value="0x906F" name="GL_RGB10_A2UI"/>
+        <enum value="0x9070" name="GL_PATH_FORMAT_SVG_NV"/>
+        <enum value="0x9071" name="GL_PATH_FORMAT_PS_NV"/>
+        <enum value="0x9072" name="GL_STANDARD_FONT_NAME_NV"/>
+        <enum value="0x9073" name="GL_SYSTEM_FONT_NAME_NV"/>
+        <enum value="0x9074" name="GL_FILE_NAME_NV"/>
+        <enum value="0x9075" name="GL_PATH_STROKE_WIDTH_NV"/>
+        <enum value="0x9076" name="GL_PATH_END_CAPS_NV"/>
+        <enum value="0x9077" name="GL_PATH_INITIAL_END_CAP_NV"/>
+        <enum value="0x9078" name="GL_PATH_TERMINAL_END_CAP_NV"/>
+        <enum value="0x9079" name="GL_PATH_JOIN_STYLE_NV"/>
+        <enum value="0x907A" name="GL_PATH_MITER_LIMIT_NV"/>
+        <enum value="0x907B" name="GL_PATH_DASH_CAPS_NV"/>
+        <enum value="0x907C" name="GL_PATH_INITIAL_DASH_CAP_NV"/>
+        <enum value="0x907D" name="GL_PATH_TERMINAL_DASH_CAP_NV"/>
+        <enum value="0x907E" name="GL_PATH_DASH_OFFSET_NV"/>
+        <enum value="0x907F" name="GL_PATH_CLIENT_LENGTH_NV"/>
+        <enum value="0x9080" name="GL_PATH_FILL_MODE_NV"/>
+        <enum value="0x9081" name="GL_PATH_FILL_MASK_NV"/>
+        <enum value="0x9082" name="GL_PATH_FILL_COVER_MODE_NV"/>
+        <enum value="0x9083" name="GL_PATH_STROKE_COVER_MODE_NV"/>
+        <enum value="0x9084" name="GL_PATH_STROKE_MASK_NV"/>
+            <!-- <enum value="0x9085" name="GL_PATH_SAMPLE_QUALITY_NV"          comment="Removed from extension"/> -->
+            <!-- <enum value="0x9086" name="GL_PATH_STROKE_BOUND_NV"            comment="Removed from extension"/> -->
+            <!-- <enum value="0x9087" name="GL_PATH_STROKE_OVERSAMPLE_COUNT_NV" comment="Removed from extension"/> -->
+        <enum value="0x9088" name="GL_COUNT_UP_NV"/>
+        <enum value="0x9089" name="GL_COUNT_DOWN_NV"/>
+        <enum value="0x908A" name="GL_PATH_OBJECT_BOUNDING_BOX_NV"/>
+        <enum value="0x908B" name="GL_CONVEX_HULL_NV"/>
+            <!-- <enum value="0x908C" name="GL_MULTI_HULLS_NV"                  comment="Removed from extension"/> -->
+        <enum value="0x908D" name="GL_BOUNDING_BOX_NV"/>
+        <enum value="0x908E" name="GL_TRANSLATE_X_NV"/>
+        <enum value="0x908F" name="GL_TRANSLATE_Y_NV"/>
+        <enum value="0x9090" name="GL_TRANSLATE_2D_NV"/>
+        <enum value="0x9091" name="GL_TRANSLATE_3D_NV"/>
+        <enum value="0x9092" name="GL_AFFINE_2D_NV"/>
+            <!-- <enum value="0x9093" name="GL_PROJECTIVE_2D_NV"                comment="Removed from extension"/> -->
+        <enum value="0x9094" name="GL_AFFINE_3D_NV"/>
+            <!-- <enum value="0x9095" name="GL_PROJECTIVE_3D_NV"                comment="Removed from extension"/> -->
+        <enum value="0x9096" name="GL_TRANSPOSE_AFFINE_2D_NV"/>
+            <!-- <enum value="0x9097" name="GL_TRANSPOSE_PROJECTIVE_2D_NV"      comment="Removed from extension"/> -->
+        <enum value="0x9098" name="GL_TRANSPOSE_AFFINE_3D_NV"/>
+            <!-- <enum value="0x9099" name="GL_TRANSPOSE_PROJECTIVE_3D_NV"      comment="Removed from extension"/> -->
+        <enum value="0x909A" name="GL_UTF8_NV"/>
+        <enum value="0x909B" name="GL_UTF16_NV"/>
+        <enum value="0x909C" name="GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV"/>
+        <enum value="0x909D" name="GL_PATH_COMMAND_COUNT_NV"/>
+        <enum value="0x909E" name="GL_PATH_COORD_COUNT_NV"/>
+        <enum value="0x909F" name="GL_PATH_DASH_ARRAY_COUNT_NV"/>
+        <enum value="0x90A0" name="GL_PATH_COMPUTED_LENGTH_NV"/>
+        <enum value="0x90A1" name="GL_PATH_FILL_BOUNDING_BOX_NV"/>
+        <enum value="0x90A2" name="GL_PATH_STROKE_BOUNDING_BOX_NV"/>
+        <enum value="0x90A3" name="GL_SQUARE_NV"/>
+        <enum value="0x90A4" name="GL_ROUND_NV"/>
+        <enum value="0x90A5" name="GL_TRIANGULAR_NV"/>
+        <enum value="0x90A6" name="GL_BEVEL_NV"/>
+        <enum value="0x90A7" name="GL_MITER_REVERT_NV"/>
+        <enum value="0x90A8" name="GL_MITER_TRUNCATE_NV"/>
+        <enum value="0x90A9" name="GL_SKIP_MISSING_GLYPH_NV"/>
+        <enum value="0x90AA" name="GL_USE_MISSING_GLYPH_NV"/>
+        <enum value="0x90AB" name="GL_PATH_ERROR_POSITION_NV"/>
+        <enum value="0x90AC" name="GL_PATH_FOG_GEN_MODE_NV"/>
+        <enum value="0x90AD" name="GL_ACCUM_ADJACENT_PAIRS_NV"/>
+        <enum value="0x90AE" name="GL_ADJACENT_PAIRS_NV"/>
+        <enum value="0x90AF" name="GL_FIRST_TO_REST_NV"/>
+        <enum value="0x90B0" name="GL_PATH_GEN_MODE_NV"/>
+        <enum value="0x90B1" name="GL_PATH_GEN_COEFF_NV"/>
+        <enum value="0x90B2" name="GL_PATH_GEN_COLOR_FORMAT_NV"/>
+        <enum value="0x90B3" name="GL_PATH_GEN_COMPONENTS_NV"/>
+        <enum value="0x90B4" name="GL_PATH_DASH_OFFSET_RESET_NV"/>
+        <enum value="0x90B5" name="GL_MOVE_TO_RESETS_NV"/>
+        <enum value="0x90B6" name="GL_MOVE_TO_CONTINUES_NV"/>
+        <enum value="0x90B7" name="GL_PATH_STENCIL_FUNC_NV"/>
+        <enum value="0x90B8" name="GL_PATH_STENCIL_REF_NV"/>
+        <enum value="0x90B9" name="GL_PATH_STENCIL_VALUE_MASK_NV"/>
+        <enum value="0x90BA" name="GL_SCALED_RESOLVE_FASTEST_EXT"/>
+        <enum value="0x90BB" name="GL_SCALED_RESOLVE_NICEST_EXT"/>
+        <enum value="0x90BC" name="GL_MIN_MAP_BUFFER_ALIGNMENT"/>
+        <enum value="0x90BD" name="GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV"/>
+        <enum value="0x90BE" name="GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV"/>
+        <enum value="0x90BF" name="GL_PATH_COVER_DEPTH_FUNC_NV"/>
+            <unused start="0x90C0" end="0x90C6" vendor="NV"/>
+        <enum value="0x90C7" name="GL_IMAGE_FORMAT_COMPATIBILITY_TYPE"/>
+        <enum value="0x90C8" name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE"/>
+        <enum value="0x90C9" name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS"/>
+        <enum value="0x90CA" name="GL_MAX_VERTEX_IMAGE_UNIFORMS"/>
+        <enum value="0x90CB" name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS"/>
+        <enum value="0x90CB" name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT"/>
+        <enum value="0x90CB" name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES"/>
+        <enum value="0x90CC" name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS"/>
+        <enum value="0x90CC" name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT"/>
+        <enum value="0x90CC" name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES"/>
+        <enum value="0x90CD" name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS"/>
+        <enum value="0x90CD" name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT"/>
+        <enum value="0x90CD" name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES"/>
+        <enum value="0x90CE" name="GL_MAX_FRAGMENT_IMAGE_UNIFORMS"/>
+        <enum value="0x90CF" name="GL_MAX_COMBINED_IMAGE_UNIFORMS"/>
+        <enum value="0x90D0" name="GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV"/>
+        <enum value="0x90D1" name="GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV"/>
+        <enum value="0x90D2" name="GL_SHADER_STORAGE_BUFFER"/>
+        <enum value="0x90D3" name="GL_SHADER_STORAGE_BUFFER_BINDING"/>
+        <enum value="0x90D4" name="GL_SHADER_STORAGE_BUFFER_START"/>
+        <enum value="0x90D5" name="GL_SHADER_STORAGE_BUFFER_SIZE"/>
+        <enum value="0x90D6" name="GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS"/>
+        <enum value="0x90D7" name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS"/>
+        <enum value="0x90D7" name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT"/>
+        <enum value="0x90D7" name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES"/>
+        <enum value="0x90D8" name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS"/>
+        <enum value="0x90D8" name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT"/>
+        <enum value="0x90D8" name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES"/>
+        <enum value="0x90D9" name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS"/>
+        <enum value="0x90D9" name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT"/>
+        <enum value="0x90D9" name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES"/>
+        <enum value="0x90DA" name="GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS"/>
+        <enum value="0x90DB" name="GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"/>
+        <enum value="0x90DC" name="GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS"/>
+        <enum value="0x90DD" name="GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS"/>
+        <enum value="0x90DE" name="GL_MAX_SHADER_STORAGE_BLOCK_SIZE"/>
+        <enum value="0x90DF" name="GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT"/>
+            <unused start="0x90E0" vendor="NV"/>
+        <enum value="0x90E1" name="GL_SYNC_X11_FENCE_EXT"/>
+            <unused start="0x90E2" end="0x90E9" vendor="NV"/>
+        <enum value="0x90EA" name="GL_DEPTH_STENCIL_TEXTURE_MODE"/>
+        <enum value="0x90EB" name="GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS"/>
+        <enum value="0x90EB" name="GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB" alias="GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS"/>
+        <enum value="0x90EC" name="GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER"/>
+        <enum value="0x90ED" name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER"/>
+        <enum value="0x90EE" name="GL_DISPATCH_INDIRECT_BUFFER"/>
+        <enum value="0x90EF" name="GL_DISPATCH_INDIRECT_BUFFER_BINDING"/>
+        <enum value="0x90F0" name="GL_COLOR_ATTACHMENT_EXT"/>
+        <enum value="0x90F1" name="GL_MULTIVIEW_EXT"/>
+        <enum value="0x90F2" name="GL_MAX_MULTIVIEW_BUFFERS_EXT"/>
+        <enum value="0x90F3" name="GL_CONTEXT_ROBUST_ACCESS"/>
+        <enum value="0x90F3" name="GL_CONTEXT_ROBUST_ACCESS_EXT"/>
+        <enum value="0x90F3" name="GL_CONTEXT_ROBUST_ACCESS_KHR"/>
+            <unused start="0x90F4" end="0x90FA" vendor="NV"/>
+        <enum value="0x90FB" name="GL_COMPUTE_PROGRAM_NV"/>
+        <enum value="0x90FC" name="GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV"/>
+            <unused start="0x90FD" end="0x90FF" vendor="NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9100" end="0x912F" vendor="ARB">
+        <enum value="0x9100" name="GL_TEXTURE_2D_MULTISAMPLE"/>
+        <enum value="0x9101" name="GL_PROXY_TEXTURE_2D_MULTISAMPLE"/>
+        <enum value="0x9102" name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+        <enum value="0x9102" name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES"/>
+        <enum value="0x9103" name="GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+        <enum value="0x9104" name="GL_TEXTURE_BINDING_2D_MULTISAMPLE"/>
+        <enum value="0x9105" name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"/>
+        <enum value="0x9105" name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES"/>
+        <enum value="0x9106" name="GL_TEXTURE_SAMPLES"/>
+        <enum value="0x9107" name="GL_TEXTURE_FIXED_SAMPLE_LOCATIONS"/>
+        <enum value="0x9108" name="GL_SAMPLER_2D_MULTISAMPLE"/>
+        <enum value="0x9109" name="GL_INT_SAMPLER_2D_MULTISAMPLE"/>
+        <enum value="0x910A" name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE"/>
+        <enum value="0x910B" name="GL_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+        <enum value="0x910B" name="GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES"/>
+        <enum value="0x910C" name="GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+        <enum value="0x910C" name="GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES"/>
+        <enum value="0x910D" name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+        <enum value="0x910D" name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES"/>
+        <enum value="0x910E" name="GL_MAX_COLOR_TEXTURE_SAMPLES"/>
+        <enum value="0x910F" name="GL_MAX_DEPTH_TEXTURE_SAMPLES"/>
+        <enum value="0x9110" name="GL_MAX_INTEGER_SAMPLES"/>
+        <enum value="0x9111" name="GL_MAX_SERVER_WAIT_TIMEOUT"/>
+        <enum value="0x9111" name="GL_MAX_SERVER_WAIT_TIMEOUT_APPLE"/>
+        <enum value="0x9112" name="GL_OBJECT_TYPE"/>
+        <enum value="0x9112" name="GL_OBJECT_TYPE_APPLE"/>
+        <enum value="0x9113" name="GL_SYNC_CONDITION"/>
+        <enum value="0x9113" name="GL_SYNC_CONDITION_APPLE"/>
+        <enum value="0x9114" name="GL_SYNC_STATUS"/>
+        <enum value="0x9114" name="GL_SYNC_STATUS_APPLE"/>
+        <enum value="0x9115" name="GL_SYNC_FLAGS"/>
+        <enum value="0x9115" name="GL_SYNC_FLAGS_APPLE"/>
+        <enum value="0x9116" name="GL_SYNC_FENCE"/>
+        <enum value="0x9116" name="GL_SYNC_FENCE_APPLE"/>
+        <enum value="0x9117" name="GL_SYNC_GPU_COMMANDS_COMPLETE"/>
+        <enum value="0x9117" name="GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE"/>
+        <enum value="0x9118" name="GL_UNSIGNALED"/>
+        <enum value="0x9118" name="GL_UNSIGNALED_APPLE"/>
+        <enum value="0x9119" name="GL_SIGNALED"/>
+        <enum value="0x9119" name="GL_SIGNALED_APPLE"/>
+        <enum value="0x911A" name="GL_ALREADY_SIGNALED"/>
+        <enum value="0x911A" name="GL_ALREADY_SIGNALED_APPLE"/>
+        <enum value="0x911B" name="GL_TIMEOUT_EXPIRED"/>
+        <enum value="0x911B" name="GL_TIMEOUT_EXPIRED_APPLE"/>
+        <enum value="0x911C" name="GL_CONDITION_SATISFIED"/>
+        <enum value="0x911C" name="GL_CONDITION_SATISFIED_APPLE"/>
+        <enum value="0x911D" name="GL_WAIT_FAILED"/>
+        <enum value="0x911D" name="GL_WAIT_FAILED_APPLE"/>
+        <enum value="0x911F" name="GL_BUFFER_ACCESS_FLAGS"/>
+        <enum value="0x9120" name="GL_BUFFER_MAP_LENGTH"/>
+        <enum value="0x9121" name="GL_BUFFER_MAP_OFFSET"/>
+        <enum value="0x9122" name="GL_MAX_VERTEX_OUTPUT_COMPONENTS"/>
+        <enum value="0x9123" name="GL_MAX_GEOMETRY_INPUT_COMPONENTS"/>
+        <enum value="0x9123" name="GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT"/>
+        <enum value="0x9123" name="GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES"/>
+        <enum value="0x9124" name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS"/>
+        <enum value="0x9124" name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x9124" name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES"/>
+        <enum value="0x9125" name="GL_MAX_FRAGMENT_INPUT_COMPONENTS"/>
+        <enum value="0x9126" name="GL_CONTEXT_PROFILE_MASK"/>
+        <enum value="0x9127" name="GL_UNPACK_COMPRESSED_BLOCK_WIDTH"/>
+        <enum value="0x9128" name="GL_UNPACK_COMPRESSED_BLOCK_HEIGHT"/>
+        <enum value="0x9129" name="GL_UNPACK_COMPRESSED_BLOCK_DEPTH"/>
+        <enum value="0x912A" name="GL_UNPACK_COMPRESSED_BLOCK_SIZE"/>
+        <enum value="0x912B" name="GL_PACK_COMPRESSED_BLOCK_WIDTH"/>
+        <enum value="0x912C" name="GL_PACK_COMPRESSED_BLOCK_HEIGHT"/>
+        <enum value="0x912D" name="GL_PACK_COMPRESSED_BLOCK_DEPTH"/>
+        <enum value="0x912E" name="GL_PACK_COMPRESSED_BLOCK_SIZE"/>
+        <enum value="0x912F" name="GL_TEXTURE_IMMUTABLE_FORMAT"/>
+        <enum value="0x912F" name="GL_TEXTURE_IMMUTABLE_FORMAT_EXT"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9130" end="0x913F" vendor="IMG" comment="Khronos bug 882">
+        <enum value="0x9130" name="GL_SGX_PROGRAM_BINARY_IMG"/>
+            <unused start="0x9131" end="0x9132" vendor="IMG"/>
+        <enum value="0x9133" name="GL_RENDERBUFFER_SAMPLES_IMG"/>
+        <enum value="0x9134" name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG"/>
+        <enum value="0x9135" name="GL_MAX_SAMPLES_IMG"/>
+        <enum value="0x9136" name="GL_TEXTURE_SAMPLES_IMG"/>
+        <enum value="0x9137" name="GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG"/>
+        <enum value="0x9138" name="GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG"/>
+        <enum value="0x9139" name="GL_CUBIC_IMG"/>
+        <enum value="0x913A" name="GL_CUBIC_MIPMAP_NEAREST_IMG"/>
+        <enum value="0x913B" name="GL_CUBIC_MIPMAP_LINEAR_IMG"/>
+        <enum value="0x913C" name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG"/>
+        <enum value="0x913D" name="GL_NUM_DOWNSAMPLE_SCALES_IMG"/>
+        <enum value="0x913E" name="GL_DOWNSAMPLE_SCALES_IMG"/>
+        <enum value="0x913F" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9140" end="0x923F" vendor="AMD" comment="Khronos bugs 5899, 6004">
+            <unused start="0x9140" end="0x9142" vendor="AMD"/>
+        <enum value="0x9143" name="GL_MAX_DEBUG_MESSAGE_LENGTH"/>
+        <enum value="0x9143" name="GL_MAX_DEBUG_MESSAGE_LENGTH_AMD"/>
+        <enum value="0x9143" name="GL_MAX_DEBUG_MESSAGE_LENGTH_ARB"/>
+        <enum value="0x9143" name="GL_MAX_DEBUG_MESSAGE_LENGTH_KHR"/>
+        <enum value="0x9144" name="GL_MAX_DEBUG_LOGGED_MESSAGES"/>
+        <enum value="0x9144" name="GL_MAX_DEBUG_LOGGED_MESSAGES_AMD"/>
+        <enum value="0x9144" name="GL_MAX_DEBUG_LOGGED_MESSAGES_ARB"/>
+        <enum value="0x9144" name="GL_MAX_DEBUG_LOGGED_MESSAGES_KHR"/>
+        <enum value="0x9145" name="GL_DEBUG_LOGGED_MESSAGES"/>
+        <enum value="0x9145" name="GL_DEBUG_LOGGED_MESSAGES_AMD"/>
+        <enum value="0x9145" name="GL_DEBUG_LOGGED_MESSAGES_ARB"/>
+        <enum value="0x9145" name="GL_DEBUG_LOGGED_MESSAGES_KHR"/>
+        <enum value="0x9146" name="GL_DEBUG_SEVERITY_HIGH"/>
+        <enum value="0x9146" name="GL_DEBUG_SEVERITY_HIGH_AMD"/>
+        <enum value="0x9146" name="GL_DEBUG_SEVERITY_HIGH_ARB"/>
+        <enum value="0x9146" name="GL_DEBUG_SEVERITY_HIGH_KHR"/>
+        <enum value="0x9147" name="GL_DEBUG_SEVERITY_MEDIUM"/>
+        <enum value="0x9147" name="GL_DEBUG_SEVERITY_MEDIUM_AMD"/>
+        <enum value="0x9147" name="GL_DEBUG_SEVERITY_MEDIUM_ARB"/>
+        <enum value="0x9147" name="GL_DEBUG_SEVERITY_MEDIUM_KHR"/>
+        <enum value="0x9148" name="GL_DEBUG_SEVERITY_LOW"/>
+        <enum value="0x9148" name="GL_DEBUG_SEVERITY_LOW_AMD"/>
+        <enum value="0x9148" name="GL_DEBUG_SEVERITY_LOW_ARB"/>
+        <enum value="0x9148" name="GL_DEBUG_SEVERITY_LOW_KHR"/>
+        <enum value="0x9149" name="GL_DEBUG_CATEGORY_API_ERROR_AMD"/>
+        <enum value="0x914A" name="GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD"/>
+        <enum value="0x914B" name="GL_DEBUG_CATEGORY_DEPRECATION_AMD"/>
+        <enum value="0x914C" name="GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD"/>
+        <enum value="0x914D" name="GL_DEBUG_CATEGORY_PERFORMANCE_AMD"/>
+        <enum value="0x914E" name="GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD"/>
+        <enum value="0x914F" name="GL_DEBUG_CATEGORY_APPLICATION_AMD"/>
+        <enum value="0x9150" name="GL_DEBUG_CATEGORY_OTHER_AMD"/>
+        <enum value="0x9151" name="GL_BUFFER_OBJECT_EXT"/>
+        <enum value="0x9151" name="GL_DATA_BUFFER_AMD"/>
+        <enum value="0x9152" name="GL_PERFORMANCE_MONITOR_AMD"/>
+        <enum value="0x9153" name="GL_QUERY_OBJECT_AMD"/>
+        <enum value="0x9153" name="GL_QUERY_OBJECT_EXT"/>
+        <enum value="0x9154" name="GL_VERTEX_ARRAY_OBJECT_AMD"/>
+        <enum value="0x9154" name="GL_VERTEX_ARRAY_OBJECT_EXT"/>
+        <enum value="0x9155" name="GL_SAMPLER_OBJECT_AMD"/>
+            <unused start="0x9156" end="0x915F" vendor="AMD"/>
+        <enum value="0x9160" name="GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD"/>
+            <unused start="0x9161" vendor="AMD"/>
+        <enum value="0x9192" name="GL_QUERY_BUFFER"/>
+        <enum value="0x9192" name="GL_QUERY_BUFFER_AMD"/>
+        <enum value="0x9193" name="GL_QUERY_BUFFER_BINDING"/>
+        <enum value="0x9193" name="GL_QUERY_BUFFER_BINDING_AMD"/>
+        <enum value="0x9194" name="GL_QUERY_RESULT_NO_WAIT"/>
+        <enum value="0x9194" name="GL_QUERY_RESULT_NO_WAIT_AMD"/>
+        <enum value="0x9195" name="GL_VIRTUAL_PAGE_SIZE_X_ARB"/>
+        <enum value="0x9195" name="GL_VIRTUAL_PAGE_SIZE_X_EXT"/>
+        <enum value="0x9195" name="GL_VIRTUAL_PAGE_SIZE_X_AMD"/>
+        <enum value="0x9196" name="GL_VIRTUAL_PAGE_SIZE_Y_ARB"/>
+        <enum value="0x9196" name="GL_VIRTUAL_PAGE_SIZE_Y_EXT"/>
+        <enum value="0x9196" name="GL_VIRTUAL_PAGE_SIZE_Y_AMD"/>
+        <enum value="0x9197" name="GL_VIRTUAL_PAGE_SIZE_Z_ARB"/>
+        <enum value="0x9197" name="GL_VIRTUAL_PAGE_SIZE_Z_EXT"/>
+        <enum value="0x9197" name="GL_VIRTUAL_PAGE_SIZE_Z_AMD"/>
+        <enum value="0x9198" name="GL_MAX_SPARSE_TEXTURE_SIZE_ARB"/>
+        <enum value="0x9198" name="GL_MAX_SPARSE_TEXTURE_SIZE_EXT"/>
+        <enum value="0x9198" name="GL_MAX_SPARSE_TEXTURE_SIZE_AMD"/>
+        <enum value="0x9199" name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB"/>
+        <enum value="0x9199" name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT"/>
+        <enum value="0x9199" name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD"/>
+        <enum value="0x919A" name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS"/>
+        <enum value="0x919A" name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB"/>
+        <enum value="0x919A" name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT"/>
+        <enum value="0x919B" name="GL_MIN_SPARSE_LEVEL_AMD"/>
+        <enum value="0x919C" name="GL_MIN_LOD_WARNING_AMD"/>
+        <enum value="0x919D" name="GL_TEXTURE_BUFFER_OFFSET"/>
+        <enum value="0x919D" name="GL_TEXTURE_BUFFER_OFFSET_EXT"/>
+        <enum value="0x919D" name="GL_TEXTURE_BUFFER_OFFSET_OES"/>
+        <enum value="0x919E" name="GL_TEXTURE_BUFFER_SIZE"/>
+        <enum value="0x919E" name="GL_TEXTURE_BUFFER_SIZE_EXT"/>
+        <enum value="0x919E" name="GL_TEXTURE_BUFFER_SIZE_OES"/>
+        <enum value="0x919F" name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT"/>
+        <enum value="0x919F" name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT"/>
+        <enum value="0x919F" name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES"/>
+        <enum value="0x91A0" name="GL_STREAM_RASTERIZATION_AMD"/>
+            <unused start="0x91A1" end="0x91A3" vendor="AMD"/>
+        <enum value="0x91A4" name="GL_VERTEX_ELEMENT_SWIZZLE_AMD"/>
+        <enum value="0x91A5" name="GL_VERTEX_ID_SWIZZLE_AMD"/>
+        <enum value="0x91A6" name="GL_TEXTURE_SPARSE_ARB"/>
+        <enum value="0x91A6" name="GL_TEXTURE_SPARSE_EXT"/>
+        <enum value="0x91A7" name="GL_VIRTUAL_PAGE_SIZE_INDEX_ARB"/>
+        <enum value="0x91A7" name="GL_VIRTUAL_PAGE_SIZE_INDEX_EXT"/>
+        <enum value="0x91A8" name="GL_NUM_VIRTUAL_PAGE_SIZES_ARB"/>
+        <enum value="0x91A8" name="GL_NUM_VIRTUAL_PAGE_SIZES_EXT"/>
+        <enum value="0x91A9" name="GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB"/>
+        <enum value="0x91A9" name="GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT"/>
+        <enum value="0x91AA" name="GL_NUM_SPARSE_LEVELS_ARB"/>
+        <enum value="0x91AA" name="GL_NUM_SPARSE_LEVELS_EXT"/>
+            <unused start="0x91AB" end="0x91AD" vendor="AMD"/>
+        <enum value="0x91AE" name="GL_PIXELS_PER_SAMPLE_PATTERN_X_AMD"/>
+        <enum value="0x91AF" name="GL_PIXELS_PER_SAMPLE_PATTERN_Y_AMD"/>
+        <enum value="0x91B0" name="GL_MAX_SHADER_COMPILER_THREADS_ARB"/>
+        <enum value="0x91B1" name="GL_COMPLETION_STATUS_ARB"/>
+            <unused start="0x91B2" end="0x91B8" vendor="AMD"/>
+        <enum value="0x91B9" name="GL_COMPUTE_SHADER"/>
+            <unused start="0x91BA" vendor="AMD"/>
+        <enum value="0x91BB" name="GL_MAX_COMPUTE_UNIFORM_BLOCKS"/>
+        <enum value="0x91BC" name="GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"/>
+        <enum value="0x91BD" name="GL_MAX_COMPUTE_IMAGE_UNIFORMS"/>
+        <enum value="0x91BE" name="GL_MAX_COMPUTE_WORK_GROUP_COUNT"/>
+        <enum value="0x91BF" name="GL_MAX_COMPUTE_WORK_GROUP_SIZE"/>
+        <enum value="0x91BF" name="GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB" alias="GL_MAX_COMPUTE_WORK_GROUP_SIZE"/>
+            <unused start="0x91C0" end="0x91C4" vendor="AMD"/>
+        <enum value="0x91C5" name="GL_FLOAT16_MAT2_AMD"/>
+        <enum value="0x91C6" name="GL_FLOAT16_MAT3_AMD"/>
+        <enum value="0x91C7" name="GL_FLOAT16_MAT4_AMD"/>
+        <enum value="0x91C8" name="GL_FLOAT16_MAT2x3_AMD"/>
+        <enum value="0x91C9" name="GL_FLOAT16_MAT2x4_AMD"/>
+        <enum value="0x91CA" name="GL_FLOAT16_MAT3x2_AMD"/>
+        <enum value="0x91CB" name="GL_FLOAT16_MAT3x4_AMD"/>
+        <enum value="0x91CC" name="GL_FLOAT16_MAT4x2_AMD"/>
+        <enum value="0x91CD" name="GL_FLOAT16_MAT4x3_AMD"/>
+            <unused start="0x91CE" end="0x923F" vendor="AMD"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9240" end="0x924F" vendor="WEBGL" comment="Khronos bug 6473,6884">
+        <enum value="0x9240" name="GL_UNPACK_FLIP_Y_WEBGL"/>
+        <enum value="0x9241" name="GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL"/>
+        <enum value="0x9242" name="GL_CONTEXT_LOST_WEBGL"/>
+        <enum value="0x9243" name="GL_UNPACK_COLORSPACE_CONVERSION_WEBGL"/>
+        <enum value="0x9244" name="GL_BROWSER_DEFAULT_WEBGL"/>
+            <unused start="0x9245" end="0x924F" vendor="WEBGL"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9250" end="0x925F" vendor="DMP" comment="For Eisaku Ohbuchi via email">
+        <enum value="0x9250" name="GL_SHADER_BINARY_DMP"/>
+        <enum value="0x9251" name="GL_SMAPHS30_PROGRAM_BINARY_DMP"/>
+        <enum value="0x9252" name="GL_SMAPHS_PROGRAM_BINARY_DMP"/>
+        <enum value="0x9253" name="GL_DMP_PROGRAM_BINARY_DMP"/>
+            <unused start="0x9254" end="0x925F" vendor="DMP"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9260" end="0x926F" vendor="FJ" comment="Khronos bug 7486">
+        <enum value="0x9260" name="GL_GCCSO_SHADER_BINARY_FJ"/>
+            <unused start="0x9261" end="0x926F" vendor="FJ"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9270" end="0x927F" vendor="OES" comment="Khronos bug 7625">
+        <enum value="0x9270" name="GL_COMPRESSED_R11_EAC"/>
+        <enum value="0x9270" name="GL_COMPRESSED_R11_EAC_OES"/>
+        <enum value="0x9271" name="GL_COMPRESSED_SIGNED_R11_EAC"/>
+        <enum value="0x9271" name="GL_COMPRESSED_SIGNED_R11_EAC_OES"/>
+        <enum value="0x9272" name="GL_COMPRESSED_RG11_EAC"/>
+        <enum value="0x9272" name="GL_COMPRESSED_RG11_EAC_OES"/>
+        <enum value="0x9273" name="GL_COMPRESSED_SIGNED_RG11_EAC"/>
+        <enum value="0x9273" name="GL_COMPRESSED_SIGNED_RG11_EAC_OES"/>
+        <enum value="0x9274" name="GL_COMPRESSED_RGB8_ETC2"/>
+        <enum value="0x9274" name="GL_COMPRESSED_RGB8_ETC2_OES"/>
+        <enum value="0x9275" name="GL_COMPRESSED_SRGB8_ETC2"/>
+        <enum value="0x9275" name="GL_COMPRESSED_SRGB8_ETC2_OES"/>
+        <enum value="0x9276" name="GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"/>
+        <enum value="0x9276" name="GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_OES"/>
+        <enum value="0x9277" name="GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"/>
+        <enum value="0x9277" name="GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_OES"/>
+        <enum value="0x9278" name="GL_COMPRESSED_RGBA8_ETC2_EAC"/>
+        <enum value="0x9278" name="GL_COMPRESSED_RGBA8_ETC2_EAC_OES"/>
+        <enum value="0x9279" name="GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"/>
+        <enum value="0x9279" name="GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_OES"/>
+            <unused start="0x927A" end="0x927F" vendor="OES"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9280" end="0x937F" vendor="NV" comment="Khronos bug 7658">
+        <enum value="0x9280" name="GL_BLEND_PREMULTIPLIED_SRC_NV"/>
+        <enum value="0x9281" name="GL_BLEND_OVERLAP_NV"/>
+        <enum value="0x9282" name="GL_UNCORRELATED_NV"/>
+        <enum value="0x9283" name="GL_DISJOINT_NV"/>
+        <enum value="0x9284" name="GL_CONJOINT_NV"/>
+        <enum value="0x9285" name="GL_BLEND_ADVANCED_COHERENT_KHR"/>
+        <enum value="0x9285" name="GL_BLEND_ADVANCED_COHERENT_NV"/>
+        <enum value="0x9286" name="GL_SRC_NV"/>
+        <enum value="0x9287" name="GL_DST_NV"/>
+        <enum value="0x9288" name="GL_SRC_OVER_NV"/>
+        <enum value="0x9289" name="GL_DST_OVER_NV"/>
+        <enum value="0x928A" name="GL_SRC_IN_NV"/>
+        <enum value="0x928B" name="GL_DST_IN_NV"/>
+        <enum value="0x928C" name="GL_SRC_OUT_NV"/>
+        <enum value="0x928D" name="GL_DST_OUT_NV"/>
+        <enum value="0x928E" name="GL_SRC_ATOP_NV"/>
+        <enum value="0x928F" name="GL_DST_ATOP_NV"/>
+            <unused start="0x9290" vendor="NV"/>
+        <enum value="0x9291" name="GL_PLUS_NV"/>
+        <enum value="0x9292" name="GL_PLUS_DARKER_NV"/>
+            <unused start="0x9293" vendor="NV"/>
+        <enum value="0x9294" name="GL_MULTIPLY"/>
+        <enum value="0x9294" name="GL_MULTIPLY_KHR"/>
+        <enum value="0x9294" name="GL_MULTIPLY_NV"/>
+        <enum value="0x9295" name="GL_SCREEN"/>
+        <enum value="0x9295" name="GL_SCREEN_KHR"/>
+        <enum value="0x9295" name="GL_SCREEN_NV"/>
+        <enum value="0x9296" name="GL_OVERLAY"/>
+        <enum value="0x9296" name="GL_OVERLAY_KHR"/>
+        <enum value="0x9296" name="GL_OVERLAY_NV"/>
+        <enum value="0x9297" name="GL_DARKEN"/>
+        <enum value="0x9297" name="GL_DARKEN_KHR"/>
+        <enum value="0x9297" name="GL_DARKEN_NV"/>
+        <enum value="0x9298" name="GL_LIGHTEN"/>
+        <enum value="0x9298" name="GL_LIGHTEN_KHR"/>
+        <enum value="0x9298" name="GL_LIGHTEN_NV"/>
+        <enum value="0x9299" name="GL_COLORDODGE"/>
+        <enum value="0x9299" name="GL_COLORDODGE_KHR"/>
+        <enum value="0x9299" name="GL_COLORDODGE_NV"/>
+        <enum value="0x929A" name="GL_COLORBURN"/>
+        <enum value="0x929A" name="GL_COLORBURN_KHR"/>
+        <enum value="0x929A" name="GL_COLORBURN_NV"/>
+        <enum value="0x929B" name="GL_HARDLIGHT"/>
+        <enum value="0x929B" name="GL_HARDLIGHT_KHR"/>
+        <enum value="0x929B" name="GL_HARDLIGHT_NV"/>
+        <enum value="0x929C" name="GL_SOFTLIGHT"/>
+        <enum value="0x929C" name="GL_SOFTLIGHT_KHR"/>
+        <enum value="0x929C" name="GL_SOFTLIGHT_NV"/>
+            <unused start="0x929D" vendor="NV"/>
+        <enum value="0x929E" name="GL_DIFFERENCE"/>
+        <enum value="0x929E" name="GL_DIFFERENCE_KHR"/>
+        <enum value="0x929E" name="GL_DIFFERENCE_NV"/>
+        <enum value="0x929F" name="GL_MINUS_NV"/>
+        <enum value="0x92A0" name="GL_EXCLUSION"/>
+        <enum value="0x92A0" name="GL_EXCLUSION_KHR"/>
+        <enum value="0x92A0" name="GL_EXCLUSION_NV"/>
+        <enum value="0x92A1" name="GL_CONTRAST_NV"/>
+            <unused start="0x92A2" vendor="NV"/>
+        <enum value="0x92A3" name="GL_INVERT_RGB_NV"/>
+        <enum value="0x92A4" name="GL_LINEARDODGE_NV"/>
+        <enum value="0x92A5" name="GL_LINEARBURN_NV"/>
+        <enum value="0x92A6" name="GL_VIVIDLIGHT_NV"/>
+        <enum value="0x92A7" name="GL_LINEARLIGHT_NV"/>
+        <enum value="0x92A8" name="GL_PINLIGHT_NV"/>
+        <enum value="0x92A9" name="GL_HARDMIX_NV"/>
+            <unused start="0x92AA" end="0x92AC" vendor="NV"/>
+        <enum value="0x92AD" name="GL_HSL_HUE"/>
+        <enum value="0x92AD" name="GL_HSL_HUE_KHR"/>
+        <enum value="0x92AD" name="GL_HSL_HUE_NV"/>
+        <enum value="0x92AE" name="GL_HSL_SATURATION"/>
+        <enum value="0x92AE" name="GL_HSL_SATURATION_KHR"/>
+        <enum value="0x92AE" name="GL_HSL_SATURATION_NV"/>
+        <enum value="0x92AF" name="GL_HSL_COLOR"/>
+        <enum value="0x92AF" name="GL_HSL_COLOR_KHR"/>
+        <enum value="0x92AF" name="GL_HSL_COLOR_NV"/>
+        <enum value="0x92B0" name="GL_HSL_LUMINOSITY"/>
+        <enum value="0x92B0" name="GL_HSL_LUMINOSITY_KHR"/>
+        <enum value="0x92B0" name="GL_HSL_LUMINOSITY_NV"/>
+        <enum value="0x92B1" name="GL_PLUS_CLAMPED_NV"/>
+        <enum value="0x92B2" name="GL_PLUS_CLAMPED_ALPHA_NV"/>
+        <enum value="0x92B3" name="GL_MINUS_CLAMPED_NV"/>
+        <enum value="0x92B4" name="GL_INVERT_OVG_NV"/>
+            <unused start="0x92B5" end="0x92BA" vendor="NV"/>
+        <enum value="0x92BB" name="GL_PURGED_CONTEXT_RESET_NV"/>
+            <unused start="0x92BC" end="0x92BD" vendor="NV"/>
+        <enum value="0x92BE" name="GL_PRIMITIVE_BOUNDING_BOX_ARB"/>
+        <enum value="0x92BE" name="GL_PRIMITIVE_BOUNDING_BOX"/>
+        <enum value="0x92BE" name="GL_PRIMITIVE_BOUNDING_BOX_EXT"/>
+        <enum value="0x92BE" name="GL_PRIMITIVE_BOUNDING_BOX_OES"/>
+            <unused start="0x92BF" vendor="NV"/>
+        <enum value="0x92C0" name="GL_ATOMIC_COUNTER_BUFFER"/>
+        <enum value="0x92C1" name="GL_ATOMIC_COUNTER_BUFFER_BINDING"/>
+        <enum value="0x92C2" name="GL_ATOMIC_COUNTER_BUFFER_START"/>
+        <enum value="0x92C3" name="GL_ATOMIC_COUNTER_BUFFER_SIZE"/>
+        <enum value="0x92C4" name="GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE"/>
+        <enum value="0x92C5" name="GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS"/>
+        <enum value="0x92C6" name="GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES"/>
+        <enum value="0x92C7" name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER"/>
+        <enum value="0x92C8" name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+        <enum value="0x92C9" name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+        <enum value="0x92CA" name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER"/>
+        <enum value="0x92CB" name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER"/>
+        <enum value="0x92CC" name="GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS"/>
+        <enum value="0x92CD" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS"/>
+        <enum value="0x92CD" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT"/>
+        <enum value="0x92CD" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES"/>
+        <enum value="0x92CE" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS"/>
+        <enum value="0x92CE" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT"/>
+        <enum value="0x92CE" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES"/>
+        <enum value="0x92CF" name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS"/>
+        <enum value="0x92CF" name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT"/>
+        <enum value="0x92CF" name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES"/>
+        <enum value="0x92D0" name="GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS"/>
+        <enum value="0x92D1" name="GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS"/>
+        <enum value="0x92D2" name="GL_MAX_VERTEX_ATOMIC_COUNTERS"/>
+        <enum value="0x92D3" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"/>
+        <enum value="0x92D3" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT"/>
+        <enum value="0x92D3" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES"/>
+        <enum value="0x92D4" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"/>
+        <enum value="0x92D4" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT"/>
+        <enum value="0x92D4" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES"/>
+        <enum value="0x92D5" name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS"/>
+        <enum value="0x92D5" name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT"/>
+        <enum value="0x92D5" name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES"/>
+        <enum value="0x92D6" name="GL_MAX_FRAGMENT_ATOMIC_COUNTERS"/>
+        <enum value="0x92D7" name="GL_MAX_COMBINED_ATOMIC_COUNTERS"/>
+        <enum value="0x92D8" name="GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE"/>
+        <enum value="0x92D9" name="GL_ACTIVE_ATOMIC_COUNTER_BUFFERS"/>
+        <enum value="0x92DA" name="GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX"/>
+        <enum value="0x92DB" name="GL_UNSIGNED_INT_ATOMIC_COUNTER"/>
+        <enum value="0x92DC" name="GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS"/>
+        <enum value="0x92DD" name="GL_FRAGMENT_COVERAGE_TO_COLOR_NV"/>
+        <enum value="0x92DE" name="GL_FRAGMENT_COVERAGE_COLOR_NV"/>
+            <unused start="0x92DF" end="0x92DF" vendor="NV"/>
+        <enum value="0x92E0" name="GL_DEBUG_OUTPUT"/>
+        <enum value="0x92E0" name="GL_DEBUG_OUTPUT_KHR"/>
+        <enum value="0x92E1" name="GL_UNIFORM"/>
+        <enum value="0x92E2" name="GL_UNIFORM_BLOCK"/>
+        <enum value="0x92E3" name="GL_PROGRAM_INPUT"/>
+        <enum value="0x92E4" name="GL_PROGRAM_OUTPUT"/>
+        <enum value="0x92E5" name="GL_BUFFER_VARIABLE"/>
+        <enum value="0x92E6" name="GL_SHADER_STORAGE_BLOCK"/>
+        <enum value="0x92E7" name="GL_IS_PER_PATCH"/>
+        <enum value="0x92E7" name="GL_IS_PER_PATCH_EXT"/>
+        <enum value="0x92E7" name="GL_IS_PER_PATCH_OES"/>
+        <enum value="0x92E8" name="GL_VERTEX_SUBROUTINE"/>
+        <enum value="0x92E9" name="GL_TESS_CONTROL_SUBROUTINE"/>
+        <enum value="0x92EA" name="GL_TESS_EVALUATION_SUBROUTINE"/>
+        <enum value="0x92EB" name="GL_GEOMETRY_SUBROUTINE"/>
+        <enum value="0x92EC" name="GL_FRAGMENT_SUBROUTINE"/>
+        <enum value="0x92ED" name="GL_COMPUTE_SUBROUTINE"/>
+        <enum value="0x92EE" name="GL_VERTEX_SUBROUTINE_UNIFORM"/>
+        <enum value="0x92EF" name="GL_TESS_CONTROL_SUBROUTINE_UNIFORM"/>
+        <enum value="0x92F0" name="GL_TESS_EVALUATION_SUBROUTINE_UNIFORM"/>
+        <enum value="0x92F1" name="GL_GEOMETRY_SUBROUTINE_UNIFORM"/>
+        <enum value="0x92F2" name="GL_FRAGMENT_SUBROUTINE_UNIFORM"/>
+        <enum value="0x92F3" name="GL_COMPUTE_SUBROUTINE_UNIFORM"/>
+        <enum value="0x92F4" name="GL_TRANSFORM_FEEDBACK_VARYING"/>
+        <enum value="0x92F5" name="GL_ACTIVE_RESOURCES"/>
+        <enum value="0x92F6" name="GL_MAX_NAME_LENGTH"/>
+        <enum value="0x92F7" name="GL_MAX_NUM_ACTIVE_VARIABLES"/>
+        <enum value="0x92F8" name="GL_MAX_NUM_COMPATIBLE_SUBROUTINES"/>
+        <enum value="0x92F9" name="GL_NAME_LENGTH"/>
+        <enum value="0x92FA" name="GL_TYPE"/>
+        <enum value="0x92FB" name="GL_ARRAY_SIZE"/>
+        <enum value="0x92FC" name="GL_OFFSET"/>
+        <enum value="0x92FD" name="GL_BLOCK_INDEX"/>
+        <enum value="0x92FE" name="GL_ARRAY_STRIDE"/>
+        <enum value="0x92FF" name="GL_MATRIX_STRIDE"/>
+        <enum value="0x9300" name="GL_IS_ROW_MAJOR"/>
+        <enum value="0x9301" name="GL_ATOMIC_COUNTER_BUFFER_INDEX"/>
+        <enum value="0x9302" name="GL_BUFFER_BINDING"/>
+        <enum value="0x9303" name="GL_BUFFER_DATA_SIZE"/>
+        <enum value="0x9304" name="GL_NUM_ACTIVE_VARIABLES"/>
+        <enum value="0x9305" name="GL_ACTIVE_VARIABLES"/>
+        <enum value="0x9306" name="GL_REFERENCED_BY_VERTEX_SHADER"/>
+        <enum value="0x9307" name="GL_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+        <enum value="0x9307" name="GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT"/>
+        <enum value="0x9307" name="GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES"/>
+        <enum value="0x9308" name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+        <enum value="0x9308" name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT"/>
+        <enum value="0x9308" name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES"/>
+        <enum value="0x9309" name="GL_REFERENCED_BY_GEOMETRY_SHADER"/>
+        <enum value="0x9309" name="GL_REFERENCED_BY_GEOMETRY_SHADER_EXT"/>
+        <enum value="0x9309" name="GL_REFERENCED_BY_GEOMETRY_SHADER_OES"/>
+        <enum value="0x930A" name="GL_REFERENCED_BY_FRAGMENT_SHADER"/>
+        <enum value="0x930B" name="GL_REFERENCED_BY_COMPUTE_SHADER"/>
+        <enum value="0x930C" name="GL_TOP_LEVEL_ARRAY_SIZE"/>
+        <enum value="0x930D" name="GL_TOP_LEVEL_ARRAY_STRIDE"/>
+        <enum value="0x930E" name="GL_LOCATION"/>
+        <enum value="0x930F" name="GL_LOCATION_INDEX"/>
+        <enum value="0x930F" name="GL_LOCATION_INDEX_EXT"/>
+        <enum value="0x9310" name="GL_FRAMEBUFFER_DEFAULT_WIDTH"/>
+        <enum value="0x9311" name="GL_FRAMEBUFFER_DEFAULT_HEIGHT"/>
+        <enum value="0x9312" name="GL_FRAMEBUFFER_DEFAULT_LAYERS"/>
+        <enum value="0x9312" name="GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT"/>
+        <enum value="0x9312" name="GL_FRAMEBUFFER_DEFAULT_LAYERS_OES"/>
+        <enum value="0x9313" name="GL_FRAMEBUFFER_DEFAULT_SAMPLES"/>
+        <enum value="0x9314" name="GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"/>
+        <enum value="0x9315" name="GL_MAX_FRAMEBUFFER_WIDTH"/>
+        <enum value="0x9316" name="GL_MAX_FRAMEBUFFER_HEIGHT"/>
+        <enum value="0x9317" name="GL_MAX_FRAMEBUFFER_LAYERS"/>
+        <enum value="0x9317" name="GL_MAX_FRAMEBUFFER_LAYERS_EXT"/>
+        <enum value="0x9317" name="GL_MAX_FRAMEBUFFER_LAYERS_OES"/>
+        <enum value="0x9318" name="GL_MAX_FRAMEBUFFER_SAMPLES"/>
+            <unused start="0x9319" end="0x9326" vendor="NV"/>
+        <enum value="0x9327" name="GL_RASTER_MULTISAMPLE_EXT"/>
+        <enum value="0x9328" name="GL_RASTER_SAMPLES_EXT"/>
+        <enum value="0x9329" name="GL_MAX_RASTER_SAMPLES_EXT"/>
+        <enum value="0x932A" name="GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT"/>
+        <enum value="0x932B" name="GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT"/>
+        <enum value="0x932C" name="GL_EFFECTIVE_RASTER_SAMPLES_EXT"/>
+        <enum value="0x932D" name="GL_DEPTH_SAMPLES_NV"/>
+        <enum value="0x932E" name="GL_STENCIL_SAMPLES_NV"/>
+        <enum value="0x932F" name="GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV"/>
+        <enum value="0x9330" name="GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV"/>
+        <enum value="0x9331" name="GL_COVERAGE_MODULATION_TABLE_NV"/>
+        <enum value="0x9332" name="GL_COVERAGE_MODULATION_NV"/>
+        <enum value="0x9333" name="GL_COVERAGE_MODULATION_TABLE_SIZE_NV"/>
+            <unused start="0x9334" end="0x9338" vendor="NV"/>
+        <enum value="0x9339" name="GL_WARP_SIZE_NV"/>
+        <enum value="0x933A" name="GL_WARPS_PER_SM_NV"/>
+        <enum value="0x933B" name="GL_SM_COUNT_NV"/>
+        <enum value="0x933C" name="GL_FILL_RECTANGLE_NV"/>
+        <enum value="0x933D" name="GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB"/>
+        <enum value="0x933D" name="GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV"/>
+        <enum value="0x933E" name="GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB"/>
+        <enum value="0x933E" name="GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV"/>
+        <enum value="0x933F" name="GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB"/>
+        <enum value="0x933F" name="GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV"/>
+        <enum value="0x9340" name="GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB"/>
+        <enum value="0x9340" name="GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV"/>
+        <enum value="0x9341" name="GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB"/>
+        <enum value="0x9341" name="GL_PROGRAMMABLE_SAMPLE_LOCATION_NV"/>
+        <enum value="0x9342" name="GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB"/>
+        <enum value="0x9342" name="GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV"/>
+        <enum value="0x9343" name="GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB"/>
+        <enum value="0x9343" name="GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV"/>
+        <enum value="0x9344" name="GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB"/>
+        <enum value="0x9345" name="GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB"/>
+        <enum value="0x9346" name="GL_CONSERVATIVE_RASTERIZATION_NV"/>
+        <enum value="0x9347" name="GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV"/>
+        <enum value="0x9348" name="GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV"/>
+        <enum value="0x9349" name="GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV"/>
+        <enum value="0x934A" name="GL_LOCATION_COMPONENT"/>
+        <enum value="0x934B" name="GL_TRANSFORM_FEEDBACK_BUFFER_INDEX"/>
+        <enum value="0x934C" name="GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE"/>
+            <unused start="0x934D" end="0x934F" vendor="NV"/>
+        <enum value="0x9350" name="GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV"/>
+        <enum value="0x9351" name="GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV"/>
+        <enum value="0x9352" name="GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV"/>
+        <enum value="0x9353" name="GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV"/>
+        <enum value="0x9354" name="GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV"/>
+        <enum value="0x9355" name="GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV"/>
+        <enum value="0x9356" name="GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV"/>
+        <enum value="0x9357" name="GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV"/>
+        <enum value="0x9358" name="GL_VIEWPORT_SWIZZLE_X_NV"/>
+        <enum value="0x9359" name="GL_VIEWPORT_SWIZZLE_Y_NV"/>
+        <enum value="0x935A" name="GL_VIEWPORT_SWIZZLE_Z_NV"/>
+        <enum value="0x935B" name="GL_VIEWPORT_SWIZZLE_W_NV"/>
+        <enum value="0x935C" name="GL_CLIP_ORIGIN"/>
+        <enum value="0x935D" name="GL_CLIP_DEPTH_MODE"/>
+        <enum value="0x935E" name="GL_NEGATIVE_ONE_TO_ONE"/>
+        <enum value="0x935F" name="GL_ZERO_TO_ONE"/>
+            <unused start="0x9360" end="0x9364" vendor="NV"/>
+        <enum value="0x9365" name="GL_CLEAR_TEXTURE"/>
+        <enum value="0x9366" name="GL_TEXTURE_REDUCTION_MODE_ARB"/>
+        <enum value="0x9367" name="GL_WEIGHTED_AVERAGE_ARB"/>
+        <enum value="0x9368" name="GL_FONT_GLYPHS_AVAILABLE_NV"/>
+        <enum value="0x9369" name="GL_FONT_TARGET_UNAVAILABLE_NV"/>
+        <enum value="0x936A" name="GL_FONT_UNAVAILABLE_NV"/>
+        <enum value="0x936B" name="GL_FONT_UNINTELLIGIBLE_NV"/>
+        <enum value="0x936C" name="GL_STANDARD_FONT_FORMAT_NV"/>
+        <enum value="0x936D" name="GL_FRAGMENT_INPUT_NV"/>
+        <enum value="0x936E" name="GL_UNIFORM_BUFFER_UNIFIED_NV"/>
+        <enum value="0x936F" name="GL_UNIFORM_BUFFER_ADDRESS_NV"/>
+        <enum value="0x9370" name="GL_UNIFORM_BUFFER_LENGTH_NV"/>
+        <enum value="0x9371" name="GL_MULTISAMPLES_NV"/>
+        <enum value="0x9372" name="GL_SUPERSAMPLE_SCALE_X_NV"/>
+        <enum value="0x9373" name="GL_SUPERSAMPLE_SCALE_Y_NV"/>
+        <enum value="0x9374" name="GL_CONFORMANT_NV"/>
+            <unused start="0x9375" end="0x9378" vendor="NV"/>
+        <enum value="0x9379" name="GL_CONSERVATIVE_RASTER_DILATE_NV"/>
+        <enum value="0x937A" name="GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV"/>
+        <enum value="0x937B" name="GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV"/>
+        <enum value="0x937C" name="GL_VIEWPORT_POSITION_W_SCALE_NV"/>
+        <enum value="0x937D" name="GL_VIEWPORT_POSITION_W_SCALE_X_COEFF_NV"/>
+        <enum value="0x937E" name="GL_VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV"/>
+            <unused start="0x937F" vendor="NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9380" end="0x939F" vendor="ARB">
+        <enum value="0x9380" name="GL_NUM_SAMPLE_COUNTS"/>
+        <enum value="0x9381" name="GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB"/>
+        <enum value="0x9381" name="GL_MULTISAMPLE_LINE_WIDTH_RANGE"/>
+        <enum value="0x9382" name="GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB"/>
+        <enum value="0x9382" name="GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY"/>
+            <unused start="0x9383" end="0x939F" vendor="ARB"/>
+    </enums>
+
+    <enums namespace="GL" start="0x93A0" end="0x93AF" vendor="ANGLE" comment="Khronos bug 8100">
+        <enum value="0x93A0" name="GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE"/>
+        <enum value="0x93A1" name="GL_BGRA8_EXT"/>
+        <enum value="0x93A2" name="GL_TEXTURE_USAGE_ANGLE"/>
+        <enum value="0x93A3" name="GL_FRAMEBUFFER_ATTACHMENT_ANGLE"/>
+        <enum value="0x93A4" name="GL_PACK_REVERSE_ROW_ORDER_ANGLE"/>
+            <unused start="0x93A5" vendor="ANGLE"/>
+        <enum value="0x93A6" name="GL_PROGRAM_BINARY_ANGLE"/>
+            <unused start="0x93A7" end="0x93AF" vendor="ANGLE"/>
+    </enums>
+
+    <enums namespace="GL" start="0x93B0" end="0x93EF" vendor="OES" comment="Khronos bug 8853">
+        <enum value="0x93B0" name="GL_COMPRESSED_RGBA_ASTC_4x4"/>
+        <enum value="0x93B0" name="GL_COMPRESSED_RGBA_ASTC_4x4_KHR"/>
+        <enum value="0x93B1" name="GL_COMPRESSED_RGBA_ASTC_5x4"/>
+        <enum value="0x93B1" name="GL_COMPRESSED_RGBA_ASTC_5x4_KHR"/>
+        <enum value="0x93B2" name="GL_COMPRESSED_RGBA_ASTC_5x5"/>
+        <enum value="0x93B2" name="GL_COMPRESSED_RGBA_ASTC_5x5_KHR"/>
+        <enum value="0x93B3" name="GL_COMPRESSED_RGBA_ASTC_6x5"/>
+        <enum value="0x93B3" name="GL_COMPRESSED_RGBA_ASTC_6x5_KHR"/>
+        <enum value="0x93B4" name="GL_COMPRESSED_RGBA_ASTC_6x6"/>
+        <enum value="0x93B4" name="GL_COMPRESSED_RGBA_ASTC_6x6_KHR"/>
+        <enum value="0x93B5" name="GL_COMPRESSED_RGBA_ASTC_8x5"/>
+        <enum value="0x93B5" name="GL_COMPRESSED_RGBA_ASTC_8x5_KHR"/>
+        <enum value="0x93B6" name="GL_COMPRESSED_RGBA_ASTC_8x6"/>
+        <enum value="0x93B6" name="GL_COMPRESSED_RGBA_ASTC_8x6_KHR"/>
+        <enum value="0x93B7" name="GL_COMPRESSED_RGBA_ASTC_8x8"/>
+        <enum value="0x93B7" name="GL_COMPRESSED_RGBA_ASTC_8x8_KHR"/>
+        <enum value="0x93B8" name="GL_COMPRESSED_RGBA_ASTC_10x5"/>
+        <enum value="0x93B8" name="GL_COMPRESSED_RGBA_ASTC_10x5_KHR"/>
+        <enum value="0x93B9" name="GL_COMPRESSED_RGBA_ASTC_10x6"/>
+        <enum value="0x93B9" name="GL_COMPRESSED_RGBA_ASTC_10x6_KHR"/>
+        <enum value="0x93BA" name="GL_COMPRESSED_RGBA_ASTC_10x8"/>
+        <enum value="0x93BA" name="GL_COMPRESSED_RGBA_ASTC_10x8_KHR"/>
+        <enum value="0x93BB" name="GL_COMPRESSED_RGBA_ASTC_10x10"/>
+        <enum value="0x93BB" name="GL_COMPRESSED_RGBA_ASTC_10x10_KHR"/>
+        <enum value="0x93BC" name="GL_COMPRESSED_RGBA_ASTC_12x10"/>
+        <enum value="0x93BC" name="GL_COMPRESSED_RGBA_ASTC_12x10_KHR"/>
+        <enum value="0x93BD" name="GL_COMPRESSED_RGBA_ASTC_12x12"/>
+        <enum value="0x93BD" name="GL_COMPRESSED_RGBA_ASTC_12x12_KHR"/>
+            <unused start="0x93BE" end="0x93BF" vendor="OES"/>
+        <enum value="0x93C0" name="GL_COMPRESSED_RGBA_ASTC_3x3x3_OES"/>
+        <enum value="0x93C1" name="GL_COMPRESSED_RGBA_ASTC_4x3x3_OES"/>
+        <enum value="0x93C2" name="GL_COMPRESSED_RGBA_ASTC_4x4x3_OES"/>
+        <enum value="0x93C3" name="GL_COMPRESSED_RGBA_ASTC_4x4x4_OES"/>
+        <enum value="0x93C4" name="GL_COMPRESSED_RGBA_ASTC_5x4x4_OES"/>
+        <enum value="0x93C5" name="GL_COMPRESSED_RGBA_ASTC_5x5x4_OES"/>
+        <enum value="0x93C6" name="GL_COMPRESSED_RGBA_ASTC_5x5x5_OES"/>
+        <enum value="0x93C7" name="GL_COMPRESSED_RGBA_ASTC_6x5x5_OES"/>
+        <enum value="0x93C8" name="GL_COMPRESSED_RGBA_ASTC_6x6x5_OES"/>
+        <enum value="0x93C9" name="GL_COMPRESSED_RGBA_ASTC_6x6x6_OES"/>
+            <unused start="0x93CA" end="0x93CF" vendor="OES"/>
+        <enum value="0x93D0" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4"/>
+        <enum value="0x93D0" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"/>
+        <enum value="0x93D1" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4"/>
+        <enum value="0x93D1" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"/>
+        <enum value="0x93D2" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5"/>
+        <enum value="0x93D2" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"/>
+        <enum value="0x93D3" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5"/>
+        <enum value="0x93D3" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"/>
+        <enum value="0x93D4" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6"/>
+        <enum value="0x93D4" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"/>
+        <enum value="0x93D5" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5"/>
+        <enum value="0x93D5" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"/>
+        <enum value="0x93D6" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6"/>
+        <enum value="0x93D6" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"/>
+        <enum value="0x93D7" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8"/>
+        <enum value="0x93D7" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"/>
+        <enum value="0x93D8" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5"/>
+        <enum value="0x93D8" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"/>
+        <enum value="0x93D9" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6"/>
+        <enum value="0x93D9" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"/>
+        <enum value="0x93DA" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8"/>
+        <enum value="0x93DA" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"/>
+        <enum value="0x93DB" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10"/>
+        <enum value="0x93DB" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"/>
+        <enum value="0x93DC" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10"/>
+        <enum value="0x93DC" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"/>
+        <enum value="0x93DD" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12"/>
+        <enum value="0x93DD" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"/>
+            <unused start="0x93DE" end="0x93DF" vendor="OES"/>
+        <enum value="0x93E0" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES"/>
+        <enum value="0x93E1" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES"/>
+        <enum value="0x93E2" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES"/>
+        <enum value="0x93E3" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES"/>
+        <enum value="0x93E4" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES"/>
+        <enum value="0x93E5" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES"/>
+        <enum value="0x93E6" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES"/>
+        <enum value="0x93E7" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES"/>
+        <enum value="0x93E8" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES"/>
+        <enum value="0x93E9" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES"/>
+            <unused start="0x93EA" end="0x93EF" vendor="OES"/>
+    </enums>
+
+    <enums namespace="GL" start="0x93F0" end="0x94EF" vendor="APPLE" comment="Khronos bug 10233">
+        <enum value="0x93F0" name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG"/>
+        <enum value="0x93F1" name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG"/>
+            <unused start="0x93F2" end="0x94EF" vendor="APPLE"/>
+    </enums>
+
+    <enums namespace="GL" start="0x94F0" end="0x950F" vendor="INTEL" comment="Khronos bug 11345">
+        <enum value="0x94F0" name="GL_PERFQUERY_COUNTER_EVENT_INTEL"/>
+        <enum value="0x94F1" name="GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL"/>
+        <enum value="0x94F2" name="GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL"/>
+        <enum value="0x94F3" name="GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL"/>
+        <enum value="0x94F4" name="GL_PERFQUERY_COUNTER_RAW_INTEL"/>
+        <enum value="0x94F5" name="GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL"/>
+            <unused start="0x94F6" end="0x94F7" vendor="INTEL"/>
+        <enum value="0x94F8" name="GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL"/>
+        <enum value="0x94F9" name="GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL"/>
+        <enum value="0x94FA" name="GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL"/>
+        <enum value="0x94FB" name="GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL"/>
+        <enum value="0x94FC" name="GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL"/>
+        <enum value="0x94FD" name="GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL"/>
+        <enum value="0x94FE" name="GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL"/>
+        <enum value="0x94FF" name="GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL"/>
+        <enum value="0x9500" name="GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL"/>
+            <unused start="0x9501" end="0x950F" vendor="INTEL"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9510" end="0x952F" vendor="Broadcom" comment="Khronos bug 12203">
+            <unused start="0x9510" end="0x952F" vendor="Broadcom"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9530" end="0x962F" vendor="NV" comment="Khronos bug 12977">
+            <unused start="0x9530" end="0x954C" vendor="NV"/>
+        <enum value="0x954D" name="GL_CONSERVATIVE_RASTER_MODE_NV"/>
+        <enum value="0x954E" name="GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV"/>
+        <enum value="0x954F" name="GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV"/>
+            <unused start="0x9550" end="0x962F" vendor="NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9630" end="0x963F" vendor="Oculus" comment="Email from Cass Everitt">
+        <enum value="0x9630" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR"/>
+        <enum value="0x9631" name="GL_MAX_VIEWS_OVR"/>
+        <enum value="0x9632" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR"/>
+        <enum value="0x9633" name="GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR"/>
+            <unused start="0x9633" end="0x963F" vendor="Oculus"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9640" end="0x964F" vendor="Mediatek" comment="Khronos bug 14294">
+        <enum value="0x9640" name="GL_GS_SHADER_BINARY_MTK"/>
+        <enum value="0x9641" name="GL_GS_PROGRAM_BINARY_MTK"/>
+            <unused start="0x9642" end="0x964F" vendor="Mediatek"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9650" end="0x968F" vendor="IMG" comment="Khronos bug 14977">
+        <enum value="0x9650" name="GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT"/>
+        <enum value="0x9651" name="GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT"/>
+        <enum value="0x9652" name="GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT"/>
+            <unused start="0x9653" end="0x968F" vendor="IMG"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9690" end="0x969F" vendor="ANGLE" comment="Khronos bug 15423">
+            <unused start="0x9690" end="0x969F" vendor="ANGLE"/>
+    </enums>
+
+    <enums namespace="GL" start="0x96A0" end="0x96AF" vendor="Qualcomm" comment="contact Maurice Ribble">
+            <unused start="0x96A0" end="0x96AF" vendor="Qualcomm"/>
+    </enums>
+
+<!-- Enums reservable for future use. To reserve a new range, allocate one
+     or more multiples of 16 starting at the lowest available point in this
+     block and note it in a new <enums> block immediately above.
+
+     Please remember that new enumerant allocations must be obtained by
+     request to the Khronos API registrar (see comments at the top of this
+     file) File requests in the Khronos Bugzilla, OpenGL project, Registry
+     component. -->
+
+    <enums namespace="GL" start="0x96B0" end="99999" vendor="ARB" comment="RESERVED FOR FUTURE ALLOCATIONS BY KHRONOS">
+        <unused start="0x96B0" end="99999" comment="RESERVED"/>
+    </enums>
+
+<!-- Historical large block allocations, all unused except (in older days) by IBM -->
+    <enums namespace="GL" start="100000" end="100999" vendor="ARB" comment="GLU enums"/>
+    <enums namespace="GL" start="101000" end="101999" vendor="ARB" comment="Conformance test enums"/>
+    <enums namespace="GL" start="102000" end="102999" vendor="ARB" comment="Unused, unlikely to ever be used"/>
+
+    <enums namespace="GL" start="103000" end="103999" vendor="IBM" comment="IBM is out of the graphics hardware business. Most of this range will remain unused.">
+        <enum value="0x19262" name="GL_RASTER_POSITION_UNCLIPPED_IBM"/>
+        <enum value="103050" name="GL_CULL_VERTEX_IBM"/>
+        <enum value="103060" name="GL_ALL_STATIC_DATA_IBM"/>
+        <enum value="103061" name="GL_STATIC_VERTEX_ARRAY_IBM"/>
+        <enum value="103070" name="GL_VERTEX_ARRAY_LIST_IBM"/>
+        <enum value="103071" name="GL_NORMAL_ARRAY_LIST_IBM"/>
+        <enum value="103072" name="GL_COLOR_ARRAY_LIST_IBM"/>
+        <enum value="103073" name="GL_INDEX_ARRAY_LIST_IBM"/>
+        <enum value="103074" name="GL_TEXTURE_COORD_ARRAY_LIST_IBM"/>
+        <enum value="103075" name="GL_EDGE_FLAG_ARRAY_LIST_IBM"/>
+        <enum value="103076" name="GL_FOG_COORDINATE_ARRAY_LIST_IBM"/>
+        <enum value="103077" name="GL_SECONDARY_COLOR_ARRAY_LIST_IBM"/>
+        <enum value="103080" name="GL_VERTEX_ARRAY_LIST_STRIDE_IBM"/>
+        <enum value="103081" name="GL_NORMAL_ARRAY_LIST_STRIDE_IBM"/>
+        <enum value="103082" name="GL_COLOR_ARRAY_LIST_STRIDE_IBM"/>
+        <enum value="103083" name="GL_INDEX_ARRAY_LIST_STRIDE_IBM"/>
+        <enum value="103084" name="GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM"/>
+        <enum value="103085" name="GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM"/>
+        <enum value="103086" name="GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM"/>
+        <enum value="103087" name="GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM"/>
+    </enums>
+
+    <enums namespace="GL" start="104000" end="104999" vendor="NEC" comment="NEC may be out of the graphics hardware business?"/>
+    <enums namespace="GL" start="105000" end="105999" vendor="Compaq" comment="Compaq was acquired by HP"/>
+    <enums namespace="GL" start="106000" end="106999" vendor="KPC" comment="Kubota Pacific is out of business"/>
+    <enums namespace="GL" start="107000" end="107999" vendor="PGI" comment="Portland Graphics was acquired by Template Graphics, which is out of business">
+            <!-- lots of <unused> areas here which won't be computed yet -->
+        <enum value="0x1A1F8" name="GL_PREFER_DOUBLEBUFFER_HINT_PGI"/>
+        <enum value="0x1A1FD" name="GL_CONSERVE_MEMORY_HINT_PGI"/>
+        <enum value="0x1A1FE" name="GL_RECLAIM_MEMORY_HINT_PGI"/>
+        <enum value="0x1A202" name="GL_NATIVE_GRAPHICS_HANDLE_PGI"/>
+        <enum value="0x1A203" name="GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI"/>
+        <enum value="0x1A204" name="GL_NATIVE_GRAPHICS_END_HINT_PGI"/>
+        <enum value="0x1A20C" name="GL_ALWAYS_FAST_HINT_PGI"/>
+        <enum value="0x1A20D" name="GL_ALWAYS_SOFT_HINT_PGI"/>
+        <enum value="0x1A20E" name="GL_ALLOW_DRAW_OBJ_HINT_PGI"/>
+        <enum value="0x1A20F" name="GL_ALLOW_DRAW_WIN_HINT_PGI"/>
+        <enum value="0x1A210" name="GL_ALLOW_DRAW_FRG_HINT_PGI"/>
+        <enum value="0x1A211" name="GL_ALLOW_DRAW_MEM_HINT_PGI"/>
+        <enum value="0x1A216" name="GL_STRICT_DEPTHFUNC_HINT_PGI"/>
+        <enum value="0x1A217" name="GL_STRICT_LIGHTING_HINT_PGI"/>
+        <enum value="0x1A218" name="GL_STRICT_SCISSOR_HINT_PGI"/>
+        <enum value="0x1A219" name="GL_FULL_STIPPLE_HINT_PGI"/>
+        <enum value="0x1A220" name="GL_CLIP_NEAR_HINT_PGI"/>
+        <enum value="0x1A221" name="GL_CLIP_FAR_HINT_PGI"/>
+        <enum value="0x1A222" name="GL_WIDE_LINE_HINT_PGI"/>
+        <enum value="0x1A223" name="GL_BACK_NORMALS_HINT_PGI"/>
+        <enum value="0x1A22A" name="GL_VERTEX_DATA_HINT_PGI"/>
+        <enum value="0x1A22B" name="GL_VERTEX_CONSISTENT_HINT_PGI"/>
+        <enum value="0x1A22C" name="GL_MATERIAL_SIDE_HINT_PGI"/>
+        <enum value="0x1A22D" name="GL_MAX_VERTEX_HINT_PGI"/>
+    </enums>
+
+    <enums namespace="GL" start="108000" end="108999" vendor="ES" comment="Evans and Sutherland is out of the graphics hardware business"/>
+
+    <!-- SECTION: GL command definitions. -->
+    <commands namespace="GL">
+        <command>
+            <proto>void <name>glAccum</name></proto>
+            <param group="AccumOp"><ptype>GLenum</ptype> <name>op</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>value</name></param>
+            <glx type="render" opcode="137"/>
+        </command>
+        <command>
+            <proto>void <name>glAccumxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLfixed</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glActiveProgramEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glActiveShaderProgram</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glActiveShaderProgramEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glActiveStencilFaceEXT</name></proto>
+            <param group="StencilFaceDirection"><ptype>GLenum</ptype> <name>face</name></param>
+            <glx type="render" opcode="4220"/>
+        </command>
+        <command>
+            <proto>void <name>glActiveTexture</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texture</name></param>
+            <glx type="render" opcode="197"/>
+        </command>
+        <command>
+            <proto>void <name>glActiveTextureARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texture</name></param>
+            <alias name="glActiveTexture"/>
+            <glx type="render" opcode="197"/>
+        </command>
+        <command>
+            <proto>void <name>glActiveVaryingNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glAlphaFragmentOp1ATI</name></proto>
+            <param group="FragmentOpATI"><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLuint</ptype> <name>dst</name></param>
+            <param><ptype>GLuint</ptype> <name>dstMod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Mod</name></param>
+        </command>
+        <command>
+            <proto>void <name>glAlphaFragmentOp2ATI</name></proto>
+            <param group="FragmentOpATI"><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLuint</ptype> <name>dst</name></param>
+            <param><ptype>GLuint</ptype> <name>dstMod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Mod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2Mod</name></param>
+        </command>
+        <command>
+            <proto>void <name>glAlphaFragmentOp3ATI</name></proto>
+            <param group="FragmentOpATI"><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLuint</ptype> <name>dst</name></param>
+            <param><ptype>GLuint</ptype> <name>dstMod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Mod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2Mod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg3</name></param>
+            <param><ptype>GLuint</ptype> <name>arg3Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg3Mod</name></param>
+        </command>
+        <command>
+            <proto>void <name>glAlphaFunc</name></proto>
+            <param group="AlphaFunction"><ptype>GLenum</ptype> <name>func</name></param>
+            <param><ptype>GLfloat</ptype> <name>ref</name></param>
+            <glx type="render" opcode="159"/>
+        </command>
+        <command>
+            <proto>void <name>glAlphaFuncQCOM</name></proto>
+            <param><ptype>GLenum</ptype> <name>func</name></param>
+            <param><ptype>GLclampf</ptype> <name>ref</name></param>
+        </command>
+        <command>
+            <proto>void <name>glAlphaFuncx</name></proto>
+            <param><ptype>GLenum</ptype> <name>func</name></param>
+            <param><ptype>GLfixed</ptype> <name>ref</name></param>
+        </command>
+        <command>
+            <proto>void <name>glAlphaFuncxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>func</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>ref</name></param>
+        </command>
+        <command>
+            <proto>void <name>glApplyFramebufferAttachmentCMAAINTEL</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glApplyTextureEXT</name></proto>
+            <param group="LightTextureModeEXT"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glAreProgramsResidentNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>programs</name></param>
+            <param group="Boolean" len="n"><ptype>GLboolean</ptype> *<name>residences</name></param>
+            <glx type="vendor" opcode="1293"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glAreTexturesResident</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Texture" len="n">const <ptype>GLuint</ptype> *<name>textures</name></param>
+            <param group="Boolean" len="n"><ptype>GLboolean</ptype> *<name>residences</name></param>
+            <glx type="single" opcode="143"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glAreTexturesResidentEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Texture" len="n">const <ptype>GLuint</ptype> *<name>textures</name></param>
+            <param group="Boolean" len="n"><ptype>GLboolean</ptype> *<name>residences</name></param>
+            <glx type="vendor" opcode="11"/>
+        </command>
+        <command>
+            <proto>void <name>glArrayElement</name></proto>
+            <param><ptype>GLint</ptype> <name>i</name></param>
+        </command>
+        <command>
+            <proto>void <name>glArrayElementEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>i</name></param>
+            <alias name="glArrayElement"/>
+        </command>
+        <command>
+            <proto>void <name>glArrayObjectATI</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="ScalarType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLuint</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glAsyncMarkerSGIX</name></proto>
+            <param><ptype>GLuint</ptype> <name>marker</name></param>
+        </command>
+        <command>
+            <proto>void <name>glAttachObjectARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>containerObj</name></param>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>obj</name></param>
+            <alias name="glAttachShader"/>
+        </command>
+        <command>
+            <proto>void <name>glAttachShader</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBegin</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="4"/>
+        </command>
+        <command>
+            <proto>void <name>glBeginConditionalRender</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBeginConditionalRenderNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glBeginConditionalRender"/>
+            <glx type="render" opcode="348"/>
+        </command>
+        <command>
+            <proto>void <name>glBeginConditionalRenderNVX</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBeginFragmentShaderATI</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glBeginOcclusionQueryNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBeginPerfMonitorAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>monitor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBeginPerfQueryINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>queryHandle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBeginQuery</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <glx type="render" opcode="231"/>
+        </command>
+        <command>
+            <proto>void <name>glBeginQueryARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <alias name="glBeginQuery"/>
+        </command>
+        <command>
+            <proto>void <name>glBeginQueryEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBeginQueryIndexed</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBeginTransformFeedback</name></proto>
+            <param><ptype>GLenum</ptype> <name>primitiveMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBeginTransformFeedbackEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>primitiveMode</name></param>
+            <alias name="glBeginTransformFeedback"/>
+        </command>
+        <command>
+            <proto>void <name>glBeginTransformFeedbackNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>primitiveMode</name></param>
+            <alias name="glBeginTransformFeedback"/>
+        </command>
+        <command>
+            <proto>void <name>glBeginVertexShaderEXT</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glBeginVideoCaptureNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindAttribLocation</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindAttribLocationARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param>const <ptype>GLcharARB</ptype> *<name>name</name></param>
+            <alias name="glBindAttribLocation"/>
+        </command>
+        <command>
+            <proto>void <name>glBindBuffer</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindBufferARB</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <alias name="glBindBuffer"/>
+        </command>
+        <command>
+            <proto>void <name>glBindBufferBase</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindBufferBaseEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <alias name="glBindBufferBase"/>
+        </command>
+        <command>
+            <proto>void <name>glBindBufferBaseNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <alias name="glBindBufferBase"/>
+        </command>
+        <command>
+            <proto>void <name>glBindBufferOffsetEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindBufferOffsetNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <alias name="glBindBufferOffsetEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glBindBufferRange</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindBufferRangeEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <alias name="glBindBufferRange"/>
+        </command>
+        <command>
+            <proto>void <name>glBindBufferRangeNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <alias name="glBindBufferRange"/>
+        </command>
+        <command>
+            <proto>void <name>glBindBuffersBase</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>buffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindBuffersRange</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>buffers</name></param>
+            <param len="count">const <ptype>GLintptr</ptype> *<name>offsets</name></param>
+            <param len="count">const <ptype>GLsizeiptr</ptype> *<name>sizes</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindFragDataLocation</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>color</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindFragDataLocationEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>color</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+            <alias name="glBindFragDataLocation"/>
+        </command>
+        <command>
+            <proto>void <name>glBindFragDataLocationIndexed</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>colorNumber</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindFragDataLocationIndexedEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>colorNumber</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+            <alias name="glBindFragDataLocationIndexed"/>
+        </command>
+        <command>
+            <proto>void <name>glBindFragmentShaderATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindFramebuffer</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <glx type="render" opcode="236"/>
+        </command>
+        <command>
+            <proto>void <name>glBindFramebufferEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <glx type="render" opcode="4319"/>
+        </command>
+        <command>
+            <proto>void <name>glBindFramebufferOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindImageTexture</name></proto>
+            <param><ptype>GLuint</ptype> <name>unit</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>layered</name></param>
+            <param><ptype>GLint</ptype> <name>layer</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindImageTextureEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>layered</name></param>
+            <param><ptype>GLint</ptype> <name>layer</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+            <param><ptype>GLint</ptype> <name>format</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindImageTextures</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>textures</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glBindLightParameterEXT</name></proto>
+            <param group="LightName"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="LightParameter"><ptype>GLenum</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glBindMaterialParameterEXT</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindMultiTextureEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glBindParameterEXT</name></proto>
+            <param group="VertexShaderParameterEXT"><ptype>GLenum</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindProgramARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <glx type="render" opcode="4180"/>
+        </command>
+        <command>
+            <proto>void <name>glBindProgramNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <alias name="glBindProgramARB"/>
+            <glx type="render" opcode="4180"/>
+        </command>
+        <command>
+            <proto>void <name>glBindProgramPipeline</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindProgramPipelineEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindRenderbuffer</name></proto>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <glx type="render" opcode="235"/>
+        </command>
+        <command>
+            <proto>void <name>glBindRenderbufferEXT</name></proto>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <glx type="render" opcode="4316"/>
+        </command>
+        <command>
+            <proto>void <name>glBindRenderbufferOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindSampler</name></proto>
+            <param><ptype>GLuint</ptype> <name>unit</name></param>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindSamplers</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>samplers</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glBindTexGenParameterEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>unit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindTexture</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <glx type="render" opcode="4117"/>
+        </command>
+        <command>
+            <proto>void <name>glBindTextureEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <alias name="glBindTexture"/>
+            <glx type="render" opcode="4117"/>
+        </command>
+        <command>
+            <proto>void <name>glBindTextureUnit</name></proto>
+            <param><ptype>GLuint</ptype> <name>unit</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glBindTextureUnitParameterEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>unit</name></param>
+            <param group="VertexShaderTextureUnitParameter"><ptype>GLenum</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindTextures</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>textures</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindTransformFeedback</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindTransformFeedbackNV</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindVertexArray</name></proto>
+            <param><ptype>GLuint</ptype> <name>array</name></param>
+            <glx type="render" opcode="350"/>
+        </command>
+        <command>
+            <proto>void <name>glBindVertexArrayAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>array</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindVertexArrayOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>array</name></param>
+            <alias name="glBindVertexArray"/>
+        </command>
+        <command>
+            <proto>void <name>glBindVertexBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindVertexBuffers</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>buffers</name></param>
+            <param len="count">const <ptype>GLintptr</ptype> *<name>offsets</name></param>
+            <param len="count">const <ptype>GLsizei</ptype> *<name>strides</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindVertexShaderEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindVideoCaptureStreamBufferNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+            <param><ptype>GLenum</ptype> <name>frame_region</name></param>
+            <param group="BufferOffsetARB"><ptype>GLintptrARB</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBindVideoCaptureStreamTextureNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+            <param><ptype>GLenum</ptype> <name>frame_region</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3bEXT</name></proto>
+            <param><ptype>GLbyte</ptype> <name>bx</name></param>
+            <param><ptype>GLbyte</ptype> <name>by</name></param>
+            <param><ptype>GLbyte</ptype> <name>bz</name></param>
+            <vecequiv name="glBinormal3bvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3bvEXT</name></proto>
+            <param len="3">const <ptype>GLbyte</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3dEXT</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>bx</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>by</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>bz</name></param>
+            <vecequiv name="glBinormal3dvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3dvEXT</name></proto>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3fEXT</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>bx</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>by</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>bz</name></param>
+            <vecequiv name="glBinormal3fvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3fvEXT</name></proto>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3iEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>bx</name></param>
+            <param><ptype>GLint</ptype> <name>by</name></param>
+            <param><ptype>GLint</ptype> <name>bz</name></param>
+            <vecequiv name="glBinormal3ivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3ivEXT</name></proto>
+            <param len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3sEXT</name></proto>
+            <param><ptype>GLshort</ptype> <name>bx</name></param>
+            <param><ptype>GLshort</ptype> <name>by</name></param>
+            <param><ptype>GLshort</ptype> <name>bz</name></param>
+            <vecequiv name="glBinormal3svEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glBinormal3svEXT</name></proto>
+            <param len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBinormalPointerEXT</name></proto>
+            <param group="BinormalPointerTypeEXT"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBitmap</name></proto>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>xorig</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>yorig</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>xmove</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>ymove</name></param>
+            <param len="COMPSIZE(width,height)">const <ptype>GLubyte</ptype> *<name>bitmap</name></param>
+            <glx type="render" opcode="5"/>
+            <glx type="render" opcode="311" name="glBitmapPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glBitmapxOES</name></proto>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLfixed</ptype> <name>xorig</name></param>
+            <param><ptype>GLfixed</ptype> <name>yorig</name></param>
+            <param><ptype>GLfixed</ptype> <name>xmove</name></param>
+            <param><ptype>GLfixed</ptype> <name>ymove</name></param>
+            <param len="COMPSIZE(width,height)">const <ptype>GLubyte</ptype> *<name>bitmap</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlendBarrier</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glBlendBarrierKHR</name></proto>
+            <alias name="glBlendBarrier"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendBarrierNV</name></proto>
+            <alias name="glBlendBarrier"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendColor</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>red</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>green</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>blue</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>alpha</name></param>
+            <glx type="render" opcode="4096"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendColorEXT</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>red</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>green</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>blue</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>alpha</name></param>
+            <alias name="glBlendColor"/>
+            <glx type="render" opcode="4096"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendColorxOES</name></proto>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>red</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>green</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>blue</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>alpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquation</name></proto>
+            <param group="BlendEquationMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="4097"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationEXT</name></proto>
+            <param group="BlendEquationModeEXT"><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glBlendEquation"/>
+            <glx type="render" opcode="4097"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationIndexedAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glBlendEquationi"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationSeparate</name></proto>
+            <param group="BlendEquationModeEXT"><ptype>GLenum</ptype> <name>modeRGB</name></param>
+            <param group="BlendEquationModeEXT"><ptype>GLenum</ptype> <name>modeAlpha</name></param>
+            <glx type="render" opcode="4228"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationSeparateEXT</name></proto>
+            <param group="BlendEquationModeEXT"><ptype>GLenum</ptype> <name>modeRGB</name></param>
+            <param group="BlendEquationModeEXT"><ptype>GLenum</ptype> <name>modeAlpha</name></param>
+            <alias name="glBlendEquationSeparate"/>
+            <glx type="render" opcode="4228"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationSeparateIndexedAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>modeRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>modeAlpha</name></param>
+            <alias name="glBlendEquationSeparatei"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationSeparateOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>modeRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>modeAlpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationSeparatei</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>modeRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>modeAlpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationSeparateiARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>modeRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>modeAlpha</name></param>
+            <alias name="glBlendEquationSeparatei"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationSeparateiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>modeRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>modeAlpha</name></param>
+            <alias name="glBlendEquationSeparatei"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationSeparateiOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>modeRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>modeAlpha</name></param>
+            <alias name="glBlendEquationSeparatei"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationi</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationiARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glBlendEquationi"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glBlendEquationi"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendEquationiOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glBlendEquationi"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFunc</name></proto>
+            <param group="BlendingFactorSrc"><ptype>GLenum</ptype> <name>sfactor</name></param>
+            <param group="BlendingFactorDest"><ptype>GLenum</ptype> <name>dfactor</name></param>
+            <glx type="render" opcode="160"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncIndexedAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>src</name></param>
+            <param><ptype>GLenum</ptype> <name>dst</name></param>
+            <alias name="glBlendFunci"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncSeparate</name></proto>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>sfactorRGB</name></param>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>dfactorRGB</name></param>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>sfactorAlpha</name></param>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>dfactorAlpha</name></param>
+            <glx type="render" opcode="4134"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncSeparateEXT</name></proto>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>sfactorRGB</name></param>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>dfactorRGB</name></param>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>sfactorAlpha</name></param>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>dfactorAlpha</name></param>
+            <alias name="glBlendFuncSeparate"/>
+            <glx type="render" opcode="4134"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncSeparateINGR</name></proto>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>sfactorRGB</name></param>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>dfactorRGB</name></param>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>sfactorAlpha</name></param>
+            <param group="BlendFuncSeparateParameterEXT"><ptype>GLenum</ptype> <name>dfactorAlpha</name></param>
+            <alias name="glBlendFuncSeparate"/>
+            <glx type="render" opcode="4134"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncSeparateIndexedAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>srcRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>dstRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>srcAlpha</name></param>
+            <param><ptype>GLenum</ptype> <name>dstAlpha</name></param>
+            <alias name="glBlendFuncSeparatei"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncSeparateOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>srcRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>dstRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>srcAlpha</name></param>
+            <param><ptype>GLenum</ptype> <name>dstAlpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncSeparatei</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>srcRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>dstRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>srcAlpha</name></param>
+            <param><ptype>GLenum</ptype> <name>dstAlpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncSeparateiARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>srcRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>dstRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>srcAlpha</name></param>
+            <param><ptype>GLenum</ptype> <name>dstAlpha</name></param>
+            <alias name="glBlendFuncSeparatei"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncSeparateiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>srcRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>dstRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>srcAlpha</name></param>
+            <param><ptype>GLenum</ptype> <name>dstAlpha</name></param>
+            <alias name="glBlendFuncSeparatei"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFuncSeparateiOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>srcRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>dstRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>srcAlpha</name></param>
+            <param><ptype>GLenum</ptype> <name>dstAlpha</name></param>
+            <alias name="glBlendFuncSeparatei"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFunci</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>src</name></param>
+            <param><ptype>GLenum</ptype> <name>dst</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlendFunciARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>src</name></param>
+            <param><ptype>GLenum</ptype> <name>dst</name></param>
+            <alias name="glBlendFunci"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFunciEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>src</name></param>
+            <param><ptype>GLenum</ptype> <name>dst</name></param>
+            <alias name="glBlendFunci"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendFunciOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>src</name></param>
+            <param><ptype>GLenum</ptype> <name>dst</name></param>
+            <alias name="glBlendFunci"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendParameteriNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlitFramebuffer</name></proto>
+            <param><ptype>GLint</ptype> <name>srcX0</name></param>
+            <param><ptype>GLint</ptype> <name>srcY0</name></param>
+            <param><ptype>GLint</ptype> <name>srcX1</name></param>
+            <param><ptype>GLint</ptype> <name>srcY1</name></param>
+            <param><ptype>GLint</ptype> <name>dstX0</name></param>
+            <param><ptype>GLint</ptype> <name>dstY0</name></param>
+            <param><ptype>GLint</ptype> <name>dstX1</name></param>
+            <param><ptype>GLint</ptype> <name>dstY1</name></param>
+            <param group="ClearBufferMask"><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>filter</name></param>
+            <glx type="render" opcode="4330"/>
+        </command>
+        <command>
+            <proto>void <name>glBlitFramebufferANGLE</name></proto>
+            <param><ptype>GLint</ptype> <name>srcX0</name></param>
+            <param><ptype>GLint</ptype> <name>srcY0</name></param>
+            <param><ptype>GLint</ptype> <name>srcX1</name></param>
+            <param><ptype>GLint</ptype> <name>srcY1</name></param>
+            <param><ptype>GLint</ptype> <name>dstX0</name></param>
+            <param><ptype>GLint</ptype> <name>dstY0</name></param>
+            <param><ptype>GLint</ptype> <name>dstX1</name></param>
+            <param><ptype>GLint</ptype> <name>dstY1</name></param>
+            <param><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>filter</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBlitFramebufferEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>srcX0</name></param>
+            <param><ptype>GLint</ptype> <name>srcY0</name></param>
+            <param><ptype>GLint</ptype> <name>srcX1</name></param>
+            <param><ptype>GLint</ptype> <name>srcY1</name></param>
+            <param><ptype>GLint</ptype> <name>dstX0</name></param>
+            <param><ptype>GLint</ptype> <name>dstY0</name></param>
+            <param><ptype>GLint</ptype> <name>dstX1</name></param>
+            <param><ptype>GLint</ptype> <name>dstY1</name></param>
+            <param group="ClearBufferMask"><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>filter</name></param>
+            <alias name="glBlitFramebuffer"/>
+            <glx type="render" opcode="4330"/>
+        </command>
+        <command>
+            <proto>void <name>glBlitFramebufferNV</name></proto>
+            <param><ptype>GLint</ptype> <name>srcX0</name></param>
+            <param><ptype>GLint</ptype> <name>srcY0</name></param>
+            <param><ptype>GLint</ptype> <name>srcX1</name></param>
+            <param><ptype>GLint</ptype> <name>srcY1</name></param>
+            <param><ptype>GLint</ptype> <name>dstX0</name></param>
+            <param><ptype>GLint</ptype> <name>dstY0</name></param>
+            <param><ptype>GLint</ptype> <name>dstX1</name></param>
+            <param><ptype>GLint</ptype> <name>dstY1</name></param>
+            <param><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>filter</name></param>
+            <alias name="glBlitFramebuffer"/>
+        </command>
+        <command>
+            <proto>void <name>glBlitNamedFramebuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>readFramebuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>drawFramebuffer</name></param>
+            <param><ptype>GLint</ptype> <name>srcX0</name></param>
+            <param><ptype>GLint</ptype> <name>srcY0</name></param>
+            <param><ptype>GLint</ptype> <name>srcX1</name></param>
+            <param><ptype>GLint</ptype> <name>srcY1</name></param>
+            <param><ptype>GLint</ptype> <name>dstX0</name></param>
+            <param><ptype>GLint</ptype> <name>dstY0</name></param>
+            <param><ptype>GLint</ptype> <name>dstX1</name></param>
+            <param><ptype>GLint</ptype> <name>dstY1</name></param>
+            <param><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>filter</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBufferAddressRangeNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>address</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBufferData</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+            <param group="BufferUsageARB"><ptype>GLenum</ptype> <name>usage</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBufferDataARB</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferSizeARB"><ptype>GLsizeiptrARB</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+            <param group="BufferUsageARB"><ptype>GLenum</ptype> <name>usage</name></param>
+            <alias name="glBufferData"/>
+        </command>
+        <command>
+            <proto>void <name>glBufferPageCommitmentARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBufferParameteriAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBufferStorage</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBufferStorageEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+            <alias name="glBufferStorage"/>
+        </command>
+        <command>
+            <proto>void <name>glBufferSubData</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glBufferSubDataARB</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferOffsetARB"><ptype>GLintptrARB</ptype> <name>offset</name></param>
+            <param group="BufferSizeARB"><ptype>GLsizeiptrARB</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+            <alias name="glBufferSubData"/>
+        </command>
+        <command>
+            <proto>void <name>glCallCommandListNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCallList</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <glx type="render" opcode="1"/>
+        </command>
+        <command>
+            <proto>void <name>glCallLists</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="ListNameType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(n,type)">const void *<name>lists</name></param>
+            <glx type="render" opcode="2"/>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glCheckFramebufferStatus</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <glx type="vendor" opcode="1427"/>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glCheckFramebufferStatusEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <alias name="glCheckFramebufferStatus"/>
+            <glx type="vendor" opcode="1427"/>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glCheckFramebufferStatusOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glCheckNamedFramebufferStatus</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto group="FramebufferStatus"><ptype>GLenum</ptype> <name>glCheckNamedFramebufferStatusEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClampColor</name></proto>
+            <param group="ClampColorTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ClampColorModeARB"><ptype>GLenum</ptype> <name>clamp</name></param>
+            <glx type="render" opcode="234"/>
+        </command>
+        <command>
+            <proto>void <name>glClampColorARB</name></proto>
+            <param group="ClampColorTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ClampColorModeARB"><ptype>GLenum</ptype> <name>clamp</name></param>
+            <alias name="glClampColor"/>
+            <glx type="render" opcode="234"/>
+        </command>
+        <command>
+            <proto>void <name>glClear</name></proto>
+            <param group="ClearBufferMask"><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <glx type="render" opcode="127"/>
+        </command>
+        <command>
+            <proto>void <name>glClearAccum</name></proto>
+            <param><ptype>GLfloat</ptype> <name>red</name></param>
+            <param><ptype>GLfloat</ptype> <name>green</name></param>
+            <param><ptype>GLfloat</ptype> <name>blue</name></param>
+            <param><ptype>GLfloat</ptype> <name>alpha</name></param>
+            <glx type="render" opcode="128"/>
+        </command>
+        <command>
+            <proto>void <name>glClearAccumxOES</name></proto>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>red</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>green</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>blue</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>alpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearBufferData</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearBufferSubData</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearBufferfi</name></proto>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param group="DrawBufferName"><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param><ptype>GLfloat</ptype> <name>depth</name></param>
+            <param><ptype>GLint</ptype> <name>stencil</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearBufferfv</name></proto>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param group="DrawBufferName"><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param len="COMPSIZE(buffer)">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearBufferiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param group="DrawBufferName"><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param len="COMPSIZE(buffer)">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearBufferuiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param group="DrawBufferName"><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param len="COMPSIZE(buffer)">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearColor</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>red</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>green</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>blue</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>alpha</name></param>
+            <glx type="render" opcode="130"/>
+        </command>
+        <command>
+            <proto>void <name>glClearColorIiEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>red</name></param>
+            <param><ptype>GLint</ptype> <name>green</name></param>
+            <param><ptype>GLint</ptype> <name>blue</name></param>
+            <param><ptype>GLint</ptype> <name>alpha</name></param>
+            <glx type="render" opcode="4292"/>
+        </command>
+        <command>
+            <proto>void <name>glClearColorIuiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>red</name></param>
+            <param><ptype>GLuint</ptype> <name>green</name></param>
+            <param><ptype>GLuint</ptype> <name>blue</name></param>
+            <param><ptype>GLuint</ptype> <name>alpha</name></param>
+            <glx type="render" opcode="4293"/>
+        </command>
+        <command>
+            <proto>void <name>glClearColorx</name></proto>
+            <param><ptype>GLfixed</ptype> <name>red</name></param>
+            <param><ptype>GLfixed</ptype> <name>green</name></param>
+            <param><ptype>GLfixed</ptype> <name>blue</name></param>
+            <param><ptype>GLfixed</ptype> <name>alpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearColorxOES</name></proto>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>red</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>green</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>blue</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>alpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearDepth</name></proto>
+            <param><ptype>GLdouble</ptype> <name>depth</name></param>
+            <glx type="render" opcode="132"/>
+        </command>
+        <command>
+            <proto>void <name>glClearDepthdNV</name></proto>
+            <param><ptype>GLdouble</ptype> <name>depth</name></param>
+            <glx type="render" opcode="4284"/>
+        </command>
+        <command>
+            <proto>void <name>glClearDepthf</name></proto>
+            <param><ptype>GLfloat</ptype> <name>d</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearDepthfOES</name></proto>
+            <param group="ClampedFloat32"><ptype>GLclampf</ptype> <name>depth</name></param>
+            <glx type="render" opcode="4308"/>
+            <alias name="glClearDepthf"/>
+        </command>
+        <command>
+            <proto>void <name>glClearDepthx</name></proto>
+            <param><ptype>GLfixed</ptype> <name>depth</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearDepthxOES</name></proto>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>depth</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearIndex</name></proto>
+            <param group="MaskedColorIndexValueF"><ptype>GLfloat</ptype> <name>c</name></param>
+            <glx type="render" opcode="129"/>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedBufferData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedBufferDataEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedBufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedBufferSubDataEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedFramebufferfi</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param><ptype>GLfloat</ptype> <name>depth</name></param>
+            <param><ptype>GLint</ptype> <name>stencil</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedFramebufferfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedFramebufferiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param>const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedFramebufferuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearPixelLocalStorageuiEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>offset</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearStencil</name></proto>
+            <param group="StencilValue"><ptype>GLint</ptype> <name>s</name></param>
+            <glx type="render" opcode="131"/>
+        </command>
+        <command>
+            <proto>void <name>glClearTexImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearTexImageEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
+            <alias name="glClearTexImage"/>
+        </command>
+        <command>
+            <proto>void <name>glClearTexSubImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearTexSubImageEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
+            <alias name="glClearTexSubImage"/>
+        </command>
+        <command>
+            <proto>void <name>glClientActiveTexture</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texture</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClientActiveTextureARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texture</name></param>
+            <alias name="glClientActiveTexture"/>
+        </command>
+        <command>
+            <proto>void <name>glClientActiveVertexStreamATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClientAttribDefaultEXT</name></proto>
+            <param group="ClientAttribMask"><ptype>GLbitfield</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glClientWaitSync</name></proto>
+            <param group="sync"><ptype>GLsync</ptype> <name>sync</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+            <param><ptype>GLuint64</ptype> <name>timeout</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glClientWaitSyncAPPLE</name></proto>
+            <param><ptype>GLsync</ptype> <name>sync</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+            <param><ptype>GLuint64</ptype> <name>timeout</name></param>
+            <alias name="glClientWaitSync"/>
+        </command>
+        <command>
+            <proto>void <name>glClipControl</name></proto>
+            <param><ptype>GLenum</ptype> <name>origin</name></param>
+            <param><ptype>GLenum</ptype> <name>depth</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClipPlane</name></proto>
+            <param group="ClipPlaneName"><ptype>GLenum</ptype> <name>plane</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>equation</name></param>
+            <glx type="render" opcode="77"/>
+        </command>
+        <command>
+            <proto>void <name>glClipPlanef</name></proto>
+            <param><ptype>GLenum</ptype> <name>p</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>eqn</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClipPlanefIMG</name></proto>
+            <param><ptype>GLenum</ptype> <name>p</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>eqn</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClipPlanefOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>plane</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>equation</name></param>
+            <glx type="render" opcode="4312"/>
+        </command>
+        <command>
+            <proto>void <name>glClipPlanex</name></proto>
+            <param><ptype>GLenum</ptype> <name>plane</name></param>
+            <param len="4">const <ptype>GLfixed</ptype> *<name>equation</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClipPlanexIMG</name></proto>
+            <param><ptype>GLenum</ptype> <name>p</name></param>
+            <param len="4">const <ptype>GLfixed</ptype> *<name>eqn</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClipPlanexOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>plane</name></param>
+            <param len="4">const <ptype>GLfixed</ptype> *<name>equation</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor3b</name></proto>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>red</name></param>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>green</name></param>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>blue</name></param>
+            <vecequiv name="glColor3bv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3bv</name></proto>
+            <param group="ColorB" len="3">const <ptype>GLbyte</ptype> *<name>v</name></param>
+            <glx type="render" opcode="6"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3d</name></proto>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>red</name></param>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>green</name></param>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>blue</name></param>
+            <vecequiv name="glColor3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3dv</name></proto>
+            <param group="ColorD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="7"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3f</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>red</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>green</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>blue</name></param>
+            <vecequiv name="glColor3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3fVertex3fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>g</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor3fVertex3fvSUN</name></proto>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor3fv</name></proto>
+            <param group="ColorF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="8"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>red</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>green</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>blue</name></param>
+            <vecequiv name="glColor3hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3hvNV</name></proto>
+            <param group="Half16NV" len="3">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4244"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3i</name></proto>
+            <param group="ColorI"><ptype>GLint</ptype> <name>red</name></param>
+            <param group="ColorI"><ptype>GLint</ptype> <name>green</name></param>
+            <param group="ColorI"><ptype>GLint</ptype> <name>blue</name></param>
+            <vecequiv name="glColor3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3iv</name></proto>
+            <param group="ColorI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="9"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3s</name></proto>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>red</name></param>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>green</name></param>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>blue</name></param>
+            <vecequiv name="glColor3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3sv</name></proto>
+            <param group="ColorS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="10"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3ub</name></proto>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>red</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>green</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>blue</name></param>
+            <vecequiv name="glColor3ubv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3ubv</name></proto>
+            <param group="ColorUB" len="3">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <glx type="render" opcode="11"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3ui</name></proto>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>red</name></param>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>green</name></param>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>blue</name></param>
+            <vecequiv name="glColor3uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3uiv</name></proto>
+            <param group="ColorUI" len="3">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="12"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3us</name></proto>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>red</name></param>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>green</name></param>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>blue</name></param>
+            <vecequiv name="glColor3usv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3usv</name></proto>
+            <param group="ColorUS" len="3">const <ptype>GLushort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="13"/>
+        </command>
+        <command>
+            <proto>void <name>glColor3xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>red</name></param>
+            <param><ptype>GLfixed</ptype> <name>green</name></param>
+            <param><ptype>GLfixed</ptype> <name>blue</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor3xvOES</name></proto>
+            <param len="3">const <ptype>GLfixed</ptype> *<name>components</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor4b</name></proto>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>red</name></param>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>green</name></param>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>blue</name></param>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>alpha</name></param>
+            <vecequiv name="glColor4bv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4bv</name></proto>
+            <param group="ColorB" len="4">const <ptype>GLbyte</ptype> *<name>v</name></param>
+            <glx type="render" opcode="14"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4d</name></proto>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>red</name></param>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>green</name></param>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>blue</name></param>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>alpha</name></param>
+            <vecequiv name="glColor4dv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4dv</name></proto>
+            <param group="ColorD" len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="15"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4f</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>red</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>green</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>blue</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>alpha</name></param>
+            <vecequiv name="glColor4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4fNormal3fVertex3fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>g</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>a</name></param>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor4fNormal3fVertex3fvSUN</name></proto>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>n</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor4fv</name></proto>
+            <param group="ColorF" len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="16"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>red</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>green</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>blue</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>alpha</name></param>
+            <vecequiv name="glColor4hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4hvNV</name></proto>
+            <param group="Half16NV" len="4">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4245"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4i</name></proto>
+            <param group="ColorI"><ptype>GLint</ptype> <name>red</name></param>
+            <param group="ColorI"><ptype>GLint</ptype> <name>green</name></param>
+            <param group="ColorI"><ptype>GLint</ptype> <name>blue</name></param>
+            <param group="ColorI"><ptype>GLint</ptype> <name>alpha</name></param>
+            <vecequiv name="glColor4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4iv</name></proto>
+            <param group="ColorI" len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="17"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4s</name></proto>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>red</name></param>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>green</name></param>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>blue</name></param>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>alpha</name></param>
+            <vecequiv name="glColor4sv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4sv</name></proto>
+            <param group="ColorS" len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="18"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4ub</name></proto>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>red</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>green</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>blue</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>alpha</name></param>
+            <vecequiv name="glColor4ubv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4ubVertex2fSUN</name></proto>
+            <param><ptype>GLubyte</ptype> <name>r</name></param>
+            <param><ptype>GLubyte</ptype> <name>g</name></param>
+            <param><ptype>GLubyte</ptype> <name>b</name></param>
+            <param><ptype>GLubyte</ptype> <name>a</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor4ubVertex2fvSUN</name></proto>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>c</name></param>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor4ubVertex3fSUN</name></proto>
+            <param><ptype>GLubyte</ptype> <name>r</name></param>
+            <param><ptype>GLubyte</ptype> <name>g</name></param>
+            <param><ptype>GLubyte</ptype> <name>b</name></param>
+            <param><ptype>GLubyte</ptype> <name>a</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor4ubVertex3fvSUN</name></proto>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor4ubv</name></proto>
+            <param group="ColorUB" len="4">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <glx type="render" opcode="19"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4ui</name></proto>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>red</name></param>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>green</name></param>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>blue</name></param>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>alpha</name></param>
+            <vecequiv name="glColor4uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4uiv</name></proto>
+            <param group="ColorUI" len="4">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="20"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4us</name></proto>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>red</name></param>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>green</name></param>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>blue</name></param>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>alpha</name></param>
+            <vecequiv name="glColor4usv"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4usv</name></proto>
+            <param group="ColorUS" len="4">const <ptype>GLushort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="21"/>
+        </command>
+        <command>
+            <proto>void <name>glColor4x</name></proto>
+            <param><ptype>GLfixed</ptype> <name>red</name></param>
+            <param><ptype>GLfixed</ptype> <name>green</name></param>
+            <param><ptype>GLfixed</ptype> <name>blue</name></param>
+            <param><ptype>GLfixed</ptype> <name>alpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor4xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>red</name></param>
+            <param><ptype>GLfixed</ptype> <name>green</name></param>
+            <param><ptype>GLfixed</ptype> <name>blue</name></param>
+            <param><ptype>GLfixed</ptype> <name>alpha</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColor4xvOES</name></proto>
+            <param len="4">const <ptype>GLfixed</ptype> *<name>components</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorFormatNV</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorFragmentOp1ATI</name></proto>
+            <param group="FragmentOpATI"><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLuint</ptype> <name>dst</name></param>
+            <param><ptype>GLuint</ptype> <name>dstMask</name></param>
+            <param><ptype>GLuint</ptype> <name>dstMod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Mod</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorFragmentOp2ATI</name></proto>
+            <param group="FragmentOpATI"><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLuint</ptype> <name>dst</name></param>
+            <param><ptype>GLuint</ptype> <name>dstMask</name></param>
+            <param><ptype>GLuint</ptype> <name>dstMod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Mod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2Mod</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorFragmentOp3ATI</name></proto>
+            <param group="FragmentOpATI"><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLuint</ptype> <name>dst</name></param>
+            <param><ptype>GLuint</ptype> <name>dstMask</name></param>
+            <param><ptype>GLuint</ptype> <name>dstMod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1Mod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2Mod</name></param>
+            <param><ptype>GLuint</ptype> <name>arg3</name></param>
+            <param><ptype>GLuint</ptype> <name>arg3Rep</name></param>
+            <param><ptype>GLuint</ptype> <name>arg3Mod</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorMask</name></proto>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>red</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>green</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>blue</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>alpha</name></param>
+            <glx type="render" opcode="134"/>
+        </command>
+        <command>
+            <proto>void <name>glColorMaskIndexedEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>r</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>g</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>b</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>a</name></param>
+            <alias name="glColorMaski"/>
+        </command>
+        <command>
+            <proto>void <name>glColorMaski</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>r</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>g</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>b</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>a</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorMaskiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>r</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>g</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>b</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>a</name></param>
+            <alias name="glColorMaski"/>
+        </command>
+        <command>
+            <proto>void <name>glColorMaskiOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>r</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>g</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>b</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>a</name></param>
+            <alias name="glColorMaski"/>
+        </command>
+        <command>
+            <proto>void <name>glColorMaterial</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="ColorMaterialParameter"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="78"/>
+        </command>
+        <command>
+            <proto>void <name>glColorP3ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>color</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorP3uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>color</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorP4ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>color</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorP4uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>color</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorPointer</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="ColorPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorPointerEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="ColorPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(size,type,stride,count)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorPointerListIBM</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="ColorPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void **<name>pointer</name></param>
+            <param><ptype>GLint</ptype> <name>ptrstride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorPointervINTEL</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="4">const void **<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glColorSubTable</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,count)">const void *<name>data</name></param>
+            <glx type="render" opcode="195"/>
+            <glx type="render" opcode="312" name="glColorSubTablePBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glColorSubTableEXT</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,count)">const void *<name>data</name></param>
+            <alias name="glColorSubTable"/>
+        </command>
+        <command>
+            <proto>void <name>glColorTable</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>table</name></param>
+            <glx type="render" opcode="2053"/>
+            <glx type="render" opcode="313" name="glColorTablePBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glColorTableEXT</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalFormat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>table</name></param>
+            <alias name="glColorTable"/>
+        </command>
+        <command>
+            <proto>void <name>glColorTableParameterfv</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ColorTableParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="2054"/>
+        </command>
+        <command>
+            <proto>void <name>glColorTableParameterfvSGI</name></proto>
+            <param group="ColorTableTargetSGI"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ColorTableParameterPNameSGI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glColorTableParameterfv"/>
+            <glx type="render" opcode="2054"/>
+        </command>
+        <command>
+            <proto>void <name>glColorTableParameteriv</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ColorTableParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="2055"/>
+        </command>
+        <command>
+            <proto>void <name>glColorTableParameterivSGI</name></proto>
+            <param group="ColorTableTargetSGI"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ColorTableParameterPNameSGI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glColorTableParameteriv"/>
+            <glx type="render" opcode="2055"/>
+        </command>
+        <command>
+            <proto>void <name>glColorTableSGI</name></proto>
+            <param group="ColorTableTargetSGI"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>table</name></param>
+            <alias name="glColorTable"/>
+            <glx type="render" opcode="2053"/>
+        </command>
+        <command>
+            <proto>void <name>glCombinerInputNV</name></proto>
+            <param group="CombinerStageNV"><ptype>GLenum</ptype> <name>stage</name></param>
+            <param group="CombinerPortionNV"><ptype>GLenum</ptype> <name>portion</name></param>
+            <param group="CombinerVariableNV"><ptype>GLenum</ptype> <name>variable</name></param>
+            <param group="CombinerRegisterNV"><ptype>GLenum</ptype> <name>input</name></param>
+            <param group="CombinerMappingNV"><ptype>GLenum</ptype> <name>mapping</name></param>
+            <param group="CombinerComponentUsageNV"><ptype>GLenum</ptype> <name>componentUsage</name></param>
+            <glx type="render" opcode="4140"/>
+        </command>
+        <command>
+            <proto>void <name>glCombinerOutputNV</name></proto>
+            <param group="CombinerStageNV"><ptype>GLenum</ptype> <name>stage</name></param>
+            <param group="CombinerPortionNV"><ptype>GLenum</ptype> <name>portion</name></param>
+            <param group="CombinerRegisterNV"><ptype>GLenum</ptype> <name>abOutput</name></param>
+            <param group="CombinerRegisterNV"><ptype>GLenum</ptype> <name>cdOutput</name></param>
+            <param group="CombinerRegisterNV"><ptype>GLenum</ptype> <name>sumOutput</name></param>
+            <param group="CombinerScaleNV"><ptype>GLenum</ptype> <name>scale</name></param>
+            <param group="CombinerBiasNV"><ptype>GLenum</ptype> <name>bias</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>abDotProduct</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>cdDotProduct</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>muxSum</name></param>
+            <glx type="render" opcode="4141"/>
+        </command>
+        <command>
+            <proto>void <name>glCombinerParameterfNV</name></proto>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="4136"/>
+        </command>
+        <command>
+            <proto>void <name>glCombinerParameterfvNV</name></proto>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="4137"/>
+        </command>
+        <command>
+            <proto>void <name>glCombinerParameteriNV</name></proto>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="4138"/>
+        </command>
+        <command>
+            <proto>void <name>glCombinerParameterivNV</name></proto>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="4139"/>
+        </command>
+        <command>
+            <proto>void <name>glCombinerStageParameterfvNV</name></proto>
+            <param group="CombinerStageNV"><ptype>GLenum</ptype> <name>stage</name></param>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCommandListSegmentsNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+            <param><ptype>GLuint</ptype> <name>segments</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompileCommandListNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompileShader</name></proto>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompileShaderARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>shaderObj</name></param>
+            <alias name="glCompileShader"/>
+        </command>
+        <command>
+            <proto>void <name>glCompileShaderIncludeARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLchar</ptype> *const*<name>path</name></param>
+            <param len="count">const <ptype>GLint</ptype> *<name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedMultiTexImage1DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedMultiTexImage2DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedMultiTexImage3DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedMultiTexSubImage1DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedMultiTexSubImage2DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedMultiTexSubImage3DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexImage1D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <glx type="render" opcode="214"/>
+            <glx type="render" opcode="314" name="glCompressedTexImage1DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexImage1DARB</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <alias name="glCompressedTexImage1D"/>
+            <glx type="render" opcode="214"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexImage2D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <glx type="render" opcode="215"/>
+            <glx type="render" opcode="315" name="glCompressedTexImage2DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexImage2DARB</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <alias name="glCompressedTexImage2D"/>
+            <glx type="render" opcode="215"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexImage3D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <glx type="render" opcode="216"/>
+            <glx type="render" opcode="316" name="glCompressedTexImage3DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexImage3DARB</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <alias name="glCompressedTexImage3D"/>
+            <glx type="render" opcode="216"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexImage3DOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>data</name></param>
+            <alias name="glCompressedTexImage3D"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexSubImage1D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <glx type="render" opcode="217"/>
+            <glx type="render" opcode="317" name="glCompressedTexSubImage1DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexSubImage1DARB</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <alias name="glCompressedTexSubImage1D"/>
+            <glx type="render" opcode="217"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexSubImage2D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <glx type="render" opcode="218"/>
+            <glx type="render" opcode="318" name="glCompressedTexSubImage2DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexSubImage2DARB</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <alias name="glCompressedTexSubImage2D"/>
+            <glx type="render" opcode="218"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexSubImage3D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <glx type="render" opcode="219"/>
+            <glx type="render" opcode="319" name="glCompressedTexSubImage3DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexSubImage3DARB</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param group="CompressedTextureARB" len="imageSize">const void *<name>data</name></param>
+            <alias name="glCompressedTexSubImage3D"/>
+            <glx type="render" opcode="219"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTexSubImage3DOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>data</name></param>
+            <alias name="glCompressedTexSubImage3D"/>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTextureImage1DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTextureImage2DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTextureImage3DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTextureSubImage1D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTextureSubImage1DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTextureSubImage2D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTextureSubImage2DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTextureSubImage3D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompressedTextureSubImage3DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param len="imageSize">const void *<name>bits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glConservativeRasterParameterfNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glConservativeRasterParameteriNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionFilter1D</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>image</name></param>
+            <glx type="render" opcode="4101"/>
+            <glx type="render" opcode="320" name="glConvolutionFilter1DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionFilter1DEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>image</name></param>
+            <alias name="glConvolutionFilter1D"/>
+            <glx type="render" opcode="4101"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionFilter2D</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>image</name></param>
+            <glx type="render" opcode="4102"/>
+            <glx type="render" opcode="321" name="glConvolutionFilter2DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionFilter2DEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>image</name></param>
+            <alias name="glConvolutionFilter2D"/>
+            <glx type="render" opcode="4102"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameterf</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>params</name></param>
+            <glx type="render" opcode="4103"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameterfEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameterEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>params</name></param>
+            <alias name="glConvolutionParameterf"/>
+            <glx type="render" opcode="4103"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameterfv</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="4104"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameterfvEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameterEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glConvolutionParameterfv"/>
+            <glx type="render" opcode="4104"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameteri</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>params</name></param>
+            <glx type="render" opcode="4105"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameteriEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameterEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>params</name></param>
+            <alias name="glConvolutionParameteri"/>
+            <glx type="render" opcode="4105"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameteriv</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="4106"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameterivEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameterEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glConvolutionParameteriv"/>
+            <glx type="render" opcode="4106"/>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameterxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glConvolutionParameterxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyBufferSubData</name></proto>
+            <param><ptype>GLenum</ptype> <name>readTarget</name></param>
+            <param><ptype>GLenum</ptype> <name>writeTarget</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>readOffset</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>writeOffset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyBufferSubDataNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>readTarget</name></param>
+            <param><ptype>GLenum</ptype> <name>writeTarget</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>readOffset</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>writeOffset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <alias name="glCopyBufferSubData"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyColorSubTable</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>start</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <glx type="render" opcode="196"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyColorSubTableEXT</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>start</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <alias name="glCopyColorSubTable"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyColorTable</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <glx type="render" opcode="2056"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyColorTableSGI</name></proto>
+            <param group="ColorTableTargetSGI"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <alias name="glCopyColorTable"/>
+            <glx type="render" opcode="2056"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyConvolutionFilter1D</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <glx type="render" opcode="4107"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyConvolutionFilter1DEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <alias name="glCopyConvolutionFilter1D"/>
+            <glx type="render" opcode="4107"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyConvolutionFilter2D</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <glx type="render" opcode="4108"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyConvolutionFilter2DEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glCopyConvolutionFilter2D"/>
+            <glx type="render" opcode="4108"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyImageSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>srcName</name></param>
+            <param><ptype>GLenum</ptype> <name>srcTarget</name></param>
+            <param><ptype>GLint</ptype> <name>srcLevel</name></param>
+            <param><ptype>GLint</ptype> <name>srcX</name></param>
+            <param><ptype>GLint</ptype> <name>srcY</name></param>
+            <param><ptype>GLint</ptype> <name>srcZ</name></param>
+            <param><ptype>GLuint</ptype> <name>dstName</name></param>
+            <param><ptype>GLenum</ptype> <name>dstTarget</name></param>
+            <param><ptype>GLint</ptype> <name>dstLevel</name></param>
+            <param><ptype>GLint</ptype> <name>dstX</name></param>
+            <param><ptype>GLint</ptype> <name>dstY</name></param>
+            <param><ptype>GLint</ptype> <name>dstZ</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcWidth</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcHeight</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcDepth</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyImageSubDataEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>srcName</name></param>
+            <param><ptype>GLenum</ptype> <name>srcTarget</name></param>
+            <param><ptype>GLint</ptype> <name>srcLevel</name></param>
+            <param><ptype>GLint</ptype> <name>srcX</name></param>
+            <param><ptype>GLint</ptype> <name>srcY</name></param>
+            <param><ptype>GLint</ptype> <name>srcZ</name></param>
+            <param><ptype>GLuint</ptype> <name>dstName</name></param>
+            <param><ptype>GLenum</ptype> <name>dstTarget</name></param>
+            <param><ptype>GLint</ptype> <name>dstLevel</name></param>
+            <param><ptype>GLint</ptype> <name>dstX</name></param>
+            <param><ptype>GLint</ptype> <name>dstY</name></param>
+            <param><ptype>GLint</ptype> <name>dstZ</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcWidth</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcHeight</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcDepth</name></param>
+            <alias name="glCopyImageSubData"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyImageSubDataNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>srcName</name></param>
+            <param><ptype>GLenum</ptype> <name>srcTarget</name></param>
+            <param><ptype>GLint</ptype> <name>srcLevel</name></param>
+            <param><ptype>GLint</ptype> <name>srcX</name></param>
+            <param><ptype>GLint</ptype> <name>srcY</name></param>
+            <param><ptype>GLint</ptype> <name>srcZ</name></param>
+            <param><ptype>GLuint</ptype> <name>dstName</name></param>
+            <param><ptype>GLenum</ptype> <name>dstTarget</name></param>
+            <param><ptype>GLint</ptype> <name>dstLevel</name></param>
+            <param><ptype>GLint</ptype> <name>dstX</name></param>
+            <param><ptype>GLint</ptype> <name>dstY</name></param>
+            <param><ptype>GLint</ptype> <name>dstZ</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <glx type="render" opcode="4291"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyImageSubDataOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>srcName</name></param>
+            <param><ptype>GLenum</ptype> <name>srcTarget</name></param>
+            <param><ptype>GLint</ptype> <name>srcLevel</name></param>
+            <param><ptype>GLint</ptype> <name>srcX</name></param>
+            <param><ptype>GLint</ptype> <name>srcY</name></param>
+            <param><ptype>GLint</ptype> <name>srcZ</name></param>
+            <param><ptype>GLuint</ptype> <name>dstName</name></param>
+            <param><ptype>GLenum</ptype> <name>dstTarget</name></param>
+            <param><ptype>GLint</ptype> <name>dstLevel</name></param>
+            <param><ptype>GLint</ptype> <name>dstX</name></param>
+            <param><ptype>GLint</ptype> <name>dstY</name></param>
+            <param><ptype>GLint</ptype> <name>dstZ</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcWidth</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcHeight</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcDepth</name></param>
+            <alias name="glCopyImageSubData"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyMultiTexImage1DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyMultiTexImage2DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyMultiTexSubImage1DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyMultiTexSubImage2DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyMultiTexSubImage3DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyNamedBufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>readBuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>writeBuffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>readOffset</name></param>
+            <param><ptype>GLintptr</ptype> <name>writeOffset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyPathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>resultPath</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>srcPath</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyPixels</name></proto>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelCopyType"><ptype>GLenum</ptype> <name>type</name></param>
+            <glx type="render" opcode="172"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexImage1D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <glx type="render" opcode="4119"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexImage1DEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <alias name="glCopyTexImage1D"/>
+            <glx type="render" opcode="4119"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexImage2D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <glx type="render" opcode="4120"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexImage2DEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <alias name="glCopyTexImage2D"/>
+            <glx type="render" opcode="4120"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexSubImage1D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <glx type="render" opcode="4121"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexSubImage1DEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <alias name="glCopyTexSubImage1D"/>
+            <glx type="render" opcode="4121"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexSubImage2D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <glx type="render" opcode="4122"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexSubImage2DEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glCopyTexSubImage2D"/>
+            <glx type="render" opcode="4122"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexSubImage3D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <glx type="render" opcode="4123"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexSubImage3DEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glCopyTexSubImage3D"/>
+            <glx type="render" opcode="4123"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTexSubImage3DOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glCopyTexSubImage3D"/>
+        </command>
+        <command>
+            <proto>void <name>glCopyTextureImage1DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyTextureImage2DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyTextureLevelsAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>destinationTexture</name></param>
+            <param><ptype>GLuint</ptype> <name>sourceTexture</name></param>
+            <param><ptype>GLint</ptype> <name>sourceBaseLevel</name></param>
+            <param><ptype>GLsizei</ptype> <name>sourceLevelCount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyTextureSubImage1D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyTextureSubImage1DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyTextureSubImage2D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyTextureSubImage2DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyTextureSubImage3D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCopyTextureSubImage3DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCoverFillPathInstancedNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param group="PathElementType"><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param group="PathElement" len="COMPSIZE(numPaths,pathNameType,paths)">const void *<name>paths</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param group="PathCoverMode"><ptype>GLenum</ptype> <name>coverMode</name></param>
+            <param group="PathTransformType"><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param len="COMPSIZE(numPaths,transformType)">const <ptype>GLfloat</ptype> *<name>transformValues</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCoverFillPathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathCoverMode"><ptype>GLenum</ptype> <name>coverMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCoverStrokePathInstancedNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param group="PathElementType"><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param group="PathElement" len="COMPSIZE(numPaths,pathNameType,paths)">const void *<name>paths</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param group="PathCoverMode"><ptype>GLenum</ptype> <name>coverMode</name></param>
+            <param group="PathTransformType"><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param len="COMPSIZE(numPaths,transformType)">const <ptype>GLfloat</ptype> *<name>transformValues</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCoverStrokePathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathCoverMode"><ptype>GLenum</ptype> <name>coverMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCoverageMaskNV</name></proto>
+            <param><ptype>GLboolean</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCoverageModulationNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>components</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCoverageModulationTableNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCoverageOperationNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>operation</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateBuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>buffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateCommandListsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>lists</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateFramebuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>framebuffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreatePerfQueryINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>queryId</name></param>
+            <param><ptype>GLuint</ptype> *<name>queryHandle</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glCreateProgram</name></proto>
+        </command>
+        <command>
+            <proto group="handleARB"><ptype>GLhandleARB</ptype> <name>glCreateProgramObjectARB</name></proto>
+            <alias name="glCreateProgram"/>
+        </command>
+        <command>
+            <proto>void <name>glCreateProgramPipelines</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>pipelines</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateQueries</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateRenderbuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>renderbuffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateSamplers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>samplers</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glCreateShader</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+        </command>
+        <command>
+            <proto group="handleARB"><ptype>GLhandleARB</ptype> <name>glCreateShaderObjectARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>shaderType</name></param>
+            <alias name="glCreateShader"/>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glCreateShaderProgramEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>string</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glCreateShaderProgramv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLchar</ptype> *const*<name>strings</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glCreateShaderProgramvEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLchar</ptype> **<name>strings</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateStatesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>states</name></param>
+        </command>
+        <command>
+            <proto group="sync"><ptype>GLsync</ptype> <name>glCreateSyncFromCLeventARB</name></proto>
+            <param group="cl_context"><ptype>struct _cl_context</ptype> *<name>context</name></param>
+            <param group="cl_event"><ptype>struct _cl_event</ptype> *<name>event</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateTextures</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>textures</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateTransformFeedbacks</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateVertexArrays</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>arrays</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCullFace</name></proto>
+            <param group="CullFaceMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="79"/>
+        </command>
+        <command>
+            <proto>void <name>glCullParameterdvEXT</name></proto>
+            <param group="CullParameterEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCullParameterfvEXT</name></proto>
+            <param group="CullParameterEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCurrentPaletteMatrixARB</name></proto>
+            <param><ptype>GLint</ptype> <name>index</name></param>
+            <glx type="render" opcode="4329"/>
+        </command>
+        <command>
+            <proto>void <name>glCurrentPaletteMatrixOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>matrixpaletteindex</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageCallback</name></proto>
+            <param><ptype>GLDEBUGPROC</ptype> <name>callback</name></param>
+            <param>const void *<name>userParam</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageCallbackAMD</name></proto>
+            <param><ptype>GLDEBUGPROCAMD</ptype> <name>callback</name></param>
+            <param>void *<name>userParam</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageCallbackARB</name></proto>
+            <param><ptype>GLDEBUGPROCARB</ptype> <name>callback</name></param>
+            <param len="COMPSIZE(callback)">const void *<name>userParam</name></param>
+            <alias name="glDebugMessageCallback"/>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageCallbackKHR</name></proto>
+            <param><ptype>GLDEBUGPROCKHR</ptype> <name>callback</name></param>
+            <param>const void *<name>userParam</name></param>
+            <alias name="glDebugMessageCallback"/>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageControl</name></proto>
+            <param><ptype>GLenum</ptype> <name>source</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLenum</ptype> <name>severity</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>ids</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>enabled</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageControlARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>source</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLenum</ptype> <name>severity</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>ids</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>enabled</name></param>
+            <alias name="glDebugMessageControl"/>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageControlKHR</name></proto>
+            <param><ptype>GLenum</ptype> <name>source</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLenum</ptype> <name>severity</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>ids</name></param>
+            <param><ptype>GLboolean</ptype> <name>enabled</name></param>
+            <alias name="glDebugMessageControl"/>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageEnableAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>category</name></param>
+            <param><ptype>GLenum</ptype> <name>severity</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>ids</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>enabled</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageInsert</name></proto>
+            <param><ptype>GLenum</ptype> <name>source</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>severity</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="COMPSIZE(buf,length)">const <ptype>GLchar</ptype> *<name>buf</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageInsertAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>category</name></param>
+            <param><ptype>GLenum</ptype> <name>severity</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="length">const <ptype>GLchar</ptype> *<name>buf</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageInsertARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>source</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>severity</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="length">const <ptype>GLchar</ptype> *<name>buf</name></param>
+            <alias name="glDebugMessageInsert"/>
+        </command>
+        <command>
+            <proto>void <name>glDebugMessageInsertKHR</name></proto>
+            <param><ptype>GLenum</ptype> <name>source</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>severity</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>buf</name></param>
+            <alias name="glDebugMessageInsert"/>
+        </command>
+        <command>
+            <proto>void <name>glDeformSGIX</name></proto>
+            <param group="FfdMaskSGIX"><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <glx type="render" opcode="2075"/>
+        </command>
+        <command>
+            <proto>void <name>glDeformationMap3dSGIX</name></proto>
+            <param group="FfdTargetSGIX"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>ustride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>uorder</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>v1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>vstride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>vorder</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>w1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>w2</name></param>
+            <param><ptype>GLint</ptype> <name>wstride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>worder</name></param>
+            <param group="CoordD" len="COMPSIZE(target,ustride,uorder,vstride,vorder,wstride,worder)">const <ptype>GLdouble</ptype> *<name>points</name></param>
+            <glx type="render" opcode="2073"/>
+        </command>
+        <command>
+            <proto>void <name>glDeformationMap3fSGIX</name></proto>
+            <param group="FfdTargetSGIX"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>ustride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>uorder</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>vstride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>vorder</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>w1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>w2</name></param>
+            <param><ptype>GLint</ptype> <name>wstride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>worder</name></param>
+            <param group="CoordF" len="COMPSIZE(target,ustride,uorder,vstride,vorder,wstride,worder)">const <ptype>GLfloat</ptype> *<name>points</name></param>
+            <glx type="render" opcode="2074"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteAsyncMarkersSGIX</name></proto>
+            <param><ptype>GLuint</ptype> <name>marker</name></param>
+            <param><ptype>GLsizei</ptype> <name>range</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteBuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>buffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteBuffersARB</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>buffers</name></param>
+            <alias name="glDeleteBuffers"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteCommandListsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>lists</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteFencesAPPLE</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="FenceNV" len="n">const <ptype>GLuint</ptype> *<name>fences</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteFencesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="FenceNV" len="n">const <ptype>GLuint</ptype> *<name>fences</name></param>
+            <glx type="vendor" opcode="1276"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteFragmentShaderATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteFramebuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>framebuffers</name></param>
+            <glx type="render" opcode="4320"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteFramebuffersEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>framebuffers</name></param>
+            <alias name="glDeleteFramebuffers"/>
+            <glx type="render" opcode="4320"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteFramebuffersOES</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>framebuffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteLists</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <param><ptype>GLsizei</ptype> <name>range</name></param>
+            <glx type="single" opcode="103"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteNamedStringARB</name></proto>
+            <param><ptype>GLint</ptype> <name>namelen</name></param>
+            <param len="namelen">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteNamesAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>identifier</name></param>
+            <param><ptype>GLuint</ptype> <name>num</name></param>
+            <param len="num">const <ptype>GLuint</ptype> *<name>names</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteObjectARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>obj</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteOcclusionQueriesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeletePathsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLsizei</ptype> <name>range</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeletePerfMonitorsAMD</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>monitors</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeletePerfQueryINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>queryHandle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteProgram</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <glx type="single" opcode="202"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteProgramPipelines</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>pipelines</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteProgramPipelinesEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>pipelines</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteProgramsARB</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>programs</name></param>
+            <glx type="vendor" opcode="1294"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteProgramsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>programs</name></param>
+            <alias name="glDeleteProgramsARB"/>
+            <glx type="vendor" opcode="1294"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteQueries</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>ids</name></param>
+            <glx type="single" opcode="161"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteQueriesARB</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>ids</name></param>
+            <alias name="glDeleteQueries"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteQueriesEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteRenderbuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>renderbuffers</name></param>
+            <glx type="render" opcode="4317"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteRenderbuffersEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>renderbuffers</name></param>
+            <alias name="glDeleteRenderbuffers"/>
+            <glx type="render" opcode="4317"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteRenderbuffersOES</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>renderbuffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteSamplers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>samplers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteShader</name></proto>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+            <glx type="single" opcode="195"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteStatesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>states</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteSync</name></proto>
+            <param group="sync"><ptype>GLsync</ptype> <name>sync</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteSyncAPPLE</name></proto>
+            <param><ptype>GLsync</ptype> <name>sync</name></param>
+            <alias name="glDeleteSync"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteTextures</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Texture" len="n">const <ptype>GLuint</ptype> *<name>textures</name></param>
+            <glx type="single" opcode="144"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteTexturesEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Texture" len="n">const <ptype>GLuint</ptype> *<name>textures</name></param>
+            <glx type="vendor" opcode="12"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteTransformFeedbacks</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDeleteTransformFeedbacksNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>ids</name></param>
+            <alias name="glDeleteTransformFeedbacks"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteVertexArrays</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>arrays</name></param>
+            <glx type="render" opcode="351"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteVertexArraysAPPLE</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>arrays</name></param>
+            <alias name="glDeleteVertexArrays"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteVertexArraysOES</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>arrays</name></param>
+            <alias name="glDeleteVertexArrays"/>
+        </command>
+        <command>
+            <proto>void <name>glDeleteVertexShaderEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDepthBoundsEXT</name></proto>
+            <param group="ClampedFloat64"><ptype>GLclampd</ptype> <name>zmin</name></param>
+            <param group="ClampedFloat64"><ptype>GLclampd</ptype> <name>zmax</name></param>
+            <glx type="render" opcode="4229"/>
+        </command>
+        <command>
+            <proto>void <name>glDepthBoundsdNV</name></proto>
+            <param><ptype>GLdouble</ptype> <name>zmin</name></param>
+            <param><ptype>GLdouble</ptype> <name>zmax</name></param>
+            <glx type="render" opcode="4285"/>
+        </command>
+        <command>
+            <proto>void <name>glDepthFunc</name></proto>
+            <param group="DepthFunction"><ptype>GLenum</ptype> <name>func</name></param>
+            <glx type="render" opcode="164"/>
+        </command>
+        <command>
+            <proto>void <name>glDepthMask</name></proto>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>flag</name></param>
+            <glx type="render" opcode="135"/>
+        </command>
+        <command>
+            <proto>void <name>glDepthRange</name></proto>
+            <param><ptype>GLdouble</ptype> <name>near</name></param>
+            <param><ptype>GLdouble</ptype> <name>far</name></param>
+            <glx type="render" opcode="174"/>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangeArrayfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangeArrayfvOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangeArrayv</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangeIndexed</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>n</name></param>
+            <param><ptype>GLdouble</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangeIndexedfNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>n</name></param>
+            <param><ptype>GLfloat</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangeIndexedfOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>n</name></param>
+            <param><ptype>GLfloat</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangedNV</name></proto>
+            <param><ptype>GLdouble</ptype> <name>zNear</name></param>
+            <param><ptype>GLdouble</ptype> <name>zFar</name></param>
+            <glx type="render" opcode="4283"/>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangef</name></proto>
+            <param><ptype>GLfloat</ptype> <name>n</name></param>
+            <param><ptype>GLfloat</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangefOES</name></proto>
+            <param group="ClampedFloat32"><ptype>GLclampf</ptype> <name>n</name></param>
+            <param group="ClampedFloat32"><ptype>GLclampf</ptype> <name>f</name></param>
+            <glx type="render" opcode="4309"/>
+            <alias name="glDepthRangef"/>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangex</name></proto>
+            <param><ptype>GLfixed</ptype> <name>n</name></param>
+            <param><ptype>GLfixed</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDepthRangexOES</name></proto>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>n</name></param>
+            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDetachObjectARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>containerObj</name></param>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>attachedObj</name></param>
+            <alias name="glDetachShader"/>
+        </command>
+        <command>
+            <proto>void <name>glDetachShader</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDetailTexFuncSGIS</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n*2">const <ptype>GLfloat</ptype> *<name>points</name></param>
+            <glx type="render" opcode="2051"/>
+        </command>
+        <command>
+            <proto>void <name>glDisable</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>cap</name></param>
+            <glx type="render" opcode="138"/>
+        </command>
+        <command>
+            <proto>void <name>glDisableClientState</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableClientStateIndexedEXT</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableClientStateiEXT</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableDriverControlQCOM</name></proto>
+            <param><ptype>GLuint</ptype> <name>driverControl</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableIndexedEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glDisablei"/>
+        </command>
+        <command>
+            <proto>void <name>glDisableVariantClientStateEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableVertexArrayAttrib</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableVertexArrayAttribEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableVertexArrayEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableVertexAttribAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableVertexAttribArray</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableVertexAttribArrayARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glDisableVertexAttribArray"/>
+        </command>
+        <command>
+            <proto>void <name>glDisablei</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDisableiEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glDisablei"/>
+        </command>
+        <command>
+            <proto>void <name>glDisableiNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glDisablei"/>
+        </command>
+        <command>
+            <proto>void <name>glDisableiOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glDisablei"/>
+        </command>
+        <command>
+            <proto>void <name>glDiscardFramebufferEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>numAttachments</name></param>
+            <param len="numAttachments">const <ptype>GLenum</ptype> *<name>attachments</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDispatchCompute</name></proto>
+            <param><ptype>GLuint</ptype> <name>num_groups_x</name></param>
+            <param><ptype>GLuint</ptype> <name>num_groups_y</name></param>
+            <param><ptype>GLuint</ptype> <name>num_groups_z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDispatchComputeGroupSizeARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>num_groups_x</name></param>
+            <param><ptype>GLuint</ptype> <name>num_groups_y</name></param>
+            <param><ptype>GLuint</ptype> <name>num_groups_z</name></param>
+            <param><ptype>GLuint</ptype> <name>group_size_x</name></param>
+            <param><ptype>GLuint</ptype> <name>group_size_y</name></param>
+            <param><ptype>GLuint</ptype> <name>group_size_z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDispatchComputeIndirect</name></proto>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>indirect</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawArrays</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <glx type="render" opcode="193"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawArraysEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <alias name="glDrawArrays"/>
+            <glx type="render" opcode="4116"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawArraysIndirect</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param>const void *<name>indirect</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawArraysInstanced</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawArraysInstancedANGLE</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glDrawArraysInstanced"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawArraysInstancedARB</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glDrawArraysInstanced"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawArraysInstancedBaseInstance</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawArraysInstancedBaseInstanceEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
+            <alias name="glDrawArraysInstancedBaseInstance"/>
+        </command>
+        <command comment="primcount should be renamed to instanceCount for OpenGL ES">
+            <proto>void <name>glDrawArraysInstancedEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glDrawArraysInstanced"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawArraysInstancedNV</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glDrawArraysInstanced"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawBuffer</name></proto>
+            <param group="DrawBufferMode"><ptype>GLenum</ptype> <name>buf</name></param>
+            <glx type="render" opcode="126"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawBuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="DrawBufferModeATI" len="n">const <ptype>GLenum</ptype> *<name>bufs</name></param>
+            <glx type="render" opcode="233"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawBuffersARB</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="DrawBufferModeATI" len="n">const <ptype>GLenum</ptype> *<name>bufs</name></param>
+            <alias name="glDrawBuffers"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawBuffersATI</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="DrawBufferModeATI" len="n">const <ptype>GLenum</ptype> *<name>bufs</name></param>
+            <alias name="glDrawBuffers"/>
+            <glx type="render" opcode="233"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawBuffersEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLenum</ptype> *<name>bufs</name></param>
+            <alias name="glDrawBuffers"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawBuffersIndexedEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLenum</ptype> *<name>location</name></param>
+            <param len="n">const <ptype>GLint</ptype> *<name>indices</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawBuffersNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLenum</ptype> *<name>bufs</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawCommandsAddressNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>primitiveMode</name></param>
+            <param>const <ptype>GLuint64</ptype> *<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawCommandsNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>primitiveMode</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param>const <ptype>GLintptr</ptype> *<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawCommandsStatesAddressNV</name></proto>
+            <param>const <ptype>GLuint64</ptype> *<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>states</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>fbos</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawCommandsStatesNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param>const <ptype>GLintptr</ptype> *<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>states</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>fbos</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementArrayAPPLE</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementArrayATI</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElements</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsBaseVertex</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsBaseVertexEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawElementsBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsBaseVertexOES</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawElementsBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsIndirect</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>indirect</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstanced</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedANGLE</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glDrawElementsInstanced"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedARB</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glDrawElementsInstanced"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseInstance</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="count">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseInstanceEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="count">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
+            <alias name="glDrawElementsInstancedBaseInstance"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseVertex</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseVertexBaseInstance</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="count">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseVertexBaseInstanceEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="count">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
+            <alias name="glDrawElementsInstancedBaseVertexBaseInstance"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseVertexEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawElementsInstancedBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseVertexOES</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawElementsInstancedBaseVertex"/>
+        </command>
+        <command comment="primcount should be renamed to instanceCount for OpenGL ES">
+            <proto>void <name>glDrawElementsInstancedEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glDrawElementsInstanced"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedNV</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glDrawElementsInstanced"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawMeshArraysSUN</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawPixels</name></proto>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>pixels</name></param>
+            <glx type="render" opcode="173"/>
+            <glx type="render" opcode="322" name="glDrawPixelsPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawRangeElementArrayAPPLE</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawRangeElementArrayATI</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawRangeElements</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawRangeElementsBaseVertex</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawRangeElementsBaseVertexEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawRangeElementsBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawRangeElementsBaseVertexOES</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawRangeElementsBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawRangeElementsEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <alias name="glDrawRangeElements"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawTexfOES</name></proto>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>width</name></param>
+            <param><ptype>GLfloat</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTexfvOES</name></proto>
+            <param>const <ptype>GLfloat</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTexiOES</name></proto>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+            <param><ptype>GLint</ptype> <name>width</name></param>
+            <param><ptype>GLint</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTexivOES</name></proto>
+            <param>const <ptype>GLint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTexsOES</name></proto>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <param><ptype>GLshort</ptype> <name>z</name></param>
+            <param><ptype>GLshort</ptype> <name>width</name></param>
+            <param><ptype>GLshort</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTexsvOES</name></proto>
+            <param>const <ptype>GLshort</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTextureNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLfloat</ptype> <name>x0</name></param>
+            <param><ptype>GLfloat</ptype> <name>y0</name></param>
+            <param><ptype>GLfloat</ptype> <name>x1</name></param>
+            <param><ptype>GLfloat</ptype> <name>y1</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>s0</name></param>
+            <param><ptype>GLfloat</ptype> <name>t0</name></param>
+            <param><ptype>GLfloat</ptype> <name>s1</name></param>
+            <param><ptype>GLfloat</ptype> <name>t1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTexxOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+            <param><ptype>GLfixed</ptype> <name>width</name></param>
+            <param><ptype>GLfixed</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTexxvOES</name></proto>
+            <param>const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTransformFeedback</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTransformFeedbackEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <alias name="glDrawTransformFeedback"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawTransformFeedbackInstanced</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTransformFeedbackInstancedEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <alias name="glDrawTransformFeedbackInstanced"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawTransformFeedbackNV</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <alias name="glDrawTransformFeedback"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawTransformFeedbackStream</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawTransformFeedbackStreamInstanced</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEGLImageTargetRenderbufferStorageOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLeglImageOES</ptype> <name>image</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEGLImageTargetTexture2DOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLeglImageOES</ptype> <name>image</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEdgeFlag</name></proto>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>flag</name></param>
+            <vecequiv name="glEdgeFlagv"/>
+        </command>
+        <command>
+            <proto>void <name>glEdgeFlagFormatNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEdgeFlagPointer</name></proto>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEdgeFlagPointerEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean" len="COMPSIZE(stride,count)">const <ptype>GLboolean</ptype> *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEdgeFlagPointerListIBM</name></proto>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param group="BooleanPointer" len="COMPSIZE(stride)">const <ptype>GLboolean</ptype> **<name>pointer</name></param>
+            <param><ptype>GLint</ptype> <name>ptrstride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEdgeFlagv</name></proto>
+            <param group="Boolean" len="1">const <ptype>GLboolean</ptype> *<name>flag</name></param>
+            <glx type="render" opcode="22"/>
+        </command>
+        <command>
+            <proto>void <name>glElementPointerAPPLE</name></proto>
+            <param group="ElementPointerTypeATI"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(type)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glElementPointerATI</name></proto>
+            <param group="ElementPointerTypeATI"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(type)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnable</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>cap</name></param>
+            <glx type="render" opcode="139"/>
+        </command>
+        <command>
+            <proto>void <name>glEnableClientState</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableClientStateIndexedEXT</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableClientStateiEXT</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableDriverControlQCOM</name></proto>
+            <param><ptype>GLuint</ptype> <name>driverControl</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableIndexedEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glEnablei"/>
+        </command>
+        <command>
+            <proto>void <name>glEnableVariantClientStateEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableVertexArrayAttrib</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableVertexArrayAttribEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableVertexArrayEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableVertexAttribAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableVertexAttribArray</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableVertexAttribArrayARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glEnableVertexAttribArray"/>
+        </command>
+        <command>
+            <proto>void <name>glEnablei</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEnableiEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glEnablei"/>
+        </command>
+        <command>
+            <proto>void <name>glEnableiNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glEnablei"/>
+        </command>
+        <command>
+            <proto>void <name>glEnableiOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glEnablei"/>
+        </command>
+        <command>
+            <proto>void <name>glEnd</name></proto>
+            <glx type="render" opcode="23"/>
+        </command>
+        <command>
+            <proto>void <name>glEndConditionalRender</name></proto>
+            <glx type="render" opcode="349"/>
+        </command>
+        <command>
+            <proto>void <name>glEndConditionalRenderNV</name></proto>
+            <alias name="glEndConditionalRender"/>
+        </command>
+        <command>
+            <proto>void <name>glEndConditionalRenderNVX</name></proto>
+            <alias name="glEndConditionalRender"/>
+        </command>
+        <command>
+            <proto>void <name>glEndFragmentShaderATI</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glEndList</name></proto>
+            <glx type="single" opcode="102"/>
+        </command>
+        <command>
+            <proto>void <name>glEndOcclusionQueryNV</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glEndPerfMonitorAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>monitor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEndPerfQueryINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>queryHandle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEndQuery</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <glx type="render" opcode="232"/>
+        </command>
+        <command>
+            <proto>void <name>glEndQueryARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <alias name="glEndQuery"/>
+        </command>
+        <command>
+            <proto>void <name>glEndQueryEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEndQueryIndexed</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEndTilingQCOM</name></proto>
+            <param><ptype>GLbitfield</ptype> <name>preserveMask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEndTransformFeedback</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glEndTransformFeedbackEXT</name></proto>
+            <alias name="glEndTransformFeedback"/>
+        </command>
+        <command>
+            <proto>void <name>glEndTransformFeedbackNV</name></proto>
+            <alias name="glEndTransformFeedback"/>
+        </command>
+        <command>
+            <proto>void <name>glEndVertexShaderEXT</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glEndVideoCaptureNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord1d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u</name></param>
+            <vecequiv name="glEvalCoord1dv"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord1dv</name></proto>
+            <param group="CoordD" len="1">const <ptype>GLdouble</ptype> *<name>u</name></param>
+            <glx type="render" opcode="151"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord1f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u</name></param>
+            <vecequiv name="glEvalCoord1fv"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord1fv</name></proto>
+            <param group="CoordF" len="1">const <ptype>GLfloat</ptype> *<name>u</name></param>
+            <glx type="render" opcode="152"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord1xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>u</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord1xvOES</name></proto>
+            <param len="1">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord2d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>v</name></param>
+            <vecequiv name="glEvalCoord2dv"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord2dv</name></proto>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>u</name></param>
+            <glx type="render" opcode="153"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord2f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>v</name></param>
+            <vecequiv name="glEvalCoord2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord2fv</name></proto>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>u</name></param>
+            <glx type="render" opcode="154"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord2xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>u</name></param>
+            <param><ptype>GLfixed</ptype> <name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEvalCoord2xvOES</name></proto>
+            <param len="2">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEvalMapsNV</name></proto>
+            <param group="EvalTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="EvalMapsModeNV"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glEvalMesh1</name></proto>
+            <param group="MeshMode1"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>i1</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>i2</name></param>
+            <glx type="render" opcode="155"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalMesh2</name></proto>
+            <param group="MeshMode2"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>i1</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>i2</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>j1</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>j2</name></param>
+            <glx type="render" opcode="157"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalPoint1</name></proto>
+            <param><ptype>GLint</ptype> <name>i</name></param>
+            <glx type="render" opcode="156"/>
+        </command>
+        <command>
+            <proto>void <name>glEvalPoint2</name></proto>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>i</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>j</name></param>
+            <glx type="render" opcode="158"/>
+        </command>
+        <command>
+            <proto>void <name>glEvaluateDepthValuesARB</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glExecuteProgramNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="4181"/>
+        </command>
+        <command>
+            <proto>void <name>glExtGetBufferPointervQCOM</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param>void **<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtGetBuffersQCOM</name></proto>
+            <param len="maxBuffers"><ptype>GLuint</ptype> *<name>buffers</name></param>
+            <param><ptype>GLint</ptype> <name>maxBuffers</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>numBuffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtGetFramebuffersQCOM</name></proto>
+            <param len="maxFramebuffers"><ptype>GLuint</ptype> *<name>framebuffers</name></param>
+            <param><ptype>GLint</ptype> <name>maxFramebuffers</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>numFramebuffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtGetProgramBinarySourceQCOM</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param><ptype>GLchar</ptype> *<name>source</name></param>
+            <param><ptype>GLint</ptype> *<name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtGetProgramsQCOM</name></proto>
+            <param len="maxPrograms"><ptype>GLuint</ptype> *<name>programs</name></param>
+            <param><ptype>GLint</ptype> <name>maxPrograms</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>numPrograms</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtGetRenderbuffersQCOM</name></proto>
+            <param len="maxRenderbuffers"><ptype>GLuint</ptype> *<name>renderbuffers</name></param>
+            <param><ptype>GLint</ptype> <name>maxRenderbuffers</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>numRenderbuffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtGetShadersQCOM</name></proto>
+            <param len="maxShaders"><ptype>GLuint</ptype> *<name>shaders</name></param>
+            <param><ptype>GLint</ptype> <name>maxShaders</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>numShaders</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtGetTexLevelParameterivQCOM</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>face</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtGetTexSubImageQCOM</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>void *<name>texels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtGetTexturesQCOM</name></proto>
+            <param><ptype>GLuint</ptype> *<name>textures</name></param>
+            <param><ptype>GLint</ptype> <name>maxTextures</name></param>
+            <param><ptype>GLint</ptype> *<name>numTextures</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glExtIsProgramBinaryQCOM</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtTexObjectStateOverrideiQCOM</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glExtractComponentEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>res</name></param>
+            <param><ptype>GLuint</ptype> <name>src</name></param>
+            <param><ptype>GLuint</ptype> <name>num</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFeedbackBuffer</name></proto>
+            <param><ptype>GLsizei</ptype> <name>size</name></param>
+            <param group="FeedbackType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="FeedbackElement" len="size"><ptype>GLfloat</ptype> *<name>buffer</name></param>
+            <glx type="single" opcode="105"/>
+        </command>
+        <command>
+            <proto>void <name>glFeedbackBufferxOES</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="n">const <ptype>GLfixed</ptype> *<name>buffer</name></param>
+        </command>
+        <command>
+            <proto group="sync"><ptype>GLsync</ptype> <name>glFenceSync</name></proto>
+            <param><ptype>GLenum</ptype> <name>condition</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLsync</ptype> <name>glFenceSyncAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>condition</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+            <alias name="glFenceSync"/>
+        </command>
+        <command>
+            <proto>void <name>glFinalCombinerInputNV</name></proto>
+            <param group="CombinerVariableNV"><ptype>GLenum</ptype> <name>variable</name></param>
+            <param group="CombinerRegisterNV"><ptype>GLenum</ptype> <name>input</name></param>
+            <param group="CombinerMappingNV"><ptype>GLenum</ptype> <name>mapping</name></param>
+            <param group="CombinerComponentUsageNV"><ptype>GLenum</ptype> <name>componentUsage</name></param>
+            <glx type="render" opcode="4142"/>
+        </command>
+        <command>
+            <proto>void <name>glFinish</name></proto>
+            <glx type="single" opcode="108"/>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glFinishAsyncSGIX</name></proto>
+            <param len="1"><ptype>GLuint</ptype> *<name>markerp</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFinishFenceAPPLE</name></proto>
+            <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFinishFenceNV</name></proto>
+            <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
+            <glx type="vendor" opcode="1312"/>
+        </command>
+        <command>
+            <proto>void <name>glFinishObjectAPPLE</name></proto>
+            <param group="ObjectTypeAPPLE"><ptype>GLenum</ptype> <name>object</name></param>
+            <param><ptype>GLint</ptype> <name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFinishTextureSUNX</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glFlush</name></proto>
+            <glx type="single" opcode="142"/>
+        </command>
+        <command>
+            <proto>void <name>glFlushMappedBufferRange</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFlushMappedBufferRangeAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <alias name="glFlushMappedBufferRange"/>
+        </command>
+        <command>
+            <proto>void <name>glFlushMappedBufferRangeEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>length</name></param>
+            <alias name="glFlushMappedBufferRange"/>
+        </command>
+        <command>
+            <proto>void <name>glFlushMappedNamedBufferRange</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFlushMappedNamedBufferRangeEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFlushPixelDataRangeNV</name></proto>
+            <param group="PixelDataRangeTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFlushRasterSGIX</name></proto>
+            <glx type="vendor" opcode="4105"/>
+        </command>
+        <command>
+            <proto>void <name>glFlushStaticDataIBM</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFlushVertexArrayRangeAPPLE</name></proto>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="length">void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFlushVertexArrayRangeNV</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordFormatNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordPointer</name></proto>
+            <param group="FogPointerTypeEXT"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordPointerEXT</name></proto>
+            <param group="FogPointerTypeEXT"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+            <alias name="glFogCoordPointer"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordPointerListIBM</name></proto>
+            <param group="FogPointerTypeIBM"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void **<name>pointer</name></param>
+            <param><ptype>GLint</ptype> <name>ptrstride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordd</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>coord</name></param>
+            <vecequiv name="glFogCoorddv"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoorddEXT</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>coord</name></param>
+            <alias name="glFogCoordd"/>
+            <vecequiv name="glFogCoorddvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoorddv</name></proto>
+            <param group="CoordD" len="1">const <ptype>GLdouble</ptype> *<name>coord</name></param>
+            <glx type="render" opcode="4125"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoorddvEXT</name></proto>
+            <param group="CoordD" len="1">const <ptype>GLdouble</ptype> *<name>coord</name></param>
+            <alias name="glFogCoorddv"/>
+            <glx type="render" opcode="4125"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordf</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>coord</name></param>
+            <vecequiv name="glFogCoordfv"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordfEXT</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>coord</name></param>
+            <alias name="glFogCoordf"/>
+            <vecequiv name="glFogCoordfvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordfv</name></proto>
+            <param group="CoordF" len="1">const <ptype>GLfloat</ptype> *<name>coord</name></param>
+            <glx type="render" opcode="4124"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordfvEXT</name></proto>
+            <param group="CoordF" len="1">const <ptype>GLfloat</ptype> *<name>coord</name></param>
+            <alias name="glFogCoordfv"/>
+            <glx type="render" opcode="4124"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordhNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>fog</name></param>
+            <vecequiv name="glFogCoordhvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glFogCoordhvNV</name></proto>
+            <param group="Half16NV" len="1">const <ptype>GLhalfNV</ptype> *<name>fog</name></param>
+            <glx type="render" opcode="4254"/>
+        </command>
+        <command>
+            <proto>void <name>glFogFuncSGIS</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n*2">const <ptype>GLfloat</ptype> *<name>points</name></param>
+            <glx type="render" opcode="2067"/>
+        </command>
+        <command>
+            <proto>void <name>glFogf</name></proto>
+            <param group="FogParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="80"/>
+        </command>
+        <command>
+            <proto>void <name>glFogfv</name></proto>
+            <param group="FogParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="81"/>
+        </command>
+        <command>
+            <proto>void <name>glFogi</name></proto>
+            <param group="FogParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="82"/>
+        </command>
+        <command>
+            <proto>void <name>glFogiv</name></proto>
+            <param group="FogParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="83"/>
+        </command>
+        <command>
+            <proto>void <name>glFogx</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFogxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFogxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFogxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentColorMaterialSGIX</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentCoverageColorNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>color</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentLightModelfSGIX</name></proto>
+            <param group="FragmentLightModelParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentLightModelfvSGIX</name></proto>
+            <param group="FragmentLightModelParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentLightModeliSGIX</name></proto>
+            <param group="FragmentLightModelParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentLightModelivSGIX</name></proto>
+            <param group="FragmentLightModelParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentLightfSGIX</name></proto>
+            <param group="FragmentLightNameSGIX"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="FragmentLightParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentLightfvSGIX</name></proto>
+            <param group="FragmentLightNameSGIX"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="FragmentLightParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentLightiSGIX</name></proto>
+            <param group="FragmentLightNameSGIX"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="FragmentLightParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentLightivSGIX</name></proto>
+            <param group="FragmentLightNameSGIX"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="FragmentLightParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentMaterialfSGIX</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentMaterialfvSGIX</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentMaterialiSGIX</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFragmentMaterialivSGIX</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFrameTerminatorGREMEDY</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glFrameZoomSGIX</name></proto>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>factor</name></param>
+            <glx type="render" opcode="2072"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferDrawBufferEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="DrawBufferMode"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferDrawBuffersEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="DrawBufferMode" len="n">const <ptype>GLenum</ptype> *<name>bufs</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferParameteri</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferPixelLocalStorageSizeEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferReadBufferEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="ReadBufferMode"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferRenderbuffer</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>renderbuffertarget</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <glx type="render" opcode="4324"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferRenderbufferEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>renderbuffertarget</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <alias name="glFramebufferRenderbuffer"/>
+            <glx type="render" opcode="4324"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferRenderbufferOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>renderbuffertarget</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferSampleLocationsfvARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferSampleLocationsfvNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferSamplePositionsfvAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>numsamples</name></param>
+            <param><ptype>GLuint</ptype> <name>pixelindex</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture1D</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <glx type="render" opcode="4321"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture1DEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <alias name="glFramebufferTexture1D"/>
+            <glx type="render" opcode="4321"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture2D</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <glx type="render" opcode="4322"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture2DEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <alias name="glFramebufferTexture2D"/>
+            <glx type="render" opcode="4322"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture2DDownsampleIMG</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xscale</name></param>
+            <param><ptype>GLint</ptype> <name>yscale</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture2DMultisampleEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture2DMultisampleIMG</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture2DOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture3D</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <glx type="render" opcode="4323"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture3DEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <alias name="glFramebufferTexture3D"/>
+            <glx type="render" opcode="4323"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTexture3DOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <alias name="glFramebufferTexture3D"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureARB</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <alias name="glFramebufferTexture"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <alias name="glFramebufferTexture"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureFaceARB</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>face</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureFaceEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>face</name></param>
+            <alias name="glFramebufferTextureFaceARB"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureLayer</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>layer</name></param>
+            <glx type="render" opcode="237"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureLayerARB</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>layer</name></param>
+            <alias name="glFramebufferTextureLayer"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureLayerEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>layer</name></param>
+            <alias name="glFramebufferTextureLayer"/>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureLayerDownsampleIMG</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>layer</name></param>
+            <param><ptype>GLint</ptype> <name>xscale</name></param>
+            <param><ptype>GLint</ptype> <name>yscale</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureMultisampleMultiviewOVR</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLint</ptype> <name>baseViewIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>numViews</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureMultiviewOVR</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>baseViewIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>numViews</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureOES</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <alias name="glFramebufferTexture"/>
+        </command>
+        <command>
+            <proto>void <name>glFreeObjectBufferATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFrontFace</name></proto>
+            <param group="FrontFaceDirection"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="84"/>
+        </command>
+        <command>
+            <proto>void <name>glFrustum</name></proto>
+            <param><ptype>GLdouble</ptype> <name>left</name></param>
+            <param><ptype>GLdouble</ptype> <name>right</name></param>
+            <param><ptype>GLdouble</ptype> <name>bottom</name></param>
+            <param><ptype>GLdouble</ptype> <name>top</name></param>
+            <param><ptype>GLdouble</ptype> <name>zNear</name></param>
+            <param><ptype>GLdouble</ptype> <name>zFar</name></param>
+            <glx type="render" opcode="175"/>
+        </command>
+        <command>
+            <proto>void <name>glFrustumf</name></proto>
+            <param><ptype>GLfloat</ptype> <name>l</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>n</name></param>
+            <param><ptype>GLfloat</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFrustumfOES</name></proto>
+            <param><ptype>GLfloat</ptype> <name>l</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>n</name></param>
+            <param><ptype>GLfloat</ptype> <name>f</name></param>
+            <glx type="render" opcode="4310"/>
+        </command>
+        <command>
+            <proto>void <name>glFrustumx</name></proto>
+            <param><ptype>GLfixed</ptype> <name>l</name></param>
+            <param><ptype>GLfixed</ptype> <name>r</name></param>
+            <param><ptype>GLfixed</ptype> <name>b</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+            <param><ptype>GLfixed</ptype> <name>n</name></param>
+            <param><ptype>GLfixed</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFrustumxOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>l</name></param>
+            <param><ptype>GLfixed</ptype> <name>r</name></param>
+            <param><ptype>GLfixed</ptype> <name>b</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+            <param><ptype>GLfixed</ptype> <name>n</name></param>
+            <param><ptype>GLfixed</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGenAsyncMarkersSGIX</name></proto>
+            <param><ptype>GLsizei</ptype> <name>range</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenBuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>buffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenBuffersARB</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>buffers</name></param>
+            <alias name="glGenBuffers"/>
+        </command>
+        <command>
+            <proto>void <name>glGenFencesAPPLE</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="FenceNV" len="n"><ptype>GLuint</ptype> *<name>fences</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenFencesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="FenceNV" len="n"><ptype>GLuint</ptype> *<name>fences</name></param>
+            <glx type="vendor" opcode="1277"/>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGenFragmentShadersATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>range</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenFramebuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>framebuffers</name></param>
+            <glx type="vendor" opcode="1426"/>
+        </command>
+        <command>
+            <proto>void <name>glGenFramebuffersEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>framebuffers</name></param>
+            <alias name="glGenFramebuffers"/>
+            <glx type="vendor" opcode="1426"/>
+        </command>
+        <command>
+            <proto>void <name>glGenFramebuffersOES</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>framebuffers</name></param>
+        </command>
+        <command>
+            <proto group="List"><ptype>GLuint</ptype> <name>glGenLists</name></proto>
+            <param><ptype>GLsizei</ptype> <name>range</name></param>
+            <glx type="single" opcode="104"/>
+        </command>
+        <command>
+            <proto>void <name>glGenNamesAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>identifier</name></param>
+            <param><ptype>GLuint</ptype> <name>num</name></param>
+            <param len="num"><ptype>GLuint</ptype> *<name>names</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenOcclusionQueriesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto group="Path"><ptype>GLuint</ptype> <name>glGenPathsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>range</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenPerfMonitorsAMD</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>monitors</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenProgramPipelines</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>pipelines</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenProgramPipelinesEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>pipelines</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenProgramsARB</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>programs</name></param>
+            <glx type="vendor" opcode="1295"/>
+        </command>
+        <command>
+            <proto>void <name>glGenProgramsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>programs</name></param>
+            <alias name="glGenProgramsARB"/>
+            <glx type="vendor" opcode="1295"/>
+        </command>
+        <command>
+            <proto>void <name>glGenQueries</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>ids</name></param>
+            <glx type="single" opcode="162"/>
+        </command>
+        <command>
+            <proto>void <name>glGenQueriesARB</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>ids</name></param>
+            <alias name="glGenQueries"/>
+        </command>
+        <command>
+            <proto>void <name>glGenQueriesEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenRenderbuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>renderbuffers</name></param>
+            <glx type="vendor" opcode="1423"/>
+        </command>
+        <command>
+            <proto>void <name>glGenRenderbuffersEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>renderbuffers</name></param>
+            <alias name="glGenRenderbuffers"/>
+            <glx type="vendor" opcode="1423"/>
+        </command>
+        <command>
+            <proto>void <name>glGenRenderbuffersOES</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>renderbuffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenSamplers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count"><ptype>GLuint</ptype> *<name>samplers</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGenSymbolsEXT</name></proto>
+            <param group="DataTypeEXT"><ptype>GLenum</ptype> <name>datatype</name></param>
+            <param group="VertexShaderStorageTypeEXT"><ptype>GLenum</ptype> <name>storagetype</name></param>
+            <param group="ParameterRangeEXT"><ptype>GLenum</ptype> <name>range</name></param>
+            <param><ptype>GLuint</ptype> <name>components</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenTextures</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Texture" len="n"><ptype>GLuint</ptype> *<name>textures</name></param>
+            <glx type="single" opcode="145"/>
+        </command>
+        <command>
+            <proto>void <name>glGenTexturesEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Texture" len="n"><ptype>GLuint</ptype> *<name>textures</name></param>
+            <glx type="vendor" opcode="13"/>
+        </command>
+        <command>
+            <proto>void <name>glGenTransformFeedbacks</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenTransformFeedbacksNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>ids</name></param>
+            <alias name="glGenTransformFeedbacks"/>
+        </command>
+        <command>
+            <proto>void <name>glGenVertexArrays</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>arrays</name></param>
+            <glx type="single" opcode="206"/>
+        </command>
+        <command>
+            <proto>void <name>glGenVertexArraysAPPLE</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>arrays</name></param>
+            <alias name="glGenVertexArrays"/>
+        </command>
+        <command>
+            <proto>void <name>glGenVertexArraysOES</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n"><ptype>GLuint</ptype> *<name>arrays</name></param>
+            <alias name="glGenVertexArrays"/>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGenVertexShadersEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>range</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenerateMipmap</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <glx type="render" opcode="4325"/>
+        </command>
+        <command>
+            <proto>void <name>glGenerateMipmapEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <alias name="glGenerateMipmap"/>
+            <glx type="render" opcode="4325"/>
+        </command>
+        <command>
+            <proto>void <name>glGenerateMipmapOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenerateMultiTexMipmapEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenerateTextureMipmap</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGenerateTextureMipmapEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveAtomicCounterBufferiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>bufferIndex</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveAttrib</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>size</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>type</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveAttribARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxLength</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>size</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>type</name></param>
+            <param len="maxLength"><ptype>GLcharARB</ptype> *<name>name</name></param>
+            <alias name="glGetActiveAttrib"/>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveSubroutineName</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufsize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufsize"><ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveSubroutineUniformName</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufsize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufsize"><ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveSubroutineUniformiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveUniform</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>size</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>type</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveUniformARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxLength</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>size</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>type</name></param>
+            <param len="maxLength"><ptype>GLcharARB</ptype> *<name>name</name></param>
+            <alias name="glGetActiveUniform"/>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveUniformBlockName</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>uniformBlockIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>uniformBlockName</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveUniformBlockiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>uniformBlockIndex</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(program,uniformBlockIndex,pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveUniformName</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>uniformIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>uniformName</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveUniformsiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLsizei</ptype> <name>uniformCount</name></param>
+            <param len="uniformCount">const <ptype>GLuint</ptype> *<name>uniformIndices</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(uniformCount,pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetActiveVaryingNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>size</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>type</name></param>
+            <param len="COMPSIZE(program,index,bufSize)"><ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetArrayObjectfvATI</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+            <param group="ArrayObjectPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetArrayObjectivATI</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>array</name></param>
+            <param group="ArrayObjectPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command comment="Could be an alias of glGetAttachedShaders except that GLhandleARB is different on MacOS X">
+            <proto>void <name>glGetAttachedObjectsARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>containerObj</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxCount</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>count</name></param>
+            <param group="handleARB" len="maxCount"><ptype>GLhandleARB</ptype> *<name>obj</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetAttachedShaders</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxCount</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>count</name></param>
+            <param len="maxCount"><ptype>GLuint</ptype> *<name>shaders</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetAttribLocation</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetAttribLocationARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <param>const <ptype>GLcharARB</ptype> *<name>name</name></param>
+            <alias name="glGetAttribLocation"/>
+        </command>
+        <command>
+            <proto>void <name>glGetBooleanIndexedvEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Boolean" len="COMPSIZE(target)"><ptype>GLboolean</ptype> *<name>data</name></param>
+            <alias name="glGetBooleani_v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetBooleani_v</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Boolean" len="COMPSIZE(target)"><ptype>GLboolean</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetBooleanv</name></proto>
+            <param group="GetPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="Boolean" len="COMPSIZE(pname)"><ptype>GLboolean</ptype> *<name>data</name></param>
+            <glx type="single" opcode="112"/>
+        </command>
+        <command>
+            <proto>void <name>glGetBufferParameteri64v</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferPNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetBufferParameteriv</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferPNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetBufferParameterivARB</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferPNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetBufferParameteriv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetBufferParameterui64vNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint64EXT</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetBufferPointerv</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferPointerNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetBufferPointervARB</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferPointerNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>params</name></param>
+            <alias name="glGetBufferPointerv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetBufferPointervOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>void **<name>params</name></param>
+            <alias name="glGetBufferPointerv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetBufferSubData</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="size">void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetBufferSubDataARB</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferOffsetARB"><ptype>GLintptrARB</ptype> <name>offset</name></param>
+            <param group="BufferSizeARB"><ptype>GLsizeiptrARB</ptype> <name>size</name></param>
+            <param len="size">void *<name>data</name></param>
+            <alias name="glGetBufferSubData"/>
+        </command>
+        <command>
+            <proto>void <name>glGetClipPlane</name></proto>
+            <param group="ClipPlaneName"><ptype>GLenum</ptype> <name>plane</name></param>
+            <param len="4"><ptype>GLdouble</ptype> *<name>equation</name></param>
+            <glx type="single" opcode="113"/>
+        </command>
+        <command>
+            <proto>void <name>glGetClipPlanef</name></proto>
+            <param><ptype>GLenum</ptype> <name>plane</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>equation</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetClipPlanefOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>plane</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>equation</name></param>
+            <glx type="vendor" opcode="1421"/>
+        </command>
+        <command>
+            <proto>void <name>glGetClipPlanex</name></proto>
+            <param><ptype>GLenum</ptype> <name>plane</name></param>
+            <param len="4"><ptype>GLfixed</ptype> *<name>equation</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetClipPlanexOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>plane</name></param>
+            <param len="4"><ptype>GLfixed</ptype> *<name>equation</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetColorTable</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>table</name></param>
+            <glx type="single" opcode="147"/>
+            <glx type="render" opcode="334" name="glGetColorTablePBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetColorTableEXT</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>data</name></param>
+            <alias name="glGetColorTable"/>
+        </command>
+        <command>
+            <proto>void <name>glGetColorTableParameterfv</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetColorTableParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="148"/>
+        </command>
+        <command>
+            <proto>void <name>glGetColorTableParameterfvEXT</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetColorTableParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glGetColorTableParameterfv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetColorTableParameterfvSGI</name></proto>
+            <param group="ColorTableTargetSGI"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetColorTableParameterPNameSGI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="4099"/>
+        </command>
+        <command>
+            <proto>void <name>glGetColorTableParameteriv</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetColorTableParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="149"/>
+        </command>
+        <command>
+            <proto>void <name>glGetColorTableParameterivEXT</name></proto>
+            <param group="ColorTableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetColorTableParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetColorTableParameteriv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetColorTableParameterivSGI</name></proto>
+            <param group="ColorTableTargetSGI"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetColorTableParameterPNameSGI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="4100"/>
+        </command>
+        <command>
+            <proto>void <name>glGetColorTableSGI</name></proto>
+            <param group="ColorTableTargetSGI"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>table</name></param>
+            <glx type="vendor" opcode="4098"/>
+        </command>
+        <command>
+            <proto>void <name>glGetCombinerInputParameterfvNV</name></proto>
+            <param group="CombinerStageNV"><ptype>GLenum</ptype> <name>stage</name></param>
+            <param group="CombinerPortionNV"><ptype>GLenum</ptype> <name>portion</name></param>
+            <param group="CombinerVariableNV"><ptype>GLenum</ptype> <name>variable</name></param>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1270"/>
+        </command>
+        <command>
+            <proto>void <name>glGetCombinerInputParameterivNV</name></proto>
+            <param group="CombinerStageNV"><ptype>GLenum</ptype> <name>stage</name></param>
+            <param group="CombinerPortionNV"><ptype>GLenum</ptype> <name>portion</name></param>
+            <param group="CombinerVariableNV"><ptype>GLenum</ptype> <name>variable</name></param>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1271"/>
+        </command>
+        <command>
+            <proto>void <name>glGetCombinerOutputParameterfvNV</name></proto>
+            <param group="CombinerStageNV"><ptype>GLenum</ptype> <name>stage</name></param>
+            <param group="CombinerPortionNV"><ptype>GLenum</ptype> <name>portion</name></param>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1272"/>
+        </command>
+        <command>
+            <proto>void <name>glGetCombinerOutputParameterivNV</name></proto>
+            <param group="CombinerStageNV"><ptype>GLenum</ptype> <name>stage</name></param>
+            <param group="CombinerPortionNV"><ptype>GLenum</ptype> <name>portion</name></param>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1273"/>
+        </command>
+        <command>
+            <proto>void <name>glGetCombinerStageParameterfvNV</name></proto>
+            <param group="CombinerStageNV"><ptype>GLenum</ptype> <name>stage</name></param>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGetCommandHeaderNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>tokenID</name></param>
+            <param><ptype>GLuint</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetCompressedMultiTexImageEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>lod</name></param>
+            <param len="COMPSIZE(target,lod)">void *<name>img</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetCompressedTexImage</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CompressedTextureARB" len="COMPSIZE(target,level)">void *<name>img</name></param>
+            <glx type="single" opcode="160"/>
+            <glx type="render" opcode="335" name="glGetCompressedTexImagePBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetCompressedTexImageARB</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CompressedTextureARB" len="COMPSIZE(target,level)">void *<name>img</name></param>
+            <alias name="glGetCompressedTexImage"/>
+            <glx type="single" opcode="160"/>
+        </command>
+        <command>
+            <proto>void <name>glGetCompressedTextureImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetCompressedTextureImageEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>lod</name></param>
+            <param len="COMPSIZE(target,lod)">void *<name>img</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetCompressedTextureSubImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetConvolutionFilter</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>image</name></param>
+            <glx type="single" opcode="150"/>
+            <glx type="render" opcode="336" name="glGetConvolutionFilterPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetConvolutionFilterEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>image</name></param>
+            <glx type="vendor" opcode="1"/>
+        </command>
+        <command>
+            <proto>void <name>glGetConvolutionParameterfv</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetConvolutionParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="151"/>
+        </command>
+        <command>
+            <proto>void <name>glGetConvolutionParameterfvEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameterEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="2"/>
+        </command>
+        <command>
+            <proto>void <name>glGetConvolutionParameteriv</name></proto>
+            <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetConvolutionParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="152"/>
+        </command>
+        <command>
+            <proto>void <name>glGetConvolutionParameterivEXT</name></proto>
+            <param group="ConvolutionTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ConvolutionParameterEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="3"/>
+        </command>
+        <command>
+            <proto>void <name>glGetConvolutionParameterxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetCoverageModulationTableNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>bufsize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGetDebugMessageLog</name></proto>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>sources</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>types</name></param>
+            <param len="count"><ptype>GLuint</ptype> *<name>ids</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>severities</name></param>
+            <param len="count"><ptype>GLsizei</ptype> *<name>lengths</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>messageLog</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGetDebugMessageLogAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufsize</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>categories</name></param>
+            <param len="count"><ptype>GLuint</ptype> *<name>severities</name></param>
+            <param len="count"><ptype>GLuint</ptype> *<name>ids</name></param>
+            <param len="count"><ptype>GLsizei</ptype> *<name>lengths</name></param>
+            <param len="bufsize"><ptype>GLchar</ptype> *<name>message</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGetDebugMessageLogARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>sources</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>types</name></param>
+            <param len="count"><ptype>GLuint</ptype> *<name>ids</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>severities</name></param>
+            <param len="count"><ptype>GLsizei</ptype> *<name>lengths</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>messageLog</name></param>
+            <alias name="glGetDebugMessageLog"/>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGetDebugMessageLogKHR</name></proto>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>sources</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>types</name></param>
+            <param len="count"><ptype>GLuint</ptype> *<name>ids</name></param>
+            <param len="count"><ptype>GLenum</ptype> *<name>severities</name></param>
+            <param len="count"><ptype>GLsizei</ptype> *<name>lengths</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>messageLog</name></param>
+            <alias name="glGetDebugMessageLog"/>
+        </command>
+        <command>
+            <proto>void <name>glGetDetailTexFuncSGIS</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLfloat</ptype> *<name>points</name></param>
+            <glx type="vendor" opcode="4096"/>
+        </command>
+        <command>
+            <proto>void <name>glGetDoubleIndexedvEXT</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLdouble</ptype> *<name>data</name></param>
+            <alias name="glGetDoublei_v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetDoublei_v</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLdouble</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetDoublei_vEXT</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <alias name="glGetDoublei_v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetDoublev</name></proto>
+            <param group="GetPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLdouble</ptype> *<name>data</name></param>
+            <glx type="single" opcode="114"/>
+        </command>
+        <command>
+            <proto>void <name>glGetDriverControlStringQCOM</name></proto>
+            <param><ptype>GLuint</ptype> <name>driverControl</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>driverControlString</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetDriverControlsQCOM</name></proto>
+            <param><ptype>GLint</ptype> *<name>num</name></param>
+            <param><ptype>GLsizei</ptype> <name>size</name></param>
+            <param len="size"><ptype>GLuint</ptype> *<name>driverControls</name></param>
+        </command>
+        <command>
+            <proto group="ErrorCode"><ptype>GLenum</ptype> <name>glGetError</name></proto>
+            <glx type="single" opcode="115"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFenceivNV</name></proto>
+            <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
+            <param group="FenceParameterNameNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1280"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFinalCombinerInputParameterfvNV</name></proto>
+            <param group="CombinerVariableNV"><ptype>GLenum</ptype> <name>variable</name></param>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1274"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFinalCombinerInputParameterivNV</name></proto>
+            <param group="CombinerVariableNV"><ptype>GLenum</ptype> <name>variable</name></param>
+            <param group="CombinerParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1275"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFirstPerfQueryIdINTEL</name></proto>
+            <param><ptype>GLuint</ptype> *<name>queryId</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFixedv</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFixedvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFloatIndexedvEXT</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLfloat</ptype> *<name>data</name></param>
+            <alias name="glGetFloati_v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFloati_v</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLfloat</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFloati_vEXT</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glGetFloati_v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFloati_vNV</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLfloat</ptype> *<name>data</name></param>
+            <alias name="glGetFloati_v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFloati_vOES</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLfloat</ptype> *<name>data</name></param>
+            <alias name="glGetFloati_v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFloatv</name></proto>
+            <param group="GetPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>data</name></param>
+            <glx type="single" opcode="116"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFogFuncSGIS</name></proto>
+            <param len="COMPSIZE()"><ptype>GLfloat</ptype> *<name>points</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetFragDataIndex</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetFragDataIndexEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+            <alias name="glGetFragDataIndex"/>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetFragDataLocation</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetFragDataLocationEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+            <alias name="glGetFragDataLocation"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFragmentLightfvSGIX</name></proto>
+            <param group="FragmentLightNameSGIX"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="FragmentLightParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFragmentLightivSGIX</name></proto>
+            <param group="FragmentLightNameSGIX"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="FragmentLightParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFragmentMaterialfvSGIX</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFragmentMaterialivSGIX</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFramebufferAttachmentParameteriv</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1428"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFramebufferAttachmentParameterivEXT</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetFramebufferAttachmentParameteriv"/>
+            <glx type="vendor" opcode="1428"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFramebufferAttachmentParameterivOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFramebufferParameterfvAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>numsamples</name></param>
+            <param><ptype>GLuint</ptype> <name>pixelindex</name></param>
+            <param><ptype>GLsizei</ptype> <name>size</name></param>
+            <param><ptype>GLfloat</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFramebufferParameteriv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetFramebufferParameterivEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="GetFramebufferParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLsizei</ptype> <name>glGetFramebufferPixelLocalStorageSizeEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glGetGraphicsResetStatus</name></proto>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glGetGraphicsResetStatusARB</name></proto>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glGetGraphicsResetStatusEXT</name></proto>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glGetGraphicsResetStatusKHR</name></proto>
+            <alias name="glGetGraphicsResetStatus"/>
+        </command>
+        <command>
+            <proto group="handleARB"><ptype>GLhandleARB</ptype> <name>glGetHandleARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetHistogram</name></proto>
+            <param group="HistogramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>values</name></param>
+            <glx type="single" opcode="154"/>
+            <glx type="render" opcode="337" name="glGetHistogramPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetHistogramEXT</name></proto>
+            <param group="HistogramTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>values</name></param>
+            <glx type="vendor" opcode="5"/>
+        </command>
+        <command>
+            <proto>void <name>glGetHistogramParameterfv</name></proto>
+            <param group="HistogramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetHistogramParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="155"/>
+        </command>
+        <command>
+            <proto>void <name>glGetHistogramParameterfvEXT</name></proto>
+            <param group="HistogramTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetHistogramParameterPNameEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="6"/>
+        </command>
+        <command>
+            <proto>void <name>glGetHistogramParameteriv</name></proto>
+            <param group="HistogramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetHistogramParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="156"/>
+        </command>
+        <command>
+            <proto>void <name>glGetHistogramParameterivEXT</name></proto>
+            <param group="HistogramTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetHistogramParameterPNameEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="7"/>
+        </command>
+        <command>
+            <proto>void <name>glGetHistogramParameterxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint64</ptype> <name>glGetImageHandleARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLboolean</ptype> <name>layered</name></param>
+            <param><ptype>GLint</ptype> <name>layer</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint64</ptype> <name>glGetImageHandleNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>layered</name></param>
+            <param><ptype>GLint</ptype> <name>layer</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetImageTransformParameterfvHP</name></proto>
+            <param group="ImageTransformTargetHP"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ImageTransformPNameHP"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetImageTransformParameterivHP</name></proto>
+            <param group="ImageTransformTargetHP"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ImageTransformPNameHP"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetInfoLogARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>obj</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxLength</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="maxLength"><ptype>GLcharARB</ptype> *<name>infoLog</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetInstrumentsSGIX</name></proto>
+            <glx type="vendor" opcode="4102"/>
+        </command>
+        <command>
+            <proto>void <name>glGetInteger64i_v</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLint64</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetInteger64v</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint64</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetInteger64vAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint64</ptype> *<name>params</name></param>
+            <alias name="glGetInteger64v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetIntegerIndexedvEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLint</ptype> *<name>data</name></param>
+            <alias name="glGetIntegeri_v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetIntegeri_v</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLint</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetIntegeri_vEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetIntegerui64i_vNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>value</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(value)"><ptype>GLuint64EXT</ptype> *<name>result</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetIntegerui64vNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>value</name></param>
+            <param len="COMPSIZE(value)"><ptype>GLuint64EXT</ptype> *<name>result</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetIntegerv</name></proto>
+            <param group="GetPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>data</name></param>
+            <glx type="single" opcode="117"/>
+        </command>
+        <command>
+            <proto>void <name>glGetInternalformatSampleivNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetInternalformati64v</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetInternalformativ</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetInvariantBooleanvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param group="Boolean" len="COMPSIZE(id)"><ptype>GLboolean</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetInvariantFloatvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param len="COMPSIZE(id)"><ptype>GLfloat</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetInvariantIntegervEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param len="COMPSIZE(id)"><ptype>GLint</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetLightfv</name></proto>
+            <param group="LightName"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="LightParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="118"/>
+        </command>
+        <command>
+            <proto>void <name>glGetLightiv</name></proto>
+            <param group="LightName"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="LightParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="119"/>
+        </command>
+        <command>
+            <proto>void <name>glGetLightxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>light</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetLightxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>light</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetLightxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>light</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetListParameterfvSGIX</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <param group="ListParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetListParameterivSGIX</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <param group="ListParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetLocalConstantBooleanvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param group="Boolean" len="COMPSIZE(id)"><ptype>GLboolean</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetLocalConstantFloatvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param len="COMPSIZE(id)"><ptype>GLfloat</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetLocalConstantIntegervEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param len="COMPSIZE(id)"><ptype>GLint</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMapAttribParameterfvNV</name></proto>
+            <param group="EvalTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="MapAttribParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMapAttribParameterivNV</name></proto>
+            <param group="EvalTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="MapAttribParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMapControlPointsNV</name></proto>
+            <param group="EvalTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="MapTypeNV"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>ustride</name></param>
+            <param><ptype>GLsizei</ptype> <name>vstride</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>packed</name></param>
+            <param len="COMPSIZE(target)">void *<name>points</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMapParameterfvNV</name></proto>
+            <param group="EvalTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="MapParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(target,pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMapParameterivNV</name></proto>
+            <param group="EvalTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="MapParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(target,pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMapdv</name></proto>
+            <param group="MapTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetMapQuery"><ptype>GLenum</ptype> <name>query</name></param>
+            <param len="COMPSIZE(target,query)"><ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="single" opcode="120"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMapfv</name></proto>
+            <param group="MapTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetMapQuery"><ptype>GLenum</ptype> <name>query</name></param>
+            <param len="COMPSIZE(target,query)"><ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="single" opcode="121"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMapiv</name></proto>
+            <param group="MapTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetMapQuery"><ptype>GLenum</ptype> <name>query</name></param>
+            <param len="COMPSIZE(target,query)"><ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="single" opcode="122"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMapxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param len="COMPSIZE(query)"><ptype>GLfixed</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMaterialfv</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="123"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMaterialiv</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="124"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMaterialxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>face</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMaterialxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>face</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMaterialxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>face</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMinmax</name></proto>
+            <param group="MinmaxTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>values</name></param>
+            <glx type="single" opcode="157"/>
+            <glx type="render" opcode="338" name="glGetMinmaxPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMinmaxEXT</name></proto>
+            <param group="MinmaxTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>values</name></param>
+            <glx type="vendor" opcode="8"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMinmaxParameterfv</name></proto>
+            <param group="MinmaxTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetMinmaxParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="158"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMinmaxParameterfvEXT</name></proto>
+            <param group="MinmaxTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetMinmaxParameterPNameEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="9"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMinmaxParameteriv</name></proto>
+            <param group="MinmaxTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetMinmaxParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="159"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMinmaxParameterivEXT</name></proto>
+            <param group="MinmaxTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetMinmaxParameterPNameEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="10"/>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexEnvfvEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexEnvivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexGendvEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexGenfvEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexGenivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexImageEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,level,format,type)">void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexLevelParameterfvEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexLevelParameterivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexParameterIivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexParameterIuivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexParameterfvEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultiTexParameterivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultisamplefv</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>val</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetMultisamplefvNV</name></proto>
+            <param group="GetMultisamplePNameNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2"><ptype>GLfloat</ptype> *<name>val</name></param>
+            <alias name="glGetMultisamplefv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedBufferParameteri64v</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedBufferParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedBufferParameterivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="VertexBufferObjectParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedBufferParameterui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="VertexBufferObjectParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint64EXT</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedBufferPointerv</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>void **<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedBufferPointervEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="VertexBufferObjectParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedBufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param>void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedBufferSubDataEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="COMPSIZE(size)">void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedFramebufferParameterfvAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>numsamples</name></param>
+            <param><ptype>GLuint</ptype> <name>pixelindex</name></param>
+            <param><ptype>GLsizei</ptype> <name>size</name></param>
+            <param><ptype>GLfloat</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedFramebufferAttachmentParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedFramebufferAttachmentParameterivEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="FramebufferAttachmentParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedFramebufferParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedFramebufferParameterivEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="GetFramebufferParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedProgramLocalParameterIivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedProgramLocalParameterIuivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedProgramLocalParameterdvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedProgramLocalParameterfvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedProgramStringEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ProgramStringProperty"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(program,pname)">void *<name>string</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedProgramivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ProgramProperty"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedRenderbufferParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedRenderbufferParameterivEXT</name></proto>
+            <param group="Renderbuffer"><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param group="RenderbufferParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedStringARB</name></proto>
+            <param><ptype>GLint</ptype> <name>namelen</name></param>
+            <param len="namelen">const <ptype>GLchar</ptype> *<name>name</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>stringlen</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>string</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedStringivARB</name></proto>
+            <param><ptype>GLint</ptype> <name>namelen</name></param>
+            <param len="namelen">const <ptype>GLchar</ptype> *<name>name</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNextPerfQueryIdINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>queryId</name></param>
+            <param><ptype>GLuint</ptype> *<name>nextQueryId</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectBufferfvATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="ArrayObjectPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectBufferivATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="ArrayObjectPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectLabel</name></proto>
+            <param><ptype>GLenum</ptype> <name>identifier</name></param>
+            <param><ptype>GLuint</ptype> <name>name</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>label</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectLabelEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>object</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>label</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectLabelKHR</name></proto>
+            <param><ptype>GLenum</ptype> <name>identifier</name></param>
+            <param><ptype>GLuint</ptype> <name>name</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>label</name></param>
+            <alias name="glGetObjectLabel"/>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectParameterfvARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>obj</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectParameterivAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>objectType</name></param>
+            <param><ptype>GLuint</ptype> <name>name</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectParameterivARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>obj</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectPtrLabel</name></proto>
+            <param>const void *<name>ptr</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>label</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetObjectPtrLabelKHR</name></proto>
+            <param>const void *<name>ptr</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>label</name></param>
+            <alias name="glGetObjectPtrLabel"/>
+        </command>
+        <command>
+            <proto>void <name>glGetOcclusionQueryivNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="OcclusionQueryParameterNameNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetOcclusionQueryuivNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="OcclusionQueryParameterNameNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathColorGenfvNV</name></proto>
+            <param group="PathColor"><ptype>GLenum</ptype> <name>color</name></param>
+            <param group="PathGenMode"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathColorGenivNV</name></proto>
+            <param group="PathColor"><ptype>GLenum</ptype> <name>color</name></param>
+            <param group="PathGenMode"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathCommandsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathCommand" len="COMPSIZE(path)"><ptype>GLubyte</ptype> *<name>commands</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathCoordsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param len="COMPSIZE(path)"><ptype>GLfloat</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathDashArrayNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param len="COMPSIZE(path)"><ptype>GLfloat</ptype> *<name>dashArray</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLfloat</ptype> <name>glGetPathLengthNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLsizei</ptype> <name>startSegment</name></param>
+            <param><ptype>GLsizei</ptype> <name>numSegments</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathMetricRangeNV</name></proto>
+            <param group="PathMetricMask"><ptype>GLbitfield</ptype> <name>metricQueryMask</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>firstPathName</name></param>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(metricQueryMask,numPaths,stride)"><ptype>GLfloat</ptype> *<name>metrics</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathMetricsNV</name></proto>
+            <param group="PathMetricMask"><ptype>GLbitfield</ptype> <name>metricQueryMask</name></param>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param group="PathElementType"><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param group="PathElement" len="COMPSIZE(numPaths,pathNameType,paths)">const void *<name>paths</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(metricQueryMask,numPaths,stride)"><ptype>GLfloat</ptype> *<name>metrics</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathParameterfvNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathParameterivNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathSpacingNV</name></proto>
+            <param group="PathListMode"><ptype>GLenum</ptype> <name>pathListMode</name></param>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param group="PathElementType"><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param group="PathElement" len="COMPSIZE(numPaths,pathNameType,paths)">const void *<name>paths</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param><ptype>GLfloat</ptype> <name>advanceScale</name></param>
+            <param><ptype>GLfloat</ptype> <name>kerningScale</name></param>
+            <param group="PathTransformType"><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param len="COMPSIZE(pathListMode,numPaths)"><ptype>GLfloat</ptype> *<name>returnedSpacing</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathTexGenfvNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texCoordSet</name></param>
+            <param group="PathGenMode"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPathTexGenivNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texCoordSet</name></param>
+            <param group="PathGenMode"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfCounterInfoINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>queryId</name></param>
+            <param><ptype>GLuint</ptype> <name>counterId</name></param>
+            <param><ptype>GLuint</ptype> <name>counterNameLength</name></param>
+            <param><ptype>GLchar</ptype> *<name>counterName</name></param>
+            <param><ptype>GLuint</ptype> <name>counterDescLength</name></param>
+            <param><ptype>GLchar</ptype> *<name>counterDesc</name></param>
+            <param><ptype>GLuint</ptype> *<name>counterOffset</name></param>
+            <param><ptype>GLuint</ptype> *<name>counterDataSize</name></param>
+            <param><ptype>GLuint</ptype> *<name>counterTypeEnum</name></param>
+            <param><ptype>GLuint</ptype> *<name>counterDataTypeEnum</name></param>
+            <param><ptype>GLuint64</ptype> *<name>rawCounterMaxValue</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfMonitorCounterDataAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>monitor</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLsizei</ptype> <name>dataSize</name></param>
+            <param len="dataSize"><ptype>GLuint</ptype> *<name>data</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>bytesWritten</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfMonitorCounterInfoAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>group</name></param>
+            <param><ptype>GLuint</ptype> <name>counter</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfMonitorCounterStringAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>group</name></param>
+            <param><ptype>GLuint</ptype> <name>counter</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>counterString</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfMonitorCountersAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>group</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>numCounters</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>maxActiveCounters</name></param>
+            <param><ptype>GLsizei</ptype> <name>counterSize</name></param>
+            <param len="counterSize"><ptype>GLuint</ptype> *<name>counters</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfMonitorGroupStringAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>group</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>groupString</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfMonitorGroupsAMD</name></proto>
+            <param len="1"><ptype>GLint</ptype> *<name>numGroups</name></param>
+            <param><ptype>GLsizei</ptype> <name>groupsSize</name></param>
+            <param len="groupsSize"><ptype>GLuint</ptype> *<name>groups</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfQueryDataINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>queryHandle</name></param>
+            <param><ptype>GLuint</ptype> <name>flags</name></param>
+            <param><ptype>GLsizei</ptype> <name>dataSize</name></param>
+            <param><ptype>GLvoid</ptype> *<name>data</name></param>
+            <param><ptype>GLuint</ptype> *<name>bytesWritten</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfQueryIdByNameINTEL</name></proto>
+            <param><ptype>GLchar</ptype> *<name>queryName</name></param>
+            <param><ptype>GLuint</ptype> *<name>queryId</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPerfQueryInfoINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>queryId</name></param>
+            <param><ptype>GLuint</ptype> <name>queryNameLength</name></param>
+            <param><ptype>GLchar</ptype> *<name>queryName</name></param>
+            <param><ptype>GLuint</ptype> *<name>dataSize</name></param>
+            <param><ptype>GLuint</ptype> *<name>noCounters</name></param>
+            <param><ptype>GLuint</ptype> *<name>noInstances</name></param>
+            <param><ptype>GLuint</ptype> *<name>capsMask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPixelMapfv</name></proto>
+            <param group="PixelMap"><ptype>GLenum</ptype> <name>map</name></param>
+            <param len="COMPSIZE(map)"><ptype>GLfloat</ptype> *<name>values</name></param>
+            <glx type="single" opcode="125"/>
+            <glx type="render" opcode="339" name="glGetPixelMapfvPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetPixelMapuiv</name></proto>
+            <param group="PixelMap"><ptype>GLenum</ptype> <name>map</name></param>
+            <param len="COMPSIZE(map)"><ptype>GLuint</ptype> *<name>values</name></param>
+            <glx type="single" opcode="126"/>
+            <glx type="render" opcode="340" name="glGetPixelMapuivPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetPixelMapusv</name></proto>
+            <param group="PixelMap"><ptype>GLenum</ptype> <name>map</name></param>
+            <param len="COMPSIZE(map)"><ptype>GLushort</ptype> *<name>values</name></param>
+            <glx type="single" opcode="127"/>
+            <glx type="render" opcode="341" name="glGetPixelMapusvPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetPixelMapxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size"><ptype>GLfixed</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPixelTexGenParameterfvSGIS</name></proto>
+            <param group="PixelTexGenParameterNameSGIS"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPixelTexGenParameterivSGIS</name></proto>
+            <param group="PixelTexGenParameterNameSGIS"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPixelTransformParameterfvEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="2051"/>
+        </command>
+        <command>
+            <proto>void <name>glGetPixelTransformParameterivEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="2052"/>
+        </command>
+        <command>
+            <proto>void <name>glGetPointerIndexedvEXT</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">void **<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPointeri_vEXT</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">void **<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetPointerv</name></proto>
+            <param group="GetPointervPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>params</name></param>
+            <glx type="single" opcode="208"/>
+        </command>
+        <command>
+            <proto>void <name>glGetPointervEXT</name></proto>
+            <param group="GetPointervPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>params</name></param>
+            <alias name="glGetPointerv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetPointervKHR</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>void **<name>params</name></param>
+            <alias name="glGetPointerv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetPolygonStipple</name></proto>
+            <param len="COMPSIZE()"><ptype>GLubyte</ptype> *<name>mask</name></param>
+            <glx type="single" opcode="128"/>
+            <glx type="render" opcode="342" name="glGetPolygonStipplePBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramBinary</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>binaryFormat</name></param>
+            <param len="bufSize">void *<name>binary</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramBinaryOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>binaryFormat</name></param>
+            <param len="bufSize">void *<name>binary</name></param>
+            <alias name="glGetProgramBinary"/>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramEnvParameterIivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramEnvParameterIuivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramEnvParameterdvARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramEnvParameterfvARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramInfoLog</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>infoLog</name></param>
+            <glx type="single" opcode="201"/>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramInterfaceiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramLocalParameterIivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramLocalParameterIuivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramLocalParameterdvARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramLocalParameterfvARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramNamedParameterdvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="1">const <ptype>GLubyte</ptype> *<name>name</name></param>
+            <param len="4"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1311"/>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramNamedParameterfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="1">const <ptype>GLubyte</ptype> *<name>name</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1310"/>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramParameterdvNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1297"/>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramParameterfvNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1296"/>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramPipelineInfoLog</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>infoLog</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramPipelineInfoLogEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>infoLog</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramPipelineiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramPipelineivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGetProgramResourceIndex</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetProgramResourceLocation</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetProgramResourceLocationIndex</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetProgramResourceLocationIndexEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramResourceName</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramResourcefvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>propCount</name></param>
+            <param>const <ptype>GLenum</ptype> *<name>props</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramResourceiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>propCount</name></param>
+            <param len="propCount">const <ptype>GLenum</ptype> *<name>props</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramStageiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramStringARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ProgramStringPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(target,pname)">void *<name>string</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramStringNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="ProgramCharacterNV" len="COMPSIZE(id,pname)"><ptype>GLubyte</ptype> *<name>program</name></param>
+            <glx type="vendor" opcode="1299"/>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramSubroutineParameteruivNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLuint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="199"/>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramivARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ProgramPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetProgramivNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1298"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryBufferObjecti64v</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryBufferObjectiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryBufferObjectui64v</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryBufferObjectuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryIndexediv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjecti64v</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjecti64vEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint64</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1328"/>
+            <alias name="glGetQueryObjecti64v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjectiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="165"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjectivARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetQueryObjectiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjectivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetQueryObjectiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjectui64v</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjectui64vEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint64</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1329"/>
+            <alias name="glGetQueryObjectui64v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjectuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="166"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjectuivARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetQueryObjectuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryObjectuivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="164"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryivARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetQueryiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryivEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetRenderbufferParameteriv</name></proto>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1424"/>
+        </command>
+        <command>
+            <proto>void <name>glGetRenderbufferParameterivEXT</name></proto>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetRenderbufferParameteriv"/>
+            <glx type="vendor" opcode="1424"/>
+        </command>
+        <command>
+            <proto>void <name>glGetRenderbufferParameterivOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetSamplerParameterIiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetSamplerParameterIivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetSamplerParameterIiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetSamplerParameterIivOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetSamplerParameterIiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetSamplerParameterIuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetSamplerParameterIuivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetSamplerParameterIuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetSamplerParameterIuivOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetSamplerParameterIuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetSamplerParameterfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetSamplerParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetSeparableFilter</name></proto>
+            <param group="SeparableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>row</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>column</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>span</name></param>
+            <glx type="single" opcode="153"/>
+            <glx type="render" opcode="343" name="glGetSeparableFilterPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetSeparableFilterEXT</name></proto>
+            <param group="SeparableTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>row</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>column</name></param>
+            <param len="COMPSIZE(target,format,type)">void *<name>span</name></param>
+            <glx type="vendor" opcode="4"/>
+        </command>
+        <command>
+            <proto>void <name>glGetShaderInfoLog</name></proto>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>infoLog</name></param>
+            <glx type="single" opcode="200"/>
+        </command>
+        <command>
+            <proto>void <name>glGetShaderPrecisionFormat</name></proto>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param><ptype>GLenum</ptype> <name>precisiontype</name></param>
+            <param len="2"><ptype>GLint</ptype> *<name>range</name></param>
+            <param len="2"><ptype>GLint</ptype> *<name>precision</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetShaderSource</name></proto>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>source</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetShaderSourceARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>obj</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxLength</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="maxLength"><ptype>GLcharARB</ptype> *<name>source</name></param>
+            <alias name="glGetShaderSource"/>
+        </command>
+        <command>
+            <proto>void <name>glGetShaderiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="198"/>
+        </command>
+        <command>
+            <proto>void <name>glGetSharpenTexFuncSGIS</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLfloat</ptype> *<name>points</name></param>
+            <glx type="vendor" opcode="4097"/>
+        </command>
+        <command>
+            <proto><ptype>GLushort</ptype> <name>glGetStageIndexNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+        </command>
+        <command>
+            <proto group="String">const <ptype>GLubyte</ptype> *<name>glGetString</name></proto>
+            <param group="StringName"><ptype>GLenum</ptype> <name>name</name></param>
+            <glx type="single" opcode="129"/>
+        </command>
+        <command>
+            <proto group="String">const <ptype>GLubyte</ptype> *<name>glGetStringi</name></proto>
+            <param><ptype>GLenum</ptype> <name>name</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGetSubroutineIndex</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetSubroutineUniformLocation</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetSynciv</name></proto>
+            <param group="sync"><ptype>GLsync</ptype> <name>sync</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetSyncivAPPLE</name></proto>
+            <param><ptype>GLsync</ptype> <name>sync</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>values</name></param>
+            <alias name="glGetSynciv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexBumpParameterfvATI</name></proto>
+            <param group="GetTexBumpParameterATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexBumpParameterivATI</name></proto>
+            <param group="GetTexBumpParameterATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexEnvfv</name></proto>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="130"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexEnviv</name></proto>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="131"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexEnvxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexEnvxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexFilterFuncSGIS</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureFilterSGIS"><ptype>GLenum</ptype> <name>filter</name></param>
+            <param len="COMPSIZE(target,filter)"><ptype>GLfloat</ptype> *<name>weights</name></param>
+            <glx type="vendor" opcode="4101"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexGendv</name></proto>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <glx type="single" opcode="132"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexGenfv</name></proto>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="133"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexGenfvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>coord</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexGeniv</name></proto>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="134"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexGenivOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>coord</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexGenxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>coord</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexImage</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,level,format,type)">void *<name>pixels</name></param>
+            <glx type="single" opcode="135"/>
+            <glx type="render" opcode="344" name="glGetTexImagePBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexLevelParameterfv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="138"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexLevelParameteriv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="139"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexLevelParameterxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterIiv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="203"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterIivEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetTexParameterIiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterIivOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetTexParameterIiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterIuiv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="204"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterIuivEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetTexParameterIuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterIuivOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetTexParameterIuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterPointervAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterfv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="single" opcode="136"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameteriv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="single" opcode="137"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTexParameterxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint64</ptype> <name>glGetTextureHandleARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint64</ptype> <name>glGetTextureHandleIMG</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <alias name="glGetTextureHandleARB"/>
+        </command>
+        <command>
+            <proto><ptype>GLuint64</ptype> <name>glGetTextureHandleNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureImageEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,level,format,type)">void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureLevelParameterfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureLevelParameterfvEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureLevelParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureLevelParameterivEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureParameterIiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureParameterIivEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureParameterIuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureParameterIuivEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureParameterfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureParameterfvEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureParameterivEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint64</ptype> <name>glGetTextureSamplerHandleARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint64</ptype> <name>glGetTextureSamplerHandleIMG</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <alias name="glGetTextureSamplerHandleARB"/>
+        </command>
+        <command>
+            <proto><ptype>GLuint64</ptype> <name>glGetTextureSamplerHandleNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTextureSubImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTrackMatrixivNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>address</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1300"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTransformFeedbackVarying</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>size</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>type</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTransformFeedbackVaryingEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>size</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>type</name></param>
+            <param len="bufSize"><ptype>GLchar</ptype> *<name>name</name></param>
+            <alias name="glGetTransformFeedbackVarying"/>
+        </command>
+        <command>
+            <proto>void <name>glGetTransformFeedbackVaryingNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>location</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTransformFeedbacki64_v</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint64</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTransformFeedbacki_v</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTransformFeedbackiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTranslatedShaderSourceANGLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufsize</name></param>
+            <param len="1"><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param><ptype>GLchar</ptype> *<name>source</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glGetUniformBlockIndex</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param len="COMPSIZE()">const <ptype>GLchar</ptype> *<name>uniformBlockName</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetUniformBufferSizeEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformIndices</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLsizei</ptype> <name>uniformCount</name></param>
+            <param len="COMPSIZE(uniformCount)">const <ptype>GLchar</ptype> *const*<name>uniformNames</name></param>
+            <param len="COMPSIZE(uniformCount)"><ptype>GLuint</ptype> *<name>uniformIndices</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetUniformLocation</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetUniformLocationARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <param>const <ptype>GLcharARB</ptype> *<name>name</name></param>
+            <alias name="glGetUniformLocation"/>
+        </command>
+        <command>
+            <proto group="BufferOffset"><ptype>GLintptr</ptype> <name>glGetUniformOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformSubroutineuiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="1"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformdv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformfvARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(programObj,location)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glGetUniformfv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformi64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformi64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLint64EXT</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformivARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(programObj,location)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetUniformiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLuint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLuint64EXT</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetUniformuivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetUniformuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVariantArrayObjectfvATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="ArrayObjectPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVariantArrayObjectivATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="ArrayObjectPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVariantBooleanvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param group="Boolean" len="COMPSIZE(id)"><ptype>GLboolean</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVariantFloatvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param len="COMPSIZE(id)"><ptype>GLfloat</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVariantIntegervEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param len="COMPSIZE(id)"><ptype>GLint</ptype> *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVariantPointervEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="GetVariantValueEXT"><ptype>GLenum</ptype> <name>value</name></param>
+            <param len="COMPSIZE(id)">void **<name>data</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glGetVaryingLocationNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexArrayIndexed64iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint64</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexArrayIndexediv</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexArrayIntegeri_vEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexArrayIntegervEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexArrayPointeri_vEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>void **<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexArrayPointervEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexArrayiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribArrayObjectfvATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="ArrayObjectPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribArrayObjectivATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="ArrayObjectPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribIiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnum"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribIivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnum"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetVertexAttribIiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribIuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnum"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribIuivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnum"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetVertexAttribIuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribLdv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribLdvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <alias name="glGetVertexAttribLdv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribLi64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint64EXT</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribLui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint64EXT</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribLui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint64EXT</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribPointerv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribPointerPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>pointer</name></param>
+            <glx type="single" opcode="209"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribPointervARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribPointerPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>pointer</name></param>
+            <alias name="glGetVertexAttribPointerv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribPointervNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">void **<name>pointer</name></param>
+            <alias name="glGetVertexAttribPointerv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribdv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1301"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribdvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <alias name="glGetVertexAttribdv"/>
+            <glx type="vendor" opcode="1301"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribdvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <alias name="glGetVertexAttribdv"/>
+            <glx type="vendor" opcode="1301"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1302"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribfvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glGetVertexAttribfv"/>
+            <glx type="vendor" opcode="1302"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glGetVertexAttribfv"/>
+            <glx type="vendor" opcode="1302"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="vendor" opcode="1303"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribivARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribPropertyARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="4"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetVertexAttribiv"/>
+            <glx type="vendor" opcode="1303"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexAttribivNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetVertexAttribiv"/>
+            <glx type="vendor" opcode="1303"/>
+        </command>
+        <command>
+            <proto>void <name>glGetVideoCaptureStreamdvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVideoCaptureStreamfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVideoCaptureStreamivNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVideoCaptureivNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVideoi64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_slot</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint64EXT</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVideoivNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_slot</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVideoui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_slot</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint64EXT</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVideouivNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_slot</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnColorTable</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>table</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnColorTableARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>table</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnCompressedTexImage</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>lod</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnCompressedTexImageARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>lod</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>img</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnConvolutionFilter</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>image</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnConvolutionFilterARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>image</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnHistogram</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnHistogramARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnMapdv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnMapdvARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnMapfv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnMapfvARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnMapiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnMapivARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnMinmax</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnMinmaxARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnPixelMapfv</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnPixelMapfvARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLfloat</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnPixelMapuiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLuint</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnPixelMapuivARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLuint</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnPixelMapusv</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLushort</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnPixelMapusvARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLushort</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnPolygonStipple</name></proto>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLubyte</ptype> *<name>pattern</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnPolygonStippleARB</name></proto>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLubyte</ptype> *<name>pattern</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnSeparableFilter</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>rowBufSize</name></param>
+            <param>void *<name>row</name></param>
+            <param><ptype>GLsizei</ptype> <name>columnBufSize</name></param>
+            <param>void *<name>column</name></param>
+            <param>void *<name>span</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnSeparableFilterARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>rowBufSize</name></param>
+            <param len="rowBufSize">void *<name>row</name></param>
+            <param><ptype>GLsizei</ptype> <name>columnBufSize</name></param>
+            <param len="columnBufSize">void *<name>column</name></param>
+            <param len="0">void *<name>span</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnTexImage</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnTexImageARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>img</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformdv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformdvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformfvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformfvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformfvKHR</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glGetnUniformfv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformi64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformivARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformivKHR</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetnUniformiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLuint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformuivARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformuivKHR</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetnUniformuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGlobalAlphaFactorbSUN</name></proto>
+            <param><ptype>GLbyte</ptype> <name>factor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGlobalAlphaFactordSUN</name></proto>
+            <param><ptype>GLdouble</ptype> <name>factor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGlobalAlphaFactorfSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>factor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGlobalAlphaFactoriSUN</name></proto>
+            <param><ptype>GLint</ptype> <name>factor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGlobalAlphaFactorsSUN</name></proto>
+            <param><ptype>GLshort</ptype> <name>factor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGlobalAlphaFactorubSUN</name></proto>
+            <param><ptype>GLubyte</ptype> <name>factor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGlobalAlphaFactoruiSUN</name></proto>
+            <param><ptype>GLuint</ptype> <name>factor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGlobalAlphaFactorusSUN</name></proto>
+            <param><ptype>GLushort</ptype> <name>factor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glHint</name></proto>
+            <param group="HintTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="HintMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="85"/>
+        </command>
+        <command>
+            <proto>void <name>glHintPGI</name></proto>
+            <param group="HintTargetPGI"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glHistogram</name></proto>
+            <param group="HistogramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>sink</name></param>
+            <glx type="render" opcode="4110"/>
+        </command>
+        <command>
+            <proto>void <name>glHistogramEXT</name></proto>
+            <param group="HistogramTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>sink</name></param>
+            <alias name="glHistogram"/>
+            <glx type="render" opcode="4110"/>
+        </command>
+        <command>
+            <proto>void <name>glIglooInterfaceSGIX</name></proto>
+            <param group="IglooFunctionSelectSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="IglooParameterSGIX" len="COMPSIZE(pname)">const void *<name>params</name></param>
+            <glx type="render" opcode="200"/>
+        </command>
+        <command>
+            <proto>void <name>glImageTransformParameterfHP</name></proto>
+            <param group="ImageTransformTargetHP"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ImageTransformPNameHP"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glImageTransformParameterfvHP</name></proto>
+            <param group="ImageTransformTargetHP"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ImageTransformPNameHP"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glImageTransformParameteriHP</name></proto>
+            <param group="ImageTransformTargetHP"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ImageTransformPNameHP"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glImageTransformParameterivHP</name></proto>
+            <param group="ImageTransformTargetHP"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ImageTransformPNameHP"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto group="sync"><ptype>GLsync</ptype> <name>glImportSyncEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>external_sync_type</name></param>
+            <param><ptype>GLintptr</ptype> <name>external_sync</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+        </command>
+        <command>
+            <proto>void <name>glIndexFormatNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glIndexFuncEXT</name></proto>
+            <param group="IndexFunctionEXT"><ptype>GLenum</ptype> <name>func</name></param>
+            <param group="ClampedFloat32"><ptype>GLclampf</ptype> <name>ref</name></param>
+        </command>
+        <command>
+            <proto>void <name>glIndexMask</name></proto>
+            <param group="MaskedColorIndexValueI"><ptype>GLuint</ptype> <name>mask</name></param>
+            <glx type="render" opcode="136"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexMaterialEXT</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="IndexMaterialParameterEXT"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glIndexPointer</name></proto>
+            <param group="IndexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glIndexPointerEXT</name></proto>
+            <param group="IndexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(type,stride,count)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glIndexPointerListIBM</name></proto>
+            <param group="IndexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void **<name>pointer</name></param>
+            <param><ptype>GLint</ptype> <name>ptrstride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glIndexd</name></proto>
+            <param group="ColorIndexValueD"><ptype>GLdouble</ptype> <name>c</name></param>
+            <vecequiv name="glIndexdv"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexdv</name></proto>
+            <param group="ColorIndexValueD" len="1">const <ptype>GLdouble</ptype> *<name>c</name></param>
+            <glx type="render" opcode="24"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexf</name></proto>
+            <param group="ColorIndexValueF"><ptype>GLfloat</ptype> <name>c</name></param>
+            <vecequiv name="glIndexfv"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexfv</name></proto>
+            <param group="ColorIndexValueF" len="1">const <ptype>GLfloat</ptype> *<name>c</name></param>
+            <glx type="render" opcode="25"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexi</name></proto>
+            <param group="ColorIndexValueI"><ptype>GLint</ptype> <name>c</name></param>
+            <vecequiv name="glIndexiv"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexiv</name></proto>
+            <param group="ColorIndexValueI" len="1">const <ptype>GLint</ptype> *<name>c</name></param>
+            <glx type="render" opcode="26"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexs</name></proto>
+            <param group="ColorIndexValueS"><ptype>GLshort</ptype> <name>c</name></param>
+            <vecequiv name="glIndexsv"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexsv</name></proto>
+            <param group="ColorIndexValueS" len="1">const <ptype>GLshort</ptype> *<name>c</name></param>
+            <glx type="render" opcode="27"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexub</name></proto>
+            <param group="ColorIndexValueUB"><ptype>GLubyte</ptype> <name>c</name></param>
+            <vecequiv name="glIndexubv"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexubv</name></proto>
+            <param group="ColorIndexValueUB" len="1">const <ptype>GLubyte</ptype> *<name>c</name></param>
+            <glx type="render" opcode="194"/>
+        </command>
+        <command>
+            <proto>void <name>glIndexxOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>component</name></param>
+        </command>
+        <command>
+            <proto>void <name>glIndexxvOES</name></proto>
+            <param len="1">const <ptype>GLfixed</ptype> *<name>component</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInitNames</name></proto>
+            <glx type="render" opcode="121"/>
+        </command>
+        <command>
+            <proto>void <name>glInsertComponentEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>res</name></param>
+            <param><ptype>GLuint</ptype> <name>src</name></param>
+            <param><ptype>GLuint</ptype> <name>num</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInsertEventMarkerEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>marker</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInstrumentsBufferSGIX</name></proto>
+            <param><ptype>GLsizei</ptype> <name>size</name></param>
+            <param len="size"><ptype>GLint</ptype> *<name>buffer</name></param>
+            <glx type="vendor" opcode="4103"/>
+        </command>
+        <command>
+            <proto>void <name>glInterleavedArrays</name></proto>
+            <param group="InterleavedArrayFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(format,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInterpolatePathsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>resultPath</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathA</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathB</name></param>
+            <param><ptype>GLfloat</ptype> <name>weight</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInvalidateBufferData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInvalidateBufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInvalidateFramebuffer</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>numAttachments</name></param>
+            <param len="numAttachments">const <ptype>GLenum</ptype> *<name>attachments</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInvalidateNamedFramebufferData</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>numAttachments</name></param>
+            <param>const <ptype>GLenum</ptype> *<name>attachments</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInvalidateNamedFramebufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>numAttachments</name></param>
+            <param>const <ptype>GLenum</ptype> *<name>attachments</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInvalidateSubFramebuffer</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>numAttachments</name></param>
+            <param len="numAttachments">const <ptype>GLenum</ptype> *<name>attachments</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInvalidateTexImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInvalidateTexSubImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsAsyncMarkerSGIX</name></proto>
+            <param><ptype>GLuint</ptype> <name>marker</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsBufferARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <alias name="glIsBuffer"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsBufferResidentNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsCommandListNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsEnabled</name></proto>
+            <param group="EnableCap"><ptype>GLenum</ptype> <name>cap</name></param>
+            <glx type="single" opcode="140"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsEnabledIndexedEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glIsEnabledi"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsEnabledi</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsEnablediEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glIsEnabledi"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsEnablediNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glIsEnabledi"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsEnablediOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glIsEnabledi"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsFenceAPPLE</name></proto>
+            <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsFenceNV</name></proto>
+            <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
+            <glx type="vendor" opcode="1278"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsFramebuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <glx type="vendor" opcode="1425"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsFramebufferEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <alias name="glIsFramebuffer"/>
+            <glx type="vendor" opcode="1425"/>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsFramebufferOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsImageHandleResidentARB</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsImageHandleResidentNV</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsList</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <glx type="single" opcode="141"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsNameAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>identifier</name></param>
+            <param><ptype>GLuint</ptype> <name>name</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsNamedBufferResidentNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsNamedStringARB</name></proto>
+            <param><ptype>GLint</ptype> <name>namelen</name></param>
+            <param len="namelen">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsObjectBufferATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsOcclusionQueryNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsPathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsPointInFillPathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsPointInStrokePathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsProgram</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <glx type="single" opcode="197"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsProgramARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <glx type="vendor" opcode="1304"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsProgramNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <alias name="glIsProgramARB"/>
+            <glx type="vendor" opcode="1304"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsProgramPipeline</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsProgramPipelineEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsQuery</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <glx type="single" opcode="163"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsQueryARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <alias name="glIsQuery"/>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsQueryEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsRenderbuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <glx type="vendor" opcode="1422"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsRenderbufferEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <alias name="glIsRenderbuffer"/>
+            <glx type="vendor" opcode="1422"/>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsRenderbufferOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsSampler</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsShader</name></proto>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+            <glx type="single" opcode="196"/>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsStateNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>state</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsSync</name></proto>
+            <param group="sync"><ptype>GLsync</ptype> <name>sync</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsSyncAPPLE</name></proto>
+            <param><ptype>GLsync</ptype> <name>sync</name></param>
+            <alias name="glIsSync"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsTexture</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <glx type="single" opcode="146"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsTextureEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <glx type="vendor" opcode="14"/>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsTextureHandleResidentARB</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsTextureHandleResidentNV</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsTransformFeedback</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsTransformFeedbackNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <alias name="glIsTransformFeedback"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsVariantEnabledEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="VariantCapEXT"><ptype>GLenum</ptype> <name>cap</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsVertexArray</name></proto>
+            <param><ptype>GLuint</ptype> <name>array</name></param>
+            <glx type="single" opcode="207"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsVertexArrayAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>array</name></param>
+            <alias name="glIsVertexArray"/>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsVertexArrayOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>array</name></param>
+            <alias name="glIsVertexArray"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsVertexAttribEnabledAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLabelObjectEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>object</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>label</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLightEnviSGIX</name></proto>
+            <param group="LightEnvParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLightModelf</name></proto>
+            <param group="LightModelParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="90"/>
+        </command>
+        <command>
+            <proto>void <name>glLightModelfv</name></proto>
+            <param group="LightModelParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="91"/>
+        </command>
+        <command>
+            <proto>void <name>glLightModeli</name></proto>
+            <param group="LightModelParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="92"/>
+        </command>
+        <command>
+            <proto>void <name>glLightModeliv</name></proto>
+            <param group="LightModelParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="93"/>
+        </command>
+        <command>
+            <proto>void <name>glLightModelx</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLightModelxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLightModelxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLightModelxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLightf</name></proto>
+            <param group="LightName"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="LightParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="86"/>
+        </command>
+        <command>
+            <proto>void <name>glLightfv</name></proto>
+            <param group="LightName"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="LightParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="87"/>
+        </command>
+        <command>
+            <proto>void <name>glLighti</name></proto>
+            <param group="LightName"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="LightParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="88"/>
+        </command>
+        <command>
+            <proto>void <name>glLightiv</name></proto>
+            <param group="LightName"><ptype>GLenum</ptype> <name>light</name></param>
+            <param group="LightParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="89"/>
+        </command>
+        <command>
+            <proto>void <name>glLightx</name></proto>
+            <param><ptype>GLenum</ptype> <name>light</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLightxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>light</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLightxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>light</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLightxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>light</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLineStipple</name></proto>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>factor</name></param>
+            <param group="LineStipple"><ptype>GLushort</ptype> <name>pattern</name></param>
+            <glx type="render" opcode="94"/>
+        </command>
+        <command>
+            <proto>void <name>glLineWidth</name></proto>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>width</name></param>
+            <glx type="render" opcode="95"/>
+        </command>
+        <command>
+            <proto>void <name>glLineWidthx</name></proto>
+            <param><ptype>GLfixed</ptype> <name>width</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLineWidthxOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>width</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLinkProgram</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLinkProgramARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <alias name="glLinkProgram"/>
+        </command>
+        <command>
+            <proto>void <name>glListBase</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>base</name></param>
+            <glx type="render" opcode="3"/>
+        </command>
+        <command>
+            <proto>void <name>glListDrawCommandsStatesClientNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+            <param><ptype>GLuint</ptype> <name>segment</name></param>
+            <param>const void **<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>states</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>fbos</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glListParameterfSGIX</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <param group="ListParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="2078"/>
+        </command>
+        <command>
+            <proto>void <name>glListParameterfvSGIX</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <param group="ListParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="2079"/>
+        </command>
+        <command>
+            <proto>void <name>glListParameteriSGIX</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <param group="ListParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="2080"/>
+        </command>
+        <command>
+            <proto>void <name>glListParameterivSGIX</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <param group="ListParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="2081"/>
+        </command>
+        <command>
+            <proto>void <name>glLoadIdentity</name></proto>
+            <glx type="render" opcode="176"/>
+        </command>
+        <command>
+            <proto>void <name>glLoadIdentityDeformationMapSGIX</name></proto>
+            <param group="FfdMaskSGIX"><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <glx type="render" opcode="2076"/>
+        </command>
+        <command>
+            <proto>void <name>glLoadMatrixd</name></proto>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+            <glx type="render" opcode="178"/>
+        </command>
+        <command>
+            <proto>void <name>glLoadMatrixf</name></proto>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+            <glx type="render" opcode="177"/>
+        </command>
+        <command>
+            <proto>void <name>glLoadMatrixx</name></proto>
+            <param len="16">const <ptype>GLfixed</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLoadMatrixxOES</name></proto>
+            <param len="16">const <ptype>GLfixed</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLoadName</name></proto>
+            <param group="SelectName"><ptype>GLuint</ptype> <name>name</name></param>
+            <glx type="render" opcode="122"/>
+        </command>
+        <command>
+            <proto>void <name>glLoadPaletteFromModelViewMatrixOES</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glLoadProgramNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="len">const <ptype>GLubyte</ptype> *<name>program</name></param>
+            <glx type="render" opcode="4183"/>
+        </command>
+        <command>
+            <proto>void <name>glLoadTransposeMatrixd</name></proto>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLoadTransposeMatrixdARB</name></proto>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+            <alias name="glLoadTransposeMatrixd"/>
+        </command>
+        <command>
+            <proto>void <name>glLoadTransposeMatrixf</name></proto>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLoadTransposeMatrixfARB</name></proto>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+            <alias name="glLoadTransposeMatrixf"/>
+        </command>
+        <command>
+            <proto>void <name>glLoadTransposeMatrixxOES</name></proto>
+            <param len="16">const <ptype>GLfixed</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLockArraysEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glLogicOp</name></proto>
+            <param group="LogicOp"><ptype>GLenum</ptype> <name>opcode</name></param>
+            <glx type="render" opcode="161"/>
+        </command>
+        <command>
+            <proto>void <name>glMakeBufferNonResidentNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeBufferResidentNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeImageHandleNonResidentARB</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeImageHandleNonResidentNV</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeImageHandleResidentARB</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeImageHandleResidentNV</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeNamedBufferNonResidentNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeNamedBufferResidentNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeTextureHandleNonResidentARB</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeTextureHandleNonResidentNV</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeTextureHandleResidentARB</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMakeTextureHandleResidentNV</name></proto>
+            <param><ptype>GLuint64</ptype> <name>handle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMap1d</name></proto>
+            <param group="MapTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>order</name></param>
+            <param group="CoordD" len="COMPSIZE(target,stride,order)">const <ptype>GLdouble</ptype> *<name>points</name></param>
+            <glx type="render" opcode="143"/>
+        </command>
+        <command>
+            <proto>void <name>glMap1f</name></proto>
+            <param group="MapTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>order</name></param>
+            <param group="CoordF" len="COMPSIZE(target,stride,order)">const <ptype>GLfloat</ptype> *<name>points</name></param>
+            <glx type="render" opcode="144"/>
+        </command>
+        <command>
+            <proto>void <name>glMap1xOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLfixed</ptype> <name>u1</name></param>
+            <param><ptype>GLfixed</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param><ptype>GLint</ptype> <name>order</name></param>
+            <param><ptype>GLfixed</ptype> <name>points</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMap2d</name></proto>
+            <param group="MapTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>ustride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>uorder</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>v1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>vstride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>vorder</name></param>
+            <param group="CoordD" len="COMPSIZE(target,ustride,uorder,vstride,vorder)">const <ptype>GLdouble</ptype> *<name>points</name></param>
+            <glx type="render" opcode="145"/>
+        </command>
+        <command>
+            <proto>void <name>glMap2f</name></proto>
+            <param group="MapTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>ustride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>uorder</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>vstride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>vorder</name></param>
+            <param group="CoordF" len="COMPSIZE(target,ustride,uorder,vstride,vorder)">const <ptype>GLfloat</ptype> *<name>points</name></param>
+            <glx type="render" opcode="146"/>
+        </command>
+        <command>
+            <proto>void <name>glMap2xOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLfixed</ptype> <name>u1</name></param>
+            <param><ptype>GLfixed</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>ustride</name></param>
+            <param><ptype>GLint</ptype> <name>uorder</name></param>
+            <param><ptype>GLfixed</ptype> <name>v1</name></param>
+            <param><ptype>GLfixed</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>vstride</name></param>
+            <param><ptype>GLint</ptype> <name>vorder</name></param>
+            <param><ptype>GLfixed</ptype> <name>points</name></param>
+        </command>
+        <command>
+            <proto>void *<name>glMapBuffer</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferAccessARB"><ptype>GLenum</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void *<name>glMapBufferARB</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferAccessARB"><ptype>GLenum</ptype> <name>access</name></param>
+            <alias name="glMapBuffer"/>
+        </command>
+        <command>
+            <proto>void *<name>glMapBufferOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+            <alias name="glMapBuffer"/>
+        </command>
+        <command>
+            <proto>void *<name>glMapBufferRange</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>length</name></param>
+            <param group="BufferAccessMask"><ptype>GLbitfield</ptype> <name>access</name></param>
+            <glx type="single" opcode="205"/>
+        </command>
+        <command>
+            <proto>void *<name>glMapBufferRangeEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>length</name></param>
+            <param><ptype>GLbitfield</ptype> <name>access</name></param>
+            <alias name="glMapBufferRange"/>
+        </command>
+        <command>
+            <proto>void <name>glMapControlPointsNV</name></proto>
+            <param group="EvalTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="MapTypeNV"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>ustride</name></param>
+            <param><ptype>GLsizei</ptype> <name>vstride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>uorder</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>vorder</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>packed</name></param>
+            <param len="COMPSIZE(target,uorder,vorder)">const void *<name>points</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMapGrid1d</name></proto>
+            <param><ptype>GLint</ptype> <name>un</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u2</name></param>
+            <glx type="render" opcode="147"/>
+        </command>
+        <command>
+            <proto>void <name>glMapGrid1f</name></proto>
+            <param><ptype>GLint</ptype> <name>un</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u2</name></param>
+            <glx type="render" opcode="148"/>
+        </command>
+        <command>
+            <proto>void <name>glMapGrid1xOES</name></proto>
+            <param><ptype>GLint</ptype> <name>n</name></param>
+            <param><ptype>GLfixed</ptype> <name>u1</name></param>
+            <param><ptype>GLfixed</ptype> <name>u2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMapGrid2d</name></proto>
+            <param><ptype>GLint</ptype> <name>un</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>vn</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>v1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>v2</name></param>
+            <glx type="render" opcode="149"/>
+        </command>
+        <command>
+            <proto>void <name>glMapGrid2f</name></proto>
+            <param><ptype>GLint</ptype> <name>un</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>vn</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>v2</name></param>
+            <glx type="render" opcode="150"/>
+        </command>
+        <command>
+            <proto>void <name>glMapGrid2xOES</name></proto>
+            <param><ptype>GLint</ptype> <name>n</name></param>
+            <param><ptype>GLfixed</ptype> <name>u1</name></param>
+            <param><ptype>GLfixed</ptype> <name>u2</name></param>
+            <param><ptype>GLfixed</ptype> <name>v1</name></param>
+            <param><ptype>GLfixed</ptype> <name>v2</name></param>
+        </command>
+        <command>
+            <proto>void *<name>glMapNamedBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void *<name>glMapNamedBufferEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="VertexBufferObjectAccess"><ptype>GLenum</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void *<name>glMapNamedBufferRange</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>length</name></param>
+            <param><ptype>GLbitfield</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void *<name>glMapNamedBufferRangeEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>length</name></param>
+            <param group="BufferAccessMask"><ptype>GLbitfield</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void *<name>glMapObjectBufferATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMapParameterfvNV</name></proto>
+            <param group="EvalTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="MapParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(target,pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMapParameterivNV</name></proto>
+            <param group="EvalTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="MapParameterNV"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(target,pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void *<name>glMapTexture2DINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLbitfield</ptype> <name>access</name></param>
+            <param len="1"><ptype>GLint</ptype> *<name>stride</name></param>
+            <param len="1"><ptype>GLenum</ptype> *<name>layout</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMapVertexAttrib1dAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>size</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>order</name></param>
+            <param group="CoordD" len="COMPSIZE(size,stride,order)">const <ptype>GLdouble</ptype> *<name>points</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMapVertexAttrib1fAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>size</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>order</name></param>
+            <param group="CoordF" len="COMPSIZE(size,stride,order)">const <ptype>GLfloat</ptype> *<name>points</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMapVertexAttrib2dAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>size</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>ustride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>uorder</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>v1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>vstride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>vorder</name></param>
+            <param group="CoordD" len="COMPSIZE(size,ustride,uorder,vstride,vorder)">const <ptype>GLdouble</ptype> *<name>points</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMapVertexAttrib2fAPPLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>size</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>u2</name></param>
+            <param><ptype>GLint</ptype> <name>ustride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>uorder</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>vstride</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>vorder</name></param>
+            <param group="CoordF" len="COMPSIZE(size,ustride,uorder,vstride,vorder)">const <ptype>GLfloat</ptype> *<name>points</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMaterialf</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="96"/>
+        </command>
+        <command>
+            <proto>void <name>glMaterialfv</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="97"/>
+        </command>
+        <command>
+            <proto>void <name>glMateriali</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="98"/>
+        </command>
+        <command>
+            <proto>void <name>glMaterialiv</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="99"/>
+        </command>
+        <command>
+            <proto>void <name>glMaterialx</name></proto>
+            <param><ptype>GLenum</ptype> <name>face</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMaterialxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>face</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMaterialxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>face</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMaterialxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>face</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixFrustumEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLdouble</ptype> <name>left</name></param>
+            <param><ptype>GLdouble</ptype> <name>right</name></param>
+            <param><ptype>GLdouble</ptype> <name>bottom</name></param>
+            <param><ptype>GLdouble</ptype> <name>top</name></param>
+            <param><ptype>GLdouble</ptype> <name>zNear</name></param>
+            <param><ptype>GLdouble</ptype> <name>zFar</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixIndexPointerARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="MatrixIndexPointerTypeARB"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixIndexPointerOES</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixIndexubvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLubyte</ptype> *<name>indices</name></param>
+            <glx type="render" opcode="4326"/>
+        </command>
+        <command>
+            <proto>void <name>glMatrixIndexuivARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLuint</ptype> *<name>indices</name></param>
+            <glx type="render" opcode="4328"/>
+        </command>
+        <command>
+            <proto>void <name>glMatrixIndexusvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLushort</ptype> *<name>indices</name></param>
+            <glx type="render" opcode="4327"/>
+        </command>
+        <command>
+            <proto>void <name>glMatrixLoad3x2fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixLoad3x3fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixLoadIdentityEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixLoadTranspose3x3fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixLoadTransposedEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixLoadTransposefEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixLoaddEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixLoadfEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMode</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="179"/>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMult3x2fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMult3x3fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMultTranspose3x3fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMultTransposedEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMultTransposefEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMultdEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMultfEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixOrthoEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLdouble</ptype> <name>left</name></param>
+            <param><ptype>GLdouble</ptype> <name>right</name></param>
+            <param><ptype>GLdouble</ptype> <name>bottom</name></param>
+            <param><ptype>GLdouble</ptype> <name>top</name></param>
+            <param><ptype>GLdouble</ptype> <name>zNear</name></param>
+            <param><ptype>GLdouble</ptype> <name>zFar</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixPopEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixPushEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixRotatedEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLdouble</ptype> <name>angle</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixRotatefEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLfloat</ptype> <name>angle</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixScaledEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixScalefEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixTranslatedEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixTranslatefEXT</name></proto>
+            <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMaxShaderCompilerThreadsARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMemoryBarrier</name></proto>
+            <param><ptype>GLbitfield</ptype> <name>barriers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMemoryBarrierByRegion</name></proto>
+            <param><ptype>GLbitfield</ptype> <name>barriers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMemoryBarrierEXT</name></proto>
+            <param><ptype>GLbitfield</ptype> <name>barriers</name></param>
+            <alias name="glMemoryBarrier"/>
+        </command>
+        <command>
+            <proto>void <name>glMinSampleShading</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMinSampleShadingARB</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>value</name></param>
+            <alias name="glMinSampleShading"/>
+        </command>
+        <command>
+            <proto>void <name>glMinSampleShadingOES</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>value</name></param>
+            <alias name="glMinSampleShading"/>
+        </command>
+        <command>
+            <proto>void <name>glMinmax</name></proto>
+            <param group="MinmaxTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>sink</name></param>
+            <glx type="render" opcode="4111"/>
+        </command>
+        <command>
+            <proto>void <name>glMinmaxEXT</name></proto>
+            <param group="MinmaxTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>sink</name></param>
+            <alias name="glMinmax"/>
+            <glx type="render" opcode="4111"/>
+        </command>
+        <command>
+            <proto>void <name>glMultMatrixd</name></proto>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+            <glx type="render" opcode="181"/>
+        </command>
+        <command>
+            <proto>void <name>glMultMatrixf</name></proto>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+            <glx type="render" opcode="180"/>
+        </command>
+        <command>
+            <proto>void <name>glMultMatrixx</name></proto>
+            <param len="16">const <ptype>GLfixed</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultMatrixxOES</name></proto>
+            <param len="16">const <ptype>GLfixed</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultTransposeMatrixd</name></proto>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultTransposeMatrixdARB</name></proto>
+            <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
+            <alias name="glMultTransposeMatrixd"/>
+        </command>
+        <command>
+            <proto>void <name>glMultTransposeMatrixf</name></proto>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultTransposeMatrixfARB</name></proto>
+            <param len="16">const <ptype>GLfloat</ptype> *<name>m</name></param>
+            <alias name="glMultTransposeMatrixf"/>
+        </command>
+        <command>
+            <proto>void <name>glMultTransposeMatrixxOES</name></proto>
+            <param len="16">const <ptype>GLfixed</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawArrays</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLint</ptype> *<name>first</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawcount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawArraysEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(primcount)">const <ptype>GLint</ptype> *<name>first</name></param>
+            <param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glMultiDrawArrays"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawArraysIndirect</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(drawcount,stride)">const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawArraysIndirectAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param>const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <alias name="glMultiDrawArraysIndirect"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawArraysIndirectBindlessCountNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param>const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxDrawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLint</ptype> <name>vertexBufferCount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawArraysIndirectBindlessNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param>const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLint</ptype> <name>vertexBufferCount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawArraysIndirectCountARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLintptr</ptype> <name>indirect</name></param>
+            <param><ptype>GLintptr</ptype> <name>drawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxdrawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawArraysIndirectEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(drawcount,stride)">const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <alias name="glMultiDrawArraysIndirect"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementArrayAPPLE</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="primcount">const <ptype>GLint</ptype> *<name>first</name></param>
+            <param len="primcount">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElements</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(drawcount)">const void *const*<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawcount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsBaseVertex</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(drawcount)">const void *const*<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawcount</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLint</ptype> *<name>basevertex</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsBaseVertexEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(drawcount)">const void *const*<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLint</ptype> *<name>basevertex</name></param>
+            <alias name="glMultiDrawElementsBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsBaseVertexOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(drawcount)">const void *const*<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLint</ptype> *<name>basevertex</name></param>
+            <alias name="glMultiDrawElementsBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(primcount)">const void *const*<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <alias name="glMultiDrawElements"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsIndirect</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(drawcount,stride)">const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsIndirectAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <alias name="glMultiDrawElementsIndirect"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsIndirectBindlessCountNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxDrawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLint</ptype> <name>vertexBufferCount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsIndirectBindlessNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLint</ptype> <name>vertexBufferCount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsIndirectCountARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLintptr</ptype> <name>indirect</name></param>
+            <param><ptype>GLintptr</ptype> <name>drawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxdrawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsIndirectEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(drawcount,stride)">const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <alias name="glMultiDrawElementsIndirect"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawRangeElementArrayAPPLE</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param len="primcount">const <ptype>GLint</ptype> *<name>first</name></param>
+            <param len="primcount">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiModeDrawArraysIBM</name></proto>
+            <param group="PrimitiveType" len="COMPSIZE(primcount)">const <ptype>GLenum</ptype> *<name>mode</name></param>
+            <param len="COMPSIZE(primcount)">const <ptype>GLint</ptype> *<name>first</name></param>
+            <param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <param><ptype>GLint</ptype> <name>modestride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiModeDrawElementsIBM</name></proto>
+            <param group="PrimitiveType" len="COMPSIZE(primcount)">const <ptype>GLenum</ptype> *<name>mode</name></param>
+            <param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(primcount)">const void *const*<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <param><ptype>GLint</ptype> <name>modestride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexBufferEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1bOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLbyte</ptype> <name>s</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1bvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param len="1">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1d</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <vecequiv name="glMultiTexCoord1dv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1dARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <vecequiv name="glMultiTexCoord1dv"/>
+            <alias name="glMultiTexCoord1d"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1dv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD" len="1">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="198"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1dvARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD" len="1">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord1dv"/>
+            <glx type="render" opcode="198"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1f</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <vecequiv name="glMultiTexCoord1fv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1fARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <vecequiv name="glMultiTexCoord1fv"/>
+            <alias name="glMultiTexCoord1f"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1fv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF" len="1">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="199"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1fvARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF" len="1">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord1fv"/>
+            <glx type="render" opcode="199"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1hNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>s</name></param>
+            <vecequiv name="glMultiTexCoord1hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1hvNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Half16NV" len="1">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4250"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1i</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <vecequiv name="glMultiTexCoord1iv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1iARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <vecequiv name="glMultiTexCoord1iv"/>
+            <alias name="glMultiTexCoord1i"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1iv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI" len="1">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="200"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1ivARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI" len="1">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord1iv"/>
+            <glx type="render" opcode="200"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1s</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <vecequiv name="glMultiTexCoord1sv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1sARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <vecequiv name="glMultiTexCoord1sv"/>
+            <alias name="glMultiTexCoord1s"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1sv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS" len="1">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="201"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1svARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS" len="1">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord1sv"/>
+            <glx type="render" opcode="201"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1xOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLfixed</ptype> <name>s</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord1xvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param len="1">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2bOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLbyte</ptype> <name>s</name></param>
+            <param><ptype>GLbyte</ptype> <name>t</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2bvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param len="2">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2d</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>t</name></param>
+            <vecequiv name="glMultiTexCoord2dv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2dARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>t</name></param>
+            <vecequiv name="glMultiTexCoord2dv"/>
+            <alias name="glMultiTexCoord2d"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2dv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="202"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2dvARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord2dv"/>
+            <glx type="render" opcode="202"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2f</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>t</name></param>
+            <vecequiv name="glMultiTexCoord2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2fARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>t</name></param>
+            <vecequiv name="glMultiTexCoord2fv"/>
+            <alias name="glMultiTexCoord2f"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2fv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="203"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2fvARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord2fv"/>
+            <glx type="render" opcode="203"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2hNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>s</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>t</name></param>
+            <vecequiv name="glMultiTexCoord2hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2hvNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Half16NV" len="2">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4251"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2i</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>t</name></param>
+            <vecequiv name="glMultiTexCoord2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2iARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>t</name></param>
+            <vecequiv name="glMultiTexCoord2iv"/>
+            <alias name="glMultiTexCoord2i"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2iv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="204"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2ivARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord2iv"/>
+            <glx type="render" opcode="204"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2s</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>t</name></param>
+            <vecequiv name="glMultiTexCoord2sv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2sARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>t</name></param>
+            <vecequiv name="glMultiTexCoord2sv"/>
+            <alias name="glMultiTexCoord2s"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2sv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="205"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2svARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord2sv"/>
+            <glx type="render" opcode="205"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2xOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLfixed</ptype> <name>s</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord2xvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param len="2">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3bOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLbyte</ptype> <name>s</name></param>
+            <param><ptype>GLbyte</ptype> <name>t</name></param>
+            <param><ptype>GLbyte</ptype> <name>r</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3bvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param len="3">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3d</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>t</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>r</name></param>
+            <vecequiv name="glMultiTexCoord3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3dARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>t</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>r</name></param>
+            <vecequiv name="glMultiTexCoord3dv"/>
+            <alias name="glMultiTexCoord3d"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3dv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="206"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3dvARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord3dv"/>
+            <glx type="render" opcode="206"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3f</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>t</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>r</name></param>
+            <vecequiv name="glMultiTexCoord3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3fARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>t</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>r</name></param>
+            <vecequiv name="glMultiTexCoord3fv"/>
+            <alias name="glMultiTexCoord3f"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3fv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="207"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3fvARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord3fv"/>
+            <glx type="render" opcode="207"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3hNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>s</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>t</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>r</name></param>
+            <vecequiv name="glMultiTexCoord3hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3hvNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Half16NV" len="3">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4252"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3i</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>t</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>r</name></param>
+            <vecequiv name="glMultiTexCoord3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3iARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>t</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>r</name></param>
+            <vecequiv name="glMultiTexCoord3iv"/>
+            <alias name="glMultiTexCoord3i"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3iv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="208"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3ivARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord3iv"/>
+            <glx type="render" opcode="208"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3s</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>t</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>r</name></param>
+            <vecequiv name="glMultiTexCoord3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3sARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>t</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>r</name></param>
+            <vecequiv name="glMultiTexCoord3sv"/>
+            <alias name="glMultiTexCoord3s"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3sv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="209"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3svARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord3sv"/>
+            <glx type="render" opcode="209"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3xOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLfixed</ptype> <name>s</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+            <param><ptype>GLfixed</ptype> <name>r</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord3xvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param len="3">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4bOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLbyte</ptype> <name>s</name></param>
+            <param><ptype>GLbyte</ptype> <name>t</name></param>
+            <param><ptype>GLbyte</ptype> <name>r</name></param>
+            <param><ptype>GLbyte</ptype> <name>q</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4bvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param len="4">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4d</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>t</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>r</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>q</name></param>
+            <vecequiv name="glMultiTexCoord4dv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4dARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>t</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>r</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>q</name></param>
+            <vecequiv name="glMultiTexCoord4dv"/>
+            <alias name="glMultiTexCoord4d"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4dv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD" len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="210"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4dvARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordD" len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord4dv"/>
+            <glx type="render" opcode="210"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4f</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>t</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>r</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>q</name></param>
+            <vecequiv name="glMultiTexCoord4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4fARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>t</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>r</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>q</name></param>
+            <vecequiv name="glMultiTexCoord4fv"/>
+            <alias name="glMultiTexCoord4f"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4fv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF" len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="211"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4fvARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordF" len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord4fv"/>
+            <glx type="render" opcode="211"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4hNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>s</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>t</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>r</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>q</name></param>
+            <vecequiv name="glMultiTexCoord4hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4hvNV</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="Half16NV" len="4">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4253"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4i</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>t</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>r</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>q</name></param>
+            <vecequiv name="glMultiTexCoord4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4iARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>t</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>r</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>q</name></param>
+            <vecequiv name="glMultiTexCoord4iv"/>
+            <alias name="glMultiTexCoord4i"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4iv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI" len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="212"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4ivARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordI" len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord4iv"/>
+            <glx type="render" opcode="212"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4s</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>t</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>r</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>q</name></param>
+            <vecequiv name="glMultiTexCoord4sv"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4sARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>t</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>r</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>q</name></param>
+            <vecequiv name="glMultiTexCoord4sv"/>
+            <alias name="glMultiTexCoord4s"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4sv</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS" len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="213"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4svARB</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CoordS" len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glMultiTexCoord4sv"/>
+            <glx type="render" opcode="213"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4x</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLfixed</ptype> <name>s</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+            <param><ptype>GLfixed</ptype> <name>r</name></param>
+            <param><ptype>GLfixed</ptype> <name>q</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4xOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLfixed</ptype> <name>s</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+            <param><ptype>GLfixed</ptype> <name>r</name></param>
+            <param><ptype>GLfixed</ptype> <name>q</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoord4xvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param len="4">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoordP1ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoordP1uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoordP2ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoordP2uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoordP3ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoordP3uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoordP4ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoordP4uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexCoordPointerEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="TexCoordPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexEnvfEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <vecequiv name="glMultiTexEnvfvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexEnvfvEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexEnviEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <vecequiv name="glMultiTexEnvivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexEnvivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexGendEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLdouble</ptype> <name>param</name></param>
+            <vecequiv name="glMultiTexGendvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexGendvEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexGenfEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <vecequiv name="glMultiTexGenfvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexGenfvEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexGeniEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <vecequiv name="glMultiTexGenivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexGenivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexImage1DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureComponentCount"><ptype>GLint</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexImage2DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureComponentCount"><ptype>GLint</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexImage3DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureComponentCount"><ptype>GLint</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexParameterIivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexParameterIuivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexParameterfEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <vecequiv name="glMultiTexParameterfvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexParameterfvEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexParameteriEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <vecequiv name="glMultiTexParameterivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexParameterivEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexRenderbufferEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexSubImage1DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexSubImage2DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMultiTexSubImage3DEXT</name></proto>
+            <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param>const void *<name>data</name></param>
+            <param><ptype>GLenum</ptype> <name>usage</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferDataEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="COMPSIZE(size)">const void *<name>data</name></param>
+            <param group="VertexBufferObjectUsage"><ptype>GLenum</ptype> <name>usage</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferPageCommitmentARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferPageCommitmentEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferStorage</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferStorageEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+            <alias name="glNamedBufferStorage"/>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="COMPSIZE(size)">const void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferSubDataEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="COMPSIZE(size)">const void *<name>data</name></param>
+            <alias name="glNamedBufferSubData"/>
+        </command>
+        <command>
+            <proto>void <name>glNamedCopyBufferSubDataEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>readBuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>writeBuffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>readOffset</name></param>
+            <param><ptype>GLintptr</ptype> <name>writeOffset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferDrawBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buf</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferDrawBuffers</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLenum</ptype> *<name>bufs</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferParameteri</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferParameteriEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferReadBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>src</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferRenderbuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>renderbuffertarget</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferRenderbufferEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>renderbuffertarget</name></param>
+            <param group="Renderbuffer"><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferSampleLocationsfvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferSampleLocationsfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferTexture</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferSamplePositionsfvAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>numsamples</name></param>
+            <param><ptype>GLuint</ptype> <name>pixelindex</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferTexture1DEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferTexture2DEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferTexture3DEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>textarget</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferTextureEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferTextureFaceEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>face</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferTextureLayer</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>layer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferTextureLayerEXT</name></proto>
+            <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>layer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParameter4dEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+            <vecequiv name="glNamedProgramLocalParameter4dvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParameter4dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParameter4fEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <vecequiv name="glNamedProgramLocalParameter4fvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParameter4fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParameterI4iEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+            <param><ptype>GLint</ptype> <name>w</name></param>
+            <vecequiv name="glNamedProgramLocalParameterI4ivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParameterI4ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParameterI4uiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <param><ptype>GLuint</ptype> <name>z</name></param>
+            <param><ptype>GLuint</ptype> <name>w</name></param>
+            <vecequiv name="glNamedProgramLocalParameterI4uivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParameterI4uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParameters4fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParametersI4ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramLocalParametersI4uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedProgramStringEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ProgramFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="len">const void *<name>string</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedRenderbufferStorage</name></proto>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedRenderbufferStorageEXT</name></proto>
+            <param group="Renderbuffer"><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedRenderbufferStorageMultisample</name></proto>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedRenderbufferStorageMultisampleCoverageEXT</name></proto>
+            <param group="Renderbuffer"><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>coverageSamples</name></param>
+            <param><ptype>GLsizei</ptype> <name>colorSamples</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedRenderbufferStorageMultisampleEXT</name></proto>
+            <param group="Renderbuffer"><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedStringARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLint</ptype> <name>namelen</name></param>
+            <param len="namelen">const <ptype>GLchar</ptype> *<name>name</name></param>
+            <param><ptype>GLint</ptype> <name>stringlen</name></param>
+            <param len="stringlen">const <ptype>GLchar</ptype> *<name>string</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNewList</name></proto>
+            <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
+            <param group="ListMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="single" opcode="101"/>
+        </command>
+        <command>
+            <proto><ptype>GLuint</ptype> <name>glNewObjectBufferATI</name></proto>
+            <param><ptype>GLsizei</ptype> <name>size</name></param>
+            <param len="size">const void *<name>pointer</name></param>
+            <param group="ArrayObjectUsageATI"><ptype>GLenum</ptype> <name>usage</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormal3b</name></proto>
+            <param><ptype>GLbyte</ptype> <name>nx</name></param>
+            <param><ptype>GLbyte</ptype> <name>ny</name></param>
+            <param><ptype>GLbyte</ptype> <name>nz</name></param>
+            <vecequiv name="glNormal3bv"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3bv</name></proto>
+            <param len="3">const <ptype>GLbyte</ptype> *<name>v</name></param>
+            <glx type="render" opcode="28"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>nx</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>ny</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>nz</name></param>
+            <vecequiv name="glNormal3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3dv</name></proto>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="29"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>nz</name></param>
+            <vecequiv name="glNormal3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3fVertex3fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormal3fVertex3fvSUN</name></proto>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>n</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormal3fv</name></proto>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="30"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>nx</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>ny</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>nz</name></param>
+            <vecequiv name="glNormal3hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3hvNV</name></proto>
+            <param group="Half16NV" len="3">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4243"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3i</name></proto>
+            <param><ptype>GLint</ptype> <name>nx</name></param>
+            <param><ptype>GLint</ptype> <name>ny</name></param>
+            <param><ptype>GLint</ptype> <name>nz</name></param>
+            <vecequiv name="glNormal3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3iv</name></proto>
+            <param len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="31"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3s</name></proto>
+            <param><ptype>GLshort</ptype> <name>nx</name></param>
+            <param><ptype>GLshort</ptype> <name>ny</name></param>
+            <param><ptype>GLshort</ptype> <name>nz</name></param>
+            <vecequiv name="glNormal3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3sv</name></proto>
+            <param len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="32"/>
+        </command>
+        <command>
+            <proto>void <name>glNormal3x</name></proto>
+            <param><ptype>GLfixed</ptype> <name>nx</name></param>
+            <param><ptype>GLfixed</ptype> <name>ny</name></param>
+            <param><ptype>GLfixed</ptype> <name>nz</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormal3xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>nx</name></param>
+            <param><ptype>GLfixed</ptype> <name>ny</name></param>
+            <param><ptype>GLfixed</ptype> <name>nz</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormal3xvOES</name></proto>
+            <param len="3">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalFormatNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalP3ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalP3uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalPointer</name></proto>
+            <param group="NormalPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalPointerEXT</name></proto>
+            <param group="NormalPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(type,stride,count)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalPointerListIBM</name></proto>
+            <param group="NormalPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void **<name>pointer</name></param>
+            <param><ptype>GLint</ptype> <name>ptrstride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalPointervINTEL</name></proto>
+            <param group="NormalPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="4">const void **<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3bATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLbyte</ptype> <name>nx</name></param>
+            <param><ptype>GLbyte</ptype> <name>ny</name></param>
+            <param><ptype>GLbyte</ptype> <name>nz</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3bvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="3">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3dATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLdouble</ptype> <name>nx</name></param>
+            <param><ptype>GLdouble</ptype> <name>ny</name></param>
+            <param><ptype>GLdouble</ptype> <name>nz</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3dvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="3">const <ptype>GLdouble</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3fATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3fvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3iATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLint</ptype> <name>nx</name></param>
+            <param><ptype>GLint</ptype> <name>ny</name></param>
+            <param><ptype>GLint</ptype> <name>nz</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3ivATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="3">const <ptype>GLint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3sATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLshort</ptype> <name>nx</name></param>
+            <param><ptype>GLshort</ptype> <name>ny</name></param>
+            <param><ptype>GLshort</ptype> <name>nz</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNormalStream3svATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="3">const <ptype>GLshort</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glObjectLabel</name></proto>
+            <param><ptype>GLenum</ptype> <name>identifier</name></param>
+            <param><ptype>GLuint</ptype> <name>name</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="COMPSIZE(label,length)">const <ptype>GLchar</ptype> *<name>label</name></param>
+        </command>
+        <command>
+            <proto>void <name>glObjectLabelKHR</name></proto>
+            <param><ptype>GLenum</ptype> <name>identifier</name></param>
+            <param><ptype>GLuint</ptype> <name>name</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>label</name></param>
+            <alias name="glObjectLabel"/>
+        </command>
+        <command>
+            <proto>void <name>glObjectPtrLabel</name></proto>
+            <param>const void *<name>ptr</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="COMPSIZE(label,length)">const <ptype>GLchar</ptype> *<name>label</name></param>
+        </command>
+        <command>
+            <proto>void <name>glObjectPtrLabelKHR</name></proto>
+            <param>const void *<name>ptr</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>label</name></param>
+            <alias name="glObjectPtrLabel"/>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glObjectPurgeableAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>objectType</name></param>
+            <param><ptype>GLuint</ptype> <name>name</name></param>
+            <param><ptype>GLenum</ptype> <name>option</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glObjectUnpurgeableAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>objectType</name></param>
+            <param><ptype>GLuint</ptype> <name>name</name></param>
+            <param><ptype>GLenum</ptype> <name>option</name></param>
+        </command>
+        <command>
+            <proto>void <name>glOrtho</name></proto>
+            <param><ptype>GLdouble</ptype> <name>left</name></param>
+            <param><ptype>GLdouble</ptype> <name>right</name></param>
+            <param><ptype>GLdouble</ptype> <name>bottom</name></param>
+            <param><ptype>GLdouble</ptype> <name>top</name></param>
+            <param><ptype>GLdouble</ptype> <name>zNear</name></param>
+            <param><ptype>GLdouble</ptype> <name>zFar</name></param>
+            <glx type="render" opcode="182"/>
+        </command>
+        <command>
+            <proto>void <name>glOrthof</name></proto>
+            <param><ptype>GLfloat</ptype> <name>l</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>n</name></param>
+            <param><ptype>GLfloat</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glOrthofOES</name></proto>
+            <param><ptype>GLfloat</ptype> <name>l</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>n</name></param>
+            <param><ptype>GLfloat</ptype> <name>f</name></param>
+            <glx type="render" opcode="4311"/>
+        </command>
+        <command>
+            <proto>void <name>glOrthox</name></proto>
+            <param><ptype>GLfixed</ptype> <name>l</name></param>
+            <param><ptype>GLfixed</ptype> <name>r</name></param>
+            <param><ptype>GLfixed</ptype> <name>b</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+            <param><ptype>GLfixed</ptype> <name>n</name></param>
+            <param><ptype>GLfixed</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glOrthoxOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>l</name></param>
+            <param><ptype>GLfixed</ptype> <name>r</name></param>
+            <param><ptype>GLfixed</ptype> <name>b</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+            <param><ptype>GLfixed</ptype> <name>n</name></param>
+            <param><ptype>GLfixed</ptype> <name>f</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPNTrianglesfATI</name></proto>
+            <param group="PNTrianglesPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPNTrianglesiATI</name></proto>
+            <param group="PNTrianglesPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPassTexCoordATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>dst</name></param>
+            <param><ptype>GLuint</ptype> <name>coord</name></param>
+            <param group="SwizzleOpATI"><ptype>GLenum</ptype> <name>swizzle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPassThrough</name></proto>
+            <param group="FeedbackElement"><ptype>GLfloat</ptype> <name>token</name></param>
+            <glx type="render" opcode="123"/>
+        </command>
+        <command>
+            <proto>void <name>glPassThroughxOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>token</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPatchParameterfv</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPatchParameteri</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPatchParameteriEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>value</name></param>
+            <alias name="glPatchParameteri"/>
+        </command>
+        <command>
+            <proto>void <name>glPatchParameteriOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>value</name></param>
+            <alias name="glPatchParameteri"/>
+        </command>
+        <command>
+            <proto>void <name>glPathColorGenNV</name></proto>
+            <param group="PathColor"><ptype>GLenum</ptype> <name>color</name></param>
+            <param group="PathGenMode"><ptype>GLenum</ptype> <name>genMode</name></param>
+            <param group="PathColorFormat"><ptype>GLenum</ptype> <name>colorFormat</name></param>
+            <param len="COMPSIZE(genMode,colorFormat)">const <ptype>GLfloat</ptype> *<name>coeffs</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathCommandsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLsizei</ptype> <name>numCommands</name></param>
+            <param group="PathCommand" len="numCommands">const <ptype>GLubyte</ptype> *<name>commands</name></param>
+            <param><ptype>GLsizei</ptype> <name>numCoords</name></param>
+            <param group="PathCoordType"><ptype>GLenum</ptype> <name>coordType</name></param>
+            <param len="COMPSIZE(numCoords,coordType)">const void *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathCoordsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLsizei</ptype> <name>numCoords</name></param>
+            <param group="PathCoordType"><ptype>GLenum</ptype> <name>coordType</name></param>
+            <param len="COMPSIZE(numCoords,coordType)">const void *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathCoverDepthFuncNV</name></proto>
+            <param group="DepthFunction"><ptype>GLenum</ptype> <name>func</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathDashArrayNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLsizei</ptype> <name>dashCount</name></param>
+            <param len="dashCount">const <ptype>GLfloat</ptype> *<name>dashArray</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathFogGenNV</name></proto>
+            <param group="PathGenMode"><ptype>GLenum</ptype> <name>genMode</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glPathGlyphIndexArrayNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>firstPathName</name></param>
+            <param><ptype>GLenum</ptype> <name>fontTarget</name></param>
+            <param>const void *<name>fontName</name></param>
+            <param><ptype>GLbitfield</ptype> <name>fontStyle</name></param>
+            <param><ptype>GLuint</ptype> <name>firstGlyphIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>numGlyphs</name></param>
+            <param><ptype>GLuint</ptype> <name>pathParameterTemplate</name></param>
+            <param><ptype>GLfloat</ptype> <name>emScale</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glPathGlyphIndexRangeNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>fontTarget</name></param>
+            <param>const void *<name>fontName</name></param>
+            <param><ptype>GLbitfield</ptype> <name>fontStyle</name></param>
+            <param><ptype>GLuint</ptype> <name>pathParameterTemplate</name></param>
+            <param><ptype>GLfloat</ptype> <name>emScale</name></param>
+            <param><ptype>GLuint</ptype> <name>baseAndCount</name>[2]</param>
+        </command>
+        <command>
+            <proto>void <name>glPathGlyphRangeNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>firstPathName</name></param>
+            <param group="PathFontTarget"><ptype>GLenum</ptype> <name>fontTarget</name></param>
+            <param len="COMPSIZE(fontTarget,fontName)">const void *<name>fontName</name></param>
+            <param group="PathFontStyle"><ptype>GLbitfield</ptype> <name>fontStyle</name></param>
+            <param><ptype>GLuint</ptype> <name>firstGlyph</name></param>
+            <param><ptype>GLsizei</ptype> <name>numGlyphs</name></param>
+            <param group="PathHandleMissingGlyphs"><ptype>GLenum</ptype> <name>handleMissingGlyphs</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathParameterTemplate</name></param>
+            <param><ptype>GLfloat</ptype> <name>emScale</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathGlyphsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>firstPathName</name></param>
+            <param group="PathFontTarget"><ptype>GLenum</ptype> <name>fontTarget</name></param>
+            <param len="COMPSIZE(fontTarget,fontName)">const void *<name>fontName</name></param>
+            <param group="PathFontStyle"><ptype>GLbitfield</ptype> <name>fontStyle</name></param>
+            <param><ptype>GLsizei</ptype> <name>numGlyphs</name></param>
+            <param group="PathElementType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(numGlyphs,type,charcodes)">const void *<name>charcodes</name></param>
+            <param group="PathHandleMissingGlyphs"><ptype>GLenum</ptype> <name>handleMissingGlyphs</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathParameterTemplate</name></param>
+            <param><ptype>GLfloat</ptype> <name>emScale</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glPathMemoryGlyphIndexArrayNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>firstPathName</name></param>
+            <param><ptype>GLenum</ptype> <name>fontTarget</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>fontSize</name></param>
+            <param>const void *<name>fontData</name></param>
+            <param><ptype>GLsizei</ptype> <name>faceIndex</name></param>
+            <param><ptype>GLuint</ptype> <name>firstGlyphIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>numGlyphs</name></param>
+            <param><ptype>GLuint</ptype> <name>pathParameterTemplate</name></param>
+            <param><ptype>GLfloat</ptype> <name>emScale</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathParameterfNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathParameterfvNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathParameteriNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathParameterivNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathStencilDepthOffsetNV</name></proto>
+            <param><ptype>GLfloat</ptype> <name>factor</name></param>
+            <param><ptype>GLfloat</ptype> <name>units</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathStencilFuncNV</name></proto>
+            <param group="StencilFunction"><ptype>GLenum</ptype> <name>func</name></param>
+            <param group="ClampedStencilValue"><ptype>GLint</ptype> <name>ref</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathStringNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathStringFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="length">const void *<name>pathString</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathSubCommandsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLsizei</ptype> <name>commandStart</name></param>
+            <param><ptype>GLsizei</ptype> <name>commandsToDelete</name></param>
+            <param><ptype>GLsizei</ptype> <name>numCommands</name></param>
+            <param group="PathCommand" len="numCommands">const <ptype>GLubyte</ptype> *<name>commands</name></param>
+            <param><ptype>GLsizei</ptype> <name>numCoords</name></param>
+            <param group="PathCoordType"><ptype>GLenum</ptype> <name>coordType</name></param>
+            <param len="COMPSIZE(numCoords,coordType)">const void *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathSubCoordsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLsizei</ptype> <name>coordStart</name></param>
+            <param><ptype>GLsizei</ptype> <name>numCoords</name></param>
+            <param group="PathCoordType"><ptype>GLenum</ptype> <name>coordType</name></param>
+            <param len="COMPSIZE(numCoords,coordType)">const void *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPathTexGenNV</name></proto>
+            <param group="PathColor"><ptype>GLenum</ptype> <name>texCoordSet</name></param>
+            <param group="PathGenMode"><ptype>GLenum</ptype> <name>genMode</name></param>
+            <param><ptype>GLint</ptype> <name>components</name></param>
+            <param len="COMPSIZE(genMode,components)">const <ptype>GLfloat</ptype> *<name>coeffs</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPauseTransformFeedback</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glPauseTransformFeedbackNV</name></proto>
+            <alias name="glPauseTransformFeedback"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelDataRangeNV</name></proto>
+            <param group="PixelDataRangeTargetNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="length">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelMapfv</name></proto>
+            <param group="PixelMap"><ptype>GLenum</ptype> <name>map</name></param>
+            <param group="CheckedInt32"><ptype>GLsizei</ptype> <name>mapsize</name></param>
+            <param len="mapsize">const <ptype>GLfloat</ptype> *<name>values</name></param>
+            <glx type="render" opcode="168"/>
+            <glx type="render" opcode="323" name="glPixelMapfvPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelMapuiv</name></proto>
+            <param group="PixelMap"><ptype>GLenum</ptype> <name>map</name></param>
+            <param group="CheckedInt32"><ptype>GLsizei</ptype> <name>mapsize</name></param>
+            <param len="mapsize">const <ptype>GLuint</ptype> *<name>values</name></param>
+            <glx type="render" opcode="169"/>
+            <glx type="render" opcode="324" name="glPixelMapuivPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelMapusv</name></proto>
+            <param group="PixelMap"><ptype>GLenum</ptype> <name>map</name></param>
+            <param group="CheckedInt32"><ptype>GLsizei</ptype> <name>mapsize</name></param>
+            <param len="mapsize">const <ptype>GLushort</ptype> *<name>values</name></param>
+            <glx type="render" opcode="170"/>
+            <glx type="render" opcode="325" name="glPixelMapusvPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelMapx</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLfixed</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelStoref</name></proto>
+            <param group="PixelStoreParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="single" opcode="109"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelStorei</name></proto>
+            <param group="PixelStoreParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="single" opcode="110"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelStorex</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelTexGenParameterfSGIS</name></proto>
+            <param group="PixelTexGenParameterNameSGIS"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelTexGenParameterfvSGIS</name></proto>
+            <param group="PixelTexGenParameterNameSGIS"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelTexGenParameteriSGIS</name></proto>
+            <param group="PixelTexGenParameterNameSGIS"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelTexGenParameterivSGIS</name></proto>
+            <param group="PixelTexGenParameterNameSGIS"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelTexGenSGIX</name></proto>
+            <param group="PixelTexGenModeSGIX"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="2059"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelTransferf</name></proto>
+            <param group="PixelTransferParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="166"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelTransferi</name></proto>
+            <param group="PixelTransferParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="167"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelTransferxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelTransformParameterfEXT</name></proto>
+            <param group="PixelTransformTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelTransformPNameEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="16385"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelTransformParameterfvEXT</name></proto>
+            <param group="PixelTransformTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelTransformPNameEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelTransformParameteriEXT</name></proto>
+            <param group="PixelTransformTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelTransformPNameEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="16386"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelTransformParameterivEXT</name></proto>
+            <param group="PixelTransformTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelTransformPNameEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="1">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPixelZoom</name></proto>
+            <param><ptype>GLfloat</ptype> <name>xfactor</name></param>
+            <param><ptype>GLfloat</ptype> <name>yfactor</name></param>
+            <glx type="render" opcode="165"/>
+        </command>
+        <command>
+            <proto>void <name>glPixelZoomxOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>xfactor</name></param>
+            <param><ptype>GLfixed</ptype> <name>yfactor</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glPointAlongPathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLsizei</ptype> <name>startSegment</name></param>
+            <param><ptype>GLsizei</ptype> <name>numSegments</name></param>
+            <param><ptype>GLfloat</ptype> <name>distance</name></param>
+            <param len="1"><ptype>GLfloat</ptype> *<name>x</name></param>
+            <param len="1"><ptype>GLfloat</ptype> *<name>y</name></param>
+            <param len="1"><ptype>GLfloat</ptype> *<name>tangentX</name></param>
+            <param len="1"><ptype>GLfloat</ptype> *<name>tangentY</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterf</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="2065"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterfARB</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <alias name="glPointParameterf"/>
+            <glx type="render" opcode="2065"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterfEXT</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <alias name="glPointParameterf"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterfSGIS</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <alias name="glPointParameterf"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterfv</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="2066"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterfvARB</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glPointParameterfv"/>
+            <glx type="render" opcode="2066"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterfvEXT</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glPointParameterfv"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterfvSGIS</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glPointParameterfv"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameteri</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="4221"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameteriNV</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+            <alias name="glPointParameteri"/>
+            <glx type="render" opcode="4221"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameteriv</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="4222"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterivNV</name></proto>
+            <param group="PointParameterNameARB"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glPointParameteriv"/>
+            <glx type="render" opcode="4222"/>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterx</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPointParameterxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPointSize</name></proto>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>size</name></param>
+            <glx type="render" opcode="100"/>
+        </command>
+        <command>
+            <proto>void <name>glPointSizePointerOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPointSizex</name></proto>
+            <param><ptype>GLfixed</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPointSizexOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glPollAsyncSGIX</name></proto>
+            <param len="1"><ptype>GLuint</ptype> *<name>markerp</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glPollInstrumentsSGIX</name></proto>
+            <param len="1"><ptype>GLint</ptype> *<name>marker_p</name></param>
+            <glx type="vendor" opcode="4104"/>
+        </command>
+        <command>
+            <proto>void <name>glPolygonMode</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="PolygonMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="101"/>
+        </command>
+        <command>
+            <proto>void <name>glPolygonModeNV</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="PolygonMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glPolygonMode"/>
+        </command>
+        <command>
+            <proto>void <name>glPolygonOffset</name></proto>
+            <param><ptype>GLfloat</ptype> <name>factor</name></param>
+            <param><ptype>GLfloat</ptype> <name>units</name></param>
+            <glx type="render" opcode="192"/>
+        </command>
+        <command>
+            <proto>void <name>glPolygonOffsetClampEXT</name></proto>
+            <param><ptype>GLfloat</ptype> <name>factor</name></param>
+            <param><ptype>GLfloat</ptype> <name>units</name></param>
+            <param><ptype>GLfloat</ptype> <name>clamp</name></param>
+            <glx type="render" opcode="4225"/>
+        </command>
+        <command>
+            <proto>void <name>glPolygonOffsetEXT</name></proto>
+            <param><ptype>GLfloat</ptype> <name>factor</name></param>
+            <param><ptype>GLfloat</ptype> <name>bias</name></param>
+            <glx type="render" opcode="4098"/>
+        </command>
+        <command>
+            <proto>void <name>glPolygonOffsetx</name></proto>
+            <param><ptype>GLfixed</ptype> <name>factor</name></param>
+            <param><ptype>GLfixed</ptype> <name>units</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPolygonOffsetxOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>factor</name></param>
+            <param><ptype>GLfixed</ptype> <name>units</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPolygonStipple</name></proto>
+            <param len="COMPSIZE()">const <ptype>GLubyte</ptype> *<name>mask</name></param>
+            <glx type="render" opcode="102"/>
+            <glx type="render" opcode="326" name="glPolygonStipplePBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glPopAttrib</name></proto>
+            <glx type="render" opcode="141"/>
+        </command>
+        <command>
+            <proto>void <name>glPopClientAttrib</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glPopDebugGroup</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glPopDebugGroupKHR</name></proto>
+            <alias name="glPopDebugGroup"/>
+        </command>
+        <command>
+            <proto>void <name>glPopGroupMarkerEXT</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glPopMatrix</name></proto>
+            <glx type="render" opcode="183"/>
+        </command>
+        <command>
+            <proto>void <name>glPopName</name></proto>
+            <glx type="render" opcode="124"/>
+        </command>
+        <command>
+            <proto>void <name>glPresentFrameDualFillNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_slot</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>minPresentTime</name></param>
+            <param><ptype>GLuint</ptype> <name>beginPresentTimeId</name></param>
+            <param><ptype>GLuint</ptype> <name>presentDurationId</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLenum</ptype> <name>target0</name></param>
+            <param><ptype>GLuint</ptype> <name>fill0</name></param>
+            <param><ptype>GLenum</ptype> <name>target1</name></param>
+            <param><ptype>GLuint</ptype> <name>fill1</name></param>
+            <param><ptype>GLenum</ptype> <name>target2</name></param>
+            <param><ptype>GLuint</ptype> <name>fill2</name></param>
+            <param><ptype>GLenum</ptype> <name>target3</name></param>
+            <param><ptype>GLuint</ptype> <name>fill3</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPresentFrameKeyedNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_slot</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>minPresentTime</name></param>
+            <param><ptype>GLuint</ptype> <name>beginPresentTimeId</name></param>
+            <param><ptype>GLuint</ptype> <name>presentDurationId</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLenum</ptype> <name>target0</name></param>
+            <param><ptype>GLuint</ptype> <name>fill0</name></param>
+            <param><ptype>GLuint</ptype> <name>key0</name></param>
+            <param><ptype>GLenum</ptype> <name>target1</name></param>
+            <param><ptype>GLuint</ptype> <name>fill1</name></param>
+            <param><ptype>GLuint</ptype> <name>key1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPrimitiveBoundingBox</name></proto>
+            <param><ptype>GLfloat</ptype> <name>minX</name></param>
+            <param><ptype>GLfloat</ptype> <name>minY</name></param>
+            <param><ptype>GLfloat</ptype> <name>minZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>minW</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxX</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxY</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxW</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPrimitiveBoundingBoxARB</name></proto>
+            <param><ptype>GLfloat</ptype> <name>minX</name></param>
+            <param><ptype>GLfloat</ptype> <name>minY</name></param>
+            <param><ptype>GLfloat</ptype> <name>minZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>minW</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxX</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxY</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxW</name></param>
+            <alias name="glPrimitiveBoundingBox"/>
+        </command>
+        <command>
+            <proto>void <name>glPrimitiveBoundingBoxEXT</name></proto>
+            <param><ptype>GLfloat</ptype> <name>minX</name></param>
+            <param><ptype>GLfloat</ptype> <name>minY</name></param>
+            <param><ptype>GLfloat</ptype> <name>minZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>minW</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxX</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxY</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxW</name></param>
+            <alias name="glPrimitiveBoundingBox"/>
+        </command>
+        <command>
+            <proto>void <name>glPrimitiveBoundingBoxOES</name></proto>
+            <param><ptype>GLfloat</ptype> <name>minX</name></param>
+            <param><ptype>GLfloat</ptype> <name>minY</name></param>
+            <param><ptype>GLfloat</ptype> <name>minZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>minW</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxX</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxY</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxW</name></param>
+            <alias name="glPrimitiveBoundingBox"/>
+        </command>
+        <command>
+            <proto>void <name>glPrimitiveRestartIndex</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPrimitiveRestartIndexNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPrimitiveRestartNV</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glPrioritizeTextures</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Texture" len="n">const <ptype>GLuint</ptype> *<name>textures</name></param>
+            <param len="n">const <ptype>GLfloat</ptype> *<name>priorities</name></param>
+            <glx type="render" opcode="4118"/>
+        </command>
+        <command>
+            <proto>void <name>glPrioritizeTexturesEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Texture" len="n">const <ptype>GLuint</ptype> *<name>textures</name></param>
+            <param group="ClampedFloat32" len="n">const <ptype>GLclampf</ptype> *<name>priorities</name></param>
+            <alias name="glPrioritizeTextures"/>
+            <glx type="render" opcode="4118"/>
+        </command>
+        <command>
+            <proto>void <name>glPrioritizeTexturesxOES</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>textures</name></param>
+            <param group="ClampedFixed" len="n">const <ptype>GLfixed</ptype> *<name>priorities</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramBinary</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>binaryFormat</name></param>
+            <param len="length">const void *<name>binary</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramBinaryOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>binaryFormat</name></param>
+            <param len="length">const void *<name>binary</name></param>
+            <param><ptype>GLint</ptype> <name>length</name></param>
+            <alias name="glProgramBinary"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramBufferParametersIivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingIndex</name></param>
+            <param><ptype>GLuint</ptype> <name>wordIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramBufferParametersIuivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingIndex</name></param>
+            <param><ptype>GLuint</ptype> <name>wordIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramBufferParametersfvNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingIndex</name></param>
+            <param><ptype>GLuint</ptype> <name>wordIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParameter4dARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+            <vecequiv name="glProgramEnvParameter4dvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParameter4dvARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParameter4fARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <vecequiv name="glProgramEnvParameter4fvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParameter4fvARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParameterI4iNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+            <param><ptype>GLint</ptype> <name>w</name></param>
+            <vecequiv name="glProgramEnvParameterI4ivNV"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParameterI4ivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParameterI4uiNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <param><ptype>GLuint</ptype> <name>z</name></param>
+            <param><ptype>GLuint</ptype> <name>w</name></param>
+            <vecequiv name="glProgramEnvParameterI4uivNV"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParameterI4uivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParameters4fvEXT</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="4281"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParametersI4ivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramEnvParametersI4uivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParameter4dARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+            <vecequiv name="glProgramLocalParameter4dvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParameter4dvARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParameter4fARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <vecequiv name="glProgramLocalParameter4fvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParameter4fvARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParameterI4iNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+            <param><ptype>GLint</ptype> <name>w</name></param>
+            <vecequiv name="glProgramLocalParameterI4ivNV"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParameterI4ivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParameterI4uiNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <param><ptype>GLuint</ptype> <name>z</name></param>
+            <param><ptype>GLuint</ptype> <name>w</name></param>
+            <vecequiv name="glProgramLocalParameterI4uivNV"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParameterI4uivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParameters4fvEXT</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="4282"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParametersI4ivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramLocalParametersI4uivNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramNamedParameter4dNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="1">const <ptype>GLubyte</ptype> *<name>name</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+            <vecequiv name="glProgramNamedParameter4dvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramNamedParameter4dvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="1">const <ptype>GLubyte</ptype> *<name>name</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4219"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramNamedParameter4fNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="1">const <ptype>GLubyte</ptype> *<name>name</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <vecequiv name="glProgramNamedParameter4fvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramNamedParameter4fvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="1">const <ptype>GLubyte</ptype> *<name>name</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4218"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramParameter4dNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+            <vecequiv name="glProgramParameter4dvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramParameter4dvNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4185"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramParameter4fNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <vecequiv name="glProgramParameter4fvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramParameter4fvNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4184"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramParameteri</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramParameteriARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>value</name></param>
+            <alias name="glProgramParameteri"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramParameteriEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param group="ProgramParameterPName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>value</name></param>
+            <alias name="glProgramParameteri"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramParameters4dvNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4187"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramParameters4fvNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4186"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramPathFragmentInputGenNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLenum</ptype> <name>genMode</name></param>
+            <param><ptype>GLint</ptype> <name>components</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>coeffs</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramStringARB</name></proto>
+            <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="ProgramFormatARB"><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="len">const void *<name>string</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramSubroutineParametersuivNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1d</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>v0</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1dEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1f</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1fEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <alias name="glProgramUniform1f"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform1fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1i</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1i64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1i64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1i64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1i64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1iEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <alias name="glProgramUniform1i"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform1iv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1ui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1ui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1ui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1ui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1uiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <alias name="glProgramUniform1ui"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform1uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform1uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2d</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>v0</name></param>
+            <param><ptype>GLdouble</ptype> <name>v1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2dEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2f</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2fEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <alias name="glProgramUniform2f"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2i</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2i64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2i64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2i64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2i64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2iEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <alias name="glProgramUniform2i"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2ui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2ui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2ui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2ui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2uiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <alias name="glProgramUniform2ui"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform2uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform2uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3d</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>v0</name></param>
+            <param><ptype>GLdouble</ptype> <name>v1</name></param>
+            <param><ptype>GLdouble</ptype> <name>v2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3dEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3f</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param><ptype>GLfloat</ptype> <name>v2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3fEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param><ptype>GLfloat</ptype> <name>v2</name></param>
+            <alias name="glProgramUniform3f"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3i</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <param><ptype>GLint</ptype> <name>v2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3i64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+            <param><ptype>GLint64</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3i64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3i64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3i64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3iEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <param><ptype>GLint</ptype> <name>v2</name></param>
+            <alias name="glProgramUniform3i"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <param><ptype>GLuint</ptype> <name>v2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3ui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+            <param><ptype>GLuint64</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3ui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3ui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3ui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3uiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <param><ptype>GLuint</ptype> <name>v2</name></param>
+            <alias name="glProgramUniform3ui"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform3uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform3uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4d</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>v0</name></param>
+            <param><ptype>GLdouble</ptype> <name>v1</name></param>
+            <param><ptype>GLdouble</ptype> <name>v2</name></param>
+            <param><ptype>GLdouble</ptype> <name>v3</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4dEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4f</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param><ptype>GLfloat</ptype> <name>v2</name></param>
+            <param><ptype>GLfloat</ptype> <name>v3</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4fEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param><ptype>GLfloat</ptype> <name>v2</name></param>
+            <param><ptype>GLfloat</ptype> <name>v3</name></param>
+            <alias name="glProgramUniform4f"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4i</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <param><ptype>GLint</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>v3</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4i64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+            <param><ptype>GLint64</ptype> <name>z</name></param>
+            <param><ptype>GLint64</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4i64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>z</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4i64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4i64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4iEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <param><ptype>GLint</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>v3</name></param>
+            <alias name="glProgramUniform4i"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <param><ptype>GLuint</ptype> <name>v2</name></param>
+            <param><ptype>GLuint</ptype> <name>v3</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4ui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+            <param><ptype>GLuint64</ptype> <name>z</name></param>
+            <param><ptype>GLuint64</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4ui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>z</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4ui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4ui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4uiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <param><ptype>GLuint</ptype> <name>v2</name></param>
+            <param><ptype>GLuint</ptype> <name>v3</name></param>
+            <alias name="glProgramUniform4ui"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniform4uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <alias name="glProgramUniform4uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformHandleui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformHandleui64IMG</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>value</name></param>
+            <alias name="glProgramUniformHandleui64ARB"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformHandleui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformHandleui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformHandleui64vIMG</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64</ptype> *<name>values</name></param>
+            <alias name="glProgramUniformHandleui64vARB"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformHandleui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniformMatrix2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2x3dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2x3dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2x3fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2x3fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniformMatrix2x3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2x4dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2x4dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2x4fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix2x4fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniformMatrix2x4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*9">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*9">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*9">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*9">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniformMatrix3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3x2dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3x2dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3x2fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3x2fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniformMatrix3x2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3x4dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3x4dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3x4fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix3x4fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniformMatrix3x4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*16">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*16">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*16">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*16">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniformMatrix4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4x2dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4x2dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4x2fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4x2fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniformMatrix4x2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4x3dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4x3dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4x3fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformMatrix4x3fvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glProgramUniformMatrix4x3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramUniformui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProgramVertexLimitNV</name></proto>
+            <param group="ProgramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>limit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProvokingVertex</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glProvokingVertexEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glProvokingVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glPushAttrib</name></proto>
+            <param group="AttribMask"><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <glx type="render" opcode="142"/>
+        </command>
+        <command>
+            <proto>void <name>glPushClientAttrib</name></proto>
+            <param group="ClientAttribMask"><ptype>GLbitfield</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPushClientAttribDefaultEXT</name></proto>
+            <param group="ClientAttribMask"><ptype>GLbitfield</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPushDebugGroup</name></proto>
+            <param><ptype>GLenum</ptype> <name>source</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="COMPSIZE(message,length)">const <ptype>GLchar</ptype> *<name>message</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPushDebugGroupKHR</name></proto>
+            <param><ptype>GLenum</ptype> <name>source</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>message</name></param>
+            <alias name="glPushDebugGroup"/>
+        </command>
+        <command>
+            <proto>void <name>glPushGroupMarkerEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>marker</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPushMatrix</name></proto>
+            <glx type="render" opcode="184"/>
+        </command>
+        <command>
+            <proto>void <name>glPushName</name></proto>
+            <param group="SelectName"><ptype>GLuint</ptype> <name>name</name></param>
+            <glx type="render" opcode="125"/>
+        </command>
+        <command>
+            <proto>void <name>glQueryCounter</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto>void <name>glQueryCounterEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <alias name="glQueryCounter"/>
+        </command>
+        <command>
+            <proto><ptype>GLbitfield</ptype> <name>glQueryMatrixxOES</name></proto>
+            <param len="16"><ptype>GLfixed</ptype> *<name>mantissa</name></param>
+            <param len="16"><ptype>GLint</ptype> *<name>exponent</name></param>
+        </command>
+        <command>
+            <proto>void <name>glQueryObjectParameteruiAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="OcclusionQueryEventMaskAMD"><ptype>GLuint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <vecequiv name="glRasterPos2dv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2dv</name></proto>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="33"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <vecequiv name="glRasterPos2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2fv</name></proto>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="34"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <vecequiv name="glRasterPos2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2iv</name></proto>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="35"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <vecequiv name="glRasterPos2sv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2sv</name></proto>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="36"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos2xvOES</name></proto>
+            <param len="2">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>z</name></param>
+            <vecequiv name="glRasterPos3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3dv</name></proto>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="37"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>z</name></param>
+            <vecequiv name="glRasterPos3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3fv</name></proto>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="38"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>z</name></param>
+            <vecequiv name="glRasterPos3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3iv</name></proto>
+            <param group="CoordI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="39"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>z</name></param>
+            <vecequiv name="glRasterPos3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3sv</name></proto>
+            <param group="CoordS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="40"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos3xvOES</name></proto>
+            <param len="3">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>z</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>w</name></param>
+            <vecequiv name="glRasterPos4dv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4dv</name></proto>
+            <param group="CoordD" len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="41"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>z</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>w</name></param>
+            <vecequiv name="glRasterPos4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4fv</name></proto>
+            <param group="CoordF" len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="42"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>z</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>w</name></param>
+            <vecequiv name="glRasterPos4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4iv</name></proto>
+            <param group="CoordI" len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="43"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>z</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>w</name></param>
+            <vecequiv name="glRasterPos4sv"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4sv</name></proto>
+            <param group="CoordS" len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="44"/>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+            <param><ptype>GLfixed</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRasterPos4xvOES</name></proto>
+            <param len="4">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRasterSamplesEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>samples</name></param>
+            <param><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReadBuffer</name></proto>
+            <param group="ReadBufferMode"><ptype>GLenum</ptype> <name>src</name></param>
+            <glx type="render" opcode="171"/>
+        </command>
+        <command>
+            <proto>void <name>glReadBufferIndexedEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>src</name></param>
+            <param><ptype>GLint</ptype> <name>index</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReadBufferNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReadInstrumentsSGIX</name></proto>
+            <param><ptype>GLint</ptype> <name>marker</name></param>
+            <glx type="render" opcode="2077"/>
+        </command>
+        <command>
+            <proto>void <name>glReadPixels</name></proto>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">void *<name>pixels</name></param>
+            <glx type="single" opcode="111"/>
+            <glx type="render" opcode="345" name="glReadPixelsPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glReadnPixels</name></proto>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>data</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReadnPixelsARB</name></proto>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>data</name></param>
+            <alias name="glReadnPixels"/>
+        </command>
+        <command>
+            <proto>void <name>glReadnPixelsEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>data</name></param>
+            <alias name="glReadnPixels"/>
+        </command>
+        <command>
+            <proto>void <name>glReadnPixelsKHR</name></proto>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>data</name></param>
+            <alias name="glReadnPixels"/>
+        </command>
+        <command>
+            <proto>void <name>glRectd</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y1</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x2</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y2</name></param>
+            <vecequiv name="glRectdv"/>
+        </command>
+        <command>
+            <proto>void <name>glRectdv</name></proto>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v1</name></param>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v2</name></param>
+            <glx type="render" opcode="45"/>
+        </command>
+        <command>
+            <proto>void <name>glRectf</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y1</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x2</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y2</name></param>
+            <vecequiv name="glRectfv"/>
+        </command>
+        <command>
+            <proto>void <name>glRectfv</name></proto>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v1</name></param>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v2</name></param>
+            <glx type="render" opcode="46"/>
+        </command>
+        <command>
+            <proto>void <name>glRecti</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x1</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y1</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x2</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y2</name></param>
+            <vecequiv name="glRectiv"/>
+        </command>
+        <command>
+            <proto>void <name>glRectiv</name></proto>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v1</name></param>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v2</name></param>
+            <glx type="render" opcode="47"/>
+        </command>
+        <command>
+            <proto>void <name>glRects</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x1</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y1</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x2</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y2</name></param>
+            <vecequiv name="glRectsv"/>
+        </command>
+        <command>
+            <proto>void <name>glRectsv</name></proto>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v1</name></param>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v2</name></param>
+            <glx type="render" opcode="48"/>
+        </command>
+        <command>
+            <proto>void <name>glRectxOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x1</name></param>
+            <param><ptype>GLfixed</ptype> <name>y1</name></param>
+            <param><ptype>GLfixed</ptype> <name>x2</name></param>
+            <param><ptype>GLfixed</ptype> <name>y2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRectxvOES</name></proto>
+            <param len="2">const <ptype>GLfixed</ptype> *<name>v1</name></param>
+            <param len="2">const <ptype>GLfixed</ptype> *<name>v2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReferencePlaneSGIX</name></proto>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>equation</name></param>
+            <glx type="render" opcode="2071"/>
+        </command>
+        <command>
+            <proto>void <name>glReleaseShaderCompiler</name></proto>
+        </command>
+        <command>
+            <proto><ptype>GLint</ptype> <name>glRenderMode</name></proto>
+            <param group="RenderingMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="single" opcode="107"/>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorage</name></proto>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <glx type="render" opcode="4318"/>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorageEXT</name></proto>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glRenderbufferStorage"/>
+            <glx type="render" opcode="4318"/>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorageMultisample</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <glx type="render" opcode="4331"/>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorageMultisampleANGLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorageMultisampleAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorageMultisampleCoverageNV</name></proto>
+            <param group="RenderbufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>coverageSamples</name></param>
+            <param><ptype>GLsizei</ptype> <name>colorSamples</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorageMultisampleEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glRenderbufferStorageMultisample"/>
+            <glx type="render" opcode="4331"/>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorageMultisampleIMG</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorageMultisampleNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glRenderbufferStorageMultisample"/>
+        </command>
+        <command>
+            <proto>void <name>glRenderbufferStorageOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodePointerSUN</name></proto>
+            <param group="ReplacementCodeTypeSUN"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void **<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeubSUN</name></proto>
+            <param><ptype>GLubyte</ptype> <name>code</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeubvSUN</name></proto>
+            <param len="COMPSIZE()">const <ptype>GLubyte</ptype> *<name>code</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiColor3fVertex3fSUN</name></proto>
+            <param group="ReplacementCodeSUN"><ptype>GLuint</ptype> <name>rc</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>g</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiColor3fVertex3fvSUN</name></proto>
+            <param group="ReplacementCodeSUN" len="1">const <ptype>GLuint</ptype> *<name>rc</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiColor4fNormal3fVertex3fSUN</name></proto>
+            <param group="ReplacementCodeSUN"><ptype>GLuint</ptype> <name>rc</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>g</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>a</name></param>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiColor4fNormal3fVertex3fvSUN</name></proto>
+            <param group="ReplacementCodeSUN" len="1">const <ptype>GLuint</ptype> *<name>rc</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>n</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiColor4ubVertex3fSUN</name></proto>
+            <param group="ReplacementCodeSUN"><ptype>GLuint</ptype> <name>rc</name></param>
+            <param><ptype>GLubyte</ptype> <name>r</name></param>
+            <param><ptype>GLubyte</ptype> <name>g</name></param>
+            <param><ptype>GLubyte</ptype> <name>b</name></param>
+            <param><ptype>GLubyte</ptype> <name>a</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiColor4ubVertex3fvSUN</name></proto>
+            <param group="ReplacementCodeSUN" len="1">const <ptype>GLuint</ptype> *<name>rc</name></param>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiNormal3fVertex3fSUN</name></proto>
+            <param group="ReplacementCodeSUN"><ptype>GLuint</ptype> <name>rc</name></param>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiNormal3fVertex3fvSUN</name></proto>
+            <param group="ReplacementCodeSUN" len="1">const <ptype>GLuint</ptype> *<name>rc</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>n</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiSUN</name></proto>
+            <param><ptype>GLuint</ptype> <name>code</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN</name></proto>
+            <param group="ReplacementCodeSUN"><ptype>GLuint</ptype> <name>rc</name></param>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>g</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>a</name></param>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN</name></proto>
+            <param group="ReplacementCodeSUN" len="1">const <ptype>GLuint</ptype> *<name>rc</name></param>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>n</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN</name></proto>
+            <param group="ReplacementCodeSUN"><ptype>GLuint</ptype> <name>rc</name></param>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN</name></proto>
+            <param group="ReplacementCodeSUN" len="1">const <ptype>GLuint</ptype> *<name>rc</name></param>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>n</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiTexCoord2fVertex3fSUN</name></proto>
+            <param group="ReplacementCodeSUN"><ptype>GLuint</ptype> <name>rc</name></param>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiTexCoord2fVertex3fvSUN</name></proto>
+            <param group="ReplacementCodeSUN" len="1">const <ptype>GLuint</ptype> *<name>rc</name></param>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiVertex3fSUN</name></proto>
+            <param group="ReplacementCodeSUN"><ptype>GLuint</ptype> <name>rc</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuiVertex3fvSUN</name></proto>
+            <param group="ReplacementCodeSUN" len="1">const <ptype>GLuint</ptype> *<name>rc</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeuivSUN</name></proto>
+            <param len="COMPSIZE()">const <ptype>GLuint</ptype> *<name>code</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeusSUN</name></proto>
+            <param><ptype>GLushort</ptype> <name>code</name></param>
+        </command>
+        <command>
+            <proto>void <name>glReplacementCodeusvSUN</name></proto>
+            <param len="COMPSIZE()">const <ptype>GLushort</ptype> *<name>code</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRequestResidentProgramsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLuint</ptype> *<name>programs</name></param>
+            <glx type="render" opcode="4182"/>
+        </command>
+        <command>
+            <proto>void <name>glResetHistogram</name></proto>
+            <param group="HistogramTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <glx type="render" opcode="4112"/>
+        </command>
+        <command>
+            <proto>void <name>glResetHistogramEXT</name></proto>
+            <param group="HistogramTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <alias name="glResetHistogram"/>
+            <glx type="render" opcode="4112"/>
+        </command>
+        <command>
+            <proto>void <name>glResetMinmax</name></proto>
+            <param group="MinmaxTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <glx type="render" opcode="4113"/>
+        </command>
+        <command>
+            <proto>void <name>glResetMinmaxEXT</name></proto>
+            <param group="MinmaxTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <alias name="glResetMinmax"/>
+            <glx type="render" opcode="4113"/>
+        </command>
+        <command>
+            <proto>void <name>glResizeBuffersMESA</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glResolveDepthValuesNV</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glResolveMultisampleFramebufferAPPLE</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glResumeTransformFeedback</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glResumeTransformFeedbackNV</name></proto>
+            <alias name="glResumeTransformFeedback"/>
+        </command>
+        <command>
+            <proto>void <name>glRotated</name></proto>
+            <param><ptype>GLdouble</ptype> <name>angle</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <glx type="render" opcode="185"/>
+        </command>
+        <command>
+            <proto>void <name>glRotatef</name></proto>
+            <param><ptype>GLfloat</ptype> <name>angle</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <glx type="render" opcode="186"/>
+        </command>
+        <command>
+            <proto>void <name>glRotatex</name></proto>
+            <param><ptype>GLfixed</ptype> <name>angle</name></param>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glRotatexOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>angle</name></param>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSampleCoverage</name></proto>
+            <param><ptype>GLfloat</ptype> <name>value</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>invert</name></param>
+            <glx type="render" opcode="229"/>
+        </command>
+        <command>
+            <proto>void <name>glSampleCoverageARB</name></proto>
+            <param><ptype>GLfloat</ptype> <name>value</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>invert</name></param>
+            <alias name="glSampleCoverage"/>
+        </command>
+        <command>
+            <proto>void <name>glSampleCoveragex</name></proto>
+            <param><ptype>GLclampx</ptype> <name>value</name></param>
+            <param><ptype>GLboolean</ptype> <name>invert</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSampleCoveragexOES</name></proto>
+            <param><ptype>GLclampx</ptype> <name>value</name></param>
+            <param><ptype>GLboolean</ptype> <name>invert</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSampleMapATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>dst</name></param>
+            <param><ptype>GLuint</ptype> <name>interp</name></param>
+            <param group="SwizzleOpATI"><ptype>GLenum</ptype> <name>swizzle</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSampleMaskEXT</name></proto>
+            <param group="ClampedFloat32"><ptype>GLclampf</ptype> <name>value</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>invert</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSampleMaskIndexedNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="SampleMaskNV"><ptype>GLbitfield</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSampleMaskSGIS</name></proto>
+            <param group="ClampedFloat32"><ptype>GLclampf</ptype> <name>value</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>invert</name></param>
+            <alias name="glSampleMaskEXT"/>
+            <glx type="render" opcode="2048"/>
+        </command>
+        <command>
+            <proto>void <name>glSampleMaski</name></proto>
+            <param><ptype>GLuint</ptype> <name>maskNumber</name></param>
+            <param><ptype>GLbitfield</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSamplePatternEXT</name></proto>
+            <param group="SamplePatternEXT"><ptype>GLenum</ptype> <name>pattern</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSamplePatternSGIS</name></proto>
+            <param group="SamplePatternSGIS"><ptype>GLenum</ptype> <name>pattern</name></param>
+            <alias name="glSamplePatternEXT"/>
+            <glx type="render" opcode="2049"/>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameterIiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameterIivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>param</name></param>
+            <alias name="glSamplerParameterIiv"/>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameterIivOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>param</name></param>
+            <alias name="glSamplerParameterIiv"/>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameterIuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameterIuivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>param</name></param>
+            <alias name="glSamplerParameterIuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameterIuivOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>param</name></param>
+            <alias name="glSamplerParameterIuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameterf</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameterfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameteri</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSamplerParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glScaled</name></proto>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <glx type="render" opcode="187"/>
+        </command>
+        <command>
+            <proto>void <name>glScalef</name></proto>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <glx type="render" opcode="188"/>
+        </command>
+        <command>
+            <proto>void <name>glScalex</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glScalexOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glScissor</name></proto>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <glx type="render" opcode="103"/>
+        </command>
+        <command>
+            <proto>void <name>glScissorArrayv</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glScissorArrayvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glScissorArrayv"/>
+        </command>
+        <command>
+            <proto>void <name>glScissorArrayvOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glScissorArrayv"/>
+        </command>
+        <command>
+            <proto>void <name>glScissorIndexed</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>left</name></param>
+            <param><ptype>GLint</ptype> <name>bottom</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glScissorIndexedNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>left</name></param>
+            <param><ptype>GLint</ptype> <name>bottom</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glScissorIndexed"/>
+        </command>
+        <command>
+            <proto>void <name>glScissorIndexedOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>left</name></param>
+            <param><ptype>GLint</ptype> <name>bottom</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glScissorIndexed"/>
+        </command>
+        <command>
+            <proto>void <name>glScissorIndexedv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glScissorIndexedvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glScissorIndexedv"/>
+        </command>
+        <command>
+            <proto>void <name>glScissorIndexedvOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glScissorIndexedv"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3b</name></proto>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>red</name></param>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>green</name></param>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>blue</name></param>
+            <vecequiv name="glSecondaryColor3bv"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3bEXT</name></proto>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>red</name></param>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>green</name></param>
+            <param group="ColorB"><ptype>GLbyte</ptype> <name>blue</name></param>
+            <alias name="glSecondaryColor3b"/>
+            <vecequiv name="glSecondaryColor3bvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3bv</name></proto>
+            <param group="ColorB" len="3">const <ptype>GLbyte</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4126"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3bvEXT</name></proto>
+            <param group="ColorB" len="3">const <ptype>GLbyte</ptype> *<name>v</name></param>
+            <alias name="glSecondaryColor3bv"/>
+            <glx type="render" opcode="4126"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3d</name></proto>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>red</name></param>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>green</name></param>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>blue</name></param>
+            <vecequiv name="glSecondaryColor3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3dEXT</name></proto>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>red</name></param>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>green</name></param>
+            <param group="ColorD"><ptype>GLdouble</ptype> <name>blue</name></param>
+            <alias name="glSecondaryColor3d"/>
+            <vecequiv name="glSecondaryColor3dvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3dv</name></proto>
+            <param group="ColorD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4130"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3dvEXT</name></proto>
+            <param group="ColorD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glSecondaryColor3dv"/>
+            <glx type="render" opcode="4130"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3f</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>red</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>green</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>blue</name></param>
+            <vecequiv name="glSecondaryColor3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3fEXT</name></proto>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>red</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>green</name></param>
+            <param group="ColorF"><ptype>GLfloat</ptype> <name>blue</name></param>
+            <alias name="glSecondaryColor3f"/>
+            <vecequiv name="glSecondaryColor3fvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3fv</name></proto>
+            <param group="ColorF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4129"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3fvEXT</name></proto>
+            <param group="ColorF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glSecondaryColor3fv"/>
+            <glx type="render" opcode="4129"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>red</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>green</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>blue</name></param>
+            <vecequiv name="glSecondaryColor3hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3hvNV</name></proto>
+            <param group="Half16NV" len="3">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4255"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3i</name></proto>
+            <param group="ColorI"><ptype>GLint</ptype> <name>red</name></param>
+            <param group="ColorI"><ptype>GLint</ptype> <name>green</name></param>
+            <param group="ColorI"><ptype>GLint</ptype> <name>blue</name></param>
+            <vecequiv name="glSecondaryColor3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3iEXT</name></proto>
+            <param group="ColorI"><ptype>GLint</ptype> <name>red</name></param>
+            <param group="ColorI"><ptype>GLint</ptype> <name>green</name></param>
+            <param group="ColorI"><ptype>GLint</ptype> <name>blue</name></param>
+            <alias name="glSecondaryColor3i"/>
+            <vecequiv name="glSecondaryColor3ivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3iv</name></proto>
+            <param group="ColorI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4128"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3ivEXT</name></proto>
+            <param group="ColorI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glSecondaryColor3iv"/>
+            <glx type="render" opcode="4128"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3s</name></proto>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>red</name></param>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>green</name></param>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>blue</name></param>
+            <vecequiv name="glSecondaryColor3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3sEXT</name></proto>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>red</name></param>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>green</name></param>
+            <param group="ColorS"><ptype>GLshort</ptype> <name>blue</name></param>
+            <alias name="glSecondaryColor3s"/>
+            <vecequiv name="glSecondaryColor3svEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3sv</name></proto>
+            <param group="ColorS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4127"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3svEXT</name></proto>
+            <param group="ColorS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glSecondaryColor3sv"/>
+            <glx type="render" opcode="4127"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3ub</name></proto>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>red</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>green</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>blue</name></param>
+            <vecequiv name="glSecondaryColor3ubv"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3ubEXT</name></proto>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>red</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>green</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>blue</name></param>
+            <alias name="glSecondaryColor3ub"/>
+            <vecequiv name="glSecondaryColor3ubvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3ubv</name></proto>
+            <param group="ColorUB" len="3">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4131"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3ubvEXT</name></proto>
+            <param group="ColorUB" len="3">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <alias name="glSecondaryColor3ubv"/>
+            <glx type="render" opcode="4131"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3ui</name></proto>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>red</name></param>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>green</name></param>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>blue</name></param>
+            <vecequiv name="glSecondaryColor3uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3uiEXT</name></proto>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>red</name></param>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>green</name></param>
+            <param group="ColorUI"><ptype>GLuint</ptype> <name>blue</name></param>
+            <alias name="glSecondaryColor3ui"/>
+            <vecequiv name="glSecondaryColor3uivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3uiv</name></proto>
+            <param group="ColorUI" len="3">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4133"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3uivEXT</name></proto>
+            <param group="ColorUI" len="3">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <alias name="glSecondaryColor3uiv"/>
+            <glx type="render" opcode="4133"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3us</name></proto>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>red</name></param>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>green</name></param>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>blue</name></param>
+            <vecequiv name="glSecondaryColor3usv"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3usEXT</name></proto>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>red</name></param>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>green</name></param>
+            <param group="ColorUS"><ptype>GLushort</ptype> <name>blue</name></param>
+            <alias name="glSecondaryColor3us"/>
+            <vecequiv name="glSecondaryColor3usvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3usv</name></proto>
+            <param group="ColorUS" len="3">const <ptype>GLushort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4132"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColor3usvEXT</name></proto>
+            <param group="ColorUS" len="3">const <ptype>GLushort</ptype> *<name>v</name></param>
+            <alias name="glSecondaryColor3usv"/>
+            <glx type="render" opcode="4132"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColorFormatNV</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColorP3ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>color</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColorP3uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>color</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColorPointer</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="ColorPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColorPointerEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="ColorPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+            <alias name="glSecondaryColorPointer"/>
+        </command>
+        <command>
+            <proto>void <name>glSecondaryColorPointerListIBM</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="SecondaryColorPointerTypeIBM"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void **<name>pointer</name></param>
+            <param><ptype>GLint</ptype> <name>ptrstride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSelectBuffer</name></proto>
+            <param><ptype>GLsizei</ptype> <name>size</name></param>
+            <param group="SelectName" len="size"><ptype>GLuint</ptype> *<name>buffer</name></param>
+            <glx type="single" opcode="106"/>
+        </command>
+        <command>
+            <proto>void <name>glSelectPerfMonitorCountersAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>monitor</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>enable</name></param>
+            <param><ptype>GLuint</ptype> <name>group</name></param>
+            <param><ptype>GLint</ptype> <name>numCounters</name></param>
+            <param len="numCounters"><ptype>GLuint</ptype> *<name>counterList</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSeparableFilter2D</name></proto>
+            <param group="SeparableTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type,width)">const void *<name>row</name></param>
+            <param len="COMPSIZE(target,format,type,height)">const void *<name>column</name></param>
+            <glx type="render" opcode="4109"/>
+            <glx type="render" opcode="327" name="glSeparableFilter2DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glSeparableFilter2DEXT</name></proto>
+            <param group="SeparableTargetEXT"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(target,format,type,width)">const void *<name>row</name></param>
+            <param len="COMPSIZE(target,format,type,height)">const void *<name>column</name></param>
+            <alias name="glSeparableFilter2D"/>
+            <glx type="render" opcode="4109"/>
+        </command>
+        <command>
+            <proto>void <name>glSetFenceAPPLE</name></proto>
+            <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSetFenceNV</name></proto>
+            <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
+            <param group="FenceConditionNV"><ptype>GLenum</ptype> <name>condition</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSetFragmentShaderConstantATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>dst</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSetInvariantEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="ScalarType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(id,type)">const void *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSetLocalConstantEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="ScalarType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(id,type)">const void *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSetMultisamplefvAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>val</name></param>
+        </command>
+        <command>
+            <proto>void <name>glShadeModel</name></proto>
+            <param group="ShadingModel"><ptype>GLenum</ptype> <name>mode</name></param>
+            <glx type="render" opcode="104"/>
+        </command>
+        <command>
+            <proto>void <name>glShaderBinary</name></proto>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>shaders</name></param>
+            <param><ptype>GLenum</ptype> <name>binaryformat</name></param>
+            <param len="length">const void *<name>binary</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glShaderOp1EXT</name></proto>
+            <param group="VertexShaderOpEXT"><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLuint</ptype> <name>res</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glShaderOp2EXT</name></proto>
+            <param group="VertexShaderOpEXT"><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLuint</ptype> <name>res</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glShaderOp3EXT</name></proto>
+            <param group="VertexShaderOpEXT"><ptype>GLenum</ptype> <name>op</name></param>
+            <param><ptype>GLuint</ptype> <name>res</name></param>
+            <param><ptype>GLuint</ptype> <name>arg1</name></param>
+            <param><ptype>GLuint</ptype> <name>arg2</name></param>
+            <param><ptype>GLuint</ptype> <name>arg3</name></param>
+        </command>
+        <command>
+            <proto>void <name>glShaderSource</name></proto>
+            <param><ptype>GLuint</ptype> <name>shader</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLchar</ptype> *const*<name>string</name></param>
+            <param len="count">const <ptype>GLint</ptype> *<name>length</name></param>
+        </command>
+        <command>
+            <proto>void <name>glShaderSourceARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>shaderObj</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLcharARB</ptype> **<name>string</name></param>
+            <param len="count">const <ptype>GLint</ptype> *<name>length</name></param>
+            <alias name="glShaderSource"/>
+        </command>
+        <command>
+            <proto>void <name>glShaderStorageBlockBinding</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>storageBlockIndex</name></param>
+            <param><ptype>GLuint</ptype> <name>storageBlockBinding</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSharpenTexFuncSGIS</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n*2">const <ptype>GLfloat</ptype> *<name>points</name></param>
+            <glx type="render" opcode="2052"/>
+        </command>
+        <command>
+            <proto>void <name>glSpriteParameterfSGIX</name></proto>
+            <param group="SpriteParameterNameSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="2060"/>
+        </command>
+        <command>
+            <proto>void <name>glSpriteParameterfvSGIX</name></proto>
+            <param group="SpriteParameterNameSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="2061"/>
+        </command>
+        <command>
+            <proto>void <name>glSpriteParameteriSGIX</name></proto>
+            <param group="SpriteParameterNameSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="2062"/>
+        </command>
+        <command>
+            <proto>void <name>glSpriteParameterivSGIX</name></proto>
+            <param group="SpriteParameterNameSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="2063"/>
+        </command>
+        <command>
+            <proto>void <name>glStartInstrumentsSGIX</name></proto>
+            <glx type="render" opcode="2069"/>
+        </command>
+        <command>
+            <proto>void <name>glStartTilingQCOM</name></proto>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <param><ptype>GLuint</ptype> <name>width</name></param>
+            <param><ptype>GLuint</ptype> <name>height</name></param>
+            <param><ptype>GLbitfield</ptype> <name>preserveMask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStateCaptureNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>state</name></param>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilClearTagEXT</name></proto>
+            <param><ptype>GLsizei</ptype> <name>stencilTagBits</name></param>
+            <param><ptype>GLuint</ptype> <name>stencilClearTag</name></param>
+            <glx type="render" opcode="4223"/>
+        </command>
+        <command>
+            <proto>void <name>glStencilFillPathInstancedNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param group="PathElementType"><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param group="PathElement" len="COMPSIZE(numPaths,pathNameType,paths)">const void *<name>paths</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param group="PathFillMode"><ptype>GLenum</ptype> <name>fillMode</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+            <param group="PathTransformType"><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param len="COMPSIZE(numPaths,transformType)">const <ptype>GLfloat</ptype> *<name>transformValues</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilFillPathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="PathFillMode"><ptype>GLenum</ptype> <name>fillMode</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilFunc</name></proto>
+            <param group="StencilFunction"><ptype>GLenum</ptype> <name>func</name></param>
+            <param group="StencilValue"><ptype>GLint</ptype> <name>ref</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+            <glx type="render" opcode="162"/>
+        </command>
+        <command>
+            <proto>void <name>glStencilFuncSeparate</name></proto>
+            <param group="StencilFaceDirection"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="StencilFunction"><ptype>GLenum</ptype> <name>func</name></param>
+            <param group="StencilValue"><ptype>GLint</ptype> <name>ref</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilFuncSeparateATI</name></proto>
+            <param group="StencilFunction"><ptype>GLenum</ptype> <name>frontfunc</name></param>
+            <param group="StencilFunction"><ptype>GLenum</ptype> <name>backfunc</name></param>
+            <param group="ClampedStencilValue"><ptype>GLint</ptype> <name>ref</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilMask</name></proto>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+            <glx type="render" opcode="133"/>
+        </command>
+        <command>
+            <proto>void <name>glStencilMaskSeparate</name></proto>
+            <param group="StencilFaceDirection"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilOp</name></proto>
+            <param group="StencilOp"><ptype>GLenum</ptype> <name>fail</name></param>
+            <param group="StencilOp"><ptype>GLenum</ptype> <name>zfail</name></param>
+            <param group="StencilOp"><ptype>GLenum</ptype> <name>zpass</name></param>
+            <glx type="render" opcode="163"/>
+        </command>
+        <command>
+            <proto>void <name>glStencilOpSeparate</name></proto>
+            <param group="StencilFaceDirection"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="StencilOp"><ptype>GLenum</ptype> <name>sfail</name></param>
+            <param group="StencilOp"><ptype>GLenum</ptype> <name>dpfail</name></param>
+            <param group="StencilOp"><ptype>GLenum</ptype> <name>dppass</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilOpSeparateATI</name></proto>
+            <param group="StencilFaceDirection"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="StencilOp"><ptype>GLenum</ptype> <name>sfail</name></param>
+            <param group="StencilOp"><ptype>GLenum</ptype> <name>dpfail</name></param>
+            <param group="StencilOp"><ptype>GLenum</ptype> <name>dppass</name></param>
+            <alias name="glStencilOpSeparate"/>
+        </command>
+        <command>
+            <proto>void <name>glStencilOpValueAMD</name></proto>
+            <param group="StencilFaceDirection"><ptype>GLenum</ptype> <name>face</name></param>
+            <param><ptype>GLuint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilStrokePathInstancedNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param group="PathElementType"><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param group="PathElement" len="COMPSIZE(numPaths,pathNameType,paths)">const void *<name>paths</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param group="StencilValue"><ptype>GLint</ptype> <name>reference</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+            <param group="PathTransformType"><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param len="COMPSIZE(numPaths,transformType)">const <ptype>GLfloat</ptype> *<name>transformValues</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilStrokePathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
+            <param group="StencilValue"><ptype>GLint</ptype> <name>reference</name></param>
+            <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilThenCoverFillPathInstancedNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param>const void *<name>paths</name></param>
+            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param><ptype>GLenum</ptype> <name>fillMode</name></param>
+            <param><ptype>GLuint</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+            <param><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>transformValues</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilThenCoverFillPathNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLenum</ptype> <name>fillMode</name></param>
+            <param><ptype>GLuint</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilThenCoverStrokePathInstancedNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param>const void *<name>paths</name></param>
+            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param><ptype>GLint</ptype> <name>reference</name></param>
+            <param><ptype>GLuint</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+            <param><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>transformValues</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilThenCoverStrokePathNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLint</ptype> <name>reference</name></param>
+            <param><ptype>GLuint</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStopInstrumentsSGIX</name></proto>
+            <param><ptype>GLint</ptype> <name>marker</name></param>
+            <glx type="render" opcode="2070"/>
+        </command>
+        <command>
+            <proto>void <name>glStringMarkerGREMEDY</name></proto>
+            <param><ptype>GLsizei</ptype> <name>len</name></param>
+            <param len="len">const void *<name>string</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSubpixelPrecisionBiasNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>xbits</name></param>
+            <param><ptype>GLuint</ptype> <name>ybits</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSwizzleEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>res</name></param>
+            <param><ptype>GLuint</ptype> <name>in</name></param>
+            <param group="VertexShaderCoordOutEXT"><ptype>GLenum</ptype> <name>outX</name></param>
+            <param group="VertexShaderCoordOutEXT"><ptype>GLenum</ptype> <name>outY</name></param>
+            <param group="VertexShaderCoordOutEXT"><ptype>GLenum</ptype> <name>outZ</name></param>
+            <param group="VertexShaderCoordOutEXT"><ptype>GLenum</ptype> <name>outW</name></param>
+        </command>
+        <command>
+            <proto>void <name>glSyncTextureINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTagSampleBufferSGIX</name></proto>
+            <glx type="render" opcode="2050"/>
+        </command>
+        <command>
+            <proto>void <name>glTangent3bEXT</name></proto>
+            <param><ptype>GLbyte</ptype> <name>tx</name></param>
+            <param><ptype>GLbyte</ptype> <name>ty</name></param>
+            <param><ptype>GLbyte</ptype> <name>tz</name></param>
+            <vecequiv name="glTangent3bvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glTangent3bvEXT</name></proto>
+            <param len="3">const <ptype>GLbyte</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTangent3dEXT</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>tx</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>ty</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>tz</name></param>
+            <vecequiv name="glTangent3dvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glTangent3dvEXT</name></proto>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTangent3fEXT</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>tx</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>ty</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>tz</name></param>
+            <vecequiv name="glTangent3fvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glTangent3fvEXT</name></proto>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTangent3iEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>tx</name></param>
+            <param><ptype>GLint</ptype> <name>ty</name></param>
+            <param><ptype>GLint</ptype> <name>tz</name></param>
+            <vecequiv name="glTangent3ivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glTangent3ivEXT</name></proto>
+            <param len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTangent3sEXT</name></proto>
+            <param><ptype>GLshort</ptype> <name>tx</name></param>
+            <param><ptype>GLshort</ptype> <name>ty</name></param>
+            <param><ptype>GLshort</ptype> <name>tz</name></param>
+            <vecequiv name="glTangent3svEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glTangent3svEXT</name></proto>
+            <param len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTangentPointerEXT</name></proto>
+            <param group="TangentPointerTypeEXT"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTbufferMask3DFX</name></proto>
+            <param><ptype>GLuint</ptype> <name>mask</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTessellationFactorAMD</name></proto>
+            <param><ptype>GLfloat</ptype> <name>factor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTessellationModeAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glTestFenceAPPLE</name></proto>
+            <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glTestFenceNV</name></proto>
+            <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
+            <glx type="vendor" opcode="1279"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glTestObjectAPPLE</name></proto>
+            <param group="ObjectTypeAPPLE"><ptype>GLenum</ptype> <name>object</name></param>
+            <param><ptype>GLuint</ptype> <name>name</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexBuffer</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexBufferARB</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <alias name="glTexBuffer"/>
+        </command>
+        <command>
+            <proto>void <name>glTexBufferEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <alias name="glTexBuffer"/>
+        </command>
+        <command>
+            <proto>void <name>glTexBufferOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <alias name="glTexBuffer"/>
+        </command>
+        <command>
+            <proto>void <name>glTexBufferRange</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexBufferRangeEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <alias name="glTexBufferRange"/>
+        </command>
+        <command>
+            <proto>void <name>glTexBufferRangeOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <alias name="glTexBufferRange"/>
+        </command>
+        <command>
+            <proto>void <name>glTexBumpParameterfvATI</name></proto>
+            <param group="TexBumpParameterATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexBumpParameterivATI</name></proto>
+            <param group="TexBumpParameterATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1bOES</name></proto>
+            <param><ptype>GLbyte</ptype> <name>s</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1bvOES</name></proto>
+            <param len="1">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <vecequiv name="glTexCoord1dv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1dv</name></proto>
+            <param group="CoordD" len="1">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="49"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <vecequiv name="glTexCoord1fv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1fv</name></proto>
+            <param group="CoordF" len="1">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="50"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>s</name></param>
+            <vecequiv name="glTexCoord1hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1hvNV</name></proto>
+            <param group="Half16NV" len="1">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4246"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <vecequiv name="glTexCoord1iv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1iv</name></proto>
+            <param group="CoordI" len="1">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="51"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <vecequiv name="glTexCoord1sv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1sv</name></proto>
+            <param group="CoordS" len="1">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="52"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>s</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord1xvOES</name></proto>
+            <param len="1">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2bOES</name></proto>
+            <param><ptype>GLbyte</ptype> <name>s</name></param>
+            <param><ptype>GLbyte</ptype> <name>t</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2bvOES</name></proto>
+            <param len="2">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>t</name></param>
+            <vecequiv name="glTexCoord2dv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2dv</name></proto>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="53"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>t</name></param>
+            <vecequiv name="glTexCoord2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fColor3fVertex3fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>g</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fColor3fVertex3fvSUN</name></proto>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fColor4fNormal3fVertex3fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>g</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>a</name></param>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fColor4fNormal3fVertex3fvSUN</name></proto>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>n</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fColor4ubVertex3fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLubyte</ptype> <name>r</name></param>
+            <param><ptype>GLubyte</ptype> <name>g</name></param>
+            <param><ptype>GLubyte</ptype> <name>b</name></param>
+            <param><ptype>GLubyte</ptype> <name>a</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fColor4ubVertex3fvSUN</name></proto>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fNormal3fVertex3fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fNormal3fVertex3fvSUN</name></proto>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>n</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fVertex3fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fVertex3fvSUN</name></proto>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2fv</name></proto>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="54"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>s</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>t</name></param>
+            <vecequiv name="glTexCoord2hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2hvNV</name></proto>
+            <param group="Half16NV" len="2">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4247"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>t</name></param>
+            <vecequiv name="glTexCoord2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2iv</name></proto>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="55"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>t</name></param>
+            <vecequiv name="glTexCoord2sv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2sv</name></proto>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="56"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>s</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord2xvOES</name></proto>
+            <param len="2">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3bOES</name></proto>
+            <param><ptype>GLbyte</ptype> <name>s</name></param>
+            <param><ptype>GLbyte</ptype> <name>t</name></param>
+            <param><ptype>GLbyte</ptype> <name>r</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3bvOES</name></proto>
+            <param len="3">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>t</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>r</name></param>
+            <vecequiv name="glTexCoord3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3dv</name></proto>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="57"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>t</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>r</name></param>
+            <vecequiv name="glTexCoord3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3fv</name></proto>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="58"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>s</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>t</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>r</name></param>
+            <vecequiv name="glTexCoord3hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3hvNV</name></proto>
+            <param group="Half16NV" len="3">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4248"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>t</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>r</name></param>
+            <vecequiv name="glTexCoord3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3iv</name></proto>
+            <param group="CoordI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="59"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>t</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>r</name></param>
+            <vecequiv name="glTexCoord3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3sv</name></proto>
+            <param group="CoordS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="60"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>s</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+            <param><ptype>GLfixed</ptype> <name>r</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord3xvOES</name></proto>
+            <param len="3">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4bOES</name></proto>
+            <param><ptype>GLbyte</ptype> <name>s</name></param>
+            <param><ptype>GLbyte</ptype> <name>t</name></param>
+            <param><ptype>GLbyte</ptype> <name>r</name></param>
+            <param><ptype>GLbyte</ptype> <name>q</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4bvOES</name></proto>
+            <param len="4">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>s</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>t</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>r</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>q</name></param>
+            <vecequiv name="glTexCoord4dv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4dv</name></proto>
+            <param group="CoordD" len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="61"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>s</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>t</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>r</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>q</name></param>
+            <vecequiv name="glTexCoord4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4fColor4fNormal3fVertex4fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>p</name></param>
+            <param><ptype>GLfloat</ptype> <name>q</name></param>
+            <param><ptype>GLfloat</ptype> <name>r</name></param>
+            <param><ptype>GLfloat</ptype> <name>g</name></param>
+            <param><ptype>GLfloat</ptype> <name>b</name></param>
+            <param><ptype>GLfloat</ptype> <name>a</name></param>
+            <param><ptype>GLfloat</ptype> <name>nx</name></param>
+            <param><ptype>GLfloat</ptype> <name>ny</name></param>
+            <param><ptype>GLfloat</ptype> <name>nz</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4fColor4fNormal3fVertex4fvSUN</name></proto>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>c</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>n</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4fVertex4fSUN</name></proto>
+            <param><ptype>GLfloat</ptype> <name>s</name></param>
+            <param><ptype>GLfloat</ptype> <name>t</name></param>
+            <param><ptype>GLfloat</ptype> <name>p</name></param>
+            <param><ptype>GLfloat</ptype> <name>q</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4fVertex4fvSUN</name></proto>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>tc</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4fv</name></proto>
+            <param group="CoordF" len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="62"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>s</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>t</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>r</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>q</name></param>
+            <vecequiv name="glTexCoord4hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4hvNV</name></proto>
+            <param group="Half16NV" len="4">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4249"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>s</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>t</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>r</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>q</name></param>
+            <vecequiv name="glTexCoord4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4iv</name></proto>
+            <param group="CoordI" len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="63"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>s</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>t</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>r</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>q</name></param>
+            <vecequiv name="glTexCoord4sv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4sv</name></proto>
+            <param group="CoordS" len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="64"/>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>s</name></param>
+            <param><ptype>GLfixed</ptype> <name>t</name></param>
+            <param><ptype>GLfixed</ptype> <name>r</name></param>
+            <param><ptype>GLfixed</ptype> <name>q</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoord4xvOES</name></proto>
+            <param len="4">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordFormatNV</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordP1ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordP1uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordP2ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordP2uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordP3ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordP3uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordP4ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordP4uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordPointer</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="TexCoordPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordPointerEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="TexCoordPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(size,type,stride,count)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordPointerListIBM</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="TexCoordPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void **<name>pointer</name></param>
+            <param><ptype>GLint</ptype> <name>ptrstride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexCoordPointervINTEL</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="4">const void **<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexEnvf</name></proto>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="111"/>
+        </command>
+        <command>
+            <proto>void <name>glTexEnvfv</name></proto>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="112"/>
+        </command>
+        <command>
+            <proto>void <name>glTexEnvi</name></proto>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="113"/>
+        </command>
+        <command>
+            <proto>void <name>glTexEnviv</name></proto>
+            <param group="TextureEnvTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureEnvParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="114"/>
+        </command>
+        <command>
+            <proto>void <name>glTexEnvx</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexEnvxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexEnvxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexEnvxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexFilterFuncSGIS</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureFilterSGIS"><ptype>GLenum</ptype> <name>filter</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param len="n">const <ptype>GLfloat</ptype> *<name>weights</name></param>
+            <glx type="render" opcode="2064"/>
+        </command>
+        <command>
+            <proto>void <name>glTexGend</name></proto>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLdouble</ptype> <name>param</name></param>
+            <glx type="render" opcode="115"/>
+        </command>
+        <command>
+            <proto>void <name>glTexGendv</name></proto>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLdouble</ptype> *<name>params</name></param>
+            <glx type="render" opcode="116"/>
+        </command>
+        <command>
+            <proto>void <name>glTexGenf</name></proto>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="117"/>
+        </command>
+        <command>
+            <proto>void <name>glTexGenfOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>coord</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexGenfv</name></proto>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="118"/>
+        </command>
+        <command>
+            <proto>void <name>glTexGenfvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>coord</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexGeni</name></proto>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="119"/>
+        </command>
+        <command>
+            <proto>void <name>glTexGeniOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>coord</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexGeniv</name></proto>
+            <param group="TextureCoordName"><ptype>GLenum</ptype> <name>coord</name></param>
+            <param group="TextureGenParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="120"/>
+        </command>
+        <command>
+            <proto>void <name>glTexGenivOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>coord</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexGenxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>coord</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexGenxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>coord</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexImage1D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureComponentCount"><ptype>GLint</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>pixels</name></param>
+            <glx type="render" opcode="109"/>
+            <glx type="render" opcode="328" name="glTexImage1DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glTexImage2D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureComponentCount"><ptype>GLint</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>pixels</name></param>
+            <glx type="render" opcode="110"/>
+            <glx type="render" opcode="329" name="glTexImage2DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glTexImage2DMultisample</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexImage2DMultisampleCoverageNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>coverageSamples</name></param>
+            <param><ptype>GLsizei</ptype> <name>colorSamples</name></param>
+            <param><ptype>GLint</ptype> <name>internalFormat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedSampleLocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexImage3D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureComponentCount"><ptype>GLint</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+            <glx type="render" opcode="4114"/>
+            <glx type="render" opcode="330" name="glTexImage3DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glTexImage3DEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+            <alias name="glTexImage3D"/>
+            <glx type="render" opcode="4114"/>
+        </command>
+        <command>
+            <proto>void <name>glTexImage3DMultisample</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexImage3DMultisampleCoverageNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>coverageSamples</name></param>
+            <param><ptype>GLsizei</ptype> <name>colorSamples</name></param>
+            <param><ptype>GLint</ptype> <name>internalFormat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedSampleLocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexImage3DOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLint</ptype> <name>border</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+            <alias name="glTexImage3D"/>
+        </command>
+        <command>
+            <proto>void <name>glTexImage4DSGIS</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLsizei</ptype> <name>size4d</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth,size4d)">const void *<name>pixels</name></param>
+            <glx type="render" opcode="2057"/>
+        </command>
+        <command>
+            <proto>void <name>glTexPageCommitmentARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexPageCommitmentEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+            <alias name="glTexPageCommitmentARB"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterIiv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="346"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterIivEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glTexParameterIiv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterIivOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glTexParameterIiv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterIuiv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="347"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterIuivEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glTexParameterIuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterIuivOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glTexParameterIuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterf</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <glx type="render" opcode="105"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterfv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+            <glx type="render" opcode="106"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameteri</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <glx type="render" opcode="107"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameteriv</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <glx type="render" opcode="108"/>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterx</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterxOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfixed</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterxv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexParameterxvOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfixed</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexRenderbufferNV</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexStorage1D</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexStorage1DEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <alias name="glTexStorage1D"/>
+        </command>
+        <command>
+            <proto>void <name>glTexStorage2D</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexStorage2DEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glTexStorage2D"/>
+        </command>
+        <command>
+            <proto>void <name>glTexStorage2DMultisample</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexStorage3D</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexStorage3DEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <alias name="glTexStorage3D"/>
+        </command>
+        <command>
+            <proto>void <name>glTexStorage3DMultisample</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexStorage3DMultisampleOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+            <alias name="glTexStorage3DMultisample"/>
+        </command>
+        <command>
+            <proto>void <name>glTexStorageSparseAMD</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalFormat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLsizei</ptype> <name>layers</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexSubImage1D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>pixels</name></param>
+            <glx type="render" opcode="4099"/>
+            <glx type="render" opcode="331" name="glTexSubImage1DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glTexSubImage1DEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>pixels</name></param>
+            <alias name="glTexSubImage1D"/>
+            <glx type="render" opcode="4099"/>
+        </command>
+        <command>
+            <proto>void <name>glTexSubImage2D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>pixels</name></param>
+            <glx type="render" opcode="4100"/>
+            <glx type="render" opcode="332" name="glTexSubImage2DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glTexSubImage2DEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>pixels</name></param>
+            <alias name="glTexSubImage2D"/>
+            <glx type="render" opcode="4100"/>
+        </command>
+        <command>
+            <proto>void <name>glTexSubImage3D</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+            <glx type="render" opcode="4115"/>
+            <glx type="render" opcode="333" name="glTexSubImage3DPBO" comment="PBO protocol"/>
+        </command>
+        <command>
+            <proto>void <name>glTexSubImage3DEXT</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+            <alias name="glTexSubImage3D"/>
+            <glx type="render" opcode="4115"/>
+        </command>
+        <command>
+            <proto>void <name>glTexSubImage3DOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+            <alias name="glTexSubImage3D"/>
+        </command>
+        <command>
+            <proto>void <name>glTexSubImage4DSGIS</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>woffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLsizei</ptype> <name>size4d</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth,size4d)">const void *<name>pixels</name></param>
+            <glx type="render" opcode="2058"/>
+        </command>
+        <command>
+            <proto>void <name>glTextureBarrier</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glTextureBarrierNV</name></proto>
+            <glx type="render" opcode="4348"/>
+        </command>
+        <command>
+            <proto>void <name>glTextureBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureBufferEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureBufferRange</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureBufferRangeEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureColorMaskSGIS</name></proto>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>red</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>green</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>blue</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>alpha</name></param>
+            <glx type="render" opcode="2082"/>
+        </command>
+        <command>
+            <proto>void <name>glTextureImage1DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureComponentCount"><ptype>GLint</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureImage2DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureComponentCount"><ptype>GLint</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureImage2DMultisampleCoverageNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>coverageSamples</name></param>
+            <param><ptype>GLsizei</ptype> <name>colorSamples</name></param>
+            <param><ptype>GLint</ptype> <name>internalFormat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedSampleLocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureImage2DMultisampleNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLint</ptype> <name>internalFormat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedSampleLocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureImage3DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="TextureComponentCount"><ptype>GLint</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>border</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureImage3DMultisampleCoverageNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>coverageSamples</name></param>
+            <param><ptype>GLsizei</ptype> <name>colorSamples</name></param>
+            <param><ptype>GLint</ptype> <name>internalFormat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedSampleLocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureImage3DMultisampleNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLint</ptype> <name>internalFormat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedSampleLocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureLightEXT</name></proto>
+            <param group="LightTexturePNameEXT"><ptype>GLenum</ptype> <name>pname</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureMaterialEXT</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="MaterialParameter"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureNormalEXT</name></proto>
+            <param group="TextureNormalModeEXT"><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexturePageCommitmentEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterIiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterIivEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterIuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterIuivEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterf</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterfEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
+            <vecequiv name="glTextureParameterfvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterfvEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameteri</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameteriEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>param</name></param>
+            <vecequiv name="glTextureParameterivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>const <ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterivEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureRangeAPPLE</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="length">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureRenderbufferEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage1D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage1DEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage2D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage2DEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage2DMultisample</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage2DMultisampleEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param group="TextureInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage3D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage3DEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage3DMultisample</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorage3DMultisampleEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureStorageSparseAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalFormat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLsizei</ptype> <name>layers</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureSubImage1D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureSubImage1DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureSubImage2D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureSubImage2DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureSubImage3D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureSubImage3DEXT</name></proto>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureView</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>origtexture</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>minlevel</name></param>
+            <param><ptype>GLuint</ptype> <name>numlevels</name></param>
+            <param><ptype>GLuint</ptype> <name>minlayer</name></param>
+            <param><ptype>GLuint</ptype> <name>numlayers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureViewEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>origtexture</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>minlevel</name></param>
+            <param><ptype>GLuint</ptype> <name>numlevels</name></param>
+            <param><ptype>GLuint</ptype> <name>minlayer</name></param>
+            <param><ptype>GLuint</ptype> <name>numlayers</name></param>
+            <alias name="glTextureView"/>
+        </command>
+        <command>
+            <proto>void <name>glTextureViewOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>origtexture</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>minlevel</name></param>
+            <param><ptype>GLuint</ptype> <name>numlevels</name></param>
+            <param><ptype>GLuint</ptype> <name>minlayer</name></param>
+            <param><ptype>GLuint</ptype> <name>numlayers</name></param>
+            <alias name="glTextureView"/>
+        </command>
+        <command>
+            <proto>void <name>glTrackMatrixNV</name></proto>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>address</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>matrix</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>transform</name></param>
+            <glx type="render" opcode="4188"/>
+        </command>
+        <command>
+            <proto>void <name>glTransformFeedbackAttribsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLint</ptype> *<name>attribs</name></param>
+            <param><ptype>GLenum</ptype> <name>bufferMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTransformFeedbackBufferBase</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTransformFeedbackBufferRange</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTransformFeedbackStreamAttribsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLint</ptype> *<name>attribs</name></param>
+            <param><ptype>GLsizei</ptype> <name>nbuffers</name></param>
+            <param len="nbuffers">const <ptype>GLint</ptype> *<name>bufstreams</name></param>
+            <param><ptype>GLenum</ptype> <name>bufferMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTransformFeedbackVaryings</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLchar</ptype> *const*<name>varyings</name></param>
+            <param><ptype>GLenum</ptype> <name>bufferMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTransformFeedbackVaryingsEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLchar</ptype> *const*<name>varyings</name></param>
+            <param><ptype>GLenum</ptype> <name>bufferMode</name></param>
+            <alias name="glTransformFeedbackVaryings"/>
+        </command>
+        <command>
+            <proto>void <name>glTransformFeedbackVaryingsNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLint</ptype> *<name>locations</name></param>
+            <param><ptype>GLenum</ptype> <name>bufferMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTransformPathNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>resultPath</name></param>
+            <param group="Path"><ptype>GLuint</ptype> <name>srcPath</name></param>
+            <param group="PathTransformType"><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param len="COMPSIZE(transformType)">const <ptype>GLfloat</ptype> *<name>transformValues</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTranslated</name></proto>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <glx type="render" opcode="189"/>
+        </command>
+        <command>
+            <proto>void <name>glTranslatef</name></proto>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <glx type="render" opcode="190"/>
+        </command>
+        <command>
+            <proto>void <name>glTranslatex</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTranslatexOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1d</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1f</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1fARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <alias name="glUniform1f"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform1fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1fvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniform1fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform1i</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1i64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1i64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1i64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1i64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1iARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <alias name="glUniform1i"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform1iv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1ivARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLint</ptype> *<name>value</name></param>
+            <alias name="glUniform1iv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform1ui</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1ui64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1ui64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1ui64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1ui64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1uiEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <alias name="glUniform1ui"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform1uiv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform1uivEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <alias name="glUniform1uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform2d</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2f</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2fARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <alias name="glUniform2f"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform2fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2fvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniform2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform2i</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2i64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2i64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2i64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2i64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2iARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <alias name="glUniform2i"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform2iv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2ivARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint</ptype> *<name>value</name></param>
+            <alias name="glUniform2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform2ui</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2ui64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2ui64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2ui64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2ui64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2uiEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <alias name="glUniform2ui"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform2uiv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform2uivEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <alias name="glUniform2uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform3d</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3f</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param><ptype>GLfloat</ptype> <name>v2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3fARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param><ptype>GLfloat</ptype> <name>v2</name></param>
+            <alias name="glUniform3f"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform3fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3fvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniform3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform3i</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <param><ptype>GLint</ptype> <name>v2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3i64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+            <param><ptype>GLint64</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3i64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3i64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3i64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3iARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <param><ptype>GLint</ptype> <name>v2</name></param>
+            <alias name="glUniform3i"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform3iv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3ivARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint</ptype> *<name>value</name></param>
+            <alias name="glUniform3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform3ui</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <param><ptype>GLuint</ptype> <name>v2</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3ui64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+            <param><ptype>GLuint64</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3ui64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3ui64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3ui64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3uiEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <param><ptype>GLuint</ptype> <name>v2</name></param>
+            <alias name="glUniform3ui"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform3uiv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform3uivEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <alias name="glUniform3uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform4d</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4f</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param><ptype>GLfloat</ptype> <name>v2</name></param>
+            <param><ptype>GLfloat</ptype> <name>v3</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4fARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLfloat</ptype> <name>v0</name></param>
+            <param><ptype>GLfloat</ptype> <name>v1</name></param>
+            <param><ptype>GLfloat</ptype> <name>v2</name></param>
+            <param><ptype>GLfloat</ptype> <name>v3</name></param>
+            <alias name="glUniform4f"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform4fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4fvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniform4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform4i</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <param><ptype>GLint</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>v3</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4i64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+            <param><ptype>GLint64</ptype> <name>z</name></param>
+            <param><ptype>GLint64</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4i64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>z</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4i64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4i64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4iARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint</ptype> <name>v0</name></param>
+            <param><ptype>GLint</ptype> <name>v1</name></param>
+            <param><ptype>GLint</ptype> <name>v2</name></param>
+            <param><ptype>GLint</ptype> <name>v3</name></param>
+            <alias name="glUniform4i"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform4iv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4ivARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint</ptype> *<name>value</name></param>
+            <alias name="glUniform4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform4ui</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <param><ptype>GLuint</ptype> <name>v2</name></param>
+            <param><ptype>GLuint</ptype> <name>v3</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4ui64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+            <param><ptype>GLuint64</ptype> <name>z</name></param>
+            <param><ptype>GLuint64</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4ui64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>z</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4ui64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4ui64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4uiEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>v0</name></param>
+            <param><ptype>GLuint</ptype> <name>v1</name></param>
+            <param><ptype>GLuint</ptype> <name>v2</name></param>
+            <param><ptype>GLuint</ptype> <name>v3</name></param>
+            <alias name="glUniform4ui"/>
+        </command>
+        <command>
+            <proto>void <name>glUniform4uiv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniform4uivEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <alias name="glUniform4uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformBlockBinding</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>uniformBlockIndex</name></param>
+            <param><ptype>GLuint</ptype> <name>uniformBlockBinding</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformBufferEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformHandleui64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformHandleui64IMG</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>value</name></param>
+            <alias name="glUniformHandleui64ARB"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformHandleui64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformHandleui64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformHandleui64vIMG</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64</ptype> *<name>value</name></param>
+            <alias name="glUniformHandleui64vARB"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformHandleui64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix2dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix2fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix2fvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniformMatrix2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix2x3dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix2x3fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <glx type="render" opcode="305"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix2x3fvNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniformMatrix2x3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix2x4dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix2x4fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <glx type="render" opcode="307"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix2x4fvNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniformMatrix2x4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix3dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*9">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix3fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*9">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix3fvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*9">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniformMatrix3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix3x2dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix3x2fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <glx type="render" opcode="306"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix3x2fvNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniformMatrix3x2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix3x4dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix3x4fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <glx type="render" opcode="309"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix3x4fvNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniformMatrix3x4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix4dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*16">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix4fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*16">const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix4fvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*16">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniformMatrix4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix4x2dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix4x2fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <glx type="render" opcode="308"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix4x2fvNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniformMatrix4x2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix4x3dv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLdouble</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix4x3fv</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <glx type="render" opcode="310"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformMatrix4x3fvNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <alias name="glUniformMatrix4x3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glUniformSubroutinesuiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint</ptype> *<name>indices</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformui64NV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUniformui64vNV</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUnlockArraysEXT</name></proto>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glUnmapBuffer</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glUnmapBufferARB</name></proto>
+            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
+            <alias name="glUnmapBuffer"/>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glUnmapBufferOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <alias name="glUnmapBuffer"/>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glUnmapNamedBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glUnmapNamedBufferEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUnmapObjectBufferATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUnmapTexture2DINTEL</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUpdateObjectBufferATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLuint</ptype> <name>offset</name></param>
+            <param><ptype>GLsizei</ptype> <name>size</name></param>
+            <param len="size">const void *<name>pointer</name></param>
+            <param group="PreserveModeATI"><ptype>GLenum</ptype> <name>preserve</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUseProgram</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUseProgramObjectARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <alias name="glUseProgram"/>
+        </command>
+        <command>
+            <proto>void <name>glUseProgramStages</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+            <param><ptype>GLbitfield</ptype> <name>stages</name></param>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUseProgramStagesEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+            <param><ptype>GLbitfield</ptype> <name>stages</name></param>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glUseShaderProgramEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVDPAUFiniNV</name></proto>
+        </command>
+        <command>
+            <proto>void <name>glVDPAUGetSurfaceivNV</name></proto>
+            <param group="vdpauSurfaceNV"><ptype>GLvdpauSurfaceNV</ptype> <name>surface</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>values</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVDPAUInitNV</name></proto>
+            <param>const void *<name>vdpDevice</name></param>
+            <param>const void *<name>getProcAddress</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLboolean</ptype> <name>glVDPAUIsSurfaceNV</name></proto>
+            <param group="vdpauSurfaceNV"><ptype>GLvdpauSurfaceNV</ptype> <name>surface</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVDPAUMapSurfacesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numSurfaces</name></param>
+            <param group="vdpauSurfaceNV" len="numSurfaces">const <ptype>GLvdpauSurfaceNV</ptype> *<name>surfaces</name></param>
+        </command>
+        <command>
+            <proto group="vdpauSurfaceNV"><ptype>GLvdpauSurfaceNV</ptype> <name>glVDPAURegisterOutputSurfaceNV</name></proto>
+            <param>const void *<name>vdpSurface</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>numTextureNames</name></param>
+            <param len="numTextureNames">const <ptype>GLuint</ptype> *<name>textureNames</name></param>
+        </command>
+        <command>
+            <proto group="vdpauSurfaceNV"><ptype>GLvdpauSurfaceNV</ptype> <name>glVDPAURegisterVideoSurfaceNV</name></proto>
+            <param>const void *<name>vdpSurface</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>numTextureNames</name></param>
+            <param len="numTextureNames">const <ptype>GLuint</ptype> *<name>textureNames</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVDPAUSurfaceAccessNV</name></proto>
+            <param group="vdpauSurfaceNV"><ptype>GLvdpauSurfaceNV</ptype> <name>surface</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVDPAUUnmapSurfacesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numSurface</name></param>
+            <param group="vdpauSurfaceNV" len="numSurface">const <ptype>GLvdpauSurfaceNV</ptype> *<name>surfaces</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVDPAUUnregisterSurfaceNV</name></proto>
+            <param group="vdpauSurfaceNV"><ptype>GLvdpauSurfaceNV</ptype> <name>surface</name></param>
+        </command>
+        <command>
+            <proto>void <name>glValidateProgram</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+        </command>
+        <command>
+            <proto>void <name>glValidateProgramARB</name></proto>
+            <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
+            <alias name="glValidateProgram"/>
+        </command>
+        <command>
+            <proto>void <name>glValidateProgramPipeline</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+        </command>
+        <command>
+            <proto>void <name>glValidateProgramPipelineEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantArrayObjectATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="ScalarType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLuint</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantPointerEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param group="ScalarType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(id,type,stride)">const void *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantbvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param len="COMPSIZE(id)">const <ptype>GLbyte</ptype> *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantdvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param len="COMPSIZE(id)">const <ptype>GLdouble</ptype> *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantfvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param len="COMPSIZE(id)">const <ptype>GLfloat</ptype> *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param len="COMPSIZE(id)">const <ptype>GLint</ptype> *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantsvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param len="COMPSIZE(id)">const <ptype>GLshort</ptype> *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantubvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param len="COMPSIZE(id)">const <ptype>GLubyte</ptype> *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantuivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param len="COMPSIZE(id)">const <ptype>GLuint</ptype> *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVariantusvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param len="COMPSIZE(id)">const <ptype>GLushort</ptype> *<name>addr</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex2bOES</name></proto>
+            <param><ptype>GLbyte</ptype> <name>x</name></param>
+            <param><ptype>GLbyte</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex2bvOES</name></proto>
+            <param len="2">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex2d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <vecequiv name="glVertex2dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2dv</name></proto>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="65"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <vecequiv name="glVertex2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2fv</name></proto>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="66"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>x</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>y</name></param>
+            <vecequiv name="glVertex2hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2hvNV</name></proto>
+            <param group="Half16NV" len="2">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4240"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <vecequiv name="glVertex2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2iv</name></proto>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="67"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <vecequiv name="glVertex2sv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2sv</name></proto>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="68"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex2xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex2xvOES</name></proto>
+            <param len="2">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex3bOES</name></proto>
+            <param><ptype>GLbyte</ptype> <name>x</name></param>
+            <param><ptype>GLbyte</ptype> <name>y</name></param>
+            <param><ptype>GLbyte</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex3bvOES</name></proto>
+            <param len="3">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex3d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>z</name></param>
+            <vecequiv name="glVertex3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3dv</name></proto>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="69"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>z</name></param>
+            <vecequiv name="glVertex3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3fv</name></proto>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="70"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>x</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>y</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>z</name></param>
+            <vecequiv name="glVertex3hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3hvNV</name></proto>
+            <param group="Half16NV" len="3">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4241"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>z</name></param>
+            <vecequiv name="glVertex3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3iv</name></proto>
+            <param group="CoordI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="71"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>z</name></param>
+            <vecequiv name="glVertex3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3sv</name></proto>
+            <param group="CoordS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="72"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex3xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex3xvOES</name></proto>
+            <param len="3">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex4bOES</name></proto>
+            <param><ptype>GLbyte</ptype> <name>x</name></param>
+            <param><ptype>GLbyte</ptype> <name>y</name></param>
+            <param><ptype>GLbyte</ptype> <name>z</name></param>
+            <param><ptype>GLbyte</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex4bvOES</name></proto>
+            <param len="4">const <ptype>GLbyte</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex4d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>z</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>w</name></param>
+            <vecequiv name="glVertex4dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4dv</name></proto>
+            <param group="CoordD" len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="73"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>z</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>w</name></param>
+            <vecequiv name="glVertex4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4fv</name></proto>
+            <param group="CoordF" len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="74"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4hNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>x</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>y</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>z</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>w</name></param>
+            <vecequiv name="glVertex4hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4hvNV</name></proto>
+            <param group="Half16NV" len="4">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4242"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>z</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>w</name></param>
+            <vecequiv name="glVertex4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4iv</name></proto>
+            <param group="CoordI" len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="75"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>z</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>w</name></param>
+            <vecequiv name="glVertex4sv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4sv</name></proto>
+            <param group="CoordS" len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="76"/>
+        </command>
+        <command>
+            <proto>void <name>glVertex4xOES</name></proto>
+            <param><ptype>GLfixed</ptype> <name>x</name></param>
+            <param><ptype>GLfixed</ptype> <name>y</name></param>
+            <param><ptype>GLfixed</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertex4xvOES</name></proto>
+            <param len="4">const <ptype>GLfixed</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayAttribBinding</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayAttribFormat</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayAttribIFormat</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayAttribLFormat</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayBindVertexBufferEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayBindingDivisor</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayColorOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="ColorPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayEdgeFlagOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayElementBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayFogCoordOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="FogCoordinatePointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayIndexOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="IndexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayMultiTexCoordOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>texunit</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="TexCoordPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayNormalOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="NormalPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayParameteriAPPLE</name></proto>
+            <param group="VertexArrayPNameAPPLE"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayRangeAPPLE</name></proto>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="length">void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayRangeNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>length</name></param>
+            <param len="COMPSIZE(length)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArraySecondaryColorOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="ColorPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayTexCoordOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="TexCoordPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexAttribBindingEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexAttribDivisorEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexAttribFormatEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexAttribIFormatEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexAttribIOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexAttribEnum"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexAttribLFormatEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexAttribLOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexAttribOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexAttribPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexBindingDivisorEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexBuffers</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>buffers</name></param>
+            <param>const <ptype>GLintptr</ptype> *<name>offsets</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>strides</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexOffsetEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1d</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <vecequiv name="glVertexAttrib1dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1dARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <alias name="glVertexAttrib1d"/>
+            <vecequiv name="glVertexAttrib1dvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1dNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <alias name="glVertexAttrib1d"/>
+            <vecequiv name="glVertexAttrib1dvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4197"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1dvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib1dv"/>
+            <glx type="render" opcode="4197"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1dvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib1dv"/>
+            <glx type="render" opcode="4197"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1f</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <vecequiv name="glVertexAttrib1fv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1fARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <alias name="glVertexAttrib1f"/>
+            <vecequiv name="glVertexAttrib1fvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1fNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <alias name="glVertexAttrib1f"/>
+            <vecequiv name="glVertexAttrib1fvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4193"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1fvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib1fv"/>
+            <glx type="render" opcode="4193"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1fvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib1fv"/>
+            <glx type="render" opcode="4193"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1hNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>x</name></param>
+            <vecequiv name="glVertexAttrib1hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1hvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Half16NV" len="1">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4257"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1s</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <vecequiv name="glVertexAttrib1sv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1sARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <alias name="glVertexAttrib1s"/>
+            <vecequiv name="glVertexAttrib1svARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1sNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <alias name="glVertexAttrib1s"/>
+            <vecequiv name="glVertexAttrib1svNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1sv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4189"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1svARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib1sv"/>
+            <glx type="render" opcode="4189"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib1svNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib1sv"/>
+            <glx type="render" opcode="4189"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2d</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <vecequiv name="glVertexAttrib2dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2dARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <alias name="glVertexAttrib2d"/>
+            <vecequiv name="glVertexAttrib2dvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2dNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <alias name="glVertexAttrib2d"/>
+            <vecequiv name="glVertexAttrib2dvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4198"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2dvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib2dv"/>
+            <glx type="render" opcode="4198"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2dvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib2dv"/>
+            <glx type="render" opcode="4198"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2f</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <vecequiv name="glVertexAttrib2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2fARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <alias name="glVertexAttrib2f"/>
+            <vecequiv name="glVertexAttrib2fvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2fNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <alias name="glVertexAttrib2f"/>
+            <vecequiv name="glVertexAttrib2fvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4194"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2fvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib2fv"/>
+            <glx type="render" opcode="4194"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2fvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib2fv"/>
+            <glx type="render" opcode="4194"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2hNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>x</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>y</name></param>
+            <vecequiv name="glVertexAttrib2hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2hvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Half16NV" len="2">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4258"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2s</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <vecequiv name="glVertexAttrib2sv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2sARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <alias name="glVertexAttrib2s"/>
+            <vecequiv name="glVertexAttrib2svARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2sNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <alias name="glVertexAttrib2s"/>
+            <vecequiv name="glVertexAttrib2svNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2sv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4190"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2svARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib2sv"/>
+            <glx type="render" opcode="4190"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib2svNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib2sv"/>
+            <glx type="render" opcode="4190"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3d</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <vecequiv name="glVertexAttrib3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3dARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <alias name="glVertexAttrib3d"/>
+            <vecequiv name="glVertexAttrib3dvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3dNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <alias name="glVertexAttrib3d"/>
+            <vecequiv name="glVertexAttrib3dvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4199"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3dvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib3dv"/>
+            <glx type="render" opcode="4199"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3dvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib3dv"/>
+            <glx type="render" opcode="4199"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3f</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <vecequiv name="glVertexAttrib3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3fARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <alias name="glVertexAttrib3f"/>
+            <vecequiv name="glVertexAttrib3fvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3fNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <alias name="glVertexAttrib3f"/>
+            <vecequiv name="glVertexAttrib3fvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4195"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3fvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib3fv"/>
+            <glx type="render" opcode="4195"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3fvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib3fv"/>
+            <glx type="render" opcode="4195"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3hNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>x</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>y</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>z</name></param>
+            <vecequiv name="glVertexAttrib3hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3hvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Half16NV" len="3">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4259"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3s</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <param><ptype>GLshort</ptype> <name>z</name></param>
+            <vecequiv name="glVertexAttrib3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3sARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <param><ptype>GLshort</ptype> <name>z</name></param>
+            <alias name="glVertexAttrib3s"/>
+            <vecequiv name="glVertexAttrib3svARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3sNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <param><ptype>GLshort</ptype> <name>z</name></param>
+            <alias name="glVertexAttrib3s"/>
+            <vecequiv name="glVertexAttrib3svNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3sv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4191"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3svARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib3sv"/>
+            <glx type="render" opcode="4191"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib3svNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib3sv"/>
+            <glx type="render" opcode="4191"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4Nbv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLbyte</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4NbvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLbyte</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4Nbv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4Niv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4NivARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4Niv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4Nsv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4NsvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4Nsv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4Nub</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLubyte</ptype> <name>x</name></param>
+            <param><ptype>GLubyte</ptype> <name>y</name></param>
+            <param><ptype>GLubyte</ptype> <name>z</name></param>
+            <param><ptype>GLubyte</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4NubARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLubyte</ptype> <name>x</name></param>
+            <param><ptype>GLubyte</ptype> <name>y</name></param>
+            <param><ptype>GLubyte</ptype> <name>z</name></param>
+            <param><ptype>GLubyte</ptype> <name>w</name></param>
+            <alias name="glVertexAttrib4Nub"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4Nubv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4201"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4NubvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4Nubv"/>
+            <glx type="render" opcode="4201"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4Nuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4NuivARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4Nuiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4Nusv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLushort</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4NusvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLushort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4Nusv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4bv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLbyte</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4bvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLbyte</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4bv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4d</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+            <vecequiv name="glVertexAttrib4dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4dARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+            <alias name="glVertexAttrib4d"/>
+            <vecequiv name="glVertexAttrib4dvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4dNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+            <alias name="glVertexAttrib4d"/>
+            <vecequiv name="glVertexAttrib4dvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4200"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4dvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4dv"/>
+            <glx type="render" opcode="4200"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4dvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4dv"/>
+            <glx type="render" opcode="4200"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4f</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <vecequiv name="glVertexAttrib4fv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4fARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <alias name="glVertexAttrib4f"/>
+            <vecequiv name="glVertexAttrib4fvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4fNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <alias name="glVertexAttrib4f"/>
+            <vecequiv name="glVertexAttrib4fvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4fv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4196"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4fvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4fv"/>
+            <glx type="render" opcode="4196"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4fvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4fv"/>
+            <glx type="render" opcode="4196"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4hNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>x</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>y</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>z</name></param>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>w</name></param>
+            <vecequiv name="glVertexAttrib4hvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4hvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Half16NV" len="4">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4260"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4ivARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4s</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <param><ptype>GLshort</ptype> <name>z</name></param>
+            <param><ptype>GLshort</ptype> <name>w</name></param>
+            <vecequiv name="glVertexAttrib4sv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4sARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <param><ptype>GLshort</ptype> <name>z</name></param>
+            <param><ptype>GLshort</ptype> <name>w</name></param>
+            <alias name="glVertexAttrib4s"/>
+            <vecequiv name="glVertexAttrib4svARB"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4sNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <param><ptype>GLshort</ptype> <name>z</name></param>
+            <param><ptype>GLshort</ptype> <name>w</name></param>
+            <alias name="glVertexAttrib4s"/>
+            <vecequiv name="glVertexAttrib4svNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4sv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4192"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4svARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4sv"/>
+            <glx type="render" opcode="4192"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4svNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4sv"/>
+            <glx type="render" opcode="4192"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4ubNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>x</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>y</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>z</name></param>
+            <param group="ColorUB"><ptype>GLubyte</ptype> <name>w</name></param>
+            <alias name="glVertexAttrib4Nub"/>
+            <vecequiv name="glVertexAttrib4ubvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4ubv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4ubvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4ubv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4ubvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="ColorUB" len="4">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4Nubv"/>
+            <glx type="render" opcode="4201"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4uivARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4usv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLushort</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttrib4usvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLushort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttrib4usv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribArrayObjectATI</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexAttribPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLuint</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribBinding</name></proto>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribDivisor</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribDivisorANGLE</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+            <alias name="glVertexAttribDivisor"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribDivisorARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+            <alias name="glVertexAttribDivisor"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribDivisorEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+            <alias name="glVertexAttribDivisor"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribDivisorNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+            <alias name="glVertexAttribDivisor"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribFormat</name></proto>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribFormatNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI1i</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <vecequiv name="glVertexAttribI1iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI1iEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <alias name="glVertexAttribI1i"/>
+            <vecequiv name="glVertexAttribI1ivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI1iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI1ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI1iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI1ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <vecequiv name="glVertexAttribI1uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI1uiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <alias name="glVertexAttribI1ui"/>
+            <vecequiv name="glVertexAttribI1uivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI1uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI1uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI1uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI2i</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <vecequiv name="glVertexAttribI2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI2iEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <alias name="glVertexAttribI2i"/>
+            <vecequiv name="glVertexAttribI2ivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI2iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI2ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI2ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <vecequiv name="glVertexAttribI2uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI2uiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <alias name="glVertexAttribI2ui"/>
+            <vecequiv name="glVertexAttribI2uivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI2uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLuint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI2uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI2uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI3i</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+            <vecequiv name="glVertexAttribI3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI3iEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+            <alias name="glVertexAttribI3i"/>
+            <vecequiv name="glVertexAttribI3ivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI3iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI3ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI3ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <param><ptype>GLuint</ptype> <name>z</name></param>
+            <vecequiv name="glVertexAttribI3uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI3uiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <param><ptype>GLuint</ptype> <name>z</name></param>
+            <alias name="glVertexAttribI3ui"/>
+            <vecequiv name="glVertexAttribI3uivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI3uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLuint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI3uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI3uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4bv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLbyte</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4bvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLbyte</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI4bv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4i</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+            <param><ptype>GLint</ptype> <name>w</name></param>
+            <vecequiv name="glVertexAttribI4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4iEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+            <param><ptype>GLint</ptype> <name>w</name></param>
+            <alias name="glVertexAttribI4i"/>
+            <vecequiv name="glVertexAttribI4ivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4ivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI4iv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4sv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4svEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI4sv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4ubv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4ubvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI4ubv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <param><ptype>GLuint</ptype> <name>z</name></param>
+            <param><ptype>GLuint</ptype> <name>w</name></param>
+            <vecequiv name="glVertexAttribI4uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4uiEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>x</name></param>
+            <param><ptype>GLuint</ptype> <name>y</name></param>
+            <param><ptype>GLuint</ptype> <name>z</name></param>
+            <param><ptype>GLuint</ptype> <name>w</name></param>
+            <alias name="glVertexAttribI4ui"/>
+            <vecequiv name="glVertexAttribI4uivEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4uivEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI4uiv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4usv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLushort</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribI4usvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLushort</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribI4usv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribIFormat</name></proto>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribIFormatNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribIPointer</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexAttribEnum"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribIPointerEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexAttribEnum"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+            <alias name="glVertexAttribIPointer"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1d</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1dEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <alias name="glVertexAttribL1d"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribL1dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1i64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1i64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLint64EXT</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1ui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1ui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1ui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param>const <ptype>GLuint64EXT</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL1ui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="1">const <ptype>GLuint64EXT</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL2d</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL2dEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <alias name="glVertexAttribL2d"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL2dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL2dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribL2dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL2i64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL2i64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLint64EXT</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL2ui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL2ui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="2">const <ptype>GLuint64EXT</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL3d</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL3dEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <alias name="glVertexAttribL3d"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL3dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL3dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribL3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL3i64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL3i64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLint64EXT</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL3ui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL3ui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="3">const <ptype>GLuint64EXT</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL4d</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL4dEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+            <alias name="glVertexAttribL4d"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL4dv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL4dvEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glVertexAttribL4dv"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL4i64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>z</name></param>
+            <param><ptype>GLint64EXT</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL4i64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint64EXT</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL4ui64NV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>z</name></param>
+            <param><ptype>GLuint64EXT</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribL4ui64vNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLuint64EXT</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribLFormat</name></proto>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribLFormatNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribLPointer</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="size">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribLPointerEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="size">const void *<name>pointer</name></param>
+            <alias name="glVertexAttribLPointer"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribP1ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLuint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribP1uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribP2ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLuint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribP2uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribP3ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLuint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribP3uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribP4ui</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLuint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribP4uiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribParameteriAMD</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribPointer</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexAttribPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribPointerARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexAttribPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+            <alias name="glVertexAttribPointer"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribPointerNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>fsize</name></param>
+            <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(fsize,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs1dvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4210"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs1fvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4206"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs1hvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Half16NV" len="n">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4261"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs1svNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4202"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs2dvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4211"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs2fvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4207"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs2hvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Half16NV" len="n">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4262"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs2svNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4203"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs3dvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4212"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs3fvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4208"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs3hvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Half16NV" len="n">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4263"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs3svNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4204"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs4dvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4213"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs4fvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4209"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs4hvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param group="Half16NV" len="n">const <ptype>GLhalfNV</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4264"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs4svNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4205"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexAttribs4ubvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="ColorUB" len="count*4">const <ptype>GLubyte</ptype> *<name>v</name></param>
+            <glx type="render" opcode="4214"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexBindingDivisor</name></proto>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexBlendARB</name></proto>
+            <param><ptype>GLint</ptype> <name>count</name></param>
+            <glx type="render" opcode="226"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexBlendEnvfATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexBlendEnviATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexFormatNV</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexP2ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexP2uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexP3ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexP3uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexP4ui</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexP4uiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="1">const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexPointer</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexPointerEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(size,type,stride,count)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexPointerListIBM</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLint</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(size,type,stride)">const void **<name>pointer</name></param>
+            <param><ptype>GLint</ptype> <name>ptrstride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexPointervINTEL</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexPointerType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="4">const void **<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream1dATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream1dvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="1">const <ptype>GLdouble</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream1fATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream1fvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="1">const <ptype>GLfloat</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream1iATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream1ivATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="1">const <ptype>GLint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream1sATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream1svATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="1">const <ptype>GLshort</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream2dATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream2dvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="2">const <ptype>GLdouble</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream2fATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream2fvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="2">const <ptype>GLfloat</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream2iATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream2ivATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="2">const <ptype>GLint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream2sATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream2svATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="2">const <ptype>GLshort</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream3dATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream3dvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="3">const <ptype>GLdouble</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream3fATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream3fvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="3">const <ptype>GLfloat</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream3iATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream3ivATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="3">const <ptype>GLint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream3sATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <param><ptype>GLshort</ptype> <name>z</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream3svATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="3">const <ptype>GLshort</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream4dATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLdouble</ptype> <name>x</name></param>
+            <param><ptype>GLdouble</ptype> <name>y</name></param>
+            <param><ptype>GLdouble</ptype> <name>z</name></param>
+            <param><ptype>GLdouble</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream4dvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="4">const <ptype>GLdouble</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream4fATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>z</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream4fvATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream4iATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>z</name></param>
+            <param><ptype>GLint</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream4ivATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream4sATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param><ptype>GLshort</ptype> <name>x</name></param>
+            <param><ptype>GLshort</ptype> <name>y</name></param>
+            <param><ptype>GLshort</ptype> <name>z</name></param>
+            <param><ptype>GLshort</ptype> <name>w</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexStream4svATI</name></proto>
+            <param group="VertexStreamATI"><ptype>GLenum</ptype> <name>stream</name></param>
+            <param len="4">const <ptype>GLshort</ptype> *<name>coords</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexWeightPointerEXT</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="VertexWeightPointerTypeEXT"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexWeightfEXT</name></proto>
+            <param><ptype>GLfloat</ptype> <name>weight</name></param>
+            <vecequiv name="glVertexWeightfvEXT"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexWeightfvEXT</name></proto>
+            <param len="1">const <ptype>GLfloat</ptype> *<name>weight</name></param>
+            <glx type="render" opcode="4135"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexWeighthNV</name></proto>
+            <param group="Half16NV"><ptype>GLhalfNV</ptype> <name>weight</name></param>
+            <vecequiv name="glVertexWeighthvNV"/>
+        </command>
+        <command>
+            <proto>void <name>glVertexWeighthvNV</name></proto>
+            <param group="Half16NV" len="1">const <ptype>GLhalfNV</ptype> *<name>weight</name></param>
+            <glx type="render" opcode="4256"/>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glVideoCaptureNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLuint</ptype> *<name>sequence_num</name></param>
+            <param><ptype>GLuint64EXT</ptype> *<name>capture_time</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVideoCaptureStreamParameterdvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVideoCaptureStreamParameterfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVideoCaptureStreamParameterivNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>video_capture_slot</name></param>
+            <param><ptype>GLuint</ptype> <name>stream</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glViewport</name></proto>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <glx type="render" opcode="191"/>
+        </command>
+        <command>
+            <proto>void <name>glViewportArrayv</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glViewportArrayvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glViewportArrayv"/>
+        </command>
+        <command>
+            <proto>void <name>glViewportArrayvOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glViewportArrayv"/>
+        </command>
+        <command>
+            <proto>void <name>glViewportIndexedf</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <param><ptype>GLfloat</ptype> <name>h</name></param>
+        </command>
+        <command>
+            <proto>void <name>glViewportIndexedfOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <param><ptype>GLfloat</ptype> <name>h</name></param>
+            <alias name="glViewportIndexedf"/>
+        </command>
+        <command>
+            <proto>void <name>glViewportIndexedfNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <param><ptype>GLfloat</ptype> <name>h</name></param>
+            <alias name="glViewportIndexedf"/>
+        </command>
+        <command>
+            <proto>void <name>glViewportIndexedfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glViewportIndexedfvOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glViewportIndexedfv"/>
+        </command>
+        <command>
+            <proto>void <name>glViewportIndexedfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glViewportIndexedfv"/>
+        </command>
+        <command>
+            <proto>void <name>glViewportPositionWScaleNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>xcoeff</name></param>
+            <param><ptype>GLfloat</ptype> <name>ycoeff</name></param>
+        </command>
+        <command>
+            <proto>void <name>glViewportSwizzleNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>swizzlex</name></param>
+            <param><ptype>GLenum</ptype> <name>swizzley</name></param>
+            <param><ptype>GLenum</ptype> <name>swizzlez</name></param>
+            <param><ptype>GLenum</ptype> <name>swizzlew</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWaitSync</name></proto>
+            <param group="sync"><ptype>GLsync</ptype> <name>sync</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+            <param><ptype>GLuint64</ptype> <name>timeout</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWaitSyncAPPLE</name></proto>
+            <param><ptype>GLsync</ptype> <name>sync</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+            <param><ptype>GLuint64</ptype> <name>timeout</name></param>
+            <alias name="glWaitSync"/>
+        </command>
+        <command>
+            <proto>void <name>glWeightPathsNV</name></proto>
+            <param group="Path"><ptype>GLuint</ptype> <name>resultPath</name></param>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param group="Path" len="numPaths">const <ptype>GLuint</ptype> *<name>paths</name></param>
+            <param len="numPaths">const <ptype>GLfloat</ptype> *<name>weights</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWeightPointerARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param group="WeightPointerTypeARB"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWeightPointerOES</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param len="COMPSIZE(type,stride)">const void *<name>pointer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWeightbvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLbyte</ptype> *<name>weights</name></param>
+            <glx type="render" opcode="220"/>
+        </command>
+        <command>
+            <proto>void <name>glWeightdvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLdouble</ptype> *<name>weights</name></param>
+            <glx type="render" opcode="228"/>
+        </command>
+        <command>
+            <proto>void <name>glWeightfvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLfloat</ptype> *<name>weights</name></param>
+            <glx type="render" opcode="227"/>
+        </command>
+        <command>
+            <proto>void <name>glWeightivARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLint</ptype> *<name>weights</name></param>
+            <glx type="render" opcode="224"/>
+        </command>
+        <command>
+            <proto>void <name>glWeightsvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLshort</ptype> *<name>weights</name></param>
+            <glx type="render" opcode="222"/>
+        </command>
+        <command>
+            <proto>void <name>glWeightubvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLubyte</ptype> *<name>weights</name></param>
+            <glx type="render" opcode="221"/>
+        </command>
+        <command>
+            <proto>void <name>glWeightuivARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLuint</ptype> *<name>weights</name></param>
+            <glx type="render" opcode="225"/>
+        </command>
+        <command>
+            <proto>void <name>glWeightusvARB</name></proto>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param len="size">const <ptype>GLushort</ptype> *<name>weights</name></param>
+            <glx type="render" opcode="223"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <vecequiv name="glWindowPos2dv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2dARB</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <alias name="glWindowPos2d"/>
+            <vecequiv name="glWindowPos2dvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2dMESA</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <alias name="glWindowPos2d"/>
+            <vecequiv name="glWindowPos2dvMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2dv</name></proto>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2dvARB</name></proto>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glWindowPos2dv"/>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2dvMESA</name></proto>
+            <param group="CoordD" len="2">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glWindowPos2dv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <vecequiv name="glWindowPos2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2fARB</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <alias name="glWindowPos2f"/>
+            <vecequiv name="glWindowPos2fvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2fMESA</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <alias name="glWindowPos2f"/>
+            <vecequiv name="glWindowPos2fvMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2fv</name></proto>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2fvARB</name></proto>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glWindowPos2fv"/>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2fvMESA</name></proto>
+            <param group="CoordF" len="2">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glWindowPos2fv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <vecequiv name="glWindowPos2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2iARB</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <alias name="glWindowPos2i"/>
+            <vecequiv name="glWindowPos2ivARB"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2iMESA</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <alias name="glWindowPos2i"/>
+            <vecequiv name="glWindowPos2ivMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2iv</name></proto>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2ivARB</name></proto>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glWindowPos2iv"/>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2ivMESA</name></proto>
+            <param group="CoordI" len="2">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glWindowPos2iv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <vecequiv name="glWindowPos2sv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2sARB</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <alias name="glWindowPos2s"/>
+            <vecequiv name="glWindowPos2svARB"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2sMESA</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <alias name="glWindowPos2s"/>
+            <vecequiv name="glWindowPos2svMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2sv</name></proto>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2svARB</name></proto>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glWindowPos2sv"/>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos2svMESA</name></proto>
+            <param group="CoordS" len="2">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glWindowPos2sv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3d</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>z</name></param>
+            <vecequiv name="glWindowPos3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3dARB</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>z</name></param>
+            <alias name="glWindowPos3d"/>
+            <vecequiv name="glWindowPos3dvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3dMESA</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>z</name></param>
+            <alias name="glWindowPos3d"/>
+            <vecequiv name="glWindowPos3dvMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3dv</name></proto>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3dvARB</name></proto>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glWindowPos3dv"/>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3dvMESA</name></proto>
+            <param group="CoordD" len="3">const <ptype>GLdouble</ptype> *<name>v</name></param>
+            <alias name="glWindowPos3dv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3f</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>z</name></param>
+            <vecequiv name="glWindowPos3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3fARB</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>z</name></param>
+            <alias name="glWindowPos3f"/>
+            <vecequiv name="glWindowPos3fvARB"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3fMESA</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>z</name></param>
+            <alias name="glWindowPos3f"/>
+            <vecequiv name="glWindowPos3fvMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3fv</name></proto>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3fvARB</name></proto>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glWindowPos3fv"/>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3fvMESA</name></proto>
+            <param group="CoordF" len="3">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glWindowPos3fv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3i</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>z</name></param>
+            <vecequiv name="glWindowPos3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3iARB</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>z</name></param>
+            <alias name="glWindowPos3i"/>
+            <vecequiv name="glWindowPos3ivARB"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3iMESA</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>z</name></param>
+            <alias name="glWindowPos3i"/>
+            <vecequiv name="glWindowPos3ivMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3iv</name></proto>
+            <param group="CoordI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3ivARB</name></proto>
+            <param group="CoordI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glWindowPos3iv"/>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3ivMESA</name></proto>
+            <param group="CoordI" len="3">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glWindowPos3iv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3s</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>z</name></param>
+            <vecequiv name="glWindowPos3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3sARB</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>z</name></param>
+            <alias name="glWindowPos3s"/>
+            <vecequiv name="glWindowPos3svARB"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3sMESA</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>z</name></param>
+            <alias name="glWindowPos3s"/>
+            <vecequiv name="glWindowPos3svMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3sv</name></proto>
+            <param group="CoordS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3svARB</name></proto>
+            <param group="CoordS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glWindowPos3sv"/>
+            <glx type="render" opcode="230"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos3svMESA</name></proto>
+            <param group="CoordS" len="3">const <ptype>GLshort</ptype> *<name>v</name></param>
+            <alias name="glWindowPos3sv"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos4dMESA</name></proto>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>x</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>y</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>z</name></param>
+            <param group="CoordD"><ptype>GLdouble</ptype> <name>w</name></param>
+            <vecequiv name="glWindowPos4dvMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos4dvMESA</name></proto>
+            <param group="CoordD" len="4">const <ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos4fMESA</name></proto>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>x</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>y</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>z</name></param>
+            <param group="CoordF"><ptype>GLfloat</ptype> <name>w</name></param>
+            <vecequiv name="glWindowPos4fvMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos4fvMESA</name></proto>
+            <param group="CoordF" len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos4iMESA</name></proto>
+            <param group="CoordI"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>y</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>z</name></param>
+            <param group="CoordI"><ptype>GLint</ptype> <name>w</name></param>
+            <vecequiv name="glWindowPos4ivMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos4ivMESA</name></proto>
+            <param group="CoordI" len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos4sMESA</name></proto>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>x</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>y</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>z</name></param>
+            <param group="CoordS"><ptype>GLshort</ptype> <name>w</name></param>
+            <vecequiv name="glWindowPos4svMESA"/>
+        </command>
+        <command>
+            <proto>void <name>glWindowPos4svMESA</name></proto>
+            <param group="CoordS" len="4">const <ptype>GLshort</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWindowRectanglesEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLint</ptype> *<name>box</name></param>
+        </command>
+        <command>
+            <proto>void <name>glWriteMaskEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>res</name></param>
+            <param><ptype>GLuint</ptype> <name>in</name></param>
+            <param group="VertexShaderWriteMaskEXT"><ptype>GLenum</ptype> <name>outX</name></param>
+            <param group="VertexShaderWriteMaskEXT"><ptype>GLenum</ptype> <name>outY</name></param>
+            <param group="VertexShaderWriteMaskEXT"><ptype>GLenum</ptype> <name>outZ</name></param>
+            <param group="VertexShaderWriteMaskEXT"><ptype>GLenum</ptype> <name>outW</name></param>
+        </command>
+
+    </commands>
+
+    <!-- SECTION: GL API interface definitions. -->
+    <feature api="gl" name="GL_VERSION_1_0" number="1.0">
+        <require>
+            <type name="GLvoid" comment="No longer used in headers"/>
+            <command name="glCullFace"/>
+            <command name="glFrontFace"/>
+            <command name="glHint"/>
+            <command name="glLineWidth"/>
+            <command name="glPointSize"/>
+            <command name="glPolygonMode"/>
+            <command name="glScissor"/>
+            <command name="glTexParameterf"/>
+            <command name="glTexParameterfv"/>
+            <command name="glTexParameteri"/>
+            <command name="glTexParameteriv"/>
+            <command name="glTexImage1D"/>
+            <command name="glTexImage2D"/>
+            <command name="glDrawBuffer"/>
+            <command name="glClear"/>
+            <command name="glClearColor"/>
+            <command name="glClearStencil"/>
+            <command name="glClearDepth"/>
+            <command name="glStencilMask"/>
+            <command name="glColorMask"/>
+            <command name="glDepthMask"/>
+            <command name="glDisable"/>
+            <command name="glEnable"/>
+            <command name="glFinish"/>
+            <command name="glFlush"/>
+            <command name="glBlendFunc"/>
+            <command name="glLogicOp"/>
+            <command name="glStencilFunc"/>
+            <command name="glStencilOp"/>
+            <command name="glDepthFunc"/>
+            <command name="glPixelStoref"/>
+            <command name="glPixelStorei"/>
+            <command name="glReadBuffer"/>
+            <command name="glReadPixels"/>
+            <command name="glGetBooleanv"/>
+            <command name="glGetDoublev"/>
+            <command name="glGetError"/>
+            <command name="glGetFloatv"/>
+            <command name="glGetIntegerv"/>
+            <command name="glGetString"/>
+            <command name="glGetTexImage"/>
+            <command name="glGetTexParameterfv"/>
+            <command name="glGetTexParameteriv"/>
+            <command name="glGetTexLevelParameterfv"/>
+            <command name="glGetTexLevelParameteriv"/>
+            <command name="glIsEnabled"/>
+            <command name="glDepthRange"/>
+            <command name="glViewport"/>
+            <command name="glNewList"/>
+            <command name="glEndList"/>
+            <command name="glCallList"/>
+            <command name="glCallLists"/>
+            <command name="glDeleteLists"/>
+            <command name="glGenLists"/>
+            <command name="glListBase"/>
+            <command name="glBegin"/>
+            <command name="glBitmap"/>
+            <command name="glColor3b"/>
+            <command name="glColor3bv"/>
+            <command name="glColor3d"/>
+            <command name="glColor3dv"/>
+            <command name="glColor3f"/>
+            <command name="glColor3fv"/>
+            <command name="glColor3i"/>
+            <command name="glColor3iv"/>
+            <command name="glColor3s"/>
+            <command name="glColor3sv"/>
+            <command name="glColor3ub"/>
+            <command name="glColor3ubv"/>
+            <command name="glColor3ui"/>
+            <command name="glColor3uiv"/>
+            <command name="glColor3us"/>
+            <command name="glColor3usv"/>
+            <command name="glColor4b"/>
+            <command name="glColor4bv"/>
+            <command name="glColor4d"/>
+            <command name="glColor4dv"/>
+            <command name="glColor4f"/>
+            <command name="glColor4fv"/>
+            <command name="glColor4i"/>
+            <command name="glColor4iv"/>
+            <command name="glColor4s"/>
+            <command name="glColor4sv"/>
+            <command name="glColor4ub"/>
+            <command name="glColor4ubv"/>
+            <command name="glColor4ui"/>
+            <command name="glColor4uiv"/>
+            <command name="glColor4us"/>
+            <command name="glColor4usv"/>
+            <command name="glEdgeFlag"/>
+            <command name="glEdgeFlagv"/>
+            <command name="glEnd"/>
+            <command name="glIndexd"/>
+            <command name="glIndexdv"/>
+            <command name="glIndexf"/>
+            <command name="glIndexfv"/>
+            <command name="glIndexi"/>
+            <command name="glIndexiv"/>
+            <command name="glIndexs"/>
+            <command name="glIndexsv"/>
+            <command name="glNormal3b"/>
+            <command name="glNormal3bv"/>
+            <command name="glNormal3d"/>
+            <command name="glNormal3dv"/>
+            <command name="glNormal3f"/>
+            <command name="glNormal3fv"/>
+            <command name="glNormal3i"/>
+            <command name="glNormal3iv"/>
+            <command name="glNormal3s"/>
+            <command name="glNormal3sv"/>
+            <command name="glRasterPos2d"/>
+            <command name="glRasterPos2dv"/>
+            <command name="glRasterPos2f"/>
+            <command name="glRasterPos2fv"/>
+            <command name="glRasterPos2i"/>
+            <command name="glRasterPos2iv"/>
+            <command name="glRasterPos2s"/>
+            <command name="glRasterPos2sv"/>
+            <command name="glRasterPos3d"/>
+            <command name="glRasterPos3dv"/>
+            <command name="glRasterPos3f"/>
+            <command name="glRasterPos3fv"/>
+            <command name="glRasterPos3i"/>
+            <command name="glRasterPos3iv"/>
+            <command name="glRasterPos3s"/>
+            <command name="glRasterPos3sv"/>
+            <command name="glRasterPos4d"/>
+            <command name="glRasterPos4dv"/>
+            <command name="glRasterPos4f"/>
+            <command name="glRasterPos4fv"/>
+            <command name="glRasterPos4i"/>
+            <command name="glRasterPos4iv"/>
+            <command name="glRasterPos4s"/>
+            <command name="glRasterPos4sv"/>
+            <command name="glRectd"/>
+            <command name="glRectdv"/>
+            <command name="glRectf"/>
+            <command name="glRectfv"/>
+            <command name="glRecti"/>
+            <command name="glRectiv"/>
+            <command name="glRects"/>
+            <command name="glRectsv"/>
+            <command name="glTexCoord1d"/>
+            <command name="glTexCoord1dv"/>
+            <command name="glTexCoord1f"/>
+            <command name="glTexCoord1fv"/>
+            <command name="glTexCoord1i"/>
+            <command name="glTexCoord1iv"/>
+            <command name="glTexCoord1s"/>
+            <command name="glTexCoord1sv"/>
+            <command name="glTexCoord2d"/>
+            <command name="glTexCoord2dv"/>
+            <command name="glTexCoord2f"/>
+            <command name="glTexCoord2fv"/>
+            <command name="glTexCoord2i"/>
+            <command name="glTexCoord2iv"/>
+            <command name="glTexCoord2s"/>
+            <command name="glTexCoord2sv"/>
+            <command name="glTexCoord3d"/>
+            <command name="glTexCoord3dv"/>
+            <command name="glTexCoord3f"/>
+            <command name="glTexCoord3fv"/>
+            <command name="glTexCoord3i"/>
+            <command name="glTexCoord3iv"/>
+            <command name="glTexCoord3s"/>
+            <command name="glTexCoord3sv"/>
+            <command name="glTexCoord4d"/>
+            <command name="glTexCoord4dv"/>
+            <command name="glTexCoord4f"/>
+            <command name="glTexCoord4fv"/>
+            <command name="glTexCoord4i"/>
+            <command name="glTexCoord4iv"/>
+            <command name="glTexCoord4s"/>
+            <command name="glTexCoord4sv"/>
+            <command name="glVertex2d"/>
+            <command name="glVertex2dv"/>
+            <command name="glVertex2f"/>
+            <command name="glVertex2fv"/>
+            <command name="glVertex2i"/>
+            <command name="glVertex2iv"/>
+            <command name="glVertex2s"/>
+            <command name="glVertex2sv"/>
+            <command name="glVertex3d"/>
+            <command name="glVertex3dv"/>
+            <command name="glVertex3f"/>
+            <command name="glVertex3fv"/>
+            <command name="glVertex3i"/>
+            <command name="glVertex3iv"/>
+            <command name="glVertex3s"/>
+            <command name="glVertex3sv"/>
+            <command name="glVertex4d"/>
+            <command name="glVertex4dv"/>
+            <command name="glVertex4f"/>
+            <command name="glVertex4fv"/>
+            <command name="glVertex4i"/>
+            <command name="glVertex4iv"/>
+            <command name="glVertex4s"/>
+            <command name="glVertex4sv"/>
+            <command name="glClipPlane"/>
+            <command name="glColorMaterial"/>
+            <command name="glFogf"/>
+            <command name="glFogfv"/>
+            <command name="glFogi"/>
+            <command name="glFogiv"/>
+            <command name="glLightf"/>
+            <command name="glLightfv"/>
+            <command name="glLighti"/>
+            <command name="glLightiv"/>
+            <command name="glLightModelf"/>
+            <command name="glLightModelfv"/>
+            <command name="glLightModeli"/>
+            <command name="glLightModeliv"/>
+            <command name="glLineStipple"/>
+            <command name="glMaterialf"/>
+            <command name="glMaterialfv"/>
+            <command name="glMateriali"/>
+            <command name="glMaterialiv"/>
+            <command name="glPolygonStipple"/>
+            <command name="glShadeModel"/>
+            <command name="glTexEnvf"/>
+            <command name="glTexEnvfv"/>
+            <command name="glTexEnvi"/>
+            <command name="glTexEnviv"/>
+            <command name="glTexGend"/>
+            <command name="glTexGendv"/>
+            <command name="glTexGenf"/>
+            <command name="glTexGenfv"/>
+            <command name="glTexGeni"/>
+            <command name="glTexGeniv"/>
+            <command name="glFeedbackBuffer"/>
+            <command name="glSelectBuffer"/>
+            <command name="glRenderMode"/>
+            <command name="glInitNames"/>
+            <command name="glLoadName"/>
+            <command name="glPassThrough"/>
+            <command name="glPopName"/>
+            <command name="glPushName"/>
+            <command name="glClearAccum"/>
+            <command name="glClearIndex"/>
+            <command name="glIndexMask"/>
+            <command name="glAccum"/>
+            <command name="glPopAttrib"/>
+            <command name="glPushAttrib"/>
+            <command name="glMap1d"/>
+            <command name="glMap1f"/>
+            <command name="glMap2d"/>
+            <command name="glMap2f"/>
+            <command name="glMapGrid1d"/>
+            <command name="glMapGrid1f"/>
+            <command name="glMapGrid2d"/>
+            <command name="glMapGrid2f"/>
+            <command name="glEvalCoord1d"/>
+            <command name="glEvalCoord1dv"/>
+            <command name="glEvalCoord1f"/>
+            <command name="glEvalCoord1fv"/>
+            <command name="glEvalCoord2d"/>
+            <command name="glEvalCoord2dv"/>
+            <command name="glEvalCoord2f"/>
+            <command name="glEvalCoord2fv"/>
+            <command name="glEvalMesh1"/>
+            <command name="glEvalPoint1"/>
+            <command name="glEvalMesh2"/>
+            <command name="glEvalPoint2"/>
+            <command name="glAlphaFunc"/>
+            <command name="glPixelZoom"/>
+            <command name="glPixelTransferf"/>
+            <command name="glPixelTransferi"/>
+            <command name="glPixelMapfv"/>
+            <command name="glPixelMapuiv"/>
+            <command name="glPixelMapusv"/>
+            <command name="glCopyPixels"/>
+            <command name="glDrawPixels"/>
+            <command name="glGetClipPlane"/>
+            <command name="glGetLightfv"/>
+            <command name="glGetLightiv"/>
+            <command name="glGetMapdv"/>
+            <command name="glGetMapfv"/>
+            <command name="glGetMapiv"/>
+            <command name="glGetMaterialfv"/>
+            <command name="glGetMaterialiv"/>
+            <command name="glGetPixelMapfv"/>
+            <command name="glGetPixelMapuiv"/>
+            <command name="glGetPixelMapusv"/>
+            <command name="glGetPolygonStipple"/>
+            <command name="glGetTexEnvfv"/>
+            <command name="glGetTexEnviv"/>
+            <command name="glGetTexGendv"/>
+            <command name="glGetTexGenfv"/>
+            <command name="glGetTexGeniv"/>
+            <command name="glIsList"/>
+            <command name="glFrustum"/>
+            <command name="glLoadIdentity"/>
+            <command name="glLoadMatrixf"/>
+            <command name="glLoadMatrixd"/>
+            <command name="glMatrixMode"/>
+            <command name="glMultMatrixf"/>
+            <command name="glMultMatrixd"/>
+            <command name="glOrtho"/>
+            <command name="glPopMatrix"/>
+            <command name="glPushMatrix"/>
+            <command name="glRotated"/>
+            <command name="glRotatef"/>
+            <command name="glScaled"/>
+            <command name="glScalef"/>
+            <command name="glTranslated"/>
+            <command name="glTranslatef"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_1_1" number="1.1">
+        <require>
+            <type name="GLclampf" comment="No longer used in GL 1.1, but still defined in Mesa gl.h"/>
+            <type name="GLclampd" comment="No longer used in GL 1.1, but still defined in Mesa gl.h"/>
+            <!-- Many of these are really VERSION_1_0 enums -->
+            <enum name="GL_DEPTH_BUFFER_BIT"/>
+            <enum name="GL_STENCIL_BUFFER_BIT"/>
+            <enum name="GL_COLOR_BUFFER_BIT"/>
+            <enum name="GL_FALSE"/>
+            <enum name="GL_TRUE"/>
+            <enum name="GL_POINTS"/>
+            <enum name="GL_LINES"/>
+            <enum name="GL_LINE_LOOP"/>
+            <enum name="GL_LINE_STRIP"/>
+            <enum name="GL_TRIANGLES"/>
+            <enum name="GL_TRIANGLE_STRIP"/>
+            <enum name="GL_TRIANGLE_FAN"/>
+            <enum name="GL_QUADS"/>
+            <enum name="GL_NEVER"/>
+            <enum name="GL_LESS"/>
+            <enum name="GL_EQUAL"/>
+            <enum name="GL_LEQUAL"/>
+            <enum name="GL_GREATER"/>
+            <enum name="GL_NOTEQUAL"/>
+            <enum name="GL_GEQUAL"/>
+            <enum name="GL_ALWAYS"/>
+            <enum name="GL_ZERO"/>
+            <enum name="GL_ONE"/>
+            <enum name="GL_SRC_COLOR"/>
+            <enum name="GL_ONE_MINUS_SRC_COLOR"/>
+            <enum name="GL_SRC_ALPHA"/>
+            <enum name="GL_ONE_MINUS_SRC_ALPHA"/>
+            <enum name="GL_DST_ALPHA"/>
+            <enum name="GL_ONE_MINUS_DST_ALPHA"/>
+            <enum name="GL_DST_COLOR"/>
+            <enum name="GL_ONE_MINUS_DST_COLOR"/>
+            <enum name="GL_SRC_ALPHA_SATURATE"/>
+            <enum name="GL_NONE"/>
+            <enum name="GL_FRONT_LEFT"/>
+            <enum name="GL_FRONT_RIGHT"/>
+            <enum name="GL_BACK_LEFT"/>
+            <enum name="GL_BACK_RIGHT"/>
+            <enum name="GL_FRONT"/>
+            <enum name="GL_BACK"/>
+            <enum name="GL_LEFT"/>
+            <enum name="GL_RIGHT"/>
+            <enum name="GL_FRONT_AND_BACK"/>
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_INVALID_ENUM"/>
+            <enum name="GL_INVALID_VALUE"/>
+            <enum name="GL_INVALID_OPERATION"/>
+            <enum name="GL_OUT_OF_MEMORY"/>
+            <enum name="GL_CW"/>
+            <enum name="GL_CCW"/>
+            <enum name="GL_POINT_SIZE"/>
+            <enum name="GL_POINT_SIZE_RANGE"/>
+            <enum name="GL_POINT_SIZE_GRANULARITY"/>
+            <enum name="GL_LINE_SMOOTH"/>
+            <enum name="GL_LINE_WIDTH"/>
+            <enum name="GL_LINE_WIDTH_RANGE"/>
+            <enum name="GL_LINE_WIDTH_GRANULARITY"/>
+            <enum name="GL_POLYGON_MODE"/>
+            <enum name="GL_POLYGON_SMOOTH"/>
+            <enum name="GL_CULL_FACE"/>
+            <enum name="GL_CULL_FACE_MODE"/>
+            <enum name="GL_FRONT_FACE"/>
+            <enum name="GL_DEPTH_RANGE"/>
+            <enum name="GL_DEPTH_TEST"/>
+            <enum name="GL_DEPTH_WRITEMASK"/>
+            <enum name="GL_DEPTH_CLEAR_VALUE"/>
+            <enum name="GL_DEPTH_FUNC"/>
+            <enum name="GL_STENCIL_TEST"/>
+            <enum name="GL_STENCIL_CLEAR_VALUE"/>
+            <enum name="GL_STENCIL_FUNC"/>
+            <enum name="GL_STENCIL_VALUE_MASK"/>
+            <enum name="GL_STENCIL_FAIL"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_FAIL"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_PASS"/>
+            <enum name="GL_STENCIL_REF"/>
+            <enum name="GL_STENCIL_WRITEMASK"/>
+            <enum name="GL_VIEWPORT"/>
+            <enum name="GL_DITHER"/>
+            <enum name="GL_BLEND_DST"/>
+            <enum name="GL_BLEND_SRC"/>
+            <enum name="GL_BLEND"/>
+            <enum name="GL_LOGIC_OP_MODE"/>
+            <enum name="GL_COLOR_LOGIC_OP"/>
+            <enum name="GL_DRAW_BUFFER"/>
+            <enum name="GL_READ_BUFFER"/>
+            <enum name="GL_SCISSOR_BOX"/>
+            <enum name="GL_SCISSOR_TEST"/>
+            <enum name="GL_COLOR_CLEAR_VALUE"/>
+            <enum name="GL_COLOR_WRITEMASK"/>
+            <enum name="GL_DOUBLEBUFFER"/>
+            <enum name="GL_STEREO"/>
+            <enum name="GL_LINE_SMOOTH_HINT"/>
+            <enum name="GL_POLYGON_SMOOTH_HINT"/>
+            <enum name="GL_UNPACK_SWAP_BYTES"/>
+            <enum name="GL_UNPACK_LSB_FIRST"/>
+            <enum name="GL_UNPACK_ROW_LENGTH"/>
+            <enum name="GL_UNPACK_SKIP_ROWS"/>
+            <enum name="GL_UNPACK_SKIP_PIXELS"/>
+            <enum name="GL_UNPACK_ALIGNMENT"/>
+            <enum name="GL_PACK_SWAP_BYTES"/>
+            <enum name="GL_PACK_LSB_FIRST"/>
+            <enum name="GL_PACK_ROW_LENGTH"/>
+            <enum name="GL_PACK_SKIP_ROWS"/>
+            <enum name="GL_PACK_SKIP_PIXELS"/>
+            <enum name="GL_PACK_ALIGNMENT"/>
+            <enum name="GL_MAX_TEXTURE_SIZE"/>
+            <enum name="GL_MAX_VIEWPORT_DIMS"/>
+            <enum name="GL_SUBPIXEL_BITS"/>
+            <enum name="GL_TEXTURE_1D"/>
+            <enum name="GL_TEXTURE_2D"/>
+            <enum name="GL_POLYGON_OFFSET_UNITS"/>
+            <enum name="GL_POLYGON_OFFSET_POINT"/>
+            <enum name="GL_POLYGON_OFFSET_LINE"/>
+            <enum name="GL_POLYGON_OFFSET_FILL"/>
+            <enum name="GL_POLYGON_OFFSET_FACTOR"/>
+            <enum name="GL_TEXTURE_BINDING_1D"/>
+            <enum name="GL_TEXTURE_BINDING_2D"/>
+            <enum name="GL_TEXTURE_WIDTH"/>
+            <enum name="GL_TEXTURE_HEIGHT"/>
+            <enum name="GL_TEXTURE_INTERNAL_FORMAT"/>
+            <enum name="GL_TEXTURE_BORDER_COLOR"/>
+            <enum name="GL_TEXTURE_RED_SIZE"/>
+            <enum name="GL_TEXTURE_GREEN_SIZE"/>
+            <enum name="GL_TEXTURE_BLUE_SIZE"/>
+            <enum name="GL_TEXTURE_ALPHA_SIZE"/>
+            <enum name="GL_DONT_CARE"/>
+            <enum name="GL_FASTEST"/>
+            <enum name="GL_NICEST"/>
+            <enum name="GL_BYTE"/>
+            <enum name="GL_UNSIGNED_BYTE"/>
+            <enum name="GL_SHORT"/>
+            <enum name="GL_UNSIGNED_SHORT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_UNSIGNED_INT"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_DOUBLE"/>
+            <enum name="GL_STACK_OVERFLOW"/>
+            <enum name="GL_STACK_UNDERFLOW"/>
+            <enum name="GL_CLEAR"/>
+            <enum name="GL_AND"/>
+            <enum name="GL_AND_REVERSE"/>
+            <enum name="GL_COPY"/>
+            <enum name="GL_AND_INVERTED"/>
+            <enum name="GL_NOOP"/>
+            <enum name="GL_XOR"/>
+            <enum name="GL_OR"/>
+            <enum name="GL_NOR"/>
+            <enum name="GL_EQUIV"/>
+            <enum name="GL_INVERT"/>
+            <enum name="GL_OR_REVERSE"/>
+            <enum name="GL_COPY_INVERTED"/>
+            <enum name="GL_OR_INVERTED"/>
+            <enum name="GL_NAND"/>
+            <enum name="GL_SET"/>
+            <enum name="GL_TEXTURE"/>
+            <enum name="GL_COLOR"/>
+            <enum name="GL_DEPTH"/>
+            <enum name="GL_STENCIL"/>
+            <enum name="GL_STENCIL_INDEX"/>
+            <enum name="GL_DEPTH_COMPONENT"/>
+            <enum name="GL_RED"/>
+            <enum name="GL_GREEN"/>
+            <enum name="GL_BLUE"/>
+            <enum name="GL_ALPHA"/>
+            <enum name="GL_RGB"/>
+            <enum name="GL_RGBA"/>
+            <enum name="GL_POINT"/>
+            <enum name="GL_LINE"/>
+            <enum name="GL_FILL"/>
+            <enum name="GL_KEEP"/>
+            <enum name="GL_REPLACE"/>
+            <enum name="GL_INCR"/>
+            <enum name="GL_DECR"/>
+            <enum name="GL_VENDOR"/>
+            <enum name="GL_RENDERER"/>
+            <enum name="GL_VERSION"/>
+            <enum name="GL_EXTENSIONS"/>
+            <enum name="GL_NEAREST"/>
+            <enum name="GL_LINEAR"/>
+            <enum name="GL_NEAREST_MIPMAP_NEAREST"/>
+            <enum name="GL_LINEAR_MIPMAP_NEAREST"/>
+            <enum name="GL_NEAREST_MIPMAP_LINEAR"/>
+            <enum name="GL_LINEAR_MIPMAP_LINEAR"/>
+            <enum name="GL_TEXTURE_MAG_FILTER"/>
+            <enum name="GL_TEXTURE_MIN_FILTER"/>
+            <enum name="GL_TEXTURE_WRAP_S"/>
+            <enum name="GL_TEXTURE_WRAP_T"/>
+            <enum name="GL_PROXY_TEXTURE_1D"/>
+            <enum name="GL_PROXY_TEXTURE_2D"/>
+            <enum name="GL_REPEAT"/>
+            <enum name="GL_R3_G3_B2"/>
+            <enum name="GL_RGB4"/>
+            <enum name="GL_RGB5"/>
+            <enum name="GL_RGB8"/>
+            <enum name="GL_RGB10"/>
+            <enum name="GL_RGB12"/>
+            <enum name="GL_RGB16"/>
+            <enum name="GL_RGBA2"/>
+            <enum name="GL_RGBA4"/>
+            <enum name="GL_RGB5_A1"/>
+            <enum name="GL_RGBA8"/>
+            <enum name="GL_RGB10_A2"/>
+            <enum name="GL_RGBA12"/>
+            <enum name="GL_RGBA16"/>
+            <enum name="GL_CURRENT_BIT"/>
+            <enum name="GL_POINT_BIT"/>
+            <enum name="GL_LINE_BIT"/>
+            <enum name="GL_POLYGON_BIT"/>
+            <enum name="GL_POLYGON_STIPPLE_BIT"/>
+            <enum name="GL_PIXEL_MODE_BIT"/>
+            <enum name="GL_LIGHTING_BIT"/>
+            <enum name="GL_FOG_BIT"/>
+            <enum name="GL_ACCUM_BUFFER_BIT"/>
+            <enum name="GL_VIEWPORT_BIT"/>
+            <enum name="GL_TRANSFORM_BIT"/>
+            <enum name="GL_ENABLE_BIT"/>
+            <enum name="GL_HINT_BIT"/>
+            <enum name="GL_EVAL_BIT"/>
+            <enum name="GL_LIST_BIT"/>
+            <enum name="GL_TEXTURE_BIT"/>
+            <enum name="GL_SCISSOR_BIT"/>
+            <enum name="GL_ALL_ATTRIB_BITS"/>
+            <enum name="GL_CLIENT_PIXEL_STORE_BIT"/>
+            <enum name="GL_CLIENT_VERTEX_ARRAY_BIT"/>
+            <enum name="GL_CLIENT_ALL_ATTRIB_BITS"/>
+            <enum name="GL_QUAD_STRIP"/>
+            <enum name="GL_POLYGON"/>
+            <enum name="GL_ACCUM"/>
+            <enum name="GL_LOAD"/>
+            <enum name="GL_RETURN"/>
+            <enum name="GL_MULT"/>
+            <enum name="GL_ADD"/>
+            <enum name="GL_AUX0"/>
+            <enum name="GL_AUX1"/>
+            <enum name="GL_AUX2"/>
+            <enum name="GL_AUX3"/>
+            <enum name="GL_2D"/>
+            <enum name="GL_3D"/>
+            <enum name="GL_3D_COLOR"/>
+            <enum name="GL_3D_COLOR_TEXTURE"/>
+            <enum name="GL_4D_COLOR_TEXTURE"/>
+            <enum name="GL_PASS_THROUGH_TOKEN"/>
+            <enum name="GL_POINT_TOKEN"/>
+            <enum name="GL_LINE_TOKEN"/>
+            <enum name="GL_POLYGON_TOKEN"/>
+            <enum name="GL_BITMAP_TOKEN"/>
+            <enum name="GL_DRAW_PIXEL_TOKEN"/>
+            <enum name="GL_COPY_PIXEL_TOKEN"/>
+            <enum name="GL_LINE_RESET_TOKEN"/>
+            <enum name="GL_EXP"/>
+            <enum name="GL_EXP2"/>
+            <enum name="GL_COEFF"/>
+            <enum name="GL_ORDER"/>
+            <enum name="GL_DOMAIN"/>
+            <enum name="GL_PIXEL_MAP_I_TO_I"/>
+            <enum name="GL_PIXEL_MAP_S_TO_S"/>
+            <enum name="GL_PIXEL_MAP_I_TO_R"/>
+            <enum name="GL_PIXEL_MAP_I_TO_G"/>
+            <enum name="GL_PIXEL_MAP_I_TO_B"/>
+            <enum name="GL_PIXEL_MAP_I_TO_A"/>
+            <enum name="GL_PIXEL_MAP_R_TO_R"/>
+            <enum name="GL_PIXEL_MAP_G_TO_G"/>
+            <enum name="GL_PIXEL_MAP_B_TO_B"/>
+            <enum name="GL_PIXEL_MAP_A_TO_A"/>
+            <enum name="GL_VERTEX_ARRAY_POINTER"/>
+            <enum name="GL_NORMAL_ARRAY_POINTER"/>
+            <enum name="GL_COLOR_ARRAY_POINTER"/>
+            <enum name="GL_INDEX_ARRAY_POINTER"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_POINTER"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_POINTER"/>
+            <enum name="GL_FEEDBACK_BUFFER_POINTER"/>
+            <enum name="GL_SELECTION_BUFFER_POINTER"/>
+            <enum name="GL_CURRENT_COLOR"/>
+            <enum name="GL_CURRENT_INDEX"/>
+            <enum name="GL_CURRENT_NORMAL"/>
+            <enum name="GL_CURRENT_TEXTURE_COORDS"/>
+            <enum name="GL_CURRENT_RASTER_COLOR"/>
+            <enum name="GL_CURRENT_RASTER_INDEX"/>
+            <enum name="GL_CURRENT_RASTER_TEXTURE_COORDS"/>
+            <enum name="GL_CURRENT_RASTER_POSITION"/>
+            <enum name="GL_CURRENT_RASTER_POSITION_VALID"/>
+            <enum name="GL_CURRENT_RASTER_DISTANCE"/>
+            <enum name="GL_POINT_SMOOTH"/>
+            <enum name="GL_LINE_STIPPLE"/>
+            <enum name="GL_LINE_STIPPLE_PATTERN"/>
+            <enum name="GL_LINE_STIPPLE_REPEAT"/>
+            <enum name="GL_LIST_MODE"/>
+            <enum name="GL_MAX_LIST_NESTING"/>
+            <enum name="GL_LIST_BASE"/>
+            <enum name="GL_LIST_INDEX"/>
+            <enum name="GL_POLYGON_STIPPLE"/>
+            <enum name="GL_EDGE_FLAG"/>
+            <enum name="GL_LIGHTING"/>
+            <enum name="GL_LIGHT_MODEL_LOCAL_VIEWER"/>
+            <enum name="GL_LIGHT_MODEL_TWO_SIDE"/>
+            <enum name="GL_LIGHT_MODEL_AMBIENT"/>
+            <enum name="GL_SHADE_MODEL"/>
+            <enum name="GL_COLOR_MATERIAL_FACE"/>
+            <enum name="GL_COLOR_MATERIAL_PARAMETER"/>
+            <enum name="GL_COLOR_MATERIAL"/>
+            <enum name="GL_FOG"/>
+            <enum name="GL_FOG_INDEX"/>
+            <enum name="GL_FOG_DENSITY"/>
+            <enum name="GL_FOG_START"/>
+            <enum name="GL_FOG_END"/>
+            <enum name="GL_FOG_MODE"/>
+            <enum name="GL_FOG_COLOR"/>
+            <enum name="GL_ACCUM_CLEAR_VALUE"/>
+            <enum name="GL_MATRIX_MODE"/>
+            <enum name="GL_NORMALIZE"/>
+            <enum name="GL_MODELVIEW_STACK_DEPTH"/>
+            <enum name="GL_PROJECTION_STACK_DEPTH"/>
+            <enum name="GL_TEXTURE_STACK_DEPTH"/>
+            <enum name="GL_MODELVIEW_MATRIX"/>
+            <enum name="GL_PROJECTION_MATRIX"/>
+            <enum name="GL_TEXTURE_MATRIX"/>
+            <enum name="GL_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_CLIENT_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_ALPHA_TEST"/>
+            <enum name="GL_ALPHA_TEST_FUNC"/>
+            <enum name="GL_ALPHA_TEST_REF"/>
+            <enum name="GL_INDEX_LOGIC_OP"/>
+            <enum name="GL_LOGIC_OP"/>
+            <enum name="GL_AUX_BUFFERS"/>
+            <enum name="GL_INDEX_CLEAR_VALUE"/>
+            <enum name="GL_INDEX_WRITEMASK"/>
+            <enum name="GL_INDEX_MODE"/>
+            <enum name="GL_RGBA_MODE"/>
+            <enum name="GL_RENDER_MODE"/>
+            <enum name="GL_PERSPECTIVE_CORRECTION_HINT"/>
+            <enum name="GL_POINT_SMOOTH_HINT"/>
+            <enum name="GL_FOG_HINT"/>
+            <enum name="GL_TEXTURE_GEN_S"/>
+            <enum name="GL_TEXTURE_GEN_T"/>
+            <enum name="GL_TEXTURE_GEN_R"/>
+            <enum name="GL_TEXTURE_GEN_Q"/>
+            <enum name="GL_PIXEL_MAP_I_TO_I_SIZE"/>
+            <enum name="GL_PIXEL_MAP_S_TO_S_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_R_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_G_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_B_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_A_SIZE"/>
+            <enum name="GL_PIXEL_MAP_R_TO_R_SIZE"/>
+            <enum name="GL_PIXEL_MAP_G_TO_G_SIZE"/>
+            <enum name="GL_PIXEL_MAP_B_TO_B_SIZE"/>
+            <enum name="GL_PIXEL_MAP_A_TO_A_SIZE"/>
+            <enum name="GL_MAP_COLOR"/>
+            <enum name="GL_MAP_STENCIL"/>
+            <enum name="GL_INDEX_SHIFT"/>
+            <enum name="GL_INDEX_OFFSET"/>
+            <enum name="GL_RED_SCALE"/>
+            <enum name="GL_RED_BIAS"/>
+            <enum name="GL_ZOOM_X"/>
+            <enum name="GL_ZOOM_Y"/>
+            <enum name="GL_GREEN_SCALE"/>
+            <enum name="GL_GREEN_BIAS"/>
+            <enum name="GL_BLUE_SCALE"/>
+            <enum name="GL_BLUE_BIAS"/>
+            <enum name="GL_ALPHA_SCALE"/>
+            <enum name="GL_ALPHA_BIAS"/>
+            <enum name="GL_DEPTH_SCALE"/>
+            <enum name="GL_DEPTH_BIAS"/>
+            <enum name="GL_MAX_EVAL_ORDER"/>
+            <enum name="GL_MAX_LIGHTS"/>
+            <enum name="GL_MAX_CLIP_PLANES"/>
+            <enum name="GL_MAX_PIXEL_MAP_TABLE"/>
+            <enum name="GL_MAX_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_MAX_MODELVIEW_STACK_DEPTH"/>
+            <enum name="GL_MAX_NAME_STACK_DEPTH"/>
+            <enum name="GL_MAX_PROJECTION_STACK_DEPTH"/>
+            <enum name="GL_MAX_TEXTURE_STACK_DEPTH"/>
+            <enum name="GL_MAX_CLIENT_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_INDEX_BITS"/>
+            <enum name="GL_RED_BITS"/>
+            <enum name="GL_GREEN_BITS"/>
+            <enum name="GL_BLUE_BITS"/>
+            <enum name="GL_ALPHA_BITS"/>
+            <enum name="GL_DEPTH_BITS"/>
+            <enum name="GL_STENCIL_BITS"/>
+            <enum name="GL_ACCUM_RED_BITS"/>
+            <enum name="GL_ACCUM_GREEN_BITS"/>
+            <enum name="GL_ACCUM_BLUE_BITS"/>
+            <enum name="GL_ACCUM_ALPHA_BITS"/>
+            <enum name="GL_NAME_STACK_DEPTH"/>
+            <enum name="GL_AUTO_NORMAL"/>
+            <enum name="GL_MAP1_COLOR_4"/>
+            <enum name="GL_MAP1_INDEX"/>
+            <enum name="GL_MAP1_NORMAL"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP1_VERTEX_3"/>
+            <enum name="GL_MAP1_VERTEX_4"/>
+            <enum name="GL_MAP2_COLOR_4"/>
+            <enum name="GL_MAP2_INDEX"/>
+            <enum name="GL_MAP2_NORMAL"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP2_VERTEX_3"/>
+            <enum name="GL_MAP2_VERTEX_4"/>
+            <enum name="GL_MAP1_GRID_DOMAIN"/>
+            <enum name="GL_MAP1_GRID_SEGMENTS"/>
+            <enum name="GL_MAP2_GRID_DOMAIN"/>
+            <enum name="GL_MAP2_GRID_SEGMENTS"/>
+            <enum name="GL_FEEDBACK_BUFFER_SIZE"/>
+            <enum name="GL_FEEDBACK_BUFFER_TYPE"/>
+            <enum name="GL_SELECTION_BUFFER_SIZE"/>
+            <enum name="GL_VERTEX_ARRAY"/>
+            <enum name="GL_NORMAL_ARRAY"/>
+            <enum name="GL_COLOR_ARRAY"/>
+            <enum name="GL_INDEX_ARRAY"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY"/>
+            <enum name="GL_EDGE_FLAG_ARRAY"/>
+            <enum name="GL_VERTEX_ARRAY_SIZE"/>
+            <enum name="GL_VERTEX_ARRAY_TYPE"/>
+            <enum name="GL_VERTEX_ARRAY_STRIDE"/>
+            <enum name="GL_NORMAL_ARRAY_TYPE"/>
+            <enum name="GL_NORMAL_ARRAY_STRIDE"/>
+            <enum name="GL_COLOR_ARRAY_SIZE"/>
+            <enum name="GL_COLOR_ARRAY_TYPE"/>
+            <enum name="GL_COLOR_ARRAY_STRIDE"/>
+            <enum name="GL_INDEX_ARRAY_TYPE"/>
+            <enum name="GL_INDEX_ARRAY_STRIDE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_SIZE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_TYPE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_STRIDE"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_STRIDE"/>
+            <enum name="GL_TEXTURE_COMPONENTS"/>
+            <enum name="GL_TEXTURE_BORDER"/>
+            <enum name="GL_TEXTURE_LUMINANCE_SIZE"/>
+            <enum name="GL_TEXTURE_INTENSITY_SIZE"/>
+            <enum name="GL_TEXTURE_PRIORITY"/>
+            <enum name="GL_TEXTURE_RESIDENT"/>
+            <enum name="GL_AMBIENT"/>
+            <enum name="GL_DIFFUSE"/>
+            <enum name="GL_SPECULAR"/>
+            <enum name="GL_POSITION"/>
+            <enum name="GL_SPOT_DIRECTION"/>
+            <enum name="GL_SPOT_EXPONENT"/>
+            <enum name="GL_SPOT_CUTOFF"/>
+            <enum name="GL_CONSTANT_ATTENUATION"/>
+            <enum name="GL_LINEAR_ATTENUATION"/>
+            <enum name="GL_QUADRATIC_ATTENUATION"/>
+            <enum name="GL_COMPILE"/>
+            <enum name="GL_COMPILE_AND_EXECUTE"/>
+            <enum name="GL_2_BYTES"/>
+            <enum name="GL_3_BYTES"/>
+            <enum name="GL_4_BYTES"/>
+            <enum name="GL_EMISSION"/>
+            <enum name="GL_SHININESS"/>
+            <enum name="GL_AMBIENT_AND_DIFFUSE"/>
+            <enum name="GL_COLOR_INDEXES"/>
+            <enum name="GL_MODELVIEW"/>
+            <enum name="GL_PROJECTION"/>
+            <enum name="GL_COLOR_INDEX"/>
+            <enum name="GL_LUMINANCE"/>
+            <enum name="GL_LUMINANCE_ALPHA"/>
+            <enum name="GL_BITMAP"/>
+            <enum name="GL_RENDER"/>
+            <enum name="GL_FEEDBACK"/>
+            <enum name="GL_SELECT"/>
+            <enum name="GL_FLAT"/>
+            <enum name="GL_SMOOTH"/>
+            <enum name="GL_S"/>
+            <enum name="GL_T"/>
+            <enum name="GL_R"/>
+            <enum name="GL_Q"/>
+            <enum name="GL_MODULATE"/>
+            <enum name="GL_DECAL"/>
+            <enum name="GL_TEXTURE_ENV_MODE"/>
+            <enum name="GL_TEXTURE_ENV_COLOR"/>
+            <enum name="GL_TEXTURE_ENV"/>
+            <enum name="GL_EYE_LINEAR"/>
+            <enum name="GL_OBJECT_LINEAR"/>
+            <enum name="GL_SPHERE_MAP"/>
+            <enum name="GL_TEXTURE_GEN_MODE"/>
+            <enum name="GL_OBJECT_PLANE"/>
+            <enum name="GL_EYE_PLANE"/>
+            <enum name="GL_CLAMP"/>
+            <enum name="GL_ALPHA4"/>
+            <enum name="GL_ALPHA8"/>
+            <enum name="GL_ALPHA12"/>
+            <enum name="GL_ALPHA16"/>
+            <enum name="GL_LUMINANCE4"/>
+            <enum name="GL_LUMINANCE8"/>
+            <enum name="GL_LUMINANCE12"/>
+            <enum name="GL_LUMINANCE16"/>
+            <enum name="GL_LUMINANCE4_ALPHA4"/>
+            <enum name="GL_LUMINANCE6_ALPHA2"/>
+            <enum name="GL_LUMINANCE8_ALPHA8"/>
+            <enum name="GL_LUMINANCE12_ALPHA4"/>
+            <enum name="GL_LUMINANCE12_ALPHA12"/>
+            <enum name="GL_LUMINANCE16_ALPHA16"/>
+            <enum name="GL_INTENSITY"/>
+            <enum name="GL_INTENSITY4"/>
+            <enum name="GL_INTENSITY8"/>
+            <enum name="GL_INTENSITY12"/>
+            <enum name="GL_INTENSITY16"/>
+            <enum name="GL_V2F"/>
+            <enum name="GL_V3F"/>
+            <enum name="GL_C4UB_V2F"/>
+            <enum name="GL_C4UB_V3F"/>
+            <enum name="GL_C3F_V3F"/>
+            <enum name="GL_N3F_V3F"/>
+            <enum name="GL_C4F_N3F_V3F"/>
+            <enum name="GL_T2F_V3F"/>
+            <enum name="GL_T4F_V4F"/>
+            <enum name="GL_T2F_C4UB_V3F"/>
+            <enum name="GL_T2F_C3F_V3F"/>
+            <enum name="GL_T2F_N3F_V3F"/>
+            <enum name="GL_T2F_C4F_N3F_V3F"/>
+            <enum name="GL_T4F_C4F_N3F_V4F"/>
+            <enum name="GL_CLIP_PLANE0"/>
+            <enum name="GL_CLIP_PLANE1"/>
+            <enum name="GL_CLIP_PLANE2"/>
+            <enum name="GL_CLIP_PLANE3"/>
+            <enum name="GL_CLIP_PLANE4"/>
+            <enum name="GL_CLIP_PLANE5"/>
+            <enum name="GL_LIGHT0"/>
+            <enum name="GL_LIGHT1"/>
+            <enum name="GL_LIGHT2"/>
+            <enum name="GL_LIGHT3"/>
+            <enum name="GL_LIGHT4"/>
+            <enum name="GL_LIGHT5"/>
+            <enum name="GL_LIGHT6"/>
+            <enum name="GL_LIGHT7"/>
+            <command name="glDrawArrays"/>
+            <command name="glDrawElements"/>
+            <command name="glGetPointerv"/>
+            <command name="glPolygonOffset"/>
+            <command name="glCopyTexImage1D"/>
+            <command name="glCopyTexImage2D"/>
+            <command name="glCopyTexSubImage1D"/>
+            <command name="glCopyTexSubImage2D"/>
+            <command name="glTexSubImage1D"/>
+            <command name="glTexSubImage2D"/>
+            <command name="glBindTexture"/>
+            <command name="glDeleteTextures"/>
+            <command name="glGenTextures"/>
+            <command name="glIsTexture"/>
+            <command name="glArrayElement"/>
+            <command name="glColorPointer"/>
+            <command name="glDisableClientState"/>
+            <command name="glEdgeFlagPointer"/>
+            <command name="glEnableClientState"/>
+            <command name="glIndexPointer"/>
+            <command name="glInterleavedArrays"/>
+            <command name="glNormalPointer"/>
+            <command name="glTexCoordPointer"/>
+            <command name="glVertexPointer"/>
+            <command name="glAreTexturesResident"/>
+            <command name="glPrioritizeTextures"/>
+            <command name="glIndexub"/>
+            <command name="glIndexubv"/>
+            <command name="glPopClientAttrib"/>
+            <command name="glPushClientAttrib"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_1_2" number="1.2">
+        <require>
+            <enum name="GL_UNSIGNED_BYTE_3_3_2"/>
+            <enum name="GL_UNSIGNED_SHORT_4_4_4_4"/>
+            <enum name="GL_UNSIGNED_SHORT_5_5_5_1"/>
+            <enum name="GL_UNSIGNED_INT_8_8_8_8"/>
+            <enum name="GL_UNSIGNED_INT_10_10_10_2"/>
+            <enum name="GL_TEXTURE_BINDING_3D"/>
+            <enum name="GL_PACK_SKIP_IMAGES"/>
+            <enum name="GL_PACK_IMAGE_HEIGHT"/>
+            <enum name="GL_UNPACK_SKIP_IMAGES"/>
+            <enum name="GL_UNPACK_IMAGE_HEIGHT"/>
+            <enum name="GL_TEXTURE_3D"/>
+            <enum name="GL_PROXY_TEXTURE_3D"/>
+            <enum name="GL_TEXTURE_DEPTH"/>
+            <enum name="GL_TEXTURE_WRAP_R"/>
+            <enum name="GL_MAX_3D_TEXTURE_SIZE"/>
+            <enum name="GL_UNSIGNED_BYTE_2_3_3_REV"/>
+            <enum name="GL_UNSIGNED_SHORT_5_6_5"/>
+            <enum name="GL_UNSIGNED_SHORT_5_6_5_REV"/>
+            <enum name="GL_UNSIGNED_SHORT_4_4_4_4_REV"/>
+            <enum name="GL_UNSIGNED_SHORT_1_5_5_5_REV"/>
+            <enum name="GL_UNSIGNED_INT_8_8_8_8_REV"/>
+            <enum name="GL_UNSIGNED_INT_2_10_10_10_REV"/>
+            <enum name="GL_BGR"/>
+            <enum name="GL_BGRA"/>
+            <enum name="GL_MAX_ELEMENTS_VERTICES"/>
+            <enum name="GL_MAX_ELEMENTS_INDICES"/>
+            <enum name="GL_CLAMP_TO_EDGE"/>
+            <enum name="GL_TEXTURE_MIN_LOD"/>
+            <enum name="GL_TEXTURE_MAX_LOD"/>
+            <enum name="GL_TEXTURE_BASE_LEVEL"/>
+            <enum name="GL_TEXTURE_MAX_LEVEL"/>
+            <enum name="GL_SMOOTH_POINT_SIZE_RANGE"/>
+            <enum name="GL_SMOOTH_POINT_SIZE_GRANULARITY"/>
+            <enum name="GL_SMOOTH_LINE_WIDTH_RANGE"/>
+            <enum name="GL_SMOOTH_LINE_WIDTH_GRANULARITY"/>
+            <enum name="GL_ALIASED_LINE_WIDTH_RANGE"/>
+            <enum name="GL_RESCALE_NORMAL"/>
+            <enum name="GL_LIGHT_MODEL_COLOR_CONTROL"/>
+            <enum name="GL_SINGLE_COLOR"/>
+            <enum name="GL_SEPARATE_SPECULAR_COLOR"/>
+            <enum name="GL_ALIASED_POINT_SIZE_RANGE"/>
+            <command name="glDrawRangeElements"/>
+            <command name="glTexImage3D"/>
+            <command name="glTexSubImage3D"/>
+            <command name="glCopyTexSubImage3D"/>
+          </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_1_3" number="1.3">
+        <require>
+            <enum name="GL_TEXTURE0"/>
+            <enum name="GL_TEXTURE1"/>
+            <enum name="GL_TEXTURE2"/>
+            <enum name="GL_TEXTURE3"/>
+            <enum name="GL_TEXTURE4"/>
+            <enum name="GL_TEXTURE5"/>
+            <enum name="GL_TEXTURE6"/>
+            <enum name="GL_TEXTURE7"/>
+            <enum name="GL_TEXTURE8"/>
+            <enum name="GL_TEXTURE9"/>
+            <enum name="GL_TEXTURE10"/>
+            <enum name="GL_TEXTURE11"/>
+            <enum name="GL_TEXTURE12"/>
+            <enum name="GL_TEXTURE13"/>
+            <enum name="GL_TEXTURE14"/>
+            <enum name="GL_TEXTURE15"/>
+            <enum name="GL_TEXTURE16"/>
+            <enum name="GL_TEXTURE17"/>
+            <enum name="GL_TEXTURE18"/>
+            <enum name="GL_TEXTURE19"/>
+            <enum name="GL_TEXTURE20"/>
+            <enum name="GL_TEXTURE21"/>
+            <enum name="GL_TEXTURE22"/>
+            <enum name="GL_TEXTURE23"/>
+            <enum name="GL_TEXTURE24"/>
+            <enum name="GL_TEXTURE25"/>
+            <enum name="GL_TEXTURE26"/>
+            <enum name="GL_TEXTURE27"/>
+            <enum name="GL_TEXTURE28"/>
+            <enum name="GL_TEXTURE29"/>
+            <enum name="GL_TEXTURE30"/>
+            <enum name="GL_TEXTURE31"/>
+            <enum name="GL_ACTIVE_TEXTURE"/>
+            <enum name="GL_MULTISAMPLE"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_COVERAGE"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_ONE"/>
+            <enum name="GL_SAMPLE_COVERAGE"/>
+            <enum name="GL_SAMPLE_BUFFERS"/>
+            <enum name="GL_SAMPLES"/>
+            <enum name="GL_SAMPLE_COVERAGE_VALUE"/>
+            <enum name="GL_SAMPLE_COVERAGE_INVERT"/>
+            <enum name="GL_TEXTURE_CUBE_MAP"/>
+            <enum name="GL_TEXTURE_BINDING_CUBE_MAP"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_X"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"/>
+            <enum name="GL_PROXY_TEXTURE_CUBE_MAP"/>
+            <enum name="GL_MAX_CUBE_MAP_TEXTURE_SIZE"/>
+            <enum name="GL_COMPRESSED_RGB"/>
+            <enum name="GL_COMPRESSED_RGBA"/>
+            <enum name="GL_TEXTURE_COMPRESSION_HINT"/>
+            <enum name="GL_TEXTURE_COMPRESSED_IMAGE_SIZE"/>
+            <enum name="GL_TEXTURE_COMPRESSED"/>
+            <enum name="GL_NUM_COMPRESSED_TEXTURE_FORMATS"/>
+            <enum name="GL_COMPRESSED_TEXTURE_FORMATS"/>
+            <enum name="GL_CLAMP_TO_BORDER"/>
+            <enum name="GL_CLIENT_ACTIVE_TEXTURE"/>
+            <enum name="GL_MAX_TEXTURE_UNITS"/>
+            <enum name="GL_TRANSPOSE_MODELVIEW_MATRIX"/>
+            <enum name="GL_TRANSPOSE_PROJECTION_MATRIX"/>
+            <enum name="GL_TRANSPOSE_TEXTURE_MATRIX"/>
+            <enum name="GL_TRANSPOSE_COLOR_MATRIX"/>
+            <enum name="GL_MULTISAMPLE_BIT"/>
+            <enum name="GL_NORMAL_MAP"/>
+            <enum name="GL_REFLECTION_MAP"/>
+            <enum name="GL_COMPRESSED_ALPHA"/>
+            <enum name="GL_COMPRESSED_LUMINANCE"/>
+            <enum name="GL_COMPRESSED_LUMINANCE_ALPHA"/>
+            <enum name="GL_COMPRESSED_INTENSITY"/>
+            <enum name="GL_COMBINE"/>
+            <enum name="GL_COMBINE_RGB"/>
+            <enum name="GL_COMBINE_ALPHA"/>
+            <enum name="GL_SOURCE0_RGB"/>
+            <enum name="GL_SOURCE1_RGB"/>
+            <enum name="GL_SOURCE2_RGB"/>
+            <enum name="GL_SOURCE0_ALPHA"/>
+            <enum name="GL_SOURCE1_ALPHA"/>
+            <enum name="GL_SOURCE2_ALPHA"/>
+            <enum name="GL_OPERAND0_RGB"/>
+            <enum name="GL_OPERAND1_RGB"/>
+            <enum name="GL_OPERAND2_RGB"/>
+            <enum name="GL_OPERAND0_ALPHA"/>
+            <enum name="GL_OPERAND1_ALPHA"/>
+            <enum name="GL_OPERAND2_ALPHA"/>
+            <enum name="GL_RGB_SCALE"/>
+            <enum name="GL_ADD_SIGNED"/>
+            <enum name="GL_INTERPOLATE"/>
+            <enum name="GL_SUBTRACT"/>
+            <enum name="GL_CONSTANT"/>
+            <enum name="GL_PRIMARY_COLOR"/>
+            <enum name="GL_PREVIOUS"/>
+            <enum name="GL_DOT3_RGB"/>
+            <enum name="GL_DOT3_RGBA"/>
+            <command name="glActiveTexture"/>
+            <command name="glSampleCoverage"/>
+            <command name="glCompressedTexImage3D"/>
+            <command name="glCompressedTexImage2D"/>
+            <command name="glCompressedTexImage1D"/>
+            <command name="glCompressedTexSubImage3D"/>
+            <command name="glCompressedTexSubImage2D"/>
+            <command name="glCompressedTexSubImage1D"/>
+            <command name="glGetCompressedTexImage"/>
+            <command name="glClientActiveTexture"/>
+            <command name="glMultiTexCoord1d"/>
+            <command name="glMultiTexCoord1dv"/>
+            <command name="glMultiTexCoord1f"/>
+            <command name="glMultiTexCoord1fv"/>
+            <command name="glMultiTexCoord1i"/>
+            <command name="glMultiTexCoord1iv"/>
+            <command name="glMultiTexCoord1s"/>
+            <command name="glMultiTexCoord1sv"/>
+            <command name="glMultiTexCoord2d"/>
+            <command name="glMultiTexCoord2dv"/>
+            <command name="glMultiTexCoord2f"/>
+            <command name="glMultiTexCoord2fv"/>
+            <command name="glMultiTexCoord2i"/>
+            <command name="glMultiTexCoord2iv"/>
+            <command name="glMultiTexCoord2s"/>
+            <command name="glMultiTexCoord2sv"/>
+            <command name="glMultiTexCoord3d"/>
+            <command name="glMultiTexCoord3dv"/>
+            <command name="glMultiTexCoord3f"/>
+            <command name="glMultiTexCoord3fv"/>
+            <command name="glMultiTexCoord3i"/>
+            <command name="glMultiTexCoord3iv"/>
+            <command name="glMultiTexCoord3s"/>
+            <command name="glMultiTexCoord3sv"/>
+            <command name="glMultiTexCoord4d"/>
+            <command name="glMultiTexCoord4dv"/>
+            <command name="glMultiTexCoord4f"/>
+            <command name="glMultiTexCoord4fv"/>
+            <command name="glMultiTexCoord4i"/>
+            <command name="glMultiTexCoord4iv"/>
+            <command name="glMultiTexCoord4s"/>
+            <command name="glMultiTexCoord4sv"/>
+            <command name="glLoadTransposeMatrixf"/>
+            <command name="glLoadTransposeMatrixd"/>
+            <command name="glMultTransposeMatrixf"/>
+            <command name="glMultTransposeMatrixd"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_1_4" number="1.4">
+        <require>
+            <enum name="GL_BLEND_DST_RGB"/>
+            <enum name="GL_BLEND_SRC_RGB"/>
+            <enum name="GL_BLEND_DST_ALPHA"/>
+            <enum name="GL_BLEND_SRC_ALPHA"/>
+            <enum name="GL_POINT_FADE_THRESHOLD_SIZE"/>
+            <enum name="GL_DEPTH_COMPONENT16"/>
+            <enum name="GL_DEPTH_COMPONENT24"/>
+            <enum name="GL_DEPTH_COMPONENT32"/>
+            <enum name="GL_MIRRORED_REPEAT"/>
+            <enum name="GL_MAX_TEXTURE_LOD_BIAS"/>
+            <enum name="GL_TEXTURE_LOD_BIAS"/>
+            <enum name="GL_INCR_WRAP"/>
+            <enum name="GL_DECR_WRAP"/>
+            <enum name="GL_TEXTURE_DEPTH_SIZE"/>
+            <enum name="GL_TEXTURE_COMPARE_MODE"/>
+            <enum name="GL_TEXTURE_COMPARE_FUNC"/>
+            <enum name="GL_POINT_SIZE_MIN"/>
+            <enum name="GL_POINT_SIZE_MAX"/>
+            <enum name="GL_POINT_DISTANCE_ATTENUATION"/>
+            <enum name="GL_GENERATE_MIPMAP"/>
+            <enum name="GL_GENERATE_MIPMAP_HINT"/>
+            <enum name="GL_FOG_COORDINATE_SOURCE"/>
+            <enum name="GL_FOG_COORDINATE"/>
+            <enum name="GL_FRAGMENT_DEPTH"/>
+            <enum name="GL_CURRENT_FOG_COORDINATE"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY_TYPE"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY_STRIDE"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY_POINTER"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY"/>
+            <enum name="GL_COLOR_SUM"/>
+            <enum name="GL_CURRENT_SECONDARY_COLOR"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_SIZE"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_TYPE"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_STRIDE"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_POINTER"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY"/>
+            <enum name="GL_TEXTURE_FILTER_CONTROL"/>
+            <enum name="GL_DEPTH_TEXTURE_MODE"/>
+            <enum name="GL_COMPARE_R_TO_TEXTURE"/>
+            <command name="glBlendFuncSeparate"/>
+            <command name="glMultiDrawArrays"/>
+            <command name="glMultiDrawElements"/>
+            <command name="glPointParameterf"/>
+            <command name="glPointParameterfv"/>
+            <command name="glPointParameteri"/>
+            <command name="glPointParameteriv"/>
+            <command name="glFogCoordf"/>
+            <command name="glFogCoordfv"/>
+            <command name="glFogCoordd"/>
+            <command name="glFogCoorddv"/>
+            <command name="glFogCoordPointer"/>
+            <command name="glSecondaryColor3b"/>
+            <command name="glSecondaryColor3bv"/>
+            <command name="glSecondaryColor3d"/>
+            <command name="glSecondaryColor3dv"/>
+            <command name="glSecondaryColor3f"/>
+            <command name="glSecondaryColor3fv"/>
+            <command name="glSecondaryColor3i"/>
+            <command name="glSecondaryColor3iv"/>
+            <command name="glSecondaryColor3s"/>
+            <command name="glSecondaryColor3sv"/>
+            <command name="glSecondaryColor3ub"/>
+            <command name="glSecondaryColor3ubv"/>
+            <command name="glSecondaryColor3ui"/>
+            <command name="glSecondaryColor3uiv"/>
+            <command name="glSecondaryColor3us"/>
+            <command name="glSecondaryColor3usv"/>
+            <command name="glSecondaryColorPointer"/>
+            <command name="glWindowPos2d"/>
+            <command name="glWindowPos2dv"/>
+            <command name="glWindowPos2f"/>
+            <command name="glWindowPos2fv"/>
+            <command name="glWindowPos2i"/>
+            <command name="glWindowPos2iv"/>
+            <command name="glWindowPos2s"/>
+            <command name="glWindowPos2sv"/>
+            <command name="glWindowPos3d"/>
+            <command name="glWindowPos3dv"/>
+            <command name="glWindowPos3f"/>
+            <command name="glWindowPos3fv"/>
+            <command name="glWindowPos3i"/>
+            <command name="glWindowPos3iv"/>
+            <command name="glWindowPos3s"/>
+            <command name="glWindowPos3sv"/>
+        </require>
+        <require comment="Promoted from ARB_imaging subset to core">
+            <enum name="GL_FUNC_ADD"/>
+            <enum name="GL_FUNC_SUBTRACT"/>
+            <enum name="GL_FUNC_REVERSE_SUBTRACT"/>
+            <enum name="GL_MIN"/>
+            <enum name="GL_MAX"/>
+            <enum name="GL_CONSTANT_COLOR"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_COLOR"/>
+            <enum name="GL_CONSTANT_ALPHA"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_ALPHA"/>
+            <command name="glBlendColor"/>
+            <command name="glBlendEquation"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_1_5" number="1.5">
+        <require>
+            <enum name="GL_BUFFER_SIZE"/>
+            <enum name="GL_BUFFER_USAGE"/>
+            <enum name="GL_QUERY_COUNTER_BITS"/>
+            <enum name="GL_CURRENT_QUERY"/>
+            <enum name="GL_QUERY_RESULT"/>
+            <enum name="GL_QUERY_RESULT_AVAILABLE"/>
+            <enum name="GL_ARRAY_BUFFER"/>
+            <enum name="GL_ELEMENT_ARRAY_BUFFER"/>
+            <enum name="GL_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_ELEMENT_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_READ_ONLY"/>
+            <enum name="GL_WRITE_ONLY"/>
+            <enum name="GL_READ_WRITE"/>
+            <enum name="GL_BUFFER_ACCESS"/>
+            <enum name="GL_BUFFER_MAPPED"/>
+            <enum name="GL_BUFFER_MAP_POINTER"/>
+            <enum name="GL_STREAM_DRAW"/>
+            <enum name="GL_STREAM_READ"/>
+            <enum name="GL_STREAM_COPY"/>
+            <enum name="GL_STATIC_DRAW"/>
+            <enum name="GL_STATIC_READ"/>
+            <enum name="GL_STATIC_COPY"/>
+            <enum name="GL_DYNAMIC_DRAW"/>
+            <enum name="GL_DYNAMIC_READ"/>
+            <enum name="GL_DYNAMIC_COPY"/>
+            <enum name="GL_SAMPLES_PASSED"/>
+            <enum name="GL_SRC1_ALPHA"/>
+            <enum name="GL_VERTEX_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_NORMAL_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_COLOR_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_INDEX_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_WEIGHT_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_FOG_COORD_SRC"/>
+            <enum name="GL_FOG_COORD"/>
+            <enum name="GL_CURRENT_FOG_COORD"/>
+            <enum name="GL_FOG_COORD_ARRAY_TYPE"/>
+            <enum name="GL_FOG_COORD_ARRAY_STRIDE"/>
+            <enum name="GL_FOG_COORD_ARRAY_POINTER"/>
+            <enum name="GL_FOG_COORD_ARRAY"/>
+            <enum name="GL_FOG_COORD_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_SRC0_RGB"/>
+            <enum name="GL_SRC1_RGB"/>
+            <enum name="GL_SRC2_RGB"/>
+            <enum name="GL_SRC0_ALPHA"/>
+            <enum name="GL_SRC2_ALPHA"/>
+            <command name="glGenQueries"/>
+            <command name="glDeleteQueries"/>
+            <command name="glIsQuery"/>
+            <command name="glBeginQuery"/>
+            <command name="glEndQuery"/>
+            <command name="glGetQueryiv"/>
+            <command name="glGetQueryObjectiv"/>
+            <command name="glGetQueryObjectuiv"/>
+            <command name="glBindBuffer"/>
+            <command name="glDeleteBuffers"/>
+            <command name="glGenBuffers"/>
+            <command name="glIsBuffer"/>
+            <command name="glBufferData"/>
+            <command name="glBufferSubData"/>
+            <command name="glGetBufferSubData"/>
+            <command name="glMapBuffer"/>
+            <command name="glUnmapBuffer"/>
+            <command name="glGetBufferParameteriv"/>
+            <command name="glGetBufferPointerv"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_2_0" number="2.0">
+        <require>
+            <enum name="GL_BLEND_EQUATION_RGB"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_ENABLED"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_SIZE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_STRIDE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_TYPE"/>
+            <enum name="GL_CURRENT_VERTEX_ATTRIB"/>
+            <enum name="GL_VERTEX_PROGRAM_POINT_SIZE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_POINTER"/>
+            <enum name="GL_STENCIL_BACK_FUNC"/>
+            <enum name="GL_STENCIL_BACK_FAIL"/>
+            <enum name="GL_STENCIL_BACK_PASS_DEPTH_FAIL"/>
+            <enum name="GL_STENCIL_BACK_PASS_DEPTH_PASS"/>
+            <enum name="GL_MAX_DRAW_BUFFERS"/>
+            <enum name="GL_DRAW_BUFFER0"/>
+            <enum name="GL_DRAW_BUFFER1"/>
+            <enum name="GL_DRAW_BUFFER2"/>
+            <enum name="GL_DRAW_BUFFER3"/>
+            <enum name="GL_DRAW_BUFFER4"/>
+            <enum name="GL_DRAW_BUFFER5"/>
+            <enum name="GL_DRAW_BUFFER6"/>
+            <enum name="GL_DRAW_BUFFER7"/>
+            <enum name="GL_DRAW_BUFFER8"/>
+            <enum name="GL_DRAW_BUFFER9"/>
+            <enum name="GL_DRAW_BUFFER10"/>
+            <enum name="GL_DRAW_BUFFER11"/>
+            <enum name="GL_DRAW_BUFFER12"/>
+            <enum name="GL_DRAW_BUFFER13"/>
+            <enum name="GL_DRAW_BUFFER14"/>
+            <enum name="GL_DRAW_BUFFER15"/>
+            <enum name="GL_BLEND_EQUATION_ALPHA"/>
+            <enum name="GL_MAX_VERTEX_ATTRIBS"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"/>
+            <enum name="GL_MAX_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_FRAGMENT_SHADER"/>
+            <enum name="GL_VERTEX_SHADER"/>
+            <enum name="GL_MAX_FRAGMENT_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_VERTEX_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_VARYING_FLOATS"/>
+            <enum name="GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_SHADER_TYPE"/>
+            <enum name="GL_FLOAT_VEC2"/>
+            <enum name="GL_FLOAT_VEC3"/>
+            <enum name="GL_FLOAT_VEC4"/>
+            <enum name="GL_INT_VEC2"/>
+            <enum name="GL_INT_VEC3"/>
+            <enum name="GL_INT_VEC4"/>
+            <enum name="GL_BOOL"/>
+            <enum name="GL_BOOL_VEC2"/>
+            <enum name="GL_BOOL_VEC3"/>
+            <enum name="GL_BOOL_VEC4"/>
+            <enum name="GL_FLOAT_MAT2"/>
+            <enum name="GL_FLOAT_MAT3"/>
+            <enum name="GL_FLOAT_MAT4"/>
+            <enum name="GL_SAMPLER_1D"/>
+            <enum name="GL_SAMPLER_2D"/>
+            <enum name="GL_SAMPLER_3D"/>
+            <enum name="GL_SAMPLER_CUBE"/>
+            <enum name="GL_SAMPLER_1D_SHADOW"/>
+            <enum name="GL_SAMPLER_2D_SHADOW"/>
+            <enum name="GL_DELETE_STATUS"/>
+            <enum name="GL_COMPILE_STATUS"/>
+            <enum name="GL_LINK_STATUS"/>
+            <enum name="GL_VALIDATE_STATUS"/>
+            <enum name="GL_INFO_LOG_LENGTH"/>
+            <enum name="GL_ATTACHED_SHADERS"/>
+            <enum name="GL_ACTIVE_UNIFORMS"/>
+            <enum name="GL_ACTIVE_UNIFORM_MAX_LENGTH"/>
+            <enum name="GL_SHADER_SOURCE_LENGTH"/>
+            <enum name="GL_ACTIVE_ATTRIBUTES"/>
+            <enum name="GL_ACTIVE_ATTRIBUTE_MAX_LENGTH"/>
+            <enum name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT"/>
+            <enum name="GL_SHADING_LANGUAGE_VERSION"/>
+            <enum name="GL_CURRENT_PROGRAM"/>
+            <enum name="GL_POINT_SPRITE_COORD_ORIGIN"/>
+            <enum name="GL_LOWER_LEFT"/>
+            <enum name="GL_UPPER_LEFT"/>
+            <enum name="GL_STENCIL_BACK_REF"/>
+            <enum name="GL_STENCIL_BACK_VALUE_MASK"/>
+            <enum name="GL_STENCIL_BACK_WRITEMASK"/>
+            <enum name="GL_VERTEX_PROGRAM_TWO_SIDE"/>
+            <enum name="GL_POINT_SPRITE"/>
+            <enum name="GL_COORD_REPLACE"/>
+            <enum name="GL_MAX_TEXTURE_COORDS"/>
+            <command name="glBlendEquationSeparate"/>
+            <command name="glDrawBuffers"/>
+            <command name="glStencilOpSeparate"/>
+            <command name="glStencilFuncSeparate"/>
+            <command name="glStencilMaskSeparate"/>
+            <command name="glAttachShader"/>
+            <command name="glBindAttribLocation"/>
+            <command name="glCompileShader"/>
+            <command name="glCreateProgram"/>
+            <command name="glCreateShader"/>
+            <command name="glDeleteProgram"/>
+            <command name="glDeleteShader"/>
+            <command name="glDetachShader"/>
+            <command name="glDisableVertexAttribArray"/>
+            <command name="glEnableVertexAttribArray"/>
+            <command name="glGetActiveAttrib"/>
+            <command name="glGetActiveUniform"/>
+            <command name="glGetAttachedShaders"/>
+            <command name="glGetAttribLocation"/>
+            <command name="glGetProgramiv"/>
+            <command name="glGetProgramInfoLog"/>
+            <command name="glGetShaderiv"/>
+            <command name="glGetShaderInfoLog"/>
+            <command name="glGetShaderSource"/>
+            <command name="glGetUniformLocation"/>
+            <command name="glGetUniformfv"/>
+            <command name="glGetUniformiv"/>
+            <command name="glGetVertexAttribdv"/>
+            <command name="glGetVertexAttribfv"/>
+            <command name="glGetVertexAttribiv"/>
+            <command name="glGetVertexAttribPointerv"/>
+            <command name="glIsProgram"/>
+            <command name="glIsShader"/>
+            <command name="glLinkProgram"/>
+            <command name="glShaderSource"/>
+            <command name="glUseProgram"/>
+            <command name="glUniform1f"/>
+            <command name="glUniform2f"/>
+            <command name="glUniform3f"/>
+            <command name="glUniform4f"/>
+            <command name="glUniform1i"/>
+            <command name="glUniform2i"/>
+            <command name="glUniform3i"/>
+            <command name="glUniform4i"/>
+            <command name="glUniform1fv"/>
+            <command name="glUniform2fv"/>
+            <command name="glUniform3fv"/>
+            <command name="glUniform4fv"/>
+            <command name="glUniform1iv"/>
+            <command name="glUniform2iv"/>
+            <command name="glUniform3iv"/>
+            <command name="glUniform4iv"/>
+            <command name="glUniformMatrix2fv"/>
+            <command name="glUniformMatrix3fv"/>
+            <command name="glUniformMatrix4fv"/>
+            <command name="glValidateProgram"/>
+            <command name="glVertexAttrib1d"/>
+            <command name="glVertexAttrib1dv"/>
+            <command name="glVertexAttrib1f"/>
+            <command name="glVertexAttrib1fv"/>
+            <command name="glVertexAttrib1s"/>
+            <command name="glVertexAttrib1sv"/>
+            <command name="glVertexAttrib2d"/>
+            <command name="glVertexAttrib2dv"/>
+            <command name="glVertexAttrib2f"/>
+            <command name="glVertexAttrib2fv"/>
+            <command name="glVertexAttrib2s"/>
+            <command name="glVertexAttrib2sv"/>
+            <command name="glVertexAttrib3d"/>
+            <command name="glVertexAttrib3dv"/>
+            <command name="glVertexAttrib3f"/>
+            <command name="glVertexAttrib3fv"/>
+            <command name="glVertexAttrib3s"/>
+            <command name="glVertexAttrib3sv"/>
+            <command name="glVertexAttrib4Nbv"/>
+            <command name="glVertexAttrib4Niv"/>
+            <command name="glVertexAttrib4Nsv"/>
+            <command name="glVertexAttrib4Nub"/>
+            <command name="glVertexAttrib4Nubv"/>
+            <command name="glVertexAttrib4Nuiv"/>
+            <command name="glVertexAttrib4Nusv"/>
+            <command name="glVertexAttrib4bv"/>
+            <command name="glVertexAttrib4d"/>
+            <command name="glVertexAttrib4dv"/>
+            <command name="glVertexAttrib4f"/>
+            <command name="glVertexAttrib4fv"/>
+            <command name="glVertexAttrib4iv"/>
+            <command name="glVertexAttrib4s"/>
+            <command name="glVertexAttrib4sv"/>
+            <command name="glVertexAttrib4ubv"/>
+            <command name="glVertexAttrib4uiv"/>
+            <command name="glVertexAttrib4usv"/>
+            <command name="glVertexAttribPointer"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_2_1" number="2.1">
+        <require>
+            <enum name="GL_PIXEL_PACK_BUFFER"/>
+            <enum name="GL_PIXEL_UNPACK_BUFFER"/>
+            <enum name="GL_PIXEL_PACK_BUFFER_BINDING"/>
+            <enum name="GL_PIXEL_UNPACK_BUFFER_BINDING"/>
+            <enum name="GL_FLOAT_MAT2x3"/>
+            <enum name="GL_FLOAT_MAT2x4"/>
+            <enum name="GL_FLOAT_MAT3x2"/>
+            <enum name="GL_FLOAT_MAT3x4"/>
+            <enum name="GL_FLOAT_MAT4x2"/>
+            <enum name="GL_FLOAT_MAT4x3"/>
+            <enum name="GL_SRGB"/>
+            <enum name="GL_SRGB8"/>
+            <enum name="GL_SRGB_ALPHA"/>
+            <enum name="GL_SRGB8_ALPHA8"/>
+            <enum name="GL_COMPRESSED_SRGB"/>
+            <enum name="GL_COMPRESSED_SRGB_ALPHA"/>
+            <enum name="GL_CURRENT_RASTER_SECONDARY_COLOR"/>
+            <enum name="GL_SLUMINANCE_ALPHA"/>
+            <enum name="GL_SLUMINANCE8_ALPHA8"/>
+            <enum name="GL_SLUMINANCE"/>
+            <enum name="GL_SLUMINANCE8"/>
+            <enum name="GL_COMPRESSED_SLUMINANCE"/>
+            <enum name="GL_COMPRESSED_SLUMINANCE_ALPHA"/>
+            <command name="glUniformMatrix2x3fv"/>
+            <command name="glUniformMatrix3x2fv"/>
+            <command name="glUniformMatrix2x4fv"/>
+            <command name="glUniformMatrix4x2fv"/>
+            <command name="glUniformMatrix3x4fv"/>
+            <command name="glUniformMatrix4x3fv"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_3_0" number="3.0">
+        <require>
+            <enum name="GL_COMPARE_REF_TO_TEXTURE"/>
+            <enum name="GL_CLIP_DISTANCE0"/>
+            <enum name="GL_CLIP_DISTANCE1"/>
+            <enum name="GL_CLIP_DISTANCE2"/>
+            <enum name="GL_CLIP_DISTANCE3"/>
+            <enum name="GL_CLIP_DISTANCE4"/>
+            <enum name="GL_CLIP_DISTANCE5"/>
+            <enum name="GL_CLIP_DISTANCE6"/>
+            <enum name="GL_CLIP_DISTANCE7"/>
+            <enum name="GL_MAX_CLIP_DISTANCES"/>
+            <enum name="GL_MAJOR_VERSION"/>
+            <enum name="GL_MINOR_VERSION"/>
+            <enum name="GL_NUM_EXTENSIONS"/>
+            <enum name="GL_CONTEXT_FLAGS"/>
+            <enum name="GL_COMPRESSED_RED"/>
+            <enum name="GL_COMPRESSED_RG"/>
+            <enum name="GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT"/>
+            <enum name="GL_RGBA32F"/>
+            <enum name="GL_RGB32F"/>
+            <enum name="GL_RGBA16F"/>
+            <enum name="GL_RGB16F"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_INTEGER"/>
+            <enum name="GL_MAX_ARRAY_TEXTURE_LAYERS"/>
+            <enum name="GL_MIN_PROGRAM_TEXEL_OFFSET"/>
+            <enum name="GL_MAX_PROGRAM_TEXEL_OFFSET"/>
+            <enum name="GL_CLAMP_READ_COLOR"/>
+            <enum name="GL_FIXED_ONLY"/>
+            <enum name="GL_MAX_VARYING_COMPONENTS"/>
+            <enum name="GL_TEXTURE_1D_ARRAY"/>
+            <enum name="GL_PROXY_TEXTURE_1D_ARRAY"/>
+            <enum name="GL_TEXTURE_2D_ARRAY"/>
+            <enum name="GL_PROXY_TEXTURE_2D_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_1D_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_2D_ARRAY"/>
+            <enum name="GL_R11F_G11F_B10F"/>
+            <enum name="GL_UNSIGNED_INT_10F_11F_11F_REV"/>
+            <enum name="GL_RGB9_E5"/>
+            <enum name="GL_UNSIGNED_INT_5_9_9_9_REV"/>
+            <enum name="GL_TEXTURE_SHARED_SIZE"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_MODE"/>
+            <enum name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_VARYINGS"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_START"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_SIZE"/>
+            <enum name="GL_PRIMITIVES_GENERATED"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"/>
+            <enum name="GL_RASTERIZER_DISCARD"/>
+            <enum name="GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS"/>
+            <enum name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS"/>
+            <enum name="GL_INTERLEAVED_ATTRIBS"/>
+            <enum name="GL_SEPARATE_ATTRIBS"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_BINDING"/>
+            <enum name="GL_RGBA32UI"/>
+            <enum name="GL_RGB32UI"/>
+            <enum name="GL_RGBA16UI"/>
+            <enum name="GL_RGB16UI"/>
+            <enum name="GL_RGBA8UI"/>
+            <enum name="GL_RGB8UI"/>
+            <enum name="GL_RGBA32I"/>
+            <enum name="GL_RGB32I"/>
+            <enum name="GL_RGBA16I"/>
+            <enum name="GL_RGB16I"/>
+            <enum name="GL_RGBA8I"/>
+            <enum name="GL_RGB8I"/>
+            <enum name="GL_RED_INTEGER"/>
+            <enum name="GL_GREEN_INTEGER"/>
+            <enum name="GL_BLUE_INTEGER"/>
+            <enum name="GL_RGB_INTEGER"/>
+            <enum name="GL_RGBA_INTEGER"/>
+            <enum name="GL_BGR_INTEGER"/>
+            <enum name="GL_BGRA_INTEGER"/>
+            <enum name="GL_SAMPLER_1D_ARRAY"/>
+            <enum name="GL_SAMPLER_2D_ARRAY"/>
+            <enum name="GL_SAMPLER_1D_ARRAY_SHADOW"/>
+            <enum name="GL_SAMPLER_2D_ARRAY_SHADOW"/>
+            <enum name="GL_SAMPLER_CUBE_SHADOW"/>
+            <enum name="GL_UNSIGNED_INT_VEC2"/>
+            <enum name="GL_UNSIGNED_INT_VEC3"/>
+            <enum name="GL_UNSIGNED_INT_VEC4"/>
+            <enum name="GL_INT_SAMPLER_1D"/>
+            <enum name="GL_INT_SAMPLER_2D"/>
+            <enum name="GL_INT_SAMPLER_3D"/>
+            <enum name="GL_INT_SAMPLER_CUBE"/>
+            <enum name="GL_INT_SAMPLER_1D_ARRAY"/>
+            <enum name="GL_INT_SAMPLER_2D_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_1D"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_3D"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_1D_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D_ARRAY"/>
+            <enum name="GL_QUERY_WAIT"/>
+            <enum name="GL_QUERY_NO_WAIT"/>
+            <enum name="GL_QUERY_BY_REGION_WAIT"/>
+            <enum name="GL_QUERY_BY_REGION_NO_WAIT"/>
+            <enum name="GL_BUFFER_ACCESS_FLAGS"/>
+            <enum name="GL_BUFFER_MAP_LENGTH"/>
+            <enum name="GL_BUFFER_MAP_OFFSET"/>
+            <command name="glColorMaski"/>
+            <command name="glGetBooleani_v"/>
+            <command name="glGetIntegeri_v"/>
+            <command name="glEnablei"/>
+            <command name="glDisablei"/>
+            <command name="glIsEnabledi"/>
+            <command name="glBeginTransformFeedback"/>
+            <command name="glEndTransformFeedback"/>
+            <command name="glBindBufferRange"/>
+            <command name="glBindBufferBase"/>
+            <command name="glTransformFeedbackVaryings"/>
+            <command name="glGetTransformFeedbackVarying"/>
+            <command name="glClampColor"/>
+            <command name="glBeginConditionalRender"/>
+            <command name="glEndConditionalRender"/>
+            <command name="glVertexAttribIPointer"/>
+            <command name="glGetVertexAttribIiv"/>
+            <command name="glGetVertexAttribIuiv"/>
+            <command name="glVertexAttribI1i"/>
+            <command name="glVertexAttribI2i"/>
+            <command name="glVertexAttribI3i"/>
+            <command name="glVertexAttribI4i"/>
+            <command name="glVertexAttribI1ui"/>
+            <command name="glVertexAttribI2ui"/>
+            <command name="glVertexAttribI3ui"/>
+            <command name="glVertexAttribI4ui"/>
+            <command name="glVertexAttribI1iv"/>
+            <command name="glVertexAttribI2iv"/>
+            <command name="glVertexAttribI3iv"/>
+            <command name="glVertexAttribI4iv"/>
+            <command name="glVertexAttribI1uiv"/>
+            <command name="glVertexAttribI2uiv"/>
+            <command name="glVertexAttribI3uiv"/>
+            <command name="glVertexAttribI4uiv"/>
+            <command name="glVertexAttribI4bv"/>
+            <command name="glVertexAttribI4sv"/>
+            <command name="glVertexAttribI4ubv"/>
+            <command name="glVertexAttribI4usv"/>
+            <command name="glGetUniformuiv"/>
+            <command name="glBindFragDataLocation"/>
+            <command name="glGetFragDataLocation"/>
+            <command name="glUniform1ui"/>
+            <command name="glUniform2ui"/>
+            <command name="glUniform3ui"/>
+            <command name="glUniform4ui"/>
+            <command name="glUniform1uiv"/>
+            <command name="glUniform2uiv"/>
+            <command name="glUniform3uiv"/>
+            <command name="glUniform4uiv"/>
+            <command name="glTexParameterIiv"/>
+            <command name="glTexParameterIuiv"/>
+            <command name="glGetTexParameterIiv"/>
+            <command name="glGetTexParameterIuiv"/>
+            <command name="glClearBufferiv"/>
+            <command name="glClearBufferuiv"/>
+            <command name="glClearBufferfv"/>
+            <command name="glClearBufferfi"/>
+            <command name="glGetStringi"/>
+        </require>
+        <require comment="Reuse ARB_depth_buffer_float">
+            <enum name="GL_DEPTH_COMPONENT32F"/>
+            <enum name="GL_DEPTH32F_STENCIL8"/>
+            <enum name="GL_FLOAT_32_UNSIGNED_INT_24_8_REV"/>
+        </require>
+        <require comment="Reuse ARB_framebuffer_object">
+            <enum name="GL_INVALID_FRAMEBUFFER_OPERATION"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT"/>
+            <enum name="GL_FRAMEBUFFER_UNDEFINED"/>
+            <enum name="GL_DEPTH_STENCIL_ATTACHMENT"/>
+            <enum name="GL_MAX_RENDERBUFFER_SIZE"/>
+            <enum name="GL_DEPTH_STENCIL"/>
+            <enum name="GL_UNSIGNED_INT_24_8"/>
+            <enum name="GL_DEPTH24_STENCIL8"/>
+            <enum name="GL_TEXTURE_STENCIL_SIZE"/>
+            <enum name="GL_TEXTURE_RED_TYPE"/>
+            <enum name="GL_TEXTURE_GREEN_TYPE"/>
+            <enum name="GL_TEXTURE_BLUE_TYPE"/>
+            <enum name="GL_TEXTURE_ALPHA_TYPE"/>
+            <enum name="GL_TEXTURE_DEPTH_TYPE"/>
+            <enum name="GL_UNSIGNED_NORMALIZED"/>
+            <enum name="GL_FRAMEBUFFER_BINDING"/>
+            <enum name="GL_DRAW_FRAMEBUFFER_BINDING"/>
+            <enum name="GL_RENDERBUFFER_BINDING"/>
+            <enum name="GL_READ_FRAMEBUFFER"/>
+            <enum name="GL_DRAW_FRAMEBUFFER"/>
+            <enum name="GL_READ_FRAMEBUFFER_BINDING"/>
+            <enum name="GL_RENDERBUFFER_SAMPLES"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER"/>
+            <enum name="GL_FRAMEBUFFER_COMPLETE"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"/>
+            <enum name="GL_FRAMEBUFFER_UNSUPPORTED"/>
+            <enum name="GL_MAX_COLOR_ATTACHMENTS"/>
+            <enum name="GL_COLOR_ATTACHMENT0"/>
+            <enum name="GL_COLOR_ATTACHMENT1"/>
+            <enum name="GL_COLOR_ATTACHMENT2"/>
+            <enum name="GL_COLOR_ATTACHMENT3"/>
+            <enum name="GL_COLOR_ATTACHMENT4"/>
+            <enum name="GL_COLOR_ATTACHMENT5"/>
+            <enum name="GL_COLOR_ATTACHMENT6"/>
+            <enum name="GL_COLOR_ATTACHMENT7"/>
+            <enum name="GL_COLOR_ATTACHMENT8"/>
+            <enum name="GL_COLOR_ATTACHMENT9"/>
+            <enum name="GL_COLOR_ATTACHMENT10"/>
+            <enum name="GL_COLOR_ATTACHMENT11"/>
+            <enum name="GL_COLOR_ATTACHMENT12"/>
+            <enum name="GL_COLOR_ATTACHMENT13"/>
+            <enum name="GL_COLOR_ATTACHMENT14"/>
+            <enum name="GL_COLOR_ATTACHMENT15"/>
+            <enum name="GL_COLOR_ATTACHMENT16"/>
+            <enum name="GL_COLOR_ATTACHMENT17"/>
+            <enum name="GL_COLOR_ATTACHMENT18"/>
+            <enum name="GL_COLOR_ATTACHMENT19"/>
+            <enum name="GL_COLOR_ATTACHMENT20"/>
+            <enum name="GL_COLOR_ATTACHMENT21"/>
+            <enum name="GL_COLOR_ATTACHMENT22"/>
+            <enum name="GL_COLOR_ATTACHMENT23"/>
+            <enum name="GL_COLOR_ATTACHMENT24"/>
+            <enum name="GL_COLOR_ATTACHMENT25"/>
+            <enum name="GL_COLOR_ATTACHMENT26"/>
+            <enum name="GL_COLOR_ATTACHMENT27"/>
+            <enum name="GL_COLOR_ATTACHMENT28"/>
+            <enum name="GL_COLOR_ATTACHMENT29"/>
+            <enum name="GL_COLOR_ATTACHMENT30"/>
+            <enum name="GL_COLOR_ATTACHMENT31"/>
+            <enum name="GL_DEPTH_ATTACHMENT"/>
+            <enum name="GL_STENCIL_ATTACHMENT"/>
+            <enum name="GL_FRAMEBUFFER"/>
+            <enum name="GL_RENDERBUFFER"/>
+            <enum name="GL_RENDERBUFFER_WIDTH"/>
+            <enum name="GL_RENDERBUFFER_HEIGHT"/>
+            <enum name="GL_RENDERBUFFER_INTERNAL_FORMAT"/>
+            <enum name="GL_STENCIL_INDEX1"/>
+            <enum name="GL_STENCIL_INDEX4"/>
+            <enum name="GL_STENCIL_INDEX8"/>
+            <enum name="GL_STENCIL_INDEX16"/>
+            <enum name="GL_RENDERBUFFER_RED_SIZE"/>
+            <enum name="GL_RENDERBUFFER_GREEN_SIZE"/>
+            <enum name="GL_RENDERBUFFER_BLUE_SIZE"/>
+            <enum name="GL_RENDERBUFFER_ALPHA_SIZE"/>
+            <enum name="GL_RENDERBUFFER_DEPTH_SIZE"/>
+            <enum name="GL_RENDERBUFFER_STENCIL_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"/>
+            <enum name="GL_MAX_SAMPLES"/>
+            <command name="glIsRenderbuffer"/>
+            <command name="glBindRenderbuffer"/>
+            <command name="glDeleteRenderbuffers"/>
+            <command name="glGenRenderbuffers"/>
+            <command name="glRenderbufferStorage"/>
+            <command name="glGetRenderbufferParameteriv"/>
+            <command name="glIsFramebuffer"/>
+            <command name="glBindFramebuffer"/>
+            <command name="glDeleteFramebuffers"/>
+            <command name="glGenFramebuffers"/>
+            <command name="glCheckFramebufferStatus"/>
+            <command name="glFramebufferTexture1D"/>
+            <command name="glFramebufferTexture2D"/>
+            <command name="glFramebufferTexture3D"/>
+            <command name="glFramebufferRenderbuffer"/>
+            <command name="glGetFramebufferAttachmentParameteriv"/>
+            <command name="glGenerateMipmap"/>
+            <command name="glBlitFramebuffer"/>
+            <command name="glRenderbufferStorageMultisample"/>
+            <command name="glFramebufferTextureLayer"/>
+        </require>
+        <require profile="compatibility" comment="Reuse ARB_framebuffer_object compatibility profile">
+            <enum name="GL_INDEX"/>
+            <enum name="GL_TEXTURE_LUMINANCE_TYPE"/>
+            <enum name="GL_TEXTURE_INTENSITY_TYPE"/>
+        </require>
+        <require comment="Reuse ARB_framebuffer_sRGB">
+            <enum name="GL_FRAMEBUFFER_SRGB"/>
+        </require>
+        <require comment="Reuse ARB_half_float_vertex">
+            <type name="GLhalf"/>
+            <enum name="GL_HALF_FLOAT"/>
+        </require>
+        <require comment="Reuse ARB_map_buffer_range">
+            <enum name="GL_MAP_READ_BIT"/>
+            <enum name="GL_MAP_WRITE_BIT"/>
+            <enum name="GL_MAP_INVALIDATE_RANGE_BIT"/>
+            <enum name="GL_MAP_INVALIDATE_BUFFER_BIT"/>
+            <enum name="GL_MAP_FLUSH_EXPLICIT_BIT"/>
+            <enum name="GL_MAP_UNSYNCHRONIZED_BIT"/>
+            <command name="glMapBufferRange"/>
+            <command name="glFlushMappedBufferRange"/>
+        </require>
+        <require comment="Reuse ARB_texture_compression_rgtc">
+            <enum name="GL_COMPRESSED_RED_RGTC1"/>
+            <enum name="GL_COMPRESSED_SIGNED_RED_RGTC1"/>
+            <enum name="GL_COMPRESSED_RG_RGTC2"/>
+            <enum name="GL_COMPRESSED_SIGNED_RG_RGTC2"/>
+        </require>
+        <require comment="Reuse ARB_texture_rg">
+            <enum name="GL_RG"/>
+            <enum name="GL_RG_INTEGER"/>
+            <enum name="GL_R8"/>
+            <enum name="GL_R16"/>
+            <enum name="GL_RG8"/>
+            <enum name="GL_RG16"/>
+            <enum name="GL_R16F"/>
+            <enum name="GL_R32F"/>
+            <enum name="GL_RG16F"/>
+            <enum name="GL_RG32F"/>
+            <enum name="GL_R8I"/>
+            <enum name="GL_R8UI"/>
+            <enum name="GL_R16I"/>
+            <enum name="GL_R16UI"/>
+            <enum name="GL_R32I"/>
+            <enum name="GL_R32UI"/>
+            <enum name="GL_RG8I"/>
+            <enum name="GL_RG8UI"/>
+            <enum name="GL_RG16I"/>
+            <enum name="GL_RG16UI"/>
+            <enum name="GL_RG32I"/>
+            <enum name="GL_RG32UI"/>
+        </require>
+        <require comment="Reuse ARB_vertex_array_object">
+            <enum name="GL_VERTEX_ARRAY_BINDING"/>
+            <enum name="GL_CLAMP_VERTEX_COLOR"/>
+            <enum name="GL_CLAMP_FRAGMENT_COLOR"/>
+            <enum name="GL_ALPHA_INTEGER"/>
+            <command name="glBindVertexArray"/>
+            <command name="glDeleteVertexArrays"/>
+            <command name="glGenVertexArrays"/>
+            <command name="glIsVertexArray"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_3_1" number="3.1">
+        <require>
+            <enum name="GL_SAMPLER_2D_RECT"/>
+            <enum name="GL_SAMPLER_2D_RECT_SHADOW"/>
+            <enum name="GL_SAMPLER_BUFFER"/>
+            <enum name="GL_INT_SAMPLER_2D_RECT"/>
+            <enum name="GL_INT_SAMPLER_BUFFER"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D_RECT"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_BUFFER"/>
+            <enum name="GL_TEXTURE_BUFFER"/>
+            <enum name="GL_MAX_TEXTURE_BUFFER_SIZE"/>
+            <enum name="GL_TEXTURE_BINDING_BUFFER"/>
+            <enum name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING"/>
+            <enum name="GL_TEXTURE_RECTANGLE"/>
+            <enum name="GL_TEXTURE_BINDING_RECTANGLE"/>
+            <enum name="GL_PROXY_TEXTURE_RECTANGLE"/>
+            <enum name="GL_MAX_RECTANGLE_TEXTURE_SIZE"/>
+            <enum name="GL_R8_SNORM"/>
+            <enum name="GL_RG8_SNORM"/>
+            <enum name="GL_RGB8_SNORM"/>
+            <enum name="GL_RGBA8_SNORM"/>
+            <enum name="GL_R16_SNORM"/>
+            <enum name="GL_RG16_SNORM"/>
+            <enum name="GL_RGB16_SNORM"/>
+            <enum name="GL_RGBA16_SNORM"/>
+            <enum name="GL_SIGNED_NORMALIZED"/>
+            <enum name="GL_PRIMITIVE_RESTART"/>
+            <enum name="GL_PRIMITIVE_RESTART_INDEX"/>
+            <command name="glDrawArraysInstanced"/>
+            <command name="glDrawElementsInstanced"/>
+            <command name="glTexBuffer"/>
+            <command name="glPrimitiveRestartIndex"/>
+        </require>
+        <require comment="Reuse ARB_copy_buffer">
+            <enum name="GL_COPY_READ_BUFFER"/>
+            <enum name="GL_COPY_WRITE_BUFFER"/>
+            <command name="glCopyBufferSubData"/>
+        </require>
+        <require comment="Reuse ARB_uniform_buffer_object">
+            <enum name="GL_UNIFORM_BUFFER"/>
+            <enum name="GL_UNIFORM_BUFFER_BINDING"/>
+            <enum name="GL_UNIFORM_BUFFER_START"/>
+            <enum name="GL_UNIFORM_BUFFER_SIZE"/>
+            <enum name="GL_MAX_VERTEX_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_FRAGMENT_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_COMBINED_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_UNIFORM_BUFFER_BINDINGS"/>
+            <enum name="GL_MAX_UNIFORM_BLOCK_SIZE"/>
+            <enum name="GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS"/>
+            <enum name="GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT"/>
+            <enum name="GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH"/>
+            <enum name="GL_ACTIVE_UNIFORM_BLOCKS"/>
+            <enum name="GL_UNIFORM_TYPE"/>
+            <enum name="GL_UNIFORM_SIZE"/>
+            <enum name="GL_UNIFORM_NAME_LENGTH"/>
+            <enum name="GL_UNIFORM_BLOCK_INDEX"/>
+            <enum name="GL_UNIFORM_OFFSET"/>
+            <enum name="GL_UNIFORM_ARRAY_STRIDE"/>
+            <enum name="GL_UNIFORM_MATRIX_STRIDE"/>
+            <enum name="GL_UNIFORM_IS_ROW_MAJOR"/>
+            <enum name="GL_UNIFORM_BLOCK_BINDING"/>
+            <enum name="GL_UNIFORM_BLOCK_DATA_SIZE"/>
+            <enum name="GL_UNIFORM_BLOCK_NAME_LENGTH"/>
+            <enum name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS"/>
+            <enum name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES"/>
+            <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"/>
+            <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER"/>
+            <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"/>
+            <enum name="GL_INVALID_INDEX"/>
+            <command name="glGetUniformIndices"/>
+            <command name="glGetActiveUniformsiv"/>
+            <command name="glGetActiveUniformName"/>
+            <command name="glGetUniformBlockIndex"/>
+            <command name="glGetActiveUniformBlockiv"/>
+            <command name="glGetActiveUniformBlockName"/>
+            <command name="glUniformBlockBinding"/>
+            <command name="glBindBufferRange"/>
+            <command name="glBindBufferBase"/>
+            <command name="glGetIntegeri_v"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_3_2" number="3.2">
+        <require>
+            <enum name="GL_CONTEXT_CORE_PROFILE_BIT"/>
+            <enum name="GL_CONTEXT_COMPATIBILITY_PROFILE_BIT"/>
+            <enum name="GL_LINES_ADJACENCY"/>
+            <enum name="GL_LINE_STRIP_ADJACENCY"/>
+            <enum name="GL_TRIANGLES_ADJACENCY"/>
+            <enum name="GL_TRIANGLE_STRIP_ADJACENCY"/>
+            <enum name="GL_PROGRAM_POINT_SIZE"/>
+            <enum name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"/>
+            <enum name="GL_GEOMETRY_SHADER"/>
+            <enum name="GL_GEOMETRY_VERTICES_OUT"/>
+            <enum name="GL_GEOMETRY_INPUT_TYPE"/>
+            <enum name="GL_GEOMETRY_OUTPUT_TYPE"/>
+            <enum name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_OUTPUT_VERTICES"/>
+            <enum name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_VERTEX_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_FRAGMENT_INPUT_COMPONENTS"/>
+            <enum name="GL_CONTEXT_PROFILE_MASK"/>
+        </require>
+        <require comment="Reuse ARB_depth_clamp">
+            <enum name="GL_DEPTH_CLAMP"/>
+        </require>
+        <require comment="Reuse ARB_draw_elements_base_vertex">
+            <command name="glDrawElementsBaseVertex"/>
+            <command name="glDrawRangeElementsBaseVertex"/>
+            <command name="glDrawElementsInstancedBaseVertex"/>
+            <command name="glMultiDrawElementsBaseVertex"/>
+        </require>
+        <require comment="Reuse ARB_fragment_coord_conventions (none)">
+        </require>
+        <require comment="Reuse ARB_provoking_vertex">
+            <enum name="GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION"/>
+            <enum name="GL_FIRST_VERTEX_CONVENTION"/>
+            <enum name="GL_LAST_VERTEX_CONVENTION"/>
+            <enum name="GL_PROVOKING_VERTEX"/>
+            <command name="glProvokingVertex"/>
+        </require>
+        <require comment="Reuse ARB_seamless_cube_map">
+            <enum name="GL_TEXTURE_CUBE_MAP_SEAMLESS"/>
+        </require>
+        <require comment="Reuse ARB_sync">
+            <enum name="GL_MAX_SERVER_WAIT_TIMEOUT"/>
+            <enum name="GL_OBJECT_TYPE"/>
+            <enum name="GL_SYNC_CONDITION"/>
+            <enum name="GL_SYNC_STATUS"/>
+            <enum name="GL_SYNC_FLAGS"/>
+            <enum name="GL_SYNC_FENCE"/>
+            <enum name="GL_SYNC_GPU_COMMANDS_COMPLETE"/>
+            <enum name="GL_UNSIGNALED"/>
+            <enum name="GL_SIGNALED"/>
+            <enum name="GL_ALREADY_SIGNALED"/>
+            <enum name="GL_TIMEOUT_EXPIRED"/>
+            <enum name="GL_CONDITION_SATISFIED"/>
+            <enum name="GL_WAIT_FAILED"/>
+            <enum name="GL_TIMEOUT_IGNORED"/>
+            <enum name="GL_SYNC_FLUSH_COMMANDS_BIT"/>
+            <command name="glFenceSync"/>
+            <command name="glIsSync"/>
+            <command name="glDeleteSync"/>
+            <command name="glClientWaitSync"/>
+            <command name="glWaitSync"/>
+            <command name="glGetInteger64v"/>
+            <command name="glGetSynciv"/>
+        </require>
+        <require comment="Reuse ARB_texture_multisample">
+            <enum name="GL_SAMPLE_POSITION"/>
+            <enum name="GL_SAMPLE_MASK"/>
+            <enum name="GL_SAMPLE_MASK_VALUE"/>
+            <enum name="GL_MAX_SAMPLE_MASK_WORDS"/>
+            <enum name="GL_TEXTURE_2D_MULTISAMPLE"/>
+            <enum name="GL_PROXY_TEXTURE_2D_MULTISAMPLE"/>
+            <enum name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE"/>
+            <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_TEXTURE_SAMPLES"/>
+            <enum name="GL_TEXTURE_FIXED_SAMPLE_LOCATIONS"/>
+            <enum name="GL_SAMPLER_2D_MULTISAMPLE"/>
+            <enum name="GL_INT_SAMPLER_2D_MULTISAMPLE"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE"/>
+            <enum name="GL_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_MAX_COLOR_TEXTURE_SAMPLES"/>
+            <enum name="GL_MAX_DEPTH_TEXTURE_SAMPLES"/>
+            <enum name="GL_MAX_INTEGER_SAMPLES"/>
+            <!-- /* Don't need to reuse tokens from ARB_vertex_array_bgra since they're already in 1.2 core */ -->
+            <command name="glGetInteger64i_v"/>
+            <command name="glGetBufferParameteri64v"/>
+            <command name="glFramebufferTexture"/>
+            <command name="glTexImage2DMultisample"/>
+            <command name="glTexImage3DMultisample"/>
+            <command name="glGetMultisamplefv"/>
+            <command name="glSampleMaski"/>
+        </require>
+        <!-- OpenGL 3.2 is where core and compatibility profiles were first
+             introduced, so many, many things were removed from the core
+             profile in this version. A few were reintroduced later (e.g.
+             GetPointerv / STACK_{UNDER,OVER}FLOW by OpenGL 4.3 for debug
+             functionality). -->
+        <remove profile="core" comment="Compatibility-only GL 1.0 features removed from GL 3.2">
+            <command name="glNewList"/>
+            <command name="glEndList"/>
+            <command name="glCallList"/>
+            <command name="glCallLists"/>
+            <command name="glDeleteLists"/>
+            <command name="glGenLists"/>
+            <command name="glListBase"/>
+            <command name="glBegin"/>
+            <command name="glBitmap"/>
+            <command name="glColor3b"/>
+            <command name="glColor3bv"/>
+            <command name="glColor3d"/>
+            <command name="glColor3dv"/>
+            <command name="glColor3f"/>
+            <command name="glColor3fv"/>
+            <command name="glColor3i"/>
+            <command name="glColor3iv"/>
+            <command name="glColor3s"/>
+            <command name="glColor3sv"/>
+            <command name="glColor3ub"/>
+            <command name="glColor3ubv"/>
+            <command name="glColor3ui"/>
+            <command name="glColor3uiv"/>
+            <command name="glColor3us"/>
+            <command name="glColor3usv"/>
+            <command name="glColor4b"/>
+            <command name="glColor4bv"/>
+            <command name="glColor4d"/>
+            <command name="glColor4dv"/>
+            <command name="glColor4f"/>
+            <command name="glColor4fv"/>
+            <command name="glColor4i"/>
+            <command name="glColor4iv"/>
+            <command name="glColor4s"/>
+            <command name="glColor4sv"/>
+            <command name="glColor4ub"/>
+            <command name="glColor4ubv"/>
+            <command name="glColor4ui"/>
+            <command name="glColor4uiv"/>
+            <command name="glColor4us"/>
+            <command name="glColor4usv"/>
+            <command name="glEdgeFlag"/>
+            <command name="glEdgeFlagv"/>
+            <command name="glEnd"/>
+            <command name="glIndexd"/>
+            <command name="glIndexdv"/>
+            <command name="glIndexf"/>
+            <command name="glIndexfv"/>
+            <command name="glIndexi"/>
+            <command name="glIndexiv"/>
+            <command name="glIndexs"/>
+            <command name="glIndexsv"/>
+            <command name="glNormal3b"/>
+            <command name="glNormal3bv"/>
+            <command name="glNormal3d"/>
+            <command name="glNormal3dv"/>
+            <command name="glNormal3f"/>
+            <command name="glNormal3fv"/>
+            <command name="glNormal3i"/>
+            <command name="glNormal3iv"/>
+            <command name="glNormal3s"/>
+            <command name="glNormal3sv"/>
+            <command name="glRasterPos2d"/>
+            <command name="glRasterPos2dv"/>
+            <command name="glRasterPos2f"/>
+            <command name="glRasterPos2fv"/>
+            <command name="glRasterPos2i"/>
+            <command name="glRasterPos2iv"/>
+            <command name="glRasterPos2s"/>
+            <command name="glRasterPos2sv"/>
+            <command name="glRasterPos3d"/>
+            <command name="glRasterPos3dv"/>
+            <command name="glRasterPos3f"/>
+            <command name="glRasterPos3fv"/>
+            <command name="glRasterPos3i"/>
+            <command name="glRasterPos3iv"/>
+            <command name="glRasterPos3s"/>
+            <command name="glRasterPos3sv"/>
+            <command name="glRasterPos4d"/>
+            <command name="glRasterPos4dv"/>
+            <command name="glRasterPos4f"/>
+            <command name="glRasterPos4fv"/>
+            <command name="glRasterPos4i"/>
+            <command name="glRasterPos4iv"/>
+            <command name="glRasterPos4s"/>
+            <command name="glRasterPos4sv"/>
+            <command name="glRectd"/>
+            <command name="glRectdv"/>
+            <command name="glRectf"/>
+            <command name="glRectfv"/>
+            <command name="glRecti"/>
+            <command name="glRectiv"/>
+            <command name="glRects"/>
+            <command name="glRectsv"/>
+            <command name="glTexCoord1d"/>
+            <command name="glTexCoord1dv"/>
+            <command name="glTexCoord1f"/>
+            <command name="glTexCoord1fv"/>
+            <command name="glTexCoord1i"/>
+            <command name="glTexCoord1iv"/>
+            <command name="glTexCoord1s"/>
+            <command name="glTexCoord1sv"/>
+            <command name="glTexCoord2d"/>
+            <command name="glTexCoord2dv"/>
+            <command name="glTexCoord2f"/>
+            <command name="glTexCoord2fv"/>
+            <command name="glTexCoord2i"/>
+            <command name="glTexCoord2iv"/>
+            <command name="glTexCoord2s"/>
+            <command name="glTexCoord2sv"/>
+            <command name="glTexCoord3d"/>
+            <command name="glTexCoord3dv"/>
+            <command name="glTexCoord3f"/>
+            <command name="glTexCoord3fv"/>
+            <command name="glTexCoord3i"/>
+            <command name="glTexCoord3iv"/>
+            <command name="glTexCoord3s"/>
+            <command name="glTexCoord3sv"/>
+            <command name="glTexCoord4d"/>
+            <command name="glTexCoord4dv"/>
+            <command name="glTexCoord4f"/>
+            <command name="glTexCoord4fv"/>
+            <command name="glTexCoord4i"/>
+            <command name="glTexCoord4iv"/>
+            <command name="glTexCoord4s"/>
+            <command name="glTexCoord4sv"/>
+            <command name="glVertex2d"/>
+            <command name="glVertex2dv"/>
+            <command name="glVertex2f"/>
+            <command name="glVertex2fv"/>
+            <command name="glVertex2i"/>
+            <command name="glVertex2iv"/>
+            <command name="glVertex2s"/>
+            <command name="glVertex2sv"/>
+            <command name="glVertex3d"/>
+            <command name="glVertex3dv"/>
+            <command name="glVertex3f"/>
+            <command name="glVertex3fv"/>
+            <command name="glVertex3i"/>
+            <command name="glVertex3iv"/>
+            <command name="glVertex3s"/>
+            <command name="glVertex3sv"/>
+            <command name="glVertex4d"/>
+            <command name="glVertex4dv"/>
+            <command name="glVertex4f"/>
+            <command name="glVertex4fv"/>
+            <command name="glVertex4i"/>
+            <command name="glVertex4iv"/>
+            <command name="glVertex4s"/>
+            <command name="glVertex4sv"/>
+            <command name="glClipPlane"/>
+            <command name="glColorMaterial"/>
+            <command name="glFogf"/>
+            <command name="glFogfv"/>
+            <command name="glFogi"/>
+            <command name="glFogiv"/>
+            <command name="glLightf"/>
+            <command name="glLightfv"/>
+            <command name="glLighti"/>
+            <command name="glLightiv"/>
+            <command name="glLightModelf"/>
+            <command name="glLightModelfv"/>
+            <command name="glLightModeli"/>
+            <command name="glLightModeliv"/>
+            <command name="glLineStipple"/>
+            <command name="glMaterialf"/>
+            <command name="glMaterialfv"/>
+            <command name="glMateriali"/>
+            <command name="glMaterialiv"/>
+            <command name="glPolygonStipple"/>
+            <command name="glShadeModel"/>
+            <command name="glTexEnvf"/>
+            <command name="glTexEnvfv"/>
+            <command name="glTexEnvi"/>
+            <command name="glTexEnviv"/>
+            <command name="glTexGend"/>
+            <command name="glTexGendv"/>
+            <command name="glTexGenf"/>
+            <command name="glTexGenfv"/>
+            <command name="glTexGeni"/>
+            <command name="glTexGeniv"/>
+            <command name="glFeedbackBuffer"/>
+            <command name="glSelectBuffer"/>
+            <command name="glRenderMode"/>
+            <command name="glInitNames"/>
+            <command name="glLoadName"/>
+            <command name="glPassThrough"/>
+            <command name="glPopName"/>
+            <command name="glPushName"/>
+            <command name="glClearAccum"/>
+            <command name="glClearIndex"/>
+            <command name="glIndexMask"/>
+            <command name="glAccum"/>
+            <command name="glPopAttrib"/>
+            <command name="glPushAttrib"/>
+            <command name="glMap1d"/>
+            <command name="glMap1f"/>
+            <command name="glMap2d"/>
+            <command name="glMap2f"/>
+            <command name="glMapGrid1d"/>
+            <command name="glMapGrid1f"/>
+            <command name="glMapGrid2d"/>
+            <command name="glMapGrid2f"/>
+            <command name="glEvalCoord1d"/>
+            <command name="glEvalCoord1dv"/>
+            <command name="glEvalCoord1f"/>
+            <command name="glEvalCoord1fv"/>
+            <command name="glEvalCoord2d"/>
+            <command name="glEvalCoord2dv"/>
+            <command name="glEvalCoord2f"/>
+            <command name="glEvalCoord2fv"/>
+            <command name="glEvalMesh1"/>
+            <command name="glEvalPoint1"/>
+            <command name="glEvalMesh2"/>
+            <command name="glEvalPoint2"/>
+            <command name="glAlphaFunc"/>
+            <command name="glPixelZoom"/>
+            <command name="glPixelTransferf"/>
+            <command name="glPixelTransferi"/>
+            <command name="glPixelMapfv"/>
+            <command name="glPixelMapuiv"/>
+            <command name="glPixelMapusv"/>
+            <command name="glCopyPixels"/>
+            <command name="glDrawPixels"/>
+            <command name="glGetClipPlane"/>
+            <command name="glGetLightfv"/>
+            <command name="glGetLightiv"/>
+            <command name="glGetMapdv"/>
+            <command name="glGetMapfv"/>
+            <command name="glGetMapiv"/>
+            <command name="glGetMaterialfv"/>
+            <command name="glGetMaterialiv"/>
+            <command name="glGetPixelMapfv"/>
+            <command name="glGetPixelMapuiv"/>
+            <command name="glGetPixelMapusv"/>
+            <command name="glGetPolygonStipple"/>
+            <command name="glGetTexEnvfv"/>
+            <command name="glGetTexEnviv"/>
+            <command name="glGetTexGendv"/>
+            <command name="glGetTexGenfv"/>
+            <command name="glGetTexGeniv"/>
+            <command name="glIsList"/>
+            <command name="glFrustum"/>
+            <command name="glLoadIdentity"/>
+            <command name="glLoadMatrixf"/>
+            <command name="glLoadMatrixd"/>
+            <command name="glMatrixMode"/>
+            <command name="glMultMatrixf"/>
+            <command name="glMultMatrixd"/>
+            <command name="glOrtho"/>
+            <command name="glPopMatrix"/>
+            <command name="glPushMatrix"/>
+            <command name="glRotated"/>
+            <command name="glRotatef"/>
+            <command name="glScaled"/>
+            <command name="glScalef"/>
+            <command name="glTranslated"/>
+            <command name="glTranslatef"/>
+        </remove>
+        <remove profile="core" comment="Compatibility-only GL 1.1 features removed from GL 3.2">
+            <enum name="GL_CURRENT_BIT"/>
+            <enum name="GL_POINT_BIT"/>
+            <enum name="GL_LINE_BIT"/>
+            <enum name="GL_POLYGON_BIT"/>
+            <enum name="GL_POLYGON_STIPPLE_BIT"/>
+            <enum name="GL_PIXEL_MODE_BIT"/>
+            <enum name="GL_LIGHTING_BIT"/>
+            <enum name="GL_FOG_BIT"/>
+            <enum name="GL_ACCUM_BUFFER_BIT"/>
+            <enum name="GL_VIEWPORT_BIT"/>
+            <enum name="GL_TRANSFORM_BIT"/>
+            <enum name="GL_ENABLE_BIT"/>
+            <enum name="GL_HINT_BIT"/>
+            <enum name="GL_EVAL_BIT"/>
+            <enum name="GL_LIST_BIT"/>
+            <enum name="GL_TEXTURE_BIT"/>
+            <enum name="GL_SCISSOR_BIT"/>
+            <enum name="GL_ALL_ATTRIB_BITS"/>
+            <enum name="GL_CLIENT_PIXEL_STORE_BIT"/>
+            <enum name="GL_CLIENT_VERTEX_ARRAY_BIT"/>
+            <enum name="GL_CLIENT_ALL_ATTRIB_BITS"/>
+            <enum name="GL_QUAD_STRIP"/>
+            <enum name="GL_QUADS"/>
+            <enum name="GL_POLYGON"/>
+            <enum name="GL_ACCUM"/>
+            <enum name="GL_LOAD"/>
+            <enum name="GL_RETURN"/>
+            <enum name="GL_MULT"/>
+            <enum name="GL_ADD"/>
+            <enum name="GL_STACK_OVERFLOW"/>
+            <enum name="GL_STACK_UNDERFLOW"/>
+            <enum name="GL_AUX0"/>
+            <enum name="GL_AUX1"/>
+            <enum name="GL_AUX2"/>
+            <enum name="GL_AUX3"/>
+            <enum name="GL_2D"/>
+            <enum name="GL_3D"/>
+            <enum name="GL_3D_COLOR"/>
+            <enum name="GL_3D_COLOR_TEXTURE"/>
+            <enum name="GL_4D_COLOR_TEXTURE"/>
+            <enum name="GL_PASS_THROUGH_TOKEN"/>
+            <enum name="GL_POINT_TOKEN"/>
+            <enum name="GL_LINE_TOKEN"/>
+            <enum name="GL_POLYGON_TOKEN"/>
+            <enum name="GL_BITMAP_TOKEN"/>
+            <enum name="GL_DRAW_PIXEL_TOKEN"/>
+            <enum name="GL_COPY_PIXEL_TOKEN"/>
+            <enum name="GL_LINE_RESET_TOKEN"/>
+            <enum name="GL_EXP"/>
+            <enum name="GL_EXP2"/>
+            <enum name="GL_COEFF"/>
+            <enum name="GL_ORDER"/>
+            <enum name="GL_DOMAIN"/>
+            <enum name="GL_PIXEL_MAP_I_TO_I"/>
+            <enum name="GL_PIXEL_MAP_S_TO_S"/>
+            <enum name="GL_PIXEL_MAP_I_TO_R"/>
+            <enum name="GL_PIXEL_MAP_I_TO_G"/>
+            <enum name="GL_PIXEL_MAP_I_TO_B"/>
+            <enum name="GL_PIXEL_MAP_I_TO_A"/>
+            <enum name="GL_PIXEL_MAP_R_TO_R"/>
+            <enum name="GL_PIXEL_MAP_G_TO_G"/>
+            <enum name="GL_PIXEL_MAP_B_TO_B"/>
+            <enum name="GL_PIXEL_MAP_A_TO_A"/>
+            <enum name="GL_VERTEX_ARRAY_POINTER"/>
+            <enum name="GL_NORMAL_ARRAY_POINTER"/>
+            <enum name="GL_COLOR_ARRAY_POINTER"/>
+            <enum name="GL_INDEX_ARRAY_POINTER"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_POINTER"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_POINTER"/>
+            <enum name="GL_FEEDBACK_BUFFER_POINTER"/>
+            <enum name="GL_SELECTION_BUFFER_POINTER"/>
+            <enum name="GL_CURRENT_COLOR"/>
+            <enum name="GL_CURRENT_INDEX"/>
+            <enum name="GL_CURRENT_NORMAL"/>
+            <enum name="GL_CURRENT_TEXTURE_COORDS"/>
+            <enum name="GL_CURRENT_RASTER_COLOR"/>
+            <enum name="GL_CURRENT_RASTER_INDEX"/>
+            <enum name="GL_CURRENT_RASTER_TEXTURE_COORDS"/>
+            <enum name="GL_CURRENT_RASTER_POSITION"/>
+            <enum name="GL_CURRENT_RASTER_POSITION_VALID"/>
+            <enum name="GL_CURRENT_RASTER_DISTANCE"/>
+            <enum name="GL_POINT_SMOOTH"/>
+            <enum name="GL_LINE_STIPPLE"/>
+            <enum name="GL_LINE_STIPPLE_PATTERN"/>
+            <enum name="GL_LINE_STIPPLE_REPEAT"/>
+            <enum name="GL_LIST_MODE"/>
+            <enum name="GL_MAX_LIST_NESTING"/>
+            <enum name="GL_LIST_BASE"/>
+            <enum name="GL_LIST_INDEX"/>
+            <enum name="GL_POLYGON_STIPPLE"/>
+            <enum name="GL_EDGE_FLAG"/>
+            <enum name="GL_LIGHTING"/>
+            <enum name="GL_LIGHT_MODEL_LOCAL_VIEWER"/>
+            <enum name="GL_LIGHT_MODEL_TWO_SIDE"/>
+            <enum name="GL_LIGHT_MODEL_AMBIENT"/>
+            <enum name="GL_SHADE_MODEL"/>
+            <enum name="GL_COLOR_MATERIAL_FACE"/>
+            <enum name="GL_COLOR_MATERIAL_PARAMETER"/>
+            <enum name="GL_COLOR_MATERIAL"/>
+            <enum name="GL_FOG"/>
+            <enum name="GL_FOG_INDEX"/>
+            <enum name="GL_FOG_DENSITY"/>
+            <enum name="GL_FOG_START"/>
+            <enum name="GL_FOG_END"/>
+            <enum name="GL_FOG_MODE"/>
+            <enum name="GL_FOG_COLOR"/>
+            <enum name="GL_ACCUM_CLEAR_VALUE"/>
+            <enum name="GL_MATRIX_MODE"/>
+            <enum name="GL_NORMALIZE"/>
+            <enum name="GL_MODELVIEW_STACK_DEPTH"/>
+            <enum name="GL_PROJECTION_STACK_DEPTH"/>
+            <enum name="GL_TEXTURE_STACK_DEPTH"/>
+            <enum name="GL_MODELVIEW_MATRIX"/>
+            <enum name="GL_PROJECTION_MATRIX"/>
+            <enum name="GL_TEXTURE_MATRIX"/>
+            <enum name="GL_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_CLIENT_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_ALPHA_TEST"/>
+            <enum name="GL_ALPHA_TEST_FUNC"/>
+            <enum name="GL_ALPHA_TEST_REF"/>
+            <enum name="GL_INDEX_LOGIC_OP"/>
+            <enum name="GL_LOGIC_OP"/>
+            <enum name="GL_AUX_BUFFERS"/>
+            <enum name="GL_INDEX_CLEAR_VALUE"/>
+            <enum name="GL_INDEX_WRITEMASK"/>
+            <enum name="GL_INDEX_MODE"/>
+            <enum name="GL_RGBA_MODE"/>
+            <enum name="GL_RENDER_MODE"/>
+            <enum name="GL_PERSPECTIVE_CORRECTION_HINT"/>
+            <enum name="GL_POINT_SMOOTH_HINT"/>
+            <enum name="GL_FOG_HINT"/>
+            <enum name="GL_TEXTURE_GEN_S"/>
+            <enum name="GL_TEXTURE_GEN_T"/>
+            <enum name="GL_TEXTURE_GEN_R"/>
+            <enum name="GL_TEXTURE_GEN_Q"/>
+            <enum name="GL_PIXEL_MAP_I_TO_I_SIZE"/>
+            <enum name="GL_PIXEL_MAP_S_TO_S_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_R_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_G_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_B_SIZE"/>
+            <enum name="GL_PIXEL_MAP_I_TO_A_SIZE"/>
+            <enum name="GL_PIXEL_MAP_R_TO_R_SIZE"/>
+            <enum name="GL_PIXEL_MAP_G_TO_G_SIZE"/>
+            <enum name="GL_PIXEL_MAP_B_TO_B_SIZE"/>
+            <enum name="GL_PIXEL_MAP_A_TO_A_SIZE"/>
+            <enum name="GL_MAP_COLOR"/>
+            <enum name="GL_MAP_STENCIL"/>
+            <enum name="GL_INDEX_SHIFT"/>
+            <enum name="GL_INDEX_OFFSET"/>
+            <enum name="GL_RED_SCALE"/>
+            <enum name="GL_RED_BIAS"/>
+            <enum name="GL_ZOOM_X"/>
+            <enum name="GL_ZOOM_Y"/>
+            <enum name="GL_GREEN_SCALE"/>
+            <enum name="GL_GREEN_BIAS"/>
+            <enum name="GL_BLUE_SCALE"/>
+            <enum name="GL_BLUE_BIAS"/>
+            <enum name="GL_ALPHA_SCALE"/>
+            <enum name="GL_ALPHA_BIAS"/>
+            <enum name="GL_DEPTH_SCALE"/>
+            <enum name="GL_DEPTH_BIAS"/>
+            <enum name="GL_MAX_EVAL_ORDER"/>
+            <enum name="GL_MAX_LIGHTS"/>
+            <enum name="GL_MAX_CLIP_PLANES"/>
+            <enum name="GL_MAX_PIXEL_MAP_TABLE"/>
+            <enum name="GL_MAX_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_MAX_MODELVIEW_STACK_DEPTH"/>
+            <enum name="GL_MAX_NAME_STACK_DEPTH"/>
+            <enum name="GL_MAX_PROJECTION_STACK_DEPTH"/>
+            <enum name="GL_MAX_TEXTURE_STACK_DEPTH"/>
+            <enum name="GL_MAX_CLIENT_ATTRIB_STACK_DEPTH"/>
+            <enum name="GL_INDEX_BITS"/>
+            <enum name="GL_RED_BITS"/>
+            <enum name="GL_GREEN_BITS"/>
+            <enum name="GL_BLUE_BITS"/>
+            <enum name="GL_ALPHA_BITS"/>
+            <enum name="GL_DEPTH_BITS"/>
+            <enum name="GL_STENCIL_BITS"/>
+            <enum name="GL_ACCUM_RED_BITS"/>
+            <enum name="GL_ACCUM_GREEN_BITS"/>
+            <enum name="GL_ACCUM_BLUE_BITS"/>
+            <enum name="GL_ACCUM_ALPHA_BITS"/>
+            <enum name="GL_NAME_STACK_DEPTH"/>
+            <enum name="GL_AUTO_NORMAL"/>
+            <enum name="GL_MAP1_COLOR_4"/>
+            <enum name="GL_MAP1_INDEX"/>
+            <enum name="GL_MAP1_NORMAL"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP1_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP1_VERTEX_3"/>
+            <enum name="GL_MAP1_VERTEX_4"/>
+            <enum name="GL_MAP2_COLOR_4"/>
+            <enum name="GL_MAP2_INDEX"/>
+            <enum name="GL_MAP2_NORMAL"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_1"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_2"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_3"/>
+            <enum name="GL_MAP2_TEXTURE_COORD_4"/>
+            <enum name="GL_MAP2_VERTEX_3"/>
+            <enum name="GL_MAP2_VERTEX_4"/>
+            <enum name="GL_MAP1_GRID_DOMAIN"/>
+            <enum name="GL_MAP1_GRID_SEGMENTS"/>
+            <enum name="GL_MAP2_GRID_DOMAIN"/>
+            <enum name="GL_MAP2_GRID_SEGMENTS"/>
+            <enum name="GL_FEEDBACK_BUFFER_SIZE"/>
+            <enum name="GL_FEEDBACK_BUFFER_TYPE"/>
+            <enum name="GL_SELECTION_BUFFER_SIZE"/>
+            <enum name="GL_VERTEX_ARRAY"/>
+            <enum name="GL_NORMAL_ARRAY"/>
+            <enum name="GL_COLOR_ARRAY"/>
+            <enum name="GL_INDEX_ARRAY"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY"/>
+            <enum name="GL_EDGE_FLAG_ARRAY"/>
+            <enum name="GL_VERTEX_ARRAY_SIZE"/>
+            <enum name="GL_VERTEX_ARRAY_TYPE"/>
+            <enum name="GL_VERTEX_ARRAY_STRIDE"/>
+            <enum name="GL_NORMAL_ARRAY_TYPE"/>
+            <enum name="GL_NORMAL_ARRAY_STRIDE"/>
+            <enum name="GL_COLOR_ARRAY_SIZE"/>
+            <enum name="GL_COLOR_ARRAY_TYPE"/>
+            <enum name="GL_COLOR_ARRAY_STRIDE"/>
+            <enum name="GL_INDEX_ARRAY_TYPE"/>
+            <enum name="GL_INDEX_ARRAY_STRIDE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_SIZE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_TYPE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_STRIDE"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_STRIDE"/>
+            <enum name="GL_TEXTURE_COMPONENTS"/>
+            <enum name="GL_TEXTURE_BORDER"/>
+            <enum name="GL_TEXTURE_LUMINANCE_SIZE"/>
+            <enum name="GL_TEXTURE_INTENSITY_SIZE"/>
+            <enum name="GL_TEXTURE_PRIORITY"/>
+            <enum name="GL_TEXTURE_RESIDENT"/>
+            <enum name="GL_AMBIENT"/>
+            <enum name="GL_DIFFUSE"/>
+            <enum name="GL_SPECULAR"/>
+            <enum name="GL_POSITION"/>
+            <enum name="GL_SPOT_DIRECTION"/>
+            <enum name="GL_SPOT_EXPONENT"/>
+            <enum name="GL_SPOT_CUTOFF"/>
+            <enum name="GL_CONSTANT_ATTENUATION"/>
+            <enum name="GL_LINEAR_ATTENUATION"/>
+            <enum name="GL_QUADRATIC_ATTENUATION"/>
+            <enum name="GL_COMPILE"/>
+            <enum name="GL_COMPILE_AND_EXECUTE"/>
+            <enum name="GL_2_BYTES"/>
+            <enum name="GL_3_BYTES"/>
+            <enum name="GL_4_BYTES"/>
+            <enum name="GL_EMISSION"/>
+            <enum name="GL_SHININESS"/>
+            <enum name="GL_AMBIENT_AND_DIFFUSE"/>
+            <enum name="GL_COLOR_INDEXES"/>
+            <enum name="GL_MODELVIEW"/>
+            <enum name="GL_PROJECTION"/>
+            <enum name="GL_COLOR_INDEX"/>
+            <enum name="GL_LUMINANCE"/>
+            <enum name="GL_LUMINANCE_ALPHA"/>
+            <enum name="GL_BITMAP"/>
+            <enum name="GL_RENDER"/>
+            <enum name="GL_FEEDBACK"/>
+            <enum name="GL_SELECT"/>
+            <enum name="GL_FLAT"/>
+            <enum name="GL_SMOOTH"/>
+            <enum name="GL_S"/>
+            <enum name="GL_T"/>
+            <enum name="GL_R"/>
+            <enum name="GL_Q"/>
+            <enum name="GL_MODULATE"/>
+            <enum name="GL_DECAL"/>
+            <enum name="GL_TEXTURE_ENV_MODE"/>
+            <enum name="GL_TEXTURE_ENV_COLOR"/>
+            <enum name="GL_TEXTURE_ENV"/>
+            <enum name="GL_EYE_LINEAR"/>
+            <enum name="GL_OBJECT_LINEAR"/>
+            <enum name="GL_SPHERE_MAP"/>
+            <enum name="GL_TEXTURE_GEN_MODE"/>
+            <enum name="GL_OBJECT_PLANE"/>
+            <enum name="GL_EYE_PLANE"/>
+            <enum name="GL_CLAMP"/>
+            <enum name="GL_ALPHA4"/>
+            <enum name="GL_ALPHA8"/>
+            <enum name="GL_ALPHA12"/>
+            <enum name="GL_ALPHA16"/>
+            <enum name="GL_LUMINANCE4"/>
+            <enum name="GL_LUMINANCE8"/>
+            <enum name="GL_LUMINANCE12"/>
+            <enum name="GL_LUMINANCE16"/>
+            <enum name="GL_LUMINANCE4_ALPHA4"/>
+            <enum name="GL_LUMINANCE6_ALPHA2"/>
+            <enum name="GL_LUMINANCE8_ALPHA8"/>
+            <enum name="GL_LUMINANCE12_ALPHA4"/>
+            <enum name="GL_LUMINANCE12_ALPHA12"/>
+            <enum name="GL_LUMINANCE16_ALPHA16"/>
+            <enum name="GL_INTENSITY"/>
+            <enum name="GL_INTENSITY4"/>
+            <enum name="GL_INTENSITY8"/>
+            <enum name="GL_INTENSITY12"/>
+            <enum name="GL_INTENSITY16"/>
+            <enum name="GL_V2F"/>
+            <enum name="GL_V3F"/>
+            <enum name="GL_C4UB_V2F"/>
+            <enum name="GL_C4UB_V3F"/>
+            <enum name="GL_C3F_V3F"/>
+            <enum name="GL_N3F_V3F"/>
+            <enum name="GL_C4F_N3F_V3F"/>
+            <enum name="GL_T2F_V3F"/>
+            <enum name="GL_T4F_V4F"/>
+            <enum name="GL_T2F_C4UB_V3F"/>
+            <enum name="GL_T2F_C3F_V3F"/>
+            <enum name="GL_T2F_N3F_V3F"/>
+            <enum name="GL_T2F_C4F_N3F_V3F"/>
+            <enum name="GL_T4F_C4F_N3F_V4F"/>
+            <enum name="GL_CLIP_PLANE0"/>
+            <enum name="GL_CLIP_PLANE1"/>
+            <enum name="GL_CLIP_PLANE2"/>
+            <enum name="GL_CLIP_PLANE3"/>
+            <enum name="GL_CLIP_PLANE4"/>
+            <enum name="GL_CLIP_PLANE5"/>
+            <enum name="GL_LIGHT0"/>
+            <enum name="GL_LIGHT1"/>
+            <enum name="GL_LIGHT2"/>
+            <enum name="GL_LIGHT3"/>
+            <enum name="GL_LIGHT4"/>
+            <enum name="GL_LIGHT5"/>
+            <enum name="GL_LIGHT6"/>
+            <enum name="GL_LIGHT7"/>
+            <command name="glArrayElement"/>
+            <command name="glColorPointer"/>
+            <command name="glDisableClientState"/>
+            <command name="glEdgeFlagPointer"/>
+            <command name="glEnableClientState"/>
+            <command name="glIndexPointer"/>
+            <command name="glGetPointerv"/>
+            <command name="glInterleavedArrays"/>
+            <command name="glNormalPointer"/>
+            <command name="glTexCoordPointer"/>
+            <command name="glVertexPointer"/>
+            <command name="glAreTexturesResident"/>
+            <command name="glPrioritizeTextures"/>
+            <command name="glIndexub"/>
+            <command name="glIndexubv"/>
+            <command name="glPopClientAttrib"/>
+            <command name="glPushClientAttrib"/>
+        </remove>
+        <remove profile="core" comment="Compatibility-only GL 1.2 features removed from GL 3.2">
+            <enum name="GL_RESCALE_NORMAL"/>
+            <enum name="GL_LIGHT_MODEL_COLOR_CONTROL"/>
+            <enum name="GL_SINGLE_COLOR"/>
+            <enum name="GL_SEPARATE_SPECULAR_COLOR"/>
+            <enum name="GL_ALIASED_POINT_SIZE_RANGE"/>
+        </remove>
+        <remove profile="core" comment="Compatibility-only GL 1.3 features removed from GL 3.2">
+            <enum name="GL_CLIENT_ACTIVE_TEXTURE"/>
+            <enum name="GL_MAX_TEXTURE_UNITS"/>
+            <enum name="GL_TRANSPOSE_MODELVIEW_MATRIX"/>
+            <enum name="GL_TRANSPOSE_PROJECTION_MATRIX"/>
+            <enum name="GL_TRANSPOSE_TEXTURE_MATRIX"/>
+            <enum name="GL_TRANSPOSE_COLOR_MATRIX"/>
+            <enum name="GL_MULTISAMPLE_BIT"/>
+            <enum name="GL_NORMAL_MAP"/>
+            <enum name="GL_REFLECTION_MAP"/>
+            <enum name="GL_COMPRESSED_ALPHA"/>
+            <enum name="GL_COMPRESSED_LUMINANCE"/>
+            <enum name="GL_COMPRESSED_LUMINANCE_ALPHA"/>
+            <enum name="GL_COMPRESSED_INTENSITY"/>
+            <enum name="GL_COMBINE"/>
+            <enum name="GL_COMBINE_RGB"/>
+            <enum name="GL_COMBINE_ALPHA"/>
+            <enum name="GL_SOURCE0_RGB"/>
+            <enum name="GL_SOURCE1_RGB"/>
+            <enum name="GL_SOURCE2_RGB"/>
+            <enum name="GL_SOURCE0_ALPHA"/>
+            <enum name="GL_SOURCE1_ALPHA"/>
+            <enum name="GL_SOURCE2_ALPHA"/>
+            <enum name="GL_OPERAND0_RGB"/>
+            <enum name="GL_OPERAND1_RGB"/>
+            <enum name="GL_OPERAND2_RGB"/>
+            <enum name="GL_OPERAND0_ALPHA"/>
+            <enum name="GL_OPERAND1_ALPHA"/>
+            <enum name="GL_OPERAND2_ALPHA"/>
+            <enum name="GL_RGB_SCALE"/>
+            <enum name="GL_ADD_SIGNED"/>
+            <enum name="GL_INTERPOLATE"/>
+            <enum name="GL_SUBTRACT"/>
+            <enum name="GL_CONSTANT"/>
+            <enum name="GL_PRIMARY_COLOR"/>
+            <enum name="GL_PREVIOUS"/>
+            <enum name="GL_DOT3_RGB"/>
+            <enum name="GL_DOT3_RGBA"/>
+            <command name="glClientActiveTexture"/>
+            <command name="glMultiTexCoord1d"/>
+            <command name="glMultiTexCoord1dv"/>
+            <command name="glMultiTexCoord1f"/>
+            <command name="glMultiTexCoord1fv"/>
+            <command name="glMultiTexCoord1i"/>
+            <command name="glMultiTexCoord1iv"/>
+            <command name="glMultiTexCoord1s"/>
+            <command name="glMultiTexCoord1sv"/>
+            <command name="glMultiTexCoord2d"/>
+            <command name="glMultiTexCoord2dv"/>
+            <command name="glMultiTexCoord2f"/>
+            <command name="glMultiTexCoord2fv"/>
+            <command name="glMultiTexCoord2i"/>
+            <command name="glMultiTexCoord2iv"/>
+            <command name="glMultiTexCoord2s"/>
+            <command name="glMultiTexCoord2sv"/>
+            <command name="glMultiTexCoord3d"/>
+            <command name="glMultiTexCoord3dv"/>
+            <command name="glMultiTexCoord3f"/>
+            <command name="glMultiTexCoord3fv"/>
+            <command name="glMultiTexCoord3i"/>
+            <command name="glMultiTexCoord3iv"/>
+            <command name="glMultiTexCoord3s"/>
+            <command name="glMultiTexCoord3sv"/>
+            <command name="glMultiTexCoord4d"/>
+            <command name="glMultiTexCoord4dv"/>
+            <command name="glMultiTexCoord4f"/>
+            <command name="glMultiTexCoord4fv"/>
+            <command name="glMultiTexCoord4i"/>
+            <command name="glMultiTexCoord4iv"/>
+            <command name="glMultiTexCoord4s"/>
+            <command name="glMultiTexCoord4sv"/>
+            <command name="glLoadTransposeMatrixf"/>
+            <command name="glLoadTransposeMatrixd"/>
+            <command name="glMultTransposeMatrixf"/>
+            <command name="glMultTransposeMatrixd"/>
+        </remove>
+        <remove profile="core" comment="Compatibility-only GL 1.4 features removed from GL 3.2">
+            <enum name="GL_POINT_SIZE_MIN"/>
+            <enum name="GL_POINT_SIZE_MAX"/>
+            <enum name="GL_POINT_DISTANCE_ATTENUATION"/>
+            <enum name="GL_GENERATE_MIPMAP"/>
+            <enum name="GL_GENERATE_MIPMAP_HINT"/>
+            <enum name="GL_FOG_COORDINATE_SOURCE"/>
+            <enum name="GL_FOG_COORDINATE"/>
+            <enum name="GL_FRAGMENT_DEPTH"/>
+            <enum name="GL_CURRENT_FOG_COORDINATE"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY_TYPE"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY_STRIDE"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY_POINTER"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY"/>
+            <enum name="GL_COLOR_SUM"/>
+            <enum name="GL_CURRENT_SECONDARY_COLOR"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_SIZE"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_TYPE"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_STRIDE"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_POINTER"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY"/>
+            <enum name="GL_TEXTURE_FILTER_CONTROL"/>
+            <enum name="GL_DEPTH_TEXTURE_MODE"/>
+            <enum name="GL_COMPARE_R_TO_TEXTURE"/>
+            <command name="glFogCoordf"/>
+            <command name="glFogCoordfv"/>
+            <command name="glFogCoordd"/>
+            <command name="glFogCoorddv"/>
+            <command name="glFogCoordPointer"/>
+            <command name="glSecondaryColor3b"/>
+            <command name="glSecondaryColor3bv"/>
+            <command name="glSecondaryColor3d"/>
+            <command name="glSecondaryColor3dv"/>
+            <command name="glSecondaryColor3f"/>
+            <command name="glSecondaryColor3fv"/>
+            <command name="glSecondaryColor3i"/>
+            <command name="glSecondaryColor3iv"/>
+            <command name="glSecondaryColor3s"/>
+            <command name="glSecondaryColor3sv"/>
+            <command name="glSecondaryColor3ub"/>
+            <command name="glSecondaryColor3ubv"/>
+            <command name="glSecondaryColor3ui"/>
+            <command name="glSecondaryColor3uiv"/>
+            <command name="glSecondaryColor3us"/>
+            <command name="glSecondaryColor3usv"/>
+            <command name="glSecondaryColorPointer"/>
+            <command name="glWindowPos2d"/>
+            <command name="glWindowPos2dv"/>
+            <command name="glWindowPos2f"/>
+            <command name="glWindowPos2fv"/>
+            <command name="glWindowPos2i"/>
+            <command name="glWindowPos2iv"/>
+            <command name="glWindowPos2s"/>
+            <command name="glWindowPos2sv"/>
+            <command name="glWindowPos3d"/>
+            <command name="glWindowPos3dv"/>
+            <command name="glWindowPos3f"/>
+            <command name="glWindowPos3fv"/>
+            <command name="glWindowPos3i"/>
+            <command name="glWindowPos3iv"/>
+            <command name="glWindowPos3s"/>
+            <command name="glWindowPos3sv"/>
+        </remove>
+        <remove profile="core" comment="Compatibility-only GL 1.5 features removed from GL 3.2">
+            <enum name="GL_VERTEX_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_NORMAL_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_COLOR_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_INDEX_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_EDGE_FLAG_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_WEIGHT_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_FOG_COORD_SRC"/>
+            <enum name="GL_FOG_COORD"/>
+            <enum name="GL_CURRENT_FOG_COORD"/>
+            <enum name="GL_FOG_COORD_ARRAY_TYPE"/>
+            <enum name="GL_FOG_COORD_ARRAY_STRIDE"/>
+            <enum name="GL_FOG_COORD_ARRAY_POINTER"/>
+            <enum name="GL_FOG_COORD_ARRAY"/>
+            <enum name="GL_FOG_COORD_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_SRC0_RGB"/>
+            <enum name="GL_SRC1_RGB"/>
+            <enum name="GL_SRC2_RGB"/>
+            <enum name="GL_SRC0_ALPHA"/>
+            <enum name="GL_SRC2_ALPHA"/>
+        </remove>
+        <remove profile="core" comment="Compatibility-only GL 2.0 features removed from GL 3.2">
+            <enum name="GL_VERTEX_PROGRAM_TWO_SIDE"/>
+            <enum name="GL_POINT_SPRITE"/>
+            <enum name="GL_COORD_REPLACE"/>
+            <enum name="GL_MAX_TEXTURE_COORDS"/>
+        </remove>
+        <remove profile="core" comment="Compatibility-only GL 2.1 features removed from GL 3.2">
+            <enum name="GL_CURRENT_RASTER_SECONDARY_COLOR"/>
+            <enum name="GL_SLUMINANCE_ALPHA"/>
+            <enum name="GL_SLUMINANCE8_ALPHA8"/>
+            <enum name="GL_SLUMINANCE"/>
+            <enum name="GL_SLUMINANCE8"/>
+            <enum name="GL_COMPRESSED_SLUMINANCE"/>
+            <enum name="GL_COMPRESSED_SLUMINANCE_ALPHA"/>
+        </remove>
+        <remove profile="core" comment="Compatibility-only GL 3.0 features removed from GL 3.2">
+            <enum name="GL_CLAMP_VERTEX_COLOR"/>
+            <enum name="GL_CLAMP_FRAGMENT_COLOR"/>
+            <enum name="GL_ALPHA_INTEGER"/>
+            <enum name="GL_TEXTURE_LUMINANCE_TYPE"/>
+            <enum name="GL_TEXTURE_INTENSITY_TYPE"/>
+        </remove>
+        <!-- Deprecated (not removed) in OpenGL 3.2 core;
+             deprecate tag not defined/supported yet
+          <deprecate profile="core">
+            <enum name="GL_MAX_VARYING_FLOATS"/>
+            <enum name="GL_MAX_VARYING_COMPONENTS"/>
+          </deprecate>
+        -->
+    </feature>
+    <feature api="gl" name="GL_VERSION_3_3" number="3.3">
+        <require>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR"/>
+        </require>
+        <require comment="Reuse ARB_blend_func_extended">
+            <enum name="GL_SRC1_COLOR"/>
+            <enum name="GL_ONE_MINUS_SRC1_COLOR"/>
+            <enum name="GL_ONE_MINUS_SRC1_ALPHA"/>
+            <enum name="GL_MAX_DUAL_SOURCE_DRAW_BUFFERS"/>
+            <command name="glBindFragDataLocationIndexed"/>
+            <command name="glGetFragDataIndex"/>
+        </require>
+        <require comment="Reuse ARB_explicit_attrib_location (none)">
+        </require>
+        <require comment="Reuse ARB_occlusion_query2">
+            <enum name="GL_ANY_SAMPLES_PASSED"/>
+        </require>
+        <require comment="Reuse ARB_sampler_objects">
+            <enum name="GL_SAMPLER_BINDING"/>
+            <command name="glGenSamplers"/>
+            <command name="glDeleteSamplers"/>
+            <command name="glIsSampler"/>
+            <command name="glBindSampler"/>
+            <command name="glSamplerParameteri"/>
+            <command name="glSamplerParameteriv"/>
+            <command name="glSamplerParameterf"/>
+            <command name="glSamplerParameterfv"/>
+            <command name="glSamplerParameterIiv"/>
+            <command name="glSamplerParameterIuiv"/>
+            <command name="glGetSamplerParameteriv"/>
+            <command name="glGetSamplerParameterIiv"/>
+            <command name="glGetSamplerParameterfv"/>
+            <command name="glGetSamplerParameterIuiv"/>
+        </require>
+        <require comment="Reuse ARB_shader_bit_encoding (none)">
+        </require>
+        <require comment="Reuse ARB_texture_rgb10_a2ui">
+            <enum name="GL_RGB10_A2UI"/>
+        </require>
+        <require comment="Reuse ARB_texture_swizzle">
+            <enum name="GL_TEXTURE_SWIZZLE_R"/>
+            <enum name="GL_TEXTURE_SWIZZLE_G"/>
+            <enum name="GL_TEXTURE_SWIZZLE_B"/>
+            <enum name="GL_TEXTURE_SWIZZLE_A"/>
+            <enum name="GL_TEXTURE_SWIZZLE_RGBA"/>
+        </require>
+        <require comment="Reuse ARB_timer_query">
+            <enum name="GL_TIME_ELAPSED"/>
+            <enum name="GL_TIMESTAMP"/>
+            <command name="glQueryCounter"/>
+            <command name="glGetQueryObjecti64v"/>
+            <command name="glGetQueryObjectui64v"/>
+        </require>
+        <require comment="Reuse ARB_vertex_type_2_10_10_10_rev">
+            <enum name="GL_INT_2_10_10_10_REV"/>
+            <command name="glVertexAttribDivisor"/>
+            <command name="glVertexAttribP1ui"/>
+            <command name="glVertexAttribP1uiv"/>
+            <command name="glVertexAttribP2ui"/>
+            <command name="glVertexAttribP2uiv"/>
+            <command name="glVertexAttribP3ui"/>
+            <command name="glVertexAttribP3uiv"/>
+            <command name="glVertexAttribP4ui"/>
+            <command name="glVertexAttribP4uiv"/>
+        </require>
+        <require profile="compatibility" comment="Reuse ARB_vertex_type_2_10_10_10_rev compatibility profile">
+            <command name="glVertexP2ui"/>
+            <command name="glVertexP2uiv"/>
+            <command name="glVertexP3ui"/>
+            <command name="glVertexP3uiv"/>
+            <command name="glVertexP4ui"/>
+            <command name="glVertexP4uiv"/>
+            <command name="glTexCoordP1ui"/>
+            <command name="glTexCoordP1uiv"/>
+            <command name="glTexCoordP2ui"/>
+            <command name="glTexCoordP2uiv"/>
+            <command name="glTexCoordP3ui"/>
+            <command name="glTexCoordP3uiv"/>
+            <command name="glTexCoordP4ui"/>
+            <command name="glTexCoordP4uiv"/>
+            <command name="glMultiTexCoordP1ui"/>
+            <command name="glMultiTexCoordP1uiv"/>
+            <command name="glMultiTexCoordP2ui"/>
+            <command name="glMultiTexCoordP2uiv"/>
+            <command name="glMultiTexCoordP3ui"/>
+            <command name="glMultiTexCoordP3uiv"/>
+            <command name="glMultiTexCoordP4ui"/>
+            <command name="glMultiTexCoordP4uiv"/>
+            <command name="glNormalP3ui"/>
+            <command name="glNormalP3uiv"/>
+            <command name="glColorP3ui"/>
+            <command name="glColorP3uiv"/>
+            <command name="glColorP4ui"/>
+            <command name="glColorP4uiv"/>
+            <command name="glSecondaryColorP3ui"/>
+            <command name="glSecondaryColorP3uiv"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_4_0" number="4.0">
+        <require>
+            <enum name="GL_SAMPLE_SHADING"/>
+            <enum name="GL_MIN_SAMPLE_SHADING_VALUE"/>
+            <enum name="GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET"/>
+            <enum name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"/>
+            <enum name="GL_PROXY_TEXTURE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_SAMPLER_CUBE_MAP_ARRAY"/>
+            <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW"/>
+            <enum name="GL_INT_SAMPLER_CUBE_MAP_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY"/>
+            <command name="glMinSampleShading"/>
+            <command name="glBlendEquationi"/>
+            <command name="glBlendEquationSeparatei"/>
+            <command name="glBlendFunci"/>
+            <command name="glBlendFuncSeparatei"/>
+        </require>
+        <require comment="Reuse ARB_draw_buffers_blend (none)">
+        </require>
+        <require comment="Reuse ARB_draw_indirect">
+            <enum name="GL_DRAW_INDIRECT_BUFFER"/>
+            <enum name="GL_DRAW_INDIRECT_BUFFER_BINDING"/>
+            <command name="glDrawArraysIndirect"/>
+            <command name="glDrawElementsIndirect"/>
+        </require>
+        <require comment="Reuse ARB_gpu_shader5">
+            <enum name="GL_GEOMETRY_SHADER_INVOCATIONS"/>
+            <enum name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS"/>
+            <enum name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET"/>
+            <enum name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET"/>
+            <enum name="GL_FRAGMENT_INTERPOLATION_OFFSET_BITS"/>
+            <enum name="GL_MAX_VERTEX_STREAMS"/>
+        </require>
+        <require comment="Reuse ARB_gpu_shader_fp64">
+            <enum name="GL_DOUBLE_VEC2"/>
+            <enum name="GL_DOUBLE_VEC3"/>
+            <enum name="GL_DOUBLE_VEC4"/>
+            <enum name="GL_DOUBLE_MAT2"/>
+            <enum name="GL_DOUBLE_MAT3"/>
+            <enum name="GL_DOUBLE_MAT4"/>
+            <enum name="GL_DOUBLE_MAT2x3"/>
+            <enum name="GL_DOUBLE_MAT2x4"/>
+            <enum name="GL_DOUBLE_MAT3x2"/>
+            <enum name="GL_DOUBLE_MAT3x4"/>
+            <enum name="GL_DOUBLE_MAT4x2"/>
+            <enum name="GL_DOUBLE_MAT4x3"/>
+            <command name="glUniform1d"/>
+            <command name="glUniform2d"/>
+            <command name="glUniform3d"/>
+            <command name="glUniform4d"/>
+            <command name="glUniform1dv"/>
+            <command name="glUniform2dv"/>
+            <command name="glUniform3dv"/>
+            <command name="glUniform4dv"/>
+            <command name="glUniformMatrix2dv"/>
+            <command name="glUniformMatrix3dv"/>
+            <command name="glUniformMatrix4dv"/>
+            <command name="glUniformMatrix2x3dv"/>
+            <command name="glUniformMatrix2x4dv"/>
+            <command name="glUniformMatrix3x2dv"/>
+            <command name="glUniformMatrix3x4dv"/>
+            <command name="glUniformMatrix4x2dv"/>
+            <command name="glUniformMatrix4x3dv"/>
+            <command name="glGetUniformdv"/>
+        </require>
+        <require comment="Reuse ARB_shader_subroutine">
+            <enum name="GL_ACTIVE_SUBROUTINES"/>
+            <enum name="GL_ACTIVE_SUBROUTINE_UNIFORMS"/>
+            <enum name="GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"/>
+            <enum name="GL_ACTIVE_SUBROUTINE_MAX_LENGTH"/>
+            <enum name="GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"/>
+            <enum name="GL_MAX_SUBROUTINES"/>
+            <enum name="GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS"/>
+            <enum name="GL_NUM_COMPATIBLE_SUBROUTINES"/>
+            <enum name="GL_COMPATIBLE_SUBROUTINES"/>
+            <command name="glGetSubroutineUniformLocation"/>
+            <command name="glGetSubroutineIndex"/>
+            <command name="glGetActiveSubroutineUniformiv"/>
+            <command name="glGetActiveSubroutineUniformName"/>
+            <command name="glGetActiveSubroutineName"/>
+            <command name="glUniformSubroutinesuiv"/>
+            <command name="glGetUniformSubroutineuiv"/>
+            <command name="glGetProgramStageiv"/>
+        </require>
+        <require comment="Reuse ARB_tessellation_shader">
+            <enum name="GL_PATCHES"/>
+            <enum name="GL_PATCH_VERTICES"/>
+            <enum name="GL_PATCH_DEFAULT_INNER_LEVEL"/>
+            <enum name="GL_PATCH_DEFAULT_OUTER_LEVEL"/>
+            <enum name="GL_TESS_CONTROL_OUTPUT_VERTICES"/>
+            <enum name="GL_TESS_GEN_MODE"/>
+            <enum name="GL_TESS_GEN_SPACING"/>
+            <enum name="GL_TESS_GEN_VERTEX_ORDER"/>
+            <enum name="GL_TESS_GEN_POINT_MODE"/>
+            <enum name="GL_ISOLINES"/>
+            <enum name="GL_QUADS"/>
+            <enum name="GL_FRACTIONAL_ODD"/>
+            <enum name="GL_FRACTIONAL_EVEN"/>
+            <enum name="GL_MAX_PATCH_VERTICES"/>
+            <enum name="GL_MAX_TESS_GEN_LEVEL"/>
+            <enum name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_PATCH_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+            <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+            <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+            <enum name="GL_TESS_EVALUATION_SHADER"/>
+            <enum name="GL_TESS_CONTROL_SHADER"/>
+            <command name="glPatchParameteri"/>
+            <command name="glPatchParameterfv"/>
+        </require>
+        <require comment="Reuse ARB_texture_buffer_object_rgb32 (none)">
+        </require>
+        <require comment="Reuse ARB_texture_cube_map_array (none)">
+        </require>
+        <require comment="Reuse ARB_texture_gather (none)">
+        </require>
+        <require comment="Reuse ARB_texture_query_lod (none)">
+        </require>
+        <require comment="Reuse ARB_transform_feedback2">
+            <enum name="GL_TRANSFORM_FEEDBACK"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BINDING"/>
+            <command name="glBindTransformFeedback"/>
+            <command name="glDeleteTransformFeedbacks"/>
+            <command name="glGenTransformFeedbacks"/>
+            <command name="glIsTransformFeedback"/>
+            <command name="glPauseTransformFeedback"/>
+            <command name="glResumeTransformFeedback"/>
+            <command name="glDrawTransformFeedback"/>
+        </require>
+        <require comment="Reuse ARB_transform_feedback3">
+            <enum name="GL_MAX_TRANSFORM_FEEDBACK_BUFFERS"/>
+            <enum name="GL_MAX_VERTEX_STREAMS"/>
+            <command name="glDrawTransformFeedbackStream"/>
+            <command name="glBeginQueryIndexed"/>
+            <command name="glEndQueryIndexed"/>
+            <command name="glGetQueryIndexediv"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_4_1" number="4.1">
+        <require comment="Reuse tokens from ARB_ES2_compatibility">
+            <enum name="GL_FIXED"/>
+            <enum name="GL_IMPLEMENTATION_COLOR_READ_TYPE"/>
+            <enum name="GL_IMPLEMENTATION_COLOR_READ_FORMAT"/>
+            <enum name="GL_LOW_FLOAT"/>
+            <enum name="GL_MEDIUM_FLOAT"/>
+            <enum name="GL_HIGH_FLOAT"/>
+            <enum name="GL_LOW_INT"/>
+            <enum name="GL_MEDIUM_INT"/>
+            <enum name="GL_HIGH_INT"/>
+            <enum name="GL_SHADER_COMPILER"/>
+            <enum name="GL_SHADER_BINARY_FORMATS"/>
+            <enum name="GL_NUM_SHADER_BINARY_FORMATS"/>
+            <enum name="GL_MAX_VERTEX_UNIFORM_VECTORS"/>
+            <enum name="GL_MAX_VARYING_VECTORS"/>
+            <enum name="GL_MAX_FRAGMENT_UNIFORM_VECTORS"/>
+            <enum name="GL_RGB565"/>
+        </require>
+        <require comment="Reuse tokens from ARB_get_program_binary">
+            <enum name="GL_PROGRAM_BINARY_RETRIEVABLE_HINT"/>
+            <enum name="GL_PROGRAM_BINARY_LENGTH"/>
+            <enum name="GL_NUM_PROGRAM_BINARY_FORMATS"/>
+            <enum name="GL_PROGRAM_BINARY_FORMATS"/>
+        </require>
+        <require comment="Reuse tokens from ARB_separate_shader_objects">
+            <enum name="GL_VERTEX_SHADER_BIT"/>
+            <enum name="GL_FRAGMENT_SHADER_BIT"/>
+            <enum name="GL_GEOMETRY_SHADER_BIT"/>
+            <enum name="GL_TESS_CONTROL_SHADER_BIT"/>
+            <enum name="GL_TESS_EVALUATION_SHADER_BIT"/>
+            <enum name="GL_ALL_SHADER_BITS"/>
+            <enum name="GL_PROGRAM_SEPARABLE"/>
+            <enum name="GL_ACTIVE_PROGRAM"/>
+            <enum name="GL_PROGRAM_PIPELINE_BINDING"/>
+        </require>
+        <require comment="Reuse tokens from ARB_shader_precision (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_vertex_attrib_64bit - all are in GL 3.0 and 4.0 already">
+        </require>
+        <require comment="Reuse tokens from ARB_viewport_array - some are in GL 1.1 and ARB_provoking_vertex already">
+            <enum name="GL_MAX_VIEWPORTS"/>
+            <enum name="GL_VIEWPORT_SUBPIXEL_BITS"/>
+            <enum name="GL_VIEWPORT_BOUNDS_RANGE"/>
+            <enum name="GL_LAYER_PROVOKING_VERTEX"/>
+            <enum name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX"/>
+            <enum name="GL_UNDEFINED_VERTEX"/>
+        </require>
+        <require comment="Reuse commands from ARB_ES2_compatibility">
+            <command name="glReleaseShaderCompiler"/>
+            <command name="glShaderBinary"/>
+            <command name="glGetShaderPrecisionFormat"/>
+            <command name="glDepthRangef"/>
+            <command name="glClearDepthf"/>
+        </require>
+        <require comment="Reuse commands from ARB_get_program_binary">
+            <command name="glGetProgramBinary"/>
+            <command name="glProgramBinary"/>
+            <command name="glProgramParameteri"/>
+        </require>
+        <require comment="Reuse commands from ARB_separate_shader_objects">
+            <command name="glUseProgramStages"/>
+            <command name="glActiveShaderProgram"/>
+            <command name="glCreateShaderProgramv"/>
+            <command name="glBindProgramPipeline"/>
+            <command name="glDeleteProgramPipelines"/>
+            <command name="glGenProgramPipelines"/>
+            <command name="glIsProgramPipeline"/>
+            <command name="glGetProgramPipelineiv"/>
+            <command name="glProgramUniform1i"/>
+            <command name="glProgramUniform1iv"/>
+            <command name="glProgramUniform1f"/>
+            <command name="glProgramUniform1fv"/>
+            <command name="glProgramUniform1d"/>
+            <command name="glProgramUniform1dv"/>
+            <command name="glProgramUniform1ui"/>
+            <command name="glProgramUniform1uiv"/>
+            <command name="glProgramUniform2i"/>
+            <command name="glProgramUniform2iv"/>
+            <command name="glProgramUniform2f"/>
+            <command name="glProgramUniform2fv"/>
+            <command name="glProgramUniform2d"/>
+            <command name="glProgramUniform2dv"/>
+            <command name="glProgramUniform2ui"/>
+            <command name="glProgramUniform2uiv"/>
+            <command name="glProgramUniform3i"/>
+            <command name="glProgramUniform3iv"/>
+            <command name="glProgramUniform3f"/>
+            <command name="glProgramUniform3fv"/>
+            <command name="glProgramUniform3d"/>
+            <command name="glProgramUniform3dv"/>
+            <command name="glProgramUniform3ui"/>
+            <command name="glProgramUniform3uiv"/>
+            <command name="glProgramUniform4i"/>
+            <command name="glProgramUniform4iv"/>
+            <command name="glProgramUniform4f"/>
+            <command name="glProgramUniform4fv"/>
+            <command name="glProgramUniform4d"/>
+            <command name="glProgramUniform4dv"/>
+            <command name="glProgramUniform4ui"/>
+            <command name="glProgramUniform4uiv"/>
+            <command name="glProgramUniformMatrix2fv"/>
+            <command name="glProgramUniformMatrix3fv"/>
+            <command name="glProgramUniformMatrix4fv"/>
+            <command name="glProgramUniformMatrix2dv"/>
+            <command name="glProgramUniformMatrix3dv"/>
+            <command name="glProgramUniformMatrix4dv"/>
+            <command name="glProgramUniformMatrix2x3fv"/>
+            <command name="glProgramUniformMatrix3x2fv"/>
+            <command name="glProgramUniformMatrix2x4fv"/>
+            <command name="glProgramUniformMatrix4x2fv"/>
+            <command name="glProgramUniformMatrix3x4fv"/>
+            <command name="glProgramUniformMatrix4x3fv"/>
+            <command name="glProgramUniformMatrix2x3dv"/>
+            <command name="glProgramUniformMatrix3x2dv"/>
+            <command name="glProgramUniformMatrix2x4dv"/>
+            <command name="glProgramUniformMatrix4x2dv"/>
+            <command name="glProgramUniformMatrix3x4dv"/>
+            <command name="glProgramUniformMatrix4x3dv"/>
+            <command name="glValidateProgramPipeline"/>
+            <command name="glGetProgramPipelineInfoLog"/>
+        </require>
+        <require comment="Reuse commands from ARB_shader_precision (none)">
+        </require>
+        <require comment="Reuse commands from ARB_vertex_attrib_64bit">
+            <command name="glVertexAttribL1d"/>
+            <command name="glVertexAttribL2d"/>
+            <command name="glVertexAttribL3d"/>
+            <command name="glVertexAttribL4d"/>
+            <command name="glVertexAttribL1dv"/>
+            <command name="glVertexAttribL2dv"/>
+            <command name="glVertexAttribL3dv"/>
+            <command name="glVertexAttribL4dv"/>
+            <command name="glVertexAttribLPointer"/>
+            <command name="glGetVertexAttribLdv"/>
+        </require>
+        <require comment="Reuse commands from ARB_viewport_array">
+            <command name="glViewportArrayv"/>
+            <command name="glViewportIndexedf"/>
+            <command name="glViewportIndexedfv"/>
+            <command name="glScissorArrayv"/>
+            <command name="glScissorIndexed"/>
+            <command name="glScissorIndexedv"/>
+            <command name="glDepthRangeArrayv"/>
+            <command name="glDepthRangeIndexed"/>
+            <command name="glGetFloati_v"/>
+            <command name="glGetDoublei_v"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_4_2" number="4.2">
+        <require comment="New aliases for old tokens">
+            <enum name="GL_COPY_READ_BUFFER_BINDING"/>
+            <enum name="GL_COPY_WRITE_BUFFER_BINDING"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_ACTIVE"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_PAUSED"/>
+        </require>
+        <require comment="Reuse tokens from ARB_base_instance (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_shading_language_420pack (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_transform_feedback_instanced (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_compressed_texture_pixel_storage">
+            <enum name="GL_UNPACK_COMPRESSED_BLOCK_WIDTH"/>
+            <enum name="GL_UNPACK_COMPRESSED_BLOCK_HEIGHT"/>
+            <enum name="GL_UNPACK_COMPRESSED_BLOCK_DEPTH"/>
+            <enum name="GL_UNPACK_COMPRESSED_BLOCK_SIZE"/>
+            <enum name="GL_PACK_COMPRESSED_BLOCK_WIDTH"/>
+            <enum name="GL_PACK_COMPRESSED_BLOCK_HEIGHT"/>
+            <enum name="GL_PACK_COMPRESSED_BLOCK_DEPTH"/>
+            <enum name="GL_PACK_COMPRESSED_BLOCK_SIZE"/>
+        </require>
+        <require comment="Reuse tokens from ARB_conservative_depth (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_internalformat_query">
+            <enum name="GL_NUM_SAMPLE_COUNTS"/>
+        </require>
+        <require comment="Reuse tokens from ARB_map_buffer_alignment">
+            <enum name="GL_MIN_MAP_BUFFER_ALIGNMENT"/>
+        </require>
+        <require comment="Reuse tokens from ARB_shader_atomic_counters">
+            <enum name="GL_ATOMIC_COUNTER_BUFFER"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_BINDING"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_START"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_SIZE"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER"/>
+            <enum name="GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_VERTEX_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_FRAGMENT_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_COMBINED_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE"/>
+            <enum name="GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS"/>
+            <enum name="GL_ACTIVE_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX"/>
+            <enum name="GL_UNSIGNED_INT_ATOMIC_COUNTER"/>
+        </require>
+        <require comment="Reuse tokens from ARB_shader_image_load_store">
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT"/>
+            <enum name="GL_ELEMENT_ARRAY_BARRIER_BIT"/>
+            <enum name="GL_UNIFORM_BARRIER_BIT"/>
+            <enum name="GL_TEXTURE_FETCH_BARRIER_BIT"/>
+            <enum name="GL_SHADER_IMAGE_ACCESS_BARRIER_BIT"/>
+            <enum name="GL_COMMAND_BARRIER_BIT"/>
+            <enum name="GL_PIXEL_BUFFER_BARRIER_BIT"/>
+            <enum name="GL_TEXTURE_UPDATE_BARRIER_BIT"/>
+            <enum name="GL_BUFFER_UPDATE_BARRIER_BIT"/>
+            <enum name="GL_FRAMEBUFFER_BARRIER_BIT"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BARRIER_BIT"/>
+            <enum name="GL_ATOMIC_COUNTER_BARRIER_BIT"/>
+            <enum name="GL_ALL_BARRIER_BITS"/>
+            <enum name="GL_MAX_IMAGE_UNITS"/>
+            <enum name="GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS"/>
+            <enum name="GL_IMAGE_BINDING_NAME"/>
+            <enum name="GL_IMAGE_BINDING_LEVEL"/>
+            <enum name="GL_IMAGE_BINDING_LAYERED"/>
+            <enum name="GL_IMAGE_BINDING_LAYER"/>
+            <enum name="GL_IMAGE_BINDING_ACCESS"/>
+            <enum name="GL_IMAGE_1D"/>
+            <enum name="GL_IMAGE_2D"/>
+            <enum name="GL_IMAGE_3D"/>
+            <enum name="GL_IMAGE_2D_RECT"/>
+            <enum name="GL_IMAGE_CUBE"/>
+            <enum name="GL_IMAGE_BUFFER"/>
+            <enum name="GL_IMAGE_1D_ARRAY"/>
+            <enum name="GL_IMAGE_2D_ARRAY"/>
+            <enum name="GL_IMAGE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_IMAGE_2D_MULTISAMPLE"/>
+            <enum name="GL_IMAGE_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_INT_IMAGE_1D"/>
+            <enum name="GL_INT_IMAGE_2D"/>
+            <enum name="GL_INT_IMAGE_3D"/>
+            <enum name="GL_INT_IMAGE_2D_RECT"/>
+            <enum name="GL_INT_IMAGE_CUBE"/>
+            <enum name="GL_INT_IMAGE_BUFFER"/>
+            <enum name="GL_INT_IMAGE_1D_ARRAY"/>
+            <enum name="GL_INT_IMAGE_2D_ARRAY"/>
+            <enum name="GL_INT_IMAGE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_INT_IMAGE_2D_MULTISAMPLE"/>
+            <enum name="GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_1D"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_2D"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_3D"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_2D_RECT"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_CUBE"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_BUFFER"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_1D_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_2D_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_MAX_IMAGE_SAMPLES"/>
+            <enum name="GL_IMAGE_BINDING_FORMAT"/>
+            <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_TYPE"/>
+            <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE"/>
+            <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS"/>
+            <enum name="GL_MAX_VERTEX_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_FRAGMENT_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_COMBINED_IMAGE_UNIFORMS"/>
+        </require>
+        <require comment="Reuse tokens from ARB_shading_language_packing (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_texture_compression_bptc">
+            <enum name="GL_COMPRESSED_RGBA_BPTC_UNORM"/>
+            <enum name="GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM"/>
+            <enum name="GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT"/>
+            <enum name="GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT"/>
+        </require>
+        <require comment="Reuse tokens from ARB_texture_storage">
+            <enum name="GL_TEXTURE_IMMUTABLE_FORMAT"/>
+        </require>
+        <require comment="Reuse commands from ARB_base_instance">
+            <command name="glDrawArraysInstancedBaseInstance"/>
+            <command name="glDrawElementsInstancedBaseInstance"/>
+            <command name="glDrawElementsInstancedBaseVertexBaseInstance"/>
+        </require>
+        <require comment="Reuse commands from ARB_compressed_texture_pixel_storage (none)">
+        </require>
+        <require comment="Reuse commands from ARB_conservative_depth (none)">
+        </require>
+        <require comment="Reuse commands from ARB_internalformat_query">
+            <command name="glGetInternalformativ"/>
+        </require>
+        <require comment="Reuse commands from ARB_map_buffer_alignment (none)">
+        </require>
+        <require comment="Reuse commands from ARB_shader_atomic_counters">
+            <command name="glGetActiveAtomicCounterBufferiv"/>
+        </require>
+        <require comment="Reuse commands from ARB_shader_image_load_store">
+            <command name="glBindImageTexture"/>
+            <command name="glMemoryBarrier"/>
+        </require>
+        <require comment="Reuse commands from ARB_shading_language_420pack (none)">
+        </require>
+        <require comment="Reuse commands from ARB_shading_language_packing (none)">
+        </require>
+        <require comment="Reuse commands from ARB_texture_storage">
+            <command name="glTexStorage1D"/>
+            <command name="glTexStorage2D"/>
+            <command name="glTexStorage3D"/>
+        </require>
+        <require comment="Reuse commands from ARB_transform_feedback_instanced">
+            <command name="glDrawTransformFeedbackInstanced"/>
+            <command name="glDrawTransformFeedbackStreamInstanced"/>
+        </require>
+        <!-- Deprecated in OpenGL 4.2 core;
+             deprecate tag not defined/supported yet
+          <deprecate profile="core">
+            <enum name="GL_NUM_COMPRESSED_TEXTURE_FORMATS"/>
+            <enum name="GL_COMPRESSED_TEXTURE_FORMATS"/>
+          </deprecate>
+        -->
+    </feature>
+    <feature api="gl" name="GL_VERSION_4_3" number="4.3">
+        <require>
+            <enum name="GL_NUM_SHADING_LANGUAGE_VERSIONS"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_LONG"/>
+        </require>
+        <require comment="Reuse tokens from ARB_arrays_of_arrays (none, GLSL only)">
+        </require>
+        <require comment="Reuse tokens from ARB_fragment_layer_viewport (none, GLSL only)">
+        </require>
+        <require comment="Reuse tokens from ARB_shader_image_size (none, GLSL only)">
+        </require>
+        <require comment="Reuse tokens from ARB_ES3_compatibility">
+            <enum name="GL_COMPRESSED_RGB8_ETC2"/>
+            <enum name="GL_COMPRESSED_SRGB8_ETC2"/>
+            <enum name="GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"/>
+            <enum name="GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"/>
+            <enum name="GL_COMPRESSED_RGBA8_ETC2_EAC"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"/>
+            <enum name="GL_COMPRESSED_R11_EAC"/>
+            <enum name="GL_COMPRESSED_SIGNED_R11_EAC"/>
+            <enum name="GL_COMPRESSED_RG11_EAC"/>
+            <enum name="GL_COMPRESSED_SIGNED_RG11_EAC"/>
+            <enum name="GL_PRIMITIVE_RESTART_FIXED_INDEX"/>
+            <enum name="GL_ANY_SAMPLES_PASSED_CONSERVATIVE"/>
+            <enum name="GL_MAX_ELEMENT_INDEX"/>
+        </require>
+        <require comment="Reuse tokens from ARB_clear_buffer_object (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_compute_shader">
+            <enum name="GL_COMPUTE_SHADER"/>
+            <enum name="GL_MAX_COMPUTE_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_COMPUTE_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"/>
+            <enum name="GL_MAX_COMPUTE_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_COMPUTE_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS"/>
+            <enum name="GL_MAX_COMPUTE_WORK_GROUP_COUNT"/>
+            <enum name="GL_MAX_COMPUTE_WORK_GROUP_SIZE"/>
+            <enum name="GL_COMPUTE_WORK_GROUP_SIZE"/>
+            <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER"/>
+            <enum name="GL_DISPATCH_INDIRECT_BUFFER"/>
+            <enum name="GL_DISPATCH_INDIRECT_BUFFER_BINDING"/>
+            <enum name="GL_COMPUTE_SHADER_BIT"/>
+        </require>
+        <require comment="Reuse tokens from ARB_copy_image (none)">
+        </require>
+        <require comment="Reuse tokens from KHR_debug">
+            <enum name="GL_DEBUG_OUTPUT_SYNCHRONOUS"/>
+            <enum name="GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH"/>
+            <enum name="GL_DEBUG_CALLBACK_FUNCTION"/>
+            <enum name="GL_DEBUG_CALLBACK_USER_PARAM"/>
+            <enum name="GL_DEBUG_SOURCE_API"/>
+            <enum name="GL_DEBUG_SOURCE_WINDOW_SYSTEM"/>
+            <enum name="GL_DEBUG_SOURCE_SHADER_COMPILER"/>
+            <enum name="GL_DEBUG_SOURCE_THIRD_PARTY"/>
+            <enum name="GL_DEBUG_SOURCE_APPLICATION"/>
+            <enum name="GL_DEBUG_SOURCE_OTHER"/>
+            <enum name="GL_DEBUG_TYPE_ERROR"/>
+            <enum name="GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"/>
+            <enum name="GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"/>
+            <enum name="GL_DEBUG_TYPE_PORTABILITY"/>
+            <enum name="GL_DEBUG_TYPE_PERFORMANCE"/>
+            <enum name="GL_DEBUG_TYPE_OTHER"/>
+            <enum name="GL_MAX_DEBUG_MESSAGE_LENGTH"/>
+            <enum name="GL_MAX_DEBUG_LOGGED_MESSAGES"/>
+            <enum name="GL_DEBUG_LOGGED_MESSAGES"/>
+            <enum name="GL_DEBUG_SEVERITY_HIGH"/>
+            <enum name="GL_DEBUG_SEVERITY_MEDIUM"/>
+            <enum name="GL_DEBUG_SEVERITY_LOW"/>
+            <enum name="GL_DEBUG_TYPE_MARKER"/>
+            <enum name="GL_DEBUG_TYPE_PUSH_GROUP"/>
+            <enum name="GL_DEBUG_TYPE_POP_GROUP"/>
+            <enum name="GL_DEBUG_SEVERITY_NOTIFICATION"/>
+            <enum name="GL_MAX_DEBUG_GROUP_STACK_DEPTH"/>
+            <enum name="GL_DEBUG_GROUP_STACK_DEPTH"/>
+            <enum name="GL_BUFFER"/>
+            <enum name="GL_SHADER"/>
+            <enum name="GL_PROGRAM"/>
+            <enum name="GL_VERTEX_ARRAY"/>
+            <enum name="GL_QUERY"/>
+            <enum name="GL_PROGRAM_PIPELINE"/>
+            <enum name="GL_SAMPLER"/>
+            <enum name="GL_MAX_LABEL_LENGTH"/>
+            <enum name="GL_DEBUG_OUTPUT"/>
+            <enum name="GL_CONTEXT_FLAG_DEBUG_BIT"/>
+        </require>
+        <require comment="Reuse tokens from ARB_explicit_uniform_location">
+            <enum name="GL_MAX_UNIFORM_LOCATIONS"/>
+        </require>
+        <require comment="Reuse tokens from ARB_framebuffer_no_attachments">
+            <enum name="GL_FRAMEBUFFER_DEFAULT_WIDTH"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_HEIGHT"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_LAYERS"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_SAMPLES"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"/>
+            <enum name="GL_MAX_FRAMEBUFFER_WIDTH"/>
+            <enum name="GL_MAX_FRAMEBUFFER_HEIGHT"/>
+            <enum name="GL_MAX_FRAMEBUFFER_LAYERS"/>
+            <enum name="GL_MAX_FRAMEBUFFER_SAMPLES"/>
+        </require>
+        <require comment="Reuse tokens from ARB_internalformat_query2">
+            <enum name="GL_INTERNALFORMAT_SUPPORTED"/>
+            <enum name="GL_INTERNALFORMAT_PREFERRED"/>
+            <enum name="GL_INTERNALFORMAT_RED_SIZE"/>
+            <enum name="GL_INTERNALFORMAT_GREEN_SIZE"/>
+            <enum name="GL_INTERNALFORMAT_BLUE_SIZE"/>
+            <enum name="GL_INTERNALFORMAT_ALPHA_SIZE"/>
+            <enum name="GL_INTERNALFORMAT_DEPTH_SIZE"/>
+            <enum name="GL_INTERNALFORMAT_STENCIL_SIZE"/>
+            <enum name="GL_INTERNALFORMAT_SHARED_SIZE"/>
+            <enum name="GL_INTERNALFORMAT_RED_TYPE"/>
+            <enum name="GL_INTERNALFORMAT_GREEN_TYPE"/>
+            <enum name="GL_INTERNALFORMAT_BLUE_TYPE"/>
+            <enum name="GL_INTERNALFORMAT_ALPHA_TYPE"/>
+            <enum name="GL_INTERNALFORMAT_DEPTH_TYPE"/>
+            <enum name="GL_INTERNALFORMAT_STENCIL_TYPE"/>
+            <enum name="GL_MAX_WIDTH"/>
+            <enum name="GL_MAX_HEIGHT"/>
+            <enum name="GL_MAX_DEPTH"/>
+            <enum name="GL_MAX_LAYERS"/>
+            <enum name="GL_MAX_COMBINED_DIMENSIONS"/>
+            <enum name="GL_COLOR_COMPONENTS"/>
+            <enum name="GL_DEPTH_COMPONENTS"/>
+            <enum name="GL_STENCIL_COMPONENTS"/>
+            <enum name="GL_COLOR_RENDERABLE"/>
+            <enum name="GL_DEPTH_RENDERABLE"/>
+            <enum name="GL_STENCIL_RENDERABLE"/>
+            <enum name="GL_FRAMEBUFFER_RENDERABLE"/>
+            <enum name="GL_FRAMEBUFFER_RENDERABLE_LAYERED"/>
+            <enum name="GL_FRAMEBUFFER_BLEND"/>
+            <enum name="GL_READ_PIXELS"/>
+            <enum name="GL_READ_PIXELS_FORMAT"/>
+            <enum name="GL_READ_PIXELS_TYPE"/>
+            <enum name="GL_TEXTURE_IMAGE_FORMAT"/>
+            <enum name="GL_TEXTURE_IMAGE_TYPE"/>
+            <enum name="GL_GET_TEXTURE_IMAGE_FORMAT"/>
+            <enum name="GL_GET_TEXTURE_IMAGE_TYPE"/>
+            <enum name="GL_MIPMAP"/>
+            <enum name="GL_MANUAL_GENERATE_MIPMAP"/>
+            <enum name="GL_AUTO_GENERATE_MIPMAP"/>
+            <enum name="GL_COLOR_ENCODING"/>
+            <enum name="GL_SRGB_READ"/>
+            <enum name="GL_SRGB_WRITE"/>
+            <enum name="GL_FILTER"/>
+            <enum name="GL_VERTEX_TEXTURE"/>
+            <enum name="GL_TESS_CONTROL_TEXTURE"/>
+            <enum name="GL_TESS_EVALUATION_TEXTURE"/>
+            <enum name="GL_GEOMETRY_TEXTURE"/>
+            <enum name="GL_FRAGMENT_TEXTURE"/>
+            <enum name="GL_COMPUTE_TEXTURE"/>
+            <enum name="GL_TEXTURE_SHADOW"/>
+            <enum name="GL_TEXTURE_GATHER"/>
+            <enum name="GL_TEXTURE_GATHER_SHADOW"/>
+            <enum name="GL_SHADER_IMAGE_LOAD"/>
+            <enum name="GL_SHADER_IMAGE_STORE"/>
+            <enum name="GL_SHADER_IMAGE_ATOMIC"/>
+            <enum name="GL_IMAGE_TEXEL_SIZE"/>
+            <enum name="GL_IMAGE_COMPATIBILITY_CLASS"/>
+            <enum name="GL_IMAGE_PIXEL_FORMAT"/>
+            <enum name="GL_IMAGE_PIXEL_TYPE"/>
+            <enum name="GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST"/>
+            <enum name="GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST"/>
+            <enum name="GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE"/>
+            <enum name="GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE"/>
+            <enum name="GL_TEXTURE_COMPRESSED_BLOCK_WIDTH"/>
+            <enum name="GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT"/>
+            <enum name="GL_TEXTURE_COMPRESSED_BLOCK_SIZE"/>
+            <enum name="GL_CLEAR_BUFFER"/>
+            <enum name="GL_TEXTURE_VIEW"/>
+            <enum name="GL_VIEW_COMPATIBILITY_CLASS"/>
+            <enum name="GL_FULL_SUPPORT"/>
+            <enum name="GL_CAVEAT_SUPPORT"/>
+            <enum name="GL_IMAGE_CLASS_4_X_32"/>
+            <enum name="GL_IMAGE_CLASS_2_X_32"/>
+            <enum name="GL_IMAGE_CLASS_1_X_32"/>
+            <enum name="GL_IMAGE_CLASS_4_X_16"/>
+            <enum name="GL_IMAGE_CLASS_2_X_16"/>
+            <enum name="GL_IMAGE_CLASS_1_X_16"/>
+            <enum name="GL_IMAGE_CLASS_4_X_8"/>
+            <enum name="GL_IMAGE_CLASS_2_X_8"/>
+            <enum name="GL_IMAGE_CLASS_1_X_8"/>
+            <enum name="GL_IMAGE_CLASS_11_11_10"/>
+            <enum name="GL_IMAGE_CLASS_10_10_10_2"/>
+            <enum name="GL_VIEW_CLASS_128_BITS"/>
+            <enum name="GL_VIEW_CLASS_96_BITS"/>
+            <enum name="GL_VIEW_CLASS_64_BITS"/>
+            <enum name="GL_VIEW_CLASS_48_BITS"/>
+            <enum name="GL_VIEW_CLASS_32_BITS"/>
+            <enum name="GL_VIEW_CLASS_24_BITS"/>
+            <enum name="GL_VIEW_CLASS_16_BITS"/>
+            <enum name="GL_VIEW_CLASS_8_BITS"/>
+            <enum name="GL_VIEW_CLASS_S3TC_DXT1_RGB"/>
+            <enum name="GL_VIEW_CLASS_S3TC_DXT1_RGBA"/>
+            <enum name="GL_VIEW_CLASS_S3TC_DXT3_RGBA"/>
+            <enum name="GL_VIEW_CLASS_S3TC_DXT5_RGBA"/>
+            <enum name="GL_VIEW_CLASS_RGTC1_RED"/>
+            <enum name="GL_VIEW_CLASS_RGTC2_RG"/>
+            <enum name="GL_VIEW_CLASS_BPTC_UNORM"/>
+            <enum name="GL_VIEW_CLASS_BPTC_FLOAT"/>
+        </require>
+        <require comment="Reuse tokens from ARB_invalidate_subdata (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_multi_draw_indirect (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_program_interface_query">
+            <enum name="GL_UNIFORM"/>
+            <enum name="GL_UNIFORM_BLOCK"/>
+            <enum name="GL_PROGRAM_INPUT"/>
+            <enum name="GL_PROGRAM_OUTPUT"/>
+            <enum name="GL_BUFFER_VARIABLE"/>
+            <enum name="GL_SHADER_STORAGE_BLOCK"/>
+            <enum name="GL_VERTEX_SUBROUTINE"/>
+            <enum name="GL_TESS_CONTROL_SUBROUTINE"/>
+            <enum name="GL_TESS_EVALUATION_SUBROUTINE"/>
+            <enum name="GL_GEOMETRY_SUBROUTINE"/>
+            <enum name="GL_FRAGMENT_SUBROUTINE"/>
+            <enum name="GL_COMPUTE_SUBROUTINE"/>
+            <enum name="GL_VERTEX_SUBROUTINE_UNIFORM"/>
+            <enum name="GL_TESS_CONTROL_SUBROUTINE_UNIFORM"/>
+            <enum name="GL_TESS_EVALUATION_SUBROUTINE_UNIFORM"/>
+            <enum name="GL_GEOMETRY_SUBROUTINE_UNIFORM"/>
+            <enum name="GL_FRAGMENT_SUBROUTINE_UNIFORM"/>
+            <enum name="GL_COMPUTE_SUBROUTINE_UNIFORM"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_VARYING"/>
+            <enum name="GL_ACTIVE_RESOURCES"/>
+            <enum name="GL_MAX_NAME_LENGTH"/>
+            <enum name="GL_MAX_NUM_ACTIVE_VARIABLES"/>
+            <enum name="GL_MAX_NUM_COMPATIBLE_SUBROUTINES"/>
+            <enum name="GL_NAME_LENGTH"/>
+            <enum name="GL_TYPE"/>
+            <enum name="GL_ARRAY_SIZE"/>
+            <enum name="GL_OFFSET"/>
+            <enum name="GL_BLOCK_INDEX"/>
+            <enum name="GL_ARRAY_STRIDE"/>
+            <enum name="GL_MATRIX_STRIDE"/>
+            <enum name="GL_IS_ROW_MAJOR"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_INDEX"/>
+            <enum name="GL_BUFFER_BINDING"/>
+            <enum name="GL_BUFFER_DATA_SIZE"/>
+            <enum name="GL_NUM_ACTIVE_VARIABLES"/>
+            <enum name="GL_ACTIVE_VARIABLES"/>
+            <enum name="GL_REFERENCED_BY_VERTEX_SHADER"/>
+            <enum name="GL_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+            <enum name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+            <enum name="GL_REFERENCED_BY_GEOMETRY_SHADER"/>
+            <enum name="GL_REFERENCED_BY_FRAGMENT_SHADER"/>
+            <enum name="GL_REFERENCED_BY_COMPUTE_SHADER"/>
+            <enum name="GL_TOP_LEVEL_ARRAY_SIZE"/>
+            <enum name="GL_TOP_LEVEL_ARRAY_STRIDE"/>
+            <enum name="GL_LOCATION"/>
+            <enum name="GL_LOCATION_INDEX"/>
+            <enum name="GL_IS_PER_PATCH"/>
+        </require>
+        <require comment="Reuse tokens from ARB_robust_buffer_access_behavior (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_shader_storage_buffer_object">
+            <enum name="GL_SHADER_STORAGE_BUFFER"/>
+            <enum name="GL_SHADER_STORAGE_BUFFER_BINDING"/>
+            <enum name="GL_SHADER_STORAGE_BUFFER_START"/>
+            <enum name="GL_SHADER_STORAGE_BUFFER_SIZE"/>
+            <enum name="GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS"/>
+            <enum name="GL_MAX_SHADER_STORAGE_BLOCK_SIZE"/>
+            <enum name="GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT"/>
+            <enum name="GL_SHADER_STORAGE_BARRIER_BIT"/>
+            <enum name="GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES"/>
+        </require>
+        <require comment="Reuse tokens from ARB_stencil_texturing">
+            <enum name="GL_DEPTH_STENCIL_TEXTURE_MODE"/>
+        </require>
+        <require comment="Reuse tokens from ARB_texture_buffer_range">
+            <enum name="GL_TEXTURE_BUFFER_OFFSET"/>
+            <enum name="GL_TEXTURE_BUFFER_SIZE"/>
+            <enum name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT"/>
+        </require>
+        <require comment="Reuse tokens from ARB_texture_query_levels (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_texture_storage_multisample (none)">
+        </require>
+        <require comment="Reuse tokens from ARB_texture_view">
+            <enum name="GL_TEXTURE_VIEW_MIN_LEVEL"/>
+            <enum name="GL_TEXTURE_VIEW_NUM_LEVELS"/>
+            <enum name="GL_TEXTURE_VIEW_MIN_LAYER"/>
+            <enum name="GL_TEXTURE_VIEW_NUM_LAYERS"/>
+            <enum name="GL_TEXTURE_IMMUTABLE_LEVELS"/>
+        </require>
+        <require comment="Reuse tokens from ARB_vertex_attrib_binding">
+            <enum name="GL_VERTEX_ATTRIB_BINDING"/>
+            <enum name="GL_VERTEX_ATTRIB_RELATIVE_OFFSET"/>
+            <enum name="GL_VERTEX_BINDING_DIVISOR"/>
+            <enum name="GL_VERTEX_BINDING_OFFSET"/>
+            <enum name="GL_VERTEX_BINDING_STRIDE"/>
+            <enum name="GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET"/>
+            <enum name="GL_MAX_VERTEX_ATTRIB_BINDINGS"/>
+            <enum name="GL_VERTEX_BINDING_BUFFER" comment="Added in 2013/10/22 update to the spec"/>
+        </require>
+        <require comment="Reuse commands from ARB_arrays_of_arrays (none, GLSL only)">
+        </require>
+        <require comment="Reuse commands from ARB_clear_buffer_object">
+            <command name="glClearBufferData"/>
+            <command name="glClearBufferSubData"/>
+        </require>
+        <require comment="Reuse commands from ARB_compute_shader">
+            <command name="glDispatchCompute"/>
+            <command name="glDispatchComputeIndirect"/>
+        </require>
+        <require comment="Reuse commands from ARB_copy_image">
+            <command name="glCopyImageSubData"/>
+        </require>
+        <require comment="Reuse commands from ARB_ES3_compatibility (none)">
+        </require>
+        <require comment="Reuse commands from ARB_explicit_uniform_location (none)">
+        </require>
+        <require comment="Reuse commands from ARB_fragment_layer_viewport (none, GLSL only)">
+        </require>
+        <require comment="Reuse commands from ARB_framebuffer_no_attachments">
+            <command name="glFramebufferParameteri"/>
+            <command name="glGetFramebufferParameteriv"/>
+        </require>
+        <require comment="Reuse commands from ARB_internalformat_query2">
+            <command name="glGetInternalformati64v"/>
+        </require>
+        <require comment="Reuse commands from ARB_invalidate_subdata">
+            <command name="glInvalidateTexSubImage"/>
+            <command name="glInvalidateTexImage"/>
+            <command name="glInvalidateBufferSubData"/>
+            <command name="glInvalidateBufferData"/>
+            <command name="glInvalidateFramebuffer"/>
+            <command name="glInvalidateSubFramebuffer"/>
+        </require>
+        <require comment="Reuse commands from ARB_multi_draw_indirect">
+            <command name="glMultiDrawArraysIndirect"/>
+            <command name="glMultiDrawElementsIndirect"/>
+        </require>
+        <require comment="Reuse commands from ARB_program_interface_query">
+            <command name="glGetProgramInterfaceiv"/>
+            <command name="glGetProgramResourceIndex"/>
+            <command name="glGetProgramResourceName"/>
+            <command name="glGetProgramResourceiv"/>
+            <command name="glGetProgramResourceLocation"/>
+            <command name="glGetProgramResourceLocationIndex"/>
+        </require>
+        <require comment="Reuse commands from ARB_robust_buffer_access_behavior (none)">
+        </require>
+        <require comment="Reuse commands from ARB_shader_image_size (none, GLSL only)">
+        </require>
+        <require comment="Reuse commands from ARB_shader_storage_buffer_object">
+            <command name="glShaderStorageBlockBinding"/>
+        </require>
+        <require comment="Reuse commands from ARB_stencil_texturing (none)">
+        </require>
+        <require comment="Reuse commands from ARB_texture_buffer_range">
+            <command name="glTexBufferRange"/>
+        </require>
+        <require comment="Reuse commands from ARB_texture_query_levels (none)">
+        </require>
+        <require comment="Reuse commands from ARB_texture_storage_multisample">
+            <command name="glTexStorage2DMultisample"/>
+            <command name="glTexStorage3DMultisample"/>
+        </require>
+        <require comment="Reuse commands from ARB_texture_view">
+            <command name="glTextureView"/>
+        </require>
+        <require comment="Reuse commands from ARB_vertex_attrib_binding">
+            <command name="glBindVertexBuffer"/>
+            <command name="glVertexAttribFormat"/>
+            <command name="glVertexAttribIFormat"/>
+            <command name="glVertexAttribLFormat"/>
+            <command name="glVertexAttribBinding"/>
+            <command name="glVertexBindingDivisor"/>
+        </require>
+        <require comment="Reuse commands from KHR_debug (includes ARB_debug_output commands promoted to KHR without suffixes)">
+            <command name="glDebugMessageControl"/>
+            <command name="glDebugMessageInsert"/>
+            <command name="glDebugMessageCallback"/>
+            <command name="glGetDebugMessageLog"/>
+            <command name="glPushDebugGroup"/>
+            <command name="glPopDebugGroup"/>
+            <command name="glObjectLabel"/>
+            <command name="glGetObjectLabel"/>
+            <command name="glObjectPtrLabel"/>
+            <command name="glGetObjectPtrLabel"/>
+            <command name="glGetPointerv"/>
+        </require>
+        <require profile="compatibility" comment="KHR_debug functionality not supported in core profile">
+            <enum name="GL_DISPLAY_LIST"/>
+        </require>
+        <require profile="core" comment="Restore functionality removed in GL 3.2 core to GL 4.3. Needed for debug interface.">
+            <enum name="GL_STACK_UNDERFLOW"/>
+            <enum name="GL_STACK_OVERFLOW"/>
+            <command name="glGetPointerv"/>
+        </require>
+        <!-- Deprecated in OpenGL 4.3 core;
+             deprecate tag not defined/supported yet
+          <deprecate profile="core">
+            <enum name="GL_UNPACK_LSB_FIRST"/>
+            <enum name="GL_PACK_LSB_FIRST"/>
+          </deprecate>
+        -->
+    </feature>
+    <feature api="gl" name="GL_VERSION_4_4" number="4.4">
+        <require>
+            <enum name="GL_MAX_VERTEX_ATTRIB_STRIDE"/>
+            <enum name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"/>
+            <enum name="GL_TEXTURE_BUFFER_BINDING"/>
+        </require>
+        <require comment="Reuse GL_ARB_buffer_storage">
+            <enum name="GL_MAP_READ_BIT"/>
+            <enum name="GL_MAP_WRITE_BIT"/>
+            <enum name="GL_MAP_PERSISTENT_BIT"/>
+            <enum name="GL_MAP_COHERENT_BIT"/>
+            <enum name="GL_DYNAMIC_STORAGE_BIT"/>
+            <enum name="GL_CLIENT_STORAGE_BIT"/>
+            <enum name="GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT"/>
+            <enum name="GL_BUFFER_IMMUTABLE_STORAGE"/>
+            <enum name="GL_BUFFER_STORAGE_FLAGS"/>
+            <command name="glBufferStorage"/>
+        </require>
+        <require comment="Reuse GL_ARB_clear_texture">
+            <enum name="GL_CLEAR_TEXTURE"/>
+            <command name="glClearTexImage"/>
+            <command name="glClearTexSubImage"/>
+        </require>
+        <require comment="Reuse GL_ARB_enhanced_layouts">
+            <enum name="GL_LOCATION_COMPONENT"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_INDEX"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE"/>
+        </require>
+        <require comment="Reuse GL_ARB_multi_bind (none)">
+            <command name="glBindBuffersBase"/>
+            <command name="glBindBuffersRange"/>
+            <command name="glBindTextures"/>
+            <command name="glBindSamplers"/>
+            <command name="glBindImageTextures"/>
+            <command name="glBindVertexBuffers"/>
+        </require>
+        <require comment="Reuse GL_ARB_query_buffer_object">
+            <enum name="GL_QUERY_BUFFER"/>
+            <enum name="GL_QUERY_BUFFER_BARRIER_BIT"/>
+            <enum name="GL_QUERY_BUFFER_BINDING"/>
+            <enum name="GL_QUERY_RESULT_NO_WAIT"/>
+        </require>
+        <require comment="Reuse GL_ARB_texture_mirror_clamp_to_edge">
+            <enum name="GL_MIRROR_CLAMP_TO_EDGE"/>
+        </require>
+        <require comment="Reuse GL_ARB_texture_stencil8">
+            <enum name="GL_STENCIL_INDEX"/>
+            <enum name="GL_STENCIL_INDEX8"/>
+        </require>
+        <require comment="Reuse GL_ARB_vertex_type_10f_11f_11f_rev">
+            <enum name="GL_UNSIGNED_INT_10F_11F_11F_REV"/>
+        </require>
+    </feature>
+    <feature api="gl" name="GL_VERSION_4_5" number="4.5">
+        <require comment="Added robustness functionality">
+            <enum name="GL_CONTEXT_LOST"/>
+        </require>
+        <require comment="Reuse GL_ARB_clip_control">
+            <command name="glClipControl"/>
+            <enum name="GL_LOWER_LEFT"/>
+            <enum name="GL_UPPER_LEFT"/>
+            <enum name="GL_NEGATIVE_ONE_TO_ONE"/>
+            <enum name="GL_ZERO_TO_ONE"/>
+            <enum name="GL_CLIP_ORIGIN"/>
+            <enum name="GL_CLIP_DEPTH_MODE"/>
+        </require>
+        <require comment="Reuse GL_ARB_conditional_render_inverted">
+            <enum name="GL_QUERY_WAIT_INVERTED"/>
+            <enum name="GL_QUERY_NO_WAIT_INVERTED"/>
+            <enum name="GL_QUERY_BY_REGION_WAIT_INVERTED"/>
+            <enum name="GL_QUERY_BY_REGION_NO_WAIT_INVERTED"/>
+        </require>
+        <require comment="Reuse GL_ARB_cull_distance">
+            <enum name="GL_MAX_CULL_DISTANCES"/>
+            <enum name="GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES"/>
+        </require>
+        <require comment="Reuse GL_ARB_direct_state_access">
+            <enum name="GL_TEXTURE_TARGET"/>
+            <enum name="GL_QUERY_TARGET"/>
+            <enum name="GL_TEXTURE_BINDING_1D"/>
+            <enum name="GL_TEXTURE_BINDING_1D_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_2D"/>
+            <enum name="GL_TEXTURE_BINDING_2D_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE"/>
+            <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_3D"/>
+            <enum name="GL_TEXTURE_BINDING_BUFFER"/>
+            <enum name="GL_TEXTURE_BINDING_CUBE_MAP"/>
+            <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_RECTANGLE"/>
+            <command name="glCreateTransformFeedbacks"/>
+            <command name="glTransformFeedbackBufferBase"/>
+            <command name="glTransformFeedbackBufferRange"/>
+            <command name="glGetTransformFeedbackiv"/>
+            <command name="glGetTransformFeedbacki_v"/>
+            <command name="glGetTransformFeedbacki64_v"/>
+            <command name="glCreateBuffers"/>
+            <command name="glNamedBufferStorage"/>
+            <command name="glNamedBufferData"/>
+            <command name="glNamedBufferSubData"/>
+            <command name="glCopyNamedBufferSubData"/>
+            <command name="glClearNamedBufferData"/>
+            <command name="glClearNamedBufferSubData"/>
+            <command name="glMapNamedBuffer"/>
+            <command name="glMapNamedBufferRange"/>
+            <command name="glUnmapNamedBuffer"/>
+            <command name="glFlushMappedNamedBufferRange"/>
+            <command name="glGetNamedBufferParameteriv"/>
+            <command name="glGetNamedBufferParameteri64v"/>
+            <command name="glGetNamedBufferPointerv"/>
+            <command name="glGetNamedBufferSubData"/>
+            <command name="glCreateFramebuffers"/>
+            <command name="glNamedFramebufferRenderbuffer"/>
+            <command name="glNamedFramebufferParameteri"/>
+            <command name="glNamedFramebufferTexture"/>
+            <command name="glNamedFramebufferTextureLayer"/>
+            <command name="glNamedFramebufferDrawBuffer"/>
+            <command name="glNamedFramebufferDrawBuffers"/>
+            <command name="glNamedFramebufferReadBuffer"/>
+            <command name="glInvalidateNamedFramebufferData"/>
+            <command name="glInvalidateNamedFramebufferSubData"/>
+            <command name="glClearNamedFramebufferiv"/>
+            <command name="glClearNamedFramebufferuiv"/>
+            <command name="glClearNamedFramebufferfv"/>
+            <command name="glClearNamedFramebufferfi"/>
+            <command name="glBlitNamedFramebuffer"/>
+            <command name="glCheckNamedFramebufferStatus"/>
+            <command name="glGetNamedFramebufferParameteriv"/>
+            <command name="glGetNamedFramebufferAttachmentParameteriv"/>
+            <command name="glCreateRenderbuffers"/>
+            <command name="glNamedRenderbufferStorage"/>
+            <command name="glNamedRenderbufferStorageMultisample"/>
+            <command name="glGetNamedRenderbufferParameteriv"/>
+            <command name="glCreateTextures"/>
+            <command name="glTextureBuffer"/>
+            <command name="glTextureBufferRange"/>
+            <command name="glTextureStorage1D"/>
+            <command name="glTextureStorage2D"/>
+            <command name="glTextureStorage3D"/>
+            <command name="glTextureStorage2DMultisample"/>
+            <command name="glTextureStorage3DMultisample"/>
+            <command name="glTextureSubImage1D"/>
+            <command name="glTextureSubImage2D"/>
+            <command name="glTextureSubImage3D"/>
+            <command name="glCompressedTextureSubImage1D"/>
+            <command name="glCompressedTextureSubImage2D"/>
+            <command name="glCompressedTextureSubImage3D"/>
+            <command name="glCopyTextureSubImage1D"/>
+            <command name="glCopyTextureSubImage2D"/>
+            <command name="glCopyTextureSubImage3D"/>
+            <command name="glTextureParameterf"/>
+            <command name="glTextureParameterfv"/>
+            <command name="glTextureParameteri"/>
+            <command name="glTextureParameterIiv"/>
+            <command name="glTextureParameterIuiv"/>
+            <command name="glTextureParameteriv"/>
+            <command name="glGenerateTextureMipmap"/>
+            <command name="glBindTextureUnit"/>
+            <command name="glGetTextureImage"/>
+            <command name="glGetCompressedTextureImage"/>
+            <command name="glGetTextureLevelParameterfv"/>
+            <command name="glGetTextureLevelParameteriv"/>
+            <command name="glGetTextureParameterfv"/>
+            <command name="glGetTextureParameterIiv"/>
+            <command name="glGetTextureParameterIuiv"/>
+            <command name="glGetTextureParameteriv"/>
+            <command name="glCreateVertexArrays"/>
+            <command name="glDisableVertexArrayAttrib"/>
+            <command name="glEnableVertexArrayAttrib"/>
+            <command name="glVertexArrayElementBuffer"/>
+            <command name="glVertexArrayVertexBuffer"/>
+            <command name="glVertexArrayVertexBuffers"/>
+            <command name="glVertexArrayAttribBinding"/>
+            <command name="glVertexArrayAttribFormat"/>
+            <command name="glVertexArrayAttribIFormat"/>
+            <command name="glVertexArrayAttribLFormat"/>
+            <command name="glVertexArrayBindingDivisor"/>
+            <command name="glGetVertexArrayiv"/>
+            <command name="glGetVertexArrayIndexediv"/>
+            <command name="glGetVertexArrayIndexed64iv"/>
+            <command name="glCreateSamplers"/>
+            <command name="glCreateProgramPipelines"/>
+            <command name="glCreateQueries"/>
+            <command name="glGetQueryBufferObjecti64v"/>
+            <command name="glGetQueryBufferObjectiv"/>
+            <command name="glGetQueryBufferObjectui64v"/>
+            <command name="glGetQueryBufferObjectuiv"/>
+        </require>
+        <require comment="Reuse GL_ARB_ES3_1_compatibility">
+            <enum name="GL_BACK"/>
+            <command name="glMemoryBarrierByRegion"/>
+        </require>
+        <require comment="Reuse GL_ARB_get_texture_sub_image">
+            <command name="glGetTextureSubImage"/>
+            <command name="glGetCompressedTextureSubImage"/>
+        </require>
+        <require comment="Reuse GL_ARB_robustness">
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_GUILTY_CONTEXT_RESET"/>
+            <enum name="GL_INNOCENT_CONTEXT_RESET"/>
+            <enum name="GL_UNKNOWN_CONTEXT_RESET"/>
+            <enum name="GL_RESET_NOTIFICATION_STRATEGY"/>
+            <enum name="GL_LOSE_CONTEXT_ON_RESET"/>
+            <enum name="GL_NO_RESET_NOTIFICATION"/>
+            <enum name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT"/>
+            <enum name="GL_CONTEXT_LOST"/>
+            <command name="glGetGraphicsResetStatus"/>
+            <command name="glGetnCompressedTexImage"/>
+            <command name="glGetnTexImage"/>
+            <command name="glGetnUniformdv"/>
+            <command name="glGetnUniformfv"/>
+            <command name="glGetnUniformiv"/>
+            <command name="glGetnUniformuiv"/>
+            <command name="glReadnPixels"/>
+        </require>
+        <require profile="compatibility" comment="Reuse GL_ARB_robustness">
+            <command name="glGetnMapdv"/>
+            <command name="glGetnMapfv"/>
+            <command name="glGetnMapiv"/>
+            <command name="glGetnPixelMapfv"/>
+            <command name="glGetnPixelMapuiv"/>
+            <command name="glGetnPixelMapusv"/>
+            <command name="glGetnPolygonStipple"/>
+            <command name="glGetnColorTable"/>
+            <command name="glGetnConvolutionFilter"/>
+            <command name="glGetnSeparableFilter"/>
+            <command name="glGetnHistogram"/>
+            <command name="glGetnMinmax"/>
+        </require>
+        <require comment="Reuse GL_ARB_texture_barrier">
+            <command name="glTextureBarrier"/>
+        </require>
+        <require comment="Reuse GL_KHR_context_flush_control">
+            <enum name="GL_CONTEXT_RELEASE_BEHAVIOR"/>
+            <enum name="GL_NONE"/>
+            <enum name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH"/>
+        </require>
+    </feature>
+
+    <!-- SECTION: OpenGL ES 1.0/1.1 API interface definitions. -->
+    <feature api="gles1" name="GL_VERSION_ES_CM_1_0" number="1.0">
+        <require>
+            <!-- Additional API definition macros - ES 1.0/1.1, common/common-lite all in one header -->
+            <enum name="GL_VERSION_ES_CL_1_0"/>
+            <enum name="GL_VERSION_ES_CM_1_1"/>
+            <enum name="GL_VERSION_ES_CL_1_1"/>
+            <type name="GLvoid" comment="No longer used in headers"/>
+            <enum name="GL_DEPTH_BUFFER_BIT"/>
+            <enum name="GL_STENCIL_BUFFER_BIT"/>
+            <enum name="GL_COLOR_BUFFER_BIT"/>
+            <enum name="GL_FALSE"/>
+            <enum name="GL_TRUE"/>
+            <enum name="GL_POINTS"/>
+            <enum name="GL_LINES"/>
+            <enum name="GL_LINE_LOOP"/>
+            <enum name="GL_LINE_STRIP"/>
+            <enum name="GL_TRIANGLES"/>
+            <enum name="GL_TRIANGLE_STRIP"/>
+            <enum name="GL_TRIANGLE_FAN"/>
+            <enum name="GL_NEVER"/>
+            <enum name="GL_LESS"/>
+            <enum name="GL_EQUAL"/>
+            <enum name="GL_LEQUAL"/>
+            <enum name="GL_GREATER"/>
+            <enum name="GL_NOTEQUAL"/>
+            <enum name="GL_GEQUAL"/>
+            <enum name="GL_ALWAYS"/>
+            <enum name="GL_ZERO"/>
+            <enum name="GL_ONE"/>
+            <enum name="GL_SRC_COLOR"/>
+            <enum name="GL_ONE_MINUS_SRC_COLOR"/>
+            <enum name="GL_SRC_ALPHA"/>
+            <enum name="GL_ONE_MINUS_SRC_ALPHA"/>
+            <enum name="GL_DST_ALPHA"/>
+            <enum name="GL_ONE_MINUS_DST_ALPHA"/>
+            <enum name="GL_DST_COLOR"/>
+            <enum name="GL_ONE_MINUS_DST_COLOR"/>
+            <enum name="GL_SRC_ALPHA_SATURATE"/>
+            <enum name="GL_CLIP_PLANE0"/>
+            <enum name="GL_CLIP_PLANE1"/>
+            <enum name="GL_CLIP_PLANE2"/>
+            <enum name="GL_CLIP_PLANE3"/>
+            <enum name="GL_CLIP_PLANE4"/>
+            <enum name="GL_CLIP_PLANE5"/>
+            <enum name="GL_FRONT"/>
+            <enum name="GL_BACK"/>
+            <enum name="GL_FRONT_AND_BACK"/>
+            <enum name="GL_FOG"/>
+            <enum name="GL_LIGHTING"/>
+            <enum name="GL_TEXTURE_2D"/>
+            <enum name="GL_CULL_FACE"/>
+            <enum name="GL_ALPHA_TEST"/>
+            <enum name="GL_BLEND"/>
+            <enum name="GL_COLOR_LOGIC_OP"/>
+            <enum name="GL_DITHER"/>
+            <enum name="GL_STENCIL_TEST"/>
+            <enum name="GL_DEPTH_TEST"/>
+            <enum name="GL_POINT_SMOOTH"/>
+            <enum name="GL_LINE_SMOOTH"/>
+            <enum name="GL_SCISSOR_TEST"/>
+            <enum name="GL_COLOR_MATERIAL"/>
+            <enum name="GL_NORMALIZE"/>
+            <enum name="GL_RESCALE_NORMAL"/>
+            <enum name="GL_VERTEX_ARRAY"/>
+            <enum name="GL_NORMAL_ARRAY"/>
+            <enum name="GL_COLOR_ARRAY"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY"/>
+            <enum name="GL_MULTISAMPLE"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_COVERAGE"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_ONE"/>
+            <enum name="GL_SAMPLE_COVERAGE"/>
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_INVALID_ENUM"/>
+            <enum name="GL_INVALID_VALUE"/>
+            <enum name="GL_INVALID_OPERATION"/>
+            <enum name="GL_STACK_OVERFLOW"/>
+            <enum name="GL_STACK_UNDERFLOW"/>
+            <enum name="GL_OUT_OF_MEMORY"/>
+            <enum name="GL_EXP"/>
+            <enum name="GL_EXP2"/>
+            <enum name="GL_FOG_DENSITY"/>
+            <enum name="GL_FOG_START"/>
+            <enum name="GL_FOG_END"/>
+            <enum name="GL_FOG_MODE"/>
+            <enum name="GL_FOG_COLOR"/>
+            <enum name="GL_CW"/>
+            <enum name="GL_CCW"/>
+            <enum name="GL_CURRENT_COLOR"/>
+            <enum name="GL_CURRENT_NORMAL"/>
+            <enum name="GL_CURRENT_TEXTURE_COORDS"/>
+            <enum name="GL_POINT_SIZE"/>
+            <enum name="GL_POINT_SIZE_MIN"/>
+            <enum name="GL_POINT_SIZE_MAX"/>
+            <enum name="GL_POINT_FADE_THRESHOLD_SIZE"/>
+            <enum name="GL_POINT_DISTANCE_ATTENUATION"/>
+            <enum name="GL_SMOOTH_POINT_SIZE_RANGE"/>
+            <enum name="GL_LINE_WIDTH"/>
+            <enum name="GL_SMOOTH_LINE_WIDTH_RANGE"/>
+            <enum name="GL_ALIASED_POINT_SIZE_RANGE"/>
+            <enum name="GL_ALIASED_LINE_WIDTH_RANGE"/>
+            <enum name="GL_CULL_FACE_MODE"/>
+            <enum name="GL_FRONT_FACE"/>
+            <enum name="GL_SHADE_MODEL"/>
+            <enum name="GL_DEPTH_RANGE"/>
+            <enum name="GL_DEPTH_WRITEMASK"/>
+            <enum name="GL_DEPTH_CLEAR_VALUE"/>
+            <enum name="GL_DEPTH_FUNC"/>
+            <enum name="GL_STENCIL_CLEAR_VALUE"/>
+            <enum name="GL_STENCIL_FUNC"/>
+            <enum name="GL_STENCIL_VALUE_MASK"/>
+            <enum name="GL_STENCIL_FAIL"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_FAIL"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_PASS"/>
+            <enum name="GL_STENCIL_REF"/>
+            <enum name="GL_STENCIL_WRITEMASK"/>
+            <enum name="GL_MATRIX_MODE"/>
+            <enum name="GL_VIEWPORT"/>
+            <enum name="GL_MODELVIEW_STACK_DEPTH"/>
+            <enum name="GL_PROJECTION_STACK_DEPTH"/>
+            <enum name="GL_TEXTURE_STACK_DEPTH"/>
+            <enum name="GL_MODELVIEW_MATRIX"/>
+            <enum name="GL_PROJECTION_MATRIX"/>
+            <enum name="GL_TEXTURE_MATRIX"/>
+            <enum name="GL_ALPHA_TEST_FUNC"/>
+            <enum name="GL_ALPHA_TEST_REF"/>
+            <enum name="GL_BLEND_DST"/>
+            <enum name="GL_BLEND_SRC"/>
+            <enum name="GL_LOGIC_OP_MODE"/>
+            <enum name="GL_SCISSOR_BOX"/>
+            <enum name="GL_COLOR_CLEAR_VALUE"/>
+            <enum name="GL_COLOR_WRITEMASK"/>
+            <enum name="GL_MAX_LIGHTS"/>
+            <enum name="GL_MAX_CLIP_PLANES"/>
+            <enum name="GL_MAX_TEXTURE_SIZE"/>
+            <enum name="GL_MAX_MODELVIEW_STACK_DEPTH"/>
+            <enum name="GL_MAX_PROJECTION_STACK_DEPTH"/>
+            <enum name="GL_MAX_TEXTURE_STACK_DEPTH"/>
+            <enum name="GL_MAX_VIEWPORT_DIMS"/>
+            <enum name="GL_MAX_TEXTURE_UNITS"/>
+            <enum name="GL_SUBPIXEL_BITS"/>
+            <enum name="GL_RED_BITS"/>
+            <enum name="GL_GREEN_BITS"/>
+            <enum name="GL_BLUE_BITS"/>
+            <enum name="GL_ALPHA_BITS"/>
+            <enum name="GL_DEPTH_BITS"/>
+            <enum name="GL_STENCIL_BITS"/>
+            <enum name="GL_POLYGON_OFFSET_UNITS"/>
+            <enum name="GL_POLYGON_OFFSET_FILL"/>
+            <enum name="GL_POLYGON_OFFSET_FACTOR"/>
+            <enum name="GL_TEXTURE_BINDING_2D"/>
+            <enum name="GL_VERTEX_ARRAY_SIZE"/>
+            <enum name="GL_VERTEX_ARRAY_TYPE"/>
+            <enum name="GL_VERTEX_ARRAY_STRIDE"/>
+            <enum name="GL_NORMAL_ARRAY_TYPE"/>
+            <enum name="GL_NORMAL_ARRAY_STRIDE"/>
+            <enum name="GL_COLOR_ARRAY_SIZE"/>
+            <enum name="GL_COLOR_ARRAY_TYPE"/>
+            <enum name="GL_COLOR_ARRAY_STRIDE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_SIZE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_TYPE"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_STRIDE"/>
+            <enum name="GL_VERTEX_ARRAY_POINTER"/>
+            <enum name="GL_NORMAL_ARRAY_POINTER"/>
+            <enum name="GL_COLOR_ARRAY_POINTER"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_POINTER"/>
+            <enum name="GL_SAMPLE_BUFFERS"/>
+            <enum name="GL_SAMPLES"/>
+            <enum name="GL_SAMPLE_COVERAGE_VALUE"/>
+            <enum name="GL_SAMPLE_COVERAGE_INVERT"/>
+            <enum name="GL_NUM_COMPRESSED_TEXTURE_FORMATS"/>
+            <enum name="GL_COMPRESSED_TEXTURE_FORMATS"/>
+            <enum name="GL_DONT_CARE"/>
+            <enum name="GL_FASTEST"/>
+            <enum name="GL_NICEST"/>
+            <enum name="GL_PERSPECTIVE_CORRECTION_HINT"/>
+            <enum name="GL_POINT_SMOOTH_HINT"/>
+            <enum name="GL_LINE_SMOOTH_HINT"/>
+            <enum name="GL_FOG_HINT"/>
+            <enum name="GL_GENERATE_MIPMAP_HINT"/>
+            <enum name="GL_LIGHT_MODEL_AMBIENT"/>
+            <enum name="GL_LIGHT_MODEL_TWO_SIDE"/>
+            <enum name="GL_AMBIENT"/>
+            <enum name="GL_DIFFUSE"/>
+            <enum name="GL_SPECULAR"/>
+            <enum name="GL_POSITION"/>
+            <enum name="GL_SPOT_DIRECTION"/>
+            <enum name="GL_SPOT_EXPONENT"/>
+            <enum name="GL_SPOT_CUTOFF"/>
+            <enum name="GL_CONSTANT_ATTENUATION"/>
+            <enum name="GL_LINEAR_ATTENUATION"/>
+            <enum name="GL_QUADRATIC_ATTENUATION"/>
+            <enum name="GL_BYTE"/>
+            <enum name="GL_UNSIGNED_BYTE"/>
+            <enum name="GL_SHORT"/>
+            <enum name="GL_UNSIGNED_SHORT"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_FIXED"/>
+            <enum name="GL_CLEAR"/>
+            <enum name="GL_AND"/>
+            <enum name="GL_AND_REVERSE"/>
+            <enum name="GL_COPY"/>
+            <enum name="GL_AND_INVERTED"/>
+            <enum name="GL_NOOP"/>
+            <enum name="GL_XOR"/>
+            <enum name="GL_OR"/>
+            <enum name="GL_NOR"/>
+            <enum name="GL_EQUIV"/>
+            <enum name="GL_INVERT"/>
+            <enum name="GL_OR_REVERSE"/>
+            <enum name="GL_COPY_INVERTED"/>
+            <enum name="GL_OR_INVERTED"/>
+            <enum name="GL_NAND"/>
+            <enum name="GL_SET"/>
+            <enum name="GL_EMISSION"/>
+            <enum name="GL_SHININESS"/>
+            <enum name="GL_AMBIENT_AND_DIFFUSE"/>
+            <enum name="GL_MODELVIEW"/>
+            <enum name="GL_PROJECTION"/>
+            <enum name="GL_TEXTURE"/>
+            <enum name="GL_ALPHA"/>
+            <enum name="GL_RGB"/>
+            <enum name="GL_RGBA"/>
+            <enum name="GL_LUMINANCE"/>
+            <enum name="GL_LUMINANCE_ALPHA"/>
+            <enum name="GL_UNPACK_ALIGNMENT"/>
+            <enum name="GL_PACK_ALIGNMENT"/>
+            <enum name="GL_UNSIGNED_SHORT_4_4_4_4"/>
+            <enum name="GL_UNSIGNED_SHORT_5_5_5_1"/>
+            <enum name="GL_UNSIGNED_SHORT_5_6_5"/>
+            <enum name="GL_FLAT"/>
+            <enum name="GL_SMOOTH"/>
+            <enum name="GL_KEEP"/>
+            <enum name="GL_REPLACE"/>
+            <enum name="GL_INCR"/>
+            <enum name="GL_DECR"/>
+            <enum name="GL_VENDOR"/>
+            <enum name="GL_RENDERER"/>
+            <enum name="GL_VERSION"/>
+            <enum name="GL_EXTENSIONS"/>
+            <enum name="GL_MODULATE"/>
+            <enum name="GL_DECAL"/>
+            <enum name="GL_ADD"/>
+            <enum name="GL_TEXTURE_ENV_MODE"/>
+            <enum name="GL_TEXTURE_ENV_COLOR"/>
+            <enum name="GL_TEXTURE_ENV"/>
+            <enum name="GL_NEAREST"/>
+            <enum name="GL_LINEAR"/>
+            <enum name="GL_NEAREST_MIPMAP_NEAREST"/>
+            <enum name="GL_LINEAR_MIPMAP_NEAREST"/>
+            <enum name="GL_NEAREST_MIPMAP_LINEAR"/>
+            <enum name="GL_LINEAR_MIPMAP_LINEAR"/>
+            <enum name="GL_TEXTURE_MAG_FILTER"/>
+            <enum name="GL_TEXTURE_MIN_FILTER"/>
+            <enum name="GL_TEXTURE_WRAP_S"/>
+            <enum name="GL_TEXTURE_WRAP_T"/>
+            <enum name="GL_GENERATE_MIPMAP"/>
+            <enum name="GL_TEXTURE0"/>
+            <enum name="GL_TEXTURE1"/>
+            <enum name="GL_TEXTURE2"/>
+            <enum name="GL_TEXTURE3"/>
+            <enum name="GL_TEXTURE4"/>
+            <enum name="GL_TEXTURE5"/>
+            <enum name="GL_TEXTURE6"/>
+            <enum name="GL_TEXTURE7"/>
+            <enum name="GL_TEXTURE8"/>
+            <enum name="GL_TEXTURE9"/>
+            <enum name="GL_TEXTURE10"/>
+            <enum name="GL_TEXTURE11"/>
+            <enum name="GL_TEXTURE12"/>
+            <enum name="GL_TEXTURE13"/>
+            <enum name="GL_TEXTURE14"/>
+            <enum name="GL_TEXTURE15"/>
+            <enum name="GL_TEXTURE16"/>
+            <enum name="GL_TEXTURE17"/>
+            <enum name="GL_TEXTURE18"/>
+            <enum name="GL_TEXTURE19"/>
+            <enum name="GL_TEXTURE20"/>
+            <enum name="GL_TEXTURE21"/>
+            <enum name="GL_TEXTURE22"/>
+            <enum name="GL_TEXTURE23"/>
+            <enum name="GL_TEXTURE24"/>
+            <enum name="GL_TEXTURE25"/>
+            <enum name="GL_TEXTURE26"/>
+            <enum name="GL_TEXTURE27"/>
+            <enum name="GL_TEXTURE28"/>
+            <enum name="GL_TEXTURE29"/>
+            <enum name="GL_TEXTURE30"/>
+            <enum name="GL_TEXTURE31"/>
+            <enum name="GL_ACTIVE_TEXTURE"/>
+            <enum name="GL_CLIENT_ACTIVE_TEXTURE"/>
+            <enum name="GL_REPEAT"/>
+            <enum name="GL_CLAMP_TO_EDGE"/>
+            <enum name="GL_LIGHT0"/>
+            <enum name="GL_LIGHT1"/>
+            <enum name="GL_LIGHT2"/>
+            <enum name="GL_LIGHT3"/>
+            <enum name="GL_LIGHT4"/>
+            <enum name="GL_LIGHT5"/>
+            <enum name="GL_LIGHT6"/>
+            <enum name="GL_LIGHT7"/>
+            <enum name="GL_ARRAY_BUFFER"/>
+            <enum name="GL_ELEMENT_ARRAY_BUFFER"/>
+            <enum name="GL_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_ELEMENT_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_VERTEX_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_NORMAL_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_COLOR_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_STATIC_DRAW"/>
+            <enum name="GL_DYNAMIC_DRAW"/>
+            <enum name="GL_BUFFER_SIZE"/>
+            <enum name="GL_BUFFER_USAGE"/>
+            <enum name="GL_SUBTRACT"/>
+            <enum name="GL_COMBINE"/>
+            <enum name="GL_COMBINE_RGB"/>
+            <enum name="GL_COMBINE_ALPHA"/>
+            <enum name="GL_RGB_SCALE"/>
+            <enum name="GL_ADD_SIGNED"/>
+            <enum name="GL_INTERPOLATE"/>
+            <enum name="GL_CONSTANT"/>
+            <enum name="GL_PRIMARY_COLOR"/>
+            <enum name="GL_PREVIOUS"/>
+            <enum name="GL_OPERAND0_RGB"/>
+            <enum name="GL_OPERAND1_RGB"/>
+            <enum name="GL_OPERAND2_RGB"/>
+            <enum name="GL_OPERAND0_ALPHA"/>
+            <enum name="GL_OPERAND1_ALPHA"/>
+            <enum name="GL_OPERAND2_ALPHA"/>
+            <enum name="GL_ALPHA_SCALE"/>
+            <enum name="GL_SRC0_RGB"/>
+            <enum name="GL_SRC1_RGB"/>
+            <enum name="GL_SRC2_RGB"/>
+            <enum name="GL_SRC0_ALPHA"/>
+            <enum name="GL_SRC1_ALPHA"/>
+            <enum name="GL_SRC2_ALPHA"/>
+            <enum name="GL_DOT3_RGB"/>
+            <enum name="GL_DOT3_RGBA"/>
+        </require>
+        <require profile="common">
+            <command name="glAlphaFunc"/>
+            <command name="glClearColor"/>
+            <command name="glClearDepthf"/>
+            <command name="glClipPlanef"/>
+            <command name="glColor4f"/>
+            <command name="glDepthRangef"/>
+            <command name="glFogf"/>
+            <command name="glFogfv"/>
+            <command name="glFrustumf"/>
+            <command name="glGetClipPlanef"/>
+            <command name="glGetFloatv"/>
+            <command name="glGetLightfv"/>
+            <command name="glGetMaterialfv"/>
+            <command name="glGetTexEnvfv"/>
+            <command name="glGetTexParameterfv"/>
+            <command name="glLightModelf"/>
+            <command name="glLightModelfv"/>
+            <command name="glLightf"/>
+            <command name="glLightfv"/>
+            <command name="glLineWidth"/>
+            <command name="glLoadMatrixf"/>
+            <command name="glMaterialf"/>
+            <command name="glMaterialfv"/>
+            <command name="glMultMatrixf"/>
+            <command name="glMultiTexCoord4f"/>
+            <command name="glNormal3f"/>
+            <command name="glOrthof"/>
+            <command name="glPointParameterf"/>
+            <command name="glPointParameterfv"/>
+            <command name="glPointSize"/>
+            <command name="glPolygonOffset"/>
+            <command name="glRotatef"/>
+            <command name="glScalef"/>
+            <command name="glTexEnvf"/>
+            <command name="glTexEnvfv"/>
+            <command name="glTexParameterf"/>
+            <command name="glTexParameterfv"/>
+            <command name="glTranslatef"/>
+        </require>
+        <require>
+            <command name="glActiveTexture"/>
+            <command name="glAlphaFuncx"/>
+            <command name="glBindBuffer"/>
+            <command name="glBindTexture"/>
+            <command name="glBlendFunc"/>
+            <command name="glBufferData"/>
+            <command name="glBufferSubData"/>
+            <command name="glClear"/>
+            <command name="glClearColorx"/>
+            <command name="glClearDepthx"/>
+            <command name="glClearStencil"/>
+            <command name="glClientActiveTexture"/>
+            <command name="glClipPlanex"/>
+            <command name="glColor4ub"/>
+            <command name="glColor4x"/>
+            <command name="glColorMask"/>
+            <command name="glColorPointer"/>
+            <command name="glCompressedTexImage2D"/>
+            <command name="glCompressedTexSubImage2D"/>
+            <command name="glCopyTexImage2D"/>
+            <command name="glCopyTexSubImage2D"/>
+            <command name="glCullFace"/>
+            <command name="glDeleteBuffers"/>
+            <command name="glDeleteTextures"/>
+            <command name="glDepthFunc"/>
+            <command name="glDepthMask"/>
+            <command name="glDepthRangex"/>
+            <command name="glDisable"/>
+            <command name="glDisableClientState"/>
+            <command name="glDrawArrays"/>
+            <command name="glDrawElements"/>
+            <command name="glEnable"/>
+            <command name="glEnableClientState"/>
+            <command name="glFinish"/>
+            <command name="glFlush"/>
+            <command name="glFogx"/>
+            <command name="glFogxv"/>
+            <command name="glFrontFace"/>
+            <command name="glFrustumx"/>
+            <command name="glGetBooleanv"/>
+            <command name="glGetBufferParameteriv"/>
+            <command name="glGetClipPlanex"/>
+            <command name="glGenBuffers"/>
+            <command name="glGenTextures"/>
+            <command name="glGetError"/>
+            <command name="glGetFixedv"/>
+            <command name="glGetIntegerv"/>
+            <command name="glGetLightxv"/>
+            <command name="glGetMaterialxv"/>
+            <command name="glGetPointerv"/>
+            <command name="glGetString"/>
+            <command name="glGetTexEnviv"/>
+            <command name="glGetTexEnvxv"/>
+            <command name="glGetTexParameteriv"/>
+            <command name="glGetTexParameterxv"/>
+            <command name="glHint"/>
+            <command name="glIsBuffer"/>
+            <command name="glIsEnabled"/>
+            <command name="glIsTexture"/>
+            <command name="glLightModelx"/>
+            <command name="glLightModelxv"/>
+            <command name="glLightx"/>
+            <command name="glLightxv"/>
+            <command name="glLineWidthx"/>
+            <command name="glLoadIdentity"/>
+            <command name="glLoadMatrixx"/>
+            <command name="glLogicOp"/>
+            <command name="glMaterialx"/>
+            <command name="glMaterialxv"/>
+            <command name="glMatrixMode"/>
+            <command name="glMultMatrixx"/>
+            <command name="glMultiTexCoord4x"/>
+            <command name="glNormal3x"/>
+            <command name="glNormalPointer"/>
+            <command name="glOrthox"/>
+            <command name="glPixelStorei"/>
+            <command name="glPointParameterx"/>
+            <command name="glPointParameterxv"/>
+            <command name="glPointSizex"/>
+            <command name="glPolygonOffsetx"/>
+            <command name="glPopMatrix"/>
+            <command name="glPushMatrix"/>
+            <command name="glReadPixels"/>
+            <command name="glRotatex"/>
+            <command name="glSampleCoverage"/>
+            <command name="glSampleCoveragex"/>
+            <command name="glScalex"/>
+            <command name="glScissor"/>
+            <command name="glShadeModel"/>
+            <command name="glStencilFunc"/>
+            <command name="glStencilMask"/>
+            <command name="glStencilOp"/>
+            <command name="glTexCoordPointer"/>
+            <command name="glTexEnvi"/>
+            <command name="glTexEnvx"/>
+            <command name="glTexEnviv"/>
+            <command name="glTexEnvxv"/>
+            <command name="glTexImage2D"/>
+            <command name="glTexParameteri"/>
+            <command name="glTexParameterx"/>
+            <command name="glTexParameteriv"/>
+            <command name="glTexParameterxv"/>
+            <command name="glTexSubImage2D"/>
+            <command name="glTranslatex"/>
+            <command name="glVertexPointer"/>
+            <command name="glViewport"/>
+        </require>
+    </feature>
+    <feature api="gles2" name="GL_ES_VERSION_2_0" number="2.0">
+        <require comment="Not used by the API, for compatibility with old gl2.h">
+            <type name="GLbyte"/>
+            <type name="GLclampf"/>
+            <type name="GLfixed"/>
+            <type name="GLshort"/>
+            <type name="GLushort"/>
+            <type name="GLvoid" comment="No longer used in headers"/>
+        </require>
+        <require comment="Not used by the API; put here so this type doesn't need to be declared in gl2ext.h">
+            <type name="GLsync"/>
+            <type name="GLint64"/>
+            <type name="GLuint64"/>
+        </require>
+        <require>
+            <enum name="GL_DEPTH_BUFFER_BIT"/>
+            <enum name="GL_STENCIL_BUFFER_BIT"/>
+            <enum name="GL_COLOR_BUFFER_BIT"/>
+            <enum name="GL_FALSE"/>
+            <enum name="GL_TRUE"/>
+            <enum name="GL_POINTS"/>
+            <enum name="GL_LINES"/>
+            <enum name="GL_LINE_LOOP"/>
+            <enum name="GL_LINE_STRIP"/>
+            <enum name="GL_TRIANGLES"/>
+            <enum name="GL_TRIANGLE_STRIP"/>
+            <enum name="GL_TRIANGLE_FAN"/>
+            <enum name="GL_ZERO"/>
+            <enum name="GL_ONE"/>
+            <enum name="GL_SRC_COLOR"/>
+            <enum name="GL_ONE_MINUS_SRC_COLOR"/>
+            <enum name="GL_SRC_ALPHA"/>
+            <enum name="GL_ONE_MINUS_SRC_ALPHA"/>
+            <enum name="GL_DST_ALPHA"/>
+            <enum name="GL_ONE_MINUS_DST_ALPHA"/>
+            <enum name="GL_DST_COLOR"/>
+            <enum name="GL_ONE_MINUS_DST_COLOR"/>
+            <enum name="GL_SRC_ALPHA_SATURATE"/>
+            <enum name="GL_FUNC_ADD"/>
+            <enum name="GL_BLEND_EQUATION"/>
+            <enum name="GL_BLEND_EQUATION_RGB"/>
+            <enum name="GL_BLEND_EQUATION_ALPHA"/>
+            <enum name="GL_FUNC_SUBTRACT"/>
+            <enum name="GL_FUNC_REVERSE_SUBTRACT"/>
+            <enum name="GL_BLEND_DST_RGB"/>
+            <enum name="GL_BLEND_SRC_RGB"/>
+            <enum name="GL_BLEND_DST_ALPHA"/>
+            <enum name="GL_BLEND_SRC_ALPHA"/>
+            <enum name="GL_CONSTANT_COLOR"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_COLOR"/>
+            <enum name="GL_CONSTANT_ALPHA"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_ALPHA"/>
+            <enum name="GL_BLEND_COLOR"/>
+            <enum name="GL_ARRAY_BUFFER"/>
+            <enum name="GL_ELEMENT_ARRAY_BUFFER"/>
+            <enum name="GL_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_ELEMENT_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_STREAM_DRAW"/>
+            <enum name="GL_STATIC_DRAW"/>
+            <enum name="GL_DYNAMIC_DRAW"/>
+            <enum name="GL_BUFFER_SIZE"/>
+            <enum name="GL_BUFFER_USAGE"/>
+            <enum name="GL_CURRENT_VERTEX_ATTRIB"/>
+            <enum name="GL_FRONT"/>
+            <enum name="GL_BACK"/>
+            <enum name="GL_FRONT_AND_BACK"/>
+            <enum name="GL_TEXTURE_2D"/>
+            <enum name="GL_CULL_FACE"/>
+            <enum name="GL_BLEND"/>
+            <enum name="GL_DITHER"/>
+            <enum name="GL_STENCIL_TEST"/>
+            <enum name="GL_DEPTH_TEST"/>
+            <enum name="GL_SCISSOR_TEST"/>
+            <enum name="GL_POLYGON_OFFSET_FILL"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_COVERAGE"/>
+            <enum name="GL_SAMPLE_COVERAGE"/>
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_INVALID_ENUM"/>
+            <enum name="GL_INVALID_VALUE"/>
+            <enum name="GL_INVALID_OPERATION"/>
+            <enum name="GL_OUT_OF_MEMORY"/>
+            <enum name="GL_CW"/>
+            <enum name="GL_CCW"/>
+            <enum name="GL_LINE_WIDTH"/>
+            <enum name="GL_ALIASED_POINT_SIZE_RANGE"/>
+            <enum name="GL_ALIASED_LINE_WIDTH_RANGE"/>
+            <enum name="GL_CULL_FACE_MODE"/>
+            <enum name="GL_FRONT_FACE"/>
+            <enum name="GL_DEPTH_RANGE"/>
+            <enum name="GL_DEPTH_WRITEMASK"/>
+            <enum name="GL_DEPTH_CLEAR_VALUE"/>
+            <enum name="GL_DEPTH_FUNC"/>
+            <enum name="GL_STENCIL_CLEAR_VALUE"/>
+            <enum name="GL_STENCIL_FUNC"/>
+            <enum name="GL_STENCIL_FAIL"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_FAIL"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_PASS"/>
+            <enum name="GL_STENCIL_REF"/>
+            <enum name="GL_STENCIL_VALUE_MASK"/>
+            <enum name="GL_STENCIL_WRITEMASK"/>
+            <enum name="GL_STENCIL_BACK_FUNC"/>
+            <enum name="GL_STENCIL_BACK_FAIL"/>
+            <enum name="GL_STENCIL_BACK_PASS_DEPTH_FAIL"/>
+            <enum name="GL_STENCIL_BACK_PASS_DEPTH_PASS"/>
+            <enum name="GL_STENCIL_BACK_REF"/>
+            <enum name="GL_STENCIL_BACK_VALUE_MASK"/>
+            <enum name="GL_STENCIL_BACK_WRITEMASK"/>
+            <enum name="GL_VIEWPORT"/>
+            <enum name="GL_SCISSOR_BOX"/>
+            <enum name="GL_COLOR_CLEAR_VALUE"/>
+            <enum name="GL_COLOR_WRITEMASK"/>
+            <enum name="GL_UNPACK_ALIGNMENT"/>
+            <enum name="GL_PACK_ALIGNMENT"/>
+            <enum name="GL_MAX_TEXTURE_SIZE"/>
+            <enum name="GL_MAX_VIEWPORT_DIMS"/>
+            <enum name="GL_SUBPIXEL_BITS"/>
+            <enum name="GL_RED_BITS"/>
+            <enum name="GL_GREEN_BITS"/>
+            <enum name="GL_BLUE_BITS"/>
+            <enum name="GL_ALPHA_BITS"/>
+            <enum name="GL_DEPTH_BITS"/>
+            <enum name="GL_STENCIL_BITS"/>
+            <enum name="GL_POLYGON_OFFSET_UNITS"/>
+            <enum name="GL_POLYGON_OFFSET_FACTOR"/>
+            <enum name="GL_TEXTURE_BINDING_2D"/>
+            <enum name="GL_SAMPLE_BUFFERS"/>
+            <enum name="GL_SAMPLES"/>
+            <enum name="GL_SAMPLE_COVERAGE_VALUE"/>
+            <enum name="GL_SAMPLE_COVERAGE_INVERT"/>
+            <enum name="GL_NUM_COMPRESSED_TEXTURE_FORMATS"/>
+            <enum name="GL_COMPRESSED_TEXTURE_FORMATS"/>
+            <enum name="GL_DONT_CARE"/>
+            <enum name="GL_FASTEST"/>
+            <enum name="GL_NICEST"/>
+            <enum name="GL_GENERATE_MIPMAP_HINT"/>
+            <enum name="GL_BYTE"/>
+            <enum name="GL_UNSIGNED_BYTE"/>
+            <enum name="GL_SHORT"/>
+            <enum name="GL_UNSIGNED_SHORT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_UNSIGNED_INT"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_FIXED"/>
+            <enum name="GL_DEPTH_COMPONENT"/>
+            <enum name="GL_ALPHA"/>
+            <enum name="GL_RGB"/>
+            <enum name="GL_RGBA"/>
+            <enum name="GL_LUMINANCE"/>
+            <enum name="GL_LUMINANCE_ALPHA"/>
+            <enum name="GL_UNSIGNED_SHORT_4_4_4_4"/>
+            <enum name="GL_UNSIGNED_SHORT_5_5_5_1"/>
+            <enum name="GL_UNSIGNED_SHORT_5_6_5"/>
+            <enum name="GL_FRAGMENT_SHADER"/>
+            <enum name="GL_VERTEX_SHADER"/>
+            <enum name="GL_MAX_VERTEX_ATTRIBS"/>
+            <enum name="GL_MAX_VERTEX_UNIFORM_VECTORS"/>
+            <enum name="GL_MAX_VARYING_VECTORS"/>
+            <enum name="GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_FRAGMENT_UNIFORM_VECTORS"/>
+            <enum name="GL_SHADER_TYPE"/>
+            <enum name="GL_DELETE_STATUS"/>
+            <enum name="GL_LINK_STATUS"/>
+            <enum name="GL_VALIDATE_STATUS"/>
+            <enum name="GL_ATTACHED_SHADERS"/>
+            <enum name="GL_ACTIVE_UNIFORMS"/>
+            <enum name="GL_ACTIVE_UNIFORM_MAX_LENGTH"/>
+            <enum name="GL_ACTIVE_ATTRIBUTES"/>
+            <enum name="GL_ACTIVE_ATTRIBUTE_MAX_LENGTH"/>
+            <enum name="GL_SHADING_LANGUAGE_VERSION"/>
+            <enum name="GL_CURRENT_PROGRAM"/>
+            <enum name="GL_NEVER"/>
+            <enum name="GL_LESS"/>
+            <enum name="GL_EQUAL"/>
+            <enum name="GL_LEQUAL"/>
+            <enum name="GL_GREATER"/>
+            <enum name="GL_NOTEQUAL"/>
+            <enum name="GL_GEQUAL"/>
+            <enum name="GL_ALWAYS"/>
+            <enum name="GL_KEEP"/>
+            <enum name="GL_REPLACE"/>
+            <enum name="GL_INCR"/>
+            <enum name="GL_DECR"/>
+            <enum name="GL_INVERT"/>
+            <enum name="GL_INCR_WRAP"/>
+            <enum name="GL_DECR_WRAP"/>
+            <enum name="GL_VENDOR"/>
+            <enum name="GL_RENDERER"/>
+            <enum name="GL_VERSION"/>
+            <enum name="GL_EXTENSIONS"/>
+            <enum name="GL_NEAREST"/>
+            <enum name="GL_LINEAR"/>
+            <enum name="GL_NEAREST_MIPMAP_NEAREST"/>
+            <enum name="GL_LINEAR_MIPMAP_NEAREST"/>
+            <enum name="GL_NEAREST_MIPMAP_LINEAR"/>
+            <enum name="GL_LINEAR_MIPMAP_LINEAR"/>
+            <enum name="GL_TEXTURE_MAG_FILTER"/>
+            <enum name="GL_TEXTURE_MIN_FILTER"/>
+            <enum name="GL_TEXTURE_WRAP_S"/>
+            <enum name="GL_TEXTURE_WRAP_T"/>
+            <enum name="GL_TEXTURE"/>
+            <enum name="GL_TEXTURE_CUBE_MAP"/>
+            <enum name="GL_TEXTURE_BINDING_CUBE_MAP"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_X"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z"/>
+            <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"/>
+            <enum name="GL_MAX_CUBE_MAP_TEXTURE_SIZE"/>
+            <enum name="GL_TEXTURE0"/>
+            <enum name="GL_TEXTURE1"/>
+            <enum name="GL_TEXTURE2"/>
+            <enum name="GL_TEXTURE3"/>
+            <enum name="GL_TEXTURE4"/>
+            <enum name="GL_TEXTURE5"/>
+            <enum name="GL_TEXTURE6"/>
+            <enum name="GL_TEXTURE7"/>
+            <enum name="GL_TEXTURE8"/>
+            <enum name="GL_TEXTURE9"/>
+            <enum name="GL_TEXTURE10"/>
+            <enum name="GL_TEXTURE11"/>
+            <enum name="GL_TEXTURE12"/>
+            <enum name="GL_TEXTURE13"/>
+            <enum name="GL_TEXTURE14"/>
+            <enum name="GL_TEXTURE15"/>
+            <enum name="GL_TEXTURE16"/>
+            <enum name="GL_TEXTURE17"/>
+            <enum name="GL_TEXTURE18"/>
+            <enum name="GL_TEXTURE19"/>
+            <enum name="GL_TEXTURE20"/>
+            <enum name="GL_TEXTURE21"/>
+            <enum name="GL_TEXTURE22"/>
+            <enum name="GL_TEXTURE23"/>
+            <enum name="GL_TEXTURE24"/>
+            <enum name="GL_TEXTURE25"/>
+            <enum name="GL_TEXTURE26"/>
+            <enum name="GL_TEXTURE27"/>
+            <enum name="GL_TEXTURE28"/>
+            <enum name="GL_TEXTURE29"/>
+            <enum name="GL_TEXTURE30"/>
+            <enum name="GL_TEXTURE31"/>
+            <enum name="GL_ACTIVE_TEXTURE"/>
+            <enum name="GL_REPEAT"/>
+            <enum name="GL_CLAMP_TO_EDGE"/>
+            <enum name="GL_MIRRORED_REPEAT"/>
+            <enum name="GL_FLOAT_VEC2"/>
+            <enum name="GL_FLOAT_VEC3"/>
+            <enum name="GL_FLOAT_VEC4"/>
+            <enum name="GL_INT_VEC2"/>
+            <enum name="GL_INT_VEC3"/>
+            <enum name="GL_INT_VEC4"/>
+            <enum name="GL_BOOL"/>
+            <enum name="GL_BOOL_VEC2"/>
+            <enum name="GL_BOOL_VEC3"/>
+            <enum name="GL_BOOL_VEC4"/>
+            <enum name="GL_FLOAT_MAT2"/>
+            <enum name="GL_FLOAT_MAT3"/>
+            <enum name="GL_FLOAT_MAT4"/>
+            <enum name="GL_SAMPLER_2D"/>
+            <enum name="GL_SAMPLER_CUBE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_ENABLED"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_SIZE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_STRIDE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_TYPE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_POINTER"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_IMPLEMENTATION_COLOR_READ_TYPE"/>
+            <enum name="GL_IMPLEMENTATION_COLOR_READ_FORMAT"/>
+            <enum name="GL_COMPILE_STATUS"/>
+            <enum name="GL_INFO_LOG_LENGTH"/>
+            <enum name="GL_SHADER_SOURCE_LENGTH"/>
+            <enum name="GL_SHADER_COMPILER"/>
+            <enum name="GL_SHADER_BINARY_FORMATS"/>
+            <enum name="GL_NUM_SHADER_BINARY_FORMATS"/>
+            <enum name="GL_LOW_FLOAT"/>
+            <enum name="GL_MEDIUM_FLOAT"/>
+            <enum name="GL_HIGH_FLOAT"/>
+            <enum name="GL_LOW_INT"/>
+            <enum name="GL_MEDIUM_INT"/>
+            <enum name="GL_HIGH_INT"/>
+            <enum name="GL_FRAMEBUFFER"/>
+            <enum name="GL_RENDERBUFFER"/>
+            <enum name="GL_RGBA4"/>
+            <enum name="GL_RGB5_A1"/>
+            <enum name="GL_RGB565"/>
+            <enum name="GL_DEPTH_COMPONENT16"/>
+            <enum name="GL_STENCIL_INDEX8"/>
+            <enum name="GL_RENDERBUFFER_WIDTH"/>
+            <enum name="GL_RENDERBUFFER_HEIGHT"/>
+            <enum name="GL_RENDERBUFFER_INTERNAL_FORMAT"/>
+            <enum name="GL_RENDERBUFFER_RED_SIZE"/>
+            <enum name="GL_RENDERBUFFER_GREEN_SIZE"/>
+            <enum name="GL_RENDERBUFFER_BLUE_SIZE"/>
+            <enum name="GL_RENDERBUFFER_ALPHA_SIZE"/>
+            <enum name="GL_RENDERBUFFER_DEPTH_SIZE"/>
+            <enum name="GL_RENDERBUFFER_STENCIL_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE"/>
+            <enum name="GL_COLOR_ATTACHMENT0"/>
+            <enum name="GL_DEPTH_ATTACHMENT"/>
+            <enum name="GL_STENCIL_ATTACHMENT"/>
+            <enum name="GL_NONE"/>
+            <enum name="GL_FRAMEBUFFER_COMPLETE"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"/>
+            <enum name="GL_FRAMEBUFFER_UNSUPPORTED"/>
+            <enum name="GL_FRAMEBUFFER_BINDING"/>
+            <enum name="GL_RENDERBUFFER_BINDING"/>
+            <enum name="GL_MAX_RENDERBUFFER_SIZE"/>
+            <enum name="GL_INVALID_FRAMEBUFFER_OPERATION"/>
+            <command name="glActiveTexture"/>
+            <command name="glAttachShader"/>
+            <command name="glBindAttribLocation"/>
+            <command name="glBindBuffer"/>
+            <command name="glBindFramebuffer"/>
+            <command name="glBindRenderbuffer"/>
+            <command name="glBindTexture"/>
+            <command name="glBlendColor"/>
+            <command name="glBlendEquation"/>
+            <command name="glBlendEquationSeparate"/>
+            <command name="glBlendFunc"/>
+            <command name="glBlendFuncSeparate"/>
+            <command name="glBufferData"/>
+            <command name="glBufferSubData"/>
+            <command name="glCheckFramebufferStatus"/>
+            <command name="glClear"/>
+            <command name="glClearColor"/>
+            <command name="glClearDepthf"/>
+            <command name="glClearStencil"/>
+            <command name="glColorMask"/>
+            <command name="glCompileShader"/>
+            <command name="glCompressedTexImage2D"/>
+            <command name="glCompressedTexSubImage2D"/>
+            <command name="glCopyTexImage2D"/>
+            <command name="glCopyTexSubImage2D"/>
+            <command name="glCreateProgram"/>
+            <command name="glCreateShader"/>
+            <command name="glCullFace"/>
+            <command name="glDeleteBuffers"/>
+            <command name="glDeleteFramebuffers"/>
+            <command name="glDeleteProgram"/>
+            <command name="glDeleteRenderbuffers"/>
+            <command name="glDeleteShader"/>
+            <command name="glDeleteTextures"/>
+            <command name="glDepthFunc"/>
+            <command name="glDepthMask"/>
+            <command name="glDepthRangef"/>
+            <command name="glDetachShader"/>
+            <command name="glDisable"/>
+            <command name="glDisableVertexAttribArray"/>
+            <command name="glDrawArrays"/>
+            <command name="glDrawElements"/>
+            <command name="glEnable"/>
+            <command name="glEnableVertexAttribArray"/>
+            <command name="glFinish"/>
+            <command name="glFlush"/>
+            <command name="glFramebufferRenderbuffer"/>
+            <command name="glFramebufferTexture2D"/>
+            <command name="glFrontFace"/>
+            <command name="glGenBuffers"/>
+            <command name="glGenerateMipmap"/>
+            <command name="glGenFramebuffers"/>
+            <command name="glGenRenderbuffers"/>
+            <command name="glGenTextures"/>
+            <command name="glGetActiveAttrib"/>
+            <command name="glGetActiveUniform"/>
+            <command name="glGetAttachedShaders"/>
+            <command name="glGetAttribLocation"/>
+            <command name="glGetBooleanv"/>
+            <command name="glGetBufferParameteriv"/>
+            <command name="glGetError"/>
+            <command name="glGetFloatv"/>
+            <command name="glGetFramebufferAttachmentParameteriv"/>
+            <command name="glGetIntegerv"/>
+            <command name="glGetProgramiv"/>
+            <command name="glGetProgramInfoLog"/>
+            <command name="glGetRenderbufferParameteriv"/>
+            <command name="glGetShaderiv"/>
+            <command name="glGetShaderInfoLog"/>
+            <command name="glGetShaderPrecisionFormat"/>
+            <command name="glGetShaderSource"/>
+            <command name="glGetString"/>
+            <command name="glGetTexParameterfv"/>
+            <command name="glGetTexParameteriv"/>
+            <command name="glGetUniformfv"/>
+            <command name="glGetUniformiv"/>
+            <command name="glGetUniformLocation"/>
+            <command name="glGetVertexAttribfv"/>
+            <command name="glGetVertexAttribiv"/>
+            <command name="glGetVertexAttribPointerv"/>
+            <command name="glHint"/>
+            <command name="glIsBuffer"/>
+            <command name="glIsEnabled"/>
+            <command name="glIsFramebuffer"/>
+            <command name="glIsProgram"/>
+            <command name="glIsRenderbuffer"/>
+            <command name="glIsShader"/>
+            <command name="glIsTexture"/>
+            <command name="glLineWidth"/>
+            <command name="glLinkProgram"/>
+            <command name="glPixelStorei"/>
+            <command name="glPolygonOffset"/>
+            <command name="glReadPixels"/>
+            <command name="glReleaseShaderCompiler"/>
+            <command name="glRenderbufferStorage"/>
+            <command name="glSampleCoverage"/>
+            <command name="glScissor"/>
+            <command name="glShaderBinary"/>
+            <command name="glShaderSource"/>
+            <command name="glStencilFunc"/>
+            <command name="glStencilFuncSeparate"/>
+            <command name="glStencilMask"/>
+            <command name="glStencilMaskSeparate"/>
+            <command name="glStencilOp"/>
+            <command name="glStencilOpSeparate"/>
+            <command name="glTexImage2D"/>
+            <command name="glTexParameterf"/>
+            <command name="glTexParameterfv"/>
+            <command name="glTexParameteri"/>
+            <command name="glTexParameteriv"/>
+            <command name="glTexSubImage2D"/>
+            <command name="glUniform1f"/>
+            <command name="glUniform1fv"/>
+            <command name="glUniform1i"/>
+            <command name="glUniform1iv"/>
+            <command name="glUniform2f"/>
+            <command name="glUniform2fv"/>
+            <command name="glUniform2i"/>
+            <command name="glUniform2iv"/>
+            <command name="glUniform3f"/>
+            <command name="glUniform3fv"/>
+            <command name="glUniform3i"/>
+            <command name="glUniform3iv"/>
+            <command name="glUniform4f"/>
+            <command name="glUniform4fv"/>
+            <command name="glUniform4i"/>
+            <command name="glUniform4iv"/>
+            <command name="glUniformMatrix2fv"/>
+            <command name="glUniformMatrix3fv"/>
+            <command name="glUniformMatrix4fv"/>
+            <command name="glUseProgram"/>
+            <command name="glValidateProgram"/>
+            <command name="glVertexAttrib1f"/>
+            <command name="glVertexAttrib1fv"/>
+            <command name="glVertexAttrib2f"/>
+            <command name="glVertexAttrib2fv"/>
+            <command name="glVertexAttrib3f"/>
+            <command name="glVertexAttrib3fv"/>
+            <command name="glVertexAttrib4f"/>
+            <command name="glVertexAttrib4fv"/>
+            <command name="glVertexAttribPointer"/>
+            <command name="glViewport"/>
+        </require>
+    </feature>
+    <feature api="gles2" name="GL_ES_VERSION_3_0" number="3.0">
+        <require comment="Not used by the API, for compatibility with old gl2.h">
+            <type name="GLhalf"/>
+        </require>
+        <require>
+            <enum name="GL_READ_BUFFER"/>
+            <enum name="GL_UNPACK_ROW_LENGTH"/>
+            <enum name="GL_UNPACK_SKIP_ROWS"/>
+            <enum name="GL_UNPACK_SKIP_PIXELS"/>
+            <enum name="GL_PACK_ROW_LENGTH"/>
+            <enum name="GL_PACK_SKIP_ROWS"/>
+            <enum name="GL_PACK_SKIP_PIXELS"/>
+            <enum name="GL_COLOR"/>
+            <enum name="GL_DEPTH"/>
+            <enum name="GL_STENCIL"/>
+            <enum name="GL_RED"/>
+            <enum name="GL_RGB8"/>
+            <enum name="GL_RGBA8"/>
+            <enum name="GL_RGB10_A2"/>
+            <enum name="GL_TEXTURE_BINDING_3D"/>
+            <enum name="GL_UNPACK_SKIP_IMAGES"/>
+            <enum name="GL_UNPACK_IMAGE_HEIGHT"/>
+            <enum name="GL_TEXTURE_3D"/>
+            <enum name="GL_TEXTURE_WRAP_R"/>
+            <enum name="GL_MAX_3D_TEXTURE_SIZE"/>
+            <enum name="GL_UNSIGNED_INT_2_10_10_10_REV"/>
+            <enum name="GL_MAX_ELEMENTS_VERTICES"/>
+            <enum name="GL_MAX_ELEMENTS_INDICES"/>
+            <enum name="GL_TEXTURE_MIN_LOD"/>
+            <enum name="GL_TEXTURE_MAX_LOD"/>
+            <enum name="GL_TEXTURE_BASE_LEVEL"/>
+            <enum name="GL_TEXTURE_MAX_LEVEL"/>
+            <enum name="GL_MIN"/>
+            <enum name="GL_MAX"/>
+            <enum name="GL_DEPTH_COMPONENT24"/>
+            <enum name="GL_MAX_TEXTURE_LOD_BIAS"/>
+            <enum name="GL_TEXTURE_COMPARE_MODE"/>
+            <enum name="GL_TEXTURE_COMPARE_FUNC"/>
+            <enum name="GL_CURRENT_QUERY"/>
+            <enum name="GL_QUERY_RESULT"/>
+            <enum name="GL_QUERY_RESULT_AVAILABLE"/>
+            <enum name="GL_BUFFER_MAPPED"/>
+            <enum name="GL_BUFFER_MAP_POINTER"/>
+            <enum name="GL_STREAM_READ"/>
+            <enum name="GL_STREAM_COPY"/>
+            <enum name="GL_STATIC_READ"/>
+            <enum name="GL_STATIC_COPY"/>
+            <enum name="GL_DYNAMIC_READ"/>
+            <enum name="GL_DYNAMIC_COPY"/>
+            <enum name="GL_MAX_DRAW_BUFFERS"/>
+            <enum name="GL_DRAW_BUFFER0"/>
+            <enum name="GL_DRAW_BUFFER1"/>
+            <enum name="GL_DRAW_BUFFER2"/>
+            <enum name="GL_DRAW_BUFFER3"/>
+            <enum name="GL_DRAW_BUFFER4"/>
+            <enum name="GL_DRAW_BUFFER5"/>
+            <enum name="GL_DRAW_BUFFER6"/>
+            <enum name="GL_DRAW_BUFFER7"/>
+            <enum name="GL_DRAW_BUFFER8"/>
+            <enum name="GL_DRAW_BUFFER9"/>
+            <enum name="GL_DRAW_BUFFER10"/>
+            <enum name="GL_DRAW_BUFFER11"/>
+            <enum name="GL_DRAW_BUFFER12"/>
+            <enum name="GL_DRAW_BUFFER13"/>
+            <enum name="GL_DRAW_BUFFER14"/>
+            <enum name="GL_DRAW_BUFFER15"/>
+            <enum name="GL_MAX_FRAGMENT_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_VERTEX_UNIFORM_COMPONENTS"/>
+            <enum name="GL_SAMPLER_3D"/>
+            <enum name="GL_SAMPLER_2D_SHADOW"/>
+            <enum name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT"/>
+            <enum name="GL_PIXEL_PACK_BUFFER"/>
+            <enum name="GL_PIXEL_UNPACK_BUFFER"/>
+            <enum name="GL_PIXEL_PACK_BUFFER_BINDING"/>
+            <enum name="GL_PIXEL_UNPACK_BUFFER_BINDING"/>
+            <enum name="GL_FLOAT_MAT2x3"/>
+            <enum name="GL_FLOAT_MAT2x4"/>
+            <enum name="GL_FLOAT_MAT3x2"/>
+            <enum name="GL_FLOAT_MAT3x4"/>
+            <enum name="GL_FLOAT_MAT4x2"/>
+            <enum name="GL_FLOAT_MAT4x3"/>
+            <enum name="GL_SRGB"/>
+            <enum name="GL_SRGB8"/>
+            <enum name="GL_SRGB8_ALPHA8"/>
+            <enum name="GL_COMPARE_REF_TO_TEXTURE"/>
+            <enum name="GL_MAJOR_VERSION"/>
+            <enum name="GL_MINOR_VERSION"/>
+            <enum name="GL_NUM_EXTENSIONS"/>
+            <enum name="GL_RGBA32F"/>
+            <enum name="GL_RGB32F"/>
+            <enum name="GL_RGBA16F"/>
+            <enum name="GL_RGB16F"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_INTEGER"/>
+            <enum name="GL_MAX_ARRAY_TEXTURE_LAYERS"/>
+            <enum name="GL_MIN_PROGRAM_TEXEL_OFFSET"/>
+            <enum name="GL_MAX_PROGRAM_TEXEL_OFFSET"/>
+            <enum name="GL_MAX_VARYING_COMPONENTS"/>
+            <enum name="GL_TEXTURE_2D_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_2D_ARRAY"/>
+            <enum name="GL_R11F_G11F_B10F"/>
+            <enum name="GL_UNSIGNED_INT_10F_11F_11F_REV"/>
+            <enum name="GL_RGB9_E5"/>
+            <enum name="GL_UNSIGNED_INT_5_9_9_9_REV"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_MODE"/>
+            <enum name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_VARYINGS"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_START"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_SIZE"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"/>
+            <enum name="GL_RASTERIZER_DISCARD"/>
+            <enum name="GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS"/>
+            <enum name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS"/>
+            <enum name="GL_INTERLEAVED_ATTRIBS"/>
+            <enum name="GL_SEPARATE_ATTRIBS"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_BINDING"/>
+            <enum name="GL_RGBA32UI"/>
+            <enum name="GL_RGB32UI"/>
+            <enum name="GL_RGBA16UI"/>
+            <enum name="GL_RGB16UI"/>
+            <enum name="GL_RGBA8UI"/>
+            <enum name="GL_RGB8UI"/>
+            <enum name="GL_RGBA32I"/>
+            <enum name="GL_RGB32I"/>
+            <enum name="GL_RGBA16I"/>
+            <enum name="GL_RGB16I"/>
+            <enum name="GL_RGBA8I"/>
+            <enum name="GL_RGB8I"/>
+            <enum name="GL_RED_INTEGER"/>
+            <enum name="GL_RGB_INTEGER"/>
+            <enum name="GL_RGBA_INTEGER"/>
+            <enum name="GL_SAMPLER_2D_ARRAY"/>
+            <enum name="GL_SAMPLER_2D_ARRAY_SHADOW"/>
+            <enum name="GL_SAMPLER_CUBE_SHADOW"/>
+            <enum name="GL_UNSIGNED_INT_VEC2"/>
+            <enum name="GL_UNSIGNED_INT_VEC3"/>
+            <enum name="GL_UNSIGNED_INT_VEC4"/>
+            <enum name="GL_INT_SAMPLER_2D"/>
+            <enum name="GL_INT_SAMPLER_3D"/>
+            <enum name="GL_INT_SAMPLER_CUBE"/>
+            <enum name="GL_INT_SAMPLER_2D_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_3D"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D_ARRAY"/>
+            <enum name="GL_BUFFER_ACCESS_FLAGS"/>
+            <enum name="GL_BUFFER_MAP_LENGTH"/>
+            <enum name="GL_BUFFER_MAP_OFFSET"/>
+            <enum name="GL_DEPTH_COMPONENT32F"/>
+            <enum name="GL_DEPTH32F_STENCIL8"/>
+            <enum name="GL_FLOAT_32_UNSIGNED_INT_24_8_REV"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT"/>
+            <enum name="GL_FRAMEBUFFER_UNDEFINED"/>
+            <enum name="GL_DEPTH_STENCIL_ATTACHMENT"/>
+            <enum name="GL_DEPTH_STENCIL"/>
+            <enum name="GL_UNSIGNED_INT_24_8"/>
+            <enum name="GL_DEPTH24_STENCIL8"/>
+            <enum name="GL_UNSIGNED_NORMALIZED"/>
+            <enum name="GL_DRAW_FRAMEBUFFER_BINDING"/>
+            <enum name="GL_READ_FRAMEBUFFER"/>
+            <enum name="GL_DRAW_FRAMEBUFFER"/>
+            <enum name="GL_READ_FRAMEBUFFER_BINDING"/>
+            <enum name="GL_RENDERBUFFER_SAMPLES"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER"/>
+            <enum name="GL_MAX_COLOR_ATTACHMENTS"/>
+            <enum name="GL_COLOR_ATTACHMENT1"/>
+            <enum name="GL_COLOR_ATTACHMENT2"/>
+            <enum name="GL_COLOR_ATTACHMENT3"/>
+            <enum name="GL_COLOR_ATTACHMENT4"/>
+            <enum name="GL_COLOR_ATTACHMENT5"/>
+            <enum name="GL_COLOR_ATTACHMENT6"/>
+            <enum name="GL_COLOR_ATTACHMENT7"/>
+            <enum name="GL_COLOR_ATTACHMENT8"/>
+            <enum name="GL_COLOR_ATTACHMENT9"/>
+            <enum name="GL_COLOR_ATTACHMENT10"/>
+            <enum name="GL_COLOR_ATTACHMENT11"/>
+            <enum name="GL_COLOR_ATTACHMENT12"/>
+            <enum name="GL_COLOR_ATTACHMENT13"/>
+            <enum name="GL_COLOR_ATTACHMENT14"/>
+            <enum name="GL_COLOR_ATTACHMENT15"/>
+            <enum name="GL_COLOR_ATTACHMENT16"/>
+            <enum name="GL_COLOR_ATTACHMENT17"/>
+            <enum name="GL_COLOR_ATTACHMENT18"/>
+            <enum name="GL_COLOR_ATTACHMENT19"/>
+            <enum name="GL_COLOR_ATTACHMENT20"/>
+            <enum name="GL_COLOR_ATTACHMENT21"/>
+            <enum name="GL_COLOR_ATTACHMENT22"/>
+            <enum name="GL_COLOR_ATTACHMENT23"/>
+            <enum name="GL_COLOR_ATTACHMENT24"/>
+            <enum name="GL_COLOR_ATTACHMENT25"/>
+            <enum name="GL_COLOR_ATTACHMENT26"/>
+            <enum name="GL_COLOR_ATTACHMENT27"/>
+            <enum name="GL_COLOR_ATTACHMENT28"/>
+            <enum name="GL_COLOR_ATTACHMENT29"/>
+            <enum name="GL_COLOR_ATTACHMENT30"/>
+            <enum name="GL_COLOR_ATTACHMENT31"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"/>
+            <enum name="GL_MAX_SAMPLES"/>
+            <enum name="GL_HALF_FLOAT"/>
+            <enum name="GL_MAP_READ_BIT"/>
+            <enum name="GL_MAP_WRITE_BIT"/>
+            <enum name="GL_MAP_INVALIDATE_RANGE_BIT"/>
+            <enum name="GL_MAP_INVALIDATE_BUFFER_BIT"/>
+            <enum name="GL_MAP_FLUSH_EXPLICIT_BIT"/>
+            <enum name="GL_MAP_UNSYNCHRONIZED_BIT"/>
+            <enum name="GL_RG"/>
+            <enum name="GL_RG_INTEGER"/>
+            <enum name="GL_R8"/>
+            <enum name="GL_RG8"/>
+            <enum name="GL_R16F"/>
+            <enum name="GL_R32F"/>
+            <enum name="GL_RG16F"/>
+            <enum name="GL_RG32F"/>
+            <enum name="GL_R8I"/>
+            <enum name="GL_R8UI"/>
+            <enum name="GL_R16I"/>
+            <enum name="GL_R16UI"/>
+            <enum name="GL_R32I"/>
+            <enum name="GL_R32UI"/>
+            <enum name="GL_RG8I"/>
+            <enum name="GL_RG8UI"/>
+            <enum name="GL_RG16I"/>
+            <enum name="GL_RG16UI"/>
+            <enum name="GL_RG32I"/>
+            <enum name="GL_RG32UI"/>
+            <enum name="GL_VERTEX_ARRAY_BINDING"/>
+            <enum name="GL_R8_SNORM"/>
+            <enum name="GL_RG8_SNORM"/>
+            <enum name="GL_RGB8_SNORM"/>
+            <enum name="GL_RGBA8_SNORM"/>
+            <enum name="GL_SIGNED_NORMALIZED"/>
+            <enum name="GL_PRIMITIVE_RESTART_FIXED_INDEX"/>
+            <enum name="GL_COPY_READ_BUFFER"/>
+            <enum name="GL_COPY_WRITE_BUFFER"/>
+            <enum name="GL_COPY_READ_BUFFER_BINDING"/>
+            <enum name="GL_COPY_WRITE_BUFFER_BINDING"/>
+            <enum name="GL_UNIFORM_BUFFER"/>
+            <enum name="GL_UNIFORM_BUFFER_BINDING"/>
+            <enum name="GL_UNIFORM_BUFFER_START"/>
+            <enum name="GL_UNIFORM_BUFFER_SIZE"/>
+            <enum name="GL_MAX_VERTEX_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_FRAGMENT_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_COMBINED_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_UNIFORM_BUFFER_BINDINGS"/>
+            <enum name="GL_MAX_UNIFORM_BLOCK_SIZE"/>
+            <enum name="GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS"/>
+            <enum name="GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT"/>
+            <enum name="GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH"/>
+            <enum name="GL_ACTIVE_UNIFORM_BLOCKS"/>
+            <enum name="GL_UNIFORM_TYPE"/>
+            <enum name="GL_UNIFORM_SIZE"/>
+            <enum name="GL_UNIFORM_NAME_LENGTH"/>
+            <enum name="GL_UNIFORM_BLOCK_INDEX"/>
+            <enum name="GL_UNIFORM_OFFSET"/>
+            <enum name="GL_UNIFORM_ARRAY_STRIDE"/>
+            <enum name="GL_UNIFORM_MATRIX_STRIDE"/>
+            <enum name="GL_UNIFORM_IS_ROW_MAJOR"/>
+            <enum name="GL_UNIFORM_BLOCK_BINDING"/>
+            <enum name="GL_UNIFORM_BLOCK_DATA_SIZE"/>
+            <enum name="GL_UNIFORM_BLOCK_NAME_LENGTH"/>
+            <enum name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS"/>
+            <enum name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES"/>
+            <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"/>
+            <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"/>
+            <enum name="GL_INVALID_INDEX"/>
+            <enum name="GL_MAX_VERTEX_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_FRAGMENT_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_SERVER_WAIT_TIMEOUT"/>
+            <enum name="GL_OBJECT_TYPE"/>
+            <enum name="GL_SYNC_CONDITION"/>
+            <enum name="GL_SYNC_STATUS"/>
+            <enum name="GL_SYNC_FLAGS"/>
+            <enum name="GL_SYNC_FENCE"/>
+            <enum name="GL_SYNC_GPU_COMMANDS_COMPLETE"/>
+            <enum name="GL_UNSIGNALED"/>
+            <enum name="GL_SIGNALED"/>
+            <enum name="GL_ALREADY_SIGNALED"/>
+            <enum name="GL_TIMEOUT_EXPIRED"/>
+            <enum name="GL_CONDITION_SATISFIED"/>
+            <enum name="GL_WAIT_FAILED"/>
+            <enum name="GL_SYNC_FLUSH_COMMANDS_BIT"/>
+            <enum name="GL_TIMEOUT_IGNORED"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR"/>
+            <enum name="GL_ANY_SAMPLES_PASSED"/>
+            <enum name="GL_ANY_SAMPLES_PASSED_CONSERVATIVE"/>
+            <enum name="GL_SAMPLER_BINDING"/>
+            <enum name="GL_RGB10_A2UI"/>
+            <enum name="GL_TEXTURE_SWIZZLE_R"/>
+            <enum name="GL_TEXTURE_SWIZZLE_G"/>
+            <enum name="GL_TEXTURE_SWIZZLE_B"/>
+            <enum name="GL_TEXTURE_SWIZZLE_A"/>
+            <enum name="GL_GREEN"/>
+            <enum name="GL_BLUE"/>
+            <enum name="GL_INT_2_10_10_10_REV"/>
+            <enum name="GL_TRANSFORM_FEEDBACK"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_PAUSED"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_ACTIVE"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BINDING"/>
+            <enum name="GL_PROGRAM_BINARY_RETRIEVABLE_HINT"/>
+            <enum name="GL_PROGRAM_BINARY_LENGTH"/>
+            <enum name="GL_NUM_PROGRAM_BINARY_FORMATS"/>
+            <enum name="GL_PROGRAM_BINARY_FORMATS"/>
+            <enum name="GL_COMPRESSED_R11_EAC"/>
+            <enum name="GL_COMPRESSED_SIGNED_R11_EAC"/>
+            <enum name="GL_COMPRESSED_RG11_EAC"/>
+            <enum name="GL_COMPRESSED_SIGNED_RG11_EAC"/>
+            <enum name="GL_COMPRESSED_RGB8_ETC2"/>
+            <enum name="GL_COMPRESSED_SRGB8_ETC2"/>
+            <enum name="GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"/>
+            <enum name="GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"/>
+            <enum name="GL_COMPRESSED_RGBA8_ETC2_EAC"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"/>
+            <enum name="GL_TEXTURE_IMMUTABLE_FORMAT"/>
+            <enum name="GL_MAX_ELEMENT_INDEX"/>
+            <enum name="GL_NUM_SAMPLE_COUNTS"/>
+            <enum name="GL_TEXTURE_IMMUTABLE_LEVELS"/>
+            <command name="glReadBuffer"/>
+            <command name="glDrawRangeElements"/>
+            <command name="glTexImage3D"/>
+            <command name="glTexSubImage3D"/>
+            <command name="glCopyTexSubImage3D"/>
+            <command name="glCompressedTexImage3D"/>
+            <command name="glCompressedTexSubImage3D"/>
+            <command name="glGenQueries"/>
+            <command name="glDeleteQueries"/>
+            <command name="glIsQuery"/>
+            <command name="glBeginQuery"/>
+            <command name="glEndQuery"/>
+            <command name="glGetQueryiv"/>
+            <command name="glGetQueryObjectuiv"/>
+            <command name="glUnmapBuffer"/>
+            <command name="glGetBufferPointerv"/>
+            <command name="glDrawBuffers"/>
+            <command name="glUniformMatrix2x3fv"/>
+            <command name="glUniformMatrix3x2fv"/>
+            <command name="glUniformMatrix2x4fv"/>
+            <command name="glUniformMatrix4x2fv"/>
+            <command name="glUniformMatrix3x4fv"/>
+            <command name="glUniformMatrix4x3fv"/>
+            <command name="glBlitFramebuffer"/>
+            <command name="glRenderbufferStorageMultisample"/>
+            <command name="glFramebufferTextureLayer"/>
+            <command name="glMapBufferRange"/>
+            <command name="glFlushMappedBufferRange"/>
+            <command name="glBindVertexArray"/>
+            <command name="glDeleteVertexArrays"/>
+            <command name="glGenVertexArrays"/>
+            <command name="glIsVertexArray"/>
+            <command name="glGetIntegeri_v"/>
+            <command name="glBeginTransformFeedback"/>
+            <command name="glEndTransformFeedback"/>
+            <command name="glBindBufferRange"/>
+            <command name="glBindBufferBase"/>
+            <command name="glTransformFeedbackVaryings"/>
+            <command name="glGetTransformFeedbackVarying"/>
+            <command name="glVertexAttribIPointer"/>
+            <command name="glGetVertexAttribIiv"/>
+            <command name="glGetVertexAttribIuiv"/>
+            <command name="glVertexAttribI4i"/>
+            <command name="glVertexAttribI4ui"/>
+            <command name="glVertexAttribI4iv"/>
+            <command name="glVertexAttribI4uiv"/>
+            <command name="glGetUniformuiv"/>
+            <command name="glGetFragDataLocation"/>
+            <command name="glUniform1ui"/>
+            <command name="glUniform2ui"/>
+            <command name="glUniform3ui"/>
+            <command name="glUniform4ui"/>
+            <command name="glUniform1uiv"/>
+            <command name="glUniform2uiv"/>
+            <command name="glUniform3uiv"/>
+            <command name="glUniform4uiv"/>
+            <command name="glClearBufferiv"/>
+            <command name="glClearBufferuiv"/>
+            <command name="glClearBufferfv"/>
+            <command name="glClearBufferfi"/>
+            <command name="glGetStringi"/>
+            <command name="glCopyBufferSubData"/>
+            <command name="glGetUniformIndices"/>
+            <command name="glGetActiveUniformsiv"/>
+            <command name="glGetUniformBlockIndex"/>
+            <command name="glGetActiveUniformBlockiv"/>
+            <command name="glGetActiveUniformBlockName"/>
+            <command name="glUniformBlockBinding"/>
+            <command name="glDrawArraysInstanced"/>
+            <command name="glDrawElementsInstanced"/>
+            <command name="glFenceSync"/>
+            <command name="glIsSync"/>
+            <command name="glDeleteSync"/>
+            <command name="glClientWaitSync"/>
+            <command name="glWaitSync"/>
+            <command name="glGetInteger64v"/>
+            <command name="glGetSynciv"/>
+            <command name="glGetInteger64i_v"/>
+            <command name="glGetBufferParameteri64v"/>
+            <command name="glGenSamplers"/>
+            <command name="glDeleteSamplers"/>
+            <command name="glIsSampler"/>
+            <command name="glBindSampler"/>
+            <command name="glSamplerParameteri"/>
+            <command name="glSamplerParameteriv"/>
+            <command name="glSamplerParameterf"/>
+            <command name="glSamplerParameterfv"/>
+            <command name="glGetSamplerParameteriv"/>
+            <command name="glGetSamplerParameterfv"/>
+            <command name="glVertexAttribDivisor"/>
+            <command name="glBindTransformFeedback"/>
+            <command name="glDeleteTransformFeedbacks"/>
+            <command name="glGenTransformFeedbacks"/>
+            <command name="glIsTransformFeedback"/>
+            <command name="glPauseTransformFeedback"/>
+            <command name="glResumeTransformFeedback"/>
+            <command name="glGetProgramBinary"/>
+            <command name="glProgramBinary"/>
+            <command name="glProgramParameteri"/>
+            <command name="glInvalidateFramebuffer"/>
+            <command name="glInvalidateSubFramebuffer"/>
+            <command name="glTexStorage2D"/>
+            <command name="glTexStorage3D"/>
+            <command name="glGetInternalformativ"/>
+        </require>
+    </feature>
+    <feature api="gles2" name="GL_ES_VERSION_3_1" number="3.1">
+        <!-- arrays_of_arrays features -->
+        <require/>
+        <!-- compute_shader features -->
+        <require>
+            <command name="glDispatchCompute"/>
+            <command name="glDispatchComputeIndirect"/>
+            <enum name="GL_COMPUTE_SHADER"/>
+            <enum name="GL_MAX_COMPUTE_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_COMPUTE_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"/>
+            <enum name="GL_MAX_COMPUTE_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_COMPUTE_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS"/>
+            <enum name="GL_MAX_COMPUTE_WORK_GROUP_COUNT"/>
+            <enum name="GL_MAX_COMPUTE_WORK_GROUP_SIZE"/>
+            <enum name="GL_COMPUTE_WORK_GROUP_SIZE"/>
+            <enum name="GL_DISPATCH_INDIRECT_BUFFER"/>
+            <enum name="GL_DISPATCH_INDIRECT_BUFFER_BINDING"/>
+            <enum name="GL_COMPUTE_SHADER_BIT"/>
+        </require>
+        <!-- draw_indirect features -->
+        <require>
+            <command name="glDrawArraysIndirect"/>
+            <command name="glDrawElementsIndirect"/>
+            <enum name="GL_DRAW_INDIRECT_BUFFER"/>
+            <enum name="GL_DRAW_INDIRECT_BUFFER_BINDING"/>
+        </require>
+        <!-- explicit_uniform_location features -->
+        <require>
+            <enum name="GL_MAX_UNIFORM_LOCATIONS"/>
+        </require>
+        <!-- framebuffer_no_attachments features -->
+        <require>
+            <command name="glFramebufferParameteri"/>
+            <command name="glGetFramebufferParameteriv"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_WIDTH"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_HEIGHT"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_SAMPLES"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"/>
+            <enum name="GL_MAX_FRAMEBUFFER_WIDTH"/>
+            <enum name="GL_MAX_FRAMEBUFFER_HEIGHT"/>
+            <enum name="GL_MAX_FRAMEBUFFER_SAMPLES"/>
+        </require>
+        <!-- program_interface_query features -->
+        <require>
+            <command name="glGetProgramInterfaceiv"/>
+            <command name="glGetProgramResourceIndex"/>
+            <command name="glGetProgramResourceName"/>
+            <command name="glGetProgramResourceiv"/>
+            <command name="glGetProgramResourceLocation"/>
+            <enum name="GL_UNIFORM"/>
+            <enum name="GL_UNIFORM_BLOCK"/>
+            <enum name="GL_PROGRAM_INPUT"/>
+            <enum name="GL_PROGRAM_OUTPUT"/>
+            <enum name="GL_BUFFER_VARIABLE"/>
+            <enum name="GL_SHADER_STORAGE_BLOCK"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_VARYING"/>
+            <enum name="GL_ACTIVE_RESOURCES"/>
+            <enum name="GL_MAX_NAME_LENGTH"/>
+            <enum name="GL_MAX_NUM_ACTIVE_VARIABLES"/>
+            <enum name="GL_NAME_LENGTH"/>
+            <enum name="GL_TYPE"/>
+            <enum name="GL_ARRAY_SIZE"/>
+            <enum name="GL_OFFSET"/>
+            <enum name="GL_BLOCK_INDEX"/>
+            <enum name="GL_ARRAY_STRIDE"/>
+            <enum name="GL_MATRIX_STRIDE"/>
+            <enum name="GL_IS_ROW_MAJOR"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_INDEX"/>
+            <enum name="GL_BUFFER_BINDING"/>
+            <enum name="GL_BUFFER_DATA_SIZE"/>
+            <enum name="GL_NUM_ACTIVE_VARIABLES"/>
+            <enum name="GL_ACTIVE_VARIABLES"/>
+            <enum name="GL_REFERENCED_BY_VERTEX_SHADER"/>
+            <enum name="GL_REFERENCED_BY_FRAGMENT_SHADER"/>
+            <enum name="GL_REFERENCED_BY_COMPUTE_SHADER"/>
+            <enum name="GL_TOP_LEVEL_ARRAY_SIZE"/>
+            <enum name="GL_TOP_LEVEL_ARRAY_STRIDE"/>
+            <enum name="GL_LOCATION"/>
+        </require>
+        <!-- separate_shader_objects features -->
+        <require>
+            <command name="glUseProgramStages"/>
+            <command name="glActiveShaderProgram"/>
+            <command name="glCreateShaderProgramv"/>
+            <command name="glBindProgramPipeline"/>
+            <command name="glDeleteProgramPipelines"/>
+            <command name="glGenProgramPipelines"/>
+            <command name="glIsProgramPipeline"/>
+            <command name="glGetProgramPipelineiv"/>
+            <command name="glProgramUniform1i"/>
+            <command name="glProgramUniform2i"/>
+            <command name="glProgramUniform3i"/>
+            <command name="glProgramUniform4i"/>
+            <command name="glProgramUniform1ui"/>
+            <command name="glProgramUniform2ui"/>
+            <command name="glProgramUniform3ui"/>
+            <command name="glProgramUniform4ui"/>
+            <command name="glProgramUniform1f"/>
+            <command name="glProgramUniform2f"/>
+            <command name="glProgramUniform3f"/>
+            <command name="glProgramUniform4f"/>
+            <command name="glProgramUniform1iv"/>
+            <command name="glProgramUniform2iv"/>
+            <command name="glProgramUniform3iv"/>
+            <command name="glProgramUniform4iv"/>
+            <command name="glProgramUniform1uiv"/>
+            <command name="glProgramUniform2uiv"/>
+            <command name="glProgramUniform3uiv"/>
+            <command name="glProgramUniform4uiv"/>
+            <command name="glProgramUniform1fv"/>
+            <command name="glProgramUniform2fv"/>
+            <command name="glProgramUniform3fv"/>
+            <command name="glProgramUniform4fv"/>
+            <command name="glProgramUniformMatrix2fv"/>
+            <command name="glProgramUniformMatrix3fv"/>
+            <command name="glProgramUniformMatrix4fv"/>
+            <command name="glProgramUniformMatrix2x3fv"/>
+            <command name="glProgramUniformMatrix3x2fv"/>
+            <command name="glProgramUniformMatrix2x4fv"/>
+            <command name="glProgramUniformMatrix4x2fv"/>
+            <command name="glProgramUniformMatrix3x4fv"/>
+            <command name="glProgramUniformMatrix4x3fv"/>
+            <command name="glValidateProgramPipeline"/>
+            <command name="glGetProgramPipelineInfoLog"/>
+            <enum name="GL_VERTEX_SHADER_BIT"/>
+            <enum name="GL_FRAGMENT_SHADER_BIT"/>
+            <enum name="GL_ALL_SHADER_BITS"/>
+            <enum name="GL_PROGRAM_SEPARABLE"/>
+            <enum name="GL_ACTIVE_PROGRAM"/>
+            <enum name="GL_PROGRAM_PIPELINE_BINDING"/>
+        </require>
+        <!-- shader_atomic_counters features -->
+        <require>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_BINDING"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_START"/>
+            <enum name="GL_ATOMIC_COUNTER_BUFFER_SIZE"/>
+            <enum name="GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_VERTEX_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_FRAGMENT_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_COMPUTE_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_COMBINED_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE"/>
+            <enum name="GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS"/>
+            <enum name="GL_ACTIVE_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_UNSIGNED_INT_ATOMIC_COUNTER"/>
+        </require>
+        <!-- shader_bitfield_operations features -->
+        <require/>
+        <!-- shader_image_load_store features -->
+        <require>
+            <command name="glBindImageTexture"/>
+            <command name="glGetBooleani_v"/>
+            <command name="glMemoryBarrier"/>
+            <command name="glMemoryBarrierByRegion"/>
+            <enum name="GL_MAX_IMAGE_UNITS"/>
+            <enum name="GL_MAX_VERTEX_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_FRAGMENT_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_COMPUTE_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_COMBINED_IMAGE_UNIFORMS"/>
+            <enum name="GL_IMAGE_BINDING_NAME"/>
+            <enum name="GL_IMAGE_BINDING_LEVEL"/>
+            <enum name="GL_IMAGE_BINDING_LAYERED"/>
+            <enum name="GL_IMAGE_BINDING_LAYER"/>
+            <enum name="GL_IMAGE_BINDING_ACCESS"/>
+            <enum name="GL_IMAGE_BINDING_FORMAT"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT"/>
+            <enum name="GL_ELEMENT_ARRAY_BARRIER_BIT"/>
+            <enum name="GL_UNIFORM_BARRIER_BIT"/>
+            <enum name="GL_TEXTURE_FETCH_BARRIER_BIT"/>
+            <enum name="GL_SHADER_IMAGE_ACCESS_BARRIER_BIT"/>
+            <enum name="GL_COMMAND_BARRIER_BIT"/>
+            <enum name="GL_PIXEL_BUFFER_BARRIER_BIT"/>
+            <enum name="GL_TEXTURE_UPDATE_BARRIER_BIT"/>
+            <enum name="GL_BUFFER_UPDATE_BARRIER_BIT"/>
+            <enum name="GL_FRAMEBUFFER_BARRIER_BIT"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_BARRIER_BIT"/>
+            <enum name="GL_ATOMIC_COUNTER_BARRIER_BIT"/>
+            <enum name="GL_ALL_BARRIER_BITS"/>
+            <enum name="GL_IMAGE_2D"/>
+            <enum name="GL_IMAGE_3D"/>
+            <enum name="GL_IMAGE_CUBE"/>
+            <enum name="GL_IMAGE_2D_ARRAY"/>
+            <enum name="GL_INT_IMAGE_2D"/>
+            <enum name="GL_INT_IMAGE_3D"/>
+            <enum name="GL_INT_IMAGE_CUBE"/>
+            <enum name="GL_INT_IMAGE_2D_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_2D"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_3D"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_CUBE"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_2D_ARRAY"/>
+            <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_TYPE"/>
+            <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE"/>
+            <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS"/>
+            <enum name="GL_READ_ONLY"/>
+            <enum name="GL_WRITE_ONLY"/>
+            <enum name="GL_READ_WRITE"/>
+        </require>
+        <!-- shader_layout_binding features -->
+        <require/>
+        <!-- shader_storage_buffer_object features -->
+        <require>
+            <enum name="GL_SHADER_STORAGE_BUFFER"/>
+            <enum name="GL_SHADER_STORAGE_BUFFER_BINDING"/>
+            <enum name="GL_SHADER_STORAGE_BUFFER_START"/>
+            <enum name="GL_SHADER_STORAGE_BUFFER_SIZE"/>
+            <enum name="GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS"/>
+            <enum name="GL_MAX_SHADER_STORAGE_BLOCK_SIZE"/>
+            <enum name="GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT"/>
+            <enum name="GL_SHADER_STORAGE_BARRIER_BIT"/>
+            <enum name="GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES"/>
+        </require>
+        <!-- stencil_texturing features -->
+        <require>
+            <enum name="GL_DEPTH_STENCIL_TEXTURE_MODE"/>
+            <enum name="GL_STENCIL_INDEX"/>
+        </require>
+        <!-- texture_gather features -->
+        <require>
+            <enum name="GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET"/>
+            <enum name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET"/>
+        </require>
+        <!-- texture_storage_multisample features -->
+        <require>
+            <command name="glTexStorage2DMultisample"/>
+            <command name="glGetMultisamplefv"/>
+            <command name="glSampleMaski"/>
+            <command name="glGetTexLevelParameteriv"/>
+            <command name="glGetTexLevelParameterfv"/>
+            <enum name="GL_SAMPLE_POSITION"/>
+            <enum name="GL_SAMPLE_MASK"/>
+            <enum name="GL_SAMPLE_MASK_VALUE"/>
+            <enum name="GL_TEXTURE_2D_MULTISAMPLE"/>
+            <enum name="GL_MAX_SAMPLE_MASK_WORDS"/>
+            <enum name="GL_MAX_COLOR_TEXTURE_SAMPLES"/>
+            <enum name="GL_MAX_DEPTH_TEXTURE_SAMPLES"/>
+            <enum name="GL_MAX_INTEGER_SAMPLES"/>
+            <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE"/>
+            <enum name="GL_TEXTURE_SAMPLES"/>
+            <enum name="GL_TEXTURE_FIXED_SAMPLE_LOCATIONS"/>
+            <enum name="GL_TEXTURE_WIDTH"/>
+            <enum name="GL_TEXTURE_HEIGHT"/>
+            <enum name="GL_TEXTURE_DEPTH"/>
+            <enum name="GL_TEXTURE_INTERNAL_FORMAT"/>
+            <enum name="GL_TEXTURE_RED_SIZE"/>
+            <enum name="GL_TEXTURE_GREEN_SIZE"/>
+            <enum name="GL_TEXTURE_BLUE_SIZE"/>
+            <enum name="GL_TEXTURE_ALPHA_SIZE"/>
+            <enum name="GL_TEXTURE_DEPTH_SIZE"/>
+            <enum name="GL_TEXTURE_STENCIL_SIZE"/>
+            <enum name="GL_TEXTURE_SHARED_SIZE"/>
+            <enum name="GL_TEXTURE_RED_TYPE"/>
+            <enum name="GL_TEXTURE_GREEN_TYPE"/>
+            <enum name="GL_TEXTURE_BLUE_TYPE"/>
+            <enum name="GL_TEXTURE_ALPHA_TYPE"/>
+            <enum name="GL_TEXTURE_DEPTH_TYPE"/>
+            <enum name="GL_TEXTURE_COMPRESSED"/>
+            <enum name="GL_SAMPLER_2D_MULTISAMPLE"/>
+            <enum name="GL_INT_SAMPLER_2D_MULTISAMPLE"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE"/>
+        </require>
+        <!-- vertex_attrib_binding features -->
+        <require>
+            <command name="glBindVertexBuffer"/>
+            <command name="glVertexAttribFormat"/>
+            <command name="glVertexAttribIFormat"/>
+            <command name="glVertexAttribBinding"/>
+            <command name="glVertexBindingDivisor"/>
+            <enum name="GL_VERTEX_ATTRIB_BINDING"/>
+            <enum name="GL_VERTEX_ATTRIB_RELATIVE_OFFSET"/>
+            <enum name="GL_VERTEX_BINDING_DIVISOR"/>
+            <enum name="GL_VERTEX_BINDING_OFFSET"/>
+            <enum name="GL_VERTEX_BINDING_STRIDE"/>
+            <enum name="GL_VERTEX_BINDING_BUFFER"/>
+            <enum name="GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET"/>
+            <enum name="GL_MAX_VERTEX_ATTRIB_BINDINGS"/>
+            <enum name="GL_MAX_VERTEX_ATTRIB_STRIDE"/>
+        </require>
+    </feature>
+    <feature api="gles2" name="GL_ES_VERSION_3_2" number="3.2">
+        <!-- 3.2-specific point features -->
+        <require>
+            <enum name="GL_MULTISAMPLE_LINE_WIDTH_RANGE"/>
+            <enum name="GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY"/>
+        </require>
+        <!-- Android extension pack features -->
+        <require/>
+        <!-- blend_equation_advanced features -->
+        <require>
+            <enum name="GL_MULTIPLY"/>
+            <enum name="GL_SCREEN"/>
+            <enum name="GL_OVERLAY"/>
+            <enum name="GL_DARKEN"/>
+            <enum name="GL_LIGHTEN"/>
+            <enum name="GL_COLORDODGE"/>
+            <enum name="GL_COLORBURN"/>
+            <enum name="GL_HARDLIGHT"/>
+            <enum name="GL_SOFTLIGHT"/>
+            <enum name="GL_DIFFERENCE"/>
+            <enum name="GL_EXCLUSION"/>
+            <enum name="GL_HSL_HUE"/>
+            <enum name="GL_HSL_SATURATION"/>
+            <enum name="GL_HSL_COLOR"/>
+            <enum name="GL_HSL_LUMINOSITY"/>
+            <command name="glBlendBarrier"/>
+        </require>
+        <!-- color_buffer_float features -->
+        <require/>
+        <!-- copy_image features -->
+        <require>
+            <command name="glCopyImageSubData"/>
+        </require>
+        <!-- debug features -->
+        <require>
+            <enum name="GL_DEBUG_OUTPUT_SYNCHRONOUS"/>
+            <enum name="GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH"/>
+            <enum name="GL_DEBUG_CALLBACK_FUNCTION"/>
+            <enum name="GL_DEBUG_CALLBACK_USER_PARAM"/>
+            <enum name="GL_DEBUG_SOURCE_API"/>
+            <enum name="GL_DEBUG_SOURCE_WINDOW_SYSTEM"/>
+            <enum name="GL_DEBUG_SOURCE_SHADER_COMPILER"/>
+            <enum name="GL_DEBUG_SOURCE_THIRD_PARTY"/>
+            <enum name="GL_DEBUG_SOURCE_APPLICATION"/>
+            <enum name="GL_DEBUG_SOURCE_OTHER"/>
+            <enum name="GL_DEBUG_TYPE_ERROR"/>
+            <enum name="GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"/>
+            <enum name="GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"/>
+            <enum name="GL_DEBUG_TYPE_PORTABILITY"/>
+            <enum name="GL_DEBUG_TYPE_PERFORMANCE"/>
+            <enum name="GL_DEBUG_TYPE_OTHER"/>
+            <enum name="GL_DEBUG_TYPE_MARKER"/>
+            <enum name="GL_DEBUG_TYPE_PUSH_GROUP"/>
+            <enum name="GL_DEBUG_TYPE_POP_GROUP"/>
+            <enum name="GL_DEBUG_SEVERITY_NOTIFICATION"/>
+            <enum name="GL_MAX_DEBUG_GROUP_STACK_DEPTH"/>
+            <enum name="GL_DEBUG_GROUP_STACK_DEPTH"/>
+            <enum name="GL_BUFFER"/>
+            <enum name="GL_SHADER"/>
+            <enum name="GL_PROGRAM"/>
+            <enum name="GL_VERTEX_ARRAY"/>
+            <enum name="GL_QUERY"/>
+            <enum name="GL_PROGRAM_PIPELINE"/>
+            <enum name="GL_SAMPLER"/>
+            <enum name="GL_MAX_LABEL_LENGTH"/>
+            <enum name="GL_MAX_DEBUG_MESSAGE_LENGTH"/>
+            <enum name="GL_MAX_DEBUG_LOGGED_MESSAGES"/>
+            <enum name="GL_DEBUG_LOGGED_MESSAGES"/>
+            <enum name="GL_DEBUG_SEVERITY_HIGH"/>
+            <enum name="GL_DEBUG_SEVERITY_MEDIUM"/>
+            <enum name="GL_DEBUG_SEVERITY_LOW"/>
+            <enum name="GL_DEBUG_OUTPUT"/>
+            <enum name="GL_CONTEXT_FLAG_DEBUG_BIT"/>
+            <enum name="GL_STACK_OVERFLOW"/>
+            <enum name="GL_STACK_UNDERFLOW"/>
+            <command name="glDebugMessageControl"/>
+            <command name="glDebugMessageInsert"/>
+            <command name="glDebugMessageCallback"/>
+            <command name="glGetDebugMessageLog"/>
+            <command name="glPushDebugGroup"/>
+            <command name="glPopDebugGroup"/>
+            <command name="glObjectLabel"/>
+            <command name="glGetObjectLabel"/>
+            <command name="glObjectPtrLabel"/>
+            <command name="glGetObjectPtrLabel"/>
+            <command name="glGetPointerv"/>
+        </require>
+        <!-- draw_buffers_indexed features -->
+        <require>
+            <!-- All tokens are already part of ES 3.0 -->
+            <command name="glEnablei"/>
+            <command name="glDisablei"/>
+            <command name="glBlendEquationi"/>
+            <command name="glBlendEquationSeparatei"/>
+            <command name="glBlendFunci"/>
+            <command name="glBlendFuncSeparatei"/>
+            <command name="glColorMaski"/>
+            <command name="glIsEnabledi"/>
+        </require>
+        <!-- draw_elements_base_vertex features -->
+        <require>
+            <command name="glDrawElementsBaseVertex"/>
+            <command name="glDrawRangeElementsBaseVertex"/>
+            <command name="glDrawElementsInstancedBaseVertex"/>
+        </require>
+        <!-- geometry_shader features -->
+        <require>
+            <enum name="GL_GEOMETRY_SHADER"/>
+            <enum name="GL_GEOMETRY_SHADER_BIT"/>
+            <enum name="GL_GEOMETRY_VERTICES_OUT"/>
+            <enum name="GL_GEOMETRY_INPUT_TYPE"/>
+            <enum name="GL_GEOMETRY_OUTPUT_TYPE"/>
+            <enum name="GL_GEOMETRY_SHADER_INVOCATIONS"/>
+            <enum name="GL_LAYER_PROVOKING_VERTEX"/>
+            <enum name="GL_LINES_ADJACENCY"/>
+            <enum name="GL_LINE_STRIP_ADJACENCY"/>
+            <enum name="GL_TRIANGLES_ADJACENCY"/>
+            <enum name="GL_TRIANGLE_STRIP_ADJACENCY"/>
+            <enum name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_OUTPUT_VERTICES"/>
+            <enum name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS"/>
+            <enum name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_FIRST_VERTEX_CONVENTION"/>
+            <enum name="GL_LAST_VERTEX_CONVENTION"/>
+            <enum name="GL_UNDEFINED_VERTEX"/>
+            <enum name="GL_PRIMITIVES_GENERATED"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_LAYERS"/>
+            <enum name="GL_MAX_FRAMEBUFFER_LAYERS"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED"/>
+            <enum name="GL_REFERENCED_BY_GEOMETRY_SHADER"/>
+            <command name="glFramebufferTexture"/>
+        </require>
+        <!-- gpu_shader5 features -->
+        <require/>
+        <!-- primitive_bounding_box features -->
+        <require>
+            <enum name="GL_PRIMITIVE_BOUNDING_BOX"/>
+            <command name="glPrimitiveBoundingBox"/>
+        </require>
+        <!-- robustness features -->
+        <require>
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT"/>
+            <enum name="GL_CONTEXT_FLAGS"/>
+            <enum name="GL_LOSE_CONTEXT_ON_RESET"/>
+            <enum name="GL_GUILTY_CONTEXT_RESET"/>
+            <enum name="GL_INNOCENT_CONTEXT_RESET"/>
+            <enum name="GL_UNKNOWN_CONTEXT_RESET"/>
+            <enum name="GL_RESET_NOTIFICATION_STRATEGY"/>
+            <enum name="GL_NO_RESET_NOTIFICATION"/>
+            <enum name="GL_CONTEXT_LOST"/>
+            <command name="glGetGraphicsResetStatus"/>
+            <command name="glReadnPixels"/>
+            <command name="glGetnUniformfv"/>
+            <command name="glGetnUniformiv"/>
+            <command name="glGetnUniformuiv"/>
+        </require>
+        <!-- sample_shading features -->
+        <require>
+            <command name="glMinSampleShading"/>
+            <enum name="GL_SAMPLE_SHADING"/>
+            <enum name="GL_MIN_SAMPLE_SHADING_VALUE"/>
+        </require>
+        <!-- sample_variables features -->
+        <require/>
+        <!-- shader_image_atomic features -->
+        <require/>
+        <!-- shader_io_blocks features -->
+        <require/>
+        <!-- shader_multisample_interpolation features -->
+        <require>
+            <enum name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET"/>
+            <enum name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET"/>
+            <enum name="GL_FRAGMENT_INTERPOLATION_OFFSET_BITS"/>
+        </require>
+        <!-- tessellation_shader features -->
+        <require>
+            <enum name="GL_PATCHES"/>
+            <enum name="GL_PATCH_VERTICES"/>
+            <enum name="GL_TESS_CONTROL_OUTPUT_VERTICES"/>
+            <enum name="GL_TESS_GEN_MODE"/>
+            <enum name="GL_TESS_GEN_SPACING"/>
+            <enum name="GL_TESS_GEN_VERTEX_ORDER"/>
+            <enum name="GL_TESS_GEN_POINT_MODE"/>
+            <enum name="GL_TRIANGLES"/>
+            <enum name="GL_ISOLINES"/>
+            <enum name="GL_QUADS"/>
+            <enum name="GL_EQUAL"/>
+            <enum name="GL_FRACTIONAL_ODD"/>
+            <enum name="GL_FRACTIONAL_EVEN"/>
+            <enum name="GL_CCW"/>
+            <enum name="GL_CW"/>
+            <enum name="GL_MAX_PATCH_VERTICES"/>
+            <enum name="GL_MAX_TESS_GEN_LEVEL"/>
+            <enum name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_PATCH_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"/>
+            <enum name="GL_IS_PER_PATCH"/>
+            <enum name="GL_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+            <enum name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+            <enum name="GL_TESS_CONTROL_SHADER"/>
+            <enum name="GL_TESS_EVALUATION_SHADER"/>
+            <enum name="GL_TESS_CONTROL_SHADER_BIT"/>
+            <enum name="GL_TESS_EVALUATION_SHADER_BIT"/>
+            <command name="glPatchParameteri"/>
+        </require>
+        <!-- texture_border_clamp features -->
+        <require>
+            <enum name="GL_TEXTURE_BORDER_COLOR"/>
+            <enum name="GL_CLAMP_TO_BORDER"/>
+            <command name="glTexParameterIiv"/>
+            <command name="glTexParameterIuiv"/>
+            <command name="glGetTexParameterIiv"/>
+            <command name="glGetTexParameterIuiv"/>
+            <command name="glSamplerParameterIiv"/>
+            <command name="glSamplerParameterIuiv"/>
+            <command name="glGetSamplerParameterIiv"/>
+            <command name="glGetSamplerParameterIuiv"/>
+        </require>
+        <!-- texture_buffer features -->
+        <require>
+            <enum name="GL_TEXTURE_BUFFER"/>
+            <enum name="GL_TEXTURE_BUFFER_BINDING"/>
+            <enum name="GL_MAX_TEXTURE_BUFFER_SIZE"/>
+            <enum name="GL_TEXTURE_BINDING_BUFFER"/>
+            <enum name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING"/>
+            <enum name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT"/>
+            <enum name="GL_SAMPLER_BUFFER"/>
+            <enum name="GL_INT_SAMPLER_BUFFER"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_BUFFER"/>
+            <enum name="GL_IMAGE_BUFFER"/>
+            <enum name="GL_INT_IMAGE_BUFFER"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_BUFFER"/>
+            <enum name="GL_TEXTURE_BUFFER_OFFSET"/>
+            <enum name="GL_TEXTURE_BUFFER_SIZE"/>
+            <command name="glTexBuffer"/>
+            <command name="glTexBufferRange"/>
+        </require>
+        <!-- texture_compression_astc_ldr features -->
+        <require>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_4x4"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_5x4"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_5x5"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_6x5"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_6x6"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_8x5"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_8x6"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_8x8"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_10x5"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_10x6"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_10x8"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_10x10"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_12x10"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_12x12"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12"/>
+        </require>
+        <!-- texture_cube_map_array features -->
+        <require>
+            <enum name="GL_TEXTURE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"/>
+            <enum name="GL_SAMPLER_CUBE_MAP_ARRAY"/>
+            <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW"/>
+            <enum name="GL_INT_SAMPLER_CUBE_MAP_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY"/>
+            <enum name="GL_IMAGE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_INT_IMAGE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY"/>
+        </require>
+        <!-- texture_stencil8 features -->
+        <require>
+            <enum name="GL_STENCIL_INDEX"/>
+            <enum name="GL_STENCIL_INDEX8"/>
+        </require>
+        <!-- texture_storage_multisample_2d_array features -->
+        <require>
+            <enum name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+            <command name="glTexStorage3DMultisample"/>
+        </require>
+    </feature>
+    <feature api="glsc2" name="GL_SC_VERSION_2_0" number="2.0">
+        <require comment="Not used by the API, but could be used by applications">
+            <type name="GLbyte" comment="Used to define GL_BYTE data"/>
+            <type name="GLshort" comment="Used to define GL_SHORT data"/>
+            <type name="GLushort" comment="Used to define GL_UNSIGNED_SHORT data"/>
+        </require>
+        <require>
+            <enum name="GL_DEPTH_BUFFER_BIT"/>
+            <enum name="GL_STENCIL_BUFFER_BIT"/>
+            <enum name="GL_COLOR_BUFFER_BIT"/>
+            <enum name="GL_FALSE"/>
+            <enum name="GL_TRUE"/>
+            <enum name="GL_POINTS"/>
+            <enum name="GL_LINES"/>
+            <enum name="GL_LINE_LOOP"/>
+            <enum name="GL_LINE_STRIP"/>
+            <enum name="GL_TRIANGLES"/>
+            <enum name="GL_TRIANGLE_STRIP"/>
+            <enum name="GL_TRIANGLE_FAN"/>
+            <enum name="GL_ZERO"/>
+            <enum name="GL_ONE"/>
+            <enum name="GL_SRC_COLOR"/>
+            <enum name="GL_ONE_MINUS_SRC_COLOR"/>
+            <enum name="GL_SRC_ALPHA"/>
+            <enum name="GL_ONE_MINUS_SRC_ALPHA"/>
+            <enum name="GL_DST_ALPHA"/>
+            <enum name="GL_ONE_MINUS_DST_ALPHA"/>
+            <enum name="GL_DST_COLOR"/>
+            <enum name="GL_ONE_MINUS_DST_COLOR"/>
+            <enum name="GL_SRC_ALPHA_SATURATE"/>
+            <enum name="GL_FUNC_ADD"/>
+            <enum name="GL_BLEND_EQUATION"/>
+            <enum name="GL_BLEND_EQUATION_RGB"/>
+            <enum name="GL_BLEND_EQUATION_ALPHA"/>
+            <enum name="GL_FUNC_SUBTRACT"/>
+            <enum name="GL_FUNC_REVERSE_SUBTRACT"/>
+            <enum name="GL_BLEND_DST_RGB"/>
+            <enum name="GL_BLEND_SRC_RGB"/>
+            <enum name="GL_BLEND_DST_ALPHA"/>
+            <enum name="GL_BLEND_SRC_ALPHA"/>
+            <enum name="GL_CONSTANT_COLOR"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_COLOR"/>
+            <enum name="GL_CONSTANT_ALPHA"/>
+            <enum name="GL_ONE_MINUS_CONSTANT_ALPHA"/>
+            <enum name="GL_BLEND_COLOR"/>
+            <enum name="GL_ARRAY_BUFFER"/>
+            <enum name="GL_ELEMENT_ARRAY_BUFFER"/>
+            <enum name="GL_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_ELEMENT_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_STREAM_DRAW"/>
+            <enum name="GL_STATIC_DRAW"/>
+            <enum name="GL_DYNAMIC_DRAW"/>
+            <enum name="GL_BUFFER_SIZE"/>
+            <enum name="GL_BUFFER_USAGE"/>
+            <enum name="GL_CURRENT_VERTEX_ATTRIB"/>
+            <enum name="GL_FRONT"/>
+            <enum name="GL_BACK"/>
+            <enum name="GL_FRONT_AND_BACK"/>
+            <enum name="GL_TEXTURE_2D"/>
+            <enum name="GL_CULL_FACE"/>
+            <enum name="GL_BLEND"/>
+            <enum name="GL_DITHER"/>
+            <enum name="GL_STENCIL_TEST"/>
+            <enum name="GL_DEPTH_TEST"/>
+            <enum name="GL_SCISSOR_TEST"/>
+            <enum name="GL_POLYGON_OFFSET_FILL"/>
+            <enum name="GL_SAMPLE_ALPHA_TO_COVERAGE"/>
+            <enum name="GL_SAMPLE_COVERAGE"/>
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_INVALID_ENUM"/>
+            <enum name="GL_INVALID_VALUE"/>
+            <enum name="GL_INVALID_OPERATION"/>
+            <enum name="GL_OUT_OF_MEMORY"/>
+            <enum name="GL_INVALID_FRAMEBUFFER_OPERATION"/>
+            <enum name="GL_CONTEXT_LOST"/>
+            <enum name="GL_CW"/>
+            <enum name="GL_CCW"/>
+            <enum name="GL_LINE_WIDTH"/>
+            <enum name="GL_ALIASED_POINT_SIZE_RANGE"/>
+            <enum name="GL_ALIASED_LINE_WIDTH_RANGE"/>
+            <enum name="GL_CULL_FACE_MODE"/>
+            <enum name="GL_FRONT_FACE"/>
+            <enum name="GL_DEPTH_RANGE"/>
+            <enum name="GL_DEPTH_WRITEMASK"/>
+            <enum name="GL_DEPTH_CLEAR_VALUE"/>
+            <enum name="GL_DEPTH_FUNC"/>
+            <enum name="GL_STENCIL_CLEAR_VALUE"/>
+            <enum name="GL_STENCIL_FUNC"/>
+            <enum name="GL_STENCIL_FAIL"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_FAIL"/>
+            <enum name="GL_STENCIL_PASS_DEPTH_PASS"/>
+            <enum name="GL_STENCIL_REF"/>
+            <enum name="GL_STENCIL_VALUE_MASK"/>
+            <enum name="GL_STENCIL_WRITEMASK"/>
+            <enum name="GL_STENCIL_BACK_FUNC"/>
+            <enum name="GL_STENCIL_BACK_FAIL"/>
+            <enum name="GL_STENCIL_BACK_PASS_DEPTH_FAIL"/>
+            <enum name="GL_STENCIL_BACK_PASS_DEPTH_PASS"/>
+            <enum name="GL_STENCIL_BACK_REF"/>
+            <enum name="GL_STENCIL_BACK_VALUE_MASK"/>
+            <enum name="GL_STENCIL_BACK_WRITEMASK"/>
+            <enum name="GL_VIEWPORT"/>
+            <enum name="GL_SCISSOR_BOX"/>
+            <enum name="GL_COLOR_CLEAR_VALUE"/>
+            <enum name="GL_COLOR_WRITEMASK"/>
+            <enum name="GL_UNPACK_ALIGNMENT"/>
+            <enum name="GL_PACK_ALIGNMENT"/>
+            <enum name="GL_MAX_TEXTURE_SIZE"/>
+            <enum name="GL_MAX_VIEWPORT_DIMS"/>
+            <enum name="GL_SUBPIXEL_BITS"/>
+            <enum name="GL_RED_BITS"/>
+            <enum name="GL_GREEN_BITS"/>
+            <enum name="GL_BLUE_BITS"/>
+            <enum name="GL_ALPHA_BITS"/>
+            <enum name="GL_DEPTH_BITS"/>
+            <enum name="GL_STENCIL_BITS"/>
+            <enum name="GL_POLYGON_OFFSET_UNITS"/>
+            <enum name="GL_POLYGON_OFFSET_FACTOR"/>
+            <enum name="GL_TEXTURE_BINDING_2D"/>
+            <enum name="GL_SAMPLE_BUFFERS"/>
+            <enum name="GL_SAMPLES"/>
+            <enum name="GL_SAMPLE_COVERAGE_VALUE"/>
+            <enum name="GL_SAMPLE_COVERAGE_INVERT"/>
+            <enum name="GL_NUM_COMPRESSED_TEXTURE_FORMATS"/>
+            <enum name="GL_COMPRESSED_TEXTURE_FORMATS"/>
+            <enum name="GL_DONT_CARE"/>
+            <enum name="GL_FASTEST"/>
+            <enum name="GL_NICEST"/>
+            <enum name="GL_GENERATE_MIPMAP_HINT"/>
+            <enum name="GL_BYTE"/>
+            <enum name="GL_UNSIGNED_BYTE"/>
+            <enum name="GL_SHORT"/>
+            <enum name="GL_UNSIGNED_SHORT"/>
+            <enum name="GL_INT"/>
+            <enum name="GL_UNSIGNED_INT"/>
+            <enum name="GL_FLOAT"/>
+            <enum name="GL_RED"/>
+            <enum name="GL_RG"/>
+            <enum name="GL_RGB"/>
+            <enum name="GL_RGBA"/>
+            <enum name="GL_UNSIGNED_SHORT_4_4_4_4"/>
+            <enum name="GL_UNSIGNED_SHORT_5_5_5_1"/>
+            <enum name="GL_UNSIGNED_SHORT_5_6_5"/>
+            <enum name="GL_MAX_VERTEX_ATTRIBS"/>
+            <enum name="GL_MAX_VERTEX_UNIFORM_VECTORS"/>
+            <enum name="GL_MAX_VARYING_VECTORS"/>
+            <enum name="GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_FRAGMENT_UNIFORM_VECTORS"/>
+            <enum name="GL_LINK_STATUS"/>
+            <enum name="GL_SHADING_LANGUAGE_VERSION"/>
+            <enum name="GL_CURRENT_PROGRAM"/>
+            <enum name="GL_NEVER"/>
+            <enum name="GL_LESS"/>
+            <enum name="GL_EQUAL"/>
+            <enum name="GL_LEQUAL"/>
+            <enum name="GL_GREATER"/>
+            <enum name="GL_NOTEQUAL"/>
+            <enum name="GL_GEQUAL"/>
+            <enum name="GL_ALWAYS"/>
+            <enum name="GL_KEEP"/>
+            <enum name="GL_REPLACE"/>
+            <enum name="GL_INCR"/>
+            <enum name="GL_DECR"/>
+            <enum name="GL_INVERT"/>
+            <enum name="GL_INCR_WRAP"/>
+            <enum name="GL_DECR_WRAP"/>
+            <enum name="GL_VENDOR"/>
+            <enum name="GL_RENDERER"/>
+            <enum name="GL_VERSION"/>
+            <enum name="GL_EXTENSIONS"/>
+            <enum name="GL_NEAREST"/>
+            <enum name="GL_LINEAR"/>
+            <enum name="GL_NEAREST_MIPMAP_NEAREST"/>
+            <enum name="GL_LINEAR_MIPMAP_NEAREST"/>
+            <enum name="GL_NEAREST_MIPMAP_LINEAR"/>
+            <enum name="GL_LINEAR_MIPMAP_LINEAR"/>
+            <enum name="GL_TEXTURE_MAG_FILTER"/>
+            <enum name="GL_TEXTURE_MIN_FILTER"/>
+            <enum name="GL_TEXTURE_WRAP_S"/>
+            <enum name="GL_TEXTURE_WRAP_T"/>
+            <enum name="GL_TEXTURE_IMMUTABLE_FORMAT"/>
+            <enum name="GL_TEXTURE"/>
+            <enum name="GL_TEXTURE0"/>
+            <enum name="GL_TEXTURE1"/>
+            <enum name="GL_TEXTURE2"/>
+            <enum name="GL_TEXTURE3"/>
+            <enum name="GL_TEXTURE4"/>
+            <enum name="GL_TEXTURE5"/>
+            <enum name="GL_TEXTURE6"/>
+            <enum name="GL_TEXTURE7"/>
+            <enum name="GL_TEXTURE8"/>
+            <enum name="GL_TEXTURE9"/>
+            <enum name="GL_TEXTURE10"/>
+            <enum name="GL_TEXTURE11"/>
+            <enum name="GL_TEXTURE12"/>
+            <enum name="GL_TEXTURE13"/>
+            <enum name="GL_TEXTURE14"/>
+            <enum name="GL_TEXTURE15"/>
+            <enum name="GL_TEXTURE16"/>
+            <enum name="GL_TEXTURE17"/>
+            <enum name="GL_TEXTURE18"/>
+            <enum name="GL_TEXTURE19"/>
+            <enum name="GL_TEXTURE20"/>
+            <enum name="GL_TEXTURE21"/>
+            <enum name="GL_TEXTURE22"/>
+            <enum name="GL_TEXTURE23"/>
+            <enum name="GL_TEXTURE24"/>
+            <enum name="GL_TEXTURE25"/>
+            <enum name="GL_TEXTURE26"/>
+            <enum name="GL_TEXTURE27"/>
+            <enum name="GL_TEXTURE28"/>
+            <enum name="GL_TEXTURE29"/>
+            <enum name="GL_TEXTURE30"/>
+            <enum name="GL_TEXTURE31"/>
+            <enum name="GL_ACTIVE_TEXTURE"/>
+            <enum name="GL_REPEAT"/>
+            <enum name="GL_CLAMP_TO_EDGE"/>
+            <enum name="GL_MIRRORED_REPEAT"/>
+            <enum name="GL_SAMPLER_2D"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_ENABLED"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_SIZE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_STRIDE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_TYPE"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_POINTER"/>
+            <enum name="GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"/>
+            <enum name="GL_IMPLEMENTATION_COLOR_READ_TYPE"/>
+            <enum name="GL_IMPLEMENTATION_COLOR_READ_FORMAT"/>
+            <enum name="GL_NUM_PROGRAM_BINARY_FORMATS"/>
+            <enum name="GL_PROGRAM_BINARY_FORMATS"/>
+            <enum name="GL_LOW_FLOAT"/>
+            <enum name="GL_MEDIUM_FLOAT"/>
+            <enum name="GL_HIGH_FLOAT"/>
+            <enum name="GL_LOW_INT"/>
+            <enum name="GL_MEDIUM_INT"/>
+            <enum name="GL_HIGH_INT"/>
+            <enum name="GL_FRAMEBUFFER"/>
+            <enum name="GL_RENDERBUFFER"/>
+            <enum name="GL_R8"/>
+            <enum name="GL_RG8"/>
+            <enum name="GL_RGB8"/>
+            <enum name="GL_RGBA8"/>
+            <enum name="GL_RGBA4"/>
+            <enum name="GL_RGB5_A1"/>
+            <enum name="GL_RGB565"/>
+            <enum name="GL_DEPTH_COMPONENT16"/>
+            <enum name="GL_STENCIL_INDEX8"/>
+            <enum name="GL_RENDERBUFFER_WIDTH"/>
+            <enum name="GL_RENDERBUFFER_HEIGHT"/>
+            <enum name="GL_RENDERBUFFER_INTERNAL_FORMAT"/>
+            <enum name="GL_RENDERBUFFER_RED_SIZE"/>
+            <enum name="GL_RENDERBUFFER_GREEN_SIZE"/>
+            <enum name="GL_RENDERBUFFER_BLUE_SIZE"/>
+            <enum name="GL_RENDERBUFFER_ALPHA_SIZE"/>
+            <enum name="GL_RENDERBUFFER_DEPTH_SIZE"/>
+            <enum name="GL_RENDERBUFFER_STENCIL_SIZE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL"/>
+            <enum name="GL_COLOR_ATTACHMENT0"/>
+            <enum name="GL_DEPTH_ATTACHMENT"/>
+            <enum name="GL_STENCIL_ATTACHMENT"/>
+            <enum name="GL_NONE"/>
+            <enum name="GL_FRAMEBUFFER_COMPLETE"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"/>
+            <enum name="GL_FRAMEBUFFER_UNSUPPORTED"/>
+            <enum name="GL_FRAMEBUFFER_UNDEFINED"/>
+            <enum name="GL_FRAMEBUFFER_BINDING"/>
+            <enum name="GL_RENDERBUFFER_BINDING"/>
+            <enum name="GL_MAX_RENDERBUFFER_SIZE"/>
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_GUILTY_CONTEXT_RESET"/>
+            <enum name="GL_INNOCENT_CONTEXT_RESET"/>
+            <enum name="GL_UNKNOWN_CONTEXT_RESET"/>
+            <enum name="GL_CONTEXT_ROBUST_ACCESS"/>
+            <enum name="GL_RESET_NOTIFICATION_STRATEGY"/>
+            <enum name="GL_LOSE_CONTEXT_ON_RESET"/>
+            <command name="glActiveTexture"/>
+            <command name="glBindBuffer"/>
+            <command name="glBindFramebuffer"/>
+            <command name="glBindRenderbuffer"/>
+            <command name="glBindTexture"/>
+            <command name="glBlendColor"/>
+            <command name="glBlendEquation"/>
+            <command name="glBlendEquationSeparate"/>
+            <command name="glBlendFunc"/>
+            <command name="glBlendFuncSeparate"/>
+            <command name="glBufferData"/>
+            <command name="glBufferSubData"/>
+            <command name="glCheckFramebufferStatus"/>
+            <command name="glClear"/>
+            <command name="glClearColor"/>
+            <command name="glClearDepthf"/>
+            <command name="glClearStencil"/>
+            <command name="glColorMask"/>
+            <command name="glCompressedTexSubImage2D"/>
+            <command name="glCreateProgram"/>
+            <command name="glCullFace"/>
+            <command name="glDepthFunc"/>
+            <command name="glDepthMask"/>
+            <command name="glDepthRangef"/>
+            <command name="glDisable"/>
+            <command name="glDisableVertexAttribArray"/>
+            <command name="glDrawArrays"/>
+            <command name="glDrawRangeElements"/>
+            <command name="glEnable"/>
+            <command name="glEnableVertexAttribArray"/>
+            <command name="glFinish"/>
+            <command name="glFlush"/>
+            <command name="glFramebufferRenderbuffer"/>
+            <command name="glFramebufferTexture2D"/>
+            <command name="glFrontFace"/>
+            <command name="glGenBuffers"/>
+            <command name="glGenerateMipmap"/>
+            <command name="glGenFramebuffers"/>
+            <command name="glGenRenderbuffers"/>
+            <command name="glGenTextures"/>
+            <command name="glGetAttribLocation"/>
+            <command name="glGetBooleanv"/>
+            <command name="glGetBufferParameteriv"/>
+            <command name="glGetError"/>
+            <command name="glGetFloatv"/>
+            <command name="glGetFramebufferAttachmentParameteriv"/>
+            <command name="glGetGraphicsResetStatus"/>
+            <command name="glGetIntegerv"/>
+            <command name="glGetProgramiv"/>
+            <command name="glGetRenderbufferParameteriv"/>
+            <command name="glGetString"/>
+            <command name="glGetTexParameterfv"/>
+            <command name="glGetTexParameteriv"/>
+            <command name="glGetnUniformfv"/>
+            <command name="glGetnUniformiv"/>
+            <command name="glGetUniformLocation"/>
+            <command name="glGetVertexAttribfv"/>
+            <command name="glGetVertexAttribiv"/>
+            <command name="glGetVertexAttribPointerv"/>
+            <command name="glHint"/>
+            <command name="glIsEnabled"/>
+            <command name="glLineWidth"/>
+            <command name="glPixelStorei"/>
+            <command name="glPolygonOffset"/>
+            <command name="glProgramBinary"/>
+            <command name="glReadnPixels"/>
+            <command name="glRenderbufferStorage"/>
+            <command name="glSampleCoverage"/>
+            <command name="glScissor"/>
+            <command name="glStencilFunc"/>
+            <command name="glStencilFuncSeparate"/>
+            <command name="glStencilMask"/>
+            <command name="glStencilMaskSeparate"/>
+            <command name="glStencilOp"/>
+            <command name="glStencilOpSeparate"/>
+            <command name="glTexStorage2D"/>
+            <command name="glTexParameterf"/>
+            <command name="glTexParameterfv"/>
+            <command name="glTexParameteri"/>
+            <command name="glTexParameteriv"/>
+            <command name="glTexSubImage2D"/>
+            <command name="glUniform1f"/>
+            <command name="glUniform1fv"/>
+            <command name="glUniform1i"/>
+            <command name="glUniform1iv"/>
+            <command name="glUniform2f"/>
+            <command name="glUniform2fv"/>
+            <command name="glUniform2i"/>
+            <command name="glUniform2iv"/>
+            <command name="glUniform3f"/>
+            <command name="glUniform3fv"/>
+            <command name="glUniform3i"/>
+            <command name="glUniform3iv"/>
+            <command name="glUniform4f"/>
+            <command name="glUniform4fv"/>
+            <command name="glUniform4i"/>
+            <command name="glUniform4iv"/>
+            <command name="glUniformMatrix2fv"/>
+            <command name="glUniformMatrix3fv"/>
+            <command name="glUniformMatrix4fv"/>
+            <command name="glUseProgram"/>
+            <command name="glVertexAttrib1f"/>
+            <command name="glVertexAttrib1fv"/>
+            <command name="glVertexAttrib2f"/>
+            <command name="glVertexAttrib2fv"/>
+            <command name="glVertexAttrib3f"/>
+            <command name="glVertexAttrib3fv"/>
+            <command name="glVertexAttrib4f"/>
+            <command name="glVertexAttrib4fv"/>
+            <command name="glVertexAttribPointer"/>
+            <command name="glViewport"/>
+        </require>
+    </feature>
+
+    <!-- SECTION: OpenGL / OpenGL ES extension interface definitions -->
+    <extensions>
+        <extension name="GL_3DFX_multisample" supported="gl">
+            <require>
+                <enum name="GL_MULTISAMPLE_3DFX"/>
+                <enum name="GL_SAMPLE_BUFFERS_3DFX"/>
+                <enum name="GL_SAMPLES_3DFX"/>
+                <enum name="GL_MULTISAMPLE_BIT_3DFX"/>
+            </require>
+        </extension>
+        <extension name="GL_3DFX_tbuffer" supported="gl">
+            <require>
+                <command name="glTbufferMask3DFX"/>
+            </require>
+        </extension>
+        <extension name="GL_3DFX_texture_compression_FXT1" supported="gl">
+            <require>
+                <enum name="GL_COMPRESSED_RGB_FXT1_3DFX"/>
+                <enum name="GL_COMPRESSED_RGBA_FXT1_3DFX"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_blend_minmax_factor" supported="gl">
+            <require>
+                <enum name="GL_FACTOR_MIN_AMD"/>
+                <enum name="GL_FACTOR_MAX_AMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_compressed_3DC_texture" supported="gles1|gles2">
+            <require>
+                <enum name="GL_3DC_X_AMD"/>
+                <enum name="GL_3DC_XY_AMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_compressed_ATC_texture" supported="gles1|gles2">
+            <require>
+                <enum name="GL_ATC_RGB_AMD"/>
+                <enum name="GL_ATC_RGBA_EXPLICIT_ALPHA_AMD"/>
+                <enum name="GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_conservative_depth" supported="gl"/>
+        <extension name="GL_AMD_debug_output" supported="gl">
+            <require>
+                <enum name="GL_MAX_DEBUG_MESSAGE_LENGTH_AMD"/>
+                <enum name="GL_MAX_DEBUG_LOGGED_MESSAGES_AMD"/>
+                <enum name="GL_DEBUG_LOGGED_MESSAGES_AMD"/>
+                <enum name="GL_DEBUG_SEVERITY_HIGH_AMD"/>
+                <enum name="GL_DEBUG_SEVERITY_MEDIUM_AMD"/>
+                <enum name="GL_DEBUG_SEVERITY_LOW_AMD"/>
+                <enum name="GL_DEBUG_CATEGORY_API_ERROR_AMD"/>
+                <enum name="GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD"/>
+                <enum name="GL_DEBUG_CATEGORY_DEPRECATION_AMD"/>
+                <enum name="GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD"/>
+                <enum name="GL_DEBUG_CATEGORY_PERFORMANCE_AMD"/>
+                <enum name="GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD"/>
+                <enum name="GL_DEBUG_CATEGORY_APPLICATION_AMD"/>
+                <enum name="GL_DEBUG_CATEGORY_OTHER_AMD"/>
+                <command name="glDebugMessageEnableAMD"/>
+                <command name="glDebugMessageInsertAMD"/>
+                <command name="glDebugMessageCallbackAMD"/>
+                <command name="glGetDebugMessageLogAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_depth_clamp_separate" supported="gl">
+            <require>
+                <enum name="GL_DEPTH_CLAMP_NEAR_AMD"/>
+                <enum name="GL_DEPTH_CLAMP_FAR_AMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_draw_buffers_blend" supported="gl">
+            <require>
+                <command name="glBlendFuncIndexedAMD"/>
+                <command name="glBlendFuncSeparateIndexedAMD"/>
+                <command name="glBlendEquationIndexedAMD"/>
+                <command name="glBlendEquationSeparateIndexedAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_framebuffer_sample_positions" supported="disabled">
+            <require>
+                <enum name="GL_SUBSAMPLE_DISTANCE_AMD"/>
+                <enum name="GL_PIXELS_PER_SAMPLE_PATTERN_X_AMD"/>
+                <enum name="GL_PIXELS_PER_SAMPLE_PATTERN_Y_AMD"/>
+                <enum name="GL_ALL_PIXELS_AMD"/>
+                <command name="glFramebufferSamplePositionsfvAMD"/>
+                <command name="glNamedFramebufferSamplePositionsfvAMD"/>
+                <command name="glGetFramebufferParameterfvAMD"/>
+                <command name="glGetNamedFramebufferParameterfvAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_gcn_shader" supported="gl"/>
+        <extension name="GL_AMD_gpu_shader_half_float" supported="gl">
+            <require>
+                <enum name="GL_FLOAT16_NV"/>
+                <enum name="GL_FLOAT16_VEC2_NV"/>
+                <enum name="GL_FLOAT16_VEC3_NV"/>
+                <enum name="GL_FLOAT16_VEC4_NV"/>
+                <enum name="GL_FLOAT16_MAT2_AMD"/>
+                <enum name="GL_FLOAT16_MAT3_AMD"/>
+                <enum name="GL_FLOAT16_MAT4_AMD"/>
+                <enum name="GL_FLOAT16_MAT2x3_AMD"/>
+                <enum name="GL_FLOAT16_MAT2x4_AMD"/>
+                <enum name="GL_FLOAT16_MAT3x2_AMD"/>
+                <enum name="GL_FLOAT16_MAT3x4_AMD"/>
+                <enum name="GL_FLOAT16_MAT4x2_AMD"/>
+                <enum name="GL_FLOAT16_MAT4x3_AMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_gpu_shader_int64" supported="gl">
+            <require>
+                <enum name="GL_INT64_NV"/>
+                <enum name="GL_UNSIGNED_INT64_NV"/>
+                <enum name="GL_INT8_NV"/>
+                <enum name="GL_INT8_VEC2_NV"/>
+                <enum name="GL_INT8_VEC3_NV"/>
+                <enum name="GL_INT8_VEC4_NV"/>
+                <enum name="GL_INT16_NV"/>
+                <enum name="GL_INT16_VEC2_NV"/>
+                <enum name="GL_INT16_VEC3_NV"/>
+                <enum name="GL_INT16_VEC4_NV"/>
+                <enum name="GL_INT64_VEC2_NV"/>
+                <enum name="GL_INT64_VEC3_NV"/>
+                <enum name="GL_INT64_VEC4_NV"/>
+                <enum name="GL_UNSIGNED_INT8_NV"/>
+                <enum name="GL_UNSIGNED_INT8_VEC2_NV"/>
+                <enum name="GL_UNSIGNED_INT8_VEC3_NV"/>
+                <enum name="GL_UNSIGNED_INT8_VEC4_NV"/>
+                <enum name="GL_UNSIGNED_INT16_NV"/>
+                <enum name="GL_UNSIGNED_INT16_VEC2_NV"/>
+                <enum name="GL_UNSIGNED_INT16_VEC3_NV"/>
+                <enum name="GL_UNSIGNED_INT16_VEC4_NV"/>
+                <enum name="GL_UNSIGNED_INT64_VEC2_NV"/>
+                <enum name="GL_UNSIGNED_INT64_VEC3_NV"/>
+                <enum name="GL_UNSIGNED_INT64_VEC4_NV"/>
+                <enum name="GL_FLOAT16_NV"/>
+                <enum name="GL_FLOAT16_VEC2_NV"/>
+                <enum name="GL_FLOAT16_VEC3_NV"/>
+                <enum name="GL_FLOAT16_VEC4_NV"/>
+                <command name="glUniform1i64NV"/>
+                <command name="glUniform2i64NV"/>
+                <command name="glUniform3i64NV"/>
+                <command name="glUniform4i64NV"/>
+                <command name="glUniform1i64vNV"/>
+                <command name="glUniform2i64vNV"/>
+                <command name="glUniform3i64vNV"/>
+                <command name="glUniform4i64vNV"/>
+                <command name="glUniform1ui64NV"/>
+                <command name="glUniform2ui64NV"/>
+                <command name="glUniform3ui64NV"/>
+                <command name="glUniform4ui64NV"/>
+                <command name="glUniform1ui64vNV"/>
+                <command name="glUniform2ui64vNV"/>
+                <command name="glUniform3ui64vNV"/>
+                <command name="glUniform4ui64vNV"/>
+                <command name="glGetUniformi64vNV"/>
+                <command name="glGetUniformui64vNV"/>
+            </require>
+            <require comment="Supported only if GL_EXT_direct_state_access is supported">
+                <command name="glProgramUniform1i64NV"/>
+                <command name="glProgramUniform2i64NV"/>
+                <command name="glProgramUniform3i64NV"/>
+                <command name="glProgramUniform4i64NV"/>
+                <command name="glProgramUniform1i64vNV"/>
+                <command name="glProgramUniform2i64vNV"/>
+                <command name="glProgramUniform3i64vNV"/>
+                <command name="glProgramUniform4i64vNV"/>
+                <command name="glProgramUniform1ui64NV"/>
+                <command name="glProgramUniform2ui64NV"/>
+                <command name="glProgramUniform3ui64NV"/>
+                <command name="glProgramUniform4ui64NV"/>
+                <command name="glProgramUniform1ui64vNV"/>
+                <command name="glProgramUniform2ui64vNV"/>
+                <command name="glProgramUniform3ui64vNV"/>
+                <command name="glProgramUniform4ui64vNV"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_interleaved_elements" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ELEMENT_SWIZZLE_AMD"/>
+                <enum name="GL_VERTEX_ID_SWIZZLE_AMD"/>
+                <enum name="GL_RED"/>
+                <enum name="GL_GREEN"/>
+                <enum name="GL_BLUE"/>
+                <enum name="GL_ALPHA"/>
+                <enum name="GL_RG8UI"/>
+                <enum name="GL_RG16UI"/>
+                <enum name="GL_RGBA8UI"/>
+                <command name="glVertexAttribParameteriAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_multi_draw_indirect" supported="gl">
+            <require>
+                <command name="glMultiDrawArraysIndirectAMD"/>
+                <command name="glMultiDrawElementsIndirectAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_name_gen_delete" supported="gl">
+            <require>
+                <enum name="GL_DATA_BUFFER_AMD"/>
+                <enum name="GL_PERFORMANCE_MONITOR_AMD"/>
+                <enum name="GL_QUERY_OBJECT_AMD"/>
+                <enum name="GL_VERTEX_ARRAY_OBJECT_AMD"/>
+                <enum name="GL_SAMPLER_OBJECT_AMD"/>
+                <command name="glGenNamesAMD"/>
+                <command name="glDeleteNamesAMD"/>
+                <command name="glIsNameAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_occlusion_query_event" supported="gl">
+            <require>
+                <enum name="GL_OCCLUSION_QUERY_EVENT_MASK_AMD"/>
+                <enum name="GL_QUERY_DEPTH_PASS_EVENT_BIT_AMD"/>
+                <enum name="GL_QUERY_DEPTH_FAIL_EVENT_BIT_AMD"/>
+                <enum name="GL_QUERY_STENCIL_FAIL_EVENT_BIT_AMD"/>
+                <enum name="GL_QUERY_DEPTH_BOUNDS_FAIL_EVENT_BIT_AMD"/>
+                <enum name="GL_QUERY_ALL_EVENT_BITS_AMD"/>
+                <command name="glQueryObjectParameteruiAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_performance_monitor" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_COUNTER_TYPE_AMD"/>
+                <enum name="GL_COUNTER_RANGE_AMD"/>
+                <enum name="GL_UNSIGNED_INT64_AMD"/>
+                <enum name="GL_PERCENTAGE_AMD"/>
+                <enum name="GL_PERFMON_RESULT_AVAILABLE_AMD"/>
+                <enum name="GL_PERFMON_RESULT_SIZE_AMD"/>
+                <enum name="GL_PERFMON_RESULT_AMD"/>
+                <command name="glGetPerfMonitorGroupsAMD"/>
+                <command name="glGetPerfMonitorCountersAMD"/>
+                <command name="glGetPerfMonitorGroupStringAMD"/>
+                <command name="glGetPerfMonitorCounterStringAMD"/>
+                <command name="glGetPerfMonitorCounterInfoAMD"/>
+                <command name="glGenPerfMonitorsAMD"/>
+                <command name="glDeletePerfMonitorsAMD"/>
+                <command name="glSelectPerfMonitorCountersAMD"/>
+                <command name="glBeginPerfMonitorAMD"/>
+                <command name="glEndPerfMonitorAMD"/>
+                <command name="glGetPerfMonitorCounterDataAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_pinned_memory" supported="gl">
+            <require>
+                <enum name="GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_program_binary_Z400" supported="gles2">
+            <require>
+                <enum name="GL_Z400_BINARY_AMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_query_buffer_object" supported="gl">
+            <require>
+                <enum name="GL_QUERY_BUFFER_AMD"/>
+                <enum name="GL_QUERY_BUFFER_BINDING_AMD"/>
+                <enum name="GL_QUERY_RESULT_NO_WAIT_AMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_sample_positions" supported="gl">
+            <require>
+                <enum name="GL_SUBSAMPLE_DISTANCE_AMD"/>
+                <command name="glSetMultisamplefvAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_seamless_cubemap_per_texture" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_CUBE_MAP_SEAMLESS"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_shader_atomic_counter_ops" supported="gl"/>
+        <extension name="GL_AMD_shader_ballot" supported="gl"/>
+        <extension name="GL_AMD_shader_stencil_export" supported="gl"/>
+        <extension name="GL_AMD_shader_trinary_minmax" supported="gl"/>
+        <extension name="GL_AMD_shader_explicit_vertex_parameter" supported="gl"/>
+        <extension name="GL_AMD_sparse_texture" supported="gl">
+            <require>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_X_AMD"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_Y_AMD"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_Z_AMD"/>
+                <enum name="GL_MAX_SPARSE_TEXTURE_SIZE_AMD"/>
+                <enum name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD"/>
+                <enum name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS" comment="Should have an AMD suffix, but probably too late now"/>
+                <enum name="GL_MIN_SPARSE_LEVEL_AMD"/>
+                <enum name="GL_MIN_LOD_WARNING_AMD"/>
+                <enum name="GL_TEXTURE_STORAGE_SPARSE_BIT_AMD"/>
+                <command name="glTexStorageSparseAMD"/>
+                <command name="glTextureStorageSparseAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_stencil_operation_extended" supported="gl">
+            <require>
+                <enum name="GL_SET_AMD"/>
+                <enum name="GL_REPLACE_VALUE_AMD"/>
+                <enum name="GL_STENCIL_OP_VALUE_AMD"/>
+                <enum name="GL_STENCIL_BACK_OP_VALUE_AMD"/>
+                <command name="glStencilOpValueAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_texture_texture4" supported="gl"/>
+        <extension name="GL_AMD_transform_feedback3_lines_triangles" supported="gl"/>
+        <extension name="GL_AMD_transform_feedback4" supported="gl">
+            <require>
+                <enum name="GL_STREAM_RASTERIZATION_AMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_vertex_shader_layer" supported="gl"/>
+        <extension name="GL_AMD_vertex_shader_tessellator" supported="gl">
+            <require>
+                <enum name="GL_SAMPLER_BUFFER_AMD"/>
+                <enum name="GL_INT_SAMPLER_BUFFER_AMD"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD"/>
+                <enum name="GL_TESSELLATION_MODE_AMD"/>
+                <enum name="GL_TESSELLATION_FACTOR_AMD"/>
+                <enum name="GL_DISCRETE_AMD"/>
+                <enum name="GL_CONTINUOUS_AMD"/>
+                <command name="glTessellationFactorAMD"/>
+                <command name="glTessellationModeAMD"/>
+            </require>
+        </extension>
+        <extension name="GL_AMD_vertex_shader_viewport_index" supported="gl"/>
+        <extension name="GL_ANDROID_extension_pack_es31a" supported="gles2">
+            <require comment="This is an alias for the following extensions. At present gl.xml doesn't actually replicate all their interfaces here.">
+                <!--
+                    KHR_debug
+                    KHR_texture_compression_astc_ldr
+                    KHR_blend_equation_advanced
+                    OES_sample_shading
+                    OES_sample_variables
+                    OES_shader_image_atomic
+                    OES_shader_multisample_interpolation
+                    OES_texture_stencil8
+                    OES_texture_storage_multisample_2d_array
+                    EXT_copy_image
+                    EXT_draw_buffers_indexed
+                    EXT_geometry_shader
+                    EXT_gpu_shader5
+                    EXT_primitive_bounding_box
+                    EXT_shader_io_blocks
+                    EXT_tessellation_shader
+                    EXT_texture_border_clamp
+                    EXT_texture_buffer
+                    EXT_texture_cube_map_array
+                    EXT_texture_srgb_decode
+                -->
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_depth_texture" supported="gles2">
+            <require>
+                <enum name="GL_DEPTH_COMPONENT"/>
+                <enum name="GL_DEPTH_STENCIL_OES"/>
+                <enum name="GL_UNSIGNED_SHORT"/>
+                <enum name="GL_UNSIGNED_INT"/>
+                <enum name="GL_UNSIGNED_INT_24_8_OES"/>
+                <enum name="GL_DEPTH_COMPONENT16"/>
+                <enum name="GL_DEPTH_COMPONENT32_OES"/>
+                <enum name="GL_DEPTH24_STENCIL8_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_framebuffer_blit" supported="gles2">
+            <require>
+                <enum name="GL_READ_FRAMEBUFFER_ANGLE"/>
+                <enum name="GL_DRAW_FRAMEBUFFER_ANGLE"/>
+                <enum name="GL_DRAW_FRAMEBUFFER_BINDING_ANGLE"/>
+                <enum name="GL_READ_FRAMEBUFFER_BINDING_ANGLE"/>
+                <command name="glBlitFramebufferANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_framebuffer_multisample" supported="gles2">
+            <require>
+                <enum name="GL_RENDERBUFFER_SAMPLES_ANGLE"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE"/>
+                <enum name="GL_MAX_SAMPLES_ANGLE"/>
+                <command name="glRenderbufferStorageMultisampleANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_instanced_arrays" supported="gles2">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE"/>
+                <command name="glDrawArraysInstancedANGLE"/>
+                <command name="glDrawElementsInstancedANGLE"/>
+                <command name="glVertexAttribDivisorANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_pack_reverse_row_order" supported="gles2">
+            <require>
+                <enum name="GL_PACK_REVERSE_ROW_ORDER_ANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_program_binary" supported="gles2">
+            <require>
+                <enum name="GL_PROGRAM_BINARY_ANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_texture_compression_dxt3" supported="gles2">
+            <require>
+                <enum name="GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_texture_compression_dxt5" supported="gles2">
+            <require>
+                <enum name="GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_texture_usage" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_USAGE_ANGLE"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_ANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_translated_shader_source" supported="gles2">
+            <require>
+                <enum name="GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE"/>
+                <command name="glGetTranslatedShaderSourceANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_aux_depth_stencil" supported="gl">
+            <require>
+                <enum name="GL_AUX_DEPTH_STENCIL_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_client_storage" supported="gl">
+            <require>
+                <enum name="GL_UNPACK_CLIENT_STORAGE_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_clip_distance" supported="gles2">
+            <require>
+                <enum name="GL_MAX_CLIP_DISTANCES_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE0_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE1_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE2_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE3_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE4_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE5_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE6_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE7_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_color_buffer_packed_float" supported="gles2"/>
+        <extension name="GL_APPLE_copy_texture_levels" supported="gles1|gles2">
+            <require>
+                <command name="glCopyTextureLevelsAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_element_array" supported="gl">
+            <require>
+                <enum name="GL_ELEMENT_ARRAY_APPLE"/>
+                <enum name="GL_ELEMENT_ARRAY_TYPE_APPLE"/>
+                <enum name="GL_ELEMENT_ARRAY_POINTER_APPLE"/>
+                <command name="glElementPointerAPPLE"/>
+                <command name="glDrawElementArrayAPPLE"/>
+                <command name="glDrawRangeElementArrayAPPLE"/>
+                <command name="glMultiDrawElementArrayAPPLE"/>
+                <command name="glMultiDrawRangeElementArrayAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_fence" supported="gl">
+            <require>
+                <enum name="GL_DRAW_PIXELS_APPLE"/>
+                <enum name="GL_FENCE_APPLE"/>
+                <command name="glGenFencesAPPLE"/>
+                <command name="glDeleteFencesAPPLE"/>
+                <command name="glSetFenceAPPLE"/>
+                <command name="glIsFenceAPPLE"/>
+                <command name="glTestFenceAPPLE"/>
+                <command name="glFinishFenceAPPLE"/>
+                <command name="glTestObjectAPPLE"/>
+                <command name="glFinishObjectAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_float_pixels" supported="gl">
+            <require>
+                <enum name="GL_HALF_APPLE"/>
+                <enum name="GL_RGBA_FLOAT32_APPLE"/>
+                <enum name="GL_RGB_FLOAT32_APPLE"/>
+                <enum name="GL_ALPHA_FLOAT32_APPLE"/>
+                <enum name="GL_INTENSITY_FLOAT32_APPLE"/>
+                <enum name="GL_LUMINANCE_FLOAT32_APPLE"/>
+                <enum name="GL_LUMINANCE_ALPHA_FLOAT32_APPLE"/>
+                <enum name="GL_RGBA_FLOAT16_APPLE"/>
+                <enum name="GL_RGB_FLOAT16_APPLE"/>
+                <enum name="GL_ALPHA_FLOAT16_APPLE"/>
+                <enum name="GL_INTENSITY_FLOAT16_APPLE"/>
+                <enum name="GL_LUMINANCE_FLOAT16_APPLE"/>
+                <enum name="GL_LUMINANCE_ALPHA_FLOAT16_APPLE"/>
+                <enum name="GL_COLOR_FLOAT_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_flush_buffer_range" supported="gl">
+            <require>
+                <enum name="GL_BUFFER_SERIALIZED_MODIFY_APPLE"/>
+                <enum name="GL_BUFFER_FLUSHING_UNMAP_APPLE"/>
+                <command name="glBufferParameteriAPPLE"/>
+                <command name="glFlushMappedBufferRangeAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_framebuffer_multisample" supported="gles1|gles2">
+            <require>
+                <enum name="GL_RENDERBUFFER_SAMPLES_APPLE"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE"/>
+                <enum name="GL_MAX_SAMPLES_APPLE"/>
+                <enum name="GL_READ_FRAMEBUFFER_APPLE"/>
+                <enum name="GL_DRAW_FRAMEBUFFER_APPLE"/>
+                <enum name="GL_DRAW_FRAMEBUFFER_BINDING_APPLE"/>
+                <enum name="GL_READ_FRAMEBUFFER_BINDING_APPLE"/>
+                <command name="glRenderbufferStorageMultisampleAPPLE"/>
+                <command name="glResolveMultisampleFramebufferAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_object_purgeable" supported="gl">
+            <require>
+                <enum name="GL_BUFFER_OBJECT_APPLE"/>
+                <enum name="GL_RELEASED_APPLE"/>
+                <enum name="GL_VOLATILE_APPLE"/>
+                <enum name="GL_RETAINED_APPLE"/>
+                <enum name="GL_UNDEFINED_APPLE"/>
+                <enum name="GL_PURGEABLE_APPLE"/>
+                <command name="glObjectPurgeableAPPLE"/>
+                <command name="glObjectUnpurgeableAPPLE"/>
+                <command name="glGetObjectParameterivAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_rgb_422" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_RGB_422_APPLE"/>
+                <enum name="GL_UNSIGNED_SHORT_8_8_APPLE"/>
+                <enum name="GL_UNSIGNED_SHORT_8_8_REV_APPLE"/>
+            </require>
+            <require comment="Depends on TexStorage* (EXT_texture_storage / ES 3.0 / GL 4.4 / etc.)">
+                <enum name="GL_RGB_RAW_422_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_row_bytes" supported="gl">
+            <require>
+                <enum name="GL_PACK_ROW_BYTES_APPLE"/>
+                <enum name="GL_UNPACK_ROW_BYTES_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_specular_vector" supported="gl">
+            <require>
+                <enum name="GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_sync" supported="gles1|gles2">
+            <require>
+                <enum name="GL_SYNC_OBJECT_APPLE"/>
+                <enum name="GL_MAX_SERVER_WAIT_TIMEOUT_APPLE"/>
+                <enum name="GL_OBJECT_TYPE_APPLE"/>
+                <enum name="GL_SYNC_CONDITION_APPLE"/>
+                <enum name="GL_SYNC_STATUS_APPLE"/>
+                <enum name="GL_SYNC_FLAGS_APPLE"/>
+                <enum name="GL_SYNC_FENCE_APPLE"/>
+                <enum name="GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE"/>
+                <enum name="GL_UNSIGNALED_APPLE"/>
+                <enum name="GL_SIGNALED_APPLE"/>
+                <enum name="GL_ALREADY_SIGNALED_APPLE"/>
+                <enum name="GL_TIMEOUT_EXPIRED_APPLE"/>
+                <enum name="GL_CONDITION_SATISFIED_APPLE"/>
+                <enum name="GL_WAIT_FAILED_APPLE"/>
+                <enum name="GL_SYNC_FLUSH_COMMANDS_BIT_APPLE"/>
+                <enum name="GL_TIMEOUT_IGNORED_APPLE"/>
+                <command name="glFenceSyncAPPLE"/>
+                <command name="glIsSyncAPPLE"/>
+                <command name="glDeleteSyncAPPLE"/>
+                <command name="glClientWaitSyncAPPLE"/>
+                <command name="glWaitSyncAPPLE"/>
+                <command name="glGetInteger64vAPPLE"/>
+                <command name="glGetSyncivAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_texture_2D_limited_npot" supported="gles1"/>
+        <extension name="GL_APPLE_texture_format_BGRA8888" supported="gles1|gles2">
+            <require>
+                <enum name="GL_BGRA_EXT"/>
+            </require>
+            <require comment="Depends on TexStorage* (EXT_texture_storage / ES 3.0 / GL 4.4 / etc.)">
+                <enum name="GL_BGRA8_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_texture_max_level" supported="gles1|gles2">
+            <require>
+                <enum name="GL_TEXTURE_MAX_LEVEL_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_texture_packed_float" supported="gles2">
+            <require>
+                <enum name="GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE"/>
+                <enum name="GL_UNSIGNED_INT_5_9_9_9_REV_APPLE"/>
+                <enum name="GL_R11F_G11F_B10F_APPLE"/>
+                <enum name="GL_RGB9_E5_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_texture_range" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_RANGE_LENGTH_APPLE"/>
+                <enum name="GL_TEXTURE_RANGE_POINTER_APPLE"/>
+                <enum name="GL_TEXTURE_STORAGE_HINT_APPLE"/>
+                <enum name="GL_STORAGE_PRIVATE_APPLE"/>
+                <enum name="GL_STORAGE_CACHED_APPLE"/>
+                <enum name="GL_STORAGE_SHARED_APPLE"/>
+                <command name="glTextureRangeAPPLE"/>
+                <command name="glGetTexParameterPointervAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_transform_hint" supported="gl">
+            <require>
+                <enum name="GL_TRANSFORM_HINT_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_vertex_array_object" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ARRAY_BINDING_APPLE"/>
+                <command name="glBindVertexArrayAPPLE"/>
+                <command name="glDeleteVertexArraysAPPLE"/>
+                <command name="glGenVertexArraysAPPLE"/>
+                <command name="glIsVertexArrayAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_vertex_array_range" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ARRAY_RANGE_APPLE"/>
+                <enum name="GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE"/>
+                <enum name="GL_VERTEX_ARRAY_STORAGE_HINT_APPLE"/>
+                <enum name="GL_VERTEX_ARRAY_RANGE_POINTER_APPLE"/>
+                <enum name="GL_STORAGE_CLIENT_APPLE"/>
+                <enum name="GL_STORAGE_CACHED_APPLE"/>
+                <enum name="GL_STORAGE_SHARED_APPLE"/>
+                <command name="glVertexArrayRangeAPPLE"/>
+                <command name="glFlushVertexArrayRangeAPPLE"/>
+                <command name="glVertexArrayParameteriAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_vertex_program_evaluators" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_MAP1_APPLE"/>
+                <enum name="GL_VERTEX_ATTRIB_MAP2_APPLE"/>
+                <enum name="GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE"/>
+                <enum name="GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE"/>
+                <enum name="GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE"/>
+                <enum name="GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE"/>
+                <enum name="GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE"/>
+                <enum name="GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE"/>
+                <enum name="GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE"/>
+                <enum name="GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE"/>
+                <command name="glEnableVertexAttribAPPLE"/>
+                <command name="glDisableVertexAttribAPPLE"/>
+                <command name="glIsVertexAttribEnabledAPPLE"/>
+                <command name="glMapVertexAttrib1dAPPLE"/>
+                <command name="glMapVertexAttrib1fAPPLE"/>
+                <command name="glMapVertexAttrib2dAPPLE"/>
+                <command name="glMapVertexAttrib2fAPPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_ycbcr_422" supported="gl">
+            <require>
+                <enum name="GL_YCBCR_422_APPLE"/>
+                <enum name="GL_UNSIGNED_SHORT_8_8_APPLE"/>
+                <enum name="GL_UNSIGNED_SHORT_8_8_REV_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_ES2_compatibility" supported="gl|glcore">
+            <require>
+                <enum name="GL_FIXED"/>
+                <enum name="GL_IMPLEMENTATION_COLOR_READ_TYPE"/>
+                <enum name="GL_IMPLEMENTATION_COLOR_READ_FORMAT"/>
+                <enum name="GL_LOW_FLOAT"/>
+                <enum name="GL_MEDIUM_FLOAT"/>
+                <enum name="GL_HIGH_FLOAT"/>
+                <enum name="GL_LOW_INT"/>
+                <enum name="GL_MEDIUM_INT"/>
+                <enum name="GL_HIGH_INT"/>
+                <enum name="GL_SHADER_COMPILER"/>
+                <enum name="GL_SHADER_BINARY_FORMATS"/>
+                <enum name="GL_NUM_SHADER_BINARY_FORMATS"/>
+                <enum name="GL_MAX_VERTEX_UNIFORM_VECTORS"/>
+                <enum name="GL_MAX_VARYING_VECTORS"/>
+                <enum name="GL_MAX_FRAGMENT_UNIFORM_VECTORS"/>
+                <enum name="GL_RGB565"/>
+                <command name="glReleaseShaderCompiler"/>
+                <command name="glShaderBinary"/>
+                <command name="glGetShaderPrecisionFormat"/>
+                <command name="glDepthRangef"/>
+                <command name="glClearDepthf"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_ES3_1_compatibility" supported="gl|glcore">
+            <require>
+                <enum name="GL_BACK"/>
+                <command name="glMemoryBarrierByRegion"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_ES3_2_compatibility" supported="gl">
+            <require>
+                <enum name="GL_PRIMITIVE_BOUNDING_BOX_ARB"/>
+                <enum name="GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB"/>
+                <enum name="GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB"/>
+                <command name="glPrimitiveBoundingBoxARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_ES3_compatibility" supported="gl|glcore">
+            <require>
+                <enum name="GL_COMPRESSED_RGB8_ETC2"/>
+                <enum name="GL_COMPRESSED_SRGB8_ETC2"/>
+                <enum name="GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"/>
+                <enum name="GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"/>
+                <enum name="GL_COMPRESSED_RGBA8_ETC2_EAC"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"/>
+                <enum name="GL_COMPRESSED_R11_EAC"/>
+                <enum name="GL_COMPRESSED_SIGNED_R11_EAC"/>
+                <enum name="GL_COMPRESSED_RG11_EAC"/>
+                <enum name="GL_COMPRESSED_SIGNED_RG11_EAC"/>
+                <enum name="GL_PRIMITIVE_RESTART_FIXED_INDEX"/>
+                <enum name="GL_ANY_SAMPLES_PASSED_CONSERVATIVE"/>
+                <enum name="GL_MAX_ELEMENT_INDEX"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_arrays_of_arrays" supported="gl|glcore"/>
+        <extension name="GL_ARB_base_instance" supported="gl|glcore">
+            <require>
+                <command name="glDrawArraysInstancedBaseInstance"/>
+                <command name="glDrawElementsInstancedBaseInstance"/>
+                <command name="glDrawElementsInstancedBaseVertexBaseInstance"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_bindless_texture" supported="gl|glcore">
+            <require>
+                <enum name="GL_UNSIGNED_INT64_ARB"/>
+                <command name="glGetTextureHandleARB"/>
+                <command name="glGetTextureSamplerHandleARB"/>
+                <command name="glMakeTextureHandleResidentARB"/>
+                <command name="glMakeTextureHandleNonResidentARB"/>
+                <command name="glGetImageHandleARB"/>
+                <command name="glMakeImageHandleResidentARB"/>
+                <command name="glMakeImageHandleNonResidentARB"/>
+                <command name="glUniformHandleui64ARB"/>
+                <command name="glUniformHandleui64vARB"/>
+                <command name="glProgramUniformHandleui64ARB"/>
+                <command name="glProgramUniformHandleui64vARB"/>
+                <command name="glIsTextureHandleResidentARB"/>
+                <command name="glIsImageHandleResidentARB"/>
+                <command name="glVertexAttribL1ui64ARB"/>
+                <command name="glVertexAttribL1ui64vARB"/>
+                <command name="glGetVertexAttribLui64vARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_blend_func_extended" supported="gl|glcore">
+            <require>
+                <enum name="GL_SRC1_COLOR"/>
+                <enum name="GL_SRC1_ALPHA"/>
+                <enum name="GL_ONE_MINUS_SRC1_COLOR"/>
+                <enum name="GL_ONE_MINUS_SRC1_ALPHA"/>
+                <enum name="GL_MAX_DUAL_SOURCE_DRAW_BUFFERS"/>
+                <command name="glBindFragDataLocationIndexed"/>
+                <command name="glGetFragDataIndex"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_buffer_storage" supported="gl|glcore">
+            <require>
+                <enum name="GL_MAP_READ_BIT"/>
+                <enum name="GL_MAP_WRITE_BIT"/>
+                <enum name="GL_MAP_PERSISTENT_BIT"/>
+                <enum name="GL_MAP_COHERENT_BIT"/>
+                <enum name="GL_DYNAMIC_STORAGE_BIT"/>
+                <enum name="GL_CLIENT_STORAGE_BIT"/>
+                <enum name="GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT"/>
+                <enum name="GL_BUFFER_IMMUTABLE_STORAGE"/>
+                <enum name="GL_BUFFER_STORAGE_FLAGS"/>
+                <command name="glBufferStorage"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_cl_event" supported="gl|glcore">
+            <require>
+                <enum name="GL_SYNC_CL_EVENT_ARB"/>
+                <enum name="GL_SYNC_CL_EVENT_COMPLETE_ARB"/>
+                <command name="glCreateSyncFromCLeventARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_clear_buffer_object" supported="gl|glcore">
+            <require>
+                <command name="glClearBufferData"/>
+                <command name="glClearBufferSubData"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_clear_texture" supported="gl|glcore">
+            <require>
+                <enum name="GL_CLEAR_TEXTURE"/>
+                <command name="glClearTexImage"/>
+                <command name="glClearTexSubImage"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_clip_control" supported="gl|glcore">
+            <require>
+                <command name="glClipControl"/>
+                <enum name="GL_LOWER_LEFT"/>
+                <enum name="GL_UPPER_LEFT"/>
+                <enum name="GL_NEGATIVE_ONE_TO_ONE"/>
+                <enum name="GL_ZERO_TO_ONE"/>
+                <enum name="GL_CLIP_ORIGIN"/>
+                <enum name="GL_CLIP_DEPTH_MODE"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_color_buffer_float" supported="gl">
+            <require>
+                <enum name="GL_RGBA_FLOAT_MODE_ARB"/>
+                <enum name="GL_CLAMP_VERTEX_COLOR_ARB"/>
+                <enum name="GL_CLAMP_FRAGMENT_COLOR_ARB"/>
+                <enum name="GL_CLAMP_READ_COLOR_ARB"/>
+                <enum name="GL_FIXED_ONLY_ARB"/>
+                <command name="glClampColorARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_compatibility" supported="gl">
+            <require comment="Defines features from OpenGL 3.0 that were removed in OpenGL 3.1 - not enumerated here yet">
+            </require>
+        </extension>
+        <extension name="GL_ARB_compressed_texture_pixel_storage" supported="gl|glcore">
+            <require>
+                <enum name="GL_UNPACK_COMPRESSED_BLOCK_WIDTH"/>
+                <enum name="GL_UNPACK_COMPRESSED_BLOCK_HEIGHT"/>
+                <enum name="GL_UNPACK_COMPRESSED_BLOCK_DEPTH"/>
+                <enum name="GL_UNPACK_COMPRESSED_BLOCK_SIZE"/>
+                <enum name="GL_PACK_COMPRESSED_BLOCK_WIDTH"/>
+                <enum name="GL_PACK_COMPRESSED_BLOCK_HEIGHT"/>
+                <enum name="GL_PACK_COMPRESSED_BLOCK_DEPTH"/>
+                <enum name="GL_PACK_COMPRESSED_BLOCK_SIZE"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_compute_shader" supported="gl|glcore">
+            <require>
+                <enum name="GL_COMPUTE_SHADER"/>
+                <enum name="GL_MAX_COMPUTE_UNIFORM_BLOCKS"/>
+                <enum name="GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"/>
+                <enum name="GL_MAX_COMPUTE_IMAGE_UNIFORMS"/>
+                <enum name="GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"/>
+                <enum name="GL_MAX_COMPUTE_UNIFORM_COMPONENTS"/>
+                <enum name="GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"/>
+                <enum name="GL_MAX_COMPUTE_ATOMIC_COUNTERS"/>
+                <enum name="GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS"/>
+                <enum name="GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS"/>
+                <enum name="GL_MAX_COMPUTE_WORK_GROUP_COUNT"/>
+                <enum name="GL_MAX_COMPUTE_WORK_GROUP_SIZE"/>
+                <enum name="GL_COMPUTE_WORK_GROUP_SIZE"/>
+                <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER"/>
+                <enum name="GL_DISPATCH_INDIRECT_BUFFER"/>
+                <enum name="GL_DISPATCH_INDIRECT_BUFFER_BINDING"/>
+                <enum name="GL_COMPUTE_SHADER_BIT"/>
+                <command name="glDispatchCompute"/>
+                <command name="glDispatchComputeIndirect"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_compute_variable_group_size" supported="gl|glcore">
+            <require>
+                <enum name="GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB"/>
+                <enum name="GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB"/>
+                <enum name="GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB"/>
+                <enum name="GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB"/>
+                <command name="glDispatchComputeGroupSizeARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_conditional_render_inverted" supported="gl|glcore">
+            <require>
+                <enum name="GL_QUERY_WAIT_INVERTED"/>
+                <enum name="GL_QUERY_NO_WAIT_INVERTED"/>
+                <enum name="GL_QUERY_BY_REGION_WAIT_INVERTED"/>
+                <enum name="GL_QUERY_BY_REGION_NO_WAIT_INVERTED"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_conservative_depth" supported="gl|glcore"/>
+        <extension name="GL_ARB_copy_buffer" supported="gl|glcore">
+            <require>
+                <enum name="GL_COPY_READ_BUFFER"/>
+                <enum name="GL_COPY_WRITE_BUFFER"/>
+                <command name="glCopyBufferSubData"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_copy_image" supported="gl|glcore">
+            <require>
+                <command name="glCopyImageSubData"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_cull_distance" supported="gl|glcore">
+            <require>
+                <enum name="GL_MAX_CULL_DISTANCES"/>
+                <enum name="GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_debug_output" supported="gl|glcore">
+            <require>
+                <enum name="GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB"/>
+                <enum name="GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB"/>
+                <enum name="GL_DEBUG_CALLBACK_FUNCTION_ARB"/>
+                <enum name="GL_DEBUG_CALLBACK_USER_PARAM_ARB"/>
+                <enum name="GL_DEBUG_SOURCE_API_ARB"/>
+                <enum name="GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB"/>
+                <enum name="GL_DEBUG_SOURCE_SHADER_COMPILER_ARB"/>
+                <enum name="GL_DEBUG_SOURCE_THIRD_PARTY_ARB"/>
+                <enum name="GL_DEBUG_SOURCE_APPLICATION_ARB"/>
+                <enum name="GL_DEBUG_SOURCE_OTHER_ARB"/>
+                <enum name="GL_DEBUG_TYPE_ERROR_ARB"/>
+                <enum name="GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB"/>
+                <enum name="GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB"/>
+                <enum name="GL_DEBUG_TYPE_PORTABILITY_ARB"/>
+                <enum name="GL_DEBUG_TYPE_PERFORMANCE_ARB"/>
+                <enum name="GL_DEBUG_TYPE_OTHER_ARB"/>
+                <enum name="GL_MAX_DEBUG_MESSAGE_LENGTH_ARB"/>
+                <enum name="GL_MAX_DEBUG_LOGGED_MESSAGES_ARB"/>
+                <enum name="GL_DEBUG_LOGGED_MESSAGES_ARB"/>
+                <enum name="GL_DEBUG_SEVERITY_HIGH_ARB"/>
+                <enum name="GL_DEBUG_SEVERITY_MEDIUM_ARB"/>
+                <enum name="GL_DEBUG_SEVERITY_LOW_ARB"/>
+                <command name="glDebugMessageControlARB"/>
+                <command name="glDebugMessageInsertARB"/>
+                <command name="glDebugMessageCallbackARB"/>
+                <command name="glGetDebugMessageLogARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_depth_buffer_float" supported="gl|glcore">
+            <require>
+                <enum name="GL_DEPTH_COMPONENT32F"/>
+                <enum name="GL_DEPTH32F_STENCIL8"/>
+                <enum name="GL_FLOAT_32_UNSIGNED_INT_24_8_REV"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_depth_clamp" supported="gl|glcore">
+            <require>
+                <enum name="GL_DEPTH_CLAMP"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_depth_texture" supported="gl">
+            <require>
+                <enum name="GL_DEPTH_COMPONENT16_ARB"/>
+                <enum name="GL_DEPTH_COMPONENT24_ARB"/>
+                <enum name="GL_DEPTH_COMPONENT32_ARB"/>
+                <enum name="GL_TEXTURE_DEPTH_SIZE_ARB"/>
+                <enum name="GL_DEPTH_TEXTURE_MODE_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_derivative_control" supported="gl|glcore"/>
+        <extension name="GL_ARB_direct_state_access" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_TARGET"/>
+                <enum name="GL_QUERY_TARGET"/>
+                <enum name="GL_TEXTURE_BINDING_1D"/>
+                <enum name="GL_TEXTURE_BINDING_1D_ARRAY"/>
+                <enum name="GL_TEXTURE_BINDING_2D"/>
+                <enum name="GL_TEXTURE_BINDING_2D_ARRAY"/>
+                <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE"/>
+                <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_TEXTURE_BINDING_3D"/>
+                <enum name="GL_TEXTURE_BINDING_BUFFER"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"/>
+                <enum name="GL_TEXTURE_BINDING_RECTANGLE"/>
+            </require>
+            <require comment="Transform Feedback object functions">
+                <command name="glCreateTransformFeedbacks"/>
+                <command name="glTransformFeedbackBufferBase"/>
+                <command name="glTransformFeedbackBufferRange"/>
+                <command name="glGetTransformFeedbackiv"/>
+                <command name="glGetTransformFeedbacki_v"/>
+                <command name="glGetTransformFeedbacki64_v"/>
+            </require>
+            <require comment="Buffer object functions">
+                <command name="glCreateBuffers"/>
+                <command name="glNamedBufferStorage"/>
+                <command name="glNamedBufferData"/>
+                <command name="glNamedBufferSubData"/>
+                <command name="glCopyNamedBufferSubData"/>
+                <command name="glClearNamedBufferData"/>
+                <command name="glClearNamedBufferSubData"/>
+                <command name="glMapNamedBuffer"/>
+                <command name="glMapNamedBufferRange"/>
+                <command name="glUnmapNamedBuffer"/>
+                <command name="glFlushMappedNamedBufferRange"/>
+                <command name="glGetNamedBufferParameteriv"/>
+                <command name="glGetNamedBufferParameteri64v"/>
+                <command name="glGetNamedBufferPointerv"/>
+                <command name="glGetNamedBufferSubData"/>
+            </require>
+            <require comment="Framebuffer object functions">
+                <command name="glCreateFramebuffers"/>
+                <command name="glNamedFramebufferRenderbuffer"/>
+                <command name="glNamedFramebufferParameteri"/>
+                <command name="glNamedFramebufferTexture"/>
+                <command name="glNamedFramebufferTextureLayer"/>
+                <command name="glNamedFramebufferDrawBuffer"/>
+                <command name="glNamedFramebufferDrawBuffers"/>
+                <command name="glNamedFramebufferReadBuffer"/>
+                <command name="glInvalidateNamedFramebufferData"/>
+                <command name="glInvalidateNamedFramebufferSubData"/>
+                <command name="glClearNamedFramebufferiv"/>
+                <command name="glClearNamedFramebufferuiv"/>
+                <command name="glClearNamedFramebufferfv"/>
+                <command name="glClearNamedFramebufferfi"/>
+                <command name="glBlitNamedFramebuffer"/>
+                <command name="glCheckNamedFramebufferStatus"/>
+                <command name="glGetNamedFramebufferParameteriv"/>
+                <command name="glGetNamedFramebufferAttachmentParameteriv"/>
+            </require>
+            <require comment="Renderbuffer object functions">
+                <command name="glCreateRenderbuffers"/>
+                <command name="glNamedRenderbufferStorage"/>
+                <command name="glNamedRenderbufferStorageMultisample"/>
+                <command name="glGetNamedRenderbufferParameteriv"/>
+            </require>
+            <require comment="Texture object functions">
+                <command name="glCreateTextures"/>
+                <command name="glTextureBuffer"/>
+                <command name="glTextureBufferRange"/>
+                <command name="glTextureStorage1D"/>
+                <command name="glTextureStorage2D"/>
+                <command name="glTextureStorage3D"/>
+                <command name="glTextureStorage2DMultisample"/>
+                <command name="glTextureStorage3DMultisample"/>
+                <command name="glTextureSubImage1D"/>
+                <command name="glTextureSubImage2D"/>
+                <command name="glTextureSubImage3D"/>
+                <command name="glCompressedTextureSubImage1D"/>
+                <command name="glCompressedTextureSubImage2D"/>
+                <command name="glCompressedTextureSubImage3D"/>
+                <command name="glCopyTextureSubImage1D"/>
+                <command name="glCopyTextureSubImage2D"/>
+                <command name="glCopyTextureSubImage3D"/>
+                <command name="glTextureParameterf"/>
+                <command name="glTextureParameterfv"/>
+                <command name="glTextureParameteri"/>
+                <command name="glTextureParameterIiv"/>
+                <command name="glTextureParameterIuiv"/>
+                <command name="glTextureParameteriv"/>
+                <command name="glGenerateTextureMipmap"/>
+                <command name="glBindTextureUnit"/>
+                <command name="glGetTextureImage"/>
+                <command name="glGetCompressedTextureImage"/>
+                <command name="glGetTextureLevelParameterfv"/>
+                <command name="glGetTextureLevelParameteriv"/>
+                <command name="glGetTextureParameterfv"/>
+                <command name="glGetTextureParameterIiv"/>
+                <command name="glGetTextureParameterIuiv"/>
+                <command name="glGetTextureParameteriv"/>
+            </require>
+            <require comment="Vertex Array object functions">
+                <command name="glCreateVertexArrays"/>
+                <command name="glDisableVertexArrayAttrib"/>
+                <command name="glEnableVertexArrayAttrib"/>
+                <command name="glVertexArrayElementBuffer"/>
+                <command name="glVertexArrayVertexBuffer"/>
+                <command name="glVertexArrayVertexBuffers"/>
+                <command name="glVertexArrayAttribBinding"/>
+                <command name="glVertexArrayAttribFormat"/>
+                <command name="glVertexArrayAttribIFormat"/>
+                <command name="glVertexArrayAttribLFormat"/>
+                <command name="glVertexArrayBindingDivisor"/>
+                <command name="glGetVertexArrayiv"/>
+                <command name="glGetVertexArrayIndexediv"/>
+                <command name="glGetVertexArrayIndexed64iv"/>
+            </require>
+            <require comment="Sampler object functions">
+                <command name="glCreateSamplers"/>
+            </require>
+            <require comment="Program Pipeline object functions">
+                <command name="glCreateProgramPipelines"/>
+            </require>
+            <require comment="Query object functions">
+                <command name="glCreateQueries"/>
+                <command name="glGetQueryBufferObjecti64v"/>
+                <command name="glGetQueryBufferObjectiv"/>
+                <command name="glGetQueryBufferObjectui64v"/>
+                <command name="glGetQueryBufferObjectuiv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_draw_buffers" supported="gl">
+            <require>
+                <enum name="GL_MAX_DRAW_BUFFERS_ARB"/>
+                <enum name="GL_DRAW_BUFFER0_ARB"/>
+                <enum name="GL_DRAW_BUFFER1_ARB"/>
+                <enum name="GL_DRAW_BUFFER2_ARB"/>
+                <enum name="GL_DRAW_BUFFER3_ARB"/>
+                <enum name="GL_DRAW_BUFFER4_ARB"/>
+                <enum name="GL_DRAW_BUFFER5_ARB"/>
+                <enum name="GL_DRAW_BUFFER6_ARB"/>
+                <enum name="GL_DRAW_BUFFER7_ARB"/>
+                <enum name="GL_DRAW_BUFFER8_ARB"/>
+                <enum name="GL_DRAW_BUFFER9_ARB"/>
+                <enum name="GL_DRAW_BUFFER10_ARB"/>
+                <enum name="GL_DRAW_BUFFER11_ARB"/>
+                <enum name="GL_DRAW_BUFFER12_ARB"/>
+                <enum name="GL_DRAW_BUFFER13_ARB"/>
+                <enum name="GL_DRAW_BUFFER14_ARB"/>
+                <enum name="GL_DRAW_BUFFER15_ARB"/>
+                <command name="glDrawBuffersARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_draw_buffers_blend" supported="gl|glcore">
+            <require>
+                <command name="glBlendEquationiARB"/>
+                <command name="glBlendEquationSeparateiARB"/>
+                <command name="glBlendFunciARB"/>
+                <command name="glBlendFuncSeparateiARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_draw_elements_base_vertex" supported="gl|glcore">
+            <require>
+                <command name="glDrawElementsBaseVertex"/>
+                <command name="glDrawRangeElementsBaseVertex"/>
+                <command name="glDrawElementsInstancedBaseVertex"/>
+                <command name="glMultiDrawElementsBaseVertex"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_draw_indirect" supported="gl|glcore">
+            <require>
+                <enum name="GL_DRAW_INDIRECT_BUFFER"/>
+                <enum name="GL_DRAW_INDIRECT_BUFFER_BINDING"/>
+                <command name="glDrawArraysIndirect"/>
+                <command name="glDrawElementsIndirect"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_draw_instanced" supported="gl">
+            <require>
+                <command name="glDrawArraysInstancedARB"/>
+                <command name="glDrawElementsInstancedARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_enhanced_layouts" supported="gl|glcore">
+            <require>
+                <enum name="GL_LOCATION_COMPONENT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_INDEX"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_explicit_attrib_location" supported="gl|glcore"/>
+        <extension name="GL_ARB_explicit_uniform_location" supported="gl|glcore">
+            <require>
+                <enum name="GL_MAX_UNIFORM_LOCATIONS"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_fragment_coord_conventions" supported="gl|glcore"/>
+        <extension name="GL_ARB_fragment_layer_viewport" supported="gl|glcore"/>
+        <extension name="GL_ARB_fragment_program" supported="gl">
+            <require>
+                <enum name="GL_FRAGMENT_PROGRAM_ARB"/>
+                <enum name="GL_PROGRAM_FORMAT_ASCII_ARB"/>
+                <enum name="GL_PROGRAM_LENGTH_ARB"/>
+                <enum name="GL_PROGRAM_FORMAT_ARB"/>
+                <enum name="GL_PROGRAM_BINDING_ARB"/>
+                <enum name="GL_PROGRAM_INSTRUCTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_INSTRUCTIONS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB"/>
+                <enum name="GL_PROGRAM_TEMPORARIES_ARB"/>
+                <enum name="GL_MAX_PROGRAM_TEMPORARIES_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_TEMPORARIES_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB"/>
+                <enum name="GL_PROGRAM_PARAMETERS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_PARAMETERS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_PARAMETERS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB"/>
+                <enum name="GL_PROGRAM_ATTRIBS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_ATTRIBS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_ATTRIBS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_ENV_PARAMETERS_ARB"/>
+                <enum name="GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB"/>
+                <enum name="GL_PROGRAM_ALU_INSTRUCTIONS_ARB"/>
+                <enum name="GL_PROGRAM_TEX_INSTRUCTIONS_ARB"/>
+                <enum name="GL_PROGRAM_TEX_INDIRECTIONS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB"/>
+                <enum name="GL_PROGRAM_STRING_ARB"/>
+                <enum name="GL_PROGRAM_ERROR_POSITION_ARB"/>
+                <enum name="GL_CURRENT_MATRIX_ARB"/>
+                <enum name="GL_TRANSPOSE_CURRENT_MATRIX_ARB"/>
+                <enum name="GL_CURRENT_MATRIX_STACK_DEPTH_ARB"/>
+                <enum name="GL_MAX_PROGRAM_MATRICES_ARB"/>
+                <enum name="GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB"/>
+                <enum name="GL_MAX_TEXTURE_COORDS_ARB"/>
+                <enum name="GL_MAX_TEXTURE_IMAGE_UNITS_ARB"/>
+                <enum name="GL_PROGRAM_ERROR_STRING_ARB"/>
+                <enum name="GL_MATRIX0_ARB"/>
+                <enum name="GL_MATRIX1_ARB"/>
+                <enum name="GL_MATRIX2_ARB"/>
+                <enum name="GL_MATRIX3_ARB"/>
+                <enum name="GL_MATRIX4_ARB"/>
+                <enum name="GL_MATRIX5_ARB"/>
+                <enum name="GL_MATRIX6_ARB"/>
+                <enum name="GL_MATRIX7_ARB"/>
+                <enum name="GL_MATRIX8_ARB"/>
+                <enum name="GL_MATRIX9_ARB"/>
+                <enum name="GL_MATRIX10_ARB"/>
+                <enum name="GL_MATRIX11_ARB"/>
+                <enum name="GL_MATRIX12_ARB"/>
+                <enum name="GL_MATRIX13_ARB"/>
+                <enum name="GL_MATRIX14_ARB"/>
+                <enum name="GL_MATRIX15_ARB"/>
+                <enum name="GL_MATRIX16_ARB"/>
+                <enum name="GL_MATRIX17_ARB"/>
+                <enum name="GL_MATRIX18_ARB"/>
+                <enum name="GL_MATRIX19_ARB"/>
+                <enum name="GL_MATRIX20_ARB"/>
+                <enum name="GL_MATRIX21_ARB"/>
+                <enum name="GL_MATRIX22_ARB"/>
+                <enum name="GL_MATRIX23_ARB"/>
+                <enum name="GL_MATRIX24_ARB"/>
+                <enum name="GL_MATRIX25_ARB"/>
+                <enum name="GL_MATRIX26_ARB"/>
+                <enum name="GL_MATRIX27_ARB"/>
+                <enum name="GL_MATRIX28_ARB"/>
+                <enum name="GL_MATRIX29_ARB"/>
+                <enum name="GL_MATRIX30_ARB"/>
+                <enum name="GL_MATRIX31_ARB"/>
+            </require>
+            <require comment="Shared with ARB_vertex_program">
+                <command name="glProgramStringARB"/>
+                <command name="glBindProgramARB"/>
+                <command name="glDeleteProgramsARB"/>
+                <command name="glGenProgramsARB"/>
+                <command name="glProgramEnvParameter4dARB"/>
+                <command name="glProgramEnvParameter4dvARB"/>
+                <command name="glProgramEnvParameter4fARB"/>
+                <command name="glProgramEnvParameter4fvARB"/>
+                <command name="glProgramLocalParameter4dARB"/>
+                <command name="glProgramLocalParameter4dvARB"/>
+                <command name="glProgramLocalParameter4fARB"/>
+                <command name="glProgramLocalParameter4fvARB"/>
+                <command name="glGetProgramEnvParameterdvARB"/>
+                <command name="glGetProgramEnvParameterfvARB"/>
+                <command name="glGetProgramLocalParameterdvARB"/>
+                <command name="glGetProgramLocalParameterfvARB"/>
+                <command name="glGetProgramivARB"/>
+                <command name="glGetProgramStringARB"/>
+                <command name="glIsProgramARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_fragment_program_shadow" supported="gl"/>
+        <extension name="GL_ARB_fragment_shader" supported="gl">
+            <require>
+                <enum name="GL_FRAGMENT_SHADER_ARB"/>
+                <enum name="GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB"/>
+                <enum name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_fragment_shader_interlock" supported="gl"/>
+        <extension name="GL_ARB_framebuffer_no_attachments" supported="gl|glcore">
+            <require>
+                <enum name="GL_FRAMEBUFFER_DEFAULT_WIDTH"/>
+                <enum name="GL_FRAMEBUFFER_DEFAULT_HEIGHT"/>
+                <enum name="GL_FRAMEBUFFER_DEFAULT_LAYERS"/>
+                <enum name="GL_FRAMEBUFFER_DEFAULT_SAMPLES"/>
+                <enum name="GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"/>
+                <enum name="GL_MAX_FRAMEBUFFER_WIDTH"/>
+                <enum name="GL_MAX_FRAMEBUFFER_HEIGHT"/>
+                <enum name="GL_MAX_FRAMEBUFFER_LAYERS"/>
+                <enum name="GL_MAX_FRAMEBUFFER_SAMPLES"/>
+                <command name="glFramebufferParameteri"/>
+                <command name="glGetFramebufferParameteriv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_framebuffer_object" supported="gl|glcore">
+            <require>
+                <enum name="GL_INVALID_FRAMEBUFFER_OPERATION"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE"/>
+                <enum name="GL_FRAMEBUFFER_DEFAULT"/>
+                <enum name="GL_FRAMEBUFFER_UNDEFINED"/>
+                <enum name="GL_DEPTH_STENCIL_ATTACHMENT"/>
+                <enum name="GL_MAX_RENDERBUFFER_SIZE"/>
+                <enum name="GL_DEPTH_STENCIL"/>
+                <enum name="GL_UNSIGNED_INT_24_8"/>
+                <enum name="GL_DEPTH24_STENCIL8"/>
+                <enum name="GL_TEXTURE_STENCIL_SIZE"/>
+                <enum name="GL_UNSIGNED_NORMALIZED"/>
+                <enum name="GL_FRAMEBUFFER_BINDING"/>
+                <enum name="GL_DRAW_FRAMEBUFFER_BINDING"/>
+                <enum name="GL_RENDERBUFFER_BINDING"/>
+                <enum name="GL_READ_FRAMEBUFFER"/>
+                <enum name="GL_DRAW_FRAMEBUFFER"/>
+                <enum name="GL_READ_FRAMEBUFFER_BINDING"/>
+                <enum name="GL_RENDERBUFFER_SAMPLES"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER"/>
+                <enum name="GL_FRAMEBUFFER_COMPLETE"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"/>
+                <enum name="GL_FRAMEBUFFER_UNSUPPORTED"/>
+                <enum name="GL_MAX_COLOR_ATTACHMENTS"/>
+                <enum name="GL_COLOR_ATTACHMENT0"/>
+                <enum name="GL_COLOR_ATTACHMENT1"/>
+                <enum name="GL_COLOR_ATTACHMENT2"/>
+                <enum name="GL_COLOR_ATTACHMENT3"/>
+                <enum name="GL_COLOR_ATTACHMENT4"/>
+                <enum name="GL_COLOR_ATTACHMENT5"/>
+                <enum name="GL_COLOR_ATTACHMENT6"/>
+                <enum name="GL_COLOR_ATTACHMENT7"/>
+                <enum name="GL_COLOR_ATTACHMENT8"/>
+                <enum name="GL_COLOR_ATTACHMENT9"/>
+                <enum name="GL_COLOR_ATTACHMENT10"/>
+                <enum name="GL_COLOR_ATTACHMENT11"/>
+                <enum name="GL_COLOR_ATTACHMENT12"/>
+                <enum name="GL_COLOR_ATTACHMENT13"/>
+                <enum name="GL_COLOR_ATTACHMENT14"/>
+                <enum name="GL_COLOR_ATTACHMENT15"/>
+                <enum name="GL_DEPTH_ATTACHMENT"/>
+                <enum name="GL_STENCIL_ATTACHMENT"/>
+                <enum name="GL_FRAMEBUFFER"/>
+                <enum name="GL_RENDERBUFFER"/>
+                <enum name="GL_RENDERBUFFER_WIDTH"/>
+                <enum name="GL_RENDERBUFFER_HEIGHT"/>
+                <enum name="GL_RENDERBUFFER_INTERNAL_FORMAT"/>
+                <enum name="GL_STENCIL_INDEX1"/>
+                <enum name="GL_STENCIL_INDEX4"/>
+                <enum name="GL_STENCIL_INDEX8"/>
+                <enum name="GL_STENCIL_INDEX16"/>
+                <enum name="GL_RENDERBUFFER_RED_SIZE"/>
+                <enum name="GL_RENDERBUFFER_GREEN_SIZE"/>
+                <enum name="GL_RENDERBUFFER_BLUE_SIZE"/>
+                <enum name="GL_RENDERBUFFER_ALPHA_SIZE"/>
+                <enum name="GL_RENDERBUFFER_DEPTH_SIZE"/>
+                <enum name="GL_RENDERBUFFER_STENCIL_SIZE"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"/>
+                <enum name="GL_MAX_SAMPLES"/>
+                <command name="glIsRenderbuffer"/>
+                <command name="glBindRenderbuffer"/>
+                <command name="glDeleteRenderbuffers"/>
+                <command name="glGenRenderbuffers"/>
+                <command name="glRenderbufferStorage"/>
+                <command name="glGetRenderbufferParameteriv"/>
+                <command name="glIsFramebuffer"/>
+                <command name="glBindFramebuffer"/>
+                <command name="glDeleteFramebuffers"/>
+                <command name="glGenFramebuffers"/>
+                <command name="glCheckFramebufferStatus"/>
+                <command name="glFramebufferTexture1D"/>
+                <command name="glFramebufferTexture2D"/>
+                <command name="glFramebufferTexture3D"/>
+                <command name="glFramebufferRenderbuffer"/>
+                <command name="glGetFramebufferAttachmentParameteriv"/>
+                <command name="glGenerateMipmap"/>
+                <command name="glBlitFramebuffer"/>
+                <command name="glRenderbufferStorageMultisample"/>
+                <command name="glFramebufferTextureLayer"/>
+            </require>
+            <require api="gl" profile="compatibility">
+                <enum name="GL_INDEX"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_framebuffer_sRGB" supported="gl|glcore">
+            <require>
+                <enum name="GL_FRAMEBUFFER_SRGB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_geometry_shader4" supported="gl">
+            <require>
+                <enum name="GL_LINES_ADJACENCY_ARB"/>
+                <enum name="GL_LINE_STRIP_ADJACENCY_ARB"/>
+                <enum name="GL_TRIANGLES_ADJACENCY_ARB"/>
+                <enum name="GL_TRIANGLE_STRIP_ADJACENCY_ARB"/>
+                <enum name="GL_PROGRAM_POINT_SIZE_ARB"/>
+                <enum name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB"/>
+                <enum name="GL_GEOMETRY_SHADER_ARB"/>
+                <enum name="GL_GEOMETRY_VERTICES_OUT_ARB"/>
+                <enum name="GL_GEOMETRY_INPUT_TYPE_ARB"/>
+                <enum name="GL_GEOMETRY_OUTPUT_TYPE_ARB"/>
+                <enum name="GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB"/>
+                <enum name="GL_MAX_VERTEX_VARYING_COMPONENTS_ARB"/>
+                <enum name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB"/>
+                <enum name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB"/>
+                <enum name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB"/>
+                <enum name="GL_MAX_VARYING_COMPONENTS"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER"/>
+                <command name="glProgramParameteriARB"/>
+                <command name="glFramebufferTextureARB"/>
+                <command name="glFramebufferTextureLayerARB"/>
+                <command name="glFramebufferTextureFaceARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_get_program_binary" supported="gl|glcore">
+            <require>
+                <enum name="GL_PROGRAM_BINARY_RETRIEVABLE_HINT"/>
+                <enum name="GL_PROGRAM_BINARY_LENGTH"/>
+                <enum name="GL_NUM_PROGRAM_BINARY_FORMATS"/>
+                <enum name="GL_PROGRAM_BINARY_FORMATS"/>
+                <command name="glGetProgramBinary"/>
+                <command name="glProgramBinary"/>
+                <command name="glProgramParameteri"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_get_texture_sub_image" supported="gl|glcore">
+            <require>
+                <command name="glGetTextureSubImage"/>
+                <command name="glGetCompressedTextureSubImage"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_gpu_shader5" supported="gl|glcore">
+            <require>
+                <enum name="GL_GEOMETRY_SHADER_INVOCATIONS"/>
+                <enum name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS"/>
+                <enum name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET"/>
+                <enum name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET"/>
+                <enum name="GL_FRAGMENT_INTERPOLATION_OFFSET_BITS"/>
+                <enum name="GL_MAX_VERTEX_STREAMS"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_gpu_shader_fp64" supported="gl|glcore">
+            <require>
+                <enum name="GL_DOUBLE"/>
+                <enum name="GL_DOUBLE_VEC2"/>
+                <enum name="GL_DOUBLE_VEC3"/>
+                <enum name="GL_DOUBLE_VEC4"/>
+                <enum name="GL_DOUBLE_MAT2"/>
+                <enum name="GL_DOUBLE_MAT3"/>
+                <enum name="GL_DOUBLE_MAT4"/>
+                <enum name="GL_DOUBLE_MAT2x3"/>
+                <enum name="GL_DOUBLE_MAT2x4"/>
+                <enum name="GL_DOUBLE_MAT3x2"/>
+                <enum name="GL_DOUBLE_MAT3x4"/>
+                <enum name="GL_DOUBLE_MAT4x2"/>
+                <enum name="GL_DOUBLE_MAT4x3"/>
+                <command name="glUniform1d"/>
+                <command name="glUniform2d"/>
+                <command name="glUniform3d"/>
+                <command name="glUniform4d"/>
+                <command name="glUniform1dv"/>
+                <command name="glUniform2dv"/>
+                <command name="glUniform3dv"/>
+                <command name="glUniform4dv"/>
+                <command name="glUniformMatrix2dv"/>
+                <command name="glUniformMatrix3dv"/>
+                <command name="glUniformMatrix4dv"/>
+                <command name="glUniformMatrix2x3dv"/>
+                <command name="glUniformMatrix2x4dv"/>
+                <command name="glUniformMatrix3x2dv"/>
+                <command name="glUniformMatrix3x4dv"/>
+                <command name="glUniformMatrix4x2dv"/>
+                <command name="glUniformMatrix4x3dv"/>
+                <command name="glGetUniformdv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_gpu_shader_int64" supported="gl">
+            <require>
+                <enum name="GL_INT64_ARB"/>
+                <enum name="GL_UNSIGNED_INT64_ARB"/>
+                <enum name="GL_INT64_VEC2_ARB"/>
+                <enum name="GL_INT64_VEC3_ARB"/>
+                <enum name="GL_INT64_VEC4_ARB"/>
+                <enum name="GL_UNSIGNED_INT64_VEC2_ARB"/>
+                <enum name="GL_UNSIGNED_INT64_VEC3_ARB"/>
+                <enum name="GL_UNSIGNED_INT64_VEC4_ARB"/>
+                <command name="glUniform1i64ARB"/>
+                <command name="glUniform2i64ARB"/>
+                <command name="glUniform3i64ARB"/>
+                <command name="glUniform4i64ARB"/>
+                <command name="glUniform1i64vARB"/>
+                <command name="glUniform2i64vARB"/>
+                <command name="glUniform3i64vARB"/>
+                <command name="glUniform4i64vARB"/>
+                <command name="glUniform1ui64ARB"/>
+                <command name="glUniform2ui64ARB"/>
+                <command name="glUniform3ui64ARB"/>
+                <command name="glUniform4ui64ARB"/>
+                <command name="glUniform1ui64vARB"/>
+                <command name="glUniform2ui64vARB"/>
+                <command name="glUniform3ui64vARB"/>
+                <command name="glUniform4ui64vARB"/>
+                <command name="glGetUniformi64vARB"/>
+                <command name="glGetUniformui64vARB"/>
+                <command name="glGetnUniformi64vARB"/>
+                <command name="glGetnUniformui64vARB"/>
+                <command name="glProgramUniform1i64ARB"/>
+                <command name="glProgramUniform2i64ARB"/>
+                <command name="glProgramUniform3i64ARB"/>
+                <command name="glProgramUniform4i64ARB"/>
+                <command name="glProgramUniform1i64vARB"/>
+                <command name="glProgramUniform2i64vARB"/>
+                <command name="glProgramUniform3i64vARB"/>
+                <command name="glProgramUniform4i64vARB"/>
+                <command name="glProgramUniform1ui64ARB"/>
+                <command name="glProgramUniform2ui64ARB"/>
+                <command name="glProgramUniform3ui64ARB"/>
+                <command name="glProgramUniform4ui64ARB"/>
+                <command name="glProgramUniform1ui64vARB"/>
+                <command name="glProgramUniform2ui64vARB"/>
+                <command name="glProgramUniform3ui64vARB"/>
+                <command name="glProgramUniform4ui64vARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_half_float_pixel" supported="gl">
+            <require>
+                <type name="GLhalfARB"/>
+                <enum name="GL_HALF_FLOAT_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_half_float_vertex" supported="gl|glcore">
+            <require>
+                <type name="GLhalf"/>
+                <enum name="GL_HALF_FLOAT"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_imaging" supported="gl|glcore" comment="Now treating ARB_imaging as an extension, not a GL API version">
+            <require>
+                <enum name="GL_CONSTANT_COLOR"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_COLOR"/>
+                <enum name="GL_CONSTANT_ALPHA"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_ALPHA"/>
+                <enum name="GL_BLEND_COLOR"/>
+                <enum name="GL_FUNC_ADD"/>
+                <enum name="GL_MIN"/>
+                <enum name="GL_MAX"/>
+                <enum name="GL_BLEND_EQUATION"/>
+                <enum name="GL_FUNC_SUBTRACT"/>
+                <enum name="GL_FUNC_REVERSE_SUBTRACT"/>
+                <command name="glBlendColor"/>
+                <command name="glBlendEquation"/>
+            </require>
+            <require api="gl" profile="compatibility">
+                <enum name="GL_CONVOLUTION_1D"/>
+                <enum name="GL_CONVOLUTION_2D"/>
+                <enum name="GL_SEPARABLE_2D"/>
+                <enum name="GL_CONVOLUTION_BORDER_MODE"/>
+                <enum name="GL_CONVOLUTION_FILTER_SCALE"/>
+                <enum name="GL_CONVOLUTION_FILTER_BIAS"/>
+                <enum name="GL_REDUCE"/>
+                <enum name="GL_CONVOLUTION_FORMAT"/>
+                <enum name="GL_CONVOLUTION_WIDTH"/>
+                <enum name="GL_CONVOLUTION_HEIGHT"/>
+                <enum name="GL_MAX_CONVOLUTION_WIDTH"/>
+                <enum name="GL_MAX_CONVOLUTION_HEIGHT"/>
+                <enum name="GL_POST_CONVOLUTION_RED_SCALE"/>
+                <enum name="GL_POST_CONVOLUTION_GREEN_SCALE"/>
+                <enum name="GL_POST_CONVOLUTION_BLUE_SCALE"/>
+                <enum name="GL_POST_CONVOLUTION_ALPHA_SCALE"/>
+                <enum name="GL_POST_CONVOLUTION_RED_BIAS"/>
+                <enum name="GL_POST_CONVOLUTION_GREEN_BIAS"/>
+                <enum name="GL_POST_CONVOLUTION_BLUE_BIAS"/>
+                <enum name="GL_POST_CONVOLUTION_ALPHA_BIAS"/>
+                <enum name="GL_HISTOGRAM"/>
+                <enum name="GL_PROXY_HISTOGRAM"/>
+                <enum name="GL_HISTOGRAM_WIDTH"/>
+                <enum name="GL_HISTOGRAM_FORMAT"/>
+                <enum name="GL_HISTOGRAM_RED_SIZE"/>
+                <enum name="GL_HISTOGRAM_GREEN_SIZE"/>
+                <enum name="GL_HISTOGRAM_BLUE_SIZE"/>
+                <enum name="GL_HISTOGRAM_ALPHA_SIZE"/>
+                <enum name="GL_HISTOGRAM_LUMINANCE_SIZE"/>
+                <enum name="GL_HISTOGRAM_SINK"/>
+                <enum name="GL_MINMAX"/>
+                <enum name="GL_MINMAX_FORMAT"/>
+                <enum name="GL_MINMAX_SINK"/>
+                <enum name="GL_TABLE_TOO_LARGE"/>
+                <enum name="GL_COLOR_MATRIX"/>
+                <enum name="GL_COLOR_MATRIX_STACK_DEPTH"/>
+                <enum name="GL_MAX_COLOR_MATRIX_STACK_DEPTH"/>
+                <enum name="GL_POST_COLOR_MATRIX_RED_SCALE"/>
+                <enum name="GL_POST_COLOR_MATRIX_GREEN_SCALE"/>
+                <enum name="GL_POST_COLOR_MATRIX_BLUE_SCALE"/>
+                <enum name="GL_POST_COLOR_MATRIX_ALPHA_SCALE"/>
+                <enum name="GL_POST_COLOR_MATRIX_RED_BIAS"/>
+                <enum name="GL_POST_COLOR_MATRIX_GREEN_BIAS"/>
+                <enum name="GL_POST_COLOR_MATRIX_BLUE_BIAS"/>
+                <enum name="GL_POST_COLOR_MATRIX_ALPHA_BIAS"/>
+                <enum name="GL_COLOR_TABLE"/>
+                <enum name="GL_POST_CONVOLUTION_COLOR_TABLE"/>
+                <enum name="GL_POST_COLOR_MATRIX_COLOR_TABLE"/>
+                <enum name="GL_PROXY_COLOR_TABLE"/>
+                <enum name="GL_PROXY_POST_CONVOLUTION_COLOR_TABLE"/>
+                <enum name="GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE"/>
+                <enum name="GL_COLOR_TABLE_SCALE"/>
+                <enum name="GL_COLOR_TABLE_BIAS"/>
+                <enum name="GL_COLOR_TABLE_FORMAT"/>
+                <enum name="GL_COLOR_TABLE_WIDTH"/>
+                <enum name="GL_COLOR_TABLE_RED_SIZE"/>
+                <enum name="GL_COLOR_TABLE_GREEN_SIZE"/>
+                <enum name="GL_COLOR_TABLE_BLUE_SIZE"/>
+                <enum name="GL_COLOR_TABLE_ALPHA_SIZE"/>
+                <enum name="GL_COLOR_TABLE_LUMINANCE_SIZE"/>
+                <enum name="GL_COLOR_TABLE_INTENSITY_SIZE"/>
+                <enum name="GL_CONSTANT_BORDER"/>
+                <enum name="GL_REPLICATE_BORDER"/>
+                <enum name="GL_CONVOLUTION_BORDER_COLOR"/>
+                <command name="glColorTable"/>
+                <command name="glColorTableParameterfv"/>
+                <command name="glColorTableParameteriv"/>
+                <command name="glCopyColorTable"/>
+                <command name="glGetColorTable"/>
+                <command name="glGetColorTableParameterfv"/>
+                <command name="glGetColorTableParameteriv"/>
+                <command name="glColorSubTable"/>
+                <command name="glCopyColorSubTable"/>
+                <command name="glConvolutionFilter1D"/>
+                <command name="glConvolutionFilter2D"/>
+                <command name="glConvolutionParameterf"/>
+                <command name="glConvolutionParameterfv"/>
+                <command name="glConvolutionParameteri"/>
+                <command name="glConvolutionParameteriv"/>
+                <command name="glCopyConvolutionFilter1D"/>
+                <command name="glCopyConvolutionFilter2D"/>
+                <command name="glGetConvolutionFilter"/>
+                <command name="glGetConvolutionParameterfv"/>
+                <command name="glGetConvolutionParameteriv"/>
+                <command name="glGetSeparableFilter"/>
+                <command name="glSeparableFilter2D"/>
+                <command name="glGetHistogram"/>
+                <command name="glGetHistogramParameterfv"/>
+                <command name="glGetHistogramParameteriv"/>
+                <command name="glGetMinmax"/>
+                <command name="glGetMinmaxParameterfv"/>
+                <command name="glGetMinmaxParameteriv"/>
+                <command name="glHistogram"/>
+                <command name="glMinmax"/>
+                <command name="glResetHistogram"/>
+                <command name="glResetMinmax"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_indirect_parameters" supported="gl|glcore">
+            <require>
+                <enum name="GL_PARAMETER_BUFFER_ARB"/>
+                <enum name="GL_PARAMETER_BUFFER_BINDING_ARB"/>
+                <command name="glMultiDrawArraysIndirectCountARB"/>
+                <command name="glMultiDrawElementsIndirectCountARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_instanced_arrays" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB"/>
+                <command name="glVertexAttribDivisorARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_internalformat_query" supported="gl|glcore">
+            <require>
+                <enum name="GL_NUM_SAMPLE_COUNTS"/>
+                <command name="glGetInternalformativ"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_internalformat_query2" supported="gl|glcore">
+            <require>
+                <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_TYPE"/>
+                <enum name="GL_NUM_SAMPLE_COUNTS"/>
+                <enum name="GL_RENDERBUFFER"/>
+                <enum name="GL_SAMPLES"/>
+                <enum name="GL_TEXTURE_1D"/>
+                <enum name="GL_TEXTURE_1D_ARRAY"/>
+                <enum name="GL_TEXTURE_2D"/>
+                <enum name="GL_TEXTURE_2D_ARRAY"/>
+                <enum name="GL_TEXTURE_3D"/>
+                <enum name="GL_TEXTURE_CUBE_MAP"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_ARRAY"/>
+                <enum name="GL_TEXTURE_RECTANGLE"/>
+                <enum name="GL_TEXTURE_BUFFER"/>
+                <enum name="GL_TEXTURE_2D_MULTISAMPLE"/>
+                <enum name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_TEXTURE_COMPRESSED"/>
+                <enum name="GL_INTERNALFORMAT_SUPPORTED"/>
+                <enum name="GL_INTERNALFORMAT_PREFERRED"/>
+                <enum name="GL_INTERNALFORMAT_RED_SIZE"/>
+                <enum name="GL_INTERNALFORMAT_GREEN_SIZE"/>
+                <enum name="GL_INTERNALFORMAT_BLUE_SIZE"/>
+                <enum name="GL_INTERNALFORMAT_ALPHA_SIZE"/>
+                <enum name="GL_INTERNALFORMAT_DEPTH_SIZE"/>
+                <enum name="GL_INTERNALFORMAT_STENCIL_SIZE"/>
+                <enum name="GL_INTERNALFORMAT_SHARED_SIZE"/>
+                <enum name="GL_INTERNALFORMAT_RED_TYPE"/>
+                <enum name="GL_INTERNALFORMAT_GREEN_TYPE"/>
+                <enum name="GL_INTERNALFORMAT_BLUE_TYPE"/>
+                <enum name="GL_INTERNALFORMAT_ALPHA_TYPE"/>
+                <enum name="GL_INTERNALFORMAT_DEPTH_TYPE"/>
+                <enum name="GL_INTERNALFORMAT_STENCIL_TYPE"/>
+                <enum name="GL_MAX_WIDTH"/>
+                <enum name="GL_MAX_HEIGHT"/>
+                <enum name="GL_MAX_DEPTH"/>
+                <enum name="GL_MAX_LAYERS"/>
+                <enum name="GL_MAX_COMBINED_DIMENSIONS"/>
+                <enum name="GL_COLOR_COMPONENTS"/>
+                <enum name="GL_DEPTH_COMPONENTS"/>
+                <enum name="GL_STENCIL_COMPONENTS"/>
+                <enum name="GL_COLOR_RENDERABLE"/>
+                <enum name="GL_DEPTH_RENDERABLE"/>
+                <enum name="GL_STENCIL_RENDERABLE"/>
+                <enum name="GL_FRAMEBUFFER_RENDERABLE"/>
+                <enum name="GL_FRAMEBUFFER_RENDERABLE_LAYERED"/>
+                <enum name="GL_FRAMEBUFFER_BLEND"/>
+                <enum name="GL_READ_PIXELS"/>
+                <enum name="GL_READ_PIXELS_FORMAT"/>
+                <enum name="GL_READ_PIXELS_TYPE"/>
+                <enum name="GL_TEXTURE_IMAGE_FORMAT"/>
+                <enum name="GL_TEXTURE_IMAGE_TYPE"/>
+                <enum name="GL_GET_TEXTURE_IMAGE_FORMAT"/>
+                <enum name="GL_GET_TEXTURE_IMAGE_TYPE"/>
+                <enum name="GL_MIPMAP"/>
+                <enum name="GL_MANUAL_GENERATE_MIPMAP"/>
+                <enum name="GL_AUTO_GENERATE_MIPMAP"/>
+                <enum name="GL_COLOR_ENCODING"/>
+                <enum name="GL_SRGB_READ"/>
+                <enum name="GL_SRGB_WRITE"/>
+                <enum name="GL_SRGB_DECODE_ARB"/>
+                <enum name="GL_FILTER"/>
+                <enum name="GL_VERTEX_TEXTURE"/>
+                <enum name="GL_TESS_CONTROL_TEXTURE"/>
+                <enum name="GL_TESS_EVALUATION_TEXTURE"/>
+                <enum name="GL_GEOMETRY_TEXTURE"/>
+                <enum name="GL_FRAGMENT_TEXTURE"/>
+                <enum name="GL_COMPUTE_TEXTURE"/>
+                <enum name="GL_TEXTURE_SHADOW"/>
+                <enum name="GL_TEXTURE_GATHER"/>
+                <enum name="GL_TEXTURE_GATHER_SHADOW"/>
+                <enum name="GL_SHADER_IMAGE_LOAD"/>
+                <enum name="GL_SHADER_IMAGE_STORE"/>
+                <enum name="GL_SHADER_IMAGE_ATOMIC"/>
+                <enum name="GL_IMAGE_TEXEL_SIZE"/>
+                <enum name="GL_IMAGE_COMPATIBILITY_CLASS"/>
+                <enum name="GL_IMAGE_PIXEL_FORMAT"/>
+                <enum name="GL_IMAGE_PIXEL_TYPE"/>
+                <enum name="GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST"/>
+                <enum name="GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST"/>
+                <enum name="GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE"/>
+                <enum name="GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE"/>
+                <enum name="GL_TEXTURE_COMPRESSED_BLOCK_WIDTH"/>
+                <enum name="GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT"/>
+                <enum name="GL_TEXTURE_COMPRESSED_BLOCK_SIZE"/>
+                <enum name="GL_CLEAR_BUFFER"/>
+                <enum name="GL_TEXTURE_VIEW"/>
+                <enum name="GL_VIEW_COMPATIBILITY_CLASS"/>
+                <enum name="GL_FULL_SUPPORT"/>
+                <enum name="GL_CAVEAT_SUPPORT"/>
+                <enum name="GL_IMAGE_CLASS_4_X_32"/>
+                <enum name="GL_IMAGE_CLASS_2_X_32"/>
+                <enum name="GL_IMAGE_CLASS_1_X_32"/>
+                <enum name="GL_IMAGE_CLASS_4_X_16"/>
+                <enum name="GL_IMAGE_CLASS_2_X_16"/>
+                <enum name="GL_IMAGE_CLASS_1_X_16"/>
+                <enum name="GL_IMAGE_CLASS_4_X_8"/>
+                <enum name="GL_IMAGE_CLASS_2_X_8"/>
+                <enum name="GL_IMAGE_CLASS_1_X_8"/>
+                <enum name="GL_IMAGE_CLASS_11_11_10"/>
+                <enum name="GL_IMAGE_CLASS_10_10_10_2"/>
+                <enum name="GL_VIEW_CLASS_128_BITS"/>
+                <enum name="GL_VIEW_CLASS_96_BITS"/>
+                <enum name="GL_VIEW_CLASS_64_BITS"/>
+                <enum name="GL_VIEW_CLASS_48_BITS"/>
+                <enum name="GL_VIEW_CLASS_32_BITS"/>
+                <enum name="GL_VIEW_CLASS_24_BITS"/>
+                <enum name="GL_VIEW_CLASS_16_BITS"/>
+                <enum name="GL_VIEW_CLASS_8_BITS"/>
+                <enum name="GL_VIEW_CLASS_S3TC_DXT1_RGB"/>
+                <enum name="GL_VIEW_CLASS_S3TC_DXT1_RGBA"/>
+                <enum name="GL_VIEW_CLASS_S3TC_DXT3_RGBA"/>
+                <enum name="GL_VIEW_CLASS_S3TC_DXT5_RGBA"/>
+                <enum name="GL_VIEW_CLASS_RGTC1_RED"/>
+                <enum name="GL_VIEW_CLASS_RGTC2_RG"/>
+                <enum name="GL_VIEW_CLASS_BPTC_UNORM"/>
+                <enum name="GL_VIEW_CLASS_BPTC_FLOAT"/>
+                <command name="glGetInternalformati64v"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_invalidate_subdata" supported="gl|glcore">
+            <require>
+                <command name="glInvalidateTexSubImage"/>
+                <command name="glInvalidateTexImage"/>
+                <command name="glInvalidateBufferSubData"/>
+                <command name="glInvalidateBufferData"/>
+                <command name="glInvalidateFramebuffer"/>
+                <command name="glInvalidateSubFramebuffer"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_map_buffer_alignment" supported="gl|glcore">
+            <require>
+                <enum name="GL_MIN_MAP_BUFFER_ALIGNMENT"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_map_buffer_range" supported="gl|glcore">
+            <require>
+                <enum name="GL_MAP_READ_BIT"/>
+                <enum name="GL_MAP_WRITE_BIT"/>
+                <enum name="GL_MAP_INVALIDATE_RANGE_BIT"/>
+                <enum name="GL_MAP_INVALIDATE_BUFFER_BIT"/>
+                <enum name="GL_MAP_FLUSH_EXPLICIT_BIT"/>
+                <enum name="GL_MAP_UNSYNCHRONIZED_BIT"/>
+                <command name="glMapBufferRange"/>
+                <command name="glFlushMappedBufferRange"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_matrix_palette" supported="gl">
+            <require>
+                <enum name="GL_MATRIX_PALETTE_ARB"/>
+                <enum name="GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB"/>
+                <enum name="GL_MAX_PALETTE_MATRICES_ARB"/>
+                <enum name="GL_CURRENT_PALETTE_MATRIX_ARB"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_ARB"/>
+                <enum name="GL_CURRENT_MATRIX_INDEX_ARB"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_SIZE_ARB"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_TYPE_ARB"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_STRIDE_ARB"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_POINTER_ARB"/>
+                <command name="glCurrentPaletteMatrixARB"/>
+                <command name="glMatrixIndexubvARB"/>
+                <command name="glMatrixIndexusvARB"/>
+                <command name="glMatrixIndexuivARB"/>
+                <command name="glMatrixIndexPointerARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_multi_bind" supported="gl|glcore">
+            <require>
+                <command name="glBindBuffersBase"/>
+                <command name="glBindBuffersRange"/>
+                <command name="glBindTextures"/>
+                <command name="glBindSamplers"/>
+                <command name="glBindImageTextures"/>
+                <command name="glBindVertexBuffers"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_multi_draw_indirect" supported="gl|glcore">
+            <require>
+                <command name="glMultiDrawArraysIndirect"/>
+                <command name="glMultiDrawElementsIndirect"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_multisample" supported="gl">
+            <require>
+                <enum name="GL_MULTISAMPLE_ARB"/>
+                <enum name="GL_SAMPLE_ALPHA_TO_COVERAGE_ARB"/>
+                <enum name="GL_SAMPLE_ALPHA_TO_ONE_ARB"/>
+                <enum name="GL_SAMPLE_COVERAGE_ARB"/>
+                <enum name="GL_SAMPLE_BUFFERS_ARB"/>
+                <enum name="GL_SAMPLES_ARB"/>
+                <enum name="GL_SAMPLE_COVERAGE_VALUE_ARB"/>
+                <enum name="GL_SAMPLE_COVERAGE_INVERT_ARB"/>
+                <enum name="GL_MULTISAMPLE_BIT_ARB"/>
+                <command name="glSampleCoverageARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_multitexture" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE0_ARB"/>
+                <enum name="GL_TEXTURE1_ARB"/>
+                <enum name="GL_TEXTURE2_ARB"/>
+                <enum name="GL_TEXTURE3_ARB"/>
+                <enum name="GL_TEXTURE4_ARB"/>
+                <enum name="GL_TEXTURE5_ARB"/>
+                <enum name="GL_TEXTURE6_ARB"/>
+                <enum name="GL_TEXTURE7_ARB"/>
+                <enum name="GL_TEXTURE8_ARB"/>
+                <enum name="GL_TEXTURE9_ARB"/>
+                <enum name="GL_TEXTURE10_ARB"/>
+                <enum name="GL_TEXTURE11_ARB"/>
+                <enum name="GL_TEXTURE12_ARB"/>
+                <enum name="GL_TEXTURE13_ARB"/>
+                <enum name="GL_TEXTURE14_ARB"/>
+                <enum name="GL_TEXTURE15_ARB"/>
+                <enum name="GL_TEXTURE16_ARB"/>
+                <enum name="GL_TEXTURE17_ARB"/>
+                <enum name="GL_TEXTURE18_ARB"/>
+                <enum name="GL_TEXTURE19_ARB"/>
+                <enum name="GL_TEXTURE20_ARB"/>
+                <enum name="GL_TEXTURE21_ARB"/>
+                <enum name="GL_TEXTURE22_ARB"/>
+                <enum name="GL_TEXTURE23_ARB"/>
+                <enum name="GL_TEXTURE24_ARB"/>
+                <enum name="GL_TEXTURE25_ARB"/>
+                <enum name="GL_TEXTURE26_ARB"/>
+                <enum name="GL_TEXTURE27_ARB"/>
+                <enum name="GL_TEXTURE28_ARB"/>
+                <enum name="GL_TEXTURE29_ARB"/>
+                <enum name="GL_TEXTURE30_ARB"/>
+                <enum name="GL_TEXTURE31_ARB"/>
+                <enum name="GL_ACTIVE_TEXTURE_ARB"/>
+                <enum name="GL_CLIENT_ACTIVE_TEXTURE_ARB"/>
+                <enum name="GL_MAX_TEXTURE_UNITS_ARB"/>
+                <command name="glActiveTextureARB"/>
+                <command name="glClientActiveTextureARB"/>
+                <command name="glMultiTexCoord1dARB"/>
+                <command name="glMultiTexCoord1dvARB"/>
+                <command name="glMultiTexCoord1fARB"/>
+                <command name="glMultiTexCoord1fvARB"/>
+                <command name="glMultiTexCoord1iARB"/>
+                <command name="glMultiTexCoord1ivARB"/>
+                <command name="glMultiTexCoord1sARB"/>
+                <command name="glMultiTexCoord1svARB"/>
+                <command name="glMultiTexCoord2dARB"/>
+                <command name="glMultiTexCoord2dvARB"/>
+                <command name="glMultiTexCoord2fARB"/>
+                <command name="glMultiTexCoord2fvARB"/>
+                <command name="glMultiTexCoord2iARB"/>
+                <command name="glMultiTexCoord2ivARB"/>
+                <command name="glMultiTexCoord2sARB"/>
+                <command name="glMultiTexCoord2svARB"/>
+                <command name="glMultiTexCoord3dARB"/>
+                <command name="glMultiTexCoord3dvARB"/>
+                <command name="glMultiTexCoord3fARB"/>
+                <command name="glMultiTexCoord3fvARB"/>
+                <command name="glMultiTexCoord3iARB"/>
+                <command name="glMultiTexCoord3ivARB"/>
+                <command name="glMultiTexCoord3sARB"/>
+                <command name="glMultiTexCoord3svARB"/>
+                <command name="glMultiTexCoord4dARB"/>
+                <command name="glMultiTexCoord4dvARB"/>
+                <command name="glMultiTexCoord4fARB"/>
+                <command name="glMultiTexCoord4fvARB"/>
+                <command name="glMultiTexCoord4iARB"/>
+                <command name="glMultiTexCoord4ivARB"/>
+                <command name="glMultiTexCoord4sARB"/>
+                <command name="glMultiTexCoord4svARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_occlusion_query" supported="gl">
+            <require>
+                <enum name="GL_QUERY_COUNTER_BITS_ARB"/>
+                <enum name="GL_CURRENT_QUERY_ARB"/>
+                <enum name="GL_QUERY_RESULT_ARB"/>
+                <enum name="GL_QUERY_RESULT_AVAILABLE_ARB"/>
+                <enum name="GL_SAMPLES_PASSED_ARB"/>
+                <command name="glGenQueriesARB"/>
+                <command name="glDeleteQueriesARB"/>
+                <command name="glIsQueryARB"/>
+                <command name="glBeginQueryARB"/>
+                <command name="glEndQueryARB"/>
+                <command name="glGetQueryivARB"/>
+                <command name="glGetQueryObjectivARB"/>
+                <command name="glGetQueryObjectuivARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_occlusion_query2" supported="gl|glcore">
+            <require>
+                <enum name="GL_ANY_SAMPLES_PASSED"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_parallel_shader_compile" supported="gl">
+            <require>
+                <enum name="GL_MAX_SHADER_COMPILER_THREADS_ARB"/>
+                <enum name="GL_COMPLETION_STATUS_ARB"/>
+                <command name="glMaxShaderCompilerThreadsARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_pipeline_statistics_query" supported="gl|glcore">
+            <require>
+                <enum name="GL_VERTICES_SUBMITTED_ARB"/>
+                <enum name="GL_PRIMITIVES_SUBMITTED_ARB"/>
+                <enum name="GL_VERTEX_SHADER_INVOCATIONS_ARB"/>
+                <enum name="GL_TESS_CONTROL_SHADER_PATCHES_ARB"/>
+                <enum name="GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB"/>
+                <enum name="GL_GEOMETRY_SHADER_INVOCATIONS"/>
+                <enum name="GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB"/>
+                <enum name="GL_FRAGMENT_SHADER_INVOCATIONS_ARB"/>
+                <enum name="GL_COMPUTE_SHADER_INVOCATIONS_ARB"/>
+                <enum name="GL_CLIPPING_INPUT_PRIMITIVES_ARB"/>
+                <enum name="GL_CLIPPING_OUTPUT_PRIMITIVES_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_pixel_buffer_object" supported="gl">
+            <require>
+                <enum name="GL_PIXEL_PACK_BUFFER_ARB"/>
+                <enum name="GL_PIXEL_UNPACK_BUFFER_ARB"/>
+                <enum name="GL_PIXEL_PACK_BUFFER_BINDING_ARB"/>
+                <enum name="GL_PIXEL_UNPACK_BUFFER_BINDING_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_point_parameters" supported="gl">
+            <require>
+                <enum name="GL_POINT_SIZE_MIN_ARB"/>
+                <enum name="GL_POINT_SIZE_MAX_ARB"/>
+                <enum name="GL_POINT_FADE_THRESHOLD_SIZE_ARB"/>
+                <enum name="GL_POINT_DISTANCE_ATTENUATION_ARB"/>
+                <command name="glPointParameterfARB"/>
+                <command name="glPointParameterfvARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_point_sprite" supported="gl">
+            <require>
+                <enum name="GL_POINT_SPRITE_ARB"/>
+                <enum name="GL_COORD_REPLACE_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_post_depth_coverage" supported="gl"/>
+        <extension name="GL_ARB_program_interface_query" supported="gl|glcore">
+            <require>
+                <enum name="GL_UNIFORM"/>
+                <enum name="GL_UNIFORM_BLOCK"/>
+                <enum name="GL_PROGRAM_INPUT"/>
+                <enum name="GL_PROGRAM_OUTPUT"/>
+                <enum name="GL_BUFFER_VARIABLE"/>
+                <enum name="GL_SHADER_STORAGE_BLOCK"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER"/>
+                <enum name="GL_VERTEX_SUBROUTINE"/>
+                <enum name="GL_TESS_CONTROL_SUBROUTINE"/>
+                <enum name="GL_TESS_EVALUATION_SUBROUTINE"/>
+                <enum name="GL_GEOMETRY_SUBROUTINE"/>
+                <enum name="GL_FRAGMENT_SUBROUTINE"/>
+                <enum name="GL_COMPUTE_SUBROUTINE"/>
+                <enum name="GL_VERTEX_SUBROUTINE_UNIFORM"/>
+                <enum name="GL_TESS_CONTROL_SUBROUTINE_UNIFORM"/>
+                <enum name="GL_TESS_EVALUATION_SUBROUTINE_UNIFORM"/>
+                <enum name="GL_GEOMETRY_SUBROUTINE_UNIFORM"/>
+                <enum name="GL_FRAGMENT_SUBROUTINE_UNIFORM"/>
+                <enum name="GL_COMPUTE_SUBROUTINE_UNIFORM"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_VARYING"/>
+                <enum name="GL_ACTIVE_RESOURCES"/>
+                <enum name="GL_MAX_NAME_LENGTH"/>
+                <enum name="GL_MAX_NUM_ACTIVE_VARIABLES"/>
+                <enum name="GL_MAX_NUM_COMPATIBLE_SUBROUTINES"/>
+                <enum name="GL_NAME_LENGTH"/>
+                <enum name="GL_TYPE"/>
+                <enum name="GL_ARRAY_SIZE"/>
+                <enum name="GL_OFFSET"/>
+                <enum name="GL_BLOCK_INDEX"/>
+                <enum name="GL_ARRAY_STRIDE"/>
+                <enum name="GL_MATRIX_STRIDE"/>
+                <enum name="GL_IS_ROW_MAJOR"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_INDEX"/>
+                <enum name="GL_BUFFER_BINDING"/>
+                <enum name="GL_BUFFER_DATA_SIZE"/>
+                <enum name="GL_NUM_ACTIVE_VARIABLES"/>
+                <enum name="GL_ACTIVE_VARIABLES"/>
+                <enum name="GL_REFERENCED_BY_VERTEX_SHADER"/>
+                <enum name="GL_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+                <enum name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+                <enum name="GL_REFERENCED_BY_GEOMETRY_SHADER"/>
+                <enum name="GL_REFERENCED_BY_FRAGMENT_SHADER"/>
+                <enum name="GL_REFERENCED_BY_COMPUTE_SHADER"/>
+                <enum name="GL_TOP_LEVEL_ARRAY_SIZE"/>
+                <enum name="GL_TOP_LEVEL_ARRAY_STRIDE"/>
+                <enum name="GL_LOCATION"/>
+                <enum name="GL_LOCATION_INDEX"/>
+                <enum name="GL_IS_PER_PATCH"/>
+                <enum name="GL_NUM_COMPATIBLE_SUBROUTINES"/>
+                <enum name="GL_COMPATIBLE_SUBROUTINES"/>
+                <command name="glGetProgramInterfaceiv"/>
+                <command name="glGetProgramResourceIndex"/>
+                <command name="glGetProgramResourceName"/>
+                <command name="glGetProgramResourceiv"/>
+                <command name="glGetProgramResourceLocation"/>
+                <command name="glGetProgramResourceLocationIndex"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_provoking_vertex" supported="gl|glcore">
+            <require>
+                <enum name="GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION"/>
+                <enum name="GL_FIRST_VERTEX_CONVENTION"/>
+                <enum name="GL_LAST_VERTEX_CONVENTION"/>
+                <enum name="GL_PROVOKING_VERTEX"/>
+                <command name="glProvokingVertex"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_query_buffer_object" supported="gl|glcore">
+            <require>
+                <enum name="GL_QUERY_BUFFER"/>
+                <enum name="GL_QUERY_BUFFER_BARRIER_BIT"/>
+                <enum name="GL_QUERY_BUFFER_BINDING"/>
+                <enum name="GL_QUERY_RESULT_NO_WAIT"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_robust_buffer_access_behavior" supported="gl|glcore"/>
+        <extension name="GL_ARB_robustness" supported="gl|glcore">
+            <require>
+                <enum name="GL_NO_ERROR"/>
+                <enum name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB"/>
+                <enum name="GL_LOSE_CONTEXT_ON_RESET_ARB"/>
+                <enum name="GL_GUILTY_CONTEXT_RESET_ARB"/>
+                <enum name="GL_INNOCENT_CONTEXT_RESET_ARB"/>
+                <enum name="GL_UNKNOWN_CONTEXT_RESET_ARB"/>
+                <enum name="GL_RESET_NOTIFICATION_STRATEGY_ARB"/>
+                <enum name="GL_NO_RESET_NOTIFICATION_ARB"/>
+                <command name="glGetGraphicsResetStatusARB"/>
+                <command name="glGetnTexImageARB"/>
+                <command name="glReadnPixelsARB"/>
+                <command name="glGetnCompressedTexImageARB"/>
+                <command name="glGetnUniformfvARB"/>
+                <command name="glGetnUniformivARB"/>
+                <command name="glGetnUniformuivARB"/>
+                <command name="glGetnUniformdvARB"/>
+            </require>
+            <require api="gl" profile="compatibility">
+                <command name="glGetnMapdvARB"/>
+                <command name="glGetnMapfvARB"/>
+                <command name="glGetnMapivARB"/>
+                <command name="glGetnPixelMapfvARB"/>
+                <command name="glGetnPixelMapuivARB"/>
+                <command name="glGetnPixelMapusvARB"/>
+                <command name="glGetnPolygonStippleARB"/>
+                <command name="glGetnColorTableARB"/>
+                <command name="glGetnConvolutionFilterARB"/>
+                <command name="glGetnSeparableFilterARB"/>
+                <command name="glGetnHistogramARB"/>
+                <command name="glGetnMinmaxARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_robustness_isolation" supported="gl|glcore"/>
+        <extension name="GL_ARB_sample_locations" supported="gl">
+            <require>
+                <enum name="GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB"/>
+                <enum name="GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB"/>
+                <enum name="GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB"/>
+                <enum name="GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB"/>
+                <enum name="GL_SAMPLE_LOCATION_ARB"/>
+                <enum name="GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB"/>
+                <enum name="GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB"/>
+                <enum name="GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB"/>
+                <command name="glFramebufferSampleLocationsfvARB"/>
+                <command name="glNamedFramebufferSampleLocationsfvARB"/>
+                <command name="glEvaluateDepthValuesARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_sample_shading" supported="gl|glcore">
+            <require>
+                <enum name="GL_SAMPLE_SHADING_ARB"/>
+                <enum name="GL_MIN_SAMPLE_SHADING_VALUE_ARB"/>
+                <command name="glMinSampleShadingARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_sampler_objects" supported="gl|glcore">
+            <require>
+                <enum name="GL_SAMPLER_BINDING"/>
+                <command name="glGenSamplers"/>
+                <command name="glDeleteSamplers"/>
+                <command name="glIsSampler"/>
+                <command name="glBindSampler"/>
+                <command name="glSamplerParameteri"/>
+                <command name="glSamplerParameteriv"/>
+                <command name="glSamplerParameterf"/>
+                <command name="glSamplerParameterfv"/>
+                <command name="glSamplerParameterIiv"/>
+                <command name="glSamplerParameterIuiv"/>
+                <command name="glGetSamplerParameteriv"/>
+                <command name="glGetSamplerParameterIiv"/>
+                <command name="glGetSamplerParameterfv"/>
+                <command name="glGetSamplerParameterIuiv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_seamless_cube_map" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_CUBE_MAP_SEAMLESS"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_seamless_cubemap_per_texture" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_CUBE_MAP_SEAMLESS"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_separate_shader_objects" supported="gl|glcore">
+            <require>
+                <enum name="GL_VERTEX_SHADER_BIT"/>
+                <enum name="GL_FRAGMENT_SHADER_BIT"/>
+                <enum name="GL_GEOMETRY_SHADER_BIT"/>
+                <enum name="GL_TESS_CONTROL_SHADER_BIT"/>
+                <enum name="GL_TESS_EVALUATION_SHADER_BIT"/>
+                <enum name="GL_ALL_SHADER_BITS"/>
+                <enum name="GL_PROGRAM_SEPARABLE"/>
+                <enum name="GL_ACTIVE_PROGRAM"/>
+                <enum name="GL_PROGRAM_PIPELINE_BINDING"/>
+                <command name="glUseProgramStages"/>
+                <command name="glActiveShaderProgram"/>
+                <command name="glCreateShaderProgramv"/>
+                <command name="glBindProgramPipeline"/>
+                <command name="glDeleteProgramPipelines"/>
+                <command name="glGenProgramPipelines"/>
+                <command name="glIsProgramPipeline"/>
+                <command name="glGetProgramPipelineiv"/>
+                <command name="glProgramUniform1i"/>
+                <command name="glProgramUniform1iv"/>
+                <command name="glProgramUniform1f"/>
+                <command name="glProgramUniform1fv"/>
+                <command name="glProgramUniform1d"/>
+                <command name="glProgramUniform1dv"/>
+                <command name="glProgramUniform1ui"/>
+                <command name="glProgramUniform1uiv"/>
+                <command name="glProgramUniform2i"/>
+                <command name="glProgramUniform2iv"/>
+                <command name="glProgramUniform2f"/>
+                <command name="glProgramUniform2fv"/>
+                <command name="glProgramUniform2d"/>
+                <command name="glProgramUniform2dv"/>
+                <command name="glProgramUniform2ui"/>
+                <command name="glProgramUniform2uiv"/>
+                <command name="glProgramUniform3i"/>
+                <command name="glProgramUniform3iv"/>
+                <command name="glProgramUniform3f"/>
+                <command name="glProgramUniform3fv"/>
+                <command name="glProgramUniform3d"/>
+                <command name="glProgramUniform3dv"/>
+                <command name="glProgramUniform3ui"/>
+                <command name="glProgramUniform3uiv"/>
+                <command name="glProgramUniform4i"/>
+                <command name="glProgramUniform4iv"/>
+                <command name="glProgramUniform4f"/>
+                <command name="glProgramUniform4fv"/>
+                <command name="glProgramUniform4d"/>
+                <command name="glProgramUniform4dv"/>
+                <command name="glProgramUniform4ui"/>
+                <command name="glProgramUniform4uiv"/>
+                <command name="glProgramUniformMatrix2fv"/>
+                <command name="glProgramUniformMatrix3fv"/>
+                <command name="glProgramUniformMatrix4fv"/>
+                <command name="glProgramUniformMatrix2dv"/>
+                <command name="glProgramUniformMatrix3dv"/>
+                <command name="glProgramUniformMatrix4dv"/>
+                <command name="glProgramUniformMatrix2x3fv"/>
+                <command name="glProgramUniformMatrix3x2fv"/>
+                <command name="glProgramUniformMatrix2x4fv"/>
+                <command name="glProgramUniformMatrix4x2fv"/>
+                <command name="glProgramUniformMatrix3x4fv"/>
+                <command name="glProgramUniformMatrix4x3fv"/>
+                <command name="glProgramUniformMatrix2x3dv"/>
+                <command name="glProgramUniformMatrix3x2dv"/>
+                <command name="glProgramUniformMatrix2x4dv"/>
+                <command name="glProgramUniformMatrix4x2dv"/>
+                <command name="glProgramUniformMatrix3x4dv"/>
+                <command name="glProgramUniformMatrix4x3dv"/>
+                <command name="glValidateProgramPipeline"/>
+                <command name="glGetProgramPipelineInfoLog"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_shader_atomic_counter_ops" supported="gl"/>
+        <extension name="GL_ARB_shader_atomic_counters" supported="gl|glcore">
+            <require>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_BINDING"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_START"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_SIZE"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER"/>
+                <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER"/>
+                <enum name="GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS"/>
+                <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS"/>
+                <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS"/>
+                <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS"/>
+                <enum name="GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS"/>
+                <enum name="GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS"/>
+                <enum name="GL_MAX_VERTEX_ATOMIC_COUNTERS"/>
+                <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"/>
+                <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"/>
+                <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS"/>
+                <enum name="GL_MAX_FRAGMENT_ATOMIC_COUNTERS"/>
+                <enum name="GL_MAX_COMBINED_ATOMIC_COUNTERS"/>
+                <enum name="GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE"/>
+                <enum name="GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS"/>
+                <enum name="GL_ACTIVE_ATOMIC_COUNTER_BUFFERS"/>
+                <enum name="GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX"/>
+                <enum name="GL_UNSIGNED_INT_ATOMIC_COUNTER"/>
+                <command name="glGetActiveAtomicCounterBufferiv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_shader_ballot" supported="gl"/>
+        <extension name="GL_ARB_shader_bit_encoding" supported="gl|glcore"/>
+        <extension name="GL_ARB_shader_clock" supported="gl"/>
+        <extension name="GL_ARB_shader_draw_parameters" supported="gl|glcore"/>
+        <extension name="GL_ARB_shader_group_vote" supported="gl|glcore"/>
+        <extension name="GL_ARB_shader_image_load_store" supported="gl|glcore">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT"/>
+                <enum name="GL_ELEMENT_ARRAY_BARRIER_BIT"/>
+                <enum name="GL_UNIFORM_BARRIER_BIT"/>
+                <enum name="GL_TEXTURE_FETCH_BARRIER_BIT"/>
+                <enum name="GL_SHADER_IMAGE_ACCESS_BARRIER_BIT"/>
+                <enum name="GL_COMMAND_BARRIER_BIT"/>
+                <enum name="GL_PIXEL_BUFFER_BARRIER_BIT"/>
+                <enum name="GL_TEXTURE_UPDATE_BARRIER_BIT"/>
+                <enum name="GL_BUFFER_UPDATE_BARRIER_BIT"/>
+                <enum name="GL_FRAMEBUFFER_BARRIER_BIT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BARRIER_BIT"/>
+                <enum name="GL_ATOMIC_COUNTER_BARRIER_BIT"/>
+                <enum name="GL_ALL_BARRIER_BITS"/>
+                <enum name="GL_MAX_IMAGE_UNITS"/>
+                <enum name="GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS"/>
+                <enum name="GL_IMAGE_BINDING_NAME"/>
+                <enum name="GL_IMAGE_BINDING_LEVEL"/>
+                <enum name="GL_IMAGE_BINDING_LAYERED"/>
+                <enum name="GL_IMAGE_BINDING_LAYER"/>
+                <enum name="GL_IMAGE_BINDING_ACCESS"/>
+                <enum name="GL_IMAGE_1D"/>
+                <enum name="GL_IMAGE_2D"/>
+                <enum name="GL_IMAGE_3D"/>
+                <enum name="GL_IMAGE_2D_RECT"/>
+                <enum name="GL_IMAGE_CUBE"/>
+                <enum name="GL_IMAGE_BUFFER"/>
+                <enum name="GL_IMAGE_1D_ARRAY"/>
+                <enum name="GL_IMAGE_2D_ARRAY"/>
+                <enum name="GL_IMAGE_CUBE_MAP_ARRAY"/>
+                <enum name="GL_IMAGE_2D_MULTISAMPLE"/>
+                <enum name="GL_IMAGE_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_INT_IMAGE_1D"/>
+                <enum name="GL_INT_IMAGE_2D"/>
+                <enum name="GL_INT_IMAGE_3D"/>
+                <enum name="GL_INT_IMAGE_2D_RECT"/>
+                <enum name="GL_INT_IMAGE_CUBE"/>
+                <enum name="GL_INT_IMAGE_BUFFER"/>
+                <enum name="GL_INT_IMAGE_1D_ARRAY"/>
+                <enum name="GL_INT_IMAGE_2D_ARRAY"/>
+                <enum name="GL_INT_IMAGE_CUBE_MAP_ARRAY"/>
+                <enum name="GL_INT_IMAGE_2D_MULTISAMPLE"/>
+                <enum name="GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_1D"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_3D"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D_RECT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_CUBE"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_BUFFER"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_1D_ARRAY"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D_ARRAY"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_MAX_IMAGE_SAMPLES"/>
+                <enum name="GL_IMAGE_BINDING_FORMAT"/>
+                <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_TYPE"/>
+                <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE"/>
+                <enum name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS"/>
+                <enum name="GL_MAX_VERTEX_IMAGE_UNIFORMS"/>
+                <enum name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS"/>
+                <enum name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS"/>
+                <enum name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS"/>
+                <enum name="GL_MAX_FRAGMENT_IMAGE_UNIFORMS"/>
+                <enum name="GL_MAX_COMBINED_IMAGE_UNIFORMS"/>
+                <command name="glBindImageTexture"/>
+                <command name="glMemoryBarrier"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_shader_image_size" supported="gl|glcore"/>
+        <extension name="GL_ARB_shader_objects" supported="gl">
+            <require>
+                <enum name="GL_PROGRAM_OBJECT_ARB"/>
+                <enum name="GL_SHADER_OBJECT_ARB"/>
+                <enum name="GL_OBJECT_TYPE_ARB"/>
+                <enum name="GL_OBJECT_SUBTYPE_ARB"/>
+                <enum name="GL_FLOAT_VEC2_ARB"/>
+                <enum name="GL_FLOAT_VEC3_ARB"/>
+                <enum name="GL_FLOAT_VEC4_ARB"/>
+                <enum name="GL_INT_VEC2_ARB"/>
+                <enum name="GL_INT_VEC3_ARB"/>
+                <enum name="GL_INT_VEC4_ARB"/>
+                <enum name="GL_BOOL_ARB"/>
+                <enum name="GL_BOOL_VEC2_ARB"/>
+                <enum name="GL_BOOL_VEC3_ARB"/>
+                <enum name="GL_BOOL_VEC4_ARB"/>
+                <enum name="GL_FLOAT_MAT2_ARB"/>
+                <enum name="GL_FLOAT_MAT3_ARB"/>
+                <enum name="GL_FLOAT_MAT4_ARB"/>
+                <enum name="GL_SAMPLER_1D_ARB"/>
+                <enum name="GL_SAMPLER_2D_ARB"/>
+                <enum name="GL_SAMPLER_3D_ARB"/>
+                <enum name="GL_SAMPLER_CUBE_ARB"/>
+                <enum name="GL_SAMPLER_1D_SHADOW_ARB"/>
+                <enum name="GL_SAMPLER_2D_SHADOW_ARB"/>
+                <enum name="GL_SAMPLER_2D_RECT_ARB"/>
+                <enum name="GL_SAMPLER_2D_RECT_SHADOW_ARB"/>
+                <enum name="GL_OBJECT_DELETE_STATUS_ARB"/>
+                <enum name="GL_OBJECT_COMPILE_STATUS_ARB"/>
+                <enum name="GL_OBJECT_LINK_STATUS_ARB"/>
+                <enum name="GL_OBJECT_VALIDATE_STATUS_ARB"/>
+                <enum name="GL_OBJECT_INFO_LOG_LENGTH_ARB"/>
+                <enum name="GL_OBJECT_ATTACHED_OBJECTS_ARB"/>
+                <enum name="GL_OBJECT_ACTIVE_UNIFORMS_ARB"/>
+                <enum name="GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB"/>
+                <enum name="GL_OBJECT_SHADER_SOURCE_LENGTH_ARB"/>
+                <command name="glDeleteObjectARB"/>
+                <command name="glGetHandleARB"/>
+                <command name="glDetachObjectARB"/>
+                <command name="glCreateShaderObjectARB"/>
+                <command name="glShaderSourceARB"/>
+                <command name="glCompileShaderARB"/>
+                <command name="glCreateProgramObjectARB"/>
+                <command name="glAttachObjectARB"/>
+                <command name="glLinkProgramARB"/>
+                <command name="glUseProgramObjectARB"/>
+                <command name="glValidateProgramARB"/>
+                <command name="glUniform1fARB"/>
+                <command name="glUniform2fARB"/>
+                <command name="glUniform3fARB"/>
+                <command name="glUniform4fARB"/>
+                <command name="glUniform1iARB"/>
+                <command name="glUniform2iARB"/>
+                <command name="glUniform3iARB"/>
+                <command name="glUniform4iARB"/>
+                <command name="glUniform1fvARB"/>
+                <command name="glUniform2fvARB"/>
+                <command name="glUniform3fvARB"/>
+                <command name="glUniform4fvARB"/>
+                <command name="glUniform1ivARB"/>
+                <command name="glUniform2ivARB"/>
+                <command name="glUniform3ivARB"/>
+                <command name="glUniform4ivARB"/>
+                <command name="glUniformMatrix2fvARB"/>
+                <command name="glUniformMatrix3fvARB"/>
+                <command name="glUniformMatrix4fvARB"/>
+                <command name="glGetObjectParameterfvARB"/>
+                <command name="glGetObjectParameterivARB"/>
+                <command name="glGetInfoLogARB"/>
+                <command name="glGetAttachedObjectsARB"/>
+                <command name="glGetUniformLocationARB"/>
+                <command name="glGetActiveUniformARB"/>
+                <command name="glGetUniformfvARB"/>
+                <command name="glGetUniformivARB"/>
+                <command name="glGetShaderSourceARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_shader_precision" supported="gl|glcore"/>
+        <extension name="GL_ARB_shader_stencil_export" supported="gl|glcore"/>
+        <extension name="GL_ARB_shader_storage_buffer_object" supported="gl|glcore">
+            <require>
+                <enum name="GL_SHADER_STORAGE_BUFFER"/>
+                <enum name="GL_SHADER_STORAGE_BUFFER_BINDING"/>
+                <enum name="GL_SHADER_STORAGE_BUFFER_START"/>
+                <enum name="GL_SHADER_STORAGE_BUFFER_SIZE"/>
+                <enum name="GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS"/>
+                <enum name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS"/>
+                <enum name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS"/>
+                <enum name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS"/>
+                <enum name="GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS"/>
+                <enum name="GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"/>
+                <enum name="GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS"/>
+                <enum name="GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS"/>
+                <enum name="GL_MAX_SHADER_STORAGE_BLOCK_SIZE"/>
+                <enum name="GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT"/>
+                <enum name="GL_SHADER_STORAGE_BARRIER_BIT"/>
+                <enum name="GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES"/>
+                <enum name="GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS"/>
+                <command name="glShaderStorageBlockBinding"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_shader_subroutine" supported="gl|glcore">
+            <require>
+                <enum name="GL_ACTIVE_SUBROUTINES"/>
+                <enum name="GL_ACTIVE_SUBROUTINE_UNIFORMS"/>
+                <enum name="GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"/>
+                <enum name="GL_ACTIVE_SUBROUTINE_MAX_LENGTH"/>
+                <enum name="GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"/>
+                <enum name="GL_MAX_SUBROUTINES"/>
+                <enum name="GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS"/>
+                <enum name="GL_NUM_COMPATIBLE_SUBROUTINES"/>
+                <enum name="GL_COMPATIBLE_SUBROUTINES"/>
+                <enum name="GL_UNIFORM_SIZE"/>
+                <enum name="GL_UNIFORM_NAME_LENGTH"/>
+                <command name="glGetSubroutineUniformLocation"/>
+                <command name="glGetSubroutineIndex"/>
+                <command name="glGetActiveSubroutineUniformiv"/>
+                <command name="glGetActiveSubroutineUniformName"/>
+                <command name="glGetActiveSubroutineName"/>
+                <command name="glUniformSubroutinesuiv"/>
+                <command name="glGetUniformSubroutineuiv"/>
+                <command name="glGetProgramStageiv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_shader_texture_image_samples" supported="gl|glcore"/>
+        <extension name="GL_ARB_shader_texture_lod" supported="gl"/>
+        <extension name="GL_ARB_shader_viewport_layer_array" supported="gl"/>
+        <extension name="GL_ARB_shading_language_100" supported="gl">
+            <require>
+                <enum name="GL_SHADING_LANGUAGE_VERSION_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_shading_language_420pack" supported="gl|glcore"/>
+        <extension name="GL_ARB_shading_language_include" supported="gl|glcore">
+            <require>
+                <enum name="GL_SHADER_INCLUDE_ARB"/>
+                <enum name="GL_NAMED_STRING_LENGTH_ARB"/>
+                <enum name="GL_NAMED_STRING_TYPE_ARB"/>
+                <command name="glNamedStringARB"/>
+                <command name="glDeleteNamedStringARB"/>
+                <command name="glCompileShaderIncludeARB"/>
+                <command name="glIsNamedStringARB"/>
+                <command name="glGetNamedStringARB"/>
+                <command name="glGetNamedStringivARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_shading_language_packing" supported="gl|glcore"/>
+        <extension name="GL_ARB_shadow" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_COMPARE_MODE_ARB"/>
+                <enum name="GL_TEXTURE_COMPARE_FUNC_ARB"/>
+                <enum name="GL_COMPARE_R_TO_TEXTURE_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_shadow_ambient" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_COMPARE_FAIL_VALUE_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_sparse_buffer" supported="gl|glcore">
+            <require>
+                <enum name="GL_SPARSE_STORAGE_BIT_ARB"/>
+                <enum name="GL_SPARSE_BUFFER_PAGE_SIZE_ARB"/>
+                <command name="glBufferPageCommitmentARB"/>
+            </require>
+            <require comment="Supported only if GL_EXT_direct_state_access is supported">
+                <command name="glNamedBufferPageCommitmentEXT"/>
+            </require>
+            <require comment="Supported only if GL_ARb_direct_state_access or GL 4.5 is supported">
+                <command name="glNamedBufferPageCommitmentARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_sparse_texture" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_SPARSE_ARB"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_INDEX_ARB"/>
+                <enum name="GL_NUM_SPARSE_LEVELS_ARB"/>
+                <enum name="GL_NUM_VIRTUAL_PAGE_SIZES_ARB"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_X_ARB"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_Y_ARB"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_Z_ARB"/>
+                <enum name="GL_MAX_SPARSE_TEXTURE_SIZE_ARB"/>
+                <enum name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB"/>
+                <enum name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB"/>
+                <enum name="GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB"/>
+                <command name="glTexPageCommitmentARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_sparse_texture2" supported="gl|glcore|gles2"/>
+        <extension name="GL_ARB_sparse_texture_clamp" supported="gl"/>
+        <extension name="GL_ARB_stencil_texturing" supported="gl|glcore">
+            <require>
+                <enum name="GL_DEPTH_STENCIL_TEXTURE_MODE"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_sync" supported="gl|glcore">
+            <require>
+                <enum name="GL_MAX_SERVER_WAIT_TIMEOUT"/>
+                <enum name="GL_OBJECT_TYPE"/>
+                <enum name="GL_SYNC_CONDITION"/>
+                <enum name="GL_SYNC_STATUS"/>
+                <enum name="GL_SYNC_FLAGS"/>
+                <enum name="GL_SYNC_FENCE"/>
+                <enum name="GL_SYNC_GPU_COMMANDS_COMPLETE"/>
+                <enum name="GL_UNSIGNALED"/>
+                <enum name="GL_SIGNALED"/>
+                <enum name="GL_ALREADY_SIGNALED"/>
+                <enum name="GL_TIMEOUT_EXPIRED"/>
+                <enum name="GL_CONDITION_SATISFIED"/>
+                <enum name="GL_WAIT_FAILED"/>
+                <enum name="GL_SYNC_FLUSH_COMMANDS_BIT"/>
+                <enum name="GL_TIMEOUT_IGNORED"/>
+                <command name="glFenceSync"/>
+                <command name="glIsSync"/>
+                <command name="glDeleteSync"/>
+                <command name="glClientWaitSync"/>
+                <command name="glWaitSync"/>
+                <command name="glGetInteger64v"/>
+                <command name="glGetSynciv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_tessellation_shader" supported="gl|glcore">
+            <require>
+                <enum name="GL_PATCHES"/>
+                <enum name="GL_PATCH_VERTICES"/>
+                <enum name="GL_PATCH_DEFAULT_INNER_LEVEL"/>
+                <enum name="GL_PATCH_DEFAULT_OUTER_LEVEL"/>
+                <enum name="GL_TESS_CONTROL_OUTPUT_VERTICES"/>
+                <enum name="GL_TESS_GEN_MODE"/>
+                <enum name="GL_TESS_GEN_SPACING"/>
+                <enum name="GL_TESS_GEN_VERTEX_ORDER"/>
+                <enum name="GL_TESS_GEN_POINT_MODE"/>
+                <enum name="GL_TRIANGLES"/>
+                <enum name="GL_ISOLINES"/>
+                <enum name="GL_QUADS"/>
+                <enum name="GL_EQUAL"/>
+                <enum name="GL_FRACTIONAL_ODD"/>
+                <enum name="GL_FRACTIONAL_EVEN"/>
+                <enum name="GL_CCW"/>
+                <enum name="GL_CW"/>
+                <enum name="GL_MAX_PATCH_VERTICES"/>
+                <enum name="GL_MAX_TESS_GEN_LEVEL"/>
+                <enum name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+                <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+                <enum name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS"/>
+                <enum name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS"/>
+                <enum name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS"/>
+                <enum name="GL_MAX_TESS_PATCH_COMPONENTS"/>
+                <enum name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS"/>
+                <enum name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS"/>
+                <enum name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS"/>
+                <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS"/>
+                <enum name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS"/>
+                <enum name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS"/>
+                <enum name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+                <enum name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+                <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+                <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+                <enum name="GL_TESS_EVALUATION_SHADER"/>
+                <enum name="GL_TESS_CONTROL_SHADER"/>
+                <command name="glPatchParameteri"/>
+                <command name="glPatchParameterfv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_barrier" supported="gl|glcore">
+            <require>
+                <command name="glTextureBarrier"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_border_clamp" supported="gl">
+            <require>
+                <enum name="GL_CLAMP_TO_BORDER_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_buffer_object" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_BUFFER_ARB"/>
+                <enum name="GL_MAX_TEXTURE_BUFFER_SIZE_ARB"/>
+                <enum name="GL_TEXTURE_BINDING_BUFFER_ARB"/>
+                <enum name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB"/>
+                <enum name="GL_TEXTURE_BUFFER_FORMAT_ARB"/>
+                <command name="glTexBufferARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_buffer_object_rgb32" supported="gl|glcore">
+            <require>
+                <enum name="GL_RGB32F"/>
+                <enum name="GL_RGB32UI"/>
+                <enum name="GL_RGB32I"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_buffer_range" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_BUFFER_OFFSET"/>
+                <enum name="GL_TEXTURE_BUFFER_SIZE"/>
+                <enum name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT"/>
+                <command name="glTexBufferRange"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_compression" supported="gl">
+            <require>
+                <enum name="GL_COMPRESSED_ALPHA_ARB"/>
+                <enum name="GL_COMPRESSED_LUMINANCE_ARB"/>
+                <enum name="GL_COMPRESSED_LUMINANCE_ALPHA_ARB"/>
+                <enum name="GL_COMPRESSED_INTENSITY_ARB"/>
+                <enum name="GL_COMPRESSED_RGB_ARB"/>
+                <enum name="GL_COMPRESSED_RGBA_ARB"/>
+                <enum name="GL_TEXTURE_COMPRESSION_HINT_ARB"/>
+                <enum name="GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB"/>
+                <enum name="GL_TEXTURE_COMPRESSED_ARB"/>
+                <enum name="GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB"/>
+                <enum name="GL_COMPRESSED_TEXTURE_FORMATS_ARB"/>
+                <command name="glCompressedTexImage3DARB"/>
+                <command name="glCompressedTexImage2DARB"/>
+                <command name="glCompressedTexImage1DARB"/>
+                <command name="glCompressedTexSubImage3DARB"/>
+                <command name="glCompressedTexSubImage2DARB"/>
+                <command name="glCompressedTexSubImage1DARB"/>
+                <command name="glGetCompressedTexImageARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_compression_bptc" supported="gl|glcore">
+            <require>
+                <enum name="GL_COMPRESSED_RGBA_BPTC_UNORM_ARB"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB"/>
+                <enum name="GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB"/>
+                <enum name="GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_compression_rgtc" supported="gl|glcore">
+            <require>
+                <enum name="GL_COMPRESSED_RED_RGTC1"/>
+                <enum name="GL_COMPRESSED_SIGNED_RED_RGTC1"/>
+                <enum name="GL_COMPRESSED_RG_RGTC2"/>
+                <enum name="GL_COMPRESSED_SIGNED_RG_RGTC2"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_cube_map" supported="gl">
+            <require>
+                <enum name="GL_NORMAL_MAP_ARB"/>
+                <enum name="GL_REFLECTION_MAP_ARB"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_ARB"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARB"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB"/>
+                <enum name="GL_PROXY_TEXTURE_CUBE_MAP_ARB"/>
+                <enum name="GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_cube_map_array" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_CUBE_MAP_ARRAY_ARB"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB"/>
+                <enum name="GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB"/>
+                <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_ARB"/>
+                <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB"/>
+                <enum name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_env_add" supported="gl"/>
+        <extension name="GL_ARB_texture_env_combine" supported="gl">
+            <require>
+                <enum name="GL_COMBINE_ARB"/>
+                <enum name="GL_COMBINE_RGB_ARB"/>
+                <enum name="GL_COMBINE_ALPHA_ARB"/>
+                <enum name="GL_SOURCE0_RGB_ARB"/>
+                <enum name="GL_SOURCE1_RGB_ARB"/>
+                <enum name="GL_SOURCE2_RGB_ARB"/>
+                <enum name="GL_SOURCE0_ALPHA_ARB"/>
+                <enum name="GL_SOURCE1_ALPHA_ARB"/>
+                <enum name="GL_SOURCE2_ALPHA_ARB"/>
+                <enum name="GL_OPERAND0_RGB_ARB"/>
+                <enum name="GL_OPERAND1_RGB_ARB"/>
+                <enum name="GL_OPERAND2_RGB_ARB"/>
+                <enum name="GL_OPERAND0_ALPHA_ARB"/>
+                <enum name="GL_OPERAND1_ALPHA_ARB"/>
+                <enum name="GL_OPERAND2_ALPHA_ARB"/>
+                <enum name="GL_RGB_SCALE_ARB"/>
+                <enum name="GL_ADD_SIGNED_ARB"/>
+                <enum name="GL_INTERPOLATE_ARB"/>
+                <enum name="GL_SUBTRACT_ARB"/>
+                <enum name="GL_CONSTANT_ARB"/>
+                <enum name="GL_PRIMARY_COLOR_ARB"/>
+                <enum name="GL_PREVIOUS_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_env_crossbar" supported="gl"/>
+        <extension name="GL_ARB_texture_env_dot3" supported="gl">
+            <require>
+                <enum name="GL_DOT3_RGB_ARB"/>
+                <enum name="GL_DOT3_RGBA_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_filter_minmax" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_REDUCTION_MODE_ARB"/>
+                <enum name="GL_WEIGHTED_AVERAGE_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_float" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_RED_TYPE_ARB"/>
+                <enum name="GL_TEXTURE_GREEN_TYPE_ARB"/>
+                <enum name="GL_TEXTURE_BLUE_TYPE_ARB"/>
+                <enum name="GL_TEXTURE_ALPHA_TYPE_ARB"/>
+                <enum name="GL_TEXTURE_LUMINANCE_TYPE_ARB"/>
+                <enum name="GL_TEXTURE_INTENSITY_TYPE_ARB"/>
+                <enum name="GL_TEXTURE_DEPTH_TYPE_ARB"/>
+                <enum name="GL_UNSIGNED_NORMALIZED_ARB"/>
+                <enum name="GL_RGBA32F_ARB"/>
+                <enum name="GL_RGB32F_ARB"/>
+                <enum name="GL_ALPHA32F_ARB"/>
+                <enum name="GL_INTENSITY32F_ARB"/>
+                <enum name="GL_LUMINANCE32F_ARB"/>
+                <enum name="GL_LUMINANCE_ALPHA32F_ARB"/>
+                <enum name="GL_RGBA16F_ARB"/>
+                <enum name="GL_RGB16F_ARB"/>
+                <enum name="GL_ALPHA16F_ARB"/>
+                <enum name="GL_INTENSITY16F_ARB"/>
+                <enum name="GL_LUMINANCE16F_ARB"/>
+                <enum name="GL_LUMINANCE_ALPHA16F_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_gather" supported="gl|glcore">
+            <require>
+                <enum name="GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB"/>
+                <enum name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB"/>
+                <enum name="GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_mirror_clamp_to_edge" supported="gl|glcore">
+            <require>
+                <enum name="GL_MIRROR_CLAMP_TO_EDGE"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_mirrored_repeat" supported="gl">
+            <require>
+                <enum name="GL_MIRRORED_REPEAT_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_multisample" supported="gl|glcore">
+            <require>
+                <enum name="GL_SAMPLE_POSITION"/>
+                <enum name="GL_SAMPLE_MASK"/>
+                <enum name="GL_SAMPLE_MASK_VALUE"/>
+                <enum name="GL_MAX_SAMPLE_MASK_WORDS"/>
+                <enum name="GL_TEXTURE_2D_MULTISAMPLE"/>
+                <enum name="GL_PROXY_TEXTURE_2D_MULTISAMPLE"/>
+                <enum name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE"/>
+                <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_TEXTURE_SAMPLES"/>
+                <enum name="GL_TEXTURE_FIXED_SAMPLE_LOCATIONS"/>
+                <enum name="GL_SAMPLER_2D_MULTISAMPLE"/>
+                <enum name="GL_INT_SAMPLER_2D_MULTISAMPLE"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE"/>
+                <enum name="GL_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_MAX_COLOR_TEXTURE_SAMPLES"/>
+                <enum name="GL_MAX_DEPTH_TEXTURE_SAMPLES"/>
+                <enum name="GL_MAX_INTEGER_SAMPLES"/>
+                <command name="glTexImage2DMultisample"/>
+                <command name="glTexImage3DMultisample"/>
+                <command name="glGetMultisamplefv"/>
+                <command name="glSampleMaski"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_non_power_of_two" supported="gl"/>
+        <extension name="GL_ARB_texture_query_levels" supported="gl|glcore"/>
+        <extension name="GL_ARB_texture_query_lod" supported="gl|glcore"/>
+        <extension name="GL_ARB_texture_rectangle" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_RECTANGLE_ARB"/>
+                <enum name="GL_TEXTURE_BINDING_RECTANGLE_ARB"/>
+                <enum name="GL_PROXY_TEXTURE_RECTANGLE_ARB"/>
+                <enum name="GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_rg" supported="gl|glcore">
+            <require>
+                <enum name="GL_RG"/>
+                <enum name="GL_RG_INTEGER"/>
+                <enum name="GL_R8"/>
+                <enum name="GL_R16"/>
+                <enum name="GL_RG8"/>
+                <enum name="GL_RG16"/>
+                <enum name="GL_R16F"/>
+                <enum name="GL_R32F"/>
+                <enum name="GL_RG16F"/>
+                <enum name="GL_RG32F"/>
+                <enum name="GL_R8I"/>
+                <enum name="GL_R8UI"/>
+                <enum name="GL_R16I"/>
+                <enum name="GL_R16UI"/>
+                <enum name="GL_R32I"/>
+                <enum name="GL_R32UI"/>
+                <enum name="GL_RG8I"/>
+                <enum name="GL_RG8UI"/>
+                <enum name="GL_RG16I"/>
+                <enum name="GL_RG16UI"/>
+                <enum name="GL_RG32I"/>
+                <enum name="GL_RG32UI"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_rgb10_a2ui" supported="gl|glcore">
+            <require>
+                <enum name="GL_RGB10_A2UI"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_stencil8" supported="gl|glcore">
+            <require>
+                <enum name="GL_STENCIL_INDEX"/>
+                <enum name="GL_STENCIL_INDEX8"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_storage" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_IMMUTABLE_FORMAT"/>
+                <command name="glTexStorage1D"/>
+                <command name="glTexStorage2D"/>
+                <command name="glTexStorage3D"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_storage_multisample" supported="gl|glcore">
+            <require>
+                <command name="glTexStorage2DMultisample"/>
+                <command name="glTexStorage3DMultisample"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_swizzle" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_SWIZZLE_R"/>
+                <enum name="GL_TEXTURE_SWIZZLE_G"/>
+                <enum name="GL_TEXTURE_SWIZZLE_B"/>
+                <enum name="GL_TEXTURE_SWIZZLE_A"/>
+                <enum name="GL_TEXTURE_SWIZZLE_RGBA"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_texture_view" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_VIEW_MIN_LEVEL"/>
+                <enum name="GL_TEXTURE_VIEW_NUM_LEVELS"/>
+                <enum name="GL_TEXTURE_VIEW_MIN_LAYER"/>
+                <enum name="GL_TEXTURE_VIEW_NUM_LAYERS"/>
+                <enum name="GL_TEXTURE_IMMUTABLE_LEVELS"/>
+                <command name="glTextureView"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_timer_query" supported="gl|glcore">
+            <require>
+                <enum name="GL_TIME_ELAPSED"/>
+                <enum name="GL_TIMESTAMP"/>
+                <command name="glQueryCounter"/>
+                <command name="glGetQueryObjecti64v"/>
+                <command name="glGetQueryObjectui64v"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_transform_feedback2" supported="gl|glcore">
+            <require>
+                <enum name="GL_TRANSFORM_FEEDBACK"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BINDING"/>
+                <command name="glBindTransformFeedback"/>
+                <command name="glDeleteTransformFeedbacks"/>
+                <command name="glGenTransformFeedbacks"/>
+                <command name="glIsTransformFeedback"/>
+                <command name="glPauseTransformFeedback"/>
+                <command name="glResumeTransformFeedback"/>
+                <command name="glDrawTransformFeedback"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_transform_feedback3" supported="gl|glcore">
+            <require>
+                <enum name="GL_MAX_TRANSFORM_FEEDBACK_BUFFERS"/>
+                <enum name="GL_MAX_VERTEX_STREAMS"/>
+                <command name="glDrawTransformFeedbackStream"/>
+                <command name="glBeginQueryIndexed"/>
+                <command name="glEndQueryIndexed"/>
+                <command name="glGetQueryIndexediv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_transform_feedback_instanced" supported="gl|glcore">
+            <require>
+                <command name="glDrawTransformFeedbackInstanced"/>
+                <command name="glDrawTransformFeedbackStreamInstanced"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_transform_feedback_overflow_query" supported="gl|glcore">
+            <require>
+                <enum name="GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_transpose_matrix" supported="gl">
+            <require>
+                <enum name="GL_TRANSPOSE_MODELVIEW_MATRIX_ARB"/>
+                <enum name="GL_TRANSPOSE_PROJECTION_MATRIX_ARB"/>
+                <enum name="GL_TRANSPOSE_TEXTURE_MATRIX_ARB"/>
+                <enum name="GL_TRANSPOSE_COLOR_MATRIX_ARB"/>
+                <command name="glLoadTransposeMatrixfARB"/>
+                <command name="glLoadTransposeMatrixdARB"/>
+                <command name="glMultTransposeMatrixfARB"/>
+                <command name="glMultTransposeMatrixdARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_uniform_buffer_object" supported="gl|glcore">
+            <require>
+                <enum name="GL_UNIFORM_BUFFER"/>
+                <enum name="GL_UNIFORM_BUFFER_BINDING"/>
+                <enum name="GL_UNIFORM_BUFFER_START"/>
+                <enum name="GL_UNIFORM_BUFFER_SIZE"/>
+                <enum name="GL_MAX_VERTEX_UNIFORM_BLOCKS"/>
+                <enum name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS"/>
+                <enum name="GL_MAX_FRAGMENT_UNIFORM_BLOCKS"/>
+                <enum name="GL_MAX_COMBINED_UNIFORM_BLOCKS"/>
+                <enum name="GL_MAX_UNIFORM_BUFFER_BINDINGS"/>
+                <enum name="GL_MAX_UNIFORM_BLOCK_SIZE"/>
+                <enum name="GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS"/>
+                <enum name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"/>
+                <enum name="GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS"/>
+                <enum name="GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT"/>
+                <enum name="GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH"/>
+                <enum name="GL_ACTIVE_UNIFORM_BLOCKS"/>
+                <enum name="GL_UNIFORM_TYPE"/>
+                <enum name="GL_UNIFORM_SIZE"/>
+                <enum name="GL_UNIFORM_NAME_LENGTH"/>
+                <enum name="GL_UNIFORM_BLOCK_INDEX"/>
+                <enum name="GL_UNIFORM_OFFSET"/>
+                <enum name="GL_UNIFORM_ARRAY_STRIDE"/>
+                <enum name="GL_UNIFORM_MATRIX_STRIDE"/>
+                <enum name="GL_UNIFORM_IS_ROW_MAJOR"/>
+                <enum name="GL_UNIFORM_BLOCK_BINDING"/>
+                <enum name="GL_UNIFORM_BLOCK_DATA_SIZE"/>
+                <enum name="GL_UNIFORM_BLOCK_NAME_LENGTH"/>
+                <enum name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS"/>
+                <enum name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES"/>
+                <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"/>
+                <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER"/>
+                <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"/>
+                <enum name="GL_INVALID_INDEX"/>
+                <command name="glGetUniformIndices"/>
+                <command name="glGetActiveUniformsiv"/>
+                <command name="glGetActiveUniformName"/>
+                <command name="glGetUniformBlockIndex"/>
+                <command name="glGetActiveUniformBlockiv"/>
+                <command name="glGetActiveUniformBlockName"/>
+                <command name="glUniformBlockBinding"/>
+                <command name="glBindBufferRange"/>
+                <command name="glBindBufferBase"/>
+                <command name="glGetIntegeri_v"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_array_bgra" supported="gl|glcore">
+            <require>
+                <enum name="GL_BGRA"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_array_object" supported="gl|glcore">
+            <require>
+                <enum name="GL_VERTEX_ARRAY_BINDING"/>
+                <command name="glBindVertexArray"/>
+                <command name="glDeleteVertexArrays"/>
+                <command name="glGenVertexArrays"/>
+                <command name="glIsVertexArray"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_attrib_64bit" supported="gl|glcore">
+            <require>
+                <enum name="GL_RGB32I"/>
+                <enum name="GL_DOUBLE_VEC2"/>
+                <enum name="GL_DOUBLE_VEC3"/>
+                <enum name="GL_DOUBLE_VEC4"/>
+                <enum name="GL_DOUBLE_MAT2"/>
+                <enum name="GL_DOUBLE_MAT3"/>
+                <enum name="GL_DOUBLE_MAT4"/>
+                <enum name="GL_DOUBLE_MAT2x3"/>
+                <enum name="GL_DOUBLE_MAT2x4"/>
+                <enum name="GL_DOUBLE_MAT3x2"/>
+                <enum name="GL_DOUBLE_MAT3x4"/>
+                <enum name="GL_DOUBLE_MAT4x2"/>
+                <enum name="GL_DOUBLE_MAT4x3"/>
+                <command name="glVertexAttribL1d"/>
+                <command name="glVertexAttribL2d"/>
+                <command name="glVertexAttribL3d"/>
+                <command name="glVertexAttribL4d"/>
+                <command name="glVertexAttribL1dv"/>
+                <command name="glVertexAttribL2dv"/>
+                <command name="glVertexAttribL3dv"/>
+                <command name="glVertexAttribL4dv"/>
+                <command name="glVertexAttribLPointer"/>
+                <command name="glGetVertexAttribLdv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_attrib_binding" supported="gl|glcore">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_BINDING"/>
+                <enum name="GL_VERTEX_ATTRIB_RELATIVE_OFFSET"/>
+                <enum name="GL_VERTEX_BINDING_DIVISOR"/>
+                <enum name="GL_VERTEX_BINDING_OFFSET"/>
+                <enum name="GL_VERTEX_BINDING_STRIDE"/>
+                <enum name="GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET"/>
+                <enum name="GL_MAX_VERTEX_ATTRIB_BINDINGS"/>
+                <command name="glBindVertexBuffer"/>
+                <command name="glVertexAttribFormat"/>
+                <command name="glVertexAttribIFormat"/>
+                <command name="glVertexAttribLFormat"/>
+                <command name="glVertexAttribBinding"/>
+                <command name="glVertexBindingDivisor"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_blend" supported="gl">
+            <require>
+                <enum name="GL_MAX_VERTEX_UNITS_ARB"/>
+                <enum name="GL_ACTIVE_VERTEX_UNITS_ARB"/>
+                <enum name="GL_WEIGHT_SUM_UNITY_ARB"/>
+                <enum name="GL_VERTEX_BLEND_ARB"/>
+                <enum name="GL_CURRENT_WEIGHT_ARB"/>
+                <enum name="GL_WEIGHT_ARRAY_TYPE_ARB"/>
+                <enum name="GL_WEIGHT_ARRAY_STRIDE_ARB"/>
+                <enum name="GL_WEIGHT_ARRAY_SIZE_ARB"/>
+                <enum name="GL_WEIGHT_ARRAY_POINTER_ARB"/>
+                <enum name="GL_WEIGHT_ARRAY_ARB"/>
+                <enum name="GL_MODELVIEW0_ARB"/>
+                <enum name="GL_MODELVIEW1_ARB"/>
+                <enum name="GL_MODELVIEW2_ARB"/>
+                <enum name="GL_MODELVIEW3_ARB"/>
+                <enum name="GL_MODELVIEW4_ARB"/>
+                <enum name="GL_MODELVIEW5_ARB"/>
+                <enum name="GL_MODELVIEW6_ARB"/>
+                <enum name="GL_MODELVIEW7_ARB"/>
+                <enum name="GL_MODELVIEW8_ARB"/>
+                <enum name="GL_MODELVIEW9_ARB"/>
+                <enum name="GL_MODELVIEW10_ARB"/>
+                <enum name="GL_MODELVIEW11_ARB"/>
+                <enum name="GL_MODELVIEW12_ARB"/>
+                <enum name="GL_MODELVIEW13_ARB"/>
+                <enum name="GL_MODELVIEW14_ARB"/>
+                <enum name="GL_MODELVIEW15_ARB"/>
+                <enum name="GL_MODELVIEW16_ARB"/>
+                <enum name="GL_MODELVIEW17_ARB"/>
+                <enum name="GL_MODELVIEW18_ARB"/>
+                <enum name="GL_MODELVIEW19_ARB"/>
+                <enum name="GL_MODELVIEW20_ARB"/>
+                <enum name="GL_MODELVIEW21_ARB"/>
+                <enum name="GL_MODELVIEW22_ARB"/>
+                <enum name="GL_MODELVIEW23_ARB"/>
+                <enum name="GL_MODELVIEW24_ARB"/>
+                <enum name="GL_MODELVIEW25_ARB"/>
+                <enum name="GL_MODELVIEW26_ARB"/>
+                <enum name="GL_MODELVIEW27_ARB"/>
+                <enum name="GL_MODELVIEW28_ARB"/>
+                <enum name="GL_MODELVIEW29_ARB"/>
+                <enum name="GL_MODELVIEW30_ARB"/>
+                <enum name="GL_MODELVIEW31_ARB"/>
+                <command name="glWeightbvARB"/>
+                <command name="glWeightsvARB"/>
+                <command name="glWeightivARB"/>
+                <command name="glWeightfvARB"/>
+                <command name="glWeightdvARB"/>
+                <command name="glWeightubvARB"/>
+                <command name="glWeightusvARB"/>
+                <command name="glWeightuivARB"/>
+                <command name="glWeightPointerARB"/>
+                <command name="glVertexBlendARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_buffer_object" supported="gl">
+            <require>
+                <enum name="GL_BUFFER_SIZE_ARB"/>
+                <enum name="GL_BUFFER_USAGE_ARB"/>
+                <enum name="GL_ARRAY_BUFFER_ARB"/>
+                <enum name="GL_ELEMENT_ARRAY_BUFFER_ARB"/>
+                <enum name="GL_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_VERTEX_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_NORMAL_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_COLOR_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_INDEX_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB"/>
+                <enum name="GL_READ_ONLY_ARB"/>
+                <enum name="GL_WRITE_ONLY_ARB"/>
+                <enum name="GL_READ_WRITE_ARB"/>
+                <enum name="GL_BUFFER_ACCESS_ARB"/>
+                <enum name="GL_BUFFER_MAPPED_ARB"/>
+                <enum name="GL_BUFFER_MAP_POINTER_ARB"/>
+                <enum name="GL_STREAM_DRAW_ARB"/>
+                <enum name="GL_STREAM_READ_ARB"/>
+                <enum name="GL_STREAM_COPY_ARB"/>
+                <enum name="GL_STATIC_DRAW_ARB"/>
+                <enum name="GL_STATIC_READ_ARB"/>
+                <enum name="GL_STATIC_COPY_ARB"/>
+                <enum name="GL_DYNAMIC_DRAW_ARB"/>
+                <enum name="GL_DYNAMIC_READ_ARB"/>
+                <enum name="GL_DYNAMIC_COPY_ARB"/>
+                <command name="glBindBufferARB"/>
+                <command name="glDeleteBuffersARB"/>
+                <command name="glGenBuffersARB"/>
+                <command name="glIsBufferARB"/>
+                <command name="glBufferDataARB"/>
+                <command name="glBufferSubDataARB"/>
+                <command name="glGetBufferSubDataARB"/>
+                <command name="glMapBufferARB"/>
+                <command name="glUnmapBufferARB"/>
+                <command name="glGetBufferParameterivARB"/>
+                <command name="glGetBufferPointervARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_program" supported="gl">
+            <require>
+                <enum name="GL_COLOR_SUM_ARB"/>
+                <enum name="GL_VERTEX_PROGRAM_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB"/>
+                <enum name="GL_CURRENT_VERTEX_ATTRIB_ARB"/>
+                <enum name="GL_PROGRAM_LENGTH_ARB"/>
+                <enum name="GL_PROGRAM_STRING_ARB"/>
+                <enum name="GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB"/>
+                <enum name="GL_MAX_PROGRAM_MATRICES_ARB"/>
+                <enum name="GL_CURRENT_MATRIX_STACK_DEPTH_ARB"/>
+                <enum name="GL_CURRENT_MATRIX_ARB"/>
+                <enum name="GL_VERTEX_PROGRAM_POINT_SIZE_ARB"/>
+                <enum name="GL_VERTEX_PROGRAM_TWO_SIDE_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB"/>
+                <enum name="GL_PROGRAM_ERROR_POSITION_ARB"/>
+                <enum name="GL_PROGRAM_BINDING_ARB"/>
+                <enum name="GL_MAX_VERTEX_ATTRIBS_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB"/>
+                <enum name="GL_PROGRAM_ERROR_STRING_ARB"/>
+                <enum name="GL_PROGRAM_FORMAT_ASCII_ARB"/>
+                <enum name="GL_PROGRAM_FORMAT_ARB"/>
+                <enum name="GL_PROGRAM_INSTRUCTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_INSTRUCTIONS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB"/>
+                <enum name="GL_PROGRAM_TEMPORARIES_ARB"/>
+                <enum name="GL_MAX_PROGRAM_TEMPORARIES_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_TEMPORARIES_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB"/>
+                <enum name="GL_PROGRAM_PARAMETERS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_PARAMETERS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_PARAMETERS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB"/>
+                <enum name="GL_PROGRAM_ATTRIBS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_ATTRIBS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_ATTRIBS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB"/>
+                <enum name="GL_PROGRAM_ADDRESS_REGISTERS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB"/>
+                <enum name="GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB"/>
+                <enum name="GL_MAX_PROGRAM_ENV_PARAMETERS_ARB"/>
+                <enum name="GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB"/>
+                <enum name="GL_TRANSPOSE_CURRENT_MATRIX_ARB"/>
+                <enum name="GL_MATRIX0_ARB"/>
+                <enum name="GL_MATRIX1_ARB"/>
+                <enum name="GL_MATRIX2_ARB"/>
+                <enum name="GL_MATRIX3_ARB"/>
+                <enum name="GL_MATRIX4_ARB"/>
+                <enum name="GL_MATRIX5_ARB"/>
+                <enum name="GL_MATRIX6_ARB"/>
+                <enum name="GL_MATRIX7_ARB"/>
+                <enum name="GL_MATRIX8_ARB"/>
+                <enum name="GL_MATRIX9_ARB"/>
+                <enum name="GL_MATRIX10_ARB"/>
+                <enum name="GL_MATRIX11_ARB"/>
+                <enum name="GL_MATRIX12_ARB"/>
+                <enum name="GL_MATRIX13_ARB"/>
+                <enum name="GL_MATRIX14_ARB"/>
+                <enum name="GL_MATRIX15_ARB"/>
+                <enum name="GL_MATRIX16_ARB"/>
+                <enum name="GL_MATRIX17_ARB"/>
+                <enum name="GL_MATRIX18_ARB"/>
+                <enum name="GL_MATRIX19_ARB"/>
+                <enum name="GL_MATRIX20_ARB"/>
+                <enum name="GL_MATRIX21_ARB"/>
+                <enum name="GL_MATRIX22_ARB"/>
+                <enum name="GL_MATRIX23_ARB"/>
+                <enum name="GL_MATRIX24_ARB"/>
+                <enum name="GL_MATRIX25_ARB"/>
+                <enum name="GL_MATRIX26_ARB"/>
+                <enum name="GL_MATRIX27_ARB"/>
+                <enum name="GL_MATRIX28_ARB"/>
+                <enum name="GL_MATRIX29_ARB"/>
+                <enum name="GL_MATRIX30_ARB"/>
+                <enum name="GL_MATRIX31_ARB"/>
+                <command name="glVertexAttrib1dARB"/>
+                <command name="glVertexAttrib1dvARB"/>
+                <command name="glVertexAttrib1fARB"/>
+                <command name="glVertexAttrib1fvARB"/>
+                <command name="glVertexAttrib1sARB"/>
+                <command name="glVertexAttrib1svARB"/>
+                <command name="glVertexAttrib2dARB"/>
+                <command name="glVertexAttrib2dvARB"/>
+                <command name="glVertexAttrib2fARB"/>
+                <command name="glVertexAttrib2fvARB"/>
+                <command name="glVertexAttrib2sARB"/>
+                <command name="glVertexAttrib2svARB"/>
+                <command name="glVertexAttrib3dARB"/>
+                <command name="glVertexAttrib3dvARB"/>
+                <command name="glVertexAttrib3fARB"/>
+                <command name="glVertexAttrib3fvARB"/>
+                <command name="glVertexAttrib3sARB"/>
+                <command name="glVertexAttrib3svARB"/>
+                <command name="glVertexAttrib4NbvARB"/>
+                <command name="glVertexAttrib4NivARB"/>
+                <command name="glVertexAttrib4NsvARB"/>
+                <command name="glVertexAttrib4NubARB"/>
+                <command name="glVertexAttrib4NubvARB"/>
+                <command name="glVertexAttrib4NuivARB"/>
+                <command name="glVertexAttrib4NusvARB"/>
+                <command name="glVertexAttrib4bvARB"/>
+                <command name="glVertexAttrib4dARB"/>
+                <command name="glVertexAttrib4dvARB"/>
+                <command name="glVertexAttrib4fARB"/>
+                <command name="glVertexAttrib4fvARB"/>
+                <command name="glVertexAttrib4ivARB"/>
+                <command name="glVertexAttrib4sARB"/>
+                <command name="glVertexAttrib4svARB"/>
+                <command name="glVertexAttrib4ubvARB"/>
+                <command name="glVertexAttrib4uivARB"/>
+                <command name="glVertexAttrib4usvARB"/>
+                <command name="glVertexAttribPointerARB"/>
+                <command name="glEnableVertexAttribArrayARB"/>
+                <command name="glDisableVertexAttribArrayARB"/>
+                <command name="glProgramStringARB"/>
+                <command name="glBindProgramARB"/>
+                <command name="glDeleteProgramsARB"/>
+                <command name="glGenProgramsARB"/>
+                <command name="glProgramEnvParameter4dARB"/>
+                <command name="glProgramEnvParameter4dvARB"/>
+                <command name="glProgramEnvParameter4fARB"/>
+                <command name="glProgramEnvParameter4fvARB"/>
+                <command name="glProgramLocalParameter4dARB"/>
+                <command name="glProgramLocalParameter4dvARB"/>
+                <command name="glProgramLocalParameter4fARB"/>
+                <command name="glProgramLocalParameter4fvARB"/>
+                <command name="glGetProgramEnvParameterdvARB"/>
+                <command name="glGetProgramEnvParameterfvARB"/>
+                <command name="glGetProgramLocalParameterdvARB"/>
+                <command name="glGetProgramLocalParameterfvARB"/>
+                <command name="glGetProgramivARB"/>
+                <command name="glGetProgramStringARB"/>
+                <command name="glGetVertexAttribdvARB"/>
+                <command name="glGetVertexAttribfvARB"/>
+                <command name="glGetVertexAttribivARB"/>
+                <command name="glGetVertexAttribPointervARB"/>
+                <command name="glIsProgramARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_shader" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_SHADER_ARB"/>
+                <enum name="GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB"/>
+                <enum name="GL_MAX_VARYING_FLOATS_ARB"/>
+                <enum name="GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB"/>
+                <enum name="GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB"/>
+                <enum name="GL_OBJECT_ACTIVE_ATTRIBUTES_ARB"/>
+                <enum name="GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB"/>
+                <enum name="GL_MAX_VERTEX_ATTRIBS_ARB"/>
+                <enum name="GL_MAX_TEXTURE_IMAGE_UNITS_ARB"/>
+                <enum name="GL_MAX_TEXTURE_COORDS_ARB"/>
+                <enum name="GL_VERTEX_PROGRAM_POINT_SIZE_ARB"/>
+                <enum name="GL_VERTEX_PROGRAM_TWO_SIDE_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB"/>
+                <enum name="GL_CURRENT_VERTEX_ATTRIB_ARB"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB"/>
+                <enum name="GL_FLOAT"/>
+                <enum name="GL_FLOAT_VEC2_ARB"/>
+                <enum name="GL_FLOAT_VEC3_ARB"/>
+                <enum name="GL_FLOAT_VEC4_ARB"/>
+                <enum name="GL_FLOAT_MAT2_ARB"/>
+                <enum name="GL_FLOAT_MAT3_ARB"/>
+                <enum name="GL_FLOAT_MAT4_ARB"/>
+                <command name="glVertexAttrib1fARB"/>
+                <command name="glVertexAttrib1sARB"/>
+                <command name="glVertexAttrib1dARB"/>
+                <command name="glVertexAttrib2fARB"/>
+                <command name="glVertexAttrib2sARB"/>
+                <command name="glVertexAttrib2dARB"/>
+                <command name="glVertexAttrib3fARB"/>
+                <command name="glVertexAttrib3sARB"/>
+                <command name="glVertexAttrib3dARB"/>
+                <command name="glVertexAttrib4fARB"/>
+                <command name="glVertexAttrib4sARB"/>
+                <command name="glVertexAttrib4dARB"/>
+                <command name="glVertexAttrib4NubARB"/>
+                <command name="glVertexAttrib1fvARB"/>
+                <command name="glVertexAttrib1svARB"/>
+                <command name="glVertexAttrib1dvARB"/>
+                <command name="glVertexAttrib2fvARB"/>
+                <command name="glVertexAttrib2svARB"/>
+                <command name="glVertexAttrib2dvARB"/>
+                <command name="glVertexAttrib3fvARB"/>
+                <command name="glVertexAttrib3svARB"/>
+                <command name="glVertexAttrib3dvARB"/>
+                <command name="glVertexAttrib4fvARB"/>
+                <command name="glVertexAttrib4svARB"/>
+                <command name="glVertexAttrib4dvARB"/>
+                <command name="glVertexAttrib4ivARB"/>
+                <command name="glVertexAttrib4bvARB"/>
+                <command name="glVertexAttrib4ubvARB"/>
+                <command name="glVertexAttrib4usvARB"/>
+                <command name="glVertexAttrib4uivARB"/>
+                <command name="glVertexAttrib4NbvARB"/>
+                <command name="glVertexAttrib4NsvARB"/>
+                <command name="glVertexAttrib4NivARB"/>
+                <command name="glVertexAttrib4NubvARB"/>
+                <command name="glVertexAttrib4NusvARB"/>
+                <command name="glVertexAttrib4NuivARB"/>
+                <command name="glVertexAttribPointerARB"/>
+                <command name="glEnableVertexAttribArrayARB"/>
+                <command name="glDisableVertexAttribArrayARB"/>
+                <command name="glBindAttribLocationARB"/>
+                <command name="glGetActiveAttribARB"/>
+                <command name="glGetAttribLocationARB"/>
+                <command name="glGetVertexAttribdvARB"/>
+                <command name="glGetVertexAttribfvARB"/>
+                <command name="glGetVertexAttribivARB"/>
+                <command name="glGetVertexAttribPointervARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_type_10f_11f_11f_rev" supported="gl|glcore">
+            <require>
+                <enum name="GL_UNSIGNED_INT_10F_11F_11F_REV"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_vertex_type_2_10_10_10_rev" supported="gl|glcore">
+            <require>
+                <enum name="GL_UNSIGNED_INT_2_10_10_10_REV"/>
+                <enum name="GL_INT_2_10_10_10_REV"/>
+                <command name="glVertexAttribP1ui"/>
+                <command name="glVertexAttribP1uiv"/>
+                <command name="glVertexAttribP2ui"/>
+                <command name="glVertexAttribP2uiv"/>
+                <command name="glVertexAttribP3ui"/>
+                <command name="glVertexAttribP3uiv"/>
+                <command name="glVertexAttribP4ui"/>
+                <command name="glVertexAttribP4uiv"/>
+            </require>
+            <require api="gl" profile="compatibility">
+                <command name="glVertexP2ui"/>
+                <command name="glVertexP2uiv"/>
+                <command name="glVertexP3ui"/>
+                <command name="glVertexP3uiv"/>
+                <command name="glVertexP4ui"/>
+                <command name="glVertexP4uiv"/>
+                <command name="glTexCoordP1ui"/>
+                <command name="glTexCoordP1uiv"/>
+                <command name="glTexCoordP2ui"/>
+                <command name="glTexCoordP2uiv"/>
+                <command name="glTexCoordP3ui"/>
+                <command name="glTexCoordP3uiv"/>
+                <command name="glTexCoordP4ui"/>
+                <command name="glTexCoordP4uiv"/>
+                <command name="glMultiTexCoordP1ui"/>
+                <command name="glMultiTexCoordP1uiv"/>
+                <command name="glMultiTexCoordP2ui"/>
+                <command name="glMultiTexCoordP2uiv"/>
+                <command name="glMultiTexCoordP3ui"/>
+                <command name="glMultiTexCoordP3uiv"/>
+                <command name="glMultiTexCoordP4ui"/>
+                <command name="glMultiTexCoordP4uiv"/>
+                <command name="glNormalP3ui"/>
+                <command name="glNormalP3uiv"/>
+                <command name="glColorP3ui"/>
+                <command name="glColorP3uiv"/>
+                <command name="glColorP4ui"/>
+                <command name="glColorP4uiv"/>
+                <command name="glSecondaryColorP3ui"/>
+                <command name="glSecondaryColorP3uiv"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_viewport_array" supported="gl|glcore">
+            <require>
+                <enum name="GL_SCISSOR_BOX"/>
+                <enum name="GL_VIEWPORT"/>
+                <enum name="GL_DEPTH_RANGE"/>
+                <enum name="GL_SCISSOR_TEST"/>
+                <enum name="GL_MAX_VIEWPORTS"/>
+                <enum name="GL_VIEWPORT_SUBPIXEL_BITS"/>
+                <enum name="GL_VIEWPORT_BOUNDS_RANGE"/>
+                <enum name="GL_LAYER_PROVOKING_VERTEX"/>
+                <enum name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX"/>
+                <enum name="GL_UNDEFINED_VERTEX"/>
+                <enum name="GL_FIRST_VERTEX_CONVENTION"/>
+                <enum name="GL_LAST_VERTEX_CONVENTION"/>
+                <enum name="GL_PROVOKING_VERTEX"/>
+                <command name="glViewportArrayv"/>
+                <command name="glViewportIndexedf"/>
+                <command name="glViewportIndexedfv"/>
+                <command name="glScissorArrayv"/>
+                <command name="glScissorIndexed"/>
+                <command name="glScissorIndexedv"/>
+                <command name="glDepthRangeArrayv"/>
+                <command name="glDepthRangeIndexed"/>
+                <command name="glGetFloati_v"/>
+                <command name="glGetDoublei_v"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_window_pos" supported="gl">
+            <require>
+                <command name="glWindowPos2dARB"/>
+                <command name="glWindowPos2dvARB"/>
+                <command name="glWindowPos2fARB"/>
+                <command name="glWindowPos2fvARB"/>
+                <command name="glWindowPos2iARB"/>
+                <command name="glWindowPos2ivARB"/>
+                <command name="glWindowPos2sARB"/>
+                <command name="glWindowPos2svARB"/>
+                <command name="glWindowPos3dARB"/>
+                <command name="glWindowPos3dvARB"/>
+                <command name="glWindowPos3fARB"/>
+                <command name="glWindowPos3fvARB"/>
+                <command name="glWindowPos3iARB"/>
+                <command name="glWindowPos3ivARB"/>
+                <command name="glWindowPos3sARB"/>
+                <command name="glWindowPos3svARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARM_mali_program_binary" supported="gles2">
+            <require>
+                <enum name="GL_MALI_PROGRAM_BINARY_ARM"/>
+            </require>
+        </extension>
+        <extension name="GL_ARM_mali_shader_binary" supported="gles2">
+            <require>
+                <enum name="GL_MALI_SHADER_BINARY_ARM"/>
+            </require>
+        </extension>
+        <extension name="GL_ARM_rgba8" supported="gles1|gles2"/>
+        <extension name="GL_ARM_shader_framebuffer_fetch" supported="gles2">
+            <require>
+                <enum name="GL_FETCH_PER_SAMPLE_ARM"/>
+                <enum name="GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM"/>
+            </require>
+        </extension>
+        <extension name="GL_ARM_shader_framebuffer_fetch_depth_stencil" supported="gles2"/>
+        <extension name="GL_ATI_draw_buffers" supported="gl">
+            <require>
+                <enum name="GL_MAX_DRAW_BUFFERS_ATI"/>
+                <enum name="GL_DRAW_BUFFER0_ATI"/>
+                <enum name="GL_DRAW_BUFFER1_ATI"/>
+                <enum name="GL_DRAW_BUFFER2_ATI"/>
+                <enum name="GL_DRAW_BUFFER3_ATI"/>
+                <enum name="GL_DRAW_BUFFER4_ATI"/>
+                <enum name="GL_DRAW_BUFFER5_ATI"/>
+                <enum name="GL_DRAW_BUFFER6_ATI"/>
+                <enum name="GL_DRAW_BUFFER7_ATI"/>
+                <enum name="GL_DRAW_BUFFER8_ATI"/>
+                <enum name="GL_DRAW_BUFFER9_ATI"/>
+                <enum name="GL_DRAW_BUFFER10_ATI"/>
+                <enum name="GL_DRAW_BUFFER11_ATI"/>
+                <enum name="GL_DRAW_BUFFER12_ATI"/>
+                <enum name="GL_DRAW_BUFFER13_ATI"/>
+                <enum name="GL_DRAW_BUFFER14_ATI"/>
+                <enum name="GL_DRAW_BUFFER15_ATI"/>
+                <command name="glDrawBuffersATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_element_array" supported="gl">
+            <require>
+                <enum name="GL_ELEMENT_ARRAY_ATI"/>
+                <enum name="GL_ELEMENT_ARRAY_TYPE_ATI"/>
+                <enum name="GL_ELEMENT_ARRAY_POINTER_ATI"/>
+                <command name="glElementPointerATI"/>
+                <command name="glDrawElementArrayATI"/>
+                <command name="glDrawRangeElementArrayATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_envmap_bumpmap" supported="gl">
+            <require>
+                <enum name="GL_BUMP_ROT_MATRIX_ATI"/>
+                <enum name="GL_BUMP_ROT_MATRIX_SIZE_ATI"/>
+                <enum name="GL_BUMP_NUM_TEX_UNITS_ATI"/>
+                <enum name="GL_BUMP_TEX_UNITS_ATI"/>
+                <enum name="GL_DUDV_ATI"/>
+                <enum name="GL_DU8DV8_ATI"/>
+                <enum name="GL_BUMP_ENVMAP_ATI"/>
+                <enum name="GL_BUMP_TARGET_ATI"/>
+                <command name="glTexBumpParameterivATI"/>
+                <command name="glTexBumpParameterfvATI"/>
+                <command name="glGetTexBumpParameterivATI"/>
+                <command name="glGetTexBumpParameterfvATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_fragment_shader" supported="gl">
+            <require>
+                <enum name="GL_FRAGMENT_SHADER_ATI"/>
+                <enum name="GL_REG_0_ATI"/>
+                <enum name="GL_REG_1_ATI"/>
+                <enum name="GL_REG_2_ATI"/>
+                <enum name="GL_REG_3_ATI"/>
+                <enum name="GL_REG_4_ATI"/>
+                <enum name="GL_REG_5_ATI"/>
+                <enum name="GL_REG_6_ATI"/>
+                <enum name="GL_REG_7_ATI"/>
+                <enum name="GL_REG_8_ATI"/>
+                <enum name="GL_REG_9_ATI"/>
+                <enum name="GL_REG_10_ATI"/>
+                <enum name="GL_REG_11_ATI"/>
+                <enum name="GL_REG_12_ATI"/>
+                <enum name="GL_REG_13_ATI"/>
+                <enum name="GL_REG_14_ATI"/>
+                <enum name="GL_REG_15_ATI"/>
+                <enum name="GL_REG_16_ATI"/>
+                <enum name="GL_REG_17_ATI"/>
+                <enum name="GL_REG_18_ATI"/>
+                <enum name="GL_REG_19_ATI"/>
+                <enum name="GL_REG_20_ATI"/>
+                <enum name="GL_REG_21_ATI"/>
+                <enum name="GL_REG_22_ATI"/>
+                <enum name="GL_REG_23_ATI"/>
+                <enum name="GL_REG_24_ATI"/>
+                <enum name="GL_REG_25_ATI"/>
+                <enum name="GL_REG_26_ATI"/>
+                <enum name="GL_REG_27_ATI"/>
+                <enum name="GL_REG_28_ATI"/>
+                <enum name="GL_REG_29_ATI"/>
+                <enum name="GL_REG_30_ATI"/>
+                <enum name="GL_REG_31_ATI"/>
+                <enum name="GL_CON_0_ATI"/>
+                <enum name="GL_CON_1_ATI"/>
+                <enum name="GL_CON_2_ATI"/>
+                <enum name="GL_CON_3_ATI"/>
+                <enum name="GL_CON_4_ATI"/>
+                <enum name="GL_CON_5_ATI"/>
+                <enum name="GL_CON_6_ATI"/>
+                <enum name="GL_CON_7_ATI"/>
+                <enum name="GL_CON_8_ATI"/>
+                <enum name="GL_CON_9_ATI"/>
+                <enum name="GL_CON_10_ATI"/>
+                <enum name="GL_CON_11_ATI"/>
+                <enum name="GL_CON_12_ATI"/>
+                <enum name="GL_CON_13_ATI"/>
+                <enum name="GL_CON_14_ATI"/>
+                <enum name="GL_CON_15_ATI"/>
+                <enum name="GL_CON_16_ATI"/>
+                <enum name="GL_CON_17_ATI"/>
+                <enum name="GL_CON_18_ATI"/>
+                <enum name="GL_CON_19_ATI"/>
+                <enum name="GL_CON_20_ATI"/>
+                <enum name="GL_CON_21_ATI"/>
+                <enum name="GL_CON_22_ATI"/>
+                <enum name="GL_CON_23_ATI"/>
+                <enum name="GL_CON_24_ATI"/>
+                <enum name="GL_CON_25_ATI"/>
+                <enum name="GL_CON_26_ATI"/>
+                <enum name="GL_CON_27_ATI"/>
+                <enum name="GL_CON_28_ATI"/>
+                <enum name="GL_CON_29_ATI"/>
+                <enum name="GL_CON_30_ATI"/>
+                <enum name="GL_CON_31_ATI"/>
+                <enum name="GL_MOV_ATI"/>
+                <enum name="GL_ADD_ATI"/>
+                <enum name="GL_MUL_ATI"/>
+                <enum name="GL_SUB_ATI"/>
+                <enum name="GL_DOT3_ATI"/>
+                <enum name="GL_DOT4_ATI"/>
+                <enum name="GL_MAD_ATI"/>
+                <enum name="GL_LERP_ATI"/>
+                <enum name="GL_CND_ATI"/>
+                <enum name="GL_CND0_ATI"/>
+                <enum name="GL_DOT2_ADD_ATI"/>
+                <enum name="GL_SECONDARY_INTERPOLATOR_ATI"/>
+                <enum name="GL_NUM_FRAGMENT_REGISTERS_ATI"/>
+                <enum name="GL_NUM_FRAGMENT_CONSTANTS_ATI"/>
+                <enum name="GL_NUM_PASSES_ATI"/>
+                <enum name="GL_NUM_INSTRUCTIONS_PER_PASS_ATI"/>
+                <enum name="GL_NUM_INSTRUCTIONS_TOTAL_ATI"/>
+                <enum name="GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI"/>
+                <enum name="GL_NUM_LOOPBACK_COMPONENTS_ATI"/>
+                <enum name="GL_COLOR_ALPHA_PAIRING_ATI"/>
+                <enum name="GL_SWIZZLE_STR_ATI"/>
+                <enum name="GL_SWIZZLE_STQ_ATI"/>
+                <enum name="GL_SWIZZLE_STR_DR_ATI"/>
+                <enum name="GL_SWIZZLE_STQ_DQ_ATI"/>
+                <enum name="GL_SWIZZLE_STRQ_ATI"/>
+                <enum name="GL_SWIZZLE_STRQ_DQ_ATI"/>
+                <enum name="GL_RED_BIT_ATI"/>
+                <enum name="GL_GREEN_BIT_ATI"/>
+                <enum name="GL_BLUE_BIT_ATI"/>
+                <enum name="GL_2X_BIT_ATI"/>
+                <enum name="GL_4X_BIT_ATI"/>
+                <enum name="GL_8X_BIT_ATI"/>
+                <enum name="GL_HALF_BIT_ATI"/>
+                <enum name="GL_QUARTER_BIT_ATI"/>
+                <enum name="GL_EIGHTH_BIT_ATI"/>
+                <enum name="GL_SATURATE_BIT_ATI"/>
+                <enum name="GL_COMP_BIT_ATI"/>
+                <enum name="GL_NEGATE_BIT_ATI"/>
+                <enum name="GL_BIAS_BIT_ATI"/>
+                <command name="glGenFragmentShadersATI"/>
+                <command name="glBindFragmentShaderATI"/>
+                <command name="glDeleteFragmentShaderATI"/>
+                <command name="glBeginFragmentShaderATI"/>
+                <command name="glEndFragmentShaderATI"/>
+                <command name="glPassTexCoordATI"/>
+                <command name="glSampleMapATI"/>
+                <command name="glColorFragmentOp1ATI"/>
+                <command name="glColorFragmentOp2ATI"/>
+                <command name="glColorFragmentOp3ATI"/>
+                <command name="glAlphaFragmentOp1ATI"/>
+                <command name="glAlphaFragmentOp2ATI"/>
+                <command name="glAlphaFragmentOp3ATI"/>
+                <command name="glSetFragmentShaderConstantATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_map_object_buffer" supported="gl">
+            <require>
+                <command name="glMapObjectBufferATI"/>
+                <command name="glUnmapObjectBufferATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_meminfo" supported="gl">
+            <require>
+                <enum name="GL_VBO_FREE_MEMORY_ATI"/>
+                <enum name="GL_TEXTURE_FREE_MEMORY_ATI"/>
+                <enum name="GL_RENDERBUFFER_FREE_MEMORY_ATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_pixel_format_float" supported="gl" comment="WGL extension defining some associated GL enums. ATI does not export this extension.">
+            <require>
+                <enum name="GL_RGBA_FLOAT_MODE_ATI"/>
+                <enum name="GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_pn_triangles" supported="gl">
+            <require>
+                <enum name="GL_PN_TRIANGLES_ATI"/>
+                <enum name="GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI"/>
+                <enum name="GL_PN_TRIANGLES_POINT_MODE_ATI"/>
+                <enum name="GL_PN_TRIANGLES_NORMAL_MODE_ATI"/>
+                <enum name="GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI"/>
+                <enum name="GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI"/>
+                <enum name="GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI"/>
+                <enum name="GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI"/>
+                <enum name="GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI"/>
+                <command name="glPNTrianglesiATI"/>
+                <command name="glPNTrianglesfATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_separate_stencil" supported="gl">
+            <require>
+                <enum name="GL_STENCIL_BACK_FUNC_ATI"/>
+                <enum name="GL_STENCIL_BACK_FAIL_ATI"/>
+                <enum name="GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI"/>
+                <enum name="GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI"/>
+                <command name="glStencilOpSeparateATI"/>
+                <command name="glStencilFuncSeparateATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_text_fragment_shader" supported="gl">
+            <require>
+                <enum name="GL_TEXT_FRAGMENT_SHADER_ATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_texture_env_combine3" supported="gl">
+            <require>
+                <enum name="GL_MODULATE_ADD_ATI"/>
+                <enum name="GL_MODULATE_SIGNED_ADD_ATI"/>
+                <enum name="GL_MODULATE_SUBTRACT_ATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_texture_float" supported="gl">
+            <require>
+                <enum name="GL_RGBA_FLOAT32_ATI"/>
+                <enum name="GL_RGB_FLOAT32_ATI"/>
+                <enum name="GL_ALPHA_FLOAT32_ATI"/>
+                <enum name="GL_INTENSITY_FLOAT32_ATI"/>
+                <enum name="GL_LUMINANCE_FLOAT32_ATI"/>
+                <enum name="GL_LUMINANCE_ALPHA_FLOAT32_ATI"/>
+                <enum name="GL_RGBA_FLOAT16_ATI"/>
+                <enum name="GL_RGB_FLOAT16_ATI"/>
+                <enum name="GL_ALPHA_FLOAT16_ATI"/>
+                <enum name="GL_INTENSITY_FLOAT16_ATI"/>
+                <enum name="GL_LUMINANCE_FLOAT16_ATI"/>
+                <enum name="GL_LUMINANCE_ALPHA_FLOAT16_ATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_texture_mirror_once" supported="gl">
+            <require>
+                <enum name="GL_MIRROR_CLAMP_ATI"/>
+                <enum name="GL_MIRROR_CLAMP_TO_EDGE_ATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_vertex_array_object" supported="gl">
+            <require>
+                <enum name="GL_STATIC_ATI"/>
+                <enum name="GL_DYNAMIC_ATI"/>
+                <enum name="GL_PRESERVE_ATI"/>
+                <enum name="GL_DISCARD_ATI"/>
+                <enum name="GL_OBJECT_BUFFER_SIZE_ATI"/>
+                <enum name="GL_OBJECT_BUFFER_USAGE_ATI"/>
+                <enum name="GL_ARRAY_OBJECT_BUFFER_ATI"/>
+                <enum name="GL_ARRAY_OBJECT_OFFSET_ATI"/>
+                <command name="glNewObjectBufferATI"/>
+                <command name="glIsObjectBufferATI"/>
+                <command name="glUpdateObjectBufferATI"/>
+                <command name="glGetObjectBufferfvATI"/>
+                <command name="glGetObjectBufferivATI"/>
+                <command name="glFreeObjectBufferATI"/>
+                <command name="glArrayObjectATI"/>
+                <command name="glGetArrayObjectfvATI"/>
+                <command name="glGetArrayObjectivATI"/>
+                <command name="glVariantArrayObjectATI"/>
+                <command name="glGetVariantArrayObjectfvATI"/>
+                <command name="glGetVariantArrayObjectivATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_vertex_attrib_array_object" supported="gl">
+            <require>
+                <command name="glVertexAttribArrayObjectATI"/>
+                <command name="glGetVertexAttribArrayObjectfvATI"/>
+                <command name="glGetVertexAttribArrayObjectivATI"/>
+            </require>
+        </extension>
+        <extension name="GL_ATI_vertex_streams" supported="gl">
+            <require>
+                <enum name="GL_MAX_VERTEX_STREAMS_ATI"/>
+                <enum name="GL_VERTEX_STREAM0_ATI"/>
+                <enum name="GL_VERTEX_STREAM1_ATI"/>
+                <enum name="GL_VERTEX_STREAM2_ATI"/>
+                <enum name="GL_VERTEX_STREAM3_ATI"/>
+                <enum name="GL_VERTEX_STREAM4_ATI"/>
+                <enum name="GL_VERTEX_STREAM5_ATI"/>
+                <enum name="GL_VERTEX_STREAM6_ATI"/>
+                <enum name="GL_VERTEX_STREAM7_ATI"/>
+                <enum name="GL_VERTEX_SOURCE_ATI"/>
+                <command name="glVertexStream1sATI"/>
+                <command name="glVertexStream1svATI"/>
+                <command name="glVertexStream1iATI"/>
+                <command name="glVertexStream1ivATI"/>
+                <command name="glVertexStream1fATI"/>
+                <command name="glVertexStream1fvATI"/>
+                <command name="glVertexStream1dATI"/>
+                <command name="glVertexStream1dvATI"/>
+                <command name="glVertexStream2sATI"/>
+                <command name="glVertexStream2svATI"/>
+                <command name="glVertexStream2iATI"/>
+                <command name="glVertexStream2ivATI"/>
+                <command name="glVertexStream2fATI"/>
+                <command name="glVertexStream2fvATI"/>
+                <command name="glVertexStream2dATI"/>
+                <command name="glVertexStream2dvATI"/>
+                <command name="glVertexStream3sATI"/>
+                <command name="glVertexStream3svATI"/>
+                <command name="glVertexStream3iATI"/>
+                <command name="glVertexStream3ivATI"/>
+                <command name="glVertexStream3fATI"/>
+                <command name="glVertexStream3fvATI"/>
+                <command name="glVertexStream3dATI"/>
+                <command name="glVertexStream3dvATI"/>
+                <command name="glVertexStream4sATI"/>
+                <command name="glVertexStream4svATI"/>
+                <command name="glVertexStream4iATI"/>
+                <command name="glVertexStream4ivATI"/>
+                <command name="glVertexStream4fATI"/>
+                <command name="glVertexStream4fvATI"/>
+                <command name="glVertexStream4dATI"/>
+                <command name="glVertexStream4dvATI"/>
+                <command name="glNormalStream3bATI"/>
+                <command name="glNormalStream3bvATI"/>
+                <command name="glNormalStream3sATI"/>
+                <command name="glNormalStream3svATI"/>
+                <command name="glNormalStream3iATI"/>
+                <command name="glNormalStream3ivATI"/>
+                <command name="glNormalStream3fATI"/>
+                <command name="glNormalStream3fvATI"/>
+                <command name="glNormalStream3dATI"/>
+                <command name="glNormalStream3dvATI"/>
+                <command name="glClientActiveVertexStreamATI"/>
+                <command name="glVertexBlendEnviATI"/>
+                <command name="glVertexBlendEnvfATI"/>
+            </require>
+        </extension>
+        <extension name="GL_DMP_program_binary" supported="gles2">
+            <require>
+                <enum name="GL_SMAPHS30_PROGRAM_BINARY_DMP"/>
+                <enum name="GL_SMAPHS_PROGRAM_BINARY_DMP"/>
+                <enum name="GL_DMP_PROGRAM_BINARY_DMP"/>
+            </require>
+        </extension>
+        <extension name="GL_DMP_shader_binary" supported="gles2">
+            <require>
+                <enum name="GL_SHADER_BINARY_DMP"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_422_pixels" supported="gl">
+            <require>
+                <enum name="GL_422_EXT"/>
+                <enum name="GL_422_REV_EXT"/>
+                <enum name="GL_422_AVERAGE_EXT"/>
+                <enum name="GL_422_REV_AVERAGE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_YUV_target" supported="gles2">
+            <require>
+                <enum name="GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT"/>
+                <enum name="GL_TEXTURE_EXTERNAL_OES"/>
+                <enum name="GL_TEXTURE_BINDING_EXTERNAL_OES"/>
+                <enum name="GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_abgr" supported="gl">
+            <require>
+                <enum name="GL_ABGR_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_base_instance" supported="gles2">
+            <require>
+                <command name="glDrawArraysInstancedBaseInstanceEXT"/>
+                <command name="glDrawElementsInstancedBaseInstanceEXT"/>
+                <command name="glDrawElementsInstancedBaseVertexBaseInstanceEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_bgra" supported="gl">
+            <require>
+                <enum name="GL_BGR_EXT"/>
+                <enum name="GL_BGRA_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_bindable_uniform" supported="gl">
+            <require>
+                <enum name="GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT"/>
+                <enum name="GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT"/>
+                <enum name="GL_MAX_BINDABLE_UNIFORM_SIZE_EXT"/>
+                <enum name="GL_UNIFORM_BUFFER_EXT"/>
+                <enum name="GL_UNIFORM_BUFFER_BINDING_EXT"/>
+                <command name="glUniformBufferEXT"/>
+                <command name="glGetUniformBufferSizeEXT"/>
+                <command name="glGetUniformOffsetEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_blend_color" supported="gl">
+            <require>
+                <enum name="GL_CONSTANT_COLOR_EXT"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_COLOR_EXT"/>
+                <enum name="GL_CONSTANT_ALPHA_EXT"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_ALPHA_EXT"/>
+                <enum name="GL_BLEND_COLOR_EXT"/>
+                <command name="glBlendColorEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_blend_equation_separate" supported="gl">
+            <require>
+                <enum name="GL_BLEND_EQUATION_RGB_EXT"/>
+                <enum name="GL_BLEND_EQUATION_ALPHA_EXT"/>
+                <command name="glBlendEquationSeparateEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_blend_func_extended" supported="gles2">
+            <require>
+                <enum name="GL_SRC1_COLOR_EXT"/>
+                <enum name="GL_SRC1_ALPHA_EXT"/>
+                <enum name="GL_ONE_MINUS_SRC1_COLOR_EXT"/>
+                <enum name="GL_ONE_MINUS_SRC1_ALPHA_EXT"/>
+                <enum name="GL_SRC_ALPHA_SATURATE_EXT"/>
+                <enum name="GL_LOCATION_INDEX_EXT"/>
+                <enum name="GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT"/>
+                <command name="glBindFragDataLocationIndexedEXT"/>
+                <command name="glBindFragDataLocationEXT"/>
+                <command name="glGetProgramResourceLocationIndexEXT"/>
+                <command name="glGetFragDataIndexEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_blend_func_separate" supported="gl">
+            <require>
+                <enum name="GL_BLEND_DST_RGB_EXT"/>
+                <enum name="GL_BLEND_SRC_RGB_EXT"/>
+                <enum name="GL_BLEND_DST_ALPHA_EXT"/>
+                <enum name="GL_BLEND_SRC_ALPHA_EXT"/>
+                <command name="glBlendFuncSeparateEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_blend_logic_op" supported="gl"/>
+        <extension name="GL_EXT_blend_minmax" supported="gl|gles1|gles2">
+            <require>
+                <enum name="GL_MIN_EXT"/>
+                <enum name="GL_MAX_EXT"/>
+            </require>
+            <require api="gl">
+                <enum name="GL_FUNC_ADD_EXT"/>
+                <enum name="GL_BLEND_EQUATION_EXT"/>
+                <command name="glBlendEquationEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_blend_subtract" supported="gl">
+            <require>
+                <enum name="GL_FUNC_SUBTRACT_EXT"/>
+                <enum name="GL_FUNC_REVERSE_SUBTRACT_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_buffer_storage" supported="gles2">
+            <require>
+                <enum name="GL_MAP_READ_BIT"/>
+                <enum name="GL_MAP_WRITE_BIT"/>
+                <enum name="GL_MAP_PERSISTENT_BIT_EXT"/>
+                <enum name="GL_MAP_COHERENT_BIT_EXT"/>
+                <enum name="GL_DYNAMIC_STORAGE_BIT_EXT"/>
+                <enum name="GL_CLIENT_STORAGE_BIT_EXT"/>
+                <enum name="GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT"/>
+                <enum name="GL_BUFFER_IMMUTABLE_STORAGE_EXT"/>
+                <enum name="GL_BUFFER_STORAGE_FLAGS_EXT"/>
+                <command name="glBufferStorageEXT"/>
+                <!-- <command name="glNamedBufferStorageEXT"/> -->
+            </require>
+        </extension>
+        <extension name="GL_EXT_clear_texture" supported="gles2">
+            <require>
+                <command name="glClearTexImageEXT"/>
+                <command name="glClearTexSubImageEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_clip_cull_distance" supported="gles2">
+            <require>
+                <enum name="GL_MAX_CLIP_DISTANCES_EXT"/>
+                <enum name="GL_MAX_CULL_DISTANCES_EXT"/>
+                <enum name="GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT"/>
+                <enum name="GL_CLIP_DISTANCE0_EXT"/>
+                <enum name="GL_CLIP_DISTANCE1_EXT"/>
+                <enum name="GL_CLIP_DISTANCE2_EXT"/>
+                <enum name="GL_CLIP_DISTANCE3_EXT"/>
+                <enum name="GL_CLIP_DISTANCE4_EXT"/>
+                <enum name="GL_CLIP_DISTANCE5_EXT"/>
+                <enum name="GL_CLIP_DISTANCE6_EXT"/>
+                <enum name="GL_CLIP_DISTANCE7_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_clip_volume_hint" supported="gl">
+            <require>
+                <enum name="GL_CLIP_VOLUME_CLIPPING_HINT_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_cmyka" supported="gl">
+            <require>
+                <enum name="GL_CMYK_EXT"/>
+                <enum name="GL_CMYKA_EXT"/>
+                <enum name="GL_PACK_CMYK_HINT_EXT"/>
+                <enum name="GL_UNPACK_CMYK_HINT_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_color_buffer_float" supported="gles2"/>
+        <extension name="GL_EXT_color_buffer_half_float" supported="gles2">
+            <require>
+                <enum name="GL_RGBA16F_EXT"/>
+                <enum name="GL_RGB16F_EXT"/>
+                <enum name="GL_RG16F_EXT"/>
+                <enum name="GL_R16F_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT"/>
+                <enum name="GL_UNSIGNED_NORMALIZED_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_color_subtable" supported="gl">
+            <require>
+                <command name="glColorSubTableEXT"/>
+                <command name="glCopyColorSubTableEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_compiled_vertex_array" supported="gl">
+            <require>
+                <enum name="GL_ARRAY_ELEMENT_LOCK_FIRST_EXT"/>
+                <enum name="GL_ARRAY_ELEMENT_LOCK_COUNT_EXT"/>
+                <command name="glLockArraysEXT"/>
+                <command name="glUnlockArraysEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_conservative_depth" supported="gles2"/>
+        <extension name="GL_EXT_convolution" supported="gl">
+            <require>
+                <enum name="GL_CONVOLUTION_1D_EXT"/>
+                <enum name="GL_CONVOLUTION_2D_EXT"/>
+                <enum name="GL_SEPARABLE_2D_EXT"/>
+                <enum name="GL_CONVOLUTION_BORDER_MODE_EXT"/>
+                <enum name="GL_CONVOLUTION_FILTER_SCALE_EXT"/>
+                <enum name="GL_CONVOLUTION_FILTER_BIAS_EXT"/>
+                <enum name="GL_REDUCE_EXT"/>
+                <enum name="GL_CONVOLUTION_FORMAT_EXT"/>
+                <enum name="GL_CONVOLUTION_WIDTH_EXT"/>
+                <enum name="GL_CONVOLUTION_HEIGHT_EXT"/>
+                <enum name="GL_MAX_CONVOLUTION_WIDTH_EXT"/>
+                <enum name="GL_MAX_CONVOLUTION_HEIGHT_EXT"/>
+                <enum name="GL_POST_CONVOLUTION_RED_SCALE_EXT"/>
+                <enum name="GL_POST_CONVOLUTION_GREEN_SCALE_EXT"/>
+                <enum name="GL_POST_CONVOLUTION_BLUE_SCALE_EXT"/>
+                <enum name="GL_POST_CONVOLUTION_ALPHA_SCALE_EXT"/>
+                <enum name="GL_POST_CONVOLUTION_RED_BIAS_EXT"/>
+                <enum name="GL_POST_CONVOLUTION_GREEN_BIAS_EXT"/>
+                <enum name="GL_POST_CONVOLUTION_BLUE_BIAS_EXT"/>
+                <enum name="GL_POST_CONVOLUTION_ALPHA_BIAS_EXT"/>
+                <command name="glConvolutionFilter1DEXT"/>
+                <command name="glConvolutionFilter2DEXT"/>
+                <command name="glConvolutionParameterfEXT"/>
+                <command name="glConvolutionParameterfvEXT"/>
+                <command name="glConvolutionParameteriEXT"/>
+                <command name="glConvolutionParameterivEXT"/>
+                <command name="glCopyConvolutionFilter1DEXT"/>
+                <command name="glCopyConvolutionFilter2DEXT"/>
+                <command name="glGetConvolutionFilterEXT"/>
+                <command name="glGetConvolutionParameterfvEXT"/>
+                <command name="glGetConvolutionParameterivEXT"/>
+                <command name="glGetSeparableFilterEXT"/>
+                <command name="glSeparableFilter2DEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_coordinate_frame" supported="gl">
+            <require>
+                <enum name="GL_TANGENT_ARRAY_EXT"/>
+                <enum name="GL_BINORMAL_ARRAY_EXT"/>
+                <enum name="GL_CURRENT_TANGENT_EXT"/>
+                <enum name="GL_CURRENT_BINORMAL_EXT"/>
+                <enum name="GL_TANGENT_ARRAY_TYPE_EXT"/>
+                <enum name="GL_TANGENT_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_BINORMAL_ARRAY_TYPE_EXT"/>
+                <enum name="GL_BINORMAL_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_TANGENT_ARRAY_POINTER_EXT"/>
+                <enum name="GL_BINORMAL_ARRAY_POINTER_EXT"/>
+                <enum name="GL_MAP1_TANGENT_EXT"/>
+                <enum name="GL_MAP2_TANGENT_EXT"/>
+                <enum name="GL_MAP1_BINORMAL_EXT"/>
+                <enum name="GL_MAP2_BINORMAL_EXT"/>
+                <command name="glTangent3bEXT"/>
+                <command name="glTangent3bvEXT"/>
+                <command name="glTangent3dEXT"/>
+                <command name="glTangent3dvEXT"/>
+                <command name="glTangent3fEXT"/>
+                <command name="glTangent3fvEXT"/>
+                <command name="glTangent3iEXT"/>
+                <command name="glTangent3ivEXT"/>
+                <command name="glTangent3sEXT"/>
+                <command name="glTangent3svEXT"/>
+                <command name="glBinormal3bEXT"/>
+                <command name="glBinormal3bvEXT"/>
+                <command name="glBinormal3dEXT"/>
+                <command name="glBinormal3dvEXT"/>
+                <command name="glBinormal3fEXT"/>
+                <command name="glBinormal3fvEXT"/>
+                <command name="glBinormal3iEXT"/>
+                <command name="glBinormal3ivEXT"/>
+                <command name="glBinormal3sEXT"/>
+                <command name="glBinormal3svEXT"/>
+                <command name="glTangentPointerEXT"/>
+                <command name="glBinormalPointerEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_copy_image" supported="gles2">
+            <require>
+                <command name="glCopyImageSubDataEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_copy_texture" supported="gl">
+            <require>
+                <command name="glCopyTexImage1DEXT"/>
+                <command name="glCopyTexImage2DEXT"/>
+                <command name="glCopyTexSubImage1DEXT"/>
+                <command name="glCopyTexSubImage2DEXT"/>
+                <command name="glCopyTexSubImage3DEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_cull_vertex" supported="gl">
+            <require>
+                <enum name="GL_CULL_VERTEX_EXT"/>
+                <enum name="GL_CULL_VERTEX_EYE_POSITION_EXT"/>
+                <enum name="GL_CULL_VERTEX_OBJECT_POSITION_EXT"/>
+                <command name="glCullParameterdvEXT"/>
+                <command name="glCullParameterfvEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_debug_label" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_PROGRAM_PIPELINE_OBJECT_EXT"/>
+                <enum name="GL_PROGRAM_OBJECT_EXT"/>
+                <enum name="GL_SHADER_OBJECT_EXT"/>
+                <enum name="GL_BUFFER_OBJECT_EXT"/>
+                <enum name="GL_QUERY_OBJECT_EXT"/>
+                <enum name="GL_VERTEX_ARRAY_OBJECT_EXT"/>
+                <command name="glLabelObjectEXT"/>
+                <command name="glGetObjectLabelEXT"/>
+            </require>
+            <require comment="Depends on OpenGL ES 3.0">
+                <enum name="GL_SAMPLER"/>
+                <enum name="GL_TRANSFORM_FEEDBACK"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_debug_marker" supported="gl|glcore|gles2">
+            <require>
+                <command name="glInsertEventMarkerEXT"/>
+                <command name="glPushGroupMarkerEXT"/>
+                <command name="glPopGroupMarkerEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_depth_bounds_test" supported="gl">
+            <require>
+                <enum name="GL_DEPTH_BOUNDS_TEST_EXT"/>
+                <enum name="GL_DEPTH_BOUNDS_EXT"/>
+                <command name="glDepthBoundsEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_direct_state_access" supported="gl" comment="DSA extension doesn't identify which interfaces are core profile and keeps getting expanded. This is in sync with revision 34, 2010/09/07">
+            <require>
+                <enum name="GL_PROGRAM_MATRIX_EXT"/>
+                <enum name="GL_TRANSPOSE_PROGRAM_MATRIX_EXT"/>
+                <enum name="GL_PROGRAM_MATRIX_STACK_DEPTH_EXT"/>
+            </require>
+            <require comment="OpenGL 1.0: New matrix commands">
+                <command name="glMatrixLoadfEXT"/>
+                <command name="glMatrixLoaddEXT"/>
+                <command name="glMatrixMultfEXT"/>
+                <command name="glMatrixMultdEXT"/>
+                <command name="glMatrixLoadIdentityEXT"/>
+                <command name="glMatrixRotatefEXT"/>
+                <command name="glMatrixRotatedEXT"/>
+                <command name="glMatrixScalefEXT"/>
+                <command name="glMatrixScaledEXT"/>
+                <command name="glMatrixTranslatefEXT"/>
+                <command name="glMatrixTranslatedEXT"/>
+                <command name="glMatrixFrustumEXT"/>
+                <command name="glMatrixOrthoEXT"/>
+                <command name="glMatrixPopEXT"/>
+                <command name="glMatrixPushEXT"/>
+            </require>
+            <require comment="OpenGL 1.1: New client commands">
+                <command name="glClientAttribDefaultEXT"/>
+                <command name="glPushClientAttribDefaultEXT"/>
+            </require>
+            <require comment="OpenGL 1.1: New texture object commands">
+                <command name="glTextureParameterfEXT"/>
+                <command name="glTextureParameterfvEXT"/>
+                <command name="glTextureParameteriEXT"/>
+                <command name="glTextureParameterivEXT"/>
+                <command name="glTextureImage1DEXT"/>
+                <command name="glTextureImage2DEXT"/>
+                <command name="glTextureSubImage1DEXT"/>
+                <command name="glTextureSubImage2DEXT"/>
+                <command name="glCopyTextureImage1DEXT"/>
+                <command name="glCopyTextureImage2DEXT"/>
+                <command name="glCopyTextureSubImage1DEXT"/>
+                <command name="glCopyTextureSubImage2DEXT"/>
+                <command name="glGetTextureImageEXT"/>
+                <command name="glGetTextureParameterfvEXT"/>
+                <command name="glGetTextureParameterivEXT"/>
+                <command name="glGetTextureLevelParameterfvEXT"/>
+                <command name="glGetTextureLevelParameterivEXT"/>
+            </require>
+            <require comment="OpenGL 1.2: New 3D texture object commands">
+                <command name="glTextureImage3DEXT"/>
+                <command name="glTextureSubImage3DEXT"/>
+                <command name="glCopyTextureSubImage3DEXT"/>
+            </require>
+            <require comment="OpenGL 1.2.1: New multitexture commands">
+                <command name="glBindMultiTextureEXT"/>
+                <command name="glMultiTexCoordPointerEXT"/>
+                <command name="glMultiTexEnvfEXT"/>
+                <command name="glMultiTexEnvfvEXT"/>
+                <command name="glMultiTexEnviEXT"/>
+                <command name="glMultiTexEnvivEXT"/>
+                <command name="glMultiTexGendEXT"/>
+                <command name="glMultiTexGendvEXT"/>
+                <command name="glMultiTexGenfEXT"/>
+                <command name="glMultiTexGenfvEXT"/>
+                <command name="glMultiTexGeniEXT"/>
+                <command name="glMultiTexGenivEXT"/>
+                <command name="glGetMultiTexEnvfvEXT"/>
+                <command name="glGetMultiTexEnvivEXT"/>
+                <command name="glGetMultiTexGendvEXT"/>
+                <command name="glGetMultiTexGenfvEXT"/>
+                <command name="glGetMultiTexGenivEXT"/>
+                <command name="glMultiTexParameteriEXT"/>
+                <command name="glMultiTexParameterivEXT"/>
+                <command name="glMultiTexParameterfEXT"/>
+                <command name="glMultiTexParameterfvEXT"/>
+                <command name="glMultiTexImage1DEXT"/>
+                <command name="glMultiTexImage2DEXT"/>
+                <command name="glMultiTexSubImage1DEXT"/>
+                <command name="glMultiTexSubImage2DEXT"/>
+                <command name="glCopyMultiTexImage1DEXT"/>
+                <command name="glCopyMultiTexImage2DEXT"/>
+                <command name="glCopyMultiTexSubImage1DEXT"/>
+                <command name="glCopyMultiTexSubImage2DEXT"/>
+                <command name="glGetMultiTexImageEXT"/>
+                <command name="glGetMultiTexParameterfvEXT"/>
+                <command name="glGetMultiTexParameterivEXT"/>
+                <command name="glGetMultiTexLevelParameterfvEXT"/>
+                <command name="glGetMultiTexLevelParameterivEXT"/>
+                <command name="glMultiTexImage3DEXT"/>
+                <command name="glMultiTexSubImage3DEXT"/>
+                <command name="glCopyMultiTexSubImage3DEXT"/>
+            </require>
+            <require comment="OpenGL 1.2.1: New indexed texture commands">
+                <command name="glEnableClientStateIndexedEXT"/>
+                <command name="glDisableClientStateIndexedEXT"/>
+            </require>
+            <require comment="OpenGL 1.2.1: New indexed generic queries">
+                <command name="glGetFloatIndexedvEXT"/>
+                <command name="glGetDoubleIndexedvEXT"/>
+                <command name="glGetPointerIndexedvEXT"/>
+            </require>
+            <require comment="OpenGL 1.2.1: Extend EXT_draw_buffers2 commands">
+                <command name="glEnableIndexedEXT"/>
+                <command name="glDisableIndexedEXT"/>
+                <command name="glIsEnabledIndexedEXT"/>
+                <command name="glGetIntegerIndexedvEXT"/>
+                <command name="glGetBooleanIndexedvEXT"/>
+            </require>
+            <require comment="OpenGL 1.3: New compressed texture object commands">
+                <command name="glCompressedTextureImage3DEXT"/>
+                <command name="glCompressedTextureImage2DEXT"/>
+                <command name="glCompressedTextureImage1DEXT"/>
+                <command name="glCompressedTextureSubImage3DEXT"/>
+                <command name="glCompressedTextureSubImage2DEXT"/>
+                <command name="glCompressedTextureSubImage1DEXT"/>
+                <command name="glGetCompressedTextureImageEXT"/>
+            </require>
+            <require comment="OpenGL 1.3: New multitexture compressed texture commands">
+                <command name="glCompressedMultiTexImage3DEXT"/>
+                <command name="glCompressedMultiTexImage2DEXT"/>
+                <command name="glCompressedMultiTexImage1DEXT"/>
+                <command name="glCompressedMultiTexSubImage3DEXT"/>
+                <command name="glCompressedMultiTexSubImage2DEXT"/>
+                <command name="glCompressedMultiTexSubImage1DEXT"/>
+                <command name="glGetCompressedMultiTexImageEXT"/>
+            </require>
+            <require comment="OpenGL 1.3: New transpose matrix commands">
+                <command name="glMatrixLoadTransposefEXT"/>
+                <command name="glMatrixLoadTransposedEXT"/>
+                <command name="glMatrixMultTransposefEXT"/>
+                <command name="glMatrixMultTransposedEXT"/>
+            </require>
+            <require comment="OpenGL 1.5: New buffer commands">
+                <command name="glNamedBufferDataEXT"/>
+                <command name="glNamedBufferSubDataEXT"/>
+                <command name="glMapNamedBufferEXT"/>
+                <command name="glUnmapNamedBufferEXT"/>
+                <command name="glGetNamedBufferParameterivEXT"/>
+                <command name="glGetNamedBufferPointervEXT"/>
+                <command name="glGetNamedBufferSubDataEXT"/>
+            </require>
+            <require comment="OpenGL 2.0: New uniform commands">
+                <command name="glProgramUniform1fEXT"/>
+                <command name="glProgramUniform2fEXT"/>
+                <command name="glProgramUniform3fEXT"/>
+                <command name="glProgramUniform4fEXT"/>
+                <command name="glProgramUniform1iEXT"/>
+                <command name="glProgramUniform2iEXT"/>
+                <command name="glProgramUniform3iEXT"/>
+                <command name="glProgramUniform4iEXT"/>
+                <command name="glProgramUniform1fvEXT"/>
+                <command name="glProgramUniform2fvEXT"/>
+                <command name="glProgramUniform3fvEXT"/>
+                <command name="glProgramUniform4fvEXT"/>
+                <command name="glProgramUniform1ivEXT"/>
+                <command name="glProgramUniform2ivEXT"/>
+                <command name="glProgramUniform3ivEXT"/>
+                <command name="glProgramUniform4ivEXT"/>
+                <command name="glProgramUniformMatrix2fvEXT"/>
+                <command name="glProgramUniformMatrix3fvEXT"/>
+                <command name="glProgramUniformMatrix4fvEXT"/>
+            </require>
+            <require comment="OpenGL 2.1: New uniform matrix commands">
+                <command name="glProgramUniformMatrix2x3fvEXT"/>
+                <command name="glProgramUniformMatrix3x2fvEXT"/>
+                <command name="glProgramUniformMatrix2x4fvEXT"/>
+                <command name="glProgramUniformMatrix4x2fvEXT"/>
+                <command name="glProgramUniformMatrix3x4fvEXT"/>
+                <command name="glProgramUniformMatrix4x3fvEXT"/>
+            </require>
+            <require comment="Extend EXT_texture_buffer_object commands">
+                <command name="glTextureBufferEXT"/>
+                <command name="glMultiTexBufferEXT"/>
+            </require>
+            <require comment="Extend EXT_texture_integer commands">
+                <command name="glTextureParameterIivEXT"/>
+                <command name="glTextureParameterIuivEXT"/>
+                <command name="glGetTextureParameterIivEXT"/>
+                <command name="glGetTextureParameterIuivEXT"/>
+                <command name="glMultiTexParameterIivEXT"/>
+                <command name="glMultiTexParameterIuivEXT"/>
+                <command name="glGetMultiTexParameterIivEXT"/>
+                <command name="glGetMultiTexParameterIuivEXT"/>
+            </require>
+            <require comment="Extend EXT_gpu_shader4 commands">
+                <command name="glProgramUniform1uiEXT"/>
+                <command name="glProgramUniform2uiEXT"/>
+                <command name="glProgramUniform3uiEXT"/>
+                <command name="glProgramUniform4uiEXT"/>
+                <command name="glProgramUniform1uivEXT"/>
+                <command name="glProgramUniform2uivEXT"/>
+                <command name="glProgramUniform3uivEXT"/>
+                <command name="glProgramUniform4uivEXT"/>
+            </require>
+            <require comment="Extend EXT_gpu_program_parameters commands">
+                <command name="glNamedProgramLocalParameters4fvEXT"/>
+            </require>
+            <require comment="Extend NV_gpu_program4 commands">
+                <command name="glNamedProgramLocalParameterI4iEXT"/>
+                <command name="glNamedProgramLocalParameterI4ivEXT"/>
+                <command name="glNamedProgramLocalParametersI4ivEXT"/>
+                <command name="glNamedProgramLocalParameterI4uiEXT"/>
+                <command name="glNamedProgramLocalParameterI4uivEXT"/>
+                <command name="glNamedProgramLocalParametersI4uivEXT"/>
+                <command name="glGetNamedProgramLocalParameterIivEXT"/>
+                <command name="glGetNamedProgramLocalParameterIuivEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New indexed texture commands">
+                <command name="glEnableClientStateiEXT"/>
+                <command name="glDisableClientStateiEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New indexed generic queries">
+                <command name="glGetFloati_vEXT"/>
+                <command name="glGetDoublei_vEXT"/>
+                <command name="glGetPointeri_vEXT"/>
+            </require>
+            <require comment="Extend GL_ARB_vertex_program commands">
+                <command name="glNamedProgramStringEXT"/>
+                <command name="glNamedProgramLocalParameter4dEXT"/>
+                <command name="glNamedProgramLocalParameter4dvEXT"/>
+                <command name="glNamedProgramLocalParameter4fEXT"/>
+                <command name="glNamedProgramLocalParameter4fvEXT"/>
+                <command name="glGetNamedProgramLocalParameterdvEXT"/>
+                <command name="glGetNamedProgramLocalParameterfvEXT"/>
+                <command name="glGetNamedProgramivEXT"/>
+                <command name="glGetNamedProgramStringEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New renderbuffer commands">
+                <command name="glNamedRenderbufferStorageEXT"/>
+                <command name="glGetNamedRenderbufferParameterivEXT"/>
+                <command name="glNamedRenderbufferStorageMultisampleEXT"/>
+            </require>
+            <require comment="Extend NV_framebuffer_multisample_coverage">
+                <command name="glNamedRenderbufferStorageMultisampleCoverageEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New framebuffer commands">
+                <command name="glCheckNamedFramebufferStatusEXT"/>
+                <command name="glNamedFramebufferTexture1DEXT"/>
+                <command name="glNamedFramebufferTexture2DEXT"/>
+                <command name="glNamedFramebufferTexture3DEXT"/>
+                <command name="glNamedFramebufferRenderbufferEXT"/>
+                <command name="glGetNamedFramebufferAttachmentParameterivEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New texture commands">
+                <command name="glGenerateTextureMipmapEXT"/>
+                <command name="glGenerateMultiTexMipmapEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New framebuffer commands">
+                <command name="glFramebufferDrawBufferEXT"/>
+                <command name="glFramebufferDrawBuffersEXT"/>
+                <command name="glFramebufferReadBufferEXT"/>
+                <command name="glGetFramebufferParameterivEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New buffer data copy command">
+                <command name="glNamedCopyBufferSubDataEXT"/>
+            </require>
+            <require comment="Extend EXT_geometry_shader4 or NV_gpu_program4">
+                <command name="glNamedFramebufferTextureEXT"/>
+                <command name="glNamedFramebufferTextureLayerEXT"/>
+                <command name="glNamedFramebufferTextureFaceEXT"/>
+            </require>
+            <require comment="Extend NV_explicit_multisample">
+                <command name="glTextureRenderbufferEXT"/>
+                <command name="glMultiTexRenderbufferEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New vertex array specification commands for VAO">
+                <command name="glVertexArrayVertexOffsetEXT"/>
+                <command name="glVertexArrayColorOffsetEXT"/>
+                <command name="glVertexArrayEdgeFlagOffsetEXT"/>
+                <command name="glVertexArrayIndexOffsetEXT"/>
+                <command name="glVertexArrayNormalOffsetEXT"/>
+                <command name="glVertexArrayTexCoordOffsetEXT"/>
+                <command name="glVertexArrayMultiTexCoordOffsetEXT"/>
+                <command name="glVertexArrayFogCoordOffsetEXT"/>
+                <command name="glVertexArraySecondaryColorOffsetEXT"/>
+                <command name="glVertexArrayVertexAttribOffsetEXT"/>
+                <command name="glVertexArrayVertexAttribIOffsetEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New vertex array enable commands for VAO">
+                <command name="glEnableVertexArrayEXT"/>
+                <command name="glDisableVertexArrayEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New vertex attrib array enable commands for VAO">
+                <command name="glEnableVertexArrayAttribEXT"/>
+                <command name="glDisableVertexArrayAttribEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New queries for VAO">
+                <command name="glGetVertexArrayIntegervEXT"/>
+                <command name="glGetVertexArrayPointervEXT"/>
+                <command name="glGetVertexArrayIntegeri_vEXT"/>
+                <command name="glGetVertexArrayPointeri_vEXT"/>
+            </require>
+            <require comment="OpenGL 3.0: New buffer commands">
+                <command name="glMapNamedBufferRangeEXT"/>
+                <command name="glFlushMappedNamedBufferRangeEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_buffer_storage">
+                <command name="glNamedBufferStorageEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_clear_buffer_object">
+                <command name="glClearNamedBufferDataEXT"/>
+                <command name="glClearNamedBufferSubDataEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_framebuffer_no_attachments">
+                <command name="glNamedFramebufferParameteriEXT"/>
+                <command name="glGetNamedFramebufferParameterivEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_gpu_shader_fp64">
+                <command name="glProgramUniform1dEXT"/>
+                <command name="glProgramUniform2dEXT"/>
+                <command name="glProgramUniform3dEXT"/>
+                <command name="glProgramUniform4dEXT"/>
+                <command name="glProgramUniform1dvEXT"/>
+                <command name="glProgramUniform2dvEXT"/>
+                <command name="glProgramUniform3dvEXT"/>
+                <command name="glProgramUniform4dvEXT"/>
+                <command name="glProgramUniformMatrix2dvEXT"/>
+                <command name="glProgramUniformMatrix3dvEXT"/>
+                <command name="glProgramUniformMatrix4dvEXT"/>
+                <command name="glProgramUniformMatrix2x3dvEXT"/>
+                <command name="glProgramUniformMatrix2x4dvEXT"/>
+                <command name="glProgramUniformMatrix3x2dvEXT"/>
+                <command name="glProgramUniformMatrix3x4dvEXT"/>
+                <command name="glProgramUniformMatrix4x2dvEXT"/>
+                <command name="glProgramUniformMatrix4x3dvEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_texture_buffer_range">
+                <command name="glTextureBufferRangeEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_texture_storage">
+                <command name="glTextureStorage1DEXT"/>
+                <command name="glTextureStorage2DEXT"/>
+                <command name="glTextureStorage3DEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_texture_storage_multisample">
+                <command name="glTextureStorage2DMultisampleEXT"/>
+                <command name="glTextureStorage3DMultisampleEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_vertex_attrib_binding">
+                <command name="glVertexArrayBindVertexBufferEXT"/>
+                <command name="glVertexArrayVertexAttribFormatEXT"/>
+                <command name="glVertexArrayVertexAttribIFormatEXT"/>
+                <command name="glVertexArrayVertexAttribLFormatEXT"/>
+                <command name="glVertexArrayVertexAttribBindingEXT"/>
+                <command name="glVertexArrayVertexBindingDivisorEXT"/>
+            </require>
+            <require comment="Extended by GL_EXT_vertex_attrib_64bit">
+                <command name="glVertexArrayVertexAttribLOffsetEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_sparse_texture">
+                <command name="glTexturePageCommitmentEXT"/>
+            </require>
+            <require comment="Extended by GL_ARB_instanced_arrays">
+                <command name="glVertexArrayVertexAttribDivisorEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_discard_framebuffer" supported="gles1|gles2">
+            <require>
+                <enum name="GL_COLOR_EXT"/>
+                <enum name="GL_DEPTH_EXT"/>
+                <enum name="GL_STENCIL_EXT"/>
+                <command name="glDiscardFramebufferEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_disjoint_timer_query" supported="gles2">
+            <require>
+                <enum name="GL_QUERY_COUNTER_BITS_EXT"/>
+                <enum name="GL_CURRENT_QUERY_EXT"/>
+                <enum name="GL_QUERY_RESULT_EXT"/>
+                <enum name="GL_QUERY_RESULT_AVAILABLE_EXT"/>
+                <enum name="GL_TIME_ELAPSED_EXT"/>
+                <enum name="GL_TIMESTAMP_EXT"/>
+                <enum name="GL_GPU_DISJOINT_EXT"/>
+                <command name="glGenQueriesEXT"/>
+                <command name="glDeleteQueriesEXT"/>
+                <command name="glIsQueryEXT"/>
+                <command name="glBeginQueryEXT"/>
+                <command name="glEndQueryEXT"/>
+                <command name="glQueryCounterEXT"/>
+                <command name="glGetQueryivEXT"/>
+                <command name="glGetQueryObjectivEXT"/>
+                <command name="glGetQueryObjectuivEXT"/>
+                <command name="glGetQueryObjecti64vEXT"/>
+                <command name="glGetQueryObjectui64vEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_draw_buffers" supported="gles2">
+            <require>
+                <enum name="GL_MAX_COLOR_ATTACHMENTS_EXT"/>
+                <enum name="GL_MAX_DRAW_BUFFERS_EXT"/>
+                <enum name="GL_DRAW_BUFFER0_EXT"/>
+                <enum name="GL_DRAW_BUFFER1_EXT"/>
+                <enum name="GL_DRAW_BUFFER2_EXT"/>
+                <enum name="GL_DRAW_BUFFER3_EXT"/>
+                <enum name="GL_DRAW_BUFFER4_EXT"/>
+                <enum name="GL_DRAW_BUFFER5_EXT"/>
+                <enum name="GL_DRAW_BUFFER6_EXT"/>
+                <enum name="GL_DRAW_BUFFER7_EXT"/>
+                <enum name="GL_DRAW_BUFFER8_EXT"/>
+                <enum name="GL_DRAW_BUFFER9_EXT"/>
+                <enum name="GL_DRAW_BUFFER10_EXT"/>
+                <enum name="GL_DRAW_BUFFER11_EXT"/>
+                <enum name="GL_DRAW_BUFFER12_EXT"/>
+                <enum name="GL_DRAW_BUFFER13_EXT"/>
+                <enum name="GL_DRAW_BUFFER14_EXT"/>
+                <enum name="GL_DRAW_BUFFER15_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT0_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT1_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT2_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT3_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT4_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT5_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT6_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT7_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT8_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT9_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT10_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT11_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT12_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT13_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT14_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT15_EXT"/>
+                <command name="glDrawBuffersEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_draw_buffers2" supported="gl">
+            <require>
+                <command name="glColorMaskIndexedEXT"/>
+                <command name="glGetBooleanIndexedvEXT"/>
+                <command name="glGetIntegerIndexedvEXT"/>
+                <command name="glEnableIndexedEXT"/>
+                <command name="glDisableIndexedEXT"/>
+                <command name="glIsEnabledIndexedEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_draw_buffers_indexed" supported="gles2">
+            <require>
+                <enum name="GL_BLEND_EQUATION_RGB"/>
+                <enum name="GL_BLEND_EQUATION_ALPHA"/>
+                <enum name="GL_BLEND_SRC_RGB"/>
+                <enum name="GL_BLEND_SRC_ALPHA"/>
+                <enum name="GL_BLEND_DST_RGB"/>
+                <enum name="GL_BLEND_DST_ALPHA"/>
+                <enum name="GL_COLOR_WRITEMASK"/>
+                <enum name="GL_BLEND"/>
+                <enum name="GL_FUNC_ADD"/>
+                <enum name="GL_FUNC_SUBTRACT"/>
+                <enum name="GL_FUNC_REVERSE_SUBTRACT"/>
+                <enum name="GL_MIN"/>
+                <enum name="GL_MAX"/>
+                <enum name="GL_ZERO"/>
+                <enum name="GL_ONE"/>
+                <enum name="GL_SRC_COLOR"/>
+                <enum name="GL_ONE_MINUS_SRC_COLOR"/>
+                <enum name="GL_DST_COLOR"/>
+                <enum name="GL_ONE_MINUS_DST_COLOR"/>
+                <enum name="GL_SRC_ALPHA"/>
+                <enum name="GL_ONE_MINUS_SRC_ALPHA"/>
+                <enum name="GL_DST_ALPHA"/>
+                <enum name="GL_ONE_MINUS_DST_ALPHA"/>
+                <enum name="GL_CONSTANT_COLOR"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_COLOR"/>
+                <enum name="GL_CONSTANT_ALPHA"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_ALPHA"/>
+                <enum name="GL_SRC_ALPHA_SATURATE"/>
+                <command name="glEnableiEXT"/>
+                <command name="glDisableiEXT"/>
+                <command name="glBlendEquationiEXT"/>
+                <command name="glBlendEquationSeparateiEXT"/>
+                <command name="glBlendFunciEXT"/>
+                <command name="glBlendFuncSeparateiEXT"/>
+                <command name="glColorMaskiEXT"/>
+                <command name="glIsEnablediEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_draw_elements_base_vertex" supported="gles2">
+            <require>
+                <command name="glDrawElementsBaseVertexEXT"/>
+                <command name="glDrawRangeElementsBaseVertexEXT" comment="Supported only if OpenGL ES 3.0 is supported"/>
+                <command name="glDrawElementsInstancedBaseVertexEXT" comment="Supported only if OpenGL ES 3.0 is supported"/>
+                <command name="glMultiDrawElementsBaseVertexEXT" comment="Supported only if GL_EXT_multi_draw_arrays is supported"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_draw_instanced" supported="gl|glcore|gles2">
+            <require>
+                <command name="glDrawArraysInstancedEXT"/>
+                <command name="glDrawElementsInstancedEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_draw_range_elements" supported="gl">
+            <require>
+                <enum name="GL_MAX_ELEMENTS_VERTICES_EXT"/>
+                <enum name="GL_MAX_ELEMENTS_INDICES_EXT"/>
+                <command name="glDrawRangeElementsEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_draw_transform_feedback" supported="gles2">
+            <require>
+                <command name="glDrawTransformFeedbackEXT"/>
+                <command name="glDrawTransformFeedbackInstancedEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_float_blend" supported="gles2"/>
+        <extension name="GL_EXT_fog_coord" supported="gl">
+            <require>
+                <enum name="GL_FOG_COORDINATE_SOURCE_EXT"/>
+                <enum name="GL_FOG_COORDINATE_EXT"/>
+                <enum name="GL_FRAGMENT_DEPTH_EXT"/>
+                <enum name="GL_CURRENT_FOG_COORDINATE_EXT"/>
+                <enum name="GL_FOG_COORDINATE_ARRAY_TYPE_EXT"/>
+                <enum name="GL_FOG_COORDINATE_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_FOG_COORDINATE_ARRAY_POINTER_EXT"/>
+                <enum name="GL_FOG_COORDINATE_ARRAY_EXT"/>
+                <command name="glFogCoordfEXT"/>
+                <command name="glFogCoordfvEXT"/>
+                <command name="glFogCoorddEXT"/>
+                <command name="glFogCoorddvEXT"/>
+                <command name="glFogCoordPointerEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_framebuffer_blit" supported="gl">
+            <require>
+                <enum name="GL_READ_FRAMEBUFFER_EXT"/>
+                <enum name="GL_DRAW_FRAMEBUFFER_EXT"/>
+                <enum name="GL_DRAW_FRAMEBUFFER_BINDING_EXT"/>
+                <enum name="GL_READ_FRAMEBUFFER_BINDING_EXT"/>
+                <command name="glBlitFramebufferEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_framebuffer_multisample" supported="gl">
+            <require>
+                <enum name="GL_RENDERBUFFER_SAMPLES_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT"/>
+                <enum name="GL_MAX_SAMPLES_EXT"/>
+                <command name="glRenderbufferStorageMultisampleEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_framebuffer_multisample_blit_scaled" supported="gl">
+            <require>
+                <enum name="GL_SCALED_RESOLVE_FASTEST_EXT"/>
+                <enum name="GL_SCALED_RESOLVE_NICEST_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_framebuffer_object" supported="gl">
+            <require>
+                <enum name="GL_INVALID_FRAMEBUFFER_OPERATION_EXT"/>
+                <enum name="GL_MAX_RENDERBUFFER_SIZE_EXT"/>
+                <enum name="GL_FRAMEBUFFER_BINDING_EXT"/>
+                <enum name="GL_RENDERBUFFER_BINDING_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT"/>
+                <enum name="GL_FRAMEBUFFER_COMPLETE_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT"/>
+                <enum name="GL_FRAMEBUFFER_UNSUPPORTED_EXT"/>
+                <enum name="GL_MAX_COLOR_ATTACHMENTS_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT0_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT1_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT2_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT3_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT4_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT5_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT6_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT7_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT8_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT9_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT10_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT11_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT12_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT13_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT14_EXT"/>
+                <enum name="GL_COLOR_ATTACHMENT15_EXT"/>
+                <enum name="GL_DEPTH_ATTACHMENT_EXT"/>
+                <enum name="GL_STENCIL_ATTACHMENT_EXT"/>
+                <enum name="GL_FRAMEBUFFER_EXT"/>
+                <enum name="GL_RENDERBUFFER_EXT"/>
+                <enum name="GL_RENDERBUFFER_WIDTH_EXT"/>
+                <enum name="GL_RENDERBUFFER_HEIGHT_EXT"/>
+                <enum name="GL_RENDERBUFFER_INTERNAL_FORMAT_EXT"/>
+                <enum name="GL_STENCIL_INDEX1_EXT"/>
+                <enum name="GL_STENCIL_INDEX4_EXT"/>
+                <enum name="GL_STENCIL_INDEX8_EXT"/>
+                <enum name="GL_STENCIL_INDEX16_EXT"/>
+                <enum name="GL_RENDERBUFFER_RED_SIZE_EXT"/>
+                <enum name="GL_RENDERBUFFER_GREEN_SIZE_EXT"/>
+                <enum name="GL_RENDERBUFFER_BLUE_SIZE_EXT"/>
+                <enum name="GL_RENDERBUFFER_ALPHA_SIZE_EXT"/>
+                <enum name="GL_RENDERBUFFER_DEPTH_SIZE_EXT"/>
+                <enum name="GL_RENDERBUFFER_STENCIL_SIZE_EXT"/>
+                <command name="glIsRenderbufferEXT"/>
+                <command name="glBindRenderbufferEXT"/>
+                <command name="glDeleteRenderbuffersEXT"/>
+                <command name="glGenRenderbuffersEXT"/>
+                <command name="glRenderbufferStorageEXT"/>
+                <command name="glGetRenderbufferParameterivEXT"/>
+                <command name="glIsFramebufferEXT"/>
+                <command name="glBindFramebufferEXT"/>
+                <command name="glDeleteFramebuffersEXT"/>
+                <command name="glGenFramebuffersEXT"/>
+                <command name="glCheckFramebufferStatusEXT"/>
+                <command name="glFramebufferTexture1DEXT"/>
+                <command name="glFramebufferTexture2DEXT"/>
+                <command name="glFramebufferTexture3DEXT"/>
+                <command name="glFramebufferRenderbufferEXT"/>
+                <command name="glGetFramebufferAttachmentParameterivEXT"/>
+                <command name="glGenerateMipmapEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_framebuffer_sRGB" supported="gl">
+            <require>
+                <enum name="GL_FRAMEBUFFER_SRGB_EXT"/>
+                <enum name="GL_FRAMEBUFFER_SRGB_CAPABLE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_geometry_point_size" supported="gles2"/>
+        <extension name="GL_EXT_geometry_shader" supported="gles2">
+            <require>
+                <enum name="GL_GEOMETRY_SHADER_EXT"/>
+                <enum name="GL_GEOMETRY_SHADER_BIT_EXT"/>
+                <enum name="GL_GEOMETRY_LINKED_VERTICES_OUT_EXT"/>
+                <enum name="GL_GEOMETRY_LINKED_INPUT_TYPE_EXT"/>
+                <enum name="GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT"/>
+                <enum name="GL_GEOMETRY_SHADER_INVOCATIONS_EXT"/>
+                <enum name="GL_LAYER_PROVOKING_VERTEX_EXT"/>
+                <enum name="GL_LINES_ADJACENCY_EXT"/>
+                <enum name="GL_LINE_STRIP_ADJACENCY_EXT"/>
+                <enum name="GL_TRIANGLES_ADJACENCY_EXT"/>
+                <enum name="GL_TRIANGLE_STRIP_ADJACENCY_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT"/>
+                <enum name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT"/>
+                <enum name="GL_FIRST_VERTEX_CONVENTION_EXT"/>
+                <enum name="GL_LAST_VERTEX_CONVENTION_EXT"/>
+                <enum name="GL_UNDEFINED_VERTEX_EXT"/>
+                <enum name="GL_PRIMITIVES_GENERATED_EXT"/>
+                <enum name="GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT"/>
+                <enum name="GL_MAX_FRAMEBUFFER_LAYERS_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT"/>
+                <enum name="GL_REFERENCED_BY_GEOMETRY_SHADER_EXT"/>
+                <command name="glFramebufferTextureEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_geometry_shader4" supported="gl">
+            <require>
+                <enum name="GL_GEOMETRY_SHADER_EXT"/>
+                <enum name="GL_GEOMETRY_VERTICES_OUT_EXT"/>
+                <enum name="GL_GEOMETRY_INPUT_TYPE_EXT"/>
+                <enum name="GL_GEOMETRY_OUTPUT_TYPE_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_VERTEX_VARYING_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_VARYING_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT"/>
+                <enum name="GL_LINES_ADJACENCY_EXT"/>
+                <enum name="GL_LINE_STRIP_ADJACENCY_EXT"/>
+                <enum name="GL_TRIANGLES_ADJACENCY_EXT"/>
+                <enum name="GL_TRIANGLE_STRIP_ADJACENCY_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT"/>
+                <enum name="GL_PROGRAM_POINT_SIZE_EXT"/>
+                <command name="glProgramParameteriEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_gpu_program_parameters" supported="gl">
+            <require>
+                <command name="glProgramEnvParameters4fvEXT"/>
+                <command name="glProgramLocalParameters4fvEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_gpu_shader4" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT"/>
+                <enum name="GL_SAMPLER_1D_ARRAY_EXT"/>
+                <enum name="GL_SAMPLER_2D_ARRAY_EXT"/>
+                <enum name="GL_SAMPLER_BUFFER_EXT"/>
+                <enum name="GL_SAMPLER_1D_ARRAY_SHADOW_EXT"/>
+                <enum name="GL_SAMPLER_2D_ARRAY_SHADOW_EXT"/>
+                <enum name="GL_SAMPLER_CUBE_SHADOW_EXT"/>
+                <enum name="GL_UNSIGNED_INT_VEC2_EXT"/>
+                <enum name="GL_UNSIGNED_INT_VEC3_EXT"/>
+                <enum name="GL_UNSIGNED_INT_VEC4_EXT"/>
+                <enum name="GL_INT_SAMPLER_1D_EXT"/>
+                <enum name="GL_INT_SAMPLER_2D_EXT"/>
+                <enum name="GL_INT_SAMPLER_3D_EXT"/>
+                <enum name="GL_INT_SAMPLER_CUBE_EXT"/>
+                <enum name="GL_INT_SAMPLER_2D_RECT_EXT"/>
+                <enum name="GL_INT_SAMPLER_1D_ARRAY_EXT"/>
+                <enum name="GL_INT_SAMPLER_2D_ARRAY_EXT"/>
+                <enum name="GL_INT_SAMPLER_BUFFER_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_1D_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_2D_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_3D_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT"/>
+                <enum name="GL_MIN_PROGRAM_TEXEL_OFFSET_EXT"/>
+                <enum name="GL_MAX_PROGRAM_TEXEL_OFFSET_EXT"/>
+                <command name="glGetUniformuivEXT"/>
+                <command name="glBindFragDataLocationEXT"/>
+                <command name="glGetFragDataLocationEXT"/>
+                <command name="glUniform1uiEXT"/>
+                <command name="glUniform2uiEXT"/>
+                <command name="glUniform3uiEXT"/>
+                <command name="glUniform4uiEXT"/>
+                <command name="glUniform1uivEXT"/>
+                <command name="glUniform2uivEXT"/>
+                <command name="glUniform3uivEXT"/>
+                <command name="glUniform4uivEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_gpu_shader5" supported="gles2"/>
+        <extension name="GL_EXT_histogram" supported="gl">
+            <require>
+                <enum name="GL_HISTOGRAM_EXT"/>
+                <enum name="GL_PROXY_HISTOGRAM_EXT"/>
+                <enum name="GL_HISTOGRAM_WIDTH_EXT"/>
+                <enum name="GL_HISTOGRAM_FORMAT_EXT"/>
+                <enum name="GL_HISTOGRAM_RED_SIZE_EXT"/>
+                <enum name="GL_HISTOGRAM_GREEN_SIZE_EXT"/>
+                <enum name="GL_HISTOGRAM_BLUE_SIZE_EXT"/>
+                <enum name="GL_HISTOGRAM_ALPHA_SIZE_EXT"/>
+                <enum name="GL_HISTOGRAM_LUMINANCE_SIZE_EXT"/>
+                <enum name="GL_HISTOGRAM_SINK_EXT"/>
+                <enum name="GL_MINMAX_EXT"/>
+                <enum name="GL_MINMAX_FORMAT_EXT"/>
+                <enum name="GL_MINMAX_SINK_EXT"/>
+                <enum name="GL_TABLE_TOO_LARGE_EXT"/>
+                <command name="glGetHistogramEXT"/>
+                <command name="glGetHistogramParameterfvEXT"/>
+                <command name="glGetHistogramParameterivEXT"/>
+                <command name="glGetMinmaxEXT"/>
+                <command name="glGetMinmaxParameterfvEXT"/>
+                <command name="glGetMinmaxParameterivEXT"/>
+                <command name="glHistogramEXT"/>
+                <command name="glMinmaxEXT"/>
+                <command name="glResetHistogramEXT"/>
+                <command name="glResetMinmaxEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_index_array_formats" supported="gl">
+            <require>
+                <enum name="GL_IUI_V2F_EXT"/>
+                <enum name="GL_IUI_V3F_EXT"/>
+                <enum name="GL_IUI_N3F_V2F_EXT"/>
+                <enum name="GL_IUI_N3F_V3F_EXT"/>
+                <enum name="GL_T2F_IUI_V2F_EXT"/>
+                <enum name="GL_T2F_IUI_V3F_EXT"/>
+                <enum name="GL_T2F_IUI_N3F_V2F_EXT"/>
+                <enum name="GL_T2F_IUI_N3F_V3F_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_index_func" supported="gl">
+            <require>
+                <enum name="GL_INDEX_TEST_EXT"/>
+                <enum name="GL_INDEX_TEST_FUNC_EXT"/>
+                <enum name="GL_INDEX_TEST_REF_EXT"/>
+                <command name="glIndexFuncEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_index_material" supported="gl">
+            <require>
+                <enum name="GL_INDEX_MATERIAL_EXT"/>
+                <enum name="GL_INDEX_MATERIAL_PARAMETER_EXT"/>
+                <enum name="GL_INDEX_MATERIAL_FACE_EXT"/>
+                <command name="glIndexMaterialEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_index_texture" supported="gl"/>
+        <extension name="GL_EXT_instanced_arrays" supported="gles2">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT"/>
+                <command name="glDrawArraysInstancedEXT"/>
+                <command name="glDrawElementsInstancedEXT"/>
+                <command name="glVertexAttribDivisorEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_light_texture" supported="gl">
+            <require>
+                <enum name="GL_FRAGMENT_MATERIAL_EXT"/>
+                <enum name="GL_FRAGMENT_NORMAL_EXT"/>
+                <enum name="GL_FRAGMENT_COLOR_EXT"/>
+                <enum name="GL_ATTENUATION_EXT"/>
+                <enum name="GL_SHADOW_ATTENUATION_EXT"/>
+                <enum name="GL_TEXTURE_APPLICATION_MODE_EXT"/>
+                <enum name="GL_TEXTURE_LIGHT_EXT"/>
+                <enum name="GL_TEXTURE_MATERIAL_FACE_EXT"/>
+                <enum name="GL_TEXTURE_MATERIAL_PARAMETER_EXT"/>
+                <enum name="GL_FRAGMENT_DEPTH_EXT"/>
+                <command name="glApplyTextureEXT"/>
+                <command name="glTextureLightEXT"/>
+                <command name="glTextureMaterialEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_map_buffer_range" supported="gles1|gles2">
+            <require>
+                <enum name="GL_MAP_READ_BIT_EXT"/>
+                <enum name="GL_MAP_WRITE_BIT_EXT"/>
+                <enum name="GL_MAP_INVALIDATE_RANGE_BIT_EXT"/>
+                <enum name="GL_MAP_INVALIDATE_BUFFER_BIT_EXT"/>
+                <enum name="GL_MAP_FLUSH_EXPLICIT_BIT_EXT"/>
+                <enum name="GL_MAP_UNSYNCHRONIZED_BIT_EXT"/>
+                <command name="glMapBufferRangeEXT"/>
+                <command name="glFlushMappedBufferRangeEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_misc_attribute" supported="gl"/>
+        <extension name="GL_EXT_multi_draw_arrays" supported="gl|gles1|gles2">
+            <require>
+                <command name="glMultiDrawArraysEXT"/>
+                <command name="glMultiDrawElementsEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_multi_draw_indirect" supported="gles2">
+            <require>
+                <command name="glMultiDrawArraysIndirectEXT"/>
+                <command name="glMultiDrawElementsIndirectEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_multisample" supported="gl">
+            <require>
+                <enum name="GL_MULTISAMPLE_EXT"/>
+                <enum name="GL_SAMPLE_ALPHA_TO_MASK_EXT"/>
+                <enum name="GL_SAMPLE_ALPHA_TO_ONE_EXT"/>
+                <enum name="GL_SAMPLE_MASK_EXT"/>
+                <enum name="GL_1PASS_EXT"/>
+                <enum name="GL_2PASS_0_EXT"/>
+                <enum name="GL_2PASS_1_EXT"/>
+                <enum name="GL_4PASS_0_EXT"/>
+                <enum name="GL_4PASS_1_EXT"/>
+                <enum name="GL_4PASS_2_EXT"/>
+                <enum name="GL_4PASS_3_EXT"/>
+                <enum name="GL_SAMPLE_BUFFERS_EXT"/>
+                <enum name="GL_SAMPLES_EXT"/>
+                <enum name="GL_SAMPLE_MASK_VALUE_EXT"/>
+                <enum name="GL_SAMPLE_MASK_INVERT_EXT"/>
+                <enum name="GL_SAMPLE_PATTERN_EXT"/>
+                <enum name="GL_MULTISAMPLE_BIT_EXT"/>
+                <command name="glSampleMaskEXT"/>
+                <command name="glSamplePatternEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_multisampled_compatibility" supported="gles2">
+            <require>
+                <enum name="GL_MULTISAMPLE_EXT"/>
+                <enum name="GL_SAMPLE_ALPHA_TO_ONE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_multisampled_render_to_texture" supported="gles1|gles2">
+            <require>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT"/>
+                <enum name="GL_RENDERBUFFER_SAMPLES_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT"/>
+                <enum name="GL_MAX_SAMPLES_EXT"/>
+                <command name="glRenderbufferStorageMultisampleEXT"/>
+                <command name="glFramebufferTexture2DMultisampleEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_multiview_draw_buffers" supported="gles2">
+            <require>
+                <enum name="GL_COLOR_ATTACHMENT_EXT"/>
+                <enum name="GL_MULTIVIEW_EXT"/>
+                <enum name="GL_DRAW_BUFFER_EXT"/>
+                <enum name="GL_READ_BUFFER_EXT"/>
+                <enum name="GL_MAX_MULTIVIEW_BUFFERS_EXT"/>
+                <command name="glReadBufferIndexedEXT"/>
+                <command name="glDrawBuffersIndexedEXT"/>
+                <command name="glGetIntegeri_vEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_occlusion_query_boolean" supported="gles2">
+            <require>
+                <enum name="GL_ANY_SAMPLES_PASSED_EXT"/>
+                <enum name="GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT"/>
+                <enum name="GL_CURRENT_QUERY_EXT"/>
+                <enum name="GL_QUERY_RESULT_EXT"/>
+                <enum name="GL_QUERY_RESULT_AVAILABLE_EXT"/>
+                <command name="glGenQueriesEXT"/>
+                <command name="glDeleteQueriesEXT"/>
+                <command name="glIsQueryEXT"/>
+                <command name="glBeginQueryEXT"/>
+                <command name="glEndQueryEXT"/>
+                <command name="glGetQueryivEXT"/>
+                <command name="glGetQueryObjectuivEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_packed_depth_stencil" supported="gl">
+            <require>
+                <enum name="GL_DEPTH_STENCIL_EXT"/>
+                <enum name="GL_UNSIGNED_INT_24_8_EXT"/>
+                <enum name="GL_DEPTH24_STENCIL8_EXT"/>
+                <enum name="GL_TEXTURE_STENCIL_SIZE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_packed_float" supported="gl">
+            <require>
+                <enum name="GL_R11F_G11F_B10F_EXT"/>
+                <enum name="GL_UNSIGNED_INT_10F_11F_11F_REV_EXT"/>
+                <enum name="GL_RGBA_SIGNED_COMPONENTS_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_packed_pixels" supported="gl">
+            <require>
+                <enum name="GL_UNSIGNED_BYTE_3_3_2_EXT"/>
+                <enum name="GL_UNSIGNED_SHORT_4_4_4_4_EXT"/>
+                <enum name="GL_UNSIGNED_SHORT_5_5_5_1_EXT"/>
+                <enum name="GL_UNSIGNED_INT_8_8_8_8_EXT"/>
+                <enum name="GL_UNSIGNED_INT_10_10_10_2_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_paletted_texture" supported="gl">
+            <require>
+                <enum name="GL_COLOR_INDEX1_EXT"/>
+                <enum name="GL_COLOR_INDEX2_EXT"/>
+                <enum name="GL_COLOR_INDEX4_EXT"/>
+                <enum name="GL_COLOR_INDEX8_EXT"/>
+                <enum name="GL_COLOR_INDEX12_EXT"/>
+                <enum name="GL_COLOR_INDEX16_EXT"/>
+                <enum name="GL_TEXTURE_INDEX_SIZE_EXT"/>
+                <command name="glColorTableEXT"/>
+                <command name="glGetColorTableEXT"/>
+                <command name="glGetColorTableParameterivEXT"/>
+                <command name="glGetColorTableParameterfvEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_pixel_buffer_object" supported="gl">
+            <require>
+                <enum name="GL_PIXEL_PACK_BUFFER_EXT"/>
+                <enum name="GL_PIXEL_UNPACK_BUFFER_EXT"/>
+                <enum name="GL_PIXEL_PACK_BUFFER_BINDING_EXT"/>
+                <enum name="GL_PIXEL_UNPACK_BUFFER_BINDING_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_pixel_transform" supported="gl">
+            <require>
+                <enum name="GL_PIXEL_TRANSFORM_2D_EXT"/>
+                <enum name="GL_PIXEL_MAG_FILTER_EXT"/>
+                <enum name="GL_PIXEL_MIN_FILTER_EXT"/>
+                <enum name="GL_PIXEL_CUBIC_WEIGHT_EXT"/>
+                <enum name="GL_CUBIC_EXT"/>
+                <enum name="GL_AVERAGE_EXT"/>
+                <enum name="GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT"/>
+                <enum name="GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT"/>
+                <enum name="GL_PIXEL_TRANSFORM_2D_MATRIX_EXT"/>
+                <command name="glPixelTransformParameteriEXT"/>
+                <command name="glPixelTransformParameterfEXT"/>
+                <command name="glPixelTransformParameterivEXT"/>
+                <command name="glPixelTransformParameterfvEXT"/>
+                <command name="glGetPixelTransformParameterivEXT"/>
+                <command name="glGetPixelTransformParameterfvEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_pixel_transform_color_table" supported="gl"/>
+        <extension name="GL_EXT_point_parameters" supported="gl">
+            <require>
+                <enum name="GL_POINT_SIZE_MIN_EXT"/>
+                <enum name="GL_POINT_SIZE_MAX_EXT"/>
+                <enum name="GL_POINT_FADE_THRESHOLD_SIZE_EXT"/>
+                <enum name="GL_DISTANCE_ATTENUATION_EXT"/>
+                <command name="glPointParameterfEXT"/>
+                <command name="glPointParameterfvEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_polygon_offset" supported="gl">
+            <require>
+                <enum name="GL_POLYGON_OFFSET_EXT"/>
+                <enum name="GL_POLYGON_OFFSET_FACTOR_EXT"/>
+                <enum name="GL_POLYGON_OFFSET_BIAS_EXT"/>
+                <command name="glPolygonOffsetEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_polygon_offset_clamp" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_POLYGON_OFFSET_CLAMP_EXT"/>
+                <command name="glPolygonOffsetClampEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_post_depth_coverage" supported="gl|glcore|gles2"/>
+        <extension name="GL_EXT_primitive_bounding_box" supported="gles2">
+            <require>
+                <enum name="GL_PRIMITIVE_BOUNDING_BOX_EXT"/>
+                <command name="glPrimitiveBoundingBoxEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_protected_textures" supported="gles2">
+            <require>
+                <enum name="GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT"/>
+                <enum name="GL_TEXTURE_PROTECTED_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_provoking_vertex" supported="gl">
+            <require>
+                <enum name="GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT"/>
+                <enum name="GL_FIRST_VERTEX_CONVENTION_EXT"/>
+                <enum name="GL_LAST_VERTEX_CONVENTION_EXT"/>
+                <enum name="GL_PROVOKING_VERTEX_EXT"/>
+                <command name="glProvokingVertexEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_pvrtc_sRGB" supported="gles2">
+            <require>
+                <enum name="GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_raster_multisample" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_RASTER_MULTISAMPLE_EXT"/>
+                <enum name="GL_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_MAX_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT"/>
+                <enum name="GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT"/>
+                <enum name="GL_EFFECTIVE_RASTER_SAMPLES_EXT"/>
+                <command name="glRasterSamplesEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_read_format_bgra" supported="gles1|gles2">
+            <require>
+                <enum name="GL_BGRA_EXT"/>
+                <enum name="GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT"/>
+                <enum name="GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_render_snorm" supported="gles2">
+            <require>
+                <enum name="GL_BYTE"/>
+                <enum name="GL_SHORT"/>
+                <enum name="GL_R8_SNORM"/>
+                <enum name="GL_RG8_SNORM"/>
+                <enum name="GL_RGBA8_SNORM"/>
+                <enum name="GL_R16_SNORM_EXT"/>
+                <enum name="GL_RG16_SNORM_EXT"/>
+                <enum name="GL_RGBA16_SNORM_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_rescale_normal" supported="gl">
+            <require>
+                <enum name="GL_RESCALE_NORMAL_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_robustness" supported="gles1|gles2">
+            <require>
+                <enum name="GL_NO_ERROR"/>
+                <enum name="GL_GUILTY_CONTEXT_RESET_EXT"/>
+                <enum name="GL_INNOCENT_CONTEXT_RESET_EXT"/>
+                <enum name="GL_UNKNOWN_CONTEXT_RESET_EXT"/>
+                <enum name="GL_CONTEXT_ROBUST_ACCESS_EXT"/>
+                <enum name="GL_RESET_NOTIFICATION_STRATEGY_EXT"/>
+                <enum name="GL_LOSE_CONTEXT_ON_RESET_EXT"/>
+                <enum name="GL_NO_RESET_NOTIFICATION_EXT"/>
+                <command name="glGetGraphicsResetStatusEXT"/>
+                <command name="glReadnPixelsEXT"/>
+                <command name="glGetnUniformfvEXT"/>
+                <command name="glGetnUniformivEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_sRGB" supported="gles1|gles2">
+            <require>
+                <enum name="GL_SRGB_EXT"/>
+                <enum name="GL_SRGB_ALPHA_EXT"/>
+                <enum name="GL_SRGB8_ALPHA8_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_sRGB_write_control" supported="gles2">
+            <require>
+                <enum name="GL_FRAMEBUFFER_SRGB_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_secondary_color" supported="gl">
+            <require>
+                <enum name="GL_COLOR_SUM_EXT"/>
+                <enum name="GL_CURRENT_SECONDARY_COLOR_EXT"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_SIZE_EXT"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_TYPE_EXT"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_POINTER_EXT"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_EXT"/>
+                <command name="glSecondaryColor3bEXT"/>
+                <command name="glSecondaryColor3bvEXT"/>
+                <command name="glSecondaryColor3dEXT"/>
+                <command name="glSecondaryColor3dvEXT"/>
+                <command name="glSecondaryColor3fEXT"/>
+                <command name="glSecondaryColor3fvEXT"/>
+                <command name="glSecondaryColor3iEXT"/>
+                <command name="glSecondaryColor3ivEXT"/>
+                <command name="glSecondaryColor3sEXT"/>
+                <command name="glSecondaryColor3svEXT"/>
+                <command name="glSecondaryColor3ubEXT"/>
+                <command name="glSecondaryColor3ubvEXT"/>
+                <command name="glSecondaryColor3uiEXT"/>
+                <command name="glSecondaryColor3uivEXT"/>
+                <command name="glSecondaryColor3usEXT"/>
+                <command name="glSecondaryColor3usvEXT"/>
+                <command name="glSecondaryColorPointerEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_separate_shader_objects" supported="gl|glcore|gles2">
+            <require api="gl" comment="The OpenGL version of this extension is completely unrelated to the OpenGL ES version">
+                <enum name="GL_ACTIVE_PROGRAM_EXT"/>
+                <command name="glUseShaderProgramEXT"/>
+                <command name="glActiveProgramEXT"/>
+                <command name="glCreateShaderProgramEXT"/>
+            </require>
+            <require api="gles2" comment="The OpenGL ES version of this extension is completely unrelated to the OpenGL version">
+                <enum name="GL_VERTEX_SHADER_BIT_EXT"/>
+                <enum name="GL_FRAGMENT_SHADER_BIT_EXT"/>
+                <enum name="GL_ALL_SHADER_BITS_EXT"/>
+                <enum name="GL_PROGRAM_SEPARABLE_EXT"/>
+                <enum name="GL_ACTIVE_PROGRAM_EXT"/>
+                <enum name="GL_PROGRAM_PIPELINE_BINDING_EXT"/>
+                <command name="glActiveShaderProgramEXT"/>
+                <command name="glBindProgramPipelineEXT"/>
+                <command name="glCreateShaderProgramvEXT"/>
+                <command name="glDeleteProgramPipelinesEXT"/>
+                <command name="glGenProgramPipelinesEXT"/>
+                <command name="glGetProgramPipelineInfoLogEXT"/>
+                <command name="glGetProgramPipelineivEXT"/>
+                <command name="glIsProgramPipelineEXT"/>
+                <command name="glProgramParameteriEXT"/>
+                <command name="glProgramUniform1fEXT"/>
+                <command name="glProgramUniform1fvEXT"/>
+                <command name="glProgramUniform1iEXT"/>
+                <command name="glProgramUniform1ivEXT"/>
+                <command name="glProgramUniform2fEXT"/>
+                <command name="glProgramUniform2fvEXT"/>
+                <command name="glProgramUniform2iEXT"/>
+                <command name="glProgramUniform2ivEXT"/>
+                <command name="glProgramUniform3fEXT"/>
+                <command name="glProgramUniform3fvEXT"/>
+                <command name="glProgramUniform3iEXT"/>
+                <command name="glProgramUniform3ivEXT"/>
+                <command name="glProgramUniform4fEXT"/>
+                <command name="glProgramUniform4fvEXT"/>
+                <command name="glProgramUniform4iEXT"/>
+                <command name="glProgramUniform4ivEXT"/>
+                <command name="glProgramUniformMatrix2fvEXT"/>
+                <command name="glProgramUniformMatrix3fvEXT"/>
+                <command name="glProgramUniformMatrix4fvEXT"/>
+                <command name="glUseProgramStagesEXT"/>
+                <command name="glValidateProgramPipelineEXT"/>
+            </require>
+            <require api="gles2" comment="Depends on OpenGL ES 3.0 or GL_NV_non_square_matrices">
+                <command name="glProgramUniform1uiEXT"/>
+                <command name="glProgramUniform2uiEXT"/>
+                <command name="glProgramUniform3uiEXT"/>
+                <command name="glProgramUniform4uiEXT"/>
+                <command name="glProgramUniform1uivEXT"/>
+                <command name="glProgramUniform2uivEXT"/>
+                <command name="glProgramUniform3uivEXT"/>
+                <command name="glProgramUniform4uivEXT"/>
+                <command name="glProgramUniformMatrix4fvEXT"/>
+                <command name="glProgramUniformMatrix2x3fvEXT"/>
+                <command name="glProgramUniformMatrix3x2fvEXT"/>
+                <command name="glProgramUniformMatrix2x4fvEXT"/>
+                <command name="glProgramUniformMatrix4x2fvEXT"/>
+                <command name="glProgramUniformMatrix3x4fvEXT"/>
+                <command name="glProgramUniformMatrix4x3fvEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_separate_specular_color" supported="gl">
+            <require>
+                <enum name="GL_LIGHT_MODEL_COLOR_CONTROL_EXT"/>
+                <enum name="GL_SINGLE_COLOR_EXT"/>
+                <enum name="GL_SEPARATE_SPECULAR_COLOR_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_shader_framebuffer_fetch" supported="gles2">
+            <require>
+                <enum name="GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_shader_group_vote" supported="gles2"/>
+        <extension name="GL_EXT_shader_image_load_formatted" supported="gl"/>
+        <extension name="GL_EXT_shader_image_load_store" supported="gl">
+            <require>
+                <enum name="GL_MAX_IMAGE_UNITS_EXT"/>
+                <enum name="GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT"/>
+                <enum name="GL_IMAGE_BINDING_NAME_EXT"/>
+                <enum name="GL_IMAGE_BINDING_LEVEL_EXT"/>
+                <enum name="GL_IMAGE_BINDING_LAYERED_EXT"/>
+                <enum name="GL_IMAGE_BINDING_LAYER_EXT"/>
+                <enum name="GL_IMAGE_BINDING_ACCESS_EXT"/>
+                <enum name="GL_IMAGE_1D_EXT"/>
+                <enum name="GL_IMAGE_2D_EXT"/>
+                <enum name="GL_IMAGE_3D_EXT"/>
+                <enum name="GL_IMAGE_2D_RECT_EXT"/>
+                <enum name="GL_IMAGE_CUBE_EXT"/>
+                <enum name="GL_IMAGE_BUFFER_EXT"/>
+                <enum name="GL_IMAGE_1D_ARRAY_EXT"/>
+                <enum name="GL_IMAGE_2D_ARRAY_EXT"/>
+                <enum name="GL_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_IMAGE_2D_MULTISAMPLE_EXT"/>
+                <enum name="GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT"/>
+                <enum name="GL_INT_IMAGE_1D_EXT"/>
+                <enum name="GL_INT_IMAGE_2D_EXT"/>
+                <enum name="GL_INT_IMAGE_3D_EXT"/>
+                <enum name="GL_INT_IMAGE_2D_RECT_EXT"/>
+                <enum name="GL_INT_IMAGE_CUBE_EXT"/>
+                <enum name="GL_INT_IMAGE_BUFFER_EXT"/>
+                <enum name="GL_INT_IMAGE_1D_ARRAY_EXT"/>
+                <enum name="GL_INT_IMAGE_2D_ARRAY_EXT"/>
+                <enum name="GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_INT_IMAGE_2D_MULTISAMPLE_EXT"/>
+                <enum name="GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_1D_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_3D_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_CUBE_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_BUFFER_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT"/>
+                <enum name="GL_MAX_IMAGE_SAMPLES_EXT"/>
+                <enum name="GL_IMAGE_BINDING_FORMAT_EXT"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT"/>
+                <enum name="GL_ELEMENT_ARRAY_BARRIER_BIT_EXT"/>
+                <enum name="GL_UNIFORM_BARRIER_BIT_EXT"/>
+                <enum name="GL_TEXTURE_FETCH_BARRIER_BIT_EXT"/>
+                <enum name="GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT"/>
+                <enum name="GL_COMMAND_BARRIER_BIT_EXT"/>
+                <enum name="GL_PIXEL_BUFFER_BARRIER_BIT_EXT"/>
+                <enum name="GL_TEXTURE_UPDATE_BARRIER_BIT_EXT"/>
+                <enum name="GL_BUFFER_UPDATE_BARRIER_BIT_EXT"/>
+                <enum name="GL_FRAMEBUFFER_BARRIER_BIT_EXT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT"/>
+                <enum name="GL_ATOMIC_COUNTER_BARRIER_BIT_EXT"/>
+                <enum name="GL_ALL_BARRIER_BITS_EXT"/>
+                <command name="glBindImageTextureEXT"/>
+                <command name="glMemoryBarrierEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_shader_implicit_conversions" supported="gles2"/>
+        <extension name="GL_EXT_shader_integer_mix" supported="gl|glcore|gles2"/>
+        <extension name="GL_EXT_shader_io_blocks" supported="gles2"/>
+        <extension name="GL_EXT_shader_non_constant_global_initializers" supported="gles2"/>
+        <extension name="GL_EXT_shader_pixel_local_storage" supported="gles2">
+            <require>
+                <enum name="GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT"/>
+                <enum name="GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT"/>
+                <enum name="GL_SHADER_PIXEL_LOCAL_STORAGE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_shader_pixel_local_storage2" supported="gles2">
+            <require>
+                <enum name="GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT"/>
+                <enum name="GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT"/>
+                <command name="glFramebufferPixelLocalStorageSizeEXT"/>
+                <command name="glGetFramebufferPixelLocalStorageSizeEXT"/>
+                <command name="glClearPixelLocalStorageuiEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_shader_texture_lod" supported="gles2"/>
+        <extension name="GL_EXT_shadow_funcs" supported="gl"/>
+        <extension name="GL_EXT_shadow_samplers" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_COMPARE_MODE_EXT"/>
+                <enum name="GL_TEXTURE_COMPARE_FUNC_EXT"/>
+                <enum name="GL_COMPARE_REF_TO_TEXTURE_EXT"/>
+                <enum name="GL_SAMPLER_2D_SHADOW_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_shared_texture_palette" supported="gl">
+            <require>
+                <enum name="GL_SHARED_TEXTURE_PALETTE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_sparse_texture" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_SPARSE_EXT"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_INDEX_EXT"/>
+                <enum name="GL_NUM_SPARSE_LEVELS_EXT"/>
+                <enum name="GL_NUM_VIRTUAL_PAGE_SIZES_EXT"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_X_EXT"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_Y_EXT"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_Z_EXT"/>
+                <enum name="GL_TEXTURE_2D"/>
+                <enum name="GL_TEXTURE_2D_ARRAY"/>
+                <enum name="GL_TEXTURE_CUBE_MAP"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_TEXTURE_3D"/>
+                <enum name="GL_MAX_SPARSE_TEXTURE_SIZE_EXT"/>
+                <enum name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT"/>
+                <enum name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT"/>
+                <enum name="GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT"/>
+                <command name="glTexPageCommitmentEXT"/>
+                <!-- <command name="glTexturePageCommitmentEXT"/> -->
+            </require>
+        </extension>
+        <extension name="GL_EXT_sparse_texture2" supported="gl"/>
+        <extension name="GL_EXT_stencil_clear_tag" supported="gl">
+            <require>
+                <enum name="GL_STENCIL_TAG_BITS_EXT"/>
+                <enum name="GL_STENCIL_CLEAR_TAG_VALUE_EXT"/>
+                <command name="glStencilClearTagEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_stencil_two_side" supported="gl">
+            <require>
+                <enum name="GL_STENCIL_TEST_TWO_SIDE_EXT"/>
+                <enum name="GL_ACTIVE_STENCIL_FACE_EXT"/>
+                <command name="glActiveStencilFaceEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_stencil_wrap" supported="gl">
+            <require>
+                <enum name="GL_INCR_WRAP_EXT"/>
+                <enum name="GL_DECR_WRAP_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_subtexture" supported="gl">
+            <require>
+                <command name="glTexSubImage1DEXT"/>
+                <command name="glTexSubImage2DEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_tessellation_point_size" supported="gles2"/>
+        <extension name="GL_EXT_tessellation_shader" supported="gles2">
+            <require>
+                <enum name="GL_PATCHES_EXT"/>
+                <enum name="GL_PATCH_VERTICES_EXT"/>
+                <enum name="GL_TESS_CONTROL_OUTPUT_VERTICES_EXT"/>
+                <enum name="GL_TESS_GEN_MODE_EXT"/>
+                <enum name="GL_TESS_GEN_SPACING_EXT"/>
+                <enum name="GL_TESS_GEN_VERTEX_ORDER_EXT"/>
+                <enum name="GL_TESS_GEN_POINT_MODE_EXT"/>
+                <enum name="GL_TRIANGLES"/>
+                <enum name="GL_ISOLINES_EXT"/>
+                <enum name="GL_QUADS_EXT"/>
+                <enum name="GL_EQUAL"/>
+                <enum name="GL_FRACTIONAL_ODD_EXT"/>
+                <enum name="GL_FRACTIONAL_EVEN_EXT"/>
+                <enum name="GL_CCW"/>
+                <enum name="GL_CW"/>
+                <enum name="GL_MAX_PATCH_VERTICES_EXT"/>
+                <enum name="GL_MAX_TESS_GEN_LEVEL_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT"/>
+                <enum name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_TESS_PATCH_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT"/>
+                <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT"/>
+                <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT"/>
+                <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT"/>
+                <enum name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT"/>
+                <enum name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT"/>
+                <enum name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT"/>
+                <enum name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"/>
+                <enum name="GL_IS_PER_PATCH_EXT"/>
+                <enum name="GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT"/>
+                <enum name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT"/>
+                <enum name="GL_TESS_CONTROL_SHADER_EXT"/>
+                <enum name="GL_TESS_EVALUATION_SHADER_EXT"/>
+                <enum name="GL_TESS_CONTROL_SHADER_BIT_EXT"/>
+                <enum name="GL_TESS_EVALUATION_SHADER_BIT_EXT"/>
+                <command name="glPatchParameteriEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture" supported="gl">
+            <require>
+                <enum name="GL_ALPHA4_EXT"/>
+                <enum name="GL_ALPHA8_EXT"/>
+                <enum name="GL_ALPHA12_EXT"/>
+                <enum name="GL_ALPHA16_EXT"/>
+                <enum name="GL_LUMINANCE4_EXT"/>
+                <enum name="GL_LUMINANCE8_EXT"/>
+                <enum name="GL_LUMINANCE12_EXT"/>
+                <enum name="GL_LUMINANCE16_EXT"/>
+                <enum name="GL_LUMINANCE4_ALPHA4_EXT"/>
+                <enum name="GL_LUMINANCE6_ALPHA2_EXT"/>
+                <enum name="GL_LUMINANCE8_ALPHA8_EXT"/>
+                <enum name="GL_LUMINANCE12_ALPHA4_EXT"/>
+                <enum name="GL_LUMINANCE12_ALPHA12_EXT"/>
+                <enum name="GL_LUMINANCE16_ALPHA16_EXT"/>
+                <enum name="GL_INTENSITY_EXT"/>
+                <enum name="GL_INTENSITY4_EXT"/>
+                <enum name="GL_INTENSITY8_EXT"/>
+                <enum name="GL_INTENSITY12_EXT"/>
+                <enum name="GL_INTENSITY16_EXT"/>
+                <enum name="GL_RGB2_EXT"/>
+                <enum name="GL_RGB4_EXT"/>
+                <enum name="GL_RGB5_EXT"/>
+                <enum name="GL_RGB8_EXT"/>
+                <enum name="GL_RGB10_EXT"/>
+                <enum name="GL_RGB12_EXT"/>
+                <enum name="GL_RGB16_EXT"/>
+                <enum name="GL_RGBA2_EXT"/>
+                <enum name="GL_RGBA4_EXT"/>
+                <enum name="GL_RGB5_A1_EXT"/>
+                <enum name="GL_RGBA8_EXT"/>
+                <enum name="GL_RGB10_A2_EXT"/>
+                <enum name="GL_RGBA12_EXT"/>
+                <enum name="GL_RGBA16_EXT"/>
+                <enum name="GL_TEXTURE_RED_SIZE_EXT"/>
+                <enum name="GL_TEXTURE_GREEN_SIZE_EXT"/>
+                <enum name="GL_TEXTURE_BLUE_SIZE_EXT"/>
+                <enum name="GL_TEXTURE_ALPHA_SIZE_EXT"/>
+                <enum name="GL_TEXTURE_LUMINANCE_SIZE_EXT"/>
+                <enum name="GL_TEXTURE_INTENSITY_SIZE_EXT"/>
+                <enum name="GL_REPLACE_EXT"/>
+                <enum name="GL_PROXY_TEXTURE_1D_EXT"/>
+                <enum name="GL_PROXY_TEXTURE_2D_EXT"/>
+                <enum name="GL_TEXTURE_TOO_LARGE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture3D" supported="gl">
+            <require>
+                <enum name="GL_PACK_SKIP_IMAGES_EXT"/>
+                <enum name="GL_PACK_IMAGE_HEIGHT_EXT"/>
+                <enum name="GL_UNPACK_SKIP_IMAGES_EXT"/>
+                <enum name="GL_UNPACK_IMAGE_HEIGHT_EXT"/>
+                <enum name="GL_TEXTURE_3D_EXT"/>
+                <enum name="GL_PROXY_TEXTURE_3D_EXT"/>
+                <enum name="GL_TEXTURE_DEPTH_EXT"/>
+                <enum name="GL_TEXTURE_WRAP_R_EXT"/>
+                <enum name="GL_MAX_3D_TEXTURE_SIZE_EXT"/>
+                <command name="glTexImage3DEXT"/>
+                <command name="glTexSubImage3DEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_array" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_1D_ARRAY_EXT"/>
+                <enum name="GL_PROXY_TEXTURE_1D_ARRAY_EXT"/>
+                <enum name="GL_TEXTURE_2D_ARRAY_EXT"/>
+                <enum name="GL_PROXY_TEXTURE_2D_ARRAY_EXT"/>
+                <enum name="GL_TEXTURE_BINDING_1D_ARRAY_EXT"/>
+                <enum name="GL_TEXTURE_BINDING_2D_ARRAY_EXT"/>
+                <enum name="GL_MAX_ARRAY_TEXTURE_LAYERS_EXT"/>
+                <enum name="GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT"/>
+                <command name="glFramebufferTextureLayerEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_border_clamp" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_BORDER_COLOR_EXT"/>
+                <enum name="GL_CLAMP_TO_BORDER_EXT"/>
+                <command name="glTexParameterIivEXT"/>
+                <command name="glTexParameterIuivEXT"/>
+                <command name="glGetTexParameterIivEXT"/>
+                <command name="glGetTexParameterIuivEXT"/>
+                <command name="glSamplerParameterIivEXT"/>
+                <command name="glSamplerParameterIuivEXT"/>
+                <command name="glGetSamplerParameterIivEXT"/>
+                <command name="glGetSamplerParameterIuivEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_buffer" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_BUFFER_EXT"/>
+                <enum name="GL_TEXTURE_BUFFER_BINDING_EXT"/>
+                <enum name="GL_MAX_TEXTURE_BUFFER_SIZE_EXT"/>
+                <enum name="GL_TEXTURE_BINDING_BUFFER_EXT"/>
+                <enum name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT"/>
+                <enum name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT"/>
+                <enum name="GL_SAMPLER_BUFFER_EXT"/>
+                <enum name="GL_INT_SAMPLER_BUFFER_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT"/>
+                <enum name="GL_IMAGE_BUFFER_EXT"/>
+                <enum name="GL_INT_IMAGE_BUFFER_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_BUFFER_EXT"/>
+                <enum name="GL_TEXTURE_BUFFER_OFFSET_EXT"/>
+                <enum name="GL_TEXTURE_BUFFER_SIZE_EXT"/>
+                <command name="glTexBufferEXT"/>
+                <command name="glTexBufferRangeEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_buffer_object" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_BUFFER_EXT"/>
+                <enum name="GL_MAX_TEXTURE_BUFFER_SIZE_EXT"/>
+                <enum name="GL_TEXTURE_BINDING_BUFFER_EXT"/>
+                <enum name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT"/>
+                <enum name="GL_TEXTURE_BUFFER_FORMAT_EXT"/>
+                <command name="glTexBufferEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_compression_dxt1" supported="gles1|gles2">
+            <require>
+                <enum name="GL_COMPRESSED_RGB_S3TC_DXT1_EXT"/>
+                <enum name="GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_compression_latc" supported="gl">
+            <require>
+                <enum name="GL_COMPRESSED_LUMINANCE_LATC1_EXT"/>
+                <enum name="GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT"/>
+                <enum name="GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT"/>
+                <enum name="GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_compression_rgtc" supported="gl">
+            <require>
+                <enum name="GL_COMPRESSED_RED_RGTC1_EXT"/>
+                <enum name="GL_COMPRESSED_SIGNED_RED_RGTC1_EXT"/>
+                <enum name="GL_COMPRESSED_RED_GREEN_RGTC2_EXT"/>
+                <enum name="GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_compression_s3tc" supported="gl|glcore|gles2|glsc2">
+            <require>
+                <enum name="GL_COMPRESSED_RGB_S3TC_DXT1_EXT"/>
+                <enum name="GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"/>
+                <enum name="GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"/>
+                <enum name="GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_cube_map" supported="gl" comment="Replaced by ARB_texture_cube_map, but was apparently shipped anyway?">
+            <require>
+                <enum name="GL_NORMAL_MAP_EXT"/>
+                <enum name="GL_REFLECTION_MAP_EXT"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_EXT"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP_EXT"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT"/>
+                <enum name="GL_PROXY_TEXTURE_CUBE_MAP_EXT"/>
+                <enum name="GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_cube_map_array" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT"/>
+                <enum name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_env_add" supported="gl"/>
+        <extension name="GL_EXT_texture_env_combine" supported="gl">
+            <require>
+                <enum name="GL_COMBINE_EXT"/>
+                <enum name="GL_COMBINE_RGB_EXT"/>
+                <enum name="GL_COMBINE_ALPHA_EXT"/>
+                <enum name="GL_RGB_SCALE_EXT"/>
+                <enum name="GL_ADD_SIGNED_EXT"/>
+                <enum name="GL_INTERPOLATE_EXT"/>
+                <enum name="GL_CONSTANT_EXT"/>
+                <enum name="GL_PRIMARY_COLOR_EXT"/>
+                <enum name="GL_PREVIOUS_EXT"/>
+                <enum name="GL_SOURCE0_RGB_EXT"/>
+                <enum name="GL_SOURCE1_RGB_EXT"/>
+                <enum name="GL_SOURCE2_RGB_EXT"/>
+                <enum name="GL_SOURCE0_ALPHA_EXT"/>
+                <enum name="GL_SOURCE1_ALPHA_EXT"/>
+                <enum name="GL_SOURCE2_ALPHA_EXT"/>
+                <enum name="GL_OPERAND0_RGB_EXT"/>
+                <enum name="GL_OPERAND1_RGB_EXT"/>
+                <enum name="GL_OPERAND2_RGB_EXT"/>
+                <enum name="GL_OPERAND0_ALPHA_EXT"/>
+                <enum name="GL_OPERAND1_ALPHA_EXT"/>
+                <enum name="GL_OPERAND2_ALPHA_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_env_dot3" supported="gl">
+            <require>
+                <enum name="GL_DOT3_RGB_EXT"/>
+                <enum name="GL_DOT3_RGBA_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_filter_anisotropic" supported="gl|gles1|gles2">
+            <require>
+                <enum name="GL_TEXTURE_MAX_ANISOTROPY_EXT"/>
+                <enum name="GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_filter_minmax" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_RASTER_MULTISAMPLE_EXT"/>
+                <enum name="GL_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_MAX_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT"/>
+                <enum name="GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT"/>
+                <enum name="GL_EFFECTIVE_RASTER_SAMPLES_EXT"/>
+                <command name="glRasterSamplesEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_format_BGRA8888" supported="gles1|gles2">
+            <require>
+                <enum name="GL_BGRA_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_integer" supported="gl">
+            <require>
+                <enum name="GL_RGBA32UI_EXT"/>
+                <enum name="GL_RGB32UI_EXT"/>
+                <enum name="GL_ALPHA32UI_EXT"/>
+                <enum name="GL_INTENSITY32UI_EXT"/>
+                <enum name="GL_LUMINANCE32UI_EXT"/>
+                <enum name="GL_LUMINANCE_ALPHA32UI_EXT"/>
+                <enum name="GL_RGBA16UI_EXT"/>
+                <enum name="GL_RGB16UI_EXT"/>
+                <enum name="GL_ALPHA16UI_EXT"/>
+                <enum name="GL_INTENSITY16UI_EXT"/>
+                <enum name="GL_LUMINANCE16UI_EXT"/>
+                <enum name="GL_LUMINANCE_ALPHA16UI_EXT"/>
+                <enum name="GL_RGBA8UI_EXT"/>
+                <enum name="GL_RGB8UI_EXT"/>
+                <enum name="GL_ALPHA8UI_EXT"/>
+                <enum name="GL_INTENSITY8UI_EXT"/>
+                <enum name="GL_LUMINANCE8UI_EXT"/>
+                <enum name="GL_LUMINANCE_ALPHA8UI_EXT"/>
+                <enum name="GL_RGBA32I_EXT"/>
+                <enum name="GL_RGB32I_EXT"/>
+                <enum name="GL_ALPHA32I_EXT"/>
+                <enum name="GL_INTENSITY32I_EXT"/>
+                <enum name="GL_LUMINANCE32I_EXT"/>
+                <enum name="GL_LUMINANCE_ALPHA32I_EXT"/>
+                <enum name="GL_RGBA16I_EXT"/>
+                <enum name="GL_RGB16I_EXT"/>
+                <enum name="GL_ALPHA16I_EXT"/>
+                <enum name="GL_INTENSITY16I_EXT"/>
+                <enum name="GL_LUMINANCE16I_EXT"/>
+                <enum name="GL_LUMINANCE_ALPHA16I_EXT"/>
+                <enum name="GL_RGBA8I_EXT"/>
+                <enum name="GL_RGB8I_EXT"/>
+                <enum name="GL_ALPHA8I_EXT"/>
+                <enum name="GL_INTENSITY8I_EXT"/>
+                <enum name="GL_LUMINANCE8I_EXT"/>
+                <enum name="GL_LUMINANCE_ALPHA8I_EXT"/>
+                <enum name="GL_RED_INTEGER_EXT"/>
+                <enum name="GL_GREEN_INTEGER_EXT"/>
+                <enum name="GL_BLUE_INTEGER_EXT"/>
+                <enum name="GL_ALPHA_INTEGER_EXT"/>
+                <enum name="GL_RGB_INTEGER_EXT"/>
+                <enum name="GL_RGBA_INTEGER_EXT"/>
+                <enum name="GL_BGR_INTEGER_EXT"/>
+                <enum name="GL_BGRA_INTEGER_EXT"/>
+                <enum name="GL_LUMINANCE_INTEGER_EXT"/>
+                <enum name="GL_LUMINANCE_ALPHA_INTEGER_EXT"/>
+                <enum name="GL_RGBA_INTEGER_MODE_EXT"/>
+                <command name="glTexParameterIivEXT"/>
+                <command name="glTexParameterIuivEXT"/>
+                <command name="glGetTexParameterIivEXT"/>
+                <command name="glGetTexParameterIuivEXT"/>
+                <command name="glClearColorIiEXT"/>
+                <command name="glClearColorIuiEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_lod_bias" supported="gl|gles1">
+            <require>
+                <enum name="GL_MAX_TEXTURE_LOD_BIAS_EXT"/>
+                <enum name="GL_TEXTURE_FILTER_CONTROL_EXT"/>
+                <enum name="GL_TEXTURE_LOD_BIAS_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_mirror_clamp" supported="gl">
+            <require>
+                <enum name="GL_MIRROR_CLAMP_EXT"/>
+                <enum name="GL_MIRROR_CLAMP_TO_EDGE_EXT"/>
+                <enum name="GL_MIRROR_CLAMP_TO_BORDER_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_norm16" supported="gles2">
+            <require>
+                <enum name="GL_R16_EXT"/>
+                <enum name="GL_RG16_EXT"/>
+                <enum name="GL_RGBA16_EXT"/>
+                <enum name="GL_RGB16_EXT"/>
+                <enum name="GL_R16_SNORM_EXT"/>
+                <enum name="GL_RG16_SNORM_EXT"/>
+                <enum name="GL_RGB16_SNORM_EXT"/>
+                <enum name="GL_RGBA16_SNORM_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_object" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_PRIORITY_EXT"/>
+                <enum name="GL_TEXTURE_RESIDENT_EXT"/>
+                <enum name="GL_TEXTURE_1D_BINDING_EXT"/>
+                <enum name="GL_TEXTURE_2D_BINDING_EXT"/>
+                <enum name="GL_TEXTURE_3D_BINDING_EXT"/>
+                <command name="glAreTexturesResidentEXT"/>
+                <command name="glBindTextureEXT"/>
+                <command name="glDeleteTexturesEXT"/>
+                <command name="glGenTexturesEXT"/>
+                <command name="glIsTextureEXT"/>
+                <command name="glPrioritizeTexturesEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_perturb_normal" supported="gl">
+            <require>
+                <enum name="GL_PERTURB_EXT"/>
+                <enum name="GL_TEXTURE_NORMAL_EXT"/>
+                <command name="glTextureNormalEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_rg" supported="gles2">
+            <require>
+                <enum name="GL_RED_EXT"/>
+                <enum name="GL_RG_EXT"/>
+                <enum name="GL_R8_EXT"/>
+                <enum name="GL_RG8_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_sRGB" supported="gl">
+            <require>
+                <enum name="GL_SRGB_EXT"/>
+                <enum name="GL_SRGB8_EXT"/>
+                <enum name="GL_SRGB_ALPHA_EXT"/>
+                <enum name="GL_SRGB8_ALPHA8_EXT"/>
+                <enum name="GL_SLUMINANCE_ALPHA_EXT"/>
+                <enum name="GL_SLUMINANCE8_ALPHA8_EXT"/>
+                <enum name="GL_SLUMINANCE_EXT"/>
+                <enum name="GL_SLUMINANCE8_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_EXT"/>
+                <enum name="GL_COMPRESSED_SLUMINANCE_EXT"/>
+                <enum name="GL_COMPRESSED_SLUMINANCE_ALPHA_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_S3TC_DXT1_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_sRGB_R8" supported="gles2">
+            <require>
+                <enum name="GL_SR8_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_sRGB_RG8" supported="gles2">
+            <require>
+                <enum name="GL_SRG8_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_sRGB_decode" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_TEXTURE_SRGB_DECODE_EXT"/>
+                <enum name="GL_DECODE_EXT"/>
+                <enum name="GL_SKIP_DECODE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_shared_exponent" supported="gl">
+            <require>
+                <enum name="GL_RGB9_E5_EXT"/>
+                <enum name="GL_UNSIGNED_INT_5_9_9_9_REV_EXT"/>
+                <enum name="GL_TEXTURE_SHARED_SIZE_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_snorm" supported="gl">
+            <require>
+                <enum name="GL_ALPHA_SNORM"/>
+                <enum name="GL_LUMINANCE_SNORM"/>
+                <enum name="GL_LUMINANCE_ALPHA_SNORM"/>
+                <enum name="GL_INTENSITY_SNORM"/>
+                <enum name="GL_ALPHA8_SNORM"/>
+                <enum name="GL_LUMINANCE8_SNORM"/>
+                <enum name="GL_LUMINANCE8_ALPHA8_SNORM"/>
+                <enum name="GL_INTENSITY8_SNORM"/>
+                <enum name="GL_ALPHA16_SNORM"/>
+                <enum name="GL_LUMINANCE16_SNORM"/>
+                <enum name="GL_LUMINANCE16_ALPHA16_SNORM"/>
+                <enum name="GL_INTENSITY16_SNORM"/>
+                <enum name="GL_RED_SNORM"/>
+                <enum name="GL_RG_SNORM"/>
+                <enum name="GL_RGB_SNORM"/>
+                <enum name="GL_RGBA_SNORM"/>
+                <enum name="GL_R8_SNORM"/>
+                <enum name="GL_RG8_SNORM"/>
+                <enum name="GL_RGB8_SNORM"/>
+                <enum name="GL_RGBA8_SNORM"/>
+                <enum name="GL_R16_SNORM"/>
+                <enum name="GL_RG16_SNORM"/>
+                <enum name="GL_RGB16_SNORM"/>
+                <enum name="GL_RGBA16_SNORM"/>
+                <enum name="GL_SIGNED_NORMALIZED"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_storage" supported="gles1|gles2">
+            <require comment="Not clear all of these enums should be here for OpenGL ES. Many are only defined if other extensions also requiring them are supported">
+                <enum name="GL_TEXTURE_IMMUTABLE_FORMAT_EXT"/>
+                <enum name="GL_ALPHA8_EXT"/>
+                <enum name="GL_LUMINANCE8_EXT"/>
+                <enum name="GL_LUMINANCE8_ALPHA8_EXT"/>
+                <enum name="GL_RGBA32F_EXT"/>
+                <enum name="GL_RGB32F_EXT"/>
+                <enum name="GL_ALPHA32F_EXT"/>
+                <enum name="GL_LUMINANCE32F_EXT"/>
+                <enum name="GL_LUMINANCE_ALPHA32F_EXT"/>
+                <enum name="GL_RGBA16F_EXT"/>
+                <enum name="GL_RGB16F_EXT"/>
+                <enum name="GL_ALPHA16F_EXT"/>
+                <enum name="GL_LUMINANCE16F_EXT"/>
+                <enum name="GL_LUMINANCE_ALPHA16F_EXT"/>
+                <enum name="GL_RGB10_A2_EXT"/>
+                <enum name="GL_RGB10_EXT"/>
+                <enum name="GL_BGRA8_EXT"/>
+                <enum name="GL_R8_EXT"/>
+                <enum name="GL_RG8_EXT"/>
+                <enum name="GL_R32F_EXT"/>
+                <enum name="GL_RG32F_EXT"/>
+                <enum name="GL_R16F_EXT"/>
+                <enum name="GL_RG16F_EXT"/>
+                <command name="glTexStorage1DEXT"/>
+                <command name="glTexStorage2DEXT"/>
+                <command name="glTexStorage3DEXT"/>
+            </require>
+            <require comment="Supported only if GL_EXT_direct_state_access is supported">
+                <command name="glTextureStorage1DEXT"/>
+                <command name="glTextureStorage2DEXT"/>
+                <command name="glTextureStorage3DEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_swizzle" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_SWIZZLE_R_EXT"/>
+                <enum name="GL_TEXTURE_SWIZZLE_G_EXT"/>
+                <enum name="GL_TEXTURE_SWIZZLE_B_EXT"/>
+                <enum name="GL_TEXTURE_SWIZZLE_A_EXT"/>
+                <enum name="GL_TEXTURE_SWIZZLE_RGBA_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_type_2_10_10_10_REV" supported="gles2">
+            <require>
+                <enum name="GL_UNSIGNED_INT_2_10_10_10_REV_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_view" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_VIEW_MIN_LEVEL_EXT"/>
+                <enum name="GL_TEXTURE_VIEW_NUM_LEVELS_EXT"/>
+                <enum name="GL_TEXTURE_VIEW_MIN_LAYER_EXT"/>
+                <enum name="GL_TEXTURE_VIEW_NUM_LAYERS_EXT"/>
+                <enum name="GL_TEXTURE_IMMUTABLE_LEVELS"/>
+                <command name="glTextureViewEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_timer_query" supported="gl">
+            <require>
+                <enum name="GL_TIME_ELAPSED_EXT"/>
+                <command name="glGetQueryObjecti64vEXT"/>
+                <command name="glGetQueryObjectui64vEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_transform_feedback" supported="gl">
+            <require>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_EXT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT"/>
+                <enum name="GL_INTERLEAVED_ATTRIBS_EXT"/>
+                <enum name="GL_SEPARATE_ATTRIBS_EXT"/>
+                <enum name="GL_PRIMITIVES_GENERATED_EXT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT"/>
+                <enum name="GL_RASTERIZER_DISCARD_EXT"/>
+                <enum name="GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT"/>
+                <enum name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT"/>
+                <enum name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_VARYINGS_EXT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT"/>
+                <command name="glBeginTransformFeedbackEXT"/>
+                <command name="glEndTransformFeedbackEXT"/>
+                <command name="glBindBufferRangeEXT"/>
+                <command name="glBindBufferOffsetEXT"/>
+                <command name="glBindBufferBaseEXT"/>
+                <command name="glTransformFeedbackVaryingsEXT"/>
+                <command name="glGetTransformFeedbackVaryingEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_unpack_subimage" supported="gles2">
+            <require>
+                <enum name="GL_UNPACK_ROW_LENGTH_EXT"/>
+                <enum name="GL_UNPACK_SKIP_ROWS_EXT"/>
+                <enum name="GL_UNPACK_SKIP_PIXELS_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_vertex_array" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ARRAY_EXT"/>
+                <enum name="GL_NORMAL_ARRAY_EXT"/>
+                <enum name="GL_COLOR_ARRAY_EXT"/>
+                <enum name="GL_INDEX_ARRAY_EXT"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_EXT"/>
+                <enum name="GL_EDGE_FLAG_ARRAY_EXT"/>
+                <enum name="GL_VERTEX_ARRAY_SIZE_EXT"/>
+                <enum name="GL_VERTEX_ARRAY_TYPE_EXT"/>
+                <enum name="GL_VERTEX_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_VERTEX_ARRAY_COUNT_EXT"/>
+                <enum name="GL_NORMAL_ARRAY_TYPE_EXT"/>
+                <enum name="GL_NORMAL_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_NORMAL_ARRAY_COUNT_EXT"/>
+                <enum name="GL_COLOR_ARRAY_SIZE_EXT"/>
+                <enum name="GL_COLOR_ARRAY_TYPE_EXT"/>
+                <enum name="GL_COLOR_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_COLOR_ARRAY_COUNT_EXT"/>
+                <enum name="GL_INDEX_ARRAY_TYPE_EXT"/>
+                <enum name="GL_INDEX_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_INDEX_ARRAY_COUNT_EXT"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_SIZE_EXT"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_TYPE_EXT"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_COUNT_EXT"/>
+                <enum name="GL_EDGE_FLAG_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_EDGE_FLAG_ARRAY_COUNT_EXT"/>
+                <enum name="GL_VERTEX_ARRAY_POINTER_EXT"/>
+                <enum name="GL_NORMAL_ARRAY_POINTER_EXT"/>
+                <enum name="GL_COLOR_ARRAY_POINTER_EXT"/>
+                <enum name="GL_INDEX_ARRAY_POINTER_EXT"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_POINTER_EXT"/>
+                <enum name="GL_EDGE_FLAG_ARRAY_POINTER_EXT"/>
+                <command name="glArrayElementEXT"/>
+                <command name="glColorPointerEXT"/>
+                <command name="glDrawArraysEXT"/>
+                <command name="glEdgeFlagPointerEXT"/>
+                <command name="glGetPointervEXT"/>
+                <command name="glIndexPointerEXT"/>
+                <command name="glNormalPointerEXT"/>
+                <command name="glTexCoordPointerEXT"/>
+                <command name="glVertexPointerEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_vertex_array_bgra" supported="gl">
+            <require>
+                <enum name="GL_BGRA"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_vertex_attrib_64bit" supported="gl">
+            <require>
+                <enum name="GL_DOUBLE"/>
+                <enum name="GL_DOUBLE_VEC2_EXT"/>
+                <enum name="GL_DOUBLE_VEC3_EXT"/>
+                <enum name="GL_DOUBLE_VEC4_EXT"/>
+                <enum name="GL_DOUBLE_MAT2_EXT"/>
+                <enum name="GL_DOUBLE_MAT3_EXT"/>
+                <enum name="GL_DOUBLE_MAT4_EXT"/>
+                <enum name="GL_DOUBLE_MAT2x3_EXT"/>
+                <enum name="GL_DOUBLE_MAT2x4_EXT"/>
+                <enum name="GL_DOUBLE_MAT3x2_EXT"/>
+                <enum name="GL_DOUBLE_MAT3x4_EXT"/>
+                <enum name="GL_DOUBLE_MAT4x2_EXT"/>
+                <enum name="GL_DOUBLE_MAT4x3_EXT"/>
+                <command name="glVertexAttribL1dEXT"/>
+                <command name="glVertexAttribL2dEXT"/>
+                <command name="glVertexAttribL3dEXT"/>
+                <command name="glVertexAttribL4dEXT"/>
+                <command name="glVertexAttribL1dvEXT"/>
+                <command name="glVertexAttribL2dvEXT"/>
+                <command name="glVertexAttribL3dvEXT"/>
+                <command name="glVertexAttribL4dvEXT"/>
+                <command name="glVertexAttribLPointerEXT"/>
+                <command name="glGetVertexAttribLdvEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_vertex_shader" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_SHADER_EXT"/>
+                <enum name="GL_VERTEX_SHADER_BINDING_EXT"/>
+                <enum name="GL_OP_INDEX_EXT"/>
+                <enum name="GL_OP_NEGATE_EXT"/>
+                <enum name="GL_OP_DOT3_EXT"/>
+                <enum name="GL_OP_DOT4_EXT"/>
+                <enum name="GL_OP_MUL_EXT"/>
+                <enum name="GL_OP_ADD_EXT"/>
+                <enum name="GL_OP_MADD_EXT"/>
+                <enum name="GL_OP_FRAC_EXT"/>
+                <enum name="GL_OP_MAX_EXT"/>
+                <enum name="GL_OP_MIN_EXT"/>
+                <enum name="GL_OP_SET_GE_EXT"/>
+                <enum name="GL_OP_SET_LT_EXT"/>
+                <enum name="GL_OP_CLAMP_EXT"/>
+                <enum name="GL_OP_FLOOR_EXT"/>
+                <enum name="GL_OP_ROUND_EXT"/>
+                <enum name="GL_OP_EXP_BASE_2_EXT"/>
+                <enum name="GL_OP_LOG_BASE_2_EXT"/>
+                <enum name="GL_OP_POWER_EXT"/>
+                <enum name="GL_OP_RECIP_EXT"/>
+                <enum name="GL_OP_RECIP_SQRT_EXT"/>
+                <enum name="GL_OP_SUB_EXT"/>
+                <enum name="GL_OP_CROSS_PRODUCT_EXT"/>
+                <enum name="GL_OP_MULTIPLY_MATRIX_EXT"/>
+                <enum name="GL_OP_MOV_EXT"/>
+                <enum name="GL_OUTPUT_VERTEX_EXT"/>
+                <enum name="GL_OUTPUT_COLOR0_EXT"/>
+                <enum name="GL_OUTPUT_COLOR1_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD0_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD1_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD2_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD3_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD4_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD5_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD6_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD7_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD8_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD9_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD10_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD11_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD12_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD13_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD14_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD15_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD16_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD17_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD18_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD19_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD20_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD21_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD22_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD23_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD24_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD25_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD26_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD27_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD28_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD29_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD30_EXT"/>
+                <enum name="GL_OUTPUT_TEXTURE_COORD31_EXT"/>
+                <enum name="GL_OUTPUT_FOG_EXT"/>
+                <enum name="GL_SCALAR_EXT"/>
+                <enum name="GL_VECTOR_EXT"/>
+                <enum name="GL_MATRIX_EXT"/>
+                <enum name="GL_VARIANT_EXT"/>
+                <enum name="GL_INVARIANT_EXT"/>
+                <enum name="GL_LOCAL_CONSTANT_EXT"/>
+                <enum name="GL_LOCAL_EXT"/>
+                <enum name="GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT"/>
+                <enum name="GL_MAX_VERTEX_SHADER_VARIANTS_EXT"/>
+                <enum name="GL_MAX_VERTEX_SHADER_INVARIANTS_EXT"/>
+                <enum name="GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT"/>
+                <enum name="GL_MAX_VERTEX_SHADER_LOCALS_EXT"/>
+                <enum name="GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT"/>
+                <enum name="GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT"/>
+                <enum name="GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT"/>
+                <enum name="GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT"/>
+                <enum name="GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT"/>
+                <enum name="GL_VERTEX_SHADER_INSTRUCTIONS_EXT"/>
+                <enum name="GL_VERTEX_SHADER_VARIANTS_EXT"/>
+                <enum name="GL_VERTEX_SHADER_INVARIANTS_EXT"/>
+                <enum name="GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT"/>
+                <enum name="GL_VERTEX_SHADER_LOCALS_EXT"/>
+                <enum name="GL_VERTEX_SHADER_OPTIMIZED_EXT"/>
+                <enum name="GL_X_EXT"/>
+                <enum name="GL_Y_EXT"/>
+                <enum name="GL_Z_EXT"/>
+                <enum name="GL_W_EXT"/>
+                <enum name="GL_NEGATIVE_X_EXT"/>
+                <enum name="GL_NEGATIVE_Y_EXT"/>
+                <enum name="GL_NEGATIVE_Z_EXT"/>
+                <enum name="GL_NEGATIVE_W_EXT"/>
+                <enum name="GL_ZERO_EXT"/>
+                <enum name="GL_ONE_EXT"/>
+                <enum name="GL_NEGATIVE_ONE_EXT"/>
+                <enum name="GL_NORMALIZED_RANGE_EXT"/>
+                <enum name="GL_FULL_RANGE_EXT"/>
+                <enum name="GL_CURRENT_VERTEX_EXT"/>
+                <enum name="GL_MVP_MATRIX_EXT"/>
+                <enum name="GL_VARIANT_VALUE_EXT"/>
+                <enum name="GL_VARIANT_DATATYPE_EXT"/>
+                <enum name="GL_VARIANT_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_VARIANT_ARRAY_TYPE_EXT"/>
+                <enum name="GL_VARIANT_ARRAY_EXT"/>
+                <enum name="GL_VARIANT_ARRAY_POINTER_EXT"/>
+                <enum name="GL_INVARIANT_VALUE_EXT"/>
+                <enum name="GL_INVARIANT_DATATYPE_EXT"/>
+                <enum name="GL_LOCAL_CONSTANT_VALUE_EXT"/>
+                <enum name="GL_LOCAL_CONSTANT_DATATYPE_EXT"/>
+                <command name="glBeginVertexShaderEXT"/>
+                <command name="glEndVertexShaderEXT"/>
+                <command name="glBindVertexShaderEXT"/>
+                <command name="glGenVertexShadersEXT"/>
+                <command name="glDeleteVertexShaderEXT"/>
+                <command name="glShaderOp1EXT"/>
+                <command name="glShaderOp2EXT"/>
+                <command name="glShaderOp3EXT"/>
+                <command name="glSwizzleEXT"/>
+                <command name="glWriteMaskEXT"/>
+                <command name="glInsertComponentEXT"/>
+                <command name="glExtractComponentEXT"/>
+                <command name="glGenSymbolsEXT"/>
+                <command name="glSetInvariantEXT"/>
+                <command name="glSetLocalConstantEXT"/>
+                <command name="glVariantbvEXT"/>
+                <command name="glVariantsvEXT"/>
+                <command name="glVariantivEXT"/>
+                <command name="glVariantfvEXT"/>
+                <command name="glVariantdvEXT"/>
+                <command name="glVariantubvEXT"/>
+                <command name="glVariantusvEXT"/>
+                <command name="glVariantuivEXT"/>
+                <command name="glVariantPointerEXT"/>
+                <command name="glEnableVariantClientStateEXT"/>
+                <command name="glDisableVariantClientStateEXT"/>
+                <command name="glBindLightParameterEXT"/>
+                <command name="glBindMaterialParameterEXT"/>
+                <command name="glBindTexGenParameterEXT"/>
+                <command name="glBindTextureUnitParameterEXT"/>
+                <command name="glBindParameterEXT"/>
+                <command name="glIsVariantEnabledEXT"/>
+                <command name="glGetVariantBooleanvEXT"/>
+                <command name="glGetVariantIntegervEXT"/>
+                <command name="glGetVariantFloatvEXT"/>
+                <command name="glGetVariantPointervEXT"/>
+                <command name="glGetInvariantBooleanvEXT"/>
+                <command name="glGetInvariantIntegervEXT"/>
+                <command name="glGetInvariantFloatvEXT"/>
+                <command name="glGetLocalConstantBooleanvEXT"/>
+                <command name="glGetLocalConstantIntegervEXT"/>
+                <command name="glGetLocalConstantFloatvEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_vertex_weighting" supported="gl">
+            <require>
+                <enum name="GL_MODELVIEW0_STACK_DEPTH_EXT"/>
+                <enum name="GL_MODELVIEW1_STACK_DEPTH_EXT"/>
+                <enum name="GL_MODELVIEW0_MATRIX_EXT"/>
+                <enum name="GL_MODELVIEW1_MATRIX_EXT"/>
+                <enum name="GL_VERTEX_WEIGHTING_EXT"/>
+                <enum name="GL_MODELVIEW0_EXT"/>
+                <enum name="GL_MODELVIEW1_EXT"/>
+                <enum name="GL_CURRENT_VERTEX_WEIGHT_EXT"/>
+                <enum name="GL_VERTEX_WEIGHT_ARRAY_EXT"/>
+                <enum name="GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT"/>
+                <enum name="GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT"/>
+                <enum name="GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT"/>
+                <enum name="GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT"/>
+                <command name="glVertexWeightfEXT"/>
+                <command name="glVertexWeightfvEXT"/>
+                <command name="glVertexWeightPointerEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_window_rectangles" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_INCLUSIVE_EXT"/>
+                <enum name="GL_EXCLUSIVE_EXT"/>
+                <enum name="GL_WINDOW_RECTANGLE_EXT"/>
+                <enum name="GL_WINDOW_RECTANGLE_MODE_EXT"/>
+                <enum name="GL_MAX_WINDOW_RECTANGLES_EXT"/>
+                <enum name="GL_NUM_WINDOW_RECTANGLES_EXT"/>
+                <command name="glWindowRectanglesEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_x11_sync_object" supported="gl">
+            <require>
+                <enum name="GL_SYNC_X11_FENCE_EXT"/>
+                <command name="glImportSyncEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_FJ_shader_binary_GCCSO" supported="gles2">
+            <require>
+                <enum name="GL_GCCSO_SHADER_BINARY_FJ"/>
+            </require>
+        </extension>
+        <extension name="GL_GREMEDY_frame_terminator" supported="gl">
+            <require>
+                <command name="glFrameTerminatorGREMEDY"/>
+            </require>
+        </extension>
+        <extension name="GL_GREMEDY_string_marker" supported="gl">
+            <require>
+                <command name="glStringMarkerGREMEDY"/>
+            </require>
+        </extension>
+        <extension name="GL_HP_convolution_border_modes" supported="gl">
+            <require>
+                <enum name="GL_IGNORE_BORDER_HP"/>
+                <enum name="GL_CONSTANT_BORDER_HP"/>
+                <enum name="GL_REPLICATE_BORDER_HP"/>
+                <enum name="GL_CONVOLUTION_BORDER_COLOR_HP"/>
+            </require>
+        </extension>
+        <extension name="GL_HP_image_transform" supported="gl">
+            <require>
+                <enum name="GL_IMAGE_SCALE_X_HP"/>
+                <enum name="GL_IMAGE_SCALE_Y_HP"/>
+                <enum name="GL_IMAGE_TRANSLATE_X_HP"/>
+                <enum name="GL_IMAGE_TRANSLATE_Y_HP"/>
+                <enum name="GL_IMAGE_ROTATE_ANGLE_HP"/>
+                <enum name="GL_IMAGE_ROTATE_ORIGIN_X_HP"/>
+                <enum name="GL_IMAGE_ROTATE_ORIGIN_Y_HP"/>
+                <enum name="GL_IMAGE_MAG_FILTER_HP"/>
+                <enum name="GL_IMAGE_MIN_FILTER_HP"/>
+                <enum name="GL_IMAGE_CUBIC_WEIGHT_HP"/>
+                <enum name="GL_CUBIC_HP"/>
+                <enum name="GL_AVERAGE_HP"/>
+                <enum name="GL_IMAGE_TRANSFORM_2D_HP"/>
+                <enum name="GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP"/>
+                <enum name="GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP"/>
+                <command name="glImageTransformParameteriHP"/>
+                <command name="glImageTransformParameterfHP"/>
+                <command name="glImageTransformParameterivHP"/>
+                <command name="glImageTransformParameterfvHP"/>
+                <command name="glGetImageTransformParameterivHP"/>
+                <command name="glGetImageTransformParameterfvHP"/>
+            </require>
+        </extension>
+        <extension name="GL_HP_occlusion_test" supported="gl">
+            <require>
+                <enum name="GL_OCCLUSION_TEST_HP"/>
+                <enum name="GL_OCCLUSION_TEST_RESULT_HP"/>
+            </require>
+        </extension>
+        <extension name="GL_HP_texture_lighting" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_LIGHTING_MODE_HP"/>
+                <enum name="GL_TEXTURE_POST_SPECULAR_HP"/>
+                <enum name="GL_TEXTURE_PRE_SPECULAR_HP"/>
+            </require>
+        </extension>
+        <extension name="GL_IBM_cull_vertex" supported="gl">
+            <require>
+                <enum name="GL_CULL_VERTEX_IBM"/>
+            </require>
+        </extension>
+        <extension name="GL_IBM_multimode_draw_arrays" supported="gl">
+            <require>
+                <command name="glMultiModeDrawArraysIBM"/>
+                <command name="glMultiModeDrawElementsIBM"/>
+            </require>
+        </extension>
+        <extension name="GL_IBM_rasterpos_clip" supported="gl">
+            <require>
+                <enum name="GL_RASTER_POSITION_UNCLIPPED_IBM"/>
+            </require>
+        </extension>
+        <extension name="GL_IBM_static_data" supported="gl">
+            <require>
+                <enum name="GL_ALL_STATIC_DATA_IBM"/>
+                <enum name="GL_STATIC_VERTEX_ARRAY_IBM"/>
+                <command name="glFlushStaticDataIBM"/>
+            </require>
+        </extension>
+        <extension name="GL_IBM_texture_mirrored_repeat" supported="gl">
+            <require>
+                <enum name="GL_MIRRORED_REPEAT_IBM"/>
+            </require>
+        </extension>
+        <extension name="GL_IBM_vertex_array_lists" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ARRAY_LIST_IBM"/>
+                <enum name="GL_NORMAL_ARRAY_LIST_IBM"/>
+                <enum name="GL_COLOR_ARRAY_LIST_IBM"/>
+                <enum name="GL_INDEX_ARRAY_LIST_IBM"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_LIST_IBM"/>
+                <enum name="GL_EDGE_FLAG_ARRAY_LIST_IBM"/>
+                <enum name="GL_FOG_COORDINATE_ARRAY_LIST_IBM"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_LIST_IBM"/>
+                <enum name="GL_VERTEX_ARRAY_LIST_STRIDE_IBM"/>
+                <enum name="GL_NORMAL_ARRAY_LIST_STRIDE_IBM"/>
+                <enum name="GL_COLOR_ARRAY_LIST_STRIDE_IBM"/>
+                <enum name="GL_INDEX_ARRAY_LIST_STRIDE_IBM"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM"/>
+                <enum name="GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM"/>
+                <enum name="GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM"/>
+                <command name="glColorPointerListIBM"/>
+                <command name="glSecondaryColorPointerListIBM"/>
+                <command name="glEdgeFlagPointerListIBM"/>
+                <command name="glFogCoordPointerListIBM"/>
+                <command name="glIndexPointerListIBM"/>
+                <command name="glNormalPointerListIBM"/>
+                <command name="glTexCoordPointerListIBM"/>
+                <command name="glVertexPointerListIBM"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_bindless_texture" supported="gles2">
+            <require>
+                <command name="glGetTextureHandleIMG"/>
+                <command name="glGetTextureSamplerHandleIMG"/>
+                <command name="glUniformHandleui64IMG"/>
+                <command name="glUniformHandleui64vIMG"/>
+                <command name="glProgramUniformHandleui64IMG"/>
+                <command name="glProgramUniformHandleui64vIMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_framebuffer_downsample" supported="gles2">
+            <require>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG"/>
+                <enum name="GL_NUM_DOWNSAMPLE_SCALES_IMG"/>
+                <enum name="GL_DOWNSAMPLE_SCALES_IMG"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG"/>
+                <command name="glFramebufferTexture2DDownsampleIMG"/>
+                <command name="glFramebufferTextureLayerDownsampleIMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_multisampled_render_to_texture" supported="gles1|gles2">
+            <require>
+                <enum name="GL_RENDERBUFFER_SAMPLES_IMG"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG"/>
+                <enum name="GL_MAX_SAMPLES_IMG"/>
+                <enum name="GL_TEXTURE_SAMPLES_IMG"/>
+                <command name="glRenderbufferStorageMultisampleIMG"/>
+                <command name="glFramebufferTexture2DMultisampleIMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_program_binary" supported="gles2">
+            <require>
+                <enum name="GL_SGX_PROGRAM_BINARY_IMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_read_format" supported="gles1|gles2">
+            <require>
+                <enum name="GL_BGRA_IMG"/>
+                <enum name="GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_shader_binary" supported="gles2">
+            <require>
+                <enum name="GL_SGX_BINARY_IMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_texture_compression_pvrtc" supported="gles1|gles2">
+            <require>
+                <enum name="GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG"/>
+                <enum name="GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG"/>
+                <enum name="GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG"/>
+                <enum name="GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_texture_compression_pvrtc2" supported="gles2">
+            <require>
+                <enum name="GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG"/>
+                <enum name="GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_texture_env_enhanced_fixed_function" supported="gles1">
+            <require>
+                <enum name="GL_MODULATE_COLOR_IMG"/>
+                <enum name="GL_RECIP_ADD_SIGNED_ALPHA_IMG"/>
+                <enum name="GL_TEXTURE_ALPHA_MODULATE_IMG"/>
+                <enum name="GL_FACTOR_ALPHA_MODULATE_IMG"/>
+                <enum name="GL_FRAGMENT_ALPHA_MODULATE_IMG"/>
+                <enum name="GL_ADD_BLEND_IMG"/>
+                <enum name="GL_DOT3_RGBA_IMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_texture_filter_cubic" supported="gles2">
+            <require>
+                <enum name="GL_CUBIC_IMG"/>
+                <enum name="GL_CUBIC_MIPMAP_NEAREST_IMG"/>
+                <enum name="GL_CUBIC_MIPMAP_LINEAR_IMG"/>
+            </require>
+        </extension>
+        <extension name="GL_IMG_user_clip_plane" supported="gles1">
+            <require>
+                <enum name="GL_CLIP_PLANE0_IMG"/>
+                <enum name="GL_CLIP_PLANE1_IMG"/>
+                <enum name="GL_CLIP_PLANE2_IMG"/>
+                <enum name="GL_CLIP_PLANE3_IMG"/>
+                <enum name="GL_CLIP_PLANE4_IMG"/>
+                <enum name="GL_CLIP_PLANE5_IMG"/>
+                <enum name="GL_MAX_CLIP_PLANES_IMG"/>
+                <command name="glClipPlanefIMG"/>
+                <command name="glClipPlanexIMG"/>
+            </require>
+        </extension>
+        <extension name="GL_INGR_blend_func_separate" supported="gl">
+            <require>
+                <command name="glBlendFuncSeparateINGR"/>
+            </require>
+        </extension>
+        <extension name="GL_INGR_color_clamp" supported="gl">
+            <require>
+                <enum name="GL_RED_MIN_CLAMP_INGR"/>
+                <enum name="GL_GREEN_MIN_CLAMP_INGR"/>
+                <enum name="GL_BLUE_MIN_CLAMP_INGR"/>
+                <enum name="GL_ALPHA_MIN_CLAMP_INGR"/>
+                <enum name="GL_RED_MAX_CLAMP_INGR"/>
+                <enum name="GL_GREEN_MAX_CLAMP_INGR"/>
+                <enum name="GL_BLUE_MAX_CLAMP_INGR"/>
+                <enum name="GL_ALPHA_MAX_CLAMP_INGR"/>
+            </require>
+        </extension>
+        <extension name="GL_INGR_interlace_read" supported="gl">
+            <require>
+                <enum name="GL_INTERLACE_READ_INGR"/>
+            </require>
+        </extension>
+        <extension name="GL_INTEL_conservative_rasterization" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_CONSERVATIVE_RASTERIZATION_INTEL"/>
+            </require>
+        </extension>
+        <extension name="GL_INTEL_fragment_shader_ordering" supported="gl"/>
+        <extension name="GL_INTEL_framebuffer_CMAA" supported="gl|glcore|gles2">
+            <require>
+                <command name="glApplyFramebufferAttachmentCMAAINTEL"/>
+            </require>
+        </extension>
+        <extension name="GL_INTEL_map_texture" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_MEMORY_LAYOUT_INTEL"/>
+                <enum name="GL_LAYOUT_DEFAULT_INTEL"/>
+                <enum name="GL_LAYOUT_LINEAR_INTEL"/>
+                <enum name="GL_LAYOUT_LINEAR_CPU_CACHED_INTEL"/>
+                <command name="glSyncTextureINTEL"/>
+                <command name="glUnmapTexture2DINTEL"/>
+                <command name="glMapTexture2DINTEL"/>
+            </require>
+        </extension>
+        <extension name="GL_INTEL_parallel_arrays" supported="gl">
+            <require>
+                <enum name="GL_PARALLEL_ARRAYS_INTEL"/>
+                <enum name="GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL"/>
+                <enum name="GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL"/>
+                <enum name="GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL"/>
+                <command name="glVertexPointervINTEL"/>
+                <command name="glNormalPointervINTEL"/>
+                <command name="glColorPointervINTEL"/>
+                <command name="glTexCoordPointervINTEL"/>
+            </require>
+        </extension>
+        <extension name="GL_INTEL_performance_query" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_PERFQUERY_SINGLE_CONTEXT_INTEL"/>
+                <enum name="GL_PERFQUERY_GLOBAL_CONTEXT_INTEL"/>
+                <enum name="GL_PERFQUERY_WAIT_INTEL"/>
+                <enum name="GL_PERFQUERY_FLUSH_INTEL"/>
+                <enum name="GL_PERFQUERY_DONOT_FLUSH_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_EVENT_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_RAW_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL"/>
+                <enum name="GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL"/>
+                <enum name="GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL"/>
+                <enum name="GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL"/>
+                <command name="glBeginPerfQueryINTEL"/>
+                <command name="glCreatePerfQueryINTEL"/>
+                <command name="glDeletePerfQueryINTEL"/>
+                <command name="glEndPerfQueryINTEL"/>
+                <command name="glGetFirstPerfQueryIdINTEL"/>
+                <command name="glGetNextPerfQueryIdINTEL"/>
+                <command name="glGetPerfCounterInfoINTEL"/>
+                <command name="glGetPerfQueryDataINTEL"/>
+                <command name="glGetPerfQueryIdByNameINTEL"/>
+                <command name="glGetPerfQueryInfoINTEL"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_blend_equation_advanced" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_MULTIPLY_KHR"/>
+                <enum name="GL_SCREEN_KHR"/>
+                <enum name="GL_OVERLAY_KHR"/>
+                <enum name="GL_DARKEN_KHR"/>
+                <enum name="GL_LIGHTEN_KHR"/>
+                <enum name="GL_COLORDODGE_KHR"/>
+                <enum name="GL_COLORBURN_KHR"/>
+                <enum name="GL_HARDLIGHT_KHR"/>
+                <enum name="GL_SOFTLIGHT_KHR"/>
+                <enum name="GL_DIFFERENCE_KHR"/>
+                <enum name="GL_EXCLUSION_KHR"/>
+                <enum name="GL_HSL_HUE_KHR"/>
+                <enum name="GL_HSL_SATURATION_KHR"/>
+                <enum name="GL_HSL_COLOR_KHR"/>
+                <enum name="GL_HSL_LUMINOSITY_KHR"/>
+                <command name="glBlendBarrierKHR"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_blend_equation_advanced_coherent" supported="gl|glcore|gles2">
+            <require comment="Otherwise identical to GL_KHR_blend_equation_advanced, just different semantic behavior">
+                <enum name="GL_BLEND_ADVANCED_COHERENT_KHR"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_context_flush_control" supported="gl|glcore|gles2">
+            <require api="gl" comment="KHR extensions *mandate* suffixes for ES, unlike for GL">
+                <enum name="GL_CONTEXT_RELEASE_BEHAVIOR"/>
+                <enum name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH"/>
+                <enum name="GL_NONE"/>
+            </require>
+            <require api="gles2">
+                <enum name="GL_CONTEXT_RELEASE_BEHAVIOR_KHR"/>
+                <enum name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR"/>
+                <enum name="GL_NONE"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_debug" supported="gl|glcore|gles2">
+            <require api="gl" comment="KHR extensions *mandate* suffixes for ES, unlike for GL">
+                <enum name="GL_DEBUG_OUTPUT_SYNCHRONOUS"/>
+                <enum name="GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH"/>
+                <enum name="GL_DEBUG_CALLBACK_FUNCTION"/>
+                <enum name="GL_DEBUG_CALLBACK_USER_PARAM"/>
+                <enum name="GL_DEBUG_SOURCE_API"/>
+                <enum name="GL_DEBUG_SOURCE_WINDOW_SYSTEM"/>
+                <enum name="GL_DEBUG_SOURCE_SHADER_COMPILER"/>
+                <enum name="GL_DEBUG_SOURCE_THIRD_PARTY"/>
+                <enum name="GL_DEBUG_SOURCE_APPLICATION"/>
+                <enum name="GL_DEBUG_SOURCE_OTHER"/>
+                <enum name="GL_DEBUG_TYPE_ERROR"/>
+                <enum name="GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"/>
+                <enum name="GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"/>
+                <enum name="GL_DEBUG_TYPE_PORTABILITY"/>
+                <enum name="GL_DEBUG_TYPE_PERFORMANCE"/>
+                <enum name="GL_DEBUG_TYPE_OTHER"/>
+                <enum name="GL_DEBUG_TYPE_MARKER"/>
+                <enum name="GL_DEBUG_TYPE_PUSH_GROUP"/>
+                <enum name="GL_DEBUG_TYPE_POP_GROUP"/>
+                <enum name="GL_DEBUG_SEVERITY_NOTIFICATION"/>
+                <enum name="GL_MAX_DEBUG_GROUP_STACK_DEPTH"/>
+                <enum name="GL_DEBUG_GROUP_STACK_DEPTH"/>
+                <enum name="GL_BUFFER"/>
+                <enum name="GL_SHADER"/>
+                <enum name="GL_PROGRAM"/>
+                <enum name="GL_VERTEX_ARRAY"/>
+                <enum name="GL_QUERY"/>
+                <enum name="GL_PROGRAM_PIPELINE"/>
+                <enum name="GL_SAMPLER"/>
+                <enum name="GL_MAX_LABEL_LENGTH"/>
+                <enum name="GL_MAX_DEBUG_MESSAGE_LENGTH"/>
+                <enum name="GL_MAX_DEBUG_LOGGED_MESSAGES"/>
+                <enum name="GL_DEBUG_LOGGED_MESSAGES"/>
+                <enum name="GL_DEBUG_SEVERITY_HIGH"/>
+                <enum name="GL_DEBUG_SEVERITY_MEDIUM"/>
+                <enum name="GL_DEBUG_SEVERITY_LOW"/>
+                <enum name="GL_DEBUG_OUTPUT"/>
+                <enum name="GL_CONTEXT_FLAG_DEBUG_BIT"/>
+                <enum name="GL_STACK_OVERFLOW"/>
+                <enum name="GL_STACK_UNDERFLOW"/>
+                <command name="glDebugMessageControl"/>
+                <command name="glDebugMessageInsert"/>
+                <command name="glDebugMessageCallback"/>
+                <command name="glGetDebugMessageLog"/>
+                <command name="glPushDebugGroup"/>
+                <command name="glPopDebugGroup"/>
+                <command name="glObjectLabel"/>
+                <command name="glGetObjectLabel"/>
+                <command name="glObjectPtrLabel"/>
+                <command name="glGetObjectPtrLabel"/>
+                <command name="glGetPointerv"/>
+            </require>
+            <require api="gles2">
+                <enum name="GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR"/>
+                <enum name="GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR"/>
+                <enum name="GL_DEBUG_CALLBACK_FUNCTION_KHR"/>
+                <enum name="GL_DEBUG_CALLBACK_USER_PARAM_KHR"/>
+                <enum name="GL_DEBUG_SOURCE_API_KHR"/>
+                <enum name="GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR"/>
+                <enum name="GL_DEBUG_SOURCE_SHADER_COMPILER_KHR"/>
+                <enum name="GL_DEBUG_SOURCE_THIRD_PARTY_KHR"/>
+                <enum name="GL_DEBUG_SOURCE_APPLICATION_KHR"/>
+                <enum name="GL_DEBUG_SOURCE_OTHER_KHR"/>
+                <enum name="GL_DEBUG_TYPE_ERROR_KHR"/>
+                <enum name="GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR"/>
+                <enum name="GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR"/>
+                <enum name="GL_DEBUG_TYPE_PORTABILITY_KHR"/>
+                <enum name="GL_DEBUG_TYPE_PERFORMANCE_KHR"/>
+                <enum name="GL_DEBUG_TYPE_OTHER_KHR"/>
+                <enum name="GL_DEBUG_TYPE_MARKER_KHR"/>
+                <enum name="GL_DEBUG_TYPE_PUSH_GROUP_KHR"/>
+                <enum name="GL_DEBUG_TYPE_POP_GROUP_KHR"/>
+                <enum name="GL_DEBUG_SEVERITY_NOTIFICATION_KHR"/>
+                <enum name="GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR"/>
+                <enum name="GL_DEBUG_GROUP_STACK_DEPTH_KHR"/>
+                <enum name="GL_BUFFER_KHR"/>
+                <enum name="GL_SHADER_KHR"/>
+                <enum name="GL_PROGRAM_KHR"/>
+                <enum name="GL_VERTEX_ARRAY_KHR"/>
+                <enum name="GL_QUERY_KHR"/>
+                <enum name="GL_PROGRAM_PIPELINE_KHR"/>
+                <enum name="GL_SAMPLER_KHR"/>
+                <enum name="GL_MAX_LABEL_LENGTH_KHR"/>
+                <enum name="GL_MAX_DEBUG_MESSAGE_LENGTH_KHR"/>
+                <enum name="GL_MAX_DEBUG_LOGGED_MESSAGES_KHR"/>
+                <enum name="GL_DEBUG_LOGGED_MESSAGES_KHR"/>
+                <enum name="GL_DEBUG_SEVERITY_HIGH_KHR"/>
+                <enum name="GL_DEBUG_SEVERITY_MEDIUM_KHR"/>
+                <enum name="GL_DEBUG_SEVERITY_LOW_KHR"/>
+                <enum name="GL_DEBUG_OUTPUT_KHR"/>
+                <enum name="GL_CONTEXT_FLAG_DEBUG_BIT_KHR"/>
+                <enum name="GL_STACK_OVERFLOW_KHR"/>
+                <enum name="GL_STACK_UNDERFLOW_KHR"/>
+                <command name="glDebugMessageControlKHR"/>
+                <command name="glDebugMessageInsertKHR"/>
+                <command name="glDebugMessageCallbackKHR"/>
+                <command name="glGetDebugMessageLogKHR"/>
+                <command name="glPushDebugGroupKHR"/>
+                <command name="glPopDebugGroupKHR"/>
+                <command name="glObjectLabelKHR"/>
+                <command name="glGetObjectLabelKHR"/>
+                <command name="glObjectPtrLabelKHR"/>
+                <command name="glGetObjectPtrLabelKHR"/>
+                <command name="glGetPointervKHR"/>
+            </require>
+            <require api="gl" profile="compatibility">
+                <enum name="GL_DISPLAY_LIST"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_no_error" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_robust_buffer_access_behavior" supported="gl|glcore|gles2"/>
+        <extension name="GL_KHR_robustness" supported="gl|glcore|gles2">
+            <require api="gl" comment="KHR extensions *mandate* suffixes for ES, unlike for GL">
+                <enum name="GL_NO_ERROR"/>
+                <enum name="GL_CONTEXT_ROBUST_ACCESS"/>
+                <enum name="GL_LOSE_CONTEXT_ON_RESET"/>
+                <enum name="GL_GUILTY_CONTEXT_RESET"/>
+                <enum name="GL_INNOCENT_CONTEXT_RESET"/>
+                <enum name="GL_UNKNOWN_CONTEXT_RESET"/>
+                <enum name="GL_RESET_NOTIFICATION_STRATEGY"/>
+                <enum name="GL_NO_RESET_NOTIFICATION"/>
+                <enum name="GL_CONTEXT_LOST"/>
+                <command name="glGetGraphicsResetStatus"/>
+                <command name="glReadnPixels"/>
+                <command name="glGetnUniformfv"/>
+                <command name="glGetnUniformiv"/>
+                <command name="glGetnUniformuiv"/>
+            </require>
+            <require api="gles2">
+                <enum name="GL_NO_ERROR"/>
+                <enum name="GL_CONTEXT_ROBUST_ACCESS_KHR"/>
+                <enum name="GL_LOSE_CONTEXT_ON_RESET_KHR"/>
+                <enum name="GL_GUILTY_CONTEXT_RESET_KHR"/>
+                <enum name="GL_INNOCENT_CONTEXT_RESET_KHR"/>
+                <enum name="GL_UNKNOWN_CONTEXT_RESET_KHR"/>
+                <enum name="GL_RESET_NOTIFICATION_STRATEGY_KHR"/>
+                <enum name="GL_NO_RESET_NOTIFICATION_KHR"/>
+                <enum name="GL_CONTEXT_LOST_KHR"/>
+                <command name="glGetGraphicsResetStatusKHR"/>
+                <command name="glReadnPixelsKHR"/>
+                <command name="glGetnUniformfvKHR"/>
+                <command name="glGetnUniformivKHR"/>
+                <command name="glGetnUniformuivKHR"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_texture_compression_astc_hdr" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_4x4_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_5x4_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_5x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_6x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_6x6_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_8x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_8x6_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_8x8_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x6_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x8_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x10_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_12x10_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_12x12_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_texture_compression_astc_ldr" supported="gl|glcore|gles2" comment="API is identical to GL_KHR_texture_compression_astc_hdr extension">
+            <require>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_4x4_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_5x4_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_5x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_6x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_6x6_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_8x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_8x6_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_8x8_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x6_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x8_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x10_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_12x10_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_12x12_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_texture_compression_astc_sliced_3d" supported="gl|glcore|gles2"/>
+        <extension name="GL_MESAX_texture_stack" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_1D_STACK_MESAX"/>
+                <enum name="GL_TEXTURE_2D_STACK_MESAX"/>
+                <enum name="GL_PROXY_TEXTURE_1D_STACK_MESAX"/>
+                <enum name="GL_PROXY_TEXTURE_2D_STACK_MESAX"/>
+                <enum name="GL_TEXTURE_1D_STACK_BINDING_MESAX"/>
+                <enum name="GL_TEXTURE_2D_STACK_BINDING_MESAX"/>
+            </require>
+        </extension>
+        <extension name="GL_MESA_pack_invert" supported="gl">
+            <require>
+                <enum name="GL_PACK_INVERT_MESA"/>
+            </require>
+        </extension>
+        <extension name="GL_MESA_resize_buffers" supported="gl">
+            <require>
+                <command name="glResizeBuffersMESA"/>
+            </require>
+        </extension>
+        <extension name="GL_MESA_window_pos" supported="gl">
+            <require>
+                <command name="glWindowPos2dMESA"/>
+                <command name="glWindowPos2dvMESA"/>
+                <command name="glWindowPos2fMESA"/>
+                <command name="glWindowPos2fvMESA"/>
+                <command name="glWindowPos2iMESA"/>
+                <command name="glWindowPos2ivMESA"/>
+                <command name="glWindowPos2sMESA"/>
+                <command name="glWindowPos2svMESA"/>
+                <command name="glWindowPos3dMESA"/>
+                <command name="glWindowPos3dvMESA"/>
+                <command name="glWindowPos3fMESA"/>
+                <command name="glWindowPos3fvMESA"/>
+                <command name="glWindowPos3iMESA"/>
+                <command name="glWindowPos3ivMESA"/>
+                <command name="glWindowPos3sMESA"/>
+                <command name="glWindowPos3svMESA"/>
+                <command name="glWindowPos4dMESA"/>
+                <command name="glWindowPos4dvMESA"/>
+                <command name="glWindowPos4fMESA"/>
+                <command name="glWindowPos4fvMESA"/>
+                <command name="glWindowPos4iMESA"/>
+                <command name="glWindowPos4ivMESA"/>
+                <command name="glWindowPos4sMESA"/>
+                <command name="glWindowPos4svMESA"/>
+            </require>
+        </extension>
+        <extension name="GL_MESA_ycbcr_texture" supported="gl">
+            <require>
+                <enum name="GL_UNSIGNED_SHORT_8_8_MESA"/>
+                <enum name="GL_UNSIGNED_SHORT_8_8_REV_MESA"/>
+                <enum name="GL_YCBCR_MESA"/>
+            </require>
+        </extension>
+        <extension name="GL_NVX_conditional_render" supported="gl">
+            <require>
+                <command name="glBeginConditionalRenderNVX"/>
+                <command name="glEndConditionalRenderNVX"/>
+            </require>
+        </extension>
+        <extension name="GL_NVX_gpu_memory_info" supported="gl">
+            <require>
+                <enum name="GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX"/>
+                <enum name="GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX"/>
+                <enum name="GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX"/>
+                <enum name="GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX"/>
+                <enum name="GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_bindless_multi_draw_indirect" supported="gl">
+            <require>
+                <command name="glMultiDrawArraysIndirectBindlessNV"/>
+                <command name="glMultiDrawElementsIndirectBindlessNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_bindless_multi_draw_indirect_count" supported="gl">
+            <require>
+                <command name="glMultiDrawArraysIndirectBindlessCountNV"/>
+                <command name="glMultiDrawElementsIndirectBindlessCountNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_bindless_texture" supported="gl|glcore|gles2">
+            <require>
+                <command name="glGetTextureHandleNV"/>
+                <command name="glGetTextureSamplerHandleNV"/>
+                <command name="glMakeTextureHandleResidentNV"/>
+                <command name="glMakeTextureHandleNonResidentNV"/>
+                <command name="glGetImageHandleNV"/>
+                <command name="glMakeImageHandleResidentNV"/>
+                <command name="glMakeImageHandleNonResidentNV"/>
+                <command name="glUniformHandleui64NV"/>
+                <command name="glUniformHandleui64vNV"/>
+                <command name="glProgramUniformHandleui64NV"/>
+                <command name="glProgramUniformHandleui64vNV"/>
+                <command name="glIsTextureHandleResidentNV"/>
+                <command name="glIsImageHandleResidentNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_blend_equation_advanced" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_BLEND_OVERLAP_NV"/>
+                <enum name="GL_BLEND_PREMULTIPLIED_SRC_NV"/>
+                <enum name="GL_BLUE_NV"/>
+                <enum name="GL_COLORBURN_NV"/>
+                <enum name="GL_COLORDODGE_NV"/>
+                <enum name="GL_CONJOINT_NV"/>
+                <enum name="GL_CONTRAST_NV"/>
+                <enum name="GL_DARKEN_NV"/>
+                <enum name="GL_DIFFERENCE_NV"/>
+                <enum name="GL_DISJOINT_NV"/>
+                <enum name="GL_DST_ATOP_NV"/>
+                <enum name="GL_DST_IN_NV"/>
+                <enum name="GL_DST_NV"/>
+                <enum name="GL_DST_OUT_NV"/>
+                <enum name="GL_DST_OVER_NV"/>
+                <enum name="GL_EXCLUSION_NV"/>
+                <enum name="GL_GREEN_NV"/>
+                <enum name="GL_HARDLIGHT_NV"/>
+                <enum name="GL_HARDMIX_NV"/>
+                <enum name="GL_HSL_COLOR_NV"/>
+                <enum name="GL_HSL_HUE_NV"/>
+                <enum name="GL_HSL_LUMINOSITY_NV"/>
+                <enum name="GL_HSL_SATURATION_NV"/>
+                <enum name="GL_INVERT"/>
+                <enum name="GL_INVERT_OVG_NV"/>
+                <enum name="GL_INVERT_RGB_NV"/>
+                <enum name="GL_LIGHTEN_NV"/>
+                <enum name="GL_LINEARBURN_NV"/>
+                <enum name="GL_LINEARDODGE_NV"/>
+                <enum name="GL_LINEARLIGHT_NV"/>
+                <enum name="GL_MINUS_CLAMPED_NV"/>
+                <enum name="GL_MINUS_NV"/>
+                <enum name="GL_MULTIPLY_NV"/>
+                <enum name="GL_OVERLAY_NV"/>
+                <enum name="GL_PINLIGHT_NV"/>
+                <enum name="GL_PLUS_CLAMPED_ALPHA_NV"/>
+                <enum name="GL_PLUS_CLAMPED_NV"/>
+                <enum name="GL_PLUS_DARKER_NV"/>
+                <enum name="GL_PLUS_NV"/>
+                <enum name="GL_RED_NV"/>
+                <enum name="GL_SCREEN_NV"/>
+                <enum name="GL_SOFTLIGHT_NV"/>
+                <enum name="GL_SRC_ATOP_NV"/>
+                <enum name="GL_SRC_IN_NV"/>
+                <enum name="GL_SRC_NV"/>
+                <enum name="GL_SRC_OUT_NV"/>
+                <enum name="GL_SRC_OVER_NV"/>
+                <enum name="GL_UNCORRELATED_NV"/>
+                <enum name="GL_VIVIDLIGHT_NV"/>
+                <enum name="GL_XOR_NV"/>
+                <enum name="GL_ZERO"/>
+                <command name="glBlendParameteriNV"/>
+                <command name="glBlendBarrierNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_blend_equation_advanced_coherent" supported="gl|glcore|gles2">
+            <require comment="Otherwise identical to GL_NV_blend_equation_advanced, just different semantic behavior">
+                <enum name="GL_BLEND_ADVANCED_COHERENT_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_blend_square" supported="gl"/>
+        <extension name="GL_NV_clip_space_w_scaling" supported="gl">
+            <require>
+                <enum name="GL_VIEWPORT_POSITION_W_SCALE_NV"/>
+                <enum name="GL_VIEWPORT_POSITION_W_SCALE_X_COEFF_NV"/>
+                <enum name="GL_VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV"/>
+                <command name="glViewportPositionWScaleNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_command_list" supported="gl">
+            <require>
+                <enum name="GL_TERMINATE_SEQUENCE_COMMAND_NV"/>
+                <enum name="GL_NOP_COMMAND_NV"/>
+                <enum name="GL_DRAW_ELEMENTS_COMMAND_NV"/>
+                <enum name="GL_DRAW_ARRAYS_COMMAND_NV"/>
+                <enum name="GL_DRAW_ELEMENTS_STRIP_COMMAND_NV"/>
+                <enum name="GL_DRAW_ARRAYS_STRIP_COMMAND_NV"/>
+                <enum name="GL_DRAW_ELEMENTS_INSTANCED_COMMAND_NV"/>
+                <enum name="GL_DRAW_ARRAYS_INSTANCED_COMMAND_NV"/>
+                <enum name="GL_ELEMENT_ADDRESS_COMMAND_NV"/>
+                <enum name="GL_ATTRIBUTE_ADDRESS_COMMAND_NV"/>
+                <enum name="GL_UNIFORM_ADDRESS_COMMAND_NV"/>
+                <enum name="GL_BLEND_COLOR_COMMAND_NV"/>
+                <enum name="GL_STENCIL_REF_COMMAND_NV"/>
+                <enum name="GL_LINE_WIDTH_COMMAND_NV"/>
+                <enum name="GL_POLYGON_OFFSET_COMMAND_NV"/>
+                <enum name="GL_ALPHA_REF_COMMAND_NV"/>
+                <enum name="GL_VIEWPORT_COMMAND_NV"/>
+                <enum name="GL_SCISSOR_COMMAND_NV"/>
+                <enum name="GL_FRONT_FACE_COMMAND_NV"/>
+                <command name="glCreateStatesNV"/>
+                <command name="glDeleteStatesNV"/>
+                <command name="glIsStateNV"/>
+                <command name="glStateCaptureNV"/>
+                <command name="glGetCommandHeaderNV"/>
+                <command name="glGetStageIndexNV"/>
+                <command name="glDrawCommandsNV"/>
+                <command name="glDrawCommandsAddressNV"/>
+                <command name="glDrawCommandsStatesNV"/>
+                <command name="glDrawCommandsStatesAddressNV"/>
+                <command name="glCreateCommandListsNV"/>
+                <command name="glDeleteCommandListsNV"/>
+                <command name="glIsCommandListNV"/>
+                <command name="glListDrawCommandsStatesClientNV"/>
+                <command name="glCommandListSegmentsNV"/>
+                <command name="glCompileCommandListNV"/>
+                <command name="glCallCommandListNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_compute_program5" supported="gl">
+            <require>
+                <enum name="GL_COMPUTE_PROGRAM_NV"/>
+                <enum name="GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_conditional_render" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_QUERY_WAIT_NV"/>
+                <enum name="GL_QUERY_NO_WAIT_NV"/>
+                <enum name="GL_QUERY_BY_REGION_WAIT_NV"/>
+                <enum name="GL_QUERY_BY_REGION_NO_WAIT_NV"/>
+                <command name="glBeginConditionalRenderNV"/>
+                <command name="glEndConditionalRenderNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_conservative_raster" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_CONSERVATIVE_RASTERIZATION_NV"/>
+                <enum name="GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV"/>
+                <enum name="GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV"/>
+                <enum name="GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV"/>
+                <command name="glSubpixelPrecisionBiasNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_conservative_raster_dilate" supported="gl">
+            <require>
+                <enum name="GL_CONSERVATIVE_RASTER_DILATE_NV"/>
+                <enum name="GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV"/>
+                <enum name="GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV"/>
+                <command name="glConservativeRasterParameterfNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_conservative_raster_pre_snap_triangles" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_CONSERVATIVE_RASTER_MODE_NV"/>
+                <enum name="GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV"/>
+                <enum name="GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV"/>
+                <enum name="GL_CONSERVATIVE_RASTER_MODE_NV"/>
+                <command name="glConservativeRasterParameteriNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_copy_buffer" supported="gles2">
+            <require>
+                <enum name="GL_COPY_READ_BUFFER_NV"/>
+                <enum name="GL_COPY_WRITE_BUFFER_NV"/>
+                <command name="glCopyBufferSubDataNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_copy_depth_to_color" supported="gl">
+            <require>
+                <enum name="GL_DEPTH_STENCIL_TO_RGBA_NV"/>
+                <enum name="GL_DEPTH_STENCIL_TO_BGRA_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_copy_image" supported="gl">
+            <require>
+                <command name="glCopyImageSubDataNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_coverage_sample" supported="gles2">
+            <require>
+                <enum name="GL_COVERAGE_COMPONENT_NV"/>
+                <enum name="GL_COVERAGE_COMPONENT4_NV"/>
+                <enum name="GL_COVERAGE_ATTACHMENT_NV"/>
+                <enum name="GL_COVERAGE_BUFFERS_NV"/>
+                <enum name="GL_COVERAGE_SAMPLES_NV"/>
+                <enum name="GL_COVERAGE_ALL_FRAGMENTS_NV"/>
+                <enum name="GL_COVERAGE_EDGE_FRAGMENTS_NV"/>
+                <enum name="GL_COVERAGE_AUTOMATIC_NV"/>
+                <enum name="GL_COVERAGE_BUFFER_BIT_NV"/>
+                <command name="glCoverageMaskNV"/>
+                <command name="glCoverageOperationNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_deep_texture3D" supported="gl">
+            <require>
+                <enum name="GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV"/>
+                <enum name="GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_depth_buffer_float" supported="gl">
+            <require>
+                <enum name="GL_DEPTH_COMPONENT32F_NV"/>
+                <enum name="GL_DEPTH32F_STENCIL8_NV"/>
+                <enum name="GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV"/>
+                <enum name="GL_DEPTH_BUFFER_FLOAT_MODE_NV"/>
+                <command name="glDepthRangedNV"/>
+                <command name="glClearDepthdNV"/>
+                <command name="glDepthBoundsdNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_depth_clamp" supported="gl">
+            <require>
+                <enum name="GL_DEPTH_CLAMP_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_depth_nonlinear" supported="gles2">
+            <require>
+                <enum name="GL_DEPTH_COMPONENT16_NONLINEAR_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_draw_buffers" supported="gles2">
+            <require>
+                <enum name="GL_MAX_DRAW_BUFFERS_NV"/>
+                <enum name="GL_DRAW_BUFFER0_NV"/>
+                <enum name="GL_DRAW_BUFFER1_NV"/>
+                <enum name="GL_DRAW_BUFFER2_NV"/>
+                <enum name="GL_DRAW_BUFFER3_NV"/>
+                <enum name="GL_DRAW_BUFFER4_NV"/>
+                <enum name="GL_DRAW_BUFFER5_NV"/>
+                <enum name="GL_DRAW_BUFFER6_NV"/>
+                <enum name="GL_DRAW_BUFFER7_NV"/>
+                <enum name="GL_DRAW_BUFFER8_NV"/>
+                <enum name="GL_DRAW_BUFFER9_NV"/>
+                <enum name="GL_DRAW_BUFFER10_NV"/>
+                <enum name="GL_DRAW_BUFFER11_NV"/>
+                <enum name="GL_DRAW_BUFFER12_NV"/>
+                <enum name="GL_DRAW_BUFFER13_NV"/>
+                <enum name="GL_DRAW_BUFFER14_NV"/>
+                <enum name="GL_DRAW_BUFFER15_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT0_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT1_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT2_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT3_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT4_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT5_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT6_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT7_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT8_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT9_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT10_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT11_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT12_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT13_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT14_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT15_NV"/>
+                <command name="glDrawBuffersNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_draw_instanced" supported="gles2">
+            <require>
+                <command name="glDrawArraysInstancedNV"/>
+                <command name="glDrawElementsInstancedNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_draw_texture" supported="gl">
+            <require>
+                <command name="glDrawTextureNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_evaluators" supported="gl">
+            <require>
+                <enum name="GL_EVAL_2D_NV"/>
+                <enum name="GL_EVAL_TRIANGULAR_2D_NV"/>
+                <enum name="GL_MAP_TESSELLATION_NV"/>
+                <enum name="GL_MAP_ATTRIB_U_ORDER_NV"/>
+                <enum name="GL_MAP_ATTRIB_V_ORDER_NV"/>
+                <enum name="GL_EVAL_FRACTIONAL_TESSELLATION_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB0_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB1_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB2_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB3_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB4_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB5_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB6_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB7_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB8_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB9_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB10_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB11_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB12_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB13_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB14_NV"/>
+                <enum name="GL_EVAL_VERTEX_ATTRIB15_NV"/>
+                <enum name="GL_MAX_MAP_TESSELLATION_NV"/>
+                <enum name="GL_MAX_RATIONAL_EVAL_ORDER_NV"/>
+                <command name="glMapControlPointsNV"/>
+                <command name="glMapParameterivNV"/>
+                <command name="glMapParameterfvNV"/>
+                <command name="glGetMapControlPointsNV"/>
+                <command name="glGetMapParameterivNV"/>
+                <command name="glGetMapParameterfvNV"/>
+                <command name="glGetMapAttribParameterivNV"/>
+                <command name="glGetMapAttribParameterfvNV"/>
+                <command name="glEvalMapsNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_explicit_attrib_location" supported="gles2"/>
+        <extension name="GL_NV_explicit_multisample" supported="gl">
+            <require>
+                <enum name="GL_SAMPLE_POSITION_NV"/>
+                <enum name="GL_SAMPLE_MASK_NV"/>
+                <enum name="GL_SAMPLE_MASK_VALUE_NV"/>
+                <enum name="GL_TEXTURE_BINDING_RENDERBUFFER_NV"/>
+                <enum name="GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV"/>
+                <enum name="GL_TEXTURE_RENDERBUFFER_NV"/>
+                <enum name="GL_SAMPLER_RENDERBUFFER_NV"/>
+                <enum name="GL_INT_SAMPLER_RENDERBUFFER_NV"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV"/>
+                <enum name="GL_MAX_SAMPLE_MASK_WORDS_NV"/>
+                <command name="glGetMultisamplefvNV"/>
+                <command name="glSampleMaskIndexedNV"/>
+                <command name="glTexRenderbufferNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_fbo_color_attachments" supported="gles2">
+            <require>
+                <enum name="GL_MAX_COLOR_ATTACHMENTS_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT0_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT1_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT2_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT3_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT4_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT5_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT6_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT7_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT8_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT9_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT10_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT11_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT12_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT13_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT14_NV"/>
+                <enum name="GL_COLOR_ATTACHMENT15_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_fence" supported="gl|gles1|gles2">
+            <require>
+                <enum name="GL_ALL_COMPLETED_NV"/>
+                <enum name="GL_FENCE_STATUS_NV"/>
+                <enum name="GL_FENCE_CONDITION_NV"/>
+                <command name="glDeleteFencesNV"/>
+                <command name="glGenFencesNV"/>
+                <command name="glIsFenceNV"/>
+                <command name="glTestFenceNV"/>
+                <command name="glGetFenceivNV"/>
+                <command name="glFinishFenceNV"/>
+                <command name="glSetFenceNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_fill_rectangle" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_FILL_RECTANGLE_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_float_buffer" supported="gl">
+            <require>
+                <enum name="GL_FLOAT_R_NV"/>
+                <enum name="GL_FLOAT_RG_NV"/>
+                <enum name="GL_FLOAT_RGB_NV"/>
+                <enum name="GL_FLOAT_RGBA_NV"/>
+                <enum name="GL_FLOAT_R16_NV"/>
+                <enum name="GL_FLOAT_R32_NV"/>
+                <enum name="GL_FLOAT_RG16_NV"/>
+                <enum name="GL_FLOAT_RG32_NV"/>
+                <enum name="GL_FLOAT_RGB16_NV"/>
+                <enum name="GL_FLOAT_RGB32_NV"/>
+                <enum name="GL_FLOAT_RGBA16_NV"/>
+                <enum name="GL_FLOAT_RGBA32_NV"/>
+                <enum name="GL_TEXTURE_FLOAT_COMPONENTS_NV"/>
+                <enum name="GL_FLOAT_CLEAR_COLOR_VALUE_NV"/>
+                <enum name="GL_FLOAT_RGBA_MODE_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_fog_distance" supported="gl">
+            <require>
+                <enum name="GL_FOG_DISTANCE_MODE_NV"/>
+                <enum name="GL_EYE_RADIAL_NV"/>
+                <enum name="GL_EYE_PLANE_ABSOLUTE_NV"/>
+                <enum name="GL_EYE_PLANE"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_fragment_coverage_to_color" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_FRAGMENT_COVERAGE_TO_COLOR_NV"/>
+                <enum name="GL_FRAGMENT_COVERAGE_COLOR_NV"/>
+                <command name="glFragmentCoverageColorNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_fragment_program" supported="gl">
+            <require>
+                <enum name="GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV"/>
+                <enum name="GL_FRAGMENT_PROGRAM_NV"/>
+                <enum name="GL_MAX_TEXTURE_COORDS_NV"/>
+                <enum name="GL_MAX_TEXTURE_IMAGE_UNITS_NV"/>
+                <enum name="GL_FRAGMENT_PROGRAM_BINDING_NV"/>
+                <enum name="GL_PROGRAM_ERROR_STRING_NV"/>
+            </require>
+            <require comment="Some NV_fragment_program entry points are shared with ARB_vertex_program">
+                <command name="glProgramNamedParameter4fNV"/>
+                <command name="glProgramNamedParameter4fvNV"/>
+                <command name="glProgramNamedParameter4dNV"/>
+                <command name="glProgramNamedParameter4dvNV"/>
+                <command name="glGetProgramNamedParameterfvNV"/>
+                <command name="glGetProgramNamedParameterdvNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_fragment_program2" supported="gl">
+            <require>
+                <enum name="GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV"/>
+                <enum name="GL_MAX_PROGRAM_CALL_DEPTH_NV"/>
+                <enum name="GL_MAX_PROGRAM_IF_DEPTH_NV"/>
+                <enum name="GL_MAX_PROGRAM_LOOP_DEPTH_NV"/>
+                <enum name="GL_MAX_PROGRAM_LOOP_COUNT_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_fragment_program4" supported="gl"/>
+        <extension name="GL_NV_fragment_program_option" supported="gl"/>
+        <extension name="GL_NV_fragment_shader_interlock" supported="gl|glcore|gles2"/>
+        <extension name="GL_NV_framebuffer_blit" supported="gles2">
+            <require>
+                <enum name="GL_READ_FRAMEBUFFER_NV"/>
+                <enum name="GL_DRAW_FRAMEBUFFER_NV"/>
+                <enum name="GL_DRAW_FRAMEBUFFER_BINDING_NV"/>
+                <enum name="GL_READ_FRAMEBUFFER_BINDING_NV"/>
+                <command name="glBlitFramebufferNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_framebuffer_mixed_samples" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_RASTER_MULTISAMPLE_EXT"/>
+                <enum name="GL_COVERAGE_MODULATION_TABLE_NV"/>
+                <enum name="GL_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_MAX_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT"/>
+                <enum name="GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT"/>
+                <enum name="GL_EFFECTIVE_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_COLOR_SAMPLES_NV"/>
+                <enum name="GL_DEPTH_SAMPLES_NV"/>
+                <enum name="GL_STENCIL_SAMPLES_NV"/>
+                <enum name="GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV"/>
+                <enum name="GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV"/>
+                <enum name="GL_COVERAGE_MODULATION_NV"/>
+                <enum name="GL_COVERAGE_MODULATION_TABLE_SIZE_NV"/>
+                <command name="glRasterSamplesEXT"/>
+                <command name="glCoverageModulationTableNV"/>
+                <command name="glGetCoverageModulationTableNV"/>
+                <command name="glCoverageModulationNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_framebuffer_multisample" supported="gles2">
+            <require>
+                <enum name="GL_RENDERBUFFER_SAMPLES_NV"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV"/>
+                <enum name="GL_MAX_SAMPLES_NV"/>
+                <command name="glRenderbufferStorageMultisampleNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_framebuffer_multisample_coverage" supported="gl">
+            <require>
+                <enum name="GL_RENDERBUFFER_COVERAGE_SAMPLES_NV"/>
+                <enum name="GL_RENDERBUFFER_COLOR_SAMPLES_NV"/>
+                <enum name="GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV"/>
+                <enum name="GL_MULTISAMPLE_COVERAGE_MODES_NV"/>
+                <command name="glRenderbufferStorageMultisampleCoverageNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_generate_mipmap_sRGB" supported="gles2"/>
+        <extension name="GL_NV_geometry_program4" supported="gl">
+            <require>
+                <enum name="GL_LINES_ADJACENCY_EXT"/>
+                <enum name="GL_LINE_STRIP_ADJACENCY_EXT"/>
+                <enum name="GL_TRIANGLES_ADJACENCY_EXT"/>
+                <enum name="GL_TRIANGLE_STRIP_ADJACENCY_EXT"/>
+                <enum name="GL_GEOMETRY_PROGRAM_NV"/>
+                <enum name="GL_MAX_PROGRAM_OUTPUT_VERTICES_NV"/>
+                <enum name="GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV"/>
+                <enum name="GL_GEOMETRY_VERTICES_OUT_EXT"/>
+                <enum name="GL_GEOMETRY_INPUT_TYPE_EXT"/>
+                <enum name="GL_GEOMETRY_OUTPUT_TYPE_EXT"/>
+                <enum name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT"/>
+                <enum name="GL_PROGRAM_POINT_SIZE_EXT"/>
+                <command name="glProgramVertexLimitNV"/>
+                <command name="glFramebufferTextureEXT"/>
+                <command name="glFramebufferTextureLayerEXT"/>
+                <command name="glFramebufferTextureFaceEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_geometry_shader4" supported="gl"/>
+        <extension name="GL_NV_geometry_shader_passthrough" supported="gl|glcore|gles2"/>
+        <extension name="GL_NV_gpu_program4" supported="gl">
+            <require>
+                <enum name="GL_MIN_PROGRAM_TEXEL_OFFSET_NV"/>
+                <enum name="GL_MAX_PROGRAM_TEXEL_OFFSET_NV"/>
+                <enum name="GL_PROGRAM_ATTRIB_COMPONENTS_NV"/>
+                <enum name="GL_PROGRAM_RESULT_COMPONENTS_NV"/>
+                <enum name="GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV"/>
+                <enum name="GL_MAX_PROGRAM_RESULT_COMPONENTS_NV"/>
+                <enum name="GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV"/>
+                <enum name="GL_MAX_PROGRAM_GENERIC_RESULTS_NV"/>
+                <command name="glProgramLocalParameterI4iNV"/>
+                <command name="glProgramLocalParameterI4ivNV"/>
+                <command name="glProgramLocalParametersI4ivNV"/>
+                <command name="glProgramLocalParameterI4uiNV"/>
+                <command name="glProgramLocalParameterI4uivNV"/>
+                <command name="glProgramLocalParametersI4uivNV"/>
+                <command name="glProgramEnvParameterI4iNV"/>
+                <command name="glProgramEnvParameterI4ivNV"/>
+                <command name="glProgramEnvParametersI4ivNV"/>
+                <command name="glProgramEnvParameterI4uiNV"/>
+                <command name="glProgramEnvParameterI4uivNV"/>
+                <command name="glProgramEnvParametersI4uivNV"/>
+                <command name="glGetProgramLocalParameterIivNV"/>
+                <command name="glGetProgramLocalParameterIuivNV"/>
+                <command name="glGetProgramEnvParameterIivNV"/>
+                <command name="glGetProgramEnvParameterIuivNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_gpu_program5" supported="gl">
+            <require>
+                <enum name="GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV"/>
+                <enum name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV"/>
+                <enum name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV"/>
+                <enum name="GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV"/>
+                <enum name="GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV"/>
+                <enum name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV"/>
+                <enum name="GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV"/>
+                <enum name="GL_MAX_PROGRAM_SUBROUTINE_NUM_NV"/>
+                <command name="glProgramSubroutineParametersuivNV"/>
+                <command name="glGetProgramSubroutineParameteruivNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_gpu_program5_mem_extended" supported="gl"/>
+        <extension name="GL_NV_gpu_shader5" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_INT64_NV"/>
+                <enum name="GL_UNSIGNED_INT64_NV"/>
+                <enum name="GL_INT8_NV"/>
+                <enum name="GL_INT8_VEC2_NV"/>
+                <enum name="GL_INT8_VEC3_NV"/>
+                <enum name="GL_INT8_VEC4_NV"/>
+                <enum name="GL_INT16_NV"/>
+                <enum name="GL_INT16_VEC2_NV"/>
+                <enum name="GL_INT16_VEC3_NV"/>
+                <enum name="GL_INT16_VEC4_NV"/>
+                <enum name="GL_INT64_VEC2_NV"/>
+                <enum name="GL_INT64_VEC3_NV"/>
+                <enum name="GL_INT64_VEC4_NV"/>
+                <enum name="GL_UNSIGNED_INT8_NV"/>
+                <enum name="GL_UNSIGNED_INT8_VEC2_NV"/>
+                <enum name="GL_UNSIGNED_INT8_VEC3_NV"/>
+                <enum name="GL_UNSIGNED_INT8_VEC4_NV"/>
+                <enum name="GL_UNSIGNED_INT16_NV"/>
+                <enum name="GL_UNSIGNED_INT16_VEC2_NV"/>
+                <enum name="GL_UNSIGNED_INT16_VEC3_NV"/>
+                <enum name="GL_UNSIGNED_INT16_VEC4_NV"/>
+                <enum name="GL_UNSIGNED_INT64_VEC2_NV"/>
+                <enum name="GL_UNSIGNED_INT64_VEC3_NV"/>
+                <enum name="GL_UNSIGNED_INT64_VEC4_NV"/>
+                <enum name="GL_FLOAT16_NV"/>
+                <enum name="GL_FLOAT16_VEC2_NV"/>
+                <enum name="GL_FLOAT16_VEC3_NV"/>
+                <enum name="GL_FLOAT16_VEC4_NV"/>
+                <enum name="GL_PATCHES"/>
+                <command name="glUniform1i64NV"/>
+                <command name="glUniform2i64NV"/>
+                <command name="glUniform3i64NV"/>
+                <command name="glUniform4i64NV"/>
+                <command name="glUniform1i64vNV"/>
+                <command name="glUniform2i64vNV"/>
+                <command name="glUniform3i64vNV"/>
+                <command name="glUniform4i64vNV"/>
+                <command name="glUniform1ui64NV"/>
+                <command name="glUniform2ui64NV"/>
+                <command name="glUniform3ui64NV"/>
+                <command name="glUniform4ui64NV"/>
+                <command name="glUniform1ui64vNV"/>
+                <command name="glUniform2ui64vNV"/>
+                <command name="glUniform3ui64vNV"/>
+                <command name="glUniform4ui64vNV"/>
+                <command name="glGetUniformi64vNV"/>
+            </require>
+            <require comment="Supported only if GL_EXT_direct_state_access is supported">
+                <command name="glProgramUniform1i64NV"/>
+                <command name="glProgramUniform2i64NV"/>
+                <command name="glProgramUniform3i64NV"/>
+                <command name="glProgramUniform4i64NV"/>
+                <command name="glProgramUniform1i64vNV"/>
+                <command name="glProgramUniform2i64vNV"/>
+                <command name="glProgramUniform3i64vNV"/>
+                <command name="glProgramUniform4i64vNV"/>
+                <command name="glProgramUniform1ui64NV"/>
+                <command name="glProgramUniform2ui64NV"/>
+                <command name="glProgramUniform3ui64NV"/>
+                <command name="glProgramUniform4ui64NV"/>
+                <command name="glProgramUniform1ui64vNV"/>
+                <command name="glProgramUniform2ui64vNV"/>
+                <command name="glProgramUniform3ui64vNV"/>
+                <command name="glProgramUniform4ui64vNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_half_float" supported="gl">
+            <require>
+                <enum name="GL_HALF_FLOAT_NV"/>
+                <command name="glVertex2hNV"/>
+                <command name="glVertex2hvNV"/>
+                <command name="glVertex3hNV"/>
+                <command name="glVertex3hvNV"/>
+                <command name="glVertex4hNV"/>
+                <command name="glVertex4hvNV"/>
+                <command name="glNormal3hNV"/>
+                <command name="glNormal3hvNV"/>
+                <command name="glColor3hNV"/>
+                <command name="glColor3hvNV"/>
+                <command name="glColor4hNV"/>
+                <command name="glColor4hvNV"/>
+                <command name="glTexCoord1hNV"/>
+                <command name="glTexCoord1hvNV"/>
+                <command name="glTexCoord2hNV"/>
+                <command name="glTexCoord2hvNV"/>
+                <command name="glTexCoord3hNV"/>
+                <command name="glTexCoord3hvNV"/>
+                <command name="glTexCoord4hNV"/>
+                <command name="glTexCoord4hvNV"/>
+                <command name="glMultiTexCoord1hNV"/>
+                <command name="glMultiTexCoord1hvNV"/>
+                <command name="glMultiTexCoord2hNV"/>
+                <command name="glMultiTexCoord2hvNV"/>
+                <command name="glMultiTexCoord3hNV"/>
+                <command name="glMultiTexCoord3hvNV"/>
+                <command name="glMultiTexCoord4hNV"/>
+                <command name="glMultiTexCoord4hvNV"/>
+                <command name="glFogCoordhNV"/>
+                <command name="glFogCoordhvNV"/>
+                <command name="glSecondaryColor3hNV"/>
+                <command name="glSecondaryColor3hvNV"/>
+                <command name="glVertexWeighthNV"/>
+                <command name="glVertexWeighthvNV"/>
+                <command name="glVertexAttrib1hNV"/>
+                <command name="glVertexAttrib1hvNV"/>
+                <command name="glVertexAttrib2hNV"/>
+                <command name="glVertexAttrib2hvNV"/>
+                <command name="glVertexAttrib3hNV"/>
+                <command name="glVertexAttrib3hvNV"/>
+                <command name="glVertexAttrib4hNV"/>
+                <command name="glVertexAttrib4hvNV"/>
+                <command name="glVertexAttribs1hvNV"/>
+                <command name="glVertexAttribs2hvNV"/>
+                <command name="glVertexAttribs3hvNV"/>
+                <command name="glVertexAttribs4hvNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_image_formats" supported="gles2"/>
+        <extension name="GL_NV_instanced_arrays" supported="gles2">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV"/>
+                <command name="glVertexAttribDivisorNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_internalformat_sample_query" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_RENDERBUFFER"/>
+                <enum name="GL_TEXTURE_2D_MULTISAMPLE"/>
+                <enum name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_MULTISAMPLES_NV"/>
+                <enum name="GL_SUPERSAMPLE_SCALE_X_NV"/>
+                <enum name="GL_SUPERSAMPLE_SCALE_Y_NV"/>
+                <enum name="GL_CONFORMANT_NV"/>
+                <command name="glGetInternalformatSampleivNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_light_max_exponent" supported="gl">
+            <require>
+                <enum name="GL_MAX_SHININESS_NV"/>
+                <enum name="GL_MAX_SPOT_EXPONENT_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_multisample_coverage" supported="gl">
+            <require>
+                <enum name="GL_SAMPLES_ARB"/>
+                <enum name="GL_COLOR_SAMPLES_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_multisample_filter_hint" supported="gl">
+            <require>
+                <enum name="GL_MULTISAMPLE_FILTER_HINT_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_non_square_matrices" supported="gles2">
+            <require>
+                <enum name="GL_FLOAT_MAT2x3_NV"/>
+                <enum name="GL_FLOAT_MAT2x4_NV"/>
+                <enum name="GL_FLOAT_MAT3x2_NV"/>
+                <enum name="GL_FLOAT_MAT3x4_NV"/>
+                <enum name="GL_FLOAT_MAT4x2_NV"/>
+                <enum name="GL_FLOAT_MAT4x3_NV"/>
+                <command name="glUniformMatrix2x3fvNV"/>
+                <command name="glUniformMatrix3x2fvNV"/>
+                <command name="glUniformMatrix2x4fvNV"/>
+                <command name="glUniformMatrix4x2fvNV"/>
+                <command name="glUniformMatrix3x4fvNV"/>
+                <command name="glUniformMatrix4x3fvNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_occlusion_query" supported="gl">
+            <require>
+                <enum name="GL_PIXEL_COUNTER_BITS_NV"/>
+                <enum name="GL_CURRENT_OCCLUSION_QUERY_ID_NV"/>
+                <enum name="GL_PIXEL_COUNT_NV"/>
+                <enum name="GL_PIXEL_COUNT_AVAILABLE_NV"/>
+                <command name="glGenOcclusionQueriesNV"/>
+                <command name="glDeleteOcclusionQueriesNV"/>
+                <command name="glIsOcclusionQueryNV"/>
+                <command name="glBeginOcclusionQueryNV"/>
+                <command name="glEndOcclusionQueryNV"/>
+                <command name="glGetOcclusionQueryivNV"/>
+                <command name="glGetOcclusionQueryuivNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_packed_depth_stencil" supported="gl">
+            <require>
+                <enum name="GL_DEPTH_STENCIL_NV"/>
+                <enum name="GL_UNSIGNED_INT_24_8_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_parameter_buffer_object" supported="gl">
+            <require>
+                <enum name="GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV"/>
+                <enum name="GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV"/>
+                <enum name="GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV"/>
+                <enum name="GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV"/>
+                <enum name="GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV"/>
+                <command name="glProgramBufferParametersfvNV"/>
+                <command name="glProgramBufferParametersIivNV"/>
+                <command name="glProgramBufferParametersIuivNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_parameter_buffer_object2" supported="gl"/>
+        <extension name="GL_NV_path_rendering" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_PATH_FORMAT_SVG_NV"/>
+                <enum name="GL_PATH_FORMAT_PS_NV"/>
+                <enum name="GL_STANDARD_FONT_NAME_NV"/>
+                <enum name="GL_SYSTEM_FONT_NAME_NV"/>
+                <enum name="GL_FILE_NAME_NV"/>
+                <enum name="GL_PATH_STROKE_WIDTH_NV"/>
+                <enum name="GL_PATH_END_CAPS_NV"/>
+                <enum name="GL_PATH_INITIAL_END_CAP_NV"/>
+                <enum name="GL_PATH_TERMINAL_END_CAP_NV"/>
+                <enum name="GL_PATH_JOIN_STYLE_NV"/>
+                <enum name="GL_PATH_MITER_LIMIT_NV"/>
+                <enum name="GL_PATH_DASH_CAPS_NV"/>
+                <enum name="GL_PATH_INITIAL_DASH_CAP_NV"/>
+                <enum name="GL_PATH_TERMINAL_DASH_CAP_NV"/>
+                <enum name="GL_PATH_DASH_OFFSET_NV"/>
+                <enum name="GL_PATH_CLIENT_LENGTH_NV"/>
+                <enum name="GL_PATH_FILL_MODE_NV"/>
+                <enum name="GL_PATH_FILL_MASK_NV"/>
+                <enum name="GL_PATH_FILL_COVER_MODE_NV"/>
+                <enum name="GL_PATH_STROKE_COVER_MODE_NV"/>
+                <enum name="GL_PATH_STROKE_MASK_NV"/>
+                <enum name="GL_COUNT_UP_NV"/>
+                <enum name="GL_COUNT_DOWN_NV"/>
+                <enum name="GL_PATH_OBJECT_BOUNDING_BOX_NV"/>
+                <enum name="GL_CONVEX_HULL_NV"/>
+                <enum name="GL_BOUNDING_BOX_NV"/>
+                <enum name="GL_TRANSLATE_X_NV"/>
+                <enum name="GL_TRANSLATE_Y_NV"/>
+                <enum name="GL_TRANSLATE_2D_NV"/>
+                <enum name="GL_TRANSLATE_3D_NV"/>
+                <enum name="GL_AFFINE_2D_NV"/>
+                <enum name="GL_AFFINE_3D_NV"/>
+                <enum name="GL_TRANSPOSE_AFFINE_2D_NV"/>
+                <enum name="GL_TRANSPOSE_AFFINE_3D_NV"/>
+                <enum name="GL_UTF8_NV"/>
+                <enum name="GL_UTF16_NV"/>
+                <enum name="GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV"/>
+                <enum name="GL_PATH_COMMAND_COUNT_NV"/>
+                <enum name="GL_PATH_COORD_COUNT_NV"/>
+                <enum name="GL_PATH_DASH_ARRAY_COUNT_NV"/>
+                <enum name="GL_PATH_COMPUTED_LENGTH_NV"/>
+                <enum name="GL_PATH_FILL_BOUNDING_BOX_NV"/>
+                <enum name="GL_PATH_STROKE_BOUNDING_BOX_NV"/>
+                <enum name="GL_SQUARE_NV"/>
+                <enum name="GL_ROUND_NV"/>
+                <enum name="GL_TRIANGULAR_NV"/>
+                <enum name="GL_BEVEL_NV"/>
+                <enum name="GL_MITER_REVERT_NV"/>
+                <enum name="GL_MITER_TRUNCATE_NV"/>
+                <enum name="GL_SKIP_MISSING_GLYPH_NV"/>
+                <enum name="GL_USE_MISSING_GLYPH_NV"/>
+                <enum name="GL_PATH_ERROR_POSITION_NV"/>
+                <enum name="GL_ACCUM_ADJACENT_PAIRS_NV"/>
+                <enum name="GL_ADJACENT_PAIRS_NV"/>
+                <enum name="GL_FIRST_TO_REST_NV"/>
+                <enum name="GL_PATH_GEN_MODE_NV"/>
+                <enum name="GL_PATH_GEN_COEFF_NV"/>
+                <enum name="GL_PATH_GEN_COMPONENTS_NV"/>
+                <enum name="GL_PATH_STENCIL_FUNC_NV"/>
+                <enum name="GL_PATH_STENCIL_REF_NV"/>
+                <enum name="GL_PATH_STENCIL_VALUE_MASK_NV"/>
+                <enum name="GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV"/>
+                <enum name="GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV"/>
+                <enum name="GL_PATH_COVER_DEPTH_FUNC_NV"/>
+                <enum name="GL_PATH_DASH_OFFSET_RESET_NV"/>
+                <enum name="GL_MOVE_TO_RESETS_NV"/>
+                <enum name="GL_MOVE_TO_CONTINUES_NV"/>
+                <enum name="GL_CLOSE_PATH_NV"/>
+                <enum name="GL_MOVE_TO_NV"/>
+                <enum name="GL_RELATIVE_MOVE_TO_NV"/>
+                <enum name="GL_LINE_TO_NV"/>
+                <enum name="GL_RELATIVE_LINE_TO_NV"/>
+                <enum name="GL_HORIZONTAL_LINE_TO_NV"/>
+                <enum name="GL_RELATIVE_HORIZONTAL_LINE_TO_NV"/>
+                <enum name="GL_VERTICAL_LINE_TO_NV"/>
+                <enum name="GL_RELATIVE_VERTICAL_LINE_TO_NV"/>
+                <enum name="GL_QUADRATIC_CURVE_TO_NV"/>
+                <enum name="GL_RELATIVE_QUADRATIC_CURVE_TO_NV"/>
+                <enum name="GL_CUBIC_CURVE_TO_NV"/>
+                <enum name="GL_RELATIVE_CUBIC_CURVE_TO_NV"/>
+                <enum name="GL_SMOOTH_QUADRATIC_CURVE_TO_NV"/>
+                <enum name="GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV"/>
+                <enum name="GL_SMOOTH_CUBIC_CURVE_TO_NV"/>
+                <enum name="GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV"/>
+                <enum name="GL_SMALL_CCW_ARC_TO_NV"/>
+                <enum name="GL_RELATIVE_SMALL_CCW_ARC_TO_NV"/>
+                <enum name="GL_SMALL_CW_ARC_TO_NV"/>
+                <enum name="GL_RELATIVE_SMALL_CW_ARC_TO_NV"/>
+                <enum name="GL_LARGE_CCW_ARC_TO_NV"/>
+                <enum name="GL_RELATIVE_LARGE_CCW_ARC_TO_NV"/>
+                <enum name="GL_LARGE_CW_ARC_TO_NV"/>
+                <enum name="GL_RELATIVE_LARGE_CW_ARC_TO_NV"/>
+                <enum name="GL_RESTART_PATH_NV"/>
+                <enum name="GL_DUP_FIRST_CUBIC_CURVE_TO_NV"/>
+                <enum name="GL_DUP_LAST_CUBIC_CURVE_TO_NV"/>
+                <enum name="GL_RECT_NV"/>
+                <enum name="GL_CIRCULAR_CCW_ARC_TO_NV"/>
+                <enum name="GL_CIRCULAR_CW_ARC_TO_NV"/>
+                <enum name="GL_CIRCULAR_TANGENT_ARC_TO_NV"/>
+                <enum name="GL_ARC_TO_NV"/>
+                <enum name="GL_RELATIVE_ARC_TO_NV"/>
+                <enum name="GL_BOLD_BIT_NV"/>
+                <enum name="GL_ITALIC_BIT_NV"/>
+                <enum name="GL_GLYPH_WIDTH_BIT_NV"/>
+                <enum name="GL_GLYPH_HEIGHT_BIT_NV"/>
+                <enum name="GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV"/>
+                <enum name="GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV"/>
+                <enum name="GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV"/>
+                <enum name="GL_GLYPH_VERTICAL_BEARING_X_BIT_NV"/>
+                <enum name="GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV"/>
+                <enum name="GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV"/>
+                <enum name="GL_GLYPH_HAS_KERNING_BIT_NV"/>
+                <enum name="GL_FONT_X_MIN_BOUNDS_BIT_NV"/>
+                <enum name="GL_FONT_Y_MIN_BOUNDS_BIT_NV"/>
+                <enum name="GL_FONT_X_MAX_BOUNDS_BIT_NV"/>
+                <enum name="GL_FONT_Y_MAX_BOUNDS_BIT_NV"/>
+                <enum name="GL_FONT_UNITS_PER_EM_BIT_NV"/>
+                <enum name="GL_FONT_ASCENDER_BIT_NV"/>
+                <enum name="GL_FONT_DESCENDER_BIT_NV"/>
+                <enum name="GL_FONT_HEIGHT_BIT_NV"/>
+                <enum name="GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV"/>
+                <enum name="GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV"/>
+                <enum name="GL_FONT_UNDERLINE_POSITION_BIT_NV"/>
+                <enum name="GL_FONT_UNDERLINE_THICKNESS_BIT_NV"/>
+                <enum name="GL_FONT_HAS_KERNING_BIT_NV"/>
+                <command name="glGenPathsNV"/>
+                <command name="glDeletePathsNV"/>
+                <command name="glIsPathNV"/>
+                <command name="glPathCommandsNV"/>
+                <command name="glPathCoordsNV"/>
+                <command name="glPathSubCommandsNV"/>
+                <command name="glPathSubCoordsNV"/>
+                <command name="glPathStringNV"/>
+                <command name="glPathGlyphsNV"/>
+                <command name="glPathGlyphRangeNV"/>
+                <command name="glWeightPathsNV"/>
+                <command name="glCopyPathNV"/>
+                <command name="glInterpolatePathsNV"/>
+                <command name="glTransformPathNV"/>
+                <command name="glPathParameterivNV"/>
+                <command name="glPathParameteriNV"/>
+                <command name="glPathParameterfvNV"/>
+                <command name="glPathParameterfNV"/>
+                <command name="glPathDashArrayNV"/>
+                <command name="glPathStencilFuncNV"/>
+                <command name="glPathStencilDepthOffsetNV"/>
+                <command name="glStencilFillPathNV"/>
+                <command name="glStencilStrokePathNV"/>
+                <command name="glStencilFillPathInstancedNV"/>
+                <command name="glStencilStrokePathInstancedNV"/>
+                <command name="glPathCoverDepthFuncNV"/>
+                <command name="glCoverFillPathNV"/>
+                <command name="glCoverStrokePathNV"/>
+                <command name="glCoverFillPathInstancedNV"/>
+                <command name="glCoverStrokePathInstancedNV"/>
+                <command name="glGetPathParameterivNV"/>
+                <command name="glGetPathParameterfvNV"/>
+                <command name="glGetPathCommandsNV"/>
+                <command name="glGetPathCoordsNV"/>
+                <command name="glGetPathDashArrayNV"/>
+                <command name="glGetPathMetricsNV"/>
+                <command name="glGetPathMetricRangeNV"/>
+                <command name="glGetPathSpacingNV"/>
+                <command name="glIsPointInFillPathNV"/>
+                <command name="glIsPointInStrokePathNV"/>
+                <command name="glGetPathLengthNV"/>
+                <command name="glPointAlongPathNV"/>
+            </require>
+            <require comment="API revision 1.2">
+                <enum name="GL_ROUNDED_RECT_NV"/>
+                <enum name="GL_RELATIVE_ROUNDED_RECT_NV"/>
+                <enum name="GL_ROUNDED_RECT2_NV"/>
+                <enum name="GL_RELATIVE_ROUNDED_RECT2_NV"/>
+                <enum name="GL_ROUNDED_RECT4_NV"/>
+                <enum name="GL_RELATIVE_ROUNDED_RECT4_NV"/>
+                <enum name="GL_ROUNDED_RECT8_NV"/>
+                <enum name="GL_RELATIVE_ROUNDED_RECT8_NV"/>
+                <enum name="GL_RELATIVE_RECT_NV"/>
+                <enum name="GL_FONT_GLYPHS_AVAILABLE_NV"/>
+                <enum name="GL_FONT_TARGET_UNAVAILABLE_NV"/>
+                <enum name="GL_FONT_UNAVAILABLE_NV"/>
+                <enum name="GL_FONT_UNINTELLIGIBLE_NV"/>
+                <command name="glMatrixLoad3x2fNV"/>
+                <command name="glMatrixLoad3x3fNV"/>
+                <command name="glMatrixLoadTranspose3x3fNV"/>
+                <command name="glMatrixMult3x2fNV"/>
+                <command name="glMatrixMult3x3fNV"/>
+                <command name="glMatrixMultTranspose3x3fNV"/>
+                <command name="glStencilThenCoverFillPathNV"/>
+                <command name="glStencilThenCoverStrokePathNV"/>
+                <command name="glStencilThenCoverFillPathInstancedNV"/>
+                <command name="glStencilThenCoverStrokePathInstancedNV"/>
+                <command name="glPathGlyphIndexRangeNV"/>
+            </require>
+            <require comment="API revision 1.3">
+                <enum name="GL_CONIC_CURVE_TO_NV"/>
+                <enum name="GL_RELATIVE_CONIC_CURVE_TO_NV"/>
+                <enum name="GL_FONT_NUM_GLYPH_INDICES_BIT_NV"/>
+                <enum name="GL_STANDARD_FONT_FORMAT_NV"/>
+                <command name="glPathGlyphIndexArrayNV"/>
+                <command name="glPathMemoryGlyphIndexArrayNV"/>
+                <command name="glProgramPathFragmentInputGenNV"/>
+                <command name="glGetProgramResourcefvNV"/>
+            </require>
+            <require api="gl" profile="compatibility">
+                <enum name="GL_2_BYTES_NV"/>
+                <enum name="GL_3_BYTES_NV"/>
+                <enum name="GL_4_BYTES_NV"/>
+                <enum name="GL_EYE_LINEAR_NV"/>
+                <enum name="GL_OBJECT_LINEAR_NV"/>
+                <enum name="GL_CONSTANT_NV"/>
+                <enum name="GL_PATH_FOG_GEN_MODE_NV"/>
+                <enum name="GL_PRIMARY_COLOR"/>
+                <enum name="GL_PRIMARY_COLOR_NV"/>
+                <enum name="GL_SECONDARY_COLOR_NV"/>
+                <enum name="GL_PATH_GEN_COLOR_FORMAT_NV"/>
+                <command name="glPathColorGenNV"/>
+                <command name="glPathTexGenNV"/>
+                <command name="glPathFogGenNV"/>
+                <command name="glGetPathColorGenivNV"/>
+                <command name="glGetPathColorGenfvNV"/>
+                <command name="glGetPathTexGenivNV"/>
+                <command name="glGetPathTexGenfvNV"/>
+            </require>
+            <require comment="Other API additions of unknown history">
+                <enum name="GL_PATH_PROJECTION_NV"/>
+                <enum name="GL_PATH_MODELVIEW_NV"/>
+                <enum name="GL_PATH_MODELVIEW_STACK_DEPTH_NV"/>
+                <enum name="GL_PATH_MODELVIEW_MATRIX_NV"/>
+                <enum name="GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV"/>
+                <enum name="GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV"/>
+                <enum name="GL_PATH_PROJECTION_STACK_DEPTH_NV"/>
+                <enum name="GL_PATH_PROJECTION_MATRIX_NV"/>
+                <enum name="GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV"/>
+                <enum name="GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV"/>
+                <enum name="GL_FRAGMENT_INPUT_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_path_rendering_shared_edge" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_SHARED_EDGE_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_pixel_data_range" supported="gl">
+            <require>
+                <enum name="GL_WRITE_PIXEL_DATA_RANGE_NV"/>
+                <enum name="GL_READ_PIXEL_DATA_RANGE_NV"/>
+                <enum name="GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV"/>
+                <enum name="GL_READ_PIXEL_DATA_RANGE_LENGTH_NV"/>
+                <enum name="GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV"/>
+                <enum name="GL_READ_PIXEL_DATA_RANGE_POINTER_NV"/>
+                <command name="glPixelDataRangeNV"/>
+                <command name="glFlushPixelDataRangeNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_point_sprite" supported="gl">
+            <require>
+                <enum name="GL_POINT_SPRITE_NV"/>
+                <enum name="GL_COORD_REPLACE_NV"/>
+                <enum name="GL_POINT_SPRITE_R_MODE_NV"/>
+                <command name="glPointParameteriNV"/>
+                <command name="glPointParameterivNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_polygon_mode" supported="gles2">
+            <require>
+                <enum name="GL_POLYGON_MODE_NV"/>
+                <enum name="GL_POLYGON_OFFSET_POINT_NV"/>
+                <enum name="GL_POLYGON_OFFSET_LINE_NV"/>
+                <enum name="GL_POINT_NV"/>
+                <enum name="GL_LINE_NV"/>
+                <enum name="GL_FILL_NV"/>
+                <command name="glPolygonModeNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_present_video" supported="gl">
+            <require>
+                <enum name="GL_FRAME_NV"/>
+                <enum name="GL_FIELDS_NV"/>
+                <enum name="GL_CURRENT_TIME_NV"/>
+                <enum name="GL_NUM_FILL_STREAMS_NV"/>
+                <enum name="GL_PRESENT_TIME_NV"/>
+                <enum name="GL_PRESENT_DURATION_NV"/>
+                <command name="glPresentFrameKeyedNV"/>
+                <command name="glPresentFrameDualFillNV"/>
+                <command name="glGetVideoivNV"/>
+                <command name="glGetVideouivNV"/>
+                <command name="glGetVideoi64vNV"/>
+                <command name="glGetVideoui64vNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_primitive_restart" supported="gl">
+            <require>
+                <enum name="GL_PRIMITIVE_RESTART_NV"/>
+                <enum name="GL_PRIMITIVE_RESTART_INDEX_NV"/>
+                <command name="glPrimitiveRestartNV"/>
+                <command name="glPrimitiveRestartIndexNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_read_buffer" supported="gles2">
+            <require>
+                <enum name="GL_READ_BUFFER_NV"/>
+                <command name="glReadBufferNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_read_buffer_front" supported="gles2"/>
+        <extension name="GL_NV_read_depth" supported="gles2"/>
+        <extension name="GL_NV_read_depth_stencil" supported="gles2"/>
+        <extension name="GL_NV_read_stencil" supported="gles2"/>
+        <extension name="GL_NV_register_combiners" supported="gl">
+            <require>
+                <enum name="GL_REGISTER_COMBINERS_NV"/>
+                <enum name="GL_VARIABLE_A_NV"/>
+                <enum name="GL_VARIABLE_B_NV"/>
+                <enum name="GL_VARIABLE_C_NV"/>
+                <enum name="GL_VARIABLE_D_NV"/>
+                <enum name="GL_VARIABLE_E_NV"/>
+                <enum name="GL_VARIABLE_F_NV"/>
+                <enum name="GL_VARIABLE_G_NV"/>
+                <enum name="GL_CONSTANT_COLOR0_NV"/>
+                <enum name="GL_CONSTANT_COLOR1_NV"/>
+                <enum name="GL_PRIMARY_COLOR_NV"/>
+                <enum name="GL_SECONDARY_COLOR_NV"/>
+                <enum name="GL_SPARE0_NV"/>
+                <enum name="GL_SPARE1_NV"/>
+                <enum name="GL_DISCARD_NV"/>
+                <enum name="GL_E_TIMES_F_NV"/>
+                <enum name="GL_SPARE0_PLUS_SECONDARY_COLOR_NV"/>
+                <enum name="GL_UNSIGNED_IDENTITY_NV"/>
+                <enum name="GL_UNSIGNED_INVERT_NV"/>
+                <enum name="GL_EXPAND_NORMAL_NV"/>
+                <enum name="GL_EXPAND_NEGATE_NV"/>
+                <enum name="GL_HALF_BIAS_NORMAL_NV"/>
+                <enum name="GL_HALF_BIAS_NEGATE_NV"/>
+                <enum name="GL_SIGNED_IDENTITY_NV"/>
+                <enum name="GL_SIGNED_NEGATE_NV"/>
+                <enum name="GL_SCALE_BY_TWO_NV"/>
+                <enum name="GL_SCALE_BY_FOUR_NV"/>
+                <enum name="GL_SCALE_BY_ONE_HALF_NV"/>
+                <enum name="GL_BIAS_BY_NEGATIVE_ONE_HALF_NV"/>
+                <enum name="GL_COMBINER_INPUT_NV"/>
+                <enum name="GL_COMBINER_MAPPING_NV"/>
+                <enum name="GL_COMBINER_COMPONENT_USAGE_NV"/>
+                <enum name="GL_COMBINER_AB_DOT_PRODUCT_NV"/>
+                <enum name="GL_COMBINER_CD_DOT_PRODUCT_NV"/>
+                <enum name="GL_COMBINER_MUX_SUM_NV"/>
+                <enum name="GL_COMBINER_SCALE_NV"/>
+                <enum name="GL_COMBINER_BIAS_NV"/>
+                <enum name="GL_COMBINER_AB_OUTPUT_NV"/>
+                <enum name="GL_COMBINER_CD_OUTPUT_NV"/>
+                <enum name="GL_COMBINER_SUM_OUTPUT_NV"/>
+                <enum name="GL_MAX_GENERAL_COMBINERS_NV"/>
+                <enum name="GL_NUM_GENERAL_COMBINERS_NV"/>
+                <enum name="GL_COLOR_SUM_CLAMP_NV"/>
+                <enum name="GL_COMBINER0_NV"/>
+                <enum name="GL_COMBINER1_NV"/>
+                <enum name="GL_COMBINER2_NV"/>
+                <enum name="GL_COMBINER3_NV"/>
+                <enum name="GL_COMBINER4_NV"/>
+                <enum name="GL_COMBINER5_NV"/>
+                <enum name="GL_COMBINER6_NV"/>
+                <enum name="GL_COMBINER7_NV"/>
+                <enum name="GL_TEXTURE0_ARB"/>
+                <enum name="GL_TEXTURE1_ARB"/>
+                <enum name="GL_ZERO"/>
+                <enum name="GL_NONE"/>
+                <enum name="GL_FOG"/>
+                <command name="glCombinerParameterfvNV"/>
+                <command name="glCombinerParameterfNV"/>
+                <command name="glCombinerParameterivNV"/>
+                <command name="glCombinerParameteriNV"/>
+                <command name="glCombinerInputNV"/>
+                <command name="glCombinerOutputNV"/>
+                <command name="glFinalCombinerInputNV"/>
+                <command name="glGetCombinerInputParameterfvNV"/>
+                <command name="glGetCombinerInputParameterivNV"/>
+                <command name="glGetCombinerOutputParameterfvNV"/>
+                <command name="glGetCombinerOutputParameterivNV"/>
+                <command name="glGetFinalCombinerInputParameterfvNV"/>
+                <command name="glGetFinalCombinerInputParameterivNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_register_combiners2" supported="gl">
+            <require>
+                <enum name="GL_PER_STAGE_CONSTANTS_NV"/>
+                <command name="glCombinerStageParameterfvNV"/>
+                <command name="glGetCombinerStageParameterfvNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_robustness_video_memory_purge" supported="gl">
+            <require>
+                <enum name="GL_PURGED_CONTEXT_RESET_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_sRGB_formats" supported="gles2">
+            <require>
+                <enum name="GL_SLUMINANCE_NV"/>
+                <enum name="GL_SLUMINANCE_ALPHA_NV"/>
+                <enum name="GL_SRGB8_NV"/>
+                <enum name="GL_SLUMINANCE8_NV"/>
+                <enum name="GL_SLUMINANCE8_ALPHA8_NV"/>
+                <enum name="GL_COMPRESSED_SRGB_S3TC_DXT1_NV"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV"/>
+                <enum name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV"/>
+                <enum name="GL_ETC1_SRGB8_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_sample_locations" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV"/>
+                <enum name="GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV"/>
+                <enum name="GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV"/>
+                <enum name="GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV"/>
+                <enum name="GL_SAMPLE_LOCATION_NV"/>
+                <enum name="GL_PROGRAMMABLE_SAMPLE_LOCATION_NV"/>
+                <enum name="GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV"/>
+                <enum name="GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV"/>
+                <command name="glFramebufferSampleLocationsfvNV"/>
+                <command name="glNamedFramebufferSampleLocationsfvNV"/>
+                <command name="glResolveDepthValuesNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_sample_mask_override_coverage" supported="gl|glcore|gles2"/>
+        <extension name="GL_NV_shader_atomic_counters" supported="gl"/>
+        <extension name="GL_NV_shader_atomic_float" supported="gl"/>
+        <extension name="GL_NV_shader_atomic_float64" supported="gl"/>
+        <extension name="GL_NV_shader_atomic_fp16_vector" supported="gl|glcore|gles2"/>
+        <extension name="GL_NV_shader_atomic_int64" supported="gl"/>
+        <extension name="GL_NV_shader_buffer_load" supported="gl">
+            <require>
+                <enum name="GL_BUFFER_GPU_ADDRESS_NV"/>
+                <enum name="GL_GPU_ADDRESS_NV"/>
+                <enum name="GL_MAX_SHADER_BUFFER_ADDRESS_NV"/>
+                <command name="glMakeBufferResidentNV"/>
+                <command name="glMakeBufferNonResidentNV"/>
+                <command name="glIsBufferResidentNV"/>
+                <command name="glMakeNamedBufferResidentNV"/>
+                <command name="glMakeNamedBufferNonResidentNV"/>
+                <command name="glIsNamedBufferResidentNV"/>
+                <command name="glGetBufferParameterui64vNV"/>
+                <command name="glGetNamedBufferParameterui64vNV"/>
+                <command name="glGetIntegerui64vNV"/>
+                <command name="glUniformui64NV"/>
+                <command name="glUniformui64vNV"/>
+                <command name="glGetUniformui64vNV"/>
+                <command name="glProgramUniformui64NV"/>
+                <command name="glProgramUniformui64vNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_shader_buffer_store" supported="gl">
+            <require>
+                <enum name="GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV"/>
+                <enum name="GL_READ_WRITE"/>
+                <enum name="GL_WRITE_ONLY"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_shader_noperspective_interpolation" supported="gles2"/>
+        <extension name="GL_NV_shader_storage_buffer_object" supported="gl"/>
+        <extension name="GL_NV_shader_thread_group" supported="gl">
+            <require>
+                <enum name="GL_WARP_SIZE_NV"/>
+                <enum name="GL_WARPS_PER_SM_NV"/>
+                <enum name="GL_SM_COUNT_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_shader_thread_shuffle" supported="gl"/>
+        <extension name="GL_NV_shadow_samplers_array" supported="gles2">
+            <require>
+                <enum name="GL_SAMPLER_2D_ARRAY_SHADOW_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_shadow_samplers_cube" supported="gles2">
+            <require>
+                <enum name="GL_SAMPLER_CUBE_SHADOW_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_stereo_view_rendering" supported="gl"/>
+        <extension name="GL_NV_tessellation_program5" supported="gl">
+            <require>
+                <enum name="GL_MAX_PROGRAM_PATCH_ATTRIBS_NV"/>
+                <enum name="GL_TESS_CONTROL_PROGRAM_NV"/>
+                <enum name="GL_TESS_EVALUATION_PROGRAM_NV"/>
+                <enum name="GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV"/>
+                <enum name="GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texgen_emboss" supported="gl">
+            <require>
+                <enum name="GL_EMBOSS_LIGHT_NV"/>
+                <enum name="GL_EMBOSS_CONSTANT_NV"/>
+                <enum name="GL_EMBOSS_MAP_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texgen_reflection" supported="gl">
+            <require>
+                <enum name="GL_NORMAL_MAP_NV"/>
+                <enum name="GL_REFLECTION_MAP_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texture_barrier" supported="gl">
+            <require>
+                <command name="glTextureBarrierNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texture_border_clamp" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_BORDER_COLOR_NV"/>
+                <enum name="GL_CLAMP_TO_BORDER_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texture_compression_s3tc_update" supported="gles2"/>
+        <extension name="GL_NV_texture_compression_vtc" supported="gl"/>
+        <extension name="GL_NV_texture_env_combine4" supported="gl">
+            <require>
+                <enum name="GL_COMBINE4_NV"/>
+                <enum name="GL_SOURCE3_RGB_NV"/>
+                <enum name="GL_SOURCE3_ALPHA_NV"/>
+                <enum name="GL_OPERAND3_RGB_NV"/>
+                <enum name="GL_OPERAND3_ALPHA_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texture_expand_normal" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_UNSIGNED_REMAP_MODE_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texture_multisample" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_COVERAGE_SAMPLES_NV"/>
+                <enum name="GL_TEXTURE_COLOR_SAMPLES_NV"/>
+                <command name="glTexImage2DMultisampleCoverageNV"/>
+                <command name="glTexImage3DMultisampleCoverageNV"/>
+            </require>
+            <require comment="Supported only if GL_EXT_direct_state_access is supported">
+                <command name="glTextureImage2DMultisampleNV"/>
+                <command name="glTextureImage3DMultisampleNV"/>
+                <command name="glTextureImage2DMultisampleCoverageNV"/>
+                <command name="glTextureImage3DMultisampleCoverageNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texture_npot_2D_mipmap" supported="gles2"/>
+        <extension name="GL_NV_texture_rectangle" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_RECTANGLE_NV"/>
+                <enum name="GL_TEXTURE_BINDING_RECTANGLE_NV"/>
+                <enum name="GL_PROXY_TEXTURE_RECTANGLE_NV"/>
+                <enum name="GL_MAX_RECTANGLE_TEXTURE_SIZE_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texture_shader" supported="gl">
+            <require>
+                <enum name="GL_OFFSET_TEXTURE_RECTANGLE_NV"/>
+                <enum name="GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV"/>
+                <enum name="GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV"/>
+                <enum name="GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV"/>
+                <enum name="GL_UNSIGNED_INT_S8_S8_8_8_NV"/>
+                <enum name="GL_UNSIGNED_INT_8_8_S8_S8_REV_NV"/>
+                <enum name="GL_DSDT_MAG_INTENSITY_NV"/>
+                <enum name="GL_SHADER_CONSISTENT_NV"/>
+                <enum name="GL_TEXTURE_SHADER_NV"/>
+                <enum name="GL_SHADER_OPERATION_NV"/>
+                <enum name="GL_CULL_MODES_NV"/>
+                <enum name="GL_OFFSET_TEXTURE_MATRIX_NV"/>
+                <enum name="GL_OFFSET_TEXTURE_SCALE_NV"/>
+                <enum name="GL_OFFSET_TEXTURE_BIAS_NV"/>
+                <enum name="GL_OFFSET_TEXTURE_2D_MATRIX_NV"/>
+                <enum name="GL_OFFSET_TEXTURE_2D_SCALE_NV"/>
+                <enum name="GL_OFFSET_TEXTURE_2D_BIAS_NV"/>
+                <enum name="GL_PREVIOUS_TEXTURE_INPUT_NV"/>
+                <enum name="GL_CONST_EYE_NV"/>
+                <enum name="GL_PASS_THROUGH_NV"/>
+                <enum name="GL_CULL_FRAGMENT_NV"/>
+                <enum name="GL_OFFSET_TEXTURE_2D_NV"/>
+                <enum name="GL_DEPENDENT_AR_TEXTURE_2D_NV"/>
+                <enum name="GL_DEPENDENT_GB_TEXTURE_2D_NV"/>
+                <enum name="GL_DOT_PRODUCT_NV"/>
+                <enum name="GL_DOT_PRODUCT_DEPTH_REPLACE_NV"/>
+                <enum name="GL_DOT_PRODUCT_TEXTURE_2D_NV"/>
+                <enum name="GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV"/>
+                <enum name="GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV"/>
+                <enum name="GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV"/>
+                <enum name="GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV"/>
+                <enum name="GL_HILO_NV"/>
+                <enum name="GL_DSDT_NV"/>
+                <enum name="GL_DSDT_MAG_NV"/>
+                <enum name="GL_DSDT_MAG_VIB_NV"/>
+                <enum name="GL_HILO16_NV"/>
+                <enum name="GL_SIGNED_HILO_NV"/>
+                <enum name="GL_SIGNED_HILO16_NV"/>
+                <enum name="GL_SIGNED_RGBA_NV"/>
+                <enum name="GL_SIGNED_RGBA8_NV"/>
+                <enum name="GL_SIGNED_RGB_NV"/>
+                <enum name="GL_SIGNED_RGB8_NV"/>
+                <enum name="GL_SIGNED_LUMINANCE_NV"/>
+                <enum name="GL_SIGNED_LUMINANCE8_NV"/>
+                <enum name="GL_SIGNED_LUMINANCE_ALPHA_NV"/>
+                <enum name="GL_SIGNED_LUMINANCE8_ALPHA8_NV"/>
+                <enum name="GL_SIGNED_ALPHA_NV"/>
+                <enum name="GL_SIGNED_ALPHA8_NV"/>
+                <enum name="GL_SIGNED_INTENSITY_NV"/>
+                <enum name="GL_SIGNED_INTENSITY8_NV"/>
+                <enum name="GL_DSDT8_NV"/>
+                <enum name="GL_DSDT8_MAG8_NV"/>
+                <enum name="GL_DSDT8_MAG8_INTENSITY8_NV"/>
+                <enum name="GL_SIGNED_RGB_UNSIGNED_ALPHA_NV"/>
+                <enum name="GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV"/>
+                <enum name="GL_HI_SCALE_NV"/>
+                <enum name="GL_LO_SCALE_NV"/>
+                <enum name="GL_DS_SCALE_NV"/>
+                <enum name="GL_DT_SCALE_NV"/>
+                <enum name="GL_MAGNITUDE_SCALE_NV"/>
+                <enum name="GL_VIBRANCE_SCALE_NV"/>
+                <enum name="GL_HI_BIAS_NV"/>
+                <enum name="GL_LO_BIAS_NV"/>
+                <enum name="GL_DS_BIAS_NV"/>
+                <enum name="GL_DT_BIAS_NV"/>
+                <enum name="GL_MAGNITUDE_BIAS_NV"/>
+                <enum name="GL_VIBRANCE_BIAS_NV"/>
+                <enum name="GL_TEXTURE_BORDER_VALUES_NV"/>
+                <enum name="GL_TEXTURE_HI_SIZE_NV"/>
+                <enum name="GL_TEXTURE_LO_SIZE_NV"/>
+                <enum name="GL_TEXTURE_DS_SIZE_NV"/>
+                <enum name="GL_TEXTURE_DT_SIZE_NV"/>
+                <enum name="GL_TEXTURE_MAG_SIZE_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texture_shader2" supported="gl">
+            <require>
+                <enum name="GL_DOT_PRODUCT_TEXTURE_3D_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_texture_shader3" supported="gl">
+            <require>
+                <enum name="GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV"/>
+                <enum name="GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV"/>
+                <enum name="GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV"/>
+                <enum name="GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV"/>
+                <enum name="GL_OFFSET_HILO_TEXTURE_2D_NV"/>
+                <enum name="GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV"/>
+                <enum name="GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV"/>
+                <enum name="GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV"/>
+                <enum name="GL_DEPENDENT_HILO_TEXTURE_2D_NV"/>
+                <enum name="GL_DEPENDENT_RGB_TEXTURE_3D_NV"/>
+                <enum name="GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV"/>
+                <enum name="GL_DOT_PRODUCT_PASS_THROUGH_NV"/>
+                <enum name="GL_DOT_PRODUCT_TEXTURE_1D_NV"/>
+                <enum name="GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV"/>
+                <enum name="GL_HILO8_NV"/>
+                <enum name="GL_SIGNED_HILO8_NV"/>
+                <enum name="GL_FORCE_BLUE_TO_ONE_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_transform_feedback" supported="gl">
+            <require>
+                <enum name="GL_BACK_PRIMARY_COLOR_NV"/>
+                <enum name="GL_BACK_SECONDARY_COLOR_NV"/>
+                <enum name="GL_TEXTURE_COORD_NV"/>
+                <enum name="GL_CLIP_DISTANCE_NV"/>
+                <enum name="GL_VERTEX_ID_NV"/>
+                <enum name="GL_PRIMITIVE_ID_NV"/>
+                <enum name="GL_GENERIC_ATTRIB_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_ATTRIBS_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV"/>
+                <enum name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV"/>
+                <enum name="GL_ACTIVE_VARYINGS_NV"/>
+                <enum name="GL_ACTIVE_VARYING_MAX_LENGTH_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_VARYINGS_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_START_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_RECORD_NV"/>
+                <enum name="GL_PRIMITIVES_GENERATED_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV"/>
+                <enum name="GL_RASTERIZER_DISCARD_NV"/>
+                <enum name="GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV"/>
+                <enum name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV"/>
+                <enum name="GL_INTERLEAVED_ATTRIBS_NV"/>
+                <enum name="GL_SEPARATE_ATTRIBS_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV"/>
+                <enum name="GL_LAYER_NV"/>
+                <command name="glBeginTransformFeedbackNV"/>
+                <command name="glEndTransformFeedbackNV"/>
+                <command name="glTransformFeedbackAttribsNV"/>
+                <command name="glBindBufferRangeNV"/>
+                <command name="glBindBufferOffsetNV"/>
+                <command name="glBindBufferBaseNV"/>
+                <command name="glTransformFeedbackVaryingsNV"/>
+                <command name="glActiveVaryingNV"/>
+                <command name="glGetVaryingLocationNV"/>
+                <command name="glGetActiveVaryingNV"/>
+                <command name="glGetTransformFeedbackVaryingNV"/>
+            </require>
+            <require comment="Extended by GL_ARB_transform_feedback3">
+                <enum name="GL_NEXT_BUFFER_NV"/>
+                <enum name="GL_SKIP_COMPONENTS4_NV"/>
+                <enum name="GL_SKIP_COMPONENTS3_NV"/>
+                <enum name="GL_SKIP_COMPONENTS2_NV"/>
+                <enum name="GL_SKIP_COMPONENTS1_NV"/>
+                <command name="glTransformFeedbackStreamAttribsNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_transform_feedback2" supported="gl">
+            <require>
+                <enum name="GL_TRANSFORM_FEEDBACK_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_BINDING_NV"/>
+                <command name="glBindTransformFeedbackNV"/>
+                <command name="glDeleteTransformFeedbacksNV"/>
+                <command name="glGenTransformFeedbacksNV"/>
+                <command name="glIsTransformFeedbackNV"/>
+                <command name="glPauseTransformFeedbackNV"/>
+                <command name="glResumeTransformFeedbackNV"/>
+                <command name="glDrawTransformFeedbackNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_uniform_buffer_unified_memory" supported="gl">
+            <require>
+                <enum name="GL_UNIFORM_BUFFER_UNIFIED_NV"/>
+                <enum name="GL_UNIFORM_BUFFER_ADDRESS_NV"/>
+                <enum name="GL_UNIFORM_BUFFER_LENGTH_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_vdpau_interop" supported="gl">
+            <require>
+                <enum name="GL_SURFACE_STATE_NV"/>
+                <enum name="GL_SURFACE_REGISTERED_NV"/>
+                <enum name="GL_SURFACE_MAPPED_NV"/>
+                <enum name="GL_WRITE_DISCARD_NV"/>
+                <command name="glVDPAUInitNV"/>
+                <command name="glVDPAUFiniNV"/>
+                <command name="glVDPAURegisterVideoSurfaceNV"/>
+                <command name="glVDPAURegisterOutputSurfaceNV"/>
+                <command name="glVDPAUIsSurfaceNV"/>
+                <command name="glVDPAUUnregisterSurfaceNV"/>
+                <command name="glVDPAUGetSurfaceivNV"/>
+                <command name="glVDPAUSurfaceAccessNV"/>
+                <command name="glVDPAUMapSurfacesNV"/>
+                <command name="glVDPAUUnmapSurfacesNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_vertex_array_range" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ARRAY_RANGE_NV"/>
+                <enum name="GL_VERTEX_ARRAY_RANGE_LENGTH_NV"/>
+                <enum name="GL_VERTEX_ARRAY_RANGE_VALID_NV"/>
+                <enum name="GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV"/>
+                <enum name="GL_VERTEX_ARRAY_RANGE_POINTER_NV"/>
+                <command name="glFlushVertexArrayRangeNV"/>
+                <command name="glVertexArrayRangeNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_vertex_array_range2" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_vertex_attrib_integer_64bit" supported="gl">
+            <require>
+                <enum name="GL_INT64_NV"/>
+                <enum name="GL_UNSIGNED_INT64_NV"/>
+                <command name="glVertexAttribL1i64NV"/>
+                <command name="glVertexAttribL2i64NV"/>
+                <command name="glVertexAttribL3i64NV"/>
+                <command name="glVertexAttribL4i64NV"/>
+                <command name="glVertexAttribL1i64vNV"/>
+                <command name="glVertexAttribL2i64vNV"/>
+                <command name="glVertexAttribL3i64vNV"/>
+                <command name="glVertexAttribL4i64vNV"/>
+                <command name="glVertexAttribL1ui64NV"/>
+                <command name="glVertexAttribL2ui64NV"/>
+                <command name="glVertexAttribL3ui64NV"/>
+                <command name="glVertexAttribL4ui64NV"/>
+                <command name="glVertexAttribL1ui64vNV"/>
+                <command name="glVertexAttribL2ui64vNV"/>
+                <command name="glVertexAttribL3ui64vNV"/>
+                <command name="glVertexAttribL4ui64vNV"/>
+                <command name="glGetVertexAttribLi64vNV"/>
+                <command name="glGetVertexAttribLui64vNV"/>
+                <command name="glVertexAttribLFormatNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_vertex_buffer_unified_memory" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV"/>
+                <enum name="GL_ELEMENT_ARRAY_UNIFIED_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_VERTEX_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_NORMAL_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_COLOR_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_INDEX_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_EDGE_FLAG_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_FOG_COORD_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_ELEMENT_ARRAY_ADDRESS_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV"/>
+                <enum name="GL_VERTEX_ARRAY_LENGTH_NV"/>
+                <enum name="GL_NORMAL_ARRAY_LENGTH_NV"/>
+                <enum name="GL_COLOR_ARRAY_LENGTH_NV"/>
+                <enum name="GL_INDEX_ARRAY_LENGTH_NV"/>
+                <enum name="GL_TEXTURE_COORD_ARRAY_LENGTH_NV"/>
+                <enum name="GL_EDGE_FLAG_ARRAY_LENGTH_NV"/>
+                <enum name="GL_SECONDARY_COLOR_ARRAY_LENGTH_NV"/>
+                <enum name="GL_FOG_COORD_ARRAY_LENGTH_NV"/>
+                <enum name="GL_ELEMENT_ARRAY_LENGTH_NV"/>
+                <enum name="GL_DRAW_INDIRECT_UNIFIED_NV"/>
+                <enum name="GL_DRAW_INDIRECT_ADDRESS_NV"/>
+                <enum name="GL_DRAW_INDIRECT_LENGTH_NV"/>
+                <command name="glBufferAddressRangeNV"/>
+                <command name="glVertexFormatNV"/>
+                <command name="glNormalFormatNV"/>
+                <command name="glColorFormatNV"/>
+                <command name="glIndexFormatNV"/>
+                <command name="glTexCoordFormatNV"/>
+                <command name="glEdgeFlagFormatNV"/>
+                <command name="glSecondaryColorFormatNV"/>
+                <command name="glFogCoordFormatNV"/>
+                <command name="glVertexAttribFormatNV"/>
+                <command name="glVertexAttribIFormatNV"/>
+                <command name="glGetIntegerui64i_vNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_vertex_program" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_PROGRAM_NV"/>
+                <enum name="GL_VERTEX_STATE_PROGRAM_NV"/>
+                <enum name="GL_ATTRIB_ARRAY_SIZE_NV"/>
+                <enum name="GL_ATTRIB_ARRAY_STRIDE_NV"/>
+                <enum name="GL_ATTRIB_ARRAY_TYPE_NV"/>
+                <enum name="GL_CURRENT_ATTRIB_NV"/>
+                <enum name="GL_PROGRAM_LENGTH_NV"/>
+                <enum name="GL_PROGRAM_STRING_NV"/>
+                <enum name="GL_MODELVIEW_PROJECTION_NV"/>
+                <enum name="GL_IDENTITY_NV"/>
+                <enum name="GL_INVERSE_NV"/>
+                <enum name="GL_TRANSPOSE_NV"/>
+                <enum name="GL_INVERSE_TRANSPOSE_NV"/>
+                <enum name="GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV"/>
+                <enum name="GL_MAX_TRACK_MATRICES_NV"/>
+                <enum name="GL_MATRIX0_NV"/>
+                <enum name="GL_MATRIX1_NV"/>
+                <enum name="GL_MATRIX2_NV"/>
+                <enum name="GL_MATRIX3_NV"/>
+                <enum name="GL_MATRIX4_NV"/>
+                <enum name="GL_MATRIX5_NV"/>
+                <enum name="GL_MATRIX6_NV"/>
+                <enum name="GL_MATRIX7_NV"/>
+                <enum name="GL_CURRENT_MATRIX_STACK_DEPTH_NV"/>
+                <enum name="GL_CURRENT_MATRIX_NV"/>
+                <enum name="GL_VERTEX_PROGRAM_POINT_SIZE_NV"/>
+                <enum name="GL_VERTEX_PROGRAM_TWO_SIDE_NV"/>
+                <enum name="GL_PROGRAM_PARAMETER_NV"/>
+                <enum name="GL_ATTRIB_ARRAY_POINTER_NV"/>
+                <enum name="GL_PROGRAM_TARGET_NV"/>
+                <enum name="GL_PROGRAM_RESIDENT_NV"/>
+                <enum name="GL_TRACK_MATRIX_NV"/>
+                <enum name="GL_TRACK_MATRIX_TRANSFORM_NV"/>
+                <enum name="GL_VERTEX_PROGRAM_BINDING_NV"/>
+                <enum name="GL_PROGRAM_ERROR_POSITION_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY0_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY1_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY2_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY3_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY4_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY5_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY6_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY7_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY8_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY9_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY10_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY11_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY12_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY13_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY14_NV"/>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY15_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB0_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB1_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB2_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB3_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB4_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB5_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB6_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB7_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB8_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB9_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB10_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB11_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB12_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB13_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB14_4_NV"/>
+                <enum name="GL_MAP1_VERTEX_ATTRIB15_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB0_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB1_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB2_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB3_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB4_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB5_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB6_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB7_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB8_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB9_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB10_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB11_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB12_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB13_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB14_4_NV"/>
+                <enum name="GL_MAP2_VERTEX_ATTRIB15_4_NV"/>
+                <command name="glAreProgramsResidentNV"/>
+                <command name="glBindProgramNV"/>
+                <command name="glDeleteProgramsNV"/>
+                <command name="glExecuteProgramNV"/>
+                <command name="glGenProgramsNV"/>
+                <command name="glGetProgramParameterdvNV"/>
+                <command name="glGetProgramParameterfvNV"/>
+                <command name="glGetProgramivNV"/>
+                <command name="glGetProgramStringNV"/>
+                <command name="glGetTrackMatrixivNV"/>
+                <command name="glGetVertexAttribdvNV"/>
+                <command name="glGetVertexAttribfvNV"/>
+                <command name="glGetVertexAttribivNV"/>
+                <command name="glGetVertexAttribPointervNV"/>
+                <command name="glIsProgramNV"/>
+                <command name="glLoadProgramNV"/>
+                <command name="glProgramParameter4dNV"/>
+                <command name="glProgramParameter4dvNV"/>
+                <command name="glProgramParameter4fNV"/>
+                <command name="glProgramParameter4fvNV"/>
+                <command name="glProgramParameters4dvNV"/>
+                <command name="glProgramParameters4fvNV"/>
+                <command name="glRequestResidentProgramsNV"/>
+                <command name="glTrackMatrixNV"/>
+                <command name="glVertexAttribPointerNV"/>
+                <command name="glVertexAttrib1dNV"/>
+                <command name="glVertexAttrib1dvNV"/>
+                <command name="glVertexAttrib1fNV"/>
+                <command name="glVertexAttrib1fvNV"/>
+                <command name="glVertexAttrib1sNV"/>
+                <command name="glVertexAttrib1svNV"/>
+                <command name="glVertexAttrib2dNV"/>
+                <command name="glVertexAttrib2dvNV"/>
+                <command name="glVertexAttrib2fNV"/>
+                <command name="glVertexAttrib2fvNV"/>
+                <command name="glVertexAttrib2sNV"/>
+                <command name="glVertexAttrib2svNV"/>
+                <command name="glVertexAttrib3dNV"/>
+                <command name="glVertexAttrib3dvNV"/>
+                <command name="glVertexAttrib3fNV"/>
+                <command name="glVertexAttrib3fvNV"/>
+                <command name="glVertexAttrib3sNV"/>
+                <command name="glVertexAttrib3svNV"/>
+                <command name="glVertexAttrib4dNV"/>
+                <command name="glVertexAttrib4dvNV"/>
+                <command name="glVertexAttrib4fNV"/>
+                <command name="glVertexAttrib4fvNV"/>
+                <command name="glVertexAttrib4sNV"/>
+                <command name="glVertexAttrib4svNV"/>
+                <command name="glVertexAttrib4ubNV"/>
+                <command name="glVertexAttrib4ubvNV"/>
+                <command name="glVertexAttribs1dvNV"/>
+                <command name="glVertexAttribs1fvNV"/>
+                <command name="glVertexAttribs1svNV"/>
+                <command name="glVertexAttribs2dvNV"/>
+                <command name="glVertexAttribs2fvNV"/>
+                <command name="glVertexAttribs2svNV"/>
+                <command name="glVertexAttribs3dvNV"/>
+                <command name="glVertexAttribs3fvNV"/>
+                <command name="glVertexAttribs3svNV"/>
+                <command name="glVertexAttribs4dvNV"/>
+                <command name="glVertexAttribs4fvNV"/>
+                <command name="glVertexAttribs4svNV"/>
+                <command name="glVertexAttribs4ubvNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_vertex_program1_1" supported="gl"/>
+        <extension name="GL_NV_vertex_program2" supported="gl"/>
+        <extension name="GL_NV_vertex_program2_option" supported="gl">
+            <require>
+                <enum name="GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV"/>
+                <enum name="GL_MAX_PROGRAM_CALL_DEPTH_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_vertex_program3" supported="gl">
+            <require>
+                <enum name="GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_vertex_program4" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV"/>
+                <command name="glVertexAttribI1iEXT"/>
+                <command name="glVertexAttribI2iEXT"/>
+                <command name="glVertexAttribI3iEXT"/>
+                <command name="glVertexAttribI4iEXT"/>
+                <command name="glVertexAttribI1uiEXT"/>
+                <command name="glVertexAttribI2uiEXT"/>
+                <command name="glVertexAttribI3uiEXT"/>
+                <command name="glVertexAttribI4uiEXT"/>
+                <command name="glVertexAttribI1ivEXT"/>
+                <command name="glVertexAttribI2ivEXT"/>
+                <command name="glVertexAttribI3ivEXT"/>
+                <command name="glVertexAttribI4ivEXT"/>
+                <command name="glVertexAttribI1uivEXT"/>
+                <command name="glVertexAttribI2uivEXT"/>
+                <command name="glVertexAttribI3uivEXT"/>
+                <command name="glVertexAttribI4uivEXT"/>
+                <command name="glVertexAttribI4bvEXT"/>
+                <command name="glVertexAttribI4svEXT"/>
+                <command name="glVertexAttribI4ubvEXT"/>
+                <command name="glVertexAttribI4usvEXT"/>
+                <command name="glVertexAttribIPointerEXT"/>
+                <command name="glGetVertexAttribIivEXT"/>
+                <command name="glGetVertexAttribIuivEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_video_capture" supported="gl">
+            <require>
+                <enum name="GL_VIDEO_BUFFER_NV"/>
+                <enum name="GL_VIDEO_BUFFER_BINDING_NV"/>
+                <enum name="GL_FIELD_UPPER_NV"/>
+                <enum name="GL_FIELD_LOWER_NV"/>
+                <enum name="GL_NUM_VIDEO_CAPTURE_STREAMS_NV"/>
+                <enum name="GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV"/>
+                <enum name="GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV"/>
+                <enum name="GL_LAST_VIDEO_CAPTURE_STATUS_NV"/>
+                <enum name="GL_VIDEO_BUFFER_PITCH_NV"/>
+                <enum name="GL_VIDEO_COLOR_CONVERSION_MATRIX_NV"/>
+                <enum name="GL_VIDEO_COLOR_CONVERSION_MAX_NV"/>
+                <enum name="GL_VIDEO_COLOR_CONVERSION_MIN_NV"/>
+                <enum name="GL_VIDEO_COLOR_CONVERSION_OFFSET_NV"/>
+                <enum name="GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV"/>
+                <enum name="GL_PARTIAL_SUCCESS_NV"/>
+                <enum name="GL_SUCCESS_NV"/>
+                <enum name="GL_FAILURE_NV"/>
+                <enum name="GL_YCBYCR8_422_NV"/>
+                <enum name="GL_YCBAYCR8A_4224_NV"/>
+                <enum name="GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV"/>
+                <enum name="GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV"/>
+                <enum name="GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV"/>
+                <enum name="GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV"/>
+                <enum name="GL_Z4Y12Z4CB12Z4CR12_444_NV"/>
+                <enum name="GL_VIDEO_CAPTURE_FRAME_WIDTH_NV"/>
+                <enum name="GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV"/>
+                <enum name="GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV"/>
+                <enum name="GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV"/>
+                <enum name="GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV"/>
+                <command name="glBeginVideoCaptureNV"/>
+                <command name="glBindVideoCaptureStreamBufferNV"/>
+                <command name="glBindVideoCaptureStreamTextureNV"/>
+                <command name="glEndVideoCaptureNV"/>
+                <command name="glGetVideoCaptureivNV"/>
+                <command name="glGetVideoCaptureStreamivNV"/>
+                <command name="glGetVideoCaptureStreamfvNV"/>
+                <command name="glGetVideoCaptureStreamdvNV"/>
+                <command name="glVideoCaptureNV"/>
+                <command name="glVideoCaptureStreamParameterivNV"/>
+                <command name="glVideoCaptureStreamParameterfvNV"/>
+                <command name="glVideoCaptureStreamParameterdvNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_viewport_array" supported="gles2">
+            <require>
+                <enum name="GL_MAX_VIEWPORTS_NV"/>
+                <enum name="GL_VIEWPORT_SUBPIXEL_BITS_NV"/>
+                <enum name="GL_VIEWPORT_BOUNDS_RANGE_NV"/>
+                <enum name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV"/>
+                <enum name="GL_SCISSOR_BOX"/>
+                <enum name="GL_VIEWPORT"/>
+                <enum name="GL_DEPTH_RANGE"/>
+                <enum name="GL_SCISSOR_TEST"/>
+                <command name="glViewportArrayvNV"/>
+                <command name="glViewportIndexedfNV"/>
+                <command name="glViewportIndexedfvNV"/>
+                <command name="glScissorArrayvNV"/>
+                <command name="glScissorIndexedNV"/>
+                <command name="glScissorIndexedvNV"/>
+                <command name="glDepthRangeArrayfvNV"/>
+                <command name="glDepthRangeIndexedfNV"/>
+                <command name="glGetFloati_vNV"/>
+                <command name="glEnableiNV"/>
+                <command name="glDisableiNV"/>
+                <command name="glIsEnablediNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_viewport_array2" supported="gl|glcore|gles2"/>
+        <extension name="GL_NV_viewport_swizzle" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_X_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_Y_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_Z_NV"/>
+                <enum name="GL_VIEWPORT_SWIZZLE_W_NV"/>
+                <command name="glViewportSwizzleNV"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_EGL_image" supported="gles1|gles2">
+            <require>
+                <type name="GLeglImageOES"/>
+                <command name="glEGLImageTargetTexture2DOES"/>
+                <command name="glEGLImageTargetRenderbufferStorageOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_EGL_image_external" supported="gles1|gles2">
+            <require>
+                <type name="GLeglImageOES"/>
+                <enum name="GL_TEXTURE_EXTERNAL_OES"/>
+                <enum name="GL_TEXTURE_BINDING_EXTERNAL_OES"/>
+                <enum name="GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES"/>
+            </require>
+            <require api="gles2">
+                <enum name="GL_SAMPLER_EXTERNAL_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_EGL_image_external_essl3" supported="gles2"/>
+        <extension name="GL_OES_blend_equation_separate" supported="gles1">
+            <require>
+                <enum name="GL_BLEND_EQUATION_RGB_OES"/>
+                <enum name="GL_BLEND_EQUATION_ALPHA_OES"/>
+                <command name="glBlendEquationSeparateOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_blend_func_separate" supported="gles1">
+            <require>
+                <enum name="GL_BLEND_DST_RGB_OES"/>
+                <enum name="GL_BLEND_SRC_RGB_OES"/>
+                <enum name="GL_BLEND_DST_ALPHA_OES"/>
+                <enum name="GL_BLEND_SRC_ALPHA_OES"/>
+                <command name="glBlendFuncSeparateOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_blend_subtract" supported="gles1">
+            <require>
+                <enum name="GL_BLEND_EQUATION_OES"/>
+                <enum name="GL_FUNC_ADD_OES"/>
+                <enum name="GL_FUNC_SUBTRACT_OES"/>
+                <enum name="GL_FUNC_REVERSE_SUBTRACT_OES"/>
+                <command name="glBlendEquationOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_byte_coordinates" supported="gl|gles1">
+            <require>
+                <type name="GLbyte"/>
+                <enum name="GL_BYTE"/>
+            </require>
+            <require api="gl" comment="Immediate-mode entry points don't exist in ES 1.x">
+                <command name="glMultiTexCoord1bOES"/>
+                <command name="glMultiTexCoord1bvOES"/>
+                <command name="glMultiTexCoord2bOES"/>
+                <command name="glMultiTexCoord2bvOES"/>
+                <command name="glMultiTexCoord3bOES"/>
+                <command name="glMultiTexCoord3bvOES"/>
+                <command name="glMultiTexCoord4bOES"/>
+                <command name="glMultiTexCoord4bvOES"/>
+                <command name="glTexCoord1bOES"/>
+                <command name="glTexCoord1bvOES"/>
+                <command name="glTexCoord2bOES"/>
+                <command name="glTexCoord2bvOES"/>
+                <command name="glTexCoord3bOES"/>
+                <command name="glTexCoord3bvOES"/>
+                <command name="glTexCoord4bOES"/>
+                <command name="glTexCoord4bvOES"/>
+                <command name="glVertex2bOES"/>
+                <command name="glVertex2bvOES"/>
+                <command name="glVertex3bOES"/>
+                <command name="glVertex3bvOES"/>
+                <command name="glVertex4bOES"/>
+                <command name="glVertex4bvOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_compressed_ETC1_RGB8_sub_texture" supported="gles1|gles2"/>
+        <extension name="GL_OES_compressed_ETC1_RGB8_texture" supported="gles1|gles2">
+            <require>
+                <enum name="GL_ETC1_RGB8_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_compressed_paletted_texture" supported="gl|gles1|gles2">
+            <require>
+                <enum name="GL_PALETTE4_RGB8_OES"/>
+                <enum name="GL_PALETTE4_RGBA8_OES"/>
+                <enum name="GL_PALETTE4_R5_G6_B5_OES"/>
+                <enum name="GL_PALETTE4_RGBA4_OES"/>
+                <enum name="GL_PALETTE4_RGB5_A1_OES"/>
+                <enum name="GL_PALETTE8_RGB8_OES"/>
+                <enum name="GL_PALETTE8_RGBA8_OES"/>
+                <enum name="GL_PALETTE8_R5_G6_B5_OES"/>
+                <enum name="GL_PALETTE8_RGBA4_OES"/>
+                <enum name="GL_PALETTE8_RGB5_A1_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_copy_image" supported="gles2">
+            <require>
+                <command name="glCopyImageSubDataOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_depth24" supported="gles1|gles2|glsc2">
+            <require>
+                <enum name="GL_DEPTH_COMPONENT24_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_depth32" supported="gles1|gles2|glsc2">
+            <require>
+                <enum name="GL_DEPTH_COMPONENT32_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_depth_texture" supported="gles2">
+            <require>
+                <enum name="GL_DEPTH_COMPONENT"/>
+                <enum name="GL_UNSIGNED_SHORT"/>
+                <enum name="GL_UNSIGNED_INT"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_draw_buffers_indexed" supported="gles2">
+            <require>
+                <enum name="GL_BLEND_EQUATION_RGB"/>
+                <enum name="GL_BLEND_EQUATION_ALPHA"/>
+                <enum name="GL_BLEND_SRC_RGB"/>
+                <enum name="GL_BLEND_SRC_ALPHA"/>
+                <enum name="GL_BLEND_DST_RGB"/>
+                <enum name="GL_BLEND_DST_ALPHA"/>
+                <enum name="GL_COLOR_WRITEMASK"/>
+                <enum name="GL_BLEND"/>
+                <enum name="GL_FUNC_ADD"/>
+                <enum name="GL_FUNC_SUBTRACT"/>
+                <enum name="GL_FUNC_REVERSE_SUBTRACT"/>
+                <enum name="GL_MIN"/>
+                <enum name="GL_MAX"/>
+                <enum name="GL_ZERO"/>
+                <enum name="GL_ONE"/>
+                <enum name="GL_SRC_COLOR"/>
+                <enum name="GL_ONE_MINUS_SRC_COLOR"/>
+                <enum name="GL_DST_COLOR"/>
+                <enum name="GL_ONE_MINUS_DST_COLOR"/>
+                <enum name="GL_SRC_ALPHA"/>
+                <enum name="GL_ONE_MINUS_SRC_ALPHA"/>
+                <enum name="GL_DST_ALPHA"/>
+                <enum name="GL_ONE_MINUS_DST_ALPHA"/>
+                <enum name="GL_CONSTANT_COLOR"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_COLOR"/>
+                <enum name="GL_CONSTANT_ALPHA"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_ALPHA"/>
+                <enum name="GL_SRC_ALPHA_SATURATE"/>
+                <command name="glEnableiOES"/>
+                <command name="glDisableiOES"/>
+                <command name="glBlendEquationiOES"/>
+                <command name="glBlendEquationSeparateiOES"/>
+                <command name="glBlendFunciOES"/>
+                <command name="glBlendFuncSeparateiOES"/>
+                <command name="glColorMaskiOES"/>
+                <command name="glIsEnablediOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_draw_elements_base_vertex" supported="gles2">
+            <require>
+                <command name="glDrawElementsBaseVertexOES"/>
+                <command name="glDrawRangeElementsBaseVertexOES" comment="Supported only if OpenGL ES 3.0 is supported"/>
+                <command name="glDrawElementsInstancedBaseVertexOES" comment="Supported only if OpenGL ES 3.0 is supported"/>
+                <command name="glMultiDrawElementsBaseVertexOES" comment="Supported only if GL_EXT_multi_draw_arrays is supported"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_draw_texture" supported="gles1">
+            <require>
+                <enum name="GL_TEXTURE_CROP_RECT_OES"/>
+                <command name="glDrawTexsOES"/>
+                <command name="glDrawTexiOES"/>
+                <command name="glDrawTexxOES"/>
+                <command name="glDrawTexsvOES"/>
+                <command name="glDrawTexivOES"/>
+                <command name="glDrawTexxvOES"/>
+                <command name="glDrawTexfOES"/>
+                <command name="glDrawTexfvOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_element_index_uint" supported="gles1|gles2">
+            <require>
+                <enum name="GL_UNSIGNED_INT"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_extended_matrix_palette" supported="gles1"/>
+        <extension name="GL_OES_fbo_render_mipmap" supported="gles1|gles2"/>
+        <extension name="GL_OES_fixed_point" supported="gl|gles1">
+            <require>
+                <enum name="GL_FIXED_OES"/>
+                <command name="glAlphaFuncxOES"/>
+                <command name="glClearColorxOES"/>
+                <command name="glClearDepthxOES"/>
+                <command name="glClipPlanexOES"/>
+                <command name="glColor4xOES"/>
+                <command name="glDepthRangexOES"/>
+                <command name="glFogxOES"/>
+                <command name="glFogxvOES"/>
+                <command name="glFrustumxOES"/>
+                <command name="glGetClipPlanexOES"/>
+                <command name="glGetFixedvOES"/>
+                <command name="glGetTexEnvxvOES"/>
+                <command name="glGetTexParameterxvOES"/>
+                <command name="glLightModelxOES"/>
+                <command name="glLightModelxvOES"/>
+                <command name="glLightxOES"/>
+                <command name="glLightxvOES"/>
+                <command name="glLineWidthxOES"/>
+                <command name="glLoadMatrixxOES"/>
+                <command name="glMaterialxOES"/>
+                <command name="glMaterialxvOES"/>
+                <command name="glMultMatrixxOES"/>
+                <command name="glMultiTexCoord4xOES"/>
+                <command name="glNormal3xOES"/>
+                <command name="glOrthoxOES"/>
+                <command name="glPointParameterxvOES"/>
+                <command name="glPointSizexOES"/>
+                <command name="glPolygonOffsetxOES"/>
+                <command name="glRotatexOES"/>
+                <command name="glScalexOES"/>
+                <command name="glTexEnvxOES"/>
+                <command name="glTexEnvxvOES"/>
+                <command name="glTexParameterxOES"/>
+                <command name="glTexParameterxvOES"/>
+                <command name="glTranslatexOES"/>
+            </require>
+            <require api="gles1" comment="Entry points not in the extension spec, but in the Khronos glext.h. Included for backward compatibility.">
+                <command name="glGetLightxvOES"/>
+                <command name="glGetMaterialxvOES"/>
+                <command name="glPointParameterxOES"/>
+                <command name="glSampleCoveragexOES"/>
+            </require>
+            <require api="gl" comment="Entry points in the extension spec, but not the Khronos glext.h. Correspond to GL-only features it's unlikely were ever implemented against ES 1.x.">
+                <command name="glAccumxOES"/>
+                <command name="glBitmapxOES"/>
+                <command name="glBlendColorxOES"/>
+                <command name="glClearAccumxOES"/>
+                <command name="glColor3xOES"/>
+                <command name="glColor3xvOES"/>
+                <command name="glColor4xvOES"/>
+                <command name="glConvolutionParameterxOES"/>
+                <command name="glConvolutionParameterxvOES"/>
+                <command name="glEvalCoord1xOES"/>
+                <command name="glEvalCoord1xvOES"/>
+                <command name="glEvalCoord2xOES"/>
+                <command name="glEvalCoord2xvOES"/>
+                <command name="glFeedbackBufferxOES"/>
+                <command name="glGetConvolutionParameterxvOES"/>
+                <command name="glGetHistogramParameterxvOES"/>
+                <command name="glGetLightxOES"/>
+                <command name="glGetMapxvOES"/>
+                <command name="glGetMaterialxOES"/>
+                <command name="glGetPixelMapxv"/>
+                <command name="glGetTexGenxvOES"/>
+                <command name="glGetTexLevelParameterxvOES"/>
+                <command name="glIndexxOES"/>
+                <command name="glIndexxvOES"/>
+                <command name="glLoadTransposeMatrixxOES"/>
+                <command name="glMap1xOES"/>
+                <command name="glMap2xOES"/>
+                <command name="glMapGrid1xOES"/>
+                <command name="glMapGrid2xOES"/>
+                <command name="glMultTransposeMatrixxOES"/>
+                <command name="glMultiTexCoord1xOES"/>
+                <command name="glMultiTexCoord1xvOES"/>
+                <command name="glMultiTexCoord2xOES"/>
+                <command name="glMultiTexCoord2xvOES"/>
+                <command name="glMultiTexCoord3xOES"/>
+                <command name="glMultiTexCoord3xvOES"/>
+                <command name="glMultiTexCoord4xvOES"/>
+                <command name="glNormal3xvOES"/>
+                <command name="glPassThroughxOES"/>
+                <command name="glPixelMapx"/>
+                <command name="glPixelStorex"/>
+                <command name="glPixelTransferxOES"/>
+                <command name="glPixelZoomxOES"/>
+                <command name="glPrioritizeTexturesxOES"/>
+                <command name="glRasterPos2xOES"/>
+                <command name="glRasterPos2xvOES"/>
+                <command name="glRasterPos3xOES"/>
+                <command name="glRasterPos3xvOES"/>
+                <command name="glRasterPos4xOES"/>
+                <command name="glRasterPos4xvOES"/>
+                <command name="glRectxOES"/>
+                <command name="glRectxvOES"/>
+                <command name="glTexCoord1xOES"/>
+                <command name="glTexCoord1xvOES"/>
+                <command name="glTexCoord2xOES"/>
+                <command name="glTexCoord2xvOES"/>
+                <command name="glTexCoord3xOES"/>
+                <command name="glTexCoord3xvOES"/>
+                <command name="glTexCoord4xOES"/>
+                <command name="glTexCoord4xvOES"/>
+                <command name="glTexGenxOES"/>
+                <command name="glTexGenxvOES"/>
+                <command name="glVertex2xOES"/>
+                <command name="glVertex2xvOES"/>
+                <command name="glVertex3xOES"/>
+                <command name="glVertex3xvOES"/>
+                <command name="glVertex4xOES"/>
+                <command name="glVertex4xvOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_fragment_precision_high" supported="gles2">
+            <require>
+            </require>
+        </extension>
+        <extension name="GL_OES_framebuffer_object" supported="gles1">
+            <require>
+                <enum name="GL_NONE_OES"/>
+                <enum name="GL_FRAMEBUFFER_OES"/>
+                <enum name="GL_RENDERBUFFER_OES"/>
+                <enum name="GL_RGBA4_OES"/>
+                <enum name="GL_RGB5_A1_OES"/>
+                <enum name="GL_RGB565_OES"/>
+                <enum name="GL_DEPTH_COMPONENT16_OES"/>
+                <enum name="GL_RENDERBUFFER_WIDTH_OES"/>
+                <enum name="GL_RENDERBUFFER_HEIGHT_OES"/>
+                <enum name="GL_RENDERBUFFER_INTERNAL_FORMAT_OES"/>
+                <enum name="GL_RENDERBUFFER_RED_SIZE_OES"/>
+                <enum name="GL_RENDERBUFFER_GREEN_SIZE_OES"/>
+                <enum name="GL_RENDERBUFFER_BLUE_SIZE_OES"/>
+                <enum name="GL_RENDERBUFFER_ALPHA_SIZE_OES"/>
+                <enum name="GL_RENDERBUFFER_DEPTH_SIZE_OES"/>
+                <enum name="GL_RENDERBUFFER_STENCIL_SIZE_OES"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES"/>
+                <enum name="GL_COLOR_ATTACHMENT0_OES"/>
+                <enum name="GL_DEPTH_ATTACHMENT_OES"/>
+                <enum name="GL_STENCIL_ATTACHMENT_OES"/>
+                <enum name="GL_FRAMEBUFFER_COMPLETE_OES"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES"/>
+                <enum name="GL_FRAMEBUFFER_UNSUPPORTED_OES"/>
+                <enum name="GL_FRAMEBUFFER_BINDING_OES"/>
+                <enum name="GL_RENDERBUFFER_BINDING_OES"/>
+                <enum name="GL_MAX_RENDERBUFFER_SIZE_OES"/>
+                <enum name="GL_INVALID_FRAMEBUFFER_OPERATION_OES"/>
+                <command name="glIsRenderbufferOES"/>
+                <command name="glBindRenderbufferOES"/>
+                <command name="glDeleteRenderbuffersOES"/>
+                <command name="glGenRenderbuffersOES"/>
+                <command name="glRenderbufferStorageOES"/>
+                <command name="glGetRenderbufferParameterivOES"/>
+                <command name="glIsFramebufferOES"/>
+                <command name="glBindFramebufferOES"/>
+                <command name="glDeleteFramebuffersOES"/>
+                <command name="glGenFramebuffersOES"/>
+                <command name="glCheckFramebufferStatusOES"/>
+                <command name="glFramebufferRenderbufferOES"/>
+                <command name="glFramebufferTexture2DOES"/>
+                <command name="glGetFramebufferAttachmentParameterivOES"/>
+                <command name="glGenerateMipmapOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_geometry_point_size" supported="gles2"/>
+        <extension name="GL_OES_geometry_shader" supported="gles2">
+            <require>
+                <enum name="GL_GEOMETRY_SHADER_OES"/>
+                <enum name="GL_GEOMETRY_SHADER_BIT_OES"/>
+                <enum name="GL_GEOMETRY_LINKED_VERTICES_OUT_OES"/>
+                <enum name="GL_GEOMETRY_LINKED_INPUT_TYPE_OES"/>
+                <enum name="GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES"/>
+                <enum name="GL_GEOMETRY_SHADER_INVOCATIONS_OES"/>
+                <enum name="GL_LAYER_PROVOKING_VERTEX_OES"/>
+                <enum name="GL_LINES_ADJACENCY_OES"/>
+                <enum name="GL_LINE_STRIP_ADJACENCY_OES"/>
+                <enum name="GL_TRIANGLES_ADJACENCY_OES"/>
+                <enum name="GL_TRIANGLE_STRIP_ADJACENCY_OES"/>
+                <enum name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES"/>
+                <enum name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES"/>
+                <enum name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES"/>
+                <enum name="GL_FIRST_VERTEX_CONVENTION_OES"/>
+                <enum name="GL_LAST_VERTEX_CONVENTION_OES"/>
+                <enum name="GL_UNDEFINED_VERTEX_OES"/>
+                <enum name="GL_PRIMITIVES_GENERATED_OES"/>
+                <enum name="GL_FRAMEBUFFER_DEFAULT_LAYERS_OES"/>
+                <enum name="GL_MAX_FRAMEBUFFER_LAYERS_OES"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES"/>
+                <enum name="GL_REFERENCED_BY_GEOMETRY_SHADER_OES"/>
+                <command name="glFramebufferTextureOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_get_program_binary" supported="gles2">
+            <require>
+                <enum name="GL_PROGRAM_BINARY_LENGTH_OES"/>
+                <enum name="GL_NUM_PROGRAM_BINARY_FORMATS_OES"/>
+                <enum name="GL_PROGRAM_BINARY_FORMATS_OES"/>
+                <command name="glGetProgramBinaryOES"/>
+                <command name="glProgramBinaryOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_gpu_shader5" supported="gles2"/>
+        <extension name="GL_OES_mapbuffer" supported="gles1|gles2">
+            <require>
+                <enum name="GL_WRITE_ONLY_OES"/>
+                <enum name="GL_BUFFER_ACCESS_OES"/>
+                <enum name="GL_BUFFER_MAPPED_OES"/>
+                <enum name="GL_BUFFER_MAP_POINTER_OES"/>
+                <command name="glMapBufferOES"/>
+                <command name="glUnmapBufferOES"/>
+                <command name="glGetBufferPointervOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_matrix_get" supported="gles1">
+            <require>
+                <enum name="GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES"/>
+                <enum name="GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES"/>
+                <enum name="GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_matrix_palette" supported="gles1">
+            <require>
+                <enum name="GL_MAX_VERTEX_UNITS_OES"/>
+                <enum name="GL_MAX_PALETTE_MATRICES_OES"/>
+                <enum name="GL_MATRIX_PALETTE_OES"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_OES"/>
+                <enum name="GL_WEIGHT_ARRAY_OES"/>
+                <enum name="GL_CURRENT_PALETTE_MATRIX_OES"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_SIZE_OES"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_TYPE_OES"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_STRIDE_OES"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_POINTER_OES"/>
+                <enum name="GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES"/>
+                <enum name="GL_WEIGHT_ARRAY_SIZE_OES"/>
+                <enum name="GL_WEIGHT_ARRAY_TYPE_OES"/>
+                <enum name="GL_WEIGHT_ARRAY_STRIDE_OES"/>
+                <enum name="GL_WEIGHT_ARRAY_POINTER_OES"/>
+                <enum name="GL_WEIGHT_ARRAY_BUFFER_BINDING_OES"/>
+                <command name="glCurrentPaletteMatrixOES"/>
+                <command name="glLoadPaletteFromModelViewMatrixOES"/>
+                <command name="glMatrixIndexPointerOES"/>
+                <command name="glWeightPointerOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_packed_depth_stencil" supported="gles1|gles2">
+            <require>
+                <enum name="GL_DEPTH_STENCIL_OES"/>
+                <enum name="GL_UNSIGNED_INT_24_8_OES"/>
+                <enum name="GL_DEPTH24_STENCIL8_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_point_size_array" supported="gles1">
+            <require>
+                <enum name="GL_POINT_SIZE_ARRAY_OES"/>
+                <enum name="GL_POINT_SIZE_ARRAY_TYPE_OES"/>
+                <enum name="GL_POINT_SIZE_ARRAY_STRIDE_OES"/>
+                <enum name="GL_POINT_SIZE_ARRAY_POINTER_OES"/>
+                <enum name="GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES"/>
+                <command name="glPointSizePointerOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_point_sprite" supported="gles1">
+            <require>
+                <enum name="GL_POINT_SPRITE_OES"/>
+                <enum name="GL_COORD_REPLACE_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_primitive_bounding_box" supported="gles2">
+            <require>
+                <enum name="GL_PRIMITIVE_BOUNDING_BOX_OES"/>
+                <command name="glPrimitiveBoundingBoxOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_query_matrix" supported="gl|gles1">
+            <require>
+                <command name="glQueryMatrixxOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_read_format" supported="gl|gles1">
+            <require>
+                <enum name="GL_IMPLEMENTATION_COLOR_READ_TYPE_OES"/>
+                <enum name="GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_required_internalformat" supported="gles1|gles2">
+            <require>
+                <enum name="GL_ALPHA8_OES"/>
+                <enum name="GL_DEPTH_COMPONENT16_OES"/>
+                <enum name="GL_DEPTH_COMPONENT24_OES"/>
+                <enum name="GL_DEPTH24_STENCIL8_OES"/>
+                <enum name="GL_DEPTH_COMPONENT32_OES"/>
+                <enum name="GL_LUMINANCE4_ALPHA4_OES"/>
+                <enum name="GL_LUMINANCE8_ALPHA8_OES"/>
+                <enum name="GL_LUMINANCE8_OES"/>
+                <enum name="GL_RGBA4_OES"/>
+                <enum name="GL_RGB5_A1_OES"/>
+                <enum name="GL_RGB565_OES"/>
+                <enum name="GL_RGB8_OES"/>
+                <enum name="GL_RGBA8_OES"/>
+                <enum name="GL_RGB10_EXT"/>
+                <enum name="GL_RGB10_A2_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_rgb8_rgba8" supported="gles1|gles2|glsc2">
+            <require>
+                <enum name="GL_RGB8_OES"/>
+                <enum name="GL_RGBA8_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_sample_shading" supported="gles2">
+            <require>
+                <command name="glMinSampleShadingOES"/>
+                <enum name="GL_SAMPLE_SHADING_OES"/>
+                <enum name="GL_MIN_SAMPLE_SHADING_VALUE_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_sample_variables" supported="gles2"/>
+        <extension name="GL_OES_shader_image_atomic" supported="gles2"/>
+        <extension name="GL_OES_shader_io_blocks" supported="gles2"/>
+        <extension name="GL_OES_shader_multisample_interpolation" supported="gles2">
+            <require>
+                <enum name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES"/>
+                <enum name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES"/>
+                <enum name="GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_single_precision" supported="gl|gles1">
+            <require>
+                <command name="glClearDepthfOES"/>
+                <command name="glClipPlanefOES"/>
+                <command name="glDepthRangefOES"/>
+                <command name="glFrustumfOES"/>
+                <command name="glGetClipPlanefOES"/>
+                <command name="glOrthofOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_standard_derivatives" supported="gles2|glsc2">
+            <require>
+                <enum name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_stencil1" supported="gles1|gles2">
+            <require>
+                <enum name="GL_STENCIL_INDEX1_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_stencil4" supported="gles1|gles2">
+            <require>
+                <enum name="GL_STENCIL_INDEX4_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_stencil8" supported="gles1">
+            <require>
+                <enum name="GL_STENCIL_INDEX8_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_stencil_wrap" supported="gles1">
+            <require>
+                <enum name="GL_INCR_WRAP_OES"/>
+                <enum name="GL_DECR_WRAP_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_surfaceless_context" supported="gles2">
+            <require>
+                <enum name="GL_FRAMEBUFFER_UNDEFINED_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_tessellation_point_size" supported="gles2"/>
+        <extension name="GL_OES_tessellation_shader" supported="gles2">
+            <require>
+                <enum name="GL_PATCHES_OES"/>
+                <enum name="GL_PATCH_VERTICES_OES"/>
+                <enum name="GL_TESS_CONTROL_OUTPUT_VERTICES_OES"/>
+                <enum name="GL_TESS_GEN_MODE_OES"/>
+                <enum name="GL_TESS_GEN_SPACING_OES"/>
+                <enum name="GL_TESS_GEN_VERTEX_ORDER_OES"/>
+                <enum name="GL_TESS_GEN_POINT_MODE_OES"/>
+                <enum name="GL_TRIANGLES"/>
+                <enum name="GL_ISOLINES_OES"/>
+                <enum name="GL_QUADS_OES"/>
+                <enum name="GL_EQUAL"/>
+                <enum name="GL_FRACTIONAL_ODD_OES"/>
+                <enum name="GL_FRACTIONAL_EVEN_OES"/>
+                <enum name="GL_CCW"/>
+                <enum name="GL_CW"/>
+                <enum name="GL_MAX_PATCH_VERTICES_OES"/>
+                <enum name="GL_MAX_TESS_GEN_LEVEL_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_PATCH_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES"/>
+                <enum name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES"/>
+                <enum name="GL_IS_PER_PATCH_OES"/>
+                <enum name="GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES"/>
+                <enum name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES"/>
+                <enum name="GL_TESS_CONTROL_SHADER_OES"/>
+                <enum name="GL_TESS_EVALUATION_SHADER_OES"/>
+                <enum name="GL_TESS_CONTROL_SHADER_BIT_OES"/>
+                <enum name="GL_TESS_EVALUATION_SHADER_BIT_OES"/>
+                <command name="glPatchParameteriOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_3D" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_WRAP_R_OES"/>
+                <enum name="GL_TEXTURE_3D_OES"/>
+                <enum name="GL_TEXTURE_BINDING_3D_OES"/>
+                <enum name="GL_MAX_3D_TEXTURE_SIZE_OES"/>
+                <enum name="GL_SAMPLER_3D_OES"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES"/>
+                <command name="glTexImage3DOES"/>
+                <command name="glTexSubImage3DOES"/>
+                <command name="glCopyTexSubImage3DOES"/>
+                <command name="glCompressedTexImage3DOES"/>
+                <command name="glCompressedTexSubImage3DOES"/>
+                <command name="glFramebufferTexture3DOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_border_clamp" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_BORDER_COLOR_OES"/>
+                <enum name="GL_CLAMP_TO_BORDER_OES"/>
+                <command name="glTexParameterIivOES"/>
+                <command name="glTexParameterIuivOES"/>
+                <command name="glGetTexParameterIivOES"/>
+                <command name="glGetTexParameterIuivOES"/>
+                <command name="glSamplerParameterIivOES"/>
+                <command name="glSamplerParameterIuivOES"/>
+                <command name="glGetSamplerParameterIivOES"/>
+                <command name="glGetSamplerParameterIuivOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_buffer" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_BUFFER_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_BINDING_OES"/>
+                <enum name="GL_MAX_TEXTURE_BUFFER_SIZE_OES"/>
+                <enum name="GL_TEXTURE_BINDING_BUFFER_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES"/>
+                <enum name="GL_SAMPLER_BUFFER_OES"/>
+                <enum name="GL_INT_SAMPLER_BUFFER_OES"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_BUFFER_OES"/>
+                <enum name="GL_IMAGE_BUFFER_OES"/>
+                <enum name="GL_INT_IMAGE_BUFFER_OES"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_BUFFER_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_OFFSET_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_SIZE_OES"/>
+                <command name="glTexBufferOES"/>
+                <command name="glTexBufferRangeOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_compression_astc" supported="gles2" comment="API is identical to GL_KHR_texture_compression_astc_hdr extension">
+            <require>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_4x4_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_5x4_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_5x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_6x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_6x6_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_8x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_8x6_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_8x8_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x5_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x6_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x8_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_10x10_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_12x10_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_12x12_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_3x3x3_OES"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_4x3x3_OES"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_4x4x3_OES"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_4x4x4_OES"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_5x4x4_OES"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_5x5x4_OES"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_5x5x5_OES"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_6x5x5_OES"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_6x6x5_OES"/>
+                <enum name="GL_COMPRESSED_RGBA_ASTC_6x6x6_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES"/>
+                <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_cube_map" supported="gles1">
+            <require>
+                <enum name="GL_NORMAL_MAP_OES"/>
+                <enum name="GL_REFLECTION_MAP_OES"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_OES"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP_OES"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES"/>
+                <enum name="GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES"/>
+                <enum name="GL_TEXTURE_GEN_MODE_OES"/>
+                <enum name="GL_TEXTURE_GEN_STR_OES"/>
+                <command name="glTexGenfOES"/>
+                <command name="glTexGenfvOES"/>
+                <command name="glTexGeniOES"/>
+                <command name="glTexGenivOES"/>
+                <command name="glTexGenxOES"/>
+                <command name="glTexGenxvOES"/>
+                <command name="glGetTexGenfvOES"/>
+                <command name="glGetTexGenivOES"/>
+                <command name="glGetTexGenxvOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_cube_map_array" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES"/>
+                <enum name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_IMAGE_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_INT_IMAGE_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_env_crossbar" supported="gles1"/>
+        <extension name="GL_OES_texture_float" supported="gles2">
+            <require>
+                <enum name="GL_FLOAT"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_float_linear" supported="gles2"/>
+        <extension name="GL_OES_texture_half_float" supported="gles2">
+            <require>
+                <enum name="GL_HALF_FLOAT_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_half_float_linear" supported="gles2"/>
+        <extension name="GL_OES_texture_mirrored_repeat" supported="gles1">
+            <require>
+                <enum name="GL_MIRRORED_REPEAT_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_npot" supported="gles2"/>
+        <extension name="GL_OES_texture_stencil8" supported="gles2">
+            <require>
+                <enum name="GL_STENCIL_INDEX_OES"/>
+                <enum name="GL_STENCIL_INDEX8_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_storage_multisample_2d_array" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES"/>
+                <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES"/>
+                <enum name="GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES"/>
+                <enum name="GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES"/>
+                <command name="glTexStorage3DMultisampleOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_view" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_VIEW_MIN_LEVEL_OES"/>
+                <enum name="GL_TEXTURE_VIEW_NUM_LEVELS_OES"/>
+                <enum name="GL_TEXTURE_VIEW_MIN_LAYER_OES"/>
+                <enum name="GL_TEXTURE_VIEW_NUM_LAYERS_OES"/>
+                <enum name="GL_TEXTURE_IMMUTABLE_LEVELS"/>
+                <command name="glTextureViewOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_vertex_array_object" supported="gles1|gles2">
+            <require>
+                <enum name="GL_VERTEX_ARRAY_BINDING_OES"/>
+                <command name="glBindVertexArrayOES"/>
+                <command name="glDeleteVertexArraysOES"/>
+                <command name="glGenVertexArraysOES"/>
+                <command name="glIsVertexArrayOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_vertex_half_float" supported="gles2">
+            <require>
+                <enum name="GL_HALF_FLOAT_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_vertex_type_10_10_10_2" supported="gles2">
+            <require>
+                <enum name="GL_UNSIGNED_INT_10_10_10_2_OES"/>
+                <enum name="GL_INT_10_10_10_2_OES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_viewport_array" supported="gles2">
+            <require>
+                <enum name="GL_SCISSOR_BOX"/>
+                <enum name="GL_VIEWPORT"/>
+                <enum name="GL_DEPTH_RANGE"/>
+                <enum name="GL_SCISSOR_TEST"/>
+                <enum name="GL_MAX_VIEWPORTS_OES"/>
+                <enum name="GL_VIEWPORT_SUBPIXEL_BITS_OES"/>
+                <enum name="GL_VIEWPORT_BOUNDS_RANGE_OES"/>
+                <enum name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES"/>
+                <command name="glViewportArrayvOES"/>
+                <command name="glViewportIndexedfOES"/>
+                <command name="glViewportIndexedfvOES"/>
+                <command name="glScissorArrayvOES"/>
+                <command name="glScissorIndexedOES"/>
+                <command name="glScissorIndexedvOES"/>
+                <command name="glDepthRangeArrayfvOES"/>
+                <command name="glDepthRangeIndexedfOES"/>
+                <command name="glGetFloati_vOES"/>
+                <command name="glEnableiOES"/>
+                <command name="glDisableiOES"/>
+                <command name="glIsEnablediOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OML_interlace" supported="gl">
+            <require>
+                <enum name="GL_INTERLACE_OML"/>
+                <enum name="GL_INTERLACE_READ_OML"/>
+            </require>
+        </extension>
+        <extension name="GL_OML_resample" supported="gl">
+            <require>
+                <enum name="GL_PACK_RESAMPLE_OML"/>
+                <enum name="GL_UNPACK_RESAMPLE_OML"/>
+                <enum name="GL_RESAMPLE_REPLICATE_OML"/>
+                <enum name="GL_RESAMPLE_ZERO_FILL_OML"/>
+                <enum name="GL_RESAMPLE_AVERAGE_OML"/>
+                <enum name="GL_RESAMPLE_DECIMATE_OML"/>
+            </require>
+        </extension>
+        <extension name="GL_OML_subsample" supported="gl">
+            <require>
+                <enum name="GL_FORMAT_SUBSAMPLE_24_24_OML"/>
+                <enum name="GL_FORMAT_SUBSAMPLE_244_244_OML"/>
+            </require>
+        </extension>
+        <extension name="GL_OVR_multiview" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR"/>
+                <enum name="GL_MAX_VIEWS_OVR"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR"/>
+                <command name="glFramebufferTextureMultiviewOVR"/>
+            </require>
+        </extension>
+        <extension name="GL_OVR_multiview2" supported="gl|glcore|gles2"/>
+        <extension name="GL_OVR_multiview_multisampled_render_to_texture" supported="gles2">
+            <require>
+                <command name="glFramebufferTextureMultisampleMultiviewOVR"/>
+            </require>
+        </extension>
+        <extension name="GL_PGI_misc_hints" supported="gl">
+            <require>
+                <enum name="GL_PREFER_DOUBLEBUFFER_HINT_PGI"/>
+                <enum name="GL_CONSERVE_MEMORY_HINT_PGI"/>
+                <enum name="GL_RECLAIM_MEMORY_HINT_PGI"/>
+                <enum name="GL_NATIVE_GRAPHICS_HANDLE_PGI"/>
+                <enum name="GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI"/>
+                <enum name="GL_NATIVE_GRAPHICS_END_HINT_PGI"/>
+                <enum name="GL_ALWAYS_FAST_HINT_PGI"/>
+                <enum name="GL_ALWAYS_SOFT_HINT_PGI"/>
+                <enum name="GL_ALLOW_DRAW_OBJ_HINT_PGI"/>
+                <enum name="GL_ALLOW_DRAW_WIN_HINT_PGI"/>
+                <enum name="GL_ALLOW_DRAW_FRG_HINT_PGI"/>
+                <enum name="GL_ALLOW_DRAW_MEM_HINT_PGI"/>
+                <enum name="GL_STRICT_DEPTHFUNC_HINT_PGI"/>
+                <enum name="GL_STRICT_LIGHTING_HINT_PGI"/>
+                <enum name="GL_STRICT_SCISSOR_HINT_PGI"/>
+                <enum name="GL_FULL_STIPPLE_HINT_PGI"/>
+                <enum name="GL_CLIP_NEAR_HINT_PGI"/>
+                <enum name="GL_CLIP_FAR_HINT_PGI"/>
+                <enum name="GL_WIDE_LINE_HINT_PGI"/>
+                <enum name="GL_BACK_NORMALS_HINT_PGI"/>
+                <command name="glHintPGI"/>
+            </require>
+        </extension>
+        <extension name="GL_PGI_vertex_hints" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_DATA_HINT_PGI"/>
+                <enum name="GL_VERTEX_CONSISTENT_HINT_PGI"/>
+                <enum name="GL_MATERIAL_SIDE_HINT_PGI"/>
+                <enum name="GL_MAX_VERTEX_HINT_PGI"/>
+                <enum name="GL_COLOR3_BIT_PGI"/>
+                <enum name="GL_COLOR4_BIT_PGI"/>
+                <enum name="GL_EDGEFLAG_BIT_PGI"/>
+                <enum name="GL_INDEX_BIT_PGI"/>
+                <enum name="GL_MAT_AMBIENT_BIT_PGI"/>
+                <enum name="GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI"/>
+                <enum name="GL_MAT_DIFFUSE_BIT_PGI"/>
+                <enum name="GL_MAT_EMISSION_BIT_PGI"/>
+                <enum name="GL_MAT_COLOR_INDEXES_BIT_PGI"/>
+                <enum name="GL_MAT_SHININESS_BIT_PGI"/>
+                <enum name="GL_MAT_SPECULAR_BIT_PGI"/>
+                <enum name="GL_NORMAL_BIT_PGI"/>
+                <enum name="GL_TEXCOORD1_BIT_PGI"/>
+                <enum name="GL_TEXCOORD2_BIT_PGI"/>
+                <enum name="GL_TEXCOORD3_BIT_PGI"/>
+                <enum name="GL_TEXCOORD4_BIT_PGI"/>
+                <enum name="GL_VERTEX23_BIT_PGI"/>
+                <enum name="GL_VERTEX4_BIT_PGI"/>
+            </require>
+        </extension>
+        <extension name="GL_QCOM_alpha_test" supported="gles2">
+            <require>
+                <enum name="GL_ALPHA_TEST_QCOM"/>
+                <enum name="GL_ALPHA_TEST_FUNC_QCOM"/>
+                <enum name="GL_ALPHA_TEST_REF_QCOM"/>
+                <command name="glAlphaFuncQCOM"/>
+            </require>
+        </extension>
+        <extension name="GL_QCOM_binning_control" supported="gles2">
+            <require>
+                <enum name="GL_BINNING_CONTROL_HINT_QCOM"/>
+                <enum name="GL_CPU_OPTIMIZED_QCOM"/>
+                <enum name="GL_GPU_OPTIMIZED_QCOM"/>
+                <enum name="GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM"/>
+            </require>
+        </extension>
+        <extension name="GL_QCOM_driver_control" supported="gles1|gles2">
+            <require>
+                <command name="glGetDriverControlsQCOM"/>
+                <command name="glGetDriverControlStringQCOM"/>
+                <command name="glEnableDriverControlQCOM"/>
+                <command name="glDisableDriverControlQCOM"/>
+            </require>
+        </extension>
+        <extension name="GL_QCOM_extended_get" supported="gles1|gles2">
+            <require>
+                <enum name="GL_TEXTURE_WIDTH_QCOM"/>
+                <enum name="GL_TEXTURE_HEIGHT_QCOM"/>
+                <enum name="GL_TEXTURE_DEPTH_QCOM"/>
+                <enum name="GL_TEXTURE_INTERNAL_FORMAT_QCOM"/>
+                <enum name="GL_TEXTURE_FORMAT_QCOM"/>
+                <enum name="GL_TEXTURE_TYPE_QCOM"/>
+                <enum name="GL_TEXTURE_IMAGE_VALID_QCOM"/>
+                <enum name="GL_TEXTURE_NUM_LEVELS_QCOM"/>
+                <enum name="GL_TEXTURE_TARGET_QCOM"/>
+                <enum name="GL_TEXTURE_OBJECT_VALID_QCOM"/>
+                <enum name="GL_STATE_RESTORE"/>
+                <command name="glExtGetTexturesQCOM"/>
+                <command name="glExtGetBuffersQCOM"/>
+                <command name="glExtGetRenderbuffersQCOM"/>
+                <command name="glExtGetFramebuffersQCOM"/>
+                <command name="glExtGetTexLevelParameterivQCOM"/>
+                <command name="glExtTexObjectStateOverrideiQCOM"/>
+                <command name="glExtGetTexSubImageQCOM"/>
+                <command name="glExtGetBufferPointervQCOM"/>
+            </require>
+        </extension>
+        <extension name="GL_QCOM_extended_get2" supported="gles1|gles2">
+            <require>
+                <command name="glExtGetShadersQCOM"/>
+                <command name="glExtGetProgramsQCOM"/>
+                <command name="glExtIsProgramBinaryQCOM"/>
+                <command name="glExtGetProgramBinarySourceQCOM"/>
+            </require>
+        </extension>
+        <extension name="GL_QCOM_perfmon_global_mode" supported="gles1|gles2">
+            <require>
+                <enum name="GL_PERFMON_GLOBAL_MODE_QCOM"/>
+            </require>
+        </extension>
+        <extension name="GL_QCOM_tiled_rendering" supported="gles1|gles2">
+            <require>
+                <enum name="GL_COLOR_BUFFER_BIT0_QCOM"/>
+                <enum name="GL_COLOR_BUFFER_BIT1_QCOM"/>
+                <enum name="GL_COLOR_BUFFER_BIT2_QCOM"/>
+                <enum name="GL_COLOR_BUFFER_BIT3_QCOM"/>
+                <enum name="GL_COLOR_BUFFER_BIT4_QCOM"/>
+                <enum name="GL_COLOR_BUFFER_BIT5_QCOM"/>
+                <enum name="GL_COLOR_BUFFER_BIT6_QCOM"/>
+                <enum name="GL_COLOR_BUFFER_BIT7_QCOM"/>
+                <enum name="GL_DEPTH_BUFFER_BIT0_QCOM"/>
+                <enum name="GL_DEPTH_BUFFER_BIT1_QCOM"/>
+                <enum name="GL_DEPTH_BUFFER_BIT2_QCOM"/>
+                <enum name="GL_DEPTH_BUFFER_BIT3_QCOM"/>
+                <enum name="GL_DEPTH_BUFFER_BIT4_QCOM"/>
+                <enum name="GL_DEPTH_BUFFER_BIT5_QCOM"/>
+                <enum name="GL_DEPTH_BUFFER_BIT6_QCOM"/>
+                <enum name="GL_DEPTH_BUFFER_BIT7_QCOM"/>
+                <enum name="GL_STENCIL_BUFFER_BIT0_QCOM"/>
+                <enum name="GL_STENCIL_BUFFER_BIT1_QCOM"/>
+                <enum name="GL_STENCIL_BUFFER_BIT2_QCOM"/>
+                <enum name="GL_STENCIL_BUFFER_BIT3_QCOM"/>
+                <enum name="GL_STENCIL_BUFFER_BIT4_QCOM"/>
+                <enum name="GL_STENCIL_BUFFER_BIT5_QCOM"/>
+                <enum name="GL_STENCIL_BUFFER_BIT6_QCOM"/>
+                <enum name="GL_STENCIL_BUFFER_BIT7_QCOM"/>
+                <enum name="GL_MULTISAMPLE_BUFFER_BIT0_QCOM"/>
+                <enum name="GL_MULTISAMPLE_BUFFER_BIT1_QCOM"/>
+                <enum name="GL_MULTISAMPLE_BUFFER_BIT2_QCOM"/>
+                <enum name="GL_MULTISAMPLE_BUFFER_BIT3_QCOM"/>
+                <enum name="GL_MULTISAMPLE_BUFFER_BIT4_QCOM"/>
+                <enum name="GL_MULTISAMPLE_BUFFER_BIT5_QCOM"/>
+                <enum name="GL_MULTISAMPLE_BUFFER_BIT6_QCOM"/>
+                <enum name="GL_MULTISAMPLE_BUFFER_BIT7_QCOM"/>
+                <command name="glStartTilingQCOM"/>
+                <command name="glEndTilingQCOM"/>
+            </require>
+        </extension>
+        <extension name="GL_QCOM_writeonly_rendering" supported="gles1|gles2">
+            <require>
+                <enum name="GL_WRITEONLY_RENDERING_QCOM"/>
+            </require>
+        </extension>
+        <extension name="GL_REND_screen_coordinates" supported="gl">
+            <require>
+                <enum name="GL_SCREEN_COORDINATES_REND"/>
+                <enum name="GL_INVERTED_SCREEN_W_REND"/>
+            </require>
+        </extension>
+        <extension name="GL_S3_s3tc" supported="gl">
+            <require>
+                <enum name="GL_RGB_S3TC"/>
+                <enum name="GL_RGB4_S3TC"/>
+                <enum name="GL_RGBA_S3TC"/>
+                <enum name="GL_RGBA4_S3TC"/>
+                <enum name="GL_RGBA_DXT5_S3TC"/>
+                <enum name="GL_RGBA4_DXT5_S3TC"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_detail_texture" supported="gl">
+            <require>
+                <enum name="GL_DETAIL_TEXTURE_2D_SGIS"/>
+                <enum name="GL_DETAIL_TEXTURE_2D_BINDING_SGIS"/>
+                <enum name="GL_LINEAR_DETAIL_SGIS"/>
+                <enum name="GL_LINEAR_DETAIL_ALPHA_SGIS"/>
+                <enum name="GL_LINEAR_DETAIL_COLOR_SGIS"/>
+                <enum name="GL_DETAIL_TEXTURE_LEVEL_SGIS"/>
+                <enum name="GL_DETAIL_TEXTURE_MODE_SGIS"/>
+                <enum name="GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS"/>
+                <command name="glDetailTexFuncSGIS"/>
+                <command name="glGetDetailTexFuncSGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_fog_function" supported="gl">
+            <require>
+                <enum name="GL_FOG_FUNC_SGIS"/>
+                <enum name="GL_FOG_FUNC_POINTS_SGIS"/>
+                <enum name="GL_MAX_FOG_FUNC_POINTS_SGIS"/>
+                <command name="glFogFuncSGIS"/>
+                <command name="glGetFogFuncSGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_generate_mipmap" supported="gl">
+            <require>
+                <enum name="GL_GENERATE_MIPMAP_SGIS"/>
+                <enum name="GL_GENERATE_MIPMAP_HINT_SGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_multisample" supported="gl">
+            <require>
+                <enum name="GL_MULTISAMPLE_SGIS"/>
+                <enum name="GL_SAMPLE_ALPHA_TO_MASK_SGIS"/>
+                <enum name="GL_SAMPLE_ALPHA_TO_ONE_SGIS"/>
+                <enum name="GL_SAMPLE_MASK_SGIS"/>
+                <enum name="GL_1PASS_SGIS"/>
+                <enum name="GL_2PASS_0_SGIS"/>
+                <enum name="GL_2PASS_1_SGIS"/>
+                <enum name="GL_4PASS_0_SGIS"/>
+                <enum name="GL_4PASS_1_SGIS"/>
+                <enum name="GL_4PASS_2_SGIS"/>
+                <enum name="GL_4PASS_3_SGIS"/>
+                <enum name="GL_SAMPLE_BUFFERS_SGIS"/>
+                <enum name="GL_SAMPLES_SGIS"/>
+                <enum name="GL_SAMPLE_MASK_VALUE_SGIS"/>
+                <enum name="GL_SAMPLE_MASK_INVERT_SGIS"/>
+                <enum name="GL_SAMPLE_PATTERN_SGIS"/>
+                <command name="glSampleMaskSGIS"/>
+                <command name="glSamplePatternSGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_pixel_texture" supported="gl">
+            <require>
+                <enum name="GL_PIXEL_TEXTURE_SGIS"/>
+                <enum name="GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS"/>
+                <enum name="GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS"/>
+                <enum name="GL_PIXEL_GROUP_COLOR_SGIS"/>
+                <command name="glPixelTexGenParameteriSGIS"/>
+                <command name="glPixelTexGenParameterivSGIS"/>
+                <command name="glPixelTexGenParameterfSGIS"/>
+                <command name="glPixelTexGenParameterfvSGIS"/>
+                <command name="glGetPixelTexGenParameterivSGIS"/>
+                <command name="glGetPixelTexGenParameterfvSGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_point_line_texgen" supported="gl">
+            <require>
+                <enum name="GL_EYE_DISTANCE_TO_POINT_SGIS"/>
+                <enum name="GL_OBJECT_DISTANCE_TO_POINT_SGIS"/>
+                <enum name="GL_EYE_DISTANCE_TO_LINE_SGIS"/>
+                <enum name="GL_OBJECT_DISTANCE_TO_LINE_SGIS"/>
+                <enum name="GL_EYE_POINT_SGIS"/>
+                <enum name="GL_OBJECT_POINT_SGIS"/>
+                <enum name="GL_EYE_LINE_SGIS"/>
+                <enum name="GL_OBJECT_LINE_SGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_point_parameters" supported="gl">
+            <require>
+                <enum name="GL_POINT_SIZE_MIN_SGIS"/>
+                <enum name="GL_POINT_SIZE_MAX_SGIS"/>
+                <enum name="GL_POINT_FADE_THRESHOLD_SIZE_SGIS"/>
+                <enum name="GL_DISTANCE_ATTENUATION_SGIS"/>
+                <command name="glPointParameterfSGIS"/>
+                <command name="glPointParameterfvSGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_sharpen_texture" supported="gl">
+            <require>
+                <enum name="GL_LINEAR_SHARPEN_SGIS"/>
+                <enum name="GL_LINEAR_SHARPEN_ALPHA_SGIS"/>
+                <enum name="GL_LINEAR_SHARPEN_COLOR_SGIS"/>
+                <enum name="GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS"/>
+                <command name="glSharpenTexFuncSGIS"/>
+                <command name="glGetSharpenTexFuncSGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_texture4D" supported="gl">
+            <require>
+                <enum name="GL_PACK_SKIP_VOLUMES_SGIS"/>
+                <enum name="GL_PACK_IMAGE_DEPTH_SGIS"/>
+                <enum name="GL_UNPACK_SKIP_VOLUMES_SGIS"/>
+                <enum name="GL_UNPACK_IMAGE_DEPTH_SGIS"/>
+                <enum name="GL_TEXTURE_4D_SGIS"/>
+                <enum name="GL_PROXY_TEXTURE_4D_SGIS"/>
+                <enum name="GL_TEXTURE_4DSIZE_SGIS"/>
+                <enum name="GL_TEXTURE_WRAP_Q_SGIS"/>
+                <enum name="GL_MAX_4D_TEXTURE_SIZE_SGIS"/>
+                <enum name="GL_TEXTURE_4D_BINDING_SGIS"/>
+                <command name="glTexImage4DSGIS"/>
+                <command name="glTexSubImage4DSGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_texture_border_clamp" supported="gl">
+            <require>
+                <enum name="GL_CLAMP_TO_BORDER_SGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_texture_color_mask" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_COLOR_WRITEMASK_SGIS"/>
+                <command name="glTextureColorMaskSGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_texture_edge_clamp" supported="gl">
+            <require>
+                <enum name="GL_CLAMP_TO_EDGE_SGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_texture_filter4" supported="gl">
+            <require>
+                <enum name="GL_FILTER4_SGIS"/>
+                <enum name="GL_TEXTURE_FILTER4_SIZE_SGIS"/>
+                <command name="glGetTexFilterFuncSGIS"/>
+                <command name="glTexFilterFuncSGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_texture_lod" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_MIN_LOD_SGIS"/>
+                <enum name="GL_TEXTURE_MAX_LOD_SGIS"/>
+                <enum name="GL_TEXTURE_BASE_LEVEL_SGIS"/>
+                <enum name="GL_TEXTURE_MAX_LEVEL_SGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIS_texture_select" supported="gl">
+            <require>
+                <enum name="GL_DUAL_ALPHA4_SGIS"/>
+                <enum name="GL_DUAL_ALPHA8_SGIS"/>
+                <enum name="GL_DUAL_ALPHA12_SGIS"/>
+                <enum name="GL_DUAL_ALPHA16_SGIS"/>
+                <enum name="GL_DUAL_LUMINANCE4_SGIS"/>
+                <enum name="GL_DUAL_LUMINANCE8_SGIS"/>
+                <enum name="GL_DUAL_LUMINANCE12_SGIS"/>
+                <enum name="GL_DUAL_LUMINANCE16_SGIS"/>
+                <enum name="GL_DUAL_INTENSITY4_SGIS"/>
+                <enum name="GL_DUAL_INTENSITY8_SGIS"/>
+                <enum name="GL_DUAL_INTENSITY12_SGIS"/>
+                <enum name="GL_DUAL_INTENSITY16_SGIS"/>
+                <enum name="GL_DUAL_LUMINANCE_ALPHA4_SGIS"/>
+                <enum name="GL_DUAL_LUMINANCE_ALPHA8_SGIS"/>
+                <enum name="GL_QUAD_ALPHA4_SGIS"/>
+                <enum name="GL_QUAD_ALPHA8_SGIS"/>
+                <enum name="GL_QUAD_LUMINANCE4_SGIS"/>
+                <enum name="GL_QUAD_LUMINANCE8_SGIS"/>
+                <enum name="GL_QUAD_INTENSITY4_SGIS"/>
+                <enum name="GL_QUAD_INTENSITY8_SGIS"/>
+                <enum name="GL_DUAL_TEXTURE_SELECT_SGIS"/>
+                <enum name="GL_QUAD_TEXTURE_SELECT_SGIS"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_async" supported="gl">
+            <require>
+                <enum name="GL_ASYNC_MARKER_SGIX"/>
+                <command name="glAsyncMarkerSGIX"/>
+                <command name="glFinishAsyncSGIX"/>
+                <command name="glPollAsyncSGIX"/>
+                <command name="glGenAsyncMarkersSGIX"/>
+                <command name="glDeleteAsyncMarkersSGIX"/>
+                <command name="glIsAsyncMarkerSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_async_histogram" supported="gl">
+            <require>
+                <enum name="GL_ASYNC_HISTOGRAM_SGIX"/>
+                <enum name="GL_MAX_ASYNC_HISTOGRAM_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_async_pixel" supported="gl">
+            <require>
+                <enum name="GL_ASYNC_TEX_IMAGE_SGIX"/>
+                <enum name="GL_ASYNC_DRAW_PIXELS_SGIX"/>
+                <enum name="GL_ASYNC_READ_PIXELS_SGIX"/>
+                <enum name="GL_MAX_ASYNC_TEX_IMAGE_SGIX"/>
+                <enum name="GL_MAX_ASYNC_DRAW_PIXELS_SGIX"/>
+                <enum name="GL_MAX_ASYNC_READ_PIXELS_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_blend_alpha_minmax" supported="gl">
+            <require>
+                <enum name="GL_ALPHA_MIN_SGIX"/>
+                <enum name="GL_ALPHA_MAX_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_calligraphic_fragment" supported="gl">
+            <require>
+                <enum name="GL_CALLIGRAPHIC_FRAGMENT_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_clipmap" supported="gl">
+            <require>
+                <enum name="GL_LINEAR_CLIPMAP_LINEAR_SGIX"/>
+                <enum name="GL_TEXTURE_CLIPMAP_CENTER_SGIX"/>
+                <enum name="GL_TEXTURE_CLIPMAP_FRAME_SGIX"/>
+                <enum name="GL_TEXTURE_CLIPMAP_OFFSET_SGIX"/>
+                <enum name="GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX"/>
+                <enum name="GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX"/>
+                <enum name="GL_TEXTURE_CLIPMAP_DEPTH_SGIX"/>
+                <enum name="GL_MAX_CLIPMAP_DEPTH_SGIX"/>
+                <enum name="GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX"/>
+                <enum name="GL_NEAREST_CLIPMAP_NEAREST_SGIX"/>
+                <enum name="GL_NEAREST_CLIPMAP_LINEAR_SGIX"/>
+                <enum name="GL_LINEAR_CLIPMAP_NEAREST_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_convolution_accuracy" supported="gl">
+            <require>
+                <enum name="GL_CONVOLUTION_HINT_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_depth_pass_instrument" supported="gl"/>
+        <extension name="GL_SGIX_depth_texture" supported="gl">
+            <require>
+                <enum name="GL_DEPTH_COMPONENT16_SGIX"/>
+                <enum name="GL_DEPTH_COMPONENT24_SGIX"/>
+                <enum name="GL_DEPTH_COMPONENT32_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_flush_raster" supported="gl">
+            <require>
+                <command name="glFlushRasterSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_fog_offset" supported="gl">
+            <require>
+                <enum name="GL_FOG_OFFSET_SGIX"/>
+                <enum name="GL_FOG_OFFSET_VALUE_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_fragment_lighting" supported="gl" comment="Incomplete extension">
+            <require>
+                <enum name="GL_FRAGMENT_LIGHTING_SGIX"/>
+                <enum name="GL_FRAGMENT_COLOR_MATERIAL_SGIX"/>
+                <enum name="GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX"/>
+                <enum name="GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX"/>
+                <enum name="GL_MAX_FRAGMENT_LIGHTS_SGIX"/>
+                <enum name="GL_MAX_ACTIVE_LIGHTS_SGIX"/>
+                <enum name="GL_CURRENT_RASTER_NORMAL_SGIX"/>
+                <enum name="GL_LIGHT_ENV_MODE_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT0_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT1_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT2_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT3_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT4_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT5_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT6_SGIX"/>
+                <enum name="GL_FRAGMENT_LIGHT7_SGIX"/>
+                <command name="glFragmentColorMaterialSGIX"/>
+                <command name="glFragmentLightfSGIX"/>
+                <command name="glFragmentLightfvSGIX"/>
+                <command name="glFragmentLightiSGIX"/>
+                <command name="glFragmentLightivSGIX"/>
+                <command name="glFragmentLightModelfSGIX"/>
+                <command name="glFragmentLightModelfvSGIX"/>
+                <command name="glFragmentLightModeliSGIX"/>
+                <command name="glFragmentLightModelivSGIX"/>
+                <command name="glFragmentMaterialfSGIX"/>
+                <command name="glFragmentMaterialfvSGIX"/>
+                <command name="glFragmentMaterialiSGIX"/>
+                <command name="glFragmentMaterialivSGIX"/>
+                <command name="glGetFragmentLightfvSGIX"/>
+                <command name="glGetFragmentLightivSGIX"/>
+                <command name="glGetFragmentMaterialfvSGIX"/>
+                <command name="glGetFragmentMaterialivSGIX"/>
+                <command name="glLightEnviSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_framezoom" supported="gl">
+            <require>
+                <enum name="GL_FRAMEZOOM_SGIX"/>
+                <enum name="GL_FRAMEZOOM_FACTOR_SGIX"/>
+                <enum name="GL_MAX_FRAMEZOOM_FACTOR_SGIX"/>
+                <command name="glFrameZoomSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_igloo_interface" supported="gl">
+            <require>
+                <command name="glIglooInterfaceSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_instruments" supported="gl">
+            <require>
+                <enum name="GL_INSTRUMENT_BUFFER_POINTER_SGIX"/>
+                <enum name="GL_INSTRUMENT_MEASUREMENTS_SGIX"/>
+                <command name="glGetInstrumentsSGIX"/>
+                <command name="glInstrumentsBufferSGIX"/>
+                <command name="glPollInstrumentsSGIX"/>
+                <command name="glReadInstrumentsSGIX"/>
+                <command name="glStartInstrumentsSGIX"/>
+                <command name="glStopInstrumentsSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_interlace" supported="gl">
+            <require>
+                <enum name="GL_INTERLACE_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_ir_instrument1" supported="gl">
+            <require>
+                <enum name="GL_IR_INSTRUMENT1_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_list_priority" supported="gl">
+            <require>
+                <enum name="GL_LIST_PRIORITY_SGIX"/>
+                <command name="glGetListParameterfvSGIX"/>
+                <command name="glGetListParameterivSGIX"/>
+                <command name="glListParameterfSGIX"/>
+                <command name="glListParameterfvSGIX"/>
+                <command name="glListParameteriSGIX"/>
+                <command name="glListParameterivSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_pixel_texture" supported="gl">
+            <require>
+                <enum name="GL_PIXEL_TEX_GEN_SGIX"/>
+                <enum name="GL_PIXEL_TEX_GEN_MODE_SGIX"/>
+                <command name="glPixelTexGenSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_pixel_tiles" supported="gl">
+            <require>
+                <enum name="GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX"/>
+                <enum name="GL_PIXEL_TILE_CACHE_INCREMENT_SGIX"/>
+                <enum name="GL_PIXEL_TILE_WIDTH_SGIX"/>
+                <enum name="GL_PIXEL_TILE_HEIGHT_SGIX"/>
+                <enum name="GL_PIXEL_TILE_GRID_WIDTH_SGIX"/>
+                <enum name="GL_PIXEL_TILE_GRID_HEIGHT_SGIX"/>
+                <enum name="GL_PIXEL_TILE_GRID_DEPTH_SGIX"/>
+                <enum name="GL_PIXEL_TILE_CACHE_SIZE_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_polynomial_ffd" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_DEFORMATION_BIT_SGIX"/>
+                <enum name="GL_GEOMETRY_DEFORMATION_BIT_SGIX"/>
+                <enum name="GL_GEOMETRY_DEFORMATION_SGIX"/>
+                <enum name="GL_TEXTURE_DEFORMATION_SGIX"/>
+                <enum name="GL_DEFORMATIONS_MASK_SGIX"/>
+                <enum name="GL_MAX_DEFORMATION_ORDER_SGIX"/>
+                <command name="glDeformationMap3dSGIX"/>
+                <command name="glDeformationMap3fSGIX"/>
+                <command name="glDeformSGIX"/>
+                <command name="glLoadIdentityDeformationMapSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_reference_plane" supported="gl">
+            <require>
+                <enum name="GL_REFERENCE_PLANE_SGIX"/>
+                <enum name="GL_REFERENCE_PLANE_EQUATION_SGIX"/>
+                <command name="glReferencePlaneSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_resample" supported="gl">
+            <require>
+                <enum name="GL_PACK_RESAMPLE_SGIX"/>
+                <enum name="GL_UNPACK_RESAMPLE_SGIX"/>
+                <enum name="GL_RESAMPLE_REPLICATE_SGIX"/>
+                <enum name="GL_RESAMPLE_ZERO_FILL_SGIX"/>
+                <enum name="GL_RESAMPLE_DECIMATE_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_scalebias_hint" supported="gl">
+            <require>
+                <enum name="GL_SCALEBIAS_HINT_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_shadow" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_COMPARE_SGIX"/>
+                <enum name="GL_TEXTURE_COMPARE_OPERATOR_SGIX"/>
+                <enum name="GL_TEXTURE_LEQUAL_R_SGIX"/>
+                <enum name="GL_TEXTURE_GEQUAL_R_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_shadow_ambient" supported="gl">
+            <require>
+                <enum name="GL_SHADOW_AMBIENT_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_sprite" supported="gl">
+            <require>
+                <enum name="GL_SPRITE_SGIX"/>
+                <enum name="GL_SPRITE_MODE_SGIX"/>
+                <enum name="GL_SPRITE_AXIS_SGIX"/>
+                <enum name="GL_SPRITE_TRANSLATION_SGIX"/>
+                <enum name="GL_SPRITE_AXIAL_SGIX"/>
+                <enum name="GL_SPRITE_OBJECT_ALIGNED_SGIX"/>
+                <enum name="GL_SPRITE_EYE_ALIGNED_SGIX"/>
+                <command name="glSpriteParameterfSGIX"/>
+                <command name="glSpriteParameterfvSGIX"/>
+                <command name="glSpriteParameteriSGIX"/>
+                <command name="glSpriteParameterivSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_subsample" supported="gl">
+            <require>
+                <enum name="GL_PACK_SUBSAMPLE_RATE_SGIX"/>
+                <enum name="GL_UNPACK_SUBSAMPLE_RATE_SGIX"/>
+                <enum name="GL_PIXEL_SUBSAMPLE_4444_SGIX"/>
+                <enum name="GL_PIXEL_SUBSAMPLE_2424_SGIX"/>
+                <enum name="GL_PIXEL_SUBSAMPLE_4242_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_tag_sample_buffer" supported="gl">
+            <require>
+                <command name="glTagSampleBufferSGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_texture_add_env" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_ENV_BIAS_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_texture_coordinate_clamp" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_MAX_CLAMP_S_SGIX"/>
+                <enum name="GL_TEXTURE_MAX_CLAMP_T_SGIX"/>
+                <enum name="GL_TEXTURE_MAX_CLAMP_R_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_texture_lod_bias" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_LOD_BIAS_S_SGIX"/>
+                <enum name="GL_TEXTURE_LOD_BIAS_T_SGIX"/>
+                <enum name="GL_TEXTURE_LOD_BIAS_R_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_texture_multi_buffer" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_MULTI_BUFFER_HINT_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_texture_scale_bias" supported="gl">
+            <require>
+                <enum name="GL_POST_TEXTURE_FILTER_BIAS_SGIX"/>
+                <enum name="GL_POST_TEXTURE_FILTER_SCALE_SGIX"/>
+                <enum name="GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX"/>
+                <enum name="GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_vertex_preclip" supported="gl">
+            <require>
+                <enum name="GL_VERTEX_PRECLIP_SGIX"/>
+                <enum name="GL_VERTEX_PRECLIP_HINT_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_ycrcb" supported="gl">
+            <require>
+                <enum name="GL_YCRCB_422_SGIX"/>
+                <enum name="GL_YCRCB_444_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGIX_ycrcb_subsample" supported="gl"/>
+        <extension name="GL_SGIX_ycrcba" supported="gl">
+            <require>
+                <enum name="GL_YCRCB_SGIX"/>
+                <enum name="GL_YCRCBA_SGIX"/>
+            </require>
+        </extension>
+        <extension name="GL_SGI_color_matrix" supported="gl">
+            <require>
+                <enum name="GL_COLOR_MATRIX_SGI"/>
+                <enum name="GL_COLOR_MATRIX_STACK_DEPTH_SGI"/>
+                <enum name="GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI"/>
+                <enum name="GL_POST_COLOR_MATRIX_RED_SCALE_SGI"/>
+                <enum name="GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI"/>
+                <enum name="GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI"/>
+                <enum name="GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI"/>
+                <enum name="GL_POST_COLOR_MATRIX_RED_BIAS_SGI"/>
+                <enum name="GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI"/>
+                <enum name="GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI"/>
+                <enum name="GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI"/>
+            </require>
+        </extension>
+        <extension name="GL_SGI_color_table" supported="gl">
+            <require>
+                <enum name="GL_COLOR_TABLE_SGI"/>
+                <enum name="GL_POST_CONVOLUTION_COLOR_TABLE_SGI"/>
+                <enum name="GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI"/>
+                <enum name="GL_PROXY_COLOR_TABLE_SGI"/>
+                <enum name="GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI"/>
+                <enum name="GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI"/>
+                <enum name="GL_COLOR_TABLE_SCALE_SGI"/>
+                <enum name="GL_COLOR_TABLE_BIAS_SGI"/>
+                <enum name="GL_COLOR_TABLE_FORMAT_SGI"/>
+                <enum name="GL_COLOR_TABLE_WIDTH_SGI"/>
+                <enum name="GL_COLOR_TABLE_RED_SIZE_SGI"/>
+                <enum name="GL_COLOR_TABLE_GREEN_SIZE_SGI"/>
+                <enum name="GL_COLOR_TABLE_BLUE_SIZE_SGI"/>
+                <enum name="GL_COLOR_TABLE_ALPHA_SIZE_SGI"/>
+                <enum name="GL_COLOR_TABLE_LUMINANCE_SIZE_SGI"/>
+                <enum name="GL_COLOR_TABLE_INTENSITY_SIZE_SGI"/>
+                <command name="glColorTableSGI"/>
+                <command name="glColorTableParameterfvSGI"/>
+                <command name="glColorTableParameterivSGI"/>
+                <command name="glCopyColorTableSGI"/>
+                <command name="glGetColorTableSGI"/>
+                <command name="glGetColorTableParameterfvSGI"/>
+                <command name="glGetColorTableParameterivSGI"/>
+            </require>
+        </extension>
+        <extension name="GL_SGI_texture_color_table" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_COLOR_TABLE_SGI"/>
+                <enum name="GL_PROXY_TEXTURE_COLOR_TABLE_SGI"/>
+            </require>
+        </extension>
+        <extension name="GL_SUNX_constant_data" supported="gl">
+            <require>
+                <enum name="GL_UNPACK_CONSTANT_DATA_SUNX"/>
+                <enum name="GL_TEXTURE_CONSTANT_DATA_SUNX"/>
+                <command name="glFinishTextureSUNX"/>
+            </require>
+        </extension>
+        <extension name="GL_SUN_convolution_border_modes" supported="gl">
+            <require>
+                <enum name="GL_WRAP_BORDER_SUN"/>
+            </require>
+        </extension>
+        <extension name="GL_SUN_global_alpha" supported="gl">
+            <require>
+                <enum name="GL_GLOBAL_ALPHA_SUN"/>
+                <enum name="GL_GLOBAL_ALPHA_FACTOR_SUN"/>
+                <command name="glGlobalAlphaFactorbSUN"/>
+                <command name="glGlobalAlphaFactorsSUN"/>
+                <command name="glGlobalAlphaFactoriSUN"/>
+                <command name="glGlobalAlphaFactorfSUN"/>
+                <command name="glGlobalAlphaFactordSUN"/>
+                <command name="glGlobalAlphaFactorubSUN"/>
+                <command name="glGlobalAlphaFactorusSUN"/>
+                <command name="glGlobalAlphaFactoruiSUN"/>
+            </require>
+        </extension>
+        <extension name="GL_SUN_mesh_array" supported="gl">
+            <require>
+                <enum name="GL_QUAD_MESH_SUN"/>
+                <enum name="GL_TRIANGLE_MESH_SUN"/>
+                <command name="glDrawMeshArraysSUN"/>
+            </require>
+        </extension>
+        <extension name="GL_SUN_slice_accum" supported="gl">
+            <require>
+                <enum name="GL_SLICE_ACCUM_SUN"/>
+            </require>
+        </extension>
+        <extension name="GL_SUN_triangle_list" supported="gl">
+            <require>
+                <enum name="GL_RESTART_SUN"/>
+                <enum name="GL_REPLACE_MIDDLE_SUN"/>
+                <enum name="GL_REPLACE_OLDEST_SUN"/>
+                <enum name="GL_TRIANGLE_LIST_SUN"/>
+                <enum name="GL_REPLACEMENT_CODE_SUN"/>
+                <enum name="GL_REPLACEMENT_CODE_ARRAY_SUN"/>
+                <enum name="GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN"/>
+                <enum name="GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN"/>
+                <enum name="GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN"/>
+                <enum name="GL_R1UI_V3F_SUN"/>
+                <enum name="GL_R1UI_C4UB_V3F_SUN"/>
+                <enum name="GL_R1UI_C3F_V3F_SUN"/>
+                <enum name="GL_R1UI_N3F_V3F_SUN"/>
+                <enum name="GL_R1UI_C4F_N3F_V3F_SUN"/>
+                <enum name="GL_R1UI_T2F_V3F_SUN"/>
+                <enum name="GL_R1UI_T2F_N3F_V3F_SUN"/>
+                <enum name="GL_R1UI_T2F_C4F_N3F_V3F_SUN"/>
+                <command name="glReplacementCodeuiSUN"/>
+                <command name="glReplacementCodeusSUN"/>
+                <command name="glReplacementCodeubSUN"/>
+                <command name="glReplacementCodeuivSUN"/>
+                <command name="glReplacementCodeusvSUN"/>
+                <command name="glReplacementCodeubvSUN"/>
+                <command name="glReplacementCodePointerSUN"/>
+            </require>
+        </extension>
+        <extension name="GL_SUN_vertex" supported="gl">
+            <require>
+                <command name="glColor4ubVertex2fSUN"/>
+                <command name="glColor4ubVertex2fvSUN"/>
+                <command name="glColor4ubVertex3fSUN"/>
+                <command name="glColor4ubVertex3fvSUN"/>
+                <command name="glColor3fVertex3fSUN"/>
+                <command name="glColor3fVertex3fvSUN"/>
+                <command name="glNormal3fVertex3fSUN"/>
+                <command name="glNormal3fVertex3fvSUN"/>
+                <command name="glColor4fNormal3fVertex3fSUN"/>
+                <command name="glColor4fNormal3fVertex3fvSUN"/>
+                <command name="glTexCoord2fVertex3fSUN"/>
+                <command name="glTexCoord2fVertex3fvSUN"/>
+                <command name="glTexCoord4fVertex4fSUN"/>
+                <command name="glTexCoord4fVertex4fvSUN"/>
+                <command name="glTexCoord2fColor4ubVertex3fSUN"/>
+                <command name="glTexCoord2fColor4ubVertex3fvSUN"/>
+                <command name="glTexCoord2fColor3fVertex3fSUN"/>
+                <command name="glTexCoord2fColor3fVertex3fvSUN"/>
+                <command name="glTexCoord2fNormal3fVertex3fSUN"/>
+                <command name="glTexCoord2fNormal3fVertex3fvSUN"/>
+                <command name="glTexCoord2fColor4fNormal3fVertex3fSUN"/>
+                <command name="glTexCoord2fColor4fNormal3fVertex3fvSUN"/>
+                <command name="glTexCoord4fColor4fNormal3fVertex4fSUN"/>
+                <command name="glTexCoord4fColor4fNormal3fVertex4fvSUN"/>
+                <command name="glReplacementCodeuiVertex3fSUN"/>
+                <command name="glReplacementCodeuiVertex3fvSUN"/>
+                <command name="glReplacementCodeuiColor4ubVertex3fSUN"/>
+                <command name="glReplacementCodeuiColor4ubVertex3fvSUN"/>
+                <command name="glReplacementCodeuiColor3fVertex3fSUN"/>
+                <command name="glReplacementCodeuiColor3fVertex3fvSUN"/>
+                <command name="glReplacementCodeuiNormal3fVertex3fSUN"/>
+                <command name="glReplacementCodeuiNormal3fVertex3fvSUN"/>
+                <command name="glReplacementCodeuiColor4fNormal3fVertex3fSUN"/>
+                <command name="glReplacementCodeuiColor4fNormal3fVertex3fvSUN"/>
+                <command name="glReplacementCodeuiTexCoord2fVertex3fSUN"/>
+                <command name="glReplacementCodeuiTexCoord2fVertex3fvSUN"/>
+                <command name="glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN"/>
+                <command name="glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN"/>
+                <command name="glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN"/>
+                <command name="glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN"/>
+            </require>
+        </extension>
+        <extension name="GL_VIV_shader_binary" supported="gles2">
+            <require>
+                <enum name="GL_SHADER_BINARY_VIV"/>
+            </require>
+        </extension>
+        <extension name="GL_WIN_phong_shading" supported="gl">
+            <require>
+                <enum name="GL_PHONG_WIN"/>
+                <enum name="GL_PHONG_HINT_WIN"/>
+            </require>
+        </extension>
+        <extension name="GL_WIN_specular_fog" supported="gl">
+            <require>
+                <enum name="GL_FOG_SPECULAR_TEXTURE_WIN"/>
+            </require>
+        </extension>
+    </extensions>
+</registry>
diff --git a/src/third_party/angle/scripts/perf_test_runner.py b/src/third_party/angle/scripts/perf_test_runner.py
new file mode 100644
index 0000000..3e896b3
--- /dev/null
+++ b/src/third_party/angle/scripts/perf_test_runner.py
@@ -0,0 +1,141 @@
+#!/usr/bin/python
+#
+# Copyright 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# perf_test_runner.py:
+#   Helper script for running and analyzing perftest results. Runs the
+#   tests in an infinite batch, printing out the mean and standard
+#   deviation of the population continuously.
+#
+
+import subprocess
+import sys
+import os
+import re
+
+base_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
+
+# You might have to re-order these to find the specific version you want.
+perftests_paths = [
+    os.path.join('src', 'tests', 'Release_x64'),
+    os.path.join('src', 'tests', 'Release_Win32'),
+    os.path.join('out', 'Release_x64'),
+    os.path.join('out', 'Release'),
+    os.path.join('gyp', 'Release_x64'),
+    os.path.join('gyp', 'Release_Win32')
+]
+metric = 'score'
+
+binary_name = 'angle_perftests'
+if sys.platform == 'win32':
+    binary_name += '.exe'
+
+scores = []
+
+# Danke to http://stackoverflow.com/a/27758326
+def mean(data):
+    """Return the sample arithmetic mean of data."""
+    n = len(data)
+    if n < 1:
+        raise ValueError('mean requires at least one data point')
+    return float(sum(data))/float(n) # in Python 2 use sum(data)/float(n)
+
+def _ss(data):
+    """Return sum of square deviations of sequence data."""
+    c = mean(data)
+    ss = sum((float(x)-c)**2 for x in data)
+    return ss
+
+def pstdev(data):
+    """Calculates the population standard deviation."""
+    n = len(data)
+    if n < 2:
+        raise ValueError('variance requires at least two data points')
+    ss = _ss(data)
+    pvar = ss/n # the population variance
+    return pvar**0.5
+
+def truncated_list(data, n):
+    """Compute a truncated list, n is truncation size"""
+    if len(data) < n * 2:
+        raise ValueError('list not large enough to truncate')
+    return sorted(data)[n:-n]
+
+def truncated_mean(data, n):
+    return mean(truncated_list(data, n))
+
+def truncated_stddev(data, n):
+    return pstdev(truncated_list(data, n))
+
+# Find most recent binary
+newest_binary = None
+newest_mtime = None
+
+for path in perftests_paths:
+    binary_path = os.path.join(base_path, path, binary_name)
+    if os.path.exists(binary_path):
+        binary_mtime = os.path.getmtime(binary_path)
+        if (newest_binary is None) or (binary_mtime > newest_mtime):
+            newest_binary = binary_path
+            newest_mtime = binary_mtime
+
+perftests_path = newest_binary
+
+if perftests_path == None or not os.path.exists(perftests_path):
+    print('Cannot find Release %s!' % binary_name)
+    sys.exit(1)
+
+if sys.platform == 'win32':
+    test_name = 'DrawCallPerfBenchmark.Run/d3d11_null'
+else:
+    test_name = 'DrawCallPerfBenchmark.Run/gl'
+
+if len(sys.argv) >= 2:
+    test_name = sys.argv[1]
+
+print('Using test executable: ' + perftests_path)
+print('Test name: ' + test_name)
+
+# Infinite loop of running the tests.
+while True:
+    output = subprocess.check_output([perftests_path, '--gtest_filter=' + test_name])
+
+    start_index = output.find(metric + "=")
+    if start_index == -1:
+        print("Did not find the score of the specified test in output:")
+        print(output)
+        sys.exit(1)
+
+    start_index += len(metric) + 2
+
+    end_index = output[start_index:].find(" ")
+    if end_index == -1:
+        print("Error parsing output:")
+        print(output)
+        sys.exit(2)
+
+    m = re.search('Running (\d+) tests', output)
+    if m and int(m.group(1)) > 1:
+        print("Found more than one test result in output:")
+        print(output)
+        sys.exit(3)
+
+    end_index += start_index
+
+    score = int(output[start_index:end_index])
+    sys.stdout.write("score: " + str(score))
+
+    scores.append(score)
+    sys.stdout.write(", mean: " + str(mean(scores)))
+
+    if (len(scores) > 1):
+        sys.stdout.write(", stddev: " + str(pstdev(scores)))
+
+    if (len(scores) > 7):
+        trucation_n = len(scores) >> 3
+        sys.stdout.write(", truncated mean: " + str(truncated_mean(scores, trucation_n)))
+        sys.stdout.write(", stddev: " + str(truncated_stddev(scores, trucation_n)))
+
+    print("")
diff --git a/src/third_party/angle/scripts/update_canary_angle.py b/src/third_party/angle/scripts/update_canary_angle.py
new file mode 100644
index 0000000..51a0359
--- /dev/null
+++ b/src/third_party/angle/scripts/update_canary_angle.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+#
+# Copyright 2016 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.
+#
+# update_canary_angle.py:
+#   Helper script that copies Windows ANGLE DLLs into the Canary
+#   application directory. Much faster than compiling Chrome from
+#   source. The script checks for the most recent DLLs in a set of
+#   search paths, and copies that into the most recent Canary
+#   binary folder. Only works on Windows.
+
+import sys, os, shutil
+
+# Set of search paths.
+source_paths = [
+    os.path.join('..', 'gyp', 'Debug_x64'),
+    os.path.join('..', 'gyp', 'Debug_Win32'),
+    os.path.join('..', 'gyp', 'Release_x64'),
+    os.path.join('..', 'gyp', 'Release_Win32'),
+    os.path.join('..', 'out', 'Debug'),
+    os.path.join('..', 'out', 'Debug_x64'),
+    os.path.join('..', 'out', 'Release'),
+    os.path.join('..', 'out', 'Release_x64'),
+]
+
+script_dir = os.path.dirname(sys.argv[0])
+
+# Default Canary installation path.
+chrome_folder = os.path.join(os.environ['LOCALAPPDATA'], 'Google', 'Chrome SxS', 'Application')
+
+# Find the most recent ANGLE DLLs
+binary_name = 'libGLESv2.dll'
+newest_folder = None
+newest_mtime = None
+for path in source_paths:
+    binary_path = os.path.join(script_dir, path, binary_name)
+    if os.path.exists(binary_path):
+        binary_mtime = os.path.getmtime(binary_path)
+        if (newest_folder is None) or (binary_mtime > newest_mtime):
+            newest_folder = os.path.join(script_dir, path)
+            newest_mtime = binary_mtime
+
+if newest_folder is None:
+    sys.exit("Could not find ANGLE DLLs!")
+
+source_folder = newest_folder
+
+# Is a folder a chrome binary directory?
+def is_chrome_bin(str):
+    chrome_file = os.path.join(chrome_folder, str)
+    return os.path.isdir(chrome_file) and all([char.isdigit() or char == '.' for char in str])
+
+sorted_chrome_bins = sorted([folder for folder in os.listdir(chrome_folder) if is_chrome_bin(folder)], reverse=True)
+
+dest_folder = os.path.join(chrome_folder, sorted_chrome_bins[0])
+
+print('Copying DLLs from ' + source_folder + ' to ' + dest_folder + '.')
+
+for dll in ['libGLESv2.dll', 'libEGL.dll']:
+    src = os.path.join(source_folder, dll)
+    if os.path.exists(src):
+        # Make a backup of the original unmodified DLLs if they are present.
+        backup = os.path.join(source_folder, dll + '.backup')
+        if not os.path.exists(backup):
+            shutil.copyfile(src, backup)
+        shutil.copyfile(src, os.path.join(dest_folder, dll))
diff --git a/src/third_party/angle/src/ANGLE.sln b/src/third_party/angle/src/ANGLE.sln
deleted file mode 100644
index 81c1382..0000000
--- a/src/third_party/angle/src/ANGLE.sln
+++ /dev/null
@@ -1,66 +0,0 @@
-

-Microsoft Visual Studio Solution File, Format Version 11.00

-# Visual C++ Express 2010

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libEGL", "libEGL\libEGL.vcxproj", "{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libGLESv2", "libGLESv2\libGLESv2.vcxproj", "{B5871A7A-968C-42E3-A33B-981E6F448E78}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "translator_hlsl", "compiler\translator_hlsl.vcxproj", "{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "translator_common", "compiler\translator_common.vcxproj", "{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}"

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "preprocessor", "compiler\preprocessor\preprocessor.vcxproj", "{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}"

-EndProject

-Global

-	GlobalSection(SolutionConfigurationPlatforms) = preSolution

-		Debug|Win32 = Debug|Win32

-		Debug|x64 = Debug|x64

-		Release|Win32 = Release|Win32

-		Release|x64 = Release|x64

-	EndGlobalSection

-	GlobalSection(ProjectConfigurationPlatforms) = postSolution

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|Win32.ActiveCfg = Debug|Win32

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|Win32.Build.0 = Debug|Win32

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|x64.ActiveCfg = Debug|x64

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|x64.Build.0 = Debug|x64

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|Win32.ActiveCfg = Release|Win32

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|Win32.Build.0 = Release|Win32

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|x64.ActiveCfg = Release|x64

-		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|x64.Build.0 = Release|x64

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|Win32.ActiveCfg = Debug|Win32

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|Win32.Build.0 = Debug|Win32

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|x64.ActiveCfg = Debug|x64

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|x64.Build.0 = Debug|x64

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|Win32.ActiveCfg = Release|Win32

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|Win32.Build.0 = Release|Win32

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|x64.ActiveCfg = Release|x64

-		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|x64.Build.0 = Release|x64

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|Win32.ActiveCfg = Debug|Win32

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|Win32.Build.0 = Debug|Win32

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|x64.ActiveCfg = Debug|x64

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Debug|x64.Build.0 = Debug|x64

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|Win32.ActiveCfg = Release|Win32

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|Win32.Build.0 = Release|Win32

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|x64.ActiveCfg = Release|x64

-		{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}.Release|x64.Build.0 = Release|x64

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.ActiveCfg = Debug|Win32

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.Build.0 = Debug|Win32

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|x64.ActiveCfg = Debug|x64

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|x64.Build.0 = Debug|x64

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.ActiveCfg = Release|Win32

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.Build.0 = Release|Win32

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|x64.ActiveCfg = Release|x64

-		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|x64.Build.0 = Release|x64

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|Win32.ActiveCfg = Debug|Win32

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|Win32.Build.0 = Debug|Win32

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|x64.ActiveCfg = Debug|x64

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Debug|x64.Build.0 = Debug|x64

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|Win32.ActiveCfg = Release|Win32

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|Win32.Build.0 = Release|Win32

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|x64.ActiveCfg = Release|x64

-		{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}.Release|x64.Build.0 = Release|x64

-	EndGlobalSection

-	GlobalSection(SolutionProperties) = preSolution

-		HideSolutionNode = FALSE

-	EndGlobalSection

-EndGlobal

diff --git a/src/third_party/angle/src/angle.gyp b/src/third_party/angle/src/angle.gyp
new file mode 100644
index 0000000..e2b0f9b
--- /dev/null
+++ b/src/third_party/angle/src/angle.gyp
@@ -0,0 +1,476 @@
+# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'variables':
+    {
+        'angle_code': 1,
+        'angle_gen_path': '<(SHARED_INTERMEDIATE_DIR)/angle',
+        'angle_id_script_base': 'commit_id.py',
+        'angle_id_script': '<(angle_gen_path)/<(angle_id_script_base)',
+        'angle_id_header_base': 'commit.h',
+        'angle_id_header': '<(angle_gen_path)/id/<(angle_id_header_base)',
+        'angle_use_commit_id%': '<!(python <(angle_id_script_base) check ..)',
+        'angle_enable_d3d9%': 0,
+        'angle_enable_d3d11%': 0,
+        'angle_enable_gl%': 0,
+        'angle_enable_vulkan%': 0,
+        'angle_enable_essl%': 1, # Enable this for all configs by default
+        'angle_enable_glsl%': 1, # Enable this for all configs by default
+        'angle_enable_hlsl%': 0,
+        'angle_link_glx%': 0,
+        'angle_gl_library_type%': 'shared_library',
+        'dcheck_always_on%': 0,
+        'conditions':
+        [
+            ['OS=="win"',
+            {
+                'angle_enable_gl%': 1,
+                'angle_enable_d3d9%': 1,
+                'angle_enable_d3d11%': 1,
+                'angle_enable_hlsl%': 1,
+                'angle_enable_vulkan%': 1,
+            }],
+            ['OS=="linux" and use_x11==1 and chromeos==0',
+            {
+                'angle_enable_gl%': 1,
+                'angle_enable_vulkan%': 1,
+            }],
+            ['OS=="mac"',
+            {
+                'angle_enable_gl%': 1,
+            }],
+            ['use_ozone==1',
+            {
+                'angle_enable_gl%': 1,
+            }],
+        ],
+        'angle_enable_null%': 1, # Available on all platforms
+    },
+    'includes':
+    [
+        'compiler.gypi',
+        'libGLESv2.gypi',
+        'libEGL.gypi',
+        'vulkan_support/vulkan.gypi',
+    ],
+
+    'targets':
+    [
+        {
+            'target_name': 'angle_common',
+            'type': 'static_library',
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources':
+            [
+                '<@(libangle_common_sources)',
+            ],
+            'include_dirs':
+            [
+                '.',
+                '../include',
+                'common/third_party/numerics',
+            ],
+            'dependencies':
+            [
+                'commit_id',
+            ],
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(angle_path)/include',
+                    '<(angle_path)/src',
+                    '<(angle_path)/src/common/third_party/numerics',
+                ],
+                'conditions':
+                [
+                    ['dcheck_always_on==1',
+                    {
+                        'configurations':
+                        {
+                            'Release_Base':
+                            {
+                                'defines':
+                                [
+                                    'ANGLE_ENABLE_RELEASE_ASSERTS',
+                                ],
+                            },
+                        },
+                    }],
+                    ['OS=="win"',
+                    {
+                        'configurations':
+                        {
+                            'Debug_Base':
+                            {
+                                'defines':
+                                [
+                                    'ANGLE_ENABLE_DEBUG_ANNOTATIONS'
+                                ],
+                            },
+                        },
+                    }],
+                ],
+            },
+            'conditions':
+            [
+                ['dcheck_always_on==1',
+                {
+                    'configurations':
+                    {
+                        'Release_Base':
+                        {
+                            'defines':
+                            [
+                                'ANGLE_ENABLE_RELEASE_ASSERTS',
+                            ],
+                        },
+                    },
+                }],
+                ['OS=="win"',
+                {
+                    'configurations':
+                    {
+                        'Debug_Base':
+                        {
+                            'defines':
+                            [
+                                'ANGLE_ENABLE_DEBUG_ANNOTATIONS'
+                            ],
+                        },
+                    },
+                    'sources':
+                    [
+                        '<@(libangle_common_win_sources)',
+                    ],
+                }],
+                ['OS=="mac"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_common_mac_sources)',
+                    ],
+                    'link_settings':
+                    {
+                        'libraries':
+                        [
+                            '$(SDKROOT)/System/Library/Frameworks/IOKit.framework',
+                            '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+                        ],
+                    },
+                }],
+                ['OS=="linux"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_common_linux_sources)',
+                    ],
+                }]
+            ],
+        },
+
+        {
+            'target_name': 'angle_image_util',
+            'type': 'static_library',
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources':
+            [
+                '<@(libangle_image_util_sources)',
+            ],
+            'include_dirs':
+            [
+                '.',
+                '../include',
+            ],
+            'dependencies':
+            [
+                'angle_common',
+            ],
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(angle_path)/include',
+                    '<(angle_path)/src',
+                ],
+            },
+        },
+
+        {
+            'target_name': 'angle_gpu_info_util',
+            'type': 'static_library',
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources':
+            [
+                '<@(libangle_gpu_info_util_sources)',
+            ],
+            'include_dirs':
+            [
+                '.',
+                '../include',
+            ],
+            'dependencies':
+            [
+                'angle_common',
+            ],
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(angle_path)/include',
+                    '<(angle_path)/src',
+                ],
+            },
+            'conditions':
+            [
+                ['OS=="win"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_win_sources)',
+                    ],
+                }],
+                ['OS=="win" and angle_build_winrt==0',
+                {
+                    'link_settings':
+                    {
+                        'msvs_settings':
+                        {
+                            'VCLinkerTool':
+                            {
+                                'AdditionalDependencies':
+                                [
+                                    'setupapi.lib'
+                                ]
+                            }
+                        }
+                    },
+                    'defines':
+                    [
+                        'GPU_INFO_USE_SETUPAPI',
+                    ],
+                },
+                {
+                    'link_settings':
+                    {
+                        'msvs_settings':
+                        {
+                            'VCLinkerTool':
+                            {
+                                'AdditionalDependencies':
+                                [
+                                    'dxgi.lib'
+                                ]
+                            }
+                        }
+                    },
+                    'defines':
+                    [
+                        'GPU_INFO_USE_DXGI',
+                    ],
+                }],
+                ['OS=="linux"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_linux_sources)',
+                    ],
+                }],
+                ['OS=="linux" and use_x11==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_x11_sources)',
+                    ],
+                    'defines':
+                    [
+                        'GPU_INFO_USE_X11',
+                    ],
+                    'dependencies':
+                    [
+                        '<(angle_path)/src/third_party/libXNVCtrl/libXNVCtrl.gyp:libXNVCtrl',
+                    ],
+                    'link_settings':
+                    {
+                        'ldflags':
+                        [
+                            '<!@(<(pkg-config) --libs-only-L --libs-only-other x11 xi xext)',
+                        ],
+                        'libraries':
+                        [
+                            '<!@(<(pkg-config) --libs-only-l x11 xi xext) -ldl',
+                        ],
+                    },
+                }],
+                ['OS=="linux" and use_libpci==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_libpci_sources)',
+                    ],
+                    'defines':
+                    [
+                        'GPU_INFO_USE_LIBPCI',
+                    ],
+                    'link_settings':
+                    {
+                        'ldflags':
+                        [
+                            '<!@(<(pkg-config) --libs-only-L --libs-only-other libpci)',
+                        ],
+                        'libraries':
+                        [
+                            '<!@(<(pkg-config) --libs-only-l libpci)',
+                        ],
+                    },
+                }],
+                ['OS=="mac"',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gpu_info_util_mac_sources)',
+                    ],
+                }],
+            ],
+        },
+
+        {
+            'target_name': 'copy_scripts',
+            'type': 'none',
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'hard_dependency': 1,
+            'copies':
+            [
+                {
+                    'destination': '<(angle_gen_path)',
+                    'files': [ 'copy_compiler_dll.bat', '<(angle_id_script_base)' ],
+                },
+            ],
+            'conditions':
+            [
+                ['angle_build_winrt==1',
+                {
+                    'type' : 'shared_library',
+                }],
+            ],
+        },
+    ],
+    'conditions':
+    [
+        ['angle_use_commit_id!=0',
+        {
+            'targets':
+            [
+                {
+                    'target_name': 'commit_id',
+                    'type': 'none',
+                    'includes': [ '../gyp/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)'
+                            ],
+                        },
+                    ],
+                    'all_dependent_settings':
+                    {
+                        'include_dirs':
+                        [
+                            '<(angle_gen_path)',
+                        ],
+                    },
+                    'conditions':
+                    [
+                        ['angle_build_winrt==1',
+                        {
+                            'type' : 'shared_library',
+                        }],
+                    ],
+                }
+            ]
+        },
+        { # angle_use_commit_id==0
+            'targets':
+            [
+                {
+                    'target_name': 'commit_id',
+                    'type': 'none',
+                    'hard_dependency': 1,
+                    'includes': [ '../gyp/common_defines.gypi', ],
+                    'copies':
+                    [
+                        {
+                            'destination': '<(angle_gen_path)/id',
+                            'files': [ '<(angle_id_header_base)' ]
+                        }
+                    ],
+                    'all_dependent_settings':
+                    {
+                        'include_dirs':
+                        [
+                            '<(angle_gen_path)',
+                        ],
+                    },
+                    'conditions':
+                    [
+                        ['angle_build_winrt==1',
+                        {
+                            'type' : 'shared_library',
+                        }],
+                    ],
+                }
+            ]
+        }],
+        ['OS=="win"',
+        {
+            'targets':
+            [
+                {
+                    'target_name': 'copy_compiler_dll',
+                    'type': 'none',
+                    'dependencies': [ 'copy_scripts', ],
+                    'includes': [ '../gyp/common_defines.gypi', ],
+                    'conditions':
+                    [
+                        ['angle_build_winrt==0',
+                        {
+                            'actions':
+                            [
+                                {
+                                    'action_name': 'copy_dll',
+                                    'message': 'Copying D3D Compiler DLL...',
+                                    'msvs_cygwin_shell': 0,
+                                    'inputs': [ 'copy_compiler_dll.bat' ],
+                                    'outputs': [ '<(PRODUCT_DIR)/d3dcompiler_47.dll' ],
+                                    'action':
+                                    [
+                                        "<(angle_gen_path)/copy_compiler_dll.bat",
+                                        "$(PlatformName)",
+                                        "<(windows_sdk_path)",
+                                        "<(PRODUCT_DIR)"
+                                    ],
+                                },
+                            ], #actions
+                        }],
+                        ['angle_build_winrt==1',
+                        {
+                            'type' : 'shared_library',
+                        }],
+                    ]
+                },
+            ], # targets
+        }],
+    ] # conditions
+}
diff --git a/src/third_party/angle/src/build_angle.gyp b/src/third_party/angle/src/build_angle.gyp
deleted file mode 100644
index 6adf142..0000000
--- a/src/third_party/angle/src/build_angle.gyp
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'includes': [
-    'build_angle.gypi',
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/src/third_party/angle/src/build_angle.gypi b/src/third_party/angle/src/build_angle.gypi
deleted file mode 100644
index 8454a60..0000000
--- a/src/third_party/angle/src/build_angle.gypi
+++ /dev/null
@@ -1,625 +0,0 @@
-# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'variables': {
-    'angle_code': 1,
-    'angle_api%': 'undefined',
-    'conditions': [
-      ['OS=="win"', {'angle_api': 'win32',}],
-    ],
-  },
-  'target_defaults': {
-    'defines': [
-      'ANGLE_DISABLE_TRACE',
-      'ANGLE_DISABLE_PERF',
-      'ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ TEXT("d3dcompiler_46.dll"), TEXT("d3dcompiler_43.dll") }',
-    ],
-    'target_conditions': [
-      ['OS=="lb_shell"', {
-        'msvs_settings': {
-          'VCResourceCompilerTool': {
-            'PreprocessorDefinitions': [
-              'NOWINRES',
-            ],
-          },
-          'VCCLCompilerTool': {
-            'AdditionalOptions': [
-              '/EHsc',
-            ],
-          },
-        },
-      }],
-    ],
-  },
-  'targets': [
-    {
-      'target_name': 'preprocessor',
-      'type': 'static_library',
-      'include_dirs': [
-      ],
-      'sources': [
-        'compiler/preprocessor/DiagnosticsBase.cpp',
-        'compiler/preprocessor/DiagnosticsBase.h',
-        'compiler/preprocessor/DirectiveHandlerBase.cpp',
-        'compiler/preprocessor/DirectiveHandlerBase.h',
-        'compiler/preprocessor/DirectiveParser.cpp',
-        'compiler/preprocessor/DirectiveParser.h',
-        'compiler/preprocessor/ExpressionParser.cpp',
-        'compiler/preprocessor/ExpressionParser.h',
-        'compiler/preprocessor/Input.cpp',
-        'compiler/preprocessor/Input.h',
-        'compiler/preprocessor/length_limits.h',
-        'compiler/preprocessor/Lexer.cpp',
-        'compiler/preprocessor/Lexer.h',
-        'compiler/preprocessor/Macro.cpp',
-        'compiler/preprocessor/Macro.h',
-        'compiler/preprocessor/MacroExpander.cpp',
-        'compiler/preprocessor/MacroExpander.h',
-        'compiler/preprocessor/numeric_lex.h',
-        'compiler/preprocessor/pp_utils.h',
-        'compiler/preprocessor/Preprocessor.cpp',
-        'compiler/preprocessor/Preprocessor.h',
-        'compiler/preprocessor/SourceLocation.h',
-        'compiler/preprocessor/Token.cpp',
-        'compiler/preprocessor/Token.h',
-        'compiler/preprocessor/Tokenizer.cpp',
-        'compiler/preprocessor/Tokenizer.h',
-      ],
-      # TODO(jschuh): http://crbug.com/167187
-      'msvs_disabled_warnings': [
-        4267,
-      ],
-    },
-    {
-      'target_name': 'translator_common',
-      'type': 'static_library',
-      'dependencies': ['preprocessor'],
-      'include_dirs': [
-        '.',
-        '../include',
-      ],
-      'defines': [
-        'COMPILER_IMPLEMENTATION',
-      ],
-      'sources': [
-        'compiler/BaseTypes.h',
-        'compiler/BuiltInFunctionEmulator.cpp',
-        'compiler/BuiltInFunctionEmulator.h',
-        'compiler/Common.h',
-        'compiler/Compiler.cpp',
-        'compiler/ConstantUnion.h',
-        'compiler/debug.cpp',
-        'compiler/debug.h',
-        'compiler/DetectCallDepth.cpp',
-        'compiler/DetectCallDepth.h',
-        'compiler/Diagnostics.h',
-        'compiler/Diagnostics.cpp',
-        'compiler/DirectiveHandler.h',
-        'compiler/DirectiveHandler.cpp',
-        'compiler/ExtensionBehavior.h',
-        'compiler/ForLoopUnroll.cpp',
-        'compiler/ForLoopUnroll.h',
-        'compiler/glslang.h',
-        'compiler/glslang_lex.cpp',
-        'compiler/glslang_tab.cpp',
-        'compiler/glslang_tab.h',
-        'compiler/HashNames.h',
-        'compiler/InfoSink.cpp',
-        'compiler/InfoSink.h',
-        'compiler/Initialize.cpp',
-        'compiler/Initialize.h',
-        'compiler/InitializeDll.cpp',
-        'compiler/InitializeDll.h',
-        'compiler/InitializeGlobals.h',
-        'compiler/InitializeParseContext.cpp',
-        'compiler/InitializeParseContext.h',
-        'compiler/Intermediate.cpp',
-        'compiler/intermediate.h',
-        'compiler/intermOut.cpp',
-        'compiler/IntermTraverse.cpp',
-        'compiler/localintermediate.h',
-        'compiler/MapLongVariableNames.cpp',
-        'compiler/MapLongVariableNames.h',
-        'compiler/MMap.h',
-        'compiler/osinclude.h',
-        'compiler/parseConst.cpp',
-        'compiler/ParseHelper.cpp',
-        'compiler/ParseHelper.h',
-        'compiler/PoolAlloc.cpp',
-        'compiler/PoolAlloc.h',
-        'compiler/QualifierAlive.cpp',
-        'compiler/QualifierAlive.h',
-        'compiler/RemoveTree.cpp',
-        'compiler/RemoveTree.h',
-        'compiler/RenameFunction.h',
-        'compiler/ShHandle.h',
-        'compiler/SymbolTable.cpp',
-        'compiler/SymbolTable.h',
-        'compiler/Types.h',
-        'compiler/Uniform.cpp',
-        'compiler/Uniform.h',
-        'compiler/util.cpp',
-        'compiler/util.h',
-        'compiler/ValidateLimitations.cpp',
-        'compiler/ValidateLimitations.h',
-        'compiler/VariableInfo.cpp',
-        'compiler/VariableInfo.h',
-        'compiler/VariablePacker.cpp',
-        'compiler/VariablePacker.h',
-        # Dependency graph
-        'compiler/depgraph/DependencyGraph.cpp',
-        'compiler/depgraph/DependencyGraph.h',
-        'compiler/depgraph/DependencyGraphBuilder.cpp',
-        'compiler/depgraph/DependencyGraphBuilder.h',
-        'compiler/depgraph/DependencyGraphOutput.cpp',
-        'compiler/depgraph/DependencyGraphOutput.h',
-        'compiler/depgraph/DependencyGraphTraverse.cpp',
-        # Timing restrictions
-        'compiler/timing/RestrictFragmentShaderTiming.cpp',
-        'compiler/timing/RestrictFragmentShaderTiming.h',
-        'compiler/timing/RestrictVertexShaderTiming.cpp',
-        'compiler/timing/RestrictVertexShaderTiming.h',
-        'third_party/compiler/ArrayBoundsClamper.cpp',
-        'third_party/compiler/ArrayBoundsClamper.h',
-      ],
-      'conditions': [
-        ['OS=="win" or (OS=="lb_shell" and actual_target_arch=="win") or angle_api=="winrt"', {
-          # TODO(jschuh): http://crbug.com/167187 size_t -> int
-          'msvs_disabled_warnings': [ 4267 ],
-          'sources': ['compiler/ossource_win.cpp'],
-        }, { # else: posix
-          'sources': ['compiler/ossource_posix.cpp'],
-        }],
-      ],
-    },
-    {
-      'target_name': 'translator_glsl',
-      'type': '<(component)',
-      'dependencies': ['translator_common'],
-      'include_dirs': [
-        '.',
-        '../include',
-      ],
-      'defines': [
-        'COMPILER_IMPLEMENTATION',
-      ],
-      'sources': [
-        'compiler/CodeGenGLSL.cpp',
-        'compiler/OutputESSL.cpp',
-        'compiler/OutputESSL.h',
-        'compiler/OutputGLSLBase.cpp',
-        'compiler/OutputGLSLBase.h',
-        'compiler/OutputGLSL.cpp',
-        'compiler/OutputGLSL.h',
-        'compiler/ShaderLang.cpp',
-        'compiler/TranslatorESSL.cpp',
-        'compiler/TranslatorESSL.h',
-        'compiler/TranslatorGLSL.cpp',
-        'compiler/TranslatorGLSL.h',
-        'compiler/VersionGLSL.cpp',
-        'compiler/VersionGLSL.h',
-      ],
-      'conditions': [
-        ['OS=="lb_shell"', {
-          'dependencies': [
-            '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
-          ],
-        }],
-      ],
-      # TODO(jschuh): http://crbug.com/167187 size_t -> int
-      'msvs_disabled_warnings': [ 4267 ],
-    },
-  ],
-  'conditions': [
-    ['OS=="win" or (OS=="lb_shell" and actual_target_arch=="win") or angle_api in ("winrt", "xb360")', {
-      'targets': [
-        {
-          'target_name': 'translator_hlsl',
-          'type': '<(component)',
-          'dependencies': ['translator_common'],
-          'include_dirs': [
-            '.',
-            '../include',
-          ],
-          'defines': [
-            'COMPILER_IMPLEMENTATION',
-          ],
-          'sources': [
-            'compiler/ShaderLang.cpp',
-            'compiler/DetectDiscontinuity.cpp',
-            'compiler/DetectDiscontinuity.h',
-            'compiler/CodeGenHLSL.cpp',
-            'compiler/OutputHLSL.cpp',
-            'compiler/OutputHLSL.h',
-            'compiler/TranslatorHLSL.cpp',
-            'compiler/TranslatorHLSL.h',
-            'compiler/UnfoldShortCircuit.cpp',
-            'compiler/UnfoldShortCircuit.h',
-            'compiler/SearchSymbol.cpp',
-            'compiler/SearchSymbol.h',
-          ],
-          'conditions': [
-            ['OS=="lb_shell"', {
-              'dependencies': [
-                '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
-              ],
-            }],
-          ],
-          # TODO(jschuh): http://crbug.com/167187 size_t -> int
-          'msvs_disabled_warnings': [ 4267 ],
-        },
-        {
-          'target_name': 'libGLESv2',
-          'type': 'shared_library',
-          'dependencies': ['translator_hlsl'],
-          'include_dirs': [
-            '.',
-            '../include',
-            'libGLESv2',
-          ],
-          'sources': [
-            'third_party/murmurhash/MurmurHash3.h',
-            'third_party/murmurhash/MurmurHash3.cpp',
-            'common/angleutils.h',
-            'common/debug.cpp',
-            'common/debug.h',
-            'common/debugperf.h',
-            'common/RefCountObject.cpp',
-            'common/RefCountObject.h',
-            'common/system.h',
-            'common/version.h',
-            'common/windowutils.h',
-            'libGLESv2/angletypes.h',
-            'libGLESv2/BinaryStream.h',
-            'libGLESv2/Buffer.cpp',
-            'libGLESv2/Buffer.h',
-            'libGLESv2/constants.h',
-            'libGLESv2/Context.cpp',
-            'libGLESv2/Context.h',
-            'libGLESv2/Fence.cpp',
-            'libGLESv2/Fence.h',
-            'libGLESv2/Float16ToFloat32.cpp',
-            'libGLESv2/Framebuffer.cpp',
-            'libGLESv2/Framebuffer.h',
-            'libGLESv2/HandleAllocator.cpp',
-            'libGLESv2/HandleAllocator.h',
-            'libGLESv2/libGLESv2.cpp',
-            'libGLESv2/libGLESv2.def',
-            'libGLESv2/libGLESv2.rc',
-            'libGLESv2/main.cpp',
-            'libGLESv2/main.h',
-            'libGLESv2/mathutil.h',
-            'libGLESv2/precompiled.cpp',
-            'libGLESv2/precompiled.h',
-            'libGLESv2/Program.cpp',
-            'libGLESv2/Program.h',
-            'libGLESv2/ProgramBinary.cpp',
-            'libGLESv2/ProgramBinary.h',
-            'libGLESv2/Query.cpp',
-            'libGLESv2/Query.h',
-            'libGLESv2/Renderbuffer.cpp',
-            'libGLESv2/Renderbuffer.h',
-            'libGLESv2/renderer/Blit.cpp',
-            'libGLESv2/renderer/Blit.h',
-            'libGLESv2/renderer/BufferStorage.cpp',
-            'libGLESv2/renderer/BufferStorage.h',
-            'libGLESv2/renderer/BufferStorage11.cpp',
-            'libGLESv2/renderer/BufferStorage11.h',
-            'libGLESv2/renderer/BufferStorage9.cpp',
-            'libGLESv2/renderer/BufferStorage9.h',
-            'libGLESv2/renderer/Fence11.cpp',
-            'libGLESv2/renderer/Fence11.h',
-            'libGLESv2/renderer/Fence9.cpp',
-            'libGLESv2/renderer/Fence9.h',
-            'libGLESv2/renderer/FenceImpl.h',
-            'libGLESv2/renderer/generatemip.h',
-            'libGLESv2/renderer/Image.cpp',
-            'libGLESv2/renderer/Image.h',
-            'libGLESv2/renderer/Image11.cpp',
-            'libGLESv2/renderer/Image11.h',
-            'libGLESv2/renderer/Image9.cpp',
-            'libGLESv2/renderer/Image9.h',
-            'libGLESv2/renderer/ImageSSE2.cpp',
-            'libGLESv2/renderer/IndexBuffer.cpp',
-            'libGLESv2/renderer/IndexBuffer.h',
-            'libGLESv2/renderer/IndexBuffer11.cpp',
-            'libGLESv2/renderer/IndexBuffer11.h',
-            'libGLESv2/renderer/IndexBuffer9.cpp',
-            'libGLESv2/renderer/IndexBuffer9.h',
-            'libGLESv2/renderer/IndexDataManager.cpp',
-            'libGLESv2/renderer/IndexDataManager.h',
-            'libGLESv2/renderer/InputLayoutCache.cpp',
-            'libGLESv2/renderer/InputLayoutCache.h',
-            'libGLESv2/renderer/Query11.cpp',
-            'libGLESv2/renderer/Query11.h',
-            'libGLESv2/renderer/Query9.cpp',
-            'libGLESv2/renderer/Query9.h',
-            'libGLESv2/renderer/QueryImpl.h',
-            'libGLESv2/renderer/Renderer.cpp',
-            'libGLESv2/renderer/Renderer.h',
-            'libGLESv2/renderer/Renderer11.cpp',
-            'libGLESv2/renderer/Renderer11.h',
-            'libGLESv2/renderer/renderer11_utils.cpp',
-            'libGLESv2/renderer/renderer11_utils.h',
-            'libGLESv2/renderer/Renderer9.cpp',
-            'libGLESv2/renderer/Renderer9.h',
-            'libGLESv2/renderer/renderer9_utils.cpp',
-            'libGLESv2/renderer/renderer9_utils.h',
-            'libGLESv2/renderer/RenderStateCache.cpp',
-            'libGLESv2/renderer/RenderStateCache.h',
-            'libGLESv2/renderer/RenderTarget.h',
-            'libGLESv2/renderer/RenderTarget11.cpp',
-            'libGLESv2/renderer/RenderTarget11.h',
-            'libGLESv2/renderer/RenderTarget9.cpp',
-            'libGLESv2/renderer/RenderTarget9.h',
-            'libGLESv2/renderer/ShaderCache.h',
-            'libGLESv2/renderer/ShaderExecutable.h',
-            'libGLESv2/renderer/ShaderExecutable11.cpp',
-            'libGLESv2/renderer/ShaderExecutable11.h',
-            'libGLESv2/renderer/ShaderExecutable9.cpp',
-            'libGLESv2/renderer/ShaderExecutable9.h',
-            'libGLESv2/renderer/SwapChain.h',
-            'libGLESv2/renderer/SwapChain11.cpp',
-            'libGLESv2/renderer/SwapChain11.h',
-            'libGLESv2/renderer/SwapChain9.cpp',
-            'libGLESv2/renderer/SwapChain9.h',
-            'libGLESv2/renderer/TextureStorage.cpp',
-            'libGLESv2/renderer/TextureStorage.h',
-            'libGLESv2/renderer/TextureStorage11.cpp',
-            'libGLESv2/renderer/TextureStorage11.h',
-            'libGLESv2/renderer/TextureStorage9.cpp',
-            'libGLESv2/renderer/TextureStorage9.h',
-            'libGLESv2/renderer/VertexBuffer.cpp',
-            'libGLESv2/renderer/VertexBuffer.h',
-            'libGLESv2/renderer/VertexBuffer11.cpp',
-            'libGLESv2/renderer/VertexBuffer11.h',
-            'libGLESv2/renderer/VertexBuffer9.cpp',
-            'libGLESv2/renderer/VertexBuffer9.h',
-            'libGLESv2/renderer/vertexconversion.h',
-            'libGLESv2/renderer/VertexDataManager.cpp',
-            'libGLESv2/renderer/VertexDataManager.h',
-            'libGLESv2/renderer/VertexDeclarationCache.cpp',
-            'libGLESv2/renderer/VertexDeclarationCache.h',
-            'libGLESv2/ResourceManager.cpp',
-            'libGLESv2/ResourceManager.h',
-            'libGLESv2/Shader.cpp',
-            'libGLESv2/Shader.h',
-            'libGLESv2/Texture.cpp',
-            'libGLESv2/Texture.h',
-            'libGLESv2/Uniform.cpp',
-            'libGLESv2/Uniform.h',
-            'libGLESv2/utilities.cpp',
-            'libGLESv2/utilities.h',
-          ],
-          'conditions': [
-            ['angle_api=="win32"', {
-              'sources': [
-                'common/win32/debugperf.cpp',
-                'common/win32/windowutils.cpp',
-                'libGLESv2/renderer/win32/SwapChain11Win32.cpp',
-              ],
-              'sources/': [
-                # Don't compile D3D11-related source codes in win32.
-                ['exclude', 'renderer/.*11'],
-                ['exclude', 'renderer/RenderStateCache'],
-                ['exclude', 'renderer/InputLayoutCache'],
-              ],
-              'msvs_settings': {
-                'VCLinkerTool': {
-                  'AdditionalDependencies': [
-                    'd3d9.lib',
-                    'dxguid.lib',
-                  ],
-                },
-              },
-              'actions':
-              [
-                # Cherry-picked from upstream Angle.
-                {
-                  'action_name': 'copy_dll',
-                  'message': 'Copying D3D Compiler DLL...',
-                  'msvs_cygwin_shell': 0,
-                  'inputs': [ 'copy_compiler_dll.bat' ],
-                  'outputs': [ '<(PRODUCT_DIR)/d3dcompiler_46.dll' ],
-                  'action':
-                  [
-                      "copy_compiler_dll.bat",
-                      "$(PlatformName)",
-                      "<(windows_sdk_path)",
-                      "<(PRODUCT_DIR)"
-                  ],
-                },
-              ],
-            }],
-            ['angle_api=="winrt"', {
-              'sources': [
-                'common/winrt/debugperf.cpp',
-                'common/winrt/windowadapter.cpp',
-                'common/winrt/windowadapter.h',
-                'common/winrt/windowutils.cpp',
-                'libGLESv2/renderer/winrt/SwapChain11WinRT.cpp',
-              ],
-              'sources/': [
-                # WinRT doesn't support D3D9 so we strip all D3D9 source files
-                ['exclude', 'renderer/.*9'],
-                ['exclude', 'renderer/Blit'],
-                ['exclude', 'renderer/VertexDeclarationCache'],
-              ],
-              'msvs_settings': {
-                'VCCLCompilerTool': {
-                  'ComponentExtensions': 'true',
-                },
-                'VCLinkerTool': {
-                  'AdditionalDependencies': [
-                    'd3d11.lib',
-                    'd3dcompiler.lib',
-                    'dxguid.lib',
-                  ],
-                },
-                'VCLibrarianTool': {
-                  'AdditionalOptions': ['/ignore:4264'],
-                },
-              },
-            }],
-            ['angle_api=="xb360"', {
-              'type': 'static_library',
-              'sources': [
-                'common/xb360/debugperf.cpp',
-                'common/xb360/windowutils.cpp',
-                'libGLESv2/renderer/VertexDataManager.cpp',
-                'libGLESv2/renderer/VertexDataManager.h',
-                'libGLESv2/renderer/xb360/BufferStorageXB360.cpp',
-                'libGLESv2/renderer/xb360/BufferStorageXB360.h',
-                'libGLESv2/renderer/xb360/GpuCapture.cpp',
-                'libGLESv2/renderer/xb360/GpuCapture.h',
-                'libGLESv2/renderer/xb360/GpuCaptureControl.cpp',
-                'libGLESv2/renderer/xb360/ImageXB360.cpp',
-                'libGLESv2/renderer/xb360/ImageXB360.h',
-                'libGLESv2/renderer/xb360/IndexBufferXB360.cpp',
-                'libGLESv2/renderer/xb360/IndexBufferXB360.h',
-                'libGLESv2/renderer/xb360/RendererXB360.cpp',
-                'libGLESv2/renderer/xb360/RendererXB360.h',
-                'libGLESv2/renderer/xb360/rendererXB360_utils.cpp',
-                'libGLESv2/renderer/xb360/rendererXB360_utils.h',
-                'libGLESv2/renderer/xb360/RenderTargetXB360.cpp',
-                'libGLESv2/renderer/xb360/RenderTargetXB360.h',
-                'libGLESv2/renderer/xb360/ShaderExecutableXB360.cpp',
-                'libGLESv2/renderer/xb360/ShaderExecutableXB360.h',
-                'libGLESv2/renderer/xb360/SwapChainXB360.cpp',
-                'libGLESv2/renderer/xb360/SwapChainXB360.h',
-                'libGLESv2/renderer/xb360/TextureStorageXB360.cpp',
-                'libGLESv2/renderer/xb360/TextureStorageXB360.h',
-                'libGLESv2/renderer/xb360/TextureXB360.cpp',
-                'libGLESv2/renderer/xb360/TextureXB360.h',
-                'libGLESv2/renderer/xb360/VertexBufferXB360.cpp',
-                'libGLESv2/renderer/xb360/VertexBufferXB360.h',
-                'libGLESv2/renderer/xb360/VertexDeclarationCacheXB360.cpp',
-                'libGLESv2/renderer/xb360/VertexDeclarationCacheXB360.h',
-              ],
-              'sources/': [
-                # Exclude all D3D9 source files
-                ['exclude', 'renderer/.*9'],
-                ['exclude', 'renderer/Blit'],
-                ['exclude', 'renderer/VertexDeclarationCache'],
-                # Exclude all DX11 source files
-                ['exclude', 'renderer/.*11'],
-                # Xbox is PPC.
-                ['exclude', 'renderer/ImageSSE2'],
-                # Xbox does not support these files
-                ['exclude', 'renderer/InputLayoutCache'],
-                ['exclude', 'renderer/RenderStateCache'],
-              ],
-            }],
-            ['OS=="lb_shell"', {
-              'dependencies': [
-                '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
-              ],
-            }],
-          ],
-          # TODO(jschuh): http://crbug.com/167187 size_t -> int
-          'msvs_disabled_warnings': [ 4267 ],
-        },
-        {
-          'target_name': 'libEGL',
-          'type': 'shared_library',
-          'dependencies': ['libGLESv2'],
-          'include_dirs': [
-            '.',
-            '../include',
-            'libGLESv2',
-          ],
-          'sources': [
-            'common/angleutils.h',
-            'common/debug.cpp',
-            'common/debug.h',
-            'common/debugperf.h',
-            'common/RefCountObject.cpp',
-            'common/RefCountObject.h',
-            'common/system.h',
-            'common/version.h',
-            'common/windowutils.h',
-            'libEGL/Config.cpp',
-            'libEGL/Config.h',
-            'libEGL/Display.cpp',
-            'libEGL/Display.h',
-            'libEGL/libEGL.cpp',
-            'libEGL/libEGL.def',
-            'libEGL/libEGL.rc',
-            'libEGL/main.cpp',
-            'libEGL/main.h',
-            'libEGL/Surface.cpp',
-            'libEGL/Surface.h',
-
-          ],
-          'conditions': [
-            ['angle_api=="win32"', {
-              'sources': [
-                'common/win32/debugperf.cpp',
-                'common/win32/windowutils.cpp',
-                'libEGL/win32/WindowSubclassWin32.cpp',
-              ],
-              'msvs_settings': {
-                'VCLinkerTool': {
-                  'AdditionalDependencies': [
-                    'd3d9.lib',
-                    'dxguid.lib',
-                  ],
-                },
-              },
-            }],
-            ['angle_api=="winrt"', {
-              'sources': [
-                'common/winrt/debugperf.cpp',
-                'common/winrt/windowadapter.cpp',
-                'common/winrt/windowadapter.h',
-                'common/winrt/windowutils.cpp',
-                'libEGL/winrt/WindowSubclassWinRT.cpp',
-              ],
-              'msvs_settings': {
-                'VCCLCompilerTool': {
-                  'ComponentExtensions': 'true',
-                },
-                'VCLinkerTool': {
-                  'AdditionalDependencies': [
-                    'd3d11.lib',
-                    'd3dcompiler.lib',
-                    'dxguid.lib',
-                  ],
-                },
-                'VCLibrarianTool': {
-                  'AdditionalOptions': ['/ignore:4264'],
-                },
-              },
-            }],
-            ['angle_api=="xb360"', {
-              # Don't build DLLs on 360.
-              'type': 'static_library',
-              'sources': [
-                'common/xb360/debugperf.cpp',
-                'common/xb360/windowutils.cpp',
-              ],
-            }],
-            ['OS=="lb_shell"', {
-              'dependencies': [
-                '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
-              ],
-            }],
-          ],
-          # TODO(jschuh): http://crbug.com/167187 size_t -> int
-          'msvs_disabled_warnings': [ 4267 ],
-        },
-      ],
-    }],
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
-# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
diff --git a/src/third_party/angle/src/commit.h b/src/third_party/angle/src/commit.h
new file mode 100644
index 0000000..4c89a65
--- /dev/null
+++ b/src/third_party/angle/src/commit.h
@@ -0,0 +1,14 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// commit.h:
+//   This is a default commit hash header, when git is not available.
+//
+
+#define ANGLE_COMMIT_HASH "unknown hash"
+#define ANGLE_COMMIT_HASH_SIZE 12
+#define ANGLE_COMMIT_DATE "unknown date"
+
+#define ANGLE_DISABLE_PROGRAM_BINARY_LOAD
diff --git a/src/third_party/angle/src/commit_id.py b/src/third_party/angle/src/commit_id.py
new file mode 100644
index 0000000..bbdb810
--- /dev/null
+++ b/src/third_party/angle/src/commit_id.py
@@ -0,0 +1,42 @@
+import subprocess as sp
+import sys
+import os
+
+usage = """\
+Usage: commit_id.py check <angle_dir>                - check if git is present
+       commit_id.py gen <angle_dir> <file_to_write>  - generate commit.h"""
+
+def grab_output(command, cwd):
+    return sp.Popen(command, stdout=sp.PIPE, shell=True, cwd=cwd).communicate()[0].strip()
+
+if len(sys.argv) < 3:
+    sys.exit(usage)
+
+operation = sys.argv[1]
+cwd = sys.argv[2]
+
+if operation == 'check':
+    index_path = os.path.join(cwd, '.git', 'index')
+    if os.path.exists(index_path):
+        print("1")
+    else:
+        print("0")
+    sys.exit(0)
+
+output_file = sys.argv[3]
+commit_id_size = 12
+
+try:
+    commit_id = grab_output('git rev-parse --short=%d HEAD' % commit_id_size, cwd)
+    commit_date = grab_output('git show -s --format=%ci HEAD', cwd)
+except:
+    commit_id = 'invalid-hash'
+    commit_date = 'invalid-date'
+
+hfile = open(output_file, 'w')
+
+hfile.write('#define ANGLE_COMMIT_HASH "%s"\n'    % commit_id)
+hfile.write('#define ANGLE_COMMIT_HASH_SIZE %d\n' % commit_id_size)
+hfile.write('#define ANGLE_COMMIT_DATE "%s"\n'    % commit_date)
+
+hfile.close()
diff --git a/src/third_party/angle/src/common/Color.h b/src/third_party/angle/src/common/Color.h
new file mode 100644
index 0000000..2b4d2f6
--- /dev/null
+++ b/src/third_party/angle/src/common/Color.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// Color.h : Defines the Color type used throughout the ANGLE libraries
+
+#ifndef COMMON_COLOR_H_
+#define COMMON_COLOR_H_
+
+namespace angle
+{
+
+template <typename T>
+struct Color
+{
+    T red;
+    T green;
+    T blue;
+    T alpha;
+
+    Color();
+    Color(T r, T g, T b, T a);
+};
+
+template <typename T>
+bool operator==(const Color<T> &a, const Color<T> &b);
+
+template <typename T>
+bool operator!=(const Color<T> &a, const Color<T> &b);
+
+typedef Color<float> ColorF;
+typedef Color<int> ColorI;
+typedef Color<unsigned int> ColorUI;
+
+}  // namespace angle
+
+// TODO: Move this fully into the angle namespace
+namespace gl
+{
+
+template <typename T>
+using Color   = angle::Color<T>;
+using ColorF  = angle::ColorF;
+using ColorI  = angle::ColorI;
+using ColorUI = angle::ColorUI;
+
+}  // namespace gl
+
+#include "Color.inl"
+
+#endif  // COMMON_COLOR_H_
diff --git a/src/third_party/angle/src/common/Color.inl b/src/third_party/angle/src/common/Color.inl
new file mode 100644
index 0000000..c307325
--- /dev/null
+++ b/src/third_party/angle/src/common/Color.inl
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// Color.inl : Inline definitions of some functions from Color.h
+
+namespace angle
+{
+
+template <typename T>
+Color<T>::Color() : Color(0, 0, 0, 0)
+{
+}
+
+template <typename T>
+Color<T>::Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a)
+{
+}
+
+template <typename T>
+bool operator==(const Color<T> &a, const Color<T> &b)
+{
+    return a.red == b.red &&
+           a.green == b.green &&
+           a.blue == b.blue &&
+           a.alpha == b.alpha;
+}
+
+template <typename T>
+bool operator!=(const Color<T> &a, const Color<T> &b)
+{
+    return !(a == b);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/common/Float16ToFloat32.cpp b/src/third_party/angle/src/common/Float16ToFloat32.cpp
new file mode 100644
index 0000000..acd0d88
--- /dev/null
+++ b/src/third_party/angle/src/common/Float16ToFloat32.cpp
@@ -0,0 +1,2205 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is automatically generated.
+
+#include "common/mathutil.h"
+
+namespace gl
+{
+
+const static unsigned g_mantissa[2048] = {
+    0x00000000,
+    0x33800000,
+    0x34000000,
+    0x34400000,
+    0x34800000,
+    0x34a00000,
+    0x34c00000,
+    0x34e00000,
+    0x35000000,
+    0x35100000,
+    0x35200000,
+    0x35300000,
+    0x35400000,
+    0x35500000,
+    0x35600000,
+    0x35700000,
+    0x35800000,
+    0x35880000,
+    0x35900000,
+    0x35980000,
+    0x35a00000,
+    0x35a80000,
+    0x35b00000,
+    0x35b80000,
+    0x35c00000,
+    0x35c80000,
+    0x35d00000,
+    0x35d80000,
+    0x35e00000,
+    0x35e80000,
+    0x35f00000,
+    0x35f80000,
+    0x36000000,
+    0x36040000,
+    0x36080000,
+    0x360c0000,
+    0x36100000,
+    0x36140000,
+    0x36180000,
+    0x361c0000,
+    0x36200000,
+    0x36240000,
+    0x36280000,
+    0x362c0000,
+    0x36300000,
+    0x36340000,
+    0x36380000,
+    0x363c0000,
+    0x36400000,
+    0x36440000,
+    0x36480000,
+    0x364c0000,
+    0x36500000,
+    0x36540000,
+    0x36580000,
+    0x365c0000,
+    0x36600000,
+    0x36640000,
+    0x36680000,
+    0x366c0000,
+    0x36700000,
+    0x36740000,
+    0x36780000,
+    0x367c0000,
+    0x36800000,
+    0x36820000,
+    0x36840000,
+    0x36860000,
+    0x36880000,
+    0x368a0000,
+    0x368c0000,
+    0x368e0000,
+    0x36900000,
+    0x36920000,
+    0x36940000,
+    0x36960000,
+    0x36980000,
+    0x369a0000,
+    0x369c0000,
+    0x369e0000,
+    0x36a00000,
+    0x36a20000,
+    0x36a40000,
+    0x36a60000,
+    0x36a80000,
+    0x36aa0000,
+    0x36ac0000,
+    0x36ae0000,
+    0x36b00000,
+    0x36b20000,
+    0x36b40000,
+    0x36b60000,
+    0x36b80000,
+    0x36ba0000,
+    0x36bc0000,
+    0x36be0000,
+    0x36c00000,
+    0x36c20000,
+    0x36c40000,
+    0x36c60000,
+    0x36c80000,
+    0x36ca0000,
+    0x36cc0000,
+    0x36ce0000,
+    0x36d00000,
+    0x36d20000,
+    0x36d40000,
+    0x36d60000,
+    0x36d80000,
+    0x36da0000,
+    0x36dc0000,
+    0x36de0000,
+    0x36e00000,
+    0x36e20000,
+    0x36e40000,
+    0x36e60000,
+    0x36e80000,
+    0x36ea0000,
+    0x36ec0000,
+    0x36ee0000,
+    0x36f00000,
+    0x36f20000,
+    0x36f40000,
+    0x36f60000,
+    0x36f80000,
+    0x36fa0000,
+    0x36fc0000,
+    0x36fe0000,
+    0x37000000,
+    0x37010000,
+    0x37020000,
+    0x37030000,
+    0x37040000,
+    0x37050000,
+    0x37060000,
+    0x37070000,
+    0x37080000,
+    0x37090000,
+    0x370a0000,
+    0x370b0000,
+    0x370c0000,
+    0x370d0000,
+    0x370e0000,
+    0x370f0000,
+    0x37100000,
+    0x37110000,
+    0x37120000,
+    0x37130000,
+    0x37140000,
+    0x37150000,
+    0x37160000,
+    0x37170000,
+    0x37180000,
+    0x37190000,
+    0x371a0000,
+    0x371b0000,
+    0x371c0000,
+    0x371d0000,
+    0x371e0000,
+    0x371f0000,
+    0x37200000,
+    0x37210000,
+    0x37220000,
+    0x37230000,
+    0x37240000,
+    0x37250000,
+    0x37260000,
+    0x37270000,
+    0x37280000,
+    0x37290000,
+    0x372a0000,
+    0x372b0000,
+    0x372c0000,
+    0x372d0000,
+    0x372e0000,
+    0x372f0000,
+    0x37300000,
+    0x37310000,
+    0x37320000,
+    0x37330000,
+    0x37340000,
+    0x37350000,
+    0x37360000,
+    0x37370000,
+    0x37380000,
+    0x37390000,
+    0x373a0000,
+    0x373b0000,
+    0x373c0000,
+    0x373d0000,
+    0x373e0000,
+    0x373f0000,
+    0x37400000,
+    0x37410000,
+    0x37420000,
+    0x37430000,
+    0x37440000,
+    0x37450000,
+    0x37460000,
+    0x37470000,
+    0x37480000,
+    0x37490000,
+    0x374a0000,
+    0x374b0000,
+    0x374c0000,
+    0x374d0000,
+    0x374e0000,
+    0x374f0000,
+    0x37500000,
+    0x37510000,
+    0x37520000,
+    0x37530000,
+    0x37540000,
+    0x37550000,
+    0x37560000,
+    0x37570000,
+    0x37580000,
+    0x37590000,
+    0x375a0000,
+    0x375b0000,
+    0x375c0000,
+    0x375d0000,
+    0x375e0000,
+    0x375f0000,
+    0x37600000,
+    0x37610000,
+    0x37620000,
+    0x37630000,
+    0x37640000,
+    0x37650000,
+    0x37660000,
+    0x37670000,
+    0x37680000,
+    0x37690000,
+    0x376a0000,
+    0x376b0000,
+    0x376c0000,
+    0x376d0000,
+    0x376e0000,
+    0x376f0000,
+    0x37700000,
+    0x37710000,
+    0x37720000,
+    0x37730000,
+    0x37740000,
+    0x37750000,
+    0x37760000,
+    0x37770000,
+    0x37780000,
+    0x37790000,
+    0x377a0000,
+    0x377b0000,
+    0x377c0000,
+    0x377d0000,
+    0x377e0000,
+    0x377f0000,
+    0x37800000,
+    0x37808000,
+    0x37810000,
+    0x37818000,
+    0x37820000,
+    0x37828000,
+    0x37830000,
+    0x37838000,
+    0x37840000,
+    0x37848000,
+    0x37850000,
+    0x37858000,
+    0x37860000,
+    0x37868000,
+    0x37870000,
+    0x37878000,
+    0x37880000,
+    0x37888000,
+    0x37890000,
+    0x37898000,
+    0x378a0000,
+    0x378a8000,
+    0x378b0000,
+    0x378b8000,
+    0x378c0000,
+    0x378c8000,
+    0x378d0000,
+    0x378d8000,
+    0x378e0000,
+    0x378e8000,
+    0x378f0000,
+    0x378f8000,
+    0x37900000,
+    0x37908000,
+    0x37910000,
+    0x37918000,
+    0x37920000,
+    0x37928000,
+    0x37930000,
+    0x37938000,
+    0x37940000,
+    0x37948000,
+    0x37950000,
+    0x37958000,
+    0x37960000,
+    0x37968000,
+    0x37970000,
+    0x37978000,
+    0x37980000,
+    0x37988000,
+    0x37990000,
+    0x37998000,
+    0x379a0000,
+    0x379a8000,
+    0x379b0000,
+    0x379b8000,
+    0x379c0000,
+    0x379c8000,
+    0x379d0000,
+    0x379d8000,
+    0x379e0000,
+    0x379e8000,
+    0x379f0000,
+    0x379f8000,
+    0x37a00000,
+    0x37a08000,
+    0x37a10000,
+    0x37a18000,
+    0x37a20000,
+    0x37a28000,
+    0x37a30000,
+    0x37a38000,
+    0x37a40000,
+    0x37a48000,
+    0x37a50000,
+    0x37a58000,
+    0x37a60000,
+    0x37a68000,
+    0x37a70000,
+    0x37a78000,
+    0x37a80000,
+    0x37a88000,
+    0x37a90000,
+    0x37a98000,
+    0x37aa0000,
+    0x37aa8000,
+    0x37ab0000,
+    0x37ab8000,
+    0x37ac0000,
+    0x37ac8000,
+    0x37ad0000,
+    0x37ad8000,
+    0x37ae0000,
+    0x37ae8000,
+    0x37af0000,
+    0x37af8000,
+    0x37b00000,
+    0x37b08000,
+    0x37b10000,
+    0x37b18000,
+    0x37b20000,
+    0x37b28000,
+    0x37b30000,
+    0x37b38000,
+    0x37b40000,
+    0x37b48000,
+    0x37b50000,
+    0x37b58000,
+    0x37b60000,
+    0x37b68000,
+    0x37b70000,
+    0x37b78000,
+    0x37b80000,
+    0x37b88000,
+    0x37b90000,
+    0x37b98000,
+    0x37ba0000,
+    0x37ba8000,
+    0x37bb0000,
+    0x37bb8000,
+    0x37bc0000,
+    0x37bc8000,
+    0x37bd0000,
+    0x37bd8000,
+    0x37be0000,
+    0x37be8000,
+    0x37bf0000,
+    0x37bf8000,
+    0x37c00000,
+    0x37c08000,
+    0x37c10000,
+    0x37c18000,
+    0x37c20000,
+    0x37c28000,
+    0x37c30000,
+    0x37c38000,
+    0x37c40000,
+    0x37c48000,
+    0x37c50000,
+    0x37c58000,
+    0x37c60000,
+    0x37c68000,
+    0x37c70000,
+    0x37c78000,
+    0x37c80000,
+    0x37c88000,
+    0x37c90000,
+    0x37c98000,
+    0x37ca0000,
+    0x37ca8000,
+    0x37cb0000,
+    0x37cb8000,
+    0x37cc0000,
+    0x37cc8000,
+    0x37cd0000,
+    0x37cd8000,
+    0x37ce0000,
+    0x37ce8000,
+    0x37cf0000,
+    0x37cf8000,
+    0x37d00000,
+    0x37d08000,
+    0x37d10000,
+    0x37d18000,
+    0x37d20000,
+    0x37d28000,
+    0x37d30000,
+    0x37d38000,
+    0x37d40000,
+    0x37d48000,
+    0x37d50000,
+    0x37d58000,
+    0x37d60000,
+    0x37d68000,
+    0x37d70000,
+    0x37d78000,
+    0x37d80000,
+    0x37d88000,
+    0x37d90000,
+    0x37d98000,
+    0x37da0000,
+    0x37da8000,
+    0x37db0000,
+    0x37db8000,
+    0x37dc0000,
+    0x37dc8000,
+    0x37dd0000,
+    0x37dd8000,
+    0x37de0000,
+    0x37de8000,
+    0x37df0000,
+    0x37df8000,
+    0x37e00000,
+    0x37e08000,
+    0x37e10000,
+    0x37e18000,
+    0x37e20000,
+    0x37e28000,
+    0x37e30000,
+    0x37e38000,
+    0x37e40000,
+    0x37e48000,
+    0x37e50000,
+    0x37e58000,
+    0x37e60000,
+    0x37e68000,
+    0x37e70000,
+    0x37e78000,
+    0x37e80000,
+    0x37e88000,
+    0x37e90000,
+    0x37e98000,
+    0x37ea0000,
+    0x37ea8000,
+    0x37eb0000,
+    0x37eb8000,
+    0x37ec0000,
+    0x37ec8000,
+    0x37ed0000,
+    0x37ed8000,
+    0x37ee0000,
+    0x37ee8000,
+    0x37ef0000,
+    0x37ef8000,
+    0x37f00000,
+    0x37f08000,
+    0x37f10000,
+    0x37f18000,
+    0x37f20000,
+    0x37f28000,
+    0x37f30000,
+    0x37f38000,
+    0x37f40000,
+    0x37f48000,
+    0x37f50000,
+    0x37f58000,
+    0x37f60000,
+    0x37f68000,
+    0x37f70000,
+    0x37f78000,
+    0x37f80000,
+    0x37f88000,
+    0x37f90000,
+    0x37f98000,
+    0x37fa0000,
+    0x37fa8000,
+    0x37fb0000,
+    0x37fb8000,
+    0x37fc0000,
+    0x37fc8000,
+    0x37fd0000,
+    0x37fd8000,
+    0x37fe0000,
+    0x37fe8000,
+    0x37ff0000,
+    0x37ff8000,
+    0x38000000,
+    0x38004000,
+    0x38008000,
+    0x3800c000,
+    0x38010000,
+    0x38014000,
+    0x38018000,
+    0x3801c000,
+    0x38020000,
+    0x38024000,
+    0x38028000,
+    0x3802c000,
+    0x38030000,
+    0x38034000,
+    0x38038000,
+    0x3803c000,
+    0x38040000,
+    0x38044000,
+    0x38048000,
+    0x3804c000,
+    0x38050000,
+    0x38054000,
+    0x38058000,
+    0x3805c000,
+    0x38060000,
+    0x38064000,
+    0x38068000,
+    0x3806c000,
+    0x38070000,
+    0x38074000,
+    0x38078000,
+    0x3807c000,
+    0x38080000,
+    0x38084000,
+    0x38088000,
+    0x3808c000,
+    0x38090000,
+    0x38094000,
+    0x38098000,
+    0x3809c000,
+    0x380a0000,
+    0x380a4000,
+    0x380a8000,
+    0x380ac000,
+    0x380b0000,
+    0x380b4000,
+    0x380b8000,
+    0x380bc000,
+    0x380c0000,
+    0x380c4000,
+    0x380c8000,
+    0x380cc000,
+    0x380d0000,
+    0x380d4000,
+    0x380d8000,
+    0x380dc000,
+    0x380e0000,
+    0x380e4000,
+    0x380e8000,
+    0x380ec000,
+    0x380f0000,
+    0x380f4000,
+    0x380f8000,
+    0x380fc000,
+    0x38100000,
+    0x38104000,
+    0x38108000,
+    0x3810c000,
+    0x38110000,
+    0x38114000,
+    0x38118000,
+    0x3811c000,
+    0x38120000,
+    0x38124000,
+    0x38128000,
+    0x3812c000,
+    0x38130000,
+    0x38134000,
+    0x38138000,
+    0x3813c000,
+    0x38140000,
+    0x38144000,
+    0x38148000,
+    0x3814c000,
+    0x38150000,
+    0x38154000,
+    0x38158000,
+    0x3815c000,
+    0x38160000,
+    0x38164000,
+    0x38168000,
+    0x3816c000,
+    0x38170000,
+    0x38174000,
+    0x38178000,
+    0x3817c000,
+    0x38180000,
+    0x38184000,
+    0x38188000,
+    0x3818c000,
+    0x38190000,
+    0x38194000,
+    0x38198000,
+    0x3819c000,
+    0x381a0000,
+    0x381a4000,
+    0x381a8000,
+    0x381ac000,
+    0x381b0000,
+    0x381b4000,
+    0x381b8000,
+    0x381bc000,
+    0x381c0000,
+    0x381c4000,
+    0x381c8000,
+    0x381cc000,
+    0x381d0000,
+    0x381d4000,
+    0x381d8000,
+    0x381dc000,
+    0x381e0000,
+    0x381e4000,
+    0x381e8000,
+    0x381ec000,
+    0x381f0000,
+    0x381f4000,
+    0x381f8000,
+    0x381fc000,
+    0x38200000,
+    0x38204000,
+    0x38208000,
+    0x3820c000,
+    0x38210000,
+    0x38214000,
+    0x38218000,
+    0x3821c000,
+    0x38220000,
+    0x38224000,
+    0x38228000,
+    0x3822c000,
+    0x38230000,
+    0x38234000,
+    0x38238000,
+    0x3823c000,
+    0x38240000,
+    0x38244000,
+    0x38248000,
+    0x3824c000,
+    0x38250000,
+    0x38254000,
+    0x38258000,
+    0x3825c000,
+    0x38260000,
+    0x38264000,
+    0x38268000,
+    0x3826c000,
+    0x38270000,
+    0x38274000,
+    0x38278000,
+    0x3827c000,
+    0x38280000,
+    0x38284000,
+    0x38288000,
+    0x3828c000,
+    0x38290000,
+    0x38294000,
+    0x38298000,
+    0x3829c000,
+    0x382a0000,
+    0x382a4000,
+    0x382a8000,
+    0x382ac000,
+    0x382b0000,
+    0x382b4000,
+    0x382b8000,
+    0x382bc000,
+    0x382c0000,
+    0x382c4000,
+    0x382c8000,
+    0x382cc000,
+    0x382d0000,
+    0x382d4000,
+    0x382d8000,
+    0x382dc000,
+    0x382e0000,
+    0x382e4000,
+    0x382e8000,
+    0x382ec000,
+    0x382f0000,
+    0x382f4000,
+    0x382f8000,
+    0x382fc000,
+    0x38300000,
+    0x38304000,
+    0x38308000,
+    0x3830c000,
+    0x38310000,
+    0x38314000,
+    0x38318000,
+    0x3831c000,
+    0x38320000,
+    0x38324000,
+    0x38328000,
+    0x3832c000,
+    0x38330000,
+    0x38334000,
+    0x38338000,
+    0x3833c000,
+    0x38340000,
+    0x38344000,
+    0x38348000,
+    0x3834c000,
+    0x38350000,
+    0x38354000,
+    0x38358000,
+    0x3835c000,
+    0x38360000,
+    0x38364000,
+    0x38368000,
+    0x3836c000,
+    0x38370000,
+    0x38374000,
+    0x38378000,
+    0x3837c000,
+    0x38380000,
+    0x38384000,
+    0x38388000,
+    0x3838c000,
+    0x38390000,
+    0x38394000,
+    0x38398000,
+    0x3839c000,
+    0x383a0000,
+    0x383a4000,
+    0x383a8000,
+    0x383ac000,
+    0x383b0000,
+    0x383b4000,
+    0x383b8000,
+    0x383bc000,
+    0x383c0000,
+    0x383c4000,
+    0x383c8000,
+    0x383cc000,
+    0x383d0000,
+    0x383d4000,
+    0x383d8000,
+    0x383dc000,
+    0x383e0000,
+    0x383e4000,
+    0x383e8000,
+    0x383ec000,
+    0x383f0000,
+    0x383f4000,
+    0x383f8000,
+    0x383fc000,
+    0x38400000,
+    0x38404000,
+    0x38408000,
+    0x3840c000,
+    0x38410000,
+    0x38414000,
+    0x38418000,
+    0x3841c000,
+    0x38420000,
+    0x38424000,
+    0x38428000,
+    0x3842c000,
+    0x38430000,
+    0x38434000,
+    0x38438000,
+    0x3843c000,
+    0x38440000,
+    0x38444000,
+    0x38448000,
+    0x3844c000,
+    0x38450000,
+    0x38454000,
+    0x38458000,
+    0x3845c000,
+    0x38460000,
+    0x38464000,
+    0x38468000,
+    0x3846c000,
+    0x38470000,
+    0x38474000,
+    0x38478000,
+    0x3847c000,
+    0x38480000,
+    0x38484000,
+    0x38488000,
+    0x3848c000,
+    0x38490000,
+    0x38494000,
+    0x38498000,
+    0x3849c000,
+    0x384a0000,
+    0x384a4000,
+    0x384a8000,
+    0x384ac000,
+    0x384b0000,
+    0x384b4000,
+    0x384b8000,
+    0x384bc000,
+    0x384c0000,
+    0x384c4000,
+    0x384c8000,
+    0x384cc000,
+    0x384d0000,
+    0x384d4000,
+    0x384d8000,
+    0x384dc000,
+    0x384e0000,
+    0x384e4000,
+    0x384e8000,
+    0x384ec000,
+    0x384f0000,
+    0x384f4000,
+    0x384f8000,
+    0x384fc000,
+    0x38500000,
+    0x38504000,
+    0x38508000,
+    0x3850c000,
+    0x38510000,
+    0x38514000,
+    0x38518000,
+    0x3851c000,
+    0x38520000,
+    0x38524000,
+    0x38528000,
+    0x3852c000,
+    0x38530000,
+    0x38534000,
+    0x38538000,
+    0x3853c000,
+    0x38540000,
+    0x38544000,
+    0x38548000,
+    0x3854c000,
+    0x38550000,
+    0x38554000,
+    0x38558000,
+    0x3855c000,
+    0x38560000,
+    0x38564000,
+    0x38568000,
+    0x3856c000,
+    0x38570000,
+    0x38574000,
+    0x38578000,
+    0x3857c000,
+    0x38580000,
+    0x38584000,
+    0x38588000,
+    0x3858c000,
+    0x38590000,
+    0x38594000,
+    0x38598000,
+    0x3859c000,
+    0x385a0000,
+    0x385a4000,
+    0x385a8000,
+    0x385ac000,
+    0x385b0000,
+    0x385b4000,
+    0x385b8000,
+    0x385bc000,
+    0x385c0000,
+    0x385c4000,
+    0x385c8000,
+    0x385cc000,
+    0x385d0000,
+    0x385d4000,
+    0x385d8000,
+    0x385dc000,
+    0x385e0000,
+    0x385e4000,
+    0x385e8000,
+    0x385ec000,
+    0x385f0000,
+    0x385f4000,
+    0x385f8000,
+    0x385fc000,
+    0x38600000,
+    0x38604000,
+    0x38608000,
+    0x3860c000,
+    0x38610000,
+    0x38614000,
+    0x38618000,
+    0x3861c000,
+    0x38620000,
+    0x38624000,
+    0x38628000,
+    0x3862c000,
+    0x38630000,
+    0x38634000,
+    0x38638000,
+    0x3863c000,
+    0x38640000,
+    0x38644000,
+    0x38648000,
+    0x3864c000,
+    0x38650000,
+    0x38654000,
+    0x38658000,
+    0x3865c000,
+    0x38660000,
+    0x38664000,
+    0x38668000,
+    0x3866c000,
+    0x38670000,
+    0x38674000,
+    0x38678000,
+    0x3867c000,
+    0x38680000,
+    0x38684000,
+    0x38688000,
+    0x3868c000,
+    0x38690000,
+    0x38694000,
+    0x38698000,
+    0x3869c000,
+    0x386a0000,
+    0x386a4000,
+    0x386a8000,
+    0x386ac000,
+    0x386b0000,
+    0x386b4000,
+    0x386b8000,
+    0x386bc000,
+    0x386c0000,
+    0x386c4000,
+    0x386c8000,
+    0x386cc000,
+    0x386d0000,
+    0x386d4000,
+    0x386d8000,
+    0x386dc000,
+    0x386e0000,
+    0x386e4000,
+    0x386e8000,
+    0x386ec000,
+    0x386f0000,
+    0x386f4000,
+    0x386f8000,
+    0x386fc000,
+    0x38700000,
+    0x38704000,
+    0x38708000,
+    0x3870c000,
+    0x38710000,
+    0x38714000,
+    0x38718000,
+    0x3871c000,
+    0x38720000,
+    0x38724000,
+    0x38728000,
+    0x3872c000,
+    0x38730000,
+    0x38734000,
+    0x38738000,
+    0x3873c000,
+    0x38740000,
+    0x38744000,
+    0x38748000,
+    0x3874c000,
+    0x38750000,
+    0x38754000,
+    0x38758000,
+    0x3875c000,
+    0x38760000,
+    0x38764000,
+    0x38768000,
+    0x3876c000,
+    0x38770000,
+    0x38774000,
+    0x38778000,
+    0x3877c000,
+    0x38780000,
+    0x38784000,
+    0x38788000,
+    0x3878c000,
+    0x38790000,
+    0x38794000,
+    0x38798000,
+    0x3879c000,
+    0x387a0000,
+    0x387a4000,
+    0x387a8000,
+    0x387ac000,
+    0x387b0000,
+    0x387b4000,
+    0x387b8000,
+    0x387bc000,
+    0x387c0000,
+    0x387c4000,
+    0x387c8000,
+    0x387cc000,
+    0x387d0000,
+    0x387d4000,
+    0x387d8000,
+    0x387dc000,
+    0x387e0000,
+    0x387e4000,
+    0x387e8000,
+    0x387ec000,
+    0x387f0000,
+    0x387f4000,
+    0x387f8000,
+    0x387fc000,
+    0x38000000,
+    0x38002000,
+    0x38004000,
+    0x38006000,
+    0x38008000,
+    0x3800a000,
+    0x3800c000,
+    0x3800e000,
+    0x38010000,
+    0x38012000,
+    0x38014000,
+    0x38016000,
+    0x38018000,
+    0x3801a000,
+    0x3801c000,
+    0x3801e000,
+    0x38020000,
+    0x38022000,
+    0x38024000,
+    0x38026000,
+    0x38028000,
+    0x3802a000,
+    0x3802c000,
+    0x3802e000,
+    0x38030000,
+    0x38032000,
+    0x38034000,
+    0x38036000,
+    0x38038000,
+    0x3803a000,
+    0x3803c000,
+    0x3803e000,
+    0x38040000,
+    0x38042000,
+    0x38044000,
+    0x38046000,
+    0x38048000,
+    0x3804a000,
+    0x3804c000,
+    0x3804e000,
+    0x38050000,
+    0x38052000,
+    0x38054000,
+    0x38056000,
+    0x38058000,
+    0x3805a000,
+    0x3805c000,
+    0x3805e000,
+    0x38060000,
+    0x38062000,
+    0x38064000,
+    0x38066000,
+    0x38068000,
+    0x3806a000,
+    0x3806c000,
+    0x3806e000,
+    0x38070000,
+    0x38072000,
+    0x38074000,
+    0x38076000,
+    0x38078000,
+    0x3807a000,
+    0x3807c000,
+    0x3807e000,
+    0x38080000,
+    0x38082000,
+    0x38084000,
+    0x38086000,
+    0x38088000,
+    0x3808a000,
+    0x3808c000,
+    0x3808e000,
+    0x38090000,
+    0x38092000,
+    0x38094000,
+    0x38096000,
+    0x38098000,
+    0x3809a000,
+    0x3809c000,
+    0x3809e000,
+    0x380a0000,
+    0x380a2000,
+    0x380a4000,
+    0x380a6000,
+    0x380a8000,
+    0x380aa000,
+    0x380ac000,
+    0x380ae000,
+    0x380b0000,
+    0x380b2000,
+    0x380b4000,
+    0x380b6000,
+    0x380b8000,
+    0x380ba000,
+    0x380bc000,
+    0x380be000,
+    0x380c0000,
+    0x380c2000,
+    0x380c4000,
+    0x380c6000,
+    0x380c8000,
+    0x380ca000,
+    0x380cc000,
+    0x380ce000,
+    0x380d0000,
+    0x380d2000,
+    0x380d4000,
+    0x380d6000,
+    0x380d8000,
+    0x380da000,
+    0x380dc000,
+    0x380de000,
+    0x380e0000,
+    0x380e2000,
+    0x380e4000,
+    0x380e6000,
+    0x380e8000,
+    0x380ea000,
+    0x380ec000,
+    0x380ee000,
+    0x380f0000,
+    0x380f2000,
+    0x380f4000,
+    0x380f6000,
+    0x380f8000,
+    0x380fa000,
+    0x380fc000,
+    0x380fe000,
+    0x38100000,
+    0x38102000,
+    0x38104000,
+    0x38106000,
+    0x38108000,
+    0x3810a000,
+    0x3810c000,
+    0x3810e000,
+    0x38110000,
+    0x38112000,
+    0x38114000,
+    0x38116000,
+    0x38118000,
+    0x3811a000,
+    0x3811c000,
+    0x3811e000,
+    0x38120000,
+    0x38122000,
+    0x38124000,
+    0x38126000,
+    0x38128000,
+    0x3812a000,
+    0x3812c000,
+    0x3812e000,
+    0x38130000,
+    0x38132000,
+    0x38134000,
+    0x38136000,
+    0x38138000,
+    0x3813a000,
+    0x3813c000,
+    0x3813e000,
+    0x38140000,
+    0x38142000,
+    0x38144000,
+    0x38146000,
+    0x38148000,
+    0x3814a000,
+    0x3814c000,
+    0x3814e000,
+    0x38150000,
+    0x38152000,
+    0x38154000,
+    0x38156000,
+    0x38158000,
+    0x3815a000,
+    0x3815c000,
+    0x3815e000,
+    0x38160000,
+    0x38162000,
+    0x38164000,
+    0x38166000,
+    0x38168000,
+    0x3816a000,
+    0x3816c000,
+    0x3816e000,
+    0x38170000,
+    0x38172000,
+    0x38174000,
+    0x38176000,
+    0x38178000,
+    0x3817a000,
+    0x3817c000,
+    0x3817e000,
+    0x38180000,
+    0x38182000,
+    0x38184000,
+    0x38186000,
+    0x38188000,
+    0x3818a000,
+    0x3818c000,
+    0x3818e000,
+    0x38190000,
+    0x38192000,
+    0x38194000,
+    0x38196000,
+    0x38198000,
+    0x3819a000,
+    0x3819c000,
+    0x3819e000,
+    0x381a0000,
+    0x381a2000,
+    0x381a4000,
+    0x381a6000,
+    0x381a8000,
+    0x381aa000,
+    0x381ac000,
+    0x381ae000,
+    0x381b0000,
+    0x381b2000,
+    0x381b4000,
+    0x381b6000,
+    0x381b8000,
+    0x381ba000,
+    0x381bc000,
+    0x381be000,
+    0x381c0000,
+    0x381c2000,
+    0x381c4000,
+    0x381c6000,
+    0x381c8000,
+    0x381ca000,
+    0x381cc000,
+    0x381ce000,
+    0x381d0000,
+    0x381d2000,
+    0x381d4000,
+    0x381d6000,
+    0x381d8000,
+    0x381da000,
+    0x381dc000,
+    0x381de000,
+    0x381e0000,
+    0x381e2000,
+    0x381e4000,
+    0x381e6000,
+    0x381e8000,
+    0x381ea000,
+    0x381ec000,
+    0x381ee000,
+    0x381f0000,
+    0x381f2000,
+    0x381f4000,
+    0x381f6000,
+    0x381f8000,
+    0x381fa000,
+    0x381fc000,
+    0x381fe000,
+    0x38200000,
+    0x38202000,
+    0x38204000,
+    0x38206000,
+    0x38208000,
+    0x3820a000,
+    0x3820c000,
+    0x3820e000,
+    0x38210000,
+    0x38212000,
+    0x38214000,
+    0x38216000,
+    0x38218000,
+    0x3821a000,
+    0x3821c000,
+    0x3821e000,
+    0x38220000,
+    0x38222000,
+    0x38224000,
+    0x38226000,
+    0x38228000,
+    0x3822a000,
+    0x3822c000,
+    0x3822e000,
+    0x38230000,
+    0x38232000,
+    0x38234000,
+    0x38236000,
+    0x38238000,
+    0x3823a000,
+    0x3823c000,
+    0x3823e000,
+    0x38240000,
+    0x38242000,
+    0x38244000,
+    0x38246000,
+    0x38248000,
+    0x3824a000,
+    0x3824c000,
+    0x3824e000,
+    0x38250000,
+    0x38252000,
+    0x38254000,
+    0x38256000,
+    0x38258000,
+    0x3825a000,
+    0x3825c000,
+    0x3825e000,
+    0x38260000,
+    0x38262000,
+    0x38264000,
+    0x38266000,
+    0x38268000,
+    0x3826a000,
+    0x3826c000,
+    0x3826e000,
+    0x38270000,
+    0x38272000,
+    0x38274000,
+    0x38276000,
+    0x38278000,
+    0x3827a000,
+    0x3827c000,
+    0x3827e000,
+    0x38280000,
+    0x38282000,
+    0x38284000,
+    0x38286000,
+    0x38288000,
+    0x3828a000,
+    0x3828c000,
+    0x3828e000,
+    0x38290000,
+    0x38292000,
+    0x38294000,
+    0x38296000,
+    0x38298000,
+    0x3829a000,
+    0x3829c000,
+    0x3829e000,
+    0x382a0000,
+    0x382a2000,
+    0x382a4000,
+    0x382a6000,
+    0x382a8000,
+    0x382aa000,
+    0x382ac000,
+    0x382ae000,
+    0x382b0000,
+    0x382b2000,
+    0x382b4000,
+    0x382b6000,
+    0x382b8000,
+    0x382ba000,
+    0x382bc000,
+    0x382be000,
+    0x382c0000,
+    0x382c2000,
+    0x382c4000,
+    0x382c6000,
+    0x382c8000,
+    0x382ca000,
+    0x382cc000,
+    0x382ce000,
+    0x382d0000,
+    0x382d2000,
+    0x382d4000,
+    0x382d6000,
+    0x382d8000,
+    0x382da000,
+    0x382dc000,
+    0x382de000,
+    0x382e0000,
+    0x382e2000,
+    0x382e4000,
+    0x382e6000,
+    0x382e8000,
+    0x382ea000,
+    0x382ec000,
+    0x382ee000,
+    0x382f0000,
+    0x382f2000,
+    0x382f4000,
+    0x382f6000,
+    0x382f8000,
+    0x382fa000,
+    0x382fc000,
+    0x382fe000,
+    0x38300000,
+    0x38302000,
+    0x38304000,
+    0x38306000,
+    0x38308000,
+    0x3830a000,
+    0x3830c000,
+    0x3830e000,
+    0x38310000,
+    0x38312000,
+    0x38314000,
+    0x38316000,
+    0x38318000,
+    0x3831a000,
+    0x3831c000,
+    0x3831e000,
+    0x38320000,
+    0x38322000,
+    0x38324000,
+    0x38326000,
+    0x38328000,
+    0x3832a000,
+    0x3832c000,
+    0x3832e000,
+    0x38330000,
+    0x38332000,
+    0x38334000,
+    0x38336000,
+    0x38338000,
+    0x3833a000,
+    0x3833c000,
+    0x3833e000,
+    0x38340000,
+    0x38342000,
+    0x38344000,
+    0x38346000,
+    0x38348000,
+    0x3834a000,
+    0x3834c000,
+    0x3834e000,
+    0x38350000,
+    0x38352000,
+    0x38354000,
+    0x38356000,
+    0x38358000,
+    0x3835a000,
+    0x3835c000,
+    0x3835e000,
+    0x38360000,
+    0x38362000,
+    0x38364000,
+    0x38366000,
+    0x38368000,
+    0x3836a000,
+    0x3836c000,
+    0x3836e000,
+    0x38370000,
+    0x38372000,
+    0x38374000,
+    0x38376000,
+    0x38378000,
+    0x3837a000,
+    0x3837c000,
+    0x3837e000,
+    0x38380000,
+    0x38382000,
+    0x38384000,
+    0x38386000,
+    0x38388000,
+    0x3838a000,
+    0x3838c000,
+    0x3838e000,
+    0x38390000,
+    0x38392000,
+    0x38394000,
+    0x38396000,
+    0x38398000,
+    0x3839a000,
+    0x3839c000,
+    0x3839e000,
+    0x383a0000,
+    0x383a2000,
+    0x383a4000,
+    0x383a6000,
+    0x383a8000,
+    0x383aa000,
+    0x383ac000,
+    0x383ae000,
+    0x383b0000,
+    0x383b2000,
+    0x383b4000,
+    0x383b6000,
+    0x383b8000,
+    0x383ba000,
+    0x383bc000,
+    0x383be000,
+    0x383c0000,
+    0x383c2000,
+    0x383c4000,
+    0x383c6000,
+    0x383c8000,
+    0x383ca000,
+    0x383cc000,
+    0x383ce000,
+    0x383d0000,
+    0x383d2000,
+    0x383d4000,
+    0x383d6000,
+    0x383d8000,
+    0x383da000,
+    0x383dc000,
+    0x383de000,
+    0x383e0000,
+    0x383e2000,
+    0x383e4000,
+    0x383e6000,
+    0x383e8000,
+    0x383ea000,
+    0x383ec000,
+    0x383ee000,
+    0x383f0000,
+    0x383f2000,
+    0x383f4000,
+    0x383f6000,
+    0x383f8000,
+    0x383fa000,
+    0x383fc000,
+    0x383fe000,
+    0x38400000,
+    0x38402000,
+    0x38404000,
+    0x38406000,
+    0x38408000,
+    0x3840a000,
+    0x3840c000,
+    0x3840e000,
+    0x38410000,
+    0x38412000,
+    0x38414000,
+    0x38416000,
+    0x38418000,
+    0x3841a000,
+    0x3841c000,
+    0x3841e000,
+    0x38420000,
+    0x38422000,
+    0x38424000,
+    0x38426000,
+    0x38428000,
+    0x3842a000,
+    0x3842c000,
+    0x3842e000,
+    0x38430000,
+    0x38432000,
+    0x38434000,
+    0x38436000,
+    0x38438000,
+    0x3843a000,
+    0x3843c000,
+    0x3843e000,
+    0x38440000,
+    0x38442000,
+    0x38444000,
+    0x38446000,
+    0x38448000,
+    0x3844a000,
+    0x3844c000,
+    0x3844e000,
+    0x38450000,
+    0x38452000,
+    0x38454000,
+    0x38456000,
+    0x38458000,
+    0x3845a000,
+    0x3845c000,
+    0x3845e000,
+    0x38460000,
+    0x38462000,
+    0x38464000,
+    0x38466000,
+    0x38468000,
+    0x3846a000,
+    0x3846c000,
+    0x3846e000,
+    0x38470000,
+    0x38472000,
+    0x38474000,
+    0x38476000,
+    0x38478000,
+    0x3847a000,
+    0x3847c000,
+    0x3847e000,
+    0x38480000,
+    0x38482000,
+    0x38484000,
+    0x38486000,
+    0x38488000,
+    0x3848a000,
+    0x3848c000,
+    0x3848e000,
+    0x38490000,
+    0x38492000,
+    0x38494000,
+    0x38496000,
+    0x38498000,
+    0x3849a000,
+    0x3849c000,
+    0x3849e000,
+    0x384a0000,
+    0x384a2000,
+    0x384a4000,
+    0x384a6000,
+    0x384a8000,
+    0x384aa000,
+    0x384ac000,
+    0x384ae000,
+    0x384b0000,
+    0x384b2000,
+    0x384b4000,
+    0x384b6000,
+    0x384b8000,
+    0x384ba000,
+    0x384bc000,
+    0x384be000,
+    0x384c0000,
+    0x384c2000,
+    0x384c4000,
+    0x384c6000,
+    0x384c8000,
+    0x384ca000,
+    0x384cc000,
+    0x384ce000,
+    0x384d0000,
+    0x384d2000,
+    0x384d4000,
+    0x384d6000,
+    0x384d8000,
+    0x384da000,
+    0x384dc000,
+    0x384de000,
+    0x384e0000,
+    0x384e2000,
+    0x384e4000,
+    0x384e6000,
+    0x384e8000,
+    0x384ea000,
+    0x384ec000,
+    0x384ee000,
+    0x384f0000,
+    0x384f2000,
+    0x384f4000,
+    0x384f6000,
+    0x384f8000,
+    0x384fa000,
+    0x384fc000,
+    0x384fe000,
+    0x38500000,
+    0x38502000,
+    0x38504000,
+    0x38506000,
+    0x38508000,
+    0x3850a000,
+    0x3850c000,
+    0x3850e000,
+    0x38510000,
+    0x38512000,
+    0x38514000,
+    0x38516000,
+    0x38518000,
+    0x3851a000,
+    0x3851c000,
+    0x3851e000,
+    0x38520000,
+    0x38522000,
+    0x38524000,
+    0x38526000,
+    0x38528000,
+    0x3852a000,
+    0x3852c000,
+    0x3852e000,
+    0x38530000,
+    0x38532000,
+    0x38534000,
+    0x38536000,
+    0x38538000,
+    0x3853a000,
+    0x3853c000,
+    0x3853e000,
+    0x38540000,
+    0x38542000,
+    0x38544000,
+    0x38546000,
+    0x38548000,
+    0x3854a000,
+    0x3854c000,
+    0x3854e000,
+    0x38550000,
+    0x38552000,
+    0x38554000,
+    0x38556000,
+    0x38558000,
+    0x3855a000,
+    0x3855c000,
+    0x3855e000,
+    0x38560000,
+    0x38562000,
+    0x38564000,
+    0x38566000,
+    0x38568000,
+    0x3856a000,
+    0x3856c000,
+    0x3856e000,
+    0x38570000,
+    0x38572000,
+    0x38574000,
+    0x38576000,
+    0x38578000,
+    0x3857a000,
+    0x3857c000,
+    0x3857e000,
+    0x38580000,
+    0x38582000,
+    0x38584000,
+    0x38586000,
+    0x38588000,
+    0x3858a000,
+    0x3858c000,
+    0x3858e000,
+    0x38590000,
+    0x38592000,
+    0x38594000,
+    0x38596000,
+    0x38598000,
+    0x3859a000,
+    0x3859c000,
+    0x3859e000,
+    0x385a0000,
+    0x385a2000,
+    0x385a4000,
+    0x385a6000,
+    0x385a8000,
+    0x385aa000,
+    0x385ac000,
+    0x385ae000,
+    0x385b0000,
+    0x385b2000,
+    0x385b4000,
+    0x385b6000,
+    0x385b8000,
+    0x385ba000,
+    0x385bc000,
+    0x385be000,
+    0x385c0000,
+    0x385c2000,
+    0x385c4000,
+    0x385c6000,
+    0x385c8000,
+    0x385ca000,
+    0x385cc000,
+    0x385ce000,
+    0x385d0000,
+    0x385d2000,
+    0x385d4000,
+    0x385d6000,
+    0x385d8000,
+    0x385da000,
+    0x385dc000,
+    0x385de000,
+    0x385e0000,
+    0x385e2000,
+    0x385e4000,
+    0x385e6000,
+    0x385e8000,
+    0x385ea000,
+    0x385ec000,
+    0x385ee000,
+    0x385f0000,
+    0x385f2000,
+    0x385f4000,
+    0x385f6000,
+    0x385f8000,
+    0x385fa000,
+    0x385fc000,
+    0x385fe000,
+    0x38600000,
+    0x38602000,
+    0x38604000,
+    0x38606000,
+    0x38608000,
+    0x3860a000,
+    0x3860c000,
+    0x3860e000,
+    0x38610000,
+    0x38612000,
+    0x38614000,
+    0x38616000,
+    0x38618000,
+    0x3861a000,
+    0x3861c000,
+    0x3861e000,
+    0x38620000,
+    0x38622000,
+    0x38624000,
+    0x38626000,
+    0x38628000,
+    0x3862a000,
+    0x3862c000,
+    0x3862e000,
+    0x38630000,
+    0x38632000,
+    0x38634000,
+    0x38636000,
+    0x38638000,
+    0x3863a000,
+    0x3863c000,
+    0x3863e000,
+    0x38640000,
+    0x38642000,
+    0x38644000,
+    0x38646000,
+    0x38648000,
+    0x3864a000,
+    0x3864c000,
+    0x3864e000,
+    0x38650000,
+    0x38652000,
+    0x38654000,
+    0x38656000,
+    0x38658000,
+    0x3865a000,
+    0x3865c000,
+    0x3865e000,
+    0x38660000,
+    0x38662000,
+    0x38664000,
+    0x38666000,
+    0x38668000,
+    0x3866a000,
+    0x3866c000,
+    0x3866e000,
+    0x38670000,
+    0x38672000,
+    0x38674000,
+    0x38676000,
+    0x38678000,
+    0x3867a000,
+    0x3867c000,
+    0x3867e000,
+    0x38680000,
+    0x38682000,
+    0x38684000,
+    0x38686000,
+    0x38688000,
+    0x3868a000,
+    0x3868c000,
+    0x3868e000,
+    0x38690000,
+    0x38692000,
+    0x38694000,
+    0x38696000,
+    0x38698000,
+    0x3869a000,
+    0x3869c000,
+    0x3869e000,
+    0x386a0000,
+    0x386a2000,
+    0x386a4000,
+    0x386a6000,
+    0x386a8000,
+    0x386aa000,
+    0x386ac000,
+    0x386ae000,
+    0x386b0000,
+    0x386b2000,
+    0x386b4000,
+    0x386b6000,
+    0x386b8000,
+    0x386ba000,
+    0x386bc000,
+    0x386be000,
+    0x386c0000,
+    0x386c2000,
+    0x386c4000,
+    0x386c6000,
+    0x386c8000,
+    0x386ca000,
+    0x386cc000,
+    0x386ce000,
+    0x386d0000,
+    0x386d2000,
+    0x386d4000,
+    0x386d6000,
+    0x386d8000,
+    0x386da000,
+    0x386dc000,
+    0x386de000,
+    0x386e0000,
+    0x386e2000,
+    0x386e4000,
+    0x386e6000,
+    0x386e8000,
+    0x386ea000,
+    0x386ec000,
+    0x386ee000,
+    0x386f0000,
+    0x386f2000,
+    0x386f4000,
+    0x386f6000,
+    0x386f8000,
+    0x386fa000,
+    0x386fc000,
+    0x386fe000,
+    0x38700000,
+    0x38702000,
+    0x38704000,
+    0x38706000,
+    0x38708000,
+    0x3870a000,
+    0x3870c000,
+    0x3870e000,
+    0x38710000,
+    0x38712000,
+    0x38714000,
+    0x38716000,
+    0x38718000,
+    0x3871a000,
+    0x3871c000,
+    0x3871e000,
+    0x38720000,
+    0x38722000,
+    0x38724000,
+    0x38726000,
+    0x38728000,
+    0x3872a000,
+    0x3872c000,
+    0x3872e000,
+    0x38730000,
+    0x38732000,
+    0x38734000,
+    0x38736000,
+    0x38738000,
+    0x3873a000,
+    0x3873c000,
+    0x3873e000,
+    0x38740000,
+    0x38742000,
+    0x38744000,
+    0x38746000,
+    0x38748000,
+    0x3874a000,
+    0x3874c000,
+    0x3874e000,
+    0x38750000,
+    0x38752000,
+    0x38754000,
+    0x38756000,
+    0x38758000,
+    0x3875a000,
+    0x3875c000,
+    0x3875e000,
+    0x38760000,
+    0x38762000,
+    0x38764000,
+    0x38766000,
+    0x38768000,
+    0x3876a000,
+    0x3876c000,
+    0x3876e000,
+    0x38770000,
+    0x38772000,
+    0x38774000,
+    0x38776000,
+    0x38778000,
+    0x3877a000,
+    0x3877c000,
+    0x3877e000,
+    0x38780000,
+    0x38782000,
+    0x38784000,
+    0x38786000,
+    0x38788000,
+    0x3878a000,
+    0x3878c000,
+    0x3878e000,
+    0x38790000,
+    0x38792000,
+    0x38794000,
+    0x38796000,
+    0x38798000,
+    0x3879a000,
+    0x3879c000,
+    0x3879e000,
+    0x387a0000,
+    0x387a2000,
+    0x387a4000,
+    0x387a6000,
+    0x387a8000,
+    0x387aa000,
+    0x387ac000,
+    0x387ae000,
+    0x387b0000,
+    0x387b2000,
+    0x387b4000,
+    0x387b6000,
+    0x387b8000,
+    0x387ba000,
+    0x387bc000,
+    0x387be000,
+    0x387c0000,
+    0x387c2000,
+    0x387c4000,
+    0x387c6000,
+    0x387c8000,
+    0x387ca000,
+    0x387cc000,
+    0x387ce000,
+    0x387d0000,
+    0x387d2000,
+    0x387d4000,
+    0x387d6000,
+    0x387d8000,
+    0x387da000,
+    0x387dc000,
+    0x387de000,
+    0x387e0000,
+    0x387e2000,
+    0x387e4000,
+    0x387e6000,
+    0x387e8000,
+    0x387ea000,
+    0x387ec000,
+    0x387ee000,
+    0x387f0000,
+    0x387f2000,
+    0x387f4000,
+    0x387f6000,
+    0x387f8000,
+    0x387fa000,
+    0x387fc000,
+    0x387fe000,
+};
+
+const static unsigned g_exponent[64] = {
+    0x00000000,
+    0x00800000,
+    0x01000000,
+    0x01800000,
+    0x02000000,
+    0x02800000,
+    0x03000000,
+    0x03800000,
+    0x04000000,
+    0x04800000,
+    0x05000000,
+    0x05800000,
+    0x06000000,
+    0x06800000,
+    0x07000000,
+    0x07800000,
+    0x08000000,
+    0x08800000,
+    0x09000000,
+    0x09800000,
+    0x0a000000,
+    0x0a800000,
+    0x0b000000,
+    0x0b800000,
+    0x0c000000,
+    0x0c800000,
+    0x0d000000,
+    0x0d800000,
+    0x0e000000,
+    0x0e800000,
+    0x0f000000,
+    0x47800000,
+    0x80000000,
+    0x80800000,
+    0x81000000,
+    0x81800000,
+    0x82000000,
+    0x82800000,
+    0x83000000,
+    0x83800000,
+    0x84000000,
+    0x84800000,
+    0x85000000,
+    0x85800000,
+    0x86000000,
+    0x86800000,
+    0x87000000,
+    0x87800000,
+    0x88000000,
+    0x88800000,
+    0x89000000,
+    0x89800000,
+    0x8a000000,
+    0x8a800000,
+    0x8b000000,
+    0x8b800000,
+    0x8c000000,
+    0x8c800000,
+    0x8d000000,
+    0x8d800000,
+    0x8e000000,
+    0x8e800000,
+    0x8f000000,
+    0xc7800000,
+};
+
+const static unsigned g_offset[64] = {
+    0x00000000,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000000,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+};
+
+float float16ToFloat32(unsigned short h)
+{
+    unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
+    return bitCast<float>(i32);
+}
+}
+
diff --git a/src/third_party/angle/src/common/Float16ToFloat32.py b/src/third_party/angle/src/common/Float16ToFloat32.py
new file mode 100644
index 0000000..7705f7b
--- /dev/null
+++ b/src/third_party/angle/src/common/Float16ToFloat32.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+# This script generates a function that converts 16-bit precision floating
+# point numbers to 32-bit.
+# It is based on ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf.
+
+#include "common/mathutil.h"
+
+def convertMantissa(i):
+    if i == 0:
+        return 0
+    elif i < 1024:
+        m = i << 13
+        e = 0
+        while not (m & 0x00800000):
+            e -= 0x00800000
+            m = m << 1
+        m &= ~0x00800000
+        e += 0x38800000
+        return m | e
+    else:
+        return 0x38000000 + ((i - 1024) << 13)
+
+def convertExponent(i):
+    if i == 0:
+        return 0
+    elif i in range(1, 31):
+        return i << 23
+    elif i == 31:
+        return 0x47800000
+    elif i == 32:
+        return 0x80000000
+    elif i in range(33, 63):
+        return 0x80000000 + ((i - 32) << 23)
+    else:
+        return 0xC7800000
+
+def convertOffset(i):
+    if i == 0 or i == 32:
+        return 0
+    else:
+        return 1024
+
+print """//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is automatically generated.
+
+namespace gl
+{
+"""
+
+print "const static unsigned g_mantissa[2048] = {"
+for i in range(0, 2048):
+    print "    %#010x," % convertMantissa(i)
+print "};\n"
+
+print "const static unsigned g_exponent[64] = {"
+for i in range(0, 64):
+    print "    %#010x," % convertExponent(i)
+print "};\n"
+
+print "const static unsigned g_offset[64] = {"
+for i in range(0, 64):
+    print "    %#010x," % convertOffset(i)
+print "};\n"
+
+print """float float16ToFloat32(unsigned short h)
+{
+    unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
+    return bitCast<float>(i32);
+}
+}
+"""
diff --git a/src/third_party/angle/src/common/MemoryBuffer.cpp b/src/third_party/angle/src/common/MemoryBuffer.cpp
new file mode 100644
index 0000000..c624572
--- /dev/null
+++ b/src/third_party/angle/src/common/MemoryBuffer.cpp
@@ -0,0 +1,141 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "common/MemoryBuffer.h"
+
+#include <algorithm>
+#include <cstdlib>
+
+#include "common/debug.h"
+
+namespace angle
+{
+
+// MemoryBuffer implementation.
+MemoryBuffer::MemoryBuffer() : mSize(0), mData(nullptr)
+{
+}
+
+MemoryBuffer::~MemoryBuffer()
+{
+    free(mData);
+    mData = nullptr;
+}
+
+bool MemoryBuffer::resize(size_t size)
+{
+    if (size == 0)
+    {
+        free(mData);
+        mData = nullptr;
+        mSize = 0;
+        return true;
+    }
+
+    if (size == mSize)
+    {
+        return true;
+    }
+
+    // Only reallocate if the size has changed.
+    uint8_t *newMemory = reinterpret_cast<uint8_t *>(malloc(sizeof(uint8_t) * size));
+    if (newMemory == nullptr)
+    {
+        return false;
+    }
+
+    if (mData)
+    {
+        // Copy the intersection of the old data and the new data
+        std::copy(mData, mData + std::min(mSize, size), newMemory);
+        free(mData);
+    }
+
+    mData = newMemory;
+    mSize = size;
+
+    return true;
+}
+
+size_t MemoryBuffer::size() const
+{
+    return mSize;
+}
+
+const uint8_t *MemoryBuffer::data() const
+{
+    return mData;
+}
+
+uint8_t *MemoryBuffer::data()
+{
+    ASSERT(mData);
+    return mData;
+}
+
+void MemoryBuffer::fill(uint8_t datum)
+{
+    if (!empty())
+    {
+        std::fill(mData, mData + mSize, datum);
+    }
+}
+
+// ScratchBuffer implementation.
+
+ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime)
+{
+}
+
+ScratchBuffer::~ScratchBuffer()
+{
+}
+
+bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
+{
+    if (mScratchMemory.size() == requestedSize)
+    {
+        mResetCounter    = mLifetime;
+        *memoryBufferOut = &mScratchMemory;
+        return true;
+    }
+
+    if (mScratchMemory.size() > requestedSize)
+    {
+        tick();
+    }
+
+    if (mResetCounter == 0 || mScratchMemory.size() < requestedSize)
+    {
+        mScratchMemory.resize(0);
+        if (!mScratchMemory.resize(requestedSize))
+        {
+            return false;
+        }
+        mResetCounter = mLifetime;
+    }
+
+    ASSERT(mScratchMemory.size() >= requestedSize);
+
+    *memoryBufferOut = &mScratchMemory;
+    return true;
+}
+
+void ScratchBuffer::tick()
+{
+    if (mResetCounter > 0)
+    {
+        --mResetCounter;
+    }
+}
+
+void ScratchBuffer::clear()
+{
+    mResetCounter = mLifetime;
+    mScratchMemory.resize(0);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/common/MemoryBuffer.h b/src/third_party/angle/src/common/MemoryBuffer.h
new file mode 100644
index 0000000..dd346b2
--- /dev/null
+++ b/src/third_party/angle/src/common/MemoryBuffer.h
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMMON_MEMORYBUFFER_H_
+#define COMMON_MEMORYBUFFER_H_
+
+#include "common/angleutils.h"
+
+#include <stdint.h>
+#include <cstddef>
+
+namespace angle
+{
+
+class MemoryBuffer final : NonCopyable
+{
+  public:
+    MemoryBuffer();
+    ~MemoryBuffer();
+
+    bool resize(size_t size);
+    size_t size() const;
+    bool empty() const { return mSize == 0; }
+
+    const uint8_t *data() const;
+    uint8_t *data();
+
+    void fill(uint8_t datum);
+
+  private:
+    size_t mSize;
+    uint8_t *mData;
+};
+
+class ScratchBuffer final : NonCopyable
+{
+  public:
+    // If we request a scratch buffer requesting a smaller size this many times, release and
+    // recreate the scratch buffer. This ensures we don't have a degenerate case where we are stuck
+    // hogging memory.
+    ScratchBuffer(uint32_t lifetime);
+    ~ScratchBuffer();
+
+    // Returns true with a memory buffer of the requested size, or false on failure.
+    bool get(size_t requestedSize, MemoryBuffer **memoryBufferOut);
+
+    // Ticks the release counter for the scratch buffer. Also done implicitly in get().
+    void tick();
+
+    void clear();
+
+  private:
+    const uint32_t mLifetime;
+    uint32_t mResetCounter;
+    MemoryBuffer mScratchMemory;
+};
+
+}  // namespace angle
+
+#endif  // COMMON_MEMORYBUFFER_H_
diff --git a/src/third_party/angle/src/common/Optional.h b/src/third_party/angle/src/common/Optional.h
new file mode 100644
index 0000000..992a76e7
--- /dev/null
+++ b/src/third_party/angle/src/common/Optional.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Optional.h:
+//   Represents a type that may be invalid, similar to std::optional.
+//
+
+#ifndef COMMON_OPTIONAL_H_
+#define COMMON_OPTIONAL_H_
+
+#include <utility>
+
+template <class T>
+struct Optional
+{
+    Optional() : mValid(false), mValue(T()) {}
+
+    Optional(const T &valueIn) : mValid(true), mValue(valueIn) {}
+
+    Optional(const Optional &other) : mValid(other.mValid), mValue(other.mValue) {}
+
+    Optional &operator=(const Optional &other)
+    {
+        this->mValid = other.mValid;
+        this->mValue = other.mValue;
+        return *this;
+    }
+
+    Optional &operator=(const T &value)
+    {
+        mValue = value;
+        mValid = true;
+        return *this;
+    }
+
+    Optional &operator=(T &&value)
+    {
+        mValue = std::move(value);
+        mValid = true;
+        return *this;
+    }
+
+    void reset() { mValid = false; }
+
+    static Optional Invalid() { return Optional(); }
+
+    bool valid() const { return mValid; }
+    const T &value() const { return mValue; }
+
+    bool operator==(const Optional &other) const
+    {
+        return ((mValid == other.mValid) && (!mValid || (mValue == other.mValue)));
+    }
+
+    bool operator!=(const Optional &other) const { return !(*this == other); }
+
+  private:
+    bool mValid;
+    T mValue;
+};
+
+#endif  // COMMON_OPTIONAL_H_
diff --git a/src/third_party/angle/src/common/Optional_unittest.cpp b/src/third_party/angle/src/common/Optional_unittest.cpp
new file mode 100644
index 0000000..8100461
--- /dev/null
+++ b/src/third_party/angle/src/common/Optional_unittest.cpp
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Unit tests for ANGLE's Optional helper class.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "common/Optional.h"
+
+namespace
+{
+
+TEST(OptionalTest, BasicInvalid)
+{
+    Optional<int> testInvalid;
+    ASSERT_FALSE(testInvalid.valid());
+    ASSERT_EQ(Optional<int>::Invalid(), testInvalid);
+}
+
+TEST(OptionalTest, BasicValid)
+{
+    Optional<int> testValid(3);
+    ASSERT_TRUE(testValid.valid());
+    ASSERT_EQ(3, testValid.value());
+    ASSERT_NE(Optional<int>::Invalid(), testValid);
+}
+
+TEST(OptionalTest, Copies)
+{
+    Optional<int> testValid(3);
+    Optional<int> testInvalid;
+
+    Optional<int> testCopy = testInvalid;
+    ASSERT_FALSE(testCopy.valid());
+    ASSERT_EQ(testInvalid, testCopy);
+
+    testCopy = testValid;
+    ASSERT_TRUE(testCopy.valid());
+    ASSERT_EQ(3, testCopy.value());
+    ASSERT_EQ(testValid, testCopy);
+}
+
+} // namespace
diff --git a/src/third_party/angle/src/common/RefCountObject.cpp b/src/third_party/angle/src/common/RefCountObject.cpp
deleted file mode 100644
index 0364adf..0000000
--- a/src/third_party/angle/src/common/RefCountObject.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RefCountObject.cpp: Defines the gl::RefCountObject base class that provides
-// lifecycle support for GL objects using the traditional BindObject scheme, but
-// that need to be reference counted for correct cross-context deletion.
-// (Concretely, textures, buffers and renderbuffers.)
-
-#include "RefCountObject.h"
-
-RefCountObject::RefCountObject(GLuint id)
-{
-    mId = id;
-    mRefCount = 0;
-}
-
-RefCountObject::~RefCountObject()
-{
-    ASSERT(mRefCount == 0);
-}
-
-void RefCountObject::addRef() const
-{
-    mRefCount++;
-}
-
-void RefCountObject::release() const
-{
-    ASSERT(mRefCount > 0);
-
-    if (--mRefCount == 0)
-    {
-        delete this;
-    }
-}
-
-void RefCountObjectBindingPointer::set(RefCountObject *newObject)
-{
-    // addRef first in case newObject == mObject and this is the last reference to it.
-    if (newObject != NULL) newObject->addRef();
-    if (mObject != NULL) mObject->release();
-
-    mObject = newObject;
-}
diff --git a/src/third_party/angle/src/common/RefCountObject.h b/src/third_party/angle/src/common/RefCountObject.h
deleted file mode 100644
index 727c71c..0000000
--- a/src/third_party/angle/src/common/RefCountObject.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RefCountObject.h: Defines the gl::RefCountObject base class that provides
-// lifecycle support for GL objects using the traditional BindObject scheme, but
-// that need to be reference counted for correct cross-context deletion.
-// (Concretely, textures, buffers and renderbuffers.)
-
-#ifndef COMMON_REFCOUNTOBJECT_H_
-#define COMMON_REFCOUNTOBJECT_H_
-
-#include <cstddef>
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
-#include "common/debug.h"
-
-class RefCountObject
-{
-  public:
-    explicit RefCountObject(GLuint id);
-    virtual ~RefCountObject();
-
-    virtual void addRef() const;
-    virtual void release() const;
-
-    GLuint id() const { return mId; }
-    
-  private:
-    GLuint mId;
-
-    mutable std::size_t mRefCount;
-};
-
-class RefCountObjectBindingPointer
-{
-  protected:
-    RefCountObjectBindingPointer() : mObject(NULL) { }
-    ~RefCountObjectBindingPointer() { ASSERT(mObject == NULL); } // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up.
-
-    void set(RefCountObject *newObject);
-    RefCountObject *get() const { return mObject; }
-
-  public:
-    GLuint id() const { return (mObject != NULL) ? mObject->id() : 0; }
-    bool operator ! () const { return (get() == NULL); }
-
-  private:
-    RefCountObject *mObject;
-};
-
-template <class ObjectType>
-class BindingPointer : public RefCountObjectBindingPointer
-{
-  public:
-    void set(ObjectType *newObject) { RefCountObjectBindingPointer::set(newObject); }
-    ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); }
-    ObjectType *operator -> () const { return get(); }
-};
-
-#endif   // COMMON_REFCOUNTOBJECT_H_
diff --git a/src/third_party/angle/src/common/angleutils.cpp b/src/third_party/angle/src/common/angleutils.cpp
new file mode 100644
index 0000000..67db1ec
--- /dev/null
+++ b/src/third_party/angle/src/common/angleutils.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+#include <stdio.h>
+
+#include <limits>
+#include <vector>
+
+namespace angle
+{
+const uintptr_t DirtyPointer = std::numeric_limits<uintptr_t>::max();
+}
+
+size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
+{
+    // The state of the va_list passed to vsnprintf is undefined after the call, do a copy in case
+    // we need to grow the buffer.
+    va_list varargCopy;
+    va_copy(varargCopy, vararg);
+
+    // Attempt to just print to the current buffer
+    int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, varargCopy);
+    va_end(varargCopy);
+
+    if (len < 0 || static_cast<size_t>(len) >= outBuffer.size())
+    {
+        // Buffer was not large enough, calculate the required size and resize the buffer
+        len = vsnprintf(nullptr, 0, fmt, vararg);
+        outBuffer.resize(len + 1);
+
+        // Print again
+        va_copy(varargCopy, vararg);
+        len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, varargCopy);
+        va_end(varargCopy);
+    }
+    ASSERT(len >= 0);
+    return static_cast<size_t>(len);
+}
+
+std::string FormatString(const char *fmt, va_list vararg)
+{
+    static std::vector<char> buffer(512);
+
+    size_t len = FormatStringIntoVector(fmt, vararg, buffer);
+    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);
+    return result;
+}
diff --git a/src/third_party/angle/src/common/angleutils.h b/src/third_party/angle/src/common/angleutils.h
index 9761567..1cbb968 100644
--- a/src/third_party/angle/src/common/angleutils.h
+++ b/src/third_party/angle/src/common/angleutils.h
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// 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.
 //
@@ -9,16 +9,40 @@
 #ifndef COMMON_ANGLEUTILS_H_
 #define COMMON_ANGLEUTILS_H_
 
-#include <stddef.h>
+#include "common/platform.h"
 
-// A macro to disallow the copy constructor and operator= functions
-// This must be used in the private: declarations for a class
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&);               \
-  void operator=(const TypeName&)
+#include <climits>
+#include <cstdarg>
+#include <cstddef>
+#include <string>
+#include <set>
+#include <sstream>
+#include <vector>
 
-template <typename T, unsigned int N>
-inline unsigned int ArraySize(T(&)[N])
+// A helper class to disallow copy and assignment operators
+namespace angle
+{
+
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+using Microsoft::WRL::ComPtr;
+#endif  // defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+
+class NonCopyable
+{
+  protected:
+    NonCopyable() = default;
+    ~NonCopyable() = default;
+
+  private:
+    NonCopyable(const NonCopyable&) = delete;
+    void operator=(const NonCopyable&) = delete;
+};
+
+extern const uintptr_t DirtyPointer;
+}  // namespace angle
+
+template <typename T, size_t N>
+constexpr inline size_t ArraySize(T (&)[N])
 {
     return N;
 }
@@ -38,19 +62,131 @@
     if (resource)
     {
         resource->Release();
-        resource = NULL;
+        resource = nullptr;
     }
 }
 
-#if defined(_MSC_VER)
+template <typename T>
+void SafeDelete(T *&resource)
+{
+    delete resource;
+    resource = nullptr;
+}
+
+template <typename T>
+void SafeDeleteContainer(T& resource)
+{
+    for (auto &element : resource)
+    {
+        SafeDelete(element);
+    }
+    resource.clear();
+}
+
+template <typename T>
+void SafeDeleteArray(T*& resource)
+{
+    delete[] resource;
+    resource = nullptr;
+}
+
+// Provide a less-than function for comparing structs
+// Note: struct memory must be initialized to zero, because of packing gaps
+template <typename T>
+inline bool StructLessThan(const T &a, const T &b)
+{
+    return (memcmp(&a, &b, sizeof(T)) < 0);
+}
+
+// Provide a less-than function for comparing structs
+// Note: struct memory must be initialized to zero, because of packing gaps
+template <typename T>
+inline bool StructEquals(const T &a, const T &b)
+{
+    return (memcmp(&a, &b, sizeof(T)) == 0);
+}
+
+template <typename T>
+inline void StructZero(T *obj)
+{
+    memset(obj, 0, sizeof(T));
+}
+
+template <typename T>
+inline bool IsMaskFlagSet(T mask, T flag)
+{
+    // Handles multibit flags as well
+    return (mask & flag) == flag;
+}
+
+inline const char* MakeStaticString(const std::string &str)
+{
+    static std::set<std::string> strings;
+    std::set<std::string>::iterator it = strings.find(str);
+    if (it != strings.end())
+    {
+        return it->c_str();
+    }
+
+    return strings.insert(str).first->c_str();
+}
+
+inline std::string ArrayString(unsigned int i)
+{
+    // We assume UINT_MAX and GL_INVALID_INDEX are equal
+    // See DynamicHLSL.cpp
+    if (i == UINT_MAX)
+    {
+        return "";
+    }
+
+    std::stringstream strstr;
+
+    strstr << "[";
+    strstr << i;
+    strstr << "]";
+
+    return strstr.str();
+}
+
+inline std::string Str(int i)
+{
+    std::stringstream strstr;
+    strstr << i;
+    return strstr.str();
+}
+
+size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& buffer);
+
+std::string FormatString(const char *fmt, va_list vararg);
+std::string FormatString(const char *fmt, ...);
+
+template <typename T>
+std::string ToString(const T &value)
+{
+    std::ostringstream o;
+    o << value;
+    return o.str();
+}
+
+// snprintf is not defined with MSVC prior to to msvc14
+#if defined(_MSC_VER) && _MSC_VER < 1900
 #define snprintf _snprintf
 #endif
 
-#define VENDOR_ID_AMD 0x1002
-#define VENDOR_ID_INTEL 0x8086
-#define VENDOR_ID_NVIDIA 0x10DE
-
+#define GL_BGR565_ANGLEX 0x6ABB
 #define GL_BGRA4_ANGLEX 0x6ABC
 #define GL_BGR5_A1_ANGLEX 0x6ABD
+#define GL_INT_64_ANGLEX 0x6ABE
+#define GL_STRUCT_ANGLEX 0x6ABF
+
+// Hidden enum for the NULL D3D device type.
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0
+
+#define ANGLE_TRY_CHECKED_MATH(result)                               \
+    if (!result.IsValid())                                           \
+    {                                                                \
+        return gl::Error(GL_INVALID_OPERATION, "Integer overflow."); \
+    }
 
 #endif // COMMON_ANGLEUTILS_H_
diff --git a/src/third_party/angle/src/common/bitset_utils.h b/src/third_party/angle/src/common/bitset_utils.h
new file mode 100644
index 0000000..7276735
--- /dev/null
+++ b/src/third_party/angle/src/common/bitset_utils.h
@@ -0,0 +1,498 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// bitset_utils:
+//   Bitset-related helper classes, such as a fast iterator to scan for set bits.
+//
+
+#ifndef COMMON_BITSETITERATOR_H_
+#define COMMON_BITSETITERATOR_H_
+
+#include <stdint.h>
+
+#include <bitset>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+
+namespace angle
+{
+
+template <size_t N, typename BitsT>
+class BitSetT final
+{
+  public:
+    class Reference final
+    {
+      public:
+        ~Reference() {}
+        Reference &operator=(bool x)
+        {
+            mParent->set(mBit, x);
+            return *this;
+        }
+        operator bool() const { return mParent->test(mBit); }
+
+      private:
+        friend class BitSetT;
+
+        Reference(BitSetT *parent, std::size_t bit) : mParent(parent), mBit(bit) {}
+
+        BitSetT *mParent;
+        std::size_t mBit;
+    };
+
+    class Iterator final
+    {
+      public:
+        Iterator(const BitSetT &bits);
+        Iterator &operator++();
+
+        bool operator==(const Iterator &other) const;
+        bool operator!=(const Iterator &other) const;
+        std::size_t operator*() const;
+
+      private:
+        std::size_t getNextBit();
+
+        BitSetT mBitsCopy;
+        std::size_t mCurrentBit;
+    };
+
+    BitSetT();
+    BitSetT(BitsT value);
+    ~BitSetT();
+
+    BitSetT(const BitSetT &other);
+    BitSetT &operator=(const BitSetT &other);
+
+    bool operator==(const BitSetT &other) const;
+    bool operator!=(const BitSetT &other) const;
+
+    constexpr bool operator[](std::size_t pos) const;
+    Reference operator[](std::size_t pos) { return Reference(this, pos); }
+
+    bool test(std::size_t pos) const;
+
+    bool all() const;
+    bool any() const;
+    bool none() const;
+    std::size_t count() const;
+
+    constexpr std::size_t size() const { return N; }
+
+    BitSetT &operator&=(const BitSetT &other);
+    BitSetT &operator|=(const BitSetT &other);
+    BitSetT &operator^=(const BitSetT &other);
+    BitSetT operator~() const;
+
+    BitSetT operator<<(std::size_t pos) const;
+    BitSetT &operator<<=(std::size_t pos);
+    BitSetT operator>>(std::size_t pos) const;
+    BitSetT &operator>>=(std::size_t pos);
+
+    BitSetT &set();
+    BitSetT &set(std::size_t pos, bool value = true);
+
+    BitSetT &reset();
+    BitSetT &reset(std::size_t pos);
+
+    BitSetT &flip();
+    BitSetT &flip(std::size_t pos);
+
+    unsigned long to_ulong() const { return static_cast<unsigned long>(mBits); }
+    BitsT bits() const { return mBits; }
+
+    Iterator begin() const { return Iterator(*this); }
+    Iterator end() const { return Iterator(BitSetT()); }
+
+  private:
+    constexpr static BitsT Bit(std::size_t x) { return (static_cast<BitsT>(1) << x); }
+    constexpr static BitsT Mask(std::size_t x) { return ((Bit(x - 1) - 1) << 1) + 1; }
+
+    BitsT mBits;
+};
+
+template <size_t N>
+class IterableBitSet : public std::bitset<N>
+{
+  public:
+    IterableBitSet() {}
+    IterableBitSet(const std::bitset<N> &implicitBitSet) : std::bitset<N>(implicitBitSet) {}
+
+    class Iterator final
+    {
+      public:
+        Iterator(const std::bitset<N> &bits);
+        Iterator &operator++();
+
+        bool operator==(const Iterator &other) const;
+        bool operator!=(const Iterator &other) const;
+        unsigned long operator*() const { return mCurrentBit; }
+
+      private:
+        unsigned long getNextBit();
+
+        static constexpr size_t BitsPerWord = sizeof(uint32_t) * 8;
+        std::bitset<N> mBits;
+        unsigned long mCurrentBit;
+        unsigned long mOffset;
+    };
+
+    Iterator begin() const { return Iterator(*this); }
+    Iterator end() const { return Iterator(std::bitset<N>(0)); }
+};
+
+template <size_t N>
+IterableBitSet<N>::Iterator::Iterator(const std::bitset<N> &bitset)
+    : mBits(bitset), mCurrentBit(0), mOffset(0)
+{
+    if (mBits.any())
+    {
+        mCurrentBit = getNextBit();
+    }
+    else
+    {
+        mOffset = static_cast<unsigned long>(rx::roundUp(N, BitsPerWord));
+    }
+}
+
+template <size_t N>
+typename IterableBitSet<N>::Iterator &IterableBitSet<N>::Iterator::operator++()
+{
+    ASSERT(mBits.any());
+    mBits.set(mCurrentBit - mOffset, 0);
+    mCurrentBit = getNextBit();
+    return *this;
+}
+
+template <size_t N>
+bool IterableBitSet<N>::Iterator::operator==(const Iterator &other) const
+{
+    return mOffset == other.mOffset && mBits == other.mBits;
+}
+
+template <size_t N>
+bool IterableBitSet<N>::Iterator::operator!=(const Iterator &other) const
+{
+    return !(*this == other);
+}
+
+template <size_t N>
+unsigned long IterableBitSet<N>::Iterator::getNextBit()
+{
+    // TODO(jmadill): Use 64-bit scan when possible.
+    static constexpr std::bitset<N> wordMask(std::numeric_limits<uint32_t>::max());
+
+    while (mOffset < N)
+    {
+        uint32_t wordBits = static_cast<uint32_t>((mBits & wordMask).to_ulong());
+        if (wordBits != 0)
+        {
+            return gl::ScanForward(wordBits) + mOffset;
+        }
+
+        mBits >>= BitsPerWord;
+        mOffset += BitsPerWord;
+    }
+    return 0;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::BitSetT() : mBits(0)
+{
+    static_assert(N > 0, "Bitset type cannot support zero bits.");
+    static_assert(N <= sizeof(BitsT) * 8, "Bitset type cannot support a size this large.");
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::BitSetT(BitsT value) : mBits(value & Mask(N))
+{
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::~BitSetT()
+{
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::BitSetT(const BitSetT &other) : mBits(other.mBits)
+{
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator=(const BitSetT &other)
+{
+    mBits = other.mBits;
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::operator==(const BitSetT &other) const
+{
+    return mBits == other.mBits;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::operator!=(const BitSetT &other) const
+{
+    return mBits != other.mBits;
+}
+
+template <size_t N, typename BitsT>
+constexpr bool BitSetT<N, BitsT>::operator[](std::size_t pos) const
+{
+    return test(pos);
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::test(std::size_t pos) const
+{
+    return (mBits & Bit(pos)) != 0;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::all() const
+{
+    ASSERT(mBits == (mBits & Mask(N)));
+    return mBits == Mask(N);
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::any() const
+{
+    ASSERT(mBits == (mBits & Mask(N)));
+    return (mBits != 0);
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::none() const
+{
+    ASSERT(mBits == (mBits & Mask(N)));
+    return (mBits == 0);
+}
+
+template <size_t N, typename BitsT>
+std::size_t BitSetT<N, BitsT>::count() const
+{
+    return gl::BitCount(mBits);
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator&=(const BitSetT &other)
+{
+    mBits &= other.mBits;
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator|=(const BitSetT &other)
+{
+    mBits |= other.mBits;
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator^=(const BitSetT &other)
+{
+    mBits = (mBits ^ other.mBits) & Mask(N);
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> BitSetT<N, BitsT>::operator~() const
+{
+    return BitSetT<N, BitsT>(~mBits & Mask(N));
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> BitSetT<N, BitsT>::operator<<(std::size_t pos) const
+{
+    return BitSetT<N, BitsT>((mBits << pos) & Mask(N));
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator<<=(std::size_t pos)
+{
+    mBits = (mBits << pos & Mask(N));
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> BitSetT<N, BitsT>::operator>>(std::size_t pos) const
+{
+    return BitSetT<N, BitsT>(mBits >> pos);
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator>>=(std::size_t pos)
+{
+    mBits = ((mBits >> pos) & Mask(N));
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::set()
+{
+    mBits = Mask(N);
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::set(std::size_t pos, bool value)
+{
+    if (value)
+    {
+        mBits |= Bit(pos);
+    }
+    else
+    {
+        reset(pos);
+    }
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::reset()
+{
+    mBits = 0;
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::reset(std::size_t pos)
+{
+    mBits &= ~Bit(pos);
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::flip()
+{
+    mBits ^= Mask(N);
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::flip(std::size_t pos)
+{
+    mBits ^= Bit(pos);
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(bits), mCurrentBit(0)
+{
+    if (bits.any())
+    {
+        mCurrentBit = getNextBit();
+    }
+}
+
+template <size_t N, typename BitsT>
+typename BitSetT<N, BitsT>::Iterator &BitSetT<N, BitsT>::Iterator::operator++()
+{
+    ASSERT(mBitsCopy.any());
+    mBitsCopy.reset(mCurrentBit);
+    mCurrentBit = getNextBit();
+    return *this;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::Iterator::operator==(const Iterator &other) const
+{
+    return mBitsCopy == other.mBitsCopy;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::Iterator::operator!=(const Iterator &other) const
+{
+    return !(*this == other);
+}
+
+template <size_t N, typename BitsT>
+std::size_t BitSetT<N, BitsT>::Iterator::operator*() const
+{
+    return mCurrentBit;
+}
+
+template <size_t N, typename BitsT>
+std::size_t BitSetT<N, BitsT>::Iterator::getNextBit()
+{
+    if (mBitsCopy.none())
+    {
+        return 0;
+    }
+
+    return gl::ScanForward(mBitsCopy.mBits);
+}
+
+template <size_t N>
+using BitSet32 = BitSetT<N, uint32_t>;
+
+// ScanForward for 64-bits requires a 64-bit implementation.
+#if defined(ANGLE_X64_CPU)
+template <size_t N>
+using BitSet64 = BitSetT<N, uint64_t>;
+#endif  // defined(ANGLE_X64_CPU)
+
+namespace priv
+{
+
+template <size_t N, typename T>
+using EnableIfBitsFit = typename std::enable_if<N <= sizeof(T) * 8>::type;
+
+template <size_t N, typename Enable = void>
+struct GetBitSet
+{
+    using Type = IterableBitSet<N>;
+};
+
+// Prefer 64-bit bitsets on 64-bit CPUs. They seem faster than 32-bit.
+#if defined(ANGLE_X64_CPU)
+template <size_t N>
+struct GetBitSet<N, EnableIfBitsFit<N, uint64_t>>
+{
+    using Type = BitSet64<N>;
+};
+#else
+template <size_t N>
+struct GetBitSet<N, EnableIfBitsFit<N, uint32_t>>
+{
+    using Type = BitSet32<N>;
+};
+#endif  // defined(ANGLE_X64_CPU)
+
+}  // namespace priv
+
+template <size_t N>
+using BitSet = typename priv::GetBitSet<N>::Type;
+
+}  // angle
+
+template <size_t N, typename BitsT>
+inline angle::BitSetT<N, BitsT> operator&(const angle::BitSetT<N, BitsT> &lhs,
+                                          const angle::BitSetT<N, BitsT> &rhs)
+{
+    return angle::BitSetT<N, BitsT>(lhs.bits() & rhs.bits());
+}
+
+template <size_t N, typename BitsT>
+inline angle::BitSetT<N, BitsT> operator|(const angle::BitSetT<N, BitsT> &lhs,
+                                          const angle::BitSetT<N, BitsT> &rhs)
+{
+    return angle::BitSetT<N, BitsT>(lhs.bits() | rhs.bits());
+}
+
+template <size_t N, typename BitsT>
+inline angle::BitSetT<N, BitsT> operator^(const angle::BitSetT<N, BitsT> &lhs,
+                                          const angle::BitSetT<N, BitsT> &rhs)
+{
+    return angle::BitSetT<N, BitsT>(lhs.bits() ^ rhs.bits());
+}
+
+#endif  // COMMON_BITSETITERATOR_H_
diff --git a/src/third_party/angle/src/common/bitset_utils_unittest.cpp b/src/third_party/angle/src/common/bitset_utils_unittest.cpp
new file mode 100644
index 0000000..3394890
--- /dev/null
+++ b/src/third_party/angle/src/common/bitset_utils_unittest.cpp
@@ -0,0 +1,112 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// bitset_utils_unittest:
+//   Tests bitset helpers and custom classes.
+//
+
+#include <gtest/gtest.h>
+
+#include "common/bitset_utils.h"
+
+using namespace angle;
+
+namespace
+{
+class BitSetIteratorTest : public testing::Test
+{
+  protected:
+    BitSet<40> mStateBits;
+};
+
+// Simple iterator test.
+TEST_F(BitSetIteratorTest, Iterator)
+{
+    std::set<size_t> originalValues;
+    originalValues.insert(2);
+    originalValues.insert(6);
+    originalValues.insert(8);
+    originalValues.insert(35);
+
+    for (size_t value : originalValues)
+    {
+        mStateBits.set(value);
+    }
+
+    std::set<size_t> readValues;
+    for (size_t bit : mStateBits)
+    {
+        EXPECT_EQ(1u, originalValues.count(bit));
+        EXPECT_EQ(0u, readValues.count(bit));
+        readValues.insert(bit);
+    }
+
+    EXPECT_EQ(originalValues.size(), readValues.size());
+}
+
+// Test an empty iterator.
+TEST_F(BitSetIteratorTest, EmptySet)
+{
+    // We don't use the FAIL gtest macro here since it returns immediately,
+    // causing an unreachable code warning in MSVS
+    bool sawBit = false;
+    for (size_t bit : mStateBits)
+    {
+        sawBit = true;
+        UNUSED_VARIABLE(bit);
+    }
+    EXPECT_FALSE(sawBit);
+}
+
+// Test iterating a result of combining two bitsets.
+TEST_F(BitSetIteratorTest, NonLValueBitset)
+{
+    BitSet<40> otherBits;
+
+    mStateBits.set(1);
+    mStateBits.set(2);
+    mStateBits.set(3);
+    mStateBits.set(4);
+
+    otherBits.set(0);
+    otherBits.set(1);
+    otherBits.set(3);
+    otherBits.set(5);
+
+    std::set<size_t> seenBits;
+
+    angle::BitSet<40> maskedBits = (mStateBits & otherBits);
+    for (size_t bit : maskedBits)
+    {
+        EXPECT_EQ(0u, seenBits.count(bit));
+        seenBits.insert(bit);
+        EXPECT_TRUE(mStateBits[bit]);
+        EXPECT_TRUE(otherBits[bit]);
+    }
+
+    EXPECT_EQ((mStateBits & otherBits).count(), seenBits.size());
+}
+
+// Test bit assignments.
+TEST_F(BitSetIteratorTest, BitAssignment)
+{
+    std::set<size_t> originalValues;
+    originalValues.insert(2);
+    originalValues.insert(6);
+    originalValues.insert(8);
+    originalValues.insert(35);
+
+    for (size_t value : originalValues)
+    {
+        (mStateBits[value] = false) = true;
+    }
+
+    for (size_t value : originalValues)
+    {
+        EXPECT_TRUE(mStateBits.test(value));
+    }
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/common/debug.cpp b/src/third_party/angle/src/common/debug.cpp
index 3727ec4..597e9d6 100644
--- a/src/third_party/angle/src/common/debug.cpp
+++ b/src/third_party/angle/src/common/debug.cpp
@@ -7,108 +7,207 @@
 // debug.cpp: Debugging utilities.
 
 #include "common/debug.h"
-#if !defined(ANGLE_DISABLE_PERF)
-#include "common/debugperf.h"
-#else
-typedef void (*PerfOutputFunction)();
-#endif
-#include "common/system.h"
+
+#include <stdarg.h>
+
+#include <array>
+#include <cstdio>
+#include <fstream>
+#include <ostream>
+#include <vector>
+
+#include "common/angleutils.h"
+#include "common/Optional.h"
 
 namespace gl
 {
 
-static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg)
+namespace
 {
-#if !defined(ANGLE_DISABLE_PERF)
-    if (gl::perfActive())
-    {
-        char message[32768];
-        int len = vsprintf_s(message, format, vararg);
-        if (len < 0)
-        {
-            return;
-        }
 
-        // There are no ASCII variants of these D3DPERF functions.
-        wchar_t wideMessage[32768];
-        for (int i = 0; i < len; ++i)
-        {
-            wideMessage[i] = message[i];
-        }
-        wideMessage[len] = 0;
+DebugAnnotator *g_debugAnnotator = nullptr;
 
-        perfFunc(0, wideMessage);
-    } else {
-#if defined(__LB_SHELL__FORCE_LOGGING__)
-        vprintf(format, vararg);
-#endif
-    }
-#endif
+constexpr std::array<const char *, LOG_NUM_SEVERITIES> g_logSeverityNames = {
+    {"EVENT", "WARN", "ERR"}};
 
-#if !defined(ANGLE_DISABLE_TRACE)
-#if defined(NDEBUG)
-    if (traceFileDebugOnly)
-    {
-        return;
-    }
-#endif
-
-    FILE* file = fopen(TRACE_OUTPUT_FILE, "a");
-    if (file)
-    {
-        vfprintf(file, format, vararg);
-        fclose(file);
-    }
-#endif
+constexpr const char *LogSeverityName(int severity)
+{
+    return (severity >= 0 && severity < LOG_NUM_SEVERITIES) ? g_logSeverityNames[severity]
+                                                            : "UNKNOWN";
 }
 
-void trace(bool traceFileDebugOnly, const char *format, ...)
+bool ShouldCreateLogMessage(LogSeverity severity)
 {
-#if !defined(ANGLE_DISABLE_PERF) || !defined(ANGLE_DISABLE_TRACE)
-    va_list vararg;
-    va_start(vararg, format);
-#if defined(ANGLE_DISABLE_PERF)
-    output(traceFileDebugOnly, NULL, format, vararg);
+#if defined(ANGLE_TRACE_ENABLED)
+    return true;
+#elif defined(ANGLE_ENABLE_ASSERTS)
+    return severity == LOG_ERR;
 #else
-    output(traceFileDebugOnly, gl::perfSetMarker, format, vararg);
-#endif
-    va_end(vararg);
-#endif
-}
-
-bool perfActive()
-{
-#if defined(ANGLE_DISABLE_PERF)
     return false;
-#else
-    static bool active = gl::perfCheckActive();
-    return active;
 #endif
 }
 
-ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
+}  // namespace
+
+namespace priv
 {
-#if !defined(ANGLE_DISABLE_PERF)
-#if defined(ANGLE_DISABLE_TRACE)
-    if (!perfActive())
+
+bool ShouldCreatePlatformLogMessage(LogSeverity severity)
+{
+#if defined(ANGLE_TRACE_ENABLED)
+    return true;
+#else
+    return severity != LOG_EVENT;
+#endif
+}
+
+}  // namespace priv
+
+bool DebugAnnotationsActive()
+{
+#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+    return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus();
+#else
+    return false;
+#endif
+}
+
+bool DebugAnnotationsInitialized()
+{
+    return g_debugAnnotator != nullptr;
+}
+
+void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator)
+{
+    UninitializeDebugAnnotations();
+    g_debugAnnotator = debugAnnotator;
+}
+
+void UninitializeDebugAnnotations()
+{
+    // Pointer is not managed.
+    g_debugAnnotator = nullptr;
+}
+
+ScopedPerfEventHelper::ScopedPerfEventHelper(const char *format, ...)
+{
+#if !defined(ANGLE_ENABLE_DEBUG_TRACE)
+    if (!DebugAnnotationsActive())
     {
         return;
     }
-#endif
+#endif  // !ANGLE_ENABLE_DEBUG_TRACE
+
     va_list vararg;
     va_start(vararg, format);
-    output(true, reinterpret_cast<PerfOutputFunction>(gl::perfBeginEvent), format, vararg);
+    std::vector<char> buffer(512);
+    size_t len = FormatStringIntoVector(format, vararg, buffer);
+    ANGLE_LOG(EVENT) << std::string(&buffer[0], len);
     va_end(vararg);
-#endif
 }
 
 ScopedPerfEventHelper::~ScopedPerfEventHelper()
 {
-#if !defined(ANGLE_DISABLE_PERF)
-    if (gl::perfActive())
+    if (DebugAnnotationsActive())
     {
-        gl::perfEndEvent();
+        g_debugAnnotator->endEvent();
+    }
+}
+
+LogMessage::LogMessage(const char *function, int line, LogSeverity severity)
+    : mFunction(function), mLine(line), mSeverity(severity)
+{
+    // EVENT() does not require additional function(line) info.
+    if (mSeverity != LOG_EVENT)
+    {
+        mStream << mFunction << "(" << mLine << "): ";
+    }
+}
+
+LogMessage::~LogMessage()
+{
+    if (DebugAnnotationsInitialized() && (mSeverity == LOG_ERR || mSeverity == LOG_WARN))
+    {
+        g_debugAnnotator->logMessage(*this);
+    }
+    else
+    {
+        Trace(getSeverity(), getMessage().c_str());
+    }
+}
+
+void Trace(LogSeverity severity, const char *message)
+{
+    if (!ShouldCreateLogMessage(severity))
+    {
+        return;
+    }
+
+    std::string str(message);
+
+    if (DebugAnnotationsActive())
+    {
+        std::wstring formattedWideMessage(str.begin(), str.end());
+
+        switch (severity)
+        {
+            case LOG_EVENT:
+                g_debugAnnotator->beginEvent(formattedWideMessage.c_str());
+                break;
+            default:
+                g_debugAnnotator->setMarker(formattedWideMessage.c_str());
+                break;
+        }
+    }
+
+    if (severity == LOG_ERR)
+    {
+        // Note: we use fprintf because <iostream> includes static initializers.
+        fprintf(stderr, "%s: %s\n", LogSeverityName(severity), str.c_str());
+    }
+
+#if defined(ANGLE_PLATFORM_WINDOWS) && \
+    (defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) || !defined(NDEBUG))
+#if !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
+    if (severity == LOG_ERR)
+#endif  // !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
+    {
+        OutputDebugStringA(str.c_str());
     }
 #endif
+
+#if defined(ANGLE_ENABLE_DEBUG_TRACE)
+#if defined(NDEBUG)
+    if (severity == LOG_EVENT || severity == LOG_WARN)
+    {
+        return;
+    }
+#endif  // defined(NDEBUG)
+    static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
+    if (file)
+    {
+        file << LogSeverityName(severity) << ": " << str << std::endl;
+        file.flush();
+    }
+#endif  // defined(ANGLE_ENABLE_DEBUG_TRACE)
 }
+
+LogSeverity LogMessage::getSeverity() const
+{
+    return mSeverity;
 }
+
+std::string LogMessage::getMessage() const
+{
+    return mStream.str();
+}
+
+#if defined(ANGLE_PLATFORM_WINDOWS)
+std::ostream &operator<<(std::ostream &os, const FmtHR &fmt)
+{
+    os << "HRESULT: ";
+    return FmtHexInt(os, fmt.mHR);
+}
+#endif  // defined(ANGLE_PLATFORM_WINDOWS)
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/common/debug.h b/src/third_party/angle/src/common/debug.h
index 442a2a5..0108ff6 100644
--- a/src/third_party/angle/src/common/debug.h
+++ b/src/third_party/angle/src/common/debug.h
@@ -9,142 +9,266 @@
 #ifndef COMMON_DEBUG_H_
 #define COMMON_DEBUG_H_
 
-#include <stdio.h>
 #include <assert.h>
+#include <stdio.h>
 
-#if defined(__LB_XB360__) && defined(NDEBUG) && defined(__LB_SHELL__FORCE_LOGGING__)
-#include <crtdbg.h>
-// on xbox360, NDEBUG defines assert() to nop
-#define lbassert(expression) do { \
-    if (!(expression)) \
-        _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, NULL, #expression); \
-} while (0)
-#else
-#define lbassert(expression) assert(expression)
-#endif
-
-#if defined(__LB_XB360__) && defined(NDEBUG)
-// on xbox360, 'D3DPERF API is not available'
-// this prevents unnecessary calls into gl::trace()
-#define ANGLE_DISABLE_PERF
-#endif
+#include <ios>
+#include <iomanip>
+#include <sstream>
+#include <string>
 
 #include "common/angleutils.h"
 
 #if !defined(TRACE_OUTPUT_FILE)
-#define TRACE_OUTPUT_FILE "debug.txt"
+#define TRACE_OUTPUT_FILE "angle_debug.txt"
 #endif
 
 namespace gl
 {
-    // Outputs text to the debugging log
-    void trace(bool traceFileDebugOnly, const char *format, ...);
 
-    // Returns whether D3DPERF is active.
-    bool perfActive();
+// Pairs a D3D begin event with an end event.
+class ScopedPerfEventHelper : angle::NonCopyable
+{
+  public:
+    ScopedPerfEventHelper(const char* format, ...);
+    ~ScopedPerfEventHelper();
+};
 
-    // Pairs a D3D begin event with an end event.
-    class ScopedPerfEventHelper
-    {
-      public:
-        ScopedPerfEventHelper(const char* format, ...);
-        ~ScopedPerfEventHelper();
+using LogSeverity = int;
+// Note: the log severities are used to index into the array of names,
+// see g_logSeverityNames.
+constexpr LogSeverity LOG_EVENT          = 0;
+constexpr LogSeverity LOG_WARN           = 1;
+constexpr LogSeverity LOG_ERR            = 2;
+constexpr LogSeverity LOG_NUM_SEVERITIES = 3;
 
-      private:
-        DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper);
-    };
+void Trace(LogSeverity severity, const char *message);
+
+// This class more or less represents a particular log message.  You
+// create an instance of LogMessage and then stream stuff to it.
+// When you finish streaming to it, ~LogMessage is called and the
+// full message gets streamed to the appropriate destination.
+//
+// You shouldn't actually use LogMessage's constructor to log things,
+// though.  You should use the ERR() and WARN() macros.
+class LogMessage : angle::NonCopyable
+{
+  public:
+    // Used for ANGLE_LOG(severity).
+    LogMessage(const char *function, int line, LogSeverity severity);
+    ~LogMessage();
+    std::ostream &stream() { return mStream; }
+
+    LogSeverity getSeverity() const;
+    std::string getMessage() const;
+
+  private:
+    const char *mFunction;
+    const int mLine;
+    const LogSeverity mSeverity;
+
+    std::ostringstream mStream;
+};
+
+// Wraps the D3D9/D3D11 debug annotation functions.
+// Also handles redirecting logging destination.
+class DebugAnnotator : angle::NonCopyable
+{
+  public:
+    DebugAnnotator(){};
+    virtual ~DebugAnnotator() { };
+    virtual void beginEvent(const wchar_t *eventName) = 0;
+    virtual void endEvent() = 0;
+    virtual void setMarker(const wchar_t *markerName) = 0;
+    virtual bool getStatus() = 0;
+    // Log Message Handler that gets passed every log message,
+    // when debug annotations are initialized,
+    // replacing default handling by LogMessage.
+    virtual void logMessage(const LogMessage &msg) const = 0;
+};
+
+void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
+void UninitializeDebugAnnotations();
+bool DebugAnnotationsActive();
+bool DebugAnnotationsInitialized();
+
+namespace priv
+{
+// This class is used to explicitly ignore values in the conditional logging macros. This avoids
+// compiler warnings like "value computed is not used" and "statement has no effect".
+class LogMessageVoidify
+{
+  public:
+    LogMessageVoidify() {}
+    // This has to be an operator with a precedence lower than << but higher than ?:
+    void operator&(std::ostream &) {}
+};
+
+// Used by ANGLE_LOG_IS_ON to lazy-evaluate stream arguments.
+bool ShouldCreatePlatformLogMessage(LogSeverity severity);
+
+template <int N, typename T>
+std::ostream &FmtHex(std::ostream &os, T value)
+{
+    os << "0x";
+
+    std::ios_base::fmtflags oldFlags = os.flags();
+    std::streamsize oldWidth         = os.width();
+    std::ostream::char_type oldFill  = os.fill();
+
+    os << std::hex << std::uppercase << std::setw(N) << std::setfill('0') << value;
+
+    os.flags(oldFlags);
+    os.width(oldWidth);
+    os.fill(oldFill);
+
+    return os;
+}
+}  // namespace priv
+
+#if defined(ANGLE_PLATFORM_WINDOWS)
+class FmtHR
+{
+  public:
+    explicit FmtHR(HRESULT hresult) : mHR(hresult) {}
+  private:
+    HRESULT mHR;
+    friend std::ostream &operator<<(std::ostream &os, const FmtHR &fmt);
+};
+#endif  // defined(ANGLE_PLATFORM_WINDOWS)
+
+template <typename T>
+std::ostream &FmtHexShort(std::ostream &os, T value)
+{
+    return priv::FmtHex<4>(os, value);
 }
 
-#if (defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)) || \
-    defined(__LB_SHELL__FOR_RELEASE__)
-#define DONT_USE_GL_TRACE
+template <typename T>
+std::ostream &FmtHexInt(std::ostream &os, T value)
+{
+    return priv::FmtHex<8>(os, value);
+}
+
+// A few definitions of macros that don't generate much code. These are used
+// by ANGLE_LOG(). Since these are used all over our code, it's
+// better to have compact code for these operations.
+#define COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ...) \
+    ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_EVENT, ##__VA_ARGS__)
+#define COMPACT_ANGLE_LOG_EX_WARN(ClassName, ...) \
+    ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_WARN, ##__VA_ARGS__)
+#define COMPACT_ANGLE_LOG_EX_ERR(ClassName, ...) \
+    ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_ERR, ##__VA_ARGS__)
+
+#define COMPACT_ANGLE_LOG_EVENT COMPACT_ANGLE_LOG_EX_EVENT(LogMessage)
+#define COMPACT_ANGLE_LOG_WARN COMPACT_ANGLE_LOG_EX_WARN(LogMessage)
+#define COMPACT_ANGLE_LOG_ERR COMPACT_ANGLE_LOG_EX_ERR(LogMessage)
+
+#define ANGLE_LOG_IS_ON(severity) (::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_##severity))
+
+// Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold.
+// Condition is evaluated once and only once.
+#define ANGLE_LAZY_STREAM(stream, condition) \
+    !(condition) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify() & (stream)
+
+// We use the preprocessor's merging operator, "##", so that, e.g.,
+// ANGLE_LOG(EVENT) becomes the token COMPACT_ANGLE_LOG_EVENT.  There's some funny
+// subtle difference between ostream member streaming functions (e.g.,
+// ostream::operator<<(int) and ostream non-member streaming functions
+// (e.g., ::operator<<(ostream&, string&): it turns out that it's
+// impossible to stream something like a string directly to an unnamed
+// ostream. We employ a neat hack by calling the stream() member
+// function of LogMessage which seems to avoid the problem.
+#define ANGLE_LOG_STREAM(severity) COMPACT_ANGLE_LOG_##severity.stream()
+
+#define ANGLE_LOG(severity) ANGLE_LAZY_STREAM(ANGLE_LOG_STREAM(severity), ANGLE_LOG_IS_ON(severity))
+
+}  // namespace gl
+
+#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+#define ANGLE_TRACE_ENABLED
 #endif
 
-// A macro to output a trace of a function call and its arguments to the debugging log
-#if defined(DONT_USE_GL_TRACE)
-#define TRACE(message, ...) (void(0))
-#else
-#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define ANGLE_EMPTY_STATEMENT for (;;) break
+#if !defined(NDEBUG) || defined(ANGLE_ENABLE_RELEASE_ASSERTS)
+#define ANGLE_ENABLE_ASSERTS
 #endif
 
-// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
-#if defined(DONT_USE_GL_TRACE)
-#if defined(__LB_SHELL__FORCE_LOGGING__)
-#define FIXME(message, ...) printf("fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define FIXME(message, ...) (void(0))
-#endif
-#else
-#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-
-// A macro to output a function call and its arguments to the debugging log, in case of error.
-#if defined(DONT_USE_GL_TRACE)
-#if defined(__LB_SHELL__FORCE_LOGGING__)
-#define ERR(message, ...) printf("err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define ERR(message, ...) (void(0))
-#endif
-#else
-#define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
+#define WARN() ANGLE_LOG(WARN)
+#define ERR() ANGLE_LOG(ERR)
 
 // A macro to log a performance event around a scope.
-#if defined(DONT_USE_GL_TRACE)
-#define EVENT(message, ...) (void(0))
-#elif defined(_MSC_VER)
-#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__(__FUNCTION__ message "\n", __VA_ARGS__);
+#if defined(ANGLE_TRACE_ENABLED)
+#if defined(_MSC_VER)
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
 #else
-#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper(message "\n", ##__VA_ARGS__);
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper("%s" message "\n", __FUNCTION__, ##__VA_ARGS__);
+#endif // _MSC_VER
+#else
+#define EVENT(message, ...) (void(0))
 #endif
 
+#if defined(COMPILER_GCC) || defined(__clang__)
+#define ANGLE_CRASH() __builtin_trap()
+#else
+#define ANGLE_CRASH() ((void)(*(volatile char *)0 = 0))
+#endif
+
+#if !defined(NDEBUG)
+#define ANGLE_ASSERT_IMPL(expression) assert(expression)
+#else
+// TODO(jmadill): Detect if debugger is attached and break.
+#define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH()
+#endif  // !defined(NDEBUG)
+
 // A macro asserting a condition and outputting failures to the debug log
-#if !defined(NDEBUG) || defined(__LB_SHELL__FORCE_LOGGING__)
-#define ASSERT(expression) do { \
-    if(!(expression)) \
-        ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
-    lbassert(expression); \
-} while(0)
+#if defined(ANGLE_ENABLE_ASSERTS)
+#define ASSERT(expression)                                                                         \
+    (expression ? static_cast<void>(0) : ((ERR() << "\t! Assert failed in " << __FUNCTION__ << "(" \
+                                                 << __LINE__ << "): " << #expression),             \
+                                          ANGLE_ASSERT_IMPL(expression)))
 #else
-#define ASSERT(expression) (void(0))
-#endif
+// These are just dummy values.
+#define COMPACT_ANGLE_LOG_EX_ASSERT(ClassName, ...) \
+    COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ##__VA_ARGS__)
+#define COMPACT_ANGLE_LOG_ASSERT COMPACT_ANGLE_LOG_EVENT
+namespace gl
+{
+constexpr LogSeverity LOG_ASSERT = LOG_EVENT;
+}  // namespace gl
+
+#define ASSERT(condition)                                                     \
+    ANGLE_LAZY_STREAM(ANGLE_LOG_STREAM(ASSERT), false ? !(condition) : false) \
+        << "Check failed: " #condition ". "
+#endif  // defined(ANGLE_ENABLE_ASSERTS)
+
+#define UNUSED_VARIABLE(variable) ((void)variable)
 
 // A macro to indicate unimplemented functionality
-#if !defined(NDEBUG) || defined(__LB_SHELL__FORCE_LOGGING__)
-#if defined (__LB_SHELL__)
-#define UNIMPLEMENTED() do { \
-    static int count = 0; \
-    if (count++ != 0) break; \
-    FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
-} while(0)
-#else
-#define UNIMPLEMENTED() do { \
-    FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
-    lbassert(false); \
-} while(0)
-#endif // __LB_SHELL__
-#else
-    #define UNIMPLEMENTED() FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__)
+#ifndef NOASSERT_UNIMPLEMENTED
+#define NOASSERT_UNIMPLEMENTED 1
 #endif
 
+#if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
+#define UNIMPLEMENTED()                                                           \
+    {                                                                             \
+        ERR() << "\t! Unimplemented: " << __FUNCTION__ << "(" << __LINE__ << ")"; \
+        ASSERT(NOASSERT_UNIMPLEMENTED);                                           \
+    }                                                                             \
+    ANGLE_EMPTY_STATEMENT
+
 // A macro for code which is not expected to be reached under valid assumptions
-#if !defined(NDEBUG) || defined(__LB_SHELL__FORCE_LOGGING__)
-#define UNREACHABLE() do { \
-    ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
-    lbassert(false); \
-} while(0)
+#define UNREACHABLE()                                                                  \
+    ((ERR() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __LINE__ << ")"), \
+     ASSERT(false))
 #else
-    #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__)
-#endif
+#define UNIMPLEMENTED()                 \
+    {                                   \
+        ASSERT(NOASSERT_UNIMPLEMENTED); \
+    }                                   \
+    ANGLE_EMPTY_STATEMENT
 
-// A macro that determines whether an object has a given runtime type.
-#if !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI))
-#define HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type >(obj) != NULL)
-#else
-#define HAS_DYNAMIC_TYPE(type, obj) true
-#endif
-
-// A macro functioning as a compile-time assert to validate constant conditions
-#define META_ASSERT(condition) typedef int COMPILE_TIME_ASSERT_##__LINE__[static_cast<bool>(condition)?1:-1]
+// A macro for code which is not expected to be reached under valid assumptions
+#define UNREACHABLE() ASSERT(false)
+#endif  // defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
 
 #endif   // COMMON_DEBUG_H_
diff --git a/src/third_party/angle/src/common/debugperf.h b/src/third_party/angle/src/common/debugperf.h
deleted file mode 100644
index f77aa6b..0000000
--- a/src/third_party/angle/src/common/debugperf.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// debug_platform.h: Platform specific debugging utilities.
-
-#ifndef COMMON_DEBUG_PLATFORM_H_
-#define COMMON_DEBUG_PLATFORM_H_
-
-namespace gl
-{
-typedef unsigned int Color;
-typedef void (*PerfOutputFunction)(Color, const wchar_t*);
-
-#if defined(__LB_SHELL__FOR_RELEASE__)
-
-// Allow compile time optimizations to remove more debugging code
-
-static bool perfCheckActive() { return false; }
-static void perfSetMarker(Color col, const wchar_t* name) { }
-static void perfBeginEvent(Color col, const wchar_t* name) { }
-static void perfEndEvent() { }
-
-#else
-
-bool perfCheckActive();
-void perfSetMarker(Color col, const wchar_t* name);
-void perfBeginEvent(Color col, const wchar_t* name);
-void perfEndEvent();
-
-#endif
-}
-
-#endif   // COMMON_DEBUG_PLATFORM_H_
diff --git a/src/third_party/angle/src/common/event_tracer.cpp b/src/third_party/angle/src/common/event_tracer.cpp
new file mode 100644
index 0000000..6dc8458
--- /dev/null
+++ b/src/third_party/angle/src/common/event_tracer.cpp
@@ -0,0 +1,55 @@
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/event_tracer.h"
+
+#include "common/debug.h"
+
+namespace angle
+{
+
+const unsigned char *GetTraceCategoryEnabledFlag(const char *name)
+{
+    auto *platform = ANGLEPlatformCurrent();
+    ASSERT(platform);
+
+    const unsigned char *categoryEnabledFlag =
+        platform->getTraceCategoryEnabledFlag(platform, name);
+    if (categoryEnabledFlag != nullptr)
+    {
+        return categoryEnabledFlag;
+    }
+
+    static unsigned char disabled = 0;
+    return &disabled;
+}
+
+angle::TraceEventHandle AddTraceEvent(char phase,
+                                      const unsigned char *categoryGroupEnabled,
+                                      const char *name,
+                                      unsigned long long id,
+                                      int numArgs,
+                                      const char **argNames,
+                                      const unsigned char *argTypes,
+                                      const unsigned long long *argValues,
+                                      unsigned char flags)
+{
+    auto *platform = ANGLEPlatformCurrent();
+    ASSERT(platform);
+
+    double timestamp = platform->monotonicallyIncreasingTime(platform);
+
+    if (timestamp != 0)
+    {
+        angle::TraceEventHandle handle =
+            platform->addTraceEvent(platform, phase, categoryGroupEnabled, name, id, timestamp,
+                                    numArgs, argNames, argTypes, argValues, flags);
+        ASSERT(handle != 0);
+        return handle;
+    }
+
+    return static_cast<angle::TraceEventHandle>(0);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/common/event_tracer.h b/src/third_party/angle/src/common/event_tracer.h
new file mode 100644
index 0000000..9b30c75
--- /dev/null
+++ b/src/third_party/angle/src/common/event_tracer.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_EVENT_TRACER_H_
+#define COMMON_EVENT_TRACER_H_
+
+#include "common/platform.h"
+#include "platform/Platform.h"
+
+namespace angle
+{
+
+const unsigned char *GetTraceCategoryEnabledFlag(const char* name);
+angle::TraceEventHandle AddTraceEvent(char phase,
+                                      const unsigned char *categoryGroupEnabled,
+                                      const char *name,
+                                      unsigned long long id,
+                                      int numArgs,
+                                      const char **argNames,
+                                      const unsigned char *argTypes,
+                                      const unsigned long long *argValues,
+                                      unsigned char flags);
+}
+
+#endif  // COMMON_EVENT_TRACER_H_
diff --git a/src/third_party/angle/src/common/mathutil.cpp b/src/third_party/angle/src/common/mathutil.cpp
new file mode 100644
index 0000000..5db997c
--- /dev/null
+++ b/src/third_party/angle/src/common/mathutil.cpp
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// mathutil.cpp: Math and bit manipulation functions.
+
+#include "common/mathutil.h"
+
+#include <algorithm>
+#include <math.h>
+
+namespace gl
+{
+
+namespace
+{
+
+struct RGB9E5Data
+{
+    unsigned int R : 9;
+    unsigned int G : 9;
+    unsigned int B : 9;
+    unsigned int E : 5;
+};
+
+// B is the exponent bias (15)
+constexpr int g_sharedexp_bias = 15;
+
+// N is the number of mantissa bits per component (9)
+constexpr int g_sharedexp_mantissabits = 9;
+
+// Emax is the maximum allowed biased exponent value (31)
+constexpr int g_sharedexp_maxexponent = 31;
+
+constexpr float g_sharedexp_max =
+    ((static_cast<float>(1 << g_sharedexp_mantissabits) - 1) /
+     static_cast<float>(1 << g_sharedexp_mantissabits)) *
+    static_cast<float>(1 << (g_sharedexp_maxexponent - g_sharedexp_bias));
+
+}  // anonymous namespace
+
+unsigned int convertRGBFloatsTo999E5(float red, float green, float blue)
+{
+    const float red_c = std::max<float>(0, std::min(g_sharedexp_max, red));
+    const float green_c = std::max<float>(0, std::min(g_sharedexp_max, green));
+    const float blue_c = std::max<float>(0, std::min(g_sharedexp_max, blue));
+
+    const float max_c = std::max<float>(std::max<float>(red_c, green_c), blue_c);
+    const float exp_p = std::max<float>(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias;
+    const int max_s = static_cast<int>(floor((max_c / (pow(2.0f, exp_p - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
+    const int exp_s = static_cast<int>((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1);
+
+    RGB9E5Data output;
+    output.R = static_cast<unsigned int>(floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
+    output.G = static_cast<unsigned int>(floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
+    output.B = static_cast<unsigned int>(floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
+    output.E = exp_s;
+
+    return bitCast<unsigned int>(output);
+}
+
+void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue)
+{
+    const RGB9E5Data *inputData = reinterpret_cast<const RGB9E5Data*>(&input);
+
+    *red = inputData->R * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
+    *green = inputData->G * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
+    *blue = inputData->B * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/common/mathutil.h b/src/third_party/angle/src/common/mathutil.h
new file mode 100644
index 0000000..71cfb2f
--- /dev/null
+++ b/src/third_party/angle/src/common/mathutil.h
@@ -0,0 +1,1094 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// mathutil.h: Math and bit manipulation functions.
+
+#ifndef COMMON_MATHUTIL_H_
+#define COMMON_MATHUTIL_H_
+
+#include <limits>
+#include <algorithm>
+#include <math.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <base/numerics/safe_math.h>
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+namespace angle
+{
+using base::CheckedNumeric;
+using base::IsValueInRangeForNumericType;
+}
+
+namespace gl
+{
+
+const unsigned int Float32One = 0x3F800000;
+const unsigned short Float16One = 0x3C00;
+
+template<typename T>
+inline bool isPow2(T x)
+{
+    static_assert(std::is_integral<T>::value, "isPow2 must be called on an integer type.");
+    return (x & (x - 1)) == 0 && (x != 0);
+}
+
+inline int log2(int x)
+{
+    int r = 0;
+    while ((x >> r) > 1) r++;
+    return r;
+}
+
+inline unsigned int ceilPow2(unsigned int x)
+{
+    if (x != 0) x--;
+    x |= x >> 1;
+    x |= x >> 2;
+    x |= x >> 4;
+    x |= x >> 8;
+    x |= x >> 16;
+    x++;
+
+    return x;
+}
+
+inline int clampToInt(unsigned int x)
+{
+    return static_cast<int>(std::min(x, static_cast<unsigned int>(std::numeric_limits<int>::max())));
+}
+
+template <typename DestT, typename SrcT>
+inline DestT clampCast(SrcT value)
+{
+    static const DestT destLo = std::numeric_limits<DestT>::min();
+    static const DestT destHi = std::numeric_limits<DestT>::max();
+    static const SrcT srcLo = static_cast<SrcT>(destLo);
+    static const SrcT srcHi = static_cast<SrcT>(destHi);
+
+    // When value is outside of or equal to the limits for DestT we use the DestT limit directly.
+    // This avoids undefined behaviors due to loss of precision when converting from floats to
+    // integers:
+    //    destHi for ints is 2147483647 but the closest float number is around 2147483648, so when
+    //  doing a conversion from float to int we run into an UB because the float is outside of the
+    //  range representable by the int.
+    if (value <= srcLo)
+    {
+        return destLo;
+    }
+    else if (value >= srcHi)
+    {
+        return destHi;
+    }
+    else
+    {
+        return static_cast<DestT>(value);
+    }
+}
+
+template<typename T, typename MIN, typename MAX>
+inline T clamp(T x, MIN min, MAX max)
+{
+    // Since NaNs fail all comparison tests, a NaN value will default to min
+    return x > min ? (x > max ? max : x) : min;
+}
+
+inline float clamp01(float x)
+{
+    return clamp(x, 0.0f, 1.0f);
+}
+
+template<const int n>
+inline unsigned int unorm(float x)
+{
+    const unsigned int max = 0xFFFFFFFF >> (32 - n);
+
+    if (x > 1)
+    {
+        return max;
+    }
+    else if (x < 0)
+    {
+        return 0;
+    }
+    else
+    {
+        return (unsigned int)(max * x + 0.5f);
+    }
+}
+
+inline bool supportsSSE2()
+{
+#if defined(ANGLE_USE_SSE)
+    static bool checked = false;
+    static bool supports = false;
+
+    if (checked)
+    {
+        return supports;
+    }
+
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
+    {
+        int info[4];
+        __cpuid(info, 0);
+
+        if (info[0] >= 1)
+        {
+            __cpuid(info, 1);
+
+            supports = (info[3] >> 26) & 1;
+        }
+    }
+#endif  // defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
+    checked = true;
+    return supports;
+#else  // defined(ANGLE_USE_SSE)
+    return false;
+#endif
+}
+
+template <typename destType, typename sourceType>
+destType bitCast(const sourceType &source)
+{
+    size_t copySize = std::min(sizeof(destType), sizeof(sourceType));
+    destType output;
+    memcpy(&output, &source, copySize);
+    return output;
+}
+
+inline unsigned short float32ToFloat16(float fp32)
+{
+    unsigned int fp32i = bitCast<unsigned int>(fp32);
+    unsigned int sign = (fp32i & 0x80000000) >> 16;
+    unsigned int abs = fp32i & 0x7FFFFFFF;
+
+    if(abs > 0x47FFEFFF)   // Infinity
+    {
+        return static_cast<unsigned short>(sign | 0x7FFF);
+    }
+    else if(abs < 0x38800000)   // Denormal
+    {
+        unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
+        int e = 113 - (abs >> 23);
+
+        if(e < 24)
+        {
+            abs = mantissa >> e;
+        }
+        else
+        {
+            abs = 0;
+        }
+
+        return static_cast<unsigned short>(sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
+    }
+    else
+    {
+        return static_cast<unsigned short>(sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
+    }
+}
+
+float float16ToFloat32(unsigned short h);
+
+unsigned int convertRGBFloatsTo999E5(float red, float green, float blue);
+void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue);
+
+inline unsigned short float32ToFloat11(float fp32)
+{
+    const unsigned int float32MantissaMask = 0x7FFFFF;
+    const unsigned int float32ExponentMask = 0x7F800000;
+    const unsigned int float32SignMask = 0x80000000;
+    const unsigned int float32ValueMask = ~float32SignMask;
+    const unsigned int float32ExponentFirstBit = 23;
+    const unsigned int float32ExponentBias = 127;
+
+    const unsigned short float11Max = 0x7BF;
+    const unsigned short float11MantissaMask = 0x3F;
+    const unsigned short float11ExponentMask = 0x7C0;
+    const unsigned short float11BitMask = 0x7FF;
+    const unsigned int float11ExponentBias = 14;
+
+    const unsigned int float32Maxfloat11 = 0x477E0000;
+    const unsigned int float32Minfloat11 = 0x38800000;
+
+    const unsigned int float32Bits = bitCast<unsigned int>(fp32);
+    const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
+
+    unsigned int float32Val = float32Bits & float32ValueMask;
+
+    if ((float32Val & float32ExponentMask) == float32ExponentMask)
+    {
+        // INF or NAN
+        if ((float32Val & float32MantissaMask) != 0)
+        {
+            return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);
+        }
+        else if (float32Sign)
+        {
+            // -INF is clamped to 0 since float11 is positive only
+            return 0;
+        }
+        else
+        {
+            return float11ExponentMask;
+        }
+    }
+    else if (float32Sign)
+    {
+        // float11 is positive only, so clamp to zero
+        return 0;
+    }
+    else if (float32Val > float32Maxfloat11)
+    {
+        // The number is too large to be represented as a float11, set to max
+        return float11Max;
+    }
+    else
+    {
+        if (float32Val < float32Minfloat11)
+        {
+            // The number is too small to be represented as a normalized float11
+            // Convert it to a denormalized value.
+            const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
+            float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+        }
+        else
+        {
+            // Rebias the exponent to represent the value as a normalized float11
+            float32Val += 0xC8000000;
+        }
+
+        return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;
+    }
+}
+
+inline unsigned short float32ToFloat10(float fp32)
+{
+    const unsigned int float32MantissaMask = 0x7FFFFF;
+    const unsigned int float32ExponentMask = 0x7F800000;
+    const unsigned int float32SignMask = 0x80000000;
+    const unsigned int float32ValueMask = ~float32SignMask;
+    const unsigned int float32ExponentFirstBit = 23;
+    const unsigned int float32ExponentBias = 127;
+
+    const unsigned short float10Max = 0x3DF;
+    const unsigned short float10MantissaMask = 0x1F;
+    const unsigned short float10ExponentMask = 0x3E0;
+    const unsigned short float10BitMask = 0x3FF;
+    const unsigned int float10ExponentBias = 14;
+
+    const unsigned int float32Maxfloat10 = 0x477C0000;
+    const unsigned int float32Minfloat10 = 0x38800000;
+
+    const unsigned int float32Bits = bitCast<unsigned int>(fp32);
+    const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
+
+    unsigned int float32Val = float32Bits & float32ValueMask;
+
+    if ((float32Val & float32ExponentMask) == float32ExponentMask)
+    {
+        // INF or NAN
+        if ((float32Val & float32MantissaMask) != 0)
+        {
+            return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);
+        }
+        else if (float32Sign)
+        {
+            // -INF is clamped to 0 since float11 is positive only
+            return 0;
+        }
+        else
+        {
+            return float10ExponentMask;
+        }
+    }
+    else if (float32Sign)
+    {
+        // float10 is positive only, so clamp to zero
+        return 0;
+    }
+    else if (float32Val > float32Maxfloat10)
+    {
+        // The number is too large to be represented as a float11, set to max
+        return float10Max;
+    }
+    else
+    {
+        if (float32Val < float32Minfloat10)
+        {
+            // The number is too small to be represented as a normalized float11
+            // Convert it to a denormalized value.
+            const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
+            float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+        }
+        else
+        {
+            // Rebias the exponent to represent the value as a normalized float11
+            float32Val += 0xC8000000;
+        }
+
+        return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;
+    }
+}
+
+inline float float11ToFloat32(unsigned short fp11)
+{
+    unsigned short exponent = (fp11 >> 6) & 0x1F;
+    unsigned short mantissa = fp11 & 0x3F;
+
+    if (exponent == 0x1F)
+    {
+        // INF or NAN
+        return bitCast<float>(0x7f800000 | (mantissa << 17));
+    }
+    else
+    {
+        if (exponent != 0)
+        {
+            // normalized
+        }
+        else if (mantissa != 0)
+        {
+            // The value is denormalized
+            exponent = 1;
+
+            do
+            {
+                exponent--;
+                mantissa <<= 1;
+            }
+            while ((mantissa & 0x40) == 0);
+
+            mantissa = mantissa & 0x3F;
+        }
+        else // The value is zero
+        {
+            exponent = static_cast<unsigned short>(-112);
+        }
+
+        return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
+    }
+}
+
+inline float float10ToFloat32(unsigned short fp11)
+{
+    unsigned short exponent = (fp11 >> 5) & 0x1F;
+    unsigned short mantissa = fp11 & 0x1F;
+
+    if (exponent == 0x1F)
+    {
+        // INF or NAN
+        return bitCast<float>(0x7f800000 | (mantissa << 17));
+    }
+    else
+    {
+        if (exponent != 0)
+        {
+            // normalized
+        }
+        else if (mantissa != 0)
+        {
+            // The value is denormalized
+            exponent = 1;
+
+            do
+            {
+                exponent--;
+                mantissa <<= 1;
+            }
+            while ((mantissa & 0x20) == 0);
+
+            mantissa = mantissa & 0x1F;
+        }
+        else // The value is zero
+        {
+            exponent = static_cast<unsigned short>(-112);
+        }
+
+        return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
+    }
+}
+
+template <typename T>
+inline float normalizedToFloat(T input)
+{
+    static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
+
+    const float inverseMax = 1.0f / std::numeric_limits<T>::max();
+    return input * inverseMax;
+}
+
+template <unsigned int inputBitCount, typename T>
+inline float normalizedToFloat(T input)
+{
+    static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
+    static_assert(inputBitCount < (sizeof(T) * 8), "T must have more bits than inputBitCount.");
+
+    const float inverseMax = 1.0f / ((1 << inputBitCount) - 1);
+    return input * inverseMax;
+}
+
+template <typename T>
+inline T floatToNormalized(float input)
+{
+    return static_cast<T>(std::numeric_limits<T>::max() * input + 0.5f);
+}
+
+template <unsigned int outputBitCount, typename T>
+inline T floatToNormalized(float input)
+{
+    static_assert(outputBitCount < (sizeof(T) * 8), "T must have more bits than outputBitCount.");
+    return static_cast<T>(((1 << outputBitCount) - 1) * input + 0.5f);
+}
+
+template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
+inline T getShiftedData(T input)
+{
+    static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
+                  "T must have at least as many bits as inputBitCount + inputBitStart.");
+    const T mask = (1 << inputBitCount) - 1;
+    return (input >> inputBitStart) & mask;
+}
+
+template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
+inline T shiftData(T input)
+{
+    static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
+                  "T must have at least as many bits as inputBitCount + inputBitStart.");
+    const T mask = (1 << inputBitCount) - 1;
+    return (input & mask) << inputBitStart;
+}
+
+inline unsigned int CountLeadingZeros(uint32_t x)
+{
+    // Use binary search to find the amount of leading zeros.
+    unsigned int zeros = 32u;
+    uint32_t y;
+
+    y = x >> 16u;
+    if (y != 0)
+    {
+        zeros = zeros - 16u;
+        x     = y;
+    }
+    y = x >> 8u;
+    if (y != 0)
+    {
+        zeros = zeros - 8u;
+        x     = y;
+    }
+    y = x >> 4u;
+    if (y != 0)
+    {
+        zeros = zeros - 4u;
+        x     = y;
+    }
+    y = x >> 2u;
+    if (y != 0)
+    {
+        zeros = zeros - 2u;
+        x     = y;
+    }
+    y = x >> 1u;
+    if (y != 0)
+    {
+        return zeros - 2u;
+    }
+    return zeros - x;
+}
+
+inline unsigned char average(unsigned char a, unsigned char b)
+{
+    return ((a ^ b) >> 1) + (a & b);
+}
+
+inline signed char average(signed char a, signed char b)
+{
+    return ((short)a + (short)b) / 2;
+}
+
+inline unsigned short average(unsigned short a, unsigned short b)
+{
+    return ((a ^ b) >> 1) + (a & b);
+}
+
+inline signed short average(signed short a, signed short b)
+{
+    return ((int)a + (int)b) / 2;
+}
+
+inline unsigned int average(unsigned int a, unsigned int b)
+{
+    return ((a ^ b) >> 1) + (a & b);
+}
+
+inline int average(int a, int b)
+{
+    long long average = (static_cast<long long>(a) + static_cast<long long>(b)) / 2ll;
+    return static_cast<int>(average);
+}
+
+inline float average(float a, float b)
+{
+    return (a + b) * 0.5f;
+}
+
+inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
+{
+    return float32ToFloat16((float16ToFloat32(a) + float16ToFloat32(b)) * 0.5f);
+}
+
+inline unsigned int averageFloat11(unsigned int a, unsigned int b)
+{
+    return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) + float11ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
+}
+
+inline unsigned int averageFloat10(unsigned int a, unsigned int b)
+{
+    return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) + float10ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
+}
+
+template <typename T>
+struct Range
+{
+    Range() {}
+    Range(T lo, T hi) : start(lo), end(hi) { ASSERT(lo <= hi); }
+
+    T start;
+    T end;
+
+    T length() const { return end - start; }
+
+    bool intersects(Range<T> other)
+    {
+        if (start <= other.start)
+        {
+            return other.start < end;
+        }
+        else
+        {
+            return start < other.end;
+        }
+    }
+
+    void extend(T value)
+    {
+        start = value > start ? value : start;
+        end = value < end ? value : end;
+    }
+
+    bool empty() const
+    {
+        return end <= start;
+    }
+};
+
+typedef Range<int> RangeI;
+typedef Range<unsigned int> RangeUI;
+
+struct IndexRange
+{
+    IndexRange() : IndexRange(0, 0, 0) {}
+    IndexRange(size_t start_, size_t end_, size_t vertexIndexCount_)
+        : start(start_), end(end_), vertexIndexCount(vertexIndexCount_)
+    {
+        ASSERT(start <= end);
+    }
+
+    // Number of vertices in the range.
+    size_t vertexCount() const { return (end - start) + 1; }
+
+    // Inclusive range of indices that are not primitive restart
+    size_t start;
+    size_t end;
+
+    // Number of non-primitive restart indices
+    size_t vertexIndexCount;
+};
+
+// Combine a floating-point value representing a mantissa (x) and an integer exponent (exp) into a
+// floating-point value. As in GLSL ldexp() built-in.
+inline float Ldexp(float x, int exp)
+{
+    if (exp > 128)
+    {
+        return std::numeric_limits<float>::infinity();
+    }
+    if (exp < -126)
+    {
+        return 0.0f;
+    }
+    double result = static_cast<double>(x) * std::pow(2.0, static_cast<double>(exp));
+    return static_cast<float>(result);
+}
+
+// First, both normalized floating-point values are converted into 16-bit integer values.
+// Then, the results are packed into the returned 32-bit unsigned integer.
+// The first float value will be written to the least significant bits of the output;
+// the last float value will be written to the most significant bits.
+// The conversion of each value to fixed point is done as follows :
+// packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
+inline uint32_t packSnorm2x16(float f1, float f2)
+{
+    int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
+    int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 |
+           (static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
+}
+
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
+// component is converted to a normalized floating-point value to generate the returned two float values.
+// The first float value will be extracted from the least significant bits of the input;
+// the last float value will be extracted from the most-significant bits.
+// The conversion for unpacked fixed-point value to floating point is done as follows:
+// unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
+inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
+{
+    int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
+    int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
+    *f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
+    *f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
+}
+
+// First, both normalized floating-point values are converted into 16-bit integer values.
+// Then, the results are packed into the returned 32-bit unsigned integer.
+// The first float value will be written to the least significant bits of the output;
+// the last float value will be written to the most significant bits.
+// The conversion of each value to fixed point is done as follows:
+// packUnorm2x16 : round(clamp(c, 0, +1) * 65535.0)
+inline uint32_t packUnorm2x16(float f1, float f2)
+{
+    uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, 0.0f, 1.0f) * 65535.0f));
+    uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+}
+
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
+// component is converted to a normalized floating-point value to generate the returned two float values.
+// The first float value will be extracted from the least significant bits of the input;
+// the last float value will be extracted from the most-significant bits.
+// The conversion for unpacked fixed-point value to floating point is done as follows:
+// unpackUnorm2x16 : f / 65535.0
+inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
+{
+    uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
+    uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
+    *f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
+    *f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
+}
+
+// Helper functions intended to be used only here.
+namespace priv
+{
+
+inline uint8_t ToPackedUnorm8(float f)
+{
+    return static_cast<uint8_t>(roundf(clamp(f, 0.0f, 1.0f) * 255.0f));
+}
+
+inline int8_t ToPackedSnorm8(float f)
+{
+    return static_cast<int8_t>(roundf(clamp(f, -1.0f, 1.0f) * 127.0f));
+}
+
+}  // namespace priv
+
+// Packs 4 normalized unsigned floating-point values to a single 32-bit unsigned integer. Works
+// similarly to packUnorm2x16. The floats are clamped to the range 0.0 to 1.0, and written to the
+// unsigned integer starting from the least significant bits.
+inline uint32_t PackUnorm4x8(float f1, float f2, float f3, float f4)
+{
+    uint8_t bits[4];
+    bits[0]         = priv::ToPackedUnorm8(f1);
+    bits[1]         = priv::ToPackedUnorm8(f2);
+    bits[2]         = priv::ToPackedUnorm8(f3);
+    bits[3]         = priv::ToPackedUnorm8(f4);
+    uint32_t result = 0u;
+    for (int i = 0; i < 4; ++i)
+    {
+        int shift = i * 8;
+        result |= (static_cast<uint32_t>(bits[i]) << shift);
+    }
+    return result;
+}
+
+// Unpacks 4 normalized unsigned floating-point values from a single 32-bit unsigned integer into f.
+// Works similarly to unpackUnorm2x16. The floats are unpacked starting from the least significant
+// bits.
+inline void UnpackUnorm4x8(uint32_t u, float *f)
+{
+    for (int i = 0; i < 4; ++i)
+    {
+        int shift    = i * 8;
+        uint8_t bits = static_cast<uint8_t>((u >> shift) & 0xFF);
+        f[i]         = static_cast<float>(bits) / 255.0f;
+    }
+}
+
+// Packs 4 normalized signed floating-point values to a single 32-bit unsigned integer. The floats
+// are clamped to the range -1.0 to 1.0, and written to the unsigned integer starting from the least
+// significant bits.
+inline uint32_t PackSnorm4x8(float f1, float f2, float f3, float f4)
+{
+    int8_t bits[4];
+    bits[0]         = priv::ToPackedSnorm8(f1);
+    bits[1]         = priv::ToPackedSnorm8(f2);
+    bits[2]         = priv::ToPackedSnorm8(f3);
+    bits[3]         = priv::ToPackedSnorm8(f4);
+    uint32_t result = 0u;
+    for (int i = 0; i < 4; ++i)
+    {
+        int shift = i * 8;
+        result |= ((static_cast<uint32_t>(bits[i]) & 0xFF) << shift);
+    }
+    return result;
+}
+
+// Unpacks 4 normalized signed floating-point values from a single 32-bit unsigned integer into f.
+// Works similarly to unpackSnorm2x16. The floats are unpacked starting from the least significant
+// bits, and clamped to the range -1.0 to 1.0.
+inline void UnpackSnorm4x8(uint32_t u, float *f)
+{
+    for (int i = 0; i < 4; ++i)
+    {
+        int shift   = i * 8;
+        int8_t bits = static_cast<int8_t>((u >> shift) & 0xFF);
+        f[i]        = clamp(static_cast<float>(bits) / 127.0f, -1.0f, 1.0f);
+    }
+}
+
+// Returns an unsigned integer obtained by converting the two floating-point values to the 16-bit
+// floating-point representation found in the OpenGL ES Specification, and then packing these
+// two 16-bit integers into a 32-bit unsigned integer.
+// f1: The 16 least-significant bits of the result;
+// f2: The 16 most-significant bits.
+inline uint32_t packHalf2x16(float f1, float f2)
+{
+    uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
+    uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+}
+
+// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
+// interpreting those values as 16-bit floating-point numbers according to the OpenGL ES Specification,
+// and converting them to 32-bit floating-point values.
+// The first float value is obtained from the 16 least-significant bits of u;
+// the second component is obtained from the 16 most-significant bits of u.
+inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
+{
+    uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
+    uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
+
+    *f1 = float16ToFloat32(leastSignificantBits);
+    *f2 = float16ToFloat32(mostSignificantBits);
+}
+
+inline uint8_t sRGBToLinear(uint8_t srgbValue)
+{
+    float value = srgbValue / 255.0f;
+    if (value <= 0.04045f)
+    {
+        value = value / 12.92f;
+    }
+    else
+    {
+        value = std::pow((value + 0.055f) / 1.055f, 2.4f);
+    }
+    return static_cast<uint8_t>(clamp(value * 255.0f + 0.5f, 0.0f, 255.0f));
+}
+
+inline uint8_t linearToSRGB(uint8_t linearValue)
+{
+    float value = linearValue / 255.0f;
+    if (value <= 0.0f)
+    {
+        value = 0.0f;
+    }
+    else if (value < 0.0031308f)
+    {
+        value = value * 12.92f;
+    }
+    else if (value < 1.0f)
+    {
+        value = std::pow(value, 0.41666f) * 1.055f - 0.055f;
+    }
+    else
+    {
+        value = 1.0f;
+    }
+    return static_cast<uint8_t>(clamp(value * 255.0f + 0.5f, 0.0f, 255.0f));
+}
+
+// Reverse the order of the bits.
+inline uint32_t BitfieldReverse(uint32_t value)
+{
+    // TODO(oetuaho@nvidia.com): Optimize this if needed. There don't seem to be compiler intrinsics
+    // for this, and right now it's not used in performance-critical paths.
+    uint32_t result = 0u;
+    for (size_t j = 0u; j < 32u; ++j)
+    {
+        result |= (((value >> j) & 1u) << (31u - j));
+    }
+    return result;
+}
+
+// Count the 1 bits.
+#if defined(ANGLE_PLATFORM_WINDOWS)
+inline int BitCount(uint32_t bits)
+{
+    return static_cast<int>(__popcnt(bits));
+}
+#if defined(ANGLE_X64_CPU)
+inline int BitCount(uint64_t bits)
+{
+    return static_cast<int>(__popcnt64(bits));
+}
+#endif  // defined(ANGLE_X64_CPU)
+#endif  // defined(ANGLE_PLATFORM_WINDOWS)
+
+#if defined(ANGLE_PLATFORM_POSIX)
+inline int BitCount(uint32_t bits)
+{
+    return __builtin_popcount(bits);
+}
+
+#if defined(ANGLE_X64_CPU)
+inline int BitCount(uint64_t bits)
+{
+    return __builtin_popcountll(bits);
+}
+#endif  // defined(ANGLE_X64_CPU)
+#endif  // defined(ANGLE_PLATFORM_POSIX)
+
+#if defined(ANGLE_PLATFORM_WINDOWS)
+// Return the index of the least significant bit set. Indexing is such that bit 0 is the least
+// significant bit. Implemented for different bit widths on different platforms.
+inline unsigned long ScanForward(uint32_t bits)
+{
+    ASSERT(bits != 0u);
+    unsigned long firstBitIndex = 0ul;
+    unsigned char ret           = _BitScanForward(&firstBitIndex, bits);
+    ASSERT(ret != 0u);
+    return firstBitIndex;
+}
+
+#if defined(ANGLE_X64_CPU)
+inline unsigned long ScanForward(uint64_t bits)
+{
+    ASSERT(bits != 0u);
+    unsigned long firstBitIndex = 0ul;
+    unsigned char ret           = _BitScanForward64(&firstBitIndex, bits);
+    ASSERT(ret != 0u);
+    return firstBitIndex;
+}
+#endif  // defined(ANGLE_X64_CPU)
+#endif  // defined(ANGLE_PLATFORM_WINDOWS)
+
+#if defined(ANGLE_PLATFORM_POSIX)
+inline unsigned long ScanForward(uint32_t bits)
+{
+    ASSERT(bits != 0u);
+    return static_cast<unsigned long>(__builtin_ctz(bits));
+}
+
+#if defined(ANGLE_X64_CPU)
+inline unsigned long ScanForward(uint64_t bits)
+{
+    ASSERT(bits != 0u);
+    return static_cast<unsigned long>(__builtin_ctzll(bits));
+}
+#endif  // defined(ANGLE_X64_CPU)
+#endif  // defined(ANGLE_PLATFORM_POSIX)
+
+// Return the index of the most significant bit set. Indexing is such that bit 0 is the least
+// significant bit.
+inline unsigned long ScanReverse(unsigned long bits)
+{
+    ASSERT(bits != 0u);
+#if defined(ANGLE_PLATFORM_WINDOWS)
+    unsigned long lastBitIndex = 0ul;
+    unsigned char ret          = _BitScanReverse(&lastBitIndex, bits);
+    ASSERT(ret != 0u);
+    return lastBitIndex;
+#elif defined(ANGLE_PLATFORM_POSIX)
+    return static_cast<unsigned long>(sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(bits));
+#else
+#error Please implement bit-scan-reverse for your platform!
+#endif
+}
+
+// Returns -1 on 0, otherwise the index of the least significant 1 bit as in GLSL.
+template <typename T>
+int FindLSB(T bits)
+{
+    static_assert(std::is_integral<T>::value, "must be integral type.");
+    if (bits == 0u)
+    {
+        return -1;
+    }
+    else
+    {
+        return static_cast<int>(ScanForward(bits));
+    }
+}
+
+// Returns -1 on 0, otherwise the index of the most significant 1 bit as in GLSL.
+template <typename T>
+int FindMSB(T bits)
+{
+    static_assert(std::is_integral<T>::value, "must be integral type.");
+    if (bits == 0u)
+    {
+        return -1;
+    }
+    else
+    {
+        return static_cast<int>(ScanReverse(bits));
+    }
+}
+
+// Returns whether the argument is Not a Number.
+// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero.
+inline bool isNaN(float f)
+{
+    // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
+    // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
+    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && (bitCast<uint32_t>(f) & 0x7fffffu);
+}
+
+// Returns whether the argument is infinity.
+// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) - zero.
+inline bool isInf(float f)
+{
+    // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
+    // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
+    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
+}
+
+namespace priv
+{
+template <unsigned int N, unsigned int R>
+struct iSquareRoot
+{
+    static constexpr unsigned int solve()
+    {
+        return (R * R > N)
+                   ? 0
+                   : ((R * R == N) ? R : static_cast<unsigned int>(iSquareRoot<N, R + 1>::value));
+    }
+    enum Result
+    {
+        value = iSquareRoot::solve()
+    };
+};
+
+template <unsigned int N>
+struct iSquareRoot<N, N>
+{
+    enum result
+    {
+        value = N
+    };
+};
+
+}  // namespace priv
+
+template <unsigned int N>
+constexpr unsigned int iSquareRoot()
+{
+    return priv::iSquareRoot<N, 1>::value;
+}
+
+// Sum, difference and multiplication operations for signed ints that wrap on 32-bit overflow.
+//
+// Unsigned types are defined to do arithmetic modulo 2^n in C++. For signed types, overflow
+// behavior is undefined.
+
+template <typename T>
+inline T WrappingSum(T lhs, T rhs)
+{
+    uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
+    uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
+    return static_cast<T>(lhsUnsigned + rhsUnsigned);
+}
+
+template <typename T>
+inline T WrappingDiff(T lhs, T rhs)
+{
+    uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
+    uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
+    return static_cast<T>(lhsUnsigned - rhsUnsigned);
+}
+
+inline int32_t WrappingMul(int32_t lhs, int32_t rhs)
+{
+    int64_t lhsWide = static_cast<int64_t>(lhs);
+    int64_t rhsWide = static_cast<int64_t>(rhs);
+    // The multiplication is guaranteed not to overflow.
+    int64_t resultWide = lhsWide * rhsWide;
+    // Implement the desired wrapping behavior by masking out the high-order 32 bits.
+    resultWide = resultWide & 0xffffffffll;
+    // Casting to a narrower signed type is fine since the casted value is representable in the
+    // narrower type.
+    return static_cast<int32_t>(resultWide);
+}
+
+}  // namespace gl
+
+namespace rx
+{
+
+template <typename T>
+T roundUp(const T value, const T alignment)
+{
+    auto temp = value + alignment - static_cast<T>(1);
+    return temp - temp % alignment;
+}
+
+template <typename T>
+angle::CheckedNumeric<T> CheckedRoundUp(const T value, const T alignment)
+{
+    angle::CheckedNumeric<T> checkedValue(value);
+    angle::CheckedNumeric<T> checkedAlignment(alignment);
+    return roundUp(checkedValue, checkedAlignment);
+}
+
+inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
+{
+    unsigned int divided = value / divisor;
+    return (divided + ((value % divisor == 0) ? 0 : 1));
+}
+
+#if defined(_MSC_VER)
+
+#define ANGLE_ROTL(x,y) _rotl(x,y)
+#define ANGLE_ROTR16(x,y) _rotr16(x,y)
+
+#else
+
+inline uint32_t RotL(uint32_t x, int8_t r)
+{
+    return (x << r) | (x >> (32 - r));
+}
+
+inline uint16_t RotR16(uint16_t x, int8_t r)
+{
+    return (x >> r) | (x << (16 - r));
+}
+
+#define ANGLE_ROTL(x, y) ::rx::RotL(x, y)
+#define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y)
+
+#endif // namespace rx
+
+}
+
+#endif   // COMMON_MATHUTIL_H_
diff --git a/src/third_party/angle/src/common/mathutil_unittest.cpp b/src/third_party/angle/src/common/mathutil_unittest.cpp
new file mode 100644
index 0000000..ad39b38
--- /dev/null
+++ b/src/third_party/angle/src/common/mathutil_unittest.cpp
@@ -0,0 +1,334 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// mathutil_unittest:
+//   Unit tests for the utils defined in mathutil.h
+//
+
+#include "mathutil.h"
+
+#include <gtest/gtest.h>
+
+using namespace gl;
+
+namespace
+{
+
+// Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions.
+// For floats f1 and f2, unpackSnorm2x16(packSnorm2x16(f1, f2)) should be same as f1 and f2.
+TEST(MathUtilTest, packAndUnpackSnorm2x16)
+{
+    const float input[8][2] =
+    {
+        { 0.0f, 0.0f },
+        { 1.0f, 1.0f },
+        { -1.0f, 1.0f },
+        { -1.0f, -1.0f },
+        { 0.875f, 0.75f },
+        { 0.00392f, -0.99215f },
+        { -0.000675f, 0.004954f },
+        { -0.6937f, -0.02146f }
+    };
+    const float floatFaultTolerance = 0.0001f;
+    float outputVal1, outputVal2;
+
+    for (size_t i = 0; i < 8; i++)
+    {
+        unpackSnorm2x16(packSnorm2x16(input[i][0], input[i][1]), &outputVal1, &outputVal2);
+        EXPECT_NEAR(input[i][0], outputVal1, floatFaultTolerance);
+        EXPECT_NEAR(input[i][1], outputVal2, floatFaultTolerance);
+    }
+}
+
+// Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions with infinity values,
+// result should be clamped to [-1, 1].
+TEST(MathUtilTest, packAndUnpackSnorm2x16Infinity)
+{
+    const float floatFaultTolerance = 0.0001f;
+    float outputVal1, outputVal2;
+
+    unpackSnorm2x16(packSnorm2x16(std::numeric_limits<float>::infinity(),
+                                  std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+    EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
+    EXPECT_NEAR(1.0f, outputVal2, floatFaultTolerance);
+
+    unpackSnorm2x16(packSnorm2x16(std::numeric_limits<float>::infinity(),
+                                  -std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+    EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
+    EXPECT_NEAR(-1.0f, outputVal2, floatFaultTolerance);
+
+    unpackSnorm2x16(packSnorm2x16(-std::numeric_limits<float>::infinity(),
+                                  -std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+    EXPECT_NEAR(-1.0f, outputVal1, floatFaultTolerance);
+    EXPECT_NEAR(-1.0f, outputVal2, floatFaultTolerance);
+}
+
+// Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions.
+// For floats f1 and f2, unpackUnorm2x16(packUnorm2x16(f1, f2)) should be same as f1 and f2.
+TEST(MathUtilTest, packAndUnpackUnorm2x16)
+{
+    const float input[8][2] =
+    {
+        { 0.0f, 0.0f },
+        { 1.0f, 1.0f },
+        { -1.0f, 1.0f },
+        { -1.0f, -1.0f },
+        { 0.875f, 0.75f },
+        { 0.00392f, -0.99215f },
+        { -0.000675f, 0.004954f },
+        { -0.6937f, -0.02146f }
+    };
+    const float floatFaultTolerance = 0.0001f;
+    float outputVal1, outputVal2;
+
+    for (size_t i = 0; i < 8; i++)
+    {
+        unpackUnorm2x16(packUnorm2x16(input[i][0], input[i][1]), &outputVal1, &outputVal2);
+        float expected = input[i][0] < 0.0f ? 0.0f : input[i][0];
+        EXPECT_NEAR(expected, outputVal1, floatFaultTolerance);
+        expected = input[i][1] < 0.0f ? 0.0f : input[i][1];
+        EXPECT_NEAR(expected, outputVal2, floatFaultTolerance);
+    }
+}
+
+// Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions with infinity values,
+// result should be clamped to [0, 1].
+TEST(MathUtilTest, packAndUnpackUnorm2x16Infinity)
+{
+    const float floatFaultTolerance = 0.0001f;
+    float outputVal1, outputVal2;
+
+    unpackUnorm2x16(packUnorm2x16(std::numeric_limits<float>::infinity(),
+                                  std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+    EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
+    EXPECT_NEAR(1.0f, outputVal2, floatFaultTolerance);
+
+    unpackUnorm2x16(packUnorm2x16(std::numeric_limits<float>::infinity(),
+                                  -std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+    EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
+    EXPECT_NEAR(0.0f, outputVal2, floatFaultTolerance);
+
+    unpackUnorm2x16(packUnorm2x16(-std::numeric_limits<float>::infinity(),
+                                  -std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+    EXPECT_NEAR(0.0f, outputVal1, floatFaultTolerance);
+    EXPECT_NEAR(0.0f, outputVal2, floatFaultTolerance);
+}
+
+// Test the correctness of packHalf2x16 and unpackHalf2x16 functions.
+// For floats f1 and f2, unpackHalf2x16(packHalf2x16(f1, f2)) should be same as f1 and f2.
+TEST(MathUtilTest, packAndUnpackHalf2x16)
+{
+    const float input[8][2] =
+    {
+        { 0.0f, 0.0f },
+        { 1.0f, 1.0f },
+        { -1.0f, 1.0f },
+        { -1.0f, -1.0f },
+        { 0.875f, 0.75f },
+        { 0.00392f, -0.99215f },
+        { -0.000675f, 0.004954f },
+        { -0.6937f, -0.02146f },
+    };
+    const float floatFaultTolerance = 0.0005f;
+    float outputVal1, outputVal2;
+
+    for (size_t i = 0; i < 8; i++)
+    {
+        unpackHalf2x16(packHalf2x16(input[i][0], input[i][1]), &outputVal1, &outputVal2);
+        EXPECT_NEAR(input[i][0], outputVal1, floatFaultTolerance);
+        EXPECT_NEAR(input[i][1], outputVal2, floatFaultTolerance);
+    }
+}
+
+// Test the correctness of packUnorm4x8 and unpackUnorm4x8 functions.
+// For floats f1 to f4, unpackUnorm4x8(packUnorm4x8(f1, f2, f3, f4)) should be same as f1 to f4.
+TEST(MathUtilTest, packAndUnpackUnorm4x8)
+{
+    const float input[5][4] = {{0.0f, 0.0f, 0.0f, 0.0f},
+                               {1.0f, 1.0f, 1.0f, 1.0f},
+                               {-1.0f, 1.0f, -1.0f, 1.0f},
+                               {-1.0f, -1.0f, -1.0f, -1.0f},
+                               {64.0f / 255.0f, 128.0f / 255.0f, 32.0f / 255.0f, 16.0f / 255.0f}};
+
+    const float floatFaultTolerance = 0.005f;
+    float outputVals[4];
+
+    for (size_t i = 0; i < 5; i++)
+    {
+        UnpackUnorm4x8(PackUnorm4x8(input[i][0], input[i][1], input[i][2], input[i][3]),
+                       outputVals);
+        for (size_t j = 0; j < 4; j++)
+        {
+            float expected = input[i][j] < 0.0f ? 0.0f : input[i][j];
+            EXPECT_NEAR(expected, outputVals[j], floatFaultTolerance);
+        }
+    }
+}
+
+// Test the correctness of packSnorm4x8 and unpackSnorm4x8 functions.
+// For floats f1 to f4, unpackSnorm4x8(packSnorm4x8(f1, f2, f3, f4)) should be same as f1 to f4.
+TEST(MathUtilTest, packAndUnpackSnorm4x8)
+{
+    const float input[5][4] = {{0.0f, 0.0f, 0.0f, 0.0f},
+                               {1.0f, 1.0f, 1.0f, 1.0f},
+                               {-1.0f, 1.0f, -1.0f, 1.0f},
+                               {-1.0f, -1.0f, -1.0f, -1.0f},
+                               {64.0f / 127.0f, -8.0f / 127.0f, 32.0f / 127.0f, 16.0f / 127.0f}};
+
+    const float floatFaultTolerance = 0.01f;
+    float outputVals[4];
+
+    for (size_t i = 0; i < 5; i++)
+    {
+        UnpackSnorm4x8(PackSnorm4x8(input[i][0], input[i][1], input[i][2], input[i][3]),
+                       outputVals);
+        for (size_t j = 0; j < 4; j++)
+        {
+            float expected = input[i][j];
+            EXPECT_NEAR(expected, outputVals[j], floatFaultTolerance);
+        }
+    }
+}
+
+// Test the correctness of gl::isNaN function.
+TEST(MathUtilTest, isNaN)
+{
+    EXPECT_TRUE(isNaN(bitCast<float>(0xffu << 23 | 1u)));
+    EXPECT_TRUE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23 | 1u)));
+    EXPECT_TRUE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23 | 0x400000u)));
+    EXPECT_TRUE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23 | 0x7fffffu)));
+    EXPECT_FALSE(isNaN(0.0f));
+    EXPECT_FALSE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23)));
+    EXPECT_FALSE(isNaN(bitCast<float>(0xffu << 23)));
+}
+
+// Test the correctness of gl::isInf function.
+TEST(MathUtilTest, isInf)
+{
+    EXPECT_TRUE(isInf(bitCast<float>(0xffu << 23)));
+    EXPECT_TRUE(isInf(bitCast<float>(1u << 31 | 0xffu << 23)));
+    EXPECT_FALSE(isInf(0.0f));
+    EXPECT_FALSE(isInf(bitCast<float>(0xffu << 23 | 1u)));
+    EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xffu << 23 | 1u)));
+    EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xffu << 23 | 0x400000u)));
+    EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xffu << 23 | 0x7fffffu)));
+    EXPECT_FALSE(isInf(bitCast<float>(0xfeu << 23 | 0x7fffffu)));
+    EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xfeu << 23 | 0x7fffffu)));
+}
+
+TEST(MathUtilTest, CountLeadingZeros)
+{
+    for (unsigned int i = 0; i < 32u; ++i)
+    {
+        uint32_t iLeadingZeros = 1u << (31u - i);
+        EXPECT_EQ(i, CountLeadingZeros(iLeadingZeros));
+    }
+    EXPECT_EQ(32u, CountLeadingZeros(0));
+}
+
+// Some basic tests. Tests that rounding up zero produces zero.
+TEST(MathUtilTest, BasicRoundUp)
+{
+    EXPECT_EQ(0u, rx::roundUp(0u, 4u));
+    EXPECT_EQ(4u, rx::roundUp(1u, 4u));
+    EXPECT_EQ(4u, rx::roundUp(4u, 4u));
+}
+
+// Test that rounding up zero produces zero for checked ints.
+TEST(MathUtilTest, CheckedRoundUpZero)
+{
+    auto checkedValue = rx::CheckedRoundUp(0u, 4u);
+    ASSERT_TRUE(checkedValue.IsValid());
+    ASSERT_EQ(0u, checkedValue.ValueOrDie());
+}
+
+// Test out-of-bounds with CheckedRoundUp
+TEST(MathUtilTest, CheckedRoundUpInvalid)
+{
+    // The answer to this query is out of bounds.
+    auto limit        = std::numeric_limits<unsigned int>::max();
+    auto checkedValue = rx::CheckedRoundUp(limit, limit - 1);
+    ASSERT_FALSE(checkedValue.IsValid());
+
+    // Our implementation can't handle this query, despite the parameters being in range.
+    auto checkedLimit = rx::CheckedRoundUp(limit - 1, limit);
+    ASSERT_FALSE(checkedLimit.IsValid());
+}
+
+// Test BitfieldReverse which reverses the order of the bits in an integer.
+TEST(MathUtilTest, BitfieldReverse)
+{
+    EXPECT_EQ(0u, gl::BitfieldReverse(0u));
+    EXPECT_EQ(0x80000000u, gl::BitfieldReverse(1u));
+    EXPECT_EQ(0x1u, gl::BitfieldReverse(0x80000000u));
+    uint32_t bits     = (1u << 4u) | (1u << 7u);
+    uint32_t reversed = (1u << (31u - 4u)) | (1u << (31u - 7u));
+    EXPECT_EQ(reversed, gl::BitfieldReverse(bits));
+}
+
+// Test BitCount, which counts 1 bits in an integer.
+TEST(MathUtilTest, BitCount)
+{
+    EXPECT_EQ(0, gl::BitCount(0u));
+    EXPECT_EQ(32, gl::BitCount(0xFFFFFFFFu));
+    EXPECT_EQ(10, gl::BitCount(0x17103121u));
+
+#if defined(ANGLE_X64_CPU)
+    EXPECT_EQ(0, gl::BitCount(0ull));
+    EXPECT_EQ(32, gl::BitCount(0xFFFFFFFFull));
+    EXPECT_EQ(10, gl::BitCount(0x17103121ull));
+#endif  // defined(ANGLE_X64_CPU)
+}
+
+// Test ScanForward, which scans for the least significant 1 bit from a non-zero integer.
+TEST(MathUtilTest, ScanForward)
+{
+    EXPECT_EQ(0ul, gl::ScanForward(1u));
+    EXPECT_EQ(16ul, gl::ScanForward(0x80010000u));
+    EXPECT_EQ(31ul, gl::ScanForward(0x80000000u));
+
+#if defined(ANGLE_X64_CPU)
+    EXPECT_EQ(0ul, gl::ScanForward(1ull));
+    EXPECT_EQ(16ul, gl::ScanForward(0x80010000ull));
+    EXPECT_EQ(31ul, gl::ScanForward(0x80000000ull));
+#endif  // defined(ANGLE_X64_CPU)
+}
+
+// Test ScanReverse, which scans for the most significant 1 bit from a non-zero integer.
+TEST(MathUtilTest, ScanReverse)
+{
+    EXPECT_EQ(0ul, gl::ScanReverse(1ul));
+    EXPECT_EQ(16ul, gl::ScanReverse(0x00010030ul));
+    EXPECT_EQ(31ul, gl::ScanReverse(0x80000000ul));
+}
+
+// Test FindLSB, which finds the least significant 1 bit.
+TEST(MathUtilTest, FindLSB)
+{
+    EXPECT_EQ(-1, gl::FindLSB(0u));
+    EXPECT_EQ(0, gl::FindLSB(1u));
+    EXPECT_EQ(16, gl::FindLSB(0x80010000u));
+    EXPECT_EQ(31, gl::FindLSB(0x80000000u));
+}
+
+// Test FindMSB, which finds the most significant 1 bit.
+TEST(MathUtilTest, FindMSB)
+{
+    EXPECT_EQ(-1, gl::FindMSB(0u));
+    EXPECT_EQ(0, gl::FindMSB(1u));
+    EXPECT_EQ(16, gl::FindMSB(0x00010030u));
+    EXPECT_EQ(31, gl::FindMSB(0x80000000u));
+}
+
+// Test Ldexp, which combines mantissa and exponent into a floating-point number.
+TEST(MathUtilTest, Ldexp)
+{
+    EXPECT_EQ(2.5f, Ldexp(0.625f, 2));
+    EXPECT_EQ(-5.0f, Ldexp(-0.625f, 3));
+    EXPECT_EQ(std::numeric_limits<float>::infinity(), Ldexp(0.625f, 129));
+    EXPECT_EQ(0.0f, Ldexp(1.0f, -129));
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/common/matrix_utils.h b/src/third_party/angle/src/common/matrix_utils.h
new file mode 100644
index 0000000..aa3f895
--- /dev/null
+++ b/src/third_party/angle/src/common/matrix_utils.h
@@ -0,0 +1,386 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Matrix:
+//   Utility class implementing various matrix operations.
+//   Supports matrices with minimum 2 and maximum 4 number of rows/columns.
+//
+// TODO: Check if we can merge Matrix.h in sample_util with this and replace it with this implementation.
+// TODO: Rename this file to Matrix.h once we remove Matrix.h in sample_util.
+
+#ifndef COMMON_MATRIX_UTILS_H_
+#define COMMON_MATRIX_UTILS_H_
+
+#include <vector>
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+
+namespace angle
+{
+
+template<typename T>
+class Matrix
+{
+  public:
+    Matrix(const std::vector<T> &elements, const unsigned int &numRows, const unsigned int &numCols)
+        : mElements(elements),
+          mRows(numRows),
+          mCols(numCols)
+    {
+        ASSERT(rows() >= 1 && rows() <= 4);
+        ASSERT(columns() >= 1 && columns() <= 4);
+    }
+
+    Matrix(const std::vector<T> &elements, const unsigned int &size)
+        : mElements(elements),
+          mRows(size),
+          mCols(size)
+    {
+        ASSERT(rows() >= 1 && rows() <= 4);
+        ASSERT(columns() >= 1 && columns() <= 4);
+    }
+
+    Matrix(const T *elements, const unsigned int &size)
+        : mRows(size),
+          mCols(size)
+    {
+        ASSERT(rows() >= 1 && rows() <= 4);
+        ASSERT(columns() >= 1 && columns() <= 4);
+        for (size_t i = 0; i < size * size; i++)
+            mElements.push_back(elements[i]);
+    }
+
+    const T &operator()(const unsigned int &rowIndex, const unsigned int &columnIndex) const
+    {
+        return mElements[rowIndex * columns() + columnIndex];
+    }
+
+    T &operator()(const unsigned int &rowIndex, const unsigned int &columnIndex)
+    {
+        return mElements[rowIndex * columns() + columnIndex];
+    }
+
+    const T &at(const unsigned int &rowIndex, const unsigned int &columnIndex) const
+    {
+        return operator()(rowIndex, columnIndex);
+    }
+
+    Matrix<T> operator*(const Matrix<T> &m)
+    {
+        ASSERT(columns() == m.rows());
+
+        unsigned int resultRows = rows();
+        unsigned int resultCols = m.columns();
+        Matrix<T> result(std::vector<T>(resultRows * resultCols), resultRows, resultCols);
+        for (unsigned int i = 0; i < resultRows; i++)
+        {
+            for (unsigned int j = 0; j < resultCols; j++)
+            {
+                T tmp = 0.0f;
+                for (unsigned int k = 0; k < columns(); k++)
+                    tmp += at(i, k) * m(k, j);
+                result(i, j) = tmp;
+            }
+        }
+
+        return result;
+    }
+
+    unsigned int size() const
+    {
+        ASSERT(rows() == columns());
+        return rows();
+    }
+
+    unsigned int rows() const { return mRows; }
+
+    unsigned int columns() const { return mCols; }
+
+    std::vector<T> elements() const { return mElements; }
+
+    Matrix<T> compMult(const Matrix<T> &mat1) const
+    {
+        Matrix result(std::vector<T>(mElements.size()), size());
+        for (unsigned int i = 0; i < columns(); i++)
+            for (unsigned int j = 0; j < rows(); j++)
+                result(i, j) = at(i, j) * mat1(i, j);
+
+        return result;
+    }
+
+    Matrix<T> outerProduct(const Matrix<T> &mat1) const
+    {
+        unsigned int cols = mat1.columns();
+        Matrix result(std::vector<T>(rows() * cols), rows(), cols);
+        for (unsigned int i = 0; i < rows(); i++)
+            for (unsigned int j = 0; j < cols; j++)
+                result(i, j) = at(i, 0) * mat1(0, j);
+
+        return result;
+    }
+
+    Matrix<T> transpose() const
+    {
+        Matrix result(std::vector<T>(mElements.size()), columns(), rows());
+        for (unsigned int i = 0; i < columns(); i++)
+            for (unsigned int j = 0; j < rows(); j++)
+                result(i, j) = at(j, i);
+
+        return result;
+    }
+
+    T determinant() const
+    {
+        ASSERT(rows() == columns());
+
+        switch (size())
+        {
+          case 2:
+            return at(0, 0) * at(1, 1) - at(0, 1) * at(1, 0);
+
+          case 3:
+            return at(0, 0) * at(1, 1) * at(2, 2) +
+                at(0, 1) * at(1, 2) * at(2, 0) +
+                at(0, 2) * at(1, 0) * at(2, 1) -
+                at(0, 2) * at(1, 1) * at(2, 0) -
+                at(0, 1) * at(1, 0) * at(2, 2) -
+                at(0, 0) * at(1, 2) * at(2, 1);
+
+          case 4:
+            {
+                const float minorMatrices[4][3 * 3] =
+                {
+                    {
+                        at(1, 1), at(2, 1), at(3, 1),
+                        at(1, 2), at(2, 2), at(3, 2),
+                        at(1, 3), at(2, 3), at(3, 3),
+                    },
+                    {
+                        at(1, 0), at(2, 0), at(3, 0),
+                        at(1, 2), at(2, 2), at(3, 2),
+                        at(1, 3), at(2, 3), at(3, 3),
+                    },
+                    {
+                        at(1, 0), at(2, 0), at(3, 0),
+                        at(1, 1), at(2, 1), at(3, 1),
+                        at(1, 3), at(2, 3), at(3, 3),
+                    },
+                    {
+                        at(1, 0), at(2, 0), at(3, 0),
+                        at(1, 1), at(2, 1), at(3, 1),
+                        at(1, 2), at(2, 2), at(3, 2),
+                    }
+              };
+              return at(0, 0) * Matrix<T>(minorMatrices[0], 3).determinant() -
+                  at(0, 1) * Matrix<T>(minorMatrices[1], 3).determinant() +
+                  at(0, 2) * Matrix<T>(minorMatrices[2], 3).determinant() -
+                  at(0, 3) * Matrix<T>(minorMatrices[3], 3).determinant();
+            }
+
+          default:
+            UNREACHABLE();
+            break;
+        }
+
+        return T();
+    }
+
+    Matrix<T> inverse() const
+    {
+        ASSERT(rows() == columns());
+
+        Matrix<T> cof(std::vector<T>(mElements.size()), rows(), columns());
+        switch (size())
+        {
+          case 2:
+            cof(0, 0) = at(1, 1);
+            cof(0, 1) = -at(1, 0);
+            cof(1, 0) = -at(0, 1);
+            cof(1, 1) = at(0, 0);
+            break;
+
+          case 3:
+            cof(0, 0) = at(1, 1) * at(2, 2) -
+                at(2, 1) * at(1, 2);
+            cof(0, 1) = -(at(1, 0) * at(2, 2) -
+                at(2, 0) * at(1, 2));
+            cof(0, 2) = at(1, 0) * at(2, 1) -
+                at(2, 0) * at(1, 1);
+            cof(1, 0) = -(at(0, 1) * at(2, 2) -
+                at(2, 1) * at(0, 2));
+            cof(1, 1) = at(0, 0) * at(2, 2) -
+                at(2, 0) * at(0, 2);
+            cof(1, 2) = -(at(0, 0) * at(2, 1) -
+                at(2, 0) * at(0, 1));
+            cof(2, 0) = at(0, 1) * at(1, 2) -
+                at(1, 1) * at(0, 2);
+            cof(2, 1) = -(at(0, 0) * at(1, 2) -
+                at(1, 0) * at(0, 2));
+            cof(2, 2) = at(0, 0) * at(1, 1) -
+                at(1, 0) * at(0, 1);
+            break;
+
+          case 4:
+            cof(0, 0) = at(1, 1) * at(2, 2) * at(3, 3) +
+                at(2, 1) * at(3, 2) * at(1, 3) +
+                at(3, 1) * at(1, 2) * at(2, 3) -
+                at(1, 1) * at(3, 2) * at(2, 3) -
+                at(2, 1) * at(1, 2) * at(3, 3) -
+                at(3, 1) * at(2, 2) * at(1, 3);
+            cof(0, 1) = -(at(1, 0) * at(2, 2) * at(3, 3) +
+                at(2, 0) * at(3, 2) * at(1, 3) +
+                at(3, 0) * at(1, 2) * at(2, 3) -
+                at(1, 0) * at(3, 2) * at(2, 3) -
+                at(2, 0) * at(1, 2) * at(3, 3) -
+                at(3, 0) * at(2, 2) * at(1, 3));
+            cof(0, 2) = at(1, 0) * at(2, 1) * at(3, 3) +
+                at(2, 0) * at(3, 1) * at(1, 3) +
+                at(3, 0) * at(1, 1) * at(2, 3) -
+                at(1, 0) * at(3, 1) * at(2, 3) -
+                at(2, 0) * at(1, 1) * at(3, 3) -
+                at(3, 0) * at(2, 1) * at(1, 3);
+            cof(0, 3) = -(at(1, 0) * at(2, 1) * at(3, 2) +
+                at(2, 0) * at(3, 1) * at(1, 2) +
+                at(3, 0) * at(1, 1) * at(2, 2) -
+                at(1, 0) * at(3, 1) * at(2, 2) -
+                at(2, 0) * at(1, 1) * at(3, 2) -
+                at(3, 0) * at(2, 1) * at(1, 2));
+            cof(1, 0) = -(at(0, 1) * at(2, 2) * at(3, 3) +
+                at(2, 1) * at(3, 2) * at(0, 3) +
+                at(3, 1) * at(0, 2) * at(2, 3) -
+                at(0, 1) * at(3, 2) * at(2, 3) -
+                at(2, 1) * at(0, 2) * at(3, 3) -
+                at(3, 1) * at(2, 2) * at(0, 3));
+            cof(1, 1) = at(0, 0) * at(2, 2) * at(3, 3) +
+                at(2, 0) * at(3, 2) * at(0, 3) +
+                at(3, 0) * at(0, 2) * at(2, 3) -
+                at(0, 0) * at(3, 2) * at(2, 3) -
+                at(2, 0) * at(0, 2) * at(3, 3) -
+                at(3, 0) * at(2, 2) * at(0, 3);
+            cof(1, 2) = -(at(0, 0) * at(2, 1) * at(3, 3) +
+                at(2, 0) * at(3, 1) * at(0, 3) +
+                at(3, 0) * at(0, 1) * at(2, 3) -
+                at(0, 0) * at(3, 1) * at(2, 3) -
+                at(2, 0) * at(0, 1) * at(3, 3) -
+                at(3, 0) * at(2, 1) * at(0, 3));
+            cof(1, 3) = at(0, 0) * at(2, 1) * at(3, 2) +
+                at(2, 0) * at(3, 1) * at(0, 2) +
+                at(3, 0) * at(0, 1) * at(2, 2) -
+                at(0, 0) * at(3, 1) * at(2, 2) -
+                at(2, 0) * at(0, 1) * at(3, 2) -
+                at(3, 0) * at(2, 1) * at(0, 2);
+            cof(2, 0) = at(0, 1) * at(1, 2) * at(3, 3) +
+                at(1, 1) * at(3, 2) * at(0, 3) +
+                at(3, 1) * at(0, 2) * at(1, 3) -
+                at(0, 1) * at(3, 2) * at(1, 3) -
+                at(1, 1) * at(0, 2) * at(3, 3) -
+                at(3, 1) * at(1, 2) * at(0, 3);
+            cof(2, 1) = -(at(0, 0) * at(1, 2) * at(3, 3) +
+                at(1, 0) * at(3, 2) * at(0, 3) +
+                at(3, 0) * at(0, 2) * at(1, 3) -
+                at(0, 0) * at(3, 2) * at(1, 3) -
+                at(1, 0) * at(0, 2) * at(3, 3) -
+                at(3, 0) * at(1, 2) * at(0, 3));
+            cof(2, 2) = at(0, 0) * at(1, 1) * at(3, 3) +
+                at(1, 0) * at(3, 1) * at(0, 3) +
+                at(3, 0) * at(0, 1) * at(1, 3) -
+                at(0, 0) * at(3, 1) * at(1, 3) -
+                at(1, 0) * at(0, 1) * at(3, 3) -
+                at(3, 0) * at(1, 1) * at(0, 3);
+            cof(2, 3) = -(at(0, 0) * at(1, 1) * at(3, 2) +
+                at(1, 0) * at(3, 1) * at(0, 2) +
+                at(3, 0) * at(0, 1) * at(1, 2) -
+                at(0, 0) * at(3, 1) * at(1, 2) -
+                at(1, 0) * at(0, 1) * at(3, 2) -
+                at(3, 0) * at(1, 1) * at(0, 2));
+            cof(3, 0) = -(at(0, 1) * at(1, 2) * at(2, 3) +
+                at(1, 1) * at(2, 2) * at(0, 3) +
+                at(2, 1) * at(0, 2) * at(1, 3) -
+                at(0, 1) * at(2, 2) * at(1, 3) -
+                at(1, 1) * at(0, 2) * at(2, 3) -
+                at(2, 1) * at(1, 2) * at(0, 3));
+            cof(3, 1) = at(0, 0) * at(1, 2) * at(2, 3) +
+                at(1, 0) * at(2, 2) * at(0, 3) +
+                at(2, 0) * at(0, 2) * at(1, 3) -
+                at(0, 0) * at(2, 2) * at(1, 3) -
+                at(1, 0) * at(0, 2) * at(2, 3) -
+                at(2, 0) * at(1, 2) * at(0, 3);
+            cof(3, 2) = -(at(0, 0) * at(1, 1) * at(2, 3) +
+                at(1, 0) * at(2, 1) * at(0, 3) +
+                at(2, 0) * at(0, 1) * at(1, 3) -
+                at(0, 0) * at(2, 1) * at(1, 3) -
+                at(1, 0) * at(0, 1) * at(2, 3) -
+                at(2, 0) * at(1, 1) * at(0, 3));
+            cof(3, 3) = at(0, 0) * at(1, 1) * at(2, 2) +
+                at(1, 0) * at(2, 1) * at(0, 2) +
+                at(2, 0) * at(0, 1) * at(1, 2) -
+                at(0, 0) * at(2, 1) * at(1, 2) -
+                at(1, 0) * at(0, 1) * at(2, 2) -
+                at(2, 0) * at(1, 1) * at(0, 2);
+            break;
+
+          default:
+            UNREACHABLE();
+            break;
+        }
+
+        // The inverse of A is the transpose of the cofactor matrix times the reciprocal of the determinant of A.
+        Matrix<T> adjugateMatrix(cof.transpose());
+        T det = determinant();
+        Matrix<T> result(std::vector<T>(mElements.size()), rows(), columns());
+        for (unsigned int i = 0; i < rows(); i++)
+            for (unsigned int j = 0; j < columns(); j++)
+                result(i, j) = det ? adjugateMatrix(i, j) / det : T();
+
+        return result;
+    }
+
+    void setToIdentity()
+    {
+        ASSERT(rows() == columns());
+
+        const auto one  = T(1);
+        const auto zero = T(0);
+
+        for (auto &e : mElements)
+            e = zero;
+
+        for (unsigned int i = 0; i < rows(); ++i)
+        {
+            const auto pos = i * columns() + (i % columns());
+            mElements[pos] = one;
+        }
+    }
+
+    template <unsigned int Size>
+    static void setToIdentity(T(&matrix)[Size])
+    {
+        static_assert(gl::iSquareRoot<Size>() != 0, "Matrix is not square.");
+
+        const auto cols = gl::iSquareRoot<Size>();
+        const auto one  = T(1);
+        const auto zero = T(0);
+
+        for (auto &e : matrix)
+            e = zero;
+
+        for (unsigned int i = 0; i < cols; ++i)
+        {
+            const auto pos = i * cols + (i % cols);
+            matrix[pos]    = one;
+        }
+    }
+
+  private:
+    std::vector<T> mElements;
+    unsigned int mRows;
+    unsigned int mCols;
+};
+
+} // namespace angle
+
+#endif   // COMMON_MATRIX_UTILS_H_
+
diff --git a/src/third_party/angle/src/common/matrix_utils_unittest.cpp b/src/third_party/angle/src/common/matrix_utils_unittest.cpp
new file mode 100644
index 0000000..6e9f92d
--- /dev/null
+++ b/src/third_party/angle/src/common/matrix_utils_unittest.cpp
@@ -0,0 +1,184 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// matrix_utils_unittests:
+//   Unit tests for the matrix utils.
+//
+
+#include "matrix_utils.h"
+
+#include <gtest/gtest.h>
+
+using namespace angle;
+
+namespace
+{
+
+const unsigned int minDimensions = 2;
+const unsigned int maxDimensions = 4;
+
+TEST(MatrixUtilsTest, MatrixConstructorTest)
+{
+    for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+    {
+        for (unsigned int j = minDimensions; j <= maxDimensions; j++)
+        {
+            unsigned int numElements = i * j;
+            Matrix<float> m(std::vector<float>(numElements, 1.0f), i, j);
+            EXPECT_EQ(m.rows(), i);
+            EXPECT_EQ(m.columns(), j);
+            EXPECT_EQ(m.elements(), std::vector<float>(numElements, 1.0f));
+        }
+    }
+
+    for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+    {
+        unsigned int numElements = i * i;
+        Matrix<float> m(std::vector<float>(numElements, 1.0f), i);
+        EXPECT_EQ(m.size(), i);
+        EXPECT_EQ(m.columns(), m.columns());
+        EXPECT_EQ(m.elements(), std::vector<float>(numElements, 1.0f));
+    }
+}
+
+TEST(MatrixUtilsTest, MatrixCompMultTest)
+{
+    for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+    {
+        unsigned int numElements = i * i;
+        Matrix<float> m1(std::vector<float>(numElements, 2.0f), i);
+        Matrix<float> actualResult = m1.compMult(m1);
+        std::vector<float> actualResultElements = actualResult.elements();
+        std::vector<float> expectedResultElements(numElements, 4.0f);
+        EXPECT_EQ(expectedResultElements, actualResultElements);
+    }
+}
+
+TEST(MatrixUtilsTest, MatrixOuterProductTest)
+{
+    for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+    {
+        for (unsigned int j = minDimensions; j <= maxDimensions; j++)
+        {
+            unsigned int numElements = i * j;
+            Matrix<float> m1(std::vector<float>(numElements, 2.0f), i, 1);
+            Matrix<float> m2(std::vector<float>(numElements, 2.0f), 1, j);
+            Matrix<float> actualResult = m1.outerProduct(m2);
+            EXPECT_EQ(actualResult.rows(), i);
+            EXPECT_EQ(actualResult.columns(), j);
+            std::vector<float> actualResultElements = actualResult.elements();
+            std::vector<float> expectedResultElements(numElements, 4.0f);
+            EXPECT_EQ(expectedResultElements, actualResultElements);
+        }
+    }
+}
+
+TEST(MatrixUtilsTest, MatrixTransposeTest)
+{
+    for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+    {
+        for (unsigned int j = minDimensions; j <= maxDimensions; j++)
+        {
+            unsigned int numElements = i * j;
+            Matrix<float> m1(std::vector<float>(numElements, 2.0f), i, j);
+            Matrix<float> expectedResult = Matrix<float>(std::vector<float>(numElements, 2.0f), j, i);
+            Matrix<float> actualResult = m1.transpose();
+            EXPECT_EQ(expectedResult.elements(), actualResult.elements());
+            EXPECT_EQ(actualResult.rows(), expectedResult.rows());
+            EXPECT_EQ(actualResult.columns(), expectedResult.columns());
+            // transpose(transpose(A)) = A
+            Matrix<float> m2 = actualResult.transpose();
+            EXPECT_EQ(m1.elements(), m2.elements());
+        }
+    }
+}
+
+TEST(MatrixUtilsTest, MatrixDeterminantTest)
+{
+    for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+    {
+        unsigned int numElements = i * i;
+        Matrix<float> m(std::vector<float>(numElements, 2.0f), i);
+        EXPECT_EQ(m.determinant(), 0.0f);
+    }
+}
+
+TEST(MatrixUtilsTest, 2x2MatrixInverseTest)
+{
+    float inputElements[] =
+    {
+        2.0f, 5.0f,
+        3.0f, 7.0f
+    };
+    unsigned int numElements = 4;
+    std::vector<float> input(inputElements, inputElements + numElements);
+    Matrix<float> inputMatrix(input, 2);
+    float identityElements[] =
+    {
+        1.0f, 0.0f,
+        0.0f, 1.0f
+    };
+    std::vector<float> identityMatrix(identityElements, identityElements + numElements);
+    // A * inverse(A) = I, where I is identity matrix.
+    Matrix<float> result = inputMatrix * inputMatrix.inverse();
+    EXPECT_EQ(identityMatrix, result.elements());
+}
+
+TEST(MatrixUtilsTest, 3x3MatrixInverseTest)
+{
+    float inputElements[] =
+    {
+        11.0f, 23.0f, 37.0f,
+        13.0f, 29.0f, 41.0f,
+        19.0f, 31.0f, 43.0f
+    };
+    unsigned int numElements = 9;
+    std::vector<float> input(inputElements, inputElements + numElements);
+    Matrix<float> inputMatrix(input, 3);
+    float identityElements[] =
+    {
+        1.0f, 0.0f, 0.0f,
+        0.0f, 1.0f, 0.0f,
+        0.0f, 0.0f, 1.0f
+    };
+    std::vector<float> identityMatrix(identityElements, identityElements + numElements);
+    // A * inverse(A) = I, where I is identity matrix.
+    Matrix<float> result = inputMatrix * inputMatrix.inverse();
+    std::vector<float> resultElements = result.elements();
+    const float floatFaultTolarance = 0.000001f;
+    for (size_t i = 0; i < numElements; i++)
+        EXPECT_NEAR(resultElements[i], identityMatrix[i], floatFaultTolarance);
+}
+
+TEST(MatrixUtilsTest, 4x4MatrixInverseTest)
+{
+    float inputElements[] =
+    {
+        29.0f, 43.0f, 61.0f, 79.0f,
+        31.0f, 47.0f, 67.0f, 83.0f,
+        37.0f, 53.0f, 71.0f, 89.0f,
+        41.0f, 59.0f, 73.0f, 97.0f
+    };
+    unsigned int numElements = 16;
+    std::vector<float> input(inputElements, inputElements + numElements);
+    Matrix<float> inputMatrix(input, 4);
+    float identityElements[] =
+    {
+        1.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 1.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 1.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 1.0f,
+    };
+    std::vector<float> identityMatrix(identityElements, identityElements + numElements);
+    // A * inverse(A) = I, where I is identity matrix.
+    Matrix<float> result = inputMatrix * inputMatrix.inverse();
+    std::vector<float> resultElements = result.elements();
+    const float floatFaultTolarance = 0.00001f;
+    for (unsigned int i = 0; i < numElements; i++)
+        EXPECT_NEAR(resultElements[i], identityMatrix[i], floatFaultTolarance);
+}
+
+}
+
diff --git a/src/third_party/angle/src/common/platform.h b/src/third_party/angle/src/common/platform.h
new file mode 100644
index 0000000..2fe55e8
--- /dev/null
+++ b/src/third_party/angle/src/common/platform.h
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// platform.h: Operating system specific includes and defines.
+
+#ifndef COMMON_PLATFORM_H_
+#define COMMON_PLATFORM_H_
+
+#if defined(_WIN32) || defined(_WIN64)
+#   define ANGLE_PLATFORM_WINDOWS 1
+#elif defined(__APPLE__)
+#   define ANGLE_PLATFORM_APPLE 1
+#   define ANGLE_PLATFORM_POSIX 1
+#elif defined(ANDROID)
+#   define ANGLE_PLATFORM_ANDROID 1
+#   define ANGLE_PLATFORM_POSIX 1
+#elif defined(__linux__) || defined(EMSCRIPTEN)
+#   define ANGLE_PLATFORM_LINUX 1
+#   define ANGLE_PLATFORM_POSIX 1
+#elif defined(__FreeBSD__) || \
+      defined(__OpenBSD__) || \
+      defined(__NetBSD__) || \
+      defined(__DragonFly__) || \
+      defined(__sun) || \
+      defined(__GLIBC__) || \
+      defined(__GNU__) || \
+      defined(__QNX__)
+#   define ANGLE_PLATFORM_POSIX 1
+#else
+#   error Unsupported platform.
+#endif
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#   ifndef STRICT
+#       define STRICT 1
+#   endif
+#   ifndef WIN32_LEAN_AND_MEAN
+#       define WIN32_LEAN_AND_MEAN 1
+#   endif
+#   ifndef NOMINMAX
+#       define NOMINMAX 1
+#   endif
+
+#   include <windows.h>
+#   include <intrin.h>
+
+#   if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+#       define ANGLE_ENABLE_WINDOWS_STORE 1
+#   endif
+
+#   if defined(ANGLE_ENABLE_D3D9)
+#       include <d3d9.h>
+#       include <d3dcompiler.h>
+#   endif
+
+#   if defined(ANGLE_ENABLE_D3D11)
+#       include <d3d10_1.h>
+#       include <d3d11.h>
+#       include <d3d11_1.h>
+#       include <dxgi.h>
+#       include <dxgi1_2.h>
+#       include <d3dcompiler.h>
+#   endif
+
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+#include <wrl.h>
+#endif
+
+#   if defined(ANGLE_ENABLE_WINDOWS_STORE)
+#       include <dxgi1_3.h>
+#       if defined(_DEBUG)
+#           include <DXProgrammableCapture.h>
+#           include <dxgidebug.h>
+#       endif
+#   endif
+
+#   undef near
+#   undef far
+#endif
+
+#if defined(_MSC_VER) && !defined(_M_ARM)
+#include <intrin.h>
+#define ANGLE_USE_SSE
+#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
+#include <x86intrin.h>
+#define ANGLE_USE_SSE
+#endif
+
+// The MemoryBarrier function name collides with a macro under Windows
+// We will undef the macro so that the function name does not get replaced
+#undef MemoryBarrier
+
+#endif // COMMON_PLATFORM_H_
diff --git a/src/third_party/angle/src/common/string_utils.cpp b/src/third_party/angle/src/common/string_utils.cpp
new file mode 100644
index 0000000..bb1edd2
--- /dev/null
+++ b/src/third_party/angle/src/common/string_utils.cpp
@@ -0,0 +1,182 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// string_utils:
+//   String helper functions.
+//
+
+#include "string_utils.h"
+
+#include <algorithm>
+#include <stdlib.h>
+#include <string.h>
+#include <fstream>
+#include <sstream>
+
+#include "common/platform.h"
+
+namespace angle
+{
+
+const char kWhitespaceASCII[] = " \f\n\r\t\v";
+
+std::vector<std::string> SplitString(const std::string &input,
+                                     const std::string &delimiters,
+                                     WhitespaceHandling whitespace,
+                                     SplitResult resultType)
+{
+    std::vector<std::string> result;
+    if (input.empty())
+    {
+        return result;
+    }
+
+    std::string::size_type start = 0;
+    while (start != std::string::npos)
+    {
+        auto end = input.find_first_of(delimiters, start);
+
+        std::string piece;
+        if (end == std::string::npos)
+        {
+            piece = input.substr(start);
+            start = std::string::npos;
+        }
+        else
+        {
+            piece = input.substr(start, end - start);
+            start = end + 1;
+        }
+
+        if (whitespace == TRIM_WHITESPACE)
+        {
+            piece = TrimString(piece, kWhitespaceASCII);
+        }
+
+        if (resultType == SPLIT_WANT_ALL || !piece.empty())
+        {
+            result.push_back(piece);
+        }
+    }
+
+    return result;
+}
+
+void SplitStringAlongWhitespace(const std::string &input,
+                                std::vector<std::string> *tokensOut)
+{
+
+    std::istringstream stream(input);
+    std::string line;
+
+    while (std::getline(stream, line))
+    {
+        size_t prev = 0, pos;
+        while ((pos = line.find_first_of(kWhitespaceASCII, prev)) != std::string::npos)
+        {
+            if (pos > prev)
+                tokensOut->push_back(line.substr(prev, pos - prev));
+            prev = pos + 1;
+        }
+        if (prev < line.length())
+            tokensOut->push_back(line.substr(prev, std::string::npos));
+    }
+}
+
+std::string TrimString(const std::string &input, const std::string &trimChars)
+{
+    auto begin = input.find_first_not_of(trimChars);
+    if (begin == std::string::npos)
+    {
+        return "";
+    }
+
+    std::string::size_type end = input.find_last_not_of(trimChars);
+    if (end == std::string::npos)
+    {
+        return input.substr(begin);
+    }
+
+    return input.substr(begin, end - begin + 1);
+}
+
+bool HexStringToUInt(const std::string &input, unsigned int *uintOut)
+{
+    unsigned int offset = 0;
+
+    if (input.size() >= 2 && input[0] == '0' && input[1] == 'x')
+    {
+        offset = 2u;
+    }
+
+    // Simple validity check
+    if (input.find_first_not_of("0123456789ABCDEFabcdef", offset) != std::string::npos)
+    {
+        return false;
+    }
+
+    std::stringstream inStream(input);
+    inStream >> std::hex >> *uintOut;
+    return !inStream.fail();
+}
+
+bool ReadFileToString(const std::string &path, std::string *stringOut)
+{
+    std::ifstream inFile(path.c_str());
+    if (inFile.fail())
+    {
+        return false;
+    }
+
+    inFile.seekg(0, std::ios::end);
+    stringOut->reserve(static_cast<std::string::size_type>(inFile.tellg()));
+    inFile.seekg(0, std::ios::beg);
+
+    stringOut->assign(std::istreambuf_iterator<char>(inFile), std::istreambuf_iterator<char>());
+    return !inFile.fail();
+}
+
+Optional<std::vector<wchar_t>> WidenString(size_t length, const char *cString)
+{
+    std::vector<wchar_t> wcstring(length + 1);
+#if !defined(ANGLE_PLATFORM_WINDOWS)
+    size_t written = mbstowcs(wcstring.data(), cString, length + 1);
+    if (written == 0)
+    {
+        return Optional<std::vector<wchar_t>>::Invalid();
+    }
+#else
+    size_t convertedChars = 0;
+    errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, cString, _TRUNCATE);
+    if (err != 0)
+    {
+        return Optional<std::vector<wchar_t>>::Invalid();
+    }
+#endif
+    return Optional<std::vector<wchar_t>>(wcstring);
+}
+
+bool BeginsWith(const std::string &str, const char *prefix)
+{
+    return strncmp(str.c_str(), prefix, strlen(prefix)) == 0;
+}
+
+bool BeginsWith(const char *str, const char *prefix)
+{
+    return strncmp(str, prefix, strlen(prefix)) == 0;
+}
+
+bool EndsWith(const std::string &str, const char *suffix)
+{
+    const auto len = strlen(suffix);
+    if (len > str.size())
+        return false;
+
+    const char *end = str.c_str() + str.size() - len;
+
+    return memcmp(end, suffix, len) == 0;
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/common/string_utils.h b/src/third_party/angle/src/common/string_utils.h
new file mode 100644
index 0000000..c649c64
--- /dev/null
+++ b/src/third_party/angle/src/common/string_utils.h
@@ -0,0 +1,67 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// string_utils:
+//   String helper functions.
+//
+
+#ifndef LIBANGLE_STRING_UTILS_H_
+#define LIBANGLE_STRING_UTILS_H_
+
+#include <string>
+#include <vector>
+
+#include "common/Optional.h"
+
+namespace angle
+{
+
+extern const char kWhitespaceASCII[];
+
+enum WhitespaceHandling
+{
+    KEEP_WHITESPACE,
+    TRIM_WHITESPACE,
+};
+
+enum SplitResult
+{
+    SPLIT_WANT_ALL,
+    SPLIT_WANT_NONEMPTY,
+};
+
+std::vector<std::string> SplitString(const std::string &input,
+                                     const std::string &delimiters,
+                                     WhitespaceHandling whitespace,
+                                     SplitResult resultType);
+
+void SplitStringAlongWhitespace(const std::string &input,
+                                std::vector<std::string> *tokensOut);
+
+std::string TrimString(const std::string &input, const std::string &trimChars);
+
+bool HexStringToUInt(const std::string &input, unsigned int *uintOut);
+
+bool ReadFileToString(const std::string &path, std::string *stringOut);
+
+Optional<std::vector<wchar_t>> WidenString(size_t length, const char *cString);
+
+// Check if the string str begins with the given prefix.
+// Prefix may not be NULL and needs to be NULL terminated.
+// The comparison is case sensitive.
+bool BeginsWith(const std::string &str, const char *prefix);
+
+// Check if the string str begins with the given prefix.
+// str and prefix may not be NULL and need to be NULL terminated.
+// The comparison is case sensitive.
+bool BeginsWith(const char *str, const char *prefix);
+
+// Check if the string str ends with the given suffix.
+// Suffix may not be NUL and needs to be NULL terminated.
+// The comparison is case sensitive.
+bool EndsWith(const std::string& str, const char* suffix);
+}
+
+#endif // LIBANGLE_STRING_UTILS_H_
diff --git a/src/third_party/angle/src/common/string_utils_unittest.cpp b/src/third_party/angle/src/common/string_utils_unittest.cpp
new file mode 100644
index 0000000..e7ce8a6
--- /dev/null
+++ b/src/third_party/angle/src/common/string_utils_unittest.cpp
@@ -0,0 +1,163 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// string_utils_unittests:
+//   Unit tests for the string utils.
+//
+
+#include "string_utils.h"
+
+#include <gtest/gtest.h>
+
+using namespace angle;
+
+namespace
+{
+
+// Basic SplitString tests
+TEST(StringUtilsTest, SplitString_Basics)
+{
+    std::vector<std::string> r;
+
+    r = SplitString(std::string(), ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+    EXPECT_TRUE(r.empty());
+
+    // Empty separator list
+    r = SplitString("hello, world", "", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+    ASSERT_EQ(1u, r.size());
+    EXPECT_EQ("hello, world", r[0]);
+
+    // Should split on any of the separators.
+    r = SplitString("::,,;;", ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+    ASSERT_EQ(7u, r.size());
+    for (auto str : r)
+        ASSERT_TRUE(str.empty());
+
+    r = SplitString("red, green; blue:", ",:;", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+    ASSERT_EQ(3u, r.size());
+    EXPECT_EQ("red", r[0]);
+    EXPECT_EQ("green", r[1]);
+    EXPECT_EQ("blue", r[2]);
+
+    // Want to split a string along whitespace sequences.
+    r = SplitString("  red green   \tblue\n", " \t\n", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+    ASSERT_EQ(3u, r.size());
+    EXPECT_EQ("red", r[0]);
+    EXPECT_EQ("green", r[1]);
+    EXPECT_EQ("blue", r[2]);
+
+    // Weird case of splitting on spaces but not trimming.
+    r = SplitString(" red ", " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
+    ASSERT_EQ(3u, r.size());
+    EXPECT_EQ("", r[0]);  // Before the first space.
+    EXPECT_EQ("red", r[1]);
+    EXPECT_EQ("", r[2]);  // After the last space.
+}
+
+// Check different whitespace and result types for SplitString
+TEST(StringUtilsTest, SplitString_WhitespaceAndResultType)
+{
+    std::vector<std::string> r;
+
+    // Empty input handling.
+    r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+    EXPECT_TRUE(r.empty());
+    r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
+    EXPECT_TRUE(r.empty());
+
+    // Input string is space and we're trimming.
+    r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
+    ASSERT_EQ(1u, r.size());
+    EXPECT_EQ("", r[0]);
+    r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+    EXPECT_TRUE(r.empty());
+
+    // Test all 4 combinations of flags on ", ,".
+    r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+    ASSERT_EQ(3u, r.size());
+    EXPECT_EQ("", r[0]);
+    EXPECT_EQ(" ", r[1]);
+    EXPECT_EQ("", r[2]);
+    r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
+    ASSERT_EQ(1u, r.size());
+    ASSERT_EQ(" ", r[0]);
+    r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
+    ASSERT_EQ(3u, r.size());
+    EXPECT_EQ("", r[0]);
+    EXPECT_EQ("", r[1]);
+    EXPECT_EQ("", r[2]);
+    r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+    ASSERT_TRUE(r.empty());
+}
+
+// Tests for TrimString
+TEST(StringUtilsTest, TrimString)
+{
+    // Basic tests
+    EXPECT_EQ("a", TrimString("a", kWhitespaceASCII));
+    EXPECT_EQ("a", TrimString(" a", kWhitespaceASCII));
+    EXPECT_EQ("a", TrimString("a ", kWhitespaceASCII));
+    EXPECT_EQ("a", TrimString(" a ", kWhitespaceASCII));
+
+    // Tests with empty strings
+    EXPECT_EQ("", TrimString("", kWhitespaceASCII));
+    EXPECT_EQ("", TrimString(" \n\r\t", kWhitespaceASCII));
+    EXPECT_EQ(" foo ", TrimString(" foo ", ""));
+
+    // Tests it doesn't removes characters in the middle
+    EXPECT_EQ("foo bar", TrimString(" foo bar ", kWhitespaceASCII));
+
+    // Test with non-whitespace trimChars
+    EXPECT_EQ(" ", TrimString("foo bar", "abcdefghijklmnopqrstuvwxyz"));
+}
+
+// Basic functionality tests for HexStringToUInt
+TEST(StringUtilsTest, HexStringToUIntBasic)
+{
+    unsigned int uintValue;
+
+    std::string emptyString;
+    ASSERT_FALSE(HexStringToUInt(emptyString, &uintValue));
+
+    std::string testStringA("0xBADF00D");
+    ASSERT_TRUE(HexStringToUInt(testStringA, &uintValue));
+    EXPECT_EQ(0xBADF00Du, uintValue);
+
+    std::string testStringB("0xBADFOOD");
+    EXPECT_FALSE(HexStringToUInt(testStringB, &uintValue));
+
+    std::string testStringC("BADF00D");
+    EXPECT_TRUE(HexStringToUInt(testStringC, &uintValue));
+    EXPECT_EQ(0xBADF00Du, uintValue);
+
+    std::string testStringD("0x BADF00D");
+    EXPECT_FALSE(HexStringToUInt(testStringD, &uintValue));
+}
+
+// Note: ReadFileToString is harder to test
+
+
+TEST(StringUtilsTest, BeginsEndsWith)
+{
+    ASSERT_FALSE(BeginsWith("foo", "bar"));
+    ASSERT_FALSE(BeginsWith("", "foo"));
+    ASSERT_FALSE(BeginsWith("foo", "foobar"));
+
+    ASSERT_TRUE(BeginsWith("foobar", "foo"));
+    ASSERT_TRUE(BeginsWith("foobar", ""));
+    ASSERT_TRUE(BeginsWith("foo", "foo"));
+    ASSERT_TRUE(BeginsWith("", ""));
+
+    ASSERT_FALSE(EndsWith("foo", "bar"));
+    ASSERT_FALSE(EndsWith("", "bar"));
+    ASSERT_FALSE(EndsWith("foo", "foobar"));
+
+    ASSERT_TRUE(EndsWith("foobar", "bar"));
+    ASSERT_TRUE(EndsWith("foobar", ""));
+    ASSERT_TRUE(EndsWith("bar", "bar"));
+    ASSERT_TRUE(EndsWith("", ""));
+}
+
+}
\ No newline at end of file
diff --git a/src/third_party/angle/src/common/system.h b/src/third_party/angle/src/common/system.h
deleted file mode 100644
index 829b189..0000000
--- a/src/third_party/angle/src/common/system.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// system.h: Includes Windows system headers and undefines macros that conflict.
-
-#ifndef COMMON_SYSTEM_H
-#define COMMON_SYSTEM_H
-
-#if !defined(WIN32_LEAN_AND_MEAN)
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#include <windows.h>
-
-#if defined(__LB_XB360__)
-#include "common/xb360/player.h"
-#endif
-
-#if defined(__cplusplus_winrt)
-#define ANGLE_WINRT 1
-#elif !defined(__LB_XB360__)
-#define ANGLE_WIN32 1
-#endif
-
-#if defined(min)
-#undef min
-#endif
-
-#if defined(max)
-#undef max
-#endif
-
-#if defined(__LB_XB360__)
-
-#if !defined (ANGLE_ENABLE_XB360_STRICT)
-#define ANGLE_ENABLE_XB360_STRICT 1
-#endif
-
-#if !defined(ANGLE_ENABLE_D3D11)
-#define ANGLE_ENABLE_D3D11 0
-#endif
-
-#endif
-
-#if defined(ANGLE_WINRT)
-
-#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_TV_APP)
-#error "Must be compiled using one of the WINAPI_FAMILY_*_APP APIs"
-#endif
-
-#if !defined(ANGLE_ENABLE_D3D11)
-#define ANGLE_ENABLE_D3D11 1
-#endif
-
-#if !defined(ANGLE_ENABLE_D3D11_STRICT)
-#define ANGLE_ENABLE_D3D11_STRICT 1
-#endif
-
-#if !defined(ANGLE_STATIC_D3D_LIB)
-#define ANGLE_STATIC_D3D_LIB 1
-#endif
-
-#define ANGLE_NO_WINDOW nullptr
-
-#else
-
-#define ANGLE_NO_WINDOW NULL
-
-#endif // ANGLE_WINRT
-
-#define EGLAPI
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#endif   // COMMON_SYSTEM_H
diff --git a/src/third_party/angle/src/common/system_utils.h b/src/third_party/angle/src/common/system_utils.h
new file mode 100644
index 0000000..cac24f7
--- /dev/null
+++ b/src/third_party/angle/src/common/system_utils.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils.h: declaration of OS-specific utility functions
+
+#ifndef COMMON_SYSTEM_UTILS_H_
+#define COMMON_SYSTEM_UTILS_H_
+
+#include "common/angleutils.h"
+#include "common/Optional.h"
+
+namespace angle
+{
+
+const char *GetExecutablePath();
+const char *GetExecutableDirectory();
+const char *GetSharedLibraryExtension();
+Optional<std::string> GetCWD();
+bool SetCWD(const char *dirName);
+
+}  // namespace angle
+
+#endif  // COMMON_SYSTEM_UTILS_H_
diff --git a/src/third_party/angle/src/common/system_utils_linux.cpp b/src/third_party/angle/src/common/system_utils_linux.cpp
new file mode 100644
index 0000000..8504c6a
--- /dev/null
+++ b/src/third_party/angle/src/common/system_utils_linux.cpp
@@ -0,0 +1,84 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils_linux.cpp: Implementation of OS-specific functions for Linux
+
+#include "system_utils.h"
+
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <array>
+
+namespace angle
+{
+
+namespace
+{
+
+std::string GetExecutablePathImpl()
+{
+    // We cannot use lstat to get the size of /proc/self/exe as it always returns 0
+    // so we just use a big buffer and hope the path fits in it.
+    char path[4096];
+
+    ssize_t result = readlink("/proc/self/exe", path, sizeof(path) - 1);
+    if (result < 0 || static_cast<size_t>(result) >= sizeof(path) - 1)
+    {
+        return "";
+    }
+
+    path[result] = '\0';
+    return path;
+}
+
+std::string GetExecutableDirectoryImpl()
+{
+    std::string executablePath = GetExecutablePath();
+    size_t lastPathSepLoc      = executablePath.find_last_of("/");
+    return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
+}
+
+}  // anonymous namespace
+
+const char *GetExecutablePath()
+{
+    // TODO(jmadill): Make global static string thread-safe.
+    const static std::string &exePath = GetExecutablePathImpl();
+    return exePath.c_str();
+}
+
+const char *GetExecutableDirectory()
+{
+    // TODO(jmadill): Make global static string thread-safe.
+    const static std::string &exeDir = GetExecutableDirectoryImpl();
+    return exeDir.c_str();
+}
+
+const char *GetSharedLibraryExtension()
+{
+    return "so";
+}
+
+Optional<std::string> GetCWD()
+{
+    std::array<char, 4096> pathBuf;
+    char *result = getcwd(pathBuf.data(), pathBuf.size());
+    if (result == nullptr)
+    {
+        return Optional<std::string>::Invalid();
+    }
+    return std::string(pathBuf.data());
+}
+
+bool SetCWD(const char *dirName)
+{
+    return (chdir(dirName) == 0);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/common/system_utils_mac.cpp b/src/third_party/angle/src/common/system_utils_mac.cpp
new file mode 100644
index 0000000..a73f1aa
--- /dev/null
+++ b/src/third_party/angle/src/common/system_utils_mac.cpp
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils_osx.cpp: Implementation of OS-specific functions for OSX
+
+#include "system_utils.h"
+
+#include <unistd.h>
+
+#include <cstdlib>
+#include <mach-o/dyld.h>
+#include <vector>
+
+#include <array>
+
+namespace angle
+{
+
+namespace
+{
+
+std::string GetExecutablePathImpl()
+{
+    std::string result;
+
+    uint32_t size = 0;
+    _NSGetExecutablePath(nullptr, &size);
+
+    std::vector<char> buffer;
+    buffer.resize(size + 1);
+
+    _NSGetExecutablePath(buffer.data(), &size);
+    buffer[size] = '\0';
+
+    if (!strrchr(buffer.data(), '/'))
+    {
+        return "";
+    }
+    return buffer.data();
+}
+
+std::string GetExecutableDirectoryImpl()
+{
+    std::string executablePath = GetExecutablePath();
+    size_t lastPathSepLoc      = executablePath.find_last_of("/");
+    return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
+}
+
+}  // anonymous namespace
+
+const char *GetExecutablePath()
+{
+    // TODO(jmadill): Make global static string thread-safe.
+    const static std::string &exePath = GetExecutablePathImpl();
+    return exePath.c_str();
+}
+
+const char *GetExecutableDirectory()
+{
+    // TODO(jmadill): Make global static string thread-safe.
+    const static std::string &exeDir = GetExecutableDirectoryImpl();
+    return exeDir.c_str();
+}
+
+const char *GetSharedLibraryExtension()
+{
+    return "dylib";
+}
+
+Optional<std::string> GetCWD()
+{
+    std::array<char, 4096> pathBuf;
+    char *result = getcwd(pathBuf.data(), pathBuf.size());
+    if (result == nullptr)
+    {
+        return Optional<std::string>::Invalid();
+    }
+    return std::string(pathBuf.data());
+}
+
+bool SetCWD(const char *dirName)
+{
+    return (chdir(dirName) == 0);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/common/system_utils_win.cpp b/src/third_party/angle/src/common/system_utils_win.cpp
new file mode 100644
index 0000000..8f765ff
--- /dev/null
+++ b/src/third_party/angle/src/common/system_utils_win.cpp
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils_win.cpp: Implementation of OS-specific functions for Windows
+
+#include "system_utils.h"
+
+#include <stdarg.h>
+#include <windows.h>
+#include <array>
+#include <vector>
+
+namespace angle
+{
+
+namespace
+{
+
+std::string GetExecutablePathImpl()
+{
+    std::array<char, MAX_PATH> executableFileBuf;
+    DWORD executablePathLen = GetModuleFileNameA(nullptr, executableFileBuf.data(),
+                                                 static_cast<DWORD>(executableFileBuf.size()));
+    return (executablePathLen > 0 ? std::string(executableFileBuf.data()) : "");
+}
+
+std::string GetExecutableDirectoryImpl()
+{
+    std::string executablePath = GetExecutablePath();
+    size_t lastPathSepLoc      = executablePath.find_last_of("\\/");
+    return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
+}
+
+}  // anonymous namespace
+
+const char *GetExecutablePath()
+{
+    // TODO(jmadill): Make global static string thread-safe.
+    const static std::string &exePath = GetExecutablePathImpl();
+    return exePath.c_str();
+}
+
+const char *GetExecutableDirectory()
+{
+    // TODO(jmadill): Make global static string thread-safe.
+    const static std::string &exeDir = GetExecutableDirectoryImpl();
+    return exeDir.c_str();
+}
+
+const char *GetSharedLibraryExtension()
+{
+    return "dll";
+}
+
+Optional<std::string> GetCWD()
+{
+    std::array<char, MAX_PATH> pathBuf;
+    DWORD result = GetCurrentDirectoryA(static_cast<DWORD>(pathBuf.size()), pathBuf.data());
+    if (result == 0)
+    {
+        return Optional<std::string>::Invalid();
+    }
+    return std::string(pathBuf.data());
+}
+
+bool SetCWD(const char *dirName)
+{
+    return (SetCurrentDirectoryA(dirName) == TRUE);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/common/third_party/numerics/README.angle b/src/third_party/angle/src/common/third_party/numerics/README.angle
new file mode 100644
index 0000000..c7df1a8
--- /dev/null
+++ b/src/third_party/angle/src/common/third_party/numerics/README.angle
@@ -0,0 +1,16 @@
+Name: Chromium: base/numerics
+Short Name: base::numerics
+Version:
+URL: https://chromium.googlesource.com/chromium/src.git/+/lkcr/base/numerics/
+SOURCE CODE: Copy the Chromium folder manually into this folder and run git cl format.
+Date: 30/05/2016
+Revision: 28b5bbb227d331c01e6ff9b2f8729732135aadc7 (Chromium)
+Security Critical: no
+License: Chromium
+License File: LICENSE in Chromium/src
+
+Description:
+base::numerics is a library for doing some simple safe math and conversions. To update the checkout, simply
+overwrite the base/numerics folder with Chromium's latest. The only modifications are to the base/logging.h
+file which defines CHECK to be ASSERT to be compatible with ANGLE.
+
diff --git a/src/third_party/angle/src/common/third_party/numerics/base/logging.h b/src/third_party/angle/src/common/third_party/numerics/base/logging.h
new file mode 100644
index 0000000..6cf05b4
--- /dev/null
+++ b/src/third_party/angle/src/common/third_party/numerics/base/logging.h
@@ -0,0 +1,22 @@
+//
+// Copyright 2016 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.
+//
+// logging.h: Compatiblity hacks for importing Chromium's base/numerics.
+
+#ifndef BASE_LOGGING_H_
+#define BASE_LOGGING_H_
+
+#include "common/debug.h"
+
+#ifndef CHECK
+#define CHECK(X) ASSERT(X)
+#endif
+
+// Unfortunately ANGLE relies on ASSERT being an empty statement, which these libs don't respect.
+#ifndef NOTREACHED
+#define NOTREACHED() UNREACHABLE()
+#endif
+
+#endif  // BASE_LOGGING_H_
diff --git a/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_conversions.h b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_conversions.h
new file mode 100644
index 0000000..3fe496c
--- /dev/null
+++ b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_conversions.h
@@ -0,0 +1,174 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_
+#define BASE_NUMERICS_SAFE_CONVERSIONS_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "base/numerics/safe_conversions_impl.h"
+
+namespace base
+{
+
+// Convenience function that returns true if the supplied value is in range
+// for the destination type.
+template <typename Dst, typename Src>
+constexpr bool IsValueInRangeForNumericType(Src value)
+{
+    return internal::DstRangeRelationToSrcRange<Dst>(value) == internal::RANGE_VALID;
+}
+
+// Convenience function for determining if a numeric value is negative without
+// throwing compiler warnings on: unsigned(value) < 0.
+template <typename T>
+constexpr typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type IsValueNegative(
+    T value)
+{
+    static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric.");
+    return value < 0;
+}
+
+template <typename T>
+constexpr typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type IsValueNegative(T)
+{
+    static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric.");
+    return false;
+}
+
+// checked_cast<> is analogous to static_cast<> for numeric types,
+// except that it CHECKs that the specified numeric conversion will not
+// overflow or underflow. NaN source will always trigger a CHECK.
+template <typename Dst, typename Src>
+inline Dst checked_cast(Src value)
+{
+    CHECK(IsValueInRangeForNumericType<Dst>(value));
+    return static_cast<Dst>(value);
+}
+
+// HandleNaN will cause this class to CHECK(false).
+struct SaturatedCastNaNBehaviorCheck
+{
+    template <typename T>
+    static T HandleNaN()
+    {
+        CHECK(false);
+        return T();
+    }
+};
+
+// HandleNaN will return 0 in this case.
+struct SaturatedCastNaNBehaviorReturnZero
+{
+    template <typename T>
+    static constexpr T HandleNaN()
+    {
+        return T();
+    }
+};
+
+namespace internal
+{
+// This wrapper is used for C++11 constexpr support by avoiding the declaration
+// of local variables in the saturated_cast template function.
+template <typename Dst, class NaNHandler, typename Src>
+constexpr Dst saturated_cast_impl(const Src value, const RangeConstraint constraint)
+{
+    return constraint == RANGE_VALID
+               ? static_cast<Dst>(value)
+               : (constraint == RANGE_UNDERFLOW
+                      ? std::numeric_limits<Dst>::min()
+                      : (constraint == RANGE_OVERFLOW
+                             ? std::numeric_limits<Dst>::max()
+                             : (constraint == RANGE_INVALID
+                                    ? NaNHandler::template HandleNaN<Dst>()
+                                    : (NOTREACHED(), static_cast<Dst>(value)))));
+}
+}  // namespace internal
+
+// saturated_cast<> is analogous to static_cast<> for numeric types, except
+// that the specified numeric conversion will saturate rather than overflow or
+// underflow. NaN assignment to an integral will defer the behavior to a
+// specified class. By default, it will return 0.
+template <typename Dst, class NaNHandler = SaturatedCastNaNBehaviorReturnZero, typename Src>
+constexpr Dst saturated_cast(Src value)
+{
+    return std::numeric_limits<Dst>::is_iec559
+               ? static_cast<Dst>(value)  // Floating point optimization.
+               : internal::saturated_cast_impl<Dst, NaNHandler>(
+                     value, internal::DstRangeRelationToSrcRange<Dst>(value));
+}
+
+// strict_cast<> is analogous to static_cast<> for numeric types, except that
+// it will cause a compile failure if the destination type is not large enough
+// to contain any value in the source type. It performs no runtime checking.
+template <typename Dst, typename Src>
+constexpr Dst strict_cast(Src value)
+{
+    static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+    static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric.");
+    static_assert((internal::StaticDstRangeRelationToSrcRange<Dst, Src>::value ==
+                   internal::NUMERIC_RANGE_CONTAINED),
+                  "The numeric conversion is out of range for this type. You "
+                  "should probably use one of the following conversion "
+                  "mechanisms on the value you want to pass:\n"
+                  "- base::checked_cast\n"
+                  "- base::saturated_cast\n"
+                  "- base::CheckedNumeric");
+
+    return static_cast<Dst>(value);
+}
+
+// StrictNumeric implements compile time range checking between numeric types by
+// wrapping assignment operations in a strict_cast. This class is intended to be
+// used for function arguments and return types, to ensure the destination type
+// can always contain the source type. This is essentially the same as enforcing
+// -Wconversion in gcc and C4302 warnings on MSVC, but it can be applied
+// incrementally at API boundaries, making it easier to convert code so that it
+// compiles cleanly with truncation warnings enabled.
+// This template should introduce no runtime overhead, but it also provides no
+// runtime checking of any of the associated mathematical operations. Use
+// CheckedNumeric for runtime range checks of the actual value being assigned.
+template <typename T>
+class StrictNumeric
+{
+  public:
+    typedef T type;
+
+    constexpr StrictNumeric() : value_(0) {}
+
+    // Copy constructor.
+    template <typename Src>
+    constexpr StrictNumeric(const StrictNumeric<Src> &rhs) : value_(strict_cast<T>(rhs.value_))
+    {
+    }
+
+    // This is not an explicit constructor because we implicitly upgrade regular
+    // numerics to StrictNumerics to make them easier to use.
+    template <typename Src>
+    constexpr StrictNumeric(Src value) : value_(strict_cast<T>(value))
+    {
+    }
+
+    // The numeric cast operator basically handles all the magic.
+    template <typename Dst>
+    constexpr operator Dst() const
+    {
+        return strict_cast<Dst>(value_);
+    }
+
+  private:
+    const T value_;
+};
+
+// Explicitly make a shorter size_t typedef for convenience.
+typedef StrictNumeric<size_t> SizeT;
+
+}  // namespace base
+
+#endif  // BASE_NUMERICS_SAFE_CONVERSIONS_H_
diff --git a/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_conversions_impl.h b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_conversions_impl.h
new file mode 100644
index 0000000..1591b9c
--- /dev/null
+++ b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_conversions_impl.h
@@ -0,0 +1,269 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
+#define BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
+
+#include <limits.h>
+#include <stdint.h>
+
+#include <climits>
+#include <limits>
+
+namespace base
+{
+namespace internal
+{
+
+// The std library doesn't provide a binary max_exponent for integers, however
+// we can compute one by adding one to the number of non-sign bits. This allows
+// for accurate range comparisons between floating point and integer types.
+template <typename NumericType>
+struct MaxExponent
+{
+    static_assert(std::is_arithmetic<NumericType>::value, "Argument must be numeric.");
+    static const int value =
+        std::numeric_limits<NumericType>::is_iec559
+            ? std::numeric_limits<NumericType>::max_exponent
+            : (sizeof(NumericType) * CHAR_BIT + 1 - std::numeric_limits<NumericType>::is_signed);
+};
+
+enum IntegerRepresentation
+{
+    INTEGER_REPRESENTATION_UNSIGNED,
+    INTEGER_REPRESENTATION_SIGNED
+};
+
+// A range for a given nunmeric Src type is contained for a given numeric Dst
+// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and
+// numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true.
+// We implement this as template specializations rather than simple static
+// comparisons to ensure type correctness in our comparisons.
+enum NumericRangeRepresentation
+{
+    NUMERIC_RANGE_NOT_CONTAINED,
+    NUMERIC_RANGE_CONTAINED
+};
+
+// Helper templates to statically determine if our destination type can contain
+// maximum and minimum values represented by the source type.
+
+template <typename Dst,
+          typename Src,
+          IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
+                                              ? INTEGER_REPRESENTATION_SIGNED
+                                              : INTEGER_REPRESENTATION_UNSIGNED,
+          IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
+                                              ? INTEGER_REPRESENTATION_SIGNED
+                                              : INTEGER_REPRESENTATION_UNSIGNED>
+struct StaticDstRangeRelationToSrcRange;
+
+// Same sign: Dst is guaranteed to contain Src only if its range is equal or
+// larger.
+template <typename Dst, typename Src, IntegerRepresentation Sign>
+struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign>
+{
+    static const NumericRangeRepresentation value =
+        MaxExponent<Dst>::value >= MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED
+                                                           : NUMERIC_RANGE_NOT_CONTAINED;
+};
+
+// Unsigned to signed: Dst is guaranteed to contain source only if its range is
+// larger.
+template <typename Dst, typename Src>
+struct StaticDstRangeRelationToSrcRange<Dst,
+                                        Src,
+                                        INTEGER_REPRESENTATION_SIGNED,
+                                        INTEGER_REPRESENTATION_UNSIGNED>
+{
+    static const NumericRangeRepresentation value =
+        MaxExponent<Dst>::value > MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED
+                                                          : NUMERIC_RANGE_NOT_CONTAINED;
+};
+
+// Signed to unsigned: Dst cannot be statically determined to contain Src.
+template <typename Dst, typename Src>
+struct StaticDstRangeRelationToSrcRange<Dst,
+                                        Src,
+                                        INTEGER_REPRESENTATION_UNSIGNED,
+                                        INTEGER_REPRESENTATION_SIGNED>
+{
+    static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
+};
+
+enum RangeConstraint : unsigned char
+{
+    RANGE_VALID     = 0x0,  // Value can be represented by the destination type.
+    RANGE_UNDERFLOW = 0x1,  // Value would overflow.
+    RANGE_OVERFLOW  = 0x2,  // Value would underflow.
+    RANGE_INVALID   = RANGE_UNDERFLOW | RANGE_OVERFLOW  // Invalid (i.e. NaN).
+};
+
+// Helper function for coercing an int back to a RangeContraint.
+constexpr RangeConstraint GetRangeConstraint(int integer_range_constraint)
+{
+    // TODO(jschuh): Once we get full C++14 support we want this
+    // assert(integer_range_constraint >= RANGE_VALID &&
+    //        integer_range_constraint <= RANGE_INVALID)
+    return static_cast<RangeConstraint>(integer_range_constraint);
+}
+
+// This function creates a RangeConstraint from an upper and lower bound
+// check by taking advantage of the fact that only NaN can be out of range in
+// both directions at once.
+constexpr inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, bool is_in_lower_bound)
+{
+    return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) |
+                              (is_in_lower_bound ? 0 : RANGE_UNDERFLOW));
+}
+
+// The following helper template addresses a corner case in range checks for
+// conversion from a floating-point type to an integral type of smaller range
+// but larger precision (e.g. float -> unsigned). The problem is as follows:
+//   1. Integral maximum is always one less than a power of two, so it must be
+//      truncated to fit the mantissa of the floating point. The direction of
+//      rounding is implementation defined, but by default it's always IEEE
+//      floats, which round to nearest and thus result in a value of larger
+//      magnitude than the integral value.
+//      Example: float f = UINT_MAX; // f is 4294967296f but UINT_MAX
+//                                   // is 4294967295u.
+//   2. If the floating point value is equal to the promoted integral maximum
+//      value, a range check will erroneously pass.
+//      Example: (4294967296f <= 4294967295u) // This is true due to a precision
+//                                            // loss in rounding up to float.
+//   3. When the floating point value is then converted to an integral, the
+//      resulting value is out of range for the target integral type and
+//      thus is implementation defined.
+//      Example: unsigned u = (float)INT_MAX; // u will typically overflow to 0.
+// To fix this bug we manually truncate the maximum value when the destination
+// type is an integral of larger precision than the source floating-point type,
+// such that the resulting maximum is represented exactly as a floating point.
+template <typename Dst, typename Src>
+struct NarrowingRange
+{
+    typedef typename std::numeric_limits<Src> SrcLimits;
+    typedef typename std::numeric_limits<Dst> DstLimits;
+    // The following logic avoids warnings where the max function is
+    // instantiated with invalid values for a bit shift (even though
+    // such a function can never be called).
+    static const int shift = (MaxExponent<Src>::value > MaxExponent<Dst>::value &&
+                              SrcLimits::digits < DstLimits::digits &&
+                              SrcLimits::is_iec559 &&
+                              DstLimits::is_integer)
+                                 ? (DstLimits::digits - SrcLimits::digits)
+                                 : 0;
+
+    static constexpr Dst max()
+    {
+        // We use UINTMAX_C below to avoid compiler warnings about shifting floating
+        // points. Since it's a compile time calculation, it shouldn't have any
+        // performance impact.
+        return DstLimits::max() - static_cast<Dst>((UINTMAX_C(1) << shift) - 1);
+    }
+
+    static constexpr Dst min()
+    {
+        return std::numeric_limits<Dst>::is_iec559 ? -DstLimits::max() : DstLimits::min();
+    }
+};
+
+template <typename Dst,
+          typename Src,
+          IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
+                                              ? INTEGER_REPRESENTATION_SIGNED
+                                              : INTEGER_REPRESENTATION_UNSIGNED,
+          IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
+                                              ? INTEGER_REPRESENTATION_SIGNED
+                                              : INTEGER_REPRESENTATION_UNSIGNED,
+          NumericRangeRepresentation DstRange = StaticDstRangeRelationToSrcRange<Dst, Src>::value>
+struct DstRangeRelationToSrcRangeImpl;
+
+// The following templates are for ranges that must be verified at runtime. We
+// split it into checks based on signedness to avoid confusing casts and
+// compiler warnings on signed an unsigned comparisons.
+
+// Dst range is statically determined to contain Src: Nothing to check.
+template <typename Dst, typename Src, IntegerRepresentation DstSign, IntegerRepresentation SrcSign>
+struct DstRangeRelationToSrcRangeImpl<Dst, Src, DstSign, SrcSign, NUMERIC_RANGE_CONTAINED>
+{
+    static constexpr RangeConstraint Check(Src value) { return RANGE_VALID; }
+};
+
+// Signed to signed narrowing: Both the upper and lower boundaries may be
+// exceeded.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+                                      Src,
+                                      INTEGER_REPRESENTATION_SIGNED,
+                                      INTEGER_REPRESENTATION_SIGNED,
+                                      NUMERIC_RANGE_NOT_CONTAINED>
+{
+    static constexpr RangeConstraint Check(Src value)
+    {
+        return GetRangeConstraint((value <= NarrowingRange<Dst, Src>::max()),
+                                  (value >= NarrowingRange<Dst, Src>::min()));
+    }
+};
+
+// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+                                      Src,
+                                      INTEGER_REPRESENTATION_UNSIGNED,
+                                      INTEGER_REPRESENTATION_UNSIGNED,
+                                      NUMERIC_RANGE_NOT_CONTAINED>
+{
+    static constexpr RangeConstraint Check(Src value)
+    {
+        return GetRangeConstraint(value <= NarrowingRange<Dst, Src>::max(), true);
+    }
+};
+
+// Unsigned to signed: The upper boundary may be exceeded.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+                                      Src,
+                                      INTEGER_REPRESENTATION_SIGNED,
+                                      INTEGER_REPRESENTATION_UNSIGNED,
+                                      NUMERIC_RANGE_NOT_CONTAINED>
+{
+    static constexpr RangeConstraint Check(Src value)
+    {
+        return sizeof(Dst) > sizeof(Src)
+                   ? RANGE_VALID
+                   : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
+                                        true);
+    }
+};
+
+// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst,
+// and any negative value exceeds the lower boundary.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+                                      Src,
+                                      INTEGER_REPRESENTATION_UNSIGNED,
+                                      INTEGER_REPRESENTATION_SIGNED,
+                                      NUMERIC_RANGE_NOT_CONTAINED>
+{
+    static constexpr RangeConstraint Check(Src value)
+    {
+        return (MaxExponent<Dst>::value >= MaxExponent<Src>::value)
+                   ? GetRangeConstraint(true, value >= static_cast<Src>(0))
+                   : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
+                                        value >= static_cast<Src>(0));
+    }
+};
+
+template <typename Dst, typename Src>
+constexpr RangeConstraint DstRangeRelationToSrcRange(Src value)
+{
+    static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+    static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric.");
+    return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value);
+}
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
diff --git a/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_math.h b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_math.h
new file mode 100644
index 0000000..505efde
--- /dev/null
+++ b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_math.h
@@ -0,0 +1,324 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_MATH_H_
+#define BASE_NUMERICS_SAFE_MATH_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "base/numerics/safe_math_impl.h"
+
+namespace base
+{
+
+namespace internal
+{
+
+// CheckedNumeric implements all the logic and operators for detecting integer
+// boundary conditions such as overflow, underflow, and invalid conversions.
+// The CheckedNumeric type implicitly converts from floating point and integer
+// data types, and contains overloads for basic arithmetic operations (i.e.: +,
+// -, *, /, %).
+//
+// The following methods convert from CheckedNumeric to standard numeric values:
+// IsValid() - Returns true if the underlying numeric value is valid (i.e. has
+//             has not wrapped and is not the result of an invalid conversion).
+// ValueOrDie() - Returns the underlying value. If the state is not valid this
+//                call will crash on a CHECK.
+// ValueOrDefault() - Returns the current value, or the supplied default if the
+//                    state is not valid.
+// ValueFloating() - Returns the underlying floating point value (valid only
+//                   only for floating point CheckedNumeric types).
+//
+// Bitwise operations are explicitly not supported, because correct
+// handling of some cases (e.g. sign manipulation) is ambiguous. Comparison
+// operations are explicitly not supported because they could result in a crash
+// on a CHECK condition. You should use patterns like the following for these
+// operations:
+// Bitwise operation:
+//     CheckedNumeric<int> checked_int = untrusted_input_value;
+//     int x = checked_int.ValueOrDefault(0) | kFlagValues;
+// Comparison:
+//   CheckedNumeric<size_t> checked_size = untrusted_input_value;
+//   checked_size += HEADER LENGTH;
+//   if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size)
+//     Do stuff...
+template <typename T>
+class CheckedNumeric
+{
+    static_assert(std::is_arithmetic<T>::value, "CheckedNumeric<T>: T must be a numeric type.");
+
+  public:
+    typedef T type;
+
+    CheckedNumeric() {}
+
+    // Copy constructor.
+    template <typename Src>
+    CheckedNumeric(const CheckedNumeric<Src> &rhs) : state_(rhs.ValueUnsafe(), rhs.validity())
+    {
+    }
+
+    template <typename Src>
+    CheckedNumeric(Src value, RangeConstraint validity) : state_(value, validity)
+    {
+    }
+
+    // This is not an explicit constructor because we implicitly upgrade regular
+    // numerics to CheckedNumerics to make them easier to use.
+    template <typename Src>
+    CheckedNumeric(Src value)  // NOLINT(runtime/explicit)
+        : state_(value)
+    {
+        static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+    }
+
+    // This is not an explicit constructor because we want a seamless conversion
+    // from StrictNumeric types.
+    template <typename Src>
+    CheckedNumeric(StrictNumeric<Src> value)  // NOLINT(runtime/explicit)
+        : state_(static_cast<Src>(value))
+    {
+    }
+
+    // IsValid() is the public API to test if a CheckedNumeric is currently valid.
+    bool IsValid() const { return validity() == RANGE_VALID; }
+
+    // ValueOrDie() The primary accessor for the underlying value. If the current
+    // state is not valid it will CHECK and crash.
+    T ValueOrDie() const
+    {
+        CHECK(IsValid());
+        return state_.value();
+    }
+
+    // ValueOrDefault(T default_value) A convenience method that returns the
+    // current value if the state is valid, and the supplied default_value for
+    // any other state.
+    T ValueOrDefault(T default_value) const { return IsValid() ? state_.value() : default_value; }
+
+    // ValueFloating() - Since floating point values include their validity state,
+    // we provide an easy method for extracting them directly, without a risk of
+    // crashing on a CHECK.
+    T ValueFloating() const
+    {
+        static_assert(std::numeric_limits<T>::is_iec559, "Argument must be float.");
+        return CheckedNumeric<T>::cast(*this).ValueUnsafe();
+    }
+
+    // validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for
+    // tests and to avoid a big matrix of friend operator overloads. But the
+    // values it returns are likely to change in the future.
+    // Returns: current validity state (i.e. valid, overflow, underflow, nan).
+    // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
+    // saturation/wrapping so we can expose this state consistently and implement
+    // saturated arithmetic.
+    RangeConstraint validity() const { return state_.validity(); }
+
+    // ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now
+    // for tests and to avoid a big matrix of friend operator overloads. But the
+    // values it returns are likely to change in the future.
+    // Returns: the raw numeric value, regardless of the current state.
+    // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
+    // saturation/wrapping so we can expose this state consistently and implement
+    // saturated arithmetic.
+    T ValueUnsafe() const { return state_.value(); }
+
+    // Prototypes for the supported arithmetic operator overloads.
+    template <typename Src>
+    CheckedNumeric &operator+=(Src rhs);
+    template <typename Src>
+    CheckedNumeric &operator-=(Src rhs);
+    template <typename Src>
+    CheckedNumeric &operator*=(Src rhs);
+    template <typename Src>
+    CheckedNumeric &operator/=(Src rhs);
+    template <typename Src>
+    CheckedNumeric &operator%=(Src rhs);
+
+    CheckedNumeric operator-() const
+    {
+        RangeConstraint validity;
+        T value = CheckedNeg(state_.value(), &validity);
+        // Negation is always valid for floating point.
+        if (std::numeric_limits<T>::is_iec559)
+            return CheckedNumeric<T>(value);
+
+        validity = GetRangeConstraint(state_.validity() | validity);
+        return CheckedNumeric<T>(value, validity);
+    }
+
+    CheckedNumeric Abs() const
+    {
+        RangeConstraint validity;
+        T value = CheckedAbs(state_.value(), &validity);
+        // Absolute value is always valid for floating point.
+        if (std::numeric_limits<T>::is_iec559)
+            return CheckedNumeric<T>(value);
+
+        validity = GetRangeConstraint(state_.validity() | validity);
+        return CheckedNumeric<T>(value, validity);
+    }
+
+    // This function is available only for integral types. It returns an unsigned
+    // integer of the same width as the source type, containing the absolute value
+    // of the source, and properly handling signed min.
+    CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const
+    {
+        return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
+            CheckedUnsignedAbs(state_.value()), state_.validity());
+    }
+
+    CheckedNumeric &operator++()
+    {
+        *this += 1;
+        return *this;
+    }
+
+    CheckedNumeric operator++(int)
+    {
+        CheckedNumeric value = *this;
+        *this += 1;
+        return value;
+    }
+
+    CheckedNumeric &operator--()
+    {
+        *this -= 1;
+        return *this;
+    }
+
+    CheckedNumeric operator--(int)
+    {
+        CheckedNumeric value = *this;
+        *this -= 1;
+        return value;
+    }
+
+    // These static methods behave like a convenience cast operator targeting
+    // the desired CheckedNumeric type. As an optimization, a reference is
+    // returned when Src is the same type as T.
+    template <typename Src>
+    static CheckedNumeric<T> cast(
+        Src u,
+        typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
+    {
+        return u;
+    }
+
+    template <typename Src>
+    static CheckedNumeric<T> cast(
+        const CheckedNumeric<Src> &u,
+        typename std::enable_if<!std::is_same<Src, T>::value, int>::type = 0)
+    {
+        return u;
+    }
+
+    static const CheckedNumeric<T> &cast(const CheckedNumeric<T> &u) { return u; }
+
+  private:
+    template <typename NumericType>
+    struct UnderlyingType
+    {
+        using type = NumericType;
+    };
+
+    template <typename NumericType>
+    struct UnderlyingType<CheckedNumeric<NumericType>>
+    {
+        using type = NumericType;
+    };
+
+    CheckedNumericState<T> state_;
+};
+
+// This is the boilerplate for the standard arithmetic operator overloads. A
+// macro isn't the prettiest solution, but it beats rewriting these five times.
+// Some details worth noting are:
+//  * We apply the standard arithmetic promotions.
+//  * We skip range checks for floating points.
+//  * We skip range checks for destination integers with sufficient range.
+// TODO(jschuh): extract these out into templates.
+#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP)                                   \
+    /* Binary arithmetic operator for CheckedNumerics of the same type. */                         \
+    template <typename T>                                                                          \
+    CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP(                             \
+        const CheckedNumeric<T> &lhs, const CheckedNumeric<T> &rhs)                                \
+    {                                                                                              \
+        typedef typename ArithmeticPromotion<T>::type Promotion;                                   \
+        /* Floating point always takes the fast path */                                            \
+        if (std::numeric_limits<T>::is_iec559)                                                     \
+            return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe());                      \
+        if (IsIntegerArithmeticSafe<Promotion, T, T>::value)                                       \
+            return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(),               \
+                                             GetRangeConstraint(rhs.validity() | lhs.validity())); \
+        RangeConstraint validity = RANGE_VALID;                                                    \
+        T result =                                                                                 \
+            static_cast<T>(Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()),                \
+                                         static_cast<Promotion>(rhs.ValueUnsafe()), &validity));   \
+        return CheckedNumeric<Promotion>(                                                          \
+            result, GetRangeConstraint(validity | lhs.validity() | rhs.validity()));               \
+    }                                                                                              \
+    /* Assignment arithmetic operator implementation from CheckedNumeric. */                       \
+    template <typename T>                                                                          \
+    template <typename Src>                                                                        \
+    CheckedNumeric<T> &CheckedNumeric<T>::operator COMPOUND_OP(Src rhs)                            \
+    {                                                                                              \
+        *this = CheckedNumeric<T>::cast(*this)                                                     \
+            OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs);                      \
+        return *this;                                                                              \
+    }                                                                                              \
+    /* Binary arithmetic operator for CheckedNumeric of different type. */                         \
+    template <typename T, typename Src>                                                            \
+    CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP(                        \
+        const CheckedNumeric<Src> &lhs, const CheckedNumeric<T> &rhs)                              \
+    {                                                                                              \
+        typedef typename ArithmeticPromotion<T, Src>::type Promotion;                              \
+        if (IsIntegerArithmeticSafe<Promotion, T, Src>::value)                                     \
+            return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(),               \
+                                             GetRangeConstraint(rhs.validity() | lhs.validity())); \
+        return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs);       \
+    }                                                                                              \
+    /* Binary arithmetic operator for left CheckedNumeric and right numeric. */                    \
+    template <typename T, typename Src,                                                            \
+              typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr>           \
+    CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP(                        \
+        const CheckedNumeric<T> &lhs, Src rhs)                                                     \
+    {                                                                                              \
+        typedef typename ArithmeticPromotion<T, Src>::type Promotion;                              \
+        if (IsIntegerArithmeticSafe<Promotion, T, Src>::value)                                     \
+            return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, lhs.validity());            \
+        return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs);       \
+    }                                                                                              \
+    /* Binary arithmetic operator for left numeric and right CheckedNumeric. */                    \
+    template <typename T, typename Src,                                                            \
+              typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr>           \
+    CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP(                        \
+        Src lhs, const CheckedNumeric<T> &rhs)                                                     \
+    {                                                                                              \
+        typedef typename ArithmeticPromotion<T, Src>::type Promotion;                              \
+        if (IsIntegerArithmeticSafe<Promotion, T, Src>::value)                                     \
+            return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), rhs.validity());            \
+        return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs);       \
+    }
+
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=)
+
+#undef BASE_NUMERIC_ARITHMETIC_OPERATORS
+
+}  // namespace internal
+
+using internal::CheckedNumeric;
+
+}  // namespace base
+
+#endif  // BASE_NUMERICS_SAFE_MATH_H_
diff --git a/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_math_impl.h b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_math_impl.h
new file mode 100644
index 0000000..341cdbc
--- /dev/null
+++ b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_math_impl.h
@@ -0,0 +1,570 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_
+#define BASE_NUMERICS_SAFE_MATH_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+
+namespace base
+{
+namespace internal
+{
+
+// Everything from here up to the floating point operations is portable C++,
+// but it may not be fast. This code could be split based on
+// platform/architecture and replaced with potentially faster implementations.
+
+// Integer promotion templates used by the portable checked integer arithmetic.
+template <size_t Size, bool IsSigned>
+struct IntegerForSizeAndSign;
+template <>
+struct IntegerForSizeAndSign<1, true>
+{
+    typedef int8_t type;
+};
+template <>
+struct IntegerForSizeAndSign<1, false>
+{
+    typedef uint8_t type;
+};
+template <>
+struct IntegerForSizeAndSign<2, true>
+{
+    typedef int16_t type;
+};
+template <>
+struct IntegerForSizeAndSign<2, false>
+{
+    typedef uint16_t type;
+};
+template <>
+struct IntegerForSizeAndSign<4, true>
+{
+    typedef int32_t type;
+};
+template <>
+struct IntegerForSizeAndSign<4, false>
+{
+    typedef uint32_t type;
+};
+template <>
+struct IntegerForSizeAndSign<8, true>
+{
+    typedef int64_t type;
+};
+template <>
+struct IntegerForSizeAndSign<8, false>
+{
+    typedef uint64_t type;
+};
+
+// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to
+// support 128-bit math, then the ArithmeticPromotion template below will need
+// to be updated (or more likely replaced with a decltype expression).
+
+template <typename Integer>
+struct UnsignedIntegerForSize
+{
+    typedef
+        typename std::enable_if<std::numeric_limits<Integer>::is_integer,
+                                typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type
+            type;
+};
+
+template <typename Integer>
+struct SignedIntegerForSize
+{
+    typedef
+        typename std::enable_if<std::numeric_limits<Integer>::is_integer,
+                                typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type
+            type;
+};
+
+template <typename Integer>
+struct TwiceWiderInteger
+{
+    typedef typename std::enable_if<
+        std::numeric_limits<Integer>::is_integer,
+        typename IntegerForSizeAndSign<sizeof(Integer) * 2,
+                                       std::numeric_limits<Integer>::is_signed>::type>::type type;
+};
+
+template <typename Integer>
+struct PositionOfSignBit
+{
+    static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, size_t>::type
+        value = CHAR_BIT * sizeof(Integer) - 1;
+};
+
+// This is used for UnsignedAbs, where we need to support floating-point
+// template instantiations even though we don't actually support the operations.
+// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs,
+// so the float versions will not compile.
+template <typename Numeric,
+          bool IsInteger = std::numeric_limits<Numeric>::is_integer,
+          bool IsFloat   = std::numeric_limits<Numeric>::is_iec559>
+struct UnsignedOrFloatForSize;
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, true, false>
+{
+    typedef typename UnsignedIntegerForSize<Numeric>::type type;
+};
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, false, true>
+{
+    typedef Numeric type;
+};
+
+// Helper templates for integer manipulations.
+
+template <typename T>
+constexpr bool HasSignBit(T x)
+{
+    // Cast to unsigned since right shift on signed is undefined.
+    return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >>
+              PositionOfSignBit<T>::value);
+}
+
+// This wrapper undoes the standard integer promotions.
+template <typename T>
+constexpr T BinaryComplement(T x)
+{
+    return static_cast<T>(~x);
+}
+
+// Here are the actual portable checked integer math implementations.
+// TODO(jschuh): Break this code out from the enable_if pattern and find a clean
+// way to coalesce things into the CheckedNumericState specializations below.
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
+CheckedAdd(T x, T y, RangeConstraint *validity)
+{
+    // Since the value of x+y is undefined if we have a signed type, we compute
+    // it using the unsigned type of the same size.
+    typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
+    UnsignedDst ux      = static_cast<UnsignedDst>(x);
+    UnsignedDst uy      = static_cast<UnsignedDst>(y);
+    UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy);
+    // Addition is valid if the sign of (x + y) is equal to either that of x or
+    // that of y.
+    if (std::numeric_limits<T>::is_signed)
+    {
+        if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (uresult ^ uy)))))
+        {
+            *validity = RANGE_VALID;
+        }
+        else
+        {  // Direction of wrap is inverse of result sign.
+            *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
+        }
+    }
+    else
+    {  // Unsigned is either valid or overflow.
+        *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW;
+    }
+    return static_cast<T>(uresult);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
+CheckedSub(T x, T y, RangeConstraint *validity)
+{
+    // Since the value of x+y is undefined if we have a signed type, we compute
+    // it using the unsigned type of the same size.
+    typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
+    UnsignedDst ux      = static_cast<UnsignedDst>(x);
+    UnsignedDst uy      = static_cast<UnsignedDst>(y);
+    UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy);
+    // Subtraction is valid if either x and y have same sign, or (x-y) and x have
+    // the same sign.
+    if (std::numeric_limits<T>::is_signed)
+    {
+        if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (ux ^ uy)))))
+        {
+            *validity = RANGE_VALID;
+        }
+        else
+        {  // Direction of wrap is inverse of result sign.
+            *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
+        }
+    }
+    else
+    {  // Unsigned is either valid or underflow.
+        *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW;
+    }
+    return static_cast<T>(uresult);
+}
+
+// Integer multiplication is a bit complicated. In the fast case we just
+// we just promote to a twice wider type, and range check the result. In the
+// slow case we need to manually check that the result won't be truncated by
+// checking with division against the appropriate bound.
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && sizeof(T) * 2 <= sizeof(uintmax_t),
+                        T>::type
+CheckedMul(T x, T y, RangeConstraint *validity)
+{
+    typedef typename TwiceWiderInteger<T>::type IntermediateType;
+    IntermediateType tmp = static_cast<IntermediateType>(x) * static_cast<IntermediateType>(y);
+    *validity            = DstRangeRelationToSrcRange<T>(tmp);
+    return static_cast<T>(tmp);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed &&
+                            (sizeof(T) * 2 > sizeof(uintmax_t)),
+                        T>::type
+CheckedMul(T x, T y, RangeConstraint *validity)
+{
+    // If either side is zero then the result will be zero.
+    if (!x || !y)
+    {
+        *validity = RANGE_VALID;
+        return static_cast<T>(0);
+    }
+    else if (x > 0)
+    {
+        if (y > 0)
+            *validity = x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW;
+        else
+            *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID : RANGE_UNDERFLOW;
+    }
+    else
+    {
+        if (y > 0)
+            *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID : RANGE_UNDERFLOW;
+        else
+            *validity = y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW;
+    }
+
+    return static_cast<T>(x * y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed &&
+                            (sizeof(T) * 2 > sizeof(uintmax_t)),
+                        T>::type
+CheckedMul(T x, T y, RangeConstraint *validity)
+{
+    *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) ? RANGE_VALID : RANGE_OVERFLOW;
+    return static_cast<T>(x * y);
+}
+
+// Division just requires a check for an invalid negation on signed min/-1.
+template <typename T>
+T CheckedDiv(T x,
+             T y,
+             RangeConstraint *validity,
+             typename std::enable_if<std::numeric_limits<T>::is_integer, int>::type = 0)
+{
+    if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() &&
+        y == static_cast<T>(-1))
+    {
+        *validity = RANGE_OVERFLOW;
+        return std::numeric_limits<T>::min();
+    }
+
+    *validity = RANGE_VALID;
+    return static_cast<T>(x / y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+                        T>::type
+CheckedMod(T x, T y, RangeConstraint *validity)
+{
+    *validity = y > 0 ? RANGE_VALID : RANGE_INVALID;
+    return static_cast<T>(x % y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+                        T>::type
+CheckedMod(T x, T y, RangeConstraint *validity)
+{
+    *validity = RANGE_VALID;
+    return static_cast<T>(x % y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+                        T>::type
+CheckedNeg(T value, RangeConstraint *validity)
+{
+    *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
+    // The negation of signed min is min, so catch that one.
+    return static_cast<T>(-value);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+                        T>::type
+CheckedNeg(T value, RangeConstraint *validity)
+{
+    // The only legal unsigned negation is zero.
+    *validity = value ? RANGE_UNDERFLOW : RANGE_VALID;
+    return static_cast<T>(-static_cast<typename SignedIntegerForSize<T>::type>(value));
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+                        T>::type
+CheckedAbs(T value, RangeConstraint *validity)
+{
+    *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
+    return static_cast<T>(std::abs(value));
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+                        T>::type
+CheckedAbs(T value, RangeConstraint *validity)
+{
+    // T is unsigned, so |value| must already be positive.
+    *validity = RANGE_VALID;
+    return value;
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+                        typename UnsignedIntegerForSize<T>::type>::type
+CheckedUnsignedAbs(T value)
+{
+    typedef typename UnsignedIntegerForSize<T>::type UnsignedT;
+    return value == std::numeric_limits<T>::min()
+               ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1
+               : static_cast<UnsignedT>(std::abs(value));
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+                        T>::type
+CheckedUnsignedAbs(T value)
+{
+    // T is unsigned, so |value| must already be positive.
+    return static_cast<T>(value);
+}
+
+// These are the floating point stubs that the compiler needs to see. Only the
+// negation operation is ever called.
+#define BASE_FLOAT_ARITHMETIC_STUBS(NAME)                                              \
+    template <typename T>                                                              \
+    typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type Checked##NAME( \
+        T, T, RangeConstraint *)                                                       \
+    {                                                                                  \
+        NOTREACHED();                                                                  \
+        return static_cast<T>(0);                                                      \
+    }
+
+BASE_FLOAT_ARITHMETIC_STUBS(Add)
+BASE_FLOAT_ARITHMETIC_STUBS(Sub)
+BASE_FLOAT_ARITHMETIC_STUBS(Mul)
+BASE_FLOAT_ARITHMETIC_STUBS(Div)
+BASE_FLOAT_ARITHMETIC_STUBS(Mod)
+
+#undef BASE_FLOAT_ARITHMETIC_STUBS
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedNeg(T value,
+                                                                               RangeConstraint *)
+{
+    return static_cast<T>(-value);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedAbs(T value,
+                                                                               RangeConstraint *)
+{
+    return static_cast<T>(std::abs(value));
+}
+
+// Floats carry around their validity state with them, but integers do not. So,
+// we wrap the underlying value in a specialization in order to hide that detail
+// and expose an interface via accessors.
+enum NumericRepresentation
+{
+    NUMERIC_INTEGER,
+    NUMERIC_FLOATING,
+    NUMERIC_UNKNOWN
+};
+
+template <typename NumericType>
+struct GetNumericRepresentation
+{
+    static const NumericRepresentation value =
+        std::numeric_limits<NumericType>::is_integer
+            ? NUMERIC_INTEGER
+            : (std::numeric_limits<NumericType>::is_iec559 ? NUMERIC_FLOATING : NUMERIC_UNKNOWN);
+};
+
+template <typename T, NumericRepresentation type = GetNumericRepresentation<T>::value>
+class CheckedNumericState
+{
+};
+
+// Integrals require quite a bit of additional housekeeping to manage state.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_INTEGER>
+{
+  private:
+    T value_;
+    RangeConstraint validity_ : CHAR_BIT;  // Actually requires only two bits.
+
+  public:
+    template <typename Src, NumericRepresentation type>
+    friend class CheckedNumericState;
+
+    CheckedNumericState() : value_(0), validity_(RANGE_VALID) {}
+
+    template <typename Src>
+    CheckedNumericState(Src value, RangeConstraint validity)
+        : value_(static_cast<T>(value)),
+          validity_(GetRangeConstraint(validity | DstRangeRelationToSrcRange<T>(value)))
+    {
+        static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+    }
+
+    // Copy constructor.
+    template <typename Src>
+    CheckedNumericState(const CheckedNumericState<Src> &rhs)
+        : value_(static_cast<T>(rhs.value())),
+          validity_(GetRangeConstraint(rhs.validity() | DstRangeRelationToSrcRange<T>(rhs.value())))
+    {
+    }
+
+    template <typename Src>
+    explicit CheckedNumericState(
+        Src value,
+        typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
+        : value_(static_cast<T>(value)), validity_(DstRangeRelationToSrcRange<T>(value))
+    {
+    }
+
+    RangeConstraint validity() const { return validity_; }
+    T value() const { return value_; }
+};
+
+// Floating points maintain their own validity, but need translation wrappers.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_FLOATING>
+{
+  private:
+    T value_;
+
+  public:
+    template <typename Src, NumericRepresentation type>
+    friend class CheckedNumericState;
+
+    CheckedNumericState() : value_(0.0) {}
+
+    template <typename Src>
+    CheckedNumericState(
+        Src value,
+        RangeConstraint validity,
+        typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type = 0)
+    {
+        switch (DstRangeRelationToSrcRange<T>(value))
+        {
+            case RANGE_VALID:
+                value_ = static_cast<T>(value);
+                break;
+
+            case RANGE_UNDERFLOW:
+                value_ = -std::numeric_limits<T>::infinity();
+                break;
+
+            case RANGE_OVERFLOW:
+                value_ = std::numeric_limits<T>::infinity();
+                break;
+
+            case RANGE_INVALID:
+                value_ = std::numeric_limits<T>::quiet_NaN();
+                break;
+
+            default:
+                NOTREACHED();
+        }
+    }
+
+    template <typename Src>
+    explicit CheckedNumericState(
+        Src value,
+        typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
+        : value_(static_cast<T>(value))
+    {
+    }
+
+    // Copy constructor.
+    template <typename Src>
+    CheckedNumericState(const CheckedNumericState<Src> &rhs) : value_(static_cast<T>(rhs.value()))
+    {
+    }
+
+    RangeConstraint validity() const
+    {
+        return GetRangeConstraint(value_ <= std::numeric_limits<T>::max(),
+                                  value_ >= -std::numeric_limits<T>::max());
+    }
+    T value() const { return value_; }
+};
+
+// For integers less than 128-bit and floats 32-bit or larger, we have the type
+// with the larger maximum exponent take precedence.
+enum ArithmeticPromotionCategory
+{
+    LEFT_PROMOTION,
+    RIGHT_PROMOTION
+};
+
+template <typename Lhs,
+          typename Rhs = Lhs,
+          ArithmeticPromotionCategory Promotion =
+              (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value) ? LEFT_PROMOTION
+                                                                  : RIGHT_PROMOTION>
+struct ArithmeticPromotion;
+
+template <typename Lhs, typename Rhs>
+struct ArithmeticPromotion<Lhs, Rhs, LEFT_PROMOTION>
+{
+    typedef Lhs type;
+};
+
+template <typename Lhs, typename Rhs>
+struct ArithmeticPromotion<Lhs, Rhs, RIGHT_PROMOTION>
+{
+    typedef Rhs type;
+};
+
+// We can statically check if operations on the provided types can wrap, so we
+// can skip the checked operations if they're not needed. So, for an integer we
+// care if the destination type preserves the sign and is twice the width of
+// the source.
+template <typename T, typename Lhs, typename Rhs>
+struct IsIntegerArithmeticSafe
+{
+    static const bool value =
+        !std::numeric_limits<T>::is_iec559 &&
+        StaticDstRangeRelationToSrcRange<T, Lhs>::value == NUMERIC_RANGE_CONTAINED &&
+        sizeof(T) >= (2 * sizeof(Lhs)) &&
+        StaticDstRangeRelationToSrcRange<T, Rhs>::value != NUMERIC_RANGE_CONTAINED &&
+        sizeof(T) >= (2 * sizeof(Rhs));
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_SAFE_MATH_IMPL_H_
diff --git a/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_numerics_unittest.cc b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_numerics_unittest.cc
new file mode 100644
index 0000000..052d850
--- /dev/null
+++ b/src/third_party/angle/src/common/third_party/numerics/base/numerics/safe_numerics_unittest.cc
@@ -0,0 +1,771 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/compiler_specific.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/numerics/safe_math.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
+#include <mmintrin.h>
+#endif
+
+using std::numeric_limits;
+using base::CheckedNumeric;
+using base::checked_cast;
+using base::IsValueInRangeForNumericType;
+using base::IsValueNegative;
+using base::SizeT;
+using base::StrictNumeric;
+using base::saturated_cast;
+using base::strict_cast;
+using base::internal::MaxExponent;
+using base::internal::RANGE_VALID;
+using base::internal::RANGE_INVALID;
+using base::internal::RANGE_OVERFLOW;
+using base::internal::RANGE_UNDERFLOW;
+using base::internal::SignedIntegerForSize;
+
+// These tests deliberately cause arithmetic overflows. If the compiler is
+// aggressive enough, it can const fold these overflows. Disable warnings about
+// overflows for const expressions.
+#if defined(OS_WIN)
+#pragma warning(disable : 4756)
+#endif
+
+// This is a helper function for finding the maximum value in Src that can be
+// wholy represented as the destination floating-point type.
+template <typename Dst, typename Src>
+Dst GetMaxConvertibleToFloat()
+{
+    typedef numeric_limits<Dst> DstLimits;
+    typedef numeric_limits<Src> SrcLimits;
+    static_assert(SrcLimits::is_specialized, "Source must be numeric.");
+    static_assert(DstLimits::is_specialized, "Destination must be numeric.");
+    CHECK(DstLimits::is_iec559);
+
+    if (SrcLimits::digits <= DstLimits::digits &&
+        MaxExponent<Src>::value <= MaxExponent<Dst>::value)
+        return SrcLimits::max();
+    Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
+    while (max != static_cast<Src>(static_cast<Dst>(max)))
+    {
+        max /= 2;
+    }
+    return static_cast<Dst>(max);
+}
+
+// Helper macros to wrap displaying the conversion types and line numbers.
+#define TEST_EXPECTED_VALIDITY(expected, actual)                                            \
+    EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).IsValid())                              \
+        << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst << " on line " \
+        << line;
+
+#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
+#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
+
+#define TEST_EXPECTED_VALUE(expected, actual)                                                 \
+    EXPECT_EQ(static_cast<Dst>(expected), CheckedNumeric<Dst>(actual).ValueUnsafe())          \
+        << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst << " on line " \
+        << line;
+
+// Signed integer arithmetic.
+template <typename Dst>
+static void TestSpecializedArithmetic(
+    const char *dst,
+    int line,
+    typename std::enable_if<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed,
+                            int>::type = 0)
+{
+    typedef numeric_limits<Dst> DstLimits;
+    TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min()));
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()).Abs());
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
+
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
+
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) - -1);
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
+
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) * 2);
+
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) / -1);
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
+
+    // Modulus is legal only for integers.
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+    TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
+    // Test all the different modulus combinations.
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+    CheckedNumeric<Dst> checked_dst = 1;
+    TEST_EXPECTED_VALUE(0, checked_dst %= 1);
+}
+
+// Unsigned integer arithmetic.
+template <typename Dst>
+static void TestSpecializedArithmetic(
+    const char *dst,
+    int line,
+    typename std::enable_if<numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed,
+                            int>::type = 0)
+{
+    typedef numeric_limits<Dst> DstLimits;
+    TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2);
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).UnsignedAbs());
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<typename SignedIntegerForSize<Dst>::type>(
+                              std::numeric_limits<typename SignedIntegerForSize<Dst>::type>::min())
+                              .UnsignedAbs());
+
+    // Modulus is legal only for integers.
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
+    // Test all the different modulus combinations.
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+    CheckedNumeric<Dst> checked_dst = 1;
+    TEST_EXPECTED_VALUE(0, checked_dst %= 1);
+}
+
+// Floating point arithmetic.
+template <typename Dst>
+void TestSpecializedArithmetic(
+    const char *dst,
+    int line,
+    typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0)
+{
+    typedef numeric_limits<Dst> DstLimits;
+    TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
+
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
+
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1);
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
+
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
+
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2);
+
+    TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
+    EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
+}
+
+// Generic arithmetic tests.
+template <typename Dst>
+static void TestArithmetic(const char *dst, int line)
+{
+    typedef numeric_limits<Dst> DstLimits;
+
+    EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
+    EXPECT_EQ(
+        false,
+        CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max()).IsValid());
+    EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
+    EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
+    EXPECT_EQ(static_cast<Dst>(1),
+              CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max())
+                  .ValueOrDefault(1));
+
+    // Test the operator combinations.
+    TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
+    CheckedNumeric<Dst> checked_dst = 1;
+    TEST_EXPECTED_VALUE(2, checked_dst += 1);
+    checked_dst = 1;
+    TEST_EXPECTED_VALUE(0, checked_dst -= 1);
+    checked_dst = 1;
+    TEST_EXPECTED_VALUE(1, checked_dst *= 1);
+    checked_dst = 1;
+    TEST_EXPECTED_VALUE(1, checked_dst /= 1);
+
+    // Generic negation.
+    TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
+    TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
+    TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
+    TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
+                        -CheckedNumeric<Dst>(DstLimits::max()));
+
+    // Generic absolute value.
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
+    TEST_EXPECTED_VALUE(DstLimits::max(), CheckedNumeric<Dst>(DstLimits::max()).Abs());
+
+    // Generic addition.
+    TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
+    TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
+    TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + 1);
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
+
+    // Generic subtraction.
+    TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
+    TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
+    TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
+    TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
+
+    // Generic multiplication.
+    TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
+    TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
+    TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
+    TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
+    TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
+    TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
+    TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
+
+    // Generic division.
+    TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
+    TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
+    TEST_EXPECTED_VALUE(DstLimits::min() / 2, CheckedNumeric<Dst>(DstLimits::min()) / 2);
+    TEST_EXPECTED_VALUE(DstLimits::max() / 2, CheckedNumeric<Dst>(DstLimits::max()) / 2);
+
+    TestSpecializedArithmetic<Dst>(dst, line);
+}
+
+// Helper macro to wrap displaying the conversion types and line numbers.
+#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
+
+TEST(SafeNumerics, SignedIntegerMath)
+{
+    TEST_ARITHMETIC(int8_t);
+    TEST_ARITHMETIC(int);
+    TEST_ARITHMETIC(intptr_t);
+    TEST_ARITHMETIC(intmax_t);
+}
+
+TEST(SafeNumerics, UnsignedIntegerMath)
+{
+    TEST_ARITHMETIC(uint8_t);
+    TEST_ARITHMETIC(unsigned int);
+    TEST_ARITHMETIC(uintptr_t);
+    TEST_ARITHMETIC(uintmax_t);
+}
+
+TEST(SafeNumerics, FloatingPointMath)
+{
+    TEST_ARITHMETIC(float);
+    TEST_ARITHMETIC(double);
+}
+
+// Enumerates the five different conversions types we need to test.
+enum NumericConversionType
+{
+    SIGN_PRESERVING_VALUE_PRESERVING,
+    SIGN_PRESERVING_NARROW,
+    SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
+    SIGN_TO_UNSIGN_NARROW,
+    UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
+};
+
+// Template covering the different conversion tests.
+template <typename Dst, typename Src, NumericConversionType conversion>
+struct TestNumericConversion
+{
+};
+
+// EXPECT_EQ wrappers providing specific detail on test failures.
+#define TEST_EXPECTED_RANGE(expected, actual)                                                \
+    EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual))             \
+        << "Conversion test: " << src << " value " << actual << " to " << dst << " on line " \
+        << line;
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING>
+{
+    static void Test(const char *dst, const char *src, int line)
+    {
+        typedef numeric_limits<Src> SrcLimits;
+        typedef numeric_limits<Dst> DstLimits;
+        // Integral to floating.
+        static_assert(
+            (DstLimits::is_iec559 && SrcLimits::is_integer) ||
+                // Not floating to integral and...
+                (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
+                 // Same sign, same numeric, source is narrower or same.
+                 ((SrcLimits::is_signed == DstLimits::is_signed && sizeof(Dst) >= sizeof(Src)) ||
+                  // Or signed destination and source is smaller
+                  (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
+            "Comparison must be sign preserving and value preserving");
+
+        const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
+        TEST_EXPECTED_SUCCESS(checked_dst);
+        if (MaxExponent<Dst>::value > MaxExponent<Src>::value)
+        {
+            if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1)
+            {
+                // At least twice larger type.
+                TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
+            }
+            else
+            {  // Larger, but not at least twice as large.
+                TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
+                TEST_EXPECTED_SUCCESS(checked_dst + 1);
+            }
+        }
+        else
+        {  // Same width type.
+            TEST_EXPECTED_FAILURE(checked_dst + 1);
+        }
+
+        TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
+        TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+        if (SrcLimits::is_iec559)
+        {
+            TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
+            TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
+            TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
+            TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+        }
+        else if (numeric_limits<Src>::is_signed)
+        {
+            TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
+            TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
+        }
+    }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW>
+{
+    static void Test(const char *dst, const char *src, int line)
+    {
+        typedef numeric_limits<Src> SrcLimits;
+        typedef numeric_limits<Dst> DstLimits;
+        static_assert(SrcLimits::is_signed == DstLimits::is_signed,
+                      "Destination and source sign must be the same");
+        static_assert(sizeof(Dst) < sizeof(Src) || (DstLimits::is_integer && SrcLimits::is_iec559),
+                      "Destination must be narrower than source");
+
+        const CheckedNumeric<Dst> checked_dst;
+        TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
+        TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+        TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
+
+        TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
+        TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+        if (SrcLimits::is_iec559)
+        {
+            TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
+            TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
+            TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
+            TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
+            TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+            if (DstLimits::is_integer)
+            {
+                if (SrcLimits::digits < DstLimits::digits)
+                {
+                    TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
+                }
+                else
+                {
+                    TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
+                }
+                TEST_EXPECTED_RANGE(RANGE_VALID,
+                                    static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
+                TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
+            }
+        }
+        else if (SrcLimits::is_signed)
+        {
+            TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
+            TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
+            TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
+        }
+        else
+        {
+            TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
+            TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
+        }
+    }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL>
+{
+    static void Test(const char *dst, const char *src, int line)
+    {
+        typedef numeric_limits<Src> SrcLimits;
+        typedef numeric_limits<Dst> DstLimits;
+        static_assert(sizeof(Dst) >= sizeof(Src),
+                      "Destination must be equal or wider than source.");
+        static_assert(SrcLimits::is_signed, "Source must be signed");
+        static_assert(!DstLimits::is_signed, "Destination must be unsigned");
+
+        const CheckedNumeric<Dst> checked_dst;
+        TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
+        TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
+        TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
+
+        TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
+        TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
+        TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+        TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
+    }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW>
+{
+    static void Test(const char *dst, const char *src, int line)
+    {
+        typedef numeric_limits<Src> SrcLimits;
+        typedef numeric_limits<Dst> DstLimits;
+        static_assert(
+            (DstLimits::is_integer && SrcLimits::is_iec559) || (sizeof(Dst) < sizeof(Src)),
+            "Destination must be narrower than source.");
+        static_assert(SrcLimits::is_signed, "Source must be signed.");
+        static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
+
+        const CheckedNumeric<Dst> checked_dst;
+        TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+        TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
+        TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
+        TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
+
+        TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
+        TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+        TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
+        if (SrcLimits::is_iec559)
+        {
+            TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
+            TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
+            TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
+            TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+            if (DstLimits::is_integer)
+            {
+                if (SrcLimits::digits < DstLimits::digits)
+                {
+                    TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
+                }
+                else
+                {
+                    TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
+                }
+                TEST_EXPECTED_RANGE(RANGE_VALID,
+                                    static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
+                TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
+            }
+        }
+        else
+        {
+            TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
+        }
+    }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL>
+{
+    static void Test(const char *dst, const char *src, int line)
+    {
+        typedef numeric_limits<Src> SrcLimits;
+        typedef numeric_limits<Dst> DstLimits;
+        static_assert(sizeof(Dst) <= sizeof(Src),
+                      "Destination must be narrower or equal to source.");
+        static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
+        static_assert(DstLimits::is_signed, "Destination must be signed.");
+
+        const CheckedNumeric<Dst> checked_dst;
+        TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+        TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
+        TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
+
+        TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
+        TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
+        TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+    }
+};
+
+// Helper macro to wrap displaying the conversion types and line numbers
+#define TEST_NUMERIC_CONVERSION(d, s, t) TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
+
+TEST(SafeNumerics, IntMinOperations)
+{
+    TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+
+    TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
+    TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
+    TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
+
+    TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+
+    TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
+    TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
+    TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
+
+    TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+    TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, IntOperations)
+{
+    TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(unsigned int, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(unsigned int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+
+    TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
+    TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
+    TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
+    TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
+
+    TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+    TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+
+    TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
+    TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
+    TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
+
+    TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+    TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, IntMaxOperations)
+{
+    TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(intmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+
+    TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
+    TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
+
+    TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+    TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+
+    TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
+    TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
+
+    TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, FloatOperations)
+{
+    TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(float, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+
+    TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
+}
+
+TEST(SafeNumerics, DoubleOperations)
+{
+    TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
+    TEST_NUMERIC_CONVERSION(double, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+}
+
+TEST(SafeNumerics, SizeTOperations)
+{
+    TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+    TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, CastTests)
+{
+// MSVC catches and warns that we're forcing saturation in these tests.
+// Since that's intentional, we need to shut this warning off.
+#if defined(COMPILER_MSVC)
+#pragma warning(disable : 4756)
+#endif
+
+    int small_positive      = 1;
+    int small_negative      = -1;
+    double double_small     = 1.0;
+    double double_large     = numeric_limits<double>::max();
+    double double_infinity  = numeric_limits<float>::infinity();
+    double double_large_int = numeric_limits<int>::max();
+    double double_small_int = numeric_limits<int>::min();
+
+    // Just test that the casts compile, since the other tests cover logic.
+    EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
+    EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
+    EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
+    EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
+    EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
+    EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
+    EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
+
+    EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
+    EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
+    EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
+
+    EXPECT_TRUE(IsValueNegative(-1));
+    EXPECT_TRUE(IsValueNegative(numeric_limits<int>::min()));
+    EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::min()));
+    EXPECT_TRUE(IsValueNegative(-numeric_limits<double>::max()));
+    EXPECT_FALSE(IsValueNegative(0));
+    EXPECT_FALSE(IsValueNegative(1));
+    EXPECT_FALSE(IsValueNegative(0u));
+    EXPECT_FALSE(IsValueNegative(1u));
+    EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
+    EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
+    EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
+
+    // These casts and coercions will fail to compile:
+    // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
+    // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
+    // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
+    // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
+
+    // Test various saturation corner cases.
+    EXPECT_EQ(saturated_cast<int>(small_negative), static_cast<int>(small_negative));
+    EXPECT_EQ(saturated_cast<int>(small_positive), static_cast<int>(small_positive));
+    EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
+    EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
+    EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
+    EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
+    EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
+    EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int));
+    EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
+
+    float not_a_number =
+        std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
+    EXPECT_TRUE(std::isnan(not_a_number));
+    EXPECT_EQ(0, saturated_cast<int>(not_a_number));
+}
+
+#if GTEST_HAS_DEATH_TEST
+
+TEST(SafeNumerics, SaturatedCastChecks)
+{
+    float not_a_number =
+        std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
+    EXPECT_TRUE(std::isnan(not_a_number));
+    EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>(not_a_number)), "");
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+TEST(SafeNumerics, IsValueInRangeForNumericType)
+{
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
+    EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
+    EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
+    EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
+    EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int32_t>::min()));
+    EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int64_t>::min()));
+
+    EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
+    EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
+    EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
+    EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
+    EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
+    EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int32_t>::min()));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
+        static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
+    EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
+        static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1));
+    EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int64_t>::min()));
+
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
+    EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
+    EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
+    EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int32_t>::min()));
+    EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
+    EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int64_t>::min()));
+
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
+    EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
+    EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int32_t>::min()));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
+        static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
+    EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int64_t>::min()));
+}
+
+TEST(SafeNumerics, CompoundNumericOperations)
+{
+    CheckedNumeric<int> a = 1;
+    CheckedNumeric<int> b = 2;
+    CheckedNumeric<int> c = 3;
+    CheckedNumeric<int> d = 4;
+    a += b;
+    EXPECT_EQ(3, a.ValueOrDie());
+    a -= c;
+    EXPECT_EQ(0, a.ValueOrDie());
+    d /= b;
+    EXPECT_EQ(2, d.ValueOrDie());
+    d *= d;
+    EXPECT_EQ(4, d.ValueOrDie());
+
+    CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
+    EXPECT_TRUE(too_large.IsValid());
+    too_large += d;
+    EXPECT_FALSE(too_large.IsValid());
+    too_large -= d;
+    EXPECT_FALSE(too_large.IsValid());
+    too_large /= d;
+    EXPECT_FALSE(too_large.IsValid());
+}
diff --git a/src/third_party/angle/src/common/tls.cpp b/src/third_party/angle/src/common/tls.cpp
new file mode 100644
index 0000000..10a1025
--- /dev/null
+++ b/src/third_party/angle/src/common/tls.cpp
@@ -0,0 +1,156 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// tls.cpp: Simple cross-platform interface for thread local storage.
+
+#include "common/tls.h"
+
+#include <assert.h>
+
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+#include <vector>
+#include <set>
+#include <map>
+#include <mutex>
+
+#include <wrl/client.h>
+#include <wrl/async.h>
+#include <Windows.System.Threading.h>
+
+using namespace std;
+using namespace Windows::Foundation;
+using namespace ABI::Windows::System::Threading;
+
+// Thread local storage for Windows Store support
+typedef vector<void*> ThreadLocalData;
+
+static __declspec(thread) ThreadLocalData* currentThreadData = nullptr;
+static set<ThreadLocalData*> allThreadData;
+static DWORD nextTlsIndex = 0;
+static vector<DWORD> freeTlsIndices;
+
+#endif
+
+TLSIndex CreateTLSIndex()
+{
+    TLSIndex index;
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    if (!freeTlsIndices.empty())
+    {
+        DWORD result = freeTlsIndices.back();
+        freeTlsIndices.pop_back();
+        index = result;
+    }
+    else
+    {
+        index = nextTlsIndex++;
+    }
+#else
+    index = TlsAlloc();
+#endif
+
+#elif defined(ANGLE_PLATFORM_POSIX)
+    // Create global pool key
+    if ((pthread_key_create(&index, nullptr)) != 0)
+    {
+        index = TLS_INVALID_INDEX;
+    }
+#endif
+
+    assert(index != TLS_INVALID_INDEX && "CreateTLSIndex(): Unable to allocate Thread Local Storage");
+    return index;
+}
+
+bool DestroyTLSIndex(TLSIndex index)
+{
+    assert(index != TLS_INVALID_INDEX && "DestroyTLSIndex(): Invalid TLS Index");
+    if (index == TLS_INVALID_INDEX)
+    {
+        return false;
+    }
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    assert(index < nextTlsIndex);
+    assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end());
+
+    freeTlsIndices.push_back(index);
+    for (auto threadData : allThreadData)
+    {
+        if (threadData->size() > index)
+        {
+            threadData->at(index) = nullptr;
+        }
+    }
+    return true;
+#else
+    return (TlsFree(index) == TRUE);
+#endif
+#elif defined(ANGLE_PLATFORM_POSIX)
+    return (pthread_key_delete(index) == 0);
+#endif
+}
+
+bool SetTLSValue(TLSIndex index, void *value)
+{
+    assert(index != TLS_INVALID_INDEX && "SetTLSValue(): Invalid TLS Index");
+    if (index == TLS_INVALID_INDEX)
+    {
+        return false;
+    }
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    ThreadLocalData* threadData = currentThreadData;
+    if (!threadData)
+    {
+        threadData = new ThreadLocalData(index + 1, nullptr);
+        allThreadData.insert(threadData);
+        currentThreadData = threadData;
+    }
+    else if (threadData->size() <= index)
+    {
+        threadData->resize(index + 1, nullptr);
+    }
+
+    threadData->at(index) = value;
+    return true;
+#else
+    return (TlsSetValue(index, value) == TRUE);
+#endif
+#elif defined(ANGLE_PLATFORM_POSIX)
+    return (pthread_setspecific(index, value) == 0);
+#endif
+}
+
+void *GetTLSValue(TLSIndex index)
+{
+    assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index");
+    if (index == TLS_INVALID_INDEX)
+    {
+        return nullptr;
+    }
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    ThreadLocalData* threadData = currentThreadData;
+    if (threadData && threadData->size() > index)
+    {
+        return threadData->at(index);
+    }
+    else
+    {
+        return nullptr;
+    }
+#else
+    return TlsGetValue(index);
+#endif
+#elif defined(ANGLE_PLATFORM_POSIX)
+    return pthread_getspecific(index);
+#endif
+}
diff --git a/src/third_party/angle/src/common/tls.h b/src/third_party/angle/src/common/tls.h
new file mode 100644
index 0000000..ca9e07a
--- /dev/null
+++ b/src/third_party/angle/src/common/tls.h
@@ -0,0 +1,46 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// tls.h: Simple cross-platform interface for thread local storage.
+
+#ifndef COMMON_TLS_H_
+#define COMMON_TLS_H_
+
+#include "common/platform.h"
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+
+// TLS does not exist for Windows Store and needs to be emulated
+#   ifdef ANGLE_ENABLE_WINDOWS_STORE
+#       ifndef TLS_OUT_OF_INDEXES
+#           define TLS_OUT_OF_INDEXES static_cast<DWORD>(0xFFFFFFFF)
+#       endif
+#       ifndef CREATE_SUSPENDED
+#           define CREATE_SUSPENDED 0x00000004
+#       endif
+#   endif
+    typedef DWORD TLSIndex;
+#   define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES)
+#elif defined(ANGLE_PLATFORM_POSIX)
+#   include <pthread.h>
+#   include <semaphore.h>
+#   include <errno.h>
+    typedef pthread_key_t TLSIndex;
+#   define TLS_INVALID_INDEX (static_cast<TLSIndex>(-1))
+#else
+#   error Unsupported platform.
+#endif
+
+// TODO(kbr): for POSIX platforms this will have to be changed to take
+// in a destructor function pointer, to allow the thread-local storage
+// to be properly deallocated upon thread exit.
+TLSIndex CreateTLSIndex();
+bool DestroyTLSIndex(TLSIndex index);
+
+bool SetTLSValue(TLSIndex index, void *value);
+void *GetTLSValue(TLSIndex index);
+
+#endif // COMMON_TLS_H_
diff --git a/src/third_party/angle/src/common/utilities.cpp b/src/third_party/angle/src/common/utilities.cpp
new file mode 100644
index 0000000..b03aada
--- /dev/null
+++ b/src/third_party/angle/src/common/utilities.cpp
@@ -0,0 +1,934 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// utilities.cpp: Conversion functions and other utility routines.
+
+#include "common/utilities.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+
+#include <set>
+
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+#  include <wrl.h>
+#  include <wrl/wrappers/corewrappers.h>
+#  include <windows.applicationmodel.core.h>
+#  include <windows.graphics.display.h>
+#endif
+
+namespace
+{
+
+template <class IndexType>
+gl::IndexRange ComputeTypedIndexRange(const IndexType *indices,
+                                      size_t count,
+                                      bool primitiveRestartEnabled,
+                                      GLuint primitiveRestartIndex)
+{
+    ASSERT(count > 0);
+
+    IndexType minIndex                = 0;
+    IndexType maxIndex                = 0;
+    size_t nonPrimitiveRestartIndices = 0;
+
+    if (primitiveRestartEnabled)
+    {
+        // Find the first non-primitive restart index to initialize the min and max values
+        size_t i = 0;
+        for (; i < count; i++)
+        {
+            if (indices[i] != primitiveRestartIndex)
+            {
+                minIndex = indices[i];
+                maxIndex = indices[i];
+                nonPrimitiveRestartIndices++;
+                break;
+            }
+        }
+
+        // Loop over the rest of the indices
+        for (; i < count; i++)
+        {
+            if (indices[i] != primitiveRestartIndex)
+            {
+                if (minIndex > indices[i])
+                {
+                    minIndex = indices[i];
+                }
+                if (maxIndex < indices[i])
+                {
+                    maxIndex = indices[i];
+                }
+                nonPrimitiveRestartIndices++;
+            }
+        }
+    }
+    else
+    {
+        minIndex                   = indices[0];
+        maxIndex                   = indices[0];
+        nonPrimitiveRestartIndices = count;
+
+        for (size_t i = 1; i < count; i++)
+        {
+            if (minIndex > indices[i])
+            {
+                minIndex = indices[i];
+            }
+            if (maxIndex < indices[i])
+            {
+                maxIndex = indices[i];
+            }
+        }
+    }
+
+    return gl::IndexRange(static_cast<size_t>(minIndex), static_cast<size_t>(maxIndex),
+                          nonPrimitiveRestartIndices);
+}
+
+}  // anonymous namespace
+
+namespace gl
+{
+
+int VariableComponentCount(GLenum type)
+{
+    return VariableRowCount(type) * VariableColumnCount(type);
+}
+
+GLenum VariableComponentType(GLenum type)
+{
+    switch(type)
+    {
+      case GL_BOOL:
+      case GL_BOOL_VEC2:
+      case GL_BOOL_VEC3:
+      case GL_BOOL_VEC4:
+        return GL_BOOL;
+      case GL_FLOAT:
+      case GL_FLOAT_VEC2:
+      case GL_FLOAT_VEC3:
+      case GL_FLOAT_VEC4:
+      case GL_FLOAT_MAT2:
+      case GL_FLOAT_MAT3:
+      case GL_FLOAT_MAT4:
+      case GL_FLOAT_MAT2x3:
+      case GL_FLOAT_MAT3x2:
+      case GL_FLOAT_MAT2x4:
+      case GL_FLOAT_MAT4x2:
+      case GL_FLOAT_MAT3x4:
+      case GL_FLOAT_MAT4x3:
+        return GL_FLOAT;
+      case GL_INT:
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_3D:
+      case GL_SAMPLER_CUBE:
+      case GL_SAMPLER_2D_ARRAY:
+      case GL_SAMPLER_EXTERNAL_OES:
+      case GL_SAMPLER_2D_MULTISAMPLE:
+      case GL_INT_SAMPLER_2D:
+      case GL_INT_SAMPLER_3D:
+      case GL_INT_SAMPLER_CUBE:
+      case GL_INT_SAMPLER_2D_ARRAY:
+      case GL_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_SAMPLER_2D_SHADOW:
+      case GL_SAMPLER_CUBE_SHADOW:
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+      case GL_INT_VEC2:
+      case GL_INT_VEC3:
+      case GL_INT_VEC4:
+      case GL_IMAGE_2D:
+      case GL_INT_IMAGE_2D:
+      case GL_UNSIGNED_INT_IMAGE_2D:
+      case GL_IMAGE_3D:
+      case GL_INT_IMAGE_3D:
+      case GL_UNSIGNED_INT_IMAGE_3D:
+      case GL_IMAGE_2D_ARRAY:
+      case GL_INT_IMAGE_2D_ARRAY:
+      case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+      case GL_IMAGE_CUBE:
+      case GL_INT_IMAGE_CUBE:
+      case GL_UNSIGNED_INT_IMAGE_CUBE:
+          return GL_INT;
+      case GL_UNSIGNED_INT:
+      case GL_UNSIGNED_INT_VEC2:
+      case GL_UNSIGNED_INT_VEC3:
+      case GL_UNSIGNED_INT_VEC4:
+        return GL_UNSIGNED_INT;
+      default:
+        UNREACHABLE();
+    }
+
+    return GL_NONE;
+}
+
+size_t VariableComponentSize(GLenum type)
+{
+    switch(type)
+    {
+      case GL_BOOL:         return sizeof(GLint);
+      case GL_FLOAT:        return sizeof(GLfloat);
+      case GL_INT:          return sizeof(GLint);
+      case GL_UNSIGNED_INT: return sizeof(GLuint);
+      default:       UNREACHABLE();
+    }
+
+    return 0;
+}
+
+size_t VariableInternalSize(GLenum type)
+{
+    // Expanded to 4-element vectors
+    return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4;
+}
+
+size_t VariableExternalSize(GLenum type)
+{
+    return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type);
+}
+
+GLenum VariableBoolVectorType(GLenum type)
+{
+    switch (type)
+    {
+      case GL_FLOAT:
+      case GL_INT:
+      case GL_UNSIGNED_INT:
+        return GL_BOOL;
+      case GL_FLOAT_VEC2:
+      case GL_INT_VEC2:
+      case GL_UNSIGNED_INT_VEC2:
+        return GL_BOOL_VEC2;
+      case GL_FLOAT_VEC3:
+      case GL_INT_VEC3:
+      case GL_UNSIGNED_INT_VEC3:
+        return GL_BOOL_VEC3;
+      case GL_FLOAT_VEC4:
+      case GL_INT_VEC4:
+      case GL_UNSIGNED_INT_VEC4:
+        return GL_BOOL_VEC4;
+
+      default:
+        UNREACHABLE();
+        return GL_NONE;
+    }
+}
+
+int VariableRowCount(GLenum type)
+{
+    switch (type)
+    {
+      case GL_NONE:
+      case GL_STRUCT_ANGLEX:
+        return 0;
+      case GL_BOOL:
+      case GL_FLOAT:
+      case GL_INT:
+      case GL_UNSIGNED_INT:
+      case GL_BOOL_VEC2:
+      case GL_FLOAT_VEC2:
+      case GL_INT_VEC2:
+      case GL_UNSIGNED_INT_VEC2:
+      case GL_BOOL_VEC3:
+      case GL_FLOAT_VEC3:
+      case GL_INT_VEC3:
+      case GL_UNSIGNED_INT_VEC3:
+      case GL_BOOL_VEC4:
+      case GL_FLOAT_VEC4:
+      case GL_INT_VEC4:
+      case GL_UNSIGNED_INT_VEC4:
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_3D:
+      case GL_SAMPLER_CUBE:
+      case GL_SAMPLER_2D_ARRAY:
+      case GL_SAMPLER_EXTERNAL_OES:
+      case GL_SAMPLER_2D_RECT_ARB:
+      case GL_SAMPLER_2D_MULTISAMPLE:
+      case GL_INT_SAMPLER_2D:
+      case GL_INT_SAMPLER_3D:
+      case GL_INT_SAMPLER_CUBE:
+      case GL_INT_SAMPLER_2D_ARRAY:
+      case GL_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_SAMPLER_2D_SHADOW:
+      case GL_SAMPLER_CUBE_SHADOW:
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+      case GL_IMAGE_2D:
+      case GL_INT_IMAGE_2D:
+      case GL_UNSIGNED_INT_IMAGE_2D:
+      case GL_IMAGE_2D_ARRAY:
+      case GL_INT_IMAGE_2D_ARRAY:
+      case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+      case GL_IMAGE_3D:
+      case GL_INT_IMAGE_3D:
+      case GL_UNSIGNED_INT_IMAGE_3D:
+      case GL_IMAGE_CUBE:
+      case GL_INT_IMAGE_CUBE:
+      case GL_UNSIGNED_INT_IMAGE_CUBE:
+          return 1;
+      case GL_FLOAT_MAT2:
+      case GL_FLOAT_MAT3x2:
+      case GL_FLOAT_MAT4x2:
+        return 2;
+      case GL_FLOAT_MAT3:
+      case GL_FLOAT_MAT2x3:
+      case GL_FLOAT_MAT4x3:
+        return 3;
+      case GL_FLOAT_MAT4:
+      case GL_FLOAT_MAT2x4:
+      case GL_FLOAT_MAT3x4:
+        return 4;
+      default:
+        UNREACHABLE();
+    }
+
+    return 0;
+}
+
+int VariableColumnCount(GLenum type)
+{
+    switch (type)
+    {
+      case GL_NONE:
+      case GL_STRUCT_ANGLEX:
+        return 0;
+      case GL_BOOL:
+      case GL_FLOAT:
+      case GL_INT:
+      case GL_UNSIGNED_INT:
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_3D:
+      case GL_SAMPLER_CUBE:
+      case GL_SAMPLER_2D_ARRAY:
+      case GL_SAMPLER_2D_MULTISAMPLE:
+      case GL_INT_SAMPLER_2D:
+      case GL_INT_SAMPLER_3D:
+      case GL_INT_SAMPLER_CUBE:
+      case GL_INT_SAMPLER_2D_ARRAY:
+      case GL_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_SAMPLER_EXTERNAL_OES:
+      case GL_SAMPLER_2D_RECT_ARB:
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_SAMPLER_2D_SHADOW:
+      case GL_SAMPLER_CUBE_SHADOW:
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+      case GL_IMAGE_2D:
+      case GL_INT_IMAGE_2D:
+      case GL_UNSIGNED_INT_IMAGE_2D:
+      case GL_IMAGE_3D:
+      case GL_INT_IMAGE_3D:
+      case GL_UNSIGNED_INT_IMAGE_3D:
+      case GL_IMAGE_2D_ARRAY:
+      case GL_INT_IMAGE_2D_ARRAY:
+      case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+      case GL_IMAGE_CUBE:
+      case GL_INT_IMAGE_CUBE:
+      case GL_UNSIGNED_INT_IMAGE_CUBE:
+          return 1;
+      case GL_BOOL_VEC2:
+      case GL_FLOAT_VEC2:
+      case GL_INT_VEC2:
+      case GL_UNSIGNED_INT_VEC2:
+      case GL_FLOAT_MAT2:
+      case GL_FLOAT_MAT2x3:
+      case GL_FLOAT_MAT2x4:
+        return 2;
+      case GL_BOOL_VEC3:
+      case GL_FLOAT_VEC3:
+      case GL_INT_VEC3:
+      case GL_UNSIGNED_INT_VEC3:
+      case GL_FLOAT_MAT3:
+      case GL_FLOAT_MAT3x2:
+      case GL_FLOAT_MAT3x4:
+        return 3;
+      case GL_BOOL_VEC4:
+      case GL_FLOAT_VEC4:
+      case GL_INT_VEC4:
+      case GL_UNSIGNED_INT_VEC4:
+      case GL_FLOAT_MAT4:
+      case GL_FLOAT_MAT4x2:
+      case GL_FLOAT_MAT4x3:
+        return 4;
+      default:
+        UNREACHABLE();
+    }
+
+    return 0;
+}
+
+bool IsSamplerType(GLenum type)
+{
+    switch (type)
+    {
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_3D:
+      case GL_SAMPLER_CUBE:
+      case GL_SAMPLER_2D_ARRAY:
+      case GL_SAMPLER_EXTERNAL_OES:
+      case GL_SAMPLER_2D_MULTISAMPLE:
+      case GL_INT_SAMPLER_2D:
+      case GL_INT_SAMPLER_3D:
+      case GL_INT_SAMPLER_CUBE:
+      case GL_INT_SAMPLER_2D_ARRAY:
+      case GL_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_SAMPLER_2D_SHADOW:
+      case GL_SAMPLER_CUBE_SHADOW:
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+        return true;
+    }
+
+    return false;
+}
+
+bool IsImageType(GLenum type)
+{
+    switch (type)
+    {
+        case GL_IMAGE_2D:
+        case GL_INT_IMAGE_2D:
+        case GL_UNSIGNED_INT_IMAGE_2D:
+        case GL_IMAGE_3D:
+        case GL_INT_IMAGE_3D:
+        case GL_UNSIGNED_INT_IMAGE_3D:
+        case GL_IMAGE_2D_ARRAY:
+        case GL_INT_IMAGE_2D_ARRAY:
+        case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+        case GL_IMAGE_CUBE:
+        case GL_INT_IMAGE_CUBE:
+        case GL_UNSIGNED_INT_IMAGE_CUBE:
+            return true;
+    }
+    return false;
+}
+
+bool IsOpaqueType(GLenum type)
+{
+    // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters.
+    // TODO(oetuaho): add atomic types
+    return IsImageType(type) || IsSamplerType(type);
+}
+
+GLenum SamplerTypeToTextureType(GLenum samplerType)
+{
+    switch (samplerType)
+    {
+      case GL_SAMPLER_2D:
+      case GL_INT_SAMPLER_2D:
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+      case GL_SAMPLER_2D_SHADOW:
+        return GL_TEXTURE_2D;
+
+      case GL_SAMPLER_EXTERNAL_OES:
+          return GL_TEXTURE_EXTERNAL_OES;
+
+      case GL_SAMPLER_CUBE:
+      case GL_INT_SAMPLER_CUBE:
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+      case GL_SAMPLER_CUBE_SHADOW:
+        return GL_TEXTURE_CUBE_MAP;
+
+      case GL_SAMPLER_2D_ARRAY:
+      case GL_INT_SAMPLER_2D_ARRAY:
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+        return GL_TEXTURE_2D_ARRAY;
+
+      case GL_SAMPLER_3D:
+      case GL_INT_SAMPLER_3D:
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+        return GL_TEXTURE_3D;
+
+      case GL_SAMPLER_2D_MULTISAMPLE:
+      case GL_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+          return GL_TEXTURE_2D_MULTISAMPLE;
+
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+}
+
+bool IsMatrixType(GLenum type)
+{
+    return VariableRowCount(type) > 1;
+}
+
+GLenum TransposeMatrixType(GLenum type)
+{
+    if (!IsMatrixType(type))
+    {
+        return type;
+    }
+
+    switch (type)
+    {
+      case GL_FLOAT_MAT2:   return GL_FLOAT_MAT2;
+      case GL_FLOAT_MAT3:   return GL_FLOAT_MAT3;
+      case GL_FLOAT_MAT4:   return GL_FLOAT_MAT4;
+      case GL_FLOAT_MAT2x3: return GL_FLOAT_MAT3x2;
+      case GL_FLOAT_MAT3x2: return GL_FLOAT_MAT2x3;
+      case GL_FLOAT_MAT2x4: return GL_FLOAT_MAT4x2;
+      case GL_FLOAT_MAT4x2: return GL_FLOAT_MAT2x4;
+      case GL_FLOAT_MAT3x4: return GL_FLOAT_MAT4x3;
+      case GL_FLOAT_MAT4x3: return GL_FLOAT_MAT3x4;
+      default: UNREACHABLE(); return GL_NONE;
+    }
+}
+
+int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix)
+{
+    ASSERT(IsMatrixType(type));
+    return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type);
+}
+
+int MatrixComponentCount(GLenum type, bool isRowMajorMatrix)
+{
+    ASSERT(IsMatrixType(type));
+    return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type);
+}
+
+int VariableRegisterCount(GLenum type)
+{
+    return IsMatrixType(type) ? VariableColumnCount(type) : 1;
+}
+
+int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
+{
+    ASSERT(allocationSize <= bitsSize);
+
+    unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
+
+    for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
+    {
+        if ((*bits & mask) == 0)
+        {
+            *bits |= mask;
+            return i;
+        }
+
+        mask <<= 1;
+    }
+
+    return -1;
+}
+
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
+
+bool IsCubeMapTextureTarget(GLenum target)
+{
+    return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
+}
+
+size_t CubeMapTextureTargetToLayerIndex(GLenum target)
+{
+    ASSERT(IsCubeMapTextureTarget(target));
+    return target - static_cast<size_t>(FirstCubeMapTextureTarget);
+}
+
+GLenum LayerIndexToCubeMapTextureTarget(size_t index)
+{
+    ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
+    return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
+}
+
+IndexRange ComputeIndexRange(GLenum indexType,
+                             const GLvoid *indices,
+                             size_t count,
+                             bool primitiveRestartEnabled)
+{
+    switch (indexType)
+    {
+        case GL_UNSIGNED_BYTE:
+            return ComputeTypedIndexRange(static_cast<const GLubyte *>(indices), count,
+                                          primitiveRestartEnabled,
+                                          GetPrimitiveRestartIndex(indexType));
+        case GL_UNSIGNED_SHORT:
+            return ComputeTypedIndexRange(static_cast<const GLushort *>(indices), count,
+                                          primitiveRestartEnabled,
+                                          GetPrimitiveRestartIndex(indexType));
+        case GL_UNSIGNED_INT:
+            return ComputeTypedIndexRange(static_cast<const GLuint *>(indices), count,
+                                          primitiveRestartEnabled,
+                                          GetPrimitiveRestartIndex(indexType));
+        default:
+            UNREACHABLE();
+            return IndexRange();
+    }
+}
+
+GLuint GetPrimitiveRestartIndex(GLenum indexType)
+{
+    switch (indexType)
+    {
+        case GL_UNSIGNED_BYTE:
+            return 0xFF;
+        case GL_UNSIGNED_SHORT:
+            return 0xFFFF;
+        case GL_UNSIGNED_INT:
+            return 0xFFFFFFFF;
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+bool IsTriangleMode(GLenum drawMode)
+{
+    switch (drawMode)
+    {
+      case GL_TRIANGLES:
+      case GL_TRIANGLE_FAN:
+      case GL_TRIANGLE_STRIP:
+        return true;
+      case GL_POINTS:
+      case GL_LINES:
+      case GL_LINE_LOOP:
+      case GL_LINE_STRIP:
+        return false;
+      default: UNREACHABLE();
+    }
+
+    return false;
+}
+
+// [OpenGL ES SL 3.00.4] Section 11 p. 120
+// Vertex Outs/Fragment Ins packing priorities
+int VariableSortOrder(GLenum type)
+{
+    switch (type)
+    {
+      // 1. Arrays of mat4 and mat4
+      // Non-square matrices of type matCxR consume the same space as a square
+      // matrix of type matN where N is the greater of C and R
+      case GL_FLOAT_MAT4:
+      case GL_FLOAT_MAT2x4:
+      case GL_FLOAT_MAT3x4:
+      case GL_FLOAT_MAT4x2:
+      case GL_FLOAT_MAT4x3:
+        return 0;
+
+      // 2. Arrays of mat2 and mat2 (since they occupy full rows)
+      case GL_FLOAT_MAT2:
+        return 1;
+
+      // 3. Arrays of vec4 and vec4
+      case GL_FLOAT_VEC4:
+      case GL_INT_VEC4:
+      case GL_BOOL_VEC4:
+      case GL_UNSIGNED_INT_VEC4:
+        return 2;
+
+      // 4. Arrays of mat3 and mat3
+      case GL_FLOAT_MAT3:
+      case GL_FLOAT_MAT2x3:
+      case GL_FLOAT_MAT3x2:
+        return 3;
+
+      // 5. Arrays of vec3 and vec3
+      case GL_FLOAT_VEC3:
+      case GL_INT_VEC3:
+      case GL_BOOL_VEC3:
+      case GL_UNSIGNED_INT_VEC3:
+        return 4;
+
+      // 6. Arrays of vec2 and vec2
+      case GL_FLOAT_VEC2:
+      case GL_INT_VEC2:
+      case GL_BOOL_VEC2:
+      case GL_UNSIGNED_INT_VEC2:
+        return 5;
+
+      // 7. Single component types
+      case GL_FLOAT:
+      case GL_INT:
+      case GL_BOOL:
+      case GL_UNSIGNED_INT:
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_CUBE:
+      case GL_SAMPLER_EXTERNAL_OES:
+      case GL_SAMPLER_2D_RECT_ARB:
+      case GL_SAMPLER_2D_ARRAY:
+      case GL_SAMPLER_2D_MULTISAMPLE:
+      case GL_SAMPLER_3D:
+      case GL_INT_SAMPLER_2D:
+      case GL_INT_SAMPLER_3D:
+      case GL_INT_SAMPLER_CUBE:
+      case GL_INT_SAMPLER_2D_ARRAY:
+      case GL_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_SAMPLER_2D_SHADOW:
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+      case GL_SAMPLER_CUBE_SHADOW:
+        return 6;
+
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+}
+
+std::string ParseResourceName(const std::string &name, size_t *outSubscript)
+{
+    // Strip any trailing array operator and retrieve the subscript
+    size_t open = name.find_last_of('[');
+    size_t close = name.find_last_of(']');
+    bool hasIndex = (open != std::string::npos) && (close == name.length() - 1);
+    if (!hasIndex)
+    {
+        if (outSubscript)
+        {
+            *outSubscript = GL_INVALID_INDEX;
+        }
+        return name;
+    }
+
+    if (outSubscript)
+    {
+        int index = atoi(name.substr(open + 1).c_str());
+        if (index >= 0)
+        {
+            *outSubscript = index;
+        }
+        else
+        {
+            *outSubscript = GL_INVALID_INDEX;
+        }
+    }
+
+    return name.substr(0, open);
+}
+
+template <>
+GLuint ConvertToGLuint(GLfloat param)
+{
+    return uiround<GLuint>(param);
+}
+
+template <>
+GLint ConvertToGLint(GLfloat param)
+{
+    return iround<GLint>(param);
+}
+
+template <>
+GLint ConvertFromGLfloat(GLfloat param)
+{
+    return iround<GLint>(param);
+}
+template <>
+GLuint ConvertFromGLfloat(GLfloat param)
+{
+    return uiround<GLuint>(param);
+}
+
+unsigned int ParseAndStripArrayIndex(std::string *name)
+{
+    unsigned int subscript = GL_INVALID_INDEX;
+
+    // Strip any trailing array operator and retrieve the subscript
+    size_t open  = name->find_last_of('[');
+    size_t close = name->find_last_of(']');
+    if (open != std::string::npos && close == name->length() - 1)
+    {
+        subscript = atoi(name->c_str() + open + 1);
+        name->erase(open);
+    }
+
+    return subscript;
+}
+
+}  // namespace gl
+
+namespace egl
+{
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1,
+              "Unexpected EGL cube map enum value.");
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 2,
+              "Unexpected EGL cube map enum value.");
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 3,
+              "Unexpected EGL cube map enum value.");
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 4,
+              "Unexpected EGL cube map enum value.");
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 5,
+              "Unexpected EGL cube map enum value.");
+
+bool IsCubeMapTextureTarget(EGLenum target)
+{
+    return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
+}
+
+size_t CubeMapTextureTargetToLayerIndex(EGLenum target)
+{
+    ASSERT(IsCubeMapTextureTarget(target));
+    return target - static_cast<size_t>(FirstCubeMapTextureTarget);
+}
+
+EGLenum LayerIndexToCubeMapTextureTarget(size_t index)
+{
+    ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
+    return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
+}
+
+bool IsTextureTarget(EGLenum target)
+{
+    switch (target)
+    {
+        case EGL_GL_TEXTURE_2D_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+        case EGL_GL_TEXTURE_3D_KHR:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool IsRenderbufferTarget(EGLenum target)
+{
+    return target == EGL_GL_RENDERBUFFER_KHR;
+}
+}  // namespace egl
+
+namespace egl_gl
+{
+GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget)
+{
+    ASSERT(egl::IsCubeMapTextureTarget(eglTarget));
+    return gl::LayerIndexToCubeMapTextureTarget(egl::CubeMapTextureTargetToLayerIndex(eglTarget));
+}
+
+GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget)
+{
+    switch (eglTarget)
+    {
+        case EGL_GL_TEXTURE_2D_KHR:
+            return GL_TEXTURE_2D;
+
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+            return EGLCubeMapTargetToGLCubeMapTarget(eglTarget);
+
+        case EGL_GL_TEXTURE_3D_KHR:
+            return GL_TEXTURE_3D;
+
+        default:
+            UNREACHABLE();
+            return GL_NONE;
+    }
+}
+
+GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
+{
+    return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
+}
+}  // namespace egl_gl
+
+namespace gl_egl
+{
+EGLenum GLComponentTypeToEGLColorComponentType(GLenum glComponentType)
+{
+    switch (glComponentType)
+    {
+        case GL_FLOAT:
+            return EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
+
+        case GL_UNSIGNED_NORMALIZED:
+            return EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+
+        default:
+            UNREACHABLE();
+            return EGL_NONE;
+    }
+}
+}  // namespace gl_egl
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+std::string getTempPath()
+{
+#ifdef ANGLE_PLATFORM_WINDOWS
+    char path[MAX_PATH];
+    DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
+    if (pathLen == 0)
+    {
+        UNREACHABLE();
+        return std::string();
+    }
+
+    UINT unique = GetTempFileNameA(path, "sh", 0, path);
+    if (unique == 0)
+    {
+        UNREACHABLE();
+        return std::string();
+    }
+
+    return path;
+#else
+    UNIMPLEMENTED();
+    return "";
+#endif
+}
+
+void writeFile(const char* path, const void* content, size_t size)
+{
+    FILE* file = fopen(path, "w");
+    if (!file)
+    {
+        UNREACHABLE();
+        return;
+    }
+
+    fwrite(content, sizeof(char), size, file);
+    fclose(file);
+}
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+
+#if defined (ANGLE_PLATFORM_WINDOWS)
+
+// Causes the thread to relinquish the remainder of its time slice to any
+// other thread that is ready to run.If there are no other threads ready
+// to run, the function returns immediately, and the thread continues execution.
+void ScheduleYield()
+{
+    Sleep(0);
+}
+
+#endif
diff --git a/src/third_party/angle/src/common/utilities.h b/src/third_party/angle/src/common/utilities.h
new file mode 100644
index 0000000..68cc9ec
--- /dev/null
+++ b/src/third_party/angle/src/common/utilities.h
@@ -0,0 +1,180 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// utilities.h: Conversion functions and other utility routines.
+
+#ifndef COMMON_UTILITIES_H_
+#define COMMON_UTILITIES_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "angle_gl.h"
+#include <string>
+#include <math.h>
+
+#include "common/mathutil.h"
+
+namespace gl
+{
+
+int VariableComponentCount(GLenum type);
+GLenum VariableComponentType(GLenum type);
+size_t VariableComponentSize(GLenum type);
+size_t VariableInternalSize(GLenum type);
+size_t VariableExternalSize(GLenum type);
+GLenum VariableBoolVectorType(GLenum type);
+int VariableRowCount(GLenum type);
+int VariableColumnCount(GLenum type);
+bool IsSamplerType(GLenum type);
+bool IsImageType(GLenum type);
+bool IsOpaqueType(GLenum type);
+GLenum SamplerTypeToTextureType(GLenum samplerType);
+bool IsMatrixType(GLenum type);
+GLenum TransposeMatrixType(GLenum type);
+int VariableRegisterCount(GLenum type);
+int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix);
+int MatrixComponentCount(GLenum type, bool isRowMajorMatrix);
+int VariableSortOrder(GLenum type);
+
+int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
+
+static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+bool IsCubeMapTextureTarget(GLenum target);
+size_t CubeMapTextureTargetToLayerIndex(GLenum target);
+GLenum LayerIndexToCubeMapTextureTarget(size_t index);
+
+// Parse the base resource name and array index.  Returns the base name of the resource.
+// outSubscript is set to GL_INVALID_INDEX if the provided name is not an array or the array index
+// is invalid.
+std::string ParseResourceName(const std::string &name, size_t *outSubscript);
+
+// Find the range of index values in the provided indices pointer.  Primitive restart indices are
+// only counted in the range if primitive restart is disabled.
+IndexRange ComputeIndexRange(GLenum indexType,
+                             const GLvoid *indices,
+                             size_t count,
+                             bool primitiveRestartEnabled);
+
+// Get the primitive restart index value for the given index type.
+GLuint GetPrimitiveRestartIndex(GLenum indexType);
+
+bool IsTriangleMode(GLenum drawMode);
+
+// [OpenGL ES 3.0.2] Section 2.3.1 page 14
+// Data Conversion For State-Setting Commands
+// Floating-point values are rounded to the nearest integer, instead of truncated, as done by static_cast.
+template <typename outT> outT iround(GLfloat value) { return static_cast<outT>(value > 0.0f ? floor(value + 0.5f) : ceil(value - 0.5f)); }
+template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>(value + 0.5f); }
+
+// Helper for converting arbitrary GL types to other GL types used in queries and state setting
+template <typename ParamType>
+GLuint ConvertToGLuint(ParamType param)
+{
+    return static_cast<GLuint>(param);
+}
+template <>
+GLuint ConvertToGLuint(GLfloat param);
+
+template <typename ParamType>
+GLint ConvertToGLint(ParamType param)
+{
+    return static_cast<GLint>(param);
+}
+template <>
+GLint ConvertToGLint(GLfloat param);
+
+// Same conversion as uint
+template <typename ParamType>
+GLenum ConvertToGLenum(ParamType param)
+{
+    return static_cast<GLenum>(ConvertToGLuint(param));
+}
+
+template <typename ParamType>
+GLfloat ConvertToGLfloat(ParamType param)
+{
+    return static_cast<GLfloat>(param);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLfloat(GLfloat param)
+{
+    return static_cast<ParamType>(param);
+}
+template <>
+GLint ConvertFromGLfloat(GLfloat param);
+template <>
+GLuint ConvertFromGLfloat(GLfloat param);
+
+template <typename ParamType>
+ParamType ConvertFromGLenum(GLenum param)
+{
+    return static_cast<ParamType>(param);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLuint(GLuint param)
+{
+    return static_cast<ParamType>(param);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLint(GLint param)
+{
+    return static_cast<ParamType>(param);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLboolean(GLboolean param)
+{
+    return static_cast<ParamType>(param ? GL_TRUE : GL_FALSE);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLint64(GLint64 param)
+{
+    return clampCast<ParamType>(param);
+}
+
+unsigned int ParseAndStripArrayIndex(std::string *name);
+
+}  // namespace gl
+
+namespace egl
+{
+static const EGLenum FirstCubeMapTextureTarget = EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
+static const EGLenum LastCubeMapTextureTarget = EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR;
+bool IsCubeMapTextureTarget(EGLenum target);
+size_t CubeMapTextureTargetToLayerIndex(EGLenum target);
+EGLenum LayerIndexToCubeMapTextureTarget(size_t index);
+bool IsTextureTarget(EGLenum target);
+bool IsRenderbufferTarget(EGLenum target);
+}
+
+namespace egl_gl
+{
+GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget);
+GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget);
+GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer);
+}
+
+namespace gl_egl
+{
+EGLenum GLComponentTypeToEGLColorComponentType(GLenum glComponentType);
+}  // namespace gl_egl
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+std::string getTempPath();
+void writeFile(const char* path, const void* data, size_t size);
+#endif
+
+#if defined (ANGLE_PLATFORM_WINDOWS)
+void ScheduleYield();
+#endif
+
+#endif  // COMMON_UTILITIES_H_
diff --git a/src/third_party/angle/src/common/utilities_unittest.cpp b/src/third_party/angle/src/common/utilities_unittest.cpp
new file mode 100644
index 0000000..92b8d2d
--- /dev/null
+++ b/src/third_party/angle/src/common/utilities_unittest.cpp
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// utilities_unittest.cpp: Unit tests for ANGLE's GL utility functions
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "common/utilities.h"
+
+namespace
+{
+
+TEST(ParseResourceName, ArrayIndex)
+{
+    size_t index;
+    EXPECT_EQ("foo", gl::ParseResourceName("foo[123]", &index));
+    EXPECT_EQ(123u, index);
+
+    EXPECT_EQ("bar", gl::ParseResourceName("bar[0]", &index));
+    EXPECT_EQ(0u, index);
+}
+
+TEST(ParseResourceName, NegativeArrayIndex)
+{
+    size_t index;
+    EXPECT_EQ("foo", gl::ParseResourceName("foo[-1]", &index));
+    EXPECT_EQ(GL_INVALID_INDEX, index);
+}
+
+TEST(ParseResourceName, NoArrayIndex)
+{
+    size_t index;
+    EXPECT_EQ("foo", gl::ParseResourceName("foo", &index));
+    EXPECT_EQ(GL_INVALID_INDEX, index);
+}
+
+TEST(ParseResourceName, NULLArrayIndex)
+{
+    EXPECT_EQ("foo", gl::ParseResourceName("foo[10]", nullptr));
+}
+
+TEST(ParseResourceName, TrailingWhitespace)
+{
+    size_t index;
+    EXPECT_EQ("foo ", gl::ParseResourceName("foo ", &index));
+    EXPECT_EQ(GL_INVALID_INDEX, index);
+
+    EXPECT_EQ("foo[10] ", gl::ParseResourceName("foo[10] ", &index));
+    EXPECT_EQ(GL_INVALID_INDEX, index);
+}
+
+}
diff --git a/src/third_party/angle/src/common/vector_utils.h b/src/third_party/angle/src/common/vector_utils.h
new file mode 100644
index 0000000..3eb7120
--- /dev/null
+++ b/src/third_party/angle/src/common/vector_utils.h
@@ -0,0 +1,476 @@
+//
+// Copyright 2016 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.
+//
+// vector_utils.h: Utility classes implementing various vector operations
+
+#ifndef COMMON_VECTOR_UTILS_H_
+#define COMMON_VECTOR_UTILS_H_
+
+#include <cstddef>
+#include <cmath>
+#include <type_traits>
+
+namespace angle
+{
+
+template <size_t Dimension, typename Type>
+class Vector;
+
+using Vector2 = Vector<2, float>;
+using Vector3 = Vector<3, float>;
+using Vector4 = Vector<4, float>;
+
+using Vector2I = Vector<2, int>;
+using Vector3I = Vector<3, int>;
+using Vector4I = Vector<4, int>;
+
+using Vector2U = Vector<2, unsigned int>;
+using Vector3U = Vector<3, unsigned int>;
+using Vector4U = Vector<4, unsigned int>;
+
+template <size_t Dimension, typename Type>
+class VectorBase
+{
+  public:
+    using VectorN = Vector<Dimension, Type>;
+
+    // Constructors
+    VectorBase() = default;
+    explicit VectorBase(Type element);
+
+    template <typename Type2>
+    VectorBase(const VectorBase<Dimension, Type2> &other);
+
+    template <typename Arg1, typename Arg2, typename... Args>
+    VectorBase(const Arg1 &arg1, const Arg2 &arg2, const Args &... args);
+
+    // Access the vector backing storage directly
+    const Type *data() const { return mData; }
+    Type *data() { return mData; }
+    constexpr size_t size() const { return Dimension; }
+
+    // Load or store the pointer from / to raw data
+    static VectorN Load(const Type *source);
+    static void Store(const VectorN &source, Type *destination);
+
+    // Index the vector
+    Type &operator[](size_t i) { return mData[i]; }
+    const Type &operator[](size_t i) const { return mData[i]; }
+
+    // Basic arithmetic operations
+    VectorN operator+() const;
+    VectorN operator-() const;
+    VectorN operator+(const VectorN &other) const;
+    VectorN operator-(const VectorN &other) const;
+    VectorN operator*(const VectorN &other) const;
+    VectorN operator/(const VectorN &other) const;
+    VectorN operator*(Type other) const;
+    VectorN operator/(Type other) const;
+    friend VectorN operator*(Type a, const VectorN &b) { return b * a; }
+
+    // Compound arithmetic operations
+    VectorN &operator+=(const VectorN &other);
+    VectorN &operator-=(const VectorN &other);
+    VectorN &operator*=(const VectorN &other);
+    VectorN &operator/=(const VectorN &other);
+    VectorN &operator*=(Type other);
+    VectorN &operator/=(Type other);
+
+    // Comparison operators
+    bool operator==(const VectorN &other) const;
+    bool operator!=(const VectorN &other) const;
+
+    // Other arithmetic operations
+    Type length() const;
+    Type lengthSquared() const;
+    Type dot(const VectorBase<Dimension, Type> &other) const;
+    VectorN normalized() const;
+
+  protected:
+    template <size_t CurrentIndex, size_t OtherDimension, typename OtherType, typename... Args>
+    void initWithList(const Vector<OtherDimension, OtherType> &arg1, const Args &... args);
+
+    // Some old compilers consider this function an alternative for initWithList(Vector)
+    // when the variant above is more precise. Use SFINAE on the return value to hide
+    // this variant for non-arithmetic types. The return value is still void.
+    template <size_t CurrentIndex, typename OtherType, typename... Args>
+    typename std::enable_if<std::is_arithmetic<OtherType>::value>::type initWithList(
+        OtherType arg1,
+        const Args &... args);
+
+    template <size_t CurrentIndex>
+    void initWithList() const;
+
+    template <size_t Dimension2, typename Type2>
+    friend class VectorBase;
+
+    Type mData[Dimension];
+};
+
+template <typename Type>
+class Vector<2, Type> : public VectorBase<2, Type>
+{
+  public:
+    // Import the constructors defined in VectorBase
+    using VectorBase<2, Type>::VectorBase;
+
+    // Element shorthands
+    Type &x() { return this->mData[0]; }
+    Type &y() { return this->mData[1]; }
+
+    const Type &x() const { return this->mData[0]; }
+    const Type &y() const { return this->mData[1]; }
+};
+
+template <typename Type>
+class Vector<3, Type> : public VectorBase<3, Type>
+{
+  public:
+    // Import the constructors defined in VectorBase
+    using VectorBase<3, Type>::VectorBase;
+
+    // Additional operations
+    Vector<3, Type> cross(const Vector<3, Type> &other) const;
+
+    // Element shorthands
+    Type &x() { return this->mData[0]; }
+    Type &y() { return this->mData[1]; }
+    Type &z() { return this->mData[2]; }
+
+    const Type &x() const { return this->mData[0]; }
+    const Type &y() const { return this->mData[1]; }
+    const Type &z() const { return this->mData[2]; }
+};
+
+template <typename Type>
+class Vector<4, Type> : public VectorBase<4, Type>
+{
+  public:
+    // Import the constructors defined in VectorBase
+    using VectorBase<4, Type>::VectorBase;
+
+    // Element shorthands
+    Type &x() { return this->mData[0]; }
+    Type &y() { return this->mData[1]; }
+    Type &z() { return this->mData[2]; }
+    Type &w() { return this->mData[3]; }
+
+    const Type &x() const { return this->mData[0]; }
+    const Type &y() const { return this->mData[1]; }
+    const Type &z() const { return this->mData[2]; }
+    const Type &w() const { return this->mData[3]; }
+};
+
+// Implementation of constructors and misc operations
+
+template <size_t Dimension, typename Type>
+VectorBase<Dimension, Type>::VectorBase(Type element)
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        mData[i] = element;
+    }
+}
+
+template <size_t Dimension, typename Type>
+template <typename Type2>
+VectorBase<Dimension, Type>::VectorBase(const VectorBase<Dimension, Type2> &other)
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        mData[i] = static_cast<Type>(other.mData[i]);
+    }
+}
+
+// Ideally we would like to have only two constructors:
+//  - a scalar constructor that takes Type as a parameter
+//  - a compound constructor
+// However if we define the compound constructor for when it has a single arguments, then calling
+// Vector2(0.0) will be ambiguous. To solve this we take advantage of there being a single compound
+// constructor with a single argument, which is the copy constructor. We end up with three
+// constructors:
+//  - the scalar constructor
+//  - the copy constructor
+//  - the compound constructor for two or more arguments, hence the arg1, and arg2 here.
+template <size_t Dimension, typename Type>
+template <typename Arg1, typename Arg2, typename... Args>
+VectorBase<Dimension, Type>::VectorBase(const Arg1 &arg1, const Arg2 &arg2, const Args &... args)
+{
+    initWithList<0>(arg1, arg2, args...);
+}
+
+template <size_t Dimension, typename Type>
+template <size_t CurrentIndex, size_t OtherDimension, typename OtherType, typename... Args>
+void VectorBase<Dimension, Type>::initWithList(const Vector<OtherDimension, OtherType> &arg1,
+                                               const Args &... args)
+{
+    static_assert(CurrentIndex + OtherDimension <= Dimension,
+                  "Too much data in the vector constructor.");
+    for (size_t i = 0; i < OtherDimension; ++i)
+    {
+        mData[CurrentIndex + i] = static_cast<Type>(arg1.mData[i]);
+    }
+    initWithList<CurrentIndex + OtherDimension>(args...);
+}
+
+template <size_t Dimension, typename Type>
+template <size_t CurrentIndex, typename OtherType, typename... Args>
+typename std::enable_if<std::is_arithmetic<OtherType>::value>::type
+VectorBase<Dimension, Type>::initWithList(OtherType arg1, const Args &... args)
+{
+    static_assert(CurrentIndex + 1 <= Dimension, "Too much data in the vector constructor.");
+    mData[CurrentIndex] = static_cast<Type>(arg1);
+    initWithList<CurrentIndex + 1>(args...);
+}
+
+template <size_t Dimension, typename Type>
+template <size_t CurrentIndex>
+void VectorBase<Dimension, Type>::initWithList() const
+{
+    static_assert(CurrentIndex == Dimension, "Not enough data in the vector constructor.");
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::Load(const Type *source)
+{
+    Vector<Dimension, Type> result;
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        result.mData[i] = source[i];
+    }
+    return result;
+}
+
+template <size_t Dimension, typename Type>
+void VectorBase<Dimension, Type>::Store(const Vector<Dimension, Type> &source, Type *destination)
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        destination[i] = source.mData[i];
+    }
+}
+
+// Implementation of basic arithmetic operations
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator+() const
+{
+    Vector<Dimension, Type> result;
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        result.mData[i] = +mData[i];
+    }
+    return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator-() const
+{
+    Vector<Dimension, Type> result;
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        result.mData[i] = -mData[i];
+    }
+    return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator+(
+    const Vector<Dimension, Type> &other) const
+{
+    Vector<Dimension, Type> result;
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        result.mData[i] = mData[i] + other.mData[i];
+    }
+    return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator-(
+    const Vector<Dimension, Type> &other) const
+{
+    Vector<Dimension, Type> result;
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        result.mData[i] = mData[i] - other.mData[i];
+    }
+    return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator*(
+    const Vector<Dimension, Type> &other) const
+{
+    Vector<Dimension, Type> result;
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        result.mData[i] = mData[i] * other.mData[i];
+    }
+    return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator/(
+    const Vector<Dimension, Type> &other) const
+{
+    Vector<Dimension, Type> result;
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        result.mData[i] = mData[i] / other.mData[i];
+    }
+    return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator*(Type other) const
+{
+    Vector<Dimension, Type> result;
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        result.mData[i] = mData[i] * other;
+    }
+    return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator/(Type other) const
+{
+    Vector<Dimension, Type> result;
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        result.mData[i] = mData[i] / other;
+    }
+    return result;
+}
+
+// Implementation of compound arithmetic operations
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator+=(
+    const Vector<Dimension, Type> &other)
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        mData[i] += other.mData[i];
+    }
+    return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator-=(
+    const Vector<Dimension, Type> &other)
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        mData[i] -= other.mData[i];
+    }
+    return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator*=(
+    const Vector<Dimension, Type> &other)
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        mData[i] *= other.mData[i];
+    }
+    return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator/=(
+    const Vector<Dimension, Type> &other)
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        mData[i] /= other.mData[i];
+    }
+    return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator*=(Type other)
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        mData[i] *= other;
+    }
+    return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator/=(Type other)
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        mData[i] /= other;
+    }
+    return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+// Implementation of comparison operators
+template <size_t Dimension, typename Type>
+bool VectorBase<Dimension, Type>::operator==(const Vector<Dimension, Type> &other) const
+{
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        if (mData[i] != other.mData[i])
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+template <size_t Dimension, typename Type>
+bool VectorBase<Dimension, Type>::operator!=(const Vector<Dimension, Type> &other) const
+{
+    return !(*this == other);
+}
+
+// Implementation of other arithmetic operations
+template <size_t Dimension, typename Type>
+Type VectorBase<Dimension, Type>::length() const
+{
+    static_assert(std::is_floating_point<Type>::value,
+                  "VectorN::length is only defined for floating point vectors");
+    return std::sqrt(lengthSquared());
+}
+
+template <size_t Dimension, typename Type>
+Type VectorBase<Dimension, Type>::lengthSquared() const
+{
+    return dot(*this);
+}
+
+template <size_t Dimension, typename Type>
+Type VectorBase<Dimension, Type>::dot(const VectorBase<Dimension, Type> &other) const
+{
+    Type sum = Type();
+    for (size_t i = 0; i < Dimension; ++i)
+    {
+        sum += mData[i] * other.mData[i];
+    }
+    return sum;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::normalized() const
+{
+    static_assert(std::is_floating_point<Type>::value,
+                  "VectorN::normalized is only defined for floating point vectors");
+    return *this / length();
+}
+
+template <typename Type>
+Vector<3, Type> Vector<3, Type>::cross(const Vector<3, Type> &other) const
+{
+    return Vector<3, Type>(y() * other.z() - z() * other.y(), z() * other.x() - x() * other.z(),
+                           x() * other.y() - y() * other.x());
+}
+
+}  // namespace angle
+
+#endif  // COMMON_VECTOR_UTILS_H_
diff --git a/src/third_party/angle/src/common/vector_utils_unittest.cpp b/src/third_party/angle/src/common/vector_utils_unittest.cpp
new file mode 100644
index 0000000..9c1184d
--- /dev/null
+++ b/src/third_party/angle/src/common/vector_utils_unittest.cpp
@@ -0,0 +1,225 @@
+//
+// Copyright 2016 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.
+//
+// vector_utils_unittests.cpp: Unit tests for the vector utils.
+//
+
+#include "vector_utils.h"
+
+#include <gtest/gtest.h>
+
+using namespace angle;
+
+namespace
+{
+
+// First test that comparing vectors work
+TEST(VectorUtilsTest, Comparison)
+{
+    // Don't use ASSERT_EQ at first because the == is more hidden
+    ASSERT_TRUE(Vector2(2.0, 3.0) == Vector2(2.0, 3.0));
+    ASSERT_TRUE(Vector2(2.0, 3.0) != Vector2(2.0, 4.0));
+
+    // Check ASSERT_EQ and ASSERT_NE work correctly
+    ASSERT_EQ(Vector2(2.0, 3.0), Vector2(2.0, 3.0));
+    ASSERT_NE(Vector2(2.0, 3.0), Vector2(2.0, 4.0));
+
+    // Check comparison works on all elements
+    ASSERT_EQ(Vector4(0.0), Vector4(0.0));
+    ASSERT_NE(Vector4(1.0, 0.0, 0.0, 0.0), Vector4(0.0));
+    ASSERT_NE(Vector4(0.0, 1.0, 0.0, 0.0), Vector4(0.0));
+    ASSERT_NE(Vector4(0.0, 0.0, 1.0, 0.0), Vector4(0.0));
+    ASSERT_NE(Vector4(0.0, 0.0, 0.0, 1.0), Vector4(0.0));
+}
+
+// Test indexing
+TEST(VectorUtilsTest, Indexing)
+{
+    Vector2 vec(1.0, 2.0);
+    ASSERT_EQ(1.0, vec[0]);
+    ASSERT_EQ(2.0, vec[1]);
+
+    vec[0] = 3.0;
+    vec[1] = 4.0;
+    ASSERT_EQ(Vector2(3.0, 4.0), vec);
+}
+
+// Test for the various constructors
+TEST(VectorUtilsTest, Constructors)
+{
+    // Constructor initializing all to a single element
+    {
+        Vector2 vec(3.0);
+        ASSERT_EQ(3.0, vec[0]);
+        ASSERT_EQ(3.0, vec[1]);
+    }
+
+    // Constructor initializing from another Vector
+    {
+        Vector2 vec(Vector2(1.0, 2.0));
+        ASSERT_EQ(1.0, vec[0]);
+        ASSERT_EQ(2.0, vec[1]);
+    }
+
+    // Mixed constructor
+    {
+        Vector4 vec(1.0, Vector2(2.0, 3.0), 4.0);
+        ASSERT_EQ(1.0, vec[0]);
+        ASSERT_EQ(2.0, vec[1]);
+        ASSERT_EQ(3.0, vec[2]);
+        ASSERT_EQ(4.0, vec[3]);
+    }
+}
+
+// Test accessing the data directly
+TEST(VectorUtilsTest, DataAccess)
+{
+    Vector2 vec(1.0, 2.0);
+    ASSERT_EQ(2u, vec.size());
+
+    ASSERT_EQ(1.0, vec.data()[0]);
+    ASSERT_EQ(2.0, vec.data()[1]);
+
+    vec.data()[0] = 3.0;
+    vec.data()[1] = 4.0;
+
+    ASSERT_EQ(Vector2(3.0, 4.0), vec);
+}
+
+// Test accessing the data directly
+TEST(VectorUtilsTest, LoadStore)
+{
+    float data[] = {1.0, 2.0};
+
+    Vector2 vec = Vector2::Load(data);
+
+    ASSERT_EQ(1.0, vec.data()[0]);
+    ASSERT_EQ(2.0, vec.data()[1]);
+
+    vec = Vector2(3.0, 4.0);
+    Vector2::Store(vec, data);
+
+    ASSERT_EQ(3.0, data[0]);
+    ASSERT_EQ(4.0, data[1]);
+}
+
+// Test basic arithmetic operations
+TEST(VectorUtilsTest, BasicArithmetic)
+{
+    ASSERT_EQ(Vector2(2.0, 3.0), +Vector2(2.0, 3.0));
+    ASSERT_EQ(Vector2(-2.0, -3.0), -Vector2(2.0, 3.0));
+    ASSERT_EQ(Vector2(4.0, 6.0), Vector2(1.0, 2.0) + Vector2(3.0, 4.0));
+    ASSERT_EQ(Vector2(-2.0, -2.0), Vector2(1.0, 2.0) - Vector2(3.0, 4.0));
+    ASSERT_EQ(Vector2(3.0, 8.0), Vector2(1.0, 2.0) * Vector2(3.0, 4.0));
+    ASSERT_EQ(Vector2(3.0, 2.0), Vector2(3.0, 4.0) / Vector2(1.0, 2.0));
+
+    ASSERT_EQ(Vector2(2.0, 4.0), Vector2(1.0, 2.0) * 2);
+    ASSERT_EQ(Vector2(2.0, 4.0), 2 * Vector2(1.0, 2.0));
+    ASSERT_EQ(Vector2(0.5, 1.0), Vector2(1.0, 2.0) / 2);
+}
+
+// Test compound arithmetic operations
+TEST(VectorUtilsTest, CompoundArithmetic)
+{
+    {
+        Vector2 vec(1.0, 2.0);
+        vec += Vector2(3.0, 4.0);
+        ASSERT_EQ(Vector2(4.0, 6.0), vec);
+    }
+    {
+        Vector2 vec(1.0, 2.0);
+        vec -= Vector2(3.0, 4.0);
+        ASSERT_EQ(Vector2(-2.0, -2.0), vec);
+    }
+    {
+        Vector2 vec(1.0, 2.0);
+        vec *= Vector2(3.0, 4.0);
+        ASSERT_EQ(Vector2(3.0, 8.0), vec);
+    }
+    {
+        Vector2 vec(3.0, 4.0);
+        vec /= Vector2(1.0, 2.0);
+        ASSERT_EQ(Vector2(3.0, 2.0), vec);
+    }
+    {
+        Vector2 vec(1.0, 2.0);
+        vec *= 2.0;
+        ASSERT_EQ(Vector2(2.0, 4.0), vec);
+    }
+    {
+        Vector2 vec(1.0, 2.0);
+        vec /= 2.0;
+        ASSERT_EQ(Vector2(0.5, 1.0), vec);
+    }
+}
+
+// Test other arithmetic operations
+TEST(VectorUtilsTest, OtherArithmeticOperations)
+{
+    Vector2 vec(3.0, 4.0);
+
+    ASSERT_EQ(25.0, vec.lengthSquared());
+    ASSERT_EQ(5.0, vec.length());
+    ASSERT_EQ(Vector2(0.6, 0.8), vec.normalized());
+
+    ASSERT_EQ(11.0, vec.dot(Vector2(1.0, 2.0)));
+}
+
+// Test element shortcuts
+TEST(VectorUtilsTest, ElementShortcuts)
+{
+    Vector2 vec2(1.0, 2.0);
+    Vector3 vec3(1.0, 2.0, 3.0);
+    Vector4 vec4(1.0, 2.0, 3.0, 4.0);
+
+    ASSERT_EQ(1.0, vec2.x());
+    ASSERT_EQ(1.0, vec3.x());
+    ASSERT_EQ(1.0, vec4.x());
+
+    ASSERT_EQ(2.0, vec2.y());
+    ASSERT_EQ(2.0, vec3.y());
+    ASSERT_EQ(2.0, vec4.y());
+
+    ASSERT_EQ(3.0, vec3.z());
+    ASSERT_EQ(3.0, vec4.z());
+
+    ASSERT_EQ(4.0, vec4.w());
+
+    vec2.x() = 0.0;
+    ASSERT_EQ(Vector2(0.0, 2.0), vec2);
+}
+
+// Test the cross product
+TEST(VectorUtilsTest, CrossProduct)
+{
+    ASSERT_EQ(Vector3(0.0, 0.0, 1.0), Vector3(1.0, 0.0, 0.0).cross(Vector3(0.0, 1.0, 0.0)));
+    ASSERT_EQ(Vector3(-3.0, 6.0, -3.0), Vector3(1.0, 2.0, 3.0).cross(Vector3(4.0, 5.0, 6.0)));
+}
+
+// Test basic functionality of int vectors
+TEST(VectorUtilsTest, IntVector)
+{
+    Vector2I vec(0);
+
+    int *data = vec.data();
+    data[1]   = 1;
+
+    ASSERT_EQ(0, vec[0]);
+    ASSERT_EQ(1, vec[1]);
+}
+
+// Test basic functionality of int vectors
+TEST(VectorUtilsTest, UIntVector)
+{
+    Vector2U vec(0);
+
+    unsigned int *data = vec.data();
+    data[1]            = 1;
+
+    ASSERT_EQ(0u, vec[0]);
+    ASSERT_EQ(1u, vec[1]);
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/common/version.h b/src/third_party/angle/src/common/version.h
index c8ff636..509fe32 100644
--- a/src/third_party/angle/src/common/version.h
+++ b/src/third_party/angle/src/common/version.h
@@ -1,12 +1,32 @@
-#define MAJOR_VERSION 1
-#define MINOR_VERSION 2
-#define BUILD_VERSION 0
-#define BUILD_REVISION 2426
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
 
-#define STRINGIFY(x) #x
-#define MACRO_STRINGIFY(x) STRINGIFY(x)
+#ifndef COMMON_VERSION_H_
+#define COMMON_VERSION_H_
 
-#define REVISION_STRING MACRO_STRINGIFY(BUILD_REVISION)
-#define VERSION_STRING MACRO_STRINGIFY(MAJOR_VERSION) "." MACRO_STRINGIFY(MINOR_VERSION) "." MACRO_STRINGIFY(BUILD_VERSION) "." MACRO_STRINGIFY(BUILD_REVISION)
+#if defined(STARBOARD)
+// Just use the default commit hash header.
+#include "../commit.h"
+#else
+#include "id/commit.h"
+#endif
 
-#define VERSION_DWORD ((MAJOR_VERSION << 24) | (MINOR_VERSION << 16) | BUILD_REVISION)
+#define ANGLE_MAJOR_VERSION 2
+#define ANGLE_MINOR_VERSION 1
+
+#ifndef ANGLE_REVISION
+#define ANGLE_REVISION 0
+#endif
+
+#define ANGLE_STRINGIFY(x)       #x
+#define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x)
+
+#define ANGLE_VERSION_STRING                       \
+    ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \
+    ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \
+    ANGLE_MACRO_STRINGIFY(ANGLE_REVISION) "." \
+    ANGLE_COMMIT_HASH
+#endif // COMMON_VERSION_H_
diff --git a/src/third_party/angle/src/common/win32/debugperf.cpp b/src/third_party/angle/src/common/win32/debugperf.cpp
deleted file mode 100644
index 2a133dd..0000000
--- a/src/third_party/angle/src/common/win32/debugperf.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// win32/debugApi.cpp: Win32 specific performance debugging utilities.
-#if !defined(ANGLE_DISABLE_PERF)
-
-#include "common/debugperf.h"
-
-#include <d3d9.h>
-
-#if !defined(__LB_SHELL__FOR_RELEASE__)
-
-namespace gl
-{
-
-bool perfCheckActive()
-{
-    return D3DPERF_GetStatus() != 0;
-}
-
-void perfSetMarker(Color col, const wchar_t* name)
-{
-    D3DPERF_SetMarker(col, name);
-}
-
-void perfBeginEvent(Color col, const wchar_t* name)
-{
-    D3DPERF_BeginEvent(col, name);
-}
-
-void perfEndEvent()
-{
-    D3DPERF_EndEvent();
-}
-
-} // namespace gl
-
-#endif // !defined(__LB_SHELL__FOR_RELEASE__)
-
-#endif // !defined(ANGLE_DISABLE_PERF)
diff --git a/src/third_party/angle/src/common/win32/windowutils.cpp b/src/third_party/angle/src/common/win32/windowutils.cpp
deleted file mode 100644
index e233788..0000000
--- a/src/third_party/angle/src/common/win32/windowutils.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// win32/windowutils.cpp: Win32 specific window utility functionality
-
-#include "common/windowutils.h"
-
-namespace egl
-{
-
-bool verifyWindowAccessible(EGLNativeWindowType window)
-{
-    return (::IsWindow(window) != FALSE);
-}
-
-} // namespace egl
diff --git a/src/third_party/angle/src/common/windowutils.h b/src/third_party/angle/src/common/windowutils.h
deleted file mode 100644
index 12e695d..0000000
--- a/src/third_party/angle/src/common/windowutils.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// windowutils.h: ANGLE window specific utilities.
-
-#ifndef COMMON_WINDOWUTILS_H_
-#define COMMON_WINDOWUTILS_H_
-
-#include "common/system.h"
-
-namespace egl
-{
-
-// Check if the given window is valid and verify that it can be accessed
-// by the caller. This is particularly important in APIs like WinRT where
-// a window can be directly used only from the owning UI thread
-bool verifyWindowAccessible(EGLNativeWindowType window);
-
-} // namespace egl
-
-#endif // COMMON_WINDOWUTILS_H_
diff --git a/src/third_party/angle/src/common/winrt/debugperf.cpp b/src/third_party/angle/src/common/winrt/debugperf.cpp
deleted file mode 100644
index 165223e..0000000
--- a/src/third_party/angle/src/common/winrt/debugperf.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// winrt/debugApi.cpp: WinRT specific performance debugging utilities.
-#if !defined(ANGLE_DISABLE_PERF)
-
-#include "common/debugperf.h"
-
-#include <windows.h>
-
-#if !defined(__LB_SHELL__FOR_RELEASE__)
-
-namespace gl
-{
-
-bool perfCheckActive()
-{
-    // D3DPERF API is not avaiable on WinRT at the moment
-    return false;
-}
-
-void perfSetMarker(Color col, const wchar_t* name)
-{
-    UNREFERENCED_PARAMETER(col);
-    UNREFERENCED_PARAMETER(name);
-}
-
-void perfBeginEvent(Color col, const wchar_t* name)
-{
-    UNREFERENCED_PARAMETER(col);
-    UNREFERENCED_PARAMETER(name);
-}
-
-void perfEndEvent()
-{
-}
-
-} // namespace gl
-
-#endif // !defined(__LB_SHELL__FOR_RELEASE__)
-
-#endif // !defined(ANGLE_DISABLE_PERF)
diff --git a/src/third_party/angle/src/common/winrt/windowadapter.cpp b/src/third_party/angle/src/common/winrt/windowadapter.cpp
deleted file mode 100644
index bd8a418..0000000
--- a/src/third_party/angle/src/common/winrt/windowadapter.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// winrt/windowadapter.cpp: WinRT specific window utility functionality
-#include "windowadapter.h"
-
-#include <dxgi1_2.h>
-
-#include "common/debug.h"
-
-using namespace Microsoft::WRL;
-using namespace Windows::UI::Core;
-
-namespace egl
-{
-
-typedef RuntimeClass<RuntimeClassFlags<ClassicCom>, IWindowAdapter> WindowAdapterBase;
-
-class WindowAdapter : public WindowAdapterBase
-{
-  public:
-    WindowAdapter(ComPtr<IUnknown> window, AngleWindowType type);
-
-    // IWindowAdapter methods
-    virtual HRESULT GetType(AngleWindowType *type) override;
-    virtual HRESULT GetWindow(IUnknown **ptr) override;
-
-  protected:
-    virtual ~WindowAdapter() {}
-
-  private:
-    AngleWindowType mWindowType;
-    ComPtr<IUnknown> mWindow;
-};
-
-WindowAdapter::WindowAdapter(ComPtr<IUnknown> window, AngleWindowType type)
-    : mWindowType(type)
-    , mWindow(window)
-{
-}
-
-HRESULT WindowAdapter::GetType(AngleWindowType *type)
-{
-    if (mWindowType < 0 || mWindowType >= AWT_NUM_TYPES)
-        return E_FAIL;
-
-    *type = mWindowType;
-    return S_OK;
-}
-
-HRESULT WindowAdapter::GetWindow(IUnknown **ptr)
-{
-    *ptr = mWindow.Get();
-    if (*ptr)
-        (*ptr)->AddRef();
-
-    return S_OK;
-}
-
-IWindowAdapter::Ptr createWindowAdapter(EGLNativeWindowType window)
-{
-    if (window == nullptr)
-        return nullptr;
-
-    ComPtr<IUnknown> unk(window);
-
-    // Try a trivial conversion first
-    IWindowAdapter::Ptr adapter;
-    if (SUCCEEDED(unk.As(&adapter)))
-        return adapter;
-
-    // Check if this is a CoreWindow
-    ComPtr<WindowAdapterABIType<CoreWindow>::Type> coreWindow;
-    if (SUCCEEDED(unk.As(&coreWindow)))
-        return Make<WindowAdapter>(unk, AWT_COREWINDOW);
-
-    // Check if this is a DXGI swapchain adapter
-    ComPtr<ISwapChainAdapter> swapChainAdapter;
-    if (SUCCEEDED(unk.As(&swapChainAdapter)))
-      return Make<WindowAdapter>(unk, AWT_SWAPCHAIN_ADAPTER);
-
-    return nullptr;
-}
-
-bool verifyWindowAccessible(IWindowAdapter::Ptr windowAdapter)
-{
-    if (windowAdapter == nullptr)
-        return false;
-
-    AngleWindowType windowType;
-    if (FAILED(windowAdapter->GetType(&windowType)))
-        return false;
-
-    if (windowType == AWT_COREWINDOW)
-    {
-        CoreWindow^ coreWindow;
-        windowAdapter->GetWindowAsWinRT(&coreWindow);
-        if (coreWindow != CoreWindow::GetForCurrentThread())
-        {
-            ERR("CoreWindow doesn't belong to the current thread,"
-                "was the function called from the matching UI thread?");
-            return false;
-        }
-    }
-
-    return true;
-}
-
-} // namespace egl
diff --git a/src/third_party/angle/src/common/winrt/windowadapter.h b/src/third_party/angle/src/common/winrt/windowadapter.h
deleted file mode 100644
index 2977e6c..0000000
--- a/src/third_party/angle/src/common/winrt/windowadapter.h
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// winrt/windowadapter.h: ANGLE window adapter
-
-#ifndef COMMON_WINRT_WINDOWADAPTER_H_
-#define COMMON_WINRT_WINDOWADAPTER_H_
-
-#include <wrl.h>
-
-#include <Windows.UI.Core.h>  // ABI interface for CoreWindow
-
-#include "common/windowutils.h"
-
-struct IDXGISwapChain;
-
-namespace egl
-{
-
-enum AngleWindowType
-{
-    // Do not reorganize to stay compatible with older versions
-    AWT_COREWINDOW = 0,
-    AWT_SWAPCHAIN_ADAPTER = 1,
-
-    AWT_NUM_TYPES,
-};
-
-// The following template is used to map between Windows Runtime classes
-// and their ABI couterparts
-template <typename WinRT_T>
-struct WindowAdapterABIType;
-
-template <>
-struct WindowAdapterABIType<Windows::UI::Core::CoreWindow>
-{
-    typedef ABI::Windows::UI::Core::ICoreWindow Type;
-};
-
-MIDL_INTERFACE("1C9CC283-C168-447A-B11A-98EF5D294EAE")
-IWindowAdapter : public IUnknown
-{
-    typedef Microsoft::WRL::ComPtr<IWindowAdapter> Ptr;
-
-    virtual HRESULT GetType(AngleWindowType *type) = 0;
-    virtual HRESULT GetWindow(IUnknown **ptr) = 0;
-
-    template <typename Interface_T>
-    HRESULT GetWindowAs(Interface_T **ptr)
-    {
-        IUnknown *unk = nullptr;
-        HRESULT hr = GetWindow(&unk);
-
-        if (SUCCEEDED(hr))
-            hr = unk->QueryInterface(ptr);
-
-        if (unk)
-            unk->Release();
-
-        return hr;
-    }
-
-    template <typename WinRT_T>
-    HRESULT GetWindowAsWinRT(WinRT_T^* winrtPtr)
-    {
-        typedef WindowAdapterABIType<WinRT_T>::Type ABIType;
-
-        Microsoft::WRL::ComPtr<ABIType> ptr;
-        HRESULT hr = GetWindowAs(ptr.GetAddressOf());
-        if (FAILED(hr))
-            return hr;
-
-        *winrtPtr = reinterpret_cast<WinRT_T ^>(ptr.Get());
-        return hr;
-    }
-};
-
-MIDL_INTERFACE("AF0D1922-B84D-4443-9D04-980E7476B16F")
-ISwapChainAdapter : public IUnknown
-{
-    virtual void GetSwapChain(Microsoft::WRL::ComPtr<IDXGISwapChain>* swapChain) = 0;
-    virtual void GetWindowSize(INT32* width, INT32* height) = 0;
-};
-
-IWindowAdapter::Ptr createWindowAdapter(EGLNativeWindowType window);
-
-bool verifyWindowAccessible(IWindowAdapter::Ptr windowAdapter);
-
-} // namespace egl
-
-#endif // COMMON_WINRT_WINDOWADAPTER_H_
diff --git a/src/third_party/angle/src/common/winrt/windowutils.cpp b/src/third_party/angle/src/common/winrt/windowutils.cpp
deleted file mode 100644
index e0ee162..0000000
--- a/src/third_party/angle/src/common/winrt/windowutils.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// winrt/windowutils.cpp: WinRT specific window utility functionality
-#include "common/windowutils.h"
-
-#include "common/debug.h"
-#include "common/winrt/windowadapter.h"
-
-namespace egl
-{
-
-bool verifyWindowAccessible(EGLNativeWindowType window)
-{
-    return verifyWindowAccessible(createWindowAdapter(window));
-}
-
-} // namespace egl
diff --git a/src/third_party/angle/src/common/winrt/windowutils.h b/src/third_party/angle/src/common/winrt/windowutils.h
deleted file mode 100644
index 12e695d..0000000
--- a/src/third_party/angle/src/common/winrt/windowutils.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// windowutils.h: ANGLE window specific utilities.
-
-#ifndef COMMON_WINDOWUTILS_H_
-#define COMMON_WINDOWUTILS_H_
-
-#include "common/system.h"
-
-namespace egl
-{
-
-// Check if the given window is valid and verify that it can be accessed
-// by the caller. This is particularly important in APIs like WinRT where
-// a window can be directly used only from the owning UI thread
-bool verifyWindowAccessible(EGLNativeWindowType window);
-
-} // namespace egl
-
-#endif // COMMON_WINDOWUTILS_H_
diff --git a/src/third_party/angle/src/compiler.gypi b/src/third_party/angle/src/compiler.gypi
new file mode 100644
index 0000000..ffa39d6
--- /dev/null
+++ b/src/third_party/angle/src/compiler.gypi
@@ -0,0 +1,365 @@
+# Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'variables':
+    {
+        # These file lists are shared with the GN build.
+        'angle_translator_sources':
+        [
+            '<(DEPTH)/third_party/angle/include/EGL/egl.h',
+            '<(DEPTH)/third_party/angle/include/EGL/eglext.h',
+            '<(DEPTH)/third_party/angle/include/EGL/eglplatform.h',
+            '<(DEPTH)/third_party/angle/include/GLES2/gl2.h',
+            '<(DEPTH)/third_party/angle/include/GLES2/gl2ext.h',
+            '<(DEPTH)/third_party/angle/include/GLES2/gl2platform.h',
+            '<(DEPTH)/third_party/angle/include/GLES3/gl3.h',
+            '<(DEPTH)/third_party/angle/include/GLES3/gl3platform.h',
+            '<(DEPTH)/third_party/angle/include/GLES3/gl31.h',
+            '<(DEPTH)/third_party/angle/include/GLES3/gl32.h',
+            '<(DEPTH)/third_party/angle/include/GLSLANG/ShaderLang.h',
+            '<(DEPTH)/third_party/angle/include/GLSLANG/ShaderVars.h',
+            '<(DEPTH)/third_party/angle/include/KHR/khrplatform.h',
+            '<(DEPTH)/third_party/angle/include/angle_gl.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/AddAndTrueToLoopCondition.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/BaseTypes.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/BuiltInFunctionEmulator.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Cache.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Cache.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/CallDAG.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/CallDAG.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/CodeGen.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Common.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Compiler.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Compiler.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ConstantUnion.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ConstantUnion.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/DeferGlobalInitializers.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/DeferGlobalInitializers.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Diagnostics.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Diagnostics.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/DirectiveHandler.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/DirectiveHandler.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/EmulatePrecision.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/EmulatePrecision.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ExpandIntegerPowExpressions.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ExtensionBehavior.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/FindMain.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/FindMain.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/FindSymbolNode.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/FindSymbolNode.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/FlagStd140Structs.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/FlagStd140Structs.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/HashNames.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/InfoSink.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/InfoSink.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Initialize.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Initialize.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/InitializeDll.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/InitializeDll.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/InitializeGlobals.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/InitializeVariables.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/InitializeVariables.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/IntermNode.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/IntermNode.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/IntermTraverse.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Intermediate.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Intermediate.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/NodeSearch.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Operator.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Operator.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ParseContext.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ParseContext.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/PoolAlloc.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/PoolAlloc.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Pragma.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/PruneEmptyDeclarations.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/PruneEmptyDeclarations.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/PrunePureLiteralStatements.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/PrunePureLiteralStatements.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/QualifierTypes.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/QualifierTypes.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RecordConstantPrecision.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RecordConstantPrecision.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RegenerateStructNames.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RegenerateStructNames.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RemoveInvariantDeclaration.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RemovePow.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RemovePow.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteDoWhile.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteDoWhile.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteTexelFetchOffset.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SearchSymbol.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SearchSymbol.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Severity.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ShaderLang.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ShaderVars.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SymbolTable.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SymbolTable.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Types.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/Types.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UnfoldShortCircuitAST.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UseInterfaceBlockFields.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UseInterfaceBlockFields.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateGlobalInitializer.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateGlobalInitializer.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateLimitations.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateLimitations.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateMaxParameters.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateMaxParameters.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateMultiviewWebGL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateMultiviewWebGL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateOutputs.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateOutputs.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateSwitch.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ValidateSwitch.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/VariableInfo.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/VariableInfo.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/VariablePacker.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/VariablePacker.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/blocklayout.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/blocklayout.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/glslang.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/glslang.l',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/glslang.y',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/glslang_lex.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/glslang_tab.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/glslang_tab.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/intermOut.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/length_limits.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/util.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/util.h',
+            '<(DEPTH)/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.cpp',
+            '<(DEPTH)/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.h',
+        ],
+        'angle_translator_essl_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputESSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputESSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TranslatorESSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TranslatorESSL.h',
+        ],
+        'angle_translator_glsl_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ExtensionGLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ExtensionGLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputGLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputGLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputGLSLBase.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputGLSLBase.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TranslatorGLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TranslatorGLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/VersionGLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/VersionGLSL.h',
+        ],
+        'angle_translator_hlsl_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/compiler/translator/AddDefaultReturnStatements.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/AddDefaultReturnStatements.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ASTMetadataHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/ASTMetadataHLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/blocklayoutHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/blocklayoutHLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/IntermNodePatternMatcher.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/IntermNodePatternMatcher.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputHLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RemoveDynamicIndexing.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RemoveDynamicIndexing.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RemoveSwitchFallThrough.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteElseBlocks.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/RewriteElseBlocks.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SeparateArrayInitialization.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SeparateArrayInitialization.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SeparateDeclarations.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SeparateDeclarations.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SimplifyLoopConditions.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SimplifyLoopConditions.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SplitSequenceOperator.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/SplitSequenceOperator.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/StructureHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/StructureHLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TextureFunctionHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TextureFunctionHLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TranslatorHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TranslatorHLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UnfoldShortCircuitToIf.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UniformHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UniformHLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UtilsHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/UtilsHLSL.h',
+        ],
+        'angle_translator_lib_vulkan_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputVulkanGLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/OutputVulkanGLSL.h',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TranslatorVulkan.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/translator/TranslatorVulkan.h',
+        ],
+        'angle_preprocessor_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/DirectiveParser.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/DirectiveParser.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/ExpressionParser.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/ExpressionParser.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/ExpressionParser.y',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Input.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Input.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Lexer.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Lexer.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Macro.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Macro.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/MacroExpander.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/MacroExpander.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Preprocessor.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Preprocessor.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/SourceLocation.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Token.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Token.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Tokenizer.cpp',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Tokenizer.h',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/Tokenizer.l',
+            '<(DEPTH)/third_party/angle/src/compiler/preprocessor/numeric_lex.h',
+        ],
+    },
+    # Everything below this is duplicated in the GN build. If you change
+    # anything also change angle/BUILD.gn
+    'targets':
+    [
+        {
+            'target_name': 'preprocessor',
+            'type': 'static_library',
+            'dependencies': [ 'angle_common' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources': [ '<@(angle_preprocessor_sources)', ],
+        },
+        {
+            'target_name': 'translator',
+            'type': 'static_library',
+            'dependencies': [ 'preprocessor', 'angle_common' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'include_dirs':
+            [
+                '<(DEPTH)/third_party/angle/include',
+                '<(DEPTH)/third_party/angle/src',
+            ],
+            'sources':
+            [
+                '<@(angle_translator_sources)',
+            ],
+            'msvs_settings':
+            {
+              'VCLibrarianTool':
+              {
+                'AdditionalOptions': ['/ignore:4221']
+              },
+            },
+            'conditions':
+            [
+                ['angle_enable_essl==1',
+                {
+                    'defines':
+                    [
+                        'ANGLE_ENABLE_ESSL',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_ESSL',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(angle_translator_essl_sources)',
+                    ],
+                }],
+                ['angle_enable_glsl==1',
+                {
+                    'defines':
+                    [
+                        'ANGLE_ENABLE_GLSL',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_GLSL',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(angle_translator_glsl_sources)',
+                    ],
+                }],
+                ['angle_enable_hlsl==1',
+                {
+                    'defines':
+                    [
+                        'ANGLE_ENABLE_HLSL',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_HLSL',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(angle_translator_hlsl_sources)',
+                    ],
+                }],
+                ['angle_enable_vulkan==1',
+                {
+                    'defines':
+                    [
+                        'ANGLE_ENABLE_VULKAN',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_VULKAN',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(angle_translator_lib_vulkan_sources)',
+                    ],
+                }],
+            ],
+        },
+    ],
+}
diff --git a/src/third_party/angle/src/compiler/64bit-lexer-safety.patch b/src/third_party/angle/src/compiler/64bit-lexer-safety.patch
deleted file mode 100644
index 7af91f5..0000000
--- a/src/third_party/angle/src/compiler/64bit-lexer-safety.patch
+++ /dev/null
@@ -1,177 +0,0 @@
---- a/src/compiler/glslang_lex.cpp
-+++ b/src/compiler/glslang_lex.cpp
-@@ -68,6 +68,7 @@ typedef int16_t flex_int16_t;
- typedef uint16_t flex_uint16_t;
- typedef int32_t flex_int32_t;
- typedef uint32_t flex_uint32_t;
-+typedef uint64_t flex_uint64_t;
- #else
- typedef signed char flex_int8_t;
- typedef short int flex_int16_t;
-@@ -191,6 +192,11 @@ typedef void* yyscan_t;
- typedef struct yy_buffer_state *YY_BUFFER_STATE;
- #endif
- 
-+#ifndef YY_TYPEDEF_YY_SIZE_T
-+#define YY_TYPEDEF_YY_SIZE_T
-+typedef size_t yy_size_t;
-+#endif
-+
- #define EOB_ACT_CONTINUE_SCAN 0
- #define EOB_ACT_END_OF_FILE 1
- #define EOB_ACT_LAST_MATCH 2
-@@ -204,7 +210,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
-      */
-     #define  YY_LESS_LINENO(n) \
-             do { \
--                int yyl;\
-+                yy_size_t yyl;\
-                 for ( yyl = n; yyl < yyleng; ++yyl )\
-                     if ( yytext[yyl] == '\n' )\
-                         --yylineno;\
-@@ -226,11 +232,6 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
- 
- #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
- 
--#ifndef YY_TYPEDEF_YY_SIZE_T
--#define YY_TYPEDEF_YY_SIZE_T
--typedef size_t yy_size_t;
--#endif
--
- #ifndef YY_STRUCT_YY_BUFFER_STATE
- #define YY_STRUCT_YY_BUFFER_STATE
- struct yy_buffer_state
-@@ -248,7 +249,7 @@ struct yy_buffer_state
- 	/* Number of characters read into yy_ch_buf, not including EOB
- 	 * characters.
- 	 */
--	int yy_n_chars;
-+	yy_size_t yy_n_chars;
- 
- 	/* Whether we "own" the buffer - i.e., we know we created it,
- 	 * and can realloc() it to grow it, and should free() it to
-@@ -327,7 +328,7 @@ static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
- 
- YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
- YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
--YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
- 
- void *yyalloc (yy_size_t ,yyscan_t yyscanner );
- void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-@@ -378,7 +379,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
-  */
- #define YY_DO_BEFORE_ACTION \
- 	yyg->yytext_ptr = yy_bp; \
--	yyleng = (size_t) (yy_cp - yy_bp); \
-+	yyleng = (yy_size_t) (yy_cp - yy_bp); \
- 	yyg->yy_hold_char = *yy_cp; \
- 	*yy_cp = '\0'; \
- 	yyg->yy_c_buf_p = yy_cp;
-@@ -1035,8 +1036,8 @@ struct yyguts_t
-     size_t yy_buffer_stack_max; /**< capacity of stack. */
-     YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
-     char yy_hold_char;
--    int yy_n_chars;
--    int yyleng_r;
-+    yy_size_t yy_n_chars;
-+    yy_size_t yyleng_r;
-     char *yy_c_buf_p;
-     int yy_init;
-     int yy_start;
-@@ -1089,7 +1090,7 @@ FILE *yyget_out (yyscan_t yyscanner );
- 
- void yyset_out  (FILE * out_str ,yyscan_t yyscanner );
- 
--int yyget_leng (yyscan_t yyscanner );
-+yy_size_t yyget_leng (yyscan_t yyscanner );
- 
- char *yyget_text (yyscan_t yyscanner );
- 
-@@ -1158,7 +1159,7 @@ static int input (yyscan_t yyscanner );
- 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
- 		{ \
- 		int c = '*'; \
--		int n; \
-+		yy_size_t n; \
- 		for ( n = 0; n < max_size && \
- 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
- 			buf[n] = (char) c; \
-@@ -1317,7 +1318,7 @@ yy_find_action:
- 
- 		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
- 			{
--			int yyl;
-+			yy_size_t yyl;
- 			for ( yyl = 0; yyl < yyleng; ++yyl )
- 				if ( yytext[yyl] == '\n' )
- 					   
-@@ -2203,7 +2204,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
- 
- 	else
- 		{
--			int num_to_read =
-+			yy_size_t num_to_read =
- 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
- 
- 		while ( num_to_read <= 0 )
-@@ -2217,7 +2218,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
- 
- 			if ( b->yy_is_our_buffer )
- 				{
--				int new_size = b->yy_buf_size * 2;
-+				yy_size_t new_size = b->yy_buf_size * 2;
- 
- 				if ( new_size <= 0 )
- 					b->yy_buf_size += b->yy_buf_size / 8;
-@@ -2248,7 +2249,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
- 
- 		/* Read in more data. */
- 		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
--			yyg->yy_n_chars, (size_t) num_to_read );
-+			yyg->yy_n_chars, num_to_read );
- 
- 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
- 		}
-@@ -2373,7 +2374,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
- 
- 		else
- 			{ /* need more input */
--			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
-+			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
- 			++yyg->yy_c_buf_p;
- 
- 			switch ( yy_get_next_buffer( yyscanner ) )
-@@ -2660,7 +2661,7 @@ void yypop_buffer_state (yyscan_t yyscanner)
-  */
- static void yyensure_buffer_stack (yyscan_t yyscanner)
- {
--	int num_to_alloc;
-+	yy_size_t num_to_alloc;
-     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- 
- 	if (!yyg->yy_buffer_stack) {
-@@ -2758,12 +2759,11 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-  * @param yyscanner The scanner object.
-  * @return the newly allocated buffer state object.
-  */
--YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
-+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
- {
- 	YY_BUFFER_STATE b;
- 	char *buf;
--	yy_size_t n;
--	int i;
-+	yy_size_t n, i;
-     
- 	/* Get memory for full buffer, including space for trailing EOB's. */
- 	n = _yybytes_len + 2;
-@@ -2913,7 +2913,7 @@ FILE *yyget_out  (yyscan_t yyscanner)
- /** Get the length of the current token.
-  * @param yyscanner The scanner object.
-  */
--int yyget_leng  (yyscan_t yyscanner)
-+yy_size_t yyget_leng  (yyscan_t yyscanner)
- {
-     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-     return yyleng;
diff --git a/src/third_party/angle/src/compiler/BaseTypes.h b/src/third_party/angle/src/compiler/BaseTypes.h
deleted file mode 100644
index 1631f4f..0000000
--- a/src/third_party/angle/src/compiler/BaseTypes.h
+++ /dev/null
@@ -1,148 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _BASICTYPES_INCLUDED_
-#define _BASICTYPES_INCLUDED_
-
-//
-// Precision qualifiers
-//
-enum TPrecision
-{
-    // These need to be kept sorted
-    EbpUndefined,
-    EbpLow,
-    EbpMedium,
-    EbpHigh
-};
-
-inline const char* getPrecisionString(TPrecision p)
-{
-    switch(p)
-    {
-    case EbpHigh:		return "highp";		break;
-    case EbpMedium:		return "mediump";	break;
-    case EbpLow:		return "lowp";		break;
-    default:			return "mediump";   break;   // Safest fallback
-    }
-}
-
-//
-// Basic type.  Arrays, vectors, etc., are orthogonal to this.
-//
-enum TBasicType
-{
-    EbtVoid,
-    EbtFloat,
-    EbtInt,
-    EbtBool,
-    EbtGuardSamplerBegin,  // non type:  see implementation of IsSampler()
-    EbtSampler2D,
-    EbtSamplerCube,
-    EbtSamplerExternalOES,  // Only valid if OES_EGL_image_external exists.
-    EbtSampler2DRect,       // Only valid if GL_ARB_texture_rectangle exists.
-    EbtGuardSamplerEnd,    // non type:  see implementation of IsSampler()
-    EbtStruct,
-    EbtAddress,            // should be deprecated??
-    EbtInvariant          // used as a type when qualifying a previously declared variable as being invariant
-};
-
-inline const char* getBasicString(TBasicType t)
-{
-    switch (t)
-    {
-    case EbtVoid:              return "void";              break;
-    case EbtFloat:             return "float";             break;
-    case EbtInt:               return "int";               break;
-    case EbtBool:              return "bool";              break;
-    case EbtSampler2D:         return "sampler2D";         break;
-    case EbtSamplerCube:       return "samplerCube";       break;
-    case EbtSamplerExternalOES: return "samplerExternalOES"; break;
-    case EbtSampler2DRect:     return "sampler2DRect";     break;
-    case EbtStruct:            return "structure";         break;
-    default:                   return "unknown type";
-    }
-}
-
-inline bool IsSampler(TBasicType type)
-{
-    return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
-}
-
-//
-// Qualifiers and built-ins.  These are mainly used to see what can be read
-// or written, and by the machine dependent translator to know which registers
-// to allocate variables in.  Since built-ins tend to go to different registers
-// than varying or uniform, it makes sense they are peers, not sub-classes.
-//
-enum TQualifier
-{
-    EvqTemporary,     // For temporaries (within a function), read/write
-    EvqGlobal,        // For globals read/write
-    EvqConst,         // User defined constants and non-output parameters in functions
-    EvqAttribute,     // Readonly
-    EvqVaryingIn,     // readonly, fragment shaders only
-    EvqVaryingOut,    // vertex shaders only  read/write
-    EvqInvariantVaryingIn,     // readonly, fragment shaders only
-    EvqInvariantVaryingOut,    // vertex shaders only  read/write
-    EvqUniform,       // Readonly, vertex and fragment
-
-    // parameters
-    EvqIn,
-    EvqOut,
-    EvqInOut,
-    EvqConstReadOnly,
-
-    // built-ins written by vertex shader
-    EvqPosition,
-    EvqPointSize,
-
-    // built-ins read by fragment shader
-    EvqFragCoord,
-    EvqFrontFacing,
-    EvqPointCoord,
-
-    // built-ins written by fragment shader
-    EvqFragColor,
-    EvqFragData,
-    EvqFragDepth,
-
-    // end of list
-    EvqLast
-};
-
-//
-// This is just for debug print out, carried along with the definitions above.
-//
-inline const char* getQualifierString(TQualifier q)
-{
-    switch(q)
-    {
-    case EvqTemporary:      return "Temporary";      break;
-    case EvqGlobal:         return "Global";         break;
-    case EvqConst:          return "const";          break;
-    case EvqConstReadOnly:  return "const";          break;
-    case EvqAttribute:      return "attribute";      break;
-    case EvqVaryingIn:      return "varying";        break;
-    case EvqVaryingOut:     return "varying";        break;
-    case EvqInvariantVaryingIn: return "invariant varying";	break;
-    case EvqInvariantVaryingOut:return "invariant varying";	break;
-    case EvqUniform:        return "uniform";        break;
-    case EvqIn:             return "in";             break;
-    case EvqOut:            return "out";            break;
-    case EvqInOut:          return "inout";          break;
-    case EvqPosition:       return "Position";       break;
-    case EvqPointSize:      return "PointSize";      break;
-    case EvqFragCoord:      return "FragCoord";      break;
-    case EvqFrontFacing:    return "FrontFacing";    break;
-    case EvqFragColor:      return "FragColor";      break;
-    case EvqFragData:       return "FragData";      break;
-    case EvqFragDepth:      return "FragDepth";     break;
-    default:                return "unknown qualifier";
-    }
-}
-
-#endif // _BASICTYPES_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/BuiltInFunctionEmulator.cpp b/src/third_party/angle/src/compiler/BuiltInFunctionEmulator.cpp
deleted file mode 100644
index 1c4b25f..0000000
--- a/src/third_party/angle/src/compiler/BuiltInFunctionEmulator.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/BuiltInFunctionEmulator.h"
-
-#include "compiler/SymbolTable.h"
-
-namespace {
-
-// we use macros here instead of function definitions to work around more GLSL
-// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
-// problematic because if the argument has side-effects they will be repeatedly
-// evaluated. This is unlikely to show up in real shaders, but is something to
-// consider.
-const char* kFunctionEmulationVertexSource[] = {
-    "#error no emulation for cos(float)",
-    "#error no emulation for cos(vec2)",
-    "#error no emulation for cos(vec3)",
-    "#error no emulation for cos(vec4)",
-
-    "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
-    "#error no emulation for distance(vec2, vec2)",
-    "#error no emulation for distance(vec3, vec3)",
-    "#error no emulation for distance(vec4, vec4)",
-
-    "#define webgl_dot_emu(x, y) ((x) * (y))",
-    "#error no emulation for dot(vec2, vec2)",
-    "#error no emulation for dot(vec3, vec3)",
-    "#error no emulation for dot(vec4, vec4)",
-
-    "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
-    "#error no emulation for length(vec2)",
-    "#error no emulation for length(vec3)",
-    "#error no emulation for length(vec4)",
-
-    "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
-    "#error no emulation for normalize(vec2)",
-    "#error no emulation for normalize(vec3)",
-    "#error no emulation for normalize(vec4)",
-
-    "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
-    "#error no emulation for reflect(vec2, vec2)",
-    "#error no emulation for reflect(vec3, vec3)",
-    "#error no emulation for reflect(vec4, vec4)"
-};
-
-const char* kFunctionEmulationFragmentSource[] = {
-    "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }",
-    "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }",
-    "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }",
-    "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }",
-
-    "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
-    "#error no emulation for distance(vec2, vec2)",
-    "#error no emulation for distance(vec3, vec3)",
-    "#error no emulation for distance(vec4, vec4)",
-
-    "#define webgl_dot_emu(x, y) ((x) * (y))",
-    "#error no emulation for dot(vec2, vec2)",
-    "#error no emulation for dot(vec3, vec3)",
-    "#error no emulation for dot(vec4, vec4)",
-
-    "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
-    "#error no emulation for length(vec2)",
-    "#error no emulation for length(vec3)",
-    "#error no emulation for length(vec4)",
-
-    "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
-    "#error no emulation for normalize(vec2)",
-    "#error no emulation for normalize(vec3)",
-    "#error no emulation for normalize(vec4)",
-
-    "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
-    "#error no emulation for reflect(vec2, vec2)",
-    "#error no emulation for reflect(vec3, vec3)",
-    "#error no emulation for reflect(vec4, vec4)"
-};
-
-const bool kFunctionEmulationVertexMask[] = {
-#if defined(__APPLE__)
-    // Work around ATI driver bugs in Mac.
-    false, // TFunctionCos1
-    false, // TFunctionCos2
-    false, // TFunctionCos3
-    false, // TFunctionCos4
-    true,  // TFunctionDistance1_1
-    false, // TFunctionDistance2_2
-    false, // TFunctionDistance3_3
-    false, // TFunctionDistance4_4
-    true,  // TFunctionDot1_1
-    false, // TFunctionDot2_2
-    false, // TFunctionDot3_3
-    false, // TFunctionDot4_4
-    true,  // TFunctionLength1
-    false, // TFunctionLength2
-    false, // TFunctionLength3
-    false, // TFunctionLength4
-    true,  // TFunctionNormalize1
-    false, // TFunctionNormalize2
-    false, // TFunctionNormalize3
-    false, // TFunctionNormalize4
-    true,  // TFunctionReflect1_1
-    false, // TFunctionReflect2_2
-    false, // TFunctionReflect3_3
-    false, // TFunctionReflect4_4
-#else
-    // Work around D3D driver bug in Win.
-    false, // TFunctionCos1
-    false, // TFunctionCos2
-    false, // TFunctionCos3
-    false, // TFunctionCos4
-    false, // TFunctionDistance1_1
-    false, // TFunctionDistance2_2
-    false, // TFunctionDistance3_3
-    false, // TFunctionDistance4_4
-    false, // TFunctionDot1_1
-    false, // TFunctionDot2_2
-    false, // TFunctionDot3_3
-    false, // TFunctionDot4_4
-    false, // TFunctionLength1
-    false, // TFunctionLength2
-    false, // TFunctionLength3
-    false, // TFunctionLength4
-    false, // TFunctionNormalize1
-    false, // TFunctionNormalize2
-    false, // TFunctionNormalize3
-    false, // TFunctionNormalize4
-    false, // TFunctionReflect1_1
-    false, // TFunctionReflect2_2
-    false, // TFunctionReflect3_3
-    false, // TFunctionReflect4_4
-#endif
-    false  // TFunctionUnknown
-};
-
-const bool kFunctionEmulationFragmentMask[] = {
-#if defined(__APPLE__)
-    // Work around ATI driver bugs in Mac.
-    true,  // TFunctionCos1
-    true,  // TFunctionCos2
-    true,  // TFunctionCos3
-    true,  // TFunctionCos4
-    true,  // TFunctionDistance1_1
-    false, // TFunctionDistance2_2
-    false, // TFunctionDistance3_3
-    false, // TFunctionDistance4_4
-    true,  // TFunctionDot1_1
-    false, // TFunctionDot2_2
-    false, // TFunctionDot3_3
-    false, // TFunctionDot4_4
-    true,  // TFunctionLength1
-    false, // TFunctionLength2
-    false, // TFunctionLength3
-    false, // TFunctionLength4
-    true,  // TFunctionNormalize1
-    false, // TFunctionNormalize2
-    false, // TFunctionNormalize3
-    false, // TFunctionNormalize4
-    true,  // TFunctionReflect1_1
-    false, // TFunctionReflect2_2
-    false, // TFunctionReflect3_3
-    false, // TFunctionReflect4_4
-#else
-    // Work around D3D driver bug in Win.
-    false, // TFunctionCos1
-    false, // TFunctionCos2
-    false, // TFunctionCos3
-    false, // TFunctionCos4
-    false, // TFunctionDistance1_1
-    false, // TFunctionDistance2_2
-    false, // TFunctionDistance3_3
-    false, // TFunctionDistance4_4
-    false, // TFunctionDot1_1
-    false, // TFunctionDot2_2
-    false, // TFunctionDot3_3
-    false, // TFunctionDot4_4
-    false, // TFunctionLength1
-    false, // TFunctionLength2
-    false, // TFunctionLength3
-    false, // TFunctionLength4
-    false, // TFunctionNormalize1
-    false, // TFunctionNormalize2
-    false, // TFunctionNormalize3
-    false, // TFunctionNormalize4
-    false, // TFunctionReflect1_1
-    false, // TFunctionReflect2_2
-    false, // TFunctionReflect3_3
-    false, // TFunctionReflect4_4
-#endif
-    false  // TFunctionUnknown
-};
-
-class BuiltInFunctionEmulationMarker : public TIntermTraverser {
-public:
-    BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator)
-        : mEmulator(emulator)
-    {
-    }
-
-    virtual bool visitUnary(Visit visit, TIntermUnary* node)
-    {
-        if (visit == PreVisit) {
-            bool needToEmulate = mEmulator.SetFunctionCalled(
-                node->getOp(), node->getOperand()->getType());
-            if (needToEmulate)
-                node->setUseEmulatedFunction();
-        }
-        return true;
-    }
-
-    virtual bool visitAggregate(Visit visit, TIntermAggregate* node)
-    {
-        if (visit == PreVisit) {
-            // Here we handle all the built-in functions instead of the ones we
-            // currently identified as problematic.
-            switch (node->getOp()) {
-                case EOpLessThan:
-                case EOpGreaterThan:
-                case EOpLessThanEqual:
-                case EOpGreaterThanEqual:
-                case EOpVectorEqual:
-                case EOpVectorNotEqual:
-                case EOpMod:
-                case EOpPow:
-                case EOpAtan:
-                case EOpMin:
-                case EOpMax:
-                case EOpClamp:
-                case EOpMix:
-                case EOpStep:
-                case EOpSmoothStep:
-                case EOpDistance:
-                case EOpDot:
-                case EOpCross:
-                case EOpFaceForward:
-                case EOpReflect:
-                case EOpRefract:
-                case EOpMul:
-                    break;
-                default:
-                    return true;
-            };
-            const TIntermSequence& sequence = node->getSequence();
-            // Right now we only handle built-in functions with two parameters.
-            if (sequence.size() != 2)
-                return true;
-            TIntermTyped* param1 = sequence[0]->getAsTyped();
-            TIntermTyped* param2 = sequence[1]->getAsTyped();
-            if (!param1 || !param2)
-                return true;
-            bool needToEmulate = mEmulator.SetFunctionCalled(
-                node->getOp(), param1->getType(), param2->getType());
-            if (needToEmulate)
-                node->setUseEmulatedFunction();
-        }
-        return true;
-    }
-
-private:
-    BuiltInFunctionEmulator& mEmulator;
-};
-
-}  // anonymous namepsace
-
-BuiltInFunctionEmulator::BuiltInFunctionEmulator(ShShaderType shaderType)
-{
-    if (shaderType == SH_FRAGMENT_SHADER) {
-        mFunctionMask = kFunctionEmulationFragmentMask;
-        mFunctionSource = kFunctionEmulationFragmentSource;
-    } else {
-        mFunctionMask = kFunctionEmulationVertexMask;
-        mFunctionSource = kFunctionEmulationVertexSource;
-    }
-}
-
-bool BuiltInFunctionEmulator::SetFunctionCalled(
-    TOperator op, const TType& param)
-{
-    TBuiltInFunction function = IdentifyFunction(op, param);
-    return SetFunctionCalled(function);
-}
-
-bool BuiltInFunctionEmulator::SetFunctionCalled(
-    TOperator op, const TType& param1, const TType& param2)
-{
-    TBuiltInFunction function = IdentifyFunction(op, param1, param2);
-    return SetFunctionCalled(function);
-}
-
-bool BuiltInFunctionEmulator::SetFunctionCalled(
-    BuiltInFunctionEmulator::TBuiltInFunction function) {
-    if (function == TFunctionUnknown || mFunctionMask[function] == false)
-        return false;
-    for (size_t i = 0; i < mFunctions.size(); ++i) {
-        if (mFunctions[i] == function)
-            return true;
-    }
-    mFunctions.push_back(function);
-    return true;
-}
-
-void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition(
-    TInfoSinkBase& out, bool withPrecision) const
-{
-    if (mFunctions.size() == 0)
-        return;
-    out << "// BEGIN: Generated code for built-in function emulation\n\n";
-    if (withPrecision) {
-        out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
-            << "#define webgl_emu_precision highp\n"
-            << "#else\n"
-            << "#define webgl_emu_precision mediump\n"
-            << "#endif\n\n";
-    } else {
-        out << "#define webgl_emu_precision\n\n";
-    }
-    for (size_t i = 0; i < mFunctions.size(); ++i) {
-        out << mFunctionSource[mFunctions[i]] << "\n\n";
-    }
-    out << "// END: Generated code for built-in function emulation\n\n";
-}
-
-BuiltInFunctionEmulator::TBuiltInFunction
-BuiltInFunctionEmulator::IdentifyFunction(
-    TOperator op, const TType& param)
-{
-    if (param.getNominalSize() > 4)
-        return TFunctionUnknown;
-    unsigned int function = TFunctionUnknown;
-    switch (op) {
-        case EOpCos:
-            function = TFunctionCos1;
-            break;
-        case EOpLength:
-            function = TFunctionLength1;
-            break;
-        case EOpNormalize:
-            function = TFunctionNormalize1;
-            break;
-        default:
-            break;
-    }
-    if (function == TFunctionUnknown)
-        return TFunctionUnknown;
-    if (param.isVector())
-        function += param.getNominalSize() - 1;
-    return static_cast<TBuiltInFunction>(function);
-}
-
-BuiltInFunctionEmulator::TBuiltInFunction
-BuiltInFunctionEmulator::IdentifyFunction(
-    TOperator op, const TType& param1, const TType& param2)
-{
-    // Right now for all the emulated functions with two parameters, the two
-    // parameters have the same type.
-    if (param1.isVector() != param2.isVector() ||
-        param1.getNominalSize() != param2.getNominalSize() ||
-        param1.getNominalSize() > 4)
-        return TFunctionUnknown;
-
-    unsigned int function = TFunctionUnknown;
-    switch (op) {
-        case EOpDistance:
-            function = TFunctionDistance1_1;
-            break;
-        case EOpDot:
-            function = TFunctionDot1_1;
-            break;
-        case EOpReflect:
-            function = TFunctionReflect1_1;
-            break;
-        default:
-            break;
-    }
-    if (function == TFunctionUnknown)
-        return TFunctionUnknown;
-    if (param1.isVector())
-        function += param1.getNominalSize() - 1;
-    return static_cast<TBuiltInFunction>(function);
-}
-
-void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
-    TIntermNode* root)
-{
-    ASSERT(root);
-
-    BuiltInFunctionEmulationMarker marker(*this);
-    root->traverse(&marker);
-}
-
-void BuiltInFunctionEmulator::Cleanup()
-{
-    mFunctions.clear();
-}
-
-//static
-TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
-    const TString& name)
-{
-    ASSERT(name[name.length() - 1] == '(');
-    return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
-}
-
diff --git a/src/third_party/angle/src/compiler/BuiltInFunctionEmulator.h b/src/third_party/angle/src/compiler/BuiltInFunctionEmulator.h
deleted file mode 100644
index 0d904f4..0000000
--- a/src/third_party/angle/src/compiler/BuiltInFunctionEmulator.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//
-// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
-#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
-
-#include "GLSLANG/ShaderLang.h"
-
-#include "compiler/InfoSink.h"
-#include "compiler/intermediate.h"
-
-//
-// This class decides which built-in functions need to be replaced with the
-// emulated ones.
-// It's only a workaround for OpenGL driver bugs, and isn't needed in general.
-//
-class BuiltInFunctionEmulator {
-public:
-    BuiltInFunctionEmulator(ShShaderType shaderType);
-    // Records that a function is called by the shader and might needs to be
-    // emulated.  If the function's group is not in mFunctionGroupFilter, this
-    // becomes an no-op.
-    // Returns true if the function call needs to be replaced with an emulated
-    // one.
-    bool SetFunctionCalled(TOperator op, const TType& param);
-    bool SetFunctionCalled(
-        TOperator op, const TType& param1, const TType& param2);
-
-    // Output function emulation definition.  This should be before any other
-    // shader source.
-    void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const;
-
-    void MarkBuiltInFunctionsForEmulation(TIntermNode* root);
-
-    void Cleanup();
-
-    // "name(" becomes "webgl_name_emu(".
-    static TString GetEmulatedFunctionName(const TString& name);
-
-private:
-    //
-    // Built-in functions.
-    //
-    enum TBuiltInFunction {
-        TFunctionCos1 = 0,  // float cos(float);
-        TFunctionCos2,  // vec2 cos(vec2);
-        TFunctionCos3,  // vec3 cos(vec3);
-        TFunctionCos4,  // vec4 cos(vec4);
-
-        TFunctionDistance1_1,  // float distance(float, float);
-        TFunctionDistance2_2,  // vec2 distance(vec2, vec2);
-        TFunctionDistance3_3,  // vec3 distance(vec3, vec3);
-        TFunctionDistance4_4,  // vec4 distance(vec4, vec4);
-
-        TFunctionDot1_1,  // float dot(float, float);
-        TFunctionDot2_2,  // vec2 dot(vec2, vec2);
-        TFunctionDot3_3,  // vec3 dot(vec3, vec3);
-        TFunctionDot4_4,  // vec4 dot(vec4, vec4);
-
-        TFunctionLength1,  // float length(float);
-        TFunctionLength2,  // float length(vec2);
-        TFunctionLength3,  // float length(vec3);
-        TFunctionLength4,  // float length(vec4);
-
-        TFunctionNormalize1,  // float normalize(float);
-        TFunctionNormalize2,  // vec2 normalize(vec2);
-        TFunctionNormalize3,  // vec3 normalize(vec3);
-        TFunctionNormalize4,  // vec4 normalize(vec4);
-
-        TFunctionReflect1_1,  // float reflect(float, float);
-        TFunctionReflect2_2,  // vec2 reflect(vec2, vec2);
-        TFunctionReflect3_3,  // vec3 reflect(vec3, vec3);
-        TFunctionReflect4_4,  // vec4 reflect(vec4, vec4);
-
-        TFunctionUnknown
-    };
-
-    TBuiltInFunction IdentifyFunction(TOperator op, const TType& param);
-    TBuiltInFunction IdentifyFunction(
-        TOperator op, const TType& param1, const TType& param2);
-
-    bool SetFunctionCalled(TBuiltInFunction function);
-
-    std::vector<TBuiltInFunction> mFunctions;
-
-    const bool* mFunctionMask;  // a boolean flag for each function.
-    const char** mFunctionSource;
-};
-
-#endif  // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
diff --git a/src/third_party/angle/src/compiler/CodeGenGLSL.cpp b/src/third_party/angle/src/compiler/CodeGenGLSL.cpp
deleted file mode 100644
index 226bf8f..0000000
--- a/src/third_party/angle/src/compiler/CodeGenGLSL.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/TranslatorGLSL.h"
-#include "compiler/TranslatorESSL.h"
-
-//
-// This function must be provided to create the actual
-// compile object used by higher level code.  It returns
-// a subclass of TCompiler.
-//
-TCompiler* ConstructCompiler(
-    ShShaderType type, ShShaderSpec spec, ShShaderOutput output)
-{
-    switch (output) {
-      case SH_GLSL_OUTPUT:
-        return new TranslatorGLSL(type, spec);
-      case SH_ESSL_OUTPUT:
-        return new TranslatorESSL(type, spec);
-      default:
-        return NULL;
-    }
-}
-
-//
-// Delete the compiler made by ConstructCompiler
-//
-void DeleteCompiler(TCompiler* compiler)
-{
-    delete compiler;
-}
diff --git a/src/third_party/angle/src/compiler/CodeGenHLSL.cpp b/src/third_party/angle/src/compiler/CodeGenHLSL.cpp
deleted file mode 100644
index 637ccc5..0000000
--- a/src/third_party/angle/src/compiler/CodeGenHLSL.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/TranslatorHLSL.h"
-
-//
-// This function must be provided to create the actual
-// compile object used by higher level code.  It returns
-// a subclass of TCompiler.
-//
-TCompiler* ConstructCompiler(
-    ShShaderType type, ShShaderSpec spec, ShShaderOutput output)
-{
-  switch (output)
-  {
-    case SH_HLSL9_OUTPUT:
-    case SH_HLSL11_OUTPUT:
-      return new TranslatorHLSL(type, spec, output);
-    default:
-      return NULL;
-  }
-}
-
-//
-// Delete the compiler made by ConstructCompiler
-//
-void DeleteCompiler(TCompiler* compiler)
-{
-    delete compiler;
-}
diff --git a/src/third_party/angle/src/compiler/Common.h b/src/third_party/angle/src/compiler/Common.h
deleted file mode 100644
index 532486a..0000000
--- a/src/third_party/angle/src/compiler/Common.h
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _COMMON_INCLUDED_
-#define _COMMON_INCLUDED_
-
-#include <map>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "compiler/PoolAlloc.h"
-
-struct TSourceLoc {
-    int first_file;
-    int first_line;
-    int last_file;
-    int last_line;
-};
-
-//
-// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
-//
-#define POOL_ALLOCATOR_NEW_DELETE(A)                                  \
-    void* operator new(size_t s) { return (A).allocate(s); }          \
-    void* operator new(size_t, void *_Where) { return (_Where);	}     \
-    void operator delete(void*) { }                                   \
-    void operator delete(void *, void *) { }                          \
-    void* operator new[](size_t s) { return (A).allocate(s); }        \
-    void* operator new[](size_t, void *_Where) { return (_Where);	} \
-    void operator delete[](void*) { }                                 \
-    void operator delete[](void *, void *) { }
-
-//
-// Pool version of string.
-//
-typedef pool_allocator<char> TStringAllocator;
-typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
-typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
-inline TString* NewPoolTString(const char* s)
-{
-	void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
-	return new(memory) TString(s);
-}
-
-//
-// Persistent string memory.  Should only be used for strings that survive
-// across compiles.
-//
-#define TPersistString std::string
-#define TPersistStringStream std::ostringstream
-
-//
-// Pool allocator versions of vectors, lists, and maps
-//
-template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
-public:
-    typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
-    TVector() : std::vector<T, pool_allocator<T> >() {}
-    TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
-    TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
-};
-
-template <class K, class D, class CMP = std::less<K> > 
-class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > {
-public:
-    typedef pool_allocator<std::pair<const K, D> > tAllocator;
-
-    TMap() : std::map<K, D, CMP, tAllocator>() {}
-    // use correct two-stage name lookup supported in gcc 3.4 and above
-    TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
-};
-
-#endif // _COMMON_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/Compiler.cpp b/src/third_party/angle/src/compiler/Compiler.cpp
deleted file mode 100644
index 263ec77..0000000
--- a/src/third_party/angle/src/compiler/Compiler.cpp
+++ /dev/null
@@ -1,408 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/BuiltInFunctionEmulator.h"
-#include "compiler/DetectCallDepth.h"
-#include "compiler/ForLoopUnroll.h"
-#include "compiler/Initialize.h"
-#include "compiler/InitializeParseContext.h"
-#include "compiler/MapLongVariableNames.h"
-#include "compiler/ParseHelper.h"
-#include "compiler/RenameFunction.h"
-#include "compiler/ShHandle.h"
-#include "compiler/ValidateLimitations.h"
-#include "compiler/VariablePacker.h"
-#include "compiler/depgraph/DependencyGraph.h"
-#include "compiler/depgraph/DependencyGraphOutput.h"
-#include "compiler/timing/RestrictFragmentShaderTiming.h"
-#include "compiler/timing/RestrictVertexShaderTiming.h"
-#include "third_party/compiler/ArrayBoundsClamper.h"
-
-bool isWebGLBasedSpec(ShShaderSpec spec)
-{
-     return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
-}
-
-namespace {
-class TScopedPoolAllocator {
-public:
-    TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
-        : mAllocator(allocator), mPushPopAllocator(pushPop) {
-        if (mPushPopAllocator) mAllocator->push();
-        SetGlobalPoolAllocator(mAllocator);
-    }
-    ~TScopedPoolAllocator() {
-        SetGlobalPoolAllocator(NULL);
-        if (mPushPopAllocator) mAllocator->pop();
-    }
-
-private:
-    TPoolAllocator* mAllocator;
-    bool mPushPopAllocator;
-};
-}  // namespace
-
-TShHandleBase::TShHandleBase() {
-    allocator.push();
-    SetGlobalPoolAllocator(&allocator);
-}
-
-TShHandleBase::~TShHandleBase() {
-    SetGlobalPoolAllocator(NULL);
-    allocator.popAll();
-}
-
-TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
-    : shaderType(type),
-      shaderSpec(spec),
-      maxUniformVectors(0),
-      maxExpressionComplexity(0),
-      maxCallStackDepth(0),
-      fragmentPrecisionHigh(false),
-      clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
-      builtInFunctionEmulator(type)
-{
-    longNameMap = LongNameMap::GetInstance();
-}
-
-TCompiler::~TCompiler()
-{
-    ASSERT(longNameMap);
-    longNameMap->Release();
-}
-
-bool TCompiler::Init(const ShBuiltInResources& resources)
-{
-    maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
-        resources.MaxVertexUniformVectors :
-        resources.MaxFragmentUniformVectors;
-    maxExpressionComplexity = resources.MaxExpressionComplexity;
-    maxCallStackDepth = resources.MaxCallStackDepth;
-    TScopedPoolAllocator scopedAlloc(&allocator, false);
-
-    // Generate built-in symbol table.
-    if (!InitBuiltInSymbolTable(resources))
-        return false;
-    InitExtensionBehavior(resources, extensionBehavior);
-    fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
-
-    arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
-    clampingStrategy = resources.ArrayIndexClampingStrategy;
-
-    hashFunction = resources.HashFunction;
-
-    return true;
-}
-
-bool TCompiler::compile(const char* const shaderStrings[],
-                        size_t numStrings,
-                        int compileOptions)
-{
-    TScopedPoolAllocator scopedAlloc(&allocator, true);
-    clearResults();
-
-    if (numStrings == 0)
-        return true;
-
-    // If compiling for WebGL, validate loop and indexing as well.
-    if (isWebGLBasedSpec(shaderSpec))
-        compileOptions |= SH_VALIDATE_LOOP_INDEXING;
-
-    // First string is path of source file if flag is set. The actual source follows.
-    const char* sourcePath = NULL;
-    size_t firstSource = 0;
-    if (compileOptions & SH_SOURCE_PATH)
-    {
-        sourcePath = shaderStrings[0];
-        ++firstSource;
-    }
-
-    TIntermediate intermediate(infoSink);
-    TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
-                               shaderType, shaderSpec, compileOptions, true,
-                               sourcePath, infoSink);
-    parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
-    GlobalParseContext = &parseContext;
-
-    // We preserve symbols at the built-in level from compile-to-compile.
-    // Start pushing the user-defined symbols at global level.
-    symbolTable.push();
-    if (!symbolTable.atGlobalLevel()) {
-        infoSink.info.prefix(EPrefixInternalError);
-        infoSink.info << "Wrong symbol table level";
-    }
-
-    // Parse shader.
-    bool success =
-        (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
-        (parseContext.treeRoot != NULL);
-    if (success) {
-        TIntermNode* root = parseContext.treeRoot;
-        success = intermediate.postProcess(root);
-
-        if (success)
-            success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
-
-        if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
-            success = validateLimitations(root);
-
-        if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
-            success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
-
-        if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
-            rewriteCSSShader(root);
-
-        // Unroll for-loop markup needs to happen after validateLimitations pass.
-        if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
-            ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
-
-        // Built-in function emulation needs to happen after validateLimitations pass.
-        if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
-            builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
-
-        // Clamping uniform array bounds needs to happen after validateLimitations pass.
-        if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
-            arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
-
-        // Disallow expressions deemed too complex.
-        if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
-            success = limitExpressionComplexity(root);
-
-        // Call mapLongVariableNames() before collectAttribsUniforms() so in
-        // collectAttribsUniforms() we already have the mapped symbol names and
-        // we could composite mapped and original variable names.
-        // Also, if we hash all the names, then no need to do this for long names.
-        if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
-            mapLongVariableNames(root);
-
-        if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
-            collectAttribsUniforms(root);
-            if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) {
-                success = enforcePackingRestrictions();
-                if (!success) {
-                    infoSink.info.prefix(EPrefixError);
-                    infoSink.info << "too many uniforms";
-                }
-            }
-        }
-
-        if (success && (compileOptions & SH_INTERMEDIATE_TREE))
-            intermediate.outputTree(root);
-
-        if (success && (compileOptions & SH_OBJECT_CODE))
-            translate(root);
-    }
-
-    // Cleanup memory.
-    intermediate.remove(parseContext.treeRoot);
-    // Ensure symbol table is returned to the built-in level,
-    // throwing away all but the built-ins.
-    while (!symbolTable.atBuiltInLevel())
-        symbolTable.pop();
-
-    return success;
-}
-
-bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
-{
-    compileResources = resources;
-
-    assert(symbolTable.isEmpty());
-    symbolTable.push();
-
-    TPublicType integer;
-    integer.type = EbtInt;
-    integer.size = 1;
-    integer.matrix = false;
-    integer.array = false;
-
-    TPublicType floatingPoint;
-    floatingPoint.type = EbtFloat;
-    floatingPoint.size = 1;
-    floatingPoint.matrix = false;
-    floatingPoint.array = false;
-
-    switch(shaderType)
-    {
-      case SH_FRAGMENT_SHADER:
-        symbolTable.setDefaultPrecision(integer, EbpMedium);
-        break;
-      case SH_VERTEX_SHADER:
-        symbolTable.setDefaultPrecision(integer, EbpHigh);
-        symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
-        break;
-      default: assert(false && "Language not supported");
-    }
-
-    InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
-
-    IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
-
-    return true;
-}
-
-void TCompiler::clearResults()
-{
-    arrayBoundsClamper.Cleanup();
-    infoSink.info.erase();
-    infoSink.obj.erase();
-    infoSink.debug.erase();
-
-    attribs.clear();
-    uniforms.clear();
-
-    builtInFunctionEmulator.Cleanup();
-
-    nameMap.clear();
-}
-
-bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
-{
-    DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
-    root->traverse(&detect);
-    switch (detect.detectCallDepth()) {
-        case DetectCallDepth::kErrorNone:
-            return true;
-        case DetectCallDepth::kErrorMissingMain:
-            infoSink.info.prefix(EPrefixError);
-            infoSink.info << "Missing main()";
-            return false;
-        case DetectCallDepth::kErrorRecursion:
-            infoSink.info.prefix(EPrefixError);
-            infoSink.info << "Function recursion detected";
-            return false;
-        case DetectCallDepth::kErrorMaxDepthExceeded:
-            infoSink.info.prefix(EPrefixError);
-            infoSink.info << "Function call stack too deep";
-            return false;
-        default:
-            UNREACHABLE();
-            return false;
-    }
-}
-
-void TCompiler::rewriteCSSShader(TIntermNode* root)
-{
-    RenameFunction renamer("main(", "css_main(");
-    root->traverse(&renamer);
-}
-
-bool TCompiler::validateLimitations(TIntermNode* root) {
-    ValidateLimitations validate(shaderType, infoSink.info);
-    root->traverse(&validate);
-    return validate.numErrors() == 0;
-}
-
-bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
-{
-    if (shaderSpec != SH_WEBGL_SPEC) {
-        infoSink.info << "Timing restrictions must be enforced under the WebGL spec.";
-        return false;
-    }
-
-    if (shaderType == SH_FRAGMENT_SHADER) {
-        TDependencyGraph graph(root);
-
-        // Output any errors first.
-        bool success = enforceFragmentShaderTimingRestrictions(graph);
-        
-        // Then, output the dependency graph.
-        if (outputGraph) {
-            TDependencyGraphOutput output(infoSink.info);
-            output.outputAllSpanningTrees(graph);
-        }
-        
-        return success;
-    }
-    else {
-        return enforceVertexShaderTimingRestrictions(root);
-    }
-}
-
-bool TCompiler::limitExpressionComplexity(TIntermNode* root)
-{
-    TIntermTraverser traverser;
-    root->traverse(&traverser);
-    TDependencyGraph graph(root);
-
-    for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
-         iter != graph.endUserDefinedFunctionCalls();
-         ++iter)
-    {
-        TGraphFunctionCall* samplerSymbol = *iter;
-        TDependencyGraphTraverser graphTraverser;
-        samplerSymbol->traverse(&graphTraverser);
-    }
-
-    if (traverser.getMaxDepth() > maxExpressionComplexity) {
-        infoSink.info << "Expression too complex.";
-        return false;
-    }
-    return true;
-}
-
-bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
-{
-    RestrictFragmentShaderTiming restrictor(infoSink.info);
-    restrictor.enforceRestrictions(graph);
-    return restrictor.numErrors() == 0;
-}
-
-bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
-{
-    RestrictVertexShaderTiming restrictor(infoSink.info);
-    restrictor.enforceRestrictions(root);
-    return restrictor.numErrors() == 0;
-}
-
-void TCompiler::collectAttribsUniforms(TIntermNode* root)
-{
-    CollectAttribsUniforms collect(attribs, uniforms, hashFunction);
-    root->traverse(&collect);
-}
-
-bool TCompiler::enforcePackingRestrictions()
-{
-    VariablePacker packer;
-    return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms);
-}
-
-void TCompiler::mapLongVariableNames(TIntermNode* root)
-{
-    ASSERT(longNameMap);
-    MapLongVariableNames map(longNameMap);
-    root->traverse(&map);
-}
-
-int TCompiler::getMappedNameMaxLength() const
-{
-    return MAX_SHORTENED_IDENTIFIER_SIZE + 1;
-}
-
-const TExtensionBehavior& TCompiler::getExtensionBehavior() const
-{
-    return extensionBehavior;
-}
-
-const ShBuiltInResources& TCompiler::getResources() const
-{
-    return compileResources;
-}
-
-const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
-{
-    return arrayBoundsClamper;
-}
-
-ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
-{
-    return clampingStrategy;
-}
-
-const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
-{
-    return builtInFunctionEmulator;
-}
diff --git a/src/third_party/angle/src/compiler/ConstantUnion.h b/src/third_party/angle/src/compiler/ConstantUnion.h
deleted file mode 100644
index 32af4d3..0000000
--- a/src/third_party/angle/src/compiler/ConstantUnion.h
+++ /dev/null
@@ -1,257 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _CONSTANT_UNION_INCLUDED_
-#define _CONSTANT_UNION_INCLUDED_
-
-#include <assert.h>
-
-class ConstantUnion {
-public:
-    ConstantUnion()
-    {
-        iConst = 0;
-        type = EbtVoid;
-    }
-
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)        
-    void setIConst(int i) {iConst = i; type = EbtInt; }
-    void setFConst(float f) {fConst = f; type = EbtFloat; }
-    void setBConst(bool b) {bConst = b; type = EbtBool; }
-
-    int getIConst() { return iConst; }
-    float getFConst() { return fConst; }
-    bool getBConst() { return bConst; }
-    int getIConst() const { return iConst; }
-    float getFConst() const { return fConst; }
-    bool getBConst() const { return bConst; }
-
-    bool operator==(const int i) const
-    {
-        return i == iConst;
-    }
-
-    bool operator==(const float f) const
-    {
-        return f == fConst;
-    }
-
-    bool operator==(const bool b) const
-    {
-        return b == bConst;
-    }
-
-    bool operator==(const ConstantUnion& constant) const
-    {
-        if (constant.type != type)
-            return false;
-
-        switch (type) {
-        case EbtInt:
-            return constant.iConst == iConst;
-        case EbtFloat:
-            return constant.fConst == fConst;
-        case EbtBool:
-            return constant.bConst == bConst;
-        default:
-            return false;
-        }
-    }
-
-    bool operator!=(const int i) const
-    {
-        return !operator==(i);
-    }
-
-    bool operator!=(const float f) const
-    {
-        return !operator==(f);
-    }
-
-    bool operator!=(const bool b) const
-    {
-        return !operator==(b);
-    }
-
-    bool operator!=(const ConstantUnion& constant) const
-    {
-        return !operator==(constant);
-    }
-
-    bool operator>(const ConstantUnion& constant) const
-    { 
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt:
-            return iConst > constant.iConst;
-        case EbtFloat:
-            return fConst > constant.fConst;
-        default:
-            return false;   // Invalid operation, handled at semantic analysis
-        }
-    }
-
-    bool operator<(const ConstantUnion& constant) const
-    { 
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt:
-            return iConst < constant.iConst;
-        case EbtFloat:
-            return fConst < constant.fConst;
-        default:
-            return false;   // Invalid operation, handled at semantic analysis
-        }
-    }
-
-    ConstantUnion operator+(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
-        case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
-        default: assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator-(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
-        case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
-        default: assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator*(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
-        case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; 
-        default: assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator%(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
-        default:     assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator>>(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
-        default:     assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator<<(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
-        default:     assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator&(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt:  returnValue.setIConst(iConst & constant.iConst); break;
-        default:     assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator|(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt:  returnValue.setIConst(iConst | constant.iConst); break;
-        default:     assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator^(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtInt:  returnValue.setIConst(iConst ^ constant.iConst); break;
-        default:     assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator&&(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
-        default:     assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    ConstantUnion operator||(const ConstantUnion& constant) const
-    { 
-        ConstantUnion returnValue;
-        assert(type == constant.type);
-        switch (type) {
-        case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
-        default:     assert(false && "Default missing");
-        }
-
-        return returnValue;
-    }
-
-    TBasicType getType() const { return type; }
-private:
-
-    union  {
-        int iConst;  // used for ivec, scalar ints
-        bool bConst; // used for bvec, scalar bools
-        float fConst;   // used for vec, mat, scalar floats
-    } ;
-
-    TBasicType type;
-};
-
-#endif // _CONSTANT_UNION_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/DetectCallDepth.cpp b/src/third_party/angle/src/compiler/DetectCallDepth.cpp
deleted file mode 100644
index 60df52c..0000000
--- a/src/third_party/angle/src/compiler/DetectCallDepth.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/DetectCallDepth.h"
-#include "compiler/InfoSink.h"
-
-DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
-    : name(fname),
-      visit(PreVisit)
-{
-}
-
-const TString& DetectCallDepth::FunctionNode::getName() const
-{
-    return name;
-}
-
-void DetectCallDepth::FunctionNode::addCallee(
-    DetectCallDepth::FunctionNode* callee)
-{
-    for (size_t i = 0; i < callees.size(); ++i) {
-        if (callees[i] == callee)
-            return;
-    }
-    callees.push_back(callee);
-}
-
-int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
-{
-    ASSERT(visit == PreVisit);
-    ASSERT(detectCallDepth);
-
-    int maxDepth = depth;
-    visit = InVisit;
-    for (size_t i = 0; i < callees.size(); ++i) {
-        switch (callees[i]->visit) {
-            case InVisit:
-                // cycle detected, i.e., recursion detected.
-                return kInfiniteCallDepth;
-            case PostVisit:
-                break;
-            case PreVisit: {
-                // Check before we recurse so we don't go too depth
-                if (detectCallDepth->checkExceedsMaxDepth(depth))
-                    return depth;
-                int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
-                // Check after we recurse so we can exit immediately and provide info.
-                if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
-                    detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
-                    return callDepth;
-                }
-                maxDepth = std::max(callDepth, maxDepth);
-                break;
-            }
-            default:
-                UNREACHABLE();
-                break;
-        }
-    }
-    visit = PostVisit;
-    return maxDepth;
-}
-
-void DetectCallDepth::FunctionNode::reset()
-{
-    visit = PreVisit;
-}
-
-DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
-    : TIntermTraverser(true, false, true, false),
-      currentFunction(NULL),
-      infoSink(infoSink),
-      maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
-{
-}
-
-DetectCallDepth::~DetectCallDepth()
-{
-    for (size_t i = 0; i < functions.size(); ++i)
-        delete functions[i];
-}
-
-bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
-{
-    switch (node->getOp())
-    {
-        case EOpPrototype:
-            // Function declaration.
-            // Don't add FunctionNode here because node->getName() is the
-            // unmangled function name.
-            break;
-        case EOpFunction: {
-            // Function definition.
-            if (visit == PreVisit) {
-                currentFunction = findFunctionByName(node->getName());
-                if (currentFunction == NULL) {
-                    currentFunction = new FunctionNode(node->getName());
-                    functions.push_back(currentFunction);
-                }
-            } else if (visit == PostVisit) {
-                currentFunction = NULL;
-            }
-            break;
-        }
-        case EOpFunctionCall: {
-            // Function call.
-            if (visit == PreVisit) {
-                FunctionNode* func = findFunctionByName(node->getName());
-                if (func == NULL) {
-                    func = new FunctionNode(node->getName());
-                    functions.push_back(func);
-                }
-                if (currentFunction)
-                    currentFunction->addCallee(func);
-            }
-            break;
-        }
-        default:
-            break;
-    }
-    return true;
-}
-
-bool DetectCallDepth::checkExceedsMaxDepth(int depth)
-{
-    return depth >= maxDepth;
-}
-
-void DetectCallDepth::resetFunctionNodes()
-{
-    for (size_t i = 0; i < functions.size(); ++i) {
-        functions[i]->reset();
-    }
-}
-
-DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
-{
-    currentFunction = NULL;
-    resetFunctionNodes();
-
-    int maxCallDepth = func->detectCallDepth(this, 1);
-
-    if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
-        return kErrorRecursion;
-
-    if (maxCallDepth >= maxDepth)
-        return kErrorMaxDepthExceeded;
-
-    return kErrorNone;
-}
-
-DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
-{
-    if (maxDepth != FunctionNode::kInfiniteCallDepth) {
-        // Check all functions because the driver may fail on them
-        // TODO: Before detectingRecursion, strip unused functions.
-        for (size_t i = 0; i < functions.size(); ++i) {
-            ErrorCode error = detectCallDepthForFunction(functions[i]);
-            if (error != kErrorNone)
-                return error;
-        }
-    } else {
-        FunctionNode* main = findFunctionByName("main(");
-        if (main == NULL)
-            return kErrorMissingMain;
-
-        return detectCallDepthForFunction(main);
-    }
-
-    return kErrorNone;
-}
-
-DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
-    const TString& name)
-{
-    for (size_t i = 0; i < functions.size(); ++i) {
-        if (functions[i]->getName() == name)
-            return functions[i];
-    }
-    return NULL;
-}
-
diff --git a/src/third_party/angle/src/compiler/DetectCallDepth.h b/src/third_party/angle/src/compiler/DetectCallDepth.h
deleted file mode 100644
index 89e85f8..0000000
--- a/src/third_party/angle/src/compiler/DetectCallDepth.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_DETECT_RECURSION_H_
-#define COMPILER_DETECT_RECURSION_H_
-
-#include "GLSLANG/ShaderLang.h"
-
-#include <limits.h>
-#include "compiler/intermediate.h"
-#include "compiler/VariableInfo.h"
-
-class TInfoSink;
-
-// Traverses intermediate tree to detect function recursion.
-class DetectCallDepth : public TIntermTraverser {
-public:
-    enum ErrorCode {
-        kErrorMissingMain,
-        kErrorRecursion,
-        kErrorMaxDepthExceeded,
-        kErrorNone
-    };
-
-    DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth);
-    ~DetectCallDepth();
-
-    virtual bool visitAggregate(Visit, TIntermAggregate*);
-
-    bool checkExceedsMaxDepth(int depth);
-
-    ErrorCode detectCallDepth();
-
-private:
-    class FunctionNode {
-    public:
-        static const int kInfiniteCallDepth = INT_MAX;
-
-        FunctionNode(const TString& fname);
-
-        const TString& getName() const;
-
-        // If a function is already in the callee list, this becomes a no-op.
-        void addCallee(FunctionNode* callee);
-
-        // Returns kInifinityCallDepth if recursive function calls are detected.
-        int detectCallDepth(DetectCallDepth* detectCallDepth, int depth);
-
-        // Reset state.
-        void reset();
-
-    private:
-        // mangled function name is unique.
-        TString name;
-
-        // functions that are directly called by this function.
-        TVector<FunctionNode*> callees;
-
-        Visit visit;
-    };
-
-    ErrorCode detectCallDepthForFunction(FunctionNode* func);
-    FunctionNode* findFunctionByName(const TString& name);
-    void resetFunctionNodes();
-
-    TInfoSink& getInfoSink() { return infoSink; }
-
-    TVector<FunctionNode*> functions;
-    FunctionNode* currentFunction;
-    TInfoSink& infoSink;
-    int maxDepth;
-
-    DetectCallDepth(const DetectCallDepth&);
-    void operator=(const DetectCallDepth&);
-};
-
-#endif  // COMPILER_DETECT_RECURSION_H_
diff --git a/src/third_party/angle/src/compiler/DetectDiscontinuity.cpp b/src/third_party/angle/src/compiler/DetectDiscontinuity.cpp
deleted file mode 100644
index 7c3b68a..0000000
--- a/src/third_party/angle/src/compiler/DetectDiscontinuity.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Contains analysis utilities for dealing with HLSL's lack of support for
-// the use of intrinsic functions which (implicitly or explicitly) compute
-// gradients of functions with discontinuities. 
-//
-
-#include "compiler/DetectDiscontinuity.h"
-
-#include "compiler/ParseHelper.h"
-
-namespace sh
-{
-bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
-{
-    mLoopDepth = 0;
-    mLoopDiscontinuity = false;
-    node->traverse(this);
-    return mLoopDiscontinuity;
-}
-
-bool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop)
-{
-    if (visit == PreVisit)
-    {
-        ++mLoopDepth;
-    }
-    else if (visit == PostVisit)
-    {
-        --mLoopDepth;
-    }
-
-    return true;
-}
-
-bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
-{
-    if (mLoopDiscontinuity)
-    {
-        return false;
-    }
-
-    if (!mLoopDepth)
-    {
-        return true;
-    }
-
-    switch (node->getFlowOp())
-    {
-      case EOpKill:
-        break;
-      case EOpBreak:
-      case EOpContinue:
-      case EOpReturn:
-        mLoopDiscontinuity = true;
-        break;
-      default: UNREACHABLE();
-    }
-
-    return !mLoopDiscontinuity;
-}
-
-bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
-{
-    return !mLoopDiscontinuity;
-}
-
-bool containsLoopDiscontinuity(TIntermNode *node)
-{
-    DetectLoopDiscontinuity detectLoopDiscontinuity;
-    return detectLoopDiscontinuity.traverse(node);
-}
-
-bool DetectGradientOperation::traverse(TIntermNode *node)
-{
-    mGradientOperation = false;
-    node->traverse(this);
-    return mGradientOperation;
-}
-
-bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node)
-{
-    if (mGradientOperation)
-    {
-        return false;
-    }
-
-    switch (node->getOp())
-    {
-      case EOpDFdx:
-      case EOpDFdy:
-        mGradientOperation = true;
-      default:
-        break;
-    }
-
-    return !mGradientOperation;
-}
-
-bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node)
-{
-    if (mGradientOperation)
-    {
-        return false;
-    }
-
-    if (node->getOp() == EOpFunctionCall)
-    {
-        if (!node->isUserDefined())
-        {
-            TString name = TFunction::unmangleName(node->getName());
-
-            if (name == "texture2D" ||
-                name == "texture2DProj" ||
-                name == "textureCube")
-            {
-                mGradientOperation = true;
-            }
-        }
-        else
-        {
-            // When a user defined function is called, we have to
-            // conservatively assume it to contain gradient operations
-            mGradientOperation = true;
-        }
-    }
-
-    return !mGradientOperation;
-}
-
-bool containsGradientOperation(TIntermNode *node)
-{
-    DetectGradientOperation detectGradientOperation;
-    return detectGradientOperation.traverse(node);
-}
-}
diff --git a/src/third_party/angle/src/compiler/DetectDiscontinuity.h b/src/third_party/angle/src/compiler/DetectDiscontinuity.h
deleted file mode 100644
index e5520bd..0000000
--- a/src/third_party/angle/src/compiler/DetectDiscontinuity.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Contains analysis utilities for dealing with HLSL's lack of support for
-// the use of intrinsic functions which (implicitly or explicitly) compute
-// gradients of functions with discontinuities. 
-//
-
-#ifndef COMPILER_DETECTDISCONTINUITY_H_
-#define COMPILER_DETECTDISCONTINUITY_H_
-
-#include "compiler/intermediate.h"
-
-namespace sh
-{
-// Checks whether a loop can run for a variable number of iterations
-class DetectLoopDiscontinuity : public TIntermTraverser
-{
-  public:
-    bool traverse(TIntermNode *node);
-
-  protected:
-    bool visitBranch(Visit visit, TIntermBranch *node);
-    bool visitLoop(Visit visit, TIntermLoop *loop);
-    bool visitAggregate(Visit visit, TIntermAggregate *node);
-
-    int mLoopDepth;
-    bool mLoopDiscontinuity;
-};
-
-bool containsLoopDiscontinuity(TIntermNode *node);
-
-// Checks for intrinsic functions which compute gradients
-class DetectGradientOperation : public TIntermTraverser
-{
-  public:
-    bool traverse(TIntermNode *node);
-
-  protected:
-    bool visitUnary(Visit visit, TIntermUnary *node);
-    bool visitAggregate(Visit visit, TIntermAggregate *node);
-
-    bool mGradientOperation;
-};
-
-bool containsGradientOperation(TIntermNode *node);
-
-}
-
-#endif   // COMPILER_DETECTDISCONTINUITY_H_
diff --git a/src/third_party/angle/src/compiler/Diagnostics.cpp b/src/third_party/angle/src/compiler/Diagnostics.cpp
deleted file mode 100644
index 8a38c41..0000000
--- a/src/third_party/angle/src/compiler/Diagnostics.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/Diagnostics.h"
-
-#include "compiler/debug.h"
-#include "compiler/InfoSink.h"
-#include "compiler/preprocessor/SourceLocation.h"
-
-TDiagnostics::TDiagnostics(TInfoSink& infoSink) :
-    mInfoSink(infoSink),
-    mNumErrors(0),
-    mNumWarnings(0)
-{
-}
-
-TDiagnostics::~TDiagnostics()
-{
-}
-
-void TDiagnostics::writeInfo(Severity severity,
-                             const pp::SourceLocation& loc,
-                             const std::string& reason,
-                             const std::string& token,
-                             const std::string& extra)
-{
-    TPrefixType prefix = EPrefixNone;
-    switch (severity)
-    {
-      case ERROR:
-        ++mNumErrors;
-        prefix = EPrefixError;
-        break;
-      case WARNING:
-        ++mNumWarnings;
-        prefix = EPrefixWarning;
-        break;
-      default:
-        UNREACHABLE();
-        break;
-    }
-
-    TInfoSinkBase& sink = mInfoSink.info;
-    /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
-    sink.prefix(prefix);
-    sink.location(loc.file, loc.line);
-    sink << "'" << token <<  "' : " << reason << " " << extra << "\n";
-}
-
-void TDiagnostics::writeDebug(const std::string& str)
-{
-    mInfoSink.debug << str;
-}
-
-void TDiagnostics::print(ID id,
-                         const pp::SourceLocation& loc,
-                         const std::string& text)
-{
-    writeInfo(severity(id), loc, message(id), text, "");
-}
diff --git a/src/third_party/angle/src/compiler/Diagnostics.h b/src/third_party/angle/src/compiler/Diagnostics.h
deleted file mode 100644
index cb71bb1..0000000
--- a/src/third_party/angle/src/compiler/Diagnostics.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_DIAGNOSTICS_H_
-#define COMPILER_DIAGNOSTICS_H_
-
-#include "compiler/preprocessor/DiagnosticsBase.h"
-
-class TInfoSink;
-
-class TDiagnostics : public pp::Diagnostics
-{
-  public:
-    TDiagnostics(TInfoSink& infoSink);
-    virtual ~TDiagnostics();
-
-    TInfoSink& infoSink() { return mInfoSink; }
-
-    int numErrors() const { return mNumErrors; }
-    int numWarnings() const { return mNumWarnings; }
-
-    void writeInfo(Severity severity,
-                   const pp::SourceLocation& loc,
-                   const std::string& reason,
-                   const std::string& token,
-                   const std::string& extra);
-
-    void writeDebug(const std::string& str);
-
-  protected:
-    virtual void print(ID id,
-                       const pp::SourceLocation& loc,
-                       const std::string& text);
-
-  private:
-    TInfoSink& mInfoSink;
-    int mNumErrors;
-    int mNumWarnings;
-};
-
-#endif  // COMPILER_DIAGNOSTICS_H_
diff --git a/src/third_party/angle/src/compiler/DirectiveHandler.cpp b/src/third_party/angle/src/compiler/DirectiveHandler.cpp
deleted file mode 100644
index d1f6ab3..0000000
--- a/src/third_party/angle/src/compiler/DirectiveHandler.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/DirectiveHandler.h"
-
-#include <sstream>
-
-#include "compiler/debug.h"
-#include "compiler/Diagnostics.h"
-
-static TBehavior getBehavior(const std::string& str)
-{
-    static const std::string kRequire("require");
-    static const std::string kEnable("enable");
-    static const std::string kDisable("disable");
-    static const std::string kWarn("warn");
-
-    if (str == kRequire) return EBhRequire;
-    else if (str == kEnable) return EBhEnable;
-    else if (str == kDisable) return EBhDisable;
-    else if (str == kWarn) return EBhWarn;
-    return EBhUndefined;
-}
-
-TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
-                                     TDiagnostics& diagnostics)
-    : mExtensionBehavior(extBehavior),
-      mDiagnostics(diagnostics)
-{
-}
-
-TDirectiveHandler::~TDirectiveHandler()
-{
-}
-
-void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
-                                    const std::string& msg)
-{
-    mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, msg, "", "");
-}
-
-void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
-                                     const std::string& name,
-                                     const std::string& value)
-{
-    static const std::string kSTDGL("STDGL");
-    static const std::string kOptimize("optimize");
-    static const std::string kDebug("debug");
-    static const std::string kOn("on");
-    static const std::string kOff("off");
-
-    bool invalidValue = false;
-    if (name == kSTDGL)
-    {
-        // The STDGL pragma is used to reserve pragmas for use by future
-        // revisions of GLSL. Ignore it.
-        return;
-    }
-    else if (name == kOptimize)
-    {
-        if (value == kOn) mPragma.optimize = true;
-        else if (value == kOff) mPragma.optimize = false;
-        else invalidValue = true;
-    }
-    else if (name == kDebug)
-    {
-        if (value == kOn) mPragma.debug = true;
-        else if (value == kOff) mPragma.debug = false;
-        else invalidValue = true;
-    }
-    else
-    {
-        mDiagnostics.report(pp::Diagnostics::UNRECOGNIZED_PRAGMA, loc, name);
-        return;
-    }
-
-    if (invalidValue)
-      mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc,
-                             "invalid pragma value", value,
-                             "'on' or 'off' expected");
-}
-
-void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
-                                        const std::string& name,
-                                        const std::string& behavior)
-{
-    static const std::string kExtAll("all");
-
-    TBehavior behaviorVal = getBehavior(behavior);
-    if (behaviorVal == EBhUndefined)
-    {
-        mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc,
-                               "behavior", name, "invalid");
-        return;
-    }
-
-    if (name == kExtAll)
-    {
-        if (behaviorVal == EBhRequire)
-        {
-            mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc,
-                                   "extension", name,
-                                   "cannot have 'require' behavior");
-        }
-        else if (behaviorVal == EBhEnable)
-        {
-            mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc,
-                                   "extension", name,
-                                   "cannot have 'enable' behavior");
-        }
-        else
-        {
-            for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin();
-                 iter != mExtensionBehavior.end(); ++iter)
-                iter->second = behaviorVal;
-        }
-        return;
-    }
-
-    TExtensionBehavior::iterator iter = mExtensionBehavior.find(name);
-    if (iter != mExtensionBehavior.end())
-    {
-        iter->second = behaviorVal;
-        return;
-    }
-
-    pp::Diagnostics::Severity severity = pp::Diagnostics::ERROR;
-    switch (behaviorVal) {
-      case EBhRequire:
-        severity = pp::Diagnostics::ERROR;
-        break;
-      case EBhEnable:
-      case EBhWarn:
-      case EBhDisable:
-        severity = pp::Diagnostics::WARNING;
-        break;
-      default:
-        UNREACHABLE();
-        break;
-    }
-    mDiagnostics.writeInfo(severity, loc,
-                           "extension", name, "is not supported");
-}
-
-void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc,
-                                      int version)
-{
-    static const int kVersion = 100;
-
-    if (version != kVersion)
-    {
-        std::stringstream stream;
-        stream << version;
-        std::string str = stream.str();
-        mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc,
-                               "version number", str, "not supported");
-    }
-}
diff --git a/src/third_party/angle/src/compiler/DirectiveHandler.h b/src/third_party/angle/src/compiler/DirectiveHandler.h
deleted file mode 100644
index 95ca59d..0000000
--- a/src/third_party/angle/src/compiler/DirectiveHandler.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_DIRECTIVE_HANDLER_H_
-#define COMPILER_DIRECTIVE_HANDLER_H_
-
-#include "compiler/ExtensionBehavior.h"
-#include "compiler/Pragma.h"
-#include "compiler/preprocessor/DirectiveHandlerBase.h"
-
-class TDiagnostics;
-
-class TDirectiveHandler : public pp::DirectiveHandler
-{
-  public:
-    TDirectiveHandler(TExtensionBehavior& extBehavior,
-                      TDiagnostics& diagnostics);
-    virtual ~TDirectiveHandler();
-
-    const TPragma& pragma() const { return mPragma; }
-    const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; }
-
-    virtual void handleError(const pp::SourceLocation& loc,
-                             const std::string& msg);
-
-    virtual void handlePragma(const pp::SourceLocation& loc,
-                              const std::string& name,
-                              const std::string& value);
-
-    virtual void handleExtension(const pp::SourceLocation& loc,
-                                 const std::string& name,
-                                 const std::string& behavior);
-
-    virtual void handleVersion(const pp::SourceLocation& loc,
-                               int version);
-
-  private:
-    TPragma mPragma;
-    TExtensionBehavior& mExtensionBehavior;
-    TDiagnostics& mDiagnostics;
-};
-
-#endif  // COMPILER_DIRECTIVE_HANDLER_H_
diff --git a/src/third_party/angle/src/compiler/ExtensionBehavior.h b/src/third_party/angle/src/compiler/ExtensionBehavior.h
deleted file mode 100644
index 5c1595f..0000000
--- a/src/third_party/angle/src/compiler/ExtensionBehavior.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _EXTENSION_BEHAVIOR_INCLUDED_
-#define _EXTENSION_BEHAVIOR_INCLUDED_
-
-#include <map>
-#include <string>
-
-typedef enum
-{
-    EBhRequire,
-    EBhEnable,
-    EBhWarn,
-    EBhDisable,
-    EBhUndefined
-} TBehavior;
-
-inline const char* getBehaviorString(TBehavior b)
-{
-    switch(b)
-    {
-      case EBhRequire: return "require";
-      case EBhEnable: return "enable";
-      case EBhWarn: return "warn";
-      case EBhDisable: return "disable";
-      default: return NULL;
-    }
-}
-
-// Mapping between extension name and behavior.
-typedef std::map<std::string, TBehavior> TExtensionBehavior;
-
-#endif // _EXTENSION_TABLE_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/ForLoopUnroll.cpp b/src/third_party/angle/src/compiler/ForLoopUnroll.cpp
deleted file mode 100644
index 27a13ea..0000000
--- a/src/third_party/angle/src/compiler/ForLoopUnroll.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/ForLoopUnroll.h"
-
-namespace {
-
-class IntegerForLoopUnrollMarker : public TIntermTraverser {
-public:
-
-    virtual bool visitLoop(Visit, TIntermLoop* node)
-    {
-        // This is called after ValidateLimitations pass, so all the ASSERT
-        // should never fail.
-        // See ValidateLimitations::validateForLoopInit().
-        ASSERT(node);
-        ASSERT(node->getType() == ELoopFor);
-        ASSERT(node->getInit());
-        TIntermAggregate* decl = node->getInit()->getAsAggregate();
-        ASSERT(decl && decl->getOp() == EOpDeclaration);
-        TIntermSequence& declSeq = decl->getSequence();
-        ASSERT(declSeq.size() == 1);
-        TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
-        ASSERT(declInit && declInit->getOp() == EOpInitialize);
-        ASSERT(declInit->getLeft());
-        TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
-        ASSERT(symbol);
-        TBasicType type = symbol->getBasicType();
-        ASSERT(type == EbtInt || type == EbtFloat);
-        if (type == EbtInt)
-            node->setUnrollFlag(true);
-        return true;
-    }
-
-};
-
-}  // anonymous namepsace
-
-void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info)
-{
-    ASSERT(node->getType() == ELoopFor);
-    ASSERT(node->getUnrollFlag());
-
-    TIntermNode* init = node->getInit();
-    ASSERT(init != NULL);
-    TIntermAggregate* decl = init->getAsAggregate();
-    ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration));
-    TIntermSequence& declSeq = decl->getSequence();
-    ASSERT(declSeq.size() == 1);
-    TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
-    ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize));
-    TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
-    ASSERT(symbol != NULL);
-    ASSERT(symbol->getBasicType() == EbtInt);
-
-    info.id = symbol->getId();
-
-    ASSERT(declInit->getRight() != NULL);
-    TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion();
-    ASSERT(initNode != NULL);
-
-    info.initValue = evaluateIntConstant(initNode);
-    info.currentValue = info.initValue;
-
-    TIntermNode* cond = node->getCondition();
-    ASSERT(cond != NULL);
-    TIntermBinary* binOp = cond->getAsBinaryNode();
-    ASSERT(binOp != NULL);
-    ASSERT(binOp->getRight() != NULL);
-    ASSERT(binOp->getRight()->getAsConstantUnion() != NULL);
-
-    info.incrementValue = getLoopIncrement(node);
-    info.stopValue = evaluateIntConstant(
-        binOp->getRight()->getAsConstantUnion());
-    info.op = binOp->getOp();
-}
-
-void ForLoopUnroll::Step()
-{
-    ASSERT(mLoopIndexStack.size() > 0);
-    TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
-    info.currentValue += info.incrementValue;
-}
-
-bool ForLoopUnroll::SatisfiesLoopCondition()
-{
-    ASSERT(mLoopIndexStack.size() > 0);
-    TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
-    // Relational operator is one of: > >= < <= == or !=.
-    switch (info.op) {
-      case EOpEqual:
-        return (info.currentValue == info.stopValue);
-      case EOpNotEqual:
-        return (info.currentValue != info.stopValue);
-      case EOpLessThan:
-        return (info.currentValue < info.stopValue);
-      case EOpGreaterThan:
-        return (info.currentValue > info.stopValue);
-      case EOpLessThanEqual:
-        return (info.currentValue <= info.stopValue);
-      case EOpGreaterThanEqual:
-        return (info.currentValue >= info.stopValue);
-      default:
-        UNREACHABLE();
-    }
-    return false;
-}
-
-bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol)
-{
-    for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
-         i != mLoopIndexStack.end();
-         ++i) {
-        if (i->id == symbol->getId())
-            return true;
-    }
-    return false;
-}
-
-int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol)
-{
-    for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
-         i != mLoopIndexStack.end();
-         ++i) {
-        if (i->id == symbol->getId())
-            return i->currentValue;
-    }
-    UNREACHABLE();
-    return false;
-}
-
-void ForLoopUnroll::Push(TLoopIndexInfo& info)
-{
-    mLoopIndexStack.push_back(info);
-}
-
-void ForLoopUnroll::Pop()
-{
-    mLoopIndexStack.pop_back();
-}
-
-// static
-void ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(
-    TIntermNode* root)
-{
-    ASSERT(root);
-
-    IntegerForLoopUnrollMarker marker;
-    root->traverse(&marker);
-}
-
-int ForLoopUnroll::getLoopIncrement(TIntermLoop* node)
-{
-    TIntermNode* expr = node->getExpression();
-    ASSERT(expr != NULL);
-    // for expression has one of the following forms:
-    //     loop_index++
-    //     loop_index--
-    //     loop_index += constant_expression
-    //     loop_index -= constant_expression
-    //     ++loop_index
-    //     --loop_index
-    // The last two forms are not specified in the spec, but I am assuming
-    // its an oversight.
-    TIntermUnary* unOp = expr->getAsUnaryNode();
-    TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
-
-    TOperator op = EOpNull;
-    TIntermConstantUnion* incrementNode = NULL;
-    if (unOp != NULL) {
-        op = unOp->getOp();
-    } else if (binOp != NULL) {
-        op = binOp->getOp();
-        ASSERT(binOp->getRight() != NULL);
-        incrementNode = binOp->getRight()->getAsConstantUnion();
-        ASSERT(incrementNode != NULL);
-    }
-
-    int increment = 0;
-    // The operator is one of: ++ -- += -=.
-    switch (op) {
-        case EOpPostIncrement:
-        case EOpPreIncrement:
-            ASSERT((unOp != NULL) && (binOp == NULL));
-            increment = 1;
-            break;
-        case EOpPostDecrement:
-        case EOpPreDecrement:
-            ASSERT((unOp != NULL) && (binOp == NULL));
-            increment = -1;
-            break;
-        case EOpAddAssign:
-            ASSERT((unOp == NULL) && (binOp != NULL));
-            increment = evaluateIntConstant(incrementNode);
-            break;
-        case EOpSubAssign:
-            ASSERT((unOp == NULL) && (binOp != NULL));
-            increment = - evaluateIntConstant(incrementNode);
-            break;
-        default:
-            ASSERT(false);
-    }
-
-    return increment;
-}
-
-int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node)
-{
-    ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL));
-    return node->getIConst(0);
-}
-
diff --git a/src/third_party/angle/src/compiler/ForLoopUnroll.h b/src/third_party/angle/src/compiler/ForLoopUnroll.h
deleted file mode 100644
index e800e25..0000000
--- a/src/third_party/angle/src/compiler/ForLoopUnroll.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/intermediate.h"
-
-struct TLoopIndexInfo {
-    int id;
-    int initValue;
-    int stopValue;
-    int incrementValue;
-    TOperator op;
-    int currentValue;
-};
-
-class ForLoopUnroll {
-public:
-    ForLoopUnroll() { }
-
-    void FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info);
-
-    // Update the info.currentValue for the next loop iteration.
-    void Step();
-
-    // Return false if loop condition is no longer satisfied.
-    bool SatisfiesLoopCondition();
-
-    // Check if the symbol is the index of a loop that's unrolled.
-    bool NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol);
-
-    // Return the current value of a given loop index symbol.
-    int GetLoopIndexValue(TIntermSymbol* symbol);
-
-    void Push(TLoopIndexInfo& info);
-    void Pop();
-
-    static void MarkForLoopsWithIntegerIndicesForUnrolling(TIntermNode* root);
-
-private:
-    int getLoopIncrement(TIntermLoop* node);
-
-    int evaluateIntConstant(TIntermConstantUnion* node);
-
-    TVector<TLoopIndexInfo> mLoopIndexStack;
-};
-
diff --git a/src/third_party/angle/src/compiler/HashNames.h b/src/third_party/angle/src/compiler/HashNames.h
deleted file mode 100644
index d2141e2..0000000
--- a/src/third_party/angle/src/compiler/HashNames.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_HASH_NAMES_H_
-#define COMPILER_HASH_NAMES_H_
-
-#include <map>
-
-#include "compiler/intermediate.h"
-#include "GLSLANG/ShaderLang.h"
-
-#define HASHED_NAME_PREFIX "webgl_"
-
-typedef std::map<TPersistString, TPersistString> NameMap;
-
-#endif  // COMPILER_HASH_NAMES_H_
diff --git a/src/third_party/angle/src/compiler/InfoSink.cpp b/src/third_party/angle/src/compiler/InfoSink.cpp
deleted file mode 100644
index d20a6c0..0000000
--- a/src/third_party/angle/src/compiler/InfoSink.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/InfoSink.h"
-
-void TInfoSinkBase::prefix(TPrefixType p) {
-    switch(p) {
-        case EPrefixNone:
-            break;
-        case EPrefixWarning:
-            sink.append("WARNING: ");
-            break;
-        case EPrefixError:
-            sink.append("ERROR: ");
-            break;
-        case EPrefixInternalError:
-            sink.append("INTERNAL ERROR: ");
-            break;
-        case EPrefixUnimplemented:
-            sink.append("UNIMPLEMENTED: ");
-            break;
-        case EPrefixNote:
-            sink.append("NOTE: ");
-            break;
-        default:
-            sink.append("UNKOWN ERROR: ");
-            break;
-    }
-}
-
-void TInfoSinkBase::location(int file, int line) {
-    TPersistStringStream stream;
-    if (line)
-        stream << file << ":" << line;
-    else
-        stream << file << ":? ";
-    stream << ": ";
-
-    sink.append(stream.str());
-}
-
-void TInfoSinkBase::location(const TSourceLoc& loc) {
-    location(loc.first_file, loc.first_line);
-}
-
-void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) {
-    prefix(p);
-    location(loc);
-    sink.append(m);
-    sink.append("\n");
-}
diff --git a/src/third_party/angle/src/compiler/InfoSink.h b/src/third_party/angle/src/compiler/InfoSink.h
deleted file mode 100644
index 6888838..0000000
--- a/src/third_party/angle/src/compiler/InfoSink.h
+++ /dev/null
@@ -1,115 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _INFOSINK_INCLUDED_
-#define _INFOSINK_INCLUDED_
-
-#include <math.h>
-#include "compiler/Common.h"
-
-// Returns the fractional part of the given floating-point number.
-inline float fractionalPart(float f) {
-  float intPart = 0.0f;
-  return modff(f, &intPart);
-}
-
-//
-// TPrefixType is used to centralize how info log messages start.
-// See below.
-//
-enum TPrefixType {
-    EPrefixNone,
-    EPrefixWarning,
-    EPrefixError,
-    EPrefixInternalError,
-    EPrefixUnimplemented,
-    EPrefixNote
-};
-
-//
-// Encapsulate info logs for all objects that have them.
-//
-// The methods are a general set of tools for getting a variety of
-// messages and types inserted into the log.
-//
-class TInfoSinkBase {
-public:
-    TInfoSinkBase() {}
-
-    template <typename T>
-    TInfoSinkBase& operator<<(const T& t) {
-        TPersistStringStream stream;
-        stream << t;
-        sink.append(stream.str());
-        return *this;
-    }
-    // Override << operator for specific types. It is faster to append strings
-    // and characters directly to the sink.
-    TInfoSinkBase& operator<<(char c) {
-        sink.append(1, c);
-        return *this;
-    }
-    TInfoSinkBase& operator<<(const char* str) {
-        sink.append(str);
-        return *this;
-    }
-    TInfoSinkBase& operator<<(const TPersistString& str) {
-        sink.append(str);
-        return *this;
-    }
-    TInfoSinkBase& operator<<(const TString& str) {
-        sink.append(str.c_str());
-        return *this;
-    }
-    // Make sure floats are written with correct precision.
-    TInfoSinkBase& operator<<(float f) {
-        // Make sure that at least one decimal point is written. If a number
-        // does not have a fractional part, the default precision format does
-        // not write the decimal portion which gets interpreted as integer by
-        // the compiler.
-        TPersistStringStream stream;
-        if (fractionalPart(f) == 0.0f) {
-            stream.precision(1);
-            stream << std::showpoint << std::fixed << f;
-        } else {
-            stream.unsetf(std::ios::fixed);
-            stream.unsetf(std::ios::scientific);
-            stream.precision(8);
-            stream << f;
-        }
-        sink.append(stream.str());
-        return *this;
-    }
-    // Write boolean values as their names instead of integral value.
-    TInfoSinkBase& operator<<(bool b) {
-        const char* str = b ? "true" : "false";
-        sink.append(str);
-        return *this;
-    }
-
-    void erase() { sink.clear(); }
-    int size() { return static_cast<int>(sink.size()); }
-
-    const TPersistString& str() const { return sink; }
-    const char* c_str() const { return sink.c_str(); }
-
-    void prefix(TPrefixType p);
-    void location(int file, int line);
-    void location(const TSourceLoc& loc);
-    void message(TPrefixType p, const TSourceLoc& loc, const char* m);
-
-private:
-    TPersistString sink;
-};
-
-class TInfoSink {
-public:
-    TInfoSinkBase info;
-    TInfoSinkBase debug;
-    TInfoSinkBase obj;
-};
-
-#endif // _INFOSINK_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/Initialize.cpp b/src/third_party/angle/src/compiler/Initialize.cpp
deleted file mode 100644
index 7138237..0000000
--- a/src/third_party/angle/src/compiler/Initialize.cpp
+++ /dev/null
@@ -1,569 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-//
-// Create strings that declare built-in definitions, add built-ins that
-// cannot be expressed in the files, and establish mappings between 
-// built-in functions and operators.
-//
-
-#if defined(__LB_XB360__)
-# undef near
-# undef far
-#endif
-
-#include "compiler/Initialize.h"
-
-#include "compiler/intermediate.h"
-
-void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
-{
-    TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1);
-    TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2);
-    TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3);
-    TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4);
-
-    TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2);
-    TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3);
-    TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4);
-
-    //
-    // Angle and Trigonometric Functions.
-    //
-    symbolTable.insertBuiltIn(float1, "radians", float1);
-    symbolTable.insertBuiltIn(float2, "radians", float2);
-    symbolTable.insertBuiltIn(float3, "radians", float3);
-    symbolTable.insertBuiltIn(float4, "radians", float4);
-
-    symbolTable.insertBuiltIn(float1, "degrees", float1);
-    symbolTable.insertBuiltIn(float2, "degrees", float2);
-    symbolTable.insertBuiltIn(float3, "degrees", float3);
-    symbolTable.insertBuiltIn(float4, "degrees", float4);
-
-    symbolTable.insertBuiltIn(float1, "sin", float1);
-    symbolTable.insertBuiltIn(float2, "sin", float2);
-    symbolTable.insertBuiltIn(float3, "sin", float3);
-    symbolTable.insertBuiltIn(float4, "sin", float4);
-
-    symbolTable.insertBuiltIn(float1, "cos", float1);
-    symbolTable.insertBuiltIn(float2, "cos", float2);
-    symbolTable.insertBuiltIn(float3, "cos", float3);
-    symbolTable.insertBuiltIn(float4, "cos", float4);
-
-    symbolTable.insertBuiltIn(float1, "tan", float1);
-    symbolTable.insertBuiltIn(float2, "tan", float2);
-    symbolTable.insertBuiltIn(float3, "tan", float3);
-    symbolTable.insertBuiltIn(float4, "tan", float4);
-
-    symbolTable.insertBuiltIn(float1, "asin", float1);
-    symbolTable.insertBuiltIn(float2, "asin", float2);
-    symbolTable.insertBuiltIn(float3, "asin", float3);
-    symbolTable.insertBuiltIn(float4, "asin", float4);
-
-    symbolTable.insertBuiltIn(float1, "acos", float1);
-    symbolTable.insertBuiltIn(float2, "acos", float2);
-    symbolTable.insertBuiltIn(float3, "acos", float3);
-    symbolTable.insertBuiltIn(float4, "acos", float4);
-
-    symbolTable.insertBuiltIn(float1, "atan", float1, float1);
-    symbolTable.insertBuiltIn(float2, "atan", float2, float2);
-    symbolTable.insertBuiltIn(float3, "atan", float3, float3);
-    symbolTable.insertBuiltIn(float4, "atan", float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "atan", float1);
-    symbolTable.insertBuiltIn(float2, "atan", float2);
-    symbolTable.insertBuiltIn(float3, "atan", float3);
-    symbolTable.insertBuiltIn(float4, "atan", float4);
-
-    //
-    // Exponential Functions.
-    //
-    symbolTable.insertBuiltIn(float1, "pow", float1, float1);
-    symbolTable.insertBuiltIn(float2, "pow", float2, float2);
-    symbolTable.insertBuiltIn(float3, "pow", float3, float3);
-    symbolTable.insertBuiltIn(float4, "pow", float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "exp", float1);
-    symbolTable.insertBuiltIn(float2, "exp", float2);
-    symbolTable.insertBuiltIn(float3, "exp", float3);
-    symbolTable.insertBuiltIn(float4, "exp", float4);
-
-    symbolTable.insertBuiltIn(float1, "log", float1);
-    symbolTable.insertBuiltIn(float2, "log", float2);
-    symbolTable.insertBuiltIn(float3, "log", float3);
-    symbolTable.insertBuiltIn(float4, "log", float4);
-
-    symbolTable.insertBuiltIn(float1, "exp2", float1);
-    symbolTable.insertBuiltIn(float2, "exp2", float2);
-    symbolTable.insertBuiltIn(float3, "exp2", float3);
-    symbolTable.insertBuiltIn(float4, "exp2", float4);
-
-    symbolTable.insertBuiltIn(float1, "log2", float1);
-    symbolTable.insertBuiltIn(float2, "log2", float2);
-    symbolTable.insertBuiltIn(float3, "log2", float3);
-    symbolTable.insertBuiltIn(float4, "log2", float4);
-
-    symbolTable.insertBuiltIn(float1, "sqrt", float1);
-    symbolTable.insertBuiltIn(float2, "sqrt", float2);
-    symbolTable.insertBuiltIn(float3, "sqrt", float3);
-    symbolTable.insertBuiltIn(float4, "sqrt", float4);
-
-    symbolTable.insertBuiltIn(float1, "inversesqrt", float1);
-    symbolTable.insertBuiltIn(float2, "inversesqrt", float2);
-    symbolTable.insertBuiltIn(float3, "inversesqrt", float3);
-    symbolTable.insertBuiltIn(float4, "inversesqrt", float4);
-
-    //
-    // Common Functions.
-    //
-    symbolTable.insertBuiltIn(float1, "abs", float1);
-    symbolTable.insertBuiltIn(float2, "abs", float2);
-    symbolTable.insertBuiltIn(float3, "abs", float3);
-    symbolTable.insertBuiltIn(float4, "abs", float4);
-
-    symbolTable.insertBuiltIn(float1, "sign", float1);
-    symbolTable.insertBuiltIn(float2, "sign", float2);
-    symbolTable.insertBuiltIn(float3, "sign", float3);
-    symbolTable.insertBuiltIn(float4, "sign", float4);
-
-    symbolTable.insertBuiltIn(float1, "floor", float1);
-    symbolTable.insertBuiltIn(float2, "floor", float2);
-    symbolTable.insertBuiltIn(float3, "floor", float3);
-    symbolTable.insertBuiltIn(float4, "floor", float4);
-
-    symbolTable.insertBuiltIn(float1, "ceil", float1);
-    symbolTable.insertBuiltIn(float2, "ceil", float2);
-    symbolTable.insertBuiltIn(float3, "ceil", float3);
-    symbolTable.insertBuiltIn(float4, "ceil", float4);
-
-    symbolTable.insertBuiltIn(float1, "fract", float1);
-    symbolTable.insertBuiltIn(float2, "fract", float2);
-    symbolTable.insertBuiltIn(float3, "fract", float3);
-    symbolTable.insertBuiltIn(float4, "fract", float4);
-
-    symbolTable.insertBuiltIn(float1, "mod", float1, float1);
-    symbolTable.insertBuiltIn(float2, "mod", float2, float1);
-    symbolTable.insertBuiltIn(float3, "mod", float3, float1);
-    symbolTable.insertBuiltIn(float4, "mod", float4, float1);
-    symbolTable.insertBuiltIn(float2, "mod", float2, float2);
-    symbolTable.insertBuiltIn(float3, "mod", float3, float3);
-    symbolTable.insertBuiltIn(float4, "mod", float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "min", float1, float1);
-    symbolTable.insertBuiltIn(float2, "min", float2, float1);
-    symbolTable.insertBuiltIn(float3, "min", float3, float1);
-    symbolTable.insertBuiltIn(float4, "min", float4, float1);
-    symbolTable.insertBuiltIn(float2, "min", float2, float2);
-    symbolTable.insertBuiltIn(float3, "min", float3, float3);
-    symbolTable.insertBuiltIn(float4, "min", float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "max", float1, float1);
-    symbolTable.insertBuiltIn(float2, "max", float2, float1);
-    symbolTable.insertBuiltIn(float3, "max", float3, float1);
-    symbolTable.insertBuiltIn(float4, "max", float4, float1);
-    symbolTable.insertBuiltIn(float2, "max", float2, float2);
-    symbolTable.insertBuiltIn(float3, "max", float3, float3);
-    symbolTable.insertBuiltIn(float4, "max", float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1);
-    symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1);
-    symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1);
-    symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1);
-    symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2);
-    symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3);
-    symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1);
-    symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1);
-    symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1);
-    symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1);
-    symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2);
-    symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3);
-    symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "step", float1, float1);
-    symbolTable.insertBuiltIn(float2, "step", float2, float2);
-    symbolTable.insertBuiltIn(float3, "step", float3, float3);
-    symbolTable.insertBuiltIn(float4, "step", float4, float4);
-    symbolTable.insertBuiltIn(float2, "step", float1, float2);
-    symbolTable.insertBuiltIn(float3, "step", float1, float3);
-    symbolTable.insertBuiltIn(float4, "step", float1, float4);
-
-    symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1);
-    symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2);
-    symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3);
-    symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4);
-    symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2);
-    symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3);
-    symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4);
-
-    //
-    // Geometric Functions.
-    //
-    symbolTable.insertBuiltIn(float1, "length", float1);
-    symbolTable.insertBuiltIn(float1, "length", float2);
-    symbolTable.insertBuiltIn(float1, "length", float3);
-    symbolTable.insertBuiltIn(float1, "length", float4);
-
-    symbolTable.insertBuiltIn(float1, "distance", float1, float1);
-    symbolTable.insertBuiltIn(float1, "distance", float2, float2);
-    symbolTable.insertBuiltIn(float1, "distance", float3, float3);
-    symbolTable.insertBuiltIn(float1, "distance", float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "dot", float1, float1);
-    symbolTable.insertBuiltIn(float1, "dot", float2, float2);
-    symbolTable.insertBuiltIn(float1, "dot", float3, float3);
-    symbolTable.insertBuiltIn(float1, "dot", float4, float4);
-
-    symbolTable.insertBuiltIn(float3, "cross", float3, float3);
-    symbolTable.insertBuiltIn(float1, "normalize", float1);
-    symbolTable.insertBuiltIn(float2, "normalize", float2);
-    symbolTable.insertBuiltIn(float3, "normalize", float3);
-    symbolTable.insertBuiltIn(float4, "normalize", float4);
-
-    symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1);
-    symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2);
-    symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3);
-    symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "reflect", float1, float1);
-    symbolTable.insertBuiltIn(float2, "reflect", float2, float2);
-    symbolTable.insertBuiltIn(float3, "reflect", float3, float3);
-    symbolTable.insertBuiltIn(float4, "reflect", float4, float4);
-
-    symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1);
-    symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1);
-    symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1);
-    symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1);
-
-    TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true);
-    TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true);
-    TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true);
-
-    //
-    // Matrix Functions.
-    //
-    symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2);
-    symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3);
-    symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4);
-
-    TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1);
-    TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2);
-    TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3);
-    TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4);
-
-    //
-    // Vector relational functions.
-    //
-    symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2);
-    symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3);
-    symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4);
-
-    symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2);
-    symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3);
-    symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4);
-
-    symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2);
-    symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3);
-    symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4);
-
-    symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2);
-    symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3);
-    symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4);
-
-    symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2);
-    symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3);
-    symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4);
-
-    symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2);
-    symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3);
-    symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4);
-
-    symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2);
-    symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3);
-    symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4);
-
-    symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2);
-    symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3);
-    symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4);
-
-    symbolTable.insertBuiltIn(bool2, "equal", float2, float2);
-    symbolTable.insertBuiltIn(bool3, "equal", float3, float3);
-    symbolTable.insertBuiltIn(bool4, "equal", float4, float4);
-
-    symbolTable.insertBuiltIn(bool2, "equal", int2, int2);
-    symbolTable.insertBuiltIn(bool3, "equal", int3, int3);
-    symbolTable.insertBuiltIn(bool4, "equal", int4, int4);
-
-    symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2);
-    symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3);
-    symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4);
-
-    symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2);
-    symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3);
-    symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4);
-
-    symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2);
-    symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3);
-    symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4);
-
-    symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2);
-    symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3);
-    symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4);
-
-    symbolTable.insertBuiltIn(bool1, "any", bool2);
-    symbolTable.insertBuiltIn(bool1, "any", bool3);
-    symbolTable.insertBuiltIn(bool1, "any", bool4);
-
-    symbolTable.insertBuiltIn(bool1, "all", bool2);
-    symbolTable.insertBuiltIn(bool1, "all", bool3);
-    symbolTable.insertBuiltIn(bool1, "all", bool4);
-
-    symbolTable.insertBuiltIn(bool2, "not", bool2);
-    symbolTable.insertBuiltIn(bool3, "not", bool3);
-    symbolTable.insertBuiltIn(bool4, "not", bool4);
-
-    TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1);
-    TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1);
-
-    //
-    // Texture Functions for GLSL ES 1.0
-    //
-    symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2);
-    symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3);
-    symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4);
-    symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3);
-
-    if (resources.OES_EGL_image_external)
-    {
-        TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1);
-
-        symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2);
-        symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3);
-        symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4);
-    }
-
-    if (resources.ARB_texture_rectangle)
-    {
-        TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1);
-
-        symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2);
-        symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3);
-        symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4);
-    }
-
-    if (type == SH_FRAGMENT_SHADER)
-    {
-        symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1);
-        symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1);
-        symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1);
-        symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1);
-
-        if (resources.OES_standard_derivatives)
-        {
-            symbolTable.insertBuiltIn(float1, "dFdx", float1);
-            symbolTable.insertBuiltIn(float2, "dFdx", float2);
-            symbolTable.insertBuiltIn(float3, "dFdx", float3);
-            symbolTable.insertBuiltIn(float4, "dFdx", float4);
-            
-            symbolTable.insertBuiltIn(float1, "dFdy", float1);
-            symbolTable.insertBuiltIn(float2, "dFdy", float2);
-            symbolTable.insertBuiltIn(float3, "dFdy", float3);
-            symbolTable.insertBuiltIn(float4, "dFdy", float4);
-
-            symbolTable.insertBuiltIn(float1, "fwidth", float1);
-            symbolTable.insertBuiltIn(float2, "fwidth", float2);
-            symbolTable.insertBuiltIn(float3, "fwidth", float3);
-            symbolTable.insertBuiltIn(float4, "fwidth", float4);
-        }
-    }
-
-    if(type == SH_VERTEX_SHADER)
-    {
-        symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1);
-        symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1);
-        symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1);
-        symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1);
-    }
-
-    //
-    // Depth range in window coordinates
-    //
-    TFieldList *fields = NewPoolTFieldList();
-    TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"));
-    TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"));
-    TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"));
-    fields->push_back(near);
-    fields->push_back(far);
-    fields->push_back(diff);
-    TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
-    TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true);
-    symbolTable.insert(*depthRangeParameters);
-    TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
-    depthRange->setQualifier(EvqUniform);
-    symbolTable.insert(*depthRange);
-
-    //
-    // Implementation dependent built-in constants.
-    //
-    symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs);
-    symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors);
-    symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors);
-    symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits);
-    symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits);
-    symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits);
-    symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors);
-
-    if (spec != SH_CSS_SHADERS_SPEC)
-    {
-        symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers);
-    }
-}
-
-void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
-                      const ShBuiltInResources &resources,
-                      TSymbolTable &symbolTable)
-{
-    //
-    // First, insert some special built-in variables that are not in 
-    // the built-in header files.
-    //
-    switch(type) {
-    case SH_FRAGMENT_SHADER:
-        symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"),                       TType(EbtFloat, EbpMedium, EvqFragCoord,   4)));
-        symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"),                     TType(EbtBool,  EbpUndefined, EvqFrontFacing, 1)));
-        symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"),                      TType(EbtFloat, EbpMedium, EvqPointCoord,  2)));
-
-        //
-        // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available.
-        // Instead, css_MixColor and css_ColorMatrix are available.
-        //
-        if (spec != SH_CSS_SHADERS_SPEC) {
-            symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"),                   TType(EbtFloat, EbpMedium, EvqFragColor,   4)));
-            symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData,    4)));
-            if (resources.EXT_frag_depth) {
-                symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"),            TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
-                symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth");
-            }
-        } else {
-            symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"),                   TType(EbtFloat, EbpMedium, EvqGlobal,      4)));
-            symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"),                TType(EbtFloat, EbpMedium, EvqGlobal,      4, true)));
-        }
-
-        break;
-
-    case SH_VERTEX_SHADER:
-        symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"),    TType(EbtFloat, EbpHigh, EvqPosition,    4)));
-        symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"),   TType(EbtFloat, EbpMedium, EvqPointSize,   1)));
-        break;
-
-    default: assert(false && "Language not supported");
-    }
-
-    //
-    // Next, identify which built-ins from the already loaded headers have
-    // a mapping to an operator.  Those that are not identified as such are
-    // expected to be resolved through a library of functions, versus as
-    // operations.
-    //
-    symbolTable.relateToOperator("matrixCompMult",   EOpMul);
-
-    symbolTable.relateToOperator("equal",            EOpVectorEqual);
-    symbolTable.relateToOperator("notEqual",         EOpVectorNotEqual);
-    symbolTable.relateToOperator("lessThan",         EOpLessThan);
-    symbolTable.relateToOperator("greaterThan",      EOpGreaterThan);
-    symbolTable.relateToOperator("lessThanEqual",    EOpLessThanEqual);
-    symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual);
-    
-    symbolTable.relateToOperator("radians",      EOpRadians);
-    symbolTable.relateToOperator("degrees",      EOpDegrees);
-    symbolTable.relateToOperator("sin",          EOpSin);
-    symbolTable.relateToOperator("cos",          EOpCos);
-    symbolTable.relateToOperator("tan",          EOpTan);
-    symbolTable.relateToOperator("asin",         EOpAsin);
-    symbolTable.relateToOperator("acos",         EOpAcos);
-    symbolTable.relateToOperator("atan",         EOpAtan);
-
-    symbolTable.relateToOperator("pow",          EOpPow);
-    symbolTable.relateToOperator("exp2",         EOpExp2);
-    symbolTable.relateToOperator("log",          EOpLog);
-    symbolTable.relateToOperator("exp",          EOpExp);
-    symbolTable.relateToOperator("log2",         EOpLog2);
-    symbolTable.relateToOperator("sqrt",         EOpSqrt);
-    symbolTable.relateToOperator("inversesqrt",  EOpInverseSqrt);
-
-    symbolTable.relateToOperator("abs",          EOpAbs);
-    symbolTable.relateToOperator("sign",         EOpSign);
-    symbolTable.relateToOperator("floor",        EOpFloor);
-    symbolTable.relateToOperator("ceil",         EOpCeil);
-    symbolTable.relateToOperator("fract",        EOpFract);
-    symbolTable.relateToOperator("mod",          EOpMod);
-    symbolTable.relateToOperator("min",          EOpMin);
-    symbolTable.relateToOperator("max",          EOpMax);
-    symbolTable.relateToOperator("clamp",        EOpClamp);
-    symbolTable.relateToOperator("mix",          EOpMix);
-    symbolTable.relateToOperator("step",         EOpStep);
-    symbolTable.relateToOperator("smoothstep",   EOpSmoothStep);
-
-    symbolTable.relateToOperator("length",       EOpLength);
-    symbolTable.relateToOperator("distance",     EOpDistance);
-    symbolTable.relateToOperator("dot",          EOpDot);
-    symbolTable.relateToOperator("cross",        EOpCross);
-    symbolTable.relateToOperator("normalize",    EOpNormalize);
-    symbolTable.relateToOperator("faceforward",  EOpFaceForward);
-    symbolTable.relateToOperator("reflect",      EOpReflect);
-    symbolTable.relateToOperator("refract",      EOpRefract);
-    
-    symbolTable.relateToOperator("any",          EOpAny);
-    symbolTable.relateToOperator("all",          EOpAll);
-    symbolTable.relateToOperator("not",          EOpVectorLogicalNot);
-
-    // Map language-specific operators.
-    switch(type) {
-    case SH_VERTEX_SHADER:
-        break;
-    case SH_FRAGMENT_SHADER:
-        if (resources.OES_standard_derivatives) {
-            symbolTable.relateToOperator("dFdx",   EOpDFdx);
-            symbolTable.relateToOperator("dFdy",   EOpDFdy);
-            symbolTable.relateToOperator("fwidth", EOpFwidth);
-
-            symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives");
-            symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives");
-            symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives");
-        }
-        break;
-    default: break;
-    }
-
-    // Finally add resource-specific variables.
-    switch(type) {
-    case SH_FRAGMENT_SHADER:
-        if (spec != SH_CSS_SHADERS_SPEC) {
-            // Set up gl_FragData.  The array size.
-            TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true);
-            fragData.setArraySize(resources.MaxDrawBuffers);
-            symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"),    fragData));
-        }
-        break;
-    default: break;
-    }
-}
-
-void InitExtensionBehavior(const ShBuiltInResources& resources,
-                           TExtensionBehavior& extBehavior)
-{
-    if (resources.OES_standard_derivatives)
-        extBehavior["GL_OES_standard_derivatives"] = EBhUndefined;
-    if (resources.OES_EGL_image_external)
-        extBehavior["GL_OES_EGL_image_external"] = EBhUndefined;
-    if (resources.ARB_texture_rectangle)
-        extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
-    if (resources.EXT_draw_buffers)
-        extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
-    if (resources.EXT_frag_depth)
-        extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
-}
diff --git a/src/third_party/angle/src/compiler/Initialize.h b/src/third_party/angle/src/compiler/Initialize.h
deleted file mode 100644
index 4aa1346..0000000
--- a/src/third_party/angle/src/compiler/Initialize.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _INITIALIZE_INCLUDED_
-#define _INITIALIZE_INCLUDED_
-
-#include "compiler/Common.h"
-#include "compiler/ShHandle.h"
-#include "compiler/SymbolTable.h"
-
-void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table);
-
-void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
-                      const ShBuiltInResources& resources,
-                      TSymbolTable& symbolTable);
-
-void InitExtensionBehavior(const ShBuiltInResources& resources,
-                           TExtensionBehavior& extensionBehavior);
-
-#endif // _INITIALIZE_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/InitializeDll.cpp b/src/third_party/angle/src/compiler/InitializeDll.cpp
deleted file mode 100644
index 8763cfe..0000000
--- a/src/third_party/angle/src/compiler/InitializeDll.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/InitializeDll.h"
-
-#include "compiler/InitializeGlobals.h"
-#include "compiler/InitializeParseContext.h"
-#include "compiler/osinclude.h"
-
-OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
-
-bool InitProcess()
-{
-    if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
-        //
-        // Function is re-entrant.
-        //
-        return true;
-    }
-
-    ThreadInitializeIndex = OS_AllocTLSIndex();
-
-    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
-        assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
-        return false;
-    }
-
-
-    if (!InitializePoolIndex()) {
-        assert(0 && "InitProcess(): Failed to initalize global pool");
-        return false;
-    }
-
-    if (!InitializeParseContextIndex()) {
-        assert(0 && "InitProcess(): Failed to initalize parse context");
-        return false;
-    }
-
-    return InitThread();
-}
-
-bool DetachProcess()
-{
-    bool success = true;
-
-    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
-        return true;
-
-    success = DetachThread();
-
-    if (!FreeParseContextIndex())
-        success = false;
-
-    FreePoolIndex();
-
-    OS_FreeTLSIndex(ThreadInitializeIndex);
-    ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
-
-    return success;
-}
-
-bool InitThread()
-{
-    //
-    // This function is re-entrant
-    //
-    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
-        assert(0 && "InitThread(): Process hasn't been initalised.");
-        return false;
-    }
-
-    if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
-        return true;
-
-    InitializeGlobalPools();
-
-    if (!InitializeGlobalParseContext())
-        return false;
-
-    if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
-        assert(0 && "InitThread(): Unable to set init flag.");
-        return false;
-    }
-
-    return true;
-}
-
-bool DetachThread()
-{
-    bool success = true;
-
-    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
-        return true;
-
-    //
-    // Function is re-entrant and this thread may not have been initalised.
-    //
-    if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
-        if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
-            assert(0 && "DetachThread(): Unable to clear init flag.");
-            success = false;
-        }
-
-        if (!FreeParseContext())
-            success = false;
-
-        FreeGlobalPools();
-    }
-
-    return success;
-}
-
diff --git a/src/third_party/angle/src/compiler/InitializeDll.h b/src/third_party/angle/src/compiler/InitializeDll.h
deleted file mode 100644
index 857238e..0000000
--- a/src/third_party/angle/src/compiler/InitializeDll.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-#ifndef __INITIALIZEDLL_H
-#define __INITIALIZEDLL_H
-
-bool InitProcess();
-bool DetachProcess();
-
-bool InitThread();
-bool DetachThread();
-
-#endif // __INITIALIZEDLL_H
-
diff --git a/src/third_party/angle/src/compiler/InitializeGlobals.h b/src/third_party/angle/src/compiler/InitializeGlobals.h
deleted file mode 100644
index 842a452..0000000
--- a/src/third_party/angle/src/compiler/InitializeGlobals.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef __INITIALIZE_GLOBALS_INCLUDED_
-#define __INITIALIZE_GLOBALS_INCLUDED_
-
-void InitializeGlobalPools();
-void FreeGlobalPools();
-bool InitializePoolIndex();
-void FreePoolIndex();
-
-#endif // __INITIALIZE_GLOBALS_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/InitializeParseContext.cpp b/src/third_party/angle/src/compiler/InitializeParseContext.cpp
deleted file mode 100644
index 1f40cf5..0000000
--- a/src/third_party/angle/src/compiler/InitializeParseContext.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/InitializeParseContext.h"
-
-#include "compiler/osinclude.h"
-
-OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
-
-bool InitializeParseContextIndex()
-{
-    if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
-        assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
-        return false;
-    }
-
-    //
-    // Allocate a TLS index.
-    //
-    GlobalParseContextIndex = OS_AllocTLSIndex();
-    
-    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
-        assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
-        return false;
-    }
-
-    return true;
-}
-
-bool FreeParseContextIndex()
-{
-    OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
-
-    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
-        assert(0 && "FreeParseContextIndex(): Parse Context index not initalized");
-        return false;
-    }
-
-    GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
-
-    return OS_FreeTLSIndex(tlsiIndex);
-}
-
-bool InitializeGlobalParseContext()
-{
-    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
-        assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized");
-        return false;
-    }
-
-    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
-    if (lpParseContext != 0) {
-        assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
-        return false;
-    }
-
-    TThreadParseContext *lpThreadData = new TThreadParseContext();
-    if (lpThreadData == 0) {
-        assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
-        return false;
-    }
-
-    lpThreadData->lpGlobalParseContext = 0;
-    OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
-
-    return true;
-}
-
-bool FreeParseContext()
-{
-    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
-        assert(0 && "FreeParseContext(): Parse Context index not initalized");
-        return false;
-    }
-
-    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
-    if (lpParseContext)
-        delete lpParseContext;
-
-    return true;
-}
-
-TParseContextPointer& GetGlobalParseContext()
-{
-    //
-    // Minimal error checking for speed
-    //
-
-    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
-
-    return lpParseContext->lpGlobalParseContext;
-}
-
diff --git a/src/third_party/angle/src/compiler/InitializeParseContext.h b/src/third_party/angle/src/compiler/InitializeParseContext.h
deleted file mode 100644
index aa53b73..0000000
--- a/src/third_party/angle/src/compiler/InitializeParseContext.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_
-#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
-
-bool InitializeParseContextIndex();
-bool FreeParseContextIndex();
-
-bool InitializeGlobalParseContext();
-bool FreeParseContext();
-
-struct TParseContext;
-typedef TParseContext* TParseContextPointer;
-extern TParseContextPointer& GetGlobalParseContext();
-#define GlobalParseContext GetGlobalParseContext()
-
-typedef struct TThreadParseContextRec
-{
-    TParseContext *lpGlobalParseContext;
-} TThreadParseContext;
-
-#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/IntermTraverse.cpp b/src/third_party/angle/src/compiler/IntermTraverse.cpp
deleted file mode 100644
index a13877f..0000000
--- a/src/third_party/angle/src/compiler/IntermTraverse.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/intermediate.h"
-
-//
-// Traverse the intermediate representation tree, and
-// call a node type specific function for each node.
-// Done recursively through the member function Traverse().
-// Node types can be skipped if their function to call is 0,
-// but their subtree will still be traversed.
-// Nodes with children can have their whole subtree skipped
-// if preVisit is turned on and the type specific function
-// returns false.
-//
-// preVisit, postVisit, and rightToLeft control what order
-// nodes are visited in.
-//
-
-//
-// Traversal functions for terminals are straighforward....
-//
-void TIntermSymbol::traverse(TIntermTraverser* it)
-{
-	it->visitSymbol(this);
-}
-
-void TIntermConstantUnion::traverse(TIntermTraverser* it)
-{
-	it->visitConstantUnion(this);
-}
-
-//
-// Traverse a binary node.
-//
-void TIntermBinary::traverse(TIntermTraverser* it)
-{
-	bool visit = true;
-
-	//
-	// visit the node before children if pre-visiting.
-	//
-	if(it->preVisit)
-	{
-		visit = it->visitBinary(PreVisit, this);
-	}
-	
-	//
-	// Visit the children, in the right order.
-	//
-	if(visit)
-	{
-		it->incrementDepth();
-
-		if(it->rightToLeft) 
-		{
-			if(right)
-			{
-				right->traverse(it);
-			}
-			
-			if(it->inVisit)
-			{
-				visit = it->visitBinary(InVisit, this);
-			}
-
-			if(visit && left)
-			{
-				left->traverse(it);
-			}
-		}
-		else
-		{
-			if(left)
-			{
-				left->traverse(it);
-			}
-			
-			if(it->inVisit)
-			{
-				visit = it->visitBinary(InVisit, this);
-			}
-
-			if(visit && right)
-			{
-				right->traverse(it);
-			}
-		}
-
-		it->decrementDepth();
-	}
-
-	//
-	// Visit the node after the children, if requested and the traversal
-	// hasn't been cancelled yet.
-	//
-	if(visit && it->postVisit)
-	{
-		it->visitBinary(PostVisit, this);
-	}
-}
-
-//
-// Traverse a unary node.  Same comments in binary node apply here.
-//
-void TIntermUnary::traverse(TIntermTraverser* it)
-{
-	bool visit = true;
-
-	if (it->preVisit)
-		visit = it->visitUnary(PreVisit, this);
-
-	if (visit) {
-		it->incrementDepth();
-		operand->traverse(it);
-		it->decrementDepth();
-	}
-	
-	if (visit && it->postVisit)
-		it->visitUnary(PostVisit, this);
-}
-
-//
-// Traverse an aggregate node.  Same comments in binary node apply here.
-//
-void TIntermAggregate::traverse(TIntermTraverser* it)
-{
-	bool visit = true;
-	
-	if(it->preVisit)
-	{
-		visit = it->visitAggregate(PreVisit, this);
-	}
-	
-	if(visit)
-	{
-		it->incrementDepth();
-
-		if(it->rightToLeft)
-		{
-			for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++)
-			{
-				(*sit)->traverse(it);
-
-				if(visit && it->inVisit)
-				{
-					if(*sit != sequence.front())
-					{
-						visit = it->visitAggregate(InVisit, this);
-					}
-				}
-			}
-		}
-		else
-		{
-			for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
-			{
-				(*sit)->traverse(it);
-
-				if(visit && it->inVisit)
-				{
-					if(*sit != sequence.back())
-					{
-						visit = it->visitAggregate(InVisit, this);
-					}
-				}
-			}
-		}
-		
-		it->decrementDepth();
-	}
-
-	if(visit && it->postVisit)
-	{
-		it->visitAggregate(PostVisit, this);
-	}
-}
-
-//
-// Traverse a selection node.  Same comments in binary node apply here.
-//
-void TIntermSelection::traverse(TIntermTraverser* it)
-{
-	bool visit = true;
-
-	if (it->preVisit)
-		visit = it->visitSelection(PreVisit, this);
-	
-	if (visit) {
-		it->incrementDepth();
-		if (it->rightToLeft) {
-			if (falseBlock)
-				falseBlock->traverse(it);
-			if (trueBlock)
-				trueBlock->traverse(it);
-			condition->traverse(it);
-		} else {
-			condition->traverse(it);
-			if (trueBlock)
-				trueBlock->traverse(it);
-			if (falseBlock)
-				falseBlock->traverse(it);
-		}
-		it->decrementDepth();
-	}
-
-	if (visit && it->postVisit)
-		it->visitSelection(PostVisit, this);
-}
-
-//
-// Traverse a loop node.  Same comments in binary node apply here.
-//
-void TIntermLoop::traverse(TIntermTraverser* it)
-{
-	bool visit = true;
-
-	if(it->preVisit)
-	{
-		visit = it->visitLoop(PreVisit, this);
-	}
-	
-	if(visit)
-	{
-		it->incrementDepth();
-
-		if(it->rightToLeft)
-		{
-			if(expr)
-			{
-				expr->traverse(it);
-			}
-
-			if(body)
-			{
-				body->traverse(it);
-			}
-
-			if(cond)
-			{
-				cond->traverse(it);
-			}
-		}
-		else
-		{
-			if(cond)
-			{
-				cond->traverse(it);
-			}
-
-			if(body)
-			{
-				body->traverse(it);
-			}
-
-			if(expr)
-			{
-				expr->traverse(it);
-			}
-		}
-
-		it->decrementDepth();
-	}
-
-	if(visit && it->postVisit)
-	{
-		it->visitLoop(PostVisit, this);
-	}
-}
-
-//
-// Traverse a branch node.  Same comments in binary node apply here.
-//
-void TIntermBranch::traverse(TIntermTraverser* it)
-{
-	bool visit = true;
-
-	if (it->preVisit)
-		visit = it->visitBranch(PreVisit, this);
-	
-	if (visit && expression) {
-		it->incrementDepth();
-		expression->traverse(it);
-		it->decrementDepth();
-	}
-
-	if (visit && it->postVisit)
-		it->visitBranch(PostVisit, this);
-}
-
diff --git a/src/third_party/angle/src/compiler/Intermediate.cpp b/src/third_party/angle/src/compiler/Intermediate.cpp
deleted file mode 100644
index 3b66221..0000000
--- a/src/third_party/angle/src/compiler/Intermediate.cpp
+++ /dev/null
@@ -1,1442 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-//
-// Build the intermediate representation.
-//
-
-#include <float.h>
-#include <limits.h>
-#include <algorithm>
-
-#include "compiler/HashNames.h"
-#include "compiler/localintermediate.h"
-#include "compiler/QualifierAlive.h"
-#include "compiler/RemoveTree.h"
-
-bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
-
-static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
-    return left > right ? left : right;
-}
-
-const char* getOperatorString(TOperator op) {
-    switch (op) {
-      case EOpInitialize: return "=";
-      case EOpAssign: return "=";
-      case EOpAddAssign: return "+=";
-      case EOpSubAssign: return "-=";
-      case EOpDivAssign: return "/=";
-
-      // Fall-through.
-      case EOpMulAssign: 
-      case EOpVectorTimesMatrixAssign:
-      case EOpVectorTimesScalarAssign:
-      case EOpMatrixTimesScalarAssign:
-      case EOpMatrixTimesMatrixAssign: return "*=";
-
-      // Fall-through.
-      case EOpIndexDirect:
-      case EOpIndexIndirect: return "[]";
-
-      case EOpIndexDirectStruct: return ".";
-      case EOpVectorSwizzle: return ".";
-      case EOpAdd: return "+";
-      case EOpSub: return "-";
-      case EOpMul: return "*";
-      case EOpDiv: return "/";
-      case EOpMod: UNIMPLEMENTED(); break;
-      case EOpEqual: return "==";
-      case EOpNotEqual: return "!=";
-      case EOpLessThan: return "<";
-      case EOpGreaterThan: return ">";
-      case EOpLessThanEqual: return "<=";
-      case EOpGreaterThanEqual: return ">=";
-
-      // Fall-through.
-      case EOpVectorTimesScalar:
-      case EOpVectorTimesMatrix:
-      case EOpMatrixTimesVector:
-      case EOpMatrixTimesScalar:
-      case EOpMatrixTimesMatrix: return "*";
-
-      case EOpLogicalOr: return "||";
-      case EOpLogicalXor: return "^^";
-      case EOpLogicalAnd: return "&&";
-      case EOpNegative: return "-";
-      case EOpVectorLogicalNot: return "not";
-      case EOpLogicalNot: return "!";
-      case EOpPostIncrement: return "++";
-      case EOpPostDecrement: return "--";
-      case EOpPreIncrement: return "++";
-      case EOpPreDecrement: return "--";
-
-      // Fall-through.
-      case EOpConvIntToBool:
-      case EOpConvFloatToBool: return "bool";
- 
-      // Fall-through.
-      case EOpConvBoolToFloat:
-      case EOpConvIntToFloat: return "float";
- 
-      // Fall-through.
-      case EOpConvFloatToInt:
-      case EOpConvBoolToInt: return "int";
-
-      case EOpRadians: return "radians";
-      case EOpDegrees: return "degrees";
-      case EOpSin: return "sin";
-      case EOpCos: return "cos";
-      case EOpTan: return "tan";
-      case EOpAsin: return "asin";
-      case EOpAcos: return "acos";
-      case EOpAtan: return "atan";
-      case EOpExp: return "exp";
-      case EOpLog: return "log";
-      case EOpExp2: return "exp2";
-      case EOpLog2: return "log2";
-      case EOpSqrt: return "sqrt";
-      case EOpInverseSqrt: return "inversesqrt";
-      case EOpAbs: return "abs";
-      case EOpSign: return "sign";
-      case EOpFloor: return "floor";
-      case EOpCeil: return "ceil";
-      case EOpFract: return "fract";
-      case EOpLength: return "length";
-      case EOpNormalize: return "normalize";
-      case EOpDFdx: return "dFdx";
-      case EOpDFdy: return "dFdy";
-      case EOpFwidth: return "fwidth";
-      case EOpAny: return "any";
-      case EOpAll: return "all";
-
-      default: break;
-    }
-    return "";
-}
-
-////////////////////////////////////////////////////////////////////////////
-//
-// First set of functions are to help build the intermediate representation.
-// These functions are not member functions of the nodes.
-// They are called from parser productions.
-//
-/////////////////////////////////////////////////////////////////////////////
-
-//
-// Add a terminal node for an identifier in an expression.
-//
-// Returns the added node.
-//
-TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line)
-{
-    TIntermSymbol* node = new TIntermSymbol(id, name, type);
-    node->setLine(line);
-
-    return node;
-}
-
-//
-// Connect two nodes with a new parent that does a binary operation on the nodes.
-//
-// Returns the added node.
-//
-TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable)
-{
-    switch (op) {
-        case EOpEqual:
-        case EOpNotEqual:
-            if (left->isArray())
-                return 0;
-            break;
-        case EOpLessThan:
-        case EOpGreaterThan:
-        case EOpLessThanEqual:
-        case EOpGreaterThanEqual:
-            if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
-                return 0;
-            }
-            break;
-        case EOpLogicalOr:
-        case EOpLogicalXor:
-        case EOpLogicalAnd:
-            if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
-                return 0;
-            }
-            break;
-        case EOpAdd:
-        case EOpSub:
-        case EOpDiv:
-        case EOpMul:
-            if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
-                return 0;
-        default: break;
-    }
-
-    //
-    // First try converting the children to compatible types.
-    //
-    if (left->getType().getStruct() && right->getType().getStruct()) {
-        if (left->getType() != right->getType())
-            return 0;
-    } else {
-        TIntermTyped* child = addConversion(op, left->getType(), right);
-        if (child)
-            right = child;
-        else {
-            child = addConversion(op, right->getType(), left);
-            if (child)
-                left = child;
-            else
-                return 0;
-        }
-    }
-
-    //
-    // Need a new node holding things together then.  Make
-    // one and promote it to the right type.
-    //
-    TIntermBinary* node = new TIntermBinary(op);
-    node->setLine(line);
-
-    node->setLeft(left);
-    node->setRight(right);
-    if (!node->promote(infoSink))
-        return 0;
-
-    //
-    // See if we can fold constants.
-    //
-    TIntermTyped* typedReturnNode = 0;
-    TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
-    TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
-    if (leftTempConstant && rightTempConstant) {
-        typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
-
-        if (typedReturnNode)
-            return typedReturnNode;
-    }
-
-    return node;
-}
-
-//
-// Connect two nodes through an assignment.
-//
-// Returns the added node.
-//
-TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
-{
-    //
-    // Like adding binary math, except the conversion can only go
-    // from right to left.
-    //
-    TIntermBinary* node = new TIntermBinary(op);
-    node->setLine(line);
-
-    TIntermTyped* child = addConversion(op, left->getType(), right);
-    if (child == 0)
-        return 0;
-
-    node->setLeft(left);
-    node->setRight(child);
-    if (! node->promote(infoSink))
-        return 0;
-
-    return node;
-}
-
-//
-// Connect two nodes through an index operator, where the left node is the base
-// of an array or struct, and the right node is a direct or indirect offset.
-//
-// Returns the added node.
-// The caller should set the type of the returned node.
-//
-TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line)
-{
-    TIntermBinary* node = new TIntermBinary(op);
-    node->setLine(line);
-    node->setLeft(base);
-    node->setRight(index);
-
-    // caller should set the type
-
-    return node;
-}
-
-//
-// Add one node as the parent of another that it operates on.
-//
-// Returns the added node.
-//
-TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable)
-{
-    TIntermUnary* node;
-    TIntermTyped* child = childNode->getAsTyped();
-
-    if (child == 0) {
-        infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath");
-        return 0;
-    }
-
-    switch (op) {
-        case EOpLogicalNot:
-            if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
-                return 0;
-            }
-            break;
-
-        case EOpPostIncrement:
-        case EOpPreIncrement:
-        case EOpPostDecrement:
-        case EOpPreDecrement:
-        case EOpNegative:
-            if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
-                return 0;
-        default: break;
-    }
-
-    //
-    // Do we need to promote the operand?
-    //
-    // Note: Implicit promotions were removed from the language.
-    //
-    TBasicType newType = EbtVoid;
-    switch (op) {
-        case EOpConstructInt:   newType = EbtInt;   break;
-        case EOpConstructBool:  newType = EbtBool;  break;
-        case EOpConstructFloat: newType = EbtFloat; break;
-        default: break;
-    }
-
-    if (newType != EbtVoid) {
-        child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
-            child->getNominalSize(),
-            child->isMatrix(),
-            child->isArray()),
-            child);
-        if (child == 0)
-            return 0;
-    }
-
-    //
-    // For constructors, we are now done, it's all in the conversion.
-    //
-    switch (op) {
-        case EOpConstructInt:
-        case EOpConstructBool:
-        case EOpConstructFloat:
-            return child;
-        default: break;
-    }
-
-    TIntermConstantUnion *childTempConstant = 0;
-    if (child->getAsConstantUnion())
-        childTempConstant = child->getAsConstantUnion();
-
-    //
-    // Make a new node for the operator.
-    //
-    node = new TIntermUnary(op);
-    node->setLine(line);
-    node->setOperand(child);
-
-    if (! node->promote(infoSink))
-        return 0;
-
-    if (childTempConstant)  {
-        TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
-
-        if (newChild)
-            return newChild;
-    }
-
-    return node;
-}
-
-//
-// This is the safe way to change the operator on an aggregate, as it
-// does lots of error checking and fixing.  Especially for establishing
-// a function call's operation on it's set of parameters.  Sequences
-// of instructions are also aggregates, but they just direnctly set
-// their operator to EOpSequence.
-//
-// Returns an aggregate node, which could be the one passed in if
-// it was already an aggregate but no operator was set.
-//
-TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line)
-{
-    TIntermAggregate* aggNode;
-
-    //
-    // Make sure we have an aggregate.  If not turn it into one.
-    //
-    if (node) {
-        aggNode = node->getAsAggregate();
-        if (aggNode == 0 || aggNode->getOp() != EOpNull) {
-            //
-            // Make an aggregate containing this node.
-            //
-            aggNode = new TIntermAggregate();
-            aggNode->getSequence().push_back(node);
-        }
-    } else
-        aggNode = new TIntermAggregate();
-
-    //
-    // Set the operator.
-    //
-    aggNode->setOp(op);
-    aggNode->setLine(line);
-
-    return aggNode;
-}
-
-//
-// Convert one type to another.
-//
-// Returns the node representing the conversion, which could be the same
-// node passed in if no conversion was needed.
-//
-// Return 0 if a conversion can't be done.
-//
-TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
-{
-    //
-    // Does the base type allow operation?
-    //
-    switch (node->getBasicType()) {
-        case EbtVoid:
-        case EbtSampler2D:
-        case EbtSamplerCube:
-            return 0;
-        default: break;
-    }
-
-    //
-    // Otherwise, if types are identical, no problem
-    //
-    if (type == node->getType())
-        return node;
-
-    //
-    // If one's a structure, then no conversions.
-    //
-    if (type.getStruct() || node->getType().getStruct())
-        return 0;
-
-    //
-    // If one's an array, then no conversions.
-    //
-    if (type.isArray() || node->getType().isArray())
-        return 0;
-
-    TBasicType promoteTo;
-
-    switch (op) {
-        //
-        // Explicit conversions
-        //
-        case EOpConstructBool:
-            promoteTo = EbtBool;
-            break;
-        case EOpConstructFloat:
-            promoteTo = EbtFloat;
-            break;
-        case EOpConstructInt:
-            promoteTo = EbtInt;
-            break;
-        default:
-            //
-            // implicit conversions were removed from the language.
-            //
-            if (type.getBasicType() != node->getType().getBasicType())
-                return 0;
-            //
-            // Size and structure could still differ, but that's
-            // handled by operator promotion.
-            //
-            return node;
-    }
-
-    if (node->getAsConstantUnion()) {
-
-        return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
-    } else {
-
-        //
-        // Add a new newNode for the conversion.
-        //
-        TIntermUnary* newNode = 0;
-
-        TOperator newOp = EOpNull;
-        switch (promoteTo) {
-            case EbtFloat:
-                switch (node->getBasicType()) {
-                    case EbtInt:   newOp = EOpConvIntToFloat;  break;
-                    case EbtBool:  newOp = EOpConvBoolToFloat; break;
-                    default:
-                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
-                        return 0;
-                }
-                break;
-            case EbtBool:
-                switch (node->getBasicType()) {
-                    case EbtInt:   newOp = EOpConvIntToBool;   break;
-                    case EbtFloat: newOp = EOpConvFloatToBool; break;
-                    default:
-                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
-                        return 0;
-                }
-                break;
-            case EbtInt:
-                switch (node->getBasicType()) {
-                    case EbtBool:   newOp = EOpConvBoolToInt;  break;
-                    case EbtFloat:  newOp = EOpConvFloatToInt; break;
-                    default:
-                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
-                        return 0;
-                }
-                break;
-            default:
-                infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type");
-                return 0;
-        }
-
-        TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
-        newNode = new TIntermUnary(newOp, type);
-        newNode->setLine(node->getLine());
-        newNode->setOperand(node);
-
-        return newNode;
-    }
-}
-
-//
-// Safe way to combine two nodes into an aggregate.  Works with null pointers,
-// a node that's not a aggregate yet, etc.
-//
-// Returns the resulting aggregate, unless 0 was passed in for
-// both existing nodes.
-//
-TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line)
-{
-    if (left == 0 && right == 0)
-        return 0;
-
-    TIntermAggregate* aggNode = 0;
-    if (left)
-        aggNode = left->getAsAggregate();
-    if (!aggNode || aggNode->getOp() != EOpNull) {
-        aggNode = new TIntermAggregate;
-        if (left)
-            aggNode->getSequence().push_back(left);
-    }
-
-    if (right)
-        aggNode->getSequence().push_back(right);
-
-    aggNode->setLine(line);
-
-    return aggNode;
-}
-
-//
-// Turn an existing node into an aggregate.
-//
-// Returns an aggregate, unless 0 was passed in for the existing node.
-//
-TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line)
-{
-    if (node == 0)
-        return 0;
-
-    TIntermAggregate* aggNode = new TIntermAggregate;
-    aggNode->getSequence().push_back(node);
-    aggNode->setLine(line);
-
-    return aggNode;
-}
-
-//
-// For "if" test nodes.  There are three children; a condition,
-// a true path, and a false path.  The two paths are in the
-// nodePair.
-//
-// Returns the selection node created.
-//
-TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line)
-{
-    //
-    // For compile time constant selections, prune the code and
-    // test now.
-    //
-
-    if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
-        if (cond->getAsConstantUnion()->getBConst(0) == true)
-            return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
-        else
-            return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
-    }
-
-    TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
-    node->setLine(line);
-
-    return node;
-}
-
-
-TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
-{
-    if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
-        return right;
-    } else {
-        TIntermTyped *commaAggregate = growAggregate(left, right, line);
-        commaAggregate->getAsAggregate()->setOp(EOpComma);
-        commaAggregate->setType(right->getType());
-        commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
-        return commaAggregate;
-    }
-}
-
-//
-// For "?:" test nodes.  There are three children; a condition,
-// a true path, and a false path.  The two paths are specified
-// as separate parameters.
-//
-// Returns the selection node created, or 0 if one could not be.
-//
-TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line)
-{
-    //
-    // Get compatible types.
-    //
-    TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
-    if (child)
-        falseBlock = child;
-    else {
-        child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
-        if (child)
-            trueBlock = child;
-        else
-            return 0;
-    }
-
-    //
-    // See if all the operands are constant, then fold it otherwise not.
-    //
-
-    if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
-        if (cond->getAsConstantUnion()->getBConst(0))
-            return trueBlock;
-        else
-            return falseBlock;
-    }
-
-    //
-    // Make a selection node.
-    //
-    TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
-    node->getTypePointer()->setQualifier(EvqTemporary);
-    node->setLine(line);
-
-    return node;
-}
-
-//
-// Constant terminal nodes.  Has a union that contains bool, float or int constants
-//
-// Returns the constant union node created.
-//
-
-TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line)
-{
-    TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
-    node->setLine(line);
-
-    return node;
-}
-
-TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line)
-{
-
-    TIntermAggregate* node = new TIntermAggregate(EOpSequence);
-
-    node->setLine(line);
-    TIntermConstantUnion* constIntNode;
-    TIntermSequence &sequenceVector = node->getSequence();
-    ConstantUnion* unionArray;
-
-    for (int i = 0; i < fields.num; i++) {
-        unionArray = new ConstantUnion[1];
-        unionArray->setIConst(fields.offsets[i]);
-        constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
-        sequenceVector.push_back(constIntNode);
-    }
-
-    return node;
-}
-
-//
-// Create loop nodes.
-//
-TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line)
-{
-    TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
-    node->setLine(line);
-
-    return node;
-}
-
-//
-// Add branches.
-//
-TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line)
-{
-    return addBranch(branchOp, 0, line);
-}
-
-TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line)
-{
-    TIntermBranch* node = new TIntermBranch(branchOp, expression);
-    node->setLine(line);
-
-    return node;
-}
-
-//
-// This is to be executed once the final root is put on top by the parsing
-// process.
-//
-bool TIntermediate::postProcess(TIntermNode* root)
-{
-    if (root == 0)
-        return true;
-
-    //
-    // First, finish off the top level sequence, if any
-    //
-    TIntermAggregate* aggRoot = root->getAsAggregate();
-    if (aggRoot && aggRoot->getOp() == EOpNull)
-        aggRoot->setOp(EOpSequence);
-
-    return true;
-}
-
-//
-// This deletes the tree.
-//
-void TIntermediate::remove(TIntermNode* root)
-{
-    if (root)
-        RemoveAllTreeNodes(root);
-}
-
-////////////////////////////////////////////////////////////////
-//
-// Member functions of the nodes used for building the tree.
-//
-////////////////////////////////////////////////////////////////
-
-//
-// Say whether or not an operation node changes the value of a variable.
-//
-// Returns true if state is modified.
-//
-bool TIntermOperator::modifiesState() const
-{
-    switch (op) {
-        case EOpPostIncrement:
-        case EOpPostDecrement:
-        case EOpPreIncrement:
-        case EOpPreDecrement:
-        case EOpAssign:
-        case EOpAddAssign:
-        case EOpSubAssign:
-        case EOpMulAssign:
-        case EOpVectorTimesMatrixAssign:
-        case EOpVectorTimesScalarAssign:
-        case EOpMatrixTimesScalarAssign:
-        case EOpMatrixTimesMatrixAssign:
-        case EOpDivAssign:
-            return true;
-        default:
-            return false;
-    }
-}
-
-//
-// returns true if the operator is for one of the constructors
-//
-bool TIntermOperator::isConstructor() const
-{
-    switch (op) {
-        case EOpConstructVec2:
-        case EOpConstructVec3:
-        case EOpConstructVec4:
-        case EOpConstructMat2:
-        case EOpConstructMat3:
-        case EOpConstructMat4:
-        case EOpConstructFloat:
-        case EOpConstructIVec2:
-        case EOpConstructIVec3:
-        case EOpConstructIVec4:
-        case EOpConstructInt:
-        case EOpConstructBVec2:
-        case EOpConstructBVec3:
-        case EOpConstructBVec4:
-        case EOpConstructBool:
-        case EOpConstructStruct:
-            return true;
-        default:
-            return false;
-    }
-}
-//
-// Make sure the type of a unary operator is appropriate for its
-// combination of operation and operand type.
-//
-// Returns false in nothing makes sense.
-//
-bool TIntermUnary::promote(TInfoSink&)
-{
-    switch (op) {
-        case EOpLogicalNot:
-            if (operand->getBasicType() != EbtBool)
-                return false;
-            break;
-        case EOpNegative:
-        case EOpPostIncrement:
-        case EOpPostDecrement:
-        case EOpPreIncrement:
-        case EOpPreDecrement:
-            if (operand->getBasicType() == EbtBool)
-                return false;
-            break;
-
-            // operators for built-ins are already type checked against their prototype
-        case EOpAny:
-        case EOpAll:
-        case EOpVectorLogicalNot:
-            return true;
-
-        default:
-            if (operand->getBasicType() != EbtFloat)
-                return false;
-    }
-
-    setType(operand->getType());
-    type.setQualifier(EvqTemporary);
-
-    return true;
-}
-
-//
-// Establishes the type of the resultant operation, as well as
-// makes the operator the correct one for the operands.
-//
-// Returns false if operator can't work on operands.
-//
-bool TIntermBinary::promote(TInfoSink& infoSink)
-{
-    // This function only handles scalars, vectors, and matrices.
-    if (left->isArray() || right->isArray()) {
-        infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays");
-        return false;
-    }
-
-    // GLSL ES 2.0 does not support implicit type casting.
-    // So the basic type should always match.
-    if (left->getBasicType() != right->getBasicType())
-        return false;
-
-    //
-    // Base assumption:  just make the type the same as the left
-    // operand.  Then only deviations from this need be coded.
-    //
-    setType(left->getType());
-
-    // The result gets promoted to the highest precision.
-    TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
-    getTypePointer()->setPrecision(higherPrecision);
-
-    // Binary operations results in temporary variables unless both
-    // operands are const.
-    if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
-        getTypePointer()->setQualifier(EvqTemporary);
-    }
-
-    int size = std::max(left->getNominalSize(), right->getNominalSize());
-
-    //
-    // All scalars. Code after this test assumes this case is removed!
-    //
-    if (size == 1) {
-        switch (op) {
-            //
-            // Promote to conditional
-            //
-            case EOpEqual:
-            case EOpNotEqual:
-            case EOpLessThan:
-            case EOpGreaterThan:
-            case EOpLessThanEqual:
-            case EOpGreaterThanEqual:
-                setType(TType(EbtBool, EbpUndefined));
-                break;
-
-            //
-            // And and Or operate on conditionals
-            //
-            case EOpLogicalAnd:
-            case EOpLogicalOr:
-                // Both operands must be of type bool.
-                if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
-                    return false;
-                setType(TType(EbtBool, EbpUndefined));
-                break;
-
-            default:
-                break;
-        }
-        return true;
-    }
-
-    // If we reach here, at least one of the operands is vector or matrix.
-    // The other operand could be a scalar, vector, or matrix.
-    // Are the sizes compatible?
-    //
-    if (left->getNominalSize() != right->getNominalSize()) {
-        // If the nominal size of operands do not match:
-        // One of them must be scalar.
-        if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
-            return false;
-        // Operator cannot be of type pure assignment.
-        if (op == EOpAssign || op == EOpInitialize)
-            return false;
-    }
-
-    //
-    // Can these two operands be combined?
-    //
-    TBasicType basicType = left->getBasicType();
-    switch (op) {
-        case EOpMul:
-            if (!left->isMatrix() && right->isMatrix()) {
-                if (left->isVector())
-                    op = EOpVectorTimesMatrix;
-                else {
-                    op = EOpMatrixTimesScalar;
-                    setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
-                }
-            } else if (left->isMatrix() && !right->isMatrix()) {
-                if (right->isVector()) {
-                    op = EOpMatrixTimesVector;
-                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
-                } else {
-                    op = EOpMatrixTimesScalar;
-                }
-            } else if (left->isMatrix() && right->isMatrix()) {
-                op = EOpMatrixTimesMatrix;
-            } else if (!left->isMatrix() && !right->isMatrix()) {
-                if (left->isVector() && right->isVector()) {
-                    // leave as component product
-                } else if (left->isVector() || right->isVector()) {
-                    op = EOpVectorTimesScalar;
-                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
-                }
-            } else {
-                infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
-                return false;
-            }
-            break;
-        case EOpMulAssign:
-            if (!left->isMatrix() && right->isMatrix()) {
-                if (left->isVector())
-                    op = EOpVectorTimesMatrixAssign;
-                else {
-                    return false;
-                }
-            } else if (left->isMatrix() && !right->isMatrix()) {
-                if (right->isVector()) {
-                    return false;
-                } else {
-                    op = EOpMatrixTimesScalarAssign;
-                }
-            } else if (left->isMatrix() && right->isMatrix()) {
-                op = EOpMatrixTimesMatrixAssign;
-            } else if (!left->isMatrix() && !right->isMatrix()) {
-                if (left->isVector() && right->isVector()) {
-                    // leave as component product
-                } else if (left->isVector() || right->isVector()) {
-                    if (! left->isVector())
-                        return false;
-                    op = EOpVectorTimesScalarAssign;
-                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
-                }
-            } else {
-                infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
-                return false;
-            }
-            break;
-
-        case EOpAssign:
-        case EOpInitialize:
-        case EOpAdd:
-        case EOpSub:
-        case EOpDiv:
-        case EOpAddAssign:
-        case EOpSubAssign:
-        case EOpDivAssign:
-            if ((left->isMatrix() && right->isVector()) ||
-                (left->isVector() && right->isMatrix()))
-                return false;
-            setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
-            break;
-
-        case EOpEqual:
-        case EOpNotEqual:
-        case EOpLessThan:
-        case EOpGreaterThan:
-        case EOpLessThanEqual:
-        case EOpGreaterThanEqual:
-            if ((left->isMatrix() && right->isVector()) ||
-                (left->isVector() && right->isMatrix()))
-                return false;
-            setType(TType(EbtBool, EbpUndefined));
-            break;
-
-        default:
-            return false;
-    }
-    
-    return true;
-}
-
-bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
-{
-    const TFieldList& fields = leftNodeType.getStruct()->fields();
-
-    size_t structSize = fields.size();
-    size_t index = 0;
-
-    for (size_t j = 0; j < structSize; j++) {
-        size_t size = fields[j]->type()->getObjectSize();
-        for (size_t i = 0; i < size; i++) {
-            if (fields[j]->type()->getBasicType() == EbtStruct) {
-                if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
-                    return false;
-            } else {
-                if (leftUnionArray[index] != rightUnionArray[index])
-                    return false;
-                index++;
-            }
-        }
-    }
-    return true;
-}
-
-bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
-{
-    if (leftNodeType.isArray()) {
-        TType typeWithoutArrayness = leftNodeType;
-        typeWithoutArrayness.clearArrayness();
-
-        size_t arraySize = leftNodeType.getArraySize();
-
-        for (size_t i = 0; i < arraySize; ++i) {
-            size_t offset = typeWithoutArrayness.getObjectSize() * i;
-            if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
-                return false;
-        }
-    } else
-        return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
-
-    return true;
-}
-
-//
-// The fold functions see if an operation on a constant can be done in place,
-// without generating run-time code.
-//
-// Returns the node to keep using, which may or may not be the node passed in.
-//
-
-TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
-{
-    ConstantUnion *unionArray = getUnionArrayPointer();
-    size_t objectSize = getType().getObjectSize();
-
-    if (constantNode) {  // binary operations
-        TIntermConstantUnion *node = constantNode->getAsConstantUnion();
-        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
-        TType returnType = getType();
-
-        // for a case like float f = 1.2 + vec4(2,3,4,5);
-        if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
-            rightUnionArray = new ConstantUnion[objectSize];
-            for (size_t i = 0; i < objectSize; ++i)
-                rightUnionArray[i] = *node->getUnionArrayPointer();
-            returnType = getType();
-        } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
-            // for a case like float f = vec4(2,3,4,5) + 1.2;
-            unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
-            for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
-                unionArray[i] = *getUnionArrayPointer();
-            returnType = node->getType();
-            objectSize = constantNode->getType().getObjectSize();
-        }
-
-        ConstantUnion* tempConstArray = 0;
-        TIntermConstantUnion *tempNode;
-
-        bool boolNodeFlag = false;
-        switch(op) {
-            case EOpAdd:
-                tempConstArray = new ConstantUnion[objectSize];
-                {// support MSVC++6.0
-                    for (size_t i = 0; i < objectSize; i++)
-                        tempConstArray[i] = unionArray[i] + rightUnionArray[i];
-                }
-                break;
-            case EOpSub:
-                tempConstArray = new ConstantUnion[objectSize];
-                {// support MSVC++6.0
-                    for (size_t i = 0; i < objectSize; i++)
-                        tempConstArray[i] = unionArray[i] - rightUnionArray[i];
-                }
-                break;
-
-            case EOpMul:
-            case EOpVectorTimesScalar:
-            case EOpMatrixTimesScalar:
-                tempConstArray = new ConstantUnion[objectSize];
-                {// support MSVC++6.0
-                    for (size_t i = 0; i < objectSize; i++)
-                        tempConstArray[i] = unionArray[i] * rightUnionArray[i];
-                }
-                break;
-            case EOpMatrixTimesMatrix:
-                if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
-                    infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply");
-                    return 0;
-                }
-                {// support MSVC++6.0
-                    int size = getNominalSize();
-                    tempConstArray = new ConstantUnion[size*size];
-                    for (int row = 0; row < size; row++) {
-                        for (int column = 0; column < size; column++) {
-                            tempConstArray[size * column + row].setFConst(0.0f);
-                            for (int i = 0; i < size; i++) {
-                                tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
-                            }
-                        }
-                    }
-                }
-                break;
-            case EOpDiv:
-                tempConstArray = new ConstantUnion[objectSize];
-                {// support MSVC++6.0
-                    for (size_t i = 0; i < objectSize; i++) {
-                        switch (getType().getBasicType()) {
-            case EbtFloat:
-                if (rightUnionArray[i] == 0.0f) {
-                    infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
-                    tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
-                } else
-                    tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
-                break;
-
-            case EbtInt:
-                if (rightUnionArray[i] == 0) {
-                    infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
-                    tempConstArray[i].setIConst(INT_MAX);
-                } else
-                    tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
-                break;
-            default:
-                infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\"");
-                return 0;
-                        }
-                    }
-                }
-                break;
-
-            case EOpMatrixTimesVector:
-                if (node->getBasicType() != EbtFloat) {
-                    infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector");
-                    return 0;
-                }
-                tempConstArray = new ConstantUnion[getNominalSize()];
-
-                {// support MSVC++6.0
-                    for (int size = getNominalSize(), i = 0; i < size; i++) {
-                        tempConstArray[i].setFConst(0.0f);
-                        for (int j = 0; j < size; j++) {
-                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
-                        }
-                    }
-                }
-
-                tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
-                tempNode->setLine(getLine());
-
-                return tempNode;
-
-            case EOpVectorTimesMatrix:
-                if (getType().getBasicType() != EbtFloat) {
-                    infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix");
-                    return 0;
-                }
-
-                tempConstArray = new ConstantUnion[getNominalSize()];
-                {// support MSVC++6.0
-                    for (int size = getNominalSize(), i = 0; i < size; i++) {
-                        tempConstArray[i].setFConst(0.0f);
-                        for (int j = 0; j < size; j++) {
-                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
-                        }
-                    }
-                }
-                break;
-
-            case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
-                tempConstArray = new ConstantUnion[objectSize];
-                {// support MSVC++6.0
-                    for (size_t i = 0; i < objectSize; i++)
-                        tempConstArray[i] = unionArray[i] && rightUnionArray[i];
-                }
-                break;
-
-            case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
-                tempConstArray = new ConstantUnion[objectSize];
-                {// support MSVC++6.0
-                    for (size_t i = 0; i < objectSize; i++)
-                        tempConstArray[i] = unionArray[i] || rightUnionArray[i];
-                }
-                break;
-
-            case EOpLogicalXor:
-                tempConstArray = new ConstantUnion[objectSize];
-                {// support MSVC++6.0
-                    for (size_t i = 0; i < objectSize; i++)
-                        switch (getType().getBasicType()) {
-            case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
-            default: assert(false && "Default missing");
-                    }
-                }
-                break;
-
-            case EOpLessThan:
-                assert(objectSize == 1);
-                tempConstArray = new ConstantUnion[1];
-                tempConstArray->setBConst(*unionArray < *rightUnionArray);
-                returnType = TType(EbtBool, EbpUndefined, EvqConst);
-                break;
-            case EOpGreaterThan:
-                assert(objectSize == 1);
-                tempConstArray = new ConstantUnion[1];
-                tempConstArray->setBConst(*unionArray > *rightUnionArray);
-                returnType = TType(EbtBool, EbpUndefined, EvqConst);
-                break;
-            case EOpLessThanEqual:
-                {
-                    assert(objectSize == 1);
-                    ConstantUnion constant;
-                    constant.setBConst(*unionArray > *rightUnionArray);
-                    tempConstArray = new ConstantUnion[1];
-                    tempConstArray->setBConst(!constant.getBConst());
-                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
-                    break;
-                }
-            case EOpGreaterThanEqual:
-                {
-                    assert(objectSize == 1);
-                    ConstantUnion constant;
-                    constant.setBConst(*unionArray < *rightUnionArray);
-                    tempConstArray = new ConstantUnion[1];
-                    tempConstArray->setBConst(!constant.getBConst());
-                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
-                    break;
-                }
-
-            case EOpEqual:
-                if (getType().getBasicType() == EbtStruct) {
-                    if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
-                        boolNodeFlag = true;
-                } else {
-                    for (size_t i = 0; i < objectSize; i++) {
-                        if (unionArray[i] != rightUnionArray[i]) {
-                            boolNodeFlag = true;
-                            break;  // break out of for loop
-                        }
-                    }
-                }
-
-                tempConstArray = new ConstantUnion[1];
-                if (!boolNodeFlag) {
-                    tempConstArray->setBConst(true);
-                }
-                else {
-                    tempConstArray->setBConst(false);
-                }
-
-                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
-                tempNode->setLine(getLine());
-
-                return tempNode;
-
-            case EOpNotEqual:
-                if (getType().getBasicType() == EbtStruct) {
-                    if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
-                        boolNodeFlag = true;
-                } else {
-                    for (size_t i = 0; i < objectSize; i++) {
-                        if (unionArray[i] == rightUnionArray[i]) {
-                            boolNodeFlag = true;
-                            break;  // break out of for loop
-                        }
-                    }
-                }
-
-                tempConstArray = new ConstantUnion[1];
-                if (!boolNodeFlag) {
-                    tempConstArray->setBConst(true);
-                }
-                else {
-                    tempConstArray->setBConst(false);
-                }
-
-                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
-                tempNode->setLine(getLine());
-
-                return tempNode;
-
-            default:
-                infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding");
-                return 0;
-        }
-        tempNode = new TIntermConstantUnion(tempConstArray, returnType);
-        tempNode->setLine(getLine());
-
-        return tempNode;
-    } else {
-        //
-        // Do unary operations
-        //
-        TIntermConstantUnion *newNode = 0;
-        ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
-        for (size_t i = 0; i < objectSize; i++) {
-            switch(op) {
-                case EOpNegative:
-                    switch (getType().getBasicType()) {
-                        case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
-                        case EbtInt:   tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
-                        default:
-                            infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
-                            return 0;
-                    }
-                    break;
-                case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
-                    switch (getType().getBasicType()) {
-                        case EbtBool:  tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
-                        default:
-                            infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
-                            return 0;
-                    }
-                    break;
-                default:
-                    return 0;
-            }
-        }
-        newNode = new TIntermConstantUnion(tempConstArray, getType());
-        newNode->setLine(getLine());
-        return newNode;
-    }
-}
-
-TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
-{
-    size_t size = node->getType().getObjectSize();
-
-    ConstantUnion *leftUnionArray = new ConstantUnion[size];
-
-    for (size_t i = 0; i < size; i++) {
-
-        switch (promoteTo) {
-            case EbtFloat:
-                switch (node->getType().getBasicType()) {
-                    case EbtInt:
-                        leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
-                        break;
-                    case EbtBool:
-                        leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
-                        break;
-                    case EbtFloat:
-                        leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
-                        break;
-                    default:
-                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
-                        return 0;
-                }
-                break;
-            case EbtInt:
-                switch (node->getType().getBasicType()) {
-                    case EbtInt:
-                        leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
-                        break;
-                    case EbtBool:
-                        leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
-                        break;
-                    case EbtFloat:
-                        leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
-                        break;
-                    default:
-                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
-                        return 0;
-                }
-                break;
-            case EbtBool:
-                switch (node->getType().getBasicType()) {
-                    case EbtInt:
-                        leftUnionArray[i].setBConst(node->getIConst(i) != 0);
-                        break;
-                    case EbtBool:
-                        leftUnionArray[i].setBConst(node->getBConst(i));
-                        break;
-                    case EbtFloat:
-                        leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
-                        break;
-                    default:
-                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
-                        return 0;
-                }
-
-                break;
-            default:
-                infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found");
-                return 0;
-        }
-
-    }
-
-    const TType& t = node->getType();
-
-    return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
-}
-
-// static
-TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction)
-{
-    if (hashFunction == NULL || name.empty())
-        return name;
-    khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
-    TStringStream stream;
-    stream << HASHED_NAME_PREFIX << std::hex << number;
-    TString hashedName = stream.str();
-    return hashedName;
-}
diff --git a/src/third_party/angle/src/compiler/MMap.h b/src/third_party/angle/src/compiler/MMap.h
deleted file mode 100644
index a308671..0000000
--- a/src/third_party/angle/src/compiler/MMap.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _MMAP_INCLUDED_
-#define _MMAP_INCLUDED_
-
-//
-// Encapsulate memory mapped files
-//
-
-class TMMap {
-public:
-    TMMap(const char* fileName) : 
-        fSize(-1), // -1 is the error value returned by GetFileSize()
-        fp(NULL),
-        fBuff(0)   // 0 is the error value returned by MapViewOfFile()
-    {
-        if ((fp = fopen(fileName, "r")) == NULL)
-            return;
-        char c = getc(fp);
-        fSize = 0;
-        while (c != EOF) {
-            fSize++;
-            c = getc(fp);
-        }
-        if (c == EOF)
-            fSize++;
-        rewind(fp);
-        fBuff = (char*)malloc(sizeof(char) * fSize);
-        int count = 0;
-        c = getc(fp);
-        while (c != EOF) {
-            fBuff[count++] = c;
-            c = getc(fp);
-        }
-        fBuff[count++] = c;
-    }
-
-    char* getData() { return fBuff; }
-    int   getSize() { return fSize; }
-
-    ~TMMap() {
-        if (fp != NULL)
-            fclose(fp);
-    }
-    
-private:
-    int             fSize;      // size of file to map in
-    FILE *fp;
-    char*           fBuff;      // the actual data;
-};
-
-#endif // _MMAP_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/MapLongVariableNames.cpp b/src/third_party/angle/src/compiler/MapLongVariableNames.cpp
deleted file mode 100644
index a41d20f..0000000
--- a/src/third_party/angle/src/compiler/MapLongVariableNames.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/MapLongVariableNames.h"
-
-namespace {
-
-TString mapLongName(size_t id, const TString& name, bool isGlobal)
-{
-    ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE);
-    TStringStream stream;
-    stream << "webgl_";
-    if (isGlobal)
-        stream << "g";
-    stream << id;
-    if (name[0] != '_')
-        stream << "_";
-    stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size());
-    return stream.str();
-}
-
-LongNameMap* gLongNameMapInstance = NULL;
-
-}  // anonymous namespace
-
-LongNameMap::LongNameMap()
-    : refCount(0)
-{
-}
-
-LongNameMap::~LongNameMap()
-{
-}
-
-// static
-LongNameMap* LongNameMap::GetInstance()
-{
-    if (gLongNameMapInstance == NULL)
-        gLongNameMapInstance = new LongNameMap;
-    gLongNameMapInstance->refCount++;
-    return gLongNameMapInstance;
-}
-
-void LongNameMap::Release()
-{
-    ASSERT(gLongNameMapInstance == this);
-    ASSERT(refCount > 0);
-    refCount--;
-    if (refCount == 0) {
-        delete gLongNameMapInstance;
-        gLongNameMapInstance = NULL;
-    }
-}
-
-const char* LongNameMap::Find(const char* originalName) const
-{
-    std::map<std::string, std::string>::const_iterator it = mLongNameMap.find(
-        originalName);
-    if (it != mLongNameMap.end())
-        return (*it).second.c_str();
-    return NULL;
-}
-
-void LongNameMap::Insert(const char* originalName, const char* mappedName)
-{
-    mLongNameMap.insert(std::map<std::string, std::string>::value_type(
-        originalName, mappedName));
-}
-
-size_t LongNameMap::Size() const
-{
-    return mLongNameMap.size();
-}
-
-MapLongVariableNames::MapLongVariableNames(LongNameMap* globalMap)
-{
-    ASSERT(globalMap);
-    mGlobalMap = globalMap;
-}
-
-void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol)
-{
-    ASSERT(symbol != NULL);
-    if (symbol->getSymbol().size() > MAX_SHORTENED_IDENTIFIER_SIZE) {
-        switch (symbol->getQualifier()) {
-          case EvqVaryingIn:
-          case EvqVaryingOut:
-          case EvqInvariantVaryingIn:
-          case EvqInvariantVaryingOut:
-          case EvqUniform:
-            symbol->setSymbol(
-                mapGlobalLongName(symbol->getSymbol()));
-            break;
-          default:
-            symbol->setSymbol(
-                mapLongName(symbol->getId(), symbol->getSymbol(), false));
-            break;
-        };
-    }
-}
-
-bool MapLongVariableNames::visitLoop(Visit, TIntermLoop* node)
-{
-    if (node->getInit())
-        node->getInit()->traverse(this);
-    return true;
-}
-
-TString MapLongVariableNames::mapGlobalLongName(const TString& name)
-{
-    ASSERT(mGlobalMap);
-    const char* mappedName = mGlobalMap->Find(name.c_str());
-    if (mappedName != NULL)
-        return mappedName;
-    size_t id = mGlobalMap->Size();
-    TString rt = mapLongName(id, name, true);
-    mGlobalMap->Insert(name.c_str(), rt.c_str());
-    return rt;
-}
diff --git a/src/third_party/angle/src/compiler/MapLongVariableNames.h b/src/third_party/angle/src/compiler/MapLongVariableNames.h
deleted file mode 100644
index d6352ac..0000000
--- a/src/third_party/angle/src/compiler/MapLongVariableNames.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_MAP_LONG_VARIABLE_NAMES_H_
-#define COMPILER_MAP_LONG_VARIABLE_NAMES_H_
-
-#include "GLSLANG/ShaderLang.h"
-
-#include "compiler/intermediate.h"
-#include "compiler/VariableInfo.h"
-
-// This size does not include '\0' in the end.
-#define MAX_SHORTENED_IDENTIFIER_SIZE 32
-
-// This is a ref-counted singleton. GetInstance() returns a pointer to the
-// singleton, and after use, call Release(). GetInstance() and Release() should
-// be paired.
-class LongNameMap {
-public:
-    static LongNameMap* GetInstance();
-    void Release();
-
-    // Return the mapped name if <originalName, mappedName> is in the map;
-    // otherwise, return NULL.
-    const char* Find(const char* originalName) const;
-
-    // Insert a pair into the map.
-    void Insert(const char* originalName, const char* mappedName);
-
-    // Return the number of entries in the map.
-    size_t Size() const;
-
-private:
-    LongNameMap();
-    ~LongNameMap();
-
-    size_t refCount;
-    std::map<std::string, std::string> mLongNameMap;
-};
-
-// Traverses intermediate tree to map attributes and uniforms names that are
-// longer than MAX_SHORTENED_IDENTIFIER_SIZE to MAX_SHORTENED_IDENTIFIER_SIZE.
-class MapLongVariableNames : public TIntermTraverser {
-public:
-    MapLongVariableNames(LongNameMap* globalMap);
-
-    virtual void visitSymbol(TIntermSymbol*);
-    virtual bool visitLoop(Visit, TIntermLoop*);
-
-private:
-    TString mapGlobalLongName(const TString& name);
-
-    LongNameMap* mGlobalMap;
-};
-
-#endif  // COMPILER_MAP_LONG_VARIABLE_NAMES_H_
diff --git a/src/third_party/angle/src/compiler/OutputESSL.cpp b/src/third_party/angle/src/compiler/OutputESSL.cpp
deleted file mode 100644
index c2048f1..0000000
--- a/src/third_party/angle/src/compiler/OutputESSL.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/OutputESSL.h"
-
-TOutputESSL::TOutputESSL(TInfoSinkBase& objSink,
-                         ShArrayIndexClampingStrategy clampingStrategy,
-                         ShHashFunction64 hashFunction,
-                         NameMap& nameMap,
-                         TSymbolTable& symbolTable)
-    : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
-{
-}
-
-bool TOutputESSL::writeVariablePrecision(TPrecision precision)
-{
-    if (precision == EbpUndefined)
-        return false;
-
-    TInfoSinkBase& out = objSink();
-    out << getPrecisionString(precision);
-    return true;
-}
diff --git a/src/third_party/angle/src/compiler/OutputESSL.h b/src/third_party/angle/src/compiler/OutputESSL.h
deleted file mode 100644
index 05db96e..0000000
--- a/src/third_party/angle/src/compiler/OutputESSL.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_
-#define CROSSCOMPILERGLSL_OUTPUTESSL_H_
-
-#include "compiler/OutputGLSLBase.h"
-
-class TOutputESSL : public TOutputGLSLBase
-{
-public:
-    TOutputESSL(TInfoSinkBase& objSink,
-                ShArrayIndexClampingStrategy clampingStrategy,
-                ShHashFunction64 hashFunction,
-                NameMap& nameMap,
-                TSymbolTable& symbolTable);
-
-protected:
-    virtual bool writeVariablePrecision(TPrecision precision);
-};
-
-#endif  // CROSSCOMPILERGLSL_OUTPUTESSL_H_
diff --git a/src/third_party/angle/src/compiler/OutputGLSL.cpp b/src/third_party/angle/src/compiler/OutputGLSL.cpp
deleted file mode 100644
index 10a451c..0000000
--- a/src/third_party/angle/src/compiler/OutputGLSL.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/OutputGLSL.h"
-
-TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
-                         ShArrayIndexClampingStrategy clampingStrategy,
-                         ShHashFunction64 hashFunction,
-                         NameMap& nameMap,
-                         TSymbolTable& symbolTable)
-    : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
-{
-}
-
-bool TOutputGLSL::writeVariablePrecision(TPrecision)
-{
-    return false;
-}
-
-void TOutputGLSL::visitSymbol(TIntermSymbol* node)
-{
-    TInfoSinkBase& out = objSink();
-
-    if (node->getSymbol() == "gl_FragDepthEXT")
-    {
-        out << "gl_FragDepth";
-    }
-    else
-    {
-        TOutputGLSLBase::visitSymbol(node);
-    }
-}
diff --git a/src/third_party/angle/src/compiler/OutputGLSL.h b/src/third_party/angle/src/compiler/OutputGLSL.h
deleted file mode 100644
index fa68ac8..0000000
--- a/src/third_party/angle/src/compiler/OutputGLSL.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_
-#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_
-
-#include "compiler/OutputGLSLBase.h"
-
-class TOutputGLSL : public TOutputGLSLBase
-{
-public:
-    TOutputGLSL(TInfoSinkBase& objSink,
-                ShArrayIndexClampingStrategy clampingStrategy,
-                ShHashFunction64 hashFunction,
-                NameMap& nameMap,
-                TSymbolTable& symbolTable);
-
-protected:
-    virtual bool writeVariablePrecision(TPrecision);
-    virtual void visitSymbol(TIntermSymbol* node);
-};
-
-#endif  // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
diff --git a/src/third_party/angle/src/compiler/OutputGLSLBase.cpp b/src/third_party/angle/src/compiler/OutputGLSLBase.cpp
deleted file mode 100644
index d677c75..0000000
--- a/src/third_party/angle/src/compiler/OutputGLSLBase.cpp
+++ /dev/null
@@ -1,817 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/OutputGLSLBase.h"
-#include "compiler/debug.h"
-
-#include <cfloat>
-
-namespace
-{
-TString arrayBrackets(const TType& type)
-{
-    ASSERT(type.isArray());
-    TInfoSinkBase out;
-    out << "[" << type.getArraySize() << "]";
-    return TString(out.c_str());
-}
-
-bool isSingleStatement(TIntermNode* node) {
-    if (const TIntermAggregate* aggregate = node->getAsAggregate())
-    {
-        return (aggregate->getOp() != EOpFunction) &&
-               (aggregate->getOp() != EOpSequence);
-    }
-    else if (const TIntermSelection* selection = node->getAsSelectionNode())
-    {
-        // Ternary operators are usually part of an assignment operator.
-        // This handles those rare cases in which they are all by themselves.
-        return selection->usesTernaryOperator();
-    }
-    else if (node->getAsLoopNode())
-    {
-        return false;
-    }
-    return true;
-}
-}  // namespace
-
-TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink,
-                                 ShArrayIndexClampingStrategy clampingStrategy,
-                                 ShHashFunction64 hashFunction,
-                                 NameMap& nameMap,
-                                 TSymbolTable& symbolTable)
-    : TIntermTraverser(true, true, true),
-      mObjSink(objSink),
-      mDeclaringVariables(false),
-      mClampingStrategy(clampingStrategy),
-      mHashFunction(hashFunction),
-      mNameMap(nameMap),
-      mSymbolTable(symbolTable)
-{
-}
-
-void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
-{
-    TInfoSinkBase& out = objSink();
-    if (visit == PreVisit && preStr)
-    {
-        out << preStr;
-    }
-    else if (visit == InVisit && inStr)
-    {
-        out << inStr;
-    }
-    else if (visit == PostVisit && postStr)
-    {
-        out << postStr;
-    }
-}
-
-void TOutputGLSLBase::writeVariableType(const TType& type)
-{
-    TInfoSinkBase& out = objSink();
-    TQualifier qualifier = type.getQualifier();
-    // TODO(alokp): Validate qualifier for variable declarations.
-    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
-        out << type.getQualifierString() << " ";
-    // Declare the struct if we have not done so already.
-    if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
-    {
-        declareStruct(type.getStruct());
-    }
-    else
-    {
-        if (writeVariablePrecision(type.getPrecision()))
-            out << " ";
-        out << getTypeName(type);
-    }
-}
-
-void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args)
-{
-    TInfoSinkBase& out = objSink();
-    for (TIntermSequence::const_iterator iter = args.begin();
-         iter != args.end(); ++iter)
-    {
-        const TIntermSymbol* arg = (*iter)->getAsSymbolNode();
-        ASSERT(arg != NULL);
-
-        const TType& type = arg->getType();
-        writeVariableType(type);
-
-        const TString& name = arg->getSymbol();
-        if (!name.empty())
-            out << " " << hashName(name);
-        if (type.isArray())
-            out << arrayBrackets(type);
-
-        // Put a comma if this is not the last argument.
-        if (iter != args.end() - 1)
-            out << ", ";
-    }
-}
-
-const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
-                                                         const ConstantUnion* pConstUnion)
-{
-    TInfoSinkBase& out = objSink();
-
-    if (type.getBasicType() == EbtStruct)
-    {
-        const TStructure* structure = type.getStruct();
-        out << hashName(structure->name()) << "(";
-
-        const TFieldList& fields = structure->fields();
-        for (size_t i = 0; i < fields.size(); ++i)
-        {
-            const TType* fieldType = fields[i]->type();
-            ASSERT(fieldType != NULL);
-            pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
-            if (i != fields.size() - 1) out << ", ";
-        }
-        out << ")";
-    }
-    else
-    {
-        size_t size = type.getObjectSize();
-        bool writeType = size > 1;
-        if (writeType) out << getTypeName(type) << "(";
-        for (size_t i = 0; i < size; ++i, ++pConstUnion)
-        {
-            switch (pConstUnion->getType())
-            {
-                case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); break;
-                case EbtInt: out << pConstUnion->getIConst(); break;
-                case EbtBool: out << pConstUnion->getBConst(); break;
-                default: UNREACHABLE();
-            }
-            if (i != size - 1) out << ", ";
-        }
-        if (writeType) out << ")";
-    }
-    return pConstUnion;
-}
-
-void TOutputGLSLBase::visitSymbol(TIntermSymbol* node)
-{
-    TInfoSinkBase& out = objSink();
-    if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node))
-        out << mLoopUnroll.GetLoopIndexValue(node);
-    else
-        out << hashVariableName(node->getSymbol());
-
-    if (mDeclaringVariables && node->getType().isArray())
-        out << arrayBrackets(node->getType());
-}
-
-void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node)
-{
-    writeConstantUnion(node->getType(), node->getUnionArrayPointer());
-}
-
-bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
-{
-    bool visitChildren = true;
-    TInfoSinkBase& out = objSink();
-    switch (node->getOp())
-    {
-        case EOpInitialize:
-            if (visit == InVisit)
-            {
-                out << " = ";
-                // RHS of initialize is not being declared.
-                mDeclaringVariables = false;
-            }
-            break;
-        case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
-        case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
-        case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
-        case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
-        // Notice the fall-through.
-        case EOpMulAssign: 
-        case EOpVectorTimesMatrixAssign:
-        case EOpVectorTimesScalarAssign:
-        case EOpMatrixTimesScalarAssign:
-        case EOpMatrixTimesMatrixAssign:
-            writeTriplet(visit, "(", " *= ", ")");
-            break;
-
-        case EOpIndexDirect:
-            writeTriplet(visit, NULL, "[", "]");
-            break;
-        case EOpIndexIndirect:
-            if (node->getAddIndexClamp())
-            {
-                if (visit == InVisit)
-                {
-                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
-                        out << "[int(clamp(float(";
-                    } else {
-                        out << "[webgl_int_clamp(";
-                    }
-                }
-                else if (visit == PostVisit)
-                {
-                    int maxSize;
-                    TIntermTyped *left = node->getLeft();
-                    TType leftType = left->getType();
-
-                    if (left->isArray())
-                    {
-                        // The shader will fail validation if the array length is not > 0.
-                        maxSize = leftType.getArraySize() - 1;
-                    }
-                    else
-                    {
-                        maxSize = leftType.getNominalSize() - 1;
-                    }
-
-                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
-                        out << "), 0.0, float(" << maxSize << ")))]";
-                    } else {
-                        out << ", 0, " << maxSize << ")]";
-                    }
-                }
-            }
-            else
-            {
-                writeTriplet(visit, NULL, "[", "]");
-            }
-            break;
-        case EOpIndexDirectStruct:
-            if (visit == InVisit)
-            {
-                // Here we are writing out "foo.bar", where "foo" is struct
-                // and "bar" is field. In AST, it is represented as a binary
-                // node, where left child represents "foo" and right child "bar".
-                // The node itself represents ".". The struct field "bar" is
-                // actually stored as an index into TStructure::fields.
-                out << ".";
-                const TStructure* structure = node->getLeft()->getType().getStruct();
-                const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
-                const TField* field = structure->fields()[index->getIConst(0)];
-
-                TString fieldName = field->name();
-                if (!mSymbolTable.findBuiltIn(structure->name()))
-                    fieldName = hashName(fieldName);
-
-                out << fieldName;
-                visitChildren = false;
-            }
-            break;
-        case EOpVectorSwizzle:
-            if (visit == InVisit)
-            {
-                out << ".";
-                TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
-                TIntermSequence& sequence = rightChild->getSequence();
-                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
-                {
-                    TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
-                    ASSERT(element->getBasicType() == EbtInt);
-                    ASSERT(element->getNominalSize() == 1);
-                    const ConstantUnion& data = element->getUnionArrayPointer()[0];
-                    ASSERT(data.getType() == EbtInt);
-                    switch (data.getIConst())
-                    {
-                        case 0: out << "x"; break;
-                        case 1: out << "y"; break;
-                        case 2: out << "z"; break;
-                        case 3: out << "w"; break;
-                        default: UNREACHABLE(); break;
-                    }
-                }
-                visitChildren = false;
-            }
-            break;
-
-        case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
-        case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
-        case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
-        case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
-        case EOpMod: UNIMPLEMENTED(); break;
-        case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
-        case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
-        case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
-        case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
-        case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
-        case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
-
-        // Notice the fall-through.
-        case EOpVectorTimesScalar:
-        case EOpVectorTimesMatrix:
-        case EOpMatrixTimesVector:
-        case EOpMatrixTimesScalar:
-        case EOpMatrixTimesMatrix:
-            writeTriplet(visit, "(", " * ", ")");
-            break;
-
-        case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
-        case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
-        case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
-        default: UNREACHABLE(); break;
-    }
-
-    return visitChildren;
-}
-
-bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node)
-{
-    TString preString;
-    TString postString = ")";
-
-    switch (node->getOp())
-    {
-        case EOpNegative: preString = "(-"; break;
-        case EOpVectorLogicalNot: preString = "not("; break;
-        case EOpLogicalNot: preString = "(!"; break;
-
-        case EOpPostIncrement: preString = "("; postString = "++)"; break;
-        case EOpPostDecrement: preString = "("; postString = "--)"; break;
-        case EOpPreIncrement: preString = "(++"; break;
-        case EOpPreDecrement: preString = "(--"; break;
-
-        case EOpConvIntToBool:
-        case EOpConvFloatToBool:
-            switch (node->getOperand()->getType().getNominalSize())
-            {
-                case 1: preString =  "bool(";  break;
-                case 2: preString = "bvec2("; break;
-                case 3: preString = "bvec3("; break;
-                case 4: preString = "bvec4("; break;
-                default: UNREACHABLE();
-            }
-            break;
-        case EOpConvBoolToFloat:
-        case EOpConvIntToFloat:
-            switch (node->getOperand()->getType().getNominalSize())
-            {
-                case 1: preString = "float(";  break;
-                case 2: preString = "vec2("; break;
-                case 3: preString = "vec3("; break;
-                case 4: preString = "vec4("; break;
-                default: UNREACHABLE();
-            }
-            break;
-        case EOpConvFloatToInt:
-        case EOpConvBoolToInt:
-            switch (node->getOperand()->getType().getNominalSize())
-            {
-                case 1: preString = "int(";  break;
-                case 2: preString = "ivec2("; break;
-                case 3: preString = "ivec3("; break;
-                case 4: preString = "ivec4("; break;
-                default: UNREACHABLE();
-            }
-            break;
-
-        case EOpRadians: preString = "radians("; break;
-        case EOpDegrees: preString = "degrees("; break;
-        case EOpSin: preString = "sin("; break;
-        case EOpCos: preString = "cos("; break;
-        case EOpTan: preString = "tan("; break;
-        case EOpAsin: preString = "asin("; break;
-        case EOpAcos: preString = "acos("; break;
-        case EOpAtan: preString = "atan("; break;
-
-        case EOpExp: preString = "exp("; break;
-        case EOpLog: preString = "log("; break;
-        case EOpExp2: preString = "exp2("; break;
-        case EOpLog2: preString = "log2("; break;
-        case EOpSqrt: preString = "sqrt("; break;
-        case EOpInverseSqrt: preString = "inversesqrt("; break;
-
-        case EOpAbs: preString = "abs("; break;
-        case EOpSign: preString = "sign("; break;
-        case EOpFloor: preString = "floor("; break;
-        case EOpCeil: preString = "ceil("; break;
-        case EOpFract: preString = "fract("; break;
-
-        case EOpLength: preString = "length("; break;
-        case EOpNormalize: preString = "normalize("; break;
-
-        case EOpDFdx: preString = "dFdx("; break;
-        case EOpDFdy: preString = "dFdy("; break;
-        case EOpFwidth: preString = "fwidth("; break;
-
-        case EOpAny: preString = "any("; break;
-        case EOpAll: preString = "all("; break;
-
-        default: UNREACHABLE(); break;
-    }
-
-    if (visit == PreVisit && node->getUseEmulatedFunction())
-        preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
-    writeTriplet(visit, preString.c_str(), NULL, postString.c_str());
-
-    return true;
-}
-
-bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node)
-{
-    TInfoSinkBase& out = objSink();
-
-    if (node->usesTernaryOperator())
-    {
-        // Notice two brackets at the beginning and end. The outer ones
-        // encapsulate the whole ternary expression. This preserves the
-        // order of precedence when ternary expressions are used in a
-        // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
-        out << "((";
-        node->getCondition()->traverse(this);
-        out << ") ? (";
-        node->getTrueBlock()->traverse(this);
-        out << ") : (";
-        node->getFalseBlock()->traverse(this);
-        out << "))";
-    }
-    else
-    {
-        out << "if (";
-        node->getCondition()->traverse(this);
-        out << ")\n";
-
-        incrementDepth();
-        visitCodeBlock(node->getTrueBlock());
-
-        if (node->getFalseBlock())
-        {
-            out << "else\n";
-            visitCodeBlock(node->getFalseBlock());
-        }
-        decrementDepth();
-    }
-    return false;
-}
-
-bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
-{
-    bool visitChildren = true;
-    TInfoSinkBase& out = objSink();
-    TString preString;
-    bool delayedWrite = false;
-    switch (node->getOp())
-    {
-        case EOpSequence: {
-            // Scope the sequences except when at the global scope.
-            if (depth > 0) out << "{\n";
-
-            incrementDepth();
-            const TIntermSequence& sequence = node->getSequence();
-            for (TIntermSequence::const_iterator iter = sequence.begin();
-                 iter != sequence.end(); ++iter)
-            {
-                TIntermNode* node = *iter;
-                ASSERT(node != NULL);
-                node->traverse(this);
-
-                if (isSingleStatement(node))
-                    out << ";\n";
-            }
-            decrementDepth();
-
-            // Scope the sequences except when at the global scope.
-            if (depth > 0) out << "}\n";
-            visitChildren = false;
-            break;
-        }
-        case EOpPrototype: {
-            // Function declaration.
-            ASSERT(visit == PreVisit);
-            writeVariableType(node->getType());
-            out << " " << hashName(node->getName());
-
-            out << "(";
-            writeFunctionParameters(node->getSequence());
-            out << ")";
-
-            visitChildren = false;
-            break;
-        }
-        case EOpFunction: {
-            // Function definition.
-            ASSERT(visit == PreVisit);
-            writeVariableType(node->getType());
-            out << " " << hashFunctionName(node->getName());
-
-            incrementDepth();
-            // Function definition node contains one or two children nodes
-            // representing function parameters and function body. The latter
-            // is not present in case of empty function bodies.
-            const TIntermSequence& sequence = node->getSequence();
-            ASSERT((sequence.size() == 1) || (sequence.size() == 2));
-            TIntermSequence::const_iterator seqIter = sequence.begin();
-
-            // Traverse function parameters.
-            TIntermAggregate* params = (*seqIter)->getAsAggregate();
-            ASSERT(params != NULL);
-            ASSERT(params->getOp() == EOpParameters);
-            params->traverse(this);
-
-            // Traverse function body.
-            TIntermAggregate* body = ++seqIter != sequence.end() ?
-                (*seqIter)->getAsAggregate() : NULL;
-            visitCodeBlock(body);
-            decrementDepth();
- 
-            // Fully processed; no need to visit children.
-            visitChildren = false;
-            break;
-        }
-        case EOpFunctionCall:
-            // Function call.
-            if (visit == PreVisit)
-            {
-                out << hashFunctionName(node->getName()) << "(";
-            }
-            else if (visit == InVisit)
-            {
-                out << ", ";
-            }
-            else
-            {
-                out << ")";
-            }
-            break;
-        case EOpParameters: {
-            // Function parameters.
-            ASSERT(visit == PreVisit);
-            out << "(";
-            writeFunctionParameters(node->getSequence());
-            out << ")";
-            visitChildren = false;
-            break;
-        }
-        case EOpDeclaration: {
-            // Variable declaration.
-            if (visit == PreVisit)
-            {
-                const TIntermSequence& sequence = node->getSequence();
-                const TIntermTyped* variable = sequence.front()->getAsTyped();
-                writeVariableType(variable->getType());
-                out << " ";
-                mDeclaringVariables = true;
-            }
-            else if (visit == InVisit)
-            {
-                out << ", ";
-                mDeclaringVariables = true;
-            }
-            else
-            {
-                mDeclaringVariables = false;
-            }
-            break;
-        }
-        case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
-        case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
-        case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
-        case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
-        case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
-        case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
-        case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
-        case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
-        case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
-        case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
-        case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
-        case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
-        case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
-        case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
-        case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
-        case EOpConstructStruct:
-            if (visit == PreVisit)
-            {
-                const TType& type = node->getType();
-                ASSERT(type.getBasicType() == EbtStruct);
-                out << hashName(type.getStruct()->name()) << "(";
-            }
-            else if (visit == InVisit)
-            {
-                out << ", ";
-            }
-            else
-            {
-                out << ")";
-            }
-            break;
-
-        case EOpLessThan: preString = "lessThan("; delayedWrite = true; break;
-        case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break;
-        case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break;
-        case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break;
-        case EOpVectorEqual: preString = "equal("; delayedWrite = true; break;
-        case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break;
-        case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
-
-        case EOpMod: preString = "mod("; delayedWrite = true; break;
-        case EOpPow: preString = "pow("; delayedWrite = true; break;
-        case EOpAtan: preString = "atan("; delayedWrite = true; break;
-        case EOpMin: preString = "min("; delayedWrite = true; break;
-        case EOpMax: preString = "max("; delayedWrite = true; break;
-        case EOpClamp: preString = "clamp("; delayedWrite = true; break;
-        case EOpMix: preString = "mix("; delayedWrite = true; break;
-        case EOpStep: preString = "step("; delayedWrite = true; break;
-        case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break;
-
-        case EOpDistance: preString = "distance("; delayedWrite = true; break;
-        case EOpDot: preString = "dot("; delayedWrite = true; break;
-        case EOpCross: preString = "cross("; delayedWrite = true; break;
-        case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break;
-        case EOpReflect: preString = "reflect("; delayedWrite = true; break;
-        case EOpRefract: preString = "refract("; delayedWrite = true; break;
-        case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break;
-
-        default: UNREACHABLE(); break;
-    }
-    if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction())
-        preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
-    if (delayedWrite)
-        writeTriplet(visit, preString.c_str(), ", ", ")");
-    return visitChildren;
-}
-
-bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node)
-{
-    TInfoSinkBase& out = objSink();
-
-    incrementDepth();
-    // Loop header.
-    TLoopType loopType = node->getType();
-    if (loopType == ELoopFor)  // for loop
-    {
-        if (!node->getUnrollFlag()) {
-            out << "for (";
-            if (node->getInit())
-                node->getInit()->traverse(this);
-            out << "; ";
-
-            if (node->getCondition())
-                node->getCondition()->traverse(this);
-            out << "; ";
-
-            if (node->getExpression())
-                node->getExpression()->traverse(this);
-            out << ")\n";
-        }
-    }
-    else if (loopType == ELoopWhile)  // while loop
-    {
-        out << "while (";
-        ASSERT(node->getCondition() != NULL);
-        node->getCondition()->traverse(this);
-        out << ")\n";
-    }
-    else  // do-while loop
-    {
-        ASSERT(loopType == ELoopDoWhile);
-        out << "do\n";
-    }
-
-    // Loop body.
-    if (node->getUnrollFlag())
-    {
-        TLoopIndexInfo indexInfo;
-        mLoopUnroll.FillLoopIndexInfo(node, indexInfo);
-        mLoopUnroll.Push(indexInfo);
-        while (mLoopUnroll.SatisfiesLoopCondition())
-        {
-            visitCodeBlock(node->getBody());
-            mLoopUnroll.Step();
-        }
-        mLoopUnroll.Pop();
-    }
-    else
-    {
-        visitCodeBlock(node->getBody());
-    }
-
-    // Loop footer.
-    if (loopType == ELoopDoWhile)  // do-while loop
-    {
-        out << "while (";
-        ASSERT(node->getCondition() != NULL);
-        node->getCondition()->traverse(this);
-        out << ");\n";
-    }
-    decrementDepth();
-
-    // No need to visit children. They have been already processed in
-    // this function.
-    return false;
-}
-
-bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node)
-{
-    switch (node->getFlowOp())
-    {
-        case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
-        case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
-        case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
-        case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
-        default: UNREACHABLE(); break;
-    }
-
-    return true;
-}
-
-void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) {
-    TInfoSinkBase &out = objSink();
-    if (node != NULL)
-    {
-        node->traverse(this);
-        // Single statements not part of a sequence need to be terminated
-        // with semi-colon.
-        if (isSingleStatement(node))
-            out << ";\n";
-    }
-    else
-    {
-        out << "{\n}\n";  // Empty code block.
-    }
-}
-
-TString TOutputGLSLBase::getTypeName(const TType& type)
-{
-    TInfoSinkBase out;
-    if (type.isMatrix())
-    {
-        out << "mat";
-        out << type.getNominalSize();
-    }
-    else if (type.isVector())
-    {
-        switch (type.getBasicType())
-        {
-            case EbtFloat: out << "vec"; break;
-            case EbtInt: out << "ivec"; break;
-            case EbtBool: out << "bvec"; break;
-            default: UNREACHABLE(); break;
-        }
-        out << type.getNominalSize();
-    }
-    else
-    {
-        if (type.getBasicType() == EbtStruct)
-            out << hashName(type.getStruct()->name());
-        else
-            out << type.getBasicString();
-    }
-    return TString(out.c_str());
-}
-
-TString TOutputGLSLBase::hashName(const TString& name)
-{
-    if (mHashFunction == NULL || name.empty())
-        return name;
-    NameMap::const_iterator it = mNameMap.find(name.c_str());
-    if (it != mNameMap.end())
-        return it->second.c_str();
-    TString hashedName = TIntermTraverser::hash(name, mHashFunction);
-    mNameMap[name.c_str()] = hashedName.c_str();
-    return hashedName;
-}
-
-TString TOutputGLSLBase::hashVariableName(const TString& name)
-{
-    if (mSymbolTable.findBuiltIn(name) != NULL)
-        return name;
-    return hashName(name);
-}
-
-TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
-{
-    TString name = TFunction::unmangleName(mangled_name);
-    if (mSymbolTable.findBuiltIn(mangled_name) != NULL || name == "main")
-        return name;
-    return hashName(name);
-}
-
-bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
-{
-    return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end();
-}
-
-void TOutputGLSLBase::declareStruct(const TStructure* structure)
-{
-    TInfoSinkBase& out = objSink();
-
-    out << "struct " << hashName(structure->name()) << "{\n";
-    const TFieldList& fields = structure->fields();
-    for (size_t i = 0; i < fields.size(); ++i)
-    {
-        const TField* field = fields[i];
-        if (writeVariablePrecision(field->type()->getPrecision()))
-            out << " ";
-        out << getTypeName(*field->type()) << " " << hashName(field->name());
-        if (field->type()->isArray())
-            out << arrayBrackets(*field->type());
-        out << ";\n";
-    }
-    out << "}";
-
-    mDeclaredStructs.insert(structure->name());
-}
diff --git a/src/third_party/angle/src/compiler/OutputGLSLBase.h b/src/third_party/angle/src/compiler/OutputGLSLBase.h
deleted file mode 100644
index df4ad68..0000000
--- a/src/third_party/angle/src/compiler/OutputGLSLBase.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
-#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
-
-#include <set>
-
-#include "compiler/ForLoopUnroll.h"
-#include "compiler/intermediate.h"
-#include "compiler/ParseHelper.h"
-
-class TOutputGLSLBase : public TIntermTraverser
-{
-public:
-    TOutputGLSLBase(TInfoSinkBase& objSink,
-                    ShArrayIndexClampingStrategy clampingStrategy,
-                    ShHashFunction64 hashFunction,
-                    NameMap& nameMap,
-                    TSymbolTable& symbolTable);
-
-protected:
-    TInfoSinkBase& objSink() { return mObjSink; }
-    void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr);
-    void writeVariableType(const TType& type);
-    virtual bool writeVariablePrecision(TPrecision precision) = 0;
-    void writeFunctionParameters(const TIntermSequence& args);
-    const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion);
-    TString getTypeName(const TType& type);
-
-    virtual void visitSymbol(TIntermSymbol* node);
-    virtual void visitConstantUnion(TIntermConstantUnion* node);
-    virtual bool visitBinary(Visit visit, TIntermBinary* node);
-    virtual bool visitUnary(Visit visit, TIntermUnary* node);
-    virtual bool visitSelection(Visit visit, TIntermSelection* node);
-    virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
-    virtual bool visitLoop(Visit visit, TIntermLoop* node);
-    virtual bool visitBranch(Visit visit, TIntermBranch* node);
-
-    void visitCodeBlock(TIntermNode* node);
-
-
-    // Return the original name if hash function pointer is NULL;
-    // otherwise return the hashed name.
-    TString hashName(const TString& name);
-    // Same as hashName(), but without hashing built-in variables.
-    TString hashVariableName(const TString& name);
-    // Same as hashName(), but without hashing built-in functions.
-    TString hashFunctionName(const TString& mangled_name);
-
-private:
-    bool structDeclared(const TStructure* structure) const;
-    void declareStruct(const TStructure* structure);
-
-    TInfoSinkBase& mObjSink;
-    bool mDeclaringVariables;
-
-    // Structs are declared as the tree is traversed. This set contains all
-    // the structs already declared. It is maintained so that a struct is
-    // declared only once.
-    typedef std::set<TString> DeclaredStructs;
-    DeclaredStructs mDeclaredStructs;
-
-    ForLoopUnroll mLoopUnroll;
-
-    ShArrayIndexClampingStrategy mClampingStrategy;
-
-    // name hashing.
-    ShHashFunction64 mHashFunction;
-
-    NameMap& mNameMap;
-
-    TSymbolTable& mSymbolTable;
-};
-
-#endif  // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
diff --git a/src/third_party/angle/src/compiler/OutputHLSL.cpp b/src/third_party/angle/src/compiler/OutputHLSL.cpp
deleted file mode 100644
index e0afe54..0000000
--- a/src/third_party/angle/src/compiler/OutputHLSL.cpp
+++ /dev/null
@@ -1,3252 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/OutputHLSL.h"
-
-#include "common/angleutils.h"
-#include "compiler/debug.h"
-#include "compiler/DetectDiscontinuity.h"
-#include "compiler/InfoSink.h"
-#include "compiler/SearchSymbol.h"
-#include "compiler/UnfoldShortCircuit.h"
-
-#include <algorithm>
-#include <cfloat>
-#include <stdio.h>
-
-namespace sh
-{
-// Integer to TString conversion
-TString str(int i)
-{
-    char buffer[20];
-    snprintf(buffer, sizeof(buffer), "%d", i);
-    return buffer;
-}
-
-OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType)
-    : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType)
-{
-    mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
-    mInsideFunction = false;
-
-    mUsesTexture2D = false;
-    mUsesTexture2D_bias = false;
-    mUsesTexture2DProj = false;
-    mUsesTexture2DProj_bias = false;
-    mUsesTexture2DProjLod = false;
-    mUsesTexture2DLod = false;
-    mUsesTextureCube = false;
-    mUsesTextureCube_bias = false;
-    mUsesTextureCubeLod = false;
-    mUsesTexture2DLod0 = false;
-    mUsesTexture2DLod0_bias = false;
-    mUsesTexture2DProjLod0 = false;
-    mUsesTexture2DProjLod0_bias = false;
-    mUsesTextureCubeLod0 = false;
-    mUsesTextureCubeLod0_bias = false;
-    mUsesFragColor = false;
-    mUsesFragData = false;
-    mUsesDepthRange = false;
-    mUsesFragCoord = false;
-    mUsesPointCoord = false;
-    mUsesFrontFacing = false;
-    mUsesPointSize = false;
-    mUsesFragDepth = false;
-    mUsesXor = false;
-    mUsesMod1 = false;
-    mUsesMod2v = false;
-    mUsesMod2f = false;
-    mUsesMod3v = false;
-    mUsesMod3f = false;
-    mUsesMod4v = false;
-    mUsesMod4f = false;
-    mUsesFaceforward1 = false;
-    mUsesFaceforward2 = false;
-    mUsesFaceforward3 = false;
-    mUsesFaceforward4 = false;
-    mUsesEqualMat2 = false;
-    mUsesEqualMat3 = false;
-    mUsesEqualMat4 = false;
-    mUsesEqualVec2 = false;
-    mUsesEqualVec3 = false;
-    mUsesEqualVec4 = false;
-    mUsesEqualIVec2 = false;
-    mUsesEqualIVec3 = false;
-    mUsesEqualIVec4 = false;
-    mUsesEqualBVec2 = false;
-    mUsesEqualBVec3 = false;
-    mUsesEqualBVec4 = false;
-    mUsesAtan2_1 = false;
-    mUsesAtan2_2 = false;
-    mUsesAtan2_3 = false;
-    mUsesAtan2_4 = false;
-
-    mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
-
-    mScopeDepth = 0;
-
-    mUniqueIndex = 0;
-
-    mContainsLoopDiscontinuity = false;
-    mOutputLod0Function = false;
-    mInsideDiscontinuousLoop = false;
-
-    mExcessiveLoopIndex = NULL;
-
-    if (mOutputType == SH_HLSL9_OUTPUT)
-    {
-        if (mContext.shaderType == SH_FRAGMENT_SHADER)
-        {
-            mUniformRegister = 3;   // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
-        }
-        else
-        {
-            mUniformRegister = 2;   // Reserve registers for dx_DepthRange and dx_ViewAdjust
-        }
-    }
-    else
-    {
-        mUniformRegister = 0;
-    }
-
-    mSamplerRegister = 0;
-}
-
-OutputHLSL::~OutputHLSL()
-{
-    delete mUnfoldShortCircuit;
-}
-
-void OutputHLSL::output()
-{
-    mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
-
-    mContext.treeRoot->traverse(this);   // Output the body first to determine what has to go in the header
-    header();
-
-    mContext.infoSink().obj << mHeader.c_str();
-    mContext.infoSink().obj << mBody.c_str();
-}
-
-TInfoSinkBase &OutputHLSL::getBodyStream()
-{
-    return mBody;
-}
-
-const ActiveUniforms &OutputHLSL::getUniforms()
-{
-    return mActiveUniforms;
-}
-
-int OutputHLSL::vectorSize(const TType &type) const
-{
-    int elementSize = type.isMatrix() ? type.getNominalSize() : 1;
-    int arraySize = type.isArray() ? type.getArraySize() : 1;
-
-    return elementSize * arraySize;
-}
-
-void OutputHLSL::header()
-{
-    ShShaderType shaderType = mContext.shaderType;
-    TInfoSinkBase &out = mHeader;
-
-    for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
-    {
-        out << *structDeclaration;
-    }
-
-    for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
-    {
-        out << *constructor;
-    }
-
-    TString uniforms;
-    TString varyings;
-    TString attributes;
-
-    for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++)
-    {
-        const TType &type = uniform->second->getType();
-        const TString &name = uniform->second->getSymbol();
-
-        if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))   // Also declare the texture
-        {
-            int index = samplerRegister(mReferencedUniforms[name]);
-
-            uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) + 
-                        " : register(s" + str(index) + ");\n";
-
-            uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) + 
-                        " : register(t" + str(index) + ");\n";
-        }
-        else
-        {
-            uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + 
-                        " : register(" + registerString(mReferencedUniforms[name]) + ");\n";
-        }
-    }
-
-    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 " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
-    }
-
-    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";
-    }
-
-    if (shaderType == SH_FRAGMENT_SHADER)
-    {
-        TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
-        const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
-
-        const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
-
-        out << "// Varyings\n";
-        out <<  varyings;
-        out << "\n"
-               "static float4 gl_Color[" << numColorValues << "] =\n"
-               "{\n";
-        for (unsigned int i = 0; i < numColorValues; i++)
-        {
-            out << "    float4(0, 0, 0, 0)";
-            if (i + 1 != numColorValues)
-            {
-                out << ",";
-            }
-            out << "\n";
-        }
-        out << "};\n";
-
-        if (mUsesFragDepth)
-        {
-            out << "static float gl_Depth = 0.0;\n";
-        }
-
-        if (mUsesFragCoord)
-        {
-            out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
-        }
-
-        if (mUsesPointCoord)
-        {
-            out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n";
-        }
-
-        if (mUsesFrontFacing)
-        {
-            out << "static bool gl_FrontFacing = false;\n";
-        }
-
-        out << "\n";
-
-        if (mUsesDepthRange)
-        {
-            out << "struct gl_DepthRangeParameters\n"
-                   "{\n"
-                   "    float near;\n"
-                   "    float far;\n"
-                   "    float diff;\n"
-                   "};\n"
-                   "\n";
-        }
-
-        if (mOutputType == SH_HLSL11_OUTPUT)
-        {
-            out << "cbuffer DriverConstants : register(b1)\n"
-                   "{\n";
-
-            if (mUsesDepthRange)
-            {
-                out << "    float3 dx_DepthRange : packoffset(c0);\n";
-            }
-
-            if (mUsesFragCoord)
-            {
-                out << "    float4 dx_ViewCoords : packoffset(c1);\n";
-            }
-
-            if (mUsesFragCoord || mUsesFrontFacing)
-            {
-                out << "    float3 dx_DepthFront : packoffset(c2);\n";
-            }
-
-            out << "};\n";
-        }
-        else
-        {
-            if (mUsesDepthRange)
-            {
-                out << "uniform float3 dx_DepthRange : register(c0);";
-            }
-
-            if (mUsesFragCoord)
-            {
-                out << "uniform float4 dx_ViewCoords : register(c1);\n";
-            }
-
-            if (mUsesFragCoord || mUsesFrontFacing)
-            {
-                out << "uniform float3 dx_DepthFront : register(c2);\n";
-            }
-        }
-
-        out << "\n";
-
-        if (mUsesDepthRange)
-        {
-            out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
-                   "\n";
-        }
-        
-        out <<  uniforms;
-        out << "\n";
-
-        if (mUsesTexture2D)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
-                       "{\n"
-                       "    return tex2D(s, t);\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n"
-                       "{\n"
-                       "    return t.Sample(s, uv);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTexture2D_bias)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n"
-                       "{\n"
-                       "    return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv, float bias)\n"
-                       "{\n"
-                       "    return t.SampleBias(s, uv, bias);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTexture2DProj)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
-                       "{\n"
-                       "    return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
-                       "{\n"
-                       "    return tex2Dproj(s, t);\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n"
-                       "{\n"
-                       "    return t.Sample(s, float2(uvw.x / uvw.z, uvw.y / uvw.z));\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
-                       "{\n"
-                       "    return t.Sample(s, float2(uvw.x / uvw.w, uvw.y / uvw.w));\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTexture2DProj_bias)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n"
-                       "{\n"
-                       "    return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n"
-                       "{\n"
-                       "    return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float bias)\n"
-                       "{\n"
-                       "    return t.SampleBias(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), bias);\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw, float bias)\n"
-                       "{\n"
-                       "    return t.SampleBias(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), bias);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTextureCube)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
-                       "{\n"
-                       "    return texCUBE(s, t);\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n"
-                       "{\n"
-                       "    return t.Sample(s, uvw);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTextureCube_bias)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n"
-                       "{\n"
-                       "    return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw, float bias)\n"
-                       "{\n"
-                       "    return t.SampleBias(s, uvw, bias);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        // These *Lod0 intrinsics are not available in GL fragment shaders.
-        // They are used to sample using discontinuous texture coordinates.
-        if (mUsesTexture2DLod0)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, uv, 0);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTexture2DLod0_bias)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv, float bias)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, uv, 0);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTexture2DProjLod0)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float3 uvw)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float4 uvw)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTexture2DProjLod0_bias)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float3 uvw, float bias)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float4 uvw, float bias)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTextureCubeLod0)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n"
-                       "{\n"
-                       "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, uvw, 0);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTextureCubeLod0_bias)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n"
-                       "{\n"
-                       "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw, float bias)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, uvw, 0);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (usingMRTExtension && mNumRenderTargets > 1)
-        {
-            out << "#define GL_USES_MRT\n";
-        }
-
-        if (mUsesFragColor)
-        {
-            out << "#define GL_USES_FRAG_COLOR\n";
-        }
-
-        if (mUsesFragData)
-        {
-            out << "#define GL_USES_FRAG_DATA\n";
-        }
-    }
-    else   // Vertex shader
-    {
-        out << "// Attributes\n";
-        out <<  attributes;
-        out << "\n"
-               "static float4 gl_Position = float4(0, 0, 0, 0);\n";
-        
-        if (mUsesPointSize)
-        {
-            out << "static float gl_PointSize = float(1);\n";
-        }
-
-        out << "\n"
-               "// Varyings\n";
-        out <<  varyings;
-        out << "\n";
-
-        if (mUsesDepthRange)
-        {
-            out << "struct gl_DepthRangeParameters\n"
-                   "{\n"
-                   "    float near;\n"
-                   "    float far;\n"
-                   "    float diff;\n"
-                   "};\n"
-                   "\n";
-        }
-
-        if (mOutputType == SH_HLSL11_OUTPUT)
-        {
-            if (mUsesDepthRange)
-            {
-                out << "cbuffer DriverConstants : register(b1)\n"
-                       "{\n"
-                       "    float3 dx_DepthRange : packoffset(c0);\n"
-                       "};\n"
-                       "\n";
-            }
-        }
-        else
-        {
-            if (mUsesDepthRange)
-            {
-                out << "uniform float3 dx_DepthRange : register(c0);\n";
-            }
-
-            out << "uniform float4 dx_ViewAdjust : register(c1);\n"
-                   "\n";
-        }
-
-        if (mUsesDepthRange)
-        {
-            out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
-                   "\n";
-        }
-
-        out << uniforms;
-        out << "\n";
-        
-        if (mUsesTexture2D)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, uv, 0);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTexture2DLod)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2DLod(Texture2D t, SamplerState s, float2 uv, float lod)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, uv, lod);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTexture2DProj)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTexture2DProjLod)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n"
-                       "{\n"
-                       "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float lod)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n"
-                       "}\n"
-                       "\n"
-                       "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTextureCube)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
-                       "{\n"
-                       "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, uvw, 0);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-
-        if (mUsesTextureCubeLod)
-        {
-            if (mOutputType == SH_HLSL9_OUTPUT)
-            {
-                out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n"
-                       "{\n"
-                       "    return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n"
-                       "}\n"
-                       "\n";
-            }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
-            {
-                out << "float4 gl_textureCubeLod(TextureCube t, SamplerState s, float3 uvw, float lod)\n"
-                       "{\n"
-                       "    return t.SampleLevel(s, uvw, lod);\n"
-                       "}\n"
-                       "\n";
-            }
-            else UNREACHABLE();
-        }
-    }
-
-    if (mUsesFragCoord)
-    {
-        out << "#define GL_USES_FRAG_COORD\n";
-    }
-
-    if (mUsesPointCoord)
-    {
-        out << "#define GL_USES_POINT_COORD\n";
-    }
-
-    if (mUsesFrontFacing)
-    {
-        out << "#define GL_USES_FRONT_FACING\n";
-    }
-
-    if (mUsesPointSize)
-    {
-        out << "#define GL_USES_POINT_SIZE\n";
-    }
-
-    if (mUsesFragDepth)
-    {
-        out << "#define GL_USES_FRAG_DEPTH\n";
-    }
-
-    if (mUsesDepthRange)
-    {
-        out << "#define GL_USES_DEPTH_RANGE\n";
-    }
-
-    if (mUsesXor)
-    {
-        out << "bool xor(bool p, bool q)\n"
-               "{\n"
-               "    return (p || q) && !(p && q);\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesMod1)
-    {
-        out << "float mod(float x, float y)\n"
-               "{\n"
-               "    return x - y * floor(x / y);\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesMod2v)
-    {
-        out << "float2 mod(float2 x, float2 y)\n"
-               "{\n"
-               "    return x - y * floor(x / y);\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesMod2f)
-    {
-        out << "float2 mod(float2 x, float y)\n"
-               "{\n"
-               "    return x - y * floor(x / y);\n"
-               "}\n"
-               "\n";
-    }
-    
-    if (mUsesMod3v)
-    {
-        out << "float3 mod(float3 x, float3 y)\n"
-               "{\n"
-               "    return x - y * floor(x / y);\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesMod3f)
-    {
-        out << "float3 mod(float3 x, float y)\n"
-               "{\n"
-               "    return x - y * floor(x / y);\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesMod4v)
-    {
-        out << "float4 mod(float4 x, float4 y)\n"
-               "{\n"
-               "    return x - y * floor(x / y);\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesMod4f)
-    {
-        out << "float4 mod(float4 x, float y)\n"
-               "{\n"
-               "    return x - y * floor(x / y);\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesFaceforward1)
-    {
-        out << "float faceforward(float N, float I, float Nref)\n"
-               "{\n"
-               "    if(dot(Nref, I) >= 0)\n"
-               "    {\n"
-               "        return -N;\n"
-               "    }\n"
-               "    else\n"
-               "    {\n"
-               "        return N;\n"
-               "    }\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesFaceforward2)
-    {
-        out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
-               "{\n"
-               "    if(dot(Nref, I) >= 0)\n"
-               "    {\n"
-               "        return -N;\n"
-               "    }\n"
-               "    else\n"
-               "    {\n"
-               "        return N;\n"
-               "    }\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesFaceforward3)
-    {
-        out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
-               "{\n"
-               "    if(dot(Nref, I) >= 0)\n"
-               "    {\n"
-               "        return -N;\n"
-               "    }\n"
-               "    else\n"
-               "    {\n"
-               "        return N;\n"
-               "    }\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesFaceforward4)
-    {
-        out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
-               "{\n"
-               "    if(dot(Nref, I) >= 0)\n"
-               "    {\n"
-               "        return -N;\n"
-               "    }\n"
-               "    else\n"
-               "    {\n"
-               "        return N;\n"
-               "    }\n"
-               "}\n"
-               "\n";
-    }
-
-    if (mUsesEqualMat2)
-    {
-        out << "bool equal(float2x2 m, float2x2 n)\n"
-               "{\n"
-               "    return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n"
-               "           m[1][0] == n[1][0] && m[1][1] == n[1][1];\n"
-               "}\n";
-    }
-
-    if (mUsesEqualMat3)
-    {
-        out << "bool equal(float3x3 m, float3x3 n)\n"
-               "{\n"
-               "    return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n"
-               "           m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n"
-               "           m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n"
-               "}\n";
-    }
-
-    if (mUsesEqualMat4)
-    {
-        out << "bool equal(float4x4 m, float4x4 n)\n"
-               "{\n"
-               "    return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n"
-               "           m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n"
-               "           m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n"
-               "           m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n"
-               "}\n";
-    }
-
-    if (mUsesEqualVec2)
-    {
-        out << "bool equal(float2 v, float2 u)\n"
-               "{\n"
-               "    return v.x == u.x && v.y == u.y;\n"
-               "}\n";
-    }
-
-    if (mUsesEqualVec3)
-    {
-        out << "bool equal(float3 v, float3 u)\n"
-               "{\n"
-               "    return v.x == u.x && v.y == u.y && v.z == u.z;\n"
-               "}\n";
-    }
-
-    if (mUsesEqualVec4)
-    {
-        out << "bool equal(float4 v, float4 u)\n"
-               "{\n"
-               "    return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
-               "}\n";
-    }
-
-    if (mUsesEqualIVec2)
-    {
-        out << "bool equal(int2 v, int2 u)\n"
-               "{\n"
-               "    return v.x == u.x && v.y == u.y;\n"
-               "}\n";
-    }
-
-    if (mUsesEqualIVec3)
-    {
-        out << "bool equal(int3 v, int3 u)\n"
-               "{\n"
-               "    return v.x == u.x && v.y == u.y && v.z == u.z;\n"
-               "}\n";
-    }
-
-    if (mUsesEqualIVec4)
-    {
-        out << "bool equal(int4 v, int4 u)\n"
-               "{\n"
-               "    return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
-               "}\n";
-    }
-
-    if (mUsesEqualBVec2)
-    {
-        out << "bool equal(bool2 v, bool2 u)\n"
-               "{\n"
-               "    return v.x == u.x && v.y == u.y;\n"
-               "}\n";
-    }
-
-    if (mUsesEqualBVec3)
-    {
-        out << "bool equal(bool3 v, bool3 u)\n"
-               "{\n"
-               "    return v.x == u.x && v.y == u.y && v.z == u.z;\n"
-               "}\n";
-    }
-
-    if (mUsesEqualBVec4)
-    {
-        out << "bool equal(bool4 v, bool4 u)\n"
-               "{\n"
-               "    return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
-               "}\n";
-    }
-
-    if (mUsesAtan2_1)
-    {
-        out << "float atanyx(float y, float x)\n"
-               "{\n"
-               "    if(x == 0 && y == 0) x = 1;\n"   // Avoid producing a NaN
-               "    return atan2(y, x);\n"
-               "}\n";
-    }
-
-    if (mUsesAtan2_2)
-    {
-        out << "float2 atanyx(float2 y, float2 x)\n"
-               "{\n"
-               "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
-               "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
-               "    return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
-               "}\n";
-    }
-
-    if (mUsesAtan2_3)
-    {
-        out << "float3 atanyx(float3 y, float3 x)\n"
-               "{\n"
-               "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
-               "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
-               "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
-               "    return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
-               "}\n";
-    }
-
-    if (mUsesAtan2_4)
-    {
-        out << "float4 atanyx(float4 y, float4 x)\n"
-               "{\n"
-               "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
-               "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
-               "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
-               "    if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
-               "    return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
-               "}\n";
-    }
-}
-
-void OutputHLSL::visitSymbol(TIntermSymbol *node)
-{
-    TInfoSinkBase &out = mBody;
-
-    TString name = node->getSymbol();
-
-    if (name == "gl_FragColor")
-    {
-        out << "gl_Color[0]";
-        mUsesFragColor = true;
-    }
-    else if (name == "gl_FragData")
-    {
-        out << "gl_Color";
-        mUsesFragData = true;
-    }
-    else if (name == "gl_DepthRange")
-    {
-        mUsesDepthRange = true;
-        out << name;
-    }
-    else if (name == "gl_FragCoord")
-    {
-        mUsesFragCoord = true;
-        out << name;
-    }
-    else if (name == "gl_PointCoord")
-    {
-        mUsesPointCoord = true;
-        out << name;
-    }
-    else if (name == "gl_FrontFacing")
-    {
-        mUsesFrontFacing = true;
-        out << name;
-    }
-    else if (name == "gl_PointSize")
-    {
-        mUsesPointSize = true;
-        out << name;
-    }
-    else if (name == "gl_FragDepthEXT")
-    {
-        mUsesFragDepth = true;
-        out << "gl_Depth";
-    }
-    else
-    {
-        TQualifier qualifier = node->getQualifier();
-
-        if (qualifier == EvqUniform)
-        {
-            mReferencedUniforms[name] = node;
-            out << decorateUniform(name, node->getType());
-        }
-        else if (qualifier == EvqAttribute)
-        {
-            mReferencedAttributes[name] = node;
-            out << decorate(name);
-        }
-        else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
-        {
-            mReferencedVaryings[name] = node;
-            out << decorate(name);
-        }
-        else
-        {
-            out << decorate(name);
-        }
-    }
-}
-
-bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
-{
-    TInfoSinkBase &out = mBody;
-
-    switch (node->getOp())
-    {
-      case EOpAssign:                  outputTriplet(visit, "(", " = ", ")");           break;
-      case EOpInitialize:
-        if (visit == PreVisit)
-        {
-            // GLSL allows to write things like "float x = x;" where a new variable x is defined
-            // and the value of an existing variable x is assigned. HLSL uses C semantics (the
-            // new variable is created before the assignment is evaluated), so we need to convert
-            // this to "float t = x, x = t;".
-
-            TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
-            TIntermTyped *expression = node->getRight();
-
-            sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
-            expression->traverse(&searchSymbol);
-            bool sameSymbol = searchSymbol.foundMatch();
-
-            if (sameSymbol)
-            {
-                // Type already printed
-                out << "t" + str(mUniqueIndex) + " = ";
-                expression->traverse(this);
-                out << ", ";
-                symbolNode->traverse(this);
-                out << " = t" + str(mUniqueIndex);
-
-                mUniqueIndex++;
-                return false;
-            }
-        }
-        else if (visit == InVisit)
-        {
-            out << " = ";
-        }
-        break;
-      case EOpAddAssign:               outputTriplet(visit, "(", " += ", ")");          break;
-      case EOpSubAssign:               outputTriplet(visit, "(", " -= ", ")");          break;
-      case EOpMulAssign:               outputTriplet(visit, "(", " *= ", ")");          break;
-      case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")");          break;
-      case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")");          break;
-      case EOpVectorTimesMatrixAssign:
-        if (visit == PreVisit)
-        {
-            out << "(";
-        }
-        else if (visit == InVisit)
-        {
-            out << " = mul(";
-            node->getLeft()->traverse(this);
-            out << ", transpose(";   
-        }
-        else
-        {
-            out << ")))";
-        }
-        break;
-      case EOpMatrixTimesMatrixAssign:
-        if (visit == PreVisit)
-        {
-            out << "(";
-        }
-        else if (visit == InVisit)
-        {
-            out << " = mul(";
-            node->getLeft()->traverse(this);
-            out << ", ";   
-        }
-        else
-        {
-            out << "))";
-        }
-        break;
-      case EOpDivAssign:               outputTriplet(visit, "(", " /= ", ")");          break;
-      case EOpIndexDirect:             outputTriplet(visit, "", "[", "]");              break;
-      case EOpIndexIndirect:           outputTriplet(visit, "", "[", "]");              break;
-      case EOpIndexDirectStruct:
-        if (visit == InVisit)
-        {
-            const TStructure* structure = node->getLeft()->getType().getStruct();
-            const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
-            const TField* field = structure->fields()[index->getIConst(0)];
-            out << "." + decorateField(field->name(), node->getLeft()->getType());
-
-            return false;
-        }
-        break;
-      case EOpVectorSwizzle:
-        if (visit == InVisit)
-        {
-            out << ".";
-
-            TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
-
-            if (swizzle)
-            {
-                TIntermSequence &sequence = swizzle->getSequence();
-
-                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
-                {
-                    TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
-
-                    if (element)
-                    {
-                        int i = element->getIConst(0);
-
-                        switch (i)
-                        {
-                        case 0: out << "x"; break;
-                        case 1: out << "y"; break;
-                        case 2: out << "z"; break;
-                        case 3: out << "w"; break;
-                        default: UNREACHABLE();
-                        }
-                    }
-                    else UNREACHABLE();
-                }
-            }
-            else UNREACHABLE();
-
-            return false;   // Fully processed
-        }
-        break;
-      case EOpAdd:               outputTriplet(visit, "(", " + ", ")"); break;
-      case EOpSub:               outputTriplet(visit, "(", " - ", ")"); break;
-      case EOpMul:               outputTriplet(visit, "(", " * ", ")"); break;
-      case EOpDiv:               outputTriplet(visit, "(", " / ", ")"); break;
-      case EOpEqual:
-      case EOpNotEqual:
-        if (node->getLeft()->isScalar())
-        {
-            if (node->getOp() == EOpEqual)
-            {
-                outputTriplet(visit, "(", " == ", ")");
-            }
-            else
-            {
-                outputTriplet(visit, "(", " != ", ")");
-            }
-        }
-        else if (node->getLeft()->getBasicType() == EbtStruct)
-        {
-            if (node->getOp() == EOpEqual)
-            {
-                out << "(";
-            }
-            else
-            {
-                out << "!(";
-            }
-
-            const TFieldList &fields = node->getLeft()->getType().getStruct()->fields();
-
-            for (size_t i = 0; i < fields.size(); i++)
-            {
-                const TField *field = fields[i];
-
-                node->getLeft()->traverse(this);
-                out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == ";
-                node->getRight()->traverse(this);
-                out << "." + decorateField(field->name(), node->getLeft()->getType());
-
-                if (i < fields.size() - 1)
-                {
-                    out << " && ";
-                }
-            }
-
-            out << ")";
-
-            return false;
-        }
-        else
-        {
-            if (node->getLeft()->isMatrix())
-            {
-                switch (node->getLeft()->getNominalSize())
-                {
-                  case 2: mUsesEqualMat2 = true; break;
-                  case 3: mUsesEqualMat3 = true; break;
-                  case 4: mUsesEqualMat4 = true; break;
-                  default: UNREACHABLE();
-                }
-            }
-            else if (node->getLeft()->isVector())
-            {
-                switch (node->getLeft()->getBasicType())
-                {
-                  case EbtFloat:
-                    switch (node->getLeft()->getNominalSize())
-                    {
-                      case 2: mUsesEqualVec2 = true; break;
-                      case 3: mUsesEqualVec3 = true; break;
-                      case 4: mUsesEqualVec4 = true; break;
-                      default: UNREACHABLE();
-                    }
-                    break;
-                  case EbtInt:
-                    switch (node->getLeft()->getNominalSize())
-                    {
-                      case 2: mUsesEqualIVec2 = true; break;
-                      case 3: mUsesEqualIVec3 = true; break;
-                      case 4: mUsesEqualIVec4 = true; break;
-                      default: UNREACHABLE();
-                    }
-                    break;
-                  case EbtBool:
-                    switch (node->getLeft()->getNominalSize())
-                    {
-                      case 2: mUsesEqualBVec2 = true; break;
-                      case 3: mUsesEqualBVec3 = true; break;
-                      case 4: mUsesEqualBVec4 = true; break;
-                      default: UNREACHABLE();
-                    }
-                    break;
-                  default: UNREACHABLE();
-                }
-            }
-            else UNREACHABLE();
-
-            if (node->getOp() == EOpEqual)
-            {
-                outputTriplet(visit, "equal(", ", ", ")");
-            }
-            else
-            {
-                outputTriplet(visit, "!equal(", ", ", ")");
-            }
-        }
-        break;
-      case EOpLessThan:          outputTriplet(visit, "(", " < ", ")");   break;
-      case EOpGreaterThan:       outputTriplet(visit, "(", " > ", ")");   break;
-      case EOpLessThanEqual:     outputTriplet(visit, "(", " <= ", ")");  break;
-      case EOpGreaterThanEqual:  outputTriplet(visit, "(", " >= ", ")");  break;
-      case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
-      case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
-      case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
-      case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
-      case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
-      case EOpLogicalOr:
-        out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
-        return false;
-      case EOpLogicalXor:
-        mUsesXor = true;
-        outputTriplet(visit, "xor(", ", ", ")");
-        break;
-      case EOpLogicalAnd:
-        out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
-        return false;
-      default: UNREACHABLE();
-    }
-
-    return true;
-}
-
-bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
-{
-    switch (node->getOp())
-    {
-      case EOpNegative:         outputTriplet(visit, "(-", "", ")");  break;
-      case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")");  break;
-      case EOpLogicalNot:       outputTriplet(visit, "(!", "", ")");  break;
-      case EOpPostIncrement:    outputTriplet(visit, "(", "", "++)"); break;
-      case EOpPostDecrement:    outputTriplet(visit, "(", "", "--)"); break;
-      case EOpPreIncrement:     outputTriplet(visit, "(++", "", ")"); break;
-      case EOpPreDecrement:     outputTriplet(visit, "(--", "", ")"); break;
-      case EOpConvIntToBool:
-      case EOpConvFloatToBool:
-        switch (node->getOperand()->getType().getNominalSize())
-        {
-          case 1:    outputTriplet(visit, "bool(", "", ")");  break;
-          case 2:    outputTriplet(visit, "bool2(", "", ")"); break;
-          case 3:    outputTriplet(visit, "bool3(", "", ")"); break;
-          case 4:    outputTriplet(visit, "bool4(", "", ")"); break;
-          default: UNREACHABLE();
-        }
-        break;
-      case EOpConvBoolToFloat:
-      case EOpConvIntToFloat:
-        switch (node->getOperand()->getType().getNominalSize())
-        {
-          case 1:    outputTriplet(visit, "float(", "", ")");  break;
-          case 2:    outputTriplet(visit, "float2(", "", ")"); break;
-          case 3:    outputTriplet(visit, "float3(", "", ")"); break;
-          case 4:    outputTriplet(visit, "float4(", "", ")"); break;
-          default: UNREACHABLE();
-        }
-        break;
-      case EOpConvFloatToInt:
-      case EOpConvBoolToInt:
-        switch (node->getOperand()->getType().getNominalSize())
-        {
-          case 1:    outputTriplet(visit, "int(", "", ")");  break;
-          case 2:    outputTriplet(visit, "int2(", "", ")"); break;
-          case 3:    outputTriplet(visit, "int3(", "", ")"); break;
-          case 4:    outputTriplet(visit, "int4(", "", ")"); break;
-          default: UNREACHABLE();
-        }
-        break;
-      case EOpRadians:          outputTriplet(visit, "radians(", "", ")");   break;
-      case EOpDegrees:          outputTriplet(visit, "degrees(", "", ")");   break;
-      case EOpSin:              outputTriplet(visit, "sin(", "", ")");       break;
-      case EOpCos:              outputTriplet(visit, "cos(", "", ")");       break;
-      case EOpTan:              outputTriplet(visit, "tan(", "", ")");       break;
-      case EOpAsin:             outputTriplet(visit, "asin(", "", ")");      break;
-      case EOpAcos:             outputTriplet(visit, "acos(", "", ")");      break;
-      case EOpAtan:             outputTriplet(visit, "atan(", "", ")");      break;
-      case EOpExp:              outputTriplet(visit, "exp(", "", ")");       break;
-      case EOpLog:              outputTriplet(visit, "log(", "", ")");       break;
-      case EOpExp2:             outputTriplet(visit, "exp2(", "", ")");      break;
-      case EOpLog2:             outputTriplet(visit, "log2(", "", ")");      break;
-      case EOpSqrt:             outputTriplet(visit, "sqrt(", "", ")");      break;
-      case EOpInverseSqrt:      outputTriplet(visit, "rsqrt(", "", ")");     break;
-      case EOpAbs:              outputTriplet(visit, "abs(", "", ")");       break;
-      case EOpSign:             outputTriplet(visit, "sign(", "", ")");      break;
-      case EOpFloor:            outputTriplet(visit, "floor(", "", ")");     break;
-      case EOpCeil:             outputTriplet(visit, "ceil(", "", ")");      break;
-      case EOpFract:            outputTriplet(visit, "frac(", "", ")");      break;
-      case EOpLength:           outputTriplet(visit, "length(", "", ")");    break;
-      case EOpNormalize:        outputTriplet(visit, "normalize(", "", ")"); break;
-      case EOpDFdx:
-        if(mInsideDiscontinuousLoop || mOutputLod0Function)
-        {
-            outputTriplet(visit, "(", "", ", 0.0)");
-        }
-        else
-        {
-            outputTriplet(visit, "ddx(", "", ")");
-        }
-        break;
-      case EOpDFdy:
-        if(mInsideDiscontinuousLoop || mOutputLod0Function)
-        {
-            outputTriplet(visit, "(", "", ", 0.0)");
-        }
-        else
-        {
-           outputTriplet(visit, "ddy(", "", ")");
-        }
-        break;
-      case EOpFwidth:
-        if(mInsideDiscontinuousLoop || mOutputLod0Function)
-        {
-            outputTriplet(visit, "(", "", ", 0.0)");
-        }
-        else
-        {
-            outputTriplet(visit, "fwidth(", "", ")");
-        }
-        break;
-      case EOpAny:              outputTriplet(visit, "any(", "", ")");       break;
-      case EOpAll:              outputTriplet(visit, "all(", "", ")");       break;
-      default: UNREACHABLE();
-    }
-
-    return true;
-}
-
-bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
-{
-    TInfoSinkBase &out = mBody;
-
-    switch (node->getOp())
-    {
-      case EOpSequence:
-        {
-            if (mInsideFunction)
-            {
-                outputLineDirective(node->getLine().first_line);
-                out << "{\n";
-
-                mScopeDepth++;
-
-                if (mScopeBracket.size() < mScopeDepth)
-                {
-                    mScopeBracket.push_back(0);   // New scope level
-                }
-                else
-                {
-                    mScopeBracket[mScopeDepth - 1]++;   // New scope at existing level
-                }
-            }
-
-            for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
-            {
-                outputLineDirective((*sit)->getLine().first_line);
-
-                traverseStatements(*sit);
-
-                out << ";\n";
-            }
-
-            if (mInsideFunction)
-            {
-                outputLineDirective(node->getLine().last_line);
-                out << "}\n";
-
-                mScopeDepth--;
-            }
-
-            return false;
-        }
-      case EOpDeclaration:
-        if (visit == PreVisit)
-        {
-            TIntermSequence &sequence = node->getSequence();
-            TIntermTyped *variable = sequence[0]->getAsTyped();
-
-            if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal))
-            {
-                if (variable->getType().getStruct())
-                {
-                    addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL);
-                }
-
-                if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "")   // Variable declaration
-                {
-                    if (!mInsideFunction)
-                    {
-                        out << "static ";
-                    }
-
-                    out << typeString(variable->getType()) + " ";
-
-                    for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
-                    {
-                        TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
-
-                        if (symbol)
-                        {
-                            symbol->traverse(this);
-                            out << arrayString(symbol->getType());
-                            out << " = " + initializer(variable->getType());
-                        }
-                        else
-                        {
-                            (*sit)->traverse(this);
-                        }
-
-                        if (*sit != sequence.back())
-                        {
-                            out << ", ";
-                        }
-                    }
-                }
-                else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "")   // Type (struct) declaration
-                {
-                    // Already added to constructor map
-                }
-                else UNREACHABLE();
-            }
-            else if (variable && (variable->getQualifier() == EvqVaryingOut || variable->getQualifier() == EvqInvariantVaryingOut))
-            {
-                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
-                {
-                    TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
-
-                    if (symbol)
-                    {
-                        // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking
-                        mReferencedVaryings[symbol->getSymbol()] = symbol;
-                    }
-                    else
-                    {
-                        (*sit)->traverse(this);
-                    }
-                }
-            }
-
-            return false;
-        }
-        else if (visit == InVisit)
-        {
-            out << ", ";
-        }
-        break;
-      case EOpPrototype:
-        if (visit == PreVisit)
-        {
-            out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
-
-            TIntermSequence &arguments = node->getSequence();
-
-            for (unsigned int i = 0; i < arguments.size(); i++)
-            {
-                TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
-
-                if (symbol)
-                {
-                    out << argumentString(symbol);
-
-                    if (i < arguments.size() - 1)
-                    {
-                        out << ", ";
-                    }
-                }
-                else UNREACHABLE();
-            }
-
-            out << ");\n";
-
-            // Also prototype the Lod0 variant if needed
-            if (mContainsLoopDiscontinuity && !mOutputLod0Function)
-            {
-                mOutputLod0Function = true;
-                node->traverse(this);
-                mOutputLod0Function = false;
-            }
-
-            return false;
-        }
-        break;
-      case EOpComma:            outputTriplet(visit, "(", ", ", ")");                break;
-      case EOpFunction:
-        {
-            TString name = TFunction::unmangleName(node->getName());
-
-            out << typeString(node->getType()) << " ";
-
-            if (name == "main")
-            {
-                out << "gl_main(";
-            }
-            else
-            {
-                out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "(");
-            }
-
-            TIntermSequence &sequence = node->getSequence();
-            TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
-
-            for (unsigned int i = 0; i < arguments.size(); i++)
-            {
-                TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
-
-                if (symbol)
-                {
-                    if (symbol->getType().getStruct())
-                    {
-                        addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL);
-                    }
-
-                    out << argumentString(symbol);
-
-                    if (i < arguments.size() - 1)
-                    {
-                        out << ", ";
-                    }
-                }
-                else UNREACHABLE();
-            }
-
-            out << ")\n"
-                "{\n";
-            
-            if (sequence.size() > 1)
-            {
-                mInsideFunction = true;
-                sequence[1]->traverse(this);
-                mInsideFunction = false;
-            }
-            
-            out << "}\n";
-
-            if (mContainsLoopDiscontinuity && !mOutputLod0Function)
-            {
-                if (name != "main")
-                {
-                    mOutputLod0Function = true;
-                    node->traverse(this);
-                    mOutputLod0Function = false;
-                }
-            }
-
-            return false;
-        }
-        break;
-      case EOpFunctionCall:
-        {
-            TString name = TFunction::unmangleName(node->getName());
-            bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
-
-            if (node->isUserDefined())
-            {
-                out << decorate(name) << (lod0 ? "Lod0(" : "(");
-            }
-            else
-            {
-                if (name == "texture2D")
-                {
-                    if (!lod0)
-                    {
-                        if (node->getSequence().size() == 2)
-                        {
-                            mUsesTexture2D = true;
-                        }
-                        else if (node->getSequence().size() == 3)
-                        {
-                            mUsesTexture2D_bias = true;
-                        }
-                        else UNREACHABLE();
-
-                        out << "gl_texture2D(";
-                    }
-                    else
-                    {
-                        if (node->getSequence().size() == 2)
-                        {
-                            mUsesTexture2DLod0 = true;
-                        }
-                        else if (node->getSequence().size() == 3)
-                        {
-                            mUsesTexture2DLod0_bias = true;
-                        }
-                        else UNREACHABLE();
-
-                        out << "gl_texture2DLod0(";
-                    }
-                }
-                else if (name == "texture2DProj")
-                {
-                    if (!lod0)
-                    {
-                        if (node->getSequence().size() == 2)
-                        {
-                            mUsesTexture2DProj = true;
-                        }
-                        else if (node->getSequence().size() == 3)
-                        {
-                            mUsesTexture2DProj_bias = true;
-                        }
-                        else UNREACHABLE();
-
-                        out << "gl_texture2DProj(";
-                    }
-                    else
-                    {
-                        if (node->getSequence().size() == 2)
-                        {
-                            mUsesTexture2DProjLod0 = true;
-                        }
-                        else if (node->getSequence().size() == 3)
-                        {
-                            mUsesTexture2DProjLod0_bias = true;
-                        }
-                        else UNREACHABLE();
-
-                        out << "gl_texture2DProjLod0(";
-                    }
-                }
-                else if (name == "textureCube")
-                {
-                    if (!lod0)
-                    {
-                        if (node->getSequence().size() == 2)
-                        {
-                            mUsesTextureCube = true;
-                        }
-                        else if (node->getSequence().size() == 3)
-                        {
-                            mUsesTextureCube_bias = true;
-                        }
-                        else UNREACHABLE();
-
-                        out << "gl_textureCube(";
-                    }
-                    else
-                    {
-                        if (node->getSequence().size() == 2)
-                        {
-                            mUsesTextureCubeLod0 = true;
-                        }
-                        else if (node->getSequence().size() == 3)
-                        {
-                            mUsesTextureCubeLod0_bias = true;
-                        }
-                        else UNREACHABLE();
-
-                        out << "gl_textureCubeLod0(";
-                    }
-                }
-                else if (name == "texture2DLod")
-                {
-                    if (node->getSequence().size() == 3)
-                    {
-                        mUsesTexture2DLod = true;
-                    }
-                    else UNREACHABLE();
-
-                    out << "gl_texture2DLod(";
-                }
-                else if (name == "texture2DProjLod")
-                {
-                    if (node->getSequence().size() == 3)
-                    {
-                        mUsesTexture2DProjLod = true;
-                    }
-                    else UNREACHABLE();
-
-                    out << "gl_texture2DProjLod(";
-                }
-                else if (name == "textureCubeLod")
-                {
-                    if (node->getSequence().size() == 3)
-                    {
-                        mUsesTextureCubeLod = true;
-                    }
-                    else UNREACHABLE();
-
-                    out << "gl_textureCubeLod(";
-                }
-                else UNREACHABLE();
-            }
-
-            TIntermSequence &arguments = node->getSequence();
-
-            for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++)
-            {
-                if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType()))
-                {
-                    out << "texture_";
-                    (*arg)->traverse(this);
-                    out << ", sampler_";
-                }
-
-                (*arg)->traverse(this);
-
-                if (arg < arguments.end() - 1)
-                {
-                    out << ", ";
-                }
-            }
-
-            out << ")";
-
-            return false;
-        }
-        break;
-      case EOpParameters:       outputTriplet(visit, "(", ", ", ")\n{\n");             break;
-      case EOpConstructFloat:
-        addConstructor(node->getType(), "vec1", &node->getSequence());
-        outputTriplet(visit, "vec1(", "", ")");
-        break;
-      case EOpConstructVec2:
-        addConstructor(node->getType(), "vec2", &node->getSequence());
-        outputTriplet(visit, "vec2(", ", ", ")");
-        break;
-      case EOpConstructVec3:
-        addConstructor(node->getType(), "vec3", &node->getSequence());
-        outputTriplet(visit, "vec3(", ", ", ")");
-        break;
-      case EOpConstructVec4:
-        addConstructor(node->getType(), "vec4", &node->getSequence());
-        outputTriplet(visit, "vec4(", ", ", ")");
-        break;
-      case EOpConstructBool:
-        addConstructor(node->getType(), "bvec1", &node->getSequence());
-        outputTriplet(visit, "bvec1(", "", ")");
-        break;
-      case EOpConstructBVec2:
-        addConstructor(node->getType(), "bvec2", &node->getSequence());
-        outputTriplet(visit, "bvec2(", ", ", ")");
-        break;
-      case EOpConstructBVec3:
-        addConstructor(node->getType(), "bvec3", &node->getSequence());
-        outputTriplet(visit, "bvec3(", ", ", ")");
-        break;
-      case EOpConstructBVec4:
-        addConstructor(node->getType(), "bvec4", &node->getSequence());
-        outputTriplet(visit, "bvec4(", ", ", ")");
-        break;
-      case EOpConstructInt:
-        addConstructor(node->getType(), "ivec1", &node->getSequence());
-        outputTriplet(visit, "ivec1(", "", ")");
-        break;
-      case EOpConstructIVec2:
-        addConstructor(node->getType(), "ivec2", &node->getSequence());
-        outputTriplet(visit, "ivec2(", ", ", ")");
-        break;
-      case EOpConstructIVec3:
-        addConstructor(node->getType(), "ivec3", &node->getSequence());
-        outputTriplet(visit, "ivec3(", ", ", ")");
-        break;
-      case EOpConstructIVec4:
-        addConstructor(node->getType(), "ivec4", &node->getSequence());
-        outputTriplet(visit, "ivec4(", ", ", ")");
-        break;
-      case EOpConstructMat2:
-        addConstructor(node->getType(), "mat2", &node->getSequence());
-        outputTriplet(visit, "mat2(", ", ", ")");
-        break;
-      case EOpConstructMat3:
-        addConstructor(node->getType(), "mat3", &node->getSequence());
-        outputTriplet(visit, "mat3(", ", ", ")");
-        break;
-      case EOpConstructMat4: 
-        addConstructor(node->getType(), "mat4", &node->getSequence());
-        outputTriplet(visit, "mat4(", ", ", ")");
-        break;
-      case EOpConstructStruct:
-        addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence());
-        outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")");
-        break;
-      case EOpLessThan:         outputTriplet(visit, "(", " < ", ")");                 break;
-      case EOpGreaterThan:      outputTriplet(visit, "(", " > ", ")");                 break;
-      case EOpLessThanEqual:    outputTriplet(visit, "(", " <= ", ")");                break;
-      case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")");                break;
-      case EOpVectorEqual:      outputTriplet(visit, "(", " == ", ")");                break;
-      case EOpVectorNotEqual:   outputTriplet(visit, "(", " != ", ")");                break;
-      case EOpMod:
-        {
-            // We need to look at the number of components in both arguments
-            switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10
-                     + node->getSequence()[1]->getAsTyped()->getNominalSize())
-            {
-              case 11: mUsesMod1 = true; break;
-              case 22: mUsesMod2v = true; break;
-              case 21: mUsesMod2f = true; break;
-              case 33: mUsesMod3v = true; break;
-              case 31: mUsesMod3f = true; break;
-              case 44: mUsesMod4v = true; break;
-              case 41: mUsesMod4f = true; break;
-              default: UNREACHABLE();
-            }
-
-            outputTriplet(visit, "mod(", ", ", ")");
-        }
-        break;
-      case EOpPow:              outputTriplet(visit, "pow(", ", ", ")");               break;
-      case EOpAtan:
-        ASSERT(node->getSequence().size() == 2);   // atan(x) is a unary operator
-        switch (node->getSequence()[0]->getAsTyped()->getNominalSize())
-        {
-          case 1: mUsesAtan2_1 = true; break;
-          case 2: mUsesAtan2_2 = true; break;
-          case 3: mUsesAtan2_3 = true; break;
-          case 4: mUsesAtan2_4 = true; break;
-          default: UNREACHABLE();
-        }
-        outputTriplet(visit, "atanyx(", ", ", ")");
-        break;
-      case EOpMin:           outputTriplet(visit, "min(", ", ", ")");           break;
-      case EOpMax:           outputTriplet(visit, "max(", ", ", ")");           break;
-      case EOpClamp:         outputTriplet(visit, "clamp(", ", ", ")");         break;
-      case EOpMix:           outputTriplet(visit, "lerp(", ", ", ")");          break;
-      case EOpStep:          outputTriplet(visit, "step(", ", ", ")");          break;
-      case EOpSmoothStep:    outputTriplet(visit, "smoothstep(", ", ", ")");    break;
-      case EOpDistance:      outputTriplet(visit, "distance(", ", ", ")");      break;
-      case EOpDot:           outputTriplet(visit, "dot(", ", ", ")");           break;
-      case EOpCross:         outputTriplet(visit, "cross(", ", ", ")");         break;
-      case EOpFaceForward:
-        {
-            switch (node->getSequence()[0]->getAsTyped()->getNominalSize())   // Number of components in the first argument
-            {
-            case 1: mUsesFaceforward1 = true; break;
-            case 2: mUsesFaceforward2 = true; break;
-            case 3: mUsesFaceforward3 = true; break;
-            case 4: mUsesFaceforward4 = true; break;
-            default: UNREACHABLE();
-            }
-            
-            outputTriplet(visit, "faceforward(", ", ", ")");
-        }
-        break;
-      case EOpReflect:       outputTriplet(visit, "reflect(", ", ", ")");       break;
-      case EOpRefract:       outputTriplet(visit, "refract(", ", ", ")");       break;
-      case EOpMul:           outputTriplet(visit, "(", " * ", ")");             break;
-      default: UNREACHABLE();
-    }
-
-    return true;
-}
-
-bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
-{
-    TInfoSinkBase &out = mBody;
-
-    if (node->usesTernaryOperator())
-    {
-        out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
-    }
-    else  // if/else statement
-    {
-        mUnfoldShortCircuit->traverse(node->getCondition());
-
-        out << "if(";
-
-        node->getCondition()->traverse(this);
-
-        out << ")\n";
-        
-        outputLineDirective(node->getLine().first_line);
-        out << "{\n";
-
-        if (node->getTrueBlock())
-        {
-            traverseStatements(node->getTrueBlock());
-        }
-
-        outputLineDirective(node->getLine().first_line);
-        out << ";\n}\n";
-
-        if (node->getFalseBlock())
-        {
-            out << "else\n";
-
-            outputLineDirective(node->getFalseBlock()->getLine().first_line);
-            out << "{\n";
-
-            outputLineDirective(node->getFalseBlock()->getLine().first_line);
-            traverseStatements(node->getFalseBlock());
-
-            outputLineDirective(node->getFalseBlock()->getLine().first_line);
-            out << ";\n}\n";
-        }
-    }
-
-    return false;
-}
-
-void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
-{
-    writeConstantUnion(node->getType(), node->getUnionArrayPointer());
-}
-
-bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
-{
-    bool wasDiscontinuous = mInsideDiscontinuousLoop;
-
-    if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop)
-    {
-        mInsideDiscontinuousLoop = containsLoopDiscontinuity(node);
-    }
-
-    if (mOutputType == SH_HLSL9_OUTPUT)
-    {
-        if (handleExcessiveLoop(node))
-        {
-            return false;
-        }
-    }
-
-    TInfoSinkBase &out = mBody;
-
-    if (node->getType() == ELoopDoWhile)
-    {
-        out << "{do\n";
-
-        outputLineDirective(node->getLine().first_line);
-        out << "{\n";
-    }
-    else
-    {
-        out << "{for(";
-        
-        if (node->getInit())
-        {
-            node->getInit()->traverse(this);
-        }
-
-        out << "; ";
-
-        if (node->getCondition())
-        {
-            node->getCondition()->traverse(this);
-        }
-
-        out << "; ";
-
-        if (node->getExpression())
-        {
-            node->getExpression()->traverse(this);
-        }
-
-        out << ")\n";
-        
-        outputLineDirective(node->getLine().first_line);
-        out << "{\n";
-    }
-
-    if (node->getBody())
-    {
-        traverseStatements(node->getBody());
-    }
-
-    outputLineDirective(node->getLine().first_line);
-    out << ";}\n";
-
-    if (node->getType() == ELoopDoWhile)
-    {
-        outputLineDirective(node->getCondition()->getLine().first_line);
-        out << "while(\n";
-
-        node->getCondition()->traverse(this);
-
-        out << ");";
-    }
-
-    out << "}\n";
-
-    mInsideDiscontinuousLoop = wasDiscontinuous;
-
-    return false;
-}
-
-bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
-{
-    TInfoSinkBase &out = mBody;
-
-    switch (node->getFlowOp())
-    {
-      case EOpKill:     outputTriplet(visit, "discard;\n", "", "");  break;
-      case EOpBreak:
-        if (visit == PreVisit)
-        {
-            if (mExcessiveLoopIndex)
-            {
-                out << "{Break";
-                mExcessiveLoopIndex->traverse(this);
-                out << " = true; break;}\n";
-            }
-            else
-            {
-                out << "break;\n";
-            }
-        }
-        break;
-      case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
-      case EOpReturn:
-        if (visit == PreVisit)
-        {
-            if (node->getExpression())
-            {
-                out << "return ";
-            }
-            else
-            {
-                out << "return;\n";
-            }
-        }
-        else if (visit == PostVisit)
-        {
-            if (node->getExpression())
-            {
-                out << ";\n";
-            }
-        }
-        break;
-      default: UNREACHABLE();
-    }
-
-    return true;
-}
-
-void OutputHLSL::traverseStatements(TIntermNode *node)
-{
-    if (isSingleStatement(node))
-    {
-        mUnfoldShortCircuit->traverse(node);
-    }
-
-    node->traverse(this);
-}
-
-bool OutputHLSL::isSingleStatement(TIntermNode *node)
-{
-    TIntermAggregate *aggregate = node->getAsAggregate();
-
-    if (aggregate)
-    {
-        if (aggregate->getOp() == EOpSequence)
-        {
-            return false;
-        }
-        else
-        {
-            for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++)
-            {
-                if (!isSingleStatement(*sit))
-                {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-    }
-
-    return true;
-}
-
-// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
-// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
-bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
-{
-    const int MAX_LOOP_ITERATIONS = 254;
-    TInfoSinkBase &out = mBody;
-
-    // Parse loops of the form:
-    // for(int index = initial; index [comparator] limit; index += increment)
-    TIntermSymbol *index = NULL;
-    TOperator comparator = EOpNull;
-    int initial = 0;
-    int limit = 0;
-    int increment = 0;
-
-    // Parse index name and intial value
-    if (node->getInit())
-    {
-        TIntermAggregate *init = node->getInit()->getAsAggregate();
-
-        if (init)
-        {
-            TIntermSequence &sequence = init->getSequence();
-            TIntermTyped *variable = sequence[0]->getAsTyped();
-
-            if (variable && variable->getQualifier() == EvqTemporary)
-            {
-                TIntermBinary *assign = variable->getAsBinaryNode();
-
-                if (assign->getOp() == EOpInitialize)
-                {
-                    TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
-                    TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
-
-                    if (symbol && constant)
-                    {
-                        if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
-                        {
-                            index = symbol;
-                            initial = constant->getIConst(0);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // Parse comparator and limit value
-    if (index != NULL && node->getCondition())
-    {
-        TIntermBinary *test = node->getCondition()->getAsBinaryNode();
-        
-        if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
-        {
-            TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
-
-            if (constant)
-            {
-                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
-                {
-                    comparator = test->getOp();
-                    limit = constant->getIConst(0);
-                }
-            }
-        }
-    }
-
-    // Parse increment
-    if (index != NULL && comparator != EOpNull && node->getExpression())
-    {
-        TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
-        TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
-        
-        if (binaryTerminal)
-        {
-            TOperator op = binaryTerminal->getOp();
-            TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
-
-            if (constant)
-            {
-                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
-                {
-                    int value = constant->getIConst(0);
-
-                    switch (op)
-                    {
-                      case EOpAddAssign: increment = value;  break;
-                      case EOpSubAssign: increment = -value; break;
-                      default: UNIMPLEMENTED();
-                    }
-                }
-            }
-        }
-        else if (unaryTerminal)
-        {
-            TOperator op = unaryTerminal->getOp();
-
-            switch (op)
-            {
-              case EOpPostIncrement: increment = 1;  break;
-              case EOpPostDecrement: increment = -1; break;
-              case EOpPreIncrement:  increment = 1;  break;
-              case EOpPreDecrement:  increment = -1; break;
-              default: UNIMPLEMENTED();
-            }
-        }
-    }
-
-    if (index != NULL && comparator != EOpNull && increment != 0)
-    {
-        if (comparator == EOpLessThanEqual)
-        {
-            comparator = EOpLessThan;
-            limit += 1;
-        }
-
-        if (comparator == EOpLessThan)
-        {
-            int iterations = (limit - initial) / increment;
-
-            if (iterations <= MAX_LOOP_ITERATIONS)
-            {
-                return false;   // Not an excessive loop
-            }
-
-            TIntermSymbol *restoreIndex = mExcessiveLoopIndex;
-            mExcessiveLoopIndex = index;
-
-            out << "{int ";
-            index->traverse(this);
-            out << ";\n"
-                   "bool Break";
-            index->traverse(this);
-            out << " = false;\n";
-
-            bool firstLoopFragment = true;
-
-            while (iterations > 0)
-            {
-                int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations);
-
-                if (!firstLoopFragment)
-                {
-                    out << "if(!Break";
-                    index->traverse(this);
-                    out << ") {\n";
-                }
-
-                if (iterations <= MAX_LOOP_ITERATIONS)   // Last loop fragment
-                {
-                    mExcessiveLoopIndex = NULL;   // Stops setting the Break flag
-                }
-                
-                // for(int index = initial; index < clampedLimit; index += increment)
-
-                out << "for(";
-                index->traverse(this);
-                out << " = ";
-                out << initial;
-
-                out << "; ";
-                index->traverse(this);
-                out << " < ";
-                out << clampedLimit;
-
-                out << "; ";
-                index->traverse(this);
-                out << " += ";
-                out << increment;
-                out << ")\n";
-                
-                outputLineDirective(node->getLine().first_line);
-                out << "{\n";
-
-                if (node->getBody())
-                {
-                    node->getBody()->traverse(this);
-                }
-
-                outputLineDirective(node->getLine().first_line);
-                out << ";}\n";
-
-                if (!firstLoopFragment)
-                {
-                    out << "}\n";
-                }
-
-                firstLoopFragment = false;
-
-                initial += MAX_LOOP_ITERATIONS * increment;
-                iterations -= MAX_LOOP_ITERATIONS;
-            }
-            
-            out << "}";
-
-            mExcessiveLoopIndex = restoreIndex;
-
-            return true;
-        }
-        else UNIMPLEMENTED();
-    }
-
-    return false;   // Not handled as an excessive loop
-}
-
-void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
-{
-    TInfoSinkBase &out = mBody;
-
-    if (visit == PreVisit)
-    {
-        out << preString;
-    }
-    else if (visit == InVisit)
-    {
-        out << inString;
-    }
-    else if (visit == PostVisit)
-    {
-        out << postString;
-    }
-}
-
-void OutputHLSL::outputLineDirective(int line)
-{
-    if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
-    {
-        mBody << "\n";
-        mBody << "#line " << line;
-
-        if (mContext.sourcePath)
-        {
-            mBody << " \"" << mContext.sourcePath << "\"";
-        }
-        
-        mBody << "\n";
-    }
-}
-
-TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
-{
-    TQualifier qualifier = symbol->getQualifier();
-    const TType &type = symbol->getType();
-    TString name = symbol->getSymbol();
-
-    if (name.empty())   // HLSL demands named arguments, also for prototypes
-    {
-        name = "x" + str(mUniqueIndex++);
-    }
-    else
-    {
-        name = decorate(name);
-    }
-
-    if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
-    {
-       return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " +
-              qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type);
-    }
-
-    return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
-}
-
-TString OutputHLSL::qualifierString(TQualifier qualifier)
-{
-    switch(qualifier)
-    {
-      case EvqIn:            return "in";
-      case EvqOut:           return "out";
-      case EvqInOut:         return "inout";
-      case EvqConstReadOnly: return "const";
-      default: UNREACHABLE();
-    }
-
-    return "";
-}
-
-TString OutputHLSL::typeString(const TType &type)
-{
-    if (type.getBasicType() == EbtStruct)
-    {
-        const TString& typeName = type.getStruct()->name();
-        if (typeName != "")
-        {
-            return structLookup(typeName);
-        }
-        else   // Nameless structure, define in place
-        {
-            const TFieldList &fields = type.getStruct()->fields();
-
-            TString string = "struct\n"
-                             "{\n";
-
-            for (unsigned int i = 0; i < fields.size(); i++)
-            {
-                const TField *field = fields[i];
-
-                string += "    " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n";
-            }
-
-            string += "} ";
-
-            return string;
-        }
-    }
-    else if (type.isMatrix())
-    {
-        switch (type.getNominalSize())
-        {
-          case 2: return "float2x2";
-          case 3: return "float3x3";
-          case 4: return "float4x4";
-        }
-    }
-    else
-    {
-        switch (type.getBasicType())
-        {
-          case EbtFloat:
-            switch (type.getNominalSize())
-            {
-              case 1: return "float";
-              case 2: return "float2";
-              case 3: return "float3";
-              case 4: return "float4";
-            }
-          case EbtInt:
-            switch (type.getNominalSize())
-            {
-              case 1: return "int";
-              case 2: return "int2";
-              case 3: return "int3";
-              case 4: return "int4";
-            }
-          case EbtBool:
-            switch (type.getNominalSize())
-            {
-              case 1: return "bool";
-              case 2: return "bool2";
-              case 3: return "bool3";
-              case 4: return "bool4";
-            }
-          case EbtVoid:
-            return "void";
-          case EbtSampler2D:
-            return "sampler2D";
-          case EbtSamplerCube:
-            return "samplerCUBE";
-          case EbtSamplerExternalOES:
-            return "sampler2D";
-          default:
-            break;
-        }
-    }
-
-    UNREACHABLE();
-    return "<unknown type>";
-}
-
-TString OutputHLSL::textureString(const TType &type)
-{
-    switch (type.getBasicType())
-    {
-      case EbtSampler2D:
-        return "Texture2D";
-      case EbtSamplerCube:
-        return "TextureCube";
-      case EbtSamplerExternalOES:
-        return "Texture2D";
-      default:
-        break;
-    }
-
-    UNREACHABLE();
-    return "<unknown texture type>";
-}
-
-TString OutputHLSL::arrayString(const TType &type)
-{
-    if (!type.isArray())
-    {
-        return "";
-    }
-
-    return "[" + str(type.getArraySize()) + "]";
-}
-
-TString OutputHLSL::initializer(const TType &type)
-{
-    TString string;
-
-    size_t size = type.getObjectSize();
-    for (size_t component = 0; component < size; component++)
-    {
-        string += "0";
-
-        if (component + 1 < size)
-        {
-            string += ", ";
-        }
-    }
-
-    return "{" + string + "}";
-}
-
-void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
-{
-    if (name == "")
-    {
-        return;   // Nameless structures don't have constructors
-    }
-
-    if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end())
-    {
-        return;   // Already added
-    }
-
-    TType ctorType = type;
-    ctorType.clearArrayness();
-    ctorType.setPrecision(EbpHigh);
-    ctorType.setQualifier(EvqTemporary);
-
-    TString ctorName = type.getStruct() ? decorate(name) : name;
-
-    typedef std::vector<TType> ParameterArray;
-    ParameterArray ctorParameters;
-
-    if (type.getStruct())
-    {
-        mStructNames.insert(decorate(name));
-
-        TString structure;
-        structure += "struct " + decorate(name) + "\n"
-                     "{\n";
-
-        const TFieldList &fields = type.getStruct()->fields();
-
-        for (unsigned int i = 0; i < fields.size(); i++)
-        {
-            const TField *field = fields[i];
-
-            structure += "    " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n";
-        }
-
-        structure += "};\n";
-
-        if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
-        {
-            mStructDeclarations.push_back(structure);
-        }
-
-        for (unsigned int i = 0; i < fields.size(); i++)
-        {
-            ctorParameters.push_back(*fields[i]->type());
-        }
-    }
-    else if (parameters)
-    {
-        for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
-        {
-            ctorParameters.push_back((*parameter)->getAsTyped()->getType());
-        }
-    }
-    else UNREACHABLE();
-
-    TString constructor;
-
-    if (ctorType.getStruct())
-    {
-        constructor += ctorName + " " + ctorName + "_ctor(";
-    }
-    else   // Built-in type
-    {
-        constructor += typeString(ctorType) + " " + ctorName + "(";
-    }
-
-    for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
-    {
-        const TType &type = ctorParameters[parameter];
-
-        constructor += typeString(type) + " x" + str(parameter) + arrayString(type);
-
-        if (parameter < ctorParameters.size() - 1)
-        {
-            constructor += ", ";
-        }
-    }
-
-    constructor += ")\n"
-                   "{\n";
-
-    if (ctorType.getStruct())
-    {
-        constructor += "    " + ctorName + " structure = {";
-    }
-    else
-    {
-        constructor += "    return " + typeString(ctorType) + "(";
-    }
-
-    if (ctorType.isMatrix() && ctorParameters.size() == 1)
-    {
-        int dim = ctorType.getNominalSize();
-        const TType &parameter = ctorParameters[0];
-
-        if (parameter.isScalar())
-        {
-            for (int row = 0; row < dim; row++)
-            {
-                for (int col = 0; col < dim; col++)
-                {
-                    constructor += TString((row == col) ? "x0" : "0.0");
-                    
-                    if (row < dim - 1 || col < dim - 1)
-                    {
-                        constructor += ", ";
-                    }
-                }
-            }
-        }
-        else if (parameter.isMatrix())
-        {
-            for (int row = 0; row < dim; row++)
-            {
-                for (int col = 0; col < dim; col++)
-                {
-                    if (row < parameter.getNominalSize() && col < parameter.getNominalSize())
-                    {
-                        constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
-                    }
-                    else
-                    {
-                        constructor += TString((row == col) ? "1.0" : "0.0");
-                    }
-
-                    if (row < dim - 1 || col < dim - 1)
-                    {
-                        constructor += ", ";
-                    }
-                }
-            }
-        }
-        else UNREACHABLE();
-    }
-    else
-    {
-        size_t remainingComponents = ctorType.getObjectSize();
-        size_t parameterIndex = 0;
-
-        while (remainingComponents > 0)
-        {
-            const TType &parameter = ctorParameters[parameterIndex];
-            const size_t parameterSize = parameter.getObjectSize();
-            bool moreParameters = parameterIndex + 1 < ctorParameters.size();
-
-            constructor += "x" + str(parameterIndex);
-
-            if (parameter.isScalar())
-            {
-                ASSERT(parameterSize <= remainingComponents);
-                remainingComponents -= parameterSize;
-            }
-            else if (parameter.isVector())
-            {
-                if (remainingComponents == parameterSize || moreParameters)
-                {
-                    ASSERT(parameterSize <= remainingComponents);
-                    remainingComponents -= parameterSize;
-                }
-                else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
-                {
-                    switch (remainingComponents)
-                    {
-                      case 1: constructor += ".x";    break;
-                      case 2: constructor += ".xy";   break;
-                      case 3: constructor += ".xyz";  break;
-                      case 4: constructor += ".xyzw"; break;
-                      default: UNREACHABLE();
-                    }
-
-                    remainingComponents = 0;
-                }
-                else UNREACHABLE();
-            }
-            else if (parameter.isMatrix() || parameter.getStruct())
-            {
-                ASSERT(remainingComponents == parameterSize || moreParameters);
-                ASSERT(parameterSize <= remainingComponents);
-                
-                remainingComponents -= parameterSize;
-            }
-            else UNREACHABLE();
-
-            if (moreParameters)
-            {
-                parameterIndex++;
-            }
-
-            if (remainingComponents)
-            {
-                constructor += ", ";
-            }
-        }
-    }
-
-    if (ctorType.getStruct())
-    {
-        constructor += "};\n"
-                       "    return structure;\n"
-                       "}\n";
-    }
-    else
-    {
-        constructor += ");\n"
-                       "}\n";
-    }
-
-    mConstructors.insert(constructor);
-}
-
-const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
-{
-    TInfoSinkBase &out = mBody;
-
-    if (type.getBasicType() == EbtStruct)
-    {
-        out << structLookup(type.getStruct()->name()) + "_ctor(";
-        
-        const TFieldList &fields = type.getStruct()->fields();
-
-        for (size_t i = 0; i < fields.size(); i++)
-        {
-            const TType *fieldType = fields[i]->type();
-
-            constUnion = writeConstantUnion(*fieldType, constUnion);
-
-            if (i != fields.size() - 1)
-            {
-                out << ", ";
-            }
-        }
-
-        out << ")";
-    }
-    else
-    {
-        size_t size = type.getObjectSize();
-        bool writeType = size > 1;
-        
-        if (writeType)
-        {
-            out << typeString(type) << "(";
-        }
-
-        for (size_t i = 0; i < size; i++, constUnion++)
-        {
-            switch (constUnion->getType())
-            {
-              case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break;
-              case EbtInt:   out << constUnion->getIConst(); break;
-              case EbtBool:  out << constUnion->getBConst(); break;
-              default: UNREACHABLE();
-            }
-
-            if (i != size - 1)
-            {
-                out << ", ";
-            }
-        }
-
-        if (writeType)
-        {
-            out << ")";
-        }
-    }
-
-    return constUnion;
-}
-
-TString OutputHLSL::scopeString(unsigned int depthLimit)
-{
-    TString string;
-
-    for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++)
-    {
-        string += "_" + str(i);
-    }
-
-    return string;
-}
-
-TString OutputHLSL::scopedStruct(const TString &typeName)
-{
-    if (typeName == "")
-    {
-        return typeName;
-    }
-
-    return typeName + scopeString(mScopeDepth);
-}
-
-TString OutputHLSL::structLookup(const TString &typeName)
-{
-    for (int depth = mScopeDepth; depth >= 0; depth--)
-    {
-        TString scopedName = decorate(typeName + scopeString(depth));
-
-        for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++)
-        {
-            if (*structName == scopedName)
-            {
-                return scopedName;
-            }
-        }
-    }
-
-    UNREACHABLE();   // Should have found a matching constructor
-
-    return typeName;
-}
-
-TString OutputHLSL::decorate(const TString &string)
-{
-    if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0)
-    {
-        return "_" + string;
-    }
-    
-    return string;
-}
-
-TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
-{
-    if (type.getBasicType() == EbtSamplerExternalOES)
-    {
-        return "ex_" + string;
-    }
-    
-    return decorate(string);
-}
-
-TString OutputHLSL::decorateField(const TString &string, const TType &structure)
-{
-    if (structure.getStruct()->name().compare(0, 3, "gl_") != 0)
-    {
-        return decorate(string);
-    }
-
-    return string;
-}
-
-TString OutputHLSL::registerString(TIntermSymbol *operand)
-{
-    ASSERT(operand->getQualifier() == EvqUniform);
-
-    if (IsSampler(operand->getBasicType()))
-    {
-        return "s" + str(samplerRegister(operand));
-    }
-
-    return "c" + str(uniformRegister(operand));
-}
-
-int OutputHLSL::samplerRegister(TIntermSymbol *sampler)
-{
-    const TType &type = sampler->getType();
-    ASSERT(IsSampler(type.getBasicType()));
-
-    int index = mSamplerRegister;
-    mSamplerRegister += sampler->totalRegisterCount();
-
-    declareUniform(type, sampler->getSymbol(), index);
-
-    return index;
-}
-
-int OutputHLSL::uniformRegister(TIntermSymbol *uniform)
-{
-    const TType &type = uniform->getType();
-    ASSERT(!IsSampler(type.getBasicType()));
-
-    int index = mUniformRegister;
-    mUniformRegister += uniform->totalRegisterCount();
-
-    declareUniform(type, uniform->getSymbol(), index);
-
-    return index;
-}
-
-void OutputHLSL::declareUniform(const TType &type, const TString &name, int index)
-{
-    TStructure *structure = type.getStruct();
-
-    if (!structure)
-    {
-        mActiveUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), index));
-    }
-    else
-    {
-        const TFieldList &fields = structure->fields();
-
-        if (type.isArray())
-        {
-            int elementIndex = index;
-
-            for (int i = 0; i < type.getArraySize(); i++)
-            {
-                for (size_t j = 0; j < fields.size(); j++)
-                {
-                    const TType &fieldType = *fields[j]->type();
-                    const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name();
-                    declareUniform(fieldType, uniformName, elementIndex);
-                    elementIndex += fieldType.totalRegisterCount();
-                }
-            }
-        }
-        else
-        {
-            int fieldIndex = index;
-
-            for (size_t i = 0; i < fields.size(); i++)
-            {
-                const TType &fieldType = *fields[i]->type();
-                const TString uniformName = name + "." + fields[i]->name();
-                declareUniform(fieldType, uniformName, fieldIndex);
-                fieldIndex += fieldType.totalRegisterCount();
-            }
-        }
-    }
-}
-
-GLenum OutputHLSL::glVariableType(const TType &type)
-{
-    if (type.getBasicType() == EbtFloat)
-    {
-        if (type.isScalar())
-        {
-            return GL_FLOAT;
-        }
-        else if (type.isVector())
-        {
-            switch(type.getNominalSize())
-            {
-              case 2: return GL_FLOAT_VEC2;
-              case 3: return GL_FLOAT_VEC3;
-              case 4: return GL_FLOAT_VEC4;
-              default: UNREACHABLE();
-            }
-        }
-        else if (type.isMatrix())
-        {
-            switch(type.getNominalSize())
-            {
-              case 2: return GL_FLOAT_MAT2;
-              case 3: return GL_FLOAT_MAT3;
-              case 4: return GL_FLOAT_MAT4;
-              default: UNREACHABLE();
-            }
-        }
-        else UNREACHABLE();
-    }
-    else if (type.getBasicType() == EbtInt)
-    {
-        if (type.isScalar())
-        {
-            return GL_INT;
-        }
-        else if (type.isVector())
-        {
-            switch(type.getNominalSize())
-            {
-              case 2: return GL_INT_VEC2;
-              case 3: return GL_INT_VEC3;
-              case 4: return GL_INT_VEC4;
-              default: UNREACHABLE();
-            }
-        }
-        else UNREACHABLE();
-    }
-    else if (type.getBasicType() == EbtBool)
-    {
-        if (type.isScalar())
-        {
-            return GL_BOOL;
-        }
-        else if (type.isVector())
-        {
-            switch(type.getNominalSize())
-            {
-              case 2: return GL_BOOL_VEC2;
-              case 3: return GL_BOOL_VEC3;
-              case 4: return GL_BOOL_VEC4;
-              default: UNREACHABLE();
-            }
-        }
-        else UNREACHABLE();
-    }
-    else if (type.getBasicType() == EbtSampler2D)
-    {
-        return GL_SAMPLER_2D;
-    }
-    else if (type.getBasicType() == EbtSamplerCube)
-    {
-        return GL_SAMPLER_CUBE;
-    }
-    else UNREACHABLE();
-
-    return GL_NONE;
-}
-
-GLenum OutputHLSL::glVariablePrecision(const TType &type)
-{
-    if (type.getBasicType() == EbtFloat)
-    {
-        switch (type.getPrecision())
-        {
-          case EbpHigh:   return GL_HIGH_FLOAT;
-          case EbpMedium: return GL_MEDIUM_FLOAT;
-          case EbpLow:    return GL_LOW_FLOAT;
-          case EbpUndefined:
-            // Should be defined as the default precision by the parser
-          default: UNREACHABLE();
-        }
-    }
-    else if (type.getBasicType() == EbtInt)
-    {
-        switch (type.getPrecision())
-        {
-          case EbpHigh:   return GL_HIGH_INT;
-          case EbpMedium: return GL_MEDIUM_INT;
-          case EbpLow:    return GL_LOW_INT;
-          case EbpUndefined:
-            // Should be defined as the default precision by the parser
-          default: UNREACHABLE();
-        }
-    }
-
-    // Other types (boolean, sampler) don't have a precision
-    return GL_NONE;
-}
-
-}
diff --git a/src/third_party/angle/src/compiler/OutputHLSL.h b/src/third_party/angle/src/compiler/OutputHLSL.h
deleted file mode 100644
index b33b1f5..0000000
--- a/src/third_party/angle/src/compiler/OutputHLSL.h
+++ /dev/null
@@ -1,178 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_OUTPUTHLSL_H_
-#define COMPILER_OUTPUTHLSL_H_
-
-#include <list>
-#include <set>
-#include <map>
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
-#include "compiler/intermediate.h"
-#include "compiler/ParseHelper.h"
-#include "compiler/Uniform.h"
-
-namespace sh
-{
-class UnfoldShortCircuit;
-
-class OutputHLSL : public TIntermTraverser
-{
-  public:
-    OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType);
-    ~OutputHLSL();
-
-    void output();
-
-    TInfoSinkBase &getBodyStream();
-    const ActiveUniforms &getUniforms();
-
-    TString typeString(const TType &type);
-    TString textureString(const TType &type);
-    static TString qualifierString(TQualifier qualifier);
-    static TString arrayString(const TType &type);
-    static TString initializer(const TType &type);
-    static TString decorate(const TString &string);                      // Prepends an underscore to avoid naming clashes
-    static TString decorateUniform(const TString &string, const TType &type);
-    static TString decorateField(const TString &string, const TType &structure);
-
-  protected:
-    void header();
-
-    // Visit AST nodes and output their code to the body stream
-    void visitSymbol(TIntermSymbol*);
-    void visitConstantUnion(TIntermConstantUnion*);
-    bool visitBinary(Visit visit, TIntermBinary*);
-    bool visitUnary(Visit visit, TIntermUnary*);
-    bool visitSelection(Visit visit, TIntermSelection*);
-    bool visitAggregate(Visit visit, TIntermAggregate*);
-    bool visitLoop(Visit visit, TIntermLoop*);
-    bool visitBranch(Visit visit, TIntermBranch*);
-
-    void traverseStatements(TIntermNode *node);
-    bool isSingleStatement(TIntermNode *node);
-    bool handleExcessiveLoop(TIntermLoop *node);
-    void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString);
-    void outputLineDirective(int line);
-    TString argumentString(const TIntermSymbol *symbol);
-    int vectorSize(const TType &type) const;
-
-    void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters);
-    const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
-
-    TString scopeString(unsigned int depthLimit);
-    TString scopedStruct(const TString &typeName);
-    TString structLookup(const TString &typeName);
-
-    TParseContext &mContext;
-    const ShShaderOutput mOutputType;
-    UnfoldShortCircuit *mUnfoldShortCircuit;
-    bool mInsideFunction;
-
-    // Output streams
-    TInfoSinkBase mHeader;
-    TInfoSinkBase mBody;
-    TInfoSinkBase mFooter;
-
-    typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
-    ReferencedSymbols mReferencedUniforms;
-    ReferencedSymbols mReferencedAttributes;
-    ReferencedSymbols mReferencedVaryings;
-
-    // Parameters determining what goes in the header output
-    bool mUsesTexture2D;
-    bool mUsesTexture2D_bias;
-    bool mUsesTexture2DLod;
-    bool mUsesTexture2DProj;
-    bool mUsesTexture2DProj_bias;
-    bool mUsesTexture2DProjLod;
-    bool mUsesTextureCube;
-    bool mUsesTextureCube_bias;
-    bool mUsesTextureCubeLod;
-    bool mUsesTexture2DLod0;
-    bool mUsesTexture2DLod0_bias;
-    bool mUsesTexture2DProjLod0;
-    bool mUsesTexture2DProjLod0_bias;
-    bool mUsesTextureCubeLod0;
-    bool mUsesTextureCubeLod0_bias;
-    bool mUsesFragColor;
-    bool mUsesFragData;
-    bool mUsesDepthRange;
-    bool mUsesFragCoord;
-    bool mUsesPointCoord;
-    bool mUsesFrontFacing;
-    bool mUsesPointSize;
-    bool mUsesFragDepth;
-    bool mUsesXor;
-    bool mUsesMod1;
-    bool mUsesMod2v;
-    bool mUsesMod2f;
-    bool mUsesMod3v;
-    bool mUsesMod3f;
-    bool mUsesMod4v;
-    bool mUsesMod4f;
-    bool mUsesFaceforward1;
-    bool mUsesFaceforward2;
-    bool mUsesFaceforward3;
-    bool mUsesFaceforward4;
-    bool mUsesEqualMat2;
-    bool mUsesEqualMat3;
-    bool mUsesEqualMat4;
-    bool mUsesEqualVec2;
-    bool mUsesEqualVec3;
-    bool mUsesEqualVec4;
-    bool mUsesEqualIVec2;
-    bool mUsesEqualIVec3;
-    bool mUsesEqualIVec4;
-    bool mUsesEqualBVec2;
-    bool mUsesEqualBVec3;
-    bool mUsesEqualBVec4;
-    bool mUsesAtan2_1;
-    bool mUsesAtan2_2;
-    bool mUsesAtan2_3;
-    bool mUsesAtan2_4;
-
-    int mNumRenderTargets;
-
-    typedef std::set<TString> Constructors;
-    Constructors mConstructors;
-
-    typedef std::set<TString> StructNames;
-    StructNames mStructNames;
-
-    typedef std::list<TString> StructDeclarations;
-    StructDeclarations mStructDeclarations;
-
-    typedef std::vector<int> ScopeBracket;
-    ScopeBracket mScopeBracket;
-    unsigned int mScopeDepth;
-
-    int mUniqueIndex;   // For creating unique names
-
-    bool mContainsLoopDiscontinuity;
-    bool mOutputLod0Function;
-    bool mInsideDiscontinuousLoop;
-
-    TIntermSymbol *mExcessiveLoopIndex;
-
-    int mUniformRegister;
-    int mSamplerRegister;
-
-    TString registerString(TIntermSymbol *operand);
-    int samplerRegister(TIntermSymbol *sampler);
-    int uniformRegister(TIntermSymbol *uniform);
-    void declareUniform(const TType &type, const TString &name, int index);
-    static GLenum glVariableType(const TType &type);
-    static GLenum glVariablePrecision(const TType &type);
-
-    ActiveUniforms mActiveUniforms;
-};
-}
-
-#endif   // COMPILER_OUTPUTHLSL_H_
diff --git a/src/third_party/angle/src/compiler/ParseHelper.cpp b/src/third_party/angle/src/compiler/ParseHelper.cpp
deleted file mode 100644
index a4787a1..0000000
--- a/src/third_party/angle/src/compiler/ParseHelper.cpp
+++ /dev/null
@@ -1,1600 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/ParseHelper.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-
-#include "compiler/glslang.h"
-#include "compiler/preprocessor/SourceLocation.h"
-
-///////////////////////////////////////////////////////////////////////
-//
-// Sub- vector and matrix fields
-//
-////////////////////////////////////////////////////////////////////////
-
-//
-// Look at a '.' field selector string and change it into offsets
-// for a vector.
-//
-bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line)
-{
-    fields.num = (int) compString.size();
-    if (fields.num > 4) {
-        error(line, "illegal vector field selection", compString.c_str());
-        return false;
-    }
-
-    enum {
-        exyzw,
-        ergba,
-        estpq
-    } fieldSet[4];
-
-    for (int i = 0; i < fields.num; ++i) {
-        switch (compString[i])  {
-        case 'x': 
-            fields.offsets[i] = 0;
-            fieldSet[i] = exyzw;
-            break;
-        case 'r': 
-            fields.offsets[i] = 0;
-            fieldSet[i] = ergba;
-            break;
-        case 's':
-            fields.offsets[i] = 0;
-            fieldSet[i] = estpq;
-            break;
-        case 'y': 
-            fields.offsets[i] = 1;
-            fieldSet[i] = exyzw;
-            break;
-        case 'g': 
-            fields.offsets[i] = 1;
-            fieldSet[i] = ergba;
-            break;
-        case 't':
-            fields.offsets[i] = 1;
-            fieldSet[i] = estpq;
-            break;
-        case 'z': 
-            fields.offsets[i] = 2;
-            fieldSet[i] = exyzw;
-            break;
-        case 'b': 
-            fields.offsets[i] = 2;
-            fieldSet[i] = ergba;
-            break;
-        case 'p':
-            fields.offsets[i] = 2;
-            fieldSet[i] = estpq;
-            break;
-        
-        case 'w': 
-            fields.offsets[i] = 3;
-            fieldSet[i] = exyzw;
-            break;
-        case 'a': 
-            fields.offsets[i] = 3;
-            fieldSet[i] = ergba;
-            break;
-        case 'q':
-            fields.offsets[i] = 3;
-            fieldSet[i] = estpq;
-            break;
-        default:
-            error(line, "illegal vector field selection", compString.c_str());
-            return false;
-        }
-    }
-
-    for (int i = 0; i < fields.num; ++i) {
-        if (fields.offsets[i] >= vecSize) {
-            error(line, "vector field selection out of range",  compString.c_str());
-            return false;
-        }
-
-        if (i > 0) {
-            if (fieldSet[i] != fieldSet[i-1]) {
-                error(line, "illegal - vector component fields not from the same set", compString.c_str());
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-
-//
-// Look at a '.' field selector string and change it into offsets
-// for a matrix.
-//
-bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line)
-{
-    fields.wholeRow = false;
-    fields.wholeCol = false;
-    fields.row = -1;
-    fields.col = -1;
-
-    if (compString.size() != 2) {
-        error(line, "illegal length of matrix field selection", compString.c_str());
-        return false;
-    }
-
-    if (compString[0] == '_') {
-        if (compString[1] < '0' || compString[1] > '3') {
-            error(line, "illegal matrix field selection", compString.c_str());
-            return false;
-        }
-        fields.wholeCol = true;
-        fields.col = compString[1] - '0';
-    } else if (compString[1] == '_') {
-        if (compString[0] < '0' || compString[0] > '3') {
-            error(line, "illegal matrix field selection", compString.c_str());
-            return false;
-        }
-        fields.wholeRow = true;
-        fields.row = compString[0] - '0';
-    } else {
-        if (compString[0] < '0' || compString[0] > '3' ||
-            compString[1] < '0' || compString[1] > '3') {
-            error(line, "illegal matrix field selection", compString.c_str());
-            return false;
-        }
-        fields.row = compString[0] - '0';
-        fields.col = compString[1] - '0';
-    }
-
-    if (fields.row >= matSize || fields.col >= matSize) {
-        error(line, "matrix field selection out of range", compString.c_str());
-        return false;
-    }
-
-    return true;
-}
-
-///////////////////////////////////////////////////////////////////////
-//
-// Errors
-//
-////////////////////////////////////////////////////////////////////////
-
-//
-// Track whether errors have occurred.
-//
-void TParseContext::recover()
-{
-}
-
-//
-// Used by flex/bison to output all syntax and parsing errors.
-//
-void TParseContext::error(const TSourceLoc& loc,
-                          const char* reason, const char* token, 
-                          const char* extraInfo)
-{
-    pp::SourceLocation srcLoc;
-    srcLoc.file = loc.first_file;
-    srcLoc.line = loc.first_line;
-    diagnostics.writeInfo(pp::Diagnostics::ERROR,
-                          srcLoc, reason, token, extraInfo);
-
-}
-
-void TParseContext::warning(const TSourceLoc& loc,
-                            const char* reason, const char* token,
-                            const char* extraInfo) {
-    pp::SourceLocation srcLoc;
-    srcLoc.file = loc.first_file;
-    srcLoc.line = loc.first_line;
-    diagnostics.writeInfo(pp::Diagnostics::WARNING,
-                          srcLoc, reason, token, extraInfo);
-}
-
-void TParseContext::trace(const char* str)
-{
-    diagnostics.writeDebug(str);
-}
-
-//
-// Same error message for all places assignments don't work.
-//
-void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right)
-{
-    std::stringstream extraInfoStream;
-    extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
-    std::string extraInfo = extraInfoStream.str();
-    error(line, "", op, extraInfo.c_str());
-}
-
-//
-// Same error message for all places unary operations don't work.
-//
-void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand)
-{
-    std::stringstream extraInfoStream;
-    extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand 
-                    << " (or there is no acceptable conversion)";
-    std::string extraInfo = extraInfoStream.str();
-    error(line, " wrong operand type", op, extraInfo.c_str());
-}
-
-//
-// Same error message for all binary operations don't work.
-//
-void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right)
-{
-    std::stringstream extraInfoStream;
-    extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left 
-                    << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
-    std::string extraInfo = extraInfoStream.str();
-    error(line, " wrong operand types ", op, extraInfo.c_str()); 
-}
-
-bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){
-    if (!checksPrecisionErrors)
-        return false;
-    switch( type ){
-    case EbtFloat:
-        if( precision == EbpUndefined ){
-            error( line, "No precision specified for (float)", "" );
-            return true;
-        }
-        break;
-    case EbtInt:
-        if( precision == EbpUndefined ){
-            error( line, "No precision specified (int)", "" );
-            return true;
-        }
-        break;
-    default:
-        return false;
-    }
-    return false;
-}
-
-//
-// Both test and if necessary, spit out an error, to see if the node is really
-// an l-value that can be operated on this way.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node)
-{
-    TIntermSymbol* symNode = node->getAsSymbolNode();
-    TIntermBinary* binaryNode = node->getAsBinaryNode();
-
-    if (binaryNode) {
-        bool errorReturn;
-
-        switch(binaryNode->getOp()) {
-        case EOpIndexDirect:
-        case EOpIndexIndirect:
-        case EOpIndexDirectStruct:
-            return lValueErrorCheck(line, op, binaryNode->getLeft());
-        case EOpVectorSwizzle:
-            errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
-            if (!errorReturn) {
-                int offset[4] = {0,0,0,0};
-
-                TIntermTyped* rightNode = binaryNode->getRight();
-                TIntermAggregate *aggrNode = rightNode->getAsAggregate();
-                
-                for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 
-                                               p != aggrNode->getSequence().end(); p++) {
-                    int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
-                    offset[value]++;     
-                    if (offset[value] > 1) {
-                        error(line, " l-value of swizzle cannot have duplicate components", op);
-
-                        return true;
-                    }
-                }
-            } 
-
-            return errorReturn;
-        default: 
-            break;
-        }
-        error(line, " l-value required", op);
-
-        return true;
-    }
-
-
-    const char* symbol = 0;
-    if (symNode != 0)
-        symbol = symNode->getSymbol().c_str();
-
-    const char* message = 0;
-    switch (node->getQualifier()) {
-    case EvqConst:          message = "can't modify a const";        break;
-    case EvqConstReadOnly:  message = "can't modify a const";        break;
-    case EvqAttribute:      message = "can't modify an attribute";   break;
-    case EvqUniform:        message = "can't modify a uniform";      break;
-    case EvqVaryingIn:      message = "can't modify a varying";      break;
-    case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
-    case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
-    case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
-    default:
-
-        //
-        // Type that can't be written to?
-        //
-        switch (node->getBasicType()) {
-        case EbtSampler2D:
-        case EbtSamplerCube:
-            message = "can't modify a sampler";
-            break;
-        case EbtVoid:
-            message = "can't modify void";
-            break;
-        default: 
-            break;
-        }
-    }
-
-    if (message == 0 && binaryNode == 0 && symNode == 0) {
-        error(line, " l-value required", op);
-
-        return true;
-    }
-
-
-    //
-    // Everything else is okay, no error.
-    //
-    if (message == 0)
-        return false;
-
-    //
-    // If we get here, we have an error and a message.
-    //
-    if (symNode) {
-        std::stringstream extraInfoStream;
-        extraInfoStream << "\"" << symbol << "\" (" << message << ")";
-        std::string extraInfo = extraInfoStream.str();
-        error(line, " l-value required", op, extraInfo.c_str());
-    }
-    else {
-        std::stringstream extraInfoStream;
-        extraInfoStream << "(" << message << ")";
-        std::string extraInfo = extraInfoStream.str();
-        error(line, " l-value required", op, extraInfo.c_str());
-    }
-
-    return true;
-}
-
-//
-// Both test, and if necessary spit out an error, to see if the node is really
-// a constant.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::constErrorCheck(TIntermTyped* node)
-{
-    if (node->getQualifier() == EvqConst)
-        return false;
-
-    error(node->getLine(), "constant expression required", "");
-
-    return true;
-}
-
-//
-// Both test, and if necessary spit out an error, to see if the node is really
-// an integer.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
-{
-    if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
-        return false;
-
-    error(node->getLine(), "integer expression required", token);
-
-    return true;
-}
-
-//
-// Both test, and if necessary spit out an error, to see if we are currently
-// globally scoped.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token)
-{
-    if (global)
-        return false;
-
-    error(line, "only allowed at global scope", token);
-
-    return true;
-}
-
-//
-// For now, keep it simple:  if it starts "gl_", it's reserved, independent
-// of scope.  Except, if the symbol table is at the built-in push-level,
-// which is when we are parsing built-ins.
-// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
-// webgl shader.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier)
-{
-    static const char* reservedErrMsg = "reserved built-in name";
-    if (!symbolTable.atBuiltInLevel()) {
-        if (identifier.compare(0, 3, "gl_") == 0) {
-            error(line, reservedErrMsg, "gl_");
-            return true;
-        }
-        if (isWebGLBasedSpec(shaderSpec)) {
-            if (identifier.compare(0, 6, "webgl_") == 0) {
-                error(line, reservedErrMsg, "webgl_");
-                return true;
-            }
-            if (identifier.compare(0, 7, "_webgl_") == 0) {
-                error(line, reservedErrMsg, "_webgl_");
-                return true;
-            }
-            if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) {
-                error(line, reservedErrMsg, "css_");
-                return true;
-            }
-        }
-        if (identifier.find("__") != TString::npos) {
-            error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
-            return true;
-        }
-    }
-
-    return false;
-}
-
-//
-// Make sure there is enough data provided to the constructor to build
-// something of the type of the constructor.  Also returns the type of
-// the constructor.
-//
-// Returns true if there was an error in construction.
-//
-bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
-{
-    *type = function.getReturnType();
-
-    bool constructingMatrix = false;
-    switch(op) {
-    case EOpConstructMat2:
-    case EOpConstructMat3:
-    case EOpConstructMat4:
-        constructingMatrix = true;
-        break;
-    default: 
-        break;
-    }
-
-    //
-    // Note: It's okay to have too many components available, but not okay to have unused
-    // arguments.  'full' will go to true when enough args have been seen.  If we loop
-    // again, there is an extra argument, so 'overfull' will become true.
-    //
-
-    size_t size = 0;
-    bool constType = true;
-    bool full = false;
-    bool overFull = false;
-    bool matrixInMatrix = false;
-    bool arrayArg = false;
-    for (size_t i = 0; i < function.getParamCount(); ++i) {
-        const TParameter& param = function.getParam(i);
-        size += param.type->getObjectSize();
-        
-        if (constructingMatrix && param.type->isMatrix())
-            matrixInMatrix = true;
-        if (full)
-            overFull = true;
-        if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
-            full = true;
-        if (param.type->getQualifier() != EvqConst)
-            constType = false;
-        if (param.type->isArray())
-            arrayArg = true;
-    }
-    
-    if (constType)
-        type->setQualifier(EvqConst);
-
-    if (type->isArray() && static_cast<size_t>(type->getArraySize()) != function.getParamCount()) {
-        error(line, "array constructor needs one argument per array element", "constructor");
-        return true;
-    }
-
-    if (arrayArg && op != EOpConstructStruct) {
-        error(line, "constructing from a non-dereferenced array", "constructor");
-        return true;
-    }
-
-    if (matrixInMatrix && !type->isArray()) {
-        if (function.getParamCount() != 1) {
-          error(line, "constructing matrix from matrix can only take one argument", "constructor");
-          return true;
-        }
-    }
-
-    if (overFull) {
-        error(line, "too many arguments", "constructor");
-        return true;
-    }
-    
-    if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
-        error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
-        return true;
-    }
-
-    if (!type->isMatrix() || !matrixInMatrix) {
-        if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
-            (op == EOpConstructStruct && size < type->getObjectSize())) {
-            error(line, "not enough data provided for construction", "constructor");
-            return true;
-        }
-    }
-
-    TIntermTyped *typed = node ? node->getAsTyped() : 0;
-    if (typed == 0) {
-        error(line, "constructor argument does not have a type", "constructor");
-        return true;
-    }
-    if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
-        error(line, "cannot convert a sampler", "constructor");
-        return true;
-    }
-    if (typed->getBasicType() == EbtVoid) {
-        error(line, "cannot convert a void", "constructor");
-        return true;
-    }
-
-    return false;
-}
-
-// This function checks to see if a void variable has been declared and raise an error message for such a case
-//
-// returns true in case of an error
-//
-bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType)
-{
-    if (pubType.type == EbtVoid) {
-        error(line, "illegal use of type 'void'", identifier.c_str());
-        return true;
-    } 
-
-    return false;
-}
-
-// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
-//
-// returns true in case of an error
-//
-bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type)
-{
-    if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
-        error(line, "boolean expression expected", "");
-        return true;
-    } 
-
-    return false;
-}
-
-// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
-//
-// returns true in case of an error
-//
-bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType)
-{
-    if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
-        error(line, "boolean expression expected", "");
-        return true;
-    } 
-
-    return false;
-}
-
-bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason)
-{
-    if (pType.type == EbtStruct) {
-        if (containsSampler(*pType.userDef)) {
-            error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
-        
-            return true;
-        }
-        
-        return false;
-    } else if (IsSampler(pType.type)) {
-        error(line, reason, getBasicString(pType.type));
-
-        return true;
-    }
-
-    return false;
-}
-
-bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType)
-{
-    if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
-        pType.type == EbtStruct) {
-        error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
-        
-        return true;
-    }
-
-    if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
-        return true;
-
-    return false;
-}
-
-bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type)
-{
-    if ((qualifier == EvqOut || qualifier == EvqInOut) && 
-             type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
-        error(line, "samplers cannot be output parameters", type.getBasicString());
-        return true;
-    }
-
-    return false;
-}
-
-bool TParseContext::containsSampler(TType& type)
-{
-    if (IsSampler(type.getBasicType()))
-        return true;
-
-    if (type.getBasicType() == EbtStruct) {
-        const TFieldList& fields = type.getStruct()->fields();
-        for (unsigned int i = 0; i < fields.size(); ++i) {
-            if (containsSampler(*fields[i]->type()))
-                return true;
-        }
-    }
-
-    return false;
-}
-
-//
-// Do size checking for an array type's size.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size)
-{
-    TIntermConstantUnion* constant = expr->getAsConstantUnion();
-    if (constant == 0 || constant->getBasicType() != EbtInt) {
-        error(line, "array size must be a constant integer expression", "");
-        return true;
-    }
-
-    size = constant->getIConst(0);
-
-    if (size <= 0) {
-        error(line, "array size must be a positive integer", "");
-        size = 1;
-        return true;
-    }
-
-    return false;
-}
-
-//
-// See if this qualifier can be an array.
-//
-// Returns true if there is an error.
-//
-bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type)
-{
-    if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
-        error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
-        return true;
-    }
-
-    return false;
-}
-
-//
-// See if this type can be an array.
-//
-// Returns true if there is an error.
-//
-bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type)
-{
-    //
-    // Can the type be an array?
-    //
-    if (type.array) {
-        error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
-        return true;
-    }
-
-    return false;
-}
-
-//
-// Do all the semantic checking for declaring an array, with and 
-// without a size, and make the right changes to the symbol table.
-//
-// size == 0 means no specified size.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable)
-{
-    //
-    // Don't check for reserved word use until after we know it's not in the symbol table,
-    // because reserved arrays can be redeclared.
-    //
-
-    bool builtIn = false; 
-    bool sameScope = false;
-    TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
-    if (symbol == 0 || !sameScope) {
-        if (reservedErrorCheck(line, identifier))
-            return true;
-        
-        variable = new TVariable(&identifier, TType(type));
-
-        if (type.arraySize)
-            variable->getType().setArraySize(type.arraySize);
-
-        if (! symbolTable.insert(*variable)) {
-            delete variable;
-            error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
-            return true;
-        }
-    } else {
-        if (! symbol->isVariable()) {
-            error(line, "variable expected", identifier.c_str());
-            return true;
-        }
-
-        variable = static_cast<TVariable*>(symbol);
-        if (! variable->getType().isArray()) {
-            error(line, "redeclaring non-array as array", identifier.c_str());
-            return true;
-        }
-        if (variable->getType().getArraySize() > 0) {
-            error(line, "redeclaration of array with size", identifier.c_str());
-            return true;
-        }
-        
-        if (! variable->getType().sameElementType(TType(type))) {
-            error(line, "redeclaration of array with a different type", identifier.c_str());
-            return true;
-        }
-
-        if (type.arraySize)
-            variable->getType().setArraySize(type.arraySize);
-    } 
-
-    if (voidErrorCheck(line, identifier, type))
-        return true;
-
-    return false;
-}
-
-//
-// Enforce non-initializer type/qualifier rules.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array)
-{
-    if (type.qualifier == EvqConst)
-    {
-        // Make the qualifier make sense.
-        type.qualifier = EvqTemporary;
-        
-        if (array)
-        {
-            error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
-        }
-        else if (type.isStructureContainingArrays())
-        {
-            error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
-        }
-        else
-        {
-            error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
-//
-// Do semantic checking for a variable declaration that has no initializer,
-// and update the symbol table.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable)
-{
-    if (reservedErrorCheck(line, identifier))
-        recover();
-
-    variable = new TVariable(&identifier, TType(type));
-
-    if (! symbolTable.insert(*variable)) {
-        error(line, "redefinition", variable->getName().c_str());
-        delete variable;
-        variable = 0;
-        return true;
-    }
-
-    if (voidErrorCheck(line, identifier, type))
-        return true;
-
-    return false;
-}
-
-bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
-{    
-    if (qualifier != EvqConst && qualifier != EvqTemporary) {
-        error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
-        return true;
-    }
-    if (qualifier == EvqConst && paramQualifier != EvqIn) {
-        error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
-        return true;
-    }
-
-    if (qualifier == EvqConst)
-        type->setQualifier(EvqConstReadOnly);
-    else
-        type->setQualifier(paramQualifier);
-
-    return false;
-}
-
-bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension)
-{
-    const TExtensionBehavior& extBehavior = extensionBehavior();
-    TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
-    if (iter == extBehavior.end()) {
-        error(line, "extension", extension.c_str(), "is not supported");
-        return true;
-    }
-    // In GLSL ES, an extension's default behavior is "disable".
-    if (iter->second == EBhDisable || iter->second == EBhUndefined) {
-        error(line, "extension", extension.c_str(), "is disabled");
-        return true;
-    }
-    if (iter->second == EBhWarn) {
-        warning(line, "extension", extension.c_str(), "is being used");
-        return false;
-    }
-
-    return false;
-}
-
-bool TParseContext::supportsExtension(const char* extension)
-{
-    const TExtensionBehavior& extbehavior = extensionBehavior();
-    TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
-    return (iter != extbehavior.end());
-}
-
-bool TParseContext::isExtensionEnabled(const char* extension) const
-{
-    const TExtensionBehavior& extbehavior = extensionBehavior();
-    TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
-
-    if (iter == extbehavior.end())
-    {
-        return false;
-    }
-
-    return (iter->second == EBhEnable || iter->second == EBhRequire);
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-//
-// Non-Errors.
-//
-/////////////////////////////////////////////////////////////////////////////////
-
-//
-// Look up a function name in the symbol table, and make sure it is a function.
-//
-// Return the function symbol if found, otherwise 0.
-//
-const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn)
-{
-    // First find by unmangled name to check whether the function name has been
-    // hidden by a variable name or struct typename.
-    // If a function is found, check for one with a matching argument list.
-    const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
-    if (symbol == 0 || symbol->isFunction()) {
-        symbol = symbolTable.find(call->getMangledName(), builtIn);
-    }
-
-    if (symbol == 0) {
-        error(line, "no matching overloaded function found", call->getName().c_str());
-        return 0;
-    }
-
-    if (!symbol->isFunction()) {
-        error(line, "function name expected", call->getName().c_str());
-        return 0;
-    }
-
-    return static_cast<const TFunction*>(symbol);
-}
-
-//
-// Initializers show up in several places in the grammar.  Have one set of
-// code to handle them here.
-//
-bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, 
-                                       TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
-{
-    TType type = TType(pType);
-
-    if (variable == 0) {
-        if (reservedErrorCheck(line, identifier))
-            return true;
-
-        if (voidErrorCheck(line, identifier, pType))
-            return true;
-
-        //
-        // add variable to symbol table
-        //
-        variable = new TVariable(&identifier, type);
-        if (! symbolTable.insert(*variable)) {
-            error(line, "redefinition", variable->getName().c_str());
-            return true;
-            // don't delete variable, it's used by error recovery, and the pool 
-            // pop will take care of the memory
-        }
-    }
-
-    //
-    // identifier must be of type constant, a global, or a temporary
-    //
-    TQualifier qualifier = variable->getType().getQualifier();
-    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
-        error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
-        return true;
-    }
-    //
-    // test for and propagate constant
-    //
-
-    if (qualifier == EvqConst) {
-        if (qualifier != initializer->getType().getQualifier()) {
-            std::stringstream extraInfoStream;
-            extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
-            std::string extraInfo = extraInfoStream.str();
-            error(line, " assigning non-constant to", "=", extraInfo.c_str());
-            variable->getType().setQualifier(EvqTemporary);
-            return true;
-        }
-        if (type != initializer->getType()) {
-            error(line, " non-matching types for const initializer ", 
-                variable->getType().getQualifierString());
-            variable->getType().setQualifier(EvqTemporary);
-            return true;
-        }
-        if (initializer->getAsConstantUnion()) { 
-            variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
-        } else if (initializer->getAsSymbolNode()) {
-            const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
-            const TVariable* tVar = static_cast<const TVariable*>(symbol);
-
-            ConstantUnion* constArray = tVar->getConstPointer();
-            variable->shareConstPointer(constArray);
-        } else {
-            std::stringstream extraInfoStream;
-            extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
-            std::string extraInfo = extraInfoStream.str();
-            error(line, " cannot assign to", "=", extraInfo.c_str());
-            variable->getType().setQualifier(EvqTemporary);
-            return true;
-        }
-    }
- 
-    if (qualifier != EvqConst) {
-        TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
-        intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
-        if (intermNode == 0) {
-            assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
-            return true;
-        }
-    } else 
-        intermNode = 0;
-
-    return false;
-}
-
-bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
-{
-    ASSERT(aggrNode != NULL);
-    if (!aggrNode->isConstructor())
-        return false;
-
-    bool allConstant = true;
-
-    // check if all the child nodes are constants so that they can be inserted into 
-    // the parent node
-    TIntermSequence &sequence = aggrNode->getSequence() ;
-    for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
-        if (!(*p)->getAsTyped()->getAsConstantUnion())
-            return false;
-    }
-
-    return allConstant;
-}
-
-// This function is used to test for the correctness of the parameters passed to various constructor functions
-// and also convert them to the right datatype if it is allowed and required. 
-//
-// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
-//
-TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line)
-{
-    if (node == 0)
-        return 0;
-
-    TIntermAggregate* aggrNode = node->getAsAggregate();
-    
-    TFieldList::const_iterator memberFields;
-    if (op == EOpConstructStruct)
-        memberFields = type->getStruct()->fields().begin();
-    
-    TType elementType = *type;
-    if (type->isArray())
-        elementType.clearArrayness();
-
-    bool singleArg;
-    if (aggrNode) {
-        if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
-            singleArg = true;
-        else
-            singleArg = false;
-    } else
-        singleArg = true;
-
-    TIntermTyped *newNode;
-    if (singleArg) {
-        // If structure constructor or array constructor is being called 
-        // for only one parameter inside the structure, we need to call constructStruct function once.
-        if (type->isArray())
-            newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
-        else if (op == EOpConstructStruct)
-            newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false);
-        else
-            newNode = constructBuiltIn(type, op, node, node->getLine(), false);
-
-        if (newNode && newNode->getAsAggregate()) {
-            TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
-            if (constConstructor)
-                return constConstructor;
-        }
-
-        return newNode;
-    }
-    
-    //
-    // Handle list of arguments.
-    //
-    TIntermSequence &sequenceVector = aggrNode->getSequence() ;    // Stores the information about the parameter to the constructor
-    // if the structure constructor contains more than one parameter, then construct
-    // each parameter
-    
-    int paramCount = 0;  // keeps a track of the constructor parameter number being checked    
-    
-    // for each parameter to the constructor call, check to see if the right type is passed or convert them 
-    // to the right type if possible (and allowed).
-    // for structure constructors, just check if the right type is passed, no conversion is allowed.
-    
-    for (TIntermSequence::iterator p = sequenceVector.begin(); 
-                                   p != sequenceVector.end(); p++, paramCount++) {
-        if (type->isArray())
-            newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
-        else if (op == EOpConstructStruct)
-            newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true);
-        else
-            newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
-        
-        if (newNode) {
-            *p = newNode;
-        }
-    }
-
-    TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
-    TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
-    if (constConstructor)
-        return constConstructor;
-
-    return constructor;
-}
-
-TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
-{
-    bool canBeFolded = areAllChildConst(aggrNode);
-    aggrNode->setType(type);
-    if (canBeFolded) {
-        bool returnVal = false;
-        ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
-        if (aggrNode->getSequence().size() == 1)  {
-            returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type, true);
-        }
-        else {
-            returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type);
-        }
-        if (returnVal)
-            return 0;
-
-        return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
-    }
-
-    return 0;
-}
-
-// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
-// for the parameter to the constructor (passed to this function). Essentially, it converts
-// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 
-// float, then float is converted to int.
-//
-// Returns 0 for an error or the constructed node.
-//
-TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset)
-{
-    TIntermTyped* newNode;
-    TOperator basicOp;
-
-    //
-    // First, convert types as needed.
-    //
-    switch (op) {
-    case EOpConstructVec2:
-    case EOpConstructVec3:
-    case EOpConstructVec4:
-    case EOpConstructMat2:
-    case EOpConstructMat3:
-    case EOpConstructMat4:
-    case EOpConstructFloat:
-        basicOp = EOpConstructFloat;
-        break;
-
-    case EOpConstructIVec2:
-    case EOpConstructIVec3:
-    case EOpConstructIVec4:
-    case EOpConstructInt:
-        basicOp = EOpConstructInt;
-        break;
-
-    case EOpConstructBVec2:
-    case EOpConstructBVec3:
-    case EOpConstructBVec4:
-    case EOpConstructBool:
-        basicOp = EOpConstructBool;
-        break;
-
-    default:
-        error(line, "unsupported construction", "");
-        recover();
-
-        return 0;
-    }
-    newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
-    if (newNode == 0) {
-        error(line, "can't convert", "constructor");
-        return 0;
-    }
-
-    //
-    // Now, if there still isn't an operation to do the construction, and we need one, add one.
-    //
-    
-    // Otherwise, skip out early.
-    if (subset || (newNode != node && newNode->getType() == *type))
-        return newNode;
-
-    // setAggregateOperator will insert a new node for the constructor, as needed.
-    return intermediate.setAggregateOperator(newNode, op, line);
-}
-
-// This function tests for the type of the parameters to the structures constructors. Raises
-// an error message if the expected type does not match the parameter passed to the constructor.
-//
-// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
-//
-TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset)
-{
-    if (*type == node->getAsTyped()->getType()) {
-        if (subset)
-            return node->getAsTyped();
-        else
-            return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
-    } else {
-        std::stringstream extraInfoStream;
-        extraInfoStream << "cannot convert parameter " << paramCount 
-                        << " from '" << node->getAsTyped()->getType().getBasicString()
-                        << "' to '" << type->getBasicString() << "'";
-        std::string extraInfo = extraInfoStream.str();
-        error(line, "", "constructor", extraInfo.c_str());
-        recover();
-    }
-
-    return 0;
-}
-
-//
-// This function returns the tree representation for the vector field(s) being accessed from contant vector.
-// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
-// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
-// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
-// a constant matrix.
-//
-TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line)
-{
-    TIntermTyped* typedNode;
-    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
-
-    ConstantUnion *unionArray;
-    if (tempConstantNode) {
-        unionArray = tempConstantNode->getUnionArrayPointer();
-
-        if (!unionArray) {
-            return node;
-        }
-    } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
-        error(line, "Cannot offset into the vector", "Error");
-        recover();
-
-        return 0;
-    }
-
-    ConstantUnion* constArray = new ConstantUnion[fields.num];
-
-    for (int i = 0; i < fields.num; i++) {
-        if (fields.offsets[i] >= node->getType().getNominalSize()) {
-            std::stringstream extraInfoStream;
-            extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
-            std::string extraInfo = extraInfoStream.str();
-            error(line, "", "[", extraInfo.c_str());
-            recover();
-            fields.offsets[i] = 0;
-        }
-        
-        constArray[i] = unionArray[fields.offsets[i]];
-
-    } 
-    typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
-    return typedNode;
-}
-
-//
-// This function returns the column being accessed from a constant matrix. The values are retrieved from
-// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 
-// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 
-// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
-//
-TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line)
-{
-    TIntermTyped* typedNode;
-    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
-
-    if (index >= node->getType().getNominalSize()) {
-        std::stringstream extraInfoStream;
-        extraInfoStream << "matrix field selection out of range '" << index << "'";
-        std::string extraInfo = extraInfoStream.str();
-        error(line, "", "[", extraInfo.c_str());
-        recover();
-        index = 0;
-    }
-
-    if (tempConstantNode) {
-         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
-         int size = tempConstantNode->getType().getNominalSize();
-         typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
-    } else {
-        error(line, "Cannot offset into the matrix", "Error");
-        recover();
-
-        return 0;
-    }
-
-    return typedNode;
-}
-
-
-//
-// This function returns an element of an array accessed from a constant array. The values are retrieved from
-// the symbol table and parse-tree is built for the type of the element. The input 
-// to the function could either be a symbol node (a[0] where a is a constant array)that represents a 
-// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
-//
-TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line)
-{
-    TIntermTyped* typedNode;
-    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
-    TType arrayElementType = node->getType();
-    arrayElementType.clearArrayness();
-
-    if (index >= node->getType().getArraySize()) {
-        std::stringstream extraInfoStream;
-        extraInfoStream << "array field selection out of range '" << index << "'";
-        std::string extraInfo = extraInfoStream.str();
-        error(line, "", "[", extraInfo.c_str());
-        recover();
-        index = 0;
-    }
-
-    if (tempConstantNode) {
-         size_t arrayElementSize = arrayElementType.getObjectSize();
-         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
-         typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
-    } else {
-        error(line, "Cannot offset into the array", "Error");
-        recover();
-
-        return 0;
-    }
-
-    return typedNode;
-}
-
-
-//
-// This function returns the value of a particular field inside a constant structure from the symbol table. 
-// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
-// function and returns the parse-tree with the values of the embedded/nested struct.
-//
-TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line)
-{
-    const TFieldList& fields = node->getType().getStruct()->fields();
-
-    size_t instanceSize = 0;
-    for (size_t index = 0; index < fields.size(); ++index) {
-        if (fields[index]->name() == identifier) {
-            break;
-        } else {
-            instanceSize += fields[index]->type()->getObjectSize();
-        }
-    }
-
-    TIntermTyped* typedNode = 0;
-    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
-    if (tempConstantNode) {
-         ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
-
-         typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
-    } else {
-        error(line, "Cannot offset into the structure", "Error");
-        recover();
-
-        return 0;
-    }
-
-    return typedNode;
-}
-
-bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier)
-{
-    ++structNestingLevel;
-
-    // Embedded structure definitions are not supported per GLSL ES spec.
-    // They aren't allowed in GLSL either, but we need to detect this here
-    // so we don't rely on the GLSL compiler to catch it.
-    if (structNestingLevel > 1) {
-        error(line, "", "Embedded struct definitions are not allowed");
-        return true;
-    }
-
-    return false;
-}
-
-void TParseContext::exitStructDeclaration()
-{
-    --structNestingLevel;
-}
-
-namespace {
-
-const int kWebGLMaxStructNesting = 4;
-
-}  // namespace
-
-bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
-{
-    if (!isWebGLBasedSpec(shaderSpec)) {
-        return false;
-    }
-
-    if (field.type()->getBasicType() != EbtStruct) {
-        return false;
-    }
-
-    // We're already inside a structure definition at this point, so add
-    // one to the field's struct nesting.
-    if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
-        std::stringstream extraInfoStream;
-        extraInfoStream << "Reference of struct type " << field.name()
-                        << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
-        std::string extraInfo = extraInfoStream.str();
-        error(line, "", "", extraInfo.c_str());
-        return true;
-    }
-
-    return false;
-}
-
-//
-// Parse an array index expression
-//
-TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression)
-{
-    TIntermTyped *indexedExpression = NULL;
-
-    if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
-    {
-        if (baseExpression->getAsSymbolNode())
-        {
-            error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
-        }
-        else
-        {
-            error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
-        }
-        recover();
-    }
-
-    if (indexExpression->getQualifier() == EvqConst)
-    {
-        int index = indexExpression->getAsConstantUnion()->getIConst(0);
-        if (index < 0)
-        {
-            std::stringstream infoStream;
-            infoStream << index;
-            std::string info = infoStream.str();
-            error(location, "negative index", info.c_str());
-            recover();
-            index = 0;
-        }
-        if (baseExpression->getType().getQualifier() == EvqConst)
-        {
-            if (baseExpression->isArray())
-            {
-                // constant folding for arrays
-                indexedExpression = addConstArrayNode(index, baseExpression, location);
-            }
-            else if (baseExpression->isVector())
-            {
-                // constant folding for vectors
-                TVectorFields fields;
-                fields.num = 1;
-                fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
-                indexedExpression = addConstVectorNode(fields, baseExpression, location);
-            }
-            else if (baseExpression->isMatrix())
-            {
-                // constant folding for matrices
-                indexedExpression = addConstMatrixNode(index, baseExpression, location);
-            }
-        }
-        else
-        {
-            if (baseExpression->isArray())
-            {
-                if (index >= baseExpression->getType().getArraySize())
-                {
-                    std::stringstream extraInfoStream;
-                    extraInfoStream << "array index out of range '" << index << "'";
-                    std::string extraInfo = extraInfoStream.str();
-                    error(location, "", "[", extraInfo.c_str());
-                    recover();
-                    index = baseExpression->getType().getArraySize() - 1;
-                }
-                else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
-                {
-                    error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
-                    recover();
-                    index = 0;
-                }
-            }
-            else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
-            {
-                std::stringstream extraInfoStream;
-                extraInfoStream << "field selection out of range '" << index << "'";
-                std::string extraInfo = extraInfoStream.str();
-                error(location, "", "[", extraInfo.c_str());
-                recover();
-                index = baseExpression->getType().getNominalSize() - 1;
-            }
-
-            indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
-            indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
-        }
-    }
-    else
-    {
-        indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
-    }
-
-    if (indexedExpression == 0)
-    {
-        ConstantUnion *unionArray = new ConstantUnion[1];
-        unionArray->setFConst(0.0f);
-        indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
-    }
-    else if (baseExpression->isArray())
-    {
-        const TType &baseType = baseExpression->getType();
-        if (baseType.getStruct())
-        {
-            TType copyOfType(baseType.getStruct());
-            indexedExpression->setType(copyOfType);
-        }
-        else
-        {
-            indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix()));
-        }
-
-        if (baseExpression->getType().getQualifier() == EvqConst)
-        {
-            indexedExpression->getTypePointer()->setQualifier(EvqConst);
-        }
-    }
-    else if (baseExpression->isMatrix())
-    {
-        TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
-        indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize()));
-    }
-    else if (baseExpression->isVector())
-    {
-        TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
-        indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
-    }
-    else
-    {
-        indexedExpression->setType(baseExpression->getType());
-    }
-
-    return indexedExpression;
-}
-
-//
-// Parse an array of strings using yyparse.
-//
-// Returns 0 for success.
-//
-int PaParseStrings(size_t count, const char* const string[], const int length[],
-                   TParseContext* context) {
-    if ((count == 0) || (string == NULL))
-        return 1;
-
-    if (glslang_initialize(context))
-        return 1;
-
-    int error = glslang_scan(count, string, length, context);
-    if (!error)
-        error = glslang_parse(context);
-
-    glslang_finalize(context);
-
-    return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
-}
-
-
-
diff --git a/src/third_party/angle/src/compiler/ParseHelper.h b/src/third_party/angle/src/compiler/ParseHelper.h
deleted file mode 100644
index c2b3c3f..0000000
--- a/src/third_party/angle/src/compiler/ParseHelper.h
+++ /dev/null
@@ -1,134 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-#ifndef _PARSER_HELPER_INCLUDED_
-#define _PARSER_HELPER_INCLUDED_
-
-#include "compiler/Diagnostics.h"
-#include "compiler/DirectiveHandler.h"
-#include "compiler/localintermediate.h"
-#include "compiler/preprocessor/Preprocessor.h"
-#include "compiler/ShHandle.h"
-#include "compiler/SymbolTable.h"
-
-struct TMatrixFields {
-    bool wholeRow;
-    bool wholeCol;
-    int row;
-    int col;
-};
-
-//
-// The following are extra variables needed during parsing, grouped together so
-// they can be passed to the parser without needing a global.
-//
-struct TParseContext {
-    TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) :
-            intermediate(interm),
-            symbolTable(symt),
-            shaderType(type),
-            shaderSpec(spec),
-            compileOptions(options),
-            sourcePath(sourcePath),
-            treeRoot(0),
-            loopNestingLevel(0),
-            structNestingLevel(0),
-            currentFunctionType(NULL),
-            functionReturnsValue(false),
-            checksPrecisionErrors(checksPrecErrors),
-            diagnostics(is),
-            directiveHandler(ext, diagnostics),
-            preprocessor(&diagnostics, &directiveHandler),
-            scanner(NULL) {  }
-    TIntermediate& intermediate; // to hold and build a parse tree
-    TSymbolTable& symbolTable;   // symbol table that goes with the language currently being parsed
-    ShShaderType shaderType;              // vertex or fragment language (future: pack or unpack)
-    ShShaderSpec shaderSpec;              // The language specification compiler conforms to - GLES2 or WebGL.
-    int compileOptions;
-    const char* sourcePath;      // Path of source file or NULL.
-    TIntermNode* treeRoot;       // root of parse tree being created
-    int loopNestingLevel;        // 0 if outside all loops
-    int structNestingLevel;      // incremented while parsing a struct declaration
-    const TType* currentFunctionType;  // the return type of the function that's currently being parsed
-    bool functionReturnsValue;   // true if a non-void function has a return
-    bool checksPrecisionErrors;  // true if an error will be generated when a variable is declared without precision, explicit or implicit.
-    bool fragmentPrecisionHigh;  // true if highp precision is supported in the fragment language.
-    TString HashErrMsg;
-    TDiagnostics diagnostics;
-    TDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor;
-    void* scanner;
-
-    int numErrors() const { return diagnostics.numErrors(); }
-    TInfoSink& infoSink() { return diagnostics.infoSink(); }
-    void error(const TSourceLoc& loc, const char *reason, const char* token,
-               const char* extraInfo="");
-    void warning(const TSourceLoc& loc, const char* reason, const char* token,
-                 const char* extraInfo="");
-    void trace(const char* str);
-    void recover();
-
-    bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line);
-    bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line);
-
-    bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier);
-    void assignError(const TSourceLoc& line, const char* op, TString left, TString right);
-    void unaryOpError(const TSourceLoc& line, const char* op, TString operand);
-    void binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right);
-    bool precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type);
-    bool lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped*);
-    bool constErrorCheck(TIntermTyped* node);
-    bool integerErrorCheck(TIntermTyped* node, const char* token);
-    bool globalErrorCheck(const TSourceLoc& line, bool global, const char* token);
-    bool constructorErrorCheck(const TSourceLoc& line, TIntermNode*, TFunction&, TOperator, TType*);
-    bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size);
-    bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type);
-    bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type);
-    bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable);
-    bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&);
-    bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*);
-    bool boolErrorCheck(const TSourceLoc&, const TPublicType&);
-    bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason);
-    bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType);
-    bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type);
-    bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array);
-    bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable);
-    bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
-    bool extensionErrorCheck(const TSourceLoc& line, const TString&);
-
-    const TPragma& pragma() const { return directiveHandler.pragma(); }
-    const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
-    bool supportsExtension(const char* extension);
-    bool isExtensionEnabled(const char* extension) const;
-
-    bool containsSampler(TType& type);
-    bool areAllChildConst(TIntermAggregate* aggrNode);
-    const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0);
-    bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
-                            TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
-
-    TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
-    TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
-    TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset);
-    TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset);
-    TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
-    TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&);
-    TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line);
-    TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&);
-    TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
-
-    // Performs an error check for embedded struct declarations.
-    // Returns true if an error was raised due to the declaration of
-    // this struct.
-    bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier);
-    void exitStructDeclaration();
-
-    bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
-};
-
-int PaParseStrings(size_t count, const char* const string[], const int length[],
-                   TParseContext* context);
-
-#endif // _PARSER_HELPER_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/PoolAlloc.cpp b/src/third_party/angle/src/compiler/PoolAlloc.cpp
deleted file mode 100644
index 3f0f5a6..0000000
--- a/src/third_party/angle/src/compiler/PoolAlloc.cpp
+++ /dev/null
@@ -1,317 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/PoolAlloc.h"
-
-#ifndef _MSC_VER
-#include <stdint.h>
-#endif
-#include <stdio.h>
-
-#include "common/angleutils.h"
-#include "compiler/InitializeGlobals.h"
-#include "compiler/osinclude.h"
-
-OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
-
-void InitializeGlobalPools()
-{
-    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
-    if (globalPools)
-        return;
-
-    TThreadGlobalPools* threadData = new TThreadGlobalPools();
-    threadData->globalPoolAllocator = 0;
-
-    OS_SetTLSValue(PoolIndex, threadData);
-}
-
-void FreeGlobalPools()
-{
-    // Release the allocated memory for this thread.
-    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
-    if (!globalPools)
-        return;
- 
-    delete globalPools;
-}
-
-bool InitializePoolIndex()
-{
-    // Allocate a TLS index.
-    if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
-        return false;
-
-    return true;
-}
-
-void FreePoolIndex()
-{
-    // Release the TLS index.
-    OS_FreeTLSIndex(PoolIndex);
-}
-
-TPoolAllocator& GetGlobalPoolAllocator()
-{
-    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
-
-    return *threadData->globalPoolAllocator;
-}
-
-void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
-{
-    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
-
-    threadData->globalPoolAllocator = poolAllocator;
-}
-
-//
-// Implement the functionality of the TPoolAllocator class, which
-// is documented in PoolAlloc.h.
-//
-TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : 
-    pageSize(growthIncrement),
-    alignment(allocationAlignment),
-    freeList(0),
-    inUseList(0),
-    numCalls(0),
-    totalBytes(0)
-{
-    //
-    // Don't allow page sizes we know are smaller than all common
-    // OS page sizes.
-    //
-    if (pageSize < 4*1024)
-        pageSize = 4*1024;
-
-    //
-    // A large currentPageOffset indicates a new page needs to
-    // be obtained to allocate memory.
-    //
-    currentPageOffset = pageSize;
-
-    //
-    // Adjust alignment to be at least pointer aligned and
-    // power of 2.
-    //
-    size_t minAlign = sizeof(void*);
-    alignment &= ~(minAlign - 1);
-    if (alignment < minAlign)
-        alignment = minAlign;
-    size_t a = 1;
-    while (a < alignment)
-        a <<= 1;
-    alignment = a;
-    alignmentMask = a - 1;
-
-    //
-    // Align header skip
-    //
-    headerSkip = minAlign;
-    if (headerSkip < sizeof(tHeader)) {
-        headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
-    }
-}
-
-TPoolAllocator::~TPoolAllocator()
-{
-    while (inUseList) {
-        tHeader* next = inUseList->nextPage;
-        inUseList->~tHeader();
-        delete [] reinterpret_cast<char*>(inUseList);
-        inUseList = next;
-    }
-
-    // We should not check the guard blocks
-    // here, because we did it already when the block was
-    // placed into the free list.
-    //
-    while (freeList) {
-        tHeader* next = freeList->nextPage;
-        delete [] reinterpret_cast<char*>(freeList);
-        freeList = next;
-    }
-}
-
-// Support MSVC++ 6.0
-const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
-const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
-const unsigned char TAllocation::userDataFill       = 0xcd;
-
-#ifdef GUARD_BLOCKS
-    const size_t TAllocation::guardBlockSize = 16;
-#else
-    const size_t TAllocation::guardBlockSize = 0;
-#endif
-
-//
-// Check a single guard block for damage
-//
-void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
-{
-#ifdef GUARD_BLOCKS
-    for (size_t x = 0; x < guardBlockSize; x++) {
-        if (blockMem[x] != val) {
-            char assertMsg[80];
-
-            // We don't print the assert message.  It's here just to be helpful.
-#if defined(_MSC_VER)
-            snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n",
-                    locText, size, data());
-#else
-            snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n",
-                    locText, size, data());
-#endif
-            assert(0 && "PoolAlloc: Damage in guard block");
-        }
-    }
-#endif
-}
-
-
-void TPoolAllocator::push()
-{
-    tAllocState state = { currentPageOffset, inUseList };
-
-    stack.push_back(state);
-        
-    //
-    // Indicate there is no current page to allocate from.
-    //
-    currentPageOffset = pageSize;
-}
-
-//
-// Do a mass-deallocation of all the individual allocations
-// that have occurred since the last push(), or since the
-// last pop(), or since the object's creation.
-//
-// The deallocated pages are saved for future allocations.
-//
-void TPoolAllocator::pop()
-{
-    if (stack.size() < 1)
-        return;
-
-    tHeader* page = stack.back().page;
-    currentPageOffset = stack.back().offset;
-
-    while (inUseList != page) {
-        // invoke destructor to free allocation list
-        inUseList->~tHeader();
-        
-        tHeader* nextInUse = inUseList->nextPage;
-        if (inUseList->pageCount > 1)
-            delete [] reinterpret_cast<char*>(inUseList);
-        else {
-            inUseList->nextPage = freeList;
-            freeList = inUseList;
-        }
-        inUseList = nextInUse;
-    }
-
-    stack.pop_back();
-}
-
-//
-// Do a mass-deallocation of all the individual allocations
-// that have occurred.
-//
-void TPoolAllocator::popAll()
-{
-    while (stack.size() > 0)
-        pop();
-}
-
-void* TPoolAllocator::allocate(size_t numBytes)
-{
-    //
-    // Just keep some interesting statistics.
-    //
-    ++numCalls;
-    totalBytes += numBytes;
-
-    // If we are using guard blocks, all allocations are bracketed by
-    // them: [guardblock][allocation][guardblock].  numBytes is how
-    // much memory the caller asked for.  allocationSize is the total
-    // size including guard blocks.  In release build,
-    // guardBlockSize=0 and this all gets optimized away.
-    size_t allocationSize = TAllocation::allocationSize(numBytes);
-    // Detect integer overflow.
-    if (allocationSize < numBytes)
-        return 0;
-
-    //
-    // Do the allocation, most likely case first, for efficiency.
-    // This step could be moved to be inline sometime.
-    //
-    if (allocationSize <= pageSize - currentPageOffset) {
-        //
-        // Safe to allocate from currentPageOffset.
-        //
-        unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
-        currentPageOffset += allocationSize;
-        currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
-
-        return initializeAllocation(inUseList, memory, numBytes);
-    }
-
-    if (allocationSize > pageSize - headerSkip) {
-        //
-        // Do a multi-page allocation.  Don't mix these with the others.
-        // The OS is efficient and allocating and free-ing multiple pages.
-        //
-        size_t numBytesToAlloc = allocationSize + headerSkip;
-        // Detect integer overflow.
-        if (numBytesToAlloc < allocationSize)
-            return 0;
-
-        tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
-        if (memory == 0)
-            return 0;
-
-        // Use placement-new to initialize header
-        new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
-        inUseList = memory;
-
-        currentPageOffset = pageSize;  // make next allocation come from a new page
-
-        // No guard blocks for multi-page allocations (yet)
-        return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
-    }
-
-    //
-    // Need a simple page to allocate from.
-    //
-    tHeader* memory;
-    if (freeList) {
-        memory = freeList;
-        freeList = freeList->nextPage;
-    } else {
-        memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
-        if (memory == 0)
-            return 0;
-    }
-
-    // Use placement-new to initialize header
-    new(memory) tHeader(inUseList, 1);
-    inUseList = memory;
-    
-    unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
-    currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
-
-    return initializeAllocation(inUseList, ret, numBytes);
-}
-
-
-//
-// Check all allocations in a list for damage by calling check on each.
-//
-void TAllocation::checkAllocList() const
-{
-    for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
-        alloc->check();
-}
diff --git a/src/third_party/angle/src/compiler/PoolAlloc.h b/src/third_party/angle/src/compiler/PoolAlloc.h
deleted file mode 100644
index a8a59c6..0000000
--- a/src/third_party/angle/src/compiler/PoolAlloc.h
+++ /dev/null
@@ -1,306 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _POOLALLOC_INCLUDED_
-#define _POOLALLOC_INCLUDED_
-
-#ifdef _DEBUG
-#define GUARD_BLOCKS  // define to enable guard block sanity checking
-#endif
-
-//
-// This header defines an allocator that can be used to efficiently
-// allocate a large number of small requests for heap memory, with the 
-// intention that they are not individually deallocated, but rather 
-// collectively deallocated at one time.
-//
-// This simultaneously
-//
-// * Makes each individual allocation much more efficient; the
-//     typical allocation is trivial.
-// * Completely avoids the cost of doing individual deallocation.
-// * Saves the trouble of tracking down and plugging a large class of leaks.
-//
-// Individual classes can use this allocator by supplying their own
-// new and delete methods.
-//
-// STL containers can use this allocator by using the pool_allocator
-// class as the allocator (second) template argument.
-//
-
-#include <stddef.h>
-#include <string.h>
-#include <vector>
-
-// If we are using guard blocks, we must track each indivual
-// allocation.  If we aren't using guard blocks, these
-// never get instantiated, so won't have any impact.
-// 
-
-class TAllocation {
-public:
-    TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
-        size(size), mem(mem), prevAlloc(prev) {
-        // Allocations are bracketed:
-        //    [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
-        // This would be cleaner with if (guardBlockSize)..., but that
-        // makes the compiler print warnings about 0 length memsets,
-        // even with the if() protecting them.
-#ifdef GUARD_BLOCKS
-        memset(preGuard(), guardBlockBeginVal, guardBlockSize);
-        memset(data(),      userDataFill,       size);
-        memset(postGuard(), guardBlockEndVal,   guardBlockSize);
-#endif
-    }
-
-    void check() const {
-        checkGuardBlock(preGuard(),  guardBlockBeginVal, "before");
-        checkGuardBlock(postGuard(), guardBlockEndVal,   "after");
-    }
-
-    void checkAllocList() const;
-
-    // Return total size needed to accomodate user buffer of 'size',
-    // plus our tracking data.
-    inline static size_t allocationSize(size_t size) {
-        return size + 2 * guardBlockSize + headerSize();
-    }
-
-    // Offset from surrounding buffer to get to user data buffer.
-    inline static unsigned char* offsetAllocation(unsigned char* m) {
-        return m + guardBlockSize + headerSize();
-    }
-
-private:
-    void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const;
-
-    // Find offsets to pre and post guard blocks, and user data buffer
-    unsigned char* preGuard()  const { return mem + headerSize(); }
-    unsigned char* data()      const { return preGuard() + guardBlockSize; }
-    unsigned char* postGuard() const { return data() + size; }
-
-    size_t size;                  // size of the user data area
-    unsigned char* mem;           // beginning of our allocation (pts to header)
-    TAllocation* prevAlloc;       // prior allocation in the chain
-
-    // Support MSVC++ 6.0
-    const static unsigned char guardBlockBeginVal;
-    const static unsigned char guardBlockEndVal;
-    const static unsigned char userDataFill;
-
-    const static size_t guardBlockSize;
-#ifdef GUARD_BLOCKS
-    inline static size_t headerSize() { return sizeof(TAllocation); }
-#else
-    inline static size_t headerSize() { return 0; }
-#endif
-};
-
-//
-// There are several stacks.  One is to track the pushing and popping
-// of the user, and not yet implemented.  The others are simply a 
-// repositories of free pages or used pages.
-//
-// Page stacks are linked together with a simple header at the beginning
-// of each allocation obtained from the underlying OS.  Multi-page allocations
-// are returned to the OS.  Individual page allocations are kept for future
-// re-use.
-//
-// The "page size" used is not, nor must it match, the underlying OS
-// page size.  But, having it be about that size or equal to a set of 
-// pages is likely most optimal.
-//
-class TPoolAllocator {
-public:
-    TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16);
-
-    //
-    // Don't call the destructor just to free up the memory, call pop()
-    //
-    ~TPoolAllocator();
-
-    //
-    // Call push() to establish a new place to pop memory too.  Does not
-    // have to be called to get things started.
-    //
-    void push();
-
-    //
-    // Call pop() to free all memory allocated since the last call to push(),
-    // or if no last call to push, frees all memory since first allocation.
-    //
-    void pop();
-
-    //
-    // Call popAll() to free all memory allocated.
-    //
-    void popAll();
-
-    //
-    // Call allocate() to actually acquire memory.  Returns 0 if no memory
-    // available, otherwise a properly aligned pointer to 'numBytes' of memory.
-    //
-    void* allocate(size_t numBytes);
-
-    //
-    // There is no deallocate.  The point of this class is that
-    // deallocation can be skipped by the user of it, as the model
-    // of use is to simultaneously deallocate everything at once
-    // by calling pop(), and to not have to solve memory leak problems.
-    //
-
-protected:
-    friend struct tHeader;
-    
-    struct tHeader {
-        tHeader(tHeader* nextPage, size_t pageCount) :
-            nextPage(nextPage),
-            pageCount(pageCount)
-#ifdef GUARD_BLOCKS
-          , lastAllocation(0)
-#endif
-            { }
-
-        ~tHeader() {
-#ifdef GUARD_BLOCKS
-            if (lastAllocation)
-                lastAllocation->checkAllocList();
-#endif
-        }
-
-        tHeader* nextPage;
-        size_t pageCount;
-#ifdef GUARD_BLOCKS
-        TAllocation* lastAllocation;
-#endif
-    };
-
-    struct tAllocState {
-        size_t offset;
-        tHeader* page;
-    };
-    typedef std::vector<tAllocState> tAllocStack;
-
-    // Track allocations if and only if we're using guard blocks
-    void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
-#ifdef GUARD_BLOCKS
-        new(memory) TAllocation(numBytes, memory, block->lastAllocation);
-        block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
-#endif
-        // This is optimized entirely away if GUARD_BLOCKS is not defined.
-        return TAllocation::offsetAllocation(memory);
-    }
-
-    size_t pageSize;        // granularity of allocation from the OS
-    size_t alignment;       // all returned allocations will be aligned at 
-                            // this granularity, which will be a power of 2
-    size_t alignmentMask;
-    size_t headerSkip;      // amount of memory to skip to make room for the
-                            //      header (basically, size of header, rounded
-                            //      up to make it aligned
-    size_t currentPageOffset;  // next offset in top of inUseList to allocate from
-    tHeader* freeList;      // list of popped memory
-    tHeader* inUseList;     // list of all memory currently being used
-    tAllocStack stack;      // stack of where to allocate from, to partition pool
-
-    int numCalls;           // just an interesting statistic
-    size_t totalBytes;      // just an interesting statistic
-private:
-    TPoolAllocator& operator=(const TPoolAllocator&);  // dont allow assignment operator
-    TPoolAllocator(const TPoolAllocator&);  // dont allow default copy constructor
-};
-
-
-//
-// There could potentially be many pools with pops happening at
-// different times.  But a simple use is to have a global pop
-// with everyone using the same global allocator.
-//
-extern TPoolAllocator& GetGlobalPoolAllocator();
-extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
-#define GlobalPoolAllocator GetGlobalPoolAllocator()
-
-struct TThreadGlobalPools
-{
-    TPoolAllocator* globalPoolAllocator;
-};
-
-//
-// This STL compatible allocator is intended to be used as the allocator
-// parameter to templatized STL containers, like vector and map.
-//
-// It will use the pools for allocation, and not
-// do any deallocation, but will still do destruction.
-//
-template<class T>
-class pool_allocator {
-public:
-    typedef size_t size_type;
-    typedef ptrdiff_t difference_type;
-    typedef T* pointer;
-    typedef const T* const_pointer;
-    typedef T& reference;
-    typedef const T& const_reference;
-    typedef T value_type;
-
-    template<class Other> 
-    struct rebind {
-        typedef pool_allocator<Other> other;
-    };
-    pointer address(reference x) const { return &x; }
-    const_pointer address(const_reference x) const { return &x; }
-
-    pool_allocator() : allocator(&GlobalPoolAllocator) { }
-    pool_allocator(TPoolAllocator& a) : allocator(&a) { }
-    pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
-
-    template <class Other>
-    pool_allocator<T>& operator=(const pool_allocator<Other>& p) {
-      allocator = p.allocator;
-      return *this;
-    }
-
-    template<class Other>
-    pool_allocator(const pool_allocator<Other>& p) : allocator(&p.getAllocator()) { }
-
-#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR)
-    // libCStd on some platforms have a different allocate/deallocate interface.
-    // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be
-    // allocated, not the number of elements.
-    void* allocate(size_type n) { 
-        return getAllocator().allocate(n);
-    }
-    void* allocate(size_type n, const void*) {
-        return getAllocator().allocate(n);
-    }
-    void deallocate(void*, size_type) {}
-#else
-    pointer allocate(size_type n) { 
-        return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
-    }
-    pointer allocate(size_type n, const void*) { 
-        return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
-    }
-    void deallocate(pointer, size_type) {}
-#endif  // _RWSTD_ALLOCATOR
-
-    void construct(pointer p, const T& val) { new ((void *)p) T(val); }
-    void destroy(pointer p) { p->T::~T(); }
-
-    bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); }
-    bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); }
-
-    size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
-    size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
-
-    void setAllocator(TPoolAllocator* a) { allocator = a; }
-    TPoolAllocator& getAllocator() const { return *allocator; }
-
-protected:
-    TPoolAllocator* allocator;
-};
-
-#endif // _POOLALLOC_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/Pragma.h b/src/third_party/angle/src/compiler/Pragma.h
deleted file mode 100644
index 2f74412..0000000
--- a/src/third_party/angle/src/compiler/Pragma.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_PRAGMA_H_
-#define COMPILER_PRAGMA_H_
-
-struct TPragma {
-    // By default optimization is turned on and debug is turned off.
-    TPragma() : optimize(true), debug(false) { }
-    TPragma(bool o, bool d) : optimize(o), debug(d) { }
-
-    bool optimize;
-    bool debug;
-};
-
-#endif // COMPILER_PRAGMA_H_
diff --git a/src/third_party/angle/src/compiler/QualifierAlive.cpp b/src/third_party/angle/src/compiler/QualifierAlive.cpp
deleted file mode 100644
index 92a6874..0000000
--- a/src/third_party/angle/src/compiler/QualifierAlive.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/intermediate.h"
-
-class TAliveTraverser : public TIntermTraverser {
-public:
-    TAliveTraverser(TQualifier q) : TIntermTraverser(true, false, false, true), found(false), qualifier(q)
-    {
-    }
-
-	bool wasFound() { return found; }
-
-protected:
-    bool found;
-    TQualifier qualifier;
-
-    void visitSymbol(TIntermSymbol*);
-    bool visitSelection(Visit, TIntermSelection*);
-};
-
-//
-// Report whether or not a variable of the given qualifier type
-// is guaranteed written.  Not always possible to determine if
-// it is written conditionally.
-//
-// ?? It does not do this well yet, this is just a place holder
-// that simply determines if it was reference at all, anywhere.
-//
-bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
-{
-    TAliveTraverser it(qualifier);
-
-    if (node)
-        node->traverse(&it);
-
-    return it.wasFound();
-}
-
-void TAliveTraverser::visitSymbol(TIntermSymbol* node)
-{
-    //
-    // If it's what we're looking for, record it.
-    //
-    if (node->getQualifier() == qualifier)
-        found = true;
-}
-
-bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node)
-{
-    if (wasFound())
-        return false;
-
-    return true;
-}
diff --git a/src/third_party/angle/src/compiler/QualifierAlive.h b/src/third_party/angle/src/compiler/QualifierAlive.h
deleted file mode 100644
index 872a06f..0000000
--- a/src/third_party/angle/src/compiler/QualifierAlive.h
+++ /dev/null
@@ -1,7 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-bool QualifierWritten(TIntermNode* root, TQualifier);
diff --git a/src/third_party/angle/src/compiler/RemoveTree.cpp b/src/third_party/angle/src/compiler/RemoveTree.cpp
deleted file mode 100644
index a4b8c1e..0000000
--- a/src/third_party/angle/src/compiler/RemoveTree.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/intermediate.h"
-#include "compiler/RemoveTree.h"
-
-//
-// Code to recursively delete the intermediate tree.
-//
-
-class RemoveTree : public TIntermTraverser
-{
-public:
-	RemoveTree() : TIntermTraverser(false, false, true)
-	{
-	}
-
-protected:
-	void visitSymbol(TIntermSymbol*);
-	void visitConstantUnion(TIntermConstantUnion*);
-	bool visitBinary(Visit visit, TIntermBinary*);
-	bool visitUnary(Visit visit, TIntermUnary*);
-	bool visitSelection(Visit visit, TIntermSelection*);
-	bool visitAggregate(Visit visit, TIntermAggregate*);
-};
-
-void RemoveTree::visitSymbol(TIntermSymbol* node)
-{
-	delete node;
-}
-
-bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node)
-{
-	delete node;
-
-	return true;
-}
-
-bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node)
-{
-    delete node;
-
-	return true;
-}
-
-bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node)
-{
-	delete node;
-
-	return true;
-}
-
-bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node)
-{
-	delete node;
-
-	return true;
-}
-
-void RemoveTree::visitConstantUnion(TIntermConstantUnion* node)
-{
-	delete node;
-}
-
-//
-// Entry point.
-//
-void RemoveAllTreeNodes(TIntermNode* root)
-{
-    RemoveTree it;
-
-    root->traverse(&it);
-}
-
diff --git a/src/third_party/angle/src/compiler/RemoveTree.h b/src/third_party/angle/src/compiler/RemoveTree.h
deleted file mode 100644
index 97a8216..0000000
--- a/src/third_party/angle/src/compiler/RemoveTree.h
+++ /dev/null
@@ -1,7 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-void RemoveAllTreeNodes(TIntermNode*);
diff --git a/src/third_party/angle/src/compiler/RenameFunction.h b/src/third_party/angle/src/compiler/RenameFunction.h
deleted file mode 100644
index 3908bfd..0000000
--- a/src/third_party/angle/src/compiler/RenameFunction.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_RENAME_FUNCTION
-#define COMPILER_RENAME_FUNCTION
-
-#include "compiler/intermediate.h"
-
-//
-// Renames a function, including its declaration and any calls to it.
-//
-class RenameFunction : public TIntermTraverser
-{
-public:
-    RenameFunction(const TString& oldFunctionName, const TString& newFunctionName)
-    : TIntermTraverser(true, false, false)
-    , mOldFunctionName(oldFunctionName)
-    , mNewFunctionName(newFunctionName) {}
-
-    virtual bool visitAggregate(Visit visit, TIntermAggregate* node)
-    {
-        TOperator op = node->getOp();
-        if ((op == EOpFunction || op == EOpFunctionCall) && node->getName() == mOldFunctionName)
-            node->setName(mNewFunctionName);
-        return true;
-    }
-
-private:
-    const TString mOldFunctionName;
-    const TString mNewFunctionName;
-};
-
-#endif  // COMPILER_RENAME_FUNCTION
diff --git a/src/third_party/angle/src/compiler/SearchSymbol.cpp b/src/third_party/angle/src/compiler/SearchSymbol.cpp
deleted file mode 100644
index 9368f1a..0000000
--- a/src/third_party/angle/src/compiler/SearchSymbol.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// SearchSymbol is an AST traverser to detect the use of a given symbol name
-//
-
-#include "compiler/SearchSymbol.h"
-
-#include "compiler/InfoSink.h"
-#include "compiler/OutputHLSL.h"
-
-namespace sh
-{
-SearchSymbol::SearchSymbol(const TString &symbol) : mSymbol(symbol)
-{
-    match = false;
-}
-
-void SearchSymbol::traverse(TIntermNode *node)
-{
-    node->traverse(this);
-}
-
-void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode)
-{
-    if (symbolNode->getSymbol() == mSymbol)
-    {
-        match = true;
-    }
-}
-
-bool SearchSymbol::foundMatch() const
-{
-    return match;
-}
-}
diff --git a/src/third_party/angle/src/compiler/SearchSymbol.h b/src/third_party/angle/src/compiler/SearchSymbol.h
deleted file mode 100644
index 6bc0b90..0000000
--- a/src/third_party/angle/src/compiler/SearchSymbol.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// SearchSymbol is an AST traverser to detect the use of a given symbol name
-//
-
-#ifndef COMPILER_SEARCHSYMBOL_H_
-#define COMPILER_SEARCHSYMBOL_H_
-
-#include "compiler/intermediate.h"
-#include "compiler/ParseHelper.h"
-
-namespace sh
-{
-class SearchSymbol : public TIntermTraverser
-{
-  public:
-    SearchSymbol(const TString &symbol);
-
-    void traverse(TIntermNode *node);
-    void visitSymbol(TIntermSymbol *symbolNode);
-
-    bool foundMatch() const;
-
-  protected:
-    const TString &mSymbol;
-    bool match;
-};
-}
-
-#endif   // COMPILER_SEARCHSYMBOL_H_
diff --git a/src/third_party/angle/src/compiler/ShHandle.h b/src/third_party/angle/src/compiler/ShHandle.h
deleted file mode 100644
index eaf6f68..0000000
--- a/src/third_party/angle/src/compiler/ShHandle.h
+++ /dev/null
@@ -1,167 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _SHHANDLE_INCLUDED_
-#define _SHHANDLE_INCLUDED_
-
-//
-// Machine independent part of the compiler private objects
-// sent as ShHandle to the driver.
-//
-// This should not be included by driver code.
-//
-
-#include "GLSLANG/ShaderLang.h"
-
-#include "compiler/BuiltInFunctionEmulator.h"
-#include "compiler/ExtensionBehavior.h"
-#include "compiler/HashNames.h"
-#include "compiler/InfoSink.h"
-#include "compiler/SymbolTable.h"
-#include "compiler/VariableInfo.h"
-#include "third_party/compiler/ArrayBoundsClamper.h"
-
-class LongNameMap;
-class TCompiler;
-class TDependencyGraph;
-class TranslatorHLSL;
-
-//
-// Helper function to identify specs that are based on the WebGL spec,
-// like the CSS Shaders spec.
-//
-bool isWebGLBasedSpec(ShShaderSpec spec);
-
-//
-// The base class used to back handles returned to the driver.
-//
-class TShHandleBase {
-public:
-    TShHandleBase();
-    virtual ~TShHandleBase();
-    virtual TCompiler* getAsCompiler() { return 0; }
-    virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; }
-
-protected:
-    // Memory allocator. Allocates and tracks memory required by the compiler.
-    // Deallocates all memory when compiler is destructed.
-    TPoolAllocator allocator;
-};
-
-//
-// The base class for the machine dependent compiler to derive from
-// for managing object code from the compile.
-//
-class TCompiler : public TShHandleBase {
-public:
-    TCompiler(ShShaderType type, ShShaderSpec spec);
-    virtual ~TCompiler();
-    virtual TCompiler* getAsCompiler() { return this; }
-
-    bool Init(const ShBuiltInResources& resources);
-    bool compile(const char* const shaderStrings[],
-                 size_t numStrings,
-                 int compileOptions);
-
-    // Get results of the last compilation.
-    TInfoSink& getInfoSink() { return infoSink; }
-    const TVariableInfoList& getAttribs() const { return attribs; }
-    const TVariableInfoList& getUniforms() const { return uniforms; }
-    int getMappedNameMaxLength() const;
-
-    ShHashFunction64 getHashFunction() const { return hashFunction; }
-    NameMap& getNameMap() { return nameMap; }
-    TSymbolTable& getSymbolTable() { return symbolTable; }
-
-protected:
-    ShShaderType getShaderType() const { return shaderType; }
-    ShShaderSpec getShaderSpec() const { return shaderSpec; }
-    // Initialize symbol-table with built-in symbols.
-    bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
-    // Clears the results from the previous compilation.
-    void clearResults();
-    // Return true if function recursion is detected or call depth exceeded.
-    bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth);
-    // Rewrites a shader's intermediate tree according to the CSS Shaders spec.
-    void rewriteCSSShader(TIntermNode* root);
-    // Returns true if the given shader does not exceed the minimum
-    // functionality mandated in GLSL 1.0 spec Appendix A.
-    bool validateLimitations(TIntermNode* root);
-    // Collect info for all attribs and uniforms.
-    void collectAttribsUniforms(TIntermNode* root);
-    // Map long variable names into shorter ones.
-    void mapLongVariableNames(TIntermNode* root);
-    // Translate to object code.
-    virtual void translate(TIntermNode* root) = 0;
-    // Returns true if, after applying the packing rules in the GLSL 1.017 spec
-    // Appendix A, section 7, the shader does not use too many uniforms.
-    bool enforcePackingRestrictions();
-    // Returns true if the shader passes the restrictions that aim to prevent timing attacks.
-    bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph);
-    // Returns true if the shader does not use samplers.
-    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 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;
-
-private:
-    ShShaderType shaderType;
-    ShShaderSpec shaderSpec;
-
-    int maxUniformVectors;
-    int maxExpressionComplexity;
-    int maxCallStackDepth;
-
-    ShBuiltInResources compileResources;
-
-    // Built-in symbol table for the given language, spec, and resources.
-    // It is preserved from compile-to-compile.
-    TSymbolTable symbolTable;
-    // Built-in extensions with default behavior.
-    TExtensionBehavior extensionBehavior;
-    bool fragmentPrecisionHigh;
-
-    ArrayBoundsClamper arrayBoundsClamper;
-    ShArrayIndexClampingStrategy clampingStrategy;
-    BuiltInFunctionEmulator builtInFunctionEmulator;
-
-    // Results of compilation.
-    TInfoSink infoSink;  // Output sink.
-    TVariableInfoList attribs;  // Active attributes in the compiled shader.
-    TVariableInfoList uniforms;  // Active uniforms in the compiled shader.
-
-    // Cached copy of the ref-counted singleton.
-    LongNameMap* longNameMap;
-
-    // name hashing.
-    ShHashFunction64 hashFunction;
-    NameMap nameMap;
-};
-
-//
-// This is the interface between the machine independent code
-// and the machine dependent code.
-//
-// The machine dependent code should derive from the classes
-// above. Then Construct*() and Delete*() will create and 
-// destroy the machine dependent objects, which contain the
-// above machine independent information.
-//
-TCompiler* ConstructCompiler(
-    ShShaderType type, ShShaderSpec spec, ShShaderOutput output);
-void DeleteCompiler(TCompiler*);
-
-#endif // _SHHANDLE_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/ShaderLang.cpp b/src/third_party/angle/src/compiler/ShaderLang.cpp
deleted file mode 100644
index 3f63703..0000000
--- a/src/third_party/angle/src/compiler/ShaderLang.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-//
-// Implement the top-level of interface to the compiler,
-// as defined in ShaderLang.h
-//
-
-#include "GLSLANG/ShaderLang.h"
-
-#include "compiler/InitializeDll.h"
-#include "compiler/preprocessor/length_limits.h"
-#include "compiler/ShHandle.h"
-#include "compiler/TranslatorHLSL.h"
-
-//
-// This is the platform independent interface between an OGL driver
-// and the shading language compiler.
-//
-
-static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
-                                                  size_t expectedValue)
-{
-    size_t activeUniformLimit = 0;
-    ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
-    size_t activeAttribLimit = 0;
-    ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
-    return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
-}
-
-static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
-{
-    size_t mappedNameMaxLength = 0;
-    ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
-    return (expectedValue == mappedNameMaxLength);
-}
-
-static void getVariableInfo(ShShaderInfo varType,
-                            const ShHandle handle,
-                            int index,
-                            size_t* length,
-                            int* size,
-                            ShDataType* type,
-                            char* name,
-                            char* mappedName)
-{
-    if (!handle || !size || !type || !name)
-        return;
-    ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
-           (varType == SH_ACTIVE_UNIFORMS));
-
-    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (compiler == 0)
-        return;
-
-    const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
-        compiler->getAttribs() : compiler->getUniforms();
-    if (index < 0 || index >= static_cast<int>(varList.size()))
-        return;
-
-    const TVariableInfo& varInfo = varList[index];
-    if (length) *length = varInfo.name.size();
-    *size = varInfo.size;
-    *type = varInfo.type;
-
-    // This size must match that queried by
-    // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
-    // in ShGetInfo, below.
-    size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
-    ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
-    strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
-    name[activeUniformAndAttribLength - 1] = 0;
-    if (mappedName) {
-        // This size must match that queried by
-        // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
-        size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
-        ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
-        strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
-        mappedName[maxMappedNameLength - 1] = 0;
-    }
-}
-
-//
-// Driver must call this first, once, before doing any other
-// compiler operations.
-//
-int ShInitialize()
-{
-    if (!InitProcess())
-        return 0;
-
-    return 1;
-}
-
-//
-// Cleanup symbol tables
-//
-int ShFinalize()
-{
-    if (!DetachProcess())
-        return 0;
-
-    return 1;
-}
-
-//
-// Initialize built-in resources with minimum expected values.
-//
-void ShInitBuiltInResources(ShBuiltInResources* resources)
-{
-    // Constants.
-    resources->MaxVertexAttribs = 8;
-    resources->MaxVertexUniformVectors = 128;
-    resources->MaxVaryingVectors = 8;
-    resources->MaxVertexTextureImageUnits = 0;
-    resources->MaxCombinedTextureImageUnits = 8;
-    resources->MaxTextureImageUnits = 8;
-    resources->MaxFragmentUniformVectors = 16;
-    resources->MaxDrawBuffers = 1;
-
-    // Extensions.
-    resources->OES_standard_derivatives = 0;
-    resources->OES_EGL_image_external = 0;
-    resources->ARB_texture_rectangle = 0;
-    resources->EXT_draw_buffers = 0;
-    resources->EXT_frag_depth = 0;
-
-    // Disable highp precision in fragment shader by default.
-    resources->FragmentPrecisionHigh = 0;
-
-    // Disable name hashing by default.
-    resources->HashFunction = NULL;
-
-    resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
-}
-
-//
-// Driver calls these to create and destroy compiler objects.
-//
-ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
-                             ShShaderOutput output,
-                             const ShBuiltInResources* resources)
-{
-    if (!InitThread())
-        return 0;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
-    TCompiler* compiler = base->getAsCompiler();
-    if (compiler == 0)
-        return 0;
-
-    // Generate built-in symbol table.
-    if (!compiler->Init(*resources)) {
-        ShDestruct(base);
-        return 0;
-    }
-
-    return reinterpret_cast<void*>(base);
-}
-
-void ShDestruct(ShHandle handle)
-{
-    if (handle == 0)
-        return;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-
-    if (base->getAsCompiler())
-        DeleteCompiler(base->getAsCompiler());
-}
-
-//
-// Do an actual compile on the given strings.  The result is left 
-// in the given compile object.
-//
-// Return:  The return value of ShCompile is really boolean, indicating
-// success or failure.
-//
-int ShCompile(
-    const ShHandle handle,
-    const char* const shaderStrings[],
-    size_t numStrings,
-    int compileOptions)
-{
-    if (!InitThread())
-        return 0;
-
-    if (handle == 0)
-        return 0;
-
-    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (compiler == 0)
-        return 0;
-
-    bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
-    return success ? 1 : 0;
-}
-
-void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
-{
-    if (!handle || !params)
-        return;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (!compiler) return;
-
-    switch(pname)
-    {
-    case SH_INFO_LOG_LENGTH:
-        *params = compiler->getInfoSink().info.size() + 1;
-        break;
-    case SH_OBJECT_CODE_LENGTH:
-        *params = compiler->getInfoSink().obj.size() + 1;
-        break;
-    case SH_ACTIVE_UNIFORMS:
-        *params = compiler->getUniforms().size();
-        break;
-    case SH_ACTIVE_UNIFORM_MAX_LENGTH:
-        *params = 1 +  MAX_SYMBOL_NAME_LEN;
-        break;
-    case SH_ACTIVE_ATTRIBUTES:
-        *params = compiler->getAttribs().size();
-        break;
-    case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
-        *params = 1 + MAX_SYMBOL_NAME_LEN;
-        break;
-    case SH_MAPPED_NAME_MAX_LENGTH:
-        // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
-        // handle array and struct dereferences.
-        *params = 1 + MAX_SYMBOL_NAME_LEN;
-        break;
-    case SH_NAME_MAX_LENGTH:
-        *params = 1 + MAX_SYMBOL_NAME_LEN;
-        break;
-    case SH_HASHED_NAME_MAX_LENGTH:
-        if (compiler->getHashFunction() == NULL) {
-            *params = 0;
-        } else {
-            // 64 bits hashing output requires 16 bytes for hex 
-            // representation.
-            const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
-            *params = 16 + sizeof(HashedNamePrefix);
-        }
-        break;
-    case SH_HASHED_NAMES_COUNT:
-        *params = compiler->getNameMap().size();
-        break;
-    default: UNREACHABLE();
-    }
-}
-
-//
-// Return any compiler log of messages for the application.
-//
-void ShGetInfoLog(const ShHandle handle, char* infoLog)
-{
-    if (!handle || !infoLog)
-        return;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (!compiler) return;
-
-    TInfoSink& infoSink = compiler->getInfoSink();
-    strcpy(infoLog, infoSink.info.c_str());
-}
-
-//
-// Return any object code.
-//
-void ShGetObjectCode(const ShHandle handle, char* objCode)
-{
-    if (!handle || !objCode)
-        return;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (!compiler) return;
-
-    TInfoSink& infoSink = compiler->getInfoSink();
-    strcpy(objCode, infoSink.obj.c_str());
-}
-
-void ShGetActiveAttrib(const ShHandle handle,
-                       int index,
-                       size_t* length,
-                       int* size,
-                       ShDataType* type,
-                       char* name,
-                       char* mappedName)
-{
-    getVariableInfo(SH_ACTIVE_ATTRIBUTES,
-                    handle, index, length, size, type, name, mappedName);
-}
-
-void ShGetActiveUniform(const ShHandle handle,
-                        int index,
-                        size_t* length,
-                        int* size,
-                        ShDataType* type,
-                        char* name,
-                        char* mappedName)
-{
-    getVariableInfo(SH_ACTIVE_UNIFORMS,
-                    handle, index, length, size, type, name, mappedName);
-}
-
-void ShGetNameHashingEntry(const ShHandle handle,
-                           int index,
-                           char* name,
-                           char* hashedName)
-{
-    if (!handle || !name || !hashedName || index < 0)
-        return;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (!compiler) return;
-
-    const NameMap& nameMap = compiler->getNameMap();
-    if (index >= static_cast<int>(nameMap.size()))
-        return;
-
-    NameMap::const_iterator it = nameMap.begin();
-    for (int i = 0; i < index; ++i)
-        ++it;
-
-    size_t len = it->first.length() + 1;
-    size_t max_len = 0;
-    ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
-    if (len > max_len) {
-        ASSERT(false);
-        len = max_len;
-    }
-    strncpy(name, it->first.c_str(), len);
-    // To be on the safe side in case the source is longer than expected.
-    name[len - 1] = '\0';
-
-    len = it->second.length() + 1;
-    max_len = 0;
-    ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
-    if (len > max_len) {
-        ASSERT(false);
-        len = max_len;
-    }
-    strncpy(hashedName, it->second.c_str(), len);
-    // To be on the safe side in case the source is longer than expected.
-    hashedName[len - 1] = '\0';
-}
-
-void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
-{
-    if (!handle || !params)
-        return;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TranslatorHLSL* translator = base->getAsTranslatorHLSL();
-    if (!translator) return;
-
-    switch(pname)
-    {
-    case SH_ACTIVE_UNIFORMS_ARRAY:
-        *params = (void*)&translator->getUniforms();
-        break;
-    default: UNREACHABLE();
-    }
-}
diff --git a/src/third_party/angle/src/compiler/SymbolTable.cpp b/src/third_party/angle/src/compiler/SymbolTable.cpp
deleted file mode 100644
index 51180af..0000000
--- a/src/third_party/angle/src/compiler/SymbolTable.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-//
-// Symbol table for parsing.  Most functionaliy and main ideas
-// are documented in the header file.
-//
-
-#if defined(_MSC_VER)
-#pragma warning(disable: 4718)
-#endif
-
-#include "compiler/SymbolTable.h"
-
-#include <stdio.h>
-#include <algorithm>
-#include <climits>
-
-TType::TType(const TPublicType &p) :
-            type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0)
-{
-    if (p.userDef)
-        structure = p.userDef->getStruct();
-}
-
-//
-// Recursively generate mangled names.
-//
-TString TType::buildMangledName() const
-{
-    TString mangledName;
-    if (isMatrix())
-        mangledName += 'm';
-    else if (isVector())
-        mangledName += 'v';
-
-    switch (type) {
-    case EbtFloat:       mangledName += 'f';      break;
-    case EbtInt:         mangledName += 'i';      break;
-    case EbtBool:        mangledName += 'b';      break;
-    case EbtSampler2D:   mangledName += "s2";     break;
-    case EbtSamplerCube: mangledName += "sC";     break;
-    case EbtStruct:      mangledName += structure->mangledName(); break;
-    default:             break;
-    }
-
-    mangledName += static_cast<char>('0' + getNominalSize());
-    if (isArray()) {
-        char buf[20];
-        snprintf(buf, sizeof(buf), "%d", arraySize);
-        mangledName += '[';
-        mangledName += buf;
-        mangledName += ']';
-    }
-    return mangledName;
-}
-
-size_t TType::getObjectSize() const
-{
-    size_t totalSize = 0;
-
-    if (getBasicType() == EbtStruct)
-        totalSize = structure->objectSize();
-    else if (matrix)
-        totalSize = size * size;
-    else
-        totalSize = size;
-
-    if (isArray()) {
-        size_t arraySize = getArraySize();
-        if (arraySize > INT_MAX / totalSize)
-            totalSize = INT_MAX;
-        else
-            totalSize *= arraySize;
-    }
-
-    return totalSize;
-}
-
-bool TStructure::containsArrays() const
-{
-    for (size_t i = 0; i < mFields->size(); ++i) {
-        const TType* fieldType = (*mFields)[i]->type();
-        if (fieldType->isArray() || fieldType->isStructureContainingArrays())
-            return true;
-    }
-    return false;
-}
-
-TString TStructure::buildMangledName() const
-{
-    TString mangledName("struct-");
-    mangledName += *mName;
-    for (size_t i = 0; i < mFields->size(); ++i) {
-        mangledName += '-';
-        mangledName += (*mFields)[i]->type()->getMangledName();
-    }
-    return mangledName;
-}
-
-size_t TStructure::calculateObjectSize() const
-{
-    size_t size = 0;
-    for (size_t i = 0; i < mFields->size(); ++i) {
-        size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
-        if (fieldSize > INT_MAX - size)
-            size = INT_MAX;
-        else
-            size += fieldSize;
-    }
-    return size;
-}
-
-int TStructure::calculateDeepestNesting() const
-{
-    int maxNesting = 0;
-    for (size_t i = 0; i < mFields->size(); ++i) {
-        maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
-    }
-    return 1 + maxNesting;
-}
-
-//
-// Dump functions.
-//
-
-void TVariable::dump(TInfoSink& infoSink) const
-{
-    infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString();
-    if (type.isArray()) {
-        infoSink.debug << "[0]";
-    }
-    infoSink.debug << "\n";
-}
-
-void TFunction::dump(TInfoSink &infoSink) const
-{
-    infoSink.debug << getName().c_str() << ": " <<  returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
-}
-
-void TSymbolTableLevel::dump(TInfoSink &infoSink) const
-{
-    tLevel::const_iterator it;
-    for (it = level.begin(); it != level.end(); ++it)
-        (*it).second->dump(infoSink);
-}
-
-void TSymbolTable::dump(TInfoSink &infoSink) const
-{
-    for (int level = currentLevel(); level >= 0; --level) {
-        infoSink.debug << "LEVEL " << level << "\n";
-        table[level]->dump(infoSink);
-    }
-}
-
-//
-// Functions have buried pointers to delete.
-//
-TFunction::~TFunction()
-{
-    for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
-        delete (*i).type;
-}
-
-//
-// Symbol table levels are a map of pointers to symbols that have to be deleted.
-//
-TSymbolTableLevel::~TSymbolTableLevel()
-{
-    for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
-        delete (*it).second;
-}
-
-//
-// Change all function entries in the table with the non-mangled name
-// to be related to the provided built-in operation.  This is a low
-// performance operation, and only intended for symbol tables that
-// live across a large number of compiles.
-//
-void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
-{
-    tLevel::iterator it;
-    for (it = level.begin(); it != level.end(); ++it) {
-        if ((*it).second->isFunction()) {
-            TFunction* function = static_cast<TFunction*>((*it).second);
-            if (function->getName() == name)
-                function->relateToOperator(op);
-        }
-    }
-}
-
-//
-// Change all function entries in the table with the non-mangled name
-// to be related to the provided built-in extension. This is a low
-// performance operation, and only intended for symbol tables that
-// live across a large number of compiles.
-//
-void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
-{
-    for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
-        TSymbol* symbol = it->second;
-        if (symbol->getName() == name)
-            symbol->relateToExtension(ext);
-    }
-}
diff --git a/src/third_party/angle/src/compiler/SymbolTable.h b/src/third_party/angle/src/compiler/SymbolTable.h
deleted file mode 100644
index 7ea6cd1..0000000
--- a/src/third_party/angle/src/compiler/SymbolTable.h
+++ /dev/null
@@ -1,389 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _SYMBOL_TABLE_INCLUDED_
-#define _SYMBOL_TABLE_INCLUDED_
-
-//
-// Symbol table for parsing.  Has these design characteristics:
-//
-// * Same symbol table can be used to compile many shaders, to preserve
-//   effort of creating and loading with the large numbers of built-in
-//   symbols.
-//
-// * Name mangling will be used to give each function a unique name
-//   so that symbol table lookups are never ambiguous.  This allows
-//   a simpler symbol table structure.
-//
-// * Pushing and popping of scope, so symbol table will really be a stack 
-//   of symbol tables.  Searched from the top, with new inserts going into
-//   the top.
-//
-// * Constants:  Compile time constant symbols will keep their values
-//   in the symbol table.  The parser can substitute constants at parse
-//   time, including doing constant folding and constant propagation.
-//
-// * No temporaries:  Temporaries made from operations (+, --, .xy, etc.)
-//   are tracked in the intermediate representation, not the symbol table.
-//
-
-#include <assert.h>
-
-#include "common/angleutils.h"
-#include "compiler/InfoSink.h"
-#include "compiler/intermediate.h"
-
-//
-// Symbol base class.  (Can build functions or variables out of these...)
-//
-class TSymbol {    
-public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-    TSymbol(const TString *n) :  name(n) { }
-    virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
-    const TString& getName() const { return *name; }
-    virtual const TString& getMangledName() const { return getName(); }
-    virtual bool isFunction() const { return false; }
-    virtual bool isVariable() const { return false; }
-    void setUniqueId(int id) { uniqueId = id; }
-    int getUniqueId() const { return uniqueId; }
-    virtual void dump(TInfoSink &infoSink) const = 0;
-    void relateToExtension(const TString& ext) { extension = ext; }
-    const TString& getExtension() const { return extension; }
-
-private:
-    DISALLOW_COPY_AND_ASSIGN(TSymbol);
-
-    const TString *name;
-    unsigned int uniqueId;      // For real comparing during code generation
-    TString extension;
-};
-
-//
-// Variable class, meaning a symbol that's not a function.
-// 
-// There could be a separate class heirarchy for Constant variables;
-// Only one of int, bool, or float, (or none) is correct for
-// any particular use, but it's easy to do this way, and doesn't
-// seem worth having separate classes, and "getConst" can't simply return
-// different values for different types polymorphically, so this is 
-// just simple and pragmatic.
-//
-class TVariable : public TSymbol {
-public:
-    TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { }
-    virtual ~TVariable() { }
-    virtual bool isVariable() const { return true; }    
-    TType& getType() { return type; }    
-    const TType& getType() const { return type; }
-    bool isUserType() const { return userType; }
-    void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
-
-    virtual void dump(TInfoSink &infoSink) const;
-
-    ConstantUnion* getConstPointer()
-    { 
-        if (!unionArray)
-            unionArray = new ConstantUnion[type.getObjectSize()];
-
-        return unionArray;
-    }
-
-    ConstantUnion* getConstPointer() const { return unionArray; }
-
-    void shareConstPointer( ConstantUnion *constArray)
-    {
-        if (unionArray == constArray)
-            return;
-
-        delete[] unionArray;
-        unionArray = constArray;  
-    }
-
-private:
-    DISALLOW_COPY_AND_ASSIGN(TVariable);
-
-    TType type;
-    bool userType;
-    // we are assuming that Pool Allocator will free the memory allocated to unionArray
-    // when this object is destroyed
-    ConstantUnion *unionArray;
-};
-
-//
-// The function sub-class of symbols and the parser will need to
-// share this definition of a function parameter.
-//
-struct TParameter {
-    TString *name;
-    TType* type;
-};
-
-//
-// The function sub-class of a symbol.  
-//
-class TFunction : public TSymbol {
-public:
-    TFunction(TOperator o) :
-        TSymbol(0),
-        returnType(TType(EbtVoid, EbpUndefined)),
-        op(o),
-        defined(false) { }
-    TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : 
-        TSymbol(name), 
-        returnType(retType),
-        mangledName(TFunction::mangleName(*name)),
-        op(tOp),
-        defined(false) { }
-    virtual ~TFunction();
-    virtual bool isFunction() const { return true; }    
-
-    static TString mangleName(const TString& name) { return name + '('; }
-    static TString unmangleName(const TString& mangledName)
-    {
-        return TString(mangledName.c_str(), mangledName.find_first_of('('));
-    }
-
-    void addParameter(TParameter& p) 
-    { 
-        parameters.push_back(p);
-        mangledName = mangledName + p.type->getMangledName();
-    }
-
-    const TString& getMangledName() const { return mangledName; }
-    const TType& getReturnType() const { return returnType; }
-
-    void relateToOperator(TOperator o) { op = o; }
-    TOperator getBuiltInOp() const { return op; }
-
-    void setDefined() { defined = true; }
-    bool isDefined() { return defined; }
-
-    size_t getParamCount() const { return parameters.size(); }  
-    const TParameter& getParam(size_t i) const { return parameters[i]; }
-
-    virtual void dump(TInfoSink &infoSink) const;
-
-private:
-    DISALLOW_COPY_AND_ASSIGN(TFunction);
-
-    typedef TVector<TParameter> TParamList;
-    TParamList parameters;
-    TType returnType;
-    TString mangledName;
-    TOperator op;
-    bool defined;
-};
-
-
-class TSymbolTableLevel {
-public:
-    typedef TMap<TString, TSymbol*> tLevel;
-    typedef tLevel::const_iterator const_iterator;
-    typedef const tLevel::value_type tLevelPair;
-    typedef std::pair<tLevel::iterator, bool> tInsertResult;
-
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-    TSymbolTableLevel() { }
-    ~TSymbolTableLevel();
-
-    bool insert(const TString &name, TSymbol &symbol)
-    {
-        //
-        // returning true means symbol was added to the table
-        //
-        tInsertResult result;
-        result = level.insert(tLevelPair(name, &symbol));
-
-        return result.second;
-    }
-
-    bool insert(TSymbol &symbol)
-    {
-        return insert(symbol.getMangledName(), symbol);
-    }
-
-    TSymbol* find(const TString& name) const
-    {
-        tLevel::const_iterator it = level.find(name);
-        if (it == level.end())
-            return 0;
-        else
-            return (*it).second;
-    }
-
-    const_iterator begin() const
-    {
-        return level.begin();
-    }
-
-    const_iterator end() const
-    {
-        return level.end();
-    }
-
-    void relateToOperator(const char* name, TOperator op);
-    void relateToExtension(const char* name, const TString& ext);
-    void dump(TInfoSink &infoSink) const;
-
-protected:
-    tLevel level;
-};
-
-class TSymbolTable {
-public:
-    TSymbolTable() : uniqueId(0)
-    {
-        //
-        // The symbol table cannot be used until push() is called, but
-        // the lack of an initial call to push() can be used to detect
-        // that the symbol table has not been preloaded with built-ins.
-        //
-    }
-
-    ~TSymbolTable()
-    {
-        // level 0 is always built In symbols, so we never pop that out
-        while (table.size() > 1)
-            pop();
-    }
-
-    //
-    // When the symbol table is initialized with the built-ins, there should
-    // 'push' calls, so that built-ins are at level 0 and the shader
-    // globals are at level 1.
-    //
-    bool isEmpty() { return table.size() == 0; }
-    bool atBuiltInLevel() { return table.size() == 1; }
-    bool atGlobalLevel() { return table.size() <= 2; }
-    void push()
-    {
-        table.push_back(new TSymbolTableLevel);
-        precisionStack.push_back( PrecisionStackLevel() );
-    }
-
-    void pop()
-    { 
-        delete table[currentLevel()]; 
-        table.pop_back(); 
-        precisionStack.pop_back();
-    }
-
-    bool insert(TSymbol& symbol)
-    {
-        symbol.setUniqueId(++uniqueId);
-        return table[currentLevel()]->insert(symbol);
-    }
-
-    bool insertConstInt(const char *name, int value)
-    {
-        TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
-        constant->getConstPointer()->setIConst(value);
-        return insert(*constant);
-    }
-
-    bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0)
-    {
-        TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
-
-        TParameter param1 = {NULL, ptype1};
-        function->addParameter(param1);
-
-        if(ptype2)
-        {
-            TParameter param2 = {NULL, ptype2};
-            function->addParameter(param2);
-        }
-
-        if(ptype3)
-        {
-            TParameter param3 = {NULL, ptype3};
-            function->addParameter(param3);
-        }
-
-        return insert(*function);
-    }
-
-    TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) 
-    {
-        int level = currentLevel();
-        TSymbol* symbol;
-        do {
-            symbol = table[level]->find(name);
-            --level;
-        } while (symbol == 0 && level >= 0);
-        level++;
-        if (builtIn)
-            *builtIn = level == 0;
-        if (sameScope)
-            *sameScope = level == currentLevel();
-        return symbol;
-    }
-
-    TSymbol *findBuiltIn(const TString &name)
-    {
-        return table[0]->find(name);
-    }
-
-    TSymbolTableLevel* getGlobalLevel() {
-        assert(table.size() >= 2);
-        return table[1];
-    }
-
-    TSymbolTableLevel* getOuterLevel() {
-        assert(table.size() >= 2);
-        return table[currentLevel() - 1];
-    }
-
-    void relateToOperator(const char* name, TOperator op) {
-        table[0]->relateToOperator(name, op);
-    }
-    void relateToExtension(const char* name, const TString& ext) {
-        table[0]->relateToExtension(name, ext);
-    }
-    int getMaxSymbolId() { return uniqueId; }
-    void dump(TInfoSink &infoSink) const;
-
-    bool setDefaultPrecision( const TPublicType& type, TPrecision prec ){
-        if (IsSampler(type.type))
-            return true;  // Skip sampler types for the time being
-        if (type.type != EbtFloat && type.type != EbtInt)
-            return false; // Only set default precision for int/float
-        if (type.size != 1 || type.matrix || type.array)
-            return false; // Not allowed to set for aggregate types
-        int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
-        precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value
-        return true;
-    }
-
-    // Searches down the precisionStack for a precision qualifier for the specified TBasicType
-    TPrecision getDefaultPrecision( TBasicType type){
-        if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
-        int level = static_cast<int>(precisionStack.size()) - 1;
-        assert( level >= 0); // Just to be safe. Should not happen.
-        PrecisionStackLevel::iterator it;
-        TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
-        while( level >= 0 ){
-            it = precisionStack[level].find( type );
-            if( it != precisionStack[level].end() ){
-                prec = (*it).second;
-                break;
-            }
-            level--;
-        }
-        return prec;
-    }
-
-protected:    
-    int currentLevel() const { return static_cast<int>(table.size()) - 1; }
-
-    std::vector<TSymbolTableLevel*> table;
-    typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
-    std::vector< PrecisionStackLevel > precisionStack;
-    int uniqueId;     // for unique identification in code generation
-};
-
-#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/TranslatorESSL.cpp b/src/third_party/angle/src/compiler/TranslatorESSL.cpp
deleted file mode 100644
index 2900f8a..0000000
--- a/src/third_party/angle/src/compiler/TranslatorESSL.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/TranslatorESSL.h"
-
-#include "compiler/OutputESSL.h"
-
-TranslatorESSL::TranslatorESSL(ShShaderType type, ShShaderSpec spec)
-    : TCompiler(type, spec) {
-}
-
-void TranslatorESSL::translate(TIntermNode* root) {
-    TInfoSinkBase& sink = getInfoSink().obj;
-
-    // Write built-in extension behaviors.
-    writeExtensionBehavior();
-
-    // Write emulated built-in functions if needed.
-    getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
-        sink, getShaderType() == SH_FRAGMENT_SHADER);
-
-    // Write array bounds clamping emulation if needed.
-    getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
-
-    // Write translated shader.
-    TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable());
-    root->traverse(&outputESSL);
-}
-
-void TranslatorESSL::writeExtensionBehavior() {
-    TInfoSinkBase& sink = getInfoSink().obj;
-    const TExtensionBehavior& extensionBehavior = getExtensionBehavior();
-    for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
-         iter != extensionBehavior.end(); ++iter) {
-        if (iter->second != EBhUndefined) {
-            sink << "#extension " << iter->first << " : "
-                 << getBehaviorString(iter->second) << "\n";
-        }
-    }
-}
diff --git a/src/third_party/angle/src/compiler/TranslatorESSL.h b/src/third_party/angle/src/compiler/TranslatorESSL.h
deleted file mode 100644
index a1196bd..0000000
--- a/src/third_party/angle/src/compiler/TranslatorESSL.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATORESSL_H_
-#define COMPILER_TRANSLATORESSL_H_
-
-#include "compiler/ShHandle.h"
-
-class TranslatorESSL : public TCompiler {
-public:
-    TranslatorESSL(ShShaderType type, ShShaderSpec spec);
-
-protected:
-    virtual void translate(TIntermNode* root);
-
-private:
-    void writeExtensionBehavior();
-};
-
-#endif  // COMPILER_TRANSLATORESSL_H_
diff --git a/src/third_party/angle/src/compiler/TranslatorGLSL.cpp b/src/third_party/angle/src/compiler/TranslatorGLSL.cpp
deleted file mode 100644
index 7ca4341..0000000
--- a/src/third_party/angle/src/compiler/TranslatorGLSL.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/TranslatorGLSL.h"
-
-#include "compiler/OutputGLSL.h"
-#include "compiler/VersionGLSL.h"
-
-static void writeVersion(ShShaderType type, TIntermNode* root,
-                         TInfoSinkBase& sink) {
-    TVersionGLSL versionGLSL(type);
-    root->traverse(&versionGLSL);
-    int version = versionGLSL.getVersion();
-    // We need to write version directive only if it is greater than 110.
-    // If there is no version directive in the shader, 110 is implied.
-    if (version > 110) {
-        sink << "#version " << version << "\n";
-    }
-}
-
-TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec)
-    : TCompiler(type, spec) {
-}
-
-void TranslatorGLSL::translate(TIntermNode* root) {
-    TInfoSinkBase& sink = getInfoSink().obj;
-
-    // Write GLSL version.
-    writeVersion(getShaderType(), root, sink);
-
-    // Write emulated built-in functions if needed.
-    getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
-        sink, false);
-
-    // Write array bounds clamping emulation if needed.
-    getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
-
-    // Write translated shader.
-    TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable());
-    root->traverse(&outputGLSL);
-}
diff --git a/src/third_party/angle/src/compiler/TranslatorGLSL.h b/src/third_party/angle/src/compiler/TranslatorGLSL.h
deleted file mode 100644
index c2ce06d..0000000
--- a/src/third_party/angle/src/compiler/TranslatorGLSL.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATORGLSL_H_
-#define COMPILER_TRANSLATORGLSL_H_
-
-#include "compiler/ShHandle.h"
-
-class TranslatorGLSL : public TCompiler {
-public:
-    TranslatorGLSL(ShShaderType type, ShShaderSpec spec);
-
-protected:
-    virtual void translate(TIntermNode* root);
-};
-
-#endif  // COMPILER_TRANSLATORGLSL_H_
diff --git a/src/third_party/angle/src/compiler/TranslatorHLSL.cpp b/src/third_party/angle/src/compiler/TranslatorHLSL.cpp
deleted file mode 100644
index 37408a0..0000000
--- a/src/third_party/angle/src/compiler/TranslatorHLSL.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/TranslatorHLSL.h"
-
-#include "compiler/InitializeParseContext.h"
-#include "compiler/OutputHLSL.h"
-
-TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output)
-    : TCompiler(type, spec), mOutputType(output)
-{
-}
-
-void TranslatorHLSL::translate(TIntermNode *root)
-{
-    TParseContext& parseContext = *GetGlobalParseContext();
-    sh::OutputHLSL outputHLSL(parseContext, getResources(), mOutputType);
-
-    outputHLSL.output();
-    mActiveUniforms = outputHLSL.getUniforms();
-}
diff --git a/src/third_party/angle/src/compiler/TranslatorHLSL.h b/src/third_party/angle/src/compiler/TranslatorHLSL.h
deleted file mode 100644
index 9550e15..0000000
--- a/src/third_party/angle/src/compiler/TranslatorHLSL.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATORHLSL_H_
-#define COMPILER_TRANSLATORHLSL_H_
-
-#include "compiler/ShHandle.h"
-#include "compiler/Uniform.h"
-
-class TranslatorHLSL : public TCompiler {
-public:
-    TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output);
-
-    virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; }
-    const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; }
-
-protected:
-    virtual void translate(TIntermNode* root);
-
-    sh::ActiveUniforms mActiveUniforms;
-    ShShaderOutput mOutputType;
-};
-
-#endif  // COMPILER_TRANSLATORHLSL_H_
diff --git a/src/third_party/angle/src/compiler/Types.h b/src/third_party/angle/src/compiler/Types.h
deleted file mode 100644
index 5946af0..0000000
--- a/src/third_party/angle/src/compiler/Types.h
+++ /dev/null
@@ -1,307 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _TYPES_INCLUDED
-#define _TYPES_INCLUDED
-
-#include "common/angleutils.h"
-
-#include "compiler/BaseTypes.h"
-#include "compiler/Common.h"
-#include "compiler/debug.h"
-
-struct TPublicType;
-class TType;
-
-class TField
-{
-public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
-    TField(TType* type, TString* name) : mType(type), mName(name) {}
-
-    // TODO(alokp): We should only return const type.
-    // Fix it by tweaking grammar.
-    TType* type() { return mType; }
-    const TType* type() const { return mType; }
-
-    const TString& name() const { return *mName; }
-
-private:
-    DISALLOW_COPY_AND_ASSIGN(TField);
-    TType* mType;
-    TString* mName;
-};
-
-typedef TVector<TField*> TFieldList;
-inline TFieldList* NewPoolTFieldList()
-{
-    void* memory = GlobalPoolAllocator.allocate(sizeof(TFieldList));
-    return new(memory) TFieldList;
-}
-
-class TStructure
-{
-public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
-    TStructure(TString* name, TFieldList* fields)
-        : mName(name),
-          mFields(fields),
-          mObjectSize(0),
-          mDeepestNesting(0) {
-    }
-
-    const TString& name() const { return *mName; }
-    const TFieldList& fields() const { return *mFields; }
-
-    const TString& mangledName() const {
-        if (mMangledName.empty())
-            mMangledName = buildMangledName();
-        return mMangledName;
-    }
-    size_t objectSize() const {
-        if (mObjectSize == 0)
-            mObjectSize = calculateObjectSize();
-        return mObjectSize;
-    };
-    int deepestNesting() const {
-        if (mDeepestNesting == 0)
-            mDeepestNesting = calculateDeepestNesting();
-        return mDeepestNesting;
-    }
-    bool containsArrays() const;
-
-private:
-    DISALLOW_COPY_AND_ASSIGN(TStructure);
-    TString buildMangledName() const;
-    size_t calculateObjectSize() const;
-    int calculateDeepestNesting() const;
-
-    TString* mName;
-    TFieldList* mFields;
-
-    mutable TString mMangledName;
-    mutable size_t mObjectSize;
-    mutable int mDeepestNesting;
-};
-
-//
-// Base class for things that have a type.
-//
-class TType
-{
-public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-    TType() {}
-    TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
-            type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0)
-    {
-    }
-    explicit TType(const TPublicType &p);
-    TType(TStructure* userDef, TPrecision p = EbpUndefined) :
-            type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef)
-    {
-    }
-
-    TBasicType getBasicType() const { return type; }
-    void setBasicType(TBasicType t) { type = t; }
-
-    TPrecision getPrecision() const { return precision; }
-    void setPrecision(TPrecision p) { precision = p; }
-
-    TQualifier getQualifier() const { return qualifier; }
-    void setQualifier(TQualifier q) { qualifier = q; }
-
-    // One-dimensional size of single instance type
-    int getNominalSize() const { return size; }
-    void setNominalSize(int s) { size = s; }
-    // Full size of single instance of type
-    size_t getObjectSize() const;
-
-    int elementRegisterCount() const
-    {
-        if (structure)
-        {
-            const TFieldList &fields = getStruct()->fields();
-            int registerCount = 0;
-
-            for (size_t i = 0; i < fields.size(); i++)
-            {
-                registerCount += fields[i]->type()->totalRegisterCount();
-            }
-
-            return registerCount;
-        }
-        else if (isMatrix())
-        {
-            return getNominalSize();
-        }
-        else
-        {
-            return 1;
-        }
-    }
-
-    int totalRegisterCount() const
-    {
-        if (array)
-        {
-            return arraySize * elementRegisterCount();
-        }
-        else
-        {
-            return elementRegisterCount();
-        }
-    }
-
-    bool isMatrix() const { return matrix ? true : false; }
-    void setMatrix(bool m) { matrix = m; }
-
-    bool isArray() const  { return array ? true : false; }
-    int getArraySize() const { return arraySize; }
-    void setArraySize(int s) { array = true; arraySize = s; }
-    void clearArrayness() { array = false; arraySize = 0; }
-
-    bool isVector() const { return size > 1 && !matrix; }
-    bool isScalar() const { return size == 1 && !matrix && !structure; }
-
-    TStructure* getStruct() const { return structure; }
-    void setStruct(TStructure* s) { structure = s; }
-
-    const TString& getMangledName() const {
-        if (mangled.empty()) {
-            mangled = buildMangledName();
-            mangled += ';';
-        }
-        return mangled;
-    }
-
-    bool sameElementType(const TType& right) const {
-        return      type == right.type   &&
-                    size == right.size   &&
-                  matrix == right.matrix &&
-               structure == right.structure;
-    }
-    bool operator==(const TType& right) const {
-        return      type == right.type   &&
-                    size == right.size   &&
-                  matrix == right.matrix &&
-                   array == right.array  && (!array || arraySize == right.arraySize) &&
-               structure == right.structure;
-        // don't check the qualifier, it's not ever what's being sought after
-    }
-    bool operator!=(const TType& right) const {
-        return !operator==(right);
-    }
-    bool operator<(const TType& right) const {
-        if (type != right.type) return type < right.type;
-        if (size != right.size) return size < right.size;
-        if (matrix != right.matrix) return matrix < right.matrix;
-        if (array != right.array) return array < right.array;
-        if (arraySize != right.arraySize) return arraySize < right.arraySize;
-        if (structure != right.structure) return structure < right.structure;
-
-        return false;
-    }
-
-    const char* getBasicString() const { return ::getBasicString(type); }
-    const char* getPrecisionString() const { return ::getPrecisionString(precision); }
-    const char* getQualifierString() const { return ::getQualifierString(qualifier); }
-    TString getCompleteString() const;
-
-    // If this type is a struct, returns the deepest struct nesting of
-    // any field in the struct. For example:
-    //   struct nesting1 {
-    //     vec4 position;
-    //   };
-    //   struct nesting2 {
-    //     nesting1 field1;
-    //     vec4 field2;
-    //   };
-    // For type "nesting2", this method would return 2 -- the number
-    // of structures through which indirection must occur to reach the
-    // deepest field (nesting2.field1.position).
-    int getDeepestStructNesting() const {
-        return structure ? structure->deepestNesting() : 0;
-    }
-
-    bool isStructureContainingArrays() const {
-        return structure ? structure->containsArrays() : false;
-    }
-
-private:
-    TString buildMangledName() const;
-
-    TBasicType type      : 6;
-    TPrecision precision;
-    TQualifier qualifier : 7;
-    int size             : 8; // size of vector or matrix, not size of array
-    unsigned int matrix  : 1;
-    unsigned int array   : 1;
-    int arraySize;
-
-    TStructure* structure;      // 0 unless this is a struct
-
-    mutable TString mangled;
-};
-
-//
-// This is a workaround for a problem with the yacc stack,  It can't have
-// types that it thinks have non-trivial constructors.  It should
-// just be used while recognizing the grammar, not anything else.  Pointers
-// could be used, but also trying to avoid lots of memory management overhead.
-//
-// Not as bad as it looks, there is no actual assumption that the fields
-// match up or are name the same or anything like that.
-//
-struct TPublicType
-{
-    TBasicType type;
-    TQualifier qualifier;
-    TPrecision precision;
-    int size;          // size of vector or matrix, not size of array
-    bool matrix;
-    bool array;
-    int arraySize;
-    TType* userDef;
-    TSourceLoc line;
-
-    void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln)
-    {
-        type = bt;
-        qualifier = q;
-        precision = EbpUndefined;
-        size = 1;
-        matrix = false;
-        array = false;
-        arraySize = 0;
-        userDef = 0;
-        line = ln;
-    }
-
-    void setAggregate(int s, bool m = false)
-    {
-        size = s;
-        matrix = m;
-    }
-
-    void setArray(bool a, int s = 0)
-    {
-        array = a;
-        arraySize = s;
-    }
-
-    bool isStructureContainingArrays() const
-    {
-        if (!userDef)
-        {
-            return false;
-        }
-
-        return userDef->isStructureContainingArrays();
-    }
-};
-
-#endif // _TYPES_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/UnfoldShortCircuit.cpp b/src/third_party/angle/src/compiler/UnfoldShortCircuit.cpp
deleted file mode 100644
index 47f0afc..0000000
--- a/src/third_party/angle/src/compiler/UnfoldShortCircuit.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements.
-// The results are assigned to s# temporaries, which are used by the main translator instead of
-// the original expression.
-//
-
-#include "compiler/UnfoldShortCircuit.h"
-
-#include "compiler/InfoSink.h"
-#include "compiler/OutputHLSL.h"
-
-namespace sh
-{
-UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
-{
-    mTemporaryIndex = 0;
-}
-
-void UnfoldShortCircuit::traverse(TIntermNode *node)
-{
-    int rewindIndex = mTemporaryIndex;
-    node->traverse(this);
-    mTemporaryIndex = rewindIndex;
-}
-
-bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node)
-{
-    TInfoSinkBase &out = mOutputHLSL->getBodyStream();
-
-    switch (node->getOp())
-    {
-      case EOpLogicalOr:
-        // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;",
-        // and then further simplifies down to "bool s = x; if(!s) s = y;".
-        {
-            int i = mTemporaryIndex;
-
-            out << "bool s" << i << ";\n";
-
-            out << "{\n";
-
-            mTemporaryIndex = i + 1;
-            node->getLeft()->traverse(this);
-            out << "s" << i << " = ";
-            mTemporaryIndex = i + 1;
-            node->getLeft()->traverse(mOutputHLSL);
-            out << ";\n";
-            out << "if(!s" << i << ")\n"
-                   "{\n";
-            mTemporaryIndex = i + 1;
-            node->getRight()->traverse(this);
-            out << "    s" << i << " = ";
-            mTemporaryIndex = i + 1;
-            node->getRight()->traverse(mOutputHLSL);
-            out << ";\n"
-                   "}\n";
-
-            out << "}\n";
-
-            mTemporaryIndex = i + 1;
-        }
-        return false;
-      case EOpLogicalAnd:
-        // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;",
-        // and then further simplifies down to "bool s = x; if(s) s = y;".
-        {
-            int i = mTemporaryIndex;
-
-            out << "bool s" << i << ";\n";
-
-            out << "{\n";
-
-            mTemporaryIndex = i + 1;
-            node->getLeft()->traverse(this);
-            out << "s" << i << " = ";
-            mTemporaryIndex = i + 1;
-            node->getLeft()->traverse(mOutputHLSL);
-            out << ";\n";
-            out << "if(s" << i << ")\n"
-                   "{\n";
-            mTemporaryIndex = i + 1;
-            node->getRight()->traverse(this);
-            out << "    s" << i << " = ";
-            mTemporaryIndex = i + 1;
-            node->getRight()->traverse(mOutputHLSL);
-            out << ";\n"
-                   "}\n";
-
-            out << "}\n";
-
-            mTemporaryIndex = i + 1;
-        }
-        return false;
-      default:
-        return true;
-    }
-}
-
-bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node)
-{
-    TInfoSinkBase &out = mOutputHLSL->getBodyStream();
-
-    // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
-    if (node->usesTernaryOperator())
-    {
-        int i = mTemporaryIndex;
-
-        out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n";
-
-        out << "{\n";
-
-        mTemporaryIndex = i + 1;
-        node->getCondition()->traverse(this);
-        out << "if(";
-        mTemporaryIndex = i + 1;
-        node->getCondition()->traverse(mOutputHLSL);
-        out << ")\n"
-               "{\n";
-        mTemporaryIndex = i + 1;
-        node->getTrueBlock()->traverse(this);
-        out << "    s" << i << " = ";
-        mTemporaryIndex = i + 1;
-        node->getTrueBlock()->traverse(mOutputHLSL);
-        out << ";\n"
-               "}\n"
-               "else\n"
-               "{\n";
-        mTemporaryIndex = i + 1;
-        node->getFalseBlock()->traverse(this);
-        out << "    s" << i << " = ";
-        mTemporaryIndex = i + 1;
-        node->getFalseBlock()->traverse(mOutputHLSL);
-        out << ";\n"
-               "}\n";
-
-        out << "}\n";
-
-        mTemporaryIndex = i + 1;
-    }
-
-    return false;
-}
-
-bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node)
-{
-    int rewindIndex = mTemporaryIndex;
-
-    if (node->getInit())
-    {
-        node->getInit()->traverse(this);
-    }
-    
-    if (node->getCondition())
-    {
-        node->getCondition()->traverse(this);
-    }
-
-    if (node->getExpression())
-    {
-        node->getExpression()->traverse(this);
-    }
-
-    mTemporaryIndex = rewindIndex;
-
-    return false;
-}
-
-int UnfoldShortCircuit::getNextTemporaryIndex()
-{
-    return mTemporaryIndex++;
-}
-}
diff --git a/src/third_party/angle/src/compiler/UnfoldShortCircuit.h b/src/third_party/angle/src/compiler/UnfoldShortCircuit.h
deleted file mode 100644
index cb176a5..0000000
--- a/src/third_party/angle/src/compiler/UnfoldShortCircuit.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements
-//
-
-#ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_
-#define COMPILER_UNFOLDSHORTCIRCUIT_H_
-
-#include "compiler/intermediate.h"
-#include "compiler/ParseHelper.h"
-
-namespace sh
-{
-class OutputHLSL;
-
-class UnfoldShortCircuit : public TIntermTraverser
-{
-  public:
-    UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL);
-
-    void traverse(TIntermNode *node);
-    bool visitBinary(Visit visit, TIntermBinary*);
-    bool visitSelection(Visit visit, TIntermSelection *node);
-    bool visitLoop(Visit visit, TIntermLoop *node);
-
-    int getNextTemporaryIndex();
-
-  protected:
-    TParseContext &mContext;
-    OutputHLSL *const mOutputHLSL;
-
-    int mTemporaryIndex;
-};
-}
-
-#endif   // COMPILER_UNFOLDSHORTCIRCUIT_H_
diff --git a/src/third_party/angle/src/compiler/Uniform.cpp b/src/third_party/angle/src/compiler/Uniform.cpp
deleted file mode 100644
index dcf3af1..0000000
--- a/src/third_party/angle/src/compiler/Uniform.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-//

-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-//

-

-#include "compiler/Uniform.h"

-

-namespace sh

-{

-

-Uniform::Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex)

-{

-    this->type = type;

-    this->precision = precision;

-    this->name = name;

-    this->arraySize = arraySize;

-    this->registerIndex = registerIndex;

-}

-

-}

diff --git a/src/third_party/angle/src/compiler/Uniform.h b/src/third_party/angle/src/compiler/Uniform.h
deleted file mode 100644
index 2ffd51e..0000000
--- a/src/third_party/angle/src/compiler/Uniform.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//

-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-//

-

-#ifndef COMPILER_UNIFORM_H_

-#define COMPILER_UNIFORM_H_

-

-#include <string>

-#include <vector>

-

-#define GL_APICALL

-#include <GLES2/gl2.h>

-

-namespace sh

-{

-

-struct Uniform

-{

-    Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex);

-

-    GLenum type;

-    GLenum precision;

-    std::string name;

-    unsigned int arraySize;

-    

-    int registerIndex;

-};

-

-typedef std::vector<Uniform> ActiveUniforms;

-

-}

-

-#endif   // COMPILER_UNIFORM_H_

diff --git a/src/third_party/angle/src/compiler/ValidateLimitations.cpp b/src/third_party/angle/src/compiler/ValidateLimitations.cpp
deleted file mode 100644
index a5562d0..0000000
--- a/src/third_party/angle/src/compiler/ValidateLimitations.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/ValidateLimitations.h"
-#include "compiler/InfoSink.h"
-#include "compiler/InitializeParseContext.h"
-#include "compiler/ParseHelper.h"
-
-namespace {
-bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) {
-    for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) {
-        if (i->index.id == symbol->getId())
-            return true;
-    }
-    return false;
-}
-
-void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) {
-    for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) {
-        if (i->index.id == symbol->getId()) {
-            ASSERT(i->loop != NULL);
-            i->loop->setUnrollFlag(true);
-            return;
-        }
-    }
-    UNREACHABLE();
-}
-
-// Traverses a node to check if it represents a constant index expression.
-// Definition:
-// constant-index-expressions are a superset of constant-expressions.
-// Constant-index-expressions can include loop indices as defined in
-// GLSL ES 1.0 spec, Appendix A, section 4.
-// The following are constant-index-expressions:
-// - Constant expressions
-// - Loop indices as defined in section 4
-// - Expressions composed of both of the above
-class ValidateConstIndexExpr : public TIntermTraverser {
-public:
-    ValidateConstIndexExpr(const TLoopStack& stack)
-        : mValid(true), mLoopStack(stack) {}
-
-    // Returns true if the parsed node represents a constant index expression.
-    bool isValid() const { return mValid; }
-
-    virtual void visitSymbol(TIntermSymbol* symbol) {
-        // Only constants and loop indices are allowed in a
-        // constant index expression.
-        if (mValid) {
-            mValid = (symbol->getQualifier() == EvqConst) ||
-                     IsLoopIndex(symbol, mLoopStack);
-        }
-    }
-
-private:
-    bool mValid;
-    const TLoopStack& mLoopStack;
-};
-
-// Traverses a node to check if it uses a loop index.
-// If an int loop index is used in its body as a sampler array index,
-// mark the loop for unroll.
-class ValidateLoopIndexExpr : public TIntermTraverser {
-public:
-    ValidateLoopIndexExpr(TLoopStack& stack)
-        : mUsesFloatLoopIndex(false),
-          mUsesIntLoopIndex(false),
-          mLoopStack(stack) {}
-
-    bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; }
-    bool usesIntLoopIndex() const { return mUsesIntLoopIndex; }
-
-    virtual void visitSymbol(TIntermSymbol* symbol) {
-        if (IsLoopIndex(symbol, mLoopStack)) {
-            switch (symbol->getBasicType()) {
-              case EbtFloat:
-                mUsesFloatLoopIndex = true;
-                break;
-              case EbtInt:
-                mUsesIntLoopIndex = true;
-                MarkLoopForUnroll(symbol, mLoopStack);
-                break;
-              default:
-                UNREACHABLE();
-            }
-        }
-    }
-
-private:
-    bool mUsesFloatLoopIndex;
-    bool mUsesIntLoopIndex;
-    TLoopStack& mLoopStack;
-};
-}  // namespace
-
-ValidateLimitations::ValidateLimitations(ShShaderType shaderType,
-                                         TInfoSinkBase& sink)
-    : mShaderType(shaderType),
-      mSink(sink),
-      mNumErrors(0)
-{
-}
-
-bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node)
-{
-    // Check if loop index is modified in the loop body.
-    validateOperation(node, node->getLeft());
-
-    // Check indexing.
-    switch (node->getOp()) {
-      case EOpIndexDirect:
-        validateIndexing(node);
-        break;
-      case EOpIndexIndirect:
-#if defined(__APPLE__)
-        // Loop unrolling is a work-around for a Mac Cg compiler bug where it
-        // crashes when a sampler array's index is also the loop index.
-        // Once Apple fixes this bug, we should remove the code in this CL.
-        // See http://codereview.appspot.com/4331048/.
-        if ((node->getLeft() != NULL) && (node->getRight() != NULL) &&
-            (node->getLeft()->getAsSymbolNode())) {
-            TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode();
-            if (IsSampler(symbol->getBasicType()) && symbol->isArray()) {
-                ValidateLoopIndexExpr validate(mLoopStack);
-                node->getRight()->traverse(&validate);
-                if (validate.usesFloatLoopIndex()) {
-                    error(node->getLine(),
-                          "sampler array index is float loop index",
-                          "for");
-                }
-            }
-        }
-#endif
-        validateIndexing(node);
-        break;
-      default: break;
-    }
-    return true;
-}
-
-bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node)
-{
-    // Check if loop index is modified in the loop body.
-    validateOperation(node, node->getOperand());
-
-    return true;
-}
-
-bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node)
-{
-    switch (node->getOp()) {
-      case EOpFunctionCall:
-        validateFunctionCall(node);
-        break;
-      default:
-        break;
-    }
-    return true;
-}
-
-bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node)
-{
-    if (!validateLoopType(node))
-        return false;
-
-    TLoopInfo info;
-    memset(&info, 0, sizeof(TLoopInfo));
-    info.loop = node;
-    if (!validateForLoopHeader(node, &info))
-        return false;
-
-    TIntermNode* body = node->getBody();
-    if (body != NULL) {
-        mLoopStack.push_back(info);
-        body->traverse(this);
-        mLoopStack.pop_back();
-    }
-
-    // The loop is fully processed - no need to visit children.
-    return false;
-}
-
-void ValidateLimitations::error(TSourceLoc loc,
-                                const char *reason, const char* token)
-{
-    mSink.prefix(EPrefixError);
-    mSink.location(loc);
-    mSink << "'" << token << "' : " << reason << "\n";
-    ++mNumErrors;
-}
-
-bool ValidateLimitations::withinLoopBody() const
-{
-    return !mLoopStack.empty();
-}
-
-bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const
-{
-    return IsLoopIndex(symbol, mLoopStack);
-}
-
-bool ValidateLimitations::validateLoopType(TIntermLoop* node) {
-    TLoopType type = node->getType();
-    if (type == ELoopFor)
-        return true;
-
-    // Reject while and do-while loops.
-    error(node->getLine(),
-          "This type of loop is not allowed",
-          type == ELoopWhile ? "while" : "do");
-    return false;
-}
-
-bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node,
-                                                TLoopInfo* info)
-{
-    ASSERT(node->getType() == ELoopFor);
-
-    //
-    // The for statement has the form:
-    //    for ( init-declaration ; condition ; expression ) statement
-    //
-    if (!validateForLoopInit(node, info))
-        return false;
-    if (!validateForLoopCond(node, info))
-        return false;
-    if (!validateForLoopExpr(node, info))
-        return false;
-
-    return true;
-}
-
-bool ValidateLimitations::validateForLoopInit(TIntermLoop* node,
-                                              TLoopInfo* info)
-{
-    TIntermNode* init = node->getInit();
-    if (init == NULL) {
-        error(node->getLine(), "Missing init declaration", "for");
-        return false;
-    }
-
-    //
-    // init-declaration has the form:
-    //     type-specifier identifier = constant-expression
-    //
-    TIntermAggregate* decl = init->getAsAggregate();
-    if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) {
-        error(init->getLine(), "Invalid init declaration", "for");
-        return false;
-    }
-    // To keep things simple do not allow declaration list.
-    TIntermSequence& declSeq = decl->getSequence();
-    if (declSeq.size() != 1) {
-        error(decl->getLine(), "Invalid init declaration", "for");
-        return false;
-    }
-    TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
-    if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) {
-        error(decl->getLine(), "Invalid init declaration", "for");
-        return false;
-    }
-    TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
-    if (symbol == NULL) {
-        error(declInit->getLine(), "Invalid init declaration", "for");
-        return false;
-    }
-    // The loop index has type int or float.
-    TBasicType type = symbol->getBasicType();
-    if ((type != EbtInt) && (type != EbtFloat)) {
-        error(symbol->getLine(),
-              "Invalid type for loop index", getBasicString(type));
-        return false;
-    }
-    // The loop index is initialized with constant expression.
-    if (!isConstExpr(declInit->getRight())) {
-        error(declInit->getLine(),
-              "Loop index cannot be initialized with non-constant expression",
-              symbol->getSymbol().c_str());
-        return false;
-    }
-
-    info->index.id = symbol->getId();
-    return true;
-}
-
-bool ValidateLimitations::validateForLoopCond(TIntermLoop* node,
-                                              TLoopInfo* info)
-{
-    TIntermNode* cond = node->getCondition();
-    if (cond == NULL) {
-        error(node->getLine(), "Missing condition", "for");
-        return false;
-    }
-    //
-    // condition has the form:
-    //     loop_index relational_operator constant_expression
-    //
-    TIntermBinary* binOp = cond->getAsBinaryNode();
-    if (binOp == NULL) {
-        error(node->getLine(), "Invalid condition", "for");
-        return false;
-    }
-    // Loop index should be to the left of relational operator.
-    TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode();
-    if (symbol == NULL) {
-        error(binOp->getLine(), "Invalid condition", "for");
-        return false;
-    }
-    if (symbol->getId() != info->index.id) {
-        error(symbol->getLine(),
-              "Expected loop index", symbol->getSymbol().c_str());
-        return false;
-    }
-    // Relational operator is one of: > >= < <= == or !=.
-    switch (binOp->getOp()) {
-      case EOpEqual:
-      case EOpNotEqual:
-      case EOpLessThan:
-      case EOpGreaterThan:
-      case EOpLessThanEqual:
-      case EOpGreaterThanEqual:
-        break;
-      default:
-        error(binOp->getLine(),
-              "Invalid relational operator",
-              getOperatorString(binOp->getOp()));
-        break;
-    }
-    // Loop index must be compared with a constant.
-    if (!isConstExpr(binOp->getRight())) {
-        error(binOp->getLine(),
-              "Loop index cannot be compared with non-constant expression",
-              symbol->getSymbol().c_str());
-        return false;
-    }
-
-    return true;
-}
-
-bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node,
-                                              TLoopInfo* info)
-{
-    TIntermNode* expr = node->getExpression();
-    if (expr == NULL) {
-        error(node->getLine(), "Missing expression", "for");
-        return false;
-    }
-
-    // for expression has one of the following forms:
-    //     loop_index++
-    //     loop_index--
-    //     loop_index += constant_expression
-    //     loop_index -= constant_expression
-    //     ++loop_index
-    //     --loop_index
-    // The last two forms are not specified in the spec, but I am assuming
-    // its an oversight.
-    TIntermUnary* unOp = expr->getAsUnaryNode();
-    TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
-
-    TOperator op = EOpNull;
-    TIntermSymbol* symbol = NULL;
-    if (unOp != NULL) {
-        op = unOp->getOp();
-        symbol = unOp->getOperand()->getAsSymbolNode();
-    } else if (binOp != NULL) {
-        op = binOp->getOp();
-        symbol = binOp->getLeft()->getAsSymbolNode();
-    }
-
-    // The operand must be loop index.
-    if (symbol == NULL) {
-        error(expr->getLine(), "Invalid expression", "for");
-        return false;
-    }
-    if (symbol->getId() != info->index.id) {
-        error(symbol->getLine(),
-              "Expected loop index", symbol->getSymbol().c_str());
-        return false;
-    }
-
-    // The operator is one of: ++ -- += -=.
-    switch (op) {
-        case EOpPostIncrement:
-        case EOpPostDecrement:
-        case EOpPreIncrement:
-        case EOpPreDecrement:
-            ASSERT((unOp != NULL) && (binOp == NULL));
-            break;
-        case EOpAddAssign:
-        case EOpSubAssign:
-            ASSERT((unOp == NULL) && (binOp != NULL));
-            break;
-        default:
-            error(expr->getLine(), "Invalid operator", getOperatorString(op));
-            return false;
-    }
-
-    // Loop index must be incremented/decremented with a constant.
-    if (binOp != NULL) {
-        if (!isConstExpr(binOp->getRight())) {
-            error(binOp->getLine(),
-                  "Loop index cannot be modified by non-constant expression",
-                  symbol->getSymbol().c_str());
-            return false;
-        }
-    }
-
-    return true;
-}
-
-bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
-{
-    ASSERT(node->getOp() == EOpFunctionCall);
-
-    // If not within loop body, there is nothing to check.
-    if (!withinLoopBody())
-        return true;
-
-    // List of param indices for which loop indices are used as argument.
-    typedef std::vector<size_t> ParamIndex;
-    ParamIndex pIndex;
-    TIntermSequence& params = node->getSequence();
-    for (TIntermSequence::size_type i = 0; i < params.size(); ++i) {
-        TIntermSymbol* symbol = params[i]->getAsSymbolNode();
-        if (symbol && isLoopIndex(symbol))
-            pIndex.push_back(i);
-    }
-    // If none of the loop indices are used as arguments,
-    // there is nothing to check.
-    if (pIndex.empty())
-        return true;
-
-    bool valid = true;
-    TSymbolTable& symbolTable = GlobalParseContext->symbolTable;
-    TSymbol* symbol = symbolTable.find(node->getName());
-    ASSERT(symbol && symbol->isFunction());
-    TFunction* function = static_cast<TFunction*>(symbol);
-    for (ParamIndex::const_iterator i = pIndex.begin();
-         i != pIndex.end(); ++i) {
-        const TParameter& param = function->getParam(*i);
-        TQualifier qual = param.type->getQualifier();
-        if ((qual == EvqOut) || (qual == EvqInOut)) {
-            error(params[*i]->getLine(),
-                  "Loop index cannot be used as argument to a function out or inout parameter",
-                  params[*i]->getAsSymbolNode()->getSymbol().c_str());
-            valid = false;
-        }
-    }
-
-    return valid;
-}
-
-bool ValidateLimitations::validateOperation(TIntermOperator* node,
-                                            TIntermNode* operand) {
-    // Check if loop index is modified in the loop body.
-    if (!withinLoopBody() || !node->modifiesState())
-        return true;
-
-    const TIntermSymbol* symbol = operand->getAsSymbolNode();
-    if (symbol && isLoopIndex(symbol)) {
-        error(node->getLine(),
-              "Loop index cannot be statically assigned to within the body of the loop",
-              symbol->getSymbol().c_str());
-    }
-    return true;
-}
-
-bool ValidateLimitations::isConstExpr(TIntermNode* node)
-{
-    ASSERT(node != NULL);
-    return node->getAsConstantUnion() != NULL;
-}
-
-bool ValidateLimitations::isConstIndexExpr(TIntermNode* node)
-{
-    ASSERT(node != NULL);
-
-    ValidateConstIndexExpr validate(mLoopStack);
-    node->traverse(&validate);
-    return validate.isValid();
-}
-
-bool ValidateLimitations::validateIndexing(TIntermBinary* node)
-{
-    ASSERT((node->getOp() == EOpIndexDirect) ||
-           (node->getOp() == EOpIndexIndirect));
-
-    bool valid = true;
-    TIntermTyped* index = node->getRight();
-    // The index expression must have integral type.
-    if (!index->isScalar() || (index->getBasicType() != EbtInt)) {
-        error(index->getLine(),
-              "Index expression must have integral type",
-              index->getCompleteString().c_str());
-        valid = false;
-    }
-    // The index expession must be a constant-index-expression unless
-    // the operand is a uniform in a vertex shader.
-    TIntermTyped* operand = node->getLeft();
-    bool skip = (mShaderType == SH_VERTEX_SHADER) &&
-                (operand->getQualifier() == EvqUniform);
-    if (!skip && !isConstIndexExpr(index)) {
-        error(index->getLine(), "Index expression must be constant", "[]");
-        valid = false;
-    }
-    return valid;
-}
-
diff --git a/src/third_party/angle/src/compiler/ValidateLimitations.h b/src/third_party/angle/src/compiler/ValidateLimitations.h
deleted file mode 100644
index a835cb3..0000000
--- a/src/third_party/angle/src/compiler/ValidateLimitations.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "GLSLANG/ShaderLang.h"
-#include "compiler/intermediate.h"
-
-class TInfoSinkBase;
-
-struct TLoopInfo {
-    struct TIndex {
-        int id;  // symbol id.
-    } index;
-    TIntermLoop* loop;
-};
-typedef TVector<TLoopInfo> TLoopStack;
-
-// Traverses intermediate tree to ensure that the shader does not exceed the
-// minimum functionality mandated in GLSL 1.0 spec, Appendix A.
-class ValidateLimitations : public TIntermTraverser {
-public:
-    ValidateLimitations(ShShaderType shaderType, TInfoSinkBase& sink);
-
-    int numErrors() const { return mNumErrors; }
-
-    virtual bool visitBinary(Visit, TIntermBinary*);
-    virtual bool visitUnary(Visit, TIntermUnary*);
-    virtual bool visitAggregate(Visit, TIntermAggregate*);
-    virtual bool visitLoop(Visit, TIntermLoop*);
-
-private:
-    void error(TSourceLoc loc, const char *reason, const char* token);
-
-    bool withinLoopBody() const;
-    bool isLoopIndex(const TIntermSymbol* symbol) const;
-    bool validateLoopType(TIntermLoop* node);
-    bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info);
-    bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info);
-    bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info);
-    bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info);
-    // Returns true if none of the loop indices is used as the argument to
-    // the given function out or inout parameter.
-    bool validateFunctionCall(TIntermAggregate* node);
-    bool validateOperation(TIntermOperator* node, TIntermNode* operand);
-
-    // Returns true if indexing does not exceed the minimum functionality
-    // mandated in GLSL 1.0 spec, Appendix A, Section 5.
-    bool isConstExpr(TIntermNode* node);
-    bool isConstIndexExpr(TIntermNode* node);
-    bool validateIndexing(TIntermBinary* node);
-
-    ShShaderType mShaderType;
-    TInfoSinkBase& mSink;
-    int mNumErrors;
-    TLoopStack mLoopStack;
-};
-
diff --git a/src/third_party/angle/src/compiler/VariableInfo.cpp b/src/third_party/angle/src/compiler/VariableInfo.cpp
deleted file mode 100644
index 84db807..0000000
--- a/src/third_party/angle/src/compiler/VariableInfo.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/VariableInfo.h"
-
-static TString arrayBrackets(int index)
-{
-    TStringStream stream;
-    stream << "[" << index << "]";
-    return stream.str();
-}
-
-// Returns the data type for an attribute or uniform.
-static ShDataType getVariableDataType(const TType& type)
-{
-    switch (type.getBasicType()) {
-      case EbtFloat:
-          if (type.isMatrix()) {
-              switch (type.getNominalSize()) {
-                case 2: return SH_FLOAT_MAT2;
-                case 3: return SH_FLOAT_MAT3;
-                case 4: return SH_FLOAT_MAT4;
-                default: UNREACHABLE();
-              }
-          } else if (type.isVector()) {
-              switch (type.getNominalSize()) {
-                case 2: return SH_FLOAT_VEC2;
-                case 3: return SH_FLOAT_VEC3;
-                case 4: return SH_FLOAT_VEC4;
-                default: UNREACHABLE();
-              }
-          } else {
-              return SH_FLOAT;
-          }
-      case EbtInt:
-          if (type.isMatrix()) {
-              UNREACHABLE();
-          } else if (type.isVector()) {
-              switch (type.getNominalSize()) {
-                case 2: return SH_INT_VEC2;
-                case 3: return SH_INT_VEC3;
-                case 4: return SH_INT_VEC4;
-                default: UNREACHABLE();
-              }
-          } else {
-              return SH_INT;
-          }
-      case EbtBool:
-          if (type.isMatrix()) {
-              UNREACHABLE();
-          } else if (type.isVector()) {
-              switch (type.getNominalSize()) {
-                case 2: return SH_BOOL_VEC2;
-                case 3: return SH_BOOL_VEC3;
-                case 4: return SH_BOOL_VEC4;
-                default: UNREACHABLE();
-              }
-          } else {
-              return SH_BOOL;
-          }
-      case EbtSampler2D: return SH_SAMPLER_2D;
-      case EbtSamplerCube: return SH_SAMPLER_CUBE;
-      case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES;
-      case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB;
-      default: UNREACHABLE();
-    }
-    return SH_NONE;
-}
-
-static void getBuiltInVariableInfo(const TType& type,
-                                   const TString& name,
-                                   const TString& mappedName,
-                                   TVariableInfoList& infoList);
-static void getUserDefinedVariableInfo(const TType& type,
-                                       const TString& name,
-                                       const TString& mappedName,
-                                       TVariableInfoList& infoList,
-                                       ShHashFunction64 hashFunction);
-
-// Returns info for an attribute or uniform.
-static void getVariableInfo(const TType& type,
-                            const TString& name,
-                            const TString& mappedName,
-                            TVariableInfoList& infoList,
-                            ShHashFunction64 hashFunction)
-{
-    if (type.getBasicType() == EbtStruct) {
-        if (type.isArray()) {
-            for (int i = 0; i < type.getArraySize(); ++i) {
-                TString lname = name + arrayBrackets(i);
-                TString lmappedName = mappedName + arrayBrackets(i);
-                getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
-            }
-        } else {
-            getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
-        }
-    } else {
-        getBuiltInVariableInfo(type, name, mappedName, infoList);
-    }
-}
-
-void getBuiltInVariableInfo(const TType& type,
-                            const TString& name,
-                            const TString& mappedName,
-                            TVariableInfoList& infoList)
-{
-    ASSERT(type.getBasicType() != EbtStruct);
-
-    TVariableInfo varInfo;
-    if (type.isArray()) {
-        varInfo.name = (name + "[0]").c_str();
-        varInfo.mappedName = (mappedName + "[0]").c_str();
-        varInfo.size = type.getArraySize();
-    } else {
-        varInfo.name = name.c_str();
-        varInfo.mappedName = mappedName.c_str();
-        varInfo.size = 1;
-    }
-    varInfo.type = getVariableDataType(type);
-    infoList.push_back(varInfo);
-}
-
-void getUserDefinedVariableInfo(const TType& type,
-                                const TString& name,
-                                const TString& mappedName,
-                                TVariableInfoList& infoList,
-                                ShHashFunction64 hashFunction)
-{
-    ASSERT(type.getBasicType() == EbtStruct);
-
-    const TFieldList& fields = type.getStruct()->fields();
-    for (size_t i = 0; i < fields.size(); ++i) {
-        const TType& fieldType = *(fields[i]->type());
-        const TString& fieldName = fields[i]->name();
-        getVariableInfo(fieldType,
-                        name + "." + fieldName,
-                        mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
-                        infoList,
-                        hashFunction);
-    }
-}
-
-TVariableInfo::TVariableInfo()
-{
-}
-
-TVariableInfo::TVariableInfo(ShDataType type, int size)
-    : type(type),
-      size(size)
-{
-}
-
-CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
-                                               TVariableInfoList& uniforms,
-                                               ShHashFunction64 hashFunction)
-    : mAttribs(attribs),
-      mUniforms(uniforms),
-      mHashFunction(hashFunction)
-{
-}
-
-// We are only interested in attribute and uniform variable declaration.
-void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
-{
-}
-
-void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
-{
-}
-
-bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
-{
-    return false;
-}
-
-bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
-{
-    return false;
-}
-
-bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
-{
-    return false;
-}
-
-bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
-{
-    bool visitChildren = false;
-
-    switch (node->getOp())
-    {
-    case EOpSequence:
-        // We need to visit sequence children to get to variable declarations.
-        visitChildren = true;
-        break;
-    case EOpDeclaration: {
-        const TIntermSequence& sequence = node->getSequence();
-        TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
-        if (qualifier == EvqAttribute || qualifier == EvqUniform)
-        {
-            TVariableInfoList& infoList = qualifier == EvqAttribute ?
-                mAttribs : mUniforms;
-            for (TIntermSequence::const_iterator i = sequence.begin();
-                 i != sequence.end(); ++i)
-            {
-                const TIntermSymbol* variable = (*i)->getAsSymbolNode();
-                // The only case in which the sequence will not contain a
-                // TIntermSymbol node is initialization. It will contain a
-                // TInterBinary node in that case. Since attributes and unifroms
-                // cannot be initialized in a shader, we must have only
-                // TIntermSymbol nodes in the sequence.
-                ASSERT(variable != NULL);
-                TString processedSymbol;
-                if (mHashFunction == NULL)
-                    processedSymbol = variable->getSymbol();
-                else
-                    processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
-                getVariableInfo(variable->getType(),
-                                variable->getOriginalSymbol(),
-                                processedSymbol,
-                                infoList,
-                                mHashFunction);
-            }
-        }
-        break;
-    }
-    default: break;
-    }
-
-    return visitChildren;
-}
-
-bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
-{
-    return false;
-}
-
-bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
-{
-    return false;
-}
-
diff --git a/src/third_party/angle/src/compiler/VariableInfo.h b/src/third_party/angle/src/compiler/VariableInfo.h
deleted file mode 100644
index 4130a58..0000000
--- a/src/third_party/angle/src/compiler/VariableInfo.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_VARIABLE_INFO_H_
-#define COMPILER_VARIABLE_INFO_H_
-
-#include "GLSLANG/ShaderLang.h"
-#include "compiler/intermediate.h"
-
-// Provides information about a variable.
-// It is currently being used to store info about active attribs and uniforms.
-struct TVariableInfo {
-    TVariableInfo(ShDataType type, int size);
-    TVariableInfo();
-
-    TPersistString name;
-    TPersistString mappedName;
-    ShDataType type;
-    int size;
-};
-typedef std::vector<TVariableInfo> TVariableInfoList;
-
-// Traverses intermediate tree to collect all attributes and uniforms.
-class CollectAttribsUniforms : public TIntermTraverser {
-public:
-    CollectAttribsUniforms(TVariableInfoList& attribs,
-                           TVariableInfoList& uniforms,
-                           ShHashFunction64 hashFunction);
-
-    virtual void visitSymbol(TIntermSymbol*);
-    virtual void visitConstantUnion(TIntermConstantUnion*);
-    virtual bool visitBinary(Visit, TIntermBinary*);
-    virtual bool visitUnary(Visit, TIntermUnary*);
-    virtual bool visitSelection(Visit, TIntermSelection*);
-    virtual bool visitAggregate(Visit, TIntermAggregate*);
-    virtual bool visitLoop(Visit, TIntermLoop*);
-    virtual bool visitBranch(Visit, TIntermBranch*);
-
-private:
-    TVariableInfoList& mAttribs;
-    TVariableInfoList& mUniforms;
-
-    ShHashFunction64 mHashFunction;
-};
-
-#endif  // COMPILER_VARIABLE_INFO_H_
diff --git a/src/third_party/angle/src/compiler/VariablePacker.cpp b/src/third_party/angle/src/compiler/VariablePacker.cpp
deleted file mode 100644
index 8957287..0000000
--- a/src/third_party/angle/src/compiler/VariablePacker.cpp
+++ /dev/null
@@ -1,297 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-#include "compiler/VariablePacker.h"
-
-#include <algorithm>
-#include "compiler/ShHandle.h"
-
-namespace {
-int GetSortOrder(ShDataType type)
-{
-    switch (type) {
-        case SH_FLOAT_MAT4:
-            return 0;
-        case SH_FLOAT_MAT2:
-            return 1;
-        case SH_FLOAT_VEC4:
-        case SH_INT_VEC4:
-        case SH_BOOL_VEC4:
-            return 2;
-        case SH_FLOAT_MAT3:
-            return 3;
-        case SH_FLOAT_VEC3:
-        case SH_INT_VEC3:
-        case SH_BOOL_VEC3:
-            return 4;
-        case SH_FLOAT_VEC2:
-        case SH_INT_VEC2:
-        case SH_BOOL_VEC2:
-            return 5;
-        case SH_FLOAT:
-        case SH_INT:
-        case SH_BOOL:
-        case SH_SAMPLER_2D:
-        case SH_SAMPLER_CUBE:
-        case SH_SAMPLER_EXTERNAL_OES:
-        case SH_SAMPLER_2D_RECT_ARB:
-            return 6;
-        default:
-            ASSERT(false);
-            return 7;
-    }
-}
-}    // namespace
-
-int VariablePacker::GetNumComponentsPerRow(ShDataType type)
-{
-    switch (type) {
-        case SH_FLOAT_MAT4:
-        case SH_FLOAT_MAT2:
-        case SH_FLOAT_VEC4:
-        case SH_INT_VEC4:
-        case SH_BOOL_VEC4:
-            return 4;
-        case SH_FLOAT_MAT3:
-        case SH_FLOAT_VEC3:
-        case SH_INT_VEC3:
-        case SH_BOOL_VEC3:
-            return 3;
-        case SH_FLOAT_VEC2:
-        case SH_INT_VEC2:
-        case SH_BOOL_VEC2:
-            return 2;
-        case SH_FLOAT:
-        case SH_INT:
-        case SH_BOOL:
-        case SH_SAMPLER_2D:
-        case SH_SAMPLER_CUBE:
-        case SH_SAMPLER_EXTERNAL_OES:
-        case SH_SAMPLER_2D_RECT_ARB:
-            return 1;
-        default:
-            ASSERT(false);
-            return 5;
-    }
-}
-
-int VariablePacker::GetNumRows(ShDataType type)
-{
-    switch (type) {
-        case SH_FLOAT_MAT4:
-            return 4;
-        case SH_FLOAT_MAT3:
-            return 3;
-        case SH_FLOAT_MAT2:
-            return 2;
-        case SH_FLOAT_VEC4:
-        case SH_INT_VEC4:
-        case SH_BOOL_VEC4:
-        case SH_FLOAT_VEC3:
-        case SH_INT_VEC3:
-        case SH_BOOL_VEC3:
-        case SH_FLOAT_VEC2:
-        case SH_INT_VEC2:
-        case SH_BOOL_VEC2:
-        case SH_FLOAT:
-        case SH_INT:
-        case SH_BOOL:
-        case SH_SAMPLER_2D:
-        case SH_SAMPLER_CUBE:
-        case SH_SAMPLER_EXTERNAL_OES:
-        case SH_SAMPLER_2D_RECT_ARB:
-            return 1;
-        default:
-            ASSERT(false);
-            return 100000;
-    }
-}
-
-struct TVariableInfoComparer {
-    bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const
-    {
-        int lhsSortOrder = GetSortOrder(lhs.type);
-        int rhsSortOrder = GetSortOrder(rhs.type);
-        if (lhsSortOrder != rhsSortOrder) {
-            return lhsSortOrder < rhsSortOrder;
-        }
-        // Sort by largest first.
-        return lhs.size > rhs.size;
-    }
-};
-
-unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
-{
-    return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
-                    kColumnMask) >> column;
-}
-
-void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
-{
-    unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
-    for (int r = 0; r < numRows; ++r) {
-        int row = topRow + r;
-        ASSERT((rows_[row] & columnFlags) == 0);
-        rows_[row] |= columnFlags;
-    }
-}
-
-bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
-{
-    ASSERT(destRow);
-
-    for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
-         ++topNonFullRow_) {
-    }
-
-    for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
-         --bottomNonFullRow_) {
-    }
-
-    if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
-        return false;
-    }
-
-    unsigned columnFlags = makeColumnFlags(column, 1);
-    int topGoodRow = 0;
-    int smallestGoodTop = -1;
-    int smallestGoodSize = maxRows_ + 1;
-    int bottomRow = bottomNonFullRow_ + 1;
-    bool found = false;
-    for (int row = topNonFullRow_; row <= bottomRow; ++row) {
-        bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
-        if (rowEmpty) {
-            if (!found) {
-                topGoodRow = row;
-                found = true;
-            }
-        } else {
-            if (found) {
-                int size = row - topGoodRow;
-                if (size >= numRows && size < smallestGoodSize) {
-                    smallestGoodSize = size;
-                    smallestGoodTop = topGoodRow;
-                }
-            }
-            found = false;
-        }
-    }
-    if (smallestGoodTop < 0) {
-        return false;
-    }
-
-    *destRow = smallestGoodTop;
-    if (destSize) {
-        *destSize = smallestGoodSize;
-    }
-    return true;
-}
-
-bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables)
-{
-    ASSERT(maxVectors > 0);
-    maxRows_ = maxVectors;
-    topNonFullRow_ = 0;
-    bottomNonFullRow_ = maxRows_ - 1;
-    TVariableInfoList variables(in_variables);
-
-    // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
-    // order by type, then by size of array, largest first.
-    std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
-    rows_.clear();
-    rows_.resize(maxVectors, 0);
-
-    // Packs the 4 column variables.
-    size_t ii = 0;
-    for (; ii < variables.size(); ++ii) {
-        const TVariableInfo& variable = variables[ii];
-        if (GetNumComponentsPerRow(variable.type) != 4) {
-            break;
-        }
-        topNonFullRow_ += GetNumRows(variable.type) * variable.size;
-    }
-
-    if (topNonFullRow_ > maxRows_) {
-        return false;
-    }
-
-    // Packs the 3 column variables.
-    int num3ColumnRows = 0;
-    for (; ii < variables.size(); ++ii) {
-        const TVariableInfo& variable = variables[ii];
-        if (GetNumComponentsPerRow(variable.type) != 3) {
-            break;
-        }
-        num3ColumnRows += GetNumRows(variable.type) * variable.size;
-    }
-
-    if (topNonFullRow_ + num3ColumnRows > maxRows_) {
-        return false;
-    }
-
-    fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
-
-    // Packs the 2 column variables.
-    int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
-    int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
-    int rowsAvailableInColumns01 = twoColumnRowsAvailable;
-    int rowsAvailableInColumns23 = twoColumnRowsAvailable;
-    for (; ii < variables.size(); ++ii) {
-        const TVariableInfo& variable = variables[ii];
-        if (GetNumComponentsPerRow(variable.type) != 2) {
-            break;
-        }
-        int numRows = GetNumRows(variable.type) * variable.size;
-        if (numRows <= rowsAvailableInColumns01) {
-            rowsAvailableInColumns01 -= numRows;
-        } else if (numRows <= rowsAvailableInColumns23) {
-            rowsAvailableInColumns23 -= numRows;
-        } else {
-            return false;
-        }
-    }
-
-    int numRowsUsedInColumns01 =
-        twoColumnRowsAvailable - rowsAvailableInColumns01;
-    int numRowsUsedInColumns23 =
-        twoColumnRowsAvailable - rowsAvailableInColumns23;
-    fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
-    fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
-                2, 2);
-
-    // Packs the 1 column variables.
-    for (; ii < variables.size(); ++ii) {
-        const TVariableInfo& variable = variables[ii];
-        ASSERT(1 == GetNumComponentsPerRow(variable.type));
-        int numRows = GetNumRows(variable.type) * variable.size;
-        int smallestColumn = -1;
-        int smallestSize = maxRows_ + 1;
-        int topRow = -1;
-        for (int column = 0; column < kNumColumns; ++column) {
-            int row = 0;
-            int size = 0;
-            if (searchColumn(column, numRows, &row, &size)) {
-                if (size < smallestSize) {
-                    smallestSize = size;
-                    smallestColumn = column;
-                    topRow = row;
-                }
-            }
-        }
-
-        if (smallestColumn < 0) {
-            return false;
-        }
-
-        fillColumns(topRow, numRows, smallestColumn, 1);
-    }
-
-    ASSERT(variables.size() == ii);
-
-    return true;
-}
-
-
-
diff --git a/src/third_party/angle/src/compiler/VariablePacker.h b/src/third_party/angle/src/compiler/VariablePacker.h
deleted file mode 100644
index 8987066..0000000
--- a/src/third_party/angle/src/compiler/VariablePacker.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _VARIABLEPACKER_INCLUDED_
-#define _VARIABLEPACKER_INCLUDED_
-
-#include <vector>
-#include "compiler/ShHandle.h"
-
-class VariablePacker {
- public:
-    // Returns true if the passed in variables pack in maxVectors following
-    // the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
-    bool CheckVariablesWithinPackingLimits(
-        int maxVectors,
-        const TVariableInfoList& in_variables);
-
-    // Gets how many components in a row a data type takes.
-    static int GetNumComponentsPerRow(ShDataType type);
-
-    // Gets how many rows a data type takes.
-    static int GetNumRows(ShDataType type);
-
- private:
-    static const int kNumColumns = 4;
-    static const unsigned kColumnMask = (1 << kNumColumns) - 1;
-
-    unsigned makeColumnFlags(int column, int numComponentsPerRow);
-    void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
-    bool searchColumn(int column, int numRows, int* destRow, int* destSize);
-
-    int topNonFullRow_;
-    int bottomNonFullRow_;
-    int maxRows_;
-    std::vector<unsigned> rows_;
-};
-
-#endif // _VARIABLEPACKER_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/VersionGLSL.cpp b/src/third_party/angle/src/compiler/VersionGLSL.cpp
deleted file mode 100644
index 7a82bb4..0000000
--- a/src/third_party/angle/src/compiler/VersionGLSL.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/VersionGLSL.h"
-
-static const int GLSL_VERSION_110 = 110;
-static const int GLSL_VERSION_120 = 120;
-
-// We need to scan for the following:
-// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
-//    but only at the global scope.
-// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
-//    but inside any scope.
-// 3. Call to a matrix constructor with another matrix as argument.
-//    (These constructors were reserved in GLSL version 1.10.)
-// 4. Arrays as "out" function parameters.
-//    GLSL spec section 6.1.1: "When calling a function, expressions that do
-//    not evaluate to l-values cannot be passed to parameters declared as
-//    out or inout."
-//    GLSL 1.1 section 5.8: "Other binary or unary expressions,
-//    non-dereferenced arrays, function names, swizzles with repeated fields,
-//    and constants cannot be l-values."
-//    GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
-//    are built-in types, entire structures or arrays... are all l-values."
-//
-// TODO(alokp): The following two cases of invariant decalaration get lost
-// during parsing - they do not get carried over to the intermediate tree.
-// Handle these cases:
-// 1. When a pragma is used to force all output variables to be invariant:
-//    - #pragma STDGL invariant(all)
-// 2. When a previously decalared or built-in variable is marked invariant:
-//    - invariant gl_Position;
-//    - varying vec3 color; invariant color;
-//
-TVersionGLSL::TVersionGLSL(ShShaderType type)
-    : mShaderType(type),
-      mVersion(GLSL_VERSION_110)
-{
-}
-
-void TVersionGLSL::visitSymbol(TIntermSymbol* node)
-{
-    if (node->getSymbol() == "gl_PointCoord")
-        updateVersion(GLSL_VERSION_120);
-}
-
-void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*)
-{
-}
-
-bool TVersionGLSL::visitBinary(Visit, TIntermBinary*)
-{
-    return true;
-}
-
-bool TVersionGLSL::visitUnary(Visit, TIntermUnary*)
-{
-    return true;
-}
-
-bool TVersionGLSL::visitSelection(Visit, TIntermSelection*)
-{
-    return true;
-}
-
-bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node)
-{
-    bool visitChildren = true;
-
-    switch (node->getOp()) {
-      case EOpSequence:
-        // We need to visit sequence children to get to global or inner scope.
-        visitChildren = true;
-        break;
-      case EOpDeclaration: {
-        const TIntermSequence& sequence = node->getSequence();
-        TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
-        if ((qualifier == EvqInvariantVaryingIn) ||
-            (qualifier == EvqInvariantVaryingOut)) {
-            updateVersion(GLSL_VERSION_120);
-        }
-        break;
-      }
-      case EOpParameters: {
-        const TIntermSequence& params = node->getSequence();
-        for (TIntermSequence::const_iterator iter = params.begin();
-             iter != params.end(); ++iter)
-        {
-            const TIntermTyped* param = (*iter)->getAsTyped();
-            if (param->isArray())
-            {
-                TQualifier qualifier = param->getQualifier();
-                if ((qualifier == EvqOut) || (qualifier ==  EvqInOut))
-                {
-                    updateVersion(GLSL_VERSION_120);
-                    break;
-                }
-            }
-        }
-        // Fully processed. No need to visit children.
-        visitChildren = false;
-        break;
-      }
-      case EOpConstructMat2:
-      case EOpConstructMat3:
-      case EOpConstructMat4: {
-        const TIntermSequence& sequence = node->getSequence();
-        if (sequence.size() == 1) {
-          TIntermTyped* typed = sequence.front()->getAsTyped();
-          if (typed && typed->isMatrix()) {
-            updateVersion(GLSL_VERSION_120);
-          }
-        }
-        break;
-      }
-
-      default: break;
-    }
-
-    return visitChildren;
-}
-
-bool TVersionGLSL::visitLoop(Visit, TIntermLoop*)
-{
-    return true;
-}
-
-bool TVersionGLSL::visitBranch(Visit, TIntermBranch*)
-{
-    return true;
-}
-
-void TVersionGLSL::updateVersion(int version)
-{
-    mVersion = std::max(version, mVersion);
-}
-
diff --git a/src/third_party/angle/src/compiler/VersionGLSL.h b/src/third_party/angle/src/compiler/VersionGLSL.h
deleted file mode 100644
index 1c1cb1a..0000000
--- a/src/third_party/angle/src/compiler/VersionGLSL.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_VERSIONGLSL_H_
-#define COMPILER_VERSIONGLSL_H_
-
-#include "GLSLANG/ShaderLang.h"
-#include "compiler/intermediate.h"
-
-// Traverses the intermediate tree to return the minimum GLSL version
-// required to legally access all built-in features used in the shader.
-// GLSL 1.1 which is mandated by OpenGL 2.0 provides:
-//   - #version and #extension to declare version and extensions.
-//   - built-in functions refract, exp, and log.
-//   - updated step() to compare x < edge instead of x <= edge.
-// GLSL 1.2 which is mandated by OpenGL 2.1 provides:
-//   - many changes to reduce differences when compared to the ES specification.
-//   - invariant keyword and its support.
-//   - c++ style name hiding rules.
-//   - built-in variable gl_PointCoord for fragment shaders.
-//   - matrix constructors taking matrix as argument.
-//   - array as "out" function parameters
-//
-class TVersionGLSL : public TIntermTraverser {
-public:
-    TVersionGLSL(ShShaderType type);
-
-    // Returns 120 if the following is used the shader:
-    // - "invariant",
-    // - "gl_PointCoord",
-    // - matrix/matrix constructors
-    // - array "out" parameters
-    // Else 110 is returned.
-    int getVersion() { return mVersion; }
-
-    virtual void visitSymbol(TIntermSymbol*);
-    virtual void visitConstantUnion(TIntermConstantUnion*);
-    virtual bool visitBinary(Visit, TIntermBinary*);
-    virtual bool visitUnary(Visit, TIntermUnary*);
-    virtual bool visitSelection(Visit, TIntermSelection*);
-    virtual bool visitAggregate(Visit, TIntermAggregate*);
-    virtual bool visitLoop(Visit, TIntermLoop*);
-    virtual bool visitBranch(Visit, TIntermBranch*);
-
-protected:
-    void updateVersion(int version);
-
-private:
-    ShShaderType mShaderType;
-    int mVersion;
-};
-
-#endif  // COMPILER_VERSIONGLSL_H_
diff --git a/src/third_party/angle/src/compiler/debug.cpp b/src/third_party/angle/src/compiler/debug.cpp
deleted file mode 100644
index 53778bd..0000000
--- a/src/third_party/angle/src/compiler/debug.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// debug.cpp: Debugging utilities.
-
-#include "compiler/debug.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-
-#include "compiler/InitializeParseContext.h"
-#include "compiler/ParseHelper.h"
-
-static const int kTraceBufferLen = 1024;
-
-#ifdef TRACE_ENABLED
-extern "C" {
-void Trace(const char *format, ...) {
-    if (!format) return;
-
-    TParseContext* parseContext = GetGlobalParseContext();
-    if (parseContext) {
-        char buf[kTraceBufferLen];
-        va_list args;
-        va_start(args, format);
-        vsnprintf(buf, kTraceBufferLen, format, args);
-        va_end(args);
-
-        parseContext->trace(buf);
-    }
-}
-}  // extern "C"
-#endif  // TRACE_ENABLED
-
diff --git a/src/third_party/angle/src/compiler/debug.h b/src/third_party/angle/src/compiler/debug.h
deleted file mode 100644
index 7a37151..0000000
--- a/src/third_party/angle/src/compiler/debug.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// debug.h: Debugging utilities.
-
-#ifndef COMPILER_DEBUG_H_
-#define COMPILER_DEBUG_H_
-
-#include <assert.h>
-
-#ifdef _DEBUG
-#define TRACE_ENABLED  // define to enable debug message tracing
-#endif  // _DEBUG
-
-// Outputs text to the debug log
-#ifdef TRACE_ENABLED
-
-#ifdef  __cplusplus
-extern "C" {
-#endif  // __cplusplus
-void Trace(const char* format, ...);
-#ifdef  __cplusplus
-}
-#endif  // __cplusplus
-
-#else   // TRACE_ENABLED
-
-#define Trace(...) ((void)0)
-
-#endif  // TRACE_ENABLED
-
-// A macro asserting a condition and outputting failures to the debug log
-#define ASSERT(expression) do { \
-    if(!(expression)) \
-        Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
-    assert(expression); \
-} while(0)
-
-#define UNIMPLEMENTED() do { \
-    Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \
-    assert(false); \
-} while(0)
-
-#define UNREACHABLE() do { \
-    Trace("Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
-    assert(false); \
-} while(0)
-
-#endif   // COMPILER_DEBUG_H_
-
diff --git a/src/third_party/angle/src/compiler/depgraph/DependencyGraph.cpp b/src/third_party/angle/src/compiler/depgraph/DependencyGraph.cpp
deleted file mode 100644
index ca661d6..0000000
--- a/src/third_party/angle/src/compiler/depgraph/DependencyGraph.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#pragma warning(disable: 4718)
-
-#include "compiler/depgraph/DependencyGraph.h"
-#include "compiler/depgraph/DependencyGraphBuilder.h"
-
-TDependencyGraph::TDependencyGraph(TIntermNode* intermNode)
-{
-    TDependencyGraphBuilder::build(intermNode, this);
-}
-
-TDependencyGraph::~TDependencyGraph()
-{
-    for (TGraphNodeVector::const_iterator iter = mAllNodes.begin(); iter != mAllNodes.end(); ++iter)
-    {
-        TGraphNode* node = *iter;
-        delete node;
-    }
-}
-
-TGraphArgument* TDependencyGraph::createArgument(TIntermAggregate* intermFunctionCall,
-                                                 int argumentNumber)
-{
-    TGraphArgument* argument = new TGraphArgument(intermFunctionCall, argumentNumber);
-    mAllNodes.push_back(argument);
-    return argument;
-}
-
-TGraphFunctionCall* TDependencyGraph::createFunctionCall(TIntermAggregate* intermFunctionCall)
-{
-    TGraphFunctionCall* functionCall = new TGraphFunctionCall(intermFunctionCall);
-    mAllNodes.push_back(functionCall);
-    if (functionCall->getIntermFunctionCall()->isUserDefined())
-        mUserDefinedFunctionCalls.push_back(functionCall);
-    return functionCall;
-}
-
-TGraphSymbol* TDependencyGraph::getOrCreateSymbol(TIntermSymbol* intermSymbol)
-{
-    TSymbolIdMap::const_iterator iter = mSymbolIdMap.find(intermSymbol->getId());
-
-    TGraphSymbol* symbol = NULL;
-
-    if (iter != mSymbolIdMap.end()) {
-        TSymbolIdPair pair = *iter;
-        symbol = pair.second;
-    } else {
-        symbol = new TGraphSymbol(intermSymbol);
-        mAllNodes.push_back(symbol);
-
-        TSymbolIdPair pair(intermSymbol->getId(), symbol);
-        mSymbolIdMap.insert(pair);
-
-        // We save all sampler symbols in a collection, so we can start graph traversals from them quickly.
-        if (IsSampler(intermSymbol->getBasicType()))
-            mSamplerSymbols.push_back(symbol);
-    }
-
-    return symbol;
-}
-
-TGraphSelection* TDependencyGraph::createSelection(TIntermSelection* intermSelection)
-{
-    TGraphSelection* selection = new TGraphSelection(intermSelection);
-    mAllNodes.push_back(selection);
-    return selection;
-}
-
-TGraphLoop* TDependencyGraph::createLoop(TIntermLoop* intermLoop)
-{
-    TGraphLoop* loop = new TGraphLoop(intermLoop);
-    mAllNodes.push_back(loop);
-    return loop;
-}
-
-TGraphLogicalOp* TDependencyGraph::createLogicalOp(TIntermBinary* intermLogicalOp)
-{
-    TGraphLogicalOp* logicalOp = new TGraphLogicalOp(intermLogicalOp);
-    mAllNodes.push_back(logicalOp);
-    return logicalOp;
-}
-
-const char* TGraphLogicalOp::getOpString() const
-{
-    const char* opString = NULL;
-    switch (getIntermLogicalOp()->getOp()) {
-        case EOpLogicalAnd: opString = "and"; break;
-        case EOpLogicalOr: opString = "or"; break;
-        default: opString = "unknown"; break;
-    }
-    return opString;
-}
diff --git a/src/third_party/angle/src/compiler/depgraph/DependencyGraph.h b/src/third_party/angle/src/compiler/depgraph/DependencyGraph.h
deleted file mode 100644
index 5a9c35d..0000000
--- a/src/third_party/angle/src/compiler/depgraph/DependencyGraph.h
+++ /dev/null
@@ -1,212 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H
-#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H
-
-#include "compiler/intermediate.h"
-
-#include <set>
-#include <stack>
-
-class TGraphNode;
-class TGraphParentNode;
-class TGraphArgument;
-class TGraphFunctionCall;
-class TGraphSymbol;
-class TGraphSelection;
-class TGraphLoop;
-class TGraphLogicalOp;
-class TDependencyGraphTraverser;
-class TDependencyGraphOutput;
-
-typedef std::set<TGraphNode*> TGraphNodeSet;
-typedef std::vector<TGraphNode*> TGraphNodeVector;
-typedef std::vector<TGraphSymbol*> TGraphSymbolVector;
-typedef std::vector<TGraphFunctionCall*> TFunctionCallVector;
-
-//
-// Base class for all dependency graph nodes.
-//
-class TGraphNode {
-public:
-    TGraphNode(TIntermNode* node) : intermNode(node) {}
-    virtual ~TGraphNode() {}
-    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
-protected:
-    TIntermNode* intermNode;
-};
-
-//
-// Base class for dependency graph nodes that may have children.
-//
-class TGraphParentNode : public TGraphNode {
-public:
-    TGraphParentNode(TIntermNode* node) : TGraphNode(node) {}
-    virtual ~TGraphParentNode() {}
-    void addDependentNode(TGraphNode* node) { if (node != this) mDependentNodes.insert(node); }
-    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
-private:
-    TGraphNodeSet mDependentNodes;
-};
-
-//
-// Handle function call arguments.
-//
-class TGraphArgument : public TGraphParentNode {
-public:
-    TGraphArgument(TIntermAggregate* intermFunctionCall, int argumentNumber)
-        : TGraphParentNode(intermFunctionCall)
-        , mArgumentNumber(argumentNumber) {}
-    virtual ~TGraphArgument() {}
-    const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); }
-    int getArgumentNumber() const { return mArgumentNumber; }
-    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
-private:
-    int mArgumentNumber;
-};
-
-//
-// Handle function calls.
-//
-class TGraphFunctionCall : public TGraphParentNode {
-public:
-    TGraphFunctionCall(TIntermAggregate* intermFunctionCall)
-        : TGraphParentNode(intermFunctionCall) {}
-    virtual ~TGraphFunctionCall() {}
-    const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); }
-    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
-};
-
-//
-// Handle symbols.
-//
-class TGraphSymbol : public TGraphParentNode {
-public:
-    TGraphSymbol(TIntermSymbol* intermSymbol) : TGraphParentNode(intermSymbol) {}
-    virtual ~TGraphSymbol() {}
-    const TIntermSymbol* getIntermSymbol() const { return intermNode->getAsSymbolNode(); }
-    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
-};
-
-//
-// Handle if statements and ternary operators.
-//
-class TGraphSelection : public TGraphNode {
-public:
-    TGraphSelection(TIntermSelection* intermSelection) : TGraphNode(intermSelection) {}
-    virtual ~TGraphSelection() {}
-    const TIntermSelection* getIntermSelection() const { return intermNode->getAsSelectionNode(); }
-    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
-};
-
-//
-// Handle for, do-while, and while loops.
-//
-class TGraphLoop : public TGraphNode {
-public:
-    TGraphLoop(TIntermLoop* intermLoop) : TGraphNode(intermLoop) {}
-    virtual ~TGraphLoop() {}
-    const TIntermLoop* getIntermLoop() const { return intermNode->getAsLoopNode(); }
-    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
-};
-
-//
-// Handle logical and, or.
-//
-class TGraphLogicalOp : public TGraphNode {
-public:
-    TGraphLogicalOp(TIntermBinary* intermLogicalOp) : TGraphNode(intermLogicalOp) {}
-    virtual ~TGraphLogicalOp() {}
-    const TIntermBinary* getIntermLogicalOp() const { return intermNode->getAsBinaryNode(); }
-    const char* getOpString() const;
-    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
-};
-
-//
-// A dependency graph of symbols, function calls, conditions etc.
-//
-// This class provides an interface to the entry points of the dependency graph.
-//
-// Dependency graph nodes should be created by using one of the provided "create..." methods.
-// This class (and nobody else) manages the memory of the created nodes.
-// Nodes may not be removed after being added, so all created nodes will exist while the
-// TDependencyGraph instance exists.
-//
-class TDependencyGraph {
-public:
-    TDependencyGraph(TIntermNode* intermNode);
-    ~TDependencyGraph();
-    TGraphNodeVector::const_iterator begin() const { return mAllNodes.begin(); }
-    TGraphNodeVector::const_iterator end() const { return mAllNodes.end(); }
-
-    TGraphSymbolVector::const_iterator beginSamplerSymbols() const
-    {
-        return mSamplerSymbols.begin();
-    }
-
-    TGraphSymbolVector::const_iterator endSamplerSymbols() const
-    {
-        return mSamplerSymbols.end();
-    }
-
-    TFunctionCallVector::const_iterator beginUserDefinedFunctionCalls() const
-    {
-        return mUserDefinedFunctionCalls.begin();
-    }
-
-    TFunctionCallVector::const_iterator endUserDefinedFunctionCalls() const
-    {
-        return mUserDefinedFunctionCalls.end();
-    }
-
-    TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber);
-    TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall);
-    TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol);
-    TGraphSelection* createSelection(TIntermSelection* intermSelection);
-    TGraphLoop* createLoop(TIntermLoop* intermLoop);
-    TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp);
-private:
-    typedef TMap<int, TGraphSymbol*> TSymbolIdMap;
-    typedef std::pair<int, TGraphSymbol*> TSymbolIdPair;
-
-    TGraphNodeVector mAllNodes;
-    TGraphSymbolVector mSamplerSymbols;
-    TFunctionCallVector mUserDefinedFunctionCalls;
-    TSymbolIdMap mSymbolIdMap;
-};
-
-//
-// For traversing the dependency graph. Users should derive from this,
-// put their traversal specific data in it, and then pass it to a
-// traverse method.
-//
-// When using this, just fill in the methods for nodes you want visited.
-//
-class TDependencyGraphTraverser {
-public:
-    TDependencyGraphTraverser() : mDepth(0) {}
-
-    virtual void visitSymbol(TGraphSymbol* symbol) {};
-    virtual void visitArgument(TGraphArgument* selection) {};
-    virtual void visitFunctionCall(TGraphFunctionCall* functionCall) {};
-    virtual void visitSelection(TGraphSelection* selection) {};
-    virtual void visitLoop(TGraphLoop* loop) {};
-    virtual void visitLogicalOp(TGraphLogicalOp* logicalOp) {};
-
-    int getDepth() const { return mDepth; }
-    void incrementDepth() { ++mDepth; }
-    void decrementDepth() { --mDepth; }
-
-    void clearVisited() { mVisited.clear(); }
-    void markVisited(TGraphNode* node) { mVisited.insert(node); }
-    bool isVisited(TGraphNode* node) const { return mVisited.find(node) != mVisited.end(); }
-private:
-    int mDepth;
-    TGraphNodeSet mVisited;
-};
-
-#endif
diff --git a/src/third_party/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp b/src/third_party/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp
deleted file mode 100644
index d586cfd..0000000
--- a/src/third_party/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/depgraph/DependencyGraphBuilder.h"
-
-void TDependencyGraphBuilder::build(TIntermNode* node, TDependencyGraph* graph)
-{
-    TDependencyGraphBuilder builder(graph);
-    builder.build(node);
-}
-
-bool TDependencyGraphBuilder::visitAggregate(Visit visit, TIntermAggregate* intermAggregate)
-{
-    switch (intermAggregate->getOp()) {
-        case EOpFunction: visitFunctionDefinition(intermAggregate); break;
-        case EOpFunctionCall: visitFunctionCall(intermAggregate); break;
-        default: visitAggregateChildren(intermAggregate); break;
-    }
-
-    return false;
-}
-
-void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAggregate)
-{
-    // Currently, we do not support user defined functions.
-    if (intermAggregate->getName() != "main(")
-        return;
-
-    visitAggregateChildren(intermAggregate);
-}
-
-// Takes an expression like "f(x)" and creates a dependency graph like
-// "x -> argument 0 -> function call".
-void TDependencyGraphBuilder::visitFunctionCall(TIntermAggregate* intermFunctionCall)
-{
-    TGraphFunctionCall* functionCall = mGraph->createFunctionCall(intermFunctionCall);
-
-    // Run through the function call arguments.
-    int argumentNumber = 0;
-    TIntermSequence& intermArguments = intermFunctionCall->getSequence();
-    for (TIntermSequence::const_iterator iter = intermArguments.begin();
-         iter != intermArguments.end();
-         ++iter, ++argumentNumber)
-    {
-        TNodeSetMaintainer nodeSetMaintainer(this);
-
-        TIntermNode* intermArgument = *iter;
-        intermArgument->traverse(this);
-
-        if (TParentNodeSet* argumentNodes = mNodeSets.getTopSet()) {
-            TGraphArgument* argument = mGraph->createArgument(intermFunctionCall, argumentNumber);
-            connectMultipleNodesToSingleNode(argumentNodes, argument);
-            argument->addDependentNode(functionCall);
-        }
-    }
-
-    // Push the leftmost symbol of this function call into the current set of dependent symbols to
-    // represent the result of this function call.
-    // Thus, an expression like "y = f(x)" will yield a dependency graph like
-    // "x -> argument 0 -> function call -> y".
-    // This line essentially passes the function call node back up to an earlier visitAssignment
-    // call, which will create the connection "function call -> y".
-    mNodeSets.insertIntoTopSet(functionCall);
-}
-
-void TDependencyGraphBuilder::visitAggregateChildren(TIntermAggregate* intermAggregate)
-{
-    TIntermSequence& sequence = intermAggregate->getSequence();
-    for(TIntermSequence::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter)
-    {
-        TIntermNode* intermChild = *iter;
-        intermChild->traverse(this);
-    }
-}
-
-void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol)
-{
-    // Push this symbol into the set of dependent symbols for the current assignment or condition
-    // that we are traversing.
-    TGraphSymbol* symbol = mGraph->getOrCreateSymbol(intermSymbol);
-    mNodeSets.insertIntoTopSet(symbol);
-
-    // If this symbol is the current leftmost symbol under an assignment, replace the previous
-    // leftmost symbol with this symbol.
-    if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) {
-        mLeftmostSymbols.pop();
-        mLeftmostSymbols.push(symbol);
-    }
-}
-
-bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary)
-{
-    TOperator op = intermBinary->getOp();
-    if (op == EOpInitialize || intermBinary->modifiesState())
-        visitAssignment(intermBinary);
-    else if (op == EOpLogicalAnd || op == EOpLogicalOr)
-        visitLogicalOp(intermBinary);
-    else
-        visitBinaryChildren(intermBinary);
-
-    return false;
-}
-
-void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment)
-{
-    TIntermTyped* intermLeft = intermAssignment->getLeft();
-    if (!intermLeft)
-        return;
-
-    TGraphSymbol* leftmostSymbol = NULL;
-
-    {
-        TNodeSetMaintainer nodeSetMaintainer(this);
-
-        {
-            TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mLeftSubtree);
-            intermLeft->traverse(this);
-            leftmostSymbol = mLeftmostSymbols.top();
-
-            // After traversing the left subtree of this assignment, we should have found a real
-            // leftmost symbol, and the leftmost symbol should not be a placeholder.
-            ASSERT(leftmostSymbol != &mLeftSubtree);
-            ASSERT(leftmostSymbol != &mRightSubtree);
-        }
-
-        if (TIntermTyped* intermRight = intermAssignment->getRight()) {
-            TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
-            intermRight->traverse(this);
-        }
-
-        if (TParentNodeSet* assignmentNodes = mNodeSets.getTopSet())
-            connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol);
-    }
-
-    // Push the leftmost symbol of this assignment into the current set of dependent symbols to
-    // represent the result of this assignment.
-    // An expression like "a = (b = c)" will yield a dependency graph like "c -> b -> a".
-    // This line essentially passes the leftmost symbol of the nested assignment ("b" in this
-    // example) back up to the earlier visitAssignment call for the outer assignment, which will
-    // create the connection "b -> a".
-    mNodeSets.insertIntoTopSet(leftmostSymbol);
-}
-
-void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary* intermLogicalOp)
-{
-    if (TIntermTyped* intermLeft = intermLogicalOp->getLeft()) {
-        TNodeSetPropagatingMaintainer nodeSetMaintainer(this);
-
-        intermLeft->traverse(this);
-        if (TParentNodeSet* leftNodes = mNodeSets.getTopSet()) {
-            TGraphLogicalOp* logicalOp = mGraph->createLogicalOp(intermLogicalOp);
-            connectMultipleNodesToSingleNode(leftNodes, logicalOp);
-        }
-    }
-
-    if (TIntermTyped* intermRight = intermLogicalOp->getRight()) {
-        TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
-        intermRight->traverse(this);
-    }
-}
-
-void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary* intermBinary)
-{
-    if (TIntermTyped* intermLeft = intermBinary->getLeft())
-        intermLeft->traverse(this);
-
-    if (TIntermTyped* intermRight = intermBinary->getRight()) {
-        TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
-        intermRight->traverse(this);
-    }
-}
-
-bool TDependencyGraphBuilder::visitSelection(Visit visit, TIntermSelection* intermSelection)
-{
-    if (TIntermNode* intermCondition = intermSelection->getCondition()) {
-        TNodeSetMaintainer nodeSetMaintainer(this);
-
-        intermCondition->traverse(this);
-        if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) {
-            TGraphSelection* selection = mGraph->createSelection(intermSelection);
-            connectMultipleNodesToSingleNode(conditionNodes, selection);
-        }
-    }
-
-    if (TIntermNode* intermTrueBlock = intermSelection->getTrueBlock())
-        intermTrueBlock->traverse(this);
-
-    if (TIntermNode* intermFalseBlock = intermSelection->getFalseBlock())
-        intermFalseBlock->traverse(this);
-
-    return false;
-}
-
-bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop)
-{
-    if (TIntermTyped* intermCondition = intermLoop->getCondition()) {
-        TNodeSetMaintainer nodeSetMaintainer(this);
-
-        intermCondition->traverse(this);
-        if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) {
-            TGraphLoop* loop = mGraph->createLoop(intermLoop);
-            connectMultipleNodesToSingleNode(conditionNodes, loop);
-        }
-    }
-
-    if (TIntermNode* intermBody = intermLoop->getBody())
-        intermBody->traverse(this);
-
-    if (TIntermTyped* intermExpression = intermLoop->getExpression())
-        intermExpression->traverse(this);
-
-    return false;
-}
-
-
-void TDependencyGraphBuilder::connectMultipleNodesToSingleNode(TParentNodeSet* nodes,
-                                                               TGraphNode* node) const
-{
-    for (TParentNodeSet::const_iterator iter = nodes->begin(); iter != nodes->end(); ++iter)
-    {
-        TGraphParentNode* currentNode = *iter;
-        currentNode->addDependentNode(node);
-    }
-}
diff --git a/src/third_party/angle/src/compiler/depgraph/DependencyGraphBuilder.h b/src/third_party/angle/src/compiler/depgraph/DependencyGraphBuilder.h
deleted file mode 100644
index c5f232c..0000000
--- a/src/third_party/angle/src/compiler/depgraph/DependencyGraphBuilder.h
+++ /dev/null
@@ -1,181 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
-#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
-
-#include "compiler/depgraph/DependencyGraph.h"
-
-//
-// Creates a dependency graph of symbols, function calls, conditions etc. by traversing a
-// intermediate tree.
-//
-class TDependencyGraphBuilder : public TIntermTraverser {
-public:
-    static void build(TIntermNode* node, TDependencyGraph* graph);
-
-    virtual void visitSymbol(TIntermSymbol*);
-    virtual bool visitBinary(Visit visit, TIntermBinary*);
-    virtual bool visitSelection(Visit visit, TIntermSelection*);
-    virtual bool visitAggregate(Visit visit, TIntermAggregate*);
-    virtual bool visitLoop(Visit visit, TIntermLoop*);
-
-private:
-    typedef std::stack<TGraphSymbol*> TSymbolStack;
-    typedef std::set<TGraphParentNode*> TParentNodeSet;
-
-    //
-    // For collecting the dependent nodes of assignments, conditions, etc.
-    // while traversing the intermediate tree.
-    //
-    // This data structure is stack of sets. Each set contains dependency graph parent nodes.
-    //
-    class TNodeSetStack {
-    public:
-        TNodeSetStack() {};
-        ~TNodeSetStack() { clear(); }
-
-        // This should only be called after a pushSet.
-        // Returns NULL if the top set is empty.
-        TParentNodeSet* getTopSet() const
-        {
-            ASSERT(!nodeSets.empty());
-            TParentNodeSet* topSet = nodeSets.top();
-            return !topSet->empty() ? topSet : NULL;
-        }
-
-        void pushSet() { nodeSets.push(new TParentNodeSet()); }
-        void popSet()
-        {
-            ASSERT(!nodeSets.empty());
-            delete nodeSets.top();
-            nodeSets.pop();
-        }
-
-        // Pops the top set and adds its contents to the new top set.
-        // This should only be called after a pushSet.
-        // If there is no set below the top set, the top set is just deleted.
-        void popSetIntoNext()
-        {
-            ASSERT(!nodeSets.empty());
-            TParentNodeSet* oldTopSet = nodeSets.top();
-            nodeSets.pop();
-
-            if (!nodeSets.empty()) {
-                TParentNodeSet* newTopSet = nodeSets.top();
-                newTopSet->insert(oldTopSet->begin(), oldTopSet->end());
-            }
-
-            delete oldTopSet;
-        }
-
-        // Does nothing if there is no top set.
-        // This can be called when there is no top set if we are visiting
-        // symbols that are not under an assignment or condition.
-        // We don't need to track those symbols.
-        void insertIntoTopSet(TGraphParentNode* node)
-        {
-            if (nodeSets.empty())
-                return;
-
-            nodeSets.top()->insert(node);
-        }
-
-        void clear()
-        {
-            while (!nodeSets.empty())
-                popSet();
-        }
-
-    private:
-        typedef std::stack<TParentNodeSet*> TParentNodeSetStack;
-
-        TParentNodeSetStack nodeSets;
-    };
-
-    //
-    // An instance of this class pushes a new node set when instantiated.
-    // When the instance goes out of scope, it and pops the node set.
-    //
-    class TNodeSetMaintainer {
-    public:
-        TNodeSetMaintainer(TDependencyGraphBuilder* factory)
-            : sets(factory->mNodeSets) { sets.pushSet(); }
-        ~TNodeSetMaintainer() { sets.popSet(); }
-    protected:
-        TNodeSetStack& sets;
-    };
-
-    //
-    // An instance of this class pushes a new node set when instantiated.
-    // When the instance goes out of scope, it and pops the top node set and adds its contents to
-    // the new top node set.
-    //
-    class TNodeSetPropagatingMaintainer {
-    public:
-        TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory)
-            : sets(factory->mNodeSets) { sets.pushSet(); }
-        ~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); }
-    protected:
-        TNodeSetStack& sets;
-    };
-
-    //
-    // An instance of this class keeps track of the leftmost symbol while we're exploring an
-    // assignment.
-    // It will push the placeholder symbol kLeftSubtree when instantiated under a left subtree,
-    // and kRightSubtree under a right subtree.
-    // When it goes out of scope, it will pop the leftmost symbol at the top of the scope.
-    // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with a real symbol.
-    // kRightSubtree will never be replaced by a real symbol because we are tracking the leftmost
-    // symbol.
-    //
-    class TLeftmostSymbolMaintainer {
-    public:
-        TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree)
-            : leftmostSymbols(factory->mLeftmostSymbols)
-        {
-            needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree;
-            if (needsPlaceholderSymbol)
-                leftmostSymbols.push(&subtree);
-        }
-
-        ~TLeftmostSymbolMaintainer()
-        {
-            if (needsPlaceholderSymbol)
-                leftmostSymbols.pop();
-        }
-
-    protected:
-        TSymbolStack& leftmostSymbols;
-        bool needsPlaceholderSymbol;
-    };
-
-    TDependencyGraphBuilder(TDependencyGraph* graph)
-        : TIntermTraverser(true, false, false)
-        , mLeftSubtree(NULL)
-        , mRightSubtree(NULL)
-        , mGraph(graph) {}
-    void build(TIntermNode* intermNode) { intermNode->traverse(this); }
-
-    void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const;
-
-    void visitAssignment(TIntermBinary*);
-    void visitLogicalOp(TIntermBinary*);
-    void visitBinaryChildren(TIntermBinary*);
-    void visitFunctionDefinition(TIntermAggregate*);
-    void visitFunctionCall(TIntermAggregate* intermFunctionCall);
-    void visitAggregateChildren(TIntermAggregate*);
-
-    TGraphSymbol mLeftSubtree;
-    TGraphSymbol mRightSubtree;
-
-    TDependencyGraph* mGraph;
-    TNodeSetStack mNodeSets;
-    TSymbolStack mLeftmostSymbols;
-};
-
-#endif  // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
diff --git a/src/third_party/angle/src/compiler/depgraph/DependencyGraphOutput.cpp b/src/third_party/angle/src/compiler/depgraph/DependencyGraphOutput.cpp
deleted file mode 100644
index 6fc489e..0000000
--- a/src/third_party/angle/src/compiler/depgraph/DependencyGraphOutput.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/depgraph/DependencyGraphOutput.h"
-
-void TDependencyGraphOutput::outputIndentation()
-{
-    for (int i = 0; i < getDepth(); ++i)
-        mSink << "  ";
-}
-
-void TDependencyGraphOutput::visitArgument(TGraphArgument* parameter)
-{
-    outputIndentation();
-    mSink << "argument " << parameter->getArgumentNumber() << " of call to "
-          << parameter->getIntermFunctionCall()->getName() << "\n";
-}
-
-void TDependencyGraphOutput::visitFunctionCall(TGraphFunctionCall* functionCall)
-{
-    outputIndentation();
-    mSink << "function call " <<  functionCall->getIntermFunctionCall()->getName() << "\n";
-}
-
-void TDependencyGraphOutput::visitSymbol(TGraphSymbol* symbol)
-{
-    outputIndentation();
-    mSink << symbol->getIntermSymbol()->getSymbol() << " (symbol id: "
-          << symbol->getIntermSymbol()->getId() << ")\n";
-}
-
-void TDependencyGraphOutput::visitSelection(TGraphSelection* selection)
-{
-    outputIndentation();
-    mSink << "selection\n";
-}
-
-void TDependencyGraphOutput::visitLoop(TGraphLoop* loop)
-{
-    outputIndentation();
-    mSink << "loop condition\n";
-}
-
-void TDependencyGraphOutput::visitLogicalOp(TGraphLogicalOp* logicalOp)
-{
-    outputIndentation();
-    mSink << "logical " << logicalOp->getOpString() << "\n";
-}
-
-void TDependencyGraphOutput::outputAllSpanningTrees(TDependencyGraph& graph)
-{
-    mSink << "\n";
-
-    for (TGraphNodeVector::const_iterator iter = graph.begin(); iter != graph.end(); ++iter)
-    {
-        TGraphNode* symbol = *iter;
-        mSink << "--- Dependency graph spanning tree ---\n";
-        clearVisited();
-        symbol->traverse(this);
-        mSink << "\n";
-    }
-}
diff --git a/src/third_party/angle/src/compiler/depgraph/DependencyGraphOutput.h b/src/third_party/angle/src/compiler/depgraph/DependencyGraphOutput.h
deleted file mode 100644
index 01447da..0000000
--- a/src/third_party/angle/src/compiler/depgraph/DependencyGraphOutput.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
-#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
-
-#include "compiler/depgraph/DependencyGraph.h"
-#include "compiler/InfoSink.h"
-
-class TDependencyGraphOutput : public TDependencyGraphTraverser {
-public:
-    TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {}
-    virtual void visitSymbol(TGraphSymbol* symbol);
-    virtual void visitArgument(TGraphArgument* parameter);
-    virtual void visitFunctionCall(TGraphFunctionCall* functionCall);
-    virtual void visitSelection(TGraphSelection* selection);
-    virtual void visitLoop(TGraphLoop* loop);
-    virtual void visitLogicalOp(TGraphLogicalOp* logicalOp);
-
-    void outputAllSpanningTrees(TDependencyGraph& graph);
-private:
-    void outputIndentation();
-
-    TInfoSinkBase& mSink;
-};
-
-#endif  // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
diff --git a/src/third_party/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp b/src/third_party/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp
deleted file mode 100644
index b158575..0000000
--- a/src/third_party/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/depgraph/DependencyGraph.h"
-
-// These methods do a breadth-first traversal through the graph and mark visited nodes.
-
-void TGraphNode::traverse(TDependencyGraphTraverser* graphTraverser)
-{
-    graphTraverser->markVisited(this);
-}
-
-void TGraphParentNode::traverse(TDependencyGraphTraverser* graphTraverser)
-{
-    TGraphNode::traverse(graphTraverser);
-
-    graphTraverser->incrementDepth();
-
-    // Visit the parent node's children.
-    for (TGraphNodeSet::const_iterator iter = mDependentNodes.begin();
-         iter != mDependentNodes.end();
-         ++iter)
-    {
-        TGraphNode* node = *iter;
-        if (!graphTraverser->isVisited(node))
-            node->traverse(graphTraverser);
-    }
-
-    graphTraverser->decrementDepth();
-}
-
-void TGraphArgument::traverse(TDependencyGraphTraverser* graphTraverser)
-{
-    graphTraverser->visitArgument(this);
-    TGraphParentNode::traverse(graphTraverser);
-}
-
-void TGraphFunctionCall::traverse(TDependencyGraphTraverser* graphTraverser)
-{
-    graphTraverser->visitFunctionCall(this);
-    TGraphParentNode::traverse(graphTraverser);
-}
-
-void TGraphSymbol::traverse(TDependencyGraphTraverser* graphTraverser)
-{
-    graphTraverser->visitSymbol(this);
-    TGraphParentNode::traverse(graphTraverser);
-}
-
-void TGraphSelection::traverse(TDependencyGraphTraverser* graphTraverser)
-{
-    graphTraverser->visitSelection(this);
-    TGraphNode::traverse(graphTraverser);
-}
-
-void TGraphLoop::traverse(TDependencyGraphTraverser* graphTraverser)
-{
-    graphTraverser->visitLoop(this);
-    TGraphNode::traverse(graphTraverser);
-}
-
-void TGraphLogicalOp::traverse(TDependencyGraphTraverser* graphTraverser)
-{
-    graphTraverser->visitLogicalOp(this);
-    TGraphNode::traverse(graphTraverser);
-}
diff --git a/src/third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp b/src/third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp
new file mode 100644
index 0000000..dcc0562
--- /dev/null
+++ b/src/third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp
@@ -0,0 +1,170 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// translator_fuzzer.cpp: A libfuzzer fuzzer for the shader translator.
+
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+#include <memory>
+#include <unordered_map>
+
+#include "angle_gl.h"
+#include "compiler/translator/Compiler.h"
+
+using namespace sh;
+
+struct TranslatorCacheKey
+{
+    bool operator==(const TranslatorCacheKey &other) const
+    {
+        return type == other.type && spec == other.spec && output == other.output;
+    }
+
+    uint32_t type   = 0;
+    uint32_t spec   = 0;
+    uint32_t output = 0;
+};
+
+namespace std
+{
+
+template <>
+struct hash<TranslatorCacheKey>
+{
+    std::size_t operator()(const TranslatorCacheKey &k) const
+    {
+        return (hash<uint32_t>()(k.type) << 1) ^ (hash<uint32_t>()(k.spec) >> 1) ^
+               hash<uint32_t>()(k.output);
+    }
+};
+}  // namespace std
+
+struct TCompilerDeleter
+{
+    void operator()(TCompiler *compiler) const { DeleteCompiler(compiler); }
+};
+
+using UniqueTCompiler = std::unique_ptr<TCompiler, TCompilerDeleter>;
+
+static std::unordered_map<TranslatorCacheKey, UniqueTCompiler> translators;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    // Reserve some size for future compile options
+    const size_t kHeaderSize = 128;
+
+    if (size <= kHeaderSize)
+    {
+        return 0;
+    }
+
+    // Make sure the rest of data will be a valid C string so that we don't have to copy it.
+    if (data[size - 1] != 0)
+    {
+        return 0;
+    }
+
+    uint32_t type    = *reinterpret_cast<const uint32_t *>(data);
+    uint32_t spec    = *reinterpret_cast<const uint32_t *>(data + 4);
+    uint32_t output  = *reinterpret_cast<const uint32_t *>(data + 8);
+    uint64_t options = *reinterpret_cast<const uint64_t *>(data + 12);
+
+    if (type != GL_FRAGMENT_SHADER && type != GL_VERTEX_SHADER)
+    {
+        return 0;
+    }
+
+    if (spec != SH_GLES2_SPEC && type != SH_WEBGL_SPEC && spec != SH_GLES3_SPEC &&
+        spec != SH_WEBGL2_SPEC)
+    {
+        return 0;
+    }
+
+    std::vector<uint32_t> validOutputs;
+    validOutputs.push_back(SH_ESSL_OUTPUT);
+    validOutputs.push_back(SH_GLSL_COMPATIBILITY_OUTPUT);
+    validOutputs.push_back(SH_GLSL_130_OUTPUT);
+    validOutputs.push_back(SH_GLSL_140_OUTPUT);
+    validOutputs.push_back(SH_GLSL_150_CORE_OUTPUT);
+    validOutputs.push_back(SH_GLSL_330_CORE_OUTPUT);
+    validOutputs.push_back(SH_GLSL_400_CORE_OUTPUT);
+    validOutputs.push_back(SH_GLSL_410_CORE_OUTPUT);
+    validOutputs.push_back(SH_GLSL_420_CORE_OUTPUT);
+    validOutputs.push_back(SH_GLSL_430_CORE_OUTPUT);
+    validOutputs.push_back(SH_GLSL_440_CORE_OUTPUT);
+    validOutputs.push_back(SH_GLSL_450_CORE_OUTPUT);
+    validOutputs.push_back(SH_HLSL_3_0_OUTPUT);
+    validOutputs.push_back(SH_HLSL_4_1_OUTPUT);
+    validOutputs.push_back(SH_HLSL_4_0_FL9_3_OUTPUT);
+    bool found = false;
+    for (auto valid : validOutputs)
+    {
+        found = found || (valid == output);
+    }
+    if (!found)
+    {
+        return 0;
+    }
+
+    size -= kHeaderSize;
+    data += kHeaderSize;
+
+    if (!sh::Initialize())
+    {
+        return 0;
+    }
+
+    TranslatorCacheKey key;
+    key.type   = type;
+    key.spec   = spec;
+    key.output = output;
+
+    if (translators.find(key) == translators.end())
+    {
+        UniqueTCompiler translator(ConstructCompiler(type, static_cast<ShShaderSpec>(spec),
+                                                     static_cast<ShShaderOutput>(output)));
+
+        if (translator == nullptr)
+        {
+            return 0;
+        }
+
+        ShBuiltInResources resources;
+        sh::InitBuiltInResources(&resources);
+
+        // Enable all the extensions to have more coverage
+        resources.OES_standard_derivatives        = 1;
+        resources.OES_EGL_image_external          = 1;
+        resources.OES_EGL_image_external_essl3    = 1;
+        resources.NV_EGL_stream_consumer_external = 1;
+        resources.ARB_texture_rectangle           = 1;
+        resources.EXT_blend_func_extended         = 1;
+        resources.EXT_draw_buffers                = 1;
+        resources.EXT_frag_depth                  = 1;
+        resources.EXT_shader_texture_lod          = 1;
+        resources.WEBGL_debug_shader_precision    = 1;
+        resources.EXT_shader_framebuffer_fetch    = 1;
+        resources.NV_shader_framebuffer_fetch     = 1;
+        resources.ARM_shader_framebuffer_fetch    = 1;
+        resources.EXT_YUV_target                  = 1;
+        resources.MaxDualSourceDrawBuffers        = 1;
+
+        if (!translator->Init(resources))
+        {
+            return 0;
+        }
+
+        translators[key] = std::move(translator);
+    }
+
+    auto &translator = translators[key];
+
+    const char *shaderStrings[] = {reinterpret_cast<const char *>(data)};
+    translator->compile(shaderStrings, 1, options);
+
+    return 0;
+}
diff --git a/src/third_party/angle/src/compiler/generate_parser.sh b/src/third_party/angle/src/compiler/generate_parser.sh
deleted file mode 100755
index e4d88b2..0000000
--- a/src/third_party/angle/src/compiler/generate_parser.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Generates GLSL ES parser - glslang_lex.cpp, glslang_tab.h, and glslang_tab.cpp
-
-run_flex()
-{
-input_file=$script_dir/$1.l
-output_source=$script_dir/$1_lex.cpp
-flex --noline --nounistd --outfile=$output_source $input_file
-}
-
-run_bison()
-{
-input_file=$script_dir/$1.y
-output_header=$script_dir/$1_tab.h
-output_source=$script_dir/$1_tab.cpp
-bison --no-lines --skeleton=yacc.c --defines=$output_header --output=$output_source $input_file
-}
-
-script_dir=$(dirname $0)
-
-# Generate Parser
-run_flex glslang
-run_bison glslang
-patch --silent --forward < 64bit-lexer-safety.patch
diff --git a/src/third_party/angle/src/compiler/glslang.h b/src/third_party/angle/src/compiler/glslang.h
deleted file mode 100644
index f221199..0000000
--- a/src/third_party/angle/src/compiler/glslang.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-struct TParseContext;
-extern int glslang_initialize(TParseContext* context);
-extern int glslang_finalize(TParseContext* context);
-
-extern int glslang_scan(size_t count,
-                        const char* const string[],
-                        const int length[],
-                        TParseContext* context);
-extern int glslang_parse(TParseContext* context);
-
diff --git a/src/third_party/angle/src/compiler/glslang.l b/src/third_party/angle/src/compiler/glslang.l
deleted file mode 100644
index 4049875..0000000
--- a/src/third_party/angle/src/compiler/glslang.l
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-This file contains the Lex specification for GLSL ES.
-Based on ANSI C grammar, Lex specification:
-http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
-
-IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
-WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
-*/
-
-%top{
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
-
-// Ignore errors in auto-generated code.
-#if defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wunused-function"
-#pragma GCC diagnostic ignored "-Wunused-variable"
-#pragma GCC diagnostic ignored "-Wswitch-enum"
-#elif defined(_MSC_VER)
-#pragma warning(disable: 4065)
-#pragma warning(disable: 4189)
-#pragma warning(disable: 4505)
-#pragma warning(disable: 4701)
-#endif
-}
-
-%{
-#include "compiler/glslang.h"
-#include "compiler/ParseHelper.h"
-#include "compiler/preprocessor/Token.h"
-#include "compiler/util.h"
-#include "glslang_tab.h"
-
-/* windows only pragma */
-#ifdef _MSC_VER
-#pragma warning(disable : 4102)
-#endif
-
-#define YY_USER_ACTION                                 \
-    yylloc->first_file = yylloc->last_file = yycolumn; \
-    yylloc->first_line = yylloc->last_line = yylineno;
-
-#define YY_INPUT(buf, result, max_size) \
-    result = string_input(buf, max_size, yyscanner);
-
-static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
-static int check_type(yyscan_t yyscanner);
-static int reserved_word(yyscan_t yyscanner);
-%}
-
-%option noyywrap nounput never-interactive
-%option yylineno reentrant bison-bridge bison-locations
-%option extra-type="TParseContext*"
-
-D           [0-9]
-L           [a-zA-Z_]
-H           [a-fA-F0-9]
-E           [Ee][+-]?{D}+
-O           [0-7]
-
-%%
-
-"invariant"    { return INVARIANT; }
-"highp"        { return HIGH_PRECISION; }
-"mediump"      { return MEDIUM_PRECISION; }
-"lowp"         { return LOW_PRECISION; }
-"precision"    { return PRECISION; }
-
-"attribute"    { return ATTRIBUTE; }
-"const"        { return CONST_QUAL; }
-"uniform"      { return UNIFORM; }
-"varying"      { return VARYING; }
-
-"break"        { return BREAK; }
-"continue"     { return CONTINUE; }
-"do"           { return DO; }
-"for"          { return FOR; }
-"while"        { return WHILE; }
-
-"if"           { return IF; }
-"else"         { return ELSE; }
-
-"in"           { return IN_QUAL; }
-"out"          { return OUT_QUAL; }
-"inout"        { return INOUT_QUAL; }
-
-"float"        { return FLOAT_TYPE; }
-"int"          { return INT_TYPE; }
-"void"         { return VOID_TYPE; }
-"bool"         { return BOOL_TYPE; }
-"true"         { yylval->lex.b = true;  return BOOLCONSTANT; }
-"false"        { yylval->lex.b = false; return BOOLCONSTANT; }
-
-"discard"      { return DISCARD; }
-"return"       { return RETURN; }
-
-"mat2"         { return MATRIX2; }
-"mat3"         { return MATRIX3; }
-"mat4"         { return MATRIX4; }
-
-"vec2"         { return VEC2; }
-"vec3"         { return VEC3; }
-"vec4"         { return VEC4; }
-"ivec2"        { return IVEC2; }
-"ivec3"        { return IVEC3; }
-"ivec4"        { return IVEC4; }
-"bvec2"        { return BVEC2; }
-"bvec3"        { return BVEC3; }
-"bvec4"        { return BVEC4; }
-
-"sampler2D"          { return SAMPLER2D; }
-"samplerCube"        { return SAMPLERCUBE; }
-"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; }
-"sampler2DRect"      { return SAMPLER2DRECT; }
-
-"struct"       { return STRUCT; }
-
-"asm"          { return reserved_word(yyscanner); }
-
-"class"        { return reserved_word(yyscanner); }
-"union"        { return reserved_word(yyscanner); }
-"enum"         { return reserved_word(yyscanner); }
-"typedef"      { return reserved_word(yyscanner); }
-"template"     { return reserved_word(yyscanner); }
-"this"         { return reserved_word(yyscanner); }
-"packed"       { return reserved_word(yyscanner); }
-
-"goto"         { return reserved_word(yyscanner); }
-"switch"       { return reserved_word(yyscanner); }
-"default"      { return reserved_word(yyscanner); }
-
-"inline"       { return reserved_word(yyscanner); }
-"noinline"     { return reserved_word(yyscanner); }
-"volatile"     { return reserved_word(yyscanner); }
-"public"       { return reserved_word(yyscanner); }
-"static"       { return reserved_word(yyscanner); }
-"extern"       { return reserved_word(yyscanner); }
-"external"     { return reserved_word(yyscanner); }
-"interface"    { return reserved_word(yyscanner); }
-"flat"         { return reserved_word(yyscanner); }
-
-"long"         { return reserved_word(yyscanner); }
-"short"        { return reserved_word(yyscanner); }
-"double"       { return reserved_word(yyscanner); }
-"half"         { return reserved_word(yyscanner); }
-"fixed"        { return reserved_word(yyscanner); }
-"unsigned"     { return reserved_word(yyscanner); }
-"superp"       { return reserved_word(yyscanner); }
-
-"input"        { return reserved_word(yyscanner); }
-"output"       { return reserved_word(yyscanner); }
-
-"hvec2"        { return reserved_word(yyscanner); }
-"hvec3"        { return reserved_word(yyscanner); }
-"hvec4"        { return reserved_word(yyscanner); }
-"dvec2"        { return reserved_word(yyscanner); }
-"dvec3"        { return reserved_word(yyscanner); }
-"dvec4"        { return reserved_word(yyscanner); }
-"fvec2"        { return reserved_word(yyscanner); }
-"fvec3"        { return reserved_word(yyscanner); }
-"fvec4"        { return reserved_word(yyscanner); }
-
-"sampler1D"           { return reserved_word(yyscanner); }
-"sampler3D"           { return reserved_word(yyscanner); }
-"sampler1DShadow"     { return reserved_word(yyscanner); }
-"sampler2DShadow"     { return reserved_word(yyscanner); }
-"sampler3DRect"       { return reserved_word(yyscanner); }
-"sampler2DRectShadow" { return reserved_word(yyscanner); }
-
-"sizeof"       { return reserved_word(yyscanner); }
-"cast"         { return reserved_word(yyscanner); }
-
-"namespace"    { return reserved_word(yyscanner); }
-"using"        { return reserved_word(yyscanner); }
-
-{L}({L}|{D})*       {
-   yylval->lex.string = NewPoolTString(yytext); 
-   return check_type(yyscanner);
-}
-
-0[xX]{H}+         { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
-0{O}+             { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
-{D}+              { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
-
-{D}+{E}           { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
-{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
-"."{D}+({E})?     { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
-
-"+="            { return ADD_ASSIGN; }
-"-="            { return SUB_ASSIGN; }
-"*="            { return MUL_ASSIGN; }
-"/="            { return DIV_ASSIGN; }
-"%="            { return MOD_ASSIGN; }
-"<<="           { return LEFT_ASSIGN; }
-">>="           { return RIGHT_ASSIGN; }
-"&="            { return AND_ASSIGN; }
-"^="            { return XOR_ASSIGN; }
-"|="            { return OR_ASSIGN; }
-
-"++"            { return INC_OP; }
-"--"            { return DEC_OP; }
-"&&"            { return AND_OP; }
-"||"            { return OR_OP; }
-"^^"            { return XOR_OP; }
-"<="            { return LE_OP; }
-">="            { return GE_OP; }
-"=="            { return EQ_OP; }
-"!="            { return NE_OP; }
-"<<"            { return LEFT_OP; }
-">>"            { return RIGHT_OP; }
-";"             { return SEMICOLON; }
-("{"|"<%")      { return LEFT_BRACE; }
-("}"|"%>")      { return RIGHT_BRACE; }
-","         { return COMMA; }
-":"         { return COLON; }
-"="         { return EQUAL; }
-"("         { return LEFT_PAREN; }
-")"         { return RIGHT_PAREN; }
-("["|"<:")  { return LEFT_BRACKET; }
-("]"|":>")  { return RIGHT_BRACKET; }
-"."         { return DOT; }
-"!"         { return BANG; }
-"-"         { return DASH; }
-"~"         { return TILDE; }
-"+"         { return PLUS; }
-"*"         { return STAR; }
-"/"         { return SLASH; }
-"%"         { return PERCENT; }
-"<"         { return LEFT_ANGLE; }
-">"         { return RIGHT_ANGLE; }
-"|"         { return VERTICAL_BAR; }
-"^"         { return CARET; }
-"&"         { return AMPERSAND; }
-"?"         { return QUESTION; }
-
-[ \t\v\n\f\r] { }
-<<EOF>>    { yyterminate(); }
-.          { assert(false); return 0; }
-
-%%
-
-yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
-    pp::Token token;
-    yyget_extra(yyscanner)->preprocessor.lex(&token);
-    yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
-    if (len < max_size)
-        memcpy(buf, token.text.c_str(), len);
-    yyset_column(token.location.file, yyscanner);
-    yyset_lineno(token.location.line, yyscanner);
-
-    if (len >= max_size)
-        YY_FATAL_ERROR("Input buffer overflow");
-    else if (len > 0)
-        buf[len++] = ' ';
-    return len;
-}
-
-int check_type(yyscan_t yyscanner) {
-    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
-    
-    int token = IDENTIFIER;
-    TSymbol* symbol = yyextra->symbolTable.find(yytext);
-    if (symbol && symbol->isVariable()) {
-        TVariable* variable = static_cast<TVariable*>(symbol);
-        if (variable->isUserType())
-            token = TYPE_NAME;
-    }
-    yylval->lex.symbol = symbol;
-    return token;
-}
-
-int reserved_word(yyscan_t yyscanner) {
-    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
-
-    yyextra->error(*yylloc, "Illegal use of reserved word", yytext, "");
-    yyextra->recover();
-    return 0;
-}
-
-int glslang_initialize(TParseContext* context) {
-    yyscan_t scanner = NULL;
-    if (yylex_init_extra(context, &scanner))
-        return 1;
-
-    context->scanner = scanner;
-    return 0;
-}
-
-int glslang_finalize(TParseContext* context) {
-    yyscan_t scanner = context->scanner;
-    if (scanner == NULL) return 0;
-    
-    context->scanner = NULL;
-    yylex_destroy(scanner);
-
-    return 0;
-}
-
-int glslang_scan(size_t count, const char* const string[], const int length[],
-                 TParseContext* context) {
-    yyrestart(NULL, context->scanner);
-    yyset_column(0, context->scanner);
-    yyset_lineno(1, context->scanner);
-
-    // Initialize preprocessor.
-    if (!context->preprocessor.init(count, string, length))
-        return 1;
-
-    // Define extension macros.
-    const TExtensionBehavior& extBehavior = context->extensionBehavior();
-    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
-         iter != extBehavior.end(); ++iter) {
-        context->preprocessor.predefineMacro(iter->first.c_str(), 1);
-    }
-    if (context->fragmentPrecisionHigh)
-        context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
-
-    return 0;
-}
-
diff --git a/src/third_party/angle/src/compiler/glslang.y b/src/third_party/angle/src/compiler/glslang.y
deleted file mode 100644
index 0e8c3c3..0000000
--- a/src/third_party/angle/src/compiler/glslang.y
+++ /dev/null
@@ -1,2014 +0,0 @@
-/*
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-This file contains the Yacc grammar for GLSL ES.
-Based on ANSI C Yacc grammar:
-http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
-
-IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
-WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
-*/
-
-%{
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
-
-// Ignore errors in auto-generated code.
-#if defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wunused-function"
-#pragma GCC diagnostic ignored "-Wunused-variable"
-#pragma GCC diagnostic ignored "-Wswitch-enum"
-#elif defined(_MSC_VER)
-#pragma warning(disable: 4065)
-#pragma warning(disable: 4189)
-#pragma warning(disable: 4505)
-#pragma warning(disable: 4701)
-#endif
-
-#include "compiler/SymbolTable.h"
-#include "compiler/ParseHelper.h"
-#include "GLSLANG/ShaderLang.h"
-
-#define YYENABLE_NLS 0
-
-#define YYLEX_PARAM context->scanner
-%}
-
-%expect 1 /* One shift reduce conflict because of if | else */
-%pure-parser
-%parse-param {TParseContext* context}
-%locations
-
-%code requires {
-#define YYLTYPE TSourceLoc
-#define YYLTYPE_IS_DECLARED 1
-}
-
-%union {
-    struct {
-        union {
-            TString *string;
-            float f;
-            int i;
-            bool b;
-        };
-        TSymbol* symbol;
-    } lex;
-    struct {
-        TOperator op;
-        union {
-            TIntermNode* intermNode;
-            TIntermNodePair nodePair;
-            TIntermTyped* intermTypedNode;
-            TIntermAggregate* intermAggregate;
-        };
-        union {
-            TPublicType type;
-            TPrecision precision;
-            TQualifier qualifier;
-            TFunction* function;
-            TParameter param;
-            TField* field;
-            TFieldList* fieldList;
-        };
-    } interm;
-}
-
-%{
-extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
-static void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason);
-
-#define YYLLOC_DEFAULT(Current, Rhs, N)                      \
-  do {                                                       \
-      if (YYID(N)) {                                         \
-        (Current).first_file = YYRHSLOC(Rhs, 1).first_file;  \
-        (Current).first_line = YYRHSLOC(Rhs, 1).first_line;  \
-        (Current).last_file = YYRHSLOC(Rhs, N).last_file;    \
-        (Current).last_line = YYRHSLOC(Rhs, N).last_line;    \
-      }                                                      \
-      else {                                                 \
-        (Current).first_file = YYRHSLOC(Rhs, 0).last_file;   \
-        (Current).first_line = YYRHSLOC(Rhs, 0).last_line;   \
-        (Current).last_file = YYRHSLOC(Rhs, 0).last_file;    \
-        (Current).last_line = YYRHSLOC(Rhs, 0).last_line;    \
-      }                                                      \
-  } while (0)
-
-#define VERTEX_ONLY(S, L) {  \
-    if (context->shaderType != SH_VERTEX_SHADER) {  \
-        context->error(L, " supported in vertex shaders only ", S);  \
-        context->recover();  \
-    }  \
-}
-
-#define FRAG_ONLY(S, L) {  \
-    if (context->shaderType != SH_FRAGMENT_SHADER) {  \
-        context->error(L, " supported in fragment shaders only ", S);  \
-        context->recover();  \
-    }  \
-}
-%}
-
-%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
-%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
-%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
-%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
-%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
-%token <lex> STRUCT VOID_TYPE WHILE
-%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT
-
-%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
-%token <lex> LEFT_OP RIGHT_OP
-%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
-%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
-%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
-%token <lex> SUB_ASSIGN
-
-%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
-%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
-%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
-
-%type <lex> identifier
-%type <interm> assignment_operator unary_operator
-%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
-%type <interm.intermTypedNode> expression integer_expression assignment_expression
-%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
-%type <interm.intermTypedNode> relational_expression equality_expression
-%type <interm.intermTypedNode> conditional_expression constant_expression
-%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
-%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
-%type <interm.intermTypedNode> function_call initializer condition conditionopt
-
-%type <interm.intermNode> translation_unit function_definition
-%type <interm.intermNode> statement simple_statement
-%type <interm.intermAggregate>  statement_list compound_statement
-%type <interm.intermNode> declaration_statement selection_statement expression_statement
-%type <interm.intermNode> declaration external_declaration
-%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
-%type <interm.nodePair> selection_rest_statement for_rest_statement
-%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
-%type <interm> single_declaration init_declarator_list
-
-%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
-%type <interm.qualifier> parameter_qualifier
-
-%type <interm.precision> precision_qualifier
-%type <interm.type> type_qualifier fully_specified_type type_specifier
-%type <interm.type> type_specifier_no_prec type_specifier_nonarray
-%type <interm.type> struct_specifier
-%type <interm.field> struct_declarator
-%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
-%type <interm.function> function_header function_declarator function_identifier
-%type <interm.function> function_header_with_parameters function_call_header
-%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
-%type <interm> function_call_or_method
-
-%start translation_unit
-%%
-
-identifier
-    : IDENTIFIER
-    | TYPE_NAME
-
-variable_identifier
-    : IDENTIFIER {
-        // The symbol table search was done in the lexical phase
-        const TSymbol* symbol = $1.symbol;
-        const TVariable* variable;
-        if (symbol == 0) {
-            context->error(@1, "undeclared identifier", $1.string->c_str());
-            context->recover();
-            TType type(EbtFloat, EbpUndefined);
-            TVariable* fakeVariable = new TVariable($1.string, type);
-            context->symbolTable.insert(*fakeVariable);
-            variable = fakeVariable;
-        } else {
-            // This identifier can only be a variable type symbol
-            if (! symbol->isVariable()) {
-                context->error(@1, "variable expected", $1.string->c_str());
-                context->recover();
-            }
-            
-            variable = static_cast<const TVariable*>(symbol);
-
-            if (context->symbolTable.findBuiltIn(variable->getName()) &&
-                !variable->getExtension().empty() &&
-                context->extensionErrorCheck(@1, variable->getExtension())) {
-                context->recover();
-            }
-        }
-
-        // don't delete $1.string, it's used by error recovery, and the pool
-        // pop will reclaim the memory
-
-        if (variable->getType().getQualifier() == EvqConst ) {
-            ConstantUnion* constArray = variable->getConstPointer();
-            TType t(variable->getType());
-            $$ = context->intermediate.addConstantUnion(constArray, t, @1);
-        } else
-            $$ = context->intermediate.addSymbol(variable->getUniqueId(),
-                                                 variable->getName(),
-                                                 variable->getType(),
-                                                 @1);
-    }
-    ;
-
-primary_expression
-    : variable_identifier {
-        $$ = $1;
-    }
-    | INTCONSTANT {
-        //
-        // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
-        // check for overflow for constants
-        //
-        if (abs($1.i) >= (1 << 16)) {
-            context->error(@1, " integer constant overflow", "");
-            context->recover();
-        }
-        ConstantUnion *unionArray = new ConstantUnion[1];
-        unionArray->setIConst($1.i);
-        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1);
-    }
-    | FLOATCONSTANT {
-        ConstantUnion *unionArray = new ConstantUnion[1];
-        unionArray->setFConst($1.f);
-        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
-    }
-    | BOOLCONSTANT {
-        ConstantUnion *unionArray = new ConstantUnion[1];
-        unionArray->setBConst($1.b);
-        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1);
-    }
-    | LEFT_PAREN expression RIGHT_PAREN {
-        $$ = $2;
-    }
-    ;
-
-postfix_expression
-    : primary_expression {
-        $$ = $1;
-    }
-    | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
-        $$ = context->addIndexExpression($1, @2, $3);
-    }
-    | function_call {
-        $$ = $1;
-    }
-    | postfix_expression DOT identifier {
-        if ($1->isArray()) {
-            context->error(@3, "cannot apply dot operator to an array", ".");
-            context->recover();
-        }
-
-        if ($1->isVector()) {
-            TVectorFields fields;
-            if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) {
-                fields.num = 1;
-                fields.offsets[0] = 0;
-                context->recover();
-            }
-
-            if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
-                $$ = context->addConstVectorNode(fields, $1, @3);
-                if ($$ == 0) {
-                    context->recover();
-                    $$ = $1;
-                }
-                else
-                    $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
-            } else {
-                TString vectorString = *$3.string;
-                TIntermTyped* index = context->intermediate.addSwizzle(fields, @3);
-                $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2);
-                $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
-            }
-        } else if ($1->isMatrix()) {
-            TMatrixFields fields;
-            if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) {
-                fields.wholeRow = false;
-                fields.wholeCol = false;
-                fields.row = 0;
-                fields.col = 0;
-                context->recover();
-            }
-
-            if (fields.wholeRow || fields.wholeCol) {
-                context->error(@2, " non-scalar fields not implemented yet", ".");
-                context->recover();
-                ConstantUnion *unionArray = new ConstantUnion[1];
-                unionArray->setIConst(0);
-                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
-                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
-                $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
-            } else {
-                ConstantUnion *unionArray = new ConstantUnion[1];
-                unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
-                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
-                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
-                $$->setType(TType($1->getBasicType(), $1->getPrecision()));
-            }
-        } else if ($1->getBasicType() == EbtStruct) {
-            bool fieldFound = false;
-            const TFieldList& fields = $1->getType().getStruct()->fields();
-            unsigned int i;
-            for (i = 0; i < fields.size(); ++i) {
-                if (fields[i]->name() == *$3.string) {
-                    fieldFound = true;
-                    break;
-                }
-            }
-            if (fieldFound) {
-                if ($1->getType().getQualifier() == EvqConst) {
-                    $$ = context->addConstStruct(*$3.string, $1, @2);
-                    if ($$ == 0) {
-                        context->recover();
-                        $$ = $1;
-                    }
-                    else {
-                        $$->setType(*fields[i]->type());
-                        // change the qualifier of the return type, not of the structure field
-                        // as the structure definition is shared between various structures.
-                        $$->getTypePointer()->setQualifier(EvqConst);
-                    }
-                } else {
-                    ConstantUnion *unionArray = new ConstantUnion[1];
-                    unionArray->setIConst(i);
-                    TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3);
-                    $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2);
-                    $$->setType(*fields[i]->type());
-                }
-            } else {
-                context->error(@2, " no such field in structure", $3.string->c_str());
-                context->recover();
-                $$ = $1;
-            }
-        } else {
-            context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str());
-            context->recover();
-            $$ = $1;
-        }
-        // don't delete $3.string, it's from the pool
-    }
-    | postfix_expression INC_OP {
-        if (context->lValueErrorCheck(@2, "++", $1))
-            context->recover();
-        $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->unaryOpError(@2, "++", $1->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
-    }
-    | postfix_expression DEC_OP {
-        if (context->lValueErrorCheck(@2, "--", $1))
-            context->recover();
-        $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->unaryOpError(@2, "--", $1->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
-    }
-    ;
-
-integer_expression
-    : expression {
-        if (context->integerErrorCheck($1, "[]"))
-            context->recover();
-        $$ = $1;
-    }
-    ;
-
-function_call
-    : function_call_or_method {
-        TFunction* fnCall = $1.function;
-        TOperator op = fnCall->getBuiltInOp();
-
-        if (op != EOpNull)
-        {
-            //
-            // Then this should be a constructor.
-            // Don't go through the symbol table for constructors.
-            // Their parameters will be verified algorithmically.
-            //
-            TType type(EbtVoid, EbpUndefined);  // use this to get the type back
-            if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) {
-                $$ = 0;
-            } else {
-                //
-                // It's a constructor, of type 'type'.
-                //
-                $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1);
-            }
-
-            if ($$ == 0) {
-                context->recover();
-                $$ = context->intermediate.setAggregateOperator(0, op, @1);
-            }
-            $$->setType(type);
-        } else {
-            //
-            // Not a constructor.  Find it in the symbol table.
-            //
-            const TFunction* fnCandidate;
-            bool builtIn;
-            fnCandidate = context->findFunction(@1, fnCall, &builtIn);
-            if (fnCandidate) {
-                //
-                // A declared function.
-                //
-                if (builtIn && !fnCandidate->getExtension().empty() &&
-                    context->extensionErrorCheck(@1, fnCandidate->getExtension())) {
-                    context->recover();
-                }
-                op = fnCandidate->getBuiltInOp();
-                if (builtIn && op != EOpNull) {
-                    //
-                    // A function call mapped to a built-in operation.
-                    //
-                    if (fnCandidate->getParamCount() == 1) {
-                        //
-                        // Treat it like a built-in unary operator.
-                        //
-                        $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable);
-                        if ($$ == 0)  {
-                            std::stringstream extraInfoStream;
-                            extraInfoStream << "built in unary operator function.  Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
-                            std::string extraInfo = extraInfoStream.str();
-                            context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
-                            YYERROR;
-                        }
-                    } else {
-                        $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
-                    }
-                } else {
-                    // This is a real function call
-
-                    $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
-                    $$->setType(fnCandidate->getReturnType());
-
-                    // this is how we know whether the given function is a builtIn function or a user defined function
-                    // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
-                    // if builtIn == true, it's definitely a builtIn function with EOpNull
-                    if (!builtIn)
-                        $$->getAsAggregate()->setUserDefined();
-                    $$->getAsAggregate()->setName(fnCandidate->getMangledName());
-
-                    TQualifier qual;
-                    for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
-                        qual = fnCandidate->getParam(i).type->getQualifier();
-                        if (qual == EvqOut || qual == EvqInOut) {
-                            if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
-                                context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
-                                context->recover();
-                            }
-                        }
-                    }
-                }
-                $$->setType(fnCandidate->getReturnType());
-            } else {
-                // error message was put out by PaFindFunction()
-                // Put on a dummy node for error recovery
-                ConstantUnion *unionArray = new ConstantUnion[1];
-                unionArray->setFConst(0.0f);
-                $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
-                context->recover();
-            }
-        }
-        delete fnCall;
-    }
-    ;
-
-function_call_or_method
-    : function_call_generic {
-        $$ = $1;
-    }
-    | postfix_expression DOT function_call_generic {
-        context->error(@3, "methods are not supported", "");
-        context->recover();
-        $$ = $3;
-    }
-    ;
-
-function_call_generic
-    : function_call_header_with_parameters RIGHT_PAREN {
-        $$ = $1;
-    }
-    | function_call_header_no_parameters RIGHT_PAREN {
-        $$ = $1;
-    }
-    ;
-
-function_call_header_no_parameters
-    : function_call_header VOID_TYPE {
-        $$.function = $1;
-        $$.intermNode = 0;
-    }
-    | function_call_header {
-        $$.function = $1;
-        $$.intermNode = 0;
-    }
-    ;
-
-function_call_header_with_parameters
-    : function_call_header assignment_expression {
-        TParameter param = { 0, new TType($2->getType()) };
-        $1->addParameter(param);
-        $$.function = $1;
-        $$.intermNode = $2;
-    }
-    | function_call_header_with_parameters COMMA assignment_expression {
-        TParameter param = { 0, new TType($3->getType()) };
-        $1.function->addParameter(param);
-        $$.function = $1.function;
-        $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2);
-    }
-    ;
-
-function_call_header
-    : function_identifier LEFT_PAREN {
-        $$ = $1;
-    }
-    ;
-
-// Grammar Note:  Constructors look like functions, but are recognized as types.
-
-function_identifier
-    : type_specifier_nonarray {
-        //
-        // Constructor
-        //
-        TOperator op = EOpNull;
-        if ($1.userDef) {
-            op = EOpConstructStruct;
-        } else {
-            switch ($1.type) {
-            case EbtFloat:
-                if ($1.matrix) {
-                    switch($1.size) {
-                    case 2: op = EOpConstructMat2;  break;
-                    case 3: op = EOpConstructMat3;  break;
-                    case 4: op = EOpConstructMat4;  break;
-                    }
-                } else {
-                    switch($1.size) {
-                    case 1: op = EOpConstructFloat; break;
-                    case 2: op = EOpConstructVec2;  break;
-                    case 3: op = EOpConstructVec3;  break;
-                    case 4: op = EOpConstructVec4;  break;
-                    }
-                }
-                break;
-            case EbtInt:
-                switch($1.size) {
-                case 1: op = EOpConstructInt;   break;
-                case 2: op = EOpConstructIVec2; break;
-                case 3: op = EOpConstructIVec3; break;
-                case 4: op = EOpConstructIVec4; break;
-                }
-                break;
-            case EbtBool:
-                switch($1.size) {
-                case 1: op = EOpConstructBool;  break;
-                case 2: op = EOpConstructBVec2; break;
-                case 3: op = EOpConstructBVec3; break;
-                case 4: op = EOpConstructBVec4; break;
-                }
-                break;
-            default: break;
-            }
-            if (op == EOpNull) {
-                context->error(@1, "cannot construct this type", getBasicString($1.type));
-                context->recover();
-                $1.type = EbtFloat;
-                op = EOpConstructFloat;
-            }
-        }
-        TString tempString;
-        TType type($1);
-        TFunction *function = new TFunction(&tempString, type, op);
-        $$ = function;
-    }
-    | IDENTIFIER {
-        if (context->reservedErrorCheck(@1, *$1.string))
-            context->recover();
-        TType type(EbtVoid, EbpUndefined);
-        TFunction *function = new TFunction($1.string, type);
-        $$ = function;
-    }
-    ;
-
-unary_expression
-    : postfix_expression {
-        $$ = $1;
-    }
-    | INC_OP unary_expression {
-        if (context->lValueErrorCheck(@1, "++", $2))
-            context->recover();
-        $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable);
-        if ($$ == 0) {
-            context->unaryOpError(@1, "++", $2->getCompleteString());
-            context->recover();
-            $$ = $2;
-        }
-    }
-    | DEC_OP unary_expression {
-        if (context->lValueErrorCheck(@1, "--", $2))
-            context->recover();
-        $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable);
-        if ($$ == 0) {
-            context->unaryOpError(@1, "--", $2->getCompleteString());
-            context->recover();
-            $$ = $2;
-        }
-    }
-    | unary_operator unary_expression {
-        if ($1.op != EOpNull) {
-            $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable);
-            if ($$ == 0) {
-                const char* errorOp = "";
-                switch($1.op) {
-                case EOpNegative:   errorOp = "-"; break;
-                case EOpLogicalNot: errorOp = "!"; break;
-                default: break;
-                }
-                context->unaryOpError(@1, errorOp, $2->getCompleteString());
-                context->recover();
-                $$ = $2;
-            }
-        } else
-            $$ = $2;
-    }
-    ;
-// Grammar Note:  No traditional style type casts.
-
-unary_operator
-    : PLUS  { $$.op = EOpNull; }
-    | DASH  { $$.op = EOpNegative; }
-    | BANG  { $$.op = EOpLogicalNot; }
-    ;
-// Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
-
-multiplicative_expression
-    : unary_expression { $$ = $1; }
-    | multiplicative_expression STAR unary_expression {
-        $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
-    }
-    | multiplicative_expression SLASH unary_expression {
-        $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
-    }
-    ;
-
-additive_expression
-    : multiplicative_expression { $$ = $1; }
-    | additive_expression PLUS multiplicative_expression {
-        $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
-    }
-    | additive_expression DASH multiplicative_expression {
-        $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
-    }
-    ;
-
-shift_expression
-    : additive_expression { $$ = $1; }
-    ;
-
-relational_expression
-    : shift_expression { $$ = $1; }
-    | relational_expression LEFT_ANGLE shift_expression {
-        $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
-    }
-    | relational_expression RIGHT_ANGLE shift_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
-    }
-    | relational_expression LE_OP shift_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
-    }
-    | relational_expression GE_OP shift_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
-    }
-    ;
-
-equality_expression
-    : relational_expression { $$ = $1; }
-    | equality_expression EQ_OP relational_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
-    }
-    | equality_expression NE_OP relational_expression {
-        $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
-    }
-    ;
-
-and_expression
-    : equality_expression { $$ = $1; }
-    ;
-
-exclusive_or_expression
-    : and_expression { $$ = $1; }
-    ;
-
-inclusive_or_expression
-    : exclusive_or_expression { $$ = $1; }
-    ;
-
-logical_and_expression
-    : inclusive_or_expression { $$ = $1; }
-    | logical_and_expression AND_OP inclusive_or_expression {
-        $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
-    }
-    ;
-
-logical_xor_expression
-    : logical_and_expression { $$ = $1; }
-    | logical_xor_expression XOR_OP logical_and_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
-    }
-    ;
-
-logical_or_expression
-    : logical_xor_expression { $$ = $1; }
-    | logical_or_expression OR_OP logical_xor_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
-    }
-    ;
-
-conditional_expression
-    : logical_or_expression { $$ = $1; }
-    | logical_or_expression QUESTION expression COLON assignment_expression {
-       if (context->boolErrorCheck(@2, $1))
-            context->recover();
-
-        $$ = context->intermediate.addSelection($1, $3, $5, @2);
-        if ($3->getType() != $5->getType())
-            $$ = 0;
-
-        if ($$ == 0) {
-            context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString());
-            context->recover();
-            $$ = $5;
-        }
-    }
-    ;
-
-assignment_expression
-    : conditional_expression { $$ = $1; }
-    | unary_expression assignment_operator assignment_expression {
-        if (context->lValueErrorCheck(@2, "assign", $1))
-            context->recover();
-        $$ = context->intermediate.addAssign($2.op, $1, $3, @2);
-        if ($$ == 0) {
-            context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
-    }
-    ;
-
-assignment_operator
-    : EQUAL        { $$.op = EOpAssign; }
-    | MUL_ASSIGN   { $$.op = EOpMulAssign; }
-    | DIV_ASSIGN   { $$.op = EOpDivAssign; }
-    | ADD_ASSIGN   { $$.op = EOpAddAssign; }
-    | SUB_ASSIGN   { $$.op = EOpSubAssign; }
-    ;
-
-expression
-    : assignment_expression {
-        $$ = $1;
-    }
-    | expression COMMA assignment_expression {
-        $$ = context->intermediate.addComma($1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $3;
-        }
-    }
-    ;
-
-constant_expression
-    : conditional_expression {
-        if (context->constErrorCheck($1))
-            context->recover();
-        $$ = $1;
-    }
-    ;
-
-declaration
-    : function_prototype SEMICOLON   {
-        TFunction &function = *($1.function);
-        
-        TIntermAggregate *prototype = new TIntermAggregate;
-        prototype->setType(function.getReturnType());
-        prototype->setName(function.getName());
-        
-        for (size_t i = 0; i < function.getParamCount(); i++)
-        {
-            const TParameter &param = function.getParam(i);
-            if (param.name != 0)
-            {
-                TVariable variable(param.name, *param.type);
-                
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1);
-            }
-            else
-            {
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
-            }
-        }
-        
-        prototype->setOp(EOpPrototype);
-        $$ = prototype;
-
-        context->symbolTable.pop();
-    }
-    | init_declarator_list SEMICOLON {
-        if ($1.intermAggregate)
-            $1.intermAggregate->setOp(EOpDeclaration);
-        $$ = $1.intermAggregate;
-    }
-    | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
-        if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) {
-            context->error(@1, "precision is not supported in fragment shader", "highp");
-            context->recover();
-        }
-        if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
-            context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type));
-            context->recover();
-        }
-        $$ = 0;
-    }
-    ;
-
-function_prototype
-    : function_declarator RIGHT_PAREN  {
-        //
-        // Multiple declarations of the same function are allowed.
-        //
-        // If this is a definition, the definition production code will check for redefinitions
-        // (we don't know at this point if it's a definition or not).
-        //
-        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
-        //
-        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName()));
-        if (prevDec) {
-            if (prevDec->getReturnType() != $1->getReturnType()) {
-                context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
-                context->recover();
-            }
-            for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
-                if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
-                    context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
-                    context->recover();
-                }
-            }
-        }
-
-        //
-        // Check for previously declared variables using the same name.
-        //
-        TSymbol *prevSym = context->symbolTable.find($1->getName());
-        if (prevSym)
-        {
-            if (!prevSym->isFunction())
-            {
-                context->error(@2, "redefinition", $1->getName().c_str(), "function");
-                context->recover();
-            }
-        }
-        else
-        {
-            // Insert the unmangled name to detect potential future redefinition as a variable.
-            context->symbolTable.getOuterLevel()->insert($1->getName(), *$1);
-        }
-
-        //
-        // If this is a redeclaration, it could also be a definition,
-        // in which case, we want to use the variable names from this one, and not the one that's
-        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
-        //
-        $$.function = $1;
-
-        // We're at the inner scope level of the function's arguments and body statement.
-        // Add the function prototype to the surrounding scope instead.
-        context->symbolTable.getOuterLevel()->insert(*$$.function);
-    }
-    ;
-
-function_declarator
-    : function_header {
-        $$ = $1;
-    }
-    | function_header_with_parameters {
-        $$ = $1;
-    }
-    ;
-
-
-function_header_with_parameters
-    : function_header parameter_declaration {
-        // Add the parameter
-        $$ = $1;
-        if ($2.param.type->getBasicType() != EbtVoid)
-            $1->addParameter($2.param);
-        else
-            delete $2.param.type;
-    }
-    | function_header_with_parameters COMMA parameter_declaration {
-        //
-        // Only first parameter of one-parameter functions can be void
-        // The check for named parameters not being void is done in parameter_declarator
-        //
-        if ($3.param.type->getBasicType() == EbtVoid) {
-            //
-            // This parameter > first is void
-            //
-            context->error(@2, "cannot be an argument type except for '(void)'", "void");
-            context->recover();
-            delete $3.param.type;
-        } else {
-            // Add the parameter
-            $$ = $1;
-            $1->addParameter($3.param);
-        }
-    }
-    ;
-
-function_header
-    : fully_specified_type IDENTIFIER LEFT_PAREN {
-        if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
-            context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
-            context->recover();
-        }
-        // make sure a sampler is not involved as well...
-        if (context->structQualifierErrorCheck(@2, $1))
-            context->recover();
-
-        // Add the function as a prototype after parsing it (we do not support recursion)
-        TFunction *function;
-        TType type($1);
-        function = new TFunction($2.string, type);
-        $$ = function;
-        
-        context->symbolTable.push();
-    }
-    ;
-
-parameter_declarator
-    // Type + name
-    : type_specifier identifier {
-        if ($1.type == EbtVoid) {
-            context->error(@2, "illegal use of type 'void'", $2.string->c_str());
-            context->recover();
-        }
-        if (context->reservedErrorCheck(@2, *$2.string))
-            context->recover();
-        TParameter param = {$2.string, new TType($1)};
-        $$.param = param;
-    }
-    | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
-        // Check that we can make an array out of this type
-        if (context->arrayTypeErrorCheck(@3, $1))
-            context->recover();
-
-        if (context->reservedErrorCheck(@2, *$2.string))
-            context->recover();
-
-        int size;
-        if (context->arraySizeErrorCheck(@3, $4, size))
-            context->recover();
-        $1.setArray(true, size);
-
-        TType* type = new TType($1);
-        TParameter param = { $2.string, type };
-        $$.param = param;
-    }
-    ;
-
-parameter_declaration
-    //
-    // The only parameter qualifier a parameter can have are
-    // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
-    //
-
-    //
-    // Type + name
-    //
-    : type_qualifier parameter_qualifier parameter_declarator {
-        $$ = $3;
-        if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
-            context->recover();
-    }
-    | parameter_qualifier parameter_declarator {
-        $$ = $2;
-        if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
-            context->recover();
-        if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
-            context->recover();
-    }
-    //
-    // Only type
-    //
-    | type_qualifier parameter_qualifier parameter_type_specifier {
-        $$ = $3;
-        if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
-            context->recover();
-    }
-    | parameter_qualifier parameter_type_specifier {
-        $$ = $2;
-        if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
-            context->recover();
-        if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
-            context->recover();
-    }
-    ;
-
-parameter_qualifier
-    : /* empty */ {
-        $$ = EvqIn;
-    }
-    | IN_QUAL {
-        $$ = EvqIn;
-    }
-    | OUT_QUAL {
-        $$ = EvqOut;
-    }
-    | INOUT_QUAL {
-        $$ = EvqInOut;
-    }
-    ;
-
-parameter_type_specifier
-    : type_specifier {
-        TParameter param = { 0, new TType($1) };
-        $$.param = param;
-    }
-    ;
-
-init_declarator_list
-    : single_declaration {
-        $$ = $1;
-    }
-    | init_declarator_list COMMA identifier {
-        if ($1.type.type == EbtInvariant && !$3.symbol)
-        {
-            context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str());
-            context->recover();
-        }
-
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3);
-        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3);
-        
-        if (context->structQualifierErrorCheck(@3, $$.type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false))
-            context->recover();
-
-        TVariable* variable = 0;
-        if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable))
-            context->recover();
-        if (symbol && variable)
-            symbol->setId(variable->getUniqueId());
-    }
-    | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET {
-        if (context->structQualifierErrorCheck(@3, $1.type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
-            context->recover();
-
-        $$ = $1;
-
-        if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
-            context->recover();
-        else {
-            $1.type.setArray(true);
-            TVariable* variable;
-            if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
-                context->recover();
-        }
-    }
-    | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
-        if (context->structQualifierErrorCheck(@3, $1.type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
-            context->recover();
-
-        $$ = $1;
-
-        if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
-            context->recover();
-        else {
-            int size;
-            if (context->arraySizeErrorCheck(@4, $5, size))
-                context->recover();
-            $1.type.setArray(true, size);
-            TVariable* variable = 0;
-            if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
-                context->recover();
-            TType type = TType($1.type);
-            type.setArraySize(size);
-            $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3);
-        }
-    }
-    | init_declarator_list COMMA identifier EQUAL initializer {
-        if (context->structQualifierErrorCheck(@3, $1.type))
-            context->recover();
-
-        $$ = $1;
-
-        TIntermNode* intermNode;
-        if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) {
-            //
-            // build the intermediate representation
-            //
-            if (intermNode)
-        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4);
-            else
-                $$.intermAggregate = $1.intermAggregate;
-        } else {
-            context->recover();
-            $$.intermAggregate = 0;
-        }
-    }
-    ;
-
-single_declaration
-    : fully_specified_type {
-        $$.type = $1;
-        $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1);
-    }
-    | fully_specified_type identifier {
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
-        $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
-        
-        if (context->structQualifierErrorCheck(@2, $$.type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false))
-            context->recover();
-            
-            $$.type = $1;
-
-        TVariable* variable = 0;
-        if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable))
-            context->recover();
-        if (variable && symbol)
-            symbol->setId(variable->getUniqueId());
-    }
-    | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET {
-        context->error(@2, "unsized array declarations not supported", $2.string->c_str());
-        context->recover();
-
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
-        $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
-        $$.type = $1;
-    }
-    | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
-        TType type = TType($1);
-        int size;
-        if (context->arraySizeErrorCheck(@2, $4, size))
-            context->recover();
-        type.setArraySize(size);
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2);
-        $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
-        
-        if (context->structQualifierErrorCheck(@2, $1))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true))
-            context->recover();
-
-        $$.type = $1;
-
-        if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1))
-            context->recover();
-        else {
-            int size;
-            if (context->arraySizeErrorCheck(@3, $4, size))
-                context->recover();
-
-            $1.setArray(true, size);
-            TVariable* variable = 0;
-            if (context->arrayErrorCheck(@3, *$2.string, $1, variable))
-                context->recover();
-            if (variable && symbol)
-                symbol->setId(variable->getUniqueId());
-        }
-    }
-    | fully_specified_type identifier EQUAL initializer {
-        if (context->structQualifierErrorCheck(@2, $1))
-            context->recover();
-
-        $$.type = $1;
-
-        TIntermNode* intermNode;
-        if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) {
-        //
-        // Build intermediate representation
-        //
-            if(intermNode)
-                $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3);
-            else
-                $$.intermAggregate = 0;
-        } else {
-            context->recover();
-            $$.intermAggregate = 0;
-        }
-    }
-    | INVARIANT IDENTIFIER {
-        VERTEX_ONLY("invariant declaration", @1);
-        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
-            context->recover();
-        $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2);
-        if (!$2.symbol)
-        {
-            context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str());
-            context->recover();
-            
-            $$.intermAggregate = 0;
-        }
-        else
-        {
-            TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2);
-            $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
-        }
-    }
-    ;
-
-fully_specified_type
-    : type_specifier {
-        $$ = $1;
-
-        if ($1.array) {
-            context->error(@1, "not supported", "first-class array");
-            context->recover();
-            $1.setArray(false);
-        }
-    }
-    | type_qualifier type_specifier  {
-        if ($2.array) {
-            context->error(@2, "not supported", "first-class array");
-            context->recover();
-            $2.setArray(false);
-        }
-
-        if ($1.qualifier == EvqAttribute &&
-            ($2.type == EbtBool || $2.type == EbtInt)) {
-            context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
-            context->recover();
-        }
-        if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
-            ($2.type == EbtBool || $2.type == EbtInt)) {
-            context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
-            context->recover();
-        }
-        $$ = $2;
-        $$.qualifier = $1.qualifier;
-    }
-    ;
-
-type_qualifier
-    : CONST_QUAL {
-        $$.setBasic(EbtVoid, EvqConst, @1);
-    }
-    | ATTRIBUTE {
-        VERTEX_ONLY("attribute", @1);
-        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute"))
-            context->recover();
-        $$.setBasic(EbtVoid, EvqAttribute, @1);
-    }
-    | VARYING {
-        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying"))
-            context->recover();
-        if (context->shaderType == SH_VERTEX_SHADER)
-            $$.setBasic(EbtVoid, EvqVaryingOut, @1);
-        else
-            $$.setBasic(EbtVoid, EvqVaryingIn, @1);
-    }
-    | INVARIANT VARYING {
-        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
-            context->recover();
-        if (context->shaderType == SH_VERTEX_SHADER)
-            $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1);
-        else
-            $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1);
-    }
-    | UNIFORM {
-        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform"))
-            context->recover();
-        $$.setBasic(EbtVoid, EvqUniform, @1);
-    }
-    ;
-
-type_specifier
-    : type_specifier_no_prec {
-        $$ = $1;
-
-        if ($$.precision == EbpUndefined) {
-            $$.precision = context->symbolTable.getDefaultPrecision($1.type);
-            if (context->precisionErrorCheck(@1, $$.precision, $1.type)) {
-                context->recover();
-            }
-        }
-    }
-    | precision_qualifier type_specifier_no_prec {
-        $$ = $2;
-        $$.precision = $1;
-    }
-    ;
-
-precision_qualifier
-    : HIGH_PRECISION {
-        $$ = EbpHigh;
-    }
-    | MEDIUM_PRECISION {
-        $$ = EbpMedium;
-    }
-    | LOW_PRECISION  {
-        $$ = EbpLow;
-    }
-    ;
-
-type_specifier_no_prec
-    : type_specifier_nonarray {
-        $$ = $1;
-    }
-    | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
-        $$ = $1;
-
-        if (context->arrayTypeErrorCheck(@2, $1))
-            context->recover();
-        else {
-            int size;
-            if (context->arraySizeErrorCheck(@2, $3, size))
-                context->recover();
-            $$.setArray(true, size);
-        }
-    }
-    ;
-
-type_specifier_nonarray
-    : VOID_TYPE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtVoid, qual, @1);
-    }
-    | FLOAT_TYPE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
-    }
-    | INT_TYPE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtInt, qual, @1);
-    }
-    | BOOL_TYPE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtBool, qual, @1);
-    }
-    | VEC2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
-        $$.setAggregate(2);
-    }
-    | VEC3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
-        $$.setAggregate(3);
-    }
-    | VEC4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
-        $$.setAggregate(4);
-    }
-    | BVEC2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtBool, qual, @1);
-        $$.setAggregate(2);
-    }
-    | BVEC3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtBool, qual, @1);
-        $$.setAggregate(3);
-    }
-    | BVEC4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtBool, qual, @1);
-        $$.setAggregate(4);
-    }
-    | IVEC2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtInt, qual, @1);
-        $$.setAggregate(2);
-    }
-    | IVEC3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtInt, qual, @1);
-        $$.setAggregate(3);
-    }
-    | IVEC4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtInt, qual, @1);
-        $$.setAggregate(4);
-    }
-    | MATRIX2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
-        $$.setAggregate(2, true);
-    }
-    | MATRIX3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
-        $$.setAggregate(3, true);
-    }
-    | MATRIX4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
-        $$.setAggregate(4, true);
-    }
-    | SAMPLER2D {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSampler2D, qual, @1);
-    }
-    | SAMPLERCUBE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSamplerCube, qual, @1);
-    }
-    | SAMPLER_EXTERNAL_OES {
-        if (!context->supportsExtension("GL_OES_EGL_image_external")) {
-            context->error(@1, "unsupported type", "samplerExternalOES");
-            context->recover();
-        }
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSamplerExternalOES, qual, @1);
-    }
-    | SAMPLER2DRECT {
-        if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
-            context->error(@1, "unsupported type", "sampler2DRect");
-            context->recover();
-        }
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSampler2DRect, qual, @1);
-    }
-    | struct_specifier {
-        $$ = $1;
-        $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-    }
-    | TYPE_NAME {
-        //
-        // This is for user defined type names.  The lexical phase looked up the
-        // type.
-        //
-        TType& structure = static_cast<TVariable*>($1.symbol)->getType();
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtStruct, qual, @1);
-        $$.userDef = &structure;
-    }
-    ;
-
-struct_specifier
-    : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
-        if (context->reservedErrorCheck(@2, *$2.string))
-            context->recover();
-
-        TType* structure = new TType(new TStructure($2.string, $5));
-        TVariable* userTypeDef = new TVariable($2.string, *structure, true);
-        if (! context->symbolTable.insert(*userTypeDef)) {
-            context->error(@2, "redefinition", $2.string->c_str(), "struct");
-            context->recover();
-        }
-        $$.setBasic(EbtStruct, EvqTemporary, @1);
-        $$.userDef = structure;
-        context->exitStructDeclaration();
-    }
-    | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
-        TType* structure = new TType(new TStructure(NewPoolTString(""), $4));
-        $$.setBasic(EbtStruct, EvqTemporary, @1);
-        $$.userDef = structure;
-        context->exitStructDeclaration();
-    }
-    ;
-
-struct_declaration_list
-    : struct_declaration {
-        $$ = $1;
-    }
-    | struct_declaration_list struct_declaration {
-        $$ = $1;
-        for (size_t i = 0; i < $2->size(); ++i) {
-            TField* field = (*$2)[i];
-            for (size_t j = 0; j < $$->size(); ++j) {
-                if ((*$$)[j]->name() == field->name()) {
-                    context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str());
-                    context->recover();
-                }
-            }
-            $$->push_back(field);
-        }
-    }
-    ;
-
-struct_declaration
-    : type_specifier struct_declarator_list SEMICOLON {
-        $$ = $2;
-
-        if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) {
-            context->recover();
-        }
-        for (unsigned int i = 0; i < $$->size(); ++i) {
-            //
-            // Careful not to replace already known aspects of type, like array-ness
-            //
-            TType* type = (*$$)[i]->type();
-            type->setBasicType($1.type);
-            type->setNominalSize($1.size);
-            type->setMatrix($1.matrix);
-            type->setPrecision($1.precision);
-
-            // don't allow arrays of arrays
-            if (type->isArray()) {
-                if (context->arrayTypeErrorCheck(@1, $1))
-                    context->recover();
-            }
-            if ($1.array)
-                type->setArraySize($1.arraySize);
-            if ($1.userDef)
-                type->setStruct($1.userDef->getStruct());
-
-            if (context->structNestingErrorCheck(@1, *(*$$)[i]))
-                context->recover();
-        }
-    }
-    ;
-
-struct_declarator_list
-    : struct_declarator {
-        $$ = NewPoolTFieldList();
-        $$->push_back($1);
-    }
-    | struct_declarator_list COMMA struct_declarator {
-        $$->push_back($3);
-    }
-    ;
-
-struct_declarator
-    : identifier {
-        if (context->reservedErrorCheck(@1, *$1.string))
-            context->recover();
-
-        TType* type = new TType(EbtVoid, EbpUndefined);
-        $$ = new TField(type, $1.string);
-    }
-    | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
-        if (context->reservedErrorCheck(@1, *$1.string))
-            context->recover();
-
-        TType* type = new TType(EbtVoid, EbpUndefined);
-        int size = 0;
-        if (context->arraySizeErrorCheck(@3, $3, size))
-            context->recover();
-        type->setArraySize(size);
-
-        $$ = new TField(type, $1.string);
-    }
-    ;
-
-initializer
-    : assignment_expression { $$ = $1; }
-    ;
-
-declaration_statement
-    : declaration { $$ = $1; }
-    ;
-
-statement
-    : compound_statement  { $$ = $1; }
-    | simple_statement    { $$ = $1; }
-    ;
-
-// Grammar Note:  No labeled statements; 'goto' is not supported.
-
-simple_statement
-    : declaration_statement { $$ = $1; }
-    | expression_statement  { $$ = $1; }
-    | selection_statement   { $$ = $1; }
-    | iteration_statement   { $$ = $1; }
-    | jump_statement        { $$ = $1; }
-    ;
-
-compound_statement
-    : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
-    | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
-        if ($3 != 0) {
-            $3->setOp(EOpSequence);
-            $3->setLine(@$);
-        }
-        $$ = $3;
-    }
-    ;
-
-statement_no_new_scope
-    : compound_statement_no_new_scope { $$ = $1; }
-    | simple_statement                { $$ = $1; }
-    ;
-
-statement_with_scope
-    : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
-    | { context->symbolTable.push(); } simple_statement                { context->symbolTable.pop(); $$ = $2; }
-    ;
-
-compound_statement_no_new_scope
-    // Statement that doesn't create a new scope, for selection_statement, iteration_statement
-    : LEFT_BRACE RIGHT_BRACE {
-        $$ = 0;
-    }
-    | LEFT_BRACE statement_list RIGHT_BRACE {
-        if ($2) {
-            $2->setOp(EOpSequence);
-            $2->setLine(@$);
-        }
-        $$ = $2;
-    }
-    ;
-
-statement_list
-    : statement {
-        $$ = context->intermediate.makeAggregate($1, @$);
-    }
-    | statement_list statement {
-        $$ = context->intermediate.growAggregate($1, $2, @$);
-    }
-    ;
-
-expression_statement
-    : SEMICOLON  { $$ = 0; }
-    | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
-    ;
-
-selection_statement
-    : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
-        if (context->boolErrorCheck(@1, $3))
-            context->recover();
-        $$ = context->intermediate.addSelection($3, $5, @1);
-    }
-    ;
-
-selection_rest_statement
-    : statement_with_scope ELSE statement_with_scope {
-        $$.node1 = $1;
-        $$.node2 = $3;
-    }
-    | statement_with_scope {
-        $$.node1 = $1;
-        $$.node2 = 0;
-    }
-    ;
-
-// Grammar Note:  No 'switch'.  Switch statements not supported.
-
-condition
-    // In 1996 c++ draft, conditions can include single declarations
-    : expression {
-        $$ = $1;
-        if (context->boolErrorCheck($1->getLine(), $1))
-            context->recover();
-    }
-    | fully_specified_type identifier EQUAL initializer {
-        TIntermNode* intermNode;
-        if (context->structQualifierErrorCheck(@2, $1))
-            context->recover();
-        if (context->boolErrorCheck(@2, $1))
-            context->recover();
-
-        if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode))
-            $$ = $4;
-        else {
-            context->recover();
-            $$ = 0;
-        }
-    }
-    ;
-
-iteration_statement
-    : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
-        context->symbolTable.pop();
-        $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
-        --context->loopNestingLevel;
-    }
-    | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
-        if (context->boolErrorCheck(@8, $6))
-            context->recover();
-
-        $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
-        --context->loopNestingLevel;
-    }
-    | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
-        context->symbolTable.pop();
-        $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
-        --context->loopNestingLevel;
-    }
-    ;
-
-for_init_statement
-    : expression_statement {
-        $$ = $1;
-    }
-    | declaration_statement {
-        $$ = $1;
-    }
-    ;
-
-conditionopt
-    : condition {
-        $$ = $1;
-    }
-    | /* May be null */ {
-        $$ = 0;
-    }
-    ;
-
-for_rest_statement
-    : conditionopt SEMICOLON {
-        $$.node1 = $1;
-        $$.node2 = 0;
-    }
-    | conditionopt SEMICOLON expression  {
-        $$.node1 = $1;
-        $$.node2 = $3;
-    }
-    ;
-
-jump_statement
-    : CONTINUE SEMICOLON {
-        if (context->loopNestingLevel <= 0) {
-            context->error(@1, "continue statement only allowed in loops", "");
-            context->recover();
-        }
-        $$ = context->intermediate.addBranch(EOpContinue, @1);
-    }
-    | BREAK SEMICOLON {
-        if (context->loopNestingLevel <= 0) {
-            context->error(@1, "break statement only allowed in loops", "");
-            context->recover();
-        }
-        $$ = context->intermediate.addBranch(EOpBreak, @1);
-    }
-    | RETURN SEMICOLON {
-        $$ = context->intermediate.addBranch(EOpReturn, @1);
-        if (context->currentFunctionType->getBasicType() != EbtVoid) {
-            context->error(@1, "non-void function must return a value", "return");
-            context->recover();
-        }
-    }
-    | RETURN expression SEMICOLON {
-        $$ = context->intermediate.addBranch(EOpReturn, $2, @1);
-        context->functionReturnsValue = true;
-        if (context->currentFunctionType->getBasicType() == EbtVoid) {
-            context->error(@1, "void function cannot return a value", "return");
-            context->recover();
-        } else if (*(context->currentFunctionType) != $2->getType()) {
-            context->error(@1, "function return is not matching type:", "return");
-            context->recover();
-        }
-    }
-    | DISCARD SEMICOLON {
-        FRAG_ONLY("discard", @1);
-        $$ = context->intermediate.addBranch(EOpKill, @1);
-    }
-    ;
-
-// Grammar Note:  No 'goto'.  Gotos are not supported.
-
-translation_unit
-    : external_declaration {
-        $$ = $1;
-        context->treeRoot = $$;
-    }
-    | translation_unit external_declaration {
-        $$ = context->intermediate.growAggregate($1, $2, @$);
-        context->treeRoot = $$;
-    }
-    ;
-
-external_declaration
-    : function_definition {
-        $$ = $1;
-    }
-    | declaration {
-        $$ = $1;
-    }
-    ;
-
-function_definition
-    : function_prototype {
-        TFunction* function = $1.function;
-        
-        const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName());
-        
-        if (builtIn)
-        {
-            context->error(@1, "built-in functions cannot be redefined", function->getName().c_str());
-            context->recover();
-        }
-        
-        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName()));
-        //
-        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
-        // as it would have just been put in the symbol table.  Otherwise, we're looking up
-        // an earlier occurance.
-        //
-        if (prevDec->isDefined()) {
-            //
-            // Then this function already has a body.
-            //
-            context->error(@1, "function already has a body", function->getName().c_str());
-            context->recover();
-        }
-        prevDec->setDefined();
-
-        //
-        // Raise error message if main function takes any parameters or return anything other than void
-        //
-        if (function->getName() == "main") {
-            if (function->getParamCount() > 0) {
-                context->error(@1, "function cannot take any parameter(s)", function->getName().c_str());
-                context->recover();
-            }
-            if (function->getReturnType().getBasicType() != EbtVoid) {
-                context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value");
-                context->recover();
-            }
-        }
-
-        //
-        // Remember the return type for later checking for RETURN statements.
-        //
-        context->currentFunctionType = &(prevDec->getReturnType());
-        context->functionReturnsValue = false;
-
-        //
-        // Insert parameters into the symbol table.
-        // If the parameter has no name, it's not an error, just don't insert it
-        // (could be used for unused args).
-        //
-        // Also, accumulate the list of parameters into the HIL, so lower level code
-        // knows where to find parameters.
-        //
-        TIntermAggregate* paramNodes = new TIntermAggregate;
-        for (size_t i = 0; i < function->getParamCount(); i++) {
-            const TParameter& param = function->getParam(i);
-            if (param.name != 0) {
-                TVariable *variable = new TVariable(param.name, *param.type);
-                //
-                // Insert the parameters with name in the symbol table.
-                //
-                if (! context->symbolTable.insert(*variable)) {
-                    context->error(@1, "redefinition", variable->getName().c_str());
-                    context->recover();
-                    delete variable;
-                }
-
-                //
-                // Add the parameter to the HIL
-                //
-                paramNodes = context->intermediate.growAggregate(
-                                               paramNodes,
-                                               context->intermediate.addSymbol(variable->getUniqueId(),
-                                                                               variable->getName(),
-                                                                               variable->getType(),
-                                                                               @1),
-                                               @1);
-            } else {
-                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
-            }
-        }
-        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
-        $1.intermAggregate = paramNodes;
-        context->loopNestingLevel = 0;
-    }
-    compound_statement_no_new_scope {
-        //?? Check that all paths return a value if return type != void ?
-        //   May be best done as post process phase on intermediate code
-        if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
-            context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
-            context->recover();
-        }
-        
-        $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$);
-        context->intermediate.setAggregateOperator($$, EOpFunction, @1);
-        $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
-        $$->getAsAggregate()->setType($1.function->getReturnType());
-
-        // store the pragma information for debug and optimize and other vendor specific
-        // information. This information can be queried from the parse tree
-        $$->getAsAggregate()->setOptimize(context->pragma().optimize);
-        $$->getAsAggregate()->setDebug(context->pragma().debug);
-
-        context->symbolTable.pop();
-    }
-    ;
-
-%%
-
-void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) {
-    context->error(*yylloc, reason, "");
-    context->recover();
-}
-
-int glslang_parse(TParseContext* context) {
-    return yyparse(context);
-}
diff --git a/src/third_party/angle/src/compiler/glslang_lex.cpp b/src/third_party/angle/src/compiler/glslang_lex.cpp
deleted file mode 100644
index 9f95521..0000000
--- a/src/third_party/angle/src/compiler/glslang_lex.cpp
+++ /dev/null
@@ -1,2940 +0,0 @@
-#line 17 "./glslang.l"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
-
-// Ignore errors in auto-generated code.
-#if defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wunused-function"
-#pragma GCC diagnostic ignored "-Wunused-variable"
-#pragma GCC diagnostic ignored "-Wswitch-enum"
-#elif defined(_MSC_VER)
-#pragma warning(disable: 4065)
-#pragma warning(disable: 4189)
-#pragma warning(disable: 4505)
-#pragma warning(disable: 4701)
-#endif
-
-
-
-#line 25 "./glslang_lex.cpp"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-typedef uint64_t flex_uint64_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
-   are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yyg->yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yyg->yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
-     *       access to the local variable yy_act. Since yyless() is a macro, it would break
-     *       existing scanners that call yyless() from OUTSIDE yylex. 
-     *       One obvious solution it to make yy_act a global. I tried that, and saw
-     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
-     *       normally declared as a register variable-- so it is not worth it.
-     */
-    #define  YY_LESS_LINENO(n) \
-            do { \
-                yy_size_t yyl;\
-                for ( yyl = n; yyl < yyleng; ++yyl )\
-                    if ( yytext[yyl] == '\n' )\
-                        --yylineno;\
-            }while(0)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = yyg->yy_hold_char; \
-		YY_RESTORE_YY_MORE_OFFSET \
-		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	yy_size_t yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via yyrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
-                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-
-void yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void yypop_buffer_state (yyscan_t yyscanner );
-
-static void yyensure_buffer_stack (yyscan_t yyscanner );
-static void yy_load_buffer_state (yyscan_t yyscanner );
-static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
-
-void *yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void yyfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        yyensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        yyensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-typedef int yy_state_type;
-
-#define yytext_ptr yytext_r
-
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	yyg->yytext_ptr = yy_bp; \
-	yyleng = (yy_size_t) (yy_cp - yy_bp); \
-	yyg->yy_hold_char = *yy_cp; \
-	*yy_cp = '\0'; \
-	yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 147
-#define YY_END_OF_BUFFER 148
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[443] =
-    {   0,
-        0,    0,  148,  146,  145,  145,  132,  138,  143,  127,
-      128,  136,  135,  124,  133,  131,  137,   96,   96,  125,
-      121,  139,  126,  140,  144,   93,  129,  130,  142,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,  122,
-      141,  123,  134,  118,  104,  123,  112,  107,  102,  110,
-      100,  111,  101,   99,  103,   98,   95,   96,    0,    0,
-      130,  122,  129,  119,  115,  117,  116,  120,   93,  108,
-      114,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   12,   93,   93,   93,   93,   93,   93,   93,   93,
-
-       93,   93,   93,   93,   93,   15,   17,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,  109,  113,    0,   98,    0,    0,
-       97,   94,  105,  106,   45,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   13,   93,   93,   93,   93,   93,   93,
-       93,   93,   21,   93,   93,   93,   93,   93,   93,   93,
-       93,   18,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-
-       93,   93,   93,   93,   93,    0,   99,    0,   98,   93,
-       23,   93,   93,   90,   93,   93,   93,   93,   93,   93,
-       93,   16,   48,   93,   93,   93,   64,   93,   93,   53,
-       68,   93,   93,   93,   93,   93,   93,   93,   93,   65,
-        4,   28,   29,   30,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       51,   24,   93,   93,   93,   93,   93,   93,   31,   32,
-       33,   22,   93,   93,   93,   10,   37,   38,   39,   46,
-        7,   93,   93,   93,   93,   77,   78,   79,   93,   25,
-       69,   20,   80,   81,   82,    2,   74,   75,   76,   93,
-
-       19,   72,   93,   93,   34,   35,   36,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   66,   93,   93,   93,
-       93,   93,   93,   93,   93,   47,   93,   92,   93,   93,
-       14,   93,   93,   93,   93,   67,   61,   56,   93,   93,
-       93,   93,   93,   73,   52,   93,   59,   27,   93,   89,
-       60,   44,   71,   54,   93,   93,   93,   93,   93,   93,
-       93,   93,   55,   26,   93,   93,   93,    3,   93,   93,
-       93,   93,   93,   49,    8,   93,    9,   93,   93,   11,
-       62,   93,   93,   93,   57,   93,   93,   93,   93,   93,
-       93,   50,   70,   58,    6,   63,    1,   91,    5,   83,
-
-       40,   84,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   41,   93,   93,   93,   93,   93,
-       93,   93,   43,   93,   87,   93,   93,   93,   93,   93,
-       85,   93,   86,   93,   93,   93,   93,   93,   93,   42,
-       88,    0
-    } ;
-
-static yyconst flex_int32_t yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        2,    2,    2,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    4,    1,    1,    1,    5,    6,    1,    7,
-        8,    9,   10,   11,   12,   13,   14,   15,   16,   17,
-       18,   19,   20,   20,   20,   21,   21,   22,   23,   24,
-       25,   26,   27,    1,   28,   28,   29,   30,   31,   28,
-       32,   32,   32,   32,   32,   32,   32,   32,   33,   32,
-       32,   34,   35,   32,   32,   32,   32,   36,   32,   32,
-       37,    1,   38,   39,   32,    1,   40,   41,   42,   43,
-
-       44,   45,   46,   47,   48,   32,   49,   50,   51,   52,
-       53,   54,   32,   55,   56,   57,   58,   59,   60,   61,
-       62,   63,   64,   65,   66,   67,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_int32_t yy_meta[68] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    2,    2,    2,    2,    2,    2,
-        2,    1,    1,    1,    1,    1,    1,    2,    2,    2,
-        2,    3,    3,    3,    3,    3,    1,    1,    1,    2,
-        2,    2,    2,    2,    2,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_int16_t yy_base[445] =
-    {   0,
-        0,    0,  587,  588,  588,  588,  561,   43,   64,  588,
-      588,  560,   61,  588,   60,   58,  559,   77,   86,  557,
-      588,  104,  557,   55,  588,    0,  588,  588,   75,   26,
-       57,   82,   83,   73,   93,  528,   97,   95,  527,   44,
-       71,  521,  104,  534,  110,  116,   35,  111,  530,  588,
-      114,  588,  588,  588,  588,  588,  588,  588,  588,  588,
-      588,  588,  588,  165,  588,  172,  202,  211,  233,    0,
-      588,  588,  588,  551,  588,  588,  588,  550,    0,  588,
-      588,  523,  516,  519,  527,  526,  513,  528,  515,  521,
-      509,  506,  519,  506,  503,  503,  509,  497,  108,  502,
-
-      512,  498,  504,  507,  508,    0,  145,  507,  113,  493,
-      506,  497,  499,  489,  503,  500,  502,  485,  490,  487,
-      476,  157,  484,  489,  485,  487,  476,  479,  118,  484,
-      476,  488,   70,  481,  588,  588,  246,  253,  270,  219,
-      283,    0,  588,  588,    0,  473,  477,  486,  483,  467,
-      467,  119,  482,  479,  479,  477,  474,  466,  472,  459,
-      470,  456,  472,    0,  469,  457,  464,  461,  465,  458,
-      447,  446,  459,  462,  459,  454,  445,  188,  450,  453,
-      444,  441,  445,  451,  442,  433,  436,  434,  444,  430,
-      428,  441,  427,  429,  426,  437,  436,  124,  431,  426,
-
-      415,  258,  433,  435,  424,  290,  297,  304,  311,  425,
-        0,  423,  275,    0,  415,  413,  421,  410,  427,  416,
-      316,    0,    0,  410,  420,  420,    0,  405,  319,    0,
-        0,  407,  322,  408,  402,  401,  402,  401,  325,    0,
-        0,    0,    0,    0,  397,  398,  403,  394,  407,  402,
-      401,  393,  397,  389,  392,  396,  401,  387,  399,  390,
-        0,    0,  396,  385,  385,  390,  389,  386,    0,    0,
-        0,    0,  376,  388,  390,    0,    0,    0,    0,    0,
-        0,  378,  379,  373,  383,    0,    0,    0,  374,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,  381,
-
-        0,    0,  379,  375,    0,    0,    0,  371,  367,  372,
-      362,  375,  361,  374,  363,  370,    0,  368,  370,  354,
-      356,  362,  368,  363,  351,    0,  353,    0,  352,  355,
-        0,  344,  343,  343,  356,    0,  358,    0,  357,  356,
-      341,  354,  341,    0,    0,  344,    0,    0,  336,    0,
-        0,    0,    0,    0,  333,  344,  337,  343,  340,  335,
-      327,  339,    0,    0,  332,  339,  328,    0,  337,  334,
-      324,  329,  332,    0,    0,  332,    0,  330,  329,    0,
-        0,  328,  314,  326,    0,  317,  338,  337,  336,  307,
-      303,    0,    0,    0,    0,    0,    0,    0,    0,  328,
-
-      166,  325,  316,  299,  308,  310,  306,  308,  307,  306,
-      309,  306,  256,  253,    0,  228,  238,  222,  235,  203,
-      207,  204,  212,  191,    0,  201,  165,  167,  153,  161,
-        0,  170,    0,  175,  151,  141,  100,  114,   59,    0,
-        0,  588,  359,  113
-    } ;
-
-static yyconst flex_int16_t yy_def[445] =
-    {   0,
-      442,    1,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  443,  442,  442,  442,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  444,
-      442,  442,  442,  442,  442,  442,  442,  442,  443,  442,
-      442,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  442,  442,  442,  442,  442,  442,
-      442,  444,  442,  442,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-
-      443,  443,  443,  443,  443,  442,  442,  442,  442,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,    0,  442,  442
-    } ;
-
-static yyconst flex_int16_t yy_nxt[656] =
-    {   0,
-        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
-       14,   15,   16,   17,   18,   19,   19,   19,   19,   19,
-       19,   20,   21,   22,   23,   24,   25,   26,   26,   26,
-       26,   26,   26,   26,   26,   26,   27,   28,   29,   30,
-       31,   32,   33,   34,   35,   36,   37,   38,   26,   39,
-       40,   41,   42,   43,   44,   45,   46,   47,   48,   49,
-       26,   26,   26,   50,   51,   52,   53,   55,   56,   57,
-       60,   62,   64,   64,   64,   64,   64,   64,   64,   77,
-       78,   82,   83,  110,   63,   61,  129,  111,   58,   66,
-      130,   67,   67,   67,   67,   67,   67,   68,   66,   80,
-
-       68,   68,   68,   68,   68,   68,   68,   69,   72,   84,
-      112,   85,   70,   81,  142,   86,   69,  203,  441,  204,
-       69,   87,   94,  113,   95,   73,   90,   74,   75,   69,
-       91,   88,   97,   96,   89,   92,  103,   70,  135,  106,
-       98,   93,   99,  115,  104,  100,  107,  162,  440,  119,
-      131,  101,  439,  108,  132,  105,  120,  121,  116,  125,
-      163,  117,  126,  133,  176,  198,  122,  123,  264,  124,
-      127,  438,  177,  199,  216,  217,  265,  128,  136,   64,
-       64,   64,   64,   64,   64,   64,  138,  138,  138,  138,
-      138,  138,  138,  437,  170,  137,  190,  171,  172,  406,
-
-      407,  173,  139,  174,  242,  243,  244,  436,  137,  435,
-      434,  191,  433,  432,   66,  139,   67,   67,   67,   67,
-       67,   67,   68,   66,  431,   68,   68,   68,   68,   68,
-       68,   68,   69,  141,  141,  141,  141,  141,  141,  141,
-      430,   69,  140,  429,  140,   69,  428,  141,  141,  141,
-      141,  141,  141,  141,   69,  206,  427,  206,  426,  425,
-      207,  207,  207,  207,  207,  207,  207,  138,  138,  138,
-      138,  138,  138,  138,  269,  270,  271,  424,  423,  208,
-      422,  208,  421,  139,  209,  209,  209,  209,  209,  209,
-      209,  277,  278,  279,  420,  419,  139,  141,  141,  141,
-
-      141,  141,  141,  141,  207,  207,  207,  207,  207,  207,
-      207,  207,  207,  207,  207,  207,  207,  207,  209,  209,
-      209,  209,  209,  209,  209,  209,  209,  209,  209,  209,
-      209,  209,  286,  287,  288,  293,  294,  295,  297,  298,
-      299,  305,  306,  307,  387,  388,  389,  418,  417,  416,
-      415,  414,  413,  412,  411,  410,  409,  390,  408,  391,
-       79,   79,  405,  404,  403,  402,  401,  400,  399,  398,
-      397,  396,  395,  394,  393,  392,  386,  385,  384,  383,
-      382,  381,  380,  379,  378,  377,  376,  375,  374,  373,
-      372,  371,  370,  369,  368,  367,  366,  365,  364,  363,
-
-      362,  361,  360,  359,  358,  357,  356,  355,  354,  353,
-      352,  351,  350,  349,  348,  347,  346,  345,  344,  343,
-      342,  341,  340,  339,  338,  337,  336,  335,  334,  333,
-      332,  331,  330,  329,  328,  327,  326,  325,  324,  323,
-      322,  321,  320,  319,  318,  317,  316,  315,  314,  313,
-      312,  311,  310,  309,  308,  304,  303,  302,  301,  300,
-      296,  292,  291,  290,  289,  285,  284,  283,  282,  281,
-      280,  276,  275,  274,  273,  272,  268,  267,  266,  263,
-      262,  261,  260,  259,  258,  257,  256,  255,  254,  253,
-      252,  251,  250,  249,  248,  247,  246,  245,  241,  240,
-
-      239,  238,  237,  236,  235,  234,  233,  232,  231,  230,
-      229,  228,  227,  226,  225,  224,  223,  222,  221,  220,
-      219,  218,  215,  214,  213,  212,  211,  210,  205,  202,
-      201,  200,  197,  196,  195,  194,  193,  192,  189,  188,
-      187,  186,  185,  184,  183,  182,  181,  180,  179,  178,
-      175,  169,  168,  167,  166,  165,  164,  161,  160,  159,
-      158,  157,  156,  155,  154,  153,  152,  151,  150,  149,
-      148,  147,  146,  145,  144,  143,  134,  118,  114,  109,
-      102,   76,   71,   65,   59,   54,  442,    3,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442
-    } ;
-
-static yyconst flex_int16_t yy_chk[656] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    8,    8,    9,
-       13,   15,   16,   16,   16,   16,   16,   16,   16,   24,
-       24,   30,   30,   40,   15,   13,   47,   40,    9,   18,
-       47,   18,   18,   18,   18,   18,   18,   18,   19,   29,
-
-       19,   19,   19,   19,   19,   19,   19,   18,   22,   31,
-       41,   31,   18,   29,  444,   31,   19,  133,  439,  133,
-       18,   32,   34,   41,   34,   22,   33,   22,   22,   19,
-       33,   32,   35,   34,   32,   33,   37,   18,   51,   38,
-       35,   33,   35,   43,   37,   35,   38,   99,  438,   45,
-       48,   35,  437,   38,   48,   37,   45,   45,   43,   46,
-       99,   43,   46,   48,  109,  129,   45,   45,  198,   45,
-       46,  436,  109,  129,  152,  152,  198,   46,   51,   64,
-       64,   64,   64,   64,   64,   64,   66,   66,   66,   66,
-       66,   66,   66,  435,  107,   64,  122,  107,  107,  401,
-
-      401,  107,   66,  107,  178,  178,  178,  434,   64,  432,
-      430,  122,  429,  428,   67,   66,   67,   67,   67,   67,
-       67,   67,   67,   68,  427,   68,   68,   68,   68,   68,
-       68,   68,   67,  140,  140,  140,  140,  140,  140,  140,
-      426,   68,   69,  424,   69,   67,  423,   69,   69,   69,
-       69,   69,   69,   69,   68,  137,  422,  137,  421,  420,
-      137,  137,  137,  137,  137,  137,  137,  138,  138,  138,
-      138,  138,  138,  138,  202,  202,  202,  419,  418,  139,
-      417,  139,  416,  138,  139,  139,  139,  139,  139,  139,
-      139,  213,  213,  213,  414,  413,  138,  141,  141,  141,
-
-      141,  141,  141,  141,  206,  206,  206,  206,  206,  206,
-      206,  207,  207,  207,  207,  207,  207,  207,  208,  208,
-      208,  208,  208,  208,  208,  209,  209,  209,  209,  209,
-      209,  209,  221,  221,  221,  229,  229,  229,  233,  233,
-      233,  239,  239,  239,  372,  372,  372,  412,  411,  410,
-      409,  408,  407,  406,  405,  404,  403,  372,  402,  372,
-      443,  443,  400,  391,  390,  389,  388,  387,  386,  384,
-      383,  382,  379,  378,  376,  373,  371,  370,  369,  367,
-      366,  365,  362,  361,  360,  359,  358,  357,  356,  355,
-      349,  346,  343,  342,  341,  340,  339,  337,  335,  334,
-
-      333,  332,  330,  329,  327,  325,  324,  323,  322,  321,
-      320,  319,  318,  316,  315,  314,  313,  312,  311,  310,
-      309,  308,  304,  303,  300,  289,  285,  284,  283,  282,
-      275,  274,  273,  268,  267,  266,  265,  264,  263,  260,
-      259,  258,  257,  256,  255,  254,  253,  252,  251,  250,
-      249,  248,  247,  246,  245,  238,  237,  236,  235,  234,
-      232,  228,  226,  225,  224,  220,  219,  218,  217,  216,
-      215,  212,  210,  205,  204,  203,  201,  200,  199,  197,
-      196,  195,  194,  193,  192,  191,  190,  189,  188,  187,
-      186,  185,  184,  183,  182,  181,  180,  179,  177,  176,
-
-      175,  174,  173,  172,  171,  170,  169,  168,  167,  166,
-      165,  163,  162,  161,  160,  159,  158,  157,  156,  155,
-      154,  153,  151,  150,  149,  148,  147,  146,  134,  132,
-      131,  130,  128,  127,  126,  125,  124,  123,  121,  120,
-      119,  118,  117,  116,  115,  114,  113,  112,  111,  110,
-      108,  105,  104,  103,  102,  101,  100,   98,   97,   96,
-       95,   94,   93,   92,   91,   90,   89,   88,   87,   86,
-       85,   84,   83,   82,   78,   74,   49,   44,   42,   39,
-       36,   23,   20,   17,   12,    7,    3,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442,  442,  442,  442,  442,  442,
-      442,  442,  442,  442,  442
-    } ;
-
-/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[148] =
-    {   0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 1, 0, 0,     };
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-/*
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-This file contains the Lex specification for GLSL ES.
-Based on ANSI C grammar, Lex specification:
-http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
-
-IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
-WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
-*/
-
-#include "compiler/glslang.h"
-#include "compiler/ParseHelper.h"
-#include "compiler/preprocessor/Token.h"
-#include "compiler/util.h"
-#include "glslang_tab.h"
-
-/* windows only pragma */
-#ifdef _MSC_VER
-#pragma warning(disable : 4102)
-#endif
-
-#define YY_USER_ACTION                                 \
-    yylloc->first_file = yylloc->last_file = yycolumn; \
-    yylloc->first_line = yylloc->last_line = yylineno;
-
-#define YY_INPUT(buf, result, max_size) \
-    result = string_input(buf, max_size, yyscanner);
-
-static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
-static int check_type(yyscan_t yyscanner);
-static int reserved_word(yyscan_t yyscanner);
-
-#define INITIAL 0
-
-#define YY_EXTRA_TYPE TParseContext*
-
-/* Holds the entire state of the reentrant scanner. */
-struct yyguts_t
-    {
-
-    /* User-defined. Not touched by flex. */
-    YY_EXTRA_TYPE yyextra_r;
-
-    /* The rest are the same as the globals declared in the non-reentrant scanner. */
-    FILE *yyin_r, *yyout_r;
-    size_t yy_buffer_stack_top; /**< index of top of stack. */
-    size_t yy_buffer_stack_max; /**< capacity of stack. */
-    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
-    char yy_hold_char;
-    yy_size_t yy_n_chars;
-    yy_size_t yyleng_r;
-    char *yy_c_buf_p;
-    int yy_init;
-    int yy_start;
-    int yy_did_buffer_switch_on_eof;
-    int yy_start_stack_ptr;
-    int yy_start_stack_depth;
-    int *yy_start_stack;
-    yy_state_type yy_last_accepting_state;
-    char* yy_last_accepting_cpos;
-
-    int yylineno_r;
-    int yy_flex_debug_r;
-
-    char *yytext_r;
-    int yy_more_flag;
-    int yy_more_len;
-
-    YYSTYPE * yylval_r;
-
-    YYLTYPE * yylloc_r;
-
-    }; /* end struct yyguts_t */
-
-static int yy_init_globals (yyscan_t yyscanner );
-
-    /* This must go here because YYSTYPE and YYLTYPE are included
-     * from bison output in section 1.*/
-    #    define yylval yyg->yylval_r
-    
-    #    define yylloc yyg->yylloc_r
-    
-int yylex_init (yyscan_t* scanner);
-
-int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int yylex_destroy (yyscan_t yyscanner );
-
-int yyget_debug (yyscan_t yyscanner );
-
-void yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
-
-void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *yyget_in (yyscan_t yyscanner );
-
-void yyset_in  (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *yyget_out (yyscan_t yyscanner );
-
-void yyset_out  (FILE * out_str ,yyscan_t yyscanner );
-
-yy_size_t yyget_leng (yyscan_t yyscanner );
-
-char *yyget_text (yyscan_t yyscanner );
-
-int yyget_lineno (yyscan_t yyscanner );
-
-void yyset_lineno (int line_number ,yyscan_t yyscanner );
-
-YYSTYPE * yyget_lval (yyscan_t yyscanner );
-
-void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
-
-       YYLTYPE *yyget_lloc (yyscan_t yyscanner );
-    
-        void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
-    
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap (yyscan_t yyscanner );
-#else
-extern int yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
-#else
-static int input (yyscan_t yyscanner );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO fwrite( yytext, yyleng, 1, yyout )
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		yy_size_t n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int yylex \
-               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
-
-#define YY_DECL int yylex \
-               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    yylval = yylval_param;
-
-    yylloc = yylloc_param;
-
-	if ( !yyg->yy_init )
-		{
-		yyg->yy_init = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! yyg->yy_start )
-			yyg->yy_start = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			yyensure_buffer_stack (yyscanner);
-			YY_CURRENT_BUFFER_LVALUE =
-				yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-		}
-
-		yy_load_buffer_state(yyscanner );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = yyg->yy_c_buf_p;
-
-		/* Support of yytext. */
-		*yy_cp = yyg->yy_hold_char;
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = yyg->yy_start;
-yy_match:
-		do
-			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
-			if ( yy_accept[yy_current_state] )
-				{
-				yyg->yy_last_accepting_state = yy_current_state;
-				yyg->yy_last_accepting_cpos = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 443 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-			++yy_cp;
-			}
-		while ( yy_current_state != 442 );
-		yy_cp = yyg->yy_last_accepting_cpos;
-		yy_current_state = yyg->yy_last_accepting_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
-			{
-			yy_size_t yyl;
-			for ( yyl = 0; yyl < yyleng; ++yyl )
-				if ( yytext[yyl] == '\n' )
-					   
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-			}
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = yyg->yy_hold_char;
-			yy_cp = yyg->yy_last_accepting_cpos;
-			yy_current_state = yyg->yy_last_accepting_state;
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-{ return INVARIANT; }
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-{ return HIGH_PRECISION; }
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-{ return MEDIUM_PRECISION; }
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-{ return LOW_PRECISION; }
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-{ return PRECISION; }
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-{ return ATTRIBUTE; }
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-{ return CONST_QUAL; }
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-{ return UNIFORM; }
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-{ return VARYING; }
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-{ return BREAK; }
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-{ return CONTINUE; }
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-{ return DO; }
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-{ return FOR; }
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-{ return WHILE; }
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-{ return IF; }
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-{ return ELSE; }
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-{ return IN_QUAL; }
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-{ return OUT_QUAL; }
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-{ return INOUT_QUAL; }
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-{ return FLOAT_TYPE; }
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-{ return INT_TYPE; }
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-{ return VOID_TYPE; }
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-{ return BOOL_TYPE; }
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-{ yylval->lex.b = true;  return BOOLCONSTANT; }
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-{ yylval->lex.b = false; return BOOLCONSTANT; }
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-{ return DISCARD; }
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-{ return RETURN; }
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-{ return MATRIX2; }
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-{ return MATRIX3; }
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-{ return MATRIX4; }
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-{ return VEC2; }
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-{ return VEC3; }
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-{ return VEC4; }
-	YY_BREAK
-case 34:
-YY_RULE_SETUP
-{ return IVEC2; }
-	YY_BREAK
-case 35:
-YY_RULE_SETUP
-{ return IVEC3; }
-	YY_BREAK
-case 36:
-YY_RULE_SETUP
-{ return IVEC4; }
-	YY_BREAK
-case 37:
-YY_RULE_SETUP
-{ return BVEC2; }
-	YY_BREAK
-case 38:
-YY_RULE_SETUP
-{ return BVEC3; }
-	YY_BREAK
-case 39:
-YY_RULE_SETUP
-{ return BVEC4; }
-	YY_BREAK
-case 40:
-YY_RULE_SETUP
-{ return SAMPLER2D; }
-	YY_BREAK
-case 41:
-YY_RULE_SETUP
-{ return SAMPLERCUBE; }
-	YY_BREAK
-case 42:
-YY_RULE_SETUP
-{ return SAMPLER_EXTERNAL_OES; }
-	YY_BREAK
-case 43:
-YY_RULE_SETUP
-{ return SAMPLER2DRECT; }
-	YY_BREAK
-case 44:
-YY_RULE_SETUP
-{ return STRUCT; }
-	YY_BREAK
-case 45:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 46:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 47:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 48:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 49:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 50:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 51:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 52:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 53:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 54:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 55:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 56:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 57:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 58:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 59:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 60:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 61:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 62:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 63:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 64:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 65:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 66:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 67:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 68:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 69:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 70:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 71:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 72:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 73:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 74:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 75:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 76:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 77:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 78:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 79:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 80:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 81:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 82:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 83:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 84:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 85:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 86:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 87:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 88:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 89:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 90:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 91:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 92:
-YY_RULE_SETUP
-{ return reserved_word(yyscanner); }
-	YY_BREAK
-case 93:
-YY_RULE_SETUP
-{
-   yylval->lex.string = NewPoolTString(yytext); 
-   return check_type(yyscanner);
-}
-	YY_BREAK
-case 94:
-YY_RULE_SETUP
-{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
-	YY_BREAK
-case 95:
-YY_RULE_SETUP
-{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
-	YY_BREAK
-case 96:
-YY_RULE_SETUP
-{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
-	YY_BREAK
-case 97:
-YY_RULE_SETUP
-{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
-	YY_BREAK
-case 98:
-YY_RULE_SETUP
-{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
-	YY_BREAK
-case 99:
-YY_RULE_SETUP
-{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
-	YY_BREAK
-case 100:
-YY_RULE_SETUP
-{ return ADD_ASSIGN; }
-	YY_BREAK
-case 101:
-YY_RULE_SETUP
-{ return SUB_ASSIGN; }
-	YY_BREAK
-case 102:
-YY_RULE_SETUP
-{ return MUL_ASSIGN; }
-	YY_BREAK
-case 103:
-YY_RULE_SETUP
-{ return DIV_ASSIGN; }
-	YY_BREAK
-case 104:
-YY_RULE_SETUP
-{ return MOD_ASSIGN; }
-	YY_BREAK
-case 105:
-YY_RULE_SETUP
-{ return LEFT_ASSIGN; }
-	YY_BREAK
-case 106:
-YY_RULE_SETUP
-{ return RIGHT_ASSIGN; }
-	YY_BREAK
-case 107:
-YY_RULE_SETUP
-{ return AND_ASSIGN; }
-	YY_BREAK
-case 108:
-YY_RULE_SETUP
-{ return XOR_ASSIGN; }
-	YY_BREAK
-case 109:
-YY_RULE_SETUP
-{ return OR_ASSIGN; }
-	YY_BREAK
-case 110:
-YY_RULE_SETUP
-{ return INC_OP; }
-	YY_BREAK
-case 111:
-YY_RULE_SETUP
-{ return DEC_OP; }
-	YY_BREAK
-case 112:
-YY_RULE_SETUP
-{ return AND_OP; }
-	YY_BREAK
-case 113:
-YY_RULE_SETUP
-{ return OR_OP; }
-	YY_BREAK
-case 114:
-YY_RULE_SETUP
-{ return XOR_OP; }
-	YY_BREAK
-case 115:
-YY_RULE_SETUP
-{ return LE_OP; }
-	YY_BREAK
-case 116:
-YY_RULE_SETUP
-{ return GE_OP; }
-	YY_BREAK
-case 117:
-YY_RULE_SETUP
-{ return EQ_OP; }
-	YY_BREAK
-case 118:
-YY_RULE_SETUP
-{ return NE_OP; }
-	YY_BREAK
-case 119:
-YY_RULE_SETUP
-{ return LEFT_OP; }
-	YY_BREAK
-case 120:
-YY_RULE_SETUP
-{ return RIGHT_OP; }
-	YY_BREAK
-case 121:
-YY_RULE_SETUP
-{ return SEMICOLON; }
-	YY_BREAK
-case 122:
-YY_RULE_SETUP
-{ return LEFT_BRACE; }
-	YY_BREAK
-case 123:
-YY_RULE_SETUP
-{ return RIGHT_BRACE; }
-	YY_BREAK
-case 124:
-YY_RULE_SETUP
-{ return COMMA; }
-	YY_BREAK
-case 125:
-YY_RULE_SETUP
-{ return COLON; }
-	YY_BREAK
-case 126:
-YY_RULE_SETUP
-{ return EQUAL; }
-	YY_BREAK
-case 127:
-YY_RULE_SETUP
-{ return LEFT_PAREN; }
-	YY_BREAK
-case 128:
-YY_RULE_SETUP
-{ return RIGHT_PAREN; }
-	YY_BREAK
-case 129:
-YY_RULE_SETUP
-{ return LEFT_BRACKET; }
-	YY_BREAK
-case 130:
-YY_RULE_SETUP
-{ return RIGHT_BRACKET; }
-	YY_BREAK
-case 131:
-YY_RULE_SETUP
-{ return DOT; }
-	YY_BREAK
-case 132:
-YY_RULE_SETUP
-{ return BANG; }
-	YY_BREAK
-case 133:
-YY_RULE_SETUP
-{ return DASH; }
-	YY_BREAK
-case 134:
-YY_RULE_SETUP
-{ return TILDE; }
-	YY_BREAK
-case 135:
-YY_RULE_SETUP
-{ return PLUS; }
-	YY_BREAK
-case 136:
-YY_RULE_SETUP
-{ return STAR; }
-	YY_BREAK
-case 137:
-YY_RULE_SETUP
-{ return SLASH; }
-	YY_BREAK
-case 138:
-YY_RULE_SETUP
-{ return PERCENT; }
-	YY_BREAK
-case 139:
-YY_RULE_SETUP
-{ return LEFT_ANGLE; }
-	YY_BREAK
-case 140:
-YY_RULE_SETUP
-{ return RIGHT_ANGLE; }
-	YY_BREAK
-case 141:
-YY_RULE_SETUP
-{ return VERTICAL_BAR; }
-	YY_BREAK
-case 142:
-YY_RULE_SETUP
-{ return CARET; }
-	YY_BREAK
-case 143:
-YY_RULE_SETUP
-{ return AMPERSAND; }
-	YY_BREAK
-case 144:
-YY_RULE_SETUP
-{ return QUESTION; }
-	YY_BREAK
-case 145:
-/* rule 145 can match eol */
-YY_RULE_SETUP
-{ }
-	YY_BREAK
-case YY_STATE_EOF(INITIAL):
-{ yyterminate(); }
-	YY_BREAK
-case 146:
-YY_RULE_SETUP
-{ assert(false); return 0; }
-	YY_BREAK
-case 147:
-YY_RULE_SETUP
-ECHO;
-	YY_BREAK
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = yyg->yy_hold_char;
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * yylex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state( yyscanner );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
-
-			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++yyg->yy_c_buf_p;
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = yyg->yy_last_accepting_cpos;
-				yy_current_state = yyg->yy_last_accepting_state;
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer( yyscanner ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				yyg->yy_did_buffer_switch_on_eof = 0;
-
-				if ( yywrap(yyscanner ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				yyg->yy_c_buf_p =
-					yyg->yytext_ptr + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				yyg->yy_c_buf_p =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = yyg->yytext_ptr;
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
-
-	else
-		{
-			yy_size_t num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				yy_size_t new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			yyg->yy_n_chars, num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	if ( yyg->yy_n_chars == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			yyrestart(yyin  ,yyscanner);
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	yyg->yy_n_chars += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
-	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	yy_current_state = yyg->yy_start;
-
-	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
-		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			yyg->yy_last_accepting_state = yy_current_state;
-			yyg->yy_last_accepting_cpos = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 443 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
-{
-	register int yy_is_jam;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
-	register char *yy_cp = yyg->yy_c_buf_p;
-
-	register YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		yyg->yy_last_accepting_state = yy_current_state;
-		yyg->yy_last_accepting_cpos = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 443 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 442);
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (yyscan_t yyscanner)
-#else
-    static int input  (yyscan_t yyscanner)
-#endif
-
-{
-	int c;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	*yyg->yy_c_buf_p = yyg->yy_hold_char;
-
-	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			/* This was really a NUL. */
-			*yyg->yy_c_buf_p = '\0';
-
-		else
-			{ /* need more input */
-			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
-			++yyg->yy_c_buf_p;
-
-			switch ( yy_get_next_buffer( yyscanner ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					yyrestart(yyin ,yyscanner);
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( yywrap(yyscanner ) )
-						return EOF;
-
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput(yyscanner);
-#else
-					return input(yyscanner);
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
-	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
-	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
-
-	if ( c == '\n' )
-		   
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * @param yyscanner The scanner object.
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void yyrestart  (FILE * input_file , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! YY_CURRENT_BUFFER ){
-        yyensure_buffer_stack (yyscanner);
-		YY_CURRENT_BUFFER_LVALUE =
-            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-	}
-
-	yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
-	yy_load_buffer_state(yyscanner );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
-    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		yypop_buffer_state();
-	 *		yypush_buffer_state(new_buffer);
-     */
-	yyensure_buffer_stack (yyscanner);
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	yy_load_buffer_state(yyscanner );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (yywrap()) processing, but the only time this flag
-	 * is looked at is after yywrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void yy_load_buffer_state  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	yyg->yy_hold_char = *yyg->yy_c_buf_p;
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * @param yyscanner The scanner object.
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	yy_init_buffer(b,file ,yyscanner);
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with yy_create_buffer()
- * @param yyscanner The scanner object.
- */
-    void yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		yyfree((void *) b->yy_ch_buf ,yyscanner );
-
-	yyfree((void *) b ,yyscanner );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a yyrestart() or at EOF.
- */
-    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
-
-{
-	int oerrno = errno;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	yy_flush_buffer(b ,yyscanner);
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then yy_init_buffer was _probably_
-     * called from yyrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * @param yyscanner The scanner object.
- */
-    void yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		yy_load_buffer_state(yyscanner );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  @param yyscanner The scanner object.
- */
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (new_buffer == NULL)
-		return;
-
-	yyensure_buffer_stack(yyscanner);
-
-	/* This block is copied from yy_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		yyg->yy_buffer_stack_top++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from yy_switch_to_buffer. */
-	yy_load_buffer_state(yyscanner );
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  @param yyscanner The scanner object.
- */
-void yypop_buffer_state (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (!YY_CURRENT_BUFFER)
-		return;
-
-	yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if (yyg->yy_buffer_stack_top > 0)
-		--yyg->yy_buffer_stack_top;
-
-	if (YY_CURRENT_BUFFER) {
-		yy_load_buffer_state(yyscanner );
-		yyg->yy_did_buffer_switch_on_eof = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void yyensure_buffer_stack (yyscan_t yyscanner)
-{
-	yy_size_t num_to_alloc;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if (!yyg->yy_buffer_stack) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-		num_to_alloc = 1;
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-								  
-		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		yyg->yy_buffer_stack_max = num_to_alloc;
-		yyg->yy_buffer_stack_top = 0;
-		return;
-	}
-
-	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
-								(yyg->yy_buffer_stack,
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
-		yyg->yy_buffer_stack_max = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	yy_switch_to_buffer(b ,yyscanner );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-    
-	return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
- * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n, i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) yyalloc(n ,yyscanner );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = yy_scan_buffer(buf,n ,yyscanner);
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = yyg->yy_hold_char; \
-		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
-		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
-		*yyg->yy_c_buf_p = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the user-defined data for this scanner.
- * @param yyscanner The scanner object.
- */
-YY_EXTRA_TYPE yyget_extra  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyextra;
-}
-
-/** Get the current line number.
- * @param yyscanner The scanner object.
- */
-int yyget_lineno  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yylineno;
-}
-
-/** Get the current column number.
- * @param yyscanner The scanner object.
- */
-int yyget_column  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yycolumn;
-}
-
-/** Get the input stream.
- * @param yyscanner The scanner object.
- */
-FILE *yyget_in  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyin;
-}
-
-/** Get the output stream.
- * @param yyscanner The scanner object.
- */
-FILE *yyget_out  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyout;
-}
-
-/** Get the length of the current token.
- * @param yyscanner The scanner object.
- */
-yy_size_t yyget_leng  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyleng;
-}
-
-/** Get the current token.
- * @param yyscanner The scanner object.
- */
-
-char *yyget_text  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yytext;
-}
-
-/** Set the user-defined data. This data is never touched by the scanner.
- * @param user_defined The data to be associated with this scanner.
- * @param yyscanner The scanner object.
- */
-void yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyextra = user_defined ;
-}
-
-/** Set the current line number.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void yyset_lineno (int  line_number , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* lineno is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           yy_fatal_error( "yyset_lineno called with no buffer" , yyscanner); 
-    
-    yylineno = line_number;
-}
-
-/** Set the current column.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void yyset_column (int  column_no , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* column is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           yy_fatal_error( "yyset_column called with no buffer" , yyscanner); 
-    
-    yycolumn = column_no;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * @param yyscanner The scanner object.
- * @see yy_switch_to_buffer
- */
-void yyset_in (FILE *  in_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyin = in_str ;
-}
-
-void yyset_out (FILE *  out_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyout = out_str ;
-}
-
-int yyget_debug  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yy_flex_debug;
-}
-
-void yyset_debug (int  bdebug , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yy_flex_debug = bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-YYSTYPE * yyget_lval  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yylval;
-}
-
-void yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yylval = yylval_param;
-}
-
-YYLTYPE *yyget_lloc  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yylloc;
-}
-    
-void yyset_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yylloc = yylloc_param;
-}
-    
-/* User-visible API */
-
-/* yylex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int yylex_init(yyscan_t* ptr_yy_globals)
-
-{
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-
-    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
-
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-
-    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-/* yylex_init_extra has the same functionality as yylex_init, but follows the
- * convention of taking the scanner as the last argument. Note however, that
- * this is a *pointer* to a scanner, as it will be allocated by this call (and
- * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to yyalloc in
- * the yyextra field.
- */
-
-int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
-{
-    struct yyguts_t dummy_yyguts;
-
-    yyset_extra (yy_user_defined, &dummy_yyguts);
-
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-	
-    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-	
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-    
-    /* By setting to 0xAA, we expose bugs in
-    yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-    
-    yyset_extra (yy_user_defined, *ptr_yy_globals);
-    
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-static int yy_init_globals (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from yylex_destroy(), so don't allocate here.
-     */
-
-    yyg->yy_buffer_stack = 0;
-    yyg->yy_buffer_stack_top = 0;
-    yyg->yy_buffer_stack_max = 0;
-    yyg->yy_c_buf_p = (char *) 0;
-    yyg->yy_init = 0;
-    yyg->yy_start = 0;
-
-    yyg->yy_start_stack_ptr = 0;
-    yyg->yy_start_stack_depth = 0;
-    yyg->yy_start_stack =  NULL;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    yyin = stdin;
-    yyout = stdout;
-#else
-    yyin = (FILE *) 0;
-    yyout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * yylex_init()
-     */
-    return 0;
-}
-
-/* yylex_destroy is for both reentrant and non-reentrant scanners. */
-int yylex_destroy  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		yypop_buffer_state(yyscanner);
-	}
-
-	/* Destroy the stack itself. */
-	yyfree(yyg->yy_buffer_stack ,yyscanner);
-	yyg->yy_buffer_stack = NULL;
-
-    /* Destroy the start condition stack. */
-        yyfree(yyg->yy_start_stack ,yyscanner );
-        yyg->yy_start_stack = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * yylex() is called, initialization will occur. */
-    yy_init_globals( yyscanner);
-
-    /* Destroy the main struct (reentrant only). */
-    yyfree ( yyscanner , yyscanner );
-    yyscanner = NULL;
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *yyalloc (yy_size_t  size , yyscan_t yyscanner)
-{
-	return (void *) malloc( size );
-}
-
-void *yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
-{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-}
-
-void yyfree (void * ptr , yyscan_t yyscanner)
-{
-	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
-    pp::Token token;
-    yyget_extra(yyscanner)->preprocessor.lex(&token);
-    yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
-    if (len < max_size)
-        memcpy(buf, token.text.c_str(), len);
-    yyset_column(token.location.file,yyscanner);
-    yyset_lineno(token.location.line,yyscanner);
-
-    if (len >= max_size)
-        YY_FATAL_ERROR("Input buffer overflow");
-    else if (len > 0)
-        buf[len++] = ' ';
-    return len;
-}
-
-int check_type(yyscan_t yyscanner) {
-    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
-    
-    int token = IDENTIFIER;
-    TSymbol* symbol = yyextra->symbolTable.find(yytext);
-    if (symbol && symbol->isVariable()) {
-        TVariable* variable = static_cast<TVariable*>(symbol);
-        if (variable->isUserType())
-            token = TYPE_NAME;
-    }
-    yylval->lex.symbol = symbol;
-    return token;
-}
-
-int reserved_word(yyscan_t yyscanner) {
-    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
-
-    yyextra->error(*yylloc, "Illegal use of reserved word", yytext, "");
-    yyextra->recover();
-    return 0;
-}
-
-int glslang_initialize(TParseContext* context) {
-    yyscan_t scanner = NULL;
-    if (yylex_init_extra(context,&scanner))
-        return 1;
-
-    context->scanner = scanner;
-    return 0;
-}
-
-int glslang_finalize(TParseContext* context) {
-    yyscan_t scanner = context->scanner;
-    if (scanner == NULL) return 0;
-    
-    context->scanner = NULL;
-    yylex_destroy(scanner);
-
-    return 0;
-}
-
-int glslang_scan(size_t count, const char* const string[], const int length[],
-                 TParseContext* context) {
-    yyrestart(NULL,context->scanner);
-    yyset_column(0,context->scanner);
-    yyset_lineno(1,context->scanner);
-
-    // Initialize preprocessor.
-    if (!context->preprocessor.init(count, string, length))
-        return 1;
-
-    // Define extension macros.
-    const TExtensionBehavior& extBehavior = context->extensionBehavior();
-    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
-         iter != extBehavior.end(); ++iter) {
-        context->preprocessor.predefineMacro(iter->first.c_str(), 1);
-    }
-    if (context->fragmentPrecisionHigh)
-        context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
-
-    return 0;
-}
-
diff --git a/src/third_party/angle/src/compiler/glslang_tab.cpp b/src/third_party/angle/src/compiler/glslang_tab.cpp
deleted file mode 100644
index 7afd4ca..0000000
--- a/src/third_party/angle/src/compiler/glslang_tab.cpp
+++ /dev/null
@@ -1,4882 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.7.  */
-
-/* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-   
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-   
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.7"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 1
-
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
-
-
-
-/* Copy the first part of user declarations.  */
-
-
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
-
-// Ignore errors in auto-generated code.
-#if defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wunused-function"
-#pragma GCC diagnostic ignored "-Wunused-variable"
-#pragma GCC diagnostic ignored "-Wswitch-enum"
-#elif defined(_MSC_VER)
-#pragma warning(disable: 4065)
-#pragma warning(disable: 4189)
-#pragma warning(disable: 4505)
-#pragma warning(disable: 4701)
-#endif
-
-#include "compiler/SymbolTable.h"
-#include "compiler/ParseHelper.h"
-#include "GLSLANG/ShaderLang.h"
-
-#define YYENABLE_NLS 0
-
-#define YYLEX_PARAM context->scanner
-
-
-
-# ifndef YY_NULL
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULL nullptr
-#  else
-#   define YY_NULL 0
-#  endif
-# endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* In a future release of Bison, this section will be replaced
-   by #include "glslang_tab.h".  */
-#ifndef YY_YY_GLSLANG_TAB_H_INCLUDED
-# define YY_YY_GLSLANG_TAB_H_INCLUDED
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-/* "%code requires" blocks.  */
-
-
-#define YYLTYPE TSourceLoc
-#define YYLTYPE_IS_DECLARED 1
-
-
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     INVARIANT = 258,
-     HIGH_PRECISION = 259,
-     MEDIUM_PRECISION = 260,
-     LOW_PRECISION = 261,
-     PRECISION = 262,
-     ATTRIBUTE = 263,
-     CONST_QUAL = 264,
-     BOOL_TYPE = 265,
-     FLOAT_TYPE = 266,
-     INT_TYPE = 267,
-     BREAK = 268,
-     CONTINUE = 269,
-     DO = 270,
-     ELSE = 271,
-     FOR = 272,
-     IF = 273,
-     DISCARD = 274,
-     RETURN = 275,
-     BVEC2 = 276,
-     BVEC3 = 277,
-     BVEC4 = 278,
-     IVEC2 = 279,
-     IVEC3 = 280,
-     IVEC4 = 281,
-     VEC2 = 282,
-     VEC3 = 283,
-     VEC4 = 284,
-     MATRIX2 = 285,
-     MATRIX3 = 286,
-     MATRIX4 = 287,
-     IN_QUAL = 288,
-     OUT_QUAL = 289,
-     INOUT_QUAL = 290,
-     UNIFORM = 291,
-     VARYING = 292,
-     STRUCT = 293,
-     VOID_TYPE = 294,
-     WHILE = 295,
-     SAMPLER2D = 296,
-     SAMPLERCUBE = 297,
-     SAMPLER_EXTERNAL_OES = 298,
-     SAMPLER2DRECT = 299,
-     IDENTIFIER = 300,
-     TYPE_NAME = 301,
-     FLOATCONSTANT = 302,
-     INTCONSTANT = 303,
-     BOOLCONSTANT = 304,
-     LEFT_OP = 305,
-     RIGHT_OP = 306,
-     INC_OP = 307,
-     DEC_OP = 308,
-     LE_OP = 309,
-     GE_OP = 310,
-     EQ_OP = 311,
-     NE_OP = 312,
-     AND_OP = 313,
-     OR_OP = 314,
-     XOR_OP = 315,
-     MUL_ASSIGN = 316,
-     DIV_ASSIGN = 317,
-     ADD_ASSIGN = 318,
-     MOD_ASSIGN = 319,
-     LEFT_ASSIGN = 320,
-     RIGHT_ASSIGN = 321,
-     AND_ASSIGN = 322,
-     XOR_ASSIGN = 323,
-     OR_ASSIGN = 324,
-     SUB_ASSIGN = 325,
-     LEFT_PAREN = 326,
-     RIGHT_PAREN = 327,
-     LEFT_BRACKET = 328,
-     RIGHT_BRACKET = 329,
-     LEFT_BRACE = 330,
-     RIGHT_BRACE = 331,
-     DOT = 332,
-     COMMA = 333,
-     COLON = 334,
-     EQUAL = 335,
-     SEMICOLON = 336,
-     BANG = 337,
-     DASH = 338,
-     TILDE = 339,
-     PLUS = 340,
-     STAR = 341,
-     SLASH = 342,
-     PERCENT = 343,
-     LEFT_ANGLE = 344,
-     RIGHT_ANGLE = 345,
-     VERTICAL_BAR = 346,
-     CARET = 347,
-     AMPERSAND = 348,
-     QUESTION = 349
-   };
-#endif
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-
-
-    struct {
-        union {
-            TString *string;
-            float f;
-            int i;
-            bool b;
-        };
-        TSymbol* symbol;
-    } lex;
-    struct {
-        TOperator op;
-        union {
-            TIntermNode* intermNode;
-            TIntermNodePair nodePair;
-            TIntermTyped* intermTypedNode;
-            TIntermAggregate* intermAggregate;
-        };
-        union {
-            TPublicType type;
-            TPrecision precision;
-            TQualifier qualifier;
-            TFunction* function;
-            TParameter param;
-            TField* field;
-            TFieldList* fieldList;
-        };
-    } interm;
-
-
-
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
-{
-  int first_line;
-  int first_column;
-  int last_line;
-  int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (TParseContext* context);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_GLSLANG_TAB_H_INCLUDED  */
-
-/* Copy the second part of user declarations.  */
-
-
-extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
-static void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason);
-
-#define YYLLOC_DEFAULT(Current, Rhs, N)                      \
-  do {                                                       \
-      if (YYID(N)) {                                         \
-        (Current).first_file = YYRHSLOC(Rhs, 1).first_file;  \
-        (Current).first_line = YYRHSLOC(Rhs, 1).first_line;  \
-        (Current).last_file = YYRHSLOC(Rhs, N).last_file;    \
-        (Current).last_line = YYRHSLOC(Rhs, N).last_line;    \
-      }                                                      \
-      else {                                                 \
-        (Current).first_file = YYRHSLOC(Rhs, 0).last_file;   \
-        (Current).first_line = YYRHSLOC(Rhs, 0).last_line;   \
-        (Current).last_file = YYRHSLOC(Rhs, 0).last_file;    \
-        (Current).last_line = YYRHSLOC(Rhs, 0).last_line;    \
-      }                                                      \
-  } while (0)
-
-#define VERTEX_ONLY(S, L) {  \
-    if (context->shaderType != SH_VERTEX_SHADER) {  \
-        context->error(L, " supported in vertex shaders only ", S);  \
-        context->recover();  \
-    }  \
-}
-
-#define FRAG_ONLY(S, L) {  \
-    if (context->shaderType != SH_FRAGMENT_SHADER) {  \
-        context->error(L, " supported in fragment shaders only ", S);  \
-        context->recover();  \
-    }  \
-}
-
-
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(Msgid) Msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
-#else
-# define YYUSE(E) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(N) (N)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
-#else
-static int
-YYID (yyi)
-    int yyi;
-#endif
-{
-  return yyi;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
-       && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef EXIT_SUCCESS
-#    define EXIT_SUCCESS 0
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-	 || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
-	     && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss_alloc;
-  YYSTYPE yyvs_alloc;
-  YYLTYPE yyls_alloc;
-};
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
-      + 2 * YYSTACK_GAP_MAXIMUM)
-
-# define YYCOPY_NEEDED 1
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(Dst, Src, Count) \
-      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
-#  else
-#   define YYCOPY(Dst, Src, Count)              \
-      do                                        \
-        {                                       \
-          YYSIZE_T yyi;                         \
-          for (yyi = 0; yyi < (Count); yyi++)   \
-            (Dst)[yyi] = (Src)[yyi];            \
-        }                                       \
-      while (YYID (0))
-#  endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  74
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   1490
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  95
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  84
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  202
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  307
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   349
-
-#define YYTRANSLATE(YYX)						\
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
-      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
-      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
-      85,    86,    87,    88,    89,    90,    91,    92,    93,    94
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     5,     7,     9,    11,    13,    15,    17,
-      21,    23,    28,    30,    34,    37,    40,    42,    44,    46,
-      50,    53,    56,    59,    61,    64,    68,    71,    73,    75,
-      77,    80,    83,    86,    88,    90,    92,    94,    98,   102,
-     104,   108,   112,   114,   116,   120,   124,   128,   132,   134,
-     138,   142,   144,   146,   148,   150,   154,   156,   160,   162,
-     166,   168,   174,   176,   180,   182,   184,   186,   188,   190,
-     192,   196,   198,   201,   204,   209,   212,   214,   216,   219,
-     223,   227,   230,   236,   240,   243,   247,   250,   251,   253,
-     255,   257,   259,   261,   265,   271,   278,   284,   286,   289,
-     294,   300,   305,   308,   310,   313,   315,   317,   319,   322,
-     324,   326,   329,   331,   333,   335,   337,   342,   344,   346,
-     348,   350,   352,   354,   356,   358,   360,   362,   364,   366,
-     368,   370,   372,   374,   376,   378,   380,   382,   384,   386,
-     387,   394,   395,   401,   403,   406,   410,   412,   416,   418,
-     423,   425,   427,   429,   431,   433,   435,   437,   439,   441,
-     444,   445,   446,   452,   454,   456,   457,   460,   461,   464,
-     467,   471,   473,   476,   478,   481,   487,   491,   493,   495,
-     500,   501,   508,   509,   518,   519,   527,   529,   531,   533,
-     534,   537,   541,   544,   547,   550,   554,   557,   559,   562,
-     564,   566,   567
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int16 yyrhs[] =
-{
-     175,     0,    -1,    45,    -1,    46,    -1,    45,    -1,    97,
-      -1,    48,    -1,    47,    -1,    49,    -1,    71,   124,    72,
-      -1,    98,    -1,    99,    73,   100,    74,    -1,   101,    -1,
-      99,    77,    96,    -1,    99,    52,    -1,    99,    53,    -1,
-     124,    -1,   102,    -1,   103,    -1,    99,    77,   103,    -1,
-     105,    72,    -1,   104,    72,    -1,   106,    39,    -1,   106,
-      -1,   106,   122,    -1,   105,    78,   122,    -1,   107,    71,
-      -1,   142,    -1,    45,    -1,    99,    -1,    52,   108,    -1,
-      53,   108,    -1,   109,   108,    -1,    85,    -1,    83,    -1,
-      82,    -1,   108,    -1,   110,    86,   108,    -1,   110,    87,
-     108,    -1,   110,    -1,   111,    85,   110,    -1,   111,    83,
-     110,    -1,   111,    -1,   112,    -1,   113,    89,   112,    -1,
-     113,    90,   112,    -1,   113,    54,   112,    -1,   113,    55,
-     112,    -1,   113,    -1,   114,    56,   113,    -1,   114,    57,
-     113,    -1,   114,    -1,   115,    -1,   116,    -1,   117,    -1,
-     118,    58,   117,    -1,   118,    -1,   119,    60,   118,    -1,
-     119,    -1,   120,    59,   119,    -1,   120,    -1,   120,    94,
-     124,    79,   122,    -1,   121,    -1,   108,   123,   122,    -1,
-      80,    -1,    61,    -1,    62,    -1,    63,    -1,    70,    -1,
-     122,    -1,   124,    78,   122,    -1,   121,    -1,   127,    81,
-      -1,   135,    81,    -1,     7,   140,   141,    81,    -1,   128,
-      72,    -1,   130,    -1,   129,    -1,   130,   132,    -1,   129,
-      78,   132,    -1,   137,    45,    71,    -1,   139,    96,    -1,
-     139,    96,    73,   125,    74,    -1,   138,   133,   131,    -1,
-     133,   131,    -1,   138,   133,   134,    -1,   133,   134,    -1,
-      -1,    33,    -1,    34,    -1,    35,    -1,   139,    -1,   136,
-      -1,   135,    78,    96,    -1,   135,    78,    96,    73,    74,
-      -1,   135,    78,    96,    73,   125,    74,    -1,   135,    78,
-      96,    80,   150,    -1,   137,    -1,   137,    96,    -1,   137,
-      96,    73,    74,    -1,   137,    96,    73,   125,    74,    -1,
-     137,    96,    80,   150,    -1,     3,    45,    -1,   139,    -1,
-     138,   139,    -1,     9,    -1,     8,    -1,    37,    -1,     3,
-      37,    -1,    36,    -1,   141,    -1,   140,   141,    -1,     4,
-      -1,     5,    -1,     6,    -1,   142,    -1,   142,    73,   125,
-      74,    -1,    39,    -1,    11,    -1,    12,    -1,    10,    -1,
-      27,    -1,    28,    -1,    29,    -1,    21,    -1,    22,    -1,
-      23,    -1,    24,    -1,    25,    -1,    26,    -1,    30,    -1,
-      31,    -1,    32,    -1,    41,    -1,    42,    -1,    43,    -1,
-      44,    -1,   143,    -1,    46,    -1,    -1,    38,    96,    75,
-     144,   146,    76,    -1,    -1,    38,    75,   145,   146,    76,
-      -1,   147,    -1,   146,   147,    -1,   139,   148,    81,    -1,
-     149,    -1,   148,    78,   149,    -1,    96,    -1,    96,    73,
-     125,    74,    -1,   122,    -1,   126,    -1,   154,    -1,   153,
-      -1,   151,    -1,   163,    -1,   164,    -1,   167,    -1,   174,
-      -1,    75,    76,    -1,    -1,    -1,    75,   155,   162,   156,
-      76,    -1,   161,    -1,   153,    -1,    -1,   159,   161,    -1,
-      -1,   160,   153,    -1,    75,    76,    -1,    75,   162,    76,
-      -1,   152,    -1,   162,   152,    -1,    81,    -1,   124,    81,
-      -1,    18,    71,   124,    72,   165,    -1,   158,    16,   158,
-      -1,   158,    -1,   124,    -1,   137,    96,    80,   150,    -1,
-      -1,    40,    71,   168,   166,    72,   157,    -1,    -1,    15,
-     169,   158,    40,    71,   124,    72,    81,    -1,    -1,    17,
-      71,   170,   171,   173,    72,   157,    -1,   163,    -1,   151,
-      -1,   166,    -1,    -1,   172,    81,    -1,   172,    81,   124,
-      -1,    14,    81,    -1,    13,    81,    -1,    20,    81,    -1,
-      20,   124,    81,    -1,    19,    81,    -1,   176,    -1,   175,
-     176,    -1,   177,    -1,   126,    -1,    -1,   127,   178,   161,
-      -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,   179,   179,   180,   183,   226,   229,   242,   247,   252,
-     258,   261,   264,   267,   362,   372,   385,   393,   493,   496,
-     504,   507,   513,   517,   524,   530,   539,   547,   602,   612,
-     615,   625,   635,   656,   657,   658,   663,   664,   672,   683,
-     684,   692,   703,   707,   708,   718,   728,   738,   751,   752,
-     762,   775,   779,   783,   787,   788,   801,   802,   815,   816,
-     829,   830,   847,   848,   861,   862,   863,   864,   865,   869,
-     872,   883,   891,   918,   923,   937,   992,   995,  1002,  1010,
-    1031,  1052,  1062,  1090,  1095,  1105,  1110,  1120,  1123,  1126,
-    1129,  1135,  1142,  1145,  1167,  1185,  1209,  1232,  1236,  1254,
-    1262,  1294,  1314,  1335,  1344,  1367,  1370,  1376,  1384,  1392,
-    1400,  1410,  1417,  1420,  1423,  1429,  1432,  1447,  1451,  1455,
-    1459,  1463,  1468,  1473,  1478,  1483,  1488,  1493,  1498,  1503,
-    1508,  1513,  1518,  1523,  1527,  1531,  1539,  1547,  1551,  1564,
-    1564,  1578,  1578,  1587,  1590,  1606,  1639,  1643,  1649,  1656,
-    1671,  1675,  1679,  1680,  1686,  1687,  1688,  1689,  1690,  1694,
-    1695,  1695,  1695,  1705,  1706,  1710,  1710,  1711,  1711,  1716,
-    1719,  1729,  1732,  1738,  1739,  1743,  1751,  1755,  1765,  1770,
-    1787,  1787,  1792,  1792,  1799,  1799,  1807,  1810,  1816,  1819,
-    1825,  1829,  1836,  1843,  1850,  1857,  1868,  1877,  1881,  1888,
-    1891,  1897,  1897
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || 0
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "INVARIANT", "HIGH_PRECISION",
-  "MEDIUM_PRECISION", "LOW_PRECISION", "PRECISION", "ATTRIBUTE",
-  "CONST_QUAL", "BOOL_TYPE", "FLOAT_TYPE", "INT_TYPE", "BREAK", "CONTINUE",
-  "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN", "BVEC2", "BVEC3",
-  "BVEC4", "IVEC2", "IVEC3", "IVEC4", "VEC2", "VEC3", "VEC4", "MATRIX2",
-  "MATRIX3", "MATRIX4", "IN_QUAL", "OUT_QUAL", "INOUT_QUAL", "UNIFORM",
-  "VARYING", "STRUCT", "VOID_TYPE", "WHILE", "SAMPLER2D", "SAMPLERCUBE",
-  "SAMPLER_EXTERNAL_OES", "SAMPLER2DRECT", "IDENTIFIER", "TYPE_NAME",
-  "FLOATCONSTANT", "INTCONSTANT", "BOOLCONSTANT", "LEFT_OP", "RIGHT_OP",
-  "INC_OP", "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP",
-  "OR_OP", "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN",
-  "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN",
-  "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACKET",
-  "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT", "COMMA", "COLON",
-  "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", "STAR", "SLASH",
-  "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", "CARET",
-  "AMPERSAND", "QUESTION", "$accept", "identifier", "variable_identifier",
-  "primary_expression", "postfix_expression", "integer_expression",
-  "function_call", "function_call_or_method", "function_call_generic",
-  "function_call_header_no_parameters",
-  "function_call_header_with_parameters", "function_call_header",
-  "function_identifier", "unary_expression", "unary_operator",
-  "multiplicative_expression", "additive_expression", "shift_expression",
-  "relational_expression", "equality_expression", "and_expression",
-  "exclusive_or_expression", "inclusive_or_expression",
-  "logical_and_expression", "logical_xor_expression",
-  "logical_or_expression", "conditional_expression",
-  "assignment_expression", "assignment_operator", "expression",
-  "constant_expression", "declaration", "function_prototype",
-  "function_declarator", "function_header_with_parameters",
-  "function_header", "parameter_declarator", "parameter_declaration",
-  "parameter_qualifier", "parameter_type_specifier",
-  "init_declarator_list", "single_declaration", "fully_specified_type",
-  "type_qualifier", "type_specifier", "precision_qualifier",
-  "type_specifier_no_prec", "type_specifier_nonarray", "struct_specifier",
-  "$@1", "$@2", "struct_declaration_list", "struct_declaration",
-  "struct_declarator_list", "struct_declarator", "initializer",
-  "declaration_statement", "statement", "simple_statement",
-  "compound_statement", "$@3", "$@4", "statement_no_new_scope",
-  "statement_with_scope", "$@5", "$@6", "compound_statement_no_new_scope",
-  "statement_list", "expression_statement", "selection_statement",
-  "selection_rest_statement", "condition", "iteration_statement", "$@7",
-  "$@8", "$@9", "for_init_statement", "conditionopt", "for_rest_statement",
-  "jump_statement", "translation_unit", "external_declaration",
-  "function_definition", "$@10", YY_NULL
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
-     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
-     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
-     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
-     335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
-     345,   346,   347,   348,   349
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    95,    96,    96,    97,    98,    98,    98,    98,    98,
-      99,    99,    99,    99,    99,    99,   100,   101,   102,   102,
-     103,   103,   104,   104,   105,   105,   106,   107,   107,   108,
-     108,   108,   108,   109,   109,   109,   110,   110,   110,   111,
-     111,   111,   112,   113,   113,   113,   113,   113,   114,   114,
-     114,   115,   116,   117,   118,   118,   119,   119,   120,   120,
-     121,   121,   122,   122,   123,   123,   123,   123,   123,   124,
-     124,   125,   126,   126,   126,   127,   128,   128,   129,   129,
-     130,   131,   131,   132,   132,   132,   132,   133,   133,   133,
-     133,   134,   135,   135,   135,   135,   135,   136,   136,   136,
-     136,   136,   136,   137,   137,   138,   138,   138,   138,   138,
-     139,   139,   140,   140,   140,   141,   141,   142,   142,   142,
-     142,   142,   142,   142,   142,   142,   142,   142,   142,   142,
-     142,   142,   142,   142,   142,   142,   142,   142,   142,   144,
-     143,   145,   143,   146,   146,   147,   148,   148,   149,   149,
-     150,   151,   152,   152,   153,   153,   153,   153,   153,   154,
-     155,   156,   154,   157,   157,   159,   158,   160,   158,   161,
-     161,   162,   162,   163,   163,   164,   165,   165,   166,   166,
-     168,   167,   169,   167,   170,   167,   171,   171,   172,   172,
-     173,   173,   174,   174,   174,   174,   174,   175,   175,   176,
-     176,   178,   177
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     1,     1,     1,     1,     1,     1,     1,     3,
-       1,     4,     1,     3,     2,     2,     1,     1,     1,     3,
-       2,     2,     2,     1,     2,     3,     2,     1,     1,     1,
-       2,     2,     2,     1,     1,     1,     1,     3,     3,     1,
-       3,     3,     1,     1,     3,     3,     3,     3,     1,     3,
-       3,     1,     1,     1,     1,     3,     1,     3,     1,     3,
-       1,     5,     1,     3,     1,     1,     1,     1,     1,     1,
-       3,     1,     2,     2,     4,     2,     1,     1,     2,     3,
-       3,     2,     5,     3,     2,     3,     2,     0,     1,     1,
-       1,     1,     1,     3,     5,     6,     5,     1,     2,     4,
-       5,     4,     2,     1,     2,     1,     1,     1,     2,     1,
-       1,     2,     1,     1,     1,     1,     4,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     0,
-       6,     0,     5,     1,     2,     3,     1,     3,     1,     4,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     2,
-       0,     0,     5,     1,     1,     0,     2,     0,     2,     2,
-       3,     1,     2,     1,     2,     5,     3,     1,     1,     4,
-       0,     6,     0,     8,     0,     7,     1,     1,     1,     0,
-       2,     3,     2,     2,     2,     3,     2,     1,     2,     1,
-       1,     0,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
-   Performed when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       0,     0,   112,   113,   114,     0,   106,   105,   120,   118,
-     119,   124,   125,   126,   127,   128,   129,   121,   122,   123,
-     130,   131,   132,   109,   107,     0,   117,   133,   134,   135,
-     136,   138,   200,   201,     0,    77,    87,     0,    92,    97,
-       0,   103,     0,   110,   115,   137,     0,   197,   199,   108,
-     102,     0,     2,     3,   141,     0,    72,     0,    75,    87,
-       0,    88,    89,    90,    78,     0,    87,     0,    73,     2,
-      98,   104,   111,     0,     1,   198,     0,     0,   139,     0,
-     202,    79,    84,    86,    91,     0,    93,    80,     0,     0,
-       4,     7,     6,     8,     0,     0,     0,    35,    34,    33,
-       5,    10,    29,    12,    17,    18,     0,     0,    23,     0,
-      36,     0,    39,    42,    43,    48,    51,    52,    53,    54,
-      56,    58,    60,    71,     0,    27,    74,     0,     0,   143,
-       0,     0,     0,   182,     0,     0,     0,     0,     0,   160,
-     169,   173,    36,    62,    69,     0,   151,     0,   115,   154,
-     171,   153,   152,     0,   155,   156,   157,   158,    81,    83,
-      85,     0,     0,    99,     0,   150,   101,    30,    31,     0,
-      14,    15,     0,     0,    21,    20,     0,    22,    24,    26,
-      32,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   116,   148,     0,   146,   142,
-     144,     0,   193,   192,   167,   184,     0,   196,   194,     0,
-     180,   159,     0,    65,    66,    67,    68,    64,     0,     0,
-     174,   170,   172,     0,    94,     0,    96,   100,     9,     0,
-      16,     2,     3,    13,    19,    25,    37,    38,    41,    40,
-      46,    47,    44,    45,    49,    50,    55,    57,    59,     0,
-       0,     0,   145,   140,     0,     0,     0,     0,     0,   195,
-       0,   161,    63,    70,     0,    95,    11,     0,     0,   147,
-       0,   166,   168,   187,   186,   189,   167,   178,     0,     0,
-       0,    82,    61,   149,     0,   188,     0,     0,   177,   175,
-       0,     0,   162,     0,   190,     0,   167,     0,   164,   181,
-     163,     0,   191,   185,   176,   179,   183
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
-{
-      -1,   196,   100,   101,   102,   229,   103,   104,   105,   106,
-     107,   108,   109,   142,   111,   112,   113,   114,   115,   116,
-     117,   118,   119,   120,   121,   122,   143,   144,   218,   145,
-     124,   146,   147,    34,    35,    36,    82,    64,    65,    83,
-      37,    38,    39,    40,    41,    42,    43,   125,    45,   130,
-      77,   128,   129,   197,   198,   166,   149,   150,   151,   152,
-     212,   280,   299,   254,   255,   256,   300,   153,   154,   155,
-     289,   279,   156,   260,   204,   257,   275,   286,   287,   157,
-      46,    47,    48,    57
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -261
-static const yytype_int16 yypact[] =
-{
-    1327,   -20,  -261,  -261,  -261,   113,  -261,  -261,  -261,  -261,
-    -261,  -261,  -261,  -261,  -261,  -261,  -261,  -261,  -261,  -261,
-    -261,  -261,  -261,  -261,  -261,   -19,  -261,  -261,  -261,  -261,
-    -261,  -261,  -261,   -61,   -40,   -28,    75,    -7,  -261,    24,
-    1370,  -261,  1444,  -261,   -11,  -261,  1283,  -261,  -261,  -261,
-    -261,  1444,  -261,  -261,  -261,     6,  -261,    54,  -261,    88,
-      62,  -261,  -261,  -261,  -261,  1370,    59,    91,  -261,    36,
-     -50,  -261,  -261,  1051,  -261,  -261,    63,  1370,  -261,   293,
-    -261,  -261,  -261,  -261,    91,  1370,   -12,  -261,   856,  1051,
-      77,  -261,  -261,  -261,  1051,  1051,  1051,  -261,  -261,  -261,
-    -261,  -261,   -14,  -261,  -261,  -261,    84,   -44,  1116,    95,
-    -261,  1051,    53,     3,  -261,   -36,    89,  -261,  -261,  -261,
-     104,   107,   -45,  -261,    96,  -261,  -261,    91,  1184,  -261,
-    1370,    92,    93,  -261,    98,   101,    94,   921,   105,   102,
-    -261,  -261,    72,  -261,  -261,     9,  -261,   -61,    42,  -261,
-    -261,  -261,  -261,   376,  -261,  -261,  -261,  -261,   106,  -261,
-    -261,   986,  1051,  -261,   103,  -261,  -261,  -261,  -261,   -41,
-    -261,  -261,  1051,  1407,  -261,  -261,  1051,   110,  -261,  -261,
-    -261,  1051,  1051,  1051,  1051,  1051,  1051,  1051,  1051,  1051,
-    1051,  1051,  1051,  1051,  1051,  -261,   109,    23,  -261,  -261,
-    -261,  1227,  -261,  -261,   111,  -261,  1051,  -261,  -261,    25,
-    -261,  -261,   459,  -261,  -261,  -261,  -261,  -261,  1051,  1051,
-    -261,  -261,  -261,  1051,  -261,   114,  -261,  -261,  -261,   115,
-     112,    77,   116,  -261,  -261,  -261,  -261,  -261,    53,    53,
-    -261,  -261,  -261,  -261,   -36,   -36,  -261,   104,   107,    76,
-    1051,    91,  -261,  -261,   145,    54,   625,   708,    -6,  -261,
-     791,   459,  -261,  -261,   117,  -261,  -261,  1051,   120,  -261,
-     124,  -261,  -261,  -261,  -261,   791,   111,   112,    91,   125,
-     122,  -261,  -261,  -261,  1051,  -261,   118,   128,   180,  -261,
-     126,   542,  -261,    -5,  1051,   542,   111,  1051,  -261,  -261,
-    -261,   123,   112,  -261,  -261,  -261,  -261
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
-{
-    -261,   -24,  -261,  -261,  -261,  -261,  -261,  -261,    34,  -261,
-    -261,  -261,  -261,    32,  -261,   -33,  -261,   -27,   -26,  -261,
-    -261,  -261,    14,    16,    18,  -261,   -66,   -87,  -261,   -92,
-     -85,    11,    12,  -261,  -261,  -261,   141,   150,   161,   143,
-    -261,  -261,  -231,     5,   -30,   224,   -18,     0,  -261,  -261,
-    -261,   100,  -119,  -261,   -17,  -156,   -25,  -145,  -243,  -261,
-    -261,  -261,   -64,  -260,  -261,  -261,   -52,    21,   -22,  -261,
-    -261,   -39,  -261,  -261,  -261,  -261,  -261,  -261,  -261,  -261,
-    -261,   191,  -261,  -261
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -166
-static const yytype_int16 yytable[] =
-{
-      44,    55,   165,   164,   169,    80,   226,   123,   222,   200,
-      71,    32,    33,   272,   193,    70,   288,    49,   185,   186,
-      56,   178,   123,    88,    72,    50,    52,    53,   175,   278,
-      89,   228,    58,    76,   176,    84,   304,   219,   170,   171,
-      44,    66,    44,    86,   278,   209,    44,   127,   298,   194,
-      59,    44,   298,   187,   188,    84,    54,    32,    33,   172,
-     158,   161,    73,   173,    66,    44,   276,   301,   162,    69,
-      53,    67,   219,   219,    68,   165,   225,    44,    60,   148,
-     230,    78,   200,     6,     7,    44,   183,   219,   184,   235,
-     220,    60,    61,    62,    63,   123,     6,     7,   127,    49,
-     127,   251,   249,   219,   252,   110,   259,    87,    61,    62,
-      63,    23,    24,   -27,   258,    73,   222,     2,     3,     4,
-     110,    61,    62,    63,    23,    24,   167,   168,    44,    79,
-      44,   262,   263,   213,   214,   215,    52,    53,   264,   181,
-     182,   305,   216,   180,   126,   189,   190,   -76,   -28,   233,
-     238,   239,   217,   148,   219,   267,   174,   123,   240,   241,
-     242,   243,   191,   244,   245,   268,   179,   192,   277,   205,
-     195,   127,   206,   202,   203,   207,   210,   227,   211,   223,
-     282,  -117,   250,   277,   123,   270,  -165,  -138,   265,   266,
-     219,   281,   293,   110,   283,   284,   296,   291,   292,   294,
-     295,    44,   302,   271,   306,   246,   297,   234,   247,    81,
-     165,   248,   148,   236,   237,   110,   110,   110,   110,   110,
-     110,   110,   110,   110,   110,   110,   159,    85,   160,    51,
-     201,   303,   273,   261,   269,   274,   285,    75,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   290,   110,   148,   148,     0,     0,
-     148,   148,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   148,     0,     0,     0,     0,
-       0,     0,   110,     0,     0,     0,     0,     0,     0,     0,
-       0,   148,     0,     0,     0,   148,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,   131,   132,   133,     0,
-     134,   135,   136,   137,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,     0,     0,     0,    23,
-      24,    25,    26,   138,    27,    28,    29,    30,    90,    31,
-      91,    92,    93,     0,     0,    94,    95,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    96,     0,     0,     0,   139,   140,
-       0,     0,     0,     0,   141,    97,    98,     0,    99,     1,
-       2,     3,     4,     5,     6,     7,     8,     9,    10,   131,
-     132,   133,     0,   134,   135,   136,   137,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,     0,
-       0,     0,    23,    24,    25,    26,   138,    27,    28,    29,
-      30,    90,    31,    91,    92,    93,     0,     0,    94,    95,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    96,     0,     0,
-       0,   139,   221,     0,     0,     0,     0,   141,    97,    98,
-       0,    99,     1,     2,     3,     4,     5,     6,     7,     8,
-       9,    10,   131,   132,   133,     0,   134,   135,   136,   137,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,     0,     0,     0,    23,    24,    25,    26,   138,
-      27,    28,    29,    30,    90,    31,    91,    92,    93,     0,
-       0,    94,    95,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      96,     0,     0,     0,   139,     0,     0,     0,     0,     0,
-     141,    97,    98,     0,    99,     1,     2,     3,     4,     5,
-       6,     7,     8,     9,    10,   131,   132,   133,     0,   134,
-     135,   136,   137,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,     0,     0,     0,    23,    24,
-      25,    26,   138,    27,    28,    29,    30,    90,    31,    91,
-      92,    93,     0,     0,    94,    95,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    96,     0,     0,     0,    79,     0,     0,
-       0,     0,     0,   141,    97,    98,     0,    99,     1,     2,
-       3,     4,     5,     6,     7,     8,     9,    10,   131,   132,
-     133,     0,   134,   135,   136,   137,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,     0,     0,
-       0,    23,    24,    25,    26,   138,    27,    28,    29,    30,
-      90,    31,    91,    92,    93,     0,     0,    94,    95,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    96,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   141,    97,    98,     0,
-      99,     1,     2,     3,     4,     5,     6,     7,     8,     9,
-      10,     0,     0,     0,     0,     0,     0,     0,     0,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,     0,     0,     0,    23,    24,    25,    26,     0,    27,
-      28,    29,    30,    90,    31,    91,    92,    93,     0,     0,
-      94,    95,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    96,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   141,
-      97,    98,     0,    99,    60,     2,     3,     4,     0,     6,
-       7,     8,     9,    10,     0,     0,     0,     0,     0,     0,
-       0,     0,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,     0,     0,     0,    23,    24,    25,
-      26,     0,    27,    28,    29,    30,    90,    31,    91,    92,
-      93,     0,     0,    94,    95,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    96,     0,     0,     0,     8,     9,    10,     0,
-       0,     0,     0,    97,    98,     0,    99,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,     0,
-       0,     0,     0,     0,    25,    26,     0,    27,    28,    29,
-      30,    90,    31,    91,    92,    93,     0,     0,    94,    95,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    96,     0,     0,
-     163,     8,     9,    10,     0,     0,     0,     0,    97,    98,
-       0,    99,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,     0,     0,     0,     0,     0,    25,
-      26,     0,    27,    28,    29,    30,    90,    31,    91,    92,
-      93,     0,     0,    94,    95,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    96,     0,     0,     0,     8,     9,    10,     0,
-       0,     0,   208,    97,    98,     0,    99,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,     0,
-       0,     0,     0,     0,    25,    26,     0,    27,    28,    29,
-      30,    90,    31,    91,    92,    93,     0,     0,    94,    95,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    96,     0,     0,
-     224,     8,     9,    10,     0,     0,     0,     0,    97,    98,
-       0,    99,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,     0,     0,     0,     0,     0,    25,
-      26,     0,    27,    28,    29,    30,    90,    31,    91,    92,
-      93,     0,     0,    94,    95,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    96,     0,     0,     0,     8,     9,    10,     0,
-       0,     0,     0,    97,    98,     0,    99,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,     0,
-       0,     0,     0,     0,    25,   177,     0,    27,    28,    29,
-      30,    90,    31,    91,    92,    93,     0,     0,    94,    95,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    96,     2,     3,
-       4,     0,     0,     0,     8,     9,    10,     0,    97,    98,
-       0,    99,     0,     0,     0,    11,    12,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,     0,     0,     0,
-       0,     0,    25,    26,     0,    27,    28,    29,    30,     0,
-      31,     2,     3,     4,     0,     0,     0,     8,     9,    10,
-       0,     0,     0,     0,     0,     0,     0,     0,    11,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-     199,     0,     0,     0,     0,    25,    26,     0,    27,    28,
-      29,    30,     0,    31,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    74,     0,     0,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,     0,     0,     0,     0,
-       0,     0,     0,   253,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,     0,     0,     0,    23,
-      24,    25,    26,     0,    27,    28,    29,    30,     0,    31,
-       1,     2,     3,     4,     5,     6,     7,     8,     9,    10,
-       0,     0,     0,     0,     0,     0,     0,     0,    11,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-       0,     0,     0,    23,    24,    25,    26,     0,    27,    28,
-      29,    30,     0,    31,     2,     3,     4,     0,     0,     0,
-       8,     9,    10,     0,     0,     0,     0,     0,     0,     0,
-       0,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,     0,     0,     0,     0,     0,    25,    26,
-       0,    27,    28,    29,    30,     0,    31,     8,     9,    10,
-       0,     0,     0,     0,     0,     0,     0,     0,    11,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-       0,     0,     0,     0,     0,    25,    26,     0,    27,    28,
-      29,    30,   231,   232,     8,     9,    10,     0,     0,     0,
-       0,     0,     0,     0,     0,    11,    12,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,     0,     0,     0,
-       0,     0,    25,    26,     0,    27,    28,    29,    30,     0,
-      31
-};
-
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-261)))
-
-#define yytable_value_is_error(Yytable_value) \
-  YYID (0)
-
-static const yytype_int16 yycheck[] =
-{
-       0,    25,    89,    88,    96,    57,   162,    73,   153,   128,
-      40,     0,     0,   256,    59,    39,   276,    37,    54,    55,
-      81,   108,    88,    73,    42,    45,    45,    46,    72,   260,
-      80,    72,    72,    51,    78,    65,   296,    78,    52,    53,
-      40,    36,    42,    67,   275,   137,    46,    77,   291,    94,
-      78,    51,   295,    89,    90,    85,    75,    46,    46,    73,
-      84,    73,    73,    77,    59,    65,    72,    72,    80,    45,
-      46,    78,    78,    78,    81,   162,   161,    77,     3,    79,
-     172,    75,   201,     8,     9,    85,    83,    78,    85,   176,
-      81,     3,    33,    34,    35,   161,     8,     9,   128,    37,
-     130,    78,   194,    78,    81,    73,    81,    71,    33,    34,
-      35,    36,    37,    71,   206,    73,   261,     4,     5,     6,
-      88,    33,    34,    35,    36,    37,    94,    95,   128,    75,
-     130,   218,   219,    61,    62,    63,    45,    46,   223,    86,
-      87,   297,    70,   111,    81,    56,    57,    72,    71,   173,
-     183,   184,    80,   153,    78,    79,    72,   223,   185,   186,
-     187,   188,    58,   189,   190,   250,    71,    60,   260,    71,
-      74,   201,    71,    81,    81,    81,    71,    74,    76,    73,
-     267,    71,    73,   275,   250,    40,    75,    71,    74,    74,
-      78,    74,   284,   161,    74,    71,    16,    72,    76,    81,
-      72,   201,   294,   255,    81,   191,    80,   173,   192,    59,
-     297,   193,   212,   181,   182,   183,   184,   185,   186,   187,
-     188,   189,   190,   191,   192,   193,    85,    66,    85,     5,
-     130,   295,   257,   212,   251,   257,   275,    46,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   278,   223,   256,   257,    -1,    -1,
-     260,   261,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   275,    -1,    -1,    -1,    -1,
-      -1,    -1,   250,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   291,    -1,    -1,    -1,   295,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    13,    14,    15,    -1,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,    31,    32,    -1,    -1,    -1,    36,
-      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
-      47,    48,    49,    -1,    -1,    52,    53,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    71,    -1,    -1,    -1,    75,    76,
-      -1,    -1,    -1,    -1,    81,    82,    83,    -1,    85,     3,
-       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
-      14,    15,    -1,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
-      -1,    -1,    36,    37,    38,    39,    40,    41,    42,    43,
-      44,    45,    46,    47,    48,    49,    -1,    -1,    52,    53,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    71,    -1,    -1,
-      -1,    75,    76,    -1,    -1,    -1,    -1,    81,    82,    83,
-      -1,    85,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    -1,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    -1,    -1,    -1,    36,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,    -1,
-      -1,    52,    53,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      71,    -1,    -1,    -1,    75,    -1,    -1,    -1,    -1,    -1,
-      81,    82,    83,    -1,    85,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    -1,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    -1,    -1,    -1,    36,    37,
-      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
-      48,    49,    -1,    -1,    52,    53,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    71,    -1,    -1,    -1,    75,    -1,    -1,
-      -1,    -1,    -1,    81,    82,    83,    -1,    85,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    -1,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    -1,    -1,
-      -1,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    -1,    -1,    52,    53,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    71,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    81,    82,    83,    -1,
-      85,     3,     4,     5,     6,     7,     8,     9,    10,    11,
-      12,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,    -1,    -1,    -1,    36,    37,    38,    39,    -1,    41,
-      42,    43,    44,    45,    46,    47,    48,    49,    -1,    -1,
-      52,    53,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    71,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    81,
-      82,    83,    -1,    85,     3,     4,     5,     6,    -1,     8,
-       9,    10,    11,    12,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    -1,    -1,    -1,    36,    37,    38,
-      39,    -1,    41,    42,    43,    44,    45,    46,    47,    48,
-      49,    -1,    -1,    52,    53,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    71,    -1,    -1,    -1,    10,    11,    12,    -1,
-      -1,    -1,    -1,    82,    83,    -1,    85,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
-      -1,    -1,    -1,    -1,    38,    39,    -1,    41,    42,    43,
-      44,    45,    46,    47,    48,    49,    -1,    -1,    52,    53,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    71,    -1,    -1,
-      74,    10,    11,    12,    -1,    -1,    -1,    -1,    82,    83,
-      -1,    85,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    -1,    -1,    -1,    -1,    -1,    38,
-      39,    -1,    41,    42,    43,    44,    45,    46,    47,    48,
-      49,    -1,    -1,    52,    53,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    71,    -1,    -1,    -1,    10,    11,    12,    -1,
-      -1,    -1,    81,    82,    83,    -1,    85,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
-      -1,    -1,    -1,    -1,    38,    39,    -1,    41,    42,    43,
-      44,    45,    46,    47,    48,    49,    -1,    -1,    52,    53,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    71,    -1,    -1,
-      74,    10,    11,    12,    -1,    -1,    -1,    -1,    82,    83,
-      -1,    85,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    -1,    -1,    -1,    -1,    -1,    38,
-      39,    -1,    41,    42,    43,    44,    45,    46,    47,    48,
-      49,    -1,    -1,    52,    53,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    71,    -1,    -1,    -1,    10,    11,    12,    -1,
-      -1,    -1,    -1,    82,    83,    -1,    85,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
-      -1,    -1,    -1,    -1,    38,    39,    -1,    41,    42,    43,
-      44,    45,    46,    47,    48,    49,    -1,    -1,    52,    53,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    71,     4,     5,
-       6,    -1,    -1,    -1,    10,    11,    12,    -1,    82,    83,
-      -1,    85,    -1,    -1,    -1,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    -1,    -1,    -1,
-      -1,    -1,    38,    39,    -1,    41,    42,    43,    44,    -1,
-      46,     4,     5,     6,    -1,    -1,    -1,    10,    11,    12,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    21,    22,
-      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      76,    -1,    -1,    -1,    -1,    38,    39,    -1,    41,    42,
-      43,    44,    -1,    46,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,     0,    -1,    -1,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    76,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,    31,    32,    -1,    -1,    -1,    36,
-      37,    38,    39,    -1,    41,    42,    43,    44,    -1,    46,
-       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    21,    22,
-      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      -1,    -1,    -1,    36,    37,    38,    39,    -1,    41,    42,
-      43,    44,    -1,    46,     4,     5,     6,    -1,    -1,    -1,
-      10,    11,    12,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    -1,    -1,    -1,    -1,    -1,    38,    39,
-      -1,    41,    42,    43,    44,    -1,    46,    10,    11,    12,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    21,    22,
-      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      -1,    -1,    -1,    -1,    -1,    38,    39,    -1,    41,    42,
-      43,    44,    45,    46,    10,    11,    12,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    -1,    -1,    -1,
-      -1,    -1,    38,    39,    -1,    41,    42,    43,    44,    -1,
-      46
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,     3,     4,     5,     6,     7,     8,     9,    10,    11,
-      12,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    36,    37,    38,    39,    41,    42,    43,
-      44,    46,   126,   127,   128,   129,   130,   135,   136,   137,
-     138,   139,   140,   141,   142,   143,   175,   176,   177,    37,
-      45,   140,    45,    46,    75,    96,    81,   178,    72,    78,
-       3,    33,    34,    35,   132,   133,   138,    78,    81,    45,
-      96,   139,   141,    73,     0,   176,   141,   145,    75,    75,
-     161,   132,   131,   134,   139,   133,    96,    71,    73,    80,
-      45,    47,    48,    49,    52,    53,    71,    82,    83,    85,
-      97,    98,    99,   101,   102,   103,   104,   105,   106,   107,
-     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
-     118,   119,   120,   121,   125,   142,    81,   139,   146,   147,
-     144,    13,    14,    15,    17,    18,    19,    20,    40,    75,
-      76,    81,   108,   121,   122,   124,   126,   127,   142,   151,
-     152,   153,   154,   162,   163,   164,   167,   174,    96,   131,
-     134,    73,    80,    74,   125,   122,   150,   108,   108,   124,
-      52,    53,    73,    77,    72,    72,    78,    39,   122,    71,
-     108,    86,    87,    83,    85,    54,    55,    89,    90,    56,
-      57,    58,    60,    59,    94,    74,    96,   148,   149,    76,
-     147,   146,    81,    81,   169,    71,    71,    81,    81,   124,
-      71,    76,   155,    61,    62,    63,    70,    80,   123,    78,
-      81,    76,   152,    73,    74,   125,   150,    74,    72,   100,
-     124,    45,    46,    96,   103,   122,   108,   108,   110,   110,
-     112,   112,   112,   112,   113,   113,   117,   118,   119,   124,
-      73,    78,    81,    76,   158,   159,   160,   170,   124,    81,
-     168,   162,   122,   122,   125,    74,    74,    79,   125,   149,
-      40,   161,   153,   151,   163,   171,    72,   124,   137,   166,
-     156,    74,   122,    74,    71,   166,   172,   173,   158,   165,
-      96,    72,    76,   124,    81,    72,    16,    80,   153,   157,
-     161,    72,   124,   157,   158,   150,    81
-};
-
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
-
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
-
-#define YYFAIL		goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (&yylloc, context, YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
-
-/* Error token number */
-#define YYTERROR	1
-#define YYERRCODE	256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                                \
-    do                                                                  \
-      if (YYID (N))                                                     \
-        {                                                               \
-          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-        }                                                               \
-      else                                                              \
-        {                                                               \
-          (Current).first_line   = (Current).last_line   =              \
-            YYRHSLOC (Rhs, 0).last_line;                                \
-          (Current).first_column = (Current).last_column =              \
-            YYRHSLOC (Rhs, 0).last_column;                              \
-        }                                                               \
-    while (YYID (0))
-#endif
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-
-/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */
-
-__attribute__((__unused__))
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static unsigned
-yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
-#else
-static unsigned
-yy_location_print_ (yyo, yylocp)
-    FILE *yyo;
-    YYLTYPE const * const yylocp;
-#endif
-{
-  unsigned res = 0;
-  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
-  if (0 <= yylocp->first_line)
-    {
-      res += fprintf (yyo, "%d", yylocp->first_line);
-      if (0 <= yylocp->first_column)
-        res += fprintf (yyo, ".%d", yylocp->first_column);
-    }
-  if (0 <= yylocp->last_line)
-    {
-      if (yylocp->first_line < yylocp->last_line)
-        {
-          res += fprintf (yyo, "-%d", yylocp->last_line);
-          if (0 <= end_col)
-            res += fprintf (yyo, ".%d", end_col);
-        }
-      else if (0 <= end_col && yylocp->first_column < end_col)
-        res += fprintf (yyo, "-%d", end_col);
-    }
-  return res;
- }
-
-#  define YY_LOCATION_PRINT(File, Loc)          \
-  yy_location_print_ (File, &(Loc))
-
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval, &yylloc)
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value, Location, context); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, TParseContext* context)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, context)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    YYLTYPE const * const yylocationp;
-    TParseContext* context;
-#endif
-{
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
-  if (!yyvaluep)
-    return;
-  YYUSE (yylocationp);
-  YYUSE (context);
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-        break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, TParseContext* context)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, context)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    YYLTYPE const * const yylocationp;
-    TParseContext* context;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  YY_LOCATION_PRINT (yyoutput, *yylocationp);
-  YYFPRINTF (yyoutput, ": ");
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, context);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; yybottom <= yytop; yybottom++)
-    {
-      int yybot = *yybottom;
-      YYFPRINTF (stderr, " %d", yybot);
-    }
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, TParseContext* context)
-#else
-static void
-yy_reduce_print (yyvsp, yylsp, yyrule, context)
-    YYSTYPE *yyvsp;
-    YYLTYPE *yylsp;
-    int yyrule;
-    TParseContext* context;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-	     yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-		       &(yyvsp[(yyi + 1) - (yynrhs)])
-		       , &(yylsp[(yyi + 1) - (yynrhs)])		       , context);
-      YYFPRINTF (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, yylsp, Rule, context); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-	switch (*++yyp)
-	  {
-	  case '\'':
-	  case ',':
-	    goto do_not_strip_quotes;
-
-	  case '\\':
-	    if (*++yyp != '\\')
-	      goto do_not_strip_quotes;
-	    /* Fall through.  */
-	  default:
-	    if (yyres)
-	      yyres[yyn] = *yyp;
-	    yyn++;
-	    break;
-
-	  case '"':
-	    if (yyres)
-	      yyres[yyn] = '\0';
-	    return yyn;
-	  }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN for the state stack whose top is
-   YYSSP.
-
-   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
-   not large enough to hold the message.  In that case, also set
-   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
-{
-  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = YY_NULL;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
-  int yycount = 0;
-
-  /* There are many possibilities here to consider:
-     - Assume YYFAIL is not used.  It's too flawed to consider.  See
-       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
-       for details.  YYERROR is fine as it does not invoke this
-       function.
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[*yyssp];
-      yyarg[yycount++] = yytname[yytoken];
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for
-             this state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
-
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytname[yyx];
-                {
-                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                    return 2;
-                  yysize = yysize1;
-                }
-              }
-        }
-    }
-
-  switch (yycount)
-    {
-# define YYCASE_(N, S)                      \
-      case N:                               \
-        yyformat = S;                       \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
-    }
-
-  {
-    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-      return 2;
-    yysize = yysize1;
-  }
-
-  if (*yymsg_alloc < yysize)
-    {
-      *yymsg_alloc = 2 * yysize;
-      if (! (yysize <= *yymsg_alloc
-             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
-        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
-      return 1;
-    }
-
-  /* Avoid sprintf, as that infringes on the user's name space.
-     Don't have undefined behavior even if the translation
-     produced a string with the wrong number of "%s"s.  */
-  {
-    char *yyp = *yymsg;
-    int yyi = 0;
-    while ((*yyp = *yyformat) != '\0')
-      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyformat += 2;
-        }
-      else
-        {
-          yyp++;
-          yyformat++;
-        }
-  }
-  return 0;
-}
-#endif /* YYERROR_VERBOSE */
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, TParseContext* context)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, yylocationp, context)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-    YYLTYPE *yylocationp;
-    TParseContext* context;
-#endif
-{
-  YYUSE (yyvaluep);
-  YYUSE (yylocationp);
-  YYUSE (context);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-        break;
-    }
-}
-
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (TParseContext* context)
-#else
-int
-yyparse (context)
-    TParseContext* context;
-#endif
-#endif
-{
-/* The lookahead symbol.  */
-int yychar;
-
-
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
-/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
-    _Pragma ("GCC diagnostic push") \
-    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
-    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
-    _Pragma ("GCC diagnostic pop")
-#else
-/* Default value used for initialization, for pacifying older GCCs
-   or non-GCC compilers.  */
-static YYSTYPE yyval_default;
-# define YY_INITIAL_VALUE(Value) = Value
-#endif
-static YYLTYPE yyloc_default
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-  = { 1, 1, 1, 1 }
-# endif
-;
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
-
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
-
-/* Location data for the lookahead symbol.  */
-YYLTYPE yylloc = yyloc_default;
-
-
-    /* Number of syntax errors so far.  */
-    int yynerrs;
-
-    int yystate;
-    /* Number of tokens to shift before error messages enabled.  */
-    int yyerrstatus;
-
-    /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
-       `yyls': related to locations.
-
-       Refer to the stacks through separate pointers, to allow yyoverflow
-       to reallocate them elsewhere.  */
-
-    /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
-
-    /* The semantic value stack.  */
-    YYSTYPE yyvsa[YYINITDEPTH];
-    YYSTYPE *yyvs;
-    YYSTYPE *yyvsp;
-
-    /* The location stack.  */
-    YYLTYPE yylsa[YYINITDEPTH];
-    YYLTYPE *yyls;
-    YYLTYPE *yylsp;
-
-    /* The locations where the error started and ended.  */
-    YYLTYPE yyerror_range[3];
-
-    YYSIZE_T yystacksize;
-
-  int yyn;
-  int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-  YYLTYPE yyloc;
-
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  yyssp = yyss = yyssa;
-  yyvsp = yyvs = yyvsa;
-  yylsp = yyls = yylsa;
-  yystacksize = YYINITDEPTH;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY; /* Cause a token to be read.  */
-  yylsp[0] = yylloc;
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-	/* Give user a chance to reallocate the stack.  Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	yytype_int16 *yyss1 = yyss;
-	YYLTYPE *yyls1 = yyls;
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow (YY_("memory exhausted"),
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-		    &yyls1, yysize * sizeof (*yylsp),
-		    &yystacksize);
-
-	yyls = yyls1;
-	yyss = yyss1;
-	yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-	goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
-
-      {
-	yytype_int16 *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss_alloc, yyss);
-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-	YYSTACK_RELOCATE (yyls_alloc, yyls);
-#  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-      yylsp = yyls + yysize - 1;
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  if (yystate == YYFINAL)
-    YYACCEPT;
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     lookahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to lookahead token.  */
-  yyn = yypact[yystate];
-  if (yypact_value_is_default (yyn))
-    goto yydefault;
-
-  /* Not known => get a lookahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yytable_value_is_error (yyn))
-        goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the lookahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token.  */
-  yychar = YYEMPTY;
-
-  yystate = yyn;
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-  *++yylsp = yylloc;
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-  /* Default location.  */
-  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 4:
-
-    {
-        // The symbol table search was done in the lexical phase
-        const TSymbol* symbol = (yyvsp[(1) - (1)].lex).symbol;
-        const TVariable* variable;
-        if (symbol == 0) {
-            context->error((yylsp[(1) - (1)]), "undeclared identifier", (yyvsp[(1) - (1)].lex).string->c_str());
-            context->recover();
-            TType type(EbtFloat, EbpUndefined);
-            TVariable* fakeVariable = new TVariable((yyvsp[(1) - (1)].lex).string, type);
-            context->symbolTable.insert(*fakeVariable);
-            variable = fakeVariable;
-        } else {
-            // This identifier can only be a variable type symbol
-            if (! symbol->isVariable()) {
-                context->error((yylsp[(1) - (1)]), "variable expected", (yyvsp[(1) - (1)].lex).string->c_str());
-                context->recover();
-            }
-            
-            variable = static_cast<const TVariable*>(symbol);
-
-            if (context->symbolTable.findBuiltIn(variable->getName()) &&
-                !variable->getExtension().empty() &&
-                context->extensionErrorCheck((yylsp[(1) - (1)]), variable->getExtension())) {
-                context->recover();
-            }
-        }
-
-        // don't delete $1.string, it's used by error recovery, and the pool
-        // pop will reclaim the memory
-
-        if (variable->getType().getQualifier() == EvqConst ) {
-            ConstantUnion* constArray = variable->getConstPointer();
-            TType t(variable->getType());
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(constArray, t, (yylsp[(1) - (1)]));
-        } else
-            (yyval.interm.intermTypedNode) = context->intermediate.addSymbol(variable->getUniqueId(),
-                                                 variable->getName(),
-                                                 variable->getType(),
-                                                 (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 5:
-
-    {
-        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
-    }
-    break;
-
-  case 6:
-
-    {
-        //
-        // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
-        // check for overflow for constants
-        //
-        if (abs((yyvsp[(1) - (1)].lex).i) >= (1 << 16)) {
-            context->error((yylsp[(1) - (1)]), " integer constant overflow", "");
-            context->recover();
-        }
-        ConstantUnion *unionArray = new ConstantUnion[1];
-        unionArray->setIConst((yyvsp[(1) - (1)].lex).i);
-        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 7:
-
-    {
-        ConstantUnion *unionArray = new ConstantUnion[1];
-        unionArray->setFConst((yyvsp[(1) - (1)].lex).f);
-        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 8:
-
-    {
-        ConstantUnion *unionArray = new ConstantUnion[1];
-        unionArray->setBConst((yyvsp[(1) - (1)].lex).b);
-        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 9:
-
-    {
-        (yyval.interm.intermTypedNode) = (yyvsp[(2) - (3)].interm.intermTypedNode);
-    }
-    break;
-
-  case 10:
-
-    {
-        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
-    }
-    break;
-
-  case 11:
-
-    {
-        (yyval.interm.intermTypedNode) = context->addIndexExpression((yyvsp[(1) - (4)].interm.intermTypedNode), (yylsp[(2) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode));
-    }
-    break;
-
-  case 12:
-
-    {
-        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
-    }
-    break;
-
-  case 13:
-
-    {
-        if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isArray()) {
-            context->error((yylsp[(3) - (3)]), "cannot apply dot operator to an array", ".");
-            context->recover();
-        }
-
-        if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isVector()) {
-            TVectorFields fields;
-            if (! context->parseVectorFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yylsp[(3) - (3)]))) {
-                fields.num = 1;
-                fields.offsets[0] = 0;
-                context->recover();
-            }
-
-            if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) { // constant folding for vector fields
-                (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (3)].interm.intermTypedNode), (yylsp[(3) - (3)]));
-                if ((yyval.interm.intermTypedNode) == 0) {
-                    context->recover();
-                    (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
-                }
-                else
-                    (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqConst, (int) (*(yyvsp[(3) - (3)].lex).string).size()));
-            } else {
-                TString vectorString = *(yyvsp[(3) - (3)].lex).string;
-                TIntermTyped* index = context->intermediate.addSwizzle(fields, (yylsp[(3) - (3)]));
-                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpVectorSwizzle, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)]));
-                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (int) vectorString.size()));
-            }
-        } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isMatrix()) {
-            TMatrixFields fields;
-            if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yylsp[(3) - (3)]))) {
-                fields.wholeRow = false;
-                fields.wholeCol = false;
-                fields.row = 0;
-                fields.col = 0;
-                context->recover();
-            }
-
-            if (fields.wholeRow || fields.wholeCol) {
-                context->error((yylsp[(2) - (3)]), " non-scalar fields not implemented yet", ".");
-                context->recover();
-                ConstantUnion *unionArray = new ConstantUnion[1];
-                unionArray->setIConst(0);
-                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[(3) - (3)]));
-                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)]));
-                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(),EvqTemporary, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize()));
-            } else {
-                ConstantUnion *unionArray = new ConstantUnion[1];
-                unionArray->setIConst(fields.col * (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize() + fields.row);
-                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[(3) - (3)]));
-                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)]));
-                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision()));
-            }
-        } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType() == EbtStruct) {
-            bool fieldFound = false;
-            const TFieldList& fields = (yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getStruct()->fields();
-            unsigned int i;
-            for (i = 0; i < fields.size(); ++i) {
-                if (fields[i]->name() == *(yyvsp[(3) - (3)].lex).string) {
-                    fieldFound = true;
-                    break;
-                }
-            }
-            if (fieldFound) {
-                if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) {
-                    (yyval.interm.intermTypedNode) = context->addConstStruct(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]));
-                    if ((yyval.interm.intermTypedNode) == 0) {
-                        context->recover();
-                        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
-                    }
-                    else {
-                        (yyval.interm.intermTypedNode)->setType(*fields[i]->type());
-                        // change the qualifier of the return type, not of the structure field
-                        // as the structure definition is shared between various structures.
-                        (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst);
-                    }
-                } else {
-                    ConstantUnion *unionArray = new ConstantUnion[1];
-                    unionArray->setIConst(i);
-                    TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), (yylsp[(3) - (3)]));
-                    (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirectStruct, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)]));
-                    (yyval.interm.intermTypedNode)->setType(*fields[i]->type());
-                }
-            } else {
-                context->error((yylsp[(2) - (3)]), " no such field in structure", (yyvsp[(3) - (3)].lex).string->c_str());
-                context->recover();
-                (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
-            }
-        } else {
-            context->error((yylsp[(2) - (3)]), " field selection requires structure, vector, or matrix on left hand side", (yyvsp[(3) - (3)].lex).string->c_str());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
-        }
-        // don't delete $3.string, it's from the pool
-    }
-    break;
-
-  case 14:
-
-    {
-        if (context->lValueErrorCheck((yylsp[(2) - (2)]), "++", (yyvsp[(1) - (2)].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostIncrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yylsp[(2) - (2)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->unaryOpError((yylsp[(2) - (2)]), "++", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 15:
-
-    {
-        if (context->lValueErrorCheck((yylsp[(2) - (2)]), "--", (yyvsp[(1) - (2)].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostDecrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yylsp[(2) - (2)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->unaryOpError((yylsp[(2) - (2)]), "--", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 16:
-
-    {
-        if (context->integerErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode), "[]"))
-            context->recover();
-        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
-    }
-    break;
-
-  case 17:
-
-    {
-        TFunction* fnCall = (yyvsp[(1) - (1)].interm).function;
-        TOperator op = fnCall->getBuiltInOp();
-
-        if (op != EOpNull)
-        {
-            //
-            // Then this should be a constructor.
-            // Don't go through the symbol table for constructors.
-            // Their parameters will be verified algorithmically.
-            //
-            TType type(EbtVoid, EbpUndefined);  // use this to get the type back
-            if (context->constructorErrorCheck((yylsp[(1) - (1)]), (yyvsp[(1) - (1)].interm).intermNode, *fnCall, op, &type)) {
-                (yyval.interm.intermTypedNode) = 0;
-            } else {
-                //
-                // It's a constructor, of type 'type'.
-                //
-                (yyval.interm.intermTypedNode) = context->addConstructor((yyvsp[(1) - (1)].interm).intermNode, &type, op, fnCall, (yylsp[(1) - (1)]));
-            }
-
-            if ((yyval.interm.intermTypedNode) == 0) {
-                context->recover();
-                (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator(0, op, (yylsp[(1) - (1)]));
-            }
-            (yyval.interm.intermTypedNode)->setType(type);
-        } else {
-            //
-            // Not a constructor.  Find it in the symbol table.
-            //
-            const TFunction* fnCandidate;
-            bool builtIn;
-            fnCandidate = context->findFunction((yylsp[(1) - (1)]), fnCall, &builtIn);
-            if (fnCandidate) {
-                //
-                // A declared function.
-                //
-                if (builtIn && !fnCandidate->getExtension().empty() &&
-                    context->extensionErrorCheck((yylsp[(1) - (1)]), fnCandidate->getExtension())) {
-                    context->recover();
-                }
-                op = fnCandidate->getBuiltInOp();
-                if (builtIn && op != EOpNull) {
-                    //
-                    // A function call mapped to a built-in operation.
-                    //
-                    if (fnCandidate->getParamCount() == 1) {
-                        //
-                        // Treat it like a built-in unary operator.
-                        //
-                        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(op, (yyvsp[(1) - (1)].interm).intermNode, (yylsp[(1) - (1)]), context->symbolTable);
-                        if ((yyval.interm.intermTypedNode) == 0)  {
-                            std::stringstream extraInfoStream;
-                            extraInfoStream << "built in unary operator function.  Type: " << static_cast<TIntermTyped*>((yyvsp[(1) - (1)].interm).intermNode)->getCompleteString();
-                            std::string extraInfo = extraInfoStream.str();
-                            context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
-                            YYERROR;
-                        }
-                    } else {
-                        (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, op, (yylsp[(1) - (1)]));
-                    }
-                } else {
-                    // This is a real function call
-
-                    (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, EOpFunctionCall, (yylsp[(1) - (1)]));
-                    (yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType());
-
-                    // this is how we know whether the given function is a builtIn function or a user defined function
-                    // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
-                    // if builtIn == true, it's definitely a builtIn function with EOpNull
-                    if (!builtIn)
-                        (yyval.interm.intermTypedNode)->getAsAggregate()->setUserDefined();
-                    (yyval.interm.intermTypedNode)->getAsAggregate()->setName(fnCandidate->getMangledName());
-
-                    TQualifier qual;
-                    for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
-                        qual = fnCandidate->getParam(i).type->getQualifier();
-                        if (qual == EvqOut || qual == EvqInOut) {
-                            if (context->lValueErrorCheck((yyval.interm.intermTypedNode)->getLine(), "assign", (yyval.interm.intermTypedNode)->getAsAggregate()->getSequence()[i]->getAsTyped())) {
-                                context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
-                                context->recover();
-                            }
-                        }
-                    }
-                }
-                (yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType());
-            } else {
-                // error message was put out by PaFindFunction()
-                // Put on a dummy node for error recovery
-                ConstantUnion *unionArray = new ConstantUnion[1];
-                unionArray->setFConst(0.0f);
-                (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yylsp[(1) - (1)]));
-                context->recover();
-            }
-        }
-        delete fnCall;
-    }
-    break;
-
-  case 18:
-
-    {
-        (yyval.interm) = (yyvsp[(1) - (1)].interm);
-    }
-    break;
-
-  case 19:
-
-    {
-        context->error((yylsp[(3) - (3)]), "methods are not supported", "");
-        context->recover();
-        (yyval.interm) = (yyvsp[(3) - (3)].interm);
-    }
-    break;
-
-  case 20:
-
-    {
-        (yyval.interm) = (yyvsp[(1) - (2)].interm);
-    }
-    break;
-
-  case 21:
-
-    {
-        (yyval.interm) = (yyvsp[(1) - (2)].interm);
-    }
-    break;
-
-  case 22:
-
-    {
-        (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
-        (yyval.interm).intermNode = 0;
-    }
-    break;
-
-  case 23:
-
-    {
-        (yyval.interm).function = (yyvsp[(1) - (1)].interm.function);
-        (yyval.interm).intermNode = 0;
-    }
-    break;
-
-  case 24:
-
-    {
-        TParameter param = { 0, new TType((yyvsp[(2) - (2)].interm.intermTypedNode)->getType()) };
-        (yyvsp[(1) - (2)].interm.function)->addParameter(param);
-        (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
-        (yyval.interm).intermNode = (yyvsp[(2) - (2)].interm.intermTypedNode);
-    }
-    break;
-
-  case 25:
-
-    {
-        TParameter param = { 0, new TType((yyvsp[(3) - (3)].interm.intermTypedNode)->getType()) };
-        (yyvsp[(1) - (3)].interm).function->addParameter(param);
-        (yyval.interm).function = (yyvsp[(1) - (3)].interm).function;
-        (yyval.interm).intermNode = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]));
-    }
-    break;
-
-  case 26:
-
-    {
-        (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function);
-    }
-    break;
-
-  case 27:
-
-    {
-        //
-        // Constructor
-        //
-        TOperator op = EOpNull;
-        if ((yyvsp[(1) - (1)].interm.type).userDef) {
-            op = EOpConstructStruct;
-        } else {
-            switch ((yyvsp[(1) - (1)].interm.type).type) {
-            case EbtFloat:
-                if ((yyvsp[(1) - (1)].interm.type).matrix) {
-                    switch((yyvsp[(1) - (1)].interm.type).size) {
-                    case 2: op = EOpConstructMat2;  break;
-                    case 3: op = EOpConstructMat3;  break;
-                    case 4: op = EOpConstructMat4;  break;
-                    }
-                } else {
-                    switch((yyvsp[(1) - (1)].interm.type).size) {
-                    case 1: op = EOpConstructFloat; break;
-                    case 2: op = EOpConstructVec2;  break;
-                    case 3: op = EOpConstructVec3;  break;
-                    case 4: op = EOpConstructVec4;  break;
-                    }
-                }
-                break;
-            case EbtInt:
-                switch((yyvsp[(1) - (1)].interm.type).size) {
-                case 1: op = EOpConstructInt;   break;
-                case 2: op = EOpConstructIVec2; break;
-                case 3: op = EOpConstructIVec3; break;
-                case 4: op = EOpConstructIVec4; break;
-                }
-                break;
-            case EbtBool:
-                switch((yyvsp[(1) - (1)].interm.type).size) {
-                case 1: op = EOpConstructBool;  break;
-                case 2: op = EOpConstructBVec2; break;
-                case 3: op = EOpConstructBVec3; break;
-                case 4: op = EOpConstructBVec4; break;
-                }
-                break;
-            default: break;
-            }
-            if (op == EOpNull) {
-                context->error((yylsp[(1) - (1)]), "cannot construct this type", getBasicString((yyvsp[(1) - (1)].interm.type).type));
-                context->recover();
-                (yyvsp[(1) - (1)].interm.type).type = EbtFloat;
-                op = EOpConstructFloat;
-            }
-        }
-        TString tempString;
-        TType type((yyvsp[(1) - (1)].interm.type));
-        TFunction *function = new TFunction(&tempString, type, op);
-        (yyval.interm.function) = function;
-    }
-    break;
-
-  case 28:
-
-    {
-        if (context->reservedErrorCheck((yylsp[(1) - (1)]), *(yyvsp[(1) - (1)].lex).string))
-            context->recover();
-        TType type(EbtVoid, EbpUndefined);
-        TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type);
-        (yyval.interm.function) = function;
-    }
-    break;
-
-  case 29:
-
-    {
-        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
-    }
-    break;
-
-  case 30:
-
-    {
-        if (context->lValueErrorCheck((yylsp[(1) - (2)]), "++", (yyvsp[(2) - (2)].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreIncrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yylsp[(1) - (2)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->unaryOpError((yylsp[(1) - (2)]), "++", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 31:
-
-    {
-        if (context->lValueErrorCheck((yylsp[(1) - (2)]), "--", (yyvsp[(2) - (2)].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreDecrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yylsp[(1) - (2)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->unaryOpError((yylsp[(1) - (2)]), "--", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 32:
-
-    {
-        if ((yyvsp[(1) - (2)].interm).op != EOpNull) {
-            (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath((yyvsp[(1) - (2)].interm).op, (yyvsp[(2) - (2)].interm.intermTypedNode), (yylsp[(1) - (2)]), context->symbolTable);
-            if ((yyval.interm.intermTypedNode) == 0) {
-                const char* errorOp = "";
-                switch((yyvsp[(1) - (2)].interm).op) {
-                case EOpNegative:   errorOp = "-"; break;
-                case EOpLogicalNot: errorOp = "!"; break;
-                default: break;
-                }
-                context->unaryOpError((yylsp[(1) - (2)]), errorOp, (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
-                context->recover();
-                (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
-            }
-        } else
-            (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
-    }
-    break;
-
-  case 33:
-
-    { (yyval.interm).op = EOpNull; }
-    break;
-
-  case 34:
-
-    { (yyval.interm).op = EOpNegative; }
-    break;
-
-  case 35:
-
-    { (yyval.interm).op = EOpLogicalNot; }
-    break;
-
-  case 36:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 37:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMul, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "*", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 38:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpDiv, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "/", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 39:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 40:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpAdd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "+", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 41:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpSub, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "-", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 42:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 43:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 44:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "<", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
-        }
-    }
-    break;
-
-  case 45:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), ">", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
-        }
-    }
-    break;
-
-  case 46:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "<=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
-        }
-    }
-    break;
-
-  case 47:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), ">=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
-        }
-    }
-    break;
-
-  case 48:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 49:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "==", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
-        }
-    }
-    break;
-
-  case 50:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpNotEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "!=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
-        }
-    }
-    break;
-
-  case 51:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 52:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 53:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 54:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 55:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalAnd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "&&", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
-        }
-    }
-    break;
-
-  case 56:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 57:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalXor, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "^^", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
-        }
-    }
-    break;
-
-  case 58:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 59:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalOr, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), "||", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
-        }
-    }
-    break;
-
-  case 60:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 61:
-
-    {
-       if (context->boolErrorCheck((yylsp[(2) - (5)]), (yyvsp[(1) - (5)].interm.intermTypedNode)))
-            context->recover();
-
-        (yyval.interm.intermTypedNode) = context->intermediate.addSelection((yyvsp[(1) - (5)].interm.intermTypedNode), (yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.intermTypedNode), (yylsp[(2) - (5)]));
-        if ((yyvsp[(3) - (5)].interm.intermTypedNode)->getType() != (yyvsp[(5) - (5)].interm.intermTypedNode)->getType())
-            (yyval.interm.intermTypedNode) = 0;
-
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (5)]), ":", (yyvsp[(3) - (5)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(5) - (5)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(5) - (5)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 62:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 63:
-
-    {
-        if (context->lValueErrorCheck((yylsp[(2) - (3)]), "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = context->intermediate.addAssign((yyvsp[(2) - (3)].interm).op, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->assignError((yylsp[(2) - (3)]), "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 64:
-
-    { (yyval.interm).op = EOpAssign; }
-    break;
-
-  case 65:
-
-    { (yyval.interm).op = EOpMulAssign; }
-    break;
-
-  case 66:
-
-    { (yyval.interm).op = EOpDivAssign; }
-    break;
-
-  case 67:
-
-    { (yyval.interm).op = EOpAddAssign; }
-    break;
-
-  case 68:
-
-    { (yyval.interm).op = EOpSubAssign; }
-    break;
-
-  case 69:
-
-    {
-        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
-    }
-    break;
-
-  case 70:
-
-    {
-        (yyval.interm.intermTypedNode) = context->intermediate.addComma((yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[(2) - (3)]), ",", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[(3) - (3)].interm.intermTypedNode);
-        }
-    }
-    break;
-
-  case 71:
-
-    {
-        if (context->constErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
-    }
-    break;
-
-  case 72:
-
-    {
-        TFunction &function = *((yyvsp[(1) - (2)].interm).function);
-        
-        TIntermAggregate *prototype = new TIntermAggregate;
-        prototype->setType(function.getReturnType());
-        prototype->setName(function.getName());
-        
-        for (size_t i = 0; i < function.getParamCount(); i++)
-        {
-            const TParameter &param = function.getParam(i);
-            if (param.name != 0)
-            {
-                TVariable variable(param.name, *param.type);
-                
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), (yylsp[(1) - (2)])), (yylsp[(1) - (2)]));
-            }
-            else
-            {
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, (yylsp[(1) - (2)])), (yylsp[(1) - (2)]));
-            }
-        }
-        
-        prototype->setOp(EOpPrototype);
-        (yyval.interm.intermNode) = prototype;
-
-        context->symbolTable.pop();
-    }
-    break;
-
-  case 73:
-
-    {
-        if ((yyvsp[(1) - (2)].interm).intermAggregate)
-            (yyvsp[(1) - (2)].interm).intermAggregate->setOp(EOpDeclaration);
-        (yyval.interm.intermNode) = (yyvsp[(1) - (2)].interm).intermAggregate;
-    }
-    break;
-
-  case 74:
-
-    {
-        if (((yyvsp[(2) - (4)].interm.precision) == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) {
-            context->error((yylsp[(1) - (4)]), "precision is not supported in fragment shader", "highp");
-            context->recover();
-        }
-        if (!context->symbolTable.setDefaultPrecision( (yyvsp[(3) - (4)].interm.type), (yyvsp[(2) - (4)].interm.precision) )) {
-            context->error((yylsp[(1) - (4)]), "illegal type argument for default precision qualifier", getBasicString((yyvsp[(3) - (4)].interm.type).type));
-            context->recover();
-        }
-        (yyval.interm.intermNode) = 0;
-    }
-    break;
-
-  case 75:
-
-    {
-        //
-        // Multiple declarations of the same function are allowed.
-        //
-        // If this is a definition, the definition production code will check for redefinitions
-        // (we don't know at this point if it's a definition or not).
-        //
-        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
-        //
-        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getMangledName()));
-        if (prevDec) {
-            if (prevDec->getReturnType() != (yyvsp[(1) - (2)].interm.function)->getReturnType()) {
-                context->error((yylsp[(2) - (2)]), "overloaded functions must have the same return type", (yyvsp[(1) - (2)].interm.function)->getReturnType().getBasicString());
-                context->recover();
-            }
-            for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
-                if (prevDec->getParam(i).type->getQualifier() != (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifier()) {
-                    context->error((yylsp[(2) - (2)]), "overloaded functions must have the same parameter qualifiers", (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifierString());
-                    context->recover();
-                }
-            }
-        }
-
-        //
-        // Check for previously declared variables using the same name.
-        //
-        TSymbol *prevSym = context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getName());
-        if (prevSym)
-        {
-            if (!prevSym->isFunction())
-            {
-                context->error((yylsp[(2) - (2)]), "redefinition", (yyvsp[(1) - (2)].interm.function)->getName().c_str(), "function");
-                context->recover();
-            }
-        }
-        else
-        {
-            // Insert the unmangled name to detect potential future redefinition as a variable.
-            context->symbolTable.getOuterLevel()->insert((yyvsp[(1) - (2)].interm.function)->getName(), *(yyvsp[(1) - (2)].interm.function));
-        }
-
-        //
-        // If this is a redeclaration, it could also be a definition,
-        // in which case, we want to use the variable names from this one, and not the one that's
-        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
-        //
-        (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
-
-        // We're at the inner scope level of the function's arguments and body statement.
-        // Add the function prototype to the surrounding scope instead.
-        context->symbolTable.getOuterLevel()->insert(*(yyval.interm).function);
-    }
-    break;
-
-  case 76:
-
-    {
-        (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function);
-    }
-    break;
-
-  case 77:
-
-    {
-        (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function);
-    }
-    break;
-
-  case 78:
-
-    {
-        // Add the parameter
-        (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function);
-        if ((yyvsp[(2) - (2)].interm).param.type->getBasicType() != EbtVoid)
-            (yyvsp[(1) - (2)].interm.function)->addParameter((yyvsp[(2) - (2)].interm).param);
-        else
-            delete (yyvsp[(2) - (2)].interm).param.type;
-    }
-    break;
-
-  case 79:
-
-    {
-        //
-        // Only first parameter of one-parameter functions can be void
-        // The check for named parameters not being void is done in parameter_declarator
-        //
-        if ((yyvsp[(3) - (3)].interm).param.type->getBasicType() == EbtVoid) {
-            //
-            // This parameter > first is void
-            //
-            context->error((yylsp[(2) - (3)]), "cannot be an argument type except for '(void)'", "void");
-            context->recover();
-            delete (yyvsp[(3) - (3)].interm).param.type;
-        } else {
-            // Add the parameter
-            (yyval.interm.function) = (yyvsp[(1) - (3)].interm.function);
-            (yyvsp[(1) - (3)].interm.function)->addParameter((yyvsp[(3) - (3)].interm).param);
-        }
-    }
-    break;
-
-  case 80:
-
-    {
-        if ((yyvsp[(1) - (3)].interm.type).qualifier != EvqGlobal && (yyvsp[(1) - (3)].interm.type).qualifier != EvqTemporary) {
-            context->error((yylsp[(2) - (3)]), "no qualifiers allowed for function return", getQualifierString((yyvsp[(1) - (3)].interm.type).qualifier));
-            context->recover();
-        }
-        // make sure a sampler is not involved as well...
-        if (context->structQualifierErrorCheck((yylsp[(2) - (3)]), (yyvsp[(1) - (3)].interm.type)))
-            context->recover();
-
-        // Add the function as a prototype after parsing it (we do not support recursion)
-        TFunction *function;
-        TType type((yyvsp[(1) - (3)].interm.type));
-        function = new TFunction((yyvsp[(2) - (3)].lex).string, type);
-        (yyval.interm.function) = function;
-        
-        context->symbolTable.push();
-    }
-    break;
-
-  case 81:
-
-    {
-        if ((yyvsp[(1) - (2)].interm.type).type == EbtVoid) {
-            context->error((yylsp[(2) - (2)]), "illegal use of type 'void'", (yyvsp[(2) - (2)].lex).string->c_str());
-            context->recover();
-        }
-        if (context->reservedErrorCheck((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string))
-            context->recover();
-        TParameter param = {(yyvsp[(2) - (2)].lex).string, new TType((yyvsp[(1) - (2)].interm.type))};
-        (yyval.interm).param = param;
-    }
-    break;
-
-  case 82:
-
-    {
-        // Check that we can make an array out of this type
-        if (context->arrayTypeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm.type)))
-            context->recover();
-
-        if (context->reservedErrorCheck((yylsp[(2) - (5)]), *(yyvsp[(2) - (5)].lex).string))
-            context->recover();
-
-        int size;
-        if (context->arraySizeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(4) - (5)].interm.intermTypedNode), size))
-            context->recover();
-        (yyvsp[(1) - (5)].interm.type).setArray(true, size);
-
-        TType* type = new TType((yyvsp[(1) - (5)].interm.type));
-        TParameter param = { (yyvsp[(2) - (5)].lex).string, type };
-        (yyval.interm).param = param;
-    }
-    break;
-
-  case 83:
-
-    {
-        (yyval.interm) = (yyvsp[(3) - (3)].interm);
-        if (context->paramErrorCheck((yylsp[(3) - (3)]), (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type))
-            context->recover();
-    }
-    break;
-
-  case 84:
-
-    {
-        (yyval.interm) = (yyvsp[(2) - (2)].interm);
-        if (context->parameterSamplerErrorCheck((yylsp[(2) - (2)]), (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type))
-            context->recover();
-        if (context->paramErrorCheck((yylsp[(2) - (2)]), EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type))
-            context->recover();
-    }
-    break;
-
-  case 85:
-
-    {
-        (yyval.interm) = (yyvsp[(3) - (3)].interm);
-        if (context->paramErrorCheck((yylsp[(3) - (3)]), (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type))
-            context->recover();
-    }
-    break;
-
-  case 86:
-
-    {
-        (yyval.interm) = (yyvsp[(2) - (2)].interm);
-        if (context->parameterSamplerErrorCheck((yylsp[(2) - (2)]), (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type))
-            context->recover();
-        if (context->paramErrorCheck((yylsp[(2) - (2)]), EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type))
-            context->recover();
-    }
-    break;
-
-  case 87:
-
-    {
-        (yyval.interm.qualifier) = EvqIn;
-    }
-    break;
-
-  case 88:
-
-    {
-        (yyval.interm.qualifier) = EvqIn;
-    }
-    break;
-
-  case 89:
-
-    {
-        (yyval.interm.qualifier) = EvqOut;
-    }
-    break;
-
-  case 90:
-
-    {
-        (yyval.interm.qualifier) = EvqInOut;
-    }
-    break;
-
-  case 91:
-
-    {
-        TParameter param = { 0, new TType((yyvsp[(1) - (1)].interm.type)) };
-        (yyval.interm).param = param;
-    }
-    break;
-
-  case 92:
-
-    {
-        (yyval.interm) = (yyvsp[(1) - (1)].interm);
-    }
-    break;
-
-  case 93:
-
-    {
-        if ((yyvsp[(1) - (3)].interm).type.type == EbtInvariant && !(yyvsp[(3) - (3)].lex).symbol)
-        {
-            context->error((yylsp[(3) - (3)]), "undeclared identifier declared as invariant", (yyvsp[(3) - (3)].lex).string->c_str());
-            context->recover();
-        }
-
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yylsp[(3) - (3)]));
-        (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, symbol, (yylsp[(3) - (3)]));
-        
-        if (context->structQualifierErrorCheck((yylsp[(3) - (3)]), (yyval.interm).type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck((yylsp[(3) - (3)]), *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, false))
-            context->recover();
-
-        TVariable* variable = 0;
-        if (context->nonInitErrorCheck((yylsp[(3) - (3)]), *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, variable))
-            context->recover();
-        if (symbol && variable)
-            symbol->setId(variable->getUniqueId());
-    }
-    break;
-
-  case 94:
-
-    {
-        if (context->structQualifierErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm).type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck((yylsp[(3) - (5)]), *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, true))
-            context->recover();
-
-        (yyval.interm) = (yyvsp[(1) - (5)].interm);
-
-        if (context->arrayTypeErrorCheck((yylsp[(4) - (5)]), (yyvsp[(1) - (5)].interm).type) || context->arrayQualifierErrorCheck((yylsp[(4) - (5)]), (yyvsp[(1) - (5)].interm).type))
-            context->recover();
-        else {
-            (yyvsp[(1) - (5)].interm).type.setArray(true);
-            TVariable* variable;
-            if (context->arrayErrorCheck((yylsp[(4) - (5)]), *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, variable))
-                context->recover();
-        }
-    }
-    break;
-
-  case 95:
-
-    {
-        if (context->structQualifierErrorCheck((yylsp[(3) - (6)]), (yyvsp[(1) - (6)].interm).type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck((yylsp[(3) - (6)]), *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, true))
-            context->recover();
-
-        (yyval.interm) = (yyvsp[(1) - (6)].interm);
-
-        if (context->arrayTypeErrorCheck((yylsp[(4) - (6)]), (yyvsp[(1) - (6)].interm).type) || context->arrayQualifierErrorCheck((yylsp[(4) - (6)]), (yyvsp[(1) - (6)].interm).type))
-            context->recover();
-        else {
-            int size;
-            if (context->arraySizeErrorCheck((yylsp[(4) - (6)]), (yyvsp[(5) - (6)].interm.intermTypedNode), size))
-                context->recover();
-            (yyvsp[(1) - (6)].interm).type.setArray(true, size);
-            TVariable* variable = 0;
-            if (context->arrayErrorCheck((yylsp[(4) - (6)]), *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, variable))
-                context->recover();
-            TType type = TType((yyvsp[(1) - (6)].interm).type);
-            type.setArraySize(size);
-            (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (6)].interm).intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *(yyvsp[(3) - (6)].lex).string, type, (yylsp[(3) - (6)])), (yylsp[(3) - (6)]));
-        }
-    }
-    break;
-
-  case 96:
-
-    {
-        if (context->structQualifierErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm).type))
-            context->recover();
-
-        (yyval.interm) = (yyvsp[(1) - (5)].interm);
-
-        TIntermNode* intermNode;
-        if (!context->executeInitializer((yylsp[(3) - (5)]), *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, (yyvsp[(5) - (5)].interm.intermTypedNode), intermNode)) {
-            //
-            // build the intermediate representation
-            //
-            if (intermNode)
-        (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (5)].interm).intermNode, intermNode, (yylsp[(4) - (5)]));
-            else
-                (yyval.interm).intermAggregate = (yyvsp[(1) - (5)].interm).intermAggregate;
-        } else {
-            context->recover();
-            (yyval.interm).intermAggregate = 0;
-        }
-    }
-    break;
-
-  case 97:
-
-    {
-        (yyval.interm).type = (yyvsp[(1) - (1)].interm.type);
-        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType((yyvsp[(1) - (1)].interm.type)), (yylsp[(1) - (1)])), (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 98:
-
-    {
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yylsp[(2) - (2)]));
-        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (2)]));
-        
-        if (context->structQualifierErrorCheck((yylsp[(2) - (2)]), (yyval.interm).type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, false))
-            context->recover();
-            
-            (yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
-
-        TVariable* variable = 0;
-        if (context->nonInitErrorCheck((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable))
-            context->recover();
-        if (variable && symbol)
-            symbol->setId(variable->getUniqueId());
-    }
-    break;
-
-  case 99:
-
-    {
-        context->error((yylsp[(2) - (4)]), "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str());
-        context->recover();
-
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yylsp[(2) - (4)]));
-        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (4)]));
-        (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
-    }
-    break;
-
-  case 100:
-
-    {
-        TType type = TType((yyvsp[(1) - (5)].interm.type));
-        int size;
-        if (context->arraySizeErrorCheck((yylsp[(2) - (5)]), (yyvsp[(4) - (5)].interm.intermTypedNode), size))
-            context->recover();
-        type.setArraySize(size);
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yylsp[(2) - (5)]));
-        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (5)]));
-        
-        if (context->structQualifierErrorCheck((yylsp[(2) - (5)]), (yyvsp[(1) - (5)].interm.type)))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck((yylsp[(2) - (5)]), *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), true))
-            context->recover();
-
-        (yyval.interm).type = (yyvsp[(1) - (5)].interm.type);
-
-        if (context->arrayTypeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm.type)) || context->arrayQualifierErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm.type)))
-            context->recover();
-        else {
-            int size;
-            if (context->arraySizeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(4) - (5)].interm.intermTypedNode), size))
-                context->recover();
-
-            (yyvsp[(1) - (5)].interm.type).setArray(true, size);
-            TVariable* variable = 0;
-            if (context->arrayErrorCheck((yylsp[(3) - (5)]), *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable))
-                context->recover();
-            if (variable && symbol)
-                symbol->setId(variable->getUniqueId());
-        }
-    }
-    break;
-
-  case 101:
-
-    {
-        if (context->structQualifierErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type)))
-            context->recover();
-
-        (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
-
-        TIntermNode* intermNode;
-        if (!context->executeInitializer((yylsp[(2) - (4)]), *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) {
-        //
-        // Build intermediate representation
-        //
-            if(intermNode)
-                (yyval.interm).intermAggregate = context->intermediate.makeAggregate(intermNode, (yylsp[(3) - (4)]));
-            else
-                (yyval.interm).intermAggregate = 0;
-        } else {
-            context->recover();
-            (yyval.interm).intermAggregate = 0;
-        }
-    }
-    break;
-
-  case 102:
-
-    {
-        VERTEX_ONLY("invariant declaration", (yylsp[(1) - (2)]));
-        if (context->globalErrorCheck((yylsp[(1) - (2)]), context->symbolTable.atGlobalLevel(), "invariant varying"))
-            context->recover();
-        (yyval.interm).type.setBasic(EbtInvariant, EvqInvariantVaryingOut, (yylsp[(2) - (2)]));
-        if (!(yyvsp[(2) - (2)].lex).symbol)
-        {
-            context->error((yylsp[(2) - (2)]), "undeclared identifier declared as invariant", (yyvsp[(2) - (2)].lex).string->c_str());
-            context->recover();
-            
-            (yyval.interm).intermAggregate = 0;
-        }
-        else
-        {
-            TIntermSymbol *symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyval.interm).type), (yylsp[(2) - (2)]));
-            (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (2)]));
-        }
-    }
-    break;
-
-  case 103:
-
-    {
-        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
-
-        if ((yyvsp[(1) - (1)].interm.type).array) {
-            context->error((yylsp[(1) - (1)]), "not supported", "first-class array");
-            context->recover();
-            (yyvsp[(1) - (1)].interm.type).setArray(false);
-        }
-    }
-    break;
-
-  case 104:
-
-    {
-        if ((yyvsp[(2) - (2)].interm.type).array) {
-            context->error((yylsp[(2) - (2)]), "not supported", "first-class array");
-            context->recover();
-            (yyvsp[(2) - (2)].interm.type).setArray(false);
-        }
-
-        if ((yyvsp[(1) - (2)].interm.type).qualifier == EvqAttribute &&
-            ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
-            context->error((yylsp[(2) - (2)]), "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier));
-            context->recover();
-        }
-        if (((yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingIn || (yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingOut) &&
-            ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
-            context->error((yylsp[(2) - (2)]), "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier));
-            context->recover();
-        }
-        (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type);
-        (yyval.interm.type).qualifier = (yyvsp[(1) - (2)].interm.type).qualifier;
-    }
-    break;
-
-  case 105:
-
-    {
-        (yyval.interm.type).setBasic(EbtVoid, EvqConst, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 106:
-
-    {
-        VERTEX_ONLY("attribute", (yylsp[(1) - (1)]));
-        if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "attribute"))
-            context->recover();
-        (yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 107:
-
-    {
-        if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "varying"))
-            context->recover();
-        if (context->shaderType == SH_VERTEX_SHADER)
-            (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[(1) - (1)]));
-        else
-            (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 108:
-
-    {
-        if (context->globalErrorCheck((yylsp[(1) - (2)]), context->symbolTable.atGlobalLevel(), "invariant varying"))
-            context->recover();
-        if (context->shaderType == SH_VERTEX_SHADER)
-            (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingOut, (yylsp[(1) - (2)]));
-        else
-            (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingIn, (yylsp[(1) - (2)]));
-    }
-    break;
-
-  case 109:
-
-    {
-        if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "uniform"))
-            context->recover();
-        (yyval.interm.type).setBasic(EbtVoid, EvqUniform, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 110:
-
-    {
-        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
-
-        if ((yyval.interm.type).precision == EbpUndefined) {
-            (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[(1) - (1)].interm.type).type);
-            if (context->precisionErrorCheck((yylsp[(1) - (1)]), (yyval.interm.type).precision, (yyvsp[(1) - (1)].interm.type).type)) {
-                context->recover();
-            }
-        }
-    }
-    break;
-
-  case 111:
-
-    {
-        (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type);
-        (yyval.interm.type).precision = (yyvsp[(1) - (2)].interm.precision);
-    }
-    break;
-
-  case 112:
-
-    {
-        (yyval.interm.precision) = EbpHigh;
-    }
-    break;
-
-  case 113:
-
-    {
-        (yyval.interm.precision) = EbpMedium;
-    }
-    break;
-
-  case 114:
-
-    {
-        (yyval.interm.precision) = EbpLow;
-    }
-    break;
-
-  case 115:
-
-    {
-        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
-    }
-    break;
-
-  case 116:
-
-    {
-        (yyval.interm.type) = (yyvsp[(1) - (4)].interm.type);
-
-        if (context->arrayTypeErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type)))
-            context->recover();
-        else {
-            int size;
-            if (context->arraySizeErrorCheck((yylsp[(2) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode), size))
-                context->recover();
-            (yyval.interm.type).setArray(true, size);
-        }
-    }
-    break;
-
-  case 117:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtVoid, qual, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 118:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 119:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 120:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 121:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(2);
-    }
-    break;
-
-  case 122:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(3);
-    }
-    break;
-
-  case 123:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(4);
-    }
-    break;
-
-  case 124:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(2);
-    }
-    break;
-
-  case 125:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(3);
-    }
-    break;
-
-  case 126:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(4);
-    }
-    break;
-
-  case 127:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(2);
-    }
-    break;
-
-  case 128:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(3);
-    }
-    break;
-
-  case 129:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(4);
-    }
-    break;
-
-  case 130:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(2, true);
-    }
-    break;
-
-  case 131:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(3, true);
-    }
-    break;
-
-  case 132:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).setAggregate(4, true);
-    }
-    break;
-
-  case 133:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSampler2D, qual, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 134:
-
-    {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSamplerCube, qual, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 135:
-
-    {
-        if (!context->supportsExtension("GL_OES_EGL_image_external")) {
-            context->error((yylsp[(1) - (1)]), "unsupported type", "samplerExternalOES");
-            context->recover();
-        }
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSamplerExternalOES, qual, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 136:
-
-    {
-        if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
-            context->error((yylsp[(1) - (1)]), "unsupported type", "sampler2DRect");
-            context->recover();
-        }
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSampler2DRect, qual, (yylsp[(1) - (1)]));
-    }
-    break;
-
-  case 137:
-
-    {
-        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
-        (yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-    }
-    break;
-
-  case 138:
-
-    {
-        //
-        // This is for user defined type names.  The lexical phase looked up the
-        // type.
-        //
-        TType& structure = static_cast<TVariable*>((yyvsp[(1) - (1)].lex).symbol)->getType();
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtStruct, qual, (yylsp[(1) - (1)]));
-        (yyval.interm.type).userDef = &structure;
-    }
-    break;
-
-  case 139:
-
-    { if (context->enterStructDeclaration((yylsp[(2) - (3)]), *(yyvsp[(2) - (3)].lex).string)) context->recover(); }
-    break;
-
-  case 140:
-
-    {
-        if (context->reservedErrorCheck((yylsp[(2) - (6)]), *(yyvsp[(2) - (6)].lex).string))
-            context->recover();
-
-        TType* structure = new TType(new TStructure((yyvsp[(2) - (6)].lex).string, (yyvsp[(5) - (6)].interm.fieldList)));
-        TVariable* userTypeDef = new TVariable((yyvsp[(2) - (6)].lex).string, *structure, true);
-        if (! context->symbolTable.insert(*userTypeDef)) {
-            context->error((yylsp[(2) - (6)]), "redefinition", (yyvsp[(2) - (6)].lex).string->c_str(), "struct");
-            context->recover();
-        }
-        (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yylsp[(1) - (6)]));
-        (yyval.interm.type).userDef = structure;
-        context->exitStructDeclaration();
-    }
-    break;
-
-  case 141:
-
-    { if (context->enterStructDeclaration((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string)) context->recover(); }
-    break;
-
-  case 142:
-
-    {
-        TType* structure = new TType(new TStructure(NewPoolTString(""), (yyvsp[(4) - (5)].interm.fieldList)));
-        (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yylsp[(1) - (5)]));
-        (yyval.interm.type).userDef = structure;
-        context->exitStructDeclaration();
-    }
-    break;
-
-  case 143:
-
-    {
-        (yyval.interm.fieldList) = (yyvsp[(1) - (1)].interm.fieldList);
-    }
-    break;
-
-  case 144:
-
-    {
-        (yyval.interm.fieldList) = (yyvsp[(1) - (2)].interm.fieldList);
-        for (size_t i = 0; i < (yyvsp[(2) - (2)].interm.fieldList)->size(); ++i) {
-            TField* field = (*(yyvsp[(2) - (2)].interm.fieldList))[i];
-            for (size_t j = 0; j < (yyval.interm.fieldList)->size(); ++j) {
-                if ((*(yyval.interm.fieldList))[j]->name() == field->name()) {
-                    context->error((yylsp[(2) - (2)]), "duplicate field name in structure:", "struct", field->name().c_str());
-                    context->recover();
-                }
-            }
-            (yyval.interm.fieldList)->push_back(field);
-        }
-    }
-    break;
-
-  case 145:
-
-    {
-        (yyval.interm.fieldList) = (yyvsp[(2) - (3)].interm.fieldList);
-
-        if (context->voidErrorCheck((yylsp[(1) - (3)]), (*(yyvsp[(2) - (3)].interm.fieldList))[0]->name(), (yyvsp[(1) - (3)].interm.type))) {
-            context->recover();
-        }
-        for (unsigned int i = 0; i < (yyval.interm.fieldList)->size(); ++i) {
-            //
-            // Careful not to replace already known aspects of type, like array-ness
-            //
-            TType* type = (*(yyval.interm.fieldList))[i]->type();
-            type->setBasicType((yyvsp[(1) - (3)].interm.type).type);
-            type->setNominalSize((yyvsp[(1) - (3)].interm.type).size);
-            type->setMatrix((yyvsp[(1) - (3)].interm.type).matrix);
-            type->setPrecision((yyvsp[(1) - (3)].interm.type).precision);
-
-            // don't allow arrays of arrays
-            if (type->isArray()) {
-                if (context->arrayTypeErrorCheck((yylsp[(1) - (3)]), (yyvsp[(1) - (3)].interm.type)))
-                    context->recover();
-            }
-            if ((yyvsp[(1) - (3)].interm.type).array)
-                type->setArraySize((yyvsp[(1) - (3)].interm.type).arraySize);
-            if ((yyvsp[(1) - (3)].interm.type).userDef)
-                type->setStruct((yyvsp[(1) - (3)].interm.type).userDef->getStruct());
-
-            if (context->structNestingErrorCheck((yylsp[(1) - (3)]), *(*(yyval.interm.fieldList))[i]))
-                context->recover();
-        }
-    }
-    break;
-
-  case 146:
-
-    {
-        (yyval.interm.fieldList) = NewPoolTFieldList();
-        (yyval.interm.fieldList)->push_back((yyvsp[(1) - (1)].interm.field));
-    }
-    break;
-
-  case 147:
-
-    {
-        (yyval.interm.fieldList)->push_back((yyvsp[(3) - (3)].interm.field));
-    }
-    break;
-
-  case 148:
-
-    {
-        if (context->reservedErrorCheck((yylsp[(1) - (1)]), *(yyvsp[(1) - (1)].lex).string))
-            context->recover();
-
-        TType* type = new TType(EbtVoid, EbpUndefined);
-        (yyval.interm.field) = new TField(type, (yyvsp[(1) - (1)].lex).string);
-    }
-    break;
-
-  case 149:
-
-    {
-        if (context->reservedErrorCheck((yylsp[(1) - (4)]), *(yyvsp[(1) - (4)].lex).string))
-            context->recover();
-
-        TType* type = new TType(EbtVoid, EbpUndefined);
-        int size = 0;
-        if (context->arraySizeErrorCheck((yylsp[(3) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode), size))
-            context->recover();
-        type->setArraySize(size);
-
-        (yyval.interm.field) = new TField(type, (yyvsp[(1) - (4)].lex).string);
-    }
-    break;
-
-  case 150:
-
-    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
-    break;
-
-  case 151:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
-    break;
-
-  case 152:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermAggregate); }
-    break;
-
-  case 153:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
-    break;
-
-  case 154:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
-    break;
-
-  case 155:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
-    break;
-
-  case 156:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
-    break;
-
-  case 157:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
-    break;
-
-  case 158:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
-    break;
-
-  case 159:
-
-    { (yyval.interm.intermAggregate) = 0; }
-    break;
-
-  case 160:
-
-    { context->symbolTable.push(); }
-    break;
-
-  case 161:
-
-    { context->symbolTable.pop(); }
-    break;
-
-  case 162:
-
-    {
-        if ((yyvsp[(3) - (5)].interm.intermAggregate) != 0) {
-            (yyvsp[(3) - (5)].interm.intermAggregate)->setOp(EOpSequence);
-            (yyvsp[(3) - (5)].interm.intermAggregate)->setLine((yyloc));
-        }
-        (yyval.interm.intermAggregate) = (yyvsp[(3) - (5)].interm.intermAggregate);
-    }
-    break;
-
-  case 163:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
-    break;
-
-  case 164:
-
-    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
-    break;
-
-  case 165:
-
-    { context->symbolTable.push(); }
-    break;
-
-  case 166:
-
-    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); }
-    break;
-
-  case 167:
-
-    { context->symbolTable.push(); }
-    break;
-
-  case 168:
-
-    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); }
-    break;
-
-  case 169:
-
-    {
-        (yyval.interm.intermNode) = 0;
-    }
-    break;
-
-  case 170:
-
-    {
-        if ((yyvsp[(2) - (3)].interm.intermAggregate)) {
-            (yyvsp[(2) - (3)].interm.intermAggregate)->setOp(EOpSequence);
-            (yyvsp[(2) - (3)].interm.intermAggregate)->setLine((yyloc));
-        }
-        (yyval.interm.intermNode) = (yyvsp[(2) - (3)].interm.intermAggregate);
-    }
-    break;
-
-  case 171:
-
-    {
-        (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[(1) - (1)].interm.intermNode), (yyloc));
-    }
-    break;
-
-  case 172:
-
-    {
-        (yyval.interm.intermAggregate) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermAggregate), (yyvsp[(2) - (2)].interm.intermNode), (yyloc));
-    }
-    break;
-
-  case 173:
-
-    { (yyval.interm.intermNode) = 0; }
-    break;
-
-  case 174:
-
-    { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[(1) - (2)].interm.intermTypedNode)); }
-    break;
-
-  case 175:
-
-    {
-        if (context->boolErrorCheck((yylsp[(1) - (5)]), (yyvsp[(3) - (5)].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.nodePair), (yylsp[(1) - (5)]));
-    }
-    break;
-
-  case 176:
-
-    {
-        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermNode);
-        (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermNode);
-    }
-    break;
-
-  case 177:
-
-    {
-        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (1)].interm.intermNode);
-        (yyval.interm.nodePair).node2 = 0;
-    }
-    break;
-
-  case 178:
-
-    {
-        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
-        if (context->boolErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode)->getLine(), (yyvsp[(1) - (1)].interm.intermTypedNode)))
-            context->recover();
-    }
-    break;
-
-  case 179:
-
-    {
-        TIntermNode* intermNode;
-        if (context->structQualifierErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type)))
-            context->recover();
-        if (context->boolErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type)))
-            context->recover();
-
-        if (!context->executeInitializer((yylsp[(2) - (4)]), *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode))
-            (yyval.interm.intermTypedNode) = (yyvsp[(4) - (4)].interm.intermTypedNode);
-        else {
-            context->recover();
-            (yyval.interm.intermTypedNode) = 0;
-        }
-    }
-    break;
-
-  case 180:
-
-    { context->symbolTable.push(); ++context->loopNestingLevel; }
-    break;
-
-  case 181:
-
-    {
-        context->symbolTable.pop();
-        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopWhile, 0, (yyvsp[(4) - (6)].interm.intermTypedNode), 0, (yyvsp[(6) - (6)].interm.intermNode), (yylsp[(1) - (6)]));
-        --context->loopNestingLevel;
-    }
-    break;
-
-  case 182:
-
-    { ++context->loopNestingLevel; }
-    break;
-
-  case 183:
-
-    {
-        if (context->boolErrorCheck((yylsp[(8) - (8)]), (yyvsp[(6) - (8)].interm.intermTypedNode)))
-            context->recover();
-
-        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[(6) - (8)].interm.intermTypedNode), 0, (yyvsp[(3) - (8)].interm.intermNode), (yylsp[(4) - (8)]));
-        --context->loopNestingLevel;
-    }
-    break;
-
-  case 184:
-
-    { context->symbolTable.push(); ++context->loopNestingLevel; }
-    break;
-
-  case 185:
-
-    {
-        context->symbolTable.pop();
-        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopFor, (yyvsp[(4) - (7)].interm.intermNode), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node1), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node2), (yyvsp[(7) - (7)].interm.intermNode), (yylsp[(1) - (7)]));
-        --context->loopNestingLevel;
-    }
-    break;
-
-  case 186:
-
-    {
-        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
-    }
-    break;
-
-  case 187:
-
-    {
-        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
-    }
-    break;
-
-  case 188:
-
-    {
-        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
-    }
-    break;
-
-  case 189:
-
-    {
-        (yyval.interm.intermTypedNode) = 0;
-    }
-    break;
-
-  case 190:
-
-    {
-        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (2)].interm.intermTypedNode);
-        (yyval.interm.nodePair).node2 = 0;
-    }
-    break;
-
-  case 191:
-
-    {
-        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermTypedNode);
-        (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermTypedNode);
-    }
-    break;
-
-  case 192:
-
-    {
-        if (context->loopNestingLevel <= 0) {
-            context->error((yylsp[(1) - (2)]), "continue statement only allowed in loops", "");
-            context->recover();
-        }
-        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpContinue, (yylsp[(1) - (2)]));
-    }
-    break;
-
-  case 193:
-
-    {
-        if (context->loopNestingLevel <= 0) {
-            context->error((yylsp[(1) - (2)]), "break statement only allowed in loops", "");
-            context->recover();
-        }
-        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpBreak, (yylsp[(1) - (2)]));
-    }
-    break;
-
-  case 194:
-
-    {
-        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yylsp[(1) - (2)]));
-        if (context->currentFunctionType->getBasicType() != EbtVoid) {
-            context->error((yylsp[(1) - (2)]), "non-void function must return a value", "return");
-            context->recover();
-        }
-    }
-    break;
-
-  case 195:
-
-    {
-        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(2) - (3)].interm.intermTypedNode), (yylsp[(1) - (3)]));
-        context->functionReturnsValue = true;
-        if (context->currentFunctionType->getBasicType() == EbtVoid) {
-            context->error((yylsp[(1) - (3)]), "void function cannot return a value", "return");
-            context->recover();
-        } else if (*(context->currentFunctionType) != (yyvsp[(2) - (3)].interm.intermTypedNode)->getType()) {
-            context->error((yylsp[(1) - (3)]), "function return is not matching type:", "return");
-            context->recover();
-        }
-    }
-    break;
-
-  case 196:
-
-    {
-        FRAG_ONLY("discard", (yylsp[(1) - (2)]));
-        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpKill, (yylsp[(1) - (2)]));
-    }
-    break;
-
-  case 197:
-
-    {
-        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
-        context->treeRoot = (yyval.interm.intermNode);
-    }
-    break;
-
-  case 198:
-
-    {
-        (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermNode), (yyvsp[(2) - (2)].interm.intermNode), (yyloc));
-        context->treeRoot = (yyval.interm.intermNode);
-    }
-    break;
-
-  case 199:
-
-    {
-        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
-    }
-    break;
-
-  case 200:
-
-    {
-        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
-    }
-    break;
-
-  case 201:
-
-    {
-        TFunction* function = (yyvsp[(1) - (1)].interm).function;
-        
-        const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName());
-        
-        if (builtIn)
-        {
-            context->error((yylsp[(1) - (1)]), "built-in functions cannot be redefined", function->getName().c_str());
-            context->recover();
-        }
-        
-        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName()));
-        //
-        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
-        // as it would have just been put in the symbol table.  Otherwise, we're looking up
-        // an earlier occurance.
-        //
-        if (prevDec->isDefined()) {
-            //
-            // Then this function already has a body.
-            //
-            context->error((yylsp[(1) - (1)]), "function already has a body", function->getName().c_str());
-            context->recover();
-        }
-        prevDec->setDefined();
-
-        //
-        // Raise error message if main function takes any parameters or return anything other than void
-        //
-        if (function->getName() == "main") {
-            if (function->getParamCount() > 0) {
-                context->error((yylsp[(1) - (1)]), "function cannot take any parameter(s)", function->getName().c_str());
-                context->recover();
-            }
-            if (function->getReturnType().getBasicType() != EbtVoid) {
-                context->error((yylsp[(1) - (1)]), "", function->getReturnType().getBasicString(), "main function cannot return a value");
-                context->recover();
-            }
-        }
-
-        //
-        // Remember the return type for later checking for RETURN statements.
-        //
-        context->currentFunctionType = &(prevDec->getReturnType());
-        context->functionReturnsValue = false;
-
-        //
-        // Insert parameters into the symbol table.
-        // If the parameter has no name, it's not an error, just don't insert it
-        // (could be used for unused args).
-        //
-        // Also, accumulate the list of parameters into the HIL, so lower level code
-        // knows where to find parameters.
-        //
-        TIntermAggregate* paramNodes = new TIntermAggregate;
-        for (size_t i = 0; i < function->getParamCount(); i++) {
-            const TParameter& param = function->getParam(i);
-            if (param.name != 0) {
-                TVariable *variable = new TVariable(param.name, *param.type);
-                //
-                // Insert the parameters with name in the symbol table.
-                //
-                if (! context->symbolTable.insert(*variable)) {
-                    context->error((yylsp[(1) - (1)]), "redefinition", variable->getName().c_str());
-                    context->recover();
-                    delete variable;
-                }
-
-                //
-                // Add the parameter to the HIL
-                //
-                paramNodes = context->intermediate.growAggregate(
-                                               paramNodes,
-                                               context->intermediate.addSymbol(variable->getUniqueId(),
-                                                                               variable->getName(),
-                                                                               variable->getType(),
-                                                                               (yylsp[(1) - (1)])),
-                                               (yylsp[(1) - (1)]));
-            } else {
-                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, (yylsp[(1) - (1)])), (yylsp[(1) - (1)]));
-            }
-        }
-        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yylsp[(1) - (1)]));
-        (yyvsp[(1) - (1)].interm).intermAggregate = paramNodes;
-        context->loopNestingLevel = 0;
-    }
-    break;
-
-  case 202:
-
-    {
-        //?? Check that all paths return a value if return type != void ?
-        //   May be best done as post process phase on intermediate code
-        if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
-            context->error((yylsp[(1) - (3)]), "function does not return a value:", "", (yyvsp[(1) - (3)].interm).function->getName().c_str());
-            context->recover();
-        }
-        
-        (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermAggregate, (yyvsp[(3) - (3)].interm.intermNode), (yyloc));
-        context->intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yylsp[(1) - (3)]));
-        (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[(1) - (3)].interm).function->getMangledName().c_str());
-        (yyval.interm.intermNode)->getAsAggregate()->setType((yyvsp[(1) - (3)].interm).function->getReturnType());
-
-        // store the pragma information for debug and optimize and other vendor specific
-        // information. This information can be queried from the parse tree
-        (yyval.interm.intermNode)->getAsAggregate()->setOptimize(context->pragma().optimize);
-        (yyval.interm.intermNode)->getAsAggregate()->setDebug(context->pragma().debug);
-
-        context->symbolTable.pop();
-    }
-    break;
-
-
-
-      default: break;
-    }
-  /* User semantic actions sometimes alter yychar, and that requires
-     that yytoken be updated with the new translation.  We take the
-     approach of translating immediately before every use of yytoken.
-     One alternative is translating here after every semantic action,
-     but that translation would be missed if the semantic action invokes
-     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
-     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
-     incorrect destructor might then be invoked immediately.  In the
-     case of YYERROR or YYBACKUP, subsequent parser actions might lead
-     to an incorrect destructor call or verbose syntax error message
-     before the lookahead is translated.  */
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-  *++yylsp = yyloc;
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* Make sure we have latest lookahead translation.  See comments at
-     user semantic actions for why this is necessary.  */
-  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (&yylloc, context, YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
-                                        yyssp, yytoken)
-      {
-        char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status;
-        yysyntax_error_status = YYSYNTAX_ERROR;
-        if (yysyntax_error_status == 0)
-          yymsgp = yymsg;
-        else if (yysyntax_error_status == 1)
-          {
-            if (yymsg != yymsgbuf)
-              YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
-            if (!yymsg)
-              {
-                yymsg = yymsgbuf;
-                yymsg_alloc = sizeof yymsgbuf;
-                yysyntax_error_status = 2;
-              }
-            else
-              {
-                yysyntax_error_status = YYSYNTAX_ERROR;
-                yymsgp = yymsg;
-              }
-          }
-        yyerror (&yylloc, context, yymsgp);
-        if (yysyntax_error_status == 2)
-          goto yyexhaustedlab;
-      }
-# undef YYSYNTAX_ERROR
-#endif
-    }
-
-  yyerror_range[1] = yylloc;
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
-
-      if (yychar <= YYEOF)
-	{
-	  /* Return failure if at end of input.  */
-	  if (yychar == YYEOF)
-	    YYABORT;
-	}
-      else
-	{
-	  yydestruct ("Error: discarding",
-		      yytoken, &yylval, &yylloc, context);
-	  yychar = YYEMPTY;
-	}
-    }
-
-  /* Else will try to reuse lookahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  yyerror_range[1] = yylsp[1-yylen];
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (!yypact_value_is_default (yyn))
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-	YYABORT;
-
-      yyerror_range[1] = *yylsp;
-      yydestruct ("Error: popping",
-		  yystos[yystate], yyvsp, yylsp, context);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-
-  yyerror_range[2] = yylloc;
-  /* Using YYLLOC is tempting, but would change the location of
-     the lookahead.  YYLOC is available though.  */
-  YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
-  *++yylsp = yyloc;
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#if !defined yyoverflow || YYERROR_VERBOSE
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (&yylloc, context, YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEMPTY)
-    {
-      /* Make sure we have latest lookahead translation.  See comments at
-         user semantic actions for why this is necessary.  */
-      yytoken = YYTRANSLATE (yychar);
-      yydestruct ("Cleanup: discarding lookahead",
-                  yytoken, &yylval, &yylloc, context);
-    }
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-		  yystos[*yyssp], yyvsp, yylsp, context);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-
-
-
-void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) {
-    context->error(*yylloc, reason, "");
-    context->recover();
-}
-
-int glslang_parse(TParseContext* context) {
-    return yyparse(context);
-}
diff --git a/src/third_party/angle/src/compiler/glslang_tab.h b/src/third_party/angle/src/compiler/glslang_tab.h
deleted file mode 100644
index 2f0f110..0000000
--- a/src/third_party/angle/src/compiler/glslang_tab.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.7.  */
-
-/* Bison interface for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-   
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-   
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-#ifndef YY_YY_GLSLANG_TAB_H_INCLUDED
-# define YY_YY_GLSLANG_TAB_H_INCLUDED
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-/* "%code requires" blocks.  */
-
-
-#define YYLTYPE TSourceLoc
-#define YYLTYPE_IS_DECLARED 1
-
-
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     INVARIANT = 258,
-     HIGH_PRECISION = 259,
-     MEDIUM_PRECISION = 260,
-     LOW_PRECISION = 261,
-     PRECISION = 262,
-     ATTRIBUTE = 263,
-     CONST_QUAL = 264,
-     BOOL_TYPE = 265,
-     FLOAT_TYPE = 266,
-     INT_TYPE = 267,
-     BREAK = 268,
-     CONTINUE = 269,
-     DO = 270,
-     ELSE = 271,
-     FOR = 272,
-     IF = 273,
-     DISCARD = 274,
-     RETURN = 275,
-     BVEC2 = 276,
-     BVEC3 = 277,
-     BVEC4 = 278,
-     IVEC2 = 279,
-     IVEC3 = 280,
-     IVEC4 = 281,
-     VEC2 = 282,
-     VEC3 = 283,
-     VEC4 = 284,
-     MATRIX2 = 285,
-     MATRIX3 = 286,
-     MATRIX4 = 287,
-     IN_QUAL = 288,
-     OUT_QUAL = 289,
-     INOUT_QUAL = 290,
-     UNIFORM = 291,
-     VARYING = 292,
-     STRUCT = 293,
-     VOID_TYPE = 294,
-     WHILE = 295,
-     SAMPLER2D = 296,
-     SAMPLERCUBE = 297,
-     SAMPLER_EXTERNAL_OES = 298,
-     SAMPLER2DRECT = 299,
-     IDENTIFIER = 300,
-     TYPE_NAME = 301,
-     FLOATCONSTANT = 302,
-     INTCONSTANT = 303,
-     BOOLCONSTANT = 304,
-     LEFT_OP = 305,
-     RIGHT_OP = 306,
-     INC_OP = 307,
-     DEC_OP = 308,
-     LE_OP = 309,
-     GE_OP = 310,
-     EQ_OP = 311,
-     NE_OP = 312,
-     AND_OP = 313,
-     OR_OP = 314,
-     XOR_OP = 315,
-     MUL_ASSIGN = 316,
-     DIV_ASSIGN = 317,
-     ADD_ASSIGN = 318,
-     MOD_ASSIGN = 319,
-     LEFT_ASSIGN = 320,
-     RIGHT_ASSIGN = 321,
-     AND_ASSIGN = 322,
-     XOR_ASSIGN = 323,
-     OR_ASSIGN = 324,
-     SUB_ASSIGN = 325,
-     LEFT_PAREN = 326,
-     RIGHT_PAREN = 327,
-     LEFT_BRACKET = 328,
-     RIGHT_BRACKET = 329,
-     LEFT_BRACE = 330,
-     RIGHT_BRACE = 331,
-     DOT = 332,
-     COMMA = 333,
-     COLON = 334,
-     EQUAL = 335,
-     SEMICOLON = 336,
-     BANG = 337,
-     DASH = 338,
-     TILDE = 339,
-     PLUS = 340,
-     STAR = 341,
-     SLASH = 342,
-     PERCENT = 343,
-     LEFT_ANGLE = 344,
-     RIGHT_ANGLE = 345,
-     VERTICAL_BAR = 346,
-     CARET = 347,
-     AMPERSAND = 348,
-     QUESTION = 349
-   };
-#endif
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-
-
-    struct {
-        union {
-            TString *string;
-            float f;
-            int i;
-            bool b;
-        };
-        TSymbol* symbol;
-    } lex;
-    struct {
-        TOperator op;
-        union {
-            TIntermNode* intermNode;
-            TIntermNodePair nodePair;
-            TIntermTyped* intermTypedNode;
-            TIntermAggregate* intermAggregate;
-        };
-        union {
-            TPublicType type;
-            TPrecision precision;
-            TQualifier qualifier;
-            TFunction* function;
-            TParameter param;
-            TField* field;
-            TFieldList* fieldList;
-        };
-    } interm;
-
-
-
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
-{
-  int first_line;
-  int first_column;
-  int last_line;
-  int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (TParseContext* context);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_GLSLANG_TAB_H_INCLUDED  */
diff --git a/src/third_party/angle/src/compiler/intermOut.cpp b/src/third_party/angle/src/compiler/intermOut.cpp
deleted file mode 100644
index 13aa96a..0000000
--- a/src/third_party/angle/src/compiler/intermOut.cpp
+++ /dev/null
@@ -1,424 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/localintermediate.h"
-
-//
-// Two purposes:
-// 1.  Show an example of how to iterate tree.  Functions can
-//     also directly call Traverse() on children themselves to
-//     have finer grained control over the process than shown here.
-//     See the last function for how to get started.
-// 2.  Print out a text based description of the tree.
-//
-
-//
-// Use this class to carry along data from node to node in
-// the traversal
-//
-class TOutputTraverser : public TIntermTraverser {
-public:
-    TOutputTraverser(TInfoSinkBase& i) : sink(i) { }
-    TInfoSinkBase& sink;
-
-protected:
-    void visitSymbol(TIntermSymbol*);
-    void visitConstantUnion(TIntermConstantUnion*);
-    bool visitBinary(Visit visit, TIntermBinary*);
-    bool visitUnary(Visit visit, TIntermUnary*);
-    bool visitSelection(Visit visit, TIntermSelection*);
-    bool visitAggregate(Visit visit, TIntermAggregate*);
-    bool visitLoop(Visit visit, TIntermLoop*);
-    bool visitBranch(Visit visit, TIntermBranch*);
-};
-
-TString TType::getCompleteString() const
-{
-    TStringStream stream;
-
-    if (qualifier != EvqTemporary && qualifier != EvqGlobal)
-        stream << getQualifierString() << " " << getPrecisionString() << " ";
-    if (array)
-        stream << "array[" << getArraySize() << "] of ";
-    if (matrix)
-        stream << size << "X" << size << " matrix of ";
-    else if (size > 1)
-        stream << size << "-component vector of ";
-
-    stream << getBasicString();
-    return stream.str();
-}
-
-//
-// Helper functions for printing, not part of traversing.
-//
-
-void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth)
-{
-    int i;
-
-    sink.location(node->getLine());
-
-    for (i = 0; i < depth; ++i)
-        sink << "  ";
-}
-
-//
-// The rest of the file are the traversal functions.  The last one
-// is the one that starts the traversal.
-//
-// Return true from interior nodes to have the external traversal
-// continue on to children.  If you process children yourself,
-// return false.
-//
-
-void TOutputTraverser::visitSymbol(TIntermSymbol* node)
-{
-    OutputTreeText(sink, node, depth);
-
-    sink << "'" << node->getSymbol() << "' ";
-    sink << "(" << node->getCompleteString() << ")\n";
-}
-
-bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
-{
-    TInfoSinkBase& out = sink;
-
-    OutputTreeText(out, node, depth);
-
-    switch (node->getOp()) {
-        case EOpAssign:                   out << "move second child to first child";           break;
-        case EOpInitialize:               out << "initialize first child with second child";   break;
-        case EOpAddAssign:                out << "add second child into first child";          break;
-        case EOpSubAssign:                out << "subtract second child into first child";     break;
-        case EOpMulAssign:                out << "multiply second child into first child";     break;
-        case EOpVectorTimesMatrixAssign:  out << "matrix mult second child into first child";  break;
-        case EOpVectorTimesScalarAssign:  out << "vector scale second child into first child"; break;
-        case EOpMatrixTimesScalarAssign:  out << "matrix scale second child into first child"; break;
-        case EOpMatrixTimesMatrixAssign:  out << "matrix mult second child into first child"; break;
-        case EOpDivAssign:                out << "divide second child into first child";       break;
-        case EOpIndexDirect:   out << "direct index";   break;
-        case EOpIndexIndirect: out << "indirect index"; break;
-        case EOpIndexDirectStruct:   out << "direct index for structure";   break;
-        case EOpVectorSwizzle: out << "vector swizzle"; break;
-
-        case EOpAdd:    out << "add";                     break;
-        case EOpSub:    out << "subtract";                break;
-        case EOpMul:    out << "component-wise multiply"; break;
-        case EOpDiv:    out << "divide";                  break;
-        case EOpEqual:            out << "Compare Equal";                 break;
-        case EOpNotEqual:         out << "Compare Not Equal";             break;
-        case EOpLessThan:         out << "Compare Less Than";             break;
-        case EOpGreaterThan:      out << "Compare Greater Than";          break;
-        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
-        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
-
-        case EOpVectorTimesScalar: out << "vector-scale";          break;
-        case EOpVectorTimesMatrix: out << "vector-times-matrix";   break;
-        case EOpMatrixTimesVector: out << "matrix-times-vector";   break;
-        case EOpMatrixTimesScalar: out << "matrix-scale";          break;
-        case EOpMatrixTimesMatrix: out << "matrix-multiply";       break;
-
-        case EOpLogicalOr:  out << "logical-or";   break;
-        case EOpLogicalXor: out << "logical-xor"; break;
-        case EOpLogicalAnd: out << "logical-and"; break;
-        default: out << "<unknown op>";
-    }
-
-    out << " (" << node->getCompleteString() << ")";
-
-    out << "\n";
-
-    return true;
-}
-
-bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
-{
-    TInfoSinkBase& out = sink;
-
-    OutputTreeText(out, node, depth);
-
-    switch (node->getOp()) {
-        case EOpNegative:       out << "Negate value";         break;
-        case EOpVectorLogicalNot:
-        case EOpLogicalNot:     out << "Negate conditional";   break;
-
-        case EOpPostIncrement:  out << "Post-Increment";       break;
-        case EOpPostDecrement:  out << "Post-Decrement";       break;
-        case EOpPreIncrement:   out << "Pre-Increment";        break;
-        case EOpPreDecrement:   out << "Pre-Decrement";        break;
-
-        case EOpConvIntToBool:  out << "Convert int to bool";  break;
-        case EOpConvFloatToBool:out << "Convert float to bool";break;
-        case EOpConvBoolToFloat:out << "Convert bool to float";break;
-        case EOpConvIntToFloat: out << "Convert int to float"; break;
-        case EOpConvFloatToInt: out << "Convert float to int"; break;
-        case EOpConvBoolToInt:  out << "Convert bool to int";  break;
-
-        case EOpRadians:        out << "radians";              break;
-        case EOpDegrees:        out << "degrees";              break;
-        case EOpSin:            out << "sine";                 break;
-        case EOpCos:            out << "cosine";               break;
-        case EOpTan:            out << "tangent";              break;
-        case EOpAsin:           out << "arc sine";             break;
-        case EOpAcos:           out << "arc cosine";           break;
-        case EOpAtan:           out << "arc tangent";          break;
-
-        case EOpExp:            out << "exp";                  break;
-        case EOpLog:            out << "log";                  break;
-        case EOpExp2:           out << "exp2";                 break;
-        case EOpLog2:           out << "log2";                 break;
-        case EOpSqrt:           out << "sqrt";                 break;
-        case EOpInverseSqrt:    out << "inverse sqrt";         break;
-
-        case EOpAbs:            out << "Absolute value";       break;
-        case EOpSign:           out << "Sign";                 break;
-        case EOpFloor:          out << "Floor";                break;
-        case EOpCeil:           out << "Ceiling";              break;
-        case EOpFract:          out << "Fraction";             break;
-
-        case EOpLength:         out << "length";               break;
-        case EOpNormalize:      out << "normalize";            break;
-            //	case EOpDPdx:           out << "dPdx";                 break;               
-            //	case EOpDPdy:           out << "dPdy";                 break;   
-            //	case EOpFwidth:         out << "fwidth";               break;                   
-
-        case EOpAny:            out << "any";                  break;
-        case EOpAll:            out << "all";                  break;
-
-        default:
-            out.prefix(EPrefixError);
-            out << "Bad unary op";
-    }
-
-    out << " (" << node->getCompleteString() << ")";
-
-    out << "\n";
-
-    return true;
-}
-
-bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
-{
-    TInfoSinkBase& out = sink;
-
-    if (node->getOp() == EOpNull) {
-        out.prefix(EPrefixError);
-        out << "node is still EOpNull!";
-        return true;
-    }
-
-    OutputTreeText(out, node, depth);
-
-    switch (node->getOp()) {
-        case EOpSequence:      out << "Sequence\n"; return true;
-        case EOpComma:         out << "Comma\n"; return true;
-        case EOpFunction:      out << "Function Definition: " << node->getName(); break;
-        case EOpFunctionCall:  out << "Function Call: " << node->getName(); break;
-        case EOpParameters:    out << "Function Parameters: ";              break;
-
-        case EOpConstructFloat: out << "Construct float"; break;
-        case EOpConstructVec2:  out << "Construct vec2";  break;
-        case EOpConstructVec3:  out << "Construct vec3";  break;
-        case EOpConstructVec4:  out << "Construct vec4";  break;
-        case EOpConstructBool:  out << "Construct bool";  break;
-        case EOpConstructBVec2: out << "Construct bvec2"; break;
-        case EOpConstructBVec3: out << "Construct bvec3"; break;
-        case EOpConstructBVec4: out << "Construct bvec4"; break;
-        case EOpConstructInt:   out << "Construct int";   break;
-        case EOpConstructIVec2: out << "Construct ivec2"; break;
-        case EOpConstructIVec3: out << "Construct ivec3"; break;
-        case EOpConstructIVec4: out << "Construct ivec4"; break;
-        case EOpConstructMat2:  out << "Construct mat2";  break;
-        case EOpConstructMat3:  out << "Construct mat3";  break;
-        case EOpConstructMat4:  out << "Construct mat4";  break;
-        case EOpConstructStruct:  out << "Construct structure";  break;
-
-        case EOpLessThan:         out << "Compare Less Than";             break;
-        case EOpGreaterThan:      out << "Compare Greater Than";          break;
-        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
-        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
-        case EOpVectorEqual:      out << "Equal";                         break;
-        case EOpVectorNotEqual:   out << "NotEqual";                      break;
-
-        case EOpMod:           out << "mod";         break;
-        case EOpPow:           out << "pow";         break;
-
-        case EOpAtan:          out << "arc tangent"; break;
-
-        case EOpMin:           out << "min";         break;
-        case EOpMax:           out << "max";         break;
-        case EOpClamp:         out << "clamp";       break;
-        case EOpMix:           out << "mix";         break;
-        case EOpStep:          out << "step";        break;
-        case EOpSmoothStep:    out << "smoothstep";  break;
-
-        case EOpDistance:      out << "distance";                break;
-        case EOpDot:           out << "dot-product";             break;
-        case EOpCross:         out << "cross-product";           break;
-        case EOpFaceForward:   out << "face-forward";            break;
-        case EOpReflect:       out << "reflect";                 break;
-        case EOpRefract:       out << "refract";                 break;
-        case EOpMul:           out << "component-wise multiply"; break;
-
-        case EOpDeclaration:   out << "Declaration: ";   break;
-
-        default:
-            out.prefix(EPrefixError);
-            out << "Bad aggregation op";
-    }
-
-    if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
-        out << " (" << node->getCompleteString() << ")";
-
-    out << "\n";
-
-    return true;
-}
-
-bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
-{
-    TInfoSinkBase& out = sink;
-
-    OutputTreeText(out, node, depth);
-
-    out << "Test condition and select";
-    out << " (" << node->getCompleteString() << ")\n";
-
-    ++depth;
-
-    OutputTreeText(sink, node, depth);
-    out << "Condition\n";
-    node->getCondition()->traverse(this);
-
-    OutputTreeText(sink, node, depth);
-    if (node->getTrueBlock()) {
-        out << "true case\n";
-        node->getTrueBlock()->traverse(this);
-    } else
-        out << "true case is null\n";
-
-    if (node->getFalseBlock()) {
-        OutputTreeText(sink, node, depth);
-        out << "false case\n";
-        node->getFalseBlock()->traverse(this);
-    }
-
-    --depth;
-
-    return false;
-}
-
-void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
-{
-    TInfoSinkBase& out = sink;
-
-    size_t size = node->getType().getObjectSize();
-
-    for (size_t i = 0; i < size; i++) {
-        OutputTreeText(out, node, depth);
-        switch (node->getUnionArrayPointer()[i].getType()) {
-            case EbtBool:
-                if (node->getUnionArrayPointer()[i].getBConst())
-                    out << "true";
-                else
-                    out << "false";
-
-                out << " (" << "const bool" << ")";
-                out << "\n";
-                break;
-            case EbtFloat:
-                out << node->getUnionArrayPointer()[i].getFConst();
-                out << " (const float)\n";
-                break;
-            case EbtInt:
-                out << node->getUnionArrayPointer()[i].getIConst();
-                out << " (const int)\n";
-                break;
-            default:
-                out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
-                break;
-        }
-    }
-}
-
-bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
-{
-    TInfoSinkBase& out = sink;
-
-    OutputTreeText(out, node, depth);
-
-    out << "Loop with condition ";
-    if (node->getType() == ELoopDoWhile)
-        out << "not ";
-    out << "tested first\n";
-
-    ++depth;
-
-    OutputTreeText(sink, node, depth);
-    if (node->getCondition()) {
-        out << "Loop Condition\n";
-        node->getCondition()->traverse(this);
-    } else
-        out << "No loop condition\n";
-
-    OutputTreeText(sink, node, depth);
-    if (node->getBody()) {
-        out << "Loop Body\n";
-        node->getBody()->traverse(this);
-    } else
-        out << "No loop body\n";
-
-    if (node->getExpression()) {
-        OutputTreeText(sink, node, depth);
-        out << "Loop Terminal Expression\n";
-        node->getExpression()->traverse(this);
-    }
-
-    --depth;
-
-    return false;
-}
-
-bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
-{
-    TInfoSinkBase& out = sink;
-
-    OutputTreeText(out, node, depth);
-
-    switch (node->getFlowOp()) {
-        case EOpKill:      out << "Branch: Kill";           break;
-        case EOpBreak:     out << "Branch: Break";          break;
-        case EOpContinue:  out << "Branch: Continue";       break;
-        case EOpReturn:    out << "Branch: Return";         break;
-        default:           out << "Branch: Unknown Branch"; break;
-    }
-
-    if (node->getExpression()) {
-        out << " with expression\n";
-        ++depth;
-        node->getExpression()->traverse(this);
-        --depth;
-    } else
-        out << "\n";
-
-    return false;
-}
-
-//
-// This function is the one to call externally to start the traversal.
-// Individual functions can be initialized to 0 to skip processing of that
-// type of node.  It's children will still be processed.
-//
-void TIntermediate::outputTree(TIntermNode* root)
-{
-    if (root == 0)
-        return;
-
-    TOutputTraverser it(infoSink.info);
-
-    root->traverse(&it);
-}
diff --git a/src/third_party/angle/src/compiler/intermediate.h b/src/third_party/angle/src/compiler/intermediate.h
deleted file mode 100644
index b1d20f7..0000000
--- a/src/third_party/angle/src/compiler/intermediate.h
+++ /dev/null
@@ -1,581 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-//
-// Definition of the in-memory high-level intermediate representation
-// of shaders.  This is a tree that parser creates.
-//
-// Nodes in the tree are defined as a hierarchy of classes derived from 
-// TIntermNode. Each is a node in a tree.  There is no preset branching factor;
-// each node can have it's own type of list of children.
-//
-
-#ifndef __INTERMEDIATE_H
-#define __INTERMEDIATE_H
-
-#include "GLSLANG/ShaderLang.h"
-
-#include <algorithm>
-#include "compiler/Common.h"
-#include "compiler/Types.h"
-#include "compiler/ConstantUnion.h"
-
-//
-// Operators used by the high-level (parse tree) representation.
-//
-enum TOperator {
-    EOpNull,            // if in a node, should only mean a node is still being built
-    EOpSequence,        // denotes a list of statements, or parameters, etc.
-    EOpFunctionCall,    
-    EOpFunction,        // For function definition
-    EOpParameters,      // an aggregate listing the parameters to a function
-
-    EOpDeclaration,
-    EOpPrototype,
-
-    //
-    // Unary operators
-    //
-
-    EOpNegative,
-    EOpLogicalNot,
-    EOpVectorLogicalNot,
-
-    EOpPostIncrement,
-    EOpPostDecrement,
-    EOpPreIncrement,
-    EOpPreDecrement,
-
-    EOpConvIntToBool,
-    EOpConvFloatToBool,
-    EOpConvBoolToFloat,
-    EOpConvIntToFloat,
-    EOpConvFloatToInt,
-    EOpConvBoolToInt,
-
-    //
-    // binary operations
-    //
-
-    EOpAdd,
-    EOpSub,
-    EOpMul,
-    EOpDiv,
-    EOpEqual,
-    EOpNotEqual,
-    EOpVectorEqual,
-    EOpVectorNotEqual,
-    EOpLessThan,
-    EOpGreaterThan,
-    EOpLessThanEqual,
-    EOpGreaterThanEqual,
-    EOpComma,
-
-    EOpVectorTimesScalar,
-    EOpVectorTimesMatrix,
-    EOpMatrixTimesVector,
-    EOpMatrixTimesScalar,
-
-    EOpLogicalOr,
-    EOpLogicalXor,
-    EOpLogicalAnd,
-
-    EOpIndexDirect,
-    EOpIndexIndirect,
-    EOpIndexDirectStruct,
-
-    EOpVectorSwizzle,
-
-    //
-    // Built-in functions potentially mapped to operators
-    //
-
-    EOpRadians,
-    EOpDegrees,
-    EOpSin,
-    EOpCos,
-    EOpTan,
-    EOpAsin,
-    EOpAcos,
-    EOpAtan,
-
-    EOpPow,
-    EOpExp,
-    EOpLog,
-    EOpExp2,
-    EOpLog2,
-    EOpSqrt,
-    EOpInverseSqrt,
-
-    EOpAbs,
-    EOpSign,
-    EOpFloor,
-    EOpCeil,
-    EOpFract,
-    EOpMod,
-    EOpMin,
-    EOpMax,
-    EOpClamp,
-    EOpMix,
-    EOpStep,
-    EOpSmoothStep,
-
-    EOpLength,
-    EOpDistance,
-    EOpDot,
-    EOpCross,
-    EOpNormalize,
-    EOpFaceForward,
-    EOpReflect,
-    EOpRefract,
-
-    EOpDFdx,            // Fragment only, OES_standard_derivatives extension
-    EOpDFdy,            // Fragment only, OES_standard_derivatives extension
-    EOpFwidth,          // Fragment only, OES_standard_derivatives extension
-
-    EOpMatrixTimesMatrix,
-
-    EOpAny,
-    EOpAll,
-
-    //
-    // Branch
-    //
-
-    EOpKill,            // Fragment only
-    EOpReturn,
-    EOpBreak,
-    EOpContinue,
-
-    //
-    // Constructors
-    //
-
-    EOpConstructInt,
-    EOpConstructBool,
-    EOpConstructFloat,
-    EOpConstructVec2,
-    EOpConstructVec3,
-    EOpConstructVec4,
-    EOpConstructBVec2,
-    EOpConstructBVec3,
-    EOpConstructBVec4,
-    EOpConstructIVec2,
-    EOpConstructIVec3,
-    EOpConstructIVec4,
-    EOpConstructMat2,
-    EOpConstructMat3,
-    EOpConstructMat4,
-    EOpConstructStruct,
-
-    //
-    // moves
-    //
-
-    EOpAssign,
-    EOpInitialize,
-    EOpAddAssign,
-    EOpSubAssign,
-    EOpMulAssign,
-    EOpVectorTimesMatrixAssign,
-    EOpVectorTimesScalarAssign,
-    EOpMatrixTimesScalarAssign,
-    EOpMatrixTimesMatrixAssign,
-    EOpDivAssign
-};
-
-extern const char* getOperatorString(TOperator op);
-
-class TIntermTraverser;
-class TIntermAggregate;
-class TIntermBinary;
-class TIntermUnary;
-class TIntermConstantUnion;
-class TIntermSelection;
-class TIntermTyped;
-class TIntermSymbol;
-class TIntermLoop;
-class TInfoSink;
-
-//
-// Base class for the tree nodes
-//
-class TIntermNode {
-public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-
-    TIntermNode() {
-        // TODO: Move this to TSourceLoc constructor
-        // after getting rid of TPublicType.
-        line.first_file = line.last_file = 0;
-        line.first_line = line.last_line = 0;
-    }
-    virtual ~TIntermNode() { }
-
-    const TSourceLoc& getLine() const { return line; }
-    void setLine(const TSourceLoc& l) { line = l; }
-
-    virtual void traverse(TIntermTraverser*) = 0;
-    virtual TIntermTyped* getAsTyped() { return 0; }
-    virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
-    virtual TIntermAggregate* getAsAggregate() { return 0; }
-    virtual TIntermBinary* getAsBinaryNode() { return 0; }
-    virtual TIntermUnary* getAsUnaryNode() { return 0; }
-    virtual TIntermSelection* getAsSelectionNode() { return 0; }
-    virtual TIntermSymbol* getAsSymbolNode() { return 0; }
-    virtual TIntermLoop* getAsLoopNode() { return 0; }
-
-protected:
-    TSourceLoc line;
-};
-
-//
-// This is just to help yacc.
-//
-struct TIntermNodePair {
-    TIntermNode* node1;
-    TIntermNode* node2;
-};
-
-//
-// Intermediate class for nodes that have a type.
-//
-class TIntermTyped : public TIntermNode {
-public:
-    TIntermTyped(const TType& t) : type(t)  { }
-    virtual TIntermTyped* getAsTyped() { return this; }
-
-    void setType(const TType& t) { type = t; }
-    const TType& getType() const { return type; }
-    TType* getTypePointer() { return &type; }
-
-    TBasicType getBasicType() const { return type.getBasicType(); }
-    TQualifier getQualifier() const { return type.getQualifier(); }
-    TPrecision getPrecision() const { return type.getPrecision(); }
-    int getNominalSize() const { return type.getNominalSize(); }
-    
-    bool isMatrix() const { return type.isMatrix(); }
-    bool isArray()  const { return type.isArray(); }
-    bool isVector() const { return type.isVector(); }
-    bool isScalar() const { return type.isScalar(); }
-    const char* getBasicString() const { return type.getBasicString(); }
-    const char* getQualifierString() const { return type.getQualifierString(); }
-    TString getCompleteString() const { return type.getCompleteString(); }
-
-    int totalRegisterCount() const { return type.totalRegisterCount(); }
-    int elementRegisterCount() const { return type.elementRegisterCount(); }
-    int getArraySize() const { return type.getArraySize(); }
-
-protected:
-    TType type;
-};
-
-//
-// Handle for, do-while, and while loops.
-//
-enum TLoopType {
-    ELoopFor,
-    ELoopWhile,
-    ELoopDoWhile
-};
-
-class TIntermLoop : public TIntermNode {
-public:
-    TIntermLoop(TLoopType aType,
-                TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
-                TIntermNode* aBody) :
-            type(aType),
-            init(aInit),
-            cond(aCond),
-            expr(aExpr),
-            body(aBody),
-            unrollFlag(false) { }
-
-    virtual TIntermLoop* getAsLoopNode() { return this; }
-    virtual void traverse(TIntermTraverser*);
-
-    TLoopType getType() const { return type; }
-    TIntermNode* getInit() { return init; }
-    TIntermTyped* getCondition() { return cond; }
-    TIntermTyped* getExpression() { return expr; }
-    TIntermNode* getBody() { return body; }
-
-    void setUnrollFlag(bool flag) { unrollFlag = flag; }
-    bool getUnrollFlag() { return unrollFlag; }
-
-protected:
-    TLoopType type;
-    TIntermNode* init;  // for-loop initialization
-    TIntermTyped* cond; // loop exit condition
-    TIntermTyped* expr; // for-loop expression
-    TIntermNode* body;  // loop body
-
-    bool unrollFlag; // Whether the loop should be unrolled or not.
-};
-
-//
-// Handle break, continue, return, and kill.
-//
-class TIntermBranch : public TIntermNode {
-public:
-    TIntermBranch(TOperator op, TIntermTyped* e) :
-            flowOp(op),
-            expression(e) { }
-
-    virtual void traverse(TIntermTraverser*);
-
-    TOperator getFlowOp() { return flowOp; }
-    TIntermTyped* getExpression() { return expression; }
-
-protected:
-    TOperator flowOp;
-    TIntermTyped* expression;  // non-zero except for "return exp;" statements
-};
-
-//
-// Nodes that correspond to symbols or constants in the source code.
-//
-class TIntermSymbol : public TIntermTyped {
-public:
-    // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
-    // per process globalpoolallocator, then it causes increased memory usage per compile
-    // it is essential to use "symbol = sym" to assign to symbol
-    TIntermSymbol(int i, const TString& sym, const TType& t) : 
-            TIntermTyped(t), id(i)  { symbol = sym; originalSymbol = sym; } 
-
-    int getId() const { return id; }
-    const TString& getSymbol() const { return symbol; }
-
-    void setId(int newId) { id = newId; }
-    void setSymbol(const TString& sym) { symbol = sym; }
-
-    const TString& getOriginalSymbol() const { return originalSymbol; }
-
-    virtual void traverse(TIntermTraverser*);
-    virtual TIntermSymbol* getAsSymbolNode() { return this; }
-
-protected:
-    int id;
-    TString symbol;
-    TString originalSymbol;
-};
-
-class TIntermConstantUnion : public TIntermTyped {
-public:
-    TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
-
-    ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
-    
-    int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
-    float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
-    bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
-
-    virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
-    virtual void traverse(TIntermTraverser*);
-
-    TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
-
-protected:
-    ConstantUnion *unionArrayPointer;
-};
-
-//
-// Intermediate class for node types that hold operators.
-//
-class TIntermOperator : public TIntermTyped {
-public:
-    TOperator getOp() const { return op; }
-    void setOp(TOperator o) { op = o; }
-
-    bool modifiesState() const;
-    bool isConstructor() const;
-
-protected:
-    TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
-    TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}   
-    TOperator op;
-};
-
-//
-// Nodes for all the basic binary math operators.
-//
-class TIntermBinary : public TIntermOperator {
-public:
-    TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
-
-    virtual TIntermBinary* getAsBinaryNode() { return this; }
-    virtual void traverse(TIntermTraverser*);
-
-    void setLeft(TIntermTyped* n) { left = n; }
-    void setRight(TIntermTyped* n) { right = n; }
-    TIntermTyped* getLeft() const { return left; }
-    TIntermTyped* getRight() const { return right; }
-    bool promote(TInfoSink&);
-
-    void setAddIndexClamp() { addIndexClamp = true; }
-    bool getAddIndexClamp() { return addIndexClamp; }
-
-protected:
-    TIntermTyped* left;
-    TIntermTyped* right;
-
-    // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
-    bool addIndexClamp;
-};
-
-//
-// Nodes for unary math operators.
-//
-class TIntermUnary : public TIntermOperator {
-public:
-    TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
-    TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
-
-    virtual void traverse(TIntermTraverser*);
-    virtual TIntermUnary* getAsUnaryNode() { return this; }
-
-    void setOperand(TIntermTyped* o) { operand = o; }
-    TIntermTyped* getOperand() { return operand; }    
-    bool promote(TInfoSink&);
-
-    void setUseEmulatedFunction() { useEmulatedFunction = true; }
-    bool getUseEmulatedFunction() { return useEmulatedFunction; }
-
-protected:
-    TIntermTyped* operand;
-
-    // If set to true, replace the built-in function call with an emulated one
-    // to work around driver bugs.
-    bool useEmulatedFunction;
-};
-
-typedef TVector<TIntermNode*> TIntermSequence;
-typedef TVector<int> TQualifierList;
-
-//
-// Nodes that operate on an arbitrary sized set of children.
-//
-class TIntermAggregate : public TIntermOperator {
-public:
-    TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
-    TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
-    ~TIntermAggregate() { }
-
-    virtual TIntermAggregate* getAsAggregate() { return this; }
-    virtual void traverse(TIntermTraverser*);
-
-    TIntermSequence& getSequence() { return sequence; }
-
-    void setName(const TString& n) { name = n; }
-    const TString& getName() const { return name; }
-
-    void setUserDefined() { userDefined = true; }
-    bool isUserDefined() const { return userDefined; }
-
-    void setOptimize(bool o) { optimize = o; }
-    bool getOptimize() { return optimize; }
-    void setDebug(bool d) { debug = d; }
-    bool getDebug() { return debug; }
-
-    void setUseEmulatedFunction() { useEmulatedFunction = true; }
-    bool getUseEmulatedFunction() { return useEmulatedFunction; }
-
-protected:
-    TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
-    TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
-    TIntermSequence sequence;
-    TString name;
-    bool userDefined; // used for user defined function names
-
-    bool optimize;
-    bool debug;
-
-    // If set to true, replace the built-in function call with an emulated one
-    // to work around driver bugs.
-    bool useEmulatedFunction;
-};
-
-//
-// For if tests.  Simplified since there is no switch statement.
-//
-class TIntermSelection : public TIntermTyped {
-public:
-    TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
-            TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
-    TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
-            TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
-
-    virtual void traverse(TIntermTraverser*);
-
-    bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
-    TIntermNode* getCondition() const { return condition; }
-    TIntermNode* getTrueBlock() const { return trueBlock; }
-    TIntermNode* getFalseBlock() const { return falseBlock; }
-    TIntermSelection* getAsSelectionNode() { return this; }
-
-protected:
-    TIntermTyped* condition;
-    TIntermNode* trueBlock;
-    TIntermNode* falseBlock;
-};
-
-enum Visit
-{
-    PreVisit,
-    InVisit,
-    PostVisit
-};
-
-//
-// For traversing the tree.  User should derive from this, 
-// put their traversal specific data in it, and then pass
-// it to a Traverse method.
-//
-// When using this, just fill in the methods for nodes you want visited.
-// Return false from a pre-visit to skip visiting that node's subtree.
-//
-class TIntermTraverser
-{
-public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-
-    TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : 
-            preVisit(preVisit),
-            inVisit(inVisit),
-            postVisit(postVisit),
-            rightToLeft(rightToLeft),
-            depth(0),
-            maxDepth(0) {}
-    virtual ~TIntermTraverser() {};
-
-    virtual void visitSymbol(TIntermSymbol*) {}
-    virtual void visitConstantUnion(TIntermConstantUnion*) {}
-    virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
-    virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
-    virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
-    virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
-    virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
-    virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
-
-    int getMaxDepth() const {return maxDepth;}
-    void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); }
-    void decrementDepth() {depth--;}
-
-    // Return the original name if hash function pointer is NULL;
-    // otherwise return the hashed name.
-    static TString hash(const TString& name, ShHashFunction64 hashFunction);
-
-    const bool preVisit;
-    const bool inVisit;
-    const bool postVisit;
-    const bool rightToLeft;
-
-protected:
-    int depth;
-    int maxDepth;
-};
-
-#endif // __INTERMEDIATE_H
diff --git a/src/third_party/angle/src/compiler/localintermediate.h b/src/third_party/angle/src/compiler/localintermediate.h
deleted file mode 100644
index b673407..0000000
--- a/src/third_party/angle/src/compiler/localintermediate.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef _LOCAL_INTERMEDIATE_INCLUDED_
-#define _LOCAL_INTERMEDIATE_INCLUDED_
-
-#include "GLSLANG/ShaderLang.h"
-#include "compiler/intermediate.h"
-#include "compiler/SymbolTable.h"
-
-struct TVectorFields {
-    int offsets[4];
-    int num;
-};
-
-//
-// Set of helper functions to help parse and build the tree.
-//
-class TInfoSink;
-class TIntermediate {
-public:    
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-
-    TIntermediate(TInfoSink& i) : infoSink(i) { }
-    TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&);
-    TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
-    TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&);
-    TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
-    TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
-    TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&);
-    TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
-    TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
-    TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&);
-    TIntermNode*  addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
-    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
-    TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
-    TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&);
-    TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
-    bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);        
-    TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&);
-    TIntermBranch* addBranch(TOperator, const TSourceLoc&);
-    TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
-    TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&);
-    bool postProcess(TIntermNode*);
-    void remove(TIntermNode*);
-    void outputTree(TIntermNode*);
-
-private:
-    void operator=(TIntermediate&); // prevent assignments
-
-    TInfoSink& infoSink;
-};
-
-#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/src/third_party/angle/src/compiler/osinclude.h b/src/third_party/angle/src/compiler/osinclude.h
deleted file mode 100644
index fae7a33..0000000
--- a/src/third_party/angle/src/compiler/osinclude.h
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef __OSINCLUDE_H
-#define __OSINCLUDE_H
-
-//
-// This file contains contains os-specific datatypes and
-// declares any os-specific functions.
-//
-
-#if (defined(_WIN32) || defined(_WIN64)) && !defined(__LB_XB360__)
-#define ANGLE_OS_WIN
-#elif defined(__APPLE__) || defined(__linux__) || \
-      defined(__FreeBSD__) || defined(__OpenBSD__) || \
-      defined(__sun) || defined(ANDROID) || \
-      defined(__GLIBC__) || defined(__GNU__) || \
-      defined(__QNX__) || defined(__LB_SHELL__)
-#define ANGLE_OS_POSIX
-#else
-#error Unsupported platform.
-#endif
-
-#if defined(ANGLE_OS_WIN)
-#define STRICT
-#define VC_EXTRALEAN 1
-#include <windows.h>
-#elif defined(ANGLE_OS_POSIX)
-#include <pthread.h>
-#include <semaphore.h>
-#include <errno.h>
-#endif  // ANGLE_OS_WIN
-
-
-#include "compiler/debug.h"
-
-//
-// Thread Local Storage Operations
-//
-#if defined(ANGLE_OS_WIN)
-typedef DWORD OS_TLSIndex;
-#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
-#elif defined(ANGLE_OS_POSIX)
-typedef pthread_key_t OS_TLSIndex;
-#if defined(PTW32_VERSION)
-#define OS_INVALID_TLS_INDEX (OS_TLSIndex())
-#else
-#define OS_INVALID_TLS_INDEX (static_cast<OS_TLSIndex>(-1))
-#endif
-#endif  // ANGLE_OS_WIN
-
-OS_TLSIndex OS_AllocTLSIndex();
-bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
-bool OS_FreeTLSIndex(OS_TLSIndex nIndex);
-
-inline void* OS_GetTLSValue(OS_TLSIndex nIndex)
-{
-    ASSERT(nIndex != OS_INVALID_TLS_INDEX);
-#if defined(ANGLE_OS_WIN)
-    return TlsGetValue(nIndex);
-#elif defined(ANGLE_OS_POSIX)
-    return pthread_getspecific(nIndex);
-#endif  // ANGLE_OS_WIN
-}
-
-#endif // __OSINCLUDE_H
diff --git a/src/third_party/angle/src/compiler/ossource_posix.cpp b/src/third_party/angle/src/compiler/ossource_posix.cpp
deleted file mode 100644
index 1e1e699..0000000
--- a/src/third_party/angle/src/compiler/ossource_posix.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-//
-// This file contains the posix specific functions
-//
-#include "compiler/osinclude.h"
-
-#if !defined(ANGLE_OS_POSIX)
-#error Trying to build a posix specific file in a non-posix build.
-#endif
-
-//
-// Thread Local Storage Operations
-//
-OS_TLSIndex OS_AllocTLSIndex()
-{
-    pthread_key_t pPoolIndex;
-
-    //
-    // Create global pool key.
-    //
-    if ((pthread_key_create(&pPoolIndex, NULL)) != 0) {
-        assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
-        return false;
-    }
-    else {
-        return pPoolIndex;
-    }
-}
-
-
-bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
-{
-    if (nIndex == OS_INVALID_TLS_INDEX) {
-        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
-        return false;
-    }
-
-    if (pthread_setspecific(nIndex, lpvValue) == 0)
-        return true;
-    else
-        return false;
-}
-
-
-bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
-{
-    if (nIndex == OS_INVALID_TLS_INDEX) {
-        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
-        return false;
-    }
-
-    //
-    // Delete the global pool key.
-    //
-    if (pthread_key_delete(nIndex) == 0)
-        return true;
-    else
-        return false;
-}
diff --git a/src/third_party/angle/src/compiler/ossource_win.cpp b/src/third_party/angle/src/compiler/ossource_win.cpp
deleted file mode 100644
index 89922fe..0000000
--- a/src/third_party/angle/src/compiler/ossource_win.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/osinclude.h"
-//
-// This file contains contains the window's specific functions
-//
-
-#if !defined(ANGLE_OS_WIN)
-#error Trying to build a windows specific file in a non windows build.
-#endif
-
-
-//
-// Thread Local Storage Operations
-//
-OS_TLSIndex OS_AllocTLSIndex()
-{
-	DWORD dwIndex = TlsAlloc();
-	if (dwIndex == TLS_OUT_OF_INDEXES) {
-		assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
-		return OS_INVALID_TLS_INDEX;
-	}
-
-	return dwIndex;
-}
-
-
-bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
-{
-	if (nIndex == OS_INVALID_TLS_INDEX) {
-		assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
-		return false;
-	}
-
-	if (TlsSetValue(nIndex, lpvValue))
-		return true;
-	else
-		return false;
-}
-
-
-bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
-{
-	if (nIndex == OS_INVALID_TLS_INDEX) {
-		assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
-		return false;
-	}
-
-	if (TlsFree(nIndex))
-		return true;
-	else
-		return false;
-}
diff --git a/src/third_party/angle/src/compiler/parseConst.cpp b/src/third_party/angle/src/compiler/parseConst.cpp
deleted file mode 100644
index 1cc5db8..0000000
--- a/src/third_party/angle/src/compiler/parseConst.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/ParseHelper.h"
-
-//
-// Use this class to carry along data from node to node in 
-// the traversal
-//
-class TConstTraverser : public TIntermTraverser {
-public:
-    TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t)
-        : error(false),
-          index(0),
-          unionArray(cUnion),
-          type(t),
-          constructorType(constructType),
-          singleConstantParam(singleConstParam),
-          infoSink(sink),
-          symbolTable(symTable),
-          size(0),
-          isMatrix(false),
-          matrixSize(0) {
-    }
-
-    bool error;
-
-protected:
-    void visitSymbol(TIntermSymbol*);
-    void visitConstantUnion(TIntermConstantUnion*);
-    bool visitBinary(Visit visit, TIntermBinary*);
-    bool visitUnary(Visit visit, TIntermUnary*);
-    bool visitSelection(Visit visit, TIntermSelection*);
-    bool visitAggregate(Visit visit, TIntermAggregate*);
-    bool visitLoop(Visit visit, TIntermLoop*);
-    bool visitBranch(Visit visit, TIntermBranch*);
-
-    size_t index;
-    ConstantUnion *unionArray;
-    TType type;
-    TOperator constructorType;
-    bool singleConstantParam;
-    TInfoSink& infoSink;
-    TSymbolTable& symbolTable;
-    size_t size; // size of the constructor ( 4 for vec4)
-    bool isMatrix;
-    size_t matrixSize; // dimension of the matrix (nominal size and not the instance size)
-};
-
-//
-// The rest of the file are the traversal functions.  The last one
-// is the one that starts the traversal.
-//
-// Return true from interior nodes to have the external traversal
-// continue on to children.  If you process children yourself,
-// return false.
-//
-
-void TConstTraverser::visitSymbol(TIntermSymbol* node)
-{
-    infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor");
-    return;
-
-}
-
-bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
-{
-    TQualifier qualifier = node->getType().getQualifier();
-    
-    if (qualifier != EvqConst) {
-        TString buf;
-        buf.append("'constructor' : assigning non-constant to ");
-        buf.append(type.getCompleteString());
-        infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
-        error = true;
-        return false;  
-    }
-
-   infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor");
-    
-    return false;
-}
-
-bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
-{
-    TString buf;
-    buf.append("'constructor' : assigning non-constant to ");
-    buf.append(type.getCompleteString());
-    infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
-    error = true;
-    return false;  
-}
-
-bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
-{
-    if (!node->isConstructor() && node->getOp() != EOpComma) {
-        TString buf;
-        buf.append("'constructor' : assigning non-constant to ");
-        buf.append(type.getCompleteString());
-        infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
-        error = true;
-        return false;  
-    }
-
-    if (node->getSequence().size() == 0) {
-        error = true;
-        return false;
-    }
-
-    bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
-    if (flag) 
-    {
-        singleConstantParam = true; 
-        constructorType = node->getOp();
-        size = node->getType().getObjectSize();
-
-        if (node->getType().isMatrix()) {
-            isMatrix = true;
-            matrixSize = node->getType().getNominalSize();
-        }
-    }       
-
-    for (TIntermSequence::iterator p = node->getSequence().begin(); 
-                                   p != node->getSequence().end(); p++) {
-
-        if (node->getOp() == EOpComma)
-            index = 0;           
-
-        (*p)->traverse(this);
-    }   
-    if (flag) 
-    {
-        singleConstantParam = false;   
-        constructorType = EOpNull;
-        size = 0;
-        isMatrix = false;
-        matrixSize = 0;
-    }
-    return false;
-}
-
-bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
-{
-    infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
-    error = true;
-    return false;
-}
-
-void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
-{
-    if (!node->getUnionArrayPointer())
-    {
-        // The constant was not initialized, this should already have been logged
-        assert(infoSink.info.size() != 0);
-        return;
-    }
-
-    ConstantUnion* leftUnionArray = unionArray;
-    size_t instanceSize = type.getObjectSize();
-
-    if (index >= instanceSize)
-        return;
-
-    if (!singleConstantParam) {
-        size_t size = node->getType().getObjectSize();
-    
-        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
-        for (size_t i = 0; i < size; i++) {
-            if (index >= instanceSize)
-                return;
-            leftUnionArray[index] = rightUnionArray[i];
-
-            (index)++;
-        }
-    } else {
-        size_t totalSize = index + size;
-        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
-        if (!isMatrix) {
-            size_t count = 0;
-            for (size_t i = index; i < totalSize; i++) {
-                if (i >= instanceSize)
-                    return;
-
-                leftUnionArray[i] = rightUnionArray[count];
-
-                (index)++;
-                
-                if (node->getType().getObjectSize() > 1)
-                    count++;
-            }
-        } else {  // for matrix constructors
-            size_t count = 0;
-            size_t element = index;
-            for (size_t i = index; i < totalSize; i++) {
-                if (i >= instanceSize)
-                    return;
-                if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
-                    leftUnionArray[i] = rightUnionArray[count];
-                else 
-                    leftUnionArray[i].setFConst(0.0f);
-
-                (index)++;
-
-                if (node->getType().getObjectSize() > 1)
-                    count++;                
-            }
-        }
-    }
-}
-
-bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
-{
-    infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
-    error = true;
-    return false;
-}
-
-bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
-{
-    infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
-    error = true;
-    return false;
-}
-
-//
-// This function is the one to call externally to start the traversal.
-// Individual functions can be initialized to 0 to skip processing of that
-// type of node.  It's children will still be processed.
-//
-bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
-{
-    if (root == 0)
-        return false;
-
-    TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
-
-    root->traverse(&it);
-    if (it.error)
-        return true;
-    else
-        return false;
-}
diff --git a/src/third_party/angle/src/compiler/preprocessor/64bit-tokenizer-safety.patch b/src/third_party/angle/src/compiler/preprocessor/64bit-tokenizer-safety.patch
index 7cb0616..912520c 100644
--- a/src/third_party/angle/src/compiler/preprocessor/64bit-tokenizer-safety.patch
+++ b/src/third_party/angle/src/compiler/preprocessor/64bit-tokenizer-safety.patch
@@ -1,130 +1,56 @@
+diff --git a/src/compiler/preprocessor/Tokenizer.cpp b/src/compiler/preprocessor/Tokenizer.cpp
+index 0d7ad58..5ef0e5e 100644
 --- a/src/compiler/preprocessor/Tokenizer.cpp
 +++ b/src/compiler/preprocessor/Tokenizer.cpp
-@@ -56,6 +56,7 @@ typedef int16_t flex_int16_t;
- typedef uint16_t flex_uint16_t;
- typedef int32_t flex_int32_t;
- typedef uint32_t flex_uint32_t;
-+typedef uint64_t flex_uint64_t;
- #else
- typedef signed char flex_int8_t;
- typedef short int flex_int16_t;
-@@ -179,6 +180,11 @@ typedef void* yyscan_t;
- typedef struct yy_buffer_state *YY_BUFFER_STATE;
- #endif
- 
-+#ifndef YY_TYPEDEF_YY_SIZE_T
-+#define YY_TYPEDEF_YY_SIZE_T
-+typedef size_t yy_size_t;
-+#endif
-+
- #define EOB_ACT_CONTINUE_SCAN 0
- #define EOB_ACT_END_OF_FILE 1
- #define EOB_ACT_LAST_MATCH 2
-@@ -201,11 +207,6 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
- 
- #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
- 
--#ifndef YY_TYPEDEF_YY_SIZE_T
--#define YY_TYPEDEF_YY_SIZE_T
--typedef size_t yy_size_t;
--#endif
--
- #ifndef YY_STRUCT_YY_BUFFER_STATE
- #define YY_STRUCT_YY_BUFFER_STATE
- struct yy_buffer_state
-@@ -223,7 +224,7 @@ struct yy_buffer_state
- 	/* Number of characters read into yy_ch_buf, not including EOB
- 	 * characters.
- 	 */
--	int yy_n_chars;
-+	yy_size_t yy_n_chars;
- 
- 	/* Whether we "own" the buffer - i.e., we know we created it,
- 	 * and can realloc() it to grow it, and should free() it to
-@@ -302,7 +303,7 @@ static void pp_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
- 
- YY_BUFFER_STATE pp_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
- YY_BUFFER_STATE pp_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
--YY_BUFFER_STATE pp_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-+YY_BUFFER_STATE pp_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
- 
- void *ppalloc (yy_size_t ,yyscan_t yyscanner );
- void *pprealloc (void *,yy_size_t ,yyscan_t yyscanner );
-@@ -353,7 +354,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
-  */
- #define YY_DO_BEFORE_ACTION \
- 	yyg->yytext_ptr = yy_bp; \
--	yyleng = (size_t) (yy_cp - yy_bp); \
-+	yyleng = (yy_size_t) (yy_cp - yy_bp); \
- 	yyg->yy_hold_char = *yy_cp; \
- 	*yy_cp = '\0'; \
- 	yyg->yy_c_buf_p = yy_cp;
-@@ -579,8 +580,8 @@ struct yyguts_t
-     size_t yy_buffer_stack_max; /**< capacity of stack. */
-     YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
-     char yy_hold_char;
--    int yy_n_chars;
--    int yyleng_r;
-+    yy_size_t yy_n_chars;
-+    yy_size_t yyleng_r;
-     char *yy_c_buf_p;
-     int yy_init;
-     int yy_start;
-@@ -637,7 +638,7 @@ FILE *ppget_out (yyscan_t yyscanner );
- 
- void ppset_out  (FILE * out_str ,yyscan_t yyscanner );
- 
--int ppget_leng (yyscan_t yyscanner );
-+yy_size_t ppget_leng (yyscan_t yyscanner );
- 
- char *ppget_text (yyscan_t yyscanner );
- 
-@@ -704,7 +705,7 @@ static int input (yyscan_t yyscanner );
- 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
- 		{ \
- 		int c = '*'; \
--		int n; \
-+		yy_size_t n; \
- 		for ( n = 0; n < max_size && \
- 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
- 			buf[n] = (char) c; \
-@@ -1338,7 +1339,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
- 
+@@ -1703,7 +1703,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
  	else
  		{
--			int num_to_read =
-+			yy_size_t num_to_read =
- 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+ 			int num_to_read =
+-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
++			static_cast<int>(YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1);
  
  		while ( num_to_read <= 0 )
-@@ -1352,7 +1353,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
+ 			{ /* Not enough room in the buffer - grow it. */
+@@ -1737,8 +1737,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
  
- 			if ( b->yy_is_our_buffer )
- 				{
--				int new_size = b->yy_buf_size * 2;
-+				yy_size_t new_size = b->yy_buf_size * 2;
+ 			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
  
- 				if ( new_size <= 0 )
- 					b->yy_buf_size += b->yy_buf_size / 8;
-@@ -1383,7 +1384,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
+-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+-						number_to_move - 1;
++			num_to_read = static_cast<int>(YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
++						number_to_move - 1);
+ 
+ 			}
+ 
+@@ -1746,8 +1746,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
+ 			num_to_read = YY_READ_BUF_SIZE;
  
  		/* Read in more data. */
++		yy_size_t ret = 0;
  		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
--			yyg->yy_n_chars, (size_t) num_to_read );
-+			yyg->yy_n_chars, num_to_read );
+-			yyg->yy_n_chars, num_to_read );
++			ret, num_to_read );
++		yyg->yy_n_chars = static_cast<int>(ret);
  
  		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
  		}
-@@ -1508,7 +1509,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
+@@ -1773,13 +1775,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
  
- 		else
- 			{ /* need more input */
--			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
-+			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
- 			++yyg->yy_c_buf_p;
+ 	if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ 		/* Extend the array by 50%, plus the number we really need. */
+-		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
++		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ 		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) pprealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ 		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ 	}
  
- 			switch ( yy_get_next_buffer( yyscanner ) )
-@@ -1788,7 +1789,7 @@ void pppop_buffer_state (yyscan_t yyscanner)
+-	yyg->yy_n_chars += number_to_move;
++	yyg->yy_n_chars += static_cast<int>(number_to_move);
+ 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+ 
+@@ -2171,7 +2173,7 @@ void pppop_buffer_state (yyscan_t yyscanner)
   */
  static void ppensure_buffer_stack (yyscan_t yyscanner)
  {
@@ -133,27 +59,21 @@
      struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
  
  	if (!yyg->yy_buffer_stack) {
-@@ -1886,12 +1887,11 @@ YY_BUFFER_STATE pp_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-  * @param yyscanner The scanner object.
-  * @return the newly allocated buffer state object.
-  */
--YY_BUFFER_STATE pp_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
-+YY_BUFFER_STATE pp_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
- {
- 	YY_BUFFER_STATE b;
- 	char *buf;
--	yy_size_t n;
--	int i;
-+	yy_size_t n, i;
-     
- 	/* Get memory for full buffer, including space for trailing EOB's. */
- 	n = _yybytes_len + 2;
-@@ -2001,7 +2001,7 @@ FILE *ppget_out  (yyscan_t yyscanner)
- /** Get the length of the current token.
-  * @param yyscanner The scanner object.
-  */
--int ppget_leng  (yyscan_t yyscanner)
-+yy_size_t ppget_leng  (yyscan_t yyscanner)
- {
-     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-     return yyleng;
+@@ -2238,7 +2240,7 @@ YY_BUFFER_STATE pp_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscann
+ 	if ( ! b )
+ 		YY_FATAL_ERROR( "out of dynamic memory in pp_scan_buffer()" );
+ 
+-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
++	b->yy_buf_size = static_cast<int>(size - 2);	/* "- 2" to take care of EOB's */
+ 	b->yy_buf_pos = b->yy_ch_buf = base;
+ 	b->yy_is_our_buffer = 0;
+ 	b->yy_input_file = NULL;
+@@ -2293,7 +2295,7 @@ YY_BUFFER_STATE pp_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yysc
+ 	if ( ! buf )
+ 		YY_FATAL_ERROR( "out of dynamic memory in pp_scan_bytes()" );
+ 
+-	for ( i = 0; i < _yybytes_len; ++i )
++	for ( i = 0; i < static_cast<yy_size_t>(_yybytes_len); ++i )
+ 		buf[i] = yybytes[i];
+ 
+ 	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
diff --git a/src/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
index 3e22e1f..1b9575b 100644
--- a/src/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
@@ -4,9 +4,9 @@
 // found in the LICENSE file.
 //
 
-#include "DiagnosticsBase.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
 
-#include <cassert>
+#include "common/debug.h"
 
 namespace pp
 {
@@ -15,112 +15,126 @@
 {
 }
 
-void Diagnostics::report(ID id,
-                         const SourceLocation& loc,
-                         const std::string& text)
+void Diagnostics::report(ID id, const SourceLocation &loc, const std::string &text)
 {
-    // TODO(alokp): Keep a count of errors and warnings.
     print(id, loc, text);
 }
 
-Diagnostics::Severity Diagnostics::severity(ID id)
+bool Diagnostics::isError(ID id)
 {
-    if ((id > ERROR_BEGIN) && (id < ERROR_END))
-        return ERROR;
+    if ((id > PP_ERROR_BEGIN) && (id < PP_ERROR_END))
+        return true;
 
-    if ((id > WARNING_BEGIN) && (id < WARNING_END))
-        return WARNING;
+    if ((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END))
+        return false;
 
-    assert(false);
-    return ERROR;
+    UNREACHABLE();
+    return true;
 }
 
-std::string Diagnostics::message(ID id)
+const char *Diagnostics::message(ID id)
 {
     switch (id)
     {
-      // Errors begin.
-      case INTERNAL_ERROR:
-          return "internal error";
-      case OUT_OF_MEMORY:
-          return "out of memory";
-      case INVALID_CHARACTER:
-          return "invalid character";
-      case INVALID_NUMBER:
-          return "invalid number";
-      case INTEGER_OVERFLOW:
-          return "integer overflow";
-      case FLOAT_OVERFLOW:
-          return "float overflow";
-      case TOKEN_TOO_LONG:
-          return "token too long";
-      case INVALID_EXPRESSION:
-          return "invalid expression";
-      case DIVISION_BY_ZERO:
-          return "division by zero";
-      case EOF_IN_COMMENT:
-          return "unexpected end of file found in comment";
-      case UNEXPECTED_TOKEN:
-          return "unexpected token";
-      case DIRECTIVE_INVALID_NAME:
-          return "invalid directive name";
-      case MACRO_NAME_RESERVED:
-          return "macro name is reserved";
-      case MACRO_REDEFINED:
-          return "macro redefined";
-      case MACRO_PREDEFINED_REDEFINED:
-          return "predefined macro redefined";
-      case MACRO_PREDEFINED_UNDEFINED:
-          return "predefined macro undefined";
-      case MACRO_UNTERMINATED_INVOCATION:
-          return "unterminated macro invocation";
-      case MACRO_TOO_FEW_ARGS:
-          return "Not enough arguments for macro";
-      case MACRO_TOO_MANY_ARGS:
-          return "Too many arguments for macro";
-      case CONDITIONAL_ENDIF_WITHOUT_IF:
-          return "unexpected #endif found without a matching #if";
-      case CONDITIONAL_ELSE_WITHOUT_IF:
-          return "unexpected #else found without a matching #if";
-      case CONDITIONAL_ELSE_AFTER_ELSE:
-          return "unexpected #else found after another #else";
-      case CONDITIONAL_ELIF_WITHOUT_IF:
-          return "unexpected #elif found without a matching #if";
-      case CONDITIONAL_ELIF_AFTER_ELSE:
-          return "unexpected #elif found after #else";
-      case CONDITIONAL_UNTERMINATED:
-          return "unexpected end of file found in conditional block";
-      case INVALID_EXTENSION_NAME:
-          return "invalid extension name";
-      case INVALID_EXTENSION_BEHAVIOR:
-          return "invalid extension behavior";
-      case INVALID_EXTENSION_DIRECTIVE:
-          return "invalid extension directive";
-      case INVALID_VERSION_NUMBER:
-          return "invalid version number";
-      case INVALID_VERSION_DIRECTIVE:
-          return "invalid version directive";
-      case VERSION_NOT_FIRST_STATEMENT:
-        return "#version directive must occur before anything else, "
-               "except for comments and white space";
-      case INVALID_LINE_NUMBER:
-          return "invalid line number";
-      case INVALID_FILE_NUMBER:
-          return "invalid file number";
-      case INVALID_LINE_DIRECTIVE:
-          return "invalid line directive";
-      // Errors end.
-      // Warnings begin.
-      case EOF_IN_DIRECTIVE:
-          return "unexpected end of file found in directive";
-      case CONDITIONAL_UNEXPECTED_TOKEN:
-          return "unexpected token after conditional expression";
-      case UNRECOGNIZED_PRAGMA:
-          return "unrecognized pragma";
-      // Warnings end.
-      default:
-          assert(false);
-          return "";
+        // Errors begin.
+        case PP_INTERNAL_ERROR:
+            return "internal error";
+        case PP_OUT_OF_MEMORY:
+            return "out of memory";
+        case PP_INVALID_CHARACTER:
+            return "invalid character";
+        case PP_INVALID_NUMBER:
+            return "invalid number";
+        case PP_INTEGER_OVERFLOW:
+            return "integer overflow";
+        case PP_FLOAT_OVERFLOW:
+            return "float overflow";
+        case PP_TOKEN_TOO_LONG:
+            return "token too long";
+        case PP_INVALID_EXPRESSION:
+            return "invalid expression";
+        case PP_DIVISION_BY_ZERO:
+            return "division by zero";
+        case PP_EOF_IN_COMMENT:
+            return "unexpected end of file found in comment";
+        case PP_UNEXPECTED_TOKEN:
+            return "unexpected token";
+        case PP_DIRECTIVE_INVALID_NAME:
+            return "invalid directive name";
+        case PP_MACRO_NAME_RESERVED:
+            return "macro name is reserved";
+        case PP_MACRO_REDEFINED:
+            return "macro redefined";
+        case PP_MACRO_PREDEFINED_REDEFINED:
+            return "predefined macro redefined";
+        case PP_MACRO_PREDEFINED_UNDEFINED:
+            return "predefined macro undefined";
+        case PP_MACRO_UNTERMINATED_INVOCATION:
+            return "unterminated macro invocation";
+        case PP_MACRO_UNDEFINED_WHILE_INVOKED:
+            return "macro undefined while being invoked";
+        case PP_MACRO_TOO_FEW_ARGS:
+            return "Not enough arguments for macro";
+        case PP_MACRO_TOO_MANY_ARGS:
+            return "Too many arguments for macro";
+        case PP_MACRO_DUPLICATE_PARAMETER_NAMES:
+            return "duplicate macro parameter name";
+        case PP_MACRO_INVOCATION_CHAIN_TOO_DEEP:
+            return "macro invocation chain too deep";
+        case PP_CONDITIONAL_ENDIF_WITHOUT_IF:
+            return "unexpected #endif found without a matching #if";
+        case PP_CONDITIONAL_ELSE_WITHOUT_IF:
+            return "unexpected #else found without a matching #if";
+        case PP_CONDITIONAL_ELSE_AFTER_ELSE:
+            return "unexpected #else found after another #else";
+        case PP_CONDITIONAL_ELIF_WITHOUT_IF:
+            return "unexpected #elif found without a matching #if";
+        case PP_CONDITIONAL_ELIF_AFTER_ELSE:
+            return "unexpected #elif found after #else";
+        case PP_CONDITIONAL_UNTERMINATED:
+            return "unexpected end of file found in conditional block";
+        case PP_INVALID_EXTENSION_NAME:
+            return "invalid extension name";
+        case PP_INVALID_EXTENSION_BEHAVIOR:
+            return "invalid extension behavior";
+        case PP_INVALID_EXTENSION_DIRECTIVE:
+            return "invalid extension directive";
+        case PP_INVALID_VERSION_NUMBER:
+            return "invalid version number";
+        case PP_INVALID_VERSION_DIRECTIVE:
+            return "invalid version directive";
+        case PP_VERSION_NOT_FIRST_STATEMENT:
+            return "#version directive must occur before anything else, "
+                   "except for comments and white space";
+        case PP_VERSION_NOT_FIRST_LINE_ESSL3:
+            return "#version directive must occur on the first line of the shader";
+        case PP_INVALID_LINE_NUMBER:
+            return "invalid line number";
+        case PP_INVALID_FILE_NUMBER:
+            return "invalid file number";
+        case PP_INVALID_LINE_DIRECTIVE:
+            return "invalid line directive";
+        case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3:
+            return "extension directive must occur before any non-preprocessor tokens in ESSL3";
+        case PP_UNDEFINED_SHIFT:
+            return "shift exponent is negative or undefined";
+        // Errors end.
+        // Warnings begin.
+        case PP_EOF_IN_DIRECTIVE:
+            return "unexpected end of file found in directive";
+        case PP_CONDITIONAL_UNEXPECTED_TOKEN:
+            return "unexpected token after conditional expression";
+        case PP_UNRECOGNIZED_PRAGMA:
+            return "unrecognized pragma";
+        case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1:
+            return "extension directive should occur before any non-preprocessor tokens";
+        case PP_WARNING_MACRO_NAME_RESERVED:
+            return "macro name with a double underscore is reserved - unintented behavior is "
+                   "possible";
+        // Warnings end.
+        default:
+            UNREACHABLE();
+            return "";
     }
 }
 
diff --git a/src/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.h b/src/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.h
index 07bc411..0c2da1b 100644
--- a/src/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.h
+++ b/src/third_party/angle/src/compiler/preprocessor/DiagnosticsBase.h
@@ -4,8 +4,8 @@
 // found in the LICENSE file.
 //
 
-#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
-#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
+#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
+#define COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
 
 #include <string>
 
@@ -19,69 +19,71 @@
 class Diagnostics
 {
   public:
-    enum Severity
-    {
-        ERROR,
-        WARNING
-    };
     enum ID
     {
-        ERROR_BEGIN,
-        INTERNAL_ERROR,
-        OUT_OF_MEMORY,
-        INVALID_CHARACTER,
-        INVALID_NUMBER,
-        INTEGER_OVERFLOW,
-        FLOAT_OVERFLOW,
-        TOKEN_TOO_LONG,
-        INVALID_EXPRESSION,
-        DIVISION_BY_ZERO,
-        EOF_IN_COMMENT,
-        UNEXPECTED_TOKEN,
-        DIRECTIVE_INVALID_NAME,
-        MACRO_NAME_RESERVED,
-        MACRO_REDEFINED,
-        MACRO_PREDEFINED_REDEFINED,
-        MACRO_PREDEFINED_UNDEFINED,
-        MACRO_UNTERMINATED_INVOCATION,
-        MACRO_TOO_FEW_ARGS,
-        MACRO_TOO_MANY_ARGS,
-        CONDITIONAL_ENDIF_WITHOUT_IF,
-        CONDITIONAL_ELSE_WITHOUT_IF,
-        CONDITIONAL_ELSE_AFTER_ELSE,
-        CONDITIONAL_ELIF_WITHOUT_IF,
-        CONDITIONAL_ELIF_AFTER_ELSE,
-        CONDITIONAL_UNTERMINATED,
-        INVALID_EXTENSION_NAME,
-        INVALID_EXTENSION_BEHAVIOR,
-        INVALID_EXTENSION_DIRECTIVE,
-        INVALID_VERSION_NUMBER,
-        INVALID_VERSION_DIRECTIVE,
-        VERSION_NOT_FIRST_STATEMENT,
-        INVALID_LINE_NUMBER,
-        INVALID_FILE_NUMBER,
-        INVALID_LINE_DIRECTIVE,
-        ERROR_END,
+        PP_ERROR_BEGIN,
+        PP_INTERNAL_ERROR,
+        PP_OUT_OF_MEMORY,
+        PP_INVALID_CHARACTER,
+        PP_INVALID_NUMBER,
+        PP_INTEGER_OVERFLOW,
+        PP_FLOAT_OVERFLOW,
+        PP_TOKEN_TOO_LONG,
+        PP_INVALID_EXPRESSION,
+        PP_DIVISION_BY_ZERO,
+        PP_EOF_IN_COMMENT,
+        PP_UNEXPECTED_TOKEN,
+        PP_DIRECTIVE_INVALID_NAME,
+        PP_MACRO_NAME_RESERVED,
+        PP_MACRO_REDEFINED,
+        PP_MACRO_PREDEFINED_REDEFINED,
+        PP_MACRO_PREDEFINED_UNDEFINED,
+        PP_MACRO_UNTERMINATED_INVOCATION,
+        PP_MACRO_UNDEFINED_WHILE_INVOKED,
+        PP_MACRO_TOO_FEW_ARGS,
+        PP_MACRO_TOO_MANY_ARGS,
+        PP_MACRO_DUPLICATE_PARAMETER_NAMES,
+        PP_MACRO_INVOCATION_CHAIN_TOO_DEEP,
+        PP_CONDITIONAL_ENDIF_WITHOUT_IF,
+        PP_CONDITIONAL_ELSE_WITHOUT_IF,
+        PP_CONDITIONAL_ELSE_AFTER_ELSE,
+        PP_CONDITIONAL_ELIF_WITHOUT_IF,
+        PP_CONDITIONAL_ELIF_AFTER_ELSE,
+        PP_CONDITIONAL_UNTERMINATED,
+        PP_CONDITIONAL_UNEXPECTED_TOKEN,
+        PP_INVALID_EXTENSION_NAME,
+        PP_INVALID_EXTENSION_BEHAVIOR,
+        PP_INVALID_EXTENSION_DIRECTIVE,
+        PP_INVALID_VERSION_NUMBER,
+        PP_INVALID_VERSION_DIRECTIVE,
+        PP_VERSION_NOT_FIRST_STATEMENT,
+        PP_VERSION_NOT_FIRST_LINE_ESSL3,
+        PP_INVALID_LINE_NUMBER,
+        PP_INVALID_FILE_NUMBER,
+        PP_INVALID_LINE_DIRECTIVE,
+        PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
+        PP_UNDEFINED_SHIFT,
+        PP_ERROR_END,
 
-        WARNING_BEGIN,
-        EOF_IN_DIRECTIVE,
-        CONDITIONAL_UNEXPECTED_TOKEN,
-        UNRECOGNIZED_PRAGMA,
-        WARNING_END
+        PP_WARNING_BEGIN,
+        PP_EOF_IN_DIRECTIVE,
+        PP_UNRECOGNIZED_PRAGMA,
+        PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1,
+        PP_WARNING_MACRO_NAME_RESERVED,
+        PP_WARNING_END
     };
 
     virtual ~Diagnostics();
 
-    void report(ID id, const SourceLocation& loc, const std::string& text);
+    void report(ID id, const SourceLocation &loc, const std::string &text);
 
   protected:
-    Severity severity(ID id);
-    std::string message(ID id);
+    bool isError(ID id);
+    const char *message(ID id);
 
-    virtual void print(ID id,
-                       const SourceLocation& loc,
-                       const std::string& text) = 0;
+    virtual void print(ID id, const SourceLocation &loc, const std::string &text) = 0;
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
+
+#endif  // COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp b/src/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp
index ef35c6e..049dae9 100644
--- a/src/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp
@@ -4,7 +4,7 @@
 // found in the LICENSE file.
 //
 
-#include "DirectiveHandlerBase.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
 
 namespace pp
 {
diff --git a/src/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
index 2aaeec2..6c81d01 100644
--- a/src/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
+++ b/src/third_party/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
@@ -4,8 +4,8 @@
 // found in the LICENSE file.
 //
 
-#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
-#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
+#ifndef COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
+#define COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
 
 #include <string>
 
@@ -23,21 +23,21 @@
   public:
     virtual ~DirectiveHandler();
 
-    virtual void handleError(const SourceLocation& loc,
-                             const std::string& msg) = 0;
+    virtual void handleError(const SourceLocation &loc, const std::string &msg) = 0;
 
     // Handle pragma of form: #pragma name[(value)]
-    virtual void handlePragma(const SourceLocation& loc,
-                              const std::string& name,
-                              const std::string& value) = 0;
+    virtual void handlePragma(const SourceLocation &loc,
+                              const std::string &name,
+                              const std::string &value,
+                              bool stdgl) = 0;
 
-    virtual void handleExtension(const SourceLocation& loc,
-                                 const std::string& name,
-                                 const std::string& behavior) = 0;
+    virtual void handleExtension(const SourceLocation &loc,
+                                 const std::string &name,
+                                 const std::string &behavior) = 0;
 
-    virtual void handleVersion(const SourceLocation& loc,
-                               int version) = 0;
+    virtual void handleVersion(const SourceLocation &loc, int version) = 0;
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
+
+#endif  // COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/third_party/angle/src/compiler/preprocessor/DirectiveParser.cpp
index 94dfdf5..9cda720 100644
--- a/src/third_party/angle/src/compiler/preprocessor/DirectiveParser.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/DirectiveParser.cpp
@@ -1,23 +1,25 @@
 //
-// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
-#include "DirectiveParser.h"
+#include "compiler/preprocessor/DirectiveParser.h"
 
-#include <cassert>
+#include <algorithm>
 #include <cstdlib>
 #include <sstream>
 
-#include "DiagnosticsBase.h"
-#include "DirectiveHandlerBase.h"
-#include "ExpressionParser.h"
-#include "MacroExpander.h"
-#include "Token.h"
-#include "Tokenizer.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
+#include "compiler/preprocessor/ExpressionParser.h"
+#include "compiler/preprocessor/MacroExpander.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/preprocessor/Tokenizer.h"
 
-namespace {
+namespace
+{
 enum DirectiveType
 {
     DIRECTIVE_NONE,
@@ -35,126 +37,120 @@
     DIRECTIVE_VERSION,
     DIRECTIVE_LINE
 };
-}  // namespace
 
-static DirectiveType getDirective(const pp::Token* token)
+DirectiveType getDirective(const pp::Token *token)
 {
-    static const std::string kDirectiveDefine("define");
-    static const std::string kDirectiveUndef("undef");
-    static const std::string kDirectiveIf("if");
-    static const std::string kDirectiveIfdef("ifdef");
-    static const std::string kDirectiveIfndef("ifndef");
-    static const std::string kDirectiveElse("else");
-    static const std::string kDirectiveElif("elif");
-    static const std::string kDirectiveEndif("endif");
-    static const std::string kDirectiveError("error");
-    static const std::string kDirectivePragma("pragma");
-    static const std::string kDirectiveExtension("extension");
-    static const std::string kDirectiveVersion("version");
-    static const std::string kDirectiveLine("line");
+    const char kDirectiveDefine[]    = "define";
+    const char kDirectiveUndef[]     = "undef";
+    const char kDirectiveIf[]        = "if";
+    const char kDirectiveIfdef[]     = "ifdef";
+    const char kDirectiveIfndef[]    = "ifndef";
+    const char kDirectiveElse[]      = "else";
+    const char kDirectiveElif[]      = "elif";
+    const char kDirectiveEndif[]     = "endif";
+    const char kDirectiveError[]     = "error";
+    const char kDirectivePragma[]    = "pragma";
+    const char kDirectiveExtension[] = "extension";
+    const char kDirectiveVersion[]   = "version";
+    const char kDirectiveLine[]      = "line";
 
     if (token->type != pp::Token::IDENTIFIER)
         return DIRECTIVE_NONE;
 
     if (token->text == kDirectiveDefine)
         return DIRECTIVE_DEFINE;
-    else if (token->text == kDirectiveUndef)
+    if (token->text == kDirectiveUndef)
         return DIRECTIVE_UNDEF;
-    else if (token->text == kDirectiveIf)
+    if (token->text == kDirectiveIf)
         return DIRECTIVE_IF;
-    else if (token->text == kDirectiveIfdef)
+    if (token->text == kDirectiveIfdef)
         return DIRECTIVE_IFDEF;
-    else if (token->text == kDirectiveIfndef)
+    if (token->text == kDirectiveIfndef)
         return DIRECTIVE_IFNDEF;
-    else if (token->text == kDirectiveElse)
+    if (token->text == kDirectiveElse)
         return DIRECTIVE_ELSE;
-    else if (token->text == kDirectiveElif)
+    if (token->text == kDirectiveElif)
         return DIRECTIVE_ELIF;
-    else if (token->text == kDirectiveEndif)
+    if (token->text == kDirectiveEndif)
         return DIRECTIVE_ENDIF;
-    else if (token->text == kDirectiveError)
+    if (token->text == kDirectiveError)
         return DIRECTIVE_ERROR;
-    else if (token->text == kDirectivePragma)
+    if (token->text == kDirectivePragma)
         return DIRECTIVE_PRAGMA;
-    else if (token->text == kDirectiveExtension)
+    if (token->text == kDirectiveExtension)
         return DIRECTIVE_EXTENSION;
-    else if (token->text == kDirectiveVersion)
+    if (token->text == kDirectiveVersion)
         return DIRECTIVE_VERSION;
-    else if (token->text == kDirectiveLine)
+    if (token->text == kDirectiveLine)
         return DIRECTIVE_LINE;
 
     return DIRECTIVE_NONE;
 }
 
-static bool isConditionalDirective(DirectiveType directive)
+bool isConditionalDirective(DirectiveType directive)
 {
     switch (directive)
     {
-      case DIRECTIVE_IF:
-      case DIRECTIVE_IFDEF:
-      case DIRECTIVE_IFNDEF:
-      case DIRECTIVE_ELSE:
-      case DIRECTIVE_ELIF:
-      case DIRECTIVE_ENDIF:
-        return true;
-      default:
-        return false;
+        case DIRECTIVE_IF:
+        case DIRECTIVE_IFDEF:
+        case DIRECTIVE_IFNDEF:
+        case DIRECTIVE_ELSE:
+        case DIRECTIVE_ELIF:
+        case DIRECTIVE_ENDIF:
+            return true;
+        default:
+            return false;
     }
 }
 
 // Returns true if the token represents End Of Directive.
-static bool isEOD(const pp::Token* token)
+bool isEOD(const pp::Token *token)
 {
     return (token->type == '\n') || (token->type == pp::Token::LAST);
 }
 
-static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token)
+void skipUntilEOD(pp::Lexer *lexer, pp::Token *token)
 {
-    while(!isEOD(token))
+    while (!isEOD(token))
     {
         lexer->lex(token);
     }
 }
 
-static bool isMacroNameReserved(const std::string& name)
+bool isMacroNameReserved(const std::string &name)
 {
-    // Names prefixed with "GL_" are reserved.
-    if (name.substr(0, 3) == "GL_")
-        return true;
-
-    // Names containing two consecutive underscores are reserved.
-    if (name.find("__") != std::string::npos)
-        return true;
-
-    return false;
+    // Names prefixed with "GL_" and the name "defined" are reserved.
+    return name == "defined" || (name.substr(0, 3) == "GL_");
 }
 
-static bool isMacroPredefined(const std::string& name,
-                              const pp::MacroSet& macroSet)
+bool hasDoubleUnderscores(const std::string &name)
+{
+    return (name.find("__") != std::string::npos);
+}
+
+bool isMacroPredefined(const std::string &name, const pp::MacroSet &macroSet)
 {
     pp::MacroSet::const_iterator iter = macroSet.find(name);
-    return iter != macroSet.end() ? iter->second.predefined : false;
+    return iter != macroSet.end() ? iter->second->predefined : false;
 }
 
+}  // namespace anonymous
+
 namespace pp
 {
 
 class DefinedParser : public Lexer
 {
   public:
-    DefinedParser(Lexer* lexer,
-                  const MacroSet* macroSet,
-                  Diagnostics* diagnostics) :
-        mLexer(lexer),
-        mMacroSet(macroSet),
-        mDiagnostics(diagnostics)
+    DefinedParser(Lexer *lexer, const MacroSet *macroSet, Diagnostics *diagnostics)
+        : mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics)
     {
     }
 
   protected:
-    virtual void lex(Token* token)
+    void lex(Token *token) override
     {
-        static const std::string kDefined("defined");
+        const char kDefined[] = "defined";
 
         mLexer->lex(token);
         if (token->type != Token::IDENTIFIER)
@@ -172,21 +168,20 @@
 
         if (token->type != Token::IDENTIFIER)
         {
-            mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                                 token->location, token->text);
+            mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
             skipUntilEOD(mLexer, token);
             return;
         }
         MacroSet::const_iterator iter = mMacroSet->find(token->text);
-        std::string expression = iter != mMacroSet->end() ? "1" : "0";
+        std::string expression        = iter != mMacroSet->end() ? "1" : "0";
 
         if (paren)
         {
             mLexer->lex(token);
             if (token->type != ')')
             {
-                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                                     token->location, token->text);
+                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+                                     token->text);
                 skipUntilEOD(mLexer, token);
                 return;
             }
@@ -199,24 +194,28 @@
     }
 
   private:
-    Lexer* mLexer;
-    const MacroSet* mMacroSet;
-    Diagnostics* mDiagnostics;
+    Lexer *mLexer;
+    const MacroSet *mMacroSet;
+    Diagnostics *mDiagnostics;
 };
 
-DirectiveParser::DirectiveParser(Tokenizer* tokenizer,
-                                 MacroSet* macroSet,
-                                 Diagnostics* diagnostics,
-                                 DirectiveHandler* directiveHandler) :
-    mPastFirstStatement(false),
-    mTokenizer(tokenizer),
-    mMacroSet(macroSet),
-    mDiagnostics(diagnostics),
-    mDirectiveHandler(directiveHandler)
+DirectiveParser::DirectiveParser(Tokenizer *tokenizer,
+                                 MacroSet *macroSet,
+                                 Diagnostics *diagnostics,
+                                 DirectiveHandler *directiveHandler,
+                                 int maxMacroExpansionDepth)
+    : mPastFirstStatement(false),
+      mSeenNonPreprocessorToken(false),
+      mTokenizer(tokenizer),
+      mMacroSet(macroSet),
+      mDiagnostics(diagnostics),
+      mDirectiveHandler(directiveHandler),
+      mShaderVersion(100),
+      mMaxMacroExpansionDepth(maxMacroExpansionDepth)
 {
 }
 
-void DirectiveParser::lex(Token* token)
+void DirectiveParser::lex(Token *token)
 {
     do
     {
@@ -227,14 +226,18 @@
             parseDirective(token);
             mPastFirstStatement = true;
         }
+        else if (!isEOD(token))
+        {
+            mSeenNonPreprocessorToken = true;
+        }
 
         if (token->type == Token::LAST)
         {
             if (!mConditionalStack.empty())
             {
-                const ConditionalBlock& block = mConditionalStack.back();
-                mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED,
-                                     block.location, block.type);
+                const ConditionalBlock &block = mConditionalStack.back();
+                mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED, block.location,
+                                     block.type);
             }
             break;
         }
@@ -244,9 +247,9 @@
     mPastFirstStatement = true;
 }
 
-void DirectiveParser::parseDirective(Token* token)
+void DirectiveParser::parseDirective(Token *token)
 {
-    assert(token->type == Token::PP_HASH);
+    ASSERT(token->type == Token::PP_HASH);
 
     mTokenizer->lex(token);
     if (isEOD(token))
@@ -265,112 +268,127 @@
         return;
     }
 
-    switch(directive)
+    switch (directive)
     {
-      case DIRECTIVE_NONE:
-        mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME,
-                             token->location, token->text);
-        skipUntilEOD(mTokenizer, token);
-        break;
-      case DIRECTIVE_DEFINE:
-        parseDefine(token);
-        break;
-      case DIRECTIVE_UNDEF:
-        parseUndef(token);
-        break;
-      case DIRECTIVE_IF:
-        parseIf(token);
-        break;
-      case DIRECTIVE_IFDEF:
-        parseIfdef(token);
-        break;
-      case DIRECTIVE_IFNDEF:
-        parseIfndef(token);
-        break;
-      case DIRECTIVE_ELSE:
-        parseElse(token);
-        break;
-      case DIRECTIVE_ELIF:
-        parseElif(token);
-        break;
-      case DIRECTIVE_ENDIF:
-        parseEndif(token);
-        break;
-      case DIRECTIVE_ERROR:
-        parseError(token);
-        break;
-      case DIRECTIVE_PRAGMA:
-        parsePragma(token);
-        break;
-      case DIRECTIVE_EXTENSION:
-        parseExtension(token);
-        break;
-      case DIRECTIVE_VERSION:
-        parseVersion(token);
-        break;
-      case DIRECTIVE_LINE:
-        parseLine(token);
-        break;
-      default:
-        assert(false);
-        break;
+        case DIRECTIVE_NONE:
+            mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME, token->location,
+                                 token->text);
+            skipUntilEOD(mTokenizer, token);
+            break;
+        case DIRECTIVE_DEFINE:
+            parseDefine(token);
+            break;
+        case DIRECTIVE_UNDEF:
+            parseUndef(token);
+            break;
+        case DIRECTIVE_IF:
+            parseIf(token);
+            break;
+        case DIRECTIVE_IFDEF:
+            parseIfdef(token);
+            break;
+        case DIRECTIVE_IFNDEF:
+            parseIfndef(token);
+            break;
+        case DIRECTIVE_ELSE:
+            parseElse(token);
+            break;
+        case DIRECTIVE_ELIF:
+            parseElif(token);
+            break;
+        case DIRECTIVE_ENDIF:
+            parseEndif(token);
+            break;
+        case DIRECTIVE_ERROR:
+            parseError(token);
+            break;
+        case DIRECTIVE_PRAGMA:
+            parsePragma(token);
+            break;
+        case DIRECTIVE_EXTENSION:
+            parseExtension(token);
+            break;
+        case DIRECTIVE_VERSION:
+            parseVersion(token);
+            break;
+        case DIRECTIVE_LINE:
+            parseLine(token);
+            break;
+        default:
+            UNREACHABLE();
+            break;
     }
 
     skipUntilEOD(mTokenizer, token);
     if (token->type == Token::LAST)
     {
-        mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE, token->location, token->text);
     }
 }
 
-void DirectiveParser::parseDefine(Token* token)
+void DirectiveParser::parseDefine(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_DEFINE);
+    ASSERT(getDirective(token) == DIRECTIVE_DEFINE);
 
     mTokenizer->lex(token);
     if (token->type != Token::IDENTIFIER)
     {
-        mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
         return;
     }
     if (isMacroPredefined(token->text, *mMacroSet))
     {
-        mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED, token->location,
+                             token->text);
         return;
     }
     if (isMacroNameReserved(token->text))
     {
-        mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED, token->location, token->text);
         return;
     }
+    // Using double underscores is allowed, but may result in unintended
+    // behavior, so a warning is issued. At the time of writing this was
+    // specified in ESSL 3.10, but the intent judging from Khronos
+    // discussions and dEQP tests was that double underscores should be
+    // allowed in earlier ESSL versions too.
+    if (hasDoubleUnderscores(token->text))
+    {
+        mDiagnostics->report(Diagnostics::PP_WARNING_MACRO_NAME_RESERVED, token->location,
+                             token->text);
+    }
 
-    Macro macro;
-    macro.type = Macro::kTypeObj;
-    macro.name = token->text;
+    std::shared_ptr<Macro> macro = std::make_shared<Macro>();
+    macro->type                  = Macro::kTypeObj;
+    macro->name                  = token->text;
 
     mTokenizer->lex(token);
     if (token->type == '(' && !token->hasLeadingSpace())
     {
         // Function-like macro. Collect arguments.
-        macro.type = Macro::kTypeFunc;
-        do {
+        macro->type = Macro::kTypeFunc;
+        do
+        {
             mTokenizer->lex(token);
             if (token->type != Token::IDENTIFIER)
                 break;
-            macro.parameters.push_back(token->text);
+
+            if (std::find(macro->parameters.begin(), macro->parameters.end(), token->text) !=
+                macro->parameters.end())
+            {
+                mDiagnostics->report(Diagnostics::PP_MACRO_DUPLICATE_PARAMETER_NAMES,
+                                     token->location, token->text);
+                return;
+            }
+
+            macro->parameters.push_back(token->text);
 
             mTokenizer->lex(token);  // Get ','.
         } while (token->type == ',');
 
         if (token->type != ')')
         {
-            mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                                 token->location,
-                                 token->text);
+            mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
             return;
         }
         mTokenizer->lex(token);  // Get ')'.
@@ -382,47 +400,51 @@
         // list. Resetting it also allows us to reuse Token::equals() to
         // compare macros.
         token->location = SourceLocation();
-        macro.replacements.push_back(*token);
+        macro->replacements.push_back(*token);
         mTokenizer->lex(token);
     }
-    if (!macro.replacements.empty())
+    if (!macro->replacements.empty())
     {
         // Whitespace preceding the replacement list is not considered part of
         // the replacement list for either form of macro.
-        macro.replacements.front().setHasLeadingSpace(false);
+        macro->replacements.front().setHasLeadingSpace(false);
     }
 
     // Check for macro redefinition.
-    MacroSet::const_iterator iter = mMacroSet->find(macro.name);
-    if (iter != mMacroSet->end() && !macro.equals(iter->second))
+    MacroSet::const_iterator iter = mMacroSet->find(macro->name);
+    if (iter != mMacroSet->end() && !macro->equals(*iter->second))
     {
-        mDiagnostics->report(Diagnostics::MACRO_REDEFINED,
-                             token->location,
-                             macro.name);
+        mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED, token->location, macro->name);
         return;
     }
-    mMacroSet->insert(std::make_pair(macro.name, macro));
+    mMacroSet->insert(std::make_pair(macro->name, macro));
 }
 
-void DirectiveParser::parseUndef(Token* token)
+void DirectiveParser::parseUndef(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_UNDEF);
+    ASSERT(getDirective(token) == DIRECTIVE_UNDEF);
 
     mTokenizer->lex(token);
     if (token->type != Token::IDENTIFIER)
     {
-        mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
         return;
     }
 
     MacroSet::iterator iter = mMacroSet->find(token->text);
     if (iter != mMacroSet->end())
     {
-        if (iter->second.predefined)
+        if (iter->second->predefined)
         {
-            mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED,
-                                 token->location, token->text);
+            mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED, token->location,
+                                 token->text);
+            return;
+        }
+        else if (iter->second->expansionCount > 0)
+        {
+            mDiagnostics->report(Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED, token->location,
+                                 token->text);
+            return;
         }
         else
         {
@@ -431,39 +453,44 @@
     }
 
     mTokenizer->lex(token);
+    if (!isEOD(token))
+    {
+        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+    }
 }
 
-void DirectiveParser::parseIf(Token* token)
+void DirectiveParser::parseIf(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_IF);
+    ASSERT(getDirective(token) == DIRECTIVE_IF);
     parseConditionalIf(token);
 }
 
-void DirectiveParser::parseIfdef(Token* token)
+void DirectiveParser::parseIfdef(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_IFDEF);
+    ASSERT(getDirective(token) == DIRECTIVE_IFDEF);
     parseConditionalIf(token);
 }
 
-void DirectiveParser::parseIfndef(Token* token)
+void DirectiveParser::parseIfndef(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_IFNDEF);
+    ASSERT(getDirective(token) == DIRECTIVE_IFNDEF);
     parseConditionalIf(token);
 }
 
-void DirectiveParser::parseElse(Token* token)
+void DirectiveParser::parseElse(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_ELSE);
+    ASSERT(getDirective(token) == DIRECTIVE_ELSE);
 
     if (mConditionalStack.empty())
     {
-        mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
         return;
     }
 
-    ConditionalBlock& block = mConditionalStack.back();
+    ConditionalBlock &block = mConditionalStack.back();
     if (block.skipBlock)
     {
         // No diagnostics. Just skip the whole line.
@@ -472,39 +499,39 @@
     }
     if (block.foundElseGroup)
     {
-        mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
         return;
     }
 
-    block.foundElseGroup = true;
-    block.skipGroup = block.foundValidGroup;
+    block.foundElseGroup  = true;
+    block.skipGroup       = block.foundValidGroup;
     block.foundValidGroup = true;
 
-    // Warn if there are extra tokens after #else.
+    // Check if there are extra tokens after #else.
     mTokenizer->lex(token);
     if (!isEOD(token))
     {
-        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
     }
 }
 
-void DirectiveParser::parseElif(Token* token)
+void DirectiveParser::parseElif(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_ELIF);
+    ASSERT(getDirective(token) == DIRECTIVE_ELIF);
 
     if (mConditionalStack.empty())
     {
-        mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
         return;
     }
 
-    ConditionalBlock& block = mConditionalStack.back();
+    ConditionalBlock &block = mConditionalStack.back();
     if (block.skipBlock)
     {
         // No diagnostics. Just skip the whole line.
@@ -513,8 +540,8 @@
     }
     if (block.foundElseGroup)
     {
-        mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
         return;
     }
@@ -527,38 +554,38 @@
         return;
     }
 
-    int expression = parseExpressionIf(token);
-    block.skipGroup = expression == 0;
+    int expression        = parseExpressionIf(token);
+    block.skipGroup       = expression == 0;
     block.foundValidGroup = expression != 0;
 }
 
-void DirectiveParser::parseEndif(Token* token)
+void DirectiveParser::parseEndif(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_ENDIF);
+    ASSERT(getDirective(token) == DIRECTIVE_ENDIF);
 
     if (mConditionalStack.empty())
     {
-        mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
         return;
     }
 
     mConditionalStack.pop_back();
 
-    // Warn if there are tokens after #endif.
+    // Check if there are tokens after #endif.
     mTokenizer->lex(token);
     if (!isEOD(token))
     {
-        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
     }
 }
 
-void DirectiveParser::parseError(Token* token)
+void DirectiveParser::parseError(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_ERROR);
+    ASSERT(getDirective(token) == DIRECTIVE_ERROR);
 
     std::ostringstream stream;
     mTokenizer->lex(token);
@@ -571,9 +598,9 @@
 }
 
 // Parses pragma of form: #pragma name[(value)].
-void DirectiveParser::parsePragma(Token* token)
+void DirectiveParser::parsePragma(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_PRAGMA);
+    ASSERT(getDirective(token) == DIRECTIVE_PRAGMA);
 
     enum State
     {
@@ -588,27 +615,32 @@
     int state = PRAGMA_NAME;
 
     mTokenizer->lex(token);
+    bool stdgl = token->text == "STDGL";
+    if (stdgl)
+    {
+        mTokenizer->lex(token);
+    }
     while ((token->type != '\n') && (token->type != Token::LAST))
     {
-        switch(state++)
+        switch (state++)
         {
-          case PRAGMA_NAME:
-            name = token->text;
-            valid = valid && (token->type == Token::IDENTIFIER);
-            break;
-          case LEFT_PAREN:
-            valid = valid && (token->type == '(');
-            break;
-          case PRAGMA_VALUE:
-            value = token->text;
-            valid = valid && (token->type == Token::IDENTIFIER);
-            break;
-          case RIGHT_PAREN:
-            valid = valid && (token->type == ')');
-            break;
-          default:
-            valid = false;
-            break;
+            case PRAGMA_NAME:
+                name  = token->text;
+                valid = valid && (token->type == Token::IDENTIFIER);
+                break;
+            case LEFT_PAREN:
+                valid = valid && (token->type == '(');
+                break;
+            case PRAGMA_VALUE:
+                value = token->text;
+                valid = valid && (token->type == Token::IDENTIFIER);
+                break;
+            case RIGHT_PAREN:
+                valid = valid && (token->type == ')');
+                break;
+            default:
+                valid = false;
+                break;
         }
         mTokenizer->lex(token);
     }
@@ -618,18 +650,17 @@
                       (state == RIGHT_PAREN + 1));  // With value.
     if (!valid)
     {
-        mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA,
-                             token->location, name);
+        mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA, token->location, name);
     }
     else if (state > PRAGMA_NAME)  // Do not notify for empty pragma.
     {
-        mDirectiveHandler->handlePragma(token->location, name, value);
+        mDirectiveHandler->handlePragma(token->location, name, value, stdgl);
     }
 }
 
-void DirectiveParser::parseExtension(Token* token)
+void DirectiveParser::parseExtension(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_EXTENSION);
+    ASSERT(getDirective(token) == DIRECTIVE_EXTENSION);
 
     enum State
     {
@@ -647,199 +678,231 @@
     {
         switch (state++)
         {
-          case EXT_NAME:
-            if (valid && (token->type != Token::IDENTIFIER))
-            {
-                mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME,
-                                     token->location, token->text);
-                valid = false;
-            }
-            if (valid) name = token->text;
-            break;
-          case COLON:
-            if (valid && (token->type != ':'))
-            {
-                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                                     token->location, token->text);
-                valid = false;
-            }
-            break;
-          case EXT_BEHAVIOR:
-            if (valid && (token->type != Token::IDENTIFIER))
-            {
-                mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR,
-                                     token->location, token->text);
-                valid = false;
-            }
-            if (valid) behavior = token->text;
-            break;
-          default:
-            if (valid)
-            {
-                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                                     token->location, token->text);
-                valid = false;
-            }
-            break;
+            case EXT_NAME:
+                if (valid && (token->type != Token::IDENTIFIER))
+                {
+                    mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME, token->location,
+                                         token->text);
+                    valid = false;
+                }
+                if (valid)
+                    name = token->text;
+                break;
+            case COLON:
+                if (valid && (token->type != ':'))
+                {
+                    mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+                                         token->text);
+                    valid = false;
+                }
+                break;
+            case EXT_BEHAVIOR:
+                if (valid && (token->type != Token::IDENTIFIER))
+                {
+                    mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR,
+                                         token->location, token->text);
+                    valid = false;
+                }
+                if (valid)
+                    behavior = token->text;
+                break;
+            default:
+                if (valid)
+                {
+                    mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+                                         token->text);
+                    valid = false;
+                }
+                break;
         }
         mTokenizer->lex(token);
     }
     if (valid && (state != EXT_BEHAVIOR + 1))
     {
-        mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE, token->location,
+                             token->text);
         valid = false;
     }
+    if (valid && mSeenNonPreprocessorToken)
+    {
+        if (mShaderVersion >= 300)
+        {
+            mDiagnostics->report(Diagnostics::PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
+                                 token->location, token->text);
+            valid = false;
+        }
+        else
+        {
+            mDiagnostics->report(Diagnostics::PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1,
+                                 token->location, token->text);
+        }
+    }
     if (valid)
         mDirectiveHandler->handleExtension(token->location, name, behavior);
 }
 
-void DirectiveParser::parseVersion(Token* token)
+void DirectiveParser::parseVersion(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_VERSION);
+    ASSERT(getDirective(token) == DIRECTIVE_VERSION);
 
     if (mPastFirstStatement)
     {
-        mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
         return;
     }
 
     enum State
     {
-        VERSION_NUMBER
+        VERSION_NUMBER,
+        VERSION_PROFILE,
+        VERSION_ENDLINE
     };
 
-    bool valid = true;
+    bool valid  = true;
     int version = 0;
-    int state = VERSION_NUMBER;
+    int state   = VERSION_NUMBER;
 
     mTokenizer->lex(token);
-    while ((token->type != '\n') && (token->type != Token::LAST))
+    while (valid && (token->type != '\n') && (token->type != Token::LAST))
     {
-        switch (state++)
+        switch (state)
         {
-          case VERSION_NUMBER:
-            if (valid && (token->type != Token::CONST_INT))
-            {
-                mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER,
-                                     token->location, token->text);
+            case VERSION_NUMBER:
+                if (token->type != Token::CONST_INT)
+                {
+                    mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER, token->location,
+                                         token->text);
+                    valid = false;
+                }
+                if (valid && !token->iValue(&version))
+                {
+                    mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW, token->location,
+                                         token->text);
+                    valid = false;
+                }
+                if (valid)
+                {
+                    state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
+                }
+                break;
+            case VERSION_PROFILE:
+                if (token->type != Token::IDENTIFIER || token->text != "es")
+                {
+                    mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location,
+                                         token->text);
+                    valid = false;
+                }
+                state = VERSION_ENDLINE;
+                break;
+            default:
+                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+                                     token->text);
                 valid = false;
-            }
-            if (valid && !token->iValue(&version))
-            {
-                mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
-                                     token->location, token->text);
-                valid = false;
-            }
-            break;
-          default:
-            if (valid)
-            {
-                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                                     token->location, token->text);
-                valid = false;
-            }
-            break;
+                break;
         }
+
         mTokenizer->lex(token);
     }
-    if (valid && (state != VERSION_NUMBER + 1))
+
+    if (valid && (state != VERSION_ENDLINE))
     {
-        mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location,
+                             token->text);
         valid = false;
     }
+
+    if (valid && version >= 300 && token->location.line > 1)
+    {
+        mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_LINE_ESSL3, token->location,
+                             token->text);
+        valid = false;
+    }
+
     if (valid)
+    {
         mDirectiveHandler->handleVersion(token->location, version);
+        mShaderVersion = version;
+        PredefineMacro(mMacroSet, "__VERSION__", version);
+    }
 }
 
-void DirectiveParser::parseLine(Token* token)
+void DirectiveParser::parseLine(Token *token)
 {
-    assert(getDirective(token) == DIRECTIVE_LINE);
+    ASSERT(getDirective(token) == DIRECTIVE_LINE);
 
-    enum State
-    {
-        LINE_NUMBER,
-        FILE_NUMBER
-    };
-
-    bool valid = true;
+    bool valid            = true;
+    bool parsedFileNumber = false;
     int line = 0, file = 0;
-    int state = LINE_NUMBER;
 
-    MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics);
+    MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, mMaxMacroExpansionDepth);
+
+    // Lex the first token after "#line" so we can check it for EOD.
     macroExpander.lex(token);
-    while ((token->type != '\n') && (token->type != Token::LAST))
-    {
-        switch (state++)
-        {
-          case LINE_NUMBER:
-            if (valid && (token->type != Token::CONST_INT))
-            {
-                mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER,
-                                     token->location, token->text);
-                valid = false;
-            }
-            if (valid && !token->iValue(&line))
-            {
-                mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
-                                     token->location, token->text);
-                valid = false;
-            }
-            break;
-          case FILE_NUMBER:
-            if (valid && (token->type != Token::CONST_INT))
-            {
-                mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER,
-                                     token->location, token->text);
-                valid = false;
-            }
-            if (valid && !token->iValue(&file))
-            {
-                mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
-                                     token->location, token->text);
-                valid = false;
-            }
-            break;
-          default:
-            if (valid)
-            {
-                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                                     token->location, token->text);
-                valid = false;
-            }
-            break;
-        }
-        macroExpander.lex(token);
-    }
 
-    if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))
+    if (isEOD(token))
     {
-        mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE, token->location, token->text);
         valid = false;
     }
+    else
+    {
+        ExpressionParser expressionParser(&macroExpander, mDiagnostics);
+        ExpressionParser::ErrorSettings errorSettings;
+
+        // See GLES3 section 12.42
+        errorSettings.integerLiteralsMustFit32BitSignedRange = true;
+
+        errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_LINE_NUMBER;
+        // The first token was lexed earlier to check if it was EOD. Include
+        // the token in parsing for a second time by setting the
+        // parsePresetToken flag to true.
+        expressionParser.parse(token, &line, true, errorSettings, &valid);
+        if (!isEOD(token) && valid)
+        {
+            errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_FILE_NUMBER;
+            // After parsing the line expression expressionParser has also
+            // advanced to the first token of the file expression - this is the
+            // token that makes the parser reduce the "input" rule for the line
+            // expression and stop. So we're using parsePresetToken = true here
+            // as well.
+            expressionParser.parse(token, &file, true, errorSettings, &valid);
+            parsedFileNumber = true;
+        }
+        if (!isEOD(token))
+        {
+            if (valid)
+            {
+                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+                                     token->text);
+                valid = false;
+            }
+            skipUntilEOD(mTokenizer, token);
+        }
+    }
+
     if (valid)
     {
         mTokenizer->setLineNumber(line);
-        if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file);
+        if (parsedFileNumber)
+            mTokenizer->setFileNumber(file);
     }
 }
 
 bool DirectiveParser::skipping() const
 {
-    if (mConditionalStack.empty()) return false;
+    if (mConditionalStack.empty())
+        return false;
 
-    const ConditionalBlock& block = mConditionalStack.back();
+    const ConditionalBlock &block = mConditionalStack.back();
     return block.skipBlock || block.skipGroup;
 }
 
-void DirectiveParser::parseConditionalIf(Token* token)
+void DirectiveParser::parseConditionalIf(Token *token)
 {
     ConditionalBlock block;
-    block.type = token->text;
+    block.type     = token->text;
     block.location = token->location;
 
     if (skipping())
@@ -858,72 +921,73 @@
         int expression = 0;
         switch (directive)
         {
-          case DIRECTIVE_IF:
-            expression = parseExpressionIf(token);
-            break;
-          case DIRECTIVE_IFDEF:
-            expression = parseExpressionIfdef(token);
-            break;
-          case DIRECTIVE_IFNDEF:
-            expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
-            break;
-          default:
-            assert(false);
-            break;
+            case DIRECTIVE_IF:
+                expression = parseExpressionIf(token);
+                break;
+            case DIRECTIVE_IFDEF:
+                expression = parseExpressionIfdef(token);
+                break;
+            case DIRECTIVE_IFNDEF:
+                expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
+                break;
+            default:
+                UNREACHABLE();
+                break;
         }
-        block.skipGroup = expression == 0;
+        block.skipGroup       = expression == 0;
         block.foundValidGroup = expression != 0;
     }
     mConditionalStack.push_back(block);
 }
 
-int DirectiveParser::parseExpressionIf(Token* token)
+int DirectiveParser::parseExpressionIf(Token *token)
 {
-    assert((getDirective(token) == DIRECTIVE_IF) ||
-           (getDirective(token) == DIRECTIVE_ELIF));
+    ASSERT((getDirective(token) == DIRECTIVE_IF) || (getDirective(token) == DIRECTIVE_ELIF));
 
     DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);
-    MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics);
+    MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics, mMaxMacroExpansionDepth);
     ExpressionParser expressionParser(&macroExpander, mDiagnostics);
 
     int expression = 0;
-    macroExpander.lex(token);
-    expressionParser.parse(token, &expression);
+    ExpressionParser::ErrorSettings errorSettings;
+    errorSettings.integerLiteralsMustFit32BitSignedRange = false;
+    errorSettings.unexpectedIdentifier = Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN;
 
-    // Warn if there are tokens after #if expression.
+    bool valid = true;
+    expressionParser.parse(token, &expression, false, errorSettings, &valid);
+
+    // Check if there are tokens after #if expression.
     if (!isEOD(token))
     {
-        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
     }
 
     return expression;
 }
 
-int DirectiveParser::parseExpressionIfdef(Token* token)
+int DirectiveParser::parseExpressionIfdef(Token *token)
 {
-    assert((getDirective(token) == DIRECTIVE_IFDEF) ||
-           (getDirective(token) == DIRECTIVE_IFNDEF));
+    ASSERT((getDirective(token) == DIRECTIVE_IFDEF) || (getDirective(token) == DIRECTIVE_IFNDEF));
 
     mTokenizer->lex(token);
     if (token->type != Token::IDENTIFIER)
     {
-        mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
         skipUntilEOD(mTokenizer, token);
         return 0;
     }
 
     MacroSet::const_iterator iter = mMacroSet->find(token->text);
-    int expression = iter != mMacroSet->end() ? 1 : 0;
+    int expression                = iter != mMacroSet->end() ? 1 : 0;
 
-    // Warn if there are tokens after #ifdef expression.
+    // Check if there are tokens after #ifdef expression.
     mTokenizer->lex(token);
     if (!isEOD(token))
     {
-        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
-                             token->location, token->text);
+        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+                             token->text);
         skipUntilEOD(mTokenizer, token);
     }
     return expression;
diff --git a/src/third_party/angle/src/compiler/preprocessor/DirectiveParser.h b/src/third_party/angle/src/compiler/preprocessor/DirectiveParser.h
index 8a7f007..4229cba 100644
--- a/src/third_party/angle/src/compiler/preprocessor/DirectiveParser.h
+++ b/src/third_party/angle/src/compiler/preprocessor/DirectiveParser.h
@@ -4,13 +4,12 @@
 // found in the LICENSE file.
 //
 
-#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
-#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
+#ifndef COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
+#define COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
 
-#include "Lexer.h"
-#include "Macro.h"
-#include "pp_utils.h"
-#include "SourceLocation.h"
+#include "compiler/preprocessor/Lexer.h"
+#include "compiler/preprocessor/Macro.h"
+#include "compiler/preprocessor/SourceLocation.h"
 
 namespace pp
 {
@@ -22,35 +21,34 @@
 class DirectiveParser : public Lexer
 {
   public:
-    DirectiveParser(Tokenizer* tokenizer,
-                    MacroSet* macroSet,
-                    Diagnostics* diagnostics,
-                    DirectiveHandler* directiveHandler);
+    DirectiveParser(Tokenizer *tokenizer,
+                    MacroSet *macroSet,
+                    Diagnostics *diagnostics,
+                    DirectiveHandler *directiveHandler,
+                    int maxMacroExpansionDepth);
 
-    virtual void lex(Token* token);
+    void lex(Token *token) override;
 
   private:
-    PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser);
-
-    void parseDirective(Token* token);
-    void parseDefine(Token* token);
-    void parseUndef(Token* token);
-    void parseIf(Token* token);
-    void parseIfdef(Token* token);
-    void parseIfndef(Token* token);
-    void parseElse(Token* token);
-    void parseElif(Token* token);
-    void parseEndif(Token* token);
-    void parseError(Token* token);
-    void parsePragma(Token* token);
-    void parseExtension(Token* token);
-    void parseVersion(Token* token);
-    void parseLine(Token* token);
+    void parseDirective(Token *token);
+    void parseDefine(Token *token);
+    void parseUndef(Token *token);
+    void parseIf(Token *token);
+    void parseIfdef(Token *token);
+    void parseIfndef(Token *token);
+    void parseElse(Token *token);
+    void parseElif(Token *token);
+    void parseEndif(Token *token);
+    void parseError(Token *token);
+    void parsePragma(Token *token);
+    void parseExtension(Token *token);
+    void parseVersion(Token *token);
+    void parseLine(Token *token);
 
     bool skipping() const;
-    void parseConditionalIf(Token* token);
-    int parseExpressionIf(Token* token);
-    int parseExpressionIfdef(Token* token);
+    void parseConditionalIf(Token *token);
+    int parseExpressionIf(Token *token);
+    int parseExpressionIfdef(Token *token);
 
     struct ConditionalBlock
     {
@@ -61,22 +59,24 @@
         bool foundValidGroup;
         bool foundElseGroup;
 
-        ConditionalBlock() :
-            skipBlock(false),
-            skipGroup(false),
-            foundValidGroup(false),
-            foundElseGroup(false)
+        ConditionalBlock()
+            : skipBlock(false), skipGroup(false), foundValidGroup(false), foundElseGroup(false)
         {
         }
     };
     bool mPastFirstStatement;
+    bool mSeenNonPreprocessorToken;  // Tracks if a non-preprocessor token has been seen yet.  Some
+                                     // macros, such as
+                                     // #extension must be declared before all shader code.
     std::vector<ConditionalBlock> mConditionalStack;
-    Tokenizer* mTokenizer;
-    MacroSet* mMacroSet;
-    Diagnostics* mDiagnostics;
-    DirectiveHandler* mDirectiveHandler;
+    Tokenizer *mTokenizer;
+    MacroSet *mMacroSet;
+    Diagnostics *mDiagnostics;
+    DirectiveHandler *mDirectiveHandler;
+    int mShaderVersion;
+    int mMaxMacroExpansionDepth;
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
 
+#endif  // COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.cpp b/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.cpp
index 67966e9..ee20a6f 100644
--- a/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.cpp
@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.7.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-   
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -26,7 +26,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -44,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.7"
+#define YYBISON_VERSION "3.0.4"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -63,11 +63,10 @@
 #define yyparse         ppparse
 #define yylex           pplex
 #define yyerror         pperror
-#define yylval          pplval
-#define yychar          ppchar
 #define yydebug         ppdebug
 #define yynerrs         ppnerrs
 
+
 /* Copy the first part of user declarations.  */
 
 
@@ -87,24 +86,29 @@
 #pragma GCC diagnostic ignored "-Wuninitialized"
 #endif
 #elif defined(_MSC_VER)
-#pragma warning(disable: 4065 4701)
+#pragma warning(disable: 4065 4244 4701 4702)
 #endif
 
 #include "ExpressionParser.h"
 
+#if defined(_MSC_VER)
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+
 #include <cassert>
 #include <sstream>
+#include <stdint.h>
 
 #include "DiagnosticsBase.h"
 #include "Lexer.h"
 #include "Token.h"
+#include "common/mathutil.h"
 
-#if defined(_MSC_VER)
-typedef __int64 YYSTYPE;
-#else
-#include <stdint.h>
-typedef intmax_t YYSTYPE;
-#endif  // _MSC_VER
+typedef int32_t YYSTYPE;
+typedef uint32_t UNSIGNED_TYPE;
+
 #define YYENABLE_NLS 0
 #define YYLTYPE_IS_TRIVIAL 1
 #define YYSTYPE_IS_TRIVIAL 1
@@ -117,6 +121,17 @@
     pp::Lexer* lexer;
     pp::Token* token;
     int* result;
+    bool parsePresetToken;
+
+    pp::ExpressionParser::ErrorSettings errorSettings;
+    bool *valid;
+
+    void startIgnoreErrors() { ++ignoreErrors; }
+    void endIgnoreErrors() { --ignoreErrors; }
+
+    bool isIgnoringErrors() { return ignoreErrors > 0; }
+
+    int ignoreErrors;
 };
 }  // namespace
 
@@ -126,11 +141,11 @@
 
 
 
-# ifndef YY_NULL
+# ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULL nullptr
+#   define YY_NULLPTR nullptr
 #  else
-#   define YY_NULL 0
+#   define YY_NULLPTR 0
 #  endif
 # endif
 
@@ -143,7 +158,7 @@
 #endif
 
 
-/* Enabling traces.  */
+/* Debug traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 0
 #endif
@@ -151,47 +166,35 @@
 extern int ppdebug;
 #endif
 
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     TOK_CONST_INT = 258,
-     TOK_OP_OR = 259,
-     TOK_OP_AND = 260,
-     TOK_OP_NE = 261,
-     TOK_OP_EQ = 262,
-     TOK_OP_GE = 263,
-     TOK_OP_LE = 264,
-     TOK_OP_RIGHT = 265,
-     TOK_OP_LEFT = 266,
-     TOK_UNARY = 267
-   };
+  enum yytokentype
+  {
+    TOK_CONST_INT = 258,
+    TOK_IDENTIFIER = 259,
+    TOK_OP_OR = 260,
+    TOK_OP_AND = 261,
+    TOK_OP_EQ = 262,
+    TOK_OP_NE = 263,
+    TOK_OP_LE = 264,
+    TOK_OP_GE = 265,
+    TOK_OP_LEFT = 266,
+    TOK_OP_RIGHT = 267,
+    TOK_UNARY = 268
+  };
 #endif
 
-
+/* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int ppparse (void *YYPARSE_PARAM);
-#else
-int ppparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
+
 int ppparse (Context *context);
-#else
-int ppparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
 
 
 
@@ -211,11 +214,8 @@
 
 #ifdef YYTYPE_INT8
 typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
 #else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
 #endif
 
 #ifdef YYTYPE_UINT16
@@ -235,8 +235,7 @@
 #  define YYSIZE_T __SIZE_TYPE__
 # elif defined size_t
 #  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
@@ -258,6 +257,33 @@
 # endif
 #endif
 
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
 # define YYUSE(E) ((void) (E))
@@ -265,23 +291,25 @@
 # define YYUSE(E) /* empty */
 #endif
 
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(N) (N)
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
 #else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
-#else
-static int
-YYID (yyi)
-    int yyi;
+# define YY_INITIAL_VALUE(Value) Value
 #endif
-{
-  return yyi;
-}
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
 #endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
 
 #if ! defined yyoverflow || YYERROR_VERBOSE
 
@@ -300,8 +328,7 @@
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
       /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
 #     ifndef EXIT_SUCCESS
@@ -313,8 +340,8 @@
 # endif
 
 # ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
     /* The OS might guarantee only one guard page at the bottom of the stack,
        and a page size can be as small as 4096 bytes.  So we cannot safely
@@ -330,7 +357,7 @@
 #  endif
 #  if (defined __cplusplus && ! defined EXIT_SUCCESS \
        && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
+             && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
 #   ifndef EXIT_SUCCESS
 #    define EXIT_SUCCESS 0
@@ -338,15 +365,13 @@
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined malloc && ! defined EXIT_SUCCESS
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined free && ! defined EXIT_SUCCESS
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
@@ -356,7 +381,7 @@
 
 #if (! defined yyoverflow \
      && (! defined __cplusplus \
-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
@@ -381,16 +406,16 @@
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
 
 #endif
 
@@ -409,48 +434,50 @@
           for (yyi = 0; yyi < (Count); yyi++)   \
             (Dst)[yyi] = (Src)[yyi];            \
         }                                       \
-      while (YYID (0))
+      while (0)
 #  endif
 # endif
 #endif /* !YYCOPY_NEEDED */
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  14
+#define YYFINAL  15
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   175
+#define YYLAST   176
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  27
+#define YYNTOKENS  28
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  3
+#define YYNNTS  5
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  26
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  52
+#define YYNRULES  29
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  55
 
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   267
+#define YYMAXUTOK   268
 
-#define YYTRANSLATE(YYX)						\
+#define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    23,     2,     2,     2,    21,     8,     2,
-      25,    26,    19,    17,     2,    18,     2,    20,     2,     2,
+       2,     2,     2,    24,     2,     2,     2,    22,     9,     2,
+      26,    27,    20,    18,     2,    19,     2,    21,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      11,     2,    12,     2,     2,     2,     2,     2,     2,     2,
+      12,     2,    13,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     7,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     8,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     6,     2,    24,     2,     2,     2,
+       2,     2,     2,     2,     7,     2,    25,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -464,40 +491,16 @@
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     9,    10,    13,    14,    15,    16,    22
+       5,     6,    10,    11,    14,    15,    16,    17,    23
 };
 
 #if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint8 yyprhs[] =
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
 {
-       0,     0,     3,     5,     7,    11,    15,    19,    23,    27,
-      31,    35,    39,    43,    47,    51,    55,    59,    63,    67,
-      71,    75,    79,    82,    85,    88,    91
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      28,     0,    -1,    29,    -1,     3,    -1,    29,     4,    29,
-      -1,    29,     5,    29,    -1,    29,     6,    29,    -1,    29,
-       7,    29,    -1,    29,     8,    29,    -1,    29,     9,    29,
-      -1,    29,    10,    29,    -1,    29,    13,    29,    -1,    29,
-      14,    29,    -1,    29,    12,    29,    -1,    29,    11,    29,
-      -1,    29,    15,    29,    -1,    29,    16,    29,    -1,    29,
-      18,    29,    -1,    29,    17,    29,    -1,    29,    21,    29,
-      -1,    29,    20,    29,    -1,    29,    19,    29,    -1,    23,
-      29,    -1,    24,    29,    -1,    18,    29,    -1,    17,    29,
-      -1,    25,    29,    26,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint8 yyrline[] =
-{
-       0,    91,    91,    98,    99,   102,   105,   108,   111,   114,
-     117,   120,   123,   126,   129,   132,   135,   138,   141,   144,
-     157,   170,   173,   176,   179,   182,   185
+       0,   108,   108,   115,   116,   127,   127,   148,   148,   169,
+     172,   175,   178,   181,   184,   187,   190,   193,   196,   221,
+     246,   249,   252,   278,   305,   308,   311,   314,   326,   329
 };
 #endif
 
@@ -506,169 +509,157 @@
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
-  "$end", "error", "$undefined", "TOK_CONST_INT", "TOK_OP_OR",
-  "TOK_OP_AND", "'|'", "'^'", "'&'", "TOK_OP_NE", "TOK_OP_EQ", "'<'",
-  "'>'", "TOK_OP_GE", "TOK_OP_LE", "TOK_OP_RIGHT", "TOK_OP_LEFT", "'+'",
-  "'-'", "'*'", "'/'", "'%'", "TOK_UNARY", "'!'", "'~'", "'('", "')'",
-  "$accept", "input", "expression", YY_NULL
+  "$end", "error", "$undefined", "TOK_CONST_INT", "TOK_IDENTIFIER",
+  "TOK_OP_OR", "TOK_OP_AND", "'|'", "'^'", "'&'", "TOK_OP_EQ", "TOK_OP_NE",
+  "'<'", "'>'", "TOK_OP_LE", "TOK_OP_GE", "TOK_OP_LEFT", "TOK_OP_RIGHT",
+  "'+'", "'-'", "'*'", "'/'", "'%'", "TOK_UNARY", "'!'", "'~'", "'('",
+  "')'", "$accept", "input", "expression", "$@1", "$@2", YY_NULLPTR
 };
 #endif
 
 # ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
 static const yytype_uint16 yytoknum[] =
 {
-       0,   256,   257,   258,   259,   260,   124,    94,    38,   261,
-     262,    60,    62,   263,   264,   265,   266,    43,    45,    42,
-      47,    37,   267,    33,   126,    40,    41
+       0,   256,   257,   258,   259,   260,   261,   124,    94,    38,
+     262,   263,    60,    62,   264,   265,   266,   267,    43,    45,
+      42,    47,    37,   268,    33,   126,    40,    41
 };
 # endif
 
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    27,    28,    29,    29,    29,    29,    29,    29,    29,
-      29,    29,    29,    29,    29,    29,    29,    29,    29,    29,
-      29,    29,    29,    29,    29,    29,    29
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     1,     1,     3,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
-       3,     3,     2,     2,     2,     2,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
-   Performed when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       0,     3,     0,     0,     0,     0,     0,     0,     2,    25,
-      24,    22,    23,     0,     1,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    26,     4,     5,     6,     7,     8,     9,
-      10,    14,    13,    11,    12,    15,    16,    18,    17,    21,
-      20,    19
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
-{
-      -1,     7,     8
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -11
-static const yytype_int16 yypact[] =
-{
-      46,   -11,    46,    46,    46,    46,    46,    12,    68,   -11,
-     -11,   -11,   -11,    27,   -11,    46,    46,    46,    46,    46,
-      46,    46,    46,    46,    46,    46,    46,    46,    46,    46,
-      46,    46,    46,   -11,    85,   101,   116,   130,   143,   154,
-     154,   -10,   -10,   -10,   -10,    37,    37,    31,    31,   -11,
-     -11,   -11
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] =
-{
-     -11,   -11,    -2
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
-static const yytype_uint8 yytable[] =
-{
-       9,    10,    11,    12,    13,    26,    27,    28,    29,    30,
-      31,    32,    14,    34,    35,    36,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    15,    16,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,     1,
-      30,    31,    32,    33,    28,    29,    30,    31,    32,     0,
-       0,     0,     0,     2,     3,     0,     0,     0,     0,     4,
-       5,     6,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,    31,    32
-};
+#define YYPACT_NINF -12
 
 #define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-11)))
+  (!!((Yystate) == (-12)))
+
+#define YYTABLE_NINF -1
 
 #define yytable_value_is_error(Yytable_value) \
-  YYID (0)
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int16 yypact[] =
+{
+      31,   -12,   -12,    31,    31,    31,    31,    31,    51,    76,
+     -12,   -12,   -12,   -12,    53,   -12,   -12,   -12,    31,    31,
+      31,    31,    31,    31,    31,    31,    31,    31,    31,    31,
+      31,    31,    31,    31,   -12,    31,    31,   124,   138,    26,
+     149,   149,   -11,   -11,   -11,   -11,   154,   154,    -8,    -8,
+     -12,   -12,   -12,    93,   109
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       0,     3,     4,     0,     0,     0,     0,     0,     0,     2,
+      28,    27,    25,    26,     0,     1,     5,     7,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    29,     0,     0,     9,    10,    11,
+      13,    12,    17,    16,    15,    14,    19,    18,    21,    20,
+      24,    23,    22,     6,     8
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -12,   -12,    -3,   -12,   -12
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     8,     9,    35,    36
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+      10,    11,    12,    13,    14,    27,    28,    29,    30,    31,
+      32,    33,    31,    32,    33,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,     0,    53,    54,     1,     2,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,     3,
+       4,    15,     0,     0,     0,     5,     6,     7,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,     0,     0,     0,     0,
+      34,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    33,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    29,    30,    31,    32,    33
+};
 
 static const yytype_int8 yycheck[] =
 {
-       2,     3,     4,     5,     6,    15,    16,    17,    18,    19,
-      20,    21,     0,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,     3,
-      19,    20,    21,    26,    17,    18,    19,    20,    21,    -1,
-      -1,    -1,    -1,    17,    18,    -1,    -1,    -1,    -1,    23,
-      24,    25,     4,     5,     6,     7,     8,     9,    10,    11,
+       3,     4,     5,     6,     7,    16,    17,    18,    19,    20,
+      21,    22,    20,    21,    22,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    -1,    35,    36,     3,     4,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    18,
+      19,     0,    -1,    -1,    -1,    24,    25,    26,     5,     6,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    -1,    -1,    -1,    -1,
+      27,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,     6,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,     7,     8,     9,    10,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,     9,    10,    11,
       12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,     6,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,     7,     8,     9,    10,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    11,    12,    13,    14,    15,
-      16,    17,    18,    19,    20,    21
+      22,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    18,    19,    20,    21,    22
 };
 
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    17,    18,    23,    24,    25,    28,    29,    29,
-      29,    29,    29,    29,     0,     4,     5,     6,     7,     8,
+       0,     3,     4,    18,    19,    24,    25,    26,    29,    30,
+      30,    30,    30,    30,    30,     0,     5,     6,     7,     8,
        9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    26,    29,    29,    29,    29,    29,    29,
-      29,    29,    29,    29,    29,    29,    29,    29,    29,    29,
-      29,    29
+      19,    20,    21,    22,    27,    31,    32,    30,    30,    30,
+      30,    30,    30,    30,    30,    30,    30,    30,    30,    30,
+      30,    30,    30,    30,    30
 };
 
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    28,    29,    30,    30,    31,    30,    32,    30,    30,
+      30,    30,    30,    30,    30,    30,    30,    30,    30,    30,
+      30,    30,    30,    30,    30,    30,    30,    30,    30,    30
+};
 
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     1,     1,     0,     4,     0,     4,     3,
+       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
+       3,     3,     3,     3,     3,     2,     2,     2,     2,     3
+};
 
 
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
 
-#define YYFAIL		goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -685,27 +676,15 @@
   else                                                          \
     {                                                           \
       yyerror (context, YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
 
 /* Error token number */
-#define YYTERROR	1
-#define YYERRCODE	256
+#define YYTERROR        1
+#define YYERRCODE       256
 
 
-/* This macro is provided for backward compatibility. */
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval, context)
-#endif
 
 /* Enable debugging if requested.  */
 #if YYDEBUG
@@ -715,58 +694,47 @@
 #  define YYFPRINTF fprintf
 # endif
 
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
 
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value, context); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, context); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
 static void
 yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, Context *context)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, context)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    Context *context;
-#endif
 {
   FILE *yyo = yyoutput;
   YYUSE (yyo);
+  YYUSE (context);
   if (!yyvaluep)
     return;
-  YYUSE (context);
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
 # endif
-  switch (yytype)
-    {
-      default:
-        break;
-    }
+  YYUSE (yytype);
 }
 
 
@@ -774,23 +742,11 @@
 | Print this symbol on YYOUTPUT.  |
 `--------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, Context *context)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, context)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    Context *context;
-#endif
 {
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
   yy_symbol_value_print (yyoutput, yytype, yyvaluep, context);
   YYFPRINTF (yyoutput, ")");
@@ -801,16 +757,8 @@
 | TOP (included).                                                   |
 `------------------------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
-#endif
 {
   YYFPRINTF (stderr, "Stack now");
   for (; yybottom <= yytop; yybottom++)
@@ -821,50 +769,42 @@
   YYFPRINTF (stderr, "\n");
 }
 
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
 
 
 /*------------------------------------------------.
 | Report that the YYRULE is going to be reduced.  |
 `------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule, Context *context)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule, context)
-    YYSTYPE *yyvsp;
-    int yyrule;
-    Context *context;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, Context *context)
 {
+  unsigned long int yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
-  unsigned long int yylno = yyrline[yyrule];
   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-	     yyrule - 1, yylno);
+             yyrule - 1, yylno);
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-		       &(yyvsp[(yyi + 1) - (yynrhs)])
-		       		       , context);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , context);
       YYFPRINTF (stderr, "\n");
     }
 }
 
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, Rule, context); \
-} while (YYID (0))
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, context); \
+} while (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
@@ -878,7 +818,7 @@
 
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
+#ifndef YYINITDEPTH
 # define YYINITDEPTH 200
 #endif
 
@@ -901,15 +841,8 @@
 #   define yystrlen strlen
 #  else
 /* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static YYSIZE_T
 yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
 {
   YYSIZE_T yylen;
   for (yylen = 0; yystr[yylen]; yylen++)
@@ -925,16 +858,8 @@
 #  else
 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
    YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static char *
 yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
 {
   char *yyd = yydest;
   const char *yys = yysrc;
@@ -964,27 +889,27 @@
       char const *yyp = yystr;
 
       for (;;)
-	switch (*++yyp)
-	  {
-	  case '\'':
-	  case ',':
-	    goto do_not_strip_quotes;
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
 
-	  case '\\':
-	    if (*++yyp != '\\')
-	      goto do_not_strip_quotes;
-	    /* Fall through.  */
-	  default:
-	    if (yyres)
-	      yyres[yyn] = *yyp;
-	    yyn++;
-	    break;
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
 
-	  case '"':
-	    if (yyres)
-	      yyres[yyn] = '\0';
-	    return yyn;
-	  }
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
     do_not_strip_quotes: ;
     }
 
@@ -1007,11 +932,11 @@
 yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                 yytype_int16 *yyssp, int yytoken)
 {
-  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
   enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
   /* Internationalized format string. */
-  const char *yyformat = YY_NULL;
+  const char *yyformat = YY_NULLPTR;
   /* Arguments of yyformat. */
   char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
   /* Number of reported tokens (one for the "unexpected", one per
@@ -1019,10 +944,6 @@
   int yycount = 0;
 
   /* There are many possibilities here to consider:
-     - Assume YYFAIL is not used.  It's too flawed to consider.  See
-       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
-       for details.  YYERROR is fine as it does not invoke this
-       function.
      - If this state is a consistent state with a default action, then
        the only way this function was invoked is if the default action
        is an error action.  In that case, don't check for expected
@@ -1072,7 +993,7 @@
                   }
                 yyarg[yycount++] = yytname[yyx];
                 {
-                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
                   if (! (yysize <= yysize1
                          && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
                     return 2;
@@ -1139,33 +1060,18 @@
 | Release the memory associated to this symbol.  |
 `-----------------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, Context *context)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, context)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-    Context *context;
-#endif
 {
   YYUSE (yyvaluep);
   YYUSE (context);
-
   if (!yymsg)
     yymsg = "Deleting";
   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
-  switch (yytype)
-    {
-
-      default:
-        break;
-    }
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 }
 
 
@@ -1175,56 +1081,18 @@
 | yyparse.  |
 `----------*/
 
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 int
 yyparse (Context *context)
-#else
-int
-yyparse (context)
-    Context *context;
-#endif
-#endif
 {
 /* The lookahead symbol.  */
 int yychar;
 
 
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
-/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
-    _Pragma ("GCC diagnostic push") \
-    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
-    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
-    _Pragma ("GCC diagnostic pop")
-#else
+/* The semantic value of the lookahead symbol.  */
 /* Default value used for initialization, for pacifying older GCCs
    or non-GCC compilers.  */
-static YYSTYPE yyval_default;
-# define YY_INITIAL_VALUE(Value) = Value
-#endif
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
-
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
 
     /* Number of syntax errors so far.  */
     int yynerrs;
@@ -1234,8 +1102,8 @@
     int yyerrstatus;
 
     /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
+       'yyss': related to states.
+       'yyvs': related to semantic values.
 
        Refer to the stacks through separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
@@ -1303,23 +1171,23 @@
 
 #ifdef yyoverflow
       {
-	/* Give user a chance to reallocate the stack.  Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	yytype_int16 *yyss1 = yyss;
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
 
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow (YY_("memory exhausted"),
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-		    &yystacksize);
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
 
-	yyss = yyss1;
-	yyvs = yyvs1;
+        yyss = yyss1;
+        yyvs = yyvs1;
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
@@ -1327,22 +1195,22 @@
 # else
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-	goto yyexhaustedlab;
+        goto yyexhaustedlab;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
+        yystacksize = YYMAXDEPTH;
 
       {
-	yytype_int16 *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss_alloc, yyss);
-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
       }
 # endif
 #endif /* no yyoverflow */
@@ -1351,10 +1219,10 @@
       yyvsp = yyvs + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
+                  (unsigned long int) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
+        YYABORT;
     }
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1383,7 +1251,7 @@
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
+      yychar = yylex (&yylval, context);
     }
 
   if (yychar <= YYEOF)
@@ -1448,7 +1316,7 @@
   yylen = yyr2[yyn];
 
   /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
+     '$$ = $1'.
 
      Otherwise, the following line sets YYVAL to garbage.
      This behavior is undocumented and Bison
@@ -1464,190 +1332,358 @@
         case 2:
 
     {
-        *(context->result) = static_cast<int>((yyvsp[(1) - (1)]));
+        *(context->result) = static_cast<int>((yyvsp[0]));
         YYACCEPT;
     }
+
     break;
 
   case 4:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) || (yyvsp[(3) - (3)]);
+        if (!context->isIgnoringErrors())
+        {
+            // This rule should be applied right after the token is lexed, so we can
+            // refer to context->token in the error message.
+            context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
+                                         context->token->location, context->token->text);
+            *(context->valid) = false;
+        }
+        (yyval) = (yyvsp[0]);
     }
+
     break;
 
   case 5:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) && (yyvsp[(3) - (3)]);
+        if ((yyvsp[-1]) != 0)
+        {
+            // Ignore errors in the short-circuited part of the expression.
+            // ESSL3.00 section 3.4:
+            // If an operand is not evaluated, the presence of undefined identifiers
+            // in the operand will not cause an error.
+            // Unevaluated division by zero should not cause an error either.
+            context->startIgnoreErrors();
+        }
     }
+
     break;
 
   case 6:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) | (yyvsp[(3) - (3)]);
+        if ((yyvsp[-3]) != 0)
+        {
+            context->endIgnoreErrors();
+            (yyval) = static_cast<YYSTYPE>(1);
+        }
+        else
+        {
+            (yyval) = (yyvsp[-3]) || (yyvsp[0]);
+        }
     }
+
     break;
 
   case 7:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) ^ (yyvsp[(3) - (3)]);
+        if ((yyvsp[-1]) == 0)
+        {
+            // Ignore errors in the short-circuited part of the expression.
+            // ESSL3.00 section 3.4:
+            // If an operand is not evaluated, the presence of undefined identifiers
+            // in the operand will not cause an error.
+            // Unevaluated division by zero should not cause an error either.
+            context->startIgnoreErrors();
+        }
     }
+
     break;
 
   case 8:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) & (yyvsp[(3) - (3)]);
+        if ((yyvsp[-3]) == 0)
+        {
+            context->endIgnoreErrors();
+            (yyval) = static_cast<YYSTYPE>(0);
+        }
+        else
+        {
+            (yyval) = (yyvsp[-3]) && (yyvsp[0]);
+        }
     }
+
     break;
 
   case 9:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) != (yyvsp[(3) - (3)]);
+        (yyval) = (yyvsp[-2]) | (yyvsp[0]);
     }
+
     break;
 
   case 10:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) == (yyvsp[(3) - (3)]);
+        (yyval) = (yyvsp[-2]) ^ (yyvsp[0]);
     }
+
     break;
 
   case 11:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) >= (yyvsp[(3) - (3)]);
+        (yyval) = (yyvsp[-2]) & (yyvsp[0]);
     }
+
     break;
 
   case 12:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) <= (yyvsp[(3) - (3)]);
+        (yyval) = (yyvsp[-2]) != (yyvsp[0]);
     }
+
     break;
 
   case 13:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) > (yyvsp[(3) - (3)]);
+        (yyval) = (yyvsp[-2]) == (yyvsp[0]);
     }
+
     break;
 
   case 14:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) < (yyvsp[(3) - (3)]);
+        (yyval) = (yyvsp[-2]) >= (yyvsp[0]);
     }
+
     break;
 
   case 15:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) >> (yyvsp[(3) - (3)]);
+        (yyval) = (yyvsp[-2]) <= (yyvsp[0]);
     }
+
     break;
 
   case 16:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) << (yyvsp[(3) - (3)]);
+        (yyval) = (yyvsp[-2]) > (yyvsp[0]);
     }
+
     break;
 
   case 17:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) - (yyvsp[(3) - (3)]);
+        (yyval) = (yyvsp[-2]) < (yyvsp[0]);
     }
+
     break;
 
   case 18:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) + (yyvsp[(3) - (3)]);
+        if ((yyvsp[0]) < 0 || (yyvsp[0]) > 31)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << (yyvsp[-2]) << " >> " << (yyvsp[0]);
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            (yyval) = static_cast<YYSTYPE>(0);
+        }
+        else if ((yyvsp[-2]) < 0)
+        {
+            // Logical shift right.
+            (yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) >> (yyvsp[0]));
+        }
+        else
+        {
+            (yyval) = (yyvsp[-2]) >> (yyvsp[0]);
+        }
     }
+
     break;
 
   case 19:
 
     {
-        if ((yyvsp[(3) - (3)]) == 0) {
-            std::ostringstream stream;
-            stream << (yyvsp[(1) - (3)]) << " % " << (yyvsp[(3) - (3)]);
-            std::string text = stream.str();
-            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
-                                         context->token->location,
-                                         text.c_str());
-            YYABORT;
-        } else {
-            (yyval) = (yyvsp[(1) - (3)]) % (yyvsp[(3) - (3)]);
+        if ((yyvsp[0]) < 0 || (yyvsp[0]) > 31)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << (yyvsp[-2]) << " << " << (yyvsp[0]);
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            (yyval) = static_cast<YYSTYPE>(0);
+        }
+        else if ((yyvsp[-2]) < 0)
+        {
+            // Logical shift left.
+            (yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) << (yyvsp[0]));
+        }
+        else
+        {
+            (yyval) = (yyvsp[-2]) << (yyvsp[0]);
         }
     }
+
     break;
 
   case 20:
 
     {
-        if ((yyvsp[(3) - (3)]) == 0) {
-            std::ostringstream stream;
-            stream << (yyvsp[(1) - (3)]) << " / " << (yyvsp[(3) - (3)]);
-            std::string text = stream.str();
-            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
-                                         context->token->location,
-                                         text.c_str());
-            YYABORT;
-        } else {
-            (yyval) = (yyvsp[(1) - (3)]) / (yyvsp[(3) - (3)]);
-        }
+        (yyval) = gl::WrappingDiff<YYSTYPE>((yyvsp[-2]), (yyvsp[0]));
     }
+
     break;
 
   case 21:
 
     {
-        (yyval) = (yyvsp[(1) - (3)]) * (yyvsp[(3) - (3)]);
+        (yyval) = gl::WrappingSum<YYSTYPE>((yyvsp[-2]), (yyvsp[0]));
     }
+
     break;
 
   case 22:
 
     {
-        (yyval) = ! (yyvsp[(2) - (2)]);
+        if ((yyvsp[0]) == 0)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << (yyvsp[-2]) << " % " << (yyvsp[0]);
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            (yyval) = static_cast<YYSTYPE>(0);
+        }
+        else if (((yyvsp[-2]) == std::numeric_limits<YYSTYPE>::min()) && ((yyvsp[0]) == -1))
+        {
+            // Check for the special case where the minimum representable number is
+            // divided by -1. If left alone this has undefined results.
+            (yyval) = 0;
+        }
+        else
+        {
+            (yyval) = (yyvsp[-2]) % (yyvsp[0]);
+        }
     }
+
     break;
 
   case 23:
 
     {
-        (yyval) = ~ (yyvsp[(2) - (2)]);
+        if ((yyvsp[0]) == 0)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << (yyvsp[-2]) << " / " << (yyvsp[0]);
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                                            context->token->location,
+                                            text.c_str());
+                *(context->valid) = false;
+            }
+            (yyval) = static_cast<YYSTYPE>(0);
+        }
+        else if (((yyvsp[-2]) == std::numeric_limits<YYSTYPE>::min()) && ((yyvsp[0]) == -1))
+        {
+            // Check for the special case where the minimum representable number is
+            // divided by -1. If left alone this leads to integer overflow in C++, which
+            // has undefined results.
+            (yyval) = std::numeric_limits<YYSTYPE>::max();
+        }
+        else
+        {
+            (yyval) = (yyvsp[-2]) / (yyvsp[0]);
+        }
     }
+
     break;
 
   case 24:
 
     {
-        (yyval) = - (yyvsp[(2) - (2)]);
+        (yyval) = gl::WrappingMul((yyvsp[-2]), (yyvsp[0]));
     }
+
     break;
 
   case 25:
 
     {
-        (yyval) = + (yyvsp[(2) - (2)]);
+        (yyval) = ! (yyvsp[0]);
     }
+
     break;
 
   case 26:
 
     {
-        (yyval) = (yyvsp[(2) - (3)]);
+        (yyval) = ~ (yyvsp[0]);
     }
+
+    break;
+
+  case 27:
+
+    {
+        // Check for negation of minimum representable integer to prevent undefined signed int
+        // overflow.
+        if ((yyvsp[0]) == std::numeric_limits<YYSTYPE>::min())
+        {
+            (yyval) = std::numeric_limits<YYSTYPE>::min();
+        }
+        else
+        {
+            (yyval) = -(yyvsp[0]);
+        }
+    }
+
+    break;
+
+  case 28:
+
+    {
+        (yyval) = + (yyvsp[0]);
+    }
+
+    break;
+
+  case 29:
+
+    {
+        (yyval) = (yyvsp[-1]);
+    }
+
     break;
 
 
@@ -1673,7 +1709,7 @@
 
   *++yyvsp = yyval;
 
-  /* Now `shift' the result of the reduction.  Determine what state
+  /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
 
@@ -1688,9 +1724,9 @@
   goto yynewstate;
 
 
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
 yyerrlab:
   /* Make sure we have latest lookahead translation.  See comments at
      user semantic actions for why this is necessary.  */
@@ -1741,20 +1777,20 @@
   if (yyerrstatus == 3)
     {
       /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
+         error, discard it.  */
 
       if (yychar <= YYEOF)
-	{
-	  /* Return failure if at end of input.  */
-	  if (yychar == YYEOF)
-	    YYABORT;
-	}
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
       else
-	{
-	  yydestruct ("Error: discarding",
-		      yytoken, &yylval, context);
-	  yychar = YYEMPTY;
-	}
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, context);
+          yychar = YYEMPTY;
+        }
     }
 
   /* Else will try to reuse lookahead token after shifting the error
@@ -1773,7 +1809,7 @@
   if (/*CONSTCOND*/ 0)
      goto yyerrorlab;
 
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
   yylen = 0;
@@ -1786,29 +1822,29 @@
 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
 `-------------------------------------------------------------*/
 yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
 
   for (;;)
     {
       yyn = yypact[yystate];
       if (!yypact_value_is_default (yyn))
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
 
       /* Pop the current state because it cannot handle the error token.  */
       if (yyssp == yyss)
-	YYABORT;
+        YYABORT;
 
 
       yydestruct ("Error: popping",
-		  yystos[yystate], yyvsp, context);
+                  yystos[yystate], yyvsp, context);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
@@ -1859,14 +1895,14 @@
       yydestruct ("Cleanup: discarding lookahead",
                   yytoken, &yylval, context);
     }
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
   YY_STACK_PRINT (yyss, yyssp);
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-		  yystos[*yyssp], yyvsp, context);
+                  yystos[*yyssp], yyvsp, context);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -1877,87 +1913,120 @@
   if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);
 #endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
+  return yyresult;
 }
 
 
 
-
-
-int yylex(YYSTYPE* lvalp, Context* context)
+int yylex(YYSTYPE *lvalp, Context *context)
 {
+    pp::Token *token = context->token;
+    if (!context->parsePresetToken)
+    {
+        context->lexer->lex(token);
+    }
+    context->parsePresetToken = false;
+
     int type = 0;
 
-    pp::Token* token = context->token;
     switch (token->type)
     {
-      case pp::Token::CONST_INT:
-      {
+      case pp::Token::CONST_INT: {
         unsigned int val = 0;
-        if (!token->uValue(&val))
+        int testVal = 0;
+        if (!token->uValue(&val) || (!token->iValue(&testVal) &&
+                                     context->errorSettings.integerLiteralsMustFit32BitSignedRange))
         {
-            context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW,
+            context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
                                          token->location, token->text);
+            *(context->valid) = false;
         }
         *lvalp = static_cast<YYSTYPE>(val);
         type = TOK_CONST_INT;
         break;
       }
-      case pp::Token::OP_OR: type = TOK_OP_OR; break;
-      case pp::Token::OP_AND: type = TOK_OP_AND; break;
-      case pp::Token::OP_NE: type = TOK_OP_NE; break;
-      case pp::Token::OP_EQ: type = TOK_OP_EQ; break;
-      case pp::Token::OP_GE: type = TOK_OP_GE; break;
-      case pp::Token::OP_LE: type = TOK_OP_LE; break;
-      case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break;
-      case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break;
-      case '|': type = '|'; break;
-      case '^': type = '^'; break;
-      case '&': type = '&'; break;
-      case '>': type = '>'; break;
-      case '<': type = '<'; break;
-      case '-': type = '-'; break;
-      case '+': type = '+'; break;
-      case '%': type = '%'; break;
-      case '/': type = '/'; break;
-      case '*': type = '*'; break;
-      case '!': type = '!'; break;
-      case '~': type = '~'; break;
-      case '(': type = '('; break;
-      case ')': type = ')'; break;
+      case pp::Token::IDENTIFIER:
+        *lvalp = static_cast<YYSTYPE>(-1);
+        type = TOK_IDENTIFIER;
+        break;
+      case pp::Token::OP_OR:
+        type = TOK_OP_OR;
+        break;
+      case pp::Token::OP_AND:
+        type = TOK_OP_AND;
+        break;
+      case pp::Token::OP_NE:
+        type = TOK_OP_NE;
+        break;
+      case pp::Token::OP_EQ:
+        type = TOK_OP_EQ;
+        break;
+      case pp::Token::OP_GE:
+        type = TOK_OP_GE;
+        break;
+      case pp::Token::OP_LE:
+        type = TOK_OP_LE;
+        break;
+      case pp::Token::OP_RIGHT:
+        type = TOK_OP_RIGHT;
+        break;
+      case pp::Token::OP_LEFT:
+        type = TOK_OP_LEFT;
+        break;
+      case '|':
+      case '^':
+      case '&':
+      case '>':
+      case '<':
+      case '-':
+      case '+':
+      case '%':
+      case '/':
+      case '*':
+      case '!':
+      case '~':
+      case '(':
+      case ')':
+        type = token->type;
+        break;
 
-      default: break;
+      default:
+        break;
     }
 
-    // Advance to the next token if the current one is valid.
-    if (type != 0) context->lexer->lex(token);
-
     return type;
 }
 
-void yyerror(Context* context, const char* reason)
+void yyerror(Context *context, const char *reason)
 {
-    context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION,
+    context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION,
                                  context->token->location,
                                  reason);
 }
 
 namespace pp {
 
-ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) :
-    mLexer(lexer),
-    mDiagnostics(diagnostics)
+ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
+    : mLexer(lexer),
+      mDiagnostics(diagnostics)
 {
 }
 
-bool ExpressionParser::parse(Token* token, int* result)
+bool ExpressionParser::parse(Token *token,
+                             int *result,
+                             bool parsePresetToken,
+                             const ErrorSettings &errorSettings,
+                             bool *valid)
 {
     Context context;
     context.diagnostics = mDiagnostics;
     context.lexer = mLexer;
     context.token = token;
     context.result = result;
+    context.ignoreErrors = 0;
+    context.parsePresetToken = parsePresetToken;
+    context.errorSettings    = errorSettings;
+    context.valid            = valid;
     int ret = yyparse(&context);
     switch (ret)
     {
@@ -1966,12 +2035,12 @@
         break;
 
       case 2:
-        mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, "");
+        mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, "");
         break;
 
       default:
         assert(false);
-        mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, "");
+        mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, "");
         break;
     }
 
diff --git a/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.h b/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.h
index 092d059..0f2901b 100644
--- a/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.h
+++ b/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.h
@@ -4,31 +4,40 @@
 // found in the LICENSE file.
 //
 
-#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
-#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
+#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
+#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
 
-#include "pp_utils.h"
+#include "common/angleutils.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
 
 namespace pp
 {
 
-class Diagnostics;
 class Lexer;
 struct Token;
 
-class ExpressionParser
+class ExpressionParser : angle::NonCopyable
 {
   public:
-    ExpressionParser(Lexer* lexer, Diagnostics* diagnostics);
+    struct ErrorSettings
+    {
+        Diagnostics::ID unexpectedIdentifier;
+        bool integerLiteralsMustFit32BitSignedRange;
+    };
 
-    bool parse(Token* token, int* result);
+    ExpressionParser(Lexer *lexer, Diagnostics *diagnostics);
+
+    bool parse(Token *token,
+               int *result,
+               bool parsePresetToken,
+               const ErrorSettings &errorSettings,
+               bool *valid);
 
   private:
-    PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);
-
-    Lexer* mLexer;
-    Diagnostics* mDiagnostics;
+    Lexer *mLexer;
+    Diagnostics *mDiagnostics;
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
+
+#endif  // COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.y b/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.y
index b6d3143..4dbc9e8 100644
--- a/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.y
+++ b/src/third_party/angle/src/compiler/preprocessor/ExpressionParser.y
@@ -28,24 +28,29 @@
 #pragma GCC diagnostic ignored "-Wuninitialized"
 #endif
 #elif defined(_MSC_VER)
-#pragma warning(disable: 4065 4701)
+#pragma warning(disable: 4065 4244 4701 4702)
 #endif
 
 #include "ExpressionParser.h"
 
+#if defined(_MSC_VER)
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+
 #include <cassert>
 #include <sstream>
+#include <stdint.h>
 
 #include "DiagnosticsBase.h"
 #include "Lexer.h"
 #include "Token.h"
+#include "common/mathutil.h"
 
-#if defined(_MSC_VER)
-typedef __int64 YYSTYPE;
-#else
-#include <stdint.h>
-typedef intmax_t YYSTYPE;
-#endif  // _MSC_VER
+typedef int32_t YYSTYPE;
+typedef uint32_t UNSIGNED_TYPE;
+
 #define YYENABLE_NLS 0
 #define YYLTYPE_IS_TRIVIAL 1
 #define YYSTYPE_IS_TRIVIAL 1
@@ -58,12 +63,23 @@
     pp::Lexer* lexer;
     pp::Token* token;
     int* result;
+    bool parsePresetToken;
+
+    pp::ExpressionParser::ErrorSettings errorSettings;
+    bool *valid;
+
+    void startIgnoreErrors() { ++ignoreErrors; }
+    void endIgnoreErrors() { --ignoreErrors; }
+
+    bool isIgnoringErrors() { return ignoreErrors > 0; }
+
+    int ignoreErrors;
 };
 }  // namespace
 %}
 
 %pure-parser
-%name-prefix="pp"
+%name-prefix "pp"
 %parse-param {Context *context}
 %lex-param {Context *context}
 
@@ -73,6 +89,7 @@
 %}
 
 %token TOK_CONST_INT
+%token TOK_IDENTIFIER
 %left TOK_OP_OR
 %left TOK_OP_AND
 %left '|'
@@ -96,11 +113,58 @@
 
 expression
     : TOK_CONST_INT
-    | expression TOK_OP_OR expression {
-        $$ = $1 || $3;
+    | TOK_IDENTIFIER {
+        if (!context->isIgnoringErrors())
+        {
+            // This rule should be applied right after the token is lexed, so we can
+            // refer to context->token in the error message.
+            context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
+                                         context->token->location, context->token->text);
+            *(context->valid) = false;
+        }
+        $$ = $1;
     }
-    | expression TOK_OP_AND expression {
-        $$ = $1 && $3;
+    | expression TOK_OP_OR {
+        if ($1 != 0)
+        {
+            // Ignore errors in the short-circuited part of the expression.
+            // ESSL3.00 section 3.4:
+            // If an operand is not evaluated, the presence of undefined identifiers
+            // in the operand will not cause an error.
+            // Unevaluated division by zero should not cause an error either.
+            context->startIgnoreErrors();
+        }
+    } expression {
+        if ($1 != 0)
+        {
+            context->endIgnoreErrors();
+            $$ = static_cast<YYSTYPE>(1);
+        }
+        else
+        {
+            $$ = $1 || $4;
+        }
+    }
+    | expression TOK_OP_AND {
+        if ($1 == 0)
+        {
+            // Ignore errors in the short-circuited part of the expression.
+            // ESSL3.00 section 3.4:
+            // If an operand is not evaluated, the presence of undefined identifiers
+            // in the operand will not cause an error.
+            // Unevaluated division by zero should not cause an error either.
+            context->startIgnoreErrors();
+        }
+    } expression {
+        if ($1 == 0)
+        {
+            context->endIgnoreErrors();
+            $$ = static_cast<YYSTYPE>(0);
+        }
+        else
+        {
+            $$ = $1 && $4;
+        }
     }
     | expression '|' expression {
         $$ = $1 | $3;
@@ -130,45 +194,116 @@
         $$ = $1 < $3;
     }
     | expression TOK_OP_RIGHT expression {
-        $$ = $1 >> $3;
+        if ($3 < 0 || $3 > 31)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << $1 << " >> " << $3;
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            $$ = static_cast<YYSTYPE>(0);
+        }
+        else if ($1 < 0)
+        {
+            // Logical shift right.
+            $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) >> $3);
+        }
+        else
+        {
+            $$ = $1 >> $3;
+        }
     }
     | expression TOK_OP_LEFT expression {
-        $$ = $1 << $3;
+        if ($3 < 0 || $3 > 31)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << $1 << " << " << $3;
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            $$ = static_cast<YYSTYPE>(0);
+        }
+        else if ($1 < 0)
+        {
+            // Logical shift left.
+            $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) << $3);
+        }
+        else
+        {
+            $$ = $1 << $3;
+        }
     }
     | expression '-' expression {
-        $$ = $1 - $3;
+        $$ = gl::WrappingDiff<YYSTYPE>($1, $3);
     }
     | expression '+' expression {
-        $$ = $1 + $3;
+        $$ = gl::WrappingSum<YYSTYPE>($1, $3);
     }
     | expression '%' expression {
-        if ($3 == 0) {
-            std::ostringstream stream;
-            stream << $1 << " % " << $3;
-            std::string text = stream.str();
-            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
-                                         context->token->location,
-                                         text.c_str());
-            YYABORT;
-        } else {
+        if ($3 == 0)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << $1 << " % " << $3;
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            $$ = static_cast<YYSTYPE>(0);
+        }
+        else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
+        {
+            // Check for the special case where the minimum representable number is
+            // divided by -1. If left alone this has undefined results.
+            $$ = 0;
+        }
+        else
+        {
             $$ = $1 % $3;
         }
     }
     | expression '/' expression {
-        if ($3 == 0) {
-            std::ostringstream stream;
-            stream << $1 << " / " << $3;
-            std::string text = stream.str();
-            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
-                                         context->token->location,
-                                         text.c_str());
-            YYABORT;
-        } else {
+        if ($3 == 0)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << $1 << " / " << $3;
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                                            context->token->location,
+                                            text.c_str());
+                *(context->valid) = false;
+            }
+            $$ = static_cast<YYSTYPE>(0);
+        }
+        else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
+        {
+            // Check for the special case where the minimum representable number is
+            // divided by -1. If left alone this leads to integer overflow in C++, which
+            // has undefined results.
+            $$ = std::numeric_limits<YYSTYPE>::max();
+        }
+        else
+        {
             $$ = $1 / $3;
         }
     }
     | expression '*' expression {
-        $$ = $1 * $3;
+        $$ = gl::WrappingMul($1, $3);
     }
     | '!' expression %prec TOK_UNARY {
         $$ = ! $2;
@@ -177,7 +312,16 @@
         $$ = ~ $2;
     }
     | '-' expression %prec TOK_UNARY {
-        $$ = - $2;
+        // Check for negation of minimum representable integer to prevent undefined signed int
+        // overflow.
+        if ($2 == std::numeric_limits<YYSTYPE>::min())
+        {
+            $$ = std::numeric_limits<YYSTYPE>::min();
+        }
+        else
+        {
+            $$ = -$2;
+        }
     }
     | '+' expression %prec TOK_UNARY {
         $$ = + $2;
@@ -189,79 +333,115 @@
 
 %%
 
-int yylex(YYSTYPE* lvalp, Context* context)
+int yylex(YYSTYPE *lvalp, Context *context)
 {
+    pp::Token *token = context->token;
+    if (!context->parsePresetToken)
+    {
+        context->lexer->lex(token);
+    }
+    context->parsePresetToken = false;
+
     int type = 0;
 
-    pp::Token* token = context->token;
     switch (token->type)
     {
-      case pp::Token::CONST_INT:
-      {
+      case pp::Token::CONST_INT: {
         unsigned int val = 0;
-        if (!token->uValue(&val))
+        int testVal = 0;
+        if (!token->uValue(&val) || (!token->iValue(&testVal) &&
+                                     context->errorSettings.integerLiteralsMustFit32BitSignedRange))
         {
-            context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW,
+            context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
                                          token->location, token->text);
+            *(context->valid) = false;
         }
         *lvalp = static_cast<YYSTYPE>(val);
         type = TOK_CONST_INT;
         break;
       }
-      case pp::Token::OP_OR: type = TOK_OP_OR; break;
-      case pp::Token::OP_AND: type = TOK_OP_AND; break;
-      case pp::Token::OP_NE: type = TOK_OP_NE; break;
-      case pp::Token::OP_EQ: type = TOK_OP_EQ; break;
-      case pp::Token::OP_GE: type = TOK_OP_GE; break;
-      case pp::Token::OP_LE: type = TOK_OP_LE; break;
-      case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break;
-      case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break;
-      case '|': type = '|'; break;
-      case '^': type = '^'; break;
-      case '&': type = '&'; break;
-      case '>': type = '>'; break;
-      case '<': type = '<'; break;
-      case '-': type = '-'; break;
-      case '+': type = '+'; break;
-      case '%': type = '%'; break;
-      case '/': type = '/'; break;
-      case '*': type = '*'; break;
-      case '!': type = '!'; break;
-      case '~': type = '~'; break;
-      case '(': type = '('; break;
-      case ')': type = ')'; break;
+      case pp::Token::IDENTIFIER:
+        *lvalp = static_cast<YYSTYPE>(-1);
+        type = TOK_IDENTIFIER;
+        break;
+      case pp::Token::OP_OR:
+        type = TOK_OP_OR;
+        break;
+      case pp::Token::OP_AND:
+        type = TOK_OP_AND;
+        break;
+      case pp::Token::OP_NE:
+        type = TOK_OP_NE;
+        break;
+      case pp::Token::OP_EQ:
+        type = TOK_OP_EQ;
+        break;
+      case pp::Token::OP_GE:
+        type = TOK_OP_GE;
+        break;
+      case pp::Token::OP_LE:
+        type = TOK_OP_LE;
+        break;
+      case pp::Token::OP_RIGHT:
+        type = TOK_OP_RIGHT;
+        break;
+      case pp::Token::OP_LEFT:
+        type = TOK_OP_LEFT;
+        break;
+      case '|':
+      case '^':
+      case '&':
+      case '>':
+      case '<':
+      case '-':
+      case '+':
+      case '%':
+      case '/':
+      case '*':
+      case '!':
+      case '~':
+      case '(':
+      case ')':
+        type = token->type;
+        break;
 
-      default: break;
+      default:
+        break;
     }
 
-    // Advance to the next token if the current one is valid.
-    if (type != 0) context->lexer->lex(token);
-
     return type;
 }
 
-void yyerror(Context* context, const char* reason)
+void yyerror(Context *context, const char *reason)
 {
-    context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION,
+    context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION,
                                  context->token->location,
                                  reason);
 }
 
 namespace pp {
 
-ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) :
-    mLexer(lexer),
-    mDiagnostics(diagnostics)
+ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
+    : mLexer(lexer),
+      mDiagnostics(diagnostics)
 {
 }
 
-bool ExpressionParser::parse(Token* token, int* result)
+bool ExpressionParser::parse(Token *token,
+                             int *result,
+                             bool parsePresetToken,
+                             const ErrorSettings &errorSettings,
+                             bool *valid)
 {
     Context context;
     context.diagnostics = mDiagnostics;
     context.lexer = mLexer;
     context.token = token;
     context.result = result;
+    context.ignoreErrors = 0;
+    context.parsePresetToken = parsePresetToken;
+    context.errorSettings    = errorSettings;
+    context.valid            = valid;
     int ret = yyparse(&context);
     switch (ret)
     {
@@ -270,12 +450,12 @@
         break;
 
       case 2:
-        mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, "");
+        mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, "");
         break;
 
       default:
         assert(false);
-        mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, "");
+        mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, "");
         break;
     }
 
diff --git a/src/third_party/angle/src/compiler/preprocessor/Input.cpp b/src/third_party/angle/src/compiler/preprocessor/Input.cpp
index b4d970a..e5bcd8e 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Input.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/Input.cpp
@@ -4,12 +4,13 @@
 // found in the LICENSE file.
 //
 
-#include "Input.h"
+#include "compiler/preprocessor/Input.h"
 
 #include <algorithm>
-#include <cassert>
 #include <cstring>
 
+#include "common/debug.h"
+
 namespace pp
 {
 
@@ -17,9 +18,8 @@
 {
 }
 
-Input::Input(size_t count, const char* const string[], const int length[]) :
-    mCount(count),
-    mString(string)
+Input::Input(size_t count, const char *const string[], const int length[])
+    : mCount(count), mString(string)
 {
     mLength.reserve(mCount);
     for (size_t i = 0; i < mCount; ++i)
@@ -29,13 +29,75 @@
     }
 }
 
-size_t Input::read(char* buf, size_t maxSize)
+const char *Input::skipChar()
+{
+    // This function should only be called when there is a character to skip.
+    ASSERT(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
+    ++mReadLoc.cIndex;
+    if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
+    {
+        ++mReadLoc.sIndex;
+        mReadLoc.cIndex = 0;
+    }
+    if (mReadLoc.sIndex >= mCount)
+    {
+        return nullptr;
+    }
+    return mString[mReadLoc.sIndex] + mReadLoc.cIndex;
+}
+
+size_t Input::read(char *buf, size_t maxSize, int *lineNo)
 {
     size_t nRead = 0;
-    while ((nRead < maxSize) && (mReadLoc.sIndex < mCount))
+    // The previous call to read might have stopped copying the string when encountering a line
+    // continuation. Check for this possibility first.
+    if (mReadLoc.sIndex < mCount && maxSize > 0)
+    {
+        const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex;
+        if ((*c) == '\\')
+        {
+            c = skipChar();
+            if (c != nullptr && (*c) == '\n')
+            {
+                // Line continuation of backslash + newline.
+                skipChar();
+                ++(*lineNo);
+            }
+            else if (c != nullptr && (*c) == '\r')
+            {
+                // Line continuation. Could be backslash + '\r\n' or just backslash + '\r'.
+                c = skipChar();
+                if (c != nullptr && (*c) == '\n')
+                {
+                    skipChar();
+                }
+                ++(*lineNo);
+            }
+            else
+            {
+                // Not line continuation, so write the skipped backslash to buf.
+                *buf = '\\';
+                ++nRead;
+            }
+        }
+    }
+
+    size_t maxRead = maxSize;
+    while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
     {
         size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
-        size = std::min(size, maxSize);
+        size        = std::min(size, maxSize);
+        for (size_t i = 0; i < size; ++i)
+        {
+            // Stop if a possible line continuation is encountered.
+            // It will be processed on the next call on input, which skips it
+            // and increments line number if necessary.
+            if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
+            {
+                size    = i;
+                maxRead = nRead + size;  // Stop reading right before the backslash.
+            }
+        }
         std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
         nRead += size;
         mReadLoc.cIndex += size;
@@ -51,4 +113,3 @@
 }
 
 }  // namespace pp
-
diff --git a/src/third_party/angle/src/compiler/preprocessor/Input.h b/src/third_party/angle/src/compiler/preprocessor/Input.h
index 14b7597..d5f3858 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Input.h
+++ b/src/third_party/angle/src/compiler/preprocessor/Input.h
@@ -7,7 +7,7 @@
 #ifndef COMPILER_PREPROCESSOR_INPUT_H_
 #define COMPILER_PREPROCESSOR_INPUT_H_
 
-#include <stddef.h>
+#include <cstddef>
 #include <vector>
 
 namespace pp
@@ -18,32 +18,36 @@
 {
   public:
     Input();
-    Input(size_t count, const char* const string[], const int length[]);
+    Input(size_t count, const char *const string[], const int length[]);
 
     size_t count() const { return mCount; }
-    const char* string(size_t index) const { return mString[index]; }
+    const char *string(size_t index) const { return mString[index]; }
     size_t length(size_t index) const { return mLength[index]; }
 
-    size_t read(char* buf, size_t maxSize);
+    size_t read(char *buf, size_t maxSize, int *lineNo);
 
     struct Location
     {
         size_t sIndex;  // String index;
         size_t cIndex;  // Char index.
 
-        Location() : sIndex(0), cIndex(0) { }
+        Location() : sIndex(0), cIndex(0) {}
     };
-    const Location& readLoc() const { return mReadLoc; }
+    const Location &readLoc() const { return mReadLoc; }
 
   private:
+    // Skip a character and return the next character after the one that was skipped.
+    // Return nullptr if data runs out.
+    const char *skipChar();
+
     // Input.
     size_t mCount;
-    const char* const* mString;
+    const char *const *mString;
     std::vector<size_t> mLength;
 
     Location mReadLoc;
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_INPUT_H_
 
+#endif  // COMPILER_PREPROCESSOR_INPUT_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/Lexer.cpp b/src/third_party/angle/src/compiler/preprocessor/Lexer.cpp
index 7c663ee..89cb3cf 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Lexer.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/Lexer.cpp
@@ -4,7 +4,7 @@
 // found in the LICENSE file.
 //
 
-#include "Lexer.h"
+#include "compiler/preprocessor/Lexer.h"
 
 namespace pp
 {
diff --git a/src/third_party/angle/src/compiler/preprocessor/Lexer.h b/src/third_party/angle/src/compiler/preprocessor/Lexer.h
index eb85cea..775bc0a 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Lexer.h
+++ b/src/third_party/angle/src/compiler/preprocessor/Lexer.h
@@ -7,19 +7,21 @@
 #ifndef COMPILER_PREPROCESSOR_LEXER_H_
 #define COMPILER_PREPROCESSOR_LEXER_H_
 
+#include "common/angleutils.h"
+
 namespace pp
 {
 
 struct Token;
 
-class Lexer
+class Lexer : angle::NonCopyable
 {
   public:
     virtual ~Lexer();
 
-    virtual void lex(Token* token) = 0;
+    virtual void lex(Token *token) = 0;
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_LEXER_H_
 
+#endif  // COMPILER_PREPROCESSOR_LEXER_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/Macro.cpp b/src/third_party/angle/src/compiler/preprocessor/Macro.cpp
index b2e3088..6162767 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Macro.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/Macro.cpp
@@ -4,20 +4,33 @@
 // found in the LICENSE file.
 //
 
-#include "Macro.h"
+#include "compiler/preprocessor/Macro.h"
 
-#include "Token.h"
+#include "common/angleutils.h"
+#include "compiler/preprocessor/Token.h"
 
 namespace pp
 {
 
-bool Macro::equals(const Macro& other) const
+bool Macro::equals(const Macro &other) const
 {
-    return (type == other.type) &&
-           (name == other.name) &&
-           (parameters == other.parameters) &&
+    return (type == other.type) && (name == other.name) && (parameters == other.parameters) &&
            (replacements == other.replacements);
 }
 
-}  // namespace pp
+void PredefineMacro(MacroSet *macroSet, const char *name, int value)
+{
+    Token token;
+    token.type = Token::CONST_INT;
+    token.text = ToString(value);
 
+    std::shared_ptr<Macro> macro = std::make_shared<Macro>();
+    macro->predefined            = true;
+    macro->type                  = Macro::kTypeObj;
+    macro->name                  = name;
+    macro->replacements.push_back(token);
+
+    (*macroSet)[name] = macro;
+}
+
+}  // namespace pp
diff --git a/src/third_party/angle/src/compiler/preprocessor/Macro.h b/src/third_party/angle/src/compiler/preprocessor/Macro.h
index 7ec0149..f835c42 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Macro.h
+++ b/src/third_party/angle/src/compiler/preprocessor/Macro.h
@@ -8,6 +8,7 @@
 #define COMPILER_PREPROCESSOR_MACRO_H_
 
 #include <map>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -26,11 +27,12 @@
     typedef std::vector<std::string> Parameters;
     typedef std::vector<Token> Replacements;
 
-    Macro() : predefined(false), disabled(false), type(kTypeObj) { }
-    bool equals(const Macro& other) const;
+    Macro() : predefined(false), disabled(false), expansionCount(0), type(kTypeObj) {}
+    bool equals(const Macro &other) const;
 
     bool predefined;
     mutable bool disabled;
+    mutable int expansionCount;
 
     Type type;
     std::string name;
@@ -38,7 +40,10 @@
     Replacements replacements;
 };
 
-typedef std::map<std::string, Macro> MacroSet;
+typedef std::map<std::string, std::shared_ptr<Macro>> MacroSet;
+
+void PredefineMacro(MacroSet *macroSet, const char *name, int value);
 
 }  // namespace pp
+
 #endif  // COMPILER_PREPROCESSOR_MACRO_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/third_party/angle/src/compiler/preprocessor/MacroExpander.cpp
index 1116c51..cc115f9 100644
--- a/src/third_party/angle/src/compiler/preprocessor/MacroExpander.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/MacroExpander.cpp
@@ -4,29 +4,34 @@
 // found in the LICENSE file.
 //
 
-#include "MacroExpander.h"
+#include "compiler/preprocessor/MacroExpander.h"
 
 #include <algorithm>
-#include <sstream>
 
-#include "DiagnosticsBase.h"
-#include "Token.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/Token.h"
 
 namespace pp
 {
 
+namespace
+{
+
+const size_t kMaxContextTokens = 10000;
+
 class TokenLexer : public Lexer
 {
- public:
+  public:
     typedef std::vector<Token> TokenVector;
 
-    TokenLexer(TokenVector* tokens)
+    TokenLexer(TokenVector *tokens)
     {
         tokens->swap(mTokens);
         mIter = mTokens.begin();
     }
 
-    virtual void lex(Token* token)
+    void lex(Token *token) override
     {
         if (mIter == mTokens.end())
         {
@@ -39,31 +44,65 @@
         }
     }
 
- private:
-    PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer);
-
+  private:
     TokenVector mTokens;
     TokenVector::const_iterator mIter;
 };
 
-MacroExpander::MacroExpander(Lexer* lexer,
-                             MacroSet* macroSet,
-                             Diagnostics* diagnostics) :
-    mLexer(lexer),
-    mMacroSet(macroSet),
-    mDiagnostics(diagnostics)
+}  // anonymous namespace
+
+class MacroExpander::ScopedMacroReenabler final : angle::NonCopyable
+{
+  public:
+    ScopedMacroReenabler(MacroExpander *expander);
+    ~ScopedMacroReenabler();
+
+  private:
+    MacroExpander *mExpander;
+};
+
+MacroExpander::ScopedMacroReenabler::ScopedMacroReenabler(MacroExpander *expander)
+    : mExpander(expander)
+{
+    mExpander->mDeferReenablingMacros = true;
+}
+
+MacroExpander::ScopedMacroReenabler::~ScopedMacroReenabler()
+{
+    mExpander->mDeferReenablingMacros = false;
+    for (auto macro : mExpander->mMacrosToReenable)
+    {
+        // Copying the string here by using substr is a check for use-after-free. It detects
+        // use-after-free more reliably than just toggling the disabled flag.
+        ASSERT(macro->name.substr() != "");
+        macro->disabled = false;
+    }
+    mExpander->mMacrosToReenable.clear();
+}
+
+MacroExpander::MacroExpander(Lexer *lexer,
+                             MacroSet *macroSet,
+                             Diagnostics *diagnostics,
+                             int allowedMacroExpansionDepth)
+    : mLexer(lexer),
+      mMacroSet(macroSet),
+      mDiagnostics(diagnostics),
+      mTotalTokensInContexts(0),
+      mAllowedMacroExpansionDepth(allowedMacroExpansionDepth),
+      mDeferReenablingMacros(false)
 {
 }
 
 MacroExpander::~MacroExpander()
 {
-    for (std::size_t i = 0; i < mContextStack.size(); ++i)
+    ASSERT(mMacrosToReenable.empty());
+    for (MacroContext *context : mContextStack)
     {
-        delete mContextStack[i];
+        delete context;
     }
 }
 
-void MacroExpander::lex(Token* token)
+void MacroExpander::lex(Token *token)
 {
     while (true)
     {
@@ -79,17 +118,22 @@
         if (iter == mMacroSet->end())
             break;
 
-        const Macro& macro = iter->second;
-        if (macro.disabled)
+        std::shared_ptr<Macro> macro = iter->second;
+        if (macro->disabled)
         {
             // If a particular token is not expanded, it is never expanded.
             token->setExpansionDisabled(true);
             break;
         }
-        if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen())
+
+        // Bump the expansion count before peeking if the next token is a '('
+        // otherwise there could be a #undef of the macro before the next token.
+        macro->expansionCount++;
+        if ((macro->type == Macro::kTypeFunc) && !isNextTokenLeftParen())
         {
             // If the token immediately after the macro name is not a '(',
             // this macro should not be expanded.
+            macro->expansionCount--;
             break;
         }
 
@@ -97,7 +141,7 @@
     }
 }
 
-void MacroExpander::getToken(Token* token)
+void MacroExpander::getToken(Token *token)
 {
     if (mReserveToken.get())
     {
@@ -118,21 +162,22 @@
     }
     else
     {
+        ASSERT(mTotalTokensInContexts == 0);
         mLexer->lex(token);
     }
 }
 
-void MacroExpander::ungetToken(const Token& token)
+void MacroExpander::ungetToken(const Token &token)
 {
     if (!mContextStack.empty())
     {
-        MacroContext* context = mContextStack.back();
+        MacroContext *context = mContextStack.back();
         context->unget();
-        assert(context->replacements[context->index] == token);
+        ASSERT(context->replacements[context->index] == token);
     }
     else
     {
-        assert(!mReserveToken.get());
+        ASSERT(!mReserveToken.get());
         mReserveToken.reset(new Token(token));
     }
 }
@@ -148,77 +193,89 @@
     return lparen;
 }
 
-bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier)
+bool MacroExpander::pushMacro(std::shared_ptr<Macro> macro, const Token &identifier)
 {
-    assert(!macro.disabled);
-    assert(!identifier.expansionDisabled());
-    assert(identifier.type == Token::IDENTIFIER);
-    assert(identifier.text == macro.name);
+    ASSERT(!macro->disabled);
+    ASSERT(!identifier.expansionDisabled());
+    ASSERT(identifier.type == Token::IDENTIFIER);
+    ASSERT(identifier.text == macro->name);
 
     std::vector<Token> replacements;
-    if (!expandMacro(macro, identifier, &replacements))
+    if (!expandMacro(*macro, identifier, &replacements))
         return false;
 
     // Macro is disabled for expansion until it is popped off the stack.
-    macro.disabled = true;
+    macro->disabled = true;
 
-    MacroContext* context = new MacroContext;
-    context->macro = &macro;
+    MacroContext *context = new MacroContext;
+    context->macro        = macro;
     context->replacements.swap(replacements);
     mContextStack.push_back(context);
+    mTotalTokensInContexts += context->replacements.size();
     return true;
 }
 
 void MacroExpander::popMacro()
 {
-    assert(!mContextStack.empty());
+    ASSERT(!mContextStack.empty());
 
-    MacroContext* context = mContextStack.back();
+    MacroContext *context = mContextStack.back();
     mContextStack.pop_back();
 
-    assert(context->empty());
-    assert(context->macro->disabled);
-    context->macro->disabled = false;
+    ASSERT(context->empty());
+    ASSERT(context->macro->disabled);
+    ASSERT(context->macro->expansionCount > 0);
+    if (mDeferReenablingMacros)
+    {
+        mMacrosToReenable.push_back(context->macro);
+    }
+    else
+    {
+        context->macro->disabled = false;
+    }
+    context->macro->expansionCount--;
+    mTotalTokensInContexts -= context->replacements.size();
     delete context;
 }
 
-bool MacroExpander::expandMacro(const Macro& macro,
-                                const Token& identifier,
-                                std::vector<Token>* replacements)
+bool MacroExpander::expandMacro(const Macro &macro,
+                                const Token &identifier,
+                                std::vector<Token> *replacements)
 {
     replacements->clear();
+
+    // In the case of an object-like macro, the replacement list gets its location
+    // from the identifier, but in the case of a function-like macro, the replacement
+    // list gets its location from the closing parenthesis of the macro invocation.
+    // This is tested by dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.*
+    SourceLocation replacementLocation = identifier.location;
     if (macro.type == Macro::kTypeObj)
     {
-        replacements->assign(macro.replacements.begin(),
-                             macro.replacements.end());
+        replacements->assign(macro.replacements.begin(), macro.replacements.end());
 
         if (macro.predefined)
         {
-            static const std::string kLine = "__LINE__";
-            static const std::string kFile = "__FILE__";
+            const char kLine[] = "__LINE__";
+            const char kFile[] = "__FILE__";
 
-            assert(replacements->size() == 1);
-            Token& repl = replacements->front();
+            ASSERT(replacements->size() == 1);
+            Token &repl = replacements->front();
             if (macro.name == kLine)
             {
-                std::ostringstream stream;
-                stream << identifier.location.line;
-                repl.text = stream.str();
+                repl.text = ToString(identifier.location.line);
             }
             else if (macro.name == kFile)
             {
-                std::ostringstream stream;
-                stream << identifier.location.file;
-                repl.text = stream.str();
+                repl.text = ToString(identifier.location.file);
             }
         }
     }
     else
     {
-        assert(macro.type == Macro::kTypeFunc);
+        ASSERT(macro.type == Macro::kTypeFunc);
         std::vector<MacroArg> args;
         args.reserve(macro.parameters.size());
-        if (!collectMacroArgs(macro, identifier, &args))
+        if (!collectMacroArgs(macro, identifier, &args, &replacementLocation))
             return false;
 
         replaceMacroParams(macro, args, replacements);
@@ -226,7 +283,7 @@
 
     for (std::size_t i = 0; i < replacements->size(); ++i)
     {
-        Token& repl = replacements->at(i);
+        Token &repl = replacements->at(i);
         if (i == 0)
         {
             // The first token in the replacement list inherits the padding
@@ -234,65 +291,76 @@
             repl.setAtStartOfLine(identifier.atStartOfLine());
             repl.setHasLeadingSpace(identifier.hasLeadingSpace());
         }
-        repl.location = identifier.location;
+        repl.location = replacementLocation;
     }
     return true;
 }
 
-bool MacroExpander::collectMacroArgs(const Macro& macro,
-                                     const Token& identifier,
-                                     std::vector<MacroArg>* args)
+bool MacroExpander::collectMacroArgs(const Macro &macro,
+                                     const Token &identifier,
+                                     std::vector<MacroArg> *args,
+                                     SourceLocation *closingParenthesisLocation)
 {
     Token token;
     getToken(&token);
-    assert(token.type == '(');
+    ASSERT(token.type == '(');
 
     args->push_back(MacroArg());
-    for (int openParens = 1; openParens != 0; )
+
+    // Defer reenabling macros until args collection is finished to avoid the possibility of
+    // infinite recursion. Otherwise infinite recursion might happen when expanding the args after
+    // macros have been popped from the context stack when parsing the args.
+    ScopedMacroReenabler deferReenablingMacros(this);
+
+    int openParens = 1;
+    while (openParens != 0)
     {
         getToken(&token);
 
         if (token.type == Token::LAST)
         {
-            mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION,
-                                 identifier.location, identifier.text);
+            mDiagnostics->report(Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION, identifier.location,
+                                 identifier.text);
             // Do not lose EOF token.
             ungetToken(token);
             return false;
         }
 
-        bool isArg = false; // True if token is part of the current argument.
+        bool isArg = false;  // True if token is part of the current argument.
         switch (token.type)
         {
-          case '(':
-            ++openParens;
-            isArg = true;
-            break;
-          case ')':
-            --openParens;
-            isArg = openParens != 0;
-            break;
-          case ',':
-            // The individual arguments are separated by comma tokens, but
-            // the comma tokens between matching inner parentheses do not
-            // seperate arguments.
-            if (openParens == 1) args->push_back(MacroArg());
-            isArg = openParens != 1;
-            break;
-          default:
-            isArg = true;
-            break;
+            case '(':
+                ++openParens;
+                isArg = true;
+                break;
+            case ')':
+                --openParens;
+                isArg                       = openParens != 0;
+                *closingParenthesisLocation = token.location;
+                break;
+            case ',':
+                // The individual arguments are separated by comma tokens, but
+                // the comma tokens between matching inner parentheses do not
+                // seperate arguments.
+                if (openParens == 1)
+                    args->push_back(MacroArg());
+                isArg = openParens != 1;
+                break;
+            default:
+                isArg = true;
+                break;
         }
         if (isArg)
         {
-            MacroArg& arg = args->back();
+            MacroArg &arg = args->back();
             // Initial whitespace is not part of the argument.
-            if (arg.empty()) token.setHasLeadingSpace(false);
+            if (arg.empty())
+                token.setHasLeadingSpace(false);
             arg.push_back(token);
         }
     }
 
-    const Macro::Parameters& params = macro.parameters;
+    const Macro::Parameters &params = macro.parameters;
     // If there is only one empty argument, it is equivalent to no argument.
     if (params.empty() && (args->size() == 1) && args->front().empty())
     {
@@ -301,9 +369,9 @@
     // Validate the number of arguments.
     if (args->size() != params.size())
     {
-        Diagnostics::ID id = args->size() < macro.parameters.size() ?
-            Diagnostics::MACRO_TOO_FEW_ARGS :
-            Diagnostics::MACRO_TOO_MANY_ARGS;
+        Diagnostics::ID id = args->size() < macro.parameters.size()
+                                 ? Diagnostics::PP_MACRO_TOO_FEW_ARGS
+                                 : Diagnostics::PP_MACRO_TOO_MANY_ARGS;
         mDiagnostics->report(id, identifier.location, identifier.text);
         return false;
     }
@@ -311,11 +379,17 @@
     // Pre-expand each argument before substitution.
     // This step expands each argument individually before they are
     // inserted into the macro body.
-    for (std::size_t i = 0; i < args->size(); ++i)
+    size_t numTokens = 0;
+    for (auto &arg : *args)
     {
-        MacroArg& arg = args->at(i);
         TokenLexer lexer(&arg);
-        MacroExpander expander(&lexer, mMacroSet, mDiagnostics);
+        if (mAllowedMacroExpansionDepth < 1)
+        {
+            mDiagnostics->report(Diagnostics::PP_MACRO_INVOCATION_CHAIN_TOO_DEEP, token.location,
+                                 token.text);
+            return false;
+        }
+        MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mAllowedMacroExpansionDepth - 1);
 
         arg.clear();
         expander.lex(&token);
@@ -323,18 +397,32 @@
         {
             arg.push_back(token);
             expander.lex(&token);
+            numTokens++;
+            if (numTokens + mTotalTokensInContexts > kMaxContextTokens)
+            {
+                mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
+                return false;
+            }
         }
     }
     return true;
 }
 
-void MacroExpander::replaceMacroParams(const Macro& macro,
-                                       const std::vector<MacroArg>& args,
-                                       std::vector<Token>* replacements)
+void MacroExpander::replaceMacroParams(const Macro &macro,
+                                       const std::vector<MacroArg> &args,
+                                       std::vector<Token> *replacements)
 {
     for (std::size_t i = 0; i < macro.replacements.size(); ++i)
     {
-        const Token& repl = macro.replacements[i];
+        if (!replacements->empty() &&
+            replacements->size() + mTotalTokensInContexts > kMaxContextTokens)
+        {
+            const Token &token = replacements->back();
+            mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
+            return;
+        }
+
+        const Token &repl = macro.replacements[i];
         if (repl.type != Token::IDENTIFIER)
         {
             replacements->push_back(repl);
@@ -344,16 +432,16 @@
         // TODO(alokp): Optimize this.
         // There is no need to search for macro params every time.
         // The param index can be cached with the replacement token.
-        Macro::Parameters::const_iterator iter = std::find(
-            macro.parameters.begin(), macro.parameters.end(), repl.text);
+        Macro::Parameters::const_iterator iter =
+            std::find(macro.parameters.begin(), macro.parameters.end(), repl.text);
         if (iter == macro.parameters.end())
         {
             replacements->push_back(repl);
             continue;
         }
 
-        std::size_t iArg = std::distance(macro.parameters.begin(), iter);
-        const MacroArg& arg = args[iArg];
+        std::size_t iArg    = std::distance(macro.parameters.begin(), iter);
+        const MacroArg &arg = args[iArg];
         if (arg.empty())
         {
             continue;
@@ -366,5 +454,24 @@
     }
 }
 
-}  // namespace pp
+MacroExpander::MacroContext::MacroContext() : macro(0), index(0)
+{
+}
 
+bool MacroExpander::MacroContext::empty() const
+{
+    return index == replacements.size();
+}
+
+const Token &MacroExpander::MacroContext::get()
+{
+    return replacements[index++];
+}
+
+void MacroExpander::MacroContext::unget()
+{
+    ASSERT(index > 0);
+    --index;
+}
+
+}  // namespace pp
diff --git a/src/third_party/angle/src/compiler/preprocessor/MacroExpander.h b/src/third_party/angle/src/compiler/preprocessor/MacroExpander.h
index 21b6757..7a4f5a9 100644
--- a/src/third_party/angle/src/compiler/preprocessor/MacroExpander.h
+++ b/src/third_party/angle/src/compiler/preprocessor/MacroExpander.h
@@ -4,72 +4,79 @@
 // found in the LICENSE file.
 //
 
-#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
-#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
+#ifndef COMPILER_PREPROCESSOR_MACROEXPANDER_H_
+#define COMPILER_PREPROCESSOR_MACROEXPANDER_H_
 
-#include <cassert>
 #include <memory>
 #include <vector>
 
-#include "Lexer.h"
-#include "Macro.h"
-#include "pp_utils.h"
+#include "compiler/preprocessor/Lexer.h"
+#include "compiler/preprocessor/Macro.h"
 
 namespace pp
 {
 
 class Diagnostics;
+struct SourceLocation;
 
 class MacroExpander : public Lexer
 {
   public:
-    MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics);
-    virtual ~MacroExpander();
+    MacroExpander(Lexer *lexer,
+                  MacroSet *macroSet,
+                  Diagnostics *diagnostics,
+                  int allowedMacroExpansionDepth);
+    ~MacroExpander() override;
 
-    virtual void lex(Token* token);
+    void lex(Token *token) override;
 
   private:
-    PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander);
-
-    void getToken(Token* token);
-    void ungetToken(const Token& token);
+    void getToken(Token *token);
+    void ungetToken(const Token &token);
     bool isNextTokenLeftParen();
 
-    bool pushMacro(const Macro& macro, const Token& identifier);
+    bool pushMacro(std::shared_ptr<Macro> macro, const Token &identifier);
     void popMacro();
 
-    bool expandMacro(const Macro& macro,
-                     const Token& identifier,
-                     std::vector<Token>* replacements);
+    bool expandMacro(const Macro &macro, const Token &identifier, std::vector<Token> *replacements);
 
     typedef std::vector<Token> MacroArg;
-    bool collectMacroArgs(const Macro& macro,
-                          const Token& identifier,
-                          std::vector<MacroArg>* args);
-    void replaceMacroParams(const Macro& macro,
-                            const std::vector<MacroArg>& args,
-                            std::vector<Token>* replacements);
+    bool collectMacroArgs(const Macro &macro,
+                          const Token &identifier,
+                          std::vector<MacroArg> *args,
+                          SourceLocation *closingParenthesisLocation);
+    void replaceMacroParams(const Macro &macro,
+                            const std::vector<MacroArg> &args,
+                            std::vector<Token> *replacements);
 
     struct MacroContext
     {
-        const Macro* macro;
+        MacroContext();
+        bool empty() const;
+        const Token &get();
+        void unget();
+
+        std::shared_ptr<Macro> macro;
         std::size_t index;
         std::vector<Token> replacements;
-
-        MacroContext() : macro(0), index(0) { }
-        bool empty() const { return index == replacements.size(); }
-        const Token& get() { return replacements[index++]; }
-        void unget() { assert(index > 0); --index; }
     };
 
-    Lexer* mLexer;
-    MacroSet* mMacroSet;
-    Diagnostics* mDiagnostics;
+    Lexer *mLexer;
+    MacroSet *mMacroSet;
+    Diagnostics *mDiagnostics;
 
-    std::auto_ptr<Token> mReserveToken;
-    std::vector<MacroContext*> mContextStack;
+    std::unique_ptr<Token> mReserveToken;
+    std::vector<MacroContext *> mContextStack;
+    size_t mTotalTokensInContexts;
+
+    int mAllowedMacroExpansionDepth;
+
+    bool mDeferReenablingMacros;
+    std::vector<std::shared_ptr<Macro>> mMacrosToReenable;
+
+    class ScopedMacroReenabler;
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
 
+#endif  // COMPILER_PREPROCESSOR_MACROEXPANDER_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/third_party/angle/src/compiler/preprocessor/Preprocessor.cpp
index 5ffc642..349c7b0 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Preprocessor.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/Preprocessor.cpp
@@ -4,43 +4,47 @@
 // found in the LICENSE file.
 //
 
-#include "Preprocessor.h"
+#include "compiler/preprocessor/Preprocessor.h"
 
-#include <cassert>
-#include <sstream>
-
-#include "DiagnosticsBase.h"
-#include "DirectiveParser.h"
-#include "Macro.h"
-#include "MacroExpander.h"
-#include "Token.h"
-#include "Tokenizer.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/DirectiveParser.h"
+#include "compiler/preprocessor/Macro.h"
+#include "compiler/preprocessor/MacroExpander.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/preprocessor/Tokenizer.h"
 
 namespace pp
 {
 
 struct PreprocessorImpl
 {
-    Diagnostics* diagnostics;
+    Diagnostics *diagnostics;
     MacroSet macroSet;
     Tokenizer tokenizer;
     DirectiveParser directiveParser;
     MacroExpander macroExpander;
 
-    PreprocessorImpl(Diagnostics* diag,
-                     DirectiveHandler* directiveHandler) :
-        diagnostics(diag),
-        tokenizer(diag),
-        directiveParser(&tokenizer, &macroSet, diag, directiveHandler),
-        macroExpander(&directiveParser, &macroSet, diag)
+    PreprocessorImpl(Diagnostics *diag,
+                     DirectiveHandler *directiveHandler,
+                     const PreprocessorSettings &settings)
+        : diagnostics(diag),
+          tokenizer(diag),
+          directiveParser(&tokenizer,
+                          &macroSet,
+                          diag,
+                          directiveHandler,
+                          settings.maxMacroExpansionDepth),
+          macroExpander(&directiveParser, &macroSet, diag, settings.maxMacroExpansionDepth)
     {
     }
 };
 
-Preprocessor::Preprocessor(Diagnostics* diagnostics,
-                           DirectiveHandler* directiveHandler)
+Preprocessor::Preprocessor(Diagnostics *diagnostics,
+                           DirectiveHandler *directiveHandler,
+                           const PreprocessorSettings &settings)
 {
-    mImpl = new PreprocessorImpl(diagnostics, directiveHandler);
+    mImpl = new PreprocessorImpl(diagnostics, directiveHandler, settings);
 }
 
 Preprocessor::~Preprocessor()
@@ -48,40 +52,25 @@
     delete mImpl;
 }
 
-bool Preprocessor::init(size_t count,
-                        const char* const string[],
-                        const int length[])
+bool Preprocessor::init(size_t count, const char *const string[], const int length[])
 {
-    static const int kGLSLVersion = 100;
+    static const int kDefaultGLSLVersion = 100;
 
     // Add standard pre-defined macros.
     predefineMacro("__LINE__", 0);
     predefineMacro("__FILE__", 0);
-    predefineMacro("__VERSION__", kGLSLVersion);
+    predefineMacro("__VERSION__", kDefaultGLSLVersion);
     predefineMacro("GL_ES", 1);
 
     return mImpl->tokenizer.init(count, string, length);
 }
 
-void Preprocessor::predefineMacro(const char* name, int value)
+void Preprocessor::predefineMacro(const char *name, int value)
 {
-    std::ostringstream stream;
-    stream << value;
-
-    Token token;
-    token.type = Token::CONST_INT;
-    token.text = stream.str();
-
-    Macro macro;
-    macro.predefined = true;
-    macro.type = Macro::kTypeObj;
-    macro.name = name;
-    macro.replacements.push_back(token);
-
-    mImpl->macroSet[name] = macro;
+    PredefineMacro(&mImpl->macroSet, name, value);
 }
 
-void Preprocessor::lex(Token* token)
+void Preprocessor::lex(Token *token)
 {
     bool validToken = false;
     while (!validToken)
@@ -89,54 +78,30 @@
         mImpl->macroExpander.lex(token);
         switch (token->type)
         {
-          // We should not be returning internal preprocessing tokens.
-          // Convert preprocessing tokens to compiler tokens or report
-          // diagnostics.
-          case Token::PP_HASH:
-            assert(false);
-            break;
-          case Token::CONST_INT:
-          {
-            int val = 0;
-            if (!token->iValue(&val))
-            {
-                // Do not mark the token as invalid.
-                // Just emit the diagnostic and reset value to 0.
-                mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
-                                           token->location, token->text);
-                token->text.assign("0");
-            }
-            validToken = true;
-            break;
-          }
-          case Token::CONST_FLOAT:
-          {
-            float val = 0;
-            if (!token->fValue(&val))
-            {
-                // Do not mark the token as invalid.
-                // Just emit the diagnostic and reset value to 0.0.
-                mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
-                                           token->location, token->text);
-                token->text.assign("0.0");
-            }
-            validToken = true;
-            break;
-          }
-          case Token::PP_NUMBER:
-            mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
-                                       token->location, token->text);
-            break;
-          case Token::PP_OTHER:
-            mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER,
-                                       token->location, token->text);
-            break;
-          default:
-            validToken = true;
-            break;
+            // We should not be returning internal preprocessing tokens.
+            // Convert preprocessing tokens to compiler tokens or report
+            // diagnostics.
+            case Token::PP_HASH:
+                UNREACHABLE();
+                break;
+            case Token::PP_NUMBER:
+                mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER, token->location,
+                                           token->text);
+                break;
+            case Token::PP_OTHER:
+                mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER, token->location,
+                                           token->text);
+                break;
+            default:
+                validToken = true;
+                break;
         }
     }
 }
 
-}  // namespace pp
+void Preprocessor::setMaxTokenSize(size_t maxTokenSize)
+{
+    mImpl->tokenizer.setMaxTokenSize(maxTokenSize);
+}
 
+}  // namespace pp
diff --git a/src/third_party/angle/src/compiler/preprocessor/Preprocessor.h b/src/third_party/angle/src/compiler/preprocessor/Preprocessor.h
index 7b70180..2fe504f 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Preprocessor.h
+++ b/src/third_party/angle/src/compiler/preprocessor/Preprocessor.h
@@ -7,9 +7,9 @@
 #ifndef COMPILER_PREPROCESSOR_PREPROCESSOR_H_
 #define COMPILER_PREPROCESSOR_PREPROCESSOR_H_
 
-#include <stddef.h>
+#include <cstddef>
 
-#include "pp_utils.h"
+#include "common/angleutils.h"
 
 namespace pp
 {
@@ -19,10 +19,18 @@
 struct PreprocessorImpl;
 struct Token;
 
-class Preprocessor
+struct PreprocessorSettings : private angle::NonCopyable
+{
+    PreprocessorSettings() : maxMacroExpansionDepth(1000) {}
+    int maxMacroExpansionDepth;
+};
+
+class Preprocessor : angle::NonCopyable
 {
   public:
-    Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler);
+    Preprocessor(Diagnostics *diagnostics,
+                 DirectiveHandler *directiveHandler,
+                 const PreprocessorSettings &settings);
     ~Preprocessor();
 
     // count: specifies the number of elements in the string and length arrays.
@@ -34,18 +42,19 @@
     // Each element in the length array may contain the length of the
     // corresponding string or a value less than 0 to indicate that the string
     // is null terminated.
-    bool init(size_t count, const char* const string[], const int length[]);
+    bool init(size_t count, const char *const string[], const int length[]);
     // Adds a pre-defined macro.
-    void predefineMacro(const char* name, int value);
+    void predefineMacro(const char *name, int value);
 
-    void lex(Token* token);
+    void lex(Token *token);
+
+    // Set maximum preprocessor token size
+    void setMaxTokenSize(size_t maxTokenSize);
 
   private:
-    PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor);
-
-    PreprocessorImpl* mImpl;
+    PreprocessorImpl *mImpl;
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_PREPROCESSOR_H_
 
+#endif  // COMPILER_PREPROCESSOR_PREPROCESSOR_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/SourceLocation.h b/src/third_party/angle/src/compiler/preprocessor/SourceLocation.h
index 6982613..51908a3 100644
--- a/src/third_party/angle/src/compiler/preprocessor/SourceLocation.h
+++ b/src/third_party/angle/src/compiler/preprocessor/SourceLocation.h
@@ -4,18 +4,18 @@
 // found in the LICENSE file.
 //
 
-#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
-#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
+#ifndef COMPILER_PREPROCESSOR_SOURCELOCATION_H_
+#define COMPILER_PREPROCESSOR_SOURCELOCATION_H_
 
 namespace pp
 {
 
 struct SourceLocation
 {
-    SourceLocation() : file(0), line(0) { }
-    SourceLocation(int f, int l) : file(f), line(l) { }
+    SourceLocation() : file(0), line(0) {}
+    SourceLocation(int f, int l) : file(f), line(l) {}
 
-    bool equals(const SourceLocation& other) const
+    bool equals(const SourceLocation &other) const
     {
         return (file == other.file) && (line == other.line);
     }
@@ -24,15 +24,16 @@
     int line;
 };
 
-inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs)
+inline bool operator==(const SourceLocation &lhs, const SourceLocation &rhs)
 {
     return lhs.equals(rhs);
 }
 
-inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs)
+inline bool operator!=(const SourceLocation &lhs, const SourceLocation &rhs)
 {
     return !lhs.equals(rhs);
 }
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
+
+#endif  // COMPILER_PREPROCESSOR_SOURCELOCATION_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/Token.cpp b/src/third_party/angle/src/compiler/preprocessor/Token.cpp
index 67f50aa..ce0ce94 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Token.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/Token.cpp
@@ -4,28 +4,25 @@
 // found in the LICENSE file.
 //
 
-#include "Token.h"
+#include "compiler/preprocessor/Token.h"
 
-#include <cassert>
-
-#include "numeric_lex.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/numeric_lex.h"
 
 namespace pp
 {
 
 void Token::reset()
 {
-    type = 0;
-    flags = 0;
+    type     = 0;
+    flags    = 0;
     location = SourceLocation();
     text.clear();
 }
 
-bool Token::equals(const Token& other) const
+bool Token::equals(const Token &other) const
 {
-    return (type == other.type) &&
-           (flags == other.flags) &&
-           (location == other.location) &&
+    return (type == other.type) && (flags == other.flags) && (location == other.location) &&
            (text == other.text);
 }
 
@@ -53,25 +50,25 @@
         flags &= ~EXPANSION_DISABLED;
 }
 
-bool Token::iValue(int* value) const
+bool Token::iValue(int *value) const
 {
-    assert(type == CONST_INT);
+    ASSERT(type == CONST_INT);
     return numeric_lex_int(text, value);
 }
 
-bool Token::uValue(unsigned int* value) const
+bool Token::uValue(unsigned int *value) const
 {
-    assert(type == CONST_INT);
+    ASSERT(type == CONST_INT);
     return numeric_lex_int(text, value);
 }
 
-bool Token::fValue(float* value) const
+bool Token::fValue(float *value) const
 {
-    assert(type == CONST_FLOAT);
+    ASSERT(type == CONST_FLOAT);
     return numeric_lex_float(text, value);
 }
 
-std::ostream& operator<<(std::ostream& out, const Token& token)
+std::ostream &operator<<(std::ostream &out, const Token &token)
 {
     if (token.hasLeadingSpace())
         out << " ";
diff --git a/src/third_party/angle/src/compiler/preprocessor/Token.h b/src/third_party/angle/src/compiler/preprocessor/Token.h
index 8b553ae..5e972ca 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Token.h
+++ b/src/third_party/angle/src/compiler/preprocessor/Token.h
@@ -10,7 +10,7 @@
 #include <ostream>
 #include <string>
 
-#include "SourceLocation.h"
+#include "compiler/preprocessor/SourceLocation.h"
 
 namespace pp
 {
@@ -62,10 +62,10 @@
         EXPANSION_DISABLED = 1 << 2
     };
 
-    Token() : type(0), flags(0) { }
+    Token() : type(0), flags(0) {}
 
     void reset();
-    bool equals(const Token& other) const;
+    bool equals(const Token &other) const;
 
     // Returns true if this is the first token on line.
     // It disregards any leading whitespace.
@@ -80,9 +80,9 @@
 
     // Converts text into numeric value for CONST_INT and CONST_FLOAT token.
     // Returns false if the parsed value cannot fit into an int or float.
-    bool iValue(int* value) const;
-    bool uValue(unsigned int* value) const;
-    bool fValue(float* value) const;
+    bool iValue(int *value) const;
+    bool uValue(unsigned int *value) const;
+    bool fValue(float *value) const;
 
     int type;
     unsigned int flags;
@@ -90,17 +90,18 @@
     std::string text;
 };
 
-inline bool operator==(const Token& lhs, const Token& rhs)
+inline bool operator==(const Token &lhs, const Token &rhs)
 {
     return lhs.equals(rhs);
 }
 
-inline bool operator!=(const Token& lhs, const Token& rhs)
+inline bool operator!=(const Token &lhs, const Token &rhs)
 {
     return !lhs.equals(rhs);
 }
 
-extern std::ostream& operator<<(std::ostream& out, const Token& token);
+std::ostream &operator<<(std::ostream &out, const Token &token);
 
 }  // namepsace pp
+
 #endif  // COMPILER_PREPROCESSOR_TOKEN_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/Tokenizer.cpp b/src/third_party/angle/src/compiler/preprocessor/Tokenizer.cpp
index 6f42678..40e910e 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Tokenizer.cpp
+++ b/src/third_party/angle/src/compiler/preprocessor/Tokenizer.cpp
@@ -1,6 +1,6 @@
 #line 16 "./Tokenizer.l"
 //
-// Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2011-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.
 //
@@ -9,20 +9,96 @@
 
 
 
-#line 13 "./Tokenizer.cpp"
-
 #define  YY_INT_ALIGNED short int
 
 /* A lexical scanner generated by flex */
 
+
+
+
+
+
+
+
+
+
+
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+        
+        
+    
+    
+
+
+    
+    
+
+
+
+    
+    
+
+
+
+    
+    
+    
+
+
+
+
+
+
 /* First, we deal with  platform-specific or compiler-specific issues. */
 
 /* begin standard C headers. */
@@ -56,7 +132,6 @@
 typedef uint16_t flex_uint16_t;
 typedef int32_t flex_int32_t;
 typedef uint32_t flex_uint32_t;
-typedef uint64_t flex_uint64_t;
 #else
 typedef signed char flex_int8_t;
 typedef short int flex_int16_t;
@@ -64,7 +139,6 @@
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -95,32 +169,31 @@
 #define UINT32_MAX             (4294967295U)
 #endif
 
+#endif /* ! C99 */
+
 #endif /* ! FLEXINT_H */
 
-#ifdef __cplusplus
 
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
 
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
 #define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
 #else
-#define yyconst
+#define yynoreturn
 #endif
 
+
+    
+
+
+
 /* Returned upon end-of-file. */
 #define YY_NULL 0
 
+
+
 /* Promotes a possibly negative, possibly signed char to an unsigned
  * integer for use as an array index.  If the signed char is negative,
  * we want to instead treat it as an 8-bit unsigned char, hence the
@@ -128,12 +201,34 @@
  */
 #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
 
+
+
+
+
 /* An opaque pointer. */
 #ifndef YY_TYPEDEF_YY_SCANNER_T
 #define YY_TYPEDEF_YY_SCANNER_T
 typedef void* yyscan_t;
 #endif
 
+
+
+
+
+
+
+
+
+    
+    
+
+
+
+
+
+
+
+
 /* For convenience, these vars (plus the bison vars far below)
    are macros in the reentrant scanner. */
 #define yyin yyg->yyin_r
@@ -145,12 +240,29 @@
 #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
 #define yy_flex_debug yyg->yy_flex_debug_r
 
+
+
+
+
+
+
+
+
+    
+    
+    
+    
+
+
+
 /* Enter a start condition.  This macro really ought to take a parameter,
  * but we do it the disgusting crufty way forced on us by the ()-less
  * definition of BEGIN.
  */
 #define BEGIN yyg->yy_start = 1 + 2 *
 
+
+
 /* Translate the current start state into a value that can be later handed
  * to BEGIN to return to the state.  The YYSTATE alias is for lex
  * compatibility.
@@ -158,23 +270,41 @@
 #define YY_START ((yyg->yy_start - 1) / 2)
 #define YYSTATE YY_START
 
+
+
 /* Action number for EOF rule of a given start state. */
 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
 
+
+
 /* Special action meaning "start processing a new file". */
 #define YY_NEW_FILE pprestart(yyin ,yyscanner )
 
+
+
 #define YY_END_OF_BUFFER_CHAR 0
 
+
 /* Size of default input buffer. */
 #ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
 #define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
 #endif
 
+
 /* The state buf must be large enough to hold one state per character in the main buffer.
  */
 #define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
 
+
+
 #ifndef YY_TYPEDEF_YY_BUFFER_STATE
 #define YY_TYPEDEF_YY_BUFFER_STATE
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
@@ -185,12 +315,22 @@
 typedef size_t yy_size_t;
 #endif
 
+
+
+
 #define EOB_ACT_CONTINUE_SCAN 0
 #define EOB_ACT_END_OF_FILE 1
 #define EOB_ACT_LAST_MATCH 2
 
-    #define YY_LESS_LINENO(n)
+
+
     
+    #define YY_LESS_LINENO(n)
+    #define YY_LINENO_REWIND_TO(ptr)
+    
+
+
+
 /* Return all but the first "n" matched characters back to the input stream. */
 #define yyless(n) \
 	do \
@@ -205,26 +345,31 @@
 		} \
 	while ( 0 )
 
+
+
 #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
 
+
 #ifndef YY_STRUCT_YY_BUFFER_STATE
 #define YY_STRUCT_YY_BUFFER_STATE
 struct yy_buffer_state
 	{
 	FILE *yy_input_file;
 
+
+
 	char *yy_ch_buf;		/* input buffer */
 	char *yy_buf_pos;		/* current position in input buffer */
 
 	/* Size of input buffer in bytes, not including room for EOB
 	 * characters.
 	 */
-	yy_size_t yy_buf_size;
+	int yy_buf_size;
 
 	/* Number of characters read into yy_ch_buf, not including EOB
 	 * characters.
 	 */
-	yy_size_t yy_n_chars;
+	int yy_n_chars;
 
 	/* Whether we "own" the buffer - i.e., we know we created it,
 	 * and can realloc() it to grow it, and should free() it to
@@ -248,6 +393,7 @@
     int yy_bs_lineno; /**< The line count. */
     int yy_bs_column; /**< The column count. */
     
+
 	/* Whether to try to fill the input buffer when we reach the
 	 * end of it.
 	 */
@@ -272,6 +418,10 @@
 	};
 #endif /* !YY_STRUCT_YY_BUFFER_STATE */
 
+
+
+
+
 /* We provide macros for accessing buffer states in case in the
  * future we want to put the buffer states in a more general
  * "scanner state".
@@ -282,11 +432,18 @@
                           ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
                           : NULL)
 
+
+
 /* Same as previous macro, but useful when we know that the buffer stack is not
  * NULL or when we need an lvalue. For internal use only.
  */
 #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
 
+
+
+
+
+
 void pprestart (FILE *input_file ,yyscan_t yyscanner );
 void pp_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
 YY_BUFFER_STATE pp_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
@@ -295,22 +452,30 @@
 void pppush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
 void pppop_buffer_state (yyscan_t yyscanner );
 
+
 static void ppensure_buffer_stack (yyscan_t yyscanner );
 static void pp_load_buffer_state (yyscan_t yyscanner );
 static void pp_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
 
+
+
 #define YY_FLUSH_BUFFER pp_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
 
+
 YY_BUFFER_STATE pp_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
 YY_BUFFER_STATE pp_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE pp_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
+YY_BUFFER_STATE pp_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
 
 void *ppalloc (yy_size_t ,yyscan_t yyscanner );
 void *pprealloc (void *,yy_size_t ,yyscan_t yyscanner );
 void ppfree (void * ,yyscan_t yyscanner );
 
+
 #define yy_new_buffer pp_create_buffer
 
+
+
 #define yy_set_interactive(is_interactive) \
 	{ \
 	if ( ! YY_CURRENT_BUFFER ){ \
@@ -321,6 +486,8 @@
 	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
 	}
 
+
+
 #define yy_set_bol(at_bol) \
 	{ \
 	if ( ! YY_CURRENT_BUFFER ){\
@@ -331,34 +498,50 @@
 	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
 	}
 
+
+
 #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
 
+
 /* Begin user sect3 */
 
-#define ppwrap(n) 1
+#define ppwrap(yyscanner) (/*CONSTCOND*/1)
 #define YY_SKIP_YYWRAP
 
 typedef unsigned char YY_CHAR;
 
+
+
+
 typedef int yy_state_type;
 
 #define yytext_ptr yytext_r
 
+
+
+
+
+
 static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
 static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
 static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
+
+
+
 
 /* Done after the current pattern has been matched and before the
  * corresponding action - sets up yytext.
  */
 #define YY_DO_BEFORE_ACTION \
 	yyg->yytext_ptr = yy_bp; \
-	yyleng = (yy_size_t) (yy_cp - yy_bp); \
+	yyleng = (int) (yy_cp - yy_bp); \
 	yyg->yy_hold_char = *yy_cp; \
 	*yy_cp = '\0'; \
 	yyg->yy_c_buf_p = yy_cp;
 
+
+
 #define YY_NUM_RULES 38
 #define YY_END_OF_BUFFER 39
 /* This struct is not used in this scanner,
@@ -368,20 +551,22 @@
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[87] =
+static yyconst flex_int16_t yy_accept[98] =
     {   0,
         0,    0,    0,    0,   39,   37,   34,   35,   35,   33,
         7,   33,   33,   33,   33,   33,   33,   33,   33,    9,
         9,   33,   33,   33,    8,   37,   33,   33,    3,    5,
         5,    4,   34,   35,   19,   27,   20,   30,   25,   12,
        23,   13,   24,   10,    2,    1,   26,   10,    9,   11,
-       11,   11,   11,    9,   14,   16,   18,   17,   15,    8,
-       36,   36,   31,   21,   32,   22,    3,    5,    6,   11,
-       10,   11,    1,   10,   11,    0,   10,    9,   28,   29,
-        0,   10,   10,   10,   10,    0
+       11,   11,    9,   11,    9,    9,   14,   16,   18,   17,
+       15,    8,   36,   36,   31,   21,   32,   22,    3,    5,
+        6,   11,   10,   11,   10,    1,   10,   11,   10,    0,
+       10,    9,    9,    9,   28,   29,    0,   10,   10,   10,
+       10,    9,   10,   10,    9,   10,    0
+
     } ;
 
-static yyconst flex_int32_t yy_ec[256] =
+static yyconst YY_CHAR yy_ec[256] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
         2,    2,    4,    1,    1,    1,    1,    1,    1,    1,
@@ -389,14 +574,14 @@
         1,    2,    5,    1,    6,    1,    7,    8,    1,    9,
         9,   10,   11,    9,   12,   13,   14,   15,   16,   16,
        16,   16,   16,   16,   16,   17,   17,    9,    9,   18,
-       19,   20,    9,    1,   21,   21,   21,   21,   22,   21,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   24,   23,   23,
-        9,   25,    9,   26,   23,    1,   21,   21,   21,   21,
+       19,   20,    9,    1,   21,   21,   21,   21,   22,   23,
+       24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
+       24,   24,   24,   24,   25,   24,   24,   26,   24,   24,
+        9,   27,    9,   28,   24,    1,   21,   21,   21,   21,
 
-       22,   21,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   24,
-       23,   23,    9,   27,    9,    9,    1,    1,    1,    1,
+       22,   23,   24,   24,   24,   24,   24,   24,   24,   24,
+       24,   24,   24,   24,   24,   24,   25,   24,   24,   26,
+       24,   24,    9,   29,    9,    9,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -413,89 +598,101 @@
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[28] =
+static yyconst YY_CHAR yy_meta[30] =
     {   0,
         1,    1,    2,    2,    1,    1,    1,    1,    1,    3,
         1,    1,    4,    1,    5,    5,    5,    1,    1,    1,
-        5,    5,    5,    5,    1,    1,    1
+        5,    5,    5,    5,    5,    5,    1,    1,    1
     } ;
 
-static yyconst flex_int16_t yy_base[92] =
+static yyconst flex_uint16_t yy_base[103] =
     {   0,
-        0,    0,   25,   27,  162,  163,  159,  163,  152,  132,
-      163,  131,   24,  163,  116,   22,   26,   31,   30,   37,
-       40,   44,  115,   46,    0,   64,   50,   15,    0,  163,
-      124,   91,   88,  163,  163,  163,  163,  163,  163,  163,
-      163,  163,  163,   64,  163,    0,  163,   76,   54,   58,
-       79,   91,   91,    0,   56,  163,  163,  163,   32,    0,
-      163,   36,  163,  163,  163,  163,    0,  163,  163,   94,
-        0,  106,    0,    0,  113,   55,   72,  113,  163,  163,
-      116,  101,  108,  123,  126,  163,  143,   31,  148,  153,
-      155
+        0,    0,   27,   29,  137,  194,  133,  194,  117,  100,
+      194,   98,   26,  194,   94,   24,   28,   33,   32,   39,
+       51,   39,   80,   50,    0,   68,   25,   54,    0,  194,
+       88,   71,   80,  194,  194,  194,  194,  194,  194,  194,
+      194,  194,  194,   71,  194,    0,  194,   85,   55,   64,
+       99,  111,   53,  105,    0,   50,   55,  194,  194,  194,
+       40,    0,  194,   38,  194,  194,  194,  194,    0,  194,
+      194,  117,    0,  130,    0,    0,    0,  137,    0,   88,
+      113,    0,  131,    0,  194,  194,  143,  139,  152,  150,
+        0,   13,  153,  194,    0,  194,  194,  176,   31,  181,
 
+      186,  188
     } ;
 
-static yyconst flex_int16_t yy_def[92] =
+static yyconst flex_int16_t yy_def[103] =
     {   0,
-       86,    1,   87,   87,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       20,   86,   86,   86,   88,   86,   86,   86,   89,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   90,   86,   86,   20,   20,
-       48,   51,   91,   21,   86,   86,   86,   86,   86,   88,
-       86,   86,   86,   86,   86,   86,   89,   86,   86,   44,
-       44,   70,   90,   48,   51,   86,   52,   91,   86,   86,
-       86,   72,   75,   86,   86,    0,   86,   86,   86,   86,
-       86
+       97,    1,   98,   98,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       20,   97,   97,   97,   99,   97,   97,   97,  100,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,  101,   97,   97,   20,   20,
+       50,   51,   51,  102,   21,   51,   97,   97,   97,   97,
+       97,   99,   97,   97,   97,   97,   97,   97,  100,   97,
+       97,   44,   44,   72,   72,  101,   48,   51,   51,   97,
+       52,   51,  102,   51,   97,   97,   97,   74,   78,   97,
+       51,   51,   97,   97,   51,   97,    0,   97,   97,   97,
 
+       97,   97
     } ;
 
-static yyconst flex_int16_t yy_nxt[191] =
+static yyconst flex_uint16_t yy_nxt[224] =
     {   0,
         6,    7,    8,    9,   10,   11,   12,   13,   14,   15,
        16,   17,   18,   19,   20,   21,   21,   22,   23,   24,
-       25,   25,   25,   25,   26,   27,   28,   30,   31,   30,
-       31,   37,   40,   65,   32,   60,   32,   42,   61,   45,
-       41,   66,   38,   46,   43,   44,   44,   44,   47,   48,
-       80,   49,   49,   50,   54,   54,   54,   51,   52,   51,
-       53,   55,   56,   51,   58,   59,   61,   62,   63,   84,
-       84,   84,   50,   50,   79,   64,   70,   51,   71,   71,
-       71,   51,   86,   86,   70,   72,   70,   70,   51,   33,
-       74,   74,   74,   51,   51,   51,   51,   75,   51,   51,
+       25,   25,   25,   25,   25,   25,   26,   27,   28,   30,
+       31,   30,   31,   37,   40,   62,   32,   95,   32,   42,
+       63,   45,   41,   65,   38,   46,   43,   44,   44,   44,
+       47,   48,   66,   49,   49,   50,   57,   58,   86,   51,
+       52,   51,   51,   53,   54,   55,   55,   55,   60,   61,
+       63,   64,   67,   85,   84,   56,   51,   82,   50,   50,
+       51,   33,   68,   72,   71,   73,   73,   73,   51,   51,
+       70,   72,   74,   75,   72,   72,   72,   51,   59,   77,
 
-       51,   76,   76,   51,   69,   77,   77,   77,   70,   70,
-       70,   86,   86,   51,   51,   70,   81,   81,   86,   86,
-       82,   82,   82,   81,   81,   51,   68,   83,   83,   83,
-       85,   85,   85,   57,   39,   51,   51,   84,   84,   84,
-       85,   85,   85,   29,   29,   29,   29,   29,   67,   36,
-       35,   67,   67,   73,   34,   73,   73,   73,   78,   78,
-       33,   86,    5,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86
+       77,   77,   90,   90,   90,   51,   78,   79,   51,   51,
+       51,   51,   39,   51,   51,   51,   36,   51,   35,   34,
+       51,   80,   80,   97,   97,   81,   81,   81,   51,   51,
+       51,   72,   72,   72,   33,   91,   97,   97,   72,   72,
+       87,   87,   97,   51,   88,   88,   88,   87,   87,   97,
+       97,   89,   89,   89,   51,   92,   51,   93,   93,   93,
+       97,   75,   97,   97,   90,   90,   90,   93,   93,   93,
+       97,   97,   94,   97,   79,   96,   29,   29,   29,   29,
+       29,   69,   97,   97,   69,   69,   76,   97,   76,   76,
+       76,   83,   83,    5,   97,   97,   97,   97,   97,   97,
+
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97
     } ;
 
-static yyconst flex_int16_t yy_chk[191] =
+static yyconst flex_int16_t yy_chk[224] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    3,    3,    4,
-        4,   13,   16,   28,    3,   88,    4,   17,   62,   19,
-       16,   28,   13,   19,   17,   18,   18,   18,   19,   20,
-       59,   20,   20,   20,   21,   21,   21,   20,   20,   20,
-       20,   22,   22,   21,   24,   24,   26,   26,   27,   76,
-       76,   76,   50,   50,   55,   27,   44,   49,   44,   44,
-       44,   50,   77,   77,   44,   44,   44,   44,   48,   33,
-       48,   48,   48,   51,   51,   51,   48,   48,   48,   48,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    3,
+        3,    4,    4,   13,   16,   99,    3,   92,    4,   17,
+       64,   19,   16,   27,   13,   19,   17,   18,   18,   18,
+       19,   20,   27,   20,   20,   20,   22,   22,   61,   20,
+       20,   20,   20,   20,   20,   21,   21,   21,   24,   24,
+       26,   26,   28,   57,   56,   21,   21,   53,   50,   50,
+       49,   33,   28,   44,   32,   44,   44,   44,   50,   50,
+       31,   44,   44,   44,   44,   44,   44,   48,   23,   48,
 
-       51,   52,   52,   53,   32,   52,   52,   52,   70,   70,
-       70,   82,   82,   53,   53,   70,   72,   72,   83,   83,
-       72,   72,   72,   75,   75,   78,   31,   75,   75,   75,
-       81,   81,   81,   23,   15,   78,   78,   84,   84,   84,
-       85,   85,   85,   87,   87,   87,   87,   87,   89,   12,
-       10,   89,   89,   90,    9,   90,   90,   90,   91,   91,
-        7,    5,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86
+       48,   48,   80,   80,   80,   48,   48,   48,   48,   48,
+       48,   51,   15,   51,   51,   51,   12,   54,   10,    9,
+       51,   52,   52,   81,   81,   52,   52,   52,   54,   54,
+       54,   72,   72,   72,    7,   81,    5,    0,   72,   72,
+       74,   74,    0,   83,   74,   74,   74,   78,   78,   88,
+       88,   78,   78,   78,   83,   83,   83,   87,   87,   87,
+        0,   88,   89,   89,   90,   90,   90,   93,   93,   93,
+        0,    0,   90,    0,   89,   93,   98,   98,   98,   98,
+       98,  100,    0,    0,  100,  100,  101,    0,  101,  101,
+      101,  102,  102,   97,   97,   97,   97,   97,   97,   97,
+
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -507,7 +704,7 @@
 #define YY_RESTORE_YY_MORE_OFFSET
 /*
 //
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
 //
@@ -519,14 +716,27 @@
 IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
 */
 
-#include "Tokenizer.h"
+#if defined(_MSC_VER)
+#pragma warning(disable: 4005)
+#endif
 
-#include "DiagnosticsBase.h"
-#include "Token.h"
+#include "compiler/preprocessor/Tokenizer.h"
+
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/Token.h"
 
 #if defined(__GNUC__)
 // Triggered by the auto-generated yy_fatal_error function.
 #pragma GCC diagnostic ignored "-Wmissing-noreturn"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4244)
+#endif
+
+// Workaround for flex using the register keyword, deprecated in C++11.
+#ifdef __cplusplus
+#if __cplusplus > 199711L
+#define register
+#endif
 #endif
 
 typedef std::string YYSTYPE;
@@ -560,13 +770,25 @@
     } while(0);
 
 #define YY_INPUT(buf, result, maxSize) \
-    result = yyextra->input.read(buf, maxSize);
+    result = yyextra->input.read(buf, maxSize, &yylineno);
+
+
+
+
 
 #define INITIAL 0
 #define COMMENT 1
 
+
+
+
+
+
 #define YY_EXTRA_TYPE pp::Tokenizer::Context*
 
+
+
+
 /* Holds the entire state of the reentrant scanner. */
 struct yyguts_t
     {
@@ -580,8 +802,8 @@
     size_t yy_buffer_stack_max; /**< capacity of stack. */
     YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
     char yy_hold_char;
-    yy_size_t yy_n_chars;
-    yy_size_t yyleng_r;
+    int yy_n_chars;
+    int yyleng_r;
     char *yy_c_buf_p;
     int yy_init;
     int yy_start;
@@ -595,65 +817,132 @@
     int yylineno_r;
     int yy_flex_debug_r;
 
+
+
+
     char *yytext_r;
     int yy_more_flag;
     int yy_more_len;
 
+
+
     YYSTYPE * yylval_r;
 
+
+
     YYLTYPE * yylloc_r;
 
+
     }; /* end struct yyguts_t */
 
+
+
+
 static int yy_init_globals (yyscan_t yyscanner );
 
+
+
+
+    
     /* This must go here because YYSTYPE and YYLTYPE are included
      * from bison output in section 1.*/
     #    define yylval yyg->yylval_r
     
+
+    
     #    define yylloc yyg->yylloc_r
     
+
+
 int pplex_init (yyscan_t* scanner);
 
 int pplex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
 
+
+
 /* Accessor methods to globals.
    These are made visible to non-reentrant scanners for convenience. */
 
+
 int pplex_destroy (yyscan_t yyscanner );
 
+
+
 int ppget_debug (yyscan_t yyscanner );
 
+
+
 void ppset_debug (int debug_flag ,yyscan_t yyscanner );
 
+
+
 YY_EXTRA_TYPE ppget_extra (yyscan_t yyscanner );
 
+
+
 void ppset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
 
+
+
 FILE *ppget_in (yyscan_t yyscanner );
 
-void ppset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+
+void ppset_in  (FILE * _in_str ,yyscan_t yyscanner );
+
+
 
 FILE *ppget_out (yyscan_t yyscanner );
 
-void ppset_out  (FILE * out_str ,yyscan_t yyscanner );
 
-yy_size_t ppget_leng (yyscan_t yyscanner );
+
+void ppset_out  (FILE * _out_str ,yyscan_t yyscanner );
+
+
+
+			int ppget_leng (yyscan_t yyscanner );
+
+
 
 char *ppget_text (yyscan_t yyscanner );
 
+
+
 int ppget_lineno (yyscan_t yyscanner );
 
-void ppset_lineno (int line_number ,yyscan_t yyscanner );
+
+
+void ppset_lineno (int _line_number ,yyscan_t yyscanner );
+
+
+
+
+int ppget_column  (yyscan_t yyscanner );
+
+
+
+
+
+void ppset_column (int _column_no ,yyscan_t yyscanner );
+
+
+
 
 YYSTYPE * ppget_lval (yyscan_t yyscanner );
 
+
 void ppset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
 
+
+    
        YYLTYPE *ppget_lloc (yyscan_t yyscanner );
     
+
+    
         void ppset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
     
+
+
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
  */
@@ -666,6 +955,12 @@
 #endif
 #endif
 
+
+#ifndef YY_NO_UNPUT
+    
+#endif
+
+
 #ifndef yytext_ptr
 static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
 #endif
@@ -684,19 +979,34 @@
 
 #endif
 
+
+
+
+
+
+
+
 /* Amount of stuff to slurp up with each read. */
 #ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
 #define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
 #endif
 
+
 /* Copy whatever the last rule matched to the standard output. */
 #ifndef ECHO
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
 #endif
 
+
+
 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
  * is returned in "result".
  */
@@ -705,7 +1015,7 @@
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		yy_size_t n; \
+		size_t n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -718,7 +1028,7 @@
 	else \
 		{ \
 		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+		while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
 			{ \
 			if( errno != EINTR) \
 				{ \
@@ -733,6 +1043,8 @@
 
 #endif
 
+
+
 /* No semi-colon after return; correct usage is to write "yyterminate();" -
  * we don't want an extra ';' after the "return" because that will cause
  * some compilers to complain about unreachable statements.
@@ -741,24 +1053,48 @@
 #define yyterminate() return YY_NULL
 #endif
 
+
 /* Number of entries by which start-condition stack grows. */
 #ifndef YY_START_STACK_INCR
 #define YY_START_STACK_INCR 25
 #endif
 
+
 /* Report a fatal error. */
 #ifndef YY_FATAL_ERROR
 #define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
 #endif
 
+
+
+
+
 /* end tables serialization structures and prototypes */
 
+
+
 /* Default declaration of generated scanner - a define so the user can
  * easily add parameters.
  */
 #ifndef YY_DECL
 #define YY_DECL_IS_OURS 1
 
+
+
+
+
+
+        
+    
+    
+
+
+
+    
+    
+    
+
+
 extern int pplex \
                (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
 
@@ -766,6 +1102,7 @@
                (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
 #endif /* !YY_DECL */
 
+
 /* Code executed at the beginning of each rule, after yytext and yyleng
  * have been set up.
  */
@@ -773,29 +1110,39 @@
 #define YY_USER_ACTION
 #endif
 
+
+
 /* Code executed at the end of each rule. */
 #ifndef YY_BREAK
-#define YY_BREAK break;
+#define YY_BREAK /*LINTED*/break;
 #endif
 
+
+
 #define YY_RULE_SETUP \
 	YY_USER_ACTION
 
+
+
 /** The main scanner function which does all the work.
  */
 YY_DECL
 {
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
+	yy_state_type yy_current_state;
+	char *yy_cp, *yy_bp;
+	int yy_act;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
-    /* Line comment */
+
+
 
     yylval = yylval_param;
 
+
+
     yylloc = yylloc_param;
 
+
 	if ( !yyg->yy_init )
 		{
 		yyg->yy_init = 1;
@@ -804,6 +1151,8 @@
 		YY_USER_INIT;
 #endif
 
+
+
 		if ( ! yyg->yy_start )
 			yyg->yy_start = 1;	/* first start state */
 
@@ -822,7 +1171,12 @@
 		pp_load_buffer_state(yyscanner );
 		}
 
-	while ( 1 )		/* loops until end-of-file is reached */
+	{
+
+
+    /* Line comment */
+
+	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
 		yy_cp = yyg->yy_c_buf_p;
 
@@ -838,7 +1192,7 @@
 yy_match:
 		do
 			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
 			if ( yy_accept[yy_current_state] )
 				{
 				yyg->yy_last_accepting_state = yy_current_state;
@@ -847,13 +1201,13 @@
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 87 )
+				if ( yy_current_state >= 98 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 86 );
+		while ( yy_current_state != 97 );
 		yy_cp = yyg->yy_last_accepting_cpos;
 		yy_current_state = yyg->yy_last_accepting_state;
 
@@ -862,8 +1216,11 @@
 
 		YY_DO_BEFORE_ACTION;
 
+
+
 do_action:	/* This label is used only to access EOF actions. */
 
+
 		switch ( yy_act )
 	{ /* beginning of action switch */
 			case 0: /* must back up */
@@ -879,7 +1236,7 @@
 	YY_BREAK
 /* Block comment */
 /* Line breaks are just counted - not returned. */
-/* The comment is replaced by a single space. */ 
+/* The comment is replaced by a single space. */
 case 2:
 YY_RULE_SETUP
 { BEGIN(COMMENT); }
@@ -1143,7 +1500,7 @@
 
     if (YY_START == COMMENT)
     {
-        yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT,
+        yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT,
                                      pp::SourceLocation(yyfileno, yylineno),
                                      "");
     }
@@ -1283,8 +1640,14 @@
 			"fatal flex scanner internal error--no action found" );
 	} /* end of action switch */
 		} /* end of scanning one token */
+	} /* end of user's declarations */
 } /* end of pplex */
 
+
+
+
+
+
 /* yy_get_next_buffer - try to read in a new buffer
  *
  * Returns a code representing an action:
@@ -1295,9 +1658,9 @@
 static int yy_get_next_buffer (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = yyg->yytext_ptr;
-	register int number_to_move, i;
+	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	char *source = yyg->yytext_ptr;
+	yy_size_t number_to_move, i;
 	int ret_val;
 
 	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1326,7 +1689,7 @@
 	/* Try to read more data. */
 
 	/* First move last chars to start of buffer. */
-	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+	number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
 
 	for ( i = 0; i < number_to_move; ++i )
 		*(dest++) = *(source++);
@@ -1339,21 +1702,21 @@
 
 	else
 		{
-			yy_size_t num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+			int num_to_read =
+			static_cast<int>(YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1);
 
 		while ( num_to_read <= 0 )
 			{ /* Not enough room in the buffer - grow it. */
 
 			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
 
 			int yy_c_buf_p_offset =
 				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
 
 			if ( b->yy_is_our_buffer )
 				{
-				yy_size_t new_size = b->yy_buf_size * 2;
+				int new_size = b->yy_buf_size * 2;
 
 				if ( new_size <= 0 )
 					b->yy_buf_size += b->yy_buf_size / 8;
@@ -1366,7 +1729,7 @@
 				}
 			else
 				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
+				b->yy_ch_buf = NULL;
 
 			if ( ! b->yy_ch_buf )
 				YY_FATAL_ERROR(
@@ -1374,8 +1737,8 @@
 
 			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
 
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
+			num_to_read = static_cast<int>(YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1);
 
 			}
 
@@ -1383,8 +1746,10 @@
 			num_to_read = YY_READ_BUF_SIZE;
 
 		/* Read in more data. */
+		yy_size_t ret = 0;
 		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			yyg->yy_n_chars, num_to_read );
+			ret, num_to_read );
+		yyg->yy_n_chars = static_cast<int>(ret);
 
 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
 		}
@@ -1408,7 +1773,7 @@
 	else
 		ret_val = EOB_ACT_CONTINUE_SCAN;
 
-	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+	if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
 		/* Extend the array by 50%, plus the number we really need. */
 		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
 		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) pprealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
@@ -1416,7 +1781,7 @@
 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
 	}
 
-	yyg->yy_n_chars += number_to_move;
+	yyg->yy_n_chars += static_cast<int>(number_to_move);
 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
 
@@ -1425,19 +1790,21 @@
 	return ret_val;
 }
 
+
 /* yy_get_previous_state - get the state just before the EOB char was reached */
 
+
     static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
 {
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
+	yy_state_type yy_current_state;
+	char *yy_cp;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
 	yy_current_state = yyg->yy_start;
 
 	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
 		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
 		if ( yy_accept[yy_current_state] )
 			{
 			yyg->yy_last_accepting_state = yy_current_state;
@@ -1446,15 +1813,16 @@
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 87 )
+			if ( yy_current_state >= 98 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
 		}
 
 	return yy_current_state;
 }
 
+
 /* yy_try_NUL_trans - try to make a transition on the NUL character
  *
  * synopsis
@@ -1462,11 +1830,11 @@
  */
     static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
 {
-	register int yy_is_jam;
+	int yy_is_jam;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
-	register char *yy_cp = yyg->yy_c_buf_p;
+	char *yy_cp = yyg->yy_c_buf_p;
 
-	register YY_CHAR yy_c = 1;
+	YY_CHAR yy_c = 1;
 	if ( yy_accept[yy_current_state] )
 		{
 		yyg->yy_last_accepting_state = yy_current_state;
@@ -1475,15 +1843,21 @@
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 87 )
+		if ( yy_current_state >= 98 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 86);
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+	yy_is_jam = (yy_current_state == 97);
 
+	(void)yyg;
 	return yy_is_jam ? 0 : yy_current_state;
 }
 
+
+#ifndef YY_NO_UNPUT
+
+#endif
+
 #ifndef YY_NO_INPUT
 #ifdef __cplusplus
     static int yyinput (yyscan_t yyscanner)
@@ -1509,7 +1883,7 @@
 
 		else
 			{ /* need more input */
-			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
 			++yyg->yy_c_buf_p;
 
 			switch ( yy_get_next_buffer( yyscanner ) )
@@ -1533,7 +1907,7 @@
 				case EOB_ACT_END_OF_FILE:
 					{
 					if ( ppwrap(yyscanner ) )
-						return EOF;
+						return 0;
 
 					if ( ! yyg->yy_did_buffer_switch_on_eof )
 						YY_NEW_FILE;
@@ -1555,6 +1929,7 @@
 	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
 	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
 
+
 	return c;
 }
 #endif	/* ifndef YY_NO_INPUT */
@@ -1578,6 +1953,7 @@
 	pp_load_buffer_state(yyscanner );
 }
 
+
 /** Switch to a different input buffer.
  * @param new_buffer The new input buffer.
  * @param yyscanner The scanner object.
@@ -1614,6 +1990,7 @@
 	yyg->yy_did_buffer_switch_on_eof = 1;
 }
 
+
 static void pp_load_buffer_state  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1637,7 +2014,7 @@
 	if ( ! b )
 		YY_FATAL_ERROR( "out of dynamic memory in pp_create_buffer()" );
 
-	b->yy_buf_size = size;
+	b->yy_buf_size = (yy_size_t)size;
 
 	/* yy_ch_buf has to be 2 characters longer than the size given because
 	 * we need to put in 2 end-of-buffer characters.
@@ -1653,6 +2030,7 @@
 	return b;
 }
 
+
 /** Destroy the buffer.
  * @param b a buffer created with pp_create_buffer()
  * @param yyscanner The scanner object.
@@ -1673,6 +2051,7 @@
 	ppfree((void *) b ,yyscanner );
 }
 
+
 /* Initializes or reinitializes a buffer.
  * This function is sometimes called more than once on the same buffer,
  * such as during a pprestart() or at EOF.
@@ -1697,8 +2076,11 @@
         b->yy_bs_column = 0;
     }
 
+
+    
         b->yy_is_interactive = 0;
     
+
 	errno = oerrno;
 }
 
@@ -1763,6 +2145,7 @@
 	yyg->yy_did_buffer_switch_on_eof = 1;
 }
 
+
 /** Removes and deletes the top of the stack, if present.
  *  The next element becomes the new top.
  *  @param yyscanner The scanner object.
@@ -1784,6 +2167,7 @@
 	}
 }
 
+
 /* Allocates the stack if it does not exist.
  *  Guarantees space for at least one push.
  */
@@ -1798,13 +2182,14 @@
 		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
 		 * immediate realloc on the next call.
          */
-		num_to_alloc = 1;
+      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
 		yyg->yy_buffer_stack = (struct yy_buffer_state**)ppalloc
 								(num_to_alloc * sizeof(struct yy_buffer_state*)
 								, yyscanner);
 		if ( ! yyg->yy_buffer_stack )
 			YY_FATAL_ERROR( "out of dynamic memory in ppensure_buffer_stack()" );
 								  
+		
 		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
 				
 		yyg->yy_buffer_stack_max = num_to_alloc;
@@ -1815,7 +2200,7 @@
 	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
 
 		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
+		yy_size_t grow_size = 8 /* arbitrary grow size */;
 
 		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
 		yyg->yy_buffer_stack = (struct yy_buffer_state**)pprealloc
@@ -1831,6 +2216,10 @@
 	}
 }
 
+
+
+
+
 /** Setup the input buffer state to scan directly from a user-specified character buffer.
  * @param base the character buffer
  * @param size the size in bytes of the character buffer
@@ -1845,16 +2234,16 @@
 	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
 	     base[size-1] != YY_END_OF_BUFFER_CHAR )
 		/* They forgot to leave room for the EOB's. */
-		return 0;
+		return NULL;
 
 	b = (YY_BUFFER_STATE) ppalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
 	if ( ! b )
 		YY_FATAL_ERROR( "out of dynamic memory in pp_scan_buffer()" );
 
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_size = static_cast<int>(size - 2);	/* "- 2" to take care of EOB's */
 	b->yy_buf_pos = b->yy_ch_buf = base;
 	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
+	b->yy_input_file = NULL;
 	b->yy_n_chars = b->yy_buf_size;
 	b->yy_is_interactive = 0;
 	b->yy_at_bol = 1;
@@ -1866,6 +2255,9 @@
 	return b;
 }
 
+
+
+
 /** Setup the input buffer state to scan a string. The next call to pplex() will
  * scan from a @e copy of @a str.
  * @param yystr a NUL-terminated string to scan
@@ -1877,29 +2269,33 @@
 YY_BUFFER_STATE pp_scan_string (yyconst char * yystr , yyscan_t yyscanner)
 {
     
-	return pp_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+	return pp_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
 }
 
+
+
+
 /** Setup the input buffer state to scan the given bytes. The next call to pplex() will
  * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
  * @param yyscanner The scanner object.
  * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE pp_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE pp_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
 	char *buf;
-	yy_size_t n, i;
+	yy_size_t n;
+	yy_size_t i;
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
+	n = (yy_size_t) _yybytes_len + 2;
 	buf = (char *) ppalloc(n ,yyscanner );
 	if ( ! buf )
 		YY_FATAL_ERROR( "out of dynamic memory in pp_scan_bytes()" );
 
-	for ( i = 0; i < _yybytes_len; ++i )
+	for ( i = 0; i < static_cast<yy_size_t>(_yybytes_len); ++i )
 		buf[i] = yybytes[i];
 
 	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
@@ -1916,13 +2312,25 @@
 	return b;
 }
 
+
+
+
+
+
+
+
+
+
+
 #ifndef YY_EXIT_FAILURE
 #define YY_EXIT_FAILURE 2
 #endif
 
-static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
 {
-    	(void) fprintf( stderr, "%s\n", msg );
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+	(void) fprintf( stderr, "%s\n", msg );
 	exit( YY_EXIT_FAILURE );
 }
 
@@ -1943,8 +2351,11 @@
 		} \
 	while ( 0 )
 
+
+
 /* Accessor  methods (get/set functions) to struct members. */
 
+
 /** Get the user-defined data for this scanner.
  * @param yyscanner The scanner object.
  */
@@ -1954,6 +2365,8 @@
     return yyextra;
 }
 
+
+
 /** Get the current line number.
  * @param yyscanner The scanner object.
  */
@@ -1961,12 +2374,16 @@
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     
+    
         if (! YY_CURRENT_BUFFER)
             return 0;
     
     return yylineno;
 }
 
+
+
+
 /** Get the current column number.
  * @param yyscanner The scanner object.
  */
@@ -1974,12 +2391,16 @@
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     
+    
         if (! YY_CURRENT_BUFFER)
             return 0;
     
     return yycolumn;
 }
 
+
+
+
 /** Get the input stream.
  * @param yyscanner The scanner object.
  */
@@ -1989,6 +2410,8 @@
     return yyin;
 }
 
+
+
 /** Get the output stream.
  * @param yyscanner The scanner object.
  */
@@ -1998,15 +2421,18 @@
     return yyout;
 }
 
+
+
 /** Get the length of the current token.
  * @param yyscanner The scanner object.
  */
-yy_size_t ppget_leng  (yyscan_t yyscanner)
+int ppget_leng  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyleng;
 }
 
+
 /** Get the current token.
  * @param yyscanner The scanner object.
  */
@@ -2017,6 +2443,8 @@
     return yytext;
 }
 
+
+
 /** Set the user-defined data. This data is never touched by the scanner.
  * @param user_defined The data to be associated with this scanner.
  * @param yyscanner The scanner object.
@@ -2027,92 +2455,123 @@
     yyextra = user_defined ;
 }
 
+
+
 /** Set the current line number.
- * @param line_number
+ * @param _line_number line number
  * @param yyscanner The scanner object.
  */
-void ppset_lineno (int  line_number , yyscan_t yyscanner)
+void ppset_lineno (int  _line_number , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
+    
         /* lineno is only valid if an input buffer exists. */
         if (! YY_CURRENT_BUFFER )
-           yy_fatal_error( "ppset_lineno called with no buffer" , yyscanner); 
+           YY_FATAL_ERROR( "ppset_lineno called with no buffer" );
     
-    yylineno = line_number;
+    yylineno = _line_number;
 }
 
+
+
+
 /** Set the current column.
- * @param line_number
+ * @param _column_no column number
  * @param yyscanner The scanner object.
  */
-void ppset_column (int  column_no , yyscan_t yyscanner)
+void ppset_column (int  _column_no , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
+    
         /* column is only valid if an input buffer exists. */
         if (! YY_CURRENT_BUFFER )
-           yy_fatal_error( "ppset_column called with no buffer" , yyscanner); 
+           YY_FATAL_ERROR( "ppset_column called with no buffer" );
     
-    yycolumn = column_no;
+    yycolumn = _column_no;
 }
 
+
+
+
+
 /** Set the input stream. This does not discard the current
  * input buffer.
- * @param in_str A readable stream.
+ * @param _in_str A readable stream.
  * @param yyscanner The scanner object.
  * @see pp_switch_to_buffer
  */
-void ppset_in (FILE *  in_str , yyscan_t yyscanner)
+void ppset_in (FILE *  _in_str , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyin = in_str ;
+    yyin = _in_str ;
 }
 
-void ppset_out (FILE *  out_str , yyscan_t yyscanner)
+
+
+void ppset_out (FILE *  _out_str , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyout = out_str ;
+    yyout = _out_str ;
 }
 
+
+
+
 int ppget_debug  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yy_flex_debug;
 }
 
-void ppset_debug (int  bdebug , yyscan_t yyscanner)
+
+
+void ppset_debug (int  _bdebug , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yy_flex_debug = bdebug ;
+    yy_flex_debug = _bdebug ;
 }
 
+
 /* Accessor methods for yylval and yylloc */
 
+
 YYSTYPE * ppget_lval  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yylval;
 }
 
+
+
 void ppset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yylval = yylval_param;
 }
 
+
+
+    
 YYLTYPE *ppget_lloc  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yylloc;
 }
     
+
+    
 void ppset_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yylloc = yylloc_param;
 }
     
+
+
+
+
 /* User-visible API */
 
 /* pplex_init is special because it creates the scanner itself, so it is
@@ -2141,6 +2600,7 @@
     return yy_init_globals ( *ptr_yy_globals );
 }
 
+
 /* pplex_init_extra has the same functionality as pplex_init, but follows the
  * convention of taking the scanner as the last argument. Note however, that
  * this is a *pointer* to a scanner, as it will be allocated by this call (and
@@ -2177,6 +2637,7 @@
     return yy_init_globals ( *ptr_yy_globals );
 }
 
+
 static int yy_init_globals (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2184,24 +2645,31 @@
      * This function is called from pplex_destroy(), so don't allocate here.
      */
 
-    yyg->yy_buffer_stack = 0;
+
+    yyg->yy_buffer_stack = NULL;
     yyg->yy_buffer_stack_top = 0;
     yyg->yy_buffer_stack_max = 0;
-    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_c_buf_p = NULL;
     yyg->yy_init = 0;
     yyg->yy_start = 0;
 
+
     yyg->yy_start_stack_ptr = 0;
     yyg->yy_start_stack_depth = 0;
     yyg->yy_start_stack =  NULL;
 
+
+
+
+
+
 /* Defined in main.c */
 #ifdef YY_STDINIT
     yyin = stdin;
     yyout = stdout;
 #else
-    yyin = (FILE *) 0;
-    yyout = (FILE *) 0;
+    yyin = NULL;
+    yyout = NULL;
 #endif
 
     /* For future reference: Set errno on error, since we are called by
@@ -2210,6 +2678,7 @@
     return 0;
 }
 
+
 /* pplex_destroy is for both reentrant and non-reentrant scanners. */
 int pplex_destroy  (yyscan_t yyscanner)
 {
@@ -2226,10 +2695,14 @@
 	ppfree(yyg->yy_buffer_stack ,yyscanner);
 	yyg->yy_buffer_stack = NULL;
 
+
     /* Destroy the start condition stack. */
         ppfree(yyg->yy_start_stack ,yyscanner );
         yyg->yy_start_stack = NULL;
 
+
+
+
     /* Reset the globals. This is important in a non-reentrant scanner so the next time
      * pplex() is called, initialization will occur. */
     yy_init_globals( yyscanner);
@@ -2240,23 +2713,32 @@
     return 0;
 }
 
+
+
 /*
  * Internal utility routines.
  */
 
+
+
 #ifndef yytext_ptr
 static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
 {
-	register int i;
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+
+	int i;
 	for ( i = 0; i < n; ++i )
 		s1[i] = s2[i];
 }
 #endif
 
+
+
 #ifdef YY_NEED_STRLEN
 static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
 {
-	register int n;
+	int n;
 	for ( n = 0; s[n]; ++n )
 		;
 
@@ -2264,13 +2746,22 @@
 }
 #endif
 
+
+
 void *ppalloc (yy_size_t  size , yyscan_t yyscanner)
 {
-	return (void *) malloc( size );
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+	return malloc(size);
 }
 
+
+
 void *pprealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
 {
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+
 	/* The cast to (char *) in the following accommodates both
 	 * implementations that use char* generic pointers, and those
 	 * that use void* generic pointers.  It works with the latter
@@ -2278,23 +2769,32 @@
 	 * any pointer type to void*, and deal with argument conversions
 	 * as though doing an assignment.
 	 */
-	return (void *) realloc( (char *) ptr, size );
+	return realloc(ptr, size);
 }
 
+
+
 void ppfree (void * ptr , yyscan_t yyscanner)
 {
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
 	free( (char *) ptr );	/* see pprealloc() for (char *) cast */
 }
 
+
 #define YYTABLES_NAME "yytables"
 
+
+
+
+
+
+
+
+
 namespace pp {
 
-// TODO(alokp): Maximum token length should ideally be specified by
-// the preprocessor client, i.e., the compiler.
-const size_t Tokenizer::kMaxTokenLength = 256;
-
-Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
+Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(nullptr), mMaxTokenSize(256)
 {
     mContext.diagnostics = diagnostics;
 }
@@ -2304,9 +2804,10 @@
     destroyScanner();
 }
 
-bool Tokenizer::init(size_t count, const char* const string[], const int length[])
+bool Tokenizer::init(size_t count, const char * const string[], const int length[])
 {
-    if ((count > 0) && (string == 0)) return false;
+    if ((count > 0) && (string == 0))
+        return false;
 
     mContext.input = Input(count, string, length);
     return initScanner();
@@ -2324,14 +2825,19 @@
     ppset_lineno(line,mHandle);
 }
 
-void Tokenizer::lex(Token* token)
+void Tokenizer::setMaxTokenSize(size_t maxTokenSize)
+{
+    mMaxTokenSize = maxTokenSize;
+}
+
+void Tokenizer::lex(Token *token)
 {
     token->type = pplex(&token->text,&token->location,mHandle);
-    if (token->text.size() > kMaxTokenLength)
+    if (token->text.size() > mMaxTokenSize)
     {
-        mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
+        mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG,
                                      token->location, token->text);
-        token->text.erase(kMaxTokenLength);
+        token->text.erase(mMaxTokenSize);
     }
 
     token->flags = 0;
@@ -2345,7 +2851,7 @@
 
 bool Tokenizer::initScanner()
 {
-    if ((mHandle == NULL) && pplex_init_extra(&mContext,&mHandle))
+    if ((mHandle == nullptr) && pplex_init_extra(&mContext, &mHandle))
         return false;
 
     pprestart(0,mHandle);
@@ -2354,12 +2860,13 @@
 
 void Tokenizer::destroyScanner()
 {
-    if (mHandle == NULL)
+    if (mHandle == nullptr)
         return;
 
     pplex_destroy(mHandle);
-    mHandle = NULL;
+    mHandle = nullptr;
 }
 
 }  // namespace pp
 
+
diff --git a/src/third_party/angle/src/compiler/preprocessor/Tokenizer.h b/src/third_party/angle/src/compiler/preprocessor/Tokenizer.h
index 7a6fa87..ce030a1 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Tokenizer.h
+++ b/src/third_party/angle/src/compiler/preprocessor/Tokenizer.h
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2012-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.
 //
@@ -7,9 +7,9 @@
 #ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_
 #define COMPILER_PREPROCESSOR_TOKENIZER_H_
 
-#include "Input.h"
-#include "Lexer.h"
-#include "pp_utils.h"
+#include "common/angleutils.h"
+#include "compiler/preprocessor/Input.h"
+#include "compiler/preprocessor/Lexer.h"
 
 namespace pp
 {
@@ -21,7 +21,7 @@
   public:
     struct Context
     {
-        Diagnostics* diagnostics;
+        Diagnostics *diagnostics;
 
         Input input;
         // The location where yytext points to. Token location should track
@@ -32,27 +32,27 @@
         bool leadingSpace;
         bool lineStart;
     };
-    static const std::size_t kMaxTokenLength;
 
-    Tokenizer(Diagnostics* diagnostics);
+    Tokenizer(Diagnostics *diagnostics);
     ~Tokenizer();
 
-    bool init(size_t count, const char* const string[], const int length[]);
+    bool init(size_t count, const char *const string[], const int length[]);
 
     void setFileNumber(int file);
     void setLineNumber(int line);
+    void setMaxTokenSize(size_t maxTokenSize);
 
-    virtual void lex(Token* token);
+    void lex(Token *token) override;
 
   private:
-    PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer);
     bool initScanner();
     void destroyScanner();
 
-    void* mHandle;  // Scanner handle.
-    Context mContext;  // Scanner extra.
+    void *mHandle;         // Scanner handle.
+    Context mContext;      // Scanner extra.
+    size_t mMaxTokenSize;  // Maximum token size
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_TOKENIZER_H_
 
+#endif  // COMPILER_PREPROCESSOR_TOKENIZER_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/Tokenizer.l b/src/third_party/angle/src/compiler/preprocessor/Tokenizer.l
index fc81d84..62eb4ca 100644
--- a/src/third_party/angle/src/compiler/preprocessor/Tokenizer.l
+++ b/src/third_party/angle/src/compiler/preprocessor/Tokenizer.l
@@ -1,6 +1,6 @@
 /*
 //
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
 //
@@ -14,7 +14,7 @@
 
 %top{
 //
-// Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2011-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.
 //
@@ -23,14 +23,27 @@
 }
 
 %{
-#include "Tokenizer.h"
+#if defined(_MSC_VER)
+#pragma warning(disable: 4005)
+#endif
 
-#include "DiagnosticsBase.h"
-#include "Token.h"
+#include "compiler/preprocessor/Tokenizer.h"
+
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/Token.h"
 
 #if defined(__GNUC__)
 // Triggered by the auto-generated yy_fatal_error function.
 #pragma GCC diagnostic ignored "-Wmissing-noreturn"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4244)
+#endif
+
+// Workaround for flex using the register keyword, deprecated in C++11.
+#ifdef __cplusplus
+#if __cplusplus > 199711L
+#define register
+#endif
 #endif
 
 typedef std::string YYSTYPE;
@@ -64,7 +77,7 @@
     } while(0);
 
 #define YY_INPUT(buf, result, maxSize) \
-    result = yyextra->input.read(buf, maxSize);
+    result = yyextra->input.read(buf, maxSize, &yylineno);
 
 %}
 
@@ -78,9 +91,9 @@
 IDENTIFIER  [_a-zA-Z][_a-zA-Z0-9]*
 PUNCTUATOR  [][<>(){}.+-/*%^|&~=!:;,?]
 
-DECIMAL_CONSTANT      [1-9][0-9]*
-OCTAL_CONSTANT        0[0-7]*
-HEXADECIMAL_CONSTANT  0[xX][0-9a-fA-F]+
+DECIMAL_CONSTANT      [1-9][0-9]*[uU]?
+OCTAL_CONSTANT        0[0-7]*[uU]?
+HEXADECIMAL_CONSTANT  0[xX][0-9a-fA-F]+[uU]?
 
 DIGIT                [0-9]
 EXPONENT_PART        [eE][+-]?{DIGIT}+
@@ -93,7 +106,7 @@
 
     /* Block comment */
     /* Line breaks are just counted - not returned. */
-    /* The comment is replaced by a single space. */ 
+    /* The comment is replaced by a single space. */
 "/*" { BEGIN(COMMENT); }
 <COMMENT>[^*\r\n]+
 <COMMENT>"*"
@@ -114,12 +127,12 @@
     return pp::Token::IDENTIFIER;
 }
 
-{DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} {
+({DECIMAL_CONSTANT}[uU]?)|({OCTAL_CONSTANT}[uU]?)|({HEXADECIMAL_CONSTANT}[uU]?) {
     yylval->assign(yytext, yyleng);
     return pp::Token::CONST_INT;
 }
 
-({DIGIT}+{EXPONENT_PART})|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?) {
+({DIGIT}+{EXPONENT_PART}[fF]?)|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?[fF]?) {
     yylval->assign(yytext, yyleng);
     return pp::Token::CONST_FLOAT;
 }
@@ -256,7 +269,7 @@
 
     if (YY_START == COMMENT)
     {
-        yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT,
+        yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT,
                                      pp::SourceLocation(yyfileno, yylineno),
                                      "");
     }
@@ -267,11 +280,7 @@
 
 namespace pp {
 
-// TODO(alokp): Maximum token length should ideally be specified by
-// the preprocessor client, i.e., the compiler.
-const size_t Tokenizer::kMaxTokenLength = 256;
-
-Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
+Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(nullptr), mMaxTokenSize(256)
 {
     mContext.diagnostics = diagnostics;
 }
@@ -281,9 +290,10 @@
     destroyScanner();
 }
 
-bool Tokenizer::init(size_t count, const char* const string[], const int length[])
+bool Tokenizer::init(size_t count, const char * const string[], const int length[])
 {
-    if ((count > 0) && (string == 0)) return false;
+    if ((count > 0) && (string == 0))
+        return false;
 
     mContext.input = Input(count, string, length);
     return initScanner();
@@ -301,14 +311,19 @@
     yyset_lineno(line, mHandle);
 }
 
-void Tokenizer::lex(Token* token)
+void Tokenizer::setMaxTokenSize(size_t maxTokenSize)
+{
+    mMaxTokenSize = maxTokenSize;
+}
+
+void Tokenizer::lex(Token *token)
 {
     token->type = yylex(&token->text, &token->location, mHandle);
-    if (token->text.size() > kMaxTokenLength)
+    if (token->text.size() > mMaxTokenSize)
     {
-        mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
+        mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG,
                                      token->location, token->text);
-        token->text.erase(kMaxTokenLength);
+        token->text.erase(mMaxTokenSize);
     }
 
     token->flags = 0;
@@ -322,7 +337,7 @@
 
 bool Tokenizer::initScanner()
 {
-    if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle))
+    if ((mHandle == nullptr) && yylex_init_extra(&mContext, &mHandle))
         return false;
 
     yyrestart(0, mHandle);
@@ -331,11 +346,11 @@
 
 void Tokenizer::destroyScanner()
 {
-    if (mHandle == NULL)
+    if (mHandle == nullptr)
         return;
 
     yylex_destroy(mHandle);
-    mHandle = NULL;
+    mHandle = nullptr;
 }
 
 }  // namespace pp
diff --git a/src/third_party/angle/src/compiler/preprocessor/length_limits.h b/src/third_party/angle/src/compiler/preprocessor/length_limits.h
deleted file mode 100644
index 4f1f713..0000000
--- a/src/third_party/angle/src/compiler/preprocessor/length_limits.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Copyright (c) 2011 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.
-//
-
-//
-// length_limits.h
-//
-
-#if !defined(__LENGTH_LIMITS_H)
-#define __LENGTH_LIMITS_H 1
-
-// These constants are factored out from the rest of the headers to
-// make it easier to reference them from the compiler sources.
-
-// These lengths do not include the NULL terminator.
-#define MAX_SYMBOL_NAME_LEN 256
-#define MAX_STRING_LEN 511
-
-#endif // !(defined(__LENGTH_LIMITS_H)
diff --git a/src/third_party/angle/src/compiler/preprocessor/numeric_lex.h b/src/third_party/angle/src/compiler/preprocessor/numeric_lex.h
index b04125d..6ea779a 100644
--- a/src/third_party/angle/src/compiler/preprocessor/numeric_lex.h
+++ b/src/third_party/angle/src/compiler/preprocessor/numeric_lex.h
@@ -6,22 +6,22 @@
 
 // numeric_lex.h: Functions to extract numeric values from string.
 
-#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
-#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
+#ifndef COMPILER_PREPROCESSOR_NUMERICLEX_H_
+#define COMPILER_PREPROCESSOR_NUMERICLEX_H_
 
+#include <cmath>
 #include <sstream>
 
-namespace pp {
-
-inline std::ios::fmtflags numeric_base_int(const std::string& str)
+namespace pp
 {
-    if ((str.size() >= 2) &&
-        (str[0] == '0') &&
-        (str[1] == 'x' || str[1] == 'X'))
+
+inline std::ios::fmtflags numeric_base_int(const std::string &str)
+{
+    if ((str.size() >= 2) && (str[0] == '0') && (str[1] == 'x' || str[1] == 'X'))
     {
         return std::ios::hex;
     }
-    else if ((str.size() >= 1) && (str[0] == '0'))
+    if ((str.size() >= 1) && (str[0] == '0'))
     {
         return std::ios::oct;
     }
@@ -33,8 +33,8 @@
 // of the correct form. They can only fail if the parsed value is too big,
 // in which case false is returned.
 
-template<typename IntType>
-bool numeric_lex_int(const std::string& str, IntType* value)
+template <typename IntType>
+bool numeric_lex_int(const std::string &str, IntType *value)
 {
     std::istringstream stream(str);
     // This should not be necessary, but MSVS has a buggy implementation.
@@ -45,17 +45,28 @@
     return !stream.fail();
 }
 
-template<typename FloatType>
-bool numeric_lex_float(const std::string& str, FloatType* value)
+template <typename FloatType>
+bool numeric_lex_float(const std::string &str, FloatType *value)
 {
+// On 64-bit Intel Android, istringstream is broken.  Until this is fixed in
+// a newer NDK, don't use it.  Android doesn't have locale support, so this
+// doesn't have to force the C locale.
+// TODO(thakis): Remove this once this bug has been fixed in the NDK and
+// that NDK has been rolled into chromium.
+#if defined(ANGLE_PLATFORM_ANDROID) && __x86_64__
+    *value = strtod(str.c_str(), nullptr);
+    return errno != ERANGE;
+#else
     std::istringstream stream(str);
     // Force "C" locale so that decimal character is always '.', and
     // not dependent on the current locale.
     stream.imbue(std::locale::classic());
 
     stream >> (*value);
-    return !stream.fail();
+    return !stream.fail() && std::isfinite(*value);
+#endif
 }
 
-} // namespace pp.
-#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
+}  // namespace pp.
+
+#endif  // COMPILER_PREPROCESSOR_NUMERICLEX_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/pp_utils.h b/src/third_party/angle/src/compiler/preprocessor/pp_utils.h
deleted file mode 100644
index 17164ea..0000000
--- a/src/third_party/angle/src/compiler/preprocessor/pp_utils.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// pp_utils.h: Common preprocessor utilities
-
-#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_
-#define COMPILER_PREPROCESSOR_PPUTILS_H_
-
-// A macro to disallow the copy constructor and operator= functions
-// This must be used in the private: declarations for a class.
-#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&);               \
-  void operator=(const TypeName&)
-
-#endif // COMPILER_PREPROCESSOR_PPUTILS_H_
diff --git a/src/third_party/angle/src/compiler/preprocessor/preprocessor.vcxproj b/src/third_party/angle/src/compiler/preprocessor/preprocessor.vcxproj
deleted file mode 100644
index ca8530b..0000000
--- a/src/third_party/angle/src/compiler/preprocessor/preprocessor.vcxproj
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Debug|x64">

-      <Configuration>Debug</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|x64">

-      <Configuration>Release</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{FBE32DF3-0FB0-4F2F-A424-2C21BD7BC325}</ProjectGuid>

-    <RootNamespace>preprocessor</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;4718;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;4718;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;4718;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="DiagnosticsBase.cpp" />

-    <ClCompile Include="DirectiveHandlerBase.cpp" />

-    <ClCompile Include="DirectiveParser.cpp" />

-    <ClCompile Include="ExpressionParser.cpp" />

-    <ClCompile Include="Input.cpp" />

-    <ClCompile Include="Lexer.cpp" />

-    <ClCompile Include="Macro.cpp" />

-    <ClCompile Include="MacroExpander.cpp" />

-    <ClCompile Include="Preprocessor.cpp" />

-    <ClCompile Include="Token.cpp" />

-    <ClCompile Include="Tokenizer.cpp" />

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="length_limits.h" />

-    <ClInclude Include="DiagnosticsBase.h" />

-    <ClInclude Include="DirectiveHandlerBase.h" />

-    <ClInclude Include="DirectiveParser.h" />

-    <ClInclude Include="ExpressionParser.h" />

-    <ClInclude Include="Input.h" />

-    <ClInclude Include="Lexer.h" />

-    <ClInclude Include="Macro.h" />

-    <ClInclude Include="MacroExpander.h" />

-    <ClInclude Include="numeric_lex.h" />

-    <ClInclude Include="pp_utils.h" />

-    <ClInclude Include="Preprocessor.h" />

-    <ClInclude Include="SourceLocation.h" />

-    <ClInclude Include="Token.h" />

-    <ClInclude Include="Tokenizer.h" />

-  </ItemGroup>

-  <ItemGroup>

-    <None Include="Tokenizer.l" />

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/preprocessor/preprocessor.vcxproj.filters b/src/third_party/angle/src/compiler/preprocessor/preprocessor.vcxproj.filters
deleted file mode 100644
index 4ac202f..0000000
--- a/src/third_party/angle/src/compiler/preprocessor/preprocessor.vcxproj.filters
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup>

-    <Filter Include="Source Files">

-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

-    </Filter>

-    <Filter Include="Header Files">

-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

-    </Filter>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="DirectiveParser.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="ExpressionParser.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Input.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Lexer.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Macro.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="MacroExpander.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Preprocessor.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Token.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Tokenizer.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="DiagnosticsBase.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="DirectiveHandlerBase.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="DirectiveParser.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="ExpressionParser.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Input.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Lexer.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Macro.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="MacroExpander.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="numeric_lex.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="pp_utils.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Preprocessor.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="SourceLocation.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Token.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Tokenizer.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="length_limits.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="DiagnosticsBase.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="DirectiveHandlerBase.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-  </ItemGroup>

-  <ItemGroup>

-    <None Include="Tokenizer.l">

-      <Filter>Source Files</Filter>

-    </None>

-  </ItemGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp b/src/third_party/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp
deleted file mode 100644
index 538b731..0000000
--- a/src/third_party/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/InfoSink.h"
-#include "compiler/ParseHelper.h"
-#include "compiler/depgraph/DependencyGraphOutput.h"
-#include "compiler/timing/RestrictFragmentShaderTiming.h"
-
-RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink)
-    : mSink(sink)
-    , mNumErrors(0)
-{
-    // Sampling ops found only in fragment shaders.
-    mSamplingOps.insert("texture2D(s21;vf2;f1;");
-    mSamplingOps.insert("texture2DProj(s21;vf3;f1;");
-    mSamplingOps.insert("texture2DProj(s21;vf4;f1;");
-    mSamplingOps.insert("textureCube(sC1;vf3;f1;");
-    // Sampling ops found in both vertex and fragment shaders.
-    mSamplingOps.insert("texture2D(s21;vf2;");
-    mSamplingOps.insert("texture2DProj(s21;vf3;");
-    mSamplingOps.insert("texture2DProj(s21;vf4;");
-    mSamplingOps.insert("textureCube(sC1;vf3;");
-    // Sampling ops provided by OES_EGL_image_external.
-    mSamplingOps.insert("texture2D(1;vf2;");
-    mSamplingOps.insert("texture2DProj(1;vf3;");
-    mSamplingOps.insert("texture2DProj(1;vf4;");
-    // Sampling ops provided by ARB_texture_rectangle.
-    mSamplingOps.insert("texture2DRect(1;vf2;");
-    mSamplingOps.insert("texture2DRectProj(1;vf3;");
-    mSamplingOps.insert("texture2DRectProj(1;vf4;");
-}
-
-// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc.
-// can vary based on the value of the input arguments. If so, we should restrict those as well.
-void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph)
-{
-    mNumErrors = 0;
-
-    // FIXME(mvujovic): The dependency graph does not support user defined function calls right now,
-    // so we generate errors for them.
-    validateUserDefinedFunctionCallUsage(graph);
-
-    // Starting from each sampler, traverse the dependency graph and generate an error each time we
-    // hit a node where sampler dependent values are not allowed.
-    for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols();
-         iter != graph.endSamplerSymbols();
-         ++iter)
-    {
-        TGraphSymbol* samplerSymbol = *iter;
-        clearVisited();
-        samplerSymbol->traverse(this);
-    }
-}
-
-void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph)
-{
-    for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
-         iter != graph.endUserDefinedFunctionCalls();
-         ++iter)
-    {
-        TGraphFunctionCall* functionCall = *iter;
-        beginError(functionCall->getIntermFunctionCall());
-        mSink << "A call to a user defined function is not permitted.\n";
-    }
-}
-
-void RestrictFragmentShaderTiming::beginError(const TIntermNode* node)
-{
-    ++mNumErrors;
-    mSink.prefix(EPrefixError);
-    mSink.location(node->getLine());
-}
-
-bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const
-{
-    return !intermFunctionCall->isUserDefined() &&
-           mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end();
-}
-
-void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter)
-{
-    // Texture cache access time might leak sensitive information.
-    // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a
-    // sampling operation.
-    if (isSamplingOp(parameter->getIntermFunctionCall())) {
-        switch (parameter->getArgumentNumber()) {
-            case 1:
-                // Second argument (coord)
-                beginError(parameter->getIntermFunctionCall());
-                mSink << "An expression dependent on a sampler is not permitted to be the"
-                      << " coordinate argument of a sampling operation.\n";
-                break;
-            case 2:
-                // Third argument (bias)
-                beginError(parameter->getIntermFunctionCall());
-                mSink << "An expression dependent on a sampler is not permitted to be the"
-                      << " bias argument of a sampling operation.\n";
-                break;
-            default:
-                // First argument (sampler)
-                break;
-        }
-    }
-}
-
-void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection)
-{
-    beginError(selection->getIntermSelection());
-    mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n";
-}
-
-void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop)
-{
-    beginError(loop->getIntermLoop());
-    mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n";
-}
-
-void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp)
-{
-    beginError(logicalOp->getIntermLogicalOp());
-    mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical "
-          << logicalOp->getOpString()
-          << " operator.\n";
-}
diff --git a/src/third_party/angle/src/compiler/timing/RestrictFragmentShaderTiming.h b/src/third_party/angle/src/compiler/timing/RestrictFragmentShaderTiming.h
deleted file mode 100644
index 899165c..0000000
--- a/src/third_party/angle/src/compiler/timing/RestrictFragmentShaderTiming.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
-#define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
-
-#include "GLSLANG/ShaderLang.h"
-
-#include "compiler/intermediate.h"
-#include "compiler/depgraph/DependencyGraph.h"
-
-class TInfoSinkBase;
-
-class RestrictFragmentShaderTiming : TDependencyGraphTraverser {
-public:
-    RestrictFragmentShaderTiming(TInfoSinkBase& sink);
-    void enforceRestrictions(const TDependencyGraph& graph);
-    int numErrors() const { return mNumErrors; }
-
-    virtual void visitArgument(TGraphArgument* parameter);
-    virtual void visitSelection(TGraphSelection* selection);
-    virtual void visitLoop(TGraphLoop* loop);
-    virtual void visitLogicalOp(TGraphLogicalOp* logicalOp);
-
-private:
-    void beginError(const TIntermNode* node);
-    void validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph);
-    bool isSamplingOp(const TIntermAggregate* intermFunctionCall) const;
-
-    TInfoSinkBase& mSink;
-    int mNumErrors;
-
-    typedef std::set<TString> StringSet;
-    StringSet mSamplingOps;
-};
-
-#endif  // COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
diff --git a/src/third_party/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp b/src/third_party/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp
deleted file mode 100644
index 355eb62..0000000
--- a/src/third_party/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/timing/RestrictVertexShaderTiming.h"
-
-void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node)
-{
-    if (IsSampler(node->getBasicType())) {
-        ++mNumErrors;
-        mSink.message(EPrefixError,
-                      node->getLine(),
-                      "Samplers are not permitted in vertex shaders");
-    }
-}
diff --git a/src/third_party/angle/src/compiler/timing/RestrictVertexShaderTiming.h b/src/third_party/angle/src/compiler/timing/RestrictVertexShaderTiming.h
deleted file mode 100644
index 19a05fa..0000000
--- a/src/third_party/angle/src/compiler/timing/RestrictVertexShaderTiming.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
-#define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
-
-#include "GLSLANG/ShaderLang.h"
-
-#include "compiler/intermediate.h"
-#include "compiler/InfoSink.h"
-
-class TInfoSinkBase;
-
-class RestrictVertexShaderTiming : public TIntermTraverser {
-public:
-    RestrictVertexShaderTiming(TInfoSinkBase& sink)
-        : TIntermTraverser(true, false, false)
-        , mSink(sink)
-        , mNumErrors(0) {}
-
-    void enforceRestrictions(TIntermNode* root) { root->traverse(this); }
-    int numErrors() { return mNumErrors; }
-
-    virtual void visitSymbol(TIntermSymbol*);
-private:
-    TInfoSinkBase& mSink;
-    int mNumErrors;
-};
-
-#endif  // COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
diff --git a/src/third_party/angle/src/compiler/translator/64bit-lexer-safety.patch b/src/third_party/angle/src/compiler/translator/64bit-lexer-safety.patch
new file mode 100644
index 0000000..e7e4037
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/64bit-lexer-safety.patch
@@ -0,0 +1,122 @@
+diff --git a/src/compiler/translator/glslang_lex.cpp b/src/compiler/translator/glslang_lex.cpp
+index 1ba63df..2a206ab 100644
+--- a/src/compiler/translator/glslang_lex.cpp
++++ b/src/compiler/translator/glslang_lex.cpp
+@@ -1,4 +1,3 @@
+-#line 17 "./glslang.l"
+ //
+ // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style license that can be
+@@ -149,6 +148,7 @@ typedef int16_t flex_int16_t;
+ typedef uint16_t flex_uint16_t;
+ typedef int32_t flex_int32_t;
+ typedef uint32_t flex_uint32_t;
++typedef uint64_t flex_uint64_t;
+ #else
+ typedef signed char flex_int8_t;
+ typedef short int flex_int16_t;
+@@ -335,6 +335,11 @@ typedef size_t yy_size_t;
+ 
+ 
+ 
++#ifndef YY_TYPEDEF_YY_SIZE_T
++#define YY_TYPEDEF_YY_SIZE_T
++typedef size_t yy_size_t;
++#endif
++
+ #define EOB_ACT_CONTINUE_SCAN 0
+ #define EOB_ACT_END_OF_FILE 1
+ #define EOB_ACT_LAST_MATCH 2
+@@ -351,8 +356,8 @@ typedef size_t yy_size_t;
+      */
+     #define  YY_LESS_LINENO(n) \
+             do { \
+-                int yyl;\
+-                for ( yyl = n; yyl < yyleng; ++yyl )\
++                yy_size_t yyl;\
++                for ( yyl = n; yyl < static_cast<yy_site_t>(yyleng); ++yyl )\
+                     if ( yytext[yyl] == '\n' )\
+                         --yylineno;\
+             }while(0)
+@@ -1692,7 +1697,7 @@ yy_find_action:
+ 		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ 			{
+ 			yy_size_t yyl;
+-			for ( yyl = 0; yyl < yyleng; ++yyl )
++			for ( yyl = 0; yyl < static_cast<yy_size_t>(yyleng); ++yyl )
+ 				if ( yytext[yyl] == '\n' )
+ 					   
+     do{ yylineno++;
+@@ -2655,7 +2660,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
+ 	else
+ 		{
+ 			int num_to_read =
+-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
++			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - static_cast<int>(number_to_move) - 1;
+ 
+ 		while ( num_to_read <= 0 )
+ 			{ /* Not enough room in the buffer - grow it. */
+@@ -2690,7 +2695,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
+ 			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+ 
+ 			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+-						number_to_move - 1;
++						static_cast<int>(number_to_move) - 1;
+ 
+ 			}
+ 
+@@ -2698,8 +2703,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
+ 			num_to_read = YY_READ_BUF_SIZE;
+ 
+ 		/* Read in more data. */
++        size_t result = 0;
+ 		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+-			yyg->yy_n_chars, num_to_read );
++            result, num_to_read );
++        yyg->yy_n_chars = static_cast<int>(result);
+ 
+ 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ 		}
+@@ -2725,13 +2732,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
+ 
+ 	if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ 		/* Extend the array by 50%, plus the number we really need. */
+-		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
++		int new_size = yyg->yy_n_chars + static_cast<int>(number_to_move) + (yyg->yy_n_chars >> 1);
+ 		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ 		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ 	}
+ 
+-	yyg->yy_n_chars += number_to_move;
++	yyg->yy_n_chars += static_cast<int>(number_to_move);
+ 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+ 
+@@ -3158,7 +3165,7 @@ static void yyensure_buffer_stack (yyscan_t yyscanner)
+ 		/* Increase the buffer to prepare for a possible push. */
+ 		yy_size_t grow_size = 8 /* arbitrary grow size */;
+ 
+-		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
++		num_to_alloc = static_cast<int>(yyg->yy_buffer_stack_max + grow_size);
+ 		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+ 								(yyg->yy_buffer_stack,
+ 								num_to_alloc * sizeof(struct yy_buffer_state*)
+@@ -3196,7 +3203,7 @@ YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscann
+ 	if ( ! b )
+ 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+ 
+-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
++	b->yy_buf_size = static_cast<int>(size) - 2;	/* "- 2" to take care of EOB's */
+ 	b->yy_buf_pos = b->yy_ch_buf = base;
+ 	b->yy_is_our_buffer = 0;
+ 	b->yy_input_file = NULL;
+@@ -3251,7 +3258,7 @@ YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yysc
+ 	if ( ! buf )
+ 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+ 
+-	for ( i = 0; i < _yybytes_len; ++i )
++	for ( i = 0; i < static_cast<yy_size_t>(_yybytes_len); ++i )
+ 		buf[i] = yybytes[i];
+ 
+ 	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
diff --git a/src/third_party/angle/src/compiler/translator/ASTMetadataHLSL.cpp b/src/third_party/angle/src/compiler/translator/ASTMetadataHLSL.cpp
new file mode 100644
index 0000000..80a8ab6
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ASTMetadataHLSL.cpp
@@ -0,0 +1,461 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Analysis of the AST needed for HLSL generation
+
+#include "compiler/translator/ASTMetadataHLSL.h"
+
+#include "compiler/translator/CallDAG.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// Class used to traverse the AST of a function definition, checking if the
+// function uses a gradient, and writing the set of control flow using gradients.
+// It assumes that the analysis has already been made for the function's
+// callees.
+class PullGradient : public TIntermTraverser
+{
+  public:
+    PullGradient(MetadataList *metadataList, size_t index, const CallDAG &dag)
+        : TIntermTraverser(true, false, true),
+          mMetadataList(metadataList),
+          mMetadata(&(*metadataList)[index]),
+          mIndex(index),
+          mDag(dag)
+    {
+        ASSERT(index < metadataList->size());
+
+        // ESSL 100 builtin gradient functions
+        mGradientBuiltinFunctions.insert("texture2D");
+        mGradientBuiltinFunctions.insert("texture2DProj");
+        mGradientBuiltinFunctions.insert("textureCube");
+
+        // ESSL 300 builtin gradient functions
+        mGradientBuiltinFunctions.insert("texture");
+        mGradientBuiltinFunctions.insert("textureProj");
+        mGradientBuiltinFunctions.insert("textureOffset");
+        mGradientBuiltinFunctions.insert("textureProjOffset");
+
+        // ESSL 310 doesn't add builtin gradient functions
+    }
+
+    void traverse(TIntermFunctionDefinition *node)
+    {
+        node->traverse(this);
+        ASSERT(mParents.empty());
+    }
+
+    // Called when a gradient operation or a call to a function using a gradient is found.
+    void onGradient()
+    {
+        mMetadata->mUsesGradient = true;
+        // Mark the latest control flow as using a gradient.
+        if (!mParents.empty())
+        {
+            mMetadata->mControlFlowsContainingGradient.insert(mParents.back());
+        }
+    }
+
+    void visitControlFlow(Visit visit, TIntermNode *node)
+    {
+        if (visit == PreVisit)
+        {
+            mParents.push_back(node);
+        }
+        else if (visit == PostVisit)
+        {
+            ASSERT(mParents.back() == node);
+            mParents.pop_back();
+            // A control flow's using a gradient means its parents are too.
+            if (mMetadata->mControlFlowsContainingGradient.count(node) > 0 && !mParents.empty())
+            {
+                mMetadata->mControlFlowsContainingGradient.insert(mParents.back());
+            }
+        }
+    }
+
+    bool visitLoop(Visit visit, TIntermLoop *loop) override
+    {
+        visitControlFlow(visit, loop);
+        return true;
+    }
+
+    bool visitIfElse(Visit visit, TIntermIfElse *ifElse) override
+    {
+        visitControlFlow(visit, ifElse);
+        return true;
+    }
+
+    bool visitUnary(Visit visit, TIntermUnary *node) override
+    {
+        if (visit == PreVisit)
+        {
+            switch (node->getOp())
+            {
+                case EOpDFdx:
+                case EOpDFdy:
+                case EOpFwidth:
+                    onGradient();
+                default:
+                    break;
+            }
+        }
+
+        return true;
+    }
+
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override
+    {
+        if (visit == PreVisit)
+        {
+            if (node->getOp() == EOpCallFunctionInAST)
+            {
+                size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
+                ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
+
+                if ((*mMetadataList)[calleeIndex].mUsesGradient)
+                {
+                    onGradient();
+                }
+            }
+            else if (node->getOp() == EOpCallBuiltInFunction)
+            {
+                if (mGradientBuiltinFunctions.find(node->getFunctionSymbolInfo()->getName()) !=
+                    mGradientBuiltinFunctions.end())
+                {
+                    onGradient();
+                }
+            }
+        }
+
+        return true;
+    }
+
+  private:
+    MetadataList *mMetadataList;
+    ASTMetadataHLSL *mMetadata;
+    size_t mIndex;
+    const CallDAG &mDag;
+
+    // Contains a stack of the control flow nodes that are parents of the node being
+    // currently visited. It is used to mark control flows using a gradient.
+    std::vector<TIntermNode *> mParents;
+
+    // A list of builtin functions that use gradients
+    std::set<TString> mGradientBuiltinFunctions;
+};
+
+// Traverses the AST of a function definition to compute the the discontinuous loops
+// and the if statements containing gradient loops. It assumes that the gradient loops
+// (loops that contain a gradient) have already been computed and that it has already
+// traversed the current function's callees.
+class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
+{
+  public:
+    PullComputeDiscontinuousAndGradientLoops(MetadataList *metadataList,
+                                             size_t index,
+                                             const CallDAG &dag)
+        : TIntermTraverser(true, false, true),
+          mMetadataList(metadataList),
+          mMetadata(&(*metadataList)[index]),
+          mIndex(index),
+          mDag(dag)
+    {
+    }
+
+    void traverse(TIntermFunctionDefinition *node)
+    {
+        node->traverse(this);
+        ASSERT(mLoopsAndSwitches.empty());
+        ASSERT(mIfs.empty());
+    }
+
+    // Called when traversing a gradient loop or a call to a function with a
+    // gradient loop in its call graph.
+    void onGradientLoop()
+    {
+        mMetadata->mHasGradientLoopInCallGraph = true;
+        // Mark the latest if as using a discontinuous loop.
+        if (!mIfs.empty())
+        {
+            mMetadata->mIfsContainingGradientLoop.insert(mIfs.back());
+        }
+    }
+
+    bool visitLoop(Visit visit, TIntermLoop *loop) override
+    {
+        if (visit == PreVisit)
+        {
+            mLoopsAndSwitches.push_back(loop);
+
+            if (mMetadata->hasGradientInCallGraph(loop))
+            {
+                onGradientLoop();
+            }
+        }
+        else if (visit == PostVisit)
+        {
+            ASSERT(mLoopsAndSwitches.back() == loop);
+            mLoopsAndSwitches.pop_back();
+        }
+
+        return true;
+    }
+
+    bool visitIfElse(Visit visit, TIntermIfElse *node) override
+    {
+        if (visit == PreVisit)
+        {
+            mIfs.push_back(node);
+        }
+        else if (visit == PostVisit)
+        {
+            ASSERT(mIfs.back() == node);
+            mIfs.pop_back();
+            // An if using a discontinuous loop means its parents ifs are also discontinuous.
+            if (mMetadata->mIfsContainingGradientLoop.count(node) > 0 && !mIfs.empty())
+            {
+                mMetadata->mIfsContainingGradientLoop.insert(mIfs.back());
+            }
+        }
+
+        return true;
+    }
+
+    bool visitBranch(Visit visit, TIntermBranch *node) override
+    {
+        if (visit == PreVisit)
+        {
+            switch (node->getFlowOp())
+            {
+                case EOpBreak:
+                {
+                    ASSERT(!mLoopsAndSwitches.empty());
+                    TIntermLoop *loop = mLoopsAndSwitches.back()->getAsLoopNode();
+                    if (loop != nullptr)
+                    {
+                        mMetadata->mDiscontinuousLoops.insert(loop);
+                    }
+                }
+                break;
+                case EOpContinue:
+                {
+                    ASSERT(!mLoopsAndSwitches.empty());
+                    TIntermLoop *loop = nullptr;
+                    size_t i          = mLoopsAndSwitches.size();
+                    while (loop == nullptr && i > 0)
+                    {
+                        --i;
+                        loop = mLoopsAndSwitches.at(i)->getAsLoopNode();
+                    }
+                    ASSERT(loop != nullptr);
+                    mMetadata->mDiscontinuousLoops.insert(loop);
+                }
+                break;
+                case EOpKill:
+                case EOpReturn:
+                    // A return or discard jumps out of all the enclosing loops
+                    if (!mLoopsAndSwitches.empty())
+                    {
+                        for (TIntermNode *intermNode : mLoopsAndSwitches)
+                        {
+                            TIntermLoop *loop = intermNode->getAsLoopNode();
+                            if (loop)
+                            {
+                                mMetadata->mDiscontinuousLoops.insert(loop);
+                            }
+                        }
+                    }
+                    break;
+                default:
+                    UNREACHABLE();
+            }
+        }
+
+        return true;
+    }
+
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override
+    {
+        if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST)
+        {
+            size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
+            ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
+
+            if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph)
+            {
+                onGradientLoop();
+            }
+        }
+
+        return true;
+    }
+
+    bool visitSwitch(Visit visit, TIntermSwitch *node) override
+    {
+        if (visit == PreVisit)
+        {
+            mLoopsAndSwitches.push_back(node);
+        }
+        else if (visit == PostVisit)
+        {
+            ASSERT(mLoopsAndSwitches.back() == node);
+            mLoopsAndSwitches.pop_back();
+        }
+        return true;
+    }
+
+  private:
+    MetadataList *mMetadataList;
+    ASTMetadataHLSL *mMetadata;
+    size_t mIndex;
+    const CallDAG &mDag;
+
+    std::vector<TIntermNode *> mLoopsAndSwitches;
+    std::vector<TIntermIfElse *> mIfs;
+};
+
+// Tags all the functions called in a discontinuous loop
+class PushDiscontinuousLoops : public TIntermTraverser
+{
+  public:
+    PushDiscontinuousLoops(MetadataList *metadataList, size_t index, const CallDAG &dag)
+        : TIntermTraverser(true, true, true),
+          mMetadataList(metadataList),
+          mMetadata(&(*metadataList)[index]),
+          mIndex(index),
+          mDag(dag),
+          mNestedDiscont(mMetadata->mCalledInDiscontinuousLoop ? 1 : 0)
+    {
+    }
+
+    void traverse(TIntermFunctionDefinition *node)
+    {
+        node->traverse(this);
+        ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0));
+    }
+
+    bool visitLoop(Visit visit, TIntermLoop *loop) override
+    {
+        bool isDiscontinuous = mMetadata->mDiscontinuousLoops.count(loop) > 0;
+
+        if (visit == PreVisit && isDiscontinuous)
+        {
+            mNestedDiscont++;
+        }
+        else if (visit == PostVisit && isDiscontinuous)
+        {
+            mNestedDiscont--;
+        }
+
+        return true;
+    }
+
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override
+    {
+        switch (node->getOp())
+        {
+            case EOpCallFunctionInAST:
+                if (visit == PreVisit && mNestedDiscont > 0)
+                {
+                    size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
+                    ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
+
+                    (*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true;
+                }
+                break;
+            default:
+                break;
+        }
+        return true;
+    }
+
+  private:
+    MetadataList *mMetadataList;
+    ASTMetadataHLSL *mMetadata;
+    size_t mIndex;
+    const CallDAG &mDag;
+
+    int mNestedDiscont;
+};
+}
+
+bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node)
+{
+    return mControlFlowsContainingGradient.count(node) > 0;
+}
+
+bool ASTMetadataHLSL::hasGradientLoop(TIntermIfElse *node)
+{
+    return mIfsContainingGradientLoop.count(node) > 0;
+}
+
+MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag)
+{
+    MetadataList metadataList(callDag.size());
+
+    // Compute all the information related to when gradient operations are used.
+    // We want to know for each function and control flow operation if they have
+    // a gradient operation in their call graph (shortened to "using a gradient"
+    // in the rest of the file).
+    //
+    // This computation is logically split in three steps:
+    //  1 - For each function compute if it uses a gradient in its body, ignoring
+    // calls to other user-defined functions.
+    //  2 - For each function determine if it uses a gradient in its call graph,
+    // using the result of step 1 and the CallDAG to know its callees.
+    //  3 - For each control flow statement of each function, check if it uses a
+    // gradient in the function's body, or if it calls a user-defined function that
+    // uses a gradient.
+    //
+    // We take advantage of the call graph being a DAG and instead compute 1, 2 and 3
+    // for leaves first, then going down the tree. This is correct because 1 doesn't
+    // depend on other functions, and 2 and 3 depend only on callees.
+    for (size_t i = 0; i < callDag.size(); i++)
+    {
+        PullGradient pull(&metadataList, i, callDag);
+        pull.traverse(callDag.getRecordFromIndex(i).node);
+    }
+
+    // Compute which loops are discontinuous and which function are called in
+    // these loops. The same way computing gradient usage is a "pull" process,
+    // computing "bing used in a discont. loop" is a push process. However we also
+    // need to know what ifs have a discontinuous loop inside so we do the same type
+    // of callgraph analysis as for the gradient.
+
+    // First compute which loops are discontinuous (no specific order) and pull
+    // the ifs and functions using a gradient loop.
+    for (size_t i = 0; i < callDag.size(); i++)
+    {
+        PullComputeDiscontinuousAndGradientLoops pull(&metadataList, i, callDag);
+        pull.traverse(callDag.getRecordFromIndex(i).node);
+    }
+
+    // Then push the information to callees, either from the a local discontinuous
+    // loop or from the caller being called in a discontinuous loop already
+    for (size_t i = callDag.size(); i-- > 0;)
+    {
+        PushDiscontinuousLoops push(&metadataList, i, callDag);
+        push.traverse(callDag.getRecordFromIndex(i).node);
+    }
+
+    // We create "Lod0" version of functions with the gradient operations replaced
+    // by non-gradient operations so that the D3D compiler is happier with discont
+    // loops.
+    for (auto &metadata : metadataList)
+    {
+        metadata.mNeedsLod0 = metadata.mCalledInDiscontinuousLoop && metadata.mUsesGradient;
+    }
+
+    return metadataList;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ASTMetadataHLSL.h b/src/third_party/angle/src/compiler/translator/ASTMetadataHLSL.h
new file mode 100644
index 0000000..550a522
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ASTMetadataHLSL.h
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Defines analyses of the AST needed for HLSL generation
+
+#ifndef COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
+#define COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
+
+#include <set>
+#include <vector>
+
+namespace sh
+{
+
+class CallDAG;
+class TIntermNode;
+class TIntermIfElse;
+class TIntermLoop;
+
+struct ASTMetadataHLSL
+{
+    ASTMetadataHLSL()
+        : mUsesGradient(false),
+          mCalledInDiscontinuousLoop(false),
+          mHasGradientLoopInCallGraph(false),
+          mNeedsLod0(false)
+    {
+    }
+
+    // Here "something uses a gradient" means here that it either contains a
+    // gradient operation, or a call to a function that uses a gradient.
+    bool hasGradientInCallGraph(TIntermLoop *node);
+    bool hasGradientLoop(TIntermIfElse *node);
+
+    // Does the function use a gradient.
+    bool mUsesGradient;
+
+    // Even if usesGradient is true, some control flow might not use a gradient
+    // so we store the set of all gradient-using control flows.
+    std::set<TIntermNode *> mControlFlowsContainingGradient;
+
+    // Remember information about the discontinuous loops and which functions
+    // are called in such loops.
+    bool mCalledInDiscontinuousLoop;
+    bool mHasGradientLoopInCallGraph;
+    std::set<TIntermLoop *> mDiscontinuousLoops;
+    std::set<TIntermIfElse *> mIfsContainingGradientLoop;
+
+    // Will we need to generate a Lod0 version of the function.
+    bool mNeedsLod0;
+};
+
+typedef std::vector<ASTMetadataHLSL> MetadataList;
+
+// Return the AST analysis result, in the order defined by the call DAG
+MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp b/src/third_party/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp
new file mode 100644
index 0000000..0177fea
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/AddAndTrueToLoopCondition.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// An AST traverser that rewrites for and while loops by replacing "condition" with
+// "condition && true" to work around condition bug on Intel Mac.
+class AddAndTrueToLoopConditionTraverser : public TIntermTraverser
+{
+  public:
+    AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {}
+
+    bool visitLoop(Visit, TIntermLoop *loop) override
+    {
+        // do-while loop doesn't have this bug.
+        if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile)
+        {
+            return true;
+        }
+
+        // For loop may not have a condition.
+        if (loop->getCondition() == nullptr)
+        {
+            return true;
+        }
+
+        // Constant true.
+        TConstantUnion *trueConstant = new TConstantUnion();
+        trueConstant->setBConst(true);
+        TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, TType(EbtBool));
+
+        // CONDITION && true.
+        TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue);
+        loop->setCondition(andOp);
+
+        return true;
+    }
+};
+
+}  // anonymous namespace
+
+void AddAndTrueToLoopCondition(TIntermNode *root)
+{
+    AddAndTrueToLoopConditionTraverser traverser;
+    root->traverse(&traverser);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/AddAndTrueToLoopCondition.h b/src/third_party/angle/src/compiler/translator/AddAndTrueToLoopCondition.h
new file mode 100644
index 0000000..34debe0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/AddAndTrueToLoopCondition.h
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// Rewrite condition in for and while loops to work around driver bug on Intel Mac.
+
+#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
+#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void AddAndTrueToLoopCondition(TIntermNode *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
diff --git a/src/third_party/angle/src/compiler/translator/AddDefaultReturnStatements.cpp b/src/third_party/angle/src/compiler/translator/AddDefaultReturnStatements.cpp
new file mode 100644
index 0000000..55442e8
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/AddDefaultReturnStatements.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2016 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.
+//
+// AddDefaultReturnStatements.cpp: Add default return statements to functions that do not end in a
+//                                 return.
+//
+
+#include "compiler/translator/AddDefaultReturnStatements.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+bool NeedsReturnStatement(TIntermFunctionDefinition *node, TType *returnType)
+{
+    *returnType = node->getFunctionPrototype()->getType();
+    if (returnType->getBasicType() == EbtVoid)
+    {
+        return false;
+    }
+
+    TIntermBlock *bodyNode    = node->getBody();
+    TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode();
+    if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+}  // anonymous namespace
+
+void AddDefaultReturnStatements(TIntermBlock *root)
+{
+    TType returnType;
+    for (TIntermNode *node : *root->getSequence())
+    {
+        TIntermFunctionDefinition *definition = node->getAsFunctionDefinition();
+        if (definition != nullptr && NeedsReturnStatement(definition, &returnType))
+        {
+            TIntermBranch *branch =
+                new TIntermBranch(EOpReturn, TIntermTyped::CreateZero(returnType));
+
+            TIntermBlock *bodyNode = definition->getBody();
+            bodyNode->getSequence()->push_back(branch);
+        }
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/AddDefaultReturnStatements.h b/src/third_party/angle/src/compiler/translator/AddDefaultReturnStatements.h
new file mode 100644
index 0000000..40a70ad
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/AddDefaultReturnStatements.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2016 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.
+//
+// AddDefaultReturnStatements.h: Add default return statements to functions that do not end in a
+//                               return.
+//
+
+#ifndef COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
+#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
+
+class TIntermBlock;
+
+namespace sh
+{
+
+void AddDefaultReturnStatements(TIntermBlock *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
diff --git a/src/third_party/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp b/src/third_party/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
new file mode 100644
index 0000000..552abc5
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
@@ -0,0 +1,202 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The ArrayReturnValueToOutParameter function changes return values of an array type to out
+// parameters in
+// function definitions, prototypes, and call sites.
+
+#include "compiler/translator/ArrayReturnValueToOutParameter.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to)
+{
+    const TIntermSequence *fromSequence = from->getSequence();
+    for (size_t ii = 0; ii < fromSequence->size(); ++ii)
+    {
+        to->getSequence()->push_back(fromSequence->at(ii));
+    }
+}
+
+TIntermSymbol *CreateReturnValueSymbol(const TType &type)
+{
+    TIntermSymbol *node = new TIntermSymbol(0, "angle_return", type);
+    node->setInternal(true);
+    return node;
+}
+
+TIntermSymbol *CreateReturnValueOutSymbol(const TType &type)
+{
+    TType outType(type);
+    outType.setQualifier(EvqOut);
+    return CreateReturnValueSymbol(outType);
+}
+
+TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall,
+                                        TIntermTyped *returnValueTarget)
+{
+    TIntermSequence *replacementArguments = new TIntermSequence();
+    TIntermSequence *originalArguments    = originalCall->getSequence();
+    for (auto &arg : *originalArguments)
+    {
+        replacementArguments->push_back(arg);
+    }
+    replacementArguments->push_back(returnValueTarget);
+    TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall(
+        TType(EbtVoid), originalCall->getFunctionSymbolInfo()->getId(),
+        originalCall->getFunctionSymbolInfo()->getNameObj(), replacementArguments);
+    replacementCall->setLine(originalCall->getLine());
+    return replacementCall;
+}
+
+class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
+{
+  public:
+    static void apply(TIntermNode *root, unsigned int *temporaryIndex);
+
+  private:
+    ArrayReturnValueToOutParameterTraverser();
+
+    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    bool visitBranch(Visit visit, TIntermBranch *node) override;
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+
+    bool mInFunctionWithArrayReturnValue;
+};
+
+void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, unsigned int *temporaryIndex)
+{
+    ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam;
+    arrayReturnValueToOutParam.useTemporaryIndex(temporaryIndex);
+    root->traverse(&arrayReturnValueToOutParam);
+    arrayReturnValueToOutParam.updateTree();
+}
+
+ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser()
+    : TIntermTraverser(true, false, true), mInFunctionWithArrayReturnValue(false)
+{
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition(
+    Visit visit,
+    TIntermFunctionDefinition *node)
+{
+    if (node->getFunctionPrototype()->isArray() && visit == PreVisit)
+    {
+        // Replacing the function header is done on visitFunctionPrototype().
+        mInFunctionWithArrayReturnValue = true;
+    }
+    if (visit == PostVisit)
+    {
+        mInFunctionWithArrayReturnValue = false;
+    }
+    return true;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit,
+                                                                     TIntermFunctionPrototype *node)
+{
+    if (visit == PreVisit && node->isArray())
+    {
+        // Replace the whole prototype node with another node that has the out parameter
+        // added. Also set the function to return void.
+        TIntermFunctionPrototype *replacement =
+            new TIntermFunctionPrototype(TType(EbtVoid), node->getFunctionSymbolInfo()->getId());
+        CopyAggregateChildren(node, replacement);
+        replacement->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
+        *replacement->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo();
+        replacement->setLine(node->getLine());
+
+        queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
+    }
+    return false;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    ASSERT(!node->isArray() || node->getOp() != EOpCallInternalRawFunction);
+    if (visit == PreVisit && node->isArray() && node->getOp() == EOpCallFunctionInAST)
+    {
+        // Handle call sites where the returned array is not assigned.
+        // Examples where f() is a function returning an array:
+        // 1. f();
+        // 2. another_array == f();
+        // 3. another_function(f());
+        // 4. return f();
+        // Cases 2 to 4 are already converted to simpler cases by
+        // SeparateExpressionsReturningArrays, so we only need to worry about the case where a
+        // function call returning an array forms an expression by itself.
+        TIntermBlock *parentBlock = getParentNode()->getAsBlock();
+        if (parentBlock)
+        {
+            nextTemporaryIndex();
+            TIntermSequence replacements;
+            replacements.push_back(createTempDeclaration(node->getType()));
+            TIntermSymbol *returnSymbol = createTempSymbol(node->getType());
+            replacements.push_back(CreateReplacementCall(node, returnSymbol));
+            mMultiReplacements.push_back(
+                NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
+        }
+        return false;
+    }
+    return true;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBranch *node)
+{
+    if (mInFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn)
+    {
+        // Instead of returning a value, assign to the out parameter and then return.
+        TIntermSequence replacements;
+
+        TIntermTyped *expression = node->getExpression();
+        ASSERT(expression != nullptr);
+        TIntermSymbol *returnValueSymbol = CreateReturnValueSymbol(expression->getType());
+        TIntermBinary *replacementAssignment =
+            new TIntermBinary(EOpAssign, returnValueSymbol, expression);
+        replacementAssignment->setLine(expression->getLine());
+        replacements.push_back(replacementAssignment);
+
+        TIntermBranch *replacementBranch = new TIntermBranch(EOpReturn, nullptr);
+        replacementBranch->setLine(node->getLine());
+        replacements.push_back(replacementBranch);
+
+        mMultiReplacements.push_back(
+            NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, replacements));
+    }
+    return false;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+    if (node->getOp() == EOpAssign && node->getLeft()->isArray())
+    {
+        TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
+        ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpCallInternalRawFunction);
+        if (rightAgg != nullptr && rightAgg->getOp() == EOpCallFunctionInAST)
+        {
+            TIntermAggregate *replacementCall = CreateReplacementCall(rightAgg, node->getLeft());
+            queueReplacement(node, replacementCall, OriginalNode::IS_DROPPED);
+        }
+    }
+    return false;
+}
+
+}  // namespace
+
+void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex)
+{
+    ArrayReturnValueToOutParameterTraverser::apply(root, temporaryIndex);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h b/src/third_party/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h
new file mode 100644
index 0000000..18f5265
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The ArrayReturnValueToOutParameter function changes return values of an array type to out
+// parameters in
+// function definitions, prototypes and call sites.
+
+#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
+#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
+
+namespace sh
+{
+class TIntermNode;
+
+void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
diff --git a/src/third_party/angle/src/compiler/translator/BaseTypes.h b/src/third_party/angle/src/compiler/translator/BaseTypes.h
new file mode 100644
index 0000000..905b59f
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/BaseTypes.h
@@ -0,0 +1,894 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_BASETYPES_H_
+#define COMPILER_TRANSLATOR_BASETYPES_H_
+
+#include <algorithm>
+#include <array>
+
+#include "common/debug.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+
+//
+// Precision qualifiers
+//
+enum TPrecision
+{
+    // These need to be kept sorted
+    EbpUndefined,
+    EbpLow,
+    EbpMedium,
+    EbpHigh,
+
+    // end of list
+    EbpLast
+};
+
+inline const char *getPrecisionString(TPrecision p)
+{
+    switch (p)
+    {
+        case EbpHigh:
+            return "highp";
+        case EbpMedium:
+            return "mediump";
+        case EbpLow:
+            return "lowp";
+        default:
+            return "mediump";  // Safest fallback
+    }
+}
+
+//
+// Basic type.  Arrays, vectors, etc., are orthogonal to this.
+//
+enum TBasicType
+{
+    EbtVoid,
+    EbtFloat,
+    EbtInt,
+    EbtUInt,
+    EbtBool,
+    EbtGVec4,              // non type: represents vec4, ivec4, and uvec4
+    EbtGenType,            // non type: represents float, vec2, vec3, and vec4
+    EbtGenIType,           // non type: represents int, ivec2, ivec3, and ivec4
+    EbtGenUType,           // non type: represents uint, uvec2, uvec3, and uvec4
+    EbtGenBType,           // non type: represents bool, bvec2, bvec3, and bvec4
+    EbtVec,                // non type: represents vec2, vec3, and vec4
+    EbtIVec,               // non type: represents ivec2, ivec3, and ivec4
+    EbtUVec,               // non type: represents uvec2, uvec3, and uvec4
+    EbtBVec,               // non type: represents bvec2, bvec3, and bvec4
+    EbtYuvCscStandardEXT,  // Only valid if EXT_YUV_target exists.
+    EbtGuardSamplerBegin,  // non type: see implementation of IsSampler()
+    EbtSampler2D,
+    EbtSampler3D,
+    EbtSamplerCube,
+    EbtSampler2DArray,
+    EbtSamplerExternalOES,       // Only valid if OES_EGL_image_external exists.
+    EbtSamplerExternal2DY2YEXT,  // Only valid if GL_EXT_YUV_target exists.
+    EbtSampler2DRect,            // Only valid if GL_ARB_texture_rectangle exists.
+    EbtSampler2DMS,
+    EbtISampler2D,
+    EbtISampler3D,
+    EbtISamplerCube,
+    EbtISampler2DArray,
+    EbtISampler2DMS,
+    EbtUSampler2D,
+    EbtUSampler3D,
+    EbtUSamplerCube,
+    EbtUSampler2DArray,
+    EbtUSampler2DMS,
+    EbtSampler2DShadow,
+    EbtSamplerCubeShadow,
+    EbtSampler2DArrayShadow,
+    EbtGuardSamplerEnd,  // non type: see implementation of IsSampler()
+    EbtGSampler2D,       // non type: represents sampler2D, isampler2D, and usampler2D
+    EbtGSampler3D,       // non type: represents sampler3D, isampler3D, and usampler3D
+    EbtGSamplerCube,     // non type: represents samplerCube, isamplerCube, and usamplerCube
+    EbtGSampler2DArray,  // non type: represents sampler2DArray, isampler2DArray, and
+                         // usampler2DArray
+    EbtGSampler2DMS,     // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS
+
+    // images
+    EbtGuardImageBegin,
+    EbtImage2D,
+    EbtIImage2D,
+    EbtUImage2D,
+    EbtImage3D,
+    EbtIImage3D,
+    EbtUImage3D,
+    EbtImage2DArray,
+    EbtIImage2DArray,
+    EbtUImage2DArray,
+    EbtImageCube,
+    EbtIImageCube,
+    EbtUImageCube,
+    EbtGuardImageEnd,
+
+    EbtGuardGImageBegin,
+    EbtGImage2D,       // non type: represents image2D, uimage2D, iimage2D
+    EbtGImage3D,       // non type: represents image3D, uimage3D, iimage3D
+    EbtGImage2DArray,  // non type: represents image2DArray, uimage2DArray, iimage2DArray
+    EbtGImageCube,     // non type: represents imageCube, uimageCube, iimageCube
+    EbtGuardGImageEnd,
+
+    EbtStruct,
+    EbtInterfaceBlock,
+    EbtAddress,  // should be deprecated??
+
+    // end of list
+    EbtLast
+};
+
+inline TBasicType convertGImageToFloatImage(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtGImage2D:
+            return EbtImage2D;
+        case EbtGImage3D:
+            return EbtImage3D;
+        case EbtGImage2DArray:
+            return EbtImage2DArray;
+        case EbtGImageCube:
+            return EbtImageCube;
+        default:
+            UNREACHABLE();
+    }
+    return EbtLast;
+}
+
+inline TBasicType convertGImageToIntImage(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtGImage2D:
+            return EbtIImage2D;
+        case EbtGImage3D:
+            return EbtIImage3D;
+        case EbtGImage2DArray:
+            return EbtIImage2DArray;
+        case EbtGImageCube:
+            return EbtIImageCube;
+        default:
+            UNREACHABLE();
+    }
+    return EbtLast;
+}
+
+inline TBasicType convertGImageToUnsignedImage(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtGImage2D:
+            return EbtUImage2D;
+        case EbtGImage3D:
+            return EbtUImage3D;
+        case EbtGImage2DArray:
+            return EbtUImage2DArray;
+        case EbtGImageCube:
+            return EbtUImageCube;
+        default:
+            UNREACHABLE();
+    }
+    return EbtLast;
+}
+
+const char *getBasicString(TBasicType t);
+
+inline bool IsSampler(TBasicType type)
+{
+    return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
+}
+
+inline bool IsImage(TBasicType type)
+{
+    return type > EbtGuardImageBegin && type < EbtGuardImageEnd;
+}
+
+inline bool IsGImage(TBasicType type)
+{
+    return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
+}
+
+inline bool IsOpaqueType(TBasicType type)
+{
+    // TODO (mradev): add atomic types as opaque.
+    return IsSampler(type) || IsImage(type);
+}
+
+inline bool IsIntegerSampler(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtISampler2D:
+        case EbtISampler3D:
+        case EbtISamplerCube:
+        case EbtISampler2DArray:
+        case EbtISampler2DMS:
+        case EbtUSampler2D:
+        case EbtUSampler3D:
+        case EbtUSamplerCube:
+        case EbtUSampler2DArray:
+        case EbtUSampler2DMS:
+            return true;
+        case EbtSampler2D:
+        case EbtSampler3D:
+        case EbtSamplerCube:
+        case EbtSamplerExternalOES:
+        case EbtSamplerExternal2DY2YEXT:
+        case EbtSampler2DRect:
+        case EbtSampler2DArray:
+        case EbtSampler2DShadow:
+        case EbtSamplerCubeShadow:
+        case EbtSampler2DArrayShadow:
+        case EbtSampler2DMS:
+            return false;
+        default:
+            assert(!IsSampler(type));
+    }
+
+    return false;
+}
+
+inline bool IsSampler2DMS(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtSampler2DMS:
+        case EbtISampler2DMS:
+        case EbtUSampler2DMS:
+            return true;
+        default:
+            return false;
+    }
+}
+
+inline bool IsFloatImage(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtImage2D:
+        case EbtImage3D:
+        case EbtImage2DArray:
+        case EbtImageCube:
+            return true;
+        default:
+            break;
+    }
+
+    return false;
+}
+
+inline bool IsIntegerImage(TBasicType type)
+{
+
+    switch (type)
+    {
+        case EbtIImage2D:
+        case EbtIImage3D:
+        case EbtIImage2DArray:
+        case EbtIImageCube:
+            return true;
+        default:
+            break;
+    }
+
+    return false;
+}
+
+inline bool IsUnsignedImage(TBasicType type)
+{
+
+    switch (type)
+    {
+        case EbtUImage2D:
+        case EbtUImage3D:
+        case EbtUImage2DArray:
+        case EbtUImageCube:
+            return true;
+        default:
+            break;
+    }
+
+    return false;
+}
+
+inline bool IsSampler2D(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtSampler2D:
+        case EbtISampler2D:
+        case EbtUSampler2D:
+        case EbtSampler2DArray:
+        case EbtISampler2DArray:
+        case EbtUSampler2DArray:
+        case EbtSampler2DRect:
+        case EbtSamplerExternalOES:
+        case EbtSamplerExternal2DY2YEXT:
+        case EbtSampler2DShadow:
+        case EbtSampler2DArrayShadow:
+        case EbtSampler2DMS:
+        case EbtISampler2DMS:
+        case EbtUSampler2DMS:
+            return true;
+        case EbtSampler3D:
+        case EbtISampler3D:
+        case EbtUSampler3D:
+        case EbtISamplerCube:
+        case EbtUSamplerCube:
+        case EbtSamplerCube:
+        case EbtSamplerCubeShadow:
+            return false;
+        default:
+            assert(!IsSampler(type));
+    }
+
+    return false;
+}
+
+inline bool IsSamplerCube(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtSamplerCube:
+        case EbtISamplerCube:
+        case EbtUSamplerCube:
+        case EbtSamplerCubeShadow:
+            return true;
+        case EbtSampler2D:
+        case EbtSampler3D:
+        case EbtSamplerExternalOES:
+        case EbtSamplerExternal2DY2YEXT:
+        case EbtSampler2DRect:
+        case EbtSampler2DArray:
+        case EbtSampler2DMS:
+        case EbtISampler2D:
+        case EbtISampler3D:
+        case EbtISampler2DArray:
+        case EbtISampler2DMS:
+        case EbtUSampler2D:
+        case EbtUSampler3D:
+        case EbtUSampler2DArray:
+        case EbtUSampler2DMS:
+        case EbtSampler2DShadow:
+        case EbtSampler2DArrayShadow:
+            return false;
+        default:
+            assert(!IsSampler(type));
+    }
+
+    return false;
+}
+
+inline bool IsSampler3D(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtSampler3D:
+        case EbtISampler3D:
+        case EbtUSampler3D:
+            return true;
+        case EbtSampler2D:
+        case EbtSamplerCube:
+        case EbtSamplerExternalOES:
+        case EbtSamplerExternal2DY2YEXT:
+        case EbtSampler2DRect:
+        case EbtSampler2DArray:
+        case EbtSampler2DMS:
+        case EbtISampler2D:
+        case EbtISamplerCube:
+        case EbtISampler2DArray:
+        case EbtISampler2DMS:
+        case EbtUSampler2D:
+        case EbtUSamplerCube:
+        case EbtUSampler2DArray:
+        case EbtUSampler2DMS:
+        case EbtSampler2DShadow:
+        case EbtSamplerCubeShadow:
+        case EbtSampler2DArrayShadow:
+            return false;
+        default:
+            assert(!IsSampler(type));
+    }
+
+    return false;
+}
+
+inline bool IsSamplerArray(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtSampler2DArray:
+        case EbtISampler2DArray:
+        case EbtUSampler2DArray:
+        case EbtSampler2DArrayShadow:
+            return true;
+        case EbtSampler2D:
+        case EbtISampler2D:
+        case EbtUSampler2D:
+        case EbtSampler2DRect:
+        case EbtSamplerExternalOES:
+        case EbtSamplerExternal2DY2YEXT:
+        case EbtSampler3D:
+        case EbtISampler3D:
+        case EbtUSampler3D:
+        case EbtISamplerCube:
+        case EbtUSamplerCube:
+        case EbtSamplerCube:
+        case EbtSampler2DShadow:
+        case EbtSamplerCubeShadow:
+        case EbtSampler2DMS:
+        case EbtISampler2DMS:
+        case EbtUSampler2DMS:
+            return false;
+        default:
+            assert(!IsSampler(type));
+    }
+
+    return false;
+}
+
+inline bool IsShadowSampler(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtSampler2DShadow:
+        case EbtSamplerCubeShadow:
+        case EbtSampler2DArrayShadow:
+            return true;
+        case EbtISampler2D:
+        case EbtISampler3D:
+        case EbtISamplerCube:
+        case EbtISampler2DArray:
+        case EbtISampler2DMS:
+        case EbtUSampler2D:
+        case EbtUSampler3D:
+        case EbtUSamplerCube:
+        case EbtUSampler2DArray:
+        case EbtUSampler2DMS:
+        case EbtSampler2D:
+        case EbtSampler3D:
+        case EbtSamplerCube:
+        case EbtSamplerExternalOES:
+        case EbtSamplerExternal2DY2YEXT:
+        case EbtSampler2DRect:
+        case EbtSampler2DArray:
+        case EbtSampler2DMS:
+            return false;
+        default:
+            assert(!IsSampler(type));
+    }
+
+    return false;
+}
+
+inline bool IsInteger(TBasicType type)
+{
+    return type == EbtInt || type == EbtUInt;
+}
+
+inline bool SupportsPrecision(TBasicType type)
+{
+    return type == EbtFloat || type == EbtInt || type == EbtUInt || IsOpaqueType(type);
+}
+
+//
+// Qualifiers and built-ins.  These are mainly used to see what can be read
+// or written, and by the machine dependent translator to know which registers
+// to allocate variables in.  Since built-ins tend to go to different registers
+// than varying or uniform, it makes sense they are peers, not sub-classes.
+//
+enum TQualifier
+{
+    EvqTemporary,   // For temporaries (within a function), read/write
+    EvqGlobal,      // For globals read/write
+    EvqConst,       // User defined constants and non-output parameters in functions
+    EvqAttribute,   // Readonly
+    EvqVaryingIn,   // readonly, fragment shaders only
+    EvqVaryingOut,  // vertex shaders only  read/write
+    EvqUniform,     // Readonly, vertex and fragment
+
+    EvqVertexIn,     // Vertex shader input
+    EvqFragmentOut,  // Fragment shader output
+    EvqVertexOut,    // Vertex shader output
+    EvqFragmentIn,   // Fragment shader input
+
+    // parameters
+    EvqIn,
+    EvqOut,
+    EvqInOut,
+    EvqConstReadOnly,
+
+    // built-ins read by vertex shader
+    EvqInstanceID,
+    EvqVertexID,
+
+    // built-ins written by vertex shader
+    EvqPosition,
+    EvqPointSize,
+
+    // built-ins read by fragment shader
+    EvqFragCoord,
+    EvqFrontFacing,
+    EvqPointCoord,
+
+    // built-ins written by fragment shader
+    EvqFragColor,
+    EvqFragData,
+
+    EvqFragDepth,     // gl_FragDepth for ESSL300.
+    EvqFragDepthEXT,  // gl_FragDepthEXT for ESSL100, EXT_frag_depth.
+
+    EvqSecondaryFragColorEXT,  // EXT_blend_func_extended
+    EvqSecondaryFragDataEXT,   // EXT_blend_func_extended
+
+    EvqViewIDOVR,  // OVR_multiview
+
+    // built-ins written by the shader_framebuffer_fetch extension(s)
+    EvqLastFragColor,
+    EvqLastFragData,
+
+    // GLSL ES 3.0 vertex output and fragment input
+    EvqSmooth,    // Incomplete qualifier, smooth is the default
+    EvqFlat,      // Incomplete qualifier
+    EvqCentroid,  // Incomplete qualifier
+    EvqSmoothOut,
+    EvqFlatOut,
+    EvqCentroidOut,  // Implies smooth
+    EvqSmoothIn,
+    EvqFlatIn,
+    EvqCentroidIn,  // Implies smooth
+
+    // GLSL ES 3.1 compute shader special variables
+    EvqShared,
+    EvqComputeIn,
+    EvqNumWorkGroups,
+    EvqWorkGroupSize,
+    EvqWorkGroupID,
+    EvqLocalInvocationID,
+    EvqGlobalInvocationID,
+    EvqLocalInvocationIndex,
+
+    // GLSL ES 3.1 memory qualifiers
+    EvqReadOnly,
+    EvqWriteOnly,
+    EvqCoherent,
+    EvqRestrict,
+    EvqVolatile,
+
+    // end of list
+    EvqLast
+};
+
+inline bool IsQualifierUnspecified(TQualifier qualifier)
+{
+    return (qualifier == EvqTemporary || qualifier == EvqGlobal);
+}
+
+enum TLayoutImageInternalFormat
+{
+    EiifUnspecified,
+    EiifRGBA32F,
+    EiifRGBA16F,
+    EiifR32F,
+    EiifRGBA32UI,
+    EiifRGBA16UI,
+    EiifRGBA8UI,
+    EiifR32UI,
+    EiifRGBA32I,
+    EiifRGBA16I,
+    EiifRGBA8I,
+    EiifR32I,
+    EiifRGBA8,
+    EiifRGBA8_SNORM
+};
+
+enum TLayoutMatrixPacking
+{
+    EmpUnspecified,
+    EmpRowMajor,
+    EmpColumnMajor
+};
+
+enum TLayoutBlockStorage
+{
+    EbsUnspecified,
+    EbsShared,
+    EbsPacked,
+    EbsStd140
+};
+
+enum TYuvCscStandardEXT
+{
+    EycsUndefined,
+    EycsItu601,
+    EycsItu601FullRange,
+    EycsItu709
+};
+
+struct TLayoutQualifier
+{
+    int location;
+    unsigned int locationsSpecified;
+    TLayoutMatrixPacking matrixPacking;
+    TLayoutBlockStorage blockStorage;
+
+    // Compute shader layout qualifiers.
+    sh::WorkGroupSize localSize;
+
+    int binding;
+
+    // Image format layout qualifier
+    TLayoutImageInternalFormat imageInternalFormat;
+
+    // OVR_multiview num_views.
+    int numViews;
+
+    // EXT_YUV_target yuv layout qualifier.
+    bool yuv;
+
+    static TLayoutQualifier create()
+    {
+        TLayoutQualifier layoutQualifier;
+
+        layoutQualifier.location           = -1;
+        layoutQualifier.locationsSpecified = 0;
+        layoutQualifier.matrixPacking      = EmpUnspecified;
+        layoutQualifier.blockStorage       = EbsUnspecified;
+
+        layoutQualifier.localSize.fill(-1);
+        layoutQualifier.binding  = -1;
+        layoutQualifier.numViews = -1;
+        layoutQualifier.yuv      = false;
+
+        layoutQualifier.imageInternalFormat = EiifUnspecified;
+        return layoutQualifier;
+    }
+
+    bool isEmpty() const
+    {
+        return location == -1 && binding == -1 && numViews == -1 && yuv == false &&
+               matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified &&
+               !localSize.isAnyValueSet() && imageInternalFormat == EiifUnspecified;
+    }
+
+    bool isCombinationValid() const
+    {
+        bool workSizeSpecified = localSize.isAnyValueSet();
+        bool numViewsSet       = (numViews != -1);
+        bool otherLayoutQualifiersSpecified =
+            (location != -1 || binding != -1 || matrixPacking != EmpUnspecified ||
+             blockStorage != EbsUnspecified || imageInternalFormat != EiifUnspecified);
+
+        // we can have either the work group size specified, or number of views,
+        // or yuv layout qualifier, or the other layout qualifiers.
+        return (workSizeSpecified ? 1 : 0) + (numViewsSet ? 1 : 0) + (yuv ? 1 : 0) +
+                   (otherLayoutQualifiersSpecified ? 1 : 0) <=
+               1;
+    }
+
+    bool isLocalSizeEqual(const sh::WorkGroupSize &localSizeIn) const
+    {
+        return localSize.isWorkGroupSizeMatching(localSizeIn);
+    }
+};
+
+struct TMemoryQualifier
+{
+    // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+    // An image can be qualified as both readonly and writeonly. It still can be can be used with
+    // imageSize().
+    bool readonly;
+    bool writeonly;
+    bool coherent;
+
+    // restrict and volatile are reserved keywords in C/C++
+    bool restrictQualifier;
+    bool volatileQualifier;
+    static TMemoryQualifier create()
+    {
+        TMemoryQualifier memoryQualifier;
+
+        memoryQualifier.readonly          = false;
+        memoryQualifier.writeonly         = false;
+        memoryQualifier.coherent          = false;
+        memoryQualifier.restrictQualifier = false;
+        memoryQualifier.volatileQualifier = false;
+
+        return memoryQualifier;
+    }
+
+    bool isEmpty()
+    {
+        return !readonly && !writeonly && !coherent && !restrictQualifier && !volatileQualifier;
+    }
+};
+
+inline const char *getWorkGroupSizeString(size_t dimension)
+{
+    switch (dimension)
+    {
+        case 0u:
+            return "local_size_x";
+        case 1u:
+            return "local_size_y";
+        case 2u:
+            return "local_size_z";
+        default:
+            UNREACHABLE();
+            return "dimension out of bounds";
+    }
+}
+
+//
+// This is just for debug print out, carried along with the definitions above.
+//
+inline const char *getQualifierString(TQualifier q)
+{
+    // clang-format off
+    switch(q)
+    {
+    case EvqTemporary:              return "Temporary";
+    case EvqGlobal:                 return "Global";
+    case EvqConst:                  return "const";
+    case EvqAttribute:              return "attribute";
+    case EvqVaryingIn:              return "varying";
+    case EvqVaryingOut:             return "varying";
+    case EvqUniform:                return "uniform";
+    case EvqVertexIn:               return "in";
+    case EvqFragmentOut:            return "out";
+    case EvqVertexOut:              return "out";
+    case EvqFragmentIn:             return "in";
+    case EvqIn:                     return "in";
+    case EvqOut:                    return "out";
+    case EvqInOut:                  return "inout";
+    case EvqConstReadOnly:          return "const";
+    case EvqInstanceID:             return "InstanceID";
+    case EvqVertexID:               return "VertexID";
+    case EvqPosition:               return "Position";
+    case EvqPointSize:              return "PointSize";
+    case EvqFragCoord:              return "FragCoord";
+    case EvqFrontFacing:            return "FrontFacing";
+    case EvqPointCoord:             return "PointCoord";
+    case EvqFragColor:              return "FragColor";
+    case EvqFragData:               return "FragData";
+    case EvqFragDepthEXT:           return "FragDepth";
+    case EvqFragDepth:              return "FragDepth";
+    case EvqSecondaryFragColorEXT:  return "SecondaryFragColorEXT";
+    case EvqSecondaryFragDataEXT:   return "SecondaryFragDataEXT";
+    case EvqViewIDOVR:              return "ViewIDOVR";
+    case EvqLastFragColor:          return "LastFragColor";
+    case EvqLastFragData:           return "LastFragData";
+    case EvqSmoothOut:              return "smooth out";
+    case EvqCentroidOut:            return "smooth centroid out";
+    case EvqFlatOut:                return "flat out";
+    case EvqSmoothIn:               return "smooth in";
+    case EvqFlatIn:                 return "flat in";
+    case EvqCentroidIn:             return "smooth centroid in";
+    case EvqCentroid:               return "centroid";
+    case EvqFlat:                   return "flat";
+    case EvqSmooth:                 return "smooth";
+    case EvqShared:                 return "shared";
+    case EvqComputeIn:              return "in";
+    case EvqNumWorkGroups:          return "NumWorkGroups";
+    case EvqWorkGroupSize:          return "WorkGroupSize";
+    case EvqWorkGroupID:            return "WorkGroupID";
+    case EvqLocalInvocationID:      return "LocalInvocationID";
+    case EvqGlobalInvocationID:     return "GlobalInvocationID";
+    case EvqLocalInvocationIndex:   return "LocalInvocationIndex";
+    case EvqReadOnly:               return "readonly";
+    case EvqWriteOnly:              return "writeonly";
+    default: UNREACHABLE();         return "unknown qualifier";
+    }
+    // clang-format on
+}
+
+inline const char *getMatrixPackingString(TLayoutMatrixPacking mpq)
+{
+    switch (mpq)
+    {
+        case EmpUnspecified:
+            return "mp_unspecified";
+        case EmpRowMajor:
+            return "row_major";
+        case EmpColumnMajor:
+            return "column_major";
+        default:
+            UNREACHABLE();
+            return "unknown matrix packing";
+    }
+}
+
+inline const char *getBlockStorageString(TLayoutBlockStorage bsq)
+{
+    switch (bsq)
+    {
+        case EbsUnspecified:
+            return "bs_unspecified";
+        case EbsShared:
+            return "shared";
+        case EbsPacked:
+            return "packed";
+        case EbsStd140:
+            return "std140";
+        default:
+            UNREACHABLE();
+            return "unknown block storage";
+    }
+}
+
+inline const char *getImageInternalFormatString(TLayoutImageInternalFormat iifq)
+{
+    switch (iifq)
+    {
+        case EiifRGBA32F:
+            return "rgba32f";
+        case EiifRGBA16F:
+            return "rgba16f";
+        case EiifR32F:
+            return "r32f";
+        case EiifRGBA32UI:
+            return "rgba32ui";
+        case EiifRGBA16UI:
+            return "rgba16ui";
+        case EiifRGBA8UI:
+            return "rgba8ui";
+        case EiifR32UI:
+            return "r32ui";
+        case EiifRGBA32I:
+            return "rgba32i";
+        case EiifRGBA16I:
+            return "rgba16i";
+        case EiifRGBA8I:
+            return "rgba8i";
+        case EiifR32I:
+            return "r32i";
+        case EiifRGBA8:
+            return "rgba8";
+        case EiifRGBA8_SNORM:
+            return "rgba8_snorm";
+        default:
+            UNREACHABLE();
+            return "unknown internal image format";
+    }
+}
+
+inline TYuvCscStandardEXT getYuvCscStandardEXT(const std::string &str)
+{
+    if (str == "itu_601")
+        return EycsItu601;
+    else if (str == "itu_601_full_range")
+        return EycsItu601FullRange;
+    else if (str == "itu_709")
+        return EycsItu709;
+    return EycsUndefined;
+}
+
+inline const char *getYuvCscStandardEXTString(TYuvCscStandardEXT ycsq)
+{
+    switch (ycsq)
+    {
+        case EycsItu601:
+            return "itu_601";
+        case EycsItu601FullRange:
+            return "itu_601_full_range";
+        case EycsItu709:
+            return "itu_709";
+        default:
+            UNREACHABLE();
+            return "unknown color space conversion standard";
+    }
+}
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_BASETYPES_H_
diff --git a/src/third_party/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp b/src/third_party/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
new file mode 100644
index 0000000..018e72c
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
@@ -0,0 +1,106 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
+//      may record a variable as aliasing another. Sometimes the alias information gets garbled
+//      so we work around this issue by breaking the aliasing chain in inner loops.
+
+#include "BreakVariableAliasingInInnerLoops.h"
+
+#include "compiler/translator/IntermNode.h"
+
+// A HLSL compiler developer gave us more details on the root cause and the workaround needed:
+//     The root problem is that if the HLSL compiler is applying aliasing information even on
+//     incomplete simulations (in this case, a single pass). The bug is triggered by an assignment
+//     that comes from a series of assignments, possibly with swizzled or ternary operators with
+//     known conditionals, where the source is before the loop.
+//     So, a workaround is to add a +0 term to variables the first time they are assigned to in
+//     an inner loop (if they are declared in an outside scope, otherwise there is no need).
+//     This will break the aliasing chain.
+
+// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because
+// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure
+// assignment don't need a workaround.
+
+namespace sh
+{
+
+namespace
+{
+
+class AliasingBreaker : public TIntermTraverser
+{
+  public:
+    AliasingBreaker() : TIntermTraverser(true, false, true) {}
+
+  protected:
+    bool visitBinary(Visit visit, TIntermBinary *binary)
+    {
+        if (visit != PreVisit)
+        {
+            return false;
+        }
+
+        if (mLoopLevel < 2 || !binary->isAssignment())
+        {
+            return true;
+        }
+
+        TIntermTyped *B = binary->getRight();
+        TType type      = B->getType();
+
+        if (!type.isScalar() && !type.isVector() && !type.isMatrix())
+        {
+            return true;
+        }
+
+        if (type.isArray() || IsSampler(type.getBasicType()))
+        {
+            return true;
+        }
+
+        // We have a scalar / vector / matrix assignment with loop depth 2.
+        // Transform it from
+        //    A = B
+        // to
+        //    A = (B + typeof<B>(0));
+
+        TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, TIntermTyped::CreateZero(type));
+        bPlusZero->setLine(B->getLine());
+
+        binary->replaceChildNode(B, bPlusZero);
+
+        return true;
+    }
+
+    bool visitLoop(Visit visit, TIntermLoop *loop)
+    {
+        if (visit == PreVisit)
+        {
+            mLoopLevel++;
+        }
+        else
+        {
+            ASSERT(mLoopLevel > 0);
+            mLoopLevel--;
+        }
+
+        return true;
+    }
+
+  private:
+    int mLoopLevel = 0;
+};
+
+}  // anonymous namespace
+
+void BreakVariableAliasingInInnerLoops(TIntermNode *root)
+{
+    AliasingBreaker breaker;
+    root->traverse(&breaker);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h b/src/third_party/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
new file mode 100644
index 0000000..b1d906f
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
+//      may record a variable as aliasing another. Sometimes the alias information gets garbled
+//      so we work around this issue by breaking the aliasing chain in inner loops.
+
+#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
+#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
+
+class TIntermNode;
+
+namespace sh
+{
+
+void BreakVariableAliasingInInnerLoops(TIntermNode *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
diff --git a/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
new file mode 100644
index 0000000..8b7d9f8
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
@@ -0,0 +1,336 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "angle_gl.h"
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/Cache.h"
+
+namespace sh
+{
+
+class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
+{
+  public:
+    BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator)
+        : TIntermTraverser(true, false, false), mEmulator(emulator)
+    {
+    }
+
+    bool visitUnary(Visit visit, TIntermUnary *node) override
+    {
+        if (visit == PreVisit)
+        {
+            bool needToEmulate =
+                mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
+            if (needToEmulate)
+                node->setUseEmulatedFunction();
+        }
+        return true;
+    }
+
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override
+    {
+        if (visit == PreVisit)
+        {
+            // Here we handle all the built-in functions mapped to ops, not just the ones that are
+            // currently identified as problematic.
+            if (node->isConstructor() || node->isFunctionCall())
+            {
+                return true;
+            }
+            const TIntermSequence &sequence = *(node->getSequence());
+            bool needToEmulate              = false;
+            // Right now we only handle built-in functions with two or three parameters.
+            if (sequence.size() == 2)
+            {
+                TIntermTyped *param1 = sequence[0]->getAsTyped();
+                TIntermTyped *param2 = sequence[1]->getAsTyped();
+                if (!param1 || !param2)
+                    return true;
+                needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
+                                                            param2->getType());
+            }
+            else if (sequence.size() == 3)
+            {
+                TIntermTyped *param1 = sequence[0]->getAsTyped();
+                TIntermTyped *param2 = sequence[1]->getAsTyped();
+                TIntermTyped *param3 = sequence[2]->getAsTyped();
+                if (!param1 || !param2 || !param3)
+                    return true;
+                needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
+                                                            param2->getType(), param3->getType());
+            }
+            else if (sequence.size() == 4)
+            {
+                TIntermTyped *param1 = sequence[0]->getAsTyped();
+                TIntermTyped *param2 = sequence[1]->getAsTyped();
+                TIntermTyped *param3 = sequence[2]->getAsTyped();
+                TIntermTyped *param4 = sequence[3]->getAsTyped();
+                if (!param1 || !param2 || !param3 || !param4)
+                    return true;
+                needToEmulate =
+                    mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(),
+                                                param3->getType(), param4->getType());
+            }
+            else
+            {
+                return true;
+            }
+
+            if (needToEmulate)
+                node->setUseEmulatedFunction();
+        }
+        return true;
+    }
+
+  private:
+    BuiltInFunctionEmulator &mEmulator;
+};
+
+BuiltInFunctionEmulator::BuiltInFunctionEmulator()
+{
+}
+
+BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction(
+    TOperator op,
+    const TType *param,
+    const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param);
+    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+    return id;
+}
+
+BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction(
+    TOperator op,
+    const TType *param1,
+    const TType *param2,
+    const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param1, param2);
+    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+    return id;
+}
+
+BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+    FunctionId dependency,
+    TOperator op,
+    const TType *param1,
+    const TType *param2,
+    const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param1, param2);
+    mEmulatedFunctions[id]    = std::string(emulatedFunctionDefinition);
+    mFunctionDependencies[id] = dependency;
+    return id;
+}
+
+BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction(
+    TOperator op,
+    const TType *param1,
+    const TType *param2,
+    const TType *param3,
+    const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param1, param2, param3);
+    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+    return id;
+}
+
+BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction(
+    TOperator op,
+    const TType *param1,
+    const TType *param2,
+    const TType *param3,
+    const TType *param4,
+    const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param1, param2, param3, param4);
+    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+    return id;
+}
+
+BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+    FunctionId dependency,
+    TOperator op,
+    const TType *param1,
+    const TType *param2,
+    const TType *param3,
+    const TType *param4,
+    const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param1, param2, param3, param4);
+    mEmulatedFunctions[id]    = std::string(emulatedFunctionDefinition);
+    mFunctionDependencies[id] = dependency;
+    return id;
+}
+
+bool BuiltInFunctionEmulator::isOutputEmpty() const
+{
+    return (mFunctions.size() == 0);
+}
+
+void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
+{
+    for (size_t i = 0; i < mFunctions.size(); ++i)
+    {
+        out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n";
+    }
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param)
+{
+    return setFunctionCalled(FunctionId(op, &param));
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+                                                const TType &param1,
+                                                const TType &param2)
+{
+    return setFunctionCalled(FunctionId(op, &param1, &param2));
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+                                                const TType &param1,
+                                                const TType &param2,
+                                                const TType &param3)
+{
+    return setFunctionCalled(FunctionId(op, &param1, &param2, &param3));
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+                                                const TType &param1,
+                                                const TType &param2,
+                                                const TType &param3,
+                                                const TType &param4)
+{
+    return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId)
+{
+    if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end())
+    {
+        for (size_t i = 0; i < mFunctions.size(); ++i)
+        {
+            if (mFunctions[i] == functionId)
+                return true;
+        }
+        // If the function depends on another, mark the dependency as called.
+        auto dependency = mFunctionDependencies.find(functionId);
+        if (dependency != mFunctionDependencies.end())
+        {
+            setFunctionCalled((*dependency).second);
+        }
+        // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
+        // remain valid and constant.
+        mFunctions.push_back(functionId.getCopy());
+        return true;
+    }
+    return false;
+}
+
+void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root)
+{
+    ASSERT(root);
+
+    if (mEmulatedFunctions.empty())
+        return;
+
+    BuiltInFunctionEmulationMarker marker(*this);
+    root->traverse(&marker);
+}
+
+void BuiltInFunctionEmulator::cleanup()
+{
+    mFunctions.clear();
+    mFunctionDependencies.clear();
+}
+
+// static
+void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
+{
+    ASSERT(name[strlen(name) - 1] != '(');
+    out << "webgl_" << name << "_emu";
+}
+
+BuiltInFunctionEmulator::FunctionId::FunctionId()
+    : mOp(EOpNull),
+      mParam1(TCache::getType(EbtVoid)),
+      mParam2(TCache::getType(EbtVoid)),
+      mParam3(TCache::getType(EbtVoid)),
+      mParam4(TCache::getType(EbtVoid))
+{
+}
+
+BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param)
+    : mOp(op),
+      mParam1(param),
+      mParam2(TCache::getType(EbtVoid)),
+      mParam3(TCache::getType(EbtVoid)),
+      mParam4(TCache::getType(EbtVoid))
+{
+}
+
+BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op,
+                                                const TType *param1,
+                                                const TType *param2)
+    : mOp(op),
+      mParam1(param1),
+      mParam2(param2),
+      mParam3(TCache::getType(EbtVoid)),
+      mParam4(TCache::getType(EbtVoid))
+{
+}
+
+BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op,
+                                                const TType *param1,
+                                                const TType *param2,
+                                                const TType *param3)
+    : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(TCache::getType(EbtVoid))
+{
+}
+
+BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op,
+                                                const TType *param1,
+                                                const TType *param2,
+                                                const TType *param3,
+                                                const TType *param4)
+    : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4)
+{
+}
+
+bool BuiltInFunctionEmulator::FunctionId::operator==(
+    const BuiltInFunctionEmulator::FunctionId &other) const
+{
+    return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 &&
+            *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4);
+}
+
+bool BuiltInFunctionEmulator::FunctionId::operator<(
+    const BuiltInFunctionEmulator::FunctionId &other) const
+{
+    if (mOp != other.mOp)
+        return mOp < other.mOp;
+    if (*mParam1 != *other.mParam1)
+        return *mParam1 < *other.mParam1;
+    if (*mParam2 != *other.mParam2)
+        return *mParam2 < *other.mParam2;
+    if (*mParam3 != *other.mParam3)
+        return *mParam3 < *other.mParam3;
+    if (*mParam4 != *other.mParam4)
+        return *mParam4 < *other.mParam4;
+    return false;  // all fields are equal
+}
+
+BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::FunctionId::getCopy() const
+{
+    return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
+                      new TType(*mParam4));
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulator.h
new file mode 100644
index 0000000..cbb1b25
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulator.h
@@ -0,0 +1,137 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
+#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+//
+// This class decides which built-in functions need to be replaced with the emulated ones. It can be
+// used to work around driver bugs or implement functions that are not natively implemented on a
+// specific platform.
+//
+class BuiltInFunctionEmulator
+{
+  public:
+    BuiltInFunctionEmulator();
+
+    void markBuiltInFunctionsForEmulation(TIntermNode *root);
+
+    void cleanup();
+
+    // "name" gets written as "webgl_name_emu".
+    static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name);
+
+    bool isOutputEmpty() const;
+
+    // Output function emulation definition. This should be before any other shader source.
+    void outputEmulatedFunctions(TInfoSinkBase &out) const;
+
+    class FunctionId
+    {
+      public:
+        FunctionId();
+        FunctionId(TOperator op, const TType *param);
+        FunctionId(TOperator op, const TType *param1, const TType *param2);
+        FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
+        FunctionId(TOperator op,
+                   const TType *param1,
+                   const TType *param2,
+                   const TType *param3,
+                   const TType *param4);
+
+        FunctionId(const FunctionId &) = default;
+        FunctionId &operator=(const FunctionId &) = default;
+
+        bool operator==(const FunctionId &other) const;
+        bool operator<(const FunctionId &other) const;
+
+        FunctionId getCopy() const;
+
+      private:
+        TOperator mOp;
+
+        // The memory that these TType objects use is freed by PoolAllocator. The
+        // BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but
+        // that's not an issue since this class never destructs these objects.
+        const TType *mParam1;
+        const TType *mParam2;
+        const TType *mParam3;
+        const TType *mParam4;
+    };
+
+    // Add functions that need to be emulated.
+    FunctionId addEmulatedFunction(TOperator op,
+                                   const TType *param,
+                                   const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunction(TOperator op,
+                                   const TType *param1,
+                                   const TType *param2,
+                                   const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunction(TOperator op,
+                                   const TType *param1,
+                                   const TType *param2,
+                                   const TType *param3,
+                                   const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunction(TOperator op,
+                                   const TType *param1,
+                                   const TType *param2,
+                                   const TType *param3,
+                                   const TType *param4,
+                                   const char *emulatedFunctionDefinition);
+
+    FunctionId addEmulatedFunctionWithDependency(FunctionId dependency,
+                                                 TOperator op,
+                                                 const TType *param1,
+                                                 const TType *param2,
+                                                 const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunctionWithDependency(FunctionId dependency,
+                                                 TOperator op,
+                                                 const TType *param1,
+                                                 const TType *param2,
+                                                 const TType *param3,
+                                                 const TType *param4,
+                                                 const char *emulatedFunctionDefinition);
+
+  private:
+    class BuiltInFunctionEmulationMarker;
+
+    // Records that a function is called by the shader and might need to be emulated. If the
+    // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
+    // call needs to be replaced with an emulated one.
+    bool setFunctionCalled(TOperator op, const TType &param);
+    bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2);
+    bool setFunctionCalled(TOperator op,
+                           const TType &param1,
+                           const TType &param2,
+                           const TType &param3);
+    bool setFunctionCalled(TOperator op,
+                           const TType &param1,
+                           const TType &param2,
+                           const TType &param3,
+                           const TType &param4);
+
+    bool setFunctionCalled(const FunctionId &functionId);
+
+    // Map from function id to emulated function definition
+    std::map<FunctionId, std::string> mEmulatedFunctions;
+
+    // Map from dependent functions to their dependencies. This structure allows each function to
+    // have at most one dependency.
+    std::map<FunctionId, FunctionId> mFunctionDependencies;
+
+    // Called function ids
+    std::vector<FunctionId> mFunctions;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
diff --git a/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
new file mode 100644
index 0000000..dada53b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
@@ -0,0 +1,293 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "angle_gl.h"
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
+#include "compiler/translator/Cache.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/VersionGLSL.h"
+
+namespace sh
+{
+
+void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
+                                                      sh::GLenum shaderType)
+{
+    if (shaderType == GL_VERTEX_SHADER)
+    {
+        const TType *int1 = TCache::getType(EbtInt);
+        emu->addEmulatedFunction(EOpAbs, int1, "int webgl_abs_emu(int x) { return x * sign(x); }");
+    }
+}
+
+void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
+                                                        int targetGLSLVersion)
+{
+    // isnan() is supported since GLSL 1.3.
+    if (targetGLSLVersion < GLSL_VERSION_130)
+        return;
+
+    const TType *float1 = TCache::getType(EbtFloat);
+    const TType *float2 = TCache::getType(EbtFloat, 2);
+    const TType *float3 = TCache::getType(EbtFloat, 3);
+    const TType *float4 = TCache::getType(EbtFloat, 4);
+
+    // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
+    emu->addEmulatedFunction(
+        EOpIsNan, float1,
+        "bool webgl_isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
+    emu->addEmulatedFunction(
+        EOpIsNan, float2,
+        "bvec2 webgl_isnan_emu(vec2 x)\n"
+        "{\n"
+        "    bvec2 isnan;\n"
+        "    for (int i = 0; i < 2; i++)\n"
+        "    {\n"
+        "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
+        "    }\n"
+        "    return isnan;\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpIsNan, float3,
+        "bvec3 webgl_isnan_emu(vec3 x)\n"
+        "{\n"
+        "    bvec3 isnan;\n"
+        "    for (int i = 0; i < 3; i++)\n"
+        "    {\n"
+        "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
+        "    }\n"
+        "    return isnan;\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpIsNan, float4,
+        "bvec4 webgl_isnan_emu(vec4 x)\n"
+        "{\n"
+        "    bvec4 isnan;\n"
+        "    for (int i = 0; i < 4; i++)\n"
+        "    {\n"
+        "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
+        "    }\n"
+        "    return isnan;\n"
+        "}\n");
+}
+
+void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
+{
+    const TType *float1 = TCache::getType(EbtFloat);
+    auto floatFuncId    = emu->addEmulatedFunction(
+        EOpAtan, float1, float1,
+        "webgl_emu_precision float webgl_atan_emu(webgl_emu_precision float y, webgl_emu_precision "
+        "float x)\n"
+        "{\n"
+        "    if (x > 0.0) return atan(y / x);\n"
+        "    else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
+        "    else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
+        "    else return 1.57079632 * sign(y);\n"
+        "}\n");
+    for (int dim = 2; dim <= 4; ++dim)
+    {
+        const TType *floatVec = TCache::getType(EbtFloat, static_cast<unsigned char>(dim));
+        std::stringstream ss;
+        ss << "webgl_emu_precision vec" << dim << " webgl_atan_emu(webgl_emu_precision vec" << dim
+           << " y, webgl_emu_precision vec" << dim << " x)\n"
+                                                      "{\n"
+                                                      "    return vec"
+           << dim << "(";
+        for (int i = 0; i < dim; ++i)
+        {
+            ss << "webgl_atan_emu(y[" << i << "], x[" << i << "])";
+            if (i < dim - 1)
+            {
+                ss << ", ";
+            }
+        }
+        ss << ");\n"
+              "}\n";
+        emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec,
+                                               ss.str().c_str());
+    }
+}
+
+// Emulate built-in functions missing from GLSL 1.30 and higher
+void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu,
+                                                        sh::GLenum shaderType,
+                                                        int targetGLSLVersion)
+{
+    // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
+    if (targetGLSLVersion < GLSL_VERSION_410)
+    {
+        const TType *float2 = TCache::getType(EbtFloat, 2);
+        const TType *uint1  = TCache::getType(EbtUInt);
+
+        // clang-format off
+        emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
+            "uint webgl_packUnorm2x16_emu(vec2 v)\n"
+            "{\n"
+            "    int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
+            "    int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n"
+            "    return uint((y << 16) | (x & 0xFFFF));\n"
+            "}\n");
+
+        emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
+            "vec2 webgl_unpackUnorm2x16_emu(uint u)\n"
+            "{\n"
+            "    float x = float(u & 0xFFFFu) / 65535.0;\n"
+            "    float y = float(u >> 16) / 65535.0;\n"
+            "    return vec2(x, y);\n"
+            "}\n");
+        // clang-format on
+    }
+
+    // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20)
+    // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
+    if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
+    {
+        const TType *float2 = TCache::getType(EbtFloat, 2);
+        const TType *uint1  = TCache::getType(EbtUInt);
+
+        // clang-format off
+        emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
+            "uint webgl_packSnorm2x16_emu(vec2 v)\n"
+            "{\n"
+            "    #if defined(GL_ARB_shading_language_packing)\n"
+            "        return packSnorm2x16(v);\n"
+            "    #else\n"
+            "        int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n"
+            "        int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n"
+            "        return uint((y << 16) | (x & 0xFFFF));\n"
+            "    #endif\n"
+            "}\n");
+        emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
+            "#if !defined(GL_ARB_shading_language_packing)\n"
+            "    float webgl_fromSnorm(uint x)\n"
+            "    {\n"
+            "        int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
+            "        return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
+            "    }\n"
+            "#endif\n"
+            "\n"
+            "vec2 webgl_unpackSnorm2x16_emu(uint u)\n"
+            "{\n"
+            "    #if defined(GL_ARB_shading_language_packing)\n"
+            "        return unpackSnorm2x16(u);\n"
+            "    #else\n"
+            "        uint y = (u >> 16);\n"
+            "        uint x = u;\n"
+            "        return vec2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
+            "    #endif\n"
+            "}\n");
+        // Functions uint webgl_f32tof16(float val) and float webgl_f16tof32(uint val) are
+        // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
+        emu->addEmulatedFunction(EOpPackHalf2x16, float2,
+            "#if !defined(GL_ARB_shading_language_packing)\n"
+            "    uint webgl_f32tof16(float val)\n"
+            "    {\n"
+            "        uint f32 = floatBitsToUint(val);\n"
+            "        uint f16 = 0u;\n"
+            "        uint sign = (f32 >> 16) & 0x8000u;\n"
+            "        int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
+            "        uint mantissa = f32 & 0x007FFFFFu;\n"
+            "        if (exponent == 128)\n"
+            "        {\n"
+            "            // Infinity or NaN\n"
+            "            // NaN bits that are masked out by 0x3FF get discarded.\n"
+            "            // This can turn some NaNs to infinity, but this is allowed by the spec.\n"
+            "            f16 = sign | (0x1Fu << 10);\n"
+            "            f16 |= (mantissa & 0x3FFu);\n"
+            "        }\n"
+            "        else if (exponent > 15)\n"
+            "        {\n"
+            "            // Overflow - flush to Infinity\n"
+            "            f16 = sign | (0x1Fu << 10);\n"
+            "        }\n"
+            "        else if (exponent > -15)\n"
+            "        {\n"
+            "            // Representable value\n"
+            "            exponent += 15;\n"
+            "            mantissa >>= 13;\n"
+            "            f16 = sign | uint(exponent << 10) | mantissa;\n"
+            "        }\n"
+            "        else\n"
+            "        {\n"
+            "            f16 = sign;\n"
+            "        }\n"
+            "        return f16;\n"
+            "    }\n"
+            "#endif\n"
+            "\n"
+            "uint webgl_packHalf2x16_emu(vec2 v)\n"
+            "{\n"
+            "    #if defined(GL_ARB_shading_language_packing)\n"
+            "        return packHalf2x16(v);\n"
+            "    #else\n"
+            "        uint x = webgl_f32tof16(v.x);\n"
+            "        uint y = webgl_f32tof16(v.y);\n"
+            "        return (y << 16) | x;\n"
+            "    #endif\n"
+            "}\n");
+        emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
+            "#if !defined(GL_ARB_shading_language_packing)\n"
+            "    float webgl_f16tof32(uint val)\n"
+            "    {\n"
+            "        uint sign = (val & 0x8000u) << 16;\n"
+            "        int exponent = int((val & 0x7C00u) >> 10);\n"
+            "        uint mantissa = val & 0x03FFu;\n"
+            "        float f32 = 0.0;\n"
+            "        if(exponent == 0)\n"
+            "        {\n"
+            "            if (mantissa != 0u)\n"
+            "            {\n"
+            "                const float scale = 1.0 / (1 << 24);\n"
+            "                f32 = scale * mantissa;\n"
+            "            }\n"
+            "        }\n"
+            "        else if (exponent == 31)\n"
+            "        {\n"
+            "            return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n"
+            "        }\n"
+            "        else\n"
+            "        {\n"
+            "            exponent -= 15;\n"
+            "            float scale;\n"
+            "            if(exponent < 0)\n"
+            "            {\n"
+            "                // The negative unary operator is buggy on OSX.\n"
+            "                // Work around this by using abs instead.\n"
+            "                scale = 1.0 / (1 << abs(exponent));\n"
+            "            }\n"
+            "            else\n"
+            "            {\n"
+            "                scale = 1 << exponent;\n"
+            "            }\n"
+            "            float decimal = 1.0 + float(mantissa) / float(1 << 10);\n"
+            "            f32 = scale * decimal;\n"
+            "        }\n"
+            "\n"
+            "        if (sign != 0u)\n"
+            "        {\n"
+            "            f32 = -f32;\n"
+            "        }\n"
+            "\n"
+            "        return f32;\n"
+            "    }\n"
+            "#endif\n"
+            "\n"
+            "vec2 webgl_unpackHalf2x16_emu(uint u)\n"
+            "{\n"
+            "    #if defined(GL_ARB_shading_language_packing)\n"
+            "        return unpackHalf2x16(u);\n"
+            "    #else\n"
+            "        uint y = (u >> 16);\n"
+            "        uint x = u & 0xFFFFu;\n"
+            "        return vec2(webgl_f16tof32(x), webgl_f16tof32(y));\n"
+            "    #endif\n"
+            "}\n");
+        // clang-format on
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h
new file mode 100644
index 0000000..e1b4779
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
+#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+class BuiltInFunctionEmulator;
+
+//
+// This works around bug in Intel Mac drivers.
+//
+void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
+                                                      sh::GLenum shaderType);
+
+//
+// This works around isnan() bug in Intel Mac drivers
+//
+void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
+                                                        int targetGLSLVersion);
+//
+// This works around atan(y, x) bug in NVIDIA drivers.
+//
+void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu);
+
+//
+// This function is emulating built-in functions missing from GLSL 1.30 and higher.
+//
+void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu,
+                                                        sh::GLenum shaderType,
+                                                        int targetGLSLVersion);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
new file mode 100644
index 0000000..6d4ace3
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
@@ -0,0 +1,1047 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "angle_gl.h"
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/VersionGLSL.h"
+
+namespace sh
+{
+
+void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
+                                                        int targetGLSLVersion)
+{
+    if (targetGLSLVersion < GLSL_VERSION_130)
+        return;
+
+    TType *float1 = new TType(EbtFloat);
+    TType *float2 = new TType(EbtFloat, 2);
+    TType *float3 = new TType(EbtFloat, 3);
+    TType *float4 = new TType(EbtFloat, 4);
+
+    emu->addEmulatedFunction(EOpIsNan, float1,
+                             "bool webgl_isnan_emu(float x)\n"
+                             "{\n"
+                             "    return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
+                             "}\n"
+                             "\n");
+
+    emu->addEmulatedFunction(
+        EOpIsNan, float2,
+        "bool2 webgl_isnan_emu(float2 x)\n"
+        "{\n"
+        "    bool2 isnan;\n"
+        "    for (int i = 0; i < 2; i++)\n"
+        "    {\n"
+        "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
+        "    }\n"
+        "    return isnan;\n"
+        "}\n");
+
+    emu->addEmulatedFunction(
+        EOpIsNan, float3,
+        "bool3 webgl_isnan_emu(float3 x)\n"
+        "{\n"
+        "    bool3 isnan;\n"
+        "    for (int i = 0; i < 3; i++)\n"
+        "    {\n"
+        "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
+        "    }\n"
+        "    return isnan;\n"
+        "}\n");
+
+    emu->addEmulatedFunction(
+        EOpIsNan, float4,
+        "bool4 webgl_isnan_emu(float4 x)\n"
+        "{\n"
+        "    bool4 isnan;\n"
+        "    for (int i = 0; i < 4; i++)\n"
+        "    {\n"
+        "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
+        "    }\n"
+        "    return isnan;\n"
+        "}\n");
+}
+
+void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
+{
+    TType *float1 = new TType(EbtFloat);
+    TType *float2 = new TType(EbtFloat, 2);
+    TType *float3 = new TType(EbtFloat, 3);
+    TType *float4 = new TType(EbtFloat, 4);
+    TType *int1   = new TType(EbtInt);
+    TType *int2   = new TType(EbtInt, 2);
+    TType *int3   = new TType(EbtInt, 3);
+    TType *int4   = new TType(EbtInt, 4);
+    TType *uint1  = new TType(EbtUInt);
+    TType *uint2  = new TType(EbtUInt, 2);
+    TType *uint3  = new TType(EbtUInt, 3);
+    TType *uint4  = new TType(EbtUInt, 4);
+
+    emu->addEmulatedFunction(EOpMod, float1, float1,
+                             "float webgl_mod_emu(float x, float y)\n"
+                             "{\n"
+                             "    return x - y * floor(x / y);\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpMod, float2, float2,
+                             "float2 webgl_mod_emu(float2 x, float2 y)\n"
+                             "{\n"
+                             "    return x - y * floor(x / y);\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpMod, float2, float1,
+                             "float2 webgl_mod_emu(float2 x, float y)\n"
+                             "{\n"
+                             "    return x - y * floor(x / y);\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpMod, float3, float3,
+                             "float3 webgl_mod_emu(float3 x, float3 y)\n"
+                             "{\n"
+                             "    return x - y * floor(x / y);\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpMod, float3, float1,
+                             "float3 webgl_mod_emu(float3 x, float y)\n"
+                             "{\n"
+                             "    return x - y * floor(x / y);\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpMod, float4, float4,
+                             "float4 webgl_mod_emu(float4 x, float4 y)\n"
+                             "{\n"
+                             "    return x - y * floor(x / y);\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpMod, float4, float1,
+                             "float4 webgl_mod_emu(float4 x, float y)\n"
+                             "{\n"
+                             "    return x - y * floor(x / y);\n"
+                             "}\n"
+                             "\n");
+
+    emu->addEmulatedFunction(EOpFrexp, float1, int1,
+                             "float webgl_frexp_emu(float x, out int exp)\n"
+                             "{\n"
+                             "    float fexp;\n"
+                             "    float mantissa = frexp(abs(x), fexp) * sign(x);\n"
+                             "    exp = int(fexp);\n"
+                             "    return mantissa;\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpFrexp, float2, int2,
+                             "float2 webgl_frexp_emu(float2 x, out int2 exp)\n"
+                             "{\n"
+                             "    float2 fexp;\n"
+                             "    float2 mantissa = frexp(abs(x), fexp) * sign(x);\n"
+                             "    exp = int2(fexp);\n"
+                             "    return mantissa;\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpFrexp, float3, int3,
+                             "float3 webgl_frexp_emu(float3 x, out int3 exp)\n"
+                             "{\n"
+                             "    float3 fexp;\n"
+                             "    float3 mantissa = frexp(abs(x), fexp) * sign(x);\n"
+                             "    exp = int3(fexp);\n"
+                             "    return mantissa;\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpFrexp, float4, int4,
+                             "float4 webgl_frexp_emu(float4 x, out int4 exp)\n"
+                             "{\n"
+                             "    float4 fexp;\n"
+                             "    float4 mantissa = frexp(abs(x), fexp) * sign(x);\n"
+                             "    exp = int4(fexp);\n"
+                             "    return mantissa;\n"
+                             "}\n"
+                             "\n");
+
+    emu->addEmulatedFunction(EOpLdexp, float1, int1,
+                             "float webgl_ldexp_emu(float x, int exp)\n"
+                             "{\n"
+                             "    return ldexp(x, float(exp));\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpLdexp, float2, int2,
+                             "float2 webgl_ldexp_emu(float2 x, int2 exp)\n"
+                             "{\n"
+                             "    return ldexp(x, float2(exp));\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpLdexp, float3, int3,
+                             "float3 webgl_ldexp_emu(float3 x, int3 exp)\n"
+                             "{\n"
+                             "    return ldexp(x, float3(exp));\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpLdexp, float4, int4,
+                             "float4 webgl_ldexp_emu(float4 x, int4 exp)\n"
+                             "{\n"
+                             "    return ldexp(x, float4(exp));\n"
+                             "}\n"
+                             "\n");
+
+    emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1,
+                             "float webgl_faceforward_emu(float N, float I, float Nref)\n"
+                             "{\n"
+                             "    if(dot(Nref, I) >= 0)\n"
+                             "    {\n"
+                             "        return -N;\n"
+                             "    }\n"
+                             "    else\n"
+                             "    {\n"
+                             "        return N;\n"
+                             "    }\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpFaceForward, float2, float2, float2,
+                             "float2 webgl_faceforward_emu(float2 N, float2 I, float2 Nref)\n"
+                             "{\n"
+                             "    if(dot(Nref, I) >= 0)\n"
+                             "    {\n"
+                             "        return -N;\n"
+                             "    }\n"
+                             "    else\n"
+                             "    {\n"
+                             "        return N;\n"
+                             "    }\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpFaceForward, float3, float3, float3,
+                             "float3 webgl_faceforward_emu(float3 N, float3 I, float3 Nref)\n"
+                             "{\n"
+                             "    if(dot(Nref, I) >= 0)\n"
+                             "    {\n"
+                             "        return -N;\n"
+                             "    }\n"
+                             "    else\n"
+                             "    {\n"
+                             "        return N;\n"
+                             "    }\n"
+                             "}\n"
+                             "\n");
+    emu->addEmulatedFunction(EOpFaceForward, float4, float4, float4,
+                             "float4 webgl_faceforward_emu(float4 N, float4 I, float4 Nref)\n"
+                             "{\n"
+                             "    if(dot(Nref, I) >= 0)\n"
+                             "    {\n"
+                             "        return -N;\n"
+                             "    }\n"
+                             "    else\n"
+                             "    {\n"
+                             "        return N;\n"
+                             "    }\n"
+                             "}\n"
+                             "\n");
+
+    emu->addEmulatedFunction(EOpAtan, float1, float1,
+                             "float webgl_atan_emu(float y, float x)\n"
+                             "{\n"
+                             "    if(x == 0 && y == 0) x = 1;\n"  // Avoid producing a NaN
+                             "    return atan2(y, x);\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAtan, float2, float2,
+                             "float2 webgl_atan_emu(float2 y, float2 x)\n"
+                             "{\n"
+                             "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+                             "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+                             "    return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
+                             "}\n");
+    emu->addEmulatedFunction(
+        EOpAtan, float3, float3,
+        "float3 webgl_atan_emu(float3 y, float3 x)\n"
+        "{\n"
+        "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+        "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+        "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+        "    return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
+        "}\n");
+    emu->addEmulatedFunction(EOpAtan, float4, float4,
+                             "float4 webgl_atan_emu(float4 y, float4 x)\n"
+                             "{\n"
+                             "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+                             "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+                             "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+                             "    if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
+                             "    return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], "
+                             "x[2]), atan2(y[3], x[3]));\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(EOpAsinh, float1,
+                             "float webgl_asinh_emu(in float x) {\n"
+                             "    return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAsinh, float2,
+                             "float2 webgl_asinh_emu(in float2 x) {\n"
+                             "    return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAsinh, float3,
+                             "float3 webgl_asinh_emu(in float3 x) {\n"
+                             "    return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAsinh, float4,
+                             "float4 webgl_asinh_emu(in float4 x) {\n"
+                             "    return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(EOpAcosh, float1,
+                             "float webgl_acosh_emu(in float x) {\n"
+                             "    return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAcosh, float2,
+                             "float2 webgl_acosh_emu(in float2 x) {\n"
+                             "    return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAcosh, float3,
+                             "float3 webgl_acosh_emu(in float3 x) {\n"
+                             "    return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAcosh, float4,
+                             "float4 webgl_acosh_emu(in float4 x) {\n"
+                             "    return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(EOpAtanh, float1,
+                             "float webgl_atanh_emu(in float x) {\n"
+                             "    return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAtanh, float2,
+                             "float2 webgl_atanh_emu(in float2 x) {\n"
+                             "    return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAtanh, float3,
+                             "float3 webgl_atanh_emu(in float3 x) {\n"
+                             "    return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpAtanh, float4,
+                             "float4 webgl_atanh_emu(in float4 x) {\n"
+                             "    return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(
+        EOpRoundEven, float1,
+        "float webgl_roundEven_emu(in float x) {\n"
+        "    return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpRoundEven, float2,
+        "float2 webgl_roundEven_emu(in float2 x) {\n"
+        "    float2 v;\n"
+        "    v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
+        "    v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
+        "    return v;\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpRoundEven, float3,
+        "float3 webgl_roundEven_emu(in float3 x) {\n"
+        "    float3 v;\n"
+        "    v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
+        "    v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
+        "    v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
+        "    return v;\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpRoundEven, float4,
+        "float4 webgl_roundEven_emu(in float4 x) {\n"
+        "    float4 v;\n"
+        "    v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
+        "    v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
+        "    v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
+        "    v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
+        "    return v;\n"
+        "}\n");
+
+    emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
+                             "int webgl_toSnorm16(in float x) {\n"
+                             "    return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
+                             "}\n"
+                             "\n"
+                             "uint webgl_packSnorm2x16_emu(in float2 v) {\n"
+                             "    int x = webgl_toSnorm16(v.x);\n"
+                             "    int y = webgl_toSnorm16(v.y);\n"
+                             "    return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
+                             "uint webgl_toUnorm16(in float x) {\n"
+                             "    return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
+                             "}\n"
+                             "\n"
+                             "uint webgl_packUnorm2x16_emu(in float2 v) {\n"
+                             "    uint x = webgl_toUnorm16(v.x);\n"
+                             "    uint y = webgl_toUnorm16(v.y);\n"
+                             "    return (y << 16) | x;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpPackHalf2x16, float2,
+                             "uint webgl_packHalf2x16_emu(in float2 v) {\n"
+                             "    uint x = f32tof16(v.x);\n"
+                             "    uint y = f32tof16(v.y);\n"
+                             "    return (y << 16) | x;\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
+                             "float webgl_fromSnorm16(in uint x) {\n"
+                             "    int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
+                             "    return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
+                             "}\n"
+                             "\n"
+                             "float2 webgl_unpackSnorm2x16_emu(in uint u) {\n"
+                             "    uint y = (u >> 16);\n"
+                             "    uint x = u;\n"
+                             "    return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
+                             "float webgl_fromUnorm16(in uint x) {\n"
+                             "    return float(x) / 65535.0;\n"
+                             "}\n"
+                             "\n"
+                             "float2 webgl_unpackUnorm2x16_emu(in uint u) {\n"
+                             "    uint y = (u >> 16);\n"
+                             "    uint x = u & 0xffffu;\n"
+                             "    return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
+                             "float2 webgl_unpackHalf2x16_emu(in uint u) {\n"
+                             "    uint y = (u >> 16);\n"
+                             "    uint x = u & 0xffffu;\n"
+                             "    return float2(f16tof32(x), f16tof32(y));\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(EOpPackSnorm4x8, float4,
+                             "int webgl_toSnorm8(in float x) {\n"
+                             "    return int(round(clamp(x, -1.0, 1.0) * 127.0));\n"
+                             "}\n"
+                             "\n"
+                             "uint webgl_packSnorm4x8_emu(in float4 v) {\n"
+                             "    int x = webgl_toSnorm8(v.x);\n"
+                             "    int y = webgl_toSnorm8(v.y);\n"
+                             "    int z = webgl_toSnorm8(v.z);\n"
+                             "    int w = webgl_toSnorm8(v.w);\n"
+                             "    return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) "
+                             "| ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpPackUnorm4x8, float4,
+                             "uint webgl_toUnorm8(in float x) {\n"
+                             "    return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n"
+                             "}\n"
+                             "\n"
+                             "uint webgl_packUnorm4x8_emu(in float4 v) {\n"
+                             "    uint x = webgl_toUnorm8(v.x);\n"
+                             "    uint y = webgl_toUnorm8(v.y);\n"
+                             "    uint z = webgl_toUnorm8(v.z);\n"
+                             "    uint w = webgl_toUnorm8(v.w);\n"
+                             "    return (w << 24) | (z << 16) | (y << 8) | x;\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(EOpUnpackSnorm4x8, uint1,
+                             "float webgl_fromSnorm8(in uint x) {\n"
+                             "    int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n"
+                             "    return clamp(float(xi) / 127.0, -1.0, 1.0);\n"
+                             "}\n"
+                             "\n"
+                             "float4 webgl_unpackSnorm4x8_emu(in uint u) {\n"
+                             "    uint w = (u >> 24);\n"
+                             "    uint z = (u >> 16);\n"
+                             "    uint y = (u >> 8);\n"
+                             "    uint x = u;\n"
+                             "    return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), "
+                             "webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpUnpackUnorm4x8, uint1,
+                             "float webgl_fromUnorm8(in uint x) {\n"
+                             "    return float(x) / 255.0;\n"
+                             "}\n"
+                             "\n"
+                             "float4 webgl_unpackUnorm4x8_emu(in uint u) {\n"
+                             "    uint w = (u >> 24) & 0xffu;\n"
+                             "    uint z = (u >> 16) & 0xffu;\n"
+                             "    uint y = (u >> 8) & 0xffu;\n"
+                             "    uint x = u & 0xffu;\n"
+                             "    return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), "
+                             "webgl_fromUnorm8(z), webgl_fromUnorm8(w));\n"
+                             "}\n");
+
+    // The matrix resulting from outer product needs to be transposed
+    // (matrices are stored as transposed to simplify element access in HLSL).
+    // So the function should return transpose(c * r) where c is a column vector
+    // and r is a row vector. This can be simplified by using the following
+    // formula:
+    //   transpose(c * r) = transpose(r) * transpose(c)
+    // transpose(r) and transpose(c) are in a sense free, since to get the
+    // transpose of r, we simply can build a column matrix out of the original
+    // vector instead of a row matrix.
+    emu->addEmulatedFunction(EOpOuterProduct, float2, float2,
+                             "float2x2 webgl_outerProduct_emu(in float2 c, in float2 r) {\n"
+                             "    return mul(float2x1(r), float1x2(c));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpOuterProduct, float3, float3,
+                             "float3x3 webgl_outerProduct_emu(in float3 c, in float3 r) {\n"
+                             "    return mul(float3x1(r), float1x3(c));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpOuterProduct, float4, float4,
+                             "float4x4 webgl_outerProduct_emu(in float4 c, in float4 r) {\n"
+                             "    return mul(float4x1(r), float1x4(c));\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(EOpOuterProduct, float3, float2,
+                             "float2x3 webgl_outerProduct_emu(in float3 c, in float2 r) {\n"
+                             "    return mul(float2x1(r), float1x3(c));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpOuterProduct, float2, float3,
+                             "float3x2 webgl_outerProduct_emu(in float2 c, in float3 r) {\n"
+                             "    return mul(float3x1(r), float1x2(c));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpOuterProduct, float4, float2,
+                             "float2x4 webgl_outerProduct_emu(in float4 c, in float2 r) {\n"
+                             "    return mul(float2x1(r), float1x4(c));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpOuterProduct, float2, float4,
+                             "float4x2 webgl_outerProduct_emu(in float2 c, in float4 r) {\n"
+                             "    return mul(float4x1(r), float1x2(c));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpOuterProduct, float4, float3,
+                             "float3x4 webgl_outerProduct_emu(in float4 c, in float3 r) {\n"
+                             "    return mul(float3x1(r), float1x4(c));\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpOuterProduct, float3, float4,
+                             "float4x3 webgl_outerProduct_emu(in float3 c, in float4 r) {\n"
+                             "    return mul(float4x1(r), float1x3(c));\n"
+                             "}\n");
+
+    TType *mat2 = new TType(EbtFloat, 2, 2);
+    TType *mat3 = new TType(EbtFloat, 3, 3);
+    TType *mat4 = new TType(EbtFloat, 4, 4);
+
+    // Remember here that the parameter matrix is actually the transpose
+    // of the matrix that we're trying to invert, and the resulting matrix
+    // should also be the transpose of the inverse.
+
+    // When accessing the parameter matrix with m[a][b] it can be thought of so
+    // that a is the column and b is the row of the matrix that we're inverting.
+
+    // We calculate the inverse as the adjugate matrix divided by the
+    // determinant of the matrix being inverted. However, as the result needs
+    // to be transposed, we actually use of the transpose of the adjugate matrix
+    // which happens to be the cofactor matrix. That's stored in "cof".
+
+    // We don't need to care about divide-by-zero since results are undefined
+    // for singular or poorly-conditioned matrices.
+
+    emu->addEmulatedFunction(EOpInverse, mat2,
+                             "float2x2 webgl_inverse_emu(in float2x2 m) {\n"
+                             "    float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
+                             "    return cof / determinant(transpose(m));\n"
+                             "}\n");
+
+    // cofAB is the cofactor for column A and row B.
+
+    emu->addEmulatedFunction(
+        EOpInverse, mat3,
+        "float3x3 webgl_inverse_emu(in float3x3 m) {\n"
+        "    float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
+        "    float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n"
+        "    float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n"
+        "    float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n"
+        "    float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n"
+        "    float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n"
+        "    float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n"
+        "    float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n"
+        "    float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n"
+        "    float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
+        "    return cof / determinant(transpose(m));\n"
+        "}\n");
+
+    emu->addEmulatedFunction(
+        EOpInverse, mat4,
+        "float4x4 webgl_inverse_emu(in float4x4 m) {\n"
+        "    float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * "
+        "m[1][2] * m[2][3]"
+        " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * "
+        "m[1][3];\n"
+        "    float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * "
+        "m[1][2] * m[2][3]"
+        " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * "
+        "m[1][3]);\n"
+        "    float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * "
+        "m[1][1] * m[2][3]"
+        " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * "
+        "m[1][3];\n"
+        "    float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * "
+        "m[1][1] * m[2][2]"
+        " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * "
+        "m[1][2]);\n"
+        "    float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * "
+        "m[0][2] * m[2][3]"
+        " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * "
+        "m[0][3]);\n"
+        "    float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * "
+        "m[0][2] * m[2][3]"
+        " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * "
+        "m[0][3];\n"
+        "    float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * "
+        "m[0][1] * m[2][3]"
+        " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * "
+        "m[0][3]);\n"
+        "    float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * "
+        "m[0][1] * m[2][2]"
+        " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * "
+        "m[0][2];\n"
+        "    float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * "
+        "m[0][2] * m[1][3]"
+        " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * "
+        "m[0][3];\n"
+        "    float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * "
+        "m[0][2] * m[1][3]"
+        " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * "
+        "m[0][3]);\n"
+        "    float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * "
+        "m[0][1] * m[1][3]"
+        " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * "
+        "m[0][3];\n"
+        "    float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * "
+        "m[0][1] * m[1][2]"
+        " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * "
+        "m[0][2]);\n"
+        "    float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * "
+        "m[0][2] * m[1][3]"
+        " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * "
+        "m[0][3]);\n"
+        "    float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * "
+        "m[0][2] * m[1][3]"
+        " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * "
+        "m[0][3];\n"
+        "    float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * "
+        "m[0][1] * m[1][3]"
+        " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * "
+        "m[0][3]);\n"
+        "    float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * "
+        "m[0][1] * m[1][2]"
+        " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * "
+        "m[0][2];\n"
+        "    float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,"
+        " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
+        "    return cof / determinant(transpose(m));\n"
+        "}\n");
+
+    TType *bool1 = new TType(EbtBool);
+    TType *bool2 = new TType(EbtBool, 2);
+    TType *bool3 = new TType(EbtBool, 3);
+    TType *bool4 = new TType(EbtBool, 4);
+
+    // Emulate ESSL3 variant of mix that takes last argument as boolean vector.
+    // genType mix (genType x, genType y, genBType a): Selects which vector each returned component
+    // comes from.
+    // For a component of 'a' that is false, the corresponding component of 'x' is returned.For a
+    // component of 'a' that is true,
+    // the corresponding component of 'y' is returned.
+    emu->addEmulatedFunction(EOpMix, float1, float1, bool1,
+                             "float webgl_mix_emu(float x, float y, bool a)\n"
+                             "{\n"
+                             "    return a ? y : x;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpMix, float2, float2, bool2,
+                             "float2 webgl_mix_emu(float2 x, float2 y, bool2 a)\n"
+                             "{\n"
+                             "    return a ? y : x;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpMix, float3, float3, bool3,
+                             "float3 webgl_mix_emu(float3 x, float3 y, bool3 a)\n"
+                             "{\n"
+                             "    return a ? y : x;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpMix, float4, float4, bool4,
+                             "float4 webgl_mix_emu(float4 x, float4 y, bool4 a)\n"
+                             "{\n"
+                             "    return a ? y : x;\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(
+        EOpBitfieldExtract, uint1, int1, int1,
+        "uint webgl_bitfieldExtract_emu(uint value, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return 0u;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    return (value & mask) >> offset;\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldExtract, uint2, int1, int1,
+        "uint2 webgl_bitfieldExtract_emu(uint2 value, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return uint2(0u, 0u);\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    return (value & mask) >> offset;\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldExtract, uint3, int1, int1,
+        "uint3 webgl_bitfieldExtract_emu(uint3 value, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return uint3(0u, 0u, 0u);\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    return (value & mask) >> offset;\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldExtract, uint4, int1, int1,
+        "uint4 webgl_bitfieldExtract_emu(uint4 value, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return uint4(0u, 0u, 0u, 0u);\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    return (value & mask) >> offset;\n"
+        "}\n");
+
+    emu->addEmulatedFunction(
+        EOpBitfieldExtract, int1, int1, int1,
+        "int webgl_bitfieldExtract_emu(int value, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return 0;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint resultUnsigned = (asuint(value) & mask) >> offset;\n"
+        "    if (bits != 32 && (resultUnsigned & maskMsb) != 0)\n"
+        "    {\n"
+        "        uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
+        "        resultUnsigned |= higherBitsMask;\n"
+        "    }\n"
+        "    return asint(resultUnsigned);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldExtract, int2, int1, int1,
+        "int2 webgl_bitfieldExtract_emu(int2 value, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return int2(0, 0);\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint2 resultUnsigned = (asuint(value) & mask) >> offset;\n"
+        "    if (bits != 32)\n"
+        "    {\n"
+        "        uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
+        "        resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
+        "    }\n"
+        "    return asint(resultUnsigned);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldExtract, int3, int1, int1,
+        "int3 webgl_bitfieldExtract_emu(int3 value, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return int3(0, 0, 0);\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint3 resultUnsigned = (asuint(value) & mask) >> offset;\n"
+        "    if (bits != 32)\n"
+        "    {\n"
+        "        uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
+        "        resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
+        "    }\n"
+        "    return asint(resultUnsigned);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldExtract, int4, int1, int1,
+        "int4 webgl_bitfieldExtract_emu(int4 value, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return int4(0, 0, 0, 0);\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint4 resultUnsigned = (asuint(value) & mask) >> offset;\n"
+        "    if (bits != 32)\n"
+        "    {\n"
+        "        uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
+        "        resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
+        "    }\n"
+        "    return asint(resultUnsigned);\n"
+        "}\n");
+
+    emu->addEmulatedFunction(
+        EOpBitfieldInsert, uint1, uint1, int1, int1,
+        "uint webgl_bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return base;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint baseMask = ~insertMask;\n"
+        "    return (base & baseMask) | ((insert << offset) & insertMask);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldInsert, uint2, uint2, int1, int1,
+        "uint2 webgl_bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return base;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint baseMask = ~insertMask;\n"
+        "    return (base & baseMask) | ((insert << offset) & insertMask);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldInsert, uint3, uint3, int1, int1,
+        "uint3 webgl_bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return base;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint baseMask = ~insertMask;\n"
+        "    return (base & baseMask) | ((insert << offset) & insertMask);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldInsert, uint4, uint4, int1, int1,
+        "uint4 webgl_bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return base;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint baseMask = ~insertMask;\n"
+        "    return (base & baseMask) | ((insert << offset) & insertMask);\n"
+        "}\n");
+
+    emu->addEmulatedFunction(
+        EOpBitfieldInsert, int1, int1, int1, int1,
+        "int webgl_bitfieldInsert_emu(int base, int insert, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return base;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint baseMask = ~insertMask;\n"
+        "    uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & "
+        "insertMask);\n"
+        "    return asint(resultUnsigned);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldInsert, int2, int2, int1, int1,
+        "int2 webgl_bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return base;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint baseMask = ~insertMask;\n"
+        "    uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & "
+        "insertMask);\n"
+        "    return asint(resultUnsigned);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldInsert, int3, int3, int1, int1,
+        "int3 webgl_bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return base;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint baseMask = ~insertMask;\n"
+        "    uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & "
+        "insertMask);\n"
+        "    return asint(resultUnsigned);\n"
+        "}\n");
+    emu->addEmulatedFunction(
+        EOpBitfieldInsert, int4, int4, int1, int1,
+        "int4 webgl_bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n"
+        "{\n"
+        "    if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+        "    {\n"
+        "        return base;\n"
+        "    }\n"
+        "    uint maskMsb = (1u << (bits - 1));\n"
+        "    uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+        "    uint baseMask = ~insertMask;\n"
+        "    uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & "
+        "insertMask);\n"
+        "    return asint(resultUnsigned);\n"
+        "}\n");
+
+    emu->addEmulatedFunction(EOpUaddCarry, uint1, uint1, uint1,
+                             "uint webgl_uaddCarry_emu(uint x, uint y, out uint carry)\n"
+                             "{\n"
+                             "    carry = uint(x > (0xffffffffu - y));\n"
+                             "    return x + y;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpUaddCarry, uint2, uint2, uint2,
+                             "uint2 webgl_uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n"
+                             "{\n"
+                             "    carry = uint2(x > (0xffffffffu - y));\n"
+                             "    return x + y;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpUaddCarry, uint3, uint3, uint3,
+                             "uint3 webgl_uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n"
+                             "{\n"
+                             "    carry = uint3(x > (0xffffffffu - y));\n"
+                             "    return x + y;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpUaddCarry, uint4, uint4, uint4,
+                             "uint4 webgl_uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n"
+                             "{\n"
+                             "    carry = uint4(x > (0xffffffffu - y));\n"
+                             "    return x + y;\n"
+                             "}\n");
+
+    emu->addEmulatedFunction(EOpUsubBorrow, uint1, uint1, uint1,
+                             "uint webgl_usubBorrow_emu(uint x, uint y, out uint borrow)\n"
+                             "{\n"
+                             "    borrow = uint(x < y);\n"
+                             "    return x - y;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpUsubBorrow, uint2, uint2, uint2,
+                             "uint2 webgl_usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n"
+                             "{\n"
+                             "    borrow = uint2(x < y);\n"
+                             "    return x - y;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpUsubBorrow, uint3, uint3, uint3,
+                             "uint3 webgl_usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n"
+                             "{\n"
+                             "    borrow = uint3(x < y);\n"
+                             "    return x - y;\n"
+                             "}\n");
+    emu->addEmulatedFunction(EOpUsubBorrow, uint4, uint4, uint4,
+                             "uint4 webgl_usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n"
+                             "{\n"
+                             "    borrow = uint4(x < y);\n"
+                             "    return x - y;\n"
+                             "}\n");
+
+    // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
+    // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
+    // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
+    BuiltInFunctionEmulator::FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
+        EOpUmulExtended, uint1, uint1, uint1, uint1,
+        "void webgl_umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
+        "{\n"
+        "    lsb = x * y;\n"
+        "    uint a = (x & 0xffffu);\n"
+        "    uint b = (x >> 16);\n"
+        "    uint c = (y & 0xffffu);\n"
+        "    uint d = (y >> 16);\n"
+        "    uint ad = a * d + ((a * c) >> 16);\n"
+        "    uint bc = b * c;\n"
+        "    uint carry = uint(ad > (0xffffffffu - bc));\n"
+        "    msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
+        "}\n");
+    emu->addEmulatedFunctionWithDependency(
+        umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2,
+        "void webgl_umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
+        "{\n"
+        "    webgl_umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+        "    webgl_umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+        "}\n");
+    emu->addEmulatedFunctionWithDependency(
+        umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3,
+        "void webgl_umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
+        "{\n"
+        "    webgl_umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+        "    webgl_umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+        "    webgl_umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
+        "}\n");
+    emu->addEmulatedFunctionWithDependency(
+        umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4,
+        "void webgl_umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
+        "{\n"
+        "    webgl_umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+        "    webgl_umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+        "    webgl_umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
+        "    webgl_umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
+        "}\n");
+
+    // The imul emulation does two's complement negation on the lsb and msb manually in case the
+    // result needs to be negative.
+    // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
+    // -2^31. abs(-2^31) is undefined.
+    BuiltInFunctionEmulator::FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
+        umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
+        "void webgl_imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
+        "{\n"
+        "    uint unsignedMsb;\n"
+        "    uint unsignedLsb;\n"
+        "    bool negative = (x < 0) != (y < 0);\n"
+        "    webgl_umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n"
+        "    lsb = asint(unsignedLsb);\n"
+        "    msb = asint(unsignedMsb);\n"
+        "    if (negative)\n"
+        "    {\n"
+        "        lsb = ~lsb;\n"
+        "        msb = ~msb;\n"
+        "        if (lsb == 0xffffffff)\n"
+        "        {\n"
+        "            lsb = 0;\n"
+        "            msb += 1;\n"
+        "        }\n"
+        "        else\n"
+        "        {\n"
+        "            lsb += 1;\n"
+        "        }\n"
+        "    }\n"
+        "}\n");
+    emu->addEmulatedFunctionWithDependency(
+        imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2,
+        "void webgl_imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
+        "{\n"
+        "    webgl_imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+        "    webgl_imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+        "}\n");
+    emu->addEmulatedFunctionWithDependency(
+        imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3,
+        "void webgl_imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
+        "{\n"
+        "    webgl_imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+        "    webgl_imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+        "    webgl_imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
+        "}\n");
+    emu->addEmulatedFunctionWithDependency(
+        imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4,
+        "void webgl_imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
+        "{\n"
+        "    webgl_imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+        "    webgl_imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+        "    webgl_imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
+        "    webgl_imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
+        "}\n");
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h
new file mode 100644
index 0000000..48da73f
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
+#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+
+class BuiltInFunctionEmulator;
+
+void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu);
+
+//
+// This works around isnan() bug on some Intel drivers.
+//
+void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
+                                                        int targetGLSLVersion);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/Cache.cpp b/src/third_party/angle/src/compiler/translator/Cache.cpp
new file mode 100644
index 0000000..07cc5b2
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Cache.cpp
@@ -0,0 +1,95 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Cache.cpp: Implements a cache for various commonly created objects.
+
+#include <limits>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "compiler/translator/Cache.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class TScopedAllocator : angle::NonCopyable
+{
+  public:
+    TScopedAllocator(TPoolAllocator *allocator) : mPreviousAllocator(GetGlobalPoolAllocator())
+    {
+        SetGlobalPoolAllocator(allocator);
+    }
+    ~TScopedAllocator() { SetGlobalPoolAllocator(mPreviousAllocator); }
+
+  private:
+    TPoolAllocator *mPreviousAllocator;
+};
+
+}  // namespace
+
+TCache::TypeKey::TypeKey(TBasicType basicType,
+                         TPrecision precision,
+                         TQualifier qualifier,
+                         unsigned char primarySize,
+                         unsigned char secondarySize)
+{
+    static_assert(sizeof(components) <= sizeof(value), "TypeKey::value is too small");
+
+    const size_t MaxEnumValue = std::numeric_limits<EnumComponentType>::max();
+
+    // TODO: change to static_assert() once we deprecate MSVC 2013 support
+    ASSERT(MaxEnumValue >= EbtLast && MaxEnumValue >= EbpLast && MaxEnumValue >= EvqLast &&
+           "TypeKey::EnumComponentType is too small");
+
+    value                    = 0;
+    components.basicType     = static_cast<EnumComponentType>(basicType);
+    components.precision     = static_cast<EnumComponentType>(precision);
+    components.qualifier     = static_cast<EnumComponentType>(qualifier);
+    components.primarySize   = primarySize;
+    components.secondarySize = secondarySize;
+}
+
+TCache *TCache::sCache = nullptr;
+
+void TCache::initialize()
+{
+    if (sCache == nullptr)
+    {
+        sCache = new TCache();
+    }
+}
+
+void TCache::destroy()
+{
+    SafeDelete(sCache);
+}
+
+const TType *TCache::getType(TBasicType basicType,
+                             TPrecision precision,
+                             TQualifier qualifier,
+                             unsigned char primarySize,
+                             unsigned char secondarySize)
+{
+    TypeKey key(basicType, precision, qualifier, primarySize, secondarySize);
+    auto it = sCache->mTypes.find(key);
+    if (it != sCache->mTypes.end())
+    {
+        return it->second;
+    }
+
+    TScopedAllocator scopedAllocator(&sCache->mAllocator);
+
+    TType *type = new TType(basicType, precision, qualifier, primarySize, secondarySize);
+    type->realize();
+    sCache->mTypes.insert(std::make_pair(key, type));
+
+    return type;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/Cache.h b/src/third_party/angle/src/compiler/translator/Cache.h
new file mode 100644
index 0000000..a45ada4
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Cache.h
@@ -0,0 +1,84 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Cache.h: Implements a cache for various commonly created objects.
+
+#ifndef COMPILER_TRANSLATOR_CACHE_H_
+#define COMPILER_TRANSLATOR_CACHE_H_
+
+#include <stdint.h>
+#include <string.h>
+#include <map>
+
+#include "compiler/translator/Types.h"
+#include "compiler/translator/PoolAlloc.h"
+
+namespace sh
+{
+
+class TCache
+{
+  public:
+    static void initialize();
+    static void destroy();
+
+    static const TType *getType(TBasicType basicType, TPrecision precision)
+    {
+        return getType(basicType, precision, EvqTemporary, 1, 1);
+    }
+    static const TType *getType(TBasicType basicType,
+                                unsigned char primarySize   = 1,
+                                unsigned char secondarySize = 1)
+    {
+        return getType(basicType, EbpUndefined, EvqGlobal, primarySize, secondarySize);
+    }
+    static const TType *getType(TBasicType basicType,
+                                TQualifier qualifier,
+                                unsigned char primarySize   = 1,
+                                unsigned char secondarySize = 1)
+    {
+        return getType(basicType, EbpUndefined, qualifier, primarySize, secondarySize);
+    }
+    static const TType *getType(TBasicType basicType,
+                                TPrecision precision,
+                                TQualifier qualifier,
+                                unsigned char primarySize,
+                                unsigned char secondarySize);
+
+  private:
+    TCache() {}
+
+    union TypeKey {
+        TypeKey(TBasicType basicType,
+                TPrecision precision,
+                TQualifier qualifier,
+                unsigned char primarySize,
+                unsigned char secondarySize);
+
+        typedef uint8_t EnumComponentType;
+        struct
+        {
+            EnumComponentType basicType;
+            EnumComponentType precision;
+            EnumComponentType qualifier;
+            unsigned char primarySize;
+            unsigned char secondarySize;
+        } components;
+        uint64_t value;
+
+        bool operator<(const TypeKey &other) const { return value < other.value; }
+    };
+    typedef std::map<TypeKey, const TType *> TypeMap;
+
+    TypeMap mTypes;
+    TPoolAllocator mAllocator;
+
+    static TCache *sCache;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_CACHE_H_
diff --git a/src/third_party/angle/src/compiler/translator/CallDAG.cpp b/src/third_party/angle/src/compiler/translator/CallDAG.cpp
new file mode 100644
index 0000000..8557fdf
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/CallDAG.cpp
@@ -0,0 +1,345 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CallDAG.h: Implements a call graph DAG of functions to be re-used accross
+// analyses, allows to efficiently traverse the functions in topological
+// order.
+
+#include "compiler/translator/CallDAG.h"
+
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+// The CallDAGCreator does all the processing required to create the CallDAG
+// structure so that the latter contains only the necessary variables.
+class CallDAG::CallDAGCreator : public TIntermTraverser
+{
+  public:
+    CallDAGCreator(TDiagnostics *diagnostics)
+        : TIntermTraverser(true, false, true),
+          mDiagnostics(diagnostics),
+          mCurrentFunction(nullptr),
+          mCurrentIndex(0)
+    {
+    }
+
+    InitResult assignIndices()
+    {
+        int skipped = 0;
+        for (auto &it : mFunctions)
+        {
+            // Skip unimplemented functions
+            if (it.second.node)
+            {
+                InitResult result = assignIndicesInternal(&it.second);
+                if (result != INITDAG_SUCCESS)
+                {
+                    return result;
+                }
+            }
+            else
+            {
+                skipped++;
+            }
+        }
+
+        ASSERT(mFunctions.size() == mCurrentIndex + skipped);
+        return INITDAG_SUCCESS;
+    }
+
+    void fillDataStructures(std::vector<Record> *records, std::map<int, int> *idToIndex)
+    {
+        ASSERT(records->empty());
+        ASSERT(idToIndex->empty());
+
+        records->resize(mCurrentIndex);
+
+        for (auto &it : mFunctions)
+        {
+            CreatorFunctionData &data = it.second;
+            // Skip unimplemented functions
+            if (!data.node)
+            {
+                continue;
+            }
+            ASSERT(data.index < records->size());
+            Record &record = (*records)[data.index];
+
+            record.name = data.name.data();
+            record.node = data.node;
+
+            record.callees.reserve(data.callees.size());
+            for (auto &callee : data.callees)
+            {
+                record.callees.push_back(static_cast<int>(callee->index));
+            }
+
+            (*idToIndex)[data.node->getFunctionSymbolInfo()->getId().get()] =
+                static_cast<int>(data.index);
+        }
+    }
+
+  private:
+    struct CreatorFunctionData
+    {
+        CreatorFunctionData() : node(nullptr), index(0), indexAssigned(false), visiting(false) {}
+
+        std::set<CreatorFunctionData *> callees;
+        TIntermFunctionDefinition *node;
+        TString name;
+        size_t index;
+        bool indexAssigned;
+        bool visiting;
+    };
+
+    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override
+    {
+        // Create the record if need be and remember the node.
+        if (visit == PreVisit)
+        {
+            auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get());
+
+            if (it == mFunctions.end())
+            {
+                mCurrentFunction       = &mFunctions[node->getFunctionSymbolInfo()->getId().get()];
+                mCurrentFunction->name = node->getFunctionSymbolInfo()->getName();
+            }
+            else
+            {
+                mCurrentFunction = &it->second;
+                ASSERT(mCurrentFunction->name == node->getFunctionSymbolInfo()->getName());
+            }
+
+            mCurrentFunction->node = node;
+        }
+        else if (visit == PostVisit)
+        {
+            mCurrentFunction = nullptr;
+        }
+        return true;
+    }
+
+    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override
+    {
+        ASSERT(visit == PreVisit);
+        if (mCurrentFunction != nullptr)
+        {
+            return false;
+        }
+
+        // Function declaration, create an empty record.
+        auto &record = mFunctions[node->getFunctionSymbolInfo()->getId().get()];
+        record.name  = node->getFunctionSymbolInfo()->getName();
+
+        // No need to traverse the parameters.
+        return false;
+    }
+
+    // Aggregates the AST node for each function as well as the name of the functions called by it
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override
+    {
+        if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST)
+        {
+            // Function call, add the callees
+            auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get());
+            ASSERT(it != mFunctions.end());
+
+            // We might be traversing the initializer of a global variable. Even though function
+            // calls in global scope are forbidden by the parser, some subsequent AST
+            // transformations can add them to emulate particular features.
+            if (mCurrentFunction)
+            {
+                mCurrentFunction->callees.insert(&it->second);
+            }
+        }
+        return true;
+    }
+
+    // Recursively assigns indices to a sub DAG
+    InitResult assignIndicesInternal(CreatorFunctionData *root)
+    {
+        // Iterative implementation of the index assignment algorithm. A recursive version
+        // would be prettier but since the CallDAG creation runs before the limiting of the
+        // call depth, we might get stack overflows (computation of the call depth uses the
+        // CallDAG).
+
+        ASSERT(root);
+
+        if (root->indexAssigned)
+        {
+            return INITDAG_SUCCESS;
+        }
+
+        // If we didn't have to detect recursion, functionsToProcess could be a simple queue
+        // in which we add the function being processed's callees. However in order to detect
+        // recursion we need to know which functions we are currently visiting. For that reason
+        // functionsToProcess will look like a concatenation of segments of the form
+        // [F visiting = true, subset of F callees with visiting = false] and the following
+        // segment (if any) will be start with a callee of F.
+        // This way we can remember when we started visiting a function, to put visiting back
+        // to false.
+        TVector<CreatorFunctionData *> functionsToProcess;
+        functionsToProcess.push_back(root);
+
+        InitResult result = INITDAG_SUCCESS;
+
+        std::stringstream errorStream;
+
+        while (!functionsToProcess.empty())
+        {
+            CreatorFunctionData *function = functionsToProcess.back();
+
+            if (function->visiting)
+            {
+                function->visiting      = false;
+                function->index         = mCurrentIndex++;
+                function->indexAssigned = true;
+
+                functionsToProcess.pop_back();
+                continue;
+            }
+
+            if (!function->node)
+            {
+                errorStream << "Undefined function '" << function->name
+                            << ")' used in the following call chain:";
+                result = INITDAG_UNDEFINED;
+                break;
+            }
+
+            if (function->indexAssigned)
+            {
+                functionsToProcess.pop_back();
+                continue;
+            }
+
+            function->visiting = true;
+
+            for (auto callee : function->callees)
+            {
+                functionsToProcess.push_back(callee);
+
+                // Check if the callee is already being visited after pushing it so that it appears
+                // in the chain printed in the info log.
+                if (callee->visiting)
+                {
+                    errorStream << "Recursive function call in the following call chain:";
+                    result = INITDAG_RECURSION;
+                    break;
+                }
+            }
+
+            if (result != INITDAG_SUCCESS)
+            {
+                break;
+            }
+        }
+
+        // The call chain is made of the function we were visiting when the error was detected.
+        if (result != INITDAG_SUCCESS)
+        {
+            bool first = true;
+            for (auto function : functionsToProcess)
+            {
+                if (function->visiting)
+                {
+                    if (!first)
+                    {
+                        errorStream << " -> ";
+                    }
+                    errorStream << function->name << ")";
+                    first = false;
+                }
+            }
+            if (mDiagnostics)
+            {
+                std::string errorStr = errorStream.str();
+                mDiagnostics->globalError(errorStr.c_str());
+            }
+        }
+
+        return result;
+    }
+
+    TDiagnostics *mDiagnostics;
+
+    std::map<int, CreatorFunctionData> mFunctions;
+    CreatorFunctionData *mCurrentFunction;
+    size_t mCurrentIndex;
+};
+
+// CallDAG
+
+CallDAG::CallDAG()
+{
+}
+
+CallDAG::~CallDAG()
+{
+}
+
+const size_t CallDAG::InvalidIndex = std::numeric_limits<size_t>::max();
+
+size_t CallDAG::findIndex(const TFunctionSymbolInfo *functionInfo) const
+{
+    auto it = mFunctionIdToIndex.find(functionInfo->getId().get());
+
+    if (it == mFunctionIdToIndex.end())
+    {
+        return InvalidIndex;
+    }
+    else
+    {
+        return it->second;
+    }
+}
+
+const CallDAG::Record &CallDAG::getRecordFromIndex(size_t index) const
+{
+    ASSERT(index != InvalidIndex && index < mRecords.size());
+    return mRecords[index];
+}
+
+const CallDAG::Record &CallDAG::getRecord(const TIntermAggregate *function) const
+{
+    size_t index = findIndex(function->getFunctionSymbolInfo());
+    ASSERT(index != InvalidIndex && index < mRecords.size());
+    return mRecords[index];
+}
+
+size_t CallDAG::size() const
+{
+    return mRecords.size();
+}
+
+void CallDAG::clear()
+{
+    mRecords.clear();
+    mFunctionIdToIndex.clear();
+}
+
+CallDAG::InitResult CallDAG::init(TIntermNode *root, TDiagnostics *diagnostics)
+{
+    CallDAGCreator creator(diagnostics);
+
+    // Creates the mapping of functions to callees
+    root->traverse(&creator);
+
+    // Does the topological sort and detects recursions
+    InitResult result = creator.assignIndices();
+    if (result != INITDAG_SUCCESS)
+    {
+        return result;
+    }
+
+    creator.fillDataStructures(&mRecords, &mFunctionIdToIndex);
+    return INITDAG_SUCCESS;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/CallDAG.h b/src/third_party/angle/src/compiler/translator/CallDAG.h
new file mode 100644
index 0000000..d29f932
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/CallDAG.h
@@ -0,0 +1,80 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CallDAG.h: Defines a call graph DAG of functions to be re-used accross
+// analyses, allows to efficiently traverse the functions in topological
+// order.
+
+#ifndef COMPILER_TRANSLATOR_CALLDAG_H_
+#define COMPILER_TRANSLATOR_CALLDAG_H_
+
+#include <map>
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/VariableInfo.h"
+
+namespace sh
+{
+
+// The translator needs to analyze the the graph of the function calls
+// to run checks and analyses; since in GLSL recursion is not allowed
+// that graph is a DAG.
+// This class is used to precompute that function call DAG so that it
+// can be reused by multiple analyses.
+//
+// It stores a vector of function records, with one record per function.
+// Records are accessed by index but a function symbol id can be converted
+// to the index of the corresponding record. The records mostly contain the
+// AST node of the function and the indices of the function's callees.
+//
+// In addition, records are in reverse topological order: a function F being
+// called by a function G will have index index(F) < index(G), that way
+// depth-first analysis becomes analysis in the order of indices.
+
+class CallDAG : angle::NonCopyable
+{
+  public:
+    CallDAG();
+    ~CallDAG();
+
+    struct Record
+    {
+        std::string name;
+        TIntermFunctionDefinition *node;
+        std::vector<int> callees;
+    };
+
+    enum InitResult
+    {
+        INITDAG_SUCCESS,
+        INITDAG_RECURSION,
+        INITDAG_UNDEFINED,
+    };
+
+    // Returns INITDAG_SUCCESS if it was able to create the DAG, otherwise prints
+    // the initialization error in diagnostics, if present.
+    InitResult init(TIntermNode *root, TDiagnostics *diagnostics);
+
+    // Returns InvalidIndex if the function wasn't found
+    size_t findIndex(const TFunctionSymbolInfo *functionInfo) const;
+
+    const Record &getRecordFromIndex(size_t index) const;
+    const Record &getRecord(const TIntermAggregate *function) const;
+    size_t size() const;
+    void clear();
+
+    const static size_t InvalidIndex;
+
+  private:
+    std::vector<Record> mRecords;
+    std::map<int, int> mFunctionIdToIndex;
+
+    class CallDAGCreator;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_CALLDAG_H_
diff --git a/src/third_party/angle/src/compiler/translator/CodeGen.cpp b/src/third_party/angle/src/compiler/translator/CodeGen.cpp
new file mode 100644
index 0000000..75f0d36
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/CodeGen.cpp
@@ -0,0 +1,97 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifdef ANGLE_ENABLE_ESSL
+#include "compiler/translator/TranslatorESSL.h"
+#endif  // ANGLE_ENABLE_ESSL
+
+#ifdef ANGLE_ENABLE_GLSL
+#include "compiler/translator/TranslatorGLSL.h"
+#endif  // ANGLE_ENABLE_GLSL
+
+#ifdef ANGLE_ENABLE_HLSL
+#include "compiler/translator/TranslatorHLSL.h"
+#endif  // ANGLE_ENABLE_HLSL
+
+#ifdef ANGLE_ENABLE_VULKAN
+#include "compiler/translator/TranslatorVulkan.h"
+#endif  // ANGLE_ENABLE_VULKAN
+
+namespace sh
+{
+
+//
+// This function must be provided to create the actual
+// compile object used by higher level code.  It returns
+// a subclass of TCompiler.
+//
+TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
+{
+    switch (output)
+    {
+        case SH_ESSL_OUTPUT:
+#ifdef ANGLE_ENABLE_ESSL
+            return new TranslatorESSL(type, spec);
+#else
+            // This compiler is not supported in this configuration. Return NULL per the
+            // sh::ConstructCompiler API.
+            return nullptr;
+#endif  // ANGLE_ENABLE_ESSL
+
+        case SH_GLSL_130_OUTPUT:
+        case SH_GLSL_140_OUTPUT:
+        case SH_GLSL_150_CORE_OUTPUT:
+        case SH_GLSL_330_CORE_OUTPUT:
+        case SH_GLSL_400_CORE_OUTPUT:
+        case SH_GLSL_410_CORE_OUTPUT:
+        case SH_GLSL_420_CORE_OUTPUT:
+        case SH_GLSL_430_CORE_OUTPUT:
+        case SH_GLSL_440_CORE_OUTPUT:
+        case SH_GLSL_450_CORE_OUTPUT:
+        case SH_GLSL_COMPATIBILITY_OUTPUT:
+#ifdef ANGLE_ENABLE_GLSL
+            return new TranslatorGLSL(type, spec, output);
+#else
+            // This compiler is not supported in this configuration. Return NULL per the
+            // sh::ConstructCompiler API.
+            return nullptr;
+#endif  // ANGLE_ENABLE_GLSL
+
+        case SH_HLSL_3_0_OUTPUT:
+        case SH_HLSL_4_1_OUTPUT:
+        case SH_HLSL_4_0_FL9_3_OUTPUT:
+#ifdef ANGLE_ENABLE_HLSL
+            return new TranslatorHLSL(type, spec, output);
+#else
+            // This compiler is not supported in this configuration. Return NULL per the
+            // sh::ConstructCompiler API.
+            return nullptr;
+#endif  // ANGLE_ENABLE_HLSL
+
+        case SH_GLSL_VULKAN_OUTPUT:
+#ifdef ANGLE_ENABLE_VULKAN
+            return new TranslatorVulkan(type, spec);
+#else
+            // This compiler is not supported in this configuration. Return NULL per the
+            // ShConstructCompiler API.
+            return nullptr;
+#endif  // ANGLE_ENABLE_VULKAN
+
+        default:
+            // Unknown format. Return NULL per the sh::ConstructCompiler API.
+            return nullptr;
+    }
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler *compiler)
+{
+    SafeDelete(compiler);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/Common.h b/src/third_party/angle/src/compiler/translator/Common.h
new file mode 100644
index 0000000..3e12d2a
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Common.h
@@ -0,0 +1,107 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_COMMON_H_
+#define COMPILER_TRANSLATOR_COMMON_H_
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <limits>
+#include <stdio.h>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "compiler/translator/PoolAlloc.h"
+
+namespace sh
+{
+
+struct TSourceLoc
+{
+    int first_file;
+    int first_line;
+    int last_file;
+    int last_line;
+};
+
+//
+// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
+//
+#define POOL_ALLOCATOR_NEW_DELETE()                                                  \
+    void *operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); }   \
+    void *operator new(size_t, void *_Where) { return (_Where); }                    \
+    void operator delete(void *) {}                                                  \
+    void operator delete(void *, void *) {}                                          \
+    void *operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
+    void *operator new[](size_t, void *_Where) { return (_Where); }                  \
+    void operator delete[](void *) {}                                                \
+    void operator delete[](void *, void *) {}
+
+//
+// Pool version of string.
+//
+typedef pool_allocator<char> TStringAllocator;
+typedef std::basic_string<char, std::char_traits<char>, TStringAllocator> TString;
+typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
+inline TString *NewPoolTString(const char *s)
+{
+    void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
+    return new (memory) TString(s);
+}
+
+//
+// Persistent string memory.  Should only be used for strings that survive
+// across compiles.
+//
+#define TPersistString std::string
+#define TPersistStringStream std::ostringstream
+
+//
+// Pool allocator versions of vectors, lists, and maps
+//
+template <class T>
+class TVector : public std::vector<T, pool_allocator<T>>
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+
+    typedef typename std::vector<T, pool_allocator<T>>::size_type size_type;
+    TVector() : std::vector<T, pool_allocator<T>>() {}
+    TVector(const pool_allocator<T> &a) : std::vector<T, pool_allocator<T>>(a) {}
+    TVector(size_type i) : std::vector<T, pool_allocator<T>>(i) {}
+};
+
+template <class K, class D, class CMP = std::less<K>>
+class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D>>>
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    typedef pool_allocator<std::pair<const K, D>> tAllocator;
+
+    TMap() : std::map<K, D, CMP, tAllocator>() {}
+    // use correct two-stage name lookup supported in gcc 3.4 and above
+    TMap(const tAllocator &a)
+        : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a)
+    {
+    }
+};
+
+// Integer to TString conversion
+template <typename T>
+inline TString str(T i)
+{
+    ASSERT(std::numeric_limits<T>::is_integer);
+    char buffer[((8 * sizeof(T)) / 3) + 3];
+    const char *formatStr = std::numeric_limits<T>::is_signed ? "%d" : "%u";
+    snprintf(buffer, sizeof(buffer), formatStr, i);
+    return buffer;
+}
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_COMMON_H_
diff --git a/src/third_party/angle/src/compiler/translator/Compiler.cpp b/src/third_party/angle/src/compiler/translator/Compiler.cpp
new file mode 100644
index 0000000..1bdb06b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Compiler.cpp
@@ -0,0 +1,1006 @@
+//
+// 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.
+//
+
+#include "compiler/translator/Compiler.h"
+
+#include <sstream>
+
+#include "angle_gl.h"
+#include "common/utilities.h"
+#include "compiler/translator/AddAndTrueToLoopCondition.h"
+#include "compiler/translator/Cache.h"
+#include "compiler/translator/CallDAG.h"
+#include "compiler/translator/DeferGlobalInitializers.h"
+#include "compiler/translator/EmulateGLFragColorBroadcast.h"
+#include "compiler/translator/EmulatePrecision.h"
+#include "compiler/translator/Initialize.h"
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/ParseContext.h"
+#include "compiler/translator/PruneEmptyDeclarations.h"
+#include "compiler/translator/RegenerateStructNames.h"
+#include "compiler/translator/RemoveInvariantDeclaration.h"
+#include "compiler/translator/RemovePow.h"
+#include "compiler/translator/RewriteDoWhile.h"
+#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
+#include "compiler/translator/UnfoldShortCircuitAST.h"
+#include "compiler/translator/UseInterfaceBlockFields.h"
+#include "compiler/translator/ValidateLimitations.h"
+#include "compiler/translator/ValidateMaxParameters.h"
+#include "compiler/translator/ValidateMultiviewWebGL.h"
+#include "compiler/translator/ValidateOutputs.h"
+#include "compiler/translator/VariablePacker.h"
+#include "third_party/compiler/ArrayBoundsClamper.h"
+
+namespace sh
+{
+
+namespace
+{
+
+#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
+void DumpFuzzerCase(char const *const *shaderStrings,
+                    size_t numStrings,
+                    uint32_t type,
+                    uint32_t spec,
+                    uint32_t output,
+                    uint64_t options)
+{
+    static int fileIndex = 0;
+
+    std::ostringstream o;
+    o << "corpus/" << fileIndex++ << ".sample";
+    std::string s = o.str();
+
+    // Must match the input format of the fuzzer
+    FILE *f = fopen(s.c_str(), "w");
+    fwrite(&type, sizeof(type), 1, f);
+    fwrite(&spec, sizeof(spec), 1, f);
+    fwrite(&output, sizeof(output), 1, f);
+    fwrite(&options, sizeof(options), 1, f);
+
+    char zero[128 - 20] = {0};
+    fwrite(&zero, 128 - 20, 1, f);
+
+    for (size_t i = 0; i < numStrings; i++)
+    {
+        fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
+    }
+    fwrite(&zero, 1, 1, f);
+
+    fclose(f);
+}
+#endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
+}  // anonymous namespace
+
+bool IsWebGLBasedSpec(ShShaderSpec spec)
+{
+    return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
+}
+
+bool IsGLSL130OrNewer(ShShaderOutput output)
+{
+    return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
+            output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
+            output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
+            output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
+            output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
+}
+
+bool IsGLSL420OrNewer(ShShaderOutput output)
+{
+    return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
+            output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
+}
+
+bool IsGLSL410OrOlder(ShShaderOutput output)
+{
+    return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
+            output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
+            output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
+}
+
+bool RemoveInvariant(sh::GLenum shaderType,
+                     int shaderVersion,
+                     ShShaderOutput outputType,
+                     ShCompileOptions compileOptions)
+{
+    if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
+        shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
+        return true;
+
+    if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
+        shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
+        return true;
+
+    return false;
+}
+
+size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
+{
+    // WebGL defines a max token length of 256, while ES2 leaves max token
+    // size undefined. ES3 defines a max size of 1024 characters.
+    switch (spec)
+    {
+        case SH_WEBGL_SPEC:
+            return 256;
+        default:
+            return 1024;
+    }
+}
+
+namespace
+{
+
+class TScopedPoolAllocator
+{
+  public:
+    TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator)
+    {
+        mAllocator->push();
+        SetGlobalPoolAllocator(mAllocator);
+    }
+    ~TScopedPoolAllocator()
+    {
+        SetGlobalPoolAllocator(nullptr);
+        mAllocator->pop();
+    }
+
+  private:
+    TPoolAllocator *mAllocator;
+};
+
+class TScopedSymbolTableLevel
+{
+  public:
+    TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
+    {
+        ASSERT(mTable->atBuiltInLevel());
+        mTable->push();
+    }
+    ~TScopedSymbolTableLevel()
+    {
+        while (!mTable->atBuiltInLevel())
+            mTable->pop();
+    }
+
+  private:
+    TSymbolTable *mTable;
+};
+
+int MapSpecToShaderVersion(ShShaderSpec spec)
+{
+    switch (spec)
+    {
+        case SH_GLES2_SPEC:
+        case SH_WEBGL_SPEC:
+            return 100;
+        case SH_GLES3_SPEC:
+        case SH_WEBGL2_SPEC:
+            return 300;
+        case SH_GLES3_1_SPEC:
+        case SH_WEBGL3_SPEC:
+            return 310;
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+}  // namespace
+
+TShHandleBase::TShHandleBase()
+{
+    allocator.push();
+    SetGlobalPoolAllocator(&allocator);
+}
+
+TShHandleBase::~TShHandleBase()
+{
+    SetGlobalPoolAllocator(nullptr);
+    allocator.popAll();
+}
+
+TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
+    : variablesCollected(false),
+      shaderType(type),
+      shaderSpec(spec),
+      outputType(output),
+      maxUniformVectors(0),
+      maxExpressionComplexity(0),
+      maxCallStackDepth(0),
+      maxFunctionParameters(0),
+      fragmentPrecisionHigh(false),
+      clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
+      builtInFunctionEmulator(),
+      mDiagnostics(infoSink.info),
+      mSourcePath(nullptr),
+      mComputeShaderLocalSizeDeclared(false),
+      mTemporaryIndex(0)
+{
+    mComputeShaderLocalSize.fill(1);
+}
+
+TCompiler::~TCompiler()
+{
+}
+
+bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
+{
+    // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
+    // validate loop and indexing as well (to verify that the shader only uses minimal functionality
+    // of ESSL 1.00 as in Appendix A of the spec).
+    return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) ||
+           (compileOptions & SH_VALIDATE_LOOP_INDEXING);
+}
+
+bool TCompiler::Init(const ShBuiltInResources &resources)
+{
+    shaderVersion     = 100;
+    maxUniformVectors = (shaderType == GL_VERTEX_SHADER) ? resources.MaxVertexUniformVectors
+                                                         : resources.MaxFragmentUniformVectors;
+    maxExpressionComplexity = resources.MaxExpressionComplexity;
+    maxCallStackDepth       = resources.MaxCallStackDepth;
+    maxFunctionParameters   = resources.MaxFunctionParameters;
+
+    SetGlobalPoolAllocator(&allocator);
+
+    // Generate built-in symbol table.
+    if (!InitBuiltInSymbolTable(resources))
+        return false;
+    InitExtensionBehavior(resources, extensionBehavior);
+    fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
+
+    arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
+    clampingStrategy = resources.ArrayIndexClampingStrategy;
+
+    hashFunction = resources.HashFunction;
+
+    return true;
+}
+
+TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
+                                               size_t numStrings,
+                                               ShCompileOptions compileOptions)
+{
+    return compileTreeImpl(shaderStrings, numStrings, compileOptions);
+}
+
+TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
+                                         size_t numStrings,
+                                         const ShCompileOptions compileOptions)
+{
+    clearResults();
+
+    ASSERT(numStrings > 0);
+    ASSERT(GetGlobalPoolAllocator());
+
+    // Reset the extension behavior for each compilation unit.
+    ResetExtensionBehavior(extensionBehavior);
+
+    // First string is path of source file if flag is set. The actual source follows.
+    size_t firstSource = 0;
+    if (compileOptions & SH_SOURCE_PATH)
+    {
+        mSourcePath = shaderStrings[0];
+        ++firstSource;
+    }
+
+    TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
+                               compileOptions, true, &mDiagnostics, getResources());
+
+    parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
+
+    // We preserve symbols at the built-in level from compile-to-compile.
+    // Start pushing the user-defined symbols at global level.
+    TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
+
+    // Parse shader.
+    bool success = (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
+                                   &parseContext) == 0) &&
+                   (parseContext.getTreeRoot() != nullptr);
+
+    shaderVersion = parseContext.getShaderVersion();
+    if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
+    {
+        mDiagnostics.globalError("unsupported shader version");
+        success = false;
+    }
+
+    TIntermBlock *root = nullptr;
+
+    if (success)
+    {
+        mPragma = parseContext.pragma();
+        symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
+
+        mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
+        mComputeShaderLocalSize         = parseContext.getComputeShaderLocalSize();
+
+        mNumViews = parseContext.getNumViews();
+
+        root = parseContext.getTreeRoot();
+
+        // Highp might have been auto-enabled based on shader version
+        fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
+
+        if (success && (IsWebGLBasedSpec(shaderSpec) &&
+                        IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview") &&
+                        IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview2")))
+        {
+            // Can't enable both extensions at the same time.
+            mDiagnostics.globalError("Can't enable both OVR_multiview and OVR_multiview2");
+            success = false;
+        }
+
+        // Disallow expressions deemed too complex.
+        if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
+            success = limitExpressionComplexity(root);
+
+        // Create the function DAG and check there is no recursion
+        if (success)
+            success = initCallDag(root);
+
+        if (success && (compileOptions & SH_LIMIT_CALL_STACK_DEPTH))
+            success = checkCallDepth();
+
+        // Checks which functions are used and if "main" exists
+        if (success)
+        {
+            functionMetadata.clear();
+            functionMetadata.resize(mCallDag.size());
+            success = tagUsedFunctions();
+        }
+
+        if (success && !(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
+            success = pruneUnusedFunctions(root);
+
+        // Prune empty declarations to work around driver bugs and to keep declaration output
+        // simple.
+        if (success)
+            PruneEmptyDeclarations(root);
+
+        if (success && shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER)
+            success = validateOutputs(root);
+
+        if (success && shouldRunLoopAndIndexingValidation(compileOptions))
+            success =
+                ValidateLimitations(root, shaderType, symbolTable, shaderVersion, &mDiagnostics);
+
+        bool multiview2 = IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview2");
+        if (success && compileResources.OVR_multiview && IsWebGLBasedSpec(shaderSpec) &&
+            (IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview") || multiview2))
+            success = ValidateMultiviewWebGL(root, shaderType, symbolTable, shaderVersion,
+                                             multiview2, &mDiagnostics);
+
+        // Fail compilation if precision emulation not supported.
+        if (success && getResources().WEBGL_debug_shader_precision &&
+            getPragma().debugShaderPrecision)
+        {
+            if (!EmulatePrecision::SupportedInLanguage(outputType))
+            {
+                mDiagnostics.globalError("Precision emulation not supported for this output type.");
+                success = false;
+            }
+        }
+
+        // Built-in function emulation needs to happen after validateLimitations pass.
+        if (success)
+        {
+            // TODO(jmadill): Remove global pool allocator.
+            GetGlobalPoolAllocator()->lock();
+            initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
+            GetGlobalPoolAllocator()->unlock();
+            builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
+        }
+
+        // Clamping uniform array bounds needs to happen after validateLimitations pass.
+        if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
+            arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
+
+        // gl_Position is always written in compatibility output mode
+        if (success && shaderType == GL_VERTEX_SHADER &&
+            ((compileOptions & SH_INIT_GL_POSITION) ||
+             (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
+            initializeGLPosition(root);
+
+        // This pass might emit short circuits so keep it before the short circuit unfolding
+        if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
+            RewriteDoWhile(root, getTemporaryIndex());
+
+        if (success && (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION))
+            sh::AddAndTrueToLoopCondition(root);
+
+        if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
+        {
+            UnfoldShortCircuitAST unfoldShortCircuit;
+            root->traverse(&unfoldShortCircuit);
+            unfoldShortCircuit.updateTree();
+        }
+
+        if (success && (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT))
+        {
+            RemovePow(root);
+        }
+
+        if (success && shouldCollectVariables(compileOptions))
+        {
+            collectVariables(root);
+            if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
+            {
+                useAllMembersInUnusedStandardAndSharedBlocks(root);
+            }
+            if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
+            {
+                success = enforcePackingRestrictions();
+                if (!success)
+                {
+                    mDiagnostics.globalError("too many uniforms");
+                }
+            }
+            if (success && (compileOptions & SH_INIT_OUTPUT_VARIABLES))
+            {
+                initializeOutputVariables(root);
+            }
+        }
+
+        // Removing invariant declarations must be done after collecting variables.
+        // Otherwise, built-in invariant declarations don't apply.
+        if (success && RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
+            sh::RemoveInvariantDeclaration(root);
+
+        if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS))
+        {
+            ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh,
+                                              &mTemporaryIndex);
+        }
+
+        if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES))
+        {
+            RegenerateStructNames gen(symbolTable, shaderVersion);
+            root->traverse(&gen);
+        }
+
+        if (success && shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
+            compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
+            IsExtensionEnabled(extensionBehavior, "GL_EXT_draw_buffers"))
+        {
+            EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables);
+        }
+
+        if (success)
+        {
+            DeferGlobalInitializers(root);
+        }
+    }
+
+    if (success)
+        return root;
+
+    return nullptr;
+}
+
+bool TCompiler::compile(const char *const shaderStrings[],
+                        size_t numStrings,
+                        ShCompileOptions compileOptionsIn)
+{
+#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
+    DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
+#endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
+
+    if (numStrings == 0)
+        return true;
+
+    ShCompileOptions compileOptions = compileOptionsIn;
+
+    // Apply key workarounds.
+    if (shouldFlattenPragmaStdglInvariantAll())
+    {
+        // This should be harmless to do in all cases, but for the moment, do it only conditionally.
+        compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
+    }
+
+    TScopedPoolAllocator scopedAlloc(&allocator);
+    TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
+
+    if (root)
+    {
+        if (compileOptions & SH_INTERMEDIATE_TREE)
+            TIntermediate::outputTree(root, infoSink.info);
+
+        if (compileOptions & SH_OBJECT_CODE)
+            translate(root, compileOptions);
+
+        // The IntermNode tree doesn't need to be deleted here, since the
+        // memory will be freed in a big chunk by the PoolAllocator.
+        return true;
+    }
+    return false;
+}
+
+bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
+{
+    if (resources.MaxDrawBuffers < 1)
+    {
+        return false;
+    }
+    if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
+    {
+        return false;
+    }
+
+    compileResources = resources;
+    setResourceString();
+
+    assert(symbolTable.isEmpty());
+    symbolTable.push();  // COMMON_BUILTINS
+    symbolTable.push();  // ESSL1_BUILTINS
+    symbolTable.push();  // ESSL3_BUILTINS
+    symbolTable.push();  // ESSL3_1_BUILTINS
+
+    TPublicType integer;
+    integer.initializeBasicType(EbtInt);
+
+    TPublicType floatingPoint;
+    floatingPoint.initializeBasicType(EbtFloat);
+
+    switch (shaderType)
+    {
+        case GL_FRAGMENT_SHADER:
+            symbolTable.setDefaultPrecision(integer, EbpMedium);
+            break;
+        case GL_VERTEX_SHADER:
+            symbolTable.setDefaultPrecision(integer, EbpHigh);
+            symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
+            break;
+        case GL_COMPUTE_SHADER:
+            symbolTable.setDefaultPrecision(integer, EbpHigh);
+            symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
+            break;
+        default:
+            assert(false && "Language not supported");
+    }
+    // Set defaults for sampler types that have default precision, even those that are
+    // only available if an extension exists.
+    // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
+    initSamplerDefaultPrecision(EbtSampler2D);
+    initSamplerDefaultPrecision(EbtSamplerCube);
+    // SamplerExternalOES is specified in the extension to have default precision.
+    initSamplerDefaultPrecision(EbtSamplerExternalOES);
+    // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
+    initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
+    // It isn't specified whether Sampler2DRect has default precision.
+    initSamplerDefaultPrecision(EbtSampler2DRect);
+
+    InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
+
+    IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
+
+    return true;
+}
+
+void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
+{
+    ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
+    TPublicType sampler;
+    sampler.initializeBasicType(samplerType);
+    symbolTable.setDefaultPrecision(sampler, EbpLow);
+}
+
+void TCompiler::setResourceString()
+{
+    std::ostringstream strstream;
+
+    // clang-format off
+    strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
+        << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
+        << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
+        << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
+        << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
+        << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
+        << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
+        << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
+        << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
+        << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
+        << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
+        << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
+        << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
+        << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
+        << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
+        << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
+        << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
+        << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
+        << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
+        << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
+        << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
+        << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
+        << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
+        << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
+        << ":EXT_YUV_target:" << compileResources.EXT_YUV_target
+        << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
+        << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
+        << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
+        << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
+        << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
+        << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
+        << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
+        << ":MaxImageUnits:" << compileResources.MaxImageUnits
+        << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
+        << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
+        << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
+        << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
+        << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
+        << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
+        << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
+        << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
+        << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
+        << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
+        << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
+        << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
+        << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
+        << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
+        << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
+        << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
+        << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
+        << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
+        << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
+        << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
+        << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
+        << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
+        << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize;
+    // clang-format on
+
+    builtInResourcesString = strstream.str();
+}
+
+void TCompiler::clearResults()
+{
+    arrayBoundsClamper.Cleanup();
+    infoSink.info.erase();
+    infoSink.obj.erase();
+    infoSink.debug.erase();
+    mDiagnostics.resetErrorCount();
+
+    attributes.clear();
+    outputVariables.clear();
+    uniforms.clear();
+    expandedUniforms.clear();
+    varyings.clear();
+    interfaceBlocks.clear();
+    variablesCollected = false;
+
+    mNumViews = -1;
+
+    builtInFunctionEmulator.cleanup();
+
+    nameMap.clear();
+
+    mSourcePath     = nullptr;
+    mTemporaryIndex = 0;
+}
+
+bool TCompiler::initCallDag(TIntermNode *root)
+{
+    mCallDag.clear();
+
+    switch (mCallDag.init(root, &mDiagnostics))
+    {
+        case CallDAG::INITDAG_SUCCESS:
+            return true;
+        case CallDAG::INITDAG_RECURSION:
+        case CallDAG::INITDAG_UNDEFINED:
+            // Error message has already been written out.
+            ASSERT(mDiagnostics.numErrors() > 0);
+            return false;
+    }
+
+    UNREACHABLE();
+    return true;
+}
+
+bool TCompiler::checkCallDepth()
+{
+    std::vector<int> depths(mCallDag.size());
+
+    for (size_t i = 0; i < mCallDag.size(); i++)
+    {
+        int depth    = 0;
+        auto &record = mCallDag.getRecordFromIndex(i);
+
+        for (auto &calleeIndex : record.callees)
+        {
+            depth = std::max(depth, depths[calleeIndex] + 1);
+        }
+
+        depths[i] = depth;
+
+        if (depth >= maxCallStackDepth)
+        {
+            // Trace back the function chain to have a meaningful info log.
+            std::stringstream errorStream;
+            errorStream << "Call stack too deep (larger than " << maxCallStackDepth
+                        << ") with the following call chain: " << record.name;
+
+            int currentFunction = static_cast<int>(i);
+            int currentDepth    = depth;
+
+            while (currentFunction != -1)
+            {
+                errorStream << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
+
+                int nextFunction = -1;
+                for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
+                {
+                    if (depths[calleeIndex] == currentDepth - 1)
+                    {
+                        currentDepth--;
+                        nextFunction = calleeIndex;
+                    }
+                }
+
+                currentFunction = nextFunction;
+            }
+
+            std::string errorStr = errorStream.str();
+            mDiagnostics.globalError(errorStr.c_str());
+
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool TCompiler::tagUsedFunctions()
+{
+    // Search from main, starting from the end of the DAG as it usually is the root.
+    for (size_t i = mCallDag.size(); i-- > 0;)
+    {
+        if (mCallDag.getRecordFromIndex(i).name == "main")
+        {
+            internalTagUsedFunction(i);
+            return true;
+        }
+    }
+
+    mDiagnostics.globalError("Missing main()");
+    return false;
+}
+
+void TCompiler::internalTagUsedFunction(size_t index)
+{
+    if (functionMetadata[index].used)
+    {
+        return;
+    }
+
+    functionMetadata[index].used = true;
+
+    for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
+    {
+        internalTagUsedFunction(calleeIndex);
+    }
+}
+
+// A predicate for the stl that returns if a top-level node is unused
+class TCompiler::UnusedPredicate
+{
+  public:
+    UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
+        : mCallDag(callDag), mMetadatas(metadatas)
+    {
+    }
+
+    bool operator()(TIntermNode *node)
+    {
+        const TIntermFunctionPrototype *asFunctionPrototype   = node->getAsFunctionPrototypeNode();
+        const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
+
+        const TFunctionSymbolInfo *functionInfo = nullptr;
+
+        if (asFunctionDefinition)
+        {
+            functionInfo = asFunctionDefinition->getFunctionSymbolInfo();
+        }
+        else if (asFunctionPrototype)
+        {
+            functionInfo = asFunctionPrototype->getFunctionSymbolInfo();
+        }
+        if (functionInfo == nullptr)
+        {
+            return false;
+        }
+
+        size_t callDagIndex = mCallDag->findIndex(functionInfo);
+        if (callDagIndex == CallDAG::InvalidIndex)
+        {
+            // This happens only for unimplemented prototypes which are thus unused
+            ASSERT(asFunctionPrototype);
+            return true;
+        }
+
+        ASSERT(callDagIndex < mMetadatas->size());
+        return !(*mMetadatas)[callDagIndex].used;
+    }
+
+  private:
+    const CallDAG *mCallDag;
+    const std::vector<FunctionMetadata> *mMetadatas;
+};
+
+bool TCompiler::pruneUnusedFunctions(TIntermBlock *root)
+{
+    UnusedPredicate isUnused(&mCallDag, &functionMetadata);
+    TIntermSequence *sequence = root->getSequence();
+
+    if (!sequence->empty())
+    {
+        sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
+                        sequence->end());
+    }
+
+    return true;
+}
+
+bool TCompiler::validateOutputs(TIntermNode *root)
+{
+    ValidateOutputs validateOutputs(getExtensionBehavior(), compileResources.MaxDrawBuffers);
+    root->traverse(&validateOutputs);
+    validateOutputs.validate(&mDiagnostics);
+    return (mDiagnostics.numErrors() == 0);
+}
+
+bool TCompiler::limitExpressionComplexity(TIntermNode *root)
+{
+    TMaxDepthTraverser traverser(maxExpressionComplexity + 1);
+    root->traverse(&traverser);
+
+    if (traverser.getMaxDepth() > maxExpressionComplexity)
+    {
+        mDiagnostics.globalError("Expression too complex.");
+        return false;
+    }
+
+    if (!ValidateMaxParameters::validate(root, maxFunctionParameters))
+    {
+        mDiagnostics.globalError("Function has too many parameters.");
+        return false;
+    }
+
+    return true;
+}
+
+void TCompiler::collectVariables(TIntermNode *root)
+{
+    if (!variablesCollected)
+    {
+        sh::CollectVariables collect(&attributes, &outputVariables, &uniforms, &varyings,
+                                     &interfaceBlocks, hashFunction, symbolTable,
+                                     extensionBehavior);
+        root->traverse(&collect);
+
+        // This is for enforcePackingRestriction().
+        sh::ExpandUniforms(uniforms, &expandedUniforms);
+        variablesCollected = true;
+    }
+}
+
+bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
+{
+    return (compileOptions & SH_VARIABLES) != 0;
+}
+
+bool TCompiler::wereVariablesCollected() const
+{
+    return variablesCollected;
+}
+
+bool TCompiler::enforcePackingRestrictions()
+{
+    VariablePacker packer;
+    return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, expandedUniforms);
+}
+
+void TCompiler::initializeGLPosition(TIntermBlock *root)
+{
+    InitVariableList list;
+    sh::ShaderVariable var(GL_FLOAT_VEC4, 0);
+    var.name = "gl_Position";
+    list.push_back(var);
+    InitializeVariables(root, list, symbolTable);
+}
+
+void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
+{
+    sh::InterfaceBlockList list;
+
+    for (auto block : interfaceBlocks)
+    {
+        if (!block.staticUse &&
+            (block.layout == sh::BLOCKLAYOUT_STANDARD || block.layout == sh::BLOCKLAYOUT_SHARED))
+        {
+            list.push_back(block);
+        }
+    }
+
+    sh::UseInterfaceBlockFields(root, list, symbolTable);
+}
+
+void TCompiler::initializeOutputVariables(TIntermBlock *root)
+{
+    InitVariableList list;
+    if (shaderType == GL_VERTEX_SHADER)
+    {
+        for (auto var : varyings)
+        {
+            list.push_back(var);
+        }
+    }
+    else
+    {
+        ASSERT(shaderType == GL_FRAGMENT_SHADER);
+        for (auto var : outputVariables)
+        {
+            list.push_back(var);
+        }
+    }
+    InitializeVariables(root, list, symbolTable);
+}
+
+const TExtensionBehavior &TCompiler::getExtensionBehavior() const
+{
+    return extensionBehavior;
+}
+
+const char *TCompiler::getSourcePath() const
+{
+    return mSourcePath;
+}
+
+const ShBuiltInResources &TCompiler::getResources() const
+{
+    return compileResources;
+}
+
+const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
+{
+    return arrayBoundsClamper;
+}
+
+ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
+{
+    return clampingStrategy;
+}
+
+const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
+{
+    return builtInFunctionEmulator;
+}
+
+void TCompiler::writePragma(ShCompileOptions compileOptions)
+{
+    if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
+    {
+        TInfoSinkBase &sink = infoSink.obj;
+        if (mPragma.stdgl.invariantAll)
+            sink << "#pragma STDGL invariant(all)\n";
+    }
+}
+
+bool TCompiler::isVaryingDefined(const char *varyingName)
+{
+    ASSERT(variablesCollected);
+    for (size_t ii = 0; ii < varyings.size(); ++ii)
+    {
+        if (varyings[ii].name == varyingName)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/Compiler.h b/src/third_party/angle/src/compiler/translator/Compiler.h
new file mode 100644
index 0000000..2614199
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Compiler.h
@@ -0,0 +1,274 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_COMPILER_H_
+#define COMPILER_TRANSLATOR_COMPILER_H_
+
+//
+// Machine independent part of the compiler private objects
+// sent as ShHandle to the driver.
+//
+// This should not be included by driver code.
+//
+
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/CallDAG.h"
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/ExtensionBehavior.h"
+#include "compiler/translator/HashNames.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/Pragma.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/VariableInfo.h"
+#include "third_party/compiler/ArrayBoundsClamper.h"
+
+namespace sh
+{
+
+class TCompiler;
+#ifdef ANGLE_ENABLE_HLSL
+class TranslatorHLSL;
+#endif  // ANGLE_ENABLE_HLSL
+
+//
+// Helper function to identify specs that are based on the WebGL spec.
+//
+bool IsWebGLBasedSpec(ShShaderSpec spec);
+
+//
+// Helper function to check if the shader type is GLSL.
+//
+bool IsGLSL130OrNewer(ShShaderOutput output);
+bool IsGLSL420OrNewer(ShShaderOutput output);
+bool IsGLSL410OrOlder(ShShaderOutput output);
+
+//
+// Helper function to check if the invariant qualifier can be removed.
+//
+bool RemoveInvariant(sh::GLenum shaderType,
+                     int shaderVersion,
+                     ShShaderOutput outputType,
+                     ShCompileOptions compileOptions);
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase
+{
+  public:
+    TShHandleBase();
+    virtual ~TShHandleBase();
+    virtual TCompiler *getAsCompiler() { return 0; }
+#ifdef ANGLE_ENABLE_HLSL
+    virtual TranslatorHLSL *getAsTranslatorHLSL() { return 0; }
+#endif  // ANGLE_ENABLE_HLSL
+
+  protected:
+    // Memory allocator. Allocates and tracks memory required by the compiler.
+    // Deallocates all memory when compiler is destructed.
+    TPoolAllocator allocator;
+};
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase
+{
+  public:
+    TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
+    ~TCompiler() override;
+    TCompiler *getAsCompiler() override { return this; }
+
+    bool Init(const ShBuiltInResources &resources);
+
+    // compileTreeForTesting should be used only when tests require access to
+    // the AST. Users of this function need to manually manage the global pool
+    // allocator. Returns nullptr whenever there are compilation errors.
+    TIntermBlock *compileTreeForTesting(const char *const shaderStrings[],
+                                        size_t numStrings,
+                                        ShCompileOptions compileOptions);
+
+    bool compile(const char *const shaderStrings[],
+                 size_t numStrings,
+                 ShCompileOptions compileOptions);
+
+    // Get results of the last compilation.
+    int getShaderVersion() const { return shaderVersion; }
+    TInfoSink &getInfoSink() { return infoSink; }
+
+    bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; }
+    const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
+    int getNumViews() const { return mNumViews; }
+
+    // Clears the results from the previous compilation.
+    void clearResults();
+
+    const std::vector<sh::Attribute> &getAttributes() const { return attributes; }
+    const std::vector<sh::OutputVariable> &getOutputVariables() const { return outputVariables; }
+    const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
+    const std::vector<sh::Varying> &getVaryings() const { return varyings; }
+    const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
+
+    ShHashFunction64 getHashFunction() const { return hashFunction; }
+    NameMap &getNameMap() { return nameMap; }
+    TSymbolTable &getSymbolTable() { return symbolTable; }
+    ShShaderSpec getShaderSpec() const { return shaderSpec; }
+    ShShaderOutput getOutputType() const { return outputType; }
+    const std::string &getBuiltInResourcesString() const { return builtInResourcesString; }
+
+    bool shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const;
+
+    // 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();
+    // Return false if the call depth is exceeded.
+    bool checkCallDepth();
+    // Returns true if a program has no conflicting or missing fragment outputs
+    bool validateOutputs(TIntermNode *root);
+    // Add emulated functions to the built-in function emulator.
+    virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+                                             ShCompileOptions compileOptions){};
+    // Translate to object code.
+    virtual void translate(TIntermBlock *root, ShCompileOptions compileOptions) = 0;
+    // Returns true if, after applying the packing rules in the GLSL 1.017 spec
+    // Appendix A, section 7, the shader does not use too many uniforms.
+    bool enforcePackingRestrictions();
+    // Insert statements to reference all members in unused uniform blocks with standard and shared
+    // layout. This is to work around a Mac driver that treats unused standard/shared
+    // uniform blocks as inactive.
+    void useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root);
+    // Insert statements to initialize output variables in the beginning of main().
+    // This is to avoid undefined behaviors.
+    void initializeOutputVariables(TIntermBlock *root);
+    // Insert gl_Position = vec4(0,0,0,0) to the beginning of main().
+    // It is to work around a Linux driver bug where missing this causes compile failure
+    // while spec says it is allowed.
+    // This function should only be applied to vertex shaders.
+    void initializeGLPosition(TIntermBlock *root);
+    // 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;
+    const char *getSourcePath() const;
+    const TPragma &getPragma() const { return mPragma; }
+    void writePragma(ShCompileOptions compileOptions);
+    unsigned int *getTemporaryIndex() { return &mTemporaryIndex; }
+    // Relies on collectVariables having been called.
+    bool isVaryingDefined(const char *varyingName);
+
+    const ArrayBoundsClamper &getArrayBoundsClamper() const;
+    ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
+    const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const;
+
+    virtual bool shouldFlattenPragmaStdglInvariantAll() = 0;
+    virtual bool shouldCollectVariables(ShCompileOptions compileOptions);
+
+    bool wereVariablesCollected() const;
+    std::vector<sh::Attribute> attributes;
+    std::vector<sh::OutputVariable> outputVariables;
+    std::vector<sh::Uniform> uniforms;
+    std::vector<sh::ShaderVariable> expandedUniforms;
+    std::vector<sh::Varying> varyings;
+    std::vector<sh::InterfaceBlock> interfaceBlocks;
+
+  private:
+    // Creates the function call DAG for further analysis, returning false if there is a recursion
+    bool initCallDag(TIntermNode *root);
+    // Return false if "main" doesn't exist
+    bool tagUsedFunctions();
+    void internalTagUsedFunction(size_t index);
+
+    void initSamplerDefaultPrecision(TBasicType samplerType);
+
+    // Collect info for all attribs, uniforms, varyings.
+    void collectVariables(TIntermNode *root);
+
+    bool variablesCollected;
+
+    // Removes unused function declarations and prototypes from the AST
+    class UnusedPredicate;
+    bool pruneUnusedFunctions(TIntermBlock *root);
+
+    TIntermBlock *compileTreeImpl(const char *const shaderStrings[],
+                                  size_t numStrings,
+                                  const ShCompileOptions compileOptions);
+
+    sh::GLenum shaderType;
+    ShShaderSpec shaderSpec;
+    ShShaderOutput outputType;
+
+    struct FunctionMetadata
+    {
+        FunctionMetadata() : used(false) {}
+        bool used;
+    };
+
+    CallDAG mCallDag;
+    std::vector<FunctionMetadata> functionMetadata;
+
+    int maxUniformVectors;
+    int maxExpressionComplexity;
+    int maxCallStackDepth;
+    int maxFunctionParameters;
+
+    ShBuiltInResources compileResources;
+    std::string builtInResourcesString;
+
+    // Built-in symbol table for the given language, spec, and resources.
+    // It is preserved from compile-to-compile.
+    TSymbolTable symbolTable;
+    // Built-in extensions with default behavior.
+    TExtensionBehavior extensionBehavior;
+    bool fragmentPrecisionHigh;
+
+    ArrayBoundsClamper arrayBoundsClamper;
+    ShArrayIndexClampingStrategy clampingStrategy;
+    BuiltInFunctionEmulator builtInFunctionEmulator;
+
+    // Results of compilation.
+    int shaderVersion;
+    TInfoSink infoSink;       // Output sink.
+    TDiagnostics mDiagnostics;
+    const char *mSourcePath;  // Path of source file or NULL
+
+    // compute shader local group size
+    bool mComputeShaderLocalSizeDeclared;
+    sh::WorkGroupSize mComputeShaderLocalSize;
+
+    // GL_OVR_multiview num_views.
+    int mNumViews;
+
+    // name hashing.
+    ShHashFunction64 hashFunction;
+    NameMap nameMap;
+
+    TPragma mPragma;
+
+    unsigned int mTemporaryIndex;
+};
+
+//
+// This is the interface between the machine independent code
+// and the machine dependent code.
+//
+// The machine dependent code should derive from the classes
+// above. Then Construct*() and Delete*() will create and
+// destroy the machine dependent objects, which contain the
+// above machine independent information.
+//
+TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
+void DeleteCompiler(TCompiler *);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_COMPILER_H_
diff --git a/src/third_party/angle/src/compiler/translator/ConstantUnion.cpp b/src/third_party/angle/src/compiler/translator/ConstantUnion.cpp
new file mode 100644
index 0000000..b960e42
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ConstantUnion.cpp
@@ -0,0 +1,651 @@
+//
+// Copyright 2016 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.
+//
+// ConstantUnion: Constant folding helper class.
+
+#include "compiler/translator/ConstantUnion.h"
+
+#include "common/mathutil.h"
+#include "compiler/translator/Diagnostics.h"
+
+namespace sh
+{
+
+namespace
+{
+
+float CheckedSum(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
+{
+    float result = lhs + rhs;
+    if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
+    {
+        diag->warning(line, "Constant folded undefined addition generated NaN", "+");
+    }
+    else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
+    {
+        diag->warning(line, "Constant folded addition overflowed to infinity", "+");
+    }
+    return result;
+}
+
+float CheckedDiff(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
+{
+    float result = lhs - rhs;
+    if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
+    {
+        diag->warning(line, "Constant folded undefined subtraction generated NaN", "-");
+    }
+    else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
+    {
+        diag->warning(line, "Constant folded subtraction overflowed to infinity", "-");
+    }
+    return result;
+}
+
+float CheckedMul(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
+{
+    float result = lhs * rhs;
+    if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
+    {
+        diag->warning(line, "Constant folded undefined multiplication generated NaN", "*");
+    }
+    else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
+    {
+        diag->warning(line, "Constant folded multiplication overflowed to infinity", "*");
+    }
+    return result;
+}
+
+bool IsValidShiftOffset(const TConstantUnion &rhs)
+{
+    return (rhs.getType() == EbtInt && (rhs.getIConst() >= 0 && rhs.getIConst() <= 31)) ||
+           (rhs.getType() == EbtUInt && rhs.getUConst() <= 31u);
+}
+
+}  // anonymous namespace
+
+TConstantUnion::TConstantUnion()
+{
+    iConst = 0;
+    type   = EbtVoid;
+}
+
+bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant)
+{
+    switch (newType)
+    {
+        case EbtFloat:
+            switch (constant.type)
+            {
+                case EbtInt:
+                    setFConst(static_cast<float>(constant.getIConst()));
+                    break;
+                case EbtUInt:
+                    setFConst(static_cast<float>(constant.getUConst()));
+                    break;
+                case EbtBool:
+                    setFConst(static_cast<float>(constant.getBConst()));
+                    break;
+                case EbtFloat:
+                    setFConst(static_cast<float>(constant.getFConst()));
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        case EbtInt:
+            switch (constant.type)
+            {
+                case EbtInt:
+                    setIConst(static_cast<int>(constant.getIConst()));
+                    break;
+                case EbtUInt:
+                    setIConst(static_cast<int>(constant.getUConst()));
+                    break;
+                case EbtBool:
+                    setIConst(static_cast<int>(constant.getBConst()));
+                    break;
+                case EbtFloat:
+                    setIConst(static_cast<int>(constant.getFConst()));
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        case EbtUInt:
+            switch (constant.type)
+            {
+                case EbtInt:
+                    setUConst(static_cast<unsigned int>(constant.getIConst()));
+                    break;
+                case EbtUInt:
+                    setUConst(static_cast<unsigned int>(constant.getUConst()));
+                    break;
+                case EbtBool:
+                    setUConst(static_cast<unsigned int>(constant.getBConst()));
+                    break;
+                case EbtFloat:
+                    setUConst(static_cast<unsigned int>(constant.getFConst()));
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        case EbtBool:
+            switch (constant.type)
+            {
+                case EbtInt:
+                    setBConst(constant.getIConst() != 0);
+                    break;
+                case EbtUInt:
+                    setBConst(constant.getUConst() != 0);
+                    break;
+                case EbtBool:
+                    setBConst(constant.getBConst());
+                    break;
+                case EbtFloat:
+                    setBConst(constant.getFConst() != 0.0f);
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        case EbtStruct:  // Struct fields don't get cast
+            switch (constant.type)
+            {
+                case EbtInt:
+                    setIConst(constant.getIConst());
+                    break;
+                case EbtUInt:
+                    setUConst(constant.getUConst());
+                    break;
+                case EbtBool:
+                    setBConst(constant.getBConst());
+                    break;
+                case EbtFloat:
+                    setFConst(constant.getFConst());
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        default:
+            return false;
+    }
+
+    return true;
+}
+
+bool TConstantUnion::operator==(const int i) const
+{
+    return i == iConst;
+}
+
+bool TConstantUnion::operator==(const unsigned int u) const
+{
+    return u == uConst;
+}
+
+bool TConstantUnion::operator==(const float f) const
+{
+    return f == fConst;
+}
+
+bool TConstantUnion::operator==(const bool b) const
+{
+    return b == bConst;
+}
+
+bool TConstantUnion::operator==(const TYuvCscStandardEXT s) const
+{
+    return s == yuvCscStandardEXTConst;
+}
+
+bool TConstantUnion::operator==(const TConstantUnion &constant) const
+{
+    if (constant.type != type)
+        return false;
+
+    switch (type)
+    {
+        case EbtInt:
+            return constant.iConst == iConst;
+        case EbtUInt:
+            return constant.uConst == uConst;
+        case EbtFloat:
+            return constant.fConst == fConst;
+        case EbtBool:
+            return constant.bConst == bConst;
+        case EbtYuvCscStandardEXT:
+            return constant.yuvCscStandardEXTConst == yuvCscStandardEXTConst;
+        default:
+            return false;
+    }
+}
+
+bool TConstantUnion::operator!=(const int i) const
+{
+    return !operator==(i);
+}
+
+bool TConstantUnion::operator!=(const unsigned int u) const
+{
+    return !operator==(u);
+}
+
+bool TConstantUnion::operator!=(const float f) const
+{
+    return !operator==(f);
+}
+
+bool TConstantUnion::operator!=(const bool b) const
+{
+    return !operator==(b);
+}
+
+bool TConstantUnion::operator!=(const TYuvCscStandardEXT s) const
+{
+    return !operator==(s);
+}
+
+bool TConstantUnion::operator!=(const TConstantUnion &constant) const
+{
+    return !operator==(constant);
+}
+
+bool TConstantUnion::operator>(const TConstantUnion &constant) const
+{
+    ASSERT(type == constant.type);
+    switch (type)
+    {
+        case EbtInt:
+            return iConst > constant.iConst;
+        case EbtUInt:
+            return uConst > constant.uConst;
+        case EbtFloat:
+            return fConst > constant.fConst;
+        default:
+            return false;  // Invalid operation, handled at semantic analysis
+    }
+}
+
+bool TConstantUnion::operator<(const TConstantUnion &constant) const
+{
+    ASSERT(type == constant.type);
+    switch (type)
+    {
+        case EbtInt:
+            return iConst < constant.iConst;
+        case EbtUInt:
+            return uConst < constant.uConst;
+        case EbtFloat:
+            return fConst < constant.fConst;
+        default:
+            return false;  // Invalid operation, handled at semantic analysis
+    }
+}
+
+// static
+TConstantUnion TConstantUnion::add(const TConstantUnion &lhs,
+                                   const TConstantUnion &rhs,
+                                   TDiagnostics *diag,
+                                   const TSourceLoc &line)
+{
+    TConstantUnion returnValue;
+    ASSERT(lhs.type == rhs.type);
+    switch (lhs.type)
+    {
+        case EbtInt:
+            returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst));
+            break;
+        case EbtUInt:
+            returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst));
+            break;
+        case EbtFloat:
+            returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line));
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return returnValue;
+}
+
+// static
+TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs,
+                                   const TConstantUnion &rhs,
+                                   TDiagnostics *diag,
+                                   const TSourceLoc &line)
+{
+    TConstantUnion returnValue;
+    ASSERT(lhs.type == rhs.type);
+    switch (lhs.type)
+    {
+        case EbtInt:
+            returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst));
+            break;
+        case EbtUInt:
+            returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst));
+            break;
+        case EbtFloat:
+            returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line));
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return returnValue;
+}
+
+// static
+TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs,
+                                   const TConstantUnion &rhs,
+                                   TDiagnostics *diag,
+                                   const TSourceLoc &line)
+{
+    TConstantUnion returnValue;
+    ASSERT(lhs.type == rhs.type);
+    switch (lhs.type)
+    {
+        case EbtInt:
+            returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst));
+            break;
+        case EbtUInt:
+            // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely on that
+            // to implement wrapping multiplication.
+            returnValue.setUConst(lhs.uConst * rhs.uConst);
+            break;
+        case EbtFloat:
+            returnValue.setFConst(CheckedMul(lhs.fConst, rhs.fConst, diag, line));
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const
+{
+    TConstantUnion returnValue;
+    ASSERT(type == constant.type);
+    switch (type)
+    {
+        case EbtInt:
+            returnValue.setIConst(iConst % constant.iConst);
+            break;
+        case EbtUInt:
+            returnValue.setUConst(uConst % constant.uConst);
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return returnValue;
+}
+
+// static
+TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs,
+                                      const TConstantUnion &rhs,
+                                      TDiagnostics *diag,
+                                      const TSourceLoc &line)
+{
+    TConstantUnion returnValue;
+    ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
+    ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
+    if (!IsValidShiftOffset(rhs))
+    {
+        diag->warning(line, "Undefined shift (operand out of range)", ">>");
+        switch (lhs.type)
+        {
+            case EbtInt:
+                returnValue.setIConst(0);
+                break;
+            case EbtUInt:
+                returnValue.setUConst(0u);
+                break;
+            default:
+                UNREACHABLE();
+        }
+        return returnValue;
+    }
+
+    switch (lhs.type)
+    {
+        case EbtInt:
+        {
+            unsigned int shiftOffset = 0;
+            switch (rhs.type)
+            {
+                case EbtInt:
+                    shiftOffset = static_cast<unsigned int>(rhs.iConst);
+                    break;
+                case EbtUInt:
+                    shiftOffset = rhs.uConst;
+                    break;
+                default:
+                    UNREACHABLE();
+            }
+            if (shiftOffset > 0)
+            {
+                // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend
+                // the sign bit." In C++ shifting negative integers is undefined, so we implement
+                // extending the sign bit manually.
+                int lhsSafe = lhs.iConst;
+                if (lhsSafe == std::numeric_limits<int>::min())
+                {
+                    // The min integer needs special treatment because only bit it has set is the
+                    // sign bit, which we clear later to implement safe right shift of negative
+                    // numbers.
+                    lhsSafe = -0x40000000;
+                    --shiftOffset;
+                }
+                if (shiftOffset > 0)
+                {
+                    bool extendSignBit = false;
+                    if (lhsSafe < 0)
+                    {
+                        extendSignBit = true;
+                        // Clear the sign bit so that bitshift right is defined in C++.
+                        lhsSafe &= 0x7fffffff;
+                        ASSERT(lhsSafe > 0);
+                    }
+                    returnValue.setIConst(lhsSafe >> shiftOffset);
+
+                    // Manually fill in the extended sign bit if necessary.
+                    if (extendSignBit)
+                    {
+                        int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset));
+                        returnValue.setIConst(returnValue.getIConst() | extendedSignBit);
+                    }
+                }
+                else
+                {
+                    returnValue.setIConst(lhsSafe);
+                }
+            }
+            else
+            {
+                returnValue.setIConst(lhs.iConst);
+            }
+            break;
+        }
+        case EbtUInt:
+            switch (rhs.type)
+            {
+                case EbtInt:
+                    returnValue.setUConst(lhs.uConst >> rhs.iConst);
+                    break;
+                case EbtUInt:
+                    returnValue.setUConst(lhs.uConst >> rhs.uConst);
+                    break;
+                default:
+                    UNREACHABLE();
+            }
+            break;
+
+        default:
+            UNREACHABLE();
+    }
+    return returnValue;
+}
+
+// static
+TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs,
+                                      const TConstantUnion &rhs,
+                                      TDiagnostics *diag,
+                                      const TSourceLoc &line)
+{
+    TConstantUnion returnValue;
+    ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
+    ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
+    if (!IsValidShiftOffset(rhs))
+    {
+        diag->warning(line, "Undefined shift (operand out of range)", "<<");
+        switch (lhs.type)
+        {
+            case EbtInt:
+                returnValue.setIConst(0);
+                break;
+            case EbtUInt:
+                returnValue.setUConst(0u);
+                break;
+            default:
+                UNREACHABLE();
+        }
+        return returnValue;
+    }
+
+    switch (lhs.type)
+    {
+        case EbtInt:
+            switch (rhs.type)
+            {
+                // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that
+                // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed
+                // integer overflow or undefined shift of a negative integer.
+                case EbtInt:
+                    returnValue.setIConst(
+                        static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst));
+                    break;
+                case EbtUInt:
+                    returnValue.setIConst(
+                        static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.uConst));
+                    break;
+                default:
+                    UNREACHABLE();
+            }
+            break;
+
+        case EbtUInt:
+            switch (rhs.type)
+            {
+                case EbtInt:
+                    returnValue.setUConst(lhs.uConst << rhs.iConst);
+                    break;
+                case EbtUInt:
+                    returnValue.setUConst(lhs.uConst << rhs.uConst);
+                    break;
+                default:
+                    UNREACHABLE();
+            }
+            break;
+
+        default:
+            UNREACHABLE();
+    }
+    return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const
+{
+    TConstantUnion returnValue;
+    ASSERT(constant.type == EbtInt || constant.type == EbtUInt);
+    switch (type)
+    {
+        case EbtInt:
+            returnValue.setIConst(iConst & constant.iConst);
+            break;
+        case EbtUInt:
+            returnValue.setUConst(uConst & constant.uConst);
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const
+{
+    TConstantUnion returnValue;
+    ASSERT(type == constant.type);
+    switch (type)
+    {
+        case EbtInt:
+            returnValue.setIConst(iConst | constant.iConst);
+            break;
+        case EbtUInt:
+            returnValue.setUConst(uConst | constant.uConst);
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const
+{
+    TConstantUnion returnValue;
+    ASSERT(type == constant.type);
+    switch (type)
+    {
+        case EbtInt:
+            returnValue.setIConst(iConst ^ constant.iConst);
+            break;
+        case EbtUInt:
+            returnValue.setUConst(uConst ^ constant.uConst);
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const
+{
+    TConstantUnion returnValue;
+    ASSERT(type == constant.type);
+    switch (type)
+    {
+        case EbtBool:
+            returnValue.setBConst(bConst && constant.bConst);
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const
+{
+    TConstantUnion returnValue;
+    ASSERT(type == constant.type);
+    switch (type)
+    {
+        case EbtBool:
+            returnValue.setBConst(bConst || constant.bConst);
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return returnValue;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ConstantUnion.h b/src/third_party/angle/src/compiler/translator/ConstantUnion.h
new file mode 100644
index 0000000..870acb6
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ConstantUnion.h
@@ -0,0 +1,117 @@
+//
+// 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.
+//
+
+#ifndef COMPILER_TRANSLATOR_CONSTANTUNION_H_
+#define COMPILER_TRANSLATOR_CONSTANTUNION_H_
+
+#include <assert.h>
+
+#include "compiler/translator/Common.h"
+#include "compiler/translator/BaseTypes.h"
+
+namespace sh
+{
+
+class TDiagnostics;
+
+class TConstantUnion
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TConstantUnion();
+
+    bool cast(TBasicType newType, const TConstantUnion &constant);
+
+    void setIConst(int i)
+    {
+        iConst = i;
+        type   = EbtInt;
+    }
+    void setUConst(unsigned int u)
+    {
+        uConst = u;
+        type   = EbtUInt;
+    }
+    void setFConst(float f)
+    {
+        fConst = f;
+        type   = EbtFloat;
+    }
+    void setBConst(bool b)
+    {
+        bConst = b;
+        type   = EbtBool;
+    }
+
+    void setYuvCscStandardEXTConst(TYuvCscStandardEXT s)
+    {
+        yuvCscStandardEXTConst = s;
+        type                   = EbtYuvCscStandardEXT;
+    }
+
+    int getIConst() const { return iConst; }
+    unsigned int getUConst() const { return uConst; }
+    float getFConst() const { return fConst; }
+    bool getBConst() const { return bConst; }
+    TYuvCscStandardEXT getYuvCscStandardEXTConst() const { return yuvCscStandardEXTConst; }
+
+    bool operator==(const int i) const;
+    bool operator==(const unsigned int u) const;
+    bool operator==(const float f) const;
+    bool operator==(const bool b) const;
+    bool operator==(const TYuvCscStandardEXT s) const;
+    bool operator==(const TConstantUnion &constant) const;
+    bool operator!=(const int i) const;
+    bool operator!=(const unsigned int u) const;
+    bool operator!=(const float f) const;
+    bool operator!=(const bool b) const;
+    bool operator!=(const TYuvCscStandardEXT s) const;
+    bool operator!=(const TConstantUnion &constant) const;
+    bool operator>(const TConstantUnion &constant) const;
+    bool operator<(const TConstantUnion &constant) const;
+    static TConstantUnion add(const TConstantUnion &lhs,
+                              const TConstantUnion &rhs,
+                              TDiagnostics *diag,
+                              const TSourceLoc &line);
+    static TConstantUnion sub(const TConstantUnion &lhs,
+                              const TConstantUnion &rhs,
+                              TDiagnostics *diag,
+                              const TSourceLoc &line);
+    static TConstantUnion mul(const TConstantUnion &lhs,
+                              const TConstantUnion &rhs,
+                              TDiagnostics *diag,
+                              const TSourceLoc &line);
+    TConstantUnion operator%(const TConstantUnion &constant) const;
+    static TConstantUnion rshift(const TConstantUnion &lhs,
+                                 const TConstantUnion &rhs,
+                                 TDiagnostics *diag,
+                                 const TSourceLoc &line);
+    static TConstantUnion lshift(const TConstantUnion &lhs,
+                                 const TConstantUnion &rhs,
+                                 TDiagnostics *diag,
+                                 const TSourceLoc &line);
+    TConstantUnion operator&(const TConstantUnion &constant) const;
+    TConstantUnion operator|(const TConstantUnion &constant) const;
+    TConstantUnion operator^(const TConstantUnion &constant) const;
+    TConstantUnion operator&&(const TConstantUnion &constant) const;
+    TConstantUnion operator||(const TConstantUnion &constant) const;
+
+    TBasicType getType() const { return type; }
+  private:
+    union {
+        int iConst;           // used for ivec, scalar ints
+        unsigned int uConst;  // used for uvec, scalar uints
+        bool bConst;          // used for bvec, scalar bools
+        float fConst;         // used for vec, mat, scalar floats
+        TYuvCscStandardEXT yuvCscStandardEXTConst;
+    };
+
+    TBasicType type;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_CONSTANTUNION_H_
diff --git a/src/third_party/angle/src/compiler/translator/DeferGlobalInitializers.cpp b/src/third_party/angle/src/compiler/translator/DeferGlobalInitializers.cpp
new file mode 100644
index 0000000..cdc8a37
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/DeferGlobalInitializers.cpp
@@ -0,0 +1,137 @@
+//
+// Copyright (c) 2016 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.
+//
+// DeferGlobalInitializers is an AST traverser that moves global initializers into a function, and
+// adds a function call to that function in the beginning of main().
+// This enables initialization of globals with uniforms or non-constant globals, as allowed by
+// the WebGL spec. Some initializers referencing non-constants may need to be unfolded into if
+// statements in HLSL - this kind of steps should be done after DeferGlobalInitializers is run.
+//
+
+#include "compiler/translator/DeferGlobalInitializers.h"
+
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void GetDeferredInitializers(TIntermDeclaration *declaration,
+                             TIntermSequence *deferredInitializersOut)
+{
+    // We iterate with an index instead of using an iterator since we're replacing the children of
+    // declaration inside the loop.
+    for (size_t i = 0; i < declaration->getSequence()->size(); ++i)
+    {
+        TIntermNode *declarator = declaration->getSequence()->at(i);
+        TIntermBinary *init     = declarator->getAsBinaryNode();
+        if (init)
+        {
+            TIntermSymbol *symbolNode = init->getLeft()->getAsSymbolNode();
+            ASSERT(symbolNode);
+            TIntermTyped *expression = init->getRight();
+
+            if ((expression->getQualifier() != EvqConst ||
+                 (expression->getAsConstantUnion() == nullptr &&
+                  !expression->isConstructorWithOnlyConstantUnionParameters())))
+            {
+                // For variables which are not constant, defer their real initialization until
+                // after we initialize uniforms.
+                // Deferral is done also in any cases where the variable has not been constant
+                // folded, since otherwise there's a chance that HLSL output will generate extra
+                // statements from the initializer expression.
+                TIntermBinary *deferredInit =
+                    new TIntermBinary(EOpAssign, symbolNode->deepCopy(), init->getRight());
+                deferredInitializersOut->push_back(deferredInit);
+
+                // Change const global to a regular global if its initialization is deferred.
+                // This can happen if ANGLE has not been able to fold the constant expression used
+                // as an initializer.
+                ASSERT(symbolNode->getQualifier() == EvqConst ||
+                       symbolNode->getQualifier() == EvqGlobal);
+                if (symbolNode->getQualifier() == EvqConst)
+                {
+                    // All of the siblings in the same declaration need to have consistent
+                    // qualifiers.
+                    auto *siblings = declaration->getSequence();
+                    for (TIntermNode *siblingNode : *siblings)
+                    {
+                        TIntermBinary *siblingBinary = siblingNode->getAsBinaryNode();
+                        if (siblingBinary)
+                        {
+                            ASSERT(siblingBinary->getOp() == EOpInitialize);
+                            siblingBinary->getLeft()->getTypePointer()->setQualifier(EvqGlobal);
+                        }
+                        siblingNode->getAsTyped()->getTypePointer()->setQualifier(EvqGlobal);
+                    }
+                    // This node is one of the siblings.
+                    ASSERT(symbolNode->getQualifier() == EvqGlobal);
+                }
+                // Remove the initializer from the global scope and just declare the global instead.
+                declaration->replaceChildNode(init, symbolNode);
+            }
+        }
+    }
+}
+
+void InsertInitFunction(TIntermBlock *root, TIntermSequence *deferredInitializers)
+{
+    TSymbolUniqueId initFunctionId;
+    const char *functionName = "initializeGlobals";
+
+    // Add function prototype to the beginning of the shader
+    TIntermFunctionPrototype *functionPrototypeNode =
+        TIntermTraverser::CreateInternalFunctionPrototypeNode(TType(EbtVoid), functionName,
+                                                              initFunctionId);
+    root->getSequence()->insert(root->getSequence()->begin(), functionPrototypeNode);
+
+    // Add function definition to the end of the shader
+    TIntermBlock *functionBodyNode = new TIntermBlock();
+    functionBodyNode->getSequence()->swap(*deferredInitializers);
+    TIntermFunctionDefinition *functionDefinition =
+        TIntermTraverser::CreateInternalFunctionDefinitionNode(TType(EbtVoid), functionName,
+                                                               functionBodyNode, initFunctionId);
+    root->getSequence()->push_back(functionDefinition);
+
+    // Insert call into main function
+    TIntermFunctionDefinition *main = FindMain(root);
+    ASSERT(main != nullptr);
+    TIntermAggregate *functionCallNode = TIntermTraverser::CreateInternalFunctionCallNode(
+        TType(EbtVoid), functionName, initFunctionId, nullptr);
+
+    TIntermBlock *mainBody = main->getBody();
+    ASSERT(mainBody != nullptr);
+    mainBody->getSequence()->insert(mainBody->getSequence()->begin(), functionCallNode);
+}
+
+}  // namespace
+
+void DeferGlobalInitializers(TIntermBlock *root)
+{
+    TIntermSequence *deferredInitializers = new TIntermSequence();
+
+    // Loop over all global statements and process the declarations. This is simpler than using a
+    // traverser.
+    for (TIntermNode *declaration : *root->getSequence())
+    {
+        TIntermDeclaration *asVariableDeclaration = declaration->getAsDeclarationNode();
+        if (asVariableDeclaration)
+        {
+            GetDeferredInitializers(asVariableDeclaration, deferredInitializers);
+        }
+    }
+
+    // Add the function with initialization and the call to that.
+    if (!deferredInitializers->empty())
+    {
+        InsertInitFunction(root, deferredInitializers);
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/DeferGlobalInitializers.h b/src/third_party/angle/src/compiler/translator/DeferGlobalInitializers.h
new file mode 100644
index 0000000..261ec90
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/DeferGlobalInitializers.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2016 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.
+//
+// DeferGlobalInitializers is an AST traverser that moves global initializers into a function, and
+// adds a function call to that function in the beginning of main().
+// This enables initialization of globals with uniforms or non-constant globals, as allowed by
+// the WebGL spec. Some initializers referencing non-constants may need to be unfolded into if
+// statements in HLSL - this kind of steps should be done after DeferGlobalInitializers is run.
+//
+
+#ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
+#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
+
+class TIntermBlock;
+
+namespace sh
+{
+void DeferGlobalInitializers(TIntermBlock *root);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
diff --git a/src/third_party/angle/src/compiler/translator/Diagnostics.cpp b/src/third_party/angle/src/compiler/translator/Diagnostics.cpp
new file mode 100644
index 0000000..d2fe429
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Diagnostics.cpp
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/Diagnostics.h"
+
+#include "common/debug.h"
+#include "compiler/preprocessor/SourceLocation.h"
+#include "compiler/translator/Common.h"
+#include "compiler/translator/InfoSink.h"
+
+namespace sh
+{
+
+TDiagnostics::TDiagnostics(TInfoSinkBase &infoSink)
+    : mInfoSink(infoSink), mNumErrors(0), mNumWarnings(0)
+{
+}
+
+TDiagnostics::~TDiagnostics()
+{
+}
+
+void TDiagnostics::writeInfo(Severity severity,
+                             const pp::SourceLocation &loc,
+                             const char *reason,
+                             const char *token)
+{
+    switch (severity)
+    {
+        case SH_ERROR:
+            ++mNumErrors;
+            break;
+        case SH_WARNING:
+            ++mNumWarnings;
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+    mInfoSink.prefix(severity);
+    mInfoSink.location(loc.file, loc.line);
+    mInfoSink << "'" << token << "' : " << reason << "\n";
+}
+
+void TDiagnostics::globalError(const char *message)
+{
+    ++mNumErrors;
+    mInfoSink.prefix(SH_ERROR);
+    mInfoSink << message << "\n";
+}
+
+void TDiagnostics::error(const pp::SourceLocation &loc, const char *reason, const char *token)
+{
+    writeInfo(SH_ERROR, loc, reason, token);
+}
+
+void TDiagnostics::warning(const pp::SourceLocation &loc, const char *reason, const char *token)
+{
+    writeInfo(SH_WARNING, loc, reason, token);
+}
+
+void TDiagnostics::error(const TSourceLoc &loc, const char *reason, const char *token)
+{
+    pp::SourceLocation srcLoc;
+    srcLoc.file = loc.first_file;
+    srcLoc.line = loc.first_line;
+    error(srcLoc, reason, token);
+}
+
+void TDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token)
+{
+    pp::SourceLocation srcLoc;
+    srcLoc.file = loc.first_file;
+    srcLoc.line = loc.first_line;
+    warning(srcLoc, reason, token);
+}
+
+void TDiagnostics::print(ID id, const pp::SourceLocation &loc, const std::string &text)
+{
+    writeInfo(isError(id) ? SH_ERROR : SH_WARNING, loc, message(id), text.c_str());
+}
+
+void TDiagnostics::resetErrorCount()
+{
+    mNumErrors   = 0;
+    mNumWarnings = 0;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/Diagnostics.h b/src/third_party/angle/src/compiler/translator/Diagnostics.h
new file mode 100644
index 0000000..78bfb75
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Diagnostics.h
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_DIAGNOSTICS_H_
+#define COMPILER_TRANSLATOR_DIAGNOSTICS_H_
+
+#include "common/angleutils.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/translator/Severity.h"
+
+namespace sh
+{
+
+class TInfoSinkBase;
+struct TSourceLoc;
+
+class TDiagnostics : public pp::Diagnostics, angle::NonCopyable
+{
+  public:
+    TDiagnostics(TInfoSinkBase &infoSink);
+    ~TDiagnostics() override;
+
+    int numErrors() const { return mNumErrors; }
+    int numWarnings() const { return mNumWarnings; }
+
+    void error(const pp::SourceLocation &loc, const char *reason, const char *token);
+    void warning(const pp::SourceLocation &loc, const char *reason, const char *token);
+
+    void error(const TSourceLoc &loc, const char *reason, const char *token);
+    void warning(const TSourceLoc &loc, const char *reason, const char *token);
+
+    void globalError(const char *message);
+
+    void resetErrorCount();
+
+  protected:
+    void writeInfo(Severity severity,
+                   const pp::SourceLocation &loc,
+                   const char *reason,
+                   const char *token);
+
+    void print(ID id, const pp::SourceLocation &loc, const std::string &text) override;
+
+  private:
+    TInfoSinkBase &mInfoSink;
+    int mNumErrors;
+    int mNumWarnings;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_DIAGNOSTICS_H_
diff --git a/src/third_party/angle/src/compiler/translator/DirectiveHandler.cpp b/src/third_party/angle/src/compiler/translator/DirectiveHandler.cpp
new file mode 100644
index 0000000..bbcad25
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/DirectiveHandler.cpp
@@ -0,0 +1,203 @@
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/DirectiveHandler.h"
+
+#include <sstream>
+
+#include "angle_gl.h"
+#include "common/debug.h"
+#include "compiler/translator/Diagnostics.h"
+
+namespace sh
+{
+
+static TBehavior getBehavior(const std::string &str)
+{
+    const char kRequire[] = "require";
+    const char kEnable[]  = "enable";
+    const char kDisable[] = "disable";
+    const char kWarn[]    = "warn";
+
+    if (str == kRequire)
+        return EBhRequire;
+    else if (str == kEnable)
+        return EBhEnable;
+    else if (str == kDisable)
+        return EBhDisable;
+    else if (str == kWarn)
+        return EBhWarn;
+    return EBhUndefined;
+}
+
+TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior,
+                                     TDiagnostics &diagnostics,
+                                     int &shaderVersion,
+                                     sh::GLenum shaderType,
+                                     bool debugShaderPrecisionSupported)
+    : mExtensionBehavior(extBehavior),
+      mDiagnostics(diagnostics),
+      mShaderVersion(shaderVersion),
+      mShaderType(shaderType),
+      mDebugShaderPrecisionSupported(debugShaderPrecisionSupported)
+{
+}
+
+TDirectiveHandler::~TDirectiveHandler()
+{
+}
+
+void TDirectiveHandler::handleError(const pp::SourceLocation &loc, const std::string &msg)
+{
+    mDiagnostics.error(loc, msg.c_str(), "");
+}
+
+void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc,
+                                     const std::string &name,
+                                     const std::string &value,
+                                     bool stdgl)
+{
+    if (stdgl)
+    {
+        const char kInvariant[] = "invariant";
+        const char kAll[]       = "all";
+
+        if (name == kInvariant && value == kAll)
+        {
+            if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER)
+            {
+                // ESSL 3.00.4 section 4.6.1
+                mDiagnostics.error(
+                    loc, "#pragma STDGL invariant(all) can not be used in fragment shader",
+                    name.c_str());
+            }
+            mPragma.stdgl.invariantAll = true;
+        }
+        // The STDGL pragma is used to reserve pragmas for use by future
+        // revisions of GLSL.  Do not generate an error on unexpected
+        // name and value.
+        return;
+    }
+    else
+    {
+        const char kOptimize[]             = "optimize";
+        const char kDebug[]                = "debug";
+        const char kDebugShaderPrecision[] = "webgl_debug_shader_precision";
+        const char kOn[]                   = "on";
+        const char kOff[]                  = "off";
+
+        bool invalidValue = false;
+        if (name == kOptimize)
+        {
+            if (value == kOn)
+                mPragma.optimize = true;
+            else if (value == kOff)
+                mPragma.optimize = false;
+            else
+                invalidValue = true;
+        }
+        else if (name == kDebug)
+        {
+            if (value == kOn)
+                mPragma.debug = true;
+            else if (value == kOff)
+                mPragma.debug = false;
+            else
+                invalidValue = true;
+        }
+        else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported)
+        {
+            if (value == kOn)
+                mPragma.debugShaderPrecision = true;
+            else if (value == kOff)
+                mPragma.debugShaderPrecision = false;
+            else
+                invalidValue = true;
+        }
+        else
+        {
+            mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
+            return;
+        }
+
+        if (invalidValue)
+        {
+            mDiagnostics.error(loc, "invalid pragma value - 'on' or 'off' expected", value.c_str());
+        }
+    }
+}
+
+void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc,
+                                        const std::string &name,
+                                        const std::string &behavior)
+{
+    const char kExtAll[] = "all";
+
+    TBehavior behaviorVal = getBehavior(behavior);
+    if (behaviorVal == EBhUndefined)
+    {
+        mDiagnostics.error(loc, "behavior invalid", name.c_str());
+        return;
+    }
+
+    if (name == kExtAll)
+    {
+        if (behaviorVal == EBhRequire)
+        {
+            mDiagnostics.error(loc, "extension cannot have 'require' behavior", name.c_str());
+        }
+        else if (behaviorVal == EBhEnable)
+        {
+            mDiagnostics.error(loc, "extension cannot have 'enable' behavior", name.c_str());
+        }
+        else
+        {
+            for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin();
+                 iter != mExtensionBehavior.end(); ++iter)
+                iter->second = behaviorVal;
+        }
+        return;
+    }
+
+    TExtensionBehavior::iterator iter = mExtensionBehavior.find(name);
+    if (iter != mExtensionBehavior.end())
+    {
+        iter->second = behaviorVal;
+        return;
+    }
+
+    switch (behaviorVal)
+    {
+        case EBhRequire:
+            mDiagnostics.error(loc, "extension is not supported", name.c_str());
+            break;
+        case EBhEnable:
+        case EBhWarn:
+        case EBhDisable:
+            mDiagnostics.warning(loc, "extension is not supported", name.c_str());
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void TDirectiveHandler::handleVersion(const pp::SourceLocation &loc, int version)
+{
+    if (version == 100 || version == 300 || version == 310)
+    {
+        mShaderVersion = version;
+    }
+    else
+    {
+        std::stringstream stream;
+        stream << version;
+        std::string str = stream.str();
+        mDiagnostics.error(loc, "version number not supported", str.c_str());
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/DirectiveHandler.h b/src/third_party/angle/src/compiler/translator/DirectiveHandler.h
new file mode 100644
index 0000000..8e8cb9b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/DirectiveHandler.h
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
+#define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/ExtensionBehavior.h"
+#include "compiler/translator/Pragma.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+class TDiagnostics;
+
+class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
+{
+  public:
+    TDirectiveHandler(TExtensionBehavior &extBehavior,
+                      TDiagnostics &diagnostics,
+                      int &shaderVersion,
+                      sh::GLenum shaderType,
+                      bool debugShaderPrecisionSupported);
+    ~TDirectiveHandler() override;
+
+    const TPragma &pragma() const { return mPragma; }
+    const TExtensionBehavior &extensionBehavior() const { return mExtensionBehavior; }
+
+    void handleError(const pp::SourceLocation &loc, const std::string &msg) override;
+
+    void handlePragma(const pp::SourceLocation &loc,
+                      const std::string &name,
+                      const std::string &value,
+                      bool stdgl) override;
+
+    void handleExtension(const pp::SourceLocation &loc,
+                         const std::string &name,
+                         const std::string &behavior) override;
+
+    void handleVersion(const pp::SourceLocation &loc, int version) override;
+
+  private:
+    TPragma mPragma;
+    TExtensionBehavior &mExtensionBehavior;
+    TDiagnostics &mDiagnostics;
+    int &mShaderVersion;
+    sh::GLenum mShaderType;
+    bool mDebugShaderPrecisionSupported;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
diff --git a/src/third_party/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp b/src/third_party/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
new file mode 100644
index 0000000..b14438a
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
@@ -0,0 +1,123 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+// gl_FragColor needs to broadcast to all color buffers in ES2 if
+// GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
+//
+// We emulate this by replacing all gl_FragColor with gl_FragData[0], and in the end
+// of main() function, assigning gl_FragData[1], ..., gl_FragData[maxDrawBuffers-1]
+// with gl_FragData[0].
+//
+
+#include "compiler/translator/EmulateGLFragColorBroadcast.h"
+
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class GLFragColorBroadcastTraverser : public TIntermTraverser
+{
+  public:
+    GLFragColorBroadcastTraverser(int maxDrawBuffers)
+        : TIntermTraverser(true, false, false),
+          mGLFragColorUsed(false),
+          mMaxDrawBuffers(maxDrawBuffers)
+    {
+    }
+
+    void broadcastGLFragColor(TIntermBlock *root);
+
+    bool isGLFragColorUsed() const { return mGLFragColorUsed; }
+
+  protected:
+    void visitSymbol(TIntermSymbol *node) override;
+
+    TIntermBinary *constructGLFragDataNode(int index) const;
+    TIntermBinary *constructGLFragDataAssignNode(int index) const;
+
+  private:
+    bool mGLFragColorUsed;
+    int mMaxDrawBuffers;
+};
+
+TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const
+{
+    TType gl_FragDataType = TType(EbtFloat, EbpMedium, EvqFragData, 4);
+    gl_FragDataType.setArraySize(mMaxDrawBuffers);
+
+    TIntermSymbol *symbol   = new TIntermSymbol(0, "gl_FragData", gl_FragDataType);
+    TIntermTyped *indexNode = TIntermTyped::CreateIndexNode(index);
+
+    TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode);
+    return binary;
+}
+
+TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const
+{
+    TIntermTyped *fragDataIndex = constructGLFragDataNode(index);
+    TIntermTyped *fragDataZero  = constructGLFragDataNode(0);
+
+    return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero);
+}
+
+void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node)
+{
+    if (node->getSymbol() == "gl_FragColor")
+    {
+        queueReplacement(node, constructGLFragDataNode(0), OriginalNode::IS_DROPPED);
+        mGLFragColorUsed = true;
+    }
+}
+
+void GLFragColorBroadcastTraverser::broadcastGLFragColor(TIntermBlock *root)
+{
+    ASSERT(mMaxDrawBuffers > 1);
+    if (!mGLFragColorUsed)
+    {
+        return;
+    }
+    TIntermSequence *mainSequence = FindMain(root)->getBody()->getSequence();
+    // Now insert statements
+    //   gl_FragData[1] = gl_FragData[0];
+    //   ...
+    //   gl_FragData[maxDrawBuffers - 1] = gl_FragData[0];
+    for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex)
+    {
+        mainSequence->insert(mainSequence->end(), constructGLFragDataAssignNode(colorIndex));
+    }
+}
+
+}  // namespace anonymous
+
+void EmulateGLFragColorBroadcast(TIntermBlock *root,
+                                 int maxDrawBuffers,
+                                 std::vector<sh::OutputVariable> *outputVariables)
+{
+    ASSERT(maxDrawBuffers > 1);
+    GLFragColorBroadcastTraverser traverser(maxDrawBuffers);
+    root->traverse(&traverser);
+    if (traverser.isGLFragColorUsed())
+    {
+        traverser.updateTree();
+        traverser.broadcastGLFragColor(root);
+        for (auto &var : *outputVariables)
+        {
+            if (var.name == "gl_FragColor")
+            {
+                // TODO(zmo): Find a way to keep the original variable information.
+                var.name       = "gl_FragData";
+                var.mappedName = "gl_FragData";
+                var.arraySize  = maxDrawBuffers;
+            }
+        }
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h b/src/third_party/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h
new file mode 100644
index 0000000..f14ee70
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+// Emulate gl_FragColor broadcast behaviors in ES2 where
+// GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
+//
+
+#ifndef COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
+#define COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
+
+#include <vector>
+
+namespace sh
+{
+struct OutputVariable;
+class TIntermBlock;
+
+// Replace all gl_FragColor with gl_FragData[0], and in the end of main() function,
+// assign gl_FragData[1] ... gl_FragData[maxDrawBuffers - 1] with gl_FragData[0].
+// If gl_FragColor is in outputVariables, it is replaced by gl_FragData.
+void EmulateGLFragColorBroadcast(TIntermBlock *root,
+                                 int maxDrawBuffers,
+                                 std::vector<OutputVariable> *outputVariables);
+}
+
+#endif  // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
diff --git a/src/third_party/angle/src/compiler/translator/EmulatePrecision.cpp b/src/third_party/angle/src/compiler/translator/EmulatePrecision.cpp
new file mode 100644
index 0000000..aebcce6
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/EmulatePrecision.cpp
@@ -0,0 +1,748 @@
+//
+// 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.
+//
+
+#include "compiler/translator/EmulatePrecision.h"
+
+#include <memory>
+
+namespace sh
+{
+
+namespace
+{
+
+class RoundingHelperWriter : angle::NonCopyable
+{
+  public:
+    static RoundingHelperWriter *createHelperWriter(const ShShaderOutput outputLanguage);
+
+    void writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion);
+    void writeCompoundAssignmentHelper(TInfoSinkBase &sink,
+                                       const char *lType,
+                                       const char *rType,
+                                       const char *opStr,
+                                       const char *opNameStr);
+
+    virtual ~RoundingHelperWriter() {}
+
+  protected:
+    RoundingHelperWriter(const ShShaderOutput outputLanguage) : mOutputLanguage(outputLanguage) {}
+    RoundingHelperWriter() = delete;
+
+    const ShShaderOutput mOutputLanguage;
+
+  private:
+    virtual std::string getTypeString(const char *glslType)     = 0;
+    virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0;
+    virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0;
+    virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink,
+                                           const unsigned int columns,
+                                           const unsigned int rows,
+                                           const char *functionName) = 0;
+};
+
+class RoundingHelperWriterGLSL : public RoundingHelperWriter
+{
+  public:
+    RoundingHelperWriterGLSL(const ShShaderOutput outputLanguage)
+        : RoundingHelperWriter(outputLanguage)
+    {
+    }
+
+  private:
+    std::string getTypeString(const char *glslType) override;
+    void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
+    void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
+    void writeMatrixRoundingHelper(TInfoSinkBase &sink,
+                                   const unsigned int columns,
+                                   const unsigned int rows,
+                                   const char *functionName) override;
+};
+
+class RoundingHelperWriterESSL : public RoundingHelperWriterGLSL
+{
+  public:
+    RoundingHelperWriterESSL(const ShShaderOutput outputLanguage)
+        : RoundingHelperWriterGLSL(outputLanguage)
+    {
+    }
+
+  private:
+    std::string getTypeString(const char *glslType) override;
+};
+
+class RoundingHelperWriterHLSL : public RoundingHelperWriter
+{
+  public:
+    RoundingHelperWriterHLSL(const ShShaderOutput outputLanguage)
+        : RoundingHelperWriter(outputLanguage)
+    {
+    }
+
+  private:
+    std::string getTypeString(const char *glslType) override;
+    void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
+    void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
+    void writeMatrixRoundingHelper(TInfoSinkBase &sink,
+                                   const unsigned int columns,
+                                   const unsigned int rows,
+                                   const char *functionName) override;
+};
+
+RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage)
+{
+    ASSERT(EmulatePrecision::SupportedInLanguage(outputLanguage));
+    switch (outputLanguage)
+    {
+        case SH_HLSL_4_1_OUTPUT:
+            return new RoundingHelperWriterHLSL(outputLanguage);
+        case SH_ESSL_OUTPUT:
+            return new RoundingHelperWriterESSL(outputLanguage);
+        default:
+            return new RoundingHelperWriterGLSL(outputLanguage);
+    }
+}
+
+void RoundingHelperWriter::writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion)
+{
+    // Write the angle_frm functions that round floating point numbers to
+    // half precision, and angle_frl functions that round them to minimum lowp
+    // precision.
+
+    writeFloatRoundingHelpers(sink);
+    writeVectorRoundingHelpers(sink, 2);
+    writeVectorRoundingHelpers(sink, 3);
+    writeVectorRoundingHelpers(sink, 4);
+    if (shaderVersion > 100)
+    {
+        for (unsigned int columns = 2; columns <= 4; ++columns)
+        {
+            for (unsigned int rows = 2; rows <= 4; ++rows)
+            {
+                writeMatrixRoundingHelper(sink, columns, rows, "angle_frm");
+                writeMatrixRoundingHelper(sink, columns, rows, "angle_frl");
+            }
+        }
+    }
+    else
+    {
+        for (unsigned int size = 2; size <= 4; ++size)
+        {
+            writeMatrixRoundingHelper(sink, size, size, "angle_frm");
+            writeMatrixRoundingHelper(sink, size, size, "angle_frl");
+        }
+    }
+}
+
+void RoundingHelperWriter::writeCompoundAssignmentHelper(TInfoSinkBase &sink,
+                                                         const char *lType,
+                                                         const char *rType,
+                                                         const char *opStr,
+                                                         const char *opNameStr)
+{
+    std::string lTypeStr = getTypeString(lType);
+    std::string rTypeStr = getTypeString(rType);
+
+    // Note that y should be passed through angle_frm at the function call site,
+    // but x can't be passed through angle_frm there since it is an inout parameter.
+    // So only pass x and the result through angle_frm here.
+    // clang-format off
+    sink <<
+        lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
+        "    x = angle_frm(angle_frm(x) " << opStr << " y);\n"
+        "    return x;\n"
+        "}\n";
+    sink <<
+        lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
+        "    x = angle_frl(angle_frm(x) " << opStr << " y);\n"
+        "    return x;\n"
+        "}\n";
+    // clang-format on
+}
+
+std::string RoundingHelperWriterGLSL::getTypeString(const char *glslType)
+{
+    return glslType;
+}
+
+std::string RoundingHelperWriterESSL::getTypeString(const char *glslType)
+{
+    std::stringstream typeStrStr;
+    typeStrStr << "highp " << glslType;
+    return typeStrStr.str();
+}
+
+void RoundingHelperWriterGLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
+{
+    // Unoptimized version of angle_frm for single floats:
+    //
+    // int webgl_maxNormalExponent(in int exponentBits)
+    // {
+    //     int possibleExponents = int(exp2(float(exponentBits)));
+    //     int exponentBias = possibleExponents / 2 - 1;
+    //     int allExponentBitsOne = possibleExponents - 1;
+    //     return (allExponentBitsOne - 1) - exponentBias;
+    // }
+    //
+    // float angle_frm(in float x)
+    // {
+    //     int mantissaBits = 10;
+    //     int exponentBits = 5;
+    //     float possibleMantissas = exp2(float(mantissaBits));
+    //     float mantissaMax = 2.0 - 1.0 / possibleMantissas;
+    //     int maxNE = webgl_maxNormalExponent(exponentBits);
+    //     float max = exp2(float(maxNE)) * mantissaMax;
+    //     if (x > max)
+    //     {
+    //         return max;
+    //     }
+    //     if (x < -max)
+    //     {
+    //         return -max;
+    //     }
+    //     float exponent = floor(log2(abs(x)));
+    //     if (abs(x) == 0.0 || exponent < -float(maxNE))
+    //     {
+    //         return 0.0 * sign(x)
+    //     }
+    //     x = x * exp2(-(exponent - float(mantissaBits)));
+    //     x = sign(x) * floor(abs(x));
+    //     return x * exp2(exponent - float(mantissaBits));
+    // }
+
+    // All numbers with a magnitude less than 2^-15 are subnormal, and are
+    // flushed to zero.
+
+    // Note the constant numbers below:
+    // a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times
+    //    2^15, the maximum normal exponent.
+    // b) 10.0 is the number of mantissa bits.
+    // c) -25.0 is the minimum normal half-float exponent -15.0 minus the number
+    //    of mantissa bits.
+    // d) + 1e-30 is to make sure the argument of log2() won't be zero. It can
+    //    only affect the result of log2 on x where abs(x) < 1e-22. Since these
+    //    numbers will be flushed to zero either way (2^-15 is the smallest
+    //    normal positive number), this does not introduce any error.
+
+    std::string floatType = getTypeString("float");
+
+    // clang-format off
+    sink <<
+        floatType << " angle_frm(in " << floatType << " x) {\n"
+        "    x = clamp(x, -65504.0, 65504.0);\n"
+        "    " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
+        "    bool isNonZero = (exponent >= -25.0);\n"
+        "    x = x * exp2(-exponent);\n"
+        "    x = sign(x) * floor(abs(x));\n"
+        "    return x * exp2(exponent) * float(isNonZero);\n"
+        "}\n";
+
+    sink <<
+        floatType << " angle_frl(in " << floatType << " x) {\n"
+        "    x = clamp(x, -2.0, 2.0);\n"
+        "    x = x * 256.0;\n"
+        "    x = sign(x) * floor(abs(x));\n"
+        "    return x * 0.00390625;\n"
+        "}\n";
+    // clang-format on
+}
+
+void RoundingHelperWriterGLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
+                                                          const unsigned int size)
+{
+    std::stringstream vecTypeStrStr;
+    vecTypeStrStr << "vec" << size;
+    std::string vecType = getTypeString(vecTypeStrStr.str().c_str());
+
+    // clang-format off
+    sink <<
+        vecType << " angle_frm(in " << vecType << " v) {\n"
+        "    v = clamp(v, -65504.0, 65504.0);\n"
+        "    " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
+        "    bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
+        "    v = v * exp2(-exponent);\n"
+        "    v = sign(v) * floor(abs(v));\n"
+        "    return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
+        "}\n";
+
+    sink <<
+        vecType << " angle_frl(in " << vecType << " v) {\n"
+        "    v = clamp(v, -2.0, 2.0);\n"
+        "    v = v * 256.0;\n"
+        "    v = sign(v) * floor(abs(v));\n"
+        "    return v * 0.00390625;\n"
+        "}\n";
+    // clang-format on
+}
+
+void RoundingHelperWriterGLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
+                                                         const unsigned int columns,
+                                                         const unsigned int rows,
+                                                         const char *functionName)
+{
+    std::stringstream matTypeStrStr;
+    matTypeStrStr << "mat" << columns;
+    if (rows != columns)
+    {
+        matTypeStrStr << "x" << rows;
+    }
+    std::string matType = getTypeString(matTypeStrStr.str().c_str());
+
+    sink << matType << " " << functionName << "(in " << matType << " m) {\n"
+         << "    " << matType << " rounded;\n";
+
+    for (unsigned int i = 0; i < columns; ++i)
+    {
+        sink << "    rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
+    }
+
+    sink << "    return rounded;\n"
+            "}\n";
+}
+
+static const char *GetHLSLTypeStr(const char *floatTypeStr)
+{
+    if (strcmp(floatTypeStr, "float") == 0)
+    {
+        return "float";
+    }
+    if (strcmp(floatTypeStr, "vec2") == 0)
+    {
+        return "float2";
+    }
+    if (strcmp(floatTypeStr, "vec3") == 0)
+    {
+        return "float3";
+    }
+    if (strcmp(floatTypeStr, "vec4") == 0)
+    {
+        return "float4";
+    }
+    if (strcmp(floatTypeStr, "mat2") == 0)
+    {
+        return "float2x2";
+    }
+    if (strcmp(floatTypeStr, "mat3") == 0)
+    {
+        return "float3x3";
+    }
+    if (strcmp(floatTypeStr, "mat4") == 0)
+    {
+        return "float4x4";
+    }
+    if (strcmp(floatTypeStr, "mat2x3") == 0)
+    {
+        return "float2x3";
+    }
+    if (strcmp(floatTypeStr, "mat2x4") == 0)
+    {
+        return "float2x4";
+    }
+    if (strcmp(floatTypeStr, "mat3x2") == 0)
+    {
+        return "float3x2";
+    }
+    if (strcmp(floatTypeStr, "mat3x4") == 0)
+    {
+        return "float3x4";
+    }
+    if (strcmp(floatTypeStr, "mat4x2") == 0)
+    {
+        return "float4x2";
+    }
+    if (strcmp(floatTypeStr, "mat4x3") == 0)
+    {
+        return "float4x3";
+    }
+    UNREACHABLE();
+    return nullptr;
+}
+
+std::string RoundingHelperWriterHLSL::getTypeString(const char *glslType)
+{
+    return GetHLSLTypeStr(glslType);
+}
+
+void RoundingHelperWriterHLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
+{
+    // In HLSL scalars are the same as 1-vectors.
+    writeVectorRoundingHelpers(sink, 1);
+}
+
+void RoundingHelperWriterHLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
+                                                          const unsigned int size)
+{
+    std::stringstream vecTypeStrStr;
+    vecTypeStrStr << "float" << size;
+    std::string vecType = vecTypeStrStr.str();
+
+    // clang-format off
+    sink <<
+        vecType << " angle_frm(" << vecType << " v) {\n"
+        "    v = clamp(v, -65504.0, 65504.0);\n"
+        "    " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
+        "    bool" << size << " isNonZero = exponent < -25.0;\n"
+        "    v = v * exp2(-exponent);\n"
+        "    v = sign(v) * floor(abs(v));\n"
+        "    return v * exp2(exponent) * (float" << size << ")(isNonZero);\n"
+        "}\n";
+
+    sink <<
+        vecType << " angle_frl(" << vecType << " v) {\n"
+        "    v = clamp(v, -2.0, 2.0);\n"
+        "    v = v * 256.0;\n"
+        "    v = sign(v) * floor(abs(v));\n"
+        "    return v * 0.00390625;\n"
+        "}\n";
+    // clang-format on
+}
+
+void RoundingHelperWriterHLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
+                                                         const unsigned int columns,
+                                                         const unsigned int rows,
+                                                         const char *functionName)
+{
+    std::stringstream matTypeStrStr;
+    matTypeStrStr << "float" << columns << "x" << rows;
+    std::string matType = matTypeStrStr.str();
+
+    sink << matType << " " << functionName << "(" << matType << " m) {\n"
+         << "    " << matType << " rounded;\n";
+
+    for (unsigned int i = 0; i < columns; ++i)
+    {
+        sink << "    rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
+    }
+
+    sink << "    return rounded;\n"
+            "}\n";
+}
+
+bool canRoundFloat(const TType &type)
+{
+    return type.getBasicType() == EbtFloat && !type.isArray() &&
+           (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
+}
+
+TIntermAggregate *createInternalFunctionCallNode(const TType &type,
+                                                 TString name,
+                                                 TIntermSequence *arguments)
+{
+    TName nameObj(name);
+    nameObj.setInternal(true);
+    TIntermAggregate *callNode =
+        TIntermAggregate::Create(type, EOpCallInternalRawFunction, arguments);
+    callNode->getFunctionSymbolInfo()->setNameObj(nameObj);
+    return callNode;
+}
+
+TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild)
+{
+    TString roundFunctionName;
+    if (roundedChild->getPrecision() == EbpMedium)
+        roundFunctionName = "angle_frm";
+    else
+        roundFunctionName      = "angle_frl";
+    TIntermSequence *arguments = new TIntermSequence();
+    arguments->push_back(roundedChild);
+    return createInternalFunctionCallNode(roundedChild->getType(), roundFunctionName, arguments);
+}
+
+TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
+                                                           TIntermTyped *right,
+                                                           const char *opNameStr)
+{
+    std::stringstream strstr;
+    if (left->getPrecision() == EbpMedium)
+        strstr << "angle_compound_" << opNameStr << "_frm";
+    else
+        strstr << "angle_compound_" << opNameStr << "_frl";
+    TString functionName       = strstr.str().c_str();
+    TIntermSequence *arguments = new TIntermSequence();
+    arguments->push_back(left);
+    arguments->push_back(right);
+    return createInternalFunctionCallNode(TType(EbtVoid), functionName, arguments);
+}
+
+bool ParentUsesResult(TIntermNode *parent, TIntermTyped *node)
+{
+    if (!parent)
+    {
+        return false;
+    }
+
+    TIntermBlock *blockParent = parent->getAsBlock();
+    // If the parent is a block, the result is not assigned anywhere,
+    // so rounding it is not needed. In particular, this can avoid a lot of
+    // unnecessary rounding of unused return values of assignment.
+    if (blockParent)
+    {
+        return false;
+    }
+    TIntermBinary *binaryParent = parent->getAsBinaryNode();
+    if (binaryParent && binaryParent->getOp() == EOpComma && (binaryParent->getRight() != node))
+    {
+        return false;
+    }
+    return true;
+}
+
+bool ParentConstructorTakesCareOfRounding(TIntermNode *parent, TIntermTyped *node)
+{
+    if (!parent)
+    {
+        return false;
+    }
+    TIntermAggregate *parentConstructor = parent->getAsAggregate();
+    if (!parentConstructor || parentConstructor->getOp() != EOpConstruct)
+    {
+        return false;
+    }
+    if (parentConstructor->getPrecision() != node->getPrecision())
+    {
+        return false;
+    }
+    return canRoundFloat(parentConstructor->getType());
+}
+
+}  // namespace anonymous
+
+EmulatePrecision::EmulatePrecision(const TSymbolTable &symbolTable, int shaderVersion)
+    : TLValueTrackingTraverser(true, true, true, symbolTable, shaderVersion),
+      mDeclaringVariables(false)
+{
+}
+
+void EmulatePrecision::visitSymbol(TIntermSymbol *node)
+{
+    TIntermNode *parent = getParentNode();
+    if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
+        !ParentConstructorTakesCareOfRounding(parent, node) && !mDeclaringVariables &&
+        !isLValueRequiredHere())
+    {
+        TIntermNode *replacement = createRoundingFunctionCallNode(node);
+        queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
+    }
+}
+
+bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
+{
+    bool visitChildren = true;
+
+    TOperator op = node->getOp();
+
+    // RHS of initialize is not being declared.
+    if (op == EOpInitialize && visit == InVisit)
+        mDeclaringVariables = false;
+
+    if ((op == EOpIndexDirectStruct) && visit == InVisit)
+        visitChildren = false;
+
+    if (visit != PreVisit)
+        return visitChildren;
+
+    const TType &type = node->getType();
+    bool roundFloat   = canRoundFloat(type);
+
+    if (roundFloat)
+    {
+        switch (op)
+        {
+            // Math operators that can result in a float may need to apply rounding to the return
+            // value. Note that in the case of assignment, the rounding is applied to its return
+            // value here, not the value being assigned.
+            case EOpAssign:
+            case EOpAdd:
+            case EOpSub:
+            case EOpMul:
+            case EOpDiv:
+            case EOpVectorTimesScalar:
+            case EOpVectorTimesMatrix:
+            case EOpMatrixTimesVector:
+            case EOpMatrixTimesScalar:
+            case EOpMatrixTimesMatrix:
+            {
+                TIntermNode *parent = getParentNode();
+                if (!ParentUsesResult(parent, node) ||
+                    ParentConstructorTakesCareOfRounding(parent, node))
+                {
+                    break;
+                }
+                TIntermNode *replacement = createRoundingFunctionCallNode(node);
+                queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
+                break;
+            }
+
+            // Compound assignment cases need to replace the operator with a function call.
+            case EOpAddAssign:
+            {
+                mEmulateCompoundAdd.insert(
+                    TypePair(type.getBuiltInTypeNameString(),
+                             node->getRight()->getType().getBuiltInTypeNameString()));
+                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
+                    node->getLeft(), node->getRight(), "add");
+                queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
+                break;
+            }
+            case EOpSubAssign:
+            {
+                mEmulateCompoundSub.insert(
+                    TypePair(type.getBuiltInTypeNameString(),
+                             node->getRight()->getType().getBuiltInTypeNameString()));
+                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
+                    node->getLeft(), node->getRight(), "sub");
+                queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
+                break;
+            }
+            case EOpMulAssign:
+            case EOpVectorTimesMatrixAssign:
+            case EOpVectorTimesScalarAssign:
+            case EOpMatrixTimesScalarAssign:
+            case EOpMatrixTimesMatrixAssign:
+            {
+                mEmulateCompoundMul.insert(
+                    TypePair(type.getBuiltInTypeNameString(),
+                             node->getRight()->getType().getBuiltInTypeNameString()));
+                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
+                    node->getLeft(), node->getRight(), "mul");
+                queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
+                break;
+            }
+            case EOpDivAssign:
+            {
+                mEmulateCompoundDiv.insert(
+                    TypePair(type.getBuiltInTypeNameString(),
+                             node->getRight()->getType().getBuiltInTypeNameString()));
+                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
+                    node->getLeft(), node->getRight(), "div");
+                queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
+                break;
+            }
+            default:
+                // The rest of the binary operations should not need precision emulation.
+                break;
+        }
+    }
+    return visitChildren;
+}
+
+bool EmulatePrecision::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+    // Variable or interface block declaration.
+    if (visit == PreVisit)
+    {
+        mDeclaringVariables = true;
+    }
+    else if (visit == InVisit)
+    {
+        mDeclaringVariables = true;
+    }
+    else
+    {
+        mDeclaringVariables = false;
+    }
+    return true;
+}
+
+bool EmulatePrecision::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+{
+    return false;
+}
+
+bool EmulatePrecision::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+{
+    return false;
+}
+
+bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (visit != PreVisit)
+        return true;
+    switch (node->getOp())
+    {
+        case EOpCallInternalRawFunction:
+        case EOpCallFunctionInAST:
+            // User-defined function return values are not rounded. The calculations that produced
+            // the value inside the function definition should have been rounded.
+            break;
+        case EOpConstruct:
+            if (node->getBasicType() == EbtStruct)
+            {
+                break;
+            }
+        default:
+            TIntermNode *parent = getParentNode();
+            if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
+                !ParentConstructorTakesCareOfRounding(parent, node))
+            {
+                TIntermNode *replacement = createRoundingFunctionCallNode(node);
+                queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
+            }
+            break;
+    }
+    return true;
+}
+
+bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
+{
+    switch (node->getOp())
+    {
+        case EOpNegative:
+        case EOpLogicalNot:
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+        case EOpLogicalNotComponentWise:
+            break;
+        default:
+            if (canRoundFloat(node->getType()) && visit == PreVisit)
+            {
+                TIntermNode *replacement = createRoundingFunctionCallNode(node);
+                queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
+            }
+            break;
+    }
+
+    return true;
+}
+
+void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase &sink,
+                                             const int shaderVersion,
+                                             const ShShaderOutput outputLanguage)
+{
+    std::unique_ptr<RoundingHelperWriter> roundingHelperWriter(
+        RoundingHelperWriter::createHelperWriter(outputLanguage));
+
+    roundingHelperWriter->writeCommonRoundingHelpers(sink, shaderVersion);
+
+    EmulationSet::const_iterator it;
+    for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
+        roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "+", "add");
+    for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++)
+        roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "-", "sub");
+    for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++)
+        roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "/", "div");
+    for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++)
+        roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "*", "mul");
+}
+
+// static
+bool EmulatePrecision::SupportedInLanguage(const ShShaderOutput outputLanguage)
+{
+    switch (outputLanguage)
+    {
+        case SH_HLSL_4_1_OUTPUT:
+        case SH_ESSL_OUTPUT:
+            return true;
+        default:
+            // Other languages not yet supported
+            return (outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
+                    sh::IsGLSL130OrNewer(outputLanguage));
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/EmulatePrecision.h b/src/third_party/angle/src/compiler/translator/EmulatePrecision.h
new file mode 100644
index 0000000..ed15395
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/EmulatePrecision.h
@@ -0,0 +1,73 @@
+//
+// 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.
+//
+
+#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
+#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/Compiler.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+#include "GLSLANG/ShaderLang.h"
+
+// This class gathers all compound assignments from the AST and can then write
+// the functions required for their precision emulation. This way there is no
+// need to write a huge number of variations of the emulated compound assignment
+// to every translated shader with emulation enabled.
+
+namespace sh
+{
+
+class EmulatePrecision : public TLValueTrackingTraverser
+{
+  public:
+    EmulatePrecision(const TSymbolTable &symbolTable, int shaderVersion);
+
+    void visitSymbol(TIntermSymbol *node) override;
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+    bool visitUnary(Visit visit, TIntermUnary *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
+    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+
+    void writeEmulationHelpers(TInfoSinkBase &sink,
+                               const int shaderVersion,
+                               const ShShaderOutput outputLanguage);
+
+    static bool SupportedInLanguage(const ShShaderOutput outputLanguage);
+
+  private:
+    struct TypePair
+    {
+        TypePair(const char *l, const char *r) : lType(l), rType(r) {}
+
+        const char *lType;
+        const char *rType;
+    };
+
+    struct TypePairComparator
+    {
+        bool operator()(const TypePair &l, const TypePair &r) const
+        {
+            if (l.lType == r.lType)
+                return l.rType < r.rType;
+            return l.lType < r.lType;
+        }
+    };
+
+    typedef std::set<TypePair, TypePairComparator> EmulationSet;
+    EmulationSet mEmulateCompoundAdd;
+    EmulationSet mEmulateCompoundSub;
+    EmulationSet mEmulateCompoundMul;
+    EmulationSet mEmulateCompoundDiv;
+
+    bool mDeclaringVariables;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
diff --git a/src/third_party/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp b/src/third_party/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp
new file mode 100644
index 0000000..9ff2f12
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp
@@ -0,0 +1,154 @@
+//
+// Copyright (c) 2016 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.
+//
+// Implementation of the integer pow expressions HLSL bug workaround.
+// See header for more info.
+
+#include "compiler/translator/ExpandIntegerPowExpressions.h"
+
+#include <cmath>
+#include <cstdlib>
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class Traverser : public TIntermTraverser
+{
+  public:
+    static void Apply(TIntermNode *root, unsigned int *tempIndex);
+
+  private:
+    Traverser();
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    void nextIteration();
+
+    bool mFound = false;
+};
+
+// static
+void Traverser::Apply(TIntermNode *root, unsigned int *tempIndex)
+{
+    Traverser traverser;
+    traverser.useTemporaryIndex(tempIndex);
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        if (traverser.mFound)
+        {
+            traverser.updateTree();
+        }
+    } while (traverser.mFound);
+}
+
+Traverser::Traverser() : TIntermTraverser(true, false, false)
+{
+}
+
+void Traverser::nextIteration()
+{
+    mFound = false;
+    nextTemporaryIndex();
+}
+
+bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (mFound)
+    {
+        return false;
+    }
+
+    // Test 0: skip non-pow operators.
+    if (node->getOp() != EOpPow)
+    {
+        return true;
+    }
+
+    const TIntermSequence *sequence = node->getSequence();
+    ASSERT(sequence->size() == 2u);
+    const TIntermConstantUnion *constantNode = sequence->at(1)->getAsConstantUnion();
+
+    // Test 1: check for a single constant.
+    if (!constantNode || constantNode->getNominalSize() != 1)
+    {
+        return true;
+    }
+
+    const TConstantUnion *constant = constantNode->getUnionArrayPointer();
+
+    TConstantUnion asFloat;
+    asFloat.cast(EbtFloat, *constant);
+
+    float value = asFloat.getFConst();
+
+    // Test 2: value is in the problematic range.
+    if (value < -5.0f || value > 9.0f)
+    {
+        return true;
+    }
+
+    // Test 3: value is integer or pretty close to an integer.
+    float absval = std::abs(value);
+    float frac   = absval - std::round(absval);
+    if (frac > 0.0001f)
+    {
+        return true;
+    }
+
+    // Test 4: skip -1, 0, and 1
+    int exponent = static_cast<int>(value);
+    int n        = std::abs(exponent);
+    if (n < 2)
+    {
+        return true;
+    }
+
+    // Potential problem case detected, apply workaround.
+    nextTemporaryIndex();
+
+    TIntermTyped *lhs = sequence->at(0)->getAsTyped();
+    ASSERT(lhs);
+
+    TIntermDeclaration *init = createTempInitDeclaration(lhs);
+    TIntermTyped *current    = createTempSymbol(lhs->getType());
+
+    insertStatementInParentBlock(init);
+
+    // Create a chain of n-1 multiples.
+    for (int i = 1; i < n; ++i)
+    {
+        TIntermBinary *mul = new TIntermBinary(EOpMul, current, createTempSymbol(lhs->getType()));
+        mul->setLine(node->getLine());
+        current = mul;
+    }
+
+    // For negative pow, compute the reciprocal of the positive pow.
+    if (exponent < 0)
+    {
+        TConstantUnion *oneVal = new TConstantUnion();
+        oneVal->setFConst(1.0f);
+        TIntermConstantUnion *oneNode = new TIntermConstantUnion(oneVal, node->getType());
+        TIntermBinary *div            = new TIntermBinary(EOpDiv, oneNode, current);
+        current                       = div;
+    }
+
+    queueReplacement(node, current, OriginalNode::IS_DROPPED);
+    mFound = true;
+    return false;
+}
+
+}  // anonymous namespace
+
+void ExpandIntegerPowExpressions(TIntermNode *root, unsigned int *tempIndex)
+{
+    Traverser::Apply(root, tempIndex);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ExpandIntegerPowExpressions.h b/src/third_party/angle/src/compiler/translator/ExpandIntegerPowExpressions.h
new file mode 100644
index 0000000..8bc8c96
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ExpandIntegerPowExpressions.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2016 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.
+//
+// This mutating tree traversal works around a bug in the HLSL compiler optimizer with "pow" that
+// manifests under the following conditions:
+//
+// - If pow() has a literal exponent value
+// - ... and this value is integer or within 10e-6 of an integer
+// - ... and it is in {-4, -3, -2, 2, 3, 4, 5, 6, 7, 8}
+//
+// The workaround is to replace the pow with a series of multiplies.
+// See http://anglebug.com/851
+
+#ifndef COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
+#define COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
+
+class TIntermNode;
+
+namespace sh
+{
+
+void ExpandIntegerPowExpressions(TIntermNode *root, unsigned int *tempIndex);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
diff --git a/src/third_party/angle/src/compiler/translator/ExtensionBehavior.h b/src/third_party/angle/src/compiler/translator/ExtensionBehavior.h
new file mode 100644
index 0000000..179dca3
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ExtensionBehavior.h
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
+#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
+
+#include <map>
+#include <string>
+
+typedef enum { EBhRequire, EBhEnable, EBhWarn, EBhDisable, EBhUndefined } TBehavior;
+
+inline const char *getBehaviorString(TBehavior b)
+{
+    switch (b)
+    {
+        case EBhRequire:
+            return "require";
+        case EBhEnable:
+            return "enable";
+        case EBhWarn:
+            return "warn";
+        case EBhDisable:
+            return "disable";
+        default:
+            return nullptr;
+    }
+}
+
+// Mapping between extension name and behavior.
+typedef std::map<std::string, TBehavior> TExtensionBehavior;
+
+inline bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, const char *extension)
+{
+    auto iter = extBehavior.find(extension);
+    return iter != extBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire);
+}
+
+#endif  // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
diff --git a/src/third_party/angle/src/compiler/translator/ExtensionGLSL.cpp b/src/third_party/angle/src/compiler/translator/ExtensionGLSL.cpp
new file mode 100644
index 0000000..5b5dc58
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ExtensionGLSL.cpp
@@ -0,0 +1,105 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ExtensionGLSL.cpp: Implements the TExtensionGLSL class that tracks GLSL extension requirements
+// of shaders.
+
+#include "compiler/translator/ExtensionGLSL.h"
+
+#include "compiler/translator/VersionGLSL.h"
+
+namespace sh
+{
+
+TExtensionGLSL::TExtensionGLSL(ShShaderOutput output)
+    : TIntermTraverser(true, false, false), mTargetVersion(ShaderOutputTypeToGLSLVersion(output))
+{
+}
+
+const std::set<std::string> &TExtensionGLSL::getEnabledExtensions() const
+{
+    return mEnabledExtensions;
+}
+
+const std::set<std::string> &TExtensionGLSL::getRequiredExtensions() const
+{
+    return mRequiredExtensions;
+}
+
+bool TExtensionGLSL::visitUnary(Visit, TIntermUnary *node)
+{
+    checkOperator(node);
+
+    return true;
+}
+
+bool TExtensionGLSL::visitAggregate(Visit, TIntermAggregate *node)
+{
+    checkOperator(node);
+
+    return true;
+}
+
+void TExtensionGLSL::checkOperator(TIntermOperator *node)
+{
+    if (mTargetVersion < GLSL_VERSION_130)
+    {
+        return;
+    }
+
+    switch (node->getOp())
+    {
+        case EOpAbs:
+            break;
+
+        case EOpSign:
+            break;
+
+        case EOpMix:
+            break;
+
+        case EOpFloatBitsToInt:
+        case EOpFloatBitsToUint:
+        case EOpIntBitsToFloat:
+        case EOpUintBitsToFloat:
+            if (mTargetVersion < GLSL_VERSION_330)
+            {
+                // Bit conversion functions cannot be emulated.
+                mRequiredExtensions.insert("GL_ARB_shader_bit_encoding");
+            }
+            break;
+
+        case EOpPackSnorm2x16:
+        case EOpPackHalf2x16:
+        case EOpUnpackSnorm2x16:
+        case EOpUnpackHalf2x16:
+            if (mTargetVersion < GLSL_VERSION_420)
+            {
+                mEnabledExtensions.insert("GL_ARB_shading_language_packing");
+
+                if (mTargetVersion < GLSL_VERSION_330)
+                {
+                    // floatBitsToUint and uintBitsToFloat are needed to emulate
+                    // packHalf2x16 and unpackHalf2x16 respectively and cannot be
+                    // emulated themselves.
+                    mRequiredExtensions.insert("GL_ARB_shader_bit_encoding");
+                }
+            }
+            break;
+
+        case EOpPackUnorm2x16:
+        case EOpUnpackUnorm2x16:
+            if (mTargetVersion < GLSL_VERSION_410)
+            {
+                mEnabledExtensions.insert("GL_ARB_shading_language_packing");
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ExtensionGLSL.h b/src/third_party/angle/src/compiler/translator/ExtensionGLSL.h
new file mode 100644
index 0000000..3c2dbe0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ExtensionGLSL.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ExtensionGLSL.h: Defines the TExtensionGLSL class that tracks GLSL extension requirements of
+// shaders.
+
+#ifndef COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
+#define COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
+
+#include <set>
+#include <string>
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+// Traverses the intermediate tree to determine which GLSL extensions are required
+// to support the shader.
+class TExtensionGLSL : public TIntermTraverser
+{
+  public:
+    TExtensionGLSL(ShShaderOutput output);
+
+    const std::set<std::string> &getEnabledExtensions() const;
+    const std::set<std::string> &getRequiredExtensions() const;
+
+    bool visitUnary(Visit visit, TIntermUnary *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+
+  private:
+    void checkOperator(TIntermOperator *node);
+
+    int mTargetVersion;
+
+    std::set<std::string> mEnabledExtensions;
+    std::set<std::string> mRequiredExtensions;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/FindMain.cpp b/src/third_party/angle/src/compiler/translator/FindMain.cpp
new file mode 100644
index 0000000..f73666b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/FindMain.cpp
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2017 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.
+//
+
+// FindMain.cpp: Find the main() function definition in a given AST.
+
+#include "compiler/translator/FindMain.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+TIntermFunctionDefinition *FindMain(TIntermBlock *root)
+{
+    for (TIntermNode *node : *root->getSequence())
+    {
+        TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition();
+        if (nodeFunction != nullptr && nodeFunction->getFunctionSymbolInfo()->isMain())
+        {
+            return nodeFunction;
+        }
+    }
+    return nullptr;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/FindMain.h b/src/third_party/angle/src/compiler/translator/FindMain.h
new file mode 100644
index 0000000..fb06583
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/FindMain.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2017 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.
+//
+
+// FindMain.h: Find the main() function definition in a given AST.
+
+#ifndef COMPILER_TRANSLATOR_FINDMAIN_H_
+#define COMPILER_TRANSLATOR_FINDMAIN_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TIntermFunctionDefinition;
+
+TIntermFunctionDefinition *FindMain(TIntermBlock *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_FINDMAIN_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/translator/FindSymbolNode.cpp b/src/third_party/angle/src/compiler/translator/FindSymbolNode.cpp
new file mode 100644
index 0000000..87fb9d5
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/FindSymbolNode.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FindSymbol.cpp:
+//     Utility for finding a symbol node inside an AST tree.
+
+#include "compiler/translator/FindSymbolNode.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class SymbolFinder : public TIntermTraverser
+{
+  public:
+    SymbolFinder(const TString &symbolName, TBasicType basicType)
+        : TIntermTraverser(true, false, false),
+          mSymbolName(symbolName),
+          mNodeFound(nullptr),
+          mBasicType(basicType)
+    {
+    }
+
+    void visitSymbol(TIntermSymbol *node)
+    {
+        if (node->getBasicType() == mBasicType && node->getSymbol() == mSymbolName)
+        {
+            mNodeFound = node;
+        }
+    }
+
+    bool isFound() const { return mNodeFound != nullptr; }
+    const TIntermSymbol *getNode() const { return mNodeFound; }
+
+  private:
+    TString mSymbolName;
+    TIntermSymbol *mNodeFound;
+    TBasicType mBasicType;
+};
+
+}  // anonymous namespace
+
+const TIntermSymbol *FindSymbolNode(TIntermNode *root,
+                                    const TString &symbolName,
+                                    TBasicType basicType)
+{
+    SymbolFinder finder(symbolName, basicType);
+    root->traverse(&finder);
+    return finder.getNode();
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/FindSymbolNode.h b/src/third_party/angle/src/compiler/translator/FindSymbolNode.h
new file mode 100644
index 0000000..08dfb9a
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/FindSymbolNode.h
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FindSymbolNode.h:
+//     Utility for finding a symbol node inside an AST tree.
+
+#ifndef COMPILER_TRANSLATOR_FIND_SYMBOL_H_
+#define COMPILER_TRANSLATOR_FIND_SYMBOL_H_
+
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Common.h"
+
+namespace sh
+{
+
+class TIntermNode;
+class TIntermSymbol;
+
+const TIntermSymbol *FindSymbolNode(TIntermNode *root,
+                                    const TString &symbolName,
+                                    TBasicType basicType);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_FIND_SYMBOL_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/translator/FlagStd140Structs.cpp b/src/third_party/angle/src/compiler/translator/FlagStd140Structs.cpp
new file mode 100644
index 0000000..d16412b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/FlagStd140Structs.cpp
@@ -0,0 +1,77 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/FlagStd140Structs.h"
+
+namespace sh
+{
+
+bool FlagStd140Structs::visitBinary(Visit visit, TIntermBinary *binaryNode)
+{
+    if (binaryNode->getRight()->getBasicType() == EbtStruct)
+    {
+        switch (binaryNode->getOp())
+        {
+            case EOpIndexDirectInterfaceBlock:
+            case EOpIndexDirectStruct:
+                if (isInStd140InterfaceBlock(binaryNode->getLeft()))
+                {
+                    mFlaggedNodes.push_back(binaryNode);
+                }
+                break;
+
+            default:
+                break;
+        }
+        return false;
+    }
+
+    if (binaryNode->getOp() == EOpIndexDirectStruct)
+    {
+        return false;
+    }
+
+    return visit == PreVisit;
+}
+
+void FlagStd140Structs::visitSymbol(TIntermSymbol *symbol)
+{
+    if (isInStd140InterfaceBlock(symbol) && symbol->getBasicType() == EbtStruct)
+    {
+        mFlaggedNodes.push_back(symbol);
+    }
+}
+
+bool FlagStd140Structs::isInStd140InterfaceBlock(TIntermTyped *node) const
+{
+    TIntermBinary *binaryNode = node->getAsBinaryNode();
+
+    if (binaryNode)
+    {
+        return isInStd140InterfaceBlock(binaryNode->getLeft());
+    }
+
+    const TType &type = node->getType();
+
+    // determine if we are in the standard layout
+    const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
+    if (interfaceBlock)
+    {
+        return (interfaceBlock->blockStorage() == EbsStd140);
+    }
+
+    return false;
+}
+
+std::vector<TIntermTyped *> FlagStd140ValueStructs(TIntermNode *node)
+{
+    FlagStd140Structs flaggingTraversal;
+
+    node->traverse(&flaggingTraversal);
+
+    return flaggingTraversal.getFlaggedNodes();
+}
+}
diff --git a/src/third_party/angle/src/compiler/translator/FlagStd140Structs.h b/src/third_party/angle/src/compiler/translator/FlagStd140Structs.h
new file mode 100644
index 0000000..672b20d
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/FlagStd140Structs.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
+#define COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+// This class finds references to nested structs of std140 blocks that access
+// the nested struct "by value", where the padding added in the translator
+// conflicts with the "natural" unpadded type.
+class FlagStd140Structs : public TIntermTraverser
+{
+  public:
+    FlagStd140Structs() : TIntermTraverser(true, false, false) {}
+
+    const std::vector<TIntermTyped *> getFlaggedNodes() const { return mFlaggedNodes; }
+
+  protected:
+    bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
+    void visitSymbol(TIntermSymbol *symbol) override;
+
+  private:
+    bool isInStd140InterfaceBlock(TIntermTyped *node) const;
+
+    std::vector<TIntermTyped *> mFlaggedNodes;
+};
+
+std::vector<TIntermTyped *> FlagStd140ValueStructs(TIntermNode *node);
+}
+
+#endif  // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
diff --git a/src/third_party/angle/src/compiler/translator/HashNames.h b/src/third_party/angle/src/compiler/translator/HashNames.h
new file mode 100644
index 0000000..09c959f
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/HashNames.h
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_HASHNAMES_H_
+#define COMPILER_TRANSLATOR_HASHNAMES_H_
+
+#include <map>
+
+#include "compiler/translator/IntermNode.h"
+
+#define HASHED_NAME_PREFIX "webgl_"
+
+typedef std::map<TPersistString, TPersistString> NameMap;
+
+#endif  // COMPILER_TRANSLATOR_HASHNAMES_H_
diff --git a/src/third_party/angle/src/compiler/translator/InfoSink.cpp b/src/third_party/angle/src/compiler/translator/InfoSink.cpp
new file mode 100644
index 0000000..db26aa6
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/InfoSink.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InfoSink.h"
+
+namespace sh
+{
+
+void TInfoSinkBase::prefix(Severity severity)
+{
+    switch (severity)
+    {
+        case SH_WARNING:
+            sink.append("WARNING: ");
+            break;
+        case SH_ERROR:
+            sink.append("ERROR: ");
+            break;
+        default:
+            sink.append("UNKOWN ERROR: ");
+            break;
+    }
+}
+
+void TInfoSinkBase::location(int file, int line)
+{
+    TPersistStringStream stream;
+    if (line)
+        stream << file << ":" << line;
+    else
+        stream << file << ":? ";
+    stream << ": ";
+
+    sink.append(stream.str());
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/InfoSink.h b/src/third_party/angle/src/compiler/translator/InfoSink.h
new file mode 100644
index 0000000..2705f48
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/InfoSink.h
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_INFOSINK_H_
+#define COMPILER_TRANSLATOR_INFOSINK_H_
+
+#include <math.h>
+#include <stdlib.h>
+#include "compiler/translator/Common.h"
+#include "compiler/translator/Severity.h"
+
+namespace sh
+{
+
+// Returns the fractional part of the given floating-point number.
+inline float fractionalPart(float f)
+{
+    float intPart = 0.0f;
+    return modff(f, &intPart);
+}
+
+//
+// Encapsulate info logs for all objects that have them.
+//
+// The methods are a general set of tools for getting a variety of
+// messages and types inserted into the log.
+//
+class TInfoSinkBase
+{
+  public:
+    TInfoSinkBase() {}
+
+    template <typename T>
+    TInfoSinkBase &operator<<(const T &t)
+    {
+        TPersistStringStream stream;
+        stream << t;
+        sink.append(stream.str());
+        return *this;
+    }
+    // Override << operator for specific types. It is faster to append strings
+    // and characters directly to the sink.
+    TInfoSinkBase &operator<<(char c)
+    {
+        sink.append(1, c);
+        return *this;
+    }
+    TInfoSinkBase &operator<<(const char *str)
+    {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase &operator<<(const TPersistString &str)
+    {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase &operator<<(const TString &str)
+    {
+        sink.append(str.c_str());
+        return *this;
+    }
+    // Make sure floats are written with correct precision.
+    TInfoSinkBase &operator<<(float f)
+    {
+        // Make sure that at least one decimal point is written. If a number
+        // does not have a fractional part, the default precision format does
+        // not write the decimal portion which gets interpreted as integer by
+        // the compiler.
+        TPersistStringStream stream;
+        if (fractionalPart(f) == 0.0f)
+        {
+            stream.precision(1);
+            stream << std::showpoint << std::fixed << f;
+        }
+        else
+        {
+            stream.unsetf(std::ios::fixed);
+            stream.unsetf(std::ios::scientific);
+            stream.precision(8);
+            stream << f;
+        }
+        sink.append(stream.str());
+        return *this;
+    }
+    // Write boolean values as their names instead of integral value.
+    TInfoSinkBase &operator<<(bool b)
+    {
+        const char *str = b ? "true" : "false";
+        sink.append(str);
+        return *this;
+    }
+
+    void erase() { sink.clear(); }
+    int size() { return static_cast<int>(sink.size()); }
+
+    const TPersistString &str() const { return sink; }
+    const char *c_str() const { return sink.c_str(); }
+
+    void prefix(Severity severity);
+    void location(int file, int line);
+
+  private:
+    TPersistString sink;
+};
+
+class TInfoSink
+{
+  public:
+    TInfoSinkBase info;
+    TInfoSinkBase debug;
+    TInfoSinkBase obj;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_INFOSINK_H_
diff --git a/src/third_party/angle/src/compiler/translator/Initialize.cpp b/src/third_party/angle/src/compiler/translator/Initialize.cpp
new file mode 100644
index 0000000..edc50b8
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Initialize.cpp
@@ -0,0 +1,970 @@
+//
+// 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.
+//
+
+//
+// Create symbols that declare built-in definitions, add built-ins that
+// cannot be expressed in the files, and establish mappings between
+// built-in functions and operators.
+//
+
+#include "compiler/translator/Initialize.h"
+#include "compiler/translator/Cache.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "angle_gl.h"
+
+namespace sh
+{
+
+void InsertBuiltInFunctions(sh::GLenum type,
+                            ShShaderSpec spec,
+                            const ShBuiltInResources &resources,
+                            TSymbolTable &symbolTable)
+{
+    const TType *voidType = TCache::getType(EbtVoid);
+    const TType *float1   = TCache::getType(EbtFloat);
+    const TType *float2   = TCache::getType(EbtFloat, 2);
+    const TType *float3   = TCache::getType(EbtFloat, 3);
+    const TType *float4   = TCache::getType(EbtFloat, 4);
+    const TType *int1     = TCache::getType(EbtInt);
+    const TType *int2     = TCache::getType(EbtInt, 2);
+    const TType *int3     = TCache::getType(EbtInt, 3);
+    const TType *uint1    = TCache::getType(EbtUInt);
+    const TType *bool1    = TCache::getType(EbtBool);
+    const TType *genType  = TCache::getType(EbtGenType);
+    const TType *genIType = TCache::getType(EbtGenIType);
+    const TType *genUType = TCache::getType(EbtGenUType);
+    const TType *genBType = TCache::getType(EbtGenBType);
+
+    //
+    // Angle and Trigonometric Functions.
+    //
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRadians, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDegrees, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSin, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCos, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpTan, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAsin, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAcos, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSinh, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpCosh, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTanh, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAsinh, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAcosh, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAtanh, genType, genType);
+
+    //
+    // Exponential Functions.
+    //
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpPow, genType, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp2, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog2, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSqrt, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpInverseSqrt, genType, genType);
+
+    //
+    // Common Functions.
+    //
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAbs, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAbs, genIType, genIType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSign, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSign, genIType, genIType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFloor, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTrunc, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRound, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRoundEven, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCeil, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFract, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, float1);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, float1);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, genIType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, int1);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, genUType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, uint1);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, float1);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, genIType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, int1);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, genUType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, uint1);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, float1, float1);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, int1, int1);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, genIType, genIType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, uint1, uint1);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, genUType, genUType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, float1);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMix, genType, genType, genType, genBType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, float1, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, genType, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, float1, float1, genType);
+
+    const TType *outGenType = TCache::getType(EbtGenType, EvqOut);
+    const TType *outGenIType = TCache::getType(EbtGenIType, EvqOut);
+
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, genType, genType, outGenType);
+
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsNan, genBType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsInf, genBType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, genType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, genIType);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, genUType);
+
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFrexp, genType, genType, outGenIType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpLdexp, genType, genType, genIType);
+
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, float2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, float2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, float2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, uint1);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, uint1);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, uint1);
+
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackUnorm4x8, uint1, float4);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackSnorm4x8, uint1, float4);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackUnorm4x8, float4, uint1);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackSnorm4x8, float4, uint1);
+
+    //
+    // Geometric Functions.
+    //
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLength, float1, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDistance, float1, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDot, float1, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCross, float3, float3, float3);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNormalize, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFaceForward, genType, genType, genType,
+                                genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpReflect, genType, genType, genType);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRefract, genType, genType, genType, float1);
+
+    const TType *mat2   = TCache::getType(EbtFloat, 2, 2);
+    const TType *mat3   = TCache::getType(EbtFloat, 3, 3);
+    const TType *mat4   = TCache::getType(EbtFloat, 4, 4);
+    const TType *mat2x3 = TCache::getType(EbtFloat, 2, 3);
+    const TType *mat3x2 = TCache::getType(EbtFloat, 3, 2);
+    const TType *mat2x4 = TCache::getType(EbtFloat, 2, 4);
+    const TType *mat4x2 = TCache::getType(EbtFloat, 4, 2);
+    const TType *mat3x4 = TCache::getType(EbtFloat, 3, 4);
+    const TType *mat4x3 = TCache::getType(EbtFloat, 4, 3);
+
+    //
+    // Matrix Functions.
+    //
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat2, mat2, mat2);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat3, mat3, mat3);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat4, mat4, mat4);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x3, mat2x3, mat2x3);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x2, mat3x2, mat3x2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x4, mat2x4, mat2x4);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x2, mat4x2, mat4x2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x4, mat3x4, mat3x4);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x3, mat4x3, mat4x3);
+
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2, float2, float2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3, float3, float3);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4, float4, float4);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, float3, float2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, float2, float3);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, float4, float2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, float2, float4);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, float4, float3);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, float3, float4);
+
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2, mat2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3, mat3);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4, mat4);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x3, mat3x2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x2, mat2x3);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x4, mat4x2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x2, mat2x4);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x4, mat4x3);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x3, mat3x4);
+
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat3);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat4);
+
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat2, mat2);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat3, mat3);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat4, mat4);
+
+    const TType *vec  = TCache::getType(EbtVec);
+    const TType *ivec = TCache::getType(EbtIVec);
+    const TType *uvec = TCache::getType(EbtUVec);
+    const TType *bvec = TCache::getType(EbtBVec);
+
+    //
+    // Vector relational functions.
+    //
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, vec, vec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, ivec, ivec);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanComponentWise, bvec, uvec, uvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, vec, vec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, ivec, ivec);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanEqualComponentWise, bvec, uvec, uvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, vec, vec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, ivec, ivec);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanComponentWise, bvec, uvec, uvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, vec, vec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, ivec,
+                                ivec);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, uvec, uvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, vec, vec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, ivec, ivec);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpEqualComponentWise, bvec, uvec, uvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, bvec, bvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, vec, vec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, ivec, ivec);
+    symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpNotEqualComponentWise, bvec, uvec, uvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, bvec, bvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAny, bool1, bvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAll, bool1, bvec);
+    symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLogicalNotComponentWise, bvec, bvec);
+
+    //
+    // Integer functions
+    //
+    const TType *outGenUType = TCache::getType(EbtGenUType, EvqOut);
+
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genIType, genIType, int1,
+                                int1);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genUType, genUType, int1,
+                                int1);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genIType, genIType, genIType,
+                                int1, int1);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genUType, genUType, genUType,
+                                int1, int1);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genIType, genIType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genUType, genUType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genIType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genUType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genIType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genUType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genIType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genUType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUaddCarry, genUType, genUType, genUType,
+                                outGenUType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUsubBorrow, genUType, genUType, genUType,
+                                outGenUType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUmulExtended, voidType, genUType, genUType,
+                                outGenUType, outGenUType);
+    symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpImulExtended, voidType, genIType, genIType,
+                                outGenIType, outGenIType);
+
+    const TType *sampler2D   = TCache::getType(EbtSampler2D);
+    const TType *samplerCube = TCache::getType(EbtSamplerCube);
+
+    //
+    // Texture Functions for GLSL ES 1.0
+    //
+    symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2);
+    symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3);
+    symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4);
+    symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3);
+
+    if (resources.OES_EGL_image_external || resources.NV_EGL_stream_consumer_external)
+    {
+        const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
+
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", samplerExternalOES, float2);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES,
+                                  float3);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES,
+                                  float4);
+    }
+
+    if (resources.ARB_texture_rectangle)
+    {
+        const TType *sampler2DRect = TCache::getType(EbtSampler2DRect);
+
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRect", sampler2DRect, float2);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect,
+                                  float3);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect,
+                                  float4);
+    }
+
+    if (resources.EXT_shader_texture_lod)
+    {
+        /* The *Grad* variants are new to both vertex and fragment shaders; the fragment
+         * shader specific pieces are added separately below.
+         */
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+                                  "texture2DGradEXT", sampler2D, float2, float2, float2);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+                                  "texture2DProjGradEXT", sampler2D, float3, float2, float2);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+                                  "texture2DProjGradEXT", sampler2D, float4, float2, float2);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+                                  "textureCubeGradEXT", samplerCube, float3, float3, float3);
+    }
+
+    if (type == GL_FRAGMENT_SHADER)
+    {
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3,
+                                  float1);
+
+        if (resources.OES_standard_derivatives)
+        {
+            symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdx, "GL_OES_standard_derivatives",
+                                        genType, genType);
+            symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdy, "GL_OES_standard_derivatives",
+                                        genType, genType);
+            symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpFwidth, "GL_OES_standard_derivatives",
+                                        genType, genType);
+        }
+
+        if (resources.EXT_shader_texture_lod)
+        {
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+                                      "texture2DLodEXT", sampler2D, float2, float1);
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+                                      "texture2DProjLodEXT", sampler2D, float3, float1);
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+                                      "texture2DProjLodEXT", sampler2D, float4, float1);
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+                                      "textureCubeLodEXT", samplerCube, float3, float1);
+        }
+    }
+
+    if (type == GL_VERTEX_SHADER)
+    {
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float4,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLod", samplerCube, float3,
+                                  float1);
+    }
+
+    const TType *gvec4 = TCache::getType(EbtGVec4);
+
+    const TType *gsampler2D      = TCache::getType(EbtGSampler2D);
+    const TType *gsamplerCube    = TCache::getType(EbtGSamplerCube);
+    const TType *gsampler3D      = TCache::getType(EbtGSampler3D);
+    const TType *gsampler2DArray = TCache::getType(EbtGSampler2DArray);
+    const TType *gsampler2DMS    = TCache::getType(EbtGSampler2DMS);
+
+    //
+    // Texture Functions for GLSL ES 3.0
+    //
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2D, float2, float1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler3D, float3, float1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1);
+
+    if (resources.OES_EGL_image_external_essl3)
+    {
+        const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
+
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
+                                  float3);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
+                                  float4);
+    }
+
+    if (resources.EXT_YUV_target)
+    {
+        const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
+
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "texture",
+                                  samplerExternal2DY2YEXT, float2);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "textureProj",
+                                  samplerExternal2DY2YEXT, float3);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "textureProj",
+                                  samplerExternal2DY2YEXT, float4);
+
+        const TType *yuvCscStandardEXT = TCache::getType(EbtYuvCscStandardEXT);
+
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float3, "rgb_2_yuv", float3,
+                                  yuvCscStandardEXT);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float3, "yuv_2_rgb", float3,
+                                  yuvCscStandardEXT);
+    }
+
+    if (type == GL_FRAGMENT_SHADER)
+    {
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3, float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3, float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3, float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1);
+
+        if (resources.OES_EGL_image_external_essl3)
+        {
+            const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
+
+            symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2,
+                                      float1);
+            symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
+                                      float3, float1);
+            symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
+                                      float4, float1);
+        }
+
+        if (resources.EXT_YUV_target)
+        {
+            const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
+
+            symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "texture",
+                                      samplerExternal2DY2YEXT, float2, float1);
+            symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "textureProj",
+                                      samplerExternal2DY2YEXT, float3, float1);
+            symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "textureProj",
+                                      samplerExternal2DY2YEXT, float4, float1);
+        }
+    }
+
+    const TType *sampler2DShadow      = TCache::getType(EbtSampler2DShadow);
+    const TType *samplerCubeShadow    = TCache::getType(EbtSamplerCubeShadow);
+    const TType *sampler2DArrayShadow = TCache::getType(EbtSampler2DArrayShadow);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DArrayShadow, float4);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLod", sampler2DShadow, float3,
+                              float1);
+
+    if (type == GL_FRAGMENT_SHADER)
+    {
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4,
+                                  float1);
+    }
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2D, int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler3D, int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsamplerCube, int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler2DArray, int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", sampler2DShadow, int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2DMS);
+
+    if (resources.OES_EGL_image_external_essl3)
+    {
+        const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
+
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerExternalOES, int1);
+    }
+
+    if (resources.EXT_YUV_target)
+    {
+        const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
+
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", int2, "textureSize",
+                                  samplerExternal2DY2YEXT, int1);
+    }
+
+    if (type == GL_FRAGMENT_SHADER)
+    {
+        symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdx, genType, genType);
+        symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdy, genType, genType);
+        symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFwidth, genType, genType);
+    }
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3,
+                              int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3,
+                              int2);
+
+    if (type == GL_FRAGMENT_SHADER)
+    {
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3,
+                                  float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3,
+                                  int2, float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3,
+                                  int2, float1);
+    }
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4,
+                              int2);
+
+    if (type == GL_FRAGMENT_SHADER)
+    {
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3,
+                                  int2, float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4,
+                                  int2, float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4,
+                                  int3, float1);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow,
+                                  float4, int2, float1);
+    }
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2D, float2, float1,
+                              int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler3D, float3, float1,
+                              int3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLodOffset", sampler2DShadow, float3,
+                              float1, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2DArray, float3,
+                              float1, int2);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float3, float1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float4, float1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler3D, float4, float1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLod", sampler2DShadow, float4,
+                              float1);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float3,
+                              float1, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float4,
+                              float1, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler3D, float4,
+                              float1, int3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLodOffset", sampler2DShadow,
+                              float4, float1, int2);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2D, int2, int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler3D, int3, int1);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2DArray, int3, int1);
+
+    if (resources.OES_EGL_image_external_essl3)
+    {
+        const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
+
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texelFetch", samplerExternalOES, int2,
+                                  int1);
+    }
+
+    if (resources.EXT_YUV_target)
+    {
+        const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
+
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "texelFetch",
+                                  samplerExternal2DY2YEXT, int2, int1);
+    }
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2D, int2, int1,
+                              int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1,
+                              int3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3,
+                              int1, int2);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2D, float2, float2,
+                              float2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler3D, float3, float3,
+                              float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsamplerCube, float3, float3,
+                              float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DShadow, float3,
+                              float2, float2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", samplerCubeShadow, float4,
+                              float3, float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2DArray, float3, float2,
+                              float2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DArrayShadow, float4,
+                              float2, float2);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2D, float2,
+                              float2, float2, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler3D, float3,
+                              float3, float3, int3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DShadow, float3,
+                              float2, float2, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2DArray, float3,
+                              float2, float2, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DArrayShadow,
+                              float4, float2, float2, int2);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float3, float2,
+                              float2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float4, float2,
+                              float2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler3D, float4, float3,
+                              float3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGrad", sampler2DShadow, float4,
+                              float2, float2);
+
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float3,
+                              float2, float2, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float4,
+                              float2, float2, int2);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4,
+                              float3, float3, int3);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow,
+                              float4, float2, float2, int2);
+
+    const TType *gimage2D      = TCache::getType(EbtGImage2D);
+    const TType *gimage3D      = TCache::getType(EbtGImage3D);
+    const TType *gimage2DArray = TCache::getType(EbtGImage2DArray);
+    const TType *gimageCube    = TCache::getType(EbtGImageCube);
+
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2D, int2, gvec4);
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage3D, int3, gvec4);
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2DArray, int3, gvec4);
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimageCube, int3, gvec4);
+
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2D, int2);
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage3D, int3);
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2DArray, int3);
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimageCube, int3);
+
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimage2D);
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage3D);
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage2DArray);
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimageCube);
+
+    symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrier, voidType,
+                                                  "memoryBarrier");
+    symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierAtomicCounter,
+                                                  voidType, "memoryBarrierAtomicCounter");
+    symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierBuffer,
+                                                  voidType, "memoryBarrierBuffer");
+    symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierImage, voidType,
+                                                  "memoryBarrierImage");
+
+    symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "texelFetch", gsampler2DMS, int2, int1);
+
+    if (type == GL_COMPUTE_SHADER)
+    {
+        symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpBarrier, voidType,
+                                                      "barrier");
+        symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierShared,
+                                                      voidType, "memoryBarrierShared");
+        symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpGroupMemoryBarrier,
+                                                      voidType, "groupMemoryBarrier");
+    }
+
+    //
+    // Depth range in window coordinates
+    //
+    TFieldList *fields       = NewPoolTFieldList();
+    TSourceLoc zeroSourceLoc = {0, 0, 0, 0};
+    auto highpFloat1         = new TType(EbtFloat, EbpHigh, EvqGlobal, 1);
+    TField *near             = new TField(highpFloat1, NewPoolTString("near"), zeroSourceLoc);
+    TField *far              = new TField(highpFloat1, NewPoolTString("far"), zeroSourceLoc);
+    TField *diff             = new TField(highpFloat1, NewPoolTString("diff"), zeroSourceLoc);
+    fields->push_back(near);
+    fields->push_back(far);
+    fields->push_back(diff);
+    TStructure *depthRangeStruct =
+        new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
+    TVariable *depthRangeParameters =
+        new TVariable(&depthRangeStruct->name(), TType(depthRangeStruct), true);
+    symbolTable.insert(COMMON_BUILTINS, depthRangeParameters);
+    TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
+    depthRange->setQualifier(EvqUniform);
+    // Do lazy initialization for depth range, so we allocate to the current scope.
+    depthRangeParameters->getType().realize();
+    depthRange->getType().realize();
+    symbolTable.insert(COMMON_BUILTINS, depthRange);
+
+    //
+    // Implementation dependent built-in constants.
+    //
+    symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexAttribs", resources.MaxVertexAttribs,
+                               EbpMedium);
+    symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexUniformVectors",
+                               resources.MaxVertexUniformVectors, EbpMedium);
+    symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexTextureImageUnits",
+                               resources.MaxVertexTextureImageUnits, EbpMedium);
+    symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxCombinedTextureImageUnits",
+                               resources.MaxCombinedTextureImageUnits, EbpMedium);
+    symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxTextureImageUnits",
+                               resources.MaxTextureImageUnits, EbpMedium);
+    symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors",
+                               resources.MaxFragmentUniformVectors, EbpMedium);
+
+    symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors,
+                               EbpMedium);
+
+    symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers,
+                               EbpMedium);
+    if (resources.EXT_blend_func_extended)
+    {
+        symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended",
+                                      "gl_MaxDualSourceDrawBuffersEXT",
+                                      resources.MaxDualSourceDrawBuffers);
+    }
+
+    symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors",
+                               resources.MaxVertexOutputVectors, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors",
+                               resources.MaxFragmentInputVectors, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset",
+                               resources.MinProgramTexelOffset, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset",
+                               resources.MaxProgramTexelOffset, EbpMedium);
+
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxImageUnits", resources.MaxImageUnits,
+                               EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexImageUniforms",
+                               resources.MaxVertexImageUniforms, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentImageUniforms",
+                               resources.MaxFragmentImageUniforms, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeImageUniforms",
+                               resources.MaxComputeImageUniforms, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedImageUniforms",
+                               resources.MaxCombinedImageUniforms, EbpMedium);
+
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedShaderOutputResources",
+                               resources.MaxCombinedShaderOutputResources, EbpMedium);
+
+    symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupCount",
+                                 resources.MaxComputeWorkGroupCount, EbpHigh);
+    symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupSize",
+                                 resources.MaxComputeWorkGroupSize, EbpHigh);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeUniformComponents",
+                               resources.MaxComputeUniformComponents, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeTextureImageUnits",
+                               resources.MaxComputeTextureImageUnits, EbpMedium);
+
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounters",
+                               resources.MaxComputeAtomicCounters, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounterBuffers",
+                               resources.MaxComputeAtomicCounterBuffers, EbpMedium);
+
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounters",
+                               resources.MaxVertexAtomicCounters, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounters",
+                               resources.MaxFragmentAtomicCounters, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounters",
+                               resources.MaxCombinedAtomicCounters, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBindings",
+                               resources.MaxAtomicCounterBindings, EbpMedium);
+
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounterBuffers",
+                               resources.MaxVertexAtomicCounterBuffers, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounterBuffers",
+                               resources.MaxFragmentAtomicCounterBuffers, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounterBuffers",
+                               resources.MaxCombinedAtomicCounterBuffers, EbpMedium);
+    symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBufferSize",
+                               resources.MaxAtomicCounterBufferSize, EbpMedium);
+}
+
+void IdentifyBuiltIns(sh::GLenum type,
+                      ShShaderSpec spec,
+                      const ShBuiltInResources &resources,
+                      TSymbolTable &symbolTable)
+{
+    //
+    // Insert some special built-in variables that are not in
+    // the built-in header files.
+    //
+
+    if (resources.OVR_multiview && type != GL_COMPUTE_SHADER)
+    {
+        symbolTable.insert(COMMON_BUILTINS, "GL_OVR_multiview",
+                           new TVariable(NewPoolTString("gl_ViewID_OVR"),
+                                         TType(EbtUInt, EbpHigh, EvqViewIDOVR, 1)));
+    }
+
+    switch (type)
+    {
+        case GL_FRAGMENT_SHADER:
+        {
+            symbolTable.insert(COMMON_BUILTINS,
+                               new TVariable(NewPoolTString("gl_FragCoord"),
+                                             TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
+            symbolTable.insert(COMMON_BUILTINS,
+                               new TVariable(NewPoolTString("gl_FrontFacing"),
+                                             TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
+            symbolTable.insert(COMMON_BUILTINS,
+                               new TVariable(NewPoolTString("gl_PointCoord"),
+                                             TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
+
+            symbolTable.insert(ESSL1_BUILTINS,
+                               new TVariable(NewPoolTString("gl_FragColor"),
+                                             TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
+            TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true);
+            fragData.setArraySize(resources.MaxDrawBuffers);
+            symbolTable.insert(ESSL1_BUILTINS,
+                               new TVariable(NewPoolTString("gl_FragData"), fragData));
+
+            if (resources.EXT_blend_func_extended)
+            {
+                symbolTable.insert(
+                    ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
+                    new TVariable(NewPoolTString("gl_SecondaryFragColorEXT"),
+                                  TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4)));
+                TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1, true);
+                secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers);
+                symbolTable.insert(
+                    ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
+                    new TVariable(NewPoolTString("gl_SecondaryFragDataEXT"), secondaryFragData));
+            }
+
+            if (resources.EXT_frag_depth)
+            {
+                symbolTable.insert(
+                    ESSL1_BUILTINS, "GL_EXT_frag_depth",
+                    new TVariable(
+                        NewPoolTString("gl_FragDepthEXT"),
+                        TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
+                              EvqFragDepthEXT, 1)));
+            }
+
+            symbolTable.insert(ESSL3_BUILTINS,
+                               new TVariable(NewPoolTString("gl_FragDepth"),
+                                             TType(EbtFloat, EbpHigh, EvqFragDepth, 1)));
+
+            if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
+            {
+                TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true);
+                lastFragData.setArraySize(resources.MaxDrawBuffers);
+
+                if (resources.EXT_shader_framebuffer_fetch)
+                {
+                    symbolTable.insert(
+                        ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch",
+                        new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
+                }
+                else if (resources.NV_shader_framebuffer_fetch)
+                {
+                    symbolTable.insert(
+                        ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
+                        new TVariable(NewPoolTString("gl_LastFragColor"),
+                                      TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
+                    symbolTable.insert(
+                        ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
+                        new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
+                }
+            }
+            else if (resources.ARM_shader_framebuffer_fetch)
+            {
+                symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch",
+                                   new TVariable(NewPoolTString("gl_LastFragColorARM"),
+                                                 TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
+            }
+        }
+
+        break;
+
+        case GL_VERTEX_SHADER:
+            symbolTable.insert(COMMON_BUILTINS,
+                               new TVariable(NewPoolTString("gl_Position"),
+                                             TType(EbtFloat, EbpHigh, EvqPosition, 4)));
+            symbolTable.insert(COMMON_BUILTINS,
+                               new TVariable(NewPoolTString("gl_PointSize"),
+                                             TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
+            symbolTable.insert(ESSL3_BUILTINS,
+                               new TVariable(NewPoolTString("gl_InstanceID"),
+                                             TType(EbtInt, EbpHigh, EvqInstanceID, 1)));
+            symbolTable.insert(ESSL3_BUILTINS,
+                               new TVariable(NewPoolTString("gl_VertexID"),
+                                             TType(EbtInt, EbpHigh, EvqVertexID, 1)));
+            break;
+        case GL_COMPUTE_SHADER:
+        {
+            symbolTable.insert(ESSL3_1_BUILTINS,
+                               new TVariable(NewPoolTString("gl_NumWorkGroups"),
+                                             TType(EbtUInt, EbpUndefined, EvqNumWorkGroups, 3)));
+            symbolTable.insert(ESSL3_1_BUILTINS,
+                               new TVariable(NewPoolTString("gl_WorkGroupSize"),
+                                             TType(EbtUInt, EbpUndefined, EvqWorkGroupSize, 3)));
+            symbolTable.insert(ESSL3_1_BUILTINS,
+                               new TVariable(NewPoolTString("gl_WorkGroupID"),
+                                             TType(EbtUInt, EbpUndefined, EvqWorkGroupID, 3)));
+            symbolTable.insert(
+                ESSL3_1_BUILTINS,
+                new TVariable(NewPoolTString("gl_LocalInvocationID"),
+                              TType(EbtUInt, EbpUndefined, EvqLocalInvocationID, 3)));
+            symbolTable.insert(
+                ESSL3_1_BUILTINS,
+                new TVariable(NewPoolTString("gl_GlobalInvocationID"),
+                              TType(EbtUInt, EbpUndefined, EvqGlobalInvocationID, 3)));
+            symbolTable.insert(
+                ESSL3_1_BUILTINS,
+                new TVariable(NewPoolTString("gl_LocalInvocationIndex"),
+                              TType(EbtUInt, EbpUndefined, EvqLocalInvocationIndex, 1)));
+        }
+        break;
+
+        default:
+            assert(false && "Language not supported");
+    }
+}
+
+void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavior &extBehavior)
+{
+    if (resources.OES_standard_derivatives)
+        extBehavior["GL_OES_standard_derivatives"] = EBhUndefined;
+    if (resources.OES_EGL_image_external)
+        extBehavior["GL_OES_EGL_image_external"] = EBhUndefined;
+    if (resources.OES_EGL_image_external_essl3)
+        extBehavior["GL_OES_EGL_image_external_essl3"] = EBhUndefined;
+    if (resources.NV_EGL_stream_consumer_external)
+        extBehavior["GL_NV_EGL_stream_consumer_external"] = EBhUndefined;
+    if (resources.ARB_texture_rectangle)
+        extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
+    if (resources.EXT_blend_func_extended)
+        extBehavior["GL_EXT_blend_func_extended"] = EBhUndefined;
+    if (resources.EXT_draw_buffers)
+        extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
+    if (resources.EXT_frag_depth)
+        extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
+    if (resources.EXT_shader_texture_lod)
+        extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined;
+    if (resources.EXT_shader_framebuffer_fetch)
+        extBehavior["GL_EXT_shader_framebuffer_fetch"] = EBhUndefined;
+    if (resources.NV_shader_framebuffer_fetch)
+        extBehavior["GL_NV_shader_framebuffer_fetch"] = EBhUndefined;
+    if (resources.ARM_shader_framebuffer_fetch)
+        extBehavior["GL_ARM_shader_framebuffer_fetch"] = EBhUndefined;
+    if (resources.OVR_multiview)
+    {
+        extBehavior["GL_OVR_multiview"]  = EBhUndefined;
+        extBehavior["GL_OVR_multiview2"] = EBhUndefined;
+    }
+    if (resources.EXT_YUV_target)
+    {
+        extBehavior["GL_EXT_YUV_target"] = EBhUndefined;
+    }
+}
+
+void ResetExtensionBehavior(TExtensionBehavior &extBehavior)
+{
+    for (auto ext_iter = extBehavior.begin(); ext_iter != extBehavior.end(); ++ext_iter)
+    {
+        ext_iter->second = EBhUndefined;
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/Initialize.h b/src/third_party/angle/src/compiler/translator/Initialize.h
new file mode 100644
index 0000000..2e61218
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Initialize.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_INITIALIZE_H_
+#define COMPILER_TRANSLATOR_INITIALIZE_H_
+
+#include "compiler/translator/Common.h"
+#include "compiler/translator/Compiler.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+void InsertBuiltInFunctions(sh::GLenum type,
+                            ShShaderSpec spec,
+                            const ShBuiltInResources &resources,
+                            TSymbolTable &table);
+
+void IdentifyBuiltIns(sh::GLenum type,
+                      ShShaderSpec spec,
+                      const ShBuiltInResources &resources,
+                      TSymbolTable &symbolTable);
+
+void InitExtensionBehavior(const ShBuiltInResources &resources,
+                           TExtensionBehavior &extensionBehavior);
+
+// Resets the behavior of the extensions listed in |extensionBehavior| to the
+// undefined state. These extensions will only be those initially supported in
+// the ShBuiltInResources object for this compiler instance. All other
+// extensions will remain unsupported.
+void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_INITIALIZE_H_
diff --git a/src/third_party/angle/src/compiler/translator/InitializeDll.cpp b/src/third_party/angle/src/compiler/translator/InitializeDll.cpp
new file mode 100644
index 0000000..43c215f
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/InitializeDll.cpp
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/Cache.h"
+#include "compiler/translator/InitializeDll.h"
+#include "compiler/translator/InitializeGlobals.h"
+
+#include "common/platform.h"
+
+#include <assert.h>
+
+namespace sh
+{
+
+bool InitProcess()
+{
+    if (!InitializePoolIndex())
+    {
+        assert(0 && "InitProcess(): Failed to initalize global pool");
+        return false;
+    }
+
+    TCache::initialize();
+
+    return true;
+}
+
+void DetachProcess()
+{
+    FreePoolIndex();
+    TCache::destroy();
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/InitializeDll.h b/src/third_party/angle/src/compiler/translator/InitializeDll.h
new file mode 100644
index 0000000..87f7251
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/InitializeDll.h
@@ -0,0 +1,15 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_
+#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_
+
+namespace sh
+{
+bool InitProcess();
+void DetachProcess();
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_INITIALIZEDLL_H_
diff --git a/src/third_party/angle/src/compiler/translator/InitializeGlobals.h b/src/third_party/angle/src/compiler/translator/InitializeGlobals.h
new file mode 100644
index 0000000..9a67ed0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/InitializeGlobals.h
@@ -0,0 +1,13 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
+#define COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
+
+bool InitializePoolIndex();
+void FreePoolIndex();
+
+#endif  // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
diff --git a/src/third_party/angle/src/compiler/translator/InitializeVariables.cpp b/src/third_party/angle/src/compiler/translator/InitializeVariables.cpp
new file mode 100644
index 0000000..0c9a959
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/InitializeVariables.cpp
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InitializeVariables.h"
+
+#include "angle_gl.h"
+#include "common/debug.h"
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void InsertInitCode(TIntermSequence *sequence,
+                    const InitVariableList &variables,
+                    const TSymbolTable &symbolTable)
+{
+    for (const auto &var : variables)
+    {
+        TString name = TString(var.name.c_str());
+
+        if (var.isArray())
+        {
+            // Assign the array elements one by one to keep the AST compatible with ESSL 1.00 which
+            // doesn't have array assignment.
+            size_t pos = name.find_last_of('[');
+            if (pos != TString::npos)
+            {
+                name = name.substr(0, pos);
+            }
+            TType elementType = sh::GetShaderVariableBasicType(var);
+            TType arrayType   = elementType;
+            arrayType.setArraySize(var.elementCount());
+
+            // Workaround for http://crbug.com/709317
+            //   This loop is reversed to initialize elements in increasing
+            // order [0 1 2 ...]. Otherwise, they're initialized in
+            // decreasing order [... 2 1 0], due to
+            // `sequence->insert(sequence->begin(), ...)` below.
+            for (unsigned int i = var.arraySize; i > 0; --i)
+            {
+                unsigned int index = i - 1;
+                TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, arrayType);
+                TIntermBinary *element     = new TIntermBinary(EOpIndexDirect, arraySymbol,
+                                                           TIntermTyped::CreateIndexNode(index));
+
+                TIntermTyped *zero        = TIntermTyped::CreateZero(elementType);
+                TIntermBinary *assignment = new TIntermBinary(EOpAssign, element, zero);
+
+                sequence->insert(sequence->begin(), assignment);
+            }
+        }
+        else if (var.isStruct())
+        {
+            TVariable *structInfo = reinterpret_cast<TVariable *>(symbolTable.findGlobal(name));
+            ASSERT(structInfo);
+
+            TIntermSymbol *symbol = new TIntermSymbol(0, name, structInfo->getType());
+            TIntermTyped *zero    = TIntermTyped::CreateZero(structInfo->getType());
+
+            TIntermBinary *assign = new TIntermBinary(EOpAssign, symbol, zero);
+            sequence->insert(sequence->begin(), assign);
+        }
+        else
+        {
+            TType type            = sh::GetShaderVariableBasicType(var);
+            TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
+            TIntermTyped *zero    = TIntermTyped::CreateZero(type);
+
+            TIntermBinary *assign = new TIntermBinary(EOpAssign, symbol, zero);
+            sequence->insert(sequence->begin(), assign);
+        }
+    }
+}
+
+}  // namespace anonymous
+
+void InitializeVariables(TIntermBlock *root,
+                         const InitVariableList &vars,
+                         const TSymbolTable &symbolTable)
+{
+    TIntermFunctionDefinition *main = FindMain(root);
+    ASSERT(main != nullptr);
+    TIntermBlock *body = main->getBody();
+    InsertInitCode(body->getSequence(), vars, symbolTable);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/InitializeVariables.h b/src/third_party/angle/src/compiler/translator/InitializeVariables.h
new file mode 100644
index 0000000..5b54689
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/InitializeVariables.h
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
+#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
+
+#include <GLSLANG/ShaderLang.h>
+
+namespace sh
+{
+class TIntermBlock;
+class TSymbolTable;
+
+typedef std::vector<sh::ShaderVariable> InitVariableList;
+
+// Currently this function is only capable of initializing variables of basic types,
+// array of basic types, or struct of basic types.
+// For now it is used for the following two scenarios:
+//   1. initializing gl_Position;
+//   2. initializing ESSL 3.00 shaders' output variables (which might be structs).
+// Specifically, it's not feasible to make it work for local variables because if their
+// types are structs, we can't look into TSymbolTable to find the TType data.
+void InitializeVariables(TIntermBlock *root,
+                         const InitVariableList &vars,
+                         const TSymbolTable &symbolTable);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
diff --git a/src/third_party/angle/src/compiler/translator/IntermNode.cpp b/src/third_party/angle/src/compiler/translator/IntermNode.cpp
new file mode 100644
index 0000000..159958c
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/IntermNode.cpp
@@ -0,0 +1,3419 @@
+//
+// 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.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <algorithm>
+#include <vector>
+
+#include "common/mathutil.h"
+#include "common/matrix_utils.h"
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/HashNames.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+const float kPi                         = 3.14159265358979323846f;
+const float kDegreesToRadiansMultiplier = kPi / 180.0f;
+const float kRadiansToDegreesMultiplier = 180.0f / kPi;
+
+TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
+{
+    return left > right ? left : right;
+}
+
+TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
+{
+    TConstantUnion *constUnion = new TConstantUnion[size];
+    for (unsigned int i = 0; i < size; ++i)
+        constUnion[i]   = constant;
+
+    return constUnion;
+}
+
+void UndefinedConstantFoldingError(const TSourceLoc &loc,
+                                   TOperator op,
+                                   TBasicType basicType,
+                                   TDiagnostics *diagnostics,
+                                   TConstantUnion *result)
+{
+    diagnostics->warning(loc, "operation result is undefined for the values passed in",
+                         GetOperatorString(op));
+
+    switch (basicType)
+    {
+        case EbtFloat:
+            result->setFConst(0.0f);
+            break;
+        case EbtInt:
+            result->setIConst(0);
+            break;
+        case EbtUInt:
+            result->setUConst(0u);
+            break;
+        case EbtBool:
+            result->setBConst(false);
+            break;
+        default:
+            break;
+    }
+}
+
+float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize)
+{
+    float result = 0.0f;
+    for (size_t i = 0; i < paramArraySize; i++)
+    {
+        float f = paramArray[i].getFConst();
+        result += f * f;
+    }
+    return sqrtf(result);
+}
+
+float VectorDotProduct(const TConstantUnion *paramArray1,
+                       const TConstantUnion *paramArray2,
+                       size_t paramArraySize)
+{
+    float result = 0.0f;
+    for (size_t i = 0; i < paramArraySize; i++)
+        result += paramArray1[i].getFConst() * paramArray2[i].getFConst();
+    return result;
+}
+
+TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray,
+                               const TIntermTyped *originalNode,
+                               TQualifier qualifier)
+{
+    if (constArray == nullptr)
+    {
+        return nullptr;
+    }
+    TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType());
+    folded->getTypePointer()->setQualifier(qualifier);
+    folded->setLine(originalNode->getLine());
+    return folded;
+}
+
+angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray,
+                               const unsigned int &rows,
+                               const unsigned int &cols)
+{
+    std::vector<float> elements;
+    for (size_t i = 0; i < rows * cols; i++)
+        elements.push_back(paramArray[i].getFConst());
+    // Transpose is used since the Matrix constructor expects arguments in row-major order,
+    // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below
+    // so that the created matrix will have the expected dimensions after the transpose.
+    return angle::Matrix<float>(elements, cols, rows).transpose();
+}
+
+angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int &size)
+{
+    std::vector<float> elements;
+    for (size_t i = 0; i < size * size; i++)
+        elements.push_back(paramArray[i].getFConst());
+    // Transpose is used since the Matrix constructor expects arguments in row-major order,
+    // whereas the paramArray is in column-major order.
+    return angle::Matrix<float>(elements, size).transpose();
+}
+
+void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resultArray)
+{
+    // Transpose is used since the input Matrix is in row-major order,
+    // whereas the actual result should be in column-major order.
+    angle::Matrix<float> result       = m.transpose();
+    std::vector<float> resultElements = result.elements();
+    for (size_t i = 0; i < resultElements.size(); i++)
+        resultArray[i].setFConst(resultElements[i]);
+}
+
+}  // namespace anonymous
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+void TIntermTyped::setTypePreservePrecision(const TType &t)
+{
+    TPrecision precision = getPrecision();
+    mType                = t;
+    ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
+    mType.setPrecision(precision);
+}
+
+#define REPLACE_IF_IS(node, type, original, replacement) \
+    if (node == original)                                \
+    {                                                    \
+        node = static_cast<type *>(replacement);         \
+        return true;                                     \
+    }
+
+bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    ASSERT(original != nullptr);  // This risks replacing multiple children.
+    REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
+    REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
+    return false;
+}
+
+bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
+    return false;
+}
+
+bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
+    REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
+    return false;
+}
+
+bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
+    return false;
+}
+
+bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
+    REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
+    return false;
+}
+
+bool TIntermInvariantDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement);
+    return false;
+}
+
+bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement);
+    REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
+    return false;
+}
+
+bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    return replaceChildNodeInternal(original, replacement);
+}
+
+bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    return replaceChildNodeInternal(original, replacement);
+}
+
+bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    return replaceChildNodeInternal(original, replacement);
+}
+
+bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    return replaceChildNodeInternal(original, replacement);
+}
+
+bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
+{
+    for (size_t ii = 0; ii < getSequence()->size(); ++ii)
+    {
+        REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement);
+    }
+    return false;
+}
+
+bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original,
+                                                        const TIntermSequence &replacements)
+{
+    for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it)
+    {
+        if (*it == original)
+        {
+            it = getSequence()->erase(it);
+            getSequence()->insert(it, replacements.begin(), replacements.end());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position,
+                                            const TIntermSequence &insertions)
+{
+    if (position > getSequence()->size())
+    {
+        return false;
+    }
+    auto it = getSequence()->begin() + position;
+    getSequence()->insert(it, insertions.begin(), insertions.end());
+    return true;
+}
+
+TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func,
+                                                       TIntermSequence *arguments)
+{
+    TIntermAggregate *callNode =
+        new TIntermAggregate(func.getReturnType(), EOpCallFunctionInAST, arguments);
+    callNode->getFunctionSymbolInfo()->setFromFunction(func);
+    return callNode;
+}
+
+TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TType &type,
+                                                       const TSymbolUniqueId &id,
+                                                       const TName &name,
+                                                       TIntermSequence *arguments)
+{
+    TIntermAggregate *callNode = new TIntermAggregate(type, EOpCallFunctionInAST, arguments);
+    callNode->getFunctionSymbolInfo()->setId(id);
+    callNode->getFunctionSymbolInfo()->setNameObj(name);
+    return callNode;
+}
+
+TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func,
+                                                              TIntermSequence *arguments)
+{
+    TIntermAggregate *callNode =
+        new TIntermAggregate(func.getReturnType(), EOpCallBuiltInFunction, arguments);
+    callNode->getFunctionSymbolInfo()->setFromFunction(func);
+    // Note that name needs to be set before texture function type is determined.
+    callNode->setBuiltInFunctionPrecision();
+    return callNode;
+}
+
+TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type,
+                                                      TIntermSequence *arguments)
+{
+    return new TIntermAggregate(type, EOpConstruct, arguments);
+}
+
+TIntermAggregate *TIntermAggregate::Create(const TType &type,
+                                           TOperator op,
+                                           TIntermSequence *arguments)
+{
+    TIntermAggregate *node = new TIntermAggregate(type, op, arguments);
+    ASSERT(op != EOpCallFunctionInAST);    // Should use CreateFunctionCall
+    ASSERT(op != EOpCallBuiltInFunction);  // Should use CreateBuiltInFunctionCall
+    ASSERT(!node->isConstructor());        // Should use CreateConstructor
+    return node;
+}
+
+TIntermAggregate::TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments)
+    : TIntermOperator(op), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false)
+{
+    if (arguments != nullptr)
+    {
+        mArguments.swap(*arguments);
+    }
+    setTypePrecisionAndQualifier(type);
+}
+
+void TIntermAggregate::setTypePrecisionAndQualifier(const TType &type)
+{
+    setType(type);
+    mType.setQualifier(EvqTemporary);
+    if (!isFunctionCall())
+    {
+        if (isConstructor())
+        {
+            // Structs should not be precision qualified, the individual members may be.
+            // Built-in types on the other hand should be precision qualified.
+            if (getBasicType() != EbtStruct)
+            {
+                setPrecisionFromChildren();
+            }
+        }
+        else
+        {
+            setPrecisionForBuiltInOp();
+        }
+        if (areChildrenConstQualified())
+        {
+            mType.setQualifier(EvqConst);
+        }
+    }
+}
+
+bool TIntermAggregate::areChildrenConstQualified()
+{
+    for (TIntermNode *&arg : mArguments)
+    {
+        TIntermTyped *typedArg = arg->getAsTyped();
+        if (typedArg && typedArg->getQualifier() != EvqConst)
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+void TIntermAggregate::setPrecisionFromChildren()
+{
+    mGotPrecisionFromChildren = true;
+    if (getBasicType() == EbtBool)
+    {
+        mType.setPrecision(EbpUndefined);
+        return;
+    }
+
+    TPrecision precision                = EbpUndefined;
+    TIntermSequence::iterator childIter = mArguments.begin();
+    while (childIter != mArguments.end())
+    {
+        TIntermTyped *typed = (*childIter)->getAsTyped();
+        if (typed)
+            precision = GetHigherPrecision(typed->getPrecision(), precision);
+        ++childIter;
+    }
+    mType.setPrecision(precision);
+}
+
+void TIntermAggregate::setPrecisionForBuiltInOp()
+{
+    ASSERT(!isConstructor());
+    ASSERT(!isFunctionCall());
+    if (!setPrecisionForSpecialBuiltInOp())
+    {
+        setPrecisionFromChildren();
+    }
+}
+
+bool TIntermAggregate::setPrecisionForSpecialBuiltInOp()
+{
+    switch (mOp)
+    {
+        case EOpBitfieldExtract:
+            mType.setPrecision(mArguments[0]->getAsTyped()->getPrecision());
+            mGotPrecisionFromChildren = true;
+            return true;
+        case EOpBitfieldInsert:
+            mType.setPrecision(GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(),
+                                                  mArguments[1]->getAsTyped()->getPrecision()));
+            mGotPrecisionFromChildren = true;
+            return true;
+        case EOpUaddCarry:
+        case EOpUsubBorrow:
+            mType.setPrecision(EbpHigh);
+            return true;
+        default:
+            return false;
+    }
+}
+
+void TIntermAggregate::setBuiltInFunctionPrecision()
+{
+    // All built-ins returning bool should be handled as ops, not functions.
+    ASSERT(getBasicType() != EbtBool);
+    ASSERT(mOp == EOpCallBuiltInFunction);
+
+    TPrecision precision = EbpUndefined;
+    for (TIntermNode *arg : mArguments)
+    {
+        TIntermTyped *typed = arg->getAsTyped();
+        // ESSL spec section 8: texture functions get their precision from the sampler.
+        if (typed && IsSampler(typed->getBasicType()))
+        {
+            precision = typed->getPrecision();
+            break;
+        }
+    }
+    // ESSL 3.0 spec section 8: textureSize always gets highp precision.
+    // All other functions that take a sampler are assumed to be texture functions.
+    if (mFunctionInfo.getName().find("textureSize") == 0)
+        mType.setPrecision(EbpHigh);
+    else
+        mType.setPrecision(precision);
+}
+
+TString TIntermAggregate::getSymbolTableMangledName() const
+{
+    ASSERT(!isConstructor());
+    switch (mOp)
+    {
+        case EOpCallInternalRawFunction:
+        case EOpCallBuiltInFunction:
+        case EOpCallFunctionInAST:
+            return TFunction::GetMangledNameFromCall(mFunctionInfo.getName(), mArguments);
+        default:
+            TString opString = GetOperatorString(mOp);
+            return TFunction::GetMangledNameFromCall(opString, mArguments);
+    }
+}
+
+void TIntermBlock::appendStatement(TIntermNode *statement)
+{
+    // Declaration nodes with no children can appear if all the declarators just added constants to
+    // the symbol table instead of generating code. They're no-ops so they aren't added to blocks.
+    if (statement != nullptr && (statement->getAsDeclarationNode() == nullptr ||
+                                 !statement->getAsDeclarationNode()->getSequence()->empty()))
+    {
+        mStatements.push_back(statement);
+    }
+}
+
+void TIntermFunctionPrototype::appendParameter(TIntermSymbol *parameter)
+{
+    ASSERT(parameter != nullptr);
+    mParameters.push_back(parameter);
+}
+
+void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
+{
+    ASSERT(declarator != nullptr);
+    ASSERT(declarator->getAsSymbolNode() != nullptr ||
+           (declarator->getAsBinaryNode() != nullptr &&
+            declarator->getAsBinaryNode()->getOp() == EOpInitialize));
+    ASSERT(mDeclarators.empty() ||
+           declarator->getType().sameElementType(mDeclarators.back()->getAsTyped()->getType()));
+    mDeclarators.push_back(declarator);
+}
+
+bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement);
+    return false;
+}
+
+bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement);
+    REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement);
+    return false;
+}
+
+bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement);
+    return false;
+}
+
+bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
+    return false;
+}
+
+TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node.mType)
+{
+    // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that
+    // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy.
+    // We need to manually copy any fields of TIntermNode besides handling fields in TIntermTyped.
+    mLine = node.mLine;
+}
+
+bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters()
+{
+    TIntermAggregate *constructor = getAsAggregate();
+    if (!constructor || !constructor->isConstructor())
+    {
+        return false;
+    }
+    for (TIntermNode *&node : *constructor->getSequence())
+    {
+        if (!node->getAsConstantUnion())
+            return false;
+    }
+    return true;
+}
+
+// static
+TIntermTyped *TIntermTyped::CreateIndexNode(int index)
+{
+    TConstantUnion *u = new TConstantUnion[1];
+    u[0].setIConst(index);
+
+    TType type(EbtInt, EbpUndefined, EvqConst, 1);
+    TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
+    return node;
+}
+
+// static
+TIntermTyped *TIntermTyped::CreateZero(const TType &type)
+{
+    TType constType(type);
+    constType.setQualifier(EvqConst);
+
+    if (!type.isArray() && type.getBasicType() != EbtStruct)
+    {
+        size_t size       = constType.getObjectSize();
+        TConstantUnion *u = new TConstantUnion[size];
+        for (size_t i = 0; i < size; ++i)
+        {
+            switch (type.getBasicType())
+            {
+                case EbtFloat:
+                    u[i].setFConst(0.0f);
+                    break;
+                case EbtInt:
+                    u[i].setIConst(0);
+                    break;
+                case EbtUInt:
+                    u[i].setUConst(0u);
+                    break;
+                case EbtBool:
+                    u[i].setBConst(false);
+                    break;
+                default:
+                    // CreateZero is called by ParseContext that keeps parsing even when an error
+                    // occurs, so it is possible for CreateZero to be called with non-basic types.
+                    // This happens only on error condition but CreateZero needs to return a value
+                    // with the correct type to continue the typecheck. That's why we handle
+                    // non-basic type by setting whatever value, we just need the type to be right.
+                    u[i].setIConst(42);
+                    break;
+            }
+        }
+
+        TIntermConstantUnion *node = new TIntermConstantUnion(u, constType);
+        return node;
+    }
+
+    if (type.getBasicType() == EbtVoid)
+    {
+        // Void array. This happens only on error condition, similarly to the case above. We don't
+        // have a constructor operator for void, so this needs special handling. We'll end up with a
+        // value without the array type, but that should not be a problem.
+        constType.clearArrayness();
+        return CreateZero(constType);
+    }
+
+    TIntermSequence *arguments = new TIntermSequence();
+
+    if (type.isArray())
+    {
+        TType elementType(type);
+        elementType.clearArrayness();
+
+        size_t arraySize = type.getArraySize();
+        for (size_t i = 0; i < arraySize; ++i)
+        {
+            arguments->push_back(CreateZero(elementType));
+        }
+    }
+    else
+    {
+        ASSERT(type.getBasicType() == EbtStruct);
+
+        TStructure *structure = type.getStruct();
+        for (const auto &field : structure->fields())
+        {
+            arguments->push_back(CreateZero(*field->type()));
+        }
+    }
+
+    return TIntermAggregate::CreateConstructor(constType, arguments);
+}
+
+// static
+TIntermTyped *TIntermTyped::CreateBool(bool value)
+{
+    TConstantUnion *u = new TConstantUnion[1];
+    u[0].setBConst(value);
+
+    TType type(EbtBool, EbpUndefined, EvqConst, 1);
+    TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
+    return node;
+}
+
+TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node)
+{
+    mUnionArrayPointer = node.mUnionArrayPointer;
+}
+
+void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
+{
+    setName(function.getName());
+    setId(TSymbolUniqueId(function));
+}
+
+TFunctionSymbolInfo::TFunctionSymbolInfo(const TSymbolUniqueId &id) : mId(new TSymbolUniqueId(id))
+{
+}
+
+TFunctionSymbolInfo::TFunctionSymbolInfo(const TFunctionSymbolInfo &info)
+    : mName(info.mName), mId(nullptr)
+{
+    if (info.mId)
+    {
+        mId = new TSymbolUniqueId(*info.mId);
+    }
+}
+
+TFunctionSymbolInfo &TFunctionSymbolInfo::operator=(const TFunctionSymbolInfo &info)
+{
+    mName = info.mName;
+    if (info.mId)
+    {
+        mId = new TSymbolUniqueId(*info.mId);
+    }
+    else
+    {
+        mId = nullptr;
+    }
+    return *this;
+}
+
+void TFunctionSymbolInfo::setId(const TSymbolUniqueId &id)
+{
+    mId = new TSymbolUniqueId(id);
+}
+
+const TSymbolUniqueId &TFunctionSymbolInfo::getId() const
+{
+    ASSERT(mId);
+    return *mId;
+}
+
+TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
+    : TIntermOperator(node),
+      mUseEmulatedFunction(node.mUseEmulatedFunction),
+      mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
+      mFunctionInfo(node.mFunctionInfo)
+{
+    for (TIntermNode *arg : node.mArguments)
+    {
+        TIntermTyped *typedArg = arg->getAsTyped();
+        ASSERT(typedArg != nullptr);
+        TIntermTyped *argCopy = typedArg->deepCopy();
+        mArguments.push_back(argCopy);
+    }
+}
+
+TIntermAggregate *TIntermAggregate::shallowCopy() const
+{
+    TIntermSequence *copySeq = new TIntermSequence();
+    copySeq->insert(copySeq->begin(), getSequence()->begin(), getSequence()->end());
+    TIntermAggregate *copyNode         = new TIntermAggregate(mType, mOp, copySeq);
+    *copyNode->getFunctionSymbolInfo() = mFunctionInfo;
+    copyNode->setLine(mLine);
+    return copyNode;
+}
+
+TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node)
+{
+    TIntermTyped *operandCopy = node.mOperand->deepCopy();
+    ASSERT(operandCopy != nullptr);
+    mOperand = operandCopy;
+    mSwizzleOffsets = node.mSwizzleOffsets;
+}
+
+TIntermBinary::TIntermBinary(const TIntermBinary &node)
+    : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
+{
+    TIntermTyped *leftCopy  = node.mLeft->deepCopy();
+    TIntermTyped *rightCopy = node.mRight->deepCopy();
+    ASSERT(leftCopy != nullptr && rightCopy != nullptr);
+    mLeft  = leftCopy;
+    mRight = rightCopy;
+}
+
+TIntermUnary::TIntermUnary(const TIntermUnary &node)
+    : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
+{
+    TIntermTyped *operandCopy = node.mOperand->deepCopy();
+    ASSERT(operandCopy != nullptr);
+    mOperand = operandCopy;
+}
+
+TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node)
+{
+    TIntermTyped *conditionCopy = node.mCondition->deepCopy();
+    TIntermTyped *trueCopy      = node.mTrueExpression->deepCopy();
+    TIntermTyped *falseCopy     = node.mFalseExpression->deepCopy();
+    ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr);
+    mCondition       = conditionCopy;
+    mTrueExpression  = trueCopy;
+    mFalseExpression = falseCopy;
+}
+
+bool TIntermOperator::isAssignment() const
+{
+    return IsAssignment(mOp);
+}
+
+bool TIntermOperator::isMultiplication() const
+{
+    switch (mOp)
+    {
+        case EOpMul:
+        case EOpMatrixTimesMatrix:
+        case EOpMatrixTimesVector:
+        case EOpMatrixTimesScalar:
+        case EOpVectorTimesMatrix:
+        case EOpVectorTimesScalar:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool TIntermOperator::isConstructor() const
+{
+    return (mOp == EOpConstruct);
+}
+
+bool TIntermOperator::isFunctionCall() const
+{
+    switch (mOp)
+    {
+        case EOpCallFunctionInAST:
+        case EOpCallBuiltInFunction:
+        case EOpCallInternalRawFunction:
+            return true;
+        default:
+            return false;
+    }
+}
+
+TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right)
+{
+    if (left.isMatrix())
+    {
+        if (right.isMatrix())
+        {
+            return EOpMatrixTimesMatrix;
+        }
+        else
+        {
+            if (right.isVector())
+            {
+                return EOpMatrixTimesVector;
+            }
+            else
+            {
+                return EOpMatrixTimesScalar;
+            }
+        }
+    }
+    else
+    {
+        if (right.isMatrix())
+        {
+            if (left.isVector())
+            {
+                return EOpVectorTimesMatrix;
+            }
+            else
+            {
+                return EOpMatrixTimesScalar;
+            }
+        }
+        else
+        {
+            // Neither operand is a matrix.
+            if (left.isVector() == right.isVector())
+            {
+                // Leave as component product.
+                return EOpMul;
+            }
+            else
+            {
+                return EOpVectorTimesScalar;
+            }
+        }
+    }
+}
+
+TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right)
+{
+    if (left.isMatrix())
+    {
+        if (right.isMatrix())
+        {
+            return EOpMatrixTimesMatrixAssign;
+        }
+        else
+        {
+            // right should be scalar, but this may not be validated yet.
+            return EOpMatrixTimesScalarAssign;
+        }
+    }
+    else
+    {
+        if (right.isMatrix())
+        {
+            // Left should be a vector, but this may not be validated yet.
+            return EOpVectorTimesMatrixAssign;
+        }
+        else
+        {
+            // Neither operand is a matrix.
+            if (left.isVector() == right.isVector())
+            {
+                // Leave as component product.
+                return EOpMulAssign;
+            }
+            else
+            {
+                // left should be vector and right should be scalar, but this may not be validated
+                // yet.
+                return EOpVectorTimesScalarAssign;
+            }
+        }
+    }
+}
+
+//
+// Make sure the type of a unary operator is appropriate for its
+// combination of operation and operand type.
+//
+void TIntermUnary::promote()
+{
+    TQualifier resultQualifier = EvqTemporary;
+    if (mOperand->getQualifier() == EvqConst)
+        resultQualifier = EvqConst;
+
+    unsigned char operandPrimarySize =
+        static_cast<unsigned char>(mOperand->getType().getNominalSize());
+    switch (mOp)
+    {
+        case EOpFloatBitsToInt:
+            setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize));
+            break;
+        case EOpFloatBitsToUint:
+            setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize));
+            break;
+        case EOpIntBitsToFloat:
+        case EOpUintBitsToFloat:
+            setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize));
+            break;
+        case EOpPackSnorm2x16:
+        case EOpPackUnorm2x16:
+        case EOpPackHalf2x16:
+        case EOpPackUnorm4x8:
+        case EOpPackSnorm4x8:
+            setType(TType(EbtUInt, EbpHigh, resultQualifier));
+            break;
+        case EOpUnpackSnorm2x16:
+        case EOpUnpackUnorm2x16:
+            setType(TType(EbtFloat, EbpHigh, resultQualifier, 2));
+            break;
+        case EOpUnpackHalf2x16:
+            setType(TType(EbtFloat, EbpMedium, resultQualifier, 2));
+            break;
+        case EOpUnpackUnorm4x8:
+        case EOpUnpackSnorm4x8:
+            setType(TType(EbtFloat, EbpMedium, resultQualifier, 4));
+            break;
+        case EOpAny:
+        case EOpAll:
+            setType(TType(EbtBool, EbpUndefined, resultQualifier));
+            break;
+        case EOpLength:
+        case EOpDeterminant:
+            setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier));
+            break;
+        case EOpTranspose:
+            setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier,
+                          static_cast<unsigned char>(mOperand->getType().getRows()),
+                          static_cast<unsigned char>(mOperand->getType().getCols())));
+            break;
+        case EOpIsInf:
+        case EOpIsNan:
+            setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize));
+            break;
+        case EOpBitfieldReverse:
+            setType(TType(mOperand->getBasicType(), EbpHigh, resultQualifier, operandPrimarySize));
+            break;
+        case EOpBitCount:
+            setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
+            break;
+        case EOpFindLSB:
+            setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
+            break;
+        case EOpFindMSB:
+            setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
+            break;
+        default:
+            setType(mOperand->getType());
+            mType.setQualifier(resultQualifier);
+            break;
+    }
+}
+
+TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
+    : TIntermTyped(TType(EbtFloat, EbpUndefined)),
+      mOperand(operand),
+      mSwizzleOffsets(swizzleOffsets)
+{
+    ASSERT(mSwizzleOffsets.size() <= 4);
+    promote();
+}
+
+TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
+    : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
+{
+    promote();
+}
+
+TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
+    : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
+{
+    promote();
+}
+
+TIntermInvariantDeclaration::TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line)
+    : TIntermNode(), mSymbol(symbol)
+{
+    ASSERT(symbol);
+    setLine(line);
+}
+
+TIntermTernary::TIntermTernary(TIntermTyped *cond,
+                               TIntermTyped *trueExpression,
+                               TIntermTyped *falseExpression)
+    : TIntermTyped(trueExpression->getType()),
+      mCondition(cond),
+      mTrueExpression(trueExpression),
+      mFalseExpression(falseExpression)
+{
+    getTypePointer()->setQualifier(
+        TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
+}
+
+TIntermLoop::TIntermLoop(TLoopType type,
+                         TIntermNode *init,
+                         TIntermTyped *cond,
+                         TIntermTyped *expr,
+                         TIntermBlock *body)
+    : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body)
+{
+    // Declaration nodes with no children can appear if all the declarators just added constants to
+    // the symbol table instead of generating code. They're no-ops so don't add them to the tree.
+    if (mInit && mInit->getAsDeclarationNode() &&
+        mInit->getAsDeclarationNode()->getSequence()->empty())
+    {
+        mInit = nullptr;
+    }
+}
+
+// static
+TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond,
+                                              TIntermTyped *trueExpression,
+                                              TIntermTyped *falseExpression)
+{
+    if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst &&
+        falseExpression->getQualifier() == EvqConst)
+    {
+        return EvqConst;
+    }
+    return EvqTemporary;
+}
+
+void TIntermSwizzle::promote()
+{
+    TQualifier resultQualifier = EvqTemporary;
+    if (mOperand->getQualifier() == EvqConst)
+        resultQualifier = EvqConst;
+
+    auto numFields = mSwizzleOffsets.size();
+    setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier,
+                  static_cast<unsigned char>(numFields)));
+}
+
+bool TIntermSwizzle::hasDuplicateOffsets() const
+{
+    int offsetCount[4] = {0u, 0u, 0u, 0u};
+    for (const auto offset : mSwizzleOffsets)
+    {
+        offsetCount[offset]++;
+        if (offsetCount[offset] > 1)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool TIntermSwizzle::offsetsMatch(int offset) const
+{
+    return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset;
+}
+
+void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
+{
+    for (const int offset : mSwizzleOffsets)
+    {
+        switch (offset)
+        {
+            case 0:
+                *out << "x";
+                break;
+            case 1:
+                *out << "y";
+                break;
+            case 2:
+                *out << "z";
+                break;
+            case 3:
+                *out << "w";
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+}
+
+TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion,
+                                            const TIntermTyped *left,
+                                            const TIntermTyped *right)
+{
+    // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
+    if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
+        right->getQualifier() != EvqConst)
+    {
+        return EvqTemporary;
+    }
+    return EvqConst;
+}
+
+// Establishes the type of the result of the binary operation.
+void TIntermBinary::promote()
+{
+    ASSERT(!isMultiplication() ||
+           mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
+
+    // Comma is handled as a special case.
+    if (mOp == EOpComma)
+    {
+        setType(mRight->getType());
+        return;
+    }
+
+    // Base assumption:  just make the type the same as the left
+    // operand.  Then only deviations from this need be coded.
+    setType(mLeft->getType());
+
+    TQualifier resultQualifier = EvqConst;
+    // Binary operations results in temporary variables unless both
+    // operands are const.
+    if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
+    {
+        resultQualifier = EvqTemporary;
+        getTypePointer()->setQualifier(EvqTemporary);
+    }
+
+    // Handle indexing ops.
+    switch (mOp)
+    {
+        case EOpIndexDirect:
+        case EOpIndexIndirect:
+            if (mLeft->isArray())
+            {
+                mType.clearArrayness();
+            }
+            else if (mLeft->isMatrix())
+            {
+                setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
+                              static_cast<unsigned char>(mLeft->getRows())));
+            }
+            else if (mLeft->isVector())
+            {
+                setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier));
+            }
+            else
+            {
+                UNREACHABLE();
+            }
+            return;
+        case EOpIndexDirectStruct:
+        {
+            const TFieldList &fields = mLeft->getType().getStruct()->fields();
+            const int i              = mRight->getAsConstantUnion()->getIConst(0);
+            setType(*fields[i]->type());
+            getTypePointer()->setQualifier(resultQualifier);
+            return;
+        }
+        case EOpIndexDirectInterfaceBlock:
+        {
+            const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
+            const int i              = mRight->getAsConstantUnion()->getIConst(0);
+            setType(*fields[i]->type());
+            getTypePointer()->setQualifier(resultQualifier);
+            return;
+        }
+        default:
+            break;
+    }
+
+    ASSERT(mLeft->isArray() == mRight->isArray());
+
+    // The result gets promoted to the highest precision.
+    TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
+    getTypePointer()->setPrecision(higherPrecision);
+
+    const int nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize());
+
+    //
+    // All scalars or structs. Code after this test assumes this case is removed!
+    //
+    if (nominalSize == 1)
+    {
+        switch (mOp)
+        {
+            //
+            // Promote to conditional
+            //
+            case EOpEqual:
+            case EOpNotEqual:
+            case EOpLessThan:
+            case EOpGreaterThan:
+            case EOpLessThanEqual:
+            case EOpGreaterThanEqual:
+                setType(TType(EbtBool, EbpUndefined, resultQualifier));
+                break;
+
+            //
+            // And and Or operate on conditionals
+            //
+            case EOpLogicalAnd:
+            case EOpLogicalXor:
+            case EOpLogicalOr:
+                ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
+                setType(TType(EbtBool, EbpUndefined, resultQualifier));
+                break;
+
+            default:
+                break;
+        }
+        return;
+    }
+
+    // If we reach here, at least one of the operands is vector or matrix.
+    // The other operand could be a scalar, vector, or matrix.
+    TBasicType basicType = mLeft->getBasicType();
+
+    switch (mOp)
+    {
+        case EOpMul:
+            break;
+        case EOpMatrixTimesScalar:
+            if (mRight->isMatrix())
+            {
+                setType(TType(basicType, higherPrecision, resultQualifier,
+                              static_cast<unsigned char>(mRight->getCols()),
+                              static_cast<unsigned char>(mRight->getRows())));
+            }
+            break;
+        case EOpMatrixTimesVector:
+            setType(TType(basicType, higherPrecision, resultQualifier,
+                          static_cast<unsigned char>(mLeft->getRows()), 1));
+            break;
+        case EOpMatrixTimesMatrix:
+            setType(TType(basicType, higherPrecision, resultQualifier,
+                          static_cast<unsigned char>(mRight->getCols()),
+                          static_cast<unsigned char>(mLeft->getRows())));
+            break;
+        case EOpVectorTimesScalar:
+            setType(TType(basicType, higherPrecision, resultQualifier,
+                          static_cast<unsigned char>(nominalSize), 1));
+            break;
+        case EOpVectorTimesMatrix:
+            setType(TType(basicType, higherPrecision, resultQualifier,
+                          static_cast<unsigned char>(mRight->getCols()), 1));
+            break;
+        case EOpMulAssign:
+        case EOpVectorTimesScalarAssign:
+        case EOpVectorTimesMatrixAssign:
+        case EOpMatrixTimesScalarAssign:
+        case EOpMatrixTimesMatrixAssign:
+            ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType()));
+            break;
+        case EOpAssign:
+        case EOpInitialize:
+            ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
+                   (mLeft->getSecondarySize() == mRight->getSecondarySize()));
+            break;
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpIMod:
+        case EOpBitShiftLeft:
+        case EOpBitShiftRight:
+        case EOpBitwiseAnd:
+        case EOpBitwiseXor:
+        case EOpBitwiseOr:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpDivAssign:
+        case EOpIModAssign:
+        case EOpBitShiftLeftAssign:
+        case EOpBitShiftRightAssign:
+        case EOpBitwiseAndAssign:
+        case EOpBitwiseXorAssign:
+        case EOpBitwiseOrAssign:
+        {
+            const int secondarySize =
+                std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
+            setType(TType(basicType, higherPrecision, resultQualifier,
+                          static_cast<unsigned char>(nominalSize),
+                          static_cast<unsigned char>(secondarySize)));
+            ASSERT(!mLeft->isArray() && !mRight->isArray());
+            break;
+        }
+        case EOpEqual:
+        case EOpNotEqual:
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
+                   (mLeft->getSecondarySize() == mRight->getSecondarySize()));
+            setType(TType(EbtBool, EbpUndefined, resultQualifier));
+            break;
+
+        case EOpIndexDirect:
+        case EOpIndexIndirect:
+        case EOpIndexDirectInterfaceBlock:
+        case EOpIndexDirectStruct:
+            // These ops should be already fully handled.
+            UNREACHABLE();
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
+{
+    if (isArray())
+    {
+        ASSERT(index < static_cast<int>(getType().getArraySize()));
+        TType arrayElementType = getType();
+        arrayElementType.clearArrayness();
+        size_t arrayElementSize = arrayElementType.getObjectSize();
+        return &mUnionArrayPointer[arrayElementSize * index];
+    }
+    else if (isMatrix())
+    {
+        ASSERT(index < getType().getCols());
+        int size = getType().getRows();
+        return &mUnionArrayPointer[size * index];
+    }
+    else if (isVector())
+    {
+        ASSERT(index < getType().getNominalSize());
+        return &mUnionArrayPointer[index];
+    }
+    else
+    {
+        UNREACHABLE();
+        return nullptr;
+    }
+}
+
+TIntermTyped *TIntermSwizzle::fold()
+{
+    TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
+    if (operandConstant == nullptr)
+    {
+        return nullptr;
+    }
+
+    TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()];
+    for (size_t i = 0; i < mSwizzleOffsets.size(); ++i)
+    {
+        constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i));
+    }
+    return CreateFoldedNode(constArray, this, mType.getQualifier());
+}
+
+TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
+{
+    TIntermConstantUnion *leftConstant  = mLeft->getAsConstantUnion();
+    TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
+    switch (mOp)
+    {
+        case EOpIndexDirect:
+        {
+            if (leftConstant == nullptr || rightConstant == nullptr)
+            {
+                return nullptr;
+            }
+            int index = rightConstant->getIConst(0);
+
+            const TConstantUnion *constArray = leftConstant->foldIndexing(index);
+            return CreateFoldedNode(constArray, this, mType.getQualifier());
+        }
+        case EOpIndexDirectStruct:
+        {
+            if (leftConstant == nullptr || rightConstant == nullptr)
+            {
+                return nullptr;
+            }
+            const TFieldList &fields = mLeft->getType().getStruct()->fields();
+            size_t index             = static_cast<size_t>(rightConstant->getIConst(0));
+
+            size_t previousFieldsSize = 0;
+            for (size_t i = 0; i < index; ++i)
+            {
+                previousFieldsSize += fields[i]->type()->getObjectSize();
+            }
+
+            const TConstantUnion *constArray = leftConstant->getUnionArrayPointer();
+            return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier());
+        }
+        case EOpIndexIndirect:
+        case EOpIndexDirectInterfaceBlock:
+            // Can never be constant folded.
+            return nullptr;
+        default:
+        {
+            if (leftConstant == nullptr || rightConstant == nullptr)
+            {
+                return nullptr;
+            }
+            TConstantUnion *constArray =
+                leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine());
+
+            // Nodes may be constant folded without being qualified as constant.
+            return CreateFoldedNode(constArray, this, mType.getQualifier());
+        }
+    }
+}
+
+TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
+{
+    TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
+    if (operandConstant == nullptr)
+    {
+        return nullptr;
+    }
+
+    TConstantUnion *constArray = nullptr;
+    switch (mOp)
+    {
+        case EOpAny:
+        case EOpAll:
+        case EOpLength:
+        case EOpTranspose:
+        case EOpDeterminant:
+        case EOpInverse:
+        case EOpPackSnorm2x16:
+        case EOpUnpackSnorm2x16:
+        case EOpPackUnorm2x16:
+        case EOpUnpackUnorm2x16:
+        case EOpPackHalf2x16:
+        case EOpUnpackHalf2x16:
+        case EOpPackUnorm4x8:
+        case EOpPackSnorm4x8:
+        case EOpUnpackUnorm4x8:
+        case EOpUnpackSnorm4x8:
+            constArray = operandConstant->foldUnaryNonComponentWise(mOp);
+            break;
+        default:
+            constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
+            break;
+    }
+
+    // Nodes may be constant folded without being qualified as constant.
+    return CreateFoldedNode(constArray, this, mType.getQualifier());
+}
+
+TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
+{
+    // Make sure that all params are constant before actual constant folding.
+    for (auto *param : *getSequence())
+    {
+        if (param->getAsConstantUnion() == nullptr)
+        {
+            return nullptr;
+        }
+    }
+    TConstantUnion *constArray = nullptr;
+    if (isConstructor())
+        constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
+    else
+        constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
+
+    // Nodes may be constant folded without being qualified as constant.
+    return CreateFoldedNode(constArray, this, getQualifier());
+}
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the constant value to keep using or nullptr.
+//
+TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
+                                                 TIntermConstantUnion *rightNode,
+                                                 TDiagnostics *diagnostics,
+                                                 const TSourceLoc &line)
+{
+    const TConstantUnion *leftArray  = getUnionArrayPointer();
+    const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
+
+    ASSERT(leftArray && rightArray);
+
+    size_t objectSize = getType().getObjectSize();
+
+    // for a case like float f = vec4(2, 3, 4, 5) + 1.2;
+    if (rightNode->getType().getObjectSize() == 1 && objectSize > 1)
+    {
+        rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize);
+    }
+    else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1)
+    {
+        // for a case like float f = 1.2 + vec4(2, 3, 4, 5);
+        leftArray  = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
+        objectSize = rightNode->getType().getObjectSize();
+    }
+
+    TConstantUnion *resultArray = nullptr;
+
+    switch (op)
+    {
+        case EOpAdd:
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; i++)
+                resultArray[i] =
+                    TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line);
+            break;
+        case EOpSub:
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; i++)
+                resultArray[i] =
+                    TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line);
+            break;
+
+        case EOpMul:
+        case EOpVectorTimesScalar:
+        case EOpMatrixTimesScalar:
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; i++)
+                resultArray[i] =
+                    TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line);
+            break;
+
+        case EOpMatrixTimesMatrix:
+        {
+            // TODO(jmadll): This code should check for overflows.
+            ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat);
+
+            const int leftCols   = getCols();
+            const int leftRows   = getRows();
+            const int rightCols  = rightNode->getType().getCols();
+            const int rightRows  = rightNode->getType().getRows();
+            const int resultCols = rightCols;
+            const int resultRows = leftRows;
+
+            resultArray = new TConstantUnion[resultCols * resultRows];
+            for (int row = 0; row < resultRows; row++)
+            {
+                for (int column = 0; column < resultCols; column++)
+                {
+                    resultArray[resultRows * column + row].setFConst(0.0f);
+                    for (int i = 0; i < leftCols; i++)
+                    {
+                        resultArray[resultRows * column + row].setFConst(
+                            resultArray[resultRows * column + row].getFConst() +
+                            leftArray[i * leftRows + row].getFConst() *
+                                rightArray[column * rightRows + i].getFConst());
+                    }
+                }
+            }
+        }
+        break;
+
+        case EOpDiv:
+        case EOpIMod:
+        {
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; i++)
+            {
+                switch (getType().getBasicType())
+                {
+                    case EbtFloat:
+                    {
+                        ASSERT(op == EOpDiv);
+                        float dividend = leftArray[i].getFConst();
+                        float divisor  = rightArray[i].getFConst();
+                        if (divisor == 0.0f)
+                        {
+                            if (dividend == 0.0f)
+                            {
+                                diagnostics->warning(
+                                    getLine(),
+                                    "Zero divided by zero during constant folding generated NaN",
+                                    "/");
+                                resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
+                            }
+                            else
+                            {
+                                diagnostics->warning(getLine(),
+                                                     "Divide by zero during constant folding", "/");
+                                bool negativeResult =
+                                    std::signbit(dividend) != std::signbit(divisor);
+                                resultArray[i].setFConst(
+                                    negativeResult ? -std::numeric_limits<float>::infinity()
+                                                   : std::numeric_limits<float>::infinity());
+                            }
+                        }
+                        else if (gl::isInf(dividend) && gl::isInf(divisor))
+                        {
+                            diagnostics->warning(getLine(),
+                                                 "Infinity divided by infinity during constant "
+                                                 "folding generated NaN",
+                                                 "/");
+                            resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
+                        }
+                        else
+                        {
+                            float result = dividend / divisor;
+                            if (!gl::isInf(dividend) && gl::isInf(result))
+                            {
+                                diagnostics->warning(
+                                    getLine(), "Constant folded division overflowed to infinity",
+                                    "/");
+                            }
+                            resultArray[i].setFConst(result);
+                        }
+                        break;
+                    }
+                    case EbtInt:
+                        if (rightArray[i] == 0)
+                        {
+                            diagnostics->warning(
+                                getLine(), "Divide by zero error during constant folding", "/");
+                            resultArray[i].setIConst(INT_MAX);
+                        }
+                        else
+                        {
+                            int lhs     = leftArray[i].getIConst();
+                            int divisor = rightArray[i].getIConst();
+                            if (op == EOpDiv)
+                            {
+                                // Check for the special case where the minimum representable number
+                                // is
+                                // divided by -1. If left alone this leads to integer overflow in
+                                // C++.
+                                // ESSL 3.00.6 section 4.1.3 Integers:
+                                // "However, for the case where the minimum representable value is
+                                // divided by -1, it is allowed to return either the minimum
+                                // representable value or the maximum representable value."
+                                if (lhs == -0x7fffffff - 1 && divisor == -1)
+                                {
+                                    resultArray[i].setIConst(0x7fffffff);
+                                }
+                                else
+                                {
+                                    resultArray[i].setIConst(lhs / divisor);
+                                }
+                            }
+                            else
+                            {
+                                ASSERT(op == EOpIMod);
+                                if (lhs < 0 || divisor < 0)
+                                {
+                                    // ESSL 3.00.6 section 5.9: Results of modulus are undefined
+                                    // when
+                                    // either one of the operands is negative.
+                                    diagnostics->warning(getLine(),
+                                                         "Negative modulus operator operand "
+                                                         "encountered during constant folding",
+                                                         "%");
+                                    resultArray[i].setIConst(0);
+                                }
+                                else
+                                {
+                                    resultArray[i].setIConst(lhs % divisor);
+                                }
+                            }
+                        }
+                        break;
+
+                    case EbtUInt:
+                        if (rightArray[i] == 0)
+                        {
+                            diagnostics->warning(
+                                getLine(), "Divide by zero error during constant folding", "/");
+                            resultArray[i].setUConst(UINT_MAX);
+                        }
+                        else
+                        {
+                            if (op == EOpDiv)
+                            {
+                                resultArray[i].setUConst(leftArray[i].getUConst() /
+                                                         rightArray[i].getUConst());
+                            }
+                            else
+                            {
+                                ASSERT(op == EOpIMod);
+                                resultArray[i].setUConst(leftArray[i].getUConst() %
+                                                         rightArray[i].getUConst());
+                            }
+                        }
+                        break;
+
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+            }
+        }
+        break;
+
+        case EOpMatrixTimesVector:
+        {
+            // TODO(jmadll): This code should check for overflows.
+            ASSERT(rightNode->getBasicType() == EbtFloat);
+
+            const int matrixCols = getCols();
+            const int matrixRows = getRows();
+
+            resultArray = new TConstantUnion[matrixRows];
+
+            for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
+            {
+                resultArray[matrixRow].setFConst(0.0f);
+                for (int col = 0; col < matrixCols; col++)
+                {
+                    resultArray[matrixRow].setFConst(
+                        resultArray[matrixRow].getFConst() +
+                        leftArray[col * matrixRows + matrixRow].getFConst() *
+                            rightArray[col].getFConst());
+                }
+            }
+        }
+        break;
+
+        case EOpVectorTimesMatrix:
+        {
+            // TODO(jmadll): This code should check for overflows.
+            ASSERT(getType().getBasicType() == EbtFloat);
+
+            const int matrixCols = rightNode->getType().getCols();
+            const int matrixRows = rightNode->getType().getRows();
+
+            resultArray = new TConstantUnion[matrixCols];
+
+            for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
+            {
+                resultArray[matrixCol].setFConst(0.0f);
+                for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
+                {
+                    resultArray[matrixCol].setFConst(
+                        resultArray[matrixCol].getFConst() +
+                        leftArray[matrixRow].getFConst() *
+                            rightArray[matrixCol * matrixRows + matrixRow].getFConst());
+                }
+            }
+        }
+        break;
+
+        case EOpLogicalAnd:
+        {
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; i++)
+            {
+                resultArray[i] = leftArray[i] && rightArray[i];
+            }
+        }
+        break;
+
+        case EOpLogicalOr:
+        {
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; i++)
+            {
+                resultArray[i] = leftArray[i] || rightArray[i];
+            }
+        }
+        break;
+
+        case EOpLogicalXor:
+        {
+            ASSERT(getType().getBasicType() == EbtBool);
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; i++)
+            {
+                resultArray[i].setBConst(leftArray[i] != rightArray[i]);
+            }
+        }
+        break;
+
+        case EOpBitwiseAnd:
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i      = 0; i < objectSize; i++)
+                resultArray[i] = leftArray[i] & rightArray[i];
+            break;
+        case EOpBitwiseXor:
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i      = 0; i < objectSize; i++)
+                resultArray[i] = leftArray[i] ^ rightArray[i];
+            break;
+        case EOpBitwiseOr:
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i      = 0; i < objectSize; i++)
+                resultArray[i] = leftArray[i] | rightArray[i];
+            break;
+        case EOpBitShiftLeft:
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; i++)
+                resultArray[i] =
+                    TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line);
+            break;
+        case EOpBitShiftRight:
+            resultArray = new TConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; i++)
+                resultArray[i] =
+                    TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line);
+            break;
+
+        case EOpLessThan:
+            ASSERT(objectSize == 1);
+            resultArray = new TConstantUnion[1];
+            resultArray->setBConst(*leftArray < *rightArray);
+            break;
+
+        case EOpGreaterThan:
+            ASSERT(objectSize == 1);
+            resultArray = new TConstantUnion[1];
+            resultArray->setBConst(*leftArray > *rightArray);
+            break;
+
+        case EOpLessThanEqual:
+            ASSERT(objectSize == 1);
+            resultArray = new TConstantUnion[1];
+            resultArray->setBConst(!(*leftArray > *rightArray));
+            break;
+
+        case EOpGreaterThanEqual:
+            ASSERT(objectSize == 1);
+            resultArray = new TConstantUnion[1];
+            resultArray->setBConst(!(*leftArray < *rightArray));
+            break;
+
+        case EOpEqual:
+        case EOpNotEqual:
+        {
+            resultArray = new TConstantUnion[1];
+            bool equal  = true;
+            for (size_t i = 0; i < objectSize; i++)
+            {
+                if (leftArray[i] != rightArray[i])
+                {
+                    equal = false;
+                    break;  // break out of for loop
+                }
+            }
+            if (op == EOpEqual)
+            {
+                resultArray->setBConst(equal);
+            }
+            else
+            {
+                resultArray->setBConst(!equal);
+            }
+        }
+        break;
+
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+    return resultArray;
+}
+
+// The fold functions do operations on a constant at GLSL compile time, without generating run-time
+// code. Returns the constant value to keep using. Nullptr should not be returned.
+TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
+{
+    // Do operations where the return type may have a different number of components compared to the
+    // operand type.
+
+    const TConstantUnion *operandArray = getUnionArrayPointer();
+    ASSERT(operandArray);
+
+    size_t objectSize           = getType().getObjectSize();
+    TConstantUnion *resultArray = nullptr;
+    switch (op)
+    {
+        case EOpAny:
+            ASSERT(getType().getBasicType() == EbtBool);
+            resultArray = new TConstantUnion();
+            resultArray->setBConst(false);
+            for (size_t i = 0; i < objectSize; i++)
+            {
+                if (operandArray[i].getBConst())
+                {
+                    resultArray->setBConst(true);
+                    break;
+                }
+            }
+            break;
+
+        case EOpAll:
+            ASSERT(getType().getBasicType() == EbtBool);
+            resultArray = new TConstantUnion();
+            resultArray->setBConst(true);
+            for (size_t i = 0; i < objectSize; i++)
+            {
+                if (!operandArray[i].getBConst())
+                {
+                    resultArray->setBConst(false);
+                    break;
+                }
+            }
+            break;
+
+        case EOpLength:
+            ASSERT(getType().getBasicType() == EbtFloat);
+            resultArray = new TConstantUnion();
+            resultArray->setFConst(VectorLength(operandArray, objectSize));
+            break;
+
+        case EOpTranspose:
+        {
+            ASSERT(getType().getBasicType() == EbtFloat);
+            resultArray = new TConstantUnion[objectSize];
+            angle::Matrix<float> result =
+                GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
+            SetUnionArrayFromMatrix(result, resultArray);
+            break;
+        }
+
+        case EOpDeterminant:
+        {
+            ASSERT(getType().getBasicType() == EbtFloat);
+            unsigned int size = getType().getNominalSize();
+            ASSERT(size >= 2 && size <= 4);
+            resultArray = new TConstantUnion();
+            resultArray->setFConst(GetMatrix(operandArray, size).determinant());
+            break;
+        }
+
+        case EOpInverse:
+        {
+            ASSERT(getType().getBasicType() == EbtFloat);
+            unsigned int size = getType().getNominalSize();
+            ASSERT(size >= 2 && size <= 4);
+            resultArray                 = new TConstantUnion[objectSize];
+            angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
+            SetUnionArrayFromMatrix(result, resultArray);
+            break;
+        }
+
+        case EOpPackSnorm2x16:
+            ASSERT(getType().getBasicType() == EbtFloat);
+            ASSERT(getType().getNominalSize() == 2);
+            resultArray = new TConstantUnion();
+            resultArray->setUConst(
+                gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
+            break;
+
+        case EOpUnpackSnorm2x16:
+        {
+            ASSERT(getType().getBasicType() == EbtUInt);
+            resultArray = new TConstantUnion[2];
+            float f1, f2;
+            gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
+            resultArray[0].setFConst(f1);
+            resultArray[1].setFConst(f2);
+            break;
+        }
+
+        case EOpPackUnorm2x16:
+            ASSERT(getType().getBasicType() == EbtFloat);
+            ASSERT(getType().getNominalSize() == 2);
+            resultArray = new TConstantUnion();
+            resultArray->setUConst(
+                gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
+            break;
+
+        case EOpUnpackUnorm2x16:
+        {
+            ASSERT(getType().getBasicType() == EbtUInt);
+            resultArray = new TConstantUnion[2];
+            float f1, f2;
+            gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
+            resultArray[0].setFConst(f1);
+            resultArray[1].setFConst(f2);
+            break;
+        }
+
+        case EOpPackHalf2x16:
+            ASSERT(getType().getBasicType() == EbtFloat);
+            ASSERT(getType().getNominalSize() == 2);
+            resultArray = new TConstantUnion();
+            resultArray->setUConst(
+                gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
+            break;
+
+        case EOpUnpackHalf2x16:
+        {
+            ASSERT(getType().getBasicType() == EbtUInt);
+            resultArray = new TConstantUnion[2];
+            float f1, f2;
+            gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
+            resultArray[0].setFConst(f1);
+            resultArray[1].setFConst(f2);
+            break;
+        }
+
+        case EOpPackUnorm4x8:
+        {
+            ASSERT(getType().getBasicType() == EbtFloat);
+            resultArray = new TConstantUnion();
+            resultArray->setUConst(
+                gl::PackUnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(),
+                                 operandArray[2].getFConst(), operandArray[3].getFConst()));
+            break;
+        }
+        case EOpPackSnorm4x8:
+        {
+            ASSERT(getType().getBasicType() == EbtFloat);
+            resultArray = new TConstantUnion();
+            resultArray->setUConst(
+                gl::PackSnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(),
+                                 operandArray[2].getFConst(), operandArray[3].getFConst()));
+            break;
+        }
+        case EOpUnpackUnorm4x8:
+        {
+            ASSERT(getType().getBasicType() == EbtUInt);
+            resultArray = new TConstantUnion[4];
+            float f[4];
+            gl::UnpackUnorm4x8(operandArray[0].getUConst(), f);
+            for (size_t i = 0; i < 4; ++i)
+            {
+                resultArray[i].setFConst(f[i]);
+            }
+            break;
+        }
+        case EOpUnpackSnorm4x8:
+        {
+            ASSERT(getType().getBasicType() == EbtUInt);
+            resultArray = new TConstantUnion[4];
+            float f[4];
+            gl::UnpackSnorm4x8(operandArray[0].getUConst(), f);
+            for (size_t i = 0; i < 4; ++i)
+            {
+                resultArray[i].setFConst(f[i]);
+            }
+            break;
+        }
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    return resultArray;
+}
+
+TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
+                                                             TDiagnostics *diagnostics)
+{
+    // Do unary operations where each component of the result is computed based on the corresponding
+    // component of the operand. Also folds normalize, though the divisor in that case takes all
+    // components into account.
+
+    const TConstantUnion *operandArray = getUnionArrayPointer();
+    ASSERT(operandArray);
+
+    size_t objectSize = getType().getObjectSize();
+
+    TConstantUnion *resultArray = new TConstantUnion[objectSize];
+    for (size_t i = 0; i < objectSize; i++)
+    {
+        switch (op)
+        {
+            case EOpNegative:
+                switch (getType().getBasicType())
+                {
+                    case EbtFloat:
+                        resultArray[i].setFConst(-operandArray[i].getFConst());
+                        break;
+                    case EbtInt:
+                        if (operandArray[i] == std::numeric_limits<int>::min())
+                        {
+                            // The minimum representable integer doesn't have a positive
+                            // counterpart, rather the negation overflows and in ESSL is supposed to
+                            // wrap back to the minimum representable integer. Make sure that we
+                            // don't actually let the negation overflow, which has undefined
+                            // behavior in C++.
+                            resultArray[i].setIConst(std::numeric_limits<int>::min());
+                        }
+                        else
+                        {
+                            resultArray[i].setIConst(-operandArray[i].getIConst());
+                        }
+                        break;
+                    case EbtUInt:
+                        if (operandArray[i] == 0x80000000u)
+                        {
+                            resultArray[i].setUConst(0x80000000u);
+                        }
+                        else
+                        {
+                            resultArray[i].setUConst(static_cast<unsigned int>(
+                                -static_cast<int>(operandArray[i].getUConst())));
+                        }
+                        break;
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+                break;
+
+            case EOpPositive:
+                switch (getType().getBasicType())
+                {
+                    case EbtFloat:
+                        resultArray[i].setFConst(operandArray[i].getFConst());
+                        break;
+                    case EbtInt:
+                        resultArray[i].setIConst(operandArray[i].getIConst());
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setUConst(static_cast<unsigned int>(
+                            static_cast<int>(operandArray[i].getUConst())));
+                        break;
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+                break;
+
+            case EOpLogicalNot:
+                switch (getType().getBasicType())
+                {
+                    case EbtBool:
+                        resultArray[i].setBConst(!operandArray[i].getBConst());
+                        break;
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+                break;
+
+            case EOpBitwiseNot:
+                switch (getType().getBasicType())
+                {
+                    case EbtInt:
+                        resultArray[i].setIConst(~operandArray[i].getIConst());
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setUConst(~operandArray[i].getUConst());
+                        break;
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+                break;
+
+            case EOpRadians:
+                ASSERT(getType().getBasicType() == EbtFloat);
+                resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
+                break;
+
+            case EOpDegrees:
+                ASSERT(getType().getBasicType() == EbtFloat);
+                resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
+                break;
+
+            case EOpSin:
+                foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
+                break;
+
+            case EOpCos:
+                foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
+                break;
+
+            case EOpTan:
+                foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
+                break;
+
+            case EOpAsin:
+                // For asin(x), results are undefined if |x| > 1, we are choosing to set result to
+                // 0.
+                if (fabsf(operandArray[i].getFConst()) > 1.0f)
+                    UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+                                                  diagnostics, &resultArray[i]);
+                else
+                    foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
+                break;
+
+            case EOpAcos:
+                // For acos(x), results are undefined if |x| > 1, we are choosing to set result to
+                // 0.
+                if (fabsf(operandArray[i].getFConst()) > 1.0f)
+                    UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+                                                  diagnostics, &resultArray[i]);
+                else
+                    foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
+                break;
+
+            case EOpAtan:
+                foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
+                break;
+
+            case EOpSinh:
+                foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
+                break;
+
+            case EOpCosh:
+                foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
+                break;
+
+            case EOpTanh:
+                foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
+                break;
+
+            case EOpAsinh:
+                foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
+                break;
+
+            case EOpAcosh:
+                // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
+                if (operandArray[i].getFConst() < 1.0f)
+                    UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+                                                  diagnostics, &resultArray[i]);
+                else
+                    foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
+                break;
+
+            case EOpAtanh:
+                // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
+                // 0.
+                if (fabsf(operandArray[i].getFConst()) >= 1.0f)
+                    UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+                                                  diagnostics, &resultArray[i]);
+                else
+                    foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
+                break;
+
+            case EOpAbs:
+                switch (getType().getBasicType())
+                {
+                    case EbtFloat:
+                        resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
+                        break;
+                    case EbtInt:
+                        resultArray[i].setIConst(abs(operandArray[i].getIConst()));
+                        break;
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+                break;
+
+            case EOpSign:
+                switch (getType().getBasicType())
+                {
+                    case EbtFloat:
+                    {
+                        float fConst  = operandArray[i].getFConst();
+                        float fResult = 0.0f;
+                        if (fConst > 0.0f)
+                            fResult = 1.0f;
+                        else if (fConst < 0.0f)
+                            fResult = -1.0f;
+                        resultArray[i].setFConst(fResult);
+                        break;
+                    }
+                    case EbtInt:
+                    {
+                        int iConst  = operandArray[i].getIConst();
+                        int iResult = 0;
+                        if (iConst > 0)
+                            iResult = 1;
+                        else if (iConst < 0)
+                            iResult = -1;
+                        resultArray[i].setIConst(iResult);
+                        break;
+                    }
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+                break;
+
+            case EOpFloor:
+                foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
+                break;
+
+            case EOpTrunc:
+                foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
+                break;
+
+            case EOpRound:
+                foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
+                break;
+
+            case EOpRoundEven:
+            {
+                ASSERT(getType().getBasicType() == EbtFloat);
+                float x = operandArray[i].getFConst();
+                float result;
+                float fractPart = modff(x, &result);
+                if (fabsf(fractPart) == 0.5f)
+                    result = 2.0f * roundf(x / 2.0f);
+                else
+                    result = roundf(x);
+                resultArray[i].setFConst(result);
+                break;
+            }
+
+            case EOpCeil:
+                foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
+                break;
+
+            case EOpFract:
+            {
+                ASSERT(getType().getBasicType() == EbtFloat);
+                float x = operandArray[i].getFConst();
+                resultArray[i].setFConst(x - floorf(x));
+                break;
+            }
+
+            case EOpIsNan:
+                ASSERT(getType().getBasicType() == EbtFloat);
+                resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst()));
+                break;
+
+            case EOpIsInf:
+                ASSERT(getType().getBasicType() == EbtFloat);
+                resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst()));
+                break;
+
+            case EOpFloatBitsToInt:
+                ASSERT(getType().getBasicType() == EbtFloat);
+                resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst()));
+                break;
+
+            case EOpFloatBitsToUint:
+                ASSERT(getType().getBasicType() == EbtFloat);
+                resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
+                break;
+
+            case EOpIntBitsToFloat:
+                ASSERT(getType().getBasicType() == EbtInt);
+                resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
+                break;
+
+            case EOpUintBitsToFloat:
+                ASSERT(getType().getBasicType() == EbtUInt);
+                resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst()));
+                break;
+
+            case EOpExp:
+                foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
+                break;
+
+            case EOpLog:
+                // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
+                if (operandArray[i].getFConst() <= 0.0f)
+                    UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+                                                  diagnostics, &resultArray[i]);
+                else
+                    foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
+                break;
+
+            case EOpExp2:
+                foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
+                break;
+
+            case EOpLog2:
+                // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
+                // And log2f is not available on some plarforms like old android, so just using
+                // log(x)/log(2) here.
+                if (operandArray[i].getFConst() <= 0.0f)
+                    UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+                                                  diagnostics, &resultArray[i]);
+                else
+                {
+                    foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
+                    resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
+                }
+                break;
+
+            case EOpSqrt:
+                // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
+                if (operandArray[i].getFConst() < 0.0f)
+                    UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+                                                  diagnostics, &resultArray[i]);
+                else
+                    foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
+                break;
+
+            case EOpInverseSqrt:
+                // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
+                // so getting the square root first using builtin function sqrt() and then taking
+                // its inverse.
+                // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
+                // result to 0.
+                if (operandArray[i].getFConst() <= 0.0f)
+                    UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+                                                  diagnostics, &resultArray[i]);
+                else
+                {
+                    foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
+                    resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
+                }
+                break;
+
+            case EOpLogicalNotComponentWise:
+                ASSERT(getType().getBasicType() == EbtBool);
+                resultArray[i].setBConst(!operandArray[i].getBConst());
+                break;
+
+            case EOpNormalize:
+            {
+                ASSERT(getType().getBasicType() == EbtFloat);
+                float x      = operandArray[i].getFConst();
+                float length = VectorLength(operandArray, objectSize);
+                if (length)
+                    resultArray[i].setFConst(x / length);
+                else
+                    UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+                                                  diagnostics, &resultArray[i]);
+                break;
+            }
+            case EOpBitfieldReverse:
+            {
+                uint32_t value;
+                if (getType().getBasicType() == EbtInt)
+                {
+                    value = static_cast<uint32_t>(operandArray[i].getIConst());
+                }
+                else
+                {
+                    ASSERT(getType().getBasicType() == EbtUInt);
+                    value = operandArray[i].getUConst();
+                }
+                uint32_t result = gl::BitfieldReverse(value);
+                if (getType().getBasicType() == EbtInt)
+                {
+                    resultArray[i].setIConst(static_cast<int32_t>(result));
+                }
+                else
+                {
+                    resultArray[i].setUConst(result);
+                }
+                break;
+            }
+            case EOpBitCount:
+            {
+                uint32_t value;
+                if (getType().getBasicType() == EbtInt)
+                {
+                    value = static_cast<uint32_t>(operandArray[i].getIConst());
+                }
+                else
+                {
+                    ASSERT(getType().getBasicType() == EbtUInt);
+                    value = operandArray[i].getUConst();
+                }
+                int result = gl::BitCount(value);
+                resultArray[i].setIConst(result);
+                break;
+            }
+            case EOpFindLSB:
+            {
+                uint32_t value;
+                if (getType().getBasicType() == EbtInt)
+                {
+                    value = static_cast<uint32_t>(operandArray[i].getIConst());
+                }
+                else
+                {
+                    ASSERT(getType().getBasicType() == EbtUInt);
+                    value = operandArray[i].getUConst();
+                }
+                resultArray[i].setIConst(gl::FindLSB(value));
+                break;
+            }
+            case EOpFindMSB:
+            {
+                uint32_t value;
+                if (getType().getBasicType() == EbtInt)
+                {
+                    int intValue = operandArray[i].getIConst();
+                    value        = static_cast<uint32_t>(intValue);
+                    if (intValue < 0)
+                    {
+                        // Look for zero instead of one in value. This also handles the intValue ==
+                        // -1 special case, where the return value needs to be -1.
+                        value = ~value;
+                    }
+                }
+                else
+                {
+                    ASSERT(getType().getBasicType() == EbtUInt);
+                    value = operandArray[i].getUConst();
+                }
+                resultArray[i].setIConst(gl::FindMSB(value));
+                break;
+            }
+            case EOpDFdx:
+            case EOpDFdy:
+            case EOpFwidth:
+                ASSERT(getType().getBasicType() == EbtFloat);
+                // Derivatives of constant arguments should be 0.
+                resultArray[i].setFConst(0.0f);
+                break;
+
+            default:
+                return nullptr;
+        }
+    }
+
+    return resultArray;
+}
+
+void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
+                                              FloatTypeUnaryFunc builtinFunc,
+                                              TConstantUnion *result) const
+{
+    ASSERT(builtinFunc);
+
+    ASSERT(getType().getBasicType() == EbtFloat);
+    result->setFConst(builtinFunc(parameter.getFConst()));
+}
+
+// static
+TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
+{
+    ASSERT(aggregate->getSequence()->size() > 0u);
+    size_t resultSize           = aggregate->getType().getObjectSize();
+    TConstantUnion *resultArray = new TConstantUnion[resultSize];
+    TBasicType basicType        = aggregate->getBasicType();
+
+    size_t resultIndex = 0u;
+
+    if (aggregate->getSequence()->size() == 1u)
+    {
+        TIntermNode *argument                    = aggregate->getSequence()->front();
+        TIntermConstantUnion *argumentConstant   = argument->getAsConstantUnion();
+        const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
+        // Check the special case of constructing a matrix diagonal from a single scalar,
+        // or a vector from a single scalar.
+        if (argumentConstant->getType().getObjectSize() == 1u)
+        {
+            if (aggregate->isMatrix())
+            {
+                int resultCols = aggregate->getType().getCols();
+                int resultRows = aggregate->getType().getRows();
+                for (int col = 0; col < resultCols; ++col)
+                {
+                    for (int row = 0; row < resultRows; ++row)
+                    {
+                        if (col == row)
+                        {
+                            resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
+                        }
+                        else
+                        {
+                            resultArray[resultIndex].setFConst(0.0f);
+                        }
+                        ++resultIndex;
+                    }
+                }
+            }
+            else
+            {
+                while (resultIndex < resultSize)
+                {
+                    resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
+                    ++resultIndex;
+                }
+            }
+            ASSERT(resultIndex == resultSize);
+            return resultArray;
+        }
+        else if (aggregate->isMatrix() && argumentConstant->isMatrix())
+        {
+            // The special case of constructing a matrix from a matrix.
+            int argumentCols = argumentConstant->getType().getCols();
+            int argumentRows = argumentConstant->getType().getRows();
+            int resultCols   = aggregate->getType().getCols();
+            int resultRows   = aggregate->getType().getRows();
+            for (int col = 0; col < resultCols; ++col)
+            {
+                for (int row = 0; row < resultRows; ++row)
+                {
+                    if (col < argumentCols && row < argumentRows)
+                    {
+                        resultArray[resultIndex].cast(basicType,
+                                                      argumentUnionArray[col * argumentRows + row]);
+                    }
+                    else if (col == row)
+                    {
+                        resultArray[resultIndex].setFConst(1.0f);
+                    }
+                    else
+                    {
+                        resultArray[resultIndex].setFConst(0.0f);
+                    }
+                    ++resultIndex;
+                }
+            }
+            ASSERT(resultIndex == resultSize);
+            return resultArray;
+        }
+    }
+
+    for (TIntermNode *&argument : *aggregate->getSequence())
+    {
+        TIntermConstantUnion *argumentConstant   = argument->getAsConstantUnion();
+        size_t argumentSize                      = argumentConstant->getType().getObjectSize();
+        const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
+        for (size_t i = 0u; i < argumentSize; ++i)
+        {
+            if (resultIndex >= resultSize)
+                break;
+            resultArray[resultIndex].cast(basicType, argumentUnionArray[i]);
+            ++resultIndex;
+        }
+    }
+    ASSERT(resultIndex == resultSize);
+    return resultArray;
+}
+
+// static
+TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
+                                                           TDiagnostics *diagnostics)
+{
+    TOperator op              = aggregate->getOp();
+    TIntermSequence *arguments = aggregate->getSequence();
+    unsigned int argsCount     = static_cast<unsigned int>(arguments->size());
+    std::vector<const TConstantUnion *> unionArrays(argsCount);
+    std::vector<size_t> objectSizes(argsCount);
+    size_t maxObjectSize = 0;
+    TBasicType basicType = EbtVoid;
+    TSourceLoc loc;
+    for (unsigned int i = 0; i < argsCount; i++)
+    {
+        TIntermConstantUnion *argConstant = (*arguments)[i]->getAsConstantUnion();
+        ASSERT(argConstant != nullptr);  // Should be checked already.
+
+        if (i == 0)
+        {
+            basicType = argConstant->getType().getBasicType();
+            loc       = argConstant->getLine();
+        }
+        unionArrays[i] = argConstant->getUnionArrayPointer();
+        objectSizes[i] = argConstant->getType().getObjectSize();
+        if (objectSizes[i] > maxObjectSize)
+            maxObjectSize = objectSizes[i];
+    }
+
+    if (!(*arguments)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
+    {
+        for (unsigned int i = 0; i < argsCount; i++)
+            if (objectSizes[i] != maxObjectSize)
+                unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
+    }
+
+    TConstantUnion *resultArray = nullptr;
+
+    switch (op)
+    {
+        case EOpAtan:
+        {
+            ASSERT(basicType == EbtFloat);
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                float y = unionArrays[0][i].getFConst();
+                float x = unionArrays[1][i].getFConst();
+                // Results are undefined if x and y are both 0.
+                if (x == 0.0f && y == 0.0f)
+                    UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
+                else
+                    resultArray[i].setFConst(atan2f(y, x));
+            }
+            break;
+        }
+
+        case EOpPow:
+        {
+            ASSERT(basicType == EbtFloat);
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                float x = unionArrays[0][i].getFConst();
+                float y = unionArrays[1][i].getFConst();
+                // Results are undefined if x < 0.
+                // Results are undefined if x = 0 and y <= 0.
+                if (x < 0.0f)
+                    UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
+                else if (x == 0.0f && y <= 0.0f)
+                    UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
+                else
+                    resultArray[i].setFConst(powf(x, y));
+            }
+            break;
+        }
+
+        case EOpMod:
+        {
+            ASSERT(basicType == EbtFloat);
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                float x = unionArrays[0][i].getFConst();
+                float y = unionArrays[1][i].getFConst();
+                resultArray[i].setFConst(x - y * floorf(x / y));
+            }
+            break;
+        }
+
+        case EOpMin:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                switch (basicType)
+                {
+                    case EbtFloat:
+                        resultArray[i].setFConst(
+                            std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
+                        break;
+                    case EbtInt:
+                        resultArray[i].setIConst(
+                            std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setUConst(
+                            std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
+                        break;
+                    default:
+                        UNREACHABLE();
+                        break;
+                }
+            }
+            break;
+        }
+
+        case EOpMax:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                switch (basicType)
+                {
+                    case EbtFloat:
+                        resultArray[i].setFConst(
+                            std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
+                        break;
+                    case EbtInt:
+                        resultArray[i].setIConst(
+                            std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setUConst(
+                            std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
+                        break;
+                    default:
+                        UNREACHABLE();
+                        break;
+                }
+            }
+            break;
+        }
+
+        case EOpStep:
+        {
+            ASSERT(basicType == EbtFloat);
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+                resultArray[i].setFConst(
+                    unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f);
+            break;
+        }
+
+        case EOpLessThanComponentWise:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                switch (basicType)
+                {
+                    case EbtFloat:
+                        resultArray[i].setBConst(unionArrays[0][i].getFConst() <
+                                                 unionArrays[1][i].getFConst());
+                        break;
+                    case EbtInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getIConst() <
+                                                 unionArrays[1][i].getIConst());
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getUConst() <
+                                                 unionArrays[1][i].getUConst());
+                        break;
+                    default:
+                        UNREACHABLE();
+                        break;
+                }
+            }
+            break;
+        }
+
+        case EOpLessThanEqualComponentWise:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                switch (basicType)
+                {
+                    case EbtFloat:
+                        resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
+                                                 unionArrays[1][i].getFConst());
+                        break;
+                    case EbtInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
+                                                 unionArrays[1][i].getIConst());
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
+                                                 unionArrays[1][i].getUConst());
+                        break;
+                    default:
+                        UNREACHABLE();
+                        break;
+                }
+            }
+            break;
+        }
+
+        case EOpGreaterThanComponentWise:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                switch (basicType)
+                {
+                    case EbtFloat:
+                        resultArray[i].setBConst(unionArrays[0][i].getFConst() >
+                                                 unionArrays[1][i].getFConst());
+                        break;
+                    case EbtInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getIConst() >
+                                                 unionArrays[1][i].getIConst());
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getUConst() >
+                                                 unionArrays[1][i].getUConst());
+                        break;
+                    default:
+                        UNREACHABLE();
+                        break;
+                }
+            }
+            break;
+        }
+        case EOpGreaterThanEqualComponentWise:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                switch (basicType)
+                {
+                    case EbtFloat:
+                        resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
+                                                 unionArrays[1][i].getFConst());
+                        break;
+                    case EbtInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
+                                                 unionArrays[1][i].getIConst());
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
+                                                 unionArrays[1][i].getUConst());
+                        break;
+                    default:
+                        UNREACHABLE();
+                        break;
+                }
+            }
+        }
+        break;
+
+        case EOpEqualComponentWise:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                switch (basicType)
+                {
+                    case EbtFloat:
+                        resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
+                                                 unionArrays[1][i].getFConst());
+                        break;
+                    case EbtInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
+                                                 unionArrays[1][i].getIConst());
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
+                                                 unionArrays[1][i].getUConst());
+                        break;
+                    case EbtBool:
+                        resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
+                                                 unionArrays[1][i].getBConst());
+                        break;
+                    default:
+                        UNREACHABLE();
+                        break;
+                }
+            }
+            break;
+        }
+
+        case EOpNotEqualComponentWise:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                switch (basicType)
+                {
+                    case EbtFloat:
+                        resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
+                                                 unionArrays[1][i].getFConst());
+                        break;
+                    case EbtInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
+                                                 unionArrays[1][i].getIConst());
+                        break;
+                    case EbtUInt:
+                        resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
+                                                 unionArrays[1][i].getUConst());
+                        break;
+                    case EbtBool:
+                        resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
+                                                 unionArrays[1][i].getBConst());
+                        break;
+                    default:
+                        UNREACHABLE();
+                        break;
+                }
+            }
+            break;
+        }
+
+        case EOpDistance:
+        {
+            ASSERT(basicType == EbtFloat);
+            TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
+            resultArray                   = new TConstantUnion();
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                float x = unionArrays[0][i].getFConst();
+                float y = unionArrays[1][i].getFConst();
+                distanceArray[i].setFConst(x - y);
+            }
+            resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
+            break;
+        }
+
+        case EOpDot:
+            ASSERT(basicType == EbtFloat);
+            resultArray = new TConstantUnion();
+            resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
+            break;
+
+        case EOpCross:
+        {
+            ASSERT(basicType == EbtFloat && maxObjectSize == 3);
+            resultArray = new TConstantUnion[maxObjectSize];
+            float x0    = unionArrays[0][0].getFConst();
+            float x1    = unionArrays[0][1].getFConst();
+            float x2    = unionArrays[0][2].getFConst();
+            float y0    = unionArrays[1][0].getFConst();
+            float y1    = unionArrays[1][1].getFConst();
+            float y2    = unionArrays[1][2].getFConst();
+            resultArray[0].setFConst(x1 * y2 - y1 * x2);
+            resultArray[1].setFConst(x2 * y0 - y2 * x0);
+            resultArray[2].setFConst(x0 * y1 - y0 * x1);
+            break;
+        }
+
+        case EOpReflect:
+        {
+            ASSERT(basicType == EbtFloat);
+            // genType reflect (genType I, genType N) :
+            //     For the incident vector I and surface orientation N, returns the reflection
+            //     direction:
+            //     I - 2 * dot(N, I) * N.
+            resultArray      = new TConstantUnion[maxObjectSize];
+            float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                float result = unionArrays[0][i].getFConst() -
+                               2.0f * dotProduct * unionArrays[1][i].getFConst();
+                resultArray[i].setFConst(result);
+            }
+            break;
+        }
+
+        case EOpMulMatrixComponentWise:
+        {
+            ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() &&
+                   (*arguments)[1]->getAsTyped()->isMatrix());
+            // Perform component-wise matrix multiplication.
+            resultArray = new TConstantUnion[maxObjectSize];
+            int size    = (*arguments)[0]->getAsTyped()->getNominalSize();
+            angle::Matrix<float> result =
+                GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
+            SetUnionArrayFromMatrix(result, resultArray);
+            break;
+        }
+
+        case EOpOuterProduct:
+        {
+            ASSERT(basicType == EbtFloat);
+            size_t numRows = (*arguments)[0]->getAsTyped()->getType().getObjectSize();
+            size_t numCols = (*arguments)[1]->getAsTyped()->getType().getObjectSize();
+            resultArray    = new TConstantUnion[numRows * numCols];
+            angle::Matrix<float> result =
+                GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
+                    .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
+            SetUnionArrayFromMatrix(result, resultArray);
+            break;
+        }
+
+        case EOpClamp:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                switch (basicType)
+                {
+                    case EbtFloat:
+                    {
+                        float x   = unionArrays[0][i].getFConst();
+                        float min = unionArrays[1][i].getFConst();
+                        float max = unionArrays[2][i].getFConst();
+                        // Results are undefined if min > max.
+                        if (min > max)
+                            UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
+                                                          &resultArray[i]);
+                        else
+                            resultArray[i].setFConst(gl::clamp(x, min, max));
+                        break;
+                    }
+
+                    case EbtInt:
+                    {
+                        int x   = unionArrays[0][i].getIConst();
+                        int min = unionArrays[1][i].getIConst();
+                        int max = unionArrays[2][i].getIConst();
+                        // Results are undefined if min > max.
+                        if (min > max)
+                            UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
+                                                          &resultArray[i]);
+                        else
+                            resultArray[i].setIConst(gl::clamp(x, min, max));
+                        break;
+                    }
+                    case EbtUInt:
+                    {
+                        unsigned int x   = unionArrays[0][i].getUConst();
+                        unsigned int min = unionArrays[1][i].getUConst();
+                        unsigned int max = unionArrays[2][i].getUConst();
+                        // Results are undefined if min > max.
+                        if (min > max)
+                            UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
+                                                          &resultArray[i]);
+                        else
+                            resultArray[i].setUConst(gl::clamp(x, min, max));
+                        break;
+                    }
+                    default:
+                        UNREACHABLE();
+                        break;
+                }
+            }
+            break;
+        }
+
+        case EOpMix:
+        {
+            ASSERT(basicType == EbtFloat);
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                float x         = unionArrays[0][i].getFConst();
+                float y         = unionArrays[1][i].getFConst();
+                TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType();
+                if (type == EbtFloat)
+                {
+                    // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
+                    float a = unionArrays[2][i].getFConst();
+                    resultArray[i].setFConst(x * (1.0f - a) + y * a);
+                }
+                else  // 3rd parameter is EbtBool
+                {
+                    ASSERT(type == EbtBool);
+                    // Selects which vector each returned component comes from.
+                    // For a component of a that is false, the corresponding component of x is
+                    // returned.
+                    // For a component of a that is true, the corresponding component of y is
+                    // returned.
+                    bool a = unionArrays[2][i].getBConst();
+                    resultArray[i].setFConst(a ? y : x);
+                }
+            }
+            break;
+        }
+
+        case EOpSmoothStep:
+        {
+            ASSERT(basicType == EbtFloat);
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                float edge0 = unionArrays[0][i].getFConst();
+                float edge1 = unionArrays[1][i].getFConst();
+                float x     = unionArrays[2][i].getFConst();
+                // Results are undefined if edge0 >= edge1.
+                if (edge0 >= edge1)
+                {
+                    UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
+                }
+                else
+                {
+                    // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
+                    // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
+                    float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
+                    resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
+                }
+            }
+            break;
+        }
+
+        case EOpLdexp:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                float x = unionArrays[0][i].getFConst();
+                int exp = unionArrays[1][i].getIConst();
+                if (exp > 128)
+                {
+                    UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
+                }
+                else
+                {
+                    resultArray[i].setFConst(gl::Ldexp(x, exp));
+                }
+            }
+            break;
+        }
+
+        case EOpFaceForward:
+        {
+            ASSERT(basicType == EbtFloat);
+            // genType faceforward(genType N, genType I, genType Nref) :
+            //     If dot(Nref, I) < 0 return N, otherwise return -N.
+            resultArray      = new TConstantUnion[maxObjectSize];
+            float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                if (dotProduct < 0)
+                    resultArray[i].setFConst(unionArrays[0][i].getFConst());
+                else
+                    resultArray[i].setFConst(-unionArrays[0][i].getFConst());
+            }
+            break;
+        }
+
+        case EOpRefract:
+        {
+            ASSERT(basicType == EbtFloat);
+            // genType refract(genType I, genType N, float eta) :
+            //     For the incident vector I and surface normal N, and the ratio of indices of
+            //     refraction eta,
+            //     return the refraction vector. The result is computed by
+            //         k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
+            //         if (k < 0.0)
+            //             return genType(0.0)
+            //         else
+            //             return eta * I - (eta * dot(N, I) + sqrt(k)) * N
+            resultArray      = new TConstantUnion[maxObjectSize];
+            float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
+            for (size_t i = 0; i < maxObjectSize; i++)
+            {
+                float eta = unionArrays[2][i].getFConst();
+                float k   = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
+                if (k < 0.0f)
+                    resultArray[i].setFConst(0.0f);
+                else
+                    resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
+                                             (eta * dotProduct + sqrtf(k)) *
+                                                 unionArrays[1][i].getFConst());
+            }
+            break;
+        }
+        case EOpBitfieldExtract:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; ++i)
+            {
+                int offset = unionArrays[1][0].getIConst();
+                int bits   = unionArrays[2][0].getIConst();
+                if (bits == 0)
+                {
+                    if (aggregate->getBasicType() == EbtInt)
+                    {
+                        resultArray[i].setIConst(0);
+                    }
+                    else
+                    {
+                        ASSERT(aggregate->getBasicType() == EbtUInt);
+                        resultArray[i].setUConst(0);
+                    }
+                }
+                else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
+                {
+                    UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
+                                                  &resultArray[i]);
+                }
+                else
+                {
+                    // bits can be 32 here, so we need to avoid bit shift overflow.
+                    uint32_t maskMsb = 1u << (bits - 1);
+                    uint32_t mask    = ((maskMsb - 1u) | maskMsb) << offset;
+                    if (aggregate->getBasicType() == EbtInt)
+                    {
+                        uint32_t value = static_cast<uint32_t>(unionArrays[0][i].getIConst());
+                        uint32_t resultUnsigned = (value & mask) >> offset;
+                        if ((resultUnsigned & maskMsb) != 0)
+                        {
+                            // The most significant bits (from bits+1 to the most significant bit)
+                            // should be set to 1.
+                            uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;
+                            resultUnsigned |= higherBitsMask;
+                        }
+                        resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
+                    }
+                    else
+                    {
+                        ASSERT(aggregate->getBasicType() == EbtUInt);
+                        uint32_t value = unionArrays[0][i].getUConst();
+                        resultArray[i].setUConst((value & mask) >> offset);
+                    }
+                }
+            }
+            break;
+        }
+        case EOpBitfieldInsert:
+        {
+            resultArray = new TConstantUnion[maxObjectSize];
+            for (size_t i = 0; i < maxObjectSize; ++i)
+            {
+                int offset = unionArrays[2][0].getIConst();
+                int bits   = unionArrays[3][0].getIConst();
+                if (bits == 0)
+                {
+                    if (aggregate->getBasicType() == EbtInt)
+                    {
+                        int32_t base = unionArrays[0][i].getIConst();
+                        resultArray[i].setIConst(base);
+                    }
+                    else
+                    {
+                        ASSERT(aggregate->getBasicType() == EbtUInt);
+                        uint32_t base = unionArrays[0][i].getUConst();
+                        resultArray[i].setUConst(base);
+                    }
+                }
+                else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
+                {
+                    UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
+                                                  &resultArray[i]);
+                }
+                else
+                {
+                    // bits can be 32 here, so we need to avoid bit shift overflow.
+                    uint32_t maskMsb    = 1u << (bits - 1);
+                    uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset;
+                    uint32_t baseMask   = ~insertMask;
+                    if (aggregate->getBasicType() == EbtInt)
+                    {
+                        uint32_t base   = static_cast<uint32_t>(unionArrays[0][i].getIConst());
+                        uint32_t insert = static_cast<uint32_t>(unionArrays[1][i].getIConst());
+                        uint32_t resultUnsigned =
+                            (base & baseMask) | ((insert << offset) & insertMask);
+                        resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
+                    }
+                    else
+                    {
+                        ASSERT(aggregate->getBasicType() == EbtUInt);
+                        uint32_t base   = unionArrays[0][i].getUConst();
+                        uint32_t insert = unionArrays[1][i].getUConst();
+                        resultArray[i].setUConst((base & baseMask) |
+                                                 ((insert << offset) & insertMask));
+                    }
+                }
+            }
+            break;
+        }
+
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+    return resultArray;
+}
+
+// static
+TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
+{
+    if (hashFunction == nullptr || name.empty())
+        return name;
+    khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
+    TStringStream stream;
+    stream << HASHED_NAME_PREFIX << std::hex << number;
+    TString hashedName = stream.str();
+    return hashedName;
+}
+
+void TIntermTraverser::updateTree()
+{
+    for (size_t ii = 0; ii < mInsertions.size(); ++ii)
+    {
+        const NodeInsertMultipleEntry &insertion = mInsertions[ii];
+        ASSERT(insertion.parent);
+        if (!insertion.insertionsAfter.empty())
+        {
+            bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
+                                                               insertion.insertionsAfter);
+            ASSERT(inserted);
+        }
+        if (!insertion.insertionsBefore.empty())
+        {
+            bool inserted =
+                insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
+            ASSERT(inserted);
+        }
+    }
+    for (size_t ii = 0; ii < mReplacements.size(); ++ii)
+    {
+        const NodeUpdateEntry &replacement = mReplacements[ii];
+        ASSERT(replacement.parent);
+        bool replaced =
+            replacement.parent->replaceChildNode(replacement.original, replacement.replacement);
+        ASSERT(replaced);
+
+        if (!replacement.originalBecomesChildOfReplacement)
+        {
+            // In AST traversing, a parent is visited before its children.
+            // After we replace a node, if its immediate child is to
+            // be replaced, we need to make sure we don't update the replaced
+            // node; instead, we update the replacement node.
+            for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
+            {
+                NodeUpdateEntry &replacement2 = mReplacements[jj];
+                if (replacement2.parent == replacement.original)
+                    replacement2.parent = replacement.replacement;
+            }
+        }
+    }
+    for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
+    {
+        const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
+        ASSERT(replacement.parent);
+        bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original,
+                                                                         replacement.replacements);
+        ASSERT(replaced);
+    }
+
+    clearReplacementQueue();
+}
+
+void TIntermTraverser::clearReplacementQueue()
+{
+    mReplacements.clear();
+    mMultiReplacements.clear();
+    mInsertions.clear();
+}
+
+void TIntermTraverser::queueReplacement(TIntermNode *original,
+                                        TIntermNode *replacement,
+                                        OriginalNode originalStatus)
+{
+    queueReplacementWithParent(getParentNode(), original, replacement, originalStatus);
+}
+
+void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
+                                                  TIntermNode *original,
+                                                  TIntermNode *replacement,
+                                                  OriginalNode originalStatus)
+{
+    bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
+    mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
+}
+
+TName TIntermTraverser::GetInternalFunctionName(const char *name)
+{
+    TString nameStr(name);
+    TName nameObj(nameStr);
+    nameObj.setInternal(true);
+    return nameObj;
+}
+
+TIntermFunctionPrototype *TIntermTraverser::CreateInternalFunctionPrototypeNode(
+    const TType &returnType,
+    const char *name,
+    const TSymbolUniqueId &functionId)
+{
+    TIntermFunctionPrototype *functionNode = new TIntermFunctionPrototype(returnType, functionId);
+    functionNode->getFunctionSymbolInfo()->setNameObj(GetInternalFunctionName(name));
+    return functionNode;
+}
+
+TIntermFunctionDefinition *TIntermTraverser::CreateInternalFunctionDefinitionNode(
+    const TType &returnType,
+    const char *name,
+    TIntermBlock *functionBody,
+    const TSymbolUniqueId &functionId)
+{
+    TIntermFunctionPrototype *prototypeNode =
+        CreateInternalFunctionPrototypeNode(returnType, name, functionId);
+    return new TIntermFunctionDefinition(prototypeNode, functionBody);
+}
+
+TIntermAggregate *TIntermTraverser::CreateInternalFunctionCallNode(
+    const TType &returnType,
+    const char *name,
+    const TSymbolUniqueId &functionId,
+    TIntermSequence *arguments)
+{
+    TIntermAggregate *functionNode = TIntermAggregate::CreateFunctionCall(
+        returnType, functionId, GetInternalFunctionName(name), arguments);
+    return functionNode;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/IntermNode.h b/src/third_party/angle/src/compiler/translator/IntermNode.h
new file mode 100644
index 0000000..ea3f097
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/IntermNode.h
@@ -0,0 +1,1288 @@
+//
+// 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.
+//
+
+//
+// Definition of the in-memory high-level intermediate representation
+// of shaders.  This is a tree that parser creates.
+//
+// Nodes in the tree are defined as a hierarchy of classes derived from
+// TIntermNode. Each is a node in a tree.  There is no preset branching factor;
+// each node can have it's own type of list of children.
+//
+
+#ifndef COMPILER_TRANSLATOR_INTERMNODE_H_
+#define COMPILER_TRANSLATOR_INTERMNODE_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include <algorithm>
+#include <queue>
+
+#include "common/angleutils.h"
+#include "compiler/translator/Common.h"
+#include "compiler/translator/ConstantUnion.h"
+#include "compiler/translator/Operator.h"
+#include "compiler/translator/Types.h"
+
+namespace sh
+{
+
+class TDiagnostics;
+
+class TIntermTraverser;
+class TIntermAggregate;
+class TIntermBlock;
+class TIntermInvariantDeclaration;
+class TIntermDeclaration;
+class TIntermFunctionPrototype;
+class TIntermFunctionDefinition;
+class TIntermSwizzle;
+class TIntermBinary;
+class TIntermUnary;
+class TIntermConstantUnion;
+class TIntermTernary;
+class TIntermIfElse;
+class TIntermSwitch;
+class TIntermCase;
+class TIntermTyped;
+class TIntermSymbol;
+class TIntermLoop;
+class TInfoSink;
+class TInfoSinkBase;
+class TIntermRaw;
+class TIntermBranch;
+
+class TSymbolTable;
+class TSymbolUniqueId;
+class TFunction;
+
+// Encapsulate an identifier string and track whether it is coming from the original shader code
+// (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed.
+class TName
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    explicit TName(const TString &name) : mName(name), mIsInternal(false) {}
+    TName() : mName(), mIsInternal(false) {}
+    TName(const TName &) = default;
+    TName &operator=(const TName &) = default;
+
+    const TString &getString() const { return mName; }
+    void setString(const TString &string) { mName = string; }
+    bool isInternal() const { return mIsInternal; }
+    void setInternal(bool isInternal) { mIsInternal = isInternal; }
+
+  private:
+    TString mName;
+    bool mIsInternal;
+};
+
+//
+// Base class for the tree nodes
+//
+class TIntermNode : angle::NonCopyable
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TIntermNode()
+    {
+        // TODO: Move this to TSourceLoc constructor
+        // after getting rid of TPublicType.
+        mLine.first_file = mLine.last_file = 0;
+        mLine.first_line = mLine.last_line = 0;
+    }
+    virtual ~TIntermNode() {}
+
+    const TSourceLoc &getLine() const { return mLine; }
+    void setLine(const TSourceLoc &l) { mLine = l; }
+
+    virtual void traverse(TIntermTraverser *) = 0;
+    virtual TIntermTyped *getAsTyped() { return 0; }
+    virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
+    virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; }
+    virtual TIntermAggregate *getAsAggregate() { return 0; }
+    virtual TIntermBlock *getAsBlock() { return nullptr; }
+    virtual TIntermFunctionPrototype *getAsFunctionPrototypeNode() { return nullptr; }
+    virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; }
+    virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; }
+    virtual TIntermBinary *getAsBinaryNode() { return 0; }
+    virtual TIntermUnary *getAsUnaryNode() { return 0; }
+    virtual TIntermTernary *getAsTernaryNode() { return nullptr; }
+    virtual TIntermIfElse *getAsIfElseNode() { return nullptr; }
+    virtual TIntermSwitch *getAsSwitchNode() { return 0; }
+    virtual TIntermCase *getAsCaseNode() { return 0; }
+    virtual TIntermSymbol *getAsSymbolNode() { return 0; }
+    virtual TIntermLoop *getAsLoopNode() { return 0; }
+    virtual TIntermRaw *getAsRawNode() { return 0; }
+    virtual TIntermBranch *getAsBranchNode() { return 0; }
+
+    // Replace a child node. Return true if |original| is a child
+    // node and it is replaced; otherwise, return false.
+    virtual bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) = 0;
+
+  protected:
+    TSourceLoc mLine;
+};
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair
+{
+    TIntermNode *node1;
+    TIntermNode *node2;
+};
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode
+{
+  public:
+    TIntermTyped(const TType &t) : mType(t) {}
+
+    virtual TIntermTyped *deepCopy() const = 0;
+
+    TIntermTyped *getAsTyped() override { return this; }
+
+    virtual bool hasSideEffects() const = 0;
+
+    void setType(const TType &t) { mType = t; }
+    void setTypePreservePrecision(const TType &t);
+    const TType &getType() const { return mType; }
+    TType *getTypePointer() { return &mType; }
+
+    TBasicType getBasicType() const { return mType.getBasicType(); }
+    TQualifier getQualifier() const { return mType.getQualifier(); }
+    TPrecision getPrecision() const { return mType.getPrecision(); }
+    TMemoryQualifier getMemoryQualifier() const { return mType.getMemoryQualifier(); }
+    int getCols() const { return mType.getCols(); }
+    int getRows() const { return mType.getRows(); }
+    int getNominalSize() const { return mType.getNominalSize(); }
+    int getSecondarySize() const { return mType.getSecondarySize(); }
+
+    bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
+    bool isMatrix() const { return mType.isMatrix(); }
+    bool isArray() const { return mType.isArray(); }
+    bool isVector() const { return mType.isVector(); }
+    bool isScalar() const { return mType.isScalar(); }
+    bool isScalarInt() const { return mType.isScalarInt(); }
+    const char *getBasicString() const { return mType.getBasicString(); }
+    TString getCompleteString() const { return mType.getCompleteString(); }
+
+    unsigned int getArraySize() const { return mType.getArraySize(); }
+
+    bool isConstructorWithOnlyConstantUnionParameters();
+
+    static TIntermTyped *CreateIndexNode(int index);
+    static TIntermTyped *CreateZero(const TType &type);
+    static TIntermTyped *CreateBool(bool value);
+
+  protected:
+    TType mType;
+
+    TIntermTyped(const TIntermTyped &node);
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+enum TLoopType
+{
+    ELoopFor,
+    ELoopWhile,
+    ELoopDoWhile
+};
+
+class TIntermLoop : public TIntermNode
+{
+  public:
+    TIntermLoop(TLoopType type,
+                TIntermNode *init,
+                TIntermTyped *cond,
+                TIntermTyped *expr,
+                TIntermBlock *body);
+
+    TIntermLoop *getAsLoopNode() override { return this; }
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    TLoopType getType() const { return mType; }
+    TIntermNode *getInit() { return mInit; }
+    TIntermTyped *getCondition() { return mCond; }
+    TIntermTyped *getExpression() { return mExpr; }
+    TIntermBlock *getBody() { return mBody; }
+
+    void setCondition(TIntermTyped *condition) { mCond = condition; }
+    void setExpression(TIntermTyped *expression) { mExpr = expression; }
+    void setBody(TIntermBlock *body) { mBody = body; }
+
+  protected:
+    TLoopType mType;
+    TIntermNode *mInit;   // for-loop initialization
+    TIntermTyped *mCond;  // loop exit condition
+    TIntermTyped *mExpr;  // for-loop expression
+    TIntermBlock *mBody;  // loop body
+};
+
+//
+// Handle break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode
+{
+  public:
+    TIntermBranch(TOperator op, TIntermTyped *e) : mFlowOp(op), mExpression(e) {}
+
+    void traverse(TIntermTraverser *it) override;
+    TIntermBranch *getAsBranchNode() override { return this; }
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    TOperator getFlowOp() { return mFlowOp; }
+    TIntermTyped *getExpression() { return mExpression; }
+
+  protected:
+    TOperator mFlowOp;
+    TIntermTyped *mExpression;  // non-zero except for "return exp;" statements
+};
+
+//
+// Nodes that correspond to symbols or constants in the source code.
+//
+class TIntermSymbol : public TIntermTyped
+{
+  public:
+    // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
+    // If sym comes from per process globalpoolallocator, then it causes increased memory usage
+    // per compile it is essential to use "symbol = sym" to assign to symbol
+    TIntermSymbol(int id, const TString &symbol, const TType &type)
+        : TIntermTyped(type), mId(id), mSymbol(symbol)
+    {
+    }
+
+    TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); }
+
+    bool hasSideEffects() const override { return false; }
+
+    int getId() const { return mId; }
+    const TString &getSymbol() const { return mSymbol.getString(); }
+    const TName &getName() const { return mSymbol; }
+
+    void setId(int newId) { mId = newId; }
+
+    void setInternal(bool internal) { mSymbol.setInternal(internal); }
+
+    void traverse(TIntermTraverser *it) override;
+    TIntermSymbol *getAsSymbolNode() override { return this; }
+    bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
+
+  protected:
+    int mId;
+    TName mSymbol;
+
+  private:
+    TIntermSymbol(const TIntermSymbol &) = default;  // Note: not deleted, just private!
+};
+
+// A Raw node stores raw code, that the translator will insert verbatim
+// into the output stream. Useful for transformation operations that make
+// complex code that might not fit naturally into the GLSL model.
+class TIntermRaw : public TIntermTyped
+{
+  public:
+    TIntermRaw(const TType &type, const TString &rawText) : TIntermTyped(type), mRawText(rawText) {}
+    TIntermRaw(const TIntermRaw &) = delete;
+
+    TIntermTyped *deepCopy() const override
+    {
+        UNREACHABLE();
+        return nullptr;
+    }
+
+    bool hasSideEffects() const override { return false; }
+
+    TString getRawText() const { return mRawText; }
+
+    void traverse(TIntermTraverser *it) override;
+
+    TIntermRaw *getAsRawNode() override { return this; }
+    bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
+
+  protected:
+    TString mRawText;
+};
+
+// Constant folded node.
+// Note that nodes may be constant folded and not be constant expressions with the EvqConst
+// qualifier. This happens for example when the following expression is processed:
+// "true ? 1.0 : non_constant"
+// Other nodes than TIntermConstantUnion may also be constant expressions.
+//
+class TIntermConstantUnion : public TIntermTyped
+{
+  public:
+    TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type)
+        : TIntermTyped(type), mUnionArrayPointer(unionPointer)
+    {
+        ASSERT(unionPointer);
+    }
+
+    TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); }
+
+    bool hasSideEffects() const override { return false; }
+
+    const TConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
+
+    int getIConst(size_t index) const
+    {
+        return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0;
+    }
+    unsigned int getUConst(size_t index) const
+    {
+        return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0;
+    }
+    float getFConst(size_t index) const
+    {
+        return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f;
+    }
+    bool getBConst(size_t index) const
+    {
+        return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
+    }
+
+    void replaceConstantUnion(const TConstantUnion *safeConstantUnion)
+    {
+        ASSERT(safeConstantUnion);
+        // Previous union pointer freed on pool deallocation.
+        mUnionArrayPointer = safeConstantUnion;
+    }
+
+    TIntermConstantUnion *getAsConstantUnion() override { return this; }
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
+
+    TConstantUnion *foldBinary(TOperator op,
+                               TIntermConstantUnion *rightNode,
+                               TDiagnostics *diagnostics,
+                               const TSourceLoc &line);
+    const TConstantUnion *foldIndexing(int index);
+    TConstantUnion *foldUnaryNonComponentWise(TOperator op);
+    TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics);
+
+    static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate);
+    static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate,
+                                                TDiagnostics *diagnostics);
+
+  protected:
+    // Same data may be shared between multiple constant unions, so it can't be modified.
+    const TConstantUnion *mUnionArrayPointer;
+
+  private:
+    typedef float (*FloatTypeUnaryFunc)(float);
+    void foldFloatTypeUnary(const TConstantUnion &parameter,
+                            FloatTypeUnaryFunc builtinFunc,
+                            TConstantUnion *result) const;
+
+    TIntermConstantUnion(const TIntermConstantUnion &node);  // Note: not deleted, just private!
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped
+{
+  public:
+    TOperator getOp() const { return mOp; }
+
+    bool isAssignment() const;
+    bool isMultiplication() const;
+    bool isConstructor() const;
+
+    // Returns true for calls mapped to EOpCall*, false for built-ins that have their own specific
+    // ops.
+    bool isFunctionCall() const;
+
+    bool hasSideEffects() const override { return isAssignment(); }
+
+  protected:
+    TIntermOperator(TOperator op) : TIntermTyped(TType(EbtFloat, EbpUndefined)), mOp(op) {}
+    TIntermOperator(TOperator op, const TType &type) : TIntermTyped(type), mOp(op) {}
+
+    TIntermOperator(const TIntermOperator &) = default;
+
+    const TOperator mOp;
+};
+
+// Node for vector swizzles.
+class TIntermSwizzle : public TIntermTyped
+{
+  public:
+    // This constructor determines the type of the node based on the operand.
+    TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets);
+
+    TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); }
+
+    TIntermSwizzle *getAsSwizzleNode() override { return this; };
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    bool hasSideEffects() const override { return mOperand->hasSideEffects(); }
+
+    TIntermTyped *getOperand() { return mOperand; }
+    void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
+
+    bool hasDuplicateOffsets() const;
+    bool offsetsMatch(int offset) const;
+
+    TIntermTyped *fold();
+
+  protected:
+    TIntermTyped *mOperand;
+    TVector<int> mSwizzleOffsets;
+
+  private:
+    void promote();
+
+    TIntermSwizzle(const TIntermSwizzle &node);  // Note: not deleted, just private!
+};
+
+//
+// Nodes for all the basic binary math operators.
+//
+class TIntermBinary : public TIntermOperator
+{
+  public:
+    // This constructor determines the type of the binary node based on the operands and op.
+    TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right);
+
+    TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
+
+    static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
+    static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
+    static TQualifier GetCommaQualifier(int shaderVersion,
+                                        const TIntermTyped *left,
+                                        const TIntermTyped *right);
+
+    TIntermBinary *getAsBinaryNode() override { return this; };
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    bool hasSideEffects() const override
+    {
+        return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
+    }
+
+    TIntermTyped *getLeft() const { return mLeft; }
+    TIntermTyped *getRight() const { return mRight; }
+    TIntermTyped *fold(TDiagnostics *diagnostics);
+
+    void setAddIndexClamp() { mAddIndexClamp = true; }
+    bool getAddIndexClamp() { return mAddIndexClamp; }
+
+  protected:
+    TIntermTyped *mLeft;
+    TIntermTyped *mRight;
+
+    // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
+    bool mAddIndexClamp;
+
+  private:
+    void promote();
+
+    TIntermBinary(const TIntermBinary &node);  // Note: not deleted, just private!
+};
+
+//
+// Nodes for unary math operators.
+//
+class TIntermUnary : public TIntermOperator
+{
+  public:
+    TIntermUnary(TOperator op, TIntermTyped *operand);
+
+    TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
+
+    void traverse(TIntermTraverser *it) override;
+    TIntermUnary *getAsUnaryNode() override { return this; }
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
+
+    TIntermTyped *getOperand() { return mOperand; }
+    TIntermTyped *fold(TDiagnostics *diagnostics);
+
+    void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
+    bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
+
+  protected:
+    TIntermTyped *mOperand;
+
+    // If set to true, replace the built-in function call with an emulated one
+    // to work around driver bugs.
+    bool mUseEmulatedFunction;
+
+  private:
+    void promote();
+
+    TIntermUnary(const TIntermUnary &node);  // note: not deleted, just private!
+};
+
+class TFunctionSymbolInfo
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TFunctionSymbolInfo(const TSymbolUniqueId &id);
+    TFunctionSymbolInfo() : mId(nullptr) {}
+
+    TFunctionSymbolInfo(const TFunctionSymbolInfo &info);
+    TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &info);
+
+    void setFromFunction(const TFunction &function);
+
+    void setNameObj(const TName &name) { mName = name; }
+    const TName &getNameObj() const { return mName; }
+
+    const TString &getName() const { return mName.getString(); }
+    void setName(const TString &name) { mName.setString(name); }
+    bool isMain() const { return mName.getString() == "main"; }
+
+    void setId(const TSymbolUniqueId &functionId);
+    const TSymbolUniqueId &getId() const;
+
+  private:
+    TName mName;
+    TSymbolUniqueId *mId;
+};
+
+typedef TVector<TIntermNode *> TIntermSequence;
+typedef TVector<int> TQualifierList;
+
+//
+// This is just to help yacc.
+//
+struct TIntermFunctionCallOrMethod
+{
+    TIntermSequence *arguments;
+    TIntermNode *thisNode;
+};
+
+// Interface for node classes that have an arbitrarily sized set of children.
+class TIntermAggregateBase
+{
+  public:
+    virtual ~TIntermAggregateBase() {}
+
+    virtual TIntermSequence *getSequence()             = 0;
+    virtual const TIntermSequence *getSequence() const = 0;
+
+    bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements);
+    bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions);
+
+  protected:
+    TIntermAggregateBase() {}
+
+    bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement);
+};
+
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
+{
+  public:
+    static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments);
+
+    // If using this, ensure that there's a consistent function definition with the same symbol id
+    // added to the AST.
+    static TIntermAggregate *CreateFunctionCall(const TType &type,
+                                                const TSymbolUniqueId &id,
+                                                const TName &name,
+                                                TIntermSequence *arguments);
+
+    static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
+                                                       TIntermSequence *arguments);
+    static TIntermAggregate *CreateConstructor(const TType &type,
+                                               TIntermSequence *arguments);
+    static TIntermAggregate *Create(const TType &type, TOperator op, TIntermSequence *arguments);
+    ~TIntermAggregate() {}
+
+    // Note: only supported for nodes that can be a part of an expression.
+    TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
+
+    TIntermAggregate *shallowCopy() const;
+
+    TIntermAggregate *getAsAggregate() override { return this; }
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    // Conservatively assume function calls and other aggregate operators have side-effects
+    bool hasSideEffects() const override { return true; }
+    TIntermTyped *fold(TDiagnostics *diagnostics);
+
+    TIntermSequence *getSequence() override { return &mArguments; }
+    const TIntermSequence *getSequence() const override { return &mArguments; }
+
+    TString getSymbolTableMangledName() const;
+
+    void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
+    bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
+
+    // Returns true if changing parameter precision may affect the return value.
+    bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; }
+
+    TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
+    const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
+
+  protected:
+    TIntermSequence mArguments;
+
+    // If set to true, replace the built-in function call with an emulated one
+    // to work around driver bugs. Only for calls mapped to ops other than EOpCall*.
+    bool mUseEmulatedFunction;
+
+    bool mGotPrecisionFromChildren;
+
+    TFunctionSymbolInfo mFunctionInfo;
+
+  private:
+    TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments);
+
+    TIntermAggregate(const TIntermAggregate &node);  // note: not deleted, just private!
+
+    void setTypePrecisionAndQualifier(const TType &type);
+
+    bool areChildrenConstQualified();
+
+    void setPrecisionFromChildren();
+
+    void setPrecisionForBuiltInOp();
+
+    // Returns true if precision was set according to special rules for this built-in.
+    bool setPrecisionForSpecialBuiltInOp();
+
+    // Used for built-in functions under EOpCallBuiltInFunction. The function name in the symbol
+    // info needs to be set before calling this.
+    void setBuiltInFunctionPrecision();
+};
+
+// A list of statements. Either the root node which contains declarations and function definitions,
+// or a block that can be marked with curly braces {}.
+class TIntermBlock : public TIntermNode, public TIntermAggregateBase
+{
+  public:
+    TIntermBlock() : TIntermNode() {}
+    ~TIntermBlock() {}
+
+    TIntermBlock *getAsBlock() override { return this; }
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    // Only intended for initially building the block.
+    void appendStatement(TIntermNode *statement);
+
+    TIntermSequence *getSequence() override { return &mStatements; }
+    const TIntermSequence *getSequence() const override { return &mStatements; }
+
+  protected:
+    TIntermSequence mStatements;
+};
+
+// Function prototype. May be in the AST either as a function prototype declaration or as a part of
+// a function definition. The type of the node is the function return type.
+class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase
+{
+  public:
+    // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor
+    // parameters.
+    TIntermFunctionPrototype(const TType &type, const TSymbolUniqueId &id)
+        : TIntermTyped(type), mFunctionInfo(id)
+    {
+    }
+    ~TIntermFunctionPrototype() {}
+
+    TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    TIntermTyped *deepCopy() const override
+    {
+        UNREACHABLE();
+        return nullptr;
+    }
+    bool hasSideEffects() const override
+    {
+        UNREACHABLE();
+        return true;
+    }
+
+    // Only intended for initially building the declaration.
+    void appendParameter(TIntermSymbol *parameter);
+
+    TIntermSequence *getSequence() override { return &mParameters; }
+    const TIntermSequence *getSequence() const override { return &mParameters; }
+
+    TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
+    const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
+
+  protected:
+    TIntermSequence mParameters;
+
+    TFunctionSymbolInfo mFunctionInfo;
+};
+
+// Node for function definitions. The prototype child node stores the function header including
+// parameters, and the body child node stores the function body.
+class TIntermFunctionDefinition : public TIntermNode
+{
+  public:
+    TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body)
+        : TIntermNode(), mPrototype(prototype), mBody(body)
+    {
+        ASSERT(prototype != nullptr);
+        ASSERT(body != nullptr);
+    }
+
+    TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
+    TIntermBlock *getBody() const { return mBody; }
+
+    const TFunctionSymbolInfo *getFunctionSymbolInfo() const
+    {
+        return mPrototype->getFunctionSymbolInfo();
+    }
+
+  private:
+    TIntermFunctionPrototype *mPrototype;
+    TIntermBlock *mBody;
+};
+
+// Struct, interface block or variable declaration. Can contain multiple variable declarators.
+class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
+{
+  public:
+    TIntermDeclaration() : TIntermNode() {}
+    ~TIntermDeclaration() {}
+
+    TIntermDeclaration *getAsDeclarationNode() override { return this; }
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    // Only intended for initially building the declaration.
+    // The declarator node should be either TIntermSymbol or TIntermBinary with op set to
+    // EOpInitialize.
+    void appendDeclarator(TIntermTyped *declarator);
+
+    TIntermSequence *getSequence() override { return &mDeclarators; }
+    const TIntermSequence *getSequence() const override { return &mDeclarators; }
+  protected:
+    TIntermSequence mDeclarators;
+};
+
+// Specialized declarations for attributing invariance.
+class TIntermInvariantDeclaration : public TIntermNode
+{
+  public:
+    TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line);
+
+    TIntermSymbol *getSymbol() { return mSymbol; }
+
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+  private:
+    TIntermSymbol *mSymbol;
+};
+
+// For ternary operators like a ? b : c.
+class TIntermTernary : public TIntermTyped
+{
+  public:
+    TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression);
+
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    TIntermTyped *getCondition() const { return mCondition; }
+    TIntermTyped *getTrueExpression() const { return mTrueExpression; }
+    TIntermTyped *getFalseExpression() const { return mFalseExpression; }
+    TIntermTernary *getAsTernaryNode() override { return this; }
+
+    TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); }
+
+    bool hasSideEffects() const override
+    {
+        return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() ||
+               mFalseExpression->hasSideEffects();
+    }
+
+    static TQualifier DetermineQualifier(TIntermTyped *cond,
+                                         TIntermTyped *trueExpression,
+                                         TIntermTyped *falseExpression);
+
+  private:
+    TIntermTernary(const TIntermTernary &node);  // Note: not deleted, just private!
+
+    TIntermTyped *mCondition;
+    TIntermTyped *mTrueExpression;
+    TIntermTyped *mFalseExpression;
+};
+
+class TIntermIfElse : public TIntermNode
+{
+  public:
+    TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB)
+        : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB)
+    {
+    }
+
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    TIntermTyped *getCondition() const { return mCondition; }
+    TIntermBlock *getTrueBlock() const { return mTrueBlock; }
+    TIntermBlock *getFalseBlock() const { return mFalseBlock; }
+    TIntermIfElse *getAsIfElseNode() override { return this; }
+
+  protected:
+    TIntermTyped *mCondition;
+    TIntermBlock *mTrueBlock;
+    TIntermBlock *mFalseBlock;
+};
+
+//
+// Switch statement.
+//
+class TIntermSwitch : public TIntermNode
+{
+  public:
+    TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList)
+        : TIntermNode(), mInit(init), mStatementList(statementList)
+    {
+    }
+
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    TIntermSwitch *getAsSwitchNode() override { return this; }
+
+    TIntermTyped *getInit() { return mInit; }
+    TIntermBlock *getStatementList() { return mStatementList; }
+    void setStatementList(TIntermBlock *statementList) { mStatementList = statementList; }
+
+  protected:
+    TIntermTyped *mInit;
+    TIntermBlock *mStatementList;
+};
+
+//
+// Case label.
+//
+class TIntermCase : public TIntermNode
+{
+  public:
+    TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {}
+
+    void traverse(TIntermTraverser *it) override;
+    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+    TIntermCase *getAsCaseNode() override { return this; }
+
+    bool hasCondition() const { return mCondition != nullptr; }
+    TIntermTyped *getCondition() const { return mCondition; }
+
+  protected:
+    TIntermTyped *mCondition;
+};
+
+enum Visit
+{
+    PreVisit,
+    InVisit,
+    PostVisit
+};
+
+//
+// For traversing the tree.  User should derive from this class overriding the visit functions,
+// and then pass an object of the subclass to a traverse method of a node.
+//
+// The traverse*() functions may also be overridden do other bookkeeping on the tree to provide
+// contextual information to the visit functions, such as whether the node is the target of an
+// assignment.
+//
+// When using this, just fill in the methods for nodes you want visited.
+// Return false from a pre-visit to skip visiting that node's subtree.
+//
+class TIntermTraverser : angle::NonCopyable
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TIntermTraverser(bool preVisit, bool inVisit, bool postVisit);
+    virtual ~TIntermTraverser();
+
+    virtual void visitSymbol(TIntermSymbol *node) {}
+    virtual void visitRaw(TIntermRaw *node) {}
+    virtual void visitConstantUnion(TIntermConstantUnion *node) {}
+    virtual bool visitSwizzle(Visit visit, TIntermSwizzle *node) { return true; }
+    virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; }
+    virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; }
+    virtual bool visitTernary(Visit visit, TIntermTernary *node) { return true; }
+    virtual bool visitIfElse(Visit visit, TIntermIfElse *node) { return true; }
+    virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; }
+    virtual bool visitCase(Visit visit, TIntermCase *node) { return true; }
+    virtual bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+    {
+        return true;
+    }
+    virtual bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+    {
+        return true;
+    }
+    virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; }
+    virtual bool visitBlock(Visit visit, TIntermBlock *node) { return true; }
+    virtual bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+    {
+        return true;
+    }
+    virtual bool visitDeclaration(Visit visit, TIntermDeclaration *node) { return true; }
+    virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; }
+    virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; }
+
+    // The traverse functions contain logic for iterating over the children of the node
+    // and calling the visit functions in the appropriate places. They also track some
+    // context that may be used by the visit functions.
+    virtual void traverseSymbol(TIntermSymbol *node);
+    virtual void traverseRaw(TIntermRaw *node);
+    virtual void traverseConstantUnion(TIntermConstantUnion *node);
+    virtual void traverseSwizzle(TIntermSwizzle *node);
+    virtual void traverseBinary(TIntermBinary *node);
+    virtual void traverseUnary(TIntermUnary *node);
+    virtual void traverseTernary(TIntermTernary *node);
+    virtual void traverseIfElse(TIntermIfElse *node);
+    virtual void traverseSwitch(TIntermSwitch *node);
+    virtual void traverseCase(TIntermCase *node);
+    virtual void traverseFunctionPrototype(TIntermFunctionPrototype *node);
+    virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node);
+    virtual void traverseAggregate(TIntermAggregate *node);
+    virtual void traverseBlock(TIntermBlock *node);
+    virtual void traverseInvariantDeclaration(TIntermInvariantDeclaration *node);
+    virtual void traverseDeclaration(TIntermDeclaration *node);
+    virtual void traverseLoop(TIntermLoop *node);
+    virtual void traverseBranch(TIntermBranch *node);
+
+    int getMaxDepth() const { return mMaxDepth; }
+
+    // Return the original name if hash function pointer is NULL;
+    // otherwise return the hashed name.
+    static TString hash(const TString &name, ShHashFunction64 hashFunction);
+
+    // If traversers need to replace nodes, they can add the replacements in
+    // mReplacements/mMultiReplacements during traversal and the user of the traverser should call
+    // this function after traversal to perform them.
+    void updateTree();
+
+    // Start creating temporary symbols from the given temporary symbol index + 1.
+    void useTemporaryIndex(unsigned int *temporaryIndex);
+
+    static TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(
+        const TType &returnType,
+        const char *name,
+        const TSymbolUniqueId &functionId);
+    static TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(
+        const TType &returnType,
+        const char *name,
+        TIntermBlock *functionBody,
+        const TSymbolUniqueId &functionId);
+    static TIntermAggregate *CreateInternalFunctionCallNode(const TType &returnType,
+                                                            const char *name,
+                                                            const TSymbolUniqueId &functionId,
+                                                            TIntermSequence *arguments);
+
+  protected:
+    // Should only be called from traverse*() functions
+    void incrementDepth(TIntermNode *current)
+    {
+        mDepth++;
+        mMaxDepth = std::max(mMaxDepth, mDepth);
+        mPath.push_back(current);
+    }
+
+    // Should only be called from traverse*() functions
+    void decrementDepth()
+    {
+        mDepth--;
+        mPath.pop_back();
+    }
+
+    // RAII helper for incrementDepth/decrementDepth
+    class ScopedNodeInTraversalPath
+    {
+      public:
+        ScopedNodeInTraversalPath(TIntermTraverser *traverser, TIntermNode *current)
+            : mTraverser(traverser)
+        {
+            mTraverser->incrementDepth(current);
+        }
+        ~ScopedNodeInTraversalPath() { mTraverser->decrementDepth(); }
+      private:
+        TIntermTraverser *mTraverser;
+    };
+
+    TIntermNode *getParentNode() { return mPath.size() <= 1 ? nullptr : mPath[mPath.size() - 2u]; }
+
+    // Return the nth ancestor of the node being traversed. getAncestorNode(0) == getParentNode()
+    TIntermNode *getAncestorNode(unsigned int n)
+    {
+        if (mPath.size() > n + 1u)
+        {
+            return mPath[mPath.size() - n - 2u];
+        }
+        return nullptr;
+    }
+
+    void pushParentBlock(TIntermBlock *node);
+    void incrementParentBlockPos();
+    void popParentBlock();
+
+    // To replace a single node with multiple nodes on the parent aggregate node
+    struct NodeReplaceWithMultipleEntry
+    {
+        NodeReplaceWithMultipleEntry(TIntermAggregateBase *_parent,
+                                     TIntermNode *_original,
+                                     TIntermSequence _replacements)
+            : parent(_parent), original(_original), replacements(_replacements)
+        {
+        }
+
+        TIntermAggregateBase *parent;
+        TIntermNode *original;
+        TIntermSequence replacements;
+    };
+
+    // To insert multiple nodes on the parent aggregate node
+    struct NodeInsertMultipleEntry
+    {
+        NodeInsertMultipleEntry(TIntermBlock *_parent,
+                                TIntermSequence::size_type _position,
+                                TIntermSequence _insertionsBefore,
+                                TIntermSequence _insertionsAfter)
+            : parent(_parent),
+              position(_position),
+              insertionsBefore(_insertionsBefore),
+              insertionsAfter(_insertionsAfter)
+        {
+        }
+
+        TIntermBlock *parent;
+        TIntermSequence::size_type position;
+        TIntermSequence insertionsBefore;
+        TIntermSequence insertionsAfter;
+    };
+
+    // Helper to insert statements in the parent block (sequence) of the node currently being
+    // traversed.
+    // The statements will be inserted before the node being traversed once updateTree is called.
+    // Should only be called during PreVisit or PostVisit from sequence nodes.
+    // Note that inserting more than one set of nodes to the same parent node on a single updateTree
+    // call is not
+    // supported.
+    void insertStatementsInParentBlock(const TIntermSequence &insertions);
+
+    // Same as above, but supports simultaneous insertion of statements before and after the node
+    // currently being traversed.
+    void insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
+                                       const TIntermSequence &insertionsAfter);
+
+    // Helper to insert a single statement.
+    void insertStatementInParentBlock(TIntermNode *statement);
+
+    // Helper to create a temporary symbol node with the given qualifier.
+    TIntermSymbol *createTempSymbol(const TType &type, TQualifier qualifier);
+    // Helper to create a temporary symbol node.
+    TIntermSymbol *createTempSymbol(const TType &type);
+    // Create a node that declares but doesn't initialize a temporary symbol.
+    TIntermDeclaration *createTempDeclaration(const TType &type);
+    // Create a node that initializes the current temporary symbol with initializer having the given
+    // qualifier.
+    TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
+    // Create a node that initializes the current temporary symbol with initializer.
+    TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer);
+    // Create a node that assigns rightNode to the current temporary symbol.
+    TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
+    // Increment temporary symbol index.
+    void nextTemporaryIndex();
+
+    enum class OriginalNode
+    {
+        BECOMES_CHILD,
+        IS_DROPPED
+    };
+
+    void clearReplacementQueue();
+    void queueReplacement(TIntermNode *original,
+                          TIntermNode *replacement,
+                          OriginalNode originalStatus);
+    void queueReplacementWithParent(TIntermNode *parent,
+                                    TIntermNode *original,
+                                    TIntermNode *replacement,
+                                    OriginalNode originalStatus);
+
+    const bool preVisit;
+    const bool inVisit;
+    const bool postVisit;
+
+    int mDepth;
+    int mMaxDepth;
+
+    bool mInGlobalScope;
+
+    // During traversing, save all the changes that need to happen into
+    // mReplacements/mMultiReplacements, then do them by calling updateTree().
+    // Multi replacements are processed after single replacements.
+    std::vector<NodeReplaceWithMultipleEntry> mMultiReplacements;
+    std::vector<NodeInsertMultipleEntry> mInsertions;
+
+  private:
+    static TName GetInternalFunctionName(const char *name);
+
+    // To replace a single node with another on the parent node
+    struct NodeUpdateEntry
+    {
+        NodeUpdateEntry(TIntermNode *_parent,
+                        TIntermNode *_original,
+                        TIntermNode *_replacement,
+                        bool _originalBecomesChildOfReplacement)
+            : parent(_parent),
+              original(_original),
+              replacement(_replacement),
+              originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement)
+        {
+        }
+
+        TIntermNode *parent;
+        TIntermNode *original;
+        TIntermNode *replacement;
+        bool originalBecomesChildOfReplacement;
+    };
+
+    struct ParentBlock
+    {
+        ParentBlock(TIntermBlock *nodeIn, TIntermSequence::size_type posIn)
+            : node(nodeIn), pos(posIn)
+        {
+        }
+
+        TIntermBlock *node;
+        TIntermSequence::size_type pos;
+    };
+
+    std::vector<NodeUpdateEntry> mReplacements;
+
+    // All the nodes from root to the current node during traversing.
+    TVector<TIntermNode *> mPath;
+
+    // All the code blocks from the root to the current node's parent during traversal.
+    std::vector<ParentBlock> mParentBlockStack;
+
+    unsigned int *mTemporaryIndex;
+};
+
+// Traverser parent class that tracks where a node is a destination of a write operation and so is
+// required to be an l-value.
+class TLValueTrackingTraverser : public TIntermTraverser
+{
+  public:
+    TLValueTrackingTraverser(bool preVisit,
+                             bool inVisit,
+                             bool postVisit,
+                             const TSymbolTable &symbolTable,
+                             int shaderVersion)
+        : TIntermTraverser(preVisit, inVisit, postVisit),
+          mOperatorRequiresLValue(false),
+          mInFunctionCallOutParameter(false),
+          mSymbolTable(symbolTable),
+          mShaderVersion(shaderVersion)
+    {
+    }
+    virtual ~TLValueTrackingTraverser() {}
+
+    void traverseBinary(TIntermBinary *node) final;
+    void traverseUnary(TIntermUnary *node) final;
+    void traverseFunctionPrototype(TIntermFunctionPrototype *node) final;
+    void traverseAggregate(TIntermAggregate *node) final;
+
+  protected:
+    bool isLValueRequiredHere() const
+    {
+        return mOperatorRequiresLValue || mInFunctionCallOutParameter;
+    }
+
+  private:
+    // Track whether an l-value is required in the node that is currently being traversed by the
+    // surrounding operator.
+    // Use isLValueRequiredHere to check all conditions which require an l-value.
+    void setOperatorRequiresLValue(bool lValueRequired)
+    {
+        mOperatorRequiresLValue = lValueRequired;
+    }
+    bool operatorRequiresLValue() const { return mOperatorRequiresLValue; }
+
+    // Add a function encountered during traversal to the function map.
+    void addToFunctionMap(const TSymbolUniqueId &id, TIntermSequence *paramSequence);
+
+    // Return true if the prototype or definition of the function being called has been encountered
+    // during traversal.
+    bool isInFunctionMap(const TIntermAggregate *callNode) const;
+
+    // Return the parameters sequence from the function definition or prototype.
+    TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode);
+
+    // Track whether an l-value is required inside a function call.
+    void setInFunctionCallOutParameter(bool inOutParameter);
+    bool isInFunctionCallOutParameter() const;
+
+    bool mOperatorRequiresLValue;
+    bool mInFunctionCallOutParameter;
+
+    // Map from function symbol id values to their parameter sequences
+    TMap<int, TIntermSequence *> mFunctionMap;
+
+    const TSymbolTable &mSymbolTable;
+    const int mShaderVersion;
+};
+
+//
+// For traversing the tree, and computing max depth.
+// Takes a maximum depth limit to prevent stack overflow.
+//
+class TMaxDepthTraverser : public TIntermTraverser
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TMaxDepthTraverser(int depthLimit)
+        : TIntermTraverser(true, true, false), mDepthLimit(depthLimit)
+    {
+    }
+
+    bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); }
+    bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); }
+    bool visitTernary(Visit, TIntermTernary *) override { return depthCheck(); }
+    bool visitIfElse(Visit, TIntermIfElse *) override { return depthCheck(); }
+    bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); }
+    bool visitBlock(Visit, TIntermBlock *) override { return depthCheck(); }
+    bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); }
+    bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); }
+
+  protected:
+    bool depthCheck() const { return mMaxDepth < mDepthLimit; }
+
+    int mDepthLimit;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_INTERMNODE_H_
diff --git a/src/third_party/angle/src/compiler/translator/IntermNodePatternMatcher.cpp b/src/third_party/angle/src/compiler/translator/IntermNodePatternMatcher.cpp
new file mode 100644
index 0000000..bc0847d
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/IntermNodePatternMatcher.cpp
@@ -0,0 +1,117 @@
+//
+// Copyright (c) 2016 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.
+//
+// IntermNodePatternMatcher is a helper class for matching node trees to given patterns.
+// It can be used whenever the same checks for certain node structures are common to multiple AST
+// traversers.
+//
+
+#include "compiler/translator/IntermNodePatternMatcher.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask)
+{
+}
+
+// static
+bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
+{
+    return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
+           node->getLeft()->getBasicType() != EbtStruct;
+}
+
+bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
+{
+    if ((mMask & kExpressionReturningArray) != 0)
+    {
+        if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
+            !parentNode->getAsBlock())
+        {
+            return true;
+        }
+    }
+
+    if ((mMask & kUnfoldedShortCircuitExpression) != 0)
+    {
+        if (node->getRight()->hasSideEffects() &&
+            (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
+{
+    // L-value tracking information is needed to check for dynamic indexing in L-value.
+    // Traversers that don't track l-values can still use this class and match binary nodes with
+    // this variation of this method if they don't need to check for dynamic indexing in l-values.
+    ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
+    return matchInternal(node, parentNode);
+}
+
+bool IntermNodePatternMatcher::match(TIntermBinary *node,
+                                     TIntermNode *parentNode,
+                                     bool isLValueRequiredHere)
+{
+    if (matchInternal(node, parentNode))
+    {
+        return true;
+    }
+    if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
+    {
+        if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
+{
+    if ((mMask & kExpressionReturningArray) != 0)
+    {
+        if (parentNode != nullptr)
+        {
+            TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
+            bool parentIsAssignment =
+                (parentBinary != nullptr &&
+                 (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
+
+            if (node->getType().isArray() && !parentIsAssignment &&
+                (node->isConstructor() || node->isFunctionCall()) && !parentNode->getAsBlock())
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool IntermNodePatternMatcher::match(TIntermTernary *node)
+{
+    if ((mMask & kUnfoldedShortCircuitExpression) != 0)
+    {
+        return true;
+    }
+    return false;
+}
+
+bool IntermNodePatternMatcher::match(TIntermDeclaration *node)
+{
+    if ((mMask & kMultiDeclaration) != 0)
+    {
+        return node->getSequence()->size() > 1;
+    }
+    return false;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/IntermNodePatternMatcher.h b/src/third_party/angle/src/compiler/translator/IntermNodePatternMatcher.h
new file mode 100644
index 0000000..c156100
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/IntermNodePatternMatcher.h
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2016 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.
+//
+// IntermNodePatternMatcher is a helper class for matching node trees to given patterns.
+// It can be used whenever the same checks for certain node structures are common to multiple AST
+// traversers.
+//
+
+#ifndef COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_
+#define COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_
+
+namespace sh
+{
+
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermNode;
+class TIntermTernary;
+class TIntermDeclaration;
+
+class IntermNodePatternMatcher
+{
+  public:
+    static bool IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node);
+
+    enum PatternType
+    {
+        // Matches expressions that are unfolded to if statements by UnfoldShortCircuitToIf
+        kUnfoldedShortCircuitExpression = 0x0001,
+
+        // Matches expressions that return arrays with the exception of simple statements where a
+        // constructor or function call result is assigned.
+        kExpressionReturningArray = 0x0002,
+
+        // Matches dynamic indexing of vectors or matrices in l-values.
+        kDynamicIndexingOfVectorOrMatrixInLValue = 0x0004,
+
+        // Matches declarations with more than one declared variables
+        kMultiDeclaration = 0x0008,
+    };
+    IntermNodePatternMatcher(const unsigned int mask);
+
+    bool match(TIntermBinary *node, TIntermNode *parentNode);
+
+    // Use this version for checking binary node matches in case you're using flag
+    // kDynamicIndexingOfVectorOrMatrixInLValue.
+    bool match(TIntermBinary *node, TIntermNode *parentNode, bool isLValueRequiredHere);
+
+    bool match(TIntermAggregate *node, TIntermNode *parentNode);
+    bool match(TIntermTernary *node);
+    bool match(TIntermDeclaration *node);
+
+  private:
+    const unsigned int mMask;
+
+    bool matchInternal(TIntermBinary *node, TIntermNode *parentNode);
+};
+
+}  // namespace sh
+
+#endif
diff --git a/src/third_party/angle/src/compiler/translator/IntermTraverse.cpp b/src/third_party/angle/src/compiler/translator/IntermTraverse.cpp
new file mode 100644
index 0000000..1819ab8
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/IntermTraverse.cpp
@@ -0,0 +1,878 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+void TIntermSymbol::traverse(TIntermTraverser *it)
+{
+    it->traverseSymbol(this);
+}
+
+void TIntermRaw::traverse(TIntermTraverser *it)
+{
+    it->traverseRaw(this);
+}
+
+void TIntermConstantUnion::traverse(TIntermTraverser *it)
+{
+    it->traverseConstantUnion(this);
+}
+
+void TIntermSwizzle::traverse(TIntermTraverser *it)
+{
+    it->traverseSwizzle(this);
+}
+
+void TIntermBinary::traverse(TIntermTraverser *it)
+{
+    it->traverseBinary(this);
+}
+
+void TIntermUnary::traverse(TIntermTraverser *it)
+{
+    it->traverseUnary(this);
+}
+
+void TIntermTernary::traverse(TIntermTraverser *it)
+{
+    it->traverseTernary(this);
+}
+
+void TIntermIfElse::traverse(TIntermTraverser *it)
+{
+    it->traverseIfElse(this);
+}
+
+void TIntermSwitch::traverse(TIntermTraverser *it)
+{
+    it->traverseSwitch(this);
+}
+
+void TIntermCase::traverse(TIntermTraverser *it)
+{
+    it->traverseCase(this);
+}
+
+void TIntermFunctionDefinition::traverse(TIntermTraverser *it)
+{
+    it->traverseFunctionDefinition(this);
+}
+
+void TIntermBlock::traverse(TIntermTraverser *it)
+{
+    it->traverseBlock(this);
+}
+
+void TIntermInvariantDeclaration::traverse(TIntermTraverser *it)
+{
+    it->traverseInvariantDeclaration(this);
+}
+
+void TIntermDeclaration::traverse(TIntermTraverser *it)
+{
+    it->traverseDeclaration(this);
+}
+
+void TIntermFunctionPrototype::traverse(TIntermTraverser *it)
+{
+    it->traverseFunctionPrototype(this);
+}
+
+void TIntermAggregate::traverse(TIntermTraverser *it)
+{
+    it->traverseAggregate(this);
+}
+
+void TIntermLoop::traverse(TIntermTraverser *it)
+{
+    it->traverseLoop(this);
+}
+
+void TIntermBranch::traverse(TIntermTraverser *it)
+{
+    it->traverseBranch(this);
+}
+
+TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
+    : preVisit(preVisit),
+      inVisit(inVisit),
+      postVisit(postVisit),
+      mDepth(-1),
+      mMaxDepth(0),
+      mInGlobalScope(true),
+      mTemporaryIndex(nullptr)
+{
+}
+
+TIntermTraverser::~TIntermTraverser()
+{
+}
+
+void TIntermTraverser::pushParentBlock(TIntermBlock *node)
+{
+    mParentBlockStack.push_back(ParentBlock(node, 0));
+}
+
+void TIntermTraverser::incrementParentBlockPos()
+{
+    ++mParentBlockStack.back().pos;
+}
+
+void TIntermTraverser::popParentBlock()
+{
+    ASSERT(!mParentBlockStack.empty());
+    mParentBlockStack.pop_back();
+}
+
+void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
+{
+    TIntermSequence emptyInsertionsAfter;
+    insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
+}
+
+void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
+                                                     const TIntermSequence &insertionsAfter)
+{
+    ASSERT(!mParentBlockStack.empty());
+    ParentBlock &parentBlock = mParentBlockStack.back();
+    if (mPath.back() == parentBlock.node)
+    {
+        ASSERT(mParentBlockStack.size() >= 2u);
+        // The current node is a block node, so the parent block is not the topmost one in the block
+        // stack, but the one below that.
+        parentBlock = mParentBlockStack.at(mParentBlockStack.size() - 2u);
+    }
+    NodeInsertMultipleEntry insert(parentBlock.node, parentBlock.pos, insertionsBefore,
+                                   insertionsAfter);
+    mInsertions.push_back(insert);
+}
+
+void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
+{
+    TIntermSequence insertions;
+    insertions.push_back(statement);
+    insertStatementsInParentBlock(insertions);
+}
+
+TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
+{
+    // Each traversal uses at most one temporary variable, so the index stays the same within a
+    // single traversal.
+    TInfoSinkBase symbolNameOut;
+    ASSERT(mTemporaryIndex != nullptr);
+    symbolNameOut << "s" << (*mTemporaryIndex);
+    TString symbolName = symbolNameOut.c_str();
+
+    TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
+    node->setInternal(true);
+
+    ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
+    node->getTypePointer()->setQualifier(qualifier);
+    // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created
+    // symbol. This might need to be done in other places as well.
+    return node;
+}
+
+TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
+{
+    return createTempSymbol(type, EvqTemporary);
+}
+
+TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
+{
+    TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
+    tempDeclaration->appendDeclarator(createTempSymbol(type));
+    return tempDeclaration;
+}
+
+TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
+                                                                TQualifier qualifier)
+{
+    ASSERT(initializer != nullptr);
+    TIntermSymbol *tempSymbol           = createTempSymbol(initializer->getType(), qualifier);
+    TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
+    TIntermBinary *tempInit             = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
+    tempDeclaration->appendDeclarator(tempInit);
+    return tempDeclaration;
+}
+
+TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
+{
+    return createTempInitDeclaration(initializer, EvqTemporary);
+}
+
+TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
+{
+    ASSERT(rightNode != nullptr);
+    TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
+    TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
+    return assignment;
+}
+
+void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
+{
+    mTemporaryIndex = temporaryIndex;
+}
+
+void TIntermTraverser::nextTemporaryIndex()
+{
+    ASSERT(mTemporaryIndex != nullptr);
+    ++(*mTemporaryIndex);
+}
+
+void TLValueTrackingTraverser::addToFunctionMap(const TSymbolUniqueId &id,
+                                                TIntermSequence *paramSequence)
+{
+    mFunctionMap[id.get()] = paramSequence;
+}
+
+bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
+{
+    ASSERT(callNode->getOp() == EOpCallFunctionInAST);
+    return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getId().get()) !=
+            mFunctionMap.end());
+}
+
+TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
+{
+    ASSERT(isInFunctionMap(callNode));
+    return mFunctionMap[callNode->getFunctionSymbolInfo()->getId().get()];
+}
+
+void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
+{
+    mInFunctionCallOutParameter = inOutParameter;
+}
+
+bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
+{
+    return mInFunctionCallOutParameter;
+}
+
+//
+// Traverse the intermediate representation tree, and
+// call a node type specific function for each node.
+// Done recursively through the member function Traverse().
+// Node types can be skipped if their function to call is 0,
+// but their subtree will still be traversed.
+// Nodes with children can have their whole subtree skipped
+// if preVisit is turned on and the type specific function
+// returns false.
+//
+
+//
+// Traversal functions for terminals are straighforward....
+//
+void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+    visitSymbol(node);
+}
+
+void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+    visitConstantUnion(node);
+}
+
+void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitSwizzle(PreVisit, node);
+
+    if (visit)
+    {
+        node->getOperand()->traverse(this);
+    }
+
+    if (visit && postVisit)
+        visitSwizzle(PostVisit, node);
+}
+
+//
+// Traverse a binary node.
+//
+void TIntermTraverser::traverseBinary(TIntermBinary *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    //
+    // visit the node before children if pre-visiting.
+    //
+    if (preVisit)
+        visit = visitBinary(PreVisit, node);
+
+    //
+    // Visit the children, in the right order.
+    //
+    if (visit)
+    {
+        if (node->getLeft())
+            node->getLeft()->traverse(this);
+
+        if (inVisit)
+            visit = visitBinary(InVisit, node);
+
+        if (visit && node->getRight())
+            node->getRight()->traverse(this);
+    }
+
+    //
+    // Visit the node after the children, if requested and the traversal
+    // hasn't been cancelled yet.
+    //
+    if (visit && postVisit)
+        visitBinary(PostVisit, node);
+}
+
+void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    //
+    // visit the node before children if pre-visiting.
+    //
+    if (preVisit)
+        visit = visitBinary(PreVisit, node);
+
+    //
+    // Visit the children, in the right order.
+    //
+    if (visit)
+    {
+        // Some binary operations like indexing can be inside an expression which must be an
+        // l-value.
+        bool parentOperatorRequiresLValue     = operatorRequiresLValue();
+        bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
+        if (node->isAssignment())
+        {
+            ASSERT(!isLValueRequiredHere());
+            setOperatorRequiresLValue(true);
+        }
+
+        if (node->getLeft())
+            node->getLeft()->traverse(this);
+
+        if (inVisit)
+            visit = visitBinary(InVisit, node);
+
+        if (node->isAssignment())
+            setOperatorRequiresLValue(false);
+
+        // Index is not required to be an l-value even when the surrounding expression is required
+        // to be an l-value.
+        TOperator op = node->getOp();
+        if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
+            op == EOpIndexDirectStruct || op == EOpIndexIndirect)
+        {
+            setOperatorRequiresLValue(false);
+            setInFunctionCallOutParameter(false);
+        }
+
+        if (visit && node->getRight())
+            node->getRight()->traverse(this);
+
+        setOperatorRequiresLValue(parentOperatorRequiresLValue);
+        setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
+    }
+
+    //
+    // Visit the node after the children, if requested and the traversal
+    // hasn't been cancelled yet.
+    //
+    if (visit && postVisit)
+        visitBinary(PostVisit, node);
+}
+
+//
+// Traverse a unary node.  Same comments in binary node apply here.
+//
+void TIntermTraverser::traverseUnary(TIntermUnary *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitUnary(PreVisit, node);
+
+    if (visit)
+    {
+        node->getOperand()->traverse(this);
+    }
+
+    if (visit && postVisit)
+        visitUnary(PostVisit, node);
+}
+
+void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitUnary(PreVisit, node);
+
+    if (visit)
+    {
+        ASSERT(!operatorRequiresLValue());
+        switch (node->getOp())
+        {
+            case EOpPostIncrement:
+            case EOpPostDecrement:
+            case EOpPreIncrement:
+            case EOpPreDecrement:
+                setOperatorRequiresLValue(true);
+                break;
+            default:
+                break;
+        }
+
+        node->getOperand()->traverse(this);
+
+        setOperatorRequiresLValue(false);
+    }
+
+    if (visit && postVisit)
+        visitUnary(PostVisit, node);
+}
+
+// Traverse a function definition node.
+void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitFunctionDefinition(PreVisit, node);
+
+    if (visit)
+    {
+        mInGlobalScope = false;
+
+        node->getFunctionPrototype()->traverse(this);
+        if (inVisit)
+            visit = visitFunctionDefinition(InVisit, node);
+        node->getBody()->traverse(this);
+
+        mInGlobalScope = true;
+    }
+
+    if (visit && postVisit)
+        visitFunctionDefinition(PostVisit, node);
+}
+
+// Traverse a block node.
+void TIntermTraverser::traverseBlock(TIntermBlock *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+    pushParentBlock(node);
+
+    bool visit = true;
+
+    TIntermSequence *sequence = node->getSequence();
+
+    if (preVisit)
+        visit = visitBlock(PreVisit, node);
+
+    if (visit)
+    {
+        for (auto *child : *sequence)
+        {
+            child->traverse(this);
+            if (visit && inVisit)
+            {
+                if (child != sequence->back())
+                    visit = visitBlock(InVisit, node);
+            }
+
+            incrementParentBlockPos();
+        }
+    }
+
+    if (visit && postVisit)
+        visitBlock(PostVisit, node);
+
+    popParentBlock();
+}
+
+void TIntermTraverser::traverseInvariantDeclaration(TIntermInvariantDeclaration *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+    {
+        visit = visitInvariantDeclaration(PreVisit, node);
+    }
+
+    if (visit)
+    {
+        node->getSymbol()->traverse(this);
+        if (postVisit)
+        {
+            visitInvariantDeclaration(PostVisit, node);
+        }
+    }
+}
+
+// Traverse a declaration node.
+void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    TIntermSequence *sequence = node->getSequence();
+
+    if (preVisit)
+        visit = visitDeclaration(PreVisit, node);
+
+    if (visit)
+    {
+        for (auto *child : *sequence)
+        {
+            child->traverse(this);
+            if (visit && inVisit)
+            {
+                if (child != sequence->back())
+                    visit = visitDeclaration(InVisit, node);
+            }
+        }
+    }
+
+    if (visit && postVisit)
+        visitDeclaration(PostVisit, node);
+}
+
+void TIntermTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    TIntermSequence *sequence = node->getSequence();
+
+    if (preVisit)
+        visit = visitFunctionPrototype(PreVisit, node);
+
+    if (visit)
+    {
+        for (auto *child : *sequence)
+        {
+            child->traverse(this);
+            if (visit && inVisit)
+            {
+                if (child != sequence->back())
+                    visit = visitFunctionPrototype(InVisit, node);
+            }
+        }
+    }
+
+    if (visit && postVisit)
+        visitFunctionPrototype(PostVisit, node);
+}
+
+// Traverse an aggregate node.  Same comments in binary node apply here.
+void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    TIntermSequence *sequence = node->getSequence();
+
+    if (preVisit)
+        visit = visitAggregate(PreVisit, node);
+
+    if (visit)
+    {
+        for (auto *child : *sequence)
+        {
+            child->traverse(this);
+            if (visit && inVisit)
+            {
+                if (child != sequence->back())
+                    visit = visitAggregate(InVisit, node);
+            }
+        }
+    }
+
+    if (visit && postVisit)
+        visitAggregate(PostVisit, node);
+}
+
+void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
+{
+    TIntermSequence *sequence = node->getSequence();
+    addToFunctionMap(node->getFunctionSymbolInfo()->getId(), sequence);
+
+    TIntermTraverser::traverseFunctionPrototype(node);
+}
+
+void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    TIntermSequence *sequence = node->getSequence();
+
+    if (preVisit)
+        visit = visitAggregate(PreVisit, node);
+
+    if (visit)
+    {
+        if (node->getOp() == EOpCallFunctionInAST)
+        {
+            if (isInFunctionMap(node))
+            {
+                TIntermSequence *params             = getFunctionParameters(node);
+                TIntermSequence::iterator paramIter = params->begin();
+                for (auto *child : *sequence)
+                {
+                    ASSERT(paramIter != params->end());
+                    TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
+                    setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
+
+                    child->traverse(this);
+                    if (visit && inVisit)
+                    {
+                        if (child != sequence->back())
+                            visit = visitAggregate(InVisit, node);
+                    }
+
+                    ++paramIter;
+                }
+            }
+            else
+            {
+                // The node might not be in the function map in case we're in the middle of
+                // transforming the AST, and have inserted function call nodes without inserting the
+                // function definitions yet.
+                setInFunctionCallOutParameter(false);
+                for (auto *child : *sequence)
+                {
+                    child->traverse(this);
+                    if (visit && inVisit)
+                    {
+                        if (child != sequence->back())
+                            visit = visitAggregate(InVisit, node);
+                    }
+                }
+            }
+
+            setInFunctionCallOutParameter(false);
+        }
+        else
+        {
+            // Find the built-in function corresponding to this op so that we can determine the
+            // in/out qualifiers of its parameters.
+            TFunction *builtInFunc = nullptr;
+            if (!node->isFunctionCall() && !node->isConstructor())
+            {
+                builtInFunc = static_cast<TFunction *>(
+                    mSymbolTable.findBuiltIn(node->getSymbolTableMangledName(), mShaderVersion));
+            }
+
+            size_t paramIndex = 0;
+
+            for (auto *child : *sequence)
+            {
+                // This assumes that raw functions called with
+                // EOpCallInternalRawFunction don't have out parameters.
+                TQualifier qualifier = EvqIn;
+                if (builtInFunc != nullptr)
+                    qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
+                setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
+                child->traverse(this);
+
+                if (visit && inVisit)
+                {
+                    if (child != sequence->back())
+                        visit = visitAggregate(InVisit, node);
+                }
+
+                ++paramIndex;
+            }
+
+            setInFunctionCallOutParameter(false);
+        }
+    }
+
+    if (visit && postVisit)
+        visitAggregate(PostVisit, node);
+}
+
+//
+// Traverse a ternary node.  Same comments in binary node apply here.
+//
+void TIntermTraverser::traverseTernary(TIntermTernary *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitTernary(PreVisit, node);
+
+    if (visit)
+    {
+        node->getCondition()->traverse(this);
+        if (node->getTrueExpression())
+            node->getTrueExpression()->traverse(this);
+        if (node->getFalseExpression())
+            node->getFalseExpression()->traverse(this);
+    }
+
+    if (visit && postVisit)
+        visitTernary(PostVisit, node);
+}
+
+// Traverse an if-else node.  Same comments in binary node apply here.
+void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitIfElse(PreVisit, node);
+
+    if (visit)
+    {
+        node->getCondition()->traverse(this);
+        if (node->getTrueBlock())
+            node->getTrueBlock()->traverse(this);
+        if (node->getFalseBlock())
+            node->getFalseBlock()->traverse(this);
+    }
+
+    if (visit && postVisit)
+        visitIfElse(PostVisit, node);
+}
+
+//
+// Traverse a switch node.  Same comments in binary node apply here.
+//
+void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitSwitch(PreVisit, node);
+
+    if (visit)
+    {
+        node->getInit()->traverse(this);
+        if (inVisit)
+            visit = visitSwitch(InVisit, node);
+        if (visit && node->getStatementList())
+            node->getStatementList()->traverse(this);
+    }
+
+    if (visit && postVisit)
+        visitSwitch(PostVisit, node);
+}
+
+//
+// Traverse a case node.  Same comments in binary node apply here.
+//
+void TIntermTraverser::traverseCase(TIntermCase *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitCase(PreVisit, node);
+
+    if (visit && node->getCondition())
+    {
+        node->getCondition()->traverse(this);
+    }
+
+    if (visit && postVisit)
+        visitCase(PostVisit, node);
+}
+
+//
+// Traverse a loop node.  Same comments in binary node apply here.
+//
+void TIntermTraverser::traverseLoop(TIntermLoop *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitLoop(PreVisit, node);
+
+    if (visit)
+    {
+        if (node->getInit())
+            node->getInit()->traverse(this);
+
+        if (node->getCondition())
+            node->getCondition()->traverse(this);
+
+        if (node->getBody())
+            node->getBody()->traverse(this);
+
+        if (node->getExpression())
+            node->getExpression()->traverse(this);
+    }
+
+    if (visit && postVisit)
+        visitLoop(PostVisit, node);
+}
+
+//
+// Traverse a branch node.  Same comments in binary node apply here.
+//
+void TIntermTraverser::traverseBranch(TIntermBranch *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    bool visit = true;
+
+    if (preVisit)
+        visit = visitBranch(PreVisit, node);
+
+    if (visit && node->getExpression())
+    {
+        node->getExpression()->traverse(this);
+    }
+
+    if (visit && postVisit)
+        visitBranch(PostVisit, node);
+}
+
+void TIntermTraverser::traverseRaw(TIntermRaw *node)
+{
+    ScopedNodeInTraversalPath addToPath(this, node);
+    visitRaw(node);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/Intermediate.cpp b/src/third_party/angle/src/compiler/translator/Intermediate.cpp
new file mode 100644
index 0000000..37e1123
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Intermediate.cpp
@@ -0,0 +1,305 @@
+//
+// 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.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include <float.h>
+#include <limits.h>
+#include <algorithm>
+
+#include "compiler/translator/Intermediate.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+TIntermSymbol *TIntermediate::addSymbol(int id,
+                                        const TString &name,
+                                        const TType &type,
+                                        const TSourceLoc &line)
+{
+    TIntermSymbol *node = new TIntermSymbol(id, name, type);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Connect two nodes through an index operator, where the left node is the base
+// of an array or struct, and the right node is a direct or indirect offset.
+//
+// Returns the added node.
+// The caller should set the type of the returned node.
+//
+TIntermTyped *TIntermediate::addIndex(TOperator op,
+                                      TIntermTyped *base,
+                                      TIntermTyped *index,
+                                      const TSourceLoc &line,
+                                      TDiagnostics *diagnostics)
+{
+    TIntermBinary *node = new TIntermBinary(op, base, index);
+    node->setLine(line);
+
+    TIntermTyped *folded = node->fold(diagnostics);
+    if (folded)
+    {
+        return folded;
+    }
+
+    return node;
+}
+
+// If the input node is nullptr, return nullptr.
+// If the input node is a block node, return it.
+// If the input node is not a block node, put it inside a block node and return that.
+TIntermBlock *TIntermediate::EnsureBlock(TIntermNode *node)
+{
+    if (node == nullptr)
+        return nullptr;
+    TIntermBlock *blockNode = node->getAsBlock();
+    if (blockNode != nullptr)
+        return blockNode;
+
+    blockNode = new TIntermBlock();
+    blockNode->setLine(node->getLine());
+    blockNode->appendStatement(node);
+    return blockNode;
+}
+
+// For "if" test nodes.  There are three children; a condition,
+// a true path, and a false path.  The two paths are in the
+// nodePair.
+//
+// Returns the node created.
+TIntermNode *TIntermediate::addIfElse(TIntermTyped *cond,
+                                      TIntermNodePair nodePair,
+                                      const TSourceLoc &line)
+{
+    // For compile time constant conditions, prune the code now.
+
+    if (cond->getAsConstantUnion())
+    {
+        if (cond->getAsConstantUnion()->getBConst(0) == true)
+        {
+            return EnsureBlock(nodePair.node1);
+        }
+        else
+        {
+            return EnsureBlock(nodePair.node2);
+        }
+    }
+
+    TIntermIfElse *node =
+        new TIntermIfElse(cond, EnsureBlock(nodePair.node1), EnsureBlock(nodePair.node2));
+    node->setLine(line);
+
+    return node;
+}
+
+TIntermTyped *TIntermediate::AddComma(TIntermTyped *left,
+                                      TIntermTyped *right,
+                                      const TSourceLoc &line,
+                                      int shaderVersion)
+{
+    TIntermTyped *commaNode = nullptr;
+    if (!left->hasSideEffects())
+    {
+        commaNode = right;
+    }
+    else
+    {
+        commaNode = new TIntermBinary(EOpComma, left, right);
+        commaNode->setLine(line);
+    }
+    TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(shaderVersion, left, right);
+    commaNode->getTypePointer()->setQualifier(resultQualifier);
+    return commaNode;
+}
+
+// For "?:" test nodes.  There are three children; a condition,
+// a true path, and a false path.  The two paths are specified
+// as separate parameters.
+//
+// Returns the ternary node created, or one of trueExpression and falseExpression if the expression
+// could be folded.
+TIntermTyped *TIntermediate::AddTernarySelection(TIntermTyped *cond,
+                                                 TIntermTyped *trueExpression,
+                                                 TIntermTyped *falseExpression,
+                                                 const TSourceLoc &line)
+{
+    // Note that the node resulting from here can be a constant union without being qualified as
+    // constant.
+    if (cond->getAsConstantUnion())
+    {
+        TQualifier resultQualifier =
+            TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression);
+        if (cond->getAsConstantUnion()->getBConst(0))
+        {
+            trueExpression->getTypePointer()->setQualifier(resultQualifier);
+            return trueExpression;
+        }
+        else
+        {
+            falseExpression->getTypePointer()->setQualifier(resultQualifier);
+            return falseExpression;
+        }
+    }
+
+    // Make a ternary node.
+    TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
+    node->setLine(line);
+
+    return node;
+}
+
+TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init,
+                                        TIntermBlock *statementList,
+                                        const TSourceLoc &line)
+{
+    TIntermSwitch *node = new TIntermSwitch(init, statementList);
+    node->setLine(line);
+
+    return node;
+}
+
+TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
+{
+    TIntermCase *node = new TIntermCase(condition);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Constant terminal nodes.  Has a union that contains bool, float or int constants
+//
+// Returns the constant union node created.
+//
+
+TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *constantUnion,
+                                                      const TType &type,
+                                                      const TSourceLoc &line)
+{
+    TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
+    node->setLine(line);
+
+    return node;
+}
+
+TIntermTyped *TIntermediate::AddSwizzle(TIntermTyped *baseExpression,
+                                        const TVectorFields &fields,
+                                        const TSourceLoc &dotLocation)
+{
+    TVector<int> fieldsVector;
+    for (int i = 0; i < fields.num; ++i)
+    {
+        fieldsVector.push_back(fields.offsets[i]);
+    }
+    TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldsVector);
+    node->setLine(dotLocation);
+
+    TIntermTyped *folded = node->fold();
+    if (folded)
+    {
+        return folded;
+    }
+
+    return node;
+}
+
+//
+// Create loop nodes.
+//
+TIntermNode *TIntermediate::addLoop(TLoopType type,
+                                    TIntermNode *init,
+                                    TIntermTyped *cond,
+                                    TIntermTyped *expr,
+                                    TIntermNode *body,
+                                    const TSourceLoc &line)
+{
+    TIntermNode *node = new TIntermLoop(type, init, cond, expr, EnsureBlock(body));
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Add branches.
+//
+TIntermBranch *TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
+{
+    return addBranch(branchOp, 0, line);
+}
+
+TIntermBranch *TIntermediate::addBranch(TOperator branchOp,
+                                        TIntermTyped *expression,
+                                        const TSourceLoc &line)
+{
+    TIntermBranch *node = new TIntermBranch(branchOp, expression);
+    node->setLine(line);
+
+    return node;
+}
+
+TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
+                                                  TDiagnostics *diagnostics)
+{
+    switch (aggregate->getOp())
+    {
+        case EOpAtan:
+        case EOpPow:
+        case EOpMod:
+        case EOpMin:
+        case EOpMax:
+        case EOpClamp:
+        case EOpMix:
+        case EOpStep:
+        case EOpSmoothStep:
+        case EOpLdexp:
+        case EOpMulMatrixComponentWise:
+        case EOpOuterProduct:
+        case EOpEqualComponentWise:
+        case EOpNotEqualComponentWise:
+        case EOpLessThanComponentWise:
+        case EOpLessThanEqualComponentWise:
+        case EOpGreaterThanComponentWise:
+        case EOpGreaterThanEqualComponentWise:
+        case EOpDistance:
+        case EOpDot:
+        case EOpCross:
+        case EOpFaceForward:
+        case EOpReflect:
+        case EOpRefract:
+        case EOpBitfieldExtract:
+        case EOpBitfieldInsert:
+            return aggregate->fold(diagnostics);
+        default:
+            // TODO: Add support for folding array constructors
+            if (aggregate->isConstructor() && !aggregate->isArray())
+            {
+                return aggregate->fold(diagnostics);
+            }
+            // Constant folding not supported for the built-in.
+            return nullptr;
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/Intermediate.h b/src/third_party/angle/src/compiler/translator/Intermediate.h
new file mode 100644
index 0000000..eb1d1d0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Intermediate.h
@@ -0,0 +1,75 @@
+//
+// 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.
+//
+
+#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_
+#define COMPILER_TRANSLATOR_INTERMEDIATE_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+struct TVectorFields
+{
+    int offsets[4];
+    int num;
+};
+
+//
+// Set of helper functions to help build the tree.
+//
+class TIntermediate
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TIntermediate() {}
+
+    TIntermSymbol *addSymbol(int id, const TString &, const TType &, const TSourceLoc &);
+    TIntermTyped *addIndex(TOperator op,
+                           TIntermTyped *base,
+                           TIntermTyped *index,
+                           const TSourceLoc &line,
+                           TDiagnostics *diagnostics);
+    static TIntermBlock *EnsureBlock(TIntermNode *node);
+    TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &line);
+    static TIntermTyped *AddTernarySelection(TIntermTyped *cond,
+                                             TIntermTyped *trueExpression,
+                                             TIntermTyped *falseExpression,
+                                             const TSourceLoc &line);
+    TIntermSwitch *addSwitch(TIntermTyped *init,
+                             TIntermBlock *statementList,
+                             const TSourceLoc &line);
+    TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &line);
+    static TIntermTyped *AddComma(TIntermTyped *left,
+                                  TIntermTyped *right,
+                                  const TSourceLoc &line,
+                                  int shaderVersion);
+    TIntermConstantUnion *addConstantUnion(const TConstantUnion *constantUnion,
+                                           const TType &type,
+                                           const TSourceLoc &line);
+    TIntermNode *addLoop(TLoopType,
+                         TIntermNode *,
+                         TIntermTyped *,
+                         TIntermTyped *,
+                         TIntermNode *,
+                         const TSourceLoc &);
+    TIntermBranch *addBranch(TOperator, const TSourceLoc &);
+    TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
+    static TIntermTyped *AddSwizzle(TIntermTyped *baseExpression,
+                                    const TVectorFields &fields,
+                                    const TSourceLoc &dotLocation);
+
+    static void outputTree(TIntermNode *, TInfoSinkBase &);
+
+    TIntermTyped *foldAggregateBuiltIn(TIntermAggregate *aggregate, TDiagnostics *diagnostics);
+
+  private:
+    void operator=(TIntermediate &);  // prevent assignments
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_INTERMEDIATE_H_
diff --git a/src/third_party/angle/src/compiler/translator/NodeSearch.h b/src/third_party/angle/src/compiler/translator/NodeSearch.h
new file mode 100644
index 0000000..96b0b33
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/NodeSearch.h
@@ -0,0 +1,56 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// NodeSearch.h: Utilities for searching translator node graphs
+//
+
+#ifndef COMPILER_TRANSLATOR_NODESEARCH_H_
+#define COMPILER_TRANSLATOR_NODESEARCH_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+template <class Parent>
+class NodeSearchTraverser : public TIntermTraverser
+{
+  public:
+    NodeSearchTraverser() : TIntermTraverser(true, false, false), mFound(false) {}
+
+    bool found() const { return mFound; }
+
+    static bool search(TIntermNode *node)
+    {
+        Parent searchTraverser;
+        node->traverse(&searchTraverser);
+        return searchTraverser.found();
+    }
+
+  protected:
+    bool mFound;
+};
+
+class FindDiscard : public NodeSearchTraverser<FindDiscard>
+{
+  public:
+    virtual bool visitBranch(Visit visit, TIntermBranch *node)
+    {
+        switch (node->getFlowOp())
+        {
+            case EOpKill:
+                mFound = true;
+                break;
+
+            default:
+                break;
+        }
+
+        return !mFound;
+    }
+};
+}
+
+#endif  // COMPILER_TRANSLATOR_NODESEARCH_H_
diff --git a/src/third_party/angle/src/compiler/translator/Operator.cpp b/src/third_party/angle/src/compiler/translator/Operator.cpp
new file mode 100644
index 0000000..1858980
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Operator.cpp
@@ -0,0 +1,377 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/Operator.h"
+
+const char *GetOperatorString(TOperator op)
+{
+    switch (op)
+    {
+        // Note: EOpNull and EOpCall* can't be handled here.
+
+        case EOpNegative:
+            return "-";
+        case EOpPositive:
+            return "+";
+        case EOpLogicalNot:
+            return "!";
+        case EOpBitwiseNot:
+            return "~";
+
+        case EOpPostIncrement:
+            return "++";
+        case EOpPostDecrement:
+            return "--";
+        case EOpPreIncrement:
+            return "++";
+        case EOpPreDecrement:
+            return "--";
+
+        case EOpAdd:
+            return "+";
+        case EOpSub:
+            return "-";
+        case EOpMul:
+            return "*";
+        case EOpDiv:
+            return "/";
+        case EOpIMod:
+            return "%";
+
+        case EOpEqual:
+            return "==";
+        case EOpNotEqual:
+            return "!=";
+        case EOpLessThan:
+            return "<";
+        case EOpGreaterThan:
+            return ">";
+        case EOpLessThanEqual:
+            return "<=";
+        case EOpGreaterThanEqual:
+            return ">=";
+
+        case EOpEqualComponentWise:
+            return "equal";
+        case EOpNotEqualComponentWise:
+            return "notEqual";
+        case EOpLessThanComponentWise:
+            return "lessThan";
+        case EOpGreaterThanComponentWise:
+            return "greaterThan";
+        case EOpLessThanEqualComponentWise:
+            return "lessThanEqual";
+        case EOpGreaterThanEqualComponentWise:
+            return "greaterThanEqual";
+
+        case EOpComma:
+            return ",";
+
+        // Fall-through.
+        case EOpVectorTimesScalar:
+        case EOpVectorTimesMatrix:
+        case EOpMatrixTimesVector:
+        case EOpMatrixTimesScalar:
+        case EOpMatrixTimesMatrix:
+            return "*";
+
+        case EOpLogicalOr:
+            return "||";
+        case EOpLogicalXor:
+            return "^^";
+        case EOpLogicalAnd:
+            return "&&";
+
+        case EOpBitShiftLeft:
+            return "<<";
+        case EOpBitShiftRight:
+            return ">>";
+
+        case EOpBitwiseAnd:
+            return "&";
+        case EOpBitwiseXor:
+            return "^";
+        case EOpBitwiseOr:
+            return "|";
+
+        // Fall-through.
+        case EOpIndexDirect:
+        case EOpIndexIndirect:
+            return "[]";
+
+        case EOpIndexDirectStruct:
+        case EOpIndexDirectInterfaceBlock:
+            return ".";
+
+        case EOpRadians:
+            return "radians";
+        case EOpDegrees:
+            return "degrees";
+        case EOpSin:
+            return "sin";
+        case EOpCos:
+            return "cos";
+        case EOpTan:
+            return "tan";
+        case EOpAsin:
+            return "asin";
+        case EOpAcos:
+            return "acos";
+        case EOpAtan:
+            return "atan";
+
+        case EOpSinh:
+            return "sinh";
+        case EOpCosh:
+            return "cosh";
+        case EOpTanh:
+            return "tanh";
+        case EOpAsinh:
+            return "asinh";
+        case EOpAcosh:
+            return "acosh";
+        case EOpAtanh:
+            return "atanh";
+
+        case EOpPow:
+            return "pow";
+        case EOpExp:
+            return "exp";
+        case EOpLog:
+            return "log";
+        case EOpExp2:
+            return "exp2";
+        case EOpLog2:
+            return "log2";
+        case EOpSqrt:
+            return "sqrt";
+        case EOpInverseSqrt:
+            return "inversesqrt";
+
+        case EOpAbs:
+            return "abs";
+        case EOpSign:
+            return "sign";
+        case EOpFloor:
+            return "floor";
+        case EOpTrunc:
+            return "trunc";
+        case EOpRound:
+            return "round";
+        case EOpRoundEven:
+            return "roundEven";
+        case EOpCeil:
+            return "ceil";
+        case EOpFract:
+            return "fract";
+        case EOpMod:
+            return "mod";
+        case EOpModf:
+            return "modf";
+        case EOpMin:
+            return "min";
+        case EOpMax:
+            return "max";
+        case EOpClamp:
+            return "clamp";
+        case EOpMix:
+            return "mix";
+        case EOpStep:
+            return "step";
+        case EOpSmoothStep:
+            return "smoothstep";
+        case EOpIsNan:
+            return "isnan";
+        case EOpIsInf:
+            return "isinf";
+
+        case EOpFloatBitsToInt:
+            return "floatBitsToInt";
+        case EOpFloatBitsToUint:
+            return "floatBitsToUint";
+        case EOpIntBitsToFloat:
+            return "intBitsToFloat";
+        case EOpUintBitsToFloat:
+            return "uintBitsToFloat";
+
+        case EOpFrexp:
+            return "frexp";
+        case EOpLdexp:
+            return "ldexp";
+
+        case EOpPackSnorm2x16:
+            return "packSnorm2x16";
+        case EOpPackUnorm2x16:
+            return "packUnorm2x16";
+        case EOpPackHalf2x16:
+            return "packHalf2x16";
+        case EOpUnpackSnorm2x16:
+            return "unpackSnorm2x16";
+        case EOpUnpackUnorm2x16:
+            return "unpackUnorm2x16";
+        case EOpUnpackHalf2x16:
+            return "unpackHalf2x16";
+
+        case EOpPackUnorm4x8:
+            return "packUnorm4x8";
+        case EOpPackSnorm4x8:
+            return "packSnorm4x8";
+        case EOpUnpackUnorm4x8:
+            return "unpackUnorm4x8";
+        case EOpUnpackSnorm4x8:
+            return "unpackSnorm4x8";
+
+        case EOpLength:
+            return "length";
+        case EOpDistance:
+            return "distance";
+        case EOpDot:
+            return "dot";
+        case EOpCross:
+            return "cross";
+        case EOpNormalize:
+            return "normalize";
+        case EOpFaceForward:
+            return "faceforward";
+        case EOpReflect:
+            return "reflect";
+        case EOpRefract:
+            return "refract";
+
+        case EOpDFdx:
+            return "dFdx";
+        case EOpDFdy:
+            return "dFdy";
+        case EOpFwidth:
+            return "fwidth";
+
+        case EOpMulMatrixComponentWise:
+            return "matrixCompMult";
+        case EOpOuterProduct:
+            return "outerProduct";
+        case EOpTranspose:
+            return "transpose";
+        case EOpDeterminant:
+            return "determinant";
+        case EOpInverse:
+            return "inverse";
+
+        case EOpAny:
+            return "any";
+        case EOpAll:
+            return "all";
+        case EOpLogicalNotComponentWise:
+            return "not";
+
+        case EOpBitfieldExtract:
+            return "bitfieldExtract";
+        case EOpBitfieldInsert:
+            return "bitfieldInsert";
+        case EOpBitfieldReverse:
+            return "bitfieldReverse";
+        case EOpBitCount:
+            return "bitCount";
+        case EOpFindLSB:
+            return "findLSB";
+        case EOpFindMSB:
+            return "findMSB";
+        case EOpUaddCarry:
+            return "uaddCarry";
+        case EOpUsubBorrow:
+            return "usubBorrow";
+        case EOpUmulExtended:
+            return "umulExtended";
+        case EOpImulExtended:
+            return "imulExtended";
+
+        case EOpKill:
+            return "kill";
+        case EOpReturn:
+            return "return";
+        case EOpBreak:
+            return "break";
+        case EOpContinue:
+            return "continue";
+
+        case EOpAssign:
+            return "=";
+        case EOpInitialize:
+            return "=";
+        case EOpAddAssign:
+            return "+=";
+        case EOpSubAssign:
+            return "-=";
+
+        // Fall-through.
+        case EOpMulAssign:
+        case EOpVectorTimesMatrixAssign:
+        case EOpVectorTimesScalarAssign:
+        case EOpMatrixTimesScalarAssign:
+        case EOpMatrixTimesMatrixAssign:
+            return "*=";
+
+        case EOpDivAssign:
+            return "/=";
+        case EOpIModAssign:
+            return "%=";
+        case EOpBitShiftLeftAssign:
+            return "<<=";
+        case EOpBitShiftRightAssign:
+            return ">>=";
+        case EOpBitwiseAndAssign:
+            return "&=";
+        case EOpBitwiseXorAssign:
+            return "^=";
+        case EOpBitwiseOrAssign:
+            return "|=";
+        case EOpBarrier:
+            return "barrier";
+        case EOpMemoryBarrier:
+            return "memoryBarrier";
+        case EOpMemoryBarrierAtomicCounter:
+            return "memoryBarrierAtomicCounter";
+        case EOpMemoryBarrierBuffer:
+            return "memoryBarrierBuffer";
+        case EOpMemoryBarrierImage:
+            return "memoryBarrierImage";
+        case EOpMemoryBarrierShared:
+            return "memoryBarrierShared";
+        case EOpGroupMemoryBarrier:
+            return "groupMemoryBarrier";
+        default:
+            break;
+    }
+    return "";
+}
+
+bool IsAssignment(TOperator op)
+{
+    switch (op)
+    {
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+        case EOpAssign:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpMulAssign:
+        case EOpVectorTimesMatrixAssign:
+        case EOpVectorTimesScalarAssign:
+        case EOpMatrixTimesScalarAssign:
+        case EOpMatrixTimesMatrixAssign:
+        case EOpDivAssign:
+        case EOpIModAssign:
+        case EOpBitShiftLeftAssign:
+        case EOpBitShiftRightAssign:
+        case EOpBitwiseAndAssign:
+        case EOpBitwiseXorAssign:
+        case EOpBitwiseOrAssign:
+            return true;
+        default:
+            return false;
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/translator/Operator.h b/src/third_party/angle/src/compiler/translator/Operator.h
new file mode 100644
index 0000000..5f028b9
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Operator.h
@@ -0,0 +1,249 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_OPERATOR_H_
+#define COMPILER_TRANSLATOR_OPERATOR_H_
+
+//
+// Operators used by the high-level (parse tree) representation.
+//
+enum TOperator
+{
+    EOpNull,  // if in a node, should only mean a node is still being built
+
+    // Call a function defined in the AST. This might be a user-defined function or a function
+    // inserted by an AST transformation.
+    EOpCallFunctionInAST,
+
+    // Call an internal helper function with a raw implementation - the implementation can't be
+    // subject to AST transformations. Raw functions have a few constraints to keep them compatible
+    // with AST traversers:
+    // * They should not return arrays.
+    // * They should not have out parameters.
+    EOpCallInternalRawFunction,
+
+    // Call a built-in function like a texture or image function.
+    EOpCallBuiltInFunction,
+
+    //
+    // Unary operators
+    //
+
+    EOpNegative,
+    EOpPositive,
+    EOpLogicalNot,
+    EOpBitwiseNot,
+
+    EOpPostIncrement,
+    EOpPostDecrement,
+    EOpPreIncrement,
+    EOpPreDecrement,
+
+    //
+    // binary operations (ones with special GLSL syntax are used in TIntermBinary nodes, others in
+    // TIntermAggregate nodes)
+    //
+
+    EOpAdd,
+    EOpSub,
+    EOpMul,
+    EOpDiv,
+    EOpIMod,
+
+    EOpEqual,
+    EOpNotEqual,
+    EOpLessThan,
+    EOpGreaterThan,
+    EOpLessThanEqual,
+    EOpGreaterThanEqual,
+
+    EOpEqualComponentWise,
+    EOpNotEqualComponentWise,
+    EOpLessThanComponentWise,
+    EOpLessThanEqualComponentWise,
+    EOpGreaterThanComponentWise,
+    EOpGreaterThanEqualComponentWise,
+
+    EOpComma,
+
+    EOpVectorTimesScalar,
+    EOpVectorTimesMatrix,
+    EOpMatrixTimesVector,
+    EOpMatrixTimesScalar,
+    EOpMatrixTimesMatrix,
+
+    EOpLogicalOr,
+    EOpLogicalXor,
+    EOpLogicalAnd,
+
+    EOpBitShiftLeft,
+    EOpBitShiftRight,
+
+    EOpBitwiseAnd,
+    EOpBitwiseXor,
+    EOpBitwiseOr,
+
+    EOpIndexDirect,
+    EOpIndexIndirect,
+    EOpIndexDirectStruct,
+    EOpIndexDirectInterfaceBlock,
+
+    //
+    // Built-in functions mapped to operators (either unary or with multiple parameters)
+    //
+
+    EOpRadians,
+    EOpDegrees,
+    EOpSin,
+    EOpCos,
+    EOpTan,
+    EOpAsin,
+    EOpAcos,
+    EOpAtan,
+
+    EOpSinh,
+    EOpCosh,
+    EOpTanh,
+    EOpAsinh,
+    EOpAcosh,
+    EOpAtanh,
+
+    EOpPow,
+    EOpExp,
+    EOpLog,
+    EOpExp2,
+    EOpLog2,
+    EOpSqrt,
+    EOpInverseSqrt,
+
+    EOpAbs,
+    EOpSign,
+    EOpFloor,
+    EOpTrunc,
+    EOpRound,
+    EOpRoundEven,
+    EOpCeil,
+    EOpFract,
+    EOpMod,
+    EOpModf,
+    EOpMin,
+    EOpMax,
+    EOpClamp,
+    EOpMix,
+    EOpStep,
+    EOpSmoothStep,
+    EOpIsNan,
+    EOpIsInf,
+
+    EOpFloatBitsToInt,
+    EOpFloatBitsToUint,
+    EOpIntBitsToFloat,
+    EOpUintBitsToFloat,
+
+    EOpFrexp,
+    EOpLdexp,
+
+    EOpPackSnorm2x16,
+    EOpPackUnorm2x16,
+    EOpPackHalf2x16,
+    EOpUnpackSnorm2x16,
+    EOpUnpackUnorm2x16,
+    EOpUnpackHalf2x16,
+
+    EOpPackUnorm4x8,
+    EOpPackSnorm4x8,
+    EOpUnpackUnorm4x8,
+    EOpUnpackSnorm4x8,
+
+    EOpLength,
+    EOpDistance,
+    EOpDot,
+    EOpCross,
+    EOpNormalize,
+    EOpFaceForward,
+    EOpReflect,
+    EOpRefract,
+
+    EOpDFdx,    // Fragment only, OES_standard_derivatives extension
+    EOpDFdy,    // Fragment only, OES_standard_derivatives extension
+    EOpFwidth,  // Fragment only, OES_standard_derivatives extension
+
+    EOpMulMatrixComponentWise,
+    EOpOuterProduct,
+    EOpTranspose,
+    EOpDeterminant,
+    EOpInverse,
+
+    EOpAny,
+    EOpAll,
+    EOpLogicalNotComponentWise,
+
+    EOpBitfieldExtract,
+    EOpBitfieldInsert,
+    EOpBitfieldReverse,
+    EOpBitCount,
+    EOpFindLSB,
+    EOpFindMSB,
+    EOpUaddCarry,
+    EOpUsubBorrow,
+    EOpUmulExtended,
+    EOpImulExtended,
+
+    //
+    // Branch
+    //
+
+    EOpKill,  // Fragment only
+    EOpReturn,
+    EOpBreak,
+    EOpContinue,
+
+    //
+    // Constructor
+    //
+
+    EOpConstruct,
+
+    //
+    // moves
+    //
+
+    EOpAssign,
+    EOpInitialize,
+    EOpAddAssign,
+    EOpSubAssign,
+
+    EOpMulAssign,
+    EOpVectorTimesMatrixAssign,
+    EOpVectorTimesScalarAssign,
+    EOpMatrixTimesScalarAssign,
+    EOpMatrixTimesMatrixAssign,
+
+    EOpDivAssign,
+    EOpIModAssign,
+    EOpBitShiftLeftAssign,
+    EOpBitShiftRightAssign,
+    EOpBitwiseAndAssign,
+    EOpBitwiseXorAssign,
+    EOpBitwiseOrAssign,
+
+    //  barriers
+    EOpBarrier,
+    EOpMemoryBarrier,
+    EOpMemoryBarrierAtomicCounter,
+    EOpMemoryBarrierBuffer,
+    EOpMemoryBarrierImage,
+    EOpMemoryBarrierShared,
+    EOpGroupMemoryBarrier
+};
+
+// Returns the string corresponding to the operator in GLSL
+const char *GetOperatorString(TOperator op);
+
+// Say whether or not a binary or unary operation changes the value of a variable.
+bool IsAssignment(TOperator op);
+
+#endif  // COMPILER_TRANSLATOR_OPERATOR_H_
diff --git a/src/third_party/angle/src/compiler/translator/OutputESSL.cpp b/src/third_party/angle/src/compiler/translator/OutputESSL.cpp
new file mode 100644
index 0000000..df985ad
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputESSL.cpp
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputESSL.h"
+
+namespace sh
+{
+
+TOutputESSL::TOutputESSL(TInfoSinkBase &objSink,
+                         ShArrayIndexClampingStrategy clampingStrategy,
+                         ShHashFunction64 hashFunction,
+                         NameMap &nameMap,
+                         TSymbolTable &symbolTable,
+                         sh::GLenum shaderType,
+                         int shaderVersion,
+                         bool forceHighp,
+                         ShCompileOptions compileOptions)
+    : TOutputGLSLBase(objSink,
+                      clampingStrategy,
+                      hashFunction,
+                      nameMap,
+                      symbolTable,
+                      shaderType,
+                      shaderVersion,
+                      SH_ESSL_OUTPUT,
+                      compileOptions),
+      mForceHighp(forceHighp)
+{
+}
+
+bool TOutputESSL::writeVariablePrecision(TPrecision precision)
+{
+    if (precision == EbpUndefined)
+        return false;
+
+    TInfoSinkBase &out = objSink();
+    if (mForceHighp)
+        out << getPrecisionString(EbpHigh);
+    else
+        out << getPrecisionString(precision);
+    return true;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/OutputESSL.h b/src/third_party/angle/src/compiler/translator/OutputESSL.h
new file mode 100644
index 0000000..5b2cb94
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputESSL.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_OUTPUTESSL_H_
+#define COMPILER_TRANSLATOR_OUTPUTESSL_H_
+
+#include "compiler/translator/OutputGLSLBase.h"
+
+namespace sh
+{
+
+class TOutputESSL : public TOutputGLSLBase
+{
+  public:
+    TOutputESSL(TInfoSinkBase &objSink,
+                ShArrayIndexClampingStrategy clampingStrategy,
+                ShHashFunction64 hashFunction,
+                NameMap &nameMap,
+                TSymbolTable &symbolTable,
+                sh::GLenum shaderType,
+                int shaderVersion,
+                bool forceHighp,
+                ShCompileOptions compileOptions);
+
+  protected:
+    bool writeVariablePrecision(TPrecision precision) override;
+
+  private:
+    bool mForceHighp;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_OUTPUTESSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/OutputGLSL.cpp b/src/third_party/angle/src/compiler/translator/OutputGLSL.cpp
new file mode 100644
index 0000000..5a7de93
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputGLSL.cpp
@@ -0,0 +1,108 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputGLSL.h"
+
+namespace sh
+{
+
+TOutputGLSL::TOutputGLSL(TInfoSinkBase &objSink,
+                         ShArrayIndexClampingStrategy clampingStrategy,
+                         ShHashFunction64 hashFunction,
+                         NameMap &nameMap,
+                         TSymbolTable &symbolTable,
+                         sh::GLenum shaderType,
+                         int shaderVersion,
+                         ShShaderOutput output,
+                         ShCompileOptions compileOptions)
+    : TOutputGLSLBase(objSink,
+                      clampingStrategy,
+                      hashFunction,
+                      nameMap,
+                      symbolTable,
+                      shaderType,
+                      shaderVersion,
+                      output,
+                      compileOptions)
+{
+}
+
+bool TOutputGLSL::writeVariablePrecision(TPrecision)
+{
+    return false;
+}
+
+void TOutputGLSL::visitSymbol(TIntermSymbol *node)
+{
+    TInfoSinkBase &out = objSink();
+
+    const TString &symbol = node->getSymbol();
+    if (symbol == "gl_FragDepthEXT")
+    {
+        out << "gl_FragDepth";
+    }
+    else if (symbol == "gl_FragColor" && sh::IsGLSL130OrNewer(getShaderOutput()))
+    {
+        out << "webgl_FragColor";
+    }
+    else if (symbol == "gl_FragData" && sh::IsGLSL130OrNewer(getShaderOutput()))
+    {
+        out << "webgl_FragData";
+    }
+    else if (symbol == "gl_SecondaryFragColorEXT")
+    {
+        out << "angle_SecondaryFragColor";
+    }
+    else if (symbol == "gl_SecondaryFragDataEXT")
+    {
+        out << "angle_SecondaryFragData";
+    }
+    else
+    {
+        TOutputGLSLBase::visitSymbol(node);
+    }
+}
+
+TString TOutputGLSL::translateTextureFunction(const TString &name)
+{
+    static const char *simpleRename[] = {"texture2DLodEXT",
+                                         "texture2DLod",
+                                         "texture2DProjLodEXT",
+                                         "texture2DProjLod",
+                                         "textureCubeLodEXT",
+                                         "textureCubeLod",
+                                         "texture2DGradEXT",
+                                         "texture2DGradARB",
+                                         "texture2DProjGradEXT",
+                                         "texture2DProjGradARB",
+                                         "textureCubeGradEXT",
+                                         "textureCubeGradARB",
+                                         nullptr,
+                                         nullptr};
+    static const char *legacyToCoreRename[] = {
+        "texture2D", "texture", "texture2DProj", "textureProj", "texture2DLod", "textureLod",
+        "texture2DProjLod", "textureProjLod", "texture2DRect", "texture", "textureCube", "texture",
+        "textureCubeLod", "textureLod",
+        // Extensions
+        "texture2DLodEXT", "textureLod", "texture2DProjLodEXT", "textureProjLod",
+        "textureCubeLodEXT", "textureLod", "texture2DGradEXT", "textureGrad",
+        "texture2DProjGradEXT", "textureProjGrad", "textureCubeGradEXT", "textureGrad", nullptr,
+        nullptr};
+    const char **mapping =
+        (sh::IsGLSL130OrNewer(getShaderOutput())) ? legacyToCoreRename : simpleRename;
+
+    for (int i = 0; mapping[i] != nullptr; i += 2)
+    {
+        if (name == mapping[i])
+        {
+            return mapping[i + 1];
+        }
+    }
+
+    return name;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/OutputGLSL.h b/src/third_party/angle/src/compiler/translator/OutputGLSL.h
new file mode 100644
index 0000000..17682ff
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputGLSL.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_OUTPUTGLSL_H_
+#define COMPILER_TRANSLATOR_OUTPUTGLSL_H_
+
+#include "compiler/translator/OutputGLSLBase.h"
+
+namespace sh
+{
+
+class TOutputGLSL : public TOutputGLSLBase
+{
+  public:
+    TOutputGLSL(TInfoSinkBase &objSink,
+                ShArrayIndexClampingStrategy clampingStrategy,
+                ShHashFunction64 hashFunction,
+                NameMap &nameMap,
+                TSymbolTable &symbolTable,
+                sh::GLenum shaderType,
+                int shaderVersion,
+                ShShaderOutput output,
+                ShCompileOptions compileOptions);
+
+  protected:
+    bool writeVariablePrecision(TPrecision) override;
+    void visitSymbol(TIntermSymbol *node) override;
+    TString translateTextureFunction(const TString &name) override;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_OUTPUTGLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/third_party/angle/src/compiler/translator/OutputGLSLBase.cpp
new file mode 100644
index 0000000..94849ec
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputGLSLBase.cpp
@@ -0,0 +1,1296 @@
+//
+// 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.
+//
+
+#include "compiler/translator/OutputGLSLBase.h"
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+
+#include <cfloat>
+
+namespace sh
+{
+
+namespace
+{
+TString arrayBrackets(const TType &type)
+{
+    ASSERT(type.isArray());
+    TInfoSinkBase out;
+    out << "[" << type.getArraySize() << "]";
+    return TString(out.c_str());
+}
+
+bool isSingleStatement(TIntermNode *node)
+{
+    if (node->getAsFunctionDefinition())
+    {
+        return false;
+    }
+    else if (node->getAsBlock())
+    {
+        return false;
+    }
+    else if (node->getAsIfElseNode())
+    {
+        return false;
+    }
+    else if (node->getAsLoopNode())
+    {
+        return false;
+    }
+    else if (node->getAsSwitchNode())
+    {
+        return false;
+    }
+    else if (node->getAsCaseNode())
+    {
+        return false;
+    }
+    return true;
+}
+
+// If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever
+// variables with specified layout qualifiers are copied. Additional checks are needed against the
+// type and storage qualifier of the variable to verify that layout qualifiers have to be outputted.
+// TODO (mradev): Fix layout qualifier spilling in ScalarizeVecAndMatConstructorArgs and remove
+// NeedsToWriteLayoutQualifier.
+bool NeedsToWriteLayoutQualifier(const TType &type)
+{
+    if (type.getBasicType() == EbtInterfaceBlock)
+    {
+        return false;
+    }
+
+    const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
+
+    if ((type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn) &&
+        layoutQualifier.location >= 0)
+    {
+        return true;
+    }
+
+    if (type.getQualifier() == EvqFragmentOut && layoutQualifier.yuv == true)
+    {
+        return true;
+    }
+
+    if (IsOpaqueType(type.getBasicType()) && layoutQualifier.binding != -1)
+    {
+        return true;
+    }
+
+    if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
+    {
+        return true;
+    }
+    return false;
+}
+
+class CommaSeparatedListItemPrefixGenerator
+{
+  public:
+    CommaSeparatedListItemPrefixGenerator() : mFirst(true) {}
+  private:
+    bool mFirst;
+
+    friend TInfoSinkBase &operator<<(TInfoSinkBase &out,
+                                     CommaSeparatedListItemPrefixGenerator &gen);
+};
+
+TInfoSinkBase &operator<<(TInfoSinkBase &out, CommaSeparatedListItemPrefixGenerator &gen)
+{
+    if (gen.mFirst)
+    {
+        gen.mFirst = false;
+    }
+    else
+    {
+        out << ", ";
+    }
+    return out;
+}
+
+}  // namespace
+
+TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
+                                 ShArrayIndexClampingStrategy clampingStrategy,
+                                 ShHashFunction64 hashFunction,
+                                 NameMap &nameMap,
+                                 TSymbolTable &symbolTable,
+                                 sh::GLenum shaderType,
+                                 int shaderVersion,
+                                 ShShaderOutput output,
+                                 ShCompileOptions compileOptions)
+    : TIntermTraverser(true, true, true),
+      mObjSink(objSink),
+      mDeclaringVariables(false),
+      mClampingStrategy(clampingStrategy),
+      mHashFunction(hashFunction),
+      mNameMap(nameMap),
+      mSymbolTable(symbolTable),
+      mShaderType(shaderType),
+      mShaderVersion(shaderVersion),
+      mOutput(output),
+      mCompileOptions(compileOptions)
+{
+}
+
+void TOutputGLSLBase::writeInvariantQualifier(const TType &type)
+{
+    if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions))
+    {
+        TInfoSinkBase &out = objSink();
+        out << "invariant ";
+    }
+}
+
+void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f)
+{
+    if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300)
+    {
+        out << "uintBitsToFloat(" << gl::bitCast<uint32_t>(f) << "u)";
+    }
+    else
+    {
+        out << std::min(FLT_MAX, std::max(-FLT_MAX, f));
+    }
+}
+
+void TOutputGLSLBase::writeTriplet(Visit visit,
+                                   const char *preStr,
+                                   const char *inStr,
+                                   const char *postStr)
+{
+    TInfoSinkBase &out = objSink();
+    if (visit == PreVisit && preStr)
+        out << preStr;
+    else if (visit == InVisit && inStr)
+        out << inStr;
+    else if (visit == PostVisit && postStr)
+        out << postStr;
+}
+
+void TOutputGLSLBase::writeBuiltInFunctionTriplet(Visit visit,
+                                                  TOperator op,
+                                                  bool useEmulatedFunction)
+{
+    TInfoSinkBase &out = objSink();
+    if (visit == PreVisit)
+    {
+        const char *opStr(GetOperatorString(op));
+        if (useEmulatedFunction)
+        {
+            BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr);
+        }
+        else
+        {
+            out << opStr;
+        }
+        out << "(";
+    }
+    else
+    {
+        writeTriplet(visit, nullptr, ", ", ")");
+    }
+}
+
+void TOutputGLSLBase::writeLayoutQualifier(const TType &type)
+{
+    if (!NeedsToWriteLayoutQualifier(type))
+    {
+        return;
+    }
+
+    TInfoSinkBase &out                      = objSink();
+    const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
+    out << "layout(";
+
+    CommaSeparatedListItemPrefixGenerator listItemPrefix;
+
+    if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn)
+    {
+        if (layoutQualifier.location >= 0)
+        {
+            out << listItemPrefix << "location = " << layoutQualifier.location;
+        }
+    }
+
+    if (type.getQualifier() == EvqFragmentOut)
+    {
+        if (layoutQualifier.yuv == true)
+        {
+            out << listItemPrefix << "yuv";
+        }
+    }
+
+    if (IsOpaqueType(type.getBasicType()))
+    {
+        if (layoutQualifier.binding >= 0)
+        {
+            out << listItemPrefix << "binding = " << layoutQualifier.binding;
+        }
+    }
+
+    if (IsImage(type.getBasicType()))
+    {
+        if (layoutQualifier.imageInternalFormat != EiifUnspecified)
+        {
+            ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform);
+            out << listItemPrefix
+                << getImageInternalFormatString(layoutQualifier.imageInternalFormat);
+        }
+    }
+
+    out << ") ";
+}
+
+const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
+{
+    if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
+        (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0)
+    {
+        switch (qualifier)
+        {
+            // The return string is consistent with sh::getQualifierString() from
+            // BaseTypes.h minus the "centroid" keyword.
+            case EvqCentroid:
+                return "";
+            case EvqCentroidIn:
+                return "smooth in";
+            case EvqCentroidOut:
+                return "smooth out";
+            default:
+                break;
+        }
+    }
+    if (sh::IsGLSL130OrNewer(mOutput))
+    {
+        switch (qualifier)
+        {
+            case EvqAttribute:
+                return "in";
+            case EvqVaryingIn:
+                return "in";
+            case EvqVaryingOut:
+                return "out";
+            default:
+                break;
+        }
+    }
+    return sh::getQualifierString(qualifier);
+}
+
+void TOutputGLSLBase::writeVariableType(const TType &type)
+{
+    TQualifier qualifier = type.getQualifier();
+    TInfoSinkBase &out   = objSink();
+    if (type.isInvariant())
+    {
+        writeInvariantQualifier(type);
+    }
+    if (type.getBasicType() == EbtInterfaceBlock)
+    {
+        TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
+        declareInterfaceBlockLayout(interfaceBlock);
+    }
+    if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+    {
+        const char *qualifierString = mapQualifierToString(qualifier);
+        if (qualifierString && qualifierString[0] != '\0')
+        {
+            out << qualifierString << " ";
+        }
+    }
+
+    const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier();
+    if (memoryQualifier.readonly)
+    {
+        ASSERT(IsImage(type.getBasicType()));
+        out << "readonly ";
+    }
+
+    if (memoryQualifier.writeonly)
+    {
+        ASSERT(IsImage(type.getBasicType()));
+        out << "writeonly ";
+    }
+
+    if (memoryQualifier.coherent)
+    {
+        ASSERT(IsImage(type.getBasicType()));
+        out << "coherent ";
+    }
+
+    if (memoryQualifier.restrictQualifier)
+    {
+        ASSERT(IsImage(type.getBasicType()));
+        out << "restrict ";
+    }
+
+    if (memoryQualifier.volatileQualifier)
+    {
+        ASSERT(IsImage(type.getBasicType()));
+        out << "volatile ";
+    }
+
+    // Declare the struct if we have not done so already.
+    if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
+    {
+        TStructure *structure = type.getStruct();
+
+        declareStruct(structure);
+
+        if (!structure->name().empty())
+        {
+            mDeclaredStructs.insert(structure->uniqueId());
+        }
+    }
+    else if (type.getBasicType() == EbtInterfaceBlock)
+    {
+        TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
+        declareInterfaceBlock(interfaceBlock);
+    }
+    else
+    {
+        if (writeVariablePrecision(type.getPrecision()))
+            out << " ";
+        out << getTypeName(type);
+    }
+}
+
+void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
+{
+    TInfoSinkBase &out = objSink();
+    for (TIntermSequence::const_iterator iter = args.begin(); iter != args.end(); ++iter)
+    {
+        const TIntermSymbol *arg = (*iter)->getAsSymbolNode();
+        ASSERT(arg != nullptr);
+
+        const TType &type = arg->getType();
+        writeVariableType(type);
+
+        if (!arg->getName().getString().empty())
+            out << " " << hashName(arg->getName());
+        if (type.isArray())
+            out << arrayBrackets(type);
+
+        // Put a comma if this is not the last argument.
+        if (iter != args.end() - 1)
+            out << ", ";
+    }
+}
+
+const TConstantUnion *TOutputGLSLBase::writeConstantUnion(const TType &type,
+                                                          const TConstantUnion *pConstUnion)
+{
+    TInfoSinkBase &out = objSink();
+
+    if (type.getBasicType() == EbtStruct)
+    {
+        const TStructure *structure = type.getStruct();
+        out << hashName(TName(structure->name())) << "(";
+
+        const TFieldList &fields = structure->fields();
+        for (size_t i = 0; i < fields.size(); ++i)
+        {
+            const TType *fieldType = fields[i]->type();
+            ASSERT(fieldType != nullptr);
+            pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
+            if (i != fields.size() - 1)
+                out << ", ";
+        }
+        out << ")";
+    }
+    else
+    {
+        size_t size    = type.getObjectSize();
+        bool writeType = size > 1;
+        if (writeType)
+            out << getTypeName(type) << "(";
+        for (size_t i = 0; i < size; ++i, ++pConstUnion)
+        {
+            switch (pConstUnion->getType())
+            {
+                case EbtFloat:
+                    writeFloat(out, pConstUnion->getFConst());
+                    break;
+                case EbtInt:
+                    out << pConstUnion->getIConst();
+                    break;
+                case EbtUInt:
+                    out << pConstUnion->getUConst() << "u";
+                    break;
+                case EbtBool:
+                    out << pConstUnion->getBConst();
+                    break;
+                case EbtYuvCscStandardEXT:
+                    out << getYuvCscStandardEXTString(pConstUnion->getYuvCscStandardEXTConst());
+                    break;
+                default:
+                    UNREACHABLE();
+            }
+            if (i != size - 1)
+                out << ", ";
+        }
+        if (writeType)
+            out << ")";
+    }
+    return pConstUnion;
+}
+
+void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type)
+{
+    TInfoSinkBase &out = objSink();
+    if (visit == PreVisit)
+    {
+        if (type.isArray())
+        {
+            out << getTypeName(type);
+            out << arrayBrackets(type);
+            out << "(";
+        }
+        else
+        {
+            out << getTypeName(type) << "(";
+        }
+    }
+    else
+    {
+        writeTriplet(visit, nullptr, ", ", ")");
+    }
+}
+
+void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
+{
+    TInfoSinkBase &out = objSink();
+    out << hashVariableName(node->getName());
+
+    if (mDeclaringVariables && node->getType().isArray())
+        out << arrayBrackets(node->getType());
+}
+
+void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node)
+{
+    writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+}
+
+bool TOutputGLSLBase::visitSwizzle(Visit visit, TIntermSwizzle *node)
+{
+    TInfoSinkBase &out = objSink();
+    if (visit == PostVisit)
+    {
+        out << ".";
+        node->writeOffsetsAsXYZW(&out);
+    }
+    return true;
+}
+
+bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
+{
+    bool visitChildren = true;
+    TInfoSinkBase &out = objSink();
+    switch (node->getOp())
+    {
+        case EOpComma:
+            writeTriplet(visit, "(", ", ", ")");
+            break;
+        case EOpInitialize:
+            if (visit == InVisit)
+            {
+                out << " = ";
+                // RHS of initialize is not being declared.
+                mDeclaringVariables = false;
+            }
+            break;
+        case EOpAssign:
+            writeTriplet(visit, "(", " = ", ")");
+            break;
+        case EOpAddAssign:
+            writeTriplet(visit, "(", " += ", ")");
+            break;
+        case EOpSubAssign:
+            writeTriplet(visit, "(", " -= ", ")");
+            break;
+        case EOpDivAssign:
+            writeTriplet(visit, "(", " /= ", ")");
+            break;
+        case EOpIModAssign:
+            writeTriplet(visit, "(", " %= ", ")");
+            break;
+        // Notice the fall-through.
+        case EOpMulAssign:
+        case EOpVectorTimesMatrixAssign:
+        case EOpVectorTimesScalarAssign:
+        case EOpMatrixTimesScalarAssign:
+        case EOpMatrixTimesMatrixAssign:
+            writeTriplet(visit, "(", " *= ", ")");
+            break;
+        case EOpBitShiftLeftAssign:
+            writeTriplet(visit, "(", " <<= ", ")");
+            break;
+        case EOpBitShiftRightAssign:
+            writeTriplet(visit, "(", " >>= ", ")");
+            break;
+        case EOpBitwiseAndAssign:
+            writeTriplet(visit, "(", " &= ", ")");
+            break;
+        case EOpBitwiseXorAssign:
+            writeTriplet(visit, "(", " ^= ", ")");
+            break;
+        case EOpBitwiseOrAssign:
+            writeTriplet(visit, "(", " |= ", ")");
+            break;
+
+        case EOpIndexDirect:
+            writeTriplet(visit, nullptr, "[", "]");
+            break;
+        case EOpIndexIndirect:
+            if (node->getAddIndexClamp())
+            {
+                if (visit == InVisit)
+                {
+                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
+                        out << "[int(clamp(float(";
+                    else
+                        out << "[webgl_int_clamp(";
+                }
+                else if (visit == PostVisit)
+                {
+                    int maxSize;
+                    TIntermTyped *left = node->getLeft();
+                    TType leftType     = left->getType();
+
+                    if (left->isArray())
+                    {
+                        // The shader will fail validation if the array length is not > 0.
+                        maxSize = static_cast<int>(leftType.getArraySize()) - 1;
+                    }
+                    else
+                    {
+                        maxSize = leftType.getNominalSize() - 1;
+                    }
+
+                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
+                        out << "), 0.0, float(" << maxSize << ")))]";
+                    else
+                        out << ", 0, " << maxSize << ")]";
+                }
+            }
+            else
+            {
+                writeTriplet(visit, nullptr, "[", "]");
+            }
+            break;
+        case EOpIndexDirectStruct:
+            if (visit == InVisit)
+            {
+                // Here we are writing out "foo.bar", where "foo" is struct
+                // and "bar" is field. In AST, it is represented as a binary
+                // node, where left child represents "foo" and right child "bar".
+                // The node itself represents ".". The struct field "bar" is
+                // actually stored as an index into TStructure::fields.
+                out << ".";
+                const TStructure *structure       = node->getLeft()->getType().getStruct();
+                const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
+                const TField *field               = structure->fields()[index->getIConst(0)];
+
+                TString fieldName = field->name();
+                if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion))
+                    fieldName = hashName(TName(fieldName));
+
+                out << fieldName;
+                visitChildren = false;
+            }
+            break;
+        case EOpIndexDirectInterfaceBlock:
+            if (visit == InVisit)
+            {
+                out << ".";
+                const TInterfaceBlock *interfaceBlock =
+                    node->getLeft()->getType().getInterfaceBlock();
+                const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
+                const TField *field               = interfaceBlock->fields()[index->getIConst(0)];
+
+                TString fieldName = field->name();
+                ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion));
+                fieldName = hashName(TName(fieldName));
+
+                out << fieldName;
+                visitChildren = false;
+            }
+            break;
+
+        case EOpAdd:
+            writeTriplet(visit, "(", " + ", ")");
+            break;
+        case EOpSub:
+            writeTriplet(visit, "(", " - ", ")");
+            break;
+        case EOpMul:
+            writeTriplet(visit, "(", " * ", ")");
+            break;
+        case EOpDiv:
+            writeTriplet(visit, "(", " / ", ")");
+            break;
+        case EOpIMod:
+            writeTriplet(visit, "(", " % ", ")");
+            break;
+        case EOpBitShiftLeft:
+            writeTriplet(visit, "(", " << ", ")");
+            break;
+        case EOpBitShiftRight:
+            writeTriplet(visit, "(", " >> ", ")");
+            break;
+        case EOpBitwiseAnd:
+            writeTriplet(visit, "(", " & ", ")");
+            break;
+        case EOpBitwiseXor:
+            writeTriplet(visit, "(", " ^ ", ")");
+            break;
+        case EOpBitwiseOr:
+            writeTriplet(visit, "(", " | ", ")");
+            break;
+
+        case EOpEqual:
+            writeTriplet(visit, "(", " == ", ")");
+            break;
+        case EOpNotEqual:
+            writeTriplet(visit, "(", " != ", ")");
+            break;
+        case EOpLessThan:
+            writeTriplet(visit, "(", " < ", ")");
+            break;
+        case EOpGreaterThan:
+            writeTriplet(visit, "(", " > ", ")");
+            break;
+        case EOpLessThanEqual:
+            writeTriplet(visit, "(", " <= ", ")");
+            break;
+        case EOpGreaterThanEqual:
+            writeTriplet(visit, "(", " >= ", ")");
+            break;
+
+        // Notice the fall-through.
+        case EOpVectorTimesScalar:
+        case EOpVectorTimesMatrix:
+        case EOpMatrixTimesVector:
+        case EOpMatrixTimesScalar:
+        case EOpMatrixTimesMatrix:
+            writeTriplet(visit, "(", " * ", ")");
+            break;
+
+        case EOpLogicalOr:
+            writeTriplet(visit, "(", " || ", ")");
+            break;
+        case EOpLogicalXor:
+            writeTriplet(visit, "(", " ^^ ", ")");
+            break;
+        case EOpLogicalAnd:
+            writeTriplet(visit, "(", " && ", ")");
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return visitChildren;
+}
+
+bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
+{
+    TString preString;
+    TString postString = ")";
+
+    switch (node->getOp())
+    {
+        case EOpNegative:
+            preString = "(-";
+            break;
+        case EOpPositive:
+            preString = "(+";
+            break;
+        case EOpLogicalNot:
+            preString = "(!";
+            break;
+        case EOpBitwiseNot:
+            preString = "(~";
+            break;
+
+        case EOpPostIncrement:
+            preString  = "(";
+            postString = "++)";
+            break;
+        case EOpPostDecrement:
+            preString  = "(";
+            postString = "--)";
+            break;
+        case EOpPreIncrement:
+            preString = "(++";
+            break;
+        case EOpPreDecrement:
+            preString = "(--";
+            break;
+
+        case EOpRadians:
+        case EOpDegrees:
+        case EOpSin:
+        case EOpCos:
+        case EOpTan:
+        case EOpAsin:
+        case EOpAcos:
+        case EOpAtan:
+        case EOpSinh:
+        case EOpCosh:
+        case EOpTanh:
+        case EOpAsinh:
+        case EOpAcosh:
+        case EOpAtanh:
+        case EOpExp:
+        case EOpLog:
+        case EOpExp2:
+        case EOpLog2:
+        case EOpSqrt:
+        case EOpInverseSqrt:
+        case EOpAbs:
+        case EOpSign:
+        case EOpFloor:
+        case EOpTrunc:
+        case EOpRound:
+        case EOpRoundEven:
+        case EOpCeil:
+        case EOpFract:
+        case EOpIsNan:
+        case EOpIsInf:
+        case EOpFloatBitsToInt:
+        case EOpFloatBitsToUint:
+        case EOpIntBitsToFloat:
+        case EOpUintBitsToFloat:
+        case EOpPackSnorm2x16:
+        case EOpPackUnorm2x16:
+        case EOpPackHalf2x16:
+        case EOpUnpackSnorm2x16:
+        case EOpUnpackUnorm2x16:
+        case EOpUnpackHalf2x16:
+        case EOpPackUnorm4x8:
+        case EOpPackSnorm4x8:
+        case EOpUnpackUnorm4x8:
+        case EOpUnpackSnorm4x8:
+        case EOpLength:
+        case EOpNormalize:
+        case EOpDFdx:
+        case EOpDFdy:
+        case EOpFwidth:
+        case EOpTranspose:
+        case EOpDeterminant:
+        case EOpInverse:
+        case EOpAny:
+        case EOpAll:
+        case EOpLogicalNotComponentWise:
+        case EOpBitfieldReverse:
+        case EOpBitCount:
+        case EOpFindLSB:
+        case EOpFindMSB:
+            writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
+            return true;
+        default:
+            UNREACHABLE();
+    }
+
+    writeTriplet(visit, preString.c_str(), nullptr, postString.c_str());
+
+    return true;
+}
+
+bool TOutputGLSLBase::visitTernary(Visit visit, TIntermTernary *node)
+{
+    TInfoSinkBase &out = objSink();
+    // Notice two brackets at the beginning and end. The outer ones
+    // encapsulate the whole ternary expression. This preserves the
+    // order of precedence when ternary expressions are used in a
+    // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
+    out << "((";
+    node->getCondition()->traverse(this);
+    out << ") ? (";
+    node->getTrueExpression()->traverse(this);
+    out << ") : (";
+    node->getFalseExpression()->traverse(this);
+    out << "))";
+    return false;
+}
+
+bool TOutputGLSLBase::visitIfElse(Visit visit, TIntermIfElse *node)
+{
+    TInfoSinkBase &out = objSink();
+
+    out << "if (";
+    node->getCondition()->traverse(this);
+    out << ")\n";
+
+    visitCodeBlock(node->getTrueBlock());
+
+    if (node->getFalseBlock())
+    {
+        out << "else\n";
+        visitCodeBlock(node->getFalseBlock());
+    }
+    return false;
+}
+
+bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node)
+{
+    if (node->getStatementList())
+    {
+        writeTriplet(visit, "switch (", ") ", nullptr);
+        // The curly braces get written when visiting the statementList aggregate
+    }
+    else
+    {
+        // No statementList, so it won't output curly braces
+        writeTriplet(visit, "switch (", ") {", "}\n");
+    }
+    return true;
+}
+
+bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node)
+{
+    if (node->hasCondition())
+    {
+        writeTriplet(visit, "case (", nullptr, "):\n");
+        return true;
+    }
+    else
+    {
+        TInfoSinkBase &out = objSink();
+        out << "default:\n";
+        return false;
+    }
+}
+
+bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
+{
+    TInfoSinkBase &out = objSink();
+    // Scope the blocks except when at the global scope.
+    if (mDepth > 0)
+    {
+        out << "{\n";
+    }
+
+    for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
+         iter != node->getSequence()->end(); ++iter)
+    {
+        TIntermNode *curNode = *iter;
+        ASSERT(curNode != nullptr);
+        curNode->traverse(this);
+
+        if (isSingleStatement(curNode))
+            out << ";\n";
+    }
+
+    // Scope the blocks except when at the global scope.
+    if (mDepth > 0)
+    {
+        out << "}\n";
+    }
+    return false;
+}
+
+bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+{
+    TIntermFunctionPrototype *prototype = node->getFunctionPrototype();
+    prototype->traverse(this);
+    visitCodeBlock(node->getBody());
+
+    // Fully processed; no need to visit children.
+    return false;
+}
+
+bool TOutputGLSLBase::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+{
+    TInfoSinkBase &out = objSink();
+    ASSERT(visit == PreVisit);
+    const TIntermSymbol *symbol = node->getSymbol();
+    out << "invariant " << hashVariableName(symbol->getName());
+    return false;
+}
+
+bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+{
+    TInfoSinkBase &out = objSink();
+    ASSERT(visit == PreVisit);
+
+    const TType &type = node->getType();
+    writeVariableType(type);
+    if (type.isArray())
+        out << arrayBrackets(type);
+
+    out << " " << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
+
+    out << "(";
+    writeFunctionParameters(*(node->getSequence()));
+    out << ")";
+
+    return false;
+}
+
+bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    bool visitChildren       = true;
+    TInfoSinkBase &out       = objSink();
+    switch (node->getOp())
+    {
+        case EOpCallFunctionInAST:
+        case EOpCallInternalRawFunction:
+        case EOpCallBuiltInFunction:
+            // Function call.
+            if (visit == PreVisit)
+            {
+                if (node->getOp() == EOpCallBuiltInFunction)
+                {
+                    out << translateTextureFunction(node->getFunctionSymbolInfo()->getName());
+                }
+                else
+                {
+                    out << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
+                }
+                out << "(";
+            }
+            else if (visit == InVisit)
+                out << ", ";
+            else
+                out << ")";
+            break;
+        case EOpConstruct:
+            writeConstructorTriplet(visit, node->getType());
+            break;
+
+        case EOpEqualComponentWise:
+        case EOpNotEqualComponentWise:
+        case EOpLessThanComponentWise:
+        case EOpGreaterThanComponentWise:
+        case EOpLessThanEqualComponentWise:
+        case EOpGreaterThanEqualComponentWise:
+        case EOpMod:
+        case EOpModf:
+        case EOpPow:
+        case EOpAtan:
+        case EOpMin:
+        case EOpMax:
+        case EOpClamp:
+        case EOpMix:
+        case EOpStep:
+        case EOpSmoothStep:
+        case EOpFrexp:
+        case EOpLdexp:
+        case EOpDistance:
+        case EOpDot:
+        case EOpCross:
+        case EOpFaceForward:
+        case EOpReflect:
+        case EOpRefract:
+        case EOpMulMatrixComponentWise:
+        case EOpOuterProduct:
+        case EOpBitfieldExtract:
+        case EOpBitfieldInsert:
+        case EOpUaddCarry:
+        case EOpUsubBorrow:
+        case EOpUmulExtended:
+        case EOpImulExtended:
+        case EOpBarrier:
+        case EOpMemoryBarrier:
+        case EOpMemoryBarrierAtomicCounter:
+        case EOpMemoryBarrierBuffer:
+        case EOpMemoryBarrierImage:
+        case EOpMemoryBarrierShared:
+        case EOpGroupMemoryBarrier:
+            writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
+            break;
+        default:
+            UNREACHABLE();
+    }
+    return visitChildren;
+}
+
+bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+    TInfoSinkBase &out = objSink();
+
+    // Variable declaration.
+    if (visit == PreVisit)
+    {
+        const TIntermSequence &sequence = *(node->getSequence());
+        const TIntermTyped *variable    = sequence.front()->getAsTyped();
+        writeLayoutQualifier(variable->getType());
+        writeVariableType(variable->getType());
+        out << " ";
+        mDeclaringVariables = true;
+    }
+    else if (visit == InVisit)
+    {
+        out << ", ";
+        mDeclaringVariables = true;
+    }
+    else
+    {
+        mDeclaringVariables = false;
+    }
+    return true;
+}
+
+bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
+{
+    TInfoSinkBase &out = objSink();
+
+    TLoopType loopType = node->getType();
+
+    if (loopType == ELoopFor)  // for loop
+    {
+        out << "for (";
+        if (node->getInit())
+            node->getInit()->traverse(this);
+        out << "; ";
+
+        if (node->getCondition())
+            node->getCondition()->traverse(this);
+        out << "; ";
+
+        if (node->getExpression())
+            node->getExpression()->traverse(this);
+        out << ")\n";
+
+        visitCodeBlock(node->getBody());
+    }
+    else if (loopType == ELoopWhile)  // while loop
+    {
+        out << "while (";
+        ASSERT(node->getCondition() != nullptr);
+        node->getCondition()->traverse(this);
+        out << ")\n";
+
+        visitCodeBlock(node->getBody());
+    }
+    else  // do-while loop
+    {
+        ASSERT(loopType == ELoopDoWhile);
+        out << "do\n";
+
+        visitCodeBlock(node->getBody());
+
+        out << "while (";
+        ASSERT(node->getCondition() != nullptr);
+        node->getCondition()->traverse(this);
+        out << ");\n";
+    }
+
+    // No need to visit children. They have been already processed in
+    // this function.
+    return false;
+}
+
+bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node)
+{
+    switch (node->getFlowOp())
+    {
+        case EOpKill:
+            writeTriplet(visit, "discard", nullptr, nullptr);
+            break;
+        case EOpBreak:
+            writeTriplet(visit, "break", nullptr, nullptr);
+            break;
+        case EOpContinue:
+            writeTriplet(visit, "continue", nullptr, nullptr);
+            break;
+        case EOpReturn:
+            writeTriplet(visit, "return ", nullptr, nullptr);
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return true;
+}
+
+void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node)
+{
+    TInfoSinkBase &out = objSink();
+    if (node != nullptr)
+    {
+        node->traverse(this);
+        // Single statements not part of a sequence need to be terminated
+        // with semi-colon.
+        if (isSingleStatement(node))
+            out << ";\n";
+    }
+    else
+    {
+        out << "{\n}\n";  // Empty code block.
+    }
+}
+
+TString TOutputGLSLBase::getTypeName(const TType &type)
+{
+    if (type.getBasicType() == EbtStruct)
+        return hashName(TName(type.getStruct()->name()));
+    else
+        return type.getBuiltInTypeNameString();
+}
+
+TString TOutputGLSLBase::hashName(const TName &name)
+{
+    if (name.getString().empty())
+    {
+        ASSERT(!name.isInternal());
+        return name.getString();
+    }
+    if (name.isInternal())
+    {
+        // TODO(oetuaho): Would be nicer to prefix non-internal names with "_" instead, like is
+        // done in the HLSL output, but that requires fairly complex changes elsewhere in the code
+        // as well.
+        // We need to use a prefix that is reserved in WebGL in order to guarantee that the internal
+        // names don't conflict with user-defined names from WebGL.
+        return "webgl_angle_" + name.getString();
+    }
+    if (mHashFunction == nullptr)
+    {
+        return name.getString();
+    }
+    NameMap::const_iterator it = mNameMap.find(name.getString().c_str());
+    if (it != mNameMap.end())
+        return it->second.c_str();
+    TString hashedName                 = TIntermTraverser::hash(name.getString(), mHashFunction);
+    mNameMap[name.getString().c_str()] = hashedName.c_str();
+    return hashedName;
+}
+
+TString TOutputGLSLBase::hashVariableName(const TName &name)
+{
+    if (mSymbolTable.findBuiltIn(name.getString(), mShaderVersion) != nullptr)
+    {
+        if (mCompileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM &&
+            name.getString() == "gl_ViewID_OVR")
+        {
+            TName uniformName(TString("ViewID_OVR"));
+            uniformName.setInternal(true);
+            return hashName(uniformName);
+        }
+        return name.getString();
+    }
+    return hashName(name);
+}
+
+TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info)
+{
+    if (info.isMain() || info.getNameObj().isInternal())
+    {
+        // Internal function names are outputted as-is - they may refer to functions manually added
+        // to the output shader source that are not included in the AST at all.
+        return info.getName();
+    }
+    else
+    {
+        return hashName(info.getNameObj());
+    }
+}
+
+bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
+{
+    ASSERT(structure);
+    if (structure->name().empty())
+    {
+        return false;
+    }
+
+    return (mDeclaredStructs.count(structure->uniqueId()) > 0);
+}
+
+void TOutputGLSLBase::declareStruct(const TStructure *structure)
+{
+    TInfoSinkBase &out = objSink();
+
+    out << "struct " << hashName(TName(structure->name())) << "{\n";
+    const TFieldList &fields = structure->fields();
+    for (size_t i = 0; i < fields.size(); ++i)
+    {
+        const TField *field = fields[i];
+        if (writeVariablePrecision(field->type()->getPrecision()))
+            out << " ";
+        out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
+        if (field->type()->isArray())
+            out << arrayBrackets(*field->type());
+        out << ";\n";
+    }
+    out << "}";
+}
+
+void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock)
+{
+    TInfoSinkBase &out = objSink();
+
+    out << "layout(";
+
+    switch (interfaceBlock->blockStorage())
+    {
+        case EbsUnspecified:
+        case EbsShared:
+            // Default block storage is shared.
+            out << "shared";
+            break;
+
+        case EbsPacked:
+            out << "packed";
+            break;
+
+        case EbsStd140:
+            out << "std140";
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    out << ", ";
+
+    switch (interfaceBlock->matrixPacking())
+    {
+        case EmpUnspecified:
+        case EmpColumnMajor:
+            // Default matrix packing is column major.
+            out << "column_major";
+            break;
+
+        case EmpRowMajor:
+            out << "row_major";
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    out << ") ";
+}
+
+void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBlock)
+{
+    TInfoSinkBase &out = objSink();
+
+    out << hashName(TName(interfaceBlock->name())) << "{\n";
+    const TFieldList &fields = interfaceBlock->fields();
+    for (size_t i = 0; i < fields.size(); ++i)
+    {
+        const TField *field = fields[i];
+        if (writeVariablePrecision(field->type()->getPrecision()))
+            out << " ";
+        out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
+        if (field->type()->isArray())
+            out << arrayBrackets(*field->type());
+        out << ";\n";
+    }
+    out << "}";
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/OutputGLSLBase.h b/src/third_party/angle/src/compiler/translator/OutputGLSLBase.h
new file mode 100644
index 0000000..af3019c
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputGLSLBase.h
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
+#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
+
+#include <set>
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
+
+class TOutputGLSLBase : public TIntermTraverser
+{
+  public:
+    TOutputGLSLBase(TInfoSinkBase &objSink,
+                    ShArrayIndexClampingStrategy clampingStrategy,
+                    ShHashFunction64 hashFunction,
+                    NameMap &nameMap,
+                    TSymbolTable &symbolTable,
+                    sh::GLenum shaderType,
+                    int shaderVersion,
+                    ShShaderOutput output,
+                    ShCompileOptions compileOptions);
+
+    ShShaderOutput getShaderOutput() const { return mOutput; }
+
+    // Return the original name if hash function pointer is NULL;
+    // otherwise return the hashed name. Has special handling for internal names, which are not
+    // hashed.
+    TString hashName(const TName &name);
+
+  protected:
+    TInfoSinkBase &objSink() { return mObjSink; }
+    void writeFloat(TInfoSinkBase &out, float f);
+    void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr);
+    virtual void writeLayoutQualifier(const TType &type);
+    void writeInvariantQualifier(const TType &type);
+    void writeVariableType(const TType &type);
+    virtual bool writeVariablePrecision(TPrecision precision) = 0;
+    void writeFunctionParameters(const TIntermSequence &args);
+    const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion);
+    void writeConstructorTriplet(Visit visit, const TType &type);
+    TString getTypeName(const TType &type);
+
+    void visitSymbol(TIntermSymbol *node) override;
+    void visitConstantUnion(TIntermConstantUnion *node) override;
+    bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+    bool visitUnary(Visit visit, TIntermUnary *node) override;
+    bool visitTernary(Visit visit, TIntermTernary *node) override;
+    bool visitIfElse(Visit visit, TIntermIfElse *node) override;
+    bool visitSwitch(Visit visit, TIntermSwitch *node) override;
+    bool visitCase(Visit visit, TIntermCase *node) override;
+    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    bool visitBlock(Visit visit, TIntermBlock *node) override;
+    bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
+    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+    bool visitLoop(Visit visit, TIntermLoop *node) override;
+    bool visitBranch(Visit visit, TIntermBranch *node) override;
+
+    void visitCodeBlock(TIntermBlock *node);
+
+    // Same as hashName(), but without hashing built-in variables.
+    TString hashVariableName(const TName &name);
+    // Same as hashName(), but without hashing internal functions or "main".
+    TString hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info);
+    // Used to translate function names for differences between ESSL and GLSL
+    virtual TString translateTextureFunction(const TString &name) { return name; }
+
+  private:
+    bool structDeclared(const TStructure *structure) const;
+    void declareStruct(const TStructure *structure);
+
+    void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock);
+    void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock);
+
+    void writeBuiltInFunctionTriplet(Visit visit, TOperator op, bool useEmulatedFunction);
+
+    const char *mapQualifierToString(TQualifier qialifier);
+
+    TInfoSinkBase &mObjSink;
+    bool mDeclaringVariables;
+
+    // This set contains all the ids of the structs from every scope.
+    std::set<int> mDeclaredStructs;
+
+    ShArrayIndexClampingStrategy mClampingStrategy;
+
+    // name hashing.
+    ShHashFunction64 mHashFunction;
+
+    NameMap &mNameMap;
+
+    TSymbolTable &mSymbolTable;
+
+    sh::GLenum mShaderType;
+
+    const int mShaderVersion;
+
+    ShShaderOutput mOutput;
+
+    ShCompileOptions mCompileOptions;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
diff --git a/src/third_party/angle/src/compiler/translator/OutputHLSL.cpp b/src/third_party/angle/src/compiler/translator/OutputHLSL.cpp
new file mode 100644
index 0000000..0ee29eb
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputHLSL.cpp
@@ -0,0 +1,2980 @@
+//
+// 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.
+//
+
+#include "compiler/translator/OutputHLSL.h"
+
+#include <algorithm>
+#include <cfloat>
+#include <stdio.h>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
+#include "compiler/translator/FlagStd140Structs.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/NodeSearch.h"
+#include "compiler/translator/RemoveSwitchFallThrough.h"
+#include "compiler/translator/SearchSymbol.h"
+#include "compiler/translator/StructureHLSL.h"
+#include "compiler/translator/TextureFunctionHLSL.h"
+#include "compiler/translator/TranslatorHLSL.h"
+#include "compiler/translator/UniformHLSL.h"
+#include "compiler/translator/UtilsHLSL.h"
+#include "compiler/translator/blocklayout.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+void OutputHLSL::writeFloat(TInfoSinkBase &out, float f)
+{
+    // This is known not to work for NaN on all drivers but make the best effort to output NaNs
+    // regardless.
+    if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300 &&
+        mOutputType == SH_HLSL_4_1_OUTPUT)
+    {
+        out << "asfloat(" << gl::bitCast<uint32_t>(f) << "u)";
+    }
+    else
+    {
+        out << std::min(FLT_MAX, std::max(-FLT_MAX, f));
+    }
+}
+
+void OutputHLSL::writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion)
+{
+    ASSERT(constUnion != nullptr);
+    switch (constUnion->getType())
+    {
+        case EbtFloat:
+            writeFloat(out, constUnion->getFConst());
+            break;
+        case EbtInt:
+            out << constUnion->getIConst();
+            break;
+        case EbtUInt:
+            out << constUnion->getUConst();
+            break;
+        case EbtBool:
+            out << constUnion->getBConst();
+            break;
+        default:
+            UNREACHABLE();
+    }
+}
+
+const TConstantUnion *OutputHLSL::writeConstantUnionArray(TInfoSinkBase &out,
+                                                          const TConstantUnion *const constUnion,
+                                                          const size_t size)
+{
+    const TConstantUnion *constUnionIterated = constUnion;
+    for (size_t i = 0; i < size; i++, constUnionIterated++)
+    {
+        writeSingleConstant(out, constUnionIterated);
+
+        if (i != size - 1)
+        {
+            out << ", ";
+        }
+    }
+    return constUnionIterated;
+}
+
+OutputHLSL::OutputHLSL(sh::GLenum shaderType,
+                       int shaderVersion,
+                       const TExtensionBehavior &extensionBehavior,
+                       const char *sourcePath,
+                       ShShaderOutput outputType,
+                       int numRenderTargets,
+                       const std::vector<Uniform> &uniforms,
+                       ShCompileOptions compileOptions)
+    : TIntermTraverser(true, true, true),
+      mShaderType(shaderType),
+      mShaderVersion(shaderVersion),
+      mExtensionBehavior(extensionBehavior),
+      mSourcePath(sourcePath),
+      mOutputType(outputType),
+      mCompileOptions(compileOptions),
+      mNumRenderTargets(numRenderTargets),
+      mCurrentFunctionMetadata(nullptr)
+{
+    mInsideFunction = false;
+
+    mUsesFragColor               = false;
+    mUsesFragData                = false;
+    mUsesDepthRange              = false;
+    mUsesFragCoord               = false;
+    mUsesPointCoord              = false;
+    mUsesFrontFacing             = false;
+    mUsesPointSize               = false;
+    mUsesInstanceID              = false;
+    mUsesVertexID                = false;
+    mUsesFragDepth               = false;
+    mUsesNumWorkGroups           = false;
+    mUsesWorkGroupID             = false;
+    mUsesLocalInvocationID       = false;
+    mUsesGlobalInvocationID      = false;
+    mUsesLocalInvocationIndex    = false;
+    mUsesXor                     = false;
+    mUsesDiscardRewriting        = false;
+    mUsesNestedBreak             = false;
+    mRequiresIEEEStrictCompiling = false;
+
+    mUniqueIndex = 0;
+
+    mOutputLod0Function      = false;
+    mInsideDiscontinuousLoop = false;
+    mNestedLoopDepth         = 0;
+
+    mExcessiveLoopIndex = nullptr;
+
+    mStructureHLSL       = new StructureHLSL;
+    mUniformHLSL         = new UniformHLSL(mStructureHLSL, outputType, uniforms);
+    mTextureFunctionHLSL = new TextureFunctionHLSL;
+
+    if (mOutputType == SH_HLSL_3_0_OUTPUT)
+    {
+        // Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront.
+        // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and
+        // dx_ViewAdjust.
+        // In both cases total 3 uniform registers need to be reserved.
+        mUniformHLSL->reserveUniformRegisters(3);
+    }
+
+    // Reserve registers for the default uniform block and driver constants
+    mUniformHLSL->reserveInterfaceBlockRegisters(2);
+}
+
+OutputHLSL::~OutputHLSL()
+{
+    SafeDelete(mStructureHLSL);
+    SafeDelete(mUniformHLSL);
+    SafeDelete(mTextureFunctionHLSL);
+    for (auto &eqFunction : mStructEqualityFunctions)
+    {
+        SafeDelete(eqFunction);
+    }
+    for (auto &eqFunction : mArrayEqualityFunctions)
+    {
+        SafeDelete(eqFunction);
+    }
+}
+
+void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink)
+{
+    const std::vector<TIntermTyped *> &flaggedStructs = FlagStd140ValueStructs(treeRoot);
+    makeFlaggedStructMaps(flaggedStructs);
+
+    BuiltInFunctionEmulator builtInFunctionEmulator;
+    InitBuiltInFunctionEmulatorForHLSL(&builtInFunctionEmulator);
+    if ((mCompileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION) != 0)
+    {
+        InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(&builtInFunctionEmulator,
+                                                           mShaderVersion);
+    }
+
+    builtInFunctionEmulator.markBuiltInFunctionsForEmulation(treeRoot);
+
+    // Now that we are done changing the AST, do the analyses need for HLSL generation
+    CallDAG::InitResult success = mCallDag.init(treeRoot, nullptr);
+    ASSERT(success == CallDAG::INITDAG_SUCCESS);
+    mASTMetadataList = CreateASTMetadataHLSL(treeRoot, mCallDag);
+
+    // Output the body and footer first to determine what has to go in the header
+    mInfoSinkStack.push(&mBody);
+    treeRoot->traverse(this);
+    mInfoSinkStack.pop();
+
+    mInfoSinkStack.push(&mFooter);
+    mInfoSinkStack.pop();
+
+    mInfoSinkStack.push(&mHeader);
+    header(mHeader, &builtInFunctionEmulator);
+    mInfoSinkStack.pop();
+
+    objSink << mHeader.c_str();
+    objSink << mBody.c_str();
+    objSink << mFooter.c_str();
+
+    builtInFunctionEmulator.cleanup();
+}
+
+void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs)
+{
+    for (unsigned int structIndex = 0; structIndex < flaggedStructs.size(); structIndex++)
+    {
+        TIntermTyped *flaggedNode = flaggedStructs[structIndex];
+
+        TInfoSinkBase structInfoSink;
+        mInfoSinkStack.push(&structInfoSink);
+
+        // This will mark the necessary block elements as referenced
+        flaggedNode->traverse(this);
+
+        TString structName(structInfoSink.c_str());
+        mInfoSinkStack.pop();
+
+        mFlaggedStructOriginalNames[flaggedNode] = structName;
+
+        for (size_t pos = structName.find('.'); pos != std::string::npos;
+             pos        = structName.find('.'))
+        {
+            structName.erase(pos, 1);
+        }
+
+        mFlaggedStructMappedNames[flaggedNode] = "map" + structName;
+    }
+}
+
+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();
+}
+
+int OutputHLSL::vectorSize(const TType &type) const
+{
+    int elementSize        = type.isMatrix() ? type.getCols() : 1;
+    unsigned int arraySize = type.isArray() ? type.getArraySize() : 1u;
+
+    return elementSize * arraySize;
+}
+
+TString OutputHLSL::structInitializerString(int indent,
+                                            const TStructure &structure,
+                                            const TString &rhsStructName)
+{
+    TString init;
+
+    TString preIndentString;
+    TString fullIndentString;
+
+    for (int spaces = 0; spaces < (indent * 4); spaces++)
+    {
+        preIndentString += ' ';
+    }
+
+    for (int spaces = 0; spaces < ((indent + 1) * 4); spaces++)
+    {
+        fullIndentString += ' ';
+    }
+
+    init += preIndentString + "{\n";
+
+    const TFieldList &fields = structure.fields();
+    for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+    {
+        const TField &field      = *fields[fieldIndex];
+        const TString &fieldName = rhsStructName + "." + Decorate(field.name());
+        const TType &fieldType   = *field.type();
+
+        if (fieldType.getStruct())
+        {
+            init += structInitializerString(indent + 1, *fieldType.getStruct(), fieldName);
+        }
+        else
+        {
+            init += fullIndentString + fieldName + ",\n";
+        }
+    }
+
+    init += preIndentString + "}" + (indent == 0 ? ";" : ",") + "\n";
+
+    return init;
+}
+
+void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *builtInFunctionEmulator)
+{
+    TString varyings;
+    TString attributes;
+    TString flaggedStructs;
+
+    for (std::map<TIntermTyped *, TString>::const_iterator flaggedStructIt =
+             mFlaggedStructMappedNames.begin();
+         flaggedStructIt != mFlaggedStructMappedNames.end(); flaggedStructIt++)
+    {
+        TIntermTyped *structNode    = flaggedStructIt->first;
+        const TString &mappedName   = flaggedStructIt->second;
+        const TStructure &structure = *structNode->getType().getStruct();
+        const TString &originalName = mFlaggedStructOriginalNames[structNode];
+
+        flaggedStructs += "static " + Decorate(structure.name()) + " " + mappedName + " =\n";
+        flaggedStructs += structInitializerString(0, structure, originalName);
+        flaggedStructs += "\n";
+    }
+
+    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";
+    }
+
+    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";
+    }
+
+    out << mStructureHLSL->structsHeader();
+
+    mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms);
+    out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks);
+
+    if (!mEqualityFunctions.empty())
+    {
+        out << "\n// Equality functions\n\n";
+        for (const auto &eqFunction : mEqualityFunctions)
+        {
+            out << eqFunction->functionDefinition << "\n";
+        }
+    }
+    if (!mArrayAssignmentFunctions.empty())
+    {
+        out << "\n// Assignment functions\n\n";
+        for (const auto &assignmentFunction : mArrayAssignmentFunctions)
+        {
+            out << assignmentFunction.functionDefinition << "\n";
+        }
+    }
+    if (!mArrayConstructIntoFunctions.empty())
+    {
+        out << "\n// Array constructor functions\n\n";
+        for (const auto &constructIntoFunction : mArrayConstructIntoFunctions)
+        {
+            out << constructIntoFunction.functionDefinition << "\n";
+        }
+    }
+
+    if (mUsesDiscardRewriting)
+    {
+        out << "#define ANGLE_USES_DISCARD_REWRITING\n";
+    }
+
+    if (mUsesNestedBreak)
+    {
+        out << "#define ANGLE_USES_NESTED_BREAK\n";
+    }
+
+    if (mRequiresIEEEStrictCompiling)
+    {
+        out << "#define ANGLE_REQUIRES_IEEE_STRICT_COMPILING\n";
+    }
+
+    out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n"
+           "#define LOOP [loop]\n"
+           "#define FLATTEN [flatten]\n"
+           "#else\n"
+           "#define LOOP\n"
+           "#define FLATTEN\n"
+           "#endif\n";
+
+    if (mShaderType == GL_FRAGMENT_SHADER)
+    {
+        TExtensionBehavior::const_iterator iter = mExtensionBehavior.find("GL_EXT_draw_buffers");
+        const bool usingMRTExtension            = (iter != mExtensionBehavior.end() &&
+                                        (iter->second == EBhEnable || iter->second == EBhRequire));
+
+        out << "// Varyings\n";
+        out << varyings;
+        out << "\n";
+
+        if (mShaderVersion >= 300)
+        {
+            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";
+            }
+        }
+        else
+        {
+            const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
+
+            out << "static float4 gl_Color[" << numColorValues << "] =\n"
+                                                                  "{\n";
+            for (unsigned int i = 0; i < numColorValues; i++)
+            {
+                out << "    float4(0, 0, 0, 0)";
+                if (i + 1 != numColorValues)
+                {
+                    out << ",";
+                }
+                out << "\n";
+            }
+
+            out << "};\n";
+        }
+
+        if (mUsesFragDepth)
+        {
+            out << "static float gl_Depth = 0.0;\n";
+        }
+
+        if (mUsesFragCoord)
+        {
+            out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
+        }
+
+        if (mUsesPointCoord)
+        {
+            out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n";
+        }
+
+        if (mUsesFrontFacing)
+        {
+            out << "static bool gl_FrontFacing = false;\n";
+        }
+
+        out << "\n";
+
+        if (mUsesDepthRange)
+        {
+            out << "struct gl_DepthRangeParameters\n"
+                   "{\n"
+                   "    float near;\n"
+                   "    float far;\n"
+                   "    float diff;\n"
+                   "};\n"
+                   "\n";
+        }
+
+        if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+        {
+            out << "cbuffer DriverConstants : register(b1)\n"
+                   "{\n";
+
+            if (mUsesDepthRange)
+            {
+                out << "    float3 dx_DepthRange : packoffset(c0);\n";
+            }
+
+            if (mUsesFragCoord)
+            {
+                out << "    float4 dx_ViewCoords : packoffset(c1);\n";
+            }
+
+            if (mUsesFragCoord || mUsesFrontFacing)
+            {
+                out << "    float3 dx_DepthFront : packoffset(c2);\n";
+            }
+
+            if (mUsesFragCoord)
+            {
+                // dx_ViewScale is only used in the fragment shader to correct
+                // the value for glFragCoord if necessary
+                out << "    float2 dx_ViewScale : packoffset(c3);\n";
+            }
+
+            if (mOutputType == SH_HLSL_4_1_OUTPUT)
+            {
+                mUniformHLSL->samplerMetadataUniforms(out, "c4");
+            }
+
+            out << "};\n";
+        }
+        else
+        {
+            if (mUsesDepthRange)
+            {
+                out << "uniform float3 dx_DepthRange : register(c0);";
+            }
+
+            if (mUsesFragCoord)
+            {
+                out << "uniform float4 dx_ViewCoords : register(c1);\n";
+            }
+
+            if (mUsesFragCoord || mUsesFrontFacing)
+            {
+                out << "uniform float3 dx_DepthFront : register(c2);\n";
+            }
+        }
+
+        out << "\n";
+
+        if (mUsesDepthRange)
+        {
+            out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, "
+                   "dx_DepthRange.y, dx_DepthRange.z};\n"
+                   "\n";
+        }
+
+        if (!flaggedStructs.empty())
+        {
+            out << "// Std140 Structures accessed by value\n";
+            out << "\n";
+            out << flaggedStructs;
+            out << "\n";
+        }
+
+        if (usingMRTExtension && mNumRenderTargets > 1)
+        {
+            out << "#define GL_USES_MRT\n";
+        }
+
+        if (mUsesFragColor)
+        {
+            out << "#define GL_USES_FRAG_COLOR\n";
+        }
+
+        if (mUsesFragData)
+        {
+            out << "#define GL_USES_FRAG_DATA\n";
+        }
+    }
+    else if (mShaderType == GL_VERTEX_SHADER)
+    {
+        out << "// Attributes\n";
+        out << attributes;
+        out << "\n"
+               "static float4 gl_Position = float4(0, 0, 0, 0);\n";
+
+        if (mUsesPointSize)
+        {
+            out << "static float gl_PointSize = float(1);\n";
+        }
+
+        if (mUsesInstanceID)
+        {
+            out << "static int gl_InstanceID;";
+        }
+
+        if (mUsesVertexID)
+        {
+            out << "static int gl_VertexID;";
+        }
+
+        out << "\n"
+               "// Varyings\n";
+        out << varyings;
+        out << "\n";
+
+        if (mUsesDepthRange)
+        {
+            out << "struct gl_DepthRangeParameters\n"
+                   "{\n"
+                   "    float near;\n"
+                   "    float far;\n"
+                   "    float diff;\n"
+                   "};\n"
+                   "\n";
+        }
+
+        if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+        {
+            out << "cbuffer DriverConstants : register(b1)\n"
+                   "{\n";
+
+            if (mUsesDepthRange)
+            {
+                out << "    float3 dx_DepthRange : packoffset(c0);\n";
+            }
+
+            // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9
+            // shaders. However, we declare it for all shaders (including Feature Level 10+).
+            // The bytecode is the same whether we declare it or not, since D3DCompiler removes it
+            // if it's unused.
+            out << "    float4 dx_ViewAdjust : packoffset(c1);\n";
+            out << "    float2 dx_ViewCoords : packoffset(c2);\n";
+            out << "    float2 dx_ViewScale  : packoffset(c3);\n";
+
+            if (mOutputType == SH_HLSL_4_1_OUTPUT)
+            {
+                mUniformHLSL->samplerMetadataUniforms(out, "c4");
+            }
+
+            out << "};\n"
+                   "\n";
+        }
+        else
+        {
+            if (mUsesDepthRange)
+            {
+                out << "uniform float3 dx_DepthRange : register(c0);\n";
+            }
+
+            out << "uniform float4 dx_ViewAdjust : register(c1);\n";
+            out << "uniform float2 dx_ViewCoords : register(c2);\n"
+                   "\n";
+        }
+
+        if (mUsesDepthRange)
+        {
+            out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, "
+                   "dx_DepthRange.y, dx_DepthRange.z};\n"
+                   "\n";
+        }
+
+        if (!flaggedStructs.empty())
+        {
+            out << "// Std140 Structures accessed by value\n";
+            out << "\n";
+            out << flaggedStructs;
+            out << "\n";
+        }
+    }
+    else  // Compute shader
+    {
+        ASSERT(mShaderType == GL_COMPUTE_SHADER);
+
+        out << "cbuffer DriverConstants : register(b1)\n"
+               "{\n";
+        if (mUsesNumWorkGroups)
+        {
+            out << "    uint3 gl_NumWorkGroups : packoffset(c0);\n";
+        }
+        ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT);
+        mUniformHLSL->samplerMetadataUniforms(out, "c1");
+        out << "};\n";
+
+        // Follow built-in variables would be initialized in
+        // DynamicHLSL::generateComputeShaderLinkHLSL, if they
+        // are used in compute shader.
+        if (mUsesWorkGroupID)
+        {
+            out << "static uint3 gl_WorkGroupID = uint3(0, 0, 0);\n";
+        }
+
+        if (mUsesLocalInvocationID)
+        {
+            out << "static uint3 gl_LocalInvocationID = uint3(0, 0, 0);\n";
+        }
+
+        if (mUsesGlobalInvocationID)
+        {
+            out << "static uint3 gl_GlobalInvocationID = uint3(0, 0, 0);\n";
+        }
+
+        if (mUsesLocalInvocationIndex)
+        {
+            out << "static uint gl_LocalInvocationIndex = uint(0);\n";
+        }
+    }
+
+    bool getDimensionsIgnoresBaseLevel =
+        (mCompileOptions & SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL) != 0;
+    mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel);
+
+    if (mUsesFragCoord)
+    {
+        out << "#define GL_USES_FRAG_COORD\n";
+    }
+
+    if (mUsesPointCoord)
+    {
+        out << "#define GL_USES_POINT_COORD\n";
+    }
+
+    if (mUsesFrontFacing)
+    {
+        out << "#define GL_USES_FRONT_FACING\n";
+    }
+
+    if (mUsesPointSize)
+    {
+        out << "#define GL_USES_POINT_SIZE\n";
+    }
+
+    if (mUsesFragDepth)
+    {
+        out << "#define GL_USES_FRAG_DEPTH\n";
+    }
+
+    if (mUsesDepthRange)
+    {
+        out << "#define GL_USES_DEPTH_RANGE\n";
+    }
+
+    if (mUsesNumWorkGroups)
+    {
+        out << "#define GL_USES_NUM_WORK_GROUPS\n";
+    }
+
+    if (mUsesWorkGroupID)
+    {
+        out << "#define GL_USES_WORK_GROUP_ID\n";
+    }
+
+    if (mUsesLocalInvocationID)
+    {
+        out << "#define GL_USES_LOCAL_INVOCATION_ID\n";
+    }
+
+    if (mUsesGlobalInvocationID)
+    {
+        out << "#define GL_USES_GLOBAL_INVOCATION_ID\n";
+    }
+
+    if (mUsesLocalInvocationIndex)
+    {
+        out << "#define GL_USES_LOCAL_INVOCATION_INDEX\n";
+    }
+
+    if (mUsesXor)
+    {
+        out << "bool xor(bool p, bool q)\n"
+               "{\n"
+               "    return (p || q) && !(p && q);\n"
+               "}\n"
+               "\n";
+    }
+
+    builtInFunctionEmulator->outputEmulatedFunctions(out);
+}
+
+void OutputHLSL::visitSymbol(TIntermSymbol *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    // Handle accessing std140 structs by value
+    if (mFlaggedStructMappedNames.count(node) > 0)
+    {
+        out << mFlaggedStructMappedNames[node];
+        return;
+    }
+
+    TString name = node->getSymbol();
+
+    if (name == "gl_DepthRange")
+    {
+        mUsesDepthRange = true;
+        out << name;
+    }
+    else
+    {
+        TQualifier qualifier = node->getQualifier();
+
+        if (qualifier == EvqUniform)
+        {
+            const TType &nodeType                 = node->getType();
+            const TInterfaceBlock *interfaceBlock = nodeType.getInterfaceBlock();
+
+            if (interfaceBlock)
+            {
+                mReferencedInterfaceBlocks[interfaceBlock->name()] = node;
+            }
+            else
+            {
+                mReferencedUniforms[name] = node;
+            }
+
+            ensureStructDefined(nodeType);
+
+            const TName &nameWithMetadata = node->getName();
+            out << DecorateUniform(nameWithMetadata, nodeType);
+        }
+        else if (qualifier == EvqAttribute || qualifier == EvqVertexIn)
+        {
+            mReferencedAttributes[name] = node;
+            out << Decorate(name);
+        }
+        else if (IsVarying(qualifier))
+        {
+            mReferencedVaryings[name] = node;
+            out << Decorate(name);
+        }
+        else if (qualifier == EvqFragmentOut)
+        {
+            mReferencedOutputVariables[name] = node;
+            out << "out_" << name;
+        }
+        else if (qualifier == EvqFragColor)
+        {
+            out << "gl_Color[0]";
+            mUsesFragColor = true;
+        }
+        else if (qualifier == EvqFragData)
+        {
+            out << "gl_Color";
+            mUsesFragData = true;
+        }
+        else if (qualifier == EvqFragCoord)
+        {
+            mUsesFragCoord = true;
+            out << name;
+        }
+        else if (qualifier == EvqPointCoord)
+        {
+            mUsesPointCoord = true;
+            out << name;
+        }
+        else if (qualifier == EvqFrontFacing)
+        {
+            mUsesFrontFacing = true;
+            out << name;
+        }
+        else if (qualifier == EvqPointSize)
+        {
+            mUsesPointSize = true;
+            out << name;
+        }
+        else if (qualifier == EvqInstanceID)
+        {
+            mUsesInstanceID = true;
+            out << name;
+        }
+        else if (qualifier == EvqVertexID)
+        {
+            mUsesVertexID = true;
+            out << name;
+        }
+        else if (name == "gl_FragDepthEXT" || name == "gl_FragDepth")
+        {
+            mUsesFragDepth = true;
+            out << "gl_Depth";
+        }
+        else if (qualifier == EvqNumWorkGroups)
+        {
+            mUsesNumWorkGroups = true;
+            out << name;
+        }
+        else if (qualifier == EvqWorkGroupID)
+        {
+            mUsesWorkGroupID = true;
+            out << name;
+        }
+        else if (qualifier == EvqLocalInvocationID)
+        {
+            mUsesLocalInvocationID = true;
+            out << name;
+        }
+        else if (qualifier == EvqGlobalInvocationID)
+        {
+            mUsesGlobalInvocationID = true;
+            out << name;
+        }
+        else if (qualifier == EvqLocalInvocationIndex)
+        {
+            mUsesLocalInvocationIndex = true;
+            out << name;
+        }
+        else
+        {
+            out << DecorateIfNeeded(node->getName());
+        }
+    }
+}
+
+void OutputHLSL::visitRaw(TIntermRaw *node)
+{
+    getInfoSink() << node->getRawText();
+}
+
+void OutputHLSL::outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out)
+{
+    if (type.isScalar() && !type.isArray())
+    {
+        if (op == EOpEqual)
+        {
+            outputTriplet(out, visit, "(", " == ", ")");
+        }
+        else
+        {
+            outputTriplet(out, visit, "(", " != ", ")");
+        }
+    }
+    else
+    {
+        if (visit == PreVisit && op == EOpNotEqual)
+        {
+            out << "!";
+        }
+
+        if (type.isArray())
+        {
+            const TString &functionName = addArrayEqualityFunction(type);
+            outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")");
+        }
+        else if (type.getBasicType() == EbtStruct)
+        {
+            const TStructure &structure = *type.getStruct();
+            const TString &functionName = addStructEqualityFunction(structure);
+            outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")");
+        }
+        else
+        {
+            ASSERT(type.isMatrix() || type.isVector());
+            outputTriplet(out, visit, "all(", " == ", ")");
+        }
+    }
+}
+
+bool OutputHLSL::ancestorEvaluatesToSamplerInStruct()
+{
+    for (unsigned int n = 0u; getAncestorNode(n) != nullptr; ++n)
+    {
+        TIntermNode *ancestor               = getAncestorNode(n);
+        const TIntermBinary *ancestorBinary = ancestor->getAsBinaryNode();
+        if (ancestorBinary == nullptr)
+        {
+            return false;
+        }
+        switch (ancestorBinary->getOp())
+        {
+            case EOpIndexDirectStruct:
+            {
+                const TStructure *structure = ancestorBinary->getLeft()->getType().getStruct();
+                const TIntermConstantUnion *index =
+                    ancestorBinary->getRight()->getAsConstantUnion();
+                const TField *field = structure->fields()[index->getIConst(0)];
+                if (IsSampler(field->type()->getBasicType()))
+                {
+                    return true;
+                }
+                break;
+            }
+            case EOpIndexDirect:
+                break;
+            default:
+                // Returning a sampler from indirect indexing is not supported.
+                return false;
+        }
+    }
+    return false;
+}
+
+bool OutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+    if (visit == PostVisit)
+    {
+        out << ".";
+        node->writeOffsetsAsXYZW(&out);
+    }
+    return true;
+}
+
+bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    // Handle accessing std140 structs by value
+    if (mFlaggedStructMappedNames.count(node) > 0)
+    {
+        out << mFlaggedStructMappedNames[node];
+        return false;
+    }
+
+    switch (node->getOp())
+    {
+        case EOpComma:
+            outputTriplet(out, visit, "(", ", ", ")");
+            break;
+        case EOpAssign:
+            if (node->getLeft()->isArray())
+            {
+                TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
+                if (rightAgg != nullptr && rightAgg->isConstructor())
+                {
+                    const TString &functionName = addArrayConstructIntoFunction(node->getType());
+                    out << functionName << "(";
+                    node->getLeft()->traverse(this);
+                    TIntermSequence *seq = rightAgg->getSequence();
+                    for (auto &arrayElement : *seq)
+                    {
+                        out << ", ";
+                        arrayElement->traverse(this);
+                    }
+                    out << ")";
+                    return false;
+                }
+                // ArrayReturnValueToOutParameter should have eliminated expressions where a
+                // function call is assigned.
+                ASSERT(rightAgg == nullptr);
+
+                const TString &functionName = addArrayAssignmentFunction(node->getType());
+                outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")");
+            }
+            else
+            {
+                outputTriplet(out, visit, "(", " = ", ")");
+            }
+            break;
+        case EOpInitialize:
+            if (visit == PreVisit)
+            {
+                TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
+                ASSERT(symbolNode);
+                TIntermTyped *expression = node->getRight();
+
+                // Global initializers must be constant at this point.
+                ASSERT(symbolNode->getQualifier() != EvqGlobal ||
+                       canWriteAsHLSLLiteral(expression));
+
+                // GLSL allows to write things like "float x = x;" where a new variable x is defined
+                // and the value of an existing variable x is assigned. HLSL uses C semantics (the
+                // new variable is created before the assignment is evaluated), so we need to
+                // convert
+                // this to "float t = x, x = t;".
+                if (writeSameSymbolInitializer(out, symbolNode, expression))
+                {
+                    // Skip initializing the rest of the expression
+                    return false;
+                }
+                else if (writeConstantInitialization(out, symbolNode, expression))
+                {
+                    return false;
+                }
+            }
+            else if (visit == InVisit)
+            {
+                out << " = ";
+            }
+            break;
+        case EOpAddAssign:
+            outputTriplet(out, visit, "(", " += ", ")");
+            break;
+        case EOpSubAssign:
+            outputTriplet(out, visit, "(", " -= ", ")");
+            break;
+        case EOpMulAssign:
+            outputTriplet(out, visit, "(", " *= ", ")");
+            break;
+        case EOpVectorTimesScalarAssign:
+            outputTriplet(out, visit, "(", " *= ", ")");
+            break;
+        case EOpMatrixTimesScalarAssign:
+            outputTriplet(out, visit, "(", " *= ", ")");
+            break;
+        case EOpVectorTimesMatrixAssign:
+            if (visit == PreVisit)
+            {
+                out << "(";
+            }
+            else if (visit == InVisit)
+            {
+                out << " = mul(";
+                node->getLeft()->traverse(this);
+                out << ", transpose(";
+            }
+            else
+            {
+                out << ")))";
+            }
+            break;
+        case EOpMatrixTimesMatrixAssign:
+            if (visit == PreVisit)
+            {
+                out << "(";
+            }
+            else if (visit == InVisit)
+            {
+                out << " = transpose(mul(transpose(";
+                node->getLeft()->traverse(this);
+                out << "), transpose(";
+            }
+            else
+            {
+                out << "))))";
+            }
+            break;
+        case EOpDivAssign:
+            outputTriplet(out, visit, "(", " /= ", ")");
+            break;
+        case EOpIModAssign:
+            outputTriplet(out, visit, "(", " %= ", ")");
+            break;
+        case EOpBitShiftLeftAssign:
+            outputTriplet(out, visit, "(", " <<= ", ")");
+            break;
+        case EOpBitShiftRightAssign:
+            outputTriplet(out, visit, "(", " >>= ", ")");
+            break;
+        case EOpBitwiseAndAssign:
+            outputTriplet(out, visit, "(", " &= ", ")");
+            break;
+        case EOpBitwiseXorAssign:
+            outputTriplet(out, visit, "(", " ^= ", ")");
+            break;
+        case EOpBitwiseOrAssign:
+            outputTriplet(out, visit, "(", " |= ", ")");
+            break;
+        case EOpIndexDirect:
+        {
+            const TType &leftType = node->getLeft()->getType();
+            if (leftType.isInterfaceBlock())
+            {
+                if (visit == PreVisit)
+                {
+                    TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock();
+                    const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
+                    mReferencedInterfaceBlocks[interfaceBlock->instanceName()] =
+                        node->getLeft()->getAsSymbolNode();
+                    out << mUniformHLSL->interfaceBlockInstanceString(*interfaceBlock, arrayIndex);
+                    return false;
+                }
+            }
+            else if (ancestorEvaluatesToSamplerInStruct())
+            {
+                // All parts of an expression that access a sampler in a struct need to use _ as
+                // separator to access the sampler variable that has been moved out of the struct.
+                outputTriplet(out, visit, "", "_", "");
+            }
+            else
+            {
+                outputTriplet(out, visit, "", "[", "]");
+            }
+        }
+        break;
+        case EOpIndexIndirect:
+            // We do not currently support indirect references to interface blocks
+            ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock);
+            outputTriplet(out, visit, "", "[", "]");
+            break;
+        case EOpIndexDirectStruct:
+        {
+            const TStructure *structure       = node->getLeft()->getType().getStruct();
+            const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
+            const TField *field               = structure->fields()[index->getIConst(0)];
+
+            // In cases where indexing returns a sampler, we need to access the sampler variable
+            // that has been moved out of the struct.
+            bool indexingReturnsSampler = IsSampler(field->type()->getBasicType());
+            if (visit == PreVisit && indexingReturnsSampler)
+            {
+                // Samplers extracted from structs have "angle" prefix to avoid name conflicts.
+                // This prefix is only output at the beginning of the indexing expression, which
+                // may have multiple parts.
+                out << "angle";
+            }
+            if (!indexingReturnsSampler)
+            {
+                // All parts of an expression that access a sampler in a struct need to use _ as
+                // separator to access the sampler variable that has been moved out of the struct.
+                indexingReturnsSampler = ancestorEvaluatesToSamplerInStruct();
+            }
+            if (visit == InVisit)
+            {
+                if (indexingReturnsSampler)
+                {
+                    out << "_" + field->name();
+                }
+                else
+                {
+                    out << "." + DecorateField(field->name(), *structure);
+                }
+
+                return false;
+            }
+        }
+        break;
+        case EOpIndexDirectInterfaceBlock:
+            if (visit == InVisit)
+            {
+                const TInterfaceBlock *interfaceBlock =
+                    node->getLeft()->getType().getInterfaceBlock();
+                const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
+                const TField *field               = interfaceBlock->fields()[index->getIConst(0)];
+                out << "." + Decorate(field->name());
+
+                return false;
+            }
+            break;
+        case EOpAdd:
+            outputTriplet(out, visit, "(", " + ", ")");
+            break;
+        case EOpSub:
+            outputTriplet(out, visit, "(", " - ", ")");
+            break;
+        case EOpMul:
+            outputTriplet(out, visit, "(", " * ", ")");
+            break;
+        case EOpDiv:
+            outputTriplet(out, visit, "(", " / ", ")");
+            break;
+        case EOpIMod:
+            outputTriplet(out, visit, "(", " % ", ")");
+            break;
+        case EOpBitShiftLeft:
+            outputTriplet(out, visit, "(", " << ", ")");
+            break;
+        case EOpBitShiftRight:
+            outputTriplet(out, visit, "(", " >> ", ")");
+            break;
+        case EOpBitwiseAnd:
+            outputTriplet(out, visit, "(", " & ", ")");
+            break;
+        case EOpBitwiseXor:
+            outputTriplet(out, visit, "(", " ^ ", ")");
+            break;
+        case EOpBitwiseOr:
+            outputTriplet(out, visit, "(", " | ", ")");
+            break;
+        case EOpEqual:
+        case EOpNotEqual:
+            outputEqual(visit, node->getLeft()->getType(), node->getOp(), out);
+            break;
+        case EOpLessThan:
+            outputTriplet(out, visit, "(", " < ", ")");
+            break;
+        case EOpGreaterThan:
+            outputTriplet(out, visit, "(", " > ", ")");
+            break;
+        case EOpLessThanEqual:
+            outputTriplet(out, visit, "(", " <= ", ")");
+            break;
+        case EOpGreaterThanEqual:
+            outputTriplet(out, visit, "(", " >= ", ")");
+            break;
+        case EOpVectorTimesScalar:
+            outputTriplet(out, visit, "(", " * ", ")");
+            break;
+        case EOpMatrixTimesScalar:
+            outputTriplet(out, visit, "(", " * ", ")");
+            break;
+        case EOpVectorTimesMatrix:
+            outputTriplet(out, visit, "mul(", ", transpose(", "))");
+            break;
+        case EOpMatrixTimesVector:
+            outputTriplet(out, visit, "mul(transpose(", "), ", ")");
+            break;
+        case EOpMatrixTimesMatrix:
+            outputTriplet(out, visit, "transpose(mul(transpose(", "), transpose(", ")))");
+            break;
+        case EOpLogicalOr:
+            // HLSL doesn't short-circuit ||, so we assume that || affected by short-circuiting have
+            // been unfolded.
+            ASSERT(!node->getRight()->hasSideEffects());
+            outputTriplet(out, visit, "(", " || ", ")");
+            return true;
+        case EOpLogicalXor:
+            mUsesXor = true;
+            outputTriplet(out, visit, "xor(", ", ", ")");
+            break;
+        case EOpLogicalAnd:
+            // HLSL doesn't short-circuit &&, so we assume that && affected by short-circuiting have
+            // been unfolded.
+            ASSERT(!node->getRight()->hasSideEffects());
+            outputTriplet(out, visit, "(", " && ", ")");
+            return true;
+        default:
+            UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    switch (node->getOp())
+    {
+        case EOpNegative:
+            outputTriplet(out, visit, "(-", "", ")");
+            break;
+        case EOpPositive:
+            outputTriplet(out, visit, "(+", "", ")");
+            break;
+        case EOpLogicalNot:
+            outputTriplet(out, visit, "(!", "", ")");
+            break;
+        case EOpBitwiseNot:
+            outputTriplet(out, visit, "(~", "", ")");
+            break;
+        case EOpPostIncrement:
+            outputTriplet(out, visit, "(", "", "++)");
+            break;
+        case EOpPostDecrement:
+            outputTriplet(out, visit, "(", "", "--)");
+            break;
+        case EOpPreIncrement:
+            outputTriplet(out, visit, "(++", "", ")");
+            break;
+        case EOpPreDecrement:
+            outputTriplet(out, visit, "(--", "", ")");
+            break;
+        case EOpRadians:
+            outputTriplet(out, visit, "radians(", "", ")");
+            break;
+        case EOpDegrees:
+            outputTriplet(out, visit, "degrees(", "", ")");
+            break;
+        case EOpSin:
+            outputTriplet(out, visit, "sin(", "", ")");
+            break;
+        case EOpCos:
+            outputTriplet(out, visit, "cos(", "", ")");
+            break;
+        case EOpTan:
+            outputTriplet(out, visit, "tan(", "", ")");
+            break;
+        case EOpAsin:
+            outputTriplet(out, visit, "asin(", "", ")");
+            break;
+        case EOpAcos:
+            outputTriplet(out, visit, "acos(", "", ")");
+            break;
+        case EOpAtan:
+            outputTriplet(out, visit, "atan(", "", ")");
+            break;
+        case EOpSinh:
+            outputTriplet(out, visit, "sinh(", "", ")");
+            break;
+        case EOpCosh:
+            outputTriplet(out, visit, "cosh(", "", ")");
+            break;
+        case EOpTanh:
+            outputTriplet(out, visit, "tanh(", "", ")");
+            break;
+        case EOpAsinh:
+        case EOpAcosh:
+        case EOpAtanh:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+        case EOpExp:
+            outputTriplet(out, visit, "exp(", "", ")");
+            break;
+        case EOpLog:
+            outputTriplet(out, visit, "log(", "", ")");
+            break;
+        case EOpExp2:
+            outputTriplet(out, visit, "exp2(", "", ")");
+            break;
+        case EOpLog2:
+            outputTriplet(out, visit, "log2(", "", ")");
+            break;
+        case EOpSqrt:
+            outputTriplet(out, visit, "sqrt(", "", ")");
+            break;
+        case EOpInverseSqrt:
+            outputTriplet(out, visit, "rsqrt(", "", ")");
+            break;
+        case EOpAbs:
+            outputTriplet(out, visit, "abs(", "", ")");
+            break;
+        case EOpSign:
+            outputTriplet(out, visit, "sign(", "", ")");
+            break;
+        case EOpFloor:
+            outputTriplet(out, visit, "floor(", "", ")");
+            break;
+        case EOpTrunc:
+            outputTriplet(out, visit, "trunc(", "", ")");
+            break;
+        case EOpRound:
+            outputTriplet(out, visit, "round(", "", ")");
+            break;
+        case EOpRoundEven:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+        case EOpCeil:
+            outputTriplet(out, visit, "ceil(", "", ")");
+            break;
+        case EOpFract:
+            outputTriplet(out, visit, "frac(", "", ")");
+            break;
+        case EOpIsNan:
+            if (node->getUseEmulatedFunction())
+                writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            else
+                outputTriplet(out, visit, "isnan(", "", ")");
+            mRequiresIEEEStrictCompiling = true;
+            break;
+        case EOpIsInf:
+            outputTriplet(out, visit, "isinf(", "", ")");
+            break;
+        case EOpFloatBitsToInt:
+            outputTriplet(out, visit, "asint(", "", ")");
+            break;
+        case EOpFloatBitsToUint:
+            outputTriplet(out, visit, "asuint(", "", ")");
+            break;
+        case EOpIntBitsToFloat:
+            outputTriplet(out, visit, "asfloat(", "", ")");
+            break;
+        case EOpUintBitsToFloat:
+            outputTriplet(out, visit, "asfloat(", "", ")");
+            break;
+        case EOpPackSnorm2x16:
+        case EOpPackUnorm2x16:
+        case EOpPackHalf2x16:
+        case EOpUnpackSnorm2x16:
+        case EOpUnpackUnorm2x16:
+        case EOpUnpackHalf2x16:
+        case EOpPackUnorm4x8:
+        case EOpPackSnorm4x8:
+        case EOpUnpackUnorm4x8:
+        case EOpUnpackSnorm4x8:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+        case EOpLength:
+            outputTriplet(out, visit, "length(", "", ")");
+            break;
+        case EOpNormalize:
+            outputTriplet(out, visit, "normalize(", "", ")");
+            break;
+        case EOpDFdx:
+            if (mInsideDiscontinuousLoop || mOutputLod0Function)
+            {
+                outputTriplet(out, visit, "(", "", ", 0.0)");
+            }
+            else
+            {
+                outputTriplet(out, visit, "ddx(", "", ")");
+            }
+            break;
+        case EOpDFdy:
+            if (mInsideDiscontinuousLoop || mOutputLod0Function)
+            {
+                outputTriplet(out, visit, "(", "", ", 0.0)");
+            }
+            else
+            {
+                outputTriplet(out, visit, "ddy(", "", ")");
+            }
+            break;
+        case EOpFwidth:
+            if (mInsideDiscontinuousLoop || mOutputLod0Function)
+            {
+                outputTriplet(out, visit, "(", "", ", 0.0)");
+            }
+            else
+            {
+                outputTriplet(out, visit, "fwidth(", "", ")");
+            }
+            break;
+        case EOpTranspose:
+            outputTriplet(out, visit, "transpose(", "", ")");
+            break;
+        case EOpDeterminant:
+            outputTriplet(out, visit, "determinant(transpose(", "", "))");
+            break;
+        case EOpInverse:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+
+        case EOpAny:
+            outputTriplet(out, visit, "any(", "", ")");
+            break;
+        case EOpAll:
+            outputTriplet(out, visit, "all(", "", ")");
+            break;
+        case EOpLogicalNotComponentWise:
+            outputTriplet(out, visit, "(!", "", ")");
+            break;
+        case EOpBitfieldReverse:
+            outputTriplet(out, visit, "reversebits(", "", ")");
+            break;
+        case EOpBitCount:
+            outputTriplet(out, visit, "countbits(", "", ")");
+            break;
+        case EOpFindLSB:
+            // Note that it's unclear from the HLSL docs what this returns for 0, but this is tested
+            // in GLSLTest and results are consistent with GL.
+            outputTriplet(out, visit, "firstbitlow(", "", ")");
+            break;
+        case EOpFindMSB:
+            // Note that it's unclear from the HLSL docs what this returns for 0 or -1, but this is
+            // tested in GLSLTest and results are consistent with GL.
+            outputTriplet(out, visit, "firstbithigh(", "", ")");
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return true;
+}
+
+TString OutputHLSL::samplerNamePrefixFromStruct(TIntermTyped *node)
+{
+    if (node->getAsSymbolNode())
+    {
+        return node->getAsSymbolNode()->getSymbol();
+    }
+    TIntermBinary *nodeBinary = node->getAsBinaryNode();
+    switch (nodeBinary->getOp())
+    {
+        case EOpIndexDirect:
+        {
+            int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0);
+
+            TInfoSinkBase prefixSink;
+            prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_" << index;
+            return TString(prefixSink.c_str());
+        }
+        case EOpIndexDirectStruct:
+        {
+            TStructure *s       = nodeBinary->getLeft()->getAsTyped()->getType().getStruct();
+            int index           = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0);
+            const TField *field = s->fields()[index];
+
+            TInfoSinkBase prefixSink;
+            prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_"
+                       << field->name();
+            return TString(prefixSink.c_str());
+        }
+        default:
+            UNREACHABLE();
+            return TString("");
+    }
+}
+
+bool OutputHLSL::visitBlock(Visit visit, TIntermBlock *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    if (mInsideFunction)
+    {
+        outputLineDirective(out, node->getLine().first_line);
+        out << "{\n";
+    }
+
+    for (TIntermSequence::iterator sit = node->getSequence()->begin();
+         sit != node->getSequence()->end(); sit++)
+    {
+        outputLineDirective(out, (*sit)->getLine().first_line);
+
+        (*sit)->traverse(this);
+
+        // Don't output ; after case labels, they're terminated by :
+        // This is needed especially since outputting a ; after a case statement would turn empty
+        // case statements into non-empty case statements, disallowing fall-through from them.
+        // Also no need to output ; after if statements or sequences. This is done just for
+        // code clarity.
+        if ((*sit)->getAsCaseNode() == nullptr && (*sit)->getAsIfElseNode() == nullptr &&
+            (*sit)->getAsBlock() == nullptr)
+            out << ";\n";
+    }
+
+    if (mInsideFunction)
+    {
+        outputLineDirective(out, node->getLine().last_line);
+        out << "}\n";
+    }
+
+    return false;
+}
+
+bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    ASSERT(mCurrentFunctionMetadata == nullptr);
+
+    size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
+    ASSERT(index != CallDAG::InvalidIndex);
+    mCurrentFunctionMetadata = &mASTMetadataList[index];
+
+    out << TypeString(node->getFunctionPrototype()->getType()) << " ";
+
+    TIntermSequence *parameters = node->getFunctionPrototype()->getSequence();
+
+    if (node->getFunctionSymbolInfo()->isMain())
+    {
+        out << "gl_main(";
+    }
+    else
+    {
+        out << DecorateIfNeeded(node->getFunctionSymbolInfo()->getNameObj())
+            << DisambiguateFunctionName(parameters) << (mOutputLod0Function ? "Lod0(" : "(");
+    }
+
+    for (unsigned int i = 0; i < parameters->size(); i++)
+    {
+        TIntermSymbol *symbol = (*parameters)[i]->getAsSymbolNode();
+
+        if (symbol)
+        {
+            ensureStructDefined(symbol->getType());
+
+            out << argumentString(symbol);
+
+            if (i < parameters->size() - 1)
+            {
+                out << ", ";
+            }
+        }
+        else
+            UNREACHABLE();
+    }
+
+    out << ")\n";
+
+    mInsideFunction = true;
+    // The function body node will output braces.
+    node->getBody()->traverse(this);
+    mInsideFunction = false;
+
+    mCurrentFunctionMetadata = nullptr;
+
+    bool needsLod0 = mASTMetadataList[index].mNeedsLod0;
+    if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER)
+    {
+        ASSERT(!node->getFunctionSymbolInfo()->isMain());
+        mOutputLod0Function = true;
+        node->traverse(this);
+        mOutputLod0Function = false;
+    }
+
+    return false;
+}
+
+bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+    if (visit == PreVisit)
+    {
+        TIntermSequence *sequence = node->getSequence();
+        TIntermTyped *variable    = (*sequence)[0]->getAsTyped();
+        ASSERT(sequence->size() == 1);
+
+        if (variable &&
+            (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal ||
+             variable->getQualifier() == EvqConst))
+        {
+            ensureStructDefined(variable->getType());
+
+            if (!variable->getAsSymbolNode() ||
+                variable->getAsSymbolNode()->getSymbol() != "")  // Variable declaration
+            {
+                if (!mInsideFunction)
+                {
+                    out << "static ";
+                }
+
+                out << TypeString(variable->getType()) + " ";
+
+                TIntermSymbol *symbol = variable->getAsSymbolNode();
+
+                if (symbol)
+                {
+                    symbol->traverse(this);
+                    out << ArrayString(symbol->getType());
+                    out << " = " + initializer(symbol->getType());
+                }
+                else
+                {
+                    variable->traverse(this);
+                }
+            }
+            else if (variable->getAsSymbolNode() &&
+                     variable->getAsSymbolNode()->getSymbol() == "")  // Type (struct) declaration
+            {
+                // Already added to constructor map
+            }
+            else
+                UNREACHABLE();
+        }
+        else if (variable && IsVaryingOut(variable->getQualifier()))
+        {
+            for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
+            {
+                TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
+
+                if (symbol)
+                {
+                    // Vertex (output) varyings which are declared but not written to should
+                    // still be declared to allow successful linking
+                    mReferencedVaryings[symbol->getSymbol()] = symbol;
+                }
+                else
+                {
+                    (*sit)->traverse(this);
+                }
+            }
+        }
+    }
+    return false;
+}
+
+bool OutputHLSL::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+{
+    // Do not do any translation
+    return false;
+}
+
+bool OutputHLSL::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    ASSERT(visit == PreVisit);
+    size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
+    // Skip the prototype if it is not implemented (and thus not used)
+    if (index == CallDAG::InvalidIndex)
+    {
+        return false;
+    }
+
+    TIntermSequence *arguments = node->getSequence();
+
+    TString name = DecorateIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
+    out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments)
+        << (mOutputLod0Function ? "Lod0(" : "(");
+
+    for (unsigned int i = 0; i < arguments->size(); i++)
+    {
+        TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode();
+        ASSERT(symbol != nullptr);
+
+        out << argumentString(symbol);
+
+        if (i < arguments->size() - 1)
+        {
+            out << ", ";
+        }
+    }
+
+    out << ");\n";
+
+    // Also prototype the Lod0 variant if needed
+    bool needsLod0 = mASTMetadataList[index].mNeedsLod0;
+    if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER)
+    {
+        mOutputLod0Function = true;
+        node->traverse(this);
+        mOutputLod0Function = false;
+    }
+
+    return false;
+}
+
+bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    switch (node->getOp())
+    {
+        case EOpCallBuiltInFunction:
+        case EOpCallFunctionInAST:
+        case EOpCallInternalRawFunction:
+        {
+            TIntermSequence *arguments = node->getSequence();
+
+            bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
+            if (node->getOp() == EOpCallFunctionInAST)
+            {
+                if (node->isArray())
+                {
+                    UNIMPLEMENTED();
+                }
+                size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
+                ASSERT(index != CallDAG::InvalidIndex);
+                lod0 &= mASTMetadataList[index].mNeedsLod0;
+
+                out << DecorateIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
+                out << DisambiguateFunctionName(node->getSequence());
+                out << (lod0 ? "Lod0(" : "(");
+            }
+            else if (node->getOp() == EOpCallInternalRawFunction)
+            {
+                // This path is used for internal functions that don't have their definitions in the
+                // AST, such as precision emulation functions.
+                out << DecorateIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "(";
+            }
+            else
+            {
+                const TString &name    = node->getFunctionSymbolInfo()->getName();
+                TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType();
+                int coords = 0;  // textureSize(gsampler2DMS) doesn't have a second argument.
+                if (arguments->size() > 1)
+                {
+                    coords = (*arguments)[1]->getAsTyped()->getNominalSize();
+                }
+                TString textureFunctionName = mTextureFunctionHLSL->useTextureFunction(
+                    name, samplerType, coords, arguments->size(), lod0, mShaderType);
+                out << textureFunctionName << "(";
+            }
+
+            for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++)
+            {
+                TIntermTyped *typedArg = (*arg)->getAsTyped();
+                if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(typedArg->getBasicType()))
+                {
+                    out << "texture_";
+                    (*arg)->traverse(this);
+                    out << ", sampler_";
+                }
+
+                (*arg)->traverse(this);
+
+                if (typedArg->getType().isStructureContainingSamplers())
+                {
+                    const TType &argType = typedArg->getType();
+                    TVector<TIntermSymbol *> samplerSymbols;
+                    TString structName = samplerNamePrefixFromStruct(typedArg);
+                    argType.createSamplerSymbols("angle_" + structName, "",
+                                                 argType.isArray() ? argType.getArraySize() : 0u,
+                                                 &samplerSymbols, nullptr);
+                    for (const TIntermSymbol *sampler : samplerSymbols)
+                    {
+                        if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+                        {
+                            out << ", texture_" << sampler->getSymbol();
+                            out << ", sampler_" << sampler->getSymbol();
+                        }
+                        else
+                        {
+                            // In case of HLSL 4.1+, this symbol is the sampler index, and in case
+                            // of D3D9, it's the sampler variable.
+                            out << ", " + sampler->getSymbol();
+                        }
+                    }
+                }
+
+                if (arg < arguments->end() - 1)
+                {
+                    out << ", ";
+                }
+            }
+
+            out << ")";
+
+            return false;
+        }
+        case EOpConstruct:
+            if (node->getBasicType() == EbtStruct)
+            {
+                if (node->getType().isArray())
+                {
+                    UNIMPLEMENTED();
+                }
+                const TString &structName = StructNameString(*node->getType().getStruct());
+                mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence());
+                outputTriplet(out, visit, (structName + "_ctor(").c_str(), ", ", ")");
+            }
+            else
+            {
+                const char *name = "";
+                if (node->getType().getNominalSize() == 1)
+                {
+                    switch (node->getBasicType())
+                    {
+                        case EbtFloat:
+                            name = "vec1";
+                            break;
+                        case EbtInt:
+                            name = "ivec1";
+                            break;
+                        case EbtUInt:
+                            name = "uvec1";
+                            break;
+                        case EbtBool:
+                            name = "bvec1";
+                            break;
+                        default:
+                            UNREACHABLE();
+                    }
+                }
+                else
+                {
+                    name = node->getType().getBuiltInTypeNameString();
+                }
+                outputConstructor(out, visit, node->getType(), name, node->getSequence());
+            }
+            break;
+        case EOpEqualComponentWise:
+            outputTriplet(out, visit, "(", " == ", ")");
+            break;
+        case EOpNotEqualComponentWise:
+            outputTriplet(out, visit, "(", " != ", ")");
+            break;
+        case EOpLessThanComponentWise:
+            outputTriplet(out, visit, "(", " < ", ")");
+            break;
+        case EOpGreaterThanComponentWise:
+            outputTriplet(out, visit, "(", " > ", ")");
+            break;
+        case EOpLessThanEqualComponentWise:
+            outputTriplet(out, visit, "(", " <= ", ")");
+            break;
+        case EOpGreaterThanEqualComponentWise:
+            outputTriplet(out, visit, "(", " >= ", ")");
+            break;
+        case EOpMod:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+        case EOpModf:
+            outputTriplet(out, visit, "modf(", ", ", ")");
+            break;
+        case EOpPow:
+            outputTriplet(out, visit, "pow(", ", ", ")");
+            break;
+        case EOpAtan:
+            ASSERT(node->getSequence()->size() == 2);  // atan(x) is a unary operator
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+        case EOpMin:
+            outputTriplet(out, visit, "min(", ", ", ")");
+            break;
+        case EOpMax:
+            outputTriplet(out, visit, "max(", ", ", ")");
+            break;
+        case EOpClamp:
+            outputTriplet(out, visit, "clamp(", ", ", ")");
+            break;
+        case EOpMix:
+        {
+            TIntermTyped *lastParamNode = (*(node->getSequence()))[2]->getAsTyped();
+            if (lastParamNode->getType().getBasicType() == EbtBool)
+            {
+                // There is no HLSL equivalent for ESSL3 built-in "genType mix (genType x, genType
+                // y, genBType a)",
+                // so use emulated version.
+                ASSERT(node->getUseEmulatedFunction());
+                writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            }
+            else
+            {
+                outputTriplet(out, visit, "lerp(", ", ", ")");
+            }
+            break;
+        }
+        case EOpStep:
+            outputTriplet(out, visit, "step(", ", ", ")");
+            break;
+        case EOpSmoothStep:
+            outputTriplet(out, visit, "smoothstep(", ", ", ")");
+            break;
+        case EOpFrexp:
+        case EOpLdexp:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+        case EOpDistance:
+            outputTriplet(out, visit, "distance(", ", ", ")");
+            break;
+        case EOpDot:
+            outputTriplet(out, visit, "dot(", ", ", ")");
+            break;
+        case EOpCross:
+            outputTriplet(out, visit, "cross(", ", ", ")");
+            break;
+        case EOpFaceForward:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+        case EOpReflect:
+            outputTriplet(out, visit, "reflect(", ", ", ")");
+            break;
+        case EOpRefract:
+            outputTriplet(out, visit, "refract(", ", ", ")");
+            break;
+        case EOpOuterProduct:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+        case EOpMulMatrixComponentWise:
+            outputTriplet(out, visit, "(", " * ", ")");
+            break;
+        case EOpBitfieldExtract:
+        case EOpBitfieldInsert:
+        case EOpUaddCarry:
+        case EOpUsubBorrow:
+        case EOpUmulExtended:
+        case EOpImulExtended:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return true;
+}
+
+void OutputHLSL::writeIfElse(TInfoSinkBase &out, TIntermIfElse *node)
+{
+    out << "if (";
+
+    node->getCondition()->traverse(this);
+
+    out << ")\n";
+
+    outputLineDirective(out, node->getLine().first_line);
+
+    bool discard = false;
+
+    if (node->getTrueBlock())
+    {
+        // The trueBlock child node will output braces.
+        node->getTrueBlock()->traverse(this);
+
+        // Detect true discard
+        discard = (discard || FindDiscard::search(node->getTrueBlock()));
+    }
+    else
+    {
+        // TODO(oetuaho): Check if the semicolon inside is necessary.
+        // It's there as a result of conservative refactoring of the output.
+        out << "{;}\n";
+    }
+
+    outputLineDirective(out, node->getLine().first_line);
+
+    if (node->getFalseBlock())
+    {
+        out << "else\n";
+
+        outputLineDirective(out, node->getFalseBlock()->getLine().first_line);
+
+        // The falseBlock child node will output braces.
+        node->getFalseBlock()->traverse(this);
+
+        outputLineDirective(out, node->getFalseBlock()->getLine().first_line);
+
+        // Detect false discard
+        discard = (discard || FindDiscard::search(node->getFalseBlock()));
+    }
+
+    // ANGLE issue 486: Detect problematic conditional discard
+    if (discard)
+    {
+        mUsesDiscardRewriting = true;
+    }
+}
+
+bool OutputHLSL::visitTernary(Visit, TIntermTernary *)
+{
+    // Ternary ops should have been already converted to something else in the AST. HLSL ternary
+    // operator doesn't short-circuit, so it's not the same as the GLSL ternary operator.
+    UNREACHABLE();
+    return false;
+}
+
+bool OutputHLSL::visitIfElse(Visit visit, TIntermIfElse *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    ASSERT(mInsideFunction);
+
+    // D3D errors when there is a gradient operation in a loop in an unflattened if.
+    if (mShaderType == GL_FRAGMENT_SHADER && mCurrentFunctionMetadata->hasGradientLoop(node))
+    {
+        out << "FLATTEN ";
+    }
+
+    writeIfElse(out, node);
+
+    return false;
+}
+
+bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    if (node->getStatementList())
+    {
+        node->setStatementList(
+            RemoveSwitchFallThrough::removeFallThrough(node->getStatementList()));
+        outputTriplet(out, visit, "switch (", ") ", "");
+        // The curly braces get written when visiting the statementList aggregate
+    }
+    else
+    {
+        // No statementList, so it won't output curly braces
+        outputTriplet(out, visit, "switch (", ") {", "}\n");
+    }
+    return true;
+}
+
+bool OutputHLSL::visitCase(Visit visit, TIntermCase *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    if (node->hasCondition())
+    {
+        outputTriplet(out, visit, "case (", "", "):\n");
+        return true;
+    }
+    else
+    {
+        out << "default:\n";
+        return false;
+    }
+}
+
+void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+    writeConstantUnion(out, node->getType(), node->getUnionArrayPointer());
+}
+
+bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
+{
+    mNestedLoopDepth++;
+
+    bool wasDiscontinuous = mInsideDiscontinuousLoop;
+    mInsideDiscontinuousLoop =
+        mInsideDiscontinuousLoop || mCurrentFunctionMetadata->mDiscontinuousLoops.count(node) > 0;
+
+    TInfoSinkBase &out = getInfoSink();
+
+    if (mOutputType == SH_HLSL_3_0_OUTPUT)
+    {
+        if (handleExcessiveLoop(out, node))
+        {
+            mInsideDiscontinuousLoop = wasDiscontinuous;
+            mNestedLoopDepth--;
+
+            return false;
+        }
+    }
+
+    const char *unroll = mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : "";
+    if (node->getType() == ELoopDoWhile)
+    {
+        out << "{" << unroll << " do\n";
+
+        outputLineDirective(out, node->getLine().first_line);
+    }
+    else
+    {
+        out << "{" << unroll << " for(";
+
+        if (node->getInit())
+        {
+            node->getInit()->traverse(this);
+        }
+
+        out << "; ";
+
+        if (node->getCondition())
+        {
+            node->getCondition()->traverse(this);
+        }
+
+        out << "; ";
+
+        if (node->getExpression())
+        {
+            node->getExpression()->traverse(this);
+        }
+
+        out << ")\n";
+
+        outputLineDirective(out, node->getLine().first_line);
+    }
+
+    if (node->getBody())
+    {
+        // The loop body node will output braces.
+        node->getBody()->traverse(this);
+    }
+    else
+    {
+        // TODO(oetuaho): Check if the semicolon inside is necessary.
+        // It's there as a result of conservative refactoring of the output.
+        out << "{;}\n";
+    }
+
+    outputLineDirective(out, node->getLine().first_line);
+
+    if (node->getType() == ELoopDoWhile)
+    {
+        outputLineDirective(out, node->getCondition()->getLine().first_line);
+        out << "while(\n";
+
+        node->getCondition()->traverse(this);
+
+        out << ");";
+    }
+
+    out << "}\n";
+
+    mInsideDiscontinuousLoop = wasDiscontinuous;
+    mNestedLoopDepth--;
+
+    return false;
+}
+
+bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
+{
+    TInfoSinkBase &out = getInfoSink();
+
+    switch (node->getFlowOp())
+    {
+        case EOpKill:
+            outputTriplet(out, visit, "discard;\n", "", "");
+            break;
+        case EOpBreak:
+            if (visit == PreVisit)
+            {
+                if (mNestedLoopDepth > 1)
+                {
+                    mUsesNestedBreak = true;
+                }
+
+                if (mExcessiveLoopIndex)
+                {
+                    out << "{Break";
+                    mExcessiveLoopIndex->traverse(this);
+                    out << " = true; break;}\n";
+                }
+                else
+                {
+                    out << "break;\n";
+                }
+            }
+            break;
+        case EOpContinue:
+            outputTriplet(out, visit, "continue;\n", "", "");
+            break;
+        case EOpReturn:
+            if (visit == PreVisit)
+            {
+                if (node->getExpression())
+                {
+                    out << "return ";
+                }
+                else
+                {
+                    out << "return;\n";
+                }
+            }
+            else if (visit == PostVisit)
+            {
+                if (node->getExpression())
+                {
+                    out << ";\n";
+                }
+            }
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return true;
+}
+
+// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
+// (The D3D documentation says 255 iterations, but the compiler complains at anything more than
+// 254).
+bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
+{
+    const int MAX_LOOP_ITERATIONS = 254;
+
+    // Parse loops of the form:
+    // for(int index = initial; index [comparator] limit; index += increment)
+    TIntermSymbol *index = nullptr;
+    TOperator comparator = EOpNull;
+    int initial          = 0;
+    int limit            = 0;
+    int increment        = 0;
+
+    // Parse index name and intial value
+    if (node->getInit())
+    {
+        TIntermDeclaration *init = node->getInit()->getAsDeclarationNode();
+
+        if (init)
+        {
+            TIntermSequence *sequence = init->getSequence();
+            TIntermTyped *variable    = (*sequence)[0]->getAsTyped();
+
+            if (variable && variable->getQualifier() == EvqTemporary)
+            {
+                TIntermBinary *assign = variable->getAsBinaryNode();
+
+                if (assign->getOp() == EOpInitialize)
+                {
+                    TIntermSymbol *symbol          = assign->getLeft()->getAsSymbolNode();
+                    TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
+
+                    if (symbol && constant)
+                    {
+                        if (constant->getBasicType() == EbtInt && constant->isScalar())
+                        {
+                            index   = symbol;
+                            initial = constant->getIConst(0);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Parse comparator and limit value
+    if (index != nullptr && node->getCondition())
+    {
+        TIntermBinary *test = node->getCondition()->getAsBinaryNode();
+
+        if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
+        {
+            TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
+
+            if (constant)
+            {
+                if (constant->getBasicType() == EbtInt && constant->isScalar())
+                {
+                    comparator = test->getOp();
+                    limit      = constant->getIConst(0);
+                }
+            }
+        }
+    }
+
+    // Parse increment
+    if (index != nullptr && comparator != EOpNull && node->getExpression())
+    {
+        TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
+        TIntermUnary *unaryTerminal   = node->getExpression()->getAsUnaryNode();
+
+        if (binaryTerminal)
+        {
+            TOperator op                   = binaryTerminal->getOp();
+            TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
+
+            if (constant)
+            {
+                if (constant->getBasicType() == EbtInt && constant->isScalar())
+                {
+                    int value = constant->getIConst(0);
+
+                    switch (op)
+                    {
+                        case EOpAddAssign:
+                            increment = value;
+                            break;
+                        case EOpSubAssign:
+                            increment = -value;
+                            break;
+                        default:
+                            UNIMPLEMENTED();
+                    }
+                }
+            }
+        }
+        else if (unaryTerminal)
+        {
+            TOperator op = unaryTerminal->getOp();
+
+            switch (op)
+            {
+                case EOpPostIncrement:
+                    increment = 1;
+                    break;
+                case EOpPostDecrement:
+                    increment = -1;
+                    break;
+                case EOpPreIncrement:
+                    increment = 1;
+                    break;
+                case EOpPreDecrement:
+                    increment = -1;
+                    break;
+                default:
+                    UNIMPLEMENTED();
+            }
+        }
+    }
+
+    if (index != nullptr && comparator != EOpNull && increment != 0)
+    {
+        if (comparator == EOpLessThanEqual)
+        {
+            comparator = EOpLessThan;
+            limit += 1;
+        }
+
+        if (comparator == EOpLessThan)
+        {
+            int iterations = (limit - initial) / increment;
+
+            if (iterations <= MAX_LOOP_ITERATIONS)
+            {
+                return false;  // Not an excessive loop
+            }
+
+            TIntermSymbol *restoreIndex = mExcessiveLoopIndex;
+            mExcessiveLoopIndex         = index;
+
+            out << "{int ";
+            index->traverse(this);
+            out << ";\n"
+                   "bool Break";
+            index->traverse(this);
+            out << " = false;\n";
+
+            bool firstLoopFragment = true;
+
+            while (iterations > 0)
+            {
+                int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations);
+
+                if (!firstLoopFragment)
+                {
+                    out << "if (!Break";
+                    index->traverse(this);
+                    out << ") {\n";
+                }
+
+                if (iterations <= MAX_LOOP_ITERATIONS)  // Last loop fragment
+                {
+                    mExcessiveLoopIndex = nullptr;  // Stops setting the Break flag
+                }
+
+                // for(int index = initial; index < clampedLimit; index += increment)
+                const char *unroll =
+                    mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : "";
+
+                out << unroll << " for(";
+                index->traverse(this);
+                out << " = ";
+                out << initial;
+
+                out << "; ";
+                index->traverse(this);
+                out << " < ";
+                out << clampedLimit;
+
+                out << "; ";
+                index->traverse(this);
+                out << " += ";
+                out << increment;
+                out << ")\n";
+
+                outputLineDirective(out, node->getLine().first_line);
+                out << "{\n";
+
+                if (node->getBody())
+                {
+                    node->getBody()->traverse(this);
+                }
+
+                outputLineDirective(out, node->getLine().first_line);
+                out << ";}\n";
+
+                if (!firstLoopFragment)
+                {
+                    out << "}\n";
+                }
+
+                firstLoopFragment = false;
+
+                initial += MAX_LOOP_ITERATIONS * increment;
+                iterations -= MAX_LOOP_ITERATIONS;
+            }
+
+            out << "}";
+
+            mExcessiveLoopIndex = restoreIndex;
+
+            return true;
+        }
+        else
+            UNIMPLEMENTED();
+    }
+
+    return false;  // Not handled as an excessive loop
+}
+
+void OutputHLSL::outputTriplet(TInfoSinkBase &out,
+                               Visit visit,
+                               const char *preString,
+                               const char *inString,
+                               const char *postString)
+{
+    if (visit == PreVisit)
+    {
+        out << preString;
+    }
+    else if (visit == InVisit)
+    {
+        out << inString;
+    }
+    else if (visit == PostVisit)
+    {
+        out << postString;
+    }
+}
+
+void OutputHLSL::outputLineDirective(TInfoSinkBase &out, int line)
+{
+    if ((mCompileOptions & SH_LINE_DIRECTIVES) && (line > 0))
+    {
+        out << "\n";
+        out << "#line " << line;
+
+        if (mSourcePath)
+        {
+            out << " \"" << mSourcePath << "\"";
+        }
+
+        out << "\n";
+    }
+}
+
+TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
+{
+    TQualifier qualifier = symbol->getQualifier();
+    const TType &type    = symbol->getType();
+    const TName &name    = symbol->getName();
+    TString nameStr;
+
+    if (name.getString().empty())  // HLSL demands named arguments, also for prototypes
+    {
+        nameStr = "x" + str(mUniqueIndex++);
+    }
+    else
+    {
+        nameStr = DecorateIfNeeded(name);
+    }
+
+    if (IsSampler(type.getBasicType()))
+    {
+        if (mOutputType == SH_HLSL_4_1_OUTPUT)
+        {
+            // Samplers are passed as indices to the sampler array.
+            ASSERT(qualifier != EvqOut && qualifier != EvqInOut);
+            return "const uint " + nameStr + ArrayString(type);
+        }
+        if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+        {
+            return QualifierString(qualifier) + " " + TextureString(type.getBasicType()) +
+                   " texture_" + nameStr + ArrayString(type) + ", " + QualifierString(qualifier) +
+                   " " + SamplerString(type.getBasicType()) + " sampler_" + nameStr +
+                   ArrayString(type);
+        }
+    }
+
+    TStringStream argString;
+    argString << QualifierString(qualifier) << " " << TypeString(type) << " " << nameStr
+              << ArrayString(type);
+
+    // If the structure parameter contains samplers, they need to be passed into the function as
+    // separate parameters. HLSL doesn't natively support samplers in structs.
+    if (type.isStructureContainingSamplers())
+    {
+        ASSERT(qualifier != EvqOut && qualifier != EvqInOut);
+        TVector<TIntermSymbol *> samplerSymbols;
+        type.createSamplerSymbols("angle" + nameStr, "", 0u, &samplerSymbols, nullptr);
+        for (const TIntermSymbol *sampler : samplerSymbols)
+        {
+            if (mOutputType == SH_HLSL_4_1_OUTPUT)
+            {
+                argString << ", const uint " << sampler->getSymbol() << ArrayString(type);
+            }
+            else if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+            {
+                const TType &samplerType = sampler->getType();
+                ASSERT((!type.isArray() && !samplerType.isArray()) ||
+                       type.getArraySize() == samplerType.getArraySize());
+                ASSERT(IsSampler(samplerType.getBasicType()));
+                argString << ", " << QualifierString(qualifier) << " "
+                          << TextureString(samplerType.getBasicType()) << " texture_"
+                          << sampler->getSymbol() << ArrayString(type) << ", "
+                          << QualifierString(qualifier) << " "
+                          << SamplerString(samplerType.getBasicType()) << " sampler_"
+                          << sampler->getSymbol() << ArrayString(type);
+            }
+            else
+            {
+                const TType &samplerType = sampler->getType();
+                ASSERT((!type.isArray() && !samplerType.isArray()) ||
+                       type.getArraySize() == samplerType.getArraySize());
+                ASSERT(IsSampler(samplerType.getBasicType()));
+                argString << ", " << QualifierString(qualifier) << " " << TypeString(samplerType)
+                          << " " << sampler->getSymbol() << ArrayString(type);
+            }
+        }
+    }
+
+    return argString.str();
+}
+
+TString OutputHLSL::initializer(const TType &type)
+{
+    TString string;
+
+    size_t size = type.getObjectSize();
+    for (size_t component = 0; component < size; component++)
+    {
+        string += "0";
+
+        if (component + 1 < size)
+        {
+            string += ", ";
+        }
+    }
+
+    return "{" + string + "}";
+}
+
+void OutputHLSL::outputConstructor(TInfoSinkBase &out,
+                                   Visit visit,
+                                   const TType &type,
+                                   const char *name,
+                                   const TIntermSequence *parameters)
+{
+    if (type.isArray())
+    {
+        UNIMPLEMENTED();
+    }
+
+    if (visit == PreVisit)
+    {
+        TString constructorName = mStructureHLSL->addConstructor(type, name, parameters);
+
+        out << constructorName << "(";
+    }
+    else if (visit == InVisit)
+    {
+        out << ", ";
+    }
+    else if (visit == PostVisit)
+    {
+        out << ")";
+    }
+}
+
+const TConstantUnion *OutputHLSL::writeConstantUnion(TInfoSinkBase &out,
+                                                     const TType &type,
+                                                     const TConstantUnion *const constUnion)
+{
+    const TConstantUnion *constUnionIterated = constUnion;
+
+    const TStructure *structure = type.getStruct();
+    if (structure)
+    {
+        out << StructNameString(*structure) + "_ctor(";
+
+        const TFieldList &fields = structure->fields();
+
+        for (size_t i = 0; i < fields.size(); i++)
+        {
+            const TType *fieldType = fields[i]->type();
+            constUnionIterated     = writeConstantUnion(out, *fieldType, constUnionIterated);
+
+            if (i != fields.size() - 1)
+            {
+                out << ", ";
+            }
+        }
+
+        out << ")";
+    }
+    else
+    {
+        size_t size    = type.getObjectSize();
+        bool writeType = size > 1;
+
+        if (writeType)
+        {
+            out << TypeString(type) << "(";
+        }
+        constUnionIterated = writeConstantUnionArray(out, constUnionIterated, size);
+        if (writeType)
+        {
+            out << ")";
+        }
+    }
+
+    return constUnionIterated;
+}
+
+void OutputHLSL::writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op)
+{
+    if (visit == PreVisit)
+    {
+        const char *opStr = GetOperatorString(op);
+        BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr);
+        out << "(";
+    }
+    else
+    {
+        outputTriplet(out, visit, nullptr, ", ", ")");
+    }
+}
+
+bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out,
+                                            TIntermSymbol *symbolNode,
+                                            TIntermTyped *expression)
+{
+    sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
+    expression->traverse(&searchSymbol);
+
+    if (searchSymbol.foundMatch())
+    {
+        // Type already printed
+        out << "t" + str(mUniqueIndex) + " = ";
+        expression->traverse(this);
+        out << ", ";
+        symbolNode->traverse(this);
+        out << " = t" + str(mUniqueIndex);
+
+        mUniqueIndex++;
+        return true;
+    }
+
+    return false;
+}
+
+bool OutputHLSL::canWriteAsHLSLLiteral(TIntermTyped *expression)
+{
+    // We support writing constant unions and constructors that only take constant unions as
+    // parameters as HLSL literals.
+    return expression->getAsConstantUnion() ||
+           expression->isConstructorWithOnlyConstantUnionParameters();
+}
+
+bool OutputHLSL::writeConstantInitialization(TInfoSinkBase &out,
+                                             TIntermSymbol *symbolNode,
+                                             TIntermTyped *expression)
+{
+    if (canWriteAsHLSLLiteral(expression))
+    {
+        symbolNode->traverse(this);
+        if (expression->getType().isArray())
+        {
+            out << "[" << expression->getType().getArraySize() << "]";
+        }
+        out << " = {";
+        if (expression->getAsConstantUnion())
+        {
+            TIntermConstantUnion *nodeConst  = expression->getAsConstantUnion();
+            const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer();
+            writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize());
+        }
+        else
+        {
+            TIntermAggregate *constructor = expression->getAsAggregate();
+            ASSERT(constructor != nullptr);
+            for (TIntermNode *&node : *constructor->getSequence())
+            {
+                TIntermConstantUnion *nodeConst = node->getAsConstantUnion();
+                ASSERT(nodeConst);
+                const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer();
+                writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize());
+                if (node != constructor->getSequence()->back())
+                {
+                    out << ", ";
+                }
+            }
+        }
+        out << "}";
+        return true;
+    }
+    return false;
+}
+
+TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
+{
+    const TFieldList &fields = structure.fields();
+
+    for (const auto &eqFunction : mStructEqualityFunctions)
+    {
+        if (eqFunction->structure == &structure)
+        {
+            return eqFunction->functionName;
+        }
+    }
+
+    const TString &structNameString = StructNameString(structure);
+
+    StructEqualityFunction *function = new StructEqualityFunction();
+    function->structure              = &structure;
+    function->functionName           = "angle_eq_" + structNameString;
+
+    TInfoSinkBase fnOut;
+
+    fnOut << "bool " << function->functionName << "(" << structNameString << " a, "
+          << structNameString + " b)\n"
+          << "{\n"
+             "    return ";
+
+    for (size_t i = 0; i < fields.size(); i++)
+    {
+        const TField *field    = fields[i];
+        const TType *fieldType = field->type();
+
+        const TString &fieldNameA = "a." + Decorate(field->name());
+        const TString &fieldNameB = "b." + Decorate(field->name());
+
+        if (i > 0)
+        {
+            fnOut << " && ";
+        }
+
+        fnOut << "(";
+        outputEqual(PreVisit, *fieldType, EOpEqual, fnOut);
+        fnOut << fieldNameA;
+        outputEqual(InVisit, *fieldType, EOpEqual, fnOut);
+        fnOut << fieldNameB;
+        outputEqual(PostVisit, *fieldType, EOpEqual, fnOut);
+        fnOut << ")";
+    }
+
+    fnOut << ";\n"
+          << "}\n";
+
+    function->functionDefinition = fnOut.c_str();
+
+    mStructEqualityFunctions.push_back(function);
+    mEqualityFunctions.push_back(function);
+
+    return function->functionName;
+}
+
+TString OutputHLSL::addArrayEqualityFunction(const TType &type)
+{
+    for (const auto &eqFunction : mArrayEqualityFunctions)
+    {
+        if (eqFunction->type == type)
+        {
+            return eqFunction->functionName;
+        }
+    }
+
+    const TString &typeName = TypeString(type);
+
+    ArrayHelperFunction *function = new ArrayHelperFunction();
+    function->type                = type;
+
+    TInfoSinkBase fnNameOut;
+    fnNameOut << "angle_eq_" << type.getArraySize() << "_" << typeName;
+    function->functionName = fnNameOut.c_str();
+
+    TType nonArrayType = type;
+    nonArrayType.clearArrayness();
+
+    TInfoSinkBase fnOut;
+
+    fnOut << "bool " << function->functionName << "(" << typeName << " a[" << type.getArraySize()
+          << "], " << typeName << " b[" << type.getArraySize() << "])\n"
+          << "{\n"
+             "    for (int i = 0; i < "
+          << type.getArraySize() << "; ++i)\n"
+                                    "    {\n"
+                                    "        if (";
+
+    outputEqual(PreVisit, nonArrayType, EOpNotEqual, fnOut);
+    fnOut << "a[i]";
+    outputEqual(InVisit, nonArrayType, EOpNotEqual, fnOut);
+    fnOut << "b[i]";
+    outputEqual(PostVisit, nonArrayType, EOpNotEqual, fnOut);
+
+    fnOut << ") { return false; }\n"
+             "    }\n"
+             "    return true;\n"
+             "}\n";
+
+    function->functionDefinition = fnOut.c_str();
+
+    mArrayEqualityFunctions.push_back(function);
+    mEqualityFunctions.push_back(function);
+
+    return function->functionName;
+}
+
+TString OutputHLSL::addArrayAssignmentFunction(const TType &type)
+{
+    for (const auto &assignFunction : mArrayAssignmentFunctions)
+    {
+        if (assignFunction.type == type)
+        {
+            return assignFunction.functionName;
+        }
+    }
+
+    const TString &typeName = TypeString(type);
+
+    ArrayHelperFunction function;
+    function.type = type;
+
+    TInfoSinkBase fnNameOut;
+    fnNameOut << "angle_assign_" << type.getArraySize() << "_" << typeName;
+    function.functionName = fnNameOut.c_str();
+
+    TInfoSinkBase fnOut;
+
+    fnOut << "void " << function.functionName << "(out " << typeName << " a[" << type.getArraySize()
+          << "], " << typeName << " b[" << type.getArraySize() << "])\n"
+          << "{\n"
+             "    for (int i = 0; i < "
+          << type.getArraySize() << "; ++i)\n"
+                                    "    {\n"
+                                    "        a[i] = b[i];\n"
+                                    "    }\n"
+                                    "}\n";
+
+    function.functionDefinition = fnOut.c_str();
+
+    mArrayAssignmentFunctions.push_back(function);
+
+    return function.functionName;
+}
+
+TString OutputHLSL::addArrayConstructIntoFunction(const TType &type)
+{
+    for (const auto &constructIntoFunction : mArrayConstructIntoFunctions)
+    {
+        if (constructIntoFunction.type == type)
+        {
+            return constructIntoFunction.functionName;
+        }
+    }
+
+    const TString &typeName = TypeString(type);
+
+    ArrayHelperFunction function;
+    function.type = type;
+
+    TInfoSinkBase fnNameOut;
+    fnNameOut << "angle_construct_into_" << type.getArraySize() << "_" << typeName;
+    function.functionName = fnNameOut.c_str();
+
+    TInfoSinkBase fnOut;
+
+    fnOut << "void " << function.functionName << "(out " << typeName << " a[" << type.getArraySize()
+          << "]";
+    for (unsigned int i = 0u; i < type.getArraySize(); ++i)
+    {
+        fnOut << ", " << typeName << " b" << i;
+    }
+    fnOut << ")\n"
+             "{\n";
+
+    for (unsigned int i = 0u; i < type.getArraySize(); ++i)
+    {
+        fnOut << "    a[" << i << "] = b" << i << ";\n";
+    }
+    fnOut << "}\n";
+
+    function.functionDefinition = fnOut.c_str();
+
+    mArrayConstructIntoFunctions.push_back(function);
+
+    return function.functionName;
+}
+
+void OutputHLSL::ensureStructDefined(const TType &type)
+{
+    TStructure *structure = type.getStruct();
+
+    if (structure)
+    {
+        mStructureHLSL->addConstructor(type, StructNameString(*structure), nullptr);
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/OutputHLSL.h b/src/third_party/angle/src/compiler/translator/OutputHLSL.h
new file mode 100644
index 0000000..b1ccbc5
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputHLSL.h
@@ -0,0 +1,246 @@
+//
+// 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.
+//
+
+#ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_
+#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_
+
+#include <list>
+#include <map>
+#include <stack>
+
+#include "angle_gl.h"
+#include "compiler/translator/ASTMetadataHLSL.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/ParseContext.h"
+
+class BuiltInFunctionEmulator;
+
+namespace sh
+{
+class StructureHLSL;
+class TextureFunctionHLSL;
+class UnfoldShortCircuit;
+class UniformHLSL;
+
+typedef std::map<TString, TIntermSymbol *> ReferencedSymbols;
+
+class OutputHLSL : public TIntermTraverser
+{
+  public:
+    OutputHLSL(sh::GLenum shaderType,
+               int shaderVersion,
+               const TExtensionBehavior &extensionBehavior,
+               const char *sourcePath,
+               ShShaderOutput outputType,
+               int numRenderTargets,
+               const std::vector<Uniform> &uniforms,
+               ShCompileOptions compileOptions);
+
+    ~OutputHLSL();
+
+    void output(TIntermNode *treeRoot, TInfoSinkBase &objSink);
+
+    const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const;
+    const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
+
+    static TString initializer(const TType &type);
+
+    TInfoSinkBase &getInfoSink()
+    {
+        ASSERT(!mInfoSinkStack.empty());
+        return *mInfoSinkStack.top();
+    }
+
+    static bool canWriteAsHLSLLiteral(TIntermTyped *expression);
+
+  protected:
+    void header(TInfoSinkBase &out, const BuiltInFunctionEmulator *builtInFunctionEmulator);
+
+    void writeFloat(TInfoSinkBase &out, float f);
+    void writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion);
+    const TConstantUnion *writeConstantUnionArray(TInfoSinkBase &out,
+                                                  const TConstantUnion *const constUnion,
+                                                  const size_t size);
+
+    // Visit AST nodes and output their code to the body stream
+    void visitSymbol(TIntermSymbol *);
+    void visitRaw(TIntermRaw *);
+    void visitConstantUnion(TIntermConstantUnion *);
+    bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
+    bool visitBinary(Visit visit, TIntermBinary *);
+    bool visitUnary(Visit visit, TIntermUnary *);
+    bool visitTernary(Visit visit, TIntermTernary *);
+    bool visitIfElse(Visit visit, TIntermIfElse *);
+    bool visitSwitch(Visit visit, TIntermSwitch *);
+    bool visitCase(Visit visit, TIntermCase *);
+    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *);
+    bool visitBlock(Visit visit, TIntermBlock *node);
+    bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node);
+    bool visitDeclaration(Visit visit, TIntermDeclaration *node);
+    bool visitLoop(Visit visit, TIntermLoop *);
+    bool visitBranch(Visit visit, TIntermBranch *);
+
+    bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node);
+
+    // Emit one of three strings depending on traverse phase. Called with literal strings so using
+    // const char* instead of TString.
+    void outputTriplet(TInfoSinkBase &out,
+                       Visit visit,
+                       const char *preString,
+                       const char *inString,
+                       const char *postString);
+    void outputLineDirective(TInfoSinkBase &out, int line);
+    TString argumentString(const TIntermSymbol *symbol);
+    int vectorSize(const TType &type) const;
+
+    // Emit constructor. Called with literal names so using const char* instead of TString.
+    void outputConstructor(TInfoSinkBase &out,
+                           Visit visit,
+                           const TType &type,
+                           const char *name,
+                           const TIntermSequence *parameters);
+    const TConstantUnion *writeConstantUnion(TInfoSinkBase &out,
+                                             const TType &type,
+                                             const TConstantUnion *constUnion);
+
+    void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out);
+
+    void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op);
+    void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
+
+    // Returns true if it found a 'same symbol' initializer (initializer that references the
+    // variable it's initting)
+    bool writeSameSymbolInitializer(TInfoSinkBase &out,
+                                    TIntermSymbol *symbolNode,
+                                    TIntermTyped *expression);
+    // Returns true if variable initializer could be written using literal {} notation.
+    bool writeConstantInitialization(TInfoSinkBase &out,
+                                     TIntermSymbol *symbolNode,
+                                     TIntermTyped *expression);
+
+    void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node);
+
+    // Returns the function name
+    TString addStructEqualityFunction(const TStructure &structure);
+    TString addArrayEqualityFunction(const TType &type);
+    TString addArrayAssignmentFunction(const TType &type);
+    TString addArrayConstructIntoFunction(const TType &type);
+
+    // Ensures if the type is a struct, the struct is defined
+    void ensureStructDefined(const TType &type);
+
+    sh::GLenum mShaderType;
+    int mShaderVersion;
+    const TExtensionBehavior &mExtensionBehavior;
+    const char *mSourcePath;
+    const ShShaderOutput mOutputType;
+    ShCompileOptions mCompileOptions;
+
+    bool mInsideFunction;
+
+    // Output streams
+    TInfoSinkBase mHeader;
+    TInfoSinkBase mBody;
+    TInfoSinkBase mFooter;
+
+    // A stack is useful when we want to traverse in the header, or in helper functions, but not
+    // always write to the body. Instead use an InfoSink stack to keep our current state intact.
+    // TODO (jmadill): Just passing an InfoSink in function parameters would be simpler.
+    std::stack<TInfoSinkBase *> mInfoSinkStack;
+
+    ReferencedSymbols mReferencedUniforms;
+    ReferencedSymbols mReferencedInterfaceBlocks;
+    ReferencedSymbols mReferencedAttributes;
+    ReferencedSymbols mReferencedVaryings;
+    ReferencedSymbols mReferencedOutputVariables;
+
+    StructureHLSL *mStructureHLSL;
+    UniformHLSL *mUniformHLSL;
+    TextureFunctionHLSL *mTextureFunctionHLSL;
+
+    // Parameters determining what goes in the header output
+    bool mUsesFragColor;
+    bool mUsesFragData;
+    bool mUsesDepthRange;
+    bool mUsesFragCoord;
+    bool mUsesPointCoord;
+    bool mUsesFrontFacing;
+    bool mUsesPointSize;
+    bool mUsesInstanceID;
+    bool mUsesVertexID;
+    bool mUsesFragDepth;
+    bool mUsesNumWorkGroups;
+    bool mUsesWorkGroupID;
+    bool mUsesLocalInvocationID;
+    bool mUsesGlobalInvocationID;
+    bool mUsesLocalInvocationIndex;
+    bool mUsesXor;
+    bool mUsesDiscardRewriting;
+    bool mUsesNestedBreak;
+    bool mRequiresIEEEStrictCompiling;
+
+    int mNumRenderTargets;
+
+    int mUniqueIndex;  // For creating unique names
+
+    CallDAG mCallDag;
+    MetadataList mASTMetadataList;
+    ASTMetadataHLSL *mCurrentFunctionMetadata;
+    bool mOutputLod0Function;
+    bool mInsideDiscontinuousLoop;
+    int mNestedLoopDepth;
+
+    TIntermSymbol *mExcessiveLoopIndex;
+
+    TString structInitializerString(int indent,
+                                    const TStructure &structure,
+                                    const TString &rhsStructName);
+
+    std::map<TIntermTyped *, TString> mFlaggedStructMappedNames;
+    std::map<TIntermTyped *, TString> mFlaggedStructOriginalNames;
+
+    struct HelperFunction
+    {
+        TString functionName;
+        TString functionDefinition;
+
+        virtual ~HelperFunction() {}
+    };
+
+    // A list of all equality comparison functions. It's important to preserve the order at
+    // which we add the functions, since nested structures call each other recursively, and
+    // structure equality functions may need to call array equality functions and vice versa.
+    // The ownership of the pointers is maintained by the type-specific arrays.
+    std::vector<HelperFunction *> mEqualityFunctions;
+
+    struct StructEqualityFunction : public HelperFunction
+    {
+        const TStructure *structure;
+    };
+    std::vector<StructEqualityFunction *> mStructEqualityFunctions;
+
+    struct ArrayHelperFunction : public HelperFunction
+    {
+        TType type;
+    };
+    std::vector<ArrayHelperFunction *> mArrayEqualityFunctions;
+
+    std::vector<ArrayHelperFunction> mArrayAssignmentFunctions;
+
+    // The construct-into functions are functions that fill an N-element array passed as an out
+    // parameter with the other N parameters of the function. This is used to work around that
+    // arrays can't be return values in HLSL.
+    std::vector<ArrayHelperFunction> mArrayConstructIntoFunctions;
+
+  private:
+    TString samplerNamePrefixFromStruct(TIntermTyped *node);
+    bool ancestorEvaluatesToSamplerInStruct();
+};
+}
+
+#endif  // COMPILER_TRANSLATOR_OUTPUTHLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/OutputVulkanGLSL.cpp b/src/third_party/angle/src/compiler/translator/OutputVulkanGLSL.cpp
new file mode 100644
index 0000000..c2c7813
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputVulkanGLSL.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2016 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.
+//
+// OutputVulkanGLSL:
+//   Code that outputs shaders that fit GL_KHR_vulkan_glsl.
+//   The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
+//   See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
+//
+
+#include "compiler/translator/OutputVulkanGLSL.h"
+
+namespace sh
+{
+
+TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink,
+                                     ShArrayIndexClampingStrategy clampingStrategy,
+                                     ShHashFunction64 hashFunction,
+                                     NameMap &nameMap,
+                                     TSymbolTable &symbolTable,
+                                     sh::GLenum shaderType,
+                                     int shaderVersion,
+                                     ShShaderOutput output,
+                                     ShCompileOptions compileOptions)
+    : TOutputGLSLBase(objSink,
+                      clampingStrategy,
+                      hashFunction,
+                      nameMap,
+                      symbolTable,
+                      shaderType,
+                      shaderVersion,
+                      output,
+                      compileOptions)
+{
+}
+
+// TODO(jmadill): This is not complete.
+void TOutputVulkanGLSL::writeLayoutQualifier(const TType &type)
+{
+    TInfoSinkBase &out                      = objSink();
+    const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
+    out << "layout(";
+
+    if (type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut ||
+        type.getQualifier() == EvqVertexIn)
+    {
+        // TODO(jmadill): Multiple output locations.
+        out << "location = "
+            << "0";
+    }
+
+    if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
+    {
+        ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform);
+        out << getImageInternalFormatString(layoutQualifier.imageInternalFormat);
+    }
+
+    out << ") ";
+}
+
+bool TOutputVulkanGLSL::writeVariablePrecision(TPrecision precision)
+{
+    if (precision == EbpUndefined)
+        return false;
+
+    TInfoSinkBase &out = objSink();
+    out << getPrecisionString(precision);
+    return true;
+}
+
+void TOutputVulkanGLSL::visitSymbol(TIntermSymbol *node)
+{
+    TInfoSinkBase &out = objSink();
+
+    const TString &symbol = node->getSymbol();
+    if (symbol == "gl_FragColor")
+    {
+        out << "webgl_FragColor";
+    }
+    else if (symbol == "gl_FragData")
+    {
+        out << "webgl_FragData";
+    }
+    else
+    {
+        TOutputGLSLBase::visitSymbol(node);
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/OutputVulkanGLSL.h b/src/third_party/angle/src/compiler/translator/OutputVulkanGLSL.h
new file mode 100644
index 0000000..75f2f35
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/OutputVulkanGLSL.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2016 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.
+//
+// OutputVulkanGLSL:
+//   Code that outputs shaders that fit GL_KHR_vulkan_glsl.
+//   The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
+//   See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
+//
+
+#include "compiler/translator/OutputGLSL.h"
+
+namespace sh
+{
+
+class TOutputVulkanGLSL : public TOutputGLSLBase
+{
+  public:
+    TOutputVulkanGLSL(TInfoSinkBase &objSink,
+                      ShArrayIndexClampingStrategy clampingStrategy,
+                      ShHashFunction64 hashFunction,
+                      NameMap &nameMap,
+                      TSymbolTable &symbolTable,
+                      sh::GLenum shaderType,
+                      int shaderVersion,
+                      ShShaderOutput output,
+                      ShCompileOptions compileOptions);
+
+  protected:
+    void writeLayoutQualifier(const TType &type) override;
+    bool writeVariablePrecision(TPrecision precision) override;
+    void visitSymbol(TIntermSymbol *node) override;
+};
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ParseContext.cpp b/src/third_party/angle/src/compiler/translator/ParseContext.cpp
new file mode 100644
index 0000000..7777f98
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ParseContext.cpp
@@ -0,0 +1,4591 @@
+//
+// 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.
+//
+
+#include "compiler/translator/ParseContext.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/preprocessor/SourceLocation.h"
+#include "compiler/translator/Cache.h"
+#include "compiler/translator/glslang.h"
+#include "compiler/translator/ValidateSwitch.h"
+#include "compiler/translator/ValidateGlobalInitializer.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+///////////////////////////////////////////////////////////////////////
+//
+// Sub- vector and matrix fields
+//
+////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+
+const int kWebGLMaxStructNesting = 4;
+
+bool ContainsSampler(const TType &type)
+{
+    if (IsSampler(type.getBasicType()))
+        return true;
+
+    if (type.getBasicType() == EbtStruct)
+    {
+        const TFieldList &fields = type.getStruct()->fields();
+        for (unsigned int i = 0; i < fields.size(); ++i)
+        {
+            if (ContainsSampler(*fields[i]->type()))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+// Get a token from an image argument to use as an error message token.
+const char *GetImageArgumentToken(TIntermTyped *imageNode)
+{
+    ASSERT(IsImage(imageNode->getBasicType()));
+    while (imageNode->getAsBinaryNode() &&
+           (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
+            imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
+    {
+        imageNode = imageNode->getAsBinaryNode()->getLeft();
+    }
+    TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
+    if (imageSymbol)
+    {
+        return imageSymbol->getSymbol().c_str();
+    }
+    return "image";
+}
+
+}  // namespace
+
+TParseContext::TParseContext(TSymbolTable &symt,
+                             TExtensionBehavior &ext,
+                             sh::GLenum type,
+                             ShShaderSpec spec,
+                             ShCompileOptions options,
+                             bool checksPrecErrors,
+                             TDiagnostics *diagnostics,
+                             const ShBuiltInResources &resources)
+    : intermediate(),
+      symbolTable(symt),
+      mDeferredNonEmptyDeclarationErrorCheck(false),
+      mShaderType(type),
+      mShaderSpec(spec),
+      mCompileOptions(options),
+      mShaderVersion(100),
+      mTreeRoot(nullptr),
+      mLoopNestingLevel(0),
+      mStructNestingLevel(0),
+      mSwitchNestingLevel(0),
+      mCurrentFunctionType(nullptr),
+      mFunctionReturnsValue(false),
+      mChecksPrecisionErrors(checksPrecErrors),
+      mFragmentPrecisionHighOnESSL1(false),
+      mDefaultMatrixPacking(EmpColumnMajor),
+      mDefaultBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
+      mDiagnostics(diagnostics),
+      mDirectiveHandler(ext,
+                        *mDiagnostics,
+                        mShaderVersion,
+                        mShaderType,
+                        resources.WEBGL_debug_shader_precision == 1),
+      mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
+      mScanner(nullptr),
+      mUsesFragData(false),
+      mUsesFragColor(false),
+      mUsesSecondaryOutputs(false),
+      mMinProgramTexelOffset(resources.MinProgramTexelOffset),
+      mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
+      mMultiviewAvailable(resources.OVR_multiview == 1),
+      mComputeShaderLocalSizeDeclared(false),
+      mNumViews(-1),
+      mMaxNumViews(resources.MaxViewsOVR),
+      mMaxImageUnits(resources.MaxImageUnits),
+      mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits),
+      mMaxUniformLocations(resources.MaxUniformLocations),
+      mDeclaringFunction(false)
+{
+    mComputeShaderLocalSize.fill(-1);
+}
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a vector.
+//
+bool TParseContext::parseVectorFields(const TString &compString,
+                                      int vecSize,
+                                      TVectorFields &fields,
+                                      const TSourceLoc &line)
+{
+    fields.num = (int)compString.size();
+    if (fields.num > 4)
+    {
+        error(line, "illegal vector field selection", compString.c_str());
+        return false;
+    }
+
+    enum
+    {
+        exyzw,
+        ergba,
+        estpq
+    } fieldSet[4];
+
+    for (int i = 0; i < fields.num; ++i)
+    {
+        switch (compString[i])
+        {
+            case 'x':
+                fields.offsets[i] = 0;
+                fieldSet[i]       = exyzw;
+                break;
+            case 'r':
+                fields.offsets[i] = 0;
+                fieldSet[i]       = ergba;
+                break;
+            case 's':
+                fields.offsets[i] = 0;
+                fieldSet[i]       = estpq;
+                break;
+            case 'y':
+                fields.offsets[i] = 1;
+                fieldSet[i]       = exyzw;
+                break;
+            case 'g':
+                fields.offsets[i] = 1;
+                fieldSet[i]       = ergba;
+                break;
+            case 't':
+                fields.offsets[i] = 1;
+                fieldSet[i]       = estpq;
+                break;
+            case 'z':
+                fields.offsets[i] = 2;
+                fieldSet[i]       = exyzw;
+                break;
+            case 'b':
+                fields.offsets[i] = 2;
+                fieldSet[i]       = ergba;
+                break;
+            case 'p':
+                fields.offsets[i] = 2;
+                fieldSet[i]       = estpq;
+                break;
+
+            case 'w':
+                fields.offsets[i] = 3;
+                fieldSet[i]       = exyzw;
+                break;
+            case 'a':
+                fields.offsets[i] = 3;
+                fieldSet[i]       = ergba;
+                break;
+            case 'q':
+                fields.offsets[i] = 3;
+                fieldSet[i]       = estpq;
+                break;
+            default:
+                error(line, "illegal vector field selection", compString.c_str());
+                return false;
+        }
+    }
+
+    for (int i = 0; i < fields.num; ++i)
+    {
+        if (fields.offsets[i] >= vecSize)
+        {
+            error(line, "vector field selection out of range", compString.c_str());
+            return false;
+        }
+
+        if (i > 0)
+        {
+            if (fieldSet[i] != fieldSet[i - 1])
+            {
+                error(line, "illegal - vector component fields not from the same set",
+                      compString.c_str());
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Errors
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Used by flex/bison to output all syntax and parsing errors.
+//
+void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
+{
+    mDiagnostics->error(loc, reason, token);
+}
+
+void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
+{
+    mDiagnostics->warning(loc, reason, token);
+}
+
+void TParseContext::outOfRangeError(bool isError,
+                                    const TSourceLoc &loc,
+                                    const char *reason,
+                                    const char *token)
+{
+    if (isError)
+    {
+        error(loc, reason, token);
+    }
+    else
+    {
+        warning(loc, reason, token);
+    }
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
+{
+    std::stringstream reasonStream;
+    reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
+    std::string reason = reasonStream.str();
+    error(line, reason.c_str(), op);
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
+{
+    std::stringstream reasonStream;
+    reasonStream << "wrong operand type - no operation '" << op
+                 << "' exists that takes an operand of type " << operand
+                 << " (or there is no acceptable conversion)";
+    std::string reason = reasonStream.str();
+    error(line, reason.c_str(), op);
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(const TSourceLoc &line,
+                                  const char *op,
+                                  TString left,
+                                  TString right)
+{
+    std::stringstream reasonStream;
+    reasonStream << "wrong operand types - no operation '" << op
+                 << "' exists that takes a left-hand operand of type '" << left
+                 << "' and a right operand of type '" << right
+                 << "' (or there is no acceptable conversion)";
+    std::string reason = reasonStream.str();
+    error(line, reason.c_str(), op);
+}
+
+void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
+                                            TPrecision precision,
+                                            TBasicType type)
+{
+    if (!mChecksPrecisionErrors)
+        return;
+
+    if (precision != EbpUndefined && !SupportsPrecision(type))
+    {
+        error(line, "illegal type for precision qualifier", getBasicString(type));
+    }
+
+    if (precision == EbpUndefined)
+    {
+        switch (type)
+        {
+            case EbtFloat:
+                error(line, "No precision specified for (float)", "");
+                return;
+            case EbtInt:
+            case EbtUInt:
+                UNREACHABLE();  // there's always a predeclared qualifier
+                error(line, "No precision specified (int)", "");
+                return;
+            default:
+                if (IsOpaqueType(type))
+                {
+                    error(line, "No precision specified", getBasicString(type));
+                    return;
+                }
+        }
+    }
+}
+
+// Both test and if necessary, spit out an error, to see if the node is really
+// an l-value that can be operated on this way.
+bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
+{
+    TIntermSymbol *symNode      = node->getAsSymbolNode();
+    TIntermBinary *binaryNode   = node->getAsBinaryNode();
+    TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
+
+    if (swizzleNode)
+    {
+        bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
+        if (ok && swizzleNode->hasDuplicateOffsets())
+        {
+            error(line, " l-value of swizzle cannot have duplicate components", op);
+            return false;
+        }
+        return ok;
+    }
+
+    if (binaryNode)
+    {
+        switch (binaryNode->getOp())
+        {
+            case EOpIndexDirect:
+            case EOpIndexIndirect:
+            case EOpIndexDirectStruct:
+            case EOpIndexDirectInterfaceBlock:
+                return checkCanBeLValue(line, op, binaryNode->getLeft());
+            default:
+                break;
+        }
+        error(line, " l-value required", op);
+        return false;
+    }
+
+    std::string message;
+    switch (node->getQualifier())
+    {
+        case EvqConst:
+            message = "can't modify a const";
+            break;
+        case EvqConstReadOnly:
+            message = "can't modify a const";
+            break;
+        case EvqAttribute:
+            message = "can't modify an attribute";
+            break;
+        case EvqFragmentIn:
+            message = "can't modify an input";
+            break;
+        case EvqVertexIn:
+            message = "can't modify an input";
+            break;
+        case EvqUniform:
+            message = "can't modify a uniform";
+            break;
+        case EvqVaryingIn:
+            message = "can't modify a varying";
+            break;
+        case EvqFragCoord:
+            message = "can't modify gl_FragCoord";
+            break;
+        case EvqFrontFacing:
+            message = "can't modify gl_FrontFacing";
+            break;
+        case EvqPointCoord:
+            message = "can't modify gl_PointCoord";
+            break;
+        case EvqNumWorkGroups:
+            message = "can't modify gl_NumWorkGroups";
+            break;
+        case EvqWorkGroupSize:
+            message = "can't modify gl_WorkGroupSize";
+            break;
+        case EvqWorkGroupID:
+            message = "can't modify gl_WorkGroupID";
+            break;
+        case EvqLocalInvocationID:
+            message = "can't modify gl_LocalInvocationID";
+            break;
+        case EvqGlobalInvocationID:
+            message = "can't modify gl_GlobalInvocationID";
+            break;
+        case EvqLocalInvocationIndex:
+            message = "can't modify gl_LocalInvocationIndex";
+            break;
+        case EvqViewIDOVR:
+            message = "can't modify gl_ViewID_OVR";
+            break;
+        case EvqComputeIn:
+            message = "can't modify work group size variable";
+            break;
+        default:
+            //
+            // Type that can't be written to?
+            //
+            if (node->getBasicType() == EbtVoid)
+            {
+                message = "can't modify void";
+            }
+            if (IsOpaqueType(node->getBasicType()))
+            {
+                message = "can't modify a variable with type ";
+                message += getBasicString(node->getBasicType());
+            }
+    }
+
+    if (message.empty() && binaryNode == 0 && symNode == 0)
+    {
+        error(line, "l-value required", op);
+
+        return false;
+    }
+
+    //
+    // Everything else is okay, no error.
+    //
+    if (message.empty())
+        return true;
+
+    //
+    // If we get here, we have an error and a message.
+    //
+    if (symNode)
+    {
+        const char *symbol = symNode->getSymbol().c_str();
+        std::stringstream reasonStream;
+        reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
+        std::string reason = reasonStream.str();
+        error(line, reason.c_str(), op);
+    }
+    else
+    {
+        std::stringstream reasonStream;
+        reasonStream << "l-value required (" << message << ")";
+        std::string reason = reasonStream.str();
+        error(line, reason.c_str(), op);
+    }
+
+    return false;
+}
+
+// Both test, and if necessary spit out an error, to see if the node is really
+// a constant.
+void TParseContext::checkIsConst(TIntermTyped *node)
+{
+    if (node->getQualifier() != EvqConst)
+    {
+        error(node->getLine(), "constant expression required", "");
+    }
+}
+
+// Both test, and if necessary spit out an error, to see if the node is really
+// an integer.
+void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
+{
+    if (!node->isScalarInt())
+    {
+        error(node->getLine(), "integer expression required", token);
+    }
+}
+
+// Both test, and if necessary spit out an error, to see if we are currently
+// globally scoped.
+bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
+{
+    if (!symbolTable.atGlobalLevel())
+    {
+        error(line, "only allowed at global scope", token);
+        return false;
+    }
+    return true;
+}
+
+// For now, keep it simple:  if it starts "gl_", it's reserved, independent
+// of scope.  Except, if the symbol table is at the built-in push-level,
+// which is when we are parsing built-ins.
+// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
+// webgl shader.
+bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
+{
+    static const char *reservedErrMsg = "reserved built-in name";
+    if (!symbolTable.atBuiltInLevel())
+    {
+        if (identifier.compare(0, 3, "gl_") == 0)
+        {
+            error(line, reservedErrMsg, "gl_");
+            return false;
+        }
+        if (sh::IsWebGLBasedSpec(mShaderSpec))
+        {
+            if (identifier.compare(0, 6, "webgl_") == 0)
+            {
+                error(line, reservedErrMsg, "webgl_");
+                return false;
+            }
+            if (identifier.compare(0, 7, "_webgl_") == 0)
+            {
+                error(line, reservedErrMsg, "_webgl_");
+                return false;
+            }
+        }
+        if (identifier.find("__") != TString::npos)
+        {
+            error(line,
+                  "identifiers containing two consecutive underscores (__) are reserved as "
+                  "possible future keywords",
+                  identifier.c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// Make sure the argument types are correct for constructing a specific type.
+bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
+                                              const TIntermSequence *arguments,
+                                              const TType &type)
+{
+    if (arguments->empty())
+    {
+        error(line, "constructor does not have any arguments", "constructor");
+        return false;
+    }
+
+    for (TIntermNode *arg : *arguments)
+    {
+        const TIntermTyped *argTyped = arg->getAsTyped();
+        ASSERT(argTyped != nullptr);
+        if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
+        {
+            std::string reason("cannot convert a variable with type ");
+            reason += getBasicString(argTyped->getBasicType());
+            error(line, reason.c_str(), "constructor");
+            return false;
+        }
+        if (argTyped->getBasicType() == EbtVoid)
+        {
+            error(line, "cannot convert a void", "constructor");
+            return false;
+        }
+    }
+
+    if (type.isArray())
+    {
+        // The size of an unsized constructor should already have been determined.
+        ASSERT(!type.isUnsizedArray());
+        if (static_cast<size_t>(type.getArraySize()) != arguments->size())
+        {
+            error(line, "array constructor needs one argument per array element", "constructor");
+            return false;
+        }
+        // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
+        // the array.
+        for (TIntermNode *const &argNode : *arguments)
+        {
+            const TType &argType = argNode->getAsTyped()->getType();
+            if (argType.isArray())
+            {
+                error(line, "constructing from a non-dereferenced array", "constructor");
+                return false;
+            }
+            if (!argType.sameElementType(type))
+            {
+                error(line, "Array constructor argument has an incorrect type", "constructor");
+                return false;
+            }
+        }
+    }
+    else if (type.getBasicType() == EbtStruct)
+    {
+        const TFieldList &fields = type.getStruct()->fields();
+        if (fields.size() != arguments->size())
+        {
+            error(line,
+                  "Number of constructor parameters does not match the number of structure fields",
+                  "constructor");
+            return false;
+        }
+
+        for (size_t i = 0; i < fields.size(); i++)
+        {
+            if (i >= arguments->size() ||
+                (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type())
+            {
+                error(line, "Structure constructor arguments do not match structure fields",
+                      "constructor");
+                return false;
+            }
+        }
+    }
+    else
+    {
+        // We're constructing a scalar, vector, or matrix.
+
+        // Note: It's okay to have too many components available, but not okay to have unused
+        // arguments. 'full' will go to true when enough args have been seen. If we loop again,
+        // there is an extra argument, so 'overFull' will become true.
+
+        size_t size    = 0;
+        bool full      = false;
+        bool overFull  = false;
+        bool matrixArg = false;
+        for (TIntermNode *arg : *arguments)
+        {
+            const TIntermTyped *argTyped = arg->getAsTyped();
+            ASSERT(argTyped != nullptr);
+
+            if (argTyped->getType().isArray())
+            {
+                error(line, "constructing from a non-dereferenced array", "constructor");
+                return false;
+            }
+            if (argTyped->getType().isMatrix())
+            {
+                matrixArg = true;
+            }
+
+            size += argTyped->getType().getObjectSize();
+            if (full)
+            {
+                overFull = true;
+            }
+            if (type.getBasicType() != EbtStruct && !type.isArray() && size >= type.getObjectSize())
+            {
+                full = true;
+            }
+        }
+
+        if (type.isMatrix() && matrixArg)
+        {
+            if (arguments->size() != 1)
+            {
+                error(line, "constructing matrix from matrix can only take one argument",
+                      "constructor");
+                return false;
+            }
+        }
+        else
+        {
+            if (size != 1 && size < type.getObjectSize())
+            {
+                error(line, "not enough data provided for construction", "constructor");
+                return false;
+            }
+            if (overFull)
+            {
+                error(line, "too many arguments", "constructor");
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+// This function checks to see if a void variable has been declared and raise an error message for
+// such a case
+//
+// returns true in case of an error
+//
+bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
+                                   const TString &identifier,
+                                   const TBasicType &type)
+{
+    if (type == EbtVoid)
+    {
+        error(line, "illegal use of type 'void'", identifier.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression
+// or not.
+void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
+{
+    if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
+    {
+        error(line, "boolean expression expected", "");
+    }
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression
+// or not.
+void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
+{
+    if (pType.getBasicType() != EbtBool || pType.isAggregate())
+    {
+        error(line, "boolean expression expected", "");
+    }
+}
+
+bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
+                                         const TTypeSpecifierNonArray &pType,
+                                         const char *reason)
+{
+    if (pType.type == EbtStruct)
+    {
+        if (ContainsSampler(*pType.userDef))
+        {
+            std::stringstream reasonStream;
+            reasonStream << reason << " (structure contains a sampler)";
+            std::string reasonStr = reasonStream.str();
+            error(line, reasonStr.c_str(), getBasicString(pType.type));
+            return false;
+        }
+        // only samplers need to be checked from structs, since other opaque types can't be struct
+        // members.
+        return true;
+    }
+    else if (IsOpaqueType(pType.type))
+    {
+        error(line, reason, getBasicString(pType.type));
+        return false;
+    }
+
+    return true;
+}
+
+void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
+                                                          const TPublicType &pType)
+{
+    if (pType.layoutQualifier.location != -1)
+    {
+        error(line, "location must only be specified for a single input or output variable",
+              "location");
+    }
+}
+
+void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
+                                                const TLayoutQualifier &layoutQualifier)
+{
+    if (layoutQualifier.location != -1)
+    {
+        const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
+        if (mShaderVersion >= 310)
+        {
+            errorMsg =
+                "invalid layout qualifier: only valid on program inputs, outputs, and uniforms";
+        }
+        error(location, errorMsg, "location");
+    }
+}
+
+void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
+                                                     TQualifier qualifier,
+                                                     const TType &type)
+{
+    ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
+    if (IsOpaqueType(type.getBasicType()))
+    {
+        error(line, "opaque types cannot be output parameters", type.getBasicString());
+    }
+}
+
+// Do size checking for an array type's size.
+unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
+{
+    TIntermConstantUnion *constant = expr->getAsConstantUnion();
+
+    // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
+    // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
+    // fold as array size.
+    if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
+    {
+        error(line, "array size must be a constant integer expression", "");
+        return 1u;
+    }
+
+    unsigned int size = 0u;
+
+    if (constant->getBasicType() == EbtUInt)
+    {
+        size = constant->getUConst(0);
+    }
+    else
+    {
+        int signedSize = constant->getIConst(0);
+
+        if (signedSize < 0)
+        {
+            error(line, "array size must be non-negative", "");
+            return 1u;
+        }
+
+        size = static_cast<unsigned int>(signedSize);
+    }
+
+    if (size == 0u)
+    {
+        error(line, "array size must be greater than zero", "");
+        return 1u;
+    }
+
+    // The size of arrays is restricted here to prevent issues further down the
+    // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
+    // 4096 registers so this should be reasonable even for aggressively optimizable code.
+    const unsigned int sizeLimit = 65536;
+
+    if (size > sizeLimit)
+    {
+        error(line, "array size too large", "");
+        return 1u;
+    }
+
+    return size;
+}
+
+// See if this qualifier can be an array.
+bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
+                                                  const TPublicType &elementQualifier)
+{
+    if ((elementQualifier.qualifier == EvqAttribute) ||
+        (elementQualifier.qualifier == EvqVertexIn) ||
+        (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
+    {
+        error(line, "cannot declare arrays of this qualifier",
+              TType(elementQualifier).getQualifierString());
+        return false;
+    }
+
+    return true;
+}
+
+// See if this element type can be formed into an array.
+bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
+{
+    //
+    // Can the type be an array?
+    //
+    if (elementType.array)
+    {
+        error(line, "cannot declare arrays of arrays",
+              TType(elementType).getCompleteString().c_str());
+        return false;
+    }
+    // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
+    // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
+    // 4.3.4).
+    if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
+        sh::IsVarying(elementType.qualifier))
+    {
+        error(line, "cannot declare arrays of structs of this qualifier",
+              TType(elementType).getCompleteString().c_str());
+        return false;
+    }
+
+    return true;
+}
+
+// Check if this qualified element type can be formed into an array.
+bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
+                                                         const TPublicType &elementType)
+{
+    if (checkIsValidTypeForArray(indexLocation, elementType))
+    {
+        return checkIsValidQualifierForArray(indexLocation, elementType);
+    }
+    return false;
+}
+
+// Enforce non-initializer type/qualifier rules.
+void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
+                                                         const TString &identifier,
+                                                         TPublicType *type)
+{
+    ASSERT(type != nullptr);
+    if (type->qualifier == EvqConst)
+    {
+        // Make the qualifier make sense.
+        type->qualifier = EvqTemporary;
+
+        // Generate informative error messages for ESSL1.
+        // In ESSL3 arrays and structures containing arrays can be constant.
+        if (mShaderVersion < 300 && type->isStructureContainingArrays())
+        {
+            error(line,
+                  "structures containing arrays may not be declared constant since they cannot be "
+                  "initialized",
+                  identifier.c_str());
+        }
+        else
+        {
+            error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
+        }
+        return;
+    }
+    if (type->isUnsizedArray())
+    {
+        error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
+    }
+}
+
+// Do some simple checks that are shared between all variable declarations,
+// and update the symbol table.
+//
+// Returns true if declaring the variable succeeded.
+//
+bool TParseContext::declareVariable(const TSourceLoc &line,
+                                    const TString &identifier,
+                                    const TType &type,
+                                    TVariable **variable)
+{
+    ASSERT((*variable) == nullptr);
+
+    checkBindingIsValid(line, type);
+
+    bool needsReservedCheck = true;
+
+    // gl_LastFragData may be redeclared with a new precision qualifier
+    if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
+    {
+        const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
+            symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
+        if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
+        {
+            if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
+            {
+                needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
+            }
+        }
+        else
+        {
+            error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
+                  identifier.c_str());
+            return false;
+        }
+    }
+
+    if (needsReservedCheck && !checkIsNotReserved(line, identifier))
+        return false;
+
+    (*variable) = new TVariable(&identifier, type);
+    if (!symbolTable.declare(*variable))
+    {
+        error(line, "redefinition", identifier.c_str());
+        *variable = nullptr;
+        return false;
+    }
+
+    if (!checkIsNonVoid(line, identifier, type.getBasicType()))
+        return false;
+
+    return true;
+}
+
+void TParseContext::checkIsParameterQualifierValid(
+    const TSourceLoc &line,
+    const TTypeQualifierBuilder &typeQualifierBuilder,
+    TType *type)
+{
+    TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
+
+    if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
+    {
+        checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
+    }
+
+    if (!IsImage(type->getBasicType()))
+    {
+        checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
+    }
+    else
+    {
+        type->setMemoryQualifier(typeQualifier.memoryQualifier);
+    }
+
+    type->setQualifier(typeQualifier.qualifier);
+
+    if (typeQualifier.precision != EbpUndefined)
+    {
+        type->setPrecision(typeQualifier.precision);
+    }
+}
+
+bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
+{
+    const TExtensionBehavior &extBehavior   = extensionBehavior();
+    TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
+    if (iter == extBehavior.end())
+    {
+        error(line, "extension is not supported", extension.c_str());
+        return false;
+    }
+    // In GLSL ES, an extension's default behavior is "disable".
+    if (iter->second == EBhDisable || iter->second == EBhUndefined)
+    {
+        // TODO(oetuaho@nvidia.com): This is slightly hacky. Might be better if symbols could be
+        // associated with more than one extension.
+        if (extension == "GL_OVR_multiview")
+        {
+            return checkCanUseExtension(line, "GL_OVR_multiview2");
+        }
+        error(line, "extension is disabled", extension.c_str());
+        return false;
+    }
+    if (iter->second == EBhWarn)
+    {
+        warning(line, "extension is being used", extension.c_str());
+        return true;
+    }
+
+    return true;
+}
+
+// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
+// compile-time or link-time errors are the same whether or not the declaration is empty".
+// This function implements all the checks that are done on qualifiers regardless of if the
+// declaration is empty.
+void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
+                                                   const sh::TLayoutQualifier &layoutQualifier,
+                                                   const TSourceLoc &location)
+{
+    if (qualifier == EvqShared && !layoutQualifier.isEmpty())
+    {
+        error(location, "Shared memory declarations cannot have layout specified", "layout");
+    }
+
+    if (layoutQualifier.matrixPacking != EmpUnspecified)
+    {
+        error(location, "layout qualifier only valid for interface blocks",
+              getMatrixPackingString(layoutQualifier.matrixPacking));
+        return;
+    }
+
+    if (layoutQualifier.blockStorage != EbsUnspecified)
+    {
+        error(location, "layout qualifier only valid for interface blocks",
+              getBlockStorageString(layoutQualifier.blockStorage));
+        return;
+    }
+
+    if (qualifier == EvqFragmentOut)
+    {
+        if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
+        {
+            error(location, "invalid layout qualifier combination", "yuv");
+            return;
+        }
+    }
+    else
+    {
+        checkYuvIsNotSpecified(location, layoutQualifier.yuv);
+    }
+
+    bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
+    if (mShaderVersion >= 310 && qualifier == EvqUniform)
+    {
+        canHaveLocation = true;
+        // We're not checking whether the uniform location is in range here since that depends on
+        // the type of the variable.
+        // The type can only be fully determined for non-empty declarations.
+    }
+    if (!canHaveLocation)
+    {
+        checkLocationIsNotSpecified(location, layoutQualifier);
+    }
+}
+
+void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
+                                               const TSourceLoc &location)
+{
+    if (publicType.isUnsizedArray())
+    {
+        // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
+        // error. It is assumed that this applies to empty declarations as well.
+        error(location, "empty array declaration needs to specify a size", "");
+    }
+}
+
+// These checks are done for all declarations that are non-empty. They're done for non-empty
+// declarations starting a declarator list, and declarators that follow an empty declaration.
+void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
+                                                  const TSourceLoc &identifierLocation)
+{
+    switch (publicType.qualifier)
+    {
+        case EvqVaryingIn:
+        case EvqVaryingOut:
+        case EvqAttribute:
+        case EvqVertexIn:
+        case EvqFragmentOut:
+        case EvqComputeIn:
+            if (publicType.getBasicType() == EbtStruct)
+            {
+                error(identifierLocation, "cannot be used with a structure",
+                      getQualifierString(publicType.qualifier));
+                return;
+            }
+
+        default:
+            break;
+    }
+    std::string reason(getBasicString(publicType.getBasicType()));
+    reason += "s must be uniform";
+    if (publicType.qualifier != EvqUniform &&
+        !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
+    {
+        return;
+    }
+
+    if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
+         publicType.qualifier != EvqConst) &&
+        publicType.getBasicType() == EbtYuvCscStandardEXT)
+    {
+        error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
+              getQualifierString(publicType.qualifier));
+        return;
+    }
+
+    if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
+    {
+        // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
+        // But invalid shaders may still reach here with an unsized array declaration.
+        if (!publicType.isUnsizedArray())
+        {
+            TType type(publicType);
+            checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
+                                        publicType.layoutQualifier);
+        }
+    }
+
+    // check for layout qualifier issues
+    const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
+
+    if (IsImage(publicType.getBasicType()))
+    {
+
+        switch (layoutQualifier.imageInternalFormat)
+        {
+            case EiifRGBA32F:
+            case EiifRGBA16F:
+            case EiifR32F:
+            case EiifRGBA8:
+            case EiifRGBA8_SNORM:
+                if (!IsFloatImage(publicType.getBasicType()))
+                {
+                    error(identifierLocation,
+                          "internal image format requires a floating image type",
+                          getBasicString(publicType.getBasicType()));
+                    return;
+                }
+                break;
+            case EiifRGBA32I:
+            case EiifRGBA16I:
+            case EiifRGBA8I:
+            case EiifR32I:
+                if (!IsIntegerImage(publicType.getBasicType()))
+                {
+                    error(identifierLocation,
+                          "internal image format requires an integer image type",
+                          getBasicString(publicType.getBasicType()));
+                    return;
+                }
+                break;
+            case EiifRGBA32UI:
+            case EiifRGBA16UI:
+            case EiifRGBA8UI:
+            case EiifR32UI:
+                if (!IsUnsignedImage(publicType.getBasicType()))
+                {
+                    error(identifierLocation,
+                          "internal image format requires an unsigned image type",
+                          getBasicString(publicType.getBasicType()));
+                    return;
+                }
+                break;
+            case EiifUnspecified:
+                error(identifierLocation, "layout qualifier", "No image internal format specified");
+                return;
+            default:
+                error(identifierLocation, "layout qualifier", "unrecognized token");
+                return;
+        }
+
+        // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+        switch (layoutQualifier.imageInternalFormat)
+        {
+            case EiifR32F:
+            case EiifR32I:
+            case EiifR32UI:
+                break;
+            default:
+                if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
+                {
+                    error(identifierLocation, "layout qualifier",
+                          "Except for images with the r32f, r32i and r32ui format qualifiers, "
+                          "image variables must be qualified readonly and/or writeonly");
+                    return;
+                }
+                break;
+        }
+    }
+    else
+    {
+        checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
+
+        checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
+    }
+}
+
+void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
+{
+    TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
+    int arraySize                    = type.isArray() ? type.getArraySize() : 1;
+    if (IsImage(type.getBasicType()))
+    {
+        checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
+    }
+    else if (IsSampler(type.getBasicType()))
+    {
+        checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
+    }
+    else
+    {
+        ASSERT(!IsOpaqueType(type.getBasicType()));
+        checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
+    }
+}
+
+void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
+                                                  const TString &layoutQualifierName,
+                                                  int versionRequired)
+{
+
+    if (mShaderVersion < versionRequired)
+    {
+        error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
+    }
+}
+
+bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
+                                                     const TLayoutQualifier &layoutQualifier)
+{
+    const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
+    for (size_t i = 0u; i < localSize.size(); ++i)
+    {
+        if (localSize[i] != -1)
+        {
+            error(location,
+                  "invalid layout qualifier: only valid when used with 'in' in a compute shader "
+                  "global layout declaration",
+                  getWorkGroupSizeString(i));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
+                                                      TLayoutImageInternalFormat internalFormat)
+{
+    if (internalFormat != EiifUnspecified)
+    {
+        error(location, "invalid layout qualifier: only valid when used with images",
+              getImageInternalFormatString(internalFormat));
+    }
+}
+
+void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
+{
+    if (binding != -1)
+    {
+        error(location,
+              "invalid layout qualifier: only valid when used with opaque types or blocks",
+              "binding");
+    }
+}
+
+void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize)
+{
+    // Expects arraySize to be 1 when setting binding for only a single variable.
+    if (binding >= 0 && binding + arraySize > mMaxImageUnits)
+    {
+        error(location, "image binding greater than gl_MaxImageUnits", "binding");
+    }
+}
+
+void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
+                                               int binding,
+                                               int arraySize)
+{
+    // Expects arraySize to be 1 when setting binding for only a single variable.
+    if (binding >= 0 && binding + arraySize > mMaxCombinedTextureImageUnits)
+    {
+        error(location, "sampler binding greater than maximum texture units", "binding");
+    }
+}
+
+void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
+                                                int objectLocationCount,
+                                                const TLayoutQualifier &layoutQualifier)
+{
+    int loc = layoutQualifier.location;
+    if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
+    {
+        error(location, "Uniform location out of range", "location");
+    }
+}
+
+void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
+{
+    if (yuv != false)
+    {
+        error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
+    }
+}
+
+void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
+                                                 TIntermAggregate *fnCall)
+{
+    for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
+    {
+        TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
+        if (qual == EvqOut || qual == EvqInOut)
+        {
+            TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
+            if (!checkCanBeLValue(argument->getLine(), "assign", argument))
+            {
+                error(argument->getLine(),
+                      "Constant value cannot be passed for 'out' or 'inout' parameters.",
+                      fnCall->getFunctionSymbolInfo()->getName().c_str());
+                return;
+            }
+        }
+    }
+}
+
+void TParseContext::checkInvariantVariableQualifier(bool invariant,
+                                                    const TQualifier qualifier,
+                                                    const TSourceLoc &invariantLocation)
+{
+    if (!invariant)
+        return;
+
+    if (mShaderVersion < 300)
+    {
+        // input variables in the fragment shader can be also qualified as invariant
+        if (!sh::CanBeInvariantESSL1(qualifier))
+        {
+            error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
+        }
+    }
+    else
+    {
+        if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
+        {
+            error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
+        }
+    }
+}
+
+bool TParseContext::supportsExtension(const char *extension)
+{
+    const TExtensionBehavior &extbehavior   = extensionBehavior();
+    TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
+    return (iter != extbehavior.end());
+}
+
+bool TParseContext::isExtensionEnabled(const char *extension) const
+{
+    return ::IsExtensionEnabled(extensionBehavior(), extension);
+}
+
+void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
+                                             const char *extName,
+                                             const char *behavior)
+{
+    pp::SourceLocation srcLoc;
+    srcLoc.file = loc.first_file;
+    srcLoc.line = loc.first_line;
+    mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
+}
+
+void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
+                                          const char *name,
+                                          const char *value,
+                                          bool stdgl)
+{
+    pp::SourceLocation srcLoc;
+    srcLoc.file = loc.first_file;
+    srcLoc.line = loc.first_line;
+    mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
+}
+
+sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
+{
+    sh::WorkGroupSize result;
+    for (size_t i = 0u; i < result.size(); ++i)
+    {
+        if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
+        {
+            result[i] = 1;
+        }
+        else
+        {
+            result[i] = mComputeShaderLocalSize[i];
+        }
+    }
+    return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Non-Errors.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
+                                                 const TString *name,
+                                                 const TSymbol *symbol)
+{
+    const TVariable *variable = nullptr;
+
+    if (!symbol)
+    {
+        error(location, "undeclared identifier", name->c_str());
+    }
+    else if (!symbol->isVariable())
+    {
+        error(location, "variable expected", name->c_str());
+    }
+    else
+    {
+        variable = static_cast<const TVariable *>(symbol);
+
+        if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
+            !variable->getExtension().empty())
+        {
+            checkCanUseExtension(location, variable->getExtension());
+        }
+
+        // Reject shaders using both gl_FragData and gl_FragColor
+        TQualifier qualifier = variable->getType().getQualifier();
+        if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
+        {
+            mUsesFragData = true;
+        }
+        else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
+        {
+            mUsesFragColor = true;
+        }
+        if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
+        {
+            mUsesSecondaryOutputs = true;
+        }
+
+        // This validation is not quite correct - it's only an error to write to
+        // both FragData and FragColor. For simplicity, and because users shouldn't
+        // be rewarded for reading from undefined varaibles, return an error
+        // if they are both referenced, rather than assigned.
+        if (mUsesFragData && mUsesFragColor)
+        {
+            const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
+            if (mUsesSecondaryOutputs)
+            {
+                errorMessage =
+                    "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
+                    " and (gl_FragColor, gl_SecondaryFragColorEXT)";
+            }
+            error(location, errorMessage, name->c_str());
+        }
+
+        // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
+        if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
+            qualifier == EvqWorkGroupSize)
+        {
+            error(location,
+                  "It is an error to use gl_WorkGroupSize before declaring the local group size",
+                  "gl_WorkGroupSize");
+        }
+    }
+
+    if (!variable)
+    {
+        TType type(EbtFloat, EbpUndefined);
+        TVariable *fakeVariable = new TVariable(name, type);
+        symbolTable.declare(fakeVariable);
+        variable = fakeVariable;
+    }
+
+    return variable;
+}
+
+TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
+                                                     const TString *name,
+                                                     const TSymbol *symbol)
+{
+    const TVariable *variable = getNamedVariable(location, name, symbol);
+
+    if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
+        mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
+    {
+        // WEBGL_multiview spec
+        error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
+              "gl_ViewID_OVR");
+    }
+
+    if (variable->getConstPointer())
+    {
+        const TConstantUnion *constArray = variable->getConstPointer();
+        return intermediate.addConstantUnion(constArray, variable->getType(), location);
+    }
+    else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
+             mComputeShaderLocalSizeDeclared)
+    {
+        // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
+        // needs to be added to the AST as a constant and not as a symbol.
+        sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
+        TConstantUnion *constArray      = new TConstantUnion[3];
+        for (size_t i = 0; i < 3; ++i)
+        {
+            constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
+        }
+
+        ASSERT(variable->getType().getBasicType() == EbtUInt);
+        ASSERT(variable->getType().getObjectSize() == 3);
+
+        TType type(variable->getType());
+        type.setQualifier(EvqConst);
+        return intermediate.addConstantUnion(constArray, type, location);
+    }
+    else
+    {
+        return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
+                                      variable->getType(), location);
+    }
+}
+
+//
+// Initializers show up in several places in the grammar.  Have one set of
+// code to handle them here.
+//
+// Returns true on error, false if no error
+//
+bool TParseContext::executeInitializer(const TSourceLoc &line,
+                                       const TString &identifier,
+                                       const TPublicType &pType,
+                                       TIntermTyped *initializer,
+                                       TIntermBinary **initNode)
+{
+    ASSERT(initNode != nullptr);
+    ASSERT(*initNode == nullptr);
+    TType type = TType(pType);
+
+    TVariable *variable = nullptr;
+    if (type.isUnsizedArray())
+    {
+        // We have not checked yet whether the initializer actually is an array or not.
+        if (initializer->isArray())
+        {
+            type.setArraySize(initializer->getArraySize());
+        }
+        else
+        {
+            // Having a non-array initializer for an unsized array will result in an error later,
+            // so we don't generate an error message here.
+            type.setArraySize(1u);
+        }
+    }
+    if (!declareVariable(line, identifier, type, &variable))
+    {
+        return true;
+    }
+
+    bool globalInitWarning = false;
+    if (symbolTable.atGlobalLevel() &&
+        !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
+    {
+        // Error message does not completely match behavior with ESSL 1.00, but
+        // we want to steer developers towards only using constant expressions.
+        error(line, "global variable initializers must be constant expressions", "=");
+        return true;
+    }
+    if (globalInitWarning)
+    {
+        warning(
+            line,
+            "global variable initializers should be constant expressions "
+            "(uniforms and globals are allowed in global initializers for legacy compatibility)",
+            "=");
+    }
+
+    //
+    // identifier must be of type constant, a global, or a temporary
+    //
+    TQualifier qualifier = variable->getType().getQualifier();
+    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
+    {
+        error(line, " cannot initialize this type of qualifier ",
+              variable->getType().getQualifierString());
+        return true;
+    }
+    //
+    // test for and propagate constant
+    //
+
+    if (qualifier == EvqConst)
+    {
+        if (qualifier != initializer->getType().getQualifier())
+        {
+            std::stringstream reasonStream;
+            reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
+                         << "'";
+            std::string reason = reasonStream.str();
+            error(line, reason.c_str(), "=");
+            variable->getType().setQualifier(EvqTemporary);
+            return true;
+        }
+        if (type != initializer->getType())
+        {
+            error(line, " non-matching types for const initializer ",
+                  variable->getType().getQualifierString());
+            variable->getType().setQualifier(EvqTemporary);
+            return true;
+        }
+
+        // Save the constant folded value to the variable if possible. For example array
+        // initializers are not folded, since that way copying the array literal to multiple places
+        // in the shader is avoided.
+        // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
+        // it would be beneficial.
+        if (initializer->getAsConstantUnion())
+        {
+            variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
+            *initNode = nullptr;
+            return false;
+        }
+        else if (initializer->getAsSymbolNode())
+        {
+            const TSymbol *symbol =
+                symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
+            const TVariable *tVar = static_cast<const TVariable *>(symbol);
+
+            const TConstantUnion *constArray = tVar->getConstPointer();
+            if (constArray)
+            {
+                variable->shareConstPointer(constArray);
+                *initNode = nullptr;
+                return false;
+            }
+        }
+    }
+
+    TIntermSymbol *intermSymbol = intermediate.addSymbol(
+        variable->getUniqueId(), variable->getName(), variable->getType(), line);
+    *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
+    if (*initNode == nullptr)
+    {
+        assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
+        return true;
+    }
+
+    return false;
+}
+
+void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
+{
+    checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
+                            typeSpecifier->getBasicType());
+
+    if (mShaderVersion < 300 && typeSpecifier->array)
+    {
+        error(typeSpecifier->getLine(), "not supported", "first-class array");
+        typeSpecifier->clearArrayness();
+    }
+}
+
+TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
+                                                 const TPublicType &typeSpecifier)
+{
+    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
+
+    TPublicType returnType     = typeSpecifier;
+    returnType.qualifier       = typeQualifier.qualifier;
+    returnType.invariant       = typeQualifier.invariant;
+    returnType.layoutQualifier = typeQualifier.layoutQualifier;
+    returnType.memoryQualifier = typeQualifier.memoryQualifier;
+    returnType.precision       = typeSpecifier.precision;
+
+    if (typeQualifier.precision != EbpUndefined)
+    {
+        returnType.precision = typeQualifier.precision;
+    }
+
+    checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
+                            typeSpecifier.getBasicType());
+
+    checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
+                                    typeSpecifier.getLine());
+
+    checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
+
+    if (mShaderVersion < 300)
+    {
+        if (typeSpecifier.array)
+        {
+            error(typeSpecifier.getLine(), "not supported", "first-class array");
+            returnType.clearArrayness();
+        }
+
+        if (returnType.qualifier == EvqAttribute &&
+            (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
+        {
+            error(typeSpecifier.getLine(), "cannot be bool or int",
+                  getQualifierString(returnType.qualifier));
+        }
+
+        if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
+            (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
+        {
+            error(typeSpecifier.getLine(), "cannot be bool or int",
+                  getQualifierString(returnType.qualifier));
+        }
+    }
+    else
+    {
+        if (!returnType.layoutQualifier.isEmpty())
+        {
+            checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
+        }
+        if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
+            returnType.qualifier == EvqFragmentOut)
+        {
+            checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
+                                           typeSpecifier.getLine());
+        }
+        if (returnType.qualifier == EvqComputeIn)
+        {
+            error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
+                  "in");
+        }
+    }
+
+    return returnType;
+}
+
+void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
+                                                   const TPublicType &type,
+                                                   const TSourceLoc &qualifierLocation)
+{
+    // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
+    if (type.getBasicType() == EbtBool)
+    {
+        error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
+    }
+
+    // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
+    switch (qualifier)
+    {
+        case EvqVertexIn:
+            // ESSL 3.00 section 4.3.4
+            if (type.array)
+            {
+                error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
+            }
+            // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
+            return;
+        case EvqFragmentOut:
+            // ESSL 3.00 section 4.3.6
+            if (type.typeSpecifierNonArray.isMatrix())
+            {
+                error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
+            }
+            // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
+            return;
+        default:
+            break;
+    }
+
+    // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
+    // restrictions.
+    bool typeContainsIntegers =
+        (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
+         type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
+    if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
+    {
+        error(qualifierLocation, "must use 'flat' interpolation here",
+              getQualifierString(qualifier));
+    }
+
+    if (type.getBasicType() == EbtStruct)
+    {
+        // ESSL 3.00 sections 4.3.4 and 4.3.6.
+        // These restrictions are only implied by the ESSL 3.00 spec, but
+        // the ESSL 3.10 spec lists these restrictions explicitly.
+        if (type.array)
+        {
+            error(qualifierLocation, "cannot be an array of structures",
+                  getQualifierString(qualifier));
+        }
+        if (type.isStructureContainingArrays())
+        {
+            error(qualifierLocation, "cannot be a structure containing an array",
+                  getQualifierString(qualifier));
+        }
+        if (type.isStructureContainingType(EbtStruct))
+        {
+            error(qualifierLocation, "cannot be a structure containing a structure",
+                  getQualifierString(qualifier));
+        }
+        if (type.isStructureContainingType(EbtBool))
+        {
+            error(qualifierLocation, "cannot be a structure containing a bool",
+                  getQualifierString(qualifier));
+        }
+    }
+}
+
+void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
+{
+    if (qualifier.getType() == QtStorage)
+    {
+        const TStorageQualifierWrapper &storageQualifier =
+            static_cast<const TStorageQualifierWrapper &>(qualifier);
+        if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
+            !symbolTable.atGlobalLevel())
+        {
+            error(storageQualifier.getLine(),
+                  "Local variables can only use the const storage qualifier.",
+                  storageQualifier.getQualifierString().c_str());
+        }
+    }
+}
+
+void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
+                                                       const TSourceLoc &location)
+{
+    if (memoryQualifier.readonly)
+    {
+        error(location, "Only allowed with images.", "readonly");
+    }
+    if (memoryQualifier.writeonly)
+    {
+        error(location, "Only allowed with images.", "writeonly");
+    }
+    if (memoryQualifier.coherent)
+    {
+        error(location, "Only allowed with images.", "coherent");
+    }
+    if (memoryQualifier.restrictQualifier)
+    {
+        error(location, "Only allowed with images.", "restrict");
+    }
+    if (memoryQualifier.volatileQualifier)
+    {
+        error(location, "Only allowed with images.", "volatile");
+    }
+}
+
+TIntermDeclaration *TParseContext::parseSingleDeclaration(
+    TPublicType &publicType,
+    const TSourceLoc &identifierOrTypeLocation,
+    const TString &identifier)
+{
+    TType type(publicType);
+    if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
+        mDirectiveHandler.pragma().stdgl.invariantAll)
+    {
+        TQualifier qualifier = type.getQualifier();
+
+        // The directive handler has already taken care of rejecting invalid uses of this pragma
+        // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
+        // affected variable declarations:
+        //
+        // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
+        // elsewhere, in TranslatorGLSL.)
+        //
+        // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
+        // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
+        // the way this is currently implemented we have to enable this compiler option before
+        // parsing the shader and determining the shading language version it uses. If this were
+        // implemented as a post-pass, the workaround could be more targeted.
+        //
+        // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
+        // the specification, but there are desktop OpenGL drivers that expect that this is the
+        // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
+        if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
+        {
+            type.setInvariant(true);
+        }
+    }
+
+    declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
+                                   identifierOrTypeLocation);
+
+    bool emptyDeclaration = (identifier == "");
+    mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
+
+    TIntermSymbol *symbol = nullptr;
+    if (emptyDeclaration)
+    {
+        emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
+        // In most cases we don't need to create a symbol node for an empty declaration.
+        // But if the empty declaration is declaring a struct type, the symbol node will store that.
+        if (type.getBasicType() == EbtStruct)
+        {
+            symbol = intermediate.addSymbol(0, "", type, identifierOrTypeLocation);
+        }
+    }
+    else
+    {
+        nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
+
+        checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
+
+        TVariable *variable = nullptr;
+        declareVariable(identifierOrTypeLocation, identifier, type, &variable);
+
+        if (variable)
+        {
+            symbol = intermediate.addSymbol(variable->getUniqueId(), identifier, type,
+                                            identifierOrTypeLocation);
+        }
+    }
+
+    TIntermDeclaration *declaration = new TIntermDeclaration();
+    declaration->setLine(identifierOrTypeLocation);
+    if (symbol)
+    {
+        declaration->appendDeclarator(symbol);
+    }
+    return declaration;
+}
+
+TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
+                                                               const TSourceLoc &identifierLocation,
+                                                               const TString &identifier,
+                                                               const TSourceLoc &indexLocation,
+                                                               TIntermTyped *indexExpression)
+{
+    mDeferredNonEmptyDeclarationErrorCheck = false;
+
+    declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
+                                   identifierLocation);
+
+    nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+
+    checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
+
+    checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
+
+    TType arrayType(publicType);
+
+    unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
+    // Make the type an array even if size check failed.
+    // This ensures useless error messages regarding the variable's non-arrayness won't follow.
+    arrayType.setArraySize(size);
+
+    TVariable *variable = nullptr;
+    declareVariable(identifierLocation, identifier, arrayType, &variable);
+
+    TIntermDeclaration *declaration = new TIntermDeclaration();
+    declaration->setLine(identifierLocation);
+
+    TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
+    if (variable && symbol)
+    {
+        symbol->setId(variable->getUniqueId());
+        declaration->appendDeclarator(symbol);
+    }
+
+    return declaration;
+}
+
+TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
+                                                              const TSourceLoc &identifierLocation,
+                                                              const TString &identifier,
+                                                              const TSourceLoc &initLocation,
+                                                              TIntermTyped *initializer)
+{
+    mDeferredNonEmptyDeclarationErrorCheck = false;
+
+    declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
+                                   identifierLocation);
+
+    nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+
+    TIntermDeclaration *declaration = new TIntermDeclaration();
+    declaration->setLine(identifierLocation);
+
+    TIntermBinary *initNode = nullptr;
+    if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
+    {
+        if (initNode)
+        {
+            declaration->appendDeclarator(initNode);
+        }
+    }
+    return declaration;
+}
+
+TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
+    TPublicType &publicType,
+    const TSourceLoc &identifierLocation,
+    const TString &identifier,
+    const TSourceLoc &indexLocation,
+    TIntermTyped *indexExpression,
+    const TSourceLoc &initLocation,
+    TIntermTyped *initializer)
+{
+    mDeferredNonEmptyDeclarationErrorCheck = false;
+
+    declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
+                                   identifierLocation);
+
+    nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+
+    checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
+
+    TPublicType arrayType(publicType);
+
+    unsigned int size = 0u;
+    // If indexExpression is nullptr, then the array will eventually get its size implicitly from
+    // the initializer.
+    if (indexExpression != nullptr)
+    {
+        size = checkIsValidArraySize(identifierLocation, indexExpression);
+    }
+    // Make the type an array even if size check failed.
+    // This ensures useless error messages regarding the variable's non-arrayness won't follow.
+    arrayType.setArraySize(size);
+
+    TIntermDeclaration *declaration = new TIntermDeclaration();
+    declaration->setLine(identifierLocation);
+
+    // initNode will correspond to the whole of "type b[n] = initializer".
+    TIntermBinary *initNode = nullptr;
+    if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
+    {
+        if (initNode)
+        {
+            declaration->appendDeclarator(initNode);
+        }
+    }
+
+    return declaration;
+}
+
+TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
+    const TTypeQualifierBuilder &typeQualifierBuilder,
+    const TSourceLoc &identifierLoc,
+    const TString *identifier,
+    const TSymbol *symbol)
+{
+    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
+
+    if (!typeQualifier.invariant)
+    {
+        error(identifierLoc, "Expected invariant", identifier->c_str());
+        return nullptr;
+    }
+    if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
+    {
+        return nullptr;
+    }
+    if (!symbol)
+    {
+        error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
+        return nullptr;
+    }
+    if (!IsQualifierUnspecified(typeQualifier.qualifier))
+    {
+        error(identifierLoc, "invariant declaration specifies qualifier",
+              getQualifierString(typeQualifier.qualifier));
+    }
+    if (typeQualifier.precision != EbpUndefined)
+    {
+        error(identifierLoc, "invariant declaration specifies precision",
+              getPrecisionString(typeQualifier.precision));
+    }
+    if (!typeQualifier.layoutQualifier.isEmpty())
+    {
+        error(identifierLoc, "invariant declaration specifies layout", "'layout'");
+    }
+
+    const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
+    ASSERT(variable);
+    const TType &type = variable->getType();
+
+    checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
+                                    typeQualifier.line);
+    checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
+
+    symbolTable.addInvariantVarying(std::string(identifier->c_str()));
+
+    TIntermSymbol *intermSymbol =
+        intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
+
+    return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
+}
+
+void TParseContext::parseDeclarator(TPublicType &publicType,
+                                    const TSourceLoc &identifierLocation,
+                                    const TString &identifier,
+                                    TIntermDeclaration *declarationOut)
+{
+    // If the declaration starting this declarator list was empty (example: int,), some checks were
+    // not performed.
+    if (mDeferredNonEmptyDeclarationErrorCheck)
+    {
+        nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+        mDeferredNonEmptyDeclarationErrorCheck = false;
+    }
+
+    checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
+
+    checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
+
+    TVariable *variable = nullptr;
+    TType type(publicType);
+    declareVariable(identifierLocation, identifier, type, &variable);
+
+    TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierLocation);
+    if (variable && symbol)
+    {
+        symbol->setId(variable->getUniqueId());
+        declarationOut->appendDeclarator(symbol);
+    }
+}
+
+void TParseContext::parseArrayDeclarator(TPublicType &publicType,
+                                         const TSourceLoc &identifierLocation,
+                                         const TString &identifier,
+                                         const TSourceLoc &arrayLocation,
+                                         TIntermTyped *indexExpression,
+                                         TIntermDeclaration *declarationOut)
+{
+    // If the declaration starting this declarator list was empty (example: int,), some checks were
+    // not performed.
+    if (mDeferredNonEmptyDeclarationErrorCheck)
+    {
+        nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+        mDeferredNonEmptyDeclarationErrorCheck = false;
+    }
+
+    checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
+
+    checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
+
+    if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
+    {
+        TType arrayType   = TType(publicType);
+        unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
+        arrayType.setArraySize(size);
+
+        TVariable *variable = nullptr;
+        declareVariable(identifierLocation, identifier, arrayType, &variable);
+
+        TIntermSymbol *symbol =
+            intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
+        if (variable && symbol)
+            symbol->setId(variable->getUniqueId());
+
+        declarationOut->appendDeclarator(symbol);
+    }
+}
+
+void TParseContext::parseInitDeclarator(const TPublicType &publicType,
+                                        const TSourceLoc &identifierLocation,
+                                        const TString &identifier,
+                                        const TSourceLoc &initLocation,
+                                        TIntermTyped *initializer,
+                                        TIntermDeclaration *declarationOut)
+{
+    // If the declaration starting this declarator list was empty (example: int,), some checks were
+    // not performed.
+    if (mDeferredNonEmptyDeclarationErrorCheck)
+    {
+        nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+        mDeferredNonEmptyDeclarationErrorCheck = false;
+    }
+
+    checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
+
+    TIntermBinary *initNode = nullptr;
+    if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
+    {
+        //
+        // build the intermediate representation
+        //
+        if (initNode)
+        {
+            declarationOut->appendDeclarator(initNode);
+        }
+    }
+}
+
+void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
+                                             const TSourceLoc &identifierLocation,
+                                             const TString &identifier,
+                                             const TSourceLoc &indexLocation,
+                                             TIntermTyped *indexExpression,
+                                             const TSourceLoc &initLocation,
+                                             TIntermTyped *initializer,
+                                             TIntermDeclaration *declarationOut)
+{
+    // If the declaration starting this declarator list was empty (example: int,), some checks were
+    // not performed.
+    if (mDeferredNonEmptyDeclarationErrorCheck)
+    {
+        nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+        mDeferredNonEmptyDeclarationErrorCheck = false;
+    }
+
+    checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
+
+    checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
+
+    TPublicType arrayType(publicType);
+
+    unsigned int size = 0u;
+    // If indexExpression is nullptr, then the array will eventually get its size implicitly from
+    // the initializer.
+    if (indexExpression != nullptr)
+    {
+        size = checkIsValidArraySize(identifierLocation, indexExpression);
+    }
+    // Make the type an array even if size check failed.
+    // This ensures useless error messages regarding the variable's non-arrayness won't follow.
+    arrayType.setArraySize(size);
+
+    // initNode will correspond to the whole of "b[n] = initializer".
+    TIntermBinary *initNode = nullptr;
+    if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
+    {
+        if (initNode)
+        {
+            declarationOut->appendDeclarator(initNode);
+        }
+    }
+}
+
+void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
+{
+    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
+    const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
+
+    checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
+                                    typeQualifier.line);
+
+    // It should never be the case, but some strange parser errors can send us here.
+    if (layoutQualifier.isEmpty())
+    {
+        error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
+        return;
+    }
+
+    if (!layoutQualifier.isCombinationValid())
+    {
+        error(typeQualifier.line, "invalid layout qualifier combination", "layout");
+        return;
+    }
+
+    checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
+
+    checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
+
+    checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
+
+    checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
+
+    if (typeQualifier.qualifier == EvqComputeIn)
+    {
+        if (mComputeShaderLocalSizeDeclared &&
+            !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
+        {
+            error(typeQualifier.line, "Work group size does not match the previous declaration",
+                  "layout");
+            return;
+        }
+
+        if (mShaderVersion < 310)
+        {
+            error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
+            return;
+        }
+
+        if (!layoutQualifier.localSize.isAnyValueSet())
+        {
+            error(typeQualifier.line, "No local work group size specified", "layout");
+            return;
+        }
+
+        const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
+            symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
+
+        const TConstantUnion *maxComputeWorkGroupSizeData =
+            maxComputeWorkGroupSize->getConstPointer();
+
+        for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
+        {
+            if (layoutQualifier.localSize[i] != -1)
+            {
+                mComputeShaderLocalSize[i]             = layoutQualifier.localSize[i];
+                const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
+                if (mComputeShaderLocalSize[i] < 1 ||
+                    mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
+                {
+                    std::stringstream reasonStream;
+                    reasonStream << "invalid value: Value must be at least 1 and no greater than "
+                                 << maxComputeWorkGroupSizeValue;
+                    const std::string &reason = reasonStream.str();
+
+                    error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
+                    return;
+                }
+            }
+        }
+
+        mComputeShaderLocalSizeDeclared = true;
+    }
+    else if (mMultiviewAvailable &&
+             (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
+             typeQualifier.qualifier == EvqVertexIn)
+    {
+        // This error is only specified in WebGL, but tightens unspecified behavior in the native
+        // specification.
+        if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
+        {
+            error(typeQualifier.line, "Number of views does not match the previous declaration",
+                  "layout");
+            return;
+        }
+
+        if (layoutQualifier.numViews == -1)
+        {
+            error(typeQualifier.line, "No num_views specified", "layout");
+            return;
+        }
+
+        if (layoutQualifier.numViews > mMaxNumViews)
+        {
+            error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
+                  "layout");
+            return;
+        }
+
+        mNumViews = layoutQualifier.numViews;
+    }
+    else
+    {
+        if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
+        {
+            return;
+        }
+
+        if (typeQualifier.qualifier != EvqUniform)
+        {
+            error(typeQualifier.line, "invalid qualifier: global layout must be uniform",
+                  getQualifierString(typeQualifier.qualifier));
+            return;
+        }
+
+        if (mShaderVersion < 300)
+        {
+            error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
+                  "layout");
+            return;
+        }
+
+        checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
+
+        if (layoutQualifier.matrixPacking != EmpUnspecified)
+        {
+            mDefaultMatrixPacking = layoutQualifier.matrixPacking;
+        }
+
+        if (layoutQualifier.blockStorage != EbsUnspecified)
+        {
+            mDefaultBlockStorage = layoutQualifier.blockStorage;
+        }
+    }
+}
+
+TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
+    const TFunction &function,
+    const TSourceLoc &location,
+    bool insertParametersToSymbolTable)
+{
+    TIntermFunctionPrototype *prototype =
+        new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
+    // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
+    // point to the data that already exists in the symbol table.
+    prototype->getFunctionSymbolInfo()->setFromFunction(function);
+    prototype->setLine(location);
+
+    for (size_t i = 0; i < function.getParamCount(); i++)
+    {
+        const TConstParameter &param = function.getParam(i);
+
+        // If the parameter has no name, it's not an error, just don't add it to symbol table (could
+        // be used for unused args).
+        if (param.name != nullptr)
+        {
+            TVariable *variable = new TVariable(param.name, *param.type);
+
+            // Insert the parameter in the symbol table.
+            if (insertParametersToSymbolTable && !symbolTable.declare(variable))
+            {
+                error(location, "redefinition", variable->getName().c_str());
+                prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
+                continue;
+            }
+            TIntermSymbol *symbol = intermediate.addSymbol(
+                variable->getUniqueId(), variable->getName(), variable->getType(), location);
+            prototype->appendParameter(symbol);
+        }
+        else
+        {
+            prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
+        }
+    }
+    return prototype;
+}
+
+TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
+    const TFunction &parsedFunction,
+    const TSourceLoc &location)
+{
+    // Note: function found from the symbol table could be the same as parsedFunction if this is the
+    // first declaration. Either way the instance in the symbol table is used to track whether the
+    // function is declared multiple times.
+    TFunction *function = static_cast<TFunction *>(
+        symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
+    if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
+    {
+        // ESSL 1.00.17 section 4.2.7.
+        // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
+        error(location, "duplicate function prototype declarations are not allowed", "function");
+    }
+    function->setHasPrototypeDeclaration();
+
+    TIntermFunctionPrototype *prototype =
+        createPrototypeNodeFromFunction(*function, location, false);
+
+    symbolTable.pop();
+
+    if (!symbolTable.atGlobalLevel())
+    {
+        // ESSL 3.00.4 section 4.2.4.
+        error(location, "local function prototype declarations are not allowed", "function");
+    }
+
+    return prototype;
+}
+
+TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
+    TIntermFunctionPrototype *functionPrototype,
+    TIntermBlock *functionBody,
+    const TSourceLoc &location)
+{
+    // Check that non-void functions have at least one return statement.
+    if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
+    {
+        error(location, "function does not return a value:",
+              functionPrototype->getFunctionSymbolInfo()->getName().c_str());
+    }
+
+    if (functionBody == nullptr)
+    {
+        functionBody = new TIntermBlock();
+        functionBody->setLine(location);
+    }
+    TIntermFunctionDefinition *functionNode =
+        new TIntermFunctionDefinition(functionPrototype, functionBody);
+    functionNode->setLine(location);
+
+    symbolTable.pop();
+    return functionNode;
+}
+
+void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
+                                                  TFunction **function,
+                                                  TIntermFunctionPrototype **prototypeOut)
+{
+    ASSERT(function);
+    ASSERT(*function);
+    const TSymbol *builtIn =
+        symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
+
+    if (builtIn)
+    {
+        error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
+    }
+    else
+    {
+        TFunction *prevDec = static_cast<TFunction *>(
+            symbolTable.find((*function)->getMangledName(), getShaderVersion()));
+
+        // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
+        // would have just been put in the symbol table. Otherwise, we're looking up an earlier
+        // occurance.
+        if (*function != prevDec)
+        {
+            // Swap the parameters of the previous declaration to the parameters of the function
+            // definition (parameter names may differ).
+            prevDec->swapParameters(**function);
+
+            // The function definition will share the same symbol as any previous declaration.
+            *function = prevDec;
+        }
+
+        if ((*function)->isDefined())
+        {
+            error(location, "function already has a body", (*function)->getName().c_str());
+        }
+
+        (*function)->setDefined();
+    }
+
+    // Remember the return type for later checking for return statements.
+    mCurrentFunctionType  = &((*function)->getReturnType());
+    mFunctionReturnsValue = false;
+
+    *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
+    setLoopNestingLevel(0);
+}
+
+TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
+{
+    //
+    // We don't know at this point whether this is a function definition or a prototype.
+    // The definition production code will check for redefinitions.
+    // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
+    //
+    // Return types and parameter qualifiers must match in all redeclarations, so those are checked
+    // here.
+    //
+    TFunction *prevDec =
+        static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
+
+    if (getShaderVersion() >= 300 &&
+        symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
+                                                        getShaderVersion()))
+    {
+        // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
+        // Therefore overloading or redefining builtin functions is an error.
+        error(location, "Name of a built-in function cannot be redeclared as function",
+              function->getName().c_str());
+    }
+    else if (prevDec)
+    {
+        if (prevDec->getReturnType() != function->getReturnType())
+        {
+            error(location, "function must have the same return type in all of its declarations",
+                  function->getReturnType().getBasicString());
+        }
+        for (size_t i = 0; i < prevDec->getParamCount(); ++i)
+        {
+            if (prevDec->getParam(i).type->getQualifier() !=
+                function->getParam(i).type->getQualifier())
+            {
+                error(location,
+                      "function must have the same parameter qualifiers in all of its declarations",
+                      function->getParam(i).type->getQualifierString());
+            }
+        }
+    }
+
+    //
+    // Check for previously declared variables using the same name.
+    //
+    TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
+    if (prevSym)
+    {
+        if (!prevSym->isFunction())
+        {
+            error(location, "redefinition of a function", function->getName().c_str());
+        }
+    }
+    else
+    {
+        // Insert the unmangled name to detect potential future redefinition as a variable.
+        symbolTable.getOuterLevel()->insertUnmangled(function);
+    }
+
+    // We're at the inner scope level of the function's arguments and body statement.
+    // Add the function prototype to the surrounding scope instead.
+    symbolTable.getOuterLevel()->insert(function);
+
+    // Raise error message if main function takes any parameters or return anything other than void
+    if (function->getName() == "main")
+    {
+        if (function->getParamCount() > 0)
+        {
+            error(location, "function cannot take any parameter(s)", "main");
+        }
+        if (function->getReturnType().getBasicType() != EbtVoid)
+        {
+            error(location, "main function cannot return a value",
+                  function->getReturnType().getBasicString());
+        }
+    }
+
+    //
+    // If this is a redeclaration, it could also be a definition, in which case, we want to use the
+    // variable names from this one, and not the one that's
+    // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
+    //
+    return function;
+}
+
+TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
+                                              const TString *name,
+                                              const TSourceLoc &location)
+{
+    if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
+    {
+        error(location, "no qualifiers allowed for function return",
+              getQualifierString(type.qualifier));
+    }
+    if (!type.layoutQualifier.isEmpty())
+    {
+        error(location, "no qualifiers allowed for function return", "layout");
+    }
+    // make sure an opaque type is not involved as well...
+    std::string reason(getBasicString(type.getBasicType()));
+    reason += "s can't be function return values";
+    checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
+    if (mShaderVersion < 300)
+    {
+        // Array return values are forbidden, but there's also no valid syntax for declaring array
+        // return values in ESSL 1.00.
+        ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
+
+        if (type.isStructureContainingArrays())
+        {
+            // ESSL 1.00.17 section 6.1 Function Definitions
+            error(location, "structures containing arrays can't be function return values",
+                  TType(type).getCompleteString().c_str());
+        }
+    }
+
+    // Add the function as a prototype after parsing it (we do not support recursion)
+    return new TFunction(name, new TType(type));
+}
+
+TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
+{
+    if (publicType.isStructSpecifier())
+    {
+        error(publicType.getLine(), "constructor can't be a structure definition",
+              getBasicString(publicType.getBasicType()));
+    }
+
+    TType *type = new TType(publicType);
+    if (!type->canBeConstructed())
+    {
+        error(publicType.getLine(), "cannot construct this type",
+              getBasicString(publicType.getBasicType()));
+        type->setBasicType(EbtFloat);
+    }
+
+    return new TFunction(nullptr, type, EOpConstruct);
+}
+
+// This function is used to test for the correctness of the parameters passed to various constructor
+// functions and also convert them to the right datatype if it is allowed and required.
+//
+// Returns a node to add to the tree regardless of if an error was generated or not.
+//
+TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
+                                            TType type,
+                                            const TSourceLoc &line)
+{
+    if (type.isUnsizedArray())
+    {
+        if (arguments->empty())
+        {
+            error(line, "implicitly sized array constructor must have at least one argument", "[]");
+            type.setArraySize(1u);
+            return TIntermTyped::CreateZero(type);
+        }
+        type.setArraySize(static_cast<unsigned int>(arguments->size()));
+    }
+
+    if (!checkConstructorArguments(line, arguments, type))
+    {
+        return TIntermTyped::CreateZero(type);
+    }
+
+    TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments);
+    constructorNode->setLine(line);
+
+    TIntermTyped *constConstructor =
+        intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
+    if (constConstructor)
+    {
+        return constConstructor;
+    }
+
+    return constructorNode;
+}
+
+//
+// Interface/uniform blocks
+//
+TIntermDeclaration *TParseContext::addInterfaceBlock(
+    const TTypeQualifierBuilder &typeQualifierBuilder,
+    const TSourceLoc &nameLine,
+    const TString &blockName,
+    TFieldList *fieldList,
+    const TString *instanceName,
+    const TSourceLoc &instanceLine,
+    TIntermTyped *arrayIndex,
+    const TSourceLoc &arrayIndexLine)
+{
+    checkIsNotReserved(nameLine, blockName);
+
+    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
+
+    if (typeQualifier.qualifier != EvqUniform)
+    {
+        error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform",
+              getQualifierString(typeQualifier.qualifier));
+    }
+
+    if (typeQualifier.invariant)
+    {
+        error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
+    }
+
+    checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
+
+    // TODO(oetuaho): Remove this and support binding for blocks.
+    checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
+
+    checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
+
+    TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
+    checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
+
+    if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
+    {
+        blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
+    }
+
+    if (blockLayoutQualifier.blockStorage == EbsUnspecified)
+    {
+        blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
+    }
+
+    checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
+
+    checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
+
+    TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
+    if (!symbolTable.declare(blockNameSymbol))
+    {
+        error(nameLine, "redefinition of an interface block name", blockName.c_str());
+    }
+
+    // check for sampler types and apply layout qualifiers
+    for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
+    {
+        TField *field    = (*fieldList)[memberIndex];
+        TType *fieldType = field->type();
+        if (IsOpaqueType(fieldType->getBasicType()))
+        {
+            std::string reason("unsupported type - ");
+            reason += fieldType->getBasicString();
+            reason += " types are not allowed in interface blocks";
+            error(field->line(), reason.c_str(), fieldType->getBasicString());
+        }
+
+        const TQualifier qualifier = fieldType->getQualifier();
+        switch (qualifier)
+        {
+            case EvqGlobal:
+            case EvqUniform:
+                break;
+            default:
+                error(field->line(), "invalid qualifier on interface block member",
+                      getQualifierString(qualifier));
+                break;
+        }
+
+        if (fieldType->isInvariant())
+        {
+            error(field->line(), "invalid qualifier on interface block member", "invariant");
+        }
+
+        // check layout qualifiers
+        TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
+        checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
+
+        if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
+        {
+            error(field->line(), "invalid layout qualifier: cannot be used here",
+                  getBlockStorageString(fieldLayoutQualifier.blockStorage));
+        }
+
+        if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
+        {
+            fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
+        }
+        else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
+        {
+            warning(field->line(),
+                    "extraneous layout qualifier: only has an effect on matrix types",
+                    getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
+        }
+
+        fieldType->setLayoutQualifier(fieldLayoutQualifier);
+    }
+
+    // add array index
+    unsigned int arraySize = 0;
+    if (arrayIndex != nullptr)
+    {
+        arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
+    }
+
+    TInterfaceBlock *interfaceBlock =
+        new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
+    TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
+                             arraySize);
+
+    TString symbolName = "";
+    int symbolId       = 0;
+
+    if (!instanceName)
+    {
+        // define symbols for the members of the interface block
+        for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
+        {
+            TField *field    = (*fieldList)[memberIndex];
+            TType *fieldType = field->type();
+
+            // set parent pointer of the field variable
+            fieldType->setInterfaceBlock(interfaceBlock);
+
+            TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
+            fieldVariable->setQualifier(typeQualifier.qualifier);
+
+            if (!symbolTable.declare(fieldVariable))
+            {
+                error(field->line(), "redefinition of an interface block member name",
+                      field->name().c_str());
+            }
+        }
+    }
+    else
+    {
+        checkIsNotReserved(instanceLine, *instanceName);
+
+        // add a symbol for this interface block
+        TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
+        instanceTypeDef->setQualifier(typeQualifier.qualifier);
+
+        if (!symbolTable.declare(instanceTypeDef))
+        {
+            error(instanceLine, "redefinition of an interface block instance name",
+                  instanceName->c_str());
+        }
+
+        symbolId   = instanceTypeDef->getUniqueId();
+        symbolName = instanceTypeDef->getName();
+    }
+
+    TIntermSymbol *blockSymbol =
+        intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
+    TIntermDeclaration *declaration = new TIntermDeclaration();
+    declaration->appendDeclarator(blockSymbol);
+    declaration->setLine(nameLine);
+
+    exitStructDeclaration();
+    return declaration;
+}
+
+void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
+{
+    ++mStructNestingLevel;
+
+    // Embedded structure definitions are not supported per GLSL ES spec.
+    // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
+    if (mStructNestingLevel > 1)
+    {
+        error(line, "Embedded struct definitions are not allowed", "struct");
+    }
+}
+
+void TParseContext::exitStructDeclaration()
+{
+    --mStructNestingLevel;
+}
+
+void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
+{
+    if (!sh::IsWebGLBasedSpec(mShaderSpec))
+    {
+        return;
+    }
+
+    if (field.type()->getBasicType() != EbtStruct)
+    {
+        return;
+    }
+
+    // We're already inside a structure definition at this point, so add
+    // one to the field's struct nesting.
+    if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
+    {
+        std::stringstream reasonStream;
+        reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
+                     << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
+        std::string reason = reasonStream.str();
+        error(line, reason.c_str(), field.name().c_str());
+        return;
+    }
+}
+
+//
+// Parse an array index expression
+//
+TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
+                                                const TSourceLoc &location,
+                                                TIntermTyped *indexExpression)
+{
+    if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
+    {
+        if (baseExpression->getAsSymbolNode())
+        {
+            error(location, " left of '[' is not of type array, matrix, or vector ",
+                  baseExpression->getAsSymbolNode()->getSymbol().c_str());
+        }
+        else
+        {
+            error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
+        }
+
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setFConst(0.0f);
+        return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
+                                             location);
+    }
+
+    TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
+
+    // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
+    // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
+    // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
+    // index is a constant expression.
+    if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
+    {
+        if (baseExpression->isInterfaceBlock())
+        {
+            error(location,
+                  "array indexes for interface blocks arrays must be constant integral expressions",
+                  "[");
+        }
+        else if (baseExpression->getQualifier() == EvqFragmentOut)
+        {
+            error(location,
+                  "array indexes for fragment outputs must be constant integral expressions", "[");
+        }
+        else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
+        {
+            error(location, "array index for gl_FragData must be constant zero", "[");
+        }
+    }
+
+    if (indexConstantUnion)
+    {
+        // If an out-of-range index is not qualified as constant, the behavior in the spec is
+        // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
+        // constant fold expressions that are not constant expressions). The most compatible way to
+        // handle this case is to report a warning instead of an error and force the index to be in
+        // the correct range.
+        bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
+        int index                   = indexConstantUnion->getIConst(0);
+
+        int safeIndex = -1;
+
+        if (baseExpression->isArray())
+        {
+            if (baseExpression->getQualifier() == EvqFragData && index > 0)
+            {
+                if (mShaderSpec == SH_WEBGL2_SPEC)
+                {
+                    // Error has been already generated if index is not const.
+                    if (indexExpression->getQualifier() == EvqConst)
+                    {
+                        error(location, "array index for gl_FragData must be constant zero", "[");
+                    }
+                    safeIndex = 0;
+                }
+                else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
+                {
+                    outOfRangeError(outOfRangeIndexIsError, location,
+                                    "array index for gl_FragData must be zero when "
+                                    "GL_EXT_draw_buffers is disabled",
+                                    "[");
+                    safeIndex = 0;
+                }
+            }
+            // Only do generic out-of-range check if similar error hasn't already been reported.
+            if (safeIndex < 0)
+            {
+                safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
+                                                 baseExpression->getArraySize(),
+                                                 "array index out of range");
+            }
+        }
+        else if (baseExpression->isMatrix())
+        {
+            safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
+                                             baseExpression->getType().getCols(),
+                                             "matrix field selection out of range");
+        }
+        else if (baseExpression->isVector())
+        {
+            safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
+                                             baseExpression->getType().getNominalSize(),
+                                             "vector field selection out of range");
+        }
+
+        ASSERT(safeIndex >= 0);
+        // Data of constant unions can't be changed, because it may be shared with other
+        // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
+        // sanitized object.
+        if (safeIndex != index)
+        {
+            TConstantUnion *safeConstantUnion = new TConstantUnion();
+            safeConstantUnion->setIConst(safeIndex);
+            indexConstantUnion->replaceConstantUnion(safeConstantUnion);
+        }
+
+        return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
+                                     mDiagnostics);
+    }
+    else
+    {
+        return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
+                                     mDiagnostics);
+    }
+}
+
+int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
+                                        const TSourceLoc &location,
+                                        int index,
+                                        int arraySize,
+                                        const char *reason)
+{
+    if (index >= arraySize || index < 0)
+    {
+        std::stringstream reasonStream;
+        reasonStream << reason << " '" << index << "'";
+        std::string token = reasonStream.str();
+        outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
+        if (index < 0)
+        {
+            return 0;
+        }
+        else
+        {
+            return arraySize - 1;
+        }
+    }
+    return index;
+}
+
+TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
+                                                         const TSourceLoc &dotLocation,
+                                                         const TString &fieldString,
+                                                         const TSourceLoc &fieldLocation)
+{
+    if (baseExpression->isArray())
+    {
+        error(fieldLocation, "cannot apply dot operator to an array", ".");
+        return baseExpression;
+    }
+
+    if (baseExpression->isVector())
+    {
+        TVectorFields fields;
+        if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
+                               fieldLocation))
+        {
+            fields.num        = 1;
+            fields.offsets[0] = 0;
+        }
+
+        return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
+    }
+    else if (baseExpression->getBasicType() == EbtStruct)
+    {
+        const TFieldList &fields = baseExpression->getType().getStruct()->fields();
+        if (fields.empty())
+        {
+            error(dotLocation, "structure has no fields", "Internal Error");
+            return baseExpression;
+        }
+        else
+        {
+            bool fieldFound = false;
+            unsigned int i;
+            for (i = 0; i < fields.size(); ++i)
+            {
+                if (fields[i]->name() == fieldString)
+                {
+                    fieldFound = true;
+                    break;
+                }
+            }
+            if (fieldFound)
+            {
+                TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
+                index->setLine(fieldLocation);
+                return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
+                                             dotLocation, mDiagnostics);
+            }
+            else
+            {
+                error(dotLocation, " no such field in structure", fieldString.c_str());
+                return baseExpression;
+            }
+        }
+    }
+    else if (baseExpression->isInterfaceBlock())
+    {
+        const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
+        if (fields.empty())
+        {
+            error(dotLocation, "interface block has no fields", "Internal Error");
+            return baseExpression;
+        }
+        else
+        {
+            bool fieldFound = false;
+            unsigned int i;
+            for (i = 0; i < fields.size(); ++i)
+            {
+                if (fields[i]->name() == fieldString)
+                {
+                    fieldFound = true;
+                    break;
+                }
+            }
+            if (fieldFound)
+            {
+                TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
+                index->setLine(fieldLocation);
+                return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
+                                             dotLocation, mDiagnostics);
+            }
+            else
+            {
+                error(dotLocation, " no such field in interface block", fieldString.c_str());
+                return baseExpression;
+            }
+        }
+    }
+    else
+    {
+        if (mShaderVersion < 300)
+        {
+            error(dotLocation, " field selection requires structure or vector on left hand side",
+                  fieldString.c_str());
+        }
+        else
+        {
+            error(dotLocation,
+                  " field selection requires structure, vector, or interface block on left hand "
+                  "side",
+                  fieldString.c_str());
+        }
+        return baseExpression;
+    }
+}
+
+TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
+                                                     const TSourceLoc &qualifierTypeLine)
+{
+    TLayoutQualifier qualifier = TLayoutQualifier::create();
+
+    if (qualifierType == "shared")
+    {
+        if (sh::IsWebGLBasedSpec(mShaderSpec))
+        {
+            error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
+        }
+        qualifier.blockStorage = EbsShared;
+    }
+    else if (qualifierType == "packed")
+    {
+        if (sh::IsWebGLBasedSpec(mShaderSpec))
+        {
+            error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
+        }
+        qualifier.blockStorage = EbsPacked;
+    }
+    else if (qualifierType == "std140")
+    {
+        qualifier.blockStorage = EbsStd140;
+    }
+    else if (qualifierType == "row_major")
+    {
+        qualifier.matrixPacking = EmpRowMajor;
+    }
+    else if (qualifierType == "column_major")
+    {
+        qualifier.matrixPacking = EmpColumnMajor;
+    }
+    else if (qualifierType == "location")
+    {
+        error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
+              qualifierType.c_str());
+    }
+    else if (qualifierType == "yuv" && isExtensionEnabled("GL_EXT_YUV_target") &&
+             mShaderType == GL_FRAGMENT_SHADER)
+    {
+        qualifier.yuv = true;
+    }
+    else if (qualifierType == "rgba32f")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA32F;
+    }
+    else if (qualifierType == "rgba16f")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA16F;
+    }
+    else if (qualifierType == "r32f")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifR32F;
+    }
+    else if (qualifierType == "rgba8")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA8;
+    }
+    else if (qualifierType == "rgba8_snorm")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA8_SNORM;
+    }
+    else if (qualifierType == "rgba32i")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA32I;
+    }
+    else if (qualifierType == "rgba16i")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA16I;
+    }
+    else if (qualifierType == "rgba8i")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA8I;
+    }
+    else if (qualifierType == "r32i")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifR32I;
+    }
+    else if (qualifierType == "rgba32ui")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA32UI;
+    }
+    else if (qualifierType == "rgba16ui")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA16UI;
+    }
+    else if (qualifierType == "rgba8ui")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifRGBA8UI;
+    }
+    else if (qualifierType == "r32ui")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.imageInternalFormat = EiifR32UI;
+    }
+
+    else
+    {
+        error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
+    }
+
+    return qualifier;
+}
+
+void TParseContext::parseLocalSize(const TString &qualifierType,
+                                   const TSourceLoc &qualifierTypeLine,
+                                   int intValue,
+                                   const TSourceLoc &intValueLine,
+                                   const std::string &intValueString,
+                                   size_t index,
+                                   sh::WorkGroupSize *localSize)
+{
+    checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+    if (intValue < 1)
+    {
+        std::stringstream reasonStream;
+        reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
+        std::string reason = reasonStream.str();
+        error(intValueLine, reason.c_str(), intValueString.c_str());
+    }
+    (*localSize)[index] = intValue;
+}
+
+void TParseContext::parseNumViews(int intValue,
+                                  const TSourceLoc &intValueLine,
+                                  const std::string &intValueString,
+                                  int *numViews)
+{
+    // This error is only specified in WebGL, but tightens unspecified behavior in the native
+    // specification.
+    if (intValue < 1)
+    {
+        error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
+    }
+    *numViews = intValue;
+}
+
+TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
+                                                     const TSourceLoc &qualifierTypeLine,
+                                                     int intValue,
+                                                     const TSourceLoc &intValueLine)
+{
+    TLayoutQualifier qualifier = TLayoutQualifier::create();
+
+    std::string intValueString = Str(intValue);
+
+    if (qualifierType == "location")
+    {
+        // must check that location is non-negative
+        if (intValue < 0)
+        {
+            error(intValueLine, "out of range: location must be non-negative",
+                  intValueString.c_str());
+        }
+        else
+        {
+            qualifier.location           = intValue;
+            qualifier.locationsSpecified = 1;
+        }
+    }
+    else if (qualifierType == "binding")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        if (intValue < 0)
+        {
+            error(intValueLine, "out of range: binding must be non-negative",
+                  intValueString.c_str());
+        }
+        else
+        {
+            qualifier.binding = intValue;
+        }
+    }
+    else if (qualifierType == "local_size_x")
+    {
+        parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
+                       &qualifier.localSize);
+    }
+    else if (qualifierType == "local_size_y")
+    {
+        parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
+                       &qualifier.localSize);
+    }
+    else if (qualifierType == "local_size_z")
+    {
+        parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
+                       &qualifier.localSize);
+    }
+    else if (qualifierType == "num_views" && mMultiviewAvailable &&
+             (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
+             mShaderType == GL_VERTEX_SHADER)
+    {
+        parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
+    }
+    else
+    {
+        error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
+    }
+
+    return qualifier;
+}
+
+TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
+{
+    return new TTypeQualifierBuilder(
+        new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
+        mShaderVersion);
+}
+
+TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
+                                                     TLayoutQualifier rightQualifier,
+                                                     const TSourceLoc &rightQualifierLocation)
+{
+    return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
+                                    mDiagnostics);
+}
+
+TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
+                                                   const TFieldList *newlyAddedFields,
+                                                   const TSourceLoc &location)
+{
+    for (TField *field : *newlyAddedFields)
+    {
+        for (TField *oldField : *processedFields)
+        {
+            if (oldField->name() == field->name())
+            {
+                error(location, "duplicate field name in structure", field->name().c_str());
+            }
+        }
+        processedFields->push_back(field);
+    }
+    return processedFields;
+}
+
+TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
+    const TTypeQualifierBuilder &typeQualifierBuilder,
+    TPublicType *typeSpecifier,
+    TFieldList *fieldList)
+{
+    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
+
+    typeSpecifier->qualifier       = typeQualifier.qualifier;
+    typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
+    typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
+    typeSpecifier->invariant       = typeQualifier.invariant;
+    if (typeQualifier.precision != EbpUndefined)
+    {
+        typeSpecifier->precision = typeQualifier.precision;
+    }
+    return addStructDeclaratorList(*typeSpecifier, fieldList);
+}
+
+TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
+                                                   TFieldList *fieldList)
+{
+    checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
+                            typeSpecifier.getBasicType());
+
+    checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
+
+    checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
+
+    for (unsigned int i = 0; i < fieldList->size(); ++i)
+    {
+        //
+        // Careful not to replace already known aspects of type, like array-ness
+        //
+        TType *type = (*fieldList)[i]->type();
+        type->setBasicType(typeSpecifier.getBasicType());
+        type->setPrimarySize(typeSpecifier.getPrimarySize());
+        type->setSecondarySize(typeSpecifier.getSecondarySize());
+        type->setPrecision(typeSpecifier.precision);
+        type->setQualifier(typeSpecifier.qualifier);
+        type->setLayoutQualifier(typeSpecifier.layoutQualifier);
+        type->setMemoryQualifier(typeSpecifier.memoryQualifier);
+        type->setInvariant(typeSpecifier.invariant);
+
+        // don't allow arrays of arrays
+        if (type->isArray())
+        {
+            checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
+        }
+        if (typeSpecifier.array)
+            type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
+        if (typeSpecifier.getUserDef())
+        {
+            type->setStruct(typeSpecifier.getUserDef()->getStruct());
+        }
+
+        checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
+    }
+
+    return fieldList;
+}
+
+TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
+                                                   const TSourceLoc &nameLine,
+                                                   const TString *structName,
+                                                   TFieldList *fieldList)
+{
+    TStructure *structure = new TStructure(structName, fieldList);
+    TType *structureType  = new TType(structure);
+
+    // Store a bool in the struct if we're at global scope, to allow us to
+    // skip the local struct scoping workaround in HLSL.
+    structure->setAtGlobalScope(symbolTable.atGlobalLevel());
+
+    if (!structName->empty())
+    {
+        checkIsNotReserved(nameLine, *structName);
+        TVariable *userTypeDef = new TVariable(structName, *structureType, true);
+        if (!symbolTable.declare(userTypeDef))
+        {
+            error(nameLine, "redefinition of a struct", structName->c_str());
+        }
+    }
+
+    // ensure we do not specify any storage qualifiers on the struct members
+    for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
+    {
+        const TField &field        = *(*fieldList)[typeListIndex];
+        const TQualifier qualifier = field.type()->getQualifier();
+        switch (qualifier)
+        {
+            case EvqGlobal:
+            case EvqTemporary:
+                break;
+            default:
+                error(field.line(), "invalid qualifier on struct member",
+                      getQualifierString(qualifier));
+                break;
+        }
+        if (field.type()->isInvariant())
+        {
+            error(field.line(), "invalid qualifier on struct member", "invariant");
+        }
+        if (IsImage(field.type()->getBasicType()))
+        {
+            error(field.line(), "disallowed type in struct", field.type()->getBasicString());
+        }
+
+        checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
+
+        checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
+
+        checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
+    }
+
+    TTypeSpecifierNonArray typeSpecifierNonArray;
+    typeSpecifierNonArray.initialize(EbtStruct, structLine);
+    typeSpecifierNonArray.userDef           = structureType;
+    typeSpecifierNonArray.isStructSpecifier = true;
+    exitStructDeclaration();
+
+    return typeSpecifierNonArray;
+}
+
+TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
+                                        TIntermBlock *statementList,
+                                        const TSourceLoc &loc)
+{
+    TBasicType switchType = init->getBasicType();
+    if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
+        init->isVector())
+    {
+        error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
+              "switch");
+        return nullptr;
+    }
+
+    if (statementList)
+    {
+        if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
+        {
+            return nullptr;
+        }
+    }
+
+    TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
+    if (node == nullptr)
+    {
+        error(loc, "erroneous switch statement", "switch");
+        return nullptr;
+    }
+    return node;
+}
+
+TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
+{
+    if (mSwitchNestingLevel == 0)
+    {
+        error(loc, "case labels need to be inside switch statements", "case");
+        return nullptr;
+    }
+    if (condition == nullptr)
+    {
+        error(loc, "case label must have a condition", "case");
+        return nullptr;
+    }
+    if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
+        condition->isMatrix() || condition->isArray() || condition->isVector())
+    {
+        error(condition->getLine(), "case label must be a scalar integer", "case");
+    }
+    TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
+    // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
+    // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
+    // fold in case labels.
+    if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
+    {
+        error(condition->getLine(), "case label must be constant", "case");
+    }
+    TIntermCase *node = intermediate.addCase(condition, loc);
+    if (node == nullptr)
+    {
+        error(loc, "erroneous case statement", "case");
+        return nullptr;
+    }
+    return node;
+}
+
+TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
+{
+    if (mSwitchNestingLevel == 0)
+    {
+        error(loc, "default labels need to be inside switch statements", "default");
+        return nullptr;
+    }
+    TIntermCase *node = intermediate.addCase(nullptr, loc);
+    if (node == nullptr)
+    {
+        error(loc, "erroneous default statement", "default");
+        return nullptr;
+    }
+    return node;
+}
+
+TIntermTyped *TParseContext::createUnaryMath(TOperator op,
+                                             TIntermTyped *child,
+                                             const TSourceLoc &loc)
+{
+    ASSERT(child != nullptr);
+
+    switch (op)
+    {
+        case EOpLogicalNot:
+            if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
+                child->isVector())
+            {
+                unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
+                return nullptr;
+            }
+            break;
+        case EOpBitwiseNot:
+            if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
+                child->isMatrix() || child->isArray())
+            {
+                unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
+                return nullptr;
+            }
+            break;
+        case EOpPostIncrement:
+        case EOpPreIncrement:
+        case EOpPostDecrement:
+        case EOpPreDecrement:
+        case EOpNegative:
+        case EOpPositive:
+            if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
+                child->getBasicType() == EbtBool || child->isArray() ||
+                IsOpaqueType(child->getBasicType()))
+            {
+                unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
+                return nullptr;
+            }
+        // Operators for built-ins are already type checked against their prototype.
+        default:
+            break;
+    }
+
+    TIntermUnary *node = new TIntermUnary(op, child);
+    node->setLine(loc);
+
+    TIntermTyped *foldedNode = node->fold(mDiagnostics);
+    if (foldedNode)
+        return foldedNode;
+
+    return node;
+}
+
+TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
+{
+    TIntermTyped *node = createUnaryMath(op, child, loc);
+    if (node == nullptr)
+    {
+        return child;
+    }
+    return node;
+}
+
+TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
+                                                TIntermTyped *child,
+                                                const TSourceLoc &loc)
+{
+    checkCanBeLValue(loc, GetOperatorString(op), child);
+    return addUnaryMath(op, child, loc);
+}
+
+bool TParseContext::binaryOpCommonCheck(TOperator op,
+                                        TIntermTyped *left,
+                                        TIntermTyped *right,
+                                        const TSourceLoc &loc)
+{
+    // Check opaque types are not allowed to be operands in expressions other than array indexing
+    // and structure member selection.
+    if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
+    {
+        switch (op)
+        {
+            case EOpIndexDirect:
+            case EOpIndexIndirect:
+                break;
+            case EOpIndexDirectStruct:
+                UNREACHABLE();
+
+            default:
+                error(loc, "Invalid operation for variables with an opaque type",
+                      GetOperatorString(op));
+                return false;
+        }
+    }
+
+    if (left->getType().getStruct() || right->getType().getStruct())
+    {
+        switch (op)
+        {
+            case EOpIndexDirectStruct:
+                ASSERT(left->getType().getStruct());
+                break;
+            case EOpEqual:
+            case EOpNotEqual:
+            case EOpAssign:
+            case EOpInitialize:
+                if (left->getType() != right->getType())
+                {
+                    return false;
+                }
+                break;
+            default:
+                error(loc, "Invalid operation for structs", GetOperatorString(op));
+                return false;
+        }
+    }
+
+    if (left->isInterfaceBlock() || right->isInterfaceBlock())
+    {
+        switch (op)
+        {
+            case EOpIndexDirectInterfaceBlock:
+                ASSERT(left->getType().getInterfaceBlock());
+                break;
+            default:
+                error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
+                return false;
+        }
+    }
+
+    if (left->isArray() || right->isArray())
+    {
+        if (mShaderVersion < 300)
+        {
+            error(loc, "Invalid operation for arrays", GetOperatorString(op));
+            return false;
+        }
+
+        if (left->isArray() != right->isArray())
+        {
+            error(loc, "array / non-array mismatch", GetOperatorString(op));
+            return false;
+        }
+
+        switch (op)
+        {
+            case EOpEqual:
+            case EOpNotEqual:
+            case EOpAssign:
+            case EOpInitialize:
+                break;
+            default:
+                error(loc, "Invalid operation for arrays", GetOperatorString(op));
+                return false;
+        }
+        // At this point, size of implicitly sized arrays should be resolved.
+        if (left->getArraySize() != right->getArraySize())
+        {
+            error(loc, "array size mismatch", GetOperatorString(op));
+            return false;
+        }
+    }
+
+    // Check ops which require integer / ivec parameters
+    bool isBitShift = false;
+    switch (op)
+    {
+        case EOpBitShiftLeft:
+        case EOpBitShiftRight:
+        case EOpBitShiftLeftAssign:
+        case EOpBitShiftRightAssign:
+            // Unsigned can be bit-shifted by signed and vice versa, but we need to
+            // check that the basic type is an integer type.
+            isBitShift = true;
+            if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
+            {
+                return false;
+            }
+            break;
+        case EOpBitwiseAnd:
+        case EOpBitwiseXor:
+        case EOpBitwiseOr:
+        case EOpBitwiseAndAssign:
+        case EOpBitwiseXorAssign:
+        case EOpBitwiseOrAssign:
+            // It is enough to check the type of only one operand, since later it
+            // is checked that the operand types match.
+            if (!IsInteger(left->getBasicType()))
+            {
+                return false;
+            }
+            break;
+        default:
+            break;
+    }
+
+    // GLSL ES 1.00 and 3.00 do not support implicit type casting.
+    // So the basic type should usually match.
+    if (!isBitShift && left->getBasicType() != right->getBasicType())
+    {
+        return false;
+    }
+
+    // Check that:
+    // 1. Type sizes match exactly on ops that require that.
+    // 2. Restrictions for structs that contain arrays or samplers are respected.
+    // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
+    switch (op)
+    {
+        case EOpAssign:
+        case EOpInitialize:
+        case EOpEqual:
+        case EOpNotEqual:
+            // ESSL 1.00 sections 5.7, 5.8, 5.9
+            if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
+            {
+                error(loc, "undefined operation for structs containing arrays",
+                      GetOperatorString(op));
+                return false;
+            }
+            // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
+            // we interpret the spec so that this extends to structs containing samplers,
+            // similarly to ESSL 1.00 spec.
+            if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
+                left->getType().isStructureContainingSamplers())
+            {
+                error(loc, "undefined operation for structs containing samplers",
+                      GetOperatorString(op));
+                return false;
+            }
+
+            if ((left->getNominalSize() != right->getNominalSize()) ||
+                (left->getSecondarySize() != right->getSecondarySize()))
+            {
+                error(loc, "dimension mismatch", GetOperatorString(op));
+                return false;
+            }
+            break;
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            if (!left->isScalar() || !right->isScalar())
+            {
+                error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
+                return false;
+            }
+            break;
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpIMod:
+        case EOpBitShiftLeft:
+        case EOpBitShiftRight:
+        case EOpBitwiseAnd:
+        case EOpBitwiseXor:
+        case EOpBitwiseOr:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpDivAssign:
+        case EOpIModAssign:
+        case EOpBitShiftLeftAssign:
+        case EOpBitShiftRightAssign:
+        case EOpBitwiseAndAssign:
+        case EOpBitwiseXorAssign:
+        case EOpBitwiseOrAssign:
+            if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
+            {
+                return false;
+            }
+
+            // Are the sizes compatible?
+            if (left->getNominalSize() != right->getNominalSize() ||
+                left->getSecondarySize() != right->getSecondarySize())
+            {
+                // If the nominal sizes of operands do not match:
+                // One of them must be a scalar.
+                if (!left->isScalar() && !right->isScalar())
+                    return false;
+
+                // In the case of compound assignment other than multiply-assign,
+                // the right side needs to be a scalar. Otherwise a vector/matrix
+                // would be assigned to a scalar. A scalar can't be shifted by a
+                // vector either.
+                if (!right->isScalar() &&
+                    (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
+                    return false;
+            }
+            break;
+        default:
+            break;
+    }
+
+    return true;
+}
+
+bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
+                                                         const TType &left,
+                                                         const TType &right)
+{
+    switch (op)
+    {
+        case EOpMul:
+        case EOpMulAssign:
+            return left.getNominalSize() == right.getNominalSize() &&
+                   left.getSecondarySize() == right.getSecondarySize();
+        case EOpVectorTimesScalar:
+            return true;
+        case EOpVectorTimesScalarAssign:
+            ASSERT(!left.isMatrix() && !right.isMatrix());
+            return left.isVector() && !right.isVector();
+        case EOpVectorTimesMatrix:
+            return left.getNominalSize() == right.getRows();
+        case EOpVectorTimesMatrixAssign:
+            ASSERT(!left.isMatrix() && right.isMatrix());
+            return left.isVector() && left.getNominalSize() == right.getRows() &&
+                   left.getNominalSize() == right.getCols();
+        case EOpMatrixTimesVector:
+            return left.getCols() == right.getNominalSize();
+        case EOpMatrixTimesScalar:
+            return true;
+        case EOpMatrixTimesScalarAssign:
+            ASSERT(left.isMatrix() && !right.isMatrix());
+            return !right.isVector();
+        case EOpMatrixTimesMatrix:
+            return left.getCols() == right.getRows();
+        case EOpMatrixTimesMatrixAssign:
+            ASSERT(left.isMatrix() && right.isMatrix());
+            // We need to check two things:
+            // 1. The matrix multiplication step is valid.
+            // 2. The result will have the same number of columns as the lvalue.
+            return left.getCols() == right.getRows() && left.getCols() == right.getCols();
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
+                                                   TIntermTyped *left,
+                                                   TIntermTyped *right,
+                                                   const TSourceLoc &loc)
+{
+    if (!binaryOpCommonCheck(op, left, right, loc))
+        return nullptr;
+
+    switch (op)
+    {
+        case EOpEqual:
+        case EOpNotEqual:
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            break;
+        case EOpLogicalOr:
+        case EOpLogicalXor:
+        case EOpLogicalAnd:
+            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+                   !right->getType().getStruct());
+            if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
+            {
+                return nullptr;
+            }
+            // Basic types matching should have been already checked.
+            ASSERT(right->getBasicType() == EbtBool);
+            break;
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpMul:
+            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+                   !right->getType().getStruct());
+            if (left->getBasicType() == EbtBool)
+            {
+                return nullptr;
+            }
+            break;
+        case EOpIMod:
+            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+                   !right->getType().getStruct());
+            // Note that this is only for the % operator, not for mod()
+            if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
+            {
+                return nullptr;
+            }
+            break;
+        default:
+            break;
+    }
+
+    if (op == EOpMul)
+    {
+        op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
+        if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
+        {
+            return nullptr;
+        }
+    }
+
+    TIntermBinary *node = new TIntermBinary(op, left, right);
+    node->setLine(loc);
+
+    // See if we can fold constants.
+    TIntermTyped *foldedNode = node->fold(mDiagnostics);
+    if (foldedNode)
+        return foldedNode;
+
+    return node;
+}
+
+TIntermTyped *TParseContext::addBinaryMath(TOperator op,
+                                           TIntermTyped *left,
+                                           TIntermTyped *right,
+                                           const TSourceLoc &loc)
+{
+    TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
+    if (node == 0)
+    {
+        binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
+                      right->getCompleteString());
+        return left;
+    }
+    return node;
+}
+
+TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
+                                                        TIntermTyped *left,
+                                                        TIntermTyped *right,
+                                                        const TSourceLoc &loc)
+{
+    TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
+    if (node == 0)
+    {
+        binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
+                      right->getCompleteString());
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setBConst(false);
+        return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
+                                             loc);
+    }
+    return node;
+}
+
+TIntermBinary *TParseContext::createAssign(TOperator op,
+                                           TIntermTyped *left,
+                                           TIntermTyped *right,
+                                           const TSourceLoc &loc)
+{
+    if (binaryOpCommonCheck(op, left, right, loc))
+    {
+        if (op == EOpMulAssign)
+        {
+            op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
+            if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
+            {
+                return nullptr;
+            }
+        }
+        TIntermBinary *node = new TIntermBinary(op, left, right);
+        node->setLine(loc);
+
+        return node;
+    }
+    return nullptr;
+}
+
+TIntermTyped *TParseContext::addAssign(TOperator op,
+                                       TIntermTyped *left,
+                                       TIntermTyped *right,
+                                       const TSourceLoc &loc)
+{
+    TIntermTyped *node = createAssign(op, left, right, loc);
+    if (node == nullptr)
+    {
+        assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
+        return left;
+    }
+    return node;
+}
+
+TIntermTyped *TParseContext::addComma(TIntermTyped *left,
+                                      TIntermTyped *right,
+                                      const TSourceLoc &loc)
+{
+    // WebGL2 section 5.26, the following results in an error:
+    // "Sequence operator applied to void, arrays, or structs containing arrays"
+    if (mShaderSpec == SH_WEBGL2_SPEC &&
+        (left->isArray() || left->getBasicType() == EbtVoid ||
+         left->getType().isStructureContainingArrays() || right->isArray() ||
+         right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
+    {
+        error(loc,
+              "sequence operator is not allowed for void, arrays, or structs containing arrays",
+              ",");
+    }
+
+    return TIntermediate::AddComma(left, right, loc, mShaderVersion);
+}
+
+TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
+{
+    switch (op)
+    {
+        case EOpContinue:
+            if (mLoopNestingLevel <= 0)
+            {
+                error(loc, "continue statement only allowed in loops", "");
+            }
+            break;
+        case EOpBreak:
+            if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
+            {
+                error(loc, "break statement only allowed in loops and switch statements", "");
+            }
+            break;
+        case EOpReturn:
+            if (mCurrentFunctionType->getBasicType() != EbtVoid)
+            {
+                error(loc, "non-void function must return a value", "return");
+            }
+            break;
+        default:
+            // No checks for discard
+            break;
+    }
+    return intermediate.addBranch(op, loc);
+}
+
+TIntermBranch *TParseContext::addBranch(TOperator op,
+                                        TIntermTyped *returnValue,
+                                        const TSourceLoc &loc)
+{
+    ASSERT(op == EOpReturn);
+    mFunctionReturnsValue = true;
+    if (mCurrentFunctionType->getBasicType() == EbtVoid)
+    {
+        error(loc, "void function cannot return a value", "return");
+    }
+    else if (*mCurrentFunctionType != returnValue->getType())
+    {
+        error(loc, "function return is not matching type:", "return");
+    }
+    return intermediate.addBranch(op, returnValue, loc);
+}
+
+void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
+{
+    ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
+    const TString &name        = functionCall->getFunctionSymbolInfo()->getName();
+    TIntermNode *offset        = nullptr;
+    TIntermSequence *arguments = functionCall->getSequence();
+    if (name == "texelFetchOffset" || name == "textureLodOffset" ||
+        name == "textureProjLodOffset" || name == "textureGradOffset" ||
+        name == "textureProjGradOffset")
+    {
+        offset = arguments->back();
+    }
+    else if (name == "textureOffset" || name == "textureProjOffset")
+    {
+        // A bias parameter might follow the offset parameter.
+        ASSERT(arguments->size() >= 3);
+        offset = (*arguments)[2];
+    }
+    if (offset != nullptr)
+    {
+        TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
+        if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
+        {
+            error(functionCall->getLine(), "Texture offset must be a constant expression",
+                  name.c_str());
+        }
+        else
+        {
+            ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
+            size_t size                  = offsetConstantUnion->getType().getObjectSize();
+            const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
+            for (size_t i = 0u; i < size; ++i)
+            {
+                int offsetValue = values[i].getIConst();
+                if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
+                {
+                    std::stringstream tokenStream;
+                    tokenStream << offsetValue;
+                    std::string token = tokenStream.str();
+                    error(offset->getLine(), "Texture offset value out of valid range",
+                          token.c_str());
+                }
+            }
+        }
+    }
+}
+
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
+{
+    ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
+    const TString &name = functionCall->getFunctionSymbolInfo()->getName();
+
+    if (name.compare(0, 5, "image") == 0)
+    {
+        TIntermSequence *arguments = functionCall->getSequence();
+        TIntermTyped *imageNode    = (*arguments)[0]->getAsTyped();
+
+        const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
+
+        if (name.compare(5, 5, "Store") == 0)
+        {
+            if (memoryQualifier.readonly)
+            {
+                error(imageNode->getLine(),
+                      "'imageStore' cannot be used with images qualified as 'readonly'",
+                      GetImageArgumentToken(imageNode));
+            }
+        }
+        else if (name.compare(5, 4, "Load") == 0)
+        {
+            if (memoryQualifier.writeonly)
+            {
+                error(imageNode->getLine(),
+                      "'imageLoad' cannot be used with images qualified as 'writeonly'",
+                      GetImageArgumentToken(imageNode));
+            }
+        }
+    }
+}
+
+// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
+void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
+    const TFunction *functionDefinition,
+    const TIntermAggregate *functionCall)
+{
+    ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
+
+    const TIntermSequence &arguments = *functionCall->getSequence();
+
+    ASSERT(functionDefinition->getParamCount() == arguments.size());
+
+    for (size_t i = 0; i < arguments.size(); ++i)
+    {
+        TIntermTyped *typedArgument        = arguments[i]->getAsTyped();
+        const TType &functionArgumentType  = typedArgument->getType();
+        const TType &functionParameterType = *functionDefinition->getParam(i).type;
+        ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
+
+        if (IsImage(functionArgumentType.getBasicType()))
+        {
+            const TMemoryQualifier &functionArgumentMemoryQualifier =
+                functionArgumentType.getMemoryQualifier();
+            const TMemoryQualifier &functionParameterMemoryQualifier =
+                functionParameterType.getMemoryQualifier();
+            if (functionArgumentMemoryQualifier.readonly &&
+                !functionParameterMemoryQualifier.readonly)
+            {
+                error(functionCall->getLine(),
+                      "Function call discards the 'readonly' qualifier from image",
+                      GetImageArgumentToken(typedArgument));
+            }
+
+            if (functionArgumentMemoryQualifier.writeonly &&
+                !functionParameterMemoryQualifier.writeonly)
+            {
+                error(functionCall->getLine(),
+                      "Function call discards the 'writeonly' qualifier from image",
+                      GetImageArgumentToken(typedArgument));
+            }
+
+            if (functionArgumentMemoryQualifier.coherent &&
+                !functionParameterMemoryQualifier.coherent)
+            {
+                error(functionCall->getLine(),
+                      "Function call discards the 'coherent' qualifier from image",
+                      GetImageArgumentToken(typedArgument));
+            }
+
+            if (functionArgumentMemoryQualifier.volatileQualifier &&
+                !functionParameterMemoryQualifier.volatileQualifier)
+            {
+                error(functionCall->getLine(),
+                      "Function call discards the 'volatile' qualifier from image",
+                      GetImageArgumentToken(typedArgument));
+            }
+        }
+    }
+}
+
+TIntermSequence *TParseContext::createEmptyArgumentsList()
+{
+    return new TIntermSequence();
+}
+
+TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
+                                                     TIntermSequence *arguments,
+                                                     TIntermNode *thisNode,
+                                                     const TSourceLoc &loc)
+{
+    if (thisNode != nullptr)
+    {
+        return addMethod(fnCall, arguments, thisNode, loc);
+    }
+
+    TOperator op = fnCall->getBuiltInOp();
+    if (op == EOpConstruct)
+    {
+        return addConstructor(arguments, fnCall->getReturnType(), loc);
+    }
+    else
+    {
+        ASSERT(op == EOpNull);
+        return addNonConstructorFunctionCall(fnCall, arguments, loc);
+    }
+}
+
+TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
+                                       TIntermSequence *arguments,
+                                       TIntermNode *thisNode,
+                                       const TSourceLoc &loc)
+{
+    TConstantUnion *unionArray = new TConstantUnion[1];
+    int arraySize              = 0;
+    TIntermTyped *typedThis    = thisNode->getAsTyped();
+    // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
+    // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
+    // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
+    // So accessing fnCall->getName() below is safe.
+    if (fnCall->getName() != "length")
+    {
+        error(loc, "invalid method", fnCall->getName().c_str());
+    }
+    else if (!arguments->empty())
+    {
+        error(loc, "method takes no parameters", "length");
+    }
+    else if (typedThis == nullptr || !typedThis->isArray())
+    {
+        error(loc, "length can only be called on arrays", "length");
+    }
+    else
+    {
+        arraySize = typedThis->getArraySize();
+        if (typedThis->getAsSymbolNode() == nullptr)
+        {
+            // This code path can be hit with expressions like these:
+            // (a = b).length()
+            // (func()).length()
+            // (int[3](0, 1, 2)).length()
+            // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
+            // expression.
+            // It allows "An array name with the length method applied" in contrast to GLSL 4.4
+            // spec section 5.9 which allows "An array, vector or matrix expression with the
+            // length method applied".
+            error(loc, "length can only be called on array names, not on array expressions",
+                  "length");
+        }
+    }
+    unionArray->setIConst(arraySize);
+    return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
+}
+
+TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
+                                                           TIntermSequence *arguments,
+                                                           const TSourceLoc &loc)
+{
+    // First find by unmangled name to check whether the function name has been
+    // hidden by a variable name or struct typename.
+    // If a function is found, check for one with a matching argument list.
+    bool builtIn;
+    const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
+    if (symbol != nullptr && !symbol->isFunction())
+    {
+        error(loc, "function name expected", fnCall->getName().c_str());
+    }
+    else
+    {
+        symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
+                                  mShaderVersion, &builtIn);
+        if (symbol == nullptr)
+        {
+            error(loc, "no matching overloaded function found", fnCall->getName().c_str());
+        }
+        else
+        {
+            const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
+            //
+            // A declared function.
+            //
+            if (builtIn && !fnCandidate->getExtension().empty())
+            {
+                checkCanUseExtension(loc, fnCandidate->getExtension());
+            }
+            TOperator op = fnCandidate->getBuiltInOp();
+            if (builtIn && op != EOpNull)
+            {
+                // A function call mapped to a built-in operation.
+                if (fnCandidate->getParamCount() == 1)
+                {
+                    // Treat it like a built-in unary operator.
+                    TIntermNode *unaryParamNode = arguments->front();
+                    TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
+                    ASSERT(callNode != nullptr);
+                    return callNode;
+                }
+                else
+                {
+                    TIntermAggregate *callNode =
+                        TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
+                    callNode->setLine(loc);
+
+                    // Some built-in functions have out parameters too.
+                    functionCallLValueErrorCheck(fnCandidate, callNode);
+
+                    // See if we can constant fold a built-in. Note that this may be possible even
+                    // if it is not const-qualified.
+                    TIntermTyped *foldedNode =
+                        intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
+                    if (foldedNode)
+                    {
+                        return foldedNode;
+                    }
+                    return callNode;
+                }
+            }
+            else
+            {
+                // This is a real function call
+                TIntermAggregate *callNode = nullptr;
+
+                // If builtIn == false, the function is user defined - could be an overloaded
+                // built-in as well.
+                // if builtIn == true, it's a builtIn function with no op associated with it.
+                // This needs to happen after the function info including name is set.
+                if (builtIn)
+                {
+                    callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
+                    checkTextureOffsetConst(callNode);
+                    checkImageMemoryAccessForBuiltinFunctions(callNode);
+                }
+                else
+                {
+                    callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
+                    checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
+                }
+
+                functionCallLValueErrorCheck(fnCandidate, callNode);
+
+                callNode->setLine(loc);
+
+                return callNode;
+            }
+        }
+    }
+
+    // Error message was already written. Put on a dummy node for error recovery.
+    return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
+}
+
+TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
+                                                 TIntermTyped *trueExpression,
+                                                 TIntermTyped *falseExpression,
+                                                 const TSourceLoc &loc)
+{
+    checkIsScalarBool(loc, cond);
+
+    if (trueExpression->getType() != falseExpression->getType())
+    {
+        binaryOpError(loc, ":", trueExpression->getCompleteString(),
+                      falseExpression->getCompleteString());
+        return falseExpression;
+    }
+    if (IsOpaqueType(trueExpression->getBasicType()))
+    {
+        // ESSL 1.00 section 4.1.7
+        // ESSL 3.00 section 4.1.7
+        // Opaque/sampler types are not allowed in most types of expressions, including ternary.
+        // Note that structs containing opaque types don't need to be checked as structs are
+        // forbidden below.
+        error(loc, "ternary operator is not allowed for opaque types", ":");
+        return falseExpression;
+    }
+
+    // ESSL1 sections 5.2 and 5.7:
+    // ESSL3 section 5.7:
+    // Ternary operator is not among the operators allowed for structures/arrays.
+    if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
+    {
+        error(loc, "ternary operator is not allowed for structures or arrays", ":");
+        return falseExpression;
+    }
+    if (trueExpression->getBasicType() == EbtInterfaceBlock)
+    {
+        error(loc, "ternary operator is not allowed for interface blocks", ":");
+        return falseExpression;
+    }
+
+    // WebGL2 section 5.26, the following results in an error:
+    // "Ternary operator applied to void, arrays, or structs containing arrays"
+    if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
+    {
+        error(loc, "ternary operator is not allowed for void", ":");
+        return falseExpression;
+    }
+
+    return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
+}
+
+//
+// Parse an array of strings using yyparse.
+//
+// Returns 0 for success.
+//
+int PaParseStrings(size_t count,
+                   const char *const string[],
+                   const int length[],
+                   TParseContext *context)
+{
+    if ((count == 0) || (string == nullptr))
+        return 1;
+
+    if (glslang_initialize(context))
+        return 1;
+
+    int error = glslang_scan(count, string, length, context);
+    if (!error)
+        error = glslang_parse(context);
+
+    glslang_finalize(context);
+
+    return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ParseContext.h b/src/third_party/angle/src/compiler/translator/ParseContext.h
new file mode 100644
index 0000000..c479c2d
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ParseContext.h
@@ -0,0 +1,489 @@
+//
+// 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.
+//
+#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_
+#define COMPILER_TRANSLATOR_PARSECONTEXT_H_
+
+#include "compiler/translator/Compiler.h"
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/DirectiveHandler.h"
+#include "compiler/translator/Intermediate.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/QualifierTypes.h"
+#include "compiler/preprocessor/Preprocessor.h"
+
+namespace sh
+{
+
+struct TMatrixFields
+{
+    bool wholeRow;
+    bool wholeCol;
+    int row;
+    int col;
+};
+
+//
+// The following are extra variables needed during parsing, grouped together so
+// they can be passed to the parser without needing a global.
+//
+class TParseContext : angle::NonCopyable
+{
+  public:
+    TParseContext(TSymbolTable &symt,
+                  TExtensionBehavior &ext,
+                  sh::GLenum type,
+                  ShShaderSpec spec,
+                  ShCompileOptions options,
+                  bool checksPrecErrors,
+                  TDiagnostics *diagnostics,
+                  const ShBuiltInResources &resources);
+
+    const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }
+    pp::Preprocessor &getPreprocessor() { return mPreprocessor; }
+    void *getScanner() const { return mScanner; }
+    void setScanner(void *scanner) { mScanner = scanner; }
+    int getShaderVersion() const { return mShaderVersion; }
+    sh::GLenum getShaderType() const { return mShaderType; }
+    ShShaderSpec getShaderSpec() const { return mShaderSpec; }
+    int numErrors() const { return mDiagnostics->numErrors(); }
+    void error(const TSourceLoc &loc, const char *reason, const char *token);
+    void warning(const TSourceLoc &loc, const char *reason, const char *token);
+
+    // If isError is false, a warning will be reported instead.
+    void outOfRangeError(bool isError,
+                         const TSourceLoc &loc,
+                         const char *reason,
+                         const char *token);
+
+    TIntermBlock *getTreeRoot() const { return mTreeRoot; }
+    void setTreeRoot(TIntermBlock *treeRoot) { mTreeRoot = treeRoot; }
+
+    bool getFragmentPrecisionHigh() const
+    {
+        return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300;
+    }
+    void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh)
+    {
+        mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh;
+    }
+
+    void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; }
+
+    void incrLoopNestingLevel() { ++mLoopNestingLevel; }
+    void decrLoopNestingLevel() { --mLoopNestingLevel; }
+
+    void incrSwitchNestingLevel() { ++mSwitchNestingLevel; }
+    void decrSwitchNestingLevel() { --mSwitchNestingLevel; }
+
+    bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; }
+    sh::WorkGroupSize getComputeShaderLocalSize() const;
+
+    int getNumViews() const { return mNumViews; }
+
+    void enterFunctionDeclaration() { mDeclaringFunction = true; }
+
+    void exitFunctionDeclaration() { mDeclaringFunction = false; }
+
+    bool declaringFunction() const { return mDeclaringFunction; }
+
+    // This method is guaranteed to succeed, even if no variable with 'name' exists.
+    const TVariable *getNamedVariable(const TSourceLoc &location,
+                                      const TString *name,
+                                      const TSymbol *symbol);
+    TIntermTyped *parseVariableIdentifier(const TSourceLoc &location,
+                                          const TString *name,
+                                          const TSymbol *symbol);
+
+    bool parseVectorFields(const TString &, int vecSize, TVectorFields &, const TSourceLoc &line);
+
+    void assignError(const TSourceLoc &line, const char *op, TString left, TString right);
+    void unaryOpError(const TSourceLoc &line, const char *op, TString operand);
+    void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right);
+
+    // Check functions - the ones that return bool return false if an error was generated.
+
+    bool checkIsNotReserved(const TSourceLoc &line, const TString &identifier);
+    void checkPrecisionSpecified(const TSourceLoc &line, TPrecision precision, TBasicType type);
+    bool checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node);
+    void checkIsConst(TIntermTyped *node);
+    void checkIsScalarInteger(TIntermTyped *node, const char *token);
+    bool checkIsAtGlobalLevel(const TSourceLoc &line, const char *token);
+    bool checkConstructorArguments(const TSourceLoc &line,
+                                   const TIntermSequence *arguments,
+                                   const TType &type);
+
+    // Returns a sanitized array size to use (the size is at least 1).
+    unsigned int checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr);
+    bool checkIsValidQualifierForArray(const TSourceLoc &line, const TPublicType &elementQualifier);
+    bool checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType);
+    bool checkIsNonVoid(const TSourceLoc &line, const TString &identifier, const TBasicType &type);
+    void checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type);
+    void checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType);
+    bool checkIsNotOpaqueType(const TSourceLoc &line,
+                              const TTypeSpecifierNonArray &pType,
+                              const char *reason);
+    void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType);
+    void checkLocationIsNotSpecified(const TSourceLoc &location,
+                                     const TLayoutQualifier &layoutQualifier);
+    void checkIsParameterQualifierValid(const TSourceLoc &line,
+                                        const TTypeQualifierBuilder &typeQualifierBuilder,
+                                        TType *type);
+    bool checkCanUseExtension(const TSourceLoc &line, const TString &extension);
+
+    // Done for all declarations, whether empty or not.
+    void declarationQualifierErrorCheck(const sh::TQualifier qualifier,
+                                        const sh::TLayoutQualifier &layoutQualifier,
+                                        const TSourceLoc &location);
+    // Done for the first non-empty declarator in a declaration.
+    void nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
+                                       const TSourceLoc &identifierLocation);
+    // Done only for empty declarations.
+    void emptyDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &location);
+
+    void checkLayoutQualifierSupported(const TSourceLoc &location,
+                                       const TString &layoutQualifierName,
+                                       int versionRequired);
+    bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
+                                          const TLayoutQualifier &layoutQualifier);
+    void functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall);
+    void checkInvariantVariableQualifier(bool invariant,
+                                         const TQualifier qualifier,
+                                         const TSourceLoc &invariantLocation);
+    void checkInputOutputTypeIsValidES3(const TQualifier qualifier,
+                                        const TPublicType &type,
+                                        const TSourceLoc &qualifierLocation);
+    void checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier);
+    const TPragma &pragma() const { return mDirectiveHandler.pragma(); }
+    const TExtensionBehavior &extensionBehavior() const
+    {
+        return mDirectiveHandler.extensionBehavior();
+    }
+    bool supportsExtension(const char *extension);
+    bool isExtensionEnabled(const char *extension) const;
+    void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior);
+    void handlePragmaDirective(const TSourceLoc &loc,
+                               const char *name,
+                               const char *value,
+                               bool stdgl);
+
+    bool executeInitializer(const TSourceLoc &line,
+                            const TString &identifier,
+                            const TPublicType &pType,
+                            TIntermTyped *initializer,
+                            TIntermBinary **initNode);
+
+    void addFullySpecifiedType(TPublicType *typeSpecifier);
+    TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
+                                      const TPublicType &typeSpecifier);
+
+    TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType,
+                                               const TSourceLoc &identifierOrTypeLocation,
+                                               const TString &identifier);
+    TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &publicType,
+                                                    const TSourceLoc &identifierLocation,
+                                                    const TString &identifier,
+                                                    const TSourceLoc &indexLocation,
+                                                    TIntermTyped *indexExpression);
+    TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType,
+                                                   const TSourceLoc &identifierLocation,
+                                                   const TString &identifier,
+                                                   const TSourceLoc &initLocation,
+                                                   TIntermTyped *initializer);
+
+    // Parse a declaration like "type a[n] = initializer"
+    // Note that this does not apply to declarations like "type[n] a = initializer"
+    TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &publicType,
+                                                        const TSourceLoc &identifierLocation,
+                                                        const TString &identifier,
+                                                        const TSourceLoc &indexLocation,
+                                                        TIntermTyped *indexExpression,
+                                                        const TSourceLoc &initLocation,
+                                                        TIntermTyped *initializer);
+
+    TIntermInvariantDeclaration *parseInvariantDeclaration(
+        const TTypeQualifierBuilder &typeQualifierBuilder,
+        const TSourceLoc &identifierLoc,
+        const TString *identifier,
+        const TSymbol *symbol);
+
+    void parseDeclarator(TPublicType &publicType,
+                         const TSourceLoc &identifierLocation,
+                         const TString &identifier,
+                         TIntermDeclaration *declarationOut);
+    void parseArrayDeclarator(TPublicType &publicType,
+                              const TSourceLoc &identifierLocation,
+                              const TString &identifier,
+                              const TSourceLoc &arrayLocation,
+                              TIntermTyped *indexExpression,
+                              TIntermDeclaration *declarationOut);
+    void parseInitDeclarator(const TPublicType &publicType,
+                             const TSourceLoc &identifierLocation,
+                             const TString &identifier,
+                             const TSourceLoc &initLocation,
+                             TIntermTyped *initializer,
+                             TIntermDeclaration *declarationOut);
+
+    // Parse a declarator like "a[n] = initializer"
+    void parseArrayInitDeclarator(const TPublicType &publicType,
+                                  const TSourceLoc &identifierLocation,
+                                  const TString &identifier,
+                                  const TSourceLoc &indexLocation,
+                                  TIntermTyped *indexExpression,
+                                  const TSourceLoc &initLocation,
+                                  TIntermTyped *initializer,
+                                  TIntermDeclaration *declarationOut);
+
+    void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder);
+    TIntermFunctionPrototype *addFunctionPrototypeDeclaration(const TFunction &parsedFunction,
+                                                              const TSourceLoc &location);
+    TIntermFunctionDefinition *addFunctionDefinition(TIntermFunctionPrototype *functionPrototype,
+                                                     TIntermBlock *functionBody,
+                                                     const TSourceLoc &location);
+    void parseFunctionDefinitionHeader(const TSourceLoc &location,
+                                       TFunction **function,
+                                       TIntermFunctionPrototype **prototypeOut);
+    TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function);
+    TFunction *parseFunctionHeader(const TPublicType &type,
+                                   const TString *name,
+                                   const TSourceLoc &location);
+    TFunction *addConstructorFunc(const TPublicType &publicType);
+
+    TIntermTyped *addIndexExpression(TIntermTyped *baseExpression,
+                                     const TSourceLoc &location,
+                                     TIntermTyped *indexExpression);
+    TIntermTyped *addFieldSelectionExpression(TIntermTyped *baseExpression,
+                                              const TSourceLoc &dotLocation,
+                                              const TString &fieldString,
+                                              const TSourceLoc &fieldLocation);
+
+    TFieldList *combineStructFieldLists(TFieldList *processedFields,
+                                        const TFieldList *newlyAddedFields,
+                                        const TSourceLoc &location);
+    TFieldList *addStructDeclaratorListWithQualifiers(
+        const TTypeQualifierBuilder &typeQualifierBuilder,
+        TPublicType *typeSpecifier,
+        TFieldList *fieldList);
+    TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
+    TTypeSpecifierNonArray addStructure(const TSourceLoc &structLine,
+                                        const TSourceLoc &nameLine,
+                                        const TString *structName,
+                                        TFieldList *fieldList);
+
+    TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
+                                          const TSourceLoc &nameLine,
+                                          const TString &blockName,
+                                          TFieldList *fieldList,
+                                          const TString *instanceName,
+                                          const TSourceLoc &instanceLine,
+                                          TIntermTyped *arrayIndex,
+                                          const TSourceLoc &arrayIndexLine);
+
+    void parseLocalSize(const TString &qualifierType,
+                        const TSourceLoc &qualifierTypeLine,
+                        int intValue,
+                        const TSourceLoc &intValueLine,
+                        const std::string &intValueString,
+                        size_t index,
+                        sh::WorkGroupSize *localSize);
+    void parseNumViews(int intValue,
+                       const TSourceLoc &intValueLine,
+                       const std::string &intValueString,
+                       int *numViews);
+    TLayoutQualifier parseLayoutQualifier(const TString &qualifierType,
+                                          const TSourceLoc &qualifierTypeLine);
+    TLayoutQualifier parseLayoutQualifier(const TString &qualifierType,
+                                          const TSourceLoc &qualifierTypeLine,
+                                          int intValue,
+                                          const TSourceLoc &intValueLine);
+    TTypeQualifierBuilder *createTypeQualifierBuilder(const TSourceLoc &loc);
+    TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier,
+                                          TLayoutQualifier rightQualifier,
+                                          const TSourceLoc &rightQualifierLocation);
+
+    // Performs an error check for embedded struct declarations.
+    void enterStructDeclaration(const TSourceLoc &line, const TString &identifier);
+    void exitStructDeclaration();
+
+    void checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field);
+
+    TIntermSwitch *addSwitch(TIntermTyped *init,
+                             TIntermBlock *statementList,
+                             const TSourceLoc &loc);
+    TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
+    TIntermCase *addDefault(const TSourceLoc &loc);
+
+    TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
+    TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
+    TIntermTyped *addBinaryMath(TOperator op,
+                                TIntermTyped *left,
+                                TIntermTyped *right,
+                                const TSourceLoc &loc);
+    TIntermTyped *addBinaryMathBooleanResult(TOperator op,
+                                             TIntermTyped *left,
+                                             TIntermTyped *right,
+                                             const TSourceLoc &loc);
+    TIntermTyped *addAssign(TOperator op,
+                            TIntermTyped *left,
+                            TIntermTyped *right,
+                            const TSourceLoc &loc);
+
+    TIntermTyped *addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
+
+    TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
+    TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
+
+    void checkTextureOffsetConst(TIntermAggregate *functionCall);
+    void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall);
+    void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition,
+                                                       const TIntermAggregate *functionCall);
+    TIntermSequence *createEmptyArgumentsList();
+
+    // fnCall is only storing the built-in op, and function name or constructor type. arguments
+    // has the arguments.
+    TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall,
+                                          TIntermSequence *arguments,
+                                          TIntermNode *thisNode,
+                                          const TSourceLoc &loc);
+
+    TIntermTyped *addTernarySelection(TIntermTyped *cond,
+                                      TIntermTyped *trueExpression,
+                                      TIntermTyped *falseExpression,
+                                      const TSourceLoc &line);
+
+    // TODO(jmadill): make these private
+    TIntermediate intermediate;  // to build a parse tree
+    TSymbolTable &symbolTable;   // symbol table that goes with the language currently being parsed
+
+  private:
+    // Returns a clamped index. If it prints out an error message, the token is "[]".
+    int checkIndexOutOfRange(bool outOfRangeIndexIsError,
+                             const TSourceLoc &location,
+                             int index,
+                             int arraySize,
+                             const char *reason);
+
+    bool declareVariable(const TSourceLoc &line,
+                         const TString &identifier,
+                         const TType &type,
+                         TVariable **variable);
+
+    void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
+                                              const TString &identifier,
+                                              TPublicType *type);
+
+    bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
+                                              const TPublicType &elementType);
+
+    // Assumes that multiplication op has already been set based on the types.
+    bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right);
+
+    void checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
+                                          TQualifier qualifier,
+                                          const TType &type);
+
+    void checkInternalFormatIsNotSpecified(const TSourceLoc &location,
+                                           TLayoutImageInternalFormat internalFormat);
+    void checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
+                                            const TSourceLoc &location);
+    void checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type);
+    void checkBindingIsNotSpecified(const TSourceLoc &location, int binding);
+    void checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize);
+    void checkSamplerBindingIsValid(const TSourceLoc &location, int binding, int arraySize);
+
+    void checkUniformLocationInRange(const TSourceLoc &location,
+                                     int objectLocationCount,
+                                     const TLayoutQualifier &layoutQualifier);
+
+    void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv);
+
+    TIntermTyped *addBinaryMathInternal(TOperator op,
+                                        TIntermTyped *left,
+                                        TIntermTyped *right,
+                                        const TSourceLoc &loc);
+    TIntermBinary *createAssign(TOperator op,
+                                TIntermTyped *left,
+                                TIntermTyped *right,
+                                const TSourceLoc &loc);
+    TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
+
+    TIntermTyped *addMethod(TFunction *fnCall,
+                            TIntermSequence *arguments,
+                            TIntermNode *thisNode,
+                            const TSourceLoc &loc);
+    TIntermTyped *addConstructor(TIntermSequence *arguments,
+                                 TType type,
+                                 const TSourceLoc &line);
+    TIntermTyped *addNonConstructorFunctionCall(TFunction *fnCall,
+                                                TIntermSequence *arguments,
+                                                const TSourceLoc &loc);
+
+    // Return true if the checks pass
+    bool binaryOpCommonCheck(TOperator op,
+                             TIntermTyped *left,
+                             TIntermTyped *right,
+                             const TSourceLoc &loc);
+
+    TIntermFunctionPrototype *createPrototypeNodeFromFunction(const TFunction &function,
+                                                              const TSourceLoc &location,
+                                                              bool insertParametersToSymbolTable);
+
+    // Set to true when the last/current declarator list was started with an empty declaration. The
+    // non-empty declaration error check will need to be performed if the empty declaration is
+    // followed by a declarator.
+    bool mDeferredNonEmptyDeclarationErrorCheck;
+
+    sh::GLenum mShaderType;    // vertex or fragment language (future: pack or unpack)
+    ShShaderSpec mShaderSpec;  // The language specification compiler conforms to - GLES2 or WebGL.
+    ShCompileOptions mCompileOptions;  // Options passed to TCompiler
+    int mShaderVersion;
+    TIntermBlock *mTreeRoot;  // root of parse tree being created
+    int mLoopNestingLevel;    // 0 if outside all loops
+    int mStructNestingLevel;  // incremented while parsing a struct declaration
+    int mSwitchNestingLevel;  // 0 if outside all switch statements
+    const TType
+        *mCurrentFunctionType;    // the return type of the function that's currently being parsed
+    bool mFunctionReturnsValue;   // true if a non-void function has a return
+    bool mChecksPrecisionErrors;  // true if an error will be generated when a variable is declared
+                                  // without precision, explicit or implicit.
+    bool mFragmentPrecisionHighOnESSL1;  // true if highp precision is supported when compiling
+                                         // ESSL1.
+    TLayoutMatrixPacking mDefaultMatrixPacking;
+    TLayoutBlockStorage mDefaultBlockStorage;
+    TString mHashErrMsg;
+    TDiagnostics *mDiagnostics;
+    TDirectiveHandler mDirectiveHandler;
+    pp::Preprocessor mPreprocessor;
+    void *mScanner;
+    bool mUsesFragData;  // track if we are using both gl_FragData and gl_FragColor
+    bool mUsesFragColor;
+    bool mUsesSecondaryOutputs;  // Track if we are using either gl_SecondaryFragData or
+                                 // gl_Secondary FragColor or both.
+    int mMinProgramTexelOffset;
+    int mMaxProgramTexelOffset;
+
+    bool mMultiviewAvailable;
+
+    // keep track of local group size declared in layout. It should be declared only once.
+    bool mComputeShaderLocalSizeDeclared;
+    sh::WorkGroupSize mComputeShaderLocalSize;
+    // keep track of number of views declared in layout.
+    int mNumViews;
+    int mMaxNumViews;
+    int mMaxImageUnits;
+    int mMaxCombinedTextureImageUnits;
+    int mMaxUniformLocations;
+    // keeps track whether we are declaring / defining a function
+    bool mDeclaringFunction;
+};
+
+int PaParseStrings(size_t count,
+                   const char *const string[],
+                   const int length[],
+                   TParseContext *context);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_PARSECONTEXT_H_
diff --git a/src/third_party/angle/src/compiler/translator/PoolAlloc.cpp b/src/third_party/angle/src/compiler/translator/PoolAlloc.cpp
new file mode 100644
index 0000000..0f1cd8b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/PoolAlloc.cpp
@@ -0,0 +1,360 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/PoolAlloc.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/platform.h"
+#include "common/tls.h"
+#include "compiler/translator/InitializeGlobals.h"
+
+TLSIndex PoolIndex = TLS_INVALID_INDEX;
+
+bool InitializePoolIndex()
+{
+    assert(PoolIndex == TLS_INVALID_INDEX);
+
+    PoolIndex = CreateTLSIndex();
+    return PoolIndex != TLS_INVALID_INDEX;
+}
+
+void FreePoolIndex()
+{
+    assert(PoolIndex != TLS_INVALID_INDEX);
+
+    DestroyTLSIndex(PoolIndex);
+    PoolIndex = TLS_INVALID_INDEX;
+}
+
+TPoolAllocator *GetGlobalPoolAllocator()
+{
+    assert(PoolIndex != TLS_INVALID_INDEX);
+    return static_cast<TPoolAllocator *>(GetTLSValue(PoolIndex));
+}
+
+void SetGlobalPoolAllocator(TPoolAllocator *poolAllocator)
+{
+    assert(PoolIndex != TLS_INVALID_INDEX);
+    SetTLSValue(PoolIndex, poolAllocator);
+}
+
+//
+// Implement the functionality of the TPoolAllocator class, which
+// is documented in PoolAlloc.h.
+//
+TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment)
+    : alignment(allocationAlignment),
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+      pageSize(growthIncrement),
+      freeList(0),
+      inUseList(0),
+      numCalls(0),
+      totalBytes(0),
+#endif
+      mLocked(false)
+{
+    //
+    // Adjust alignment to be at least pointer aligned and
+    // power of 2.
+    //
+    size_t minAlign = sizeof(void *);
+    alignment &= ~(minAlign - 1);
+    if (alignment < minAlign)
+        alignment = minAlign;
+    size_t a      = 1;
+    while (a < alignment)
+        a <<= 1;
+    alignment     = a;
+    alignmentMask = a - 1;
+
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    //
+    // Don't allow page sizes we know are smaller than all common
+    // OS page sizes.
+    //
+    if (pageSize < 4 * 1024)
+        pageSize = 4 * 1024;
+
+    //
+    // A large currentPageOffset indicates a new page needs to
+    // be obtained to allocate memory.
+    //
+    currentPageOffset = pageSize;
+
+    //
+    // Align header skip
+    //
+    headerSkip = minAlign;
+    if (headerSkip < sizeof(tHeader))
+    {
+        headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
+    }
+#else  // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    mStack.push_back({});
+#endif
+}
+
+TPoolAllocator::~TPoolAllocator()
+{
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    while (inUseList)
+    {
+        tHeader *next = inUseList->nextPage;
+        inUseList->~tHeader();
+        delete[] reinterpret_cast<char *>(inUseList);
+        inUseList = next;
+    }
+
+    // We should not check the guard blocks
+    // here, because we did it already when the block was
+    // placed into the free list.
+    //
+    while (freeList)
+    {
+        tHeader *next = freeList->nextPage;
+        delete[] reinterpret_cast<char *>(freeList);
+        freeList = next;
+    }
+#else  // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    for (auto &allocs : mStack)
+    {
+        for (auto alloc : allocs)
+        {
+            free(alloc);
+        }
+    }
+    mStack.clear();
+#endif
+}
+
+// Support MSVC++ 6.0
+const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
+const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
+const unsigned char TAllocation::userDataFill       = 0xcd;
+
+#ifdef GUARD_BLOCKS
+const size_t TAllocation::guardBlockSize = 16;
+#else
+const size_t TAllocation::guardBlockSize = 0;
+#endif
+
+//
+// Check a single guard block for damage
+//
+void TAllocation::checkGuardBlock(unsigned char *blockMem,
+                                  unsigned char val,
+                                  const char *locText) const
+{
+#ifdef GUARD_BLOCKS
+    for (size_t x = 0; x < guardBlockSize; x++)
+    {
+        if (blockMem[x] != val)
+        {
+            char assertMsg[80];
+
+// We don't print the assert message.  It's here just to be helpful.
+#if defined(_MSC_VER)
+            snprintf(assertMsg, sizeof(assertMsg),
+                     "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n", locText, size, data());
+#else
+            snprintf(assertMsg, sizeof(assertMsg),
+                     "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", locText, size, data());
+#endif
+            assert(0 && "PoolAlloc: Damage in guard block");
+        }
+    }
+#endif
+}
+
+void TPoolAllocator::push()
+{
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    tAllocState state = {currentPageOffset, inUseList};
+
+    mStack.push_back(state);
+
+    //
+    // Indicate there is no current page to allocate from.
+    //
+    currentPageOffset = pageSize;
+#else  // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    mStack.push_back({});
+#endif
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred since the last push(), or since the
+// last pop(), or since the object's creation.
+//
+// The deallocated pages are saved for future allocations.
+//
+void TPoolAllocator::pop()
+{
+    if (mStack.size() < 1)
+        return;
+
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    tHeader *page     = mStack.back().page;
+    currentPageOffset = mStack.back().offset;
+
+    while (inUseList != page)
+    {
+        // invoke destructor to free allocation list
+        inUseList->~tHeader();
+
+        tHeader *nextInUse = inUseList->nextPage;
+        if (inUseList->pageCount > 1)
+            delete[] reinterpret_cast<char *>(inUseList);
+        else
+        {
+            inUseList->nextPage = freeList;
+            freeList            = inUseList;
+        }
+        inUseList = nextInUse;
+    }
+
+    mStack.pop_back();
+#else  // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    for (auto &alloc : mStack.back())
+    {
+        free(alloc);
+    }
+    mStack.pop_back();
+#endif
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred.
+//
+void TPoolAllocator::popAll()
+{
+    while (mStack.size() > 0)
+        pop();
+}
+
+void *TPoolAllocator::allocate(size_t numBytes)
+{
+    ASSERT(!mLocked);
+
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    //
+    // Just keep some interesting statistics.
+    //
+    ++numCalls;
+    totalBytes += numBytes;
+
+    // If we are using guard blocks, all allocations are bracketed by
+    // them: [guardblock][allocation][guardblock].  numBytes is how
+    // much memory the caller asked for.  allocationSize is the total
+    // size including guard blocks.  In release build,
+    // guardBlockSize=0 and this all gets optimized away.
+    size_t allocationSize = TAllocation::allocationSize(numBytes);
+    // Detect integer overflow.
+    if (allocationSize < numBytes)
+        return 0;
+
+    //
+    // Do the allocation, most likely case first, for efficiency.
+    // This step could be moved to be inline sometime.
+    //
+    if (allocationSize <= pageSize - currentPageOffset)
+    {
+        //
+        // Safe to allocate from currentPageOffset.
+        //
+        unsigned char *memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
+        currentPageOffset += allocationSize;
+        currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
+
+        return initializeAllocation(inUseList, memory, numBytes);
+    }
+
+    if (allocationSize > pageSize - headerSkip)
+    {
+        //
+        // Do a multi-page allocation.  Don't mix these with the others.
+        // The OS is efficient and allocating and free-ing multiple pages.
+        //
+        size_t numBytesToAlloc = allocationSize + headerSkip;
+        // Detect integer overflow.
+        if (numBytesToAlloc < allocationSize)
+            return 0;
+
+        tHeader *memory = reinterpret_cast<tHeader *>(::new char[numBytesToAlloc]);
+        if (memory == 0)
+            return 0;
+
+        // Use placement-new to initialize header
+        new (memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+        inUseList = memory;
+
+        currentPageOffset = pageSize;  // make next allocation come from a new page
+
+        // No guard blocks for multi-page allocations (yet)
+        return reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
+    }
+
+    //
+    // Need a simple page to allocate from.
+    //
+    tHeader *memory;
+    if (freeList)
+    {
+        memory   = freeList;
+        freeList = freeList->nextPage;
+    }
+    else
+    {
+        memory = reinterpret_cast<tHeader *>(::new char[pageSize]);
+        if (memory == 0)
+            return 0;
+    }
+
+    // Use placement-new to initialize header
+    new (memory) tHeader(inUseList, 1);
+    inUseList = memory;
+
+    unsigned char *ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
+    currentPageOffset  = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
+
+    return initializeAllocation(inUseList, ret, numBytes);
+#else  // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    void *alloc = malloc(numBytes + alignmentMask);
+    mStack.back().push_back(alloc);
+
+    intptr_t intAlloc = reinterpret_cast<intptr_t>(alloc);
+    intAlloc          = (intAlloc + alignmentMask) & ~alignmentMask;
+    return reinterpret_cast<void *>(intAlloc);
+#endif
+}
+
+void TPoolAllocator::lock()
+{
+    ASSERT(!mLocked);
+    mLocked = true;
+}
+
+void TPoolAllocator::unlock()
+{
+    ASSERT(mLocked);
+    mLocked = false;
+}
+
+//
+// Check all allocations in a list for damage by calling check on each.
+//
+void TAllocation::checkAllocList() const
+{
+    for (const TAllocation *alloc = this; alloc != 0; alloc = alloc->prevAlloc)
+        alloc->check();
+}
diff --git a/src/third_party/angle/src/compiler/translator/PoolAlloc.h b/src/third_party/angle/src/compiler/translator/PoolAlloc.h
new file mode 100644
index 0000000..ad63bc4
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/PoolAlloc.h
@@ -0,0 +1,319 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_POOLALLOC_H_
+#define COMPILER_TRANSLATOR_POOLALLOC_H_
+
+#ifdef _DEBUG
+#define GUARD_BLOCKS  // define to enable guard block sanity checking
+#endif
+
+//
+// This header defines an allocator that can be used to efficiently
+// allocate a large number of small requests for heap memory, with the
+// intention that they are not individually deallocated, but rather
+// collectively deallocated at one time.
+//
+// This simultaneously
+//
+// * Makes each individual allocation much more efficient; the
+//     typical allocation is trivial.
+// * Completely avoids the cost of doing individual deallocation.
+// * Saves the trouble of tracking down and plugging a large class of leaks.
+//
+// Individual classes can use this allocator by supplying their own
+// new and delete methods.
+//
+// STL containers can use this allocator by using the pool_allocator
+// class as the allocator (second) template argument.
+//
+
+#include <stddef.h>
+#include <string.h>
+#include <vector>
+
+// If we are using guard blocks, we must track each indivual
+// allocation.  If we aren't using guard blocks, these
+// never get instantiated, so won't have any impact.
+//
+
+class TAllocation
+{
+  public:
+    TAllocation(size_t size, unsigned char *mem, TAllocation *prev = 0)
+        : size(size), mem(mem), prevAlloc(prev)
+    {
+// Allocations are bracketed:
+//    [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
+// This would be cleaner with if (guardBlockSize)..., but that
+// makes the compiler print warnings about 0 length memsets,
+// even with the if() protecting them.
+#ifdef GUARD_BLOCKS
+        memset(preGuard(), guardBlockBeginVal, guardBlockSize);
+        memset(data(), userDataFill, size);
+        memset(postGuard(), guardBlockEndVal, guardBlockSize);
+#endif
+    }
+
+    void check() const
+    {
+        checkGuardBlock(preGuard(), guardBlockBeginVal, "before");
+        checkGuardBlock(postGuard(), guardBlockEndVal, "after");
+    }
+
+    void checkAllocList() const;
+
+    // Return total size needed to accomodate user buffer of 'size',
+    // plus our tracking data.
+    inline static size_t allocationSize(size_t size)
+    {
+        return size + 2 * guardBlockSize + headerSize();
+    }
+
+    // Offset from surrounding buffer to get to user data buffer.
+    inline static unsigned char *offsetAllocation(unsigned char *m)
+    {
+        return m + guardBlockSize + headerSize();
+    }
+
+  private:
+    void checkGuardBlock(unsigned char *blockMem, unsigned char val, const char *locText) const;
+
+    // Find offsets to pre and post guard blocks, and user data buffer
+    unsigned char *preGuard() const { return mem + headerSize(); }
+    unsigned char *data() const { return preGuard() + guardBlockSize; }
+    unsigned char *postGuard() const { return data() + size; }
+
+    size_t size;             // size of the user data area
+    unsigned char *mem;      // beginning of our allocation (pts to header)
+    TAllocation *prevAlloc;  // prior allocation in the chain
+
+    // Support MSVC++ 6.0
+    const static unsigned char guardBlockBeginVal;
+    const static unsigned char guardBlockEndVal;
+    const static unsigned char userDataFill;
+
+    const static size_t guardBlockSize;
+#ifdef GUARD_BLOCKS
+    inline static size_t headerSize() { return sizeof(TAllocation); }
+#else
+    inline static size_t headerSize() { return 0; }
+#endif
+};
+
+//
+// There are several stacks.  One is to track the pushing and popping
+// of the user, and not yet implemented.  The others are simply a
+// repositories of free pages or used pages.
+//
+// Page stacks are linked together with a simple header at the beginning
+// of each allocation obtained from the underlying OS.  Multi-page allocations
+// are returned to the OS.  Individual page allocations are kept for future
+// re-use.
+//
+// The "page size" used is not, nor must it match, the underlying OS
+// page size.  But, having it be about that size or equal to a set of
+// pages is likely most optimal.
+//
+class TPoolAllocator
+{
+  public:
+    TPoolAllocator(int growthIncrement = 8 * 1024, int allocationAlignment = 16);
+
+    //
+    // Don't call the destructor just to free up the memory, call pop()
+    //
+    ~TPoolAllocator();
+
+    //
+    // Call push() to establish a new place to pop memory too.  Does not
+    // have to be called to get things started.
+    //
+    void push();
+
+    //
+    // Call pop() to free all memory allocated since the last call to push(),
+    // or if no last call to push, frees all memory since first allocation.
+    //
+    void pop();
+
+    //
+    // Call popAll() to free all memory allocated.
+    //
+    void popAll();
+
+    //
+    // Call allocate() to actually acquire memory.  Returns 0 if no memory
+    // available, otherwise a properly aligned pointer to 'numBytes' of memory.
+    //
+    void *allocate(size_t numBytes);
+
+    //
+    // There is no deallocate.  The point of this class is that
+    // deallocation can be skipped by the user of it, as the model
+    // of use is to simultaneously deallocate everything at once
+    // by calling pop(), and to not have to solve memory leak problems.
+    //
+
+    // Catch unwanted allocations.
+    // TODO(jmadill): Remove this when we remove the global allocator.
+    void lock();
+    void unlock();
+
+  private:
+    size_t alignment;  // all returned allocations will be aligned at
+                       // this granularity, which will be a power of 2
+    size_t alignmentMask;
+
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    friend struct tHeader;
+
+    struct tHeader
+    {
+        tHeader(tHeader *nextPage, size_t pageCount)
+            : nextPage(nextPage),
+              pageCount(pageCount)
+#ifdef GUARD_BLOCKS
+              ,
+              lastAllocation(0)
+#endif
+        {
+        }
+
+        ~tHeader()
+        {
+#ifdef GUARD_BLOCKS
+            if (lastAllocation)
+                lastAllocation->checkAllocList();
+#endif
+        }
+
+        tHeader *nextPage;
+        size_t pageCount;
+#ifdef GUARD_BLOCKS
+        TAllocation *lastAllocation;
+#endif
+    };
+
+    struct tAllocState
+    {
+        size_t offset;
+        tHeader *page;
+    };
+    typedef std::vector<tAllocState> tAllocStack;
+
+    // Track allocations if and only if we're using guard blocks
+    void *initializeAllocation(tHeader *block, unsigned char *memory, size_t numBytes)
+    {
+#ifdef GUARD_BLOCKS
+        new (memory) TAllocation(numBytes, memory, block->lastAllocation);
+        block->lastAllocation = reinterpret_cast<TAllocation *>(memory);
+#endif
+        // This is optimized entirely away if GUARD_BLOCKS is not defined.
+        return TAllocation::offsetAllocation(memory);
+    }
+
+    size_t pageSize;           // granularity of allocation from the OS
+    size_t headerSkip;         // amount of memory to skip to make room for the
+                               //      header (basically, size of header, rounded
+                               //      up to make it aligned
+    size_t currentPageOffset;  // next offset in top of inUseList to allocate from
+    tHeader *freeList;         // list of popped memory
+    tHeader *inUseList;        // list of all memory currently being used
+    tAllocStack mStack;        // stack of where to allocate from, to partition pool
+
+    int numCalls;       // just an interesting statistic
+    size_t totalBytes;  // just an interesting statistic
+
+#else  // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+    std::vector<std::vector<void *>> mStack;
+#endif
+
+    TPoolAllocator &operator=(const TPoolAllocator &);  // dont allow assignment operator
+    TPoolAllocator(const TPoolAllocator &);             // dont allow default copy constructor
+    bool mLocked;
+};
+
+//
+// There could potentially be many pools with pops happening at
+// different times.  But a simple use is to have a global pop
+// with everyone using the same global allocator.
+//
+extern TPoolAllocator *GetGlobalPoolAllocator();
+extern void SetGlobalPoolAllocator(TPoolAllocator *poolAllocator);
+
+//
+// This STL compatible allocator is intended to be used as the allocator
+// parameter to templatized STL containers, like vector and map.
+//
+// It will use the pools for allocation, and not
+// do any deallocation, but will still do destruction.
+//
+template <class T>
+class pool_allocator
+{
+  public:
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    typedef T *pointer;
+    typedef const T *const_pointer;
+    typedef T &reference;
+    typedef const T &const_reference;
+    typedef T value_type;
+
+    template <class Other>
+    struct rebind
+    {
+        typedef pool_allocator<Other> other;
+    };
+    pointer address(reference x) const { return &x; }
+    const_pointer address(const_reference x) const { return &x; }
+
+    pool_allocator() {}
+
+    template <class Other>
+    pool_allocator(const pool_allocator<Other> &p)
+    {
+    }
+
+    template <class Other>
+    pool_allocator<T> &operator=(const pool_allocator<Other> &p)
+    {
+        return *this;
+    }
+
+#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR)
+    // libCStd on some platforms have a different allocate/deallocate interface.
+    // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be
+    // allocated, not the number of elements.
+    void *allocate(size_type n) { return getAllocator().allocate(n); }
+    void *allocate(size_type n, const void *) { return getAllocator().allocate(n); }
+    void deallocate(void *, size_type) {}
+#else
+    pointer allocate(size_type n)
+    {
+        return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
+    }
+    pointer allocate(size_type n, const void *)
+    {
+        return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
+    }
+    void deallocate(pointer, size_type) {}
+#endif  // _RWSTD_ALLOCATOR
+
+    void construct(pointer p, const T &val) { new ((void *)p) T(val); }
+    void destroy(pointer p) { p->T::~T(); }
+
+    bool operator==(const pool_allocator &rhs) const { return true; }
+    bool operator!=(const pool_allocator &rhs) const { return false; }
+
+    size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
+    size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
+
+    TPoolAllocator &getAllocator() const { return *GetGlobalPoolAllocator(); }
+};
+
+#endif  // COMPILER_TRANSLATOR_POOLALLOC_H_
diff --git a/src/third_party/angle/src/compiler/translator/Pragma.h b/src/third_party/angle/src/compiler/translator/Pragma.h
new file mode 100644
index 0000000..8c419fc
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Pragma.h
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_PRAGMA_H_
+#define COMPILER_TRANSLATOR_PRAGMA_H_
+
+struct TPragma
+{
+    struct STDGL
+    {
+        STDGL() : invariantAll(false) {}
+
+        bool invariantAll;
+    };
+
+    // By default optimization is turned on and debug is turned off.
+    // Precision emulation is turned on by default, but has no effect unless
+    // the extension is enabled.
+    TPragma() : optimize(true), debug(false), debugShaderPrecision(true) {}
+    TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) {}
+
+    bool optimize;
+    bool debug;
+    bool debugShaderPrecision;
+    STDGL stdgl;
+};
+
+#endif  // COMPILER_TRANSLATOR_PRAGMA_H_
diff --git a/src/third_party/angle/src/compiler/translator/PruneEmptyDeclarations.cpp b/src/third_party/angle/src/compiler/translator/PruneEmptyDeclarations.cpp
new file mode 100644
index 0000000..fd0eb41
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/PruneEmptyDeclarations.cpp
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The PruneEmptyDeclarations function prunes unnecessary empty declarations and declarators from
+// the AST.
+
+#include "compiler/translator/PruneEmptyDeclarations.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class PruneEmptyDeclarationsTraverser : private TIntermTraverser
+{
+  public:
+    static void apply(TIntermNode *root);
+
+  private:
+    PruneEmptyDeclarationsTraverser();
+    bool visitDeclaration(Visit, TIntermDeclaration *node) override;
+};
+
+void PruneEmptyDeclarationsTraverser::apply(TIntermNode *root)
+{
+    PruneEmptyDeclarationsTraverser prune;
+    root->traverse(&prune);
+    prune.updateTree();
+}
+
+PruneEmptyDeclarationsTraverser::PruneEmptyDeclarationsTraverser()
+    : TIntermTraverser(true, false, false)
+{
+}
+
+bool PruneEmptyDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
+{
+    TIntermSequence *sequence = node->getSequence();
+    if (sequence->size() >= 1)
+    {
+        TIntermSymbol *sym = sequence->front()->getAsSymbolNode();
+        // Prune declarations without a variable name, unless it's an interface block declaration.
+        if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock())
+        {
+            if (sequence->size() > 1)
+            {
+                // Generate a replacement that will remove the empty declarator in the beginning of
+                // a declarator list. Example of a declaration that will be changed:
+                // float, a;
+                // will be changed to
+                // float a;
+                // This applies also to struct declarations.
+                TIntermSequence emptyReplacement;
+                mMultiReplacements.push_back(
+                    NodeReplaceWithMultipleEntry(node, sym, emptyReplacement));
+            }
+            else if (sym->getBasicType() != EbtStruct)
+            {
+                // Single struct declarations may just declare the struct type and no variables, so
+                // they should not be pruned. All other single empty declarations can be pruned
+                // entirely. Example of an empty declaration that will be pruned:
+                // float;
+                TIntermSequence emptyReplacement;
+                TIntermBlock *parentAsBlock = getParentNode()->getAsBlock();
+                // The declaration may be inside a block or in a loop init expression.
+                ASSERT(parentAsBlock != nullptr || getParentNode()->getAsLoopNode() != nullptr);
+                if (parentAsBlock)
+                {
+                    mMultiReplacements.push_back(
+                        NodeReplaceWithMultipleEntry(parentAsBlock, node, emptyReplacement));
+                }
+                else
+                {
+                    queueReplacement(node, nullptr, OriginalNode::IS_DROPPED);
+                }
+            }
+            else if (sym->getType().getQualifier() != EvqGlobal &&
+                     sym->getType().getQualifier() != EvqTemporary)
+            {
+                // We've hit an empty struct declaration with a qualifier, for example like
+                // this:
+                // const struct a { int i; };
+                // NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so
+                // we convert the declaration to a regular struct declaration. This is okay,
+                // since ESSL 1.00 spec section 4.1.8 says about structs that "The optional
+                // qualifiers only apply to any declarators, and are not part of the type being
+                // defined for name."
+
+                if (mInGlobalScope)
+                {
+                    sym->getTypePointer()->setQualifier(EvqGlobal);
+                }
+                else
+                {
+                    sym->getTypePointer()->setQualifier(EvqTemporary);
+                }
+            }
+        }
+    }
+    return false;
+}
+
+}  // namespace
+
+void PruneEmptyDeclarations(TIntermNode *root)
+{
+    PruneEmptyDeclarationsTraverser::apply(root);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/PruneEmptyDeclarations.h b/src/third_party/angle/src/compiler/translator/PruneEmptyDeclarations.h
new file mode 100644
index 0000000..f928978
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/PruneEmptyDeclarations.h
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The PruneEmptyDeclarations function prunes unnecessary empty declarations and declarators from
+// the AST.
+
+#ifndef COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_
+#define COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_
+
+namespace sh
+{
+class TIntermNode;
+
+void PruneEmptyDeclarations(TIntermNode *root);
+}
+
+#endif  // COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_
diff --git a/src/third_party/angle/src/compiler/translator/PrunePureLiteralStatements.cpp b/src/third_party/angle/src/compiler/translator/PrunePureLiteralStatements.cpp
new file mode 100644
index 0000000..5def5a0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/PrunePureLiteralStatements.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2017 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.
+//
+// PrunePureLiteralStatements.cpp: Removes statements that are literals and nothing else.
+
+#include "compiler/translator/PrunePureLiteralStatements.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class PrunePureLiteralStatementsTraverser : public TIntermTraverser
+{
+  public:
+    PrunePureLiteralStatementsTraverser() : TIntermTraverser(true, false, false) {}
+
+    bool visitBlock(Visit visit, TIntermBlock *node) override
+    {
+        TIntermSequence *statements = node->getSequence();
+        if (statements == nullptr)
+        {
+            return false;
+        }
+
+        // Empty case statements at the end of a switch are invalid: if the last statements
+        // of a block was a pure literal, also delete all the case statements directly preceding it.
+        bool deleteCaseStatements = false;
+        for (int i = static_cast<int>(statements->size()); i-- > 0;)
+        {
+            TIntermNode *statement = (*statements)[i];
+
+            if (statement->getAsConstantUnion() != nullptr)
+            {
+                TIntermSequence emptyReplacement;
+                mMultiReplacements.push_back(
+                    NodeReplaceWithMultipleEntry(node, statement, emptyReplacement));
+
+                if (i == static_cast<int>(statements->size()) - 1)
+                {
+                    deleteCaseStatements = true;
+                }
+
+                continue;
+            }
+
+            if (deleteCaseStatements)
+            {
+                if (statement->getAsCaseNode() != nullptr)
+                {
+                    TIntermSequence emptyReplacement;
+                    mMultiReplacements.push_back(
+                        NodeReplaceWithMultipleEntry(node, statement, emptyReplacement));
+                }
+                else
+                {
+                    deleteCaseStatements = false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    bool visitLoop(Visit visit, TIntermLoop *loop) override
+    {
+        TIntermTyped *expr = loop->getExpression();
+        if (expr != nullptr && expr->getAsConstantUnion() != nullptr)
+        {
+            loop->setExpression(nullptr);
+        }
+
+        return true;
+    }
+};
+
+}  // namespace
+
+void PrunePureLiteralStatements(TIntermNode *root)
+{
+    PrunePureLiteralStatementsTraverser prune;
+    root->traverse(&prune);
+    prune.updateTree();
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/PrunePureLiteralStatements.h b/src/third_party/angle/src/compiler/translator/PrunePureLiteralStatements.h
new file mode 100644
index 0000000..ef956c0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/PrunePureLiteralStatements.h
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2017 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.
+//
+// PrunePureLiteralStatements.h: Removes statements that are literals and nothing else.
+
+#ifndef COMPILER_TRANSLATOR_PRUNEPURELITERALSTATEMENTS_H_
+#define COMPILER_TRANSLATOR_PRUNEPURELITERALSTATEMENTS_H_
+
+namespace sh
+{
+class TIntermNode;
+
+void PrunePureLiteralStatements(TIntermNode *root);
+}
+
+#endif  // COMPILER_TRANSLATOR_PRUNEPURELITERALSTATEMENTS_H_
diff --git a/src/third_party/angle/src/compiler/translator/QualifierTypes.cpp b/src/third_party/angle/src/compiler/translator/QualifierTypes.cpp
new file mode 100644
index 0000000..a70ff97
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/QualifierTypes.cpp
@@ -0,0 +1,738 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/QualifierTypes.h"
+
+#include "compiler/translator/Diagnostics.h"
+
+#include <algorithm>
+
+namespace sh
+{
+
+namespace
+{
+
+// GLSL ES 3.10 does not impose a strict order on type qualifiers and allows multiple layout
+// declarations.
+// GLSL ES 3.10 Revision 4, 4.10 Order of Qualification
+bool AreTypeQualifierChecksRelaxed(int shaderVersion)
+{
+    return shaderVersion >= 310;
+}
+
+bool IsScopeQualifier(TQualifier qualifier)
+{
+    return qualifier == EvqGlobal || qualifier == EvqTemporary;
+}
+
+bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier)
+{
+    if (qualifier->getType() != QtStorage)
+        return false;
+    const TStorageQualifierWrapper *storageQualifier =
+        static_cast<const TStorageQualifierWrapper *>(qualifier);
+    TQualifier q = storageQualifier->getQualifier();
+    return IsScopeQualifier(q);
+}
+
+// Returns true if the invariant for the qualifier sequence holds
+bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers)
+{
+    // We should have at least one qualifier.
+    // The first qualifier always tells the scope.
+    return qualifiers.size() >= 1 && IsScopeQualifierWrapper(qualifiers[0]);
+}
+
+// Returns true if there are qualifiers which have been specified multiple times
+// If areQualifierChecksRelaxed is set to true, then layout qualifier repetition is allowed.
+bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
+                            bool areQualifierChecksRelaxed,
+                            std::string *errorMessage)
+{
+    bool invariantFound     = false;
+    bool precisionFound     = false;
+    bool layoutFound        = false;
+    bool interpolationFound = false;
+
+    unsigned int locationsSpecified = 0;
+    bool isOut                      = false;
+
+    // The iteration starts from one since the first qualifier only reveals the scope of the
+    // expression. It is inserted first whenever the sequence gets created.
+    for (size_t i = 1; i < qualifiers.size(); ++i)
+    {
+        switch (qualifiers[i]->getType())
+        {
+            case QtInvariant:
+            {
+                if (invariantFound)
+                {
+                    *errorMessage = "The invariant qualifier specified multiple times.";
+                    return true;
+                }
+                invariantFound = true;
+                break;
+            }
+            case QtPrecision:
+            {
+                if (precisionFound)
+                {
+                    *errorMessage = "The precision qualifier specified multiple times.";
+                    return true;
+                }
+                precisionFound = true;
+                break;
+            }
+            case QtLayout:
+            {
+                if (layoutFound && !areQualifierChecksRelaxed)
+                {
+                    *errorMessage = "The layout qualifier specified multiple times.";
+                    return true;
+                }
+                if (invariantFound && !areQualifierChecksRelaxed)
+                {
+                    // This combination is not correct according to the syntax specified in the
+                    // formal grammar in the ESSL 3.00 spec. In ESSL 3.10 the grammar does not have
+                    // a similar restriction.
+                    *errorMessage =
+                        "The layout qualifier and invariant qualifier cannot coexist in the same "
+                        "declaration according to the grammar.";
+                    return true;
+                }
+                layoutFound = true;
+                const TLayoutQualifier &currentQualifier =
+                    static_cast<const TLayoutQualifierWrapper *>(qualifiers[i])->getQualifier();
+                locationsSpecified += currentQualifier.locationsSpecified;
+                break;
+            }
+            case QtInterpolation:
+            {
+                // 'centroid' is treated as a storage qualifier
+                // 'flat centroid' will be squashed to 'flat'
+                // 'smooth centroid' will be squashed to 'centroid'
+                if (interpolationFound)
+                {
+                    *errorMessage = "The interpolation qualifier specified multiple times.";
+                    return true;
+                }
+                interpolationFound = true;
+                break;
+            }
+            case QtStorage:
+            {
+                // Go over all of the storage qualifiers up until the current one and check for
+                // repetitions.
+                TQualifier currentQualifier =
+                    static_cast<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier();
+                if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut)
+                {
+                    isOut = true;
+                }
+                for (size_t j = 1; j < i; ++j)
+                {
+                    if (qualifiers[j]->getType() == QtStorage)
+                    {
+                        const TStorageQualifierWrapper *previousQualifierWrapper =
+                            static_cast<const TStorageQualifierWrapper *>(qualifiers[j]);
+                        TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
+                        if (currentQualifier == previousQualifier)
+                        {
+                            *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
+                            *errorMessage += " specified multiple times";
+                            return true;
+                        }
+                    }
+                }
+                break;
+            }
+            case QtMemory:
+            {
+                // Go over all of the memory qualifiers up until the current one and check for
+                // repetitions.
+                // Having both readonly and writeonly in a sequence is valid.
+                // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+                TQualifier currentQualifier =
+                    static_cast<const TMemoryQualifierWrapper *>(qualifiers[i])->getQualifier();
+                for (size_t j = 1; j < i; ++j)
+                {
+                    if (qualifiers[j]->getType() == QtMemory)
+                    {
+                        const TMemoryQualifierWrapper *previousQualifierWrapper =
+                            static_cast<const TMemoryQualifierWrapper *>(qualifiers[j]);
+                        TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
+                        if (currentQualifier == previousQualifier)
+                        {
+                            *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
+                            *errorMessage += " specified multiple times";
+                            return true;
+                        }
+                    }
+                }
+                break;
+            }
+            default:
+                UNREACHABLE();
+        }
+    }
+
+    if (locationsSpecified > 1 && isOut)
+    {
+        // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers
+        // GLSL ES 3.10 section 4.4.2 Output Layout Qualifiers
+        // "The qualifier may appear at most once within a declaration."
+        *errorMessage = "Output layout location specified multiple times.";
+        return true;
+    }
+
+    return false;
+}
+
+// GLSL ES 3.00_6, 4.7 Order of Qualification
+// The correct order of qualifiers is:
+// invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier
+// layout-qualifier has to be before storage-qualifier.
+bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
+                          std::string *errorMessage)
+{
+    bool foundInterpolation = false;
+    bool foundStorage       = false;
+    bool foundPrecision     = false;
+    for (size_t i = 1; i < qualifiers.size(); ++i)
+    {
+        switch (qualifiers[i]->getType())
+        {
+            case QtInvariant:
+                if (foundInterpolation || foundStorage || foundPrecision)
+                {
+                    *errorMessage = "The invariant qualifier has to be first in the expression.";
+                    return false;
+                }
+                break;
+            case QtInterpolation:
+                if (foundStorage)
+                {
+                    *errorMessage = "Storage qualifiers have to be after interpolation qualifiers.";
+                    return false;
+                }
+                else if (foundPrecision)
+                {
+                    *errorMessage =
+                        "Precision qualifiers have to be after interpolation qualifiers.";
+                    return false;
+                }
+                foundInterpolation = true;
+                break;
+            case QtLayout:
+                if (foundStorage)
+                {
+                    *errorMessage = "Storage qualifiers have to be after layout qualifiers.";
+                    return false;
+                }
+                else if (foundPrecision)
+                {
+                    *errorMessage = "Precision qualifiers have to be after layout qualifiers.";
+                    return false;
+                }
+                break;
+            case QtStorage:
+                if (foundPrecision)
+                {
+                    *errorMessage = "Precision qualifiers have to be after storage qualifiers.";
+                    return false;
+                }
+                foundStorage = true;
+                break;
+            case QtMemory:
+                if (foundPrecision)
+                {
+                    *errorMessage = "Precision qualifiers have to be after memory qualifiers.";
+                    return false;
+                }
+                break;
+            case QtPrecision:
+                foundPrecision = true;
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+    return true;
+}
+
+struct QualifierComparator
+{
+    bool operator()(const TQualifierWrapperBase *q1, const TQualifierWrapperBase *q2)
+    {
+        return q1->getRank() < q2->getRank();
+    }
+};
+
+void SortSequence(TTypeQualifierBuilder::QualifierSequence &qualifiers)
+{
+    // We need a stable sorting algorithm since the order of layout-qualifier declarations matter.
+    // The sorting starts from index 1, instead of 0, since the element at index 0 tells the scope
+    // and we always want it to be first.
+    std::stable_sort(qualifiers.begin() + 1, qualifiers.end(), QualifierComparator());
+}
+
+// Handles the joining of storage qualifiers for variables.
+bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier)
+{
+    switch (*joinedQualifier)
+    {
+        case EvqGlobal:
+            *joinedQualifier = storageQualifier;
+            break;
+        case EvqTemporary:
+        {
+            switch (storageQualifier)
+            {
+                case EvqConst:
+                    *joinedQualifier = storageQualifier;
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        }
+        case EvqSmooth:
+        {
+            switch (storageQualifier)
+            {
+                case EvqCentroid:
+                    *joinedQualifier = EvqCentroid;
+                    break;
+                case EvqVertexOut:
+                    *joinedQualifier = EvqSmoothOut;
+                    break;
+                case EvqFragmentIn:
+                    *joinedQualifier = EvqSmoothIn;
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        }
+        case EvqFlat:
+        {
+            switch (storageQualifier)
+            {
+                case EvqCentroid:
+                    *joinedQualifier = EvqFlat;
+                    break;
+                case EvqVertexOut:
+                    *joinedQualifier = EvqFlatOut;
+                    break;
+                case EvqFragmentIn:
+                    *joinedQualifier = EvqFlatIn;
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        }
+        case EvqCentroid:
+        {
+            switch (storageQualifier)
+            {
+                case EvqVertexOut:
+                    *joinedQualifier = EvqCentroidOut;
+                    break;
+                case EvqFragmentIn:
+                    *joinedQualifier = EvqCentroidIn;
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        }
+        default:
+            return false;
+    }
+    return true;
+}
+
+// Handles the joining of storage qualifiers for a parameter in a function.
+bool JoinParameterStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier)
+{
+    switch (*joinedQualifier)
+    {
+        case EvqTemporary:
+            *joinedQualifier = storageQualifier;
+            break;
+        case EvqConst:
+        {
+            switch (storageQualifier)
+            {
+                case EvqIn:
+                    *joinedQualifier = EvqConstReadOnly;
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        }
+        default:
+            return false;
+    }
+    return true;
+}
+
+bool JoinMemoryQualifier(TMemoryQualifier *joinedMemoryQualifier, TQualifier memoryQualifier)
+{
+    switch (memoryQualifier)
+    {
+        case EvqReadOnly:
+            joinedMemoryQualifier->readonly = true;
+            break;
+        case EvqWriteOnly:
+            joinedMemoryQualifier->writeonly = true;
+            break;
+        case EvqCoherent:
+            joinedMemoryQualifier->coherent = true;
+            break;
+        case EvqRestrict:
+            joinedMemoryQualifier->restrictQualifier = true;
+            break;
+        case EvqVolatile:
+            // Variables having the volatile qualifier are automatcally treated as coherent as well.
+            // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers
+            joinedMemoryQualifier->volatileQualifier = true;
+            joinedMemoryQualifier->coherent          = true;
+            break;
+        default:
+            UNREACHABLE();
+    }
+    return true;
+}
+
+TTypeQualifier GetVariableTypeQualifierFromSortedSequence(
+    const TTypeQualifierBuilder::QualifierSequence &sortedSequence,
+    TDiagnostics *diagnostics)
+{
+    TTypeQualifier typeQualifier(
+        static_cast<const TStorageQualifierWrapper *>(sortedSequence[0])->getQualifier(),
+        sortedSequence[0]->getLine());
+    for (size_t i = 1; i < sortedSequence.size(); ++i)
+    {
+        const TQualifierWrapperBase *qualifier = sortedSequence[i];
+        bool isQualifierValid                  = false;
+        switch (qualifier->getType())
+        {
+            case QtInvariant:
+                isQualifierValid        = true;
+                typeQualifier.invariant = true;
+                break;
+            case QtInterpolation:
+            {
+                switch (typeQualifier.qualifier)
+                {
+                    case EvqGlobal:
+                        isQualifierValid = true;
+                        typeQualifier.qualifier =
+                            static_cast<const TInterpolationQualifierWrapper *>(qualifier)
+                                ->getQualifier();
+                        break;
+                    default:
+                        isQualifierValid = false;
+                }
+                break;
+            }
+            case QtLayout:
+            {
+                const TLayoutQualifierWrapper *layoutQualifierWrapper =
+                    static_cast<const TLayoutQualifierWrapper *>(qualifier);
+                isQualifierValid              = true;
+                typeQualifier.layoutQualifier = sh::JoinLayoutQualifiers(
+                    typeQualifier.layoutQualifier, layoutQualifierWrapper->getQualifier(),
+                    layoutQualifierWrapper->getLine(), diagnostics);
+                break;
+            }
+            case QtStorage:
+                isQualifierValid = JoinVariableStorageQualifier(
+                    &typeQualifier.qualifier,
+                    static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
+                break;
+            case QtPrecision:
+                isQualifierValid = true;
+                typeQualifier.precision =
+                    static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
+                ASSERT(typeQualifier.precision != EbpUndefined);
+                break;
+            case QtMemory:
+                isQualifierValid = JoinMemoryQualifier(
+                    &typeQualifier.memoryQualifier,
+                    static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
+                break;
+            default:
+                UNREACHABLE();
+        }
+        if (!isQualifierValid)
+        {
+            const TString &qualifierString = qualifier->getQualifierString();
+            diagnostics->error(qualifier->getLine(), "invalid qualifier combination",
+                               qualifierString.c_str());
+            break;
+        }
+    }
+    return typeQualifier;
+}
+
+TTypeQualifier GetParameterTypeQualifierFromSortedSequence(
+    const TTypeQualifierBuilder::QualifierSequence &sortedSequence,
+    TDiagnostics *diagnostics)
+{
+    TTypeQualifier typeQualifier(EvqTemporary, sortedSequence[0]->getLine());
+    for (size_t i = 1; i < sortedSequence.size(); ++i)
+    {
+        const TQualifierWrapperBase *qualifier = sortedSequence[i];
+        bool isQualifierValid                  = false;
+        switch (qualifier->getType())
+        {
+            case QtInvariant:
+            case QtInterpolation:
+            case QtLayout:
+                break;
+            case QtMemory:
+                isQualifierValid = JoinMemoryQualifier(
+                    &typeQualifier.memoryQualifier,
+                    static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
+                break;
+            case QtStorage:
+                isQualifierValid = JoinParameterStorageQualifier(
+                    &typeQualifier.qualifier,
+                    static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
+                break;
+            case QtPrecision:
+                isQualifierValid = true;
+                typeQualifier.precision =
+                    static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
+                ASSERT(typeQualifier.precision != EbpUndefined);
+                break;
+            default:
+                UNREACHABLE();
+        }
+        if (!isQualifierValid)
+        {
+            const TString &qualifierString = qualifier->getQualifierString();
+            diagnostics->error(qualifier->getLine(), "invalid parameter qualifier",
+                               qualifierString.c_str());
+            break;
+        }
+    }
+
+    switch (typeQualifier.qualifier)
+    {
+        case EvqIn:
+        case EvqConstReadOnly:  // const in
+        case EvqOut:
+        case EvqInOut:
+            break;
+        case EvqConst:
+            typeQualifier.qualifier = EvqConstReadOnly;
+            break;
+        case EvqTemporary:
+            // no qualifier has been specified, set it to EvqIn which is the default
+            typeQualifier.qualifier = EvqIn;
+            break;
+        default:
+            diagnostics->error(sortedSequence[0]->getLine(), "Invalid parameter qualifier ",
+                               getQualifierString(typeQualifier.qualifier));
+    }
+    return typeQualifier;
+}
+}  // namespace
+
+TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
+                                      TLayoutQualifier rightQualifier,
+                                      const TSourceLoc &rightQualifierLocation,
+                                      TDiagnostics *diagnostics)
+{
+    TLayoutQualifier joinedQualifier = leftQualifier;
+
+    if (rightQualifier.location != -1)
+    {
+        joinedQualifier.location = rightQualifier.location;
+        ++joinedQualifier.locationsSpecified;
+    }
+    if (rightQualifier.yuv != false)
+    {
+        joinedQualifier.yuv = rightQualifier.yuv;
+    }
+    if (rightQualifier.binding != -1)
+    {
+        joinedQualifier.binding = rightQualifier.binding;
+    }
+    if (rightQualifier.matrixPacking != EmpUnspecified)
+    {
+        joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
+    }
+    if (rightQualifier.blockStorage != EbsUnspecified)
+    {
+        joinedQualifier.blockStorage = rightQualifier.blockStorage;
+    }
+
+    for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
+    {
+        if (rightQualifier.localSize[i] != -1)
+        {
+            if (joinedQualifier.localSize[i] != -1 &&
+                joinedQualifier.localSize[i] != rightQualifier.localSize[i])
+            {
+                diagnostics->error(rightQualifierLocation,
+                                   "Cannot have multiple different work group size specifiers",
+                                   getWorkGroupSizeString(i));
+            }
+            joinedQualifier.localSize[i] = rightQualifier.localSize[i];
+        }
+    }
+
+    if (rightQualifier.numViews != -1)
+    {
+        joinedQualifier.numViews = rightQualifier.numViews;
+    }
+
+    if (rightQualifier.imageInternalFormat != EiifUnspecified)
+    {
+        joinedQualifier.imageInternalFormat = rightQualifier.imageInternalFormat;
+    }
+
+    return joinedQualifier;
+}
+
+unsigned int TInvariantQualifierWrapper::getRank() const
+{
+    return 0u;
+}
+
+unsigned int TInterpolationQualifierWrapper::getRank() const
+{
+    return 1u;
+}
+
+unsigned int TLayoutQualifierWrapper::getRank() const
+{
+    return 2u;
+}
+
+unsigned int TStorageQualifierWrapper::getRank() const
+{
+    // Force the 'centroid' auxilary storage qualifier to be always first among all storage
+    // qualifiers.
+    if (mStorageQualifier == EvqCentroid)
+    {
+        return 3u;
+    }
+    else
+    {
+        return 4u;
+    }
+}
+
+unsigned int TMemoryQualifierWrapper::getRank() const
+{
+    return 4u;
+}
+
+unsigned int TPrecisionQualifierWrapper::getRank() const
+{
+    return 5u;
+}
+
+TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc)
+    : layoutQualifier(TLayoutQualifier::create()),
+      memoryQualifier(TMemoryQualifier::create()),
+      precision(EbpUndefined),
+      qualifier(scope),
+      invariant(false),
+      line(loc)
+{
+    ASSERT(IsScopeQualifier(qualifier));
+}
+
+TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope,
+                                             int shaderVersion)
+    : mShaderVersion(shaderVersion)
+{
+    ASSERT(IsScopeQualifier(scope->getQualifier()));
+    mQualifiers.push_back(scope);
+}
+
+void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifier)
+{
+    mQualifiers.push_back(qualifier);
+}
+
+bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) const
+{
+    bool areQualifierChecksRelaxed = AreTypeQualifierChecksRelaxed(mShaderVersion);
+    std::string errorMessage;
+    if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage))
+    {
+        diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence");
+        return false;
+    }
+
+    if (!areQualifierChecksRelaxed && !AreQualifiersInOrder(mQualifiers, &errorMessage))
+    {
+        diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence");
+        return false;
+    }
+
+    return true;
+}
+
+TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TDiagnostics *diagnostics) const
+{
+    ASSERT(IsInvariantCorrect(mQualifiers));
+    ASSERT(static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier() ==
+           EvqTemporary);
+
+    if (!checkSequenceIsValid(diagnostics))
+    {
+        return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine());
+    }
+
+    // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
+    // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
+    // combine the qualifiers.
+    if (AreTypeQualifierChecksRelaxed(mShaderVersion))
+    {
+        // Copy the qualifier sequence so that we can sort them.
+        QualifierSequence sortedQualifierSequence = mQualifiers;
+        SortSequence(sortedQualifierSequence);
+        return GetParameterTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics);
+    }
+    return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
+}
+
+TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const
+{
+    ASSERT(IsInvariantCorrect(mQualifiers));
+
+    if (!checkSequenceIsValid(diagnostics))
+    {
+        return TTypeQualifier(
+            static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier(),
+            mQualifiers[0]->getLine());
+    }
+
+    // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
+    // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
+    // combine the qualifiers.
+    if (AreTypeQualifierChecksRelaxed(mShaderVersion))
+    {
+        // Copy the qualifier sequence so that we can sort them.
+        QualifierSequence sortedQualifierSequence = mQualifiers;
+        SortSequence(sortedQualifierSequence);
+        return GetVariableTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics);
+    }
+    return GetVariableTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/QualifierTypes.h b/src/third_party/angle/src/compiler/translator/QualifierTypes.h
new file mode 100644
index 0000000..10bdeed
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/QualifierTypes.h
@@ -0,0 +1,191 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
+#define COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Types.h"
+
+namespace sh
+{
+class TDiagnostics;
+
+TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
+                                      TLayoutQualifier rightQualifier,
+                                      const TSourceLoc &rightQualifierLocation,
+                                      TDiagnostics *diagnostics);
+
+enum TQualifierType
+{
+    QtInvariant,
+    QtInterpolation,
+    QtLayout,
+    QtStorage,
+    QtPrecision,
+    QtMemory
+};
+
+class TQualifierWrapperBase : angle::NonCopyable
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TQualifierWrapperBase(const TSourceLoc &line) : mLine(line) {}
+    virtual ~TQualifierWrapperBase(){};
+    virtual TQualifierType getType() const     = 0;
+    virtual TString getQualifierString() const = 0;
+    virtual unsigned int getRank() const       = 0;
+    const TSourceLoc &getLine() const { return mLine; }
+  private:
+    TSourceLoc mLine;
+};
+
+class TInvariantQualifierWrapper final : public TQualifierWrapperBase
+{
+  public:
+    TInvariantQualifierWrapper(const TSourceLoc &line) : TQualifierWrapperBase(line) {}
+    ~TInvariantQualifierWrapper() {}
+
+    TQualifierType getType() const { return QtInvariant; }
+    TString getQualifierString() const { return "invariant"; }
+    unsigned int getRank() const;
+};
+
+class TInterpolationQualifierWrapper final : public TQualifierWrapperBase
+{
+  public:
+    TInterpolationQualifierWrapper(TQualifier interpolationQualifier, const TSourceLoc &line)
+        : TQualifierWrapperBase(line), mInterpolationQualifier(interpolationQualifier)
+    {
+    }
+    ~TInterpolationQualifierWrapper() {}
+
+    TQualifierType getType() const { return QtInterpolation; }
+    TString getQualifierString() const { return sh::getQualifierString(mInterpolationQualifier); }
+    TQualifier getQualifier() const { return mInterpolationQualifier; }
+    unsigned int getRank() const;
+
+  private:
+    TQualifier mInterpolationQualifier;
+};
+
+class TLayoutQualifierWrapper final : public TQualifierWrapperBase
+{
+  public:
+    TLayoutQualifierWrapper(TLayoutQualifier layoutQualifier, const TSourceLoc &line)
+        : TQualifierWrapperBase(line), mLayoutQualifier(layoutQualifier)
+    {
+    }
+    ~TLayoutQualifierWrapper() {}
+
+    TQualifierType getType() const { return QtLayout; }
+    TString getQualifierString() const { return "layout"; }
+    const TLayoutQualifier &getQualifier() const { return mLayoutQualifier; }
+    unsigned int getRank() const;
+
+  private:
+    TLayoutQualifier mLayoutQualifier;
+};
+
+class TStorageQualifierWrapper final : public TQualifierWrapperBase
+{
+  public:
+    TStorageQualifierWrapper(TQualifier storageQualifier, const TSourceLoc &line)
+        : TQualifierWrapperBase(line), mStorageQualifier(storageQualifier)
+    {
+    }
+    ~TStorageQualifierWrapper() {}
+
+    TQualifierType getType() const { return QtStorage; }
+    TString getQualifierString() const { return sh::getQualifierString(mStorageQualifier); }
+    TQualifier getQualifier() const { return mStorageQualifier; }
+    unsigned int getRank() const;
+
+  private:
+    TQualifier mStorageQualifier;
+};
+
+class TPrecisionQualifierWrapper final : public TQualifierWrapperBase
+{
+  public:
+    TPrecisionQualifierWrapper(TPrecision precisionQualifier, const TSourceLoc &line)
+        : TQualifierWrapperBase(line), mPrecisionQualifier(precisionQualifier)
+    {
+    }
+    ~TPrecisionQualifierWrapper() {}
+
+    TQualifierType getType() const { return QtPrecision; }
+    TString getQualifierString() const { return sh::getPrecisionString(mPrecisionQualifier); }
+    TPrecision getQualifier() const { return mPrecisionQualifier; }
+    unsigned int getRank() const;
+
+  private:
+    TPrecision mPrecisionQualifier;
+};
+
+class TMemoryQualifierWrapper final : public TQualifierWrapperBase
+{
+  public:
+    TMemoryQualifierWrapper(TQualifier memoryQualifier, const TSourceLoc &line)
+        : TQualifierWrapperBase(line), mMemoryQualifier(memoryQualifier)
+    {
+    }
+    ~TMemoryQualifierWrapper() {}
+
+    TQualifierType getType() const { return QtMemory; }
+    TString getQualifierString() const { return sh::getQualifierString(mMemoryQualifier); }
+    TQualifier getQualifier() const { return mMemoryQualifier; }
+    unsigned int getRank() const;
+
+  private:
+    TQualifier mMemoryQualifier;
+};
+
+// TTypeQualifier tightly covers type_qualifier from the grammar
+struct TTypeQualifier
+{
+    // initializes all of the qualifiers and sets the scope
+    TTypeQualifier(TQualifier scope, const TSourceLoc &loc);
+
+    TLayoutQualifier layoutQualifier;
+    TMemoryQualifier memoryQualifier;
+    TPrecision precision;
+    TQualifier qualifier;
+    bool invariant;
+    TSourceLoc line;
+};
+
+// TTypeQualifierBuilder contains all of the qualifiers when type_qualifier gets parsed.
+// It is to be used to validate the qualifier sequence and build a TTypeQualifier from it.
+class TTypeQualifierBuilder : angle::NonCopyable
+{
+  public:
+    using QualifierSequence = TVector<const TQualifierWrapperBase *>;
+
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, int shaderVersion);
+    // Adds the passed qualifier to the end of the sequence.
+    void appendQualifier(const TQualifierWrapperBase *qualifier);
+    // Checks for the order of qualification and repeating qualifiers.
+    bool checkSequenceIsValid(TDiagnostics *diagnostics) const;
+    // Goes over the qualifier sequence and parses it to form a type qualifier for a function
+    // parameter.
+    // The returned object is initialized even if the parsing fails.
+    TTypeQualifier getParameterTypeQualifier(TDiagnostics *diagnostics) const;
+    // Goes over the qualifier sequence and parses it to form a type qualifier for a variable.
+    // The returned object is initialized even if the parsing fails.
+    TTypeQualifier getVariableTypeQualifier(TDiagnostics *diagnostics) const;
+
+  private:
+    QualifierSequence mQualifiers;
+    int mShaderVersion;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
diff --git a/src/third_party/angle/src/compiler/translator/RecordConstantPrecision.cpp b/src/third_party/angle/src/compiler/translator/RecordConstantPrecision.cpp
new file mode 100644
index 0000000..5106f9e
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RecordConstantPrecision.cpp
@@ -0,0 +1,169 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// During parsing, all constant expressions are folded to constant union nodes. The expressions that
+// have been folded may have had precision qualifiers, which should affect the precision of the
+// consuming operation. If the folded constant union nodes are written to output as such they won't
+// have any precision qualifiers, and their effect on the precision of the consuming operation is
+// lost.
+//
+// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants
+// and hoists the constants outside the containing expression as precision qualified named variables
+// in case that is required for correct precision propagation.
+//
+
+#include "compiler/translator/RecordConstantPrecision.h"
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class RecordConstantPrecisionTraverser : public TIntermTraverser
+{
+  public:
+    RecordConstantPrecisionTraverser();
+
+    void visitConstantUnion(TIntermConstantUnion *node) override;
+
+    void nextIteration();
+
+    bool foundHigherPrecisionConstant() const { return mFoundHigherPrecisionConstant; }
+  protected:
+    bool operandAffectsParentOperationPrecision(TIntermTyped *operand);
+
+    bool mFoundHigherPrecisionConstant;
+};
+
+RecordConstantPrecisionTraverser::RecordConstantPrecisionTraverser()
+    : TIntermTraverser(true, false, true), mFoundHigherPrecisionConstant(false)
+{
+}
+
+bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TIntermTyped *operand)
+{
+    if (getParentNode()->getAsCaseNode() || getParentNode()->getAsBlock())
+    {
+        return false;
+    }
+
+    const TIntermBinary *parentAsBinary = getParentNode()->getAsBinaryNode();
+    if (parentAsBinary != nullptr)
+    {
+        // If the constant is assigned or is used to initialize a variable, or if it's an index,
+        // its precision has no effect.
+        switch (parentAsBinary->getOp())
+        {
+            case EOpInitialize:
+            case EOpAssign:
+            case EOpIndexDirect:
+            case EOpIndexDirectStruct:
+            case EOpIndexDirectInterfaceBlock:
+            case EOpIndexIndirect:
+                return false;
+            default:
+                break;
+        }
+
+        TIntermTyped *otherOperand = parentAsBinary->getRight();
+        if (otherOperand == operand)
+        {
+            otherOperand = parentAsBinary->getLeft();
+        }
+        // If the precision of the other child is at least as high as the precision of the constant,
+        // the precision of the constant has no effect.
+        if (otherOperand->getAsConstantUnion() == nullptr &&
+            otherOperand->getPrecision() >= operand->getPrecision())
+        {
+            return false;
+        }
+    }
+
+    TIntermAggregate *parentAsAggregate = getParentNode()->getAsAggregate();
+    if (parentAsAggregate != nullptr)
+    {
+        if (!parentAsAggregate->gotPrecisionFromChildren())
+        {
+            // This can be either:
+            // * a call to an user-defined function
+            // * a call to a texture function
+            // * some other kind of aggregate
+            // In any of these cases the constant precision has no effect.
+            return false;
+        }
+        if (parentAsAggregate->isConstructor() && parentAsAggregate->getBasicType() == EbtBool)
+        {
+            return false;
+        }
+        // If the precision of operands does affect the result, but the precision of any of the
+        // other children has a precision that's at least as high as the precision of the constant,
+        // the precision of the constant has no effect.
+        TIntermSequence *parameters = parentAsAggregate->getSequence();
+        for (TIntermNode *parameter : *parameters)
+        {
+            const TIntermTyped *typedParameter = parameter->getAsTyped();
+            if (parameter != operand && typedParameter != nullptr &&
+                parameter->getAsConstantUnion() == nullptr &&
+                typedParameter->getPrecision() >= operand->getPrecision())
+            {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+void RecordConstantPrecisionTraverser::visitConstantUnion(TIntermConstantUnion *node)
+{
+    if (mFoundHigherPrecisionConstant)
+        return;
+
+    // If the constant has lowp or undefined precision, it can't increase the precision of consuming
+    // operations.
+    if (node->getPrecision() < EbpMedium)
+        return;
+
+    // It's possible the node has no effect on the precision of the consuming expression, depending
+    // on the consuming expression, and the precision of the other parameters of the expression.
+    if (!operandAffectsParentOperationPrecision(node))
+        return;
+
+    // Make the constant a precision-qualified named variable to make sure it affects the precision
+    // of the consuming expression.
+    TIntermSequence insertions;
+    insertions.push_back(createTempInitDeclaration(node, EvqConst));
+    insertStatementsInParentBlock(insertions);
+    queueReplacement(node, createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
+    mFoundHigherPrecisionConstant = true;
+}
+
+void RecordConstantPrecisionTraverser::nextIteration()
+{
+    nextTemporaryIndex();
+    mFoundHigherPrecisionConstant = false;
+}
+
+}  // namespace
+
+void RecordConstantPrecision(TIntermNode *root, unsigned int *temporaryIndex)
+{
+    RecordConstantPrecisionTraverser traverser;
+    ASSERT(temporaryIndex != nullptr);
+    traverser.useTemporaryIndex(temporaryIndex);
+    // Iterate as necessary, and reset the traverser between iterations.
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        if (traverser.foundHigherPrecisionConstant())
+            traverser.updateTree();
+    } while (traverser.foundHigherPrecisionConstant());
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/RecordConstantPrecision.h b/src/third_party/angle/src/compiler/translator/RecordConstantPrecision.h
new file mode 100644
index 0000000..cbe92d4
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RecordConstantPrecision.h
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// During parsing, all constant expressions are folded to constant union nodes. The expressions that
+// have been folded may have had precision qualifiers, which should affect the precision of the
+// consuming operation. If the folded constant union nodes are written to output as such they won't
+// have any precision qualifiers, and their effect on the precision of the consuming operation is
+// lost.
+//
+// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants
+// and hoists the constants outside the containing expression as precision qualified named variables
+// in case that is required for correct precision propagation.
+//
+
+#ifndef COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
+#define COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
+
+namespace sh
+{
+class TIntermNode;
+
+void RecordConstantPrecision(TIntermNode *root, unsigned int *temporaryIndex);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
diff --git a/src/third_party/angle/src/compiler/translator/RegenerateStructNames.cpp b/src/third_party/angle/src/compiler/translator/RegenerateStructNames.cpp
new file mode 100644
index 0000000..1613008
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RegenerateStructNames.cpp
@@ -0,0 +1,76 @@
+//
+// 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.
+//
+
+#include "common/debug.h"
+#include "compiler/translator/RegenerateStructNames.h"
+
+namespace sh
+{
+
+void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
+{
+    ASSERT(symbol);
+    TType *type = symbol->getTypePointer();
+    ASSERT(type);
+    TStructure *userType = type->getStruct();
+    if (!userType)
+        return;
+
+    if (mSymbolTable.findBuiltIn(userType->name(), mShaderVersion))
+    {
+        // Built-in struct, do not touch it.
+        return;
+    }
+
+    int uniqueId = userType->uniqueId();
+
+    ASSERT(mScopeDepth > 0);
+    if (mScopeDepth == 1)
+    {
+        // If a struct is defined at global scope, we don't map its name.
+        // This is because at global level, the struct might be used to
+        // declare a uniform, so the same name needs to stay the same for
+        // vertex/fragment shaders. However, our mapping uses internal ID,
+        // which will be different for the same struct in vertex/fragment
+        // shaders.
+        // This is OK because names for any structs defined in other scopes
+        // will begin with "_webgl", which is reserved. So there will be
+        // no conflicts among unmapped struct names from global scope and
+        // mapped struct names from other scopes.
+        // However, we need to keep track of these global structs, so if a
+        // variable is used in a local scope, we don't try to modify the
+        // struct name through that variable.
+        mDeclaredGlobalStructs.insert(uniqueId);
+        return;
+    }
+    if (mDeclaredGlobalStructs.count(uniqueId) > 0)
+        return;
+    // Map {name} to _webgl_struct_{uniqueId}_{name}.
+    const char kPrefix[] = "_webgl_struct_";
+    if (userType->name().find(kPrefix) == 0)
+    {
+        // The name has already been regenerated.
+        return;
+    }
+    std::string id = Str(uniqueId);
+    TString tmp    = kPrefix + TString(id.c_str());
+    tmp += "_" + userType->name();
+    userType->setName(tmp);
+}
+
+bool RegenerateStructNames::visitBlock(Visit, TIntermBlock *block)
+{
+    ++mScopeDepth;
+    TIntermSequence &sequence = *(block->getSequence());
+    for (TIntermNode *node : sequence)
+    {
+        node->traverse(this);
+    }
+    --mScopeDepth;
+    return false;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/RegenerateStructNames.h b/src/third_party/angle/src/compiler/translator/RegenerateStructNames.h
new file mode 100644
index 0000000..e4fc67e
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RegenerateStructNames.h
@@ -0,0 +1,47 @@
+//
+// 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.
+//
+
+#ifndef COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
+#define COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
+
+#include "compiler/translator/Intermediate.h"
+#include "compiler/translator/SymbolTable.h"
+
+#include <set>
+
+namespace sh
+{
+
+class RegenerateStructNames : public TIntermTraverser
+{
+  public:
+    RegenerateStructNames(const TSymbolTable &symbolTable, int shaderVersion)
+        : TIntermTraverser(true, false, false),
+          mSymbolTable(symbolTable),
+          mShaderVersion(shaderVersion),
+          mScopeDepth(0)
+    {
+    }
+
+  protected:
+    void visitSymbol(TIntermSymbol *) override;
+    bool visitBlock(Visit, TIntermBlock *block) override;
+
+  private:
+    const TSymbolTable &mSymbolTable;
+    int mShaderVersion;
+
+    // Indicating the depth of the current scope.
+    // The global scope is 1.
+    int mScopeDepth;
+
+    // If a struct's declared globally, push its ID in this set.
+    std::set<int> mDeclaredGlobalStructs;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
diff --git a/src/third_party/angle/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/third_party/angle/src/compiler/translator/RemoveDynamicIndexing.cpp
new file mode 100644
index 0000000..5d136a3
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RemoveDynamicIndexing.cpp
@@ -0,0 +1,547 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of vectors and matrices,
+// replacing them with calls to functions that choose which component to return or write.
+//
+
+#include "compiler/translator/RemoveDynamicIndexing.h"
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+std::string GetIndexFunctionName(const TType &type, bool write)
+{
+    TInfoSinkBase nameSink;
+    nameSink << "dyn_index_";
+    if (write)
+    {
+        nameSink << "write_";
+    }
+    if (type.isMatrix())
+    {
+        nameSink << "mat" << type.getCols() << "x" << type.getRows();
+    }
+    else
+    {
+        switch (type.getBasicType())
+        {
+            case EbtInt:
+                nameSink << "ivec";
+                break;
+            case EbtBool:
+                nameSink << "bvec";
+                break;
+            case EbtUInt:
+                nameSink << "uvec";
+                break;
+            case EbtFloat:
+                nameSink << "vec";
+                break;
+            default:
+                UNREACHABLE();
+        }
+        nameSink << type.getNominalSize();
+    }
+    return nameSink.str();
+}
+
+TIntermSymbol *CreateBaseSymbol(const TType &type, TQualifier qualifier)
+{
+    TIntermSymbol *symbol = new TIntermSymbol(0, "base", type);
+    symbol->setInternal(true);
+    symbol->getTypePointer()->setQualifier(qualifier);
+    return symbol;
+}
+
+TIntermSymbol *CreateIndexSymbol()
+{
+    TIntermSymbol *symbol = new TIntermSymbol(0, "index", TType(EbtInt, EbpHigh));
+    symbol->setInternal(true);
+    symbol->getTypePointer()->setQualifier(EvqIn);
+    return symbol;
+}
+
+TIntermSymbol *CreateValueSymbol(const TType &type)
+{
+    TIntermSymbol *symbol = new TIntermSymbol(0, "value", type);
+    symbol->setInternal(true);
+    symbol->getTypePointer()->setQualifier(EvqIn);
+    return symbol;
+}
+
+TIntermConstantUnion *CreateIntConstantNode(int i)
+{
+    TConstantUnion *constant = new TConstantUnion();
+    constant->setIConst(i);
+    return new TIntermConstantUnion(constant, TType(EbtInt, EbpHigh));
+}
+
+TIntermBinary *CreateIndexDirectBaseSymbolNode(const TType &indexedType,
+                                               const TType &fieldType,
+                                               const int index,
+                                               TQualifier baseQualifier)
+{
+    TIntermSymbol *baseSymbol = CreateBaseSymbol(indexedType, baseQualifier);
+    TIntermBinary *indexNode =
+        new TIntermBinary(EOpIndexDirect, baseSymbol, TIntermTyped::CreateIndexNode(index));
+    return indexNode;
+}
+
+TIntermBinary *CreateAssignValueSymbolNode(TIntermTyped *targetNode, const TType &assignedValueType)
+{
+    return new TIntermBinary(EOpAssign, targetNode, CreateValueSymbol(assignedValueType));
+}
+
+TIntermTyped *EnsureSignedInt(TIntermTyped *node)
+{
+    if (node->getBasicType() == EbtInt)
+        return node;
+
+    TIntermSequence *arguments = new TIntermSequence();
+    arguments->push_back(node);
+    return TIntermAggregate::CreateConstructor(TType(EbtInt), arguments);
+}
+
+TType GetFieldType(const TType &indexedType)
+{
+    if (indexedType.isMatrix())
+    {
+        TType fieldType = TType(indexedType.getBasicType(), indexedType.getPrecision());
+        fieldType.setPrimarySize(static_cast<unsigned char>(indexedType.getRows()));
+        return fieldType;
+    }
+    else
+    {
+        return TType(indexedType.getBasicType(), indexedType.getPrecision());
+    }
+}
+
+// Generate a read or write function for one field in a vector/matrix.
+// Out-of-range indices are clamped. This is consistent with how ANGLE handles out-of-range
+// indices in other places.
+// Note that indices can be either int or uint. We create only int versions of the functions,
+// and convert uint indices to int at the call site.
+// read function example:
+// float dyn_index_vec2(in vec2 base, in int index)
+// {
+//    switch(index)
+//    {
+//      case (0):
+//        return base[0];
+//      case (1):
+//        return base[1];
+//      default:
+//        break;
+//    }
+//    if (index < 0)
+//      return base[0];
+//    return base[1];
+// }
+// write function example:
+// void dyn_index_write_vec2(inout vec2 base, in int index, in float value)
+// {
+//    switch(index)
+//    {
+//      case (0):
+//        base[0] = value;
+//        return;
+//      case (1):
+//        base[1] = value;
+//        return;
+//      default:
+//        break;
+//    }
+//    if (index < 0)
+//    {
+//      base[0] = value;
+//      return;
+//    }
+//    base[1] = value;
+// }
+// Note that else is not used in above functions to avoid the RewriteElseBlocks transformation.
+TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type,
+                                                      bool write,
+                                                      const TSymbolUniqueId &functionId)
+{
+    ASSERT(!type.isArray());
+    // Conservatively use highp here, even if the indexed type is not highp. That way the code can't
+    // end up using mediump version of an indexing function for a highp value, if both mediump and
+    // highp values are being indexed in the shader. For HLSL precision doesn't matter, but in
+    // principle this code could be used with multiple backends.
+    type.setPrecision(EbpHigh);
+
+    TType fieldType = GetFieldType(type);
+    int numCases    = 0;
+    if (type.isMatrix())
+    {
+        numCases = type.getCols();
+    }
+    else
+    {
+        numCases = type.getNominalSize();
+    }
+
+    TType returnType(EbtVoid);
+    if (!write)
+    {
+        returnType = fieldType;
+    }
+
+    std::string functionName                = GetIndexFunctionName(type, write);
+    TIntermFunctionPrototype *prototypeNode = TIntermTraverser::CreateInternalFunctionPrototypeNode(
+        returnType, functionName.c_str(), functionId);
+
+    TQualifier baseQualifier     = EvqInOut;
+    if (!write)
+        baseQualifier        = EvqIn;
+    TIntermSymbol *baseParam = CreateBaseSymbol(type, baseQualifier);
+    prototypeNode->getSequence()->push_back(baseParam);
+    TIntermSymbol *indexParam = CreateIndexSymbol();
+    prototypeNode->getSequence()->push_back(indexParam);
+    if (write)
+    {
+        TIntermSymbol *valueParam = CreateValueSymbol(fieldType);
+        prototypeNode->getSequence()->push_back(valueParam);
+    }
+
+    TIntermBlock *statementList = new TIntermBlock();
+    for (int i = 0; i < numCases; ++i)
+    {
+        TIntermCase *caseNode = new TIntermCase(CreateIntConstantNode(i));
+        statementList->getSequence()->push_back(caseNode);
+
+        TIntermBinary *indexNode =
+            CreateIndexDirectBaseSymbolNode(type, fieldType, i, baseQualifier);
+        if (write)
+        {
+            TIntermBinary *assignNode = CreateAssignValueSymbolNode(indexNode, fieldType);
+            statementList->getSequence()->push_back(assignNode);
+            TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr);
+            statementList->getSequence()->push_back(returnNode);
+        }
+        else
+        {
+            TIntermBranch *returnNode = new TIntermBranch(EOpReturn, indexNode);
+            statementList->getSequence()->push_back(returnNode);
+        }
+    }
+
+    // Default case
+    TIntermCase *defaultNode = new TIntermCase(nullptr);
+    statementList->getSequence()->push_back(defaultNode);
+    TIntermBranch *breakNode = new TIntermBranch(EOpBreak, nullptr);
+    statementList->getSequence()->push_back(breakNode);
+
+    TIntermSwitch *switchNode = new TIntermSwitch(CreateIndexSymbol(), statementList);
+
+    TIntermBlock *bodyNode = new TIntermBlock();
+    bodyNode->getSequence()->push_back(switchNode);
+
+    TIntermBinary *cond =
+        new TIntermBinary(EOpLessThan, CreateIndexSymbol(), CreateIntConstantNode(0));
+    cond->setType(TType(EbtBool, EbpUndefined));
+
+    // Two blocks: one accesses (either reads or writes) the first element and returns,
+    // the other accesses the last element.
+    TIntermBlock *useFirstBlock = new TIntermBlock();
+    TIntermBlock *useLastBlock  = new TIntermBlock();
+    TIntermBinary *indexFirstNode =
+        CreateIndexDirectBaseSymbolNode(type, fieldType, 0, baseQualifier);
+    TIntermBinary *indexLastNode =
+        CreateIndexDirectBaseSymbolNode(type, fieldType, numCases - 1, baseQualifier);
+    if (write)
+    {
+        TIntermBinary *assignFirstNode = CreateAssignValueSymbolNode(indexFirstNode, fieldType);
+        useFirstBlock->getSequence()->push_back(assignFirstNode);
+        TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr);
+        useFirstBlock->getSequence()->push_back(returnNode);
+
+        TIntermBinary *assignLastNode = CreateAssignValueSymbolNode(indexLastNode, fieldType);
+        useLastBlock->getSequence()->push_back(assignLastNode);
+    }
+    else
+    {
+        TIntermBranch *returnFirstNode = new TIntermBranch(EOpReturn, indexFirstNode);
+        useFirstBlock->getSequence()->push_back(returnFirstNode);
+
+        TIntermBranch *returnLastNode = new TIntermBranch(EOpReturn, indexLastNode);
+        useLastBlock->getSequence()->push_back(returnLastNode);
+    }
+    TIntermIfElse *ifNode = new TIntermIfElse(cond, useFirstBlock, nullptr);
+    bodyNode->getSequence()->push_back(ifNode);
+    bodyNode->getSequence()->push_back(useLastBlock);
+
+    TIntermFunctionDefinition *indexingFunction =
+        new TIntermFunctionDefinition(prototypeNode, bodyNode);
+    return indexingFunction;
+}
+
+class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser
+{
+  public:
+    RemoveDynamicIndexingTraverser(const TSymbolTable &symbolTable, int shaderVersion);
+
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+
+    void insertHelperDefinitions(TIntermNode *root);
+
+    void nextIteration();
+
+    bool usedTreeInsertion() const { return mUsedTreeInsertion; }
+
+  protected:
+    // Maps of types that are indexed to the indexing function ids used for them. Note that these
+    // can not store multiple variants of the same type with different precisions - only one
+    // precision gets stored.
+    std::map<TType, TSymbolUniqueId> mIndexedVecAndMatrixTypes;
+    std::map<TType, TSymbolUniqueId> mWrittenVecAndMatrixTypes;
+
+    bool mUsedTreeInsertion;
+
+    // When true, the traverser will remove side effects from any indexing expression.
+    // This is done so that in code like
+    //   V[j++][i]++.
+    // where V is an array of vectors, j++ will only be evaluated once.
+    bool mRemoveIndexSideEffectsInSubtree;
+};
+
+RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser(const TSymbolTable &symbolTable,
+                                                               int shaderVersion)
+    : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
+      mUsedTreeInsertion(false),
+      mRemoveIndexSideEffectsInSubtree(false)
+{
+}
+
+void RemoveDynamicIndexingTraverser::insertHelperDefinitions(TIntermNode *root)
+{
+    TIntermBlock *rootBlock = root->getAsBlock();
+    ASSERT(rootBlock != nullptr);
+    TIntermSequence insertions;
+    for (auto &type : mIndexedVecAndMatrixTypes)
+    {
+        insertions.push_back(GetIndexFunctionDefinition(type.first, false, type.second));
+    }
+    for (auto &type : mWrittenVecAndMatrixTypes)
+    {
+        insertions.push_back(GetIndexFunctionDefinition(type.first, true, type.second));
+    }
+    mInsertions.push_back(NodeInsertMultipleEntry(rootBlock, 0, insertions, TIntermSequence()));
+}
+
+// Create a call to dyn_index_*() based on an indirect indexing op node
+TIntermAggregate *CreateIndexFunctionCall(TIntermBinary *node,
+                                          TIntermTyped *index,
+                                          const TSymbolUniqueId &functionId)
+{
+    ASSERT(node->getOp() == EOpIndexIndirect);
+    TIntermSequence *arguments = new TIntermSequence();
+    arguments->push_back(node->getLeft());
+    arguments->push_back(index);
+
+    TType fieldType                = GetFieldType(node->getLeft()->getType());
+    std::string functionName       = GetIndexFunctionName(node->getLeft()->getType(), false);
+    TIntermAggregate *indexingCall = TIntermTraverser::CreateInternalFunctionCallNode(
+        fieldType, functionName.c_str(), functionId, arguments);
+    indexingCall->setLine(node->getLine());
+    return indexingCall;
+}
+
+TIntermAggregate *CreateIndexedWriteFunctionCall(TIntermBinary *node,
+                                                 TIntermTyped *index,
+                                                 TIntermTyped *writtenValue,
+                                                 const TSymbolUniqueId &functionId)
+{
+    ASSERT(node->getOp() == EOpIndexIndirect);
+    TIntermSequence *arguments = new TIntermSequence();
+    // Deep copy the child nodes so that two pointers to the same node don't end up in the tree.
+    arguments->push_back(node->getLeft()->deepCopy());
+    arguments->push_back(index->deepCopy());
+    arguments->push_back(writtenValue);
+
+    std::string functionName           = GetIndexFunctionName(node->getLeft()->getType(), true);
+    TIntermAggregate *indexedWriteCall = TIntermTraverser::CreateInternalFunctionCallNode(
+        TType(EbtVoid), functionName.c_str(), functionId, arguments);
+    indexedWriteCall->setLine(node->getLine());
+    return indexedWriteCall;
+}
+
+bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+    if (mUsedTreeInsertion)
+        return false;
+
+    if (node->getOp() == EOpIndexIndirect)
+    {
+        if (mRemoveIndexSideEffectsInSubtree)
+        {
+            ASSERT(node->getRight()->hasSideEffects());
+            // In case we're just removing index side effects, convert
+            //   v_expr[index_expr]
+            // to this:
+            //   int s0 = index_expr; v_expr[s0];
+            // Now v_expr[s0] can be safely executed several times without unintended side effects.
+
+            // Init the temp variable holding the index
+            TIntermDeclaration *initIndex = createTempInitDeclaration(node->getRight());
+            insertStatementInParentBlock(initIndex);
+            mUsedTreeInsertion = true;
+
+            // Replace the index with the temp variable
+            TIntermSymbol *tempIndex = createTempSymbol(node->getRight()->getType());
+            queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED);
+        }
+        else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node))
+        {
+            bool write = isLValueRequiredHere();
+
+#if defined(ANGLE_ENABLE_ASSERTS)
+            // Make sure that IntermNodePatternMatcher is consistent with the slightly differently
+            // implemented checks in this traverser.
+            IntermNodePatternMatcher matcher(
+                IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue);
+            ASSERT(matcher.match(node, getParentNode(), isLValueRequiredHere()) == write);
+#endif
+
+            const TType &type = node->getLeft()->getType();
+            TSymbolUniqueId indexingFunctionId;
+            if (mIndexedVecAndMatrixTypes.find(type) == mIndexedVecAndMatrixTypes.end())
+            {
+                mIndexedVecAndMatrixTypes[type] = indexingFunctionId;
+            }
+            else
+            {
+                indexingFunctionId = mIndexedVecAndMatrixTypes[type];
+            }
+
+            if (write)
+            {
+                // Convert:
+                //   v_expr[index_expr]++;
+                // to this:
+                //   int s0 = index_expr; float s1 = dyn_index(v_expr, s0); s1++;
+                //   dyn_index_write(v_expr, s0, s1);
+                // This works even if index_expr has some side effects.
+                if (node->getLeft()->hasSideEffects())
+                {
+                    // If v_expr has side effects, those need to be removed before proceeding.
+                    // Otherwise the side effects of v_expr would be evaluated twice.
+                    // The only case where an l-value can have side effects is when it is
+                    // indexing. For example, it can be V[j++] where V is an array of vectors.
+                    mRemoveIndexSideEffectsInSubtree = true;
+                    return true;
+                }
+
+                TIntermBinary *leftBinary = node->getLeft()->getAsBinaryNode();
+                if (leftBinary != nullptr &&
+                    IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(leftBinary))
+                {
+                    // This is a case like:
+                    // mat2 m;
+                    // m[a][b]++;
+                    // Process the child node m[a] first.
+                    return true;
+                }
+
+                // TODO(oetuaho@nvidia.com): This is not optimal if the expression using the value
+                // only writes it and doesn't need the previous value. http://anglebug.com/1116
+
+                TSymbolUniqueId indexedWriteFunctionId;
+                if (mWrittenVecAndMatrixTypes.find(type) == mWrittenVecAndMatrixTypes.end())
+                {
+                    mWrittenVecAndMatrixTypes[type] = indexedWriteFunctionId;
+                }
+                else
+                {
+                    indexedWriteFunctionId = mWrittenVecAndMatrixTypes[type];
+                }
+                TType fieldType = GetFieldType(type);
+
+                TIntermSequence insertionsBefore;
+                TIntermSequence insertionsAfter;
+
+                // Store the index in a temporary signed int variable.
+                TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight());
+                TIntermDeclaration *initIndex  = createTempInitDeclaration(indexInitializer);
+                initIndex->setLine(node->getLine());
+                insertionsBefore.push_back(initIndex);
+
+                // Create a node for referring to the index after the nextTemporaryIndex() call
+                // below.
+                TIntermSymbol *tempIndex = createTempSymbol(indexInitializer->getType());
+
+                TIntermAggregate *indexingCall =
+                    CreateIndexFunctionCall(node, tempIndex, indexingFunctionId);
+
+                nextTemporaryIndex();  // From now on, creating temporary symbols that refer to the
+                                       // field value.
+                insertionsBefore.push_back(createTempInitDeclaration(indexingCall));
+
+                TIntermAggregate *indexedWriteCall = CreateIndexedWriteFunctionCall(
+                    node, tempIndex, createTempSymbol(fieldType), indexedWriteFunctionId);
+                insertionsAfter.push_back(indexedWriteCall);
+                insertStatementsInParentBlock(insertionsBefore, insertionsAfter);
+                queueReplacement(node, createTempSymbol(fieldType), OriginalNode::IS_DROPPED);
+                mUsedTreeInsertion = true;
+            }
+            else
+            {
+                // The indexed value is not being written, so we can simply convert
+                //   v_expr[index_expr]
+                // into
+                //   dyn_index(v_expr, index_expr)
+                // If the index_expr is unsigned, we'll convert it to signed.
+                ASSERT(!mRemoveIndexSideEffectsInSubtree);
+                TIntermAggregate *indexingCall = CreateIndexFunctionCall(
+                    node, EnsureSignedInt(node->getRight()), indexingFunctionId);
+                queueReplacement(node, indexingCall, OriginalNode::IS_DROPPED);
+            }
+        }
+    }
+    return !mUsedTreeInsertion;
+}
+
+void RemoveDynamicIndexingTraverser::nextIteration()
+{
+    mUsedTreeInsertion               = false;
+    mRemoveIndexSideEffectsInSubtree = false;
+    nextTemporaryIndex();
+}
+
+}  // namespace
+
+void RemoveDynamicIndexing(TIntermNode *root,
+                           unsigned int *temporaryIndex,
+                           const TSymbolTable &symbolTable,
+                           int shaderVersion)
+{
+    RemoveDynamicIndexingTraverser traverser(symbolTable, shaderVersion);
+    ASSERT(temporaryIndex != nullptr);
+    traverser.useTemporaryIndex(temporaryIndex);
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        traverser.updateTree();
+    } while (traverser.usedTreeInsertion());
+    // TOOD(oetuaho@nvidia.com): It might be nicer to add the helper definitions also in the middle
+    // of traversal. Now the tree ends up in an inconsistent state in the middle, since there are
+    // function call nodes with no corresponding definition nodes. This needs special handling in
+    // TIntermLValueTrackingTraverser, and creates intricacies that are not easily apparent from a
+    // superficial reading of the code.
+    traverser.insertHelperDefinitions(root);
+    traverser.updateTree();
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/RemoveDynamicIndexing.h b/src/third_party/angle/src/compiler/translator/RemoveDynamicIndexing.h
new file mode 100644
index 0000000..06305d0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RemoveDynamicIndexing.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of vectors and matrices,
+// replacing them with calls to functions that choose which component to return or write.
+//
+
+#ifndef COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_
+#define COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_
+
+namespace sh
+{
+
+class TIntermNode;
+class TSymbolTable;
+
+void RemoveDynamicIndexing(TIntermNode *root,
+                           unsigned int *temporaryIndex,
+                           const TSymbolTable &symbolTable,
+                           int shaderVersion);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_
diff --git a/src/third_party/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp b/src/third_party/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp
new file mode 100644
index 0000000..d5e12ba
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/RemoveInvariantDeclaration.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// An AST traverser that removes invariant declaration for input in fragment shader
+// when GLSL >= 4.20 and for output in vertex shader when GLSL < 4.2.
+class RemoveInvariantDeclarationTraverser : public TIntermTraverser
+{
+  public:
+    RemoveInvariantDeclarationTraverser() : TIntermTraverser(true, false, false) {}
+
+  private:
+    bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override
+    {
+        TIntermSequence emptyReplacement;
+        mMultiReplacements.push_back(
+            NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement));
+        return false;
+    }
+};
+
+}  // anonymous namespace
+
+void RemoveInvariantDeclaration(TIntermNode *root)
+{
+    RemoveInvariantDeclarationTraverser traverser;
+    root->traverse(&traverser);
+    traverser.updateTree();
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/RemoveInvariantDeclaration.h b/src/third_party/angle/src/compiler/translator/RemoveInvariantDeclaration.h
new file mode 100644
index 0000000..cf9d4aa
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RemoveInvariantDeclaration.h
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_
+#define COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void RemoveInvariantDeclaration(TIntermNode *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_
diff --git a/src/third_party/angle/src/compiler/translator/RemovePow.cpp b/src/third_party/angle/src/compiler/translator/RemovePow.cpp
new file mode 100644
index 0000000..ca7d08d
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RemovePow.cpp
@@ -0,0 +1,97 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemovePow is an AST traverser to convert pow(x, y) built-in calls where y is a
+// constant to exp2(y * log2(x)). This works around an issue in NVIDIA 311 series
+// OpenGL drivers.
+//
+
+#include "compiler/translator/RemovePow.h"
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+bool IsProblematicPow(TIntermTyped *node)
+{
+    TIntermAggregate *agg = node->getAsAggregate();
+    if (agg != nullptr && agg->getOp() == EOpPow)
+    {
+        ASSERT(agg->getSequence()->size() == 2);
+        return agg->getSequence()->at(1)->getAsConstantUnion() != nullptr;
+    }
+    return false;
+}
+
+// Traverser that converts all pow operations simultaneously.
+class RemovePowTraverser : public TIntermTraverser
+{
+  public:
+    RemovePowTraverser();
+
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+
+    void nextIteration() { mNeedAnotherIteration = false; }
+    bool needAnotherIteration() const { return mNeedAnotherIteration; }
+
+  protected:
+    bool mNeedAnotherIteration;
+};
+
+RemovePowTraverser::RemovePowTraverser()
+    : TIntermTraverser(true, false, false), mNeedAnotherIteration(false)
+{
+}
+
+bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (IsProblematicPow(node))
+    {
+        TIntermTyped *x = node->getSequence()->at(0)->getAsTyped();
+        TIntermTyped *y = node->getSequence()->at(1)->getAsTyped();
+
+        TIntermUnary *log = new TIntermUnary(EOpLog2, x);
+        log->setLine(node->getLine());
+
+        TOperator op       = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType());
+        TIntermBinary *mul = new TIntermBinary(op, y, log);
+        mul->setLine(node->getLine());
+
+        TIntermUnary *exp = new TIntermUnary(EOpExp2, mul);
+        exp->setLine(node->getLine());
+
+        queueReplacement(node, exp, OriginalNode::IS_DROPPED);
+
+        // If the x parameter also needs to be replaced, we need to do that in another traversal,
+        // since it's parent node will change in a way that's not handled correctly by updateTree().
+        if (IsProblematicPow(x))
+        {
+            mNeedAnotherIteration = true;
+            return false;
+        }
+    }
+    return true;
+}
+
+}  // namespace
+
+void RemovePow(TIntermNode *root)
+{
+    RemovePowTraverser traverser;
+    // Iterate as necessary, and reset the traverser between iterations.
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        traverser.updateTree();
+    } while (traverser.needAnotherIteration());
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/RemovePow.h b/src/third_party/angle/src/compiler/translator/RemovePow.h
new file mode 100644
index 0000000..3cd8498
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RemovePow.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemovePow is an AST traverser to convert pow(x, y) built-in calls where y is a
+// constant to exp2(y * log2(x)). This works around an issue in NVIDIA 311 series
+// OpenGL drivers.
+//
+
+#ifndef COMPILER_TRANSLATOR_REMOVEPOW_H_
+#define COMPILER_TRANSLATOR_REMOVEPOW_H_
+
+namespace sh
+{
+class TIntermNode;
+
+void RemovePow(TIntermNode *root);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_REMOVEPOW_H_
diff --git a/src/third_party/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/third_party/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
new file mode 100644
index 0000000..6c108a1
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
@@ -0,0 +1,174 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/RemoveSwitchFallThrough.h"
+
+namespace sh
+{
+
+TIntermBlock *RemoveSwitchFallThrough::removeFallThrough(TIntermBlock *statementList)
+{
+    RemoveSwitchFallThrough rm(statementList);
+    ASSERT(statementList);
+    statementList->traverse(&rm);
+    bool lastStatementWasBreak = rm.mLastStatementWasBreak;
+    rm.mLastStatementWasBreak  = true;
+    rm.handlePreviousCase();
+    if (!lastStatementWasBreak)
+    {
+        TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr);
+        rm.mStatementListOut->getSequence()->push_back(finalBreak);
+    }
+    return rm.mStatementListOut;
+}
+
+RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermBlock *statementList)
+    : TIntermTraverser(true, false, false),
+      mStatementList(statementList),
+      mLastStatementWasBreak(false),
+      mPreviousCase(nullptr)
+{
+    mStatementListOut = new TIntermBlock();
+}
+
+void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node)
+{
+    // Note that this assumes that switch statements which don't begin by a case statement
+    // have already been weeded out in validation.
+    mPreviousCase->getSequence()->push_back(node);
+    mLastStatementWasBreak = false;
+}
+
+void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node)
+{
+    // Conditions of case labels are not traversed, so this is some other constant
+    // Could be just a statement like "0;"
+    mPreviousCase->getSequence()->push_back(node);
+    mLastStatementWasBreak = false;
+}
+
+bool RemoveSwitchFallThrough::visitBinary(Visit, TIntermBinary *node)
+{
+    mPreviousCase->getSequence()->push_back(node);
+    mLastStatementWasBreak = false;
+    return false;
+}
+
+bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node)
+{
+    mPreviousCase->getSequence()->push_back(node);
+    mLastStatementWasBreak = false;
+    return false;
+}
+
+bool RemoveSwitchFallThrough::visitTernary(Visit, TIntermTernary *node)
+{
+    mPreviousCase->getSequence()->push_back(node);
+    mLastStatementWasBreak = false;
+    return false;
+}
+
+bool RemoveSwitchFallThrough::visitIfElse(Visit, TIntermIfElse *node)
+{
+    mPreviousCase->getSequence()->push_back(node);
+    mLastStatementWasBreak = false;
+    return false;
+}
+
+bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node)
+{
+    mPreviousCase->getSequence()->push_back(node);
+    mLastStatementWasBreak = false;
+    // Don't go into nested switch statements
+    return false;
+}
+
+void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t startIndex)
+{
+    for (size_t i = startIndex; i < sequence->size(); ++i)
+    {
+        mStatementListOut->getSequence()->push_back(sequence->at(i));
+    }
+}
+
+void RemoveSwitchFallThrough::handlePreviousCase()
+{
+    if (mPreviousCase)
+        mCasesSharingBreak.push_back(mPreviousCase);
+    if (mLastStatementWasBreak)
+    {
+        bool labelsWithNoStatements = true;
+        for (size_t i = 0; i < mCasesSharingBreak.size(); ++i)
+        {
+            if (mCasesSharingBreak.at(i)->getSequence()->size() > 1)
+            {
+                labelsWithNoStatements = false;
+            }
+            if (labelsWithNoStatements)
+            {
+                // Fall-through is allowed in case the label has no statements.
+                outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0);
+            }
+            else
+            {
+                // Include all the statements that this case can fall through under the same label.
+                for (size_t j = i; j < mCasesSharingBreak.size(); ++j)
+                {
+                    size_t startIndex =
+                        j > i ? 1 : 0;  // Add the label only from the first sequence.
+                    outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex);
+                }
+            }
+        }
+        mCasesSharingBreak.clear();
+    }
+    mLastStatementWasBreak = false;
+    mPreviousCase          = nullptr;
+}
+
+bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node)
+{
+    handlePreviousCase();
+    mPreviousCase = new TIntermBlock();
+    mPreviousCase->getSequence()->push_back(node);
+    // Don't traverse the condition of the case statement
+    return false;
+}
+
+bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node)
+{
+    mPreviousCase->getSequence()->push_back(node);
+    mLastStatementWasBreak = false;
+    return false;
+}
+
+bool RemoveSwitchFallThrough::visitBlock(Visit, TIntermBlock *node)
+{
+    if (node != mStatementList)
+    {
+        mPreviousCase->getSequence()->push_back(node);
+        mLastStatementWasBreak = false;
+        return false;
+    }
+    return true;
+}
+
+bool RemoveSwitchFallThrough::visitLoop(Visit, TIntermLoop *node)
+{
+    mPreviousCase->getSequence()->push_back(node);
+    mLastStatementWasBreak = false;
+    return false;
+}
+
+bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node)
+{
+    mPreviousCase->getSequence()->push_back(node);
+    // TODO: Verify that accepting return or continue statements here doesn't cause problems.
+    mLastStatementWasBreak = true;
+    return false;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/RemoveSwitchFallThrough.h b/src/third_party/angle/src/compiler/translator/RemoveSwitchFallThrough.h
new file mode 100644
index 0000000..a19c437
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RemoveSwitchFallThrough.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
+#define COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+class RemoveSwitchFallThrough : public TIntermTraverser
+{
+  public:
+    // When given a statementList from a switch AST node, return an updated
+    // statementList that has fall-through removed.
+    static TIntermBlock *removeFallThrough(TIntermBlock *statementList);
+
+  private:
+    RemoveSwitchFallThrough(TIntermBlock *statementList);
+
+    void visitSymbol(TIntermSymbol *node) override;
+    void visitConstantUnion(TIntermConstantUnion *node) override;
+    bool visitBinary(Visit, TIntermBinary *node) override;
+    bool visitUnary(Visit, TIntermUnary *node) override;
+    bool visitTernary(Visit visit, TIntermTernary *node) override;
+    bool visitIfElse(Visit visit, TIntermIfElse *node) override;
+    bool visitSwitch(Visit, TIntermSwitch *node) override;
+    bool visitCase(Visit, TIntermCase *node) override;
+    bool visitAggregate(Visit, TIntermAggregate *node) override;
+    bool visitBlock(Visit, TIntermBlock *node) override;
+    bool visitLoop(Visit, TIntermLoop *node) override;
+    bool visitBranch(Visit, TIntermBranch *node) override;
+
+    void outputSequence(TIntermSequence *sequence, size_t startIndex);
+    void handlePreviousCase();
+
+    TIntermBlock *mStatementList;
+    TIntermBlock *mStatementListOut;
+    bool mLastStatementWasBreak;
+    TIntermBlock *mPreviousCase;
+    std::vector<TIntermBlock *> mCasesSharingBreak;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
diff --git a/src/third_party/angle/src/compiler/translator/RewriteDoWhile.cpp b/src/third_party/angle/src/compiler/translator/RewriteDoWhile.cpp
new file mode 100644
index 0000000..7999cbf
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteDoWhile.cpp
@@ -0,0 +1,159 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RewriteDoWhile.cpp: rewrites do-while loops using another equivalent
+// construct.
+
+#include "compiler/translator/RewriteDoWhile.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// An AST traverser that rewrites loops of the form
+//   do {
+//     CODE;
+//   } while (CONDITION)
+//
+// to loops of the form
+//   bool temp = false;
+//   while (true) {
+//     if (temp) {
+//       if (!CONDITION) {
+//         break;
+//       }
+//     }
+//     temp = true;
+//     CODE;
+//   }
+//
+// The reason we don't use a simpler form, with for example just (temp && !CONDITION) in the
+// while condition, is that short-circuit is often badly supported by driver shader compiler.
+// The double if has the same effect, but forces shader compilers to behave.
+//
+// TODO(cwallez) when UnfoldShortCircuitIntoIf handles loops correctly, revisit this as we might
+// be able to use while (temp || CONDITION) with temp initially set to true then run
+// UnfoldShortCircuitIntoIf
+class DoWhileRewriter : public TIntermTraverser
+{
+  public:
+    DoWhileRewriter() : TIntermTraverser(true, false, false) {}
+
+    bool visitBlock(Visit, TIntermBlock *node) override
+    {
+        // A well-formed AST can only have do-while inside TIntermBlock. By doing a prefix traversal
+        // we are able to replace the do-while in the sequence directly as the content of the
+        // do-while will be traversed later.
+
+        TIntermSequence *statements = node->getSequence();
+
+        // The statements vector will have new statements inserted when we encounter a do-while,
+        // which prevents us from using a range-based for loop. Using the usual i++ works, as
+        // the (two) new statements inserted replace the statement at the current position.
+        for (size_t i = 0; i < statements->size(); i++)
+        {
+            TIntermNode *statement = (*statements)[i];
+            TIntermLoop *loop      = statement->getAsLoopNode();
+
+            if (loop == nullptr || loop->getType() != ELoopDoWhile)
+            {
+                continue;
+            }
+
+            TType boolType = TType(EbtBool);
+
+            // bool temp = false;
+            TIntermDeclaration *tempDeclaration = nullptr;
+            {
+                TConstantUnion *falseConstant = new TConstantUnion();
+                falseConstant->setBConst(false);
+                TIntermTyped *falseValue = new TIntermConstantUnion(falseConstant, boolType);
+
+                tempDeclaration = createTempInitDeclaration(falseValue);
+            }
+
+            // temp = true;
+            TIntermBinary *assignTrue = nullptr;
+            {
+                TConstantUnion *trueConstant = new TConstantUnion();
+                trueConstant->setBConst(true);
+                TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType);
+
+                assignTrue = createTempAssignment(trueValue);
+            }
+
+            // if (temp) {
+            //   if (!CONDITION) {
+            //     break;
+            //   }
+            // }
+            TIntermIfElse *breakIf = nullptr;
+            {
+                TIntermBranch *breakStatement = new TIntermBranch(EOpBreak, nullptr);
+
+                TIntermBlock *breakBlock = new TIntermBlock();
+                breakBlock->getSequence()->push_back(breakStatement);
+
+                TIntermUnary *negatedCondition =
+                    new TIntermUnary(EOpLogicalNot, loop->getCondition());
+
+                TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr);
+
+                TIntermBlock *innerIfBlock = new TIntermBlock();
+                innerIfBlock->getSequence()->push_back(innerIf);
+
+                breakIf = new TIntermIfElse(createTempSymbol(boolType), innerIfBlock, nullptr);
+            }
+
+            // Assemble the replacement loops, reusing the do-while loop's body and inserting our
+            // statements at the front.
+            TIntermLoop *newLoop = nullptr;
+            {
+                TConstantUnion *trueConstant = new TConstantUnion();
+                trueConstant->setBConst(true);
+                TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType);
+
+                TIntermBlock *body = loop->getBody();
+                if (body == nullptr)
+                {
+                    body = new TIntermBlock();
+                }
+                auto sequence = body->getSequence();
+                sequence->insert(sequence->begin(), assignTrue);
+                sequence->insert(sequence->begin(), breakIf);
+
+                newLoop = new TIntermLoop(ELoopWhile, nullptr, trueValue, nullptr, body);
+            }
+
+            TIntermSequence replacement;
+            replacement.push_back(tempDeclaration);
+            replacement.push_back(newLoop);
+
+            node->replaceChildNodeWithMultiple(loop, replacement);
+
+            nextTemporaryIndex();
+        }
+        return true;
+    }
+};
+
+}  // anonymous namespace
+
+void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex)
+{
+    ASSERT(temporaryIndex != 0);
+
+    DoWhileRewriter rewriter;
+    rewriter.useTemporaryIndex(temporaryIndex);
+
+    root->traverse(&rewriter);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/RewriteDoWhile.h b/src/third_party/angle/src/compiler/translator/RewriteDoWhile.h
new file mode 100644
index 0000000..91a7958
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteDoWhile.h
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RewriteDoWhile.h: rewrite do-while loops as while loops to work around
+// driver bugs
+
+#ifndef COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
+#define COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
+
+namespace sh
+{
+class TIntermNode;
+void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
diff --git a/src/third_party/angle/src/compiler/translator/RewriteElseBlocks.cpp b/src/third_party/angle/src/compiler/translator/RewriteElseBlocks.cpp
new file mode 100644
index 0000000..ab14fcc
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteElseBlocks.cpp
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RewriteElseBlocks.cpp: Implementation for tree transform to change
+//   all if-else blocks to if-if blocks.
+//
+
+#include "compiler/translator/RewriteElseBlocks.h"
+
+#include "compiler/translator/Intermediate.h"
+#include "compiler/translator/NodeSearch.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class ElseBlockRewriter : public TIntermTraverser
+{
+  public:
+    ElseBlockRewriter();
+
+  protected:
+    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *aggregate) override;
+    bool visitBlock(Visit visit, TIntermBlock *block) override;
+
+  private:
+    const TType *mFunctionType;
+
+    TIntermNode *rewriteIfElse(TIntermIfElse *ifElse);
+};
+
+ElseBlockRewriter::ElseBlockRewriter() : TIntermTraverser(true, false, true), mFunctionType(nullptr)
+{
+}
+
+bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+{
+    // Store the current function context (see comment below)
+    mFunctionType = ((visit == PreVisit) ? &node->getFunctionPrototype()->getType() : nullptr);
+    return true;
+}
+
+bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node)
+{
+    if (visit == PostVisit)
+    {
+        for (size_t statementIndex = 0; statementIndex != node->getSequence()->size();
+             statementIndex++)
+        {
+            TIntermNode *statement = (*node->getSequence())[statementIndex];
+            TIntermIfElse *ifElse  = statement->getAsIfElseNode();
+            if (ifElse && ifElse->getFalseBlock() != nullptr)
+            {
+                (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
+            }
+        }
+    }
+    return true;
+}
+
+TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
+{
+    ASSERT(ifElse != nullptr);
+
+    nextTemporaryIndex();
+
+    TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
+
+    TIntermBlock *falseBlock = nullptr;
+
+    TType boolType(EbtBool, EbpUndefined, EvqTemporary);
+
+    if (ifElse->getFalseBlock())
+    {
+        TIntermBlock *negatedElse = nullptr;
+        // crbug.com/346463
+        // D3D generates error messages claiming a function has no return value, when rewriting
+        // an if-else clause that returns something non-void in a function. By appending dummy
+        // returns (that are unreachable) we can silence this compile error.
+        if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
+        {
+            TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name()
+                                                            : mFunctionType->getBasicString();
+            TString rawText        = "return (" + typeString + ")0";
+            TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
+            negatedElse            = new TIntermBlock();
+            negatedElse->getSequence()->push_back(returnNode);
+        }
+
+        TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
+        TIntermUnary *negatedCondition     = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
+        TIntermIfElse *falseIfElse =
+            new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
+        falseBlock = TIntermediate::EnsureBlock(falseIfElse);
+    }
+
+    TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
+    TIntermIfElse *newIfElse =
+        new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
+
+    TIntermBlock *block = new TIntermBlock();
+    block->getSequence()->push_back(storeCondition);
+    block->getSequence()->push_back(newIfElse);
+
+    return block;
+}
+}
+
+void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
+{
+    ElseBlockRewriter rewriter;
+    rewriter.useTemporaryIndex(temporaryIndex);
+    node->traverse(&rewriter);
+}
+}
diff --git a/src/third_party/angle/src/compiler/translator/RewriteElseBlocks.h b/src/third_party/angle/src/compiler/translator/RewriteElseBlocks.h
new file mode 100644
index 0000000..05a8634
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteElseBlocks.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RewriteElseBlocks.h: Prototype for tree transform to change
+//   all if-else blocks to if-if blocks.
+//
+
+#ifndef COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
+#define COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex);
+}
+
+#endif  // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
diff --git a/src/third_party/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp b/src/third_party/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp
new file mode 100644
index 0000000..13f834a
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright (c) 2016 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.
+//
+// Implementation of texelFetchOffset translation issue workaround.
+// See header for more info.
+
+#include "compiler/translator/RewriteTexelFetchOffset.h"
+
+#include "common/angleutils.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class Traverser : public TIntermTraverser
+{
+  public:
+    static void Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion);
+
+  private:
+    Traverser(const TSymbolTable &symbolTable, int shaderVersion);
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    void nextIteration();
+
+    const TSymbolTable *symbolTable;
+    const int shaderVersion;
+    bool mFound = false;
+};
+
+Traverser::Traverser(const TSymbolTable &symbolTable, int shaderVersion)
+    : TIntermTraverser(true, false, false), symbolTable(&symbolTable), shaderVersion(shaderVersion)
+{
+}
+
+// static
+void Traverser::Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion)
+{
+    Traverser traverser(symbolTable, shaderVersion);
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        if (traverser.mFound)
+        {
+            traverser.updateTree();
+        }
+    } while (traverser.mFound);
+}
+
+void Traverser::nextIteration()
+{
+    mFound = false;
+}
+
+bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (mFound)
+    {
+        return false;
+    }
+
+    // Decide if the node represents the call of texelFetchOffset.
+    if (node->getOp() != EOpCallBuiltInFunction)
+    {
+        return true;
+    }
+
+    if (node->getFunctionSymbolInfo()->getName() != "texelFetchOffset")
+    {
+        return true;
+    }
+
+    // Potential problem case detected, apply workaround.
+    const TIntermSequence *sequence = node->getSequence();
+    ASSERT(sequence->size() == 4u);
+
+    // Decide if the sampler is a 2DArray sampler. In that case position is ivec3 and offset is
+    // ivec2.
+    bool is2DArray = sequence->at(1)->getAsTyped()->getNominalSize() == 3 &&
+                     sequence->at(3)->getAsTyped()->getNominalSize() == 2;
+
+    // Create new node that represents the call of function texelFetch.
+    // Its argument list will be: texelFetch(sampler, Position+offset, lod).
+
+    TIntermSequence *texelFetchArguments = new TIntermSequence();
+
+    // sampler
+    texelFetchArguments->push_back(sequence->at(0));
+
+    // Position
+    TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped();
+    ASSERT(texCoordNode);
+
+    // offset
+    TIntermTyped *offsetNode = nullptr;
+    ASSERT(sequence->at(3)->getAsTyped());
+    if (is2DArray)
+    {
+        // For 2DArray samplers, Position is ivec3 and offset is ivec2;
+        // So offset must be converted into an ivec3 before being added to Position.
+        TIntermSequence *constructOffsetIvecArguments = new TIntermSequence();
+        constructOffsetIvecArguments->push_back(sequence->at(3)->getAsTyped());
+
+        TIntermTyped *zeroNode = TIntermTyped::CreateZero(TType(EbtInt));
+        constructOffsetIvecArguments->push_back(zeroNode);
+
+        offsetNode = TIntermAggregate::CreateConstructor(texCoordNode->getType(),
+                                                         constructOffsetIvecArguments);
+        offsetNode->setLine(texCoordNode->getLine());
+    }
+    else
+    {
+        offsetNode = sequence->at(3)->getAsTyped();
+    }
+
+    // Position+offset
+    TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode);
+    add->setLine(texCoordNode->getLine());
+    texelFetchArguments->push_back(add);
+
+    // lod
+    texelFetchArguments->push_back(sequence->at(2));
+
+    ASSERT(texelFetchArguments->size() == 3u);
+
+    // Get the symbol of the texel fetch function to use.
+    TString mangledName = TFunction::GetMangledNameFromCall("texelFetch", *texelFetchArguments);
+    TSymbol *texelFetchSymbol = symbolTable->findBuiltIn(mangledName, shaderVersion);
+    ASSERT(texelFetchSymbol && texelFetchSymbol->isFunction());
+
+    TIntermAggregate *texelFetchNode = TIntermAggregate::CreateBuiltInFunctionCall(
+        *static_cast<const TFunction *>(texelFetchSymbol), texelFetchArguments);
+    texelFetchNode->setLine(node->getLine());
+
+    // Replace the old node by this new node.
+    queueReplacement(node, texelFetchNode, OriginalNode::IS_DROPPED);
+    mFound = true;
+    return false;
+}
+
+}  // anonymous namespace
+
+void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion)
+{
+    // texelFetchOffset is only valid in GLSL 3.0 and later.
+    if (shaderVersion < 300)
+        return;
+
+    Traverser::Apply(root, symbolTable, shaderVersion);
+}
+
+}  // namespace sh
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/translator/RewriteTexelFetchOffset.h b/src/third_party/angle/src/compiler/translator/RewriteTexelFetchOffset.h
new file mode 100644
index 0000000..694d709
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteTexelFetchOffset.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2016 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.
+//
+// This mutating tree traversal works around an issue on the translation
+// from texelFetchOffset into HLSL function Load on INTEL drivers. It
+// works by translating texelFetchOffset into texelFetch:
+//
+// - From: texelFetchOffset(sampler, Position, lod, offset)
+// - To: texelFetch(sampler, Position+offset, lod)
+//
+// See http://anglebug.com/1469
+
+#ifndef COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_
+#define COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_
+
+class TIntermNode;
+class TSymbolTable;
+
+namespace sh
+{
+
+void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp b/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp
new file mode 100644
index 0000000..1350c5e
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class Traverser : public TIntermTraverser
+{
+  public:
+    static void Apply(TIntermNode *root);
+
+  private:
+    Traverser();
+    bool visitUnary(Visit visit, TIntermUnary *node) override;
+    void nextIteration();
+
+    bool mFound = false;
+};
+
+// static
+void Traverser::Apply(TIntermNode *root)
+{
+    Traverser traverser;
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        if (traverser.mFound)
+        {
+            traverser.updateTree();
+        }
+    } while (traverser.mFound);
+}
+
+Traverser::Traverser() : TIntermTraverser(true, false, false)
+{
+}
+
+void Traverser::nextIteration()
+{
+    mFound = false;
+}
+
+bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+    if (mFound)
+    {
+        return false;
+    }
+
+    // Detect if the current operator is unary minus operator.
+    if (node->getOp() != EOpNegative)
+    {
+        return true;
+    }
+
+    // Detect if the current operand is a float variable.
+    TIntermTyped *fValue = node->getOperand();
+    if (!fValue->getType().isScalarFloat())
+    {
+        return true;
+    }
+
+    // 0.0 - float
+    TIntermTyped *zero = TIntermTyped::CreateZero(fValue->getType());
+    zero->setLine(fValue->getLine());
+    TIntermBinary *sub = new TIntermBinary(EOpSub, zero, fValue);
+    sub->setLine(fValue->getLine());
+
+    queueReplacement(node, sub, OriginalNode::IS_DROPPED);
+
+    mFound = true;
+    return false;
+}
+
+}  // anonymous namespace
+
+void RewriteUnaryMinusOperatorFloat(TIntermNode *root)
+{
+    Traverser::Apply(root);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h b/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h
new file mode 100644
index 0000000..ccbfbcb
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2016 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.
+//
+// Rewrite "-float" to "0.0 - float" to work around unary minus operator on float issue on Intel Mac
+// OSX 10.11.
+
+#ifndef COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_
+#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void RewriteUnaryMinusOperatorFloat(TIntermNode *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_
diff --git a/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp b/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp
new file mode 100644
index 0000000..ef708cb
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 2016 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.
+//
+// Implementation of evaluating unary integer variable bug workaround.
+// See header for more info.
+
+#include "compiler/translator/RewriteUnaryMinusOperatorInt.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class Traverser : public TIntermTraverser
+{
+  public:
+    static void Apply(TIntermNode *root);
+
+  private:
+    Traverser();
+    bool visitUnary(Visit visit, TIntermUnary *node) override;
+    void nextIteration();
+
+    bool mFound = false;
+};
+
+// static
+void Traverser::Apply(TIntermNode *root)
+{
+    Traverser traverser;
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        if (traverser.mFound)
+        {
+            traverser.updateTree();
+        }
+    } while (traverser.mFound);
+}
+
+Traverser::Traverser() : TIntermTraverser(true, false, false)
+{
+}
+
+void Traverser::nextIteration()
+{
+    mFound = false;
+}
+
+bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+    if (mFound)
+    {
+        return false;
+    }
+
+    // Decide if the current unary operator is unary minus.
+    if (node->getOp() != EOpNegative)
+    {
+        return true;
+    }
+
+    // Decide if the current operand is an integer variable.
+    TIntermTyped *opr = node->getOperand();
+    if (!opr->getType().isScalarInt())
+    {
+        return true;
+    }
+
+    // Potential problem case detected, apply workaround: -(int) -> ~(int) + 1.
+    // ~(int)
+    TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr);
+    bitwiseNot->setLine(opr->getLine());
+
+    // Constant 1 (or 1u)
+    TConstantUnion *one = new TConstantUnion();
+    if (opr->getType().getBasicType() == EbtInt)
+    {
+        one->setIConst(1);
+    }
+    else
+    {
+        one->setUConst(1u);
+    }
+    TIntermConstantUnion *oneNode = new TIntermConstantUnion(one, opr->getType());
+    oneNode->getTypePointer()->setQualifier(EvqConst);
+    oneNode->setLine(opr->getLine());
+
+    // ~(int) + 1
+    TIntermBinary *add = new TIntermBinary(EOpAdd, bitwiseNot, oneNode);
+    add->setLine(opr->getLine());
+
+    queueReplacement(node, add, OriginalNode::IS_DROPPED);
+
+    mFound = true;
+    return false;
+}
+
+}  // anonymous namespace
+
+void RewriteUnaryMinusOperatorInt(TIntermNode *root)
+{
+    Traverser::Apply(root);
+}
+
+}  // namespace sh
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h b/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h
new file mode 100644
index 0000000..50f0c44
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 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.
+//
+// This mutating tree traversal works around a bug on evaluating unary
+// integer variable on Intel D3D driver. It works by rewriting -(int) to
+// ~(int) + 1 when evaluating unary integer variables.
+
+#ifndef COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_
+#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void RewriteUnaryMinusOperatorInt(TIntermNode *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/third_party/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
new file mode 100644
index 0000000..e09241a
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
@@ -0,0 +1,239 @@
+//
+// 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.
+//
+// Scalarize vector and matrix constructor args, so that vectors built from components don't have
+// matrix arguments, and matrices built from components don't have vector arguments. This avoids
+// driver bugs around vector and matrix constructors.
+//
+
+#include "common/debug.h"
+#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
+
+#include <algorithm>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+bool ContainsMatrixNode(const TIntermSequence &sequence)
+{
+    for (size_t ii = 0; ii < sequence.size(); ++ii)
+    {
+        TIntermTyped *node = sequence[ii]->getAsTyped();
+        if (node && node->isMatrix())
+            return true;
+    }
+    return false;
+}
+
+bool ContainsVectorNode(const TIntermSequence &sequence)
+{
+    for (size_t ii = 0; ii < sequence.size(); ++ii)
+    {
+        TIntermTyped *node = sequence[ii]->getAsTyped();
+        if (node && node->isVector())
+            return true;
+    }
+    return false;
+}
+
+TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index)
+{
+    return new TIntermBinary(EOpIndexDirect, symbolNode, TIntermTyped::CreateIndexNode(index));
+}
+
+TIntermBinary *ConstructMatrixIndexBinaryNode(TIntermSymbol *symbolNode, int colIndex, int rowIndex)
+{
+    TIntermBinary *colVectorNode = ConstructVectorIndexBinaryNode(symbolNode, colIndex);
+
+    return new TIntermBinary(EOpIndexDirect, colVectorNode,
+                             TIntermTyped::CreateIndexNode(rowIndex));
+}
+
+class ScalarizeArgsTraverser : public TIntermTraverser
+{
+  public:
+    ScalarizeArgsTraverser(sh::GLenum shaderType,
+                           bool fragmentPrecisionHigh,
+                           unsigned int *temporaryIndex)
+        : TIntermTraverser(true, false, false),
+          mShaderType(shaderType),
+          mFragmentPrecisionHigh(fragmentPrecisionHigh)
+    {
+        useTemporaryIndex(temporaryIndex);
+    }
+
+  protected:
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    bool visitBlock(Visit visit, TIntermBlock *node) override;
+
+  private:
+    void scalarizeArgs(TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix);
+
+    // If we have the following code:
+    //   mat4 m(0);
+    //   vec4 v(1, m);
+    // We will rewrite to:
+    //   mat4 m(0);
+    //   mat4 s0 = m;
+    //   vec4 v(1, s0[0][0], s0[0][1], s0[0][2]);
+    // This function is to create nodes for "mat4 s0 = m;" and insert it to the code sequence. This
+    // way the possible side effects of the constructor argument will only be evaluated once.
+    void createTempVariable(TIntermTyped *original);
+
+    std::vector<TIntermSequence> mBlockStack;
+
+    sh::GLenum mShaderType;
+    bool mFragmentPrecisionHigh;
+};
+
+bool ScalarizeArgsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (visit == PreVisit && node->getOp() == EOpConstruct)
+    {
+        if (node->getType().isVector() && ContainsMatrixNode(*(node->getSequence())))
+            scalarizeArgs(node, false, true);
+        else if (node->getType().isMatrix() && ContainsVectorNode(*(node->getSequence())))
+            scalarizeArgs(node, true, false);
+    }
+    return true;
+}
+
+bool ScalarizeArgsTraverser::visitBlock(Visit visit, TIntermBlock *node)
+{
+    mBlockStack.push_back(TIntermSequence());
+    {
+        for (TIntermNode *child : *node->getSequence())
+        {
+            ASSERT(child != nullptr);
+            child->traverse(this);
+            mBlockStack.back().push_back(child);
+        }
+    }
+    if (mBlockStack.back().size() > node->getSequence()->size())
+    {
+        node->getSequence()->clear();
+        *(node->getSequence()) = mBlockStack.back();
+    }
+    mBlockStack.pop_back();
+    return false;
+}
+
+void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate,
+                                           bool scalarizeVector,
+                                           bool scalarizeMatrix)
+{
+    ASSERT(aggregate);
+    ASSERT(!aggregate->isArray());
+    int size                  = static_cast<int>(aggregate->getType().getObjectSize());
+    TIntermSequence *sequence = aggregate->getSequence();
+    TIntermSequence original(*sequence);
+    sequence->clear();
+    for (size_t ii = 0; ii < original.size(); ++ii)
+    {
+        ASSERT(size > 0);
+        TIntermTyped *node = original[ii]->getAsTyped();
+        ASSERT(node);
+        createTempVariable(node);
+        if (node->isScalar())
+        {
+            sequence->push_back(createTempSymbol(node->getType()));
+            size--;
+        }
+        else if (node->isVector())
+        {
+            if (scalarizeVector)
+            {
+                int repeat = std::min(size, node->getNominalSize());
+                size -= repeat;
+                for (int index = 0; index < repeat; ++index)
+                {
+                    TIntermSymbol *symbolNode = createTempSymbol(node->getType());
+                    TIntermBinary *newNode    = ConstructVectorIndexBinaryNode(symbolNode, index);
+                    sequence->push_back(newNode);
+                }
+            }
+            else
+            {
+                TIntermSymbol *symbolNode = createTempSymbol(node->getType());
+                sequence->push_back(symbolNode);
+                size -= node->getNominalSize();
+            }
+        }
+        else
+        {
+            ASSERT(node->isMatrix());
+            if (scalarizeMatrix)
+            {
+                int colIndex = 0, rowIndex = 0;
+                int repeat = std::min(size, node->getCols() * node->getRows());
+                size -= repeat;
+                while (repeat > 0)
+                {
+                    TIntermSymbol *symbolNode = createTempSymbol(node->getType());
+                    TIntermBinary *newNode =
+                        ConstructMatrixIndexBinaryNode(symbolNode, colIndex, rowIndex);
+                    sequence->push_back(newNode);
+                    rowIndex++;
+                    if (rowIndex >= node->getRows())
+                    {
+                        rowIndex = 0;
+                        colIndex++;
+                    }
+                    repeat--;
+                }
+            }
+            else
+            {
+                TIntermSymbol *symbolNode = createTempSymbol(node->getType());
+                sequence->push_back(symbolNode);
+                size -= node->getCols() * node->getRows();
+            }
+        }
+    }
+}
+
+void ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original)
+{
+    ASSERT(original);
+    nextTemporaryIndex();
+    TIntermDeclaration *decl = createTempInitDeclaration(original);
+
+    TType type = original->getType();
+    if (mShaderType == GL_FRAGMENT_SHADER && type.getBasicType() == EbtFloat &&
+        type.getPrecision() == EbpUndefined)
+    {
+        // We use the highest available precision for the temporary variable
+        // to avoid computing the actual precision using the rules defined
+        // in GLSL ES 1.0 Section 4.5.2.
+        TIntermBinary *init = decl->getSequence()->at(0)->getAsBinaryNode();
+        init->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium);
+        init->getLeft()->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh
+                                                                               : EbpMedium);
+    }
+
+    ASSERT(mBlockStack.size() > 0);
+    TIntermSequence &sequence = mBlockStack.back();
+    sequence.push_back(decl);
+}
+
+}  // namespace anonymous
+
+void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root,
+                                       sh::GLenum shaderType,
+                                       bool fragmentPrecisionHigh,
+                                       unsigned int *temporaryIndex)
+{
+    ScalarizeArgsTraverser scalarizer(shaderType, fragmentPrecisionHigh, temporaryIndex);
+    root->traverse(&scalarizer);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/third_party/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
new file mode 100644
index 0000000..14bbbe1
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
@@ -0,0 +1,26 @@
+//
+// 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.
+//
+// Scalarize vector and matrix constructor args, so that vectors built from components don't have
+// matrix arguments, and matrices built from components don't have vector arguments. This avoids
+// driver bugs around vector and matrix constructors.
+//
+
+#ifndef COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
+#define COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+class TIntermBlock;
+
+void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root,
+                                       sh::GLenum shaderType,
+                                       bool fragmentPrecisionHigh,
+                                       unsigned int *temporaryIndex);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
diff --git a/src/third_party/angle/src/compiler/translator/SearchSymbol.cpp b/src/third_party/angle/src/compiler/translator/SearchSymbol.cpp
new file mode 100644
index 0000000..34c644d
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SearchSymbol.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SearchSymbol is an AST traverser to detect the use of a given symbol name
+//
+
+#include "compiler/translator/SearchSymbol.h"
+
+#include "compiler/translator/InfoSink.h"
+
+namespace sh
+{
+SearchSymbol::SearchSymbol(const TString &symbol)
+    : TIntermTraverser(true, false, false), mSymbol(symbol)
+{
+    match = false;
+}
+
+void SearchSymbol::traverse(TIntermNode *node)
+{
+    node->traverse(this);
+}
+
+void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode)
+{
+    if (symbolNode->getSymbol() == mSymbol)
+    {
+        match = true;
+    }
+}
+
+bool SearchSymbol::foundMatch() const
+{
+    return match;
+}
+}
diff --git a/src/third_party/angle/src/compiler/translator/SearchSymbol.h b/src/third_party/angle/src/compiler/translator/SearchSymbol.h
new file mode 100644
index 0000000..4fbea8c
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SearchSymbol.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SearchSymbol is an AST traverser to detect the use of a given symbol name
+//
+
+#ifndef COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
+#define COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
+class SearchSymbol : public TIntermTraverser
+{
+  public:
+    SearchSymbol(const TString &symbol);
+
+    void traverse(TIntermNode *node);
+    void visitSymbol(TIntermSymbol *symbolNode) override;
+
+    bool foundMatch() const;
+
+  protected:
+    const TString &mSymbol;
+    bool match;
+};
+}
+
+#endif  // COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
diff --git a/src/third_party/angle/src/compiler/translator/SeparateArrayInitialization.cpp b/src/third_party/angle/src/compiler/translator/SeparateArrayInitialization.cpp
new file mode 100644
index 0000000..fe25823
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SeparateArrayInitialization.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The SeparateArrayInitialization function splits each array initialization into a declaration and
+// an assignment.
+// Example:
+//     type[n] a = initializer;
+// will effectively become
+//     type[n] a;
+//     a = initializer;
+//
+// Note that if the array is declared as const, the initialization may still be split, making the
+// AST technically invalid. Because of that this transformation should only be used when subsequent
+// stages don't care about const qualifiers. However, the initialization will not be split if the
+// initializer can be written as a HLSL literal.
+
+#include "compiler/translator/SeparateArrayInitialization.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/OutputHLSL.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class SeparateArrayInitTraverser : private TIntermTraverser
+{
+  public:
+    static void apply(TIntermNode *root);
+
+  private:
+    SeparateArrayInitTraverser();
+    bool visitDeclaration(Visit, TIntermDeclaration *node) override;
+};
+
+void SeparateArrayInitTraverser::apply(TIntermNode *root)
+{
+    SeparateArrayInitTraverser separateInit;
+    root->traverse(&separateInit);
+    separateInit.updateTree();
+}
+
+SeparateArrayInitTraverser::SeparateArrayInitTraverser() : TIntermTraverser(true, false, false)
+{
+}
+
+bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
+{
+    TIntermSequence *sequence = node->getSequence();
+    TIntermBinary *initNode   = sequence->back()->getAsBinaryNode();
+    if (initNode != nullptr && initNode->getOp() == EOpInitialize)
+    {
+        TIntermTyped *initializer = initNode->getRight();
+        if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer))
+        {
+            // We rely on that array declarations have been isolated to single declarations.
+            ASSERT(sequence->size() == 1);
+            TIntermTyped *symbol      = initNode->getLeft();
+            TIntermBlock *parentBlock = getParentNode()->getAsBlock();
+            ASSERT(parentBlock != nullptr);
+
+            TIntermSequence replacements;
+
+            TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
+            replacementDeclaration->appendDeclarator(symbol);
+            replacementDeclaration->setLine(symbol->getLine());
+            replacements.push_back(replacementDeclaration);
+
+            TIntermBinary *replacementAssignment =
+                new TIntermBinary(EOpAssign, symbol, initializer);
+            replacementAssignment->setLine(symbol->getLine());
+            replacements.push_back(replacementAssignment);
+
+            mMultiReplacements.push_back(
+                NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
+        }
+    }
+    return false;
+}
+
+}  // namespace
+
+void SeparateArrayInitialization(TIntermNode *root)
+{
+    SeparateArrayInitTraverser::apply(root);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/SeparateArrayInitialization.h b/src/third_party/angle/src/compiler/translator/SeparateArrayInitialization.h
new file mode 100644
index 0000000..3a9bb55
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SeparateArrayInitialization.h
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The SeparateArrayInitialization function splits each array initialization into a declaration and
+// an assignment.
+// Example:
+//     type[n] a = initializer;
+// will effectively become
+//     type[n] a;
+//     a = initializer;
+//
+// Note that if the array is declared as const, the initialization may still be split, making the
+// AST technically invalid. Because of that this transformation should only be used when subsequent
+// stages don't care about const qualifiers. However, the initialization will not be split if the
+// initializer can be written as a HLSL literal.
+
+#ifndef COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_
+#define COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_
+
+namespace sh
+{
+class TIntermNode;
+
+void SeparateArrayInitialization(TIntermNode *root);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_
diff --git a/src/third_party/angle/src/compiler/translator/SeparateDeclarations.cpp b/src/third_party/angle/src/compiler/translator/SeparateDeclarations.cpp
new file mode 100644
index 0000000..93c8b38
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SeparateDeclarations.cpp
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The SeparateDeclarations function processes declarations, so that in the end each declaration
+// contains only one declarator.
+// This is useful as an intermediate step when initialization needs to be separated from
+// declaration, or when things need to be unfolded out of the initializer.
+// Example:
+//     int a[1] = int[1](1), b[1] = int[1](2);
+// gets transformed when run through this class into the AST equivalent of:
+//     int a[1] = int[1](1);
+//     int b[1] = int[1](2);
+
+#include "compiler/translator/SeparateDeclarations.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class SeparateDeclarationsTraverser : private TIntermTraverser
+{
+  public:
+    static void apply(TIntermNode *root);
+
+  private:
+    SeparateDeclarationsTraverser();
+    bool visitDeclaration(Visit, TIntermDeclaration *node) override;
+};
+
+void SeparateDeclarationsTraverser::apply(TIntermNode *root)
+{
+    SeparateDeclarationsTraverser separateDecl;
+    root->traverse(&separateDecl);
+    separateDecl.updateTree();
+}
+
+SeparateDeclarationsTraverser::SeparateDeclarationsTraverser()
+    : TIntermTraverser(true, false, false)
+{
+}
+
+bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
+{
+    TIntermSequence *sequence = node->getSequence();
+    if (sequence->size() > 1)
+    {
+        TIntermBlock *parentBlock = getParentNode()->getAsBlock();
+        ASSERT(parentBlock != nullptr);
+
+        TIntermSequence replacementDeclarations;
+        for (size_t ii = 0; ii < sequence->size(); ++ii)
+        {
+            TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
+
+            replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped());
+            replacementDeclaration->setLine(sequence->at(ii)->getLine());
+            replacementDeclarations.push_back(replacementDeclaration);
+        }
+
+        mMultiReplacements.push_back(
+            NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations));
+    }
+    return false;
+}
+
+}  // namespace
+
+void SeparateDeclarations(TIntermNode *root)
+{
+    SeparateDeclarationsTraverser::apply(root);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/SeparateDeclarations.h b/src/third_party/angle/src/compiler/translator/SeparateDeclarations.h
new file mode 100644
index 0000000..8142fae
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SeparateDeclarations.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The SeparateDeclarations function processes declarations, so that in the end each declaration
+// contains only one declarator.
+// This is useful as an intermediate step when initialization needs to be separated from
+// declaration, or when things need to be unfolded out of the initializer.
+// Example:
+//     int a[1] = int[1](1), b[1] = int[1](2);
+// gets transformed when run through this class into the AST equivalent of:
+//     int a[1] = int[1](1);
+//     int b[1] = int[1](2);
+
+#ifndef COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_
+#define COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_
+
+namespace sh
+{
+class TIntermNode;
+
+void SeparateDeclarations(TIntermNode *root);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_
diff --git a/src/third_party/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp b/src/third_party/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
new file mode 100644
index 0000000..1e7000b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
@@ -0,0 +1,128 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names
+// from more complex expressions, assigning them to a temporary variable a#.
+// Examples where a, b and c are all arrays:
+// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2;
+// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i];
+
+#include "compiler/translator/SeparateExpressionsReturningArrays.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// Traverser that separates one array expression into a statement at a time.
+class SeparateExpressionsTraverser : public TIntermTraverser
+{
+  public:
+    SeparateExpressionsTraverser();
+
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+
+    void nextIteration();
+    bool foundArrayExpression() const { return mFoundArrayExpression; }
+
+  protected:
+    // Marked to true once an operation that needs to be hoisted out of the expression has been
+    // found. After that, no more AST updates are performed on that traversal.
+    bool mFoundArrayExpression;
+
+    IntermNodePatternMatcher mPatternToSeparateMatcher;
+};
+
+SeparateExpressionsTraverser::SeparateExpressionsTraverser()
+    : TIntermTraverser(true, false, false),
+      mFoundArrayExpression(false),
+      mPatternToSeparateMatcher(IntermNodePatternMatcher::kExpressionReturningArray)
+{
+}
+
+// Performs a shallow copy of an assignment node.
+// These shallow copies are useful when a node gets inserted into an aggregate node
+// and also needs to be replaced in its original location by a different node.
+TIntermBinary *CopyAssignmentNode(TIntermBinary *node)
+{
+    return new TIntermBinary(node->getOp(), node->getLeft(), node->getRight());
+}
+
+bool SeparateExpressionsTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+    if (mFoundArrayExpression)
+        return false;
+
+    // Return if the expression is not an array or if we're not inside a complex expression.
+    if (!mPatternToSeparateMatcher.match(node, getParentNode()))
+        return true;
+
+    ASSERT(node->getOp() == EOpAssign);
+
+    mFoundArrayExpression = true;
+
+    TIntermSequence insertions;
+    insertions.push_back(CopyAssignmentNode(node));
+    // TODO(oetuaho): In some cases it would be more optimal to not add the temporary node, but just
+    // use the original target of the assignment. Care must be taken so that this doesn't happen
+    // when the same array symbol is a target of assignment more than once in one expression.
+    insertions.push_back(createTempInitDeclaration(node->getLeft()));
+    insertStatementsInParentBlock(insertions);
+
+    queueReplacement(node, createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
+
+    return false;
+}
+
+bool SeparateExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (mFoundArrayExpression)
+        return false;  // No need to traverse further
+
+    if (!mPatternToSeparateMatcher.match(node, getParentNode()))
+        return true;
+
+    ASSERT(node->isConstructor() || node->getOp() == EOpCallFunctionInAST);
+
+    mFoundArrayExpression = true;
+
+    TIntermSequence insertions;
+    insertions.push_back(createTempInitDeclaration(node->shallowCopy()));
+    insertStatementsInParentBlock(insertions);
+
+    queueReplacement(node, createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
+
+    return false;
+}
+
+void SeparateExpressionsTraverser::nextIteration()
+{
+    mFoundArrayExpression = false;
+    nextTemporaryIndex();
+}
+
+}  // namespace
+
+void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *temporaryIndex)
+{
+    SeparateExpressionsTraverser traverser;
+    ASSERT(temporaryIndex != nullptr);
+    traverser.useTemporaryIndex(temporaryIndex);
+    // Separate one expression at a time, and reset the traverser between iterations.
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        if (traverser.foundArrayExpression())
+            traverser.updateTree();
+    } while (traverser.foundArrayExpression());
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h b/src/third_party/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h
new file mode 100644
index 0000000..1ed50a0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names
+// from more complex expressions, assigning them to a temporary variable a#.
+// Examples where a, b and c are all arrays:
+// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2;
+// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i];
+
+#ifndef COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
+#define COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
+
+namespace sh
+{
+class TIntermNode;
+
+void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *temporaryIndex);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
diff --git a/src/third_party/angle/src/compiler/translator/Severity.h b/src/third_party/angle/src/compiler/translator/Severity.h
new file mode 100644
index 0000000..47808a1
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Severity.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_SEVERITY_H_
+#define COMPILER_TRANSLATOR_SEVERITY_H_
+
+namespace sh
+{
+
+// Severity is used to classify info log messages.
+enum Severity
+{
+    SH_WARNING,
+    SH_ERROR
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_SEVERITY_H_
diff --git a/src/third_party/angle/src/compiler/translator/ShaderLang.cpp b/src/third_party/angle/src/compiler/translator/ShaderLang.cpp
new file mode 100644
index 0000000..831f369
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ShaderLang.cpp
@@ -0,0 +1,431 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Implement the top-level of interface to the compiler,
+// as defined in ShaderLang.h
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/translator/Compiler.h"
+#include "compiler/translator/InitializeDll.h"
+#include "compiler/translator/length_limits.h"
+#ifdef ANGLE_ENABLE_HLSL
+#include "compiler/translator/TranslatorHLSL.h"
+#endif  // ANGLE_ENABLE_HLSL
+#include "compiler/translator/VariablePacker.h"
+#include "angle_gl.h"
+
+namespace sh
+{
+
+namespace
+{
+
+bool isInitialized = false;
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler.
+//
+
+template <typename VarT>
+const std::vector<VarT> *GetVariableList(const TCompiler *compiler);
+
+template <>
+const std::vector<Uniform> *GetVariableList(const TCompiler *compiler)
+{
+    return &compiler->getUniforms();
+}
+
+template <>
+const std::vector<Varying> *GetVariableList(const TCompiler *compiler)
+{
+    return &compiler->getVaryings();
+}
+
+template <>
+const std::vector<Attribute> *GetVariableList(const TCompiler *compiler)
+{
+    return &compiler->getAttributes();
+}
+
+template <>
+const std::vector<OutputVariable> *GetVariableList(const TCompiler *compiler)
+{
+    return &compiler->getOutputVariables();
+}
+
+template <>
+const std::vector<InterfaceBlock> *GetVariableList(const TCompiler *compiler)
+{
+    return &compiler->getInterfaceBlocks();
+}
+
+template <typename VarT>
+const std::vector<VarT> *GetShaderVariables(const ShHandle handle)
+{
+    if (!handle)
+    {
+        return nullptr;
+    }
+
+    TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+    TCompiler *compiler = base->getAsCompiler();
+    if (!compiler)
+    {
+        return nullptr;
+    }
+
+    return GetVariableList<VarT>(compiler);
+}
+
+TCompiler *GetCompilerFromHandle(ShHandle handle)
+{
+    if (!handle)
+        return nullptr;
+    TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+    return base->getAsCompiler();
+}
+
+#ifdef ANGLE_ENABLE_HLSL
+TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
+{
+    if (!handle)
+        return nullptr;
+    TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+    return base->getAsTranslatorHLSL();
+}
+#endif  // ANGLE_ENABLE_HLSL
+
+}  // anonymous namespace
+
+//
+// Driver must call this first, once, before doing any other compiler operations.
+// Subsequent calls to this function are no-op.
+//
+bool Initialize()
+{
+    if (!isInitialized)
+    {
+        isInitialized = InitProcess();
+    }
+    return isInitialized;
+}
+
+//
+// Cleanup symbol tables
+//
+bool Finalize()
+{
+    if (isInitialized)
+    {
+        DetachProcess();
+        isInitialized = false;
+    }
+    return true;
+}
+
+//
+// Initialize built-in resources with minimum expected values.
+//
+void InitBuiltInResources(ShBuiltInResources *resources)
+{
+    // Make comparable.
+    memset(resources, 0, sizeof(*resources));
+
+    // Constants.
+    resources->MaxVertexAttribs             = 8;
+    resources->MaxVertexUniformVectors      = 128;
+    resources->MaxVaryingVectors            = 8;
+    resources->MaxVertexTextureImageUnits   = 0;
+    resources->MaxCombinedTextureImageUnits = 8;
+    resources->MaxTextureImageUnits         = 8;
+    resources->MaxFragmentUniformVectors    = 16;
+    resources->MaxDrawBuffers               = 1;
+
+    // Extensions.
+    resources->OES_standard_derivatives        = 0;
+    resources->OES_EGL_image_external          = 0;
+    resources->OES_EGL_image_external_essl3    = 0;
+    resources->NV_EGL_stream_consumer_external = 0;
+    resources->ARB_texture_rectangle           = 0;
+    resources->EXT_blend_func_extended         = 0;
+    resources->EXT_draw_buffers                = 0;
+    resources->EXT_frag_depth                  = 0;
+    resources->EXT_shader_texture_lod          = 0;
+    resources->WEBGL_debug_shader_precision    = 0;
+    resources->EXT_shader_framebuffer_fetch    = 0;
+    resources->NV_shader_framebuffer_fetch     = 0;
+    resources->ARM_shader_framebuffer_fetch    = 0;
+    resources->OVR_multiview                   = 0;
+    resources->EXT_YUV_target                  = 0;
+
+    resources->NV_draw_buffers = 0;
+
+    // Disable highp precision in fragment shader by default.
+    resources->FragmentPrecisionHigh = 0;
+
+    // GLSL ES 3.0 constants.
+    resources->MaxVertexOutputVectors  = 16;
+    resources->MaxFragmentInputVectors = 15;
+    resources->MinProgramTexelOffset   = -8;
+    resources->MaxProgramTexelOffset   = 7;
+
+    // Extensions constants.
+    resources->MaxDualSourceDrawBuffers = 0;
+
+    resources->MaxViewsOVR = 2;
+
+    // Disable name hashing by default.
+    resources->HashFunction = nullptr;
+
+    resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
+
+    resources->MaxExpressionComplexity = 256;
+    resources->MaxCallStackDepth       = 256;
+    resources->MaxFunctionParameters   = 1024;
+
+    // ES 3.1 Revision 4, 7.2 Built-in Constants
+    resources->MaxImageUnits            = 4;
+    resources->MaxVertexImageUniforms   = 0;
+    resources->MaxFragmentImageUniforms = 0;
+    resources->MaxComputeImageUniforms  = 4;
+    resources->MaxCombinedImageUniforms = 4;
+
+    resources->MaxUniformLocations = 1024;
+
+    resources->MaxCombinedShaderOutputResources = 4;
+
+    resources->MaxComputeWorkGroupCount[0] = 65535;
+    resources->MaxComputeWorkGroupCount[1] = 65535;
+    resources->MaxComputeWorkGroupCount[2] = 65535;
+    resources->MaxComputeWorkGroupSize[0]  = 128;
+    resources->MaxComputeWorkGroupSize[1]  = 128;
+    resources->MaxComputeWorkGroupSize[2]  = 64;
+    resources->MaxComputeUniformComponents = 512;
+    resources->MaxComputeTextureImageUnits = 16;
+
+    resources->MaxComputeAtomicCounters       = 8;
+    resources->MaxComputeAtomicCounterBuffers = 1;
+
+    resources->MaxVertexAtomicCounters   = 0;
+    resources->MaxFragmentAtomicCounters = 0;
+    resources->MaxCombinedAtomicCounters = 8;
+    resources->MaxAtomicCounterBindings  = 1;
+
+    resources->MaxVertexAtomicCounterBuffers   = 0;
+    resources->MaxFragmentAtomicCounterBuffers = 0;
+    resources->MaxCombinedAtomicCounterBuffers = 1;
+    resources->MaxAtomicCounterBufferSize      = 32;
+}
+
+//
+// Driver calls these to create and destroy compiler objects.
+//
+ShHandle ConstructCompiler(sh::GLenum type,
+                           ShShaderSpec spec,
+                           ShShaderOutput output,
+                           const ShBuiltInResources *resources)
+{
+    TShHandleBase *base = static_cast<TShHandleBase *>(ConstructCompiler(type, spec, output));
+    if (base == nullptr)
+    {
+        return 0;
+    }
+
+    TCompiler *compiler = base->getAsCompiler();
+    if (compiler == nullptr)
+    {
+        return 0;
+    }
+
+    // Generate built-in symbol table.
+    if (!compiler->Init(*resources))
+    {
+        Destruct(base);
+        return 0;
+    }
+
+    return reinterpret_cast<void *>(base);
+}
+
+void Destruct(ShHandle handle)
+{
+    if (handle == 0)
+        return;
+
+    TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+
+    if (base->getAsCompiler())
+        DeleteCompiler(base->getAsCompiler());
+}
+
+const std::string &GetBuiltInResourcesString(const ShHandle handle)
+{
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+    return compiler->getBuiltInResourcesString();
+}
+
+//
+// Do an actual compile on the given strings.  The result is left
+// in the given compile object.
+//
+// Return:  The return value of ShCompile is really boolean, indicating
+// success or failure.
+//
+bool Compile(const ShHandle handle,
+             const char *const shaderStrings[],
+             size_t numStrings,
+             ShCompileOptions compileOptions)
+{
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+
+    return compiler->compile(shaderStrings, numStrings, compileOptions);
+}
+
+void ClearResults(const ShHandle handle)
+{
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+    compiler->clearResults();
+}
+
+int GetShaderVersion(const ShHandle handle)
+{
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+    return compiler->getShaderVersion();
+}
+
+ShShaderOutput GetShaderOutputType(const ShHandle handle)
+{
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+    return compiler->getOutputType();
+}
+
+//
+// Return any compiler log of messages for the application.
+//
+const std::string &GetInfoLog(const ShHandle handle)
+{
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+
+    TInfoSink &infoSink = compiler->getInfoSink();
+    return infoSink.info.str();
+}
+
+//
+// Return any object code.
+//
+const std::string &GetObjectCode(const ShHandle handle)
+{
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+
+    TInfoSink &infoSink = compiler->getInfoSink();
+    return infoSink.obj.str();
+}
+
+const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle)
+{
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+    return &(compiler->getNameMap());
+}
+
+const std::vector<Uniform> *GetUniforms(const ShHandle handle)
+{
+    return GetShaderVariables<Uniform>(handle);
+}
+
+const std::vector<Varying> *GetVaryings(const ShHandle handle)
+{
+    return GetShaderVariables<Varying>(handle);
+}
+
+const std::vector<Attribute> *GetAttributes(const ShHandle handle)
+{
+    return GetShaderVariables<Attribute>(handle);
+}
+
+const std::vector<OutputVariable> *GetOutputVariables(const ShHandle handle)
+{
+    return GetShaderVariables<OutputVariable>(handle);
+}
+
+const std::vector<InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle)
+{
+    return GetShaderVariables<InterfaceBlock>(handle);
+}
+
+WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle)
+{
+    ASSERT(handle);
+
+    TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+    TCompiler *compiler = base->getAsCompiler();
+    ASSERT(compiler);
+
+    return compiler->getComputeShaderLocalSize();
+}
+
+int GetVertexShaderNumViews(const ShHandle handle)
+{
+    ASSERT(handle);
+    TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+    TCompiler *compiler = base->getAsCompiler();
+    ASSERT(compiler);
+
+    return compiler->getNumViews();
+}
+
+bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables)
+{
+    VariablePacker packer;
+    return packer.CheckVariablesWithinPackingLimits(maxVectors, variables);
+}
+
+bool GetInterfaceBlockRegister(const ShHandle handle,
+                               const std::string &interfaceBlockName,
+                               unsigned int *indexOut)
+{
+#ifdef ANGLE_ENABLE_HLSL
+    ASSERT(indexOut);
+
+    TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
+    ASSERT(translator);
+
+    if (!translator->hasInterfaceBlock(interfaceBlockName))
+    {
+        return false;
+    }
+
+    *indexOut = translator->getInterfaceBlockRegister(interfaceBlockName);
+    return true;
+#else
+    return false;
+#endif  // ANGLE_ENABLE_HLSL
+}
+
+const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle)
+{
+#ifdef ANGLE_ENABLE_HLSL
+    TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
+    ASSERT(translator);
+
+    return translator->getUniformRegisterMap();
+#else
+    return nullptr;
+#endif  // ANGLE_ENABLE_HLSL
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ShaderVars.cpp b/src/third_party/angle/src/compiler/translator/ShaderVars.cpp
new file mode 100644
index 0000000..8660b3b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ShaderVars.cpp
@@ -0,0 +1,489 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ShaderVars.cpp:
+//  Methods for GL variable types (varyings, uniforms, etc)
+//
+
+#include <GLSLANG/ShaderLang.h>
+
+#include "common/debug.h"
+
+namespace sh
+{
+
+namespace
+{
+
+InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation)
+{
+    return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation);
+}
+}
+// The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion
+// on Khronos.org, clarifies that a smooth/flat mismatch produces a link error,
+// but auxiliary qualifier mismatch (centroid) does not.
+bool InterpolationTypesMatch(InterpolationType a, InterpolationType b)
+{
+    return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b));
+}
+
+ShaderVariable::ShaderVariable() : type(0), precision(0), arraySize(0), staticUse(false)
+{
+}
+
+ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn)
+    : type(typeIn), precision(0), arraySize(arraySizeIn), staticUse(false)
+{
+}
+
+ShaderVariable::~ShaderVariable()
+{
+}
+
+ShaderVariable::ShaderVariable(const ShaderVariable &other)
+    : type(other.type),
+      precision(other.precision),
+      name(other.name),
+      mappedName(other.mappedName),
+      arraySize(other.arraySize),
+      staticUse(other.staticUse),
+      fields(other.fields),
+      structName(other.structName)
+{
+}
+
+ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
+{
+    type       = other.type;
+    precision  = other.precision;
+    name       = other.name;
+    mappedName = other.mappedName;
+    arraySize  = other.arraySize;
+    staticUse  = other.staticUse;
+    fields     = other.fields;
+    structName = other.structName;
+    return *this;
+}
+
+bool ShaderVariable::operator==(const ShaderVariable &other) const
+{
+    if (type != other.type || precision != other.precision || name != other.name ||
+        mappedName != other.mappedName || arraySize != other.arraySize ||
+        staticUse != other.staticUse || fields.size() != other.fields.size() ||
+        structName != other.structName)
+    {
+        return false;
+    }
+    for (size_t ii = 0; ii < fields.size(); ++ii)
+    {
+        if (fields[ii] != other.fields[ii])
+            return false;
+    }
+    return true;
+}
+
+bool ShaderVariable::findInfoByMappedName(const std::string &mappedFullName,
+                                          const ShaderVariable **leafVar,
+                                          std::string *originalFullName) const
+{
+    ASSERT(leafVar && originalFullName);
+    // There are three cases:
+    // 1) the top variable is of struct type;
+    // 2) the top variable is an array;
+    // 3) otherwise.
+    size_t pos = mappedFullName.find_first_of(".[");
+
+    if (pos == std::string::npos)
+    {
+        // Case 3.
+        if (mappedFullName != this->mappedName)
+            return false;
+        *originalFullName = this->name;
+        *leafVar          = this;
+        return true;
+    }
+    else
+    {
+        std::string topName = mappedFullName.substr(0, pos);
+        if (topName != this->mappedName)
+            return false;
+        std::string originalName = this->name;
+        std::string remaining;
+        if (mappedFullName[pos] == '[')
+        {
+            // Case 2.
+            size_t closePos = mappedFullName.find_first_of(']');
+            if (closePos < pos || closePos == std::string::npos)
+                return false;
+            // Append '[index]'.
+            originalName += mappedFullName.substr(pos, closePos - pos + 1);
+            if (closePos + 1 == mappedFullName.size())
+            {
+                *originalFullName = originalName;
+                *leafVar          = this;
+                return true;
+            }
+            else
+            {
+                // In the form of 'a[0].b', so after ']', '.' is expected.
+                if (mappedFullName[closePos + 1] != '.')
+                    return false;
+                remaining = mappedFullName.substr(closePos + 2);  // Skip "]."
+            }
+        }
+        else
+        {
+            // Case 1.
+            remaining = mappedFullName.substr(pos + 1);  // Skip "."
+        }
+        for (size_t ii = 0; ii < this->fields.size(); ++ii)
+        {
+            const ShaderVariable *fieldVar = nullptr;
+            std::string originalFieldName;
+            bool found = fields[ii].findInfoByMappedName(remaining, &fieldVar, &originalFieldName);
+            if (found)
+            {
+                *originalFullName = originalName + "." + originalFieldName;
+                *leafVar          = fieldVar;
+                return true;
+            }
+        }
+        return false;
+    }
+}
+
+bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
+                                              bool matchPrecision) const
+{
+    if (type != other.type)
+        return false;
+    if (matchPrecision && precision != other.precision)
+        return false;
+    if (name != other.name)
+        return false;
+    ASSERT(mappedName == other.mappedName);
+    if (arraySize != other.arraySize)
+        return false;
+    if (fields.size() != other.fields.size())
+        return false;
+    for (size_t ii = 0; ii < fields.size(); ++ii)
+    {
+        if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii], matchPrecision))
+        {
+            return false;
+        }
+    }
+    if (structName != other.structName)
+        return false;
+    return true;
+}
+
+Uniform::Uniform() : binding(-1)
+{
+}
+
+Uniform::~Uniform()
+{
+}
+
+Uniform::Uniform(const Uniform &other) : VariableWithLocation(other), binding(other.binding)
+{
+}
+
+Uniform &Uniform::operator=(const Uniform &other)
+{
+    VariableWithLocation::operator=(other);
+    binding                 = other.binding;
+    return *this;
+}
+
+bool Uniform::operator==(const Uniform &other) const
+{
+    return VariableWithLocation::operator==(other) && binding == other.binding;
+}
+
+bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
+{
+    if (binding != -1 && other.binding != -1 && binding != other.binding)
+    {
+        return false;
+    }
+    if (location != -1 && other.location != -1 && location != other.location)
+    {
+        return false;
+    }
+    return VariableWithLocation::isSameVariableAtLinkTime(other, true);
+}
+
+VariableWithLocation::VariableWithLocation() : location(-1)
+{
+}
+
+VariableWithLocation::~VariableWithLocation()
+{
+}
+
+VariableWithLocation::VariableWithLocation(const VariableWithLocation &other)
+    : ShaderVariable(other), location(other.location)
+{
+}
+
+VariableWithLocation &VariableWithLocation::operator=(const VariableWithLocation &other)
+{
+    ShaderVariable::operator=(other);
+    location                = other.location;
+    return *this;
+}
+
+bool VariableWithLocation::operator==(const VariableWithLocation &other) const
+{
+    return (ShaderVariable::operator==(other) && location == other.location);
+}
+
+Attribute::Attribute()
+{
+}
+
+Attribute::~Attribute()
+{
+}
+
+Attribute::Attribute(const Attribute &other) : VariableWithLocation(other)
+{
+}
+
+Attribute &Attribute::operator=(const Attribute &other)
+{
+    VariableWithLocation::operator=(other);
+    return *this;
+}
+
+bool Attribute::operator==(const Attribute &other) const
+{
+    return VariableWithLocation::operator==(other);
+}
+
+OutputVariable::OutputVariable()
+{
+}
+
+OutputVariable::~OutputVariable()
+{
+}
+
+OutputVariable::OutputVariable(const OutputVariable &other) : VariableWithLocation(other)
+{
+}
+
+OutputVariable &OutputVariable::operator=(const OutputVariable &other)
+{
+    VariableWithLocation::operator=(other);
+    return *this;
+}
+
+bool OutputVariable::operator==(const OutputVariable &other) const
+{
+    return VariableWithLocation::operator==(other);
+}
+
+InterfaceBlockField::InterfaceBlockField() : isRowMajorLayout(false)
+{
+}
+
+InterfaceBlockField::~InterfaceBlockField()
+{
+}
+
+InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other)
+    : ShaderVariable(other), isRowMajorLayout(other.isRowMajorLayout)
+{
+}
+
+InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other)
+{
+    ShaderVariable::operator=(other);
+    isRowMajorLayout        = other.isRowMajorLayout;
+    return *this;
+}
+
+bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
+{
+    return (ShaderVariable::operator==(other) && isRowMajorLayout == other.isRowMajorLayout);
+}
+
+bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
+    const InterfaceBlockField &other) const
+{
+    return (ShaderVariable::isSameVariableAtLinkTime(other, true) &&
+            isRowMajorLayout == other.isRowMajorLayout);
+}
+
+Varying::Varying() : interpolation(INTERPOLATION_SMOOTH), isInvariant(false)
+{
+}
+
+Varying::~Varying()
+{
+}
+
+Varying::Varying(const Varying &other)
+    : ShaderVariable(other), interpolation(other.interpolation), isInvariant(other.isInvariant)
+{
+}
+
+Varying &Varying::operator=(const Varying &other)
+{
+    ShaderVariable::operator=(other);
+    interpolation           = other.interpolation;
+    isInvariant             = other.isInvariant;
+    return *this;
+}
+
+bool Varying::operator==(const Varying &other) const
+{
+    return (ShaderVariable::operator==(other) && interpolation == other.interpolation &&
+            isInvariant == other.isInvariant);
+}
+
+bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
+{
+    return isSameVaryingAtLinkTime(other, 100);
+}
+
+bool Varying::isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const
+{
+    return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
+            InterpolationTypesMatch(interpolation, other.interpolation) &&
+            (shaderVersion >= 300 || isInvariant == other.isInvariant));
+}
+
+InterfaceBlock::InterfaceBlock()
+    : arraySize(0), layout(BLOCKLAYOUT_PACKED), isRowMajorLayout(false), staticUse(false)
+{
+}
+
+InterfaceBlock::~InterfaceBlock()
+{
+}
+
+InterfaceBlock::InterfaceBlock(const InterfaceBlock &other)
+    : name(other.name),
+      mappedName(other.mappedName),
+      instanceName(other.instanceName),
+      arraySize(other.arraySize),
+      layout(other.layout),
+      isRowMajorLayout(other.isRowMajorLayout),
+      staticUse(other.staticUse),
+      fields(other.fields)
+{
+}
+
+InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
+{
+    name             = other.name;
+    mappedName       = other.mappedName;
+    instanceName     = other.instanceName;
+    arraySize        = other.arraySize;
+    layout           = other.layout;
+    isRowMajorLayout = other.isRowMajorLayout;
+    staticUse        = other.staticUse;
+    fields           = other.fields;
+    return *this;
+}
+
+std::string InterfaceBlock::fieldPrefix() const
+{
+    return instanceName.empty() ? "" : name;
+}
+
+bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const
+{
+    if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize ||
+        layout != other.layout || isRowMajorLayout != other.isRowMajorLayout ||
+        fields.size() != other.fields.size())
+    {
+        return false;
+    }
+
+    for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex)
+    {
+        if (!fields[fieldIndex].isSameInterfaceBlockFieldAtLinkTime(other.fields[fieldIndex]))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void WorkGroupSize::fill(int fillValue)
+{
+    localSizeQualifiers[0] = fillValue;
+    localSizeQualifiers[1] = fillValue;
+    localSizeQualifiers[2] = fillValue;
+}
+
+void WorkGroupSize::setLocalSize(int localSizeX, int localSizeY, int localSizeZ)
+{
+    localSizeQualifiers[0] = localSizeX;
+    localSizeQualifiers[1] = localSizeY;
+    localSizeQualifiers[2] = localSizeZ;
+}
+
+// check that if one of them is less than 1, then all of them are.
+// Or if one is positive, then all of them are positive.
+bool WorkGroupSize::isLocalSizeValid() const
+{
+    return (
+        (localSizeQualifiers[0] < 1 && localSizeQualifiers[1] < 1 && localSizeQualifiers[2] < 1) ||
+        (localSizeQualifiers[0] > 0 && localSizeQualifiers[1] > 0 && localSizeQualifiers[2] > 0));
+}
+
+bool WorkGroupSize::isAnyValueSet() const
+{
+    return localSizeQualifiers[0] > 0 || localSizeQualifiers[1] > 0 || localSizeQualifiers[2] > 0;
+}
+
+bool WorkGroupSize::isDeclared() const
+{
+    bool localSizeDeclared = localSizeQualifiers[0] > 0;
+    ASSERT(isLocalSizeValid());
+    return localSizeDeclared;
+}
+
+bool WorkGroupSize::isWorkGroupSizeMatching(const WorkGroupSize &right) const
+{
+    for (size_t i = 0u; i < size(); ++i)
+    {
+        bool result = (localSizeQualifiers[i] == right.localSizeQualifiers[i] ||
+                       (localSizeQualifiers[i] == 1 && right.localSizeQualifiers[i] == -1) ||
+                       (localSizeQualifiers[i] == -1 && right.localSizeQualifiers[i] == 1));
+        if (!result)
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+int &WorkGroupSize::operator[](size_t index)
+{
+    ASSERT(index < size());
+    return localSizeQualifiers[index];
+}
+
+int WorkGroupSize::operator[](size_t index) const
+{
+    ASSERT(index < size());
+    return localSizeQualifiers[index];
+}
+
+size_t WorkGroupSize::size() const
+{
+    return 3u;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/SimplifyLoopConditions.cpp b/src/third_party/angle/src/compiler/translator/SimplifyLoopConditions.cpp
new file mode 100644
index 0000000..a2ed7f3
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SimplifyLoopConditions.cpp
@@ -0,0 +1,306 @@
+//
+// Copyright (c) 2016 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.
+//
+// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions
+// to regular statements inside the loop. This way further transformations that generate statements
+// from loop conditions and loop expressions work correctly.
+//
+
+#include "compiler/translator/SimplifyLoopConditions.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+
+namespace sh
+{
+
+namespace
+{
+
+TIntermConstantUnion *CreateBoolConstantNode(bool value)
+{
+    TConstantUnion *u = new TConstantUnion;
+    u->setBConst(value);
+    TIntermConstantUnion *node =
+        new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1));
+    return node;
+}
+
+class SimplifyLoopConditionsTraverser : public TLValueTrackingTraverser
+{
+  public:
+    SimplifyLoopConditionsTraverser(unsigned int conditionsToSimplifyMask,
+                                    const TSymbolTable &symbolTable,
+                                    int shaderVersion);
+
+    void traverseLoop(TIntermLoop *node) override;
+
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    bool visitTernary(Visit visit, TIntermTernary *node) override;
+    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+
+    void nextIteration();
+    bool foundLoopToChange() const { return mFoundLoopToChange; }
+
+  protected:
+    // Marked to true once an operation that needs to be hoisted out of the expression has been
+    // found. After that, no more AST updates are performed on that traversal.
+    bool mFoundLoopToChange;
+    bool mInsideLoopInitConditionOrExpression;
+    IntermNodePatternMatcher mConditionsToSimplify;
+};
+
+SimplifyLoopConditionsTraverser::SimplifyLoopConditionsTraverser(
+    unsigned int conditionsToSimplifyMask,
+    const TSymbolTable &symbolTable,
+    int shaderVersion)
+    : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
+      mFoundLoopToChange(false),
+      mInsideLoopInitConditionOrExpression(false),
+      mConditionsToSimplify(conditionsToSimplifyMask)
+{
+}
+
+void SimplifyLoopConditionsTraverser::nextIteration()
+{
+    mFoundLoopToChange                   = false;
+    mInsideLoopInitConditionOrExpression = false;
+    nextTemporaryIndex();
+}
+
+// The visit functions operate in three modes:
+// 1. If a matching expression has already been found, we return early since only one loop can
+//    be transformed on one traversal.
+// 2. We try to find loops. In case a node is not inside a loop and can not contain loops, we
+//    stop traversing the subtree.
+// 3. If we're inside a loop initialization, condition or expression, we check for expressions
+//    that should be moved out of the loop condition or expression. If one is found, the loop
+//    is processed.
+bool SimplifyLoopConditionsTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+
+    if (mFoundLoopToChange)
+        return false;
+
+    if (!mInsideLoopInitConditionOrExpression)
+        return false;
+
+    mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode(), isLValueRequiredHere());
+    return !mFoundLoopToChange;
+}
+
+bool SimplifyLoopConditionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (mFoundLoopToChange)
+        return false;
+
+    if (!mInsideLoopInitConditionOrExpression)
+        return false;
+
+    mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode());
+    return !mFoundLoopToChange;
+}
+
+bool SimplifyLoopConditionsTraverser::visitTernary(Visit visit, TIntermTernary *node)
+{
+    if (mFoundLoopToChange)
+        return false;
+
+    if (!mInsideLoopInitConditionOrExpression)
+        return false;
+
+    mFoundLoopToChange = mConditionsToSimplify.match(node);
+    return !mFoundLoopToChange;
+}
+
+bool SimplifyLoopConditionsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+    if (mFoundLoopToChange)
+        return false;
+
+    if (!mInsideLoopInitConditionOrExpression)
+        return false;
+
+    mFoundLoopToChange = mConditionsToSimplify.match(node);
+    return !mFoundLoopToChange;
+}
+
+void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node)
+{
+    if (mFoundLoopToChange)
+        return;
+
+    // Mark that we're inside a loop condition or expression, and transform the loop if needed.
+
+    ScopedNodeInTraversalPath addToPath(this, node);
+
+    mInsideLoopInitConditionOrExpression = true;
+    TLoopType loopType                   = node->getType();
+
+    if (!mFoundLoopToChange && node->getInit())
+    {
+        node->getInit()->traverse(this);
+    }
+
+    if (!mFoundLoopToChange && node->getCondition())
+    {
+        node->getCondition()->traverse(this);
+    }
+
+    if (!mFoundLoopToChange && node->getExpression())
+    {
+        node->getExpression()->traverse(this);
+    }
+
+    if (mFoundLoopToChange)
+    {
+        // Replace the loop condition with a boolean variable that's updated on each iteration.
+        if (loopType == ELoopWhile)
+        {
+            // Transform:
+            //   while (expr) { body; }
+            // into
+            //   bool s0 = expr;
+            //   while (s0) { { body; } s0 = expr; }
+            TIntermSequence tempInitSeq;
+            tempInitSeq.push_back(createTempInitDeclaration(node->getCondition()->deepCopy()));
+            insertStatementsInParentBlock(tempInitSeq);
+
+            TIntermBlock *newBody = new TIntermBlock();
+            if (node->getBody())
+            {
+                newBody->getSequence()->push_back(node->getBody());
+            }
+            newBody->getSequence()->push_back(
+                createTempAssignment(node->getCondition()->deepCopy()));
+
+            // Can't use queueReplacement to replace old body, since it may have been nullptr.
+            // It's safe to do the replacements in place here - this node won't be traversed
+            // further.
+            node->setBody(newBody);
+            node->setCondition(createTempSymbol(node->getCondition()->getType()));
+        }
+        else if (loopType == ELoopDoWhile)
+        {
+            // Transform:
+            //   do {
+            //     body;
+            //   } while (expr);
+            // into
+            //   bool s0 = true;
+            //   do {
+            //     { body; }
+            //     s0 = expr;
+            //   } while (s0);
+            TIntermSequence tempInitSeq;
+            tempInitSeq.push_back(createTempInitDeclaration(CreateBoolConstantNode(true)));
+            insertStatementsInParentBlock(tempInitSeq);
+
+            TIntermBlock *newBody = new TIntermBlock();
+            if (node->getBody())
+            {
+                newBody->getSequence()->push_back(node->getBody());
+            }
+            newBody->getSequence()->push_back(
+                createTempAssignment(node->getCondition()->deepCopy()));
+
+            // Can't use queueReplacement to replace old body, since it may have been nullptr.
+            // It's safe to do the replacements in place here - this node won't be traversed
+            // further.
+            node->setBody(newBody);
+            node->setCondition(createTempSymbol(node->getCondition()->getType()));
+        }
+        else if (loopType == ELoopFor)
+        {
+            // Move the loop condition inside the loop.
+            // Transform:
+            //   for (init; expr; exprB) { body; }
+            // into
+            //   {
+            //     init;
+            //     bool s0 = expr;
+            //     while (s0) {
+            //       { body; }
+            //       exprB;
+            //       s0 = expr;
+            //     }
+            //   }
+            TIntermBlock *loopScope            = new TIntermBlock();
+            TIntermSequence *loopScopeSequence = loopScope->getSequence();
+
+            // Insert "init;"
+            if (node->getInit())
+            {
+                loopScopeSequence->push_back(node->getInit());
+            }
+
+            // Insert "bool s0 = expr;" if applicable, "bool s0 = true;" otherwise
+            TIntermTyped *conditionInitializer = nullptr;
+            if (node->getCondition())
+            {
+                conditionInitializer = node->getCondition()->deepCopy();
+            }
+            else
+            {
+                conditionInitializer = TIntermTyped::CreateBool(true);
+            }
+            loopScopeSequence->push_back(createTempInitDeclaration(conditionInitializer));
+
+            // Insert "{ body; }" in the while loop
+            TIntermBlock *whileLoopBody = new TIntermBlock();
+            if (node->getBody())
+            {
+                whileLoopBody->getSequence()->push_back(node->getBody());
+            }
+            // Insert "exprB;" in the while loop
+            if (node->getExpression())
+            {
+                whileLoopBody->getSequence()->push_back(node->getExpression());
+            }
+            // Insert "s0 = expr;" in the while loop
+            if (node->getCondition())
+            {
+                whileLoopBody->getSequence()->push_back(
+                    createTempAssignment(node->getCondition()->deepCopy()));
+            }
+
+            // Create "while(s0) { whileLoopBody }"
+            TIntermLoop *whileLoop = new TIntermLoop(
+                ELoopWhile, nullptr, createTempSymbol(conditionInitializer->getType()), nullptr,
+                whileLoopBody);
+            loopScope->getSequence()->push_back(whileLoop);
+            queueReplacement(node, loopScope, OriginalNode::IS_DROPPED);
+        }
+    }
+
+    mInsideLoopInitConditionOrExpression = false;
+
+    if (!mFoundLoopToChange && node->getBody())
+        node->getBody()->traverse(this);
+}
+
+}  // namespace
+
+void SimplifyLoopConditions(TIntermNode *root,
+                            unsigned int conditionsToSimplifyMask,
+                            unsigned int *temporaryIndex,
+                            const TSymbolTable &symbolTable,
+                            int shaderVersion)
+{
+    SimplifyLoopConditionsTraverser traverser(conditionsToSimplifyMask, symbolTable, shaderVersion);
+    ASSERT(temporaryIndex != nullptr);
+    traverser.useTemporaryIndex(temporaryIndex);
+    // Process one loop at a time, and reset the traverser between iterations.
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        if (traverser.foundLoopToChange())
+            traverser.updateTree();
+    } while (traverser.foundLoopToChange());
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/SimplifyLoopConditions.h b/src/third_party/angle/src/compiler/translator/SimplifyLoopConditions.h
new file mode 100644
index 0000000..968089d
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SimplifyLoopConditions.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2016 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.
+//
+// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions
+// to regular statements inside the loop. This way further transformations that generate statements
+// from loop conditions and loop expressions work correctly.
+//
+
+#ifndef COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_
+#define COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_
+
+namespace sh
+{
+class TIntermNode;
+class TSymbolTable;
+
+void SimplifyLoopConditions(TIntermNode *root,
+                            unsigned int conditionsToSimplify,
+                            unsigned int *temporaryIndex,
+                            const TSymbolTable &symbolTable,
+                            int shaderVersion);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_
diff --git a/src/third_party/angle/src/compiler/translator/SplitSequenceOperator.cpp b/src/third_party/angle/src/compiler/translator/SplitSequenceOperator.cpp
new file mode 100644
index 0000000..4c63b59
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SplitSequenceOperator.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright (c) 2016 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.
+//
+// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that
+// go through further AST transformations that generate statements, and splits them so that
+// possible side effects of earlier parts of the sequence operator expression are guaranteed to be
+// evaluated before the latter parts of the sequence operator expression are evaluated.
+//
+
+#include "compiler/translator/SplitSequenceOperator.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser
+{
+  public:
+    SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
+                                   const TSymbolTable &symbolTable,
+                                   int shaderVersion);
+
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    bool visitTernary(Visit visit, TIntermTernary *node) override;
+
+    void nextIteration();
+    bool foundExpressionToSplit() const { return mFoundExpressionToSplit; }
+
+  protected:
+    // Marked to true once an operation that needs to be hoisted out of the expression has been
+    // found. After that, no more AST updates are performed on that traversal.
+    bool mFoundExpressionToSplit;
+    int mInsideSequenceOperator;
+
+    IntermNodePatternMatcher mPatternToSplitMatcher;
+};
+
+SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
+                                                               const TSymbolTable &symbolTable,
+                                                               int shaderVersion)
+    : TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion),
+      mFoundExpressionToSplit(false),
+      mInsideSequenceOperator(0),
+      mPatternToSplitMatcher(patternsToSplitMask)
+{
+}
+
+void SplitSequenceOperatorTraverser::nextIteration()
+{
+    mFoundExpressionToSplit = false;
+    mInsideSequenceOperator = 0;
+    nextTemporaryIndex();
+}
+
+bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (mFoundExpressionToSplit)
+        return false;
+
+    if (mInsideSequenceOperator > 0 && visit == PreVisit)
+    {
+        // Detect expressions that need to be simplified
+        mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode());
+        return !mFoundExpressionToSplit;
+    }
+
+    return true;
+}
+
+bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+    if (node->getOp() == EOpComma)
+    {
+        if (visit == PreVisit)
+        {
+            if (mFoundExpressionToSplit)
+            {
+                return false;
+            }
+            mInsideSequenceOperator++;
+        }
+        else if (visit == PostVisit)
+        {
+            // Split sequence operators starting from the outermost one to preserve correct
+            // execution order.
+            if (mFoundExpressionToSplit && mInsideSequenceOperator == 1)
+            {
+                // Move the left side operand into a separate statement in the parent block.
+                TIntermSequence insertions;
+                insertions.push_back(node->getLeft());
+                insertStatementsInParentBlock(insertions);
+                // Replace the comma node with its right side operand.
+                queueReplacement(node, node->getRight(), OriginalNode::IS_DROPPED);
+            }
+            mInsideSequenceOperator--;
+        }
+        return true;
+    }
+
+    if (mFoundExpressionToSplit)
+        return false;
+
+    if (mInsideSequenceOperator > 0 && visit == PreVisit)
+    {
+        // Detect expressions that need to be simplified
+        mFoundExpressionToSplit =
+            mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
+        return !mFoundExpressionToSplit;
+    }
+
+    return true;
+}
+
+bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node)
+{
+    if (mFoundExpressionToSplit)
+        return false;
+
+    if (mInsideSequenceOperator > 0 && visit == PreVisit)
+    {
+        // Detect expressions that need to be simplified
+        mFoundExpressionToSplit = mPatternToSplitMatcher.match(node);
+        return !mFoundExpressionToSplit;
+    }
+
+    return true;
+}
+
+}  // namespace
+
+void SplitSequenceOperator(TIntermNode *root,
+                           int patternsToSplitMask,
+                           unsigned int *temporaryIndex,
+                           const TSymbolTable &symbolTable,
+                           int shaderVersion)
+{
+    SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion);
+    ASSERT(temporaryIndex != nullptr);
+    traverser.useTemporaryIndex(temporaryIndex);
+    // Separate one expression at a time, and reset the traverser between iterations.
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        if (traverser.foundExpressionToSplit())
+            traverser.updateTree();
+    } while (traverser.foundExpressionToSplit());
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/SplitSequenceOperator.h b/src/third_party/angle/src/compiler/translator/SplitSequenceOperator.h
new file mode 100644
index 0000000..6df9d45
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SplitSequenceOperator.h
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2016 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.
+//
+// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that
+// go through further AST transformations that generate statements, and splits them so that
+// possible side effects of earlier parts of the sequence operator expression are guaranteed to be
+// evaluated before the latter parts of the sequence operator expression are evaluated.
+//
+
+#ifndef COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
+#define COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
+
+namespace sh
+{
+
+class TIntermNode;
+class TSymbolTable;
+
+void SplitSequenceOperator(TIntermNode *root,
+                           int patternsToSplitMask,
+                           unsigned int *temporaryIndex,
+                           const TSymbolTable &symbolTable,
+                           int shaderVersion);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
diff --git a/src/third_party/angle/src/compiler/translator/StructureHLSL.cpp b/src/third_party/angle/src/compiler/translator/StructureHLSL.cpp
new file mode 100644
index 0000000..57c7c75
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/StructureHLSL.cpp
@@ -0,0 +1,569 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// StructureHLSL.cpp:
+//   Definitions of methods for HLSL translation of GLSL structures.
+//
+
+#include "compiler/translator/StructureHLSL.h"
+#include "common/utilities.h"
+#include "compiler/translator/OutputHLSL.h"
+#include "compiler/translator/Types.h"
+#include "compiler/translator/util.h"
+#include "compiler/translator/UtilsHLSL.h"
+
+namespace sh
+{
+
+Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &structElementIndexes,
+                                         unsigned *uniqueCounter)
+    : mPaddingCounter(uniqueCounter), mElementIndex(0), mStructElementIndexes(&structElementIndexes)
+{
+}
+
+Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other)
+    : mPaddingCounter(other.mPaddingCounter),
+      mElementIndex(other.mElementIndex),
+      mStructElementIndexes(other.mStructElementIndexes)
+{
+}
+
+Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other)
+{
+    mPaddingCounter       = other.mPaddingCounter;
+    mElementIndex         = other.mElementIndex;
+    mStructElementIndexes = other.mStructElementIndexes;
+    return *this;
+}
+
+TString Std140PaddingHelper::next()
+{
+    unsigned value = (*mPaddingCounter)++;
+    return str(value);
+}
+
+int Std140PaddingHelper::prePadding(const TType &type)
+{
+    if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
+    {
+        // no padding needed, HLSL will align the field to a new register
+        mElementIndex = 0;
+        return 0;
+    }
+
+    const GLenum glType     = GLVariableType(type);
+    const int numComponents = gl::VariableComponentCount(glType);
+
+    if (numComponents >= 4)
+    {
+        // no padding needed, HLSL will align the field to a new register
+        mElementIndex = 0;
+        return 0;
+    }
+
+    if (mElementIndex + numComponents > 4)
+    {
+        // no padding needed, HLSL will align the field to a new register
+        mElementIndex = numComponents;
+        return 0;
+    }
+
+    const int alignment     = numComponents == 3 ? 4 : numComponents;
+    const int paddingOffset = (mElementIndex % alignment);
+    const int paddingCount  = (paddingOffset != 0 ? (alignment - paddingOffset) : 0);
+
+    mElementIndex += paddingCount;
+    mElementIndex += numComponents;
+    mElementIndex %= 4;
+
+    return paddingCount;
+}
+
+TString Std140PaddingHelper::prePaddingString(const TType &type)
+{
+    int paddingCount = prePadding(type);
+
+    TString padding;
+
+    for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++)
+    {
+        padding += "    float pad_" + next() + ";\n";
+    }
+
+    return padding;
+}
+
+TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRowMajorPacking)
+{
+    if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
+    {
+        return "";
+    }
+
+    int numComponents     = 0;
+    TStructure *structure = type.getStruct();
+
+    if (type.isMatrix())
+    {
+        // This method can also be called from structureString, which does not use layout
+        // qualifiers.
+        // Thus, use the method parameter for determining the matrix packing.
+        //
+        // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we
+        // wish to always transpose GL matrices to play well with HLSL's matrix array indexing.
+        //
+        const bool isRowMajorMatrix = !useHLSLRowMajorPacking;
+        const GLenum glType         = GLVariableType(type);
+        numComponents               = gl::MatrixComponentCount(glType, isRowMajorMatrix);
+    }
+    else if (structure)
+    {
+        const TString &structName =
+            QualifiedStructNameString(*structure, useHLSLRowMajorPacking, true);
+        numComponents = mStructElementIndexes->find(structName)->second;
+
+        if (numComponents == 0)
+        {
+            return "";
+        }
+    }
+    else
+    {
+        const GLenum glType = GLVariableType(type);
+        numComponents       = gl::VariableComponentCount(glType);
+    }
+
+    TString padding;
+    for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++)
+    {
+        padding += "    float pad_" + next() + ";\n";
+    }
+    return padding;
+}
+
+StructureHLSL::StructureHLSL() : mUniquePaddingCounter(0)
+{
+}
+
+Std140PaddingHelper StructureHLSL::getPaddingHelper()
+{
+    return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter);
+}
+
+TString StructureHLSL::defineQualified(const TStructure &structure,
+                                       bool useHLSLRowMajorPacking,
+                                       bool useStd140Packing)
+{
+    if (useStd140Packing)
+    {
+        Std140PaddingHelper padHelper = getPaddingHelper();
+        return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper);
+    }
+    else
+    {
+        return define(structure, useHLSLRowMajorPacking, useStd140Packing, nullptr);
+    }
+}
+
+TString StructureHLSL::defineNameless(const TStructure &structure)
+{
+    return define(structure, false, false, nullptr);
+}
+
+TString StructureHLSL::define(const TStructure &structure,
+                              bool useHLSLRowMajorPacking,
+                              bool useStd140Packing,
+                              Std140PaddingHelper *padHelper)
+{
+    const TFieldList &fields = structure.fields();
+    const bool isNameless    = (structure.name() == "");
+    const TString &structName =
+        QualifiedStructNameString(structure, useHLSLRowMajorPacking, useStd140Packing);
+    const TString declareString = (isNameless ? "struct" : "struct " + structName);
+
+    TString string;
+    string += declareString +
+              "\n"
+              "{\n";
+
+    for (const TField *field : fields)
+    {
+        const TType &fieldType = *field->type();
+        if (!IsSampler(fieldType.getBasicType()))
+        {
+            const TStructure *fieldStruct = fieldType.getStruct();
+            const TString &fieldTypeString =
+                fieldStruct ? QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking,
+                                                        useStd140Packing)
+                            : TypeString(fieldType);
+
+            if (padHelper)
+            {
+                string += padHelper->prePaddingString(fieldType);
+            }
+
+            string += "    " + fieldTypeString + " " + DecorateField(field->name(), structure) +
+                      ArrayString(fieldType) + ";\n";
+
+            if (padHelper)
+            {
+                string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking);
+            }
+        }
+    }
+
+    // Nameless structs do not finish with a semicolon and newline, to leave room for an instance
+    // variable
+    string += (isNameless ? "} " : "};\n");
+
+    return string;
+}
+
+TString StructureHLSL::addConstructor(const TType &type,
+                                      const TString &name,
+                                      const TIntermSequence *parameters)
+{
+    if (name == "")
+    {
+        return TString();  // Nameless structures don't have constructors
+    }
+
+    if (type.getStruct() && mStructNames.find(name) != mStructNames.end())
+    {
+        return TString(name);  // Already added
+    }
+
+    TType ctorType = type;
+    ctorType.clearArrayness();
+    ctorType.setPrecision(EbpHigh);
+    ctorType.setQualifier(EvqTemporary);
+
+    typedef std::vector<TType> ParameterArray;
+    ParameterArray ctorParameters;
+
+    TString constructorFunctionName;
+
+    const TStructure *structure = type.getStruct();
+    if (structure)
+    {
+        mStructNames.insert(name);
+
+        // Add element index
+        storeStd140ElementIndex(*structure, false);
+        storeStd140ElementIndex(*structure, true);
+
+        const TString &structString = defineQualified(*structure, false, false);
+
+        if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) ==
+            mStructDeclarations.end())
+        {
+            // Add row-major packed struct for interface blocks
+            TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
+                                     defineQualified(*structure, true, false) +
+                                     "#pragma pack_matrix(column_major)\n";
+
+            TString std140String         = defineQualified(*structure, false, true);
+            TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
+                                           defineQualified(*structure, true, true) +
+                                           "#pragma pack_matrix(column_major)\n";
+
+            mStructDeclarations.push_back(structString);
+            mStructDeclarations.push_back(rowMajorString);
+            mStructDeclarations.push_back(std140String);
+            mStructDeclarations.push_back(std140RowMajorString);
+        }
+
+        const TFieldList &fields = structure->fields();
+        for (const TField *field : fields)
+        {
+            const TType *fieldType = field->type();
+            if (!IsSampler(fieldType->getBasicType()))
+            {
+                ctorParameters.push_back(*fieldType);
+            }
+        }
+        constructorFunctionName = TString(name);
+    }
+    else if (parameters)
+    {
+        for (auto parameter : *parameters)
+        {
+            const TType &paramType = parameter->getAsTyped()->getType();
+            ctorParameters.push_back(paramType);
+        }
+        constructorFunctionName = TString(name) + DisambiguateFunctionName(parameters);
+    }
+    else
+        UNREACHABLE();
+
+    TString constructor;
+
+    if (ctorType.getStruct())
+    {
+        constructor += name + " " + name + "_ctor(";
+    }
+    else  // Built-in type
+    {
+        constructor += TypeString(ctorType) + " " + constructorFunctionName + "(";
+    }
+
+    for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
+    {
+        const TType &paramType = ctorParameters[parameter];
+
+        constructor += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType);
+
+        if (parameter < ctorParameters.size() - 1)
+        {
+            constructor += ", ";
+        }
+    }
+
+    constructor +=
+        ")\n"
+        "{\n";
+
+    if (ctorType.getStruct())
+    {
+        constructor += "    " + name + " structure";
+        if (ctorParameters.empty())
+        {
+            constructor += ";\n";
+        }
+        else
+        {
+            constructor += " = { ";
+        }
+    }
+    else
+    {
+        constructor += "    return " + TypeString(ctorType) + "(";
+    }
+
+    if (ctorType.isMatrix() && ctorParameters.size() == 1)
+    {
+        int rows               = ctorType.getRows();
+        int cols               = ctorType.getCols();
+        const TType &parameter = ctorParameters[0];
+
+        if (parameter.isScalar())
+        {
+            for (int col = 0; col < cols; col++)
+            {
+                for (int row = 0; row < rows; row++)
+                {
+                    constructor += TString((row == col) ? "x0" : "0.0");
+
+                    if (row < rows - 1 || col < cols - 1)
+                    {
+                        constructor += ", ";
+                    }
+                }
+            }
+        }
+        else if (parameter.isMatrix())
+        {
+            for (int col = 0; col < cols; col++)
+            {
+                for (int row = 0; row < rows; row++)
+                {
+                    if (row < parameter.getRows() && col < parameter.getCols())
+                    {
+                        constructor += TString("x0") + "[" + str(col) + "][" + str(row) + "]";
+                    }
+                    else
+                    {
+                        constructor += TString((row == col) ? "1.0" : "0.0");
+                    }
+
+                    if (row < rows - 1 || col < cols - 1)
+                    {
+                        constructor += ", ";
+                    }
+                }
+            }
+        }
+        else
+        {
+            ASSERT(rows == 2 && cols == 2 && parameter.isVector() &&
+                   parameter.getNominalSize() == 4);
+
+            constructor += "x0";
+        }
+    }
+    else
+    {
+        size_t remainingComponents = 0;
+        if (ctorType.getStruct())
+        {
+            remainingComponents = ctorParameters.size();
+        }
+        else
+        {
+            remainingComponents = ctorType.getObjectSize();
+        }
+        size_t parameterIndex = 0;
+
+        while (remainingComponents > 0)
+        {
+            const TType &parameter     = ctorParameters[parameterIndex];
+            const size_t parameterSize = parameter.getObjectSize();
+            bool moreParameters        = parameterIndex + 1 < ctorParameters.size();
+
+            constructor += "x" + str(parameterIndex);
+
+            if (ctorType.getStruct())
+            {
+                ASSERT(remainingComponents == 1 || moreParameters);
+
+                --remainingComponents;
+            }
+            else if (parameter.isScalar())
+            {
+                remainingComponents -= parameter.getObjectSize();
+            }
+            else if (parameter.isVector())
+            {
+                if (remainingComponents == parameterSize || moreParameters)
+                {
+                    ASSERT(parameterSize <= remainingComponents);
+                    remainingComponents -= parameterSize;
+                }
+                else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
+                {
+                    switch (remainingComponents)
+                    {
+                        case 1:
+                            constructor += ".x";
+                            break;
+                        case 2:
+                            constructor += ".xy";
+                            break;
+                        case 3:
+                            constructor += ".xyz";
+                            break;
+                        case 4:
+                            constructor += ".xyzw";
+                            break;
+                        default:
+                            UNREACHABLE();
+                    }
+
+                    remainingComponents = 0;
+                }
+                else
+                    UNREACHABLE();
+            }
+            else if (parameter.isMatrix())
+            {
+                int column = 0;
+                while (remainingComponents > 0 && column < parameter.getCols())
+                {
+                    constructor += "[" + str(column) + "]";
+
+                    if (remainingComponents < static_cast<size_t>(parameter.getRows()))
+                    {
+                        switch (remainingComponents)
+                        {
+                            case 1:
+                                constructor += ".x";
+                                break;
+                            case 2:
+                                constructor += ".xy";
+                                break;
+                            case 3:
+                                constructor += ".xyz";
+                                break;
+                            default:
+                                UNREACHABLE();
+                        }
+
+                        remainingComponents = 0;
+                    }
+                    else
+                    {
+                        remainingComponents -= parameter.getRows();
+
+                        if (remainingComponents > 0)
+                        {
+                            constructor += ", x" + str(parameterIndex);
+                        }
+                    }
+
+                    column++;
+                }
+            }
+            else
+                UNREACHABLE();
+
+            if (moreParameters)
+            {
+                parameterIndex++;
+            }
+
+            if (remainingComponents)
+            {
+                constructor += ", ";
+            }
+        }
+    }
+
+    if (ctorType.getStruct())
+    {
+        if (!ctorParameters.empty())
+        {
+            constructor += "};\n";
+        }
+        constructor +=
+            "    return structure;\n"
+            "}\n";
+    }
+    else
+    {
+        constructor +=
+            ");\n"
+            "}\n";
+    }
+
+    mConstructors.insert(constructor);
+
+    return constructorFunctionName;
+}
+
+std::string StructureHLSL::structsHeader() const
+{
+    TInfoSinkBase out;
+
+    for (size_t structIndex = 0; structIndex < mStructDeclarations.size(); structIndex++)
+    {
+        out << mStructDeclarations[structIndex];
+    }
+
+    for (Constructors::const_iterator constructor = mConstructors.begin();
+         constructor != mConstructors.end(); constructor++)
+    {
+        out << *constructor;
+    }
+
+    return out.str();
+}
+
+void StructureHLSL::storeStd140ElementIndex(const TStructure &structure,
+                                            bool useHLSLRowMajorPacking)
+{
+    Std140PaddingHelper padHelper = getPaddingHelper();
+    const TFieldList &fields      = structure.fields();
+
+    for (unsigned int i = 0; i < fields.size(); i++)
+    {
+        padHelper.prePadding(*fields[i]->type());
+    }
+
+    // Add remaining element index to the global map, for use with nested structs in standard
+    // layouts
+    const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, true);
+    mStd140StructElementIndexes[structName] = padHelper.elementIndex();
+}
+}
diff --git a/src/third_party/angle/src/compiler/translator/StructureHLSL.h b/src/third_party/angle/src/compiler/translator/StructureHLSL.h
new file mode 100644
index 0000000..b8c6d62
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/StructureHLSL.h
@@ -0,0 +1,88 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// StructureHLSL.h:
+//   Interfaces of methods for HLSL translation of GLSL structures.
+//
+
+#ifndef COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
+#define COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
+
+#include "compiler/translator/Common.h"
+#include "compiler/translator/IntermNode.h"
+
+#include <set>
+
+class TInfoSinkBase;
+class TScopeBracket;
+
+namespace sh
+{
+
+// This helper class assists structure and interface block definitions in determining
+// how to pack std140 structs within HLSL's packing rules.
+class Std140PaddingHelper
+{
+  public:
+    explicit Std140PaddingHelper(const std::map<TString, int> &structElementIndexes,
+                                 unsigned int *uniqueCounter);
+    Std140PaddingHelper(const Std140PaddingHelper &other);
+    Std140PaddingHelper &operator=(const Std140PaddingHelper &other);
+
+    int elementIndex() const { return mElementIndex; }
+    int prePadding(const TType &type);
+    TString prePaddingString(const TType &type);
+    TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking);
+
+  private:
+    TString next();
+
+    unsigned *mPaddingCounter;
+    int mElementIndex;
+    const std::map<TString, int> *mStructElementIndexes;
+};
+
+class StructureHLSL : angle::NonCopyable
+{
+  public:
+    StructureHLSL();
+
+    // Returns the name of the constructor function. "name" parameter is the name of the type being
+    // constructed.
+    TString addConstructor(const TType &type,
+                           const TString &name,
+                           const TIntermSequence *parameters);
+    std::string structsHeader() const;
+
+    TString defineQualified(const TStructure &structure,
+                            bool useHLSLRowMajorPacking,
+                            bool useStd140Packing);
+    static TString defineNameless(const TStructure &structure);
+
+    Std140PaddingHelper getPaddingHelper();
+
+  private:
+    unsigned mUniquePaddingCounter;
+
+    std::map<TString, int> mStd140StructElementIndexes;
+
+    typedef std::set<TString> StructNames;
+    StructNames mStructNames;
+
+    typedef std::set<TString> Constructors;
+    Constructors mConstructors;
+
+    typedef std::vector<TString> StructDeclarations;
+    StructDeclarations mStructDeclarations;
+
+    void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking);
+    static TString define(const TStructure &structure,
+                          bool useHLSLRowMajorPacking,
+                          bool useStd140Packing,
+                          Std140PaddingHelper *padHelper);
+};
+}
+
+#endif  // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/SymbolTable.cpp b/src/third_party/angle/src/compiler/translator/SymbolTable.cpp
new file mode 100644
index 0000000..a7f7e8f
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SymbolTable.cpp
@@ -0,0 +1,536 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Symbol table for parsing.  Most functionaliy and main ideas
+// are documented in the header file.
+//
+
+#if defined(_MSC_VER)
+#pragma warning(disable : 4718)
+#endif
+
+#include "compiler/translator/SymbolTable.h"
+
+#include "compiler/translator/Cache.h"
+#include "compiler/translator/IntermNode.h"
+
+#include <stdio.h>
+#include <algorithm>
+
+namespace sh
+{
+
+namespace
+{
+
+static const char kFunctionMangledNameSeparator = '(';
+
+}  // anonymous namespace
+
+int TSymbolTable::uniqueIdCounter = 0;
+
+TSymbolUniqueId::TSymbolUniqueId() : mId(TSymbolTable::nextUniqueId())
+{
+}
+
+TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.getUniqueId())
+{
+}
+
+int TSymbolUniqueId::get() const
+{
+    return mId;
+}
+
+TSymbol::TSymbol(const TString *n) : uniqueId(TSymbolTable::nextUniqueId()), name(n)
+{
+}
+
+//
+// Functions have buried pointers to delete.
+//
+TFunction::~TFunction()
+{
+    clearParameters();
+}
+
+void TFunction::clearParameters()
+{
+    for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
+        delete (*i).type;
+    parameters.clear();
+    mangledName = nullptr;
+}
+
+void TFunction::swapParameters(const TFunction &parametersSource)
+{
+    clearParameters();
+    for (auto parameter : parametersSource.parameters)
+    {
+        addParameter(parameter);
+    }
+}
+
+const TString *TFunction::buildMangledName() const
+{
+    std::string newName = getName().c_str();
+    newName += kFunctionMangledNameSeparator;
+
+    for (const auto &p : parameters)
+    {
+        newName += p.type->getMangledName().c_str();
+    }
+    return NewPoolTString(newName.c_str());
+}
+
+const TString &TFunction::GetMangledNameFromCall(const TString &functionName,
+                                                 const TIntermSequence &arguments)
+{
+    std::string newName = functionName.c_str();
+    newName += kFunctionMangledNameSeparator;
+
+    for (TIntermNode *argument : arguments)
+    {
+        newName += argument->getAsTyped()->getType().getMangledName().c_str();
+    }
+    return *NewPoolTString(newName.c_str());
+}
+
+//
+// Symbol table levels are a map of pointers to symbols that have to be deleted.
+//
+TSymbolTableLevel::~TSymbolTableLevel()
+{
+    for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+        delete (*it).second;
+}
+
+bool TSymbolTableLevel::insert(TSymbol *symbol)
+{
+    // returning true means symbol was added to the table
+    tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
+
+    return result.second;
+}
+
+bool TSymbolTableLevel::insertUnmangled(TFunction *function)
+{
+    // returning true means symbol was added to the table
+    tInsertResult result = level.insert(tLevelPair(function->getName(), function));
+
+    return result.second;
+}
+
+TSymbol *TSymbolTableLevel::find(const TString &name) const
+{
+    tLevel::const_iterator it = level.find(name);
+    if (it == level.end())
+        return 0;
+    else
+        return (*it).second;
+}
+
+TSymbol *TSymbolTable::find(const TString &name,
+                            int shaderVersion,
+                            bool *builtIn,
+                            bool *sameScope) const
+{
+    int level = currentLevel();
+    TSymbol *symbol;
+
+    do
+    {
+        if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
+            level--;
+        if (level == ESSL3_BUILTINS && shaderVersion < 300)
+            level--;
+        if (level == ESSL1_BUILTINS && shaderVersion != 100)
+            level--;
+
+        symbol = table[level]->find(name);
+    } while (symbol == 0 && --level >= 0);
+
+    if (builtIn)
+        *builtIn = (level <= LAST_BUILTIN_LEVEL);
+    if (sameScope)
+        *sameScope = (level == currentLevel());
+
+    return symbol;
+}
+
+TSymbol *TSymbolTable::findGlobal(const TString &name) const
+{
+    ASSERT(table.size() > GLOBAL_LEVEL);
+    return table[GLOBAL_LEVEL]->find(name);
+}
+
+TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const
+{
+    for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
+    {
+        if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
+            level--;
+        if (level == ESSL3_BUILTINS && shaderVersion < 300)
+            level--;
+        if (level == ESSL1_BUILTINS && shaderVersion != 100)
+            level--;
+
+        TSymbol *symbol = table[level]->find(name);
+
+        if (symbol)
+            return symbol;
+    }
+
+    return 0;
+}
+
+TSymbolTable::~TSymbolTable()
+{
+    while (table.size() > 0)
+        pop();
+}
+
+bool IsGenType(const TType *type)
+{
+    if (type)
+    {
+        TBasicType basicType = type->getBasicType();
+        return basicType == EbtGenType || basicType == EbtGenIType || basicType == EbtGenUType ||
+               basicType == EbtGenBType;
+    }
+
+    return false;
+}
+
+bool IsVecType(const TType *type)
+{
+    if (type)
+    {
+        TBasicType basicType = type->getBasicType();
+        return basicType == EbtVec || basicType == EbtIVec || basicType == EbtUVec ||
+               basicType == EbtBVec;
+    }
+
+    return false;
+}
+
+const TType *SpecificType(const TType *type, int size)
+{
+    ASSERT(size >= 1 && size <= 4);
+
+    if (!type)
+    {
+        return nullptr;
+    }
+
+    ASSERT(!IsVecType(type));
+
+    switch (type->getBasicType())
+    {
+        case EbtGenType:
+            return TCache::getType(EbtFloat, type->getQualifier(),
+                                   static_cast<unsigned char>(size));
+        case EbtGenIType:
+            return TCache::getType(EbtInt, type->getQualifier(), static_cast<unsigned char>(size));
+        case EbtGenUType:
+            return TCache::getType(EbtUInt, type->getQualifier(), static_cast<unsigned char>(size));
+        case EbtGenBType:
+            return TCache::getType(EbtBool, type->getQualifier(), static_cast<unsigned char>(size));
+        default:
+            return type;
+    }
+}
+
+const TType *VectorType(const TType *type, int size)
+{
+    ASSERT(size >= 2 && size <= 4);
+
+    if (!type)
+    {
+        return nullptr;
+    }
+
+    ASSERT(!IsGenType(type));
+
+    switch (type->getBasicType())
+    {
+        case EbtVec:
+            return TCache::getType(EbtFloat, static_cast<unsigned char>(size));
+        case EbtIVec:
+            return TCache::getType(EbtInt, static_cast<unsigned char>(size));
+        case EbtUVec:
+            return TCache::getType(EbtUInt, static_cast<unsigned char>(size));
+        case EbtBVec:
+            return TCache::getType(EbtBool, static_cast<unsigned char>(size));
+        default:
+            return type;
+    }
+}
+
+void TSymbolTable::insertBuiltIn(ESymbolLevel level,
+                                 TOperator op,
+                                 const char *ext,
+                                 const TType *rvalue,
+                                 const char *name,
+                                 const TType *ptype1,
+                                 const TType *ptype2,
+                                 const TType *ptype3,
+                                 const TType *ptype4,
+                                 const TType *ptype5)
+{
+    if (ptype1->getBasicType() == EbtGSampler2D)
+    {
+        insertUnmangledBuiltInName(name, level);
+        bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+                      TCache::getType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+                      TCache::getType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+                      TCache::getType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5);
+    }
+    else if (ptype1->getBasicType() == EbtGSampler3D)
+    {
+        insertUnmangledBuiltInName(name, level);
+        bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+                      TCache::getType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+                      TCache::getType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+                      TCache::getType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5);
+    }
+    else if (ptype1->getBasicType() == EbtGSamplerCube)
+    {
+        insertUnmangledBuiltInName(name, level);
+        bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+                      TCache::getType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+                      TCache::getType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+                      TCache::getType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5);
+    }
+    else if (ptype1->getBasicType() == EbtGSampler2DArray)
+    {
+        insertUnmangledBuiltInName(name, level);
+        bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+                      TCache::getType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+                      TCache::getType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+                      TCache::getType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5);
+    }
+    else if (ptype1->getBasicType() == EbtGSampler2DMS)
+    {
+        insertUnmangledBuiltInName(name, level);
+        bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+                      TCache::getType(EbtSampler2DMS), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+                      TCache::getType(EbtISampler2DMS), ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+                      TCache::getType(EbtUSampler2DMS), ptype2, ptype3, ptype4, ptype5);
+    }
+    else if (IsGImage(ptype1->getBasicType()))
+    {
+        insertUnmangledBuiltInName(name, level);
+
+        const TType *floatType    = TCache::getType(EbtFloat, 4);
+        const TType *intType      = TCache::getType(EbtInt, 4);
+        const TType *unsignedType = TCache::getType(EbtUInt, 4);
+
+        const TType *floatImage =
+            TCache::getType(convertGImageToFloatImage(ptype1->getBasicType()));
+        const TType *intImage = TCache::getType(convertGImageToIntImage(ptype1->getBasicType()));
+        const TType *unsignedImage =
+            TCache::getType(convertGImageToUnsignedImage(ptype1->getBasicType()));
+
+        // GLSL ES 3.10, Revision 4, 8.12 Image Functions
+        if (rvalue->getBasicType() == EbtGVec4)
+        {
+            // imageLoad
+            insertBuiltIn(level, floatType, name, floatImage, ptype2, ptype3, ptype4, ptype5);
+            insertBuiltIn(level, intType, name, intImage, ptype2, ptype3, ptype4, ptype5);
+            insertBuiltIn(level, unsignedType, name, unsignedImage, ptype2, ptype3, ptype4, ptype5);
+        }
+        else if (rvalue->getBasicType() == EbtVoid)
+        {
+            // imageStore
+            insertBuiltIn(level, rvalue, name, floatImage, ptype2, floatType, ptype4, ptype5);
+            insertBuiltIn(level, rvalue, name, intImage, ptype2, intType, ptype4, ptype5);
+            insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, unsignedType, ptype4, ptype5);
+        }
+        else
+        {
+            // imageSize
+            insertBuiltIn(level, rvalue, name, floatImage, ptype2, ptype3, ptype4, ptype5);
+            insertBuiltIn(level, rvalue, name, intImage, ptype2, ptype3, ptype4, ptype5);
+            insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, ptype3, ptype4, ptype5);
+        }
+    }
+    else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3) ||
+             IsGenType(ptype4))
+    {
+        ASSERT(!ptype5);
+        insertUnmangledBuiltInName(name, level);
+        insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1),
+                      SpecificType(ptype2, 1), SpecificType(ptype3, 1), SpecificType(ptype4, 1));
+        insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2),
+                      SpecificType(ptype2, 2), SpecificType(ptype3, 2), SpecificType(ptype4, 2));
+        insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3),
+                      SpecificType(ptype2, 3), SpecificType(ptype3, 3), SpecificType(ptype4, 3));
+        insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4),
+                      SpecificType(ptype2, 4), SpecificType(ptype3, 4), SpecificType(ptype4, 4));
+    }
+    else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3))
+    {
+        ASSERT(!ptype4 && !ptype5);
+        insertUnmangledBuiltInName(name, level);
+        insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2),
+                      VectorType(ptype2, 2), VectorType(ptype3, 2));
+        insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3),
+                      VectorType(ptype2, 3), VectorType(ptype3, 3));
+        insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4),
+                      VectorType(ptype2, 4), VectorType(ptype3, 4));
+    }
+    else
+    {
+        TFunction *function = new TFunction(NewPoolTString(name), rvalue, op, ext);
+
+        function->addParameter(TConstParameter(ptype1));
+
+        if (ptype2)
+        {
+            function->addParameter(TConstParameter(ptype2));
+        }
+
+        if (ptype3)
+        {
+            function->addParameter(TConstParameter(ptype3));
+        }
+
+        if (ptype4)
+        {
+            function->addParameter(TConstParameter(ptype4));
+        }
+
+        if (ptype5)
+        {
+            function->addParameter(TConstParameter(ptype5));
+        }
+
+        ASSERT(hasUnmangledBuiltInAtLevel(name, level));
+        insert(level, function);
+    }
+}
+
+void TSymbolTable::insertBuiltInOp(ESymbolLevel level,
+                                   TOperator op,
+                                   const TType *rvalue,
+                                   const TType *ptype1,
+                                   const TType *ptype2,
+                                   const TType *ptype3,
+                                   const TType *ptype4,
+                                   const TType *ptype5)
+{
+    const char *name = GetOperatorString(op);
+    ASSERT(strlen(name) > 0);
+    insertUnmangledBuiltInName(name, level);
+    insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+}
+
+void TSymbolTable::insertBuiltInOp(ESymbolLevel level,
+                                   TOperator op,
+                                   const char *ext,
+                                   const TType *rvalue,
+                                   const TType *ptype1,
+                                   const TType *ptype2,
+                                   const TType *ptype3,
+                                   const TType *ptype4,
+                                   const TType *ptype5)
+{
+    const char *name = GetOperatorString(op);
+    insertUnmangledBuiltInName(name, level);
+    insertBuiltIn(level, op, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+}
+
+void TSymbolTable::insertBuiltInFunctionNoParameters(ESymbolLevel level,
+                                                     TOperator op,
+                                                     const TType *rvalue,
+                                                     const char *name)
+{
+    insertUnmangledBuiltInName(name, level);
+    insert(level, new TFunction(NewPoolTString(name), rvalue, op));
+}
+
+TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
+{
+    if (!SupportsPrecision(type))
+        return EbpUndefined;
+
+    // unsigned integers use the same precision as signed
+    TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
+
+    int level = static_cast<int>(precisionStack.size()) - 1;
+    assert(level >= 0);  // Just to be safe. Should not happen.
+    // If we dont find anything we return this. Some types don't have predefined default precision.
+    TPrecision prec = EbpUndefined;
+    while (level >= 0)
+    {
+        PrecisionStackLevel::iterator it = precisionStack[level]->find(baseType);
+        if (it != precisionStack[level]->end())
+        {
+            prec = (*it).second;
+            break;
+        }
+        level--;
+    }
+    return prec;
+}
+
+void TSymbolTable::insertUnmangledBuiltInName(const char *name, ESymbolLevel level)
+{
+    ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size()));
+    table[level]->insertUnmangledBuiltInName(std::string(name));
+}
+
+bool TSymbolTable::hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level)
+{
+    ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size()));
+    return table[level]->hasUnmangledBuiltIn(std::string(name));
+}
+
+bool TSymbolTable::hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion)
+{
+    ASSERT(static_cast<ESymbolLevel>(table.size()) > LAST_BUILTIN_LEVEL);
+
+    for (int level = LAST_BUILTIN_LEVEL; level >= 0; --level)
+    {
+        if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
+        {
+            --level;
+        }
+        if (level == ESSL3_BUILTINS && shaderVersion < 300)
+        {
+            --level;
+        }
+        if (level == ESSL1_BUILTINS && shaderVersion != 100)
+        {
+            --level;
+        }
+
+        if (table[level]->hasUnmangledBuiltIn(name))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/SymbolTable.h b/src/third_party/angle/src/compiler/translator/SymbolTable.h
new file mode 100644
index 0000000..e76768f
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/SymbolTable.h
@@ -0,0 +1,513 @@
+//
+// 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.
+//
+
+#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_
+#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_
+
+//
+// Symbol table for parsing.  Has these design characteristics:
+//
+// * Same symbol table can be used to compile many shaders, to preserve
+//   effort of creating and loading with the large numbers of built-in
+//   symbols.
+//
+// * Name mangling will be used to give each function a unique name
+//   so that symbol table lookups are never ambiguous.  This allows
+//   a simpler symbol table structure.
+//
+// * Pushing and popping of scope, so symbol table will really be a stack
+//   of symbol tables.  Searched from the top, with new inserts going into
+//   the top.
+//
+// * Constants:  Compile time constant symbols will keep their values
+//   in the symbol table.  The parser can substitute constants at parse
+//   time, including doing constant folding and constant propagation.
+//
+// * No temporaries:  Temporaries made from operations (+, --, .xy, etc.)
+//   are tracked in the intermediate representation, not the symbol table.
+//
+
+#include <array>
+#include <assert.h>
+#include <set>
+
+#include "common/angleutils.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+// Encapsulates a unique id for a symbol.
+class TSymbolUniqueId
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TSymbolUniqueId();
+    TSymbolUniqueId(const TSymbol &symbol);
+    TSymbolUniqueId(const TSymbolUniqueId &) = default;
+    TSymbolUniqueId &operator=(const TSymbolUniqueId &) = default;
+
+    int get() const;
+
+  private:
+    int mId;
+};
+
+// Symbol base class. (Can build functions or variables out of these...)
+class TSymbol : angle::NonCopyable
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TSymbol(const TString *n);
+
+    virtual ~TSymbol()
+    {
+        // don't delete name, it's from the pool
+    }
+
+    const TString &getName() const { return *name; }
+    virtual const TString &getMangledName() const { return getName(); }
+    virtual bool isFunction() const { return false; }
+    virtual bool isVariable() const { return false; }
+    int getUniqueId() const { return uniqueId; }
+    void relateToExtension(const TString &ext) { extension = ext; }
+    const TString &getExtension() const { return extension; }
+
+  private:
+    const int uniqueId;
+    const TString *name;
+    TString extension;
+};
+
+// Variable class, meaning a symbol that's not a function.
+//
+// There could be a separate class heirarchy for Constant variables;
+// Only one of int, bool, or float, (or none) is correct for
+// any particular use, but it's easy to do this way, and doesn't
+// seem worth having separate classes, and "getConst" can't simply return
+// different values for different types polymorphically, so this is
+// just simple and pragmatic.
+class TVariable : public TSymbol
+{
+  public:
+    TVariable(const TString *name, const TType &t, bool uT = false)
+        : TSymbol(name), type(t), userType(uT), unionArray(0)
+    {
+    }
+    ~TVariable() override {}
+    bool isVariable() const override { return true; }
+    TType &getType() { return type; }
+    const TType &getType() const { return type; }
+    bool isUserType() const { return userType; }
+    void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
+
+    const TConstantUnion *getConstPointer() const { return unionArray; }
+
+    void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
+
+  private:
+    TType type;
+    bool userType;
+    // we are assuming that Pool Allocator will free the memory
+    // allocated to unionArray when this object is destroyed.
+    const TConstantUnion *unionArray;
+};
+
+// Immutable version of TParameter.
+struct TConstParameter
+{
+    TConstParameter() : name(nullptr), type(nullptr) {}
+    explicit TConstParameter(const TString *n) : name(n), type(nullptr) {}
+    explicit TConstParameter(const TType *t) : name(nullptr), type(t) {}
+    TConstParameter(const TString *n, const TType *t) : name(n), type(t) {}
+
+    // Both constructor arguments must be const.
+    TConstParameter(TString *n, TType *t)       = delete;
+    TConstParameter(const TString *n, TType *t) = delete;
+    TConstParameter(TString *n, const TType *t) = delete;
+
+    const TString *name;
+    const TType *type;
+};
+
+// The function sub-class of symbols and the parser will need to
+// share this definition of a function parameter.
+struct TParameter
+{
+    // Destructively converts to TConstParameter.
+    // This method resets name and type to nullptrs to make sure
+    // their content cannot be modified after the call.
+    TConstParameter turnToConst()
+    {
+        const TString *constName = name;
+        const TType *constType   = type;
+        name                     = nullptr;
+        type                     = nullptr;
+        return TConstParameter(constName, constType);
+    }
+
+    TString *name;
+    TType *type;
+};
+
+// The function sub-class of a symbol.
+class TFunction : public TSymbol
+{
+  public:
+    TFunction(const TString *name,
+              const TType *retType,
+              TOperator tOp   = EOpNull,
+              const char *ext = "")
+        : TSymbol(name),
+          returnType(retType),
+          mangledName(nullptr),
+          op(tOp),
+          defined(false),
+          mHasPrototypeDeclaration(false)
+    {
+        relateToExtension(ext);
+    }
+    ~TFunction() override;
+    bool isFunction() const override { return true; }
+
+    void addParameter(const TConstParameter &p)
+    {
+        parameters.push_back(p);
+        mangledName = nullptr;
+    }
+
+    void swapParameters(const TFunction &parametersSource);
+
+    const TString &getMangledName() const override
+    {
+        if (mangledName == nullptr)
+        {
+            mangledName = buildMangledName();
+        }
+        return *mangledName;
+    }
+
+    static const TString &GetMangledNameFromCall(const TString &functionName,
+                                                 const TIntermSequence &arguments);
+
+    const TType &getReturnType() const { return *returnType; }
+
+    TOperator getBuiltInOp() const { return op; }
+
+    void setDefined() { defined = true; }
+    bool isDefined() { return defined; }
+    void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
+    bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
+
+    size_t getParamCount() const { return parameters.size(); }
+    const TConstParameter &getParam(size_t i) const { return parameters[i]; }
+
+  private:
+    void clearParameters();
+
+    const TString *buildMangledName() const;
+
+    typedef TVector<TConstParameter> TParamList;
+    TParamList parameters;
+    const TType *returnType;
+    mutable const TString *mangledName;
+    TOperator op;
+    bool defined;
+    bool mHasPrototypeDeclaration;
+};
+
+// Interface block name sub-symbol
+class TInterfaceBlockName : public TSymbol
+{
+  public:
+    TInterfaceBlockName(const TString *name) : TSymbol(name) {}
+
+    virtual ~TInterfaceBlockName() {}
+};
+
+class TSymbolTableLevel
+{
+  public:
+    typedef TMap<TString, TSymbol *> tLevel;
+    typedef tLevel::const_iterator const_iterator;
+    typedef const tLevel::value_type tLevelPair;
+    typedef std::pair<tLevel::iterator, bool> tInsertResult;
+
+    TSymbolTableLevel() : mGlobalInvariant(false) {}
+    ~TSymbolTableLevel();
+
+    bool insert(TSymbol *symbol);
+
+    // Insert a function using its unmangled name as the key.
+    bool insertUnmangled(TFunction *function);
+
+    TSymbol *find(const TString &name) const;
+
+    void addInvariantVarying(const std::string &name) { mInvariantVaryings.insert(name); }
+
+    bool isVaryingInvariant(const std::string &name)
+    {
+        return (mGlobalInvariant || mInvariantVaryings.count(name) > 0);
+    }
+
+    void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; }
+
+    void insertUnmangledBuiltInName(const std::string &name)
+    {
+        mUnmangledBuiltInNames.insert(name);
+    }
+
+    bool hasUnmangledBuiltIn(const std::string &name)
+    {
+        return mUnmangledBuiltInNames.count(name) > 0;
+    }
+
+  protected:
+    tLevel level;
+    std::set<std::string> mInvariantVaryings;
+    bool mGlobalInvariant;
+
+  private:
+    std::set<std::string> mUnmangledBuiltInNames;
+};
+
+// Define ESymbolLevel as int rather than an enum since level can go
+// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
+// compiler optimizes the >= of the last element to ==.
+typedef int ESymbolLevel;
+const int COMMON_BUILTINS    = 0;
+const int ESSL1_BUILTINS     = 1;
+const int ESSL3_BUILTINS     = 2;
+const int ESSL3_1_BUILTINS   = 3;
+const int LAST_BUILTIN_LEVEL = ESSL3_1_BUILTINS;
+const int GLOBAL_LEVEL       = 4;
+
+class TSymbolTable : angle::NonCopyable
+{
+  public:
+    TSymbolTable()
+    {
+        // The symbol table cannot be used until push() is called, but
+        // the lack of an initial call to push() can be used to detect
+        // that the symbol table has not been preloaded with built-ins.
+    }
+
+    ~TSymbolTable();
+
+    // When the symbol table is initialized with the built-ins, there should
+    // 'push' calls, so that built-ins are at level 0 and the shader
+    // globals are at level 1.
+    bool isEmpty() const { return table.empty(); }
+    bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; }
+    bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; }
+    void push()
+    {
+        table.push_back(new TSymbolTableLevel);
+        precisionStack.push_back(new PrecisionStackLevel);
+    }
+
+    void pop()
+    {
+        delete table.back();
+        table.pop_back();
+
+        delete precisionStack.back();
+        precisionStack.pop_back();
+    }
+
+    bool declare(TSymbol *symbol) { return insert(currentLevel(), symbol); }
+
+    bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); }
+
+    bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol)
+    {
+        symbol->relateToExtension(ext);
+        return table[level]->insert(symbol);
+    }
+
+    bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
+    {
+        TVariable *constant =
+            new TVariable(NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1));
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray[0].setIConst(value);
+        constant->shareConstPointer(unionArray);
+        return insert(level, constant);
+    }
+
+    bool insertConstIntExt(ESymbolLevel level, const char *ext, const char *name, int value)
+    {
+        TVariable *constant =
+            new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray[0].setIConst(value);
+        constant->shareConstPointer(unionArray);
+        return insert(level, ext, constant);
+    }
+
+    bool insertConstIvec3(ESymbolLevel level,
+                          const char *name,
+                          const std::array<int, 3> &values,
+                          TPrecision precision)
+    {
+        TVariable *constantIvec3 =
+            new TVariable(NewPoolTString(name), TType(EbtInt, precision, EvqConst, 3));
+
+        TConstantUnion *unionArray = new TConstantUnion[3];
+        for (size_t index = 0u; index < 3u; ++index)
+        {
+            unionArray[index].setIConst(values[index]);
+        }
+        constantIvec3->shareConstPointer(unionArray);
+
+        return insert(level, constantIvec3);
+    }
+
+    void insertBuiltIn(ESymbolLevel level,
+                       TOperator op,
+                       const char *ext,
+                       const TType *rvalue,
+                       const char *name,
+                       const TType *ptype1,
+                       const TType *ptype2 = 0,
+                       const TType *ptype3 = 0,
+                       const TType *ptype4 = 0,
+                       const TType *ptype5 = 0);
+
+    void insertBuiltIn(ESymbolLevel level,
+                       const TType *rvalue,
+                       const char *name,
+                       const TType *ptype1,
+                       const TType *ptype2 = 0,
+                       const TType *ptype3 = 0,
+                       const TType *ptype4 = 0,
+                       const TType *ptype5 = 0)
+    {
+        insertUnmangledBuiltInName(name, level);
+        insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+    }
+
+    void insertBuiltIn(ESymbolLevel level,
+                       const char *ext,
+                       const TType *rvalue,
+                       const char *name,
+                       const TType *ptype1,
+                       const TType *ptype2 = 0,
+                       const TType *ptype3 = 0,
+                       const TType *ptype4 = 0,
+                       const TType *ptype5 = 0)
+    {
+        insertUnmangledBuiltInName(name, level);
+        insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+    }
+
+    void insertBuiltInOp(ESymbolLevel level,
+                         TOperator op,
+                         const TType *rvalue,
+                         const TType *ptype1,
+                         const TType *ptype2 = 0,
+                         const TType *ptype3 = 0,
+                         const TType *ptype4 = 0,
+                         const TType *ptype5 = 0);
+
+    void insertBuiltInOp(ESymbolLevel level,
+                         TOperator op,
+                         const char *ext,
+                         const TType *rvalue,
+                         const TType *ptype1,
+                         const TType *ptype2 = 0,
+                         const TType *ptype3 = 0,
+                         const TType *ptype4 = 0,
+                         const TType *ptype5 = 0);
+
+    void insertBuiltInFunctionNoParameters(ESymbolLevel level,
+                                           TOperator op,
+                                           const TType *rvalue,
+                                           const char *name);
+
+    TSymbol *find(const TString &name,
+                  int shaderVersion,
+                  bool *builtIn   = nullptr,
+                  bool *sameScope = nullptr) const;
+
+    TSymbol *findGlobal(const TString &name) const;
+
+    TSymbol *findBuiltIn(const TString &name, int shaderVersion) const;
+
+    TSymbolTableLevel *getOuterLevel()
+    {
+        assert(currentLevel() >= 1);
+        return table[currentLevel() - 1];
+    }
+
+    void dump(TInfoSink &infoSink) const;
+
+    bool setDefaultPrecision(const TPublicType &type, TPrecision prec)
+    {
+        if (!SupportsPrecision(type.getBasicType()))
+            return false;
+        if (type.getBasicType() == EbtUInt)
+            return false;  // ESSL 3.00.4 section 4.5.4
+        if (type.isAggregate())
+            return false;  // Not allowed to set for aggregate types
+        int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
+        // Uses map operator [], overwrites the current value
+        (*precisionStack[indexOfLastElement])[type.getBasicType()] = prec;
+        return true;
+    }
+
+    // Searches down the precisionStack for a precision qualifier
+    // for the specified TBasicType
+    TPrecision getDefaultPrecision(TBasicType type) const;
+
+    // This records invariant varyings declared through
+    // "invariant varying_name;".
+    void addInvariantVarying(const std::string &originalName)
+    {
+        ASSERT(atGlobalLevel());
+        table[currentLevel()]->addInvariantVarying(originalName);
+    }
+    // If this returns false, the varying could still be invariant
+    // if it is set as invariant during the varying variable
+    // declaration - this piece of information is stored in the
+    // variable's type, not here.
+    bool isVaryingInvariant(const std::string &originalName) const
+    {
+        ASSERT(atGlobalLevel());
+        return table[currentLevel()]->isVaryingInvariant(originalName);
+    }
+
+    void setGlobalInvariant(bool invariant)
+    {
+        ASSERT(atGlobalLevel());
+        table[currentLevel()]->setGlobalInvariant(invariant);
+    }
+
+    static int nextUniqueId() { return ++uniqueIdCounter; }
+
+    // Checks whether there is a built-in accessible by a shader with the specified version.
+    bool hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion);
+
+  private:
+    ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
+
+    // Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and
+    // above.
+    void insertUnmangledBuiltInName(const char *name, ESymbolLevel level);
+
+    bool hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level);
+
+    std::vector<TSymbolTableLevel *> table;
+    typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
+    std::vector<PrecisionStackLevel *> precisionStack;
+
+    static int uniqueIdCounter;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_SYMBOLTABLE_H_
diff --git a/src/third_party/angle/src/compiler/translator/TextureFunctionHLSL.cpp b/src/third_party/angle/src/compiler/translator/TextureFunctionHLSL.cpp
new file mode 100644
index 0000000..51d4540
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TextureFunctionHLSL.cpp
@@ -0,0 +1,1294 @@
+//
+// Copyright (c) 2016 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.
+//
+// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL
+// output. Some of the implementations are straightforward and just call the HLSL equivalent of the
+// ESSL texture function, others do more work to emulate ESSL texture sampling or size query
+// behavior.
+//
+
+#include "compiler/translator/TextureFunctionHLSL.h"
+
+#include "compiler/translator/UtilsHLSL.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void OutputIntTexCoordWrap(TInfoSinkBase &out,
+                           const char *wrapMode,
+                           const char *size,
+                           const TString &texCoord,
+                           const TString &texCoordOffset,
+                           const char *texCoordOutName)
+{
+    // GLES 3.0.4 table 3.22 specifies how the wrap modes work. We don't use the formulas verbatim
+    // but rather use equivalent formulas that map better to HLSL.
+    out << "int " << texCoordOutName << ";\n";
+    out << "float " << texCoordOutName << "Offset = " << texCoord << " + float(" << texCoordOffset
+        << ") / " << size << ";\n";
+
+    // CLAMP_TO_EDGE
+    out << "if (" << wrapMode << " == 1)\n";
+    out << "{\n";
+    out << "    " << texCoordOutName << " = clamp(int(floor(" << size << " * " << texCoordOutName
+        << "Offset)), 0, int(" << size << ") - 1);\n";
+    out << "}\n";
+
+    // MIRRORED_REPEAT
+    out << "else if (" << wrapMode << " == 3)\n";
+    out << "{\n";
+    out << "    float coordWrapped = 1.0 - abs(frac(abs(" << texCoordOutName
+        << "Offset) * 0.5) * 2.0 - 1.0);\n";
+    out << "    " << texCoordOutName << " = int(floor(" << size << " * coordWrapped));\n";
+    out << "}\n";
+
+    // REPEAT
+    out << "else\n";
+    out << "{\n";
+    out << "    " << texCoordOutName << " = int(floor(" << size << " * frac(" << texCoordOutName
+        << "Offset)));\n";
+    out << "}\n";
+}
+
+void OutputIntTexCoordWraps(TInfoSinkBase &out,
+                            const TextureFunctionHLSL::TextureFunction &textureFunction,
+                            TString *texCoordX,
+                            TString *texCoordY,
+                            TString *texCoordZ)
+{
+    // Convert from normalized floating-point to integer
+    out << "int wrapS = samplerMetadata[samplerIndex].wrapModes & 0x3;\n";
+    if (textureFunction.offset)
+    {
+        OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "offset.x", "tix");
+    }
+    else
+    {
+        OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "0", "tix");
+    }
+    *texCoordX = "tix";
+    out << "int wrapT = (samplerMetadata[samplerIndex].wrapModes >> 2) & 0x3;\n";
+    if (textureFunction.offset)
+    {
+        OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "offset.y", "tiy");
+    }
+    else
+    {
+        OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "0", "tiy");
+    }
+    *texCoordY = "tiy";
+
+    if (IsSamplerArray(textureFunction.sampler))
+    {
+        *texCoordZ = "int(max(0, min(layers - 1, floor(0.5 + t.z))))";
+    }
+    else if (!IsSamplerCube(textureFunction.sampler) && !IsSampler2D(textureFunction.sampler))
+    {
+        out << "int wrapR = (samplerMetadata[samplerIndex].wrapModes >> 4) & 0x3;\n";
+        if (textureFunction.offset)
+        {
+            OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "offset.z", "tiz");
+        }
+        else
+        {
+            OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "0", "tiz");
+        }
+        *texCoordZ = "tiz";
+    }
+}
+
+void OutputHLSL4SampleFunctionPrefix(TInfoSinkBase &out,
+                                     const TextureFunctionHLSL::TextureFunction &textureFunction,
+                                     const TString &textureReference,
+                                     const TString &samplerReference)
+{
+    out << textureReference;
+    if (IsIntegerSampler(textureFunction.sampler) ||
+        textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
+    {
+        out << ".Load(";
+        return;
+    }
+
+    if (IsShadowSampler(textureFunction.sampler))
+    {
+        switch (textureFunction.method)
+        {
+            case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+            case TextureFunctionHLSL::TextureFunction::BIAS:
+            case TextureFunctionHLSL::TextureFunction::LOD:
+                out << ".SampleCmp(";
+                break;
+            case TextureFunctionHLSL::TextureFunction::LOD0:
+            case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+            case TextureFunctionHLSL::TextureFunction::GRAD:
+                out << ".SampleCmpLevelZero(";
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+    else
+    {
+        switch (textureFunction.method)
+        {
+            case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+                out << ".Sample(";
+                break;
+            case TextureFunctionHLSL::TextureFunction::BIAS:
+                out << ".SampleBias(";
+                break;
+            case TextureFunctionHLSL::TextureFunction::LOD:
+            case TextureFunctionHLSL::TextureFunction::LOD0:
+            case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+                out << ".SampleLevel(";
+                break;
+            case TextureFunctionHLSL::TextureFunction::GRAD:
+                out << ".SampleGrad(";
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+    out << samplerReference << ", ";
+}
+
+const char *GetSamplerCoordinateTypeString(
+    const TextureFunctionHLSL::TextureFunction &textureFunction,
+    int hlslCoords)
+{
+    if (IsIntegerSampler(textureFunction.sampler) ||
+        textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
+    {
+        switch (hlslCoords)
+        {
+            case 2:
+                return "int3";
+            case 3:
+                return "int4";
+            default:
+                UNREACHABLE();
+        }
+    }
+    else
+    {
+        switch (hlslCoords)
+        {
+            case 2:
+                return "float2";
+            case 3:
+                return "float3";
+            case 4:
+                return "float4";
+            default:
+                UNREACHABLE();
+        }
+    }
+    return "";
+}
+
+int GetHLSLCoordCount(const TextureFunctionHLSL::TextureFunction &textureFunction,
+                      ShShaderOutput outputType)
+{
+    if (outputType == SH_HLSL_3_0_OUTPUT)
+    {
+        int hlslCoords = 2;
+        switch (textureFunction.sampler)
+        {
+            case EbtSampler2D:
+            case EbtSamplerExternalOES:
+                hlslCoords = 2;
+                break;
+            case EbtSamplerCube:
+                hlslCoords = 3;
+                break;
+            default:
+                UNREACHABLE();
+        }
+
+        switch (textureFunction.method)
+        {
+            case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+            case TextureFunctionHLSL::TextureFunction::GRAD:
+                return hlslCoords;
+            case TextureFunctionHLSL::TextureFunction::BIAS:
+            case TextureFunctionHLSL::TextureFunction::LOD:
+            case TextureFunctionHLSL::TextureFunction::LOD0:
+            case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+                return 4;
+            default:
+                UNREACHABLE();
+        }
+    }
+    else
+    {
+        switch (textureFunction.sampler)
+        {
+            case EbtSampler2D:
+                return 2;
+            case EbtSampler3D:
+                return 3;
+            case EbtSamplerCube:
+                return 3;
+            case EbtSampler2DArray:
+                return 3;
+            case EbtSamplerExternalOES:
+                return 2;
+            case EbtISampler2D:
+                return 2;
+            case EbtISampler3D:
+                return 3;
+            case EbtISamplerCube:
+                return 3;
+            case EbtISampler2DArray:
+                return 3;
+            case EbtUSampler2D:
+                return 2;
+            case EbtUSampler3D:
+                return 3;
+            case EbtUSamplerCube:
+                return 3;
+            case EbtUSampler2DArray:
+                return 3;
+            case EbtSampler2DShadow:
+                return 2;
+            case EbtSamplerCubeShadow:
+                return 3;
+            case EbtSampler2DArrayShadow:
+                return 3;
+            default:
+                UNREACHABLE();
+        }
+    }
+    return 0;
+}
+
+void OutputTextureFunctionArgumentList(TInfoSinkBase &out,
+                                       const TextureFunctionHLSL::TextureFunction &textureFunction,
+                                       const ShShaderOutput outputType)
+{
+    if (outputType == SH_HLSL_3_0_OUTPUT)
+    {
+        switch (textureFunction.sampler)
+        {
+            case EbtSampler2D:
+            case EbtSamplerExternalOES:
+                out << "sampler2D s";
+                break;
+            case EbtSamplerCube:
+                out << "samplerCUBE s";
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+    else
+    {
+        if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+        {
+            out << TextureString(textureFunction.sampler) << " x, "
+                << SamplerString(textureFunction.sampler) << " s";
+        }
+        else
+        {
+            ASSERT(outputType == SH_HLSL_4_1_OUTPUT);
+            // A bug in the D3D compiler causes some nested sampling operations to fail.
+            // See http://anglebug.com/1923
+            // TODO(jmadill): Reinstate the const keyword when possible.
+            out << /*"const"*/ "uint samplerIndex";
+        }
+    }
+
+    if (textureFunction.method ==
+        TextureFunctionHLSL::TextureFunction::FETCH)  // Integer coordinates
+    {
+        switch (textureFunction.coords)
+        {
+            case 2:
+                out << ", int2 t";
+                break;
+            case 3:
+                out << ", int3 t";
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+    else  // Floating-point coordinates (except textureSize)
+    {
+        switch (textureFunction.coords)
+        {
+            case 0:
+                break;  // textureSize(gSampler2DMS sampler)
+            case 1:
+                out << ", int lod";
+                break;  // textureSize()
+            case 2:
+                out << ", float2 t";
+                break;
+            case 3:
+                out << ", float3 t";
+                break;
+            case 4:
+                out << ", float4 t";
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+
+    if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+    {
+        switch (textureFunction.sampler)
+        {
+            case EbtSampler2D:
+            case EbtISampler2D:
+            case EbtUSampler2D:
+            case EbtSampler2DArray:
+            case EbtISampler2DArray:
+            case EbtUSampler2DArray:
+            case EbtSampler2DShadow:
+            case EbtSampler2DArrayShadow:
+            case EbtSamplerExternalOES:
+                out << ", float2 ddx, float2 ddy";
+                break;
+            case EbtSampler3D:
+            case EbtISampler3D:
+            case EbtUSampler3D:
+            case EbtSamplerCube:
+            case EbtISamplerCube:
+            case EbtUSamplerCube:
+            case EbtSamplerCubeShadow:
+                out << ", float3 ddx, float3 ddy";
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+
+    switch (textureFunction.method)
+    {
+        case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+            break;
+        case TextureFunctionHLSL::TextureFunction::BIAS:
+            break;  // Comes after the offset parameter
+        case TextureFunctionHLSL::TextureFunction::LOD:
+            out << ", float lod";
+            break;
+        case TextureFunctionHLSL::TextureFunction::LOD0:
+            break;
+        case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+            break;  // Comes after the offset parameter
+        case TextureFunctionHLSL::TextureFunction::SIZE:
+            break;
+        case TextureFunctionHLSL::TextureFunction::FETCH:
+            out << ", int mip";
+            break;
+        case TextureFunctionHLSL::TextureFunction::GRAD:
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    if (textureFunction.offset)
+    {
+        switch (textureFunction.sampler)
+        {
+            case EbtSampler3D:
+            case EbtISampler3D:
+            case EbtUSampler3D:
+                out << ", int3 offset";
+                break;
+            case EbtSampler2D:
+            case EbtSampler2DArray:
+            case EbtISampler2D:
+            case EbtISampler2DArray:
+            case EbtUSampler2D:
+            case EbtUSampler2DArray:
+            case EbtSampler2DShadow:
+            case EbtSampler2DArrayShadow:
+            case EbtSamplerExternalOES:
+                out << ", int2 offset";
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+
+    if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS ||
+        textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+    {
+        out << ", float bias";
+    }
+}
+
+void GetTextureReference(TInfoSinkBase &out,
+                         const TextureFunctionHLSL::TextureFunction &textureFunction,
+                         const ShShaderOutput outputType,
+                         TString *textureReference,
+                         TString *samplerReference)
+{
+    if (outputType == SH_HLSL_4_1_OUTPUT)
+    {
+        TString suffix = TextureGroupSuffix(textureFunction.sampler);
+        if (TextureGroup(textureFunction.sampler) == HLSL_TEXTURE_2D)
+        {
+            *textureReference = TString("textures") + suffix + "[samplerIndex]";
+            *samplerReference = TString("samplers") + suffix + "[samplerIndex]";
+        }
+        else
+        {
+            out << "    const uint textureIndex = samplerIndex - textureIndexOffset" << suffix
+                << ";\n";
+            *textureReference = TString("textures") + suffix + "[textureIndex]";
+            out << "    const uint samplerArrayIndex = samplerIndex - samplerIndexOffset" << suffix
+                << ";\n";
+            *samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]";
+        }
+    }
+    else
+    {
+        *textureReference = "x";
+        *samplerReference = "s";
+    }
+}
+
+void OutputTextureSizeFunctionBody(TInfoSinkBase &out,
+                                   const TextureFunctionHLSL::TextureFunction &textureFunction,
+                                   const TString &textureReference,
+                                   bool getDimensionsIgnoresBaseLevel)
+{
+    if (IsSampler2DMS(textureFunction.sampler))
+    {
+        out << "    uint width; uint height; uint samples;\n"
+            << "    " << textureReference << ".GetDimensions(width, height, samples);\n";
+    }
+    else
+    {
+        if (getDimensionsIgnoresBaseLevel)
+        {
+            out << "    int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
+        }
+        else
+        {
+            out << "    int baseLevel = 0;\n";
+        }
+
+        if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) ||
+            (IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler)))
+        {
+            // "depth" stores either the number of layers in an array texture or 3D depth
+            out << "    uint width; uint height; uint depth; uint numberOfLevels;\n"
+                << "    " << textureReference
+                << ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n"
+                << "    width = max(width >> lod, 1);\n"
+                << "    height = max(height >> lod, 1);\n";
+
+            if (!IsSamplerArray(textureFunction.sampler))
+            {
+                out << "    depth = max(depth >> lod, 1);\n";
+            }
+        }
+        else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler))
+        {
+            out << "    uint width; uint height; uint numberOfLevels;\n"
+                << "    " << textureReference
+                << ".GetDimensions(baseLevel, width, height, numberOfLevels);\n"
+                << "    width = max(width >> lod, 1);\n"
+                << "    height = max(height >> lod, 1);\n";
+        }
+        else
+            UNREACHABLE();
+    }
+
+    if (strcmp(textureFunction.getReturnType(), "int3") == 0)
+    {
+        out << "    return int3(width, height, depth);\n";
+    }
+    else
+    {
+        out << "    return int2(width, height);\n";
+    }
+}
+
+void ProjectTextureCoordinates(const TextureFunctionHLSL::TextureFunction &textureFunction,
+                               TString *texCoordX,
+                               TString *texCoordY,
+                               TString *texCoordZ)
+{
+    if (textureFunction.proj)
+    {
+        TString proj("");
+        switch (textureFunction.coords)
+        {
+            case 3:
+                proj = " / t.z";
+                break;
+            case 4:
+                proj = " / t.w";
+                break;
+            default:
+                UNREACHABLE();
+        }
+        *texCoordX = "(" + *texCoordX + proj + ")";
+        *texCoordY = "(" + *texCoordY + proj + ")";
+        *texCoordZ = "(" + *texCoordZ + proj + ")";
+    }
+}
+
+void OutputIntegerTextureSampleFunctionComputations(
+    TInfoSinkBase &out,
+    const TextureFunctionHLSL::TextureFunction &textureFunction,
+    const ShShaderOutput outputType,
+    const TString &textureReference,
+    TString *texCoordX,
+    TString *texCoordY,
+    TString *texCoordZ)
+{
+    if (!IsIntegerSampler(textureFunction.sampler))
+    {
+        return;
+    }
+    if (IsSamplerCube(textureFunction.sampler))
+    {
+        out << "    float width; float height; float layers; float levels;\n";
+
+        out << "    uint mip = 0;\n";
+
+        out << "    " << textureReference
+            << ".GetDimensions(mip, width, height, layers, levels);\n";
+
+        out << "    bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n";
+        out << "    bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n";
+        out << "    bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n";
+        out << "    bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || "
+               "(zMajor && t.z < 0.0f);\n";
+
+        // FACE_POSITIVE_X = 000b
+        // FACE_NEGATIVE_X = 001b
+        // FACE_POSITIVE_Y = 010b
+        // FACE_NEGATIVE_Y = 011b
+        // FACE_POSITIVE_Z = 100b
+        // FACE_NEGATIVE_Z = 101b
+        out << "    int face = (int)negative + (int)yMajor * 2 + (int)zMajor * 4;\n";
+
+        out << "    float u = xMajor ? -t.z : (yMajor && t.y < 0.0f ? -t.x : t.x);\n";
+        out << "    float v = yMajor ? t.z : (negative ? t.y : -t.y);\n";
+        out << "    float m = xMajor ? t.x : (yMajor ? t.y : t.z);\n";
+
+        out << "    t.x = (u * 0.5f / m) + 0.5f;\n";
+        out << "    t.y = (v * 0.5f / m) + 0.5f;\n";
+
+        // Mip level computation.
+        if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+            textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD ||
+            textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+        {
+            if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT)
+            {
+                out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
+                       "    float2 dx = ddx(tSized);\n"
+                       "    float2 dy = ddy(tSized);\n"
+                       "    float lod = 0.5f * log2(max(dot(dx, dx), dot(dy, dy)));\n";
+            }
+            else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+            {
+                // ESSL 3.00.6 spec section 8.8: "For the cube version, the partial
+                // derivatives of P are assumed to be in the coordinate system used before
+                // texture coordinates are projected onto the appropriate cube face."
+                // ddx[0] and ddy[0] are the derivatives of t.x passed into the function
+                // ddx[1] and ddy[1] are the derivatives of t.y passed into the function
+                // ddx[2] and ddy[2] are the derivatives of t.z passed into the function
+                // Determine the derivatives of u, v and m
+                out << "    float dudx = xMajor ? ddx[2] : (yMajor && t.y < 0.0f ? -ddx[0] "
+                       ": ddx[0]);\n"
+                       "    float dudy = xMajor ? ddy[2] : (yMajor && t.y < 0.0f ? -ddy[0] "
+                       ": ddy[0]);\n"
+                       "    float dvdx = yMajor ? ddx[2] : (negative ? ddx[1] : -ddx[1]);\n"
+                       "    float dvdy = yMajor ? ddy[2] : (negative ? ddy[1] : -ddy[1]);\n"
+                       "    float dmdx = xMajor ? ddx[0] : (yMajor ? ddx[1] : ddx[2]);\n"
+                       "    float dmdy = xMajor ? ddy[0] : (yMajor ? ddy[1] : ddy[2]);\n";
+                // Now determine the derivatives of the face coordinates, using the
+                // derivatives calculated above.
+                // d / dx (u(x) * 0.5 / m(x) + 0.5)
+                // = 0.5 * (m(x) * u'(x) - u(x) * m'(x)) / m(x)^2
+                out << "    float dfacexdx = 0.5f * (m * dudx - u * dmdx) / (m * m);\n"
+                       "    float dfaceydx = 0.5f * (m * dvdx - v * dmdx) / (m * m);\n"
+                       "    float dfacexdy = 0.5f * (m * dudy - u * dmdy) / (m * m);\n"
+                       "    float dfaceydy = 0.5f * (m * dvdy - v * dmdy) / (m * m);\n"
+                       "    float2 sizeVec = float2(width, height);\n"
+                       "    float2 faceddx = float2(dfacexdx, dfaceydx) * sizeVec;\n"
+                       "    float2 faceddy = float2(dfacexdy, dfaceydy) * sizeVec;\n";
+                // Optimization: instead of: log2(max(length(faceddx), length(faceddy)))
+                // we compute: log2(max(length(faceddx)^2, length(faceddy)^2)) / 2
+                out << "    float lengthfaceddx2 = dot(faceddx, faceddx);\n"
+                       "    float lengthfaceddy2 = dot(faceddy, faceddy);\n"
+                       "    float lod = log2(max(lengthfaceddx2, lengthfaceddy2)) * 0.5f;\n";
+            }
+            out << "    mip = uint(min(max(round(lod), 0), levels - 1));\n"
+                << "    " << textureReference
+                << ".GetDimensions(mip, width, height, layers, levels);\n";
+        }
+
+        // Convert from normalized floating-point to integer
+        *texCoordX = "int(floor(width * frac(" + *texCoordX + ")))";
+        *texCoordY = "int(floor(height * frac(" + *texCoordY + ")))";
+        *texCoordZ = "face";
+    }
+    else if (textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH)
+    {
+        if (IsSampler2D(textureFunction.sampler))
+        {
+            if (IsSamplerArray(textureFunction.sampler))
+            {
+                out << "    float width; float height; float layers; float levels;\n";
+
+                if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
+                {
+                    out << "    uint mip = 0;\n";
+                }
+                else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+                {
+                    out << "    uint mip = bias;\n";
+                }
+                else
+                {
+
+                    out << "    " << textureReference
+                        << ".GetDimensions(0, width, height, layers, levels);\n";
+                    if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+                        textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                    {
+                        out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
+                               "    float dx = length(ddx(tSized));\n"
+                               "    float dy = length(ddy(tSized));\n"
+                               "    float lod = log2(max(dx, dy));\n";
+
+                        if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                        {
+                            out << "    lod += bias;\n";
+                        }
+                    }
+                    else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+                    {
+                        out << "    float2 sizeVec = float2(width, height);\n"
+                               "    float2 sizeDdx = ddx * sizeVec;\n"
+                               "    float2 sizeDdy = ddy * sizeVec;\n"
+                               "    float lod = log2(max(dot(sizeDdx, sizeDdx), "
+                               "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
+                    }
+
+                    out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+                }
+
+                out << "    " << textureReference
+                    << ".GetDimensions(mip, width, height, layers, levels);\n";
+            }
+            else
+            {
+                out << "    float width; float height; float levels;\n";
+
+                if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
+                {
+                    out << "    uint mip = 0;\n";
+                }
+                else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+                {
+                    out << "    uint mip = bias;\n";
+                }
+                else
+                {
+                    out << "    " << textureReference
+                        << ".GetDimensions(0, width, height, levels);\n";
+
+                    if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+                        textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                    {
+                        out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
+                               "    float dx = length(ddx(tSized));\n"
+                               "    float dy = length(ddy(tSized));\n"
+                               "    float lod = log2(max(dx, dy));\n";
+
+                        if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                        {
+                            out << "    lod += bias;\n";
+                        }
+                    }
+                    else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+                    {
+                        out << "    float2 sizeVec = float2(width, height);\n"
+                               "    float2 sizeDdx = ddx * sizeVec;\n"
+                               "    float2 sizeDdy = ddy * sizeVec;\n"
+                               "    float lod = log2(max(dot(sizeDdx, sizeDdx), "
+                               "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
+                    }
+
+                    out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+                }
+
+                out << "    " << textureReference
+                    << ".GetDimensions(mip, width, height, levels);\n";
+            }
+        }
+        else if (IsSampler3D(textureFunction.sampler))
+        {
+            out << "    float width; float height; float depth; float levels;\n";
+
+            if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
+            {
+                out << "    uint mip = 0;\n";
+            }
+            else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+            {
+                out << "    uint mip = bias;\n";
+            }
+            else
+            {
+                out << "    " << textureReference
+                    << ".GetDimensions(0, width, height, depth, levels);\n";
+
+                if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+                    textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                {
+                    out << "    float3 tSized = float3(t.x * width, t.y * height, t.z * depth);\n"
+                           "    float dx = length(ddx(tSized));\n"
+                           "    float dy = length(ddy(tSized));\n"
+                           "    float lod = log2(max(dx, dy));\n";
+
+                    if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                    {
+                        out << "    lod += bias;\n";
+                    }
+                }
+                else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+                {
+                    out << "    float3 sizeVec = float3(width, height, depth);\n"
+                           "    float3 sizeDdx = ddx * sizeVec;\n"
+                           "    float3 sizeDdy = ddy * sizeVec;\n"
+                           "    float lod = log2(max(dot(sizeDdx, sizeDdx), dot(sizeDdy, "
+                           "sizeDdy))) * 0.5f;\n";
+                }
+
+                out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+            }
+
+            out << "    " << textureReference
+                << ".GetDimensions(mip, width, height, depth, levels);\n";
+        }
+        else
+            UNREACHABLE();
+
+        OutputIntTexCoordWraps(out, textureFunction, texCoordX, texCoordY, texCoordZ);
+    }
+}
+
+void OutputTextureSampleFunctionReturnStatement(
+    TInfoSinkBase &out,
+    const TextureFunctionHLSL::TextureFunction &textureFunction,
+    const ShShaderOutput outputType,
+    const TString &textureReference,
+    const TString &samplerReference,
+    const TString &texCoordX,
+    const TString &texCoordY,
+    const TString &texCoordZ)
+{
+    out << "    return ";
+
+    // HLSL intrinsic
+    if (outputType == SH_HLSL_3_0_OUTPUT)
+    {
+        switch (textureFunction.sampler)
+        {
+            case EbtSampler2D:
+            case EbtSamplerExternalOES:
+                out << "tex2D";
+                break;
+            case EbtSamplerCube:
+                out << "texCUBE";
+                break;
+            default:
+                UNREACHABLE();
+        }
+
+        switch (textureFunction.method)
+        {
+            case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+                out << "(" << samplerReference << ", ";
+                break;
+            case TextureFunctionHLSL::TextureFunction::BIAS:
+                out << "bias(" << samplerReference << ", ";
+                break;
+            case TextureFunctionHLSL::TextureFunction::LOD:
+                out << "lod(" << samplerReference << ", ";
+                break;
+            case TextureFunctionHLSL::TextureFunction::LOD0:
+                out << "lod(" << samplerReference << ", ";
+                break;
+            case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+                out << "lod(" << samplerReference << ", ";
+                break;
+            case TextureFunctionHLSL::TextureFunction::GRAD:
+                out << "grad(" << samplerReference << ", ";
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+    else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+    {
+        OutputHLSL4SampleFunctionPrefix(out, textureFunction, textureReference, samplerReference);
+    }
+    else
+        UNREACHABLE();
+
+    const int hlslCoords = GetHLSLCoordCount(textureFunction, outputType);
+
+    out << GetSamplerCoordinateTypeString(textureFunction, hlslCoords) << "(" << texCoordX << ", "
+        << texCoordY;
+
+    if (outputType == SH_HLSL_3_0_OUTPUT)
+    {
+        if (hlslCoords >= 3)
+        {
+            if (textureFunction.coords < 3)
+            {
+                out << ", 0";
+            }
+            else
+            {
+                out << ", " << texCoordZ;
+            }
+        }
+
+        if (hlslCoords == 4)
+        {
+            switch (textureFunction.method)
+            {
+                case TextureFunctionHLSL::TextureFunction::BIAS:
+                    out << ", bias";
+                    break;
+                case TextureFunctionHLSL::TextureFunction::LOD:
+                    out << ", lod";
+                    break;
+                case TextureFunctionHLSL::TextureFunction::LOD0:
+                    out << ", 0";
+                    break;
+                case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+                    out << ", bias";
+                    break;
+                default:
+                    UNREACHABLE();
+            }
+        }
+
+        out << ")";
+    }
+    else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+    {
+        if (hlslCoords >= 3)
+        {
+            ASSERT(!IsIntegerSampler(textureFunction.sampler) ||
+                   !IsSamplerCube(textureFunction.sampler) || texCoordZ == "face");
+            out << ", " << texCoordZ;
+        }
+
+        if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+        {
+            if (IsIntegerSampler(textureFunction.sampler))
+            {
+                out << ", mip)";
+            }
+            else if (IsShadowSampler(textureFunction.sampler))
+            {
+                // Compare value
+                if (textureFunction.proj)
+                {
+                    // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
+                    // The resulting third component of P' in the shadow forms is used as
+                    // Dref
+                    out << "), " << texCoordZ;
+                }
+                else
+                {
+                    switch (textureFunction.coords)
+                    {
+                        case 3:
+                            out << "), t.z";
+                            break;
+                        case 4:
+                            out << "), t.w";
+                            break;
+                        default:
+                            UNREACHABLE();
+                    }
+                }
+            }
+            else
+            {
+                out << "), ddx, ddy";
+            }
+        }
+        else if (IsIntegerSampler(textureFunction.sampler) ||
+                 textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
+        {
+            out << ", mip)";
+        }
+        else if (IsShadowSampler(textureFunction.sampler))
+        {
+            // Compare value
+            if (textureFunction.proj)
+            {
+                // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
+                // The resulting third component of P' in the shadow forms is used as Dref
+                out << "), " << texCoordZ;
+            }
+            else
+            {
+                switch (textureFunction.coords)
+                {
+                    case 3:
+                        out << "), t.z";
+                        break;
+                    case 4:
+                        out << "), t.w";
+                        break;
+                    default:
+                        UNREACHABLE();
+                }
+            }
+        }
+        else
+        {
+            switch (textureFunction.method)
+            {
+                case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+                    out << ")";
+                    break;
+                case TextureFunctionHLSL::TextureFunction::BIAS:
+                    out << "), bias";
+                    break;
+                case TextureFunctionHLSL::TextureFunction::LOD:
+                    out << "), lod";
+                    break;
+                case TextureFunctionHLSL::TextureFunction::LOD0:
+                    out << "), 0";
+                    break;
+                case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+                    out << "), bias";
+                    break;
+                default:
+                    UNREACHABLE();
+            }
+        }
+
+        if (textureFunction.offset &&
+            (!IsIntegerSampler(textureFunction.sampler) ||
+             textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH))
+        {
+            out << ", offset";
+        }
+    }
+    else
+        UNREACHABLE();
+
+    out << ");\n";  // Close the sample function call and return statement
+}
+
+}  // Anonymous namespace
+
+TString TextureFunctionHLSL::TextureFunction::name() const
+{
+    TString name = "gl_texture";
+
+    // We need to include full the sampler type in the function name to make the signature unique
+    // on D3D11, where samplers are passed to texture functions as indices.
+    name += TextureTypeSuffix(this->sampler);
+
+    if (proj)
+    {
+        name += "Proj";
+    }
+
+    if (offset)
+    {
+        name += "Offset";
+    }
+
+    switch (method)
+    {
+        case IMPLICIT:
+            break;
+        case BIAS:
+            break;  // Extra parameter makes the signature unique
+        case LOD:
+            name += "Lod";
+            break;
+        case LOD0:
+            name += "Lod0";
+            break;
+        case LOD0BIAS:
+            name += "Lod0";
+            break;  // Extra parameter makes the signature unique
+        case SIZE:
+            name += "Size";
+            break;
+        case FETCH:
+            name += "Fetch";
+            break;
+        case GRAD:
+            name += "Grad";
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return name;
+}
+
+const char *TextureFunctionHLSL::TextureFunction::getReturnType() const
+{
+    if (method == TextureFunction::SIZE)
+    {
+        switch (sampler)
+        {
+            case EbtSampler2D:
+            case EbtISampler2D:
+            case EbtUSampler2D:
+            case EbtSampler2DShadow:
+            case EbtSamplerCube:
+            case EbtISamplerCube:
+            case EbtUSamplerCube:
+            case EbtSamplerCubeShadow:
+            case EbtSamplerExternalOES:
+            case EbtSampler2DMS:
+            case EbtISampler2DMS:
+            case EbtUSampler2DMS:
+                return "int2";
+            case EbtSampler3D:
+            case EbtISampler3D:
+            case EbtUSampler3D:
+            case EbtSampler2DArray:
+            case EbtISampler2DArray:
+            case EbtUSampler2DArray:
+            case EbtSampler2DArrayShadow:
+                return "int3";
+            default:
+                UNREACHABLE();
+        }
+    }
+    else  // Sampling function
+    {
+        switch (sampler)
+        {
+            case EbtSampler2D:
+            case EbtSampler3D:
+            case EbtSamplerCube:
+            case EbtSampler2DArray:
+            case EbtSamplerExternalOES:
+                return "float4";
+            case EbtISampler2D:
+            case EbtISampler3D:
+            case EbtISamplerCube:
+            case EbtISampler2DArray:
+                return "int4";
+            case EbtUSampler2D:
+            case EbtUSampler3D:
+            case EbtUSamplerCube:
+            case EbtUSampler2DArray:
+                return "uint4";
+            case EbtSampler2DShadow:
+            case EbtSamplerCubeShadow:
+            case EbtSampler2DArrayShadow:
+                return "float";
+            default:
+                UNREACHABLE();
+        }
+    }
+    return "";
+}
+
+bool TextureFunctionHLSL::TextureFunction::operator<(const TextureFunction &rhs) const
+{
+    return std::tie(sampler, coords, proj, offset, method) <
+           std::tie(rhs.sampler, rhs.coords, rhs.proj, rhs.offset, rhs.method);
+}
+
+TString TextureFunctionHLSL::useTextureFunction(const TString &name,
+                                                TBasicType samplerType,
+                                                int coords,
+                                                size_t argumentCount,
+                                                bool lod0,
+                                                sh::GLenum shaderType)
+{
+    TextureFunction textureFunction;
+    textureFunction.sampler = samplerType;
+    textureFunction.coords  = coords;
+    textureFunction.method  = TextureFunction::IMPLICIT;
+    textureFunction.proj    = false;
+    textureFunction.offset  = false;
+
+    if (name == "texture2D" || name == "textureCube" || name == "texture")
+    {
+        textureFunction.method = TextureFunction::IMPLICIT;
+    }
+    else if (name == "texture2DProj" || name == "textureProj")
+    {
+        textureFunction.method = TextureFunction::IMPLICIT;
+        textureFunction.proj   = true;
+    }
+    else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod" ||
+             name == "texture2DLodEXT" || name == "textureCubeLodEXT")
+    {
+        textureFunction.method = TextureFunction::LOD;
+    }
+    else if (name == "texture2DProjLod" || name == "textureProjLod" ||
+             name == "texture2DProjLodEXT")
+    {
+        textureFunction.method = TextureFunction::LOD;
+        textureFunction.proj   = true;
+    }
+    else if (name == "textureSize")
+    {
+        textureFunction.method = TextureFunction::SIZE;
+    }
+    else if (name == "textureOffset")
+    {
+        textureFunction.method = TextureFunction::IMPLICIT;
+        textureFunction.offset = true;
+    }
+    else if (name == "textureProjOffset")
+    {
+        textureFunction.method = TextureFunction::IMPLICIT;
+        textureFunction.offset = true;
+        textureFunction.proj   = true;
+    }
+    else if (name == "textureLodOffset")
+    {
+        textureFunction.method = TextureFunction::LOD;
+        textureFunction.offset = true;
+    }
+    else if (name == "textureProjLodOffset")
+    {
+        textureFunction.method = TextureFunction::LOD;
+        textureFunction.proj   = true;
+        textureFunction.offset = true;
+    }
+    else if (name == "texelFetch")
+    {
+        textureFunction.method = TextureFunction::FETCH;
+    }
+    else if (name == "texelFetchOffset")
+    {
+        textureFunction.method = TextureFunction::FETCH;
+        textureFunction.offset = true;
+    }
+    else if (name == "textureGrad" || name == "texture2DGradEXT")
+    {
+        textureFunction.method = TextureFunction::GRAD;
+    }
+    else if (name == "textureGradOffset")
+    {
+        textureFunction.method = TextureFunction::GRAD;
+        textureFunction.offset = true;
+    }
+    else if (name == "textureProjGrad" || name == "texture2DProjGradEXT" ||
+             name == "textureCubeGradEXT")
+    {
+        textureFunction.method = TextureFunction::GRAD;
+        textureFunction.proj   = true;
+    }
+    else if (name == "textureProjGradOffset")
+    {
+        textureFunction.method = TextureFunction::GRAD;
+        textureFunction.proj   = true;
+        textureFunction.offset = true;
+    }
+    else
+        UNREACHABLE();
+
+    if (textureFunction.method ==
+        TextureFunction::IMPLICIT)  // Could require lod 0 or have a bias argument
+    {
+        size_t mandatoryArgumentCount = 2;  // All functions have sampler and coordinate arguments
+
+        if (textureFunction.offset)
+        {
+            mandatoryArgumentCount++;
+        }
+
+        bool bias = (argumentCount > mandatoryArgumentCount);  // Bias argument is optional
+
+        if (lod0 || shaderType == GL_VERTEX_SHADER)
+        {
+            if (bias)
+            {
+                textureFunction.method = TextureFunction::LOD0BIAS;
+            }
+            else
+            {
+                textureFunction.method = TextureFunction::LOD0;
+            }
+        }
+        else if (bias)
+        {
+            textureFunction.method = TextureFunction::BIAS;
+        }
+    }
+
+    mUsesTexture.insert(textureFunction);
+    return textureFunction.name();
+}
+
+void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out,
+                                                const ShShaderOutput outputType,
+                                                bool getDimensionsIgnoresBaseLevel)
+{
+    for (const TextureFunction &textureFunction : mUsesTexture)
+    {
+        // Function header
+        out << textureFunction.getReturnType() << " " << textureFunction.name() << "(";
+
+        OutputTextureFunctionArgumentList(out, textureFunction, outputType);
+
+        out << ")\n"
+               "{\n";
+
+        // In some cases we use a variable to store the texture/sampler objects, but to work around
+        // a D3D11 compiler bug related to discard inside a loop that is conditional on texture
+        // sampling we need to call the function directly on references to the texture and sampler
+        // arrays. The bug was found using dEQP-GLES3.functional.shaders.discard*loop_texture*
+        // tests.
+        TString textureReference;
+        TString samplerReference;
+        GetTextureReference(out, textureFunction, outputType, &textureReference, &samplerReference);
+
+        if (textureFunction.method == TextureFunction::SIZE)
+        {
+            OutputTextureSizeFunctionBody(out, textureFunction, textureReference,
+                                          getDimensionsIgnoresBaseLevel);
+        }
+        else
+        {
+            TString texCoordX("t.x");
+            TString texCoordY("t.y");
+            TString texCoordZ("t.z");
+            ProjectTextureCoordinates(textureFunction, &texCoordX, &texCoordY, &texCoordZ);
+            OutputIntegerTextureSampleFunctionComputations(out, textureFunction, outputType,
+                                                           textureReference, &texCoordX, &texCoordY,
+                                                           &texCoordZ);
+            OutputTextureSampleFunctionReturnStatement(out, textureFunction, outputType,
+                                                       textureReference, samplerReference,
+                                                       texCoordX, texCoordY, texCoordZ);
+        }
+
+        out << "}\n"
+               "\n";
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/TextureFunctionHLSL.h b/src/third_party/angle/src/compiler/translator/TextureFunctionHLSL.h
new file mode 100644
index 0000000..68bf8c0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TextureFunctionHLSL.h
@@ -0,0 +1,76 @@
+//
+// Copyright (c) 2016 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.
+//
+// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL
+// output. Some of the implementations are straightforward and just call the HLSL equivalent of the
+// ESSL texture function, others do more work to emulate ESSL texture sampling or size query
+// behavior.
+//
+
+#ifndef COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_
+#define COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_
+
+#include <set>
+
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Common.h"
+#include "compiler/translator/InfoSink.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+
+class TextureFunctionHLSL final : angle::NonCopyable
+{
+  public:
+    struct TextureFunction
+    {
+        // See ESSL 3.00.6 section 8.8 for reference about what the different methods below do.
+        enum Method
+        {
+            IMPLICIT,  // Mipmap LOD determined implicitly (standard lookup)
+            BIAS,
+            LOD,
+            LOD0,
+            LOD0BIAS,
+            SIZE,  // textureSize()
+            FETCH,
+            GRAD
+        };
+
+        TString name() const;
+
+        bool operator<(const TextureFunction &rhs) const;
+
+        const char *getReturnType() const;
+
+        TBasicType sampler;
+        int coords;
+        bool proj;
+        bool offset;
+        Method method;
+    };
+
+    // Returns the name of the texture function implementation to call.
+    // The name that's passed in is the name of the GLSL texture function that it should implement.
+    TString useTextureFunction(const TString &name,
+                               TBasicType samplerType,
+                               int coords,
+                               size_t argumentCount,
+                               bool lod0,
+                               sh::GLenum shaderType);
+
+    void textureFunctionHeader(TInfoSinkBase &out,
+                               const ShShaderOutput outputType,
+                               bool getDimensionsIgnoresBaseLevel);
+
+  private:
+    typedef std::set<TextureFunction> TextureFunctionSet;
+    TextureFunctionSet mUsesTexture;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/TranslatorESSL.cpp b/src/third_party/angle/src/compiler/translator/TranslatorESSL.cpp
new file mode 100644
index 0000000..ddb8c4c
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TranslatorESSL.cpp
@@ -0,0 +1,154 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/TranslatorESSL.h"
+
+#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
+#include "compiler/translator/EmulatePrecision.h"
+#include "compiler/translator/PrunePureLiteralStatements.h"
+#include "compiler/translator/RecordConstantPrecision.h"
+#include "compiler/translator/OutputESSL.h"
+#include "angle_gl.h"
+
+namespace sh
+{
+
+TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
+    : TCompiler(type, spec, SH_ESSL_OUTPUT)
+{
+}
+
+void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+                                                 ShCompileOptions compileOptions)
+{
+    if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
+    {
+        InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
+    }
+}
+
+void TranslatorESSL::translate(TIntermBlock *root, ShCompileOptions compileOptions)
+{
+    // The ESSL output doesn't define a default precision for float, so float literal statements
+    // end up with no precision which is invalid ESSL.
+    PrunePureLiteralStatements(root);
+
+    TInfoSinkBase &sink = getInfoSink().obj;
+
+    int shaderVer = getShaderVersion();
+    if (shaderVer > 100)
+    {
+        sink << "#version " << shaderVer << " es\n";
+    }
+
+    // Write built-in extension behaviors.
+    writeExtensionBehavior(compileOptions);
+
+    // Write pragmas after extensions because some drivers consider pragmas
+    // like non-preprocessor tokens.
+    writePragma(compileOptions);
+
+    bool precisionEmulation =
+        getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
+
+    if (precisionEmulation)
+    {
+        EmulatePrecision emulatePrecision(getSymbolTable(), shaderVer);
+        root->traverse(&emulatePrecision);
+        emulatePrecision.updateTree();
+        emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT);
+    }
+
+    RecordConstantPrecision(root, getTemporaryIndex());
+
+    // Write emulated built-in functions if needed.
+    if (!getBuiltInFunctionEmulator().isOutputEmpty())
+    {
+        sink << "// BEGIN: Generated code for built-in function emulation\n\n";
+        if (getShaderType() == GL_FRAGMENT_SHADER)
+        {
+            sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
+                 << "#define webgl_emu_precision highp\n"
+                 << "#else\n"
+                 << "#define webgl_emu_precision mediump\n"
+                 << "#endif\n\n";
+        }
+        else
+        {
+            sink << "#define webgl_emu_precision highp\n";
+        }
+
+        getBuiltInFunctionEmulator().outputEmulatedFunctions(sink);
+        sink << "// END: Generated code for built-in function emulation\n\n";
+    }
+
+    // Write array bounds clamping emulation if needed.
+    getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
+    if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
+    {
+        const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
+        sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
+             << ", local_size_z=" << localSize[2] << ") in;\n";
+    }
+
+    // Write translated shader.
+    TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
+                           getSymbolTable(), getShaderType(), shaderVer, precisionEmulation,
+                           compileOptions);
+
+    if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM)
+    {
+        TName uniformName(TString("ViewID_OVR"));
+        uniformName.setInternal(true);
+        sink << "highp uniform int " << outputESSL.hashName(uniformName) << ";\n";
+    }
+
+    root->traverse(&outputESSL);
+}
+
+bool TranslatorESSL::shouldFlattenPragmaStdglInvariantAll()
+{
+    // Not necessary when translating to ESSL.
+    return false;
+}
+
+void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions)
+{
+    TInfoSinkBase &sink                   = getInfoSink().obj;
+    const TExtensionBehavior &extBehavior = getExtensionBehavior();
+    for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end();
+         ++iter)
+    {
+        if (iter->second != EBhUndefined)
+        {
+            if (getResources().NV_shader_framebuffer_fetch &&
+                iter->first == "GL_EXT_shader_framebuffer_fetch")
+            {
+                sink << "#extension GL_NV_shader_framebuffer_fetch : "
+                     << getBehaviorString(iter->second) << "\n";
+            }
+            else if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers")
+            {
+                sink << "#extension GL_NV_draw_buffers : " << getBehaviorString(iter->second)
+                     << "\n";
+            }
+            else if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM &&
+                     (iter->first == "GL_OVR_multiview" || iter->first == "GL_OVR_multiview2"))
+            {
+                // No output
+                continue;
+            }
+            else
+            {
+                sink << "#extension " << iter->first << " : " << getBehaviorString(iter->second)
+                     << "\n";
+            }
+        }
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/TranslatorESSL.h b/src/third_party/angle/src/compiler/translator/TranslatorESSL.h
new file mode 100644
index 0000000..7e5a897
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TranslatorESSL.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_TRANSLATORESSL_H_
+#define COMPILER_TRANSLATOR_TRANSLATORESSL_H_
+
+#include "compiler/translator/Compiler.h"
+
+namespace sh
+{
+
+class TranslatorESSL : public TCompiler
+{
+  public:
+    TranslatorESSL(sh::GLenum type, ShShaderSpec spec);
+
+  protected:
+    void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+                                     ShCompileOptions compileOptions) override;
+
+    void translate(TIntermBlock *root, ShCompileOptions compileOptions) override;
+    bool shouldFlattenPragmaStdglInvariantAll() override;
+
+  private:
+    void writeExtensionBehavior(ShCompileOptions compileOptions);
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_TRANSLATORESSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/third_party/angle/src/compiler/translator/TranslatorGLSL.cpp
new file mode 100644
index 0000000..41abbfc
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TranslatorGLSL.cpp
@@ -0,0 +1,314 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/TranslatorGLSL.h"
+
+#include "angle_gl.h"
+#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
+#include "compiler/translator/EmulatePrecision.h"
+#include "compiler/translator/ExtensionGLSL.h"
+#include "compiler/translator/OutputGLSL.h"
+#include "compiler/translator/RewriteTexelFetchOffset.h"
+#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h"
+#include "compiler/translator/VersionGLSL.h"
+
+namespace sh
+{
+
+TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
+    : TCompiler(type, spec, output)
+{
+}
+
+void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+                                                 ShCompileOptions compileOptions)
+{
+    if (compileOptions & SH_EMULATE_ABS_INT_FUNCTION)
+    {
+        InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
+    }
+
+    if (compileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION)
+    {
+        InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion());
+    }
+
+    if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
+    {
+        InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
+    }
+
+    int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType());
+    InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion);
+}
+
+void TranslatorGLSL::translate(TIntermBlock *root, ShCompileOptions compileOptions)
+{
+    TInfoSinkBase &sink = getInfoSink().obj;
+
+    // Write GLSL version.
+    writeVersion(root);
+
+    // Write extension behaviour as needed
+    writeExtensionBehavior(root);
+
+    // Write pragmas after extensions because some drivers consider pragmas
+    // like non-preprocessor tokens.
+    writePragma(compileOptions);
+
+    // If flattening the global invariant pragma, write invariant declarations for built-in
+    // variables. It should be harmless to do this twice in the case that the shader also explicitly
+    // did this. However, it's important to emit invariant qualifiers only for those built-in
+    // variables that are actually used, to avoid affecting the behavior of the shader.
+    if ((compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) != 0 &&
+        getPragma().stdgl.invariantAll &&
+        !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions))
+    {
+        ASSERT(wereVariablesCollected());
+
+        switch (getShaderType())
+        {
+            case GL_VERTEX_SHADER:
+                sink << "invariant gl_Position;\n";
+
+                // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment
+                // shaders if it's statically referenced.
+                conditionallyOutputInvariantDeclaration("gl_PointSize");
+                break;
+            case GL_FRAGMENT_SHADER:
+                // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment
+                // shaders, so we can use simple logic to determine whether to declare these
+                // variables invariant.
+                conditionallyOutputInvariantDeclaration("gl_FragCoord");
+                conditionallyOutputInvariantDeclaration("gl_PointCoord");
+                break;
+            default:
+                // Currently not reached, but leave this in for future expansion.
+                ASSERT(false);
+                break;
+        }
+    }
+
+    if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
+    {
+        sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion());
+    }
+
+    if ((compileOptions & SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR) != 0)
+    {
+        sh::RewriteUnaryMinusOperatorFloat(root);
+    }
+
+    bool precisionEmulation =
+        getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
+
+    if (precisionEmulation)
+    {
+        EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion());
+        root->traverse(&emulatePrecision);
+        emulatePrecision.updateTree();
+        emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType());
+    }
+
+    // Write emulated built-in functions if needed.
+    if (!getBuiltInFunctionEmulator().isOutputEmpty())
+    {
+        sink << "// BEGIN: Generated code for built-in function emulation\n\n";
+        sink << "#define webgl_emu_precision\n\n";
+        getBuiltInFunctionEmulator().outputEmulatedFunctions(sink);
+        sink << "// END: Generated code for built-in function emulation\n\n";
+    }
+
+    // Write array bounds clamping emulation if needed.
+    getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
+    // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
+    // if it's core profile shaders and they are used.
+    if (getShaderType() == GL_FRAGMENT_SHADER)
+    {
+        const bool mayHaveESSL1SecondaryOutputs =
+            IsExtensionEnabled(getExtensionBehavior(), "GL_EXT_blend_func_extended") &&
+            getShaderVersion() == 100;
+        const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType());
+
+        bool hasGLFragColor          = false;
+        bool hasGLFragData           = false;
+        bool hasGLSecondaryFragColor = false;
+        bool hasGLSecondaryFragData  = false;
+
+        for (const auto &outputVar : outputVariables)
+        {
+            if (declareGLFragmentOutputs)
+            {
+                if (outputVar.name == "gl_FragColor")
+                {
+                    ASSERT(!hasGLFragColor);
+                    hasGLFragColor = true;
+                    continue;
+                }
+                else if (outputVar.name == "gl_FragData")
+                {
+                    ASSERT(!hasGLFragData);
+                    hasGLFragData = true;
+                    continue;
+                }
+            }
+            if (mayHaveESSL1SecondaryOutputs)
+            {
+                if (outputVar.name == "gl_SecondaryFragColorEXT")
+                {
+                    ASSERT(!hasGLSecondaryFragColor);
+                    hasGLSecondaryFragColor = true;
+                    continue;
+                }
+                else if (outputVar.name == "gl_SecondaryFragDataEXT")
+                {
+                    ASSERT(!hasGLSecondaryFragData);
+                    hasGLSecondaryFragData = true;
+                    continue;
+                }
+            }
+        }
+        ASSERT(!((hasGLFragColor || hasGLSecondaryFragColor) &&
+                 (hasGLFragData || hasGLSecondaryFragData)));
+        if (hasGLFragColor)
+        {
+            sink << "out vec4 webgl_FragColor;\n";
+        }
+        if (hasGLFragData)
+        {
+            sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n";
+        }
+        if (hasGLSecondaryFragColor)
+        {
+            sink << "out vec4 angle_SecondaryFragColor;\n";
+        }
+        if (hasGLSecondaryFragData)
+        {
+            sink << "out vec4 angle_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers
+                 << "];\n";
+        }
+    }
+
+    if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
+    {
+        const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
+        sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
+             << ", local_size_z=" << localSize[2] << ") in;\n";
+    }
+
+    // Write translated shader.
+    TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
+                           getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(),
+                           compileOptions);
+
+    if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM)
+    {
+        TName uniformName(TString("ViewID_OVR"));
+        uniformName.setInternal(true);
+        sink << "uniform int " << outputGLSL.hashName(uniformName) << ";\n";
+    }
+
+    root->traverse(&outputGLSL);
+}
+
+bool TranslatorGLSL::shouldFlattenPragmaStdglInvariantAll()
+{
+    // Required when outputting to any GLSL version greater than 1.20, but since ANGLE doesn't
+    // translate to that version, return true for the next higher version.
+    return IsGLSL130OrNewer(getOutputType());
+}
+
+bool TranslatorGLSL::shouldCollectVariables(ShCompileOptions compileOptions)
+{
+    return (compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) ||
+           TCompiler::shouldCollectVariables(compileOptions);
+}
+
+void TranslatorGLSL::writeVersion(TIntermNode *root)
+{
+    TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType());
+    root->traverse(&versionGLSL);
+    int version = versionGLSL.getVersion();
+    // We need to write version directive only if it is greater than 110.
+    // If there is no version directive in the shader, 110 is implied.
+    if (version > 110)
+    {
+        TInfoSinkBase &sink = getInfoSink().obj;
+        sink << "#version " << version << "\n";
+    }
+}
+
+void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root)
+{
+    TInfoSinkBase &sink                   = getInfoSink().obj;
+    const TExtensionBehavior &extBehavior = getExtensionBehavior();
+    for (const auto &iter : extBehavior)
+    {
+        if (iter.second == EBhUndefined)
+        {
+            continue;
+        }
+
+        if (getOutputType() == SH_GLSL_COMPATIBILITY_OUTPUT)
+        {
+            // For GLSL output, we don't need to emit most extensions explicitly,
+            // but some we need to translate in GL compatibility profile.
+            if (iter.first == "GL_EXT_shader_texture_lod")
+            {
+                sink << "#extension GL_ARB_shader_texture_lod : " << getBehaviorString(iter.second)
+                     << "\n";
+            }
+
+            if (iter.first == "GL_EXT_draw_buffers")
+            {
+                sink << "#extension GL_ARB_draw_buffers : " << getBehaviorString(iter.second)
+                     << "\n";
+            }
+        }
+    }
+
+    // GLSL ES 3 explicit location qualifiers need to use an extension before GLSL 330
+    if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT &&
+        getShaderType() != GL_COMPUTE_SHADER)
+    {
+        sink << "#extension GL_ARB_explicit_attrib_location : require\n";
+    }
+
+    // Need to enable gpu_shader5 to have index constant sampler array indexing
+    if (getOutputType() != SH_ESSL_OUTPUT && getOutputType() < SH_GLSL_400_CORE_OUTPUT &&
+        getShaderVersion() == 100)
+    {
+        // Don't use "require" on to avoid breaking WebGL 1 on drivers that silently
+        // support index constant sampler array indexing, but don't have the extension or
+        // on drivers that don't have the extension at all as it would break WebGL 1 for
+        // some users.
+        sink << "#extension GL_ARB_gpu_shader5 : enable\n";
+    }
+
+    TExtensionGLSL extensionGLSL(getOutputType());
+    root->traverse(&extensionGLSL);
+
+    for (const auto &ext : extensionGLSL.getEnabledExtensions())
+    {
+        sink << "#extension " << ext << " : enable\n";
+    }
+    for (const auto &ext : extensionGLSL.getRequiredExtensions())
+    {
+        sink << "#extension " << ext << " : require\n";
+    }
+}
+
+void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtinVaryingName)
+{
+    if (isVaryingDefined(builtinVaryingName))
+    {
+        TInfoSinkBase &sink = getInfoSink().obj;
+        sink << "invariant " << builtinVaryingName << ";\n";
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/TranslatorGLSL.h b/src/third_party/angle/src/compiler/translator/TranslatorGLSL.h
new file mode 100644
index 0000000..9e47db9
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TranslatorGLSL.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_TRANSLATORGLSL_H_
+#define COMPILER_TRANSLATOR_TRANSLATORGLSL_H_
+
+#include "compiler/translator/Compiler.h"
+
+namespace sh
+{
+
+class TranslatorGLSL : public TCompiler
+{
+  public:
+    TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
+
+  protected:
+    void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+                                     ShCompileOptions compileOptions) override;
+
+    void translate(TIntermBlock *root, ShCompileOptions compileOptions) override;
+    bool shouldFlattenPragmaStdglInvariantAll() override;
+    bool shouldCollectVariables(ShCompileOptions compileOptions) override;
+
+  private:
+    void writeVersion(TIntermNode *root);
+    void writeExtensionBehavior(TIntermNode *root);
+    void conditionallyOutputInvariantDeclaration(const char *builtinVaryingName);
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/third_party/angle/src/compiler/translator/TranslatorHLSL.cpp
new file mode 100644
index 0000000..67cd53f
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TranslatorHLSL.cpp
@@ -0,0 +1,152 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/TranslatorHLSL.h"
+
+#include "compiler/translator/AddDefaultReturnStatements.h"
+#include "compiler/translator/ArrayReturnValueToOutParameter.h"
+#include "compiler/translator/BreakVariableAliasingInInnerLoops.h"
+#include "compiler/translator/EmulatePrecision.h"
+#include "compiler/translator/ExpandIntegerPowExpressions.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+#include "compiler/translator/OutputHLSL.h"
+#include "compiler/translator/RemoveDynamicIndexing.h"
+#include "compiler/translator/RewriteElseBlocks.h"
+#include "compiler/translator/RewriteTexelFetchOffset.h"
+#include "compiler/translator/RewriteUnaryMinusOperatorInt.h"
+#include "compiler/translator/SeparateArrayInitialization.h"
+#include "compiler/translator/SeparateDeclarations.h"
+#include "compiler/translator/SeparateExpressionsReturningArrays.h"
+#include "compiler/translator/SimplifyLoopConditions.h"
+#include "compiler/translator/SplitSequenceOperator.h"
+#include "compiler/translator/UnfoldShortCircuitToIf.h"
+
+namespace sh
+{
+
+TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
+    : TCompiler(type, spec, output)
+{
+}
+
+void TranslatorHLSL::translate(TIntermBlock *root, ShCompileOptions compileOptions)
+{
+    const ShBuiltInResources &resources = getResources();
+    int numRenderTargets                = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
+
+    sh::AddDefaultReturnStatements(root);
+
+    // Note that SimplifyLoopConditions needs to be run before any other AST transformations that
+    // may need to generate new statements from loop conditions or loop expressions.
+    SimplifyLoopConditions(root,
+                           IntermNodePatternMatcher::kExpressionReturningArray |
+                               IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
+                               IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue |
+                               IntermNodePatternMatcher::kMultiDeclaration,
+                           getTemporaryIndex(), getSymbolTable(), getShaderVersion());
+
+    // Note that separate declarations need to be run before other AST transformations that
+    // generate new statements from expressions.
+    SeparateDeclarations(root);
+
+    SplitSequenceOperator(root,
+                          IntermNodePatternMatcher::kExpressionReturningArray |
+                              IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
+                              IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
+                          getTemporaryIndex(), getSymbolTable(), getShaderVersion());
+
+    // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
+    UnfoldShortCircuitToIf(root, getTemporaryIndex());
+
+    SeparateExpressionsReturningArrays(root, getTemporaryIndex());
+
+    // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization.
+    SeparateArrayInitialization(root);
+
+    // HLSL doesn't support arrays as return values, we'll need to make functions that have an array
+    // as a return value to use an out parameter to transfer the array data instead.
+    ArrayReturnValueToOutParameter(root, getTemporaryIndex());
+
+    if (!shouldRunLoopAndIndexingValidation(compileOptions))
+    {
+        // HLSL doesn't support dynamic indexing of vectors and matrices.
+        RemoveDynamicIndexing(root, getTemporaryIndex(), getSymbolTable(), getShaderVersion());
+    }
+
+    // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
+    // use a vertex attribute as a condition, and some related computation in the else block.
+    if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
+    {
+        sh::RewriteElseBlocks(root, getTemporaryIndex());
+    }
+
+    // Work around an HLSL compiler frontend aliasing optimization bug.
+    // TODO(cwallez) The date is 2016-08-25, Microsoft said the bug would be fixed
+    // in the next release of d3dcompiler.dll, it would be nice to detect the DLL
+    // version and only apply the workaround if it is too old.
+    sh::BreakVariableAliasingInInnerLoops(root);
+
+    bool precisionEmulation =
+        getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
+
+    if (precisionEmulation)
+    {
+        EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion());
+        root->traverse(&emulatePrecision);
+        emulatePrecision.updateTree();
+        emulatePrecision.writeEmulationHelpers(getInfoSink().obj, getShaderVersion(),
+                                               getOutputType());
+    }
+
+    if ((compileOptions & SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS) != 0)
+    {
+        sh::ExpandIntegerPowExpressions(root, getTemporaryIndex());
+    }
+
+    if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
+    {
+        sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion());
+    }
+
+    if (((compileOptions & SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR) != 0) &&
+        getShaderType() == GL_VERTEX_SHADER)
+    {
+        sh::RewriteUnaryMinusOperatorInt(root);
+    }
+
+    sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
+                              getSourcePath(), getOutputType(), numRenderTargets, getUniforms(),
+                              compileOptions);
+
+    outputHLSL.output(root, getInfoSink().obj);
+
+    mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap();
+    mUniformRegisterMap        = outputHLSL.getUniformRegisterMap();
+}
+
+bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll()
+{
+    // Not necessary when translating to HLSL.
+    return false;
+}
+
+bool TranslatorHLSL::hasInterfaceBlock(const std::string &interfaceBlockName) const
+{
+    return (mInterfaceBlockRegisterMap.count(interfaceBlockName) > 0);
+}
+
+unsigned int TranslatorHLSL::getInterfaceBlockRegister(const std::string &interfaceBlockName) const
+{
+    ASSERT(hasInterfaceBlock(interfaceBlockName));
+    return mInterfaceBlockRegisterMap.find(interfaceBlockName)->second;
+}
+
+const std::map<std::string, unsigned int> *TranslatorHLSL::getUniformRegisterMap() const
+{
+    return &mUniformRegisterMap;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/TranslatorHLSL.h b/src/third_party/angle/src/compiler/translator/TranslatorHLSL.h
new file mode 100644
index 0000000..495ff42
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TranslatorHLSL.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_TRANSLATORHLSL_H_
+#define COMPILER_TRANSLATOR_TRANSLATORHLSL_H_
+
+#include "compiler/translator/Compiler.h"
+
+namespace sh
+{
+
+class TranslatorHLSL : public TCompiler
+{
+  public:
+    TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
+    TranslatorHLSL *getAsTranslatorHLSL() override { return this; }
+
+    bool hasInterfaceBlock(const std::string &interfaceBlockName) const;
+    unsigned int getInterfaceBlockRegister(const std::string &interfaceBlockName) const;
+
+    const std::map<std::string, unsigned int> *getUniformRegisterMap() const;
+
+  protected:
+    void translate(TIntermBlock *root, ShCompileOptions compileOptions) override;
+    bool shouldFlattenPragmaStdglInvariantAll() override;
+
+    // collectVariables needs to be run always so registers can be assigned.
+    bool shouldCollectVariables(ShCompileOptions compileOptions) override { return true; }
+
+    std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
+    std::map<std::string, unsigned int> mUniformRegisterMap;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/TranslatorVulkan.cpp b/src/third_party/angle/src/compiler/translator/TranslatorVulkan.cpp
new file mode 100644
index 0000000..e3699f0
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TranslatorVulkan.cpp
@@ -0,0 +1,77 @@
+//
+// Copyright (c) 2016 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.
+//
+// TranslatorVulkan:
+//   A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl.
+//   The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
+//   See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
+//
+
+#include "compiler/translator/TranslatorVulkan.h"
+
+#include "angle_gl.h"
+#include "compiler/translator/OutputVulkanGLSL.h"
+
+namespace sh
+{
+
+TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec)
+    : TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT)
+{
+}
+
+void TranslatorVulkan::translate(TIntermBlock *root, ShCompileOptions compileOptions)
+{
+    TInfoSinkBase &sink = getInfoSink().obj;
+
+    sink << "#version 450 core\n";
+
+    // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
+    // if it's core profile shaders and they are used.
+    if (getShaderType() == GL_FRAGMENT_SHADER)
+    {
+        bool hasGLFragColor = false;
+        bool hasGLFragData  = false;
+
+        for (const auto &outputVar : outputVariables)
+        {
+            if (outputVar.name == "gl_FragColor")
+            {
+                ASSERT(!hasGLFragColor);
+                hasGLFragColor = true;
+                continue;
+            }
+            else if (outputVar.name == "gl_FragData")
+            {
+                ASSERT(!hasGLFragData);
+                hasGLFragData = true;
+                continue;
+            }
+        }
+        ASSERT(!(hasGLFragColor && hasGLFragData));
+        if (hasGLFragColor)
+        {
+            sink << "layout(location = 0) out vec4 webgl_FragColor;\n";
+        }
+        if (hasGLFragData)
+        {
+            sink << "layout(location = 0) out vec4 webgl_FragData[gl_MaxDrawBuffers];\n";
+        }
+    }
+
+    // Write translated shader.
+    TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(),
+                                 getNameMap(), getSymbolTable(), getShaderType(),
+                                 getShaderVersion(), getOutputType(), compileOptions);
+    root->traverse(&outputGLSL);
+}
+
+bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll()
+{
+    // Not necessary.
+    return false;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/TranslatorVulkan.h b/src/third_party/angle/src/compiler/translator/TranslatorVulkan.h
new file mode 100644
index 0000000..f7a7cd9
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/TranslatorVulkan.h
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2016 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.
+//
+// TranslatorVulkan:
+//   A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl.
+//   The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
+//   See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
+//
+
+#ifndef COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_
+#define COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_
+
+#include "compiler/translator/Compiler.h"
+
+namespace sh
+{
+
+class TranslatorVulkan : public TCompiler
+{
+  public:
+    TranslatorVulkan(sh::GLenum type, ShShaderSpec spec);
+
+  protected:
+    void translate(TIntermBlock *root, ShCompileOptions compileOptions) override;
+    bool shouldFlattenPragmaStdglInvariantAll() override;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_
diff --git a/src/third_party/angle/src/compiler/translator/Types.cpp b/src/third_party/angle/src/compiler/translator/Types.cpp
new file mode 100644
index 0000000..2015b56
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Types.cpp
@@ -0,0 +1,669 @@
+//
+// 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.
+//
+
+#if defined(_MSC_VER)
+#pragma warning(disable : 4718)
+#endif
+
+#include "compiler/translator/Types.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolTable.h"
+
+#include <algorithm>
+#include <climits>
+
+namespace sh
+{
+
+const char *getBasicString(TBasicType t)
+{
+    switch (t)
+    {
+        case EbtVoid:
+            return "void";
+        case EbtFloat:
+            return "float";
+        case EbtInt:
+            return "int";
+        case EbtUInt:
+            return "uint";
+        case EbtBool:
+            return "bool";
+        case EbtYuvCscStandardEXT:
+            return "yuvCscStandardEXT";
+        case EbtSampler2D:
+            return "sampler2D";
+        case EbtSampler3D:
+            return "sampler3D";
+        case EbtSamplerCube:
+            return "samplerCube";
+        case EbtSamplerExternalOES:
+            return "samplerExternalOES";
+        case EbtSamplerExternal2DY2YEXT:
+            return "__samplerExternal2DY2YEXT";
+        case EbtSampler2DRect:
+            return "sampler2DRect";
+        case EbtSampler2DArray:
+            return "sampler2DArray";
+        case EbtSampler2DMS:
+            return "sampler2DMS";
+        case EbtISampler2D:
+            return "isampler2D";
+        case EbtISampler3D:
+            return "isampler3D";
+        case EbtISamplerCube:
+            return "isamplerCube";
+        case EbtISampler2DArray:
+            return "isampler2DArray";
+        case EbtISampler2DMS:
+            return "isampler2DMS";
+        case EbtUSampler2D:
+            return "usampler2D";
+        case EbtUSampler3D:
+            return "usampler3D";
+        case EbtUSamplerCube:
+            return "usamplerCube";
+        case EbtUSampler2DArray:
+            return "usampler2DArray";
+        case EbtUSampler2DMS:
+            return "usampler2DMS";
+        case EbtSampler2DShadow:
+            return "sampler2DShadow";
+        case EbtSamplerCubeShadow:
+            return "samplerCubeShadow";
+        case EbtSampler2DArrayShadow:
+            return "sampler2DArrayShadow";
+        case EbtStruct:
+            return "structure";
+        case EbtInterfaceBlock:
+            return "interface block";
+        case EbtImage2D:
+            return "image2D";
+        case EbtIImage2D:
+            return "iimage2D";
+        case EbtUImage2D:
+            return "uimage2D";
+        case EbtImage3D:
+            return "image3D";
+        case EbtIImage3D:
+            return "iimage3D";
+        case EbtUImage3D:
+            return "uimage3D";
+        case EbtImage2DArray:
+            return "image2DArray";
+        case EbtIImage2DArray:
+            return "iimage2DArray";
+        case EbtUImage2DArray:
+            return "uimage2DArray";
+        case EbtImageCube:
+            return "imageCube";
+        case EbtIImageCube:
+            return "iimageCube";
+        case EbtUImageCube:
+            return "uimageCube";
+        default:
+            UNREACHABLE();
+            return "unknown type";
+    }
+}
+
+TType::TType(const TPublicType &p)
+    : type(p.getBasicType()),
+      precision(p.precision),
+      qualifier(p.qualifier),
+      invariant(p.invariant),
+      memoryQualifier(p.memoryQualifier),
+      layoutQualifier(p.layoutQualifier),
+      primarySize(p.getPrimarySize()),
+      secondarySize(p.getSecondarySize()),
+      array(p.array),
+      arraySize(p.arraySize),
+      interfaceBlock(0),
+      structure(0)
+{
+    ASSERT(primarySize <= 4);
+    ASSERT(secondarySize <= 4);
+    if (p.getUserDef())
+        structure = p.getUserDef()->getStruct();
+}
+
+bool TStructure::equals(const TStructure &other) const
+{
+    return (uniqueId() == other.uniqueId());
+}
+
+bool TType::canBeConstructed() const
+{
+    switch (type)
+    {
+        case EbtFloat:
+        case EbtInt:
+        case EbtUInt:
+        case EbtBool:
+        case EbtStruct:
+            return true;
+        default:
+            return false;
+    }
+}
+
+const char *TType::getBuiltInTypeNameString() const
+{
+    if (isMatrix())
+    {
+        switch (getCols())
+        {
+            case 2:
+                switch (getRows())
+                {
+                    case 2:
+                        return "mat2";
+                    case 3:
+                        return "mat2x3";
+                    case 4:
+                        return "mat2x4";
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+            case 3:
+                switch (getRows())
+                {
+                    case 2:
+                        return "mat3x2";
+                    case 3:
+                        return "mat3";
+                    case 4:
+                        return "mat3x4";
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+            case 4:
+                switch (getRows())
+                {
+                    case 2:
+                        return "mat4x2";
+                    case 3:
+                        return "mat4x3";
+                    case 4:
+                        return "mat4";
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+            default:
+                UNREACHABLE();
+                return nullptr;
+        }
+    }
+    if (isVector())
+    {
+        switch (getBasicType())
+        {
+            case EbtFloat:
+                switch (getNominalSize())
+                {
+                    case 2:
+                        return "vec2";
+                    case 3:
+                        return "vec3";
+                    case 4:
+                        return "vec4";
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+            case EbtInt:
+                switch (getNominalSize())
+                {
+                    case 2:
+                        return "ivec2";
+                    case 3:
+                        return "ivec3";
+                    case 4:
+                        return "ivec4";
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+            case EbtBool:
+                switch (getNominalSize())
+                {
+                    case 2:
+                        return "bvec2";
+                    case 3:
+                        return "bvec3";
+                    case 4:
+                        return "bvec4";
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+            case EbtUInt:
+                switch (getNominalSize())
+                {
+                    case 2:
+                        return "uvec2";
+                    case 3:
+                        return "uvec3";
+                    case 4:
+                        return "uvec4";
+                    default:
+                        UNREACHABLE();
+                        return nullptr;
+                }
+            default:
+                UNREACHABLE();
+                return nullptr;
+        }
+    }
+    ASSERT(getBasicType() != EbtStruct);
+    ASSERT(getBasicType() != EbtInterfaceBlock);
+    return getBasicString();
+}
+
+TString TType::getCompleteString() const
+{
+    TStringStream stream;
+
+    if (invariant)
+        stream << "invariant ";
+    if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+        stream << getQualifierString() << " ";
+    if (precision != EbpUndefined)
+        stream << getPrecisionString() << " ";
+    if (array)
+        stream << "array[" << getArraySize() << "] of ";
+    if (isMatrix())
+        stream << getCols() << "X" << getRows() << " matrix of ";
+    else if (isVector())
+        stream << getNominalSize() << "-component vector of ";
+
+    stream << getBasicString();
+    return stream.str();
+}
+
+//
+// Recursively generate mangled names.
+//
+TString TType::buildMangledName() const
+{
+    TString mangledName;
+    if (isMatrix())
+        mangledName += 'm';
+    else if (isVector())
+        mangledName += 'v';
+
+    switch (type)
+    {
+        case EbtFloat:
+            mangledName += 'f';
+            break;
+        case EbtInt:
+            mangledName += 'i';
+            break;
+        case EbtUInt:
+            mangledName += 'u';
+            break;
+        case EbtBool:
+            mangledName += 'b';
+            break;
+        case EbtYuvCscStandardEXT:
+            mangledName += "ycs";
+            break;
+        case EbtSampler2D:
+            mangledName += "s2";
+            break;
+        case EbtSampler3D:
+            mangledName += "s3";
+            break;
+        case EbtSamplerCube:
+            mangledName += "sC";
+            break;
+        case EbtSampler2DArray:
+            mangledName += "s2a";
+            break;
+        case EbtSamplerExternalOES:
+            mangledName += "sext";
+            break;
+        case EbtSamplerExternal2DY2YEXT:
+            mangledName += "sext2y2y";
+            break;
+        case EbtSampler2DRect:
+            mangledName += "s2r";
+            break;
+        case EbtSampler2DMS:
+            mangledName += "s2ms";
+            break;
+        case EbtISampler2D:
+            mangledName += "is2";
+            break;
+        case EbtISampler3D:
+            mangledName += "is3";
+            break;
+        case EbtISamplerCube:
+            mangledName += "isC";
+            break;
+        case EbtISampler2DArray:
+            mangledName += "is2a";
+            break;
+        case EbtISampler2DMS:
+            mangledName += "is2ms";
+            break;
+        case EbtUSampler2D:
+            mangledName += "us2";
+            break;
+        case EbtUSampler3D:
+            mangledName += "us3";
+            break;
+        case EbtUSamplerCube:
+            mangledName += "usC";
+            break;
+        case EbtUSampler2DArray:
+            mangledName += "us2a";
+            break;
+        case EbtUSampler2DMS:
+            mangledName += "us2ms";
+            break;
+        case EbtSampler2DShadow:
+            mangledName += "s2s";
+            break;
+        case EbtSamplerCubeShadow:
+            mangledName += "sCs";
+            break;
+        case EbtSampler2DArrayShadow:
+            mangledName += "s2as";
+            break;
+        case EbtImage2D:
+            mangledName += "im2";
+            break;
+        case EbtIImage2D:
+            mangledName += "iim2";
+            break;
+        case EbtUImage2D:
+            mangledName += "uim2";
+            break;
+        case EbtImage3D:
+            mangledName += "im3";
+            break;
+        case EbtIImage3D:
+            mangledName += "iim3";
+            break;
+        case EbtUImage3D:
+            mangledName += "uim3";
+            break;
+        case EbtImage2DArray:
+            mangledName += "im2a";
+            break;
+        case EbtIImage2DArray:
+            mangledName += "iim2a";
+            break;
+        case EbtUImage2DArray:
+            mangledName += "uim2a";
+            break;
+        case EbtImageCube:
+            mangledName += "imc";
+            break;
+        case EbtIImageCube:
+            mangledName += "iimc";
+            break;
+        case EbtUImageCube:
+            mangledName += "uimc";
+            break;
+        case EbtStruct:
+            mangledName += structure->mangledName();
+            break;
+        case EbtInterfaceBlock:
+            mangledName += interfaceBlock->mangledName();
+            break;
+        default:
+            // EbtVoid, EbtAddress and non types
+            break;
+    }
+
+    if (isMatrix())
+    {
+        mangledName += static_cast<char>('0' + getCols());
+        mangledName += static_cast<char>('x');
+        mangledName += static_cast<char>('0' + getRows());
+    }
+    else
+    {
+        mangledName += static_cast<char>('0' + getNominalSize());
+    }
+
+    if (isArray())
+    {
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%d", arraySize);
+        mangledName += '[';
+        mangledName += buf;
+        mangledName += ']';
+    }
+    return mangledName;
+}
+
+size_t TType::getObjectSize() const
+{
+    size_t totalSize;
+
+    if (getBasicType() == EbtStruct)
+        totalSize = structure->objectSize();
+    else
+        totalSize = primarySize * secondarySize;
+
+    if (isArray())
+    {
+        if (totalSize == 0)
+            return 0;
+
+        size_t currentArraySize = getArraySize();
+        if (currentArraySize > INT_MAX / totalSize)
+            totalSize = INT_MAX;
+        else
+            totalSize *= currentArraySize;
+    }
+
+    return totalSize;
+}
+
+int TType::getLocationCount() const
+{
+    int count = 1;
+
+    if (getBasicType() == EbtStruct)
+    {
+        count = structure->getLocationCount();
+    }
+
+    if (isArray())
+    {
+        if (count == 0)
+        {
+            return 0;
+        }
+
+        unsigned int currentArraySize = getArraySize();
+        if (currentArraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count))
+        {
+            count = std::numeric_limits<int>::max();
+        }
+        else
+        {
+            count *= static_cast<int>(currentArraySize);
+        }
+    }
+
+    return count;
+}
+
+TStructure::TStructure(const TString *name, TFieldList *fields)
+    : TFieldListCollection(name, fields),
+      mDeepestNesting(0),
+      mUniqueId(TSymbolTable::nextUniqueId()),
+      mAtGlobalScope(false)
+{
+}
+
+bool TStructure::containsArrays() const
+{
+    for (size_t i = 0; i < mFields->size(); ++i)
+    {
+        const TType *fieldType = (*mFields)[i]->type();
+        if (fieldType->isArray() || fieldType->isStructureContainingArrays())
+            return true;
+    }
+    return false;
+}
+
+bool TStructure::containsType(TBasicType type) const
+{
+    for (size_t i = 0; i < mFields->size(); ++i)
+    {
+        const TType *fieldType = (*mFields)[i]->type();
+        if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
+            return true;
+    }
+    return false;
+}
+
+bool TStructure::containsSamplers() const
+{
+    for (size_t i = 0; i < mFields->size(); ++i)
+    {
+        const TType *fieldType = (*mFields)[i]->type();
+        if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
+            return true;
+    }
+    return false;
+}
+
+void TStructure::createSamplerSymbols(const TString &structName,
+                                      const TString &structAPIName,
+                                      const unsigned int arrayOfStructsSize,
+                                      TVector<TIntermSymbol *> *outputSymbols,
+                                      TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const
+{
+    for (auto &field : *mFields)
+    {
+        const TType *fieldType = field->type();
+        if (IsSampler(fieldType->getBasicType()))
+        {
+            if (arrayOfStructsSize > 0u)
+            {
+                for (unsigned int arrayIndex = 0u; arrayIndex < arrayOfStructsSize; ++arrayIndex)
+                {
+                    TStringStream name;
+                    name << structName << "_" << arrayIndex << "_" << field->name();
+                    TIntermSymbol *symbol = new TIntermSymbol(0, name.str(), *fieldType);
+                    outputSymbols->push_back(symbol);
+
+                    if (outputSymbolsToAPINames)
+                    {
+                        TStringStream apiName;
+                        apiName << structAPIName << "[" << arrayIndex << "]." << field->name();
+                        (*outputSymbolsToAPINames)[symbol] = apiName.str();
+                    }
+                }
+            }
+            else
+            {
+                TString symbolName    = structName + "_" + field->name();
+                TIntermSymbol *symbol = new TIntermSymbol(0, symbolName, *fieldType);
+                outputSymbols->push_back(symbol);
+
+                if (outputSymbolsToAPINames)
+                {
+                    TString apiName                    = structAPIName + "." + field->name();
+                    (*outputSymbolsToAPINames)[symbol] = apiName;
+                }
+            }
+        }
+        else if (fieldType->isStructureContainingSamplers())
+        {
+            unsigned int nestedArrayOfStructsSize =
+                fieldType->isArray() ? fieldType->getArraySize() : 0u;
+            if (arrayOfStructsSize > 0)
+            {
+                for (unsigned int arrayIndex = 0u; arrayIndex < arrayOfStructsSize; ++arrayIndex)
+                {
+                    TStringStream fieldName;
+                    fieldName << structName << "_" << arrayIndex << "_" << field->name();
+                    TStringStream fieldAPIName;
+                    if (outputSymbolsToAPINames)
+                    {
+                        fieldAPIName << structAPIName << "[" << arrayIndex << "]." << field->name();
+                    }
+                    fieldType->createSamplerSymbols(fieldName.str(), fieldAPIName.str(),
+                                                    nestedArrayOfStructsSize, outputSymbols,
+                                                    outputSymbolsToAPINames);
+                }
+            }
+            else
+            {
+                fieldType->createSamplerSymbols(
+                    structName + "_" + field->name(), structAPIName + "." + field->name(),
+                    nestedArrayOfStructsSize, outputSymbols, outputSymbolsToAPINames);
+            }
+        }
+    }
+}
+
+TString TFieldListCollection::buildMangledName(const TString &mangledNamePrefix) const
+{
+    TString mangledName(mangledNamePrefix);
+    mangledName += *mName;
+    for (size_t i = 0; i < mFields->size(); ++i)
+    {
+        mangledName += '-';
+        mangledName += (*mFields)[i]->type()->getMangledName();
+    }
+    return mangledName;
+}
+
+size_t TFieldListCollection::calculateObjectSize() const
+{
+    size_t size = 0;
+    for (const TField *field : *mFields)
+    {
+        size_t fieldSize = field->type()->getObjectSize();
+        if (fieldSize > INT_MAX - size)
+            size = INT_MAX;
+        else
+            size += fieldSize;
+    }
+    return size;
+}
+
+int TFieldListCollection::getLocationCount() const
+{
+    int count = 0;
+    for (const TField *field : *mFields)
+    {
+        int fieldCount = field->type()->getLocationCount();
+        if (fieldCount > std::numeric_limits<int>::max() - count)
+        {
+            count = std::numeric_limits<int>::max();
+        }
+        else
+        {
+            count += fieldCount;
+        }
+    }
+    return count;
+}
+
+int TStructure::calculateDeepestNesting() const
+{
+    int maxNesting = 0;
+    for (size_t i = 0; i < mFields->size(); ++i)
+        maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
+    return 1 + maxNesting;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/Types.h b/src/third_party/angle/src/compiler/translator/Types.h
new file mode 100644
index 0000000..721c090
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/Types.h
@@ -0,0 +1,646 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_TYPES_H_
+#define COMPILER_TRANSLATOR_TYPES_H_
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Common.h"
+
+namespace sh
+{
+
+struct TPublicType;
+class TType;
+class TSymbol;
+class TIntermSymbol;
+
+class TField : angle::NonCopyable
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TField(TType *type, TString *name, const TSourceLoc &line)
+        : mType(type), mName(name), mLine(line)
+    {
+    }
+
+    // TODO(alokp): We should only return const type.
+    // Fix it by tweaking grammar.
+    TType *type() { return mType; }
+    const TType *type() const { return mType; }
+
+    const TString &name() const { return *mName; }
+    const TSourceLoc &line() const { return mLine; }
+
+  private:
+    TType *mType;
+    TString *mName;
+    TSourceLoc mLine;
+};
+
+typedef TVector<TField *> TFieldList;
+inline TFieldList *NewPoolTFieldList()
+{
+    void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
+    return new (memory) TFieldList;
+}
+
+class TFieldListCollection : angle::NonCopyable
+{
+  public:
+    const TString &name() const { return *mName; }
+    const TFieldList &fields() const { return *mFields; }
+
+    size_t objectSize() const
+    {
+        if (mObjectSize == 0)
+            mObjectSize = calculateObjectSize();
+        return mObjectSize;
+    }
+
+    // How many locations the field list consumes as a uniform.
+    int getLocationCount() const;
+
+  protected:
+    TFieldListCollection(const TString *name, TFieldList *fields)
+        : mName(name), mFields(fields), mObjectSize(0)
+    {
+    }
+    TString buildMangledName(const TString &mangledNamePrefix) const;
+    size_t calculateObjectSize() const;
+
+    const TString *mName;
+    TFieldList *mFields;
+
+    mutable TString mMangledName;
+    mutable size_t mObjectSize;
+};
+
+// May also represent interface blocks
+class TStructure : public TFieldListCollection
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TStructure(const TString *name, TFieldList *fields);
+
+    int deepestNesting() const
+    {
+        if (mDeepestNesting == 0)
+            mDeepestNesting = calculateDeepestNesting();
+        return mDeepestNesting;
+    }
+    bool containsArrays() const;
+    bool containsType(TBasicType t) const;
+    bool containsSamplers() const;
+
+    void createSamplerSymbols(const TString &structName,
+                              const TString &structAPIName,
+                              const unsigned int arrayOfStructsSize,
+                              TVector<TIntermSymbol *> *outputSymbols,
+                              TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const;
+
+    bool equals(const TStructure &other) const;
+
+    void setUniqueId(int uniqueId) { mUniqueId = uniqueId; }
+
+    int uniqueId() const
+    {
+        ASSERT(mUniqueId != 0);
+        return mUniqueId;
+    }
+
+    void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
+
+    bool atGlobalScope() const { return mAtGlobalScope; }
+
+    const TString &mangledName() const
+    {
+        if (mMangledName.empty())
+            mMangledName = buildMangledName("struct-");
+        return mMangledName;
+    }
+
+  private:
+    // TODO(zmo): Find a way to get rid of the const_cast in function
+    // setName().  At the moment keep this function private so only
+    // friend class RegenerateStructNames may call it.
+    friend class RegenerateStructNames;
+    void setName(const TString &name)
+    {
+        TString *mutableName = const_cast<TString *>(mName);
+        *mutableName         = name;
+    }
+
+    int calculateDeepestNesting() const;
+
+    mutable int mDeepestNesting;
+    int mUniqueId;
+    bool mAtGlobalScope;
+};
+
+class TInterfaceBlock : public TFieldListCollection
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TInterfaceBlock(const TString *name,
+                    TFieldList *fields,
+                    const TString *instanceName,
+                    int arraySize,
+                    const TLayoutQualifier &layoutQualifier)
+        : TFieldListCollection(name, fields),
+          mInstanceName(instanceName),
+          mArraySize(arraySize),
+          mBlockStorage(layoutQualifier.blockStorage),
+          mMatrixPacking(layoutQualifier.matrixPacking)
+    {
+    }
+
+    const TString &instanceName() const { return *mInstanceName; }
+    bool hasInstanceName() const { return mInstanceName != nullptr; }
+    bool isArray() const { return mArraySize > 0; }
+    int arraySize() const { return mArraySize; }
+    TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
+    TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; }
+    const TString &mangledName() const
+    {
+        if (mMangledName.empty())
+            mMangledName = buildMangledName("iblock-");
+        return mMangledName;
+    }
+
+  private:
+    const TString *mInstanceName;  // for interface block instance names
+    int mArraySize;                // 0 if not an array
+    TLayoutBlockStorage mBlockStorage;
+    TLayoutMatrixPacking mMatrixPacking;
+};
+
+//
+// Base class for things that have a type.
+//
+class TType
+{
+  public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TType()
+        : type(EbtVoid),
+          precision(EbpUndefined),
+          qualifier(EvqGlobal),
+          invariant(false),
+          memoryQualifier(TMemoryQualifier::create()),
+          layoutQualifier(TLayoutQualifier::create()),
+          primarySize(0),
+          secondarySize(0),
+          array(false),
+          arraySize(0),
+          interfaceBlock(nullptr),
+          structure(nullptr)
+    {
+    }
+    explicit TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1)
+        : type(t),
+          precision(EbpUndefined),
+          qualifier(EvqGlobal),
+          invariant(false),
+          memoryQualifier(TMemoryQualifier::create()),
+          layoutQualifier(TLayoutQualifier::create()),
+          primarySize(ps),
+          secondarySize(ss),
+          array(false),
+          arraySize(0),
+          interfaceBlock(0),
+          structure(0)
+    {
+    }
+    TType(TBasicType t,
+          TPrecision p,
+          TQualifier q     = EvqTemporary,
+          unsigned char ps = 1,
+          unsigned char ss = 1,
+          bool a           = false)
+        : type(t),
+          precision(p),
+          qualifier(q),
+          invariant(false),
+          memoryQualifier(TMemoryQualifier::create()),
+          layoutQualifier(TLayoutQualifier::create()),
+          primarySize(ps),
+          secondarySize(ss),
+          array(a),
+          arraySize(0),
+          interfaceBlock(0),
+          structure(0)
+    {
+    }
+    explicit TType(const TPublicType &p);
+    explicit TType(TStructure *userDef, TPrecision p = EbpUndefined)
+        : type(EbtStruct),
+          precision(p),
+          qualifier(EvqTemporary),
+          invariant(false),
+          memoryQualifier(TMemoryQualifier::create()),
+          layoutQualifier(TLayoutQualifier::create()),
+          primarySize(1),
+          secondarySize(1),
+          array(false),
+          arraySize(0),
+          interfaceBlock(0),
+          structure(userDef)
+    {
+    }
+    TType(TInterfaceBlock *interfaceBlockIn,
+          TQualifier qualifierIn,
+          TLayoutQualifier layoutQualifierIn,
+          int arraySizeIn)
+        : type(EbtInterfaceBlock),
+          precision(EbpUndefined),
+          qualifier(qualifierIn),
+          invariant(false),
+          memoryQualifier(TMemoryQualifier::create()),
+          layoutQualifier(layoutQualifierIn),
+          primarySize(1),
+          secondarySize(1),
+          array(arraySizeIn > 0),
+          arraySize(arraySizeIn),
+          interfaceBlock(interfaceBlockIn),
+          structure(0)
+    {
+    }
+
+    TType(const TType &) = default;
+    TType &operator=(const TType &) = default;
+
+    TBasicType getBasicType() const { return type; }
+    void setBasicType(TBasicType t)
+    {
+        if (type != t)
+        {
+            type = t;
+            invalidateMangledName();
+        }
+    }
+
+    TPrecision getPrecision() const { return precision; }
+    void setPrecision(TPrecision p) { precision = p; }
+
+    TQualifier getQualifier() const { return qualifier; }
+    void setQualifier(TQualifier q) { qualifier = q; }
+
+    bool isInvariant() const { return invariant; }
+
+    void setInvariant(bool i) { invariant = i; }
+
+    TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; }
+    void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; }
+
+    TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
+    void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
+
+    int getNominalSize() const { return primarySize; }
+    int getSecondarySize() const { return secondarySize; }
+    int getCols() const
+    {
+        ASSERT(isMatrix());
+        return primarySize;
+    }
+    int getRows() const
+    {
+        ASSERT(isMatrix());
+        return secondarySize;
+    }
+    void setPrimarySize(unsigned char ps)
+    {
+        if (primarySize != ps)
+        {
+            ASSERT(ps <= 4);
+            primarySize = ps;
+            invalidateMangledName();
+        }
+    }
+    void setSecondarySize(unsigned char ss)
+    {
+        if (secondarySize != ss)
+        {
+            ASSERT(ss <= 4);
+            secondarySize = ss;
+            invalidateMangledName();
+        }
+    }
+
+    // Full size of single instance of type
+    size_t getObjectSize() const;
+
+    // Get how many locations this type consumes as a uniform.
+    int getLocationCount() const;
+
+    bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
+    bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; }
+    bool isArray() const { return array; }
+    bool isUnsizedArray() const { return array && arraySize == 0u; }
+    unsigned int getArraySize() const { return arraySize; }
+    void setArraySize(unsigned int s)
+    {
+        if (!array || arraySize != s)
+        {
+            array     = true;
+            arraySize = s;
+            invalidateMangledName();
+        }
+    }
+    void clearArrayness()
+    {
+        if (array)
+        {
+            array     = false;
+            arraySize = 0u;
+            invalidateMangledName();
+        }
+    }
+
+    TInterfaceBlock *getInterfaceBlock() const { return interfaceBlock; }
+    void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn)
+    {
+        if (interfaceBlock != interfaceBlockIn)
+        {
+            interfaceBlock = interfaceBlockIn;
+            invalidateMangledName();
+        }
+    }
+    bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
+
+    bool isVector() const { return primarySize > 1 && secondarySize == 1; }
+    bool isScalar() const { return primarySize == 1 && secondarySize == 1 && !structure; }
+    bool isScalarFloat() const { return isScalar() && type == EbtFloat; }
+    bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }
+
+    bool canBeConstructed() const;
+
+    TStructure *getStruct() const { return structure; }
+    void setStruct(TStructure *s)
+    {
+        if (structure != s)
+        {
+            structure = s;
+            invalidateMangledName();
+        }
+    }
+
+    const TString &getMangledName() const
+    {
+        if (mangled.empty())
+        {
+            mangled = buildMangledName();
+            mangled += ';';
+        }
+
+        return mangled;
+    }
+
+    bool sameElementType(const TType &right) const
+    {
+        return type == right.type && primarySize == right.primarySize &&
+               secondarySize == right.secondarySize && structure == right.structure;
+    }
+    bool operator==(const TType &right) const
+    {
+        return type == right.type && primarySize == right.primarySize &&
+               secondarySize == right.secondarySize && array == right.array &&
+               (!array || arraySize == right.arraySize) && structure == right.structure;
+        // don't check the qualifier, it's not ever what's being sought after
+    }
+    bool operator!=(const TType &right) const { return !operator==(right); }
+    bool operator<(const TType &right) const
+    {
+        if (type != right.type)
+            return type < right.type;
+        if (primarySize != right.primarySize)
+            return primarySize < right.primarySize;
+        if (secondarySize != right.secondarySize)
+            return secondarySize < right.secondarySize;
+        if (array != right.array)
+            return array < right.array;
+        if (arraySize != right.arraySize)
+            return arraySize < right.arraySize;
+        if (structure != right.structure)
+            return structure < right.structure;
+
+        return false;
+    }
+
+    const char *getBasicString() const { return sh::getBasicString(type); }
+
+    const char *getPrecisionString() const { return sh::getPrecisionString(precision); }
+    const char *getQualifierString() const { return sh::getQualifierString(qualifier); }
+
+    const char *getBuiltInTypeNameString() const;
+
+    TString getCompleteString() const;
+
+    // If this type is a struct, returns the deepest struct nesting of
+    // any field in the struct. For example:
+    //   struct nesting1 {
+    //     vec4 position;
+    //   };
+    //   struct nesting2 {
+    //     nesting1 field1;
+    //     vec4 field2;
+    //   };
+    // For type "nesting2", this method would return 2 -- the number
+    // of structures through which indirection must occur to reach the
+    // deepest field (nesting2.field1.position).
+    int getDeepestStructNesting() const { return structure ? structure->deepestNesting() : 0; }
+
+    bool isStructureContainingArrays() const
+    {
+        return structure ? structure->containsArrays() : false;
+    }
+
+    bool isStructureContainingType(TBasicType t) const
+    {
+        return structure ? structure->containsType(t) : false;
+    }
+
+    bool isStructureContainingSamplers() const
+    {
+        return structure ? structure->containsSamplers() : false;
+    }
+
+    void createSamplerSymbols(const TString &structName,
+                              const TString &structAPIName,
+                              const unsigned int arrayOfStructsSize,
+                              TVector<TIntermSymbol *> *outputSymbols,
+                              TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const
+    {
+        ASSERT(structure != nullptr && structure->containsSamplers());
+        structure->createSamplerSymbols(structName, structAPIName, arrayOfStructsSize,
+                                        outputSymbols, outputSymbolsToAPINames);
+    }
+
+    // Initializes all lazily-initialized members.
+    void realize() { getMangledName(); }
+
+  private:
+    void invalidateMangledName() { mangled = ""; }
+    TString buildMangledName() const;
+
+    TBasicType type;
+    TPrecision precision;
+    TQualifier qualifier;
+    bool invariant;
+    TMemoryQualifier memoryQualifier;
+    TLayoutQualifier layoutQualifier;
+    unsigned char primarySize;    // size of vector or cols matrix
+    unsigned char secondarySize;  // rows of a matrix
+    bool array;
+    unsigned int arraySize;
+
+    // 0 unless this is an interface block, or interface block member variable
+    TInterfaceBlock *interfaceBlock;
+
+    // 0 unless this is a struct
+    TStructure *structure;
+
+    mutable TString mangled;
+};
+
+// TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the
+// grammar
+struct TTypeSpecifierNonArray
+{
+    TBasicType type;
+    unsigned char primarySize;    // size of vector or cols of matrix
+    unsigned char secondarySize;  // rows of matrix
+    TType *userDef;
+    TSourceLoc line;
+
+    // true if the type was defined by a struct specifier rather than a reference to a type name.
+    bool isStructSpecifier;
+
+    void initialize(TBasicType bt, const TSourceLoc &ln)
+    {
+        type              = bt;
+        primarySize       = 1;
+        secondarySize     = 1;
+        userDef           = nullptr;
+        line              = ln;
+        isStructSpecifier = false;
+    }
+
+    void setAggregate(unsigned char size) { primarySize = size; }
+
+    void setMatrix(unsigned char columns, unsigned char rows)
+    {
+        ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4);
+        primarySize   = columns;
+        secondarySize = rows;
+    }
+
+    bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
+
+    bool isVector() const { return primarySize > 1 && secondarySize == 1; }
+};
+
+//
+// This is a workaround for a problem with the yacc stack,  It can't have
+// types that it thinks have non-trivial constructors.  It should
+// just be used while recognizing the grammar, not anything else.  Pointers
+// could be used, but also trying to avoid lots of memory management overhead.
+//
+// Not as bad as it looks, there is no actual assumption that the fields
+// match up or are name the same or anything like that.
+//
+struct TPublicType
+{
+    TTypeSpecifierNonArray typeSpecifierNonArray;
+    TLayoutQualifier layoutQualifier;
+    TMemoryQualifier memoryQualifier;
+    TQualifier qualifier;
+    bool invariant;
+    TPrecision precision;
+    bool array;
+    int arraySize;
+
+    void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q)
+    {
+        typeSpecifierNonArray = typeSpecifier;
+        layoutQualifier       = TLayoutQualifier::create();
+        memoryQualifier       = TMemoryQualifier::create();
+        qualifier             = q;
+        invariant             = false;
+        precision             = EbpUndefined;
+        array                 = false;
+        arraySize             = 0;
+    }
+
+    void initializeBasicType(TBasicType basicType)
+    {
+        typeSpecifierNonArray.type          = basicType;
+        typeSpecifierNonArray.primarySize   = 1;
+        typeSpecifierNonArray.secondarySize = 1;
+        layoutQualifier                     = TLayoutQualifier::create();
+        memoryQualifier                     = TMemoryQualifier::create();
+        qualifier                           = EvqTemporary;
+        invariant                           = false;
+        precision                           = EbpUndefined;
+        array                               = false;
+        arraySize                           = 0;
+    }
+
+    TBasicType getBasicType() const { return typeSpecifierNonArray.type; }
+    void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; }
+
+    unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
+    unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
+
+    const TType *getUserDef() const { return typeSpecifierNonArray.userDef; }
+    const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }
+
+    bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }
+
+    bool isStructureContainingArrays() const
+    {
+        if (!typeSpecifierNonArray.userDef)
+        {
+            return false;
+        }
+
+        return typeSpecifierNonArray.userDef->isStructureContainingArrays();
+    }
+
+    bool isStructureContainingType(TBasicType t) const
+    {
+        if (!typeSpecifierNonArray.userDef)
+        {
+            return false;
+        }
+
+        return typeSpecifierNonArray.userDef->isStructureContainingType(t);
+    }
+
+    bool isUnsizedArray() const { return array && arraySize == 0; }
+    void setArraySize(int s)
+    {
+        array     = true;
+        arraySize = s;
+    }
+    void clearArrayness()
+    {
+        array     = false;
+        arraySize = 0;
+    }
+
+    bool isAggregate() const
+    {
+        return array || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector();
+    }
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_TYPES_H_
diff --git a/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
new file mode 100644
index 0000000..e6d953a
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/UnfoldShortCircuitAST.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// "x || y" is equivalent to "x ? true : y".
+TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y)
+{
+    TConstantUnion *u = new TConstantUnion;
+    u->setBConst(true);
+    TIntermConstantUnion *trueNode =
+        new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1));
+    return new TIntermTernary(x, trueNode, y);
+}
+
+// "x && y" is equivalent to "x ? y : false".
+TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y)
+{
+    TConstantUnion *u = new TConstantUnion;
+    u->setBConst(false);
+    TIntermConstantUnion *falseNode =
+        new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1));
+    return new TIntermTernary(x, y, falseNode);
+}
+
+}  // namespace anonymous
+
+bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node)
+{
+    TIntermTernary *replacement = nullptr;
+
+    switch (node->getOp())
+    {
+        case EOpLogicalOr:
+            replacement = UnfoldOR(node->getLeft(), node->getRight());
+            break;
+        case EOpLogicalAnd:
+            replacement = UnfoldAND(node->getLeft(), node->getRight());
+            break;
+        default:
+            break;
+    }
+    if (replacement)
+    {
+        queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
+    }
+    return true;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitAST.h
new file mode 100644
index 0000000..fe6d8fd
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitAST.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// UnfoldShortCircuitAST is an AST traverser to replace short-circuiting
+// operations with ternary operations.
+//
+
+#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
+#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+// This traverser identifies all the short circuit binary  nodes that need to
+// be replaced, and creates the corresponding replacement nodes. However,
+// the actual replacements happen after the traverse through updateTree().
+
+class UnfoldShortCircuitAST : public TIntermTraverser
+{
+  public:
+    UnfoldShortCircuitAST() : TIntermTraverser(true, false, false) {}
+
+    bool visitBinary(Visit visit, TIntermBinary *) override;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
diff --git a/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp b/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp
new file mode 100644
index 0000000..3751128
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp
@@ -0,0 +1,188 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else
+// statements.
+// The results are assigned to s# temporaries, which are used by the main translator instead of
+// the original expression.
+//
+
+#include "compiler/translator/UnfoldShortCircuitToIf.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// Traverser that unfolds one short-circuiting operation at a time.
+class UnfoldShortCircuitTraverser : public TIntermTraverser
+{
+  public:
+    UnfoldShortCircuitTraverser();
+
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+    bool visitTernary(Visit visit, TIntermTernary *node) override;
+
+    void nextIteration();
+    bool foundShortCircuit() const { return mFoundShortCircuit; }
+
+  protected:
+    // Marked to true once an operation that needs to be unfolded has been found.
+    // After that, no more unfolding is performed on that traversal.
+    bool mFoundShortCircuit;
+
+    IntermNodePatternMatcher mPatternToUnfoldMatcher;
+};
+
+UnfoldShortCircuitTraverser::UnfoldShortCircuitTraverser()
+    : TIntermTraverser(true, false, true),
+      mFoundShortCircuit(false),
+      mPatternToUnfoldMatcher(IntermNodePatternMatcher::kUnfoldedShortCircuitExpression)
+{
+}
+
+bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+    if (mFoundShortCircuit)
+        return false;
+
+    if (visit != PreVisit)
+        return true;
+
+    if (!mPatternToUnfoldMatcher.match(node, getParentNode()))
+        return true;
+
+    // If our right node doesn't have side effects, we know we don't need to unfold this
+    // expression: there will be no short-circuiting side effects to avoid
+    // (note: unfolding doesn't depend on the left node -- it will always be evaluated)
+    ASSERT(node->getRight()->hasSideEffects());
+
+    mFoundShortCircuit = true;
+
+    switch (node->getOp())
+    {
+        case EOpLogicalOr:
+        {
+            // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true;
+            // else s = y;",
+            // and then further simplifies down to "bool s = x; if(!s) s = y;".
+
+            TIntermSequence insertions;
+            TType boolType(EbtBool, EbpUndefined, EvqTemporary);
+
+            ASSERT(node->getLeft()->getType() == boolType);
+            insertions.push_back(createTempInitDeclaration(node->getLeft()));
+
+            TIntermBlock *assignRightBlock = new TIntermBlock();
+            ASSERT(node->getRight()->getType() == boolType);
+            assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight()));
+
+            TIntermUnary *notTempSymbol =
+                new TIntermUnary(EOpLogicalNot, createTempSymbol(boolType));
+            TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr);
+            insertions.push_back(ifNode);
+
+            insertStatementsInParentBlock(insertions);
+
+            queueReplacement(node, createTempSymbol(boolType), OriginalNode::IS_DROPPED);
+            return false;
+        }
+        case EOpLogicalAnd:
+        {
+            // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y;
+            // else s = false;",
+            // and then further simplifies down to "bool s = x; if(s) s = y;".
+            TIntermSequence insertions;
+            TType boolType(EbtBool, EbpUndefined, EvqTemporary);
+
+            ASSERT(node->getLeft()->getType() == boolType);
+            insertions.push_back(createTempInitDeclaration(node->getLeft()));
+
+            TIntermBlock *assignRightBlock = new TIntermBlock();
+            ASSERT(node->getRight()->getType() == boolType);
+            assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight()));
+
+            TIntermIfElse *ifNode =
+                new TIntermIfElse(createTempSymbol(boolType), assignRightBlock, nullptr);
+            insertions.push_back(ifNode);
+
+            insertStatementsInParentBlock(insertions);
+
+            queueReplacement(node, createTempSymbol(boolType), OriginalNode::IS_DROPPED);
+            return false;
+        }
+        default:
+            UNREACHABLE();
+            return true;
+    }
+}
+
+bool UnfoldShortCircuitTraverser::visitTernary(Visit visit, TIntermTernary *node)
+{
+    if (mFoundShortCircuit)
+        return false;
+
+    if (visit != PreVisit)
+        return true;
+
+    if (!mPatternToUnfoldMatcher.match(node))
+        return true;
+
+    mFoundShortCircuit = true;
+
+    // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
+    TIntermSequence insertions;
+
+    TIntermDeclaration *tempDeclaration = createTempDeclaration(node->getType());
+    insertions.push_back(tempDeclaration);
+
+    TIntermBlock *trueBlock       = new TIntermBlock();
+    TIntermBinary *trueAssignment = createTempAssignment(node->getTrueExpression());
+    trueBlock->getSequence()->push_back(trueAssignment);
+
+    TIntermBlock *falseBlock       = new TIntermBlock();
+    TIntermBinary *falseAssignment = createTempAssignment(node->getFalseExpression());
+    falseBlock->getSequence()->push_back(falseAssignment);
+
+    TIntermIfElse *ifNode =
+        new TIntermIfElse(node->getCondition()->getAsTyped(), trueBlock, falseBlock);
+    insertions.push_back(ifNode);
+
+    insertStatementsInParentBlock(insertions);
+
+    TIntermSymbol *ternaryResult = createTempSymbol(node->getType());
+    queueReplacement(node, ternaryResult, OriginalNode::IS_DROPPED);
+
+    return false;
+}
+
+void UnfoldShortCircuitTraverser::nextIteration()
+{
+    mFoundShortCircuit = false;
+    nextTemporaryIndex();
+}
+
+}  // namespace
+
+void UnfoldShortCircuitToIf(TIntermNode *root, unsigned int *temporaryIndex)
+{
+    UnfoldShortCircuitTraverser traverser;
+    ASSERT(temporaryIndex != nullptr);
+    traverser.useTemporaryIndex(temporaryIndex);
+    // Unfold one operator at a time, and reset the traverser between iterations.
+    do
+    {
+        traverser.nextIteration();
+        root->traverse(&traverser);
+        if (traverser.foundShortCircuit())
+            traverser.updateTree();
+    } while (traverser.foundShortCircuit());
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitToIf.h b/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitToIf.h
new file mode 100644
index 0000000..b1ff064
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UnfoldShortCircuitToIf.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else
+// statements.
+// The results are assigned to s# temporaries, which are used by the main translator instead of
+// the original expression.
+//
+
+#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
+#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
+
+namespace sh
+{
+class TIntermNode;
+
+void UnfoldShortCircuitToIf(TIntermNode *root, unsigned int *temporaryIndex);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
diff --git a/src/third_party/angle/src/compiler/translator/UniformHLSL.cpp b/src/third_party/angle/src/compiler/translator/UniformHLSL.cpp
new file mode 100644
index 0000000..f27335b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UniformHLSL.cpp
@@ -0,0 +1,487 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// UniformHLSL.cpp:
+//   Methods for GLSL to HLSL translation for uniforms and interface blocks.
+//
+
+#include "compiler/translator/UniformHLSL.h"
+
+#include "common/utilities.h"
+#include "compiler/translator/StructureHLSL.h"
+#include "compiler/translator/UtilsHLSL.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+static const char *UniformRegisterPrefix(const TType &type)
+{
+    if (IsSampler(type.getBasicType()))
+    {
+        return "s";
+    }
+    else
+    {
+        return "c";
+    }
+}
+
+static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
+{
+    const TType &fieldType                   = *field.type();
+    const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
+    ASSERT(matrixPacking != EmpUnspecified);
+    TStructure *structure = fieldType.getStruct();
+
+    if (fieldType.isMatrix())
+    {
+        // Use HLSL row-major packing for GLSL column-major matrices
+        const TString &matrixPackString =
+            (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
+        return matrixPackString + " " + TypeString(fieldType);
+    }
+    else if (structure)
+    {
+        // Use HLSL row-major packing for GLSL column-major matrices
+        return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor,
+                                         blockStorage == EbsStd140);
+    }
+    else
+    {
+        return TypeString(fieldType);
+    }
+}
+
+static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
+{
+    return DecoratePrivate(interfaceBlock.name()) + "_type";
+}
+
+UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL,
+                         ShShaderOutput outputType,
+                         const std::vector<Uniform> &uniforms)
+    : mUniformRegister(0),
+      mInterfaceBlockRegister(0),
+      mSamplerRegister(0),
+      mStructureHLSL(structureHLSL),
+      mOutputType(outputType),
+      mUniforms(uniforms)
+{
+}
+
+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];
+        }
+    }
+
+    return nullptr;
+}
+
+unsigned int UniformHLSL::assignUniformRegister(const TType &type,
+                                                const TString &name,
+                                                unsigned int *outRegisterCount)
+{
+    unsigned int registerIndex =
+        (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
+
+    const Uniform *uniform = findUniformByName(name);
+    ASSERT(uniform);
+
+    mUniformRegisterMap[uniform->name] = registerIndex;
+
+    unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
+
+    if (gl::IsSamplerType(uniform->type))
+    {
+        mSamplerRegister += registerCount;
+    }
+    else
+    {
+        mUniformRegister += registerCount;
+    }
+    if (outRegisterCount)
+    {
+        *outRegisterCount = registerCount;
+    }
+    return registerIndex;
+}
+
+unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type,
+                                                               const TString &name,
+                                                               unsigned int *outRegisterCount)
+{
+    // Sampler that is a field of a uniform structure.
+    ASSERT(IsSampler(type.getBasicType()));
+    unsigned int registerIndex                     = mSamplerRegister;
+    mUniformRegisterMap[std::string(name.c_str())] = registerIndex;
+    unsigned int registerCount                     = type.isArray() ? type.getArraySize() : 1u;
+    mSamplerRegister += registerCount;
+    if (outRegisterCount)
+    {
+        *outRegisterCount = registerCount;
+    }
+    return registerIndex;
+}
+
+void UniformHLSL::outputHLSLSamplerUniformGroup(
+    TInfoSinkBase &out,
+    const HLSLTextureSamplerGroup textureGroup,
+    const TVector<const TIntermSymbol *> &group,
+    const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames,
+    unsigned int *groupTextureRegisterIndex)
+{
+    if (group.empty())
+    {
+        return;
+    }
+    unsigned int groupRegisterCount = 0;
+    for (const TIntermSymbol *uniform : group)
+    {
+        const TType &type   = uniform->getType();
+        const TString &name = uniform->getSymbol();
+        unsigned int registerCount;
+
+        // The uniform might be just a regular sampler or one extracted from a struct.
+        unsigned int samplerArrayIndex = 0u;
+        const Uniform *uniformByName   = findUniformByName(name);
+        if (uniformByName)
+        {
+            samplerArrayIndex = assignUniformRegister(type, name, &registerCount);
+        }
+        else
+        {
+            ASSERT(samplerInStructSymbolsToAPINames.find(uniform) !=
+                   samplerInStructSymbolsToAPINames.end());
+            samplerArrayIndex = assignSamplerInStructUniformRegister(
+                type, samplerInStructSymbolsToAPINames.at(uniform), &registerCount);
+        }
+        groupRegisterCount += registerCount;
+
+        if (type.isArray())
+        {
+            out << "static const uint " << DecorateIfNeeded(uniform->getName()) << ArrayString(type)
+                << " = {";
+            for (unsigned int i = 0u; i < type.getArraySize(); ++i)
+            {
+                if (i > 0u)
+                    out << ", ";
+                out << (samplerArrayIndex + i);
+            }
+            out << "};\n";
+        }
+        else
+        {
+            out << "static const uint " << DecorateIfNeeded(uniform->getName()) << " = "
+                << samplerArrayIndex << ";\n";
+        }
+    }
+    TString suffix = TextureGroupSuffix(textureGroup);
+    // Since HLSL_TEXTURE_2D is the first group, it has a fixed offset of zero.
+    if (textureGroup != HLSL_TEXTURE_2D)
+    {
+        out << "static const uint textureIndexOffset" << suffix << " = "
+            << (*groupTextureRegisterIndex) << ";\n";
+        out << "static const uint samplerIndexOffset" << suffix << " = "
+            << (*groupTextureRegisterIndex) << ";\n";
+    }
+    out << "uniform " << TextureString(textureGroup) << " textures" << suffix << "["
+        << groupRegisterCount << "]"
+        << " : register(t" << (*groupTextureRegisterIndex) << ");\n";
+    out << "uniform " << SamplerString(textureGroup) << " samplers" << suffix << "["
+        << groupRegisterCount << "]"
+        << " : register(s" << (*groupTextureRegisterIndex) << ");\n";
+    *groupTextureRegisterIndex += groupRegisterCount;
+}
+
+void UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
+                                             const TType &type,
+                                             const TName &name,
+                                             const unsigned int registerIndex)
+{
+    out << "uniform " << SamplerString(type.getBasicType()) << " sampler_"
+        << DecorateUniform(name, type) << ArrayString(type) << " : register(s" << str(registerIndex)
+        << ");\n";
+    out << "uniform " << TextureString(type.getBasicType()) << " texture_"
+        << DecorateUniform(name, type) << ArrayString(type) << " : register(t" << str(registerIndex)
+        << ");\n";
+}
+
+void UniformHLSL::outputUniform(TInfoSinkBase &out,
+                                const TType &type,
+                                const TName &name,
+                                const unsigned int registerIndex)
+{
+    const TStructure *structure = type.getStruct();
+    // If this is a nameless struct, we need to use its full definition, rather than its (empty)
+    // name.
+    // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for
+    // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers
+    // are permitted.
+    const TString &typeName = ((structure && !structure->name().empty())
+                                   ? QualifiedStructNameString(*structure, false, false)
+                                   : TypeString(type));
+
+    const TString &registerString =
+        TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";
+
+    out << "uniform " << typeName << " ";
+
+    out << DecorateUniform(name, type);
+
+    out << ArrayString(type) << " : " << registerString << ";\n";
+}
+
+void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
+                                 ShShaderOutput outputType,
+                                 const ReferencedSymbols &referencedUniforms)
+{
+    if (!referencedUniforms.empty())
+    {
+        out << "// Uniforms\n\n";
+    }
+    // In the case of HLSL 4, sampler uniforms need to be grouped by type before the code is
+    // written. They are grouped based on the combination of the HLSL texture type and
+    // HLSL sampler type, enumerated in HLSLTextureSamplerGroup.
+    TVector<TVector<const TIntermSymbol *>> groupedSamplerUniforms(HLSL_TEXTURE_MAX + 1);
+    TMap<const TIntermSymbol *, TString> samplerInStructSymbolsToAPINames;
+    for (auto &uniformIt : referencedUniforms)
+    {
+        // Output regular uniforms. Group sampler uniforms by type.
+        const TIntermSymbol &uniform = *uniformIt.second;
+        const TType &type            = uniform.getType();
+        const TName &name            = uniform.getName();
+
+        if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType()))
+        {
+            HLSLTextureSamplerGroup group = TextureGroup(type.getBasicType());
+            groupedSamplerUniforms[group].push_back(&uniform);
+        }
+        else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType()))
+        {
+            unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
+            outputHLSL4_0_FL9_3Sampler(out, type, name, registerIndex);
+        }
+        else
+        {
+            if (type.isStructureContainingSamplers())
+            {
+                TVector<TIntermSymbol *> samplerSymbols;
+                TMap<TIntermSymbol *, TString> symbolsToAPINames;
+                unsigned int arrayOfStructsSize = type.isArray() ? type.getArraySize() : 0u;
+                type.createSamplerSymbols("angle_" + name.getString(), name.getString(),
+                                          arrayOfStructsSize, &samplerSymbols, &symbolsToAPINames);
+                for (TIntermSymbol *sampler : samplerSymbols)
+                {
+                    const TType &samplerType = sampler->getType();
+
+                    // Will use angle_ prefix instead of regular prefix.
+                    sampler->setInternal(true);
+                    const TName &samplerName = sampler->getName();
+
+                    if (outputType == SH_HLSL_4_1_OUTPUT)
+                    {
+                        HLSLTextureSamplerGroup group = TextureGroup(samplerType.getBasicType());
+                        groupedSamplerUniforms[group].push_back(sampler);
+                        samplerInStructSymbolsToAPINames[sampler] = symbolsToAPINames[sampler];
+                    }
+                    else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+                    {
+                        unsigned int registerIndex = assignSamplerInStructUniformRegister(
+                            samplerType, symbolsToAPINames[sampler], nullptr);
+                        outputHLSL4_0_FL9_3Sampler(out, samplerType, samplerName, registerIndex);
+                    }
+                    else
+                    {
+                        ASSERT(outputType == SH_HLSL_3_0_OUTPUT);
+                        unsigned int registerIndex = assignSamplerInStructUniformRegister(
+                            samplerType, symbolsToAPINames[sampler], nullptr);
+                        outputUniform(out, samplerType, samplerName, registerIndex);
+                    }
+                }
+            }
+            unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
+            outputUniform(out, type, name, registerIndex);
+        }
+    }
+
+    if (outputType == SH_HLSL_4_1_OUTPUT)
+    {
+        unsigned int groupTextureRegisterIndex = 0;
+        // TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case.
+        ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D);
+        for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId)
+        {
+            outputHLSLSamplerUniformGroup(
+                out, HLSLTextureSamplerGroup(groupId), groupedSamplerUniforms[groupId],
+                samplerInStructSymbolsToAPINames, &groupTextureRegisterIndex);
+        }
+    }
+}
+
+void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg)
+{
+    // If mSamplerRegister is 0 the shader doesn't use any textures.
+    if (mSamplerRegister > 0)
+    {
+        out << "    struct SamplerMetadata\n"
+               "    {\n"
+               "        int baseLevel;\n"
+               "        int internalFormatBits;\n"
+               "        int wrapModes;\n"
+               "        int padding;\n"
+               "    };\n"
+               "    SamplerMetadata samplerMetadata["
+            << mSamplerRegister << "] : packoffset(" << reg << ");\n";
+    }
+}
+
+TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
+{
+    TString interfaceBlocks;
+
+    for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
+         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;
+
+        mInterfaceBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
+        mInterfaceBlockRegister += std::max(1u, arraySize);
+
+        // FIXME: interface block field names
+
+        if (interfaceBlock.hasInstanceName())
+        {
+            interfaceBlocks += interfaceBlockStructString(interfaceBlock);
+        }
+
+        if (arraySize > 0)
+        {
+            for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
+            {
+                interfaceBlocks +=
+                    interfaceBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex);
+            }
+        }
+        else
+        {
+            interfaceBlocks +=
+                interfaceBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX);
+        }
+    }
+
+    return (interfaceBlocks.empty() ? "" : ("// Interface Blocks\n\n" + interfaceBlocks));
+}
+
+TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock,
+                                          unsigned int registerIndex,
+                                          unsigned int arrayIndex)
+{
+    const TString &arrayIndexString =
+        (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
+    const TString &blockName = interfaceBlock.name() + arrayIndexString;
+    TString hlsl;
+
+    hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) +
+            ")\n"
+            "{\n";
+
+    if (interfaceBlock.hasInstanceName())
+    {
+        hlsl += "    " + InterfaceBlockStructName(interfaceBlock) + " " +
+                interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
+    }
+    else
+    {
+        const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
+        hlsl += interfaceBlockMembersString(interfaceBlock, blockStorage);
+    }
+
+    hlsl += "};\n\n";
+
+    return hlsl;
+}
+
+TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock &interfaceBlock,
+                                                  unsigned int arrayIndex)
+{
+    if (!interfaceBlock.hasInstanceName())
+    {
+        return "";
+    }
+    else if (interfaceBlock.isArray())
+    {
+        return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
+    }
+    else
+    {
+        return Decorate(interfaceBlock.instanceName());
+    }
+}
+
+TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock,
+                                                 TLayoutBlockStorage blockStorage)
+{
+    TString hlsl;
+
+    Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper();
+
+    for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
+    {
+        const TField &field    = *interfaceBlock.fields()[typeIndex];
+        const TType &fieldType = *field.type();
+
+        if (blockStorage == EbsStd140)
+        {
+            // 2 and 3 component vector types in some cases need pre-padding
+            hlsl += padHelper.prePaddingString(fieldType);
+        }
+
+        hlsl += "    " + InterfaceBlockFieldTypeString(field, blockStorage) + " " +
+                Decorate(field.name()) + ArrayString(fieldType) + ";\n";
+
+        // must pad out after matrices and arrays, where HLSL usually allows itself room to pack
+        // stuff
+        if (blockStorage == EbsStd140)
+        {
+            const bool useHLSLRowMajorPacking =
+                (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
+            hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
+        }
+    }
+
+    return hlsl;
+}
+
+TString UniformHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
+{
+    const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
+
+    return "struct " + InterfaceBlockStructName(interfaceBlock) +
+           "\n"
+           "{\n" +
+           interfaceBlockMembersString(interfaceBlock, blockStorage) + "};\n\n";
+}
+}
diff --git a/src/third_party/angle/src/compiler/translator/UniformHLSL.h b/src/third_party/angle/src/compiler/translator/UniformHLSL.h
new file mode 100644
index 0000000..7bbf41b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UniformHLSL.h
@@ -0,0 +1,97 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// UniformHLSL.h:
+//   Methods for GLSL to HLSL translation for uniforms and interface blocks.
+//
+
+#ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_
+#define COMPILER_TRANSLATOR_UNIFORMHLSL_H_
+
+#include "compiler/translator/OutputHLSL.h"
+#include "compiler/translator/UtilsHLSL.h"
+
+namespace sh
+{
+class StructureHLSL;
+
+class UniformHLSL : angle::NonCopyable
+{
+  public:
+    UniformHLSL(StructureHLSL *structureHLSL,
+                ShShaderOutput outputType,
+                const std::vector<Uniform> &uniforms);
+
+    void reserveUniformRegisters(unsigned int registerCount);
+    void reserveInterfaceBlockRegisters(unsigned int registerCount);
+    void uniformsHeader(TInfoSinkBase &out,
+                        ShShaderOutput outputType,
+                        const ReferencedSymbols &referencedUniforms);
+
+    // Must be called after uniformsHeader
+    void samplerMetadataUniforms(TInfoSinkBase &out, const char *reg);
+
+    TString interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks);
+
+    // Used for direct index references
+    static TString interfaceBlockInstanceString(const TInterfaceBlock &interfaceBlock,
+                                                unsigned int arrayIndex);
+
+    const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const
+    {
+        return mInterfaceBlockRegisterMap;
+    }
+    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;
+
+    void outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
+                                    const TType &type,
+                                    const TName &name,
+                                    const unsigned int registerIndex);
+
+    void outputUniform(TInfoSinkBase &out,
+                       const TType &type,
+                       const TName &name,
+                       const unsigned int registerIndex);
+
+    // Returns the uniform's register index
+    unsigned int assignUniformRegister(const TType &type,
+                                       const TString &name,
+                                       unsigned int *outRegisterCount);
+    unsigned int assignSamplerInStructUniformRegister(const TType &type,
+                                                      const TString &name,
+                                                      unsigned int *outRegisterCount);
+
+    void outputHLSLSamplerUniformGroup(
+        TInfoSinkBase &out,
+        const HLSLTextureSamplerGroup textureGroup,
+        const TVector<const TIntermSymbol *> &group,
+        const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames,
+        unsigned int *groupTextureRegisterIndex);
+
+    unsigned int mUniformRegister;
+    unsigned int mInterfaceBlockRegister;
+    unsigned int mSamplerRegister;
+    StructureHLSL *mStructureHLSL;
+    ShShaderOutput mOutputType;
+
+    const std::vector<Uniform> &mUniforms;
+    std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
+    std::map<std::string, unsigned int> mUniformRegisterMap;
+};
+}
+
+#endif  // COMPILER_TRANSLATOR_UNIFORMHLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/UseInterfaceBlockFields.cpp b/src/third_party/angle/src/compiler/translator/UseInterfaceBlockFields.cpp
new file mode 100644
index 0000000..0819cab
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UseInterfaceBlockFields.cpp
@@ -0,0 +1,130 @@
+//
+// Copyright 2016 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.
+//
+
+// UseInterfaceBlockFields.cpp: insert statements to reference all members in InterfaceBlock list at
+// the beginning of main. This is to work around a Mac driver that treats unused standard/shared
+// uniform blocks as inactive.
+
+#include "compiler/translator/UseInterfaceBlockFields.h"
+
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void AddFieldUseStatements(const ShaderVariable &var,
+                           TIntermSequence *sequence,
+                           const TSymbolTable &symbolTable)
+{
+    TString name = TString(var.name.c_str());
+    if (var.isArray())
+    {
+        size_t pos = name.find_last_of('[');
+        if (pos != TString::npos)
+        {
+            name = name.substr(0, pos);
+        }
+    }
+    const TType *type;
+    TType basicType;
+    if (var.isStruct())
+    {
+        TVariable *structInfo = reinterpret_cast<TVariable *>(symbolTable.findGlobal(name));
+        ASSERT(structInfo);
+        const TType &structType = structInfo->getType();
+        type                    = &structType;
+    }
+    else
+    {
+        basicType = sh::GetShaderVariableBasicType(var);
+        type      = &basicType;
+    }
+    ASSERT(type);
+
+    TIntermSymbol *symbol = new TIntermSymbol(0, name, *type);
+    if (var.isArray())
+    {
+        for (unsigned int i = 0; i < var.arraySize; ++i)
+        {
+            TIntermBinary *element =
+                new TIntermBinary(EOpIndexDirect, symbol, TIntermTyped::CreateIndexNode(i));
+            sequence->insert(sequence->begin(), element);
+        }
+    }
+    else
+    {
+        sequence->insert(sequence->begin(), symbol);
+    }
+}
+
+void InsertUseCode(TIntermSequence *sequence,
+                   const InterfaceBlockList &blocks,
+                   const TSymbolTable &symbolTable)
+{
+    for (const auto &block : blocks)
+    {
+        if (block.instanceName.empty())
+        {
+            for (const auto &var : block.fields)
+            {
+                AddFieldUseStatements(var, sequence, symbolTable);
+            }
+        }
+        else if (block.arraySize > 0)
+        {
+            TString name      = TString(block.instanceName.c_str());
+            TVariable *ubInfo = reinterpret_cast<TVariable *>(symbolTable.findGlobal(name));
+            ASSERT(ubInfo);
+            TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, ubInfo->getType());
+            for (unsigned int i = 0; i < block.arraySize; ++i)
+            {
+                TIntermBinary *instanceSymbol = new TIntermBinary(EOpIndexDirect, arraySymbol,
+                                                                  TIntermTyped::CreateIndexNode(i));
+                for (unsigned int j = 0; j < block.fields.size(); ++j)
+                {
+                    TIntermBinary *element =
+                        new TIntermBinary(EOpIndexDirectInterfaceBlock, instanceSymbol,
+                                          TIntermTyped::CreateIndexNode(j));
+                    sequence->insert(sequence->begin(), element);
+                }
+            }
+        }
+        else
+        {
+            TString name      = TString(block.instanceName.c_str());
+            TVariable *ubInfo = reinterpret_cast<TVariable *>(symbolTable.findGlobal(name));
+            ASSERT(ubInfo);
+            TIntermSymbol *blockSymbol = new TIntermSymbol(0, name, ubInfo->getType());
+            for (unsigned int i = 0; i < block.fields.size(); ++i)
+            {
+                TIntermBinary *element = new TIntermBinary(
+                    EOpIndexDirectInterfaceBlock, blockSymbol, TIntermTyped::CreateIndexNode(i));
+
+                sequence->insert(sequence->begin(), element);
+            }
+        }
+    }
+}
+
+}  // namespace anonymous
+
+void UseInterfaceBlockFields(TIntermBlock *root,
+                             const InterfaceBlockList &blocks,
+                             const TSymbolTable &symbolTable)
+{
+    TIntermFunctionDefinition *main = FindMain(root);
+    TIntermBlock *mainBody          = main->getBody();
+    ASSERT(mainBody);
+    InsertUseCode(mainBody->getSequence(), blocks, symbolTable);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/UseInterfaceBlockFields.h b/src/third_party/angle/src/compiler/translator/UseInterfaceBlockFields.h
new file mode 100644
index 0000000..3e2a481
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UseInterfaceBlockFields.h
@@ -0,0 +1,30 @@
+//
+// Copyright 2016 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.
+//
+
+// UseInterfaceBlockFields.h: insert statements to reference all members in InterfaceBlock list at
+// the beginning of main. This is to work around a Mac driver that treats unused standard/shared
+// uniform blocks as inactive.
+
+#ifndef COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_
+#define COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_
+
+#include <GLSLANG/ShaderLang.h>
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+using InterfaceBlockList = std::vector<sh::InterfaceBlock>;
+
+void UseInterfaceBlockFields(TIntermBlock *root,
+                             const InterfaceBlockList &blocks,
+                             const TSymbolTable &symbolTable);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_
diff --git a/src/third_party/angle/src/compiler/translator/UtilsHLSL.cpp b/src/third_party/angle/src/compiler/translator/UtilsHLSL.cpp
new file mode 100644
index 0000000..accb3b5
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UtilsHLSL.cpp
@@ -0,0 +1,454 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// UtilsHLSL.cpp:
+//   Utility methods for GLSL to HLSL translation.
+//
+
+#include "compiler/translator/UtilsHLSL.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/StructureHLSL.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+TString SamplerString(const TBasicType type)
+{
+    if (IsShadowSampler(type))
+    {
+        return "SamplerComparisonState";
+    }
+    else
+    {
+        return "SamplerState";
+    }
+}
+
+TString SamplerString(HLSLTextureSamplerGroup type)
+{
+    if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END)
+    {
+        return "SamplerComparisonState";
+    }
+    else
+    {
+        return "SamplerState";
+    }
+}
+
+HLSLTextureSamplerGroup TextureGroup(const TBasicType type)
+{
+    switch (type)
+    {
+        case EbtSampler2D:
+            return HLSL_TEXTURE_2D;
+        case EbtSamplerCube:
+            return HLSL_TEXTURE_CUBE;
+        case EbtSamplerExternalOES:
+            return HLSL_TEXTURE_2D;
+        case EbtSampler2DArray:
+            return HLSL_TEXTURE_2D_ARRAY;
+        case EbtSampler3D:
+            return HLSL_TEXTURE_3D;
+        case EbtSampler2DMS:
+            return HLSL_TEXTURE_2D_MS;
+        case EbtISampler2D:
+            return HLSL_TEXTURE_2D_INT4;
+        case EbtISampler3D:
+            return HLSL_TEXTURE_3D_INT4;
+        case EbtISamplerCube:
+            return HLSL_TEXTURE_2D_ARRAY_INT4;
+        case EbtISampler2DArray:
+            return HLSL_TEXTURE_2D_ARRAY_INT4;
+        case EbtISampler2DMS:
+            return HLSL_TEXTURE_2D_MS_INT4;
+        case EbtUSampler2D:
+            return HLSL_TEXTURE_2D_UINT4;
+        case EbtUSampler3D:
+            return HLSL_TEXTURE_3D_UINT4;
+        case EbtUSamplerCube:
+            return HLSL_TEXTURE_2D_ARRAY_UINT4;
+        case EbtUSampler2DArray:
+            return HLSL_TEXTURE_2D_ARRAY_UINT4;
+        case EbtUSampler2DMS:
+            return HLSL_TEXTURE_2D_MS_UINT4;
+        case EbtSampler2DShadow:
+            return HLSL_TEXTURE_2D_COMPARISON;
+        case EbtSamplerCubeShadow:
+            return HLSL_TEXTURE_CUBE_COMPARISON;
+        case EbtSampler2DArrayShadow:
+            return HLSL_TEXTURE_2D_ARRAY_COMPARISON;
+        default:
+            UNREACHABLE();
+    }
+    return HLSL_TEXTURE_UNKNOWN;
+}
+
+TString TextureString(const HLSLTextureSamplerGroup type)
+{
+    switch (type)
+    {
+        case HLSL_TEXTURE_2D:
+            return "Texture2D";
+        case HLSL_TEXTURE_CUBE:
+            return "TextureCube";
+        case HLSL_TEXTURE_2D_ARRAY:
+            return "Texture2DArray";
+        case HLSL_TEXTURE_3D:
+            return "Texture3D";
+        case HLSL_TEXTURE_2D_MS:
+            return "Texture2DMS<float4>";
+        case HLSL_TEXTURE_2D_INT4:
+            return "Texture2D<int4>";
+        case HLSL_TEXTURE_3D_INT4:
+            return "Texture3D<int4>";
+        case HLSL_TEXTURE_2D_ARRAY_INT4:
+            return "Texture2DArray<int4>";
+        case HLSL_TEXTURE_2D_MS_INT4:
+            return "Texture2DMS<int4>";
+        case HLSL_TEXTURE_2D_UINT4:
+            return "Texture2D<uint4>";
+        case HLSL_TEXTURE_3D_UINT4:
+            return "Texture3D<uint4>";
+        case HLSL_TEXTURE_2D_ARRAY_UINT4:
+            return "Texture2DArray<uint4>";
+        case HLSL_TEXTURE_2D_MS_UINT4:
+            return "Texture2DMS<uint4>";
+        case HLSL_TEXTURE_2D_COMPARISON:
+            return "Texture2D";
+        case HLSL_TEXTURE_CUBE_COMPARISON:
+            return "TextureCube";
+        case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
+            return "Texture2DArray";
+        default:
+            UNREACHABLE();
+    }
+
+    return "<unknown texture type>";
+}
+
+TString TextureString(const TBasicType type)
+{
+    return TextureString(TextureGroup(type));
+}
+
+TString TextureGroupSuffix(const HLSLTextureSamplerGroup type)
+{
+    switch (type)
+    {
+        case HLSL_TEXTURE_2D:
+            return "2D";
+        case HLSL_TEXTURE_CUBE:
+            return "Cube";
+        case HLSL_TEXTURE_2D_ARRAY:
+            return "2DArray";
+        case HLSL_TEXTURE_3D:
+            return "3D";
+        case HLSL_TEXTURE_2D_MS:
+            return "2DMS";
+        case HLSL_TEXTURE_2D_INT4:
+            return "2D_int4_";
+        case HLSL_TEXTURE_3D_INT4:
+            return "3D_int4_";
+        case HLSL_TEXTURE_2D_ARRAY_INT4:
+            return "2DArray_int4_";
+        case HLSL_TEXTURE_2D_MS_INT4:
+            return "2DMS_int4_";
+        case HLSL_TEXTURE_2D_UINT4:
+            return "2D_uint4_";
+        case HLSL_TEXTURE_3D_UINT4:
+            return "3D_uint4_";
+        case HLSL_TEXTURE_2D_ARRAY_UINT4:
+            return "2DArray_uint4_";
+        case HLSL_TEXTURE_2D_MS_UINT4:
+            return "2DMS_uint4_";
+        case HLSL_TEXTURE_2D_COMPARISON:
+            return "2D_comparison";
+        case HLSL_TEXTURE_CUBE_COMPARISON:
+            return "Cube_comparison";
+        case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
+            return "2DArray_comparison";
+        default:
+            UNREACHABLE();
+    }
+
+    return "<unknown texture type>";
+}
+
+TString TextureGroupSuffix(const TBasicType type)
+{
+    return TextureGroupSuffix(TextureGroup(type));
+}
+
+TString TextureTypeSuffix(const TBasicType type)
+{
+    switch (type)
+    {
+        case EbtISamplerCube:
+            return "Cube_int4_";
+        case EbtUSamplerCube:
+            return "Cube_uint4_";
+        case EbtSamplerExternalOES:
+            return "_External";
+        default:
+            // All other types are identified by their group suffix
+            return TextureGroupSuffix(type);
+    }
+}
+
+TString DecorateUniform(const TName &name, const TType &type)
+{
+    return DecorateIfNeeded(name);
+}
+
+TString DecorateField(const TString &string, const TStructure &structure)
+{
+    if (structure.name().compare(0, 3, "gl_") != 0)
+    {
+        return Decorate(string);
+    }
+
+    return string;
+}
+
+TString DecoratePrivate(const TString &privateText)
+{
+    return "dx_" + privateText;
+}
+
+TString Decorate(const TString &string)
+{
+    if (string.compare(0, 3, "gl_") != 0)
+    {
+        return "_" + string;
+    }
+
+    return string;
+}
+
+TString DecorateIfNeeded(const TName &name)
+{
+    if (name.isInternal())
+    {
+        return name.getString();
+    }
+    else
+    {
+        return Decorate(name.getString());
+    }
+}
+
+TString TypeString(const TType &type)
+{
+    const TStructure *structure = type.getStruct();
+    if (structure)
+    {
+        const TString &typeName = structure->name();
+        if (typeName != "")
+        {
+            return StructNameString(*structure);
+        }
+        else  // Nameless structure, define in place
+        {
+            return StructureHLSL::defineNameless(*structure);
+        }
+    }
+    else if (type.isMatrix())
+    {
+        int cols = type.getCols();
+        int rows = type.getRows();
+        return "float" + str(cols) + "x" + str(rows);
+    }
+    else
+    {
+        switch (type.getBasicType())
+        {
+            case EbtFloat:
+                switch (type.getNominalSize())
+                {
+                    case 1:
+                        return "float";
+                    case 2:
+                        return "float2";
+                    case 3:
+                        return "float3";
+                    case 4:
+                        return "float4";
+                }
+            case EbtInt:
+                switch (type.getNominalSize())
+                {
+                    case 1:
+                        return "int";
+                    case 2:
+                        return "int2";
+                    case 3:
+                        return "int3";
+                    case 4:
+                        return "int4";
+                }
+            case EbtUInt:
+                switch (type.getNominalSize())
+                {
+                    case 1:
+                        return "uint";
+                    case 2:
+                        return "uint2";
+                    case 3:
+                        return "uint3";
+                    case 4:
+                        return "uint4";
+                }
+            case EbtBool:
+                switch (type.getNominalSize())
+                {
+                    case 1:
+                        return "bool";
+                    case 2:
+                        return "bool2";
+                    case 3:
+                        return "bool3";
+                    case 4:
+                        return "bool4";
+                }
+            case EbtVoid:
+                return "void";
+            case EbtSampler2D:
+            case EbtISampler2D:
+            case EbtUSampler2D:
+            case EbtSampler2DArray:
+            case EbtISampler2DArray:
+            case EbtUSampler2DArray:
+                return "sampler2D";
+            case EbtSamplerCube:
+            case EbtISamplerCube:
+            case EbtUSamplerCube:
+                return "samplerCUBE";
+            case EbtSamplerExternalOES:
+                return "sampler2D";
+            default:
+                break;
+        }
+    }
+
+    UNREACHABLE();
+    return "<unknown type>";
+}
+
+TString StructNameString(const TStructure &structure)
+{
+    if (structure.name().empty())
+    {
+        return "";
+    }
+
+    // For structures at global scope we use a consistent
+    // translation so that we can link between shader stages.
+    if (structure.atGlobalScope())
+    {
+        return Decorate(structure.name());
+    }
+
+    return "ss" + str(structure.uniqueId()) + "_" + structure.name();
+}
+
+TString QualifiedStructNameString(const TStructure &structure,
+                                  bool useHLSLRowMajorPacking,
+                                  bool useStd140Packing)
+{
+    if (structure.name() == "")
+    {
+        return "";
+    }
+
+    TString prefix = "";
+
+    // Structs packed with row-major matrices in HLSL are prefixed with "rm"
+    // GLSL column-major maps to HLSL row-major, and the converse is true
+
+    if (useStd140Packing)
+    {
+        prefix += "std_";
+    }
+
+    if (useHLSLRowMajorPacking)
+    {
+        prefix += "rm_";
+    }
+
+    return prefix + StructNameString(structure);
+}
+
+TString InterpolationString(TQualifier qualifier)
+{
+    switch (qualifier)
+    {
+        case EvqVaryingIn:
+            return "";
+        case EvqFragmentIn:
+            return "";
+        case EvqSmoothIn:
+            return "linear";
+        case EvqFlatIn:
+            return "nointerpolation";
+        case EvqCentroidIn:
+            return "centroid";
+        case EvqVaryingOut:
+            return "";
+        case EvqVertexOut:
+            return "";
+        case EvqSmoothOut:
+            return "linear";
+        case EvqFlatOut:
+            return "nointerpolation";
+        case EvqCentroidOut:
+            return "centroid";
+        default:
+            UNREACHABLE();
+    }
+
+    return "";
+}
+
+TString QualifierString(TQualifier qualifier)
+{
+    switch (qualifier)
+    {
+        case EvqIn:
+            return "in";
+        case EvqOut:
+            return "inout";  // 'out' results in an HLSL error if not all fields are written, for
+                             // GLSL it's undefined
+        case EvqInOut:
+            return "inout";
+        case EvqConstReadOnly:
+            return "const";
+        default:
+            UNREACHABLE();
+    }
+
+    return "";
+}
+
+TString DisambiguateFunctionName(const TIntermSequence *parameters)
+{
+    TString disambiguatingString;
+    for (auto parameter : *parameters)
+    {
+        const TType &paramType = parameter->getAsTyped()->getType();
+        // Disambiguation is needed for float2x2 and float4 parameters. These are the only parameter
+        // types that HLSL thinks are identical. float2x3 and float3x2 are different types, for
+        // example. Other parameter types are not added to function names to avoid making function
+        // names longer.
+        if (paramType.getObjectSize() == 4 && paramType.getBasicType() == EbtFloat)
+        {
+            disambiguatingString += "_" + TypeString(paramType);
+        }
+    }
+    return disambiguatingString;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/UtilsHLSL.h b/src/third_party/angle/src/compiler/translator/UtilsHLSL.h
new file mode 100644
index 0000000..37edce4
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/UtilsHLSL.h
@@ -0,0 +1,83 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// UtilsHLSL.h:
+//   Utility methods for GLSL to HLSL translation.
+//
+
+#ifndef COMPILER_TRANSLATOR_UTILSHLSL_H_
+#define COMPILER_TRANSLATOR_UTILSHLSL_H_
+
+#include <vector>
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/Types.h"
+
+#include "angle_gl.h"
+
+class TName;
+
+namespace sh
+{
+
+// Unique combinations of HLSL Texture type and HLSL Sampler type.
+enum HLSLTextureSamplerGroup
+{
+    // Regular samplers
+    HLSL_TEXTURE_2D,
+    HLSL_TEXTURE_MIN = HLSL_TEXTURE_2D,
+
+    HLSL_TEXTURE_CUBE,
+    HLSL_TEXTURE_2D_ARRAY,
+    HLSL_TEXTURE_3D,
+    HLSL_TEXTURE_2D_MS,
+    HLSL_TEXTURE_2D_INT4,
+    HLSL_TEXTURE_3D_INT4,
+    HLSL_TEXTURE_2D_ARRAY_INT4,
+    HLSL_TEXTURE_2D_MS_INT4,
+    HLSL_TEXTURE_2D_UINT4,
+    HLSL_TEXTURE_3D_UINT4,
+    HLSL_TEXTURE_2D_ARRAY_UINT4,
+    HLSL_TEXTURE_2D_MS_UINT4,
+
+    // Comparison samplers
+
+    HLSL_TEXTURE_2D_COMPARISON,
+    HLSL_TEXTURE_CUBE_COMPARISON,
+    HLSL_TEXTURE_2D_ARRAY_COMPARISON,
+
+    HLSL_COMPARISON_SAMPLER_GROUP_BEGIN = HLSL_TEXTURE_2D_COMPARISON,
+    HLSL_COMPARISON_SAMPLER_GROUP_END   = HLSL_TEXTURE_2D_ARRAY_COMPARISON,
+
+    HLSL_TEXTURE_UNKNOWN,
+    HLSL_TEXTURE_MAX = HLSL_TEXTURE_UNKNOWN
+};
+
+HLSLTextureSamplerGroup TextureGroup(const TBasicType type);
+TString TextureString(const HLSLTextureSamplerGroup type);
+TString TextureString(const TBasicType type);
+TString TextureGroupSuffix(const HLSLTextureSamplerGroup type);
+TString TextureGroupSuffix(const TBasicType type);
+TString TextureTypeSuffix(const TBasicType type);
+TString SamplerString(const TBasicType type);
+TString SamplerString(HLSLTextureSamplerGroup type);
+// Prepends an underscore to avoid naming clashes
+TString Decorate(const TString &string);
+TString DecorateIfNeeded(const TName &name);
+TString DecorateUniform(const TName &name, const TType &type);
+TString DecorateField(const TString &string, const TStructure &structure);
+TString DecoratePrivate(const TString &privateText);
+TString TypeString(const TType &type);
+TString StructNameString(const TStructure &structure);
+TString QualifiedStructNameString(const TStructure &structure,
+                                  bool useHLSLRowMajorPacking,
+                                  bool useStd140Packing);
+TString InterpolationString(TQualifier qualifier);
+TString QualifierString(TQualifier qualifier);
+// Parameters may need to be included in function names to disambiguate between overloaded
+// functions.
+TString DisambiguateFunctionName(const TIntermSequence *parameters);
+}
+
+#endif  // COMPILER_TRANSLATOR_UTILSHLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/ValidateGlobalInitializer.cpp b/src/third_party/angle/src/compiler/translator/ValidateGlobalInitializer.cpp
new file mode 100644
index 0000000..10a3e51
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateGlobalInitializer.cpp
@@ -0,0 +1,119 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ValidateGlobalInitializer.h"
+
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class ValidateGlobalInitializerTraverser : public TIntermTraverser
+{
+  public:
+    ValidateGlobalInitializerTraverser(const TParseContext *context);
+
+    void visitSymbol(TIntermSymbol *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+    bool visitUnary(Visit visit, TIntermUnary *node) override;
+
+    bool isValid() const { return mIsValid; }
+    bool issueWarning() const { return mIssueWarning; }
+
+  private:
+    const TParseContext *mContext;
+    bool mIsValid;
+    bool mIssueWarning;
+};
+
+void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
+{
+    const TSymbol *sym =
+        mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion());
+    if (sym->isVariable())
+    {
+        // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3):
+        // Global initializers must be constant expressions.
+        const TVariable *var = static_cast<const TVariable *>(sym);
+        switch (var->getType().getQualifier())
+        {
+            case EvqConst:
+                break;
+            case EvqGlobal:
+            case EvqTemporary:
+            case EvqUniform:
+                // We allow these cases to be compatible with legacy ESSL 1.00 content.
+                // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal
+                // with.
+                if (mContext->getShaderVersion() >= 300)
+                {
+                    mIsValid = false;
+                }
+                else
+                {
+                    mIssueWarning = true;
+                }
+                break;
+            default:
+                mIsValid = false;
+        }
+    }
+}
+
+bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    // Disallow calls to user-defined functions and texture lookup functions in global variable
+    // initializers.
+    // This is done simply by disabling all function calls - built-in math functions don't use
+    // the function call ops.
+    if (node->isFunctionCall())
+    {
+        mIsValid = false;
+    }
+    return true;
+}
+
+bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+    if (node->isAssignment())
+    {
+        mIsValid = false;
+    }
+    return true;
+}
+
+bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+    if (node->isAssignment())
+    {
+        mIsValid = false;
+    }
+    return true;
+}
+
+ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context)
+    : TIntermTraverser(true, false, false), mContext(context), mIsValid(true), mIssueWarning(false)
+{
+}
+
+}  // namespace
+
+bool ValidateGlobalInitializer(TIntermTyped *initializer,
+                               const TParseContext *context,
+                               bool *warning)
+{
+    ValidateGlobalInitializerTraverser validate(context);
+    initializer->traverse(&validate);
+    ASSERT(warning != nullptr);
+    *warning = validate.issueWarning();
+    return validate.isValid();
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ValidateGlobalInitializer.h b/src/third_party/angle/src/compiler/translator/ValidateGlobalInitializer.h
new file mode 100644
index 0000000..2e75706
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateGlobalInitializer.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
+#define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
+
+namespace sh
+{
+
+class TIntermTyped;
+class TParseContext;
+
+// Returns true if the initializer is valid.
+bool ValidateGlobalInitializer(TIntermTyped *initializer,
+                               const TParseContext *context,
+                               bool *warning);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
diff --git a/src/third_party/angle/src/compiler/translator/ValidateLimitations.cpp b/src/third_party/angle/src/compiler/translator/ValidateLimitations.cpp
new file mode 100644
index 0000000..a59b1bb
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateLimitations.cpp
@@ -0,0 +1,443 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ValidateLimitations.h"
+
+#include "angle_gl.h"
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
+
+namespace
+{
+
+int GetLoopSymbolId(TIntermLoop *loop)
+{
+    // Here we assume all the operations are valid, because the loop node is
+    // already validated before this call.
+    TIntermSequence *declSeq = loop->getInit()->getAsDeclarationNode()->getSequence();
+    TIntermBinary *declInit  = (*declSeq)[0]->getAsBinaryNode();
+    TIntermSymbol *symbol    = declInit->getLeft()->getAsSymbolNode();
+
+    return symbol->getId();
+}
+
+// Traverses a node to check if it represents a constant index expression.
+// Definition:
+// constant-index-expressions are a superset of constant-expressions.
+// Constant-index-expressions can include loop indices as defined in
+// GLSL ES 1.0 spec, Appendix A, section 4.
+// The following are constant-index-expressions:
+// - Constant expressions
+// - Loop indices as defined in section 4
+// - Expressions composed of both of the above
+class ValidateConstIndexExpr : public TIntermTraverser
+{
+  public:
+    ValidateConstIndexExpr(const std::vector<int> &loopSymbols)
+        : TIntermTraverser(true, false, false), mValid(true), mLoopSymbolIds(loopSymbols)
+    {
+    }
+
+    // Returns true if the parsed node represents a constant index expression.
+    bool isValid() const { return mValid; }
+
+    void visitSymbol(TIntermSymbol *symbol) override
+    {
+        // Only constants and loop indices are allowed in a
+        // constant index expression.
+        if (mValid)
+        {
+            bool isLoopSymbol = std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(),
+                                          symbol->getId()) != mLoopSymbolIds.end();
+            mValid = (symbol->getQualifier() == EvqConst) || isLoopSymbol;
+        }
+    }
+
+  private:
+    bool mValid;
+    const std::vector<int> mLoopSymbolIds;
+};
+
+// Traverses intermediate tree to ensure that the shader does not exceed the
+// minimum functionality mandated in GLSL 1.0 spec, Appendix A.
+class ValidateLimitationsTraverser : public TLValueTrackingTraverser
+{
+  public:
+    ValidateLimitationsTraverser(sh::GLenum shaderType,
+                                 const TSymbolTable &symbolTable,
+                                 int shaderVersion,
+                                 TDiagnostics *diagnostics);
+
+    void visitSymbol(TIntermSymbol *node) override;
+    bool visitBinary(Visit, TIntermBinary *) override;
+    bool visitLoop(Visit, TIntermLoop *) override;
+
+  private:
+    void error(TSourceLoc loc, const char *reason, const char *token);
+
+    bool withinLoopBody() const;
+    bool isLoopIndex(TIntermSymbol *symbol);
+    bool validateLoopType(TIntermLoop *node);
+
+    bool validateForLoopHeader(TIntermLoop *node);
+    // If valid, return the index symbol id; Otherwise, return -1.
+    int validateForLoopInit(TIntermLoop *node);
+    bool validateForLoopCond(TIntermLoop *node, int indexSymbolId);
+    bool validateForLoopExpr(TIntermLoop *node, int indexSymbolId);
+
+    // Returns true if indexing does not exceed the minimum functionality
+    // mandated in GLSL 1.0 spec, Appendix A, Section 5.
+    bool isConstExpr(TIntermNode *node);
+    bool isConstIndexExpr(TIntermNode *node);
+    bool validateIndexing(TIntermBinary *node);
+
+    sh::GLenum mShaderType;
+    TDiagnostics *mDiagnostics;
+    std::vector<int> mLoopSymbolIds;
+};
+
+ValidateLimitationsTraverser::ValidateLimitationsTraverser(sh::GLenum shaderType,
+                                                           const TSymbolTable &symbolTable,
+                                                           int shaderVersion,
+                                                           TDiagnostics *diagnostics)
+    : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
+      mShaderType(shaderType),
+      mDiagnostics(diagnostics)
+{
+    ASSERT(diagnostics);
+}
+
+void ValidateLimitationsTraverser::visitSymbol(TIntermSymbol *node)
+{
+    if (isLoopIndex(node) && isLValueRequiredHere())
+    {
+        error(node->getLine(),
+              "Loop index cannot be statically assigned to within the body of the loop",
+              node->getSymbol().c_str());
+    }
+}
+
+bool ValidateLimitationsTraverser::visitBinary(Visit, TIntermBinary *node)
+{
+    // Check indexing.
+    switch (node->getOp())
+    {
+        case EOpIndexDirect:
+        case EOpIndexIndirect:
+            validateIndexing(node);
+            break;
+        default:
+            break;
+    }
+    return true;
+}
+
+bool ValidateLimitationsTraverser::visitLoop(Visit, TIntermLoop *node)
+{
+    if (!validateLoopType(node))
+        return false;
+
+    if (!validateForLoopHeader(node))
+        return false;
+
+    TIntermNode *body = node->getBody();
+    if (body != nullptr)
+    {
+        mLoopSymbolIds.push_back(GetLoopSymbolId(node));
+        body->traverse(this);
+        mLoopSymbolIds.pop_back();
+    }
+
+    // The loop is fully processed - no need to visit children.
+    return false;
+}
+
+void ValidateLimitationsTraverser::error(TSourceLoc loc, const char *reason, const char *token)
+{
+    mDiagnostics->error(loc, reason, token);
+}
+
+bool ValidateLimitationsTraverser::withinLoopBody() const
+{
+    return !mLoopSymbolIds.empty();
+}
+
+bool ValidateLimitationsTraverser::isLoopIndex(TIntermSymbol *symbol)
+{
+    return std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), symbol->getId()) !=
+           mLoopSymbolIds.end();
+}
+
+bool ValidateLimitationsTraverser::validateLoopType(TIntermLoop *node)
+{
+    TLoopType type = node->getType();
+    if (type == ELoopFor)
+        return true;
+
+    // Reject while and do-while loops.
+    error(node->getLine(), "This type of loop is not allowed", type == ELoopWhile ? "while" : "do");
+    return false;
+}
+
+bool ValidateLimitationsTraverser::validateForLoopHeader(TIntermLoop *node)
+{
+    ASSERT(node->getType() == ELoopFor);
+
+    //
+    // The for statement has the form:
+    //    for ( init-declaration ; condition ; expression ) statement
+    //
+    int indexSymbolId = validateForLoopInit(node);
+    if (indexSymbolId < 0)
+        return false;
+    if (!validateForLoopCond(node, indexSymbolId))
+        return false;
+    if (!validateForLoopExpr(node, indexSymbolId))
+        return false;
+
+    return true;
+}
+
+int ValidateLimitationsTraverser::validateForLoopInit(TIntermLoop *node)
+{
+    TIntermNode *init = node->getInit();
+    if (init == nullptr)
+    {
+        error(node->getLine(), "Missing init declaration", "for");
+        return -1;
+    }
+
+    //
+    // init-declaration has the form:
+    //     type-specifier identifier = constant-expression
+    //
+    TIntermDeclaration *decl = init->getAsDeclarationNode();
+    if (decl == nullptr)
+    {
+        error(init->getLine(), "Invalid init declaration", "for");
+        return -1;
+    }
+    // To keep things simple do not allow declaration list.
+    TIntermSequence *declSeq = decl->getSequence();
+    if (declSeq->size() != 1)
+    {
+        error(decl->getLine(), "Invalid init declaration", "for");
+        return -1;
+    }
+    TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode();
+    if ((declInit == nullptr) || (declInit->getOp() != EOpInitialize))
+    {
+        error(decl->getLine(), "Invalid init declaration", "for");
+        return -1;
+    }
+    TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
+    if (symbol == nullptr)
+    {
+        error(declInit->getLine(), "Invalid init declaration", "for");
+        return -1;
+    }
+    // The loop index has type int or float.
+    TBasicType type = symbol->getBasicType();
+    if ((type != EbtInt) && (type != EbtUInt) && (type != EbtFloat))
+    {
+        error(symbol->getLine(), "Invalid type for loop index", getBasicString(type));
+        return -1;
+    }
+    // The loop index is initialized with constant expression.
+    if (!isConstExpr(declInit->getRight()))
+    {
+        error(declInit->getLine(), "Loop index cannot be initialized with non-constant expression",
+              symbol->getSymbol().c_str());
+        return -1;
+    }
+
+    return symbol->getId();
+}
+
+bool ValidateLimitationsTraverser::validateForLoopCond(TIntermLoop *node, int indexSymbolId)
+{
+    TIntermNode *cond = node->getCondition();
+    if (cond == nullptr)
+    {
+        error(node->getLine(), "Missing condition", "for");
+        return false;
+    }
+    //
+    // condition has the form:
+    //     loop_index relational_operator constant_expression
+    //
+    TIntermBinary *binOp = cond->getAsBinaryNode();
+    if (binOp == nullptr)
+    {
+        error(node->getLine(), "Invalid condition", "for");
+        return false;
+    }
+    // Loop index should be to the left of relational operator.
+    TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode();
+    if (symbol == nullptr)
+    {
+        error(binOp->getLine(), "Invalid condition", "for");
+        return false;
+    }
+    if (symbol->getId() != indexSymbolId)
+    {
+        error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str());
+        return false;
+    }
+    // Relational operator is one of: > >= < <= == or !=.
+    switch (binOp->getOp())
+    {
+        case EOpEqual:
+        case EOpNotEqual:
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            break;
+        default:
+            error(binOp->getLine(), "Invalid relational operator",
+                  GetOperatorString(binOp->getOp()));
+            break;
+    }
+    // Loop index must be compared with a constant.
+    if (!isConstExpr(binOp->getRight()))
+    {
+        error(binOp->getLine(), "Loop index cannot be compared with non-constant expression",
+              symbol->getSymbol().c_str());
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateLimitationsTraverser::validateForLoopExpr(TIntermLoop *node, int indexSymbolId)
+{
+    TIntermNode *expr = node->getExpression();
+    if (expr == nullptr)
+    {
+        error(node->getLine(), "Missing expression", "for");
+        return false;
+    }
+
+    // for expression has one of the following forms:
+    //     loop_index++
+    //     loop_index--
+    //     loop_index += constant_expression
+    //     loop_index -= constant_expression
+    //     ++loop_index
+    //     --loop_index
+    // The last two forms are not specified in the spec, but I am assuming
+    // its an oversight.
+    TIntermUnary *unOp   = expr->getAsUnaryNode();
+    TIntermBinary *binOp = unOp ? nullptr : expr->getAsBinaryNode();
+
+    TOperator op          = EOpNull;
+    TIntermSymbol *symbol = nullptr;
+    if (unOp != nullptr)
+    {
+        op     = unOp->getOp();
+        symbol = unOp->getOperand()->getAsSymbolNode();
+    }
+    else if (binOp != nullptr)
+    {
+        op     = binOp->getOp();
+        symbol = binOp->getLeft()->getAsSymbolNode();
+    }
+
+    // The operand must be loop index.
+    if (symbol == nullptr)
+    {
+        error(expr->getLine(), "Invalid expression", "for");
+        return false;
+    }
+    if (symbol->getId() != indexSymbolId)
+    {
+        error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str());
+        return false;
+    }
+
+    // The operator is one of: ++ -- += -=.
+    switch (op)
+    {
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+            ASSERT((unOp != nullptr) && (binOp == nullptr));
+            break;
+        case EOpAddAssign:
+        case EOpSubAssign:
+            ASSERT((unOp == nullptr) && (binOp != nullptr));
+            break;
+        default:
+            error(expr->getLine(), "Invalid operator", GetOperatorString(op));
+            return false;
+    }
+
+    // Loop index must be incremented/decremented with a constant.
+    if (binOp != nullptr)
+    {
+        if (!isConstExpr(binOp->getRight()))
+        {
+            error(binOp->getLine(), "Loop index cannot be modified by non-constant expression",
+                  symbol->getSymbol().c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateLimitationsTraverser::isConstExpr(TIntermNode *node)
+{
+    ASSERT(node != nullptr);
+    return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst;
+}
+
+bool ValidateLimitationsTraverser::isConstIndexExpr(TIntermNode *node)
+{
+    ASSERT(node != nullptr);
+
+    ValidateConstIndexExpr validate(mLoopSymbolIds);
+    node->traverse(&validate);
+    return validate.isValid();
+}
+
+bool ValidateLimitationsTraverser::validateIndexing(TIntermBinary *node)
+{
+    ASSERT((node->getOp() == EOpIndexDirect) || (node->getOp() == EOpIndexIndirect));
+
+    bool valid          = true;
+    TIntermTyped *index = node->getRight();
+    // The index expession must be a constant-index-expression unless
+    // the operand is a uniform in a vertex shader.
+    TIntermTyped *operand = node->getLeft();
+    bool skip = (mShaderType == GL_VERTEX_SHADER) && (operand->getQualifier() == EvqUniform);
+    if (!skip && !isConstIndexExpr(index))
+    {
+        error(index->getLine(), "Index expression must be constant", "[]");
+        valid = false;
+    }
+    return valid;
+}
+
+}  // namespace anonymous
+
+bool ValidateLimitations(TIntermNode *root,
+                         GLenum shaderType,
+                         const TSymbolTable &symbolTable,
+                         int shaderVersion,
+                         TDiagnostics *diagnostics)
+{
+    ValidateLimitationsTraverser validate(shaderType, symbolTable, shaderVersion, diagnostics);
+    root->traverse(&validate);
+    return diagnostics->numErrors() == 0;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ValidateLimitations.h b/src/third_party/angle/src/compiler/translator/ValidateLimitations.h
new file mode 100644
index 0000000..6947fde
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateLimitations.h
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
+#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+class TDiagnostics;
+
+// Returns true if the given shader does not exceed the minimum functionality mandated in GLSL ES
+// 1.00 spec Appendix A.
+bool ValidateLimitations(TIntermNode *root,
+                         GLenum shaderType,
+                         const TSymbolTable &symbolTable,
+                         int shaderVersion,
+                         TDiagnostics *diagnostics);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
diff --git a/src/third_party/angle/src/compiler/translator/ValidateMaxParameters.cpp b/src/third_party/angle/src/compiler/translator/ValidateMaxParameters.cpp
new file mode 100644
index 0000000..2d0b3eb
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateMaxParameters.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2016 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.
+//
+// ValidateMaxParameters checks if function definitions have more than a set number of parameters.
+
+#include "compiler/translator/ValidateMaxParameters.h"
+
+namespace sh
+{
+
+ValidateMaxParameters::ValidateMaxParameters(unsigned int maxParameters)
+    : TIntermTraverser(true, false, false), mMaxParameters(maxParameters), mValid(true)
+{
+}
+
+bool ValidateMaxParameters::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+{
+    if (!mValid)
+    {
+        return false;
+    }
+
+    if (node->getFunctionPrototype()->getSequence()->size() > mMaxParameters)
+    {
+        mValid = false;
+    }
+
+    return mValid;
+}
+
+bool ValidateMaxParameters::validate(TIntermNode *root, unsigned int maxParameters)
+{
+    ValidateMaxParameters argsTraverser(maxParameters);
+    root->traverse(&argsTraverser);
+    return argsTraverser.mValid;
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ValidateMaxParameters.h b/src/third_party/angle/src/compiler/translator/ValidateMaxParameters.h
new file mode 100644
index 0000000..7c73390
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateMaxParameters.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2016 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.
+//
+// ValidateMaxParameters checks if function definitions have more than a set number of parameters.
+
+#ifndef COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_
+#define COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+class ValidateMaxParameters : public TIntermTraverser
+{
+  public:
+    // Returns false if maxParameters is exceeded.
+    static bool validate(TIntermNode *root, unsigned int maxParameters);
+
+  protected:
+    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
+
+  private:
+    ValidateMaxParameters(unsigned int maxParameters);
+
+    unsigned int mMaxParameters;
+    bool mValid;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_
diff --git a/src/third_party/angle/src/compiler/translator/ValidateMultiviewWebGL.cpp b/src/third_party/angle/src/compiler/translator/ValidateMultiviewWebGL.cpp
new file mode 100644
index 0000000..169a32e
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateMultiviewWebGL.cpp
@@ -0,0 +1,414 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+// ValidateMultiviewWebGL.cpp:
+//   Validate the AST according to rules in the WEBGL_multiview extension spec. Only covers those
+//   rules not already covered in ParseContext.
+//
+
+#include "compiler/translator/ValidateMultiviewWebGL.h"
+
+#include <array>
+
+#include "angle_gl.h"
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/FindSymbolNode.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class ValidateMultiviewTraverser : public TIntermTraverser
+{
+  public:
+    // Check for errors and write error messages to diagnostics. Returns true if there are no
+    // errors.
+    static bool validate(TIntermBlock *root,
+                         GLenum shaderType,
+                         const TSymbolTable &symbolTable,
+                         int shaderVersion,
+                         bool multiview2,
+                         TDiagnostics *diagnostics);
+
+    bool isValid() { return mValid; }
+
+  protected:
+    void visitSymbol(TIntermSymbol *node) override;
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+    bool visitUnary(Visit visit, TIntermUnary *node) override;
+    bool visitIfElse(Visit visit, TIntermIfElse *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+
+  private:
+    ValidateMultiviewTraverser(GLenum shaderType,
+                               const TSymbolTable &symbolTable,
+                               int shaderVersion,
+                               bool multiview2,
+                               TDiagnostics *diagnostics);
+
+    static bool IsGLPosition(TIntermNode *node);
+    static bool IsGLViewIDOVR(TIntermNode *node);
+    static bool IsSimpleAssignmentToGLPositionX(TIntermBinary *node);
+    static bool IsSimpleAssignmentToGLPosition(TIntermBinary *node);
+
+    void validateAndTraverseViewIDConditionalBlock(TIntermBlock *block, const char *token);
+
+    bool mValid;
+    bool mMultiview2;
+    GLenum mShaderType;
+    const TSymbolTable &mSymbolTable;
+    const int mShaderVersion;
+
+    bool mInsideViewIDConditional;  // Only set if mMultiview2 is false.
+    bool mInsideRestrictedAssignment;
+    bool mGLPositionAllowed;
+    bool mViewIDOVRAllowed;
+
+    TDiagnostics *mDiagnostics;
+};
+
+bool ValidateMultiviewTraverser::validate(TIntermBlock *root,
+                                          GLenum shaderType,
+                                          const TSymbolTable &symbolTable,
+                                          int shaderVersion,
+                                          bool multiview2,
+                                          TDiagnostics *diagnostics)
+{
+    ValidateMultiviewTraverser validate(shaderType, symbolTable, shaderVersion, multiview2,
+                                        diagnostics);
+    ASSERT(root);
+    root->traverse(&validate);
+    return validate.isValid();
+}
+
+ValidateMultiviewTraverser::ValidateMultiviewTraverser(GLenum shaderType,
+                                                       const TSymbolTable &symbolTable,
+                                                       int shaderVersion,
+                                                       bool multiview2,
+                                                       TDiagnostics *diagnostics)
+    : TIntermTraverser(true, true, true),
+      mValid(true),
+      mMultiview2(multiview2),
+      mShaderType(shaderType),
+      mSymbolTable(symbolTable),
+      mShaderVersion(shaderVersion),
+      mInsideViewIDConditional(false),
+      mInsideRestrictedAssignment(false),
+      mGLPositionAllowed(multiview2),
+      mViewIDOVRAllowed(multiview2),
+      mDiagnostics(diagnostics)
+{
+}
+
+bool ValidateMultiviewTraverser::IsGLPosition(TIntermNode *node)
+{
+    TIntermSymbol *symbolNode = node->getAsSymbolNode();
+    return (symbolNode && symbolNode->getName().getString() == "gl_Position");
+}
+
+bool ValidateMultiviewTraverser::IsGLViewIDOVR(TIntermNode *node)
+{
+    TIntermSymbol *symbolNode = node->getAsSymbolNode();
+    return (symbolNode && symbolNode->getName().getString() == "gl_ViewID_OVR");
+}
+
+bool ValidateMultiviewTraverser::IsSimpleAssignmentToGLPositionX(TIntermBinary *node)
+{
+    if (node->getOp() == EOpAssign)
+    {
+        TIntermSwizzle *leftAsSwizzle = node->getLeft()->getAsSwizzleNode();
+        if (leftAsSwizzle && IsGLPosition(leftAsSwizzle->getOperand()) &&
+            leftAsSwizzle->offsetsMatch(0))
+        {
+            return true;
+        }
+        TIntermBinary *leftAsBinary = node->getLeft()->getAsBinaryNode();
+        if (leftAsBinary && leftAsBinary->getOp() == EOpIndexDirect &&
+            IsGLPosition(leftAsBinary->getLeft()) &&
+            leftAsBinary->getRight()->getAsConstantUnion()->getIConst(0) == 0)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool ValidateMultiviewTraverser::IsSimpleAssignmentToGLPosition(TIntermBinary *node)
+{
+    if (node->getOp() == EOpAssign)
+    {
+        if (IsGLPosition(node->getLeft()))
+        {
+            return true;
+        }
+        TIntermSwizzle *leftAsSwizzle = node->getLeft()->getAsSwizzleNode();
+        if (leftAsSwizzle && IsGLPosition(leftAsSwizzle->getOperand()))
+        {
+            return true;
+        }
+        TIntermBinary *leftAsBinary = node->getLeft()->getAsBinaryNode();
+        if (leftAsBinary && leftAsBinary->getOp() == EOpIndexDirect &&
+            IsGLPosition(leftAsBinary->getLeft()))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+void ValidateMultiviewTraverser::visitSymbol(TIntermSymbol *node)
+{
+    if (IsGLPosition(node) && !mGLPositionAllowed)
+    {
+        ASSERT(!mMultiview2);
+        mDiagnostics->error(node->getLine(),
+                            "Disallowed use of gl_Position when using OVR_multiview",
+                            "gl_Position");
+        mValid = false;
+    }
+    else if (IsGLViewIDOVR(node) && !mViewIDOVRAllowed)
+    {
+        ASSERT(!mMultiview2);
+        mDiagnostics->error(node->getLine(),
+                            "Disallowed use of gl_ViewID_OVR when using OVR_multiview",
+                            "gl_ViewID_OVR");
+        mValid = false;
+    }
+    else if (!mMultiview2 && mShaderType == GL_FRAGMENT_SHADER)
+    {
+        std::array<const char *, 3> disallowedFragmentShaderSymbols{
+            {"gl_FragCoord", "gl_PointCoord", "gl_FrontFacing"}};
+        for (auto disallowedSymbol : disallowedFragmentShaderSymbols)
+        {
+            if (node->getSymbol() == disallowedSymbol)
+            {
+                mDiagnostics->error(
+                    node->getLine(),
+                    "Disallowed use of a built-in variable when using OVR_multiview",
+                    disallowedSymbol);
+                mValid = false;
+            }
+        }
+    }
+}
+
+bool ValidateMultiviewTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+    if (!mMultiview2 && mShaderType == GL_VERTEX_SHADER)
+    {
+        if (visit == PreVisit)
+        {
+            ASSERT(!mInsideViewIDConditional || mInsideRestrictedAssignment);
+            if (node->isAssignment())
+            {
+                if (mInsideRestrictedAssignment)
+                {
+                    mDiagnostics->error(node->getLine(),
+                                        "Disallowed assignment inside assignment to gl_Position.x "
+                                        "when using OVR_multiview",
+                                        GetOperatorString(node->getOp()));
+                    mValid = false;
+                }
+                else if (IsSimpleAssignmentToGLPositionX(node) &&
+                         FindSymbolNode(node->getRight(), "gl_ViewID_OVR", EbtUInt))
+                {
+                    if (!getParentNode()->getAsBlock())
+                    {
+                        mDiagnostics->error(node->getLine(),
+                                            "Disallowed use of assignment to gl_Position.x "
+                                            "when using OVR_multiview",
+                                            "=");
+                        mValid = false;
+                    }
+                    mInsideRestrictedAssignment = true;
+                    mViewIDOVRAllowed           = true;
+                    node->getRight()->traverse(this);
+                    mInsideRestrictedAssignment = false;
+                    mViewIDOVRAllowed           = false;
+                    return false;
+                }
+                else if (IsSimpleAssignmentToGLPosition(node))
+                {
+                    node->getRight()->traverse(this);
+                    return false;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+bool ValidateMultiviewTraverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+    if (visit == PreVisit && !mMultiview2 && mInsideRestrictedAssignment)
+    {
+        if (node->isAssignment())
+        {
+            mDiagnostics->error(node->getLine(),
+                                "Disallowed unary operator inside assignment to gl_Position.x when "
+                                "using OVR_multiview",
+                                GetOperatorString(node->getOp()));
+            mValid = false;
+        }
+    }
+    return true;
+}
+
+void ValidateMultiviewTraverser::validateAndTraverseViewIDConditionalBlock(TIntermBlock *block,
+                                                                           const char *token)
+{
+    if (block->getSequence()->size() > 1)
+    {
+        mDiagnostics->error(block->getLine(),
+                            "Only one assignment to gl_Position allowed inside if block dependent "
+                            "on gl_ViewID_OVR when using OVR_multiview",
+                            token);
+        mValid = false;
+    }
+    else if (block->getSequence()->size() == 1)
+    {
+        TIntermBinary *assignment = block->getSequence()->at(0)->getAsBinaryNode();
+        if (assignment && IsSimpleAssignmentToGLPositionX(assignment))
+        {
+            mInsideRestrictedAssignment = true;
+            assignment->getRight()->traverse(this);
+            mInsideRestrictedAssignment = false;
+        }
+        else
+        {
+            mDiagnostics->error(block->getLine(),
+                                "Only one assignment to gl_Position.x allowed inside if block "
+                                "dependent on gl_ViewID_OVR when using OVR_multiview",
+                                token);
+            mValid = false;
+        }
+    }
+}
+
+bool ValidateMultiviewTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
+{
+    if (!mMultiview2 && mShaderType == GL_VERTEX_SHADER)
+    {
+        ASSERT(visit == PreVisit);
+
+        // Check if the if statement refers to gl_ViewID_OVR and if it does so correctly
+        TIntermBinary *binaryCondition              = node->getCondition()->getAsBinaryNode();
+        bool conditionIsAllowedComparisonWithViewID = false;
+        if (binaryCondition && binaryCondition->getOp() == EOpEqual)
+        {
+            conditionIsAllowedComparisonWithViewID =
+                IsGLViewIDOVR(binaryCondition->getLeft()) &&
+                binaryCondition->getRight()->getAsConstantUnion() &&
+                binaryCondition->getRight()->getQualifier() == EvqConst;
+            if (!conditionIsAllowedComparisonWithViewID)
+            {
+                conditionIsAllowedComparisonWithViewID =
+                    IsGLViewIDOVR(binaryCondition->getRight()) &&
+                    binaryCondition->getLeft()->getAsConstantUnion() &&
+                    binaryCondition->getLeft()->getQualifier() == EvqConst;
+            }
+        }
+        if (conditionIsAllowedComparisonWithViewID)
+        {
+            mInsideViewIDConditional = true;
+            if (node->getTrueBlock())
+            {
+                validateAndTraverseViewIDConditionalBlock(node->getTrueBlock(), "if");
+            }
+            else
+            {
+                mDiagnostics->error(node->getLine(), "Expected assignment to gl_Position.x", "if");
+            }
+            if (node->getFalseBlock())
+            {
+                validateAndTraverseViewIDConditionalBlock(node->getFalseBlock(), "else");
+            }
+            mInsideViewIDConditional = false;
+        }
+        else
+        {
+            node->getCondition()->traverse(this);
+            if (node->getTrueBlock())
+            {
+                node->getTrueBlock()->traverse(this);
+            }
+            if (node->getFalseBlock())
+            {
+                node->getFalseBlock()->traverse(this);
+            }
+        }
+        return false;
+    }
+    return true;
+}
+
+bool ValidateMultiviewTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (visit == PreVisit && !mMultiview2 && mInsideRestrictedAssignment)
+    {
+        // Check if the node is an user-defined function call or if an l-value is required, or if
+        // there are possible visible side effects, such as image writes.
+        if (node->getOp() == EOpCallFunctionInAST)
+        {
+            mDiagnostics->error(node->getLine(),
+                                "Disallowed user defined function call inside assignment to "
+                                "gl_Position.x when using OVR_multiview",
+                                GetOperatorString(node->getOp()));
+            mValid = false;
+        }
+        else if (node->getOp() == EOpCallBuiltInFunction &&
+                 node->getFunctionSymbolInfo()->getName() == "imageStore")
+        {
+            // TODO(oetuaho@nvidia.com): Record which built-in functions have side effects in
+            // the symbol info instead.
+            mDiagnostics->error(node->getLine(),
+                                "Disallowed function call with side effects inside assignment "
+                                "to gl_Position.x when using OVR_multiview",
+                                GetOperatorString(node->getOp()));
+            mValid = false;
+        }
+        else if (!node->isConstructor())
+        {
+            TFunction *builtInFunc = static_cast<TFunction *>(
+                mSymbolTable.findBuiltIn(node->getSymbolTableMangledName(), mShaderVersion));
+            for (size_t paramIndex = 0u; paramIndex < builtInFunc->getParamCount(); ++paramIndex)
+            {
+                TQualifier qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
+                if (qualifier == EvqOut || qualifier == EvqInOut)
+                {
+                    mDiagnostics->error(node->getLine(),
+                                        "Disallowed use of a function with an out parameter inside "
+                                        "assignment to gl_Position.x when using OVR_multiview",
+                                        GetOperatorString(node->getOp()));
+                    mValid = false;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+}  // anonymous namespace
+
+bool ValidateMultiviewWebGL(TIntermBlock *root,
+                            GLenum shaderType,
+                            const TSymbolTable &symbolTable,
+                            int shaderVersion,
+                            bool multiview2,
+                            TDiagnostics *diagnostics)
+{
+    if (shaderType == GL_VERTEX_SHADER && !FindSymbolNode(root, "gl_ViewID_OVR", EbtUInt))
+    {
+        return true;
+    }
+    return ValidateMultiviewTraverser::validate(root, shaderType, symbolTable, shaderVersion,
+                                                multiview2, diagnostics);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ValidateMultiviewWebGL.h b/src/third_party/angle/src/compiler/translator/ValidateMultiviewWebGL.h
new file mode 100644
index 0000000..371a03d
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateMultiviewWebGL.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+// ValidateMultiviewWebGL.h:
+//   Validate the AST according to rules in the WEBGL_multiview extension spec. Only covers those
+//   rules not already covered in ParseContext.
+//
+
+#ifndef COMPILER_TRANSLATOR_VALIDATEMULTIVIEWWEBGL_H_
+#define COMPILER_TRANSLATOR_VALIDATEMULTIVIEWWEBGL_H_
+
+#include "GLSLANG/ShaderVars.h"
+
+namespace sh
+{
+class TDiagnostics;
+class TIntermBlock;
+class TSymbolTable;
+
+// Check for errors and output error messages with diagnostics.
+// Returns true if there are no errors.
+bool ValidateMultiviewWebGL(TIntermBlock *root,
+                            sh::GLenum shaderType,
+                            const TSymbolTable &symbolTable,
+                            int shaderVersion,
+                            bool multiview2,
+                            TDiagnostics *diagnostics);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_VALIDATEMULTIVIEWWEBGL_H_
diff --git a/src/third_party/angle/src/compiler/translator/ValidateOutputs.cpp b/src/third_party/angle/src/compiler/translator/ValidateOutputs.cpp
new file mode 100644
index 0000000..27ab814
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateOutputs.cpp
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ValidateOutputs.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
+
+namespace
+{
+void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
+{
+    diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
+}
+
+}  // namespace
+
+ValidateOutputs::ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers)
+    : TIntermTraverser(true, false, false),
+      mMaxDrawBuffers(maxDrawBuffers),
+      mAllowUnspecifiedOutputLocationResolution(
+          IsExtensionEnabled(extBehavior, "GL_EXT_blend_func_extended")),
+      mUsesFragDepth(false)
+{
+}
+
+void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
+{
+    TString name         = symbol->getSymbol();
+    TQualifier qualifier = symbol->getQualifier();
+
+    if (mVisitedSymbols.count(name.c_str()) == 1)
+        return;
+
+    mVisitedSymbols.insert(name.c_str());
+
+    if (qualifier == EvqFragmentOut)
+    {
+        if (symbol->getType().getLayoutQualifier().location != -1)
+        {
+            mOutputs.push_back(symbol);
+        }
+        else if (symbol->getType().getLayoutQualifier().yuv == true)
+        {
+            mYuvOutputs.push_back(symbol);
+        }
+        else
+        {
+            mUnspecifiedLocationOutputs.push_back(symbol);
+        }
+    }
+    else if (qualifier == EvqFragDepth || qualifier == EvqFragDepthEXT)
+    {
+        mUsesFragDepth = true;
+    }
+}
+
+void ValidateOutputs::validate(TDiagnostics *diagnostics) const
+{
+    ASSERT(diagnostics);
+    OutputVector validOutputs(mMaxDrawBuffers);
+
+    for (const auto &symbol : mOutputs)
+    {
+        const TType &type         = symbol->getType();
+        const size_t elementCount = static_cast<size_t>(type.isArray() ? type.getArraySize() : 1u);
+        const size_t location     = static_cast<size_t>(type.getLayoutQualifier().location);
+
+        ASSERT(type.getLayoutQualifier().location != -1);
+
+        if (location + elementCount <= validOutputs.size())
+        {
+            for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++)
+            {
+                const size_t offsetLocation = location + elementIndex;
+                if (validOutputs[offsetLocation])
+                {
+                    std::stringstream strstr;
+                    strstr << "conflicting output locations with previously defined output '"
+                           << validOutputs[offsetLocation]->getSymbol() << "'";
+                    error(*symbol, strstr.str().c_str(), diagnostics);
+                }
+                else
+                {
+                    validOutputs[offsetLocation] = symbol;
+                }
+            }
+        }
+        else
+        {
+            if (elementCount > 0)
+            {
+                error(*symbol,
+                      elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS"
+                                       : "output location must be < MAX_DRAW_BUFFERS",
+                      diagnostics);
+            }
+        }
+    }
+
+    if (!mAllowUnspecifiedOutputLocationResolution &&
+        ((!mOutputs.empty() && !mUnspecifiedLocationOutputs.empty()) ||
+         mUnspecifiedLocationOutputs.size() > 1))
+    {
+        for (const auto &symbol : mUnspecifiedLocationOutputs)
+        {
+            error(*symbol,
+                  "must explicitly specify all locations when using multiple fragment outputs",
+                  diagnostics);
+        }
+    }
+
+    if (!mYuvOutputs.empty() && (mYuvOutputs.size() > 1 || mUsesFragDepth || !mOutputs.empty() ||
+                                 !mUnspecifiedLocationOutputs.empty()))
+    {
+        for (const auto &symbol : mYuvOutputs)
+        {
+            error(*symbol,
+                  "not allowed to specify yuv qualifier when using depth or multiple color "
+                  "fragment outputs",
+                  diagnostics);
+        }
+    }
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ValidateOutputs.h b/src/third_party/angle/src/compiler/translator/ValidateOutputs.h
new file mode 100644
index 0000000..c9282d2
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateOutputs.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
+#define COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
+
+#include "compiler/translator/ExtensionBehavior.h"
+#include "compiler/translator/IntermNode.h"
+
+#include <set>
+
+namespace sh
+{
+
+class TInfoSinkBase;
+
+class ValidateOutputs : public TIntermTraverser
+{
+  public:
+    ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers);
+
+    void validate(TDiagnostics *diagnostics) const;
+
+    void visitSymbol(TIntermSymbol *) override;
+
+  private:
+    int mMaxDrawBuffers;
+    bool mAllowUnspecifiedOutputLocationResolution;
+    bool mUsesFragDepth;
+
+    typedef std::vector<TIntermSymbol *> OutputVector;
+    OutputVector mOutputs;
+    OutputVector mUnspecifiedLocationOutputs;
+    OutputVector mYuvOutputs;
+    std::set<std::string> mVisitedSymbols;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
diff --git a/src/third_party/angle/src/compiler/translator/ValidateSwitch.cpp b/src/third_party/angle/src/compiler/translator/ValidateSwitch.cpp
new file mode 100644
index 0000000..6091c72
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateSwitch.cpp
@@ -0,0 +1,270 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ValidateSwitch.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/Diagnostics.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class ValidateSwitch : public TIntermTraverser
+{
+  public:
+    static bool validate(TBasicType switchType,
+                         TDiagnostics *diagnostics,
+                         TIntermBlock *statementList,
+                         const TSourceLoc &loc);
+
+    void visitSymbol(TIntermSymbol *) override;
+    void visitConstantUnion(TIntermConstantUnion *) override;
+    bool visitBinary(Visit, TIntermBinary *) override;
+    bool visitUnary(Visit, TIntermUnary *) override;
+    bool visitTernary(Visit, TIntermTernary *) override;
+    bool visitIfElse(Visit visit, TIntermIfElse *) override;
+    bool visitSwitch(Visit, TIntermSwitch *) override;
+    bool visitCase(Visit, TIntermCase *node) override;
+    bool visitAggregate(Visit, TIntermAggregate *) override;
+    bool visitLoop(Visit visit, TIntermLoop *) override;
+    bool visitBranch(Visit, TIntermBranch *) override;
+
+  private:
+    ValidateSwitch(TBasicType switchType, TDiagnostics *context);
+
+    bool validateInternal(const TSourceLoc &loc);
+
+    TBasicType mSwitchType;
+    TDiagnostics *mDiagnostics;
+    bool mCaseTypeMismatch;
+    bool mFirstCaseFound;
+    bool mStatementBeforeCase;
+    bool mLastStatementWasCase;
+    int mControlFlowDepth;
+    bool mCaseInsideControlFlow;
+    int mDefaultCount;
+    std::set<int> mCasesSigned;
+    std::set<unsigned int> mCasesUnsigned;
+    bool mDuplicateCases;
+};
+
+bool ValidateSwitch::validate(TBasicType switchType,
+                              TDiagnostics *diagnostics,
+                              TIntermBlock *statementList,
+                              const TSourceLoc &loc)
+{
+    ValidateSwitch validate(switchType, diagnostics);
+    ASSERT(statementList);
+    statementList->traverse(&validate);
+    return validate.validateInternal(loc);
+}
+
+ValidateSwitch::ValidateSwitch(TBasicType switchType, TDiagnostics *diagnostics)
+    : TIntermTraverser(true, false, true),
+      mSwitchType(switchType),
+      mDiagnostics(diagnostics),
+      mCaseTypeMismatch(false),
+      mFirstCaseFound(false),
+      mStatementBeforeCase(false),
+      mLastStatementWasCase(false),
+      mControlFlowDepth(0),
+      mCaseInsideControlFlow(false),
+      mDefaultCount(0),
+      mDuplicateCases(false)
+{
+}
+
+void ValidateSwitch::visitSymbol(TIntermSymbol *)
+{
+    if (!mFirstCaseFound)
+        mStatementBeforeCase = true;
+    mLastStatementWasCase    = false;
+}
+
+void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *)
+{
+    // Conditions of case labels are not traversed, so this is some other constant
+    // Could be just a statement like "0;"
+    if (!mFirstCaseFound)
+        mStatementBeforeCase = true;
+    mLastStatementWasCase    = false;
+}
+
+bool ValidateSwitch::visitBinary(Visit, TIntermBinary *)
+{
+    if (!mFirstCaseFound)
+        mStatementBeforeCase = true;
+    mLastStatementWasCase    = false;
+    return true;
+}
+
+bool ValidateSwitch::visitUnary(Visit, TIntermUnary *)
+{
+    if (!mFirstCaseFound)
+        mStatementBeforeCase = true;
+    mLastStatementWasCase    = false;
+    return true;
+}
+
+bool ValidateSwitch::visitTernary(Visit, TIntermTernary *)
+{
+    if (!mFirstCaseFound)
+        mStatementBeforeCase = true;
+    mLastStatementWasCase    = false;
+    return true;
+}
+
+bool ValidateSwitch::visitIfElse(Visit visit, TIntermIfElse *)
+{
+    if (visit == PreVisit)
+        ++mControlFlowDepth;
+    if (visit == PostVisit)
+        --mControlFlowDepth;
+    if (!mFirstCaseFound)
+        mStatementBeforeCase = true;
+    mLastStatementWasCase    = false;
+    return true;
+}
+
+bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *)
+{
+    if (!mFirstCaseFound)
+        mStatementBeforeCase = true;
+    mLastStatementWasCase    = false;
+    // Don't go into nested switch statements
+    return false;
+}
+
+bool ValidateSwitch::visitCase(Visit, TIntermCase *node)
+{
+    const char *nodeStr = node->hasCondition() ? "case" : "default";
+    if (mControlFlowDepth > 0)
+    {
+        mDiagnostics->error(node->getLine(), "label statement nested inside control flow", nodeStr);
+        mCaseInsideControlFlow = true;
+    }
+    mFirstCaseFound       = true;
+    mLastStatementWasCase = true;
+    if (!node->hasCondition())
+    {
+        ++mDefaultCount;
+        if (mDefaultCount > 1)
+        {
+            mDiagnostics->error(node->getLine(), "duplicate default label", nodeStr);
+        }
+    }
+    else
+    {
+        TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion();
+        if (condition == nullptr)
+        {
+            // This can happen in error cases.
+            return false;
+        }
+        TBasicType conditionType = condition->getBasicType();
+        if (conditionType != mSwitchType)
+        {
+            mDiagnostics->error(condition->getLine(),
+                                "case label type does not match switch init-expression type",
+                                nodeStr);
+            mCaseTypeMismatch = true;
+        }
+
+        if (conditionType == EbtInt)
+        {
+            int iConst = condition->getIConst(0);
+            if (mCasesSigned.find(iConst) != mCasesSigned.end())
+            {
+                mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr);
+                mDuplicateCases = true;
+            }
+            else
+            {
+                mCasesSigned.insert(iConst);
+            }
+        }
+        else if (conditionType == EbtUInt)
+        {
+            unsigned int uConst = condition->getUConst(0);
+            if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end())
+            {
+                mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr);
+                mDuplicateCases = true;
+            }
+            else
+            {
+                mCasesUnsigned.insert(uConst);
+            }
+        }
+        // Other types are possible only in error cases, where the error has already been generated
+        // when parsing the case statement.
+    }
+    // Don't traverse the condition of the case statement
+    return false;
+}
+
+bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *)
+{
+    if (getParentNode() != nullptr)
+    {
+        // This is not the statementList node, but some other node.
+        if (!mFirstCaseFound)
+            mStatementBeforeCase = true;
+        mLastStatementWasCase    = false;
+    }
+    return true;
+}
+
+bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *)
+{
+    if (visit == PreVisit)
+        ++mControlFlowDepth;
+    if (visit == PostVisit)
+        --mControlFlowDepth;
+    if (!mFirstCaseFound)
+        mStatementBeforeCase = true;
+    mLastStatementWasCase    = false;
+    return true;
+}
+
+bool ValidateSwitch::visitBranch(Visit, TIntermBranch *)
+{
+    if (!mFirstCaseFound)
+        mStatementBeforeCase = true;
+    mLastStatementWasCase    = false;
+    return true;
+}
+
+bool ValidateSwitch::validateInternal(const TSourceLoc &loc)
+{
+    if (mStatementBeforeCase)
+    {
+        mDiagnostics->error(loc, "statement before the first label", "switch");
+    }
+    if (mLastStatementWasCase)
+    {
+        mDiagnostics->error(
+            loc, "no statement between the last label and the end of the switch statement",
+            "switch");
+    }
+    return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow &&
+           !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases;
+}
+
+}  // anonymous namespace
+
+bool ValidateSwitchStatementList(TBasicType switchType,
+                                 TDiagnostics *diagnostics,
+                                 TIntermBlock *statementList,
+                                 const TSourceLoc &loc)
+{
+    return ValidateSwitch::validate(switchType, diagnostics, statementList, loc);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/ValidateSwitch.h b/src/third_party/angle/src/compiler/translator/ValidateSwitch.h
new file mode 100644
index 0000000..757820a
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/ValidateSwitch.h
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_VALIDATESWITCH_H_
+#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_
+
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Common.h"
+
+namespace sh
+{
+class TDiagnostics;
+class TIntermBlock;
+
+// Check for errors and output error messages on the context.
+// Returns true if there are no errors.
+bool ValidateSwitchStatementList(TBasicType switchType,
+                                 TDiagnostics *diagnostics,
+                                 TIntermBlock *statementList,
+                                 const TSourceLoc &loc);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_VALIDATESWITCH_H_
diff --git a/src/third_party/angle/src/compiler/translator/VariableInfo.cpp b/src/third_party/angle/src/compiler/translator/VariableInfo.cpp
new file mode 100644
index 0000000..7673edc
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/VariableInfo.cpp
@@ -0,0 +1,710 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "angle_gl.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/VariableInfo.h"
+#include "compiler/translator/util.h"
+#include "common/utilities.h"
+
+namespace sh
+{
+
+namespace
+{
+
+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)
+{
+    ASSERT(variable.isStruct());
+
+    const std::vector<ShaderVariable> &fields = variable.fields;
+
+    for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+    {
+        const ShaderVariable &field = fields[fieldIndex];
+        ExpandVariable(field, name + "." + field.name, mappedName + "." + field.mappedName,
+                       markStaticUse, expanded);
+    }
+}
+
+template <class VarT>
+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 nullptr;
+}
+}
+
+CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
+                                   std::vector<sh::OutputVariable> *outputVariables,
+                                   std::vector<sh::Uniform> *uniforms,
+                                   std::vector<sh::Varying> *varyings,
+                                   std::vector<sh::InterfaceBlock> *interfaceBlocks,
+                                   ShHashFunction64 hashFunction,
+                                   const TSymbolTable &symbolTable,
+                                   const TExtensionBehavior &extensionBehavior)
+    : TIntermTraverser(true, false, false),
+      mAttribs(attribs),
+      mOutputVariables(outputVariables),
+      mUniforms(uniforms),
+      mVaryings(varyings),
+      mInterfaceBlocks(interfaceBlocks),
+      mDepthRangeAdded(false),
+      mPointCoordAdded(false),
+      mFrontFacingAdded(false),
+      mFragCoordAdded(false),
+      mInstanceIDAdded(false),
+      mVertexIDAdded(false),
+      mPositionAdded(false),
+      mPointSizeAdded(false),
+      mLastFragDataAdded(false),
+      mFragColorAdded(false),
+      mFragDataAdded(false),
+      mFragDepthEXTAdded(false),
+      mFragDepthAdded(false),
+      mSecondaryFragColorEXTAdded(false),
+      mSecondaryFragDataEXTAdded(false),
+      mHashFunction(hashFunction),
+      mSymbolTable(symbolTable),
+      mExtensionBehavior(extensionBehavior)
+{
+}
+
+// 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 != nullptr);
+    ShaderVariable *var       = nullptr;
+    const TString &symbolName = symbol->getSymbol();
+
+    if (IsVarying(symbol->getQualifier()))
+    {
+        var = FindVariable(symbolName, mVaryings);
+    }
+    else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
+    {
+        UNREACHABLE();
+    }
+    else if (symbolName == "gl_DepthRange")
+    {
+        ASSERT(symbol->getQualifier() == EvqUniform);
+
+        if (!mDepthRangeAdded)
+        {
+            Uniform info;
+            const char kName[] = "gl_DepthRange";
+            info.name          = kName;
+            info.mappedName    = kName;
+            info.type          = GL_STRUCT_ANGLEX;
+            info.arraySize     = 0;
+            info.precision     = GL_NONE;
+            info.staticUse     = true;
+
+            ShaderVariable nearInfo;
+            const char kNearName[] = "near";
+            nearInfo.name          = kNearName;
+            nearInfo.mappedName    = kNearName;
+            nearInfo.type          = GL_FLOAT;
+            nearInfo.arraySize     = 0;
+            nearInfo.precision     = GL_HIGH_FLOAT;
+            nearInfo.staticUse     = true;
+
+            ShaderVariable farInfo;
+            const char kFarName[] = "far";
+            farInfo.name          = kFarName;
+            farInfo.mappedName    = kFarName;
+            farInfo.type          = GL_FLOAT;
+            farInfo.arraySize     = 0;
+            farInfo.precision     = GL_HIGH_FLOAT;
+            farInfo.staticUse     = true;
+
+            ShaderVariable diffInfo;
+            const char kDiffName[] = "diff";
+            diffInfo.name          = kDiffName;
+            diffInfo.mappedName    = kDiffName;
+            diffInfo.type          = GL_FLOAT;
+            diffInfo.arraySize     = 0;
+            diffInfo.precision     = GL_HIGH_FLOAT;
+            diffInfo.staticUse     = true;
+
+            info.fields.push_back(nearInfo);
+            info.fields.push_back(farInfo);
+            info.fields.push_back(diffInfo);
+
+            mUniforms->push_back(info);
+            mDepthRangeAdded = true;
+        }
+    }
+    else
+    {
+        switch (symbol->getQualifier())
+        {
+            case EvqAttribute:
+            case EvqVertexIn:
+                var = FindVariable(symbolName, mAttribs);
+                break;
+            case EvqFragmentOut:
+                var = FindVariable(symbolName, mOutputVariables);
+                break;
+            case EvqUniform:
+            {
+                const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
+                if (interfaceBlock)
+                {
+                    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
+                {
+                    var = FindVariable(symbolName, mUniforms);
+                }
+
+                // It's an internal error to reference an undefined user uniform
+                ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
+            }
+            break;
+            case EvqFragCoord:
+                if (!mFragCoordAdded)
+                {
+                    Varying info;
+                    const char kName[] = "gl_FragCoord";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT_VEC4;
+                    info.arraySize     = 0;
+                    info.precision     = GL_MEDIUM_FLOAT;  // Defined by spec.
+                    info.staticUse     = true;
+                    info.isInvariant   = mSymbolTable.isVaryingInvariant(kName);
+                    mVaryings->push_back(info);
+                    mFragCoordAdded = true;
+                }
+                return;
+            case EvqFrontFacing:
+                if (!mFrontFacingAdded)
+                {
+                    Varying info;
+                    const char kName[] = "gl_FrontFacing";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_BOOL;
+                    info.arraySize     = 0;
+                    info.precision     = GL_NONE;
+                    info.staticUse     = true;
+                    info.isInvariant   = mSymbolTable.isVaryingInvariant(kName);
+                    mVaryings->push_back(info);
+                    mFrontFacingAdded = true;
+                }
+                return;
+            case EvqPointCoord:
+                if (!mPointCoordAdded)
+                {
+                    Varying info;
+                    const char kName[] = "gl_PointCoord";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT_VEC2;
+                    info.arraySize     = 0;
+                    info.precision     = GL_MEDIUM_FLOAT;  // Defined by spec.
+                    info.staticUse     = true;
+                    info.isInvariant   = mSymbolTable.isVaryingInvariant(kName);
+                    mVaryings->push_back(info);
+                    mPointCoordAdded = true;
+                }
+                return;
+            case EvqInstanceID:
+                if (!mInstanceIDAdded)
+                {
+                    Attribute info;
+                    const char kName[] = "gl_InstanceID";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_INT;
+                    info.arraySize     = 0;
+                    info.precision     = GL_HIGH_INT;  // Defined by spec.
+                    info.staticUse     = true;
+                    info.location      = -1;
+                    mAttribs->push_back(info);
+                    mInstanceIDAdded = true;
+                }
+                return;
+            case EvqVertexID:
+                if (!mVertexIDAdded)
+                {
+                    Attribute info;
+                    const char kName[] = "gl_VertexID";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_INT;
+                    info.arraySize     = 0;
+                    info.precision     = GL_HIGH_INT;  // Defined by spec.
+                    info.staticUse     = true;
+                    info.location      = -1;
+                    mAttribs->push_back(info);
+                    mVertexIDAdded = true;
+                }
+                return;
+            case EvqPosition:
+                if (!mPositionAdded)
+                {
+                    Varying info;
+                    const char kName[] = "gl_Position";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT_VEC4;
+                    info.arraySize     = 0;
+                    info.precision     = GL_HIGH_FLOAT;  // Defined by spec.
+                    info.staticUse     = true;
+                    info.isInvariant   = mSymbolTable.isVaryingInvariant(kName);
+                    mVaryings->push_back(info);
+                    mPositionAdded = true;
+                }
+                return;
+            case EvqPointSize:
+                if (!mPointSizeAdded)
+                {
+                    Varying info;
+                    const char kName[] = "gl_PointSize";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT;
+                    info.arraySize     = 0;
+                    info.precision     = GL_MEDIUM_FLOAT;  // Defined by spec.
+                    info.staticUse     = true;
+                    info.isInvariant   = mSymbolTable.isVaryingInvariant(kName);
+                    mVaryings->push_back(info);
+                    mPointSizeAdded = true;
+                }
+                return;
+            case EvqLastFragData:
+                if (!mLastFragDataAdded)
+                {
+                    Varying info;
+                    const char kName[] = "gl_LastFragData";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT_VEC4;
+                    info.arraySize     = static_cast<const TVariable *>(
+                                         mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
+                                         ->getConstPointer()
+                                         ->getIConst();
+                    info.precision   = GL_MEDIUM_FLOAT;  // Defined by spec.
+                    info.staticUse   = true;
+                    info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
+                    mVaryings->push_back(info);
+                    mLastFragDataAdded = true;
+                }
+                return;
+            case EvqFragColor:
+                if (!mFragColorAdded)
+                {
+                    OutputVariable info;
+                    const char kName[] = "gl_FragColor";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT_VEC4;
+                    info.arraySize     = 0;
+                    info.precision     = GL_MEDIUM_FLOAT;  // Defined by spec.
+                    info.staticUse     = true;
+                    mOutputVariables->push_back(info);
+                    mFragColorAdded = true;
+                }
+                return;
+            case EvqFragData:
+                if (!mFragDataAdded)
+                {
+                    OutputVariable info;
+                    const char kName[] = "gl_FragData";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT_VEC4;
+                    if (::IsExtensionEnabled(mExtensionBehavior, "GL_EXT_draw_buffers"))
+                    {
+                        info.arraySize = static_cast<const TVariable *>(
+                                             mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
+                                             ->getConstPointer()
+                                             ->getIConst();
+                    }
+                    else
+                    {
+                        info.arraySize = 1;
+                    }
+                    info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
+                    info.staticUse = true;
+                    mOutputVariables->push_back(info);
+                    mFragDataAdded = true;
+                }
+                return;
+            case EvqFragDepthEXT:
+                if (!mFragDepthEXTAdded)
+                {
+                    OutputVariable info;
+                    const char kName[] = "gl_FragDepthEXT";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT;
+                    info.arraySize     = 0;
+                    info.precision =
+                        GLVariablePrecision(static_cast<const TVariable *>(
+                                                mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
+                                                ->getType());
+                    info.staticUse = true;
+                    mOutputVariables->push_back(info);
+                    mFragDepthEXTAdded = true;
+                }
+                return;
+            case EvqFragDepth:
+                if (!mFragDepthAdded)
+                {
+                    OutputVariable info;
+                    const char kName[] = "gl_FragDepth";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT;
+                    info.arraySize     = 0;
+                    info.precision     = GL_HIGH_FLOAT;
+                    info.staticUse     = true;
+                    mOutputVariables->push_back(info);
+                    mFragDepthAdded = true;
+                }
+                return;
+            case EvqSecondaryFragColorEXT:
+                if (!mSecondaryFragColorEXTAdded)
+                {
+                    OutputVariable info;
+                    const char kName[] = "gl_SecondaryFragColorEXT";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT_VEC4;
+                    info.arraySize     = 0;
+                    info.precision     = GL_MEDIUM_FLOAT;  // Defined by spec.
+                    info.staticUse     = true;
+                    mOutputVariables->push_back(info);
+                    mSecondaryFragColorEXTAdded = true;
+                }
+                return;
+            case EvqSecondaryFragDataEXT:
+                if (!mSecondaryFragDataEXTAdded)
+                {
+                    OutputVariable info;
+                    const char kName[] = "gl_SecondaryFragDataEXT";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_FLOAT_VEC4;
+
+                    const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
+                        mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
+                    info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
+                    info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
+                    info.staticUse = true;
+                    mOutputVariables->push_back(info);
+                    mSecondaryFragDataEXTAdded = true;
+                }
+                return;
+            default:
+                break;
+        }
+    }
+    if (var)
+    {
+        var->staticUse = true;
+    }
+}
+
+void CollectVariables::setCommonVariableProperties(const TType &type,
+                                                   const TString &name,
+                                                   ShaderVariable *variableOut) const
+{
+    ASSERT(variableOut);
+
+    const TStructure *structure = type.getStruct();
+
+    if (!structure)
+    {
+        variableOut->type      = GLVariableType(type);
+        variableOut->precision = GLVariablePrecision(type);
+    }
+    else
+    {
+        // Note: this enum value is not exposed outside ANGLE
+        variableOut->type       = GL_STRUCT_ANGLEX;
+        variableOut->structName = structure->name().c_str();
+
+        const TFieldList &fields = structure->fields();
+
+        for (TField *field : fields)
+        {
+            // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
+            // ShaderVariable objects.
+            ShaderVariable fieldVariable;
+            setCommonVariableProperties(*field->type(), field->name(), &fieldVariable);
+            variableOut->fields.push_back(fieldVariable);
+        }
+    }
+    variableOut->name       = name.c_str();
+    variableOut->mappedName = TIntermTraverser::hash(name, mHashFunction).c_str();
+    variableOut->arraySize  = type.getArraySize();
+}
+
+Attribute CollectVariables::recordAttribute(const TIntermSymbol &variable) const
+{
+    const TType &type = variable.getType();
+    ASSERT(!type.getStruct());
+
+    Attribute attribute;
+    setCommonVariableProperties(type, variable.getSymbol(), &attribute);
+
+    attribute.location = type.getLayoutQualifier().location;
+    return attribute;
+}
+
+OutputVariable CollectVariables::recordOutputVariable(const TIntermSymbol &variable) const
+{
+    const TType &type = variable.getType();
+    ASSERT(!type.getStruct());
+
+    OutputVariable outputVariable;
+    setCommonVariableProperties(type, variable.getSymbol(), &outputVariable);
+
+    outputVariable.location = type.getLayoutQualifier().location;
+    return outputVariable;
+}
+
+Varying CollectVariables::recordVarying(const TIntermSymbol &variable) const
+{
+    const TType &type = variable.getType();
+
+    Varying varying;
+    setCommonVariableProperties(type, variable.getSymbol(), &varying);
+
+    switch (type.getQualifier())
+    {
+        case EvqVaryingIn:
+        case EvqVaryingOut:
+        case EvqVertexOut:
+        case EvqSmoothOut:
+        case EvqFlatOut:
+        case EvqCentroidOut:
+            if (mSymbolTable.isVaryingInvariant(std::string(variable.getSymbol().c_str())) ||
+                type.isInvariant())
+            {
+                varying.isInvariant = true;
+            }
+            break;
+        default:
+            break;
+    }
+
+    varying.interpolation = GetInterpolationType(type.getQualifier());
+    return varying;
+}
+
+InterfaceBlock CollectVariables::recordInterfaceBlock(const TIntermSymbol &variable) const
+{
+    const TInterfaceBlock *blockType = variable.getType().getInterfaceBlock();
+    ASSERT(blockType);
+
+    InterfaceBlock interfaceBlock;
+    interfaceBlock.name = blockType->name().c_str();
+    interfaceBlock.mappedName =
+        TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
+    interfaceBlock.instanceName =
+        (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
+    interfaceBlock.arraySize        = variable.getArraySize();
+    interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
+    interfaceBlock.layout           = GetBlockLayoutType(blockType->blockStorage());
+
+    // Gather field information
+    for (const TField *field : blockType->fields())
+    {
+        const TType &fieldType = *field->type();
+
+        InterfaceBlockField fieldVariable;
+        setCommonVariableProperties(fieldType, field->name(), &fieldVariable);
+        fieldVariable.isRowMajorLayout =
+            (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
+        interfaceBlock.fields.push_back(fieldVariable);
+    }
+    return interfaceBlock;
+}
+
+Uniform CollectVariables::recordUniform(const TIntermSymbol &variable) const
+{
+    Uniform uniform;
+    setCommonVariableProperties(variable.getType(), variable.getSymbol(), &uniform);
+    uniform.binding = variable.getType().getLayoutQualifier().binding;
+    uniform.location = variable.getType().getLayoutQualifier().location;
+    return uniform;
+}
+
+bool CollectVariables::visitDeclaration(Visit, TIntermDeclaration *node)
+{
+    const TIntermSequence &sequence = *(node->getSequence());
+    ASSERT(!sequence.empty());
+
+    const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
+    TQualifier qualifier          = typedNode.getQualifier();
+
+    bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
+                            qualifier == EvqFragmentOut || qualifier == EvqUniform ||
+                            IsVarying(qualifier);
+
+    if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
+    {
+        return true;
+    }
+
+    for (TIntermNode *variableNode : sequence)
+    {
+        // The only case in which the sequence will not contain a TIntermSymbol node is
+        // initialization. It will contain a TInterBinary node in that case. Since attributes,
+        // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
+        // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
+        const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
+        if (typedNode.getBasicType() == EbtInterfaceBlock)
+        {
+            mInterfaceBlocks->push_back(recordInterfaceBlock(variable));
+        }
+        else
+        {
+            switch (qualifier)
+            {
+                case EvqAttribute:
+                case EvqVertexIn:
+                    mAttribs->push_back(recordAttribute(variable));
+                    break;
+                case EvqFragmentOut:
+                    mOutputVariables->push_back(recordOutputVariable(variable));
+                    break;
+                case EvqUniform:
+                    mUniforms->push_back(recordUniform(variable));
+                    break;
+                default:
+                    mVaryings->push_back(recordVarying(variable));
+                    break;
+            }
+        }
+    }
+
+    // None of the recorded variables can have initializers, so we don't need to traverse the
+    // declarators.
+    return false;
+}
+
+bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
+{
+    if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
+    {
+        // 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();
+        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;
+}
+
+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 (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
+                 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
+    {
+        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;
+        }
+
+        if (expandedVar.isArray())
+        {
+            expandedVar.name += "[0]";
+            expandedVar.mappedName += "[0]";
+        }
+
+        expanded->push_back(expandedVar);
+    }
+}
+
+void ExpandUniforms(const std::vector<Uniform> &compact, std::vector<ShaderVariable> *expanded)
+{
+    for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
+    {
+        const ShaderVariable &variable = compact[variableIndex];
+        ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
+    }
+}
+}
diff --git a/src/third_party/angle/src/compiler/translator/VariableInfo.h b/src/third_party/angle/src/compiler/translator/VariableInfo.h
new file mode 100644
index 0000000..f24e2c8
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/VariableInfo.h
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_VARIABLEINFO_H_
+#define COMPILER_TRANSLATOR_VARIABLEINFO_H_
+
+#include <GLSLANG/ShaderLang.h>
+
+#include "compiler/translator/ExtensionBehavior.h"
+#include "compiler/translator/IntermNode.h"
+
+class TSymbolTable;
+
+namespace sh
+{
+
+// Traverses intermediate tree to collect all attributes, uniforms, varyings.
+class CollectVariables : public TIntermTraverser
+{
+  public:
+    CollectVariables(std::vector<Attribute> *attribs,
+                     std::vector<OutputVariable> *outputVariables,
+                     std::vector<Uniform> *uniforms,
+                     std::vector<Varying> *varyings,
+                     std::vector<InterfaceBlock> *interfaceBlocks,
+                     ShHashFunction64 hashFunction,
+                     const TSymbolTable &symbolTable,
+                     const TExtensionBehavior &extensionBehavior);
+
+    void visitSymbol(TIntermSymbol *symbol) override;
+    bool visitDeclaration(Visit, TIntermDeclaration *node) override;
+    bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
+
+  private:
+    void setCommonVariableProperties(const TType &type,
+                                     const TString &name,
+                                     ShaderVariable *variableOut) const;
+
+    Attribute recordAttribute(const TIntermSymbol &variable) const;
+    OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
+    Varying recordVarying(const TIntermSymbol &variable) const;
+    InterfaceBlock recordInterfaceBlock(const TIntermSymbol &variable) const;
+    Uniform recordUniform(const TIntermSymbol &variable) const;
+
+    std::vector<Attribute> *mAttribs;
+    std::vector<OutputVariable> *mOutputVariables;
+    std::vector<Uniform> *mUniforms;
+    std::vector<Varying> *mVaryings;
+    std::vector<InterfaceBlock> *mInterfaceBlocks;
+
+    std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
+
+    bool mDepthRangeAdded;
+    bool mPointCoordAdded;
+    bool mFrontFacingAdded;
+    bool mFragCoordAdded;
+
+    bool mInstanceIDAdded;
+    bool mVertexIDAdded;
+    bool mPositionAdded;
+    bool mPointSizeAdded;
+    bool mLastFragDataAdded;
+    bool mFragColorAdded;
+    bool mFragDataAdded;
+    bool mFragDepthEXTAdded;
+    bool mFragDepthAdded;
+    bool mSecondaryFragColorEXTAdded;
+    bool mSecondaryFragDataEXTAdded;
+
+    ShHashFunction64 mHashFunction;
+
+    const TSymbolTable &mSymbolTable;
+    const TExtensionBehavior &mExtensionBehavior;
+};
+
+void ExpandVariable(const ShaderVariable &variable,
+                    const std::string &name,
+                    const std::string &mappedName,
+                    bool markStaticUse,
+                    std::vector<ShaderVariable> *expanded);
+
+// Expand struct uniforms to flattened lists of split variables
+void ExpandUniforms(const std::vector<Uniform> &compact, std::vector<ShaderVariable> *expanded);
+}
+
+#endif  // COMPILER_TRANSLATOR_VARIABLEINFO_H_
diff --git a/src/third_party/angle/src/compiler/translator/VariablePacker.cpp b/src/third_party/angle/src/compiler/translator/VariablePacker.cpp
new file mode 100644
index 0000000..9c4c937
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/VariablePacker.cpp
@@ -0,0 +1,297 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include <algorithm>
+
+#include "angle_gl.h"
+
+#include "compiler/translator/VariablePacker.h"
+#include "common/utilities.h"
+
+int VariablePacker::GetNumComponentsPerRow(sh::GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT_MAT4:
+        case GL_FLOAT_MAT2:
+        case GL_FLOAT_MAT2x4:
+        case GL_FLOAT_MAT3x4:
+        case GL_FLOAT_MAT4x2:
+        case GL_FLOAT_MAT4x3:
+        case GL_FLOAT_VEC4:
+        case GL_INT_VEC4:
+        case GL_BOOL_VEC4:
+        case GL_UNSIGNED_INT_VEC4:
+            return 4;
+        case GL_FLOAT_MAT3:
+        case GL_FLOAT_MAT2x3:
+        case GL_FLOAT_MAT3x2:
+        case GL_FLOAT_VEC3:
+        case GL_INT_VEC3:
+        case GL_BOOL_VEC3:
+        case GL_UNSIGNED_INT_VEC3:
+            return 3;
+        case GL_FLOAT_VEC2:
+        case GL_INT_VEC2:
+        case GL_BOOL_VEC2:
+        case GL_UNSIGNED_INT_VEC2:
+            return 2;
+        default:
+            ASSERT(gl::VariableComponentCount(type) == 1);
+            return 1;
+    }
+}
+
+int VariablePacker::GetNumRows(sh::GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT_MAT4:
+        case GL_FLOAT_MAT2x4:
+        case GL_FLOAT_MAT3x4:
+        case GL_FLOAT_MAT4x3:
+        case GL_FLOAT_MAT4x2:
+            return 4;
+        case GL_FLOAT_MAT3:
+        case GL_FLOAT_MAT2x3:
+        case GL_FLOAT_MAT3x2:
+            return 3;
+        case GL_FLOAT_MAT2:
+            return 2;
+        default:
+            ASSERT(gl::VariableRowCount(type) == 1);
+            return 1;
+    }
+}
+
+struct TVariableInfoComparer
+{
+    bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const
+    {
+        int lhsSortOrder = gl::VariableSortOrder(lhs.type);
+        int rhsSortOrder = gl::VariableSortOrder(rhs.type);
+        if (lhsSortOrder != rhsSortOrder)
+        {
+            return lhsSortOrder < rhsSortOrder;
+        }
+        // Sort by largest first.
+        return lhs.arraySize > rhs.arraySize;
+    }
+};
+
+unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
+{
+    return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & kColumnMask) >> column;
+}
+
+void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
+{
+    unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
+    for (int r = 0; r < numRows; ++r)
+    {
+        int row = topRow + r;
+        ASSERT((rows_[row] & columnFlags) == 0);
+        rows_[row] |= columnFlags;
+    }
+}
+
+bool VariablePacker::searchColumn(int column, int numRows, int *destRow, int *destSize)
+{
+    ASSERT(destRow);
+
+    for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; ++topNonFullRow_)
+    {
+    }
+
+    for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; --bottomNonFullRow_)
+    {
+    }
+
+    if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows)
+    {
+        return false;
+    }
+
+    unsigned columnFlags = makeColumnFlags(column, 1);
+    int topGoodRow       = 0;
+    int smallestGoodTop  = -1;
+    int smallestGoodSize = maxRows_ + 1;
+    int bottomRow        = bottomNonFullRow_ + 1;
+    bool found           = false;
+    for (int row = topNonFullRow_; row <= bottomRow; ++row)
+    {
+        bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
+        if (rowEmpty)
+        {
+            if (!found)
+            {
+                topGoodRow = row;
+                found      = true;
+            }
+        }
+        else
+        {
+            if (found)
+            {
+                int size = row - topGoodRow;
+                if (size >= numRows && size < smallestGoodSize)
+                {
+                    smallestGoodSize = size;
+                    smallestGoodTop  = topGoodRow;
+                }
+            }
+            found = false;
+        }
+    }
+    if (smallestGoodTop < 0)
+    {
+        return false;
+    }
+
+    *destRow = smallestGoodTop;
+    if (destSize)
+    {
+        *destSize = smallestGoodSize;
+    }
+    return true;
+}
+
+bool VariablePacker::CheckVariablesWithinPackingLimits(
+    unsigned int maxVectors,
+    const std::vector<sh::ShaderVariable> &in_variables)
+{
+    ASSERT(maxVectors > 0);
+    maxRows_          = maxVectors;
+    topNonFullRow_    = 0;
+    bottomNonFullRow_ = maxRows_ - 1;
+    std::vector<sh::ShaderVariable> variables;
+
+    for (const auto &variable : in_variables)
+    {
+        ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse,
+                       &variables);
+    }
+
+    // Check whether each variable fits in the available vectors.
+    for (size_t i = 0; i < variables.size(); i++)
+    {
+        const sh::ShaderVariable &variable = variables[i];
+        if (variable.elementCount() > maxVectors / GetNumRows(variable.type))
+        {
+            return false;
+        }
+    }
+
+    // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
+    // order by type, then by size of array, largest first.
+    std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
+    rows_.clear();
+    rows_.resize(maxVectors, 0);
+
+    // Packs the 4 column variables.
+    size_t ii = 0;
+    for (; ii < variables.size(); ++ii)
+    {
+        const sh::ShaderVariable &variable = variables[ii];
+        if (GetNumComponentsPerRow(variable.type) != 4)
+        {
+            break;
+        }
+        topNonFullRow_ += GetNumRows(variable.type) * variable.elementCount();
+    }
+
+    if (topNonFullRow_ > maxRows_)
+    {
+        return false;
+    }
+
+    // Packs the 3 column variables.
+    int num3ColumnRows = 0;
+    for (; ii < variables.size(); ++ii)
+    {
+        const sh::ShaderVariable &variable = variables[ii];
+        if (GetNumComponentsPerRow(variable.type) != 3)
+        {
+            break;
+        }
+        num3ColumnRows += GetNumRows(variable.type) * variable.elementCount();
+    }
+
+    if (topNonFullRow_ + num3ColumnRows > maxRows_)
+    {
+        return false;
+    }
+
+    fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
+
+    // Packs the 2 column variables.
+    int top2ColumnRow            = topNonFullRow_ + num3ColumnRows;
+    int twoColumnRowsAvailable   = maxRows_ - top2ColumnRow;
+    int rowsAvailableInColumns01 = twoColumnRowsAvailable;
+    int rowsAvailableInColumns23 = twoColumnRowsAvailable;
+    for (; ii < variables.size(); ++ii)
+    {
+        const sh::ShaderVariable &variable = variables[ii];
+        if (GetNumComponentsPerRow(variable.type) != 2)
+        {
+            break;
+        }
+        int numRows = GetNumRows(variable.type) * variable.elementCount();
+        if (numRows <= rowsAvailableInColumns01)
+        {
+            rowsAvailableInColumns01 -= numRows;
+        }
+        else if (numRows <= rowsAvailableInColumns23)
+        {
+            rowsAvailableInColumns23 -= numRows;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    int numRowsUsedInColumns01 = twoColumnRowsAvailable - rowsAvailableInColumns01;
+    int numRowsUsedInColumns23 = twoColumnRowsAvailable - rowsAvailableInColumns23;
+    fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
+    fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, 2, 2);
+
+    // Packs the 1 column variables.
+    for (; ii < variables.size(); ++ii)
+    {
+        const sh::ShaderVariable &variable = variables[ii];
+        ASSERT(1 == GetNumComponentsPerRow(variable.type));
+        int numRows        = GetNumRows(variable.type) * variable.elementCount();
+        int smallestColumn = -1;
+        int smallestSize   = maxRows_ + 1;
+        int topRow         = -1;
+        for (int column = 0; column < kNumColumns; ++column)
+        {
+            int row  = 0;
+            int size = 0;
+            if (searchColumn(column, numRows, &row, &size))
+            {
+                if (size < smallestSize)
+                {
+                    smallestSize   = size;
+                    smallestColumn = column;
+                    topRow         = row;
+                }
+            }
+        }
+
+        if (smallestColumn < 0)
+        {
+            return false;
+        }
+
+        fillColumns(topRow, numRows, smallestColumn, 1);
+    }
+
+    ASSERT(variables.size() == ii);
+
+    return true;
+}
diff --git a/src/third_party/angle/src/compiler/translator/VariablePacker.h b/src/third_party/angle/src/compiler/translator/VariablePacker.h
new file mode 100644
index 0000000..c6a3206
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/VariablePacker.h
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_
+#define COMPILER_TRANSLATOR_VARIABLEPACKER_H_
+
+#include <vector>
+#include "compiler/translator/VariableInfo.h"
+
+class VariablePacker
+{
+  public:
+    // Returns true if the passed in variables pack in maxVectors following
+    // the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
+    bool CheckVariablesWithinPackingLimits(unsigned int maxVectors,
+                                           const std::vector<sh::ShaderVariable> &in_variables);
+
+    // Gets how many components in a row a data type takes.
+    static int GetNumComponentsPerRow(sh::GLenum type);
+
+    // Gets how many rows a data type takes.
+    static int GetNumRows(sh::GLenum type);
+
+  private:
+    static const int kNumColumns      = 4;
+    static const unsigned kColumnMask = (1 << kNumColumns) - 1;
+
+    unsigned makeColumnFlags(int column, int numComponentsPerRow);
+    void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
+    bool searchColumn(int column, int numRows, int *destRow, int *destSize);
+
+    int topNonFullRow_;
+    int bottomNonFullRow_;
+    int maxRows_;
+    std::vector<unsigned> rows_;
+};
+
+#endif  // COMPILER_TRANSLATOR_VARIABLEPACKER_H_
diff --git a/src/third_party/angle/src/compiler/translator/VersionGLSL.cpp b/src/third_party/angle/src/compiler/translator/VersionGLSL.cpp
new file mode 100644
index 0000000..8168876
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/VersionGLSL.cpp
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/VersionGLSL.h"
+
+#include "angle_gl.h"
+
+namespace sh
+{
+
+int ShaderOutputTypeToGLSLVersion(ShShaderOutput output)
+{
+    switch (output)
+    {
+        case SH_GLSL_130_OUTPUT:
+            return GLSL_VERSION_130;
+        case SH_GLSL_140_OUTPUT:
+            return GLSL_VERSION_140;
+        case SH_GLSL_150_CORE_OUTPUT:
+            return GLSL_VERSION_150;
+        case SH_GLSL_330_CORE_OUTPUT:
+            return GLSL_VERSION_330;
+        case SH_GLSL_400_CORE_OUTPUT:
+            return GLSL_VERSION_400;
+        case SH_GLSL_410_CORE_OUTPUT:
+            return GLSL_VERSION_410;
+        case SH_GLSL_420_CORE_OUTPUT:
+            return GLSL_VERSION_420;
+        case SH_GLSL_430_CORE_OUTPUT:
+            return GLSL_VERSION_430;
+        case SH_GLSL_440_CORE_OUTPUT:
+            return GLSL_VERSION_440;
+        case SH_GLSL_450_CORE_OUTPUT:
+            return GLSL_VERSION_450;
+        case SH_GLSL_COMPATIBILITY_OUTPUT:
+            return GLSL_VERSION_110;
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+// We need to scan for the following:
+// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
+//    but only at the global scope.
+// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
+//    but inside any scope.
+// 3. Call to a matrix constructor with another matrix as argument.
+//    (These constructors were reserved in GLSL version 1.10.)
+// 4. Arrays as "out" function parameters.
+//    GLSL spec section 6.1.1: "When calling a function, expressions that do
+//    not evaluate to l-values cannot be passed to parameters declared as
+//    out or inout."
+//    GLSL 1.1 section 5.8: "Other binary or unary expressions,
+//    non-dereferenced arrays, function names, swizzles with repeated fields,
+//    and constants cannot be l-values."
+//    GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
+//    are built-in types, entire structures or arrays... are all l-values."
+//
+TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output)
+    : TIntermTraverser(true, false, false)
+{
+    mVersion = ShaderOutputTypeToGLSLVersion(output);
+    if (pragma.stdgl.invariantAll)
+    {
+        ensureVersionIsAtLeast(GLSL_VERSION_120);
+    }
+    if (type == GL_COMPUTE_SHADER)
+    {
+        ensureVersionIsAtLeast(GLSL_VERSION_430);
+    }
+}
+
+void TVersionGLSL::visitSymbol(TIntermSymbol *node)
+{
+    if (node->getSymbol() == "gl_PointCoord")
+    {
+        ensureVersionIsAtLeast(GLSL_VERSION_120);
+    }
+}
+
+bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node)
+{
+    const TIntermSequence &sequence = *(node->getSequence());
+    if (sequence.front()->getAsTyped()->getType().isInvariant())
+    {
+        ensureVersionIsAtLeast(GLSL_VERSION_120);
+    }
+    return true;
+}
+
+bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node)
+{
+    ensureVersionIsAtLeast(GLSL_VERSION_120);
+    return true;
+}
+
+bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node)
+{
+    const TIntermSequence &params = *(node->getSequence());
+    for (TIntermSequence::const_iterator iter = params.begin(); iter != params.end(); ++iter)
+    {
+        const TIntermTyped *param = (*iter)->getAsTyped();
+        if (param->isArray())
+        {
+            TQualifier qualifier = param->getQualifier();
+            if ((qualifier == EvqOut) || (qualifier == EvqInOut))
+            {
+                ensureVersionIsAtLeast(GLSL_VERSION_120);
+                break;
+            }
+        }
+    }
+    // Fully processed. No need to visit children.
+    return false;
+}
+
+bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
+{
+    if (node->getOp() == EOpConstruct && node->getType().isMatrix())
+    {
+        const TIntermSequence &sequence = *(node->getSequence());
+        if (sequence.size() == 1)
+        {
+            TIntermTyped *typed = sequence.front()->getAsTyped();
+            if (typed && typed->isMatrix())
+            {
+                ensureVersionIsAtLeast(GLSL_VERSION_120);
+            }
+        }
+    }
+    return true;
+}
+
+void TVersionGLSL::ensureVersionIsAtLeast(int version)
+{
+    mVersion = std::max(version, mVersion);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/VersionGLSL.h b/src/third_party/angle/src/compiler/translator/VersionGLSL.h
new file mode 100644
index 0000000..9cf727c
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/VersionGLSL.h
@@ -0,0 +1,76 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_
+#define COMPILER_TRANSLATOR_VERSIONGLSL_H_
+
+#include "compiler/translator/IntermNode.h"
+
+#include "compiler/translator/Pragma.h"
+
+namespace sh
+{
+
+static const int GLSL_VERSION_110 = 110;
+static const int GLSL_VERSION_120 = 120;
+static const int GLSL_VERSION_130 = 130;
+static const int GLSL_VERSION_140 = 140;
+static const int GLSL_VERSION_150 = 150;
+static const int GLSL_VERSION_330 = 330;
+static const int GLSL_VERSION_400 = 400;
+static const int GLSL_VERSION_410 = 410;
+static const int GLSL_VERSION_420 = 420;
+static const int GLSL_VERSION_430 = 430;
+static const int GLSL_VERSION_440 = 440;
+static const int GLSL_VERSION_450 = 450;
+
+int ShaderOutputTypeToGLSLVersion(ShShaderOutput output);
+
+// Traverses the intermediate tree to return the minimum GLSL version
+// required to legally access all built-in features used in the shader.
+// GLSL 1.1 which is mandated by OpenGL 2.0 provides:
+//   - #version and #extension to declare version and extensions.
+//   - built-in functions refract, exp, and log.
+//   - updated step() to compare x < edge instead of x <= edge.
+// GLSL 1.2 which is mandated by OpenGL 2.1 provides:
+//   - many changes to reduce differences when compared to the ES specification.
+//   - invariant keyword and its support.
+//   - c++ style name hiding rules.
+//   - built-in variable gl_PointCoord for fragment shaders.
+//   - matrix constructors taking matrix as argument.
+//   - array as "out" function parameters
+//
+// TODO: ES3 equivalent versions of GLSL
+class TVersionGLSL : public TIntermTraverser
+{
+  public:
+    TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output);
+
+    // If output is core profile, returns 150.
+    // If output is legacy profile,
+    //   Returns 120 if the following is used the shader:
+    //   - "invariant",
+    //   - "gl_PointCoord",
+    //   - matrix/matrix constructors
+    //   - array "out" parameters
+    //   Else 110 is returned.
+    int getVersion() const { return mVersion; }
+
+    void visitSymbol(TIntermSymbol *node) override;
+    bool visitAggregate(Visit, TIntermAggregate *node) override;
+    bool visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) override;
+    bool visitFunctionPrototype(Visit, TIntermFunctionPrototype *node) override;
+    bool visitDeclaration(Visit, TIntermDeclaration *node) override;
+
+  private:
+    void ensureVersionIsAtLeast(int version);
+
+    int mVersion;
+};
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_VERSIONGLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/blocklayout.cpp b/src/third_party/angle/src/compiler/translator/blocklayout.cpp
new file mode 100644
index 0000000..33090a9
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/blocklayout.cpp
@@ -0,0 +1,134 @@
+//
+// Copyright (c) 2013-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.
+//
+// blocklayout.cpp:
+//   Implementation for block layout classes and methods.
+//
+
+#include "compiler/translator/blocklayout.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+namespace sh
+{
+
+BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0)
+{
+}
+
+BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
+                                               unsigned int arraySize,
+                                               bool isRowMajorMatrix)
+{
+    int arrayStride;
+    int matrixStride;
+
+    getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
+
+    const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent),
+                                     static_cast<int>(arrayStride * BytesPerComponent),
+                                     static_cast<int>(matrixStride * BytesPerComponent),
+                                     isRowMajorMatrix);
+
+    advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
+
+    return memberInfo;
+}
+
+// static
+size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info)
+{
+    return (info.offset / BytesPerComponent) / ComponentsPerRegister;
+}
+
+// static
+size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info)
+{
+    return (info.offset / BytesPerComponent) % ComponentsPerRegister;
+}
+
+void BlockLayoutEncoder::nextRegister()
+{
+    mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
+}
+
+Std140BlockEncoder::Std140BlockEncoder()
+{
+}
+
+void Std140BlockEncoder::enterAggregateType()
+{
+    nextRegister();
+}
+
+void Std140BlockEncoder::exitAggregateType()
+{
+    nextRegister();
+}
+
+void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
+                                            unsigned int arraySize,
+                                            bool isRowMajorMatrix,
+                                            int *arrayStrideOut,
+                                            int *matrixStrideOut)
+{
+    // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
+    ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
+
+    size_t baseAlignment = 0;
+    int matrixStride     = 0;
+    int arrayStride      = 0;
+
+    if (gl::IsMatrixType(type))
+    {
+        baseAlignment = ComponentsPerRegister;
+        matrixStride  = ComponentsPerRegister;
+
+        if (arraySize > 0)
+        {
+            const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
+            arrayStride            = ComponentsPerRegister * numRegisters;
+        }
+    }
+    else if (arraySize > 0)
+    {
+        baseAlignment = ComponentsPerRegister;
+        arrayStride   = ComponentsPerRegister;
+    }
+    else
+    {
+        const int numComponents = gl::VariableComponentCount(type);
+        baseAlignment           = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
+    }
+
+    mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
+
+    *matrixStrideOut = matrixStride;
+    *arrayStrideOut  = arrayStride;
+}
+
+void Std140BlockEncoder::advanceOffset(GLenum type,
+                                       unsigned int arraySize,
+                                       bool isRowMajorMatrix,
+                                       int arrayStride,
+                                       int matrixStride)
+{
+    if (arraySize > 0)
+    {
+        mCurrentOffset += arrayStride * arraySize;
+    }
+    else if (gl::IsMatrixType(type))
+    {
+        ASSERT(matrixStride == ComponentsPerRegister);
+        const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
+        mCurrentOffset += ComponentsPerRegister * numRegisters;
+    }
+    else
+    {
+        mCurrentOffset += gl::VariableComponentCount(type);
+    }
+}
+}
diff --git a/src/third_party/angle/src/compiler/translator/blocklayout.h b/src/third_party/angle/src/compiler/translator/blocklayout.h
new file mode 100644
index 0000000..caa82e6
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/blocklayout.h
@@ -0,0 +1,108 @@
+//
+// Copyright (c) 2013-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.
+//
+// blocklayout.h:
+//   Methods and classes related to uniform layout and packing in GLSL and HLSL.
+//
+
+#ifndef COMMON_BLOCKLAYOUT_H_
+#define COMMON_BLOCKLAYOUT_H_
+
+#include <cstddef>
+#include <vector>
+
+#include "angle_gl.h"
+#include <GLSLANG/ShaderLang.h>
+
+namespace sh
+{
+struct ShaderVariable;
+struct InterfaceBlockField;
+struct Uniform;
+struct Varying;
+struct InterfaceBlock;
+
+struct BlockMemberInfo
+{
+    BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {}
+
+    BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
+        : offset(offset),
+          arrayStride(arrayStride),
+          matrixStride(matrixStride),
+          isRowMajorMatrix(isRowMajorMatrix)
+    {
+    }
+
+    static BlockMemberInfo getDefaultBlockInfo() { return BlockMemberInfo(-1, -1, -1, false); }
+
+    int offset;
+    int arrayStride;
+    int matrixStride;
+    bool isRowMajorMatrix;
+};
+
+class BlockLayoutEncoder
+{
+  public:
+    BlockLayoutEncoder();
+    virtual ~BlockLayoutEncoder() {}
+
+    BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
+
+    size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
+
+    virtual void enterAggregateType() = 0;
+    virtual void exitAggregateType()  = 0;
+
+    static const size_t BytesPerComponent           = 4u;
+    static const unsigned int ComponentsPerRegister = 4u;
+
+    static size_t getBlockRegister(const BlockMemberInfo &info);
+    static size_t getBlockRegisterElement(const BlockMemberInfo &info);
+
+  protected:
+    size_t mCurrentOffset;
+
+    void nextRegister();
+
+    virtual void getBlockLayoutInfo(GLenum type,
+                                    unsigned int arraySize,
+                                    bool isRowMajorMatrix,
+                                    int *arrayStrideOut,
+                                    int *matrixStrideOut) = 0;
+    virtual void advanceOffset(GLenum type,
+                               unsigned int arraySize,
+                               bool isRowMajorMatrix,
+                               int arrayStride,
+                               int matrixStride) = 0;
+};
+
+// Block layout according to the std140 block layout
+// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
+
+class Std140BlockEncoder : public BlockLayoutEncoder
+{
+  public:
+    Std140BlockEncoder();
+
+    void enterAggregateType() override;
+    void exitAggregateType() override;
+
+  protected:
+    void getBlockLayoutInfo(GLenum type,
+                            unsigned int arraySize,
+                            bool isRowMajorMatrix,
+                            int *arrayStrideOut,
+                            int *matrixStrideOut) override;
+    void advanceOffset(GLenum type,
+                       unsigned int arraySize,
+                       bool isRowMajorMatrix,
+                       int arrayStride,
+                       int matrixStride) override;
+};
+}
+
+#endif  // COMMON_BLOCKLAYOUT_H_
diff --git a/src/third_party/angle/src/compiler/translator/blocklayoutHLSL.cpp b/src/third_party/angle/src/compiler/translator/blocklayoutHLSL.cpp
new file mode 100644
index 0000000..39b1a5b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/blocklayoutHLSL.cpp
@@ -0,0 +1,166 @@
+//
+// Copyright (c) 2013-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.
+//
+// blocklayout.cpp:
+//   Implementation for block layout classes and methods.
+//
+
+#include "compiler/translator/blocklayoutHLSL.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+namespace sh
+{
+
+HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices)
+    : mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices)
+{
+}
+
+void HLSLBlockEncoder::enterAggregateType()
+{
+    nextRegister();
+}
+
+void HLSLBlockEncoder::exitAggregateType()
+{
+}
+
+void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
+                                          unsigned int arraySize,
+                                          bool isRowMajorMatrix,
+                                          int *arrayStrideOut,
+                                          int *matrixStrideOut)
+{
+    GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
+
+    // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
+    ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
+
+    int matrixStride = 0;
+    int arrayStride  = 0;
+
+    // if variables are not to be packed, or we're about to
+    // pack a matrix or array, skip to the start of the next
+    // register
+    if (!isPacked() || gl::IsMatrixType(type) || arraySize > 0)
+    {
+        nextRegister();
+    }
+
+    if (gl::IsMatrixType(type))
+    {
+        matrixStride = ComponentsPerRegister;
+
+        if (arraySize > 0)
+        {
+            const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
+            arrayStride            = ComponentsPerRegister * numRegisters;
+        }
+    }
+    else if (arraySize > 0)
+    {
+        arrayStride = ComponentsPerRegister;
+    }
+    else if (isPacked())
+    {
+        int numComponents = gl::VariableComponentCount(type);
+        if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
+        {
+            nextRegister();
+        }
+    }
+
+    *matrixStrideOut = matrixStride;
+    *arrayStrideOut  = arrayStride;
+}
+
+void HLSLBlockEncoder::advanceOffset(GLenum typeIn,
+                                     unsigned int arraySize,
+                                     bool isRowMajorMatrix,
+                                     int arrayStride,
+                                     int matrixStride)
+{
+    GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
+
+    if (arraySize > 0)
+    {
+        mCurrentOffset += arrayStride * (arraySize - 1);
+    }
+
+    if (gl::IsMatrixType(type))
+    {
+        ASSERT(matrixStride == ComponentsPerRegister);
+        const int numRegisters  = gl::MatrixRegisterCount(type, isRowMajorMatrix);
+        const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
+        mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
+        mCurrentOffset += numComponents;
+    }
+    else if (isPacked())
+    {
+        mCurrentOffset += gl::VariableComponentCount(type);
+    }
+    else
+    {
+        mCurrentOffset += ComponentsPerRegister;
+    }
+}
+
+void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
+{
+    mCurrentOffset += (numRegisters * ComponentsPerRegister);
+}
+
+HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(
+    ShShaderOutput outputType)
+{
+    switch (outputType)
+    {
+        case SH_HLSL_3_0_OUTPUT:
+            return ENCODE_LOOSE;
+        case SH_HLSL_4_1_OUTPUT:
+        case SH_HLSL_4_0_FL9_3_OUTPUT:
+            return ENCODE_PACKED;
+        default:
+            UNREACHABLE();
+            return ENCODE_PACKED;
+    }
+}
+
+template <class ShaderVarType>
+void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
+{
+    if (variable.isStruct())
+    {
+        for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
+        {
+            encoder->enterAggregateType();
+
+            for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
+            {
+                HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
+            }
+
+            encoder->exitAggregateType();
+        }
+    }
+    else
+    {
+        // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
+        encoder->encodeType(variable.type, variable.arraySize, false);
+    }
+}
+
+unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
+{
+    HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType), true);
+    HLSLVariableRegisterCount(variable, &encoder);
+
+    const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
+    return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) /
+                                     registerBytes);
+}
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/blocklayoutHLSL.h b/src/third_party/angle/src/compiler/translator/blocklayoutHLSL.h
new file mode 100644
index 0000000..a0220dc
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/blocklayoutHLSL.h
@@ -0,0 +1,68 @@
+//
+// Copyright (c) 2013-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.
+//
+// blocklayout.h:
+//   Methods and classes related to uniform layout and packing in GLSL and HLSL.
+//
+
+#ifndef COMMON_BLOCKLAYOUTHLSL_H_
+#define COMMON_BLOCKLAYOUTHLSL_H_
+
+#include <cstddef>
+#include <vector>
+
+#include "angle_gl.h"
+#include "blocklayout.h"
+#include <GLSLANG/ShaderLang.h>
+
+namespace sh
+{
+// Block layout packed according to the D3D9 or default D3D10+ register packing rules
+// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
+// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED
+// for everything else (D3D10+ constant blocks and all attributes/varyings).
+
+class HLSLBlockEncoder : public BlockLayoutEncoder
+{
+  public:
+    enum HLSLBlockEncoderStrategy
+    {
+        ENCODE_PACKED,
+        ENCODE_LOOSE
+    };
+
+    HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices);
+
+    virtual void enterAggregateType();
+    virtual void exitAggregateType();
+    void skipRegisters(unsigned int numRegisters);
+
+    bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
+
+    static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType);
+
+  protected:
+    virtual void getBlockLayoutInfo(GLenum type,
+                                    unsigned int arraySize,
+                                    bool isRowMajorMatrix,
+                                    int *arrayStrideOut,
+                                    int *matrixStrideOut);
+    virtual void advanceOffset(GLenum type,
+                               unsigned int arraySize,
+                               bool isRowMajorMatrix,
+                               int arrayStride,
+                               int matrixStride);
+
+    HLSLBlockEncoderStrategy mEncoderStrategy;
+    bool mTransposeMatrices;
+};
+
+// This method returns the number of used registers for a ShaderVariable. It is dependent on the
+// HLSLBlockEncoder class to count the number of used registers in a struct (which are individually
+// packed according to the same rules).
+unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType);
+}
+
+#endif  // COMMON_BLOCKLAYOUTHLSL_H_
diff --git a/src/third_party/angle/src/compiler/translator/generate_parser.sh b/src/third_party/angle/src/compiler/translator/generate_parser.sh
new file mode 100644
index 0000000..61eecce
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/generate_parser.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Generates GLSL ES parser - glslang_lex.cpp, glslang_tab.h, and glslang_tab.cpp
+
+run_flex()
+{
+input_file=./$1.l
+output_source=./$1_lex.cpp
+flex --noline --nounistd --outfile=$output_source $input_file
+}
+
+run_bison()
+{
+input_file=./$1.y
+output_header=./$1_tab.h
+output_source=./$1_tab.cpp
+bison --no-lines --skeleton=yacc.c --defines=$output_header --output=$output_source $input_file
+}
+
+script_dir=$(dirname $0)
+
+# Generate Parser
+cd $script_dir
+run_flex glslang
+run_bison glslang
+patch --silent --forward < 64bit-lexer-safety.patch
diff --git a/src/third_party/angle/src/compiler/translator/glslang.h b/src/third_party/angle/src/compiler/translator/glslang.h
new file mode 100644
index 0000000..e54c31b
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/glslang.h
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_GLSLANG_H_
+#define COMPILER_TRANSLATOR_GLSLANG_H_
+
+namespace sh
+{
+class TParseContext;
+}
+
+extern int glslang_initialize(sh::TParseContext *context);
+extern int glslang_finalize(sh::TParseContext *context);
+
+extern int glslang_scan(size_t count,
+                        const char *const string[],
+                        const int length[],
+                        sh::TParseContext *context);
+extern int glslang_parse(sh::TParseContext *context);
+
+#endif  // COMPILER_TRANSLATOR_GLSLANG_H_
diff --git a/src/third_party/angle/src/compiler/translator/glslang.l b/src/third_party/angle/src/compiler/translator/glslang.l
new file mode 100644
index 0000000..c123bc6
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/glslang.l
@@ -0,0 +1,679 @@
+/*
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Lex specification for GLSL ES.
+Based on ANSI C grammar, Lex specification:
+http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
+*/
+
+%top{
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+/* clang-format off */
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4005)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#pragma warning(disable: 4702)
+#endif
+}
+
+%{
+#include "compiler/translator/glslang.h"
+#include "compiler/translator/ParseContext.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/translator/util.h"
+#include "compiler/translator/length_limits.h"
+
+using namespace sh;
+
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+// Workaround for flex using the register keyword, deprecated in C++11.
+#ifdef __cplusplus
+#if __cplusplus > 199711L
+#define register
+#endif
+#endif
+
+#define YY_USER_ACTION                                 \
+    yylloc->first_file = yylloc->last_file = yycolumn; \
+    yylloc->first_line = yylloc->last_line = yylineno;
+
+#define YY_INPUT(buf, result, max_size) \
+    result = string_input(buf, max_size, yyscanner);
+
+static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
+static int check_type(yyscan_t yyscanner);
+static int reserved_word(yyscan_t yyscanner);
+static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
+static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
+static int ES2_ident_ES3_keyword(TParseContext *context, int token);
+static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
+static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
+static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token);
+static int ES3_extension_keyword_else_ident(TParseContext *context, const char *extension, int token);
+static int uint_constant(TParseContext *context);
+static int int_constant(TParseContext *context);
+static int float_constant(yyscan_t yyscanner);
+static int floatsuffix_check(TParseContext* context);
+static int yuvcscstandardext_constant(TParseContext *context);
+%}
+
+%option noyywrap nounput never-interactive
+%option yylineno reentrant bison-bridge bison-locations
+%option extra-type="TParseContext*"
+%x FIELDS
+
+D           [0-9]
+L           [a-zA-Z_]
+H           [a-fA-F0-9]
+E           [Ee][+-]?{D}+
+O           [0-7]
+
+%%
+
+%{
+    TParseContext* context = yyextra;
+%}
+
+"invariant"    { return INVARIANT; }
+"highp"        { return HIGH_PRECISION; }
+"mediump"      { return MEDIUM_PRECISION; }
+"lowp"         { return LOW_PRECISION; }
+"precision"    { return PRECISION; }
+
+"attribute"    { return ES2_keyword_ES3_reserved(context, ATTRIBUTE); }
+"const"        { return CONST_QUAL; }
+"uniform"      { return UNIFORM; }
+"varying"      { return ES2_keyword_ES3_reserved(context, VARYING); }
+
+"break"        { return BREAK; }
+"continue"     { return CONTINUE; }
+"do"           { return DO; }
+"for"          { return FOR; }
+"while"        { return WHILE; }
+
+"if"           { return IF; }
+"else"         { return ELSE; }
+"switch"       { return ES2_reserved_ES3_keyword(context, SWITCH); }
+"case"         { return ES2_ident_ES3_keyword(context, CASE); }
+"default"      { return ES2_reserved_ES3_keyword(context, DEFAULT); }
+
+"centroid"     { return ES2_ident_ES3_keyword(context, CENTROID); }
+"flat"         { return ES2_reserved_ES3_keyword(context, FLAT); }
+"smooth"       { return ES2_ident_ES3_keyword(context, SMOOTH); }
+
+"in"           { return IN_QUAL; }
+"out"          { return OUT_QUAL; }
+"inout"        { return INOUT_QUAL; }
+"shared"       { return ES2_and_ES3_ident_ES3_1_keyword(context, SHARED); }
+
+"float"        { return FLOAT_TYPE; }
+"int"          { return INT_TYPE; }
+"uint"         { return ES2_ident_ES3_keyword(context, UINT_TYPE); }
+"void"         { return VOID_TYPE; }
+"bool"         { return BOOL_TYPE; }
+"true"         { yylval->lex.b = true;  return BOOLCONSTANT; }
+"false"        { yylval->lex.b = false; return BOOLCONSTANT; }
+
+"discard"      { return DISCARD; }
+"return"       { return RETURN; }
+
+"mat2"         { return MATRIX2; }
+"mat3"         { return MATRIX3; }
+"mat4"         { return MATRIX4; }
+
+"mat2x2"         { return ES2_ident_ES3_keyword(context, MATRIX2); }
+"mat3x3"         { return ES2_ident_ES3_keyword(context, MATRIX3); }
+"mat4x4"         { return ES2_ident_ES3_keyword(context, MATRIX4); }
+
+"mat2x3"         { return ES2_ident_ES3_keyword(context, MATRIX2x3); }
+"mat3x2"         { return ES2_ident_ES3_keyword(context, MATRIX3x2); }
+"mat2x4"         { return ES2_ident_ES3_keyword(context, MATRIX2x4); }
+"mat4x2"         { return ES2_ident_ES3_keyword(context, MATRIX4x2); }
+"mat3x4"         { return ES2_ident_ES3_keyword(context, MATRIX3x4); }
+"mat4x3"         { return ES2_ident_ES3_keyword(context, MATRIX4x3); }
+
+"vec2"         { return VEC2; }
+"vec3"         { return VEC3; }
+"vec4"         { return VEC4; }
+"ivec2"        { return IVEC2; }
+"ivec3"        { return IVEC3; }
+"ivec4"        { return IVEC4; }
+"bvec2"        { return BVEC2; }
+"bvec3"        { return BVEC3; }
+"bvec4"        { return BVEC4; }
+"uvec2"        { return ES2_ident_ES3_keyword(context, UVEC2); }
+"uvec3"        { return ES2_ident_ES3_keyword(context, UVEC3); }
+"uvec4"        { return ES2_ident_ES3_keyword(context, UVEC4); }
+
+"sampler2D"            { return SAMPLER2D; }
+"samplerCube"          { return SAMPLERCUBE; }
+"samplerExternalOES"   { return SAMPLER_EXTERNAL_OES; }
+"sampler3D"            { return ES2_reserved_ES3_keyword(context, SAMPLER3D); }
+"sampler3DRect"        { return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); }
+"sampler2DRect"        { return SAMPLER2DRECT; }
+"sampler2DArray"       { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAY); }
+"sampler2DMS"          { return ES2_ident_ES3_reserved_ES3_1_keyword(context, SAMPLER2DMS); }
+"isampler2D"           { return ES2_ident_ES3_keyword(context, ISAMPLER2D); }
+"isampler3D"           { return ES2_ident_ES3_keyword(context, ISAMPLER3D); }
+"isamplerCube"         { return ES2_ident_ES3_keyword(context, ISAMPLERCUBE); }
+"isampler2DArray"      { return ES2_ident_ES3_keyword(context, ISAMPLER2DARRAY); }
+"isampler2DMS"         { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ISAMPLER2DMS); }
+"usampler2D"           { return ES2_ident_ES3_keyword(context, USAMPLER2D); }
+"usampler3D"           { return ES2_ident_ES3_keyword(context, USAMPLER3D); }
+"usamplerCube"         { return ES2_ident_ES3_keyword(context, USAMPLERCUBE); }
+"usampler2DArray"      { return ES2_ident_ES3_keyword(context, USAMPLER2DARRAY); }
+"usampler2DMS"         { return ES2_ident_ES3_reserved_ES3_1_keyword(context, USAMPLER2DMS); }
+"sampler2DShadow"      { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); }
+"samplerCubeShadow"    { return ES2_ident_ES3_keyword(context, SAMPLERCUBESHADOW); }
+"sampler2DArrayShadow" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAYSHADOW); }
+"__samplerExternal2DY2YEXT"   { return ES3_extension_keyword_else_ident(context, "GL_EXT_YUV_target", SAMPLEREXTERNAL2DY2YEXT); }
+
+"struct"       { return STRUCT; }
+
+"layout"  { return ES2_ident_ES3_keyword(context, LAYOUT); }
+
+"yuvCscStandardEXT"    { return ES3_extension_keyword_else_ident(context, "GL_EXT_YUV_target", YUVCSCSTANDARDEXT); }
+"itu_601"              { return yuvcscstandardext_constant(context); }
+"itu_601_full_range"   { return yuvcscstandardext_constant(context); }
+"itu_709"              { return yuvcscstandardext_constant(context); }
+
+"image2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2D); }
+"iimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2D); }
+"uimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2D); }
+"image2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); }
+"iimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); }
+"uimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); }
+"image3D"  { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE3D); }
+"uimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE3D); }
+"iimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE3D); }
+"iimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); }
+"uimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); }
+"imageCube"	{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGECUBE); }
+"readonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, READONLY); }
+"writeonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, WRITEONLY); }
+"coherent" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); }
+"restrict" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); }
+"volatile" { return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); }
+
+    /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
+"resource"          |
+"atomic_uint"       |
+"noperspective"     |
+"patch"             |
+"sample"            |
+"subroutine"        |
+"common"            |
+"partition"         |
+"active"            |
+
+"filter"            |
+"image1D"           |
+"iimage1D"          |
+"uimage1D"          |
+"image1DArray"      |
+"iimage1DArray"     |
+"uimage1DArray"     |
+"image1DShadow"     |
+"image2DShadow"     |
+"image1DArrayShadow" |
+"image2DArrayShadow" |
+"imageBuffer"       |
+"iimageBuffer"      |
+"uimageBuffer"      |
+
+"sampler1DArray"    |
+"sampler1DArrayShadow" |
+"isampler1D"        |
+"isampler1DArray"   |
+"usampler1D"        |
+"usampler1DArray"   |
+"isampler2DRect"    |
+"usampler2DRect"    |
+"samplerBuffer"     |
+"isamplerBuffer"    |
+"usamplerBuffer"    |
+"sampler2DMSArray"  |
+"isampler2DMSArray" |
+"usampler2DMSArray" { 
+    if (context->getShaderVersion() < 300) {
+		yylval->lex.string = NewPoolTString(yytext); 
+	    return check_type(yyscanner); 
+	}
+	return reserved_word(yyscanner);
+}
+
+    /* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */
+"packed"  {
+    if (context->getShaderVersion() >= 300)
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return check_type(yyscanner);
+    }
+
+    return reserved_word(yyscanner);
+}
+
+    /* Reserved keywords */
+"asm"          |
+
+"class"        |
+"union"        |
+"enum"         |
+"typedef"      |
+"template"     |
+"this"         |
+
+"goto"         |
+
+"inline"       |
+"noinline"     |
+"public"       |
+"static"       |
+"extern"       |
+"external"     |
+"interface"    |
+
+"long"         |
+"short"        |
+"double"       |
+"half"         |
+"fixed"        |
+"unsigned"     |
+"superp"       |
+
+"input"        |
+"output"       |
+
+"hvec2"        |
+"hvec3"        |
+"hvec4"        |
+"dvec2"        |
+"dvec3"        |
+"dvec4"        |
+"fvec2"        |
+"fvec3"        |
+"fvec4"        |
+
+"sampler1D"    |
+"sampler1DShadow" |
+"sampler2DRectShadow" |
+
+"sizeof"       |
+"cast"         |
+
+"namespace"    |
+"using"        { return reserved_word(yyscanner); }
+
+{L}({L}|{D})*       {
+   yylval->lex.string = NewPoolTString(yytext); 
+   return check_type(yyscanner);
+}
+
+0[xX]{H}+         { return int_constant(context); }
+0{O}+             { return int_constant(context); }
+{D}+              { return int_constant(context); }
+
+0[xX]{H}+[uU]     { return uint_constant(context); }
+0{O}+[uU]         { return uint_constant(context); }
+{D}+[uU]          { return uint_constant(context); }
+
+{D}+{E}           { return float_constant(yyscanner); }
+{D}+"."{D}*({E})? { return float_constant(yyscanner); }
+"."{D}+({E})?     { return float_constant(yyscanner); }
+
+{D}+{E}[fF]           { return floatsuffix_check(context); }
+{D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); }
+"."{D}+({E})?[fF]     { return floatsuffix_check(context); }
+
+"+="            { return ADD_ASSIGN; }
+"-="            { return SUB_ASSIGN; }
+"*="            { return MUL_ASSIGN; }
+"/="            { return DIV_ASSIGN; }
+"%="            { return MOD_ASSIGN; }
+"<<="           { return LEFT_ASSIGN; }
+">>="           { return RIGHT_ASSIGN; }
+"&="            { return AND_ASSIGN; }
+"^="            { return XOR_ASSIGN; }
+"|="            { return OR_ASSIGN; }
+
+"++"            { return INC_OP; }
+"--"            { return DEC_OP; }
+"&&"            { return AND_OP; }
+"||"            { return OR_OP; }
+"^^"            { return XOR_OP; }
+"<="            { return LE_OP; }
+">="            { return GE_OP; }
+"=="            { return EQ_OP; }
+"!="            { return NE_OP; }
+"<<"            { return LEFT_OP; }
+">>"            { return RIGHT_OP; }
+";"             { return SEMICOLON; }
+("{"|"<%")      { return LEFT_BRACE; }
+("}"|"%>")      { return RIGHT_BRACE; }
+","             { return COMMA; }
+":"             { return COLON; }
+"="             { return EQUAL; }
+"("             { return LEFT_PAREN; }
+")"             { return RIGHT_PAREN; }
+("["|"<:")      { return LEFT_BRACKET; }
+("]"|":>")      { return RIGHT_BRACKET; }
+"."             { BEGIN(FIELDS); return DOT; }
+"!"             { return BANG; }
+"-"             { return DASH; }
+"~"             { return TILDE; }
+"+"             { return PLUS; }
+"*"             { return STAR; }
+"/"             { return SLASH; }
+"%"             { return PERCENT; }
+"<"             { return LEFT_ANGLE; }
+">"             { return RIGHT_ANGLE; }
+"|"             { return VERTICAL_BAR; }
+"^"             { return CARET; }
+"&"             { return AMPERSAND; }
+"?"             { return QUESTION; }
+
+<FIELDS>{L}({L}|{D})* {
+    BEGIN(INITIAL);
+    yylval->lex.string = NewPoolTString(yytext);
+    return FIELD_SELECTION;
+}
+<FIELDS>[ \t\v\f\r] {}
+<FIELDS>. {
+    yyextra->error(*yylloc, "Illegal character at fieldname start", yytext);
+    return 0;
+}
+
+[ \t\v\n\f\r] { }
+<*><<EOF>>    { yyterminate(); }
+<*>.          { assert(false); return 0; }
+
+%%
+
+yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
+    pp::Token token;
+    yyget_extra(yyscanner)->getPreprocessor().lex(&token);
+    yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
+    if (len < max_size)
+        memcpy(buf, token.text.c_str(), len);
+    yyset_column(token.location.file, yyscanner);
+    yyset_lineno(token.location.line, yyscanner);
+
+    if (len >= max_size)
+        YY_FATAL_ERROR("Input buffer overflow");
+    else if (len > 0)
+        buf[len++] = ' ';
+    return len;
+}
+
+int check_type(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+    
+    int token = IDENTIFIER;
+    TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion());
+    if (symbol && symbol->isVariable()) {
+        TVariable* variable = static_cast<TVariable*>(symbol);
+        if (variable->isUserType()) {
+            token = TYPE_NAME;
+        }
+    }
+    yylval->lex.symbol = symbol;
+    return token;
+}
+
+int reserved_word(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+    yyextra->error(*yylloc, "Illegal use of reserved word", yytext);
+    return 0;
+}
+
+int ES2_reserved_ES3_keyword(TParseContext *context, int token)
+{
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    if (context->getShaderVersion() < 300)
+    {
+        return reserved_word(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_keyword_ES3_reserved(TParseContext *context, int token)
+{
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    if (context->getShaderVersion() >= 300)
+    {
+        return reserved_word(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    if (context->getShaderVersion() < 300)
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return check_type(yyscanner);
+    }
+    else if (context->getShaderVersion() == 300)
+    {
+        return reserved_word(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_ident_ES3_keyword(TParseContext *context, int token)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
+    if (context->getShaderVersion() < 300)
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return check_type(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token)
+{
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    if (context->getShaderVersion() < 310)
+    {
+        return reserved_word(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    // not a reserved word in GLSL ES 1.00 and GLSL ES 3.00, so could be used as an identifier/type name
+    if (context->getShaderVersion() < 310)
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return check_type(yyscanner);
+    }
+
+    return token;
+}
+
+int ES3_extension_keyword_else_ident(TParseContext *context, const char* extension, int token)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name
+    if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(extension))
+    {
+        return token;
+    }
+
+    yylval->lex.string = NewPoolTString(yytext);
+    return check_type(yyscanner);
+}
+
+int uint_constant(TParseContext *context)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+
+    if (context->getShaderVersion() < 300)
+    {
+        context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext);
+        return 0;
+    }
+
+    if (!atoi_clamp(yytext, &(yylval->lex.u)))
+        yyextra->error(*yylloc, "Integer overflow", yytext);
+
+    return UINTCONSTANT;
+}
+
+int floatsuffix_check(TParseContext* context)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+
+    if (context->getShaderVersion() < 300)
+    {
+        context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext);
+        return 0;
+    }
+
+    std::string text = yytext;
+    text.resize(text.size() - 1);
+    if (!strtof_clamp(text, &(yylval->lex.f)))
+        yyextra->warning(*yylloc, "Float overflow", yytext);
+
+    return(FLOATCONSTANT);
+}
+
+void yyerror(YYLTYPE* lloc, TParseContext* context, void *scanner, const char* reason) {
+    context->error(*lloc, reason, yyget_text(scanner));
+}
+
+int int_constant(TParseContext *context) {
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+
+    unsigned int u;
+    if (!atoi_clamp(yytext, &u))
+    {
+        if (context->getShaderVersion() >= 300)
+            yyextra->error(*yylloc, "Integer overflow", yytext);
+        else
+            yyextra->warning(*yylloc, "Integer overflow", yytext);
+    }
+    yylval->lex.i = static_cast<int>(u);
+    return INTCONSTANT;
+}
+
+int float_constant(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+    if (!strtof_clamp(yytext, &(yylval->lex.f)))
+        yyextra->warning(*yylloc, "Float overflow", yytext);
+    return FLOATCONSTANT;
+}
+
+int yuvcscstandardext_constant(TParseContext *context)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name
+    if (context->getShaderVersion() >= 300 && context->isExtensionEnabled("GL_EXT_YUV_target"))
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return YUVCSCSTANDARDEXTCONSTANT;
+    }
+
+    yylval->lex.string = NewPoolTString(yytext);
+    return check_type(yyscanner);
+}
+
+int glslang_initialize(TParseContext* context) {
+    yyscan_t scanner = NULL;
+    if (yylex_init_extra(context, &scanner))
+        return 1;
+
+    context->setScanner(scanner);
+    return 0;
+}
+
+int glslang_finalize(TParseContext* context) {
+    yyscan_t scanner = context->getScanner();
+    if (scanner == NULL) return 0;
+    
+    context->setScanner(NULL);
+    yylex_destroy(scanner);
+
+    return 0;
+}
+
+int glslang_scan(size_t count, const char* const string[], const int length[],
+                 TParseContext* context) {
+    yyrestart(NULL, context->getScanner());
+    yyset_column(0, context->getScanner());
+    yyset_lineno(1, context->getScanner());
+
+    // Initialize preprocessor.
+    pp::Preprocessor *preprocessor = &context->getPreprocessor();
+
+    if (!preprocessor->init(count, string, length))
+        return 1;
+
+    // Define extension macros.
+    const TExtensionBehavior& extBehavior = context->extensionBehavior();
+    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+         iter != extBehavior.end(); ++iter) {
+        preprocessor->predefineMacro(iter->first.c_str(), 1);
+    }
+    if (context->getFragmentPrecisionHigh())
+        preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
+
+    preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec()));
+
+    return 0;
+}
diff --git a/src/third_party/angle/src/compiler/translator/glslang.y b/src/third_party/angle/src/compiler/translator/glslang.y
new file mode 100644
index 0000000..d67752c
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/glslang.y
@@ -0,0 +1,1558 @@
+/*
+//
+// 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.
+//
+
+This file contains the Yacc grammar for GLSL ES.
+Based on ANSI C Yacc grammar:
+http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
+*/
+
+%{
+//
+// 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.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// clang-format off
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#pragma warning(disable: 4702)
+#endif
+
+#include "angle_gl.h"
+#include "compiler/translator/Cache.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/ParseContext.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYENABLE_NLS 0
+
+using namespace sh;
+
+%}
+%expect 1 /* One shift reduce conflict because of if | else */
+%parse-param {TParseContext* context}
+%param   {void *scanner}
+%define api.pure full
+%locations
+
+%code requires {
+#define YYLTYPE TSourceLoc
+#define YYLTYPE_IS_DECLARED 1
+}
+
+%union {
+    struct {
+        union {
+            TString *string;
+            float f;
+            int i;
+            unsigned int u;
+            bool b;
+        };
+        TSymbol* symbol;
+    } lex;
+    struct {
+        TOperator op;
+        union {
+            TIntermNode *intermNode;
+            TIntermNodePair nodePair;
+            TIntermFunctionCallOrMethod callOrMethodPair;
+            TIntermTyped *intermTypedNode;
+            TIntermAggregate *intermAggregate;
+            TIntermBlock *intermBlock;
+            TIntermDeclaration *intermDeclaration;
+            TIntermFunctionPrototype *intermFunctionPrototype;
+            TIntermSwitch *intermSwitch;
+            TIntermCase *intermCase;
+        };
+        union {
+            TTypeSpecifierNonArray typeSpecifierNonArray;
+            TPublicType type;
+            TPrecision precision;
+            TLayoutQualifier layoutQualifier;
+            TQualifier qualifier;
+            TFunction *function;
+            TParameter param;
+            TField *field;
+            TFieldList *fieldList;
+            TQualifierWrapperBase *qualifierWrapper;
+            TTypeQualifierBuilder *typeQualifierBuilder;
+        };
+    } interm;
+}
+
+%{
+extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
+extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, const char* reason);
+
+#define YYLLOC_DEFAULT(Current, Rhs, N)                      \
+  do {                                                       \
+      if (N) {                                         \
+        (Current).first_file = YYRHSLOC(Rhs, 1).first_file;  \
+        (Current).first_line = YYRHSLOC(Rhs, 1).first_line;  \
+        (Current).last_file = YYRHSLOC(Rhs, N).last_file;    \
+        (Current).last_line = YYRHSLOC(Rhs, N).last_line;    \
+      }                                                      \
+      else {                                                 \
+        (Current).first_file = YYRHSLOC(Rhs, 0).last_file;   \
+        (Current).first_line = YYRHSLOC(Rhs, 0).last_line;   \
+        (Current).last_file = YYRHSLOC(Rhs, 0).last_file;    \
+        (Current).last_line = YYRHSLOC(Rhs, 0).last_line;    \
+      }                                                      \
+  } while (0)
+
+#define VERTEX_ONLY(S, L) {  \
+    if (context->getShaderType() != GL_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex shaders only ", S);  \
+    }  \
+}
+
+#define FRAG_ONLY(S, L) {  \
+    if (context->getShaderType() != GL_FRAGMENT_SHADER) {  \
+        context->error(L, " supported in fragment shaders only ", S);  \
+    }  \
+}
+
+#define COMPUTE_ONLY(S, L) {  \
+    if (context->getShaderType() != GL_COMPUTE_SHADER) {  \
+        context->error(L, " supported in compute shaders only ", S);  \
+    }  \
+}
+
+#define NON_COMPUTE_ONLY(S, L) {  \
+    if (context->getShaderType() != GL_VERTEX_SHADER && context->getShaderType() != GL_FRAGMENT_SHADER) {  \
+        context->error(L, " supported in vertex and fragment shaders only ", S);  \
+    }  \
+}
+
+#define ES2_ONLY(S, L) {  \
+    if (context->getShaderVersion() != 100) {  \
+        context->error(L, " supported in GLSL ES 1.00 only ", S);  \
+    }  \
+}
+
+#define ES3_OR_NEWER(TOKEN, LINE, REASON) {  \
+    if (context->getShaderVersion() < 300) {  \
+        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only ", TOKEN);  \
+    }  \
+}
+
+#define ES3_1_ONLY(TOKEN, LINE, REASON) {  \
+    if (context->getShaderVersion() != 310) {  \
+        context->error(LINE, REASON " supported in GLSL ES 3.10 only ", TOKEN);  \
+    }  \
+}
+%}
+
+%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
+%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE
+%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
+%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4
+%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
+%token <lex> MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3
+%token <lex> CENTROID FLAT SMOOTH
+%token <lex> READONLY WRITEONLY COHERENT RESTRICT VOLATILE SHARED
+%token <lex> STRUCT VOID_TYPE WHILE
+%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY
+%token <lex> ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY
+%token <lex> USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY
+%token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
+%token <lex> SAMPLER3D SAMPLER3DRECT SAMPLER2DSHADOW SAMPLERCUBESHADOW SAMPLER2DARRAYSHADOW
+%token <lex> SAMPLEREXTERNAL2DY2YEXT
+%token <lex> IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
+%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE
+%token <lex> LAYOUT
+%token <lex> YUVCSCSTANDARDEXT YUVCSCSTANDARDEXTCONSTANT
+
+%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT
+%token <lex> FIELD_SELECTION
+%token <lex> LEFT_OP RIGHT_OP
+%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token <lex> SUB_ASSIGN
+
+%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
+%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
+%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+
+%type <lex> identifier
+%type <interm> assignment_operator unary_operator
+%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
+%type <interm.intermTypedNode> expression integer_expression assignment_expression
+%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
+%type <interm.intermTypedNode> relational_expression equality_expression
+%type <interm.intermTypedNode> conditional_expression constant_expression
+%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
+%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
+%type <interm.intermTypedNode> function_call initializer condition conditionopt
+
+%type <interm.intermBlock> translation_unit
+%type <interm.intermNode> function_definition statement simple_statement
+%type <interm.intermBlock> statement_list compound_statement compound_statement_no_new_scope
+%type <interm.intermNode> declaration_statement selection_statement expression_statement
+%type <interm.intermNode> declaration external_declaration
+%type <interm.intermNode> for_init_statement
+%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermSwitch> switch_statement
+%type <interm.intermCase> case_label
+%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
+%type <interm> single_declaration init_declarator_list
+
+%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+%type <interm.layoutQualifier> layout_qualifier_id_list layout_qualifier_id
+
+%type <interm.type> fully_specified_type type_specifier
+
+%type <interm.precision> precision_qualifier
+%type <interm.layoutQualifier> layout_qualifier
+%type <interm.qualifier> interpolation_qualifier
+%type <interm.qualifierWrapper> storage_qualifier single_type_qualifier invariant_qualifier
+%type <interm.typeQualifierBuilder> type_qualifier
+
+%type <interm.typeSpecifierNonArray> type_specifier_nonarray struct_specifier
+%type <interm.type> type_specifier_no_prec
+%type <interm.field> struct_declarator
+%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm.function> function_header function_declarator function_identifier
+%type <interm.function> function_header_with_parameters function_call_header
+%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
+%type <interm> function_call_or_method
+
+%type <lex> enter_struct
+
+%start translation_unit
+%%
+
+identifier
+    : IDENTIFIER
+    | TYPE_NAME
+
+variable_identifier
+    : IDENTIFIER {
+        // The symbol table search was done in the lexical phase
+        $$ = context->parseVariableIdentifier(@1, $1.string, $1.symbol);
+
+        // don't delete $1.string, it's used by error recovery, and the pool
+        // pop will reclaim the memory
+    }
+    ;
+
+primary_expression
+    : variable_identifier {
+        $$ = $1;
+    }
+    | INTCONSTANT {
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setIConst($1.i);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1);
+    }
+    | UINTCONSTANT {
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setUConst($1.u);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtUInt, EbpUndefined, EvqConst), @1);
+    }
+    | FLOATCONSTANT {
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setFConst($1.f);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
+    }
+    | BOOLCONSTANT {
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setBConst($1.b);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1);
+    }
+    | YUVCSCSTANDARDEXTCONSTANT {
+        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+           context->error(@1, "unsupported value", $1.string->c_str());
+        }
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setYuvCscStandardEXTConst(getYuvCscStandardEXT($1.string->c_str()));
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtYuvCscStandardEXT, EbpUndefined, EvqConst), @1);
+    }
+    | LEFT_PAREN expression RIGHT_PAREN {
+        $$ = $2;
+    }
+    ;
+
+postfix_expression
+    : primary_expression {
+        $$ = $1;
+    }
+    | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
+        $$ = context->addIndexExpression($1, @2, $3);
+    }
+    | function_call {
+        $$ = $1;
+    }
+    | postfix_expression DOT FIELD_SELECTION {
+        $$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3);
+    }
+    | postfix_expression INC_OP {
+        $$ = context->addUnaryMathLValue(EOpPostIncrement, $1, @2);
+    }
+    | postfix_expression DEC_OP {
+        $$ = context->addUnaryMathLValue(EOpPostDecrement, $1, @2);
+    }
+    ;
+
+integer_expression
+    : expression {
+        context->checkIsScalarInteger($1, "[]");
+        $$ = $1;
+    }
+    ;
+
+function_call
+    : function_call_or_method {
+        $$ = context->addFunctionCallOrMethod($1.function, $1.callOrMethodPair.arguments, $1.callOrMethodPair.thisNode, @1);
+    }
+    ;
+
+function_call_or_method
+    : function_call_generic {
+        $$ = $1;
+        $$.callOrMethodPair.thisNode = nullptr;
+    }
+    | postfix_expression DOT function_call_generic {
+        ES3_OR_NEWER("", @3, "methods");
+        $$ = $3;
+        $$.callOrMethodPair.thisNode = $1;
+    }
+    ;
+
+function_call_generic
+    : function_call_header_with_parameters RIGHT_PAREN {
+        $$ = $1;
+    }
+    | function_call_header_no_parameters RIGHT_PAREN {
+        $$ = $1;
+    }
+    ;
+
+function_call_header_no_parameters
+    : function_call_header VOID_TYPE {
+        $$.function = $1;
+        $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
+    }
+    | function_call_header {
+        $$.function = $1;
+        $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
+    }
+    ;
+
+function_call_header_with_parameters
+    : function_call_header assignment_expression {
+        $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
+        $$.function = $1;
+        $$.callOrMethodPair.arguments->push_back($2);
+    }
+    | function_call_header_with_parameters COMMA assignment_expression {
+        $$.function = $1.function;
+        $$.callOrMethodPair.arguments->push_back($3);
+    }
+    ;
+
+function_call_header
+    : function_identifier LEFT_PAREN {
+        $$ = $1;
+    }
+    ;
+
+// Grammar Note:  Constructors look like functions, but are recognized as types.
+
+function_identifier
+    : type_specifier_no_prec {
+        if ($1.array) {
+            ES3_OR_NEWER("[]", @1, "array constructor");
+        }
+        $$ = context->addConstructorFunc($1);
+    }
+    | IDENTIFIER {
+        context->checkIsNotReserved(@1, *$1.string);
+        const TType *type = TCache::getType(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    | FIELD_SELECTION {
+        context->checkIsNotReserved(@1, *$1.string);
+        const TType *type = TCache::getType(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    ;
+
+unary_expression
+    : postfix_expression {
+        $$ = $1;
+    }
+    | INC_OP unary_expression {
+        $$ = context->addUnaryMathLValue(EOpPreIncrement, $2, @1);
+    }
+    | DEC_OP unary_expression {
+        $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1);
+    }
+    | unary_operator unary_expression {
+        if ($1.op != EOpNull) {
+            $$ = context->addUnaryMath($1.op, $2, @1);
+        } else
+            $$ = $2;
+    }
+    ;
+// Grammar Note:  No traditional style type casts.
+
+unary_operator
+    : PLUS  { $$.op = EOpPositive; }
+    | DASH  { $$.op = EOpNegative; }
+    | BANG  { $$.op = EOpLogicalNot; }
+    | TILDE {
+        ES3_OR_NEWER("~", @$, "bit-wise operator");
+        $$.op = EOpBitwiseNot;
+    }
+    ;
+// Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
+
+multiplicative_expression
+    : unary_expression { $$ = $1; }
+    | multiplicative_expression STAR unary_expression {
+        $$ = context->addBinaryMath(EOpMul, $1, $3, @2);
+    }
+    | multiplicative_expression SLASH unary_expression {
+        $$ = context->addBinaryMath(EOpDiv, $1, $3, @2);
+    }
+    | multiplicative_expression PERCENT unary_expression {
+        ES3_OR_NEWER("%", @2, "integer modulus operator");
+        $$ = context->addBinaryMath(EOpIMod, $1, $3, @2);
+    }
+    ;
+
+additive_expression
+    : multiplicative_expression { $$ = $1; }
+    | additive_expression PLUS multiplicative_expression {
+        $$ = context->addBinaryMath(EOpAdd, $1, $3, @2);
+    }
+    | additive_expression DASH multiplicative_expression {
+        $$ = context->addBinaryMath(EOpSub, $1, $3, @2);
+    }
+    ;
+
+shift_expression
+    : additive_expression { $$ = $1; }
+    | shift_expression LEFT_OP additive_expression {
+        ES3_OR_NEWER("<<", @2, "bit-wise operator");
+        $$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2);
+    }
+    | shift_expression RIGHT_OP additive_expression {
+        ES3_OR_NEWER(">>", @2, "bit-wise operator");
+        $$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2);
+    }
+    ;
+
+relational_expression
+    : shift_expression { $$ = $1; }
+    | relational_expression LEFT_ANGLE shift_expression {
+        $$ = context->addBinaryMathBooleanResult(EOpLessThan, $1, $3, @2);
+    }
+    | relational_expression RIGHT_ANGLE shift_expression  {
+        $$ = context->addBinaryMathBooleanResult(EOpGreaterThan, $1, $3, @2);
+    }
+    | relational_expression LE_OP shift_expression  {
+        $$ = context->addBinaryMathBooleanResult(EOpLessThanEqual, $1, $3, @2);
+    }
+    | relational_expression GE_OP shift_expression  {
+        $$ = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, $1, $3, @2);
+    }
+    ;
+
+equality_expression
+    : relational_expression { $$ = $1; }
+    | equality_expression EQ_OP relational_expression  {
+        $$ = context->addBinaryMathBooleanResult(EOpEqual, $1, $3, @2);
+    }
+    | equality_expression NE_OP relational_expression {
+        $$ = context->addBinaryMathBooleanResult(EOpNotEqual, $1, $3, @2);
+    }
+    ;
+
+and_expression
+    : equality_expression { $$ = $1; }
+    | and_expression AMPERSAND equality_expression {
+        ES3_OR_NEWER("&", @2, "bit-wise operator");
+        $$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2);
+    }
+    ;
+
+exclusive_or_expression
+    : and_expression { $$ = $1; }
+    | exclusive_or_expression CARET and_expression {
+        ES3_OR_NEWER("^", @2, "bit-wise operator");
+        $$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2);
+    }
+    ;
+
+inclusive_or_expression
+    : exclusive_or_expression { $$ = $1; }
+    | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
+        ES3_OR_NEWER("|", @2, "bit-wise operator");
+        $$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2);
+    }
+    ;
+
+logical_and_expression
+    : inclusive_or_expression { $$ = $1; }
+    | logical_and_expression AND_OP inclusive_or_expression {
+        $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2);
+    }
+    ;
+
+logical_xor_expression
+    : logical_and_expression { $$ = $1; }
+    | logical_xor_expression XOR_OP logical_and_expression  {
+        $$ = context->addBinaryMathBooleanResult(EOpLogicalXor, $1, $3, @2);
+    }
+    ;
+
+logical_or_expression
+    : logical_xor_expression { $$ = $1; }
+    | logical_or_expression OR_OP logical_xor_expression  {
+        $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2);
+    }
+    ;
+
+conditional_expression
+    : logical_or_expression { $$ = $1; }
+    | logical_or_expression QUESTION expression COLON assignment_expression {
+        $$ = context->addTernarySelection($1, $3, $5, @2);
+    }
+    ;
+
+assignment_expression
+    : conditional_expression { $$ = $1; }
+    | unary_expression assignment_operator assignment_expression {
+        context->checkCanBeLValue(@2, "assign", $1);
+        $$ = context->addAssign($2.op, $1, $3, @2);
+    }
+    ;
+
+assignment_operator
+    : EQUAL        { $$.op = EOpAssign; }
+    | MUL_ASSIGN   { $$.op = EOpMulAssign; }
+    | DIV_ASSIGN   { $$.op = EOpDivAssign; }
+    | MOD_ASSIGN   {
+        ES3_OR_NEWER("%=", @$, "integer modulus operator");
+        $$.op = EOpIModAssign;
+    }
+    | ADD_ASSIGN   { $$.op = EOpAddAssign; }
+    | SUB_ASSIGN   { $$.op = EOpSubAssign; }
+    | LEFT_ASSIGN {
+        ES3_OR_NEWER("<<=", @$, "bit-wise operator");
+        $$.op = EOpBitShiftLeftAssign;
+    }
+    | RIGHT_ASSIGN {
+        ES3_OR_NEWER(">>=", @$, "bit-wise operator");
+        $$.op = EOpBitShiftRightAssign;
+    }
+    | AND_ASSIGN {
+        ES3_OR_NEWER("&=", @$, "bit-wise operator");
+        $$.op = EOpBitwiseAndAssign;
+    }
+    | XOR_ASSIGN {
+        ES3_OR_NEWER("^=", @$, "bit-wise operator");
+        $$.op = EOpBitwiseXorAssign;
+    }
+    | OR_ASSIGN {
+        ES3_OR_NEWER("|=", @$, "bit-wise operator");
+        $$.op = EOpBitwiseOrAssign;
+    }
+    ;
+
+expression
+    : assignment_expression {
+        $$ = $1;
+    }
+    | expression COMMA assignment_expression {
+        $$ = context->addComma($1, $3, @2);
+    }
+    ;
+
+constant_expression
+    : conditional_expression {
+        context->checkIsConst($1);
+        $$ = $1;
+    }
+    ;
+
+enter_struct
+    : IDENTIFIER LEFT_BRACE {
+        context->enterStructDeclaration(@1, *$1.string);
+        $$ = $1;
+    }
+    ;
+
+declaration
+    : function_prototype SEMICOLON {
+        $$ = context->addFunctionPrototypeDeclaration(*($1.function), @1);
+    }
+    | init_declarator_list SEMICOLON {
+        $$ = $1.intermDeclaration;
+    }
+    | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
+        if (($2 == EbpHigh) && (context->getShaderType() == GL_FRAGMENT_SHADER) && !context->getFragmentPrecisionHigh()) {
+            context->error(@1, "precision is not supported in fragment shader", "highp");
+        }
+        if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
+            context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.getBasicType()));
+        }
+        $$ = 0;
+    }
+    | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON {
+        ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
+        $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, NULL, @$, NULL, @$);
+    }
+    | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
+        ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
+        $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, NULL, @$);
+    }
+    | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON {
+        ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
+        $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, $7, @6);
+    }
+    | type_qualifier SEMICOLON {
+        context->parseGlobalLayoutQualifier(*$1);
+        $$ = 0;
+    }
+    | type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant
+    {
+        $$ = context->parseInvariantDeclaration(*$1, @2, $2.string, $2.symbol);
+    }
+    ;
+
+function_prototype
+    : function_declarator RIGHT_PAREN  {
+        $$.function = context->parseFunctionDeclarator(@2, $1);
+        context->exitFunctionDeclaration();
+    }
+    ;
+
+function_declarator
+    : function_header {
+        $$ = $1;
+    }
+    | function_header_with_parameters {
+        $$ = $1;
+    }
+    ;
+
+
+function_header_with_parameters
+    : function_header parameter_declaration {
+        // Add the parameter
+        $$ = $1;
+        if ($2.param.type->getBasicType() != EbtVoid)
+            $1->addParameter($2.param.turnToConst());
+        else
+            delete $2.param.type;
+    }
+    | function_header_with_parameters COMMA parameter_declaration {
+        //
+        // Only first parameter of one-parameter functions can be void
+        // The check for named parameters not being void is done in parameter_declarator
+        //
+        if ($3.param.type->getBasicType() == EbtVoid) {
+            //
+            // This parameter > first is void
+            //
+            context->error(@2, "cannot be an argument type except for '(void)'", "void");
+            delete $3.param.type;
+        } else {
+            // Add the parameter
+            $$ = $1;
+            $1->addParameter($3.param.turnToConst());
+        }
+    }
+    ;
+
+function_header
+    : fully_specified_type IDENTIFIER LEFT_PAREN {
+        $$ = context->parseFunctionHeader($1, $2.string, @2);
+
+        context->symbolTable.push();
+        context->enterFunctionDeclaration();
+    }
+    ;
+
+parameter_declarator
+    // Type + name
+    : type_specifier identifier {
+        if ($1.getBasicType() == EbtVoid) {
+            context->error(@2, "illegal use of type 'void'", $2.string->c_str());
+        }
+        context->checkIsNotReserved(@2, *$2.string);
+        TParameter param = {$2.string, new TType($1)};
+        $$.param = param;
+    }
+    | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        // Check that we can make an array out of this type
+        context->checkIsValidTypeForArray(@3, $1);
+
+        context->checkIsNotReserved(@2, *$2.string);
+
+        unsigned int size = context->checkIsValidArraySize(@3, $4);
+
+        $1.setArraySize(size);
+
+        TType* type = new TType($1);
+        TParameter param = { $2.string, type };
+        $$.param = param;
+    }
+    ;
+
+parameter_declaration
+    //
+    // The only parameter qualifier a parameter can have are
+    // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
+    //
+
+    //
+    // Type + name
+    //
+    : type_qualifier parameter_declarator {
+        $$ = $2;
+        context->checkIsParameterQualifierValid(@2, *$1, $2.param.type);
+    }
+    | parameter_declarator {
+        $$ = $1;
+        $$.param.type->setQualifier(EvqIn);
+    }
+    | type_qualifier parameter_type_specifier {
+        $$ = $2;
+        context->checkIsParameterQualifierValid(@2, *$1, $2.param.type);
+    }
+    | parameter_type_specifier {
+        $$ = $1;
+        $$.param.type->setQualifier(EvqIn);
+    }
+    ;
+
+parameter_type_specifier
+    : type_specifier {
+        TParameter param = { 0, new TType($1) };
+        $$.param = param;
+    }
+    ;
+
+init_declarator_list
+    : single_declaration {
+        $$ = $1;
+    }
+    | init_declarator_list COMMA identifier {
+        $$ = $1;
+        context->parseDeclarator($$.type, @3, *$3.string, $$.intermDeclaration);
+    }
+    | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        $$ = $1;
+        context->parseArrayDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration);
+    }
+    | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
+        ES3_OR_NEWER("[]", @3, "implicitly sized array");
+        $$ = $1;
+        context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, nullptr, @6, $7, $$.intermDeclaration);
+    }
+    | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
+        ES3_OR_NEWER("=", @7, "first-class arrays (array initializer)");
+        $$ = $1;
+        context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, $5, @7, $8, $$.intermDeclaration);
+    }
+    | init_declarator_list COMMA identifier EQUAL initializer {
+        $$ = $1;
+        context->parseInitDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration);
+    }
+    ;
+
+single_declaration
+    : fully_specified_type {
+        $$.type = $1;
+        $$.intermDeclaration = context->parseSingleDeclaration($$.type, @1, "");
+    }
+    | fully_specified_type identifier {
+        $$.type = $1;
+        $$.intermDeclaration = context->parseSingleDeclaration($$.type, @2, *$2.string);
+    }
+    | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        $$.type = $1;
+        $$.intermDeclaration = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, $4);
+    }
+    | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
+        ES3_OR_NEWER("[]", @3, "implicitly sized array");
+        $$.type = $1;
+        $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, nullptr, @5, $6);
+    }
+    | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
+        ES3_OR_NEWER("=", @6, "first-class arrays (array initializer)");
+        $$.type = $1;
+        $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, $4, @6, $7);
+    }
+    | fully_specified_type identifier EQUAL initializer {
+        $$.type = $1;
+        $$.intermDeclaration = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4);
+    }
+    ;
+
+fully_specified_type
+    : type_specifier {
+        context->addFullySpecifiedType(&$1);
+        $$ = $1;
+    }
+    | type_qualifier type_specifier {
+        $$ = context->addFullySpecifiedType(*$1, $2);
+    }
+    ;
+
+interpolation_qualifier
+    : SMOOTH {
+        $$ = EvqSmooth;
+    }
+    | FLAT {
+        $$ = EvqFlat;
+    }
+    ;
+
+type_qualifier
+    : single_type_qualifier {
+        $$ = context->createTypeQualifierBuilder(@1);
+        $$->appendQualifier($1);
+    }
+    | type_qualifier single_type_qualifier {
+        $$ = $1;
+        $$->appendQualifier($2);
+    }
+    ;
+
+invariant_qualifier
+    : INVARIANT {
+        // empty
+    }
+    ;
+
+single_type_qualifier
+    : storage_qualifier {
+        context->checkLocalVariableConstStorageQualifier(*$1);
+        $$ = $1;
+    }
+    | layout_qualifier {
+        context->checkIsAtGlobalLevel(@1, "layout");
+        $$ = new TLayoutQualifierWrapper($1, @1);
+    }
+    | precision_qualifier {
+        $$ = new TPrecisionQualifierWrapper($1, @1);
+    }
+    | interpolation_qualifier {
+        $$ = new TInterpolationQualifierWrapper($1, @1);
+    }
+    | invariant_qualifier {
+        context->checkIsAtGlobalLevel(@1, "invariant");
+        $$ = new TInvariantQualifierWrapper(@1);
+    }
+    ;
+
+
+storage_qualifier
+    :
+    ATTRIBUTE {
+        VERTEX_ONLY("attribute", @1);
+        ES2_ONLY("attribute", @1);
+        context->checkIsAtGlobalLevel(@1, "attribute");
+        $$ = new TStorageQualifierWrapper(EvqAttribute, @1);
+    }
+    | VARYING {
+        ES2_ONLY("varying", @1);
+        context->checkIsAtGlobalLevel(@1, "varying");
+        if (context->getShaderType() == GL_VERTEX_SHADER)
+            $$ = new TStorageQualifierWrapper(EvqVaryingOut, @1);
+        else
+            $$ = new TStorageQualifierWrapper(EvqVaryingIn, @1);
+    }
+    | CONST_QUAL {
+        $$ = new TStorageQualifierWrapper(EvqConst, @1);
+    }
+    | IN_QUAL {
+        if (context->declaringFunction())
+        {
+            $$ = new TStorageQualifierWrapper(EvqIn, @1);
+        }
+        else if (context->getShaderType() == GL_FRAGMENT_SHADER)
+        {
+            ES3_OR_NEWER("in", @1, "storage qualifier");
+            $$ = new TStorageQualifierWrapper(EvqFragmentIn, @1);
+        }
+        else if (context->getShaderType() == GL_VERTEX_SHADER)
+        {
+            ES3_OR_NEWER("in", @1, "storage qualifier");
+            $$ = new TStorageQualifierWrapper(EvqVertexIn, @1);
+        }
+        else
+        {
+            $$ = new TStorageQualifierWrapper(EvqComputeIn, @1);
+        }
+    }
+    | OUT_QUAL {
+        if (context->declaringFunction())
+        {
+            $$ = new TStorageQualifierWrapper(EvqOut, @1);
+        }
+        else
+        {
+            ES3_OR_NEWER("out", @1, "storage qualifier");
+            NON_COMPUTE_ONLY("out", @1);
+            if (context->getShaderType() == GL_FRAGMENT_SHADER)
+            {
+                $$ = new TStorageQualifierWrapper(EvqFragmentOut, @1);
+            }
+            else
+            {
+                $$ = new TStorageQualifierWrapper(EvqVertexOut, @1);
+            }
+        }
+    }
+    | INOUT_QUAL {
+        if (!context->declaringFunction())
+        {
+            context->error(@1, "invalid qualifier: can be only used with function parameters", "inout");
+        }
+        $$ = new TStorageQualifierWrapper(EvqInOut, @1);
+    }
+    | CENTROID {
+        ES3_OR_NEWER("centroid", @1, "storage qualifier");
+        $$ = new TStorageQualifierWrapper(EvqCentroid, @1);
+    }
+    | UNIFORM {
+        context->checkIsAtGlobalLevel(@1, "uniform");
+        $$ = new TStorageQualifierWrapper(EvqUniform, @1);
+    }
+    | READONLY {
+        $$ = new TMemoryQualifierWrapper(EvqReadOnly, @1);
+    }
+    | WRITEONLY {
+        $$ = new TMemoryQualifierWrapper(EvqWriteOnly, @1);
+    }
+    | COHERENT {
+        $$ = new TMemoryQualifierWrapper(EvqCoherent, @1);
+    }
+    | RESTRICT {
+        $$ = new TMemoryQualifierWrapper(EvqRestrict, @1);
+    }
+    | VOLATILE {
+        $$ = new TMemoryQualifierWrapper(EvqVolatile, @1);
+    }
+    | SHARED {
+        context->checkIsAtGlobalLevel(@1, "shared");
+        COMPUTE_ONLY("shared", @1);
+        $$ = new TStorageQualifierWrapper(EvqShared, @1);
+    }
+    ;
+
+type_specifier
+    : type_specifier_no_prec {
+        $$ = $1;
+        $$.precision = context->symbolTable.getDefaultPrecision($1.getBasicType());
+    }
+    ;
+
+precision_qualifier
+    : HIGH_PRECISION {
+        $$ = EbpHigh;
+    }
+    | MEDIUM_PRECISION {
+        $$ = EbpMedium;
+    }
+    | LOW_PRECISION  {
+        $$ = EbpLow;
+    }
+    ;
+
+layout_qualifier
+    : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN {
+        ES3_OR_NEWER("layout", @1, "qualifier");
+        $$ = $3;
+    }
+    ;
+
+layout_qualifier_id_list
+    : layout_qualifier_id {
+        $$ = $1;
+    }
+    | layout_qualifier_id_list COMMA layout_qualifier_id {
+        $$ = context->joinLayoutQualifiers($1, $3, @3);
+    }
+    ;
+
+layout_qualifier_id
+    : IDENTIFIER {
+        $$ = context->parseLayoutQualifier(*$1.string, @1);
+    }
+    | IDENTIFIER EQUAL INTCONSTANT {
+        $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3);
+    }
+    | IDENTIFIER EQUAL UINTCONSTANT {
+        $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3);
+    }
+    | SHARED {
+        $$ = context->parseLayoutQualifier("shared", @1);
+    }
+    ;
+
+type_specifier_no_prec
+    : type_specifier_nonarray {
+        $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+    }
+    | type_specifier_nonarray LEFT_BRACKET RIGHT_BRACKET {
+        ES3_OR_NEWER("[]", @2, "implicitly sized array");
+        $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+        $$.setArraySize(0);
+    }
+    | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+        if (context->checkIsValidTypeForArray(@2, $$))
+        {
+            unsigned int size = context->checkIsValidArraySize(@2, $3);
+            $$.setArraySize(size);
+        }
+    }
+    ;
+
+type_specifier_nonarray
+    : VOID_TYPE {
+        $$.initialize(EbtVoid, @1);
+    }
+    | FLOAT_TYPE {
+        $$.initialize(EbtFloat, @1);
+    }
+    | INT_TYPE {
+        $$.initialize(EbtInt, @1);
+    }
+    | UINT_TYPE {
+        $$.initialize(EbtUInt, @1);
+    }
+    | BOOL_TYPE {
+        $$.initialize(EbtBool, @1);
+    }
+    | VEC2 {
+        $$.initialize(EbtFloat, @1);
+        $$.setAggregate(2);
+    }
+    | VEC3 {
+        $$.initialize(EbtFloat, @1);
+        $$.setAggregate(3);
+    }
+    | VEC4 {
+        $$.initialize(EbtFloat, @1);
+        $$.setAggregate(4);
+    }
+    | BVEC2 {
+        $$.initialize(EbtBool, @1);
+        $$.setAggregate(2);
+    }
+    | BVEC3 {
+        $$.initialize(EbtBool, @1);
+        $$.setAggregate(3);
+    }
+    | BVEC4 {
+        $$.initialize(EbtBool, @1);
+        $$.setAggregate(4);
+    }
+    | IVEC2 {
+        $$.initialize(EbtInt, @1);
+        $$.setAggregate(2);
+    }
+    | IVEC3 {
+        $$.initialize(EbtInt, @1);
+        $$.setAggregate(3);
+    }
+    | IVEC4 {
+        $$.initialize(EbtInt, @1);
+        $$.setAggregate(4);
+    }
+    | UVEC2 {
+        $$.initialize(EbtUInt, @1);
+        $$.setAggregate(2);
+    }
+    | UVEC3 {
+        $$.initialize(EbtUInt, @1);
+        $$.setAggregate(3);
+    }
+    | UVEC4 {
+        $$.initialize(EbtUInt, @1);
+        $$.setAggregate(4);
+    }
+    | MATRIX2 {
+        $$.initialize(EbtFloat, @1);
+        $$.setMatrix(2, 2);
+    }
+    | MATRIX3 {
+        $$.initialize(EbtFloat, @1);
+        $$.setMatrix(3, 3);
+    }
+    | MATRIX4 {
+        $$.initialize(EbtFloat, @1);
+        $$.setMatrix(4, 4);
+    }
+    | MATRIX2x3 {
+        $$.initialize(EbtFloat, @1);
+        $$.setMatrix(2, 3);
+    }
+    | MATRIX3x2 {
+        $$.initialize(EbtFloat, @1);
+        $$.setMatrix(3, 2);
+    }
+    | MATRIX2x4 {
+        $$.initialize(EbtFloat, @1);
+        $$.setMatrix(2, 4);
+    }
+    | MATRIX4x2 {
+        $$.initialize(EbtFloat, @1);
+        $$.setMatrix(4, 2);
+    }
+    | MATRIX3x4 {
+        $$.initialize(EbtFloat, @1);
+        $$.setMatrix(3, 4);
+    }
+    | MATRIX4x3 {
+        $$.initialize(EbtFloat, @1);
+        $$.setMatrix(4, 3);
+    }
+    | YUVCSCSTANDARDEXT {
+        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+            context->error(@1, "unsupported type", "yuvCscStandardEXT");
+        }
+        $$.initialize(EbtYuvCscStandardEXT, @1);
+    }
+    | SAMPLER2D {
+        $$.initialize(EbtSampler2D, @1);
+    }
+    | SAMPLER3D {
+        $$.initialize(EbtSampler3D, @1);
+    }
+    | SAMPLERCUBE {
+        $$.initialize(EbtSamplerCube, @1);
+    }
+    | SAMPLER2DARRAY {
+        $$.initialize(EbtSampler2DArray, @1);
+    }
+    | SAMPLER2DMS {
+        $$.initialize(EbtSampler2DMS, @1);
+    }
+    | ISAMPLER2D {
+        $$.initialize(EbtISampler2D, @1);
+    }
+    | ISAMPLER3D {
+        $$.initialize(EbtISampler3D, @1);
+    }
+    | ISAMPLERCUBE {
+        $$.initialize(EbtISamplerCube, @1);
+    }
+    | ISAMPLER2DARRAY {
+        $$.initialize(EbtISampler2DArray, @1);
+    }
+    | ISAMPLER2DMS {
+        $$.initialize(EbtISampler2DMS, @1);
+    }
+    | USAMPLER2D {
+        $$.initialize(EbtUSampler2D, @1);
+    }
+    | USAMPLER3D {
+        $$.initialize(EbtUSampler3D, @1);
+    }
+    | USAMPLERCUBE {
+        $$.initialize(EbtUSamplerCube, @1);
+    }
+    | USAMPLER2DARRAY {
+        $$.initialize(EbtUSampler2DArray, @1);
+    }
+    | USAMPLER2DMS {
+        $$.initialize(EbtUSampler2DMS, @1);
+    }
+    | SAMPLER2DSHADOW {
+        $$.initialize(EbtSampler2DShadow, @1);
+    }
+    | SAMPLERCUBESHADOW {
+        $$.initialize(EbtSamplerCubeShadow, @1);
+    }
+    | SAMPLER2DARRAYSHADOW {
+        $$.initialize(EbtSampler2DArrayShadow, @1);
+    }
+    | SAMPLER_EXTERNAL_OES {
+        if (!context->supportsExtension("GL_OES_EGL_image_external") &&
+            !context->supportsExtension("GL_NV_EGL_stream_consumer_external")) {
+            context->error(@1, "unsupported type", "samplerExternalOES");
+        }
+        $$.initialize(EbtSamplerExternalOES, @1);
+    }
+    | SAMPLEREXTERNAL2DY2YEXT {
+        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+            context->error(@1, "unsupported type", "__samplerExternal2DY2YEXT");
+        }
+        $$.initialize(EbtSamplerExternal2DY2YEXT, @1);
+    }
+    | SAMPLER2DRECT {
+        if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
+            context->error(@1, "unsupported type", "sampler2DRect");
+        }
+        $$.initialize(EbtSampler2DRect, @1);
+    }
+    | struct_specifier {
+        $$ = $1;
+    }
+    | IMAGE2D {
+        $$.initialize(EbtImage2D, @1);
+    }
+    | IIMAGE2D {
+        $$.initialize(EbtIImage2D, @1);
+    }
+    | UIMAGE2D {
+        $$.initialize(EbtUImage2D, @1);
+    }
+    | IMAGE3D {
+        $$.initialize(EbtImage3D, @1);
+    }
+    | IIMAGE3D {
+        $$.initialize(EbtIImage3D, @1);
+    }
+    | UIMAGE3D {
+        $$.initialize(EbtUImage3D, @1);
+    }
+    | IMAGE2DARRAY {
+        $$.initialize(EbtImage2DArray, @1);
+    }
+    | IIMAGE2DARRAY {
+        $$.initialize(EbtIImage2DArray, @1);
+    }
+    | UIMAGE2DARRAY {
+        $$.initialize(EbtUImage2DArray, @1);
+    }
+    | IMAGECUBE {
+        $$.initialize(EbtImageCube, @1);
+    }
+    | IIMAGECUBE {
+        $$.initialize(EbtIImageCube, @1);
+    }
+    | UIMAGECUBE {
+        $$.initialize(EbtUImageCube, @1);
+    }
+    | TYPE_NAME {
+        //
+        // This is for user defined type names.  The lexical phase looked up the
+        // type.
+        //
+        TType& structure = static_cast<TVariable*>($1.symbol)->getType();
+        $$.initialize(EbtStruct, @1);
+        $$.userDef = &structure;
+    }
+    ;
+
+struct_specifier
+    : STRUCT identifier LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE {
+        $$ = context->addStructure(@1, @2, $2.string, $5);
+    }
+    | STRUCT LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE {
+        $$ = context->addStructure(@1, @$, NewPoolTString(""), $4);
+    }
+    ;
+
+struct_declaration_list
+    : struct_declaration {
+        $$ = $1;
+    }
+    | struct_declaration_list struct_declaration {
+        $$ = context->combineStructFieldLists($1, $2, @2);
+    }
+    ;
+
+struct_declaration
+    : type_specifier struct_declarator_list SEMICOLON {
+        $$ = context->addStructDeclaratorList($1, $2);
+    }
+    | type_qualifier type_specifier struct_declarator_list SEMICOLON {
+        // ES3 Only, but errors should be handled elsewhere
+        $$ = context->addStructDeclaratorListWithQualifiers(*$1, &$2, $3);
+    }
+    ;
+
+struct_declarator_list
+    : struct_declarator {
+        $$ = NewPoolTFieldList();
+        $$->push_back($1);
+    }
+    | struct_declarator_list COMMA struct_declarator {
+        $$->push_back($3);
+    }
+    ;
+
+struct_declarator
+    : identifier {
+        context->checkIsNotReserved(@1, *$1.string);
+
+        TType* type = new TType(EbtVoid, EbpUndefined);
+        $$ = new TField(type, $1.string, @1);
+    }
+    | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        context->checkIsNotReserved(@1, *$1.string);
+
+        TType* type = new TType(EbtVoid, EbpUndefined);
+        unsigned int size = context->checkIsValidArraySize(@3, $3);
+        type->setArraySize(size);
+
+        $$ = new TField(type, $1.string, @1);
+    }
+    ;
+
+initializer
+    : assignment_expression { $$ = $1; }
+    ;
+
+declaration_statement
+    : declaration { $$ = $1; }
+    ;
+
+statement
+    : compound_statement  { $$ = $1; }
+    | simple_statement    { $$ = $1; }
+    ;
+
+// Grammar Note:  Labeled statements for SWITCH only; 'goto' is not supported.
+
+simple_statement
+    : declaration_statement { $$ = $1; }
+    | expression_statement  { $$ = $1; }
+    | selection_statement   { $$ = $1; }
+    | switch_statement      { $$ = $1; }
+    | case_label            { $$ = $1; }
+    | iteration_statement   { $$ = $1; }
+    | jump_statement        { $$ = $1; }
+    ;
+
+compound_statement
+    : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+    | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
+        if ($3 != 0) {
+            $3->setLine(@$);
+        }
+        $$ = $3;
+    }
+    ;
+
+statement_no_new_scope
+    : compound_statement_no_new_scope { $$ = $1; }
+    | simple_statement                { $$ = $1; }
+    ;
+
+statement_with_scope
+    : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
+    | { context->symbolTable.push(); } simple_statement                { context->symbolTable.pop(); $$ = $2; }
+    ;
+
+compound_statement_no_new_scope
+    // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+    : LEFT_BRACE RIGHT_BRACE {
+        $$ = 0;
+    }
+    | LEFT_BRACE statement_list RIGHT_BRACE {
+        if ($2) {
+            $2->setLine(@$);
+        }
+        $$ = $2;
+    }
+    ;
+
+statement_list
+    : statement {
+        $$ = new TIntermBlock();
+        $$->setLine(@$);
+        $$->appendStatement($1);
+    }
+    | statement_list statement {
+        $$ = $1;
+        $$->appendStatement($2);
+    }
+    ;
+
+expression_statement
+    : SEMICOLON  { $$ = 0; }
+    | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
+    ;
+
+selection_statement
+    : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
+        context->checkIsScalarBool(@1, $3);
+        $$ = context->intermediate.addIfElse($3, $5, @1);
+    }
+    ;
+
+selection_rest_statement
+    : statement_with_scope ELSE statement_with_scope {
+        $$.node1 = $1;
+        $$.node2 = $3;
+    }
+    | statement_with_scope {
+        $$.node1 = $1;
+        $$.node2 = 0;
+    }
+    ;
+
+switch_statement
+    : SWITCH LEFT_PAREN expression RIGHT_PAREN { context->incrSwitchNestingLevel(); } compound_statement {
+        $$ = context->addSwitch($3, $6, @1);
+        context->decrSwitchNestingLevel();
+    }
+    ;
+
+case_label
+    : CASE constant_expression COLON {
+        $$ = context->addCase($2, @1);
+    }
+    | DEFAULT COLON {
+        $$ = context->addDefault(@1);
+    }
+    ;
+
+condition
+    // In 1996 c++ draft, conditions can include single declarations
+    : expression {
+        $$ = $1;
+        context->checkIsScalarBool($1->getLine(), $1);
+    }
+    | fully_specified_type identifier EQUAL initializer {
+        TIntermBinary *initNode = nullptr;
+        context->checkIsScalarBool(@2, $1);
+
+        if (!context->executeInitializer(@2, *$2.string, $1, $4, &initNode))
+            $$ = $4;
+        else {
+            $$ = 0;
+        }
+    }
+    ;
+
+iteration_statement
+    : WHILE LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } condition RIGHT_PAREN statement_no_new_scope {
+        context->symbolTable.pop();
+        $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
+        context->decrLoopNestingLevel();
+    }
+    | DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+        context->checkIsScalarBool(@8, $6);
+
+        $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
+        context->decrLoopNestingLevel();
+    }
+    | FOR LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+        context->symbolTable.pop();
+        $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
+        context->decrLoopNestingLevel();
+    }
+    ;
+
+for_init_statement
+    : expression_statement {
+        $$ = $1;
+    }
+    | declaration_statement {
+        $$ = $1;
+    }
+    ;
+
+conditionopt
+    : condition {
+        $$ = $1;
+    }
+    | /* May be null */ {
+        $$ = 0;
+    }
+    ;
+
+for_rest_statement
+    : conditionopt SEMICOLON {
+        $$.node1 = $1;
+        $$.node2 = 0;
+    }
+    | conditionopt SEMICOLON expression  {
+        $$.node1 = $1;
+        $$.node2 = $3;
+    }
+    ;
+
+jump_statement
+    : CONTINUE SEMICOLON {
+        $$ = context->addBranch(EOpContinue, @1);
+    }
+    | BREAK SEMICOLON {
+        $$ = context->addBranch(EOpBreak, @1);
+    }
+    | RETURN SEMICOLON {
+        $$ = context->addBranch(EOpReturn, @1);
+    }
+    | RETURN expression SEMICOLON {
+        $$ = context->addBranch(EOpReturn, $2, @1);
+    }
+    | DISCARD SEMICOLON {
+        FRAG_ONLY("discard", @1);
+        $$ = context->addBranch(EOpKill, @1);
+    }
+    ;
+
+// Grammar Note:  No 'goto'.  Gotos are not supported.
+
+translation_unit
+    : external_declaration {
+        $$ = new TIntermBlock();
+        $$->setLine(@$);
+        $$->appendStatement($1);
+        context->setTreeRoot($$);
+    }
+    | translation_unit external_declaration {
+        $$->appendStatement($2);
+    }
+    ;
+
+external_declaration
+    : function_definition {
+        $$ = $1;
+    }
+    | declaration {
+        $$ = $1;
+    }
+    ;
+
+function_definition
+    : function_prototype {
+        context->parseFunctionDefinitionHeader(@1, &($1.function), &($1.intermFunctionPrototype));
+    }
+    compound_statement_no_new_scope {
+        $$ = context->addFunctionDefinition($1.intermFunctionPrototype, $3, @1);
+    }
+    ;
+
+%%
+
+int glslang_parse(TParseContext* context) {
+    return yyparse(context, context->getScanner());
+}
diff --git a/src/third_party/angle/src/compiler/translator/glslang_lex.cpp b/src/third_party/angle/src/compiler/translator/glslang_lex.cpp
new file mode 100644
index 0000000..6d00711
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/glslang_lex.cpp
@@ -0,0 +1,3637 @@
+#line 17 "./glslang.l"
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+/* clang-format off */
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4005)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#pragma warning(disable: 4702)
+#endif
+
+
+
+#line 30 "./glslang_lex.cpp"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 39
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+typedef uint64_t flex_uint64_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                yy_size_t yyl;\
+                for ( yyl = n; yyl < static_cast<yy_site_t>(yyleng); ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    #define YY_LINENO_REWIND_TO(dst) \
+            do {\
+                const char *p;\
+                for ( p = yy_cp-1; p >= (dst); --p)\
+                    if ( *p == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = yyg->yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	yy_size_t yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+static void yyensure_buffer_stack (yyscan_t yyscanner );
+static void yy_load_buffer_state (yyscan_t yyscanner );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(yyscanner) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yyg->yytext_ptr = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyg->yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 246
+#define YY_END_OF_BUFFER 247
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[886] =
+    {   0,
+        0,    0,    0,    0,  247,  245,  244,  244,  228,  234,
+      239,  223,  224,  232,  231,  220,  229,  227,  233,  186,
+      186,  221,  217,  235,  222,  236,  240,  183,  225,  226,
+      238,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  218,  237,  219,  230,  243,  242,  246,
+      241,  214,  200,  219,  208,  203,  198,  206,  196,  207,
+      197,  192,  199,  191,  185,  186,    0,  189,    0,  226,
+      218,  225,  215,  211,  213,  212,  216,  183,  204,  210,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+
+      183,  183,  183,   12,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,   15,  183,  183,
+       23,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  205,  209,  241,    0,
+      195,  191,    0,  194,  188,    0,  190,  184,  201,  202,
+      183,  183,  143,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,   13,  183,  183,  183,
+
+      183,  183,  183,  183,  183,  183,  183,   28,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+       24,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,    0,  192,    0,
+      191,  193,  187,  183,  183,  183,  183,   31,  183,  183,
+       18,  180,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,   16,  146,  183,  183,  183,  183,   21,  183,
+      183,  150,  161,  183,  183,  183,  183,  183,  183,  183,
+
+      183,  183,  183,  183,  183,  183,  158,    4,   36,   37,
+       38,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  149,   32,  183,  183,
+       29,  183,  183,  183,  183,  183,  183,  183,   48,   49,
+       50,   30,  183,  183,  183,  183,  183,  183,  183,  183,
+       10,   54,   55,   56,  183,  144,  183,  183,    7,  183,
+      183,  183,  183,  170,  171,  172,  183,   33,  183,  162,
+       27,  173,  174,  175,    2,  167,  168,  169,  183,  183,
+      183,   25,  165,  183,  183,  183,  183,  183,   51,   52,
+
+       53,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  108,  183,  183,  183,  183,  183,  183,  183,
+      183,  159,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  145,  183,  183,  182,   57,   58,   59,
+      183,  183,   14,  183,  183,  183,  113,  183,  183,  183,
+      183,  111,  183,  183,  183,  160,  155,  114,  183,  183,
+      183,  183,  183,  183,  151,  183,  183,  183,  183,  183,
+       83,   39,   42,   44,   43,   40,   46,   45,   47,   41,
+      183,  183,  183,  183,  166,  142,  183,  183,  153,  183,
+      183,  183,   35,  109,   26,  179,   22,  154,   82,  183,
+
+      164,   17,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,   19,   34,
+      183,  183,  183,  183,  183,  183,  115,   88,   94,  183,
+      183,  183,  183,  183,   85,   87,    3,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  147,  183,
+      183,  183,  183,  183,    8,  183,  183,    9,  183,  183,
+      183,  183,  183,  183,   20,  102,   11,  156,  116,   89,
+       96,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  152,  183,  183,  183,  100,  105,
+      103,  183,  183,  183,  183,  183,  183,  183,  148,  117,
+
+       90,   95,  183,  183,  163,  183,  104,  183,  183,  183,
+      183,    6,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,   99,  157,    1,  183,  183,  183,  183,  183,  183,
+      181,  183,  112,    5,  176,   60,   63,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      101,  183,  183,  183,  183,  183,  183,   97,  183,  183,
+      183,  183,  183,  130,   68,   69,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      110,  183,  183,  183,   98,  132,   73,   74,  183,  183,
+      183,  183,  106,  183,  183,  183,  183,  183,  183,  183,
+
+      125,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,   67,  183,  183,  183,  183,   61,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  126,  118,  183,   91,  183,  183,  183,   72,
+      183,  183,   70,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  127,  183,  183,
+       77,  183,  183,   75,  183,  183,  119,   92,  183,  121,
+      183,  122,  183,  183,  183,  183,  183,  183,  107,  183,
+      183,  183,  183,   65,  183,   64,  136,  183,  183,  120,
+       93,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+
+      183,  183,  183,  134,  137,  183,  128,  183,   66,  183,
+      183,  183,  183,  183,  183,  183,  183,  135,  138,  183,
+      183,  183,  183,  131,   71,  183,  183,  183,  177,  183,
+      183,  183,   78,  183,  183,  133,   76,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  139,  183,  183,  183,
+      183,  183,  183,  183,  183,  140,  183,  183,  183,  183,
+       79,  183,  141,   84,  183,  123,  124,   86,  183,  183,
+      183,   62,  183,  183,  183,  178,  183,  129,   80,  183,
+      183,  183,  183,   81,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        2,    2,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    1,    1,    1,    5,    6,    1,    7,
+        8,    9,   10,   11,   12,   13,   14,   15,   16,   17,
+       18,   19,   20,   21,   22,   23,   24,   25,   26,   27,
+       28,   29,   30,    1,   31,   32,   33,   34,   35,   36,
+       37,   37,   37,   37,   37,   37,   38,   37,   39,   37,
+       37,   40,   41,   42,   43,   37,   37,   44,   45,   37,
+       46,    1,   47,   48,   49,    1,   50,   51,   52,   53,
+
+       54,   55,   56,   57,   58,   37,   59,   60,   61,   62,
+       63,   64,   37,   65,   66,   67,   68,   69,   70,   71,
+       72,   73,   74,   75,   76,   77,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[78] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    2,
+        1,    2,    3,    1,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    1,    1,    1,    1,    1,    1,
+        5,    5,    5,    5,    6,    7,    8,    8,    8,    8,
+        8,    8,    9,    8,    8,    1,    1,    1,    8,    5,
+        5,    5,    5,    6,    7,    8,    8,    8,    8,    8,
+        8,    8,    8,    8,    8,    8,    8,    9,    8,    8,
+        8,    8,    8,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[895] =
+    {   0,
+        0,    0,   77,    0, 1089, 1090, 1090, 1090, 1060,  127,
+      151, 1090, 1090, 1059,  148, 1090,  147,  145, 1058,  167,
+      158, 1056, 1090,  167, 1056,  145, 1090,    0, 1090, 1090,
+      149, 1034,  147,  135,  155,  162,  146,  174, 1019,  172,
+      178,  179,  153,  196, 1013,  198, 1026,  200,  197,  213,
+      202,  113, 1011, 1090,  153, 1090, 1090, 1090, 1090, 1090,
+        0, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090,
+     1090,  237, 1090,  241,  237,  271,  243, 1090,    0, 1090,
+     1090, 1090, 1050, 1090, 1090, 1090, 1049,    0, 1090, 1090,
+     1010, 1008, 1013,  156, 1010, 1018, 1017, 1004, 1007, 1018,
+
+      226, 1012, 1000,  997, 1010,  997,  994,  994, 1000,  189,
+      235,  994, 1004,  990,  996,  999, 1000,    0,  992, 1002,
+      230, 1001,  982,  995,  976,  216,  980,  993,  984,  243,
+      977,  237,  989,  991,  250,  980,  259,  967,  976,  253,
+      259,  980,  976,  978,  967,  970,  250,  255,  269,  979,
+      967,  979,  266,  972,  971,  959, 1090, 1090,    0,  318,
+     1090,  296,  323, 1090, 1090,  325,  324,  286, 1090, 1090,
+      977,  968,    0,  964,  959,  963,  972,  969,  298,  953,
+      953,  964,  956,  271,  966,  963,  963,  961,  958,  950,
+      956,  943,  941,  953,  939,  955,    0,  952,  940,  947,
+
+      944,  948,  949,  942,  939,  928,  927,  940,  943,  931,
+      942,  938,  926,  932,  923,  338,  928,  931,  922,  929,
+      918,  922,  913,  927,  926,  917,  923,  295,  907,  910,
+      908,  907,  917,  907,  902,  900,  902,  912,  898,  900,
+      897,  908,  907,  910,  892,  298,  900,  896,  894,  903,
+      882,  349,  900,  902,  891,  883,  916,  354,  370,  368,
+      383, 1090, 1090,  887,  878,  888,  887,    0,  885,  379,
+        0,    0,  878,  876,  876,  877,  872,  880,  869,  886,
+      875,  382,    0,    0,  869,  879,  878,  878,    0,  863,
+      385,    0,    0,  865,  390,  872,  873,  864,  858,  857,
+
+      858,  857,  857,  342,  393,  852,    0,    0,  848,  847,
+      846,  848,  849,  854,  848,  844,  857,  852,  852,  850,
+      849,  843,  837,  839,  838,  842,  847,  833,  836,  831,
+      839,  844,  832,  829,  841,  832,    0,    0,  838,  834,
+        0,  826,  826,  831,  822,  829,  396,  826,    0,    0,
+        0,    0,  816,  828,  827,  814,  815,  824,  825,  825,
+        0,    0,    0,    0,  812,    0,  820,  811,    0,  810,
+      811,  805,  815,    0,    0,    0,  806,    0,  802,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  812,  400,
+      811,    0,    0,  809,  805,  802,  846,  845,    0,    0,
+
+        0,  792,  403,  409,  412,  797,  793,  798,  789,  787,
+      800,  785,    0,  785,  798,  787,  783,  789,  784,  791,
+      791,    0,  788,  785,  789,  773,  771,  774,  780,  786,
+      781,  780,  768,    0,  770,  771,    0,    0,    0,    0,
+      768,  771,    0,  765,  775,  766,    0,  776,  756,  765,
+      760,    0,  753,  753,  766,    0,  768,    0,  418,  783,
+      782,  781,  746,  745,    0,  762,  761,  756,  793,  784,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      743,  756,  743,  740,    0,    0,  745,  744,    0,  741,
+      748,  747,    0,  733,    0,    0,    0,    0,    0,  730,
+
+        0,    0,  729,  740,  423,  733,  739,  738,  735,  730,
+      727,  747,  733,  718,  718,  731,  716,  728,    0,    0,
+      721,  746,  745,  744,  709,  708,  233,  406,    0,  720,
+      723,  721,  710,  706,  721,    0,    0,  717,  714,  713,
+      703,  702,  692,  709,  695,  426,  703,  706,    0,  725,
+      724,  723,  688,  687,    0,  701,  688,    0,  698,  691,
+      683,  684,  690,  693,    0,    0,    0,    0,  715,  714,
+        0,  689,  692,  677,  684,  675,  682,  683,  683,  682,
+      668,  436,  679,  679,    0,  680,  669,  668,    0,    0,
+        0,  695,  694,  693,  658,  657,  653,  661,    0,  691,
+
+      690,    0,  665,  668,    0,  446,    0,  646,  667,  681,
+      653,    0,  649,  648,  657,  657,  645,  659,  643,  657,
+      652,    0,    0,    0,  671,  670,  669,  634,  633,  632,
+        0,  632,    0,    0,  426,  434,  658,  642,  645,  628,
+      640,  628,  627,  636,  636,  655,  654,  653,  618,  617,
+        0,  622,  612,  615,  616,  615,  625,    0,  628,  624,
+      626,  622,  609,  642,  442,    0,  617,  620,  610,  611,
+      603,  610,  601,  624,  610,  606,  608,  606,  606,  605,
+        0,  593,  592,  602,    0,  624,  445,    0,  599,  602,
+      599,  584,    0,  600,  599,  583,  575,  583,  573,  581,
+
+        0,  578,  577,  600,  586,  584,  584,  577,  567,  570,
+      584,  568,  601,  579,  580,  577,  574,  586,  561,  575,
+      574,  558,  557,  556,  579,  565,  563,  563,  566,  561,
+      542,  541,    0,  571,  541,  569,  539,  543,  542,  575,
+      553,  550,    0,  554,  548,  551,  547,  549,  532,  527,
+      534,  516,  514,  507,  501,  489,  124,    0,  162,  250,
+      289,  307,  327,    0,  329,  340,    0,    0,  366,    0,
+      367,    0,  395,  396,  383,  382,  395,  401,    0,  398,
+      408,  405,  416,  443,  423,    0,    0,  437,  438,    0,
+        0,  439,  440,  426,  425,  428,  441,  433,  446,  447,
+
+      426,  427,  435,    0,    0,  451,  461,  433,  463,  455,
+      449,  437,  455,  449,  438,  439,  447,    0,    0,  478,
+      464,  462,  463,    0,    0,  467,  456,  462,    0,  463,
+      449,  472,    0,  460,  485,    0,    0,  475,  482,  467,
+      465,  466,  458,  475,  482,  483,    0,  481,  465,  501,
+      465,  496,  522,  470,  471,    0,  488,  490,  491,  482,
+        0,  505,    0,    0,  513,    0,    0,    0,  485,  486,
+      480,    0,  506,  482,  483,    0,  537,    0,    0,  510,
+      521,  513,  516,    0, 1090,  556,  562,  568,  574,  578,
+      584,  585,  591,  594
+
+    } ;
+
+static yyconst flex_int16_t yy_def[895] =
+    {   0,
+      885,    1,  885,    3,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      886,  885,  885,  885,  885,  885,  885,  887,  885,  885,
+      885,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  885,  885,  885,  885,  885,  885,  885,
+      888,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  889,  885,  890,   20,  886,  891,  885,  892,  885,
+      885,  885,  885,  885,  885,  885,  885,  887,  885,  885,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  885,  885,  888,  893,
+      885,  890,  894,  885,  885,  885,  891,  892,  885,  885,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  885,  893,  885,
+      894,  885,  885,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,  887,  887,  887,  887,  887,  887,
+      887,  887,  887,  887,    0,  885,  885,  885,  885,  885,
+      885,  885,  885,  885
+
+    } ;
+
+static yyconst flex_int16_t yy_nxt[1168] =
+    {   0,
+        6,    7,    8,    9,   10,   11,   12,   13,   14,   15,
+       16,   17,   18,   19,   20,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   22,   23,   24,   25,   26,   27,
+       28,   28,   28,   28,   28,   28,   28,   28,   28,   28,
+       28,   28,   28,   28,   28,   29,   30,   31,   32,   33,
+       34,   35,   36,   37,   38,   39,   40,   41,   28,   42,
+       43,   44,   45,   46,   47,   48,   49,   50,   51,   52,
+       28,   53,   28,   54,   55,   56,   57,   58,   59,   60,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   61,   61,   61,
+       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
+       61,   61,   58,   58,   58,   61,   61,   61,   61,   61,
+       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
+       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
+       58,   58,   58,   58,   63,   64,   65,   68,   70,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,  154,
+       74,   81,   86,   87,   71,   69,   89,  155,   66,   74,
+      157,   75,   75,   75,   75,   75,   75,   75,   75,   76,
+       76,   82,   77,   83,   84,  791,   90,   95,   92,   96,
+
+       78,   77,  127,   97,   98,  106,  128,  107,   99,   78,
+       79,   77,   93,   94,  100,  102,  108,  101,  174,  103,
+       77,  115,  175,  109,  104,   78,  792,  158,  125,  116,
+      105,  110,  118,  111,   78,  119,  112,   79,  120,  121,
+      117,  126,  113,  122,  123,  129,  124,  132,  193,  136,
+      143,  151,  166,  144,  166,  152,  137,  138,  130,  194,
+      139,  145,  133,  574,  153,  134,  140,  141,  146,  142,
+      147,  160,  161,  575,  148,  163,  164,  214,  149,  165,
+      885,  150,  182,   74,  195,  215,  183,  184,  222,  205,
+      160,  161,  206,  207,  163,  164,  208,  196,  209,  227,
+
+      219,  223,  235,  224,  165,   77,  220,  885,  231,  237,
+      244,  245,  246,   78,  793,  228,  229,  236,  248,  794,
+      247,  232,  238,  253,   77,  254,  249,  258,  263,  258,
+      163,  164,  260,  885,  260,  885,  277,  278,   78,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  163,
+      164,  271,  342,  263,  309,  310,  311,  323,  795,  262,
+      343,  324,  397,  398,  272,  349,  350,  351,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  262,  885,
+      796,  885,  261,  261,  261,  261,  261,  261,  261,  261,
+      261,  261,  885,  797,  885,  362,  363,  364,  374,  375,
+
+      376,  382,  383,  384,  798,  161,  386,  387,  388,  399,
+      400,  401,  438,  439,  440,  460,  461,  462,  164,  472,
+      473,  474,  799,  800,  161,  475,  476,  477,  478,  479,
+      480,  463,  464,  522,  523,  524,  576,  164,  550,  551,
+      552,  592,  593,  594,  801,  802,  577,  803,  804,  525,
+      526,  625,  626,  627,  553,  554,  671,  595,  596,  805,
+      597,  646,  647,  648,  673,  806,  672,  628,  629,  807,
+      808,  674,  703,  675,  676,  724,  809,  649,  650,  704,
+      810,  705,  725,  811,  726,  812,  813,  814,  815,  816,
+      817,  818,  819,  820,  821,  822,  823,  824,  825,  826,
+
+      827,  828,  829,  830,  831,  832,  833,  834,  835,  836,
+      837,  838,  839,  840,  841,  842,  843,  844,  845,  846,
+      847,  848,  849,  850,  851,  852,  853,  854,  855,  856,
+      857,  858,  859,  860,  861,  862,  863,  864,  865,  866,
+      867,  868,  869,  870,  871,  872,  873,  874,  875,  876,
+      877,  878,  879,  880,  881,  882,  883,  884,   76,   76,
+      790,   76,  789,  788,   76,   88,   88,   88,   88,   88,
+       88,  159,  159,  159,  159,  159,  159,   72,  787,   72,
+       72,  162,  786,  162,  162,  167,  785,  167,  168,  168,
+      168,  168,  259,  784,  259,  261,  783,  261,  782,  781,
+
+      780,  779,  778,  777,  776,  775,  774,  773,  772,  771,
+      770,  769,  768,  767,  766,  765,  764,  763,  762,  761,
+      760,  759,  758,  757,  756,  755,  754,  753,  752,  751,
+      750,  749,  748,  747,  746,  745,  744,  743,  742,  741,
+      740,  739,  738,  737,  736,  735,  734,  733,  732,  731,
+      730,  729,  728,  727,  723,  722,  721,  720,  719,  718,
+      717,  716,  715,  714,  713,  712,  711,  710,  709,  708,
+      707,  706,  702,  701,  700,  699,  698,  697,  696,  695,
+      694,  693,  692,  691,  690,  689,  688,  687,  686,  685,
+      684,  683,  682,  681,  680,  679,  678,  677,  670,  669,
+
+      668,  667,  666,  665,  664,  663,  662,  661,  660,  659,
+      658,  657,  656,  655,  654,  653,  652,  651,  645,  644,
+      643,  642,  641,  640,  639,  638,  637,  636,  635,  634,
+      633,  632,  631,  630,  624,  623,  622,  621,  620,  619,
+      618,  617,  616,  615,  614,  613,  612,  611,  610,  609,
+      608,  607,  606,  605,  604,  603,  602,  601,  600,  599,
+      598,  591,  590,  589,  588,  587,  586,  585,  584,  583,
+      582,  581,  580,  579,  578,  573,  572,  571,  570,  569,
+      568,  567,  566,  565,  564,  563,  562,  561,  560,  559,
+      558,  557,  556,  555,  549,  548,  547,  546,  545,  544,
+
+      543,  542,  541,  540,  539,  538,  537,  536,  535,  534,
+      533,  532,  531,  530,  529,  528,  527,  521,  520,  519,
+      518,  517,  516,  515,  514,  513,  512,  511,  510,  509,
+      508,  507,  506,  505,  504,  503,  502,  501,  500,  499,
+      498,  497,  496,  495,  494,  493,  492,  491,  490,  489,
+      488,  487,  486,  485,  484,  483,  482,  481,  471,  470,
+      469,  468,  467,  466,  465,  459,  458,  457,  456,  455,
+      454,  453,  452,  451,  450,  449,  448,  447,  446,  445,
+      444,  443,  442,  441,  437,  436,  435,  434,  433,  432,
+      431,  430,  429,  428,  427,  426,  425,  424,  423,  422,
+
+      421,  420,  419,  418,  417,  416,  415,  414,  413,  412,
+      411,  410,  409,  408,  407,  406,  405,  404,  403,  402,
+      396,  395,  394,  393,  392,  391,  390,  389,  385,  381,
+      380,  379,  378,  377,  373,  372,  371,  370,  369,  368,
+      367,  366,  365,  361,  360,  359,  358,  357,  356,  355,
+      354,  353,  352,  348,  347,  346,  345,  344,  341,  340,
+      339,  338,  337,  336,  335,  334,  333,  332,  331,  330,
+      329,  328,  327,  326,  325,  322,  321,  320,  319,  318,
+      317,  316,  315,  314,  313,  312,  308,  307,  306,  305,
+      304,  303,  302,  301,  300,  299,  298,  297,  296,  295,
+
+      294,  293,  292,  291,  290,  289,  288,  287,  286,  285,
+      284,  283,  282,  281,  280,  279,  276,  275,  274,  273,
+      270,  269,  268,  267,  266,  265,  264,  257,  256,  255,
+      252,  251,  250,  243,  242,  241,  240,  239,  234,  233,
+      230,  226,  225,  221,  218,  217,  216,  213,  212,  211,
+      210,  204,  203,  202,  201,  200,  199,  198,  197,  192,
+      191,  190,  189,  188,  187,  186,  185,  181,  180,  179,
+      178,  177,  176,  173,  172,  171,  170,  169,  156,  135,
+      131,  114,   91,   85,   80,   73,   67,   62,  885,    5,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885
+    } ;
+
+static yyconst flex_int16_t yy_chk[1168] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,   10,   10,   11,   15,   17,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   52,
+       21,   24,   26,   26,   17,   15,   31,   52,   11,   20,
+       55,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,   24,   21,   24,   24,  757,   31,   34,   33,   34,
+
+       21,   20,   43,   34,   35,   37,   43,   37,   35,   20,
+       20,   21,   33,   33,   35,   36,   37,   35,   94,   36,
+       20,   40,   94,   38,   36,   21,  759,   55,   42,   40,
+       36,   38,   41,   38,   20,   41,   38,   20,   41,   41,
+       40,   42,   38,   41,   41,   44,   41,   46,  110,   48,
+       49,   51,   77,   49,   77,   51,   48,   48,   44,  110,
+       48,   49,   46,  527,   51,   46,   48,   48,   49,   48,
+       50,   72,   72,  527,   50,   74,   74,  126,   50,   75,
+       75,   50,  101,   76,  111,  126,  101,  101,  132,  121,
+       72,   72,  121,  121,   74,   74,  121,  111,  121,  135,
+
+      130,  132,  140,  132,   75,   76,  130,   75,  137,  141,
+      147,  147,  148,   76,  760,  135,  135,  140,  149,  761,
+      148,  137,  141,  153,   76,  153,  149,  160,  168,  160,
+      162,  162,  163,  167,  163,  167,  184,  184,   76,  166,
+      166,  166,  166,  166,  166,  166,  166,  166,  166,  162,
+      162,  179,  246,  168,  216,  216,  216,  228,  762,  167,
+      246,  228,  304,  304,  179,  252,  252,  252,  258,  258,
+      258,  258,  258,  258,  258,  258,  258,  258,  167,  259,
+      763,  259,  260,  260,  260,  260,  260,  260,  260,  260,
+      260,  260,  261,  765,  261,  270,  270,  270,  282,  282,
+
+      282,  291,  291,  291,  766,  259,  295,  295,  295,  305,
+      305,  305,  347,  347,  347,  390,  390,  390,  261,  403,
+      403,  403,  769,  771,  259,  404,  404,  404,  405,  405,
+      405,  390,  390,  459,  459,  459,  528,  261,  505,  505,
+      505,  546,  546,  546,  773,  774,  528,  775,  776,  459,
+      459,  582,  582,  582,  505,  505,  635,  546,  546,  777,
+      546,  606,  606,  606,  636,  778,  635,  582,  582,  780,
+      781,  636,  665,  636,  636,  687,  782,  606,  606,  665,
+      783,  665,  687,  784,  687,  785,  788,  789,  792,  793,
+      794,  795,  796,  797,  798,  799,  800,  801,  802,  803,
+
+      806,  807,  808,  809,  810,  811,  812,  813,  814,  815,
+      816,  817,  820,  821,  822,  823,  826,  827,  828,  830,
+      831,  832,  834,  835,  838,  839,  840,  841,  842,  843,
+      844,  845,  846,  848,  849,  850,  851,  852,  853,  854,
+      855,  857,  858,  859,  860,  862,  865,  869,  870,  871,
+      873,  874,  875,  877,  880,  881,  882,  883,  886,  886,
+      756,  886,  755,  754,  886,  887,  887,  887,  887,  887,
+      887,  888,  888,  888,  888,  888,  888,  889,  753,  889,
+      889,  890,  752,  890,  890,  891,  751,  891,  892,  892,
+      892,  892,  893,  750,  893,  894,  749,  894,  748,  747,
+
+      746,  745,  744,  742,  741,  740,  739,  738,  737,  736,
+      735,  734,  732,  731,  730,  729,  728,  727,  726,  725,
+      724,  723,  722,  721,  720,  719,  718,  717,  716,  715,
+      714,  713,  712,  711,  710,  709,  708,  707,  706,  705,
+      704,  703,  702,  700,  699,  698,  697,  696,  695,  694,
+      692,  691,  690,  689,  686,  684,  683,  682,  680,  679,
+      678,  677,  676,  675,  674,  673,  672,  671,  670,  669,
+      668,  667,  664,  663,  662,  661,  660,  659,  657,  656,
+      655,  654,  653,  652,  650,  649,  648,  647,  646,  645,
+      644,  643,  642,  641,  640,  639,  638,  637,  632,  630,
+
+      629,  628,  627,  626,  625,  621,  620,  619,  618,  617,
+      616,  615,  614,  613,  611,  610,  609,  608,  604,  603,
+      601,  600,  598,  597,  596,  595,  594,  593,  592,  588,
+      587,  586,  584,  583,  581,  580,  579,  578,  577,  576,
+      575,  574,  573,  572,  570,  569,  564,  563,  562,  561,
+      560,  559,  557,  556,  554,  553,  552,  551,  550,  548,
+      547,  545,  544,  543,  542,  541,  540,  539,  538,  535,
+      534,  533,  532,  531,  530,  526,  525,  524,  523,  522,
+      521,  518,  517,  516,  515,  514,  513,  512,  511,  510,
+      509,  508,  507,  506,  504,  503,  500,  494,  492,  491,
+
+      490,  488,  487,  484,  483,  482,  481,  470,  469,  468,
+      467,  466,  464,  463,  462,  461,  460,  457,  455,  454,
+      453,  451,  450,  449,  448,  446,  445,  444,  442,  441,
+      436,  435,  433,  432,  431,  430,  429,  428,  427,  426,
+      425,  424,  423,  421,  420,  419,  418,  417,  416,  415,
+      414,  412,  411,  410,  409,  408,  407,  406,  402,  398,
+      397,  396,  395,  394,  391,  389,  379,  377,  373,  372,
+      371,  370,  368,  367,  365,  360,  359,  358,  357,  356,
+      355,  354,  353,  348,  346,  345,  344,  343,  342,  340,
+      339,  336,  335,  334,  333,  332,  331,  330,  329,  328,
+
+      327,  326,  325,  324,  323,  322,  321,  320,  319,  318,
+      317,  316,  315,  314,  313,  312,  311,  310,  309,  306,
+      303,  302,  301,  300,  299,  298,  297,  296,  294,  290,
+      288,  287,  286,  285,  281,  280,  279,  278,  277,  276,
+      275,  274,  273,  269,  267,  266,  265,  264,  257,  256,
+      255,  254,  253,  251,  250,  249,  248,  247,  245,  244,
+      243,  242,  241,  240,  239,  238,  237,  236,  235,  234,
+      233,  232,  231,  230,  229,  227,  226,  225,  224,  223,
+      222,  221,  220,  219,  218,  217,  215,  214,  213,  212,
+      211,  210,  209,  208,  207,  206,  205,  204,  203,  202,
+
+      201,  200,  199,  198,  196,  195,  194,  193,  192,  191,
+      190,  189,  188,  187,  186,  185,  183,  182,  181,  180,
+      178,  177,  176,  175,  174,  172,  171,  156,  155,  154,
+      152,  151,  150,  146,  145,  144,  143,  142,  139,  138,
+      136,  134,  133,  131,  129,  128,  127,  125,  124,  123,
+      122,  120,  119,  117,  116,  115,  114,  113,  112,  109,
+      108,  107,  106,  105,  104,  103,  102,  100,   99,   98,
+       97,   96,   95,   93,   92,   91,   87,   83,   53,   47,
+       45,   39,   32,   25,   22,   19,   14,    9,    5,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885,  885,  885,  885,
+      885,  885,  885,  885,  885,  885,  885
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[247] =
+    {   0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 1, 0, 0,     };
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+/*
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Lex specification for GLSL ES.
+Based on ANSI C grammar, Lex specification:
+http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
+*/
+
+#include "compiler/translator/glslang.h"
+#include "compiler/translator/ParseContext.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/translator/util.h"
+#include "compiler/translator/length_limits.h"
+
+using namespace sh;
+
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+// Workaround for flex using the register keyword, deprecated in C++11.
+#ifdef __cplusplus
+#if __cplusplus > 199711L
+#define register
+#endif
+#endif
+
+#define YY_USER_ACTION                                 \
+    yylloc->first_file = yylloc->last_file = yycolumn; \
+    yylloc->first_line = yylloc->last_line = yylineno;
+
+#define YY_INPUT(buf, result, max_size) \
+    result = string_input(buf, max_size, yyscanner);
+
+static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
+static int check_type(yyscan_t yyscanner);
+static int reserved_word(yyscan_t yyscanner);
+static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
+static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
+static int ES2_ident_ES3_keyword(TParseContext *context, int token);
+static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
+static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
+static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token);
+static int ES3_extension_keyword_else_ident(TParseContext *context, const char *extension, int token);
+static int uint_constant(TParseContext *context);
+static int int_constant(TParseContext *context);
+static int float_constant(yyscan_t yyscanner);
+static int floatsuffix_check(TParseContext* context);
+static int yuvcscstandardext_constant(TParseContext *context);
+
+#define INITIAL 0
+#define FIELDS 1
+
+#define YY_EXTRA_TYPE TParseContext*
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    yy_size_t yy_n_chars;
+    yy_size_t yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    YYLTYPE * yylloc_r;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+    #    define yylloc yyg->yylloc_r
+    
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out  (FILE * out_str ,yyscan_t yyscanner );
+
+yy_size_t yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+int yyget_column  (yyscan_t yyscanner );
+
+void yyset_column (int column_no ,yyscan_t yyscanner );
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner );
+
+void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+       YYLTYPE *yyget_lloc (yyscan_t yyscanner );
+    
+        void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+    
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex \
+               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int yylex \
+               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    yylval = yylval_param;
+
+    yylloc = yylloc_param;
+
+	if ( !yyg->yy_init )
+		{
+		yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yyg->yy_start )
+			yyg->yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack (yyscanner);
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+		}
+
+		yy_load_buffer_state(yyscanner );
+		}
+
+	{
+
+    TParseContext* context = yyextra;
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yyg->yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yyg->yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yyg->yy_start;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+			if ( yy_accept[yy_current_state] )
+				{
+				yyg->yy_last_accepting_state = yy_current_state;
+				yyg->yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 886 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_current_state != 885 );
+		yy_cp = yyg->yy_last_accepting_cpos;
+		yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			yy_size_t yyl;
+			for ( yyl = 0; yyl < static_cast<yy_size_t>(yyleng); ++yyl )
+				if ( yytext[yyl] == '\n' )
+					   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yyg->yy_hold_char;
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+{ return INVARIANT; }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+{ return HIGH_PRECISION; }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+{ return MEDIUM_PRECISION; }
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+{ return LOW_PRECISION; }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+{ return PRECISION; }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+{ return ES2_keyword_ES3_reserved(context, ATTRIBUTE); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+{ return CONST_QUAL; }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+{ return UNIFORM; }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+{ return ES2_keyword_ES3_reserved(context, VARYING); }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+{ return BREAK; }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+{ return CONTINUE; }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+{ return DO; }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+{ return FOR; }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+{ return WHILE; }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+{ return IF; }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+{ return ELSE; }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+{ return ES2_reserved_ES3_keyword(context, SWITCH); }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, CASE); }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+{ return ES2_reserved_ES3_keyword(context, DEFAULT); }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, CENTROID); }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+{ return ES2_reserved_ES3_keyword(context, FLAT); }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, SMOOTH); }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+{ return IN_QUAL; }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+{ return OUT_QUAL; }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+{ return INOUT_QUAL; }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+{ return ES2_and_ES3_ident_ES3_1_keyword(context, SHARED); }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+{ return FLOAT_TYPE; }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+{ return INT_TYPE; }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, UINT_TYPE); }
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+{ return VOID_TYPE; }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+{ return BOOL_TYPE; }
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+{ yylval->lex.b = true;  return BOOLCONSTANT; }
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+{ yylval->lex.b = false; return BOOLCONSTANT; }
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+{ return DISCARD; }
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+{ return RETURN; }
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+{ return MATRIX2; }
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+{ return MATRIX3; }
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+{ return MATRIX4; }
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, MATRIX2); }
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, MATRIX3); }
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, MATRIX4); }
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, MATRIX2x3); }
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, MATRIX3x2); }
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, MATRIX2x4); }
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, MATRIX4x2); }
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, MATRIX3x4); }
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, MATRIX4x3); }
+	YY_BREAK
+case 48:
+YY_RULE_SETUP
+{ return VEC2; }
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+{ return VEC3; }
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+{ return VEC4; }
+	YY_BREAK
+case 51:
+YY_RULE_SETUP
+{ return IVEC2; }
+	YY_BREAK
+case 52:
+YY_RULE_SETUP
+{ return IVEC3; }
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+{ return IVEC4; }
+	YY_BREAK
+case 54:
+YY_RULE_SETUP
+{ return BVEC2; }
+	YY_BREAK
+case 55:
+YY_RULE_SETUP
+{ return BVEC3; }
+	YY_BREAK
+case 56:
+YY_RULE_SETUP
+{ return BVEC4; }
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, UVEC2); }
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, UVEC3); }
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, UVEC4); }
+	YY_BREAK
+case 60:
+YY_RULE_SETUP
+{ return SAMPLER2D; }
+	YY_BREAK
+case 61:
+YY_RULE_SETUP
+{ return SAMPLERCUBE; }
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+{ return SAMPLER_EXTERNAL_OES; }
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+{ return ES2_reserved_ES3_keyword(context, SAMPLER3D); }
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+{ return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); }
+	YY_BREAK
+case 65:
+YY_RULE_SETUP
+{ return SAMPLER2DRECT; }
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, SAMPLER2DARRAY); }
+	YY_BREAK
+case 67:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, SAMPLER2DMS); }
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, ISAMPLER2D); }
+	YY_BREAK
+case 69:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, ISAMPLER3D); }
+	YY_BREAK
+case 70:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, ISAMPLERCUBE); }
+	YY_BREAK
+case 71:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, ISAMPLER2DARRAY); }
+	YY_BREAK
+case 72:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, ISAMPLER2DMS); }
+	YY_BREAK
+case 73:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, USAMPLER2D); }
+	YY_BREAK
+case 74:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, USAMPLER3D); }
+	YY_BREAK
+case 75:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, USAMPLERCUBE); }
+	YY_BREAK
+case 76:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, USAMPLER2DARRAY); }
+	YY_BREAK
+case 77:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, USAMPLER2DMS); }
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+{ return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); }
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, SAMPLERCUBESHADOW); }
+	YY_BREAK
+case 80:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, SAMPLER2DARRAYSHADOW); }
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+{ return ES3_extension_keyword_else_ident(context, "GL_EXT_YUV_target", SAMPLEREXTERNAL2DY2YEXT); }
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+{ return STRUCT; }
+	YY_BREAK
+case 83:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_keyword(context, LAYOUT); }
+	YY_BREAK
+case 84:
+YY_RULE_SETUP
+{ return ES3_extension_keyword_else_ident(context, "GL_EXT_YUV_target", YUVCSCSTANDARDEXT); }
+	YY_BREAK
+case 85:
+YY_RULE_SETUP
+{ return yuvcscstandardext_constant(context); }
+	YY_BREAK
+case 86:
+YY_RULE_SETUP
+{ return yuvcscstandardext_constant(context); }
+	YY_BREAK
+case 87:
+YY_RULE_SETUP
+{ return yuvcscstandardext_constant(context); }
+	YY_BREAK
+case 88:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2D); }
+	YY_BREAK
+case 89:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2D); }
+	YY_BREAK
+case 90:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2D); }
+	YY_BREAK
+case 91:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); }
+	YY_BREAK
+case 92:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); }
+	YY_BREAK
+case 93:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); }
+	YY_BREAK
+case 94:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE3D); }
+	YY_BREAK
+case 95:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE3D); }
+	YY_BREAK
+case 96:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE3D); }
+	YY_BREAK
+case 97:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); }
+	YY_BREAK
+case 98:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); }
+	YY_BREAK
+case 99:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGECUBE); }
+	YY_BREAK
+case 100:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, READONLY); }
+	YY_BREAK
+case 101:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, WRITEONLY); }
+	YY_BREAK
+case 102:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); }
+	YY_BREAK
+case 103:
+YY_RULE_SETUP
+{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); }
+	YY_BREAK
+case 104:
+YY_RULE_SETUP
+{ return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); }
+	YY_BREAK
+/* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
+case 105:
+case 106:
+case 107:
+case 108:
+case 109:
+case 110:
+case 111:
+case 112:
+case 113:
+case 114:
+case 115:
+case 116:
+case 117:
+case 118:
+case 119:
+case 120:
+case 121:
+case 122:
+case 123:
+case 124:
+case 125:
+case 126:
+case 127:
+case 128:
+case 129:
+case 130:
+case 131:
+case 132:
+case 133:
+case 134:
+case 135:
+case 136:
+case 137:
+case 138:
+case 139:
+case 140:
+case 141:
+YY_RULE_SETUP
+{ 
+    if (context->getShaderVersion() < 300) {
+		yylval->lex.string = NewPoolTString(yytext); 
+	    return check_type(yyscanner); 
+	}
+	return reserved_word(yyscanner);
+}
+	YY_BREAK
+/* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */
+case 142:
+YY_RULE_SETUP
+{
+    if (context->getShaderVersion() >= 300)
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return check_type(yyscanner);
+    }
+
+    return reserved_word(yyscanner);
+}
+	YY_BREAK
+/* Reserved keywords */
+case 143:
+case 144:
+case 145:
+case 146:
+case 147:
+case 148:
+case 149:
+case 150:
+case 151:
+case 152:
+case 153:
+case 154:
+case 155:
+case 156:
+case 157:
+case 158:
+case 159:
+case 160:
+case 161:
+case 162:
+case 163:
+case 164:
+case 165:
+case 166:
+case 167:
+case 168:
+case 169:
+case 170:
+case 171:
+case 172:
+case 173:
+case 174:
+case 175:
+case 176:
+case 177:
+case 178:
+case 179:
+case 180:
+case 181:
+case 182:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 183:
+YY_RULE_SETUP
+{
+   yylval->lex.string = NewPoolTString(yytext); 
+   return check_type(yyscanner);
+}
+	YY_BREAK
+case 184:
+YY_RULE_SETUP
+{ return int_constant(context); }
+	YY_BREAK
+case 185:
+YY_RULE_SETUP
+{ return int_constant(context); }
+	YY_BREAK
+case 186:
+YY_RULE_SETUP
+{ return int_constant(context); }
+	YY_BREAK
+case 187:
+YY_RULE_SETUP
+{ return uint_constant(context); }
+	YY_BREAK
+case 188:
+YY_RULE_SETUP
+{ return uint_constant(context); }
+	YY_BREAK
+case 189:
+YY_RULE_SETUP
+{ return uint_constant(context); }
+	YY_BREAK
+case 190:
+YY_RULE_SETUP
+{ return float_constant(yyscanner); }
+	YY_BREAK
+case 191:
+YY_RULE_SETUP
+{ return float_constant(yyscanner); }
+	YY_BREAK
+case 192:
+YY_RULE_SETUP
+{ return float_constant(yyscanner); }
+	YY_BREAK
+case 193:
+YY_RULE_SETUP
+{ return floatsuffix_check(context); }
+	YY_BREAK
+case 194:
+YY_RULE_SETUP
+{ return floatsuffix_check(context); }
+	YY_BREAK
+case 195:
+YY_RULE_SETUP
+{ return floatsuffix_check(context); }
+	YY_BREAK
+case 196:
+YY_RULE_SETUP
+{ return ADD_ASSIGN; }
+	YY_BREAK
+case 197:
+YY_RULE_SETUP
+{ return SUB_ASSIGN; }
+	YY_BREAK
+case 198:
+YY_RULE_SETUP
+{ return MUL_ASSIGN; }
+	YY_BREAK
+case 199:
+YY_RULE_SETUP
+{ return DIV_ASSIGN; }
+	YY_BREAK
+case 200:
+YY_RULE_SETUP
+{ return MOD_ASSIGN; }
+	YY_BREAK
+case 201:
+YY_RULE_SETUP
+{ return LEFT_ASSIGN; }
+	YY_BREAK
+case 202:
+YY_RULE_SETUP
+{ return RIGHT_ASSIGN; }
+	YY_BREAK
+case 203:
+YY_RULE_SETUP
+{ return AND_ASSIGN; }
+	YY_BREAK
+case 204:
+YY_RULE_SETUP
+{ return XOR_ASSIGN; }
+	YY_BREAK
+case 205:
+YY_RULE_SETUP
+{ return OR_ASSIGN; }
+	YY_BREAK
+case 206:
+YY_RULE_SETUP
+{ return INC_OP; }
+	YY_BREAK
+case 207:
+YY_RULE_SETUP
+{ return DEC_OP; }
+	YY_BREAK
+case 208:
+YY_RULE_SETUP
+{ return AND_OP; }
+	YY_BREAK
+case 209:
+YY_RULE_SETUP
+{ return OR_OP; }
+	YY_BREAK
+case 210:
+YY_RULE_SETUP
+{ return XOR_OP; }
+	YY_BREAK
+case 211:
+YY_RULE_SETUP
+{ return LE_OP; }
+	YY_BREAK
+case 212:
+YY_RULE_SETUP
+{ return GE_OP; }
+	YY_BREAK
+case 213:
+YY_RULE_SETUP
+{ return EQ_OP; }
+	YY_BREAK
+case 214:
+YY_RULE_SETUP
+{ return NE_OP; }
+	YY_BREAK
+case 215:
+YY_RULE_SETUP
+{ return LEFT_OP; }
+	YY_BREAK
+case 216:
+YY_RULE_SETUP
+{ return RIGHT_OP; }
+	YY_BREAK
+case 217:
+YY_RULE_SETUP
+{ return SEMICOLON; }
+	YY_BREAK
+case 218:
+YY_RULE_SETUP
+{ return LEFT_BRACE; }
+	YY_BREAK
+case 219:
+YY_RULE_SETUP
+{ return RIGHT_BRACE; }
+	YY_BREAK
+case 220:
+YY_RULE_SETUP
+{ return COMMA; }
+	YY_BREAK
+case 221:
+YY_RULE_SETUP
+{ return COLON; }
+	YY_BREAK
+case 222:
+YY_RULE_SETUP
+{ return EQUAL; }
+	YY_BREAK
+case 223:
+YY_RULE_SETUP
+{ return LEFT_PAREN; }
+	YY_BREAK
+case 224:
+YY_RULE_SETUP
+{ return RIGHT_PAREN; }
+	YY_BREAK
+case 225:
+YY_RULE_SETUP
+{ return LEFT_BRACKET; }
+	YY_BREAK
+case 226:
+YY_RULE_SETUP
+{ return RIGHT_BRACKET; }
+	YY_BREAK
+case 227:
+YY_RULE_SETUP
+{ BEGIN(FIELDS); return DOT; }
+	YY_BREAK
+case 228:
+YY_RULE_SETUP
+{ return BANG; }
+	YY_BREAK
+case 229:
+YY_RULE_SETUP
+{ return DASH; }
+	YY_BREAK
+case 230:
+YY_RULE_SETUP
+{ return TILDE; }
+	YY_BREAK
+case 231:
+YY_RULE_SETUP
+{ return PLUS; }
+	YY_BREAK
+case 232:
+YY_RULE_SETUP
+{ return STAR; }
+	YY_BREAK
+case 233:
+YY_RULE_SETUP
+{ return SLASH; }
+	YY_BREAK
+case 234:
+YY_RULE_SETUP
+{ return PERCENT; }
+	YY_BREAK
+case 235:
+YY_RULE_SETUP
+{ return LEFT_ANGLE; }
+	YY_BREAK
+case 236:
+YY_RULE_SETUP
+{ return RIGHT_ANGLE; }
+	YY_BREAK
+case 237:
+YY_RULE_SETUP
+{ return VERTICAL_BAR; }
+	YY_BREAK
+case 238:
+YY_RULE_SETUP
+{ return CARET; }
+	YY_BREAK
+case 239:
+YY_RULE_SETUP
+{ return AMPERSAND; }
+	YY_BREAK
+case 240:
+YY_RULE_SETUP
+{ return QUESTION; }
+	YY_BREAK
+case 241:
+YY_RULE_SETUP
+{
+    BEGIN(INITIAL);
+    yylval->lex.string = NewPoolTString(yytext);
+    return FIELD_SELECTION;
+}
+	YY_BREAK
+case 242:
+YY_RULE_SETUP
+{}
+	YY_BREAK
+case 243:
+YY_RULE_SETUP
+{
+    yyextra->error(*yylloc, "Illegal character at fieldname start", yytext);
+    return 0;
+}
+	YY_BREAK
+case 244:
+/* rule 244 can match eol */
+YY_RULE_SETUP
+{ }
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(FIELDS):
+{ yyterminate(); }
+	YY_BREAK
+case 245:
+YY_RULE_SETUP
+{ assert(false); return 0; }
+	YY_BREAK
+case 246:
+YY_RULE_SETUP
+ECHO;
+	YY_BREAK
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yyg->yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state( yyscanner );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yyg->yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yyg->yy_last_accepting_cpos;
+				yy_current_state = yyg->yy_last_accepting_state;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer( yyscanner ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yyg->yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap(yyscanner ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yyg->yy_c_buf_p =
+					yyg->yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yyg->yy_c_buf_p =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of user's declarations */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = yyg->yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+	else
+		{
+			yy_size_t num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+			int yy_c_buf_p_offset =
+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				yy_size_t new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						static_cast<int>(number_to_move) - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+        size_t result = 0;
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+            result, num_to_read );
+        yyg->yy_n_chars = static_cast<int>(result);
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	if ( yyg->yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  ,yyscanner);
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	yyg->yy_n_chars += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_current_state = yyg->yy_start;
+
+	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yyg->yy_last_accepting_state = yy_current_state;
+			yyg->yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 886 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+	register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+	register char *yy_cp = yyg->yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yyg->yy_last_accepting_state = yy_current_state;
+		yyg->yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 886 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 885);
+
+	(void)yyg;
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+{
+	int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	*yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			/* This was really a NUL. */
+			*yyg->yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			++yyg->yy_c_buf_p;
+
+			switch ( yy_get_next_buffer( yyscanner ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin ,yyscanner);
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap(yyscanner ) )
+						return EOF;
+
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput(yyscanner);
+#else
+					return input(yyscanner);
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+	if ( c == '\n' )
+		   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack (yyscanner);
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+	yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack (yyscanner);
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state(yyscanner );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void yy_load_buffer_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file ,yyscanner);
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+	yyfree((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+
+{
+	int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_flush_buffer(b ,yyscanner);
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack(yyscanner);
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		yyg->yy_buffer_stack_top++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state(yyscanner );
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+void yypop_buffer_state (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if (yyg->yy_buffer_stack_top > 0)
+		--yyg->yy_buffer_stack_top;
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state(yyscanner );
+		yyg->yy_did_buffer_switch_on_eof = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (yyscan_t yyscanner)
+{
+	yy_size_t num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if (!yyg->yy_buffer_stack) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		yyg->yy_buffer_stack_max = num_to_alloc;
+		yyg->yy_buffer_stack_top = 0;
+		return;
+	}
+
+	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = static_cast<int>(yyg->yy_buffer_stack_max + grow_size);
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+								(yyg->yy_buffer_stack,
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+		yyg->yy_buffer_stack_max = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = static_cast<int>(size) - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b ,yyscanner );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	yy_size_t i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n ,yyscanner );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < static_cast<yy_size_t>(_yybytes_len); ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n ,yyscanner);
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = yyg->yy_hold_char; \
+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+		*yyg->yy_c_buf_p = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE yyget_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+yy_size_t yyget_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *yyget_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           YY_FATAL_ERROR( "yyset_column called with no buffer" );
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int yyget_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * yyget_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+YYLTYPE *yyget_lloc  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylloc;
+}
+    
+void yyset_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylloc = yylloc_param;
+}
+    
+/* User-visible API */
+
+/* yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to yyalloc in
+ * the yyextra field.
+ */
+
+int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    yyset_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+	
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+	
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    yyset_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state(yyscanner);
+	}
+
+	/* Destroy the stack itself. */
+	yyfree(yyg->yy_buffer_stack ,yyscanner);
+	yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        yyfree(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+    /* Destroy the main struct (reentrant only). */
+    yyfree ( yyscanner , yyscanner );
+    yyscanner = NULL;
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size , yyscan_t yyscanner)
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr , yyscan_t yyscanner)
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
+    pp::Token token;
+    yyget_extra(yyscanner)->getPreprocessor().lex(&token);
+    yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
+    if (len < max_size)
+        memcpy(buf, token.text.c_str(), len);
+    yyset_column(token.location.file,yyscanner);
+    yyset_lineno(token.location.line,yyscanner);
+
+    if (len >= max_size)
+        YY_FATAL_ERROR("Input buffer overflow");
+    else if (len > 0)
+        buf[len++] = ' ';
+    return len;
+}
+
+int check_type(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+    
+    int token = IDENTIFIER;
+    TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion());
+    if (symbol && symbol->isVariable()) {
+        TVariable* variable = static_cast<TVariable*>(symbol);
+        if (variable->isUserType()) {
+            token = TYPE_NAME;
+        }
+    }
+    yylval->lex.symbol = symbol;
+    return token;
+}
+
+int reserved_word(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+    yyextra->error(*yylloc, "Illegal use of reserved word", yytext);
+    return 0;
+}
+
+int ES2_reserved_ES3_keyword(TParseContext *context, int token)
+{
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    if (context->getShaderVersion() < 300)
+    {
+        return reserved_word(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_keyword_ES3_reserved(TParseContext *context, int token)
+{
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    if (context->getShaderVersion() >= 300)
+    {
+        return reserved_word(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    if (context->getShaderVersion() < 300)
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return check_type(yyscanner);
+    }
+    else if (context->getShaderVersion() == 300)
+    {
+        return reserved_word(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_ident_ES3_keyword(TParseContext *context, int token)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
+    if (context->getShaderVersion() < 300)
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return check_type(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token)
+{
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    if (context->getShaderVersion() < 310)
+    {
+        return reserved_word(yyscanner);
+    }
+
+    return token;
+}
+
+int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    // not a reserved word in GLSL ES 1.00 and GLSL ES 3.00, so could be used as an identifier/type name
+    if (context->getShaderVersion() < 310)
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return check_type(yyscanner);
+    }
+
+    return token;
+}
+
+int ES3_extension_keyword_else_ident(TParseContext *context, const char* extension, int token)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name
+    if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(extension))
+    {
+        return token;
+    }
+
+    yylval->lex.string = NewPoolTString(yytext);
+    return check_type(yyscanner);
+}
+
+int uint_constant(TParseContext *context)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+
+    if (context->getShaderVersion() < 300)
+    {
+        context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext);
+        return 0;
+    }
+
+    if (!atoi_clamp(yytext, &(yylval->lex.u)))
+        yyextra->error(*yylloc, "Integer overflow", yytext);
+
+    return UINTCONSTANT;
+}
+
+int floatsuffix_check(TParseContext* context)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+
+    if (context->getShaderVersion() < 300)
+    {
+        context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext);
+        return 0;
+    }
+
+    std::string text = yytext;
+    text.resize(text.size() - 1);
+    if (!strtof_clamp(text, &(yylval->lex.f)))
+        yyextra->warning(*yylloc, "Float overflow", yytext);
+
+    return(FLOATCONSTANT);
+}
+
+void yyerror(YYLTYPE* lloc, TParseContext* context, void *scanner, const char* reason) {
+    context->error(*lloc, reason, yyget_text(scanner));
+}
+
+int int_constant(TParseContext *context) {
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+
+    unsigned int u;
+    if (!atoi_clamp(yytext, &u))
+    {
+        if (context->getShaderVersion() >= 300)
+            yyextra->error(*yylloc, "Integer overflow", yytext);
+        else
+            yyextra->warning(*yylloc, "Integer overflow", yytext);
+    }
+    yylval->lex.i = static_cast<int>(u);
+    return INTCONSTANT;
+}
+
+int float_constant(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+    if (!strtof_clamp(yytext, &(yylval->lex.f)))
+        yyextra->warning(*yylloc, "Float overflow", yytext);
+    return FLOATCONSTANT;
+}
+
+int yuvcscstandardext_constant(TParseContext *context)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name
+    if (context->getShaderVersion() >= 300 && context->isExtensionEnabled("GL_EXT_YUV_target"))
+    {
+        yylval->lex.string = NewPoolTString(yytext);
+        return YUVCSCSTANDARDEXTCONSTANT;
+    }
+
+    yylval->lex.string = NewPoolTString(yytext);
+    return check_type(yyscanner);
+}
+
+int glslang_initialize(TParseContext* context) {
+    yyscan_t scanner = NULL;
+    if (yylex_init_extra(context,&scanner))
+        return 1;
+
+    context->setScanner(scanner);
+    return 0;
+}
+
+int glslang_finalize(TParseContext* context) {
+    yyscan_t scanner = context->getScanner();
+    if (scanner == NULL) return 0;
+    
+    context->setScanner(NULL);
+    yylex_destroy(scanner);
+
+    return 0;
+}
+
+int glslang_scan(size_t count, const char* const string[], const int length[],
+                 TParseContext* context) {
+    yyrestart(NULL,context->getScanner());
+    yyset_column(0,context->getScanner());
+    yyset_lineno(1,context->getScanner());
+
+    // Initialize preprocessor.
+    pp::Preprocessor *preprocessor = &context->getPreprocessor();
+
+    if (!preprocessor->init(count, string, length))
+        return 1;
+
+    // Define extension macros.
+    const TExtensionBehavior& extBehavior = context->extensionBehavior();
+    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+         iter != extBehavior.end(); ++iter) {
+        preprocessor->predefineMacro(iter->first.c_str(), 1);
+    }
+    if (context->getFragmentPrecisionHigh())
+        preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
+
+    preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec()));
+
+    return 0;
+}
+
diff --git a/src/third_party/angle/src/compiler/translator/glslang_tab.cpp b/src/third_party/angle/src/compiler/translator/glslang_tab.cpp
new file mode 100644
index 0000000..41f7cdf
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/glslang_tab.cpp
@@ -0,0 +1,5258 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 2
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+/* Copy the first part of user declarations.  */
+
+//
+// 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.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// clang-format off
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#pragma warning(disable: 4702)
+#endif
+
+#include "angle_gl.h"
+#include "compiler/translator/Cache.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/ParseContext.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYENABLE_NLS 0
+
+using namespace sh;
+
+
+
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "glslang_tab.h".  */
+#ifndef YY_YY_GLSLANG_TAB_H_INCLUDED
+# define YY_YY_GLSLANG_TAB_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+/* "%code requires" blocks.  */
+
+
+#define YYLTYPE TSourceLoc
+#define YYLTYPE_IS_DECLARED 1
+
+
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    INVARIANT = 258,
+    HIGH_PRECISION = 259,
+    MEDIUM_PRECISION = 260,
+    LOW_PRECISION = 261,
+    PRECISION = 262,
+    ATTRIBUTE = 263,
+    CONST_QUAL = 264,
+    BOOL_TYPE = 265,
+    FLOAT_TYPE = 266,
+    INT_TYPE = 267,
+    UINT_TYPE = 268,
+    BREAK = 269,
+    CONTINUE = 270,
+    DO = 271,
+    ELSE = 272,
+    FOR = 273,
+    IF = 274,
+    DISCARD = 275,
+    RETURN = 276,
+    SWITCH = 277,
+    CASE = 278,
+    DEFAULT = 279,
+    BVEC2 = 280,
+    BVEC3 = 281,
+    BVEC4 = 282,
+    IVEC2 = 283,
+    IVEC3 = 284,
+    IVEC4 = 285,
+    VEC2 = 286,
+    VEC3 = 287,
+    VEC4 = 288,
+    UVEC2 = 289,
+    UVEC3 = 290,
+    UVEC4 = 291,
+    MATRIX2 = 292,
+    MATRIX3 = 293,
+    MATRIX4 = 294,
+    IN_QUAL = 295,
+    OUT_QUAL = 296,
+    INOUT_QUAL = 297,
+    UNIFORM = 298,
+    VARYING = 299,
+    MATRIX2x3 = 300,
+    MATRIX3x2 = 301,
+    MATRIX2x4 = 302,
+    MATRIX4x2 = 303,
+    MATRIX3x4 = 304,
+    MATRIX4x3 = 305,
+    CENTROID = 306,
+    FLAT = 307,
+    SMOOTH = 308,
+    READONLY = 309,
+    WRITEONLY = 310,
+    COHERENT = 311,
+    RESTRICT = 312,
+    VOLATILE = 313,
+    SHARED = 314,
+    STRUCT = 315,
+    VOID_TYPE = 316,
+    WHILE = 317,
+    SAMPLER2D = 318,
+    SAMPLERCUBE = 319,
+    SAMPLER_EXTERNAL_OES = 320,
+    SAMPLER2DRECT = 321,
+    SAMPLER2DARRAY = 322,
+    ISAMPLER2D = 323,
+    ISAMPLER3D = 324,
+    ISAMPLERCUBE = 325,
+    ISAMPLER2DARRAY = 326,
+    USAMPLER2D = 327,
+    USAMPLER3D = 328,
+    USAMPLERCUBE = 329,
+    USAMPLER2DARRAY = 330,
+    SAMPLER2DMS = 331,
+    ISAMPLER2DMS = 332,
+    USAMPLER2DMS = 333,
+    SAMPLER3D = 334,
+    SAMPLER3DRECT = 335,
+    SAMPLER2DSHADOW = 336,
+    SAMPLERCUBESHADOW = 337,
+    SAMPLER2DARRAYSHADOW = 338,
+    SAMPLEREXTERNAL2DY2YEXT = 339,
+    IMAGE2D = 340,
+    IIMAGE2D = 341,
+    UIMAGE2D = 342,
+    IMAGE3D = 343,
+    IIMAGE3D = 344,
+    UIMAGE3D = 345,
+    IMAGE2DARRAY = 346,
+    IIMAGE2DARRAY = 347,
+    UIMAGE2DARRAY = 348,
+    IMAGECUBE = 349,
+    IIMAGECUBE = 350,
+    UIMAGECUBE = 351,
+    LAYOUT = 352,
+    YUVCSCSTANDARDEXT = 353,
+    YUVCSCSTANDARDEXTCONSTANT = 354,
+    IDENTIFIER = 355,
+    TYPE_NAME = 356,
+    FLOATCONSTANT = 357,
+    INTCONSTANT = 358,
+    UINTCONSTANT = 359,
+    BOOLCONSTANT = 360,
+    FIELD_SELECTION = 361,
+    LEFT_OP = 362,
+    RIGHT_OP = 363,
+    INC_OP = 364,
+    DEC_OP = 365,
+    LE_OP = 366,
+    GE_OP = 367,
+    EQ_OP = 368,
+    NE_OP = 369,
+    AND_OP = 370,
+    OR_OP = 371,
+    XOR_OP = 372,
+    MUL_ASSIGN = 373,
+    DIV_ASSIGN = 374,
+    ADD_ASSIGN = 375,
+    MOD_ASSIGN = 376,
+    LEFT_ASSIGN = 377,
+    RIGHT_ASSIGN = 378,
+    AND_ASSIGN = 379,
+    XOR_ASSIGN = 380,
+    OR_ASSIGN = 381,
+    SUB_ASSIGN = 382,
+    LEFT_PAREN = 383,
+    RIGHT_PAREN = 384,
+    LEFT_BRACKET = 385,
+    RIGHT_BRACKET = 386,
+    LEFT_BRACE = 387,
+    RIGHT_BRACE = 388,
+    DOT = 389,
+    COMMA = 390,
+    COLON = 391,
+    EQUAL = 392,
+    SEMICOLON = 393,
+    BANG = 394,
+    DASH = 395,
+    TILDE = 396,
+    PLUS = 397,
+    STAR = 398,
+    SLASH = 399,
+    PERCENT = 400,
+    LEFT_ANGLE = 401,
+    RIGHT_ANGLE = 402,
+    VERTICAL_BAR = 403,
+    CARET = 404,
+    AMPERSAND = 405,
+    QUESTION = 406
+  };
+#endif
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+
+
+    struct {
+        union {
+            TString *string;
+            float f;
+            int i;
+            unsigned int u;
+            bool b;
+        };
+        TSymbol* symbol;
+    } lex;
+    struct {
+        TOperator op;
+        union {
+            TIntermNode *intermNode;
+            TIntermNodePair nodePair;
+            TIntermFunctionCallOrMethod callOrMethodPair;
+            TIntermTyped *intermTypedNode;
+            TIntermAggregate *intermAggregate;
+            TIntermBlock *intermBlock;
+            TIntermDeclaration *intermDeclaration;
+            TIntermFunctionPrototype *intermFunctionPrototype;
+            TIntermSwitch *intermSwitch;
+            TIntermCase *intermCase;
+        };
+        union {
+            TTypeSpecifierNonArray typeSpecifierNonArray;
+            TPublicType type;
+            TPrecision precision;
+            TLayoutQualifier layoutQualifier;
+            TQualifier qualifier;
+            TFunction *function;
+            TParameter param;
+            TField *field;
+            TFieldList *fieldList;
+            TQualifierWrapperBase *qualifierWrapper;
+            TTypeQualifierBuilder *typeQualifierBuilder;
+        };
+    } interm;
+
+
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+/* Location type.  */
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE YYLTYPE;
+struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+};
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+int yyparse (TParseContext* context, void *scanner);
+
+#endif /* !YY_YY_GLSLANG_TAB_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+
+extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
+extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, const char* reason);
+
+#define YYLLOC_DEFAULT(Current, Rhs, N)                      \
+  do {                                                       \
+      if (N) {                                         \
+        (Current).first_file = YYRHSLOC(Rhs, 1).first_file;  \
+        (Current).first_line = YYRHSLOC(Rhs, 1).first_line;  \
+        (Current).last_file = YYRHSLOC(Rhs, N).last_file;    \
+        (Current).last_line = YYRHSLOC(Rhs, N).last_line;    \
+      }                                                      \
+      else {                                                 \
+        (Current).first_file = YYRHSLOC(Rhs, 0).last_file;   \
+        (Current).first_line = YYRHSLOC(Rhs, 0).last_line;   \
+        (Current).last_file = YYRHSLOC(Rhs, 0).last_file;    \
+        (Current).last_line = YYRHSLOC(Rhs, 0).last_line;    \
+      }                                                      \
+  } while (0)
+
+#define VERTEX_ONLY(S, L) {  \
+    if (context->getShaderType() != GL_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex shaders only ", S);  \
+    }  \
+}
+
+#define FRAG_ONLY(S, L) {  \
+    if (context->getShaderType() != GL_FRAGMENT_SHADER) {  \
+        context->error(L, " supported in fragment shaders only ", S);  \
+    }  \
+}
+
+#define COMPUTE_ONLY(S, L) {  \
+    if (context->getShaderType() != GL_COMPUTE_SHADER) {  \
+        context->error(L, " supported in compute shaders only ", S);  \
+    }  \
+}
+
+#define NON_COMPUTE_ONLY(S, L) {  \
+    if (context->getShaderType() != GL_VERTEX_SHADER && context->getShaderType() != GL_FRAGMENT_SHADER) {  \
+        context->error(L, " supported in vertex and fragment shaders only ", S);  \
+    }  \
+}
+
+#define ES2_ONLY(S, L) {  \
+    if (context->getShaderVersion() != 100) {  \
+        context->error(L, " supported in GLSL ES 1.00 only ", S);  \
+    }  \
+}
+
+#define ES3_OR_NEWER(TOKEN, LINE, REASON) {  \
+    if (context->getShaderVersion() < 300) {  \
+        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only ", TOKEN);  \
+    }  \
+}
+
+#define ES3_1_ONLY(TOKEN, LINE, REASON) {  \
+    if (context->getShaderVersion() != 310) {  \
+        context->error(LINE, REASON " supported in GLSL ES 3.10 only ", TOKEN);  \
+    }  \
+}
+
+
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+             && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+  YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+      + 2 * YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  132
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   2993
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  152
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  94
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  294
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  430
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   406
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
+     115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
+     125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
+     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
+     145,   146,   147,   148,   149,   150,   151
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   248,   248,   249,   252,   262,   265,   270,   275,   280,
+     285,   293,   299,   302,   305,   308,   311,   314,   320,   327,
+     333,   337,   345,   348,   354,   358,   365,   370,   377,   385,
+     391,   397,   406,   409,   412,   415,   425,   426,   427,   428,
+     436,   437,   440,   443,   450,   451,   454,   460,   461,   465,
+     472,   473,   476,   479,   482,   488,   489,   492,   498,   499,
+     506,   507,   514,   515,   522,   523,   529,   530,   536,   537,
+     543,   544,   550,   551,   558,   559,   560,   561,   565,   566,
+     567,   571,   575,   579,   583,   590,   593,   599,   606,   613,
+     616,   619,   628,   632,   636,   640,   644,   651,   658,   661,
+     668,   676,   696,   706,   714,   739,   743,   747,   751,   758,
+     765,   768,   772,   776,   781,   786,   793,   797,   801,   805,
+     810,   815,   822,   826,   832,   835,   841,   845,   852,   858,
+     862,   866,   869,   872,   881,   887,   895,   898,   918,   937,
+     944,   948,   952,   955,   958,   961,   964,   967,   975,   982,
+     985,   988,   994,  1001,  1004,  1010,  1013,  1016,  1019,  1025,
+    1028,  1033,  1044,  1047,  1050,  1053,  1056,  1059,  1063,  1067,
+    1071,  1075,  1079,  1083,  1087,  1091,  1095,  1099,  1103,  1107,
+    1111,  1115,  1119,  1123,  1127,  1131,  1135,  1139,  1143,  1149,
+    1152,  1155,  1158,  1161,  1164,  1167,  1170,  1173,  1176,  1179,
+    1182,  1185,  1188,  1191,  1194,  1197,  1200,  1203,  1210,  1216,
+    1222,  1225,  1228,  1231,  1234,  1237,  1240,  1243,  1246,  1249,
+    1252,  1255,  1258,  1261,  1273,  1273,  1276,  1276,  1282,  1285,
+    1291,  1294,  1301,  1305,  1311,  1317,  1329,  1333,  1337,  1338,
+    1344,  1345,  1346,  1347,  1348,  1349,  1350,  1354,  1355,  1355,
+    1355,  1364,  1365,  1369,  1369,  1370,  1370,  1375,  1378,  1387,
+    1392,  1399,  1400,  1404,  1411,  1415,  1422,  1422,  1429,  1432,
+    1439,  1443,  1456,  1456,  1461,  1461,  1467,  1467,  1475,  1478,
+    1484,  1487,  1493,  1497,  1504,  1507,  1510,  1513,  1516,  1525,
+    1531,  1537,  1540,  1546,  1546
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "INVARIANT", "HIGH_PRECISION",
+  "MEDIUM_PRECISION", "LOW_PRECISION", "PRECISION", "ATTRIBUTE",
+  "CONST_QUAL", "BOOL_TYPE", "FLOAT_TYPE", "INT_TYPE", "UINT_TYPE",
+  "BREAK", "CONTINUE", "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN",
+  "SWITCH", "CASE", "DEFAULT", "BVEC2", "BVEC3", "BVEC4", "IVEC2", "IVEC3",
+  "IVEC4", "VEC2", "VEC3", "VEC4", "UVEC2", "UVEC3", "UVEC4", "MATRIX2",
+  "MATRIX3", "MATRIX4", "IN_QUAL", "OUT_QUAL", "INOUT_QUAL", "UNIFORM",
+  "VARYING", "MATRIX2x3", "MATRIX3x2", "MATRIX2x4", "MATRIX4x2",
+  "MATRIX3x4", "MATRIX4x3", "CENTROID", "FLAT", "SMOOTH", "READONLY",
+  "WRITEONLY", "COHERENT", "RESTRICT", "VOLATILE", "SHARED", "STRUCT",
+  "VOID_TYPE", "WHILE", "SAMPLER2D", "SAMPLERCUBE", "SAMPLER_EXTERNAL_OES",
+  "SAMPLER2DRECT", "SAMPLER2DARRAY", "ISAMPLER2D", "ISAMPLER3D",
+  "ISAMPLERCUBE", "ISAMPLER2DARRAY", "USAMPLER2D", "USAMPLER3D",
+  "USAMPLERCUBE", "USAMPLER2DARRAY", "SAMPLER2DMS", "ISAMPLER2DMS",
+  "USAMPLER2DMS", "SAMPLER3D", "SAMPLER3DRECT", "SAMPLER2DSHADOW",
+  "SAMPLERCUBESHADOW", "SAMPLER2DARRAYSHADOW", "SAMPLEREXTERNAL2DY2YEXT",
+  "IMAGE2D", "IIMAGE2D", "UIMAGE2D", "IMAGE3D", "IIMAGE3D", "UIMAGE3D",
+  "IMAGE2DARRAY", "IIMAGE2DARRAY", "UIMAGE2DARRAY", "IMAGECUBE",
+  "IIMAGECUBE", "UIMAGECUBE", "LAYOUT", "YUVCSCSTANDARDEXT",
+  "YUVCSCSTANDARDEXTCONSTANT", "IDENTIFIER", "TYPE_NAME", "FLOATCONSTANT",
+  "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT", "FIELD_SELECTION",
+  "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP", "GE_OP", "EQ_OP",
+  "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN",
+  "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN",
+  "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", "RIGHT_PAREN",
+  "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT",
+  "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS",
+  "STAR", "SLASH", "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR",
+  "CARET", "AMPERSAND", "QUESTION", "$accept", "identifier",
+  "variable_identifier", "primary_expression", "postfix_expression",
+  "integer_expression", "function_call", "function_call_or_method",
+  "function_call_generic", "function_call_header_no_parameters",
+  "function_call_header_with_parameters", "function_call_header",
+  "function_identifier", "unary_expression", "unary_operator",
+  "multiplicative_expression", "additive_expression", "shift_expression",
+  "relational_expression", "equality_expression", "and_expression",
+  "exclusive_or_expression", "inclusive_or_expression",
+  "logical_and_expression", "logical_xor_expression",
+  "logical_or_expression", "conditional_expression",
+  "assignment_expression", "assignment_operator", "expression",
+  "constant_expression", "enter_struct", "declaration",
+  "function_prototype", "function_declarator",
+  "function_header_with_parameters", "function_header",
+  "parameter_declarator", "parameter_declaration",
+  "parameter_type_specifier", "init_declarator_list", "single_declaration",
+  "fully_specified_type", "interpolation_qualifier", "type_qualifier",
+  "invariant_qualifier", "single_type_qualifier", "storage_qualifier",
+  "type_specifier", "precision_qualifier", "layout_qualifier",
+  "layout_qualifier_id_list", "layout_qualifier_id",
+  "type_specifier_no_prec", "type_specifier_nonarray", "struct_specifier",
+  "$@1", "$@2", "struct_declaration_list", "struct_declaration",
+  "struct_declarator_list", "struct_declarator", "initializer",
+  "declaration_statement", "statement", "simple_statement",
+  "compound_statement", "$@3", "$@4", "statement_no_new_scope",
+  "statement_with_scope", "$@5", "$@6", "compound_statement_no_new_scope",
+  "statement_list", "expression_statement", "selection_statement",
+  "selection_rest_statement", "switch_statement", "$@7", "case_label",
+  "condition", "iteration_statement", "$@8", "$@9", "$@10",
+  "for_init_statement", "conditionopt", "for_rest_statement",
+  "jump_statement", "translation_unit", "external_declaration",
+  "function_definition", "$@11", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
+     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
+     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
+     335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
+     345,   346,   347,   348,   349,   350,   351,   352,   353,   354,
+     355,   356,   357,   358,   359,   360,   361,   362,   363,   364,
+     365,   366,   367,   368,   369,   370,   371,   372,   373,   374,
+     375,   376,   377,   378,   379,   380,   381,   382,   383,   384,
+     385,   386,   387,   388,   389,   390,   391,   392,   393,   394,
+     395,   396,   397,   398,   399,   400,   401,   402,   403,   404,
+     405,   406
+};
+# endif
+
+#define YYPACT_NINF -368
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-368)))
+
+#define YYTABLE_NINF -254
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int16 yypact[] =
+{
+    2609,  -368,  -368,  -368,  -368,   142,  -368,  -368,  -368,  -368,
+    -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,
+    -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,
+    -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,
+    -368,  -368,  -368,  -368,  -368,  -368,  -368,   -80,  -368,  -368,
+    -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,
+    -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,
+    -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,
+    -368,  -368,   -68,  -368,  -368,  -368,   -69,   -56,   -50,  2708,
+     -95,  -368,   -75,  -368,  1364,  -368,  -368,  -368,  -368,  -368,
+    -368,  -368,   -37,  -368,  2510,  -368,  -368,  2892,  -368,  -368,
+    -368,   -22,   -43,  -368,   -17,  -368,  2708,  -368,  -368,  -368,
+    2708,    29,    29,  -368,   -20,  -103,   -96,  -368,  2708,  -368,
+    -368,  1458,  -368,  -368,   -32,  2708,  -368,  -368,   -15,   -65,
+    -368,   422,  -368,  -368,  -368,  -368,     9,   -99,  -368,  1580,
+    1943,  -368,  -368,  2708,    29,  2183,  -368,  -368,    24,  -368,
+    -368,  -368,  -368,  -368,  1943,  1943,  1943,  -368,  -368,  -368,
+    -368,  -368,  -368,  -368,   -38,  -368,  -368,  -368,    35,   -48,
+    2062,    26,  -368,  1943,     6,   -89,    49,   -67,    23,    18,
+      22,    27,    57,    60,   -93,  -368,    47,  -368,  -368,  2292,
+    2708,    55,  -368,   -43,    41,    42,  -368,    53,    56,    48,
+    1702,    61,  1943,    52,    62,    50,  -368,  -368,    98,  -368,
+    -368,   -73,  -368,   -69,    64,  -368,  -368,  -368,  -368,   562,
+    -368,  -368,  -368,  -368,  -368,  -368,  1943,  1821,  1943,    58,
+      54,  -368,  -368,    29,    63,   -52,  -368,   -82,  -368,  -368,
+    -368,   -47,  -368,  -368,  1943,  2800,  -368,  -368,  1943,    67,
+    -368,  -368,  -368,  1943,  1943,  1943,  1943,  1943,  1943,  1943,
+    1943,  1943,  1943,  1943,  1943,  1943,  1943,  1943,  1943,  1943,
+    1943,  1943,  1943,  -368,  -368,  2401,  -368,  -368,  -368,  -368,
+    -368,    65,  -368,  1943,  -368,  -368,   -40,  1943,    66,  -368,
+    -368,  -368,   702,  -368,  -368,  -368,  -368,  -368,  -368,  -368,
+    -368,  -368,  -368,  -368,  1943,  1943,  -368,  -368,  -368,    70,
+      68,    72,  -368,  1943,    69,   -12,  1943,    29,  -368,  -106,
+    -368,  -368,    76,    73,  -368,    83,  -368,  -368,  -368,  -368,
+    -368,     6,     6,   -89,   -89,    49,    49,    49,    49,   -67,
+     -67,    23,    18,    22,    27,    57,    60,    25,  -368,   151,
+     -17,   982,  1122,   -45,  -368,   -26,  -368,  1243,   702,  -368,
+    -368,  -368,  1943,    78,  -368,  1943,  -368,    95,  -368,  1943,
+    -368,  -368,  1943,    99,  -368,  -368,  -368,  -368,  1243,    65,
+    -368,    73,    29,  2708,   101,   103,  -368,  1943,  -368,  -368,
+     106,  -368,  1943,  -368,    94,   109,   222,  -368,   108,   105,
+     842,  -368,  -368,   107,   -24,  1943,   842,    65,  -368,  1943,
+    -368,  -368,  -368,  -368,   110,    73,  -368,  -368,  -368,  -368
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint16 yydefact[] =
+{
+       0,   128,   149,   150,   151,     0,   134,   136,   166,   163,
+     164,   165,   170,   171,   172,   173,   174,   175,   167,   168,
+     169,   176,   177,   178,   179,   180,   181,   137,   138,   139,
+     141,   135,   182,   183,   184,   185,   186,   187,   140,   125,
+     124,   142,   143,   144,   145,   146,   147,     0,   162,   189,
+     191,   207,   209,   192,   194,   195,   196,   197,   199,   200,
+     201,   202,   193,   198,   203,   190,   204,   205,   206,   208,
+     211,   212,   213,   214,   215,   216,   217,   218,   219,   220,
+     221,   222,     0,   188,   223,   292,   293,     0,    99,    98,
+       0,   110,   116,   132,     0,   133,   126,   129,   122,   131,
+     130,   148,   159,   210,     0,   289,   291,     0,     2,     3,
+     226,     0,     0,    89,     0,    97,     0,   106,   100,   108,
+       0,   109,     0,    90,     2,   117,     0,    95,     0,   127,
+     123,     0,     1,   290,     0,     0,   224,   158,   155,     0,
+     153,     0,   294,   101,   105,   107,   103,   111,   102,     0,
+       0,    88,    96,     0,     0,     0,   228,    10,     4,     8,
+       6,     7,     9,    31,     0,     0,     0,   160,    38,    37,
+      39,    36,     5,    12,    32,    14,    19,    20,     0,     0,
+      25,     0,    40,     0,    44,    47,    50,    55,    58,    60,
+      62,    64,    66,    68,    70,    87,     0,    29,    91,     0,
+       0,     0,   152,     0,     0,     0,   274,     0,     0,     0,
+       0,     0,     0,     0,     0,   248,   257,   261,    40,    72,
+      85,     0,   237,     0,   148,   240,   259,   239,   238,     0,
+     241,   242,   243,   244,   245,   246,     0,     0,     0,     0,
+       0,   236,   121,     0,   234,     0,   232,     0,   229,    33,
+      34,     0,    16,    17,     0,     0,    23,    22,     0,   162,
+      26,    28,    35,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   161,   227,     0,   156,   157,   154,   285,
+     284,   255,   276,     0,   288,   286,     0,     0,     0,   269,
+     272,   247,     0,    75,    76,    78,    77,    80,    81,    82,
+      83,    84,    79,    74,     0,     0,   262,   258,   260,     0,
+       0,     0,   115,     0,   118,     0,     0,     0,   230,     0,
+      92,    11,     0,    18,    30,    15,    21,    27,    41,    42,
+      43,    46,    45,    48,    49,    53,    54,    51,    52,    56,
+      57,    59,    61,    63,    65,    67,    69,     0,   225,     0,
+       0,     0,     0,     0,   287,     0,   268,     0,   249,    73,
+      86,   104,     0,   112,   119,     0,   231,     0,   233,     0,
+      93,    13,     0,     0,   254,   256,   279,   278,   281,   255,
+     266,   270,     0,     0,     0,     0,   113,     0,   120,   235,
+       0,    71,     0,   280,     0,     0,   265,   263,     0,     0,
+       0,   250,   114,     0,     0,   282,     0,   255,   267,     0,
+     252,   273,   251,    94,     0,   283,   277,   264,   271,   275
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -368,   -46,  -368,  -368,  -368,  -368,  -368,  -368,    -9,  -368,
+    -368,  -368,  -368,    45,  -368,  -104,  -102,  -139,  -105,   -33,
+     -27,   -25,   -28,   -21,   -29,  -368,  -112,  -141,  -368,  -155,
+    -135,  -368,    10,    17,  -368,  -368,  -368,   134,   139,   138,
+    -368,  -368,  -339,  -368,   -81,  -368,   -90,  -368,   -87,   256,
+    -368,  -368,    59,     0,  -368,  -368,  -368,  -368,  -122,  -140,
+      20,   -63,  -232,   -97,  -224,  -349,  -142,  -368,  -368,  -148,
+    -367,  -368,  -368,  -111,   -31,   -92,  -368,  -368,  -368,  -368,
+    -368,  -119,  -368,  -368,  -368,  -368,  -368,  -368,  -368,  -368,
+    -368,   168,  -368,  -368
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,   244,   172,   173,   174,   332,   175,   176,   177,   178,
+     179,   180,   181,   218,   183,   184,   185,   186,   187,   188,
+     189,   190,   191,   192,   193,   194,   219,   220,   314,   221,
+     196,   128,   222,   223,    87,    88,    89,   117,   118,   119,
+      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
+     100,   139,   140,   197,   102,   103,   200,   135,   155,   156,
+     245,   246,   242,   225,   226,   227,   228,   302,   395,   421,
+     359,   360,   361,   422,   229,   230,   231,   407,   232,   408,
+     233,   394,   234,   367,   291,   362,   388,   404,   405,   235,
+     104,   105,   106,   114
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_int16 yytable[] =
+{
+     101,   111,   121,   142,   129,   318,   322,   130,   120,   241,
+      85,   251,   385,   199,   240,   248,   137,    86,   329,   195,
+     108,   109,   406,   281,   379,   124,   109,   149,   392,   121,
+     129,   237,   380,   121,   150,   120,   151,   195,   238,   260,
+     122,   154,   152,   123,   270,   271,   125,   153,   154,   392,
+     427,   266,   110,   267,   153,   296,   330,   138,   282,   248,
+     112,   420,   315,   129,   202,   316,   243,   420,   154,   113,
+     203,   252,   253,   115,   153,   146,   147,   298,   285,   272,
+     273,   257,   331,   327,   389,   116,   328,   258,   315,   101,
+     315,   374,   254,   131,   101,   315,   255,   241,   364,   333,
+     195,   319,   321,   390,   101,   424,   198,   134,   148,   315,
+     136,   315,   154,   154,    85,   141,   101,   337,   153,   153,
+     101,    86,   201,   327,   195,   195,   376,   357,   101,   108,
+     109,   345,   346,   347,   348,   101,   274,   275,   363,   236,
+     396,   224,   365,   398,   318,   248,     2,     3,     4,   263,
+     264,   265,   -30,   101,   261,   101,   268,   269,   286,   287,
+     315,   382,   341,   342,   256,   412,   343,   344,   276,   349,
+     350,   277,   279,   369,   370,   278,   182,   280,   283,   289,
+     290,   292,   241,   301,   293,   324,   294,   428,   299,   297,
+     300,   377,   -29,   326,   182,   323,   -24,  -253,   154,   101,
+     101,   371,   366,   373,   153,   372,   375,   381,   315,   249,
+     250,   -31,   391,   383,   195,   397,   303,   304,   305,   306,
+     307,   308,   309,   310,   311,   312,   399,   402,   262,   224,
+     410,   241,   415,   391,   241,   313,   411,   413,   416,   417,
+     215,   401,   419,   351,   400,   423,   336,   414,   429,   384,
+     352,   354,   356,   353,   144,   143,   241,   182,   145,   355,
+     425,   107,   288,   325,   378,   386,   418,   195,   426,   403,
+     387,   368,   133,     0,     0,     0,     0,     0,   241,     0,
+       0,   182,   182,     0,     0,   101,   393,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   224,   129,     0,     0,   130,   393,   338,   339,
+     340,   182,   182,   182,   182,   182,   182,   182,   182,   182,
+     182,   182,   182,   182,   182,   182,   182,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   409,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   224,   224,     0,     0,     0,     0,   224,   224,     0,
+       0,   182,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   224,     0,
+       0,     0,     0,   101,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     224,     0,     0,     0,     0,     0,   224,     0,     0,     0,
+       0,     0,     0,     0,   182,     1,     2,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,   204,   205,   206,     0,
+     207,   208,   209,   210,   211,   212,   213,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,   214,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
+      83,   157,   158,    84,   159,   160,   161,   162,   163,     0,
+       0,   164,   165,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     166,     0,     0,     0,   215,   216,     0,     0,     0,     0,
+     217,   168,   169,   170,   171,     1,     2,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,   204,   205,   206,     0,
+     207,   208,   209,   210,   211,   212,   213,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,   214,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
+      83,   157,   158,    84,   159,   160,   161,   162,   163,     0,
+       0,   164,   165,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     166,     0,     0,     0,   215,   317,     0,     0,     0,     0,
+     217,   168,   169,   170,   171,     1,     2,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,   204,   205,   206,     0,
+     207,   208,   209,   210,   211,   212,   213,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,   214,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
+      83,   157,   158,    84,   159,   160,   161,   162,   163,     0,
+       0,   164,   165,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     166,     0,     0,     0,   215,     0,     0,     0,     0,     0,
+     217,   168,   169,   170,   171,     1,     2,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,   204,   205,   206,     0,
+     207,   208,   209,   210,   211,   212,   213,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,   214,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
+      83,   157,   158,    84,   159,   160,   161,   162,   163,     0,
+       0,   164,   165,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     166,     0,     0,     0,   141,     0,     0,     0,     0,     0,
+     217,   168,   169,   170,   171,     1,     2,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,   204,   205,   206,     0,
+     207,   208,   209,   210,   211,   212,   213,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,   214,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
+      83,   157,   158,    84,   159,   160,   161,   162,   163,     0,
+       0,   164,   165,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     166,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     217,   168,   169,   170,   171,     1,     2,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,     0,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
+      83,   157,   158,    84,   159,   160,   161,   162,   163,     0,
+       0,   164,   165,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     1,     2,     3,     4,
+     166,     6,     7,     8,     9,    10,    11,     0,     0,     0,
+     217,   168,   169,   170,   171,     0,     0,     0,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,     0,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    64,    65,     0,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
+      82,    83,   157,   158,    84,   159,   160,   161,   162,   163,
+       0,     0,   164,   165,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     1,     2,     3,
+       4,   166,     6,     7,     8,     9,    10,    11,     0,     0,
+       0,     0,   168,   169,   170,   171,     0,     0,     0,    12,
+      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,     0,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
+      62,    63,    64,    65,     0,    66,    67,    68,    69,    70,
+      71,    72,    73,    74,    75,    76,    77,    78,    79,    80,
+      81,    82,    83,     0,   126,    84,     0,     0,     8,     9,
+      10,    11,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,     0,     0,
+       0,     0,   127,    32,    33,    34,    35,    36,    37,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    47,    48,
+       0,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,     0,    66,
+      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
+      77,    78,    79,    80,    81,     0,    83,   157,   158,    84,
+     159,   160,   161,   162,   163,     0,     0,   164,   165,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   166,     0,     0,   167,
+       8,     9,    10,    11,     0,     0,     0,   168,   169,   170,
+     171,     0,     0,     0,     0,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+       0,     0,     0,     0,     0,    32,    33,    34,    35,    36,
+      37,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      47,    48,     0,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+       0,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,     0,    83,   157,
+     158,    84,   159,   160,   161,   162,   163,     0,     0,   164,
+     165,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   166,     0,
+       0,   239,     8,     9,    10,    11,     0,     0,     0,   168,
+     169,   170,   171,     0,     0,     0,     0,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,     0,     0,     0,     0,     0,    32,    33,    34,
+      35,    36,    37,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    47,    48,     0,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,     0,
+      83,   157,   158,    84,   159,   160,   161,   162,   163,     0,
+       0,   164,   165,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     166,     8,     9,    10,    11,     0,     0,     0,     0,     0,
+     295,   168,   169,   170,   171,     0,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,     0,     0,     0,     0,     0,    32,    33,    34,    35,
+      36,    37,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    47,    48,     0,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,     0,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,     0,    83,
+     157,   158,    84,   159,   160,   161,   162,   163,     0,     0,
+     164,   165,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   166,
+       0,     0,   320,     8,     9,    10,    11,     0,     0,     0,
+     168,   169,   170,   171,     0,     0,     0,     0,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,     0,     0,     0,     0,     0,    32,    33,
+      34,    35,    36,    37,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    47,    48,     0,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    64,    65,     0,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
+       0,    83,   157,   158,    84,   159,   160,   161,   162,   163,
+       0,     0,   164,   165,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   166,     8,     9,    10,    11,     0,     0,     0,     0,
+       0,     0,   168,   169,   170,   171,     0,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,     0,     0,     0,     0,     0,    32,    33,    34,
+      35,    36,    37,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    47,   259,     0,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,     0,
+      83,   157,   158,    84,   159,   160,   161,   162,   163,     0,
+       0,   164,   165,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     1,     2,     3,     4,
+     166,     6,     7,     8,     9,    10,    11,     0,     0,     0,
+       0,   168,   169,   170,   171,     0,     0,     0,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,     0,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    64,    65,     0,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
+      82,    83,     0,     0,    84,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     1,     2,     3,     4,     0,
+       6,     7,     8,     9,    10,    11,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   247,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,     0,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
+      83,     0,     0,    84,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     1,     2,     3,     4,     0,     6,
+       7,     8,     9,    10,    11,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   284,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,     0,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,     0,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+       0,     0,    84,     0,     0,     0,     0,     0,     0,     0,
+     132,     0,     0,     1,     2,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   358,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
+      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,     0,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+       0,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,     0,
+       0,    84,     1,     2,     3,     4,     5,     6,     7,     8,
+       9,    10,    11,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,     0,    49,    50,    51,    52,    53,    54,    55,    56,
+      57,    58,    59,    60,    61,    62,    63,    64,    65,     0,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,    75,
+      76,    77,    78,    79,    80,    81,    82,    83,     0,     0,
+      84,     1,     2,     3,     4,     0,     6,     7,     8,     9,
+      10,    11,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+       0,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,     0,    66,
+      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
+      77,    78,    79,    80,    81,    82,    83,     0,     0,    84,
+       8,     9,    10,    11,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+       0,     0,     0,     0,     0,    32,    33,    34,    35,    36,
+      37,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      47,    48,     0,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+       0,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,     0,    83,     0,
+     334,    84,     8,     9,    10,    11,   335,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,     0,     0,     0,     0,     0,    32,    33,    34,
+      35,    36,    37,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    47,    48,     0,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     0,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,     0,
+      83,     0,     0,    84
+};
+
+static const yytype_int16 yycheck[] =
+{
+       0,    47,    89,   114,    94,   229,   238,    94,    89,   150,
+       0,   166,   361,   135,   149,   155,    59,     0,   100,   131,
+     100,   101,   389,   116,   130,   100,   101,   130,   367,   116,
+     120,   130,   138,   120,   137,   116,   132,   149,   137,   180,
+     135,   128,   138,   138,   111,   112,    92,   128,   135,   388,
+     417,   140,   132,   142,   135,   210,   138,   100,   151,   199,
+     128,   410,   135,   153,   129,   138,   153,   416,   155,   138,
+     135,   109,   110,   129,   155,   121,   122,   212,   200,   146,
+     147,   129,   129,   135,   129,   135,   138,   135,   135,    89,
+     135,   323,   130,   130,    94,   135,   134,   238,   138,   254,
+     212,   236,   237,   129,   104,   129,   138,   107,   128,   135,
+     132,   135,   199,   200,   104,   132,   116,   258,   199,   200,
+     120,   104,   137,   135,   236,   237,   138,   282,   128,   100,
+     101,   270,   271,   272,   273,   135,   113,   114,   293,   130,
+     372,   141,   297,   375,   368,   285,     4,     5,     6,   143,
+     144,   145,   128,   153,   128,   155,   107,   108,   103,   104,
+     135,   136,   266,   267,   129,   397,   268,   269,   150,   274,
+     275,   149,   115,   314,   315,   148,   131,   117,   131,   138,
+     138,   128,   323,   133,   128,   131,   138,   419,   136,   128,
+     128,   326,   128,   130,   149,   137,   129,   132,   285,   199,
+     200,   131,   136,   131,   285,   137,   137,   131,   135,   164,
+     165,   128,   367,    62,   326,   137,   118,   119,   120,   121,
+     122,   123,   124,   125,   126,   127,   131,   128,   183,   229,
+     129,   372,   138,   388,   375,   137,   133,   131,   129,    17,
+     132,   382,   137,   276,   379,   138,   255,   402,   138,   360,
+     277,   279,   281,   278,   120,   116,   397,   212,   120,   280,
+     415,     5,   203,   243,   327,   362,   408,   379,   416,   388,
+     362,   302,   104,    -1,    -1,    -1,    -1,    -1,   419,    -1,
+      -1,   236,   237,    -1,    -1,   285,   367,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   302,   393,    -1,    -1,   393,   388,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   392,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   361,   362,    -1,    -1,    -1,    -1,   367,   368,    -1,
+      -1,   326,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   388,    -1,
+      -1,    -1,    -1,   393,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     410,    -1,    -1,    -1,    -1,    -1,   416,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   379,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    -1,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,    -1,
+      -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     128,    -1,    -1,    -1,   132,   133,    -1,    -1,    -1,    -1,
+     138,   139,   140,   141,   142,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    -1,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,    -1,
+      -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     128,    -1,    -1,    -1,   132,   133,    -1,    -1,    -1,    -1,
+     138,   139,   140,   141,   142,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    -1,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,    -1,
+      -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     128,    -1,    -1,    -1,   132,    -1,    -1,    -1,    -1,    -1,
+     138,   139,   140,   141,   142,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    -1,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,    -1,
+      -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     128,    -1,    -1,    -1,   132,    -1,    -1,    -1,    -1,    -1,
+     138,   139,   140,   141,   142,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    -1,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,    -1,
+      -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     128,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     138,   139,   140,   141,   142,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    -1,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,    -1,
+      -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,     3,     4,     5,     6,
+     128,     8,     9,    10,    11,    12,    13,    -1,    -1,    -1,
+     138,   139,   140,   141,   142,    -1,    -1,    -1,    25,    26,
+      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
+      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
+      57,    58,    59,    60,    61,    -1,    63,    64,    65,    66,
+      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
+      77,    78,    79,    -1,    81,    82,    83,    84,    85,    86,
+      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
+      97,    98,    99,   100,   101,   102,   103,   104,   105,   106,
+      -1,    -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,     3,     4,     5,
+       6,   128,     8,     9,    10,    11,    12,    13,    -1,    -1,
+      -1,    -1,   139,   140,   141,   142,    -1,    -1,    -1,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    -1,    63,    64,    65,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,    75,
+      76,    77,    78,    79,    -1,    81,    82,    83,    84,    85,
+      86,    87,    88,    89,    90,    91,    92,    93,    94,    95,
+      96,    97,    98,    -1,   100,   101,    -1,    -1,    10,    11,
+      12,    13,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,    -1,    -1,
+      -1,    -1,   138,    45,    46,    47,    48,    49,    50,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    60,    61,
+      -1,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    -1,    81,
+      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
+      92,    93,    94,    95,    96,    -1,    98,    99,   100,   101,
+     102,   103,   104,   105,   106,    -1,    -1,   109,   110,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   128,    -1,    -1,   131,
+      10,    11,    12,    13,    -1,    -1,    -1,   139,   140,   141,
+     142,    -1,    -1,    -1,    -1,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      -1,    -1,    -1,    -1,    -1,    45,    46,    47,    48,    49,
+      50,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      60,    61,    -1,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      -1,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+      90,    91,    92,    93,    94,    95,    96,    -1,    98,    99,
+     100,   101,   102,   103,   104,   105,   106,    -1,    -1,   109,
+     110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   128,    -1,
+      -1,   131,    10,    11,    12,    13,    -1,    -1,    -1,   139,
+     140,   141,   142,    -1,    -1,    -1,    -1,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    -1,    -1,    -1,    -1,    -1,    45,    46,    47,
+      48,    49,    50,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    60,    61,    -1,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    -1,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,    -1,
+      -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     128,    10,    11,    12,    13,    -1,    -1,    -1,    -1,    -1,
+     138,   139,   140,   141,   142,    -1,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
+      39,    -1,    -1,    -1,    -1,    -1,    45,    46,    47,    48,
+      49,    50,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    60,    61,    -1,    63,    64,    65,    66,    67,    68,
+      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
+      79,    -1,    81,    82,    83,    84,    85,    86,    87,    88,
+      89,    90,    91,    92,    93,    94,    95,    96,    -1,    98,
+      99,   100,   101,   102,   103,   104,   105,   106,    -1,    -1,
+     109,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   128,
+      -1,    -1,   131,    10,    11,    12,    13,    -1,    -1,    -1,
+     139,   140,   141,   142,    -1,    -1,    -1,    -1,    25,    26,
+      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
+      37,    38,    39,    -1,    -1,    -1,    -1,    -1,    45,    46,
+      47,    48,    49,    50,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    60,    61,    -1,    63,    64,    65,    66,
+      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
+      77,    78,    79,    -1,    81,    82,    83,    84,    85,    86,
+      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
+      -1,    98,    99,   100,   101,   102,   103,   104,   105,   106,
+      -1,    -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   128,    10,    11,    12,    13,    -1,    -1,    -1,    -1,
+      -1,    -1,   139,   140,   141,   142,    -1,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    -1,    -1,    -1,    -1,    -1,    45,    46,    47,
+      48,    49,    50,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    60,    61,    -1,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    -1,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,    -1,
+      -1,   109,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,     3,     4,     5,     6,
+     128,     8,     9,    10,    11,    12,    13,    -1,    -1,    -1,
+      -1,   139,   140,   141,   142,    -1,    -1,    -1,    25,    26,
+      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
+      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
+      57,    58,    59,    60,    61,    -1,    63,    64,    65,    66,
+      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
+      77,    78,    79,    -1,    81,    82,    83,    84,    85,    86,
+      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
+      97,    98,    -1,    -1,   101,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,     3,     4,     5,     6,    -1,
+       8,     9,    10,    11,    12,    13,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   133,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    -1,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    -1,    -1,   101,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,     3,     4,     5,     6,    -1,     8,
+       9,    10,    11,    12,    13,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   133,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    60,    61,    -1,    63,    64,    65,    66,    67,    68,
+      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
+      79,    -1,    81,    82,    83,    84,    85,    86,    87,    88,
+      89,    90,    91,    92,    93,    94,    95,    96,    97,    98,
+      -1,    -1,   101,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+       0,    -1,    -1,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    13,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   133,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    -1,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      -1,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+      90,    91,    92,    93,    94,    95,    96,    97,    98,    -1,
+      -1,   101,     3,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,    13,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
+      61,    -1,    63,    64,    65,    66,    67,    68,    69,    70,
+      71,    72,    73,    74,    75,    76,    77,    78,    79,    -1,
+      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
+      91,    92,    93,    94,    95,    96,    97,    98,    -1,    -1,
+     101,     3,     4,     5,     6,    -1,     8,     9,    10,    11,
+      12,    13,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
+      -1,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    -1,    81,
+      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
+      92,    93,    94,    95,    96,    97,    98,    -1,    -1,   101,
+      10,    11,    12,    13,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      -1,    -1,    -1,    -1,    -1,    45,    46,    47,    48,    49,
+      50,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      60,    61,    -1,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      -1,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+      90,    91,    92,    93,    94,    95,    96,    -1,    98,    -1,
+     100,   101,    10,    11,    12,    13,   106,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    -1,    -1,    -1,    -1,    -1,    45,    46,    47,
+      48,    49,    50,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    60,    61,    -1,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    -1,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    -1,
+      98,    -1,    -1,   101
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,   101,   184,   185,   186,   187,   188,
+     192,   193,   194,   195,   196,   197,   198,   199,   200,   201,
+     202,   205,   206,   207,   242,   243,   244,   201,   100,   101,
+     132,   153,   128,   138,   245,   129,   135,   189,   190,   191,
+     196,   200,   135,   138,   100,   153,   100,   138,   183,   198,
+     200,   130,     0,   243,   205,   209,   132,    59,   100,   203,
+     204,   132,   225,   190,   189,   191,   153,   153,   128,   130,
+     137,   132,   138,   196,   200,   210,   211,    99,   100,   102,
+     103,   104,   105,   106,   109,   110,   128,   131,   139,   140,
+     141,   142,   154,   155,   156,   158,   159,   160,   161,   162,
+     163,   164,   165,   166,   167,   168,   169,   170,   171,   172,
+     173,   174,   175,   176,   177,   178,   182,   205,   138,   210,
+     208,   137,   129,   135,    14,    15,    16,    18,    19,    20,
+      21,    22,    23,    24,    62,   132,   133,   138,   165,   178,
+     179,   181,   184,   185,   205,   215,   216,   217,   218,   226,
+     227,   228,   230,   232,   234,   241,   130,   130,   137,   131,
+     182,   179,   214,   200,   153,   212,   213,   133,   211,   165,
+     165,   181,   109,   110,   130,   134,   129,   129,   135,    61,
+     179,   128,   165,   143,   144,   145,   140,   142,   107,   108,
+     111,   112,   146,   147,   113,   114,   150,   149,   148,   115,
+     117,   116,   151,   131,   133,   210,   103,   104,   204,   138,
+     138,   236,   128,   128,   138,   138,   181,   128,   182,   136,
+     128,   133,   219,   118,   119,   120,   121,   122,   123,   124,
+     125,   126,   127,   137,   180,   135,   138,   133,   216,   182,
+     131,   182,   214,   137,   131,   212,   130,   135,   138,   100,
+     138,   129,   157,   181,   100,   106,   160,   179,   165,   165,
+     165,   167,   167,   168,   168,   169,   169,   169,   169,   170,
+     170,   171,   172,   173,   174,   175,   176,   181,   133,   222,
+     223,   224,   237,   181,   138,   181,   136,   235,   226,   179,
+     179,   131,   137,   131,   214,   137,   138,   182,   213,   130,
+     138,   131,   136,    62,   225,   217,   215,   227,   238,   129,
+     129,   181,   194,   196,   233,   220,   214,   137,   214,   131,
+     182,   179,   128,   233,   239,   240,   222,   229,   231,   153,
+     129,   133,   214,   131,   181,   138,   129,    17,   218,   137,
+     217,   221,   225,   138,   129,   181,   221,   222,   214,   138
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,   152,   153,   153,   154,   155,   155,   155,   155,   155,
+     155,   155,   156,   156,   156,   156,   156,   156,   157,   158,
+     159,   159,   160,   160,   161,   161,   162,   162,   163,   164,
+     164,   164,   165,   165,   165,   165,   166,   166,   166,   166,
+     167,   167,   167,   167,   168,   168,   168,   169,   169,   169,
+     170,   170,   170,   170,   170,   171,   171,   171,   172,   172,
+     173,   173,   174,   174,   175,   175,   176,   176,   177,   177,
+     178,   178,   179,   179,   180,   180,   180,   180,   180,   180,
+     180,   180,   180,   180,   180,   181,   181,   182,   183,   184,
+     184,   184,   184,   184,   184,   184,   184,   185,   186,   186,
+     187,   187,   188,   189,   189,   190,   190,   190,   190,   191,
+     192,   192,   192,   192,   192,   192,   193,   193,   193,   193,
+     193,   193,   194,   194,   195,   195,   196,   196,   197,   198,
+     198,   198,   198,   198,   199,   199,   199,   199,   199,   199,
+     199,   199,   199,   199,   199,   199,   199,   199,   200,   201,
+     201,   201,   202,   203,   203,   204,   204,   204,   204,   205,
+     205,   205,   206,   206,   206,   206,   206,   206,   206,   206,
+     206,   206,   206,   206,   206,   206,   206,   206,   206,   206,
+     206,   206,   206,   206,   206,   206,   206,   206,   206,   206,
+     206,   206,   206,   206,   206,   206,   206,   206,   206,   206,
+     206,   206,   206,   206,   206,   206,   206,   206,   206,   206,
+     206,   206,   206,   206,   206,   206,   206,   206,   206,   206,
+     206,   206,   206,   206,   208,   207,   209,   207,   210,   210,
+     211,   211,   212,   212,   213,   213,   214,   215,   216,   216,
+     217,   217,   217,   217,   217,   217,   217,   218,   219,   220,
+     218,   221,   221,   223,   222,   224,   222,   225,   225,   226,
+     226,   227,   227,   228,   229,   229,   231,   230,   232,   232,
+     233,   233,   235,   234,   236,   234,   237,   234,   238,   238,
+     239,   239,   240,   240,   241,   241,   241,   241,   241,   242,
+     242,   243,   243,   245,   244
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     3,     1,     4,     1,     3,     2,     2,     1,     1,
+       1,     3,     2,     2,     2,     1,     2,     3,     2,     1,
+       1,     1,     1,     2,     2,     2,     1,     1,     1,     1,
+       1,     3,     3,     3,     1,     3,     3,     1,     3,     3,
+       1,     3,     3,     3,     3,     1,     3,     3,     1,     3,
+       1,     3,     1,     3,     1,     3,     1,     3,     1,     3,
+       1,     5,     1,     3,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     3,     1,     2,     2,
+       2,     4,     5,     6,     9,     2,     3,     2,     1,     1,
+       2,     3,     3,     2,     5,     2,     1,     2,     1,     1,
+       1,     3,     6,     7,     8,     5,     1,     2,     5,     6,
+       7,     4,     1,     2,     1,     1,     1,     2,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     4,     1,     3,     1,     3,     3,     1,     1,
+       3,     4,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     0,     6,     0,     5,     1,     2,
+       3,     4,     1,     3,     1,     4,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     2,     0,     0,
+       5,     1,     1,     0,     2,     0,     2,     2,     3,     1,
+       2,     1,     2,     5,     3,     1,     0,     6,     3,     2,
+       1,     4,     0,     6,     0,     8,     0,     7,     1,     1,
+       1,     0,     2,     3,     2,     2,     2,     3,     2,     1,
+       2,     1,     1,     0,     3
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (&yylloc, context, scanner, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)                                \
+    do                                                                  \
+      if (N)                                                            \
+        {                                                               \
+          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+        }                                                               \
+      else                                                              \
+        {                                                               \
+          (Current).first_line   = (Current).last_line   =              \
+            YYRHSLOC (Rhs, 0).last_line;                                \
+          (Current).first_column = (Current).last_column =              \
+            YYRHSLOC (Rhs, 0).last_column;                              \
+        }                                                               \
+    while (0)
+#endif
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+
+/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */
+
+YY_ATTRIBUTE_UNUSED
+static unsigned
+yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
+{
+  unsigned res = 0;
+  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
+  if (0 <= yylocp->first_line)
+    {
+      res += YYFPRINTF (yyo, "%d", yylocp->first_line);
+      if (0 <= yylocp->first_column)
+        res += YYFPRINTF (yyo, ".%d", yylocp->first_column);
+    }
+  if (0 <= yylocp->last_line)
+    {
+      if (yylocp->first_line < yylocp->last_line)
+        {
+          res += YYFPRINTF (yyo, "-%d", yylocp->last_line);
+          if (0 <= end_col)
+            res += YYFPRINTF (yyo, ".%d", end_col);
+        }
+      else if (0 <= end_col && yylocp->first_column < end_col)
+        res += YYFPRINTF (yyo, "-%d", end_col);
+    }
+  return res;
+ }
+
+#  define YY_LOCATION_PRINT(File, Loc)          \
+  yy_location_print_ (File, &(Loc))
+
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, Location, context, scanner); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, TParseContext* context, void *scanner)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (yylocationp);
+  YYUSE (context);
+  YYUSE (scanner);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, TParseContext* context, void *scanner)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  YY_LOCATION_PRINT (yyoutput, *yylocationp);
+  YYFPRINTF (yyoutput, ": ");
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, context, scanner);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, TParseContext* context, void *scanner)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                       , &(yylsp[(yyi + 1) - (yynrhs)])                       , context, scanner);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, yylsp, Rule, context, scanner); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, TParseContext* context, void *scanner)
+{
+  YYUSE (yyvaluep);
+  YYUSE (yylocationp);
+  YYUSE (context);
+  YYUSE (scanner);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (TParseContext* context, void *scanner)
+{
+/* The lookahead symbol.  */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol.  */
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+/* Location data for the lookahead symbol.  */
+static YYLTYPE yyloc_default
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+  = { 1, 1, 1, 1 }
+# endif
+;
+YYLTYPE yylloc = yyloc_default;
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+       'yyls': related to locations.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    /* The location stack.  */
+    YYLTYPE yylsa[YYINITDEPTH];
+    YYLTYPE *yyls;
+    YYLTYPE *yylsp;
+
+    /* The locations where the error started and ended.  */
+    YYLTYPE yyerror_range[3];
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+  YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yylsp = yyls = yylsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  yylsp[0] = yylloc;
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+        YYLTYPE *yyls1 = yyls;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yyls1, yysize * sizeof (*yylsp),
+                    &yystacksize);
+
+        yyls = yyls1;
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+        YYSTACK_RELOCATE (yyls_alloc, yyls);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+      yylsp = yyls + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex (&yylval, &yylloc, scanner);
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+  *++yylsp = yylloc;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+  /* Default location.  */
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 4:
+
+    {
+        // The symbol table search was done in the lexical phase
+        (yyval.interm.intermTypedNode) = context->parseVariableIdentifier((yylsp[0]), (yyvsp[0].lex).string, (yyvsp[0].lex).symbol);
+
+        // don't delete $1.string, it's used by error recovery, and the pool
+        // pop will reclaim the memory
+    }
+
+    break;
+
+  case 5:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 6:
+
+    {
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setIConst((yyvsp[0].lex).i);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[0]));
+    }
+
+    break;
+
+  case 7:
+
+    {
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setUConst((yyvsp[0].lex).u);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtUInt, EbpUndefined, EvqConst), (yylsp[0]));
+    }
+
+    break;
+
+  case 8:
+
+    {
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setFConst((yyvsp[0].lex).f);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yylsp[0]));
+    }
+
+    break;
+
+  case 9:
+
+    {
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setBConst((yyvsp[0].lex).b);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[0]));
+    }
+
+    break;
+
+  case 10:
+
+    {
+        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+           context->error((yylsp[0]), "unsupported value", (yyvsp[0].lex).string->c_str());
+        }
+        TConstantUnion *unionArray = new TConstantUnion[1];
+        unionArray->setYuvCscStandardEXTConst(getYuvCscStandardEXT((yyvsp[0].lex).string->c_str()));
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtYuvCscStandardEXT, EbpUndefined, EvqConst), (yylsp[0]));
+    }
+
+    break;
+
+  case 11:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 12:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 13:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addIndexExpression((yyvsp[-3].interm.intermTypedNode), (yylsp[-2]), (yyvsp[-1].interm.intermTypedNode));
+    }
+
+    break;
+
+  case 14:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 15:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addFieldSelectionExpression((yyvsp[-2].interm.intermTypedNode), (yylsp[-1]), *(yyvsp[0].lex).string, (yylsp[0]));
+    }
+
+    break;
+
+  case 16:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addUnaryMathLValue(EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode), (yylsp[0]));
+    }
+
+    break;
+
+  case 17:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addUnaryMathLValue(EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode), (yylsp[0]));
+    }
+
+    break;
+
+  case 18:
+
+    {
+        context->checkIsScalarInteger((yyvsp[0].interm.intermTypedNode), "[]");
+        (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 19:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addFunctionCallOrMethod((yyvsp[0].interm).function, (yyvsp[0].interm).callOrMethodPair.arguments, (yyvsp[0].interm).callOrMethodPair.thisNode, (yylsp[0]));
+    }
+
+    break;
+
+  case 20:
+
+    {
+        (yyval.interm) = (yyvsp[0].interm);
+        (yyval.interm).callOrMethodPair.thisNode = nullptr;
+    }
+
+    break;
+
+  case 21:
+
+    {
+        ES3_OR_NEWER("", (yylsp[0]), "methods");
+        (yyval.interm) = (yyvsp[0].interm);
+        (yyval.interm).callOrMethodPair.thisNode = (yyvsp[-2].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 22:
+
+    {
+        (yyval.interm) = (yyvsp[-1].interm);
+    }
+
+    break;
+
+  case 23:
+
+    {
+        (yyval.interm) = (yyvsp[-1].interm);
+    }
+
+    break;
+
+  case 24:
+
+    {
+        (yyval.interm).function = (yyvsp[-1].interm.function);
+        (yyval.interm).callOrMethodPair.arguments = context->createEmptyArgumentsList();
+    }
+
+    break;
+
+  case 25:
+
+    {
+        (yyval.interm).function = (yyvsp[0].interm.function);
+        (yyval.interm).callOrMethodPair.arguments = context->createEmptyArgumentsList();
+    }
+
+    break;
+
+  case 26:
+
+    {
+        (yyval.interm).callOrMethodPair.arguments = context->createEmptyArgumentsList();
+        (yyval.interm).function = (yyvsp[-1].interm.function);
+        (yyval.interm).callOrMethodPair.arguments->push_back((yyvsp[0].interm.intermTypedNode));
+    }
+
+    break;
+
+  case 27:
+
+    {
+        (yyval.interm).function = (yyvsp[-2].interm).function;
+        (yyval.interm).callOrMethodPair.arguments->push_back((yyvsp[0].interm.intermTypedNode));
+    }
+
+    break;
+
+  case 28:
+
+    {
+        (yyval.interm.function) = (yyvsp[-1].interm.function);
+    }
+
+    break;
+
+  case 29:
+
+    {
+        if ((yyvsp[0].interm.type).array) {
+            ES3_OR_NEWER("[]", (yylsp[0]), "array constructor");
+        }
+        (yyval.interm.function) = context->addConstructorFunc((yyvsp[0].interm.type));
+    }
+
+    break;
+
+  case 30:
+
+    {
+        context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
+        const TType *type = TCache::getType(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction((yyvsp[0].lex).string, type);
+        (yyval.interm.function) = function;
+    }
+
+    break;
+
+  case 31:
+
+    {
+        context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
+        const TType *type = TCache::getType(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction((yyvsp[0].lex).string, type);
+        (yyval.interm.function) = function;
+    }
+
+    break;
+
+  case 32:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 33:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addUnaryMathLValue(EOpPreIncrement, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 34:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addUnaryMathLValue(EOpPreDecrement, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 35:
+
+    {
+        if ((yyvsp[-1].interm).op != EOpNull) {
+            (yyval.interm.intermTypedNode) = context->addUnaryMath((yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+        } else
+            (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 36:
+
+    { (yyval.interm).op = EOpPositive; }
+
+    break;
+
+  case 37:
+
+    { (yyval.interm).op = EOpNegative; }
+
+    break;
+
+  case 38:
+
+    { (yyval.interm).op = EOpLogicalNot; }
+
+    break;
+
+  case 39:
+
+    {
+        ES3_OR_NEWER("~", (yyloc), "bit-wise operator");
+        (yyval.interm).op = EOpBitwiseNot;
+    }
+
+    break;
+
+  case 40:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 41:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 42:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 43:
+
+    {
+        ES3_OR_NEWER("%", (yylsp[-1]), "integer modulus operator");
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpIMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 44:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 45:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 46:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 47:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 48:
+
+    {
+        ES3_OR_NEWER("<<", (yylsp[-1]), "bit-wise operator");
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitShiftLeft, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 49:
+
+    {
+        ES3_OR_NEWER(">>", (yylsp[-1]), "bit-wise operator");
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitShiftRight, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 50:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 51:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 52:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 53:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 54:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 55:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 56:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 57:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 58:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 59:
+
+    {
+        ES3_OR_NEWER("&", (yylsp[-1]), "bit-wise operator");
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitwiseAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 60:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 61:
+
+    {
+        ES3_OR_NEWER("^", (yylsp[-1]), "bit-wise operator");
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitwiseXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 62:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 63:
+
+    {
+        ES3_OR_NEWER("|", (yylsp[-1]), "bit-wise operator");
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitwiseOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 64:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 65:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 66:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 67:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 68:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 69:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 70:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 71:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addTernarySelection((yyvsp[-4].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-3]));
+    }
+
+    break;
+
+  case 72:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 73:
+
+    {
+        context->checkCanBeLValue((yylsp[-1]), "assign", (yyvsp[-2].interm.intermTypedNode));
+        (yyval.interm.intermTypedNode) = context->addAssign((yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 74:
+
+    { (yyval.interm).op = EOpAssign; }
+
+    break;
+
+  case 75:
+
+    { (yyval.interm).op = EOpMulAssign; }
+
+    break;
+
+  case 76:
+
+    { (yyval.interm).op = EOpDivAssign; }
+
+    break;
+
+  case 77:
+
+    {
+        ES3_OR_NEWER("%=", (yyloc), "integer modulus operator");
+        (yyval.interm).op = EOpIModAssign;
+    }
+
+    break;
+
+  case 78:
+
+    { (yyval.interm).op = EOpAddAssign; }
+
+    break;
+
+  case 79:
+
+    { (yyval.interm).op = EOpSubAssign; }
+
+    break;
+
+  case 80:
+
+    {
+        ES3_OR_NEWER("<<=", (yyloc), "bit-wise operator");
+        (yyval.interm).op = EOpBitShiftLeftAssign;
+    }
+
+    break;
+
+  case 81:
+
+    {
+        ES3_OR_NEWER(">>=", (yyloc), "bit-wise operator");
+        (yyval.interm).op = EOpBitShiftRightAssign;
+    }
+
+    break;
+
+  case 82:
+
+    {
+        ES3_OR_NEWER("&=", (yyloc), "bit-wise operator");
+        (yyval.interm).op = EOpBitwiseAndAssign;
+    }
+
+    break;
+
+  case 83:
+
+    {
+        ES3_OR_NEWER("^=", (yyloc), "bit-wise operator");
+        (yyval.interm).op = EOpBitwiseXorAssign;
+    }
+
+    break;
+
+  case 84:
+
+    {
+        ES3_OR_NEWER("|=", (yyloc), "bit-wise operator");
+        (yyval.interm).op = EOpBitwiseOrAssign;
+    }
+
+    break;
+
+  case 85:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 86:
+
+    {
+        (yyval.interm.intermTypedNode) = context->addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+    }
+
+    break;
+
+  case 87:
+
+    {
+        context->checkIsConst((yyvsp[0].interm.intermTypedNode));
+        (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 88:
+
+    {
+        context->enterStructDeclaration((yylsp[-1]), *(yyvsp[-1].lex).string);
+        (yyval.lex) = (yyvsp[-1].lex);
+    }
+
+    break;
+
+  case 89:
+
+    {
+        (yyval.interm.intermNode) = context->addFunctionPrototypeDeclaration(*((yyvsp[-1].interm).function), (yylsp[-1]));
+    }
+
+    break;
+
+  case 90:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[-1].interm).intermDeclaration;
+    }
+
+    break;
+
+  case 91:
+
+    {
+        if (((yyvsp[-2].interm.precision) == EbpHigh) && (context->getShaderType() == GL_FRAGMENT_SHADER) && !context->getFragmentPrecisionHigh()) {
+            context->error((yylsp[-3]), "precision is not supported in fragment shader", "highp");
+        }
+        if (!context->symbolTable.setDefaultPrecision( (yyvsp[-1].interm.type), (yyvsp[-2].interm.precision) )) {
+            context->error((yylsp[-3]), "illegal type argument for default precision qualifier", getBasicString((yyvsp[-1].interm.type).getBasicType()));
+        }
+        (yyval.interm.intermNode) = 0;
+    }
+
+    break;
+
+  case 92:
+
+    {
+        ES3_OR_NEWER((yyvsp[-3].lex).string->c_str(), (yylsp[-4]), "interface blocks");
+        (yyval.interm.intermNode) = context->addInterfaceBlock(*(yyvsp[-4].interm.typeQualifierBuilder), (yylsp[-3]), *(yyvsp[-3].lex).string, (yyvsp[-2].interm.fieldList), NULL, (yyloc), NULL, (yyloc));
+    }
+
+    break;
+
+  case 93:
+
+    {
+        ES3_OR_NEWER((yyvsp[-4].lex).string->c_str(), (yylsp[-5]), "interface blocks");
+        (yyval.interm.intermNode) = context->addInterfaceBlock(*(yyvsp[-5].interm.typeQualifierBuilder), (yylsp[-4]), *(yyvsp[-4].lex).string, (yyvsp[-3].interm.fieldList), (yyvsp[-1].lex).string, (yylsp[-1]), NULL, (yyloc));
+    }
+
+    break;
+
+  case 94:
+
+    {
+        ES3_OR_NEWER((yyvsp[-7].lex).string->c_str(), (yylsp[-8]), "interface blocks");
+        (yyval.interm.intermNode) = context->addInterfaceBlock(*(yyvsp[-8].interm.typeQualifierBuilder), (yylsp[-7]), *(yyvsp[-7].lex).string, (yyvsp[-6].interm.fieldList), (yyvsp[-4].lex).string, (yylsp[-4]), (yyvsp[-2].interm.intermTypedNode), (yylsp[-3]));
+    }
+
+    break;
+
+  case 95:
+
+    {
+        context->parseGlobalLayoutQualifier(*(yyvsp[-1].interm.typeQualifierBuilder));
+        (yyval.interm.intermNode) = 0;
+    }
+
+    break;
+
+  case 96:
+
+    {
+        (yyval.interm.intermNode) = context->parseInvariantDeclaration(*(yyvsp[-2].interm.typeQualifierBuilder), (yylsp[-1]), (yyvsp[-1].lex).string, (yyvsp[-1].lex).symbol);
+    }
+
+    break;
+
+  case 97:
+
+    {
+        (yyval.interm).function = context->parseFunctionDeclarator((yylsp[0]), (yyvsp[-1].interm.function));
+        context->exitFunctionDeclaration();
+    }
+
+    break;
+
+  case 98:
+
+    {
+        (yyval.interm.function) = (yyvsp[0].interm.function);
+    }
+
+    break;
+
+  case 99:
+
+    {
+        (yyval.interm.function) = (yyvsp[0].interm.function);
+    }
+
+    break;
+
+  case 100:
+
+    {
+        // Add the parameter
+        (yyval.interm.function) = (yyvsp[-1].interm.function);
+        if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid)
+            (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param.turnToConst());
+        else
+            delete (yyvsp[0].interm).param.type;
+    }
+
+    break;
+
+  case 101:
+
+    {
+        //
+        // Only first parameter of one-parameter functions can be void
+        // The check for named parameters not being void is done in parameter_declarator
+        //
+        if ((yyvsp[0].interm).param.type->getBasicType() == EbtVoid) {
+            //
+            // This parameter > first is void
+            //
+            context->error((yylsp[-1]), "cannot be an argument type except for '(void)'", "void");
+            delete (yyvsp[0].interm).param.type;
+        } else {
+            // Add the parameter
+            (yyval.interm.function) = (yyvsp[-2].interm.function);
+            (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param.turnToConst());
+        }
+    }
+
+    break;
+
+  case 102:
+
+    {
+        (yyval.interm.function) = context->parseFunctionHeader((yyvsp[-2].interm.type), (yyvsp[-1].lex).string, (yylsp[-1]));
+
+        context->symbolTable.push();
+        context->enterFunctionDeclaration();
+    }
+
+    break;
+
+  case 103:
+
+    {
+        if ((yyvsp[-1].interm.type).getBasicType() == EbtVoid) {
+            context->error((yylsp[0]), "illegal use of type 'void'", (yyvsp[0].lex).string->c_str());
+        }
+        context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
+        TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))};
+        (yyval.interm).param = param;
+    }
+
+    break;
+
+  case 104:
+
+    {
+        // Check that we can make an array out of this type
+        context->checkIsValidTypeForArray((yylsp[-2]), (yyvsp[-4].interm.type));
+
+        context->checkIsNotReserved((yylsp[-3]), *(yyvsp[-3].lex).string);
+
+        unsigned int size = context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode));
+
+        (yyvsp[-4].interm.type).setArraySize(size);
+
+        TType* type = new TType((yyvsp[-4].interm.type));
+        TParameter param = { (yyvsp[-3].lex).string, type };
+        (yyval.interm).param = param;
+    }
+
+    break;
+
+  case 105:
+
+    {
+        (yyval.interm) = (yyvsp[0].interm);
+        context->checkIsParameterQualifierValid((yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm).param.type);
+    }
+
+    break;
+
+  case 106:
+
+    {
+        (yyval.interm) = (yyvsp[0].interm);
+        (yyval.interm).param.type->setQualifier(EvqIn);
+    }
+
+    break;
+
+  case 107:
+
+    {
+        (yyval.interm) = (yyvsp[0].interm);
+        context->checkIsParameterQualifierValid((yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm).param.type);
+    }
+
+    break;
+
+  case 108:
+
+    {
+        (yyval.interm) = (yyvsp[0].interm);
+        (yyval.interm).param.type->setQualifier(EvqIn);
+    }
+
+    break;
+
+  case 109:
+
+    {
+        TParameter param = { 0, new TType((yyvsp[0].interm.type)) };
+        (yyval.interm).param = param;
+    }
+
+    break;
+
+  case 110:
+
+    {
+        (yyval.interm) = (yyvsp[0].interm);
+    }
+
+    break;
+
+  case 111:
+
+    {
+        (yyval.interm) = (yyvsp[-2].interm);
+        context->parseDeclarator((yyval.interm).type, (yylsp[0]), *(yyvsp[0].lex).string, (yyval.interm).intermDeclaration);
+    }
+
+    break;
+
+  case 112:
+
+    {
+        (yyval.interm) = (yyvsp[-5].interm);
+        context->parseArrayDeclarator((yyval.interm).type, (yylsp[-3]), *(yyvsp[-3].lex).string, (yylsp[-2]), (yyvsp[-1].interm.intermTypedNode), (yyval.interm).intermDeclaration);
+    }
+
+    break;
+
+  case 113:
+
+    {
+        ES3_OR_NEWER("[]", (yylsp[-4]), "implicitly sized array");
+        (yyval.interm) = (yyvsp[-6].interm);
+        context->parseArrayInitDeclarator((yyval.interm).type, (yylsp[-4]), *(yyvsp[-4].lex).string, (yylsp[-3]), nullptr, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode), (yyval.interm).intermDeclaration);
+    }
+
+    break;
+
+  case 114:
+
+    {
+        ES3_OR_NEWER("=", (yylsp[-1]), "first-class arrays (array initializer)");
+        (yyval.interm) = (yyvsp[-7].interm);
+        context->parseArrayInitDeclarator((yyval.interm).type, (yylsp[-5]), *(yyvsp[-5].lex).string, (yylsp[-4]), (yyvsp[-3].interm.intermTypedNode), (yylsp[-1]), (yyvsp[0].interm.intermTypedNode), (yyval.interm).intermDeclaration);
+    }
+
+    break;
+
+  case 115:
+
+    {
+        (yyval.interm) = (yyvsp[-4].interm);
+        context->parseInitDeclarator((yyval.interm).type, (yylsp[-2]), *(yyvsp[-2].lex).string, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode), (yyval.interm).intermDeclaration);
+    }
+
+    break;
+
+  case 116:
+
+    {
+        (yyval.interm).type = (yyvsp[0].interm.type);
+        (yyval.interm).intermDeclaration = context->parseSingleDeclaration((yyval.interm).type, (yylsp[0]), "");
+    }
+
+    break;
+
+  case 117:
+
+    {
+        (yyval.interm).type = (yyvsp[-1].interm.type);
+        (yyval.interm).intermDeclaration = context->parseSingleDeclaration((yyval.interm).type, (yylsp[0]), *(yyvsp[0].lex).string);
+    }
+
+    break;
+
+  case 118:
+
+    {
+        (yyval.interm).type = (yyvsp[-4].interm.type);
+        (yyval.interm).intermDeclaration = context->parseSingleArrayDeclaration((yyval.interm).type, (yylsp[-3]), *(yyvsp[-3].lex).string, (yylsp[-2]), (yyvsp[-1].interm.intermTypedNode));
+    }
+
+    break;
+
+  case 119:
+
+    {
+        ES3_OR_NEWER("[]", (yylsp[-3]), "implicitly sized array");
+        (yyval.interm).type = (yyvsp[-5].interm.type);
+        (yyval.interm).intermDeclaration = context->parseSingleArrayInitDeclaration((yyval.interm).type, (yylsp[-4]), *(yyvsp[-4].lex).string, (yylsp[-3]), nullptr, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode));
+    }
+
+    break;
+
+  case 120:
+
+    {
+        ES3_OR_NEWER("=", (yylsp[-1]), "first-class arrays (array initializer)");
+        (yyval.interm).type = (yyvsp[-6].interm.type);
+        (yyval.interm).intermDeclaration = context->parseSingleArrayInitDeclaration((yyval.interm).type, (yylsp[-5]), *(yyvsp[-5].lex).string, (yylsp[-4]), (yyvsp[-3].interm.intermTypedNode), (yylsp[-1]), (yyvsp[0].interm.intermTypedNode));
+    }
+
+    break;
+
+  case 121:
+
+    {
+        (yyval.interm).type = (yyvsp[-3].interm.type);
+        (yyval.interm).intermDeclaration = context->parseSingleInitDeclaration((yyval.interm).type, (yylsp[-2]), *(yyvsp[-2].lex).string, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode));
+    }
+
+    break;
+
+  case 122:
+
+    {
+        context->addFullySpecifiedType(&(yyvsp[0].interm.type));
+        (yyval.interm.type) = (yyvsp[0].interm.type);
+    }
+
+    break;
+
+  case 123:
+
+    {
+        (yyval.interm.type) = context->addFullySpecifiedType(*(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm.type));
+    }
+
+    break;
+
+  case 124:
+
+    {
+        (yyval.interm.qualifier) = EvqSmooth;
+    }
+
+    break;
+
+  case 125:
+
+    {
+        (yyval.interm.qualifier) = EvqFlat;
+    }
+
+    break;
+
+  case 126:
+
+    {
+        (yyval.interm.typeQualifierBuilder) = context->createTypeQualifierBuilder((yylsp[0]));
+        (yyval.interm.typeQualifierBuilder)->appendQualifier((yyvsp[0].interm.qualifierWrapper));
+    }
+
+    break;
+
+  case 127:
+
+    {
+        (yyval.interm.typeQualifierBuilder) = (yyvsp[-1].interm.typeQualifierBuilder);
+        (yyval.interm.typeQualifierBuilder)->appendQualifier((yyvsp[0].interm.qualifierWrapper));
+    }
+
+    break;
+
+  case 128:
+
+    {
+        // empty
+    }
+
+    break;
+
+  case 129:
+
+    {
+        context->checkLocalVariableConstStorageQualifier(*(yyvsp[0].interm.qualifierWrapper));
+        (yyval.interm.qualifierWrapper) = (yyvsp[0].interm.qualifierWrapper);
+    }
+
+    break;
+
+  case 130:
+
+    {
+        context->checkIsAtGlobalLevel((yylsp[0]), "layout");
+        (yyval.interm.qualifierWrapper) = new TLayoutQualifierWrapper((yyvsp[0].interm.layoutQualifier), (yylsp[0]));
+    }
+
+    break;
+
+  case 131:
+
+    {
+        (yyval.interm.qualifierWrapper) = new TPrecisionQualifierWrapper((yyvsp[0].interm.precision), (yylsp[0]));
+    }
+
+    break;
+
+  case 132:
+
+    {
+        (yyval.interm.qualifierWrapper) = new TInterpolationQualifierWrapper((yyvsp[0].interm.qualifier), (yylsp[0]));
+    }
+
+    break;
+
+  case 133:
+
+    {
+        context->checkIsAtGlobalLevel((yylsp[0]), "invariant");
+        (yyval.interm.qualifierWrapper) = new TInvariantQualifierWrapper((yylsp[0]));
+    }
+
+    break;
+
+  case 134:
+
+    {
+        VERTEX_ONLY("attribute", (yylsp[0]));
+        ES2_ONLY("attribute", (yylsp[0]));
+        context->checkIsAtGlobalLevel((yylsp[0]), "attribute");
+        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqAttribute, (yylsp[0]));
+    }
+
+    break;
+
+  case 135:
+
+    {
+        ES2_ONLY("varying", (yylsp[0]));
+        context->checkIsAtGlobalLevel((yylsp[0]), "varying");
+        if (context->getShaderType() == GL_VERTEX_SHADER)
+            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVaryingOut, (yylsp[0]));
+        else
+            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVaryingIn, (yylsp[0]));
+    }
+
+    break;
+
+  case 136:
+
+    {
+        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqConst, (yylsp[0]));
+    }
+
+    break;
+
+  case 137:
+
+    {
+        if (context->declaringFunction())
+        {
+            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqIn, (yylsp[0]));
+        }
+        else if (context->getShaderType() == GL_FRAGMENT_SHADER)
+        {
+            ES3_OR_NEWER("in", (yylsp[0]), "storage qualifier");
+            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqFragmentIn, (yylsp[0]));
+        }
+        else if (context->getShaderType() == GL_VERTEX_SHADER)
+        {
+            ES3_OR_NEWER("in", (yylsp[0]), "storage qualifier");
+            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVertexIn, (yylsp[0]));
+        }
+        else
+        {
+            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqComputeIn, (yylsp[0]));
+        }
+    }
+
+    break;
+
+  case 138:
+
+    {
+        if (context->declaringFunction())
+        {
+            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqOut, (yylsp[0]));
+        }
+        else
+        {
+            ES3_OR_NEWER("out", (yylsp[0]), "storage qualifier");
+            NON_COMPUTE_ONLY("out", (yylsp[0]));
+            if (context->getShaderType() == GL_FRAGMENT_SHADER)
+            {
+                (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqFragmentOut, (yylsp[0]));
+            }
+            else
+            {
+                (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVertexOut, (yylsp[0]));
+            }
+        }
+    }
+
+    break;
+
+  case 139:
+
+    {
+        if (!context->declaringFunction())
+        {
+            context->error((yylsp[0]), "invalid qualifier: can be only used with function parameters", "inout");
+        }
+        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqInOut, (yylsp[0]));
+    }
+
+    break;
+
+  case 140:
+
+    {
+        ES3_OR_NEWER("centroid", (yylsp[0]), "storage qualifier");
+        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqCentroid, (yylsp[0]));
+    }
+
+    break;
+
+  case 141:
+
+    {
+        context->checkIsAtGlobalLevel((yylsp[0]), "uniform");
+        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqUniform, (yylsp[0]));
+    }
+
+    break;
+
+  case 142:
+
+    {
+        (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqReadOnly, (yylsp[0]));
+    }
+
+    break;
+
+  case 143:
+
+    {
+        (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqWriteOnly, (yylsp[0]));
+    }
+
+    break;
+
+  case 144:
+
+    {
+        (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqCoherent, (yylsp[0]));
+    }
+
+    break;
+
+  case 145:
+
+    {
+        (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqRestrict, (yylsp[0]));
+    }
+
+    break;
+
+  case 146:
+
+    {
+        (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqVolatile, (yylsp[0]));
+    }
+
+    break;
+
+  case 147:
+
+    {
+        context->checkIsAtGlobalLevel((yylsp[0]), "shared");
+        COMPUTE_ONLY("shared", (yylsp[0]));
+        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqShared, (yylsp[0]));
+    }
+
+    break;
+
+  case 148:
+
+    {
+        (yyval.interm.type) = (yyvsp[0].interm.type);
+        (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[0].interm.type).getBasicType());
+    }
+
+    break;
+
+  case 149:
+
+    {
+        (yyval.interm.precision) = EbpHigh;
+    }
+
+    break;
+
+  case 150:
+
+    {
+        (yyval.interm.precision) = EbpMedium;
+    }
+
+    break;
+
+  case 151:
+
+    {
+        (yyval.interm.precision) = EbpLow;
+    }
+
+    break;
+
+  case 152:
+
+    {
+        ES3_OR_NEWER("layout", (yylsp[-3]), "qualifier");
+        (yyval.interm.layoutQualifier) = (yyvsp[-1].interm.layoutQualifier);
+    }
+
+    break;
+
+  case 153:
+
+    {
+        (yyval.interm.layoutQualifier) = (yyvsp[0].interm.layoutQualifier);
+    }
+
+    break;
+
+  case 154:
+
+    {
+        (yyval.interm.layoutQualifier) = context->joinLayoutQualifiers((yyvsp[-2].interm.layoutQualifier), (yyvsp[0].interm.layoutQualifier), (yylsp[0]));
+    }
+
+    break;
+
+  case 155:
+
+    {
+        (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(*(yyvsp[0].lex).string, (yylsp[0]));
+    }
+
+    break;
+
+  case 156:
+
+    {
+        (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(*(yyvsp[-2].lex).string, (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0]));
+    }
+
+    break;
+
+  case 157:
+
+    {
+        (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(*(yyvsp[-2].lex).string, (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0]));
+    }
+
+    break;
+
+  case 158:
+
+    {
+        (yyval.interm.layoutQualifier) = context->parseLayoutQualifier("shared", (yylsp[0]));
+    }
+
+    break;
+
+  case 159:
+
+    {
+        (yyval.interm.type).initialize((yyvsp[0].interm.typeSpecifierNonArray), (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+    }
+
+    break;
+
+  case 160:
+
+    {
+        ES3_OR_NEWER("[]", (yylsp[-1]), "implicitly sized array");
+        (yyval.interm.type).initialize((yyvsp[-2].interm.typeSpecifierNonArray), (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+        (yyval.interm.type).setArraySize(0);
+    }
+
+    break;
+
+  case 161:
+
+    {
+        (yyval.interm.type).initialize((yyvsp[-3].interm.typeSpecifierNonArray), (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+        if (context->checkIsValidTypeForArray((yylsp[-2]), (yyval.interm.type)))
+        {
+            unsigned int size = context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode));
+            (yyval.interm.type).setArraySize(size);
+        }
+    }
+
+    break;
+
+  case 162:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtVoid, (yylsp[0]));
+    }
+
+    break;
+
+  case 163:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+    }
+
+    break;
+
+  case 164:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
+    }
+
+    break;
+
+  case 165:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
+    }
+
+    break;
+
+  case 166:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
+    }
+
+    break;
+
+  case 167:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(2);
+    }
+
+    break;
+
+  case 168:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(3);
+    }
+
+    break;
+
+  case 169:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(4);
+    }
+
+    break;
+
+  case 170:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(2);
+    }
+
+    break;
+
+  case 171:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(3);
+    }
+
+    break;
+
+  case 172:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(4);
+    }
+
+    break;
+
+  case 173:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(2);
+    }
+
+    break;
+
+  case 174:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(3);
+    }
+
+    break;
+
+  case 175:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(4);
+    }
+
+    break;
+
+  case 176:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(2);
+    }
+
+    break;
+
+  case 177:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(3);
+    }
+
+    break;
+
+  case 178:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(4);
+    }
+
+    break;
+
+  case 179:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(2, 2);
+    }
+
+    break;
+
+  case 180:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(3, 3);
+    }
+
+    break;
+
+  case 181:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(4, 4);
+    }
+
+    break;
+
+  case 182:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(2, 3);
+    }
+
+    break;
+
+  case 183:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(3, 2);
+    }
+
+    break;
+
+  case 184:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(2, 4);
+    }
+
+    break;
+
+  case 185:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(4, 2);
+    }
+
+    break;
+
+  case 186:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(3, 4);
+    }
+
+    break;
+
+  case 187:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(4, 3);
+    }
+
+    break;
+
+  case 188:
+
+    {
+        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+            context->error((yylsp[0]), "unsupported type", "yuvCscStandardEXT");
+        }
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtYuvCscStandardEXT, (yylsp[0]));
+    }
+
+    break;
+
+  case 189:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2D, (yylsp[0]));
+    }
+
+    break;
+
+  case 190:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler3D, (yylsp[0]));
+    }
+
+    break;
+
+  case 191:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCube, (yylsp[0]));
+    }
+
+    break;
+
+  case 192:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArray, (yylsp[0]));
+    }
+
+    break;
+
+  case 193:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DMS, (yylsp[0]));
+    }
+
+    break;
+
+  case 194:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2D, (yylsp[0]));
+    }
+
+    break;
+
+  case 195:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler3D, (yylsp[0]));
+    }
+
+    break;
+
+  case 196:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtISamplerCube, (yylsp[0]));
+    }
+
+    break;
+
+  case 197:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DArray, (yylsp[0]));
+    }
+
+    break;
+
+  case 198:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DMS, (yylsp[0]));
+    }
+
+    break;
+
+  case 199:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2D, (yylsp[0]));
+    }
+
+    break;
+
+  case 200:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler3D, (yylsp[0]));
+    }
+
+    break;
+
+  case 201:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUSamplerCube, (yylsp[0]));
+    }
+
+    break;
+
+  case 202:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DArray, (yylsp[0]));
+    }
+
+    break;
+
+  case 203:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DMS, (yylsp[0]));
+    }
+
+    break;
+
+  case 204:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DShadow, (yylsp[0]));
+    }
+
+    break;
+
+  case 205:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeShadow, (yylsp[0]));
+    }
+
+    break;
+
+  case 206:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArrayShadow, (yylsp[0]));
+    }
+
+    break;
+
+  case 207:
+
+    {
+        if (!context->supportsExtension("GL_OES_EGL_image_external") &&
+            !context->supportsExtension("GL_NV_EGL_stream_consumer_external")) {
+            context->error((yylsp[0]), "unsupported type", "samplerExternalOES");
+        }
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternalOES, (yylsp[0]));
+    }
+
+    break;
+
+  case 208:
+
+    {
+        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+            context->error((yylsp[0]), "unsupported type", "__samplerExternal2DY2YEXT");
+        }
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternal2DY2YEXT, (yylsp[0]));
+    }
+
+    break;
+
+  case 209:
+
+    {
+        if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
+            context->error((yylsp[0]), "unsupported type", "sampler2DRect");
+        }
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DRect, (yylsp[0]));
+    }
+
+    break;
+
+  case 210:
+
+    {
+        (yyval.interm.typeSpecifierNonArray) = (yyvsp[0].interm.typeSpecifierNonArray);
+    }
+
+    break;
+
+  case 211:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2D, (yylsp[0]));
+    }
+
+    break;
+
+  case 212:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2D, (yylsp[0]));
+    }
+
+    break;
+
+  case 213:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2D, (yylsp[0]));
+    }
+
+    break;
+
+  case 214:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtImage3D, (yylsp[0]));
+    }
+
+    break;
+
+  case 215:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage3D, (yylsp[0]));
+    }
+
+    break;
+
+  case 216:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage3D, (yylsp[0]));
+    }
+
+    break;
+
+  case 217:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2DArray, (yylsp[0]));
+    }
+
+    break;
+
+  case 218:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2DArray, (yylsp[0]));
+    }
+
+    break;
+
+  case 219:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2DArray, (yylsp[0]));
+    }
+
+    break;
+
+  case 220:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtImageCube, (yylsp[0]));
+    }
+
+    break;
+
+  case 221:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtIImageCube, (yylsp[0]));
+    }
+
+    break;
+
+  case 222:
+
+    {
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUImageCube, (yylsp[0]));
+    }
+
+    break;
+
+  case 223:
+
+    {
+        //
+        // This is for user defined type names.  The lexical phase looked up the
+        // type.
+        //
+        TType& structure = static_cast<TVariable*>((yyvsp[0].lex).symbol)->getType();
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtStruct, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).userDef = &structure;
+    }
+
+    break;
+
+  case 224:
+
+    { context->enterStructDeclaration((yylsp[-1]), *(yyvsp[-1].lex).string); }
+
+    break;
+
+  case 225:
+
+    {
+        (yyval.interm.typeSpecifierNonArray) = context->addStructure((yylsp[-5]), (yylsp[-4]), (yyvsp[-4].lex).string, (yyvsp[-1].interm.fieldList));
+    }
+
+    break;
+
+  case 226:
+
+    { context->enterStructDeclaration((yylsp[0]), *(yyvsp[0].lex).string); }
+
+    break;
+
+  case 227:
+
+    {
+        (yyval.interm.typeSpecifierNonArray) = context->addStructure((yylsp[-4]), (yyloc), NewPoolTString(""), (yyvsp[-1].interm.fieldList));
+    }
+
+    break;
+
+  case 228:
+
+    {
+        (yyval.interm.fieldList) = (yyvsp[0].interm.fieldList);
+    }
+
+    break;
+
+  case 229:
+
+    {
+        (yyval.interm.fieldList) = context->combineStructFieldLists((yyvsp[-1].interm.fieldList), (yyvsp[0].interm.fieldList), (yylsp[0]));
+    }
+
+    break;
+
+  case 230:
+
+    {
+        (yyval.interm.fieldList) = context->addStructDeclaratorList((yyvsp[-2].interm.type), (yyvsp[-1].interm.fieldList));
+    }
+
+    break;
+
+  case 231:
+
+    {
+        // ES3 Only, but errors should be handled elsewhere
+        (yyval.interm.fieldList) = context->addStructDeclaratorListWithQualifiers(*(yyvsp[-3].interm.typeQualifierBuilder), &(yyvsp[-2].interm.type), (yyvsp[-1].interm.fieldList));
+    }
+
+    break;
+
+  case 232:
+
+    {
+        (yyval.interm.fieldList) = NewPoolTFieldList();
+        (yyval.interm.fieldList)->push_back((yyvsp[0].interm.field));
+    }
+
+    break;
+
+  case 233:
+
+    {
+        (yyval.interm.fieldList)->push_back((yyvsp[0].interm.field));
+    }
+
+    break;
+
+  case 234:
+
+    {
+        context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
+
+        TType* type = new TType(EbtVoid, EbpUndefined);
+        (yyval.interm.field) = new TField(type, (yyvsp[0].lex).string, (yylsp[0]));
+    }
+
+    break;
+
+  case 235:
+
+    {
+        context->checkIsNotReserved((yylsp[-3]), *(yyvsp[-3].lex).string);
+
+        TType* type = new TType(EbtVoid, EbpUndefined);
+        unsigned int size = context->checkIsValidArraySize((yylsp[-1]), (yyvsp[-1].interm.intermTypedNode));
+        type->setArraySize(size);
+
+        (yyval.interm.field) = new TField(type, (yyvsp[-3].lex).string, (yylsp[-3]));
+    }
+
+    break;
+
+  case 236:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+
+    break;
+
+  case 237:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+
+    break;
+
+  case 238:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); }
+
+    break;
+
+  case 239:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+
+    break;
+
+  case 240:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+
+    break;
+
+  case 241:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+
+    break;
+
+  case 242:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+
+    break;
+
+  case 243:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermSwitch); }
+
+    break;
+
+  case 244:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermCase); }
+
+    break;
+
+  case 245:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+
+    break;
+
+  case 246:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+
+    break;
+
+  case 247:
+
+    { (yyval.interm.intermBlock) = 0; }
+
+    break;
+
+  case 248:
+
+    { context->symbolTable.push(); }
+
+    break;
+
+  case 249:
+
+    { context->symbolTable.pop(); }
+
+    break;
+
+  case 250:
+
+    {
+        if ((yyvsp[-2].interm.intermBlock) != 0) {
+            (yyvsp[-2].interm.intermBlock)->setLine((yyloc));
+        }
+        (yyval.interm.intermBlock) = (yyvsp[-2].interm.intermBlock);
+    }
+
+    break;
+
+  case 251:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); }
+
+    break;
+
+  case 252:
+
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+
+    break;
+
+  case 253:
+
+    { context->symbolTable.push(); }
+
+    break;
+
+  case 254:
+
+    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); }
+
+    break;
+
+  case 255:
+
+    { context->symbolTable.push(); }
+
+    break;
+
+  case 256:
+
+    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+
+    break;
+
+  case 257:
+
+    {
+        (yyval.interm.intermBlock) = 0;
+    }
+
+    break;
+
+  case 258:
+
+    {
+        if ((yyvsp[-1].interm.intermBlock)) {
+            (yyvsp[-1].interm.intermBlock)->setLine((yyloc));
+        }
+        (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock);
+    }
+
+    break;
+
+  case 259:
+
+    {
+        (yyval.interm.intermBlock) = new TIntermBlock();
+        (yyval.interm.intermBlock)->setLine((yyloc));
+        (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode));
+    }
+
+    break;
+
+  case 260:
+
+    {
+        (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock);
+        (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode));
+    }
+
+    break;
+
+  case 261:
+
+    { (yyval.interm.intermNode) = 0; }
+
+    break;
+
+  case 262:
+
+    { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[-1].interm.intermTypedNode)); }
+
+    break;
+
+  case 263:
+
+    {
+        context->checkIsScalarBool((yylsp[-4]), (yyvsp[-2].interm.intermTypedNode));
+        (yyval.interm.intermNode) = context->intermediate.addIfElse((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yylsp[-4]));
+    }
+
+    break;
+
+  case 264:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode);
+        (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode);
+    }
+
+    break;
+
+  case 265:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode);
+        (yyval.interm.nodePair).node2 = 0;
+    }
+
+    break;
+
+  case 266:
+
+    { context->incrSwitchNestingLevel(); }
+
+    break;
+
+  case 267:
+
+    {
+        (yyval.interm.intermSwitch) = context->addSwitch((yyvsp[-3].interm.intermTypedNode), (yyvsp[0].interm.intermBlock), (yylsp[-5]));
+        context->decrSwitchNestingLevel();
+    }
+
+    break;
+
+  case 268:
+
+    {
+        (yyval.interm.intermCase) = context->addCase((yyvsp[-1].interm.intermTypedNode), (yylsp[-2]));
+    }
+
+    break;
+
+  case 269:
+
+    {
+        (yyval.interm.intermCase) = context->addDefault((yylsp[-1]));
+    }
+
+    break;
+
+  case 270:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+        context->checkIsScalarBool((yyvsp[0].interm.intermTypedNode)->getLine(), (yyvsp[0].interm.intermTypedNode));
+    }
+
+    break;
+
+  case 271:
+
+    {
+        TIntermBinary *initNode = nullptr;
+        context->checkIsScalarBool((yylsp[-2]), (yyvsp[-3].interm.type));
+
+        if (!context->executeInitializer((yylsp[-2]), *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), (yyvsp[0].interm.intermTypedNode), &initNode))
+            (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+        else {
+            (yyval.interm.intermTypedNode) = 0;
+        }
+    }
+
+    break;
+
+  case 272:
+
+    { context->symbolTable.push(); context->incrLoopNestingLevel(); }
+
+    break;
+
+  case 273:
+
+    {
+        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopWhile, 0, (yyvsp[-2].interm.intermTypedNode), 0, (yyvsp[0].interm.intermNode), (yylsp[-5]));
+        context->decrLoopNestingLevel();
+    }
+
+    break;
+
+  case 274:
+
+    { context->incrLoopNestingLevel(); }
+
+    break;
+
+  case 275:
+
+    {
+        context->checkIsScalarBool((yylsp[0]), (yyvsp[-2].interm.intermTypedNode));
+
+        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[-2].interm.intermTypedNode), 0, (yyvsp[-5].interm.intermNode), (yylsp[-4]));
+        context->decrLoopNestingLevel();
+    }
+
+    break;
+
+  case 276:
+
+    { context->symbolTable.push(); context->incrLoopNestingLevel(); }
+
+    break;
+
+  case 277:
+
+    {
+        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopFor, (yyvsp[-3].interm.intermNode), reinterpret_cast<TIntermTyped*>((yyvsp[-2].interm.nodePair).node1), reinterpret_cast<TIntermTyped*>((yyvsp[-2].interm.nodePair).node2), (yyvsp[0].interm.intermNode), (yylsp[-6]));
+        context->decrLoopNestingLevel();
+    }
+
+    break;
+
+  case 278:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+    }
+
+    break;
+
+  case 279:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+    }
+
+    break;
+
+  case 280:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 281:
+
+    {
+        (yyval.interm.intermTypedNode) = 0;
+    }
+
+    break;
+
+  case 282:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode);
+        (yyval.interm.nodePair).node2 = 0;
+    }
+
+    break;
+
+  case 283:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode);
+        (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode);
+    }
+
+    break;
+
+  case 284:
+
+    {
+        (yyval.interm.intermNode) = context->addBranch(EOpContinue, (yylsp[-1]));
+    }
+
+    break;
+
+  case 285:
+
+    {
+        (yyval.interm.intermNode) = context->addBranch(EOpBreak, (yylsp[-1]));
+    }
+
+    break;
+
+  case 286:
+
+    {
+        (yyval.interm.intermNode) = context->addBranch(EOpReturn, (yylsp[-1]));
+    }
+
+    break;
+
+  case 287:
+
+    {
+        (yyval.interm.intermNode) = context->addBranch(EOpReturn, (yyvsp[-1].interm.intermTypedNode), (yylsp[-2]));
+    }
+
+    break;
+
+  case 288:
+
+    {
+        FRAG_ONLY("discard", (yylsp[-1]));
+        (yyval.interm.intermNode) = context->addBranch(EOpKill, (yylsp[-1]));
+    }
+
+    break;
+
+  case 289:
+
+    {
+        (yyval.interm.intermBlock) = new TIntermBlock();
+        (yyval.interm.intermBlock)->setLine((yyloc));
+        (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode));
+        context->setTreeRoot((yyval.interm.intermBlock));
+    }
+
+    break;
+
+  case 290:
+
+    {
+        (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode));
+    }
+
+    break;
+
+  case 291:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+    }
+
+    break;
+
+  case 292:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+    }
+
+    break;
+
+  case 293:
+
+    {
+        context->parseFunctionDefinitionHeader((yylsp[0]), &((yyvsp[0].interm).function), &((yyvsp[0].interm).intermFunctionPrototype));
+    }
+
+    break;
+
+  case 294:
+
+    {
+        (yyval.interm.intermNode) = context->addFunctionDefinition((yyvsp[-2].interm).intermFunctionPrototype, (yyvsp[0].interm.intermBlock), (yylsp[-2]));
+    }
+
+    break;
+
+
+
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+  *++yylsp = yyloc;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (&yylloc, context, scanner, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (&yylloc, context, scanner, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+  yyerror_range[1] = yylloc;
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, &yylloc, context, scanner);
+          yychar = YYEMPTY;
+        }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  yyerror_range[1] = yylsp[1-yylen];
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+      yyerror_range[1] = *yylsp;
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, yylsp, context, scanner);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  yyerror_range[2] = yylloc;
+  /* Using YYLLOC is tempting, but would change the location of
+     the lookahead.  YYLOC is available though.  */
+  YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
+  *++yylsp = yyloc;
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (&yylloc, context, scanner, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, &yylloc, context, scanner);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp, yylsp, context, scanner);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
+
+
+
+int glslang_parse(TParseContext* context) {
+    return yyparse(context, context->getScanner());
+}
diff --git a/src/third_party/angle/src/compiler/translator/glslang_tab.h b/src/third_party/angle/src/compiler/translator/glslang_tab.h
new file mode 100644
index 0000000..49aae95
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/glslang_tab.h
@@ -0,0 +1,272 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_YY_GLSLANG_TAB_H_INCLUDED
+#define YY_YY_GLSLANG_TAB_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+/* "%code requires" blocks.  */
+
+#define YYLTYPE TSourceLoc
+#define YYLTYPE_IS_DECLARED 1
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+#define YYTOKENTYPE
+enum yytokentype
+{
+    INVARIANT                 = 258,
+    HIGH_PRECISION            = 259,
+    MEDIUM_PRECISION          = 260,
+    LOW_PRECISION             = 261,
+    PRECISION                 = 262,
+    ATTRIBUTE                 = 263,
+    CONST_QUAL                = 264,
+    BOOL_TYPE                 = 265,
+    FLOAT_TYPE                = 266,
+    INT_TYPE                  = 267,
+    UINT_TYPE                 = 268,
+    BREAK                     = 269,
+    CONTINUE                  = 270,
+    DO                        = 271,
+    ELSE                      = 272,
+    FOR                       = 273,
+    IF                        = 274,
+    DISCARD                   = 275,
+    RETURN                    = 276,
+    SWITCH                    = 277,
+    CASE                      = 278,
+    DEFAULT                   = 279,
+    BVEC2                     = 280,
+    BVEC3                     = 281,
+    BVEC4                     = 282,
+    IVEC2                     = 283,
+    IVEC3                     = 284,
+    IVEC4                     = 285,
+    VEC2                      = 286,
+    VEC3                      = 287,
+    VEC4                      = 288,
+    UVEC2                     = 289,
+    UVEC3                     = 290,
+    UVEC4                     = 291,
+    MATRIX2                   = 292,
+    MATRIX3                   = 293,
+    MATRIX4                   = 294,
+    IN_QUAL                   = 295,
+    OUT_QUAL                  = 296,
+    INOUT_QUAL                = 297,
+    UNIFORM                   = 298,
+    VARYING                   = 299,
+    MATRIX2x3                 = 300,
+    MATRIX3x2                 = 301,
+    MATRIX2x4                 = 302,
+    MATRIX4x2                 = 303,
+    MATRIX3x4                 = 304,
+    MATRIX4x3                 = 305,
+    CENTROID                  = 306,
+    FLAT                      = 307,
+    SMOOTH                    = 308,
+    READONLY                  = 309,
+    WRITEONLY                 = 310,
+    COHERENT                  = 311,
+    RESTRICT                  = 312,
+    VOLATILE                  = 313,
+    SHARED                    = 314,
+    STRUCT                    = 315,
+    VOID_TYPE                 = 316,
+    WHILE                     = 317,
+    SAMPLER2D                 = 318,
+    SAMPLERCUBE               = 319,
+    SAMPLER_EXTERNAL_OES      = 320,
+    SAMPLER2DRECT             = 321,
+    SAMPLER2DARRAY            = 322,
+    ISAMPLER2D                = 323,
+    ISAMPLER3D                = 324,
+    ISAMPLERCUBE              = 325,
+    ISAMPLER2DARRAY           = 326,
+    USAMPLER2D                = 327,
+    USAMPLER3D                = 328,
+    USAMPLERCUBE              = 329,
+    USAMPLER2DARRAY           = 330,
+    SAMPLER2DMS               = 331,
+    ISAMPLER2DMS              = 332,
+    USAMPLER2DMS              = 333,
+    SAMPLER3D                 = 334,
+    SAMPLER3DRECT             = 335,
+    SAMPLER2DSHADOW           = 336,
+    SAMPLERCUBESHADOW         = 337,
+    SAMPLER2DARRAYSHADOW      = 338,
+    SAMPLEREXTERNAL2DY2YEXT   = 339,
+    IMAGE2D                   = 340,
+    IIMAGE2D                  = 341,
+    UIMAGE2D                  = 342,
+    IMAGE3D                   = 343,
+    IIMAGE3D                  = 344,
+    UIMAGE3D                  = 345,
+    IMAGE2DARRAY              = 346,
+    IIMAGE2DARRAY             = 347,
+    UIMAGE2DARRAY             = 348,
+    IMAGECUBE                 = 349,
+    IIMAGECUBE                = 350,
+    UIMAGECUBE                = 351,
+    LAYOUT                    = 352,
+    YUVCSCSTANDARDEXT         = 353,
+    YUVCSCSTANDARDEXTCONSTANT = 354,
+    IDENTIFIER                = 355,
+    TYPE_NAME                 = 356,
+    FLOATCONSTANT             = 357,
+    INTCONSTANT               = 358,
+    UINTCONSTANT              = 359,
+    BOOLCONSTANT              = 360,
+    FIELD_SELECTION           = 361,
+    LEFT_OP                   = 362,
+    RIGHT_OP                  = 363,
+    INC_OP                    = 364,
+    DEC_OP                    = 365,
+    LE_OP                     = 366,
+    GE_OP                     = 367,
+    EQ_OP                     = 368,
+    NE_OP                     = 369,
+    AND_OP                    = 370,
+    OR_OP                     = 371,
+    XOR_OP                    = 372,
+    MUL_ASSIGN                = 373,
+    DIV_ASSIGN                = 374,
+    ADD_ASSIGN                = 375,
+    MOD_ASSIGN                = 376,
+    LEFT_ASSIGN               = 377,
+    RIGHT_ASSIGN              = 378,
+    AND_ASSIGN                = 379,
+    XOR_ASSIGN                = 380,
+    OR_ASSIGN                 = 381,
+    SUB_ASSIGN                = 382,
+    LEFT_PAREN                = 383,
+    RIGHT_PAREN               = 384,
+    LEFT_BRACKET              = 385,
+    RIGHT_BRACKET             = 386,
+    LEFT_BRACE                = 387,
+    RIGHT_BRACE               = 388,
+    DOT                       = 389,
+    COMMA                     = 390,
+    COLON                     = 391,
+    EQUAL                     = 392,
+    SEMICOLON                 = 393,
+    BANG                      = 394,
+    DASH                      = 395,
+    TILDE                     = 396,
+    PLUS                      = 397,
+    STAR                      = 398,
+    SLASH                     = 399,
+    PERCENT                   = 400,
+    LEFT_ANGLE                = 401,
+    RIGHT_ANGLE               = 402,
+    VERTICAL_BAR              = 403,
+    CARET                     = 404,
+    AMPERSAND                 = 405,
+    QUESTION                  = 406
+};
+#endif
+
+/* Value type.  */
+#if !defined YYSTYPE && !defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE {
+
+    struct
+    {
+        union {
+            TString *string;
+            float f;
+            int i;
+            unsigned int u;
+            bool b;
+        };
+        TSymbol *symbol;
+    } lex;
+    struct
+    {
+        TOperator op;
+        union {
+            TIntermNode *intermNode;
+            TIntermNodePair nodePair;
+            TIntermFunctionCallOrMethod callOrMethodPair;
+            TIntermTyped *intermTypedNode;
+            TIntermAggregate *intermAggregate;
+            TIntermBlock *intermBlock;
+            TIntermDeclaration *intermDeclaration;
+            TIntermFunctionPrototype *intermFunctionPrototype;
+            TIntermSwitch *intermSwitch;
+            TIntermCase *intermCase;
+        };
+        union {
+            TTypeSpecifierNonArray typeSpecifierNonArray;
+            TPublicType type;
+            TPrecision precision;
+            TLayoutQualifier layoutQualifier;
+            TQualifier qualifier;
+            TFunction *function;
+            TParameter param;
+            TField *field;
+            TFieldList *fieldList;
+            TQualifierWrapperBase *qualifierWrapper;
+            TTypeQualifierBuilder *typeQualifierBuilder;
+        };
+    } interm;
+};
+
+typedef union YYSTYPE YYSTYPE;
+#define YYSTYPE_IS_TRIVIAL 1
+#define YYSTYPE_IS_DECLARED 1
+#endif
+
+/* Location type.  */
+#if !defined YYLTYPE && !defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE YYLTYPE;
+struct YYLTYPE
+{
+    int first_line;
+    int first_column;
+    int last_line;
+    int last_column;
+};
+#define YYLTYPE_IS_DECLARED 1
+#define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+int yyparse(TParseContext *context, void *scanner);
+
+#endif /* !YY_YY_GLSLANG_TAB_H_INCLUDED  */
diff --git a/src/third_party/angle/src/compiler/translator/intermOut.cpp b/src/third_party/angle/src/compiler/translator/intermOut.cpp
new file mode 100644
index 0000000..d3e48ed
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/intermOut.cpp
@@ -0,0 +1,717 @@
+//
+// 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.
+//
+
+#include "compiler/translator/Intermediate.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void OutputFunction(TInfoSinkBase &out, const char *str, TFunctionSymbolInfo *info)
+{
+    const char *internal = info->getNameObj().isInternal() ? " (internal function)" : "";
+    out << str << internal << ": " << info->getNameObj().getString() << " (symbol id "
+        << info->getId().get() << ")";
+}
+
+//
+// Two purposes:
+// 1.  Show an example of how to iterate tree.  Functions can
+//     also directly call Traverse() on children themselves to
+//     have finer grained control over the process than shown here.
+//     See the last function for how to get started.
+// 2.  Print out a text based description of the tree.
+//
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TOutputTraverser : public TIntermTraverser
+{
+  public:
+    TOutputTraverser(TInfoSinkBase &i) : TIntermTraverser(true, false, false), sink(i) {}
+    TInfoSinkBase &sink;
+
+  protected:
+    void visitSymbol(TIntermSymbol *) override;
+    void visitConstantUnion(TIntermConstantUnion *) override;
+    bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
+    bool visitBinary(Visit visit, TIntermBinary *) override;
+    bool visitUnary(Visit visit, TIntermUnary *) override;
+    bool visitTernary(Visit visit, TIntermTernary *node) override;
+    bool visitIfElse(Visit visit, TIntermIfElse *node) override;
+    bool visitSwitch(Visit visit, TIntermSwitch *node) override;
+    bool visitCase(Visit visit, TIntermCase *node) override;
+    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *) override;
+    bool visitBlock(Visit visit, TIntermBlock *) override;
+    bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
+    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+    bool visitLoop(Visit visit, TIntermLoop *) override;
+    bool visitBranch(Visit visit, TIntermBranch *) override;
+};
+
+//
+// Helper functions for printing, not part of traversing.
+//
+void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth)
+{
+    int i;
+
+    sink.location(node->getLine().first_file, node->getLine().first_line);
+
+    for (i = 0; i < depth; ++i)
+        sink << "  ";
+}
+
+}  // namespace anonymous
+
+//
+// The rest of the file are the traversal functions.  The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children.  If you process children yourself,
+// return false.
+//
+
+void TOutputTraverser::visitSymbol(TIntermSymbol *node)
+{
+    OutputTreeText(sink, node, mDepth);
+
+    sink << "'" << node->getSymbol() << "' ";
+    sink << "(" << node->getCompleteString() << ")\n";
+}
+
+bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
+{
+    TInfoSinkBase &out = sink;
+    OutputTreeText(out, node, mDepth);
+    out << "vector swizzle (";
+    node->writeOffsetsAsXYZW(&out);
+    out << ")";
+
+    out << " (" << node->getCompleteString() << ")";
+    out << "\n";
+    return true;
+}
+
+bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+
+    switch (node->getOp())
+    {
+        case EOpComma:
+            out << "comma";
+            break;
+        case EOpAssign:
+            out << "move second child to first child";
+            break;
+        case EOpInitialize:
+            out << "initialize first child with second child";
+            break;
+        case EOpAddAssign:
+            out << "add second child into first child";
+            break;
+        case EOpSubAssign:
+            out << "subtract second child into first child";
+            break;
+        case EOpMulAssign:
+            out << "multiply second child into first child";
+            break;
+        case EOpVectorTimesMatrixAssign:
+            out << "matrix mult second child into first child";
+            break;
+        case EOpVectorTimesScalarAssign:
+            out << "vector scale second child into first child";
+            break;
+        case EOpMatrixTimesScalarAssign:
+            out << "matrix scale second child into first child";
+            break;
+        case EOpMatrixTimesMatrixAssign:
+            out << "matrix mult second child into first child";
+            break;
+        case EOpDivAssign:
+            out << "divide second child into first child";
+            break;
+        case EOpIModAssign:
+            out << "modulo second child into first child";
+            break;
+        case EOpBitShiftLeftAssign:
+            out << "bit-wise shift first child left by second child";
+            break;
+        case EOpBitShiftRightAssign:
+            out << "bit-wise shift first child right by second child";
+            break;
+        case EOpBitwiseAndAssign:
+            out << "bit-wise and second child into first child";
+            break;
+        case EOpBitwiseXorAssign:
+            out << "bit-wise xor second child into first child";
+            break;
+        case EOpBitwiseOrAssign:
+            out << "bit-wise or second child into first child";
+            break;
+
+        case EOpIndexDirect:
+            out << "direct index";
+            break;
+        case EOpIndexIndirect:
+            out << "indirect index";
+            break;
+        case EOpIndexDirectStruct:
+            out << "direct index for structure";
+            break;
+        case EOpIndexDirectInterfaceBlock:
+            out << "direct index for interface block";
+            break;
+
+        case EOpAdd:
+            out << "add";
+            break;
+        case EOpSub:
+            out << "subtract";
+            break;
+        case EOpMul:
+            out << "component-wise multiply";
+            break;
+        case EOpDiv:
+            out << "divide";
+            break;
+        case EOpIMod:
+            out << "modulo";
+            break;
+        case EOpBitShiftLeft:
+            out << "bit-wise shift left";
+            break;
+        case EOpBitShiftRight:
+            out << "bit-wise shift right";
+            break;
+        case EOpBitwiseAnd:
+            out << "bit-wise and";
+            break;
+        case EOpBitwiseXor:
+            out << "bit-wise xor";
+            break;
+        case EOpBitwiseOr:
+            out << "bit-wise or";
+            break;
+
+        case EOpEqual:
+            out << "Compare Equal";
+            break;
+        case EOpNotEqual:
+            out << "Compare Not Equal";
+            break;
+        case EOpLessThan:
+            out << "Compare Less Than";
+            break;
+        case EOpGreaterThan:
+            out << "Compare Greater Than";
+            break;
+        case EOpLessThanEqual:
+            out << "Compare Less Than or Equal";
+            break;
+        case EOpGreaterThanEqual:
+            out << "Compare Greater Than or Equal";
+            break;
+
+        case EOpVectorTimesScalar:
+            out << "vector-scale";
+            break;
+        case EOpVectorTimesMatrix:
+            out << "vector-times-matrix";
+            break;
+        case EOpMatrixTimesVector:
+            out << "matrix-times-vector";
+            break;
+        case EOpMatrixTimesScalar:
+            out << "matrix-scale";
+            break;
+        case EOpMatrixTimesMatrix:
+            out << "matrix-multiply";
+            break;
+
+        case EOpLogicalOr:
+            out << "logical-or";
+            break;
+        case EOpLogicalXor:
+            out << "logical-xor";
+            break;
+        case EOpLogicalAnd:
+            out << "logical-and";
+            break;
+        default:
+            out << "<unknown op>";
+    }
+
+    out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    // Special handling for direct indexes. Because constant
+    // unions are not aware they are struct indexes, treat them
+    // here where we have that contextual knowledge.
+    if (node->getOp() == EOpIndexDirectStruct || node->getOp() == EOpIndexDirectInterfaceBlock)
+    {
+        node->getLeft()->traverse(this);
+
+        TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
+        ASSERT(intermConstantUnion);
+
+        OutputTreeText(out, intermConstantUnion, mDepth + 1);
+
+        // The following code finds the field name from the constant union
+        const TConstantUnion *constantUnion   = intermConstantUnion->getUnionArrayPointer();
+        const TStructure *structure           = node->getLeft()->getType().getStruct();
+        const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
+        ASSERT(structure || interfaceBlock);
+
+        const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();
+
+        const TField *field = fields[constantUnion->getIConst()];
+
+        out << constantUnion->getIConst() << " (field '" << field->name() << "')";
+
+        out << "\n";
+
+        return false;
+    }
+
+    return true;
+}
+
+bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+
+    switch (node->getOp())
+    {
+        // Give verbose names for ops that have special syntax and some built-in functions that are
+        // easy to confuse with others, but mostly use GLSL names for functions.
+        case EOpNegative:
+            out << "Negate value";
+            break;
+        case EOpPositive:
+            out << "Positive sign";
+            break;
+        case EOpLogicalNot:
+            out << "negation";
+            break;
+        case EOpBitwiseNot:
+            out << "bit-wise not";
+            break;
+
+        case EOpPostIncrement:
+            out << "Post-Increment";
+            break;
+        case EOpPostDecrement:
+            out << "Post-Decrement";
+            break;
+        case EOpPreIncrement:
+            out << "Pre-Increment";
+            break;
+        case EOpPreDecrement:
+            out << "Pre-Decrement";
+            break;
+
+        case EOpLogicalNotComponentWise:
+            out << "component-wise not";
+            break;
+
+        default:
+            out << GetOperatorString(node->getOp());
+            break;
+    }
+
+    out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+{
+    TInfoSinkBase &out = sink;
+    OutputTreeText(out, node, mDepth);
+    out << "Function Definition:\n";
+    out << "\n";
+    return true;
+}
+
+bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+{
+    TInfoSinkBase &out = sink;
+    OutputTreeText(out, node, mDepth);
+    out << "Invariant Declaration:\n";
+    return true;
+}
+
+bool TOutputTraverser::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+    OutputFunction(out, "Function Prototype", node->getFunctionSymbolInfo());
+    out << " (" << node->getCompleteString() << ")";
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+
+    if (node->getOp() == EOpNull)
+    {
+        out.prefix(SH_ERROR);
+        out << "node is still EOpNull!\n";
+        return true;
+    }
+
+    // Give verbose names for some built-in functions that are easy to confuse with others, but
+    // mostly use GLSL names for functions.
+    switch (node->getOp())
+    {
+        case EOpCallFunctionInAST:
+            OutputFunction(out, "Call an user-defined function", node->getFunctionSymbolInfo());
+            break;
+        case EOpCallInternalRawFunction:
+            OutputFunction(out, "Call an internal function with raw implementation",
+                           node->getFunctionSymbolInfo());
+            break;
+        case EOpCallBuiltInFunction:
+            OutputFunction(out, "Call a built-in function", node->getFunctionSymbolInfo());
+            break;
+
+        case EOpConstruct:
+            // The type of the constructor will be printed below.
+            out << "Construct";
+            break;
+
+        case EOpEqualComponentWise:
+            out << "component-wise equal";
+            break;
+        case EOpNotEqualComponentWise:
+            out << "component-wise not equal";
+            break;
+        case EOpLessThanComponentWise:
+            out << "component-wise less than";
+            break;
+        case EOpGreaterThanComponentWise:
+            out << "component-wise greater than";
+            break;
+        case EOpLessThanEqualComponentWise:
+            out << "component-wise less than or equal";
+            break;
+        case EOpGreaterThanEqualComponentWise:
+            out << "component-wise greater than or equal";
+            break;
+
+        case EOpDot:
+            out << "dot product";
+            break;
+        case EOpCross:
+            out << "cross product";
+            break;
+        case EOpMulMatrixComponentWise:
+            out << "component-wise multiply";
+            break;
+
+        default:
+            out << GetOperatorString(node->getOp());
+            break;
+    }
+
+    out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+    out << "Code block\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+    out << "Declaration\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+
+    out << "Ternary selection";
+    out << " (" << node->getCompleteString() << ")\n";
+
+    ++mDepth;
+
+    OutputTreeText(sink, node, mDepth);
+    out << "Condition\n";
+    node->getCondition()->traverse(this);
+
+    OutputTreeText(sink, node, mDepth);
+    if (node->getTrueExpression())
+    {
+        out << "true case\n";
+        node->getTrueExpression()->traverse(this);
+    }
+    if (node->getFalseExpression())
+    {
+        OutputTreeText(sink, node, mDepth);
+        out << "false case\n";
+        node->getFalseExpression()->traverse(this);
+    }
+
+    --mDepth;
+
+    return false;
+}
+
+bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+
+    out << "If test\n";
+
+    ++mDepth;
+
+    OutputTreeText(sink, node, mDepth);
+    out << "Condition\n";
+    node->getCondition()->traverse(this);
+
+    OutputTreeText(sink, node, mDepth);
+    if (node->getTrueBlock())
+    {
+        out << "true case\n";
+        node->getTrueBlock()->traverse(this);
+    }
+    else
+    {
+        out << "true case is null\n";
+    }
+
+    if (node->getFalseBlock())
+    {
+        OutputTreeText(sink, node, mDepth);
+        out << "false case\n";
+        node->getFalseBlock()->traverse(this);
+    }
+
+    --mDepth;
+
+    return false;
+}
+
+bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+
+    out << "Switch\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+
+    if (node->getCondition() == nullptr)
+    {
+        out << "Default\n";
+    }
+    else
+    {
+        out << "Case\n";
+    }
+
+    return true;
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
+{
+    TInfoSinkBase &out = sink;
+
+    size_t size = node->getType().getObjectSize();
+
+    for (size_t i = 0; i < size; i++)
+    {
+        OutputTreeText(out, node, mDepth);
+        switch (node->getUnionArrayPointer()[i].getType())
+        {
+            case EbtBool:
+                if (node->getUnionArrayPointer()[i].getBConst())
+                    out << "true";
+                else
+                    out << "false";
+
+                out << " ("
+                    << "const bool"
+                    << ")";
+                out << "\n";
+                break;
+            case EbtFloat:
+                out << node->getUnionArrayPointer()[i].getFConst();
+                out << " (const float)\n";
+                break;
+            case EbtInt:
+                out << node->getUnionArrayPointer()[i].getIConst();
+                out << " (const int)\n";
+                break;
+            case EbtUInt:
+                out << node->getUnionArrayPointer()[i].getUConst();
+                out << " (const uint)\n";
+                break;
+            case EbtYuvCscStandardEXT:
+                out << getYuvCscStandardEXTString(
+                    node->getUnionArrayPointer()[i].getYuvCscStandardEXTConst());
+                out << " (const yuvCscStandardEXT)\n";
+                break;
+            default:
+                out.prefix(SH_ERROR);
+                out << "Unknown constant\n";
+                break;
+        }
+    }
+}
+
+bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+
+    out << "Loop with condition ";
+    if (node->getType() == ELoopDoWhile)
+        out << "not ";
+    out << "tested first\n";
+
+    ++mDepth;
+
+    OutputTreeText(sink, node, mDepth);
+    if (node->getCondition())
+    {
+        out << "Loop Condition\n";
+        node->getCondition()->traverse(this);
+    }
+    else
+    {
+        out << "No loop condition\n";
+    }
+
+    OutputTreeText(sink, node, mDepth);
+    if (node->getBody())
+    {
+        out << "Loop Body\n";
+        node->getBody()->traverse(this);
+    }
+    else
+    {
+        out << "No loop body\n";
+    }
+
+    if (node->getExpression())
+    {
+        OutputTreeText(sink, node, mDepth);
+        out << "Loop Terminal Expression\n";
+        node->getExpression()->traverse(this);
+    }
+
+    --mDepth;
+
+    return false;
+}
+
+bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
+{
+    TInfoSinkBase &out = sink;
+
+    OutputTreeText(out, node, mDepth);
+
+    switch (node->getFlowOp())
+    {
+        case EOpKill:
+            out << "Branch: Kill";
+            break;
+        case EOpBreak:
+            out << "Branch: Break";
+            break;
+        case EOpContinue:
+            out << "Branch: Continue";
+            break;
+        case EOpReturn:
+            out << "Branch: Return";
+            break;
+        default:
+            out << "Branch: Unknown Branch";
+            break;
+    }
+
+    if (node->getExpression())
+    {
+        out << " with expression\n";
+        ++mDepth;
+        node->getExpression()->traverse(this);
+        --mDepth;
+    }
+    else
+    {
+        out << "\n";
+    }
+
+    return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node. Its children will still be processed.
+//
+void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink)
+{
+    TOutputTraverser it(infoSink);
+
+    ASSERT(root);
+
+    root->traverse(&it);
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/length_limits.h b/src/third_party/angle/src/compiler/translator/length_limits.h
new file mode 100644
index 0000000..fcda639
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/length_limits.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2011-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.
+//
+
+//
+// length_limits.h
+//
+
+#ifndef COMPILER_TRANSLATOR_LENGTHLIMITS_H_
+#define COMPILER_TRANSLATOR_LENGTHLIMITS_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+// These constants are factored out from the rest of the headers to
+// make it easier to reference them from the compiler sources.
+
+namespace sh
+{
+
+size_t GetGlobalMaxTokenSize(ShShaderSpec spec);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_LENGTHLIMITS_H_
diff --git a/src/third_party/angle/src/compiler/translator/util.cpp b/src/third_party/angle/src/compiler/translator/util.cpp
new file mode 100644
index 0000000..c87b725
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/util.cpp
@@ -0,0 +1,626 @@
+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/util.h"
+
+#include <limits>
+
+#include "common/utilities.h"
+#include "compiler/preprocessor/numeric_lex.h"
+#include "compiler/translator/SymbolTable.h"
+
+bool atoi_clamp(const char *str, unsigned int *value)
+{
+    bool success = pp::numeric_lex_int(str, value);
+    if (!success)
+        *value = std::numeric_limits<unsigned int>::max();
+    return success;
+}
+
+namespace sh
+{
+
+float NumericLexFloat32OutOfRangeToInfinity(const std::string &str)
+{
+    // Parses a decimal string using scientific notation into a floating point number.
+    // Out-of-range values are converted to infinity. Values that are too small to be
+    // represented are converted to zero.
+
+    // The mantissa in decimal scientific notation. The magnitude of the mantissa integer does not
+    // matter.
+    unsigned int decimalMantissa = 0;
+    size_t i                     = 0;
+    bool decimalPointSeen        = false;
+    bool nonZeroSeenInMantissa   = false;
+
+    // The exponent offset reflects the position of the decimal point.
+    int exponentOffset = -1;
+    while (i < str.length())
+    {
+        const char c = str[i];
+        if (c == 'e' || c == 'E')
+        {
+            break;
+        }
+        if (c == '.')
+        {
+            decimalPointSeen = true;
+            ++i;
+            continue;
+        }
+
+        unsigned int digit = static_cast<unsigned int>(c - '0');
+        ASSERT(digit < 10u);
+        if (digit != 0u)
+        {
+            nonZeroSeenInMantissa = true;
+        }
+        if (nonZeroSeenInMantissa)
+        {
+            // Add bits to the mantissa until space runs out in 32-bit int. This should be
+            // enough precision to make the resulting binary mantissa accurate to 1 ULP.
+            if (decimalMantissa <= (std::numeric_limits<unsigned int>::max() - 9u) / 10u)
+            {
+                decimalMantissa = decimalMantissa * 10u + digit;
+            }
+            if (!decimalPointSeen)
+            {
+                ++exponentOffset;
+            }
+        }
+        else if (decimalPointSeen)
+        {
+            --exponentOffset;
+        }
+        ++i;
+    }
+    if (decimalMantissa == 0)
+    {
+        return 0.0f;
+    }
+    int exponent = 0;
+    if (i < str.length())
+    {
+        ASSERT(str[i] == 'e' || str[i] == 'E');
+        ++i;
+        bool exponentOutOfRange = false;
+        bool negativeExponent   = false;
+        if (str[i] == '-')
+        {
+            negativeExponent = true;
+            ++i;
+        }
+        else if (str[i] == '+')
+        {
+            ++i;
+        }
+        while (i < str.length())
+        {
+            const char c       = str[i];
+            unsigned int digit = static_cast<unsigned int>(c - '0');
+            ASSERT(digit < 10u);
+            if (exponent <= (std::numeric_limits<int>::max() - 9) / 10)
+            {
+                exponent = exponent * 10 + digit;
+            }
+            else
+            {
+                exponentOutOfRange = true;
+            }
+            ++i;
+        }
+        if (negativeExponent)
+        {
+            exponent = -exponent;
+        }
+        if (exponentOutOfRange)
+        {
+            if (negativeExponent)
+            {
+                return 0.0f;
+            }
+            else
+            {
+                return std::numeric_limits<float>::infinity();
+            }
+        }
+    }
+    // Do the calculation in 64-bit to avoid overflow.
+    long long exponentLong =
+        static_cast<long long>(exponent) + static_cast<long long>(exponentOffset);
+    if (exponentLong > std::numeric_limits<float>::max_exponent10)
+    {
+        return std::numeric_limits<float>::infinity();
+    }
+    else if (exponentLong < std::numeric_limits<float>::min_exponent10)
+    {
+        return 0.0f;
+    }
+    // The exponent is in range, so we need to actually evaluate the float.
+    exponent     = static_cast<int>(exponentLong);
+    double value = decimalMantissa;
+
+    // Calculate the exponent offset to normalize the mantissa.
+    int normalizationExponentOffset = 0;
+    while (decimalMantissa >= 10u)
+    {
+        --normalizationExponentOffset;
+        decimalMantissa /= 10u;
+    }
+    // Apply the exponent.
+    value *= std::pow(10.0, static_cast<double>(exponent + normalizationExponentOffset));
+    if (value > static_cast<double>(std::numeric_limits<float>::max()))
+    {
+        return std::numeric_limits<float>::infinity();
+    }
+    if (value < static_cast<double>(std::numeric_limits<float>::min()))
+    {
+        return 0.0f;
+    }
+    return static_cast<float>(value);
+}
+
+bool strtof_clamp(const std::string &str, float *value)
+{
+    // Try the standard float parsing path first.
+    bool success = pp::numeric_lex_float(str, value);
+
+    // If the standard path doesn't succeed, take the path that can handle the following corner
+    // cases:
+    //   1. The decimal mantissa is very small but the exponent is very large, putting the resulting
+    //   number inside the float range.
+    //   2. The decimal mantissa is very large but the exponent is very small, putting the resulting
+    //   number inside the float range.
+    //   3. The value is out-of-range and should be evaluated as infinity.
+    //   4. The value is too small and should be evaluated as zero.
+    // See ESSL 3.00.6 section 4.1.4 for the relevant specification.
+    if (!success)
+        *value = NumericLexFloat32OutOfRangeToInfinity(str);
+    return !gl::isInf(*value);
+}
+
+GLenum GLVariableType(const TType &type)
+{
+    if (type.getBasicType() == EbtFloat)
+    {
+        if (type.isScalar())
+        {
+            return GL_FLOAT;
+        }
+        else if (type.isVector())
+        {
+            switch (type.getNominalSize())
+            {
+                case 2:
+                    return GL_FLOAT_VEC2;
+                case 3:
+                    return GL_FLOAT_VEC3;
+                case 4:
+                    return GL_FLOAT_VEC4;
+                default:
+                    UNREACHABLE();
+            }
+        }
+        else if (type.isMatrix())
+        {
+            switch (type.getCols())
+            {
+                case 2:
+                    switch (type.getRows())
+                    {
+                        case 2:
+                            return GL_FLOAT_MAT2;
+                        case 3:
+                            return GL_FLOAT_MAT2x3;
+                        case 4:
+                            return GL_FLOAT_MAT2x4;
+                        default:
+                            UNREACHABLE();
+                    }
+
+                case 3:
+                    switch (type.getRows())
+                    {
+                        case 2:
+                            return GL_FLOAT_MAT3x2;
+                        case 3:
+                            return GL_FLOAT_MAT3;
+                        case 4:
+                            return GL_FLOAT_MAT3x4;
+                        default:
+                            UNREACHABLE();
+                    }
+
+                case 4:
+                    switch (type.getRows())
+                    {
+                        case 2:
+                            return GL_FLOAT_MAT4x2;
+                        case 3:
+                            return GL_FLOAT_MAT4x3;
+                        case 4:
+                            return GL_FLOAT_MAT4;
+                        default:
+                            UNREACHABLE();
+                    }
+
+                default:
+                    UNREACHABLE();
+            }
+        }
+        else
+            UNREACHABLE();
+    }
+    else if (type.getBasicType() == EbtInt)
+    {
+        if (type.isScalar())
+        {
+            return GL_INT;
+        }
+        else if (type.isVector())
+        {
+            switch (type.getNominalSize())
+            {
+                case 2:
+                    return GL_INT_VEC2;
+                case 3:
+                    return GL_INT_VEC3;
+                case 4:
+                    return GL_INT_VEC4;
+                default:
+                    UNREACHABLE();
+            }
+        }
+        else
+            UNREACHABLE();
+    }
+    else if (type.getBasicType() == EbtUInt)
+    {
+        if (type.isScalar())
+        {
+            return GL_UNSIGNED_INT;
+        }
+        else if (type.isVector())
+        {
+            switch (type.getNominalSize())
+            {
+                case 2:
+                    return GL_UNSIGNED_INT_VEC2;
+                case 3:
+                    return GL_UNSIGNED_INT_VEC3;
+                case 4:
+                    return GL_UNSIGNED_INT_VEC4;
+                default:
+                    UNREACHABLE();
+            }
+        }
+        else
+            UNREACHABLE();
+    }
+    else if (type.getBasicType() == EbtBool)
+    {
+        if (type.isScalar())
+        {
+            return GL_BOOL;
+        }
+        else if (type.isVector())
+        {
+            switch (type.getNominalSize())
+            {
+                case 2:
+                    return GL_BOOL_VEC2;
+                case 3:
+                    return GL_BOOL_VEC3;
+                case 4:
+                    return GL_BOOL_VEC4;
+                default:
+                    UNREACHABLE();
+            }
+        }
+        else
+            UNREACHABLE();
+    }
+
+    switch (type.getBasicType())
+    {
+        case EbtSampler2D:
+            return GL_SAMPLER_2D;
+        case EbtSampler3D:
+            return GL_SAMPLER_3D;
+        case EbtSamplerCube:
+            return GL_SAMPLER_CUBE;
+        case EbtSamplerExternalOES:
+            return GL_SAMPLER_EXTERNAL_OES;
+        case EbtSamplerExternal2DY2YEXT:
+            return GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
+        case EbtSampler2DRect:
+            return GL_SAMPLER_2D_RECT_ARB;
+        case EbtSampler2DArray:
+            return GL_SAMPLER_2D_ARRAY;
+        case EbtSampler2DMS:
+            return GL_SAMPLER_2D_MULTISAMPLE;
+        case EbtISampler2D:
+            return GL_INT_SAMPLER_2D;
+        case EbtISampler3D:
+            return GL_INT_SAMPLER_3D;
+        case EbtISamplerCube:
+            return GL_INT_SAMPLER_CUBE;
+        case EbtISampler2DArray:
+            return GL_INT_SAMPLER_2D_ARRAY;
+        case EbtISampler2DMS:
+            return GL_INT_SAMPLER_2D_MULTISAMPLE;
+        case EbtUSampler2D:
+            return GL_UNSIGNED_INT_SAMPLER_2D;
+        case EbtUSampler3D:
+            return GL_UNSIGNED_INT_SAMPLER_3D;
+        case EbtUSamplerCube:
+            return GL_UNSIGNED_INT_SAMPLER_CUBE;
+        case EbtUSampler2DArray:
+            return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
+        case EbtUSampler2DMS:
+            return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE;
+        case EbtSampler2DShadow:
+            return GL_SAMPLER_2D_SHADOW;
+        case EbtSamplerCubeShadow:
+            return GL_SAMPLER_CUBE_SHADOW;
+        case EbtSampler2DArrayShadow:
+            return GL_SAMPLER_2D_ARRAY_SHADOW;
+        case EbtImage2D:
+            return GL_IMAGE_2D;
+        case EbtIImage2D:
+            return GL_INT_IMAGE_2D;
+        case EbtUImage2D:
+            return GL_UNSIGNED_INT_IMAGE_2D;
+        case EbtImage2DArray:
+            return GL_IMAGE_2D_ARRAY;
+        case EbtIImage2DArray:
+            return GL_INT_IMAGE_2D_ARRAY;
+        case EbtUImage2DArray:
+            return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
+        case EbtImage3D:
+            return GL_IMAGE_3D;
+        case EbtIImage3D:
+            return GL_INT_IMAGE_3D;
+        case EbtUImage3D:
+            return GL_UNSIGNED_INT_IMAGE_3D;
+        case EbtImageCube:
+            return GL_IMAGE_CUBE;
+        case EbtIImageCube:
+            return GL_INT_IMAGE_CUBE;
+        case EbtUImageCube:
+            return GL_UNSIGNED_INT_IMAGE_CUBE;
+        default:
+            UNREACHABLE();
+    }
+
+    return GL_NONE;
+}
+
+GLenum GLVariablePrecision(const TType &type)
+{
+    if (type.getBasicType() == EbtFloat)
+    {
+        switch (type.getPrecision())
+        {
+            case EbpHigh:
+                return GL_HIGH_FLOAT;
+            case EbpMedium:
+                return GL_MEDIUM_FLOAT;
+            case EbpLow:
+                return GL_LOW_FLOAT;
+            case EbpUndefined:
+            // Should be defined as the default precision by the parser
+            default:
+                UNREACHABLE();
+        }
+    }
+    else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt)
+    {
+        switch (type.getPrecision())
+        {
+            case EbpHigh:
+                return GL_HIGH_INT;
+            case EbpMedium:
+                return GL_MEDIUM_INT;
+            case EbpLow:
+                return GL_LOW_INT;
+            case EbpUndefined:
+            // Should be defined as the default precision by the parser
+            default:
+                UNREACHABLE();
+        }
+    }
+
+    // Other types (boolean, sampler) don't have a precision
+    return GL_NONE;
+}
+
+TString ArrayString(const TType &type)
+{
+    if (!type.isArray())
+    {
+        return "";
+    }
+
+    return "[" + str(type.getArraySize()) + "]";
+}
+
+bool IsVaryingOut(TQualifier qualifier)
+{
+    switch (qualifier)
+    {
+        case EvqVaryingOut:
+        case EvqSmoothOut:
+        case EvqFlatOut:
+        case EvqCentroidOut:
+        case EvqVertexOut:
+            return true;
+
+        default:
+            break;
+    }
+
+    return false;
+}
+
+bool IsVaryingIn(TQualifier qualifier)
+{
+    switch (qualifier)
+    {
+        case EvqVaryingIn:
+        case EvqSmoothIn:
+        case EvqFlatIn:
+        case EvqCentroidIn:
+        case EvqFragmentIn:
+            return true;
+
+        default:
+            break;
+    }
+
+    return false;
+}
+
+bool IsVarying(TQualifier qualifier)
+{
+    return IsVaryingIn(qualifier) || IsVaryingOut(qualifier);
+}
+
+InterpolationType GetInterpolationType(TQualifier qualifier)
+{
+    switch (qualifier)
+    {
+        case EvqFlatIn:
+        case EvqFlatOut:
+            return INTERPOLATION_FLAT;
+
+        case EvqSmoothIn:
+        case EvqSmoothOut:
+        case EvqVertexOut:
+        case EvqFragmentIn:
+        case EvqVaryingIn:
+        case EvqVaryingOut:
+            return INTERPOLATION_SMOOTH;
+
+        case EvqCentroidIn:
+        case EvqCentroidOut:
+            return INTERPOLATION_CENTROID;
+
+        default:
+            UNREACHABLE();
+            return INTERPOLATION_SMOOTH;
+    }
+}
+
+TType GetShaderVariableBasicType(const sh::ShaderVariable &var)
+{
+    switch (var.type)
+    {
+        case GL_BOOL:
+            return TType(EbtBool);
+        case GL_BOOL_VEC2:
+            return TType(EbtBool, 2);
+        case GL_BOOL_VEC3:
+            return TType(EbtBool, 3);
+        case GL_BOOL_VEC4:
+            return TType(EbtBool, 4);
+        case GL_FLOAT:
+            return TType(EbtFloat);
+        case GL_FLOAT_VEC2:
+            return TType(EbtFloat, 2);
+        case GL_FLOAT_VEC3:
+            return TType(EbtFloat, 3);
+        case GL_FLOAT_VEC4:
+            return TType(EbtFloat, 4);
+        case GL_FLOAT_MAT2:
+            return TType(EbtFloat, 2, 2);
+        case GL_FLOAT_MAT3:
+            return TType(EbtFloat, 3, 3);
+        case GL_FLOAT_MAT4:
+            return TType(EbtFloat, 4, 4);
+        case GL_FLOAT_MAT2x3:
+            return TType(EbtFloat, 2, 3);
+        case GL_FLOAT_MAT2x4:
+            return TType(EbtFloat, 2, 4);
+        case GL_FLOAT_MAT3x2:
+            return TType(EbtFloat, 3, 2);
+        case GL_FLOAT_MAT3x4:
+            return TType(EbtFloat, 3, 4);
+        case GL_FLOAT_MAT4x2:
+            return TType(EbtFloat, 4, 2);
+        case GL_FLOAT_MAT4x3:
+            return TType(EbtFloat, 4, 3);
+        case GL_INT:
+            return TType(EbtInt);
+        case GL_INT_VEC2:
+            return TType(EbtInt, 2);
+        case GL_INT_VEC3:
+            return TType(EbtInt, 3);
+        case GL_INT_VEC4:
+            return TType(EbtInt, 4);
+        case GL_UNSIGNED_INT:
+            return TType(EbtUInt);
+        case GL_UNSIGNED_INT_VEC2:
+            return TType(EbtUInt, 2);
+        case GL_UNSIGNED_INT_VEC3:
+            return TType(EbtUInt, 3);
+        case GL_UNSIGNED_INT_VEC4:
+            return TType(EbtUInt, 4);
+        default:
+            UNREACHABLE();
+            return TType();
+    }
+}
+
+// GLSL ES 1.0.17 4.6.1 The Invariant Qualifier
+bool CanBeInvariantESSL1(TQualifier qualifier)
+{
+    return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) ||
+           IsBuiltinOutputVariable(qualifier) ||
+           (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing);
+}
+
+// GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier
+// GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier
+bool CanBeInvariantESSL3OrGreater(TQualifier qualifier)
+{
+    return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut ||
+           IsBuiltinOutputVariable(qualifier);
+}
+
+bool IsBuiltinOutputVariable(TQualifier qualifier)
+{
+    switch (qualifier)
+    {
+        case EvqPosition:
+        case EvqPointSize:
+        case EvqFragDepth:
+        case EvqFragDepthEXT:
+        case EvqFragColor:
+        case EvqSecondaryFragColorEXT:
+        case EvqFragData:
+        case EvqSecondaryFragDataEXT:
+            return true;
+        default:
+            break;
+    }
+    return false;
+}
+
+bool IsBuiltinFragmentInputVariable(TQualifier qualifier)
+{
+    switch (qualifier)
+    {
+        case EvqFragCoord:
+        case EvqPointCoord:
+        case EvqFrontFacing:
+            return true;
+        default:
+            break;
+    }
+    return false;
+}
+}  // namespace sh
diff --git a/src/third_party/angle/src/compiler/translator/util.h b/src/third_party/angle/src/compiler/translator/util.h
new file mode 100644
index 0000000..f27933c
--- /dev/null
+++ b/src/third_party/angle/src/compiler/translator/util.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_UTIL_H_
+#define COMPILER_TRANSLATOR_UTIL_H_
+
+#include <stack>
+
+#include "angle_gl.h"
+#include <GLSLANG/ShaderLang.h>
+
+#include "compiler/translator/Operator.h"
+#include "compiler/translator/Types.h"
+
+// If overflow happens, clamp the value to UINT_MIN or UINT_MAX.
+// Return false if overflow happens.
+bool atoi_clamp(const char *str, unsigned int *value);
+
+namespace sh
+{
+class TSymbolTable;
+
+float NumericLexFloat32OutOfRangeToInfinity(const std::string &str);
+
+// strtof_clamp is like strtof but
+//   1. it forces C locale, i.e. forcing '.' as decimal point.
+//   2. it sets the value to infinity if overflow happens.
+//   3. str should be guaranteed to be in the valid format for a floating point number as defined
+//      by the grammar in the ESSL 3.00.6 spec section 4.1.4.
+// Return false if overflow happens.
+bool strtof_clamp(const std::string &str, float *value);
+
+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);
+TString ArrayString(const TType &type);
+
+TType GetShaderVariableBasicType(const sh::ShaderVariable &var);
+
+bool IsBuiltinOutputVariable(TQualifier qualifier);
+bool IsBuiltinFragmentInputVariable(TQualifier qualifier);
+bool CanBeInvariantESSL1(TQualifier qualifier);
+bool CanBeInvariantESSL3OrGreater(TQualifier qualifier);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_UTIL_H_
diff --git a/src/third_party/angle/src/compiler/translator_common.vcxproj b/src/third_party/angle/src/compiler/translator_common.vcxproj
deleted file mode 100644
index 3800094..0000000
--- a/src/third_party/angle/src/compiler/translator_common.vcxproj
+++ /dev/null
@@ -1,273 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Debug|x64">

-      <Configuration>Debug</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|x64">

-      <Configuration>Release</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}</ProjectGuid>

-    <RootNamespace>compiler</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>NotSet</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\common\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\common\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4267;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4267;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="BuiltInFunctionEmulator.cpp" />

-    <ClCompile Include="Compiler.cpp" />

-    <ClCompile Include="debug.cpp" />

-    <ClCompile Include="DetectCallDepth.cpp" />

-    <ClCompile Include="Diagnostics.cpp" />

-    <ClCompile Include="DirectiveHandler.cpp" />

-    <ClCompile Include="ForLoopUnroll.cpp" />

-    <ClCompile Include="InfoSink.cpp" />

-    <ClCompile Include="Initialize.cpp" />

-    <ClCompile Include="InitializeDll.cpp" />

-    <ClCompile Include="InitializeParseContext.cpp" />

-    <ClCompile Include="Intermediate.cpp" />

-    <ClCompile Include="intermOut.cpp" />

-    <ClCompile Include="IntermTraverse.cpp" />

-    <ClCompile Include="MapLongVariableNames.cpp" />

-    <ClCompile Include="ossource_win.cpp" />

-    <ClCompile Include="parseConst.cpp" />

-    <ClCompile Include="ParseHelper.cpp" />

-    <ClCompile Include="PoolAlloc.cpp" />

-    <ClCompile Include="QualifierAlive.cpp" />

-    <ClCompile Include="RemoveTree.cpp" />

-    <ClCompile Include="ShaderLang.cpp" />

-    <ClCompile Include="SymbolTable.cpp" />

-    <ClCompile Include="util.cpp" />

-    <ClCompile Include="ValidateLimitations.cpp" />

-    <ClCompile Include="VariableInfo.cpp" />

-    <ClCompile Include="VariablePacker.cpp" />

-    <ClCompile Include="glslang_lex.cpp" />

-    <ClCompile Include="glslang_tab.cpp" />

-    <ClCompile Include="depgraph\DependencyGraph.cpp" />

-    <ClCompile Include="depgraph\DependencyGraphBuilder.cpp" />

-    <ClCompile Include="depgraph\DependencyGraphOutput.cpp" />

-    <ClCompile Include="depgraph\DependencyGraphTraverse.cpp" />

-    <ClCompile Include="timing\RestrictFragmentShaderTiming.cpp" />

-    <ClCompile Include="timing\RestrictVertexShaderTiming.cpp" />

-    <ClCompile Include="..\third_party\compiler\ArrayBoundsClamper.cpp" />

-  </ItemGroup>

-  <ItemGroup>

-    <CustomBuild Include="glslang.l">

-      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-      </Message>

-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-      </Command>

-      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>

-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Outputs)</Outputs>

-      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-      </Message>

-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-      </Command>

-      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalInputs)</AdditionalInputs>

-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Outputs)</Outputs>

-      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-      </Message>

-      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-      </Command>

-      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>

-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Outputs)</Outputs>

-      <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-      </Message>

-      <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-      </Command>

-      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalInputs)</AdditionalInputs>

-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Outputs)</Outputs>

-    </CustomBuild>

-    <CustomBuild Include="glslang.y">

-      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-      </Message>

-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-      </Command>

-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Outputs)</Outputs>

-      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-      </Message>

-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-      </Command>

-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Outputs)</Outputs>

-      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-      </Message>

-      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-      </Command>

-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Outputs)</Outputs>

-      <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-      </Message>

-      <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-      </Command>

-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Outputs)</Outputs>

-    </CustomBuild>

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="BaseTypes.h" />

-    <ClInclude Include="BuiltInFunctionEmulator.h" />

-    <ClInclude Include="Common.h" />

-    <ClInclude Include="ConstantUnion.h" />

-    <ClInclude Include="debug.h" />

-    <ClInclude Include="DetectCallDepth.h" />

-    <ClInclude Include="Diagnostics.h" />

-    <ClInclude Include="DirectiveHandler.h" />

-    <ClInclude Include="ForLoopUnroll.h" />

-    <ClInclude Include="HashNames.h" />

-    <ClInclude Include="InfoSink.h" />

-    <ClInclude Include="Initialize.h" />

-    <ClInclude Include="InitializeDll.h" />

-    <ClInclude Include="InitializeGlobals.h" />

-    <ClInclude Include="InitializeParseContext.h" />

-    <ClInclude Include="intermediate.h" />

-    <ClInclude Include="localintermediate.h" />

-    <ClInclude Include="MapLongVariableNames.h" />

-    <ClInclude Include="MMap.h" />

-    <ClInclude Include="osinclude.h" />

-    <ClInclude Include="ParseHelper.h" />

-    <ClInclude Include="PoolAlloc.h" />

-    <ClInclude Include="QualifierAlive.h" />

-    <ClInclude Include="RemoveTree.h" />

-    <ClInclude Include="RenameFunction.h" />

-    <ClInclude Include="..\..\include\GLSLANG\ShaderLang.h" />

-    <ClInclude Include="ShHandle.h" />

-    <ClInclude Include="SymbolTable.h" />

-    <ClInclude Include="Types.h" />

-    <ClInclude Include="util.h" />

-    <ClInclude Include="ValidateLimitations.h" />

-    <ClInclude Include="VariableInfo.h" />

-    <ClInclude Include="VariablePacker.h" />

-    <ClInclude Include="glslang_tab.h" />

-    <ClInclude Include="timing\RestrictFragmentShaderTiming.h" />

-    <ClInclude Include="timing\RestrictVertexShaderTiming.h" />

-    <ClInclude Include="depgraph\DependencyGraph.h" />

-    <ClInclude Include="depgraph\DependencyGraphBuilder.h" />

-    <ClInclude Include="depgraph\DependencyGraphOutput.h" />

-    <ClInclude Include="..\third_party\compiler\ArrayBoundsClamper.h" />

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
diff --git a/src/third_party/angle/src/compiler/translator_common.vcxproj.filters b/src/third_party/angle/src/compiler/translator_common.vcxproj.filters
deleted file mode 100644
index e5692b4..0000000
--- a/src/third_party/angle/src/compiler/translator_common.vcxproj.filters
+++ /dev/null
@@ -1,271 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup>

-    <Filter Include="Source Files">

-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

-    </Filter>

-    <Filter Include="Source Files\generated">

-      <UniqueIdentifier>{eb8da157-b29c-43c3-880d-54679e176dc5}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Source Files\depgraph">

-      <UniqueIdentifier>{b5410d3a-c3c8-4ae6-843a-b000d652632e}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Source Files\timing">

-      <UniqueIdentifier>{a9847611-dcd5-4c89-8262-a22b96c7c98d}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Header Files">

-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

-    </Filter>

-    <Filter Include="Header Files\generated">

-      <UniqueIdentifier>{094f7115-35d3-4c63-870c-ab5f393dc2c2}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Header Files\timing">

-      <UniqueIdentifier>{5f5742e9-15e1-43b4-b1e7-0c118be14e04}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Header Files\depgraph">

-      <UniqueIdentifier>{c4007e35-3c11-44d6-95f7-bb81db528068}</UniqueIdentifier>

-    </Filter>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="BuiltInFunctionEmulator.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Compiler.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="debug.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="DetectCallDepth.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Diagnostics.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="DirectiveHandler.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="ForLoopUnroll.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="InfoSink.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Initialize.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="InitializeDll.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="InitializeParseContext.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Intermediate.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="intermOut.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="IntermTraverse.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="MapLongVariableNames.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="ossource_win.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="parseConst.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="ParseHelper.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="PoolAlloc.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="QualifierAlive.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="RemoveTree.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="ShaderLang.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="SymbolTable.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="util.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="ValidateLimitations.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="VariableInfo.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="VariablePacker.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="glslang_lex.cpp">

-      <Filter>Source Files\generated</Filter>

-    </ClCompile>

-    <ClCompile Include="glslang_tab.cpp">

-      <Filter>Source Files\generated</Filter>

-    </ClCompile>

-    <ClCompile Include="depgraph\DependencyGraph.cpp">

-      <Filter>Source Files\depgraph</Filter>

-    </ClCompile>

-    <ClCompile Include="depgraph\DependencyGraphBuilder.cpp">

-      <Filter>Source Files\depgraph</Filter>

-    </ClCompile>

-    <ClCompile Include="depgraph\DependencyGraphOutput.cpp">

-      <Filter>Source Files\depgraph</Filter>

-    </ClCompile>

-    <ClCompile Include="depgraph\DependencyGraphTraverse.cpp">

-      <Filter>Source Files\depgraph</Filter>

-    </ClCompile>

-    <ClCompile Include="timing\RestrictFragmentShaderTiming.cpp">

-      <Filter>Source Files\timing</Filter>

-    </ClCompile>

-    <ClCompile Include="timing\RestrictVertexShaderTiming.cpp">

-      <Filter>Source Files\timing</Filter>

-    </ClCompile>

-    <ClCompile Include="ArrayBoundsClamper.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="BaseTypes.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="BuiltInFunctionEmulator.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Common.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="ConstantUnion.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="debug.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="DetectCallDepth.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Diagnostics.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="DirectiveHandler.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="ForLoopUnroll.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="InfoSink.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Initialize.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="InitializeDll.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="InitializeGlobals.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="InitializeParseContext.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="intermediate.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="localintermediate.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="MapLongVariableNames.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="MMap.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="osinclude.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="ParseHelper.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="PoolAlloc.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="QualifierAlive.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="RemoveTree.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="RenameFunction.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\..\include\GLSLANG\ShaderLang.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="ShHandle.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="SymbolTable.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Types.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="util.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="ValidateLimitations.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="VariableInfo.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="VariablePacker.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="glslang_tab.h">

-      <Filter>Header Files\generated</Filter>

-    </ClInclude>

-    <ClInclude Include="timing\RestrictFragmentShaderTiming.h">

-      <Filter>Header Files\timing</Filter>

-    </ClInclude>

-    <ClInclude Include="timing\RestrictVertexShaderTiming.h">

-      <Filter>Header Files\timing</Filter>

-    </ClInclude>

-    <ClInclude Include="depgraph\DependencyGraph.h">

-      <Filter>Header Files\depgraph</Filter>

-    </ClInclude>

-    <ClInclude Include="depgraph\DependencyGraphBuilder.h">

-      <Filter>Header Files\depgraph</Filter>

-    </ClInclude>

-    <ClInclude Include="depgraph\DependencyGraphOutput.h">

-      <Filter>Header Files\depgraph</Filter>

-    </ClInclude>

-    <ClInclude Include="HashNames.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="ArrayBoundsClamper.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-  </ItemGroup>

-  <ItemGroup>

-    <CustomBuild Include="glslang.l">

-      <Filter>Source Files</Filter>

-    </CustomBuild>

-    <CustomBuild Include="glslang.y">

-      <Filter>Source Files</Filter>

-    </CustomBuild>

-  </ItemGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/translator_hlsl.vcxproj b/src/third_party/angle/src/compiler/translator_hlsl.vcxproj
deleted file mode 100644
index 0aade59..0000000
--- a/src/third_party/angle/src/compiler/translator_hlsl.vcxproj
+++ /dev/null
@@ -1,164 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Debug|x64">

-      <Configuration>Debug</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|x64">

-      <Configuration>Release</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}</ProjectGuid>

-    <RootNamespace>CrossCompilerHLSL</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\hlsl\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\hlsl\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-      <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <TreatWarningAsError>true</TreatWarningAsError>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-      <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <TreatWarningAsError>true</TreatWarningAsError>

-    </ClCompile>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="CodeGenHLSL.cpp" />

-    <ClCompile Include="DetectDiscontinuity.cpp" />

-    <ClCompile Include="OutputHLSL.cpp" />

-    <ClCompile Include="SearchSymbol.cpp" />

-    <ClCompile Include="TranslatorHLSL.cpp" />

-    <ClCompile Include="UnfoldShortCircuit.cpp" />

-    <ClCompile Include="Uniform.cpp" />

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="DetectDiscontinuity.h" />

-    <ClInclude Include="OutputHLSL.h" />

-    <ClInclude Include="SearchSymbol.h" />

-    <ClInclude Include="TranslatorHLSL.h" />

-    <ClInclude Include="UnfoldShortCircuit.h" />

-    <ClInclude Include="Uniform.h" />

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/translator_hlsl.vcxproj.filters b/src/third_party/angle/src/compiler/translator_hlsl.vcxproj.filters
deleted file mode 100644
index f4824dc..0000000
--- a/src/third_party/angle/src/compiler/translator_hlsl.vcxproj.filters
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup>

-    <Filter Include="Source Files">

-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

-    </Filter>

-    <Filter Include="Header Files">

-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

-    </Filter>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="CodeGenHLSL.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="DetectDiscontinuity.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="OutputHLSL.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="SearchSymbol.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="TranslatorHLSL.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="UnfoldShortCircuit.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Uniform.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="DetectDiscontinuity.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="OutputHLSL.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="SearchSymbol.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="TranslatorHLSL.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="UnfoldShortCircuit.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Uniform.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-  </ItemGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/src/compiler/util.cpp b/src/third_party/angle/src/compiler/util.cpp
deleted file mode 100644
index 74cec0f..0000000
--- a/src/third_party/angle/src/compiler/util.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include <math.h>
-#include <stdlib.h>
-
-#include "util.h"
-
-#if defined(_MSC_VER) && !defined(__LB_XB360__)
-    #include <locale.h>
-#else
-    #include <sstream>
-#endif
-
-double atof_dot(const char *str)
-{
-#if defined(_MSC_VER) && !defined(__LB_XB360__)
-    _locale_t l = _create_locale(LC_NUMERIC, "C");
-    double result = _atof_l(str, l);
-    _free_locale(l);
-    return result;
-#else
-    double result;
-    std::istringstream s(str);
-    std::locale l("C");
-    s.imbue(l);
-    s >> result;
-    return result;
-#endif
-}
diff --git a/src/third_party/angle/src/compiler/util.h b/src/third_party/angle/src/compiler/util.h
deleted file mode 100644
index 35288b7..0000000
--- a/src/third_party/angle/src/compiler/util.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_UTIL_H
-#define COMPILER_UTIL_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point.
-double atof_dot(const char *str);
-
-#ifdef __cplusplus
-} // end extern "C"
-#endif
-
-#endif // COMPILER_UTIL_H
diff --git a/src/third_party/angle/src/copy_compiler_dll.bat b/src/third_party/angle/src/copy_compiler_dll.bat
index 7ab253e..1aac1ab 100644
--- a/src/third_party/angle/src/copy_compiler_dll.bat
+++ b/src/third_party/angle/src/copy_compiler_dll.bat
@@ -1,9 +1,9 @@
-@echo off
-set _arch=%1
-set _arch=%_arch:Win32=x86%
-copy %2"\Redist\D3D\"%_arch%"\d3dcompiler_46.dll" %3 > NUL
-:: This is equivalent to `touch', see:
-:: https://technet.microsoft.com/en-us/library/bb490886.aspx
-:: This avoids rerunning because this batch file is also copied to the gen dir,
-:: so it's timestamp would otherwise be newer than the dll.
-copy /b %3\d3dcompiler_46.dll+,, %3\d3dcompiler_46.dll > NUL
+@echo off

+set _arch=%1

+set _arch=%_arch:Win32=x86%

+copy %2"\Redist\D3D\"%_arch%"\d3dcompiler_47.dll" %3 > NUL

+:: This is equivalent to `touch', see:

+:: https://technet.microsoft.com/en-us/library/bb490886.aspx

+:: This avoids rerunning because this batch file is also copied to the gen dir,

+:: so it's timestamp would otherwise be newer than the dll.

+copy /b %3\d3dcompiler_47.dll+,, %3\d3dcompiler_47.dll > NUL

diff --git a/src/third_party/angle/src/gpu_info_util/SystemInfo.cpp b/src/third_party/angle/src/gpu_info_util/SystemInfo.cpp
new file mode 100644
index 0000000..dd384c6
--- /dev/null
+++ b/src/third_party/angle/src/gpu_info_util/SystemInfo.cpp
@@ -0,0 +1,159 @@
+//
+// Copyright (c) 2013-2017 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.
+//
+
+// SystemInfo.cpp: implementation of the system-agnostic parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo.h"
+
+#include <cstring>
+#include <sstream>
+
+#include "common/debug.h"
+#include "common/string_utils.h"
+
+namespace angle
+{
+
+bool IsAMD(VendorID vendorId)
+{
+    return vendorId == kVendorID_AMD;
+}
+
+bool IsIntel(VendorID vendorId)
+{
+    return vendorId == kVendorID_Intel;
+}
+
+bool IsNvidia(VendorID vendorId)
+{
+    return vendorId == kVendorID_Nvidia;
+}
+
+bool IsQualcomm(VendorID vendorId)
+{
+    return vendorId == kVendorID_Qualcomm;
+}
+
+bool ParseAMDBrahmaDriverVersion(const std::string &content, std::string *version)
+{
+    const size_t begin = content.find_first_of("0123456789");
+    if (begin == std::string::npos)
+    {
+        return false;
+    }
+
+    const size_t end = content.find_first_not_of("0123456789.", begin);
+    if (end == std::string::npos)
+    {
+        *version = content.substr(begin);
+    }
+    else
+    {
+        *version = content.substr(begin, end - begin);
+    }
+    return true;
+}
+
+bool ParseAMDCatalystDriverVersion(const std::string &content, std::string *version)
+{
+    std::istringstream stream(content);
+
+    std::string line;
+    while (std::getline(stream, line))
+    {
+        static const char kReleaseVersion[] = "ReleaseVersion=";
+        if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0)
+        {
+            continue;
+        }
+
+        if (ParseAMDBrahmaDriverVersion(line, version))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool ParseMacMachineModel(const std::string &identifier,
+                          std::string *type,
+                          int32_t *major,
+                          int32_t *minor)
+{
+    size_t numberLoc = identifier.find_first_of("0123456789");
+    if (numberLoc == std::string::npos)
+    {
+        return false;
+    }
+
+    size_t commaLoc = identifier.find(',', numberLoc);
+    if (commaLoc == std::string::npos || commaLoc >= identifier.size())
+    {
+        return false;
+    }
+
+    const char *numberPtr = &identifier[numberLoc];
+    const char *commaPtr  = &identifier[commaLoc + 1];
+    char *endPtr          = nullptr;
+
+    int32_t majorTmp = std::strtol(numberPtr, &endPtr, 10);
+    if (endPtr == numberPtr)
+    {
+        return false;
+    }
+
+    int32_t minorTmp = std::strtol(commaPtr, &endPtr, 10);
+    if (endPtr == commaPtr)
+    {
+        return false;
+    }
+
+    *major = majorTmp;
+    *minor = minorTmp;
+    *type  = identifier.substr(0, numberLoc);
+
+    return true;
+}
+
+bool CMDeviceIDToDeviceAndVendorID(const std::string &id, uint32_t *vendorId, uint32_t *deviceId)
+{
+    unsigned int vendor = 0;
+    unsigned int device = 0;
+
+    bool success = id.length() >= 21 && HexStringToUInt(id.substr(8, 4), &vendor) &&
+                   HexStringToUInt(id.substr(17, 4), &device);
+
+    *vendorId = vendor;
+    *deviceId = device;
+    return success;
+}
+
+void FindPrimaryGPU(SystemInfo *info)
+{
+    ASSERT(!info->gpus.empty());
+
+    // On dual-GPU systems we assume the non-Intel GPU is the primary one.
+    int primary   = 0;
+    bool hasIntel = false;
+    for (size_t i = 0; i < info->gpus.size(); ++i)
+    {
+        if (IsIntel(info->gpus[i].vendorId))
+        {
+            hasIntel = true;
+        }
+        if (IsIntel(info->gpus[primary].vendorId))
+        {
+            primary = static_cast<int>(i);
+        }
+    }
+
+    // Assume that a combination of AMD or Nvidia with Intel means Optimus or AMD Switchable
+    info->primaryGPUIndex = primary;
+    info->isOptimus       = hasIntel && IsNvidia(info->gpus[primary].vendorId);
+    info->isAMDSwitchable = hasIntel && IsAMD(info->gpus[primary].vendorId);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/gpu_info_util/SystemInfo.h b/src/third_party/angle/src/gpu_info_util/SystemInfo.h
new file mode 100644
index 0000000..6bda5c9
--- /dev/null
+++ b/src/third_party/angle/src/gpu_info_util/SystemInfo.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2013-2017 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.
+//
+
+// SystemInfo.h: gathers information available without starting a GPU driver.
+
+#ifndef GPU_INFO_UTIL_SYSTEM_INFO_H_
+#define GPU_INFO_UTIL_SYSTEM_INFO_H_
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace angle
+{
+
+using VendorID = uint32_t;
+using DeviceID = uint32_t;
+
+constexpr VendorID kVendorID_AMD      = 0x1002;
+constexpr VendorID kVendorID_Intel    = 0x8086;
+constexpr VendorID kVendorID_Nvidia   = 0x10DE;
+constexpr VendorID kVendorID_Qualcomm = 0x5143;
+
+struct GPUDeviceInfo
+{
+    VendorID vendorId = 0;
+    DeviceID deviceId = 0;
+
+    std::string driverVendor;
+    std::string driverVersion;
+    std::string driverDate;
+};
+
+struct SystemInfo
+{
+    std::vector<GPUDeviceInfo> gpus;
+    int primaryGPUIndex = -1;
+    int activeGPUIndex  = -1;
+
+    bool isOptimus       = false;
+    bool isAMDSwitchable = false;
+
+    std::string machineModelName;
+    std::string machineModelVersion;
+};
+
+bool GetSystemInfo(SystemInfo *info);
+
+bool IsAMD(VendorID vendorId);
+bool IsIntel(VendorID vendorId);
+bool IsNvidia(VendorID vendorId);
+bool IsQualcomm(VendorID vendorId);
+
+}  // namespace angle
+
+#endif  // GPU_INFO_UTIL_SYSTEM_INFO_H_
diff --git a/src/third_party/angle/src/gpu_info_util/SystemInfo_internal.h b/src/third_party/angle/src/gpu_info_util/SystemInfo_internal.h
new file mode 100644
index 0000000..d2f6124
--- /dev/null
+++ b/src/third_party/angle/src/gpu_info_util/SystemInfo_internal.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2013-2017 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.
+//
+
+// SystemInfo_internal.h: Functions used by the SystemInfo_* files and unittests
+
+#ifndef GPU_INFO_UTIL_SYSTEM_INFO_INTERNAL_H_
+#define GPU_INFO_UTIL_SYSTEM_INFO_INTERNAL_H_
+
+#include "gpu_info_util/SystemInfo.h"
+
+namespace angle
+{
+
+// Defined in SystemInfo_libpci when GPU_INFO_USE_LIBPCI is defined.
+bool GetPCIDevicesWithLibPCI(std::vector<GPUDeviceInfo> *devices);
+// Defined in SystemInfo_x11 when GPU_INFO_USE_X11 is defined.
+bool GetNvidiaDriverVersionWithXNVCtrl(std::string *version);
+
+// Target specific helper functions that can be compiled on all targets
+// Live in SystemInfo.cpp
+bool ParseAMDBrahmaDriverVersion(const std::string &content, std::string *version);
+bool ParseAMDCatalystDriverVersion(const std::string &content, std::string *version);
+bool ParseMacMachineModel(const std::string &identifier,
+                          std::string *type,
+                          int32_t *major,
+                          int32_t *minor);
+bool CMDeviceIDToDeviceAndVendorID(const std::string &id, uint32_t *vendorId, uint32_t *deviceId);
+
+// In the case there are multiple GPUs, this finds the primary one and sets Optimus or AMD
+// Switchable
+void FindPrimaryGPU(SystemInfo *info);
+
+}  // namespace angle
+
+#endif  // GPU_INFO_UTIL_SYSTEM_INFO_INTERNAL_H_
diff --git a/src/third_party/angle/src/gpu_info_util/SystemInfo_libpci.cpp b/src/third_party/angle/src/gpu_info_util/SystemInfo_libpci.cpp
new file mode 100644
index 0000000..07c7287
--- /dev/null
+++ b/src/third_party/angle/src/gpu_info_util/SystemInfo_libpci.cpp
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 2013-2017 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.
+//
+
+// SystemInfo_libpci.cpp: implementation of the libPCI-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#include <dlfcn.h>
+#include <pci/pci.h>
+#include <unistd.h>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+#if !defined(GPU_INFO_USE_LIBPCI)
+#error SystemInfo_libpci.cpp compiled without GPU_INFO_USE_LIBPCI
+#endif
+
+namespace angle
+{
+
+namespace
+{
+
+struct LibPCI : private angle::NonCopyable
+{
+    LibPCI()
+    {
+        if (access("/sys/bus/pci/", F_OK) != 0 && access("/sys/bs/pci_express/", F_OK) != 0)
+        {
+            return;
+        }
+
+        mHandle = dlopen("libpci.so.3", RTLD_LAZY);
+
+        if (mHandle == nullptr)
+        {
+            mHandle = dlopen("libpci.so", RTLD_LAZY);
+        }
+
+        if (mHandle == nullptr)
+        {
+            return;
+        }
+
+        mValid =
+            (Alloc = reinterpret_cast<decltype(Alloc)>(dlsym(mHandle, "pci_alloc"))) != nullptr &&
+            (Init = reinterpret_cast<decltype(Init)>(dlsym(mHandle, "pci_init"))) != nullptr &&
+            (Cleanup = reinterpret_cast<decltype(Cleanup)>(dlsym(mHandle, "pci_cleanup"))) !=
+                nullptr &&
+            (ScanBus = reinterpret_cast<decltype(ScanBus)>(dlsym(mHandle, "pci_scan_bus"))) !=
+                nullptr &&
+            (FillInfo = reinterpret_cast<decltype(FillInfo)>(dlsym(mHandle, "pci_fill_info"))) !=
+                nullptr &&
+            (LookupName = reinterpret_cast<decltype(LookupName)>(
+                 dlsym(mHandle, "pci_lookup_name"))) != nullptr;
+    }
+
+    bool IsValid() const { return mValid; }
+
+    ~LibPCI()
+    {
+        if (mHandle != nullptr)
+        {
+            dlclose(mHandle);
+        }
+    }
+
+    decltype(&::pci_alloc) Alloc            = nullptr;
+    decltype(&::pci_init) Init              = nullptr;
+    decltype(&::pci_cleanup) Cleanup        = nullptr;
+    decltype(&::pci_scan_bus) ScanBus       = nullptr;
+    decltype(&::pci_fill_info) FillInfo     = nullptr;
+    decltype(&::pci_lookup_name) LookupName = nullptr;
+
+  private:
+    void *mHandle = nullptr;
+    bool mValid   = false;
+};
+
+}  // anonymous namespace
+
+// Adds an entry per PCI GPU found and fills the device and vendor ID.
+bool GetPCIDevicesWithLibPCI(std::vector<GPUDeviceInfo> *devices)
+{
+    LibPCI pci;
+    if (!pci.IsValid())
+    {
+        return false;
+    }
+
+    pci_access *access = pci.Alloc();
+    ASSERT(access != nullptr);
+    pci.Init(access);
+    pci.ScanBus(access);
+
+    for (pci_dev *device = access->devices; device != nullptr; device = device->next)
+    {
+        pci.FillInfo(device, PCI_FILL_IDENT | PCI_FILL_CLASS);
+
+        // Skip non-GPU devices
+        switch (device->device_class)
+        {
+            case PCI_CLASS_DISPLAY_VGA:
+            case PCI_CLASS_DISPLAY_XGA:
+            case PCI_CLASS_DISPLAY_3D:
+                break;
+            default:
+                continue;
+        }
+
+        // Skip unknown devices
+        if (device->vendor_id == 0 || device->device_id == 0)
+        {
+            continue;
+        }
+
+        GPUDeviceInfo info;
+        info.vendorId = device->vendor_id;
+        info.deviceId = device->device_id;
+
+        devices->push_back(info);
+    }
+
+    pci.Cleanup(access);
+
+    return true;
+}
+}
diff --git a/src/third_party/angle/src/gpu_info_util/SystemInfo_linux.cpp b/src/third_party/angle/src/gpu_info_util/SystemInfo_linux.cpp
new file mode 100644
index 0000000..98f000b
--- /dev/null
+++ b/src/third_party/angle/src/gpu_info_util/SystemInfo_linux.cpp
@@ -0,0 +1,144 @@
+//
+// Copyright (c) 2013-2017 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.
+//
+
+// SystemInfo_linux.cpp: implementation of the Linux-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#include <cstring>
+#include <fstream>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+namespace angle
+{
+
+namespace
+{
+
+bool ReadWholeFile(const char *filename, std::string *content)
+{
+    std::ifstream file(filename);
+
+    if (!file)
+    {
+        return false;
+    }
+
+    *content = std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
+    return true;
+}
+
+// Scan /sys/module/amdgpu/version.
+bool GetAMDBrahmaDriverVersion(std::string *version)
+{
+    *version = "";
+    std::string content;
+
+    return ReadWholeFile("/sys/module/amdgpu/version", &content) &&
+           ParseAMDBrahmaDriverVersion(content, version);
+}
+
+// Scan /etc/ati/amdpcsdb.default for "ReleaseVersion".
+bool GetAMDCatalystDriverVersion(std::string *version)
+{
+    *version = "";
+    std::string content;
+
+    return ReadWholeFile("/etc/ati/amdpcsdb.default", &content) &&
+           ParseAMDCatalystDriverVersion(content, version);
+}
+
+}  // anonymous namespace
+
+#if !defined(GPU_INFO_USE_X11)
+bool GetNvidiaDriverVersionWithXNVCtrl(std::string *version)
+{
+    return false;
+}
+#endif
+
+#if !defined(GPU_INFO_USE_LIBPCI)
+bool GetPCIDevicesWithLibPCI(std::vector<GPUDeviceInfo> *devices)
+{
+    return false;
+}
+#endif
+
+bool GetSystemInfo(SystemInfo *info)
+{
+    if (!GetPCIDevicesWithLibPCI(&(info->gpus)))
+    {
+        return false;
+    }
+
+    if (info->gpus.size() == 0)
+    {
+        return false;
+    }
+
+    FindPrimaryGPU(info);
+
+    for (size_t i = 0; i < info->gpus.size(); ++i)
+    {
+        GPUDeviceInfo *gpu = &info->gpus[i];
+
+        // New GPUs might be added inside this loop, don't query for their driver version again
+        if (!gpu->driverVendor.empty())
+        {
+            continue;
+        }
+
+        if (IsAMD(gpu->vendorId))
+        {
+            std::string version;
+            if (GetAMDBrahmaDriverVersion(&version))
+            {
+                gpu->driverVendor  = "AMD (Brahma)";
+                gpu->driverVersion = std::move(version);
+            }
+            else if (GetAMDCatalystDriverVersion(&version))
+            {
+                gpu->driverVendor  = "AMD (Catalyst)";
+                gpu->driverVersion = std::move(version);
+            }
+        }
+
+        if (IsNvidia(gpu->vendorId))
+        {
+            std::string version;
+            if (GetNvidiaDriverVersionWithXNVCtrl(&version))
+            {
+                gpu->driverVendor  = "Nvidia";
+                gpu->driverVersion = std::move(version);
+            }
+        }
+
+        // In dual-GPU cases the PCI scan sometimes only gives us the Intel GPU.
+        // If we are able to query for the Nvidia driver version, it means there
+        // was hidden Nvidia GPU, so we add it to the list and make it primary.
+        if (IsIntel(gpu->vendorId) && info->gpus.size() == 1)
+        {
+            std::string version;
+            if (GetNvidiaDriverVersionWithXNVCtrl(&version))
+            {
+                GPUDeviceInfo nvidiaInfo;
+                nvidiaInfo.vendorId = kVendorID_Nvidia;
+                nvidiaInfo.deviceId = 0;
+                gpu->driverVendor   = "Nvidia";
+                gpu->driverVersion  = std::move(version);
+
+                info->gpus.emplace_back(std::move(nvidiaInfo));
+                info->isOptimus = true;
+            }
+        }
+    }
+
+    return true;
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/gpu_info_util/SystemInfo_mac.mm b/src/third_party/angle/src/gpu_info_util/SystemInfo_mac.mm
new file mode 100644
index 0000000..7a7a62d
--- /dev/null
+++ b/src/third_party/angle/src/gpu_info_util/SystemInfo_mac.mm
@@ -0,0 +1,170 @@
+//
+// Copyright (c) 2017 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.
+//
+
+// SystemInfo_mac.cpp: implementation of the Mac-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#import <Cocoa/Cocoa.h>
+#import <IOKit/IOKitLib.h>
+
+namespace angle
+{
+
+namespace
+{
+
+std::string GetMachineModel()
+{
+    io_service_t platformExpert = IOServiceGetMatchingService(
+        kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
+
+    if (platformExpert == IO_OBJECT_NULL)
+    {
+        return "";
+    }
+
+    CFDataRef modelData = static_cast<CFDataRef>(
+        IORegistryEntryCreateCFProperty(platformExpert, CFSTR("model"), kCFAllocatorDefault, 0));
+    if (modelData == nullptr)
+    {
+        IOObjectRelease(platformExpert);
+        return "";
+    }
+
+    std::string result = reinterpret_cast<const char *>(CFDataGetBytePtr(modelData));
+
+    IOObjectRelease(platformExpert);
+    CFRelease(modelData);
+
+    return result;
+}
+
+// Extracts one integer property from a registry entry.
+bool GetEntryProperty(io_registry_entry_t entry, CFStringRef name, uint32_t *value)
+{
+    *value = 0;
+
+    CFDataRef data = static_cast<CFDataRef>(
+        IORegistryEntrySearchCFProperty(entry, kIOServicePlane, name, kCFAllocatorDefault,
+                                        kIORegistryIterateRecursively | kIORegistryIterateParents));
+
+    if (data == nullptr)
+    {
+        return false;
+    }
+
+    const uint32_t *valuePtr = reinterpret_cast<const uint32_t *>(CFDataGetBytePtr(data));
+
+    if (valuePtr == nullptr)
+    {
+        CFRelease(data);
+        return false;
+    }
+
+    *value = *valuePtr;
+    CFRelease(data);
+    return true;
+}
+
+// CGDisplayIOServicePort is deprecated as of macOS 10.9, but has no replacement, see
+// https://crbug.com/650837
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+// Find the info of the current GPU.
+bool GetActiveGPU(VendorID *vendorId, DeviceID *deviceId)
+{
+    io_registry_entry_t port = CGDisplayIOServicePort(kCGDirectMainDisplay);
+
+    return GetEntryProperty(port, CFSTR("vendor-id"), vendorId) &&
+           GetEntryProperty(port, CFSTR("device-id"), deviceId);
+}
+
+#pragma clang diagnostic pop
+
+// Gathers the vendor and device IDs for the PCI GPUs
+bool GetPCIDevices(std::vector<GPUDeviceInfo> *devices)
+{
+    // matchDictionary will be consumed by IOServiceGetMatchingServices, no need to release it.
+    CFMutableDictionaryRef matchDictionary = IOServiceMatching("IOPCIDevice");
+
+    io_iterator_t entryIterator;
+    if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchDictionary, &entryIterator) !=
+        kIOReturnSuccess)
+    {
+        return false;
+    }
+
+    io_registry_entry_t entry = IO_OBJECT_NULL;
+
+    while ((entry = IOIteratorNext(entryIterator)) != IO_OBJECT_NULL)
+    {
+        constexpr uint32_t kClassCodeDisplayVGA = 0x30000;
+        uint32_t classCode;
+        GPUDeviceInfo info;
+
+        if (GetEntryProperty(entry, CFSTR("class-code"), &classCode) &&
+            classCode == kClassCodeDisplayVGA &&
+            GetEntryProperty(entry, CFSTR("vendor-id"), &info.vendorId) &&
+            GetEntryProperty(entry, CFSTR("device-id"), &info.deviceId))
+        {
+            devices->push_back(info);
+        }
+
+        IOObjectRelease(entry);
+    }
+    IOObjectRelease(entryIterator);
+
+    return true;
+}
+
+}  // anonymous namespace
+
+bool GetSystemInfo(SystemInfo *info)
+{
+    {
+        int32_t major = 0;
+        int32_t minor = 0;
+        ParseMacMachineModel(GetMachineModel(), &info->machineModelName, &major, &minor);
+        info->machineModelVersion = std::to_string(major) + "." + std::to_string(minor);
+    }
+
+    if (!GetPCIDevices(&(info->gpus)))
+    {
+        return false;
+    }
+
+    if (info->gpus.empty())
+    {
+        return false;
+    }
+
+    // Find the active GPU
+    {
+        VendorID activeVendor;
+        DeviceID activeDevice;
+        if (!GetActiveGPU(&activeVendor, &activeDevice))
+        {
+            return false;
+        }
+
+        for (size_t i = 0; i < info->gpus.size(); ++i)
+        {
+            if (info->gpus[i].vendorId == activeVendor && info->gpus[i].deviceId == activeDevice)
+            {
+                info->activeGPUIndex = i;
+                break;
+            }
+        }
+    }
+
+    FindPrimaryGPU(info);
+
+    return true;
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/gpu_info_util/SystemInfo_unittest.cpp b/src/third_party/angle/src/gpu_info_util/SystemInfo_unittest.cpp
new file mode 100644
index 0000000..37d1384
--- /dev/null
+++ b/src/third_party/angle/src/gpu_info_util/SystemInfo_unittest.cpp
@@ -0,0 +1,131 @@
+//
+// Copyright 2017 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.
+//
+// SystemInfo_unittest.cpp: Unit tests for SystemInfo* helper functions.
+//
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#include <gtest/gtest.h>
+
+using namespace angle;
+
+namespace
+{
+
+// Test AMD Brahma driver version parsing
+TEST(SystemInfoTest, AMDBrahmaVersionParsing)
+{
+    std::string version;
+
+    // Check parsing fails when no version string is present.
+    ASSERT_FALSE(ParseAMDBrahmaDriverVersion("I am a lumberjack.", &version));
+    ASSERT_EQ("", version);
+
+    // Check parsing when the string is just the version string, with and without dots
+    ASSERT_TRUE(ParseAMDBrahmaDriverVersion("42", &version));
+    ASSERT_EQ("42", version);
+    ASSERT_TRUE(ParseAMDBrahmaDriverVersion("42.0.56", &version));
+    ASSERT_EQ("42.0.56", version);
+
+    // Check parsing with prefix / suffix
+    ASSERT_TRUE(ParseAMDBrahmaDriverVersion("Version=42.0.56", &version));
+    ASSERT_EQ("42.0.56", version);
+    ASSERT_TRUE(ParseAMDBrahmaDriverVersion("42.0.56 is the version", &version));
+    ASSERT_EQ("42.0.56", version);
+    ASSERT_TRUE(ParseAMDBrahmaDriverVersion("42.0.56 is the version, 111", &version));
+    ASSERT_EQ("42.0.56", version);
+}
+
+// Test AMD Catalyst version parsing
+TEST(SystemInfoTest, AMDCatalystVersionParsing)
+{
+    std::string version;
+
+    // Check parsing fails when no version string is present.
+    ASSERT_FALSE(ParseAMDCatalystDriverVersion("I am a lumberjack.\nReleaseVersion=", &version));
+    ASSERT_EQ("", version);
+
+    // Check parsing fails when ReleaseVersion= is present but no number appears in the line
+    ASSERT_FALSE(ParseAMDCatalystDriverVersion("11\nReleaseVersion=\n12", &version));
+    ASSERT_EQ("", version);
+
+    // Check parsing works on the simple case
+    ASSERT_TRUE(ParseAMDCatalystDriverVersion("ReleaseVersion=42.0.56", &version));
+    ASSERT_EQ("42.0.56", version);
+
+    // Check parsing works if there are other lines
+    ASSERT_TRUE(ParseAMDCatalystDriverVersion("11\nReleaseVersion=42.0.56\n12", &version));
+    ASSERT_EQ("42.0.56", version);
+
+    // Check parsing get the first version string
+    ASSERT_TRUE(
+        ParseAMDCatalystDriverVersion("ReleaseVersion=42.0.56\nReleaseVersion=0", &version));
+    ASSERT_EQ("42.0.56", version);
+
+    // Check parsing with prefix / suffix
+    ASSERT_TRUE(ParseAMDCatalystDriverVersion("ReleaseVersion=version is 42.0.56", &version));
+    ASSERT_EQ("42.0.56", version);
+    ASSERT_TRUE(ParseAMDCatalystDriverVersion("ReleaseVersion=42.0.56 is the version", &version));
+    ASSERT_EQ("42.0.56", version);
+}
+
+// Test Mac machine model parsing
+TEST(SystemInfoTest, MacMachineModelParsing)
+{
+    std::string model;
+    int32_t major = 1, minor = 2;
+
+    // Test on the empty string, that is returned by GetMachineModel on an error
+    EXPECT_FALSE(ParseMacMachineModel("", &model, &major, &minor));
+    EXPECT_EQ(0U, model.length());
+    EXPECT_EQ(1, major);
+    EXPECT_EQ(2, minor);
+
+    // Test on an invalid string
+    EXPECT_FALSE(ParseMacMachineModel("FooBar", &model, &major, &minor));
+
+    // Test on a MacPro model
+    EXPECT_TRUE(ParseMacMachineModel("MacPro4,1", &model, &major, &minor));
+    EXPECT_EQ("MacPro", model);
+    EXPECT_EQ(4, major);
+    EXPECT_EQ(1, minor);
+
+    // Test on a MacBookPro model
+    EXPECT_TRUE(ParseMacMachineModel("MacBookPro6,2", &model, &major, &minor));
+    EXPECT_EQ("MacBookPro", model);
+    EXPECT_EQ(6, major);
+    EXPECT_EQ(2, minor);
+}
+
+// Test Windows CM Device ID parsing
+TEST(SystemInfoTest, CMDeviceIDToDeviceAndVendorID)
+{
+    uint32_t vendor = 0;
+    uint32_t device = 0;
+
+    // Test on a real-life CM Device ID
+    EXPECT_TRUE(CMDeviceIDToDeviceAndVendorID(
+        "PCI\\VEN_10DE&DEV_0FFA&SUBSYS_094B10DE&REV_A1\\4&95673C&0&0018", &vendor, &device));
+    EXPECT_EQ(0x10deu, vendor);
+    EXPECT_EQ(0x0ffau, device);
+
+    // Test on a stripped-down but valid CM Device ID string
+    EXPECT_TRUE(CMDeviceIDToDeviceAndVendorID("PCI\\VEN_10DE&DEV_0FFA", &vendor, &device));
+    EXPECT_EQ(0x10deu, vendor);
+    EXPECT_EQ(0x0ffau, device);
+
+    // Test on a string that is too small
+    EXPECT_FALSE(CMDeviceIDToDeviceAndVendorID("\\VEN_10DE&DEV_0FFA", &vendor, &device));
+    EXPECT_EQ(0u, vendor);
+    EXPECT_EQ(0u, device);
+
+    // Test with invalid number
+    EXPECT_FALSE(CMDeviceIDToDeviceAndVendorID("PCI\\VEN_XXXX&DEV_XXXX", &vendor, &device));
+    EXPECT_EQ(0u, vendor);
+    EXPECT_EQ(0u, device);
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/gpu_info_util/SystemInfo_win.cpp b/src/third_party/angle/src/gpu_info_util/SystemInfo_win.cpp
new file mode 100644
index 0000000..3073822
--- /dev/null
+++ b/src/third_party/angle/src/gpu_info_util/SystemInfo_win.cpp
@@ -0,0 +1,204 @@
+//
+// Copyright (c) 2013-2017 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.
+//
+
+// SystemInfo_win.cpp: implementation of the Windows-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+// Windows.h needs to be included first
+#include <windows.h>
+
+#if defined(GPU_INFO_USE_SETUPAPI)
+#include <cfgmgr32.h>
+#include <setupapi.h>
+#elif defined(GPU_INFO_USE_DXGI)
+#include <dxgi.h>
+#include <d3d10.h>
+#else
+#error "SystemInfo_win needs at least GPU_INFO_USE_SETUPAPI or GPU_INFO_USE_DXGI defined"
+#endif
+
+#include <array>
+#include <sstream>
+
+namespace angle
+{
+
+namespace
+{
+
+#if defined(GPU_INFO_USE_SETUPAPI)
+
+std::string GetRegistryStringValue(HKEY key, const char *valueName)
+{
+    std::array<char, 255> value;
+    DWORD valueSize = sizeof(value);
+    if (RegQueryValueExA(key, valueName, nullptr, nullptr, reinterpret_cast<LPBYTE>(value.data()),
+                         &valueSize) == ERROR_SUCCESS)
+    {
+        return value.data();
+    }
+    return "";
+}
+
+// Gathers information about the devices from the registry. The reason why we aren't using
+// a dedicated API such as DXGI is that we need information like the driver vendor and date.
+// DXGI doesn't provide a way to know the device registry key from an IDXGIAdapter.
+bool GetDevicesFromRegistry(std::vector<GPUDeviceInfo> *devices)
+{
+    // Display adapter class GUID from
+    // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx
+    GUID displayClass = {
+        0x4d36e968, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
+
+    HDEVINFO deviceInfo = SetupDiGetClassDevsW(&displayClass, nullptr, nullptr, DIGCF_PRESENT);
+
+    if (deviceInfo == INVALID_HANDLE_VALUE)
+    {
+        return false;
+    }
+
+    // This iterates over the devices of the "Display adapter" class
+    DWORD deviceIndex = 0;
+    SP_DEVINFO_DATA deviceData;
+    deviceData.cbSize = sizeof(deviceData);
+    while (SetupDiEnumDeviceInfo(deviceInfo, deviceIndex++, &deviceData))
+    {
+        // The device and vendor IDs can be gathered directly, but information about the driver
+        // requires some registry digging
+        char fullDeviceID[MAX_DEVICE_ID_LEN];
+        if (CM_Get_Device_IDA(deviceData.DevInst, fullDeviceID, MAX_DEVICE_ID_LEN, 0) != CR_SUCCESS)
+        {
+            continue;
+        }
+
+        GPUDeviceInfo device;
+
+        if (!CMDeviceIDToDeviceAndVendorID(fullDeviceID, &device.vendorId, &device.deviceId))
+        {
+            continue;
+        }
+
+        // The driver key will end with something like {<displayClass>}/<4 digit number>.
+        std::array<WCHAR, 255> value;
+        if (!SetupDiGetDeviceRegistryPropertyW(deviceInfo, &deviceData, SPDRP_DRIVER, nullptr,
+                                               reinterpret_cast<PBYTE>(value.data()), sizeof(value),
+                                               nullptr))
+        {
+            continue;
+        }
+
+        std::wstring driverKey = L"System\\CurrentControlSet\\Control\\Class\\";
+        driverKey += value.data();
+
+        HKEY key;
+        if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.c_str(), 0, KEY_QUERY_VALUE, &key) !=
+            ERROR_SUCCESS)
+        {
+            continue;
+        }
+
+        device.driverVersion = GetRegistryStringValue(key, "DriverVersion");
+        device.driverDate    = GetRegistryStringValue(key, "DriverDate");
+        device.driverVendor  = GetRegistryStringValue(key, "ProviderName");
+
+        RegCloseKey(key);
+
+        devices->push_back(device);
+    }
+
+    SetupDiDestroyDeviceInfoList(deviceInfo);
+
+    return true;
+}
+
+#elif defined(GPU_INFO_USE_DXGI)
+
+bool GetDevicesFromDXGI(std::vector<GPUDeviceInfo> *devices)
+{
+    IDXGIFactory *factory;
+    if (!SUCCEEDED(CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&factory))))
+    {
+        return false;
+    }
+
+    UINT i                = 0;
+    IDXGIAdapter *adapter = nullptr;
+    while (factory->EnumAdapters(i++, &adapter) != DXGI_ERROR_NOT_FOUND)
+    {
+        DXGI_ADAPTER_DESC desc;
+        adapter->GetDesc(&desc);
+
+        LARGE_INTEGER umdVersion;
+        if (adapter->CheckInterfaceSupport(__uuidof(ID3D10Device), &umdVersion) ==
+            DXGI_ERROR_UNSUPPORTED)
+        {
+            adapter->Release();
+            continue;
+        }
+
+        // The UMD driver version here is the same as in the registry except for the last number.
+        uint64_t intVersion = umdVersion.QuadPart;
+        std::ostringstream o;
+
+        const uint64_t kMask = 0xFF;
+        o << ((intVersion >> 48) & kMask) << ".";
+        o << ((intVersion >> 32) & kMask) << ".";
+        o << ((intVersion >> 16) & kMask) << ".";
+        o << (intVersion & kMask);
+
+        GPUDeviceInfo device;
+        device.vendorId      = desc.VendorId;
+        device.deviceId      = desc.DeviceId;
+        device.driverVersion = o.str();
+
+        devices->push_back(device);
+
+        adapter->Release();
+    }
+
+    factory->Release();
+
+    return true;
+}
+
+#else
+#error
+#endif
+
+}  // anonymous namespace
+
+bool GetSystemInfo(SystemInfo *info)
+{
+#if defined(GPU_INFO_USE_SETUPAPI)
+    if (!GetDevicesFromRegistry(&info->gpus))
+    {
+        return false;
+    }
+#elif defined(GPU_INFO_USE_DXGI)
+    if (!GetDevicesFromDXGI(&info->gpus))
+    {
+        return false;
+    }
+#else
+#error
+#endif
+
+    if (info->gpus.size() == 0)
+    {
+        return false;
+    }
+
+    FindPrimaryGPU(info);
+
+    // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled.
+    HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll");
+    info->isOptimus    = nvd3d9wrap != nullptr;
+
+    return true;
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/gpu_info_util/SystemInfo_x11.cpp b/src/third_party/angle/src/gpu_info_util/SystemInfo_x11.cpp
new file mode 100644
index 0000000..3513309
--- /dev/null
+++ b/src/third_party/angle/src/gpu_info_util/SystemInfo_x11.cpp
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2013-2017 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.
+//
+
+// SystemInfo_x11.cpp: implementation of the X11-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#include <X11/Xlib.h>
+
+#include "common/debug.h"
+#include "third_party/libXNVCtrl/NVCtrl.h"
+#include "third_party/libXNVCtrl/NVCtrlLib.h"
+
+#if !defined(GPU_INFO_USE_X11)
+#error SystemInfo_x11.cpp compiled without GPU_INFO_USE_X11
+#endif
+
+namespace angle
+{
+
+bool GetNvidiaDriverVersionWithXNVCtrl(std::string *version)
+{
+    *version = "";
+
+    int eventBase = 0;
+    int errorBase = 0;
+
+    Display *display = XOpenDisplay(nullptr);
+
+    if (XNVCTRLQueryExtension(display, &eventBase, &errorBase))
+    {
+        int screenCount = ScreenCount(display);
+        for (int screen = 0; screen < screenCount; ++screen)
+        {
+            char *buffer = nullptr;
+            if (XNVCTRLIsNvScreen(display, screen) &&
+                XNVCTRLQueryStringAttribute(display, screen, 0,
+                                            NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &buffer))
+            {
+                ASSERT(buffer != nullptr);
+                *version = buffer;
+                XFree(buffer);
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+}
diff --git a/src/third_party/angle/src/image_util/copyimage.cpp b/src/third_party/angle/src/image_util/copyimage.cpp
new file mode 100644
index 0000000..cc07908
--- /dev/null
+++ b/src/third_party/angle/src/image_util/copyimage.cpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// copyimage.cpp: Defines image copying functions
+
+#include "image_util/copyimage.h"
+
+namespace angle
+{
+
+void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest)
+{
+    uint32_t argb                       = *reinterpret_cast<const uint32_t *>(source);
+    *reinterpret_cast<uint32_t *>(dest) = (argb & 0xFF00FF00) |        // Keep alpha and green
+                                          (argb & 0x00FF0000) >> 16 |  // Move red to blue
+                                          (argb & 0x000000FF) << 16;   // Move blue to red
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/image_util/copyimage.h b/src/third_party/angle/src/image_util/copyimage.h
new file mode 100644
index 0000000..bc8c139
--- /dev/null
+++ b/src/third_party/angle/src/image_util/copyimage.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// copyimage.h: Defines image copying functions
+
+#ifndef IMAGEUTIL_COPYIMAGE_H_
+#define IMAGEUTIL_COPYIMAGE_H_
+
+#include "common/Color.h"
+
+#include "image_util/imageformats.h"
+
+#include <stdint.h>
+
+namespace angle
+{
+
+template <typename sourceType, typename colorDataType>
+void ReadColor(const uint8_t *source, uint8_t *dest);
+
+template <typename destType, typename colorDataType>
+void WriteColor(const uint8_t *source, uint8_t *dest);
+
+template <typename sourceType, typename destType, typename colorDataType>
+void CopyPixel(const uint8_t *source, uint8_t *dest);
+
+void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest);
+
+}  // namespace angle
+
+#include "copyimage.inl"
+
+#endif  // IMAGEUTIL_COPYIMAGE_H_
diff --git a/src/third_party/angle/src/image_util/copyimage.inl b/src/third_party/angle/src/image_util/copyimage.inl
new file mode 100644
index 0000000..dbada81
--- /dev/null
+++ b/src/third_party/angle/src/image_util/copyimage.inl
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// copyimage.inl: Defines image copying functions
+
+namespace angle
+{
+
+template <typename sourceType, typename colorDataType>
+inline void ReadColor(const uint8_t *source, uint8_t *dest)
+{
+    sourceType::readColor(reinterpret_cast<Color<colorDataType>*>(dest),
+                          reinterpret_cast<const sourceType*>(source));
+}
+
+template <typename destType, typename colorDataType>
+inline void WriteColor(const uint8_t *source, uint8_t *dest)
+{
+    destType::writeColor(reinterpret_cast<destType*>(dest),
+                         reinterpret_cast<const Color<colorDataType>*>(source));
+}
+
+template <typename sourceType, typename destType, typename colorDataType>
+inline void CopyPixel(const uint8_t *source, uint8_t *dest)
+{
+    colorDataType temp;
+    ReadColor<sourceType, colorDataType>(source, &temp);
+    WriteColor<destType, colorDataType>(&temp, dest);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/image_util/generatemip.h b/src/third_party/angle/src/image_util/generatemip.h
new file mode 100644
index 0000000..a89db82
--- /dev/null
+++ b/src/third_party/angle/src/image_util/generatemip.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// generatemip.h: Defines the GenerateMip function, templated on the format
+// type of the image for which mip levels are being generated.
+
+#ifndef IMAGEUTIL_GENERATEMIP_H_
+#define IMAGEUTIL_GENERATEMIP_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace angle
+{
+
+template <typename T>
+inline void GenerateMip(size_t sourceWidth,
+                        size_t sourceHeight,
+                        size_t sourceDepth,
+                        const uint8_t *sourceData,
+                        size_t sourceRowPitch,
+                        size_t sourceDepthPitch,
+                        uint8_t *destData,
+                        size_t destRowPitch,
+                        size_t destDepthPitch);
+
+}  // namespace angle
+
+#include "generatemip.inl"
+
+#endif  // IMAGEUTIL_GENERATEMIP_H_
diff --git a/src/third_party/angle/src/image_util/generatemip.inl b/src/third_party/angle/src/image_util/generatemip.inl
new file mode 100644
index 0000000..ddf510c
--- /dev/null
+++ b/src/third_party/angle/src/image_util/generatemip.inl
@@ -0,0 +1,268 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// generatemip.inl: Defines the GenerateMip function, templated on the format
+// type of the image for which mip levels are being generated.
+
+#include "common/mathutil.h"
+
+#include "image_util/imageformats.h"
+
+namespace angle
+{
+
+namespace priv
+{
+
+template <typename T>
+static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+    return reinterpret_cast<T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename T>
+static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+    return reinterpret_cast<const T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename T>
+static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+                          const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+                          size_t destWidth, size_t destHeight, size_t destDepth,
+                          uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+    ASSERT(sourceWidth == 1);
+    ASSERT(sourceHeight > 1);
+    ASSERT(sourceDepth == 1);
+
+    for (size_t y = 0; y < destHeight; y++)
+    {
+        const T *src0 = GetPixel<T>(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch);
+        const T *src1 = GetPixel<T>(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
+        T *dst = GetPixel<T>(destData, 0, y, 0, destRowPitch, destDepthPitch);
+
+        T::average(dst, src0, src1);
+    }
+}
+
+template <typename T>
+static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+                          const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+                          size_t destWidth, size_t destHeight, size_t destDepth,
+                          uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+    ASSERT(sourceWidth > 1);
+    ASSERT(sourceHeight == 1);
+    ASSERT(sourceDepth == 1);
+
+    for (size_t x = 0; x < destWidth; x++)
+    {
+        const T *src0 = GetPixel<T>(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch);
+        const T *src1 = GetPixel<T>(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch);
+        T *dst = GetPixel<T>(destData, x, 0, 0, destRowPitch, destDepthPitch);
+
+        T::average(dst, src0, src1);
+    }
+}
+
+template <typename T>
+static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+                          const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+                          size_t destWidth, size_t destHeight, size_t destDepth,
+                          uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+    ASSERT(sourceWidth == 1);
+    ASSERT(sourceHeight == 1);
+    ASSERT(sourceDepth > 1);
+
+    for (size_t z = 0; z < destDepth; z++)
+    {
+        const T *src0 = GetPixel<T>(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch);
+        const T *src1 = GetPixel<T>(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+        T *dst = GetPixel<T>(destData, 0, 0, z, destRowPitch, destDepthPitch);
+
+        T::average(dst, src0, src1);
+    }
+}
+
+template <typename T>
+static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+                           const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+                           size_t destWidth, size_t destHeight, size_t destDepth,
+                           uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+    ASSERT(sourceWidth > 1);
+    ASSERT(sourceHeight > 1);
+    ASSERT(sourceDepth == 1);
+
+    for (size_t y = 0; y < destHeight; y++)
+    {
+        for (size_t x = 0; x < destWidth; x++)
+        {
+            const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch);
+            const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
+            const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch);
+            const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
+            T *dst = GetPixel<T>(destData, x, y, 0, destRowPitch, destDepthPitch);
+
+            T tmp0, tmp1;
+
+            T::average(&tmp0, src0, src1);
+            T::average(&tmp1, src2, src3);
+            T::average(dst, &tmp0, &tmp1);
+        }
+    }
+}
+
+template <typename T>
+static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+                           const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+                           size_t destWidth, size_t destHeight, size_t destDepth,
+                           uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+    ASSERT(sourceWidth == 1);
+    ASSERT(sourceHeight > 1);
+    ASSERT(sourceDepth > 1);
+
+    for (size_t z = 0; z < destDepth; z++)
+    {
+        for (size_t y = 0; y < destHeight; y++)
+        {
+            const T *src0 = GetPixel<T>(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
+            const T *src1 = GetPixel<T>(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+            const T *src2 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
+            const T *src3 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+            T *dst = GetPixel<T>(destData, 0, y, z, destRowPitch, destDepthPitch);
+
+            T tmp0, tmp1;
+
+            T::average(&tmp0, src0, src1);
+            T::average(&tmp1, src2, src3);
+            T::average(dst, &tmp0, &tmp1);
+        }
+    }
+}
+
+template <typename T>
+static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+                           const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+                           size_t destWidth, size_t destHeight, size_t destDepth,
+                           uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+    ASSERT(sourceWidth > 1);
+    ASSERT(sourceHeight == 1);
+    ASSERT(sourceDepth > 1);
+
+    for (size_t z = 0; z < destDepth; z++)
+    {
+        for (size_t x = 0; x < destWidth; x++)
+        {
+            const T *src0 = GetPixel<T>(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch);
+            const T *src1 = GetPixel<T>(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+            const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch);
+            const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+            T *dst = GetPixel<T>(destData, x, 0, z, destRowPitch, destDepthPitch);
+
+            T tmp0, tmp1;
+
+            T::average(&tmp0, src0, src1);
+            T::average(&tmp1, src2, src3);
+            T::average(dst, &tmp0, &tmp1);
+        }
+    }
+}
+
+template <typename T>
+static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+                            const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+                            size_t destWidth, size_t destHeight, size_t destDepth,
+                            uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+    ASSERT(sourceWidth > 1);
+    ASSERT(sourceHeight > 1);
+    ASSERT(sourceDepth > 1);
+
+    for (size_t z = 0; z < destDepth; z++)
+    {
+        for (size_t y = 0; y < destHeight; y++)
+        {
+            for (size_t x = 0; x < destWidth; x++)
+            {
+                const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
+                const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+                const T *src2 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
+                const T *src3 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+                const T *src4 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
+                const T *src5 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+                const T *src6 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
+                const T *src7 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+                T *dst = GetPixel<T>(destData, x, y, z, destRowPitch, destDepthPitch);
+
+                T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+
+                T::average(&tmp0, src0, src1);
+                T::average(&tmp1, src2, src3);
+                T::average(&tmp2, src4, src5);
+                T::average(&tmp3, src6, src7);
+
+                T::average(&tmp4, &tmp0, &tmp1);
+                T::average(&tmp5, &tmp2, &tmp3);
+
+                T::average(dst, &tmp4, &tmp5);
+            }
+        }
+    }
+}
+
+
+typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+                                      const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+                                      size_t destWidth, size_t destHeight, size_t destDepth,
+                                      uint8_t *destData, size_t destRowPitch, size_t destDepthPitch);
+
+template <typename T>
+static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth)
+{
+    uint8_t index = ((sourceWidth > 1)  ? 1 : 0) |
+                    ((sourceHeight > 1) ? 2 : 0) |
+                    ((sourceDepth > 1)  ? 4 : 0);
+
+    switch (index)
+    {
+      case 0: return nullptr;
+      case 1: return GenerateMip_X<T>;   // W x 1 x 1
+      case 2: return GenerateMip_Y<T>;   // 1 x H x 1
+      case 3: return GenerateMip_XY<T>;  // W x H x 1
+      case 4: return GenerateMip_Z<T>;   // 1 x 1 x D
+      case 5: return GenerateMip_XZ<T>;  // W x 1 x D
+      case 6: return GenerateMip_YZ<T>;  // 1 x H x D
+      case 7: return GenerateMip_XYZ<T>; // W x H x D
+    }
+
+    UNREACHABLE();
+    return nullptr;
+}
+
+}  // namespace priv
+
+template <typename T>
+inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+                        const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+                        uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+    size_t mipWidth = std::max<size_t>(1, sourceWidth >> 1);
+    size_t mipHeight = std::max<size_t>(1, sourceHeight >> 1);
+    size_t mipDepth = std::max<size_t>(1, sourceDepth >> 1);
+
+    priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction<T>(sourceWidth, sourceHeight, sourceDepth);
+    ASSERT(generationFunction != nullptr);
+
+    generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch,
+                       mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/image_util/imageformats.cpp b/src/third_party/angle/src/image_util/imageformats.cpp
new file mode 100644
index 0000000..84292a9
--- /dev/null
+++ b/src/third_party/angle/src/image_util/imageformats.cpp
@@ -0,0 +1,1714 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// imageformats.cpp: Defines image format types with functions for mip generation
+// and copying.
+
+#include "image_util/imageformats.h"
+
+#include "common/mathutil.h"
+
+namespace angle
+{
+
+void L8::readColor(gl::ColorF *dst, const L8 *src)
+{
+    const float lum = gl::normalizedToFloat(src->L);
+    dst->red        = lum;
+    dst->green      = lum;
+    dst->blue       = lum;
+    dst->alpha      = 1.0f;
+}
+
+void L8::writeColor(L8 *dst, const gl::ColorF *src)
+{
+    dst->L = gl::floatToNormalized<uint8_t>(src->red);
+}
+
+void L8::average(L8 *dst, const L8 *src1, const L8 *src2)
+{
+    dst->L = gl::average(src1->L, src2->L);
+}
+
+void R8::readColor(gl::ColorUI *dst, const R8 *src)
+{
+    dst->red   = src->R;
+    dst->green = 0;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R8::readColor(gl::ColorF *dst, const R8 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R8::writeColor(R8 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint8_t>(src->red);
+}
+
+void R8::writeColor(R8 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint8_t>(src->red);
+}
+
+void R8::average(R8 *dst, const R8 *src1, const R8 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+}
+
+void A8::readColor(gl::ColorF *dst, const A8 *src)
+{
+    dst->red   = 0.0f;
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void A8::writeColor(A8 *dst, const gl::ColorF *src)
+{
+    dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void A8::average(A8 *dst, const A8 *src1, const A8 *src2)
+{
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void L8A8::readColor(gl::ColorF *dst, const L8A8 *src)
+{
+    const float lum = gl::normalizedToFloat(src->L);
+    dst->red        = lum;
+    dst->green      = lum;
+    dst->blue       = lum;
+    dst->alpha      = gl::normalizedToFloat(src->A);
+}
+
+void L8A8::writeColor(L8A8 *dst, const gl::ColorF *src)
+{
+    dst->L = gl::floatToNormalized<uint8_t>(src->red);
+    dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void L8A8::average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2)
+{
+    *(uint16_t *)dst = (((*(uint16_t *)src1 ^ *(uint16_t *)src2) & 0xFEFE) >> 1) +
+                       (*(uint16_t *)src1 & *(uint16_t *)src2);
+}
+
+void A8L8::readColor(gl::ColorF *dst, const A8L8 *src)
+{
+    const float lum = gl::normalizedToFloat(src->L);
+    dst->red        = lum;
+    dst->green      = lum;
+    dst->blue       = lum;
+    dst->alpha      = gl::normalizedToFloat(src->A);
+}
+
+void A8L8::writeColor(A8L8 *dst, const gl::ColorF *src)
+{
+    dst->L = gl::floatToNormalized<uint8_t>(src->red);
+    dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void A8L8::average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2)
+{
+    *(uint16_t *)dst = (((*(uint16_t *)src1 ^ *(uint16_t *)src2) & 0xFEFE) >> 1) +
+                       (*(uint16_t *)src1 & *(uint16_t *)src2);
+}
+
+void R8G8::readColor(gl::ColorUI *dst, const R8G8 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R8G8::readColor(gl::ColorF *dst, const R8G8 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R8G8::writeColor(R8G8 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint8_t>(src->red);
+    dst->G = static_cast<uint8_t>(src->green);
+}
+
+void R8G8::writeColor(R8G8 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint8_t>(src->red);
+    dst->G = gl::floatToNormalized<uint8_t>(src->green);
+}
+
+void R8G8::average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2)
+{
+    *(uint16_t *)dst = (((*(uint16_t *)src1 ^ *(uint16_t *)src2) & 0xFEFE) >> 1) +
+                       (*(uint16_t *)src1 & *(uint16_t *)src2);
+}
+
+void R8G8B8::readColor(gl::ColorUI *dst, const R8G8B8 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->G;
+    dst->alpha = 1;
+}
+
+void R8G8B8::readColor(gl::ColorF *dst, const R8G8B8 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = 1.0f;
+}
+
+void R8G8B8::writeColor(R8G8B8 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint8_t>(src->red);
+    dst->G = static_cast<uint8_t>(src->green);
+    dst->B = static_cast<uint8_t>(src->blue);
+}
+
+void R8G8B8::writeColor(R8G8B8 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint8_t>(src->red);
+    dst->G = gl::floatToNormalized<uint8_t>(src->green);
+    dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+}
+
+void R8G8B8::average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+}
+
+void B8G8R8::readColor(gl::ColorUI *dst, const B8G8R8 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->G;
+    dst->alpha = 1;
+}
+
+void B8G8R8::readColor(gl::ColorF *dst, const B8G8R8 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = 1.0f;
+}
+
+void B8G8R8::writeColor(B8G8R8 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint8_t>(src->red);
+    dst->G = static_cast<uint8_t>(src->green);
+    dst->B = static_cast<uint8_t>(src->blue);
+}
+
+void B8G8R8::writeColor(B8G8R8 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint8_t>(src->red);
+    dst->G = gl::floatToNormalized<uint8_t>(src->green);
+    dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+}
+
+void B8G8R8::average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+}
+
+void R5G6B5::readColor(gl::ColorF *dst, const R5G6B5 *src)
+{
+    dst->red   = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGB));
+    dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->RGB));
+    dst->blue  = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGB));
+    dst->alpha = 1.0f;
+}
+
+void R5G6B5::writeColor(R5G6B5 *dst, const gl::ColorF *src)
+{
+    dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, uint16_t>(src->red)) |
+               gl::shiftData<6, 5>(gl::floatToNormalized<6, uint16_t>(src->green)) |
+               gl::shiftData<5, 0>(gl::floatToNormalized<5, uint16_t>(src->blue));
+}
+
+void R5G6B5::average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2)
+{
+    dst->RGB = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGB),
+                                                gl::getShiftedData<5, 11>(src2->RGB))) |
+               gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->RGB),
+                                               gl::getShiftedData<6, 5>(src2->RGB))) |
+               gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGB),
+                                               gl::getShiftedData<5, 0>(src2->RGB)));
+}
+
+void B5G6R5::readColor(gl::ColorF *dst, const B5G6R5 *src)
+{
+    dst->red   = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->BGR));
+    dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->BGR));
+    dst->blue  = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGR));
+    dst->alpha = 1.0f;
+}
+
+void B5G6R5::writeColor(B5G6R5 *dst, const gl::ColorF *src)
+{
+    dst->BGR = gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)) |
+               gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) |
+               gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red));
+}
+
+void B5G6R5::average(B5G6R5 *dst, const B5G6R5 *src1, const B5G6R5 *src2)
+{
+    dst->BGR = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->BGR),
+                                                gl::getShiftedData<5, 11>(src2->BGR))) |
+               gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->BGR),
+                                               gl::getShiftedData<6, 5>(src2->BGR))) |
+               gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->BGR),
+                                               gl::getShiftedData<5, 0>(src2->BGR)));
+}
+
+void A8R8G8B8::readColor(gl::ColorUI *dst, const A8R8G8B8 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void A8R8G8B8::readColor(gl::ColorF *dst, const A8R8G8B8 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void A8R8G8B8::writeColor(A8R8G8B8 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint8_t>(src->red);
+    dst->G = static_cast<uint8_t>(src->green);
+    dst->B = static_cast<uint8_t>(src->blue);
+    dst->A = static_cast<uint8_t>(src->alpha);
+}
+
+void A8R8G8B8::writeColor(A8R8G8B8 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint8_t>(src->red);
+    dst->G = gl::floatToNormalized<uint8_t>(src->green);
+    dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+    dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void A8R8G8B8::average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2)
+{
+    *(uint32_t *)dst = (((*(uint32_t *)src1 ^ *(uint32_t *)src2) & 0xFEFEFEFE) >> 1) +
+                       (*(uint32_t *)src1 & *(uint32_t *)src2);
+}
+
+void R8G8B8A8::readColor(gl::ColorUI *dst, const R8G8B8A8 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void R8G8B8A8::readColor(gl::ColorF *dst, const R8G8B8A8 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R8G8B8A8::writeColor(R8G8B8A8 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint8_t>(src->red);
+    dst->G = static_cast<uint8_t>(src->green);
+    dst->B = static_cast<uint8_t>(src->blue);
+    dst->A = static_cast<uint8_t>(src->alpha);
+}
+
+void R8G8B8A8::writeColor(R8G8B8A8 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint8_t>(src->red);
+    dst->G = gl::floatToNormalized<uint8_t>(src->green);
+    dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+    dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void R8G8B8A8::average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2)
+{
+    *(uint32_t *)dst = (((*(uint32_t *)src1 ^ *(uint32_t *)src2) & 0xFEFEFEFE) >> 1) +
+                       (*(uint32_t *)src1 & *(uint32_t *)src2);
+}
+
+void R8G8B8A8SRGB::readColor(gl::ColorF *dst, const R8G8B8A8SRGB *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R8G8B8A8SRGB::average(R8G8B8A8SRGB *dst, const R8G8B8A8SRGB *src1, const R8G8B8A8SRGB *src2)
+{
+    dst->R =
+        gl::linearToSRGB(static_cast<uint8_t>((static_cast<uint16_t>(gl::sRGBToLinear(src1->R)) +
+                                               static_cast<uint16_t>(gl::sRGBToLinear(src2->R))) >>
+                                              1));
+    dst->G =
+        gl::linearToSRGB(static_cast<uint8_t>((static_cast<uint16_t>(gl::sRGBToLinear(src1->G)) +
+                                               static_cast<uint16_t>(gl::sRGBToLinear(src2->G))) >>
+                                              1));
+    dst->B =
+        gl::linearToSRGB(static_cast<uint8_t>((static_cast<uint16_t>(gl::sRGBToLinear(src1->B)) +
+                                               static_cast<uint16_t>(gl::sRGBToLinear(src2->B))) >>
+                                              1));
+    dst->A = static_cast<uint8_t>(
+        (static_cast<uint16_t>(src1->A) + static_cast<uint16_t>(src2->A)) >> 1);
+}
+
+void B8G8R8A8::readColor(gl::ColorUI *dst, const B8G8R8A8 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void B8G8R8A8::readColor(gl::ColorF *dst, const B8G8R8A8 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void B8G8R8A8::writeColor(B8G8R8A8 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint8_t>(src->red);
+    dst->G = static_cast<uint8_t>(src->green);
+    dst->B = static_cast<uint8_t>(src->blue);
+    dst->A = static_cast<uint8_t>(src->alpha);
+}
+
+void B8G8R8A8::writeColor(B8G8R8A8 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint8_t>(src->red);
+    dst->G = gl::floatToNormalized<uint8_t>(src->green);
+    dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+    dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void B8G8R8A8::average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2)
+{
+    *(uint32_t *)dst = (((*(uint32_t *)src1 ^ *(uint32_t *)src2) & 0xFEFEFEFE) >> 1) +
+                       (*(uint32_t *)src1 & *(uint32_t *)src2);
+}
+
+void B8G8R8X8::readColor(gl::ColorUI *dst, const B8G8R8X8 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = 1;
+}
+
+void B8G8R8X8::readColor(gl::ColorF *dst, const B8G8R8X8 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = 1.0f;
+}
+
+void B8G8R8X8::writeColor(B8G8R8X8 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint8_t>(src->red);
+    dst->G = static_cast<uint8_t>(src->green);
+    dst->B = static_cast<uint8_t>(src->blue);
+    dst->X = 255;
+}
+
+void B8G8R8X8::writeColor(B8G8R8X8 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint8_t>(src->red);
+    dst->G = gl::floatToNormalized<uint8_t>(src->green);
+    dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+    dst->X = 255;
+}
+
+void B8G8R8X8::average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2)
+{
+    *(uint32_t *)dst = (((*(uint32_t *)src1 ^ *(uint32_t *)src2) & 0xFEFEFEFE) >> 1) +
+                       (*(uint32_t *)src1 & *(uint32_t *)src2);
+    dst->X = 255;
+}
+
+void A1R5G5B5::readColor(gl::ColorF *dst, const A1R5G5B5 *src)
+{
+    dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->ARGB));
+    dst->red   = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->ARGB));
+    dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->ARGB));
+    dst->blue  = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->ARGB));
+}
+
+void A1R5G5B5::writeColor(A1R5G5B5 *dst, const gl::ColorF *src)
+{
+    dst->ARGB = gl::shiftData<1, 15>(gl::floatToNormalized<1, uint16_t>(src->alpha)) |
+                gl::shiftData<5, 10>(gl::floatToNormalized<5, uint16_t>(src->red)) |
+                gl::shiftData<5, 5>(gl::floatToNormalized<5, uint16_t>(src->green)) |
+                gl::shiftData<5, 0>(gl::floatToNormalized<5, uint16_t>(src->blue));
+}
+
+void A1R5G5B5::average(A1R5G5B5 *dst, const A1R5G5B5 *src1, const A1R5G5B5 *src2)
+{
+    dst->ARGB = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->ARGB),
+                                                 gl::getShiftedData<1, 15>(src2->ARGB))) |
+                gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->ARGB),
+                                                 gl::getShiftedData<5, 10>(src2->ARGB))) |
+                gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->ARGB),
+                                                gl::getShiftedData<5, 5>(src2->ARGB))) |
+                gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->ARGB),
+                                                gl::getShiftedData<5, 0>(src2->ARGB)));
+}
+
+void R5G5B5A1::readColor(gl::ColorF *dst, const R5G5B5A1 *src)
+{
+    dst->red   = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGBA));
+    dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 6>(src->RGBA));
+    dst->blue  = gl::normalizedToFloat<5>(gl::getShiftedData<5, 1>(src->RGBA));
+    dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 0>(src->RGBA));
+}
+
+void R5G5B5A1::writeColor(R5G5B5A1 *dst, const gl::ColorF *src)
+{
+    dst->RGBA = gl::shiftData<5, 11>(gl::floatToNormalized<5, uint16_t>(src->red)) |
+                gl::shiftData<5, 6>(gl::floatToNormalized<5, uint16_t>(src->green)) |
+                gl::shiftData<5, 1>(gl::floatToNormalized<5, uint16_t>(src->blue)) |
+                gl::shiftData<1, 0>(gl::floatToNormalized<1, uint16_t>(src->alpha));
+}
+
+void R5G5B5A1::average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2)
+{
+    dst->RGBA = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGBA),
+                                                 gl::getShiftedData<5, 11>(src2->RGBA))) |
+                gl::shiftData<5, 6>(gl::average(gl::getShiftedData<5, 6>(src1->RGBA),
+                                                gl::getShiftedData<5, 6>(src2->RGBA))) |
+                gl::shiftData<5, 1>(gl::average(gl::getShiftedData<5, 1>(src1->RGBA),
+                                                gl::getShiftedData<5, 1>(src2->RGBA))) |
+                gl::shiftData<1, 0>(gl::average(gl::getShiftedData<1, 0>(src1->RGBA),
+                                                gl::getShiftedData<1, 0>(src2->RGBA)));
+}
+
+void R4G4B4A4::readColor(gl::ColorF *dst, const R4G4B4A4 *src)
+{
+    dst->red   = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->RGBA));
+    dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->RGBA));
+    dst->blue  = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->RGBA));
+    dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->RGBA));
+}
+
+void R4G4B4A4::writeColor(R4G4B4A4 *dst, const gl::ColorF *src)
+{
+    dst->RGBA = gl::shiftData<4, 12>(gl::floatToNormalized<4, uint16_t>(src->red)) |
+                gl::shiftData<4, 8>(gl::floatToNormalized<4, uint16_t>(src->green)) |
+                gl::shiftData<4, 4>(gl::floatToNormalized<4, uint16_t>(src->blue)) |
+                gl::shiftData<4, 0>(gl::floatToNormalized<4, uint16_t>(src->alpha));
+}
+
+void R4G4B4A4::average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2)
+{
+    dst->RGBA = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->RGBA),
+                                                 gl::getShiftedData<4, 12>(src2->RGBA))) |
+                gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->RGBA),
+                                                gl::getShiftedData<4, 8>(src2->RGBA))) |
+                gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->RGBA),
+                                                gl::getShiftedData<4, 4>(src2->RGBA))) |
+                gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->RGBA),
+                                                gl::getShiftedData<4, 0>(src2->RGBA)));
+}
+
+void A4R4G4B4::readColor(gl::ColorF *dst, const A4R4G4B4 *src)
+{
+    dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->ARGB));
+    dst->red   = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->ARGB));
+    dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->ARGB));
+    dst->blue  = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->ARGB));
+}
+
+void A4R4G4B4::writeColor(A4R4G4B4 *dst, const gl::ColorF *src)
+{
+    dst->ARGB = gl::shiftData<4, 12>(gl::floatToNormalized<4, uint16_t>(src->alpha)) |
+                gl::shiftData<4, 8>(gl::floatToNormalized<4, uint16_t>(src->red)) |
+                gl::shiftData<4, 4>(gl::floatToNormalized<4, uint16_t>(src->green)) |
+                gl::shiftData<4, 0>(gl::floatToNormalized<4, uint16_t>(src->blue));
+}
+
+void A4R4G4B4::average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2)
+{
+    dst->ARGB = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->ARGB),
+                                                 gl::getShiftedData<4, 12>(src2->ARGB))) |
+                gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->ARGB),
+                                                gl::getShiftedData<4, 8>(src2->ARGB))) |
+                gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->ARGB),
+                                                gl::getShiftedData<4, 4>(src2->ARGB))) |
+                gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->ARGB),
+                                                gl::getShiftedData<4, 0>(src2->ARGB)));
+}
+
+void R16::readColor(gl::ColorUI *dst, const R16 *src)
+{
+    dst->red   = src->R;
+    dst->green = 0;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R16::readColor(gl::ColorF *dst, const R16 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R16::writeColor(R16 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint16_t>(src->red);
+}
+
+void R16::writeColor(R16 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint16_t>(src->red);
+}
+
+void R16::average(R16 *dst, const R16 *src1, const R16 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+}
+
+void R16G16::readColor(gl::ColorUI *dst, const R16G16 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R16G16::readColor(gl::ColorF *dst, const R16G16 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R16G16::writeColor(R16G16 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint16_t>(src->red);
+    dst->G = static_cast<uint16_t>(src->green);
+}
+
+void R16G16::writeColor(R16G16 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint16_t>(src->red);
+    dst->G = gl::floatToNormalized<uint16_t>(src->green);
+}
+
+void R16G16::average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+}
+
+void R16G16B16::readColor(gl::ColorUI *dst, const R16G16B16 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = 1;
+}
+
+void R16G16B16::readColor(gl::ColorF *dst, const R16G16B16 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = 1.0f;
+}
+
+void R16G16B16::writeColor(R16G16B16 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint16_t>(src->red);
+    dst->G = static_cast<uint16_t>(src->green);
+    dst->B = static_cast<uint16_t>(src->blue);
+}
+
+void R16G16B16::writeColor(R16G16B16 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint16_t>(src->red);
+    dst->G = gl::floatToNormalized<uint16_t>(src->green);
+    dst->B = gl::floatToNormalized<uint16_t>(src->blue);
+}
+
+void R16G16B16::average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+}
+
+void R16G16B16A16::readColor(gl::ColorUI *dst, const R16G16B16A16 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void R16G16B16A16::readColor(gl::ColorF *dst, const R16G16B16A16 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R16G16B16A16::writeColor(R16G16B16A16 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint16_t>(src->red);
+    dst->G = static_cast<uint16_t>(src->green);
+    dst->B = static_cast<uint16_t>(src->blue);
+    dst->A = static_cast<uint16_t>(src->alpha);
+}
+
+void R16G16B16A16::writeColor(R16G16B16A16 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint16_t>(src->red);
+    dst->G = gl::floatToNormalized<uint16_t>(src->green);
+    dst->B = gl::floatToNormalized<uint16_t>(src->blue);
+    dst->A = gl::floatToNormalized<uint16_t>(src->alpha);
+}
+
+void R16G16B16A16::average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32::readColor(gl::ColorUI *dst, const R32 *src)
+{
+    dst->red   = src->R;
+    dst->green = 0;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R32::readColor(gl::ColorF *dst, const R32 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R32::writeColor(R32 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint32_t>(src->red);
+}
+
+void R32::writeColor(R32 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint32_t>(src->red);
+}
+
+void R32::average(R32 *dst, const R32 *src1, const R32 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+}
+
+void R32G32::readColor(gl::ColorUI *dst, const R32G32 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R32G32::readColor(gl::ColorF *dst, const R32G32 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R32G32::writeColor(R32G32 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint32_t>(src->red);
+    dst->G = static_cast<uint32_t>(src->green);
+}
+
+void R32G32::writeColor(R32G32 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint32_t>(src->red);
+    dst->G = gl::floatToNormalized<uint32_t>(src->green);
+}
+
+void R32G32::average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+}
+
+void R32G32B32::readColor(gl::ColorUI *dst, const R32G32B32 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = 1;
+}
+
+void R32G32B32::readColor(gl::ColorF *dst, const R32G32B32 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = 1.0f;
+}
+
+void R32G32B32::writeColor(R32G32B32 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint32_t>(src->red);
+    dst->G = static_cast<uint32_t>(src->green);
+    dst->B = static_cast<uint32_t>(src->blue);
+}
+
+void R32G32B32::writeColor(R32G32B32 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint32_t>(src->red);
+    dst->G = gl::floatToNormalized<uint32_t>(src->green);
+    dst->B = gl::floatToNormalized<uint32_t>(src->blue);
+}
+
+void R32G32B32::average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+}
+
+void R32G32B32A32::readColor(gl::ColorUI *dst, const R32G32B32A32 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void R32G32B32A32::readColor(gl::ColorF *dst, const R32G32B32A32 *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R32G32B32A32::writeColor(R32G32B32A32 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint32_t>(src->red);
+    dst->G = static_cast<uint32_t>(src->green);
+    dst->B = static_cast<uint32_t>(src->blue);
+    dst->A = static_cast<uint32_t>(src->alpha);
+}
+
+void R32G32B32A32::writeColor(R32G32B32A32 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<uint32_t>(src->red);
+    dst->G = gl::floatToNormalized<uint32_t>(src->green);
+    dst->B = gl::floatToNormalized<uint32_t>(src->blue);
+    dst->A = gl::floatToNormalized<uint32_t>(src->alpha);
+}
+
+void R32G32B32A32::average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void R8S::readColor(gl::ColorI *dst, const R8S *src)
+{
+    dst->red   = src->R;
+    dst->green = 0;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R8S::readColor(gl::ColorF *dst, const R8S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R8S::writeColor(R8S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int8_t>(src->red);
+}
+
+void R8S::writeColor(R8S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int8_t>(src->red);
+}
+
+void R8S::average(R8S *dst, const R8S *src1, const R8S *src2)
+{
+    dst->R = static_cast<int8_t>(gl::average(src1->R, src2->R));
+}
+
+void R8G8S::readColor(gl::ColorI *dst, const R8G8S *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R8G8S::readColor(gl::ColorF *dst, const R8G8S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R8G8S::writeColor(R8G8S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int8_t>(src->red);
+    dst->G = static_cast<int8_t>(src->green);
+}
+
+void R8G8S::writeColor(R8G8S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int8_t>(src->red);
+    dst->G = gl::floatToNormalized<int8_t>(src->green);
+}
+
+void R8G8S::average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2)
+{
+    dst->R = static_cast<int8_t>(gl::average(src1->R, src2->R));
+    dst->G = static_cast<int8_t>(gl::average(src1->G, src2->G));
+}
+
+void R8G8B8S::readColor(gl::ColorI *dst, const R8G8B8S *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = 1;
+}
+
+void R8G8B8S::readColor(gl::ColorF *dst, const R8G8B8S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = 1.0f;
+}
+
+void R8G8B8S::writeColor(R8G8B8S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int8_t>(src->red);
+    dst->G = static_cast<int8_t>(src->green);
+    dst->B = static_cast<int8_t>(src->blue);
+}
+
+void R8G8B8S::writeColor(R8G8B8S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int8_t>(src->red);
+    dst->G = gl::floatToNormalized<int8_t>(src->green);
+    dst->B = gl::floatToNormalized<int8_t>(src->blue);
+}
+
+void R8G8B8S::average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2)
+{
+    dst->R = static_cast<int8_t>(gl::average(src1->R, src2->R));
+    dst->G = static_cast<int8_t>(gl::average(src1->G, src2->G));
+    dst->B = static_cast<int8_t>(gl::average(src1->B, src2->B));
+}
+
+void R8G8B8A8S::readColor(gl::ColorI *dst, const R8G8B8A8S *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void R8G8B8A8S::readColor(gl::ColorF *dst, const R8G8B8A8S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R8G8B8A8S::writeColor(R8G8B8A8S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int8_t>(src->red);
+    dst->G = static_cast<int8_t>(src->green);
+    dst->B = static_cast<int8_t>(src->blue);
+    dst->A = static_cast<int8_t>(src->alpha);
+}
+
+void R8G8B8A8S::writeColor(R8G8B8A8S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int8_t>(src->red);
+    dst->G = gl::floatToNormalized<int8_t>(src->green);
+    dst->B = gl::floatToNormalized<int8_t>(src->blue);
+    dst->A = gl::floatToNormalized<int8_t>(src->alpha);
+}
+
+void R8G8B8A8S::average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2)
+{
+    dst->R = static_cast<int8_t>(gl::average(src1->R, src2->R));
+    dst->G = static_cast<int8_t>(gl::average(src1->G, src2->G));
+    dst->B = static_cast<int8_t>(gl::average(src1->B, src2->B));
+    dst->A = static_cast<int8_t>(gl::average(src1->A, src2->A));
+}
+
+void R16S::readColor(gl::ColorI *dst, const R16S *src)
+{
+    dst->red   = src->R;
+    dst->green = 0;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R16S::readColor(gl::ColorF *dst, const R16S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R16S::writeColor(R16S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int16_t>(src->red);
+}
+
+void R16S::writeColor(R16S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int16_t>(src->red);
+}
+
+void R16S::average(R16S *dst, const R16S *src1, const R16S *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+}
+
+void R16G16S::readColor(gl::ColorI *dst, const R16G16S *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R16G16S::readColor(gl::ColorF *dst, const R16G16S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R16G16S::writeColor(R16G16S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int16_t>(src->red);
+    dst->G = static_cast<int16_t>(src->green);
+}
+
+void R16G16S::writeColor(R16G16S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int16_t>(src->red);
+    dst->G = gl::floatToNormalized<int16_t>(src->green);
+}
+
+void R16G16S::average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+}
+
+void R16G16B16S::readColor(gl::ColorI *dst, const R16G16B16S *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = 1;
+}
+
+void R16G16B16S::readColor(gl::ColorF *dst, const R16G16B16S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = 1.0f;
+}
+
+void R16G16B16S::writeColor(R16G16B16S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int16_t>(src->red);
+    dst->G = static_cast<int16_t>(src->green);
+    dst->B = static_cast<int16_t>(src->blue);
+}
+
+void R16G16B16S::writeColor(R16G16B16S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int16_t>(src->red);
+    dst->G = gl::floatToNormalized<int16_t>(src->green);
+    dst->B = gl::floatToNormalized<int16_t>(src->blue);
+}
+
+void R16G16B16S::average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+}
+
+void R16G16B16A16S::readColor(gl::ColorI *dst, const R16G16B16A16S *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void R16G16B16A16S::readColor(gl::ColorF *dst, const R16G16B16A16S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R16G16B16A16S::writeColor(R16G16B16A16S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int16_t>(src->red);
+    dst->G = static_cast<int16_t>(src->green);
+    dst->B = static_cast<int16_t>(src->blue);
+    dst->A = static_cast<int16_t>(src->alpha);
+}
+
+void R16G16B16A16S::writeColor(R16G16B16A16S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int16_t>(src->red);
+    dst->G = gl::floatToNormalized<int16_t>(src->green);
+    dst->B = gl::floatToNormalized<int16_t>(src->blue);
+    dst->A = gl::floatToNormalized<int16_t>(src->alpha);
+}
+
+void R16G16B16A16S::average(R16G16B16A16S *dst,
+                            const R16G16B16A16S *src1,
+                            const R16G16B16A16S *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32S::readColor(gl::ColorI *dst, const R32S *src)
+{
+    dst->red   = src->R;
+    dst->green = 0;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R32S::readColor(gl::ColorF *dst, const R32S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R32S::writeColor(R32S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int32_t>(src->red);
+}
+
+void R32S::writeColor(R32S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int32_t>(src->red);
+}
+
+void R32S::average(R32S *dst, const R32S *src1, const R32S *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+}
+
+void R32G32S::readColor(gl::ColorI *dst, const R32G32S *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = 0;
+    dst->alpha = 1;
+}
+
+void R32G32S::readColor(gl::ColorF *dst, const R32G32S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R32G32S::writeColor(R32G32S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int32_t>(src->red);
+    dst->G = static_cast<int32_t>(src->green);
+}
+
+void R32G32S::writeColor(R32G32S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int32_t>(src->red);
+    dst->G = gl::floatToNormalized<int32_t>(src->green);
+}
+
+void R32G32S::average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+}
+
+void R32G32B32S::readColor(gl::ColorI *dst, const R32G32B32S *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = 1;
+}
+
+void R32G32B32S::readColor(gl::ColorF *dst, const R32G32B32S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = 1.0f;
+}
+
+void R32G32B32S::writeColor(R32G32B32S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int32_t>(src->red);
+    dst->G = static_cast<int32_t>(src->green);
+    dst->B = static_cast<int32_t>(src->blue);
+}
+
+void R32G32B32S::writeColor(R32G32B32S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int32_t>(src->red);
+    dst->G = gl::floatToNormalized<int32_t>(src->green);
+    dst->B = gl::floatToNormalized<int32_t>(src->blue);
+}
+
+void R32G32B32S::average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+}
+
+void R32G32B32A32S::readColor(gl::ColorI *dst, const R32G32B32A32S *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void R32G32B32A32S::readColor(gl::ColorF *dst, const R32G32B32A32S *src)
+{
+    dst->red   = gl::normalizedToFloat(src->R);
+    dst->green = gl::normalizedToFloat(src->G);
+    dst->blue  = gl::normalizedToFloat(src->B);
+    dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R32G32B32A32S::writeColor(R32G32B32A32S *dst, const gl::ColorI *src)
+{
+    dst->R = static_cast<int32_t>(src->red);
+    dst->G = static_cast<int32_t>(src->green);
+    dst->B = static_cast<int32_t>(src->blue);
+    dst->A = static_cast<int32_t>(src->alpha);
+}
+
+void R32G32B32A32S::writeColor(R32G32B32A32S *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<int32_t>(src->red);
+    dst->G = gl::floatToNormalized<int32_t>(src->green);
+    dst->B = gl::floatToNormalized<int32_t>(src->blue);
+    dst->A = gl::floatToNormalized<int32_t>(src->alpha);
+}
+
+void R32G32B32A32S::average(R32G32B32A32S *dst,
+                            const R32G32B32A32S *src1,
+                            const R32G32B32A32S *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void A16B16G16R16F::readColor(gl::ColorF *dst, const A16B16G16R16F *src)
+{
+    dst->red   = gl::float16ToFloat32(src->R);
+    dst->green = gl::float16ToFloat32(src->G);
+    dst->blue  = gl::float16ToFloat32(src->B);
+    dst->alpha = gl::float16ToFloat32(src->A);
+}
+
+void A16B16G16R16F::writeColor(A16B16G16R16F *dst, const gl::ColorF *src)
+{
+    dst->R = gl::float32ToFloat16(src->red);
+    dst->G = gl::float32ToFloat16(src->green);
+    dst->B = gl::float32ToFloat16(src->blue);
+    dst->A = gl::float32ToFloat16(src->alpha);
+}
+
+void A16B16G16R16F::average(A16B16G16R16F *dst,
+                            const A16B16G16R16F *src1,
+                            const A16B16G16R16F *src2)
+{
+    dst->R = gl::averageHalfFloat(src1->R, src2->R);
+    dst->G = gl::averageHalfFloat(src1->G, src2->G);
+    dst->B = gl::averageHalfFloat(src1->B, src2->B);
+    dst->A = gl::averageHalfFloat(src1->A, src2->A);
+}
+
+void R16G16B16A16F::readColor(gl::ColorF *dst, const R16G16B16A16F *src)
+{
+    dst->red   = gl::float16ToFloat32(src->R);
+    dst->green = gl::float16ToFloat32(src->G);
+    dst->blue  = gl::float16ToFloat32(src->B);
+    dst->alpha = gl::float16ToFloat32(src->A);
+}
+
+void R16G16B16A16F::writeColor(R16G16B16A16F *dst, const gl::ColorF *src)
+{
+    dst->R = gl::float32ToFloat16(src->red);
+    dst->G = gl::float32ToFloat16(src->green);
+    dst->B = gl::float32ToFloat16(src->blue);
+    dst->A = gl::float32ToFloat16(src->alpha);
+}
+
+void R16G16B16A16F::average(R16G16B16A16F *dst,
+                            const R16G16B16A16F *src1,
+                            const R16G16B16A16F *src2)
+{
+    dst->R = gl::averageHalfFloat(src1->R, src2->R);
+    dst->G = gl::averageHalfFloat(src1->G, src2->G);
+    dst->B = gl::averageHalfFloat(src1->B, src2->B);
+    dst->A = gl::averageHalfFloat(src1->A, src2->A);
+}
+
+void R16F::readColor(gl::ColorF *dst, const R16F *src)
+{
+    dst->red   = gl::float16ToFloat32(src->R);
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R16F::writeColor(R16F *dst, const gl::ColorF *src)
+{
+    dst->R = gl::float32ToFloat16(src->red);
+}
+
+void R16F::average(R16F *dst, const R16F *src1, const R16F *src2)
+{
+    dst->R = gl::averageHalfFloat(src1->R, src2->R);
+}
+
+void A16F::readColor(gl::ColorF *dst, const A16F *src)
+{
+    dst->red   = 0.0f;
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = gl::float16ToFloat32(src->A);
+}
+
+void A16F::writeColor(A16F *dst, const gl::ColorF *src)
+{
+    dst->A = gl::float32ToFloat16(src->alpha);
+}
+
+void A16F::average(A16F *dst, const A16F *src1, const A16F *src2)
+{
+    dst->A = gl::averageHalfFloat(src1->A, src2->A);
+}
+
+void L16F::readColor(gl::ColorF *dst, const L16F *src)
+{
+    float lum  = gl::float16ToFloat32(src->L);
+    dst->red   = lum;
+    dst->green = lum;
+    dst->blue  = lum;
+    dst->alpha = 1.0f;
+}
+
+void L16F::writeColor(L16F *dst, const gl::ColorF *src)
+{
+    dst->L = gl::float32ToFloat16(src->red);
+}
+
+void L16F::average(L16F *dst, const L16F *src1, const L16F *src2)
+{
+    dst->L = gl::averageHalfFloat(src1->L, src2->L);
+}
+
+void L16A16F::readColor(gl::ColorF *dst, const L16A16F *src)
+{
+    float lum  = gl::float16ToFloat32(src->L);
+    dst->red   = lum;
+    dst->green = lum;
+    dst->blue  = lum;
+    dst->alpha = gl::float16ToFloat32(src->A);
+}
+
+void L16A16F::writeColor(L16A16F *dst, const gl::ColorF *src)
+{
+    dst->L = gl::float32ToFloat16(src->red);
+    dst->A = gl::float32ToFloat16(src->alpha);
+}
+
+void L16A16F::average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2)
+{
+    dst->L = gl::averageHalfFloat(src1->L, src2->L);
+    dst->A = gl::averageHalfFloat(src1->A, src2->A);
+}
+
+void R16G16F::readColor(gl::ColorF *dst, const R16G16F *src)
+{
+    dst->red   = gl::float16ToFloat32(src->R);
+    dst->green = gl::float16ToFloat32(src->G);
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R16G16F::writeColor(R16G16F *dst, const gl::ColorF *src)
+{
+    dst->R = gl::float32ToFloat16(src->red);
+    dst->G = gl::float32ToFloat16(src->green);
+}
+
+void R16G16F::average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2)
+{
+    dst->R = gl::averageHalfFloat(src1->R, src2->R);
+    dst->G = gl::averageHalfFloat(src1->G, src2->G);
+}
+
+void R16G16B16F::readColor(gl::ColorF *dst, const R16G16B16F *src)
+{
+    dst->red   = gl::float16ToFloat32(src->R);
+    dst->green = gl::float16ToFloat32(src->G);
+    dst->blue  = gl::float16ToFloat32(src->B);
+    dst->alpha = 1.0f;
+}
+
+void R16G16B16F::writeColor(R16G16B16F *dst, const gl::ColorF *src)
+{
+    dst->R = gl::float32ToFloat16(src->red);
+    dst->G = gl::float32ToFloat16(src->green);
+    dst->B = gl::float32ToFloat16(src->blue);
+}
+
+void R16G16B16F::average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2)
+{
+    dst->R = gl::averageHalfFloat(src1->R, src2->R);
+    dst->G = gl::averageHalfFloat(src1->G, src2->G);
+    dst->B = gl::averageHalfFloat(src1->B, src2->B);
+}
+
+void A32B32G32R32F::readColor(gl::ColorF *dst, const A32B32G32R32F *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void A32B32G32R32F::writeColor(A32B32G32R32F *dst, const gl::ColorF *src)
+{
+    dst->R = src->red;
+    dst->G = src->green;
+    dst->B = src->blue;
+    dst->A = src->alpha;
+}
+
+void A32B32G32R32F::average(A32B32G32R32F *dst,
+                            const A32B32G32R32F *src1,
+                            const A32B32G32R32F *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32G32B32A32F::readColor(gl::ColorF *dst, const R32G32B32A32F *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void R32G32B32A32F::writeColor(R32G32B32A32F *dst, const gl::ColorF *src)
+{
+    dst->R = src->red;
+    dst->G = src->green;
+    dst->B = src->blue;
+    dst->A = src->alpha;
+}
+
+void R32G32B32A32F::average(R32G32B32A32F *dst,
+                            const R32G32B32A32F *src1,
+                            const R32G32B32A32F *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32F::readColor(gl::ColorF *dst, const R32F *src)
+{
+    dst->red   = src->R;
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R32F::writeColor(R32F *dst, const gl::ColorF *src)
+{
+    dst->R = src->red;
+}
+
+void R32F::average(R32F *dst, const R32F *src1, const R32F *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+}
+
+void A32F::readColor(gl::ColorF *dst, const A32F *src)
+{
+    dst->red   = 0.0f;
+    dst->green = 0.0f;
+    dst->blue  = 0.0f;
+    dst->alpha = src->A;
+}
+
+void A32F::writeColor(A32F *dst, const gl::ColorF *src)
+{
+    dst->A = src->alpha;
+}
+
+void A32F::average(A32F *dst, const A32F *src1, const A32F *src2)
+{
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void L32F::readColor(gl::ColorF *dst, const L32F *src)
+{
+    dst->red   = src->L;
+    dst->green = src->L;
+    dst->blue  = src->L;
+    dst->alpha = 1.0f;
+}
+
+void L32F::writeColor(L32F *dst, const gl::ColorF *src)
+{
+    dst->L = src->red;
+}
+
+void L32F::average(L32F *dst, const L32F *src1, const L32F *src2)
+{
+    dst->L = gl::average(src1->L, src2->L);
+}
+
+void L32A32F::readColor(gl::ColorF *dst, const L32A32F *src)
+{
+    dst->red   = src->L;
+    dst->green = src->L;
+    dst->blue  = src->L;
+    dst->alpha = src->A;
+}
+
+void L32A32F::writeColor(L32A32F *dst, const gl::ColorF *src)
+{
+    dst->L = src->red;
+    dst->A = src->alpha;
+}
+
+void L32A32F::average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2)
+{
+    dst->L = gl::average(src1->L, src2->L);
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32G32F::readColor(gl::ColorF *dst, const R32G32F *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = 0.0f;
+    dst->alpha = 1.0f;
+}
+
+void R32G32F::writeColor(R32G32F *dst, const gl::ColorF *src)
+{
+    dst->R = src->red;
+    dst->G = src->green;
+}
+
+void R32G32F::average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+}
+
+void R32G32B32F::readColor(gl::ColorF *dst, const R32G32B32F *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = 1.0f;
+}
+
+void R32G32B32F::writeColor(R32G32B32F *dst, const gl::ColorF *src)
+{
+    dst->R = src->red;
+    dst->G = src->green;
+    dst->B = src->blue;
+}
+
+void R32G32B32F::average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+}
+
+void R10G10B10A2::readColor(gl::ColorUI *dst, const R10G10B10A2 *src)
+{
+    dst->red   = src->R;
+    dst->green = src->G;
+    dst->blue  = src->B;
+    dst->alpha = src->A;
+}
+
+void R10G10B10A2::readColor(gl::ColorF *dst, const R10G10B10A2 *src)
+{
+    dst->red   = gl::normalizedToFloat<10>(src->R);
+    dst->green = gl::normalizedToFloat<10>(src->G);
+    dst->blue  = gl::normalizedToFloat<10>(src->B);
+    dst->alpha = gl::normalizedToFloat<2>(src->A);
+}
+
+void R10G10B10A2::writeColor(R10G10B10A2 *dst, const gl::ColorUI *src)
+{
+    dst->R = static_cast<uint32_t>(src->red);
+    dst->G = static_cast<uint32_t>(src->green);
+    dst->B = static_cast<uint32_t>(src->blue);
+    dst->A = static_cast<uint32_t>(src->alpha);
+}
+
+void R10G10B10A2::writeColor(R10G10B10A2 *dst, const gl::ColorF *src)
+{
+    dst->R = gl::floatToNormalized<10, uint32_t>(src->red);
+    dst->G = gl::floatToNormalized<10, uint32_t>(src->green);
+    dst->B = gl::floatToNormalized<10, uint32_t>(src->blue);
+    dst->A = gl::floatToNormalized<2, uint32_t>(src->alpha);
+}
+
+void R10G10B10A2::average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2)
+{
+    dst->R = gl::average(src1->R, src2->R);
+    dst->G = gl::average(src1->G, src2->G);
+    dst->B = gl::average(src1->B, src2->B);
+    dst->A = gl::average(src1->A, src2->A);
+}
+
+void R9G9B9E5::readColor(gl::ColorF *dst, const R9G9B9E5 *src)
+{
+    gl::convert999E5toRGBFloats(gl::bitCast<uint32_t>(*src), &dst->red, &dst->green, &dst->blue);
+    dst->alpha = 1.0f;
+}
+
+void R9G9B9E5::writeColor(R9G9B9E5 *dst, const gl::ColorF *src)
+{
+    *reinterpret_cast<uint32_t *>(dst) =
+        gl::convertRGBFloatsTo999E5(src->red, src->green, src->blue);
+}
+
+void R9G9B9E5::average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2)
+{
+    float r1, g1, b1;
+    gl::convert999E5toRGBFloats(*reinterpret_cast<const uint32_t *>(src1), &r1, &g1, &b1);
+
+    float r2, g2, b2;
+    gl::convert999E5toRGBFloats(*reinterpret_cast<const uint32_t *>(src2), &r2, &g2, &b2);
+
+    *reinterpret_cast<uint32_t *>(dst) =
+        gl::convertRGBFloatsTo999E5(gl::average(r1, r2), gl::average(g1, g2), gl::average(b1, b2));
+}
+
+void R11G11B10F::readColor(gl::ColorF *dst, const R11G11B10F *src)
+{
+    dst->red   = gl::float11ToFloat32(src->R);
+    dst->green = gl::float11ToFloat32(src->G);
+    dst->blue  = gl::float10ToFloat32(src->B);
+    dst->alpha = 1.0f;
+}
+
+void R11G11B10F::writeColor(R11G11B10F *dst, const gl::ColorF *src)
+{
+    dst->R = gl::float32ToFloat11(src->red);
+    dst->G = gl::float32ToFloat11(src->green);
+    dst->B = gl::float32ToFloat10(src->blue);
+}
+
+void R11G11B10F::average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2)
+{
+    dst->R = gl::averageFloat11(src1->R, src2->R);
+    dst->G = gl::averageFloat11(src1->G, src2->G);
+    dst->B = gl::averageFloat10(src1->B, src2->B);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/image_util/imageformats.h b/src/third_party/angle/src/image_util/imageformats.h
new file mode 100644
index 0000000..84ae631
--- /dev/null
+++ b/src/third_party/angle/src/image_util/imageformats.h
@@ -0,0 +1,699 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// imageformats.h: Defines image format types with functions for mip generation
+// and copying.
+
+#ifndef IMAGEUTIL_IMAGEFORMATS_H_
+#define IMAGEUTIL_IMAGEFORMATS_H_
+
+#include "common/Color.h"
+
+#include <cstdint>
+
+namespace angle
+{
+
+// Several structures share functionality for reading, writing or mipmapping but the layout
+// must match the texture format which the structure represents. If collapsing or typedefing
+// structs in this header, make sure the functionality and memory layout is exactly the same.
+
+struct L8
+{
+    uint8_t L;
+
+    static void readColor(gl::ColorF *dst, const L8 *src);
+    static void writeColor(L8 *dst, const gl::ColorF *src);
+    static void average(L8 *dst, const L8 *src1, const L8 *src2);
+};
+
+struct R8
+{
+    uint8_t R;
+
+    static void readColor(gl::ColorF *dst, const R8 *src);
+    static void readColor(gl::ColorUI *dst, const R8 *src);
+    static void writeColor(R8 *dst, const gl::ColorF *src);
+    static void writeColor(R8 *dst, const gl::ColorUI *src);
+    static void average(R8 *dst, const R8 *src1, const R8 *src2);
+};
+
+struct A8
+{
+    uint8_t A;
+
+    static void readColor(gl::ColorF *dst, const A8 *src);
+    static void writeColor(A8 *dst, const gl::ColorF *src);
+    static void average(A8 *dst, const A8 *src1, const A8 *src2);
+};
+
+struct L8A8
+{
+    uint8_t L;
+    uint8_t A;
+
+    static void readColor(gl::ColorF *dst, const L8A8 *src);
+    static void writeColor(L8A8 *dst, const gl::ColorF *src);
+    static void average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2);
+};
+
+struct A8L8
+{
+    uint8_t A;
+    uint8_t L;
+
+    static void readColor(gl::ColorF *dst, const A8L8 *src);
+    static void writeColor(A8L8 *dst, const gl::ColorF *src);
+    static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2);
+};
+
+struct R8G8
+{
+    uint8_t R;
+    uint8_t G;
+
+    static void readColor(gl::ColorF *dst, const R8G8 *src);
+    static void readColor(gl::ColorUI *dst, const R8G8 *src);
+    static void writeColor(R8G8 *dst, const gl::ColorF *src);
+    static void writeColor(R8G8 *dst, const gl::ColorUI *src);
+    static void average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2);
+};
+
+struct R8G8B8
+{
+    uint8_t R;
+    uint8_t G;
+    uint8_t B;
+
+    static void readColor(gl::ColorF *dst, const R8G8B8 *src);
+    static void readColor(gl::ColorUI *dst, const R8G8B8 *src);
+    static void writeColor(R8G8B8 *dst, const gl::ColorF *src);
+    static void writeColor(R8G8B8 *dst, const gl::ColorUI *src);
+    static void average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2);
+};
+
+struct B8G8R8
+{
+    uint8_t B;
+    uint8_t G;
+    uint8_t R;
+
+    static void readColor(gl::ColorF *dst, const B8G8R8 *src);
+    static void readColor(gl::ColorUI *dst, const B8G8R8 *src);
+    static void writeColor(B8G8R8 *dst, const gl::ColorF *src);
+    static void writeColor(B8G8R8 *dst, const gl::ColorUI *src);
+    static void average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2);
+};
+
+struct R5G6B5
+{
+    // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the
+    // most significant bits of the bitfield, and successive component occupying progressively less
+    // significant locations"
+    uint16_t RGB;
+
+    static void readColor(gl::ColorF *dst, const R5G6B5 *src);
+    static void writeColor(R5G6B5 *dst, const gl::ColorF *src);
+    static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2);
+};
+
+struct B5G6R5
+{
+    uint16_t BGR;
+
+    static void readColor(gl::ColorF *dst, const B5G6R5 *src);
+    static void writeColor(B5G6R5 *dst, const gl::ColorF *src);
+    static void average(B5G6R5 *dst, const B5G6R5 *src1, const B5G6R5 *src2);
+};
+
+struct A8R8G8B8
+{
+    uint8_t A;
+    uint8_t R;
+    uint8_t G;
+    uint8_t B;
+
+    static void readColor(gl::ColorF *dst, const A8R8G8B8 *src);
+    static void readColor(gl::ColorUI *dst, const A8R8G8B8 *src);
+    static void writeColor(A8R8G8B8 *dst, const gl::ColorF *src);
+    static void writeColor(A8R8G8B8 *dst, const gl::ColorUI *src);
+    static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2);
+};
+
+struct R8G8B8A8
+{
+    uint8_t R;
+    uint8_t G;
+    uint8_t B;
+    uint8_t A;
+
+    static void readColor(gl::ColorF *dst, const R8G8B8A8 *src);
+    static void readColor(gl::ColorUI *dst, const R8G8B8A8 *src);
+    static void writeColor(R8G8B8A8 *dst, const gl::ColorF *src);
+    static void writeColor(R8G8B8A8 *dst, const gl::ColorUI *src);
+    static void average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2);
+};
+
+struct R8G8B8A8SRGB
+{
+    uint8_t R;
+    uint8_t G;
+    uint8_t B;
+    uint8_t A;
+
+    static void readColor(gl::ColorF *dst, const R8G8B8A8SRGB *src);
+    static void average(R8G8B8A8SRGB *dst, const R8G8B8A8SRGB *src1, const R8G8B8A8SRGB *src2);
+};
+
+struct B8G8R8A8
+{
+    uint8_t B;
+    uint8_t G;
+    uint8_t R;
+    uint8_t A;
+
+    static void readColor(gl::ColorF *dst, const B8G8R8A8 *src);
+    static void readColor(gl::ColorUI *dst, const B8G8R8A8 *src);
+    static void writeColor(B8G8R8A8 *dst, const gl::ColorF *src);
+    static void writeColor(B8G8R8A8 *dst, const gl::ColorUI *src);
+    static void average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2);
+};
+
+struct B8G8R8X8
+{
+    uint8_t B;
+    uint8_t G;
+    uint8_t R;
+    uint8_t X;
+
+    static void readColor(gl::ColorF *dst, const B8G8R8X8 *src);
+    static void readColor(gl::ColorUI *dst, const B8G8R8X8 *src);
+    static void writeColor(B8G8R8X8 *dst, const gl::ColorF *src);
+    static void writeColor(B8G8R8X8 *dst, const gl::ColorUI *src);
+    static void average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2);
+};
+
+struct A1R5G5B5
+{
+    uint16_t ARGB;
+
+    static void readColor(gl::ColorF *dst, const A1R5G5B5 *src);
+    static void writeColor(A1R5G5B5 *dst, const gl::ColorF *src);
+    static void average(A1R5G5B5 *dst, const A1R5G5B5 *src1, const A1R5G5B5 *src2);
+};
+
+struct R5G5B5A1
+{
+    // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the
+    // most significant
+    // bits of the bitfield, and successive component occupying progressively less significant
+    // locations"
+    uint16_t RGBA;
+
+    static void readColor(gl::ColorF *dst, const R5G5B5A1 *src);
+    static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src);
+    static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2);
+};
+
+struct R4G4B4A4
+{
+    // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the
+    // most significant
+    // bits of the bitfield, and successive component occupying progressively less significant
+    // locations"
+    uint16_t RGBA;
+
+    static void readColor(gl::ColorF *dst, const R4G4B4A4 *src);
+    static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src);
+    static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2);
+};
+
+struct A4R4G4B4
+{
+    uint16_t ARGB;
+
+    static void readColor(gl::ColorF *dst, const A4R4G4B4 *src);
+    static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src);
+    static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2);
+};
+
+struct R16
+{
+    uint16_t R;
+
+    static void readColor(gl::ColorF *dst, const R16 *src);
+    static void readColor(gl::ColorUI *dst, const R16 *src);
+    static void writeColor(R16 *dst, const gl::ColorF *src);
+    static void writeColor(R16 *dst, const gl::ColorUI *src);
+    static void average(R16 *dst, const R16 *src1, const R16 *src2);
+};
+
+struct R16G16
+{
+    uint16_t R;
+    uint16_t G;
+
+    static void readColor(gl::ColorF *dst, const R16G16 *src);
+    static void readColor(gl::ColorUI *dst, const R16G16 *src);
+    static void writeColor(R16G16 *dst, const gl::ColorF *src);
+    static void writeColor(R16G16 *dst, const gl::ColorUI *src);
+    static void average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2);
+};
+
+struct R16G16B16
+{
+    uint16_t R;
+    uint16_t G;
+    uint16_t B;
+
+    static void readColor(gl::ColorF *dst, const R16G16B16 *src);
+    static void readColor(gl::ColorUI *dst, const R16G16B16 *src);
+    static void writeColor(R16G16B16 *dst, const gl::ColorF *src);
+    static void writeColor(R16G16B16 *dst, const gl::ColorUI *src);
+    static void average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2);
+};
+
+struct R16G16B16A16
+{
+    uint16_t R;
+    uint16_t G;
+    uint16_t B;
+    uint16_t A;
+
+    static void readColor(gl::ColorF *dst, const R16G16B16A16 *src);
+    static void readColor(gl::ColorUI *dst, const R16G16B16A16 *src);
+    static void writeColor(R16G16B16A16 *dst, const gl::ColorF *src);
+    static void writeColor(R16G16B16A16 *dst, const gl::ColorUI *src);
+    static void average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2);
+};
+
+struct R32
+{
+    uint32_t R;
+
+    static void readColor(gl::ColorF *dst, const R32 *src);
+    static void readColor(gl::ColorUI *dst, const R32 *src);
+    static void writeColor(R32 *dst, const gl::ColorF *src);
+    static void writeColor(R32 *dst, const gl::ColorUI *src);
+    static void average(R32 *dst, const R32 *src1, const R32 *src2);
+};
+
+struct R32G32
+{
+    uint32_t R;
+    uint32_t G;
+
+    static void readColor(gl::ColorF *dst, const R32G32 *src);
+    static void readColor(gl::ColorUI *dst, const R32G32 *src);
+    static void writeColor(R32G32 *dst, const gl::ColorF *src);
+    static void writeColor(R32G32 *dst, const gl::ColorUI *src);
+    static void average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2);
+};
+
+struct R32G32B32
+{
+    uint32_t R;
+    uint32_t G;
+    uint32_t B;
+
+    static void readColor(gl::ColorF *dst, const R32G32B32 *src);
+    static void readColor(gl::ColorUI *dst, const R32G32B32 *src);
+    static void writeColor(R32G32B32 *dst, const gl::ColorF *src);
+    static void writeColor(R32G32B32 *dst, const gl::ColorUI *src);
+    static void average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2);
+};
+
+struct R32G32B32A32
+{
+    uint32_t R;
+    uint32_t G;
+    uint32_t B;
+    uint32_t A;
+
+    static void readColor(gl::ColorF *dst, const R32G32B32A32 *src);
+    static void readColor(gl::ColorUI *dst, const R32G32B32A32 *src);
+    static void writeColor(R32G32B32A32 *dst, const gl::ColorF *src);
+    static void writeColor(R32G32B32A32 *dst, const gl::ColorUI *src);
+    static void average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2);
+};
+
+struct R8S
+{
+    int8_t R;
+
+    static void readColor(gl::ColorF *dst, const R8S *src);
+    static void readColor(gl::ColorI *dst, const R8S *src);
+    static void writeColor(R8S *dst, const gl::ColorF *src);
+    static void writeColor(R8S *dst, const gl::ColorI *src);
+    static void average(R8S *dst, const R8S *src1, const R8S *src2);
+};
+
+struct R8G8S
+{
+    int8_t R;
+    int8_t G;
+
+    static void readColor(gl::ColorF *dst, const R8G8S *src);
+    static void readColor(gl::ColorI *dst, const R8G8S *src);
+    static void writeColor(R8G8S *dst, const gl::ColorF *src);
+    static void writeColor(R8G8S *dst, const gl::ColorI *src);
+    static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2);
+};
+
+struct R8G8B8S
+{
+    int8_t R;
+    int8_t G;
+    int8_t B;
+
+    static void readColor(gl::ColorF *dst, const R8G8B8S *src);
+    static void readColor(gl::ColorI *dst, const R8G8B8S *src);
+    static void writeColor(R8G8B8S *dst, const gl::ColorF *src);
+    static void writeColor(R8G8B8S *dst, const gl::ColorI *src);
+    static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2);
+};
+
+struct R8G8B8A8S
+{
+    int8_t R;
+    int8_t G;
+    int8_t B;
+    int8_t A;
+
+    static void readColor(gl::ColorF *dst, const R8G8B8A8S *src);
+    static void readColor(gl::ColorI *dst, const R8G8B8A8S *src);
+    static void writeColor(R8G8B8A8S *dst, const gl::ColorF *src);
+    static void writeColor(R8G8B8A8S *dst, const gl::ColorI *src);
+    static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2);
+};
+
+struct R16S
+{
+    int16_t R;
+
+    static void readColor(gl::ColorF *dst, const R16S *src);
+    static void readColor(gl::ColorI *dst, const R16S *src);
+    static void writeColor(R16S *dst, const gl::ColorF *src);
+    static void writeColor(R16S *dst, const gl::ColorI *src);
+    static void average(R16S *dst, const R16S *src1, const R16S *src2);
+};
+
+struct R16G16S
+{
+    int16_t R;
+    int16_t G;
+
+    static void readColor(gl::ColorF *dst, const R16G16S *src);
+    static void readColor(gl::ColorI *dst, const R16G16S *src);
+    static void writeColor(R16G16S *dst, const gl::ColorF *src);
+    static void writeColor(R16G16S *dst, const gl::ColorI *src);
+    static void average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2);
+};
+
+struct R16G16B16S
+{
+    int16_t R;
+    int16_t G;
+    int16_t B;
+
+    static void readColor(gl::ColorF *dst, const R16G16B16S *src);
+    static void readColor(gl::ColorI *dst, const R16G16B16S *src);
+    static void writeColor(R16G16B16S *dst, const gl::ColorF *src);
+    static void writeColor(R16G16B16S *dst, const gl::ColorI *src);
+    static void average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2);
+};
+
+struct R16G16B16A16S
+{
+    int16_t R;
+    int16_t G;
+    int16_t B;
+    int16_t A;
+
+    static void readColor(gl::ColorF *dst, const R16G16B16A16S *src);
+    static void readColor(gl::ColorI *dst, const R16G16B16A16S *src);
+    static void writeColor(R16G16B16A16S *dst, const gl::ColorF *src);
+    static void writeColor(R16G16B16A16S *dst, const gl::ColorI *src);
+    static void average(R16G16B16A16S *dst, const R16G16B16A16S *src1, const R16G16B16A16S *src2);
+};
+
+struct R32S
+{
+    int32_t R;
+
+    static void readColor(gl::ColorF *dst, const R32S *src);
+    static void readColor(gl::ColorI *dst, const R32S *src);
+    static void writeColor(R32S *dst, const gl::ColorF *src);
+    static void writeColor(R32S *dst, const gl::ColorI *src);
+    static void average(R32S *dst, const R32S *src1, const R32S *src2);
+};
+
+struct R32G32S
+{
+    int32_t R;
+    int32_t G;
+
+    static void readColor(gl::ColorF *dst, const R32G32S *src);
+    static void readColor(gl::ColorI *dst, const R32G32S *src);
+    static void writeColor(R32G32S *dst, const gl::ColorF *src);
+    static void writeColor(R32G32S *dst, const gl::ColorI *src);
+    static void average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2);
+};
+
+struct R32G32B32S
+{
+    int32_t R;
+    int32_t G;
+    int32_t B;
+
+    static void readColor(gl::ColorF *dst, const R32G32B32S *src);
+    static void readColor(gl::ColorI *dst, const R32G32B32S *src);
+    static void writeColor(R32G32B32S *dst, const gl::ColorF *src);
+    static void writeColor(R32G32B32S *dst, const gl::ColorI *src);
+    static void average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2);
+};
+
+struct R32G32B32A32S
+{
+    int32_t R;
+    int32_t G;
+    int32_t B;
+    int32_t A;
+
+    static void readColor(gl::ColorF *dst, const R32G32B32A32S *src);
+    static void readColor(gl::ColorI *dst, const R32G32B32A32S *src);
+    static void writeColor(R32G32B32A32S *dst, const gl::ColorF *src);
+    static void writeColor(R32G32B32A32S *dst, const gl::ColorI *src);
+    static void average(R32G32B32A32S *dst, const R32G32B32A32S *src1, const R32G32B32A32S *src2);
+};
+
+struct A16B16G16R16F
+{
+    uint16_t A;
+    uint16_t R;
+    uint16_t G;
+    uint16_t B;
+
+    static void readColor(gl::ColorF *dst, const A16B16G16R16F *src);
+    static void writeColor(A16B16G16R16F *dst, const gl::ColorF *src);
+    static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2);
+};
+
+struct R16G16B16A16F
+{
+    uint16_t R;
+    uint16_t G;
+    uint16_t B;
+    uint16_t A;
+
+    static void readColor(gl::ColorF *dst, const R16G16B16A16F *src);
+    static void writeColor(R16G16B16A16F *dst, const gl::ColorF *src);
+    static void average(R16G16B16A16F *dst, const R16G16B16A16F *src1, const R16G16B16A16F *src2);
+};
+
+struct R16F
+{
+    uint16_t R;
+
+    static void readColor(gl::ColorF *dst, const R16F *src);
+    static void writeColor(R16F *dst, const gl::ColorF *src);
+    static void average(R16F *dst, const R16F *src1, const R16F *src2);
+};
+
+struct A16F
+{
+    uint16_t A;
+
+    static void readColor(gl::ColorF *dst, const A16F *src);
+    static void writeColor(A16F *dst, const gl::ColorF *src);
+    static void average(A16F *dst, const A16F *src1, const A16F *src2);
+};
+
+struct L16F
+{
+    uint16_t L;
+
+    static void readColor(gl::ColorF *dst, const L16F *src);
+    static void writeColor(L16F *dst, const gl::ColorF *src);
+    static void average(L16F *dst, const L16F *src1, const L16F *src2);
+};
+
+struct L16A16F
+{
+    uint16_t L;
+    uint16_t A;
+
+    static void readColor(gl::ColorF *dst, const L16A16F *src);
+    static void writeColor(L16A16F *dst, const gl::ColorF *src);
+    static void average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2);
+};
+
+struct R16G16F
+{
+    uint16_t R;
+    uint16_t G;
+
+    static void readColor(gl::ColorF *dst, const R16G16F *src);
+    static void writeColor(R16G16F *dst, const gl::ColorF *src);
+    static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2);
+};
+
+struct R16G16B16F
+{
+    uint16_t R;
+    uint16_t G;
+    uint16_t B;
+
+    static void readColor(gl::ColorF *dst, const R16G16B16F *src);
+    static void writeColor(R16G16B16F *dst, const gl::ColorF *src);
+    static void average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2);
+};
+
+struct A32B32G32R32F
+{
+    float A;
+    float R;
+    float G;
+    float B;
+
+    static void readColor(gl::ColorF *dst, const A32B32G32R32F *src);
+    static void writeColor(A32B32G32R32F *dst, const gl::ColorF *src);
+    static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2);
+};
+
+struct R32G32B32A32F
+{
+    float R;
+    float G;
+    float B;
+    float A;
+
+    static void readColor(gl::ColorF *dst, const R32G32B32A32F *src);
+    static void writeColor(R32G32B32A32F *dst, const gl::ColorF *src);
+    static void average(R32G32B32A32F *dst, const R32G32B32A32F *src1, const R32G32B32A32F *src2);
+};
+
+struct R32F
+{
+    float R;
+
+    static void readColor(gl::ColorF *dst, const R32F *src);
+    static void writeColor(R32F *dst, const gl::ColorF *src);
+    static void average(R32F *dst, const R32F *src1, const R32F *src2);
+};
+
+struct A32F
+{
+    float A;
+
+    static void readColor(gl::ColorF *dst, const A32F *src);
+    static void writeColor(A32F *dst, const gl::ColorF *src);
+    static void average(A32F *dst, const A32F *src1, const A32F *src2);
+};
+
+struct L32F
+{
+    float L;
+
+    static void readColor(gl::ColorF *dst, const L32F *src);
+    static void writeColor(L32F *dst, const gl::ColorF *src);
+    static void average(L32F *dst, const L32F *src1, const L32F *src2);
+};
+
+struct L32A32F
+{
+    float L;
+    float A;
+
+    static void readColor(gl::ColorF *dst, const L32A32F *src);
+    static void writeColor(L32A32F *dst, const gl::ColorF *src);
+    static void average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2);
+};
+
+struct R32G32F
+{
+    float R;
+    float G;
+
+    static void readColor(gl::ColorF *dst, const R32G32F *src);
+    static void writeColor(R32G32F *dst, const gl::ColorF *src);
+    static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2);
+};
+
+struct R32G32B32F
+{
+    float R;
+    float G;
+    float B;
+
+    static void readColor(gl::ColorF *dst, const R32G32B32F *src);
+    static void writeColor(R32G32B32F *dst, const gl::ColorF *src);
+    static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2);
+};
+
+struct R10G10B10A2
+{
+    uint32_t R : 10;
+    uint32_t G : 10;
+    uint32_t B : 10;
+    uint32_t A : 2;
+
+    static void readColor(gl::ColorF *dst, const R10G10B10A2 *src);
+    static void readColor(gl::ColorUI *dst, const R10G10B10A2 *src);
+    static void writeColor(R10G10B10A2 *dst, const gl::ColorF *src);
+    static void writeColor(R10G10B10A2 *dst, const gl::ColorUI *src);
+    static void average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2);
+};
+static_assert(sizeof(R10G10B10A2) == 4, "R10G10B10A2 struct not 32-bits.");
+
+struct R9G9B9E5
+{
+    uint32_t R : 9;
+    uint32_t G : 9;
+    uint32_t B : 9;
+    uint32_t E : 5;
+
+    static void readColor(gl::ColorF *dst, const R9G9B9E5 *src);
+    static void writeColor(R9G9B9E5 *dst, const gl::ColorF *src);
+    static void average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2);
+};
+static_assert(sizeof(R9G9B9E5) == 4, "R9G9B9E5 struct not 32-bits.");
+
+struct R11G11B10F
+{
+    uint32_t R : 11;
+    uint32_t G : 11;
+    uint32_t B : 10;
+
+    static void readColor(gl::ColorF *dst, const R11G11B10F *src);
+    static void writeColor(R11G11B10F *dst, const gl::ColorF *src);
+    static void average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2);
+};
+static_assert(sizeof(R11G11B10F) == 4, "R11G11B10F struct not 32-bits.");
+
+}  // namespace angle
+
+#endif  // IMAGEUTIL_IMAGEFORMATS_H_
diff --git a/src/third_party/angle/src/image_util/loadimage.cpp b/src/third_party/angle/src/image_util/loadimage.cpp
new file mode 100644
index 0000000..56ad3b3
--- /dev/null
+++ b/src/third_party/angle/src/image_util/loadimage.cpp
@@ -0,0 +1,1323 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angle_loadimage.cpp: Defines image loading functions.
+
+#include "image_util/loadimage.h"
+
+#include "common/mathutil.h"
+#include "common/platform.h"
+#include "image_util/imageformats.h"
+
+namespace angle
+{
+
+void LoadA8ToRGBA8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch)
+{
+#if defined(ANGLE_USE_SSE)
+    if (gl::supportsSSE2())
+    {
+        __m128i zeroWide = _mm_setzero_si128();
+
+        for (size_t z = 0; z < depth; z++)
+        {
+            for (size_t y = 0; y < height; y++)
+            {
+                const uint8_t *source =
+                    priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+                uint32_t *dest = priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch,
+                                                                   outputDepthPitch);
+
+                size_t x = 0;
+
+                // Make output writes aligned
+                for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
+                {
+                    dest[x] = static_cast<uint32_t>(source[x]) << 24;
+                }
+
+                for (; x + 7 < width; x += 8)
+                {
+                    __m128i sourceData =
+                        _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&source[x]));
+                    // Interleave each byte to 16bit, make the lower byte to zero
+                    sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
+                    // Interleave each 16bit to 32bit, make the lower 16bit to zero
+                    __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
+                    __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
+
+                    _mm_store_si128(reinterpret_cast<__m128i *>(&dest[x]), lo);
+                    _mm_store_si128(reinterpret_cast<__m128i *>(&dest[x + 4]), hi);
+                }
+
+                // Handle the remainder
+                for (; x < width; x++)
+                {
+                    dest[x] = static_cast<uint32_t>(source[x]) << 24;
+                }
+            }
+        }
+
+        return;
+    }
+#endif
+
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint8_t *source =
+                priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint32_t *dest =
+                priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = static_cast<uint32_t>(source[x]) << 24;
+            }
+        }
+    }
+}
+
+void LoadA8ToBGRA8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch)
+{
+    // Same as loading to RGBA
+    LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                  outputRowPitch, outputDepthPitch);
+}
+
+void LoadA32FToRGBA32F(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const float *source =
+                priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+            float *dest =
+                priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = 0.0f;
+                dest[4 * x + 1] = 0.0f;
+                dest[4 * x + 2] = 0.0f;
+                dest[4 * x + 3] = source[x];
+            }
+        }
+    }
+}
+
+void LoadA16FToRGBA16F(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = 0;
+                dest[4 * x + 1] = 0;
+                dest[4 * x + 2] = 0;
+                dest[4 * x + 3] = source[x];
+            }
+        }
+    }
+}
+
+void LoadL8ToRGBA8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint8_t *source =
+                priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint8_t sourceVal = source[x];
+                dest[4 * x + 0]   = sourceVal;
+                dest[4 * x + 1]   = sourceVal;
+                dest[4 * x + 2]   = sourceVal;
+                dest[4 * x + 3]   = 0xFF;
+            }
+        }
+    }
+}
+
+void LoadL8ToBGRA8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch)
+{
+    // Same as loading to RGBA
+    LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                  outputRowPitch, outputDepthPitch);
+}
+
+void LoadL32FToRGBA32F(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const float *source =
+                priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+            float *dest =
+                priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x];
+                dest[4 * x + 1] = source[x];
+                dest[4 * x + 2] = source[x];
+                dest[4 * x + 3] = 1.0f;
+            }
+        }
+    }
+}
+
+void LoadL16FToRGBA16F(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x];
+                dest[4 * x + 1] = source[x];
+                dest[4 * x + 2] = source[x];
+                dest[4 * x + 3] = gl::Float16One;
+            }
+        }
+    }
+}
+
+void LoadLA8ToRGBA8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint8_t *source =
+                priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[2 * x + 0];
+                dest[4 * x + 1] = source[2 * x + 0];
+                dest[4 * x + 2] = source[2 * x + 0];
+                dest[4 * x + 3] = source[2 * x + 1];
+            }
+        }
+    }
+}
+
+void LoadLA8ToBGRA8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch)
+{
+    // Same as loading to RGBA
+    LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                   outputRowPitch, outputDepthPitch);
+}
+
+void LoadLA32FToRGBA32F(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const float *source =
+                priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+            float *dest =
+                priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[2 * x + 0];
+                dest[4 * x + 1] = source[2 * x + 0];
+                dest[4 * x + 2] = source[2 * x + 0];
+                dest[4 * x + 3] = source[2 * x + 1];
+            }
+        }
+    }
+}
+
+void LoadLA16FToRGBA16F(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[2 * x + 0];
+                dest[4 * x + 1] = source[2 * x + 0];
+                dest[4 * x + 2] = source[2 * x + 0];
+                dest[4 * x + 3] = source[2 * x + 1];
+            }
+        }
+    }
+}
+
+void LoadRGB8ToBGR565(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint8_t *source =
+                priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint8_t r8 = source[x * 3 + 0];
+                uint8_t g8 = source[x * 3 + 1];
+                uint8_t b8 = source[x * 3 + 2];
+                auto r5    = static_cast<uint16_t>(r8 >> 3);
+                auto g6    = static_cast<uint16_t>(g8 >> 2);
+                auto b5    = static_cast<uint16_t>(b8 >> 3);
+                dest[x]    = (r5 << 11) | (g6 << 5) | b5;
+            }
+        }
+    }
+}
+
+void LoadRGB565ToBGR565(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                // The GL type RGB is packed with with red in the MSB, while the D3D11 type BGR
+                // is packed with red in the LSB
+                auto rgb    = source[x];
+                uint16_t r5 = gl::getShiftedData<5, 11>(rgb);
+                uint16_t g6 = gl::getShiftedData<6, 5>(rgb);
+                uint16_t b5 = gl::getShiftedData<5, 0>(rgb);
+                dest[x]     = (r5 << 11) | (g6 << 5) | b5;
+            }
+        }
+    }
+}
+
+void LoadRGB8ToBGRX8(size_t width,
+                     size_t height,
+                     size_t depth,
+                     const uint8_t *input,
+                     size_t inputRowPitch,
+                     size_t inputDepthPitch,
+                     uint8_t *output,
+                     size_t outputRowPitch,
+                     size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint8_t *source =
+                priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x * 3 + 2];
+                dest[4 * x + 1] = source[x * 3 + 1];
+                dest[4 * x + 2] = source[x * 3 + 0];
+                dest[4 * x + 3] = 0xFF;
+            }
+        }
+    }
+}
+
+void LoadRG8ToBGRX8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint8_t *source =
+                priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = 0x00;
+                dest[4 * x + 1] = source[x * 2 + 1];
+                dest[4 * x + 2] = source[x * 2 + 0];
+                dest[4 * x + 3] = 0xFF;
+            }
+        }
+    }
+}
+
+void LoadR8ToBGRX8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint8_t *source =
+                priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = 0x00;
+                dest[4 * x + 1] = 0x00;
+                dest[4 * x + 2] = source[x];
+                dest[4 * x + 3] = 0xFF;
+            }
+        }
+    }
+}
+
+void LoadR5G6B5ToBGRA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint16_t rgb = source[x];
+                dest[4 * x + 0] =
+                    static_cast<uint8_t>(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2));
+                dest[4 * x + 1] =
+                    static_cast<uint8_t>(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9));
+                dest[4 * x + 2] =
+                    static_cast<uint8_t>(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13));
+                dest[4 * x + 3] = 0xFF;
+            }
+        }
+    }
+}
+
+void LoadR5G6B5ToRGBA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint16_t rgb = source[x];
+                dest[4 * x + 0] =
+                    static_cast<uint8_t>(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13));
+                dest[4 * x + 1] =
+                    static_cast<uint8_t>(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9));
+                dest[4 * x + 2] =
+                    static_cast<uint8_t>(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2));
+                dest[4 * x + 3] = 0xFF;
+            }
+        }
+    }
+}
+
+void LoadRGBA8ToBGRA8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch)
+{
+#if defined(ANGLE_USE_SSE)
+    if (gl::supportsSSE2())
+    {
+        __m128i brMask = _mm_set1_epi32(0x00ff00ff);
+
+        for (size_t z = 0; z < depth; z++)
+        {
+            for (size_t y = 0; y < height; y++)
+            {
+                const uint32_t *source =
+                    priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+                uint32_t *dest = priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch,
+                                                                   outputDepthPitch);
+
+                size_t x = 0;
+
+                // Make output writes aligned
+                for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
+                {
+                    uint32_t rgba = source[x];
+                    dest[x]       = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+                }
+
+                for (; x + 3 < width; x += 4)
+                {
+                    __m128i sourceData =
+                        _mm_loadu_si128(reinterpret_cast<const __m128i *>(&source[x]));
+                    // Mask out g and a, which don't change
+                    __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
+                    // Mask out b and r
+                    __m128i brComponents = _mm_and_si128(sourceData, brMask);
+                    // Swap b and r
+                    __m128i brSwapped = _mm_shufflehi_epi16(
+                        _mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)),
+                        _MM_SHUFFLE(2, 3, 0, 1));
+                    __m128i result = _mm_or_si128(gaComponents, brSwapped);
+                    _mm_store_si128(reinterpret_cast<__m128i *>(&dest[x]), result);
+                }
+
+                // Perform leftover writes
+                for (; x < width; x++)
+                {
+                    uint32_t rgba = source[x];
+                    dest[x]       = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+                }
+            }
+        }
+
+        return;
+    }
+#endif
+
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint32_t *source =
+                priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint32_t *dest =
+                priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint32_t rgba = source[x];
+                dest[x]       = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+            }
+        }
+    }
+}
+
+void LoadRGBA8ToBGRA4(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint32_t *source =
+                priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint32_t rgba8 = source[x];
+                auto r4        = static_cast<uint16_t>((rgba8 & 0x000000FF) >> 4);
+                auto g4        = static_cast<uint16_t>((rgba8 & 0x0000FF00) >> 12);
+                auto b4        = static_cast<uint16_t>((rgba8 & 0x00FF0000) >> 20);
+                auto a4        = static_cast<uint16_t>((rgba8 & 0xFF000000) >> 28);
+                dest[x]        = (a4 << 12) | (r4 << 8) | (g4 << 4) | b4;
+            }
+        }
+    }
+}
+
+void LoadRGBA4ToARGB4(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = ANGLE_ROTR16(source[x], 4);
+            }
+        }
+    }
+}
+
+void LoadRGBA4ToBGRA8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint16_t rgba = source[x];
+                dest[4 * x + 0] =
+                    static_cast<uint8_t>(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4));
+                dest[4 * x + 1] =
+                    static_cast<uint8_t>(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8));
+                dest[4 * x + 2] =
+                    static_cast<uint8_t>(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12));
+                dest[4 * x + 3] =
+                    static_cast<uint8_t>(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0));
+            }
+        }
+    }
+}
+
+void LoadRGBA4ToRGBA8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint16_t rgba = source[x];
+                dest[4 * x + 0] =
+                    static_cast<uint8_t>(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12));
+                dest[4 * x + 1] =
+                    static_cast<uint8_t>(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8));
+                dest[4 * x + 2] =
+                    static_cast<uint8_t>(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4));
+                dest[4 * x + 3] =
+                    static_cast<uint8_t>(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0));
+            }
+        }
+    }
+}
+
+void LoadBGRA4ToBGRA8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint16_t bgra = source[x];
+                dest[4 * x + 0] =
+                    static_cast<uint8_t>(((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12));
+                dest[4 * x + 1] =
+                    static_cast<uint8_t>(((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8));
+                dest[4 * x + 2] =
+                    static_cast<uint8_t>(((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4));
+                dest[4 * x + 3] =
+                    static_cast<uint8_t>(((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0));
+            }
+        }
+    }
+}
+
+void LoadRGBA8ToBGR5A1(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint32_t *source =
+                priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint32_t rgba8 = source[x];
+                auto r5        = static_cast<uint16_t>((rgba8 & 0x000000FF) >> 3);
+                auto g5        = static_cast<uint16_t>((rgba8 & 0x0000FF00) >> 11);
+                auto b5        = static_cast<uint16_t>((rgba8 & 0x00FF0000) >> 19);
+                auto a1        = static_cast<uint16_t>((rgba8 & 0xFF000000) >> 31);
+                dest[x]        = (a1 << 15) | (r5 << 10) | (g5 << 5) | b5;
+            }
+        }
+    }
+}
+
+void LoadRGB10A2ToBGR5A1(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const R10G10B10A2 *source =
+                priv::OffsetDataPointer<R10G10B10A2>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                R10G10B10A2 rgb10a2 = source[x];
+
+                uint16_t r5 = static_cast<uint16_t>(rgb10a2.R >> 5u);
+                uint16_t g5 = static_cast<uint16_t>(rgb10a2.G >> 5u);
+                uint16_t b5 = static_cast<uint16_t>(rgb10a2.B >> 5u);
+                uint16_t a1 = static_cast<uint16_t>(rgb10a2.A >> 1u);
+
+                dest[x] = (a1 << 15) | (r5 << 10) | (g5 << 5) | b5;
+            }
+        }
+    }
+}
+
+void LoadRGB5A1ToA1RGB5(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = ANGLE_ROTR16(source[x], 1);
+            }
+        }
+    }
+}
+
+void LoadRGB5A1ToBGRA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint16_t rgba = source[x];
+                dest[4 * x + 0] =
+                    static_cast<uint8_t>(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3));
+                dest[4 * x + 1] =
+                    static_cast<uint8_t>(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8));
+                dest[4 * x + 2] =
+                    static_cast<uint8_t>(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13));
+                dest[4 * x + 3] = static_cast<uint8_t>((rgba & 0x0001) ? 0xFF : 0);
+            }
+        }
+    }
+}
+
+void LoadRGB5A1ToRGBA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint16_t rgba = source[x];
+                dest[4 * x + 0] =
+                    static_cast<uint8_t>(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13));
+                dest[4 * x + 1] =
+                    static_cast<uint8_t>(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8));
+                dest[4 * x + 2] =
+                    static_cast<uint8_t>(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3));
+                dest[4 * x + 3] = static_cast<uint8_t>((rgba & 0x0001) ? 0xFF : 0);
+            }
+        }
+    }
+}
+
+void LoadBGR5A1ToBGRA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint16_t bgra = source[x];
+                dest[4 * x + 0] =
+                    static_cast<uint8_t>(((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13));
+                dest[4 * x + 1] =
+                    static_cast<uint8_t>(((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8));
+                dest[4 * x + 2] =
+                    static_cast<uint8_t>(((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3));
+                dest[4 * x + 3] = static_cast<uint8_t>((bgra & 0x0001) ? 0xFF : 0);
+            }
+        }
+    }
+}
+
+void LoadRGB10A2ToRGBA8(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint32_t *source =
+                priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint32_t rgba   = source[x];
+                dest[4 * x + 0] = static_cast<uint8_t>((rgba & 0x000003FF) >> 2);
+                dest[4 * x + 1] = static_cast<uint8_t>((rgba & 0x000FFC00) >> 12);
+                dest[4 * x + 2] = static_cast<uint8_t>((rgba & 0x3FF00000) >> 22);
+                dest[4 * x + 3] = static_cast<uint8_t>(((rgba & 0xC0000000) >> 30) * 0x55);
+            }
+        }
+    }
+}
+
+void LoadRGB16FToRGB9E5(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint32_t *dest =
+                priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]),
+                                                      gl::float16ToFloat32(source[x * 3 + 1]),
+                                                      gl::float16ToFloat32(source[x * 3 + 2]));
+            }
+        }
+    }
+}
+
+void LoadRGB32FToRGB9E5(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const float *source =
+                priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint32_t *dest =
+                priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1],
+                                                      source[x * 3 + 2]);
+            }
+        }
+    }
+}
+
+void LoadRGB16FToRG11B10F(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint32_t *dest =
+                priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) |
+                          (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) |
+                          (gl::float32ToFloat10(gl::float16ToFloat32(source[x * 3 + 2])) << 22);
+            }
+        }
+    }
+}
+
+void LoadRGB32FToRG11B10F(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const float *source =
+                priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint32_t *dest =
+                priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) |
+                          (gl::float32ToFloat11(source[x * 3 + 1]) << 11) |
+                          (gl::float32ToFloat10(source[x * 3 + 2]) << 22);
+            }
+        }
+    }
+}
+
+void LoadG8R24ToR24G8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint32_t *source =
+                priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint32_t *dest =
+                priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                uint32_t d = source[x] >> 8;
+                uint8_t s  = source[x] & 0xFF;
+                dest[x]    = d | (s << 24);
+            }
+        }
+    }
+}
+
+void LoadD32FToD32F(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const float *source =
+                priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+            float *dest =
+                priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = gl::clamp01(source[x]);
+            }
+        }
+    }
+}
+
+void LoadD32FS8X24ToD32FS8X24(size_t width,
+                              size_t height,
+                              size_t depth,
+                              const uint8_t *input,
+                              size_t inputRowPitch,
+                              size_t inputDepthPitch,
+                              uint8_t *output,
+                              size_t outputRowPitch,
+                              size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const float *sourceDepth =
+                priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+            const uint32_t *sourceStencil =
+                priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch) + 1;
+            float *destDepth =
+                priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+            uint32_t *destStencil =
+                priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch) +
+                1;
+            for (size_t x = 0; x < width; x++)
+            {
+                destDepth[x * 2]   = gl::clamp01(sourceDepth[x * 2]);
+                destStencil[x * 2] = sourceStencil[x * 2] & 0xFF000000;
+            }
+        }
+    }
+}
+
+void LoadRGB32FToRGBA16F(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const float *source =
+                priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]);
+                dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]);
+                dest[x * 4 + 2] = gl::float32ToFloat16(source[x * 3 + 2]);
+                dest[x * 4 + 3] = gl::Float16One;
+            }
+        }
+    }
+}
+
+void LoadR32ToR16(size_t width,
+                  size_t height,
+                  size_t depth,
+                  const uint8_t *input,
+                  size_t inputRowPitch,
+                  size_t inputDepthPitch,
+                  uint8_t *output,
+                  size_t outputRowPitch,
+                  size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint32_t *source =
+                priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = source[x] >> 16;
+            }
+        }
+    }
+}
+
+void LoadR32ToR24G8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint32_t *source =
+                priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint32_t *dest =
+                priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x] = source[x] >> 8;
+            }
+        }
+    }
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/image_util/loadimage.h b/src/third_party/angle/src/image_util/loadimage.h
new file mode 100644
index 0000000..3e8aac7
--- /dev/null
+++ b/src/third_party/angle/src/image_util/loadimage.h
@@ -0,0 +1,658 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// loadimage.h: Defines image loading functions
+
+#ifndef IMAGEUTIL_LOADIMAGE_H_
+#define IMAGEUTIL_LOADIMAGE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace angle
+{
+
+void LoadA8ToRGBA8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch);
+
+void LoadA8ToBGRA8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch);
+
+void LoadA32FToRGBA32F(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadA16FToRGBA16F(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadL8ToRGBA8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch);
+
+void LoadL8ToBGRA8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch);
+
+void LoadL32FToRGBA32F(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadL16FToRGBA16F(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadLA8ToRGBA8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch);
+
+void LoadLA8ToBGRA8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch);
+
+void LoadLA32FToRGBA32F(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch);
+
+void LoadLA16FToRGBA16F(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch);
+
+void LoadRGB8ToBGR565(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch);
+
+void LoadRGB565ToBGR565(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch);
+
+void LoadRGB8ToBGRX8(size_t width,
+                     size_t height,
+                     size_t depth,
+                     const uint8_t *input,
+                     size_t inputRowPitch,
+                     size_t inputDepthPitch,
+                     uint8_t *output,
+                     size_t outputRowPitch,
+                     size_t outputDepthPitch);
+
+void LoadRG8ToBGRX8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch);
+
+void LoadR8ToBGRX8(size_t width,
+                   size_t height,
+                   size_t depth,
+                   const uint8_t *input,
+                   size_t inputRowPitch,
+                   size_t inputDepthPitch,
+                   uint8_t *output,
+                   size_t outputRowPitch,
+                   size_t outputDepthPitch);
+
+void LoadR5G6B5ToBGRA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadR5G6B5ToRGBA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadRGBA8ToBGRA8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch);
+
+void LoadRGBA8ToBGRA4(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch);
+
+void LoadRGBA4ToARGB4(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch);
+
+void LoadRGBA4ToBGRA8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch);
+
+void LoadRGBA4ToRGBA8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch);
+
+void LoadBGRA4ToBGRA8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch);
+
+void LoadRGBA8ToBGR5A1(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadRGB10A2ToBGR5A1(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch);
+
+void LoadRGB5A1ToA1RGB5(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch);
+
+void LoadRGB5A1ToBGRA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadRGB5A1ToRGBA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadBGR5A1ToBGRA8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadRGB10A2ToRGBA8(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch);
+
+void LoadRGB16FToRGB9E5(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch);
+
+void LoadRGB32FToRGB9E5(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch);
+
+void LoadRGB16FToRG11B10F(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch);
+
+void LoadRGB32FToRG11B10F(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch);
+
+void LoadG8R24ToR24G8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch);
+
+void LoadD32FToD32F(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch);
+
+void LoadD32FS8X24ToD32FS8X24(size_t width,
+                              size_t height,
+                              size_t depth,
+                              const uint8_t *input,
+                              size_t inputRowPitch,
+                              size_t inputDepthPitch,
+                              uint8_t *output,
+                              size_t outputRowPitch,
+                              size_t outputDepthPitch);
+
+template <typename type, size_t componentCount>
+inline void LoadToNative(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch);
+
+template <typename type, uint32_t fourthComponentBits>
+inline void LoadToNative3To4(size_t width,
+                             size_t height,
+                             size_t depth,
+                             const uint8_t *input,
+                             size_t inputRowPitch,
+                             size_t inputDepthPitch,
+                             uint8_t *output,
+                             size_t outputRowPitch,
+                             size_t outputDepthPitch);
+
+template <size_t componentCount>
+inline void Load32FTo16F(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch);
+
+void LoadRGB32FToRGBA16F(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch);
+
+template <size_t blockWidth, size_t blockHeight, size_t blockSize>
+inline void LoadCompressedToNative(size_t width,
+                                   size_t height,
+                                   size_t depth,
+                                   const uint8_t *input,
+                                   size_t inputRowPitch,
+                                   size_t inputDepthPitch,
+                                   uint8_t *output,
+                                   size_t outputRowPitch,
+                                   size_t outputDepthPitch);
+
+void LoadR32ToR16(size_t width,
+                  size_t height,
+                  size_t depth,
+                  const uint8_t *input,
+                  size_t inputRowPitch,
+                  size_t inputDepthPitch,
+                  uint8_t *output,
+                  size_t outputRowPitch,
+                  size_t outputDepthPitch);
+
+template <typename type,
+          uint32_t firstBits,
+          uint32_t secondBits,
+          uint32_t thirdBits,
+          uint32_t fourthBits>
+inline void Initialize4ComponentData(size_t width,
+                                     size_t height,
+                                     size_t depth,
+                                     uint8_t *output,
+                                     size_t outputRowPitch,
+                                     size_t outputDepthPitch);
+
+void LoadR32ToR24G8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch);
+
+void LoadETC1RGB8ToRGBA8(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch);
+
+void LoadETC1RGB8ToBC1(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadEACR11ToR8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch);
+
+void LoadEACR11SToR8(size_t width,
+                     size_t height,
+                     size_t depth,
+                     const uint8_t *input,
+                     size_t inputRowPitch,
+                     size_t inputDepthPitch,
+                     uint8_t *output,
+                     size_t outputRowPitch,
+                     size_t outputDepthPitch);
+
+void LoadEACRG11ToRG8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch);
+
+void LoadEACRG11SToRG8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadETC2RGB8ToRGBA8(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch);
+
+void LoadETC2RGB8ToBC1(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch);
+
+void LoadETC2SRGB8ToRGBA8(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch);
+
+void LoadETC2SRGB8ToBC1(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch);
+
+void LoadETC2RGB8A1ToRGBA8(size_t width,
+                           size_t height,
+                           size_t depth,
+                           const uint8_t *input,
+                           size_t inputRowPitch,
+                           size_t inputDepthPitch,
+                           uint8_t *output,
+                           size_t outputRowPitch,
+                           size_t outputDepthPitch);
+
+void LoadETC2RGB8A1ToBC1(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch);
+
+void LoadETC2SRGB8A1ToRGBA8(size_t width,
+                            size_t height,
+                            size_t depth,
+                            const uint8_t *input,
+                            size_t inputRowPitch,
+                            size_t inputDepthPitch,
+                            uint8_t *output,
+                            size_t outputRowPitch,
+                            size_t outputDepthPitch);
+
+void LoadETC2SRGB8A1ToBC1(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch);
+
+void LoadETC2RGBA8ToRGBA8(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch);
+
+void LoadETC2SRGBA8ToSRGBA8(size_t width,
+                            size_t height,
+                            size_t depth,
+                            const uint8_t *input,
+                            size_t inputRowPitch,
+                            size_t inputDepthPitch,
+                            uint8_t *output,
+                            size_t outputRowPitch,
+                            size_t outputDepthPitch);
+
+}  // namespace angle
+
+#include "loadimage.inl"
+
+#endif  // IMAGEUTIL_LOADIMAGE_H_
diff --git a/src/third_party/angle/src/image_util/loadimage.inl b/src/third_party/angle/src/image_util/loadimage.inl
new file mode 100644
index 0000000..b8d590c
--- /dev/null
+++ b/src/third_party/angle/src/image_util/loadimage.inl
@@ -0,0 +1,163 @@
+//
+// Copyright (c) 2014-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "common/mathutil.h"
+
+#include <string.h>
+
+namespace angle
+{
+
+namespace priv
+{
+
+template <typename T>
+inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+    return reinterpret_cast<T*>(data + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename T>
+inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+    return reinterpret_cast<const T*>(data + (y * rowPitch) + (z * depthPitch));
+}
+
+}  // namespace priv
+
+template <typename type, size_t componentCount>
+inline void LoadToNative(size_t width, size_t height, size_t depth,
+                         const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+                         uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+    const size_t rowSize = width * sizeof(type) * componentCount;
+    const size_t layerSize = rowSize * height;
+    const size_t imageSize = layerSize * depth;
+
+    if (layerSize == inputDepthPitch && layerSize == outputDepthPitch)
+    {
+        ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch);
+        memcpy(output, input, imageSize);
+    }
+    else if (rowSize == inputRowPitch && rowSize == outputRowPitch)
+    {
+        for (size_t z = 0; z < depth; z++)
+        {
+            const type *source = priv::OffsetDataPointer<type>(input, 0, z, inputRowPitch, inputDepthPitch);
+            type *dest = priv::OffsetDataPointer<type>(output, 0, z, outputRowPitch, outputDepthPitch);
+
+            memcpy(dest, source, layerSize);
+        }
+    }
+    else
+    {
+        for (size_t z = 0; z < depth; z++)
+        {
+            for (size_t y = 0; y < height; y++)
+            {
+                const type *source = priv::OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
+                type *dest = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
+                memcpy(dest, source, width * sizeof(type) * componentCount);
+            }
+        }
+    }
+}
+
+template <typename type, uint32_t fourthComponentBits>
+inline void LoadToNative3To4(size_t width, size_t height, size_t depth,
+                             const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+                             uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+    const type fourthValue = gl::bitCast<type>(fourthComponentBits);
+
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const type *source = priv::OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
+            type *dest = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                dest[x * 4 + 0] = source[x * 3 + 0];
+                dest[x * 4 + 1] = source[x * 3 + 1];
+                dest[x * 4 + 2] = source[x * 3 + 2];
+                dest[x * 4 + 3] = fourthValue;
+            }
+        }
+    }
+}
+
+template <size_t componentCount>
+inline void Load32FTo16F(size_t width, size_t height, size_t depth,
+                         const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+                         uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+    const size_t elementWidth = componentCount * width;
+
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const float *source = priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest = priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+            for (size_t x = 0; x < elementWidth; x++)
+            {
+                dest[x] = gl::float32ToFloat16(source[x]);
+            }
+        }
+    }
+}
+
+template <size_t blockWidth, size_t blockHeight, size_t blockSize>
+inline void LoadCompressedToNative(size_t width, size_t height, size_t depth,
+                                   const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+                                   uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+    const size_t columns = (width + (blockWidth - 1)) / blockWidth;
+    const size_t rows = (height + (blockHeight - 1)) / blockHeight;
+
+    for (size_t z = 0; z < depth; ++z)
+    {
+        for (size_t y = 0; y < rows; ++y)
+        {
+            const uint8_t *source = priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint8_t *dest = priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            memcpy(dest, source, columns * blockSize);
+        }
+    }
+}
+
+template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits>
+inline void Initialize4ComponentData(size_t width, size_t height, size_t depth,
+                                     uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+    type writeValues[4] =
+    {
+        gl::bitCast<type>(firstBits),
+        gl::bitCast<type>(secondBits),
+        gl::bitCast<type>(thirdBits),
+        gl::bitCast<type>(fourthBits),
+    };
+
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            type *destRow = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                type* destPixel = destRow + x * 4;
+
+                // This could potentially be optimized by generating an entire row of initialization
+                // data and copying row by row instead of pixel by pixel.
+                memcpy(destPixel, writeValues, sizeof(type) * 4);
+            }
+        }
+    }
+}
+
+} // namespace angle
diff --git a/src/third_party/angle/src/image_util/loadimage_etc.cpp b/src/third_party/angle/src/image_util/loadimage_etc.cpp
new file mode 100644
index 0000000..7c7e8dd
--- /dev/null
+++ b/src/third_party/angle/src/image_util/loadimage_etc.cpp
@@ -0,0 +1,1726 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// loadimage_etc.cpp: Decodes ETC and EAC encoded textures.
+
+#include "image_util/loadimage.h"
+
+#include "common/mathutil.h"
+
+#include "image_util/imageformats.h"
+
+namespace angle
+{
+namespace
+{
+// Table 3.17.2 sorted according to table 3.17.3
+// clang-format off
+static const int intensityModifierDefault[][4] =
+{
+    {  2,   8,  -2,   -8 },
+    {  5,  17,  -5,  -17 },
+    {  9,  29,  -9,  -29 },
+    { 13,  42, -13,  -42 },
+    { 18,  60, -18,  -60 },
+    { 24,  80, -24,  -80 },
+    { 33, 106, -33, -106 },
+    { 47, 183, -47, -183 },
+};
+// clang-format on
+
+// Table C.12, intensity modifier for non opaque punchthrough alpha
+// clang-format off
+static const int intensityModifierNonOpaque[][4] =
+{
+    { 0,   8, 0,   -8 },
+    { 0,  17, 0,  -17 },
+    { 0,  29, 0,  -29 },
+    { 0,  42, 0,  -42 },
+    { 0,  60, 0,  -60 },
+    { 0,  80, 0,  -80 },
+    { 0, 106, 0, -106 },
+    { 0, 183, 0, -183 },
+};
+// clang-format on
+
+static const int kNumPixelsInBlock = 16;
+
+struct ETC2Block
+{
+    // Decodes unsigned single or dual channel block to bytes
+    void decodeAsSingleChannel(uint8_t *dest,
+                               size_t x,
+                               size_t y,
+                               size_t w,
+                               size_t h,
+                               size_t destPixelStride,
+                               size_t destRowPitch,
+                               bool isSigned) const
+    {
+        for (size_t j = 0; j < 4 && (y + j) < h; j++)
+        {
+            uint8_t *row = dest + (j * destRowPitch);
+            for (size_t i = 0; i < 4 && (x + i) < w; i++)
+            {
+                uint8_t *pixel = row + (i * destPixelStride);
+                if (isSigned)
+                {
+                    *pixel = clampSByte(getSingleChannel(i, j, isSigned));
+                }
+                else
+                {
+                    *pixel = clampByte(getSingleChannel(i, j, isSigned));
+                }
+            }
+        }
+    }
+
+    // Decodes RGB block to rgba8
+    void decodeAsRGB(uint8_t *dest,
+                     size_t x,
+                     size_t y,
+                     size_t w,
+                     size_t h,
+                     size_t destRowPitch,
+                     const uint8_t alphaValues[4][4],
+                     bool punchThroughAlpha) const
+    {
+        bool opaqueBit                  = u.idht.mode.idm.diffbit;
+        bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
+        // Select mode
+        if (u.idht.mode.idm.diffbit || punchThroughAlpha)
+        {
+            const auto &block = u.idht.mode.idm.colors.diff;
+            int r             = (block.R + block.dR);
+            int g             = (block.G + block.dG);
+            int b             = (block.B + block.dB);
+            if (r < 0 || r > 31)
+            {
+                decodeTBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+                             nonOpaquePunchThroughAlpha);
+            }
+            else if (g < 0 || g > 31)
+            {
+                decodeHBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+                             nonOpaquePunchThroughAlpha);
+            }
+            else if (b < 0 || b > 31)
+            {
+                decodePlanarBlock(dest, x, y, w, h, destRowPitch, alphaValues);
+            }
+            else
+            {
+                decodeDifferentialBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+                                        nonOpaquePunchThroughAlpha);
+            }
+        }
+        else
+        {
+            decodeIndividualBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+                                  nonOpaquePunchThroughAlpha);
+        }
+    }
+
+    // Transcodes RGB block to BC1
+    void transcodeAsBC1(uint8_t *dest,
+                        size_t x,
+                        size_t y,
+                        size_t w,
+                        size_t h,
+                        const uint8_t alphaValues[4][4],
+                        bool punchThroughAlpha) const
+    {
+        bool opaqueBit                  = u.idht.mode.idm.diffbit;
+        bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
+        // Select mode
+        if (u.idht.mode.idm.diffbit || punchThroughAlpha)
+        {
+            const auto &block = u.idht.mode.idm.colors.diff;
+            int r             = (block.R + block.dR);
+            int g             = (block.G + block.dG);
+            int b             = (block.B + block.dB);
+            if (r < 0 || r > 31)
+            {
+                transcodeTBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha);
+            }
+            else if (g < 0 || g > 31)
+            {
+                transcodeHBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha);
+            }
+            else if (b < 0 || b > 31)
+            {
+                transcodePlanarBlockToBC1(dest, x, y, w, h, alphaValues);
+            }
+            else
+            {
+                transcodeDifferentialBlockToBC1(dest, x, y, w, h, alphaValues,
+                                                nonOpaquePunchThroughAlpha);
+            }
+        }
+        else
+        {
+            transcodeIndividualBlockToBC1(dest, x, y, w, h, alphaValues,
+                                          nonOpaquePunchThroughAlpha);
+        }
+    }
+
+  private:
+    union {
+        // Individual, differential, H and T modes
+        struct
+        {
+            union {
+                // Individual and differential modes
+                struct
+                {
+                    union {
+                        struct  // Individual colors
+                        {
+                            unsigned char R2 : 4;
+                            unsigned char R1 : 4;
+                            unsigned char G2 : 4;
+                            unsigned char G1 : 4;
+                            unsigned char B2 : 4;
+                            unsigned char B1 : 4;
+                        } indiv;
+                        struct  // Differential colors
+                        {
+                            signed char dR : 3;
+                            unsigned char R : 5;
+                            signed char dG : 3;
+                            unsigned char G : 5;
+                            signed char dB : 3;
+                            unsigned char B : 5;
+                        } diff;
+                    } colors;
+                    bool flipbit : 1;
+                    bool diffbit : 1;
+                    unsigned char cw2 : 3;
+                    unsigned char cw1 : 3;
+                } idm;
+                // T mode
+                struct
+                {
+                    // Byte 1
+                    unsigned char TR1b : 2;
+                    unsigned char TdummyB : 1;
+                    unsigned char TR1a : 2;
+                    unsigned char TdummyA : 3;
+                    // Byte 2
+                    unsigned char TB1 : 4;
+                    unsigned char TG1 : 4;
+                    // Byte 3
+                    unsigned char TG2 : 4;
+                    unsigned char TR2 : 4;
+                    // Byte 4
+                    unsigned char Tdb : 1;
+                    bool Tflipbit : 1;
+                    unsigned char Tda : 2;
+                    unsigned char TB2 : 4;
+                } tm;
+                // H mode
+                struct
+                {
+                    // Byte 1
+                    unsigned char HG1a : 3;
+                    unsigned char HR1 : 4;
+                    unsigned char HdummyA : 1;
+                    // Byte 2
+                    unsigned char HB1b : 2;
+                    unsigned char HdummyC : 1;
+                    unsigned char HB1a : 1;
+                    unsigned char HG1b : 1;
+                    unsigned char HdummyB : 3;
+                    // Byte 3
+                    unsigned char HG2a : 3;
+                    unsigned char HR2 : 4;
+                    unsigned char HB1c : 1;
+                    // Byte 4
+                    unsigned char Hdb : 1;
+                    bool Hflipbit : 1;
+                    unsigned char Hda : 1;
+                    unsigned char HB2 : 4;
+                    unsigned char HG2b : 1;
+                } hm;
+            } mode;
+            unsigned char pixelIndexMSB[2];
+            unsigned char pixelIndexLSB[2];
+        } idht;
+        // planar mode
+        struct
+        {
+            // Byte 1
+            unsigned char GO1 : 1;
+            unsigned char RO : 6;
+            unsigned char PdummyA : 1;
+            // Byte 2
+            unsigned char BO1 : 1;
+            unsigned char GO2 : 6;
+            unsigned char PdummyB : 1;
+            // Byte 3
+            unsigned char BO3a : 2;
+            unsigned char PdummyD : 1;
+            unsigned char BO2 : 2;
+            unsigned char PdummyC : 3;
+            // Byte 4
+            unsigned char RH2 : 1;
+            bool Pflipbit : 1;
+            unsigned char RH1 : 5;
+            unsigned char BO3b : 1;
+            // Byte 5
+            unsigned char BHa : 1;
+            unsigned char GH : 7;
+            // Byte 6
+            unsigned char RVa : 3;
+            unsigned char BHb : 5;
+            // Byte 7
+            unsigned char GVa : 5;
+            unsigned char RVb : 3;
+            // Byte 8
+            unsigned char BV : 6;
+            unsigned char GVb : 2;
+        } pblk;
+        // Single channel block
+        struct
+        {
+            union {
+                unsigned char us;
+                signed char s;
+            } base_codeword;
+            unsigned char table_index : 4;
+            unsigned char multiplier : 4;
+            unsigned char mc1 : 2;
+            unsigned char mb : 3;
+            unsigned char ma : 3;
+            unsigned char mf1 : 1;
+            unsigned char me : 3;
+            unsigned char md : 3;
+            unsigned char mc2 : 1;
+            unsigned char mh : 3;
+            unsigned char mg : 3;
+            unsigned char mf2 : 2;
+            unsigned char mk1 : 2;
+            unsigned char mj : 3;
+            unsigned char mi : 3;
+            unsigned char mn1 : 1;
+            unsigned char mm : 3;
+            unsigned char ml : 3;
+            unsigned char mk2 : 1;
+            unsigned char mp : 3;
+            unsigned char mo : 3;
+            unsigned char mn2 : 2;
+        } scblk;
+    } u;
+
+    static unsigned char clampByte(int value)
+    {
+        return static_cast<unsigned char>(gl::clamp(value, 0, 255));
+    }
+
+    static signed char clampSByte(int value)
+    {
+        return static_cast<signed char>(gl::clamp(value, -128, 127));
+    }
+
+    static R8G8B8A8 createRGBA(int red, int green, int blue, int alpha)
+    {
+        R8G8B8A8 rgba;
+        rgba.R = clampByte(red);
+        rgba.G = clampByte(green);
+        rgba.B = clampByte(blue);
+        rgba.A = clampByte(alpha);
+        return rgba;
+    }
+
+    static R8G8B8A8 createRGBA(int red, int green, int blue)
+    {
+        return createRGBA(red, green, blue, 255);
+    }
+
+    static int extend_4to8bits(int x) { return (x << 4) | x; }
+    static int extend_5to8bits(int x) { return (x << 3) | (x >> 2); }
+    static int extend_6to8bits(int x) { return (x << 2) | (x >> 4); }
+    static int extend_7to8bits(int x) { return (x << 1) | (x >> 6); }
+
+    void decodeIndividualBlock(uint8_t *dest,
+                               size_t x,
+                               size_t y,
+                               size_t w,
+                               size_t h,
+                               size_t destRowPitch,
+                               const uint8_t alphaValues[4][4],
+                               bool nonOpaquePunchThroughAlpha) const
+    {
+        const auto &block = u.idht.mode.idm.colors.indiv;
+        int r1            = extend_4to8bits(block.R1);
+        int g1            = extend_4to8bits(block.G1);
+        int b1            = extend_4to8bits(block.B1);
+        int r2            = extend_4to8bits(block.R2);
+        int g2            = extend_4to8bits(block.G2);
+        int b2            = extend_4to8bits(block.B2);
+        decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
+                                            alphaValues, nonOpaquePunchThroughAlpha);
+    }
+
+    void decodeDifferentialBlock(uint8_t *dest,
+                                 size_t x,
+                                 size_t y,
+                                 size_t w,
+                                 size_t h,
+                                 size_t destRowPitch,
+                                 const uint8_t alphaValues[4][4],
+                                 bool nonOpaquePunchThroughAlpha) const
+    {
+        const auto &block = u.idht.mode.idm.colors.diff;
+        int b1            = extend_5to8bits(block.B);
+        int g1            = extend_5to8bits(block.G);
+        int r1            = extend_5to8bits(block.R);
+        int r2            = extend_5to8bits(block.R + block.dR);
+        int g2            = extend_5to8bits(block.G + block.dG);
+        int b2            = extend_5to8bits(block.B + block.dB);
+        decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
+                                            alphaValues, nonOpaquePunchThroughAlpha);
+    }
+
+    void decodeIndividualOrDifferentialBlock(uint8_t *dest,
+                                             size_t x,
+                                             size_t y,
+                                             size_t w,
+                                             size_t h,
+                                             size_t destRowPitch,
+                                             int r1,
+                                             int g1,
+                                             int b1,
+                                             int r2,
+                                             int g2,
+                                             int b2,
+                                             const uint8_t alphaValues[4][4],
+                                             bool nonOpaquePunchThroughAlpha) const
+    {
+        const auto intensityModifier =
+            nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
+
+        R8G8B8A8 subblockColors0[4];
+        R8G8B8A8 subblockColors1[4];
+        for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++)
+        {
+            const int i1                 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx];
+            subblockColors0[modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1);
+
+            const int i2                 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx];
+            subblockColors1[modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2);
+        }
+
+        if (u.idht.mode.idm.flipbit)
+        {
+            uint8_t *curPixel = dest;
+            for (size_t j = 0; j < 2 && (y + j) < h; j++)
+            {
+                R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+                for (size_t i = 0; i < 4 && (x + i) < w; i++)
+                {
+                    row[i]   = subblockColors0[getIndex(i, j)];
+                    row[i].A = alphaValues[j][i];
+                }
+                curPixel += destRowPitch;
+            }
+            for (size_t j = 2; j < 4 && (y + j) < h; j++)
+            {
+                R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+                for (size_t i = 0; i < 4 && (x + i) < w; i++)
+                {
+                    row[i]   = subblockColors1[getIndex(i, j)];
+                    row[i].A = alphaValues[j][i];
+                }
+                curPixel += destRowPitch;
+            }
+        }
+        else
+        {
+            uint8_t *curPixel = dest;
+            for (size_t j = 0; j < 4 && (y + j) < h; j++)
+            {
+                R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+                for (size_t i = 0; i < 2 && (x + i) < w; i++)
+                {
+                    row[i]   = subblockColors0[getIndex(i, j)];
+                    row[i].A = alphaValues[j][i];
+                }
+                for (size_t i = 2; i < 4 && (x + i) < w; i++)
+                {
+                    row[i]   = subblockColors1[getIndex(i, j)];
+                    row[i].A = alphaValues[j][i];
+                }
+                curPixel += destRowPitch;
+            }
+        }
+        if (nonOpaquePunchThroughAlpha)
+        {
+            decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
+        }
+    }
+
+    void decodeTBlock(uint8_t *dest,
+                      size_t x,
+                      size_t y,
+                      size_t w,
+                      size_t h,
+                      size_t destRowPitch,
+                      const uint8_t alphaValues[4][4],
+                      bool nonOpaquePunchThroughAlpha) const
+    {
+        // Table C.8, distance index for T and H modes
+        const auto &block = u.idht.mode.tm;
+
+        int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b);
+        int g1 = extend_4to8bits(block.TG1);
+        int b1 = extend_4to8bits(block.TB1);
+        int r2 = extend_4to8bits(block.TR2);
+        int g2 = extend_4to8bits(block.TG2);
+        int b2 = extend_4to8bits(block.TB2);
+
+        static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+        const int d            = distance[block.Tda << 1 | block.Tdb];
+
+        const R8G8B8A8 paintColors[4] = {
+            createRGBA(r1, g1, b1), createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2, g2, b2),
+            createRGBA(r2 - d, g2 - d, b2 - d),
+        };
+
+        uint8_t *curPixel = dest;
+        for (size_t j = 0; j < 4 && (y + j) < h; j++)
+        {
+            R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+            for (size_t i = 0; i < 4 && (x + i) < w; i++)
+            {
+                row[i]   = paintColors[getIndex(i, j)];
+                row[i].A = alphaValues[j][i];
+            }
+            curPixel += destRowPitch;
+        }
+
+        if (nonOpaquePunchThroughAlpha)
+        {
+            decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
+        }
+    }
+
+    void decodeHBlock(uint8_t *dest,
+                      size_t x,
+                      size_t y,
+                      size_t w,
+                      size_t h,
+                      size_t destRowPitch,
+                      const uint8_t alphaValues[4][4],
+                      bool nonOpaquePunchThroughAlpha) const
+    {
+        // Table C.8, distance index for T and H modes
+        const auto &block = u.idht.mode.hm;
+
+        int r1 = extend_4to8bits(block.HR1);
+        int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b);
+        int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c);
+        int r2 = extend_4to8bits(block.HR2);
+        int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b);
+        int b2 = extend_4to8bits(block.HB2);
+
+        static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+        const int orderingTrickBit =
+            ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0);
+        const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | orderingTrickBit];
+
+        const R8G8B8A8 paintColors[4] = {
+            createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d),
+            createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2 - d, g2 - d, b2 - d),
+        };
+
+        uint8_t *curPixel = dest;
+        for (size_t j = 0; j < 4 && (y + j) < h; j++)
+        {
+            R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+            for (size_t i = 0; i < 4 && (x + i) < w; i++)
+            {
+                row[i]   = paintColors[getIndex(i, j)];
+                row[i].A = alphaValues[j][i];
+            }
+            curPixel += destRowPitch;
+        }
+
+        if (nonOpaquePunchThroughAlpha)
+        {
+            decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
+        }
+    }
+
+    void decodePlanarBlock(uint8_t *dest,
+                           size_t x,
+                           size_t y,
+                           size_t w,
+                           size_t h,
+                           size_t pitch,
+                           const uint8_t alphaValues[4][4]) const
+    {
+        int ro = extend_6to8bits(u.pblk.RO);
+        int go = extend_7to8bits(u.pblk.GO1 << 6 | u.pblk.GO2);
+        int bo =
+            extend_6to8bits(u.pblk.BO1 << 5 | u.pblk.BO2 << 3 | u.pblk.BO3a << 1 | u.pblk.BO3b);
+        int rh = extend_6to8bits(u.pblk.RH1 << 1 | u.pblk.RH2);
+        int gh = extend_7to8bits(u.pblk.GH);
+        int bh = extend_6to8bits(u.pblk.BHa << 5 | u.pblk.BHb);
+        int rv = extend_6to8bits(u.pblk.RVa << 3 | u.pblk.RVb);
+        int gv = extend_7to8bits(u.pblk.GVa << 2 | u.pblk.GVb);
+        int bv = extend_6to8bits(u.pblk.BV);
+
+        uint8_t *curPixel = dest;
+        for (size_t j = 0; j < 4 && (y + j) < h; j++)
+        {
+            R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+
+            int ry = static_cast<int>(j) * (rv - ro) + 2;
+            int gy = static_cast<int>(j) * (gv - go) + 2;
+            int by = static_cast<int>(j) * (bv - bo) + 2;
+            for (size_t i = 0; i < 4 && (x + i) < w; i++)
+            {
+                row[i] = createRGBA(((static_cast<int>(i) * (rh - ro) + ry) >> 2) + ro,
+                                    ((static_cast<int>(i) * (gh - go) + gy) >> 2) + go,
+                                    ((static_cast<int>(i) * (bh - bo) + by) >> 2) + bo,
+                                    alphaValues[j][i]);
+            }
+            curPixel += pitch;
+        }
+    }
+
+    // Index for individual, differential, H and T modes
+    size_t getIndex(size_t x, size_t y) const
+    {
+        size_t bitIndex  = x * 4 + y;
+        size_t bitOffset = bitIndex & 7;
+        size_t lsb       = (u.idht.pixelIndexLSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
+        size_t msb       = (u.idht.pixelIndexMSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
+        return (msb << 1) | lsb;
+    }
+
+    void decodePunchThroughAlphaBlock(uint8_t *dest,
+                                      size_t x,
+                                      size_t y,
+                                      size_t w,
+                                      size_t h,
+                                      size_t destRowPitch) const
+    {
+        uint8_t *curPixel = dest;
+        for (size_t j = 0; j < 4 && (y + j) < h; j++)
+        {
+            R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+            for (size_t i = 0; i < 4 && (x + i) < w; i++)
+            {
+                if (getIndex(i, j) == 2)  //  msb == 1 && lsb == 0
+                {
+                    row[i] = createRGBA(0, 0, 0, 0);
+                }
+            }
+            curPixel += destRowPitch;
+        }
+    }
+
+    uint16_t RGB8ToRGB565(const R8G8B8A8 &rgba) const
+    {
+        return (static_cast<uint16_t>(rgba.R >> 3) << 11) |
+               (static_cast<uint16_t>(rgba.G >> 2) << 5) |
+               (static_cast<uint16_t>(rgba.B >> 3) << 0);
+    }
+
+    uint32_t matchBC1Bits(const int *pixelIndices,
+                          const int *pixelIndexCounts,
+                          const R8G8B8A8 *subblockColors,
+                          size_t numColors,
+                          const R8G8B8A8 &minColor,
+                          const R8G8B8A8 &maxColor,
+                          bool nonOpaquePunchThroughAlpha) const
+    {
+        // Project each pixel on the (maxColor, minColor) line to decide which
+        // BC1 code to assign to it.
+
+        uint8_t decodedColors[2][3] = {{maxColor.R, maxColor.G, maxColor.B},
+                                       {minColor.R, minColor.G, minColor.B}};
+
+        int direction[3];
+        for (int ch = 0; ch < 3; ch++)
+        {
+            direction[ch] = decodedColors[0][ch] - decodedColors[1][ch];
+        }
+
+        int stops[2];
+        for (int i = 0; i < 2; i++)
+        {
+            stops[i] = decodedColors[i][0] * direction[0] + decodedColors[i][1] * direction[1] +
+                       decodedColors[i][2] * direction[2];
+        }
+
+        ASSERT(numColors <= kNumPixelsInBlock);
+
+        int encodedColors[kNumPixelsInBlock];
+        if (nonOpaquePunchThroughAlpha)
+        {
+            for (size_t i = 0; i < numColors; i++)
+            {
+                const int count = pixelIndexCounts[i];
+                if (count > 0)
+                {
+                    // In non-opaque mode, 3 is for tranparent pixels.
+
+                    if (0 == subblockColors[i].A)
+                    {
+                        encodedColors[i] = 3;
+                    }
+                    else
+                    {
+                        const R8G8B8A8 &pixel = subblockColors[i];
+                        const int dot         = pixel.R * direction[0] + pixel.G * direction[1] +
+                                        pixel.B * direction[2];
+                        const int factor = gl::clamp(
+                            static_cast<int>(
+                                (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 2 +
+                                0.5f),
+                            0, 2);
+                        switch (factor)
+                        {
+                            case 0:
+                                encodedColors[i] = 0;
+                                break;
+                            case 1:
+                                encodedColors[i] = 2;
+                                break;
+                            case 2:
+                            default:
+                                encodedColors[i] = 1;
+                                break;
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+            for (size_t i = 0; i < numColors; i++)
+            {
+                const int count = pixelIndexCounts[i];
+                if (count > 0)
+                {
+                    // In opaque mode, the code is from 0 to 3.
+
+                    const R8G8B8A8 &pixel = subblockColors[i];
+                    const int dot =
+                        pixel.R * direction[0] + pixel.G * direction[1] + pixel.B * direction[2];
+                    const int factor = gl::clamp(
+                        static_cast<int>(
+                            (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 3 +
+                            0.5f),
+                        0, 3);
+                    switch (factor)
+                    {
+                        case 0:
+                            encodedColors[i] = 1;
+                            break;
+                        case 1:
+                            encodedColors[i] = 3;
+                            break;
+                        case 2:
+                            encodedColors[i] = 2;
+                            break;
+                        case 3:
+                        default:
+                            encodedColors[i] = 0;
+                            break;
+                    }
+                }
+            }
+        }
+
+        uint32_t bits = 0;
+        for (int i = kNumPixelsInBlock - 1; i >= 0; i--)
+        {
+            bits <<= 2;
+            bits |= encodedColors[pixelIndices[i]];
+        }
+
+        return bits;
+    }
+
+    void packBC1(void *bc1,
+                 const int *pixelIndices,
+                 const int *pixelIndexCounts,
+                 const R8G8B8A8 *subblockColors,
+                 size_t numColors,
+                 int minColorIndex,
+                 int maxColorIndex,
+                 bool nonOpaquePunchThroughAlpha) const
+    {
+        const R8G8B8A8 &minColor = subblockColors[minColorIndex];
+        const R8G8B8A8 &maxColor = subblockColors[maxColorIndex];
+
+        uint32_t bits;
+        uint16_t max16 = RGB8ToRGB565(maxColor);
+        uint16_t min16 = RGB8ToRGB565(minColor);
+        if (max16 != min16)
+        {
+            // Find the best BC1 code for each pixel
+            bits = matchBC1Bits(pixelIndices, pixelIndexCounts, subblockColors, numColors, minColor,
+                                maxColor, nonOpaquePunchThroughAlpha);
+        }
+        else
+        {
+            // Same colors, BC1 index 0 is the color in both opaque and transparent mode
+            bits = 0;
+            // BC1 index 3 is transparent
+            if (nonOpaquePunchThroughAlpha)
+            {
+                for (int i = 0; i < kNumPixelsInBlock; i++)
+                {
+                    if (0 == subblockColors[pixelIndices[i]].A)
+                    {
+                        bits |= (3 << (i * 2));
+                    }
+                }
+            }
+        }
+
+        if (max16 < min16)
+        {
+            std::swap(max16, min16);
+
+            uint32_t xorMask = 0;
+            if (nonOpaquePunchThroughAlpha)
+            {
+                // In transparent mode switching the colors is doing the
+                // following code swap: 0 <-> 1. 0xA selects the second bit of
+                // each code, bits >> 1 selects the first bit of the code when
+                // the seconds bit is set (case 2 and 3). We invert all the
+                // non-selected bits, that is the first bit when the code is
+                // 0 or 1.
+                xorMask = ~((bits >> 1) | 0xAAAAAAAA);
+            }
+            else
+            {
+                // In opaque mode switching the two colors is doing the
+                // following code swaps: 0 <-> 1 and 2 <-> 3. This is
+                // equivalent to flipping the first bit of each code
+                // (5 = 0b0101)
+                xorMask = 0x55555555;
+            }
+            bits ^= xorMask;
+        }
+
+        struct BC1Block
+        {
+            uint16_t color0;
+            uint16_t color1;
+            uint32_t bits;
+        };
+
+        // Encode the opaqueness in the order of the two BC1 colors
+        BC1Block *dest = reinterpret_cast<BC1Block *>(bc1);
+        if (nonOpaquePunchThroughAlpha)
+        {
+            dest->color0 = min16;
+            dest->color1 = max16;
+        }
+        else
+        {
+            dest->color0 = max16;
+            dest->color1 = min16;
+        }
+        dest->bits = bits;
+    }
+
+    void transcodeIndividualBlockToBC1(uint8_t *dest,
+                                       size_t x,
+                                       size_t y,
+                                       size_t w,
+                                       size_t h,
+                                       const uint8_t alphaValues[4][4],
+                                       bool nonOpaquePunchThroughAlpha) const
+    {
+        const auto &block = u.idht.mode.idm.colors.indiv;
+        int r1            = extend_4to8bits(block.R1);
+        int g1            = extend_4to8bits(block.G1);
+        int b1            = extend_4to8bits(block.B1);
+        int r2            = extend_4to8bits(block.R2);
+        int g2            = extend_4to8bits(block.G2);
+        int b2            = extend_4to8bits(block.B2);
+        transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2,
+                                                    alphaValues, nonOpaquePunchThroughAlpha);
+    }
+
+    void transcodeDifferentialBlockToBC1(uint8_t *dest,
+                                         size_t x,
+                                         size_t y,
+                                         size_t w,
+                                         size_t h,
+                                         const uint8_t alphaValues[4][4],
+                                         bool nonOpaquePunchThroughAlpha) const
+    {
+        const auto &block = u.idht.mode.idm.colors.diff;
+        int b1            = extend_5to8bits(block.B);
+        int g1            = extend_5to8bits(block.G);
+        int r1            = extend_5to8bits(block.R);
+        int r2            = extend_5to8bits(block.R + block.dR);
+        int g2            = extend_5to8bits(block.G + block.dG);
+        int b2            = extend_5to8bits(block.B + block.dB);
+        transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2,
+                                                    alphaValues, nonOpaquePunchThroughAlpha);
+    }
+
+    void extractPixelIndices(int *pixelIndices,
+                             int *pixelIndicesCounts,
+                             size_t x,
+                             size_t y,
+                             size_t w,
+                             size_t h,
+                             bool flipbit,
+                             size_t subblockIdx) const
+    {
+        size_t dxBegin = 0;
+        size_t dxEnd   = 4;
+        size_t dyBegin = subblockIdx * 2;
+        size_t dyEnd   = dyBegin + 2;
+        if (!flipbit)
+        {
+            std::swap(dxBegin, dyBegin);
+            std::swap(dxEnd, dyEnd);
+        }
+
+        for (size_t j = dyBegin; j < dyEnd; j++)
+        {
+            int *row = &pixelIndices[j * 4];
+            for (size_t i = dxBegin; i < dxEnd; i++)
+            {
+                const size_t pixelIndex = subblockIdx * 4 + getIndex(i, j);
+                row[i]                  = static_cast<int>(pixelIndex);
+                pixelIndicesCounts[pixelIndex]++;
+            }
+        }
+    }
+
+    void selectEndPointPCA(const int *pixelIndexCounts,
+                           const R8G8B8A8 *subblockColors,
+                           size_t numColors,
+                           int *minColorIndex,
+                           int *maxColorIndex) const
+    {
+        // determine color distribution
+        int mu[3], min[3], max[3];
+        for (int ch = 0; ch < 3; ch++)
+        {
+            int muv  = 0;
+            int minv = 255;
+            int maxv = 0;
+            for (size_t i = 0; i < numColors; i++)
+            {
+                const int count = pixelIndexCounts[i];
+                if (count > 0)
+                {
+                    const auto &pixel = subblockColors[i];
+                    if (pixel.A > 0)
+                    {
+                        // Non-transparent pixels
+                        muv += (&pixel.R)[ch] * count;
+                        minv = std::min<int>(minv, (&pixel.R)[ch]);
+                        maxv = std::max<int>(maxv, (&pixel.R)[ch]);
+                    }
+                }
+            }
+
+            mu[ch]  = (muv + kNumPixelsInBlock / 2) / kNumPixelsInBlock;
+            min[ch] = minv;
+            max[ch] = maxv;
+        }
+
+        // determine covariance matrix
+        int cov[6] = {0, 0, 0, 0, 0, 0};
+        for (size_t i = 0; i < numColors; i++)
+        {
+            const int count = pixelIndexCounts[i];
+            if (count > 0)
+            {
+                const auto &pixel = subblockColors[i];
+                if (pixel.A > 0)
+                {
+                    int r = pixel.R - mu[0];
+                    int g = pixel.G - mu[1];
+                    int b = pixel.B - mu[2];
+
+                    cov[0] += r * r * count;
+                    cov[1] += r * g * count;
+                    cov[2] += r * b * count;
+                    cov[3] += g * g * count;
+                    cov[4] += g * b * count;
+                    cov[5] += b * b * count;
+                }
+            }
+        }
+
+        // Power iteration algorithm to get the eigenvalues and eigenvector
+
+        // Starts with diagonal vector
+        float vfr = static_cast<float>(max[0] - min[0]);
+        float vfg = static_cast<float>(max[1] - min[1]);
+        float vfb = static_cast<float>(max[2] - min[2]);
+        float eigenvalue;
+
+        static const size_t kPowerIterations = 4;
+        for (size_t i = 0; i < kPowerIterations; i++)
+        {
+            float r = vfr * cov[0] + vfg * cov[1] + vfb * cov[2];
+            float g = vfr * cov[1] + vfg * cov[3] + vfb * cov[4];
+            float b = vfr * cov[2] + vfg * cov[4] + vfb * cov[5];
+
+            vfr = r;
+            vfg = g;
+            vfb = b;
+
+            eigenvalue = sqrt(r * r + g * g + b * b);
+            if (eigenvalue > 0)
+            {
+                float invNorm = 1.0f / eigenvalue;
+                vfr *= invNorm;
+                vfg *= invNorm;
+                vfb *= invNorm;
+            }
+        }
+
+        int vr, vg, vb;
+
+        static const float kDefaultLuminanceThreshold = 4.0f * 255;
+        static const float kQuantizeRange             = 512.0f;
+        if (eigenvalue < kDefaultLuminanceThreshold)  // too small, default to luminance
+        {
+            // Luminance weights defined by ITU-R Recommendation BT.601, scaled by 1000
+            vr = 299;
+            vg = 587;
+            vb = 114;
+        }
+        else
+        {
+            // From the eigenvalue and eigenvector, choose the axis to project
+            // colors on. When projecting colors we want to do integer computations
+            // for speed, so we normalize the eigenvector to the [0, 512] range.
+            float magn = std::max(std::max(std::abs(vfr), std::abs(vfg)), std::abs(vfb));
+            magn       = kQuantizeRange / magn;
+            vr         = static_cast<int>(vfr * magn);
+            vg         = static_cast<int>(vfg * magn);
+            vb         = static_cast<int>(vfb * magn);
+        }
+
+        // Pick colors at extreme points
+        int minD        = INT_MAX;
+        int maxD        = 0;
+        size_t minIndex = 0;
+        size_t maxIndex = 0;
+        for (size_t i = 0; i < numColors; i++)
+        {
+            const int count = pixelIndexCounts[i];
+            if (count > 0)
+            {
+                const auto &pixel = subblockColors[i];
+                if (pixel.A > 0)
+                {
+                    int dot = pixel.R * vr + pixel.G * vg + pixel.B * vb;
+                    if (dot < minD)
+                    {
+                        minD     = dot;
+                        minIndex = i;
+                    }
+                    if (dot > maxD)
+                    {
+                        maxD     = dot;
+                        maxIndex = i;
+                    }
+                }
+            }
+        }
+
+        *minColorIndex = static_cast<int>(minIndex);
+        *maxColorIndex = static_cast<int>(maxIndex);
+    }
+
+    void transcodeIndividualOrDifferentialBlockToBC1(uint8_t *dest,
+                                                     size_t x,
+                                                     size_t y,
+                                                     size_t w,
+                                                     size_t h,
+                                                     int r1,
+                                                     int g1,
+                                                     int b1,
+                                                     int r2,
+                                                     int g2,
+                                                     int b2,
+                                                     const uint8_t alphaValues[4][4],
+                                                     bool nonOpaquePunchThroughAlpha) const
+    {
+        // A BC1 block has 2 endpoints, pixels is encoded as linear
+        // interpolations of them. A ETC1/ETC2 individual or differential block
+        // has 2 subblocks. Each subblock has one color and a modifier. We
+        // select axis by principal component analysis (PCA) to use as
+        // our two BC1 endpoints and then map pixels to BC1 by projecting on the
+        // line between the two endpoints and choosing the right fraction.
+
+        // The goal of this algorithm is make it faster than decode ETC to RGBs
+        //   and then encode to BC. To achieve this, we only extract subblock
+        //   colors, pixel indices, and counts of each pixel indices from ETC.
+        //   With those information, we can only encode used subblock colors
+        //   to BC1, and copy the bits to the right pixels.
+        // Fully decode and encode need to process 16 RGBA pixels. With this
+        //   algorithm, it's 8 pixels at maximum for a individual or
+        //   differential block. Saves us bandwidth and computations.
+
+        static const size_t kNumColors = 8;
+
+        const auto intensityModifier =
+            nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
+
+        // Compute the colors that pixels can have in each subblock both for
+        // the decoding of the RGBA data and BC1 encoding
+        R8G8B8A8 subblockColors[kNumColors];
+        for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++)
+        {
+            if (nonOpaquePunchThroughAlpha && (modifierIdx == 2))
+            {
+                // In ETC opaque punch through formats, individual and
+                // differential blocks take index 2 as transparent pixel.
+                // Thus we don't need to compute its color, just assign it
+                // as black.
+                subblockColors[modifierIdx]     = createRGBA(0, 0, 0, 0);
+                subblockColors[4 + modifierIdx] = createRGBA(0, 0, 0, 0);
+            }
+            else
+            {
+                const int i1                = intensityModifier[u.idht.mode.idm.cw1][modifierIdx];
+                subblockColors[modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1);
+
+                const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx];
+                subblockColors[4 + modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2);
+            }
+        }
+
+        int pixelIndices[kNumPixelsInBlock];
+        int pixelIndexCounts[kNumColors] = {0};
+        // Extract pixel indices from a ETC block.
+        for (size_t blockIdx = 0; blockIdx < 2; blockIdx++)
+        {
+            extractPixelIndices(pixelIndices, pixelIndexCounts, x, y, w, h, u.idht.mode.idm.flipbit,
+                                blockIdx);
+        }
+
+        int minColorIndex, maxColorIndex;
+        selectEndPointPCA(pixelIndexCounts, subblockColors, kNumColors, &minColorIndex,
+                          &maxColorIndex);
+
+        packBC1(dest, pixelIndices, pixelIndexCounts, subblockColors, kNumColors, minColorIndex,
+                maxColorIndex, nonOpaquePunchThroughAlpha);
+    }
+
+    void transcodeTBlockToBC1(uint8_t *dest,
+                              size_t x,
+                              size_t y,
+                              size_t w,
+                              size_t h,
+                              const uint8_t alphaValues[4][4],
+                              bool nonOpaquePunchThroughAlpha) const
+    {
+        static const size_t kNumColors = 4;
+
+        // Table C.8, distance index for T and H modes
+        const auto &block = u.idht.mode.tm;
+
+        int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b);
+        int g1 = extend_4to8bits(block.TG1);
+        int b1 = extend_4to8bits(block.TB1);
+        int r2 = extend_4to8bits(block.TR2);
+        int g2 = extend_4to8bits(block.TG2);
+        int b2 = extend_4to8bits(block.TB2);
+
+        static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+        const int d            = distance[block.Tda << 1 | block.Tdb];
+
+        // In ETC opaque punch through formats, index == 2 means transparent pixel.
+        // Thus we don't need to compute its color, just assign it as black.
+        const R8G8B8A8 paintColors[kNumColors] = {
+            createRGBA(r1, g1, b1), createRGBA(r2 + d, g2 + d, b2 + d),
+            nonOpaquePunchThroughAlpha ? createRGBA(0, 0, 0, 0) : createRGBA(r2, g2, b2),
+            createRGBA(r2 - d, g2 - d, b2 - d),
+        };
+
+        int pixelIndices[kNumPixelsInBlock];
+        int pixelIndexCounts[kNumColors] = {0};
+        for (size_t j = 0; j < 4; j++)
+        {
+            int *row = &pixelIndices[j * 4];
+            for (size_t i = 0; i < 4; i++)
+            {
+                const size_t pixelIndex = getIndex(i, j);
+                row[i]                  = static_cast<int>(pixelIndex);
+                pixelIndexCounts[pixelIndex]++;
+            }
+        }
+
+        int minColorIndex, maxColorIndex;
+        selectEndPointPCA(pixelIndexCounts, paintColors, kNumColors, &minColorIndex,
+                          &maxColorIndex);
+
+        packBC1(dest, pixelIndices, pixelIndexCounts, paintColors, kNumColors, minColorIndex,
+                maxColorIndex, nonOpaquePunchThroughAlpha);
+    }
+
+    void transcodeHBlockToBC1(uint8_t *dest,
+                              size_t x,
+                              size_t y,
+                              size_t w,
+                              size_t h,
+                              const uint8_t alphaValues[4][4],
+                              bool nonOpaquePunchThroughAlpha) const
+    {
+        static const size_t kNumColors = 4;
+
+        // Table C.8, distance index for T and H modes
+        const auto &block = u.idht.mode.hm;
+
+        int r1 = extend_4to8bits(block.HR1);
+        int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b);
+        int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c);
+        int r2 = extend_4to8bits(block.HR2);
+        int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b);
+        int b2 = extend_4to8bits(block.HB2);
+
+        static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+        const int orderingTrickBit =
+            ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0);
+        const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | orderingTrickBit];
+
+        // In ETC opaque punch through formats, index == 2 means transparent pixel.
+        // Thus we don't need to compute its color, just assign it as black.
+        const R8G8B8A8 paintColors[kNumColors] = {
+            createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d),
+            nonOpaquePunchThroughAlpha ? createRGBA(0, 0, 0, 0)
+                                       : createRGBA(r2 + d, g2 + d, b2 + d),
+            createRGBA(r2 - d, g2 - d, b2 - d),
+        };
+
+        int pixelIndices[kNumPixelsInBlock];
+        int pixelIndexCounts[kNumColors] = {0};
+        for (size_t j = 0; j < 4; j++)
+        {
+            int *row = &pixelIndices[j * 4];
+            for (size_t i = 0; i < 4; i++)
+            {
+                const size_t pixelIndex = getIndex(i, j);
+                row[i]                  = static_cast<int>(pixelIndex);
+                pixelIndexCounts[pixelIndex]++;
+            }
+        }
+
+        int minColorIndex, maxColorIndex;
+        selectEndPointPCA(pixelIndexCounts, paintColors, kNumColors, &minColorIndex,
+                          &maxColorIndex);
+
+        packBC1(dest, pixelIndices, pixelIndexCounts, paintColors, kNumColors, minColorIndex,
+                maxColorIndex, nonOpaquePunchThroughAlpha);
+    }
+
+    void transcodePlanarBlockToBC1(uint8_t *dest,
+                                   size_t x,
+                                   size_t y,
+                                   size_t w,
+                                   size_t h,
+                                   const uint8_t alphaValues[4][4]) const
+    {
+        static const size_t kNumColors = kNumPixelsInBlock;
+
+        R8G8B8A8 rgbaBlock[kNumColors];
+        decodePlanarBlock(reinterpret_cast<uint8_t *>(rgbaBlock), x, y, w, h, sizeof(R8G8B8A8) * 4,
+                          alphaValues);
+
+        // Planar block doesn't have a color table, fill indices as full
+        int pixelIndices[kNumPixelsInBlock] = {0, 1, 2,  3,  4,  5,  6,  7,
+                                               8, 9, 10, 11, 12, 13, 14, 15};
+        int pixelIndexCounts[kNumColors] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+
+        int minColorIndex, maxColorIndex;
+        selectEndPointPCA(pixelIndexCounts, rgbaBlock, kNumColors, &minColorIndex, &maxColorIndex);
+
+        packBC1(dest, pixelIndices, pixelIndexCounts, rgbaBlock, kNumColors, minColorIndex,
+                maxColorIndex, false);
+    }
+
+    // Single channel utility functions
+    int getSingleChannel(size_t x, size_t y, bool isSigned) const
+    {
+        int codeword = isSigned ? u.scblk.base_codeword.s : u.scblk.base_codeword.us;
+        return codeword + getSingleChannelModifier(x, y) * u.scblk.multiplier;
+    }
+
+    int getSingleChannelIndex(size_t x, size_t y) const
+    {
+        ASSERT(x < 4 && y < 4);
+
+        // clang-format off
+        switch (x * 4 + y)
+        {
+            case 0: return u.scblk.ma;
+            case 1: return u.scblk.mb;
+            case 2: return u.scblk.mc1 << 1 | u.scblk.mc2;
+            case 3: return u.scblk.md;
+            case 4: return u.scblk.me;
+            case 5: return u.scblk.mf1 << 2 | u.scblk.mf2;
+            case 6: return u.scblk.mg;
+            case 7: return u.scblk.mh;
+            case 8: return u.scblk.mi;
+            case 9: return u.scblk.mj;
+            case 10: return u.scblk.mk1 << 1 | u.scblk.mk2;
+            case 11: return u.scblk.ml;
+            case 12: return u.scblk.mm;
+            case 13: return u.scblk.mn1 << 2 | u.scblk.mn2;
+            case 14: return u.scblk.mo;
+            case 15: return u.scblk.mp;
+            default: UNREACHABLE(); return 0;
+        }
+        // clang-format on
+    }
+
+    int getSingleChannelModifier(size_t x, size_t y) const
+    {
+        // clang-format off
+        static const int modifierTable[16][8] =
+        {
+            { -3, -6,  -9, -15, 2, 5, 8, 14 },
+            { -3, -7, -10, -13, 2, 6, 9, 12 },
+            { -2, -5,  -8, -13, 1, 4, 7, 12 },
+            { -2, -4,  -6, -13, 1, 3, 5, 12 },
+            { -3, -6,  -8, -12, 2, 5, 7, 11 },
+            { -3, -7,  -9, -11, 2, 6, 8, 10 },
+            { -4, -7,  -8, -11, 3, 6, 7, 10 },
+            { -3, -5,  -8, -11, 2, 4, 7, 10 },
+            { -2, -6,  -8, -10, 1, 5, 7,  9 },
+            { -2, -5,  -8, -10, 1, 4, 7,  9 },
+            { -2, -4,  -8, -10, 1, 3, 7,  9 },
+            { -2, -5,  -7, -10, 1, 4, 6,  9 },
+            { -3, -4,  -7, -10, 2, 3, 6,  9 },
+            { -1, -2,  -3, -10, 0, 1, 2,  9 },
+            { -4, -6,  -8,  -9, 3, 5, 7,  8 },
+            { -3, -5,  -7,  -9, 2, 4, 6,  8 }
+        };
+        // clang-format on
+
+        return modifierTable[u.scblk.table_index][getSingleChannelIndex(x, y)];
+    }
+};
+
+// clang-format off
+static const uint8_t DefaultETCAlphaValues[4][4] =
+{
+    { 255, 255, 255, 255 },
+    { 255, 255, 255, 255 },
+    { 255, 255, 255, 255 },
+    { 255, 255, 255, 255 },
+};
+// clang-format on
+
+void LoadR11EACToR8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch,
+                    bool isSigned)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y += 4)
+        {
+            const ETC2Block *sourceRow =
+                priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+            uint8_t *destRow =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+            for (size_t x = 0; x < width; x += 4)
+            {
+                const ETC2Block *sourceBlock = sourceRow + (x / 4);
+                uint8_t *destPixels          = destRow + x;
+
+                sourceBlock->decodeAsSingleChannel(destPixels, x, y, width, height, 1,
+                                                   outputRowPitch, isSigned);
+            }
+        }
+    }
+}
+
+void LoadRG11EACToRG8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch,
+                      bool isSigned)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y += 4)
+        {
+            const ETC2Block *sourceRow =
+                priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+            uint8_t *destRow =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+            for (size_t x = 0; x < width; x += 4)
+            {
+                uint8_t *destPixelsRed          = destRow + (x * 2);
+                const ETC2Block *sourceBlockRed = sourceRow + (x / 2);
+                sourceBlockRed->decodeAsSingleChannel(destPixelsRed, x, y, width, height, 2,
+                                                      outputRowPitch, isSigned);
+
+                uint8_t *destPixelsGreen          = destPixelsRed + 1;
+                const ETC2Block *sourceBlockGreen = sourceBlockRed + 1;
+                sourceBlockGreen->decodeAsSingleChannel(destPixelsGreen, x, y, width, height, 2,
+                                                        outputRowPitch, isSigned);
+            }
+        }
+    }
+}
+
+void LoadETC2RGB8ToRGBA8(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch,
+                         bool punchthroughAlpha)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y += 4)
+        {
+            const ETC2Block *sourceRow =
+                priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+            uint8_t *destRow =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+            for (size_t x = 0; x < width; x += 4)
+            {
+                const ETC2Block *sourceBlock = sourceRow + (x / 4);
+                uint8_t *destPixels          = destRow + (x * 4);
+
+                sourceBlock->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
+                                         DefaultETCAlphaValues, punchthroughAlpha);
+            }
+        }
+    }
+}
+
+void LoadETC2RGB8ToBC1(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch,
+                       bool punchthroughAlpha)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y += 4)
+        {
+            const ETC2Block *sourceRow =
+                priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+            uint8_t *destRow = priv::OffsetDataPointer<uint8_t>(output, y / 4, z, outputRowPitch,
+                                                                outputDepthPitch);
+
+            for (size_t x = 0; x < width; x += 4)
+            {
+                const ETC2Block *sourceBlock = sourceRow + (x / 4);
+                uint8_t *destPixels          = destRow + (x * 2);
+
+                sourceBlock->transcodeAsBC1(destPixels, x, y, width, height, DefaultETCAlphaValues,
+                                            punchthroughAlpha);
+            }
+        }
+    }
+}
+
+void LoadETC2RGBA8ToRGBA8(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch,
+                          bool srgb)
+{
+    uint8_t decodedAlphaValues[4][4];
+
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y += 4)
+        {
+            const ETC2Block *sourceRow =
+                priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+            uint8_t *destRow =
+                priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+            for (size_t x = 0; x < width; x += 4)
+            {
+                const ETC2Block *sourceBlockAlpha = sourceRow + (x / 2);
+                sourceBlockAlpha->decodeAsSingleChannel(
+                    reinterpret_cast<uint8_t *>(decodedAlphaValues), x, y, width, height, 1, 4,
+                    false);
+
+                uint8_t *destPixels             = destRow + (x * 4);
+                const ETC2Block *sourceBlockRGB = sourceBlockAlpha + 1;
+                sourceBlockRGB->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
+                                            decodedAlphaValues, false);
+            }
+        }
+    }
+}
+
+}  // anonymous namespace
+
+void LoadETC1RGB8ToRGBA8(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                        outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC1RGB8ToBC1(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                      outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadEACR11ToR8(size_t width,
+                    size_t height,
+                    size_t depth,
+                    const uint8_t *input,
+                    size_t inputRowPitch,
+                    size_t inputDepthPitch,
+                    uint8_t *output,
+                    size_t outputRowPitch,
+                    size_t outputDepthPitch)
+{
+    LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                   outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadEACR11SToR8(size_t width,
+                     size_t height,
+                     size_t depth,
+                     const uint8_t *input,
+                     size_t inputRowPitch,
+                     size_t inputDepthPitch,
+                     uint8_t *output,
+                     size_t outputRowPitch,
+                     size_t outputDepthPitch)
+{
+    LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                   outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadEACRG11ToRG8(size_t width,
+                      size_t height,
+                      size_t depth,
+                      const uint8_t *input,
+                      size_t inputRowPitch,
+                      size_t inputDepthPitch,
+                      uint8_t *output,
+                      size_t outputRowPitch,
+                      size_t outputDepthPitch)
+{
+    LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                     outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadEACRG11SToRG8(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                     outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2RGB8ToRGBA8(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                        outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2RGB8ToBC1(size_t width,
+                       size_t height,
+                       size_t depth,
+                       const uint8_t *input,
+                       size_t inputRowPitch,
+                       size_t inputDepthPitch,
+                       uint8_t *output,
+                       size_t outputRowPitch,
+                       size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                      outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2SRGB8ToRGBA8(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                        outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2SRGB8ToBC1(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                      outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2RGB8A1ToRGBA8(size_t width,
+                           size_t height,
+                           size_t depth,
+                           const uint8_t *input,
+                           size_t inputRowPitch,
+                           size_t inputDepthPitch,
+                           uint8_t *output,
+                           size_t outputRowPitch,
+                           size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                        outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2RGB8A1ToBC1(size_t width,
+                         size_t height,
+                         size_t depth,
+                         const uint8_t *input,
+                         size_t inputRowPitch,
+                         size_t inputDepthPitch,
+                         uint8_t *output,
+                         size_t outputRowPitch,
+                         size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                      outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2SRGB8A1ToRGBA8(size_t width,
+                            size_t height,
+                            size_t depth,
+                            const uint8_t *input,
+                            size_t inputRowPitch,
+                            size_t inputDepthPitch,
+                            uint8_t *output,
+                            size_t outputRowPitch,
+                            size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                        outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2SRGB8A1ToBC1(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch)
+{
+    LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                      outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2RGBA8ToRGBA8(size_t width,
+                          size_t height,
+                          size_t depth,
+                          const uint8_t *input,
+                          size_t inputRowPitch,
+                          size_t inputDepthPitch,
+                          uint8_t *output,
+                          size_t outputRowPitch,
+                          size_t outputDepthPitch)
+{
+    LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                         outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2SRGBA8ToSRGBA8(size_t width,
+                            size_t height,
+                            size_t depth,
+                            const uint8_t *input,
+                            size_t inputRowPitch,
+                            size_t inputDepthPitch,
+                            uint8_t *output,
+                            size_t outputRowPitch,
+                            size_t outputDepthPitch)
+{
+    LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+                         outputRowPitch, outputDepthPitch, true);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/libANGLE/AttributeMap.cpp b/src/third_party/angle/src/libANGLE/AttributeMap.cpp
new file mode 100644
index 0000000..dc450b8
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/AttributeMap.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/AttributeMap.h"
+
+namespace egl
+{
+
+AttributeMap::AttributeMap()
+{
+}
+
+void AttributeMap::insert(EGLAttrib key, EGLAttrib value)
+{
+    mAttributes[key] = value;
+}
+
+bool AttributeMap::contains(EGLAttrib key) const
+{
+    return (mAttributes.find(key) != mAttributes.end());
+}
+
+EGLAttrib AttributeMap::get(EGLAttrib key, EGLAttrib defaultValue) const
+{
+    auto iter = mAttributes.find(key);
+    return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue;
+}
+
+EGLint AttributeMap::getAsInt(EGLAttrib key, EGLint defaultValue) const
+{
+    return static_cast<EGLint>(get(key, static_cast<EGLAttrib>(defaultValue)));
+}
+
+bool AttributeMap::isEmpty() const
+{
+    return mAttributes.empty();
+}
+
+std::vector<EGLint> AttributeMap::toIntVector() const
+{
+    std::vector<EGLint> ret;
+    for (const auto &pair : mAttributes)
+    {
+        ret.push_back(static_cast<EGLint>(pair.first));
+        ret.push_back(static_cast<EGLint>(pair.second));
+    }
+    ret.push_back(EGL_NONE);
+
+    return ret;
+}
+
+AttributeMap::const_iterator AttributeMap::begin() const
+{
+    return mAttributes.begin();
+}
+
+AttributeMap::const_iterator AttributeMap::end() const
+{
+    return mAttributes.end();
+}
+
+// static
+AttributeMap AttributeMap::CreateFromIntArray(const EGLint *attributes)
+{
+    AttributeMap map;
+    if (attributes)
+    {
+        for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
+        {
+            map.insert(static_cast<EGLAttrib>(curAttrib[0]), static_cast<EGLAttrib>(curAttrib[1]));
+        }
+    }
+    return map;
+}
+
+// static
+AttributeMap AttributeMap::CreateFromAttribArray(const EGLAttrib *attributes)
+{
+    AttributeMap map;
+    if (attributes)
+    {
+        for (const EGLAttrib *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
+        {
+            map.insert(curAttrib[0], curAttrib[1]);
+        }
+    }
+    return map;
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/AttributeMap.h b/src/third_party/angle/src/libANGLE/AttributeMap.h
new file mode 100644
index 0000000..01bba74
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/AttributeMap.h
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_ATTRIBUTEMAP_H_
+#define LIBANGLE_ATTRIBUTEMAP_H_
+
+
+#include <EGL/egl.h>
+
+#include <map>
+#include <vector>
+
+namespace egl
+{
+
+class AttributeMap final
+{
+  public:
+    AttributeMap();
+
+    void insert(EGLAttrib key, EGLAttrib value);
+    bool contains(EGLAttrib key) const;
+    EGLAttrib get(EGLAttrib key, EGLAttrib defaultValue) const;
+    EGLint getAsInt(EGLAttrib key, EGLint defaultValue) const;
+    bool isEmpty() const;
+    std::vector<EGLint> toIntVector() const;
+
+    typedef std::map<EGLAttrib, EGLAttrib>::const_iterator const_iterator;
+
+    const_iterator begin() const;
+    const_iterator end() const;
+
+    static AttributeMap CreateFromIntArray(const EGLint *attributes);
+    static AttributeMap CreateFromAttribArray(const EGLAttrib *attributes);
+
+  private:
+    std::map<EGLAttrib, EGLAttrib> mAttributes;
+};
+
+}
+
+#endif   // LIBANGLE_ATTRIBUTEMAP_H_
diff --git a/src/third_party/angle/src/libANGLE/BinaryStream.h b/src/third_party/angle/src/libANGLE/BinaryStream.h
new file mode 100644
index 0000000..c195e9d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/BinaryStream.h
@@ -0,0 +1,235 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BinaryStream.h: Provides binary serialization of simple types.
+
+#ifndef LIBANGLE_BINARYSTREAM_H_
+#define LIBANGLE_BINARYSTREAM_H_
+
+#include <cstddef>
+#include <string>
+#include <vector>
+#include <stdint.h>
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+
+namespace gl
+{
+
+class BinaryInputStream : angle::NonCopyable
+{
+  public:
+    BinaryInputStream(const void *data, size_t length)
+    {
+        mError = false;
+        mOffset = 0;
+        mData = static_cast<const uint8_t*>(data);
+        mLength = length;
+    }
+
+    // readInt will generate an error for bool types
+    template <class IntT>
+    IntT readInt()
+    {
+        int value = 0;
+        read(&value);
+        return static_cast<IntT>(value);
+    }
+
+    template <class IntT>
+    void readInt(IntT *outValue)
+    {
+        *outValue = readInt<IntT>();
+    }
+
+    bool readBool()
+    {
+        int value = 0;
+        read(&value);
+        return (value > 0);
+    }
+
+    void readBool(bool *outValue)
+    {
+        *outValue = readBool();
+    }
+
+    void readBytes(unsigned char outArray[], size_t count)
+    {
+        read<unsigned char>(outArray, count);
+    }
+
+    std::string readString()
+    {
+        std::string outString;
+        readString(&outString);
+        return outString;
+    }
+
+    void readString(std::string *v)
+    {
+        size_t length;
+        readInt(&length);
+
+        if (mError)
+        {
+            return;
+        }
+
+        angle::CheckedNumeric<size_t> checkedOffset(mOffset);
+        checkedOffset += length;
+
+        if (!checkedOffset.IsValid() || mOffset + length > mLength)
+        {
+            mError = true;
+            return;
+        }
+
+        v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
+        mOffset = checkedOffset.ValueOrDie();
+    }
+
+    void skip(size_t length)
+    {
+        angle::CheckedNumeric<size_t> checkedOffset(mOffset);
+        checkedOffset += length;
+
+        if (!checkedOffset.IsValid() || mOffset + length > mLength)
+        {
+            mError = true;
+            return;
+        }
+
+        mOffset = checkedOffset.ValueOrDie();
+    }
+
+    size_t offset() const
+    {
+        return mOffset;
+    }
+
+    bool error() const
+    {
+        return mError;
+    }
+
+    bool endOfStream() const
+    {
+        return mOffset == mLength;
+    }
+
+    const uint8_t *data()
+    {
+        return mData;
+    }
+
+  private:
+    bool mError;
+    size_t mOffset;
+    const uint8_t *mData;
+    size_t mLength;
+
+    template <typename T>
+    void read(T *v, size_t num)
+    {
+        static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
+
+        angle::CheckedNumeric<size_t> checkedLength(num);
+        checkedLength *= sizeof(T);
+        if (!checkedLength.IsValid())
+        {
+            mError = true;
+            return;
+        }
+
+        angle::CheckedNumeric<size_t> checkedOffset(mOffset);
+        checkedOffset += checkedLength;
+
+        if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mLength)
+        {
+            mError = true;
+            return;
+        }
+
+        memcpy(v, mData + mOffset, checkedLength.ValueOrDie());
+        mOffset = checkedOffset.ValueOrDie();
+    }
+
+    template <typename T>
+    void read(T *v)
+    {
+        read(v, 1);
+    }
+
+};
+
+class BinaryOutputStream : angle::NonCopyable
+{
+  public:
+    BinaryOutputStream()
+    {
+    }
+
+    // writeInt also handles bool types
+    template <class IntT>
+    void writeInt(IntT param)
+    {
+        ASSERT(angle::IsValueInRangeForNumericType<int>(param));
+        int intValue = static_cast<int>(param);
+        write(&intValue, 1);
+    }
+
+    // Specialized writeInt for values that can also be exactly -1.
+    template <class UintT>
+    void writeIntOrNegOne(UintT param)
+    {
+        if (param == static_cast<UintT>(-1))
+        {
+            writeInt(-1);
+        }
+        else
+        {
+            writeInt(param);
+        }
+    }
+
+    void writeString(const std::string &v)
+    {
+        writeInt(v.length());
+        write(v.c_str(), v.length());
+    }
+
+    void writeBytes(const unsigned char *bytes, size_t count)
+    {
+        write(bytes, count);
+    }
+
+    size_t length() const
+    {
+        return mData.size();
+    }
+
+    const void* data() const
+    {
+        return mData.size() ? &mData[0] : nullptr;
+    }
+
+  private:
+    std::vector<char> mData;
+
+    template <typename T>
+    void write(const T *v, size_t num)
+    {
+        static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
+        const char *asBytes = reinterpret_cast<const char*>(v);
+        mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
+    }
+
+};
+}
+
+#endif  // LIBANGLE_BINARYSTREAM_H_
diff --git a/src/third_party/angle/src/libANGLE/BinaryStream_unittest.cpp b/src/third_party/angle/src/libANGLE/BinaryStream_unittest.cpp
new file mode 100644
index 0000000..963f489
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/BinaryStream_unittest.cpp
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BinaryStream_unittest.cpp: Unit tests of the binary stream classes.
+
+#include <gtest/gtest.h>
+
+#include "libANGLE/BinaryStream.h"
+
+namespace angle
+{
+
+// Test that errors are properly generated for overflows.
+TEST(BinaryInputStream, Overflow)
+{
+    const uint8_t goodValue = 2;
+    const uint8_t badValue = 255;
+
+    const size_t dataSize = 1024;
+    const size_t slopSize = 1024;
+
+    std::vector<uint8_t> data(dataSize + slopSize);
+    std::fill(data.begin(), data.begin() + dataSize, goodValue);
+    std::fill(data.begin() + dataSize, data.end(), badValue);
+
+    std::vector<uint8_t> outputData(dataSize);
+
+    auto checkDataIsSafe = [=](uint8_t item)
+    {
+        return item == goodValue;
+    };
+
+    {
+        // One large read
+        gl::BinaryInputStream stream(data.data(), dataSize);
+        stream.readBytes(outputData.data(), dataSize);
+        ASSERT_FALSE(stream.error());
+        ASSERT_TRUE(std::all_of(outputData.begin(), outputData.end(), checkDataIsSafe));
+        ASSERT_TRUE(stream.endOfStream());
+    }
+
+    {
+        // Two half-sized reads
+        gl::BinaryInputStream stream(data.data(), dataSize);
+        stream.readBytes(outputData.data(), dataSize / 2);
+        ASSERT_FALSE(stream.error());
+        stream.readBytes(outputData.data() + dataSize / 2, dataSize / 2);
+        ASSERT_FALSE(stream.error());
+        ASSERT_TRUE(std::all_of(outputData.begin(), outputData.end(), checkDataIsSafe));
+        ASSERT_TRUE(stream.endOfStream());
+    }
+
+    {
+        // One large read that is too big
+        gl::BinaryInputStream stream(data.data(), dataSize);
+        stream.readBytes(outputData.data(), dataSize + 1);
+        ASSERT_TRUE(stream.error());
+    }
+
+    {
+        // Two reads, one that overflows the offset
+        gl::BinaryInputStream stream(data.data(), dataSize);
+        stream.readBytes(outputData.data(), dataSize - 1);
+        ASSERT_FALSE(stream.error());
+        stream.readBytes(outputData.data(), std::numeric_limits<size_t>::max() - dataSize - 2);
+    }
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/Buffer.cpp b/src/third_party/angle/src/libANGLE/Buffer.cpp
new file mode 100644
index 0000000..bb2f9fd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Buffer.cpp
@@ -0,0 +1,213 @@
+//
+// 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.
+//
+
+// Buffer.cpp: Implements 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.
+
+#include "libANGLE/Buffer.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/BufferImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+
+BufferState::BufferState()
+    : mLabel(),
+      mUsage(GL_STATIC_DRAW),
+      mSize(0),
+      mAccessFlags(0),
+      mAccess(GL_WRITE_ONLY_OES),
+      mMapped(GL_FALSE),
+      mMapPointer(nullptr),
+      mMapOffset(0),
+      mMapLength(0)
+{
+}
+
+BufferState::~BufferState()
+{
+}
+
+Buffer::Buffer(rx::GLImplFactory *factory, GLuint id)
+    : RefCountObject(id), mImpl(factory->createBuffer(mState))
+{
+}
+
+Buffer::~Buffer()
+{
+    SafeDelete(mImpl);
+}
+
+void Buffer::destroy(const Context *context)
+{
+    // In tests, mImpl might be null.
+    if (mImpl)
+        mImpl->destroy(rx::SafeGetImpl(context));
+}
+
+void Buffer::setLabel(const std::string &label)
+{
+    mState.mLabel = label;
+}
+
+const std::string &Buffer::getLabel() const
+{
+    return mState.mLabel;
+}
+
+Error Buffer::bufferData(const Context *context,
+                         GLenum target,
+                         const void *data,
+                         GLsizeiptr size,
+                         GLenum usage)
+{
+    const void *dataForImpl = data;
+
+    // If we are using robust resource init, make sure the buffer starts cleared.
+    // TODO(jmadill): Investigate lazier clearing.
+    if (context && context->getGLState().isRobustResourceInitEnabled() && data == nullptr)
+    {
+        angle::MemoryBuffer *scratchBuffer = nullptr;
+        ANGLE_TRY(context->getScratchBuffer(static_cast<size_t>(size), &scratchBuffer));
+        std::fill(scratchBuffer->data(), scratchBuffer->data() + size, static_cast<uint8_t>(0));
+        dataForImpl = scratchBuffer->data();
+    }
+
+    ANGLE_TRY(mImpl->setData(rx::SafeGetImpl(context), target, dataForImpl, size, usage));
+
+    mIndexRangeCache.clear();
+    mState.mUsage = usage;
+    mState.mSize  = size;
+
+    return NoError();
+}
+
+Error Buffer::bufferSubData(const Context *context,
+                            GLenum target,
+                            const void *data,
+                            GLsizeiptr size,
+                            GLintptr offset)
+{
+    ANGLE_TRY(mImpl->setSubData(rx::SafeGetImpl(context), target, data, size, offset));
+
+    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));
+
+    return NoError();
+}
+
+Error Buffer::copyBufferSubData(const Context *context,
+                                Buffer *source,
+                                GLintptr sourceOffset,
+                                GLintptr destOffset,
+                                GLsizeiptr size)
+{
+    ANGLE_TRY(mImpl->copySubData(rx::SafeGetImpl(context), source->getImplementation(),
+                                 sourceOffset, destOffset, size));
+
+    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));
+
+    return NoError();
+}
+
+Error Buffer::map(const Context *context, GLenum access)
+{
+    ASSERT(!mState.mMapped);
+
+    mState.mMapPointer = nullptr;
+    ANGLE_TRY(mImpl->map(rx::SafeGetImpl(context), access, &mState.mMapPointer));
+
+    ASSERT(access == GL_WRITE_ONLY_OES);
+
+    mState.mMapped      = GL_TRUE;
+    mState.mMapOffset   = 0;
+    mState.mMapLength   = mState.mSize;
+    mState.mAccess      = access;
+    mState.mAccessFlags = GL_MAP_WRITE_BIT;
+    mIndexRangeCache.clear();
+
+    return NoError();
+}
+
+Error Buffer::mapRange(const Context *context,
+                       GLintptr offset,
+                       GLsizeiptr length,
+                       GLbitfield access)
+{
+    ASSERT(!mState.mMapped);
+    ASSERT(offset + length <= mState.mSize);
+
+    mState.mMapPointer = nullptr;
+    ANGLE_TRY(
+        mImpl->mapRange(rx::SafeGetImpl(context), offset, length, access, &mState.mMapPointer));
+
+    mState.mMapped      = GL_TRUE;
+    mState.mMapOffset   = static_cast<GLint64>(offset);
+    mState.mMapLength   = static_cast<GLint64>(length);
+    mState.mAccess      = GL_WRITE_ONLY_OES;
+    mState.mAccessFlags = access;
+
+    // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
+    // value for GL_BUFFER_ACCESS_OES because it was written against ES2.  Since there is
+    // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
+    // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.
+
+    if ((access & GL_MAP_WRITE_BIT) > 0)
+    {
+        mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(length));
+    }
+
+    return NoError();
+}
+
+Error Buffer::unmap(const Context *context, GLboolean *result)
+{
+    ASSERT(mState.mMapped);
+
+    *result = GL_FALSE;
+    ANGLE_TRY(mImpl->unmap(rx::SafeGetImpl(context), result));
+
+    mState.mMapped      = GL_FALSE;
+    mState.mMapPointer  = nullptr;
+    mState.mMapOffset   = 0;
+    mState.mMapLength   = 0;
+    mState.mAccess      = GL_WRITE_ONLY_OES;
+    mState.mAccessFlags = 0;
+
+    return NoError();
+}
+
+void Buffer::onTransformFeedback()
+{
+    mIndexRangeCache.clear();
+}
+
+void Buffer::onPixelUnpack()
+{
+    mIndexRangeCache.clear();
+}
+
+Error Buffer::getIndexRange(GLenum type,
+                            size_t offset,
+                            size_t count,
+                            bool primitiveRestartEnabled,
+                            IndexRange *outRange) const
+{
+    if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
+    {
+        return NoError();
+    }
+
+    ANGLE_TRY(mImpl->getIndexRange(type, offset, count, primitiveRestartEnabled, outRange));
+
+    mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
+
+    return NoError();
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/Buffer.h b/src/third_party/angle/src/libANGLE/Buffer.h
new file mode 100644
index 0000000..f13f45d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Buffer.h
@@ -0,0 +1,121 @@
+//
+// 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.
+//
+
+// Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or
+// index data. Implements GL buffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 2.9 page 21.
+
+#ifndef LIBANGLE_BUFFER_H_
+#define LIBANGLE_BUFFER_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/IndexRangeCache.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class BufferImpl;
+class GLImplFactory;
+};
+
+namespace gl
+{
+class Buffer;
+class Context;
+
+class BufferState final : angle::NonCopyable
+{
+  public:
+    BufferState();
+    ~BufferState();
+
+    const std::string &getLabel();
+
+    GLenum getUsage() const { return mUsage; }
+    GLbitfield getAccessFlags() const { return mAccessFlags; }
+    GLenum getAccess() const { return mAccess; }
+    GLboolean isMapped() const { return mMapped; }
+    void *getMapPointer() const { return mMapPointer; }
+    GLint64 getMapOffset() const { return mMapOffset; }
+    GLint64 getMapLength() const { return mMapLength; }
+    GLint64 getSize() const { return mSize; }
+
+  private:
+    friend class Buffer;
+
+    std::string mLabel;
+
+    GLenum mUsage;
+    GLint64 mSize;
+    GLbitfield mAccessFlags;
+    GLenum mAccess;
+    GLboolean mMapped;
+    void *mMapPointer;
+    GLint64 mMapOffset;
+    GLint64 mMapLength;
+};
+
+class Buffer final : public RefCountObject, public LabeledObject
+{
+  public:
+    Buffer(rx::GLImplFactory *factory, GLuint id);
+    ~Buffer() override;
+    void destroy(const Context *context) override;
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    Error bufferData(const Context *context,
+                     GLenum target,
+                     const void *data,
+                     GLsizeiptr size,
+                     GLenum usage);
+    Error bufferSubData(const Context *context,
+                        GLenum target,
+                        const void *data,
+                        GLsizeiptr size,
+                        GLintptr offset);
+    Error copyBufferSubData(const Context *context,
+                            Buffer *source,
+                            GLintptr sourceOffset,
+                            GLintptr destOffset,
+                            GLsizeiptr size);
+    Error map(const Context *context, GLenum access);
+    Error mapRange(const Context *context, GLintptr offset, GLsizeiptr length, GLbitfield access);
+    Error unmap(const Context *context, GLboolean *result);
+
+    void onTransformFeedback();
+    void onPixelUnpack();
+
+    Error getIndexRange(GLenum type,
+                        size_t offset,
+                        size_t count,
+                        bool primitiveRestartEnabled,
+                        IndexRange *outRange) const;
+
+    GLenum getUsage() const { return mState.mUsage; }
+    GLbitfield getAccessFlags() const { return mState.mAccessFlags; }
+    GLenum getAccess() const { return mState.mAccess; }
+    GLboolean isMapped() const { return mState.mMapped; }
+    void *getMapPointer() const { return mState.mMapPointer; }
+    GLint64 getMapOffset() const { return mState.mMapOffset; }
+    GLint64 getMapLength() const { return mState.mMapLength; }
+    GLint64 getSize() const { return mState.mSize; }
+
+    rx::BufferImpl *getImplementation() const { return mImpl; }
+
+  private:
+    BufferState mState;
+    rx::BufferImpl *mImpl;
+
+    mutable IndexRangeCache mIndexRangeCache;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_BUFFER_H_
diff --git a/src/third_party/angle/src/libANGLE/Caps.cpp b/src/third_party/angle/src/libANGLE/Caps.cpp
new file mode 100644
index 0000000..df7947c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Caps.cpp
@@ -0,0 +1,1185 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/Caps.h"
+
+#include "common/debug.h"
+#include "common/angleutils.h"
+
+#include "libANGLE/formatutils.h"
+
+#include "angle_gl.h"
+
+#include <algorithm>
+#include <sstream>
+
+static void InsertExtensionString(const std::string &extension, bool supported, std::vector<std::string> *extensionVector)
+{
+    if (supported)
+    {
+        extensionVector->push_back(extension);
+    }
+}
+
+namespace gl
+{
+
+TextureCaps::TextureCaps()
+    : texturable(false),
+      filterable(false),
+      renderable(false),
+      sampleCounts()
+{
+}
+
+GLuint TextureCaps::getMaxSamples() const
+{
+    return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0;
+}
+
+GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const
+{
+    if (requestedSamples == 0)
+    {
+        return 0;
+    }
+
+    for (SupportedSampleSet::const_iterator i = sampleCounts.begin(); i != sampleCounts.end(); i++)
+    {
+        GLuint samples = *i;
+        if (samples >= requestedSamples)
+        {
+            return samples;
+        }
+    }
+
+    return 0;
+}
+
+TextureCaps GenerateMinimumTextureCaps(GLenum sizedInternalFormat,
+                                       const Version &clientVersion,
+                                       const Extensions &extensions)
+{
+    TextureCaps caps;
+
+    const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(sizedInternalFormat);
+    caps.texturable = internalFormatInfo.textureSupport(clientVersion, extensions);
+    caps.renderable = internalFormatInfo.renderSupport(clientVersion, extensions);
+    caps.filterable = internalFormatInfo.filterSupport(clientVersion, extensions);
+
+    caps.sampleCounts.insert(0);
+
+    return caps;
+}
+
+void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps)
+{
+    mCapsMap[internalFormat] = caps;
+}
+
+void TextureCapsMap::remove(GLenum internalFormat)
+{
+    InternalFormatToCapsMap::iterator i = mCapsMap.find(internalFormat);
+    if (i != mCapsMap.end())
+    {
+        mCapsMap.erase(i);
+    }
+}
+
+void TextureCapsMap::clear()
+{
+    mCapsMap.clear();
+}
+
+const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const
+{
+    static TextureCaps defaultUnsupportedTexture;
+    InternalFormatToCapsMap::const_iterator iter = mCapsMap.find(internalFormat);
+    return (iter != mCapsMap.end()) ? iter->second : defaultUnsupportedTexture;
+}
+
+TextureCapsMap::const_iterator TextureCapsMap::begin() const
+{
+    return mCapsMap.begin();
+}
+
+TextureCapsMap::const_iterator TextureCapsMap::end() const
+{
+    return mCapsMap.end();
+}
+
+size_t TextureCapsMap::size() const
+{
+    return mCapsMap.size();
+}
+
+TextureCapsMap GenerateMinimumTextureCapsMap(const Version &clientVersion,
+                                             const Extensions &extensions)
+{
+    TextureCapsMap capsMap;
+
+    for (GLenum internalFormat : GetAllSizedInternalFormats())
+    {
+        capsMap.insert(internalFormat,
+                       GenerateMinimumTextureCaps(internalFormat, clientVersion, extensions));
+    }
+
+    return capsMap;
+}
+
+Extensions::Extensions()
+    : elementIndexUint(false),
+      packedDepthStencil(false),
+      getProgramBinary(false),
+      rgb8rgba8(false),
+      textureFormatBGRA8888(false),
+      readFormatBGRA(false),
+      pixelBufferObject(false),
+      mapBuffer(false),
+      mapBufferRange(false),
+      colorBufferHalfFloat(false),
+      textureHalfFloat(false),
+      textureHalfFloatLinear(false),
+      textureFloat(false),
+      textureFloatLinear(false),
+      textureRG(false),
+      textureCompressionDXT1(false),
+      textureCompressionDXT3(false),
+      textureCompressionDXT5(false),
+      textureCompressionS3TCsRGB(false),
+      textureCompressionASTCHDR(false),
+      textureCompressionASTCLDR(false),
+      compressedETC1RGB8Texture(false),
+      sRGB(false),
+      depthTextures(false),
+      depth32(false),
+      textureStorage(false),
+      textureNPOT(false),
+      drawBuffers(false),
+      textureFilterAnisotropic(false),
+      maxTextureAnisotropy(0.0f),
+      occlusionQueryBoolean(false),
+      fence(false),
+      timerQuery(false),
+      disjointTimerQuery(false),
+      queryCounterBitsTimeElapsed(0),
+      queryCounterBitsTimestamp(0),
+      robustness(false),
+      blendMinMax(false),
+      framebufferBlit(false),
+      framebufferMultisample(false),
+      instancedArrays(false),
+      packReverseRowOrder(false),
+      standardDerivatives(false),
+      shaderTextureLOD(false),
+      shaderFramebufferFetch(false),
+      ARMshaderFramebufferFetch(false),
+      NVshaderFramebufferFetch(false),
+      fragDepth(false),
+      textureUsage(false),
+      translatedShaderSource(false),
+      fboRenderMipmap(false),
+      discardFramebuffer(false),
+      debugMarker(false),
+      eglImage(false),
+      eglImageExternal(false),
+      eglImageExternalEssl3(false),
+      eglStreamConsumerExternal(false),
+      unpackSubimage(false),
+      packSubimage(false),
+      vertexArrayObject(false),
+      debug(false),
+      maxDebugMessageLength(0),
+      maxDebugLoggedMessages(0),
+      maxDebugGroupStackDepth(0),
+      maxLabelLength(0),
+      noError(false),
+      lossyETCDecode(false),
+      bindUniformLocation(false),
+      syncQuery(false),
+      copyTexture(false),
+      copyCompressedTexture(false),
+      webglCompatibility(false),
+      requestExtension(false),
+      bindGeneratesResource(false),
+      robustClientMemory(false),
+      textureSRGBDecode(false),
+      sRGBWriteControl(false),
+      colorBufferFloatRGB(false),
+      colorBufferFloatRGBA(false),
+      colorBufferFloat(false),
+      multisampleCompatibility(false),
+      framebufferMixedSamples(false),
+      textureNorm16(false),
+      pathRendering(false),
+      surfacelessContext(false),
+      clientArrays(false),
+      robustResourceInitialization(false)
+{
+}
+
+std::vector<std::string> Extensions::getStrings() const
+{
+    std::vector<std::string> extensionStrings;
+
+    for (const auto &extensionInfo : GetExtensionInfoMap())
+    {
+        if (this->*(extensionInfo.second.ExtensionsMember))
+        {
+            extensionStrings.push_back(extensionInfo.first);
+        }
+    }
+
+    return extensionStrings;
+}
+
+Limitations::Limitations()
+    : noFrontFacingSupport(false),
+      noSampleAlphaToCoverageSupport(false),
+      attributeZeroRequiresZeroDivisorInEXT(false),
+      noSeparateStencilRefsAndMasks(false),
+      shadersRequireIndexedLoopValidation(false),
+      noSimultaneousConstantColorAndAlphaBlendFunc(false)
+{
+}
+
+static bool GetFormatSupportBase(const TextureCapsMap &textureCaps,
+                                 const GLenum *requiredFormats,
+                                 size_t requiredFormatsSize,
+                                 bool requiresTexturing,
+                                 bool requiresFiltering,
+                                 bool requiresRendering)
+{
+    for (size_t i = 0; i < requiredFormatsSize; 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;
+        }
+    }
+
+    return true;
+}
+
+template <size_t N>
+static bool GetFormatSupport(const TextureCapsMap &textureCaps,
+                             const GLenum (&requiredFormats)[N],
+                             bool requiresTexturing,
+                             bool requiresFiltering,
+                             bool requiresRendering)
+{
+    return GetFormatSupportBase(textureCaps, requiredFormats, N, requiresTexturing,
+                                requiresFiltering, requiresRendering);
+}
+
+// Check for GL_OES_packed_depth_stencil
+static bool DeterminePackedDepthStencilSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_DEPTH24_STENCIL8,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, false, false, true);
+}
+
+// Checks for GL_OES_rgb8_rgba8 support
+static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_RGB8, GL_RGBA8,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
+}
+
+// Checks for GL_EXT_texture_format_BGRA8888 support
+static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_BGRA8_EXT,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
+}
+
+// Checks for GL_OES_color_buffer_half_float support
+static bool DetermineColorBufferHalfFloatSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_RGBA16F, GL_RGB16F, GL_RG16F, GL_R16F,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
+// Checks for GL_OES_texture_half_float support
+static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_RGB16F, GL_RGBA16F,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, false);
+}
+
+// Checks for GL_OES_texture_half_float_linear support
+static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_RGB16F, GL_RGBA16F,
+    };
+
+    return DetermineHalfFloatTextureSupport(textureCaps) &&
+           GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Checks for GL_OES_texture_float support
+static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_RGB32F, GL_RGBA32F,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, false);
+}
+
+// Checks for GL_OES_texture_float_linear support
+static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_RGB32F, GL_RGBA32F,
+    };
+
+    return DetermineFloatTextureSupport(textureCaps) &&
+           GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Checks for GL_EXT_texture_rg support
+static bool DetermineRGHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_R16F, GL_RG16F,
+    };
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+static bool DetermineRGFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_R32F, GL_RG32F,
+    };
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats)
+{
+    if (checkHalfFloatFormats && !DetermineRGHalfFloatTextureSupport(textureCaps))
+    {
+        return false;
+    }
+
+    if (checkFloatFormats && !DetermineRGFloatTextureSupport(textureCaps))
+    {
+        return false;
+    }
+
+    constexpr GLenum requiredFormats[] = {
+        GL_R8, GL_RG8,
+    };
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_EXT_texture_compression_dxt1
+static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_ANGLE_texture_compression_dxt3
+static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_ANGLE_texture_compression_dxt5
+static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_EXT_texture_compression_s3tc_srgb
+static bool DetermineS3TCsRGBTextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
+        GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_KHR_texture_compression_astc_hdr and GL_KHR_texture_compression_astc_ldr
+static bool DetermineASTCTextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_COMPRESSED_RGBA_ASTC_4x4_KHR,           GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
+        GL_COMPRESSED_RGBA_ASTC_5x5_KHR,           GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
+        GL_COMPRESSED_RGBA_ASTC_6x6_KHR,           GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
+        GL_COMPRESSED_RGBA_ASTC_8x6_KHR,           GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
+        GL_COMPRESSED_RGBA_ASTC_10x5_KHR,          GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
+        GL_COMPRESSED_RGBA_ASTC_10x8_KHR,          GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
+        GL_COMPRESSED_RGBA_ASTC_12x10_KHR,         GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
+        GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,   GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
+        GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,   GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
+        GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,   GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
+        GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,   GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
+        GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,  GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
+        GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,  GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+        GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_ETC1_RGB8_OES
+static bool DetermineETC1RGB8TextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_ETC1_RGB8_OES,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_ANGLE_texture_compression_dxt5
+static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFilterFormats[] = {
+        GL_SRGB8, GL_SRGB8_ALPHA8,
+    };
+
+    constexpr GLenum requiredRenderFormats[] = {
+        GL_SRGB8_ALPHA8,
+    };
+
+    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)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT32_OES, GL_DEPTH24_STENCIL8_OES,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
+}
+
+// Check for GL_OES_depth32
+static bool DetermineDepth32Support(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_DEPTH_COMPONENT32_OES,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, false, false, true);
+}
+
+// Check for GL_CHROMIUM_color_buffer_float_rgb
+static bool DetermineColorBufferFloatRGBSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_RGB32F,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
+// Check for GL_CHROMIUM_color_buffer_float_rgba
+static bool DetermineColorBufferFloatRGBASupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_RGBA32F,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
+// Check for GL_EXT_color_buffer_float
+static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFormats[] = {
+        GL_R16F, GL_RG16F, GL_RGBA16F, GL_R32F, GL_RG32F, GL_RGBA32F, GL_R11F_G11F_B10F,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
+// Check for GL_EXT_texture_norm16
+static bool DetermineTextureNorm16Support(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFilterFormats[] = {
+        GL_R16_EXT,       GL_RG16_EXT,       GL_RGB16_EXT,       GL_RGBA16_EXT,
+        GL_R16_SNORM_EXT, GL_RG16_SNORM_EXT, GL_RGB16_SNORM_EXT, GL_RGBA16_SNORM_EXT,
+    };
+
+    constexpr GLenum requiredRenderFormats[] = {
+        GL_R16_EXT, GL_RG16_EXT, GL_RGBA16_EXT,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) &&
+           GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true);
+}
+
+void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
+{
+    packedDepthStencil = DeterminePackedDepthStencilSupport(textureCaps);
+    rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps);
+    textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps);
+    colorBufferHalfFloat      = DetermineColorBufferHalfFloatSupport(textureCaps);
+    textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps);
+    textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps);
+    textureFloat = DetermineFloatTextureSupport(textureCaps);
+    textureFloatLinear = DetermineFloatTextureFilteringSupport(textureCaps);
+    textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat);
+    textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps);
+    textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps);
+    textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps);
+    textureCompressionS3TCsRGB = DetermineS3TCsRGBTextureSupport(textureCaps);
+    textureCompressionASTCHDR = DetermineASTCTextureSupport(textureCaps);
+    textureCompressionASTCLDR = textureCompressionASTCHDR;
+    compressedETC1RGB8Texture = DetermineETC1RGB8TextureSupport(textureCaps);
+    sRGB = DetermineSRGBTextureSupport(textureCaps);
+    depthTextures = DetermineDepthTextureSupport(textureCaps);
+    depth32                   = DetermineDepth32Support(textureCaps);
+    colorBufferFloatRGB        = DetermineColorBufferFloatRGBSupport(textureCaps);
+    colorBufferFloatRGBA       = DetermineColorBufferFloatRGBASupport(textureCaps);
+    colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps);
+    textureNorm16             = DetermineTextureNorm16Support(textureCaps);
+}
+
+const ExtensionInfoMap &GetExtensionInfoMap()
+{
+    auto buildExtensionInfoMap = []() {
+        auto enableableExtension = [](ExtensionInfo::ExtensionBool member) {
+            ExtensionInfo info;
+            info.Requestable      = true;
+            info.ExtensionsMember = member;
+            return info;
+        };
+
+        auto esOnlyExtension = [](ExtensionInfo::ExtensionBool member) {
+            ExtensionInfo info;
+            info.ExtensionsMember = member;
+            return info;
+        };
+
+        // clang-format off
+        ExtensionInfoMap map;
+        map["GL_OES_element_index_uint"] = enableableExtension(&Extensions::elementIndexUint);
+        map["GL_OES_packed_depth_stencil"] = esOnlyExtension(&Extensions::packedDepthStencil);
+        map["GL_OES_get_program_binary"] = esOnlyExtension(&Extensions::getProgramBinary);
+        map["GL_OES_rgb8_rgba8"] = esOnlyExtension(&Extensions::rgb8rgba8);
+        map["GL_EXT_texture_format_BGRA8888"] = esOnlyExtension(&Extensions::textureFormatBGRA8888);
+        map["GL_EXT_read_format_bgra"] = esOnlyExtension(&Extensions::readFormatBGRA);
+        map["GL_NV_pixel_buffer_object"] = esOnlyExtension(&Extensions::pixelBufferObject);
+        map["GL_OES_mapbuffer"] = esOnlyExtension(&Extensions::mapBuffer);
+        map["GL_EXT_map_buffer_range"] = esOnlyExtension(&Extensions::mapBufferRange);
+        map["GL_EXT_color_buffer_half_float"] = enableableExtension(&Extensions::colorBufferHalfFloat);
+        map["GL_OES_texture_half_float"] = enableableExtension(&Extensions::textureHalfFloat);
+        map["GL_OES_texture_half_float_linear"] = enableableExtension(&Extensions::textureHalfFloatLinear);
+        map["GL_OES_texture_float"] = enableableExtension(&Extensions::textureFloat);
+        map["GL_OES_texture_float_linear"] = enableableExtension(&Extensions::textureFloatLinear);
+        map["GL_EXT_texture_rg"] = esOnlyExtension(&Extensions::textureRG);
+        map["GL_EXT_texture_compression_dxt1"] = esOnlyExtension(&Extensions::textureCompressionDXT1);
+        map["GL_ANGLE_texture_compression_dxt3"] = esOnlyExtension(&Extensions::textureCompressionDXT3);
+        map["GL_ANGLE_texture_compression_dxt5"] = esOnlyExtension(&Extensions::textureCompressionDXT5);
+        map["GL_EXT_texture_compression_s3tc_srgb"] = esOnlyExtension(&Extensions::textureCompressionS3TCsRGB);
+        map["GL_KHR_texture_compression_astc_hdr"] = esOnlyExtension(&Extensions::textureCompressionASTCHDR);
+        map["GL_KHR_texture_compression_astc_ldr"] = esOnlyExtension(&Extensions::textureCompressionASTCLDR);
+        map["GL_OES_compressed_ETC1_RGB8_texture"] = esOnlyExtension(&Extensions::compressedETC1RGB8Texture);
+        map["GL_EXT_sRGB"] = esOnlyExtension(&Extensions::sRGB);
+        map["GL_ANGLE_depth_texture"] = esOnlyExtension(&Extensions::depthTextures);
+        map["GL_OES_depth32"] = esOnlyExtension(&Extensions::depth32);
+        map["GL_EXT_texture_storage"] = esOnlyExtension(&Extensions::textureStorage);
+        map["GL_OES_texture_npot"] = enableableExtension(&Extensions::textureNPOT);
+        map["GL_EXT_draw_buffers"] = enableableExtension(&Extensions::drawBuffers);
+        map["GL_EXT_texture_filter_anisotropic"] = enableableExtension(&Extensions::textureFilterAnisotropic);
+        map["GL_EXT_occlusion_query_boolean"] = esOnlyExtension(&Extensions::occlusionQueryBoolean);
+        map["GL_NV_fence"] = esOnlyExtension(&Extensions::fence);
+        map["GL_ANGLE_timer_query"] = esOnlyExtension(&Extensions::timerQuery);
+        map["GL_EXT_disjoint_timer_query"] = esOnlyExtension(&Extensions::disjointTimerQuery);
+        map["GL_EXT_robustness"] = esOnlyExtension(&Extensions::robustness);
+        map["GL_EXT_blend_minmax"] = esOnlyExtension(&Extensions::blendMinMax);
+        map["GL_ANGLE_framebuffer_blit"] = esOnlyExtension(&Extensions::framebufferBlit);
+        map["GL_ANGLE_framebuffer_multisample"] = esOnlyExtension(&Extensions::framebufferMultisample);
+        map["GL_ANGLE_instanced_arrays"] = esOnlyExtension(&Extensions::instancedArrays);
+        map["GL_ANGLE_pack_reverse_row_order"] = esOnlyExtension(&Extensions::packReverseRowOrder);
+        map["GL_OES_standard_derivatives"] = enableableExtension(&Extensions::standardDerivatives);
+        map["GL_EXT_shader_texture_lod"] = enableableExtension(&Extensions::shaderTextureLOD);
+        map["GL_NV_shader_framebuffer_fetch"] = esOnlyExtension(&Extensions::NVshaderFramebufferFetch);
+        map["GL_ARM_shader_framebuffer_fetch"] = esOnlyExtension(&Extensions::ARMshaderFramebufferFetch);
+        map["GL_EXT_shader_framebuffer_fetch"] = esOnlyExtension(&Extensions::shaderFramebufferFetch);
+        map["GL_EXT_frag_depth"] = enableableExtension(&Extensions::fragDepth);
+        map["GL_ANGLE_texture_usage"] = esOnlyExtension(&Extensions::textureUsage);
+        map["GL_ANGLE_translated_shader_source"] = esOnlyExtension(&Extensions::translatedShaderSource);
+        map["GL_OES_fbo_render_mipmap"] = esOnlyExtension(&Extensions::fboRenderMipmap);
+        map["GL_EXT_discard_framebuffer"] = esOnlyExtension(&Extensions::discardFramebuffer);
+        map["GL_EXT_debug_marker"] = esOnlyExtension(&Extensions::debugMarker);
+        map["GL_OES_EGL_image"] = esOnlyExtension(&Extensions::eglImage);
+        map["GL_OES_EGL_image_external"] = esOnlyExtension(&Extensions::eglImageExternal);
+        map["GL_OES_EGL_image_external_essl3"] = esOnlyExtension(&Extensions::eglImageExternalEssl3);
+        map["GL_NV_EGL_stream_consumer_external"] = esOnlyExtension(&Extensions::eglStreamConsumerExternal);
+        map["GL_EXT_unpack_subimage"] = esOnlyExtension(&Extensions::unpackSubimage);
+        map["GL_NV_pack_subimage"] = esOnlyExtension(&Extensions::packSubimage);
+        map["GL_EXT_color_buffer_float"] = enableableExtension(&Extensions::colorBufferFloat);
+        map["GL_OES_vertex_array_object"] = esOnlyExtension(&Extensions::vertexArrayObject);
+        map["GL_KHR_debug"] = esOnlyExtension(&Extensions::debug);
+        // TODO(jmadill): Enable this when complete.
+        //map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noError);
+        map["GL_ANGLE_lossy_etc_decode"] = esOnlyExtension(&Extensions::lossyETCDecode);
+        map["GL_CHROMIUM_bind_uniform_location"] = esOnlyExtension(&Extensions::bindUniformLocation);
+        map["GL_CHROMIUM_sync_query"] = esOnlyExtension(&Extensions::syncQuery);
+        map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
+        map["GL_CHROMIUM_copy_compressed_texture"] = esOnlyExtension(&Extensions::copyCompressedTexture);
+        map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
+        map["GL_ANGLE_request_extension"] = esOnlyExtension(&Extensions::requestExtension);
+        map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
+        map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory);
+        map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode);
+        map["GL_EXT_sRGB_write_control"] = esOnlyExtension(&Extensions::sRGBWriteControl);
+        map["GL_CHROMIUM_color_buffer_float_rgb"] = enableableExtension(&Extensions::colorBufferFloatRGB);
+        map["GL_CHROMIUM_color_buffer_float_rgba"] = enableableExtension(&Extensions::colorBufferFloatRGBA);
+        map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
+        map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
+        map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
+        map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering);
+        map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContext);
+        map["GL_ANGLE_client_arrays"] = esOnlyExtension(&Extensions::clientArrays);
+        map["GL_ANGLE_robust_resource_initialization"] = esOnlyExtension(&Extensions::robustResourceInitialization);
+        // clang-format on
+
+        return map;
+    };
+
+    static const ExtensionInfoMap extensionInfo = buildExtensionInfoMap();
+    return extensionInfo;
+}
+
+TypePrecision::TypePrecision() : range({{0, 0}}), precision(0)
+{
+}
+
+void TypePrecision::setIEEEFloat()
+{
+    range     = {{127, 127}};
+    precision = 23;
+}
+
+void TypePrecision::setTwosComplementInt(unsigned int bits)
+{
+    range     = {{static_cast<GLint>(bits) - 1, static_cast<GLint>(bits) - 2}};
+    precision = 0;
+}
+
+void TypePrecision::setSimulatedFloat(unsigned int r, unsigned int p)
+{
+    range     = {{static_cast<GLint>(r), static_cast<GLint>(r)}};
+    precision = static_cast<GLint>(p);
+}
+
+void TypePrecision::setSimulatedInt(unsigned int r)
+{
+    range     = {{static_cast<GLint>(r), static_cast<GLint>(r)}};
+    precision = 0;
+}
+
+void TypePrecision::get(GLint *returnRange, GLint *returnPrecision) const
+{
+    std::copy(range.begin(), range.end(), returnRange);
+    *returnPrecision = precision;
+}
+
+Caps::Caps()
+    : maxElementIndex(0),
+      max3DTextureSize(0),
+      max2DTextureSize(0),
+      maxArrayTextureLayers(0),
+      maxLODBias(0),
+      maxCubeMapTextureSize(0),
+      maxRenderbufferSize(0),
+      minAliasedPointSize(0),
+      maxAliasedPointSize(0),
+      minAliasedLineWidth(0),
+      maxAliasedLineWidth(0),
+
+      // Table 20.40
+      maxDrawBuffers(0),
+      maxFramebufferWidth(0),
+      maxFramebufferHeight(0),
+      maxFramebufferSamples(0),
+      maxColorAttachments(0),
+      maxViewportWidth(0),
+      maxViewportHeight(0),
+      maxSampleMaskWords(0),
+      maxColorTextureSamples(0),
+      maxDepthTextureSamples(0),
+      maxIntegerSamples(0),
+      maxServerWaitTimeout(0),
+
+      // Table 20.41
+      maxVertexAttribRelativeOffset(0),
+      maxVertexAttribBindings(0),
+      maxVertexAttribStride(0),
+      maxElementsIndices(0),
+      maxElementsVertices(0),
+
+      // Table 20.43
+      maxVertexAttributes(0),
+      maxVertexUniformComponents(0),
+      maxVertexUniformVectors(0),
+      maxVertexUniformBlocks(0),
+      maxVertexOutputComponents(0),
+      maxVertexTextureImageUnits(0),
+      maxVertexAtomicCounterBuffers(0),
+      maxVertexAtomicCounters(0),
+      maxVertexImageUniforms(0),
+      maxVertexShaderStorageBlocks(0),
+
+      // Table 20.44
+      maxFragmentUniformComponents(0),
+      maxFragmentUniformVectors(0),
+      maxFragmentUniformBlocks(0),
+      maxFragmentInputComponents(0),
+      maxTextureImageUnits(0),
+      maxFragmentAtomicCounterBuffers(0),
+      maxFragmentAtomicCounters(0),
+      maxFragmentImageUniforms(0),
+      maxFragmentShaderStorageBlocks(0),
+      minProgramTextureGatherOffset(0),
+      maxProgramTextureGatherOffset(0),
+      minProgramTexelOffset(0),
+      maxProgramTexelOffset(0),
+
+      // Table 20.45
+      maxComputeWorkGroupInvocations(0),
+      maxComputeUniformBlocks(0),
+      maxComputeTextureImageUnits(0),
+      maxComputeSharedMemorySize(0),
+      maxComputeUniformComponents(0),
+      maxComputeAtomicCounterBuffers(0),
+      maxComputeAtomicCounters(0),
+      maxComputeImageUniforms(0),
+      maxCombinedComputeUniformComponents(0),
+      maxComputeShaderStorageBlocks(0),
+
+      // Table 20.46
+      maxUniformBufferBindings(0),
+      maxUniformBlockSize(0),
+      uniformBufferOffsetAlignment(0),
+      maxCombinedUniformBlocks(0),
+      maxCombinedVertexUniformComponents(0),
+      maxCombinedFragmentUniformComponents(0),
+      maxVaryingComponents(0),
+      maxVaryingVectors(0),
+      maxCombinedTextureImageUnits(0),
+      maxCombinedShaderOutputResources(0),
+
+      // Table 20.47
+      maxUniformLocations(0),
+      maxAtomicCounterBufferBindings(0),
+      maxAtomicCounterBufferSize(0),
+      maxCombinedAtomicCounterBuffers(0),
+      maxCombinedAtomicCounters(0),
+      maxImageUnits(0),
+      maxCombinedImageUniforms(0),
+      maxShaderStorageBufferBindings(0),
+      maxShaderStorageBlockSize(0),
+      maxCombinedShaderStorageBlocks(0),
+      shaderStorageBufferOffsetAlignment(0),
+
+      // Table 20.48
+      maxTransformFeedbackInterleavedComponents(0),
+      maxTransformFeedbackSeparateAttributes(0),
+      maxTransformFeedbackSeparateComponents(0),
+
+      // Table 20.49
+      maxSamples(0)
+
+{
+    for (size_t i = 0; i < 3; ++i)
+    {
+        maxComputeWorkGroupCount[i] = 0;
+        maxComputeWorkGroupSize[i]  = 0;
+    }
+}
+
+Caps GenerateMinimumCaps(const Version &clientVersion)
+{
+    Caps caps;
+
+    if (clientVersion >= Version(2, 0))
+    {
+        // Table 6.18
+        caps.max2DTextureSize      = 64;
+        caps.maxCubeMapTextureSize = 16;
+        caps.maxViewportWidth      = caps.max2DTextureSize;
+        caps.maxViewportHeight     = caps.max2DTextureSize;
+        caps.minAliasedPointSize   = 1;
+        caps.maxAliasedPointSize   = 1;
+        caps.minAliasedLineWidth   = 1;
+        caps.maxAliasedLineWidth   = 1;
+
+        // Table 6.19
+        caps.vertexHighpFloat.setSimulatedFloat(62, 16);
+        caps.vertexMediumpFloat.setSimulatedFloat(14, 10);
+        caps.vertexLowpFloat.setSimulatedFloat(1, 8);
+        caps.vertexHighpInt.setSimulatedInt(16);
+        caps.vertexMediumpInt.setSimulatedInt(10);
+        caps.vertexLowpInt.setSimulatedInt(8);
+        caps.fragmentHighpFloat.setSimulatedFloat(62, 16);
+        caps.fragmentMediumpFloat.setSimulatedFloat(14, 10);
+        caps.fragmentLowpFloat.setSimulatedFloat(1, 8);
+        caps.fragmentHighpInt.setSimulatedInt(16);
+        caps.fragmentMediumpInt.setSimulatedInt(10);
+        caps.fragmentLowpInt.setSimulatedInt(8);
+
+        // Table 6.20
+        caps.maxVertexAttributes          = 8;
+        caps.maxVertexUniformVectors      = 128;
+        caps.maxVaryingVectors            = 8;
+        caps.maxCombinedTextureImageUnits = 8;
+        caps.maxTextureImageUnits         = 8;
+        caps.maxFragmentUniformVectors    = 16;
+        caps.maxRenderbufferSize          = 1;
+    }
+
+    if (clientVersion >= Version(3, 0))
+    {
+        // Table 6.28
+        caps.maxElementIndex       = (1 << 24) - 1;
+        caps.max3DTextureSize      = 256;
+        caps.max2DTextureSize      = 2048;
+        caps.maxArrayTextureLayers = 256;
+        caps.maxLODBias            = 2.0f;
+        caps.maxCubeMapTextureSize = 2048;
+        caps.maxRenderbufferSize   = 2048;
+        caps.maxDrawBuffers        = 4;
+        caps.maxColorAttachments   = 4;
+        caps.maxViewportWidth      = caps.max2DTextureSize;
+        caps.maxViewportHeight     = caps.max2DTextureSize;
+
+        // Table 6.29
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_R11_EAC);
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_SIGNED_R11_EAC);
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_RG11_EAC);
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_SIGNED_RG11_EAC);
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGB8_ETC2);
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_ETC2);
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGBA8_ETC2_EAC);
+        caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
+        caps.vertexHighpFloat.setIEEEFloat();
+        caps.vertexHighpInt.setTwosComplementInt(32);
+        caps.vertexMediumpInt.setTwosComplementInt(16);
+        caps.vertexLowpInt.setTwosComplementInt(8);
+        caps.fragmentHighpFloat.setIEEEFloat();
+        caps.fragmentHighpInt.setSimulatedInt(32);
+        caps.fragmentMediumpInt.setTwosComplementInt(16);
+        caps.fragmentLowpInt.setTwosComplementInt(8);
+        caps.maxServerWaitTimeout = 0;
+
+        // Table 6.31
+        caps.maxVertexAttributes        = 16;
+        caps.maxVertexUniformComponents = 1024;
+        caps.maxVertexUniformVectors    = 256;
+        caps.maxVertexUniformBlocks     = 12;
+        caps.maxVertexOutputComponents  = 64;
+        caps.maxVertexTextureImageUnits = 16;
+
+        // Table 6.32
+        caps.maxFragmentUniformComponents = 896;
+        caps.maxFragmentUniformVectors    = 224;
+        caps.maxFragmentUniformBlocks     = 12;
+        caps.maxFragmentInputComponents   = 60;
+        caps.maxTextureImageUnits         = 16;
+        caps.minProgramTexelOffset        = -8;
+        caps.maxProgramTexelOffset        = 7;
+
+        // Table 6.33
+        caps.maxUniformBufferBindings     = 24;
+        caps.maxUniformBlockSize          = 16384;
+        caps.uniformBufferOffsetAlignment = 256;
+        caps.maxCombinedUniformBlocks     = 24;
+        caps.maxCombinedVertexUniformComponents =
+            caps.maxVertexUniformBlocks * (caps.maxUniformBlockSize / 4) +
+            caps.maxVertexUniformComponents;
+        caps.maxCombinedFragmentUniformComponents =
+            caps.maxFragmentUniformBlocks * (caps.maxUniformBlockSize / 4) +
+            caps.maxFragmentUniformComponents;
+        caps.maxVaryingComponents         = 60;
+        caps.maxVaryingVectors            = 15;
+        caps.maxCombinedTextureImageUnits = 32;
+
+        // Table 6.34
+        caps.maxTransformFeedbackInterleavedComponents = 64;
+        caps.maxTransformFeedbackSeparateAttributes    = 4;
+        caps.maxTransformFeedbackSeparateComponents    = 4;
+
+        // Table 3.35
+        caps.maxSamples = 4;
+    }
+
+    if (clientVersion >= Version(3, 1))
+    {
+        // Table 20.40
+        caps.maxFramebufferWidth    = 2048;
+        caps.maxFramebufferHeight   = 2048;
+        caps.maxFramebufferSamples  = 4;
+        caps.maxSampleMaskWords     = 1;
+        caps.maxColorTextureSamples = 1;
+        caps.maxDepthTextureSamples = 1;
+        caps.maxIntegerSamples      = 1;
+
+        // Table 20.41
+        caps.maxVertexAttribRelativeOffset = 2047;
+        caps.maxVertexAttribBindings       = 16;
+        caps.maxVertexAttribStride         = 2048;
+
+        // Table 20.43
+        caps.maxVertexAtomicCounterBuffers = 0;
+        caps.maxVertexAtomicCounters       = 0;
+        caps.maxVertexImageUniforms        = 0;
+        caps.maxVertexShaderStorageBlocks  = 0;
+
+        // Table 20.44
+        caps.maxFragmentUniformComponents    = 1024;
+        caps.maxFragmentUniformVectors       = 256;
+        caps.maxFragmentAtomicCounterBuffers = 0;
+        caps.maxFragmentAtomicCounters       = 0;
+        caps.maxFragmentImageUniforms        = 0;
+        caps.maxFragmentShaderStorageBlocks  = 0;
+        caps.minProgramTextureGatherOffset   = 0;
+        caps.maxProgramTextureGatherOffset   = 0;
+
+        // Table 20.45
+        caps.maxComputeWorkGroupCount       = {{65535, 65535, 65535}};
+        caps.maxComputeWorkGroupSize        = {{128, 128, 64}};
+        caps.maxComputeWorkGroupInvocations = 12;
+        caps.maxComputeUniformBlocks        = 12;
+        caps.maxComputeTextureImageUnits    = 16;
+        caps.maxComputeSharedMemorySize     = 16384;
+        caps.maxComputeUniformComponents    = 1024;
+        caps.maxComputeAtomicCounterBuffers = 1;
+        caps.maxComputeAtomicCounters       = 8;
+        caps.maxComputeImageUniforms        = 4;
+        caps.maxCombinedComputeUniformComponents =
+            caps.maxComputeUniformBlocks * static_cast<GLuint>(caps.maxUniformBlockSize / 4) +
+            caps.maxComputeUniformComponents;
+        caps.maxComputeShaderStorageBlocks = 4;
+
+        // Table 20.46
+        caps.maxUniformBufferBindings = 36;
+        caps.maxCombinedFragmentUniformComponents =
+            caps.maxFragmentUniformBlocks * (caps.maxUniformBlockSize / 4) +
+            caps.maxFragmentUniformComponents;
+        caps.maxCombinedTextureImageUnits     = 48;
+        caps.maxCombinedShaderOutputResources = 4;
+
+        // Table 20.47
+        caps.maxUniformLocations                = 1024;
+        caps.maxAtomicCounterBufferBindings     = 1;
+        caps.maxAtomicCounterBufferSize         = 32;
+        caps.maxCombinedAtomicCounterBuffers    = 1;
+        caps.maxCombinedAtomicCounters          = 8;
+        caps.maxImageUnits                      = 4;
+        caps.maxCombinedImageUniforms           = 4;
+        caps.maxShaderStorageBufferBindings     = 4;
+        caps.maxShaderStorageBlockSize          = 1 << 27;
+        caps.maxCombinedShaderStorageBlocks     = 4;
+        caps.shaderStorageBufferOffsetAlignment = 256;
+    }
+
+    return caps;
+}
+}
+
+namespace egl
+{
+
+Caps::Caps()
+    : textureNPOT(false)
+{
+}
+
+DisplayExtensions::DisplayExtensions()
+    : createContextRobustness(false),
+      d3dShareHandleClientBuffer(false),
+      d3dTextureClientBuffer(false),
+      surfaceD3DTexture2DShareHandle(false),
+      querySurfacePointer(false),
+      windowFixedSize(false),
+      keyedMutex(false),
+      surfaceOrientation(false),
+      postSubBuffer(false),
+      createContext(false),
+      deviceQuery(false),
+      image(false),
+      imageBase(false),
+      imagePixmap(false),
+      glTexture2DImage(false),
+      glTextureCubemapImage(false),
+      glTexture3DImage(false),
+      glRenderbufferImage(false),
+      getAllProcAddresses(false),
+      flexibleSurfaceCompatibility(false),
+      directComposition(false),
+      createContextNoError(false),
+      stream(false),
+      streamConsumerGLTexture(false),
+      streamConsumerGLTextureYUV(false),
+      streamProducerD3DTextureNV12(false),
+      createContextWebGLCompatibility(false),
+      createContextBindGeneratesResource(false),
+      getSyncValues(false),
+      swapBuffersWithDamage(false),
+      pixelFormatFloat(false),
+      surfacelessContext(false),
+      displayTextureShareGroup(false),
+      createContextClientArrays(false),
+      createContextRobustResourceInitialization(false)
+{
+}
+
+std::vector<std::string> DisplayExtensions::getStrings() const
+{
+    std::vector<std::string> extensionStrings;
+
+    // clang-format off
+    //                   | Extension name                                       | Supported flag                    | Output vector   |
+    InsertExtensionString("EGL_EXT_create_context_robustness",                   createContextRobustness,            &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer",            d3dShareHandleClientBuffer,         &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_d3d_texture_client_buffer",                 d3dTextureClientBuffer,             &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle",       surfaceD3DTexture2DShareHandle,     &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_query_surface_pointer",                     querySurfacePointer,                &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_window_fixed_size",                         windowFixedSize,                    &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_keyed_mutex",                               keyedMutex,                         &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_surface_orientation",                       surfaceOrientation,                 &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_direct_composition",                        directComposition,                  &extensionStrings);
+    InsertExtensionString("EGL_NV_post_sub_buffer",                              postSubBuffer,                      &extensionStrings);
+    InsertExtensionString("EGL_KHR_create_context",                              createContext,                      &extensionStrings);
+    InsertExtensionString("EGL_EXT_device_query",                                deviceQuery,                        &extensionStrings);
+    InsertExtensionString("EGL_KHR_image",                                       image,                              &extensionStrings);
+    InsertExtensionString("EGL_KHR_image_base",                                  imageBase,                          &extensionStrings);
+    InsertExtensionString("EGL_KHR_image_pixmap",                                imagePixmap,                        &extensionStrings);
+    InsertExtensionString("EGL_KHR_gl_texture_2D_image",                         glTexture2DImage,                   &extensionStrings);
+    InsertExtensionString("EGL_KHR_gl_texture_cubemap_image",                    glTextureCubemapImage,              &extensionStrings);
+    InsertExtensionString("EGL_KHR_gl_texture_3D_image",                         glTexture3DImage,                   &extensionStrings);
+    InsertExtensionString("EGL_KHR_gl_renderbuffer_image",                       glRenderbufferImage,                &extensionStrings);
+    InsertExtensionString("EGL_KHR_get_all_proc_addresses",                      getAllProcAddresses,                &extensionStrings);
+    InsertExtensionString("EGL_KHR_stream",                                      stream,                             &extensionStrings);
+    InsertExtensionString("EGL_KHR_stream_consumer_gltexture",                   streamConsumerGLTexture,            &extensionStrings);
+    InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv",                streamConsumerGLTextureYUV,         &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility",            flexibleSurfaceCompatibility,       &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12",          streamProducerD3DTextureNV12,       &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility",        createContextWebGLCompatibility,    &extensionStrings);
+    InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings);
+    InsertExtensionString("EGL_CHROMIUM_sync_control",                           getSyncValues,                      &extensionStrings);
+    InsertExtensionString("EGL_EXT_swap_buffers_with_damage",                    swapBuffersWithDamage,              &extensionStrings);
+    InsertExtensionString("EGL_EXT_pixel_format_float",                          pixelFormatFloat,                   &extensionStrings);
+    InsertExtensionString("EGL_KHR_surfaceless_context",                         surfacelessContext,                 &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_display_texture_share_group",               displayTextureShareGroup,           &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_create_context_client_arrays",              createContextClientArrays,          &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_create_context_robust_resource_initialization", createContextRobustResourceInitialization, &extensionStrings);
+    // TODO(jmadill): Enable this when complete.
+    //InsertExtensionString("KHR_create_context_no_error",                       createContextNoError,               &extensionStrings);
+    // clang-format on
+
+    return extensionStrings;
+}
+
+DeviceExtensions::DeviceExtensions()
+    : deviceD3D(false)
+{
+}
+
+std::vector<std::string> DeviceExtensions::getStrings() const
+{
+    std::vector<std::string> extensionStrings;
+
+    //                   | Extension name                                 | Supported flag                | Output vector   |
+    InsertExtensionString("EGL_ANGLE_device_d3d",                          deviceD3D,                      &extensionStrings);
+
+    return extensionStrings;
+}
+
+ClientExtensions::ClientExtensions()
+    : clientExtensions(false),
+      platformBase(false),
+      platformDevice(false),
+      platformANGLE(false),
+      platformANGLED3D(false),
+      platformANGLEOpenGL(false),
+      platformANGLEVulkan(false),
+      deviceCreation(false),
+      deviceCreationD3D11(false),
+      x11Visual(false),
+      experimentalPresentPath(false),
+      clientGetAllProcAddresses(false)
+{
+}
+
+std::vector<std::string> ClientExtensions::getStrings() const
+{
+    std::vector<std::string> extensionStrings;
+
+    // clang-format off
+    //                   | Extension name                         | Supported flag           | Output vector   |
+    InsertExtensionString("EGL_EXT_client_extensions",             clientExtensions,          &extensionStrings);
+    InsertExtensionString("EGL_EXT_platform_base",                 platformBase,              &extensionStrings);
+    InsertExtensionString("EGL_EXT_platform_device",               platformDevice,            &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_platform_angle",              platformANGLE,             &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_platform_angle_d3d",          platformANGLED3D,          &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_platform_angle_opengl",       platformANGLEOpenGL,       &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_platform_angle_null",         platformANGLENULL,         &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_platform_angle_vulkan",       platformANGLEVulkan,       &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_device_creation",             deviceCreation,            &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_device_creation_d3d11",       deviceCreationD3D11,       &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_x11_visual",                  x11Visual,                 &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_experimental_present_path",   experimentalPresentPath,   &extensionStrings);
+    InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
+    // clang-format on
+
+    return extensionStrings;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/Caps.h b/src/third_party/angle/src/libANGLE/Caps.h
new file mode 100644
index 0000000..29041a1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Caps.h
@@ -0,0 +1,735 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_CAPS_H_
+#define LIBANGLE_CAPS_H_
+
+#include "angle_gl.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Version.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <array>
+
+namespace gl
+{
+
+struct Extensions;
+
+typedef std::set<GLuint> SupportedSampleSet;
+
+struct TextureCaps
+{
+    TextureCaps();
+
+    // Supports for basic texturing: glTexImage, glTexSubImage, etc
+    bool texturable;
+
+    // Support for linear or anisotropic filtering
+    bool filterable;
+
+    // Support for being used as a framebuffer attachment or renderbuffer format
+    bool renderable;
+
+    // Set of supported sample counts, only guaranteed to be valid in ES3.
+    SupportedSampleSet sampleCounts;
+
+    // Get the maximum number of samples supported
+    GLuint getMaxSamples() const;
+
+    // Get the number of supported samples that is at least as many as requested.  Returns 0 if
+    // there are no sample counts available
+    GLuint getNearestSamples(GLuint requestedSamples) const;
+};
+
+TextureCaps GenerateMinimumTextureCaps(GLenum internalFormat,
+                                       const Version &clientVersion,
+                                       const Extensions &extensions);
+
+class TextureCapsMap
+{
+  public:
+    typedef std::map<GLenum, TextureCaps>::const_iterator const_iterator;
+
+    void insert(GLenum internalFormat, const TextureCaps &caps);
+    void remove(GLenum internalFormat);
+    void clear();
+
+    const TextureCaps &get(GLenum internalFormat) const;
+
+    const_iterator begin() const;
+    const_iterator end() const;
+
+    size_t size() const;
+
+  private:
+    typedef std::map<GLenum, TextureCaps> InternalFormatToCapsMap;
+    InternalFormatToCapsMap mCapsMap;
+};
+
+TextureCapsMap GenerateMinimumTextureCapsMap(const Version &clientVersion,
+                                             const Extensions &extensions);
+
+struct Extensions
+{
+    Extensions();
+
+    // Generate a vector of supported extension strings
+    std::vector<std::string> getStrings() const;
+
+    // Set all texture related extension support based on the supported textures.
+    // Determines support for:
+    // GL_OES_packed_depth_stencil
+    // GL_OES_rgb8_rgba8
+    // GL_EXT_texture_format_BGRA8888
+    // GL_EXT_color_buffer_half_float,
+    // GL_OES_texture_half_float, GL_OES_texture_half_float_linear
+    // GL_OES_texture_float, GL_OES_texture_float_linear
+    // GL_EXT_texture_rg
+    // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3,
+    // GL_ANGLE_texture_compression_dxt5
+    // GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr
+    // GL_OES_compressed_ETC1_RGB8_texture
+    // GL_EXT_sRGB
+    // GL_ANGLE_depth_texture, GL_OES_depth32
+    // GL_EXT_color_buffer_float
+    // GL_EXT_texture_norm16
+    void setTextureExtensionSupport(const TextureCapsMap &textureCaps);
+
+    // ES2 Extension support
+
+    // GL_OES_element_index_uint
+    bool elementIndexUint;
+
+    // GL_OES_packed_depth_stencil
+    bool packedDepthStencil;
+
+    // GL_OES_get_program_binary
+    bool getProgramBinary;
+
+    // GL_OES_rgb8_rgba8
+    // Implies that TextureCaps for GL_RGB8 and GL_RGBA8 exist
+    bool rgb8rgba8;
+
+    // GL_EXT_texture_format_BGRA8888
+    // Implies that TextureCaps for GL_BGRA8 exist
+    bool textureFormatBGRA8888;
+
+    // GL_EXT_read_format_bgra
+    bool readFormatBGRA;
+
+    // GL_NV_pixel_buffer_object
+    bool pixelBufferObject;
+
+    // GL_OES_mapbuffer and GL_EXT_map_buffer_range
+    bool mapBuffer;
+    bool mapBufferRange;
+
+    // GL_EXT_color_buffer_half_float
+    // Together with GL_OES_texture_half_float in a GLES 2.0 context, implies that half-float
+    // textures are renderable.
+    bool colorBufferHalfFloat;
+
+    // GL_OES_texture_half_float and GL_OES_texture_half_float_linear
+    // Implies that TextureCaps for GL_RGB16F, GL_RGBA16F, GL_ALPHA32F_EXT, GL_LUMINANCE32F_EXT and
+    // GL_LUMINANCE_ALPHA32F_EXT exist
+    bool textureHalfFloat;
+    bool textureHalfFloatLinear;
+
+    // GL_OES_texture_float and GL_OES_texture_float_linear
+    // Implies that TextureCaps for GL_RGB32F, GL_RGBA32F, GL_ALPHA16F_EXT, GL_LUMINANCE16F_EXT and
+    // GL_LUMINANCE_ALPHA16F_EXT exist
+    bool textureFloat;
+    bool textureFloatLinear;
+
+    // GL_EXT_texture_rg
+    // Implies that TextureCaps for GL_R8, GL_RG8 (and floating point R/RG texture formats if floating point extensions
+    // are also present) exist
+    bool textureRG;
+
+    // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3 and GL_ANGLE_texture_compression_dxt5
+    // Implies that TextureCaps exist for GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
+    // GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE and GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE
+    bool textureCompressionDXT1;
+    bool textureCompressionDXT3;
+    bool textureCompressionDXT5;
+
+    // GL_EXT_texture_compression_s3tc_srgb
+    // Implies that TextureCaps exist for GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
+    // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, and
+    // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
+    bool textureCompressionS3TCsRGB;
+
+    // GL_KHR_texture_compression_astc_hdr
+    bool textureCompressionASTCHDR;
+
+    // GL_KHR_texture_compression_astc_ldr
+    bool textureCompressionASTCLDR;
+
+    // GL_OES_compressed_ETC1_RGB8_texture
+    // Implies that TextureCaps for GL_ETC1_RGB8_OES exist
+    bool compressedETC1RGB8Texture;
+
+    // GL_EXT_sRGB
+    // Implies that TextureCaps for GL_SRGB8_ALPHA8 and GL_SRGB8 exist
+    // TODO: Don't advertise this extension in ES3
+    bool sRGB;
+
+    // GL_ANGLE_depth_texture
+    bool depthTextures;
+
+    // GL_OES_depth32
+    // Allows DEPTH_COMPONENT32_OES as a valid Renderbuffer format.
+    bool depth32;
+
+    // GL_EXT_texture_storage
+    bool textureStorage;
+
+    // GL_OES_texture_npot
+    bool textureNPOT;
+
+    // GL_EXT_draw_buffers
+    bool drawBuffers;
+
+    // GL_EXT_texture_filter_anisotropic
+    bool textureFilterAnisotropic;
+    GLfloat maxTextureAnisotropy;
+
+    // GL_EXT_occlusion_query_boolean
+    bool occlusionQueryBoolean;
+
+    // GL_NV_fence
+    bool fence;
+
+    // GL_ANGLE_timer_query
+    bool timerQuery;
+
+    // GL_EXT_disjoint_timer_query
+    bool disjointTimerQuery;
+    GLuint queryCounterBitsTimeElapsed;
+    GLuint queryCounterBitsTimestamp;
+
+    // GL_EXT_robustness
+    bool robustness;
+
+    // GL_EXT_blend_minmax
+    bool blendMinMax;
+
+    // GL_ANGLE_framebuffer_blit
+    bool framebufferBlit;
+
+    // GL_ANGLE_framebuffer_multisample
+    bool framebufferMultisample;
+
+    // GL_ANGLE_instanced_arrays
+    bool instancedArrays;
+
+    // GL_ANGLE_pack_reverse_row_order
+    bool packReverseRowOrder;
+
+    // GL_OES_standard_derivatives
+    bool standardDerivatives;
+
+    // GL_EXT_shader_texture_lod
+    bool shaderTextureLOD;
+
+    // GL_EXT_shader_framebuffer_fetch
+    bool shaderFramebufferFetch;
+
+    // GL_ARM_shader_framebuffer_fetch
+    bool ARMshaderFramebufferFetch;
+
+    // GL_NV_shader_framebuffer_fetch
+    bool NVshaderFramebufferFetch;
+
+    // GL_EXT_frag_depth
+    bool fragDepth;
+
+    // GL_ANGLE_texture_usage
+    bool textureUsage;
+
+    // GL_ANGLE_translated_shader_source
+    bool translatedShaderSource;
+
+    // GL_OES_fbo_render_mipmap
+    bool fboRenderMipmap;
+
+    // GL_EXT_discard_framebuffer
+    bool discardFramebuffer;
+
+    // EXT_debug_marker
+    bool debugMarker;
+
+    // GL_OES_EGL_image
+    bool eglImage;
+
+    // GL_OES_EGL_image_external
+    bool eglImageExternal;
+
+    // GL_OES_EGL_image_external_essl3
+    bool eglImageExternalEssl3;
+
+    // NV_EGL_stream_consumer_external
+    bool eglStreamConsumerExternal;
+
+    // EXT_unpack_subimage
+    bool unpackSubimage;
+
+    // NV_pack_subimage
+    bool packSubimage;
+
+    // GL_OES_vertex_array_object
+    bool vertexArrayObject;
+
+    // GL_KHR_debug
+    bool debug;
+    GLuint maxDebugMessageLength;
+    GLuint maxDebugLoggedMessages;
+    GLuint maxDebugGroupStackDepth;
+    GLuint maxLabelLength;
+
+    // KHR_no_error
+    bool noError;
+
+    // GL_ANGLE_lossy_etc_decode
+    bool lossyETCDecode;
+
+    // GL_CHROMIUM_bind_uniform_location
+    bool bindUniformLocation;
+
+    // GL_CHROMIUM_sync_query
+    bool syncQuery;
+
+    // GL_CHROMIUM_copy_texture
+    bool copyTexture;
+
+    // GL_CHROMIUM_copy_compressed_texture
+    bool copyCompressedTexture;
+
+    // GL_ANGLE_webgl_compatibility
+    bool webglCompatibility;
+
+    // GL_ANGLE_request_extension
+    bool requestExtension;
+
+    // GL_CHROMIUM_bind_generates_resource
+    bool bindGeneratesResource;
+
+    // GL_ANGLE_robust_client_memory
+    bool robustClientMemory;
+
+    // GL_EXT_texture_sRGB_decode
+    bool textureSRGBDecode;
+
+    // GL_EXT_sRGB_write_control
+    bool sRGBWriteControl;
+
+    // GL_CHROMIUM_color_buffer_float_rgb
+    bool colorBufferFloatRGB;
+
+    // GL_CHROMIUM_color_buffer_float_rgba
+    bool colorBufferFloatRGBA;
+
+    // ES3 Extension support
+
+    // GL_EXT_color_buffer_float
+    bool colorBufferFloat;
+
+    // GL_EXT_multisample_compatibility.
+    // written against ES 3.1 but can apply to earlier versions.
+    bool multisampleCompatibility;
+
+    // GL_CHROMIUM_framebuffer_mixed_samples
+    bool framebufferMixedSamples;
+
+    // GL_EXT_texture_norm16
+    // written against ES 3.1 but can apply to ES 3.0 as well.
+    bool textureNorm16;
+
+    // GL_CHROMIUM_path_rendering
+    bool pathRendering;
+
+    // GL_OES_surfaceless_context
+    bool surfacelessContext;
+
+    // GL_ANGLE_client_arrays
+    bool clientArrays;
+
+    // GL_ANGLE_robust_resource_initialization
+    bool robustResourceInitialization;
+};
+
+struct ExtensionInfo
+{
+    // If this extension can be enabled with glRequestExtension (GL_ANGLE_request_extension)
+    bool Requestable = false;
+
+    // Pointer to a boolean member of the Extensions struct
+    typedef bool(Extensions::*ExtensionBool);
+    ExtensionBool ExtensionsMember = nullptr;
+};
+
+using ExtensionInfoMap = std::map<std::string, ExtensionInfo>;
+const ExtensionInfoMap &GetExtensionInfoMap();
+
+struct Limitations
+{
+    Limitations();
+
+    // Renderer doesn't support gl_FrontFacing in fragment shaders
+    bool noFrontFacingSupport;
+
+    // Renderer doesn't support GL_SAMPLE_ALPHA_TO_COVERAGE
+    bool noSampleAlphaToCoverageSupport;
+
+    // In glVertexAttribDivisorANGLE, attribute zero must have a zero divisor
+    bool attributeZeroRequiresZeroDivisorInEXT;
+
+    // Unable to support different values for front and back faces for stencil refs and masks
+    bool noSeparateStencilRefsAndMasks;
+
+    // Renderer doesn't support non-constant indexing loops in fragment shader
+    bool shadersRequireIndexedLoopValidation;
+
+    // Renderer doesn't support Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA
+    // and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR blend functions.
+    bool noSimultaneousConstantColorAndAlphaBlendFunc;
+};
+
+struct TypePrecision
+{
+    TypePrecision();
+
+    void setIEEEFloat();
+    void setTwosComplementInt(unsigned int bits);
+    void setSimulatedFloat(unsigned int range, unsigned int precision);
+    void setSimulatedInt(unsigned int range);
+
+    void get(GLint *returnRange, GLint *returnPrecision) const;
+
+    std::array<GLint, 2> range;
+    GLint precision;
+};
+
+struct Caps
+{
+    Caps();
+
+    // ES 3.1 (April 29, 2015) 20.39: implementation dependent values
+    GLuint64 maxElementIndex;
+    GLuint max3DTextureSize;
+    GLuint max2DTextureSize;
+    GLuint maxArrayTextureLayers;
+    GLfloat maxLODBias;
+    GLuint maxCubeMapTextureSize;
+    GLuint maxRenderbufferSize;
+    GLfloat minAliasedPointSize;
+    GLfloat maxAliasedPointSize;
+    GLfloat minAliasedLineWidth;
+    GLfloat maxAliasedLineWidth;
+
+    // ES 3.1 (April 29, 2015) 20.40: implementation dependent values (cont.)
+    GLuint maxDrawBuffers;
+    GLuint maxFramebufferWidth;
+    GLuint maxFramebufferHeight;
+    GLuint maxFramebufferSamples;
+    GLuint maxColorAttachments;
+    GLuint maxViewportWidth;
+    GLuint maxViewportHeight;
+    GLuint maxSampleMaskWords;
+    GLuint maxColorTextureSamples;
+    GLuint maxDepthTextureSamples;
+    GLuint maxIntegerSamples;
+    GLuint64 maxServerWaitTimeout;
+
+    // ES 3.1 (April 29, 2015) Table 20.41: Implementation dependent values (cont.)
+    GLint maxVertexAttribRelativeOffset;
+    GLuint maxVertexAttribBindings;
+    GLint maxVertexAttribStride;
+    GLuint maxElementsIndices;
+    GLuint maxElementsVertices;
+    std::vector<GLenum> compressedTextureFormats;
+    std::vector<GLenum> programBinaryFormats;
+    std::vector<GLenum> shaderBinaryFormats;
+    TypePrecision vertexHighpFloat;
+    TypePrecision vertexMediumpFloat;
+    TypePrecision vertexLowpFloat;
+    TypePrecision vertexHighpInt;
+    TypePrecision vertexMediumpInt;
+    TypePrecision vertexLowpInt;
+    TypePrecision fragmentHighpFloat;
+    TypePrecision fragmentMediumpFloat;
+    TypePrecision fragmentLowpFloat;
+    TypePrecision fragmentHighpInt;
+    TypePrecision fragmentMediumpInt;
+    TypePrecision fragmentLowpInt;
+
+    // ES 3.1 (April 29, 2015) Table 20.43: Implementation dependent Vertex shader limits
+    GLuint maxVertexAttributes;
+    GLuint maxVertexUniformComponents;
+    GLuint maxVertexUniformVectors;
+    GLuint maxVertexUniformBlocks;
+    GLuint maxVertexOutputComponents;
+    GLuint maxVertexTextureImageUnits;
+    GLuint maxVertexAtomicCounterBuffers;
+    GLuint maxVertexAtomicCounters;
+    GLuint maxVertexImageUniforms;
+    GLuint maxVertexShaderStorageBlocks;
+
+    // ES 3.1 (April 29, 2015) Table 20.44: Implementation dependent Fragment shader limits
+    GLuint maxFragmentUniformComponents;
+    GLuint maxFragmentUniformVectors;
+    GLuint maxFragmentUniformBlocks;
+    GLuint maxFragmentInputComponents;
+    GLuint maxTextureImageUnits;
+    GLuint maxFragmentAtomicCounterBuffers;
+    GLuint maxFragmentAtomicCounters;
+    GLuint maxFragmentImageUniforms;
+    GLuint maxFragmentShaderStorageBlocks;
+    GLint minProgramTextureGatherOffset;
+    GLuint maxProgramTextureGatherOffset;
+    GLint minProgramTexelOffset;
+    GLint maxProgramTexelOffset;
+
+    // ES 3.1 (April 29, 2015) Table 20.45: implementation dependent compute shader limits
+    std::array<GLuint, 3> maxComputeWorkGroupCount;
+    std::array<GLuint, 3> maxComputeWorkGroupSize;
+    GLuint maxComputeWorkGroupInvocations;
+    GLuint maxComputeUniformBlocks;
+    GLuint maxComputeTextureImageUnits;
+    GLuint maxComputeSharedMemorySize;
+    GLuint maxComputeUniformComponents;
+    GLuint maxComputeAtomicCounterBuffers;
+    GLuint maxComputeAtomicCounters;
+    GLuint maxComputeImageUniforms;
+    GLuint maxCombinedComputeUniformComponents;
+    GLuint maxComputeShaderStorageBlocks;
+
+    // ES 3.1 (April 29, 2015) Table 20.46: implementation dependent aggregate shader limits
+    GLuint maxUniformBufferBindings;
+    GLuint64 maxUniformBlockSize;
+    GLuint uniformBufferOffsetAlignment;
+    GLuint maxCombinedUniformBlocks;
+    GLuint64 maxCombinedVertexUniformComponents;
+    GLuint64 maxCombinedFragmentUniformComponents;
+    GLuint maxVaryingComponents;
+    GLuint maxVaryingVectors;
+    GLuint maxCombinedTextureImageUnits;
+    GLuint maxCombinedShaderOutputResources;
+
+    // ES 3.1 (April 29, 2015) Table 20.47: implementation dependent aggregate shader limits (cont.)
+    GLuint maxUniformLocations;
+    GLuint maxAtomicCounterBufferBindings;
+    GLuint maxAtomicCounterBufferSize;
+    GLuint maxCombinedAtomicCounterBuffers;
+    GLuint maxCombinedAtomicCounters;
+    GLuint maxImageUnits;
+    GLuint maxCombinedImageUniforms;
+    GLuint maxShaderStorageBufferBindings;
+    GLuint64 maxShaderStorageBlockSize;
+    GLuint maxCombinedShaderStorageBlocks;
+    GLuint shaderStorageBufferOffsetAlignment;
+
+    // ES 3.1 (April 29, 2015) Table 20.48: implementation dependent transform feedback limits
+    GLuint maxTransformFeedbackInterleavedComponents;
+    GLuint maxTransformFeedbackSeparateAttributes;
+    GLuint maxTransformFeedbackSeparateComponents;
+
+    // ES 3.1 (April 29, 2015) Table 20.49: Framebuffer Dependent Values
+    GLuint maxSamples;
+};
+
+Caps GenerateMinimumCaps(const Version &clientVersion);
+}
+
+namespace egl
+{
+
+struct Caps
+{
+    Caps();
+
+    // Support for NPOT surfaces
+    bool textureNPOT;
+};
+
+struct DisplayExtensions
+{
+    DisplayExtensions();
+
+    // Generate a vector of supported extension strings
+    std::vector<std::string> getStrings() const;
+
+    // EGL_EXT_create_context_robustness
+    bool createContextRobustness;
+
+    // EGL_ANGLE_d3d_share_handle_client_buffer
+    bool d3dShareHandleClientBuffer;
+
+    // EGL_ANGLE_d3d_texture_client_buffer
+    bool d3dTextureClientBuffer;
+
+    // EGL_ANGLE_surface_d3d_texture_2d_share_handle
+    bool surfaceD3DTexture2DShareHandle;
+
+    // EGL_ANGLE_query_surface_pointer
+    bool querySurfacePointer;
+
+    // EGL_ANGLE_window_fixed_size
+    bool windowFixedSize;
+
+    // EGL_ANGLE_keyed_mutex
+    bool keyedMutex;
+
+    // EGL_ANGLE_surface_orientation
+    bool surfaceOrientation;
+
+    // EGL_NV_post_sub_buffer
+    bool postSubBuffer;
+
+    // EGL_KHR_create_context
+    bool createContext;
+
+    // EGL_EXT_device_query
+    bool deviceQuery;
+
+    // EGL_KHR_image
+    bool image;
+
+    // EGL_KHR_image_base
+    bool imageBase;
+
+    // EGL_KHR_image_pixmap
+    bool imagePixmap;
+
+    // EGL_KHR_gl_texture_2D_image
+    bool glTexture2DImage;
+
+    // EGL_KHR_gl_texture_cubemap_image
+    bool glTextureCubemapImage;
+
+    // EGL_KHR_gl_texture_3D_image
+    bool glTexture3DImage;
+
+    // EGL_KHR_gl_renderbuffer_image
+    bool glRenderbufferImage;
+
+    // EGL_KHR_get_all_proc_addresses
+    bool getAllProcAddresses;
+
+    // EGL_ANGLE_flexible_surface_compatibility
+    bool flexibleSurfaceCompatibility;
+
+    // EGL_ANGLE_direct_composition
+    bool directComposition;
+
+    // KHR_create_context_no_error
+    bool createContextNoError;
+
+    // EGL_KHR_stream
+    bool stream;
+
+    // EGL_KHR_stream_consumer_gltexture
+    bool streamConsumerGLTexture;
+
+    // EGL_NV_stream_consumer_gltexture_yuv
+    bool streamConsumerGLTextureYUV;
+
+    // EGL_ANGLE_stream_producer_d3d_texture_nv12
+    bool streamProducerD3DTextureNV12;
+
+    // EGL_ANGLE_create_context_webgl_compatibility
+    bool createContextWebGLCompatibility;
+
+    // EGL_CHROMIUM_create_context_bind_generates_resource
+    bool createContextBindGeneratesResource;
+
+    // EGL_CHROMIUM_get_sync_values
+    bool getSyncValues;
+
+    // EGL_EXT_swap_buffers_with_damage
+    bool swapBuffersWithDamage;
+
+    // EGL_EXT_pixel_format_float
+    bool pixelFormatFloat;
+
+    // EGL_KHR_surfaceless_context
+    bool surfacelessContext;
+
+    // EGL_ANGLE_display_texture_share_group
+    bool displayTextureShareGroup;
+
+    // EGL_ANGLE_create_context_client_arrays
+    bool createContextClientArrays;
+
+    // EGL_ANGLE_create_context_robust_resource_initialization
+    bool createContextRobustResourceInitialization;
+};
+
+struct DeviceExtensions
+{
+    DeviceExtensions();
+
+    // Generate a vector of supported extension strings
+    std::vector<std::string> getStrings() const;
+
+    // EGL_ANGLE_device_d3d
+    bool deviceD3D;
+};
+
+struct ClientExtensions
+{
+    ClientExtensions();
+
+    // Generate a vector of supported extension strings
+    std::vector<std::string> getStrings() const;
+
+    // EGL_EXT_client_extensions
+    bool clientExtensions;
+
+    // EGL_EXT_platform_base
+    bool platformBase;
+
+    // EGL_EXT_platform_device
+    bool platformDevice;
+
+    // EGL_ANGLE_platform_angle
+    bool platformANGLE;
+
+    // EGL_ANGLE_platform_angle_d3d
+    bool platformANGLED3D;
+
+    // EGL_ANGLE_platform_angle_opengl
+    bool platformANGLEOpenGL;
+
+    // EGL_ANGLE_platform_angle_null
+    bool platformANGLENULL;
+
+    // EGL_ANGLE_platform_angle_vulkan
+    bool platformANGLEVulkan;
+
+    // EGL_ANGLE_device_creation
+    bool deviceCreation;
+
+    // EGL_ANGLE_device_creation_d3d11
+    bool deviceCreationD3D11;
+
+    // EGL_ANGLE_x11_visual
+    bool x11Visual;
+
+    // EGL_ANGLE_experimental_present_path
+    bool experimentalPresentPath;
+
+    // EGL_KHR_client_get_all_proc_addresses
+    bool clientGetAllProcAddresses;
+};
+
+}  // namespace egl
+
+#endif // LIBANGLE_CAPS_H_
diff --git a/src/third_party/angle/src/libANGLE/Compiler.cpp b/src/third_party/angle/src/libANGLE/Compiler.cpp
new file mode 100644
index 0000000..23854d2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Compiler.cpp
@@ -0,0 +1,201 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Compiler.cpp: implements the gl::Compiler class.
+
+#include "libANGLE/Compiler.h"
+
+#include "common/debug.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/renderer/CompilerImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+
+namespace
+{
+
+// Global count of active shader compiler handles. Needed to know when to call sh::Initialize and
+// sh::Finalize.
+size_t activeCompilerHandles = 0;
+
+ShShaderSpec SelectShaderSpec(GLint majorVersion, GLint minorVersion, bool isWebGL)
+{
+    if (majorVersion >= 3)
+    {
+        if (minorVersion == 1)
+        {
+            return isWebGL ? SH_WEBGL3_SPEC : SH_GLES3_1_SPEC;
+        }
+        else
+        {
+            return isWebGL ? SH_WEBGL2_SPEC : SH_GLES3_SPEC;
+        }
+    }
+    return isWebGL ? SH_WEBGL_SPEC : SH_GLES2_SPEC;
+}
+
+}  // anonymous namespace
+
+Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
+    : mImplementation(implFactory->createCompiler()),
+      mSpec(SelectShaderSpec(state.getClientMajorVersion(),
+                             state.getClientMinorVersion(),
+                             state.getExtensions().webglCompatibility)),
+      mOutputType(mImplementation->getTranslatorOutputType()),
+      mResources(),
+      mFragmentCompiler(nullptr),
+      mVertexCompiler(nullptr),
+      mComputeCompiler(nullptr)
+{
+    ASSERT(state.getClientMajorVersion() == 2 || state.getClientMajorVersion() == 3);
+
+    const gl::Caps &caps             = state.getCaps();
+    const gl::Extensions &extensions = state.getExtensions();
+
+    sh::InitBuiltInResources(&mResources);
+    mResources.MaxVertexAttribs             = caps.maxVertexAttributes;
+    mResources.MaxVertexUniformVectors      = caps.maxVertexUniformVectors;
+    mResources.MaxVaryingVectors            = caps.maxVaryingVectors;
+    mResources.MaxVertexTextureImageUnits   = caps.maxVertexTextureImageUnits;
+    mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
+    mResources.MaxTextureImageUnits         = caps.maxTextureImageUnits;
+    mResources.MaxFragmentUniformVectors    = caps.maxFragmentUniformVectors;
+    mResources.MaxDrawBuffers               = caps.maxDrawBuffers;
+    mResources.OES_standard_derivatives     = extensions.standardDerivatives;
+    mResources.EXT_draw_buffers             = extensions.drawBuffers;
+    mResources.EXT_shader_texture_lod       = extensions.shaderTextureLOD;
+    mResources.OES_EGL_image_external          = extensions.eglImageExternal;
+    mResources.OES_EGL_image_external_essl3    = extensions.eglImageExternalEssl3;
+    mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal;
+    // TODO: use shader precision caps to determine if high precision is supported?
+    mResources.FragmentPrecisionHigh = 1;
+    mResources.EXT_frag_depth        = extensions.fragDepth;
+
+    // GLSL ES 3.0 constants
+    mResources.MaxVertexOutputVectors  = caps.maxVertexOutputComponents / 4;
+    mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
+    mResources.MinProgramTexelOffset   = caps.minProgramTexelOffset;
+    mResources.MaxProgramTexelOffset   = caps.maxProgramTexelOffset;
+
+    // GLSL ES 3.1 constants
+    mResources.MaxImageUnits                    = caps.maxImageUnits;
+    mResources.MaxVertexImageUniforms           = caps.maxVertexImageUniforms;
+    mResources.MaxFragmentImageUniforms         = caps.maxFragmentImageUniforms;
+    mResources.MaxComputeImageUniforms          = caps.maxComputeImageUniforms;
+    mResources.MaxCombinedImageUniforms         = caps.maxCombinedImageUniforms;
+    mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources;
+    mResources.MaxUniformLocations              = caps.maxUniformLocations;
+
+    for (size_t index = 0u; index < 3u; ++index)
+    {
+        mResources.MaxComputeWorkGroupCount[index] = caps.maxComputeWorkGroupCount[index];
+        mResources.MaxComputeWorkGroupSize[index]  = caps.maxComputeWorkGroupSize[index];
+    }
+
+    mResources.MaxComputeUniformComponents = caps.maxComputeUniformComponents;
+    mResources.MaxComputeTextureImageUnits = caps.maxComputeTextureImageUnits;
+
+    mResources.MaxComputeAtomicCounters       = caps.maxComputeAtomicCounters;
+    mResources.MaxComputeAtomicCounterBuffers = caps.maxComputeAtomicCounterBuffers;
+
+    mResources.MaxVertexAtomicCounters         = caps.maxVertexAtomicCounters;
+    mResources.MaxFragmentAtomicCounters       = caps.maxFragmentAtomicCounters;
+    mResources.MaxCombinedAtomicCounters       = caps.maxCombinedAtomicCounters;
+    mResources.MaxAtomicCounterBindings        = caps.maxAtomicCounterBufferBindings;
+    mResources.MaxVertexAtomicCounterBuffers   = caps.maxVertexAtomicCounterBuffers;
+    mResources.MaxFragmentAtomicCounterBuffers = caps.maxFragmentAtomicCounterBuffers;
+    mResources.MaxCombinedAtomicCounterBuffers = caps.maxCombinedAtomicCounterBuffers;
+    mResources.MaxAtomicCounterBufferSize      = caps.maxAtomicCounterBufferSize;
+
+    if (state.getClientMajorVersion() == 2 && !extensions.drawBuffers)
+    {
+        mResources.MaxDrawBuffers = 1;
+    }
+}
+
+Compiler::~Compiler()
+{
+    release();
+    SafeDelete(mImplementation);
+}
+
+Error Compiler::release()
+{
+    if (mFragmentCompiler)
+    {
+        sh::Destruct(mFragmentCompiler);
+        mFragmentCompiler = nullptr;
+
+        ASSERT(activeCompilerHandles > 0);
+        activeCompilerHandles--;
+    }
+
+    if (mVertexCompiler)
+    {
+        sh::Destruct(mVertexCompiler);
+        mVertexCompiler = nullptr;
+
+        ASSERT(activeCompilerHandles > 0);
+        activeCompilerHandles--;
+    }
+
+    if (mComputeCompiler)
+    {
+        sh::Destruct(mComputeCompiler);
+        mComputeCompiler = nullptr;
+
+        ASSERT(activeCompilerHandles > 0);
+        activeCompilerHandles--;
+    }
+
+    if (activeCompilerHandles == 0)
+    {
+        sh::Finalize();
+    }
+
+    mImplementation->release();
+
+    return gl::NoError();
+}
+
+ShHandle Compiler::getCompilerHandle(GLenum type)
+{
+    ShHandle *compiler = nullptr;
+    switch (type)
+    {
+        case GL_VERTEX_SHADER:
+            compiler = &mVertexCompiler;
+            break;
+
+        case GL_FRAGMENT_SHADER:
+            compiler = &mFragmentCompiler;
+            break;
+        case GL_COMPUTE_SHADER:
+            compiler = &mComputeCompiler;
+            break;
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+
+    if (!(*compiler))
+    {
+        if (activeCompilerHandles == 0)
+        {
+            sh::Initialize();
+        }
+
+        *compiler = sh::ConstructCompiler(type, mSpec, mOutputType, &mResources);
+        ASSERT(*compiler);
+        activeCompilerHandles++;
+    }
+
+    return *compiler;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/Compiler.h b/src/third_party/angle/src/libANGLE/Compiler.h
new file mode 100644
index 0000000..1422663
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Compiler.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Compiler.h: Defines the gl::Compiler class, abstracting the ESSL compiler
+// that a GL context holds.
+
+#ifndef LIBANGLE_COMPILER_H_
+#define LIBANGLE_COMPILER_H_
+
+#include "libANGLE/Error.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace rx
+{
+class CompilerImpl;
+class GLImplFactory;
+}
+
+namespace gl
+{
+class ContextState;
+
+class Compiler final : angle::NonCopyable
+{
+  public:
+    Compiler(rx::GLImplFactory *implFactory, const ContextState &data);
+    ~Compiler();
+
+    Error release();
+
+    ShHandle getCompilerHandle(GLenum type);
+    ShShaderOutput getShaderOutputType() const { return mOutputType; }
+
+  private:
+    rx::CompilerImpl *mImplementation;
+    ShShaderSpec mSpec;
+    ShShaderOutput mOutputType;
+    ShBuiltInResources mResources;
+
+    ShHandle mFragmentCompiler;
+    ShHandle mVertexCompiler;
+    ShHandle mComputeCompiler;
+};
+
+}  // namespace gl
+
+#endif // LIBANGLE_COMPILER_H_
diff --git a/src/third_party/angle/src/libANGLE/Config.cpp b/src/third_party/angle/src/libANGLE/Config.cpp
new file mode 100644
index 0000000..e0268d0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Config.cpp
@@ -0,0 +1,287 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Config.cpp: Implements the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.5] section 3.4 page 19.
+
+#include "libANGLE/Config.h"
+#include "libANGLE/AttributeMap.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "angle_gl.h"
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+
+namespace egl
+{
+
+Config::Config()
+    : renderTargetFormat(GL_NONE),
+      depthStencilFormat(GL_NONE),
+      bufferSize(0),
+      redSize(0),
+      greenSize(0),
+      blueSize(0),
+      luminanceSize(0),
+      alphaSize(0),
+      alphaMaskSize(0),
+      bindToTextureRGB(EGL_FALSE),
+      bindToTextureRGBA(EGL_FALSE),
+      colorBufferType(EGL_NONE),
+      configCaveat(EGL_NONE),
+      configID(0),
+      conformant(0),
+      depthSize(0),
+      level(0),
+      matchNativePixmap(EGL_FALSE),
+      maxPBufferWidth(0),
+      maxPBufferHeight(0),
+      maxPBufferPixels(0),
+      maxSwapInterval(0),
+      minSwapInterval(0),
+      nativeRenderable(EGL_FALSE),
+      nativeVisualID(0),
+      nativeVisualType(0),
+      renderableType(0),
+      sampleBuffers(0),
+      samples(0),
+      stencilSize(0),
+      surfaceType(0),
+      transparentType(EGL_NONE),
+      transparentRedValue(0),
+      transparentGreenValue(0),
+      transparentBlueValue(0),
+      optimalOrientation(0),
+      colorComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)
+{
+}
+
+EGLint ConfigSet::add(const Config &config)
+{
+    // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
+    EGLint id = static_cast<EGLint>(mConfigs.size()) + 1;
+
+    Config copyConfig(config);
+    copyConfig.configID = id;
+    mConfigs.insert(std::make_pair(id, copyConfig));
+
+    return id;
+}
+
+const Config &ConfigSet::get(EGLint id) const
+{
+    ASSERT(mConfigs.find(id) != mConfigs.end());
+    return mConfigs.find(id)->second;
+}
+
+void ConfigSet::clear()
+{
+    mConfigs.clear();
+}
+
+size_t ConfigSet::size() const
+{
+    return mConfigs.size();
+}
+
+bool ConfigSet::contains(const Config *config) const
+{
+    for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
+    {
+        const Config &item = i->second;
+        if (config == &item)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5] section 3.4.1.2 page 28.
+class ConfigSorter
+{
+  public:
+    explicit ConfigSorter(const AttributeMap &attributeMap)
+        : mWantRed(false),
+          mWantGreen(false),
+          mWantBlue(false),
+          mWantAlpha(false),
+          mWantLuminance(false)
+    {
+        scanForWantedComponents(attributeMap);
+    }
+
+    bool operator()(const Config *x, const Config *y) const
+    {
+        return (*this)(*x, *y);
+    }
+
+    bool operator()(const Config &x, const Config &y) const
+    {
+        #define SORT(attribute)                        \
+            if (x.attribute != y.attribute)            \
+            {                                          \
+                return x.attribute < y.attribute;      \
+            }
+
+        static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "Unexpected EGL enum value.");
+        SORT(configCaveat);
+
+        static_assert(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT < EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+                      "Unexpected order of EGL enums.");
+        SORT(colorComponentType);
+
+        static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value.");
+        SORT(colorBufferType);
+
+        // By larger total number of color bits, only considering those that are requested to be > 0.
+        EGLint xComponentsSize = wantedComponentsSize(x);
+        EGLint yComponentsSize = wantedComponentsSize(y);
+        if (xComponentsSize != yComponentsSize)
+        {
+            return xComponentsSize > yComponentsSize;
+        }
+
+        SORT(bufferSize);
+        SORT(sampleBuffers);
+        SORT(samples);
+        SORT(depthSize);
+        SORT(stencilSize);
+        SORT(alphaMaskSize);
+        SORT(nativeVisualType);
+        SORT(configID);
+
+        #undef SORT
+
+        return false;
+    }
+
+  private:
+    void scanForWantedComponents(const AttributeMap &attributeMap)
+    {
+        // [EGL 1.5] section 3.4.1.2 page 30
+        // Sorting rule #3: by larger total number of color bits, not considering
+        // components that are 0 or don't-care.
+        for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
+        {
+            EGLAttrib attributeKey   = attribIter->first;
+            EGLAttrib attributeValue = attribIter->second;
+            if (attributeKey != 0 && attributeValue != EGL_DONT_CARE)
+            {
+                switch (attributeKey)
+                {
+                case EGL_RED_SIZE:       mWantRed = true; break;
+                case EGL_GREEN_SIZE:     mWantGreen = true; break;
+                case EGL_BLUE_SIZE:      mWantBlue = true; break;
+                case EGL_ALPHA_SIZE:     mWantAlpha = true; break;
+                case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
+                }
+            }
+        }
+    }
+
+    EGLint wantedComponentsSize(const Config &config) const
+    {
+        EGLint total = 0;
+
+        if (mWantRed)       total += config.redSize;
+        if (mWantGreen)     total += config.greenSize;
+        if (mWantBlue)      total += config.blueSize;
+        if (mWantAlpha)     total += config.alphaSize;
+        if (mWantLuminance) total += config.luminanceSize;
+
+        return total;
+    }
+
+    bool mWantRed;
+    bool mWantGreen;
+    bool mWantBlue;
+    bool mWantAlpha;
+    bool mWantLuminance;
+};
+
+std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) const
+{
+    std::vector<const Config*> result;
+    result.reserve(mConfigs.size());
+
+    for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
+    {
+        const Config &config = configIter->second;
+        bool match = true;
+
+        for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
+        {
+            EGLAttrib attributeKey   = attribIter->first;
+            EGLAttrib attributeValue = attribIter->second;
+
+            switch (attributeKey)
+            {
+              case EGL_BUFFER_SIZE:               match = config.bufferSize >= attributeValue;                        break;
+              case EGL_ALPHA_SIZE:                match = config.alphaSize >= attributeValue;                         break;
+              case EGL_BLUE_SIZE:                 match = config.blueSize >= attributeValue;                          break;
+              case EGL_GREEN_SIZE:                match = config.greenSize >= attributeValue;                         break;
+              case EGL_RED_SIZE:                  match = config.redSize >= attributeValue;                           break;
+              case EGL_DEPTH_SIZE:                match = config.depthSize >= attributeValue;                         break;
+              case EGL_STENCIL_SIZE:              match = config.stencilSize >= attributeValue;                       break;
+              case EGL_CONFIG_CAVEAT:             match = config.configCaveat == (EGLenum)attributeValue;             break;
+              case EGL_CONFIG_ID:                 match = config.configID == attributeValue;                          break;
+              case EGL_LEVEL:                     match = config.level >= attributeValue;                             break;
+              case EGL_NATIVE_RENDERABLE:         match = config.nativeRenderable == (EGLBoolean)attributeValue;      break;
+              case EGL_NATIVE_VISUAL_TYPE:        match = config.nativeVisualType == attributeValue;                  break;
+              case EGL_SAMPLES:                   match = config.samples >= attributeValue;                           break;
+              case EGL_SAMPLE_BUFFERS:            match = config.sampleBuffers >= attributeValue;                     break;
+              case EGL_SURFACE_TYPE:              match = (config.surfaceType & attributeValue) == attributeValue;    break;
+              case EGL_TRANSPARENT_TYPE:          match = config.transparentType == (EGLenum)attributeValue;          break;
+              case EGL_TRANSPARENT_BLUE_VALUE:    match = config.transparentBlueValue == attributeValue;              break;
+              case EGL_TRANSPARENT_GREEN_VALUE:   match = config.transparentGreenValue == attributeValue;             break;
+              case EGL_TRANSPARENT_RED_VALUE:     match = config.transparentRedValue == attributeValue;               break;
+              case EGL_BIND_TO_TEXTURE_RGB:       match = config.bindToTextureRGB == (EGLBoolean)attributeValue;      break;
+              case EGL_BIND_TO_TEXTURE_RGBA:      match = config.bindToTextureRGBA == (EGLBoolean)attributeValue;     break;
+              case EGL_MIN_SWAP_INTERVAL:         match = config.minSwapInterval == attributeValue;                   break;
+              case EGL_MAX_SWAP_INTERVAL:         match = config.maxSwapInterval == attributeValue;                   break;
+              case EGL_LUMINANCE_SIZE:            match = config.luminanceSize >= attributeValue;                     break;
+              case EGL_ALPHA_MASK_SIZE:           match = config.alphaMaskSize >= attributeValue;                     break;
+              case EGL_COLOR_BUFFER_TYPE:         match = config.colorBufferType == (EGLenum)attributeValue;          break;
+              case EGL_RENDERABLE_TYPE:           match = (config.renderableType & attributeValue) == attributeValue; break;
+              case EGL_MATCH_NATIVE_PIXMAP:       match = false; UNIMPLEMENTED();                                     break;
+              case EGL_CONFORMANT:                match = (config.conformant & attributeValue) == attributeValue;     break;
+              case EGL_MAX_PBUFFER_WIDTH:         match = config.maxPBufferWidth >= attributeValue;                   break;
+              case EGL_MAX_PBUFFER_HEIGHT:        match = config.maxPBufferHeight >= attributeValue;                  break;
+              case EGL_MAX_PBUFFER_PIXELS:        match = config.maxPBufferPixels >= attributeValue;                  break;
+              case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+                  match = config.optimalOrientation == attributeValue;
+                  break;
+              case EGL_COLOR_COMPONENT_TYPE_EXT:
+                  match = config.colorComponentType == static_cast<EGLenum>(attributeValue);
+                  break;
+              default: UNREACHABLE();
+            }
+
+            if (!match)
+            {
+                break;
+            }
+        }
+
+        if (match)
+        {
+            result.push_back(&config);
+        }
+    }
+
+    // Sort the result
+    std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
+
+    return result;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/Config.h b/src/third_party/angle/src/libANGLE/Config.h
new file mode 100644
index 0000000..fb0147e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Config.h
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Config.h: Defines the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.5] section 3.4 page 19.
+
+#ifndef INCLUDE_CONFIG_H_
+#define INCLUDE_CONFIG_H_
+
+#include "libANGLE/AttributeMap.h"
+
+#include "common/angleutils.h"
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+#include <map>
+#include <vector>
+
+namespace egl
+{
+
+struct Config
+{
+    Config();
+
+    GLenum renderTargetFormat;      // TODO(geofflang): remove this
+    GLenum depthStencilFormat;      // TODO(geofflang): remove this
+
+    EGLint bufferSize;              // Depth of the color buffer
+    EGLint redSize;                 // Bits of Red in the color buffer
+    EGLint greenSize;               // Bits of Green in the color buffer
+    EGLint blueSize;                // Bits of Blue in the color buffer
+    EGLint luminanceSize;           // Bits of Luminance in the color buffer
+    EGLint alphaSize;               // Bits of Alpha in the color buffer
+    EGLint alphaMaskSize;           // Bits of Alpha Mask in the mask buffer
+    EGLBoolean bindToTextureRGB;    // True if bindable to RGB textures.
+    EGLBoolean bindToTextureRGBA;   // True if bindable to RGBA textures.
+    EGLenum colorBufferType;        // Color buffer type
+    EGLenum configCaveat;           // Any caveats for the configuration
+    EGLint configID;                // Unique EGLConfig identifier
+    EGLint conformant;              // Whether contexts created with this config are conformant
+    EGLint depthSize;               // Bits of Z in the depth buffer
+    EGLint level;                   // Frame buffer level
+    EGLBoolean matchNativePixmap;   // Match the native pixmap format
+    EGLint maxPBufferWidth;         // Maximum width of pbuffer
+    EGLint maxPBufferHeight;        // Maximum height of pbuffer
+    EGLint maxPBufferPixels;        // Maximum size of pbuffer
+    EGLint maxSwapInterval;         // Maximum swap interval
+    EGLint minSwapInterval;         // Minimum swap interval
+    EGLBoolean nativeRenderable;    // EGL_TRUE if native rendering APIs can render to surface
+    EGLint nativeVisualID;          // Handle of corresponding native visual
+    EGLint nativeVisualType;        // Native visual type of the associated visual
+    EGLint renderableType;          // Which client rendering APIs are supported.
+    EGLint sampleBuffers;           // Number of multisample buffers
+    EGLint samples;                 // Number of samples per pixel
+    EGLint stencilSize;             // Bits of Stencil in the stencil buffer
+    EGLint surfaceType;             // Which types of EGL surfaces are supported.
+    EGLenum transparentType;        // Type of transparency supported
+    EGLint transparentRedValue;     // Transparent red value
+    EGLint transparentGreenValue;   // Transparent green value
+    EGLint transparentBlueValue;    // Transparent blue value
+    EGLint optimalOrientation;      // Optimal window surface orientation
+    EGLenum colorComponentType;     // Color component type
+};
+
+class ConfigSet
+{
+  public:
+    EGLint add(const Config &config);
+    const Config &get(EGLint id) const;
+
+    void clear();
+
+    size_t size() const;
+
+    bool contains(const Config *config) const;
+
+    // Filter configurations based on the table in [EGL 1.5] section 3.4.1.2 page 29
+    std::vector<const Config*> filter(const AttributeMap &attributeMap) const;
+
+  private:
+    typedef std::map<EGLint, const Config> ConfigMap;
+    ConfigMap mConfigs;
+};
+
+}
+
+#endif   // INCLUDE_CONFIG_H_
diff --git a/src/third_party/angle/src/libANGLE/Config_unittest.cpp b/src/third_party/angle/src/libANGLE/Config_unittest.cpp
new file mode 100644
index 0000000..4c49df6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Config_unittest.cpp
@@ -0,0 +1,220 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Config.h"
+
+// Create a generic, valid EGL config that can be modified to test sorting and
+// filtering routines
+static egl::Config GenerateGenericConfig()
+{
+    egl::Config config;
+
+    config.bufferSize = 24;
+    config.redSize = 8;
+    config.greenSize = 8;
+    config.blueSize = 8;
+    config.luminanceSize = 0;
+    config.alphaSize = 8;
+    config.alphaMaskSize = 0;
+    config.bindToTextureRGB = EGL_TRUE;
+    config.bindToTextureRGBA = EGL_TRUE;
+    config.colorBufferType = EGL_RGB_BUFFER;
+    config.configCaveat = EGL_NONE;
+    config.configID = 0;
+    config.conformant = EGL_OPENGL_ES2_BIT;
+    config.depthSize = 24;
+    config.level = 0;
+    config.matchNativePixmap = EGL_NONE;
+    config.maxPBufferWidth = 1024;
+    config.maxPBufferHeight = 1024;
+    config.maxPBufferPixels = config.maxPBufferWidth * config.maxPBufferWidth;
+    config.maxSwapInterval = 0;
+    config.minSwapInterval = 4;
+    config.nativeRenderable = EGL_OPENGL_ES2_BIT;
+    config.nativeVisualID = 0;
+    config.nativeVisualType = 0;
+    config.renderableType = EGL_FALSE;
+    config.sampleBuffers = 0;
+    config.samples = 0;
+    config.stencilSize = 8;
+    config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+    config.transparentType = EGL_NONE;
+    config.transparentRedValue = 0;
+    config.transparentGreenValue = 0;
+    config.transparentBlueValue = 0;
+
+    return config;
+}
+
+static std::vector<egl::Config> GenerateUniqueConfigs(size_t count)
+{
+    std::vector<egl::Config> configs;
+
+    for (size_t i = 0; i < count; i++)
+    {
+        egl::Config config = GenerateGenericConfig();
+        config.samples = static_cast<EGLint>(i);
+        configs.push_back(config);
+    }
+
+    return configs;
+}
+
+// Add unique configs to a ConfigSet and expect that the size of the
+// set is equal to the number of configs added.
+TEST(ConfigSetTest, Size)
+{
+    egl::ConfigSet set;
+
+    std::vector<egl::Config> uniqueConfigs = GenerateUniqueConfigs(16);
+    for (size_t i = 0; i < uniqueConfigs.size(); i++)
+    {
+        set.add(uniqueConfigs[i]);
+        EXPECT_EQ(set.size(), i + 1);
+    }
+}
+
+// [EGL 1.5] section 3.4:
+// EGL_CONFIG_ID is a unique integer identifying different EGLConfigs. Configuration IDs
+// must be small positive integers starting at 1 and ID assignment should be compact;
+// that is, if there are N EGLConfigs defined by the EGL implementation, their
+// configuration IDs should be in the range [1, N].
+TEST(ConfigSetTest, IDs)
+{
+    egl::ConfigSet set;
+
+    std::set<EGLint> ids;
+
+    std::vector<egl::Config> uniqueConfigs = GenerateUniqueConfigs(16);
+    for (size_t i = 0; i < uniqueConfigs.size(); i++)
+    {
+        EGLint id = set.add(uniqueConfigs[i]);
+
+        // Check that the config that was inserted has the ID that was returned
+        // by ConfigSet::add
+        EXPECT_EQ(id, set.get(id).configID);
+
+        ids.insert(id);
+    }
+
+    // Verify configCount unique IDs
+    EXPECT_EQ(ids.size(), set.size());
+
+    // Check that there are no gaps and the IDs are in the range [1, N].
+    EXPECT_EQ(*std::min_element(ids.begin(), ids.end()), 1);
+    EXPECT_EQ(*std::max_element(ids.begin(), ids.end()), static_cast<EGLint>(set.size()));
+}
+
+TEST(ConfigSetTest, Filtering_BitSizes)
+{
+    egl::ConfigSet set;
+
+    struct VariableConfigBitSize
+    {
+        EGLint Name;
+        EGLint(egl::Config::*ConfigMember);
+    };
+
+    VariableConfigBitSize testMembers[] = 
+    {
+        { EGL_RED_SIZE,     &egl::Config::redSize     },
+        { EGL_GREEN_SIZE,   &egl::Config::greenSize   },
+        { EGL_BLUE_SIZE,    &egl::Config::blueSize    },
+        { EGL_ALPHA_SIZE,   &egl::Config::alphaSize   },
+        { EGL_DEPTH_SIZE,   &egl::Config::depthSize   },
+        { EGL_STENCIL_SIZE, &egl::Config::stencilSize },
+    };
+
+    // Generate configsPerType configs with varying bit sizes of each type
+    size_t configsPerType = 4;
+    for (size_t i = 0; i < ArraySize(testMembers); i++)
+    {
+        for (size_t j = 0; j < configsPerType; j++)
+        {
+            egl::Config config = GenerateGenericConfig();
+
+            // Set all the other tested members of this config to 0
+            for (size_t k = 0; k < ArraySize(testMembers); k++)
+            {
+                config.*(testMembers[k].ConfigMember) = 0;
+            }
+
+            // Set the tested member of this config to i so it ranges from
+            // [1, configsPerType]
+            config.*(testMembers[i].ConfigMember) = static_cast<EGLint>(j) + 1;
+
+            set.add(config);
+        }
+    }
+
+    // for each tested member, filter by it's type and verify that the correct number
+    // of results are returned
+    for (size_t i = 0; i < ArraySize(testMembers); i++)
+    {
+        // Start with a filter of 1 to not grab the other members
+        for (EGLint j = 0; j < static_cast<EGLint>(configsPerType); j++)
+        {
+            egl::AttributeMap filter;
+            filter.insert(testMembers[i].Name, j + 1);
+
+            std::vector<const egl::Config *> filteredConfigs = set.filter(filter);
+
+            EXPECT_EQ(filteredConfigs.size(), configsPerType - j);
+        }
+    }
+}
+
+// Verify the sorting, [EGL 1.5] section 3.4.1.2 pg 30:
+// [configs are sorted] by larger total number of color bits (for an RGB
+// color buffer this is the sum of EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE,
+// and EGL_ALPHA_SIZE; for a luminance color buffer, the sum of EGL_LUMINANCE_SIZE
+// and EGL_ALPHA_SIZE).If the requested number of bits in attrib list for a
+// particular color component is 0 or EGL_DONT_CARE, then the number of bits
+// for that component is not considered.
+TEST(ConfigSetTest, Sorting_BitSizes)
+{
+    egl::ConfigSet set;
+    size_t testConfigCount = 64;
+    for (size_t i = 0; i < testConfigCount; i++)
+    {
+        egl::Config config = GenerateGenericConfig();
+
+        // Give random-ish bit sizes to the config
+        config.redSize =   (i *  2) %  3;
+        config.greenSize = (i +  5) %  7;
+        config.blueSize =  (i +  7) % 11;
+        config.alphaSize = (i + 13) % 17;
+
+        set.add(config);
+    }
+
+    egl::AttributeMap greaterThan1BitFilter;
+    greaterThan1BitFilter.insert(EGL_RED_SIZE, 1);
+    greaterThan1BitFilter.insert(EGL_GREEN_SIZE, 1);
+    greaterThan1BitFilter.insert(EGL_BLUE_SIZE, 1);
+    greaterThan1BitFilter.insert(EGL_ALPHA_SIZE, 1);
+
+    std::vector<const egl::Config *> filteredConfigs = set.filter(greaterThan1BitFilter);
+    for (size_t i = 1; i < filteredConfigs.size(); i++)
+    {
+        const egl::Config &prevConfig = *filteredConfigs[i - 1];
+        size_t prevBitCount = prevConfig.redSize +
+                              prevConfig.greenSize +
+                              prevConfig.blueSize +
+                              prevConfig.alphaSize;
+
+        const egl::Config &curConfig = *filteredConfigs[i];
+        size_t curBitCount = curConfig.redSize +
+                             curConfig.greenSize +
+                             curConfig.blueSize +
+                             curConfig.alphaSize;
+
+        EXPECT_GE(prevBitCount, curBitCount);
+    }
+}
diff --git a/src/third_party/angle/src/libANGLE/Constants.h b/src/third_party/angle/src/libANGLE/Constants.h
new file mode 100644
index 0000000..f9a0279
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Constants.h
@@ -0,0 +1,46 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Contants.h: Defines some implementation specific and gl constants
+
+#ifndef LIBANGLE_CONSTANTS_H_
+#define LIBANGLE_CONSTANTS_H_
+
+namespace gl
+{
+
+enum
+{
+    MAX_VERTEX_ATTRIBS         = 16,
+    MAX_VERTEX_ATTRIB_BINDINGS = 16,
+
+    // Implementation upper limits, real maximums depend on the hardware
+    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,
+
+    IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4,
+
+    // These are the maximums the implementation can support
+    // The actual GL caps are limited by the device caps
+    // and should be queried from the Context
+    IMPLEMENTATION_MAX_2D_TEXTURE_SIZE         = 16384,
+    IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE   = 16384,
+    IMPLEMENTATION_MAX_3D_TEXTURE_SIZE         = 2048,
+    IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048,
+
+    IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15  // 1+log2 of MAX_TEXTURE_SIZE
+};
+}
+
+#endif // LIBANGLE_CONSTANTS_H_
diff --git a/src/third_party/angle/src/libANGLE/Context.cpp b/src/third_party/angle/src/libANGLE/Context.cpp
new file mode 100644
index 0000000..671f5ed
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Context.cpp
@@ -0,0 +1,4688 @@
+//
+// 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.
+//
+
+// Context.cpp: Implements the gl::Context class, managing all GL state and performing
+// rendering operations. It is the GLES2 specific implementation of EGLContext.
+
+#include "libANGLE/Context.h"
+
+#include <string.h>
+#include <iterator>
+#include <sstream>
+#include <vector>
+
+#include "common/matrix_utils.h"
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "common/version.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Path.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/Workarounds.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/validationES.h"
+
+namespace
+{
+
+template <typename T>
+std::vector<gl::Path *> GatherPaths(gl::PathManager &resourceManager,
+                                    GLsizei numPaths,
+                                    const void *paths,
+                                    GLuint pathBase)
+{
+    std::vector<gl::Path *> ret;
+    ret.reserve(numPaths);
+
+    const auto *nameArray = static_cast<const T *>(paths);
+
+    for (GLsizei i = 0; i < numPaths; ++i)
+    {
+        const GLuint pathName = nameArray[i] + pathBase;
+
+        ret.push_back(resourceManager.getPath(pathName));
+    }
+
+    return ret;
+}
+
+std::vector<gl::Path *> GatherPaths(gl::PathManager &resourceManager,
+                                    GLsizei numPaths,
+                                    GLenum pathNameType,
+                                    const void *paths,
+                                    GLuint pathBase)
+{
+    switch (pathNameType)
+    {
+        case GL_UNSIGNED_BYTE:
+            return GatherPaths<GLubyte>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_BYTE:
+            return GatherPaths<GLbyte>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_UNSIGNED_SHORT:
+            return GatherPaths<GLushort>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_SHORT:
+            return GatherPaths<GLshort>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_UNSIGNED_INT:
+            return GatherPaths<GLuint>(resourceManager, numPaths, paths, pathBase);
+
+        case GL_INT:
+            return GatherPaths<GLint>(resourceManager, numPaths, paths, pathBase);
+    }
+
+    UNREACHABLE();
+    return std::vector<gl::Path *>();
+}
+
+template <typename T>
+gl::Error GetQueryObjectParameter(gl::Query *query, GLenum pname, T *params)
+{
+    ASSERT(query != nullptr);
+
+    switch (pname)
+    {
+        case GL_QUERY_RESULT_EXT:
+            return query->getResult(params);
+        case GL_QUERY_RESULT_AVAILABLE_EXT:
+        {
+            bool available;
+            gl::Error error = query->isResultAvailable(&available);
+            if (!error.isError())
+            {
+                *params = gl::ConvertFromGLboolean<T>(available);
+            }
+            return error;
+        }
+        default:
+            UNREACHABLE();
+            return gl::Error(GL_INVALID_OPERATION, "Unreachable Error");
+    }
+}
+
+void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback)
+{
+    if (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
+    {
+        for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount();
+             tfBufferIndex++)
+        {
+            const OffsetBindingPointer<gl::Buffer> &buffer =
+                transformFeedback->getIndexedBuffer(tfBufferIndex);
+            if (buffer.get() != nullptr)
+            {
+                buffer->onTransformFeedback();
+            }
+        }
+    }
+}
+
+// Attribute map queries.
+EGLint GetClientMajorVersion(const egl::AttributeMap &attribs)
+{
+    return static_cast<EGLint>(attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1));
+}
+
+EGLint GetClientMinorVersion(const egl::AttributeMap &attribs)
+{
+    return static_cast<EGLint>(attribs.get(EGL_CONTEXT_MINOR_VERSION, 0));
+}
+
+gl::Version GetClientVersion(const egl::AttributeMap &attribs)
+{
+    return gl::Version(GetClientMajorVersion(attribs), GetClientMinorVersion(attribs));
+}
+
+GLenum GetResetStrategy(const egl::AttributeMap &attribs)
+{
+    EGLAttrib attrib = attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
+                                   EGL_NO_RESET_NOTIFICATION_EXT);
+    switch (attrib)
+    {
+        case EGL_NO_RESET_NOTIFICATION:
+            return GL_NO_RESET_NOTIFICATION_EXT;
+        case EGL_LOSE_CONTEXT_ON_RESET:
+            return GL_LOSE_CONTEXT_ON_RESET_EXT;
+        default:
+            UNREACHABLE();
+            return GL_NONE;
+    }
+}
+
+bool GetRobustAccess(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE) ||
+           ((attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) !=
+            0);
+}
+
+bool GetDebug(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE) ||
+           ((attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) != 0);
+}
+
+bool GetNoError(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, EGL_FALSE) == EGL_TRUE);
+}
+
+bool GetWebGLContext(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
+bool GetBindGeneratesResource(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE) == EGL_TRUE);
+}
+
+bool GetClientArraysEnabled(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE) == EGL_TRUE);
+}
+
+bool GetRobustResourceInit(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
+std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label)
+{
+    std::string labelName;
+    if (label != nullptr)
+    {
+        size_t labelLength = length < 0 ? strlen(label) : length;
+        labelName          = std::string(label, labelLength);
+    }
+    return labelName;
+}
+
+void GetObjectLabelBase(const std::string &objectLabel,
+                        GLsizei bufSize,
+                        GLsizei *length,
+                        GLchar *label)
+{
+    size_t writeLength = objectLabel.length();
+    if (label != nullptr && bufSize > 0)
+    {
+        writeLength = std::min(static_cast<size_t>(bufSize) - 1, objectLabel.length());
+        std::copy(objectLabel.begin(), objectLabel.begin() + writeLength, label);
+        label[writeLength] = '\0';
+    }
+
+    if (length != nullptr)
+    {
+        *length = static_cast<GLsizei>(writeLength);
+    }
+}
+
+}  // anonymous namespace
+
+namespace gl
+{
+
+Context::Context(rx::EGLImplFactory *implFactory,
+                 const egl::Config *config,
+                 const Context *shareContext,
+                 TextureManager *shareTextures,
+                 const egl::AttributeMap &attribs,
+                 const egl::DisplayExtensions &displayExtensions)
+
+    : ValidationContext(shareContext,
+                        shareTextures,
+                        GetClientVersion(attribs),
+                        &mGLState,
+                        mCaps,
+                        mTextureCaps,
+                        mExtensions,
+                        mLimitations,
+                        GetNoError(attribs)),
+      mImplementation(implFactory->createContext(mState)),
+      mCompiler(nullptr),
+      mConfig(config),
+      mClientType(EGL_OPENGL_ES_API),
+      mHasBeenCurrent(false),
+      mContextLost(false),
+      mResetStatus(GL_NO_ERROR),
+      mContextLostForced(false),
+      mResetStrategy(GetResetStrategy(attribs)),
+      mRobustAccess(GetRobustAccess(attribs)),
+      mCurrentSurface(nullptr),
+      mSurfacelessFramebuffer(nullptr),
+      mWebGLContext(GetWebGLContext(attribs)),
+      mScratchBuffer(1000u)
+{
+    if (mRobustAccess)
+    {
+        UNIMPLEMENTED();
+    }
+
+    initCaps(displayExtensions);
+    initWorkarounds();
+
+    mGLState.initialize(mCaps, mExtensions, getClientVersion(), GetDebug(attribs),
+                        GetBindGeneratesResource(attribs), GetClientArraysEnabled(attribs),
+                        GetRobustResourceInit(attribs));
+
+    mFenceNVHandleAllocator.setBaseHandle(0);
+
+    // [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.
+
+    Texture *zeroTexture2D = new Texture(mImplementation.get(), 0, GL_TEXTURE_2D);
+    mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D);
+
+    Texture *zeroTextureCube = new Texture(mImplementation.get(), 0, GL_TEXTURE_CUBE_MAP);
+    mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube);
+
+    if (getClientVersion() >= Version(3, 0))
+    {
+        // TODO: These could also be enabled via extension
+        Texture *zeroTexture3D = new Texture(mImplementation.get(), 0, GL_TEXTURE_3D);
+        mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D);
+
+        Texture *zeroTexture2DArray = new Texture(mImplementation.get(), 0, GL_TEXTURE_2D_ARRAY);
+        mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray);
+    }
+    if (getClientVersion() >= Version(3, 1))
+    {
+        Texture *zeroTexture2DMultisample =
+            new Texture(mImplementation.get(), 0, GL_TEXTURE_2D_MULTISAMPLE);
+        mZeroTextures[GL_TEXTURE_2D_MULTISAMPLE].set(zeroTexture2DMultisample);
+
+        bindGenericAtomicCounterBuffer(0);
+        for (unsigned int i = 0; i < mCaps.maxAtomicCounterBufferBindings; i++)
+        {
+            bindIndexedAtomicCounterBuffer(0, i, 0, 0);
+        }
+
+        bindGenericShaderStorageBuffer(0);
+        for (unsigned int i = 0; i < mCaps.maxShaderStorageBufferBindings; i++)
+        {
+            bindIndexedShaderStorageBuffer(0, i, 0, 0);
+        }
+    }
+
+    if (mExtensions.eglImageExternal || mExtensions.eglStreamConsumerExternal)
+    {
+        Texture *zeroTextureExternal =
+            new Texture(mImplementation.get(), 0, GL_TEXTURE_EXTERNAL_OES);
+        mZeroTextures[GL_TEXTURE_EXTERNAL_OES].set(zeroTextureExternal);
+    }
+
+    mGLState.initializeZeroTextures(mZeroTextures);
+
+    bindVertexArray(0);
+    bindArrayBuffer(0);
+    bindDrawIndirectBuffer(0);
+    bindElementArrayBuffer(0);
+
+    bindRenderbuffer(GL_RENDERBUFFER, 0);
+
+    bindGenericUniformBuffer(0);
+    for (unsigned int i = 0; i < mCaps.maxUniformBufferBindings; i++)
+    {
+        bindIndexedUniformBuffer(0, i, 0, -1);
+    }
+
+    bindCopyReadBuffer(0);
+    bindCopyWriteBuffer(0);
+    bindPixelPackBuffer(0);
+    bindPixelUnpackBuffer(0);
+
+    if (getClientVersion() >= Version(3, 0))
+    {
+        // [OpenGL ES 3.0.2] section 2.14.1 pg 85:
+        // In the initial state, a default transform feedback object is bound and treated as
+        // a transform feedback object with a name of zero. That object is bound any time
+        // BindTransformFeedback is called with id of zero
+        bindTransformFeedback(0);
+    }
+
+    mCompiler = new Compiler(mImplementation.get(), mState);
+
+    // Initialize dirty bit masks
+    // TODO(jmadill): additional ES3 state
+    mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_ALIGNMENT);
+    mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_ROW_LENGTH);
+    mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+    mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_SKIP_IMAGES);
+    mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_SKIP_ROWS);
+    mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_SKIP_PIXELS);
+    mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_BUFFER_BINDING);
+    // No dirty objects.
+
+    // Readpixels uses the pack state and read FBO
+    mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_ALIGNMENT);
+    mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
+    mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_ROW_LENGTH);
+    mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_SKIP_ROWS);
+    mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_SKIP_PIXELS);
+    mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_BUFFER_BINDING);
+    mReadPixelsDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
+
+    mClearDirtyBits.set(State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
+    mClearDirtyBits.set(State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
+    mClearDirtyBits.set(State::DIRTY_BIT_SCISSOR);
+    mClearDirtyBits.set(State::DIRTY_BIT_VIEWPORT);
+    mClearDirtyBits.set(State::DIRTY_BIT_CLEAR_COLOR);
+    mClearDirtyBits.set(State::DIRTY_BIT_CLEAR_DEPTH);
+    mClearDirtyBits.set(State::DIRTY_BIT_CLEAR_STENCIL);
+    mClearDirtyBits.set(State::DIRTY_BIT_COLOR_MASK);
+    mClearDirtyBits.set(State::DIRTY_BIT_DEPTH_MASK);
+    mClearDirtyBits.set(State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+    mClearDirtyBits.set(State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+    mClearDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+
+    mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
+    mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR);
+    mBlitDirtyBits.set(State::DIRTY_BIT_FRAMEBUFFER_SRGB);
+    mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
+    mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+
+    handleError(mImplementation->initialize());
+}
+
+void Context::destroy(egl::Display *display)
+{
+    mGLState.reset(this);
+
+    for (auto fence : mFenceNVMap)
+    {
+        SafeDelete(fence.second);
+    }
+
+    for (auto query : mQueryMap)
+    {
+        if (query.second != nullptr)
+        {
+            query.second->release();
+        }
+    }
+
+    for (auto vertexArray : mVertexArrayMap)
+    {
+        SafeDelete(vertexArray.second);
+    }
+
+    for (auto transformFeedback : mTransformFeedbackMap)
+    {
+        if (transformFeedback.second != nullptr)
+        {
+            transformFeedback.second->release(this);
+        }
+    }
+
+    for (auto &zeroTexture : mZeroTextures)
+    {
+        zeroTexture.second.set(nullptr);
+    }
+    mZeroTextures.clear();
+
+    SafeDelete(mSurfacelessFramebuffer);
+
+    releaseSurface(display);
+
+    SafeDelete(mCompiler);
+
+    mState.mBuffers->release(this);
+    mState.mShaderPrograms->release(this);
+    mState.mTextures->release(this);
+    mState.mRenderbuffers->release(this);
+    mState.mSamplers->release(this);
+    mState.mFenceSyncs->release(this);
+    mState.mPaths->release(this);
+    mState.mFramebuffers->release(this);
+}
+
+Context::~Context()
+{
+}
+
+void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
+{
+    if (!mHasBeenCurrent)
+    {
+        initRendererString();
+        initVersionStrings();
+        initExtensionStrings();
+
+        int width  = 0;
+        int height = 0;
+        if (surface != nullptr)
+        {
+            width  = surface->getWidth();
+            height = surface->getHeight();
+        }
+
+        mGLState.setViewportParams(0, 0, width, height);
+        mGLState.setScissorParams(0, 0, width, height);
+
+        mHasBeenCurrent = true;
+    }
+
+    // TODO(jmadill): Rework this when we support ContextImpl
+    mGLState.setAllDirtyBits();
+
+    releaseSurface(display);
+
+    Framebuffer *newDefault = nullptr;
+    if (surface != nullptr)
+    {
+        surface->setIsCurrent(display, true);
+        mCurrentSurface = surface;
+        newDefault      = surface->getDefaultFramebuffer();
+    }
+    else
+    {
+        if (mSurfacelessFramebuffer == nullptr)
+        {
+            mSurfacelessFramebuffer = new Framebuffer(mImplementation.get());
+        }
+
+        newDefault = mSurfacelessFramebuffer;
+    }
+
+    // Update default framebuffer, the binding of the previous default
+    // framebuffer (or lack of) will have a nullptr.
+    {
+        if (mGLState.getReadFramebuffer() == nullptr)
+        {
+            mGLState.setReadFramebufferBinding(newDefault);
+        }
+        if (mGLState.getDrawFramebuffer() == nullptr)
+        {
+            mGLState.setDrawFramebufferBinding(newDefault);
+        }
+        mState.mFramebuffers->setDefaultFramebuffer(newDefault);
+    }
+
+    // Notify the renderer of a context switch
+    mImplementation->onMakeCurrent(mState);
+}
+
+void Context::releaseSurface(egl::Display *display)
+{
+    // Remove the default framebuffer
+    Framebuffer *currentDefault = nullptr;
+    if (mCurrentSurface != nullptr)
+    {
+        currentDefault = mCurrentSurface->getDefaultFramebuffer();
+    }
+    else if (mSurfacelessFramebuffer != nullptr)
+    {
+        currentDefault = mSurfacelessFramebuffer;
+    }
+
+    if (mGLState.getReadFramebuffer() == currentDefault)
+    {
+        mGLState.setReadFramebufferBinding(nullptr);
+    }
+    if (mGLState.getDrawFramebuffer() == currentDefault)
+    {
+        mGLState.setDrawFramebufferBinding(nullptr);
+    }
+    mState.mFramebuffers->setDefaultFramebuffer(nullptr);
+
+    if (mCurrentSurface)
+    {
+        mCurrentSurface->setIsCurrent(display, false);
+        mCurrentSurface = nullptr;
+    }
+}
+
+GLuint Context::createBuffer()
+{
+    return mState.mBuffers->createBuffer();
+}
+
+GLuint Context::createProgram()
+{
+    return mState.mShaderPrograms->createProgram(mImplementation.get());
+}
+
+GLuint Context::createShader(GLenum type)
+{
+    return mState.mShaderPrograms->createShader(mImplementation.get(), mLimitations, type);
+}
+
+GLuint Context::createTexture()
+{
+    return mState.mTextures->createTexture();
+}
+
+GLuint Context::createRenderbuffer()
+{
+    return mState.mRenderbuffers->createRenderbuffer();
+}
+
+GLsync Context::createFenceSync()
+{
+    GLuint handle = mState.mFenceSyncs->createFenceSync(mImplementation.get());
+
+    return reinterpret_cast<GLsync>(static_cast<uintptr_t>(handle));
+}
+
+GLuint Context::createPaths(GLsizei range)
+{
+    auto resultOrError = mState.mPaths->createPaths(mImplementation.get(), range);
+    if (resultOrError.isError())
+    {
+        handleError(resultOrError.getError());
+        return 0;
+    }
+    return resultOrError.getResult();
+}
+
+GLuint Context::createVertexArray()
+{
+    GLuint vertexArray           = mVertexArrayHandleAllocator.allocate();
+    mVertexArrayMap[vertexArray] = nullptr;
+    return vertexArray;
+}
+
+GLuint Context::createSampler()
+{
+    return mState.mSamplers->createSampler();
+}
+
+GLuint Context::createTransformFeedback()
+{
+    GLuint transformFeedback                 = mTransformFeedbackAllocator.allocate();
+    mTransformFeedbackMap[transformFeedback] = nullptr;
+    return transformFeedback;
+}
+
+// Returns an unused framebuffer name
+GLuint Context::createFramebuffer()
+{
+    return mState.mFramebuffers->createFramebuffer();
+}
+
+GLuint Context::createFenceNV()
+{
+    GLuint handle = mFenceNVHandleAllocator.allocate();
+
+    mFenceNVMap[handle] = new FenceNV(mImplementation->createFenceNV());
+
+    return handle;
+}
+
+// Returns an unused query name
+GLuint Context::createQuery()
+{
+    GLuint handle = mQueryHandleAllocator.allocate();
+
+    mQueryMap[handle] = nullptr;
+
+    return handle;
+}
+
+void Context::deleteBuffer(GLuint buffer)
+{
+    if (mState.mBuffers->getBuffer(buffer))
+    {
+        detachBuffer(buffer);
+    }
+
+    mState.mBuffers->deleteObject(this, buffer);
+}
+
+void Context::deleteShader(GLuint shader)
+{
+    mState.mShaderPrograms->deleteShader(this, shader);
+}
+
+void Context::deleteProgram(GLuint program)
+{
+    mState.mShaderPrograms->deleteProgram(this, program);
+}
+
+void Context::deleteTexture(GLuint texture)
+{
+    if (mState.mTextures->getTexture(texture))
+    {
+        detachTexture(texture);
+    }
+
+    mState.mTextures->deleteObject(this, texture);
+}
+
+void Context::deleteRenderbuffer(GLuint renderbuffer)
+{
+    if (mState.mRenderbuffers->getRenderbuffer(renderbuffer))
+    {
+        detachRenderbuffer(renderbuffer);
+    }
+
+    mState.mRenderbuffers->deleteObject(this, renderbuffer);
+}
+
+void Context::deleteFenceSync(GLsync fenceSync)
+{
+    // The spec specifies the underlying Fence object is not deleted until all current
+    // wait commands finish. However, since the name becomes invalid, we cannot query the fence,
+    // and since our API is currently designed for being called from a single thread, we can delete
+    // the fence immediately.
+    mState.mFenceSyncs->deleteObject(this,
+                                     static_cast<GLuint>(reinterpret_cast<uintptr_t>(fenceSync)));
+}
+
+void Context::deletePaths(GLuint first, GLsizei range)
+{
+    mState.mPaths->deletePaths(first, range);
+}
+
+bool Context::hasPathData(GLuint path) const
+{
+    const auto *pathObj = mState.mPaths->getPath(path);
+    if (pathObj == nullptr)
+        return false;
+
+    return pathObj->hasPathData();
+}
+
+bool Context::hasPath(GLuint path) const
+{
+    return mState.mPaths->hasPath(path);
+}
+
+void Context::setPathCommands(GLuint path,
+                              GLsizei numCommands,
+                              const GLubyte *commands,
+                              GLsizei numCoords,
+                              GLenum coordType,
+                              const void *coords)
+{
+    auto *pathObject = mState.mPaths->getPath(path);
+
+    handleError(pathObject->setCommands(numCommands, commands, numCoords, coordType, coords));
+}
+
+void Context::setPathParameterf(GLuint path, GLenum pname, GLfloat value)
+{
+    auto *pathObj = mState.mPaths->getPath(path);
+
+    switch (pname)
+    {
+        case GL_PATH_STROKE_WIDTH_CHROMIUM:
+            pathObj->setStrokeWidth(value);
+            break;
+        case GL_PATH_END_CAPS_CHROMIUM:
+            pathObj->setEndCaps(static_cast<GLenum>(value));
+            break;
+        case GL_PATH_JOIN_STYLE_CHROMIUM:
+            pathObj->setJoinStyle(static_cast<GLenum>(value));
+            break;
+        case GL_PATH_MITER_LIMIT_CHROMIUM:
+            pathObj->setMiterLimit(value);
+            break;
+        case GL_PATH_STROKE_BOUND_CHROMIUM:
+            pathObj->setStrokeBound(value);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void Context::getPathParameterfv(GLuint path, GLenum pname, GLfloat *value) const
+{
+    const auto *pathObj = mState.mPaths->getPath(path);
+
+    switch (pname)
+    {
+        case GL_PATH_STROKE_WIDTH_CHROMIUM:
+            *value = pathObj->getStrokeWidth();
+            break;
+        case GL_PATH_END_CAPS_CHROMIUM:
+            *value = static_cast<GLfloat>(pathObj->getEndCaps());
+            break;
+        case GL_PATH_JOIN_STYLE_CHROMIUM:
+            *value = static_cast<GLfloat>(pathObj->getJoinStyle());
+            break;
+        case GL_PATH_MITER_LIMIT_CHROMIUM:
+            *value = pathObj->getMiterLimit();
+            break;
+        case GL_PATH_STROKE_BOUND_CHROMIUM:
+            *value = pathObj->getStrokeBound();
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void Context::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+    mGLState.setPathStencilFunc(func, ref, mask);
+}
+
+void Context::deleteVertexArray(GLuint vertexArray)
+{
+    auto iter = mVertexArrayMap.find(vertexArray);
+    if (iter != mVertexArrayMap.end())
+    {
+        VertexArray *vertexArrayObject = iter->second;
+        if (vertexArrayObject != nullptr)
+        {
+            detachVertexArray(vertexArray);
+            delete vertexArrayObject;
+        }
+
+        mVertexArrayMap.erase(iter);
+        mVertexArrayHandleAllocator.release(vertexArray);
+    }
+}
+
+void Context::deleteSampler(GLuint sampler)
+{
+    if (mState.mSamplers->getSampler(sampler))
+    {
+        detachSampler(sampler);
+    }
+
+    mState.mSamplers->deleteObject(this, sampler);
+}
+
+void Context::deleteTransformFeedback(GLuint transformFeedback)
+{
+    if (transformFeedback == 0)
+    {
+        return;
+    }
+
+    auto iter = mTransformFeedbackMap.find(transformFeedback);
+    if (iter != mTransformFeedbackMap.end())
+    {
+        TransformFeedback *transformFeedbackObject = iter->second;
+        if (transformFeedbackObject != nullptr)
+        {
+            detachTransformFeedback(transformFeedback);
+            transformFeedbackObject->release(this);
+        }
+
+        mTransformFeedbackMap.erase(iter);
+        mTransformFeedbackAllocator.release(transformFeedback);
+    }
+}
+
+void Context::deleteFramebuffer(GLuint framebuffer)
+{
+    if (mState.mFramebuffers->getFramebuffer(framebuffer))
+    {
+        detachFramebuffer(framebuffer);
+    }
+
+    mState.mFramebuffers->deleteObject(this, framebuffer);
+}
+
+void Context::deleteFenceNV(GLuint fence)
+{
+    auto fenceObject = mFenceNVMap.find(fence);
+
+    if (fenceObject != mFenceNVMap.end())
+    {
+        mFenceNVHandleAllocator.release(fenceObject->first);
+        delete fenceObject->second;
+        mFenceNVMap.erase(fenceObject);
+    }
+}
+
+void Context::deleteQuery(GLuint query)
+{
+    auto queryObject = mQueryMap.find(query);
+    if (queryObject != mQueryMap.end())
+    {
+        mQueryHandleAllocator.release(queryObject->first);
+        if (queryObject->second)
+        {
+            queryObject->second->release();
+        }
+        mQueryMap.erase(queryObject);
+    }
+}
+
+Buffer *Context::getBuffer(GLuint handle) const
+{
+    return mState.mBuffers->getBuffer(handle);
+}
+
+Texture *Context::getTexture(GLuint handle) const
+{
+    return mState.mTextures->getTexture(handle);
+}
+
+Renderbuffer *Context::getRenderbuffer(GLuint handle) const
+{
+    return mState.mRenderbuffers->getRenderbuffer(handle);
+}
+
+FenceSync *Context::getFenceSync(GLsync handle) const
+{
+    return mState.mFenceSyncs->getFenceSync(
+        static_cast<GLuint>(reinterpret_cast<uintptr_t>(handle)));
+}
+
+VertexArray *Context::getVertexArray(GLuint handle) const
+{
+    auto vertexArray = mVertexArrayMap.find(handle);
+    return (vertexArray != mVertexArrayMap.end()) ? vertexArray->second : nullptr;
+}
+
+Sampler *Context::getSampler(GLuint handle) const
+{
+    return mState.mSamplers->getSampler(handle);
+}
+
+TransformFeedback *Context::getTransformFeedback(GLuint handle) const
+{
+    auto iter = mTransformFeedbackMap.find(handle);
+    return (iter != mTransformFeedbackMap.end()) ? iter->second : nullptr;
+}
+
+LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
+{
+    switch (identifier)
+    {
+        case GL_BUFFER:
+            return getBuffer(name);
+        case GL_SHADER:
+            return getShader(name);
+        case GL_PROGRAM:
+            return getProgram(name);
+        case GL_VERTEX_ARRAY:
+            return getVertexArray(name);
+        case GL_QUERY:
+            return getQuery(name);
+        case GL_TRANSFORM_FEEDBACK:
+            return getTransformFeedback(name);
+        case GL_SAMPLER:
+            return getSampler(name);
+        case GL_TEXTURE:
+            return getTexture(name);
+        case GL_RENDERBUFFER:
+            return getRenderbuffer(name);
+        case GL_FRAMEBUFFER:
+            return getFramebuffer(name);
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+}
+
+LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const
+{
+    return getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr)));
+}
+
+void Context::objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
+{
+    LabeledObject *object = getLabeledObject(identifier, name);
+    ASSERT(object != nullptr);
+
+    std::string labelName = GetObjectLabelFromPointer(length, label);
+    object->setLabel(labelName);
+}
+
+void Context::objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
+{
+    LabeledObject *object = getLabeledObjectFromPtr(ptr);
+    ASSERT(object != nullptr);
+
+    std::string labelName = GetObjectLabelFromPointer(length, label);
+    object->setLabel(labelName);
+}
+
+void Context::getObjectLabel(GLenum identifier,
+                             GLuint name,
+                             GLsizei bufSize,
+                             GLsizei *length,
+                             GLchar *label) const
+{
+    LabeledObject *object = getLabeledObject(identifier, name);
+    ASSERT(object != nullptr);
+
+    const std::string &objectLabel = object->getLabel();
+    GetObjectLabelBase(objectLabel, bufSize, length, label);
+}
+
+void Context::getObjectPtrLabel(const void *ptr,
+                                GLsizei bufSize,
+                                GLsizei *length,
+                                GLchar *label) const
+{
+    LabeledObject *object = getLabeledObjectFromPtr(ptr);
+    ASSERT(object != nullptr);
+
+    const std::string &objectLabel = object->getLabel();
+    GetObjectLabelBase(objectLabel, bufSize, length, label);
+}
+
+bool Context::isSampler(GLuint samplerName) const
+{
+    return mState.mSamplers->isSampler(samplerName);
+}
+
+void Context::bindArrayBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setArrayBufferBinding(buffer);
+}
+
+void Context::bindDrawIndirectBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setDrawIndirectBufferBinding(buffer);
+}
+
+void Context::bindElementArrayBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setElementArrayBuffer(buffer);
+}
+
+void Context::bindTexture(GLenum target, GLuint handle)
+{
+    Texture *texture = nullptr;
+
+    if (handle == 0)
+    {
+        texture = mZeroTextures[target].get();
+    }
+    else
+    {
+        texture = mState.mTextures->checkTextureAllocation(mImplementation.get(), handle, target);
+    }
+
+    ASSERT(texture);
+    mGLState.setSamplerTexture(target, texture);
+}
+
+void Context::bindReadFramebuffer(GLuint framebufferHandle)
+{
+    Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation(
+        mImplementation.get(), mCaps, framebufferHandle);
+    mGLState.setReadFramebufferBinding(framebuffer);
+}
+
+void Context::bindDrawFramebuffer(GLuint framebufferHandle)
+{
+    Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation(
+        mImplementation.get(), mCaps, framebufferHandle);
+    mGLState.setDrawFramebufferBinding(framebuffer);
+}
+
+void Context::bindVertexArray(GLuint vertexArrayHandle)
+{
+    VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle);
+    mGLState.setVertexArrayBinding(vertexArray);
+}
+
+void Context::bindVertexBuffer(GLuint bindingIndex,
+                               GLuint bufferHandle,
+                               GLintptr offset,
+                               GLsizei stride)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.bindVertexBuffer(bindingIndex, buffer, offset, stride);
+}
+
+void Context::bindSampler(GLuint textureUnit, GLuint samplerHandle)
+{
+    ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits);
+    Sampler *sampler =
+        mState.mSamplers->checkSamplerAllocation(mImplementation.get(), samplerHandle);
+    mGLState.setSamplerBinding(textureUnit, sampler);
+}
+
+void Context::bindGenericUniformBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setGenericUniformBufferBinding(buffer);
+}
+
+void Context::bindIndexedUniformBuffer(GLuint bufferHandle,
+                                       GLuint index,
+                                       GLintptr offset,
+                                       GLsizeiptr size)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setIndexedUniformBufferBinding(index, buffer, offset, size);
+}
+
+void Context::bindGenericTransformFeedbackBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.getCurrentTransformFeedback()->bindGenericBuffer(buffer);
+}
+
+void Context::bindIndexedTransformFeedbackBuffer(GLuint bufferHandle,
+                                                 GLuint index,
+                                                 GLintptr offset,
+                                                 GLsizeiptr size)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.getCurrentTransformFeedback()->bindIndexedBuffer(index, buffer, offset, size);
+}
+
+void Context::bindGenericAtomicCounterBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setGenericAtomicCounterBufferBinding(buffer);
+}
+
+void Context::bindIndexedAtomicCounterBuffer(GLuint bufferHandle,
+                                             GLuint index,
+                                             GLintptr offset,
+                                             GLsizeiptr size)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setIndexedAtomicCounterBufferBinding(index, buffer, offset, size);
+}
+
+void Context::bindGenericShaderStorageBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setGenericShaderStorageBufferBinding(buffer);
+}
+
+void Context::bindIndexedShaderStorageBuffer(GLuint bufferHandle,
+                                             GLuint index,
+                                             GLintptr offset,
+                                             GLsizeiptr size)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setIndexedShaderStorageBufferBinding(index, buffer, offset, size);
+}
+
+void Context::bindCopyReadBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setCopyReadBufferBinding(buffer);
+}
+
+void Context::bindCopyWriteBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setCopyWriteBufferBinding(buffer);
+}
+
+void Context::bindPixelPackBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setPixelPackBufferBinding(buffer);
+}
+
+void Context::bindPixelUnpackBuffer(GLuint bufferHandle)
+{
+    Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+    mGLState.setPixelUnpackBufferBinding(buffer);
+}
+
+void Context::useProgram(GLuint program)
+{
+    mGLState.setProgram(this, getProgram(program));
+}
+
+void Context::bindTransformFeedback(GLuint transformFeedbackHandle)
+{
+    TransformFeedback *transformFeedback =
+        checkTransformFeedbackAllocation(transformFeedbackHandle);
+    mGLState.setTransformFeedbackBinding(transformFeedback);
+}
+
+Error Context::beginQuery(GLenum target, GLuint query)
+{
+    Query *queryObject = getQuery(query, true, target);
+    ASSERT(queryObject);
+
+    // begin query
+    Error error = queryObject->begin();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    // set query as active for specified target only if begin succeeded
+    mGLState.setActiveQuery(target, queryObject);
+
+    return NoError();
+}
+
+Error Context::endQuery(GLenum target)
+{
+    Query *queryObject = mGLState.getActiveQuery(target);
+    ASSERT(queryObject);
+
+    gl::Error error = queryObject->end();
+
+    // Always unbind the query, even if there was an error. This may delete the query object.
+    mGLState.setActiveQuery(target, nullptr);
+
+    return error;
+}
+
+Error Context::queryCounter(GLuint id, GLenum target)
+{
+    ASSERT(target == GL_TIMESTAMP_EXT);
+
+    Query *queryObject = getQuery(id, true, target);
+    ASSERT(queryObject);
+
+    return queryObject->queryCounter();
+}
+
+void Context::getQueryiv(GLenum target, GLenum pname, GLint *params)
+{
+    switch (pname)
+    {
+        case GL_CURRENT_QUERY_EXT:
+            params[0] = mGLState.getActiveQueryId(target);
+            break;
+        case GL_QUERY_COUNTER_BITS_EXT:
+            switch (target)
+            {
+                case GL_TIME_ELAPSED_EXT:
+                    params[0] = getExtensions().queryCounterBitsTimeElapsed;
+                    break;
+                case GL_TIMESTAMP_EXT:
+                    params[0] = getExtensions().queryCounterBitsTimestamp;
+                    break;
+                default:
+                    UNREACHABLE();
+                    params[0] = 0;
+                    break;
+            }
+            break;
+        default:
+            UNREACHABLE();
+            return;
+    }
+}
+
+void Context::getQueryObjectiv(GLuint id, GLenum pname, GLint *params)
+{
+    handleError(GetQueryObjectParameter(getQuery(id), pname, params));
+}
+
+void Context::getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
+{
+    handleError(GetQueryObjectParameter(getQuery(id), pname, params));
+}
+
+void Context::getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params)
+{
+    handleError(GetQueryObjectParameter(getQuery(id), pname, params));
+}
+
+void Context::getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params)
+{
+    handleError(GetQueryObjectParameter(getQuery(id), pname, params));
+}
+
+Framebuffer *Context::getFramebuffer(GLuint handle) const
+{
+    return mState.mFramebuffers->getFramebuffer(handle);
+}
+
+FenceNV *Context::getFenceNV(unsigned int handle)
+{
+    auto fence = mFenceNVMap.find(handle);
+
+    if (fence == mFenceNVMap.end())
+    {
+        return nullptr;
+    }
+    else
+    {
+        return fence->second;
+    }
+}
+
+Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
+{
+    auto query = mQueryMap.find(handle);
+
+    if (query == mQueryMap.end())
+    {
+        return nullptr;
+    }
+    else
+    {
+        if (!query->second && create)
+        {
+            query->second = new Query(mImplementation->createQuery(type), handle);
+            query->second->addRef();
+        }
+        return query->second;
+    }
+}
+
+Query *Context::getQuery(GLuint handle) const
+{
+    auto iter = mQueryMap.find(handle);
+    return (iter != mQueryMap.end()) ? iter->second : nullptr;
+}
+
+Texture *Context::getTargetTexture(GLenum target) const
+{
+    ASSERT(ValidTextureTarget(this, target) || ValidTextureExternalTarget(this, target));
+    return mGLState.getTargetTexture(target);
+}
+
+Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
+{
+    return mGLState.getSamplerTexture(sampler, type);
+}
+
+Compiler *Context::getCompiler() const
+{
+    return mCompiler;
+}
+
+void Context::getBooleanvImpl(GLenum pname, GLboolean *params)
+{
+    switch (pname)
+    {
+        case GL_SHADER_COMPILER:
+            *params = GL_TRUE;
+            break;
+        case GL_CONTEXT_ROBUST_ACCESS_EXT:
+            *params = mRobustAccess ? GL_TRUE : GL_FALSE;
+            break;
+        default:
+            mGLState.getBooleanv(pname, params);
+            break;
+    }
+}
+
+void Context::getFloatvImpl(GLenum pname, GLfloat *params)
+{
+    // Queries about context capabilities and maximums are answered by Context.
+    // Queries about current GL state values are answered by State.
+    switch (pname)
+    {
+        case GL_ALIASED_LINE_WIDTH_RANGE:
+            params[0] = mCaps.minAliasedLineWidth;
+            params[1] = mCaps.maxAliasedLineWidth;
+            break;
+        case GL_ALIASED_POINT_SIZE_RANGE:
+            params[0] = mCaps.minAliasedPointSize;
+            params[1] = mCaps.maxAliasedPointSize;
+            break;
+        case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+            ASSERT(mExtensions.textureFilterAnisotropic);
+            *params = mExtensions.maxTextureAnisotropy;
+            break;
+        case GL_MAX_TEXTURE_LOD_BIAS:
+            *params = mCaps.maxLODBias;
+            break;
+
+        case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
+        case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
+        {
+            ASSERT(mExtensions.pathRendering);
+            const GLfloat *m = mGLState.getPathRenderingMatrix(pname);
+            memcpy(params, m, 16 * sizeof(GLfloat));
+        }
+        break;
+
+        default:
+            mGLState.getFloatv(pname, params);
+            break;
+    }
+}
+
+void Context::getIntegervImpl(GLenum pname, GLint *params)
+{
+    // Queries about context capabilities and maximums are answered by Context.
+    // Queries about current GL state values are answered by State.
+
+    switch (pname)
+    {
+        case GL_MAX_VERTEX_ATTRIBS:
+            *params = mCaps.maxVertexAttributes;
+            break;
+        case GL_MAX_VERTEX_UNIFORM_VECTORS:
+            *params = mCaps.maxVertexUniformVectors;
+            break;
+        case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
+            *params = mCaps.maxVertexUniformComponents;
+            break;
+        case GL_MAX_VARYING_VECTORS:
+            *params = mCaps.maxVaryingVectors;
+            break;
+        case GL_MAX_VARYING_COMPONENTS:
+            *params = mCaps.maxVertexOutputComponents;
+            break;
+        case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+            *params = mCaps.maxCombinedTextureImageUnits;
+            break;
+        case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+            *params = mCaps.maxVertexTextureImageUnits;
+            break;
+        case GL_MAX_TEXTURE_IMAGE_UNITS:
+            *params = mCaps.maxTextureImageUnits;
+            break;
+        case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+            *params = mCaps.maxFragmentUniformVectors;
+            break;
+        case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+            *params = mCaps.maxFragmentUniformComponents;
+            break;
+        case GL_MAX_RENDERBUFFER_SIZE:
+            *params = mCaps.maxRenderbufferSize;
+            break;
+        case GL_MAX_COLOR_ATTACHMENTS_EXT:
+            *params = mCaps.maxColorAttachments;
+            break;
+        case GL_MAX_DRAW_BUFFERS_EXT:
+            *params = mCaps.maxDrawBuffers;
+            break;
+        // case GL_FRAMEBUFFER_BINDING:                    // now equivalent to
+        // GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
+        case GL_SUBPIXEL_BITS:
+            *params = 4;
+            break;
+        case GL_MAX_TEXTURE_SIZE:
+            *params = mCaps.max2DTextureSize;
+            break;
+        case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+            *params = mCaps.maxCubeMapTextureSize;
+            break;
+        case GL_MAX_3D_TEXTURE_SIZE:
+            *params = mCaps.max3DTextureSize;
+            break;
+        case GL_MAX_ARRAY_TEXTURE_LAYERS:
+            *params = mCaps.maxArrayTextureLayers;
+            break;
+        case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+            *params = mCaps.uniformBufferOffsetAlignment;
+            break;
+        case GL_MAX_UNIFORM_BUFFER_BINDINGS:
+            *params = mCaps.maxUniformBufferBindings;
+            break;
+        case GL_MAX_VERTEX_UNIFORM_BLOCKS:
+            *params = mCaps.maxVertexUniformBlocks;
+            break;
+        case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
+            *params = mCaps.maxFragmentUniformBlocks;
+            break;
+        case GL_MAX_COMBINED_UNIFORM_BLOCKS:
+            *params = mCaps.maxCombinedTextureImageUnits;
+            break;
+        case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
+            *params = mCaps.maxVertexOutputComponents;
+            break;
+        case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
+            *params = mCaps.maxFragmentInputComponents;
+            break;
+        case GL_MIN_PROGRAM_TEXEL_OFFSET:
+            *params = mCaps.minProgramTexelOffset;
+            break;
+        case GL_MAX_PROGRAM_TEXEL_OFFSET:
+            *params = mCaps.maxProgramTexelOffset;
+            break;
+        case GL_MAJOR_VERSION:
+            *params = getClientVersion().major;
+            break;
+        case GL_MINOR_VERSION:
+            *params = getClientVersion().minor;
+            break;
+        case GL_MAX_ELEMENTS_INDICES:
+            *params = mCaps.maxElementsIndices;
+            break;
+        case GL_MAX_ELEMENTS_VERTICES:
+            *params = mCaps.maxElementsVertices;
+            break;
+        case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
+            *params = mCaps.maxTransformFeedbackInterleavedComponents;
+            break;
+        case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+            *params = mCaps.maxTransformFeedbackSeparateAttributes;
+            break;
+        case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
+            *params = mCaps.maxTransformFeedbackSeparateComponents;
+            break;
+        case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+            *params = static_cast<GLint>(mCaps.compressedTextureFormats.size());
+            break;
+        case GL_MAX_SAMPLES_ANGLE:
+            *params = mCaps.maxSamples;
+            break;
+        case GL_MAX_VIEWPORT_DIMS:
+        {
+            params[0] = mCaps.maxViewportWidth;
+            params[1] = mCaps.maxViewportHeight;
+        }
+        break;
+        case GL_COMPRESSED_TEXTURE_FORMATS:
+            std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(),
+                      params);
+            break;
+        case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+            *params = mResetStrategy;
+            break;
+        case GL_NUM_SHADER_BINARY_FORMATS:
+            *params = static_cast<GLint>(mCaps.shaderBinaryFormats.size());
+            break;
+        case GL_SHADER_BINARY_FORMATS:
+            std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params);
+            break;
+        case GL_NUM_PROGRAM_BINARY_FORMATS:
+            *params = static_cast<GLint>(mCaps.programBinaryFormats.size());
+            break;
+        case GL_PROGRAM_BINARY_FORMATS:
+            std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params);
+            break;
+        case GL_NUM_EXTENSIONS:
+            *params = static_cast<GLint>(mExtensionStrings.size());
+            break;
+
+        // GL_KHR_debug
+        case GL_MAX_DEBUG_MESSAGE_LENGTH:
+            *params = mExtensions.maxDebugMessageLength;
+            break;
+        case GL_MAX_DEBUG_LOGGED_MESSAGES:
+            *params = mExtensions.maxDebugLoggedMessages;
+            break;
+        case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
+            *params = mExtensions.maxDebugGroupStackDepth;
+            break;
+        case GL_MAX_LABEL_LENGTH:
+            *params = mExtensions.maxLabelLength;
+            break;
+
+        // GL_EXT_disjoint_timer_query
+        case GL_GPU_DISJOINT_EXT:
+            *params = mImplementation->getGPUDisjoint();
+            break;
+        case GL_MAX_FRAMEBUFFER_WIDTH:
+            *params = mCaps.maxFramebufferWidth;
+            break;
+        case GL_MAX_FRAMEBUFFER_HEIGHT:
+            *params = mCaps.maxFramebufferHeight;
+            break;
+        case GL_MAX_FRAMEBUFFER_SAMPLES:
+            *params = mCaps.maxFramebufferSamples;
+            break;
+        case GL_MAX_SAMPLE_MASK_WORDS:
+            *params = mCaps.maxSampleMaskWords;
+            break;
+        case GL_MAX_COLOR_TEXTURE_SAMPLES:
+            *params = mCaps.maxColorTextureSamples;
+            break;
+        case GL_MAX_DEPTH_TEXTURE_SAMPLES:
+            *params = mCaps.maxDepthTextureSamples;
+            break;
+        case GL_MAX_INTEGER_SAMPLES:
+            *params = mCaps.maxIntegerSamples;
+            break;
+        case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
+            *params = mCaps.maxVertexAttribRelativeOffset;
+            break;
+        case GL_MAX_VERTEX_ATTRIB_BINDINGS:
+            *params = mCaps.maxVertexAttribBindings;
+            break;
+        case GL_MAX_VERTEX_ATTRIB_STRIDE:
+            *params = mCaps.maxVertexAttribStride;
+            break;
+        case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
+            *params = mCaps.maxVertexAtomicCounterBuffers;
+            break;
+        case GL_MAX_VERTEX_ATOMIC_COUNTERS:
+            *params = mCaps.maxVertexAtomicCounters;
+            break;
+        case GL_MAX_VERTEX_IMAGE_UNIFORMS:
+            *params = mCaps.maxVertexImageUniforms;
+            break;
+        case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
+            *params = mCaps.maxVertexShaderStorageBlocks;
+            break;
+        case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
+            *params = mCaps.maxFragmentAtomicCounterBuffers;
+            break;
+        case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
+            *params = mCaps.maxFragmentAtomicCounters;
+            break;
+        case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
+            *params = mCaps.maxFragmentImageUniforms;
+            break;
+        case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
+            *params = mCaps.maxFragmentShaderStorageBlocks;
+            break;
+        case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
+            *params = mCaps.minProgramTextureGatherOffset;
+            break;
+        case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
+            *params = mCaps.maxProgramTextureGatherOffset;
+            break;
+        case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
+            *params = mCaps.maxComputeWorkGroupInvocations;
+            break;
+        case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
+            *params = mCaps.maxComputeUniformBlocks;
+            break;
+        case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
+            *params = mCaps.maxComputeTextureImageUnits;
+            break;
+        case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
+            *params = mCaps.maxComputeSharedMemorySize;
+            break;
+        case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
+            *params = mCaps.maxComputeUniformComponents;
+            break;
+        case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
+            *params = mCaps.maxComputeAtomicCounterBuffers;
+            break;
+        case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
+            *params = mCaps.maxComputeAtomicCounters;
+            break;
+        case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
+            *params = mCaps.maxComputeImageUniforms;
+            break;
+        case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
+            *params = mCaps.maxCombinedComputeUniformComponents;
+            break;
+        case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
+            *params = mCaps.maxComputeShaderStorageBlocks;
+            break;
+        case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
+            *params = mCaps.maxCombinedShaderOutputResources;
+            break;
+        case GL_MAX_UNIFORM_LOCATIONS:
+            *params = mCaps.maxUniformLocations;
+            break;
+        case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
+            *params = mCaps.maxAtomicCounterBufferBindings;
+            break;
+        case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
+            *params = mCaps.maxAtomicCounterBufferSize;
+            break;
+        case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
+            *params = mCaps.maxCombinedAtomicCounterBuffers;
+            break;
+        case GL_MAX_COMBINED_ATOMIC_COUNTERS:
+            *params = mCaps.maxCombinedAtomicCounters;
+            break;
+        case GL_MAX_IMAGE_UNITS:
+            *params = mCaps.maxImageUnits;
+            break;
+        case GL_MAX_COMBINED_IMAGE_UNIFORMS:
+            *params = mCaps.maxCombinedImageUniforms;
+            break;
+        case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
+            *params = mCaps.maxShaderStorageBufferBindings;
+            break;
+        case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
+            *params = mCaps.maxCombinedShaderStorageBlocks;
+            break;
+        case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
+            *params = mCaps.shaderStorageBufferOffsetAlignment;
+            break;
+        default:
+            mGLState.getIntegerv(this, pname, params);
+            break;
+    }
+}
+
+void Context::getInteger64v(GLenum pname, GLint64 *params)
+{
+    // Queries about context capabilities and maximums are answered by Context.
+    // Queries about current GL state values are answered by State.
+    switch (pname)
+    {
+        case GL_MAX_ELEMENT_INDEX:
+            *params = mCaps.maxElementIndex;
+            break;
+        case GL_MAX_UNIFORM_BLOCK_SIZE:
+            *params = mCaps.maxUniformBlockSize;
+            break;
+        case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+            *params = mCaps.maxCombinedVertexUniformComponents;
+            break;
+        case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+            *params = mCaps.maxCombinedFragmentUniformComponents;
+            break;
+        case GL_MAX_SERVER_WAIT_TIMEOUT:
+            *params = mCaps.maxServerWaitTimeout;
+            break;
+
+        // GL_EXT_disjoint_timer_query
+        case GL_TIMESTAMP_EXT:
+            *params = mImplementation->getTimestamp();
+            break;
+
+        case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
+            *params = mCaps.maxShaderStorageBlockSize;
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void Context::getPointerv(GLenum pname, void **params) const
+{
+    mGLState.getPointerv(pname, params);
+}
+
+void Context::getIntegeri_v(GLenum target, GLuint index, GLint *data)
+{
+    // Queries about context capabilities and maximums are answered by Context.
+    // Queries about current GL state values are answered by State.
+
+    GLenum nativeType;
+    unsigned int numParams;
+    bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
+    ASSERT(queryStatus);
+
+    if (nativeType == GL_INT)
+    {
+        switch (target)
+        {
+            case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+                ASSERT(index < 3u);
+                *data = mCaps.maxComputeWorkGroupCount[index];
+                break;
+            case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+                ASSERT(index < 3u);
+                *data = mCaps.maxComputeWorkGroupSize[index];
+                break;
+            default:
+                mGLState.getIntegeri_v(target, index, data);
+        }
+    }
+    else
+    {
+        CastIndexedStateValues(this, nativeType, target, index, numParams, data);
+    }
+}
+
+void Context::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
+{
+    // Queries about context capabilities and maximums are answered by Context.
+    // Queries about current GL state values are answered by State.
+
+    GLenum nativeType;
+    unsigned int numParams;
+    bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
+    ASSERT(queryStatus);
+
+    if (nativeType == GL_INT_64_ANGLEX)
+    {
+        mGLState.getInteger64i_v(target, index, data);
+    }
+    else
+    {
+        CastIndexedStateValues(this, nativeType, target, index, numParams, data);
+    }
+}
+
+void Context::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+    // Queries about context capabilities and maximums are answered by Context.
+    // Queries about current GL state values are answered by State.
+
+    GLenum nativeType;
+    unsigned int numParams;
+    bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
+    ASSERT(queryStatus);
+
+    if (nativeType == GL_BOOL)
+    {
+        mGLState.getBooleani_v(target, index, data);
+    }
+    else
+    {
+        CastIndexedStateValues(this, nativeType, target, index, numParams, data);
+    }
+}
+
+void Context::getBufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    Buffer *buffer = mGLState.getTargetBuffer(target);
+    QueryBufferParameteriv(buffer, pname, params);
+}
+
+void Context::getFramebufferAttachmentParameteriv(GLenum target,
+                                                  GLenum attachment,
+                                                  GLenum pname,
+                                                  GLint *params)
+{
+    const Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    QueryFramebufferAttachmentParameteriv(framebuffer, attachment, pname, params);
+}
+
+void Context::getRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    Renderbuffer *renderbuffer = mGLState.getCurrentRenderbuffer();
+    QueryRenderbufferiv(this, renderbuffer, pname, params);
+}
+
+void Context::getTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+    Texture *texture = getTargetTexture(target);
+    QueryTexParameterfv(texture, pname, params);
+}
+
+void Context::getTexParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    Texture *texture = getTargetTexture(target);
+    QueryTexParameteriv(texture, pname, params);
+}
+void Context::texParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+    Texture *texture = getTargetTexture(target);
+    SetTexParameterf(texture, pname, param);
+}
+
+void Context::texParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+    Texture *texture = getTargetTexture(target);
+    SetTexParameterfv(texture, pname, params);
+}
+
+void Context::texParameteri(GLenum target, GLenum pname, GLint param)
+{
+    Texture *texture = getTargetTexture(target);
+    SetTexParameteri(texture, pname, param);
+}
+
+void Context::texParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+    Texture *texture = getTargetTexture(target);
+    SetTexParameteriv(texture, pname, params);
+}
+
+void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    syncRendererState();
+    auto error = mImplementation->drawArrays(mode, first, count);
+    handleError(error);
+    if (!error.isError())
+    {
+        MarkTransformFeedbackBufferUsage(mGLState.getCurrentTransformFeedback());
+    }
+}
+
+void Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+{
+    syncRendererState();
+    auto error = mImplementation->drawArraysInstanced(mode, first, count, instanceCount);
+    handleError(error);
+    if (!error.isError())
+    {
+        MarkTransformFeedbackBufferUsage(mGLState.getCurrentTransformFeedback());
+    }
+}
+
+void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
+{
+    syncRendererState();
+    const IndexRange &indexRange = getParams<HasIndexRange>().getIndexRange().value();
+    handleError(mImplementation->drawElements(mode, count, type, indices, indexRange));
+}
+
+void Context::drawElementsInstanced(GLenum mode,
+                                    GLsizei count,
+                                    GLenum type,
+                                    const void *indices,
+                                    GLsizei instances)
+{
+    syncRendererState();
+    const IndexRange &indexRange = getParams<HasIndexRange>().getIndexRange().value();
+    handleError(
+        mImplementation->drawElementsInstanced(mode, count, type, indices, instances, indexRange));
+}
+
+void Context::drawRangeElements(GLenum mode,
+                                GLuint start,
+                                GLuint end,
+                                GLsizei count,
+                                GLenum type,
+                                const void *indices)
+{
+    syncRendererState();
+    const IndexRange &indexRange = getParams<HasIndexRange>().getIndexRange().value();
+    handleError(
+        mImplementation->drawRangeElements(mode, start, end, count, type, indices, indexRange));
+}
+
+void Context::drawArraysIndirect(GLenum mode, const void *indirect)
+{
+    syncRendererState();
+    handleError(mImplementation->drawArraysIndirect(mode, indirect));
+}
+
+void Context::drawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+    syncRendererState();
+    handleError(mImplementation->drawElementsIndirect(mode, type, indirect));
+}
+
+void Context::flush()
+{
+    handleError(mImplementation->flush());
+}
+
+void Context::finish()
+{
+    handleError(mImplementation->finish());
+}
+
+void Context::insertEventMarker(GLsizei length, const char *marker)
+{
+    ASSERT(mImplementation);
+    mImplementation->insertEventMarker(length, marker);
+}
+
+void Context::pushGroupMarker(GLsizei length, const char *marker)
+{
+    ASSERT(mImplementation);
+    mImplementation->pushGroupMarker(length, marker);
+}
+
+void Context::popGroupMarker()
+{
+    ASSERT(mImplementation);
+    mImplementation->popGroupMarker();
+}
+
+void Context::bindUniformLocation(GLuint program, GLint location, const GLchar *name)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+
+    programObject->bindUniformLocation(location, name);
+}
+
+void Context::setCoverageModulation(GLenum components)
+{
+    mGLState.setCoverageModulation(components);
+}
+
+void Context::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
+{
+    mGLState.loadPathRenderingMatrix(matrixMode, matrix);
+}
+
+void Context::loadPathRenderingIdentityMatrix(GLenum matrixMode)
+{
+    GLfloat I[16];
+    angle::Matrix<GLfloat>::setToIdentity(I);
+
+    mGLState.loadPathRenderingMatrix(matrixMode, I);
+}
+
+void Context::stencilFillPath(GLuint path, GLenum fillMode, GLuint mask)
+{
+    const auto *pathObj = mState.mPaths->getPath(path);
+    if (!pathObj)
+        return;
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilFillPath(pathObj, fillMode, mask);
+}
+
+void Context::stencilStrokePath(GLuint path, GLint reference, GLuint mask)
+{
+    const auto *pathObj = mState.mPaths->getPath(path);
+    if (!pathObj)
+        return;
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilStrokePath(pathObj, reference, mask);
+}
+
+void Context::coverFillPath(GLuint path, GLenum coverMode)
+{
+    const auto *pathObj = mState.mPaths->getPath(path);
+    if (!pathObj)
+        return;
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->coverFillPath(pathObj, coverMode);
+}
+
+void Context::coverStrokePath(GLuint path, GLenum coverMode)
+{
+    const auto *pathObj = mState.mPaths->getPath(path);
+    if (!pathObj)
+        return;
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->coverStrokePath(pathObj, coverMode);
+}
+
+void Context::stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode)
+{
+    const auto *pathObj = mState.mPaths->getPath(path);
+    if (!pathObj)
+        return;
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilThenCoverFillPath(pathObj, fillMode, mask, coverMode);
+}
+
+void Context::stencilThenCoverStrokePath(GLuint path,
+                                         GLint reference,
+                                         GLuint mask,
+                                         GLenum coverMode)
+{
+    const auto *pathObj = mState.mPaths->getPath(path);
+    if (!pathObj)
+        return;
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilThenCoverStrokePath(pathObj, reference, mask, coverMode);
+}
+
+void Context::coverFillPathInstanced(GLsizei numPaths,
+                                     GLenum pathNameType,
+                                     const void *paths,
+                                     GLuint pathBase,
+                                     GLenum coverMode,
+                                     GLenum transformType,
+                                     const GLfloat *transformValues)
+{
+    const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->coverFillPathInstanced(pathObjects, coverMode, transformType, transformValues);
+}
+
+void Context::coverStrokePathInstanced(GLsizei numPaths,
+                                       GLenum pathNameType,
+                                       const void *paths,
+                                       GLuint pathBase,
+                                       GLenum coverMode,
+                                       GLenum transformType,
+                                       const GLfloat *transformValues)
+{
+    const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->coverStrokePathInstanced(pathObjects, coverMode, transformType,
+                                              transformValues);
+}
+
+void Context::stencilFillPathInstanced(GLsizei numPaths,
+                                       GLenum pathNameType,
+                                       const void *paths,
+                                       GLuint pathBase,
+                                       GLenum fillMode,
+                                       GLuint mask,
+                                       GLenum transformType,
+                                       const GLfloat *transformValues)
+{
+    const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilFillPathInstanced(pathObjects, fillMode, mask, transformType,
+                                              transformValues);
+}
+
+void Context::stencilStrokePathInstanced(GLsizei numPaths,
+                                         GLenum pathNameType,
+                                         const void *paths,
+                                         GLuint pathBase,
+                                         GLint reference,
+                                         GLuint mask,
+                                         GLenum transformType,
+                                         const GLfloat *transformValues)
+{
+    const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilStrokePathInstanced(pathObjects, reference, mask, transformType,
+                                                transformValues);
+}
+
+void Context::stencilThenCoverFillPathInstanced(GLsizei numPaths,
+                                                GLenum pathNameType,
+                                                const void *paths,
+                                                GLuint pathBase,
+                                                GLenum fillMode,
+                                                GLuint mask,
+                                                GLenum coverMode,
+                                                GLenum transformType,
+                                                const GLfloat *transformValues)
+{
+    const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilThenCoverFillPathInstanced(pathObjects, coverMode, fillMode, mask,
+                                                       transformType, transformValues);
+}
+
+void Context::stencilThenCoverStrokePathInstanced(GLsizei numPaths,
+                                                  GLenum pathNameType,
+                                                  const void *paths,
+                                                  GLuint pathBase,
+                                                  GLint reference,
+                                                  GLuint mask,
+                                                  GLenum coverMode,
+                                                  GLenum transformType,
+                                                  const GLfloat *transformValues)
+{
+    const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+    syncRendererState();
+
+    mImplementation->stencilThenCoverStrokePathInstanced(pathObjects, coverMode, reference, mask,
+                                                         transformType, transformValues);
+}
+
+void Context::bindFragmentInputLocation(GLuint program, GLint location, const GLchar *name)
+{
+    auto *programObject = getProgram(program);
+
+    programObject->bindFragmentInputLocation(location, name);
+}
+
+void Context::programPathFragmentInputGen(GLuint program,
+                                          GLint location,
+                                          GLenum genMode,
+                                          GLint components,
+                                          const GLfloat *coeffs)
+{
+    auto *programObject = getProgram(program);
+
+    programObject->pathFragmentInputGen(location, genMode, components, coeffs);
+}
+
+GLuint Context::getProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name)
+{
+    const auto *programObject = getProgram(program);
+    return QueryProgramResourceIndex(programObject, programInterface, name);
+}
+
+void Context::getProgramResourceName(GLuint program,
+                                     GLenum programInterface,
+                                     GLuint index,
+                                     GLsizei bufSize,
+                                     GLsizei *length,
+                                     GLchar *name)
+{
+    const auto *programObject = getProgram(program);
+    QueryProgramResourceName(programObject, programInterface, index, bufSize, length, name);
+}
+
+void Context::handleError(const Error &error)
+{
+    if (error.isError())
+    {
+        GLenum code = error.getCode();
+        mErrors.insert(code);
+        if (code == GL_OUT_OF_MEMORY && getWorkarounds().loseContextOnOutOfMemory)
+        {
+            markContextLost();
+        }
+
+        if (!error.getMessage().empty())
+        {
+            auto *debug = &mGLState.getDebug();
+            debug->insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, error.getID(),
+                                 GL_DEBUG_SEVERITY_HIGH, error.getMessage());
+        }
+    }
+}
+
+// Get one of the recorded errors and clear its flag, if any.
+// [OpenGL ES 2.0.24] section 2.5 page 13.
+GLenum Context::getError()
+{
+    if (mErrors.empty())
+    {
+        return GL_NO_ERROR;
+    }
+    else
+    {
+        GLenum error = *mErrors.begin();
+        mErrors.erase(mErrors.begin());
+        return error;
+    }
+}
+
+// NOTE: this function should not assume that this context is current!
+void Context::markContextLost()
+{
+    if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
+    {
+        mResetStatus       = GL_UNKNOWN_CONTEXT_RESET_EXT;
+        mContextLostForced = true;
+    }
+    mContextLost = true;
+}
+
+bool Context::isContextLost()
+{
+    return mContextLost;
+}
+
+GLenum Context::getResetStatus()
+{
+    // Even if the application doesn't want to know about resets, we want to know
+    // as it will allow us to skip all the calls.
+    if (mResetStrategy == GL_NO_RESET_NOTIFICATION_EXT)
+    {
+        if (!mContextLost && mImplementation->getResetStatus() != GL_NO_ERROR)
+        {
+            mContextLost = true;
+        }
+
+        // EXT_robustness, section 2.6: If the reset notification behavior is
+        // NO_RESET_NOTIFICATION_EXT, then the implementation will never deliver notification of
+        // reset events, and GetGraphicsResetStatusEXT will always return NO_ERROR.
+        return GL_NO_ERROR;
+    }
+
+    // The GL_EXT_robustness spec says that if a reset is encountered, a reset
+    // status should be returned at least once, and GL_NO_ERROR should be returned
+    // once the device has finished resetting.
+    if (!mContextLost)
+    {
+        ASSERT(mResetStatus == GL_NO_ERROR);
+        mResetStatus = mImplementation->getResetStatus();
+
+        if (mResetStatus != GL_NO_ERROR)
+        {
+            mContextLost = true;
+        }
+    }
+    else if (!mContextLostForced && mResetStatus != GL_NO_ERROR)
+    {
+        // If markContextLost was used to mark the context lost then
+        // assume that is not recoverable, and continue to report the
+        // lost reset status for the lifetime of this context.
+        mResetStatus = mImplementation->getResetStatus();
+    }
+
+    return mResetStatus;
+}
+
+bool Context::isResetNotificationEnabled()
+{
+    return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
+}
+
+const egl::Config *Context::getConfig() const
+{
+    return mConfig;
+}
+
+EGLenum Context::getClientType() const
+{
+    return mClientType;
+}
+
+EGLenum Context::getRenderBuffer() const
+{
+    const Framebuffer *framebuffer = mState.mFramebuffers->getFramebuffer(0);
+    if (framebuffer == nullptr)
+    {
+        return EGL_NONE;
+    }
+
+    const FramebufferAttachment *backAttachment = framebuffer->getAttachment(GL_BACK);
+    ASSERT(backAttachment != nullptr);
+    return backAttachment->getSurface()->getRenderBuffer();
+}
+
+VertexArray *Context::checkVertexArrayAllocation(GLuint vertexArrayHandle)
+{
+    // Only called after a prior call to Gen.
+    VertexArray *vertexArray = getVertexArray(vertexArrayHandle);
+    if (!vertexArray)
+    {
+        vertexArray = new VertexArray(mImplementation.get(), vertexArrayHandle,
+                                      mCaps.maxVertexAttributes, mCaps.maxVertexAttribBindings);
+
+        mVertexArrayMap[vertexArrayHandle] = vertexArray;
+    }
+
+    return vertexArray;
+}
+
+TransformFeedback *Context::checkTransformFeedbackAllocation(GLuint transformFeedbackHandle)
+{
+    // Only called after a prior call to Gen.
+    TransformFeedback *transformFeedback = getTransformFeedback(transformFeedbackHandle);
+    if (!transformFeedback)
+    {
+        transformFeedback =
+            new TransformFeedback(mImplementation.get(), transformFeedbackHandle, mCaps);
+        transformFeedback->addRef();
+        mTransformFeedbackMap[transformFeedbackHandle] = transformFeedback;
+    }
+
+    return transformFeedback;
+}
+
+bool Context::isVertexArrayGenerated(GLuint vertexArray)
+{
+    ASSERT(mVertexArrayMap.find(0) != mVertexArrayMap.end());
+    return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end();
+}
+
+bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
+{
+    ASSERT(mTransformFeedbackMap.find(0) != mTransformFeedbackMap.end());
+    return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end();
+}
+
+void Context::detachTexture(GLuint texture)
+{
+    // Simple pass-through to State's detachTexture method, as textures do not require
+    // allocation map management either here or in the resource manager at detach time.
+    // Zero textures are held by the Context, and we don't attempt to request them from
+    // the State.
+    mGLState.detachTexture(this, mZeroTextures, texture);
+}
+
+void Context::detachBuffer(GLuint buffer)
+{
+    // Simple pass-through to State's detachBuffer method, since
+    // only buffer attachments to container objects that are bound to the current context
+    // should be detached. And all those are available in State.
+
+    // [OpenGL ES 3.2] section 5.1.2 page 45:
+    // Attachments to unbound container objects, such as
+    // deletion of a buffer attached to a vertex array object which is not bound to the context,
+    // are not affected and continue to act as references on the deleted object
+    mGLState.detachBuffer(buffer);
+}
+
+void Context::detachFramebuffer(GLuint framebuffer)
+{
+    // Framebuffer detachment is handled by Context, because 0 is a valid
+    // Framebuffer object, and a pointer to it must be passed from Context
+    // to State at binding time.
+
+    // [OpenGL ES 2.0.24] section 4.4 page 107:
+    // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as
+    // though BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of
+    // zero.
+
+    if (mGLState.removeReadFramebufferBinding(framebuffer) && framebuffer != 0)
+    {
+        bindReadFramebuffer(0);
+    }
+
+    if (mGLState.removeDrawFramebufferBinding(framebuffer) && framebuffer != 0)
+    {
+        bindDrawFramebuffer(0);
+    }
+}
+
+void Context::detachRenderbuffer(GLuint renderbuffer)
+{
+    mGLState.detachRenderbuffer(this, renderbuffer);
+}
+
+void Context::detachVertexArray(GLuint vertexArray)
+{
+    // Vertex array detachment is handled by Context, because 0 is a valid
+    // VAO, and a pointer to it must be passed from Context to State at
+    // binding time.
+
+    // [OpenGL ES 3.0.2] section 2.10 page 43:
+    // If a vertex array object that is currently bound is deleted, the binding
+    // for that object reverts to zero and the default vertex array becomes current.
+    if (mGLState.removeVertexArrayBinding(vertexArray))
+    {
+        bindVertexArray(0);
+    }
+}
+
+void Context::detachTransformFeedback(GLuint transformFeedback)
+{
+    // Transform feedback detachment is handled by Context, because 0 is a valid
+    // transform feedback, and a pointer to it must be passed from Context to State at
+    // binding time.
+
+    // The OpenGL specification doesn't mention what should happen when the currently bound
+    // transform feedback object is deleted. Since it is a container object, we treat it like
+    // VAOs and FBOs and set the current bound transform feedback back to 0.
+    if (mGLState.removeTransformFeedbackBinding(transformFeedback))
+    {
+        bindTransformFeedback(0);
+    }
+}
+
+void Context::detachSampler(GLuint sampler)
+{
+    mGLState.detachSampler(sampler);
+}
+
+void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+    mGLState.setVertexAttribDivisor(index, divisor);
+}
+
+void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+    Sampler *samplerObject =
+        mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+    SetSamplerParameteri(samplerObject, pname, param);
+}
+
+void Context::samplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
+{
+    Sampler *samplerObject =
+        mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+    SetSamplerParameteriv(samplerObject, pname, param);
+}
+
+void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+{
+    Sampler *samplerObject =
+        mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+    SetSamplerParameterf(samplerObject, pname, param);
+}
+
+void Context::samplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
+{
+    Sampler *samplerObject =
+        mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+    SetSamplerParameterfv(samplerObject, pname, param);
+}
+
+void Context::getSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
+{
+    const Sampler *samplerObject =
+        mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+    QuerySamplerParameteriv(samplerObject, pname, params);
+}
+
+void Context::getSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
+{
+    const Sampler *samplerObject =
+        mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+    QuerySamplerParameterfv(samplerObject, pname, params);
+}
+
+void Context::programParameteri(GLuint program, GLenum pname, GLint value)
+{
+    gl::Program *programObject = getProgram(program);
+    SetProgramParameteri(programObject, pname, value);
+}
+
+void Context::initRendererString()
+{
+    std::ostringstream rendererString;
+    rendererString << "ANGLE (";
+    rendererString << mImplementation->getRendererDescription();
+    rendererString << ")";
+
+    mRendererString = MakeStaticString(rendererString.str());
+}
+
+void Context::initVersionStrings()
+{
+    const Version &clientVersion = getClientVersion();
+
+    std::ostringstream versionString;
+    versionString << "OpenGL ES " << clientVersion.major << "." << clientVersion.minor << " (ANGLE "
+                  << ANGLE_VERSION_STRING << ")";
+    mVersionString = MakeStaticString(versionString.str());
+
+    std::ostringstream shadingLanguageVersionString;
+    shadingLanguageVersionString << "OpenGL ES GLSL ES "
+                                 << (clientVersion.major == 2 ? 1 : clientVersion.major) << "."
+                                 << clientVersion.minor << "0 (ANGLE " << ANGLE_VERSION_STRING
+                                 << ")";
+    mShadingLanguageString = MakeStaticString(shadingLanguageVersionString.str());
+}
+
+void Context::initExtensionStrings()
+{
+    auto mergeExtensionStrings = [](const std::vector<const char *> &strings) {
+        std::ostringstream combinedStringStream;
+        std::copy(strings.begin(), strings.end(),
+                  std::ostream_iterator<const char *>(combinedStringStream, " "));
+        return MakeStaticString(combinedStringStream.str());
+    };
+
+    mExtensionStrings.clear();
+    for (const auto &extensionString : mExtensions.getStrings())
+    {
+        mExtensionStrings.push_back(MakeStaticString(extensionString));
+    }
+    mExtensionString = mergeExtensionStrings(mExtensionStrings);
+
+    const gl::Extensions &nativeExtensions = mImplementation->getNativeExtensions();
+
+    mRequestableExtensionStrings.clear();
+    for (const auto &extensionInfo : GetExtensionInfoMap())
+    {
+        if (extensionInfo.second.Requestable &&
+            !(mExtensions.*(extensionInfo.second.ExtensionsMember)) &&
+            nativeExtensions.*(extensionInfo.second.ExtensionsMember))
+        {
+            mRequestableExtensionStrings.push_back(MakeStaticString(extensionInfo.first));
+        }
+    }
+    mRequestableExtensionString = mergeExtensionStrings(mRequestableExtensionStrings);
+}
+
+const GLubyte *Context::getString(GLenum name) const
+{
+    switch (name)
+    {
+        case GL_VENDOR:
+            return reinterpret_cast<const GLubyte *>("Google Inc.");
+
+        case GL_RENDERER:
+            return reinterpret_cast<const GLubyte *>(mRendererString);
+
+        case GL_VERSION:
+            return reinterpret_cast<const GLubyte *>(mVersionString);
+
+        case GL_SHADING_LANGUAGE_VERSION:
+            return reinterpret_cast<const GLubyte *>(mShadingLanguageString);
+
+        case GL_EXTENSIONS:
+            return reinterpret_cast<const GLubyte *>(mExtensionString);
+
+        case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+            return reinterpret_cast<const GLubyte *>(mRequestableExtensionString);
+
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+}
+
+const GLubyte *Context::getStringi(GLenum name, GLuint index) const
+{
+    switch (name)
+    {
+        case GL_EXTENSIONS:
+            return reinterpret_cast<const GLubyte *>(mExtensionStrings[index]);
+
+        case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+            return reinterpret_cast<const GLubyte *>(mRequestableExtensionStrings[index]);
+
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+}
+
+size_t Context::getExtensionStringCount() const
+{
+    return mExtensionStrings.size();
+}
+
+void Context::requestExtension(const char *name)
+{
+    const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+    ASSERT(extensionInfos.find(name) != extensionInfos.end());
+    const auto &extension = extensionInfos.at(name);
+    ASSERT(extension.Requestable);
+
+    if (mExtensions.*(extension.ExtensionsMember))
+    {
+        // Extension already enabled
+        return;
+    }
+
+    mExtensions.*(extension.ExtensionsMember) = true;
+    updateCaps();
+    initExtensionStrings();
+
+    // Re-create the compiler with the requested extensions enabled.
+    SafeDelete(mCompiler);
+    mCompiler = new Compiler(mImplementation.get(), mState);
+
+    // Invalidate all cached completenesses for textures and framebuffer. Some extensions make new
+    // formats renderable or sampleable.
+    mState.mTextures->invalidateTextureComplenessCache();
+    for (auto &zeroTexture : mZeroTextures)
+    {
+        zeroTexture.second->invalidateCompletenessCache();
+    }
+
+    mState.mFramebuffers->invalidateFramebufferComplenessCache();
+}
+
+size_t Context::getRequestableExtensionStringCount() const
+{
+    return mRequestableExtensionStrings.size();
+}
+
+void Context::beginTransformFeedback(GLenum primitiveMode)
+{
+    TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
+    ASSERT(transformFeedback != nullptr);
+    ASSERT(!transformFeedback->isPaused());
+
+    transformFeedback->begin(this, primitiveMode, mGLState.getProgram());
+}
+
+bool Context::hasActiveTransformFeedback(GLuint program) const
+{
+    for (auto pair : mTransformFeedbackMap)
+    {
+        if (pair.second != nullptr && pair.second->hasBoundProgram(program))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+void Context::initCaps(const egl::DisplayExtensions &displayExtensions)
+{
+    mCaps = mImplementation->getNativeCaps();
+
+    mExtensions = mImplementation->getNativeExtensions();
+
+    mLimitations = mImplementation->getNativeLimitations();
+
+    if (getClientVersion() < Version(3, 0))
+    {
+        // Disable ES3+ extensions
+        mExtensions.colorBufferFloat      = false;
+        mExtensions.eglImageExternalEssl3 = false;
+        mExtensions.textureNorm16         = false;
+    }
+
+    if (getClientVersion() > Version(2, 0))
+    {
+        // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
+        // mExtensions.sRGB = false;
+    }
+
+    // Some extensions are always available because they are implemented in the GL layer.
+    mExtensions.bindUniformLocation   = true;
+    mExtensions.vertexArrayObject     = true;
+    mExtensions.bindGeneratesResource = true;
+    mExtensions.clientArrays          = true;
+    mExtensions.requestExtension      = true;
+
+    // Enable the no error extension if the context was created with the flag.
+    mExtensions.noError = mSkipValidation;
+
+    // Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO
+    mExtensions.surfacelessContext = displayExtensions.surfacelessContext;
+
+    // Explicitly enable GL_KHR_debug
+    mExtensions.debug                   = true;
+    mExtensions.maxDebugMessageLength   = 1024;
+    mExtensions.maxDebugLoggedMessages  = 1024;
+    mExtensions.maxDebugGroupStackDepth = 1024;
+    mExtensions.maxLabelLength          = 1024;
+
+    // Explicitly enable GL_ANGLE_robust_client_memory
+    mExtensions.robustClientMemory = true;
+
+    // Determine robust resource init availability from EGL.
+    mExtensions.robustResourceInitialization =
+        displayExtensions.createContextRobustResourceInitialization;
+
+    // Apply implementation limits
+    mCaps.maxVertexAttributes = std::min<GLuint>(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
+    mCaps.maxVertexAttribBindings =
+        getClientVersion() < ES_3_1
+            ? mCaps.maxVertexAttributes
+            : std::min<GLuint>(mCaps.maxVertexAttribBindings, MAX_VERTEX_ATTRIB_BINDINGS);
+
+    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);
+
+    // WebGL compatibility
+    mExtensions.webglCompatibility = mWebGLContext;
+    for (const auto &extensionInfo : GetExtensionInfoMap())
+    {
+        // If this context is for WebGL, disable all enableable extensions
+        if (mWebGLContext && extensionInfo.second.Requestable)
+        {
+            mExtensions.*(extensionInfo.second.ExtensionsMember) = false;
+        }
+    }
+
+    // Generate texture caps
+    updateCaps();
+}
+
+void Context::updateCaps()
+{
+    mCaps.compressedTextureFormats.clear();
+    mTextureCaps.clear();
+
+    for (auto capsIt : mImplementation->getNativeTextureCaps())
+    {
+        GLenum sizedInternalFormat = capsIt.first;
+        TextureCaps formatCaps     = capsIt.second;
+
+        const InternalFormat &formatInfo = GetSizedInternalFormatInfo(sizedInternalFormat);
+
+        // Update the format caps based on the client version and extensions.
+        // Caps are AND'd with the renderer caps because some core formats are still unsupported in
+        // ES3.
+        formatCaps.texturable =
+            formatCaps.texturable && formatInfo.textureSupport(getClientVersion(), mExtensions);
+        formatCaps.renderable =
+            formatCaps.renderable && formatInfo.renderSupport(getClientVersion(), mExtensions);
+        formatCaps.filterable =
+            formatCaps.filterable && formatInfo.filterSupport(getClientVersion(), mExtensions);
+
+        // OpenGL ES does not support multisampling with non-rendererable formats
+        // OpenGL ES 3.0 or prior does not support multisampling with integer formats
+        if (!formatInfo.renderSupport ||
+            (getClientVersion() < ES_3_1 &&
+             (formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT)))
+        {
+            formatCaps.sampleCounts.clear();
+        }
+
+        if (formatCaps.texturable && formatInfo.compressed)
+        {
+            mCaps.compressedTextureFormats.push_back(sizedInternalFormat);
+        }
+
+        mTextureCaps.insert(sizedInternalFormat, formatCaps);
+    }
+}
+
+void Context::initWorkarounds()
+{
+    // Lose the context upon out of memory error if the application is
+    // expecting to watch for those events.
+    mWorkarounds.loseContextOnOutOfMemory = (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
+}
+
+void Context::syncRendererState()
+{
+    const State::DirtyBits &dirtyBits = mGLState.getDirtyBits();
+    mImplementation->syncState(dirtyBits);
+    mGLState.clearDirtyBits();
+    mGLState.syncDirtyObjects(this);
+}
+
+void Context::syncRendererState(const State::DirtyBits &bitMask,
+                                const State::DirtyObjects &objectMask)
+{
+    const State::DirtyBits &dirtyBits = (mGLState.getDirtyBits() & bitMask);
+    mImplementation->syncState(dirtyBits);
+    mGLState.clearDirtyBits(dirtyBits);
+    mGLState.syncDirtyObjects(this, objectMask);
+}
+
+void Context::blitFramebuffer(GLint srcX0,
+                              GLint srcY0,
+                              GLint srcX1,
+                              GLint srcY1,
+                              GLint dstX0,
+                              GLint dstY0,
+                              GLint dstX1,
+                              GLint dstY1,
+                              GLbitfield mask,
+                              GLenum filter)
+{
+    Framebuffer *drawFramebuffer = mGLState.getDrawFramebuffer();
+    ASSERT(drawFramebuffer);
+
+    Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
+    Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
+
+    syncStateForBlit();
+
+    handleError(drawFramebuffer->blit(mImplementation.get(), srcArea, dstArea, mask, filter));
+}
+
+void Context::clear(GLbitfield mask)
+{
+    syncStateForClear();
+    handleError(mGLState.getDrawFramebuffer()->clear(mImplementation.get(), mask));
+}
+
+void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
+{
+    syncStateForClear();
+    handleError(mGLState.getDrawFramebuffer()->clearBufferfv(mImplementation.get(), buffer,
+                                                             drawbuffer, values));
+}
+
+void Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values)
+{
+    syncStateForClear();
+    handleError(mGLState.getDrawFramebuffer()->clearBufferuiv(mImplementation.get(), buffer,
+                                                              drawbuffer, values));
+}
+
+void Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values)
+{
+    syncStateForClear();
+    handleError(mGLState.getDrawFramebuffer()->clearBufferiv(mImplementation.get(), buffer,
+                                                             drawbuffer, values));
+}
+
+void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+    Framebuffer *framebufferObject = mGLState.getDrawFramebuffer();
+    ASSERT(framebufferObject);
+
+    // If a buffer is not present, the clear has no effect
+    if (framebufferObject->getDepthbuffer() == nullptr &&
+        framebufferObject->getStencilbuffer() == nullptr)
+    {
+        return;
+    }
+
+    syncStateForClear();
+    handleError(framebufferObject->clearBufferfi(mImplementation.get(), buffer, drawbuffer, depth,
+                                                 stencil));
+}
+
+void Context::readPixels(GLint x,
+                         GLint y,
+                         GLsizei width,
+                         GLsizei height,
+                         GLenum format,
+                         GLenum type,
+                         void *pixels)
+{
+    if (width == 0 || height == 0)
+    {
+        return;
+    }
+
+    syncStateForReadPixels();
+
+    Framebuffer *framebufferObject = mGLState.getReadFramebuffer();
+    ASSERT(framebufferObject);
+
+    Rectangle area(x, y, width, height);
+    handleError(framebufferObject->readPixels(mImplementation.get(), area, format, type, pixels));
+}
+
+void Context::copyTexImage2D(GLenum target,
+                             GLint level,
+                             GLenum internalformat,
+                             GLint x,
+                             GLint y,
+                             GLsizei width,
+                             GLsizei height,
+                             GLint border)
+{
+    // Only sync the read FBO
+    mGLState.syncDirtyObject(this, GL_READ_FRAMEBUFFER);
+
+    Rectangle sourceArea(x, y, width, height);
+
+    const Framebuffer *framebuffer = mGLState.getReadFramebuffer();
+    Texture *texture =
+        getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    handleError(texture->copyImage(this, target, level, sourceArea, internalformat, framebuffer));
+}
+
+void Context::copyTexSubImage2D(GLenum target,
+                                GLint level,
+                                GLint xoffset,
+                                GLint yoffset,
+                                GLint x,
+                                GLint y,
+                                GLsizei width,
+                                GLsizei height)
+{
+    if (width == 0 || height == 0)
+    {
+        return;
+    }
+
+    // Only sync the read FBO
+    mGLState.syncDirtyObject(this, GL_READ_FRAMEBUFFER);
+
+    Offset destOffset(xoffset, yoffset, 0);
+    Rectangle sourceArea(x, y, width, height);
+
+    const Framebuffer *framebuffer = mGLState.getReadFramebuffer();
+    Texture *texture =
+        getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    handleError(texture->copySubImage(this, target, level, destOffset, sourceArea, framebuffer));
+}
+
+void Context::copyTexSubImage3D(GLenum target,
+                                GLint level,
+                                GLint xoffset,
+                                GLint yoffset,
+                                GLint zoffset,
+                                GLint x,
+                                GLint y,
+                                GLsizei width,
+                                GLsizei height)
+{
+    if (width == 0 || height == 0)
+    {
+        return;
+    }
+
+    // Only sync the read FBO
+    mGLState.syncDirtyObject(this, GL_READ_FRAMEBUFFER);
+
+    Offset destOffset(xoffset, yoffset, zoffset);
+    Rectangle sourceArea(x, y, width, height);
+
+    const Framebuffer *framebuffer = mGLState.getReadFramebuffer();
+    Texture *texture               = getTargetTexture(target);
+    handleError(texture->copySubImage(this, target, level, destOffset, sourceArea, framebuffer));
+}
+
+void Context::framebufferTexture2D(GLenum target,
+                                   GLenum attachment,
+                                   GLenum textarget,
+                                   GLuint texture,
+                                   GLint level)
+{
+    Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (texture != 0)
+    {
+        Texture *textureObj = getTexture(texture);
+
+        ImageIndex index = ImageIndex::MakeInvalid();
+
+        if (textarget == GL_TEXTURE_2D)
+        {
+            index = ImageIndex::Make2D(level);
+        }
+        else if (textarget == GL_TEXTURE_2D_MULTISAMPLE)
+        {
+            ASSERT(level == 0);
+            index = ImageIndex::Make2DMultisample();
+        }
+        else
+        {
+            ASSERT(IsCubeMapTextureTarget(textarget));
+            index = ImageIndex::MakeCube(textarget, level);
+        }
+
+        framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObj);
+    }
+    else
+    {
+        framebuffer->resetAttachment(this, attachment);
+    }
+
+    mGLState.setObjectDirty(target);
+}
+
+void Context::framebufferRenderbuffer(GLenum target,
+                                      GLenum attachment,
+                                      GLenum renderbuffertarget,
+                                      GLuint renderbuffer)
+{
+    Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (renderbuffer != 0)
+    {
+        Renderbuffer *renderbufferObject = getRenderbuffer(renderbuffer);
+
+        framebuffer->setAttachment(this, GL_RENDERBUFFER, attachment, gl::ImageIndex::MakeInvalid(),
+                                   renderbufferObject);
+    }
+    else
+    {
+        framebuffer->resetAttachment(this, attachment);
+    }
+
+    mGLState.setObjectDirty(target);
+}
+
+void Context::framebufferTextureLayer(GLenum target,
+                                      GLenum attachment,
+                                      GLuint texture,
+                                      GLint level,
+                                      GLint layer)
+{
+    Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (texture != 0)
+    {
+        Texture *textureObject = getTexture(texture);
+
+        ImageIndex index = ImageIndex::MakeInvalid();
+
+        if (textureObject->getTarget() == GL_TEXTURE_3D)
+        {
+            index = ImageIndex::Make3D(level, layer);
+        }
+        else
+        {
+            ASSERT(textureObject->getTarget() == GL_TEXTURE_2D_ARRAY);
+            index = ImageIndex::Make2DArray(level, layer);
+        }
+
+        framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObject);
+    }
+    else
+    {
+        framebuffer->resetAttachment(this, attachment);
+    }
+
+    mGLState.setObjectDirty(target);
+}
+
+void Context::drawBuffers(GLsizei n, const GLenum *bufs)
+{
+    Framebuffer *framebuffer = mGLState.getDrawFramebuffer();
+    ASSERT(framebuffer);
+    framebuffer->setDrawBuffers(n, bufs);
+    mGLState.setObjectDirty(GL_DRAW_FRAMEBUFFER);
+}
+
+void Context::readBuffer(GLenum mode)
+{
+    Framebuffer *readFBO = mGLState.getReadFramebuffer();
+    readFBO->setReadBuffer(mode);
+    mGLState.setObjectDirty(GL_READ_FRAMEBUFFER);
+}
+
+void Context::discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
+{
+    // Only sync the FBO
+    mGLState.syncDirtyObject(this, target);
+
+    Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    // The specification isn't clear what should be done when the framebuffer isn't complete.
+    // We leave it up to the framebuffer implementation to decide what to do.
+    handleError(framebuffer->discard(numAttachments, attachments));
+}
+
+void Context::invalidateFramebuffer(GLenum target,
+                                    GLsizei numAttachments,
+                                    const GLenum *attachments)
+{
+    // Only sync the FBO
+    mGLState.syncDirtyObject(this, target);
+
+    Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (framebuffer->checkStatus(this) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return;
+    }
+
+    handleError(framebuffer->invalidate(numAttachments, attachments));
+}
+
+void Context::invalidateSubFramebuffer(GLenum target,
+                                       GLsizei numAttachments,
+                                       const GLenum *attachments,
+                                       GLint x,
+                                       GLint y,
+                                       GLsizei width,
+                                       GLsizei height)
+{
+    // Only sync the FBO
+    mGLState.syncDirtyObject(this, target);
+
+    Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (framebuffer->checkStatus(this) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return;
+    }
+
+    Rectangle area(x, y, width, height);
+    handleError(framebuffer->invalidateSub(numAttachments, attachments, area));
+}
+
+void Context::texImage2D(GLenum target,
+                         GLint level,
+                         GLint internalformat,
+                         GLsizei width,
+                         GLsizei height,
+                         GLint border,
+                         GLenum format,
+                         GLenum type,
+                         const void *pixels)
+{
+    syncStateForTexImage();
+
+    Extents size(width, height, 1);
+    Texture *texture =
+        getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    handleError(texture->setImage(this, mGLState.getUnpackState(), target, level, internalformat,
+                                  size, format, type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texImage3D(GLenum target,
+                         GLint level,
+                         GLint internalformat,
+                         GLsizei width,
+                         GLsizei height,
+                         GLsizei depth,
+                         GLint border,
+                         GLenum format,
+                         GLenum type,
+                         const void *pixels)
+{
+    syncStateForTexImage();
+
+    Extents size(width, height, depth);
+    Texture *texture = getTargetTexture(target);
+    handleError(texture->setImage(this, mGLState.getUnpackState(), target, level, internalformat,
+                                  size, format, type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texSubImage2D(GLenum target,
+                            GLint level,
+                            GLint xoffset,
+                            GLint yoffset,
+                            GLsizei width,
+                            GLsizei height,
+                            GLenum format,
+                            GLenum type,
+                            const void *pixels)
+{
+    // Zero sized uploads are valid but no-ops
+    if (width == 0 || height == 0)
+    {
+        return;
+    }
+
+    syncStateForTexImage();
+
+    Box area(xoffset, yoffset, 0, width, height, 1);
+    Texture *texture =
+        getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    handleError(texture->setSubImage(this, mGLState.getUnpackState(), target, level, area, format,
+                                     type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texSubImage3D(GLenum target,
+                            GLint level,
+                            GLint xoffset,
+                            GLint yoffset,
+                            GLint zoffset,
+                            GLsizei width,
+                            GLsizei height,
+                            GLsizei depth,
+                            GLenum format,
+                            GLenum type,
+                            const void *pixels)
+{
+    // Zero sized uploads are valid but no-ops
+    if (width == 0 || height == 0 || depth == 0)
+    {
+        return;
+    }
+
+    syncStateForTexImage();
+
+    Box area(xoffset, yoffset, zoffset, width, height, depth);
+    Texture *texture = getTargetTexture(target);
+    handleError(texture->setSubImage(this, mGLState.getUnpackState(), target, level, area, format,
+                                     type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::compressedTexImage2D(GLenum target,
+                                   GLint level,
+                                   GLenum internalformat,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   GLint border,
+                                   GLsizei imageSize,
+                                   const void *data)
+{
+    syncStateForTexImage();
+
+    Extents size(width, height, 1);
+    Texture *texture =
+        getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    handleError(texture->setCompressedImage(this, mGLState.getUnpackState(), target, level,
+                                            internalformat, size, imageSize,
+                                            reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexImage3D(GLenum target,
+                                   GLint level,
+                                   GLenum internalformat,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   GLsizei depth,
+                                   GLint border,
+                                   GLsizei imageSize,
+                                   const void *data)
+{
+    syncStateForTexImage();
+
+    Extents size(width, height, depth);
+    Texture *texture = getTargetTexture(target);
+    handleError(texture->setCompressedImage(this, mGLState.getUnpackState(), target, level,
+                                            internalformat, size, imageSize,
+                                            reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexSubImage2D(GLenum target,
+                                      GLint level,
+                                      GLint xoffset,
+                                      GLint yoffset,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLenum format,
+                                      GLsizei imageSize,
+                                      const void *data)
+{
+    syncStateForTexImage();
+
+    Box area(xoffset, yoffset, 0, width, height, 1);
+    Texture *texture =
+        getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    handleError(texture->setCompressedSubImage(this, mGLState.getUnpackState(), target, level, area,
+                                               format, imageSize,
+                                               reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexSubImage3D(GLenum target,
+                                      GLint level,
+                                      GLint xoffset,
+                                      GLint yoffset,
+                                      GLint zoffset,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLsizei depth,
+                                      GLenum format,
+                                      GLsizei imageSize,
+                                      const void *data)
+{
+    // Zero sized uploads are valid but no-ops
+    if (width == 0 || height == 0)
+    {
+        return;
+    }
+
+    syncStateForTexImage();
+
+    Box area(xoffset, yoffset, zoffset, width, height, depth);
+    Texture *texture = getTargetTexture(target);
+    handleError(texture->setCompressedSubImage(this, mGLState.getUnpackState(), target, level, area,
+                                               format, imageSize,
+                                               reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::generateMipmap(GLenum target)
+{
+    Texture *texture = getTargetTexture(target);
+    handleError(texture->generateMipmap(this));
+}
+
+void Context::copyTextureCHROMIUM(GLuint sourceId,
+                                  GLint sourceLevel,
+                                  GLenum destTarget,
+                                  GLuint destId,
+                                  GLint destLevel,
+                                  GLint internalFormat,
+                                  GLenum destType,
+                                  GLboolean unpackFlipY,
+                                  GLboolean unpackPremultiplyAlpha,
+                                  GLboolean unpackUnmultiplyAlpha)
+{
+    syncStateForTexImage();
+
+    gl::Texture *sourceTexture = getTexture(sourceId);
+    gl::Texture *destTexture   = getTexture(destId);
+    handleError(destTexture->copyTexture(
+        this, destTarget, destLevel, internalFormat, destType, sourceLevel, unpackFlipY == GL_TRUE,
+        unpackPremultiplyAlpha == GL_TRUE, unpackUnmultiplyAlpha == GL_TRUE, sourceTexture));
+}
+
+void Context::copySubTextureCHROMIUM(GLuint sourceId,
+                                     GLint sourceLevel,
+                                     GLenum destTarget,
+                                     GLuint destId,
+                                     GLint destLevel,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLint x,
+                                     GLint y,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLboolean unpackFlipY,
+                                     GLboolean unpackPremultiplyAlpha,
+                                     GLboolean unpackUnmultiplyAlpha)
+{
+    // Zero sized copies are valid but no-ops
+    if (width == 0 || height == 0)
+    {
+        return;
+    }
+
+    syncStateForTexImage();
+
+    gl::Texture *sourceTexture = getTexture(sourceId);
+    gl::Texture *destTexture   = getTexture(destId);
+    Offset offset(xoffset, yoffset, 0);
+    Rectangle area(x, y, width, height);
+    handleError(destTexture->copySubTexture(
+        this, destTarget, destLevel, offset, sourceLevel, area, unpackFlipY == GL_TRUE,
+        unpackPremultiplyAlpha == GL_TRUE, unpackUnmultiplyAlpha == GL_TRUE, sourceTexture));
+}
+
+void Context::compressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId)
+{
+    syncStateForTexImage();
+
+    gl::Texture *sourceTexture = getTexture(sourceId);
+    gl::Texture *destTexture   = getTexture(destId);
+    handleError(destTexture->copyCompressedTexture(this, sourceTexture));
+}
+
+void Context::getBufferPointerv(GLenum target, GLenum pname, void **params)
+{
+    Buffer *buffer = mGLState.getTargetBuffer(target);
+    ASSERT(buffer);
+
+    QueryBufferPointerv(buffer, pname, params);
+}
+
+void *Context::mapBuffer(GLenum target, GLenum access)
+{
+    Buffer *buffer = mGLState.getTargetBuffer(target);
+    ASSERT(buffer);
+
+    Error error = buffer->map(this, access);
+    if (error.isError())
+    {
+        handleError(error);
+        return nullptr;
+    }
+
+    return buffer->getMapPointer();
+}
+
+GLboolean Context::unmapBuffer(GLenum target)
+{
+    Buffer *buffer = mGLState.getTargetBuffer(target);
+    ASSERT(buffer);
+
+    GLboolean result;
+    Error error = buffer->unmap(this, &result);
+    if (error.isError())
+    {
+        handleError(error);
+        return GL_FALSE;
+    }
+
+    return result;
+}
+
+void *Context::mapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+{
+    Buffer *buffer = mGLState.getTargetBuffer(target);
+    ASSERT(buffer);
+
+    Error error = buffer->mapRange(this, offset, length, access);
+    if (error.isError())
+    {
+        handleError(error);
+        return nullptr;
+    }
+
+    return buffer->getMapPointer();
+}
+
+void Context::flushMappedBufferRange(GLenum /*target*/, GLintptr /*offset*/, GLsizeiptr /*length*/)
+{
+    // We do not currently support a non-trivial implementation of FlushMappedBufferRange
+}
+
+void Context::syncStateForReadPixels()
+{
+    syncRendererState(mReadPixelsDirtyBits, mReadPixelsDirtyObjects);
+}
+
+void Context::syncStateForTexImage()
+{
+    syncRendererState(mTexImageDirtyBits, mTexImageDirtyObjects);
+}
+
+void Context::syncStateForClear()
+{
+    syncRendererState(mClearDirtyBits, mClearDirtyObjects);
+}
+
+void Context::syncStateForBlit()
+{
+    syncRendererState(mBlitDirtyBits, mBlitDirtyObjects);
+}
+
+void Context::activeTexture(GLenum texture)
+{
+    mGLState.setActiveSampler(texture - GL_TEXTURE0);
+}
+
+void Context::blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+    mGLState.setBlendColor(clamp01(red), clamp01(green), clamp01(blue), clamp01(alpha));
+}
+
+void Context::blendEquation(GLenum mode)
+{
+    mGLState.setBlendEquation(mode, mode);
+}
+
+void Context::blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+    mGLState.setBlendEquation(modeRGB, modeAlpha);
+}
+
+void Context::blendFunc(GLenum sfactor, GLenum dfactor)
+{
+    mGLState.setBlendFactors(sfactor, dfactor, sfactor, dfactor);
+}
+
+void Context::blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+    mGLState.setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void Context::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+    mGLState.setColorClearValue(red, green, blue, alpha);
+}
+
+void Context::clearDepthf(GLfloat depth)
+{
+    mGLState.setDepthClearValue(depth);
+}
+
+void Context::clearStencil(GLint s)
+{
+    mGLState.setStencilClearValue(s);
+}
+
+void Context::colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+    mGLState.setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
+}
+
+void Context::cullFace(GLenum mode)
+{
+    mGLState.setCullMode(mode);
+}
+
+void Context::depthFunc(GLenum func)
+{
+    mGLState.setDepthFunc(func);
+}
+
+void Context::depthMask(GLboolean flag)
+{
+    mGLState.setDepthMask(flag != GL_FALSE);
+}
+
+void Context::depthRangef(GLfloat zNear, GLfloat zFar)
+{
+    mGLState.setDepthRange(zNear, zFar);
+}
+
+void Context::disable(GLenum cap)
+{
+    mGLState.setEnableFeature(cap, false);
+}
+
+void Context::disableVertexAttribArray(GLuint index)
+{
+    mGLState.setEnableVertexAttribArray(index, false);
+}
+
+void Context::enable(GLenum cap)
+{
+    mGLState.setEnableFeature(cap, true);
+}
+
+void Context::enableVertexAttribArray(GLuint index)
+{
+    mGLState.setEnableVertexAttribArray(index, true);
+}
+
+void Context::frontFace(GLenum mode)
+{
+    mGLState.setFrontFace(mode);
+}
+
+void Context::hint(GLenum target, GLenum mode)
+{
+    switch (target)
+    {
+        case GL_GENERATE_MIPMAP_HINT:
+            mGLState.setGenerateMipmapHint(mode);
+            break;
+
+        case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+            mGLState.setFragmentShaderDerivativeHint(mode);
+            break;
+
+        default:
+            UNREACHABLE();
+            return;
+    }
+}
+
+void Context::lineWidth(GLfloat width)
+{
+    mGLState.setLineWidth(width);
+}
+
+void Context::pixelStorei(GLenum pname, GLint param)
+{
+    switch (pname)
+    {
+        case GL_UNPACK_ALIGNMENT:
+            mGLState.setUnpackAlignment(param);
+            break;
+
+        case GL_PACK_ALIGNMENT:
+            mGLState.setPackAlignment(param);
+            break;
+
+        case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+            mGLState.setPackReverseRowOrder(param != 0);
+            break;
+
+        case GL_UNPACK_ROW_LENGTH:
+            ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimage);
+            mGLState.setUnpackRowLength(param);
+            break;
+
+        case GL_UNPACK_IMAGE_HEIGHT:
+            ASSERT(getClientMajorVersion() >= 3);
+            mGLState.setUnpackImageHeight(param);
+            break;
+
+        case GL_UNPACK_SKIP_IMAGES:
+            ASSERT(getClientMajorVersion() >= 3);
+            mGLState.setUnpackSkipImages(param);
+            break;
+
+        case GL_UNPACK_SKIP_ROWS:
+            ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimage);
+            mGLState.setUnpackSkipRows(param);
+            break;
+
+        case GL_UNPACK_SKIP_PIXELS:
+            ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimage);
+            mGLState.setUnpackSkipPixels(param);
+            break;
+
+        case GL_PACK_ROW_LENGTH:
+            ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimage);
+            mGLState.setPackRowLength(param);
+            break;
+
+        case GL_PACK_SKIP_ROWS:
+            ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimage);
+            mGLState.setPackSkipRows(param);
+            break;
+
+        case GL_PACK_SKIP_PIXELS:
+            ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimage);
+            mGLState.setPackSkipPixels(param);
+            break;
+
+        default:
+            UNREACHABLE();
+            return;
+    }
+}
+
+void Context::polygonOffset(GLfloat factor, GLfloat units)
+{
+    mGLState.setPolygonOffsetParams(factor, units);
+}
+
+void Context::sampleCoverage(GLfloat value, GLboolean invert)
+{
+    mGLState.setSampleCoverageParams(clamp01(value), invert == GL_TRUE);
+}
+
+void Context::scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    mGLState.setScissorParams(x, y, width, height);
+}
+
+void Context::stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+    if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+    {
+        mGLState.setStencilParams(func, ref, mask);
+    }
+
+    if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+    {
+        mGLState.setStencilBackParams(func, ref, mask);
+    }
+}
+
+void Context::stencilMaskSeparate(GLenum face, GLuint mask)
+{
+    if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+    {
+        mGLState.setStencilWritemask(mask);
+    }
+
+    if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+    {
+        mGLState.setStencilBackWritemask(mask);
+    }
+}
+
+void Context::stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+    if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+    {
+        mGLState.setStencilOperations(fail, zfail, zpass);
+    }
+
+    if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+    {
+        mGLState.setStencilBackOperations(fail, zfail, zpass);
+    }
+}
+
+void Context::vertexAttrib1f(GLuint index, GLfloat x)
+{
+    GLfloat vals[4] = {x, 0, 0, 1};
+    mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib1fv(GLuint index, const GLfloat *values)
+{
+    GLfloat vals[4] = {values[0], 0, 0, 1};
+    mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+    GLfloat vals[4] = {x, y, 0, 1};
+    mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib2fv(GLuint index, const GLfloat *values)
+{
+    GLfloat vals[4] = {values[0], values[1], 0, 1};
+    mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+    GLfloat vals[4] = {x, y, z, 1};
+    mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib3fv(GLuint index, const GLfloat *values)
+{
+    GLfloat vals[4] = {values[0], values[1], values[2], 1};
+    mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    GLfloat vals[4] = {x, y, z, w};
+    mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib4fv(GLuint index, const GLfloat *values)
+{
+    mGLState.setVertexAttribf(index, values);
+}
+
+void Context::vertexAttribPointer(GLuint index,
+                                  GLint size,
+                                  GLenum type,
+                                  GLboolean normalized,
+                                  GLsizei stride,
+                                  const void *ptr)
+{
+    mGLState.setVertexAttribState(index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size, type,
+                                  normalized == GL_TRUE, false, stride, ptr);
+}
+
+void Context::vertexAttribFormat(GLuint attribIndex,
+                                 GLint size,
+                                 GLenum type,
+                                 GLboolean normalized,
+                                 GLuint relativeOffset)
+{
+    mGLState.setVertexAttribFormat(attribIndex, size, type, normalized == GL_TRUE, false,
+                                   relativeOffset);
+}
+
+void Context::vertexAttribIFormat(GLuint attribIndex,
+                                  GLint size,
+                                  GLenum type,
+                                  GLuint relativeOffset)
+{
+    mGLState.setVertexAttribFormat(attribIndex, size, type, false, true, relativeOffset);
+}
+
+void Context::vertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
+{
+    mGLState.setVertexAttribBinding(attribIndex, bindingIndex);
+}
+
+void Context::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+{
+    mGLState.setVertexBindingDivisor(bindingIndex, divisor);
+}
+
+void Context::viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    mGLState.setViewportParams(x, y, width, height);
+}
+
+void Context::vertexAttribIPointer(GLuint index,
+                                   GLint size,
+                                   GLenum type,
+                                   GLsizei stride,
+                                   const void *pointer)
+{
+    mGLState.setVertexAttribState(index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size, type,
+                                  false, true, stride, pointer);
+}
+
+void Context::vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+    GLint vals[4] = {x, y, z, w};
+    mGLState.setVertexAttribi(index, vals);
+}
+
+void Context::vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+    GLuint vals[4] = {x, y, z, w};
+    mGLState.setVertexAttribu(index, vals);
+}
+
+void Context::vertexAttribI4iv(GLuint index, const GLint *v)
+{
+    mGLState.setVertexAttribi(index, v);
+}
+
+void Context::vertexAttribI4uiv(GLuint index, const GLuint *v)
+{
+    mGLState.setVertexAttribu(index, v);
+}
+
+void Context::getVertexAttribiv(GLuint index, GLenum pname, GLint *params)
+{
+    const VertexAttribCurrentValueData &currentValues =
+        getGLState().getVertexAttribCurrentValue(index);
+    const VertexArray *vao = getGLState().getVertexArray();
+    QueryVertexAttribiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+                        currentValues, pname, params);
+}
+
+void Context::getVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
+{
+    const VertexAttribCurrentValueData &currentValues =
+        getGLState().getVertexAttribCurrentValue(index);
+    const VertexArray *vao = getGLState().getVertexArray();
+    QueryVertexAttribfv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+                        currentValues, pname, params);
+}
+
+void Context::getVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
+{
+    const VertexAttribCurrentValueData &currentValues =
+        getGLState().getVertexAttribCurrentValue(index);
+    const VertexArray *vao = getGLState().getVertexArray();
+    QueryVertexAttribIiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+                         currentValues, pname, params);
+}
+
+void Context::getVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
+{
+    const VertexAttribCurrentValueData &currentValues =
+        getGLState().getVertexAttribCurrentValue(index);
+    const VertexArray *vao = getGLState().getVertexArray();
+    QueryVertexAttribIuiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+                          currentValues, pname, params);
+}
+
+void Context::getVertexAttribPointerv(GLuint index, GLenum pname, void **pointer)
+{
+    const VertexAttribute &attrib = getGLState().getVertexArray()->getVertexAttribute(index);
+    QueryVertexAttribPointerv(attrib, pname, pointer);
+}
+
+void Context::debugMessageControl(GLenum source,
+                                  GLenum type,
+                                  GLenum severity,
+                                  GLsizei count,
+                                  const GLuint *ids,
+                                  GLboolean enabled)
+{
+    std::vector<GLuint> idVector(ids, ids + count);
+    mGLState.getDebug().setMessageControl(source, type, severity, std::move(idVector),
+                                          (enabled != GL_FALSE));
+}
+
+void Context::debugMessageInsert(GLenum source,
+                                 GLenum type,
+                                 GLuint id,
+                                 GLenum severity,
+                                 GLsizei length,
+                                 const GLchar *buf)
+{
+    std::string msg(buf, (length > 0) ? static_cast<size_t>(length) : strlen(buf));
+    mGLState.getDebug().insertMessage(source, type, id, severity, std::move(msg));
+}
+
+void Context::debugMessageCallback(GLDEBUGPROCKHR callback, const void *userParam)
+{
+    mGLState.getDebug().setCallback(callback, userParam);
+}
+
+GLuint Context::getDebugMessageLog(GLuint count,
+                                   GLsizei bufSize,
+                                   GLenum *sources,
+                                   GLenum *types,
+                                   GLuint *ids,
+                                   GLenum *severities,
+                                   GLsizei *lengths,
+                                   GLchar *messageLog)
+{
+    return static_cast<GLuint>(mGLState.getDebug().getMessages(count, bufSize, sources, types, ids,
+                                                               severities, lengths, messageLog));
+}
+
+void Context::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message)
+{
+    std::string msg(message, (length > 0) ? static_cast<size_t>(length) : strlen(message));
+    mGLState.getDebug().pushGroup(source, id, std::move(msg));
+}
+
+void Context::popDebugGroup()
+{
+    mGLState.getDebug().popGroup();
+}
+
+void Context::bufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
+{
+    Buffer *buffer = mGLState.getTargetBuffer(target);
+    ASSERT(buffer);
+    handleError(buffer->bufferData(this, target, data, size, usage));
+}
+
+void Context::bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
+{
+    if (data == nullptr)
+    {
+        return;
+    }
+
+    Buffer *buffer = mGLState.getTargetBuffer(target);
+    ASSERT(buffer);
+    handleError(buffer->bufferSubData(this, target, data, size, offset));
+}
+
+void Context::attachShader(GLuint program, GLuint shader)
+{
+    auto programObject = mState.mShaderPrograms->getProgram(program);
+    auto shaderObject  = mState.mShaderPrograms->getShader(shader);
+    ASSERT(programObject && shaderObject);
+    programObject->attachShader(shaderObject);
+}
+
+const Workarounds &Context::getWorkarounds() const
+{
+    return mWorkarounds;
+}
+
+void Context::copyBufferSubData(GLenum readTarget,
+                                GLenum writeTarget,
+                                GLintptr readOffset,
+                                GLintptr writeOffset,
+                                GLsizeiptr size)
+{
+    // if size is zero, the copy is a successful no-op
+    if (size == 0)
+    {
+        return;
+    }
+
+    // TODO(jmadill): cache these.
+    Buffer *readBuffer  = mGLState.getTargetBuffer(readTarget);
+    Buffer *writeBuffer = mGLState.getTargetBuffer(writeTarget);
+
+    handleError(writeBuffer->copyBufferSubData(this, readBuffer, readOffset, writeOffset, size));
+}
+
+void Context::bindAttribLocation(GLuint program, GLuint index, const GLchar *name)
+{
+    Program *programObject = getProgram(program);
+    // TODO(jmadill): Re-use this from the validation if possible.
+    ASSERT(programObject);
+    programObject->bindAttributeLocation(index, name);
+}
+
+void Context::bindBuffer(GLenum target, GLuint buffer)
+{
+    switch (target)
+    {
+        case GL_ARRAY_BUFFER:
+            bindArrayBuffer(buffer);
+            break;
+        case GL_ELEMENT_ARRAY_BUFFER:
+            bindElementArrayBuffer(buffer);
+            break;
+        case GL_COPY_READ_BUFFER:
+            bindCopyReadBuffer(buffer);
+            break;
+        case GL_COPY_WRITE_BUFFER:
+            bindCopyWriteBuffer(buffer);
+            break;
+        case GL_PIXEL_PACK_BUFFER:
+            bindPixelPackBuffer(buffer);
+            break;
+        case GL_PIXEL_UNPACK_BUFFER:
+            bindPixelUnpackBuffer(buffer);
+            break;
+        case GL_UNIFORM_BUFFER:
+            bindGenericUniformBuffer(buffer);
+            break;
+        case GL_TRANSFORM_FEEDBACK_BUFFER:
+            bindGenericTransformFeedbackBuffer(buffer);
+            break;
+        case GL_ATOMIC_COUNTER_BUFFER:
+            bindGenericAtomicCounterBuffer(buffer);
+            break;
+        case GL_SHADER_STORAGE_BUFFER:
+            bindGenericShaderStorageBuffer(buffer);
+            break;
+        case GL_DRAW_INDIRECT_BUFFER:
+            bindDrawIndirectBuffer(buffer);
+            break;
+        case GL_DISPATCH_INDIRECT_BUFFER:
+            if (buffer != 0)
+            {
+                // Binding buffers to this binding point is not implemented yet.
+                UNIMPLEMENTED();
+            }
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void Context::bindBufferBase(GLenum target, GLuint index, GLuint buffer)
+{
+    bindBufferRange(target, index, buffer, 0, 0);
+}
+
+void Context::bindBufferRange(GLenum target,
+                              GLuint index,
+                              GLuint buffer,
+                              GLintptr offset,
+                              GLsizeiptr size)
+{
+    switch (target)
+    {
+        case GL_TRANSFORM_FEEDBACK_BUFFER:
+            bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
+            bindGenericTransformFeedbackBuffer(buffer);
+            break;
+        case GL_UNIFORM_BUFFER:
+            bindIndexedUniformBuffer(buffer, index, offset, size);
+            bindGenericUniformBuffer(buffer);
+            break;
+        case GL_ATOMIC_COUNTER_BUFFER:
+            bindIndexedAtomicCounterBuffer(buffer, index, offset, size);
+            bindGenericAtomicCounterBuffer(buffer);
+            break;
+        case GL_SHADER_STORAGE_BUFFER:
+            bindIndexedShaderStorageBuffer(buffer, index, offset, size);
+            bindGenericShaderStorageBuffer(buffer);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void Context::bindFramebuffer(GLenum target, GLuint framebuffer)
+{
+    if (target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
+    {
+        bindReadFramebuffer(framebuffer);
+    }
+
+    if (target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
+    {
+        bindDrawFramebuffer(framebuffer);
+    }
+}
+
+void Context::bindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+    ASSERT(target == GL_RENDERBUFFER);
+    Renderbuffer *object =
+        mState.mRenderbuffers->checkRenderbufferAllocation(mImplementation.get(), renderbuffer);
+    mGLState.setRenderbufferBinding(object);
+}
+
+void Context::texStorage2DMultisample(GLenum target,
+                                      GLsizei samples,
+                                      GLenum internalformat,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLboolean fixedsamplelocations)
+{
+    Extents size(width, height, 1);
+    Texture *texture = getTargetTexture(target);
+    handleError(texture->setStorageMultisample(this, target, samples, internalformat, size,
+                                               fixedsamplelocations));
+}
+
+void Context::getMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
+{
+    mGLState.syncDirtyObject(this, GL_READ_FRAMEBUFFER);
+    const Framebuffer *framebuffer = mGLState.getReadFramebuffer();
+
+    switch (pname)
+    {
+        case GL_SAMPLE_POSITION:
+            handleError(framebuffer->getSamplePosition(index, val));
+            break;
+        default:
+            UNREACHABLE();
+    }
+}
+
+void Context::renderbufferStorage(GLenum target,
+                                  GLenum internalformat,
+                                  GLsizei width,
+                                  GLsizei height)
+{
+    // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+    GLenum convertedInternalFormat = getConvertedRenderbufferFormat(internalformat);
+
+    Renderbuffer *renderbuffer = mGLState.getCurrentRenderbuffer();
+    handleError(renderbuffer->setStorage(convertedInternalFormat, width, height));
+}
+
+void Context::renderbufferStorageMultisample(GLenum target,
+                                             GLsizei samples,
+                                             GLenum internalformat,
+                                             GLsizei width,
+                                             GLsizei height)
+{
+    // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+    GLenum convertedInternalFormat = getConvertedRenderbufferFormat(internalformat);
+
+    Renderbuffer *renderbuffer = mGLState.getCurrentRenderbuffer();
+    handleError(
+        renderbuffer->setStorageMultisample(samples, convertedInternalFormat, width, height));
+}
+
+void Context::getSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+{
+    const FenceSync *syncObject = getFenceSync(sync);
+    handleError(QuerySynciv(syncObject, pname, bufSize, length, values));
+}
+
+void Context::getFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    QueryFramebufferParameteriv(framebuffer, pname, params);
+}
+
+void Context::setFramebufferParameteri(GLenum target, GLenum pname, GLint param)
+{
+    Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    SetFramebufferParameteri(framebuffer, pname, param);
+}
+
+Error Context::getScratchBuffer(size_t requestedSize, angle::MemoryBuffer **scratchBufferOut) const
+{
+    if (!mScratchBuffer.get(requestedSize, scratchBufferOut))
+    {
+        return gl::OutOfMemory() << "Failed to allocate internal buffer.";
+    }
+    return gl::NoError();
+}
+
+void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+    if (numGroupsX == 0u || numGroupsY == 0u || numGroupsZ == 0u)
+    {
+        return;
+    }
+
+    mImplementation->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
+}
+
+GLenum Context::checkFramebufferStatus(GLenum target)
+{
+    Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    return framebuffer->checkStatus(this);
+}
+
+void Context::compileShader(GLuint shader)
+{
+    Shader *shaderObject = GetValidShader(this, shader);
+    if (!shaderObject)
+    {
+        return;
+    }
+    shaderObject->compile(this);
+}
+
+void Context::deleteBuffers(GLsizei n, const GLuint *buffers)
+{
+    for (int i = 0; i < n; i++)
+    {
+        deleteBuffer(buffers[i]);
+    }
+}
+
+void Context::deleteFramebuffers(GLsizei n, const GLuint *framebuffers)
+{
+    for (int i = 0; i < n; i++)
+    {
+        if (framebuffers[i] != 0)
+        {
+            deleteFramebuffer(framebuffers[i]);
+        }
+    }
+}
+
+void Context::deleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
+{
+    for (int i = 0; i < n; i++)
+    {
+        deleteRenderbuffer(renderbuffers[i]);
+    }
+}
+
+void Context::deleteTextures(GLsizei n, const GLuint *textures)
+{
+    for (int i = 0; i < n; i++)
+    {
+        if (textures[i] != 0)
+        {
+            deleteTexture(textures[i]);
+        }
+    }
+}
+
+void Context::detachShader(GLuint program, GLuint shader)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+
+    Shader *shaderObject = getShader(shader);
+    ASSERT(shaderObject);
+
+    programObject->detachShader(this, shaderObject);
+}
+
+void Context::genBuffers(GLsizei n, GLuint *buffers)
+{
+    for (int i = 0; i < n; i++)
+    {
+        buffers[i] = createBuffer();
+    }
+}
+
+void Context::genFramebuffers(GLsizei n, GLuint *framebuffers)
+{
+    for (int i = 0; i < n; i++)
+    {
+        framebuffers[i] = createFramebuffer();
+    }
+}
+
+void Context::genRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+    for (int i = 0; i < n; i++)
+    {
+        renderbuffers[i] = createRenderbuffer();
+    }
+}
+
+void Context::genTextures(GLsizei n, GLuint *textures)
+{
+    for (int i = 0; i < n; i++)
+    {
+        textures[i] = createTexture();
+    }
+}
+
+void Context::getActiveAttrib(GLuint program,
+                              GLuint index,
+                              GLsizei bufsize,
+                              GLsizei *length,
+                              GLint *size,
+                              GLenum *type,
+                              GLchar *name)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    programObject->getActiveAttribute(index, bufsize, length, size, type, name);
+}
+
+void Context::getActiveUniform(GLuint program,
+                               GLuint index,
+                               GLsizei bufsize,
+                               GLsizei *length,
+                               GLint *size,
+                               GLenum *type,
+                               GLchar *name)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    programObject->getActiveUniform(index, bufsize, length, size, type, name);
+}
+
+void Context::getAttachedShaders(GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    programObject->getAttachedShaders(maxcount, count, shaders);
+}
+
+GLint Context::getAttribLocation(GLuint program, const GLchar *name)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    return programObject->getAttributeLocation(name);
+}
+
+void Context::getBooleanv(GLenum pname, GLboolean *params)
+{
+    GLenum nativeType;
+    unsigned int numParams = 0;
+    getQueryParameterInfo(pname, &nativeType, &numParams);
+
+    if (nativeType == GL_BOOL)
+    {
+        getBooleanvImpl(pname, params);
+    }
+    else
+    {
+        CastStateValues(this, nativeType, pname, numParams, params);
+    }
+}
+
+void Context::getFloatv(GLenum pname, GLfloat *params)
+{
+    GLenum nativeType;
+    unsigned int numParams = 0;
+    getQueryParameterInfo(pname, &nativeType, &numParams);
+
+    if (nativeType == GL_FLOAT)
+    {
+        getFloatvImpl(pname, params);
+    }
+    else
+    {
+        CastStateValues(this, nativeType, pname, numParams, params);
+    }
+}
+
+void Context::getIntegerv(GLenum pname, GLint *params)
+{
+    GLenum nativeType;
+    unsigned int numParams = 0;
+    getQueryParameterInfo(pname, &nativeType, &numParams);
+
+    if (nativeType == GL_INT)
+    {
+        getIntegervImpl(pname, params);
+    }
+    else
+    {
+        CastStateValues(this, nativeType, pname, numParams, params);
+    }
+}
+
+void Context::getProgramiv(GLuint program, GLenum pname, GLint *params)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    QueryProgramiv(programObject, pname, params);
+}
+
+void Context::getProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    programObject->getInfoLog(bufsize, length, infolog);
+}
+
+void Context::getShaderiv(GLuint shader, GLenum pname, GLint *params)
+{
+    Shader *shaderObject = getShader(shader);
+    ASSERT(shaderObject);
+    QueryShaderiv(shaderObject, pname, params);
+}
+
+void Context::getShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *infolog)
+{
+    Shader *shaderObject = getShader(shader);
+    ASSERT(shaderObject);
+    shaderObject->getInfoLog(bufsize, length, infolog);
+}
+
+void Context::getShaderPrecisionFormat(GLenum shadertype,
+                                       GLenum precisiontype,
+                                       GLint *range,
+                                       GLint *precision)
+{
+    // TODO(jmadill): Compute shaders.
+
+    switch (shadertype)
+    {
+        case GL_VERTEX_SHADER:
+            switch (precisiontype)
+            {
+                case GL_LOW_FLOAT:
+                    mCaps.vertexLowpFloat.get(range, precision);
+                    break;
+                case GL_MEDIUM_FLOAT:
+                    mCaps.vertexMediumpFloat.get(range, precision);
+                    break;
+                case GL_HIGH_FLOAT:
+                    mCaps.vertexHighpFloat.get(range, precision);
+                    break;
+
+                case GL_LOW_INT:
+                    mCaps.vertexLowpInt.get(range, precision);
+                    break;
+                case GL_MEDIUM_INT:
+                    mCaps.vertexMediumpInt.get(range, precision);
+                    break;
+                case GL_HIGH_INT:
+                    mCaps.vertexHighpInt.get(range, precision);
+                    break;
+
+                default:
+                    UNREACHABLE();
+                    return;
+            }
+            break;
+
+        case GL_FRAGMENT_SHADER:
+            switch (precisiontype)
+            {
+                case GL_LOW_FLOAT:
+                    mCaps.fragmentLowpFloat.get(range, precision);
+                    break;
+                case GL_MEDIUM_FLOAT:
+                    mCaps.fragmentMediumpFloat.get(range, precision);
+                    break;
+                case GL_HIGH_FLOAT:
+                    mCaps.fragmentHighpFloat.get(range, precision);
+                    break;
+
+                case GL_LOW_INT:
+                    mCaps.fragmentLowpInt.get(range, precision);
+                    break;
+                case GL_MEDIUM_INT:
+                    mCaps.fragmentMediumpInt.get(range, precision);
+                    break;
+                case GL_HIGH_INT:
+                    mCaps.fragmentHighpInt.get(range, precision);
+                    break;
+
+                default:
+                    UNREACHABLE();
+                    return;
+            }
+            break;
+
+        default:
+            UNREACHABLE();
+            return;
+    }
+}
+
+void Context::getShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
+{
+    Shader *shaderObject = getShader(shader);
+    ASSERT(shaderObject);
+    shaderObject->getSource(bufsize, length, source);
+}
+
+void Context::getUniformfv(GLuint program, GLint location, GLfloat *params)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    programObject->getUniformfv(location, params);
+}
+
+void Context::getUniformiv(GLuint program, GLint location, GLint *params)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    programObject->getUniformiv(location, params);
+}
+
+GLint Context::getUniformLocation(GLuint program, const GLchar *name)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    return programObject->getUniformLocation(name);
+}
+
+GLboolean Context::isBuffer(GLuint buffer)
+{
+    if (buffer == 0)
+    {
+        return GL_FALSE;
+    }
+
+    return (getBuffer(buffer) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isEnabled(GLenum cap)
+{
+    return mGLState.getEnableFeature(cap);
+}
+
+GLboolean Context::isFramebuffer(GLuint framebuffer)
+{
+    if (framebuffer == 0)
+    {
+        return GL_FALSE;
+    }
+
+    return (getFramebuffer(framebuffer) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isProgram(GLuint program)
+{
+    if (program == 0)
+    {
+        return GL_FALSE;
+    }
+
+    return (getProgram(program) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isRenderbuffer(GLuint renderbuffer)
+{
+    if (renderbuffer == 0)
+    {
+        return GL_FALSE;
+    }
+
+    return (getRenderbuffer(renderbuffer) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isShader(GLuint shader)
+{
+    if (shader == 0)
+    {
+        return GL_FALSE;
+    }
+
+    return (getShader(shader) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isTexture(GLuint texture)
+{
+    if (texture == 0)
+    {
+        return GL_FALSE;
+    }
+
+    return (getTexture(texture) ? GL_TRUE : GL_FALSE);
+}
+
+void Context::linkProgram(GLuint program)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    handleError(programObject->link(this));
+}
+
+void Context::releaseShaderCompiler()
+{
+    handleError(mCompiler->release());
+}
+
+void Context::shaderBinary(GLsizei n,
+                           const GLuint *shaders,
+                           GLenum binaryformat,
+                           const void *binary,
+                           GLsizei length)
+{
+    // No binary shader formats are supported.
+    UNIMPLEMENTED();
+}
+
+void Context::shaderSource(GLuint shader,
+                           GLsizei count,
+                           const GLchar *const *string,
+                           const GLint *length)
+{
+    Shader *shaderObject = getShader(shader);
+    ASSERT(shaderObject);
+    shaderObject->setSource(count, string, length);
+}
+
+void Context::stencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+    stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
+}
+
+void Context::stencilMask(GLuint mask)
+{
+    stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
+}
+
+void Context::stencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+    stencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
+}
+
+void Context::uniform1f(GLint location, GLfloat x)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform1fv(location, 1, &x);
+}
+
+void Context::uniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform1fv(location, count, v);
+}
+
+void Context::uniform1i(GLint location, GLint x)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform1iv(location, 1, &x);
+}
+
+void Context::uniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform1iv(location, count, v);
+}
+
+void Context::uniform2f(GLint location, GLfloat x, GLfloat y)
+{
+    GLfloat xy[2]    = {x, y};
+    Program *program = mGLState.getProgram();
+    program->setUniform2fv(location, 1, xy);
+}
+
+void Context::uniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform2fv(location, count, v);
+}
+
+void Context::uniform2i(GLint location, GLint x, GLint y)
+{
+    GLint xy[2]      = {x, y};
+    Program *program = mGLState.getProgram();
+    program->setUniform2iv(location, 1, xy);
+}
+
+void Context::uniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform2iv(location, count, v);
+}
+
+void Context::uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+    GLfloat xyz[3]   = {x, y, z};
+    Program *program = mGLState.getProgram();
+    program->setUniform3fv(location, 1, xyz);
+}
+
+void Context::uniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform3fv(location, count, v);
+}
+
+void Context::uniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+    GLint xyz[3]     = {x, y, z};
+    Program *program = mGLState.getProgram();
+    program->setUniform3iv(location, 1, xyz);
+}
+
+void Context::uniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform3iv(location, count, v);
+}
+
+void Context::uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    GLfloat xyzw[4]  = {x, y, z, w};
+    Program *program = mGLState.getProgram();
+    program->setUniform4fv(location, 1, xyzw);
+}
+
+void Context::uniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform4fv(location, count, v);
+}
+
+void Context::uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+    GLint xyzw[4]    = {x, y, z, w};
+    Program *program = mGLState.getProgram();
+    program->setUniform4iv(location, 1, xyzw);
+}
+
+void Context::uniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniform4iv(location, count, v);
+}
+
+void Context::uniformMatrix2fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniformMatrix2fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix3fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniformMatrix3fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix4fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value)
+{
+    Program *program = mGLState.getProgram();
+    program->setUniformMatrix4fv(location, count, transpose, value);
+}
+
+void Context::validateProgram(GLuint program)
+{
+    Program *programObject = getProgram(program);
+    ASSERT(programObject);
+    programObject->validate(mCaps);
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/Context.h b/src/third_party/angle/src/libANGLE/Context.h
new file mode 100644
index 0000000..8018b25
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Context.h
@@ -0,0 +1,901 @@
+//
+// 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.
+//
+
+// Context.h: Defines the gl::Context class, managing all GL state and performing
+// rendering operations. It is the GLES2 specific implementation of EGLContext.
+
+#ifndef LIBANGLE_CONTEXT_H_
+#define LIBANGLE_CONTEXT_H_
+
+#include <set>
+#include <string>
+
+#include "angle_gl.h"
+#include "common/MemoryBuffer.h"
+#include "common/angleutils.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/HandleAllocator.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/Workarounds.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class ContextImpl;
+class EGLImplFactory;
+}
+
+namespace egl
+{
+class AttributeMap;
+class Surface;
+struct Config;
+}
+
+namespace gl
+{
+class Compiler;
+class Shader;
+class Program;
+class Texture;
+class Framebuffer;
+class Renderbuffer;
+class FenceNV;
+class FenceSync;
+class Query;
+class Buffer;
+struct VertexAttribute;
+class VertexArray;
+class Sampler;
+class TransformFeedback;
+
+class Context final : public ValidationContext
+{
+  public:
+    Context(rx::EGLImplFactory *implFactory,
+            const egl::Config *config,
+            const Context *shareContext,
+            TextureManager *shareTextures,
+            const egl::AttributeMap &attribs,
+            const egl::DisplayExtensions &displayExtensions);
+
+    void destroy(egl::Display *display);
+    ~Context() override;
+
+    void makeCurrent(egl::Display *display, egl::Surface *surface);
+    void releaseSurface(egl::Display *display);
+
+    // These create  and destroy methods are merely pass-throughs to
+    // ResourceManager, which owns these object types
+    GLuint createBuffer();
+    GLuint createShader(GLenum type);
+    GLuint createProgram();
+    GLuint createTexture();
+    GLuint createRenderbuffer();
+    GLuint createSampler();
+    GLuint createTransformFeedback();
+    GLsync createFenceSync();
+    GLuint createPaths(GLsizei range);
+
+    void deleteBuffer(GLuint buffer);
+    void deleteShader(GLuint shader);
+    void deleteProgram(GLuint program);
+    void deleteTexture(GLuint texture);
+    void deleteRenderbuffer(GLuint renderbuffer);
+    void deleteSampler(GLuint sampler);
+    void deleteTransformFeedback(GLuint transformFeedback);
+    void deleteFenceSync(GLsync fenceSync);
+    void deletePaths(GLuint first, GLsizei range);
+
+    // CHROMIUM_path_rendering
+    bool hasPathData(GLuint path) const;
+    bool hasPath(GLuint path) const;
+    void setPathCommands(GLuint path,
+                         GLsizei numCommands,
+                         const GLubyte *commands,
+                         GLsizei numCoords,
+                         GLenum coordType,
+                         const void *coords);
+    void setPathParameterf(GLuint path, GLenum pname, GLfloat value);
+    void getPathParameterfv(GLuint path, GLenum pname, GLfloat *value) const;
+    void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
+
+    // Framebuffers are owned by the Context, so these methods do not pass through
+    GLuint createFramebuffer();
+    void deleteFramebuffer(GLuint framebuffer);
+
+    // NV Fences are owned by the Context.
+    GLuint createFenceNV();
+    void deleteFenceNV(GLuint fence);
+
+    // Queries are owned by the Context;
+    GLuint createQuery();
+    void deleteQuery(GLuint query);
+
+    // Vertex arrays are owned by the Context
+    GLuint createVertexArray();
+    void deleteVertexArray(GLuint vertexArray);
+
+    void bindArrayBuffer(GLuint bufferHandle);
+    void bindElementArrayBuffer(GLuint bufferHandle);
+    void bindTexture(GLenum target, GLuint handle);
+    void bindReadFramebuffer(GLuint framebufferHandle);
+    void bindDrawFramebuffer(GLuint framebufferHandle);
+    void bindVertexArray(GLuint vertexArrayHandle);
+    void bindVertexBuffer(GLuint bindingIndex,
+                          GLuint bufferHandle,
+                          GLintptr offset,
+                          GLsizei stride);
+    void bindSampler(GLuint textureUnit, GLuint samplerHandle);
+    void bindGenericUniformBuffer(GLuint bufferHandle);
+    void bindIndexedUniformBuffer(GLuint bufferHandle,
+                                  GLuint index,
+                                  GLintptr offset,
+                                  GLsizeiptr size);
+    void bindGenericTransformFeedbackBuffer(GLuint bufferHandle);
+    void bindIndexedTransformFeedbackBuffer(GLuint bufferHandle,
+                                            GLuint index,
+                                            GLintptr offset,
+                                            GLsizeiptr size);
+    void bindGenericAtomicCounterBuffer(GLuint bufferHandle);
+    void bindIndexedAtomicCounterBuffer(GLuint bufferHandle,
+                                        GLuint index,
+                                        GLintptr offset,
+                                        GLsizeiptr size);
+    void bindGenericShaderStorageBuffer(GLuint bufferHandle);
+    void bindIndexedShaderStorageBuffer(GLuint bufferHandle,
+                                        GLuint index,
+                                        GLintptr offset,
+                                        GLsizeiptr size);
+    void bindCopyReadBuffer(GLuint bufferHandle);
+    void bindCopyWriteBuffer(GLuint bufferHandle);
+    void bindPixelPackBuffer(GLuint bufferHandle);
+    void bindPixelUnpackBuffer(GLuint bufferHandle);
+    void useProgram(GLuint program);
+    void bindTransformFeedback(GLuint transformFeedbackHandle);
+    void bindDrawIndirectBuffer(GLuint bufferHandle);
+
+    Error beginQuery(GLenum target, GLuint query);
+    Error endQuery(GLenum target);
+    Error queryCounter(GLuint id, GLenum target);
+    void getQueryiv(GLenum target, GLenum pname, GLint *params);
+    void getQueryObjectiv(GLuint id, GLenum pname, GLint *params);
+    void getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
+    void getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params);
+    void getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params);
+
+    void setVertexAttribDivisor(GLuint index, GLuint divisor);
+    void setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor);
+
+    void getBufferParameteriv(GLenum target, GLenum pname, GLint *params);
+    void getFramebufferAttachmentParameteriv(GLenum target,
+                                             GLenum attachment,
+                                             GLenum pname,
+                                             GLint *params);
+    void getRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params);
+
+    void getTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
+    void getTexParameteriv(GLenum target, GLenum pname, GLint *params);
+    void texParameterf(GLenum target, GLenum pname, GLfloat param);
+    void texParameterfv(GLenum target, GLenum pname, const GLfloat *params);
+    void texParameteri(GLenum target, GLenum pname, GLint param);
+    void texParameteriv(GLenum target, GLenum pname, const GLint *params);
+
+    void samplerParameteri(GLuint sampler, GLenum pname, GLint param);
+    void samplerParameteriv(GLuint sampler, GLenum pname, const GLint *param);
+    void samplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
+    void samplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param);
+
+    void getSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params);
+    void getSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params);
+
+    void programParameteri(GLuint program, GLenum pname, GLint value);
+
+    GLuint getProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name);
+    void getProgramResourceName(GLuint program,
+                                GLenum programInterface,
+                                GLuint index,
+                                GLsizei bufSize,
+                                GLsizei *length,
+                                GLchar *name);
+
+    Buffer *getBuffer(GLuint handle) const;
+    FenceNV *getFenceNV(GLuint handle);
+    FenceSync *getFenceSync(GLsync handle) const;
+    Texture *getTexture(GLuint handle) const;
+    Framebuffer *getFramebuffer(GLuint handle) const;
+    Renderbuffer *getRenderbuffer(GLuint handle) const;
+    VertexArray *getVertexArray(GLuint handle) const;
+    Sampler *getSampler(GLuint handle) const;
+    Query *getQuery(GLuint handle, bool create, GLenum type);
+    Query *getQuery(GLuint handle) const;
+    TransformFeedback *getTransformFeedback(GLuint handle) const;
+    void objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+    void objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label);
+    void getObjectLabel(GLenum identifier,
+                        GLuint name,
+                        GLsizei bufSize,
+                        GLsizei *length,
+                        GLchar *label) const;
+    void getObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label) const;
+
+    Texture *getTargetTexture(GLenum target) const;
+    Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
+
+    Compiler *getCompiler() const;
+
+    bool isSampler(GLuint samplerName) const;
+
+    bool isVertexArrayGenerated(GLuint vertexArray);
+    bool isTransformFeedbackGenerated(GLuint vertexArray);
+
+    void getBooleanv(GLenum pname, GLboolean *params);
+    void getBooleanvImpl(GLenum pname, GLboolean *params);
+    void getFloatv(GLenum pname, GLfloat *params);
+    void getFloatvImpl(GLenum pname, GLfloat *params);
+    void getIntegerv(GLenum pname, GLint *params);
+    void getIntegervImpl(GLenum pname, GLint *params);
+    void getInteger64v(GLenum pname, GLint64 *params);
+    void getPointerv(GLenum pname, void **params) const;
+    void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
+    void getIntegeri_v(GLenum target, GLuint index, GLint *data);
+    void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
+
+    void activeTexture(GLenum texture);
+    void blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+    void blendEquation(GLenum mode);
+    void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
+    void blendFunc(GLenum sfactor, GLenum dfactor);
+    void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+    void clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+    void clearDepthf(GLfloat depth);
+    void clearStencil(GLint s);
+    void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+    void cullFace(GLenum mode);
+    void depthFunc(GLenum func);
+    void depthMask(GLboolean flag);
+    void depthRangef(GLfloat zNear, GLfloat zFar);
+    void disable(GLenum cap);
+    void disableVertexAttribArray(GLuint index);
+    void enable(GLenum cap);
+    void enableVertexAttribArray(GLuint index);
+    void frontFace(GLenum mode);
+    void hint(GLenum target, GLenum mode);
+    void lineWidth(GLfloat width);
+    void pixelStorei(GLenum pname, GLint param);
+    void polygonOffset(GLfloat factor, GLfloat units);
+    void sampleCoverage(GLfloat value, GLboolean invert);
+    void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
+    void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
+    void stencilMaskSeparate(GLenum face, GLuint mask);
+    void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+    void vertexAttrib1f(GLuint index, GLfloat x);
+    void vertexAttrib1fv(GLuint index, const GLfloat *values);
+    void vertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
+    void vertexAttrib2fv(GLuint index, const GLfloat *values);
+    void vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+    void vertexAttrib3fv(GLuint index, const GLfloat *values);
+    void vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+    void vertexAttrib4fv(GLuint index, const GLfloat *values);
+    void vertexAttribFormat(GLuint attribIndex,
+                            GLint size,
+                            GLenum type,
+                            GLboolean normalized,
+                            GLuint relativeOffset);
+    void vertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, GLuint relativeOffset);
+    void vertexAttribBinding(GLuint attribIndex, GLuint bindingIndex);
+    void vertexAttribPointer(GLuint index,
+                             GLint size,
+                             GLenum type,
+                             GLboolean normalized,
+                             GLsizei stride,
+                             const void *ptr);
+    void vertexAttribIPointer(GLuint index,
+                              GLint size,
+                              GLenum type,
+                              GLsizei stride,
+                              const void *pointer);
+    void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+
+    void vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
+    void vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+    void vertexAttribI4iv(GLuint index, const GLint *v);
+    void vertexAttribI4uiv(GLuint index, const GLuint *v);
+    void getVertexAttribiv(GLuint index, GLenum pname, GLint *params);
+    void getVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
+    void getVertexAttribIiv(GLuint index, GLenum pname, GLint *params);
+    void getVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params);
+    void getVertexAttribPointerv(GLuint index, GLenum pname, void **pointer);
+
+    void debugMessageControl(GLenum source,
+                             GLenum type,
+                             GLenum severity,
+                             GLsizei count,
+                             const GLuint *ids,
+                             GLboolean enabled);
+    void debugMessageInsert(GLenum source,
+                            GLenum type,
+                            GLuint id,
+                            GLenum severity,
+                            GLsizei length,
+                            const GLchar *buf);
+    void debugMessageCallback(GLDEBUGPROCKHR callback, const void *userParam);
+    GLuint getDebugMessageLog(GLuint count,
+                              GLsizei bufSize,
+                              GLenum *sources,
+                              GLenum *types,
+                              GLuint *ids,
+                              GLenum *severities,
+                              GLsizei *lengths,
+                              GLchar *messageLog);
+    void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message);
+    void popDebugGroup();
+
+    void clear(GLbitfield mask);
+    void clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values);
+    void clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values);
+    void clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values);
+    void clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+
+    void drawArrays(GLenum mode, GLint first, GLsizei count);
+    void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
+
+    void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
+    void drawElementsInstanced(GLenum mode,
+                               GLsizei count,
+                               GLenum type,
+                               const void *indices,
+                               GLsizei instances);
+    void drawRangeElements(GLenum mode,
+                           GLuint start,
+                           GLuint end,
+                           GLsizei count,
+                           GLenum type,
+                           const void *indices);
+    void drawArraysIndirect(GLenum mode, const void *indirect);
+    void drawElementsIndirect(GLenum mode, GLenum type, const void *indirect);
+
+    void blitFramebuffer(GLint srcX0,
+                         GLint srcY0,
+                         GLint srcX1,
+                         GLint srcY1,
+                         GLint dstX0,
+                         GLint dstY0,
+                         GLint dstX1,
+                         GLint dstY1,
+                         GLbitfield mask,
+                         GLenum filter);
+
+    void readPixels(GLint x,
+                    GLint y,
+                    GLsizei width,
+                    GLsizei height,
+                    GLenum format,
+                    GLenum type,
+                    void *pixels);
+
+    void copyTexImage2D(GLenum target,
+                        GLint level,
+                        GLenum internalformat,
+                        GLint x,
+                        GLint y,
+                        GLsizei width,
+                        GLsizei height,
+                        GLint border);
+
+    void copyTexSubImage2D(GLenum target,
+                           GLint level,
+                           GLint xoffset,
+                           GLint yoffset,
+                           GLint x,
+                           GLint y,
+                           GLsizei width,
+                           GLsizei height);
+
+    void copyTexSubImage3D(GLenum target,
+                           GLint level,
+                           GLint xoffset,
+                           GLint yoffset,
+                           GLint zoffset,
+                           GLint x,
+                           GLint y,
+                           GLsizei width,
+                           GLsizei height);
+
+    void framebufferTexture2D(GLenum target,
+                              GLenum attachment,
+                              GLenum textarget,
+                              GLuint texture,
+                              GLint level);
+
+    void framebufferRenderbuffer(GLenum target,
+                                 GLenum attachment,
+                                 GLenum renderbuffertarget,
+                                 GLuint renderbuffer);
+
+    void framebufferTextureLayer(GLenum target,
+                                 GLenum attachment,
+                                 GLuint texture,
+                                 GLint level,
+                                 GLint layer);
+
+    void drawBuffers(GLsizei n, const GLenum *bufs);
+    void readBuffer(GLenum mode);
+
+    void discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments);
+    void invalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments);
+    void invalidateSubFramebuffer(GLenum target,
+                                  GLsizei numAttachments,
+                                  const GLenum *attachments,
+                                  GLint x,
+                                  GLint y,
+                                  GLsizei width,
+                                  GLsizei height);
+
+    void texImage2D(GLenum target,
+                    GLint level,
+                    GLint internalformat,
+                    GLsizei width,
+                    GLsizei height,
+                    GLint border,
+                    GLenum format,
+                    GLenum type,
+                    const void *pixels);
+    void texImage3D(GLenum target,
+                    GLint level,
+                    GLint internalformat,
+                    GLsizei width,
+                    GLsizei height,
+                    GLsizei depth,
+                    GLint border,
+                    GLenum format,
+                    GLenum type,
+                    const void *pixels);
+    void texSubImage2D(GLenum target,
+                       GLint level,
+                       GLint xoffset,
+                       GLint yoffset,
+                       GLsizei width,
+                       GLsizei height,
+                       GLenum format,
+                       GLenum type,
+                       const void *pixels);
+    void texSubImage3D(GLenum target,
+                       GLint level,
+                       GLint xoffset,
+                       GLint yoffset,
+                       GLint zoffset,
+                       GLsizei width,
+                       GLsizei height,
+                       GLsizei depth,
+                       GLenum format,
+                       GLenum type,
+                       const void *pixels);
+    void compressedTexImage2D(GLenum target,
+                              GLint level,
+                              GLenum internalformat,
+                              GLsizei width,
+                              GLsizei height,
+                              GLint border,
+                              GLsizei imageSize,
+                              const void *data);
+    void compressedTexImage3D(GLenum target,
+                              GLint level,
+                              GLenum internalformat,
+                              GLsizei width,
+                              GLsizei height,
+                              GLsizei depth,
+                              GLint border,
+                              GLsizei imageSize,
+                              const void *data);
+    void compressedTexSubImage2D(GLenum target,
+                                 GLint level,
+                                 GLint xoffset,
+                                 GLint yoffset,
+                                 GLsizei width,
+                                 GLsizei height,
+                                 GLenum format,
+                                 GLsizei imageSize,
+                                 const void *data);
+    void compressedTexSubImage3D(GLenum target,
+                                 GLint level,
+                                 GLint xoffset,
+                                 GLint yoffset,
+                                 GLint zoffset,
+                                 GLsizei width,
+                                 GLsizei height,
+                                 GLsizei depth,
+                                 GLenum format,
+                                 GLsizei imageSize,
+                                 const void *data);
+    void copyTextureCHROMIUM(GLuint sourceId,
+                             GLint sourceLevel,
+                             GLenum destTarget,
+                             GLuint destId,
+                             GLint destLevel,
+                             GLint internalFormat,
+                             GLenum destType,
+                             GLboolean unpackFlipY,
+                             GLboolean unpackPremultiplyAlpha,
+                             GLboolean unpackUnmultiplyAlpha);
+    void copySubTextureCHROMIUM(GLuint sourceId,
+                                GLint sourceLevel,
+                                GLenum destTarget,
+                                GLuint destId,
+                                GLint destLevel,
+                                GLint xoffset,
+                                GLint yoffset,
+                                GLint x,
+                                GLint y,
+                                GLsizei width,
+                                GLsizei height,
+                                GLboolean unpackFlipY,
+                                GLboolean unpackPremultiplyAlpha,
+                                GLboolean unpackUnmultiplyAlpha);
+    void compressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
+
+    void generateMipmap(GLenum target);
+
+    void flush();
+    void finish();
+
+    void getBufferPointerv(GLenum target, GLenum pname, void **params);
+    void *mapBuffer(GLenum target, GLenum access);
+    GLboolean unmapBuffer(GLenum target);
+    void *mapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+    void flushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
+
+    void beginTransformFeedback(GLenum primitiveMode);
+
+    bool hasActiveTransformFeedback(GLuint program) const;
+
+    void insertEventMarker(GLsizei length, const char *marker);
+    void pushGroupMarker(GLsizei length, const char *marker);
+    void popGroupMarker();
+
+    void bindUniformLocation(GLuint program, GLint location, const GLchar *name);
+    void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+    void renderbufferStorageMultisample(GLenum target,
+                                        GLsizei samples,
+                                        GLenum internalformat,
+                                        GLsizei width,
+                                        GLsizei height);
+
+    void getSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+
+    // CHROMIUM_framebuffer_mixed_samples
+    void setCoverageModulation(GLenum components);
+
+    // CHROMIUM_path_rendering
+    void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
+    void loadPathRenderingIdentityMatrix(GLenum matrixMode);
+    void stencilFillPath(GLuint path, GLenum fillMode, GLuint mask);
+    void stencilStrokePath(GLuint path, GLint reference, GLuint mask);
+    void coverFillPath(GLuint path, GLenum coverMode);
+    void coverStrokePath(GLuint path, GLenum coverMode);
+    void stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+    void stencilThenCoverStrokePath(GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+    void coverFillPathInstanced(GLsizei numPaths,
+                                GLenum pathNameType,
+                                const void *paths,
+                                GLuint pathBase,
+                                GLenum coverMode,
+                                GLenum transformType,
+                                const GLfloat *transformValues);
+    void coverStrokePathInstanced(GLsizei numPaths,
+                                  GLenum pathNameType,
+                                  const void *paths,
+                                  GLuint pathBase,
+                                  GLenum coverMode,
+                                  GLenum transformType,
+                                  const GLfloat *transformValues);
+    void stencilFillPathInstanced(GLsizei numPaths,
+                                  GLenum pathNameType,
+                                  const void *paths,
+                                  GLuint pathBAse,
+                                  GLenum fillMode,
+                                  GLuint mask,
+                                  GLenum transformType,
+                                  const GLfloat *transformValues);
+    void stencilStrokePathInstanced(GLsizei numPaths,
+                                    GLenum pathNameType,
+                                    const void *paths,
+                                    GLuint pathBase,
+                                    GLint reference,
+                                    GLuint mask,
+                                    GLenum transformType,
+                                    const GLfloat *transformValues);
+    void stencilThenCoverFillPathInstanced(GLsizei numPaths,
+                                           GLenum pathNameType,
+                                           const void *paths,
+                                           GLuint pathBase,
+                                           GLenum fillMode,
+                                           GLuint mask,
+                                           GLenum coverMode,
+                                           GLenum transformType,
+                                           const GLfloat *transformValues);
+    void stencilThenCoverStrokePathInstanced(GLsizei numPaths,
+                                             GLenum pathNameType,
+                                             const void *paths,
+                                             GLuint pathBase,
+                                             GLint reference,
+                                             GLuint mask,
+                                             GLenum coverMode,
+                                             GLenum transformType,
+                                             const GLfloat *transformValues);
+    void bindFragmentInputLocation(GLuint program, GLint location, const GLchar *name);
+    void programPathFragmentInputGen(GLuint program,
+                                     GLint location,
+                                     GLenum genMode,
+                                     GLint components,
+                                     const GLfloat *coeffs);
+
+    void bufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+    void bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+    void attachShader(GLuint program, GLuint shader);
+    void bindAttribLocation(GLuint program, GLuint index, const GLchar *name);
+    void bindBuffer(GLenum target, GLuint buffer);
+    void bindBufferBase(GLenum target, GLuint index, GLuint buffer);
+    void bindBufferRange(GLenum target,
+                         GLuint index,
+                         GLuint buffer,
+                         GLintptr offset,
+                         GLsizeiptr size);
+    void bindFramebuffer(GLenum target, GLuint framebuffer);
+    void bindRenderbuffer(GLenum target, GLuint renderbuffer);
+
+    void texStorage2DMultisample(GLenum target,
+                                 GLsizei samples,
+                                 GLenum internalformat,
+                                 GLsizei width,
+                                 GLsizei height,
+                                 GLboolean fixedsamplelocations);
+
+    void getMultisamplefv(GLenum pname, GLuint index, GLfloat *val);
+
+    void copyBufferSubData(GLenum readTarget,
+                           GLenum writeTarget,
+                           GLintptr readOffset,
+                           GLintptr writeOffset,
+                           GLsizeiptr size);
+
+    GLenum checkFramebufferStatus(GLenum target);
+    void compileShader(GLuint shader);
+    void deleteBuffers(GLsizei n, const GLuint *buffers);
+    void deleteFramebuffers(GLsizei n, const GLuint *framebuffers);
+    void deleteRenderbuffers(GLsizei n, const GLuint *renderbuffers);
+    void deleteTextures(GLsizei n, const GLuint *textures);
+    void detachShader(GLuint program, GLuint shader);
+    void genBuffers(GLsizei n, GLuint *buffers);
+    void genFramebuffers(GLsizei n, GLuint *framebuffers);
+    void genRenderbuffers(GLsizei n, GLuint *renderbuffers);
+    void genTextures(GLsizei n, GLuint *textures);
+    void getActiveAttrib(GLuint program,
+                         GLuint index,
+                         GLsizei bufsize,
+                         GLsizei *length,
+                         GLint *size,
+                         GLenum *type,
+                         GLchar *name);
+    void getActiveUniform(GLuint program,
+                          GLuint index,
+                          GLsizei bufsize,
+                          GLsizei *length,
+                          GLint *size,
+                          GLenum *type,
+                          GLchar *name);
+    void getAttachedShaders(GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders);
+    GLint getAttribLocation(GLuint program, const GLchar *name);
+    void getProgramiv(GLuint program, GLenum pname, GLint *params);
+    void getProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog);
+    void getShaderiv(GLuint shader, GLenum pname, GLint *params);
+    void getShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *infolog);
+    void getShaderPrecisionFormat(GLenum shadertype,
+                                  GLenum precisiontype,
+                                  GLint *range,
+                                  GLint *precision);
+    void getShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+    void getUniformfv(GLuint program, GLint location, GLfloat *params);
+    void getUniformiv(GLuint program, GLint location, GLint *params);
+    GLint getUniformLocation(GLuint program, const GLchar *name);
+    GLboolean isBuffer(GLuint buffer);
+    GLboolean isEnabled(GLenum cap);
+    GLboolean isFramebuffer(GLuint framebuffer);
+    GLboolean isProgram(GLuint program);
+    GLboolean isRenderbuffer(GLuint renderbuffer);
+    GLboolean isShader(GLuint shader);
+    GLboolean isTexture(GLuint texture);
+    void linkProgram(GLuint program);
+    void releaseShaderCompiler();
+    void shaderBinary(GLsizei n,
+                      const GLuint *shaders,
+                      GLenum binaryformat,
+                      const void *binary,
+                      GLsizei length);
+    void shaderSource(GLuint shader,
+                      GLsizei count,
+                      const GLchar *const *string,
+                      const GLint *length);
+    void stencilFunc(GLenum func, GLint ref, GLuint mask);
+    void stencilMask(GLuint mask);
+    void stencilOp(GLenum fail, GLenum zfail, GLenum zpass);
+    void uniform1f(GLint location, GLfloat x);
+    void uniform1fv(GLint location, GLsizei count, const GLfloat *v);
+    void uniform1i(GLint location, GLint x);
+    void uniform1iv(GLint location, GLsizei count, const GLint *v);
+    void uniform2f(GLint location, GLfloat x, GLfloat y);
+    void uniform2fv(GLint location, GLsizei count, const GLfloat *v);
+    void uniform2i(GLint location, GLint x, GLint y);
+    void uniform2iv(GLint location, GLsizei count, const GLint *v);
+    void uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z);
+    void uniform3fv(GLint location, GLsizei count, const GLfloat *v);
+    void uniform3i(GLint location, GLint x, GLint y, GLint z);
+    void uniform3iv(GLint location, GLsizei count, const GLint *v);
+    void uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+    void uniform4fv(GLint location, GLsizei count, const GLfloat *v);
+    void uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w);
+    void uniform4iv(GLint location, GLsizei count, const GLint *v);
+    void uniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void uniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void uniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void validateProgram(GLuint program);
+
+    void handleError(const Error &error) override;
+
+    GLenum getError();
+    void markContextLost();
+    bool isContextLost();
+    GLenum getResetStatus();
+    bool isResetNotificationEnabled();
+
+    const egl::Config *getConfig() const;
+    EGLenum getClientType() const;
+    EGLenum getRenderBuffer() const;
+
+    const GLubyte *getString(GLenum name) const;
+    const GLubyte *getStringi(GLenum name, GLuint index) const;
+
+    size_t getExtensionStringCount() const;
+
+    void requestExtension(const char *name);
+    size_t getRequestableExtensionStringCount() const;
+
+    rx::ContextImpl *getImplementation() const { return mImplementation.get(); }
+    const Workarounds &getWorkarounds() const;
+
+    void getFramebufferParameteriv(GLenum target, GLenum pname, GLint *params);
+    void setFramebufferParameteri(GLenum target, GLenum pname, GLint param);
+
+    Error getScratchBuffer(size_t requestedSize, angle::MemoryBuffer **scratchBufferOut) const;
+
+    void dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
+
+    template <EntryPoint EP, typename... ParamsT>
+    void gatherParams(ParamsT &&... params);
+
+  private:
+    void syncRendererState();
+    void syncRendererState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask);
+    void syncStateForReadPixels();
+    void syncStateForTexImage();
+    void syncStateForClear();
+    void syncStateForBlit();
+    VertexArray *checkVertexArrayAllocation(GLuint vertexArrayHandle);
+    TransformFeedback *checkTransformFeedbackAllocation(GLuint transformFeedback);
+
+    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 initRendererString();
+    void initVersionStrings();
+    void initExtensionStrings();
+
+    void initCaps(const egl::DisplayExtensions &displayExtensions);
+    void updateCaps();
+    void initWorkarounds();
+
+    LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
+    LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
+
+    std::unique_ptr<rx::ContextImpl> mImplementation;
+
+    // Caps to use for validation
+    Caps mCaps;
+    TextureCapsMap mTextureCaps;
+    Extensions mExtensions;
+    Limitations mLimitations;
+
+    // Shader compiler
+    Compiler *mCompiler;
+
+    State mGLState;
+
+    const egl::Config *mConfig;
+    EGLenum mClientType;
+
+    TextureMap mZeroTextures;
+
+    ResourceMap<FenceNV> mFenceNVMap;
+    HandleAllocator mFenceNVHandleAllocator;
+
+    ResourceMap<Query> mQueryMap;
+    HandleAllocator mQueryHandleAllocator;
+
+    ResourceMap<VertexArray> mVertexArrayMap;
+    HandleAllocator mVertexArrayHandleAllocator;
+
+    ResourceMap<TransformFeedback> mTransformFeedbackMap;
+    HandleAllocator mTransformFeedbackAllocator;
+
+    const char *mVersionString;
+    const char *mShadingLanguageString;
+    const char *mRendererString;
+    const char *mExtensionString;
+    std::vector<const char *> mExtensionStrings;
+    const char *mRequestableExtensionString;
+    std::vector<const char *> mRequestableExtensionStrings;
+
+    // Recorded errors
+    typedef std::set<GLenum> ErrorSet;
+    ErrorSet mErrors;
+
+    // Current/lost context flags
+    bool mHasBeenCurrent;
+    bool mContextLost;
+    GLenum mResetStatus;
+    bool mContextLostForced;
+    GLenum mResetStrategy;
+    bool mRobustAccess;
+    egl::Surface *mCurrentSurface;
+    Framebuffer *mSurfacelessFramebuffer;
+    bool mWebGLContext;
+
+    State::DirtyBits mTexImageDirtyBits;
+    State::DirtyObjects mTexImageDirtyObjects;
+    State::DirtyBits mReadPixelsDirtyBits;
+    State::DirtyObjects mReadPixelsDirtyObjects;
+    State::DirtyBits mClearDirtyBits;
+    State::DirtyObjects mClearDirtyObjects;
+    State::DirtyBits mBlitDirtyBits;
+    State::DirtyObjects mBlitDirtyObjects;
+
+    Workarounds mWorkarounds;
+
+    // Not really a property of context state. The size and contexts change per-api-call.
+    mutable angle::ScratchBuffer mScratchBuffer;
+};
+
+template <EntryPoint EP, typename... ArgsT>
+void Context::gatherParams(ArgsT &&... args)
+{
+    static_assert(sizeof(EntryPointParamType<EP>) <= kParamsBufferSize,
+                  "Params struct too large, please increase kParamsBufferSize.");
+
+    mSavedArgsType = &EntryPointParamType<EP>::TypeInfo;
+
+    // Skip doing any work for ParamsBase/Invalid type.
+    if (!EntryPointParamType<EP>::TypeInfo.isValid())
+    {
+        return;
+    }
+
+    EntryPointParamType<EP> *objBuffer =
+        reinterpret_cast<EntryPointParamType<EP> *>(mParamsBuffer.data());
+    EntryPointParamType<EP>::template Factory<EP>(objBuffer, this, std::forward<ArgsT>(args)...);
+}
+
+}  // namespace gl
+
+#endif  // LIBANGLE_CONTEXT_H_
diff --git a/src/third_party/angle/src/libANGLE/ContextState.cpp b/src/third_party/angle/src/libANGLE/ContextState.cpp
new file mode 100644
index 0000000..450e0ef
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/ContextState.cpp
@@ -0,0 +1,758 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Data.cpp: Container class for all GL relevant state, caps and objects
+
+#include "libANGLE/ContextState.h"
+
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/ResourceManager.h"
+
+namespace gl
+{
+
+namespace
+{
+
+template <typename T>
+using ContextStateMember = T *(ContextState::*);
+
+template <typename T>
+T *AllocateOrGetSharedResourceManager(const ContextState *shareContextState,
+                                      ContextStateMember<T> member)
+{
+    if (shareContextState)
+    {
+        T *resourceManager = (*shareContextState).*member;
+        resourceManager->addRef();
+        return resourceManager;
+    }
+    else
+    {
+        return new T();
+    }
+}
+
+TextureManager *AllocateOrGetSharedTextureManager(const ContextState *shareContextState,
+                                                  TextureManager *shareTextures,
+                                                  ContextStateMember<TextureManager> member)
+{
+    if (shareContextState)
+    {
+        TextureManager *textureManager = (*shareContextState).*member;
+        ASSERT(shareTextures == nullptr || textureManager == shareTextures);
+        textureManager->addRef();
+        return textureManager;
+    }
+    else if (shareTextures)
+    {
+        TextureManager *textureManager = shareTextures;
+        textureManager->addRef();
+        return textureManager;
+    }
+    else
+    {
+        return new TextureManager();
+    }
+}
+
+}  // anonymous namespace
+
+ContextState::ContextState(ContextID contextIn,
+                           const ContextState *shareContextState,
+                           TextureManager *shareTextures,
+                           const Version &clientVersion,
+                           State *stateIn,
+                           const Caps &capsIn,
+                           const TextureCapsMap &textureCapsIn,
+                           const Extensions &extensionsIn,
+                           const Limitations &limitationsIn)
+    : mClientVersion(clientVersion),
+      mContext(contextIn),
+      mState(stateIn),
+      mCaps(capsIn),
+      mTextureCaps(textureCapsIn),
+      mExtensions(extensionsIn),
+      mLimitations(limitationsIn),
+      mBuffers(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mBuffers)),
+      mShaderPrograms(
+          AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mShaderPrograms)),
+      mTextures(AllocateOrGetSharedTextureManager(shareContextState,
+                                                  shareTextures,
+                                                  &ContextState::mTextures)),
+      mRenderbuffers(
+          AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mRenderbuffers)),
+      mSamplers(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mSamplers)),
+      mFenceSyncs(
+          AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mFenceSyncs)),
+      mPaths(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mPaths)),
+      mFramebuffers(new FramebufferManager())
+{
+}
+
+ContextState::~ContextState()
+{
+    // Handles are released by the Context.
+}
+
+bool ContextState::isWebGL1() const
+{
+    return (mExtensions.webglCompatibility && mClientVersion.major == 2);
+}
+
+const TextureCaps &ContextState::getTextureCap(GLenum internalFormat) const
+{
+    return mTextureCaps.get(internalFormat);
+}
+
+ValidationContext::ValidationContext(const ValidationContext *shareContext,
+                                     TextureManager *shareTextures,
+                                     const Version &clientVersion,
+                                     State *state,
+                                     const Caps &caps,
+                                     const TextureCapsMap &textureCaps,
+                                     const Extensions &extensions,
+                                     const Limitations &limitations,
+                                     bool skipValidation)
+    : mState(reinterpret_cast<ContextID>(this),
+             shareContext ? &shareContext->mState : nullptr,
+             shareTextures,
+             clientVersion,
+             state,
+             caps,
+             textureCaps,
+             extensions,
+             limitations),
+      mSkipValidation(skipValidation),
+      mDisplayTextureShareGroup(shareTextures != nullptr)
+{
+}
+
+bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
+{
+    // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
+    // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
+    // to the fact that it is stored internally as a float, and so would require conversion
+    // if returned from Context::getIntegerv. Since this conversion is already implemented
+    // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
+    // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
+    // application.
+    switch (pname)
+    {
+        case GL_COMPRESSED_TEXTURE_FORMATS:
+        {
+            *type      = GL_INT;
+            *numParams = static_cast<unsigned int>(getCaps().compressedTextureFormats.size());
+            return true;
+        }
+        case GL_PROGRAM_BINARY_FORMATS_OES:
+        {
+            *type      = GL_INT;
+            *numParams = static_cast<unsigned int>(getCaps().programBinaryFormats.size());
+            return true;
+        }
+        case GL_SHADER_BINARY_FORMATS:
+        {
+            *type      = GL_INT;
+            *numParams = static_cast<unsigned int>(getCaps().shaderBinaryFormats.size());
+            return true;
+        }
+
+        case GL_MAX_VERTEX_ATTRIBS:
+        case GL_MAX_VERTEX_UNIFORM_VECTORS:
+        case GL_MAX_VARYING_VECTORS:
+        case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+        case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+        case GL_MAX_TEXTURE_IMAGE_UNITS:
+        case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+        case GL_MAX_RENDERBUFFER_SIZE:
+        case GL_NUM_SHADER_BINARY_FORMATS:
+        case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+        case GL_ARRAY_BUFFER_BINDING:
+        // case GL_FRAMEBUFFER_BINDING: // equivalent to DRAW_FRAMEBUFFER_BINDING_ANGLE
+        case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:
+        case GL_READ_FRAMEBUFFER_BINDING_ANGLE:
+        case GL_RENDERBUFFER_BINDING:
+        case GL_CURRENT_PROGRAM:
+        case GL_PACK_ALIGNMENT:
+        case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+        case GL_UNPACK_ALIGNMENT:
+        case GL_GENERATE_MIPMAP_HINT:
+        case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+        case GL_RED_BITS:
+        case GL_GREEN_BITS:
+        case GL_BLUE_BITS:
+        case GL_ALPHA_BITS:
+        case GL_DEPTH_BITS:
+        case GL_STENCIL_BITS:
+        case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+        case GL_CULL_FACE_MODE:
+        case GL_FRONT_FACE:
+        case GL_ACTIVE_TEXTURE:
+        case GL_STENCIL_FUNC:
+        case GL_STENCIL_VALUE_MASK:
+        case GL_STENCIL_REF:
+        case GL_STENCIL_FAIL:
+        case GL_STENCIL_PASS_DEPTH_FAIL:
+        case GL_STENCIL_PASS_DEPTH_PASS:
+        case GL_STENCIL_BACK_FUNC:
+        case GL_STENCIL_BACK_VALUE_MASK:
+        case GL_STENCIL_BACK_REF:
+        case GL_STENCIL_BACK_FAIL:
+        case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+        case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+        case GL_DEPTH_FUNC:
+        case GL_BLEND_SRC_RGB:
+        case GL_BLEND_SRC_ALPHA:
+        case GL_BLEND_DST_RGB:
+        case GL_BLEND_DST_ALPHA:
+        case GL_BLEND_EQUATION_RGB:
+        case GL_BLEND_EQUATION_ALPHA:
+        case GL_STENCIL_WRITEMASK:
+        case GL_STENCIL_BACK_WRITEMASK:
+        case GL_STENCIL_CLEAR_VALUE:
+        case GL_SUBPIXEL_BITS:
+        case GL_MAX_TEXTURE_SIZE:
+        case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+        case GL_SAMPLE_BUFFERS:
+        case GL_SAMPLES:
+        case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+        case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+        case GL_TEXTURE_BINDING_2D:
+        case GL_TEXTURE_BINDING_CUBE_MAP:
+        case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+        case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
+        {
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        }
+        case GL_MAX_DRAW_BUFFERS_EXT:
+        case GL_MAX_COLOR_ATTACHMENTS_EXT:
+        {
+            if ((getClientMajorVersion() < 3) && !getExtensions().drawBuffers)
+            {
+                return false;
+            }
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        }
+        case GL_MAX_VIEWPORT_DIMS:
+        {
+            *type      = GL_INT;
+            *numParams = 2;
+            return true;
+        }
+        case GL_VIEWPORT:
+        case GL_SCISSOR_BOX:
+        {
+            *type      = GL_INT;
+            *numParams = 4;
+            return true;
+        }
+        case GL_SHADER_COMPILER:
+        case GL_SAMPLE_COVERAGE_INVERT:
+        case GL_DEPTH_WRITEMASK:
+        case GL_CULL_FACE:                 // CULL_FACE through DITHER are natural to IsEnabled,
+        case GL_POLYGON_OFFSET_FILL:       // but can be retrieved through the Get{Type}v queries.
+        case GL_SAMPLE_ALPHA_TO_COVERAGE:  // For this purpose, they are treated here as
+                                           // bool-natural
+        case GL_SAMPLE_COVERAGE:
+        case GL_SCISSOR_TEST:
+        case GL_STENCIL_TEST:
+        case GL_DEPTH_TEST:
+        case GL_BLEND:
+        case GL_DITHER:
+        case GL_CONTEXT_ROBUST_ACCESS_EXT:
+        {
+            *type      = GL_BOOL;
+            *numParams = 1;
+            return true;
+        }
+        case GL_COLOR_WRITEMASK:
+        {
+            *type      = GL_BOOL;
+            *numParams = 4;
+            return true;
+        }
+        case GL_POLYGON_OFFSET_FACTOR:
+        case GL_POLYGON_OFFSET_UNITS:
+        case GL_SAMPLE_COVERAGE_VALUE:
+        case GL_DEPTH_CLEAR_VALUE:
+        case GL_LINE_WIDTH:
+        {
+            *type      = GL_FLOAT;
+            *numParams = 1;
+            return true;
+        }
+        case GL_ALIASED_LINE_WIDTH_RANGE:
+        case GL_ALIASED_POINT_SIZE_RANGE:
+        case GL_DEPTH_RANGE:
+        {
+            *type      = GL_FLOAT;
+            *numParams = 2;
+            return true;
+        }
+        case GL_COLOR_CLEAR_VALUE:
+        case GL_BLEND_COLOR:
+        {
+            *type      = GL_FLOAT;
+            *numParams = 4;
+            return true;
+        }
+        case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+            if (!getExtensions().textureFilterAnisotropic)
+            {
+                return false;
+            }
+            *type      = GL_FLOAT;
+            *numParams = 1;
+            return true;
+        case GL_TIMESTAMP_EXT:
+            if (!getExtensions().disjointTimerQuery)
+            {
+                return false;
+            }
+            *type      = GL_INT_64_ANGLEX;
+            *numParams = 1;
+            return true;
+        case GL_GPU_DISJOINT_EXT:
+            if (!getExtensions().disjointTimerQuery)
+            {
+                return false;
+            }
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        case GL_COVERAGE_MODULATION_CHROMIUM:
+            if (!getExtensions().framebufferMixedSamples)
+            {
+                return false;
+            }
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        case GL_TEXTURE_BINDING_EXTERNAL_OES:
+            if (!getExtensions().eglStreamConsumerExternal && !getExtensions().eglImageExternal)
+            {
+                return false;
+            }
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+    }
+
+    if (getExtensions().debug)
+    {
+        switch (pname)
+        {
+            case GL_DEBUG_LOGGED_MESSAGES:
+            case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
+            case GL_DEBUG_GROUP_STACK_DEPTH:
+            case GL_MAX_DEBUG_MESSAGE_LENGTH:
+            case GL_MAX_DEBUG_LOGGED_MESSAGES:
+            case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
+            case GL_MAX_LABEL_LENGTH:
+                *type      = GL_INT;
+                *numParams = 1;
+                return true;
+
+            case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+            case GL_DEBUG_OUTPUT:
+                *type      = GL_BOOL;
+                *numParams = 1;
+                return true;
+        }
+    }
+
+    if (getExtensions().multisampleCompatibility)
+    {
+        switch (pname)
+        {
+            case GL_MULTISAMPLE_EXT:
+            case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+                *type      = GL_BOOL;
+                *numParams = 1;
+                return true;
+        }
+    }
+
+    if (getExtensions().pathRendering)
+    {
+        switch (pname)
+        {
+            case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
+            case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
+                *type = GL_FLOAT;
+                *numParams = 16;
+                return true;
+        }
+    }
+
+    if (getExtensions().bindGeneratesResource)
+    {
+        switch (pname)
+        {
+            case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+                *type      = GL_BOOL;
+                *numParams = 1;
+                return true;
+        }
+    }
+
+    if (getExtensions().clientArrays)
+    {
+        switch (pname)
+        {
+            case GL_CLIENT_ARRAYS_ANGLE:
+                *type      = GL_BOOL;
+                *numParams = 1;
+                return true;
+        }
+    }
+
+    if (getExtensions().sRGBWriteControl)
+    {
+        switch (pname)
+        {
+            case GL_FRAMEBUFFER_SRGB_EXT:
+                *type      = GL_BOOL;
+                *numParams = 1;
+                return true;
+        }
+    }
+
+    if (getExtensions().robustResourceInitialization &&
+        pname == GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE)
+    {
+        *type      = GL_BOOL;
+        *numParams = 1;
+        return true;
+    }
+
+    // Check for ES3.0+ parameter names which are also exposed as ES2 extensions
+    switch (pname)
+    {
+        case GL_PACK_ROW_LENGTH:
+        case GL_PACK_SKIP_ROWS:
+        case GL_PACK_SKIP_PIXELS:
+            if ((getClientMajorVersion() < 3) && !getExtensions().packSubimage)
+            {
+                return false;
+            }
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        case GL_UNPACK_ROW_LENGTH:
+        case GL_UNPACK_SKIP_ROWS:
+        case GL_UNPACK_SKIP_PIXELS:
+            if ((getClientMajorVersion() < 3) && !getExtensions().unpackSubimage)
+            {
+                return false;
+            }
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        case GL_VERTEX_ARRAY_BINDING:
+            if ((getClientMajorVersion() < 3) && !getExtensions().vertexArrayObject)
+            {
+                return false;
+            }
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        case GL_PIXEL_PACK_BUFFER_BINDING:
+        case GL_PIXEL_UNPACK_BUFFER_BINDING:
+            if ((getClientMajorVersion() < 3) && !getExtensions().pixelBufferObject)
+            {
+                return false;
+            }
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        case GL_MAX_SAMPLES:
+        {
+            static_assert(GL_MAX_SAMPLES_ANGLE == GL_MAX_SAMPLES,
+                          "GL_MAX_SAMPLES_ANGLE not equal to GL_MAX_SAMPLES");
+            if ((getClientMajorVersion() < 3) && !getExtensions().framebufferMultisample)
+            {
+                return false;
+            }
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        }
+    }
+
+    if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
+    {
+        if ((getClientVersion() < Version(3, 0)) && !getExtensions().drawBuffers)
+        {
+            return false;
+        }
+        *type      = GL_INT;
+        *numParams = 1;
+        return true;
+    }
+
+    if (getClientVersion() < Version(3, 0))
+    {
+        return false;
+    }
+
+    // Check for ES3.0+ parameter names
+    switch (pname)
+    {
+        case GL_MAX_UNIFORM_BUFFER_BINDINGS:
+        case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+        case GL_UNIFORM_BUFFER_BINDING:
+        case GL_TRANSFORM_FEEDBACK_BINDING:
+        case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+        case GL_COPY_READ_BUFFER_BINDING:
+        case GL_COPY_WRITE_BUFFER_BINDING:
+        case GL_SAMPLER_BINDING:
+        case GL_READ_BUFFER:
+        case GL_TEXTURE_BINDING_3D:
+        case GL_TEXTURE_BINDING_2D_ARRAY:
+        case GL_MAX_3D_TEXTURE_SIZE:
+        case GL_MAX_ARRAY_TEXTURE_LAYERS:
+        case GL_MAX_VERTEX_UNIFORM_BLOCKS:
+        case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
+        case GL_MAX_COMBINED_UNIFORM_BLOCKS:
+        case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
+        case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
+        case GL_MAX_VARYING_COMPONENTS:
+        case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
+        case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+        case GL_MIN_PROGRAM_TEXEL_OFFSET:
+        case GL_MAX_PROGRAM_TEXEL_OFFSET:
+        case GL_NUM_EXTENSIONS:
+        case GL_MAJOR_VERSION:
+        case GL_MINOR_VERSION:
+        case GL_MAX_ELEMENTS_INDICES:
+        case GL_MAX_ELEMENTS_VERTICES:
+        case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
+        case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+        case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
+        case GL_UNPACK_IMAGE_HEIGHT:
+        case GL_UNPACK_SKIP_IMAGES:
+        {
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        }
+
+        case GL_MAX_ELEMENT_INDEX:
+        case GL_MAX_UNIFORM_BLOCK_SIZE:
+        case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+        case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+        case GL_MAX_SERVER_WAIT_TIMEOUT:
+        {
+            *type      = GL_INT_64_ANGLEX;
+            *numParams = 1;
+            return true;
+        }
+
+        case GL_TRANSFORM_FEEDBACK_ACTIVE:
+        case GL_TRANSFORM_FEEDBACK_PAUSED:
+        case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+        case GL_RASTERIZER_DISCARD:
+        {
+            *type      = GL_BOOL;
+            *numParams = 1;
+            return true;
+        }
+
+        case GL_MAX_TEXTURE_LOD_BIAS:
+        {
+            *type      = GL_FLOAT;
+            *numParams = 1;
+            return true;
+        }
+    }
+
+    if (getExtensions().requestExtension)
+    {
+        switch (pname)
+        {
+            case GL_NUM_REQUESTABLE_EXTENSIONS_ANGLE:
+                *type      = GL_INT;
+                *numParams = 1;
+                return true;
+        }
+    }
+
+    if (getClientVersion() < Version(3, 1))
+    {
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+        case GL_DRAW_INDIRECT_BUFFER_BINDING:
+        case GL_MAX_FRAMEBUFFER_WIDTH:
+        case GL_MAX_FRAMEBUFFER_HEIGHT:
+        case GL_MAX_FRAMEBUFFER_SAMPLES:
+        case GL_MAX_SAMPLE_MASK_WORDS:
+        case GL_MAX_COLOR_TEXTURE_SAMPLES:
+        case GL_MAX_DEPTH_TEXTURE_SAMPLES:
+        case GL_MAX_INTEGER_SAMPLES:
+        case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
+        case GL_MAX_VERTEX_ATTRIB_BINDINGS:
+        case GL_MAX_VERTEX_ATTRIB_STRIDE:
+        case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
+        case GL_MAX_VERTEX_ATOMIC_COUNTERS:
+        case GL_MAX_VERTEX_IMAGE_UNIFORMS:
+        case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
+        case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
+        case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
+        case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
+        case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
+        case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
+        case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
+        case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
+        case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
+        case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
+        case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
+        case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
+        case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
+        case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
+        case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
+        case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
+        case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
+        case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
+        case GL_MAX_UNIFORM_LOCATIONS:
+        case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
+        case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
+        case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
+        case GL_MAX_COMBINED_ATOMIC_COUNTERS:
+        case GL_MAX_IMAGE_UNITS:
+        case GL_MAX_COMBINED_IMAGE_UNIFORMS:
+        case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
+        case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
+        case GL_SHADER_STORAGE_BUFFER_BINDING:
+        case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
+            *type      = GL_INT_64_ANGLEX;
+            *numParams = 1;
+            return true;
+    }
+
+    return false;
+}
+
+bool ValidationContext::getIndexedQueryParameterInfo(GLenum target,
+                                                     GLenum *type,
+                                                     unsigned int *numParams)
+{
+    if (getClientVersion() < Version(3, 0))
+    {
+        return false;
+    }
+
+    switch (target)
+    {
+        case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+        case GL_UNIFORM_BUFFER_BINDING:
+        {
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        }
+        case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+        case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+        case GL_UNIFORM_BUFFER_START:
+        case GL_UNIFORM_BUFFER_SIZE:
+        {
+            *type      = GL_INT_64_ANGLEX;
+            *numParams = 1;
+            return true;
+        }
+    }
+
+    if (getClientVersion() < Version(3, 1))
+    {
+        return false;
+    }
+
+    switch (target)
+    {
+        case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+        case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+        case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+        case GL_SHADER_STORAGE_BUFFER_BINDING:
+        case GL_VERTEX_BINDING_BUFFER:
+        case GL_VERTEX_BINDING_DIVISOR:
+        case GL_VERTEX_BINDING_OFFSET:
+        case GL_VERTEX_BINDING_STRIDE:
+        {
+            *type      = GL_INT;
+            *numParams = 1;
+            return true;
+        }
+        case GL_ATOMIC_COUNTER_BUFFER_START:
+        case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+        case GL_SHADER_STORAGE_BUFFER_START:
+        case GL_SHADER_STORAGE_BUFFER_SIZE:
+        {
+            *type      = GL_INT_64_ANGLEX;
+            *numParams = 1;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+Program *ValidationContext::getProgram(GLuint handle) const
+{
+    return mState.mShaderPrograms->getProgram(handle);
+}
+
+Shader *ValidationContext::getShader(GLuint handle) const
+{
+    return mState.mShaderPrograms->getShader(handle);
+}
+
+bool ValidationContext::isTextureGenerated(GLuint texture) const
+{
+    return mState.mTextures->isTextureGenerated(texture);
+}
+
+bool ValidationContext::isBufferGenerated(GLuint buffer) const
+{
+    return mState.mBuffers->isBufferGenerated(buffer);
+}
+
+bool ValidationContext::isRenderbufferGenerated(GLuint renderbuffer) const
+{
+    return mState.mRenderbuffers->isRenderbufferGenerated(renderbuffer);
+}
+
+bool ValidationContext::isFramebufferGenerated(GLuint framebuffer) const
+{
+    return mState.mFramebuffers->isFramebufferGenerated(framebuffer);
+}
+
+bool ValidationContext::usingDisplayTextureShareGroup() const
+{
+    return mDisplayTextureShareGroup;
+}
+
+GLenum ValidationContext::getConvertedRenderbufferFormat(GLenum internalformat) const
+{
+    return mState.mExtensions.webglCompatibility && mState.mClientVersion.major == 2 &&
+                   internalformat == GL_DEPTH_STENCIL
+               ? GL_DEPTH24_STENCIL8
+               : internalformat;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/ContextState.h b/src/third_party/angle/src/libANGLE/ContextState.h
new file mode 100644
index 0000000..6f6a167
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/ContextState.h
@@ -0,0 +1,159 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ContextState: Container class for all GL context state, caps and objects.
+
+#ifndef LIBANGLE_CONTEXTSTATE_H_
+#define LIBANGLE_CONTEXTSTATE_H_
+
+#include "common/MemoryBuffer.h"
+#include "common/angleutils.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/params.h"
+
+namespace gl
+{
+class BufferManager;
+class ContextState;
+class FenceSyncManager;
+class FramebufferManager;
+class PathManager;
+class RenderbufferManager;
+class SamplerManager;
+class ShaderProgramManager;
+class TextureManager;
+class ValidationContext;
+
+static constexpr Version ES_2_0 = Version(2, 0);
+static constexpr Version ES_3_0 = Version(3, 0);
+static constexpr Version ES_3_1 = Version(3, 1);
+
+using ContextID = uintptr_t;
+
+class ContextState final : angle::NonCopyable
+{
+  public:
+    ContextState(ContextID context,
+                 const ContextState *shareContextState,
+                 TextureManager *shareTextures,
+                 const Version &clientVersion,
+                 State *state,
+                 const Caps &caps,
+                 const TextureCapsMap &textureCaps,
+                 const Extensions &extensions,
+                 const Limitations &limitations);
+    ~ContextState();
+
+    ContextID getContextID() const { return mContext; }
+    GLint getClientMajorVersion() const { return mClientVersion.major; }
+    GLint getClientMinorVersion() const { return mClientVersion.minor; }
+    const Version &getClientVersion() const { return mClientVersion; }
+    const State &getState() const { return *mState; }
+    const Caps &getCaps() const { return mCaps; }
+    const TextureCapsMap &getTextureCaps() const { return mTextureCaps; }
+    const Extensions &getExtensions() const { return mExtensions; }
+    const Limitations &getLimitations() const { return mLimitations; }
+
+    const TextureCaps &getTextureCap(GLenum internalFormat) const;
+
+    bool usingDisplayTextureShareGroup() const;
+
+    bool isWebGL1() const;
+
+  private:
+    friend class Context;
+    friend class ValidationContext;
+
+    Version mClientVersion;
+    ContextID mContext;
+    State *mState;
+    const Caps &mCaps;
+    const TextureCapsMap &mTextureCaps;
+    const Extensions &mExtensions;
+    const Limitations &mLimitations;
+
+    BufferManager *mBuffers;
+    ShaderProgramManager *mShaderPrograms;
+    TextureManager *mTextures;
+    RenderbufferManager *mRenderbuffers;
+    SamplerManager *mSamplers;
+    FenceSyncManager *mFenceSyncs;
+    PathManager *mPaths;
+    FramebufferManager *mFramebuffers;
+};
+
+class ValidationContext : angle::NonCopyable
+{
+  public:
+    ValidationContext(const ValidationContext *shareContext,
+                      TextureManager *shareTextures,
+                      const Version &clientVersion,
+                      State *state,
+                      const Caps &caps,
+                      const TextureCapsMap &textureCaps,
+                      const Extensions &extensions,
+                      const Limitations &limitations,
+                      bool skipValidation);
+    virtual ~ValidationContext() {}
+
+    virtual void handleError(const Error &error) = 0;
+
+    const ContextState &getContextState() const { return mState; }
+    GLint getClientMajorVersion() const { return mState.getClientMajorVersion(); }
+    GLint getClientMinorVersion() const { return mState.getClientMinorVersion(); }
+    const Version &getClientVersion() const { return mState.getClientVersion(); }
+    const State &getGLState() const { return mState.getState(); }
+    const Caps &getCaps() const { return mState.getCaps(); }
+    const TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); }
+    const Extensions &getExtensions() const { return mState.getExtensions(); }
+    const Limitations &getLimitations() const { return mState.getLimitations(); }
+    bool skipValidation() const { return mSkipValidation; }
+
+    // Specific methods needed for validation.
+    bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
+    bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
+
+    Program *getProgram(GLuint handle) const;
+    Shader *getShader(GLuint handle) const;
+
+    bool isTextureGenerated(GLuint texture) const;
+    bool isBufferGenerated(GLuint buffer) const;
+    bool isRenderbufferGenerated(GLuint renderbuffer) const;
+    bool isFramebufferGenerated(GLuint framebuffer) const;
+
+    bool usingDisplayTextureShareGroup() const;
+
+    // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+    GLenum getConvertedRenderbufferFormat(GLenum internalformat) const;
+
+    bool isWebGL1() const { return mState.isWebGL1(); }
+
+    template <typename T>
+    const T &getParams() const;
+
+  protected:
+    ContextState mState;
+    bool mSkipValidation;
+    bool mDisplayTextureShareGroup;
+
+    // Caches entry point parameters and values re-used between layers.
+    mutable const ParamTypeInfo *mSavedArgsType;
+    static constexpr size_t kParamsBufferSize = 64u;
+    mutable std::array<uint8_t, kParamsBufferSize> mParamsBuffer;
+};
+
+template <typename T>
+const T &ValidationContext::getParams() const
+{
+    const T *params = reinterpret_cast<T *>(mParamsBuffer.data());
+    ASSERT(mSavedArgsType->hasDynamicType(T::TypeInfo));
+    return *params;
+}
+
+}  // namespace gl
+
+#endif  // LIBANGLE_CONTEXTSTATE_H_
diff --git a/src/third_party/angle/src/libANGLE/Debug.cpp b/src/third_party/angle/src/libANGLE/Debug.cpp
new file mode 100644
index 0000000..30321f4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Debug.cpp
@@ -0,0 +1,303 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Debug.cpp: Defines debug state used for GL_KHR_debug
+
+#include "libANGLE/Debug.h"
+
+#include "common/debug.h"
+
+#include <algorithm>
+#include <tuple>
+
+namespace gl
+{
+
+Debug::Debug()
+    : mOutputEnabled(false),
+      mCallbackFunction(nullptr),
+      mCallbackUserParam(nullptr),
+      mMessages(),
+      mMaxLoggedMessages(0),
+      mOutputSynchronous(false),
+      mGroups()
+{
+    pushDefaultGroup();
+}
+
+void Debug::setMaxLoggedMessages(GLuint maxLoggedMessages)
+{
+    mMaxLoggedMessages = maxLoggedMessages;
+}
+
+void Debug::setOutputEnabled(bool enabled)
+{
+    mOutputEnabled = enabled;
+}
+
+bool Debug::isOutputEnabled() const
+{
+    return mOutputEnabled;
+}
+
+void Debug::setOutputSynchronous(bool synchronous)
+{
+    mOutputSynchronous = synchronous;
+}
+
+bool Debug::isOutputSynchronous() const
+{
+    return mOutputSynchronous;
+}
+
+void Debug::setCallback(GLDEBUGPROCKHR callback, const void *userParam)
+{
+    mCallbackFunction  = callback;
+    mCallbackUserParam = userParam;
+}
+
+GLDEBUGPROCKHR Debug::getCallback() const
+{
+    return mCallbackFunction;
+}
+
+const void *Debug::getUserParam() const
+{
+    return mCallbackUserParam;
+}
+
+void Debug::insertMessage(GLenum source,
+                          GLenum type,
+                          GLuint id,
+                          GLenum severity,
+                          const std::string &message)
+{
+    std::string messageCopy(message);
+    insertMessage(source, type, id, severity, std::move(messageCopy));
+}
+
+void Debug::insertMessage(GLenum source,
+                          GLenum type,
+                          GLuint id,
+                          GLenum severity,
+                          std::string &&message)
+{
+    if (!isMessageEnabled(source, type, id, severity))
+    {
+        return;
+    }
+
+    if (mCallbackFunction != nullptr)
+    {
+        // TODO(geofflang) Check the synchronous flag and potentially flush messages from another
+        // thread.
+        mCallbackFunction(source, type, id, severity, static_cast<GLsizei>(message.length()),
+                          message.c_str(), mCallbackUserParam);
+    }
+    else
+    {
+        if (mMessages.size() >= mMaxLoggedMessages)
+        {
+            // Drop messages over the limit
+            return;
+        }
+
+        Message m;
+        m.source   = source;
+        m.type     = type;
+        m.id       = id;
+        m.severity = severity;
+        m.message  = std::move(message);
+
+        mMessages.push_back(std::move(m));
+    }
+}
+
+size_t Debug::getMessages(GLuint count,
+                          GLsizei bufSize,
+                          GLenum *sources,
+                          GLenum *types,
+                          GLuint *ids,
+                          GLenum *severities,
+                          GLsizei *lengths,
+                          GLchar *messageLog)
+{
+    size_t messageCount       = 0;
+    size_t messageStringIndex = 0;
+    while (messageCount <= count && !mMessages.empty())
+    {
+        const Message &m = mMessages.front();
+
+        if (messageLog != nullptr)
+        {
+            // Check that this message can fit in the message buffer
+            if (messageStringIndex + m.message.length() + 1 > static_cast<size_t>(bufSize))
+            {
+                break;
+            }
+
+            std::copy(m.message.begin(), m.message.end(), messageLog + messageStringIndex);
+            messageStringIndex += m.message.length();
+
+            messageLog[messageStringIndex] = '\0';
+            messageStringIndex += 1;
+        }
+
+        if (sources != nullptr)
+        {
+            sources[messageCount] = m.source;
+        }
+
+        if (types != nullptr)
+        {
+            types[messageCount] = m.type;
+        }
+
+        if (ids != nullptr)
+        {
+            ids[messageCount] = m.id;
+        }
+
+        if (severities != nullptr)
+        {
+            severities[messageCount] = m.severity;
+        }
+
+        if (lengths != nullptr)
+        {
+            lengths[messageCount] = static_cast<GLsizei>(m.message.length());
+        }
+
+        mMessages.pop_front();
+
+        messageCount++;
+    }
+
+    return messageCount;
+}
+
+size_t Debug::getNextMessageLength() const
+{
+    return mMessages.empty() ? 0 : mMessages.front().message.length();
+}
+
+size_t Debug::getMessageCount() const
+{
+    return mMessages.size();
+}
+
+void Debug::setMessageControl(GLenum source,
+                              GLenum type,
+                              GLenum severity,
+                              std::vector<GLuint> &&ids,
+                              bool enabled)
+{
+    Control c;
+    c.source   = source;
+    c.type     = type;
+    c.severity = severity;
+    c.ids      = std::move(ids);
+    c.enabled  = enabled;
+
+    auto &controls = mGroups.back().controls;
+    controls.push_back(std::move(c));
+}
+
+void Debug::pushGroup(GLenum source, GLuint id, std::string &&message)
+{
+    insertMessage(source, GL_DEBUG_TYPE_PUSH_GROUP, id, GL_DEBUG_SEVERITY_NOTIFICATION,
+                  std::string(message));
+
+    Group g;
+    g.source  = source;
+    g.id      = id;
+    g.message = std::move(message);
+    mGroups.push_back(std::move(g));
+}
+
+void Debug::popGroup()
+{
+    // Make sure the default group is not about to be popped
+    ASSERT(mGroups.size() > 1);
+
+    Group g = mGroups.back();
+    mGroups.pop_back();
+
+    insertMessage(g.source, GL_DEBUG_TYPE_POP_GROUP, g.id, GL_DEBUG_SEVERITY_NOTIFICATION,
+                  g.message);
+}
+
+size_t Debug::getGroupStackDepth() const
+{
+    return mGroups.size();
+}
+
+bool Debug::isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const
+{
+    if (!mOutputEnabled)
+    {
+        return false;
+    }
+
+    for (auto groupIter = mGroups.rbegin(); groupIter != mGroups.rend(); groupIter++)
+    {
+        const auto &controls = groupIter->controls;
+        for (auto controlIter = controls.rbegin(); controlIter != controls.rend(); controlIter++)
+        {
+            const auto &control = *controlIter;
+
+            if (control.source != GL_DONT_CARE && control.source != source)
+            {
+                continue;
+            }
+
+            if (control.type != GL_DONT_CARE && control.type != type)
+            {
+                continue;
+            }
+
+            if (control.severity != GL_DONT_CARE && control.severity != severity)
+            {
+                continue;
+            }
+
+            if (!control.ids.empty() &&
+                std::find(control.ids.begin(), control.ids.end(), id) == control.ids.end())
+            {
+                continue;
+            }
+
+            return control.enabled;
+        }
+    }
+
+    return true;
+}
+
+void Debug::pushDefaultGroup()
+{
+    Group g;
+    g.source  = GL_NONE;
+    g.id      = 0;
+    g.message = "";
+
+    Control c0;
+    c0.source   = GL_DONT_CARE;
+    c0.type     = GL_DONT_CARE;
+    c0.severity = GL_DONT_CARE;
+    c0.enabled = true;
+    g.controls.push_back(std::move(c0));
+
+    Control c1;
+    c1.source   = GL_DONT_CARE;
+    c1.type     = GL_DONT_CARE;
+    c1.severity = GL_DEBUG_SEVERITY_LOW;
+    c1.enabled = false;
+    g.controls.push_back(std::move(c1));
+
+    mGroups.push_back(std::move(g));
+}
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/Debug.h b/src/third_party/angle/src/libANGLE/Debug.h
new file mode 100644
index 0000000..f545b81
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Debug.h
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Debug.h: Defines debug state used for GL_KHR_debug
+
+#ifndef LIBANGLE_DEBUG_H_
+#define LIBANGLE_DEBUG_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+#include <deque>
+#include <string>
+#include <vector>
+
+namespace gl
+{
+
+class LabeledObject
+{
+  public:
+    virtual ~LabeledObject() {}
+    virtual void setLabel(const std::string &label) = 0;
+    virtual const std::string &getLabel() const = 0;
+};
+
+class Debug : angle::NonCopyable
+{
+  public:
+    Debug();
+
+    void setMaxLoggedMessages(GLuint maxLoggedMessages);
+
+    void setOutputEnabled(bool enabled);
+    bool isOutputEnabled() const;
+
+    void setOutputSynchronous(bool synchronous);
+    bool isOutputSynchronous() const;
+
+    void setCallback(GLDEBUGPROCKHR callback, const void *userParam);
+    GLDEBUGPROCKHR getCallback() const;
+    const void *getUserParam() const;
+
+    void insertMessage(GLenum source,
+                       GLenum type,
+                       GLuint id,
+                       GLenum severity,
+                       const std::string &message);
+    void insertMessage(GLenum source,
+                       GLenum type,
+                       GLuint id,
+                       GLenum severity,
+                       std::string &&message);
+
+    void setMessageControl(GLenum source,
+                           GLenum type,
+                           GLenum severity,
+                           std::vector<GLuint> &&ids,
+                           bool enabled);
+    size_t getMessages(GLuint count,
+                       GLsizei bufSize,
+                       GLenum *sources,
+                       GLenum *types,
+                       GLuint *ids,
+                       GLenum *severities,
+                       GLsizei *lengths,
+                       GLchar *messageLog);
+    size_t getNextMessageLength() const;
+    size_t getMessageCount() const;
+
+    void pushGroup(GLenum source, GLuint id, std::string &&message);
+    void popGroup();
+    size_t getGroupStackDepth() const;
+
+  private:
+    bool isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const;
+
+    void pushDefaultGroup();
+
+    struct Message
+    {
+        GLenum source;
+        GLenum type;
+        GLuint id;
+        GLenum severity;
+        std::string message;
+    };
+
+    struct Control
+    {
+        GLenum source;
+        GLenum type;
+        GLenum severity;
+        std::vector<GLuint> ids;
+        bool enabled;
+    };
+
+    struct Group
+    {
+        GLenum source;
+        GLuint id;
+        std::string message;
+
+        std::vector<Control> controls;
+    };
+
+    bool mOutputEnabled;
+    GLDEBUGPROCKHR mCallbackFunction;
+    const void *mCallbackUserParam;
+    std::deque<Message> mMessages;
+    GLuint mMaxLoggedMessages;
+    bool mOutputSynchronous;
+    std::vector<Group> mGroups;
+};
+}  // namespace gl
+
+#endif  // LIBANGLE_DEBUG_H_
diff --git a/src/third_party/angle/src/libANGLE/Device.cpp b/src/third_party/angle/src/libANGLE/Device.cpp
new file mode 100644
index 0000000..eb30b20
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Device.cpp
@@ -0,0 +1,130 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Device.cpp: Implements the egl::Device class, representing the abstract
+// device. Implements EGLDevice.
+
+#include "libANGLE/Device.h"
+
+#include <iterator>
+
+#include <platform/Platform.h>
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "common/platform.h"
+#include "libANGLE/renderer/DeviceImpl.h"
+
+#if defined(ANGLE_ENABLE_D3D11)
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#endif
+
+namespace egl
+{
+
+template <typename T>
+static std::string GenerateExtensionsString(const T &extensions)
+{
+    std::vector<std::string> extensionsVector = extensions.getStrings();
+
+    std::ostringstream stream;
+    std::copy(extensionsVector.begin(), extensionsVector.end(), std::ostream_iterator<std::string>(stream, " "));
+    return stream.str();
+}
+
+typedef std::set<egl::Device *> DeviceSet;
+static DeviceSet *GetDeviceSet()
+{
+    static DeviceSet devices;
+    return &devices;
+}
+
+// Static factory methods
+egl::Error Device::CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice)
+{
+#if defined(ANGLE_ENABLE_D3D11)
+    if (deviceType == EGL_D3D11_DEVICE_ANGLE)
+    {
+        rx::DeviceD3D *deviceD3D = new rx::DeviceD3D();
+        egl::Error error = deviceD3D->initialize(devicePointer, deviceType, EGL_TRUE);
+        if (error.isError())
+        {
+            *outDevice = nullptr;
+            return error;
+        }
+
+        *outDevice = new Device(nullptr, deviceD3D);
+        GetDeviceSet()->insert(*outDevice);
+        return egl::Error(EGL_SUCCESS);
+    }
+#endif
+
+    // Note that creating an EGL device from inputted D3D9 parameters isn't currently supported
+    *outDevice = nullptr;
+    return egl::Error(EGL_BAD_ATTRIBUTE);
+}
+
+egl::Error Device::CreateDevice(Display *owningDisplay, rx::DeviceImpl *impl, Device **outDevice)
+{
+    *outDevice = new Device(owningDisplay, impl);
+    GetDeviceSet()->insert(*outDevice);
+    return egl::Error(EGL_SUCCESS);
+}
+
+bool Device::IsValidDevice(Device *device)
+{
+    const DeviceSet *deviceSet = GetDeviceSet();
+    return deviceSet->find(device) != deviceSet->end();
+}
+
+Device::Device(Display *owningDisplay, rx::DeviceImpl *impl)
+    : mOwningDisplay(owningDisplay), mImplementation(impl)
+{
+    initDeviceExtensions();
+}
+
+Device::~Device()
+{
+    ASSERT(GetDeviceSet()->find(this) != GetDeviceSet()->end());
+    GetDeviceSet()->erase(this);
+
+    if (mImplementation->deviceExternallySourced())
+    {
+        // If the device isn't externally sourced then it is up to the renderer to delete the impl
+        SafeDelete(mImplementation);
+    }
+}
+
+Error Device::getDevice(EGLAttrib *value)
+{
+    void *nativeDevice = nullptr;
+    egl::Error error = getImplementation()->getDevice(&nativeDevice);
+    *value = reinterpret_cast<EGLAttrib>(nativeDevice);
+    return error;
+}
+
+EGLint Device::getType()
+{
+    return getImplementation()->getType();
+}
+
+void Device::initDeviceExtensions()
+{
+    mImplementation->generateExtensions(&mDeviceExtensions);
+    mDeviceExtensionString = GenerateExtensionsString(mDeviceExtensions);
+}
+
+const DeviceExtensions &Device::getExtensions() const
+{
+    return mDeviceExtensions;
+}
+
+const std::string &Device::getExtensionString() const
+{
+    return mDeviceExtensionString;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/Device.h b/src/third_party/angle/src/libANGLE/Device.h
new file mode 100644
index 0000000..4bc58ff
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Device.h
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Device.h: Implements the egl::Device class, representing the abstract
+// device. Implements EGLDevice.
+
+#ifndef LIBANGLE_DEVICE_H_
+#define LIBANGLE_DEVICE_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Display.h"
+
+namespace rx
+{
+class DeviceImpl;
+}
+
+namespace egl
+{
+class Device final : angle::NonCopyable
+{
+  public:
+    virtual ~Device();
+
+    Error getDevice(EGLAttrib *value);
+    Display *getOwningDisplay() { return mOwningDisplay; };
+    EGLint getType();
+
+    const DeviceExtensions &getExtensions() const;
+    const std::string &getExtensionString() const;
+
+    rx::DeviceImpl *getImplementation() { return mImplementation; }
+
+    static egl::Error CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice);
+    static egl::Error CreateDevice(Display *owningDisplay,
+                                   rx::DeviceImpl *impl,
+                                   Device **outDevice);
+
+    static bool IsValidDevice(Device *device);
+
+  private:
+    Device(Display *owningDisplay, rx::DeviceImpl *impl);
+    void initDeviceExtensions();
+
+    Display *mOwningDisplay;
+    rx::DeviceImpl *mImplementation;
+
+    DeviceExtensions mDeviceExtensions;
+    std::string mDeviceExtensionString;
+};
+
+}
+
+#endif   // LIBANGLE_DEVICE_H_
diff --git a/src/third_party/angle/src/libANGLE/Display.cpp b/src/third_party/angle/src/libANGLE/Display.cpp
new file mode 100644
index 0000000..d67bdd2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Display.cpp
@@ -0,0 +1,1056 @@
+//
+// 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.
+//
+
+// Display.cpp: Implements the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#include "libANGLE/Display.h"
+
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <sstream>
+#include <vector>
+
+#include <platform/Platform.h>
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/renderer/ImageImpl.h"
+#include "third_party/trace_event/trace_event.h"
+
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+#   include "libANGLE/renderer/d3d/DisplayD3D.h"
+#endif
+
+#if defined(ANGLE_ENABLE_OPENGL)
+#   if defined(ANGLE_PLATFORM_WINDOWS)
+#       include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+#   elif defined(ANGLE_USE_X11)
+#       include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#   elif defined(ANGLE_PLATFORM_APPLE)
+#       include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
+#   elif defined(ANGLE_USE_OZONE)
+#       include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+#   elif defined(ANGLE_PLATFORM_ANDROID)
+#       include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
+#   else
+#       error Unsupported OpenGL platform.
+#   endif
+#endif
+
+#if defined(ANGLE_ENABLE_NULL)
+#include "libANGLE/renderer/null/DisplayNULL.h"
+#endif  // defined(ANGLE_ENABLE_NULL)
+
+#if defined(ANGLE_ENABLE_VULKAN)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+#include "libANGLE/renderer/vulkan/win32/DisplayVkWin32.h"
+#elif defined(ANGLE_PLATFORM_LINUX)
+#include "libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h"
+#else
+#error Unsupported Vulkan platform.
+#endif
+#endif  // defined(ANGLE_ENABLE_VULKAN)
+
+namespace egl
+{
+
+namespace
+{
+
+typedef std::map<EGLNativeWindowType, Surface*> WindowSurfaceMap;
+// Get a map of all EGL window surfaces to validate that no window has more than one EGL surface
+// associated with it.
+static WindowSurfaceMap *GetWindowSurfaces()
+{
+    static WindowSurfaceMap windowSurfaces;
+    return &windowSurfaces;
+}
+
+typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap;
+static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
+{
+    static ANGLEPlatformDisplayMap displays;
+    return &displays;
+}
+
+typedef std::map<Device *, Display *> DevicePlatformDisplayMap;
+static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
+{
+    static DevicePlatformDisplayMap displays;
+    return &displays;
+}
+
+rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState &state)
+{
+    rx::DisplayImpl *impl = nullptr;
+
+    switch (eglDevice->getType())
+    {
+#if defined(ANGLE_ENABLE_D3D11)
+        case EGL_D3D11_DEVICE_ANGLE:
+            impl = new rx::DisplayD3D(state);
+            break;
+#endif
+#if defined(ANGLE_ENABLE_D3D9)
+        case EGL_D3D9_DEVICE_ANGLE:
+            // Currently the only way to get EGLDeviceEXT representing a D3D9 device
+            // is to retrieve one from an already-existing EGLDisplay.
+            // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT,
+            // the already-existing display should be returned.
+            // Therefore this codepath to create a new display from the device
+            // should never be hit.
+            UNREACHABLE();
+            break;
+#endif
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    ASSERT(impl != nullptr);
+    return impl;
+}
+
+rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap, const DisplayState &state)
+{
+    rx::DisplayImpl *impl = nullptr;
+    EGLAttrib displayType =
+        attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+    switch (displayType)
+    {
+        case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+            // Default to D3D displays
+            impl = new rx::DisplayD3D(state);
+#elif defined(ANGLE_USE_X11)
+            impl = new rx::DisplayGLX(state);
+#elif defined(ANGLE_PLATFORM_APPLE)
+            impl = new rx::DisplayCGL(state);
+#elif defined(ANGLE_USE_OZONE)
+            impl = new rx::DisplayOzone(state);
+#elif defined(ANGLE_PLATFORM_ANDROID)
+            impl = new rx::DisplayAndroid(state);
+#else
+            // No display available
+            UNREACHABLE();
+#endif
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+        case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+            impl = new rx::DisplayD3D(state);
+#else
+            // A D3D display was requested on a platform that doesn't support it
+            UNREACHABLE();
+#endif
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+#if defined(ANGLE_ENABLE_OPENGL)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+            impl = new rx::DisplayWGL(state);
+#elif defined(ANGLE_USE_X11)
+            impl = new rx::DisplayGLX(state);
+#elif defined(ANGLE_PLATFORM_APPLE)
+            impl = new rx::DisplayCGL(state);
+#elif defined(ANGLE_USE_OZONE)
+            // This might work but has never been tried, so disallow for now.
+            impl = nullptr;
+#elif defined(ANGLE_PLATFORM_ANDROID)
+            // No GL support on this platform, fail display creation.
+            impl = nullptr;
+#else
+#error Unsupported OpenGL platform.
+#endif
+#else
+            // No display available
+            UNREACHABLE();
+#endif  // defined(ANGLE_ENABLE_OPENGL)
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+#if defined(ANGLE_ENABLE_OPENGL)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+            impl = new rx::DisplayWGL(state);
+#elif defined(ANGLE_USE_X11)
+            impl = new rx::DisplayGLX(state);
+#elif defined(ANGLE_USE_OZONE)
+            impl = new rx::DisplayOzone(state);
+#elif defined(ANGLE_PLATFORM_ANDROID)
+            impl = new rx::DisplayAndroid(state);
+#else
+            // No GLES support on this platform, fail display creation.
+            impl = nullptr;
+#endif
+#endif  // defined(ANGLE_ENABLE_OPENGL)
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+#if defined(ANGLE_ENABLE_VULKAN)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+            impl = new rx::DisplayVkWin32(state);
+#elif defined(ANGLE_PLATFORM_LINUX)
+            impl = new rx::DisplayVkXcb(state);
+#else
+#error Unsupported Vulkan platform.
+#endif
+#else
+            // No display available
+            UNREACHABLE();
+#endif  // defined(ANGLE_ENABLE_VULKAN)
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
+#if defined(ANGLE_ENABLE_NULL)
+            impl = new rx::DisplayNULL(state);
+#else
+            // No display available
+            UNREACHABLE();
+#endif  // defined(ANGLE_ENABLE_NULL)
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    return impl;
+}
+
+void Display_logError(angle::PlatformMethods *platform, const char *errorMessage)
+{
+    gl::Trace(gl::LOG_ERR, errorMessage);
+}
+
+void Display_logWarning(angle::PlatformMethods *platform, const char *warningMessage)
+{
+    gl::Trace(gl::LOG_WARN, warningMessage);
+}
+
+void Display_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
+{
+    // Uncomment to get info spam
+    // gl::Trace(gl::LOG_WARN, infoMessage);
+}
+
+void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)
+{
+    angle::PlatformMethods *platformMethods = ANGLEPlatformCurrent();
+    if (platformMethods->logError != angle::ANGLE_logError)
+    {
+        // Don't reset pre-set Platform to Default
+        return;
+    }
+
+    ANGLEResetDisplayPlatform(display);
+    platformMethods->logError   = Display_logError;
+    platformMethods->logWarning = Display_logWarning;
+    platformMethods->logInfo    = Display_logInfo;
+}
+
+}  // anonymous namespace
+
+Display *Display::GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
+                                              const AttributeMap &attribMap)
+{
+    Display *display = nullptr;
+
+    ANGLEPlatformDisplayMap *displays            = GetANGLEPlatformDisplayMap();
+    ANGLEPlatformDisplayMap::const_iterator iter = displays->find(nativeDisplay);
+    if (iter != displays->end())
+    {
+        display = iter->second;
+    }
+
+    if (display == nullptr)
+    {
+        // Validate the native display
+        if (!Display::isValidNativeDisplay(nativeDisplay))
+        {
+            return nullptr;
+        }
+
+        display = new Display(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, nullptr);
+        displays->insert(std::make_pair(nativeDisplay, display));
+    }
+
+    // Apply new attributes if the display is not initialized yet.
+    if (!display->isInitialized())
+    {
+        rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap, display->getState());
+        if (impl == nullptr)
+        {
+            // No valid display implementation for these attributes
+            return nullptr;
+        }
+
+        display->setAttributes(impl, attribMap);
+    }
+
+    return display;
+}
+
+Display *Display::GetDisplayFromDevice(Device *device)
+{
+    Display *display = nullptr;
+
+    ASSERT(Device::IsValidDevice(device));
+
+    ANGLEPlatformDisplayMap *anglePlatformDisplays   = GetANGLEPlatformDisplayMap();
+    DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
+
+    // First see if this eglDevice is in use by a Display created using ANGLE platform
+    for (auto &displayMapEntry : *anglePlatformDisplays)
+    {
+        egl::Display *iterDisplay = displayMapEntry.second;
+        if (iterDisplay->getDevice() == device)
+        {
+            display = iterDisplay;
+        }
+    }
+
+    if (display == nullptr)
+    {
+        // See if the eglDevice is in use by a Display created using the DEVICE platform
+        DevicePlatformDisplayMap::const_iterator iter = devicePlatformDisplays->find(device);
+        if (iter != devicePlatformDisplays->end())
+        {
+            display = iter->second;
+        }
+    }
+
+    if (display == nullptr)
+    {
+        // Otherwise create a new Display
+        display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, device);
+        devicePlatformDisplays->insert(std::make_pair(device, display));
+    }
+
+    // Apply new attributes if the display is not initialized yet.
+    if (!display->isInitialized())
+    {
+        rx::DisplayImpl *impl = CreateDisplayFromDevice(device, display->getState());
+        display->setAttributes(impl, egl::AttributeMap());
+    }
+
+    return display;
+}
+
+Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
+    : mImplementation(nullptr),
+      mDisplayId(displayId),
+      mAttributeMap(),
+      mConfigSet(),
+      mContextSet(),
+      mStreamSet(),
+      mInitialized(false),
+      mDeviceLost(false),
+      mCaps(),
+      mDisplayExtensions(),
+      mDisplayExtensionString(),
+      mVendorString(),
+      mDevice(eglDevice),
+      mPlatform(platform),
+      mTextureManager(nullptr),
+      mGlobalTextureShareGroupUsers(0)
+{
+}
+
+Display::~Display()
+{
+    terminate();
+
+    if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE)
+    {
+        ANGLEPlatformDisplayMap *displays      = GetANGLEPlatformDisplayMap();
+        ANGLEPlatformDisplayMap::iterator iter = displays->find(mDisplayId);
+        if (iter != displays->end())
+        {
+            displays->erase(iter);
+        }
+    }
+    else if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
+    {
+        DevicePlatformDisplayMap *displays      = GetDevicePlatformDisplayMap();
+        DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
+        if (iter != displays->end())
+        {
+            displays->erase(iter);
+        }
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+
+    SafeDelete(mDevice);
+    SafeDelete(mImplementation);
+}
+
+void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap)
+{
+    ASSERT(!mInitialized);
+
+    ASSERT(impl != nullptr);
+    SafeDelete(mImplementation);
+    mImplementation = impl;
+
+    mAttributeMap = attribMap;
+}
+
+Error Display::initialize()
+{
+    // TODO(jmadill): Store Platform in Display and init here.
+    ANGLESetDefaultDisplayPlatform(this);
+
+    gl::InitializeDebugAnnotations(&mAnnotator);
+
+    SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.DisplayInitializeMS");
+    TRACE_EVENT0("gpu.angle", "egl::Display::initialize");
+
+    ASSERT(mImplementation != nullptr);
+
+    if (isInitialized())
+    {
+        return egl::Error(EGL_SUCCESS);
+    }
+
+    Error error = mImplementation->initialize(this);
+    if (error.isError())
+    {
+        // Log extended error message here
+        ERR() << "ANGLE Display::initialize error " << error.getID() << ": " << error.getMessage();
+        return error;
+    }
+
+    mCaps = mImplementation->getCaps();
+
+    mConfigSet = mImplementation->generateConfigs();
+    if (mConfigSet.size() == 0)
+    {
+        mImplementation->terminate();
+        return Error(EGL_NOT_INITIALIZED);
+    }
+
+    initDisplayExtensions();
+    initVendorString();
+
+    // Populate the Display's EGLDeviceEXT if the Display wasn't created using one
+    if (mPlatform != EGL_PLATFORM_DEVICE_EXT)
+    {
+        if (mDisplayExtensions.deviceQuery)
+        {
+            rx::DeviceImpl *impl = nullptr;
+            ANGLE_TRY(mImplementation->getDevice(&impl));
+            ANGLE_TRY(Device::CreateDevice(this, impl, &mDevice));
+        }
+        else
+        {
+            mDevice = nullptr;
+        }
+    }
+    else
+    {
+        // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
+        // an external device
+        ASSERT(mDevice != nullptr);
+    }
+
+    mInitialized = true;
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+void Display::terminate()
+{
+    makeCurrent(nullptr, nullptr, nullptr);
+
+    while (!mContextSet.empty())
+    {
+        destroyContext(*mContextSet.begin());
+    }
+
+    // The global texture manager should be deleted with the last context that uses it.
+    ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr);
+
+    while (!mImageSet.empty())
+    {
+        destroyImage(*mImageSet.begin());
+    }
+
+    while (!mStreamSet.empty())
+    {
+        destroyStream(*mStreamSet.begin());
+    }
+
+    while (!mState.surfaceSet.empty())
+    {
+        destroySurface(*mState.surfaceSet.begin());
+    }
+
+    mConfigSet.clear();
+
+    if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr)
+    {
+        // Don't delete the device if it was created externally using eglCreateDeviceANGLE
+        // We also shouldn't set it to null in case eglInitialize() is called again later
+        SafeDelete(mDevice);
+    }
+
+    mImplementation->terminate();
+
+    mDeviceLost = false;
+
+    mInitialized = false;
+
+    gl::UninitializeDebugAnnotations();
+
+    // TODO(jmadill): Store Platform in Display and deinit here.
+    ANGLEResetDisplayPlatform(this);
+}
+
+std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs) const
+{
+    return mConfigSet.filter(attribs);
+}
+
+Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
+                                   Surface **outSurface)
+{
+    if (mImplementation->testDeviceLost())
+    {
+        ANGLE_TRY(restoreLostDevice());
+    }
+
+    std::unique_ptr<Surface> surface(
+        new WindowSurface(mImplementation, configuration, window, attribs));
+    ANGLE_TRY(surface->initialize(*this));
+
+    ASSERT(outSurface != nullptr);
+    *outSurface = surface.release();
+    mState.surfaceSet.insert(*outSurface);
+
+    WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+    ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
+    windowSurfaces->insert(std::make_pair(window, *outSurface));
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface)
+{
+    ASSERT(isInitialized());
+
+    if (mImplementation->testDeviceLost())
+    {
+        ANGLE_TRY(restoreLostDevice());
+    }
+
+    std::unique_ptr<Surface> surface(new PbufferSurface(mImplementation, configuration, attribs));
+    ANGLE_TRY(surface->initialize(*this));
+
+    ASSERT(outSurface != nullptr);
+    *outSurface = surface.release();
+    mState.surfaceSet.insert(*outSurface);
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::createPbufferFromClientBuffer(const Config *configuration,
+                                             EGLenum buftype,
+                                             EGLClientBuffer clientBuffer,
+                                             const AttributeMap &attribs,
+                                             Surface **outSurface)
+{
+    ASSERT(isInitialized());
+
+    if (mImplementation->testDeviceLost())
+    {
+        ANGLE_TRY(restoreLostDevice());
+    }
+
+    std::unique_ptr<Surface> surface(
+        new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs));
+    ANGLE_TRY(surface->initialize(*this));
+
+    ASSERT(outSurface != nullptr);
+    *outSurface = surface.release();
+    mState.surfaceSet.insert(*outSurface);
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs,
+                                   Surface **outSurface)
+{
+    ASSERT(isInitialized());
+
+    if (mImplementation->testDeviceLost())
+    {
+        ANGLE_TRY(restoreLostDevice());
+    }
+
+    std::unique_ptr<Surface> surface(
+        new PixmapSurface(mImplementation, configuration, nativePixmap, attribs));
+    ANGLE_TRY(surface->initialize(*this));
+
+    ASSERT(outSurface != nullptr);
+    *outSurface = surface.release();
+    mState.surfaceSet.insert(*outSurface);
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::createImage(gl::Context *context,
+                           EGLenum target,
+                           EGLClientBuffer buffer,
+                           const AttributeMap &attribs,
+                           Image **outImage)
+{
+    ASSERT(isInitialized());
+
+    if (mImplementation->testDeviceLost())
+    {
+        ANGLE_TRY(restoreLostDevice());
+    }
+
+    egl::ImageSibling *sibling = nullptr;
+    if (IsTextureTarget(target))
+    {
+        sibling = context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+    }
+    else if (IsRenderbufferTarget(target))
+    {
+        sibling = context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+    ASSERT(sibling != nullptr);
+
+    std::unique_ptr<Image> imagePtr(new Image(mImplementation, target, sibling, attribs));
+    ANGLE_TRY(imagePtr->initialize());
+
+    Image *image = imagePtr.release();
+
+    ASSERT(outImage != nullptr);
+    *outImage = image;
+
+    // Add this image to the list of all images and hold a ref to it.
+    image->addRef();
+    mImageSet.insert(image);
+
+    return egl::NoError();
+}
+
+Error Display::createStream(const AttributeMap &attribs, Stream **outStream)
+{
+    ASSERT(isInitialized());
+
+    Stream *stream = new Stream(this, attribs);
+
+    ASSERT(stream != nullptr);
+    mStreamSet.insert(stream);
+
+    ASSERT(outStream != nullptr);
+    *outStream = stream;
+
+    return Error(EGL_SUCCESS);
+}
+
+Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
+                             gl::Context **outContext)
+{
+    ASSERT(isInitialized());
+
+    if (mImplementation->testDeviceLost())
+    {
+        ANGLE_TRY(restoreLostDevice());
+    }
+
+    // This display texture sharing will allow the first context to create the texture share group.
+    bool usingDisplayTextureShareGroup =
+        attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
+    gl::TextureManager *shareTextures = nullptr;
+
+    if (usingDisplayTextureShareGroup)
+    {
+        ASSERT((mTextureManager == nullptr) == (mGlobalTextureShareGroupUsers == 0));
+        if (mTextureManager == nullptr)
+        {
+            mTextureManager = new gl::TextureManager();
+        }
+
+        mGlobalTextureShareGroupUsers++;
+        shareTextures = mTextureManager;
+    }
+
+    gl::Context *context = new gl::Context(mImplementation, configuration, shareContext,
+                                           shareTextures, attribs, mDisplayExtensions);
+
+    ASSERT(context != nullptr);
+    mContextSet.insert(context);
+
+    ASSERT(outContext != nullptr);
+    *outContext = context;
+    return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+{
+    ANGLE_TRY(mImplementation->makeCurrent(drawSurface, readSurface, context));
+
+    if (context != nullptr)
+    {
+        ASSERT(readSurface == drawSurface);
+        context->makeCurrent(this, drawSurface);
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::restoreLostDevice()
+{
+    for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
+    {
+        if ((*ctx)->isResetNotificationEnabled())
+        {
+            // If reset notifications have been requested, application must delete all contexts first
+            return Error(EGL_CONTEXT_LOST);
+        }
+    }
+
+    return mImplementation->restoreLostDevice();
+}
+
+void Display::destroySurface(Surface *surface)
+{
+    if (surface->getType() == EGL_WINDOW_BIT)
+    {
+        WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+        ASSERT(windowSurfaces);
+
+        bool surfaceRemoved = false;
+        for (WindowSurfaceMap::iterator iter = windowSurfaces->begin(); iter != windowSurfaces->end(); iter++)
+        {
+            if (iter->second == surface)
+            {
+                windowSurfaces->erase(iter);
+                surfaceRemoved = true;
+                break;
+            }
+        }
+
+        ASSERT(surfaceRemoved);
+    }
+
+    mState.surfaceSet.erase(surface);
+    surface->onDestroy(this);
+}
+
+void Display::destroyImage(egl::Image *image)
+{
+    auto iter = mImageSet.find(image);
+    ASSERT(iter != mImageSet.end());
+    (*iter)->release();
+    mImageSet.erase(iter);
+}
+
+void Display::destroyStream(egl::Stream *stream)
+{
+    mStreamSet.erase(stream);
+    SafeDelete(stream);
+}
+
+void Display::destroyContext(gl::Context *context)
+{
+    if (context->usingDisplayTextureShareGroup())
+    {
+        ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr);
+        if (mGlobalTextureShareGroupUsers == 1)
+        {
+            // If this is the last context using the global share group, destroy the global texture
+            // manager so that the textures can be destroyed while a context still exists
+            mTextureManager->release(context);
+            mTextureManager = nullptr;
+        }
+        mGlobalTextureShareGroupUsers--;
+    }
+
+    context->destroy(this);
+    mContextSet.erase(context);
+    SafeDelete(context);
+}
+
+bool Display::isDeviceLost() const
+{
+    ASSERT(isInitialized());
+    return mDeviceLost;
+}
+
+bool Display::testDeviceLost()
+{
+    ASSERT(isInitialized());
+
+    if (!mDeviceLost && mImplementation->testDeviceLost())
+    {
+        notifyDeviceLost();
+    }
+
+    return mDeviceLost;
+}
+
+void Display::notifyDeviceLost()
+{
+    if (mDeviceLost)
+    {
+        return;
+    }
+
+    for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
+    {
+        (*context)->markContextLost();
+    }
+
+    mDeviceLost = true;
+}
+
+Error Display::waitClient() const
+{
+    return mImplementation->waitClient();
+}
+
+Error Display::waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const
+{
+    return mImplementation->waitNative(engine, drawSurface, readSurface);
+}
+
+const Caps &Display::getCaps() const
+{
+    return mCaps;
+}
+
+bool Display::isInitialized() const
+{
+    return mInitialized;
+}
+
+bool Display::isValidConfig(const Config *config) const
+{
+    return mConfigSet.contains(config);
+}
+
+bool Display::isValidContext(const gl::Context *context) const
+{
+    return mContextSet.find(const_cast<gl::Context *>(context)) != mContextSet.end();
+}
+
+bool Display::isValidSurface(const Surface *surface) const
+{
+    return mState.surfaceSet.find(const_cast<Surface *>(surface)) != mState.surfaceSet.end();
+}
+
+bool Display::isValidImage(const Image *image) const
+{
+    return mImageSet.find(const_cast<Image *>(image)) != mImageSet.end();
+}
+
+bool Display::isValidStream(const Stream *stream) const
+{
+    return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end();
+}
+
+bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
+{
+    WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+    ASSERT(windowSurfaces);
+
+    return windowSurfaces->find(window) != windowSurfaces->end();
+}
+
+static ClientExtensions GenerateClientExtensions()
+{
+    ClientExtensions extensions;
+
+    extensions.clientExtensions = true;
+    extensions.platformBase = true;
+    extensions.platformANGLE = true;
+
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+    extensions.platformANGLED3D = true;
+    extensions.platformDevice   = true;
+#endif
+
+#if defined(ANGLE_ENABLE_OPENGL)
+    extensions.platformANGLEOpenGL = true;
+#endif
+
+#if defined(ANGLE_ENABLE_NULL)
+    extensions.platformANGLENULL = true;
+#endif
+
+#if defined(ANGLE_ENABLE_D3D11)
+    extensions.deviceCreation      = true;
+    extensions.deviceCreationD3D11 = true;
+    extensions.experimentalPresentPath = true;
+#endif
+
+#if defined(ANGLE_ENABLE_VULKAN)
+    extensions.platformANGLEVulkan = true;
+#endif
+
+#if defined(ANGLE_USE_X11)
+    extensions.x11Visual = true;
+#endif
+
+    extensions.clientGetAllProcAddresses = true;
+
+    return extensions;
+}
+
+template <typename T>
+static std::string GenerateExtensionsString(const T &extensions)
+{
+    std::vector<std::string> extensionsVector = extensions.getStrings();
+
+    std::ostringstream stream;
+    std::copy(extensionsVector.begin(), extensionsVector.end(), std::ostream_iterator<std::string>(stream, " "));
+    return stream.str();
+}
+
+const ClientExtensions &Display::getClientExtensions()
+{
+    static const ClientExtensions clientExtensions = GenerateClientExtensions();
+    return clientExtensions;
+}
+
+const std::string &Display::getClientExtensionString()
+{
+    static const std::string clientExtensionsString = GenerateExtensionsString(getClientExtensions());
+    return clientExtensionsString;
+}
+
+void Display::initDisplayExtensions()
+{
+    mDisplayExtensions = mImplementation->getExtensions();
+
+    // Some extensions are always available because they are implemented in the EGL layer.
+    mDisplayExtensions.createContext        = true;
+    mDisplayExtensions.createContextNoError = true;
+    mDisplayExtensions.createContextWebGLCompatibility = true;
+    mDisplayExtensions.createContextBindGeneratesResource = true;
+    mDisplayExtensions.createContextClientArrays          = true;
+    mDisplayExtensions.pixelFormatFloat                   = true;
+
+    // Force EGL_KHR_get_all_proc_addresses on.
+    mDisplayExtensions.getAllProcAddresses = true;
+
+    mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
+}
+
+bool Display::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    return mImplementation->isValidNativeWindow(window);
+}
+
+Error Display::validateClientBuffer(const Config *configuration,
+                                    EGLenum buftype,
+                                    EGLClientBuffer clientBuffer,
+                                    const AttributeMap &attribs)
+{
+    return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+}
+
+bool Display::isValidDisplay(const egl::Display *display)
+{
+    const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
+    for (const auto &displayPair : *anglePlatformDisplayMap)
+    {
+        if (displayPair.second == display)
+        {
+            return true;
+        }
+    }
+
+    const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap();
+    for (const auto &displayPair : *devicePlatformDisplayMap)
+    {
+        if (displayPair.second == display)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool Display::isValidNativeDisplay(EGLNativeDisplayType display)
+{
+    // TODO(jmadill): handle this properly
+    if (display == EGL_DEFAULT_DISPLAY)
+    {
+        return true;
+    }
+
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    if (display == EGL_SOFTWARE_DISPLAY_ANGLE ||
+        display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+        display == EGL_D3D11_ONLY_DISPLAY_ANGLE)
+    {
+        return true;
+    }
+    return (WindowFromDC(display) != nullptr);
+#else
+    return true;
+#endif
+}
+
+void Display::initVendorString()
+{
+    mVendorString = mImplementation->getVendorString();
+}
+
+const DisplayExtensions &Display::getExtensions() const
+{
+    return mDisplayExtensions;
+}
+
+const std::string &Display::getExtensionString() const
+{
+    return mDisplayExtensionString;
+}
+
+const std::string &Display::getVendorString() const
+{
+    return mVendorString;
+}
+
+Device *Display::getDevice() const
+{
+    return mDevice;
+}
+
+gl::Version Display::getMaxSupportedESVersion() const
+{
+    return mImplementation->getMaxSupportedESVersion();
+}
+}  // namespace egl
diff --git a/src/third_party/angle/src/libANGLE/Display.h b/src/third_party/angle/src/libANGLE/Display.h
new file mode 100644
index 0000000..36f8513
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Display.h
@@ -0,0 +1,183 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Display.h: Defines the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#ifndef LIBANGLE_DISPLAY_H_
+#define LIBANGLE_DISPLAY_H_
+
+#include <set>
+#include <vector>
+
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/LoggingAnnotator.h"
+#include "libANGLE/Version.h"
+
+namespace gl
+{
+class Context;
+class TextureManager;
+}
+
+namespace rx
+{
+class DisplayImpl;
+}
+
+namespace egl
+{
+class Device;
+class Image;
+class Surface;
+class Stream;
+
+using SurfaceSet = std::set<Surface *>;
+
+struct DisplayState final : private angle::NonCopyable
+{
+    SurfaceSet surfaceSet;
+};
+
+class Display final : angle::NonCopyable
+{
+  public:
+    ~Display();
+
+    Error initialize();
+    void terminate();
+
+    static egl::Display *GetDisplayFromDevice(Device *device);
+    static egl::Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
+                                                     const AttributeMap &attribMap);
+
+    static const ClientExtensions &getClientExtensions();
+    static const std::string &getClientExtensionString();
+
+    std::vector<const Config*> getConfigs(const egl::AttributeMap &attribs) const;
+
+    Error createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
+                              Surface **outSurface);
+    Error createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface);
+    Error createPbufferFromClientBuffer(const Config *configuration,
+                                        EGLenum buftype,
+                                        EGLClientBuffer clientBuffer,
+                                        const AttributeMap &attribs,
+                                        Surface **outSurface);
+    Error createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs,
+                              Surface **outSurface);
+
+    Error createImage(gl::Context *context,
+                      EGLenum target,
+                      EGLClientBuffer buffer,
+                      const AttributeMap &attribs,
+                      Image **outImage);
+
+    Error createStream(const AttributeMap &attribs, Stream **outStream);
+
+    Error createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
+                        gl::Context **outContext);
+
+    Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context);
+
+    void destroySurface(egl::Surface *surface);
+    void destroyImage(egl::Image *image);
+    void destroyStream(egl::Stream *stream);
+    void destroyContext(gl::Context *context);
+
+    bool isInitialized() const;
+    bool isValidConfig(const Config *config) const;
+    bool isValidContext(const gl::Context *context) const;
+    bool isValidSurface(const egl::Surface *surface) const;
+    bool isValidImage(const Image *image) const;
+    bool isValidStream(const Stream *stream) const;
+    bool isValidNativeWindow(EGLNativeWindowType window) const;
+
+    Error validateClientBuffer(const Config *configuration,
+                               EGLenum buftype,
+                               EGLClientBuffer clientBuffer,
+                               const AttributeMap &attribs);
+
+    static bool isValidDisplay(const egl::Display *display);
+    static bool isValidNativeDisplay(EGLNativeDisplayType display);
+    static bool hasExistingWindowSurface(EGLNativeWindowType window);
+
+    bool isDeviceLost() const;
+    bool testDeviceLost();
+    void notifyDeviceLost();
+
+    Error waitClient() const;
+    Error waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const;
+
+    const Caps &getCaps() const;
+
+    const DisplayExtensions &getExtensions() const;
+    const std::string &getExtensionString() const;
+    const std::string &getVendorString() const;
+
+    const AttributeMap &getAttributeMap() const { return mAttributeMap; }
+    EGLNativeDisplayType getNativeDisplayId() const { return mDisplayId; }
+
+    rx::DisplayImpl *getImplementation() const { return mImplementation; }
+    Device *getDevice() const;
+    EGLenum getPlatform() const { return mPlatform; }
+
+    gl::Version getMaxSupportedESVersion() const;
+
+    const DisplayState &getState() const { return mState; }
+
+  private:
+    Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice);
+
+    void setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap);
+
+    Error restoreLostDevice();
+
+    void initDisplayExtensions();
+    void initVendorString();
+
+    DisplayState mState;
+    rx::DisplayImpl *mImplementation;
+
+    EGLNativeDisplayType mDisplayId;
+    AttributeMap mAttributeMap;
+
+    ConfigSet mConfigSet;
+
+    typedef std::set<gl::Context*> ContextSet;
+    ContextSet mContextSet;
+
+    typedef std::set<Image *> ImageSet;
+    ImageSet mImageSet;
+
+    typedef std::set<Stream *> StreamSet;
+    StreamSet mStreamSet;
+
+    bool mInitialized;
+    bool mDeviceLost;
+
+    Caps mCaps;
+
+    DisplayExtensions mDisplayExtensions;
+    std::string mDisplayExtensionString;
+
+    std::string mVendorString;
+
+    Device *mDevice;
+    EGLenum mPlatform;
+    angle::LoggingAnnotator mAnnotator;
+
+    gl::TextureManager *mTextureManager;
+    size_t mGlobalTextureShareGroupUsers;
+};
+
+}  // namespace egl
+
+#endif   // LIBANGLE_DISPLAY_H_
diff --git a/src/third_party/angle/src/libANGLE/Error.cpp b/src/third_party/angle/src/libANGLE/Error.cpp
new file mode 100644
index 0000000..33cab98
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Error.cpp
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Error.cpp: Implements the egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+#include <cstdarg>
+
+namespace gl
+{
+
+Error::Error(GLenum errorCode, std::string &&message)
+    : mCode(errorCode), mID(errorCode), mMessage(new std::string(std::move(message)))
+{
+}
+
+Error::Error(GLenum errorCode, const char *msg, ...) : mCode(errorCode), mID(errorCode)
+{
+    va_list vararg;
+    va_start(vararg, msg);
+    createMessageString();
+    *mMessage = FormatString(msg, vararg);
+    va_end(vararg);
+}
+
+Error::Error(GLenum errorCode, GLuint id, const char *msg, ...) : mCode(errorCode), mID(id)
+{
+    va_list vararg;
+    va_start(vararg, msg);
+    createMessageString();
+    *mMessage = FormatString(msg, vararg);
+    va_end(vararg);
+}
+
+void Error::createMessageString() const
+{
+    if (!mMessage)
+    {
+        mMessage.reset(new std::string);
+    }
+}
+
+const std::string &Error::getMessage() const
+{
+    createMessageString();
+    return *mMessage;
+}
+
+bool Error::operator==(const Error &other) const
+{
+    if (mCode != other.mCode)
+        return false;
+
+    // TODO(jmadill): Compare extended error codes instead of strings.
+    if ((!mMessage || !other.mMessage) && (!mMessage != !other.mMessage))
+        return false;
+
+    return (*mMessage == *other.mMessage);
+}
+
+bool Error::operator!=(const Error &other) const
+{
+    return !(*this == other);
+}
+
+std::ostream &operator<<(std::ostream &os, const Error &err)
+{
+    return gl::FmtHexShort(os, err.getCode());
+}
+
+namespace priv
+{
+template <GLenum EnumT>
+ErrorStream<EnumT>::ErrorStream()
+{
+}
+
+template <GLenum EnumT>
+ErrorStream<EnumT>::operator gl::Error()
+{
+    return Error(EnumT, mErrorStream.str().c_str());
+}
+
+template class ErrorStream<GL_OUT_OF_MEMORY>;
+template class ErrorStream<GL_INVALID_OPERATION>;
+
+}  // namespace priv
+
+}  // namespace gl
+
+namespace egl
+{
+
+Error::Error(EGLint errorCode, const char *msg, ...) : mCode(errorCode), mID(0)
+{
+    va_list vararg;
+    va_start(vararg, msg);
+    createMessageString();
+    *mMessage = FormatString(msg, vararg);
+    va_end(vararg);
+}
+
+Error::Error(EGLint errorCode, EGLint id, const char *msg, ...) : mCode(errorCode), mID(id)
+{
+    va_list vararg;
+    va_start(vararg, msg);
+    createMessageString();
+    *mMessage = FormatString(msg, vararg);
+    va_end(vararg);
+}
+
+Error::Error(EGLint errorCode, EGLint id, const std::string &msg)
+    : mCode(errorCode), mID(id), mMessage(new std::string(msg))
+{
+}
+
+void Error::createMessageString() const
+{
+    if (!mMessage)
+    {
+        mMessage.reset(new std::string);
+    }
+}
+
+const std::string &Error::getMessage() const
+{
+    createMessageString();
+    return *mMessage;
+}
+
+std::ostream &operator<<(std::ostream &os, const Error &err)
+{
+    return gl::FmtHexShort(os, err.getCode());
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/Error.h b/src/third_party/angle/src/libANGLE/Error.h
new file mode 100644
index 0000000..bce4cd2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Error.h
@@ -0,0 +1,221 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Error.h: Defines the egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#ifndef LIBANGLE_ERROR_H_
+#define LIBANGLE_ERROR_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include <EGL/egl.h>
+
+#include <memory>
+#include <ostream>
+#include <string>
+
+namespace angle
+{
+template <typename ErrorT, typename ResultT, typename ErrorBaseT, ErrorBaseT NoErrorVal>
+class ErrorOrResultBase
+{
+  public:
+    ErrorOrResultBase(const ErrorT &error) : mError(error) {}
+    ErrorOrResultBase(ErrorT &&error) : mError(std::move(error)) {}
+
+    ErrorOrResultBase(ResultT &&result) : mError(NoErrorVal), mResult(std::forward<ResultT>(result))
+    {
+    }
+
+    ErrorOrResultBase(const ResultT &result) : mError(NoErrorVal), mResult(result) {}
+
+    bool isError() const { return mError.isError(); }
+    const ErrorT &getError() const { return mError; }
+    ResultT &&getResult() { return std::move(mResult); }
+
+  private:
+    ErrorT mError;
+    ResultT mResult;
+};
+}  // namespace angle
+
+namespace gl
+{
+
+class Error final
+{
+  public:
+    explicit inline Error(GLenum errorCode);
+    Error(GLenum errorCode, std::string &&msg);
+    Error(GLenum errorCode, const char *msg, ...);
+    Error(GLenum errorCode, GLuint id, const char *msg, ...);
+    inline Error(const Error &other);
+    inline Error(Error &&other);
+
+    inline Error &operator=(const Error &other);
+    inline Error &operator=(Error &&other);
+
+    inline GLenum getCode() const;
+    inline GLuint getID() const;
+    inline bool isError() const;
+
+    const std::string &getMessage() const;
+
+    // Useful for mocking and testing
+    bool operator==(const Error &other) const;
+    bool operator!=(const Error &other) const;
+
+  private:
+    void createMessageString() const;
+
+    friend std::ostream &operator<<(std::ostream &os, const Error &err);
+
+    GLenum mCode;
+    GLuint mID;
+    mutable std::unique_ptr<std::string> mMessage;
+};
+
+template <typename ResultT>
+using ErrorOrResult = angle::ErrorOrResultBase<Error, ResultT, GLenum, GL_NO_ERROR>;
+
+namespace priv
+{
+template <GLenum EnumT>
+class ErrorStream : angle::NonCopyable
+{
+  public:
+    ErrorStream();
+
+    template <typename T>
+    ErrorStream &operator<<(T value);
+
+    operator Error();
+
+    template <typename T>
+    operator ErrorOrResult<T>()
+    {
+        return static_cast<Error>(*this);
+    }
+
+  private:
+    std::ostringstream mErrorStream;
+};
+
+// These convience methods for HRESULTS (really long) are used all over the place in the D3D
+// back-ends.
+#if defined(ANGLE_PLATFORM_WINDOWS)
+template <>
+template <>
+inline ErrorStream<GL_OUT_OF_MEMORY> &ErrorStream<GL_OUT_OF_MEMORY>::operator<<(HRESULT hresult)
+{
+    mErrorStream << "HRESULT: 0x" << std::ios::hex << hresult;
+    return *this;
+}
+
+template <>
+template <>
+inline ErrorStream<GL_INVALID_OPERATION> &ErrorStream<GL_INVALID_OPERATION>::operator<<(
+    HRESULT hresult)
+{
+    mErrorStream << "HRESULT: 0x" << std::ios::hex << hresult;
+    return *this;
+}
+#endif  // defined(ANGLE_PLATFORM_WINDOWS)
+
+template <GLenum EnumT>
+template <typename T>
+ErrorStream<EnumT> &ErrorStream<EnumT>::operator<<(T value)
+{
+    mErrorStream << value;
+    return *this;
+}
+
+}  // namespace priv
+
+using OutOfMemory   = priv::ErrorStream<GL_OUT_OF_MEMORY>;
+using InternalError = priv::ErrorStream<GL_INVALID_OPERATION>;
+
+inline Error NoError()
+{
+    return Error(GL_NO_ERROR);
+}
+
+}  // namespace gl
+
+namespace egl
+{
+
+class Error final
+{
+  public:
+    explicit inline Error(EGLint errorCode);
+    Error(EGLint errorCode, const char *msg, ...);
+    Error(EGLint errorCode, EGLint id, const char *msg, ...);
+    Error(EGLint errorCode, EGLint id, const std::string &msg);
+    inline Error(const Error &other);
+    inline Error(Error &&other);
+
+    inline Error &operator=(const Error &other);
+    inline Error &operator=(Error &&other);
+
+    inline EGLint getCode() const;
+    inline EGLint getID() const;
+    inline bool isError() const;
+
+    const std::string &getMessage() const;
+
+  private:
+    void createMessageString() const;
+
+    friend std::ostream &operator<<(std::ostream &os, const Error &err);
+
+    EGLint mCode;
+    EGLint mID;
+    mutable std::unique_ptr<std::string> mMessage;
+};
+
+inline Error NoError()
+{
+    return Error(EGL_SUCCESS);
+}
+
+template <typename ResultT>
+using ErrorOrResult = angle::ErrorOrResultBase<Error, ResultT, EGLint, EGL_SUCCESS>;
+
+}  // namespace egl
+
+#define ANGLE_CONCAT1(x, y) x##y
+#define ANGLE_CONCAT2(x, y) ANGLE_CONCAT1(x, y)
+#define ANGLE_LOCAL_VAR ANGLE_CONCAT2(_localVar, __LINE__)
+
+#define ANGLE_TRY(EXPR)                \
+    {                                  \
+        auto ANGLE_LOCAL_VAR = EXPR;   \
+        if (ANGLE_LOCAL_VAR.isError()) \
+        {                              \
+            return ANGLE_LOCAL_VAR;    \
+        }                              \
+    }                                  \
+    ANGLE_EMPTY_STATEMENT
+
+#define ANGLE_TRY_RESULT(EXPR, RESULT)         \
+    {                                          \
+        auto ANGLE_LOCAL_VAR = EXPR;           \
+        if (ANGLE_LOCAL_VAR.isError())         \
+        {                                      \
+            return ANGLE_LOCAL_VAR.getError(); \
+        }                                      \
+        RESULT = ANGLE_LOCAL_VAR.getResult();  \
+    }                                          \
+    ANGLE_EMPTY_STATEMENT
+
+#undef ANGLE_LOCAL_VAR
+#undef ANGLE_CONCAT2
+#undef ANGLE_CONCAT1
+
+#include "Error.inl"
+
+#endif // LIBANGLE_ERROR_H_
diff --git a/src/third_party/angle/src/libANGLE/Error.inl b/src/third_party/angle/src/libANGLE/Error.inl
new file mode 100644
index 0000000..900fc5f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Error.inl
@@ -0,0 +1,159 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Error.inl: Inline definitions of egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#include "common/angleutils.h"
+
+#include <cstdarg>
+
+namespace gl
+{
+
+Error::Error(GLenum errorCode)
+    : mCode(errorCode),
+      mID(errorCode)
+{
+}
+
+Error::Error(const Error &other)
+    : mCode(other.mCode),
+      mID(other.mID)
+{
+    if (other.mMessage)
+    {
+        createMessageString();
+        *mMessage = *(other.mMessage);
+    }
+}
+
+Error::Error(Error &&other)
+    : mCode(other.mCode),
+      mID(other.mID),
+      mMessage(std::move(other.mMessage))
+{
+}
+
+Error &Error::operator=(const Error &other)
+{
+    mCode = other.mCode;
+    mID = other.mID;
+
+    if (other.mMessage)
+    {
+        createMessageString();
+        *mMessage = *(other.mMessage);
+    }
+    else
+    {
+        mMessage.release();
+    }
+
+    return *this;
+}
+
+Error &Error::operator=(Error &&other)
+{
+    if (this != &other)
+    {
+        mCode = other.mCode;
+        mID = other.mID;
+        mMessage = std::move(other.mMessage);
+    }
+
+    return *this;
+}
+
+GLenum Error::getCode() const
+{
+    return mCode;
+}
+
+GLuint Error::getID() const
+{
+    return mID;
+}
+
+bool Error::isError() const
+{
+    return (mCode != GL_NO_ERROR);
+}
+
+}
+
+namespace egl
+{
+
+Error::Error(EGLint errorCode)
+    : mCode(errorCode),
+      mID(0)
+{
+}
+
+Error::Error(const Error &other)
+    : mCode(other.mCode),
+      mID(other.mID)
+{
+    if (other.mMessage)
+    {
+        createMessageString();
+        *mMessage = *(other.mMessage);
+    }
+}
+
+Error::Error(Error &&other)
+    : mCode(other.mCode),
+      mID(other.mID),
+      mMessage(std::move(other.mMessage))
+{
+}
+
+Error &Error::operator=(const Error &other)
+{
+    mCode = other.mCode;
+    mID = other.mID;
+
+    if (other.mMessage)
+    {
+        createMessageString();
+        *mMessage = *(other.mMessage);
+    }
+    else
+    {
+        mMessage.release();
+    }
+
+    return *this;
+}
+
+Error &Error::operator=(Error &&other)
+{
+    if (this != &other)
+    {
+        mCode = other.mCode;
+        mID = other.mID;
+        mMessage = std::move(other.mMessage);
+    }
+
+    return *this;
+}
+
+EGLint Error::getCode() const
+{
+    return mCode;
+}
+
+EGLint Error::getID() const
+{
+    return mID;
+}
+
+bool Error::isError() const
+{
+    return (mCode != EGL_SUCCESS);
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/Fence.cpp b/src/third_party/angle/src/libANGLE/Fence.cpp
new file mode 100644
index 0000000..2e1c590
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Fence.cpp
@@ -0,0 +1,126 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
+// extension and GLES3 sync objects.
+
+#include "libANGLE/Fence.h"
+
+#include "angle_gl.h"
+
+#include "common/utilities.h"
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace gl
+{
+
+FenceNV::FenceNV(rx::FenceNVImpl *impl)
+    : mFence(impl),
+      mIsSet(false),
+      mStatus(GL_FALSE),
+      mCondition(GL_NONE)
+{
+}
+
+FenceNV::~FenceNV()
+{
+    SafeDelete(mFence);
+}
+
+Error FenceNV::set(GLenum condition)
+{
+    Error error = mFence->set(condition);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    mCondition = condition;
+    mStatus = GL_FALSE;
+    mIsSet = true;
+
+    return NoError();
+}
+
+Error FenceNV::test(GLboolean *outResult)
+{
+    // Flush the command buffer by default
+    Error error = mFence->test(&mStatus);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    *outResult = mStatus;
+    return NoError();
+}
+
+Error FenceNV::finish()
+{
+    ASSERT(mIsSet);
+
+    gl::Error error = mFence->finish();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    mStatus = GL_TRUE;
+
+    return NoError();
+}
+
+FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id)
+    : RefCountObject(id), mFence(impl), mLabel(), mCondition(GL_SYNC_GPU_COMMANDS_COMPLETE), mFlags(0)
+{
+}
+
+FenceSync::~FenceSync()
+{
+    SafeDelete(mFence);
+}
+
+void FenceSync::setLabel(const std::string &label)
+{
+    mLabel = label;
+}
+
+const std::string &FenceSync::getLabel() const
+{
+    return mLabel;
+}
+
+Error FenceSync::set(GLenum condition, GLbitfield flags)
+{
+    Error error = mFence->set(condition, flags);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    mCondition = condition;
+    mFlags = flags;
+    return NoError();
+}
+
+Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+    ASSERT(mCondition != GL_NONE);
+    return mFence->clientWait(flags, timeout, outResult);
+}
+
+Error FenceSync::serverWait(GLbitfield flags, GLuint64 timeout)
+{
+    return mFence->serverWait(flags, timeout);
+}
+
+Error FenceSync::getStatus(GLint *outResult) const
+{
+    return mFence->getStatus(outResult);
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/Fence.h b/src/third_party/angle/src/libANGLE/Fence.h
new file mode 100644
index 0000000..3b250a2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Fence.h
@@ -0,0 +1,81 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
+// extension and GLES3 sync objects.
+
+#ifndef LIBANGLE_FENCE_H_
+#define LIBANGLE_FENCE_H_
+
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+class FenceNVImpl;
+class FenceSyncImpl;
+}
+
+namespace gl
+{
+
+class FenceNV final : angle::NonCopyable
+{
+  public:
+    explicit FenceNV(rx::FenceNVImpl *impl);
+    virtual ~FenceNV();
+
+    Error set(GLenum condition);
+    Error test(GLboolean *outResult);
+    Error finish();
+
+    bool isSet() const { return mIsSet; }
+    GLboolean getStatus() const { return mStatus; }
+    GLenum getCondition() const { return mCondition; }
+
+  private:
+    rx::FenceNVImpl *mFence;
+
+    bool mIsSet;
+
+    GLboolean mStatus;
+    GLenum mCondition;
+};
+
+class FenceSync final : public RefCountObject, public LabeledObject
+{
+  public:
+    FenceSync(rx::FenceSyncImpl *impl, GLuint id);
+    virtual ~FenceSync();
+
+    void destroy(const Context *context) override {}
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    Error set(GLenum condition, GLbitfield flags);
+    Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult);
+    Error serverWait(GLbitfield flags, GLuint64 timeout);
+    Error getStatus(GLint *outResult) const;
+
+    GLenum getCondition() const { return mCondition; }
+    GLbitfield getFlags() const { return mFlags; }
+
+  private:
+    rx::FenceSyncImpl *mFence;
+
+    std::string mLabel;
+
+    GLenum mCondition;
+    GLbitfield mFlags;
+};
+
+}
+
+#endif   // LIBANGLE_FENCE_H_
diff --git a/src/third_party/angle/src/libANGLE/Fence_unittest.cpp b/src/third_party/angle/src/libANGLE/Fence_unittest.cpp
new file mode 100644
index 0000000..f7fd215
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Fence_unittest.cpp
@@ -0,0 +1,155 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+
+namespace {
+
+//
+// FenceNV tests
+//
+
+class MockFenceNVImpl : public rx::FenceNVImpl
+{
+  public:
+    virtual ~MockFenceNVImpl() { destroy(); }
+
+    MOCK_METHOD1(set, gl::Error(GLenum));
+    MOCK_METHOD1(test, gl::Error(GLboolean *));
+    MOCK_METHOD0(finish, gl::Error());
+
+    MOCK_METHOD0(destroy, void());
+};
+
+class FenceNVTest : public testing::Test
+{
+  protected:
+    virtual void SetUp()
+    {
+        mImpl = new MockFenceNVImpl;
+        EXPECT_CALL(*mImpl, destroy());
+        mFence = new gl::FenceNV(mImpl);
+    }
+
+    virtual void TearDown()
+    {
+        delete mFence;
+    }
+
+    MockFenceNVImpl *mImpl;
+    gl::FenceNV* mFence;
+};
+
+TEST_F(FenceNVTest, DestructionDeletesImpl)
+{
+    MockFenceNVImpl* impl = new MockFenceNVImpl;
+    EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation();
+
+    gl::FenceNV* fence = new gl::FenceNV(impl);
+    delete fence;
+
+    // Only needed because the mock is leaked if bugs are present,
+    // which logs an error, but does not cause the test to fail.
+    // Ordinarily mocks are verified when destroyed.
+    testing::Mock::VerifyAndClear(impl);
+}
+
+TEST_F(FenceNVTest, SetAndTestBehavior)
+{
+    EXPECT_CALL(*mImpl, set(_)).WillOnce(Return(gl::NoError())).RetiresOnSaturation();
+    EXPECT_FALSE(mFence->isSet());
+    mFence->set(GL_ALL_COMPLETED_NV);
+    EXPECT_TRUE(mFence->isSet());
+    // Fake the behavior of testing the fence before and after it's passed.
+    EXPECT_CALL(*mImpl, test(_))
+        .WillOnce(DoAll(SetArgumentPointee<0>(GL_FALSE), Return(gl::NoError())))
+        .WillOnce(DoAll(SetArgumentPointee<0>(GL_TRUE), Return(gl::NoError())))
+        .RetiresOnSaturation();
+    GLboolean out;
+    mFence->test(&out);
+    EXPECT_EQ(GL_FALSE, out);
+    mFence->test(&out);
+    EXPECT_EQ(GL_TRUE, out);
+}
+
+//
+// FenceSync tests
+//
+
+class MockFenceSyncImpl : public rx::FenceSyncImpl
+{
+  public:
+    virtual ~MockFenceSyncImpl() { destroy(); }
+
+    MOCK_METHOD2(set, gl::Error(GLenum, GLbitfield));
+    MOCK_METHOD3(clientWait, gl::Error(GLbitfield, GLuint64, GLenum *));
+    MOCK_METHOD2(serverWait, gl::Error(GLbitfield, GLuint64));
+    MOCK_METHOD1(getStatus, gl::Error(GLint *));
+
+    MOCK_METHOD0(destroy, void());
+};
+
+class FenceSyncTest : public testing::Test
+{
+  protected:
+    virtual void SetUp()
+    {
+        mImpl = new MockFenceSyncImpl;
+        EXPECT_CALL(*mImpl, destroy());
+        mFence = new gl::FenceSync(mImpl, 1);
+        mFence->addRef();
+    }
+
+    virtual void TearDown()
+    {
+        mFence->release();
+    }
+
+    MockFenceSyncImpl *mImpl;
+    gl::FenceSync* mFence;
+};
+
+TEST_F(FenceSyncTest, DestructionDeletesImpl)
+{
+    MockFenceSyncImpl* impl = new MockFenceSyncImpl;
+    EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation();
+
+    gl::FenceSync* fence = new gl::FenceSync(impl, 1);
+    fence->addRef();
+    fence->release();
+
+    // Only needed because the mock is leaked if bugs are present,
+    // which logs an error, but does not cause the test to fail.
+    // Ordinarily mocks are verified when destroyed.
+    testing::Mock::VerifyAndClear(impl);
+}
+
+TEST_F(FenceSyncTest, SetAndGetStatusBehavior)
+{
+    EXPECT_CALL(*mImpl, set(_, _)).WillOnce(Return(gl::NoError())).RetiresOnSaturation();
+    mFence->set(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+    EXPECT_EQ(static_cast<GLenum>(GL_SYNC_GPU_COMMANDS_COMPLETE), mFence->getCondition());
+    // Fake the behavior of testing the fence before and after it's passed.
+    EXPECT_CALL(*mImpl, getStatus(_))
+        .WillOnce(DoAll(SetArgumentPointee<0>(GL_UNSIGNALED), Return(gl::NoError())))
+        .WillOnce(DoAll(SetArgumentPointee<0>(GL_SIGNALED), Return(gl::NoError())))
+        .RetiresOnSaturation();
+    GLint out;
+    mFence->getStatus(&out);
+    EXPECT_EQ(GL_UNSIGNALED, out);
+    mFence->getStatus(&out);
+    EXPECT_EQ(GL_SIGNALED, out);
+}
+
+} // namespace
diff --git a/src/third_party/angle/src/libANGLE/Framebuffer.cpp b/src/third_party/angle/src/libANGLE/Framebuffer.cpp
new file mode 100644
index 0000000..2f0e48d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Framebuffer.cpp
@@ -0,0 +1,1369 @@
+//
+// 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.
+//
+
+// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
+
+#include "libANGLE/Framebuffer.h"
+
+#include "common/Optional.h"
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+namespace
+{
+
+void BindResourceChannel(OnAttachmentDirtyBinding *binding, FramebufferAttachmentObject *resource)
+{
+    binding->bind(resource ? resource->getDirtyChannel() : nullptr);
+}
+
+bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
+{
+    ASSERT(attachment.isAttached());
+
+    const Extents &size = attachment.getSize();
+    if (size.width == 0 || size.height == 0)
+    {
+        return false;
+    }
+
+    const InternalFormat &format = *attachment.getFormat().info;
+    if (!format.renderSupport(context->getClientVersion(), context->getExtensions()))
+    {
+        return false;
+    }
+
+    if (attachment.type() == GL_TEXTURE)
+    {
+        if (attachment.layer() >= size.depth)
+        {
+            return false;
+        }
+
+        // ES3 specifies that cube map texture attachments must be cube complete.
+        // This language is missing from the ES2 spec, but we enforce it here because some
+        // desktop OpenGL drivers also enforce this validation.
+        // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
+        const Texture *texture = attachment.getTexture();
+        ASSERT(texture);
+        if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
+            !texture->getTextureState().isCubeComplete())
+        {
+            return false;
+        }
+    }
+
+    return true;
+};
+
+}  // anonymous namespace
+
+// This constructor is only used for default framebuffers.
+FramebufferState::FramebufferState()
+    : mLabel(),
+      mColorAttachments(1),
+      mDrawBufferStates(IMPLEMENTATION_MAX_DRAW_BUFFERS, GL_NONE),
+      mReadBufferState(GL_BACK),
+      mDefaultWidth(0),
+      mDefaultHeight(0),
+      mDefaultSamples(0),
+      mDefaultFixedSampleLocations(GL_FALSE),
+      mWebGLDepthStencilConsistent(true)
+{
+    ASSERT(mDrawBufferStates.size() > 0);
+    mDrawBufferStates[0] = GL_BACK;
+    mEnabledDrawBuffers.set(0);
+}
+
+FramebufferState::FramebufferState(const Caps &caps)
+    : mLabel(),
+      mColorAttachments(caps.maxColorAttachments),
+      mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
+      mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
+      mDefaultWidth(0),
+      mDefaultHeight(0),
+      mDefaultSamples(0),
+      mDefaultFixedSampleLocations(GL_FALSE),
+      mWebGLDepthStencilConsistent(true)
+{
+    ASSERT(mDrawBufferStates.size() > 0);
+    mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
+}
+
+FramebufferState::~FramebufferState()
+{
+}
+
+const std::string &FramebufferState::getLabel()
+{
+    return mLabel;
+}
+
+const FramebufferAttachment *FramebufferState::getAttachment(GLenum attachment) const
+{
+    if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
+    {
+        return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
+    }
+
+    switch (attachment)
+    {
+        case GL_COLOR:
+        case GL_BACK:
+            return getColorAttachment(0);
+        case GL_DEPTH:
+        case GL_DEPTH_ATTACHMENT:
+            return getDepthAttachment();
+        case GL_STENCIL:
+        case GL_STENCIL_ATTACHMENT:
+            return getStencilAttachment();
+        case GL_DEPTH_STENCIL:
+        case GL_DEPTH_STENCIL_ATTACHMENT:
+            return getDepthStencilAttachment();
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+}
+
+const FramebufferAttachment *FramebufferState::getReadAttachment() const
+{
+    if (mReadBufferState == GL_NONE)
+    {
+        return nullptr;
+    }
+    ASSERT(mReadBufferState == GL_BACK ||
+           (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
+    size_t readIndex = (mReadBufferState == GL_BACK
+                            ? 0
+                            : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
+    ASSERT(readIndex < mColorAttachments.size());
+    return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
+{
+    auto *colorAttachment = getFirstColorAttachment();
+    if (colorAttachment)
+    {
+        return colorAttachment;
+    }
+    return getDepthOrStencilAttachment();
+}
+
+const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
+{
+    for (const FramebufferAttachment &colorAttachment : mColorAttachments)
+    {
+        if (colorAttachment.isAttached())
+        {
+            return &colorAttachment;
+        }
+    }
+
+    return nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
+{
+    if (mDepthAttachment.isAttached())
+    {
+        return &mDepthAttachment;
+    }
+    if (mStencilAttachment.isAttached())
+    {
+        return &mStencilAttachment;
+    }
+    return nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
+{
+    if (mStencilAttachment.isAttached())
+    {
+        return &mStencilAttachment;
+    }
+    return getDepthStencilAttachment();
+}
+
+const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
+{
+    ASSERT(colorAttachment < mColorAttachments.size());
+    return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
+                                                           : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getDepthAttachment() const
+{
+    return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getStencilAttachment() const
+{
+    return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
+{
+    // A valid depth-stencil attachment has the same resource bound to both the
+    // depth and stencil attachment points.
+    if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
+        mDepthAttachment == mStencilAttachment)
+    {
+        return &mDepthAttachment;
+    }
+
+    return nullptr;
+}
+
+bool FramebufferState::attachmentsHaveSameDimensions() const
+{
+    Optional<Extents> attachmentSize;
+
+    auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
+        if (!attachment.isAttached())
+        {
+            return false;
+        }
+
+        if (!attachmentSize.valid())
+        {
+            attachmentSize = attachment.getSize();
+            return false;
+        }
+
+        return (attachment.getSize() != attachmentSize.value());
+    };
+
+    for (const auto &attachment : mColorAttachments)
+    {
+        if (hasMismatchedSize(attachment))
+        {
+            return false;
+        }
+    }
+
+    if (hasMismatchedSize(mDepthAttachment))
+    {
+        return false;
+    }
+
+    return !hasMismatchedSize(mStencilAttachment);
+}
+
+const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
+{
+    ASSERT(drawBufferIdx < mDrawBufferStates.size());
+    if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
+    {
+        // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
+        // must be COLOR_ATTACHMENTi or NONE"
+        ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
+               (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
+        return getAttachment(mDrawBufferStates[drawBufferIdx]);
+    }
+    else
+    {
+        return nullptr;
+    }
+}
+
+size_t FramebufferState::getDrawBufferCount() const
+{
+    return mDrawBufferStates.size();
+}
+
+bool FramebufferState::colorAttachmentsAreUniqueImages() const
+{
+    for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
+         firstAttachmentIdx++)
+    {
+        const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
+        if (!firstAttachment.isAttached())
+        {
+            continue;
+        }
+
+        for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
+             secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
+        {
+            const gl::FramebufferAttachment &secondAttachment =
+                mColorAttachments[secondAttachmentIdx];
+            if (!secondAttachment.isAttached())
+            {
+                continue;
+            }
+
+            if (firstAttachment == secondAttachment)
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
+    : mState(caps),
+      mImpl(factory->createFramebuffer(mState)),
+      mId(id),
+      mCachedStatus(),
+      mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+      mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
+{
+    ASSERT(mId != 0);
+    ASSERT(mImpl != nullptr);
+    ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
+
+    for (uint32_t colorIndex = 0;
+         colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
+    {
+        mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
+    }
+}
+
+Framebuffer::Framebuffer(egl::Surface *surface)
+    : mState(),
+      mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
+      mId(0),
+      mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
+      mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+      mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
+{
+    ASSERT(mImpl != nullptr);
+    mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
+
+    setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(), surface);
+
+    if (surface->getConfig()->depthSize > 0)
+    {
+        setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface);
+    }
+
+    if (surface->getConfig()->stencilSize > 0)
+    {
+        setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, gl::ImageIndex::MakeInvalid(),
+                          surface);
+    }
+}
+
+Framebuffer::Framebuffer(rx::GLImplFactory *factory)
+    : mState(),
+      mImpl(factory->createFramebuffer(mState)),
+      mId(0),
+      mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
+      mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+      mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
+{
+    mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
+}
+
+Framebuffer::~Framebuffer()
+{
+    SafeDelete(mImpl);
+}
+
+void Framebuffer::destroy(const Context *context)
+{
+    mImpl->destroy(rx::SafeGetImpl(context));
+}
+
+void Framebuffer::destroyDefault(const egl::Display *display)
+{
+    mImpl->destroyDefault(rx::SafeGetImpl(display));
+}
+
+void Framebuffer::setLabel(const std::string &label)
+{
+    mState.mLabel = label;
+}
+
+const std::string &Framebuffer::getLabel() const
+{
+    return mState.mLabel;
+}
+
+void Framebuffer::detachTexture(const Context *context, GLuint textureId)
+{
+    detachResourceById(context, GL_TEXTURE, textureId);
+}
+
+void Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
+{
+    detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
+}
+
+void Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
+{
+    for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
+    {
+        detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
+                                 DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
+    }
+
+    if (context->isWebGL1())
+    {
+        const std::array<FramebufferAttachment *, 3> attachments = {
+            {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
+             &mState.mWebGLStencilAttachment}};
+        for (FramebufferAttachment *attachment : attachments)
+        {
+            if (attachment->isAttached() && attachment->type() == resourceType &&
+                attachment->id() == resourceId)
+            {
+                resetAttachment(context, attachment->getBinding());
+            }
+        }
+    }
+    else
+    {
+        detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
+                                 DIRTY_BIT_DEPTH_ATTACHMENT);
+        detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
+                                 DIRTY_BIT_STENCIL_ATTACHMENT);
+    }
+}
+
+void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
+                                           GLenum matchType,
+                                           GLuint matchId,
+                                           size_t dirtyBit)
+{
+    if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
+    {
+        attachment->detach();
+        mDirtyBits.set(dirtyBit);
+    }
+}
+
+const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
+{
+    return mState.getColorAttachment(colorAttachment);
+}
+
+const FramebufferAttachment *Framebuffer::getDepthbuffer() const
+{
+    return mState.getDepthAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getStencilbuffer() const
+{
+    return mState.getStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
+{
+    return mState.getDepthStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
+{
+    return mState.getDepthOrStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
+{
+    return mState.getStencilOrDepthStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
+{
+    return mState.getReadAttachment();
+}
+
+GLenum Framebuffer::getReadColorbufferType() const
+{
+    const FramebufferAttachment *readAttachment = mState.getReadAttachment();
+    return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
+}
+
+const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
+{
+    return mState.getFirstColorAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
+{
+    return mState.getAttachment(attachment);
+}
+
+size_t Framebuffer::getDrawbufferStateCount() const
+{
+    return mState.mDrawBufferStates.size();
+}
+
+GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
+{
+    ASSERT(drawBuffer < mState.mDrawBufferStates.size());
+    return mState.mDrawBufferStates[drawBuffer];
+}
+
+const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
+{
+    return mState.getDrawBufferStates();
+}
+
+void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
+{
+    auto &drawStates = mState.mDrawBufferStates;
+
+    ASSERT(count <= drawStates.size());
+    std::copy(buffers, buffers + count, drawStates.begin());
+    std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
+    mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
+
+    mState.mEnabledDrawBuffers.reset();
+    for (size_t index = 0; index < count; ++index)
+    {
+        if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
+        {
+            mState.mEnabledDrawBuffers.set(index);
+        }
+    }
+}
+
+const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
+{
+    return mState.getDrawBuffer(drawBuffer);
+}
+
+bool Framebuffer::hasEnabledDrawBuffer() const
+{
+    for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
+    {
+        if (getDrawBuffer(drawbufferIdx) != nullptr)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+GLenum Framebuffer::getReadBufferState() const
+{
+    return mState.mReadBufferState;
+}
+
+void Framebuffer::setReadBuffer(GLenum buffer)
+{
+    ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
+           (buffer >= GL_COLOR_ATTACHMENT0 &&
+            (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
+    mState.mReadBufferState = buffer;
+    mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
+}
+
+size_t Framebuffer::getNumColorBuffers() const
+{
+    return mState.mColorAttachments.size();
+}
+
+bool Framebuffer::hasDepth() const
+{
+    return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
+}
+
+bool Framebuffer::hasStencil() const
+{
+    return (mState.mStencilAttachment.isAttached() &&
+            mState.mStencilAttachment.getStencilSize() > 0);
+}
+
+bool Framebuffer::usingExtendedDrawBuffers() const
+{
+    for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
+    {
+        if (getDrawBuffer(drawbufferIdx) != nullptr)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void Framebuffer::invalidateCompletenessCache()
+{
+    if (mId != 0)
+    {
+        mCachedStatus.reset();
+    }
+}
+
+GLenum Framebuffer::checkStatus(const Context *context)
+{
+    // The default framebuffer is always complete except when it is surfaceless in which
+    // case it is always unsupported. We return early because the default framebuffer may
+    // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
+    if (mId == 0)
+    {
+        ASSERT(mCachedStatus.valid());
+        ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
+               mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
+        return mCachedStatus.value();
+    }
+
+    if (hasAnyDirtyBit() || !mCachedStatus.valid())
+    {
+        mCachedStatus = checkStatusImpl(context);
+    }
+
+    return mCachedStatus.value();
+}
+
+GLenum Framebuffer::checkStatusImpl(const Context *context)
+{
+    const ContextState &state = context->getContextState();
+
+    ASSERT(mId != 0);
+
+    unsigned int colorbufferSize = 0;
+    int samples                  = -1;
+    bool missingAttachment       = true;
+    Optional<GLboolean> fixedSampleLocations;
+    bool hasRenderbuffer = false;
+
+    for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
+    {
+        if (colorAttachment.isAttached())
+        {
+            if (!CheckAttachmentCompleteness(context, colorAttachment))
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+
+            const InternalFormat &format = *colorAttachment.getFormat().info;
+            if (format.depthBits > 0 || format.stencilBits > 0)
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+
+            if (colorAttachment.type() == GL_TEXTURE)
+            {
+                // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS
+                // should be the same for all attached textures.
+                GLboolean fixedSampleloc = colorAttachment.getTexture()->getFixedSampleLocations(
+                    colorAttachment.getTextureImageIndex().type, 0);
+                if (fixedSampleLocations.valid() && fixedSampleloc != fixedSampleLocations.value())
+                {
+                    return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+                }
+                else
+                {
+                    fixedSampleLocations = fixedSampleloc;
+                }
+            }
+            else if (colorAttachment.type() == GL_RENDERBUFFER)
+            {
+                hasRenderbuffer = true;
+            }
+
+            if (!missingAttachment)
+            {
+                // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
+                // all color attachments have the same number of samples for the FBO to be complete.
+                if (colorAttachment.getSamples() != samples)
+                {
+                    return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
+                }
+
+                // in GLES 2.0, all color attachments attachments must have the same number of
+                // bitplanes in GLES 3.0, there is no such restriction
+                if (state.getClientMajorVersion() < 3)
+                {
+                    if (format.pixelBytes != colorbufferSize)
+                    {
+                        return GL_FRAMEBUFFER_UNSUPPORTED;
+                    }
+                }
+            }
+            else
+            {
+                samples           = colorAttachment.getSamples();
+                colorbufferSize   = format.pixelBytes;
+                missingAttachment = false;
+            }
+        }
+    }
+
+    const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
+    if (depthAttachment.isAttached())
+    {
+        if (!CheckAttachmentCompleteness(context, depthAttachment))
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        const InternalFormat &format = *depthAttachment.getFormat().info;
+        if (format.depthBits == 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (missingAttachment)
+        {
+            samples           = depthAttachment.getSamples();
+            missingAttachment = false;
+        }
+        else if (samples != depthAttachment.getSamples())
+        {
+            // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be
+            // considered complete when its depth or stencil samples are a
+            // multiple of the number of color samples.
+            const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
+            if (!mixedSamples)
+                return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+
+            const int colorSamples = samples ? samples : 1;
+            const int depthSamples = depthAttachment.getSamples();
+            if ((depthSamples % colorSamples) != 0)
+                return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+        }
+    }
+
+    const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
+    if (stencilAttachment.isAttached())
+    {
+        if (!CheckAttachmentCompleteness(context, stencilAttachment))
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        const InternalFormat &format = *stencilAttachment.getFormat().info;
+        if (format.stencilBits == 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (missingAttachment)
+        {
+            samples           = stencilAttachment.getSamples();
+            missingAttachment = false;
+        }
+        else if (samples != stencilAttachment.getSamples())
+        {
+            // see the comments in depth attachment check.
+            const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
+            if (!mixedSamples)
+                return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+
+            const int colorSamples   = samples ? samples : 1;
+            const int stencilSamples = stencilAttachment.getSamples();
+            if ((stencilSamples % colorSamples) != 0)
+                return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+        }
+
+        // Starting from ES 3.0 stencil and depth, if present, should be the same image
+        if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
+            stencilAttachment != depthAttachment)
+        {
+            return GL_FRAMEBUFFER_UNSUPPORTED;
+        }
+    }
+
+    // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
+    if (state.isWebGL1())
+    {
+        if (!mState.mWebGLDepthStencilConsistent)
+        {
+            return GL_FRAMEBUFFER_UNSUPPORTED;
+        }
+
+        if (mState.mWebGLDepthStencilAttachment.isAttached())
+        {
+            if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
+                mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+        }
+        else if (mState.mStencilAttachment.isAttached() &&
+                 mState.mStencilAttachment.getDepthSize() > 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+        else if (mState.mDepthAttachment.isAttached() &&
+                 mState.mDepthAttachment.getStencilSize() > 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+    }
+
+    // ES3.1(section 9.4) requires that if no image is attached to the
+    // framebuffer, and either the value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH
+    // or FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is
+    // considered incomplete.
+    GLint defaultWidth  = mState.getDefaultWidth();
+    GLint defaultHeight = mState.getDefaultHeight();
+
+    if (missingAttachment && (defaultWidth == 0 || defaultHeight == 0))
+    {
+        return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+    }
+
+    // In ES 2.0 and WebGL, all color attachments must have the same width and height.
+    // In ES 3.0, there is no such restriction.
+    if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
+        !mState.attachmentsHaveSameDimensions())
+    {
+        return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+    }
+
+    // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers
+    // and textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all
+    // attached textures.
+    if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
+    {
+        return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+    }
+
+    syncState(context);
+    if (!mImpl->checkStatus())
+    {
+        return GL_FRAMEBUFFER_UNSUPPORTED;
+    }
+
+    return GL_FRAMEBUFFER_COMPLETE;
+}
+
+Error Framebuffer::discard(size_t count, const GLenum *attachments)
+{
+    return mImpl->discard(count, attachments);
+}
+
+Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
+{
+    return mImpl->invalidate(count, attachments);
+}
+
+Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
+{
+    return mImpl->invalidateSub(count, attachments, area);
+}
+
+Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
+{
+    if (context->getGLState().isRasterizerDiscardEnabled())
+    {
+        return gl::NoError();
+    }
+
+    return mImpl->clear(context, mask);
+}
+
+Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
+                                 GLenum buffer,
+                                 GLint drawbuffer,
+                                 const GLfloat *values)
+{
+    if (context->getGLState().isRasterizerDiscardEnabled())
+    {
+        return gl::NoError();
+    }
+
+    return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
+}
+
+Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
+                                  GLenum buffer,
+                                  GLint drawbuffer,
+                                  const GLuint *values)
+{
+    if (context->getGLState().isRasterizerDiscardEnabled())
+    {
+        return gl::NoError();
+    }
+
+    return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
+}
+
+Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
+                                 GLenum buffer,
+                                 GLint drawbuffer,
+                                 const GLint *values)
+{
+    if (context->getGLState().isRasterizerDiscardEnabled())
+    {
+        return gl::NoError();
+    }
+
+    return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
+}
+
+Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
+                                 GLenum buffer,
+                                 GLint drawbuffer,
+                                 GLfloat depth,
+                                 GLint stencil)
+{
+    if (context->getGLState().isRasterizerDiscardEnabled())
+    {
+        return gl::NoError();
+    }
+
+    return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
+}
+
+GLenum Framebuffer::getImplementationColorReadFormat() const
+{
+    return mImpl->getImplementationColorReadFormat();
+}
+
+GLenum Framebuffer::getImplementationColorReadType() const
+{
+    return mImpl->getImplementationColorReadType();
+}
+
+Error Framebuffer::readPixels(rx::ContextImpl *context,
+                              const Rectangle &area,
+                              GLenum format,
+                              GLenum type,
+                              void *pixels) const
+{
+    ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
+
+    Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
+    if (unpackBuffer)
+    {
+        unpackBuffer->onPixelUnpack();
+    }
+
+    return NoError();
+}
+
+Error Framebuffer::blit(rx::ContextImpl *context,
+                        const Rectangle &sourceArea,
+                        const Rectangle &destArea,
+                        GLbitfield mask,
+                        GLenum filter)
+{
+    GLbitfield blitMask = mask;
+
+    // Note that blitting is called against draw framebuffer.
+    // See the code in gl::Context::blitFramebuffer.
+    if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
+    {
+        blitMask &= ~GL_COLOR_BUFFER_BIT;
+    }
+
+    if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
+    {
+        blitMask &= ~GL_STENCIL_BUFFER_BIT;
+    }
+
+    if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
+    {
+        blitMask &= ~GL_DEPTH_BUFFER_BIT;
+    }
+
+    if (!blitMask)
+    {
+        return NoError();
+    }
+
+    return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
+}
+
+int Framebuffer::getSamples(const Context *context)
+{
+    if (complete(context))
+    {
+        // For a complete framebuffer, all attachments must have the same sample count.
+        // In this case return the first nonzero sample size.
+        const auto *firstColorAttachment = mState.getFirstColorAttachment();
+        if (firstColorAttachment)
+        {
+            ASSERT(firstColorAttachment->isAttached());
+            return firstColorAttachment->getSamples();
+        }
+    }
+
+    return 0;
+}
+
+Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
+{
+    ANGLE_TRY(mImpl->getSamplePosition(index, xy));
+    return gl::NoError();
+}
+
+bool Framebuffer::hasValidDepthStencil() const
+{
+    return mState.getDepthStencilAttachment() != nullptr;
+}
+
+void Framebuffer::setAttachment(const Context *context,
+                                GLenum type,
+                                GLenum binding,
+                                const ImageIndex &textureIndex,
+                                FramebufferAttachmentObject *resource)
+{
+    // Context may be null in unit tests.
+    if (!context || !context->isWebGL1())
+    {
+        setAttachmentImpl(type, binding, textureIndex, resource);
+        return;
+    }
+
+    switch (binding)
+    {
+        case GL_DEPTH_STENCIL:
+        case GL_DEPTH_STENCIL_ATTACHMENT:
+            mState.mWebGLDepthStencilAttachment.attach(type, binding, textureIndex, resource);
+            break;
+        case GL_DEPTH:
+        case GL_DEPTH_ATTACHMENT:
+            mState.mWebGLDepthAttachment.attach(type, binding, textureIndex, resource);
+            break;
+        case GL_STENCIL:
+        case GL_STENCIL_ATTACHMENT:
+            mState.mWebGLStencilAttachment.attach(type, binding, textureIndex, resource);
+            break;
+        default:
+            setAttachmentImpl(type, binding, textureIndex, resource);
+            return;
+    }
+
+    commitWebGL1DepthStencilIfConsistent();
+}
+
+void Framebuffer::commitWebGL1DepthStencilIfConsistent()
+{
+    int count = 0;
+
+    std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
+                                                           &mState.mWebGLDepthAttachment,
+                                                           &mState.mWebGLStencilAttachment}};
+    for (FramebufferAttachment *attachment : attachments)
+    {
+        if (attachment->isAttached())
+        {
+            count++;
+        }
+    }
+
+    mState.mWebGLDepthStencilConsistent = (count <= 1);
+    if (!mState.mWebGLDepthStencilConsistent)
+    {
+        // Inconsistent.
+        return;
+    }
+
+    auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
+        if (attachment.type() == GL_TEXTURE)
+        {
+            return attachment.getTextureImageIndex();
+        }
+        else
+        {
+            return ImageIndex::MakeInvalid();
+        }
+    };
+
+    if (mState.mWebGLDepthAttachment.isAttached())
+    {
+        const auto &depth = mState.mWebGLDepthAttachment;
+        setAttachmentImpl(depth.type(), GL_DEPTH_ATTACHMENT,
+                          getImageIndexIfTextureAttachment(depth), depth.getResource());
+        setAttachmentImpl(GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
+    }
+    else if (mState.mWebGLStencilAttachment.isAttached())
+    {
+        const auto &stencil = mState.mWebGLStencilAttachment;
+        setAttachmentImpl(GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
+        setAttachmentImpl(stencil.type(), GL_STENCIL_ATTACHMENT,
+                          getImageIndexIfTextureAttachment(stencil), stencil.getResource());
+    }
+    else if (mState.mWebGLDepthStencilAttachment.isAttached())
+    {
+        const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
+        setAttachmentImpl(depthStencil.type(), GL_DEPTH_ATTACHMENT,
+                          getImageIndexIfTextureAttachment(depthStencil),
+                          depthStencil.getResource());
+        setAttachmentImpl(depthStencil.type(), GL_STENCIL_ATTACHMENT,
+                          getImageIndexIfTextureAttachment(depthStencil),
+                          depthStencil.getResource());
+    }
+    else
+    {
+        setAttachmentImpl(GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
+        setAttachmentImpl(GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
+    }
+}
+
+void Framebuffer::setAttachmentImpl(GLenum type,
+                                    GLenum binding,
+                                    const ImageIndex &textureIndex,
+                                    FramebufferAttachmentObject *resource)
+{
+    switch (binding)
+    {
+        case GL_DEPTH_STENCIL:
+        case GL_DEPTH_STENCIL_ATTACHMENT:
+        {
+            // ensure this is a legitimate depth+stencil format
+            FramebufferAttachmentObject *attachmentObj = resource;
+            if (resource)
+            {
+                const Format &format = resource->getAttachmentFormat(binding, textureIndex);
+                if (format.info->depthBits == 0 || format.info->stencilBits == 0)
+                {
+                    // Attaching nullptr detaches the current attachment.
+                    attachmentObj = nullptr;
+                }
+            }
+
+            updateAttachment(&mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
+                             &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
+                             attachmentObj);
+            updateAttachment(&mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
+                             &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
+                             attachmentObj);
+            return;
+        }
+
+        case GL_DEPTH:
+        case GL_DEPTH_ATTACHMENT:
+            updateAttachment(&mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
+                             &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource);
+            break;
+
+        case GL_STENCIL:
+        case GL_STENCIL_ATTACHMENT:
+            updateAttachment(&mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
+                             &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
+                             resource);
+            break;
+
+        case GL_BACK:
+            mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
+            mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
+            // No need for a resource binding for the default FBO, it's always complete.
+            break;
+
+        default:
+        {
+            size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
+            ASSERT(colorIndex < mState.mColorAttachments.size());
+            size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
+            updateAttachment(&mState.mColorAttachments[colorIndex], dirtyBit,
+                             &mDirtyColorAttachmentBindings[colorIndex], type, binding,
+                             textureIndex, resource);
+
+            bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
+            mState.mEnabledDrawBuffers.set(colorIndex, enabled);
+        }
+        break;
+    }
+}
+
+void Framebuffer::updateAttachment(FramebufferAttachment *attachment,
+                                   size_t dirtyBit,
+                                   OnAttachmentDirtyBinding *onDirtyBinding,
+                                   GLenum type,
+                                   GLenum binding,
+                                   const ImageIndex &textureIndex,
+                                   FramebufferAttachmentObject *resource)
+{
+    attachment->attach(type, binding, textureIndex, resource);
+    mDirtyBits.set(dirtyBit);
+    BindResourceChannel(onDirtyBinding, resource);
+}
+
+void Framebuffer::resetAttachment(const Context *context, GLenum binding)
+{
+    setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
+}
+
+void Framebuffer::syncState(const Context *context)
+{
+    if (mDirtyBits.any())
+    {
+        mImpl->syncState(rx::SafeGetImpl(context), mDirtyBits);
+        mDirtyBits.reset();
+        if (mId != 0)
+        {
+            mCachedStatus.reset();
+        }
+    }
+}
+
+void Framebuffer::signal(uint32_t token)
+{
+    // TOOD(jmadill): Make this only update individual attachments to do less work.
+    mCachedStatus.reset();
+}
+
+bool Framebuffer::complete(const Context *context)
+{
+    return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
+}
+
+bool Framebuffer::cachedComplete() const
+{
+    return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
+}
+
+bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
+{
+    const Program *program = state.getProgram();
+
+    // TODO(jmadill): Default framebuffer feedback loops.
+    if (mId == 0)
+    {
+        return false;
+    }
+
+    // The bitset will skip inactive draw buffers.
+    for (size_t drawIndex : mState.mEnabledDrawBuffers)
+    {
+        const FramebufferAttachment *attachment = getDrawBuffer(drawIndex);
+        if (attachment && attachment->type() == GL_TEXTURE)
+        {
+            // Validate the feedback loop.
+            if (program->samplesFromTexture(state, attachment->id()))
+            {
+                return true;
+            }
+        }
+    }
+
+    // Validate depth-stencil feedback loop.
+    const auto &dsState = state.getDepthStencilState();
+
+    // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
+    const FramebufferAttachment *depth = getDepthbuffer();
+    if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
+    {
+        if (program->samplesFromTexture(state, depth->id()))
+        {
+            return true;
+        }
+    }
+
+    // Note: we assume the front and back masks are the same for WebGL.
+    const FramebufferAttachment *stencil = getStencilbuffer();
+    ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
+    if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
+        dsState.stencilWritemask != 0)
+    {
+        // Skip the feedback loop check if depth/stencil point to the same resource.
+        if (!depth || *stencil != *depth)
+        {
+            if (program->samplesFromTexture(state, stencil->id()))
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
+                                               GLint copyTextureLevel,
+                                               GLint copyTextureLayer) const
+{
+    if (mId == 0)
+    {
+        // It seems impossible to form a texture copying feedback loop with the default FBO.
+        return false;
+    }
+
+    const FramebufferAttachment *readAttachment = getReadColorbuffer();
+    ASSERT(readAttachment);
+
+    if (readAttachment->isTextureWithId(copyTextureID))
+    {
+        const auto &imageIndex = readAttachment->getTextureImageIndex();
+        if (imageIndex.mipIndex == copyTextureLevel)
+        {
+            // Check 3D/Array texture layers.
+            return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
+                   copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
+                   imageIndex.layerIndex == copyTextureLayer;
+        }
+    }
+    return false;
+}
+
+GLint Framebuffer::getDefaultWidth() const
+{
+    return mState.getDefaultWidth();
+}
+
+GLint Framebuffer::getDefaultHeight() const
+{
+    return mState.getDefaultHeight();
+}
+
+GLint Framebuffer::getDefaultSamples() const
+{
+    return mState.getDefaultSamples();
+}
+
+GLboolean Framebuffer::getDefaultFixedSampleLocations() const
+{
+    return mState.getDefaultFixedSampleLocations();
+}
+
+void Framebuffer::setDefaultWidth(GLint defaultWidth)
+{
+    mState.mDefaultWidth = defaultWidth;
+    mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
+}
+
+void Framebuffer::setDefaultHeight(GLint defaultHeight)
+{
+    mState.mDefaultHeight = defaultHeight;
+    mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
+}
+
+void Framebuffer::setDefaultSamples(GLint defaultSamples)
+{
+    mState.mDefaultSamples = defaultSamples;
+    mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
+}
+
+void Framebuffer::setDefaultFixedSampleLocations(GLboolean defaultFixedSampleLocations)
+{
+    mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
+    mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
+}
+
+// TODO(jmadill): Remove this kludge.
+GLenum Framebuffer::checkStatus(const ValidationContext *context)
+{
+    return checkStatus(static_cast<const Context *>(context));
+}
+
+int Framebuffer::getSamples(const ValidationContext *context)
+{
+    return getSamples(static_cast<const Context *>(context));
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/Framebuffer.h b/src/third_party/angle/src/libANGLE/Framebuffer.h
new file mode 100644
index 0000000..efcce1e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Framebuffer.h
@@ -0,0 +1,311 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// 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 LIBANGLE_FRAMEBUFFER_H_
+#define LIBANGLE_FRAMEBUFFER_H_
+
+#include <vector>
+
+#include "common/Optional.h"
+#include "common/angleutils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/signal_utils.h"
+
+namespace rx
+{
+class ContextImpl;
+class GLImplFactory;
+class FramebufferImpl;
+class RenderbufferImpl;
+class SurfaceImpl;
+}
+
+namespace egl
+{
+class Display;
+class Surface;
+}
+
+namespace gl
+{
+class Context;
+class ContextState;
+class Framebuffer;
+class Renderbuffer;
+class State;
+class Texture;
+class TextureCapsMap;
+class ValidationContext;
+struct Caps;
+struct Extensions;
+struct ImageIndex;
+struct Rectangle;
+
+class FramebufferState final : angle::NonCopyable
+{
+  public:
+    FramebufferState();
+    explicit FramebufferState(const Caps &caps);
+    ~FramebufferState();
+
+    const std::string &getLabel();
+
+    const FramebufferAttachment *getAttachment(GLenum attachment) const;
+    const FramebufferAttachment *getReadAttachment() const;
+    const FramebufferAttachment *getFirstNonNullAttachment() const;
+    const FramebufferAttachment *getFirstColorAttachment() const;
+    const FramebufferAttachment *getDepthOrStencilAttachment() const;
+    const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
+    const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
+    const FramebufferAttachment *getDepthAttachment() const;
+    const FramebufferAttachment *getStencilAttachment() const;
+    const FramebufferAttachment *getDepthStencilAttachment() const;
+
+    const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
+    GLenum getReadBufferState() const { return mReadBufferState; }
+    const std::vector<FramebufferAttachment> &getColorAttachments() const
+    {
+        return mColorAttachments;
+    }
+
+    bool attachmentsHaveSameDimensions() const;
+    bool colorAttachmentsAreUniqueImages() const;
+
+    const FramebufferAttachment *getDrawBuffer(size_t drawBufferIdx) const;
+    size_t getDrawBufferCount() const;
+
+    GLint getDefaultWidth() const { return mDefaultWidth; };
+    GLint getDefaultHeight() const { return mDefaultHeight; };
+    GLint getDefaultSamples() const { return mDefaultSamples; };
+    GLboolean getDefaultFixedSampleLocations() const { return mDefaultFixedSampleLocations; };
+
+  private:
+    friend class Framebuffer;
+
+    std::string mLabel;
+
+    std::vector<FramebufferAttachment> mColorAttachments;
+    FramebufferAttachment mDepthAttachment;
+    FramebufferAttachment mStencilAttachment;
+
+    std::vector<GLenum> mDrawBufferStates;
+    GLenum mReadBufferState;
+    angle::BitSet<IMPLEMENTATION_MAX_DRAW_BUFFERS> mEnabledDrawBuffers;
+
+    GLint mDefaultWidth;
+    GLint mDefaultHeight;
+    GLint mDefaultSamples;
+    GLboolean mDefaultFixedSampleLocations;
+
+    // It's necessary to store all this extra state so we can restore attachments
+    // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1.
+    FramebufferAttachment mWebGLDepthStencilAttachment;
+    FramebufferAttachment mWebGLDepthAttachment;
+    FramebufferAttachment mWebGLStencilAttachment;
+    bool mWebGLDepthStencilConsistent;
+};
+
+using OnAttachmentDirtyBinding  = angle::ChannelBinding<>;
+using OnAttachmentDirtyChannel  = angle::BroadcastChannel<>;
+using OnAttachmentDirtyReceiver = angle::SignalReceiver<>;
+
+class Framebuffer final : public LabeledObject, public OnAttachmentDirtyReceiver
+{
+  public:
+    // Constructor to build application-defined framebuffers
+    Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id);
+    // Constructor to build default framebuffers for a surface
+    Framebuffer(egl::Surface *surface);
+    // Constructor to build a fake default framebuffer when surfaceless
+    Framebuffer(rx::GLImplFactory *factory);
+
+    virtual ~Framebuffer();
+    void destroy(const Context *context);
+    void destroyDefault(const egl::Display *display);
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    rx::FramebufferImpl *getImplementation() const { return mImpl; }
+
+    GLuint id() const { return mId; }
+
+    void setAttachment(const Context *context,
+                       GLenum type,
+                       GLenum binding,
+                       const ImageIndex &textureIndex,
+                       FramebufferAttachmentObject *resource);
+    void resetAttachment(const Context *context, GLenum binding);
+
+    void detachTexture(const Context *context, GLuint texture);
+    void detachRenderbuffer(const Context *context, GLuint renderbuffer);
+
+    const FramebufferAttachment *getColorbuffer(size_t colorAttachment) const;
+    const FramebufferAttachment *getDepthbuffer() const;
+    const FramebufferAttachment *getStencilbuffer() const;
+    const FramebufferAttachment *getDepthStencilBuffer() const;
+    const FramebufferAttachment *getDepthOrStencilbuffer() const;
+    const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
+    const FramebufferAttachment *getReadColorbuffer() const;
+    GLenum getReadColorbufferType() const;
+    const FramebufferAttachment *getFirstColorbuffer() const;
+
+    const FramebufferAttachment *getAttachment(GLenum attachment) const;
+
+    size_t getDrawbufferStateCount() const;
+    GLenum getDrawBufferState(size_t drawBuffer) const;
+    const std::vector<GLenum> &getDrawBufferStates() const;
+    void setDrawBuffers(size_t count, const GLenum *buffers);
+    const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const;
+    bool hasEnabledDrawBuffer() const;
+
+    GLenum getReadBufferState() const;
+    void setReadBuffer(GLenum buffer);
+
+    size_t getNumColorBuffers() const;
+    bool hasDepth() const;
+    bool hasStencil() const;
+
+    bool usingExtendedDrawBuffers() const;
+
+    // This method calls checkStatus.
+    int getSamples(const Context *context);
+
+    Error getSamplePosition(size_t index, GLfloat *xy) const;
+
+    GLint getDefaultWidth() const;
+    GLint getDefaultHeight() const;
+    GLint getDefaultSamples() const;
+    GLboolean getDefaultFixedSampleLocations() const;
+    void setDefaultWidth(GLint defaultWidth);
+    void setDefaultHeight(GLint defaultHeight);
+    void setDefaultSamples(GLint defaultSamples);
+    void setDefaultFixedSampleLocations(GLboolean defaultFixedSampleLocations);
+
+    void invalidateCompletenessCache();
+
+    GLenum checkStatus(const Context *context);
+
+    // TODO(jmadill): Remove this kludge.
+    GLenum checkStatus(const ValidationContext *context);
+    int getSamples(const ValidationContext *context);
+
+    // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
+    bool complete(const Context *context);
+    bool cachedComplete() const;
+
+    bool hasValidDepthStencil() const;
+
+    Error discard(size_t count, const GLenum *attachments);
+    Error invalidate(size_t count, const GLenum *attachments);
+    Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area);
+
+    Error clear(rx::ContextImpl *context, GLbitfield mask);
+    Error clearBufferfv(rx::ContextImpl *context,
+                        GLenum buffer,
+                        GLint drawbuffer,
+                        const GLfloat *values);
+    Error clearBufferuiv(rx::ContextImpl *context,
+                         GLenum buffer,
+                         GLint drawbuffer,
+                         const GLuint *values);
+    Error clearBufferiv(rx::ContextImpl *context,
+                        GLenum buffer,
+                        GLint drawbuffer,
+                        const GLint *values);
+    Error clearBufferfi(rx::ContextImpl *context,
+                        GLenum buffer,
+                        GLint drawbuffer,
+                        GLfloat depth,
+                        GLint stencil);
+
+    GLenum getImplementationColorReadFormat() const;
+    GLenum getImplementationColorReadType() const;
+    Error readPixels(rx::ContextImpl *context,
+                     const gl::Rectangle &area,
+                     GLenum format,
+                     GLenum type,
+                     void *pixels) const;
+
+    Error blit(rx::ContextImpl *context,
+               const Rectangle &sourceArea,
+               const Rectangle &destArea,
+               GLbitfield mask,
+               GLenum filter);
+
+    enum DirtyBitType : uint32_t
+    {
+        DIRTY_BIT_COLOR_ATTACHMENT_0,
+        DIRTY_BIT_COLOR_ATTACHMENT_MAX =
+            DIRTY_BIT_COLOR_ATTACHMENT_0 + gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS,
+        DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX,
+        DIRTY_BIT_STENCIL_ATTACHMENT,
+        DIRTY_BIT_DRAW_BUFFERS,
+        DIRTY_BIT_READ_BUFFER,
+        DIRTY_BIT_DEFAULT_WIDTH,
+        DIRTY_BIT_DEFAULT_HEIGHT,
+        DIRTY_BIT_DEFAULT_SAMPLES,
+        DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS,
+        DIRTY_BIT_UNKNOWN,
+        DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN
+    };
+
+    typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits;
+    bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+    void syncState(const Context *context);
+
+    // angle::SignalReceiver implementation
+    void signal(uint32_t token) override;
+
+    bool formsRenderingFeedbackLoopWith(const State &state) const;
+    bool formsCopyingFeedbackLoopWith(GLuint copyTextureID,
+                                      GLint copyTextureLevel,
+                                      GLint copyTextureLayer) const;
+
+  private:
+    void detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId);
+    void detachMatchingAttachment(FramebufferAttachment *attachment,
+                                  GLenum matchType,
+                                  GLuint matchId,
+                                  size_t dirtyBit);
+    GLenum checkStatusImpl(const Context *context);
+    void commitWebGL1DepthStencilIfConsistent();
+
+    void setAttachmentImpl(GLenum type,
+                           GLenum binding,
+                           const ImageIndex &textureIndex,
+                           FramebufferAttachmentObject *resource);
+    void updateAttachment(FramebufferAttachment *attachment,
+                          size_t dirtyBit,
+                          OnAttachmentDirtyBinding *onDirtyBinding,
+                          GLenum type,
+                          GLenum binding,
+                          const ImageIndex &textureIndex,
+                          FramebufferAttachmentObject *resource);
+
+    FramebufferState mState;
+    rx::FramebufferImpl *mImpl;
+    GLuint mId;
+
+    Optional<GLenum> mCachedStatus;
+    std::vector<OnAttachmentDirtyBinding> mDirtyColorAttachmentBindings;
+    OnAttachmentDirtyBinding mDirtyDepthAttachmentBinding;
+    OnAttachmentDirtyBinding mDirtyStencilAttachmentBinding;
+
+    DirtyBits mDirtyBits;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_FRAMEBUFFER_H_
diff --git a/src/third_party/angle/src/libANGLE/FramebufferAttachment.cpp b/src/third_party/angle/src/libANGLE/FramebufferAttachment.cpp
new file mode 100644
index 0000000..aeea903
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/FramebufferAttachment.cpp
@@ -0,0 +1,251 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#include "libANGLE/FramebufferAttachment.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace gl
+{
+
+////// FramebufferAttachment::Target Implementation //////
+
+FramebufferAttachment::Target::Target()
+    : mBinding(GL_NONE),
+      mTextureIndex(ImageIndex::MakeInvalid())
+{
+}
+
+FramebufferAttachment::Target::Target(GLenum binding, const ImageIndex &imageIndex)
+    : mBinding(binding),
+      mTextureIndex(imageIndex)
+{
+}
+
+FramebufferAttachment::Target::Target(const Target &other)
+    : mBinding(other.mBinding),
+      mTextureIndex(other.mTextureIndex)
+{
+}
+
+FramebufferAttachment::Target &FramebufferAttachment::Target::operator=(const Target &other)
+{
+    this->mBinding = other.mBinding;
+    this->mTextureIndex = other.mTextureIndex;
+    return *this;
+}
+
+////// FramebufferAttachment Implementation //////
+
+FramebufferAttachment::FramebufferAttachment()
+    : mType(GL_NONE), mResource(nullptr)
+{
+}
+
+FramebufferAttachment::FramebufferAttachment(GLenum type,
+                                             GLenum binding,
+                                             const ImageIndex &textureIndex,
+                                             FramebufferAttachmentObject *resource)
+    : mResource(nullptr)
+{
+    attach(type, binding, textureIndex, resource);
+}
+
+FramebufferAttachment::FramebufferAttachment(const FramebufferAttachment &other)
+    : mResource(nullptr)
+{
+    attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource);
+}
+
+FramebufferAttachment &FramebufferAttachment::operator=(const FramebufferAttachment &other)
+{
+    attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource);
+    return *this;
+}
+
+FramebufferAttachment::~FramebufferAttachment()
+{
+    detach();
+}
+
+void FramebufferAttachment::detach()
+{
+    mType = GL_NONE;
+    if (mResource != nullptr)
+    {
+        mResource->onDetach();
+        mResource = nullptr;
+    }
+
+    // not technically necessary, could omit for performance
+    mTarget = Target();
+}
+
+void FramebufferAttachment::attach(GLenum type,
+                                   GLenum binding,
+                                   const ImageIndex &textureIndex,
+                                   FramebufferAttachmentObject *resource)
+{
+    if (resource == nullptr)
+    {
+        detach();
+        return;
+    }
+
+    mType = type;
+    mTarget = Target(binding, textureIndex);
+    resource->onAttach();
+
+    if (mResource != nullptr)
+    {
+        mResource->onDetach();
+    }
+
+    mResource = resource;
+}
+
+GLuint FramebufferAttachment::getRedSize() const
+{
+    return getFormat().info->redBits;
+}
+
+GLuint FramebufferAttachment::getGreenSize() const
+{
+    return getFormat().info->greenBits;
+}
+
+GLuint FramebufferAttachment::getBlueSize() const
+{
+    return getFormat().info->blueBits;
+}
+
+GLuint FramebufferAttachment::getAlphaSize() const
+{
+    return getFormat().info->alphaBits;
+}
+
+GLuint FramebufferAttachment::getDepthSize() const
+{
+    return getFormat().info->depthBits;
+}
+
+GLuint FramebufferAttachment::getStencilSize() const
+{
+    return getFormat().info->stencilBits;
+}
+
+GLenum FramebufferAttachment::getComponentType() const
+{
+    return getFormat().info->componentType;
+}
+
+GLenum FramebufferAttachment::getColorEncoding() const
+{
+    return getFormat().info->colorEncoding;
+}
+
+GLuint FramebufferAttachment::id() const
+{
+    return mResource->getId();
+}
+
+const ImageIndex &FramebufferAttachment::getTextureImageIndex() const
+{
+    ASSERT(type() == GL_TEXTURE);
+    return mTarget.textureIndex();
+}
+
+GLenum FramebufferAttachment::cubeMapFace() const
+{
+    ASSERT(mType == GL_TEXTURE);
+
+    const auto &index = mTarget.textureIndex();
+    return IsCubeMapTextureTarget(index.type) ? index.type : GL_NONE;
+}
+
+GLint FramebufferAttachment::mipLevel() const
+{
+    ASSERT(type() == GL_TEXTURE);
+    return mTarget.textureIndex().mipIndex;
+}
+
+GLint FramebufferAttachment::layer() const
+{
+    ASSERT(mType == GL_TEXTURE);
+
+    const auto &index = mTarget.textureIndex();
+
+    if (index.type == GL_TEXTURE_2D_ARRAY || index.type == GL_TEXTURE_3D)
+    {
+        return index.layerIndex;
+    }
+    return 0;
+}
+
+Texture *FramebufferAttachment::getTexture() const
+{
+    return rx::GetAs<Texture>(mResource);
+}
+
+Renderbuffer *FramebufferAttachment::getRenderbuffer() const
+{
+    return rx::GetAs<Renderbuffer>(mResource);
+}
+
+const egl::Surface *FramebufferAttachment::getSurface() const
+{
+    return rx::GetAs<egl::Surface>(mResource);
+}
+
+FramebufferAttachmentObject *FramebufferAttachment::getResource() const
+{
+    return mResource;
+}
+
+bool FramebufferAttachment::operator==(const FramebufferAttachment &other) const
+{
+    if (mResource != other.mResource || mType != other.mType)
+    {
+        return false;
+    }
+
+    if (mType == GL_TEXTURE && getTextureImageIndex() != other.getTextureImageIndex())
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool FramebufferAttachment::operator!=(const FramebufferAttachment &other) const
+{
+    return !(*this == other);
+}
+
+Error FramebufferAttachmentObject::getAttachmentRenderTarget(
+    GLenum binding,
+    const ImageIndex &imageIndex,
+    rx::FramebufferAttachmentRenderTarget **rtOut) const
+{
+    return getAttachmentImpl()->getAttachmentRenderTarget(binding, imageIndex, rtOut);
+}
+
+angle::BroadcastChannel<> *FramebufferAttachmentObject::getDirtyChannel()
+{
+    return &mDirtyChannel;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/FramebufferAttachment.h b/src/third_party/angle/src/libANGLE/FramebufferAttachment.h
new file mode 100644
index 0000000..ead0bac
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/FramebufferAttachment.h
@@ -0,0 +1,207 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// 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 LIBANGLE_FRAMEBUFFERATTACHMENT_H_
+#define LIBANGLE_FRAMEBUFFERATTACHMENT_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/signal_utils.h"
+
+namespace egl
+{
+class Surface;
+}
+
+namespace rx
+{
+// An implementation-specific object associated with an attachment.
+
+class FramebufferAttachmentRenderTarget : angle::NonCopyable
+{
+  public:
+    FramebufferAttachmentRenderTarget() {}
+    virtual ~FramebufferAttachmentRenderTarget() {}
+};
+
+class FramebufferAttachmentObjectImpl;
+}
+
+namespace gl
+{
+class FramebufferAttachmentObject;
+struct Format;
+class Renderbuffer;
+class Texture;
+
+// 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 final
+{
+  public:
+    FramebufferAttachment();
+
+    FramebufferAttachment(GLenum type,
+                          GLenum binding,
+                          const ImageIndex &textureIndex,
+                          FramebufferAttachmentObject *resource);
+
+    FramebufferAttachment(const FramebufferAttachment &other);
+    FramebufferAttachment &operator=(const FramebufferAttachment &other);
+
+    ~FramebufferAttachment();
+
+    void detach();
+    void attach(GLenum type,
+                GLenum binding,
+                const ImageIndex &textureIndex,
+                FramebufferAttachmentObject *resource);
+
+    // 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 isTextureWithId(GLuint textureId) const { return mType == GL_TEXTURE && id() == textureId; }
+    bool isRenderbufferWithId(GLuint renderbufferId) const { return mType == GL_RENDERBUFFER && id() == renderbufferId; }
+
+    GLenum getBinding() const { return mTarget.binding(); }
+    GLuint id() const;
+
+    // These methods are only legal to call on Texture attachments
+    const ImageIndex &getTextureImageIndex() const;
+    GLenum cubeMapFace() const;
+    GLint mipLevel() const;
+    GLint layer() const;
+
+    // The size of the underlying resource the attachment points to. The 'depth' value will
+    // correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and
+    // Renderbuffers, it will always be 1.
+    Extents getSize() const;
+    const Format &getFormat() const;
+    GLsizei getSamples() const;
+    GLenum type() const { return mType; }
+    bool isAttached() const { return mType != GL_NONE; }
+
+    Renderbuffer *getRenderbuffer() const;
+    Texture *getTexture() const;
+    const egl::Surface *getSurface() const;
+    FramebufferAttachmentObject *getResource() const;
+
+    // "T" must be static_castable from FramebufferAttachmentRenderTarget
+    template <typename T>
+    gl::Error getRenderTarget(T **rtOut) const
+    {
+        static_assert(std::is_base_of<rx::FramebufferAttachmentRenderTarget, T>(),
+                      "Invalid RenderTarget class.");
+        return getRenderTargetImpl(
+            reinterpret_cast<rx::FramebufferAttachmentRenderTarget **>(rtOut));
+    }
+
+    bool operator==(const FramebufferAttachment &other) const;
+    bool operator!=(const FramebufferAttachment &other) const;
+
+  private:
+    gl::Error getRenderTargetImpl(rx::FramebufferAttachmentRenderTarget **rtOut) const;
+
+    // A framebuffer attachment points to one of three types of resources: Renderbuffers,
+    // Textures and egl::Surface. The "Target" struct indicates which part of the
+    // object an attachment references. For the three types:
+    //   - a Renderbuffer has a unique renderable target, and needs no target index
+    //   - a Texture has targets for every image and uses an ImageIndex
+    //   - a Surface has targets for Color and Depth/Stencil, and uses the attachment binding
+    class Target
+    {
+      public:
+        Target();
+        Target(GLenum binding, const ImageIndex &imageIndex);
+        Target(const Target &other);
+        Target &operator=(const Target &other);
+
+        GLenum binding() const { return mBinding; }
+        const ImageIndex &textureIndex() const { return mTextureIndex; }
+
+      private:
+        GLenum mBinding;
+        ImageIndex mTextureIndex;
+    };
+
+    GLenum mType;
+    Target mTarget;
+    FramebufferAttachmentObject *mResource;
+};
+
+// A base class for objects that FBO Attachments may point to.
+class FramebufferAttachmentObject
+{
+  public:
+    FramebufferAttachmentObject() {}
+    virtual ~FramebufferAttachmentObject() {}
+
+    virtual Extents getAttachmentSize(const ImageIndex &imageIndex) const = 0;
+    virtual const Format &getAttachmentFormat(GLenum binding,
+                                              const ImageIndex &imageIndex) const = 0;
+    virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const      = 0;
+
+    virtual void onAttach() = 0;
+    virtual void onDetach() = 0;
+    virtual GLuint getId() const = 0;
+
+    Error getAttachmentRenderTarget(GLenum binding,
+                                    const ImageIndex &imageIndex,
+                                    rx::FramebufferAttachmentRenderTarget **rtOut) const;
+
+    angle::BroadcastChannel<> *getDirtyChannel();
+
+  protected:
+    virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
+
+    angle::BroadcastChannel<> mDirtyChannel;
+};
+
+inline Extents FramebufferAttachment::getSize() const
+{
+    ASSERT(mResource);
+    return mResource->getAttachmentSize(mTarget.textureIndex());
+}
+
+inline const Format &FramebufferAttachment::getFormat() const
+{
+    ASSERT(mResource);
+    return mResource->getAttachmentFormat(mTarget.binding(), mTarget.textureIndex());
+}
+
+inline GLsizei FramebufferAttachment::getSamples() const
+{
+    ASSERT(mResource);
+    return mResource->getAttachmentSamples(mTarget.textureIndex());
+}
+
+inline gl::Error FramebufferAttachment::getRenderTargetImpl(
+    rx::FramebufferAttachmentRenderTarget **rtOut) const
+{
+    ASSERT(mResource);
+    return mResource->getAttachmentRenderTarget(mTarget.binding(), mTarget.textureIndex(), rtOut);
+}
+
+} // namespace gl
+
+#endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_
diff --git a/src/third_party/angle/src/libANGLE/HandleAllocator.cpp b/src/third_party/angle/src/libANGLE/HandleAllocator.cpp
new file mode 100644
index 0000000..c090b3d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/HandleAllocator.cpp
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2002-2011 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.
+//
+
+// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
+// to allocate GL handles.
+
+#include "libANGLE/HandleAllocator.h"
+
+#include <algorithm>
+
+#include "common/debug.h"
+
+namespace gl
+{
+
+struct HandleAllocator::HandleRangeComparator
+{
+    bool operator()(const HandleRange &range, GLuint handle) const
+    {
+        return (range.end < handle);
+    }
+};
+
+HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1)
+{
+    mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max()));
+}
+
+HandleAllocator::HandleAllocator(GLuint maximumHandleValue) : mBaseValue(1), mNextValue(1)
+{
+    mUnallocatedList.push_back(HandleRange(1, maximumHandleValue));
+}
+
+HandleAllocator::~HandleAllocator()
+{
+}
+
+void HandleAllocator::setBaseHandle(GLuint value)
+{
+    ASSERT(mBaseValue == mNextValue);
+    mBaseValue = value;
+    mNextValue = value;
+}
+
+GLuint HandleAllocator::allocate()
+{
+    ASSERT(!mUnallocatedList.empty() || !mReleasedList.empty());
+
+    // Allocate from released list, constant time.
+    if (!mReleasedList.empty())
+    {
+        GLuint reusedHandle = mReleasedList.back();
+        mReleasedList.pop_back();
+        return reusedHandle;
+    }
+
+    // Allocate from unallocated list, constant time.
+    auto listIt = mUnallocatedList.begin();
+
+    GLuint freeListHandle = listIt->begin;
+    ASSERT(freeListHandle > 0);
+
+    if (listIt->begin == listIt->end)
+    {
+        mUnallocatedList.erase(listIt);
+    }
+    else
+    {
+        listIt->begin++;
+    }
+
+    return freeListHandle;
+}
+
+void HandleAllocator::release(GLuint handle)
+{
+    // Add to released list, constant time.
+    mReleasedList.push_back(handle);
+}
+
+void HandleAllocator::reserve(GLuint handle)
+{
+    // Clear from released list -- might be a slow operation.
+    if (!mReleasedList.empty())
+    {
+        auto releasedIt = std::find(mReleasedList.begin(), mReleasedList.end(), handle);
+        if (releasedIt != mReleasedList.end())
+        {
+            mReleasedList.erase(releasedIt);
+            return;
+        }
+    }
+
+    // Not in released list, reserve in the unallocated list.
+    auto boundIt = std::lower_bound(mUnallocatedList.begin(), mUnallocatedList.end(), handle, HandleRangeComparator());
+
+    ASSERT(boundIt != mUnallocatedList.end());
+
+    GLuint begin = boundIt->begin;
+    GLuint end = boundIt->end;
+
+    if (handle == begin || handle == end)
+    {
+        if (begin == end)
+        {
+            mUnallocatedList.erase(boundIt);
+        }
+        else if (handle == begin)
+        {
+            boundIt->begin++;
+        }
+        else
+        {
+            ASSERT(handle == end);
+            boundIt->end--;
+        }
+        return;
+    }
+
+    ASSERT(begin < handle && handle < end);
+
+    // need to split the range
+    auto placementIt = mUnallocatedList.erase(boundIt);
+    placementIt      = mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end));
+    mUnallocatedList.insert(placementIt, HandleRange(begin, handle - 1));
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/HandleAllocator.h b/src/third_party/angle/src/libANGLE/HandleAllocator.h
new file mode 100644
index 0000000..c7e0a0d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/HandleAllocator.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2002-2011 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.
+//
+
+// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to
+// allocate GL handles.
+
+#ifndef LIBANGLE_HANDLEALLOCATOR_H_
+#define LIBANGLE_HANDLEALLOCATOR_H_
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+#include <stack>
+
+namespace gl
+{
+
+class HandleAllocator final : angle::NonCopyable
+{
+  public:
+    // Maximum handle = MAX_UINT-1
+    HandleAllocator();
+    // Specify maximum handle value
+    HandleAllocator(GLuint maximumHandleValue);
+
+    ~HandleAllocator();
+
+    void setBaseHandle(GLuint value);
+
+    GLuint allocate();
+    void release(GLuint handle);
+    void reserve(GLuint handle);
+
+  private:
+    GLuint mBaseValue;
+    GLuint mNextValue;
+    typedef std::vector<GLuint> HandleList;
+    HandleList mFreeValues;
+
+    // Represents an inclusive range [begin, end]
+    struct HandleRange
+    {
+        HandleRange(GLuint beginIn, GLuint endIn) : begin(beginIn), end(endIn) {}
+
+        GLuint begin;
+        GLuint end;
+    };
+
+    struct HandleRangeComparator;
+
+    // The freelist consists of never-allocated handles, stored
+    // as ranges, and handles that were previously allocated and
+    // released, stored in a stack.
+    std::vector<HandleRange> mUnallocatedList;
+    std::vector<GLuint> mReleasedList;
+};
+
+}  // namespace gl
+
+#endif   // LIBANGLE_HANDLEALLOCATOR_H_
diff --git a/src/third_party/angle/src/libANGLE/HandleAllocator_unittest.cpp b/src/third_party/angle/src/libANGLE/HandleAllocator_unittest.cpp
new file mode 100644
index 0000000..bfcbd8f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/HandleAllocator_unittest.cpp
@@ -0,0 +1,138 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Unit tests for HandleAllocator.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "libANGLE/HandleAllocator.h"
+
+namespace
+{
+
+TEST(HandleAllocatorTest, ReservationsWithGaps)
+{
+    gl::HandleAllocator allocator;
+
+    std::set<GLuint> allocationList;
+    for (GLuint id = 2; id < 50; id += 2)
+    {
+        allocationList.insert(id);
+    }
+
+    for (GLuint id : allocationList)
+    {
+        allocator.reserve(id);
+    }
+
+    std::set<GLuint> allocatedList;
+    for (size_t allocationNum = 0; allocationNum < allocationList.size() * 2; ++allocationNum)
+    {
+        GLuint handle = allocator.allocate();
+        EXPECT_EQ(0u, allocationList.count(handle));
+        EXPECT_EQ(0u, allocatedList.count(handle));
+        allocatedList.insert(handle);
+    }
+}
+
+TEST(HandleAllocatorTest, Random)
+{
+    gl::HandleAllocator allocator;
+
+    std::set<GLuint> allocationList;
+    for (size_t iterationCount = 0; iterationCount < 40; ++iterationCount)
+    {
+        for (size_t randomCount = 0; randomCount < 40; ++randomCount)
+        {
+            GLuint randomHandle = (rand() % 1000) + 1;
+            if (allocationList.count(randomHandle) == 0)
+            {
+                allocator.reserve(randomHandle);
+                allocationList.insert(randomHandle);
+            }
+        }
+
+        for (size_t normalCount = 0; normalCount < 40; ++normalCount)
+        {
+            GLuint normalHandle = allocator.allocate();
+            EXPECT_EQ(0u, allocationList.count(normalHandle));
+            allocationList.insert(normalHandle);
+        }
+    }
+}
+
+TEST(HandleAllocatorTest, Reallocation)
+{
+    // Note: no current test for overflow
+    gl::HandleAllocator limitedAllocator(10);
+
+    for (GLuint count = 1; count < 10; count++)
+    {
+        GLuint result = limitedAllocator.allocate();
+        EXPECT_EQ(count, result);
+    }
+
+    for (GLuint count = 1; count < 10; count++)
+    {
+        limitedAllocator.release(count);
+    }
+
+    for (GLuint count = 2; count < 10; count++)
+    {
+        limitedAllocator.reserve(count);
+    }
+
+    GLint finalResult = limitedAllocator.allocate();
+    EXPECT_EQ(finalResult, 1);
+}
+
+// The following test covers reserving a handle with max uint value. See http://anglebug.com/1052
+TEST(HandleAllocatorTest, ReserveMaxUintHandle)
+{
+    gl::HandleAllocator allocator;
+
+    GLuint maxUintHandle = std::numeric_limits<GLuint>::max();
+    allocator.reserve(maxUintHandle);
+
+    GLuint normalHandle = allocator.allocate();
+    EXPECT_EQ(1u, normalHandle);
+}
+
+// The following test covers reserving a handle with max uint value minus one then max uint value.
+TEST(HandleAllocatorTest, ReserveMaxUintHandle2)
+{
+    gl::HandleAllocator allocator;
+
+    GLuint maxUintHandle = std::numeric_limits<GLuint>::max();
+    allocator.reserve(maxUintHandle - 1);
+    allocator.reserve(maxUintHandle);
+
+    GLuint normalHandle = allocator.allocate();
+    EXPECT_EQ(1u, normalHandle);
+}
+
+// To test if the allocator keep the handle in a sorted order.
+TEST(HandleAllocatorTest, SortedOrderHandle)
+{
+    gl::HandleAllocator allocator;
+
+    allocator.reserve(3);
+
+    GLuint allocatedList[5];
+    for (GLuint count = 0; count < 5; count++)
+    {
+        allocatedList[count] = allocator.allocate();
+    }
+
+    EXPECT_EQ(1u, allocatedList[0]);
+    EXPECT_EQ(2u, allocatedList[1]);
+    EXPECT_EQ(4u, allocatedList[2]);
+    EXPECT_EQ(5u, allocatedList[3]);
+    EXPECT_EQ(6u, allocatedList[4]);
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/HandleRangeAllocator.cpp b/src/third_party/angle/src/libANGLE/HandleRangeAllocator.cpp
new file mode 100644
index 0000000..500a796
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/HandleRangeAllocator.cpp
@@ -0,0 +1,225 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// HandleRangeAllocator.cpp : Implementation for HandleRangeAllocator.h
+
+#include "libANGLE/HandleRangeAllocator.h"
+
+#include <algorithm>
+#include <limits>
+#include <utility>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+const GLuint HandleRangeAllocator::kInvalidHandle = 0;
+
+HandleRangeAllocator::HandleRangeAllocator()
+{
+    // Simplify the code by making sure that lower_bound(id) never
+    // returns the beginning of the map, if id is valid (eg != kInvalidHandle).
+    mUsed.insert(std::make_pair(0u, 0u));
+}
+
+GLuint HandleRangeAllocator::allocate()
+{
+    return allocateRange(1u);
+}
+
+GLuint HandleRangeAllocator::allocateAtOrAbove(GLuint wanted)
+{
+    if (wanted == 0u || wanted == 1u)
+        return allocateRange(1u);
+
+    auto current = mUsed.lower_bound(wanted);
+    auto next = current;
+    if (current == mUsed.end() || current->first > wanted)
+    {
+        current--;
+    }
+    else
+    {
+        next++;
+    }
+
+    GLuint firstId = current->first;
+    GLuint lastId = current->second;
+    ASSERT(wanted >= firstId);
+
+    if (wanted - 1u <= lastId)
+    {
+        // Append to current range.
+        lastId++;
+        if (lastId == 0)
+        {
+            // The increment overflowed.
+            return allocateRange(1u);
+        }
+
+        current->second = lastId;
+
+        if (next != mUsed.end() && next->first - 1u == lastId)
+        {
+            // Merge with next range.
+            current->second = next->second;
+            mUsed.erase(next);
+        }
+        return lastId;
+    }
+    else if (next != mUsed.end() && next->first - 1u == wanted)
+    {
+        // Prepend to next range.
+        GLuint lastExisting = next->second;
+        mUsed.erase(next);
+        mUsed.insert(std::make_pair(wanted, lastExisting));
+        return wanted;
+    }
+    mUsed.insert(std::make_pair(wanted, wanted));
+    return wanted;
+}
+
+GLuint HandleRangeAllocator::allocateRange(GLuint range)
+{
+    ASSERT(range != 0);
+
+    auto current = mUsed.begin();
+    auto next    = current;
+
+    while (++next != mUsed.end())
+    {
+        if (next->first - current->second > range)
+            break;
+        current = next;
+    }
+    const GLuint firstId = current->second + 1u;
+    const GLuint lastId  = firstId + range - 1u;
+
+    // deal with wraparound
+    if (firstId == 0u || lastId < firstId)
+        return kInvalidHandle;
+
+    current->second = lastId;
+
+    if (next != mUsed.end() && next->first - 1u == lastId)
+    {
+        // merge with next range
+        current->second = next->second;
+        mUsed.erase(next);
+    }
+    return firstId;
+}
+
+bool HandleRangeAllocator::markAsUsed(GLuint handle)
+{
+    ASSERT(handle);
+    auto current = mUsed.lower_bound(handle);
+    if (current != mUsed.end() && current->first == handle)
+        return false;
+
+    auto next = current;
+    --current;
+
+    if (current->second >= handle)
+        return false;
+
+    ASSERT(current->first < handle && current->second < handle);
+
+    if (current->second + 1u == handle)
+    {
+        // Append to current range.
+        current->second = handle;
+        if (next != mUsed.end() && next->first - 1u == handle)
+        {
+            // Merge with next range.
+            current->second = next->second;
+            mUsed.erase(next);
+        }
+        return true;
+    }
+    else if (next != mUsed.end() && next->first - 1u == handle)
+    {
+        // Prepend to next range.
+        GLuint lastExisting = next->second;
+        mUsed.erase(next);
+        mUsed.insert(std::make_pair(handle, lastExisting));
+        return true;
+    }
+
+    mUsed.insert(std::make_pair(handle, handle));
+    return true;
+}
+
+void HandleRangeAllocator::release(GLuint handle)
+{
+    releaseRange(handle, 1u);
+}
+
+void HandleRangeAllocator::releaseRange(GLuint first, GLuint range)
+{
+    if (range == 0u || (first == 0u && range == 1u))
+        return;
+
+    if (first == 0u)
+    {
+        first++;
+        range--;
+    }
+
+    GLuint last = first + range - 1u;
+    if (last < first)
+        last = std::numeric_limits<GLuint>::max();
+
+    while (true)
+    {
+        auto current = mUsed.lower_bound(last);
+        if (current == mUsed.end() || current->first > last)
+            --current;
+
+        if (current->second < first)
+            return;
+
+        if (current->first >= first)
+        {
+            const GLuint lastExisting = current->second;
+            mUsed.erase(current);
+            if (last < lastExisting)
+            {
+                mUsed.insert(std::make_pair(last + 1u, lastExisting));
+            }
+        }
+        else if (current->second <= last)
+        {
+            current->second = first - 1u;
+        }
+        else
+        {
+            ASSERT(current->first < first && current->second > last);
+            const GLuint lastExisting = current->second;
+            current->second = first - 1u;
+            mUsed.insert(std::make_pair(last + 1u, lastExisting));
+        }
+    }
+}
+
+bool HandleRangeAllocator::isUsed(GLuint handle) const
+{
+    if (handle == kInvalidHandle)
+        return false;
+
+    auto current = mUsed.lower_bound(handle);
+    if (current != mUsed.end())
+    {
+        if (current->first == handle)
+            return true;
+    }
+    --current;
+    return current->second >= handle;
+}
+
+}  // namespace gl
\ No newline at end of file
diff --git a/src/third_party/angle/src/libANGLE/HandleRangeAllocator.h b/src/third_party/angle/src/libANGLE/HandleRangeAllocator.h
new file mode 100644
index 0000000..20f9a11
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/HandleRangeAllocator.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+
+// HandleRangeAllocator.h: Defines the gl::HandleRangeAllocator class, which is used to
+// allocate contiguous ranges of GL path handles.
+
+#ifndef LIBANGLE_HANDLERANGEALLOCATOR_H_
+#define LIBANGLE_HANDLERANGEALLOCATOR_H_
+
+#include <map>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+namespace gl
+{
+
+// Allocates contiguous ranges of path object handles.
+class HandleRangeAllocator final : angle::NonCopyable
+{
+  public:
+    static const GLuint kInvalidHandle;
+
+    HandleRangeAllocator();
+
+    // Allocates a new path handle.
+    GLuint allocate();
+
+    // Allocates a handle starting at or above the value of |wanted|.
+    // Note: may wrap if it starts near limit.
+    GLuint allocateAtOrAbove(GLuint wanted);
+
+    // Allocates |range| amount of contiguous paths.
+    // Returns the first id to |first_id| or |kInvalidHandle| if
+    // allocation failed.
+    GLuint allocateRange(GLuint range);
+
+    // Marks an id as used. Returns false if handle was already used.
+    bool markAsUsed(GLuint handle);
+
+    // Release handle.
+    void release(GLuint handle);
+
+    // Release a |range| amount of contiguous handles, starting from |first|
+    void releaseRange(GLuint first, GLuint range);
+
+    // Checks whether or not a resource ID is in use.
+    bool isUsed(GLuint handle) const;
+
+  private:
+    std::map<GLuint, GLuint> mUsed;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_HANDLERANGEALLOCATOR_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libANGLE/HandleRangeAllocator_unittest.cpp b/src/third_party/angle/src/libANGLE/HandleRangeAllocator_unittest.cpp
new file mode 100644
index 0000000..1d825f7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/HandleRangeAllocator_unittest.cpp
@@ -0,0 +1,275 @@
+//
+// Copyright 2016 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.
+//
+// Unit tests for HandleRangeAllocator.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "libANGLE/HandleRangeAllocator.h"
+
+namespace
+{
+
+class HandleRangeAllocatorTest : public testing::Test
+{
+  protected:
+    gl::HandleRangeAllocator *getAllocator() { return &mAllocator; }
+
+  private:
+    gl::HandleRangeAllocator mAllocator;
+};
+
+// Checks basic functionality: allocate, release, isUsed.
+TEST_F(HandleRangeAllocatorTest, TestBasic)
+{
+    auto *allocator = getAllocator();
+    // Check that resource 1 is not in use
+    EXPECT_FALSE(allocator->isUsed(1));
+
+    // Allocate an ID, check that it's in use.
+    GLuint id1 = allocator->allocate();
+    EXPECT_TRUE(allocator->isUsed(id1));
+
+    // Allocate another ID, check that it's in use, and different from the first
+    // one.
+    GLuint id2 = allocator->allocate();
+    EXPECT_TRUE(allocator->isUsed(id2));
+    EXPECT_NE(id1, id2);
+
+    // Free one of the IDs, check that it's not in use any more.
+    allocator->release(id1);
+    EXPECT_FALSE(allocator->isUsed(id1));
+
+    // Frees the other ID, check that it's not in use any more.
+    allocator->release(id2);
+    EXPECT_FALSE(allocator->isUsed(id2));
+}
+
+// Checks that the resource handles are re-used after being freed.
+TEST_F(HandleRangeAllocatorTest, TestAdvanced)
+{
+    auto *allocator = getAllocator();
+
+    // Allocate the highest possible ID, to make life awkward.
+    allocator->allocateAtOrAbove(~static_cast<GLuint>(0));
+
+    // Allocate a significant number of resources.
+    const unsigned int kNumResources = 100;
+    GLuint ids[kNumResources];
+    for (unsigned int i = 0; i < kNumResources; ++i)
+    {
+        ids[i] = allocator->allocate();
+        EXPECT_TRUE(allocator->isUsed(ids[i]));
+    }
+
+    // Check that a new allocation re-uses the resource we just freed.
+    GLuint id1 = ids[kNumResources / 2];
+    allocator->release(id1);
+    EXPECT_FALSE(allocator->isUsed(id1));
+    GLuint id2 = allocator->allocate();
+    EXPECT_TRUE(allocator->isUsed(id2));
+    EXPECT_EQ(id1, id2);
+}
+
+// Checks that we can choose our own ids and they won't be reused.
+TEST_F(HandleRangeAllocatorTest, MarkAsUsed)
+{
+    auto *allocator = getAllocator();
+    GLuint id = allocator->allocate();
+    allocator->release(id);
+    EXPECT_FALSE(allocator->isUsed(id));
+    EXPECT_TRUE(allocator->markAsUsed(id));
+    EXPECT_TRUE(allocator->isUsed(id));
+    GLuint id2 = allocator->allocate();
+    EXPECT_NE(id, id2);
+    EXPECT_TRUE(allocator->markAsUsed(id2 + 1));
+    GLuint id3 = allocator->allocate();
+    // Checks our algorithm. If the algorithm changes this check should be
+    // changed.
+    EXPECT_EQ(id3, id2 + 2);
+}
+
+// Checks allocateAtOrAbove.
+TEST_F(HandleRangeAllocatorTest, AllocateAtOrAbove)
+{
+    const GLuint kOffset = 123456;
+    auto *allocator      = getAllocator();
+    GLuint id1 = allocator->allocateAtOrAbove(kOffset);
+    EXPECT_EQ(kOffset, id1);
+    GLuint id2 = allocator->allocateAtOrAbove(kOffset);
+    EXPECT_GT(id2, kOffset);
+    GLuint id3 = allocator->allocateAtOrAbove(kOffset);
+    EXPECT_GT(id3, kOffset);
+}
+
+// Checks that allocateAtOrAbove wraps around at the maximum value.
+TEST_F(HandleRangeAllocatorTest, AllocateIdAtOrAboveWrapsAround)
+{
+    const GLuint kMaxPossibleOffset = ~static_cast<GLuint>(0);
+    auto *allocator                 = getAllocator();
+    GLuint id1 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+    EXPECT_EQ(kMaxPossibleOffset, id1);
+    GLuint id2 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+    EXPECT_EQ(1u, id2);
+    GLuint id3 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+    EXPECT_EQ(2u, id3);
+}
+
+// Checks that freeing an already freed range causes no harm.
+TEST_F(HandleRangeAllocatorTest, RedundantFreeIsIgnored)
+{
+    auto *allocator = getAllocator();
+    GLuint id1 = allocator->allocate();
+    allocator->release(0);
+    allocator->release(id1);
+    allocator->release(id1);
+    allocator->release(id1 + 1);
+    GLuint id2 = allocator->allocate();
+    GLuint id3 = allocator->allocate();
+    EXPECT_NE(id2, id3);
+    EXPECT_NE(allocator->kInvalidHandle, id2);
+    EXPECT_NE(allocator->kInvalidHandle, id3);
+}
+
+// Check allocating and releasing multiple ranges.
+TEST_F(HandleRangeAllocatorTest, allocateRange)
+{
+    const GLuint kMaxPossibleOffset = std::numeric_limits<GLuint>::max();
+
+    auto *allocator = getAllocator();
+
+    GLuint id1 = allocator->allocateRange(1);
+    EXPECT_EQ(1u, id1);
+    GLuint id2 = allocator->allocateRange(2);
+    EXPECT_EQ(2u, id2);
+    GLuint id3 = allocator->allocateRange(3);
+    EXPECT_EQ(4u, id3);
+    GLuint id4 = allocator->allocate();
+    EXPECT_EQ(7u, id4);
+    allocator->release(3);
+    GLuint id5 = allocator->allocateRange(1);
+    EXPECT_EQ(3u, id5);
+    allocator->release(5);
+    allocator->release(2);
+    allocator->release(4);
+    GLuint id6 = allocator->allocateRange(2);
+    EXPECT_EQ(4u, id6);
+    GLuint id7 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+    EXPECT_EQ(kMaxPossibleOffset, id7);
+    GLuint id8 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+    EXPECT_EQ(2u, id8);
+    GLuint id9 = allocator->allocateRange(50);
+    EXPECT_EQ(8u, id9);
+    GLuint id10 = allocator->allocateRange(50);
+    EXPECT_EQ(58u, id10);
+    // Remove all the low-numbered ids.
+    allocator->release(1);
+    allocator->release(15);
+    allocator->releaseRange(2, 107);
+    GLuint id11 = allocator->allocateRange(100);
+    EXPECT_EQ(1u, id11);
+    allocator->release(kMaxPossibleOffset);
+    GLuint id12 = allocator->allocateRange(100);
+    EXPECT_EQ(101u, id12);
+
+    GLuint id13 = allocator->allocateAtOrAbove(kMaxPossibleOffset - 2u);
+    EXPECT_EQ(kMaxPossibleOffset - 2u, id13);
+    GLuint id14 = allocator->allocateRange(3);
+    EXPECT_EQ(201u, id14);
+}
+
+// Checks that having allocated a high range doesn't interfere
+// with normal low range allocation.
+TEST_F(HandleRangeAllocatorTest, AllocateRangeEndNoEffect)
+{
+    const GLuint kMaxPossibleOffset = std::numeric_limits<GLuint>::max();
+
+    auto *allocator = getAllocator();
+    GLuint id1 = allocator->allocateAtOrAbove(kMaxPossibleOffset - 2u);
+    EXPECT_EQ(kMaxPossibleOffset - 2u, id1);
+    GLuint id3 = allocator->allocateRange(3);
+    EXPECT_EQ(1u, id3);
+    GLuint id2 = allocator->allocateRange(2);
+    EXPECT_EQ(4u, id2);
+}
+
+// Checks allocating a range that consumes the whole uint32 space.
+TEST_F(HandleRangeAllocatorTest, AllocateMax)
+{
+    const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
+
+    auto *allocator = getAllocator();
+    GLuint id = allocator->allocateRange(kMaxPossibleRange);
+    EXPECT_EQ(1u, id);
+    allocator->releaseRange(id, kMaxPossibleRange - 1u);
+    GLuint id2 = allocator->allocateRange(kMaxPossibleRange);
+    EXPECT_EQ(0u, id2);
+    allocator->releaseRange(id, kMaxPossibleRange);
+    GLuint id3 = allocator->allocateRange(kMaxPossibleRange);
+    EXPECT_EQ(1u, id3);
+}
+
+// Checks allocating a range that consumes the whole uint32 space
+// causes next allocation to fail.
+// Subsequently checks that once the big range is reduced new allocations
+// are possible.
+TEST_F(HandleRangeAllocatorTest, AllocateFullRange)
+{
+    const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
+    const GLuint kFreedId            = 555u;
+    auto *allocator                  = getAllocator();
+
+    GLuint id1 = allocator->allocateRange(kMaxPossibleRange);
+    EXPECT_EQ(1u, id1);
+    GLuint id2 = allocator->allocate();
+    EXPECT_EQ(gl::HandleRangeAllocator::kInvalidHandle, id2);
+    allocator->release(kFreedId);
+    GLuint id3 = allocator->allocate();
+    EXPECT_EQ(kFreedId, id3);
+    GLuint id4 = allocator->allocate();
+    EXPECT_EQ(0u, id4);
+    allocator->release(kFreedId + 1u);
+    allocator->release(kFreedId + 4u);
+    allocator->release(kFreedId + 3u);
+    allocator->release(kFreedId + 5u);
+    allocator->release(kFreedId + 2u);
+    GLuint id5 = allocator->allocateRange(5);
+    EXPECT_EQ(kFreedId + 1u, id5);
+}
+
+// Checks that allocating a range that exceeds uint32
+// does not wrap incorrectly and fails.
+TEST_F(HandleRangeAllocatorTest, AllocateRangeNoWrapInRange)
+{
+    const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
+    const GLuint kAllocId            = 10u;
+    auto *allocator                  = getAllocator();
+
+    GLuint id1 = allocator->allocateAtOrAbove(kAllocId);
+    EXPECT_EQ(kAllocId, id1);
+    GLuint id2 = allocator->allocateRange(kMaxPossibleRange - 5u);
+    EXPECT_EQ(0u, id2);
+    GLuint id3 = allocator->allocateRange(kMaxPossibleRange - kAllocId);
+    EXPECT_EQ(kAllocId + 1u, id3);
+}
+
+// Check special cases for 0 range allocations and zero handles.
+TEST_F(HandleRangeAllocatorTest, ZeroIdCases)
+{
+    auto *allocator = getAllocator();
+    EXPECT_FALSE(allocator->isUsed(0));
+    GLuint id1 = allocator->allocateAtOrAbove(0);
+    EXPECT_NE(0u, id1);
+    EXPECT_FALSE(allocator->isUsed(0));
+    allocator->release(0);
+    EXPECT_FALSE(allocator->isUsed(0));
+    EXPECT_TRUE(allocator->isUsed(id1));
+    allocator->release(id1);
+    EXPECT_FALSE(allocator->isUsed(id1));
+}
+
+}  // namespace
\ No newline at end of file
diff --git a/src/third_party/angle/src/libANGLE/Image.cpp b/src/third_party/angle/src/libANGLE/Image.cpp
new file mode 100644
index 0000000..194fad1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Image.cpp
@@ -0,0 +1,191 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image.cpp: Implements the egl::Image class representing the EGLimage object.
+
+#include "libANGLE/Image.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace egl
+{
+
+namespace
+{
+gl::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
+{
+    if (eglTarget == EGL_GL_RENDERBUFFER)
+    {
+        return gl::ImageIndex::MakeInvalid();
+    }
+
+    GLenum target = egl_gl::EGLImageTargetToGLTextureTarget(eglTarget);
+    GLint mip     = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0));
+    GLint layer   = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0));
+
+    if (target == GL_TEXTURE_3D)
+    {
+        return gl::ImageIndex::Make3D(mip, layer);
+    }
+    else
+    {
+        ASSERT(layer == 0);
+        return gl::ImageIndex::MakeGeneric(target, mip);
+    }
+}
+}  // anonymous namespace
+
+ImageSibling::ImageSibling(GLuint id) : RefCountObject(id), mSourcesOf(), mTargetOf()
+{
+}
+
+ImageSibling::~ImageSibling()
+{
+    // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
+    // while it is attached to an EGL image.
+    ASSERT(mSourcesOf.empty());
+    orphanImages();
+}
+
+void ImageSibling::setTargetImage(egl::Image *imageTarget)
+{
+    ASSERT(imageTarget != nullptr);
+    mTargetOf.set(imageTarget);
+    imageTarget->addTargetSibling(this);
+}
+
+gl::Error ImageSibling::orphanImages()
+{
+    if (mTargetOf.get() != nullptr)
+    {
+        // Can't be a target and have sources.
+        ASSERT(mSourcesOf.empty());
+
+        ANGLE_TRY(mTargetOf->orphanSibling(this));
+        mTargetOf.set(nullptr);
+    }
+    else
+    {
+        for (auto &sourceImage : mSourcesOf)
+        {
+            ANGLE_TRY(sourceImage->orphanSibling(this));
+        }
+        mSourcesOf.clear();
+    }
+
+    return gl::NoError();
+}
+
+void ImageSibling::addImageSource(egl::Image *imageSource)
+{
+    ASSERT(imageSource != nullptr);
+    mSourcesOf.insert(imageSource);
+}
+
+void ImageSibling::removeImageSource(egl::Image *imageSource)
+{
+    ASSERT(mSourcesOf.find(imageSource) != mSourcesOf.end());
+    mSourcesOf.erase(imageSource);
+}
+
+ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
+    : imageIndex(GetImageIndex(target, attribs)), source(), targets()
+{
+    source.set(buffer);
+}
+
+Image::Image(rx::EGLImplFactory *factory,
+             EGLenum target,
+             ImageSibling *buffer,
+             const AttributeMap &attribs)
+    : RefCountObject(0),
+      mState(target, buffer, attribs),
+      mImplementation(factory->createImage(mState, target, attribs))
+{
+    ASSERT(mImplementation != nullptr);
+    ASSERT(buffer != nullptr);
+
+    mState.source->addImageSource(this);
+}
+
+Image::~Image()
+{
+    SafeDelete(mImplementation);
+
+    // All targets should hold a ref to the egl image and it should not be deleted until there are
+    // no siblings left.
+    ASSERT(mState.targets.empty());
+
+    // Tell the source that it is no longer used by this image
+    if (mState.source.get() != nullptr)
+    {
+        mState.source->removeImageSource(this);
+        mState.source.set(nullptr);
+    }
+}
+
+void Image::addTargetSibling(ImageSibling *sibling)
+{
+    mState.targets.insert(sibling);
+}
+
+gl::Error Image::orphanSibling(ImageSibling *sibling)
+{
+    // notify impl
+    ANGLE_TRY(mImplementation->orphan(sibling));
+
+    if (mState.source.get() == sibling)
+    {
+        // If the sibling is the source, it cannot be a target.
+        ASSERT(mState.targets.find(sibling) == mState.targets.end());
+        mState.source.set(nullptr);
+    }
+    else
+    {
+        mState.targets.erase(sibling);
+    }
+
+    return gl::NoError();
+}
+
+const gl::Format &Image::getFormat() const
+{
+    return mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex);
+}
+
+size_t Image::getWidth() const
+{
+    return mState.source->getAttachmentSize(mState.imageIndex).width;
+}
+
+size_t Image::getHeight() const
+{
+    return mState.source->getAttachmentSize(mState.imageIndex).height;
+}
+
+size_t Image::getSamples() const
+{
+    return mState.source->getAttachmentSamples(mState.imageIndex);
+}
+
+rx::ImageImpl *Image::getImplementation() const
+{
+    return mImplementation;
+}
+
+Error Image::initialize()
+{
+    return mImplementation->initialize();
+}
+
+}  // namespace egl
diff --git a/src/third_party/angle/src/libANGLE/Image.h b/src/third_party/angle/src/libANGLE/Image.h
new file mode 100644
index 0000000..adb5f23
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Image.h
@@ -0,0 +1,103 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image.h: Defines the egl::Image class representing the EGLimage object.
+
+#ifndef LIBANGLE_IMAGE_H_
+#define LIBANGLE_IMAGE_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/formatutils.h"
+
+#include <set>
+
+namespace rx
+{
+class EGLImplFactory;
+class ImageImpl;
+}
+
+namespace egl
+{
+class Image;
+
+// Only currently Renderbuffers and Textures can be bound with images. This makes the relationship
+// explicit, and also ensures that an image sibling can determine if it's been initialized or not,
+// which is important for the robust resource init extension with Textures and EGLImages.
+class ImageSibling : public RefCountObject, public gl::FramebufferAttachmentObject
+{
+  public:
+    ImageSibling(GLuint id);
+    virtual ~ImageSibling();
+
+  protected:
+    // Set the image target of this sibling
+    void setTargetImage(egl::Image *imageTarget);
+
+    // Orphan all EGL image sources and targets
+    gl::Error orphanImages();
+
+  private:
+    friend class Image;
+
+    // Called from Image only to add a new source image
+    void addImageSource(egl::Image *imageSource);
+
+    // Called from Image only to remove a source image when the Image is being deleted
+    void removeImageSource(egl::Image *imageSource);
+
+    std::set<Image *> mSourcesOf;
+    BindingPointer<Image> mTargetOf;
+};
+
+struct ImageState : private angle::NonCopyable
+{
+    ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
+
+    gl::ImageIndex imageIndex;
+    BindingPointer<ImageSibling> source;
+    std::set<ImageSibling *> targets;
+};
+
+class Image final : public RefCountObject
+{
+  public:
+    Image(rx::EGLImplFactory *factory,
+          EGLenum target,
+          ImageSibling *buffer,
+          const AttributeMap &attribs);
+    ~Image();
+
+    const gl::Format &getFormat() const;
+    size_t getWidth() const;
+    size_t getHeight() const;
+    size_t getSamples() const;
+
+    Error initialize();
+
+    rx::ImageImpl *getImplementation() const;
+
+  private:
+    friend class ImageSibling;
+
+    // Called from ImageSibling only notify the image that a new target sibling exists for state
+    // tracking.
+    void addTargetSibling(ImageSibling *sibling);
+
+    // Called from ImageSibling only to notify the image that a sibling (source or target) has
+    // been respecified and state tracking should be updated.
+    gl::Error orphanSibling(ImageSibling *sibling);
+
+    ImageState mState;
+    rx::ImageImpl *mImplementation;
+};
+}  // namespace egl
+
+#endif  // LIBANGLE_IMAGE_H_
diff --git a/src/third_party/angle/src/libANGLE/ImageIndex.cpp b/src/third_party/angle/src/libANGLE/ImageIndex.cpp
new file mode 100644
index 0000000..2318541
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/ImageIndex.cpp
@@ -0,0 +1,223 @@
+#include "ImageIndex.h"
+//
+// 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 "libANGLE/ImageIndex.h"
+#include "libANGLE/Constants.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;
+}
+
+bool ImageIndex::is3D() const
+{
+    return type == GL_TEXTURE_3D || type == GL_TEXTURE_2D_ARRAY;
+}
+
+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,
+                      static_cast<GLint>(CubeMapTextureTargetToLayerIndex(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::MakeGeneric(GLenum target, GLint mipIndex)
+{
+    GLint layerIndex = IsCubeMapTextureTarget(target)
+                           ? static_cast<GLint>(CubeMapTextureTargetToLayerIndex(target))
+                           : ENTIRE_LEVEL;
+    return ImageIndex(target, mipIndex, layerIndex);
+}
+
+ImageIndex ImageIndex::Make2DMultisample()
+{
+    return ImageIndex(GL_TEXTURE_2D_MULTISAMPLE, 0, ENTIRE_LEVEL);
+}
+
+ImageIndex ImageIndex::MakeInvalid()
+{
+    return ImageIndex(GL_NONE, -1, -1);
+}
+
+bool ImageIndex::operator<(const ImageIndex &other) const
+{
+    if (type != other.type)
+    {
+        return type < other.type;
+    }
+    else if (mipIndex != other.mipIndex)
+    {
+        return mipIndex < other.mipIndex;
+    }
+    else
+    {
+        return layerIndex < other.layerIndex;
+    }
+}
+
+bool ImageIndex::operator==(const ImageIndex &other) const
+{
+    return (type == other.type) && (mipIndex == other.mipIndex) && (layerIndex == other.layerIndex);
+}
+
+bool ImageIndex::operator!=(const ImageIndex &other) const
+{
+    return !(*this == other);
+}
+
+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, Range<GLint>(minMip, maxMip),
+                              Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
+                              nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
+{
+    return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, Range<GLint>(minMip, maxMip), Range<GLint>(0, 6),
+                              nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip,
+                                              GLint minLayer, GLint maxLayer)
+{
+    return ImageIndexIterator(GL_TEXTURE_3D, Range<GLint>(minMip, maxMip),
+                              Range<GLint>(minLayer, maxLayer), nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
+                                                   const GLsizei *layerCounts)
+{
+    return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, Range<GLint>(minMip, maxMip),
+                              Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts);
+}
+
+ImageIndexIterator ImageIndexIterator::Make2DMultisample()
+{
+    return ImageIndexIterator(GL_TEXTURE_2D_MULTISAMPLE, Range<GLint>(0, 0),
+                              Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
+                              nullptr);
+}
+
+ImageIndexIterator::ImageIndexIterator(GLenum type, const Range<GLint> &mipRange,
+                                       const Range<GLint> &layerRange, const GLsizei *layerCounts)
+    : mType(type),
+      mMipRange(mipRange),
+      mLayerRange(layerRange),
+      mLayerCounts(layerCounts),
+      mCurrentMip(mipRange.start),
+      mCurrentLayer(layerRange.start)
+{}
+
+GLint ImageIndexIterator::maxLayer() const
+{
+    if (mLayerCounts)
+    {
+        ASSERT(mCurrentMip >= 0);
+        return (mCurrentMip < mMipRange.end) ? mLayerCounts[mCurrentMip] : 0;
+    }
+    return 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
+        {
+            done();
+        }
+    }
+    else if (mCurrentMip < mMipRange.end - 1)
+    {
+        mCurrentMip++;
+        mCurrentLayer = mLayerRange.start;
+    }
+    else
+    {
+        done();
+    }
+
+    return value;
+}
+
+ImageIndex ImageIndexIterator::current() const
+{
+    ImageIndex value(mType, mCurrentMip, mCurrentLayer);
+
+    if (mType == GL_TEXTURE_CUBE_MAP)
+    {
+        value.type = LayerIndexToCubeMapTextureTarget(mCurrentLayer);
+    }
+
+    return value;
+}
+
+bool ImageIndexIterator::hasNext() const
+{
+    return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer());
+}
+
+void ImageIndexIterator::done()
+{
+    mCurrentMip   = mMipRange.end;
+    mCurrentLayer = maxLayer();
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/ImageIndex.h b/src/third_party/angle/src/libANGLE/ImageIndex.h
new file mode 100644
index 0000000..5992784
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/ImageIndex.h
@@ -0,0 +1,85 @@
+//
+// 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 LIBANGLE_IMAGE_INDEX_H_
+#define LIBANGLE_IMAGE_INDEX_H_
+
+#include "common/mathutil.h"
+
+#include "angle_gl.h"
+
+namespace gl
+{
+
+class ImageIndexIterator;
+
+struct ImageIndex
+{
+    GLenum type;
+    GLint mipIndex;
+    GLint layerIndex;
+
+    ImageIndex(const ImageIndex &other);
+    ImageIndex &operator=(const ImageIndex &other);
+
+    bool hasLayer() const { return layerIndex != ENTIRE_LEVEL; }
+    bool is3D() const;
+
+    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 ImageIndex MakeGeneric(GLenum target, GLint mipIndex);
+    static ImageIndex Make2DMultisample();
+
+    static ImageIndex MakeInvalid();
+
+    static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
+
+    bool operator<(const ImageIndex &other) const;
+    bool operator==(const ImageIndex &other) const;
+    bool operator!=(const ImageIndex &other) const;
+
+  private:
+    friend class ImageIndexIterator;
+
+    ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
+};
+
+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);
+    static ImageIndexIterator Make2DMultisample();
+
+    ImageIndex next();
+    ImageIndex current() const;
+    bool hasNext() const;
+
+  private:
+
+    ImageIndexIterator(GLenum type, const Range<GLint> &mipRange,
+                       const Range<GLint> &layerRange, const GLsizei *layerCounts);
+
+    GLint maxLayer() const;
+    void done();
+
+    GLenum mType;
+    Range<GLint> mMipRange;
+    Range<GLint> mLayerRange;
+    const GLsizei *mLayerCounts;
+    GLint mCurrentMip;
+    GLint mCurrentLayer;
+};
+
+}
+
+#endif // LIBANGLE_IMAGE_INDEX_H_
diff --git a/src/third_party/angle/src/libANGLE/ImageIndexIterator_unittest.cpp b/src/third_party/angle/src/libANGLE/ImageIndexIterator_unittest.cpp
new file mode 100644
index 0000000..2f97e8e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/ImageIndexIterator_unittest.cpp
@@ -0,0 +1,122 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "common/utilities.h"
+#include "libANGLE/ImageIndex.h"
+
+using namespace gl;
+
+namespace
+{
+
+static const GLint minMip = 0;
+static const GLint maxMip = 4;
+static const GLint minLayer = 1;
+static const GLint maxLayer = 3;
+
+TEST(ImageIndexTest, Iterator2D)
+{
+    ImageIndexIterator iter = ImageIndexIterator::Make2D(minMip, maxMip);
+
+    ASSERT_GE(0, minMip);
+
+    for (GLint mip = minMip; mip < maxMip; mip++)
+    {
+        EXPECT_TRUE(iter.hasNext());
+        ImageIndex current = iter.current();
+        ImageIndex nextIndex = iter.next();
+
+        EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), nextIndex.type);
+        EXPECT_EQ(mip, nextIndex.mipIndex);
+        EXPECT_FALSE(nextIndex.hasLayer());
+
+        // Also test current
+        EXPECT_EQ(current.type, nextIndex.type);
+        EXPECT_EQ(current.mipIndex, nextIndex.mipIndex);
+        EXPECT_EQ(current.layerIndex, nextIndex.layerIndex);
+    }
+
+    EXPECT_FALSE(iter.hasNext());
+}
+
+TEST(ImageIndexTest, IteratorCube)
+{
+    ImageIndexIterator iter = ImageIndexIterator::MakeCube(0, 4);
+
+    ASSERT_GE(0, minMip);
+
+    for (GLint mip = minMip; mip < maxMip; mip++)
+    {
+        for (GLint layer = 0; layer < 6; layer++)
+        {
+            EXPECT_TRUE(iter.hasNext());
+            ImageIndex nextIndex = iter.next();
+
+            GLenum cubeTarget = LayerIndexToCubeMapTextureTarget(layer);
+
+            EXPECT_EQ(cubeTarget, nextIndex.type);
+            EXPECT_EQ(mip, nextIndex.mipIndex);
+            EXPECT_EQ(layer, nextIndex.layerIndex);
+            EXPECT_TRUE(nextIndex.hasLayer());
+        }
+    }
+
+    EXPECT_FALSE(iter.hasNext());
+}
+
+TEST(ImageIndexTest, Iterator3D)
+{
+    ImageIndexIterator iter = ImageIndexIterator::Make3D(minMip, maxMip, minLayer, maxLayer);
+
+    ASSERT_GE(0, minMip);
+
+    for (GLint mip = minMip; mip < maxMip; mip++)
+    {
+        for (GLint layer = minLayer; layer < maxLayer; layer++)
+        {
+            EXPECT_TRUE(iter.hasNext());
+            ImageIndex nextIndex = iter.next();
+
+            EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_3D), nextIndex.type);
+            EXPECT_EQ(mip, nextIndex.mipIndex);
+            EXPECT_EQ(layer, nextIndex.layerIndex);
+            EXPECT_TRUE(nextIndex.hasLayer());
+        }
+    }
+
+    EXPECT_FALSE(iter.hasNext());
+}
+
+TEST(ImageIndexTest, Iterator2DArray)
+{
+    GLsizei layerCounts[] = { 1, 3, 5, 2 };
+
+    ImageIndexIterator iter = ImageIndexIterator::Make2DArray(minMip, maxMip, layerCounts);
+
+    ASSERT_GE(0, minMip);
+    ASSERT_EQ(ArraySize(layerCounts), static_cast<size_t>(maxMip));
+
+    for (GLint mip = minMip; mip < maxMip; mip++)
+    {
+        for (GLint layer = 0; layer < layerCounts[mip]; layer++)
+        {
+            EXPECT_TRUE(iter.hasNext());
+            ImageIndex nextIndex = iter.next();
+
+            EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D_ARRAY), nextIndex.type);
+            EXPECT_EQ(mip, nextIndex.mipIndex);
+            EXPECT_EQ(layer, nextIndex.layerIndex);
+            EXPECT_TRUE(nextIndex.hasLayer());
+        }
+    }
+
+    EXPECT_FALSE(iter.hasNext());
+}
+
+} // namespace
diff --git a/src/third_party/angle/src/libANGLE/Image_unittest.cpp b/src/third_party/angle/src/libANGLE/Image_unittest.cpp
new file mode 100644
index 0000000..8d70b57
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Image_unittest.cpp
@@ -0,0 +1,152 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image_unittest.cpp : Unittets of the Image and ImageSibling classes.
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/renderer/ImageImpl_mock.h"
+#include "libANGLE/renderer/TextureImpl_mock.h"
+#include "libANGLE/renderer/RenderbufferImpl_mock.h"
+#include "tests/angle_unittests_utils.h"
+
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+
+namespace angle
+{
+ACTION(CreateMockImageImpl)
+{
+    return new rx::MockImageImpl(arg0, arg1, arg2);
+}
+
+// Verify ref counts are maintained between images and their siblings when objects are deleted
+TEST(ImageTest, RefCounting)
+{
+    NiceMock<rx::MockGLFactory> mockGLFactory;
+    NiceMock<rx::MockEGLFactory> mockEGLFactory;
+
+    // Create a texture and an EGL image that uses the texture as its source
+    rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
+    EXPECT_CALL(mockGLFactory, createTexture(_)).WillOnce(Return(textureImpl));
+    gl::Texture *texture = new gl::Texture(&mockGLFactory, 1, GL_TEXTURE_2D);
+    texture->addRef();
+
+    EXPECT_CALL(mockEGLFactory, createImage(_, _, _))
+        .WillOnce(CreateMockImageImpl())
+        .RetiresOnSaturation();
+
+    egl::Image *image =
+        new egl::Image(&mockEGLFactory, EGL_GL_TEXTURE_2D, texture, egl::AttributeMap());
+    image->addRef();
+
+    // Verify that the image added a ref to the texture and the texture has not added a ref to the
+    // image
+    EXPECT_EQ(2u, texture->getRefCount());
+    EXPECT_EQ(1u, image->getRefCount());
+
+    // Create a renderbuffer and set it as a target of the EGL image
+    rx::MockRenderbufferImpl *renderbufferImpl = new rx::MockRenderbufferImpl();
+    gl::Renderbuffer *renderbuffer = new gl::Renderbuffer(renderbufferImpl, 1);
+    renderbuffer->addRef();
+
+    EXPECT_CALL(*renderbufferImpl, setStorageEGLImageTarget(_))
+        .WillOnce(Return(gl::NoError()))
+        .RetiresOnSaturation();
+    renderbuffer->setStorageEGLImageTarget(image);
+
+    // Verify that the renderbuffer added a ref to the image and the image did not add a ref to
+    // the renderbuffer
+    EXPECT_EQ(2u, texture->getRefCount());
+    EXPECT_EQ(2u, image->getRefCount());
+    EXPECT_EQ(1u, renderbuffer->getRefCount());
+
+    // Simulate deletion of the texture and verify that it still exists because the image holds a
+    // ref
+    texture->release();
+    EXPECT_EQ(1u, texture->getRefCount());
+    EXPECT_EQ(2u, image->getRefCount());
+    EXPECT_EQ(1u, renderbuffer->getRefCount());
+
+    // Simulate deletion of the image and verify that it still exists because the renderbuffer holds
+    // a ref
+    image->release();
+    EXPECT_EQ(1u, texture->getRefCount());
+    EXPECT_EQ(1u, image->getRefCount());
+    EXPECT_EQ(1u, renderbuffer->getRefCount());
+
+    // Simulate deletion of the renderbuffer and verify that the deletion cascades to all objects
+    rx::MockImageImpl *imageImpl = static_cast<rx::MockImageImpl *>(image->getImplementation());
+    EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
+    EXPECT_CALL(*imageImpl, orphan(_)).WillOnce(Return(gl::NoError())).RetiresOnSaturation();
+
+    EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
+    EXPECT_CALL(*renderbufferImpl, destructor()).Times(1).RetiresOnSaturation();
+
+    renderbuffer->release();
+}
+
+// Verify that respecifiying textures releases references to the Image.
+TEST(ImageTest, RespecificationReleasesReferences)
+{
+    NiceMock<rx::MockGLFactory> mockGLFactory;
+    NiceMock<rx::MockEGLFactory> mockEGLFactory;
+
+    // Create a texture and an EGL image that uses the texture as its source
+    rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
+    EXPECT_CALL(mockGLFactory, createTexture(_)).WillOnce(Return(textureImpl));
+    gl::Texture *texture = new gl::Texture(&mockGLFactory, 1, GL_TEXTURE_2D);
+    texture->addRef();
+
+    gl::PixelUnpackState defaultUnpackState;
+
+    EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _, _))
+        .WillOnce(Return(gl::NoError()))
+        .RetiresOnSaturation();
+    texture->setImage(nullptr, defaultUnpackState, GL_TEXTURE_2D, 0, GL_RGBA8, gl::Extents(1, 1, 1),
+                      GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    EXPECT_CALL(mockEGLFactory, createImage(_, _, _))
+        .WillOnce(CreateMockImageImpl())
+        .RetiresOnSaturation();
+
+    egl::Image *image =
+        new egl::Image(&mockEGLFactory, EGL_GL_TEXTURE_2D, texture, egl::AttributeMap());
+    image->addRef();
+
+    // Verify that the image added a ref to the texture and the texture has not added a ref to the
+    // image
+    EXPECT_EQ(2u, texture->getRefCount());
+    EXPECT_EQ(1u, image->getRefCount());
+
+    // Respecify the texture and verify that the image releases its reference
+    rx::MockImageImpl *imageImpl = static_cast<rx::MockImageImpl *>(image->getImplementation());
+    EXPECT_CALL(*imageImpl, orphan(_)).WillOnce(Return(gl::NoError())).RetiresOnSaturation();
+    EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _, _))
+        .WillOnce(Return(gl::NoError()))
+        .RetiresOnSaturation();
+
+    texture->setImage(nullptr, defaultUnpackState, GL_TEXTURE_2D, 0, GL_RGBA8, gl::Extents(1, 1, 1),
+                      GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    EXPECT_EQ(1u, texture->getRefCount());
+    EXPECT_EQ(1u, image->getRefCount());
+
+    // Delete the texture and verify that the image still exists
+    EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
+    texture->release();
+
+    EXPECT_EQ(1u, image->getRefCount());
+
+    // Delete the image
+    EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
+    image->release();
+}
+}  // namespace angle
diff --git a/src/third_party/angle/src/libANGLE/IndexRangeCache.cpp b/src/third_party/angle/src/libANGLE/IndexRangeCache.cpp
new file mode 100644
index 0000000..4f165c1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/IndexRangeCache.cpp
@@ -0,0 +1,113 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexRangeCache.cpp: Defines the gl::IndexRangeCache class which stores information about
+// ranges of indices.
+
+#include "libANGLE/IndexRangeCache.h"
+
+#include "common/debug.h"
+#include "libANGLE/formatutils.h"
+
+namespace gl
+{
+
+void IndexRangeCache::addRange(GLenum type,
+                               size_t offset,
+                               size_t count,
+                               bool primitiveRestartEnabled,
+                               const IndexRange &range)
+{
+    mIndexRangeCache[IndexRangeKey(type, offset, count, primitiveRestartEnabled)] = range;
+}
+
+bool IndexRangeCache::findRange(GLenum type,
+                                size_t offset,
+                                size_t count,
+                                bool primitiveRestartEnabled,
+                                IndexRange *outRange) const
+{
+    auto i = mIndexRangeCache.find(IndexRangeKey(type, offset, count, primitiveRestartEnabled));
+    if (i != mIndexRangeCache.end())
+    {
+        if (outRange)
+        {
+            *outRange = i->second;
+        }
+        return true;
+    }
+    else
+    {
+        if (outRange)
+        {
+            *outRange = IndexRange();
+        }
+        return false;
+    }
+}
+
+void IndexRangeCache::invalidateRange(size_t offset, size_t size)
+{
+    size_t invalidateStart = offset;
+    size_t invalidateEnd   = offset + size;
+
+    auto i = mIndexRangeCache.begin();
+    while (i != mIndexRangeCache.end())
+    {
+        size_t rangeStart = i->first.offset;
+        size_t rangeEnd   = i->first.offset + (GetTypeInfo(i->first.type).bytes * i->first.count);
+
+        if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
+        {
+            ++i;
+        }
+        else
+        {
+            mIndexRangeCache.erase(i++);
+        }
+    }
+}
+
+void IndexRangeCache::clear()
+{
+    mIndexRangeCache.clear();
+}
+
+IndexRangeCache::IndexRangeKey::IndexRangeKey()
+    : IndexRangeCache::IndexRangeKey(GL_NONE, 0, 0, false)
+{
+}
+
+IndexRangeCache::IndexRangeKey::IndexRangeKey(GLenum type_,
+                                              size_t offset_,
+                                              size_t count_,
+                                              bool primitiveRestartEnabled_)
+    : type(type_), offset(offset_), count(count_), primitiveRestartEnabled(primitiveRestartEnabled_)
+{
+}
+
+bool IndexRangeCache::IndexRangeKey::operator<(const IndexRangeKey &rhs) const
+{
+    if (type != rhs.type)
+    {
+        return type < rhs.type;
+    }
+    if (offset != rhs.offset)
+    {
+        return offset < rhs.offset;
+    }
+    if (count != rhs.count)
+    {
+        return count < rhs.count;
+    }
+    if (primitiveRestartEnabled != rhs.primitiveRestartEnabled)
+    {
+        return primitiveRestartEnabled;
+    }
+    return false;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/IndexRangeCache.h b/src/third_party/angle/src/libANGLE/IndexRangeCache.h
new file mode 100644
index 0000000..69de421
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/IndexRangeCache.h
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexRangeCache.h: Defines the gl::IndexRangeCache class which stores information about
+// ranges of indices.
+
+#ifndef LIBANGLE_INDEXRANGECACHE_H_
+#define LIBANGLE_INDEXRANGECACHE_H_
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+
+#include "angle_gl.h"
+
+#include <map>
+
+namespace gl
+{
+
+class IndexRangeCache
+{
+  public:
+    void addRange(GLenum type,
+                  size_t offset,
+                  size_t count,
+                  bool primitiveRestartEnabled,
+                  const IndexRange &range);
+    bool findRange(GLenum type,
+                   size_t offset,
+                   size_t count,
+                   bool primitiveRestartEnabled,
+                   IndexRange *outRange) const;
+
+    void invalidateRange(size_t offset, size_t size);
+    void clear();
+
+  private:
+    struct IndexRangeKey
+    {
+        IndexRangeKey();
+        IndexRangeKey(GLenum type, size_t offset, size_t count, bool primitiveRestart);
+
+        bool operator<(const IndexRangeKey &rhs) const;
+
+        GLenum type;
+        size_t offset;
+        size_t count;
+        bool primitiveRestartEnabled;
+    };
+
+    typedef std::map<IndexRangeKey, IndexRange> IndexRangeMap;
+    IndexRangeMap mIndexRangeCache;
+};
+
+}
+
+#endif // LIBANGLE_INDEXRANGECACHE_H_
diff --git a/src/third_party/angle/src/libANGLE/LoggingAnnotator.cpp b/src/third_party/angle/src/libANGLE/LoggingAnnotator.cpp
new file mode 100644
index 0000000..4a79ce0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/LoggingAnnotator.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright 2017 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.
+//
+// LoggingAnnotator.cpp: DebugAnnotator implementing logging
+//
+
+#include "libANGLE/LoggingAnnotator.h"
+
+#include <platform/Platform.h>
+
+namespace angle
+{
+
+void LoggingAnnotator::logMessage(const gl::LogMessage &msg) const
+{
+    auto *plat = ANGLEPlatformCurrent();
+    if (plat != nullptr)
+    {
+        switch (msg.getSeverity())
+        {
+            case gl::LOG_ERR:
+                plat->logError(plat, msg.getMessage().c_str());
+                break;
+            case gl::LOG_WARN:
+                plat->logWarning(plat, msg.getMessage().c_str());
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+    else
+    {
+        gl::Trace(msg.getSeverity(), msg.getMessage().c_str());
+    }
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/libANGLE/LoggingAnnotator.h b/src/third_party/angle/src/libANGLE/LoggingAnnotator.h
new file mode 100644
index 0000000..3617dd5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/LoggingAnnotator.h
@@ -0,0 +1,31 @@
+//
+// Copyright 2017 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.
+//
+// LoggingAnnotator.h: DebugAnnotator implementing logging
+//
+
+#ifndef LIBANGLE_LOGGINGANNOTATOR_H_
+#define LIBANGLE_LOGGINGANNOTATOR_H_
+
+#include "common/debug.h"
+
+namespace angle
+{
+
+class LoggingAnnotator : public gl::DebugAnnotator
+{
+  public:
+    LoggingAnnotator(){};
+    ~LoggingAnnotator() override{};
+    void beginEvent(const wchar_t *eventName) override {}
+    void endEvent() override {}
+    void setMarker(const wchar_t *markerName) override {}
+    bool getStatus() override { return false; }
+    void logMessage(const gl::LogMessage &msg) const override;
+};
+
+}  // namespace angle
+
+#endif  // LIBANGLE_LOGGINGANNOTATOR_H_
diff --git a/src/third_party/angle/src/libANGLE/Path.cpp b/src/third_party/angle/src/libANGLE/Path.cpp
new file mode 100644
index 0000000..e0c45db
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Path.cpp
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+
+// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
+// path object.
+
+#include "libANGLE/Path.h"
+#include "libANGLE/renderer/PathImpl.h"
+
+#include "common/mathutil.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+Path::Path(rx::PathImpl *impl)
+    : mPath(impl),
+      mHasData(false),
+      mEndCaps(GL_FLAT_CHROMIUM),
+      mJoinStyle(GL_MITER_REVERT_CHROMIUM),
+      mStrokeWidth(1.0f),
+      mStrokeBound(0.2f),
+      mMiterLimit(4.0f)
+{
+}
+
+Path::~Path()
+{
+    delete mPath;
+}
+
+Error Path::setCommands(GLsizei numCommands,
+                        const GLubyte *commands,
+                        GLsizei numCoords,
+                        GLenum coordType,
+                        const void *coords)
+{
+    ANGLE_TRY(mPath->setCommands(numCommands, commands, numCoords, coordType, coords));
+
+    mHasData = true;
+
+    return gl::NoError();
+}
+
+void Path::setStrokeWidth(GLfloat width)
+{
+    mStrokeWidth = width;
+    mPath->setPathParameter(GL_PATH_STROKE_WIDTH_CHROMIUM, mStrokeWidth);
+}
+
+void Path::setStrokeBound(GLfloat bound)
+{
+    mStrokeBound = clamp(bound, 0.0f, 1.0f);
+    mPath->setPathParameter(GL_PATH_STROKE_BOUND_CHROMIUM, mStrokeBound);
+}
+
+void Path::setEndCaps(GLenum type)
+{
+    mEndCaps = type;
+    mPath->setPathParameter(GL_PATH_END_CAPS_CHROMIUM, static_cast<GLfloat>(type));
+}
+
+void Path::setJoinStyle(GLenum type)
+{
+    mJoinStyle = type;
+    mPath->setPathParameter(GL_PATH_JOIN_STYLE_CHROMIUM, static_cast<GLfloat>(type));
+}
+
+void Path::setMiterLimit(GLfloat value)
+{
+    mMiterLimit = value;
+    mPath->setPathParameter(GL_PATH_MITER_LIMIT_CHROMIUM, value);
+}
+
+}  // gl
diff --git a/src/third_party/angle/src/libANGLE/Path.h b/src/third_party/angle/src/libANGLE/Path.h
new file mode 100644
index 0000000..b103c84
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Path.h
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+
+// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
+// path object.
+
+#ifndef LIBANGLE_PATH_H_
+#define LIBANGLE_PATH_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class PathImpl;
+}
+
+namespace gl
+{
+class Path final : angle::NonCopyable
+{
+  public:
+    Path(rx::PathImpl *impl);
+
+    ~Path();
+
+    Error setCommands(GLsizei numCommands,
+                      const GLubyte *commands,
+                      GLsizei numCoords,
+                      GLenum coordType,
+                      const void *coords);
+
+    void setStrokeWidth(GLfloat width);
+    void setStrokeBound(GLfloat bound);
+    void setEndCaps(GLenum type);
+    void setJoinStyle(GLenum type);
+    void setMiterLimit(GLfloat value);
+
+    GLfloat getStrokeWidth() const { return mStrokeWidth; }
+    GLfloat getStrokeBound() const { return mStrokeBound; }
+    GLfloat getMiterLimit() const { return mMiterLimit; }
+    GLenum getEndCaps() const { return mEndCaps; }
+    GLenum getJoinStyle() const { return mJoinStyle; }
+
+    bool hasPathData() const { return mHasData; }
+
+    rx::PathImpl *getImplementation() const { return mPath; }
+
+  private:
+    rx::PathImpl *mPath;
+
+    // a Path object is not actually considered "a path"
+    // untill it has been specified with data. So we'll
+    // keep this flag to support this semantics.
+    bool mHasData;
+
+    GLenum mEndCaps;
+    GLenum mJoinStyle;
+    GLfloat mStrokeWidth;
+    GLfloat mStrokeBound;
+    GLfloat mMiterLimit;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_PATH_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libANGLE/Platform.cpp b/src/third_party/angle/src/libANGLE/Platform.cpp
new file mode 100644
index 0000000..6cbbd1e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Platform.cpp
@@ -0,0 +1,65 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Platform.cpp: Implementation methods for angle::Platform.
+
+#include <platform/Platform.h>
+
+#include <cstring>
+
+#include "common/debug.h"
+
+namespace
+{
+// TODO(jmadill): Make methods owned by egl::Display.
+angle::PlatformMethods g_platformMethods;
+}  // anonymous namespace
+
+angle::PlatformMethods *ANGLEPlatformCurrent()
+{
+    return &g_platformMethods;
+}
+
+bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
+                                            const char *const methodNames[],
+                                            unsigned int methodNameCount,
+                                            void *context,
+                                            void *platformMethods)
+{
+    angle::PlatformMethods **platformMethodsOut =
+        reinterpret_cast<angle::PlatformMethods **>(platformMethods);
+
+    // We allow for a lower input count of impl platform methods if the subset is correct.
+    if (methodNameCount > angle::g_NumPlatformMethods)
+    {
+        ERR() << "Invalid platform method count: " << methodNameCount << ", expected "
+              << angle::g_NumPlatformMethods << ".";
+        return false;
+    }
+
+    for (unsigned int nameIndex = 0; nameIndex < methodNameCount; ++nameIndex)
+    {
+        const char *expectedName = angle::g_PlatformMethodNames[nameIndex];
+        const char *actualName   = methodNames[nameIndex];
+        if (strcmp(expectedName, actualName) != 0)
+        {
+            ERR() << "Invalid platform method name: " << actualName << ", expected " << expectedName
+                  << ".";
+            return false;
+        }
+    }
+
+    // TODO(jmadill): Store platform methods in display.
+    g_platformMethods.context = context;
+    *platformMethodsOut       = &g_platformMethods;
+    return true;
+}
+
+void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display)
+{
+    // TODO(jmadill): Store platform methods in display.
+    g_platformMethods = angle::PlatformMethods();
+}
diff --git a/src/third_party/angle/src/libANGLE/Program.cpp b/src/third_party/angle/src/libANGLE/Program.cpp
new file mode 100644
index 0000000..2680741
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Program.cpp
@@ -0,0 +1,3087 @@
+//
+// 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.
+//
+
+// 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 "libANGLE/Program.h"
+
+#include <algorithm>
+
+#include "common/bitset_utils.h"
+#include "common/debug.h"
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "common/version.h"
+#include "compiler/translator/blocklayout.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "libANGLE/VaryingPacking.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/UniformLinker.h"
+
+namespace gl
+{
+
+namespace
+{
+
+void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
+{
+    stream->writeInt(var.type);
+    stream->writeInt(var.precision);
+    stream->writeString(var.name);
+    stream->writeString(var.mappedName);
+    stream->writeInt(var.arraySize);
+    stream->writeInt(var.staticUse);
+    stream->writeString(var.structName);
+    ASSERT(var.fields.empty());
+}
+
+void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
+{
+    var->type       = stream->readInt<GLenum>();
+    var->precision  = stream->readInt<GLenum>();
+    var->name       = stream->readString();
+    var->mappedName = stream->readString();
+    var->arraySize  = stream->readInt<unsigned int>();
+    var->staticUse  = stream->readBool();
+    var->structName = stream->readString();
+}
+
+// This simplified cast function doesn't need to worry about advanced concepts like
+// depth range values, or casting to bool.
+template <typename DestT, typename SrcT>
+DestT UniformStateQueryCast(SrcT value);
+
+// From-Float-To-Integer Casts
+template <>
+GLint UniformStateQueryCast(GLfloat value)
+{
+    return clampCast<GLint>(roundf(value));
+}
+
+template <>
+GLuint UniformStateQueryCast(GLfloat value)
+{
+    return clampCast<GLuint>(roundf(value));
+}
+
+// From-Integer-to-Integer Casts
+template <>
+GLint UniformStateQueryCast(GLuint value)
+{
+    return clampCast<GLint>(value);
+}
+
+template <>
+GLuint UniformStateQueryCast(GLint value)
+{
+    return clampCast<GLuint>(value);
+}
+
+// From-Boolean-to-Anything Casts
+template <>
+GLfloat UniformStateQueryCast(GLboolean value)
+{
+    return (value == GL_TRUE ? 1.0f : 0.0f);
+}
+
+template <>
+GLint UniformStateQueryCast(GLboolean value)
+{
+    return (value == GL_TRUE ? 1 : 0);
+}
+
+template <>
+GLuint UniformStateQueryCast(GLboolean value)
+{
+    return (value == GL_TRUE ? 1u : 0u);
+}
+
+// Default to static_cast
+template <typename DestT, typename SrcT>
+DestT UniformStateQueryCast(SrcT value)
+{
+    return static_cast<DestT>(value);
+}
+
+template <typename SrcT, typename DestT>
+void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
+{
+    for (int comp = 0; comp < components; ++comp)
+    {
+        // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
+        // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
+        size_t offset               = comp * 4;
+        const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
+        dataOut[comp]               = UniformStateQueryCast<DestT>(*typedSrcPointer);
+    }
+}
+
+// true if varying x has a higher priority in packing than y
+bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
+{
+    // If the PackedVarying 'x' or 'y' to be compared is an array element, this clones an equivalent
+    // non-array shader variable 'vx' or 'vy' for actual comparison instead.
+    sh::ShaderVariable vx, vy;
+    const sh::ShaderVariable *px, *py;
+    if (x.isArrayElement())
+    {
+        vx           = *x.varying;
+        vx.arraySize = 0;
+        px           = &vx;
+    }
+    else
+    {
+        px = x.varying;
+    }
+
+    if (y.isArrayElement())
+    {
+        vy           = *y.varying;
+        vy.arraySize = 0;
+        py           = &vy;
+    }
+    else
+    {
+        py = y.varying;
+    }
+
+    return gl::CompareShaderVar(*px, *py);
+}
+
+template <typename VarT>
+GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
+{
+    size_t subscript     = GL_INVALID_INDEX;
+    std::string baseName = ParseResourceName(name, &subscript);
+
+    // The app is not allowed to specify array indices other than 0 for arrays of basic types
+    if (subscript != 0 && subscript != GL_INVALID_INDEX)
+    {
+        return GL_INVALID_INDEX;
+    }
+
+    for (size_t index = 0; index < list.size(); index++)
+    {
+        const VarT &resource = list[index];
+        if (resource.name == baseName)
+        {
+            if (resource.isArray() || subscript == GL_INVALID_INDEX)
+            {
+                return static_cast<GLuint>(index);
+            }
+        }
+    }
+
+    return GL_INVALID_INDEX;
+}
+
+void CopyStringToBuffer(GLchar *buffer, const std::string &string, GLsizei bufSize, GLsizei *length)
+{
+    ASSERT(bufSize > 0);
+    strncpy(buffer, string.c_str(), bufSize);
+    buffer[bufSize - 1] = '\0';
+
+    if (length)
+    {
+        *length = static_cast<GLsizei>(strlen(buffer));
+    }
+}
+
+bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
+{
+    size_t subscript     = GL_INVALID_INDEX;
+    std::string baseName = ParseResourceName(name, &subscript);
+    for (auto it = nameSet.begin(); it != nameSet.end(); ++it)
+    {
+        size_t arrayIndex     = GL_INVALID_INDEX;
+        std::string arrayName = ParseResourceName(*it, &arrayIndex);
+        if (baseName == arrayName && (subscript == GL_INVALID_INDEX ||
+                                      arrayIndex == GL_INVALID_INDEX || subscript == arrayIndex))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+}  // anonymous namespace
+
+const char *const g_fakepath = "C:\\fakepath";
+
+InfoLog::InfoLog()
+{
+}
+
+InfoLog::~InfoLog()
+{
+}
+
+size_t InfoLog::getLength() const
+{
+    const std::string &logString = mStream.str();
+    return logString.empty() ? 0 : logString.length() + 1;
+}
+
+void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+{
+    size_t index = 0;
+
+    if (bufSize > 0)
+    {
+        const std::string str(mStream.str());
+
+        if (!str.empty())
+        {
+            index = std::min(static_cast<size_t>(bufSize) - 1, str.length());
+            memcpy(infoLog, str.c_str(), index);
+        }
+
+        infoLog[index] = '\0';
+    }
+
+    if (length)
+    {
+        *length = static_cast<GLsizei>(index);
+    }
+}
+
+// append a santized message to the program info log.
+// The D3D compiler includes a fake file path in some of the warning or error
+// messages, so lets remove all occurrences of this fake file path from the log.
+void InfoLog::appendSanitized(const char *message)
+{
+    std::string msg(message);
+
+    size_t found;
+    do
+    {
+        found = msg.find(g_fakepath);
+        if (found != std::string::npos)
+        {
+            msg.erase(found, strlen(g_fakepath));
+        }
+    }
+    while (found != std::string::npos);
+
+    mStream << message << std::endl;
+}
+
+void InfoLog::reset()
+{
+}
+
+VariableLocation::VariableLocation() : name(), element(0), index(0), used(false), ignored(false)
+{
+}
+
+VariableLocation::VariableLocation(const std::string &name,
+                                   unsigned int element,
+                                   unsigned int index)
+    : name(name), element(element), index(index), used(true), ignored(false)
+{
+}
+
+void Program::Bindings::bindLocation(GLuint index, const std::string &name)
+{
+    mBindings[name] = index;
+}
+
+int Program::Bindings::getBinding(const std::string &name) const
+{
+    auto iter = mBindings.find(name);
+    return (iter != mBindings.end()) ? iter->second : -1;
+}
+
+Program::Bindings::const_iterator Program::Bindings::begin() const
+{
+    return mBindings.begin();
+}
+
+Program::Bindings::const_iterator Program::Bindings::end() const
+{
+    return mBindings.end();
+}
+
+ProgramState::ProgramState()
+    : mLabel(),
+      mAttachedFragmentShader(nullptr),
+      mAttachedVertexShader(nullptr),
+      mAttachedComputeShader(nullptr),
+      mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
+      mSamplerUniformRange(0, 0),
+      mBinaryRetrieveableHint(false)
+{
+    mComputeShaderLocalSize.fill(1);
+}
+
+ProgramState::~ProgramState()
+{
+    ASSERT(!mAttachedVertexShader && !mAttachedFragmentShader && !mAttachedComputeShader);
+}
+
+const std::string &ProgramState::getLabel()
+{
+    return mLabel;
+}
+
+GLint ProgramState::getUniformLocation(const std::string &name) const
+{
+    size_t subscript     = GL_INVALID_INDEX;
+    std::string baseName = ParseResourceName(name, &subscript);
+
+    for (size_t location = 0; location < mUniformLocations.size(); ++location)
+    {
+        const VariableLocation &uniformLocation = mUniformLocations[location];
+        if (!uniformLocation.used)
+        {
+            continue;
+        }
+
+        const LinkedUniform &uniform = mUniforms[uniformLocation.index];
+
+        if (uniform.name == baseName)
+        {
+            if (uniform.isArray())
+            {
+                if (uniformLocation.element == subscript ||
+                    (uniformLocation.element == 0 && subscript == GL_INVALID_INDEX))
+                {
+                    return static_cast<GLint>(location);
+                }
+            }
+            else
+            {
+                if (subscript == GL_INVALID_INDEX)
+                {
+                    return static_cast<GLint>(location);
+                }
+            }
+        }
+    }
+
+    return -1;
+}
+
+GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
+{
+    return GetResourceIndexFromName(mUniforms, name);
+}
+
+GLuint ProgramState::getUniformIndexFromLocation(GLint location) const
+{
+    ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformLocations.size());
+    return mUniformLocations[location].index;
+}
+
+Optional<GLuint> ProgramState::getSamplerIndex(GLint location) const
+{
+    GLuint index = getUniformIndexFromLocation(location);
+    if (!isSamplerUniformIndex(index))
+    {
+        return Optional<GLuint>::Invalid();
+    }
+
+    return getSamplerIndexFromUniformIndex(index);
+}
+
+bool ProgramState::isSamplerUniformIndex(GLuint index) const
+{
+    return index >= mSamplerUniformRange.start && index < mSamplerUniformRange.end;
+}
+
+GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
+{
+    ASSERT(isSamplerUniformIndex(uniformIndex));
+    return uniformIndex - mSamplerUniformRange.start;
+}
+
+Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle)
+    : mProgram(factory->createProgram(mState)),
+      mValidated(false),
+      mLinked(false),
+      mDeleteStatus(false),
+      mRefCount(0),
+      mResourceManager(manager),
+      mHandle(handle)
+{
+    ASSERT(mProgram);
+
+    resetUniformBlockBindings();
+    unlink();
+}
+
+Program::~Program()
+{
+    ASSERT(!mState.mAttachedVertexShader && !mState.mAttachedFragmentShader &&
+           !mState.mAttachedComputeShader);
+    SafeDelete(mProgram);
+}
+
+void Program::destroy(const Context *context)
+{
+    if (mState.mAttachedVertexShader != nullptr)
+    {
+        mState.mAttachedVertexShader->release(context);
+        mState.mAttachedVertexShader = nullptr;
+    }
+
+    if (mState.mAttachedFragmentShader != nullptr)
+    {
+        mState.mAttachedFragmentShader->release(context);
+        mState.mAttachedFragmentShader = nullptr;
+    }
+
+    if (mState.mAttachedComputeShader != nullptr)
+    {
+        mState.mAttachedComputeShader->release(context);
+        mState.mAttachedComputeShader = nullptr;
+    }
+
+    mProgram->destroy(rx::SafeGetImpl(context));
+}
+
+void Program::setLabel(const std::string &label)
+{
+    mState.mLabel = label;
+}
+
+const std::string &Program::getLabel() const
+{
+    return mState.mLabel;
+}
+
+void Program::attachShader(Shader *shader)
+{
+    switch (shader->getType())
+    {
+        case GL_VERTEX_SHADER:
+        {
+            ASSERT(!mState.mAttachedVertexShader);
+            mState.mAttachedVertexShader = shader;
+            mState.mAttachedVertexShader->addRef();
+            break;
+        }
+        case GL_FRAGMENT_SHADER:
+        {
+            ASSERT(!mState.mAttachedFragmentShader);
+            mState.mAttachedFragmentShader = shader;
+            mState.mAttachedFragmentShader->addRef();
+            break;
+        }
+        case GL_COMPUTE_SHADER:
+        {
+            ASSERT(!mState.mAttachedComputeShader);
+            mState.mAttachedComputeShader = shader;
+            mState.mAttachedComputeShader->addRef();
+            break;
+        }
+        default:
+            UNREACHABLE();
+    }
+}
+
+void Program::detachShader(const Context *context, Shader *shader)
+{
+    switch (shader->getType())
+    {
+        case GL_VERTEX_SHADER:
+        {
+            ASSERT(mState.mAttachedVertexShader == shader);
+            shader->release(context);
+            mState.mAttachedVertexShader = nullptr;
+            break;
+        }
+        case GL_FRAGMENT_SHADER:
+        {
+            ASSERT(mState.mAttachedFragmentShader == shader);
+            shader->release(context);
+            mState.mAttachedFragmentShader = nullptr;
+            break;
+        }
+        case GL_COMPUTE_SHADER:
+        {
+            ASSERT(mState.mAttachedComputeShader == shader);
+            shader->release(context);
+            mState.mAttachedComputeShader = nullptr;
+            break;
+        }
+        default:
+            UNREACHABLE();
+    }
+}
+
+int Program::getAttachedShadersCount() const
+{
+    return (mState.mAttachedVertexShader ? 1 : 0) + (mState.mAttachedFragmentShader ? 1 : 0) +
+           (mState.mAttachedComputeShader ? 1 : 0);
+}
+
+void Program::bindAttributeLocation(GLuint index, const char *name)
+{
+    mAttributeBindings.bindLocation(index, name);
+}
+
+void Program::bindUniformLocation(GLuint index, const char *name)
+{
+    // Bind the base uniform name only since array indices other than 0 cannot be bound
+    mUniformLocationBindings.bindLocation(index, ParseResourceName(name, nullptr));
+}
+
+void Program::bindFragmentInputLocation(GLint index, const char *name)
+{
+    mFragmentInputBindings.bindLocation(index, name);
+}
+
+BindingInfo Program::getFragmentInputBindingInfo(GLint index) const
+{
+    BindingInfo ret;
+    ret.type  = GL_NONE;
+    ret.valid = false;
+
+    const Shader *fragmentShader = mState.getAttachedFragmentShader();
+    ASSERT(fragmentShader);
+
+    // Find the actual fragment shader varying we're interested in
+    const std::vector<sh::Varying> &inputs = fragmentShader->getVaryings();
+
+    for (const auto &binding : mFragmentInputBindings)
+    {
+        if (binding.second != static_cast<GLuint>(index))
+            continue;
+
+        ret.valid = true;
+
+        std::string originalName = binding.first;
+        unsigned int arrayIndex  = ParseAndStripArrayIndex(&originalName);
+
+        for (const auto &in : inputs)
+        {
+            if (in.name == originalName)
+            {
+                if (in.isArray())
+                {
+                    // The client wants to bind either "name" or "name[0]".
+                    // GL ES 3.1 spec refers to active array names with language such as:
+                    // "if the string identifies the base name of an active array, where the
+                    // string would exactly match the name of the variable if the suffix "[0]"
+                    // were appended to the string".
+                    if (arrayIndex == GL_INVALID_INDEX)
+                        arrayIndex = 0;
+
+                    ret.name = in.mappedName + "[" + ToString(arrayIndex) + "]";
+                }
+                else
+                {
+                    ret.name = in.mappedName;
+                }
+                ret.type = in.type;
+                return ret;
+            }
+        }
+    }
+
+    return ret;
+}
+
+void Program::pathFragmentInputGen(GLint index,
+                                   GLenum genMode,
+                                   GLint components,
+                                   const GLfloat *coeffs)
+{
+    // If the location is -1 then the command is silently ignored
+    if (index == -1)
+        return;
+
+    const auto &binding = getFragmentInputBindingInfo(index);
+
+    // If the input doesn't exist then then the command is silently ignored
+    // This could happen through optimization for example, the shader translator
+    // decides that a variable is not actually being used and optimizes it away.
+    if (binding.name.empty())
+        return;
+
+    mProgram->setPathFragmentInputGen(binding.name, genMode, components, coeffs);
+}
+
+// The attached shaders are checked for linking errors by matching up their variables.
+// Uniform, input and output variables get collected.
+// The code gets compiled into binaries.
+Error Program::link(const gl::Context *context)
+{
+    const auto &data = context->getContextState();
+
+    unlink();
+
+    mInfoLog.reset();
+    resetUniformBlockBindings();
+
+    const Caps &caps = data.getCaps();
+
+    auto vertexShader   = mState.mAttachedVertexShader;
+    auto fragmentShader = mState.mAttachedFragmentShader;
+    auto computeShader  = mState.mAttachedComputeShader;
+
+    bool isComputeShaderAttached   = (computeShader != nullptr);
+    bool nonComputeShadersAttached = (vertexShader != nullptr || fragmentShader != nullptr);
+    // Check whether we both have a compute and non-compute shaders attached.
+    // If there are of both types attached, then linking should fail.
+    // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
+    if (isComputeShaderAttached == true && nonComputeShadersAttached == true)
+    {
+        mInfoLog << "Both a compute and non-compute shaders are attached to the same program.";
+        return NoError();
+    }
+
+    if (computeShader)
+    {
+        if (!computeShader->isCompiled())
+        {
+            mInfoLog << "Attached compute shader is not compiled.";
+            return NoError();
+        }
+        ASSERT(computeShader->getType() == GL_COMPUTE_SHADER);
+
+        mState.mComputeShaderLocalSize = computeShader->getWorkGroupSize();
+
+        // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
+        // If the work group size is not specified, a link time error should occur.
+        if (!mState.mComputeShaderLocalSize.isDeclared())
+        {
+            mInfoLog << "Work group size is not specified.";
+            return NoError();
+        }
+
+        if (!linkUniforms(mInfoLog, caps, mUniformLocationBindings))
+        {
+            return NoError();
+        }
+
+        if (!linkUniformBlocks(mInfoLog, caps))
+        {
+            return NoError();
+        }
+
+        gl::VaryingPacking noPacking(0, PackMode::ANGLE_RELAXED);
+        ANGLE_TRY_RESULT(mProgram->link(context->getImplementation(), noPacking, mInfoLog),
+                         mLinked);
+        if (!mLinked)
+        {
+            return NoError();
+        }
+    }
+    else
+    {
+        if (!fragmentShader || !fragmentShader->isCompiled())
+        {
+            return NoError();
+        }
+        ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
+
+        if (!vertexShader || !vertexShader->isCompiled())
+        {
+            return NoError();
+        }
+        ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
+
+        if (fragmentShader->getShaderVersion() != vertexShader->getShaderVersion())
+        {
+            mInfoLog << "Fragment shader version does not match vertex shader version.";
+            return NoError();
+        }
+
+        if (!linkAttributes(data, mInfoLog))
+        {
+            return NoError();
+        }
+
+        if (!linkVaryings(mInfoLog))
+        {
+            return NoError();
+        }
+
+        if (!linkUniforms(mInfoLog, caps, mUniformLocationBindings))
+        {
+            return NoError();
+        }
+
+        if (!linkUniformBlocks(mInfoLog, caps))
+        {
+            return NoError();
+        }
+
+        const auto &mergedVaryings = getMergedVaryings();
+
+        if (!linkValidateTransformFeedback(context, mInfoLog, mergedVaryings, caps))
+        {
+            return NoError();
+        }
+
+        linkOutputVariables();
+
+        // Validate we can pack the varyings.
+        std::vector<PackedVarying> packedVaryings = getPackedVaryings(mergedVaryings);
+
+        // Map the varyings to the register file
+        // In WebGL, we use a slightly different handling for packing variables.
+        auto packMode = data.getExtensions().webglCompatibility ? PackMode::WEBGL_STRICT
+                                                                : PackMode::ANGLE_RELAXED;
+        VaryingPacking varyingPacking(data.getCaps().maxVaryingVectors, packMode);
+        if (!varyingPacking.packUserVaryings(mInfoLog, packedVaryings,
+                                             mState.getTransformFeedbackVaryingNames()))
+        {
+            return NoError();
+        }
+
+        ANGLE_TRY_RESULT(mProgram->link(context->getImplementation(), varyingPacking, mInfoLog),
+                         mLinked);
+        if (!mLinked)
+        {
+            return NoError();
+        }
+
+        gatherTransformFeedbackVaryings(mergedVaryings);
+    }
+
+    setUniformValuesFromBindingQualifiers();
+
+    gatherInterfaceBlockInfo();
+
+    return NoError();
+}
+
+// Returns the program object to an unlinked state, before re-linking, or at destruction
+void Program::unlink()
+{
+    mState.mAttributes.clear();
+    mState.mActiveAttribLocationsMask.reset();
+    mState.mLinkedTransformFeedbackVaryings.clear();
+    mState.mUniforms.clear();
+    mState.mUniformLocations.clear();
+    mState.mUniformBlocks.clear();
+    mState.mOutputVariables.clear();
+    mState.mOutputLocations.clear();
+    mState.mComputeShaderLocalSize.fill(1);
+    mState.mSamplerBindings.clear();
+
+    mValidated = false;
+
+    mLinked = false;
+}
+
+bool Program::isLinked() const
+{
+    return mLinked;
+}
+
+Error Program::loadBinary(const Context *context,
+                          GLenum binaryFormat,
+                          const void *binary,
+                          GLsizei length)
+{
+    unlink();
+
+#if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
+    return NoError();
+#else
+    ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
+    if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
+    {
+        mInfoLog << "Invalid program binary format.";
+        return NoError();
+    }
+
+    BinaryInputStream stream(binary, length);
+
+    unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
+    stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
+    if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
+        0)
+    {
+        mInfoLog << "Invalid program binary version.";
+        return NoError();
+    }
+
+    int majorVersion = stream.readInt<int>();
+    int minorVersion = stream.readInt<int>();
+    if (majorVersion != context->getClientMajorVersion() ||
+        minorVersion != context->getClientMinorVersion())
+    {
+        mInfoLog << "Cannot load program binaries across different ES context versions.";
+        return NoError();
+    }
+
+    mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
+    mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
+    mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
+
+    static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
+                  "Too many vertex attribs for mask");
+    mState.mActiveAttribLocationsMask = stream.readInt<unsigned long>();
+
+    unsigned int attribCount = stream.readInt<unsigned int>();
+    ASSERT(mState.mAttributes.empty());
+    for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+    {
+        sh::Attribute attrib;
+        LoadShaderVar(&stream, &attrib);
+        attrib.location = stream.readInt<int>();
+        mState.mAttributes.push_back(attrib);
+    }
+
+    unsigned int uniformCount = stream.readInt<unsigned int>();
+    ASSERT(mState.mUniforms.empty());
+    for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
+    {
+        LinkedUniform uniform;
+        LoadShaderVar(&stream, &uniform);
+
+        uniform.blockIndex                 = stream.readInt<int>();
+        uniform.blockInfo.offset           = stream.readInt<int>();
+        uniform.blockInfo.arrayStride      = stream.readInt<int>();
+        uniform.blockInfo.matrixStride     = stream.readInt<int>();
+        uniform.blockInfo.isRowMajorMatrix = stream.readBool();
+
+        mState.mUniforms.push_back(uniform);
+    }
+
+    const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
+    ASSERT(mState.mUniformLocations.empty());
+    for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
+         uniformIndexIndex++)
+    {
+        VariableLocation variable;
+        stream.readString(&variable.name);
+        stream.readInt(&variable.element);
+        stream.readInt(&variable.index);
+        stream.readBool(&variable.used);
+        stream.readBool(&variable.ignored);
+
+        mState.mUniformLocations.push_back(variable);
+    }
+
+    unsigned int uniformBlockCount = stream.readInt<unsigned int>();
+    ASSERT(mState.mUniformBlocks.empty());
+    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
+         ++uniformBlockIndex)
+    {
+        UniformBlock uniformBlock;
+        stream.readString(&uniformBlock.name);
+        stream.readBool(&uniformBlock.isArray);
+        stream.readInt(&uniformBlock.arrayElement);
+        stream.readInt(&uniformBlock.dataSize);
+        stream.readBool(&uniformBlock.vertexStaticUse);
+        stream.readBool(&uniformBlock.fragmentStaticUse);
+
+        unsigned int numMembers = stream.readInt<unsigned int>();
+        for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
+        {
+            uniformBlock.memberUniformIndexes.push_back(stream.readInt<unsigned int>());
+        }
+
+        mState.mUniformBlocks.push_back(uniformBlock);
+    }
+
+    for (GLuint bindingIndex = 0; bindingIndex < mState.mUniformBlockBindings.size();
+         ++bindingIndex)
+    {
+        stream.readInt(&mState.mUniformBlockBindings[bindingIndex]);
+        mState.mActiveUniformBlockBindings.set(bindingIndex,
+                                               mState.mUniformBlockBindings[bindingIndex] != 0);
+    }
+
+    unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
+    ASSERT(mState.mLinkedTransformFeedbackVaryings.empty());
+    for (unsigned int transformFeedbackVaryingIndex = 0;
+        transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
+        ++transformFeedbackVaryingIndex)
+    {
+        sh::Varying varying;
+        stream.readInt(&varying.arraySize);
+        stream.readInt(&varying.type);
+        stream.readString(&varying.name);
+
+        GLuint arrayIndex = stream.readInt<GLuint>();
+
+        mState.mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
+    }
+
+    stream.readInt(&mState.mTransformFeedbackBufferMode);
+
+    unsigned int outputCount = stream.readInt<unsigned int>();
+    ASSERT(mState.mOutputVariables.empty());
+    for (unsigned int outputIndex = 0; outputIndex < outputCount; ++outputIndex)
+    {
+        sh::OutputVariable output;
+        LoadShaderVar(&stream, &output);
+        output.location = stream.readInt<int>();
+        mState.mOutputVariables.push_back(output);
+    }
+
+    unsigned int outputVarCount = stream.readInt<unsigned int>();
+    for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
+    {
+        int locationIndex = stream.readInt<int>();
+        VariableLocation locationData;
+        stream.readInt(&locationData.element);
+        stream.readInt(&locationData.index);
+        stream.readString(&locationData.name);
+        mState.mOutputLocations[locationIndex] = locationData;
+    }
+
+    stream.readInt(&mState.mSamplerUniformRange.start);
+    stream.readInt(&mState.mSamplerUniformRange.end);
+
+    unsigned int samplerCount = stream.readInt<unsigned int>();
+    for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
+    {
+        GLenum textureType  = stream.readInt<GLenum>();
+        size_t bindingCount = stream.readInt<size_t>();
+        mState.mSamplerBindings.emplace_back(SamplerBinding(textureType, bindingCount));
+    }
+
+    ANGLE_TRY_RESULT(mProgram->load(context->getImplementation(), mInfoLog, &stream), mLinked);
+
+    return NoError();
+#endif  // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
+}
+
+Error Program::saveBinary(const Context *context,
+                          GLenum *binaryFormat,
+                          void *binary,
+                          GLsizei bufSize,
+                          GLsizei *length) const
+{
+    if (binaryFormat)
+    {
+        *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
+    }
+
+    BinaryOutputStream stream;
+
+    stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
+
+    // nullptr context is supported when computing binary length.
+    if (context)
+    {
+        stream.writeInt(context->getClientVersion().major);
+        stream.writeInt(context->getClientVersion().minor);
+    }
+    else
+    {
+        stream.writeInt(2);
+        stream.writeInt(0);
+    }
+
+    stream.writeInt(mState.mComputeShaderLocalSize[0]);
+    stream.writeInt(mState.mComputeShaderLocalSize[1]);
+    stream.writeInt(mState.mComputeShaderLocalSize[2]);
+
+    stream.writeInt(mState.mActiveAttribLocationsMask.to_ulong());
+
+    stream.writeInt(mState.mAttributes.size());
+    for (const sh::Attribute &attrib : mState.mAttributes)
+    {
+        WriteShaderVar(&stream, attrib);
+        stream.writeInt(attrib.location);
+    }
+
+    stream.writeInt(mState.mUniforms.size());
+    for (const LinkedUniform &uniform : mState.mUniforms)
+    {
+        WriteShaderVar(&stream, uniform);
+
+        // FIXME: referenced
+
+        stream.writeInt(uniform.blockIndex);
+        stream.writeInt(uniform.blockInfo.offset);
+        stream.writeInt(uniform.blockInfo.arrayStride);
+        stream.writeInt(uniform.blockInfo.matrixStride);
+        stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
+    }
+
+    stream.writeInt(mState.mUniformLocations.size());
+    for (const auto &variable : mState.mUniformLocations)
+    {
+        stream.writeString(variable.name);
+        stream.writeInt(variable.element);
+        stream.writeInt(variable.index);
+        stream.writeInt(variable.used);
+        stream.writeInt(variable.ignored);
+    }
+
+    stream.writeInt(mState.mUniformBlocks.size());
+    for (const UniformBlock &uniformBlock : mState.mUniformBlocks)
+    {
+        stream.writeString(uniformBlock.name);
+        stream.writeInt(uniformBlock.isArray);
+        stream.writeInt(uniformBlock.arrayElement);
+        stream.writeInt(uniformBlock.dataSize);
+
+        stream.writeInt(uniformBlock.vertexStaticUse);
+        stream.writeInt(uniformBlock.fragmentStaticUse);
+
+        stream.writeInt(uniformBlock.memberUniformIndexes.size());
+        for (unsigned int memberUniformIndex : uniformBlock.memberUniformIndexes)
+        {
+            stream.writeInt(memberUniformIndex);
+        }
+    }
+
+    for (GLuint binding : mState.mUniformBlockBindings)
+    {
+        stream.writeInt(binding);
+    }
+
+    stream.writeInt(mState.mLinkedTransformFeedbackVaryings.size());
+    for (const auto &var : mState.mLinkedTransformFeedbackVaryings)
+    {
+        stream.writeInt(var.arraySize);
+        stream.writeInt(var.type);
+        stream.writeString(var.name);
+
+        stream.writeIntOrNegOne(var.arrayIndex);
+    }
+
+    stream.writeInt(mState.mTransformFeedbackBufferMode);
+
+    stream.writeInt(mState.mOutputVariables.size());
+    for (const sh::OutputVariable &output : mState.mOutputVariables)
+    {
+        WriteShaderVar(&stream, output);
+        stream.writeInt(output.location);
+    }
+
+    stream.writeInt(mState.mOutputLocations.size());
+    for (const auto &outputPair : mState.mOutputLocations)
+    {
+        stream.writeInt(outputPair.first);
+        stream.writeIntOrNegOne(outputPair.second.element);
+        stream.writeInt(outputPair.second.index);
+        stream.writeString(outputPair.second.name);
+    }
+
+    stream.writeInt(mState.mSamplerUniformRange.start);
+    stream.writeInt(mState.mSamplerUniformRange.end);
+
+    stream.writeInt(mState.mSamplerBindings.size());
+    for (const auto &samplerBinding : mState.mSamplerBindings)
+    {
+        stream.writeInt(samplerBinding.textureType);
+        stream.writeInt(samplerBinding.boundTextureUnits.size());
+    }
+
+    ANGLE_TRY(mProgram->save(&stream));
+
+    GLsizei streamLength   = static_cast<GLsizei>(stream.length());
+    const void *streamState = stream.data();
+
+    if (streamLength > bufSize)
+    {
+        if (length)
+        {
+            *length = 0;
+        }
+
+        // TODO: This should be moved to the validation layer but computing the size of the binary before saving
+        // it causes the save to happen twice.  It may be possible to write the binary to a separate buffer, validate
+        // sizes and then copy it.
+        return Error(GL_INVALID_OPERATION);
+    }
+
+    if (binary)
+    {
+        char *ptr = reinterpret_cast<char*>(binary);
+
+        memcpy(ptr, streamState, streamLength);
+        ptr += streamLength;
+
+        ASSERT(ptr - streamLength == binary);
+    }
+
+    if (length)
+    {
+        *length = streamLength;
+    }
+
+    return NoError();
+}
+
+GLint Program::getBinaryLength() const
+{
+    GLint length;
+    Error error = saveBinary(nullptr, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
+    if (error.isError())
+    {
+        return 0;
+    }
+
+    return length;
+}
+
+void Program::setBinaryRetrievableHint(bool retrievable)
+{
+    // TODO(jmadill) : replace with dirty bits
+    mProgram->setBinaryRetrievableHint(retrievable);
+    mState.mBinaryRetrieveableHint = retrievable;
+}
+
+bool Program::getBinaryRetrievableHint() const
+{
+    return mState.mBinaryRetrieveableHint;
+}
+
+void Program::setSeparable(bool separable)
+{
+    // TODO(yunchao) : replace with dirty bits
+    if (mState.mSeparable != separable)
+    {
+        mProgram->setSeparable(separable);
+        mState.mSeparable = separable;
+    }
+}
+
+bool Program::isSeparable() const
+{
+    return mState.mSeparable;
+}
+
+void Program::release(const Context *context)
+{
+    mRefCount--;
+
+    if (mRefCount == 0 && mDeleteStatus)
+    {
+        mResourceManager->deleteProgram(context, mHandle);
+    }
+}
+
+void Program::addRef()
+{
+    mRefCount++;
+}
+
+unsigned int Program::getRefCount() const
+{
+    return mRefCount;
+}
+
+int Program::getInfoLogLength() const
+{
+    return static_cast<int>(mInfoLog.getLength());
+}
+
+void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+{
+    return mInfoLog.getLog(bufSize, length, infoLog);
+}
+
+void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const
+{
+    int total = 0;
+
+    if (mState.mAttachedComputeShader)
+    {
+        if (total < maxCount)
+        {
+            shaders[total] = mState.mAttachedComputeShader->getHandle();
+            total++;
+        }
+    }
+
+    if (mState.mAttachedVertexShader)
+    {
+        if (total < maxCount)
+        {
+            shaders[total] = mState.mAttachedVertexShader->getHandle();
+            total++;
+        }
+    }
+
+    if (mState.mAttachedFragmentShader)
+    {
+        if (total < maxCount)
+        {
+            shaders[total] = mState.mAttachedFragmentShader->getHandle();
+            total++;
+        }
+    }
+
+    if (count)
+    {
+        *count = total;
+    }
+}
+
+GLuint Program::getAttributeLocation(const std::string &name) const
+{
+    for (const sh::Attribute &attribute : mState.mAttributes)
+    {
+        if (attribute.name == name)
+        {
+            return attribute.location;
+        }
+    }
+
+    return static_cast<GLuint>(-1);
+}
+
+bool Program::isAttribLocationActive(size_t attribLocation) const
+{
+    ASSERT(attribLocation < mState.mActiveAttribLocationsMask.size());
+    return mState.mActiveAttribLocationsMask[attribLocation];
+}
+
+void Program::getActiveAttribute(GLuint index,
+                                 GLsizei bufsize,
+                                 GLsizei *length,
+                                 GLint *size,
+                                 GLenum *type,
+                                 GLchar *name) const
+{
+    if (!mLinked)
+    {
+        if (bufsize > 0)
+        {
+            name[0] = '\0';
+        }
+
+        if (length)
+        {
+            *length = 0;
+        }
+
+        *type = GL_NONE;
+        *size = 1;
+        return;
+    }
+
+    ASSERT(index < mState.mAttributes.size());
+    const sh::Attribute &attrib = mState.mAttributes[index];
+
+    if (bufsize > 0)
+    {
+        CopyStringToBuffer(name, attrib.name, bufsize, length);
+    }
+
+    // Always a single 'type' instance
+    *size = 1;
+    *type = attrib.type;
+}
+
+GLint Program::getActiveAttributeCount() const
+{
+    if (!mLinked)
+    {
+        return 0;
+    }
+
+    return static_cast<GLint>(mState.mAttributes.size());
+}
+
+GLint Program::getActiveAttributeMaxLength() const
+{
+    if (!mLinked)
+    {
+        return 0;
+    }
+
+    size_t maxLength = 0;
+
+    for (const sh::Attribute &attrib : mState.mAttributes)
+    {
+        maxLength = std::max(attrib.name.length() + 1, maxLength);
+    }
+
+    return static_cast<GLint>(maxLength);
+}
+
+GLuint Program::getInputResourceIndex(const GLchar *name) const
+{
+    for (GLuint attributeIndex = 0; attributeIndex < mState.mAttributes.size(); ++attributeIndex)
+    {
+        const sh::Attribute &attribute = mState.mAttributes[attributeIndex];
+        if (attribute.name == name)
+        {
+            return attributeIndex;
+        }
+    }
+    return GL_INVALID_INDEX;
+}
+
+GLuint Program::getOutputResourceIndex(const GLchar *name) const
+{
+    return GetResourceIndexFromName(mState.mOutputVariables, std::string(name));
+}
+
+size_t Program::getOutputResourceCount() const
+{
+    return (mLinked ? mState.mOutputVariables.size() : 0);
+}
+
+void Program::getInputResourceName(GLuint index,
+                                   GLsizei bufSize,
+                                   GLsizei *length,
+                                   GLchar *name) const
+{
+    GLint size;
+    GLenum type;
+    getActiveAttribute(index, bufSize, length, &size, &type, name);
+}
+
+void Program::getOutputResourceName(GLuint index,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLchar *name) const
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (!mLinked)
+    {
+        if (bufSize > 0)
+        {
+            name[0] = '\0';
+        }
+        return;
+    }
+    ASSERT(index < mState.mOutputVariables.size());
+    const auto &output = mState.mOutputVariables[index];
+
+    if (bufSize > 0)
+    {
+        std::string nameWithArray = (output.isArray() ? output.name + "[0]" : output.name);
+
+        CopyStringToBuffer(name, nameWithArray, bufSize, length);
+    }
+}
+
+GLint Program::getFragDataLocation(const std::string &name) const
+{
+    std::string baseName(name);
+    unsigned int arrayIndex = ParseAndStripArrayIndex(&baseName);
+    for (auto outputPair : mState.mOutputLocations)
+    {
+        const VariableLocation &outputVariable = outputPair.second;
+        if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
+        {
+            return static_cast<GLint>(outputPair.first);
+        }
+    }
+    return -1;
+}
+
+void Program::getActiveUniform(GLuint index,
+                               GLsizei bufsize,
+                               GLsizei *length,
+                               GLint *size,
+                               GLenum *type,
+                               GLchar *name) const
+{
+    if (mLinked)
+    {
+        // index must be smaller than getActiveUniformCount()
+        ASSERT(index < mState.mUniforms.size());
+        const LinkedUniform &uniform = mState.mUniforms[index];
+
+        if (bufsize > 0)
+        {
+            std::string string = uniform.name;
+            if (uniform.isArray())
+            {
+                string += "[0]";
+            }
+            CopyStringToBuffer(name, string, bufsize, length);
+        }
+
+        *size = uniform.elementCount();
+        *type = uniform.type;
+    }
+    else
+    {
+        if (bufsize > 0)
+        {
+            name[0] = '\0';
+        }
+
+        if (length)
+        {
+            *length = 0;
+        }
+
+        *size = 0;
+        *type = GL_NONE;
+    }
+}
+
+GLint Program::getActiveUniformCount() const
+{
+    if (mLinked)
+    {
+        return static_cast<GLint>(mState.mUniforms.size());
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+GLint Program::getActiveUniformMaxLength() const
+{
+    size_t maxLength = 0;
+
+    if (mLinked)
+    {
+        for (const LinkedUniform &uniform : mState.mUniforms)
+        {
+            if (!uniform.name.empty())
+            {
+                size_t length = uniform.name.length() + 1u;
+                if (uniform.isArray())
+                {
+                    length += 3;  // Counting in "[0]".
+                }
+                maxLength = std::max(length, maxLength);
+            }
+        }
+    }
+
+    return static_cast<GLint>(maxLength);
+}
+
+GLint Program::getActiveUniformi(GLuint index, GLenum pname) const
+{
+    ASSERT(static_cast<size_t>(index) < mState.mUniforms.size());
+    const LinkedUniform &uniform = mState.mUniforms[index];
+    switch (pname)
+    {
+      case GL_UNIFORM_TYPE:         return static_cast<GLint>(uniform.type);
+      case GL_UNIFORM_SIZE:         return static_cast<GLint>(uniform.elementCount());
+      case GL_UNIFORM_NAME_LENGTH:  return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0));
+      case GL_UNIFORM_BLOCK_INDEX:  return uniform.blockIndex;
+      case GL_UNIFORM_OFFSET:       return uniform.blockInfo.offset;
+      case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
+      case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
+      case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
+      default:
+        UNREACHABLE();
+        break;
+    }
+    return 0;
+}
+
+bool Program::isValidUniformLocation(GLint location) const
+{
+    ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
+    return (location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size() &&
+            mState.mUniformLocations[static_cast<size_t>(location)].used);
+}
+
+const LinkedUniform &Program::getUniformByLocation(GLint location) const
+{
+    ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
+    return mState.mUniforms[mState.getUniformIndexFromLocation(location)];
+}
+
+const VariableLocation &Program::getUniformLocation(GLint location) const
+{
+    ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
+    return mState.mUniformLocations[location];
+}
+
+const std::vector<VariableLocation> &Program::getUniformLocations() const
+{
+    return mState.mUniformLocations;
+}
+
+const LinkedUniform &Program::getUniformByIndex(GLuint index) const
+{
+    ASSERT(index < static_cast<size_t>(mState.mUniforms.size()));
+    return mState.mUniforms[index];
+}
+
+GLint Program::getUniformLocation(const std::string &name) const
+{
+    return mState.getUniformLocation(name);
+}
+
+GLuint Program::getUniformIndex(const std::string &name) const
+{
+    return mState.getUniformIndexFromName(name);
+}
+
+void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 1, v);
+    mProgram->setUniform1fv(location, clampedCount, v);
+}
+
+void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 2, v);
+    mProgram->setUniform2fv(location, clampedCount, v);
+}
+
+void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 3, v);
+    mProgram->setUniform3fv(location, clampedCount, v);
+}
+
+void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 4, v);
+    mProgram->setUniform4fv(location, clampedCount, v);
+}
+
+void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 1, v);
+    mProgram->setUniform1iv(location, clampedCount, v);
+}
+
+void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 2, v);
+    mProgram->setUniform2iv(location, clampedCount, v);
+}
+
+void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 3, v);
+    mProgram->setUniform3iv(location, clampedCount, v);
+}
+
+void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 4, v);
+    mProgram->setUniform4iv(location, clampedCount, v);
+}
+
+void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 1, v);
+    mProgram->setUniform1uiv(location, clampedCount, v);
+}
+
+void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 2, v);
+    mProgram->setUniform2uiv(location, clampedCount, v);
+}
+
+void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 3, v);
+    mProgram->setUniform3uiv(location, clampedCount, v);
+}
+
+void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    GLsizei clampedCount = setUniformInternal(location, count, 4, v);
+    mProgram->setUniform4uiv(location, clampedCount, v);
+}
+
+void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+    GLsizei clampedCount = setMatrixUniformInternal<2, 2>(location, count, transpose, v);
+    mProgram->setUniformMatrix2fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+    GLsizei clampedCount = setMatrixUniformInternal<3, 3>(location, count, transpose, v);
+    mProgram->setUniformMatrix3fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+    GLsizei clampedCount = setMatrixUniformInternal<4, 4>(location, count, transpose, v);
+    mProgram->setUniformMatrix4fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+    GLsizei clampedCount = setMatrixUniformInternal<2, 3>(location, count, transpose, v);
+    mProgram->setUniformMatrix2x3fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+    GLsizei clampedCount = setMatrixUniformInternal<2, 4>(location, count, transpose, v);
+    mProgram->setUniformMatrix2x4fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+    GLsizei clampedCount = setMatrixUniformInternal<3, 2>(location, count, transpose, v);
+    mProgram->setUniformMatrix3x2fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+    GLsizei clampedCount = setMatrixUniformInternal<3, 4>(location, count, transpose, v);
+    mProgram->setUniformMatrix3x4fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+    GLsizei clampedCount = setMatrixUniformInternal<4, 2>(location, count, transpose, v);
+    mProgram->setUniformMatrix4x2fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+    GLsizei clampedCount = setMatrixUniformInternal<4, 3>(location, count, transpose, v);
+    mProgram->setUniformMatrix4x3fv(location, clampedCount, transpose, v);
+}
+
+void Program::getUniformfv(GLint location, GLfloat *v) const
+{
+    getUniformInternal(location, v);
+}
+
+void Program::getUniformiv(GLint location, GLint *v) const
+{
+    getUniformInternal(location, v);
+}
+
+void Program::getUniformuiv(GLint location, GLuint *v) const
+{
+    getUniformInternal(location, v);
+}
+
+void Program::flagForDeletion()
+{
+    mDeleteStatus = true;
+}
+
+bool Program::isFlaggedForDeletion() const
+{
+    return mDeleteStatus;
+}
+
+void Program::validate(const Caps &caps)
+{
+    mInfoLog.reset();
+
+    if (mLinked)
+    {
+        mValidated = (mProgram->validate(caps, &mInfoLog) == GL_TRUE);
+    }
+    else
+    {
+        mInfoLog << "Program has not been successfully linked.";
+    }
+}
+
+bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps)
+{
+    // Skip cache if we're using an infolog, so we get the full error.
+    // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
+    if (infoLog == nullptr && mCachedValidateSamplersResult.valid())
+    {
+        return mCachedValidateSamplersResult.value();
+    }
+
+    if (mTextureUnitTypesCache.empty())
+    {
+        mTextureUnitTypesCache.resize(caps.maxCombinedTextureImageUnits, GL_NONE);
+    }
+    else
+    {
+        std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
+    }
+
+    // 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.
+    for (const auto &samplerBinding : mState.mSamplerBindings)
+    {
+        GLenum textureType = samplerBinding.textureType;
+
+        for (GLuint textureUnit : samplerBinding.boundTextureUnits)
+        {
+            if (textureUnit >= caps.maxCombinedTextureImageUnits)
+            {
+                if (infoLog)
+                {
+                    (*infoLog) << "Sampler uniform (" << textureUnit
+                               << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
+                               << caps.maxCombinedTextureImageUnits << ")";
+                }
+
+                mCachedValidateSamplersResult = false;
+                return false;
+            }
+
+            if (mTextureUnitTypesCache[textureUnit] != GL_NONE)
+            {
+                if (textureType != mTextureUnitTypesCache[textureUnit])
+                {
+                    if (infoLog)
+                    {
+                        (*infoLog) << "Samplers of conflicting types refer to the same texture "
+                                      "image unit ("
+                                   << textureUnit << ").";
+                    }
+
+                    mCachedValidateSamplersResult = false;
+                    return false;
+                }
+            }
+            else
+            {
+                mTextureUnitTypesCache[textureUnit] = textureType;
+            }
+        }
+    }
+
+    mCachedValidateSamplersResult = true;
+    return true;
+}
+
+bool Program::isValidated() const
+{
+    return mValidated;
+}
+
+GLuint Program::getActiveUniformBlockCount() const
+{
+    return static_cast<GLuint>(mState.mUniformBlocks.size());
+}
+
+void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
+{
+    ASSERT(
+        uniformBlockIndex <
+        mState.mUniformBlocks.size());  // index must be smaller than getActiveUniformBlockCount()
+
+    const UniformBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex];
+
+    if (bufSize > 0)
+    {
+        std::string string = uniformBlock.name;
+
+        if (uniformBlock.isArray)
+        {
+            string += ArrayString(uniformBlock.arrayElement);
+        }
+        CopyStringToBuffer(uniformBlockName, string, bufSize, length);
+    }
+}
+
+GLint Program::getActiveUniformBlockMaxLength() const
+{
+    int maxLength = 0;
+
+    if (mLinked)
+    {
+        unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size());
+        for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
+        {
+            const UniformBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex];
+            if (!uniformBlock.name.empty())
+            {
+                const int length = static_cast<int>(uniformBlock.name.length()) + 1;
+
+                // Counting in "[0]".
+                const int arrayLength = (uniformBlock.isArray ? 3 : 0);
+
+                maxLength = std::max(length + arrayLength, maxLength);
+            }
+        }
+    }
+
+    return maxLength;
+}
+
+GLuint Program::getUniformBlockIndex(const std::string &name) const
+{
+    size_t subscript     = GL_INVALID_INDEX;
+    std::string baseName = ParseResourceName(name, &subscript);
+
+    unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size());
+    for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
+    {
+        const UniformBlock &uniformBlock = mState.mUniformBlocks[blockIndex];
+        if (uniformBlock.name == baseName)
+        {
+            const bool arrayElementZero =
+                (subscript == GL_INVALID_INDEX &&
+                 (!uniformBlock.isArray || uniformBlock.arrayElement == 0));
+            if (subscript == uniformBlock.arrayElement || arrayElementZero)
+            {
+                return blockIndex;
+            }
+        }
+    }
+
+    return GL_INVALID_INDEX;
+}
+
+const UniformBlock &Program::getUniformBlockByIndex(GLuint index) const
+{
+    ASSERT(index < static_cast<GLuint>(mState.mUniformBlocks.size()));
+    return mState.mUniformBlocks[index];
+}
+
+void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+    mState.mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
+    mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlockBinding != 0);
+    mProgram->setUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
+}
+
+GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
+{
+    return mState.getUniformBlockBinding(uniformBlockIndex);
+}
+
+void Program::resetUniformBlockBindings()
+{
+    for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
+    {
+        mState.mUniformBlockBindings[blockId] = 0;
+    }
+    mState.mActiveUniformBlockBindings.reset();
+}
+
+void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
+{
+    mState.mTransformFeedbackVaryingNames.resize(count);
+    for (GLsizei i = 0; i < count; i++)
+    {
+        mState.mTransformFeedbackVaryingNames[i] = varyings[i];
+    }
+
+    mState.mTransformFeedbackBufferMode = bufferMode;
+}
+
+void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
+{
+    if (mLinked)
+    {
+        ASSERT(index < mState.mLinkedTransformFeedbackVaryings.size());
+        const auto &var     = mState.mLinkedTransformFeedbackVaryings[index];
+        std::string varName = var.nameWithArrayIndex();
+        GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
+        if (length)
+        {
+            *length = lastNameIdx;
+        }
+        if (size)
+        {
+            *size = var.size();
+        }
+        if (type)
+        {
+            *type = var.type;
+        }
+        if (name)
+        {
+            memcpy(name, varName.c_str(), lastNameIdx);
+            name[lastNameIdx] = '\0';
+        }
+    }
+}
+
+GLsizei Program::getTransformFeedbackVaryingCount() const
+{
+    if (mLinked)
+    {
+        return static_cast<GLsizei>(mState.mLinkedTransformFeedbackVaryings.size());
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+GLsizei Program::getTransformFeedbackVaryingMaxLength() const
+{
+    if (mLinked)
+    {
+        GLsizei maxSize = 0;
+        for (const auto &var : mState.mLinkedTransformFeedbackVaryings)
+        {
+            maxSize =
+                std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
+        }
+
+        return maxSize;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+GLenum Program::getTransformFeedbackBufferMode() const
+{
+    return mState.mTransformFeedbackBufferMode;
+}
+
+bool Program::linkVaryings(InfoLog &infoLog) const
+{
+    const Shader *vertexShader   = mState.mAttachedVertexShader;
+    const Shader *fragmentShader = mState.mAttachedFragmentShader;
+
+    ASSERT(vertexShader->getShaderVersion() == fragmentShader->getShaderVersion());
+
+    const std::vector<sh::Varying> &vertexVaryings   = vertexShader->getVaryings();
+    const std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getVaryings();
+
+    std::map<GLuint, std::string> staticFragmentInputLocations;
+
+    for (const sh::Varying &output : fragmentVaryings)
+    {
+        bool matched = false;
+
+        // Built-in varyings obey special rules
+        if (output.isBuiltIn())
+        {
+            continue;
+        }
+
+        for (const sh::Varying &input : vertexVaryings)
+        {
+            if (output.name == input.name)
+            {
+                ASSERT(!input.isBuiltIn());
+                if (!linkValidateVaryings(infoLog, output.name, input, output,
+                                          vertexShader->getShaderVersion()))
+                {
+                    return false;
+                }
+
+                matched = true;
+                break;
+            }
+        }
+
+        // We permit unmatched, unreferenced varyings
+        if (!matched && output.staticUse)
+        {
+            infoLog << "Fragment varying " << output.name << " does not match any vertex varying";
+            return false;
+        }
+
+        // Check for aliased path rendering input bindings (if any).
+        // If more than one binding refer statically to the same
+        // location the link must fail.
+
+        if (!output.staticUse)
+            continue;
+
+        const auto inputBinding = mFragmentInputBindings.getBinding(output.name);
+        if (inputBinding == -1)
+            continue;
+
+        const auto it = staticFragmentInputLocations.find(inputBinding);
+        if (it == std::end(staticFragmentInputLocations))
+        {
+            staticFragmentInputLocations.insert(std::make_pair(inputBinding, output.name));
+        }
+        else
+        {
+            infoLog << "Binding for fragment input " << output.name << " conflicts with "
+                    << it->second;
+            return false;
+        }
+    }
+
+    if (!linkValidateBuiltInVaryings(infoLog))
+    {
+        return false;
+    }
+
+    // TODO(jmadill): verify no unmatched vertex varyings?
+
+    return true;
+}
+
+bool Program::linkUniforms(InfoLog &infoLog,
+                           const Caps &caps,
+                           const Bindings &uniformLocationBindings)
+{
+    UniformLinker linker(mState);
+    if (!linker.link(infoLog, caps, uniformLocationBindings))
+    {
+        return false;
+    }
+
+    linker.getResults(&mState.mUniforms, &mState.mUniformLocations);
+
+    linkSamplerBindings();
+
+    return true;
+}
+
+void Program::linkSamplerBindings()
+{
+    mState.mSamplerUniformRange.end   = static_cast<unsigned int>(mState.mUniforms.size());
+    mState.mSamplerUniformRange.start = mState.mSamplerUniformRange.end;
+    auto samplerIter                  = mState.mUniforms.rbegin();
+    while (samplerIter != mState.mUniforms.rend() && samplerIter->isSampler())
+    {
+        --mState.mSamplerUniformRange.start;
+        ++samplerIter;
+    }
+    // If uniform is a sampler type, insert it into the mSamplerBindings array.
+    for (unsigned int samplerIndex = mState.mSamplerUniformRange.start;
+         samplerIndex < mState.mUniforms.size(); ++samplerIndex)
+    {
+        const auto &samplerUniform = mState.mUniforms[samplerIndex];
+        GLenum textureType         = SamplerTypeToTextureType(samplerUniform.type);
+        mState.mSamplerBindings.emplace_back(
+            SamplerBinding(textureType, samplerUniform.elementCount()));
+    }
+}
+
+bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog,
+                                               const std::string &uniformName,
+                                               const sh::InterfaceBlockField &vertexUniform,
+                                               const sh::InterfaceBlockField &fragmentUniform)
+{
+    // We don't validate precision on UBO fields. See resolution of Khronos bug 10287.
+    if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, false))
+    {
+        return false;
+    }
+
+    if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
+    {
+        infoLog << "Matrix packings for " << uniformName << " differ between vertex and fragment shaders";
+        return false;
+    }
+
+    return true;
+}
+
+// Assigns locations to all attributes from the bindings and program locations.
+bool Program::linkAttributes(const ContextState &data, InfoLog &infoLog)
+{
+    const auto *vertexShader = mState.getAttachedVertexShader();
+
+    unsigned int usedLocations = 0;
+    mState.mAttributes         = vertexShader->getActiveAttributes();
+    GLuint maxAttribs          = data.getCaps().maxVertexAttributes;
+
+    // TODO(jmadill): handle aliasing robustly
+    if (mState.mAttributes.size() > maxAttribs)
+    {
+        infoLog << "Too many vertex attributes.";
+        return false;
+    }
+
+    std::vector<sh::Attribute *> usedAttribMap(maxAttribs, nullptr);
+
+    // Link attributes that have a binding location
+    for (sh::Attribute &attribute : mState.mAttributes)
+    {
+        int bindingLocation = mAttributeBindings.getBinding(attribute.name);
+        if (attribute.location == -1 && bindingLocation != -1)
+        {
+            attribute.location = bindingLocation;
+        }
+
+        if (attribute.location != -1)
+        {
+            // Location is set by glBindAttribLocation or by location layout qualifier
+            const int regs = VariableRegisterCount(attribute.type);
+
+            if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
+            {
+                infoLog << "Active attribute (" << attribute.name << ") at location "
+                        << attribute.location << " is too big to fit";
+
+                return false;
+            }
+
+            for (int reg = 0; reg < regs; reg++)
+            {
+                const int regLocation               = attribute.location + reg;
+                sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
+
+                // In GLSL 3.00, attribute aliasing produces a link error
+                // In GLSL 1.00, attribute aliasing is allowed, but ANGLE currently has a bug
+                if (linkedAttribute)
+                {
+                    // TODO(jmadill): fix aliasing on ES2
+                    // if (mProgram->getShaderVersion() >= 300)
+                    {
+                        infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
+                                << linkedAttribute->name << "' at location " << regLocation;
+                        return false;
+                    }
+                }
+                else
+                {
+                    usedAttribMap[regLocation] = &attribute;
+                }
+
+                usedLocations |= 1 << regLocation;
+            }
+        }
+    }
+
+    // Link attributes that don't have a binding location
+    for (sh::Attribute &attribute : mState.mAttributes)
+    {
+        // Not set by glBindAttribLocation or by location layout qualifier
+        if (attribute.location == -1)
+        {
+            int regs           = VariableRegisterCount(attribute.type);
+            int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
+
+            if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
+            {
+                infoLog << "Too many active attributes (" << attribute.name << ")";
+                return false;
+            }
+
+            attribute.location = availableIndex;
+        }
+    }
+
+    for (const sh::Attribute &attribute : mState.mAttributes)
+    {
+        ASSERT(attribute.location != -1);
+        int regs = VariableRegisterCount(attribute.type);
+
+        for (int r = 0; r < regs; r++)
+        {
+            mState.mActiveAttribLocationsMask.set(attribute.location + r);
+        }
+    }
+
+    return true;
+}
+
+bool Program::validateUniformBlocksCount(GLuint maxUniformBlocks,
+                                         const std::vector<sh::InterfaceBlock> &intefaceBlocks,
+                                         const std::string &errorMessage,
+                                         InfoLog &infoLog) const
+{
+    GLuint blockCount = 0;
+    for (const sh::InterfaceBlock &block : intefaceBlocks)
+    {
+        if (block.staticUse || block.layout != sh::BLOCKLAYOUT_PACKED)
+        {
+            if (++blockCount > maxUniformBlocks)
+            {
+                infoLog << errorMessage << maxUniformBlocks << ")";
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool Program::validateVertexAndFragmentInterfaceBlocks(
+    const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
+    const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
+    InfoLog &infoLog) const
+{
+    // 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 (const sh::InterfaceBlock &vertexInterfaceBlock : vertexInterfaceBlocks)
+    {
+        linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
+    }
+
+    for (const sh::InterfaceBlock &fragmentInterfaceBlock : fragmentInterfaceBlocks)
+    {
+        auto entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
+        if (entry != linkedUniformBlocks.end())
+        {
+            const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
+            if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
+            {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool Program::linkUniformBlocks(InfoLog &infoLog, const Caps &caps)
+{
+    if (mState.mAttachedComputeShader)
+    {
+        const Shader &computeShader        = *mState.mAttachedComputeShader;
+        const auto &computeInterfaceBlocks = computeShader.getInterfaceBlocks();
+
+        if (!validateUniformBlocksCount(
+                caps.maxComputeUniformBlocks, computeInterfaceBlocks,
+                "Compute shader uniform block count exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS (",
+                infoLog))
+        {
+            return false;
+        }
+        return true;
+    }
+
+    const Shader &vertexShader   = *mState.mAttachedVertexShader;
+    const Shader &fragmentShader = *mState.mAttachedFragmentShader;
+
+    const auto &vertexInterfaceBlocks   = vertexShader.getInterfaceBlocks();
+    const auto &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
+
+    if (!validateUniformBlocksCount(
+            caps.maxVertexUniformBlocks, vertexInterfaceBlocks,
+            "Vertex shader uniform block count exceeds GL_MAX_VERTEX_UNIFORM_BLOCKS (", infoLog))
+    {
+        return false;
+    }
+    if (!validateUniformBlocksCount(
+            caps.maxFragmentUniformBlocks, fragmentInterfaceBlocks,
+            "Fragment shader uniform block count exceeds GL_MAX_FRAGMENT_UNIFORM_BLOCKS (",
+            infoLog))
+    {
+
+        return false;
+    }
+    if (!validateVertexAndFragmentInterfaceBlocks(vertexInterfaceBlocks, fragmentInterfaceBlocks,
+                                                  infoLog))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool Program::areMatchingInterfaceBlocks(InfoLog &infoLog,
+                                         const sh::InterfaceBlock &vertexInterfaceBlock,
+                                         const sh::InterfaceBlock &fragmentInterfaceBlock) const
+{
+    const char* blockName = vertexInterfaceBlock.name.c_str();
+    // validate blocks for the same member types
+    if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
+    {
+        infoLog << "Types for interface block '" << blockName
+                << "' differ between vertex and fragment shaders";
+        return false;
+    }
+    if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
+    {
+        infoLog << "Array sizes differ for interface block '" << blockName
+                << "' between vertex and fragment shaders";
+        return false;
+    }
+    if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
+    {
+        infoLog << "Layout qualifiers differ for interface block '" << blockName
+                << "' between vertex and fragment shaders";
+        return false;
+    }
+    const unsigned int numBlockMembers =
+        static_cast<unsigned int>(vertexInterfaceBlock.fields.size());
+    for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
+    {
+        const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
+        const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
+        if (vertexMember.name != fragmentMember.name)
+        {
+            infoLog << "Name mismatch for field " << blockMemberIndex
+                    << " of interface block '" << blockName
+                    << "': (in vertex: '" << vertexMember.name
+                    << "', in fragment: '" << fragmentMember.name << "')";
+            return false;
+        }
+        std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
+        if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
+                                              const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
+{
+    if (vertexVariable.type != fragmentVariable.type)
+    {
+        infoLog << "Types for " << variableName << " differ between vertex and fragment shaders";
+        return false;
+    }
+    if (vertexVariable.arraySize != fragmentVariable.arraySize)
+    {
+        infoLog << "Array sizes for " << variableName << " differ between vertex and fragment shaders";
+        return false;
+    }
+    if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
+    {
+        infoLog << "Precisions for " << variableName << " differ between vertex and fragment shaders";
+        return false;
+    }
+
+    if (vertexVariable.fields.size() != fragmentVariable.fields.size())
+    {
+        infoLog << "Structure lengths for " << variableName << " differ between vertex and fragment shaders";
+        return false;
+    }
+    const unsigned int numMembers = static_cast<unsigned int>(vertexVariable.fields.size());
+    for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
+    {
+        const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex];
+        const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex];
+
+        if (vertexMember.name != fragmentMember.name)
+        {
+            infoLog << "Name mismatch for field '" << memberIndex
+                    << "' of " << variableName
+                    << ": (in vertex: '" << vertexMember.name
+                    << "', in fragment: '" << fragmentMember.name << "')";
+            return false;
+        }
+
+        const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." +
+                                       vertexMember.name + "'";
+
+        if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool Program::linkValidateVaryings(InfoLog &infoLog,
+                                   const std::string &varyingName,
+                                   const sh::Varying &vertexVarying,
+                                   const sh::Varying &fragmentVarying,
+                                   int shaderVersion)
+{
+    if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
+    {
+        return false;
+    }
+
+    if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation))
+    {
+        infoLog << "Interpolation types for " << varyingName
+                << " differ between vertex and fragment shaders.";
+        return false;
+    }
+
+    if (shaderVersion == 100 && vertexVarying.isInvariant != fragmentVarying.isInvariant)
+    {
+        infoLog << "Invariance for " << varyingName
+                << " differs between vertex and fragment shaders.";
+        return false;
+    }
+
+    return true;
+}
+
+bool Program::linkValidateBuiltInVaryings(InfoLog &infoLog) const
+{
+    const Shader *vertexShader                       = mState.mAttachedVertexShader;
+    const Shader *fragmentShader                     = mState.mAttachedFragmentShader;
+    const std::vector<sh::Varying> &vertexVaryings   = vertexShader->getVaryings();
+    const std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getVaryings();
+    int shaderVersion                                = vertexShader->getShaderVersion();
+
+    if (shaderVersion != 100)
+    {
+        // Only ESSL 1.0 has restrictions on matching input and output invariance
+        return true;
+    }
+
+    bool glPositionIsInvariant   = false;
+    bool glPointSizeIsInvariant  = false;
+    bool glFragCoordIsInvariant  = false;
+    bool glPointCoordIsInvariant = false;
+
+    for (const sh::Varying &varying : vertexVaryings)
+    {
+        if (!varying.isBuiltIn())
+        {
+            continue;
+        }
+        if (varying.name.compare("gl_Position") == 0)
+        {
+            glPositionIsInvariant = varying.isInvariant;
+        }
+        else if (varying.name.compare("gl_PointSize") == 0)
+        {
+            glPointSizeIsInvariant = varying.isInvariant;
+        }
+    }
+
+    for (const sh::Varying &varying : fragmentVaryings)
+    {
+        if (!varying.isBuiltIn())
+        {
+            continue;
+        }
+        if (varying.name.compare("gl_FragCoord") == 0)
+        {
+            glFragCoordIsInvariant = varying.isInvariant;
+        }
+        else if (varying.name.compare("gl_PointCoord") == 0)
+        {
+            glPointCoordIsInvariant = varying.isInvariant;
+        }
+    }
+
+    // There is some ambiguity in ESSL 1.00.17 paragraph 4.6.4 interpretation,
+    // for example, https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13842.
+    // Not requiring invariance to match is supported by:
+    // dEQP, WebGL CTS, Nexus 5X GLES
+    if (glFragCoordIsInvariant && !glPositionIsInvariant)
+    {
+        infoLog << "gl_FragCoord can only be declared invariant if and only if gl_Position is "
+                   "declared invariant.";
+        return false;
+    }
+    if (glPointCoordIsInvariant && !glPointSizeIsInvariant)
+    {
+        infoLog << "gl_PointCoord can only be declared invariant if and only if gl_PointSize is "
+                   "declared invariant.";
+        return false;
+    }
+
+    return true;
+}
+
+bool Program::linkValidateTransformFeedback(const gl::Context *context,
+                                            InfoLog &infoLog,
+                                            const Program::MergedVaryings &varyings,
+                                            const Caps &caps) const
+{
+    size_t totalComponents = 0;
+
+    std::set<std::string> uniqueNames;
+
+    for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
+    {
+        bool found = false;
+        size_t subscript     = GL_INVALID_INDEX;
+        std::string baseName = ParseResourceName(tfVaryingName, &subscript);
+
+        for (const auto &ref : varyings)
+        {
+            const sh::Varying *varying = ref.second.get();
+
+            if (baseName == varying->name)
+            {
+                if (uniqueNames.count(tfVaryingName) > 0)
+                {
+                    infoLog << "Two transform feedback varyings specify the same output variable ("
+                            << tfVaryingName << ").";
+                    return false;
+                }
+                if (context->getClientVersion() >= Version(3, 1))
+                {
+                    if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
+                    {
+                        infoLog
+                            << "Two transform feedback varyings include the same array element ("
+                            << tfVaryingName << ").";
+                        return false;
+                    }
+                }
+                else if (varying->isArray())
+                {
+                    infoLog << "Capture of arrays is undefined and not supported.";
+                    return false;
+                }
+
+                uniqueNames.insert(tfVaryingName);
+
+                // TODO(jmadill): Investigate implementation limits on D3D11
+                size_t elementCount =
+                    ((varying->isArray() && subscript == GL_INVALID_INDEX) ? varying->elementCount()
+                                                                           : 1);
+                size_t componentCount = VariableComponentCount(varying->type) * elementCount;
+                if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
+                    componentCount > caps.maxTransformFeedbackSeparateComponents)
+                {
+                    infoLog << "Transform feedback varying's " << varying->name << " components ("
+                            << componentCount << ") exceed the maximum separate components ("
+                            << caps.maxTransformFeedbackSeparateComponents << ").";
+                    return false;
+                }
+
+                totalComponents += componentCount;
+                found = true;
+                break;
+            }
+        }
+        if (context->getClientVersion() < Version(3, 1) &&
+            tfVaryingName.find('[') != std::string::npos)
+        {
+            infoLog << "Capture of array elements is undefined and not supported.";
+            return false;
+        }
+        // All transform feedback varyings are expected to exist since packVaryings checks for them.
+        ASSERT(found);
+    }
+
+    if (mState.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
+        totalComponents > caps.maxTransformFeedbackInterleavedComponents)
+    {
+        infoLog << "Transform feedback varying total components (" << totalComponents
+                << ") exceed the maximum interleaved components ("
+                << caps.maxTransformFeedbackInterleavedComponents << ").";
+        return false;
+    }
+
+    return true;
+}
+
+void Program::gatherTransformFeedbackVaryings(const Program::MergedVaryings &varyings)
+{
+    // Gather the linked varyings that are used for transform feedback, they should all exist.
+    mState.mLinkedTransformFeedbackVaryings.clear();
+    for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
+    {
+        size_t subscript     = GL_INVALID_INDEX;
+        std::string baseName = ParseResourceName(tfVaryingName, &subscript);
+        for (const auto &ref : varyings)
+        {
+            const sh::Varying *varying = ref.second.get();
+            if (baseName == varying->name)
+            {
+                mState.mLinkedTransformFeedbackVaryings.emplace_back(
+                    *varying, static_cast<GLuint>(subscript));
+                break;
+            }
+        }
+    }
+}
+
+Program::MergedVaryings Program::getMergedVaryings() const
+{
+    MergedVaryings merged;
+
+    for (const sh::Varying &varying : mState.mAttachedVertexShader->getVaryings())
+    {
+        merged[varying.name].vertex = &varying;
+    }
+
+    for (const sh::Varying &varying : mState.mAttachedFragmentShader->getVaryings())
+    {
+        merged[varying.name].fragment = &varying;
+    }
+
+    return merged;
+}
+
+std::vector<PackedVarying> Program::getPackedVaryings(
+    const Program::MergedVaryings &mergedVaryings) const
+{
+    const std::vector<std::string> &tfVaryings = mState.getTransformFeedbackVaryingNames();
+    std::vector<PackedVarying> packedVaryings;
+    std::set<std::string> uniqueFullNames;
+
+    for (const auto &ref : mergedVaryings)
+    {
+        const sh::Varying *input  = ref.second.vertex;
+        const sh::Varying *output = ref.second.fragment;
+
+        // Only pack varyings that have a matched input or output, plus special builtins.
+        if ((input && output) || (output && output->isBuiltIn()))
+        {
+            // Will get the vertex shader interpolation by default.
+            auto interpolation = ref.second.get()->interpolation;
+
+            // Interpolation qualifiers must match.
+            if (output->isStruct())
+            {
+                ASSERT(!output->isArray());
+                for (const auto &field : output->fields)
+                {
+                    ASSERT(!field.isStruct() && !field.isArray());
+                    packedVaryings.push_back(PackedVarying(field, interpolation, output->name));
+                }
+            }
+            else
+            {
+                packedVaryings.push_back(PackedVarying(*output, interpolation));
+            }
+            continue;
+        }
+
+        // Keep Transform FB varyings in the merged list always.
+        if (!input)
+        {
+            continue;
+        }
+
+        for (const std::string &tfVarying : tfVaryings)
+        {
+            size_t subscript     = GL_INVALID_INDEX;
+            std::string baseName = ParseResourceName(tfVarying, &subscript);
+            if (uniqueFullNames.count(tfVarying) > 0)
+            {
+                continue;
+            }
+            if (baseName == input->name)
+            {
+                // Transform feedback for varying structs is underspecified.
+                // See Khronos bug 9856.
+                // TODO(jmadill): Figure out how to be spec-compliant here.
+                if (!input->isStruct())
+                {
+                    packedVaryings.push_back(PackedVarying(*input, input->interpolation));
+                    packedVaryings.back().vertexOnly = true;
+                    packedVaryings.back().arrayIndex = static_cast<GLuint>(subscript);
+                    uniqueFullNames.insert(tfVarying);
+                }
+                if (subscript == GL_INVALID_INDEX)
+                {
+                    break;
+                }
+            }
+        }
+    }
+
+    std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying);
+
+    return packedVaryings;
+}
+
+void Program::linkOutputVariables()
+{
+    const Shader *fragmentShader = mState.mAttachedFragmentShader;
+    ASSERT(fragmentShader != nullptr);
+
+    // Skip this step for GLES2 shaders.
+    if (fragmentShader->getShaderVersion() == 100)
+        return;
+
+    mState.mOutputVariables = fragmentShader->getActiveOutputVariables();
+    // TODO(jmadill): any caps validation here?
+
+    for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size();
+         outputVariableIndex++)
+    {
+        const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
+
+        // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
+        if (outputVariable.isBuiltIn())
+            continue;
+
+        // Since multiple output locations must be specified, use 0 for non-specified locations.
+        int baseLocation = (outputVariable.location == -1 ? 0 : outputVariable.location);
+
+        for (unsigned int elementIndex = 0; elementIndex < outputVariable.elementCount();
+             elementIndex++)
+        {
+            const int location = baseLocation + elementIndex;
+            ASSERT(mState.mOutputLocations.count(location) == 0);
+            unsigned int element = outputVariable.isArray() ? elementIndex : GL_INVALID_INDEX;
+            mState.mOutputLocations[location] =
+                VariableLocation(outputVariable.name, element, outputVariableIndex);
+        }
+    }
+}
+
+void Program::setUniformValuesFromBindingQualifiers()
+{
+    for (unsigned int samplerIndex = mState.mSamplerUniformRange.start;
+         samplerIndex < mState.mSamplerUniformRange.end; ++samplerIndex)
+    {
+        const auto &samplerUniform = mState.mUniforms[samplerIndex];
+        if (samplerUniform.binding != -1)
+        {
+            GLint location = mState.getUniformLocation(samplerUniform.name);
+            ASSERT(location != -1);
+            std::vector<GLint> boundTextureUnits;
+            for (unsigned int elementIndex = 0; elementIndex < samplerUniform.elementCount();
+                 ++elementIndex)
+            {
+                boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
+            }
+            setUniform1iv(location, static_cast<GLsizei>(boundTextureUnits.size()),
+                          boundTextureUnits.data());
+        }
+    }
+}
+
+void Program::gatherInterfaceBlockInfo()
+{
+    ASSERT(mState.mUniformBlocks.empty());
+
+    if (mState.mAttachedComputeShader)
+    {
+        const Shader *computeShader = mState.getAttachedComputeShader();
+
+        for (const sh::InterfaceBlock &computeBlock : computeShader->getInterfaceBlocks())
+        {
+
+            // Only 'packed' blocks are allowed to be considered inactive.
+            if (!computeBlock.staticUse && computeBlock.layout == sh::BLOCKLAYOUT_PACKED)
+                continue;
+
+            for (UniformBlock &block : mState.mUniformBlocks)
+            {
+                if (block.name == computeBlock.name)
+                {
+                    block.computeStaticUse = computeBlock.staticUse;
+                }
+            }
+
+            defineUniformBlock(computeBlock, GL_COMPUTE_SHADER);
+        }
+        return;
+    }
+
+    std::set<std::string> visitedList;
+
+    const Shader *vertexShader = mState.getAttachedVertexShader();
+
+    for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
+    {
+        // Only 'packed' blocks are allowed to be considered inactive.
+        if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
+            continue;
+
+        if (visitedList.count(vertexBlock.name) > 0)
+            continue;
+
+        defineUniformBlock(vertexBlock, GL_VERTEX_SHADER);
+        visitedList.insert(vertexBlock.name);
+    }
+
+    const Shader *fragmentShader = mState.getAttachedFragmentShader();
+
+    for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
+    {
+        // Only 'packed' blocks are allowed to be considered inactive.
+        if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
+            continue;
+
+        if (visitedList.count(fragmentBlock.name) > 0)
+        {
+            for (UniformBlock &block : mState.mUniformBlocks)
+            {
+                if (block.name == fragmentBlock.name)
+                {
+                    block.fragmentStaticUse = fragmentBlock.staticUse;
+                }
+            }
+
+            continue;
+        }
+
+        defineUniformBlock(fragmentBlock, GL_FRAGMENT_SHADER);
+        visitedList.insert(fragmentBlock.name);
+    }
+}
+
+template <typename VarT>
+void Program::defineUniformBlockMembers(const std::vector<VarT> &fields,
+                                        const std::string &prefix,
+                                        int blockIndex)
+{
+    for (const VarT &field : fields)
+    {
+        const std::string &fullName = (prefix.empty() ? field.name : prefix + "." + field.name);
+
+        if (field.isStruct())
+        {
+            for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
+            {
+                const std::string uniformElementName =
+                    fullName + (field.isArray() ? ArrayString(arrayElement) : "");
+                defineUniformBlockMembers(field.fields, uniformElementName, blockIndex);
+            }
+        }
+        else
+        {
+            // If getBlockMemberInfo returns false, the uniform is optimized out.
+            sh::BlockMemberInfo memberInfo;
+            if (!mProgram->getUniformBlockMemberInfo(fullName, &memberInfo))
+            {
+                continue;
+            }
+
+            LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySize, -1, -1,
+                                     blockIndex, memberInfo);
+
+            // Since block uniforms have no location, we don't need to store them in the uniform
+            // locations list.
+            mState.mUniforms.push_back(newUniform);
+        }
+    }
+}
+
+void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType)
+{
+    int blockIndex   = static_cast<int>(mState.mUniformBlocks.size());
+    size_t blockSize = 0;
+
+    // Don't define this block at all if it's not active in the implementation.
+    std::stringstream blockNameStr;
+    blockNameStr << interfaceBlock.name;
+    if (interfaceBlock.arraySize > 0)
+    {
+        blockNameStr << "[0]";
+    }
+    if (!mProgram->getUniformBlockSize(blockNameStr.str(), &blockSize))
+    {
+        return;
+    }
+
+    // Track the first and last uniform index to determine the range of active uniforms in the
+    // block.
+    size_t firstBlockUniformIndex = mState.mUniforms.size();
+    defineUniformBlockMembers(interfaceBlock.fields, interfaceBlock.fieldPrefix(), blockIndex);
+    size_t lastBlockUniformIndex = mState.mUniforms.size();
+
+    std::vector<unsigned int> blockUniformIndexes;
+    for (size_t blockUniformIndex = firstBlockUniformIndex;
+         blockUniformIndex < lastBlockUniformIndex; ++blockUniformIndex)
+    {
+        blockUniformIndexes.push_back(static_cast<unsigned int>(blockUniformIndex));
+    }
+
+    if (interfaceBlock.arraySize > 0)
+    {
+        for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement)
+        {
+            UniformBlock block(interfaceBlock.name, true, arrayElement);
+            block.memberUniformIndexes = blockUniformIndexes;
+
+            switch (shaderType)
+            {
+                case GL_VERTEX_SHADER:
+                {
+                    block.vertexStaticUse = interfaceBlock.staticUse;
+                    break;
+                }
+                case GL_FRAGMENT_SHADER:
+                {
+                    block.fragmentStaticUse = interfaceBlock.staticUse;
+                    break;
+                }
+                case GL_COMPUTE_SHADER:
+                {
+                    block.computeStaticUse = interfaceBlock.staticUse;
+                    break;
+                }
+                default:
+                    UNREACHABLE();
+            }
+
+            // Since all block elements in an array share the same active uniforms, they will all be
+            // active once any uniform member is used. So, since interfaceBlock.name[0] was active,
+            // here we will add every block element in the array.
+            block.dataSize = static_cast<unsigned int>(blockSize);
+            mState.mUniformBlocks.push_back(block);
+        }
+    }
+    else
+    {
+        UniformBlock block(interfaceBlock.name, false, 0);
+        block.memberUniformIndexes = blockUniformIndexes;
+
+        switch (shaderType)
+        {
+            case GL_VERTEX_SHADER:
+            {
+                block.vertexStaticUse = interfaceBlock.staticUse;
+                break;
+            }
+            case GL_FRAGMENT_SHADER:
+            {
+                block.fragmentStaticUse = interfaceBlock.staticUse;
+                break;
+            }
+            case GL_COMPUTE_SHADER:
+            {
+                block.computeStaticUse = interfaceBlock.staticUse;
+                break;
+            }
+            default:
+                UNREACHABLE();
+        }
+
+        block.dataSize = static_cast<unsigned int>(blockSize);
+        mState.mUniformBlocks.push_back(block);
+    }
+}
+
+template <>
+void Program::updateSamplerUniform(const VariableLocation &locationInfo,
+                                   const uint8_t *destPointer,
+                                   GLsizei clampedCount,
+                                   const GLint *v)
+{
+    // Invalidate the validation cache only if we modify the sampler data.
+    if (mState.isSamplerUniformIndex(locationInfo.index) &&
+        memcmp(destPointer, v, sizeof(GLint) * clampedCount) != 0)
+    {
+        GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
+        std::vector<GLuint> *boundTextureUnits =
+            &mState.mSamplerBindings[samplerIndex].boundTextureUnits;
+
+        std::copy(v, v + clampedCount, boundTextureUnits->begin() + locationInfo.element);
+        mCachedValidateSamplersResult.reset();
+    }
+}
+
+template <typename T>
+void Program::updateSamplerUniform(const VariableLocation &locationInfo,
+                                   const uint8_t *destPointer,
+                                   GLsizei clampedCount,
+                                   const T *v)
+{
+}
+
+template <typename T>
+GLsizei Program::setUniformInternal(GLint location, GLsizei countIn, int vectorSize, const T *v)
+{
+    const VariableLocation &locationInfo = mState.mUniformLocations[location];
+    LinkedUniform *linkedUniform         = &mState.mUniforms[locationInfo.index];
+    uint8_t *destPointer                 = linkedUniform->getDataPtrToElement(locationInfo.element);
+
+    // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
+    // element index used, as reported by GetActiveUniform, will be ignored by the GL."
+    unsigned int remainingElements = linkedUniform->elementCount() - locationInfo.element;
+    GLsizei maxElementCount =
+        static_cast<GLsizei>(remainingElements * linkedUniform->getElementComponents());
+
+    GLsizei count        = countIn;
+    GLsizei clampedCount = count * vectorSize;
+    if (clampedCount > maxElementCount)
+    {
+        clampedCount = maxElementCount;
+        count        = maxElementCount / vectorSize;
+    }
+
+    if (VariableComponentType(linkedUniform->type) == GL_BOOL)
+    {
+        // Do a cast conversion for boolean types. From the spec:
+        // "The uniform is set to FALSE if the input value is 0 or 0.0f, and set to TRUE otherwise."
+        GLint *destAsInt = reinterpret_cast<GLint *>(destPointer);
+        for (GLsizei component = 0; component < clampedCount; ++component)
+        {
+            destAsInt[component] = (v[component] != static_cast<T>(0) ? GL_TRUE : GL_FALSE);
+        }
+    }
+    else
+    {
+        updateSamplerUniform(locationInfo, destPointer, clampedCount, v);
+        memcpy(destPointer, v, sizeof(T) * clampedCount);
+    }
+
+    return count;
+}
+
+template <size_t cols, size_t rows, typename T>
+GLsizei Program::setMatrixUniformInternal(GLint location,
+                                          GLsizei count,
+                                          GLboolean transpose,
+                                          const T *v)
+{
+    if (!transpose)
+    {
+        return setUniformInternal(location, count, cols * rows, v);
+    }
+
+    // Perform a transposing copy.
+    const VariableLocation &locationInfo = mState.mUniformLocations[location];
+    LinkedUniform *linkedUniform         = &mState.mUniforms[locationInfo.index];
+    T *destPtr = reinterpret_cast<T *>(linkedUniform->getDataPtrToElement(locationInfo.element));
+
+    // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
+    // element index used, as reported by GetActiveUniform, will be ignored by the GL."
+    unsigned int remainingElements = linkedUniform->elementCount() - locationInfo.element;
+    GLsizei clampedCount           = std::min(count, static_cast<GLsizei>(remainingElements));
+
+    for (GLsizei element = 0; element < clampedCount; ++element)
+    {
+        size_t elementOffset = element * rows * cols;
+
+        for (size_t row = 0; row < rows; ++row)
+        {
+            for (size_t col = 0; col < cols; ++col)
+            {
+                destPtr[col * rows + row + elementOffset] = v[row * cols + col + elementOffset];
+            }
+        }
+    }
+
+    return clampedCount;
+}
+
+template <typename DestT>
+void Program::getUniformInternal(GLint location, DestT *dataOut) const
+{
+    const VariableLocation &locationInfo = mState.mUniformLocations[location];
+    const LinkedUniform &uniform         = mState.mUniforms[locationInfo.index];
+
+    const uint8_t *srcPointer = uniform.getDataPtrToElement(locationInfo.element);
+
+    GLenum componentType = VariableComponentType(uniform.type);
+    if (componentType == GLTypeToGLenum<DestT>::value)
+    {
+        memcpy(dataOut, srcPointer, uniform.getElementSize());
+        return;
+    }
+
+    int components = VariableComponentCount(uniform.type);
+
+    switch (componentType)
+    {
+        case GL_INT:
+            UniformStateQueryCastLoop<GLint>(dataOut, srcPointer, components);
+            break;
+        case GL_UNSIGNED_INT:
+            UniformStateQueryCastLoop<GLuint>(dataOut, srcPointer, components);
+            break;
+        case GL_BOOL:
+            UniformStateQueryCastLoop<GLboolean>(dataOut, srcPointer, components);
+            break;
+        case GL_FLOAT:
+            UniformStateQueryCastLoop<GLfloat>(dataOut, srcPointer, components);
+            break;
+        default:
+            UNREACHABLE();
+    }
+}
+
+bool Program::samplesFromTexture(const gl::State &state, GLuint textureID) const
+{
+    // Must be called after samplers are validated.
+    ASSERT(mCachedValidateSamplersResult.valid() && mCachedValidateSamplersResult.value());
+
+    for (const auto &binding : mState.mSamplerBindings)
+    {
+        GLenum textureType = binding.textureType;
+        for (const auto &unit : binding.boundTextureUnits)
+        {
+            GLenum programTextureID = state.getSamplerTextureId(unit, textureType);
+            if (programTextureID == textureID)
+            {
+                // TODO(jmadill): Check for appropriate overlap.
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/Program.h b/src/third_party/angle/src/libANGLE/Program.h
new file mode 100644
index 0000000..1a74596
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Program.h
@@ -0,0 +1,575 @@
+//
+// 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.
+//
+
+// Program.h: Defines the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#ifndef LIBANGLE_PROGRAM_H_
+#define LIBANGLE_PROGRAM_H_
+
+#include <GLES2/gl2.h>
+#include <GLSLANG/ShaderVars.h>
+
+#include <array>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "common/Optional.h"
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class GLImplFactory;
+class ProgramImpl;
+struct TranslatedAttribute;
+}
+
+namespace gl
+{
+struct Caps;
+class Context;
+class ContextState;
+class Shader;
+class ShaderProgramManager;
+class State;
+class InfoLog;
+class Buffer;
+class Framebuffer;
+struct UniformBlock;
+struct LinkedUniform;
+struct PackedVarying;
+
+extern const char * const g_fakepath;
+
+class InfoLog : angle::NonCopyable
+{
+  public:
+    InfoLog();
+    ~InfoLog();
+
+    size_t getLength() const;
+    void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+
+    void appendSanitized(const char *message);
+    void reset();
+
+    // This helper class ensures we append a newline after writing a line.
+    class StreamHelper : angle::NonCopyable
+    {
+      public:
+        StreamHelper(StreamHelper &&rhs)
+            : mStream(rhs.mStream)
+        {
+            rhs.mStream = nullptr;
+        }
+
+        StreamHelper &operator=(StreamHelper &&rhs)
+        {
+            std::swap(mStream, rhs.mStream);
+            return *this;
+        }
+
+        ~StreamHelper()
+        {
+            // Write newline when destroyed on the stack
+            if (mStream)
+            {
+                (*mStream) << std::endl;
+            }
+        }
+
+        template <typename T>
+        StreamHelper &operator<<(const T &value)
+        {
+            (*mStream) << value;
+            return *this;
+        }
+
+      private:
+        friend class InfoLog;
+
+        StreamHelper(std::stringstream *stream)
+            : mStream(stream)
+        {
+            ASSERT(stream);
+        }
+
+        std::stringstream *mStream;
+    };
+
+    template <typename T>
+    StreamHelper operator<<(const T &value)
+    {
+        StreamHelper helper(&mStream);
+        helper << value;
+        return helper;
+    }
+
+    std::string str() const { return mStream.str(); }
+
+  private:
+    std::stringstream mStream;
+};
+
+// Struct used for correlating uniforms/elements of uniform arrays to handles
+struct VariableLocation
+{
+    VariableLocation();
+    VariableLocation(const std::string &name, unsigned int element, unsigned int index);
+
+    std::string name;
+    unsigned int element;
+    unsigned int index;
+
+    // If this is a valid uniform location
+    bool used;
+
+    // If this location was bound to an unreferenced uniform.  Setting data on this uniform is a
+    // no-op.
+    bool ignored;
+};
+
+// Information about a variable binding.
+// Currently used by CHROMIUM_path_rendering
+struct BindingInfo
+{
+    // The type of binding, for example GL_FLOAT_VEC3.
+    // This can be GL_NONE if the variable is optimized away.
+    GLenum type;
+
+    // This is the name of the variable in
+    // the translated shader program. Note that
+    // this can be empty in the case where the
+    // variable has been optimized away.
+    std::string name;
+
+    // True if the binding is valid, otherwise false.
+    bool valid;
+};
+
+// This small structure encapsulates binding sampler uniforms to active GL textures.
+struct SamplerBinding
+{
+    SamplerBinding(GLenum textureTypeIn, size_t elementCount)
+        : textureType(textureTypeIn), boundTextureUnits(elementCount, 0)
+    {
+    }
+
+    // Necessary for retrieving active textures from the GL state.
+    GLenum textureType;
+
+    // List of all textures bound to this sampler, of type textureType.
+    std::vector<GLuint> boundTextureUnits;
+};
+
+// A varying with tranform feedback enabled. If it's an array, either the whole array or one of its
+// elements specified by 'arrayIndex' can set to be enabled.
+struct TransformFeedbackVarying : public sh::Varying
+{
+    TransformFeedbackVarying(const sh::Varying &varyingIn, GLuint index)
+        : sh::Varying(varyingIn), arrayIndex(index)
+    {
+    }
+    std::string nameWithArrayIndex() const
+    {
+        std::stringstream fullNameStr;
+        fullNameStr << name;
+        if (arrayIndex != GL_INVALID_INDEX)
+        {
+            fullNameStr << "[" << arrayIndex << "]";
+        }
+        return fullNameStr.str();
+    }
+    GLsizei size() const { return (arrayIndex == GL_INVALID_INDEX ? elementCount() : 1); }
+
+    GLuint arrayIndex;
+};
+
+class ProgramState final : angle::NonCopyable
+{
+  public:
+    ProgramState();
+    ~ProgramState();
+
+    const std::string &getLabel();
+
+    const Shader *getAttachedVertexShader() const { return mAttachedVertexShader; }
+    const Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; }
+    const Shader *getAttachedComputeShader() const { return mAttachedComputeShader; }
+    const std::vector<std::string> &getTransformFeedbackVaryingNames() const
+    {
+        return mTransformFeedbackVaryingNames;
+    }
+    GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
+    GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
+    {
+        ASSERT(uniformBlockIndex < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
+        return mUniformBlockBindings[uniformBlockIndex];
+    }
+    const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
+    {
+        return mActiveUniformBlockBindings;
+    }
+    const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; }
+    const AttributesMask &getActiveAttribLocationsMask() const
+    {
+        return mActiveAttribLocationsMask;
+    }
+    const std::map<int, VariableLocation> &getOutputLocations() const { return mOutputLocations; }
+    const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
+    const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
+    const std::vector<UniformBlock> &getUniformBlocks() const { return mUniformBlocks; }
+    const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
+
+    GLint getUniformLocation(const std::string &name) const;
+    GLuint getUniformIndexFromName(const std::string &name) const;
+    GLuint getUniformIndexFromLocation(GLint location) const;
+    Optional<GLuint> getSamplerIndex(GLint location) const;
+    bool isSamplerUniformIndex(GLuint index) const;
+    GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
+
+  private:
+    friend class Program;
+
+    std::string mLabel;
+
+    sh::WorkGroupSize mComputeShaderLocalSize;
+
+    Shader *mAttachedFragmentShader;
+    Shader *mAttachedVertexShader;
+    Shader *mAttachedComputeShader;
+
+    std::vector<std::string> mTransformFeedbackVaryingNames;
+    std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
+    GLenum mTransformFeedbackBufferMode;
+
+    std::array<GLuint, IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS> mUniformBlockBindings;
+    UniformBlockBindingMask mActiveUniformBlockBindings;
+
+    std::vector<sh::Attribute> mAttributes;
+    angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
+
+    // Uniforms are sorted in order:
+    //  1. Non-sampler uniforms
+    //  2. Sampler uniforms
+    //  3. Uniform block uniforms
+    // This makes sampler validation easier, since we don't need a separate list.
+    std::vector<LinkedUniform> mUniforms;
+    std::vector<VariableLocation> mUniformLocations;
+    std::vector<UniformBlock> mUniformBlocks;
+    RangeUI mSamplerUniformRange;
+
+    // An array of the samplers that are used by the program
+    std::vector<gl::SamplerBinding> mSamplerBindings;
+
+    std::vector<sh::OutputVariable> mOutputVariables;
+    // TODO(jmadill): use unordered/hash map when available
+    std::map<int, VariableLocation> mOutputLocations;
+
+    bool mBinaryRetrieveableHint;
+    bool mSeparable;
+};
+
+class Program final : angle::NonCopyable, public LabeledObject
+{
+  public:
+    Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle);
+    ~Program();
+    void destroy(const Context *context);
+
+    GLuint id() const { return mHandle; }
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    rx::ProgramImpl *getImplementation() const { return mProgram; }
+
+    void attachShader(Shader *shader);
+    void detachShader(const Context *context, Shader *shader);
+    int getAttachedShadersCount() const;
+
+    const Shader *getAttachedVertexShader() const { return mState.mAttachedVertexShader; }
+    const Shader *getAttachedFragmentShader() const { return mState.mAttachedFragmentShader; }
+    const Shader *getAttachedComputeShader() const { return mState.mAttachedComputeShader; }
+
+    void bindAttributeLocation(GLuint index, const char *name);
+    void bindUniformLocation(GLuint index, const char *name);
+
+    // CHROMIUM_path_rendering
+    BindingInfo getFragmentInputBindingInfo(GLint index) const;
+    void bindFragmentInputLocation(GLint index, const char *name);
+    void pathFragmentInputGen(GLint index,
+                              GLenum genMode,
+                              GLint components,
+                              const GLfloat *coeffs);
+
+    Error link(const gl::Context *context);
+    bool isLinked() const;
+
+    Error loadBinary(const Context *context,
+                     GLenum binaryFormat,
+                     const void *binary,
+                     GLsizei length);
+    Error saveBinary(const Context *context,
+                     GLenum *binaryFormat,
+                     void *binary,
+                     GLsizei bufSize,
+                     GLsizei *length) const;
+    GLint getBinaryLength() const;
+    void setBinaryRetrievableHint(bool retrievable);
+    bool getBinaryRetrievableHint() const;
+
+    void setSeparable(bool separable);
+    bool isSeparable() const;
+
+    int getInfoLogLength() const;
+    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+    void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const;
+
+    GLuint getAttributeLocation(const std::string &name) const;
+    bool isAttribLocationActive(size_t attribLocation) const;
+
+    void getActiveAttribute(GLuint index,
+                            GLsizei bufsize,
+                            GLsizei *length,
+                            GLint *size,
+                            GLenum *type,
+                            GLchar *name) const;
+    GLint getActiveAttributeCount() const;
+    GLint getActiveAttributeMaxLength() const;
+    const std::vector<sh::Attribute> &getAttributes() const { return mState.mAttributes; }
+
+    GLint getFragDataLocation(const std::string &name) const;
+    size_t getOutputResourceCount() const;
+
+    void getActiveUniform(GLuint index,
+                          GLsizei bufsize,
+                          GLsizei *length,
+                          GLint *size,
+                          GLenum *type,
+                          GLchar *name) const;
+    GLint getActiveUniformCount() const;
+    GLint getActiveUniformMaxLength() const;
+    GLint getActiveUniformi(GLuint index, GLenum pname) const;
+    bool isValidUniformLocation(GLint location) const;
+    const LinkedUniform &getUniformByLocation(GLint location) const;
+    const VariableLocation &getUniformLocation(GLint location) const;
+    const std::vector<VariableLocation> &getUniformLocations() const;
+    const LinkedUniform &getUniformByIndex(GLuint index) const;
+
+    GLint getUniformLocation(const std::string &name) const;
+    GLuint getUniformIndex(const std::string &name) const;
+    void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform1iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform2iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform3iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform4iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+
+    void getUniformfv(GLint location, GLfloat *params) const;
+    void getUniformiv(GLint location, GLint *params) const;
+    void getUniformuiv(GLint location, GLuint *params) const;
+
+    void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
+    GLuint getActiveUniformBlockCount() const;
+    GLint getActiveUniformBlockMaxLength() const;
+
+    GLuint getUniformBlockIndex(const std::string &name) const;
+
+    void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+    GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
+
+    const UniformBlock &getUniformBlockByIndex(GLuint index) const;
+
+    void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
+    void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
+    GLsizei getTransformFeedbackVaryingCount() const;
+    GLsizei getTransformFeedbackVaryingMaxLength() const;
+    GLenum getTransformFeedbackBufferMode() const;
+
+    static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
+
+    void addRef();
+    void release(const Context *context);
+    unsigned int getRefCount() const;
+    void flagForDeletion();
+    bool isFlaggedForDeletion() const;
+
+    void validate(const Caps &caps);
+    bool validateSamplers(InfoLog *infoLog, const Caps &caps);
+    bool isValidated() const;
+    bool samplesFromTexture(const gl::State &state, GLuint textureID) const;
+
+    const AttributesMask &getActiveAttribLocationsMask() const
+    {
+        return mState.mActiveAttribLocationsMask;
+    }
+
+    const std::vector<SamplerBinding> &getSamplerBindings() const
+    {
+        return mState.mSamplerBindings;
+    }
+    const ProgramState &getState() const { return mState; }
+
+    static bool linkValidateVariablesBase(InfoLog &infoLog,
+                                          const std::string &variableName,
+                                          const sh::ShaderVariable &vertexVariable,
+                                          const sh::ShaderVariable &fragmentVariable,
+                                          bool validatePrecision);
+
+    GLuint getInputResourceIndex(const GLchar *name) const;
+    GLuint getOutputResourceIndex(const GLchar *name) const;
+    void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+    void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+
+    class Bindings final : angle::NonCopyable
+    {
+      public:
+        void bindLocation(GLuint index, const std::string &name);
+        int getBinding(const std::string &name) const;
+
+        typedef std::unordered_map<std::string, GLuint>::const_iterator const_iterator;
+        const_iterator begin() const;
+        const_iterator end() const;
+
+      private:
+        std::unordered_map<std::string, GLuint> mBindings;
+    };
+
+  private:
+    struct VaryingRef
+    {
+        const sh::Varying *get() const { return vertex ? vertex : fragment; }
+
+        const sh::Varying *vertex   = nullptr;
+        const sh::Varying *fragment = nullptr;
+    };
+
+    using MergedVaryings = std::map<std::string, VaryingRef>;
+
+    void unlink();
+    void resetUniformBlockBindings();
+
+    bool linkAttributes(const ContextState &data, InfoLog &infoLog);
+    bool validateUniformBlocksCount(GLuint maxUniformBlocks,
+                                    const std::vector<sh::InterfaceBlock> &block,
+                                    const std::string &errorMessage,
+                                    InfoLog &infoLog) const;
+    bool validateVertexAndFragmentInterfaceBlocks(
+        const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
+        const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
+        InfoLog &infoLog) const;
+    bool linkUniformBlocks(InfoLog &infoLog, const Caps &caps);
+    bool linkVaryings(InfoLog &infoLog) const;
+
+    bool linkUniforms(InfoLog &infoLog, const Caps &caps, const Bindings &uniformLocationBindings);
+    void linkSamplerBindings();
+
+    bool areMatchingInterfaceBlocks(InfoLog &infoLog,
+                                    const sh::InterfaceBlock &vertexInterfaceBlock,
+                                    const sh::InterfaceBlock &fragmentInterfaceBlock) const;
+
+    static bool linkValidateVaryings(InfoLog &infoLog,
+                                     const std::string &varyingName,
+                                     const sh::Varying &vertexVarying,
+                                     const sh::Varying &fragmentVarying,
+                                     int shaderVersion);
+    bool linkValidateBuiltInVaryings(InfoLog &infoLog) const;
+    bool linkValidateTransformFeedback(const gl::Context *context,
+                                       InfoLog &infoLog,
+                                       const MergedVaryings &linkedVaryings,
+                                       const Caps &caps) const;
+
+    void gatherTransformFeedbackVaryings(const MergedVaryings &varyings);
+
+    MergedVaryings getMergedVaryings() const;
+    std::vector<PackedVarying> getPackedVaryings(const MergedVaryings &mergedVaryings) const;
+    void linkOutputVariables();
+
+    void setUniformValuesFromBindingQualifiers();
+
+    void gatherInterfaceBlockInfo();
+    template <typename VarT>
+    void defineUniformBlockMembers(const std::vector<VarT> &fields,
+                                   const std::string &prefix,
+                                   int blockIndex);
+
+    void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
+
+    // Both these function update the cached uniform values and return a modified "count"
+    // so that the uniform update doesn't overflow the uniform.
+    template <typename T>
+    GLsizei setUniformInternal(GLint location, GLsizei count, int vectorSize, const T *v);
+    template <size_t cols, size_t rows, typename T>
+    GLsizei setMatrixUniformInternal(GLint location,
+                                     GLsizei count,
+                                     GLboolean transpose,
+                                     const T *v);
+    template <typename T>
+    void updateSamplerUniform(const VariableLocation &locationInfo,
+                              const uint8_t *destPointer,
+                              GLsizei clampedCount,
+                              const T *v);
+
+    template <typename DestT>
+    void getUniformInternal(GLint location, DestT *dataOut) const;
+
+    ProgramState mState;
+    rx::ProgramImpl *mProgram;
+
+    bool mValidated;
+
+    Bindings mAttributeBindings;
+
+    // Note that this has nothing to do with binding layout qualifiers that can be set for some
+    // uniforms in GLES3.1+. It is used to pre-set the location of uniforms.
+    Bindings mUniformLocationBindings;
+
+    // CHROMIUM_path_rendering
+    Bindings mFragmentInputBindings;
+
+    bool mLinked;
+    bool mDeleteStatus;   // Flag to indicate that the program can be deleted when no longer in use
+
+    unsigned int mRefCount;
+
+    ShaderProgramManager *mResourceManager;
+    const GLuint mHandle;
+
+    InfoLog mInfoLog;
+
+    // Cache for sampler validation
+    Optional<bool> mCachedValidateSamplersResult;
+    std::vector<GLenum> mTextureUnitTypesCache;
+};
+}  // namespace gl
+
+#endif   // LIBANGLE_PROGRAM_H_
diff --git a/src/third_party/angle/src/libANGLE/Program_unittest.cpp b/src/third_party/angle/src/libANGLE/Program_unittest.cpp
new file mode 100644
index 0000000..6d99f00
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Program_unittest.cpp
@@ -0,0 +1,42 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Unit tests for Program and related classes.
+//
+
+#include <gtest/gtest.h>
+
+#include "libANGLE/Program.h"
+
+using namespace gl;
+
+namespace
+{
+
+// Tests that the log length properly counts the terminating \0.
+TEST(InfoLogTest, LogLengthCountsTerminator)
+{
+    InfoLog infoLog;
+    EXPECT_EQ(0u, infoLog.getLength());
+    infoLog << " ";
+
+    // " \n\0" = 3 characters
+    EXPECT_EQ(3u, infoLog.getLength());
+}
+
+// Tests that newlines get appended to the info log properly.
+TEST(InfoLogTest, AppendingNewline)
+{
+    InfoLog infoLog;
+
+    infoLog << "First" << 1 << 'x';
+    infoLog << "Second" << 2 << 'y';
+
+    std::string expected = "First1x\nSecond2y\n";
+
+    EXPECT_EQ(expected, infoLog.str());
+}
+
+} // namespace
diff --git a/src/third_party/angle/src/libANGLE/Query.cpp b/src/third_party/angle/src/libANGLE/Query.cpp
new file mode 100644
index 0000000..cd1fb5f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Query.cpp
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query.cpp: Implements the gl::Query class
+
+#include "libANGLE/Query.h"
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace gl
+{
+Query::Query(rx::QueryImpl *impl, GLuint id) : RefCountObject(id), mQuery(impl), mLabel()
+{
+}
+
+Query::~Query()
+{
+    SafeDelete(mQuery);
+}
+
+void Query::setLabel(const std::string &label)
+{
+    mLabel = label;
+}
+
+const std::string &Query::getLabel() const
+{
+    return mLabel;
+}
+
+Error Query::begin()
+{
+    return mQuery->begin();
+}
+
+Error Query::end()
+{
+    return mQuery->end();
+}
+
+Error Query::queryCounter()
+{
+    return mQuery->queryCounter();
+}
+
+Error Query::getResult(GLint *params)
+{
+    return mQuery->getResult(params);
+}
+
+Error Query::getResult(GLuint *params)
+{
+    return mQuery->getResult(params);
+}
+
+Error Query::getResult(GLint64 *params)
+{
+    return mQuery->getResult(params);
+}
+
+Error Query::getResult(GLuint64 *params)
+{
+    return mQuery->getResult(params);
+}
+
+Error Query::isResultAvailable(bool *available)
+{
+    return mQuery->isResultAvailable(available);
+}
+
+GLenum Query::getType() const
+{
+    return mQuery->getType();
+}
+
+rx::QueryImpl *Query::getImplementation()
+{
+    return mQuery;
+}
+
+const rx::QueryImpl *Query::getImplementation() const
+{
+    return mQuery;
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/Query.h b/src/third_party/angle/src/libANGLE/Query.h
new file mode 100644
index 0000000..5486f98
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Query.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query.h: Defines the gl::Query class
+
+#ifndef LIBANGLE_QUERY_H_
+#define LIBANGLE_QUERY_H_
+
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+class QueryImpl;
+}
+
+namespace gl
+{
+
+class Query final : public RefCountObject, public LabeledObject
+{
+  public:
+    Query(rx::QueryImpl *impl, GLuint id);
+    virtual ~Query();
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    Error begin();
+    Error end();
+    Error queryCounter();
+    Error getResult(GLint *params);
+    Error getResult(GLuint *params);
+    Error getResult(GLint64 *params);
+    Error getResult(GLuint64 *params);
+    Error isResultAvailable(bool *available);
+
+    GLenum getType() const;
+
+    rx::QueryImpl *getImplementation();
+    const rx::QueryImpl *getImplementation() const;
+
+  private:
+    rx::QueryImpl *mQuery;
+
+    std::string mLabel;
+};
+
+}
+
+#endif   // LIBANGLE_QUERY_H_
diff --git a/src/third_party/angle/src/libANGLE/RefCountObject.h b/src/third_party/angle/src/libANGLE/RefCountObject.h
new file mode 100644
index 0000000..112312e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/RefCountObject.h
@@ -0,0 +1,166 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RefCountObject.h: Defines the gl::RefCountObject base class that provides
+// lifecycle support for GL objects using the traditional BindObject scheme, but
+// that need to be reference counted for correct cross-context deletion.
+// (Concretely, textures, buffers and renderbuffers.)
+
+#ifndef LIBANGLE_REFCOUNTOBJECT_H_
+#define LIBANGLE_REFCOUNTOBJECT_H_
+
+#include "common/debug.h"
+
+#include "angle_gl.h"
+
+#include <cstddef>
+
+namespace gl
+{
+class Context;
+}
+
+class RefCountObjectNoID : angle::NonCopyable
+{
+  public:
+    RefCountObjectNoID() : mRefCount(0) {}
+
+    void addRef() const { ++mRefCount; }
+
+    void release() const
+    {
+        ASSERT(mRefCount > 0);
+
+        if (--mRefCount == 0)
+        {
+            delete this;
+        }
+    }
+
+    // A specialized release method for objects which need a destroy context.
+    void release(const gl::Context *context)
+    {
+        ASSERT(mRefCount > 0);
+        if (--mRefCount == 0)
+        {
+            destroy(context);
+            delete this;
+        }
+    }
+
+    size_t getRefCount() const { return mRefCount; }
+
+  protected:
+    virtual ~RefCountObjectNoID() { ASSERT(mRefCount == 0); }
+    virtual void destroy(const gl::Context *context) {}
+
+  private:
+    mutable std::size_t mRefCount;
+};
+
+class RefCountObject : public RefCountObjectNoID
+{
+  public:
+    explicit RefCountObject(GLuint id) : mId(id) {}
+
+    GLuint id() const { return mId; }
+
+  protected:
+    ~RefCountObject() override {}
+
+  private:
+    GLuint mId;
+};
+
+template <class ObjectType>
+class BindingPointer
+{
+  public:
+    BindingPointer()
+        : mObject(nullptr)
+    {
+    }
+
+    BindingPointer(const BindingPointer<ObjectType> &other)
+        : mObject(nullptr)
+    {
+        set(other.mObject);
+    }
+
+    void operator=(const BindingPointer<ObjectType> &other)
+    {
+        set(other.mObject);
+    }
+
+    virtual ~BindingPointer()
+    {
+        // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up.
+        ASSERT(mObject == nullptr);
+    }
+
+    virtual void set(ObjectType *newObject)
+    {
+        // addRef first in case newObject == mObject and this is the last reference to it.
+        if (newObject != nullptr) reinterpret_cast<const RefCountObject*>(newObject)->addRef();
+        if (mObject != nullptr) reinterpret_cast<const RefCountObject*>(mObject)->release();
+        mObject = newObject;
+    }
+
+    ObjectType *get() const { return mObject; }
+    ObjectType *operator->() const { return mObject; }
+
+    GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; }
+
+    bool operator==(const BindingPointer<ObjectType> &other) const
+    {
+        return mObject == other.mObject;
+    }
+
+    bool operator!=(const BindingPointer<ObjectType> &other) const { return !(*this == other); }
+
+  private:
+    ObjectType *mObject;
+};
+
+template <class ObjectType>
+class OffsetBindingPointer : public BindingPointer<ObjectType>
+{
+  public:
+    OffsetBindingPointer() : mOffset(0), mSize(0) { }
+
+    void set(ObjectType *newObject) override
+    {
+        BindingPointer<ObjectType>::set(newObject);
+        mOffset = 0;
+        mSize = 0;
+    }
+
+    void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
+    {
+        BindingPointer<ObjectType>::set(newObject);
+        mOffset = offset;
+        mSize = size;
+    }
+
+    GLintptr getOffset() const { return mOffset; }
+    GLsizeiptr getSize() const { return mSize; }
+
+    bool operator==(const OffsetBindingPointer<ObjectType> &other) const
+    {
+        return this->get() == other.get() && mOffset == other.mOffset && mSize == other.mSize;
+    }
+
+    bool operator!=(const OffsetBindingPointer<ObjectType> &other) const
+    {
+        return !(*this == other);
+    }
+
+  private:
+    GLintptr mOffset;
+    GLsizeiptr mSize;
+};
+
+#endif   // LIBANGLE_REFCOUNTOBJECT_H_
diff --git a/src/third_party/angle/src/libANGLE/Renderbuffer.cpp b/src/third_party/angle/src/libANGLE/Renderbuffer.cpp
new file mode 100644
index 0000000..68b011d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Renderbuffer.cpp
@@ -0,0 +1,173 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class,
+// GL renderbuffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#include "libANGLE/Renderbuffer.h"
+
+#include "common/utilities.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace gl
+{
+Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id)
+    : egl::ImageSibling(id),
+      mRenderbuffer(impl),
+      mLabel(),
+      mWidth(0),
+      mHeight(0),
+      mFormat(GL_RGBA4),
+      mSamples(0)
+{
+}
+
+Renderbuffer::~Renderbuffer()
+{
+    SafeDelete(mRenderbuffer);
+}
+
+void Renderbuffer::setLabel(const std::string &label)
+{
+    mLabel = label;
+}
+
+const std::string &Renderbuffer::getLabel() const
+{
+    return mLabel;
+}
+
+Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+    orphanImages();
+
+    ANGLE_TRY(mRenderbuffer->setStorage(internalformat, width, height));
+
+    mWidth          = static_cast<GLsizei>(width);
+    mHeight         = static_cast<GLsizei>(height);
+    mFormat         = Format(internalformat);
+    mSamples = 0;
+
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+Error Renderbuffer::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
+{
+    orphanImages();
+
+    ANGLE_TRY(mRenderbuffer->setStorageMultisample(samples, internalformat, width, height));
+
+    mWidth          = static_cast<GLsizei>(width);
+    mHeight         = static_cast<GLsizei>(height);
+    mFormat         = Format(internalformat);
+    mSamples        = static_cast<GLsizei>(samples);
+
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+Error Renderbuffer::setStorageEGLImageTarget(egl::Image *image)
+{
+    orphanImages();
+
+    ANGLE_TRY(mRenderbuffer->setStorageEGLImageTarget(image));
+
+    setTargetImage(image);
+
+    mWidth          = static_cast<GLsizei>(image->getWidth());
+    mHeight         = static_cast<GLsizei>(image->getHeight());
+    mFormat         = Format(image->getFormat());
+    mSamples        = 0;
+
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+rx::RenderbufferImpl *Renderbuffer::getImplementation() const
+{
+    ASSERT(mRenderbuffer);
+    return mRenderbuffer;
+}
+
+GLsizei Renderbuffer::getWidth() const
+{
+    return mWidth;
+}
+
+GLsizei Renderbuffer::getHeight() const
+{
+    return mHeight;
+}
+
+const Format &Renderbuffer::getFormat() const
+{
+    return mFormat;
+}
+
+GLsizei Renderbuffer::getSamples() const
+{
+    return mSamples;
+}
+
+GLuint Renderbuffer::getRedSize() const
+{
+    return mFormat.info->redBits;
+}
+
+GLuint Renderbuffer::getGreenSize() const
+{
+    return mFormat.info->greenBits;
+}
+
+GLuint Renderbuffer::getBlueSize() const
+{
+    return mFormat.info->blueBits;
+}
+
+GLuint Renderbuffer::getAlphaSize() const
+{
+    return mFormat.info->alphaBits;
+}
+
+GLuint Renderbuffer::getDepthSize() const
+{
+    return mFormat.info->depthBits;
+}
+
+GLuint Renderbuffer::getStencilSize() const
+{
+    return mFormat.info->stencilBits;
+}
+
+void Renderbuffer::onAttach()
+{
+    addRef();
+}
+
+void Renderbuffer::onDetach()
+{
+    release();
+}
+
+GLuint Renderbuffer::getId() const
+{
+    return id();
+}
+
+Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
+{
+    return Extents(mWidth, mHeight, 1);
+}
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/Renderbuffer.h b/src/third_party/angle/src/libANGLE/Renderbuffer.h
new file mode 100644
index 0000000..da17125
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Renderbuffer.h
@@ -0,0 +1,90 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderbuffer.h: Defines the renderer-agnostic container class gl::Renderbuffer.
+// Implements GL renderbuffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#ifndef LIBANGLE_RENDERBUFFER_H_
+#define LIBANGLE_RENDERBUFFER_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace gl
+{
+// A GL renderbuffer object is usually used as a depth or stencil buffer attachment
+// for a framebuffer object. The renderbuffer itself is a distinct GL object, see
+// FramebufferAttachment and Framebuffer for how they are applied to an FBO via an
+// attachment point.
+
+class Renderbuffer final : public egl::ImageSibling,
+                           public LabeledObject
+{
+  public:
+    Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
+    virtual ~Renderbuffer();
+
+    void destroy(const Context *context) override {}
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    Error setStorage(GLenum internalformat, size_t width, size_t height);
+    Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height);
+    Error setStorageEGLImageTarget(egl::Image *imageTarget);
+
+    rx::RenderbufferImpl *getImplementation() const;
+
+    GLsizei getWidth() const;
+    GLsizei getHeight() const;
+    const Format &getFormat() const;
+    GLsizei getSamples() const;
+    GLuint getRedSize() const;
+    GLuint getGreenSize() const;
+    GLuint getBlueSize() const;
+    GLuint getAlphaSize() const;
+    GLuint getDepthSize() const;
+    GLuint getStencilSize() const;
+
+    // FramebufferAttachmentObject Impl
+    Extents getAttachmentSize(const ImageIndex &imageIndex) const override;
+    const Format &getAttachmentFormat(GLenum /*binding*/,
+                                      const ImageIndex & /*imageIndex*/) const override
+    {
+        return getFormat();
+    }
+    GLsizei getAttachmentSamples(const ImageIndex & /*imageIndex*/) const override
+    {
+        return getSamples();
+    }
+
+    void onAttach() override;
+    void onDetach() override;
+    GLuint getId() const override;
+
+  private:
+    rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mRenderbuffer; }
+
+    rx::RenderbufferImpl *mRenderbuffer;
+
+    std::string mLabel;
+
+    GLsizei mWidth;
+    GLsizei mHeight;
+    Format mFormat;
+    GLsizei mSamples;
+};
+
+}
+
+#endif   // LIBANGLE_RENDERBUFFER_H_
diff --git a/src/third_party/angle/src/libANGLE/ResourceManager.cpp b/src/third_party/angle/src/libANGLE/ResourceManager.cpp
new file mode 100644
index 0000000..f51bed2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/ResourceManager.cpp
@@ -0,0 +1,522 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+
+// ResourceManager.cpp: Implements the the ResourceManager classes, which handle allocation and
+// lifetime of GL objects.
+
+#include "libANGLE/ResourceManager.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Path.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+
+namespace
+{
+
+template <typename ResourceType>
+GLuint AllocateEmptyObject(HandleAllocator *handleAllocator, ResourceMap<ResourceType> *objectMap)
+{
+    GLuint handle        = handleAllocator->allocate();
+    (*objectMap)[handle] = nullptr;
+    return handle;
+}
+
+template <typename ResourceType>
+ResourceType *GetObject(const ResourceMap<ResourceType> &objectMap, GLuint handle)
+{
+    auto iter = objectMap.find(handle);
+    return iter != objectMap.end() ? iter->second : nullptr;
+}
+
+}  // anonymous namespace
+
+template <typename HandleAllocatorType>
+ResourceManagerBase<HandleAllocatorType>::ResourceManagerBase() : mRefCount(1)
+{
+}
+
+template <typename HandleAllocatorType>
+void ResourceManagerBase<HandleAllocatorType>::addRef()
+{
+    mRefCount++;
+}
+
+template <typename HandleAllocatorType>
+void ResourceManagerBase<HandleAllocatorType>::release(const Context *context)
+{
+    if (--mRefCount == 0)
+    {
+        reset(context);
+        delete this;
+    }
+}
+
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::~TypedResourceManager()
+{
+    ASSERT(mObjectMap.empty());
+}
+
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::reset(const Context *context)
+{
+    while (!mObjectMap.empty())
+    {
+        deleteObject(context, mObjectMap.begin()->first);
+    }
+    mObjectMap.clear();
+}
+
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::deleteObject(
+    const Context *context,
+    GLuint handle)
+{
+    auto objectIter = mObjectMap.find(handle);
+    if (objectIter == mObjectMap.end())
+    {
+        return;
+    }
+
+    if (objectIter->second != nullptr)
+    {
+        objectIter->second->destroy(context);
+        ImplT::DeleteObject(objectIter->second);
+    }
+
+    // Requires an explicit this-> because of C++ template rules.
+    this->mHandleAllocator.release(objectIter->first);
+    mObjectMap.erase(objectIter);
+}
+
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+template <typename... ArgTypes>
+ResourceType *TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::allocateObject(
+    typename ResourceMap<ResourceType>::iterator &objectMapIter,
+    rx::GLImplFactory *factory,
+    GLuint handle,
+    ArgTypes... args)
+{
+    ResourceType *object = ImplT::AllocateNewObject(factory, handle, args...);
+
+    if (objectMapIter != mObjectMap.end())
+    {
+        objectMapIter->second = object;
+    }
+    else
+    {
+        this->mHandleAllocator.reserve(handle);
+        mObjectMap[handle] = object;
+    }
+
+    return object;
+}
+
+template class ResourceManagerBase<HandleAllocator>;
+template class ResourceManagerBase<HandleRangeAllocator>;
+template class TypedResourceManager<Buffer, HandleAllocator, BufferManager>;
+template Buffer *TypedResourceManager<Buffer, HandleAllocator, BufferManager>::allocateObject(
+    ResourceMap<Buffer>::iterator &,
+    rx::GLImplFactory *,
+    GLuint);
+template class TypedResourceManager<Texture, HandleAllocator, TextureManager>;
+template Texture *TypedResourceManager<Texture, HandleAllocator, TextureManager>::allocateObject(
+    ResourceMap<Texture>::iterator &,
+    rx::GLImplFactory *,
+    GLuint,
+    GLenum);
+template class TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>;
+template Renderbuffer *
+TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>::allocateObject(
+    ResourceMap<Renderbuffer>::iterator &,
+    rx::GLImplFactory *,
+    GLuint);
+template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager>;
+template Sampler *TypedResourceManager<Sampler, HandleAllocator, SamplerManager>::allocateObject(
+    ResourceMap<Sampler>::iterator &,
+    rx::GLImplFactory *,
+    GLuint);
+template class TypedResourceManager<FenceSync, HandleAllocator, FenceSyncManager>;
+template class TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>;
+template Framebuffer *
+TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>::allocateObject(
+    ResourceMap<Framebuffer>::iterator &,
+    rx::GLImplFactory *,
+    GLuint,
+    const Caps &);
+
+// BufferManager Implementation.
+
+// static
+Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
+{
+    Buffer *buffer = new Buffer(factory, handle);
+    buffer->addRef();
+    return buffer;
+}
+
+// static
+void BufferManager::DeleteObject(Buffer *buffer)
+{
+    buffer->release();
+}
+
+GLuint BufferManager::createBuffer()
+{
+    return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Buffer *BufferManager::getBuffer(GLuint handle) const
+{
+    return GetObject(mObjectMap, handle);
+}
+
+bool BufferManager::isBufferGenerated(GLuint buffer) const
+{
+    return buffer == 0 || mObjectMap.find(buffer) != mObjectMap.end();
+}
+
+// ShaderProgramManager Implementation.
+
+ShaderProgramManager::~ShaderProgramManager()
+{
+    ASSERT(mPrograms.empty());
+    ASSERT(mShaders.empty());
+}
+
+void ShaderProgramManager::reset(const Context *context)
+{
+    while (!mPrograms.empty())
+    {
+        deleteProgram(context, mPrograms.begin()->first);
+    }
+    mPrograms.clear();
+    while (!mShaders.empty())
+    {
+        deleteShader(context, mShaders.begin()->first);
+    }
+    mShaders.clear();
+}
+
+GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
+                                          const gl::Limitations &rendererLimitations,
+                                          GLenum type)
+{
+    ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER);
+    GLuint handle    = mHandleAllocator.allocate();
+    mShaders[handle] = new Shader(this, factory, rendererLimitations, type, handle);
+    return handle;
+}
+
+void ShaderProgramManager::deleteShader(const Context *context, GLuint shader)
+{
+    deleteObject(context, &mShaders, shader);
+}
+
+Shader *ShaderProgramManager::getShader(GLuint handle) const
+{
+    return GetObject(mShaders, handle);
+}
+
+GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
+{
+    GLuint handle     = mHandleAllocator.allocate();
+    mPrograms[handle] = new Program(factory, this, handle);
+    return handle;
+}
+
+void ShaderProgramManager::deleteProgram(const gl::Context *context, GLuint program)
+{
+    deleteObject(context, &mPrograms, program);
+}
+
+Program *ShaderProgramManager::getProgram(GLuint handle) const
+{
+    return GetObject(mPrograms, handle);
+}
+
+template <typename ObjectType>
+void ShaderProgramManager::deleteObject(const Context *context,
+                                        ResourceMap<ObjectType> *objectMap,
+                                        GLuint id)
+{
+    auto iter = objectMap->find(id);
+    if (iter == objectMap->end())
+    {
+        return;
+    }
+
+    auto object = iter->second;
+    if (object->getRefCount() == 0)
+    {
+        mHandleAllocator.release(id);
+        object->destroy(context);
+        SafeDelete(object);
+        objectMap->erase(iter);
+    }
+    else
+    {
+        object->flagForDeletion();
+    }
+}
+
+// TextureManager Implementation.
+
+// static
+Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle, GLenum target)
+{
+    Texture *texture = new Texture(factory, handle, target);
+    texture->addRef();
+    return texture;
+}
+
+// static
+void TextureManager::DeleteObject(Texture *texture)
+{
+    texture->release();
+}
+
+GLuint TextureManager::createTexture()
+{
+    return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Texture *TextureManager::getTexture(GLuint handle) const
+{
+    ASSERT(GetObject(mObjectMap, 0) == nullptr);
+    return GetObject(mObjectMap, handle);
+}
+
+bool TextureManager::isTextureGenerated(GLuint texture) const
+{
+    return texture == 0 || mObjectMap.find(texture) != mObjectMap.end();
+}
+
+void TextureManager::invalidateTextureComplenessCache()
+{
+    for (auto &texture : mObjectMap)
+    {
+        if (texture.second)
+        {
+            texture.second->invalidateCompletenessCache();
+        }
+    }
+}
+
+// RenderbufferManager Implementation.
+
+// static
+Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
+{
+    Renderbuffer *renderbuffer = new Renderbuffer(factory->createRenderbuffer(), handle);
+    renderbuffer->addRef();
+    return renderbuffer;
+}
+
+// static
+void RenderbufferManager::DeleteObject(Renderbuffer *renderbuffer)
+{
+    renderbuffer->release();
+}
+
+GLuint RenderbufferManager::createRenderbuffer()
+{
+    return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Renderbuffer *RenderbufferManager::getRenderbuffer(GLuint handle)
+{
+    return GetObject(mObjectMap, handle);
+}
+
+bool RenderbufferManager::isRenderbufferGenerated(GLuint renderbuffer) const
+{
+    return renderbuffer == 0 || mObjectMap.find(renderbuffer) != mObjectMap.end();
+}
+
+// SamplerManager Implementation.
+
+// static
+Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
+{
+    Sampler *sampler = new Sampler(factory, handle);
+    sampler->addRef();
+    return sampler;
+}
+
+// static
+void SamplerManager::DeleteObject(Sampler *sampler)
+{
+    sampler->release();
+}
+
+GLuint SamplerManager::createSampler()
+{
+    return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Sampler *SamplerManager::getSampler(GLuint handle)
+{
+    return GetObject(mObjectMap, handle);
+}
+
+bool SamplerManager::isSampler(GLuint sampler)
+{
+    return mObjectMap.find(sampler) != mObjectMap.end();
+}
+
+// FenceSyncManager Implementation.
+
+// static
+void FenceSyncManager::DeleteObject(FenceSync *fenceSync)
+{
+    fenceSync->release();
+}
+
+GLuint FenceSyncManager::createFenceSync(rx::GLImplFactory *factory)
+{
+    GLuint handle        = mHandleAllocator.allocate();
+    FenceSync *fenceSync = new FenceSync(factory->createFenceSync(), handle);
+    fenceSync->addRef();
+    mObjectMap[handle] = fenceSync;
+    return handle;
+}
+
+FenceSync *FenceSyncManager::getFenceSync(GLuint handle)
+{
+    return GetObject(mObjectMap, handle);
+}
+
+// PathManager Implementation.
+
+ErrorOrResult<GLuint> PathManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
+{
+    // Allocate client side handles.
+    const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range));
+    if (client == HandleRangeAllocator::kInvalidHandle)
+        return Error(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.");
+
+    const auto &paths = factory->createPaths(range);
+    if (paths.empty())
+    {
+        mHandleAllocator.releaseRange(client, range);
+        return Error(GL_OUT_OF_MEMORY, "Failed to allocate path objects.");
+    }
+
+    auto hint = mPaths.begin();
+
+    for (GLsizei i = 0; i < range; ++i)
+    {
+        const auto impl = paths[static_cast<unsigned>(i)];
+        const auto id   = client + i;
+        hint            = mPaths.insert(hint, std::make_pair(id, new Path(impl)));
+    }
+    return client;
+}
+
+void PathManager::deletePaths(GLuint first, GLsizei range)
+{
+    for (GLsizei i = 0; i < range; ++i)
+    {
+        const auto id = first + i;
+        const auto it = mPaths.find(id);
+        if (it == mPaths.end())
+            continue;
+        Path *p = it->second;
+        delete p;
+        mPaths.erase(it);
+    }
+    mHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
+}
+
+Path *PathManager::getPath(GLuint handle) const
+{
+    auto iter = mPaths.find(handle);
+    return iter != mPaths.end() ? iter->second : nullptr;
+}
+
+bool PathManager::hasPath(GLuint handle) const
+{
+    return mHandleAllocator.isUsed(handle);
+}
+
+PathManager::~PathManager()
+{
+    ASSERT(mPaths.empty());
+}
+
+void PathManager::reset(const Context *context)
+{
+    for (auto path : mPaths)
+    {
+        SafeDelete(path.second);
+    }
+    mPaths.clear();
+}
+
+// FramebufferManager Implementation.
+
+// static
+Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
+                                                   GLuint handle,
+                                                   const Caps &caps)
+{
+    return new Framebuffer(caps, factory, handle);
+}
+
+// static
+void FramebufferManager::DeleteObject(Framebuffer *framebuffer)
+{
+    // Default framebuffer are owned by their respective Surface
+    if (framebuffer->id() != 0)
+    {
+        delete framebuffer;
+    }
+}
+
+GLuint FramebufferManager::createFramebuffer()
+{
+    return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const
+{
+    return GetObject(mObjectMap, handle);
+}
+
+void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
+{
+    ASSERT(framebuffer == nullptr || framebuffer->id() == 0);
+    mObjectMap[0] = framebuffer;
+}
+
+bool FramebufferManager::isFramebufferGenerated(GLuint framebuffer)
+{
+    ASSERT(mObjectMap.find(0) != mObjectMap.end());
+    return mObjectMap.find(framebuffer) != mObjectMap.end();
+}
+
+void FramebufferManager::invalidateFramebufferComplenessCache()
+{
+    for (auto &framebuffer : mObjectMap)
+    {
+        if (framebuffer.second)
+        {
+            framebuffer.second->invalidateCompletenessCache();
+        }
+    }
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/ResourceManager.h b/src/third_party/angle/src/libANGLE/ResourceManager.h
new file mode 100644
index 0000000..82d2307
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/ResourceManager.h
@@ -0,0 +1,263 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+
+// ResourceManager.h : Defines the ResourceManager classes, which handle allocation and lifetime of
+// GL objects.
+
+#ifndef LIBANGLE_RESOURCEMANAGER_H_
+#define LIBANGLE_RESOURCEMANAGER_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/HandleAllocator.h"
+#include "libANGLE/HandleRangeAllocator.h"
+
+namespace rx
+{
+class GLImplFactory;
+}
+
+namespace gl
+{
+class Buffer;
+struct Caps;
+class Context;
+class FenceSync;
+class Framebuffer;
+struct Limitations;
+class Path;
+class Program;
+class Renderbuffer;
+class Sampler;
+class Shader;
+class Texture;
+
+template <typename HandleAllocatorType>
+class ResourceManagerBase : angle::NonCopyable
+{
+  public:
+    ResourceManagerBase();
+
+    void addRef();
+    void release(const Context *context);
+
+  protected:
+    virtual void reset(const Context *context) = 0;
+    virtual ~ResourceManagerBase() {}
+
+    HandleAllocatorType mHandleAllocator;
+
+  private:
+    size_t mRefCount;
+};
+
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType>
+{
+  public:
+    TypedResourceManager() {}
+
+    void deleteObject(const Context *context, GLuint handle);
+
+  protected:
+    ~TypedResourceManager() override;
+
+    // Inlined in the header for performance.
+    template <typename... ArgTypes>
+    ResourceType *checkObjectAllocation(rx::GLImplFactory *factory, GLuint handle, ArgTypes... args)
+    {
+        auto objectMapIter = mObjectMap.find(handle);
+
+        if (objectMapIter != mObjectMap.end() && objectMapIter->second != nullptr)
+        {
+            return objectMapIter->second;
+        }
+
+        if (handle == 0)
+        {
+            return nullptr;
+        }
+
+        return allocateObject<ArgTypes...>(objectMapIter, factory, handle, args...);
+    }
+
+    template <typename... ArgTypes>
+    ResourceType *allocateObject(typename ResourceMap<ResourceType>::iterator &objectMapIter,
+                                 rx::GLImplFactory *factory,
+                                 GLuint handle,
+                                 ArgTypes... args);
+
+    void reset(const Context *context) override;
+
+    ResourceMap<ResourceType> mObjectMap;
+};
+
+class BufferManager : public TypedResourceManager<Buffer, HandleAllocator, BufferManager>
+{
+  public:
+    GLuint createBuffer();
+    Buffer *getBuffer(GLuint handle) const;
+    bool isBufferGenerated(GLuint buffer) const;
+
+    Buffer *checkBufferAllocation(rx::GLImplFactory *factory, GLuint handle)
+    {
+        return checkObjectAllocation(factory, handle);
+    }
+
+    // TODO(jmadill): Investigate design which doesn't expose these methods publicly.
+    static Buffer *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
+    static void DeleteObject(Buffer *buffer);
+
+  protected:
+    ~BufferManager() override {}
+};
+
+class ShaderProgramManager : public ResourceManagerBase<HandleAllocator>
+{
+  public:
+    GLuint createShader(rx::GLImplFactory *factory,
+                        const Limitations &rendererLimitations,
+                        GLenum type);
+    void deleteShader(const Context *context, GLuint shader);
+    Shader *getShader(GLuint handle) const;
+
+    GLuint createProgram(rx::GLImplFactory *factory);
+    void deleteProgram(const Context *context, GLuint program);
+    Program *getProgram(GLuint handle) const;
+
+  protected:
+    ~ShaderProgramManager() override;
+
+  private:
+    template <typename ObjectType>
+    void deleteObject(const Context *context, ResourceMap<ObjectType> *objectMap, GLuint id);
+
+    void reset(const Context *context) override;
+
+    ResourceMap<Shader> mShaders;
+    ResourceMap<Program> mPrograms;
+};
+
+class TextureManager : public TypedResourceManager<Texture, HandleAllocator, TextureManager>
+{
+  public:
+    GLuint createTexture();
+    Texture *getTexture(GLuint handle) const;
+    bool isTextureGenerated(GLuint texture) const;
+
+    void invalidateTextureComplenessCache();
+
+    Texture *checkTextureAllocation(rx::GLImplFactory *factory, GLuint handle, GLenum target)
+    {
+        return checkObjectAllocation(factory, handle, target);
+    }
+
+    static Texture *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle, GLenum target);
+    static void DeleteObject(Texture *texture);
+
+  protected:
+    ~TextureManager() override {}
+};
+
+class RenderbufferManager
+    : public TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>
+{
+  public:
+    GLuint createRenderbuffer();
+    Renderbuffer *getRenderbuffer(GLuint handle);
+    bool isRenderbufferGenerated(GLuint renderbuffer) const;
+
+    Renderbuffer *checkRenderbufferAllocation(rx::GLImplFactory *factory, GLuint handle)
+    {
+        return checkObjectAllocation(factory, handle);
+    }
+
+    static Renderbuffer *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
+    static void DeleteObject(Renderbuffer *renderbuffer);
+
+  protected:
+    ~RenderbufferManager() override {}
+};
+
+class SamplerManager : public TypedResourceManager<Sampler, HandleAllocator, SamplerManager>
+{
+  public:
+    GLuint createSampler();
+    Sampler *getSampler(GLuint handle);
+    bool isSampler(GLuint sampler);
+
+    Sampler *checkSamplerAllocation(rx::GLImplFactory *factory, GLuint handle)
+    {
+        return checkObjectAllocation(factory, handle);
+    }
+
+    static Sampler *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
+    static void DeleteObject(Sampler *sampler);
+
+  protected:
+    ~SamplerManager() override {}
+};
+
+class FenceSyncManager : public TypedResourceManager<FenceSync, HandleAllocator, FenceSyncManager>
+{
+  public:
+    GLuint createFenceSync(rx::GLImplFactory *factory);
+    FenceSync *getFenceSync(GLuint handle);
+
+    static void DeleteObject(FenceSync *fenceSync);
+
+  protected:
+    ~FenceSyncManager() override {}
+};
+
+class PathManager : public ResourceManagerBase<HandleRangeAllocator>
+{
+  public:
+    ErrorOrResult<GLuint> createPaths(rx::GLImplFactory *factory, GLsizei range);
+    void deletePaths(GLuint first, GLsizei range);
+    Path *getPath(GLuint handle) const;
+    bool hasPath(GLuint handle) const;
+
+  protected:
+    ~PathManager() override;
+    void reset(const Context *context) override;
+
+  private:
+    ResourceMap<Path> mPaths;
+};
+
+class FramebufferManager
+    : public TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>
+{
+  public:
+    GLuint createFramebuffer();
+    Framebuffer *getFramebuffer(GLuint handle) const;
+    void setDefaultFramebuffer(Framebuffer *framebuffer);
+    bool isFramebufferGenerated(GLuint framebuffer);
+
+    void invalidateFramebufferComplenessCache();
+
+    Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory,
+                                            const Caps &caps,
+                                            GLuint handle)
+    {
+        return checkObjectAllocation<const Caps &>(factory, handle, caps);
+    }
+
+    static Framebuffer *AllocateNewObject(rx::GLImplFactory *factory,
+                                          GLuint handle,
+                                          const Caps &caps);
+    static void DeleteObject(Framebuffer *framebuffer);
+
+  protected:
+    ~FramebufferManager() override {}
+};
+
+}  // namespace gl
+
+#endif // LIBANGLE_RESOURCEMANAGER_H_
diff --git a/src/third_party/angle/src/libANGLE/ResourceManager_unittest.cpp b/src/third_party/angle/src/libANGLE/ResourceManager_unittest.cpp
new file mode 100644
index 0000000..03ca94a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/ResourceManager_unittest.cpp
@@ -0,0 +1,73 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Unit tests for ResourceManager.
+//
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "libANGLE/ResourceManager.h"
+#include "tests/angle_unittests_utils.h"
+
+using namespace rx;
+using namespace gl;
+
+using ::testing::_;
+
+namespace
+{
+
+class ResourceManagerTest : public testing::Test
+{
+  protected:
+    void SetUp() override
+    {
+        mTextureManager      = new TextureManager();
+        mBufferManager       = new BufferManager();
+        mRenderbuffermanager = new RenderbufferManager();
+    }
+
+    void TearDown() override
+    {
+        mTextureManager->release(nullptr);
+        mBufferManager->release(nullptr);
+        mRenderbuffermanager->release(nullptr);
+    }
+
+    MockGLFactory mMockFactory;
+    TextureManager *mTextureManager;
+    BufferManager *mBufferManager;
+    RenderbufferManager *mRenderbuffermanager;
+};
+
+TEST_F(ResourceManagerTest, ReallocateBoundTexture)
+{
+    EXPECT_CALL(mMockFactory, createTexture(_)).Times(1).RetiresOnSaturation();
+
+    mTextureManager->checkTextureAllocation(&mMockFactory, 1, GL_TEXTURE_2D);
+    GLuint newTexture = mTextureManager->createTexture();
+    EXPECT_NE(1u, newTexture);
+}
+
+TEST_F(ResourceManagerTest, ReallocateBoundBuffer)
+{
+    EXPECT_CALL(mMockFactory, createBuffer(_)).Times(1).RetiresOnSaturation();
+
+    mBufferManager->checkBufferAllocation(&mMockFactory, 1);
+    GLuint newBuffer = mBufferManager->createBuffer();
+    EXPECT_NE(1u, newBuffer);
+}
+
+TEST_F(ResourceManagerTest, ReallocateBoundRenderbuffer)
+{
+    EXPECT_CALL(mMockFactory, createRenderbuffer()).Times(1).RetiresOnSaturation();
+
+    mRenderbuffermanager->checkRenderbufferAllocation(&mMockFactory, 1);
+    GLuint newRenderbuffer = mRenderbuffermanager->createRenderbuffer();
+    EXPECT_NE(1u, newRenderbuffer);
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/libANGLE/Sampler.cpp b/src/third_party/angle/src/libANGLE/Sampler.cpp
new file mode 100644
index 0000000..369c3cb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Sampler.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Sampler.cpp : Implements the Sampler class, which represents a GLES 3
+// sampler object. Sampler objects store some state needed to sample textures.
+
+#include "libANGLE/Sampler.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace gl
+{
+
+Sampler::Sampler(rx::GLImplFactory *factory, GLuint id)
+    : RefCountObject(id), mImpl(factory->createSampler()), mLabel(), mSamplerState()
+{
+}
+
+Sampler::~Sampler()
+{
+    SafeDelete(mImpl);
+}
+
+void Sampler::setLabel(const std::string &label)
+{
+    mLabel = label;
+}
+
+const std::string &Sampler::getLabel() const
+{
+    return mLabel;
+}
+
+void Sampler::setMinFilter(GLenum minFilter)
+{
+    mSamplerState.minFilter = minFilter;
+}
+
+GLenum Sampler::getMinFilter() const
+{
+    return mSamplerState.minFilter;
+}
+
+void Sampler::setMagFilter(GLenum magFilter)
+{
+    mSamplerState.magFilter = magFilter;
+}
+
+GLenum Sampler::getMagFilter() const
+{
+    return mSamplerState.magFilter;
+}
+
+void Sampler::setWrapS(GLenum wrapS)
+{
+    mSamplerState.wrapS = wrapS;
+}
+
+GLenum Sampler::getWrapS() const
+{
+    return mSamplerState.wrapS;
+}
+
+void Sampler::setWrapT(GLenum wrapT)
+{
+    mSamplerState.wrapT = wrapT;
+}
+
+GLenum Sampler::getWrapT() const
+{
+    return mSamplerState.wrapT;
+}
+
+void Sampler::setWrapR(GLenum wrapR)
+{
+    mSamplerState.wrapR = wrapR;
+}
+
+GLenum Sampler::getWrapR() const
+{
+    return mSamplerState.wrapR;
+}
+
+void Sampler::setMaxAnisotropy(float maxAnisotropy)
+{
+    mSamplerState.maxAnisotropy = maxAnisotropy;
+}
+
+float Sampler::getMaxAnisotropy() const
+{
+    return mSamplerState.maxAnisotropy;
+}
+
+void Sampler::setMinLod(GLfloat minLod)
+{
+    mSamplerState.minLod = minLod;
+}
+
+GLfloat Sampler::getMinLod() const
+{
+    return mSamplerState.minLod;
+}
+
+void Sampler::setMaxLod(GLfloat maxLod)
+{
+    mSamplerState.maxLod = maxLod;
+}
+
+GLfloat Sampler::getMaxLod() const
+{
+    return mSamplerState.maxLod;
+}
+
+void Sampler::setCompareMode(GLenum compareMode)
+{
+    mSamplerState.compareMode = compareMode;
+}
+
+GLenum Sampler::getCompareMode() const
+{
+    return mSamplerState.compareMode;
+}
+
+void Sampler::setCompareFunc(GLenum compareFunc)
+{
+    mSamplerState.compareFunc = compareFunc;
+}
+
+GLenum Sampler::getCompareFunc() const
+{
+    return mSamplerState.compareFunc;
+}
+
+void Sampler::setSRGBDecode(GLenum sRGBDecode)
+{
+    mSamplerState.sRGBDecode = sRGBDecode;
+}
+
+GLenum Sampler::getSRGBDecode() const
+{
+    return mSamplerState.sRGBDecode;
+}
+
+const SamplerState &Sampler::getSamplerState() const
+{
+    return mSamplerState;
+}
+
+rx::SamplerImpl *Sampler::getImplementation() const
+{
+    return mImpl;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/Sampler.h b/src/third_party/angle/src/libANGLE/Sampler.h
new file mode 100644
index 0000000..0e5ff8a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Sampler.h
@@ -0,0 +1,84 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Sampler.h : Defines the Sampler class, which represents a GLES 3
+// sampler object. Sampler objects store some state needed to sample textures.
+
+#ifndef LIBANGLE_SAMPLER_H_
+#define LIBANGLE_SAMPLER_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class GLImplFactory;
+class SamplerImpl;
+}
+
+namespace gl
+{
+
+class Sampler final : public RefCountObject, public LabeledObject
+{
+  public:
+    Sampler(rx::GLImplFactory *factory, GLuint id);
+    ~Sampler() override;
+
+    void destroy(const Context *context) override {}
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    void setMinFilter(GLenum minFilter);
+    GLenum getMinFilter() const;
+
+    void setMagFilter(GLenum magFilter);
+    GLenum getMagFilter() const;
+
+    void setWrapS(GLenum wrapS);
+    GLenum getWrapS() const;
+
+    void setWrapT(GLenum wrapT);
+    GLenum getWrapT() const;
+
+    void setWrapR(GLenum wrapR);
+    GLenum getWrapR() const;
+
+    void setMaxAnisotropy(float maxAnisotropy);
+    float getMaxAnisotropy() const;
+
+    void setMinLod(GLfloat minLod);
+    GLfloat getMinLod() const;
+
+    void setMaxLod(GLfloat maxLod);
+    GLfloat getMaxLod() const;
+
+    void setCompareMode(GLenum compareMode);
+    GLenum getCompareMode() const;
+
+    void setCompareFunc(GLenum compareFunc);
+    GLenum getCompareFunc() const;
+
+    void setSRGBDecode(GLenum sRGBDecode);
+    GLenum getSRGBDecode() const;
+
+    const SamplerState &getSamplerState() const;
+
+    rx::SamplerImpl *getImplementation() const;
+
+  private:
+    rx::SamplerImpl *mImpl;
+
+    std::string mLabel;
+
+    SamplerState mSamplerState;
+};
+
+}
+
+#endif // LIBANGLE_SAMPLER_H_
diff --git a/src/third_party/angle/src/libANGLE/Shader.cpp b/src/third_party/angle/src/libANGLE/Shader.cpp
new file mode 100644
index 0000000..6bd07a2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Shader.cpp
@@ -0,0 +1,432 @@
+//
+// 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.
+//
+
+// Shader.cpp: Implements the gl::Shader class and its  derived classes
+// VertexShader and FragmentShader. Implements GL shader objects and related
+// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
+
+#include "libANGLE/Shader.h"
+
+#include <sstream>
+
+#include "common/utilities.h"
+#include "GLSLANG/ShaderLang.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ShaderImpl.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Context.h"
+
+namespace gl
+{
+
+namespace
+{
+template <typename VarT>
+std::vector<VarT> GetActiveShaderVariables(const std::vector<VarT> *variableList)
+{
+    ASSERT(variableList);
+    std::vector<VarT> result;
+    for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++)
+    {
+        const VarT &var = variableList->at(varIndex);
+        if (var.staticUse)
+        {
+            result.push_back(var);
+        }
+    }
+    return result;
+}
+
+template <typename VarT>
+const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
+{
+    ASSERT(variableList);
+    return *variableList;
+}
+
+}  // anonymous namespace
+
+// true if varying x has a higher priority in packing than y
+bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
+{
+    if (x.type == y.type)
+    {
+        return x.arraySize > y.arraySize;
+    }
+
+    // Special case for handling structs: we sort these to the end of the list
+    if (x.type == GL_STRUCT_ANGLEX)
+    {
+        return false;
+    }
+
+    if (y.type == GL_STRUCT_ANGLEX)
+    {
+        return true;
+    }
+
+    return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
+}
+
+ShaderState::ShaderState(GLenum shaderType) : mLabel(), mShaderType(shaderType), mShaderVersion(100)
+{
+    mLocalSize.fill(-1);
+}
+
+ShaderState::~ShaderState()
+{
+}
+
+Shader::Shader(ShaderProgramManager *manager,
+               rx::GLImplFactory *implFactory,
+               const gl::Limitations &rendererLimitations,
+               GLenum type,
+               GLuint handle)
+    : mState(type),
+      mImplementation(implFactory->createShader(mState)),
+      mRendererLimitations(rendererLimitations),
+      mHandle(handle),
+      mType(type),
+      mRefCount(0),
+      mDeleteStatus(false),
+      mCompiled(false),
+      mResourceManager(manager)
+{
+    ASSERT(mImplementation);
+}
+
+Shader::~Shader()
+{
+    SafeDelete(mImplementation);
+}
+
+void Shader::setLabel(const std::string &label)
+{
+    mState.mLabel = label;
+}
+
+const std::string &Shader::getLabel() const
+{
+    return mState.mLabel;
+}
+
+GLuint Shader::getHandle() const
+{
+    return mHandle;
+}
+
+void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
+{
+    std::ostringstream stream;
+
+    for (int i = 0; i < count; i++)
+    {
+        if (length == nullptr || length[i] < 0)
+        {
+            stream.write(string[i], strlen(string[i]));
+        }
+        else
+        {
+            stream.write(string[i], length[i]);
+        }
+    }
+
+    mState.mSource = stream.str();
+}
+
+int Shader::getInfoLogLength() const
+{
+    if (mInfoLog.empty())
+    {
+        return 0;
+    }
+
+    return (static_cast<int>(mInfoLog.length()) + 1);
+}
+
+void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+{
+    int index = 0;
+
+    if (bufSize > 0)
+    {
+        index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
+        memcpy(infoLog, mInfoLog.c_str(), index);
+
+        infoLog[index] = '\0';
+    }
+
+    if (length)
+    {
+        *length = index;
+    }
+}
+
+int Shader::getSourceLength() const
+{
+    return mState.mSource.empty() ? 0 : (static_cast<int>(mState.mSource.length()) + 1);
+}
+
+int Shader::getTranslatedSourceLength() const
+{
+    if (mState.mTranslatedSource.empty())
+    {
+        return 0;
+    }
+
+    return (static_cast<int>(mState.mTranslatedSource.length()) + 1);
+}
+
+int Shader::getTranslatedSourceWithDebugInfoLength() const
+{
+    const std::string &debugInfo = mImplementation->getDebugInfo();
+    if (debugInfo.empty())
+    {
+        return 0;
+    }
+
+    return (static_cast<int>(debugInfo.length()) + 1);
+}
+
+void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer)
+{
+    int index = 0;
+
+    if (bufSize > 0)
+    {
+        index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
+        memcpy(buffer, source.c_str(), index);
+
+        buffer[index] = '\0';
+    }
+
+    if (length)
+    {
+        *length = index;
+    }
+}
+
+void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
+{
+    getSourceImpl(mState.mSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const
+{
+    getSourceImpl(mState.mTranslatedSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const
+{
+    const std::string &debugInfo = mImplementation->getDebugInfo();
+    getSourceImpl(debugInfo, bufSize, length, buffer);
+}
+
+void Shader::compile(const Context *context)
+{
+    mState.mTranslatedSource.clear();
+    mInfoLog.clear();
+    mState.mShaderVersion = 100;
+    mState.mVaryings.clear();
+    mState.mUniforms.clear();
+    mState.mInterfaceBlocks.clear();
+    mState.mActiveAttributes.clear();
+    mState.mActiveOutputVariables.clear();
+
+    Compiler *compiler = context->getCompiler();
+    ShHandle compilerHandle = compiler->getCompilerHandle(mState.mShaderType);
+
+    std::stringstream sourceStream;
+
+    std::string sourcePath;
+    ShCompileOptions additionalOptions =
+        mImplementation->prepareSourceAndReturnOptions(&sourceStream, &sourcePath);
+    ShCompileOptions compileOptions = (SH_OBJECT_CODE | SH_VARIABLES | additionalOptions);
+
+    // Add default options to WebGL shaders to prevent unexpected behavior during compilation.
+    if (context->getExtensions().webglCompatibility)
+    {
+        compileOptions |= SH_INIT_GL_POSITION;
+        compileOptions |= SH_LIMIT_CALL_STACK_DEPTH;
+        compileOptions |= SH_LIMIT_EXPRESSION_COMPLEXITY;
+        compileOptions |= SH_ENFORCE_PACKING_RESTRICTIONS;
+    }
+
+    // Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes
+    // in fragment shaders. Shader compilation will fail. To provide a better error message we can
+    // instruct the compiler to pre-validate.
+    if (mRendererLimitations.shadersRequireIndexedLoopValidation)
+    {
+        compileOptions |= SH_VALIDATE_LOOP_INDEXING;
+    }
+
+    std::string sourceString  = sourceStream.str();
+    std::vector<const char *> sourceCStrings;
+
+    if (!sourcePath.empty())
+    {
+        sourceCStrings.push_back(sourcePath.c_str());
+    }
+
+    sourceCStrings.push_back(sourceString.c_str());
+
+    bool result =
+        sh::Compile(compilerHandle, &sourceCStrings[0], sourceCStrings.size(), compileOptions);
+
+    if (!result)
+    {
+        mInfoLog = sh::GetInfoLog(compilerHandle);
+        WARN() << std::endl << mInfoLog;
+        mCompiled = false;
+        return;
+    }
+
+    mState.mTranslatedSource = sh::GetObjectCode(compilerHandle);
+
+#ifndef NDEBUG
+    // Prefix translated shader with commented out un-translated shader.
+    // Useful in diagnostics tools which capture the shader source.
+    std::ostringstream shaderStream;
+    shaderStream << "// GLSL\n";
+    shaderStream << "//\n";
+
+    std::istringstream inputSourceStream(mState.mSource);
+    std::string line;
+    while (std::getline(inputSourceStream, line))
+    {
+        // Remove null characters from the source line
+        line.erase(std::remove(line.begin(), line.end(), '\0'), line.end());
+
+        shaderStream << "// " << line;
+    }
+    shaderStream << "\n\n";
+    shaderStream << mState.mTranslatedSource;
+    mState.mTranslatedSource = shaderStream.str();
+#endif
+
+    // Gather the shader information
+    mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);
+
+    mState.mVaryings        = GetShaderVariables(sh::GetVaryings(compilerHandle));
+    mState.mUniforms        = GetShaderVariables(sh::GetUniforms(compilerHandle));
+    mState.mInterfaceBlocks = GetShaderVariables(sh::GetInterfaceBlocks(compilerHandle));
+
+    switch (mState.mShaderType)
+    {
+        case GL_COMPUTE_SHADER:
+        {
+            mState.mLocalSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
+            break;
+        }
+        case GL_VERTEX_SHADER:
+        {
+            mState.mActiveAttributes = GetActiveShaderVariables(sh::GetAttributes(compilerHandle));
+            break;
+        }
+        case GL_FRAGMENT_SHADER:
+        {
+            // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
+            std::sort(mState.mVaryings.begin(), mState.mVaryings.end(), CompareShaderVar);
+            mState.mActiveOutputVariables =
+                GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
+            break;
+        }
+        default:
+            UNREACHABLE();
+    }
+
+    ASSERT(!mState.mTranslatedSource.empty());
+
+    mCompiled = mImplementation->postTranslateCompile(compiler, &mInfoLog);
+}
+
+void Shader::addRef()
+{
+    mRefCount++;
+}
+
+void Shader::release(const Context *context)
+{
+    mRefCount--;
+
+    if (mRefCount == 0 && mDeleteStatus)
+    {
+        mResourceManager->deleteShader(context, mHandle);
+    }
+}
+
+unsigned int Shader::getRefCount() const
+{
+    return mRefCount;
+}
+
+bool Shader::isFlaggedForDeletion() const
+{
+    return mDeleteStatus;
+}
+
+void Shader::flagForDeletion()
+{
+    mDeleteStatus = true;
+}
+
+int Shader::getShaderVersion() const
+{
+    return mState.mShaderVersion;
+}
+
+const std::vector<sh::Varying> &Shader::getVaryings() const
+{
+    return mState.getVaryings();
+}
+
+const std::vector<sh::Uniform> &Shader::getUniforms() const
+{
+    return mState.getUniforms();
+}
+
+const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
+{
+    return mState.getInterfaceBlocks();
+}
+
+const std::vector<sh::Attribute> &Shader::getActiveAttributes() const
+{
+    return mState.getActiveAttributes();
+}
+
+const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables() const
+{
+    return mState.getActiveOutputVariables();
+}
+
+int Shader::getSemanticIndex(const std::string &attributeName) const
+{
+    if (!attributeName.empty())
+    {
+        const auto &activeAttributes = mState.getActiveAttributes();
+
+        int semanticIndex = 0;
+        for (size_t attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
+        {
+            const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
+
+            if (attribute.name == attributeName)
+            {
+                return semanticIndex;
+            }
+
+            semanticIndex += gl::VariableRegisterCount(attribute.type);
+        }
+    }
+
+    return -1;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/Shader.h b/src/third_party/angle/src/libANGLE/Shader.h
new file mode 100644
index 0000000..39f7b94
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Shader.h
@@ -0,0 +1,155 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Shader.h: Defines the abstract gl::Shader class and its concrete derived
+// classes VertexShader and FragmentShader. Implements GL shader objects and
+// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section
+// 3.8 page 84.
+
+#ifndef LIBANGLE_SHADER_H_
+#define LIBANGLE_SHADER_H_
+
+#include <string>
+#include <list>
+#include <vector>
+
+#include "angle_gl.h"
+#include <GLSLANG/ShaderLang.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Debug.h"
+
+namespace rx
+{
+class GLImplFactory;
+class ShaderImpl;
+class ShaderSh;
+}
+
+namespace gl
+{
+class Compiler;
+class ContextState;
+struct Limitations;
+class ShaderProgramManager;
+class Context;
+
+class ShaderState final : angle::NonCopyable
+{
+  public:
+    ShaderState(GLenum shaderType);
+    ~ShaderState();
+
+    const std::string &getLabel() const { return mLabel; }
+
+    const std::string &getSource() const { return mSource; }
+    const std::string &getTranslatedSource() const { return mTranslatedSource; }
+
+    GLenum getShaderType() const { return mShaderType; }
+    int getShaderVersion() const { return mShaderVersion; }
+
+    const std::vector<sh::Varying> &getVaryings() const { return mVaryings; }
+    const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; }
+    const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; }
+    const std::vector<sh::Attribute> &getActiveAttributes() const { return mActiveAttributes; }
+    const std::vector<sh::OutputVariable> &getActiveOutputVariables() const
+    {
+        return mActiveOutputVariables;
+    }
+
+  private:
+    friend class Shader;
+
+    std::string mLabel;
+
+    GLenum mShaderType;
+    int mShaderVersion;
+    std::string mTranslatedSource;
+    std::string mSource;
+
+    sh::WorkGroupSize mLocalSize;
+
+    std::vector<sh::Varying> mVaryings;
+    std::vector<sh::Uniform> mUniforms;
+    std::vector<sh::InterfaceBlock> mInterfaceBlocks;
+    std::vector<sh::Attribute> mActiveAttributes;
+    std::vector<sh::OutputVariable> mActiveOutputVariables;
+};
+
+class Shader final : angle::NonCopyable, public LabeledObject
+{
+  public:
+    Shader(ShaderProgramManager *manager,
+           rx::GLImplFactory *implFactory,
+           const gl::Limitations &rendererLimitations,
+           GLenum type,
+           GLuint handle);
+
+    void destroy(const Context *context) {}
+    virtual ~Shader();
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    GLenum getType() const { return mType; }
+    GLuint getHandle() const;
+
+    rx::ShaderImpl *getImplementation() const { return mImplementation; }
+
+    void deleteSource();
+    void setSource(GLsizei count, const char *const *string, const GLint *length);
+    int getInfoLogLength() const;
+    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+    int getSourceLength() const;
+    void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
+    int getTranslatedSourceLength() const;
+    int getTranslatedSourceWithDebugInfoLength() const;
+    const std::string &getTranslatedSource() const { return mState.getTranslatedSource(); }
+    void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
+    void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const;
+
+    void compile(const Context *context);
+    bool isCompiled() const { return mCompiled; }
+
+    void addRef();
+    void release(const Context *context);
+    unsigned int getRefCount() const;
+    bool isFlaggedForDeletion() const;
+    void flagForDeletion();
+
+    int getShaderVersion() const;
+
+    const std::vector<sh::Varying> &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::OutputVariable> &getActiveOutputVariables() const;
+
+    int getSemanticIndex(const std::string &attributeName) const;
+
+    const sh::WorkGroupSize &getWorkGroupSize() const { return mState.mLocalSize; }
+
+  private:
+    static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer);
+
+    ShaderState mState;
+    rx::ShaderImpl *mImplementation;
+    const gl::Limitations &mRendererLimitations;
+    const GLuint mHandle;
+    const GLenum mType;
+    unsigned int mRefCount;     // Number of program objects this shader is attached to
+    bool mDeleteStatus;         // Flag to indicate that the shader can be deleted when no longer in use
+    bool mCompiled;             // Indicates if this shader has been successfully compiled
+    std::string mInfoLog;
+
+    ShaderProgramManager *mResourceManager;
+};
+
+bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y);
+}
+
+#endif   // LIBANGLE_SHADER_H_
diff --git a/src/third_party/angle/src/libANGLE/State.cpp b/src/third_party/angle/src/libANGLE/State.cpp
new file mode 100644
index 0000000..2932978
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/State.cpp
@@ -0,0 +1,2197 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// State.cpp: Implements the State class, encapsulating raw GL state.
+
+#include "libANGLE/State.h"
+
+#include <limits>
+#include <string.h>
+
+#include "common/bitset_utils.h"
+#include "common/matrix_utils.h"
+#include "common/mathutil.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+
+namespace
+{
+
+GLenum ActiveQueryType(const GLenum type)
+{
+    return (type == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) ? GL_ANY_SAMPLES_PASSED : type;
+}
+
+}  // anonymous namepace
+
+namespace gl
+{
+
+State::State()
+    : mMaxDrawBuffers(0),
+      mMaxCombinedTextureImageUnits(0),
+      mDepthClearValue(0),
+      mStencilClearValue(0),
+      mScissorTest(false),
+      mSampleCoverage(false),
+      mSampleCoverageValue(0),
+      mSampleCoverageInvert(false),
+      mStencilRef(0),
+      mStencilBackRef(0),
+      mLineWidth(0),
+      mGenerateMipmapHint(GL_NONE),
+      mFragmentShaderDerivativeHint(GL_NONE),
+      mBindGeneratesResource(true),
+      mClientArraysEnabled(true),
+      mNearZ(0),
+      mFarZ(0),
+      mReadFramebuffer(nullptr),
+      mDrawFramebuffer(nullptr),
+      mProgram(nullptr),
+      mVertexArray(nullptr),
+      mActiveSampler(0),
+      mPrimitiveRestart(false),
+      mMultiSampling(false),
+      mSampleAlphaToOne(false),
+      mFramebufferSRGB(true),
+      mRobustResourceInit(false)
+{
+}
+
+State::~State()
+{
+}
+
+void State::initialize(const Caps &caps,
+                       const Extensions &extensions,
+                       const Version &clientVersion,
+                       bool debug,
+                       bool bindGeneratesResource,
+                       bool clientArraysEnabled,
+                       bool robustResourceInit)
+{
+    mMaxDrawBuffers = caps.maxDrawBuffers;
+    mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
+
+    setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
+
+    mDepthClearValue = 1.0f;
+    mStencilClearValue = 0;
+
+    mRasterizer.rasterizerDiscard = false;
+    mRasterizer.cullFace = false;
+    mRasterizer.cullMode = GL_BACK;
+    mRasterizer.frontFace = GL_CCW;
+    mRasterizer.polygonOffsetFill = false;
+    mRasterizer.polygonOffsetFactor = 0.0f;
+    mRasterizer.polygonOffsetUnits = 0.0f;
+    mRasterizer.pointDrawMode = false;
+    mRasterizer.multiSample = false;
+    mScissorTest = false;
+    mScissor.x = 0;
+    mScissor.y = 0;
+    mScissor.width = 0;
+    mScissor.height = 0;
+
+    mBlend.blend = false;
+    mBlend.sourceBlendRGB = GL_ONE;
+    mBlend.sourceBlendAlpha = GL_ONE;
+    mBlend.destBlendRGB = GL_ZERO;
+    mBlend.destBlendAlpha = GL_ZERO;
+    mBlend.blendEquationRGB = GL_FUNC_ADD;
+    mBlend.blendEquationAlpha = GL_FUNC_ADD;
+    mBlend.sampleAlphaToCoverage = false;
+    mBlend.dither = true;
+
+    mBlendColor.red = 0;
+    mBlendColor.green = 0;
+    mBlendColor.blue = 0;
+    mBlendColor.alpha = 0;
+
+    mDepthStencil.depthTest = false;
+    mDepthStencil.depthFunc = GL_LESS;
+    mDepthStencil.depthMask = true;
+    mDepthStencil.stencilTest = false;
+    mDepthStencil.stencilFunc = GL_ALWAYS;
+    mDepthStencil.stencilMask = static_cast<GLuint>(-1);
+    mDepthStencil.stencilWritemask = static_cast<GLuint>(-1);
+    mDepthStencil.stencilBackFunc = GL_ALWAYS;
+    mDepthStencil.stencilBackMask = static_cast<GLuint>(-1);
+    mDepthStencil.stencilBackWritemask = static_cast<GLuint>(-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;
+
+    mStencilRef = 0;
+    mStencilBackRef = 0;
+
+    mSampleCoverage = false;
+    mSampleCoverageValue = 1.0f;
+    mSampleCoverageInvert = false;
+    mGenerateMipmapHint = GL_DONT_CARE;
+    mFragmentShaderDerivativeHint = GL_DONT_CARE;
+
+    mBindGeneratesResource = bindGeneratesResource;
+    mClientArraysEnabled   = clientArraysEnabled;
+
+    mLineWidth = 1.0f;
+
+    mViewport.x = 0;
+    mViewport.y = 0;
+    mViewport.width = 0;
+    mViewport.height = 0;
+    mNearZ = 0.0f;
+    mFarZ = 1.0f;
+
+    mBlend.colorMaskRed = true;
+    mBlend.colorMaskGreen = true;
+    mBlend.colorMaskBlue = true;
+    mBlend.colorMaskAlpha = true;
+
+    mActiveSampler = 0;
+
+    mVertexAttribCurrentValues.resize(caps.maxVertexAttributes);
+
+    mUniformBuffers.resize(caps.maxUniformBufferBindings);
+
+    mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
+    mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
+    if (clientVersion >= Version(3, 0))
+    {
+        // TODO: These could also be enabled via extension
+        mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits);
+        mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits);
+    }
+    if (clientVersion >= Version(3, 1))
+    {
+        mSamplerTextures[GL_TEXTURE_2D_MULTISAMPLE].resize(caps.maxCombinedTextureImageUnits);
+
+        mAtomicCounterBuffers.resize(caps.maxAtomicCounterBufferBindings);
+        mShaderStorageBuffers.resize(caps.maxShaderStorageBufferBindings);
+    }
+    if (extensions.eglImageExternal || extensions.eglStreamConsumerExternal)
+    {
+        mSamplerTextures[GL_TEXTURE_EXTERNAL_OES].resize(caps.maxCombinedTextureImageUnits);
+    }
+
+    mSamplers.resize(caps.maxCombinedTextureImageUnits);
+
+    mActiveQueries[GL_ANY_SAMPLES_PASSED].set(nullptr);
+    mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(nullptr);
+    mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(nullptr);
+    mActiveQueries[GL_TIME_ELAPSED_EXT].set(nullptr);
+    mActiveQueries[GL_COMMANDS_COMPLETED_CHROMIUM].set(nullptr);
+
+    mProgram = nullptr;
+
+    mReadFramebuffer = nullptr;
+    mDrawFramebuffer = nullptr;
+
+    mPrimitiveRestart = false;
+
+    mDebug.setOutputEnabled(debug);
+    mDebug.setMaxLoggedMessages(extensions.maxDebugLoggedMessages);
+
+    if (extensions.framebufferMultisample)
+    {
+        mMultiSampling = true;
+        mSampleAlphaToOne = false;
+    }
+
+    mCoverageModulation = GL_NONE;
+
+    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+    mPathStencilFunc = GL_ALWAYS;
+    mPathStencilRef  = 0;
+    mPathStencilMask = std::numeric_limits<GLuint>::max();
+
+    mRobustResourceInit = robustResourceInit;
+}
+
+void State::reset(const Context *context)
+{
+    for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
+    {
+        TextureBindingVector &textureVector = bindingVec->second;
+        for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
+        {
+            textureVector[textureIdx].set(nullptr);
+        }
+    }
+    for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
+    {
+        mSamplers[samplerIdx].set(nullptr);
+    }
+
+    mArrayBuffer.set(nullptr);
+    mDrawIndirectBuffer.set(nullptr);
+    mRenderbuffer.set(nullptr);
+
+    if (mProgram)
+    {
+        mProgram->release(context);
+    }
+    mProgram = nullptr;
+
+    mTransformFeedback.set(nullptr);
+
+    for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++)
+    {
+        i->second.set(nullptr);
+    }
+
+    mGenericUniformBuffer.set(nullptr);
+    for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
+    {
+        bufItr->set(nullptr);
+    }
+
+    mCopyReadBuffer.set(nullptr);
+    mCopyWriteBuffer.set(nullptr);
+
+    mPack.pixelBuffer.set(nullptr);
+    mUnpack.pixelBuffer.set(nullptr);
+
+    mGenericAtomicCounterBuffer.set(nullptr);
+    for (auto &buf : mAtomicCounterBuffers)
+    {
+        buf.set(nullptr);
+    }
+
+    mGenericShaderStorageBuffer.set(nullptr);
+    for (auto &buf : mShaderStorageBuffers)
+    {
+        buf.set(nullptr);
+    }
+
+    mProgram = nullptr;
+
+    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+    mPathStencilFunc = GL_ALWAYS;
+    mPathStencilRef  = 0;
+    mPathStencilMask = std::numeric_limits<GLuint>::max();
+
+    // TODO(jmadill): Is this necessary?
+    setAllDirtyBits();
+}
+
+const RasterizerState &State::getRasterizerState() const
+{
+    return mRasterizer;
+}
+
+const BlendState &State::getBlendState() const
+{
+    return mBlend;
+}
+
+const DepthStencilState &State::getDepthStencilState() const
+{
+    return mDepthStencil;
+}
+
+void State::setColorClearValue(float red, float green, float blue, float alpha)
+{
+    mColorClearValue.red = red;
+    mColorClearValue.green = green;
+    mColorClearValue.blue = blue;
+    mColorClearValue.alpha = alpha;
+    mDirtyBits.set(DIRTY_BIT_CLEAR_COLOR);
+}
+
+void State::setDepthClearValue(float depth)
+{
+    mDepthClearValue = depth;
+    mDirtyBits.set(DIRTY_BIT_CLEAR_DEPTH);
+}
+
+void State::setStencilClearValue(int stencil)
+{
+    mStencilClearValue = stencil;
+    mDirtyBits.set(DIRTY_BIT_CLEAR_STENCIL);
+}
+
+void State::setColorMask(bool red, bool green, bool blue, bool alpha)
+{
+    mBlend.colorMaskRed = red;
+    mBlend.colorMaskGreen = green;
+    mBlend.colorMaskBlue = blue;
+    mBlend.colorMaskAlpha = alpha;
+    mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+}
+
+void State::setDepthMask(bool mask)
+{
+    mDepthStencil.depthMask = mask;
+    mDirtyBits.set(DIRTY_BIT_DEPTH_MASK);
+}
+
+bool State::isRasterizerDiscardEnabled() const
+{
+    return mRasterizer.rasterizerDiscard;
+}
+
+void State::setRasterizerDiscard(bool enabled)
+{
+    mRasterizer.rasterizerDiscard = enabled;
+    mDirtyBits.set(DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
+}
+
+bool State::isCullFaceEnabled() const
+{
+    return mRasterizer.cullFace;
+}
+
+void State::setCullFace(bool enabled)
+{
+    mRasterizer.cullFace = enabled;
+    mDirtyBits.set(DIRTY_BIT_CULL_FACE_ENABLED);
+}
+
+void State::setCullMode(GLenum mode)
+{
+    mRasterizer.cullMode = mode;
+    mDirtyBits.set(DIRTY_BIT_CULL_FACE);
+}
+
+void State::setFrontFace(GLenum front)
+{
+    mRasterizer.frontFace = front;
+    mDirtyBits.set(DIRTY_BIT_FRONT_FACE);
+}
+
+bool State::isDepthTestEnabled() const
+{
+    return mDepthStencil.depthTest;
+}
+
+void State::setDepthTest(bool enabled)
+{
+    mDepthStencil.depthTest = enabled;
+    mDirtyBits.set(DIRTY_BIT_DEPTH_TEST_ENABLED);
+}
+
+void State::setDepthFunc(GLenum depthFunc)
+{
+     mDepthStencil.depthFunc = depthFunc;
+     mDirtyBits.set(DIRTY_BIT_DEPTH_FUNC);
+}
+
+void State::setDepthRange(float zNear, float zFar)
+{
+    mNearZ = zNear;
+    mFarZ = zFar;
+    mDirtyBits.set(DIRTY_BIT_DEPTH_RANGE);
+}
+
+float State::getNearPlane() const
+{
+    return mNearZ;
+}
+
+float State::getFarPlane() const
+{
+    return mFarZ;
+}
+
+bool State::isBlendEnabled() const
+{
+    return mBlend.blend;
+}
+
+void State::setBlend(bool enabled)
+{
+    mBlend.blend = enabled;
+    mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+}
+
+void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
+{
+    mBlend.sourceBlendRGB = sourceRGB;
+    mBlend.destBlendRGB = destRGB;
+    mBlend.sourceBlendAlpha = sourceAlpha;
+    mBlend.destBlendAlpha = destAlpha;
+    mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS);
+}
+
+void State::setBlendColor(float red, float green, float blue, float alpha)
+{
+    mBlendColor.red = red;
+    mBlendColor.green = green;
+    mBlendColor.blue = blue;
+    mBlendColor.alpha = alpha;
+    mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+}
+
+void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
+{
+    mBlend.blendEquationRGB = rgbEquation;
+    mBlend.blendEquationAlpha = alphaEquation;
+    mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS);
+}
+
+const ColorF &State::getBlendColor() const
+{
+    return mBlendColor;
+}
+
+bool State::isStencilTestEnabled() const
+{
+    return mDepthStencil.stencilTest;
+}
+
+void State::setStencilTest(bool enabled)
+{
+    mDepthStencil.stencilTest = enabled;
+    mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
+}
+
+void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
+{
+    mDepthStencil.stencilFunc = stencilFunc;
+    mStencilRef = (stencilRef > 0) ? stencilRef : 0;
+    mDepthStencil.stencilMask = stencilMask;
+    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+}
+
+void State::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
+{
+    mDepthStencil.stencilBackFunc = stencilBackFunc;
+    mStencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
+    mDepthStencil.stencilBackMask = stencilBackMask;
+    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+}
+
+void State::setStencilWritemask(GLuint stencilWritemask)
+{
+    mDepthStencil.stencilWritemask = stencilWritemask;
+    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+}
+
+void State::setStencilBackWritemask(GLuint stencilBackWritemask)
+{
+    mDepthStencil.stencilBackWritemask = stencilBackWritemask;
+    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+}
+
+void State::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
+{
+    mDepthStencil.stencilFail = stencilFail;
+    mDepthStencil.stencilPassDepthFail = stencilPassDepthFail;
+    mDepthStencil.stencilPassDepthPass = stencilPassDepthPass;
+    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+}
+
+void State::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
+{
+    mDepthStencil.stencilBackFail = stencilBackFail;
+    mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail;
+    mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
+    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+}
+
+GLint State::getStencilRef() const
+{
+    return mStencilRef;
+}
+
+GLint State::getStencilBackRef() const
+{
+    return mStencilBackRef;
+}
+
+bool State::isPolygonOffsetFillEnabled() const
+{
+    return mRasterizer.polygonOffsetFill;
+}
+
+void State::setPolygonOffsetFill(bool enabled)
+{
+    mRasterizer.polygonOffsetFill = enabled;
+    mDirtyBits.set(DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
+}
+
+void State::setPolygonOffsetParams(GLfloat factor, GLfloat units)
+{
+    // An application can pass NaN values here, so handle this gracefully
+    mRasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor;
+    mRasterizer.polygonOffsetUnits = units != units ? 0.0f : units;
+    mDirtyBits.set(DIRTY_BIT_POLYGON_OFFSET);
+}
+
+bool State::isSampleAlphaToCoverageEnabled() const
+{
+    return mBlend.sampleAlphaToCoverage;
+}
+
+void State::setSampleAlphaToCoverage(bool enabled)
+{
+    mBlend.sampleAlphaToCoverage = enabled;
+    mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
+}
+
+bool State::isSampleCoverageEnabled() const
+{
+    return mSampleCoverage;
+}
+
+void State::setSampleCoverage(bool enabled)
+{
+    mSampleCoverage = enabled;
+    mDirtyBits.set(DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
+}
+
+void State::setSampleCoverageParams(GLclampf value, bool invert)
+{
+    mSampleCoverageValue = value;
+    mSampleCoverageInvert = invert;
+    mDirtyBits.set(DIRTY_BIT_SAMPLE_COVERAGE);
+}
+
+GLclampf State::getSampleCoverageValue() const
+{
+    return mSampleCoverageValue;
+}
+
+bool State::getSampleCoverageInvert() const
+{
+    return mSampleCoverageInvert;
+}
+
+void State::setSampleAlphaToOne(bool enabled)
+{
+    mSampleAlphaToOne = enabled;
+    mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
+}
+
+bool State::isSampleAlphaToOneEnabled() const
+{
+    return mSampleAlphaToOne;
+}
+
+void State::setMultisampling(bool enabled)
+{
+    mMultiSampling = enabled;
+    mDirtyBits.set(DIRTY_BIT_MULTISAMPLING);
+}
+
+bool State::isMultisamplingEnabled() const
+{
+    return mMultiSampling;
+}
+
+bool State::isScissorTestEnabled() const
+{
+    return mScissorTest;
+}
+
+void State::setScissorTest(bool enabled)
+{
+    mScissorTest = enabled;
+    mDirtyBits.set(DIRTY_BIT_SCISSOR_TEST_ENABLED);
+}
+
+void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    mScissor.x = x;
+    mScissor.y = y;
+    mScissor.width = width;
+    mScissor.height = height;
+    mDirtyBits.set(DIRTY_BIT_SCISSOR);
+}
+
+const Rectangle &State::getScissor() const
+{
+    return mScissor;
+}
+
+bool State::isDitherEnabled() const
+{
+    return mBlend.dither;
+}
+
+void State::setDither(bool enabled)
+{
+    mBlend.dither = enabled;
+    mDirtyBits.set(DIRTY_BIT_DITHER_ENABLED);
+}
+
+bool State::isPrimitiveRestartEnabled() const
+{
+    return mPrimitiveRestart;
+}
+
+void State::setPrimitiveRestart(bool enabled)
+{
+    mPrimitiveRestart = enabled;
+    mDirtyBits.set(DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
+}
+
+void State::setEnableFeature(GLenum feature, bool enabled)
+{
+    switch (feature)
+    {
+      case GL_MULTISAMPLE_EXT:               setMultisampling(enabled);         break;
+      case GL_SAMPLE_ALPHA_TO_ONE_EXT:       setSampleAlphaToOne(enabled);      break;
+      case GL_CULL_FACE:                     setCullFace(enabled);              break;
+      case GL_POLYGON_OFFSET_FILL:           setPolygonOffsetFill(enabled);     break;
+      case GL_SAMPLE_ALPHA_TO_COVERAGE:      setSampleAlphaToCoverage(enabled); break;
+      case GL_SAMPLE_COVERAGE:               setSampleCoverage(enabled);        break;
+      case GL_SCISSOR_TEST:                  setScissorTest(enabled);           break;
+      case GL_STENCIL_TEST:                  setStencilTest(enabled);           break;
+      case GL_DEPTH_TEST:                    setDepthTest(enabled);             break;
+      case GL_BLEND:                         setBlend(enabled);                 break;
+      case GL_DITHER:                        setDither(enabled);                break;
+      case GL_PRIMITIVE_RESTART_FIXED_INDEX: setPrimitiveRestart(enabled);      break;
+      case GL_RASTERIZER_DISCARD:            setRasterizerDiscard(enabled);     break;
+      case GL_SAMPLE_MASK:
+          if (enabled)
+          {
+              // Enabling this feature is not implemented yet.
+              UNIMPLEMENTED();
+          }
+          break;
+      case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+          mDebug.setOutputSynchronous(enabled);
+          break;
+      case GL_DEBUG_OUTPUT:
+          mDebug.setOutputEnabled(enabled);
+          break;
+      case GL_FRAMEBUFFER_SRGB_EXT:
+          setFramebufferSRGB(enabled);
+          break;
+      default:                               UNREACHABLE();
+    }
+}
+
+bool State::getEnableFeature(GLenum feature) const
+{
+    switch (feature)
+    {
+      case GL_MULTISAMPLE_EXT:               return isMultisamplingEnabled();
+      case GL_SAMPLE_ALPHA_TO_ONE_EXT:       return isSampleAlphaToOneEnabled();
+      case GL_CULL_FACE:                     return isCullFaceEnabled();
+      case GL_POLYGON_OFFSET_FILL:           return isPolygonOffsetFillEnabled();
+      case GL_SAMPLE_ALPHA_TO_COVERAGE:      return isSampleAlphaToCoverageEnabled();
+      case GL_SAMPLE_COVERAGE:               return isSampleCoverageEnabled();
+      case GL_SCISSOR_TEST:                  return isScissorTestEnabled();
+      case GL_STENCIL_TEST:                  return isStencilTestEnabled();
+      case GL_DEPTH_TEST:                    return isDepthTestEnabled();
+      case GL_BLEND:                         return isBlendEnabled();
+      case GL_DITHER:                        return isDitherEnabled();
+      case GL_PRIMITIVE_RESTART_FIXED_INDEX: return isPrimitiveRestartEnabled();
+      case GL_RASTERIZER_DISCARD:            return isRasterizerDiscardEnabled();
+      case GL_SAMPLE_MASK:
+          UNIMPLEMENTED();
+          return false;
+      case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+          return mDebug.isOutputSynchronous();
+      case GL_DEBUG_OUTPUT:
+          return mDebug.isOutputEnabled();
+      case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+          return isBindGeneratesResourceEnabled();
+      case GL_CLIENT_ARRAYS_ANGLE:
+          return areClientArraysEnabled();
+      case GL_FRAMEBUFFER_SRGB_EXT:
+          return getFramebufferSRGB();
+      case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+          return mRobustResourceInit;
+      default:                               UNREACHABLE(); return false;
+    }
+}
+
+void State::setLineWidth(GLfloat width)
+{
+    mLineWidth = width;
+    mDirtyBits.set(DIRTY_BIT_LINE_WIDTH);
+}
+
+float State::getLineWidth() const
+{
+    return mLineWidth;
+}
+
+void State::setGenerateMipmapHint(GLenum hint)
+{
+    mGenerateMipmapHint = hint;
+    mDirtyBits.set(DIRTY_BIT_GENERATE_MIPMAP_HINT);
+}
+
+void State::setFragmentShaderDerivativeHint(GLenum hint)
+{
+    mFragmentShaderDerivativeHint = hint;
+    mDirtyBits.set(DIRTY_BIT_SHADER_DERIVATIVE_HINT);
+    // TODO: Propagate the hint to shader translator so we can write
+    // ddx, ddx_coarse, or ddx_fine depending on the hint.
+    // Ignore for now. It is valid for implementations to ignore hint.
+}
+
+bool State::isBindGeneratesResourceEnabled() const
+{
+    return mBindGeneratesResource;
+}
+
+bool State::areClientArraysEnabled() const
+{
+    return mClientArraysEnabled;
+}
+
+void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    mViewport.x = x;
+    mViewport.y = y;
+    mViewport.width = width;
+    mViewport.height = height;
+    mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+}
+
+const Rectangle &State::getViewport() const
+{
+    return mViewport;
+}
+
+void State::setActiveSampler(unsigned int active)
+{
+    mActiveSampler = active;
+}
+
+unsigned int State::getActiveSampler() const
+{
+    return static_cast<unsigned int>(mActiveSampler);
+}
+
+void State::setSamplerTexture(GLenum type, Texture *texture)
+{
+    mSamplerTextures[type][mActiveSampler].set(texture);
+}
+
+Texture *State::getTargetTexture(GLenum target) const
+{
+    return getSamplerTexture(static_cast<unsigned int>(mActiveSampler), target);
+}
+
+Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const
+{
+    const auto it = mSamplerTextures.find(type);
+    ASSERT(it != mSamplerTextures.end());
+    ASSERT(sampler < it->second.size());
+    return it->second[sampler].get();
+}
+
+GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
+{
+    const auto it = mSamplerTextures.find(type);
+    ASSERT(it != mSamplerTextures.end());
+    ASSERT(sampler < it->second.size());
+    return it->second[sampler].id();
+}
+
+void State::detachTexture(const Context *context, const TextureMap &zeroTextures, GLuint texture)
+{
+    // Textures have a detach method on State rather than a simple
+    // removeBinding, because the zero/null texture objects are managed
+    // 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 (auto &bindingVec : mSamplerTextures)
+    {
+        GLenum textureType = bindingVec.first;
+        TextureBindingVector &textureVector = bindingVec.second;
+        for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
+        {
+            BindingPointer<Texture> &binding = textureVector[textureIdx];
+            if (binding.id() == texture)
+            {
+                auto it = zeroTextures.find(textureType);
+                ASSERT(it != zeroTextures.end());
+                // Zero textures are the "default" textures instead of NULL
+                binding.set(it->second.get());
+            }
+        }
+    }
+
+    // [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.
+
+    if (mReadFramebuffer)
+    {
+        mReadFramebuffer->detachTexture(context, texture);
+    }
+
+    if (mDrawFramebuffer)
+    {
+        mDrawFramebuffer->detachTexture(context, texture);
+    }
+}
+
+void State::initializeZeroTextures(const TextureMap &zeroTextures)
+{
+    for (const auto &zeroTexture : zeroTextures)
+    {
+        auto &samplerTextureArray = mSamplerTextures[zeroTexture.first];
+
+        for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
+        {
+            samplerTextureArray[textureUnit].set(zeroTexture.second.get());
+        }
+    }
+}
+
+void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler)
+{
+    mSamplers[textureUnit].set(sampler);
+}
+
+GLuint State::getSamplerId(GLuint textureUnit) const
+{
+    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 (size_t textureUnit = 0; textureUnit < mSamplers.size(); textureUnit++)
+    {
+        BindingPointer<Sampler> &samplerBinding = mSamplers[textureUnit];
+        if (samplerBinding.id() == sampler)
+        {
+            samplerBinding.set(nullptr);
+        }
+    }
+}
+
+void State::setRenderbufferBinding(Renderbuffer *renderbuffer)
+{
+    mRenderbuffer.set(renderbuffer);
+}
+
+GLuint State::getRenderbufferId() const
+{
+    return mRenderbuffer.id();
+}
+
+Renderbuffer *State::getCurrentRenderbuffer() const
+{
+    return mRenderbuffer.get();
+}
+
+void State::detachRenderbuffer(const Context *context, GLuint renderbuffer)
+{
+    // [OpenGL ES 2.0.24] section 4.4 page 109:
+    // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
+    // had been executed with the target RENDERBUFFER and name of zero.
+
+    if (mRenderbuffer.id() == renderbuffer)
+    {
+        mRenderbuffer.set(nullptr);
+    }
+
+    // [OpenGL ES 2.0.24] section 4.4 page 111:
+    // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
+    // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
+    // point to which this image was attached in the currently bound framebuffer.
+
+    Framebuffer *readFramebuffer = mReadFramebuffer;
+    Framebuffer *drawFramebuffer = mDrawFramebuffer;
+
+    if (readFramebuffer)
+    {
+        readFramebuffer->detachRenderbuffer(context, renderbuffer);
+    }
+
+    if (drawFramebuffer && drawFramebuffer != readFramebuffer)
+    {
+        drawFramebuffer->detachRenderbuffer(context, renderbuffer);
+    }
+
+}
+
+void State::setReadFramebufferBinding(Framebuffer *framebuffer)
+{
+    if (mReadFramebuffer == framebuffer)
+        return;
+
+    mReadFramebuffer = framebuffer;
+    mDirtyBits.set(DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
+
+    if (mReadFramebuffer && mReadFramebuffer->hasAnyDirtyBit())
+    {
+        mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+    }
+}
+
+void State::setDrawFramebufferBinding(Framebuffer *framebuffer)
+{
+    if (mDrawFramebuffer == framebuffer)
+        return;
+
+    mDrawFramebuffer = framebuffer;
+    mDirtyBits.set(DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
+
+    if (mDrawFramebuffer && mDrawFramebuffer->hasAnyDirtyBit())
+    {
+        mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+    }
+}
+
+Framebuffer *State::getTargetFramebuffer(GLenum target) const
+{
+    switch (target)
+    {
+        case GL_READ_FRAMEBUFFER_ANGLE:
+            return mReadFramebuffer;
+        case GL_DRAW_FRAMEBUFFER_ANGLE:
+        case GL_FRAMEBUFFER:
+            return mDrawFramebuffer;
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+}
+
+Framebuffer *State::getReadFramebuffer() const
+{
+    return mReadFramebuffer;
+}
+
+Framebuffer *State::getDrawFramebuffer() const
+{
+    return mDrawFramebuffer;
+}
+
+bool State::removeReadFramebufferBinding(GLuint framebuffer)
+{
+    if (mReadFramebuffer != nullptr &&
+        mReadFramebuffer->id() == framebuffer)
+    {
+        setReadFramebufferBinding(nullptr);
+        return true;
+    }
+
+    return false;
+}
+
+bool State::removeDrawFramebufferBinding(GLuint framebuffer)
+{
+    if (mReadFramebuffer != nullptr &&
+        mDrawFramebuffer->id() == framebuffer)
+    {
+        setDrawFramebufferBinding(nullptr);
+        return true;
+    }
+
+    return false;
+}
+
+void State::setVertexArrayBinding(VertexArray *vertexArray)
+{
+    mVertexArray = vertexArray;
+    mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
+
+    if (mVertexArray && mVertexArray->hasAnyDirtyBit())
+    {
+        mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+    }
+}
+
+GLuint State::getVertexArrayId() const
+{
+    ASSERT(mVertexArray != nullptr);
+    return mVertexArray->id();
+}
+
+VertexArray *State::getVertexArray() const
+{
+    ASSERT(mVertexArray != nullptr);
+    return mVertexArray;
+}
+
+bool State::removeVertexArrayBinding(GLuint vertexArray)
+{
+    if (mVertexArray->id() == vertexArray)
+    {
+        mVertexArray = nullptr;
+        mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
+        mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+        return true;
+    }
+
+    return false;
+}
+
+void State::setElementArrayBuffer(Buffer *buffer)
+{
+    getVertexArray()->setElementArrayBuffer(buffer);
+    mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::bindVertexBuffer(GLuint bindingIndex,
+                             Buffer *boundBuffer,
+                             GLintptr offset,
+                             GLsizei stride)
+{
+    getVertexArray()->bindVertexBuffer(bindingIndex, boundBuffer, offset, stride);
+    mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
+{
+    getVertexArray()->setVertexAttribBinding(attribIndex, bindingIndex);
+    mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribFormat(GLuint attribIndex,
+                                  GLint size,
+                                  GLenum type,
+                                  bool normalized,
+                                  bool pureInteger,
+                                  GLuint relativeOffset)
+{
+    getVertexArray()->setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger,
+                                            relativeOffset);
+    mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+{
+    getVertexArray()->setVertexBindingDivisor(bindingIndex, divisor);
+    mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setProgram(const Context *context, Program *newProgram)
+{
+    if (mProgram != newProgram)
+    {
+        if (mProgram)
+        {
+            mProgram->release(context);
+        }
+
+        mProgram = newProgram;
+
+        if (mProgram)
+        {
+            newProgram->addRef();
+        }
+    }
+}
+
+Program *State::getProgram() const
+{
+    return mProgram;
+}
+
+void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback)
+{
+    mTransformFeedback.set(transformFeedback);
+}
+
+TransformFeedback *State::getCurrentTransformFeedback() const
+{
+    return mTransformFeedback.get();
+}
+
+bool State::isTransformFeedbackActiveUnpaused() const
+{
+    gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
+    return curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused();
+}
+
+bool State::removeTransformFeedbackBinding(GLuint transformFeedback)
+{
+    if (mTransformFeedback.id() == transformFeedback)
+    {
+        mTransformFeedback.set(nullptr);
+        return true;
+    }
+
+    return false;
+}
+
+bool State::isQueryActive(const GLenum type) const
+{
+    for (auto &iter : mActiveQueries)
+    {
+        const Query *query = iter.second.get();
+        if (query != nullptr && ActiveQueryType(query->getType()) == ActiveQueryType(type))
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool State::isQueryActive(Query *query) const
+{
+    for (auto &iter : mActiveQueries)
+    {
+        if (iter.second.get() == query)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void State::setActiveQuery(GLenum target, Query *query)
+{
+    mActiveQueries[target].set(query);
+}
+
+GLuint State::getActiveQueryId(GLenum target) const
+{
+    const Query *query = getActiveQuery(target);
+    return (query ? query->id() : 0u);
+}
+
+Query *State::getActiveQuery(GLenum target) const
+{
+    const auto it = mActiveQueries.find(target);
+
+    // All query types should already exist in the activeQueries map
+    ASSERT(it != mActiveQueries.end());
+
+    return it->second.get();
+}
+
+void State::setArrayBufferBinding(Buffer *buffer)
+{
+    mArrayBuffer.set(buffer);
+}
+
+GLuint State::getArrayBufferId() const
+{
+    return mArrayBuffer.id();
+}
+
+void State::setDrawIndirectBufferBinding(Buffer *buffer)
+{
+    mDrawIndirectBuffer.set(buffer);
+    mDirtyBits.set(DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
+}
+
+void State::setGenericUniformBufferBinding(Buffer *buffer)
+{
+    mGenericUniformBuffer.set(buffer);
+}
+
+void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size)
+{
+    mUniformBuffers[index].set(buffer, offset, size);
+}
+
+const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
+{
+    ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+    return mUniformBuffers[index];
+}
+
+void State::setGenericAtomicCounterBufferBinding(Buffer *buffer)
+{
+    mGenericAtomicCounterBuffer.set(buffer);
+}
+
+void State::setIndexedAtomicCounterBufferBinding(GLuint index,
+                                                 Buffer *buffer,
+                                                 GLintptr offset,
+                                                 GLsizeiptr size)
+{
+    ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+    mAtomicCounterBuffers[index].set(buffer, offset, size);
+}
+
+const OffsetBindingPointer<Buffer> &State::getIndexedAtomicCounterBuffer(size_t index) const
+{
+    ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+    return mAtomicCounterBuffers[index];
+}
+
+void State::setGenericShaderStorageBufferBinding(Buffer *buffer)
+{
+    mGenericShaderStorageBuffer.set(buffer);
+}
+
+void State::setIndexedShaderStorageBufferBinding(GLuint index,
+                                                 Buffer *buffer,
+                                                 GLintptr offset,
+                                                 GLsizeiptr size)
+{
+    ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+    mShaderStorageBuffers[index].set(buffer, offset, size);
+}
+
+const OffsetBindingPointer<Buffer> &State::getIndexedShaderStorageBuffer(size_t index) const
+{
+    ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+    return mShaderStorageBuffers[index];
+}
+
+void State::setCopyReadBufferBinding(Buffer *buffer)
+{
+    mCopyReadBuffer.set(buffer);
+}
+
+void State::setCopyWriteBufferBinding(Buffer *buffer)
+{
+    mCopyWriteBuffer.set(buffer);
+}
+
+void State::setPixelPackBufferBinding(Buffer *buffer)
+{
+    mPack.pixelBuffer.set(buffer);
+    mDirtyBits.set(DIRTY_BIT_PACK_BUFFER_BINDING);
+}
+
+void State::setPixelUnpackBufferBinding(Buffer *buffer)
+{
+    mUnpack.pixelBuffer.set(buffer);
+    mDirtyBits.set(DIRTY_BIT_UNPACK_BUFFER_BINDING);
+}
+
+Buffer *State::getTargetBuffer(GLenum target) const
+{
+    switch (target)
+    {
+      case GL_ARRAY_BUFFER:              return mArrayBuffer.get();
+      case GL_COPY_READ_BUFFER:          return mCopyReadBuffer.get();
+      case GL_COPY_WRITE_BUFFER:         return mCopyWriteBuffer.get();
+      case GL_ELEMENT_ARRAY_BUFFER:      return getVertexArray()->getElementArrayBuffer().get();
+      case GL_PIXEL_PACK_BUFFER:         return mPack.pixelBuffer.get();
+      case GL_PIXEL_UNPACK_BUFFER:       return mUnpack.pixelBuffer.get();
+      case GL_TRANSFORM_FEEDBACK_BUFFER: return mTransformFeedback->getGenericBuffer().get();
+      case GL_UNIFORM_BUFFER:            return mGenericUniformBuffer.get();
+      case GL_ATOMIC_COUNTER_BUFFER:
+          return mGenericAtomicCounterBuffer.get();
+      case GL_SHADER_STORAGE_BUFFER:
+          return mGenericShaderStorageBuffer.get();
+      case GL_DRAW_INDIRECT_BUFFER:
+          return mDrawIndirectBuffer.get();
+      default:
+          UNREACHABLE();
+          return nullptr;
+    }
+}
+
+void State::detachBuffer(GLuint bufferName)
+{
+    BindingPointer<Buffer> *buffers[] = {
+        &mArrayBuffer,        &mGenericAtomicCounterBuffer, &mCopyReadBuffer,
+        &mCopyWriteBuffer,    &mDrawIndirectBuffer,         &mPack.pixelBuffer,
+        &mUnpack.pixelBuffer, &mGenericUniformBuffer,       &mGenericShaderStorageBuffer};
+    for (auto buffer : buffers)
+    {
+        if (buffer->id() == bufferName)
+        {
+            buffer->set(nullptr);
+        }
+    }
+
+    TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
+    if (curTransformFeedback)
+    {
+        curTransformFeedback->detachBuffer(bufferName);
+    }
+
+    getVertexArray()->detachBuffer(bufferName);
+}
+
+void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
+{
+    getVertexArray()->enableAttribute(attribNum, enabled);
+    mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribf(GLuint index, const GLfloat values[4])
+{
+    ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
+    mVertexAttribCurrentValues[index].setFloatValues(values);
+    mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
+}
+
+void State::setVertexAttribu(GLuint index, const GLuint values[4])
+{
+    ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
+    mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
+    mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
+}
+
+void State::setVertexAttribi(GLuint index, const GLint values[4])
+{
+    ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
+    mVertexAttribCurrentValues[index].setIntValues(values);
+    mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
+}
+
+void State::setVertexAttribState(unsigned int attribNum,
+                                 Buffer *boundBuffer,
+                                 GLint size,
+                                 GLenum type,
+                                 bool normalized,
+                                 bool pureInteger,
+                                 GLsizei stride,
+                                 const void *pointer)
+{
+    getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer);
+    mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+    getVertexArray()->setVertexAttribDivisor(index, divisor);
+    mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(size_t attribNum) const
+{
+    ASSERT(attribNum < mVertexAttribCurrentValues.size());
+    return mVertexAttribCurrentValues[attribNum];
+}
+
+const void *State::getVertexAttribPointer(unsigned int attribNum) const
+{
+    return getVertexArray()->getVertexAttribute(attribNum).pointer;
+}
+
+void State::setPackAlignment(GLint alignment)
+{
+    mPack.alignment = alignment;
+    mDirtyBits.set(DIRTY_BIT_PACK_ALIGNMENT);
+}
+
+GLint State::getPackAlignment() const
+{
+    return mPack.alignment;
+}
+
+void State::setPackReverseRowOrder(bool reverseRowOrder)
+{
+    mPack.reverseRowOrder = reverseRowOrder;
+    mDirtyBits.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
+}
+
+bool State::getPackReverseRowOrder() const
+{
+    return mPack.reverseRowOrder;
+}
+
+void State::setPackRowLength(GLint rowLength)
+{
+    mPack.rowLength = rowLength;
+    mDirtyBits.set(DIRTY_BIT_PACK_ROW_LENGTH);
+}
+
+GLint State::getPackRowLength() const
+{
+    return mPack.rowLength;
+}
+
+void State::setPackSkipRows(GLint skipRows)
+{
+    mPack.skipRows = skipRows;
+    mDirtyBits.set(DIRTY_BIT_PACK_SKIP_ROWS);
+}
+
+GLint State::getPackSkipRows() const
+{
+    return mPack.skipRows;
+}
+
+void State::setPackSkipPixels(GLint skipPixels)
+{
+    mPack.skipPixels = skipPixels;
+    mDirtyBits.set(DIRTY_BIT_PACK_SKIP_PIXELS);
+}
+
+GLint State::getPackSkipPixels() const
+{
+    return mPack.skipPixels;
+}
+
+const PixelPackState &State::getPackState() const
+{
+    return mPack;
+}
+
+PixelPackState &State::getPackState()
+{
+    return mPack;
+}
+
+void State::setUnpackAlignment(GLint alignment)
+{
+    mUnpack.alignment = alignment;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_ALIGNMENT);
+}
+
+GLint State::getUnpackAlignment() const
+{
+    return mUnpack.alignment;
+}
+
+void State::setUnpackRowLength(GLint rowLength)
+{
+    mUnpack.rowLength = rowLength;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_ROW_LENGTH);
+}
+
+GLint State::getUnpackRowLength() const
+{
+    return mUnpack.rowLength;
+}
+
+void State::setUnpackImageHeight(GLint imageHeight)
+{
+    mUnpack.imageHeight = imageHeight;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+}
+
+GLint State::getUnpackImageHeight() const
+{
+    return mUnpack.imageHeight;
+}
+
+void State::setUnpackSkipImages(GLint skipImages)
+{
+    mUnpack.skipImages = skipImages;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_IMAGES);
+}
+
+GLint State::getUnpackSkipImages() const
+{
+    return mUnpack.skipImages;
+}
+
+void State::setUnpackSkipRows(GLint skipRows)
+{
+    mUnpack.skipRows = skipRows;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_ROWS);
+}
+
+GLint State::getUnpackSkipRows() const
+{
+    return mUnpack.skipRows;
+}
+
+void State::setUnpackSkipPixels(GLint skipPixels)
+{
+    mUnpack.skipPixels = skipPixels;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_PIXELS);
+}
+
+GLint State::getUnpackSkipPixels() const
+{
+    return mUnpack.skipPixels;
+}
+
+const PixelUnpackState &State::getUnpackState() const
+{
+    return mUnpack;
+}
+
+PixelUnpackState &State::getUnpackState()
+{
+    return mUnpack;
+}
+
+const Debug &State::getDebug() const
+{
+    return mDebug;
+}
+
+Debug &State::getDebug()
+{
+    return mDebug;
+}
+
+void State::setCoverageModulation(GLenum components)
+{
+    mCoverageModulation = components;
+    mDirtyBits.set(DIRTY_BIT_COVERAGE_MODULATION);
+}
+
+GLenum State::getCoverageModulation() const
+{
+    return mCoverageModulation;
+}
+
+void State::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
+{
+    if (matrixMode == GL_PATH_MODELVIEW_CHROMIUM)
+    {
+        memcpy(mPathMatrixMV, matrix, 16 * sizeof(GLfloat));
+        mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_MV);
+    }
+    else if (matrixMode == GL_PATH_PROJECTION_CHROMIUM)
+    {
+        memcpy(mPathMatrixProj, matrix, 16 * sizeof(GLfloat));
+        mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ);
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+}
+
+const GLfloat *State::getPathRenderingMatrix(GLenum which) const
+{
+    if (which == GL_PATH_MODELVIEW_MATRIX_CHROMIUM)
+    {
+        return mPathMatrixMV;
+    }
+    else if (which == GL_PATH_PROJECTION_MATRIX_CHROMIUM)
+    {
+        return mPathMatrixProj;
+    }
+
+    UNREACHABLE();
+    return nullptr;
+}
+
+void State::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+    mPathStencilFunc = func;
+    mPathStencilRef  = ref;
+    mPathStencilMask = mask;
+    mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_STENCIL_STATE);
+}
+
+GLenum State::getPathStencilFunc() const
+{
+    return mPathStencilFunc;
+}
+
+GLint State::getPathStencilRef() const
+{
+    return mPathStencilRef;
+}
+
+GLuint State::getPathStencilMask() const
+{
+    return mPathStencilMask;
+}
+
+void State::setFramebufferSRGB(bool sRGB)
+{
+    mFramebufferSRGB = sRGB;
+    mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB);
+}
+
+bool State::getFramebufferSRGB() const
+{
+    return mFramebufferSRGB;
+}
+
+void State::getBooleanv(GLenum pname, GLboolean *params)
+{
+    switch (pname)
+    {
+      case GL_SAMPLE_COVERAGE_INVERT:    *params = mSampleCoverageInvert;         break;
+      case GL_DEPTH_WRITEMASK:           *params = mDepthStencil.depthMask;       break;
+      case GL_COLOR_WRITEMASK:
+        params[0] = mBlend.colorMaskRed;
+        params[1] = mBlend.colorMaskGreen;
+        params[2] = mBlend.colorMaskBlue;
+        params[3] = mBlend.colorMaskAlpha;
+        break;
+      case GL_CULL_FACE:                 *params = mRasterizer.cullFace;          break;
+      case GL_POLYGON_OFFSET_FILL:       *params = mRasterizer.polygonOffsetFill; break;
+      case GL_SAMPLE_ALPHA_TO_COVERAGE:  *params = mBlend.sampleAlphaToCoverage;  break;
+      case GL_SAMPLE_COVERAGE:           *params = mSampleCoverage;               break;
+      case GL_SCISSOR_TEST:              *params = mScissorTest;                  break;
+      case GL_STENCIL_TEST:              *params = mDepthStencil.stencilTest;     break;
+      case GL_DEPTH_TEST:                *params = mDepthStencil.depthTest;       break;
+      case GL_BLEND:                     *params = mBlend.blend;                  break;
+      case GL_DITHER:                    *params = mBlend.dither;                 break;
+      case GL_TRANSFORM_FEEDBACK_ACTIVE: *params = getCurrentTransformFeedback()->isActive() ? GL_TRUE : GL_FALSE; break;
+      case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused() ? GL_TRUE : GL_FALSE; break;
+      case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+          *params = mPrimitiveRestart;
+          break;
+      case GL_RASTERIZER_DISCARD:
+          *params = isRasterizerDiscardEnabled() ? GL_TRUE : GL_FALSE;
+          break;
+      case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+          *params = mDebug.isOutputSynchronous() ? GL_TRUE : GL_FALSE;
+          break;
+      case GL_DEBUG_OUTPUT:
+          *params = mDebug.isOutputEnabled() ? GL_TRUE : GL_FALSE;
+          break;
+      case GL_MULTISAMPLE_EXT:
+          *params = mMultiSampling;
+          break;
+      case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+          *params = mSampleAlphaToOne;
+          break;
+      case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+          *params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
+          break;
+      case GL_CLIENT_ARRAYS_ANGLE:
+          *params = areClientArraysEnabled() ? GL_TRUE : GL_FALSE;
+          break;
+      case GL_FRAMEBUFFER_SRGB_EXT:
+          *params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE;
+          break;
+      case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+          *params = mRobustResourceInit ? GL_TRUE : GL_FALSE;
+          break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+}
+
+void State::getFloatv(GLenum pname, GLfloat *params)
+{
+    // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
+    // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
+    // GetIntegerv as its native query function. As it would require conversion in any
+    // case, this should make no difference to the calling application.
+    switch (pname)
+    {
+      case GL_LINE_WIDTH:               *params = mLineWidth;                         break;
+      case GL_SAMPLE_COVERAGE_VALUE:    *params = mSampleCoverageValue;               break;
+      case GL_DEPTH_CLEAR_VALUE:        *params = mDepthClearValue;                   break;
+      case GL_POLYGON_OFFSET_FACTOR:    *params = mRasterizer.polygonOffsetFactor;    break;
+      case GL_POLYGON_OFFSET_UNITS:     *params = mRasterizer.polygonOffsetUnits;     break;
+      case GL_DEPTH_RANGE:
+        params[0] = mNearZ;
+        params[1] = mFarZ;
+        break;
+      case GL_COLOR_CLEAR_VALUE:
+        params[0] = mColorClearValue.red;
+        params[1] = mColorClearValue.green;
+        params[2] = mColorClearValue.blue;
+        params[3] = mColorClearValue.alpha;
+        break;
+      case GL_BLEND_COLOR:
+        params[0] = mBlendColor.red;
+        params[1] = mBlendColor.green;
+        params[2] = mBlendColor.blue;
+        params[3] = mBlendColor.alpha;
+        break;
+      case GL_MULTISAMPLE_EXT:
+        *params = static_cast<GLfloat>(mMultiSampling);
+        break;
+      case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+        *params = static_cast<GLfloat>(mSampleAlphaToOne);
+      case GL_COVERAGE_MODULATION_CHROMIUM:
+          params[0] = static_cast<GLfloat>(mCoverageModulation);
+          break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+}
+
+void State::getIntegerv(const Context *context, GLenum pname, GLint *params)
+{
+    if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
+    {
+        unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
+        ASSERT(colorAttachment < mMaxDrawBuffers);
+        Framebuffer *framebuffer = mDrawFramebuffer;
+        *params = framebuffer->getDrawBufferState(colorAttachment);
+        return;
+    }
+
+    // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
+    // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
+    // GetIntegerv as its native query function. As it would require conversion in any
+    // case, this should make no difference to the calling application. You may find it in
+    // State::getFloatv.
+    switch (pname)
+    {
+      case GL_ARRAY_BUFFER_BINDING:                     *params = mArrayBuffer.id();                              break;
+      case GL_DRAW_INDIRECT_BUFFER_BINDING:
+          *params = mDrawIndirectBuffer.id();
+          break;
+      case GL_ELEMENT_ARRAY_BUFFER_BINDING:             *params = getVertexArray()->getElementArrayBuffer().id(); break;
+        //case GL_FRAMEBUFFER_BINDING:                    // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
+      case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:           *params = mDrawFramebuffer->id();                         break;
+      case GL_READ_FRAMEBUFFER_BINDING_ANGLE:           *params = mReadFramebuffer->id();                         break;
+      case GL_RENDERBUFFER_BINDING:                     *params = mRenderbuffer.id();                             break;
+      case GL_VERTEX_ARRAY_BINDING:                     *params = mVertexArray->id();                             break;
+      case GL_CURRENT_PROGRAM:                          *params = mProgram ? mProgram->id() : 0;                  break;
+      case GL_PACK_ALIGNMENT:                           *params = mPack.alignment;                                break;
+      case GL_PACK_REVERSE_ROW_ORDER_ANGLE:             *params = mPack.reverseRowOrder;                          break;
+      case GL_PACK_ROW_LENGTH:
+          *params = mPack.rowLength;
+          break;
+      case GL_PACK_SKIP_ROWS:
+          *params = mPack.skipRows;
+          break;
+      case GL_PACK_SKIP_PIXELS:
+          *params = mPack.skipPixels;
+          break;
+      case GL_UNPACK_ALIGNMENT:                         *params = mUnpack.alignment;                              break;
+      case GL_UNPACK_ROW_LENGTH:                        *params = mUnpack.rowLength;                              break;
+      case GL_UNPACK_IMAGE_HEIGHT:
+          *params = mUnpack.imageHeight;
+          break;
+      case GL_UNPACK_SKIP_IMAGES:
+          *params = mUnpack.skipImages;
+          break;
+      case GL_UNPACK_SKIP_ROWS:
+          *params = mUnpack.skipRows;
+          break;
+      case GL_UNPACK_SKIP_PIXELS:
+          *params = mUnpack.skipPixels;
+          break;
+      case GL_GENERATE_MIPMAP_HINT:                     *params = mGenerateMipmapHint;                            break;
+      case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:      *params = mFragmentShaderDerivativeHint;                  break;
+      case GL_ACTIVE_TEXTURE:
+          *params = (static_cast<GLint>(mActiveSampler) + GL_TEXTURE0);
+          break;
+      case GL_STENCIL_FUNC:                             *params = mDepthStencil.stencilFunc;                      break;
+      case GL_STENCIL_REF:                              *params = mStencilRef;                                    break;
+      case GL_STENCIL_VALUE_MASK:                       *params = clampToInt(mDepthStencil.stencilMask);          break;
+      case GL_STENCIL_BACK_FUNC:                        *params = mDepthStencil.stencilBackFunc;                  break;
+      case GL_STENCIL_BACK_REF:                         *params = mStencilBackRef;                                break;
+      case GL_STENCIL_BACK_VALUE_MASK:                  *params = clampToInt(mDepthStencil.stencilBackMask);      break;
+      case GL_STENCIL_FAIL:                             *params = mDepthStencil.stencilFail;                      break;
+      case GL_STENCIL_PASS_DEPTH_FAIL:                  *params = mDepthStencil.stencilPassDepthFail;             break;
+      case GL_STENCIL_PASS_DEPTH_PASS:                  *params = mDepthStencil.stencilPassDepthPass;             break;
+      case GL_STENCIL_BACK_FAIL:                        *params = mDepthStencil.stencilBackFail;                  break;
+      case GL_STENCIL_BACK_PASS_DEPTH_FAIL:             *params = mDepthStencil.stencilBackPassDepthFail;         break;
+      case GL_STENCIL_BACK_PASS_DEPTH_PASS:             *params = mDepthStencil.stencilBackPassDepthPass;         break;
+      case GL_DEPTH_FUNC:                               *params = mDepthStencil.depthFunc;                        break;
+      case GL_BLEND_SRC_RGB:                            *params = mBlend.sourceBlendRGB;                          break;
+      case GL_BLEND_SRC_ALPHA:                          *params = mBlend.sourceBlendAlpha;                        break;
+      case GL_BLEND_DST_RGB:                            *params = mBlend.destBlendRGB;                            break;
+      case GL_BLEND_DST_ALPHA:                          *params = mBlend.destBlendAlpha;                          break;
+      case GL_BLEND_EQUATION_RGB:                       *params = mBlend.blendEquationRGB;                        break;
+      case GL_BLEND_EQUATION_ALPHA:                     *params = mBlend.blendEquationAlpha;                      break;
+      case GL_STENCIL_WRITEMASK:                        *params = clampToInt(mDepthStencil.stencilWritemask);     break;
+      case GL_STENCIL_BACK_WRITEMASK:                   *params = clampToInt(mDepthStencil.stencilBackWritemask); break;
+      case GL_STENCIL_CLEAR_VALUE:                      *params = mStencilClearValue;                             break;
+      case GL_IMPLEMENTATION_COLOR_READ_TYPE:           *params = mReadFramebuffer->getImplementationColorReadType();   break;
+      case GL_IMPLEMENTATION_COLOR_READ_FORMAT:         *params = mReadFramebuffer->getImplementationColorReadFormat(); break;
+      case GL_SAMPLE_BUFFERS:
+      case GL_SAMPLES:
+        {
+            gl::Framebuffer *framebuffer = mDrawFramebuffer;
+            if (framebuffer->checkStatus(context) == GL_FRAMEBUFFER_COMPLETE)
+            {
+                switch (pname)
+                {
+                  case GL_SAMPLE_BUFFERS:
+                      if (framebuffer->getSamples(context) != 0)
+                      {
+                          *params = 1;
+                    }
+                    else
+                    {
+                        *params = 0;
+                    }
+                    break;
+                  case GL_SAMPLES:
+                      *params = framebuffer->getSamples(context);
+                      break;
+                }
+            }
+            else
+            {
+                *params = 0;
+            }
+        }
+        break;
+      case GL_VIEWPORT:
+        params[0] = mViewport.x;
+        params[1] = mViewport.y;
+        params[2] = mViewport.width;
+        params[3] = mViewport.height;
+        break;
+      case GL_SCISSOR_BOX:
+        params[0] = mScissor.x;
+        params[1] = mScissor.y;
+        params[2] = mScissor.width;
+        params[3] = mScissor.height;
+        break;
+      case GL_CULL_FACE_MODE:                   *params = mRasterizer.cullMode;   break;
+      case GL_FRONT_FACE:                       *params = mRasterizer.frontFace;  break;
+      case GL_RED_BITS:
+      case GL_GREEN_BITS:
+      case GL_BLUE_BITS:
+      case GL_ALPHA_BITS:
+        {
+            gl::Framebuffer *framebuffer = getDrawFramebuffer();
+            const gl::FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer();
+
+            if (colorbuffer)
+            {
+                switch (pname)
+                {
+                case GL_RED_BITS:   *params = colorbuffer->getRedSize();      break;
+                case GL_GREEN_BITS: *params = colorbuffer->getGreenSize();    break;
+                case GL_BLUE_BITS:  *params = colorbuffer->getBlueSize();     break;
+                case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize();    break;
+                }
+            }
+            else
+            {
+                *params = 0;
+            }
+        }
+        break;
+      case GL_DEPTH_BITS:
+        {
+            const gl::Framebuffer *framebuffer = getDrawFramebuffer();
+            const gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer();
+
+            if (depthbuffer)
+            {
+                *params = depthbuffer->getDepthSize();
+            }
+            else
+            {
+                *params = 0;
+            }
+        }
+        break;
+      case GL_STENCIL_BITS:
+        {
+            const gl::Framebuffer *framebuffer = getDrawFramebuffer();
+            const gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer();
+
+            if (stencilbuffer)
+            {
+                *params = stencilbuffer->getStencilSize();
+            }
+            else
+            {
+                *params = 0;
+            }
+        }
+        break;
+      case GL_TEXTURE_BINDING_2D:
+        ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+        *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D);
+        break;
+      case GL_TEXTURE_BINDING_CUBE_MAP:
+        ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+        *params =
+            getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_CUBE_MAP);
+        break;
+      case GL_TEXTURE_BINDING_3D:
+        ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+        *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_3D);
+        break;
+      case GL_TEXTURE_BINDING_2D_ARRAY:
+        ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+        *params =
+            getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D_ARRAY);
+        break;
+      case GL_TEXTURE_BINDING_EXTERNAL_OES:
+          ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+          *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+                                        GL_TEXTURE_EXTERNAL_OES);
+          break;
+      case GL_UNIFORM_BUFFER_BINDING:
+        *params = mGenericUniformBuffer.id();
+        break;
+      case GL_TRANSFORM_FEEDBACK_BINDING:
+        *params = mTransformFeedback.id();
+        break;
+      case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+        *params = mTransformFeedback->getGenericBuffer().id();
+        break;
+      case GL_COPY_READ_BUFFER_BINDING:
+        *params = mCopyReadBuffer.id();
+        break;
+      case GL_COPY_WRITE_BUFFER_BINDING:
+        *params = mCopyWriteBuffer.id();
+        break;
+      case GL_PIXEL_PACK_BUFFER_BINDING:
+        *params = mPack.pixelBuffer.id();
+        break;
+      case GL_PIXEL_UNPACK_BUFFER_BINDING:
+        *params = mUnpack.pixelBuffer.id();
+        break;
+      case GL_READ_BUFFER:
+          *params = mReadFramebuffer->getReadBufferState();
+          break;
+      case GL_SAMPLER_BINDING:
+          ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+          *params = getSamplerId(static_cast<GLuint>(mActiveSampler));
+          break;
+      case GL_DEBUG_LOGGED_MESSAGES:
+          *params = static_cast<GLint>(mDebug.getMessageCount());
+          break;
+      case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
+          *params = static_cast<GLint>(mDebug.getNextMessageLength());
+          break;
+      case GL_DEBUG_GROUP_STACK_DEPTH:
+          *params = static_cast<GLint>(mDebug.getGroupStackDepth());
+          break;
+      case GL_MULTISAMPLE_EXT:
+          *params = static_cast<GLint>(mMultiSampling);
+          break;
+      case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+          *params = static_cast<GLint>(mSampleAlphaToOne);
+      case GL_COVERAGE_MODULATION_CHROMIUM:
+          *params = static_cast<GLint>(mCoverageModulation);
+          break;
+      case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+          *params = mGenericAtomicCounterBuffer.id();
+          break;
+      case GL_SHADER_STORAGE_BUFFER_BINDING:
+          *params = mGenericShaderStorageBuffer.id();
+          break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+}
+
+void State::getPointerv(GLenum pname, void **params) const
+{
+    switch (pname)
+    {
+        case GL_DEBUG_CALLBACK_FUNCTION:
+            *params = reinterpret_cast<void *>(mDebug.getCallback());
+            break;
+        case GL_DEBUG_CALLBACK_USER_PARAM:
+            *params = const_cast<void *>(mDebug.getUserParam());
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void State::getIntegeri_v(GLenum target, GLuint index, GLint *data)
+{
+    switch (target)
+    {
+      case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+          ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+          *data = mTransformFeedback->getIndexedBuffer(index).id();
+          break;
+      case GL_UNIFORM_BUFFER_BINDING:
+          ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+          *data = mUniformBuffers[index].id();
+          break;
+      case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+          ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+          *data = mAtomicCounterBuffers[index].id();
+          break;
+      case GL_SHADER_STORAGE_BUFFER_BINDING:
+          ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+          *data = mShaderStorageBuffers[index].id();
+          break;
+      case GL_VERTEX_BINDING_BUFFER:
+          ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+          *data = mVertexArray->getVertexBinding(index).buffer.id();
+          break;
+      case GL_VERTEX_BINDING_DIVISOR:
+          ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+          *data = mVertexArray->getVertexBinding(index).divisor;
+          break;
+      case GL_VERTEX_BINDING_OFFSET:
+          ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+          *data = static_cast<GLuint>(mVertexArray->getVertexBinding(index).offset);
+          break;
+      case GL_VERTEX_BINDING_STRIDE:
+          ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+          *data = mVertexArray->getVertexBinding(index).stride;
+          break;
+      default:
+          UNREACHABLE();
+          break;
+    }
+}
+
+void State::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
+{
+    switch (target)
+    {
+      case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+          ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+          *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
+          break;
+      case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+          ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+          *data = mTransformFeedback->getIndexedBuffer(index).getSize();
+          break;
+      case GL_UNIFORM_BUFFER_START:
+          ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+          *data = mUniformBuffers[index].getOffset();
+          break;
+      case GL_UNIFORM_BUFFER_SIZE:
+          ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+          *data = mUniformBuffers[index].getSize();
+          break;
+      case GL_ATOMIC_COUNTER_BUFFER_START:
+          ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+          *data = mAtomicCounterBuffers[index].getOffset();
+          break;
+      case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+          ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+          *data = mAtomicCounterBuffers[index].getSize();
+          break;
+      case GL_SHADER_STORAGE_BUFFER_START:
+          ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+          *data = mShaderStorageBuffers[index].getOffset();
+          break;
+      case GL_SHADER_STORAGE_BUFFER_SIZE:
+          ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+          *data = mShaderStorageBuffers[index].getSize();
+          break;
+      default:
+          UNREACHABLE();
+          break;
+    }
+}
+
+void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+    UNREACHABLE();
+}
+
+bool State::hasMappedBuffer(GLenum target) const
+{
+    if (target == GL_ARRAY_BUFFER)
+    {
+        const VertexArray *vao     = getVertexArray();
+        const auto &vertexAttribs = vao->getVertexAttributes();
+        const auto &vertexBindings = vao->getVertexBindings();
+        size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
+        for (size_t attribIndex = 0; attribIndex < maxEnabledAttrib; attribIndex++)
+        {
+            const gl::VertexAttribute &vertexAttrib = vertexAttribs[attribIndex];
+            auto *boundBuffer = vertexBindings[vertexAttrib.bindingIndex].buffer.get();
+            if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped())
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+    else
+    {
+        Buffer *buffer = getTargetBuffer(target);
+        return (buffer && buffer->isMapped());
+    }
+}
+
+void State::syncDirtyObjects(const Context *context)
+{
+    if (!mDirtyObjects.any())
+        return;
+
+    syncDirtyObjects(context, mDirtyObjects);
+}
+
+void State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset)
+{
+    for (auto dirtyObject : bitset)
+    {
+        switch (dirtyObject)
+        {
+            case DIRTY_OBJECT_READ_FRAMEBUFFER:
+                ASSERT(mReadFramebuffer);
+                mReadFramebuffer->syncState(context);
+                break;
+            case DIRTY_OBJECT_DRAW_FRAMEBUFFER:
+                ASSERT(mDrawFramebuffer);
+                mDrawFramebuffer->syncState(context);
+                break;
+            case DIRTY_OBJECT_VERTEX_ARRAY:
+                ASSERT(mVertexArray);
+                mVertexArray->syncImplState(context);
+                break;
+            case DIRTY_OBJECT_PROGRAM:
+                // TODO(jmadill): implement this
+                break;
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+
+    mDirtyObjects &= ~bitset;
+}
+
+void State::syncDirtyObject(const Context *context, GLenum target)
+{
+    DirtyObjects localSet;
+
+    switch (target)
+    {
+        case GL_READ_FRAMEBUFFER:
+            localSet.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+            break;
+        case GL_DRAW_FRAMEBUFFER:
+            localSet.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+            break;
+        case GL_FRAMEBUFFER:
+            localSet.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+            localSet.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+            break;
+        case GL_VERTEX_ARRAY:
+            localSet.set(DIRTY_OBJECT_VERTEX_ARRAY);
+            break;
+        case GL_PROGRAM:
+            localSet.set(DIRTY_OBJECT_PROGRAM);
+            break;
+    }
+
+    syncDirtyObjects(context, localSet);
+}
+
+void State::setObjectDirty(GLenum target)
+{
+    switch (target)
+    {
+        case GL_READ_FRAMEBUFFER:
+            mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+            break;
+        case GL_DRAW_FRAMEBUFFER:
+            mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+            break;
+        case GL_FRAMEBUFFER:
+            mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+            mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+            break;
+        case GL_VERTEX_ARRAY:
+            mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+            break;
+        case GL_PROGRAM:
+            mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
+            break;
+    }
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/State.h b/src/third_party/angle/src/libANGLE/State.h
new file mode 100644
index 0000000..f6a018d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/State.h
@@ -0,0 +1,561 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// State.h: Defines the State class, encapsulating raw GL state
+
+#ifndef LIBANGLE_STATE_H_
+#define LIBANGLE_STATE_H_
+
+#include <bitset>
+#include <memory>
+
+#include "common/Color.h"
+#include "common/angleutils.h"
+#include "common/bitset_utils.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+class Query;
+class VertexArray;
+class Context;
+struct Caps;
+
+typedef std::map<GLenum, BindingPointer<Texture>> TextureMap;
+
+class State : angle::NonCopyable
+{
+  public:
+    State();
+    ~State();
+
+    void initialize(const Caps &caps,
+                    const Extensions &extensions,
+                    const Version &clientVersion,
+                    bool debug,
+                    bool bindGeneratesResource,
+                    bool clientArraysEnabled,
+                    bool robustResourceInit);
+    void reset(const Context *context);
+
+    // State chunk getters
+    const RasterizerState &getRasterizerState() const;
+    const BlendState &getBlendState() const;
+    const DepthStencilState &getDepthStencilState() const;
+
+    // Clear behavior setters & state parameter block generation function
+    void setColorClearValue(float red, float green, float blue, float alpha);
+    void setDepthClearValue(float depth);
+    void setStencilClearValue(int stencil);
+
+    const ColorF &getColorClearValue() const { return mColorClearValue; }
+    float getDepthClearValue() const { return mDepthClearValue; }
+    int getStencilClearValue() const { return mStencilClearValue; }
+
+    // Write mask manipulation
+    void setColorMask(bool red, bool green, bool blue, bool alpha);
+    void setDepthMask(bool mask);
+
+    // Discard toggle & query
+    bool isRasterizerDiscardEnabled() const;
+    void setRasterizerDiscard(bool enabled);
+
+    // Primitive restart
+    bool isPrimitiveRestartEnabled() const;
+    void setPrimitiveRestart(bool enabled);
+
+    // Face culling state manipulation
+    bool isCullFaceEnabled() const;
+    void setCullFace(bool enabled);
+    void setCullMode(GLenum mode);
+    void setFrontFace(GLenum front);
+
+    // Depth test state manipulation
+    bool isDepthTestEnabled() const;
+    void setDepthTest(bool enabled);
+    void setDepthFunc(GLenum depthFunc);
+    void setDepthRange(float zNear, float zFar);
+    float getNearPlane() const;
+    float getFarPlane() const;
+
+    // Blend state manipulation
+    bool isBlendEnabled() const;
+    void setBlend(bool enabled);
+    void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
+    void setBlendColor(float red, float green, float blue, float alpha);
+    void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);
+    const ColorF &getBlendColor() const;
+
+    // Stencil state maniupulation
+    bool isStencilTestEnabled() const;
+    void setStencilTest(bool enabled);
+    void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);
+    void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask);
+    void setStencilWritemask(GLuint stencilWritemask);
+    void setStencilBackWritemask(GLuint stencilBackWritemask);
+    void setStencilOperations(GLenum stencilFail,
+                              GLenum stencilPassDepthFail,
+                              GLenum stencilPassDepthPass);
+    void setStencilBackOperations(GLenum stencilBackFail,
+                                  GLenum stencilBackPassDepthFail,
+                                  GLenum stencilBackPassDepthPass);
+    GLint getStencilRef() const;
+    GLint getStencilBackRef() const;
+
+    // Depth bias/polygon offset state manipulation
+    bool isPolygonOffsetFillEnabled() const;
+    void setPolygonOffsetFill(bool enabled);
+    void setPolygonOffsetParams(GLfloat factor, GLfloat units);
+
+    // Multisample coverage state manipulation
+    bool isSampleAlphaToCoverageEnabled() const;
+    void setSampleAlphaToCoverage(bool enabled);
+    bool isSampleCoverageEnabled() const;
+    void setSampleCoverage(bool enabled);
+    void setSampleCoverageParams(GLfloat value, bool invert);
+    GLfloat getSampleCoverageValue() const;
+    bool getSampleCoverageInvert() const;
+
+    // Multisampling/alpha to one manipulation.
+    void setSampleAlphaToOne(bool enabled);
+    bool isSampleAlphaToOneEnabled() const;
+    void setMultisampling(bool enabled);
+    bool isMultisamplingEnabled() const;
+
+    // Scissor test state toggle & query
+    bool isScissorTestEnabled() const;
+    void setScissorTest(bool enabled);
+    void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
+    const Rectangle &getScissor() const;
+
+    // Dither state toggle & query
+    bool isDitherEnabled() const;
+    void setDither(bool enabled);
+
+    // Generic state toggle & query
+    void setEnableFeature(GLenum feature, bool enabled);
+    bool getEnableFeature(GLenum feature) const;
+
+    // Line width state setter
+    void setLineWidth(GLfloat width);
+    float getLineWidth() const;
+
+    // Hint setters
+    void setGenerateMipmapHint(GLenum hint);
+    void setFragmentShaderDerivativeHint(GLenum hint);
+
+    // GL_CHROMIUM_bind_generates_resource
+    bool isBindGeneratesResourceEnabled() const;
+
+    // GL_ANGLE_client_arrays
+    bool areClientArraysEnabled() const;
+
+    // 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(GLenum type, Texture *texture);
+    Texture *getTargetTexture(GLenum target) const;
+    Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
+    GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const;
+    void detachTexture(const Context *context, const TextureMap &zeroTextures, GLuint texture);
+    void initializeZeroTextures(const TextureMap &zeroTextures);
+
+    // Sampler object binding manipulation
+    void setSamplerBinding(GLuint textureUnit, Sampler *sampler);
+    GLuint getSamplerId(GLuint textureUnit) const;
+    Sampler *getSampler(GLuint textureUnit) const;
+    void detachSampler(GLuint sampler);
+
+    // Renderbuffer binding manipulation
+    void setRenderbufferBinding(Renderbuffer *renderbuffer);
+    GLuint getRenderbufferId() const;
+    Renderbuffer *getCurrentRenderbuffer() const;
+    void detachRenderbuffer(const Context *context, GLuint renderbuffer);
+
+    // Framebuffer binding manipulation
+    void setReadFramebufferBinding(Framebuffer *framebuffer);
+    void setDrawFramebufferBinding(Framebuffer *framebuffer);
+    Framebuffer *getTargetFramebuffer(GLenum target) const;
+    Framebuffer *getReadFramebuffer() const;
+    Framebuffer *getDrawFramebuffer() const;
+    bool removeReadFramebufferBinding(GLuint framebuffer);
+    bool removeDrawFramebufferBinding(GLuint framebuffer);
+
+    // Vertex array object binding manipulation
+    void setVertexArrayBinding(VertexArray *vertexArray);
+    GLuint getVertexArrayId() const;
+    VertexArray *getVertexArray() const;
+    bool removeVertexArrayBinding(GLuint vertexArray);
+
+    // Program binding manipulation
+    void setProgram(const Context *context, Program *newProgram);
+    Program *getProgram() const;
+
+    // Transform feedback object (not buffer) binding manipulation
+    void setTransformFeedbackBinding(TransformFeedback *transformFeedback);
+    TransformFeedback *getCurrentTransformFeedback() const;
+    bool isTransformFeedbackActiveUnpaused() const;
+    bool removeTransformFeedbackBinding(GLuint transformFeedback);
+
+    // Query binding manipulation
+    bool isQueryActive(const GLenum type) const;
+    bool isQueryActive(Query *query) const;
+    void setActiveQuery(GLenum target, Query *query);
+    GLuint getActiveQueryId(GLenum target) const;
+    Query *getActiveQuery(GLenum target) const;
+
+    //// Typed buffer binding point manipulation ////
+    // GL_ARRAY_BUFFER
+    void setArrayBufferBinding(Buffer *buffer);
+    GLuint getArrayBufferId() const;
+
+    void setDrawIndirectBufferBinding(Buffer *buffer);
+    Buffer *getDrawIndirectBuffer() const { return mDrawIndirectBuffer.get(); }
+
+    // GL_UNIFORM_BUFFER - Both indexed and generic targets
+    void setGenericUniformBufferBinding(Buffer *buffer);
+    void setIndexedUniformBufferBinding(GLuint index,
+                                        Buffer *buffer,
+                                        GLintptr offset,
+                                        GLsizeiptr size);
+    const OffsetBindingPointer<Buffer> &getIndexedUniformBuffer(size_t index) const;
+
+    // GL_ATOMIC_COUNTER_BUFFER - Both indexed and generic targets
+    void setGenericAtomicCounterBufferBinding(Buffer *buffer);
+    void setIndexedAtomicCounterBufferBinding(GLuint index,
+                                              Buffer *buffer,
+                                              GLintptr offset,
+                                              GLsizeiptr size);
+    const OffsetBindingPointer<Buffer> &getIndexedAtomicCounterBuffer(size_t index) const;
+
+    // GL_SHADER_STORAGE_BUFFER - Both indexed and generic targets
+    void setGenericShaderStorageBufferBinding(Buffer *buffer);
+    void setIndexedShaderStorageBufferBinding(GLuint index,
+                                              Buffer *buffer,
+                                              GLintptr offset,
+                                              GLsizeiptr size);
+    const OffsetBindingPointer<Buffer> &getIndexedShaderStorageBuffer(size_t index) const;
+
+    // GL_COPY_[READ/WRITE]_BUFFER
+    void setCopyReadBufferBinding(Buffer *buffer);
+    void setCopyWriteBufferBinding(Buffer *buffer);
+
+    // GL_PIXEL[PACK/UNPACK]_BUFFER
+    void setPixelPackBufferBinding(Buffer *buffer);
+    void setPixelUnpackBufferBinding(Buffer *buffer);
+
+    // Retrieve typed buffer by target (non-indexed)
+    Buffer *getTargetBuffer(GLenum target) const;
+    // Detach a buffer from all bindings
+    void detachBuffer(GLuint bufferName);
+
+    // Vertex attrib manipulation
+    void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
+    void setElementArrayBuffer(Buffer *buffer);
+    void setVertexAttribf(GLuint index, const GLfloat values[4]);
+    void setVertexAttribu(GLuint index, const GLuint values[4]);
+    void setVertexAttribi(GLuint index, const GLint values[4]);
+    void setVertexAttribState(unsigned int attribNum,
+                              Buffer *boundBuffer,
+                              GLint size,
+                              GLenum type,
+                              bool normalized,
+                              bool pureInteger,
+                              GLsizei stride,
+                              const void *pointer);
+    void setVertexAttribDivisor(GLuint index, GLuint divisor);
+    const VertexAttribCurrentValueData &getVertexAttribCurrentValue(size_t attribNum) const;
+    const void *getVertexAttribPointer(unsigned int attribNum) const;
+    void bindVertexBuffer(GLuint bindingIndex,
+                          Buffer *boundBuffer,
+                          GLintptr offset,
+                          GLsizei stride);
+    void setVertexAttribFormat(GLuint attribIndex,
+                               GLint size,
+                               GLenum type,
+                               bool normalized,
+                               bool pureInteger,
+                               GLuint relativeOffset);
+    void setVertexAttribBinding(GLuint attribIndex, GLuint bindingIndex);
+    void setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor);
+
+    // Pixel pack state manipulation
+    void setPackAlignment(GLint alignment);
+    GLint getPackAlignment() const;
+    void setPackReverseRowOrder(bool reverseRowOrder);
+    bool getPackReverseRowOrder() const;
+    void setPackRowLength(GLint rowLength);
+    GLint getPackRowLength() const;
+    void setPackSkipRows(GLint skipRows);
+    GLint getPackSkipRows() const;
+    void setPackSkipPixels(GLint skipPixels);
+    GLint getPackSkipPixels() const;
+    const PixelPackState &getPackState() const;
+    PixelPackState &getPackState();
+
+    // Pixel unpack state manipulation
+    void setUnpackAlignment(GLint alignment);
+    GLint getUnpackAlignment() const;
+    void setUnpackRowLength(GLint rowLength);
+    GLint getUnpackRowLength() const;
+    void setUnpackImageHeight(GLint imageHeight);
+    GLint getUnpackImageHeight() const;
+    void setUnpackSkipImages(GLint skipImages);
+    GLint getUnpackSkipImages() const;
+    void setUnpackSkipRows(GLint skipRows);
+    GLint getUnpackSkipRows() const;
+    void setUnpackSkipPixels(GLint skipPixels);
+    GLint getUnpackSkipPixels() const;
+    const PixelUnpackState &getUnpackState() const;
+    PixelUnpackState &getUnpackState();
+
+    // Debug state
+    const Debug &getDebug() const;
+    Debug &getDebug();
+
+    // CHROMIUM_framebuffer_mixed_samples coverage modulation
+    void setCoverageModulation(GLenum components);
+    GLenum getCoverageModulation() const;
+
+    // CHROMIUM_path_rendering
+    void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
+    const GLfloat *getPathRenderingMatrix(GLenum which) const;
+    void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
+
+    GLenum getPathStencilFunc() const;
+    GLint getPathStencilRef() const;
+    GLuint getPathStencilMask() const;
+
+    // GL_EXT_sRGB_write_control
+    void setFramebufferSRGB(bool sRGB);
+    bool getFramebufferSRGB() const;
+
+    // State query functions
+    void getBooleanv(GLenum pname, GLboolean *params);
+    void getFloatv(GLenum pname, GLfloat *params);
+    void getIntegerv(const Context *context, GLenum pname, GLint *params);
+    void getPointerv(GLenum pname, void **params) const;
+    void getIntegeri_v(GLenum target, GLuint index, GLint *data);
+    void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
+    void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
+
+    bool hasMappedBuffer(GLenum target) const;
+    bool isRobustResourceInitEnabled() const { return mRobustResourceInit; }
+
+    enum DirtyBitType
+    {
+        DIRTY_BIT_SCISSOR_TEST_ENABLED,
+        DIRTY_BIT_SCISSOR,
+        DIRTY_BIT_VIEWPORT,
+        DIRTY_BIT_DEPTH_RANGE,
+        DIRTY_BIT_BLEND_ENABLED,
+        DIRTY_BIT_BLEND_COLOR,
+        DIRTY_BIT_BLEND_FUNCS,
+        DIRTY_BIT_BLEND_EQUATIONS,
+        DIRTY_BIT_COLOR_MASK,
+        DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED,
+        DIRTY_BIT_SAMPLE_COVERAGE_ENABLED,
+        DIRTY_BIT_SAMPLE_COVERAGE,
+        DIRTY_BIT_DEPTH_TEST_ENABLED,
+        DIRTY_BIT_DEPTH_FUNC,
+        DIRTY_BIT_DEPTH_MASK,
+        DIRTY_BIT_STENCIL_TEST_ENABLED,
+        DIRTY_BIT_STENCIL_FUNCS_FRONT,
+        DIRTY_BIT_STENCIL_FUNCS_BACK,
+        DIRTY_BIT_STENCIL_OPS_FRONT,
+        DIRTY_BIT_STENCIL_OPS_BACK,
+        DIRTY_BIT_STENCIL_WRITEMASK_FRONT,
+        DIRTY_BIT_STENCIL_WRITEMASK_BACK,
+        DIRTY_BIT_CULL_FACE_ENABLED,
+        DIRTY_BIT_CULL_FACE,
+        DIRTY_BIT_FRONT_FACE,
+        DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED,
+        DIRTY_BIT_POLYGON_OFFSET,
+        DIRTY_BIT_RASTERIZER_DISCARD_ENABLED,
+        DIRTY_BIT_LINE_WIDTH,
+        DIRTY_BIT_PRIMITIVE_RESTART_ENABLED,
+        DIRTY_BIT_CLEAR_COLOR,
+        DIRTY_BIT_CLEAR_DEPTH,
+        DIRTY_BIT_CLEAR_STENCIL,
+        DIRTY_BIT_UNPACK_ALIGNMENT,
+        DIRTY_BIT_UNPACK_ROW_LENGTH,
+        DIRTY_BIT_UNPACK_IMAGE_HEIGHT,
+        DIRTY_BIT_UNPACK_SKIP_IMAGES,
+        DIRTY_BIT_UNPACK_SKIP_ROWS,
+        DIRTY_BIT_UNPACK_SKIP_PIXELS,
+        DIRTY_BIT_UNPACK_BUFFER_BINDING,
+        DIRTY_BIT_PACK_ALIGNMENT,
+        DIRTY_BIT_PACK_REVERSE_ROW_ORDER,
+        DIRTY_BIT_PACK_ROW_LENGTH,
+        DIRTY_BIT_PACK_SKIP_ROWS,
+        DIRTY_BIT_PACK_SKIP_PIXELS,
+        DIRTY_BIT_PACK_BUFFER_BINDING,
+        DIRTY_BIT_DITHER_ENABLED,
+        DIRTY_BIT_GENERATE_MIPMAP_HINT,
+        DIRTY_BIT_SHADER_DERIVATIVE_HINT,
+        DIRTY_BIT_READ_FRAMEBUFFER_BINDING,
+        DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING,
+        DIRTY_BIT_RENDERBUFFER_BINDING,
+        DIRTY_BIT_VERTEX_ARRAY_BINDING,
+        DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING,
+        DIRTY_BIT_PROGRAM_BINDING,
+        DIRTY_BIT_MULTISAMPLING,
+        DIRTY_BIT_SAMPLE_ALPHA_TO_ONE,
+        DIRTY_BIT_COVERAGE_MODULATION,         // CHROMIUM_framebuffer_mixed_samples
+        DIRTY_BIT_PATH_RENDERING_MATRIX_MV,    // CHROMIUM_path_rendering path model view matrix
+        DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ,  // CHROMIUM_path_rendering path projection matrix
+        DIRTY_BIT_PATH_RENDERING_STENCIL_STATE,
+        DIRTY_BIT_FRAMEBUFFER_SRGB,  // GL_EXT_sRGB_write_control
+        DIRTY_BIT_CURRENT_VALUE_0,
+        DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS,
+        DIRTY_BIT_INVALID           = DIRTY_BIT_CURRENT_VALUE_MAX,
+        DIRTY_BIT_MAX               = DIRTY_BIT_INVALID,
+    };
+
+    // TODO(jmadill): Consider storing dirty objects in a list instead of by binding.
+    enum DirtyObjectType
+    {
+        DIRTY_OBJECT_READ_FRAMEBUFFER,
+        DIRTY_OBJECT_DRAW_FRAMEBUFFER,
+        DIRTY_OBJECT_VERTEX_ARRAY,
+        DIRTY_OBJECT_PROGRAM,
+        DIRTY_OBJECT_UNKNOWN,
+        DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
+    };
+
+    typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits;
+    const DirtyBits &getDirtyBits() const { return mDirtyBits; }
+    void clearDirtyBits() { mDirtyBits.reset(); }
+    void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; }
+    void setAllDirtyBits() { mDirtyBits.set(); }
+
+    typedef angle::BitSet<DIRTY_OBJECT_MAX> DirtyObjects;
+    void clearDirtyObjects() { mDirtyObjects.reset(); }
+    void setAllDirtyObjects() { mDirtyObjects.set(); }
+    void syncDirtyObjects(const Context *context);
+    void syncDirtyObjects(const Context *context, const DirtyObjects &bitset);
+    void syncDirtyObject(const Context *context, GLenum target);
+    void setObjectDirty(GLenum target);
+
+  private:
+    // Cached values from Context's caps
+    GLuint mMaxDrawBuffers;
+    GLuint mMaxCombinedTextureImageUnits;
+
+    ColorF mColorClearValue;
+    GLfloat mDepthClearValue;
+    int mStencilClearValue;
+
+    RasterizerState mRasterizer;
+    bool mScissorTest;
+    Rectangle mScissor;
+
+    BlendState mBlend;
+    ColorF mBlendColor;
+    bool mSampleCoverage;
+    GLfloat mSampleCoverageValue;
+    bool mSampleCoverageInvert;
+
+    DepthStencilState mDepthStencil;
+    GLint mStencilRef;
+    GLint mStencilBackRef;
+
+    GLfloat mLineWidth;
+
+    GLenum mGenerateMipmapHint;
+    GLenum mFragmentShaderDerivativeHint;
+
+    bool mBindGeneratesResource;
+    bool mClientArraysEnabled;
+
+    Rectangle mViewport;
+    float mNearZ;
+    float mFarZ;
+
+    BindingPointer<Buffer> mArrayBuffer;
+    BindingPointer<Buffer> mDrawIndirectBuffer;
+    Framebuffer *mReadFramebuffer;
+    Framebuffer *mDrawFramebuffer;
+    BindingPointer<Renderbuffer> mRenderbuffer;
+    Program *mProgram;
+
+    typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector;
+    VertexAttribVector mVertexAttribCurrentValues;  // From glVertexAttrib
+    VertexArray *mVertexArray;
+
+    // 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;
+    typedef std::vector<OffsetBindingPointer<Buffer>> BufferVector;
+    BufferVector mUniformBuffers;
+
+    BindingPointer<TransformFeedback> mTransformFeedback;
+
+    BindingPointer<Buffer> mGenericAtomicCounterBuffer;
+    BufferVector mAtomicCounterBuffers;
+
+    BindingPointer<Buffer> mGenericShaderStorageBuffer;
+    BufferVector mShaderStorageBuffers;
+
+    BindingPointer<Buffer> mCopyReadBuffer;
+    BindingPointer<Buffer> mCopyWriteBuffer;
+
+    PixelUnpackState mUnpack;
+    PixelPackState mPack;
+
+    bool mPrimitiveRestart;
+
+    Debug mDebug;
+
+    bool mMultiSampling;
+    bool mSampleAlphaToOne;
+
+    GLenum mCoverageModulation;
+
+    // CHROMIUM_path_rendering
+    GLfloat mPathMatrixMV[16];
+    GLfloat mPathMatrixProj[16];
+    GLenum mPathStencilFunc;
+    GLint mPathStencilRef;
+    GLuint mPathStencilMask;
+
+    // GL_EXT_sRGB_write_control
+    bool mFramebufferSRGB;
+
+    // GL_ANGLE_robust_resource_intialization
+    bool mRobustResourceInit;
+
+    DirtyBits mDirtyBits;
+    DirtyObjects mDirtyObjects;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_STATE_H_
diff --git a/src/third_party/angle/src/libANGLE/Stream.cpp b/src/third_party/angle/src/libANGLE/Stream.cpp
new file mode 100644
index 0000000..8cf078c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Stream.cpp
@@ -0,0 +1,271 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// Stream.cpp: Implements the egl::Stream class, representing the stream
+// where frames are streamed in. Implements EGLStreanKHR.
+
+#include "libANGLE/Stream.h"
+
+#include <platform/Platform.h>
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/renderer/StreamProducerImpl.h"
+
+namespace egl
+{
+
+Stream::Stream(Display *display, const AttributeMap &attribs)
+    : mDisplay(display),
+      mProducerImplementation(nullptr),
+      mState(EGL_STREAM_STATE_CREATED_KHR),
+      mProducerFrame(0),
+      mConsumerFrame(0),
+      mConsumerLatency(attribs.getAsInt(EGL_CONSUMER_LATENCY_USEC_KHR, 0)),
+      mConsumerAcquireTimeout(attribs.getAsInt(EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0)),
+      mPlaneCount(0),
+      mConsumerType(ConsumerType::NoConsumer),
+      mProducerType(ProducerType::NoProducer)
+{
+    for (auto &plane : mPlanes)
+    {
+        plane.textureUnit = -1;
+        plane.texture     = nullptr;
+    }
+}
+
+Stream::~Stream()
+{
+    SafeDelete(mProducerImplementation);
+    for (auto &plane : mPlanes)
+    {
+        if (plane.texture != nullptr)
+        {
+            plane.texture->releaseStream();
+        }
+    }
+}
+
+void Stream::setConsumerLatency(EGLint latency)
+{
+    mConsumerLatency = latency;
+}
+
+EGLint Stream::getConsumerLatency() const
+{
+    return mConsumerLatency;
+}
+
+EGLuint64KHR Stream::getProducerFrame() const
+{
+    return mProducerFrame;
+}
+
+EGLuint64KHR Stream::getConsumerFrame() const
+{
+    return mConsumerFrame;
+}
+
+EGLenum Stream::getState() const
+{
+    return mState;
+}
+
+void Stream::setConsumerAcquireTimeout(EGLint timeout)
+{
+    mConsumerAcquireTimeout = timeout;
+}
+
+EGLint Stream::getConsumerAcquireTimeout() const
+{
+    return mConsumerAcquireTimeout;
+}
+
+Stream::ProducerType Stream::getProducerType() const
+{
+    return mProducerType;
+}
+
+Stream::ConsumerType Stream::getConsumerType() const
+{
+    return mConsumerType;
+}
+
+EGLint Stream::getPlaneCount() const
+{
+    return mPlaneCount;
+}
+
+rx::StreamProducerImpl *Stream::getImplementation()
+{
+    return mProducerImplementation;
+}
+
+Error Stream::createConsumerGLTextureExternal(const AttributeMap &attributes, gl::Context *context)
+{
+    ASSERT(mState == EGL_STREAM_STATE_CREATED_KHR);
+    ASSERT(mConsumerType == ConsumerType::NoConsumer);
+    ASSERT(mProducerType == ProducerType::NoProducer);
+    ASSERT(context != nullptr);
+
+    const auto &glState = context->getGLState();
+    EGLenum bufferType = attributes.getAsInt(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
+    if (bufferType == EGL_RGB_BUFFER)
+    {
+        mPlanes[0].texture = glState.getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
+        ASSERT(mPlanes[0].texture != nullptr);
+        mPlanes[0].texture->bindStream(this);
+        mConsumerType = ConsumerType::GLTextureRGB;
+        mPlaneCount   = 1;
+    }
+    else
+    {
+        mPlaneCount = attributes.getAsInt(EGL_YUV_NUMBER_OF_PLANES_EXT, 2);
+        ASSERT(mPlaneCount <= 3);
+        for (EGLint i = 0; i < mPlaneCount; i++)
+        {
+            // Fetch all the textures
+            mPlanes[i].textureUnit = attributes.getAsInt(EGL_YUV_PLANE0_TEXTURE_UNIT_NV + i, -1);
+            if (mPlanes[i].textureUnit != EGL_NONE)
+            {
+                mPlanes[i].texture =
+                    glState.getSamplerTexture(mPlanes[i].textureUnit, GL_TEXTURE_EXTERNAL_OES);
+                ASSERT(mPlanes[i].texture != nullptr);
+            }
+        }
+
+        // Bind them to the stream
+        for (EGLint i = 0; i < mPlaneCount; i++)
+        {
+            if (mPlanes[i].textureUnit != EGL_NONE)
+            {
+                mPlanes[i].texture->bindStream(this);
+            }
+        }
+        mConsumerType = ConsumerType::GLTextureYUV;
+    }
+
+    mContext = context;
+    mState   = EGL_STREAM_STATE_CONNECTING_KHR;
+
+    return Error(EGL_SUCCESS);
+}
+
+Error Stream::createProducerD3D11TextureNV12(const AttributeMap &attributes)
+{
+    ASSERT(mState == EGL_STREAM_STATE_CONNECTING_KHR);
+    ASSERT(mConsumerType == ConsumerType::GLTextureYUV);
+    ASSERT(mProducerType == ProducerType::NoProducer);
+    ASSERT(mPlaneCount == 2);
+
+    mProducerImplementation = mDisplay->getImplementation()->createStreamProducerD3DTextureNV12(
+        mConsumerType, attributes);
+    mProducerType = ProducerType::D3D11TextureNV12;
+    mState        = EGL_STREAM_STATE_EMPTY_KHR;
+
+    return Error(EGL_SUCCESS);
+}
+
+// Called when the consumer of this stream starts using the stream
+Error Stream::consumerAcquire()
+{
+    ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
+           mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
+    ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+           mConsumerType == ConsumerType::GLTextureYUV);
+    ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+
+    mState = EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR;
+    mConsumerFrame++;
+
+    // Bind the planes to the gl textures
+    for (int i = 0; i < mPlaneCount; i++)
+    {
+        if (mPlanes[i].texture != nullptr)
+        {
+            mPlanes[i].texture->acquireImageFromStream(
+                mProducerImplementation->getGLFrameDescription(i));
+        }
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error Stream::consumerRelease()
+{
+    ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
+           mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
+    ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+           mConsumerType == ConsumerType::GLTextureYUV);
+    ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+
+    // Release the images
+    for (int i = 0; i < mPlaneCount; i++)
+    {
+        if (mPlanes[i].texture != nullptr)
+        {
+            mPlanes[i].texture->releaseImageFromStream();
+        }
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+bool Stream::isConsumerBoundToContext(const gl::Context *context) const
+{
+    ASSERT(context != nullptr);
+    return (context == mContext);
+}
+
+Error Stream::validateD3D11NV12Texture(void *texture) const
+{
+    ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+           mConsumerType == ConsumerType::GLTextureYUV);
+    ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+    ASSERT(mProducerImplementation != nullptr);
+
+    return mProducerImplementation->validateD3DNV12Texture(texture);
+}
+
+Error Stream::postD3D11NV12Texture(void *texture, const AttributeMap &attributes)
+{
+    ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+           mConsumerType == ConsumerType::GLTextureYUV);
+    ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+
+    mProducerImplementation->postD3DNV12Texture(texture, attributes);
+    mProducerFrame++;
+
+    mState = EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR;
+
+    return Error(EGL_SUCCESS);
+}
+
+// This is called when a texture object associated with this stream is destroyed. Even if multiple
+// textures are bound, one being destroyed invalidates the stream, so all the remaining textures
+// will be released and the stream will be invalidated.
+void Stream::releaseTextures()
+{
+    for (auto &plane : mPlanes)
+    {
+        if (plane.texture != nullptr)
+        {
+            plane.texture->releaseStream();
+            plane.texture = nullptr;
+        }
+    }
+    mConsumerType = ConsumerType::NoConsumer;
+    mProducerType = ProducerType::NoProducer;
+    mState        = EGL_STREAM_STATE_DISCONNECTED_KHR;
+}
+
+}  // namespace egl
diff --git a/src/third_party/angle/src/libANGLE/Stream.h b/src/third_party/angle/src/libANGLE/Stream.h
new file mode 100644
index 0000000..799e326
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Stream.h
@@ -0,0 +1,142 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// Stream.h: Defines the egl::Stream class, representing the stream
+// where frames are streamed in. Implements EGLStreanKHR.
+
+#ifndef LIBANGLE_STREAM_H_
+#define LIBANGLE_STREAM_H_
+
+#include <array>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/AttributeMap.h"
+
+namespace rx
+{
+class StreamProducerImpl;
+}
+
+namespace gl
+{
+class Context;
+class Texture;
+}
+
+namespace egl
+{
+class Display;
+class Error;
+
+class Stream final : angle::NonCopyable
+{
+  public:
+    Stream(Display *display, const AttributeMap &attribs);
+    ~Stream();
+
+    enum class ConsumerType
+    {
+        NoConsumer,
+        GLTextureRGB,
+        GLTextureYUV,
+    };
+
+    enum class ProducerType
+    {
+        NoProducer,
+        D3D11TextureNV12,
+    };
+
+    // A GL texture interpretation of a part of a producer frame. For use with GL texture consumers
+    struct GLTextureDescription
+    {
+        unsigned int width;
+        unsigned int height;
+        unsigned int internalFormat;
+        unsigned int mipLevels;
+    };
+
+    EGLenum getState() const;
+
+    void setConsumerLatency(EGLint latency);
+    EGLint getConsumerLatency() const;
+
+    EGLuint64KHR getProducerFrame() const;
+    EGLuint64KHR getConsumerFrame() const;
+
+    void setConsumerAcquireTimeout(EGLint timeout);
+    EGLint getConsumerAcquireTimeout() const;
+
+    ConsumerType getConsumerType() const;
+    ProducerType getProducerType() const;
+
+    EGLint getPlaneCount() const;
+
+    rx::StreamProducerImpl *getImplementation();
+
+    // Consumer creation methods
+    Error createConsumerGLTextureExternal(const AttributeMap &attributes, gl::Context *context);
+
+    // Producer creation methods
+    Error createProducerD3D11TextureNV12(const AttributeMap &attributes);
+
+    // Consumer methods
+    Error consumerAcquire();
+    Error consumerRelease();
+
+    // Some consumers are bound to GL contexts. This validates that a given context is bound to the
+    // stream's consumer
+    bool isConsumerBoundToContext(const gl::Context *context) const;
+
+    // Producer methods
+    Error validateD3D11NV12Texture(void *texture) const;
+    Error postD3D11NV12Texture(void *texture, const AttributeMap &attributes);
+
+  private:
+    // Associated display
+    Display *mDisplay;
+
+    // Producer Implementation
+    rx::StreamProducerImpl *mProducerImplementation;
+
+    // Associated GL context. Note that this is a weak pointer used for validation purposes only,
+    // and should never be arbitrarily dereferenced without knowing the context still exists as it
+    // can become dangling at any time.
+    gl::Context *mContext;
+
+    // EGL defined attributes
+    EGLint mState;
+    EGLuint64KHR mProducerFrame;
+    EGLuint64KHR mConsumerFrame;
+    EGLint mConsumerLatency;
+
+    // EGL gltexture consumer attributes
+    EGLint mConsumerAcquireTimeout;
+
+    // EGL gltexture yuv consumer attributes
+    EGLint mPlaneCount;
+    struct PlaneTexture
+    {
+        EGLint textureUnit;
+        gl::Texture *texture;
+    };
+    // Texture units and textures for all the planes
+    std::array<PlaneTexture, 3> mPlanes;
+
+    // Consumer and producer types
+    ConsumerType mConsumerType;
+    ProducerType mProducerType;
+
+    // ANGLE-only method, used internally
+    friend class gl::Texture;
+    void releaseTextures();
+};
+}  // namespace egl
+
+#endif  // LIBANGLE_STREAM_H_
diff --git a/src/third_party/angle/src/libANGLE/Surface.cpp b/src/third_party/angle/src/libANGLE/Surface.cpp
new file mode 100644
index 0000000..231dab6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Surface.cpp
@@ -0,0 +1,333 @@
+//
+// 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.
+//
+
+// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#include "libANGLE/Surface.h"
+
+#include <EGL/eglext.h>
+
+#include <iostream>
+
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+
+namespace egl
+{
+
+SurfaceState::SurfaceState(const egl::Config *configIn)
+    : defaultFramebuffer(nullptr), config(configIn)
+{
+}
+
+Surface::Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes)
+    : FramebufferAttachmentObject(),
+      mState(config),
+      mImplementation(nullptr),
+      mCurrentCount(0),
+      mDestroyed(false),
+      mType(surfaceType),
+      mPostSubBufferRequested(false),
+      mFixedSize(false),
+      mFixedWidth(0),
+      mFixedHeight(0),
+      mTextureFormat(EGL_NO_TEXTURE),
+      mTextureTarget(EGL_NO_TEXTURE),
+      // FIXME: Determine actual pixel aspect ratio
+      mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
+      mRenderBuffer(EGL_BACK_BUFFER),
+      mSwapBehavior(EGL_NONE),
+      mOrientation(0),
+      mTexture(),
+      mBackFormat(config->renderTargetFormat),
+      mDSFormat(config->depthStencilFormat)
+{
+    mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
+    mFlexibleSurfaceCompatibilityRequested =
+        (attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE);
+
+    mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
+
+    mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
+    if (mFixedSize)
+    {
+        mFixedWidth  = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
+        mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
+    }
+
+    if (mType != EGL_WINDOW_BIT)
+    {
+        mTextureFormat = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
+        mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
+    }
+
+    mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
+}
+
+Surface::~Surface()
+{
+    if (mTexture.get())
+    {
+        if (mImplementation)
+        {
+            mImplementation->releaseTexImage(EGL_BACK_BUFFER);
+        }
+        mTexture->releaseTexImageFromSurface();
+        mTexture.set(nullptr);
+    }
+
+    SafeDelete(mState.defaultFramebuffer);
+    SafeDelete(mImplementation);
+}
+
+void Surface::destroy(const Display *display)
+{
+    if (mState.defaultFramebuffer)
+    {
+        mState.defaultFramebuffer->destroyDefault(display);
+    }
+    if (mImplementation)
+    {
+        mImplementation->destroy(rx::SafeGetImpl(display));
+    }
+    delete this;
+}
+
+Error Surface::initialize(const Display &display)
+{
+    ANGLE_TRY(mImplementation->initialize(display.getImplementation()));
+
+    // Initialized here since impl is nullptr in the constructor.
+    // Must happen after implementation initialize for Android.
+    mSwapBehavior = mImplementation->getSwapBehavior();
+
+    // Must happen after implementation initialize for OSX.
+    mState.defaultFramebuffer = createDefaultFramebuffer();
+    ASSERT(mState.defaultFramebuffer != nullptr);
+
+    return Error(EGL_SUCCESS);
+}
+
+void Surface::setIsCurrent(Display *display, bool isCurrent)
+{
+    if (isCurrent)
+    {
+        mCurrentCount++;
+        return;
+    }
+
+    ASSERT(mCurrentCount > 0);
+    mCurrentCount--;
+    if (mCurrentCount == 0 && mDestroyed)
+    {
+        destroy(display);
+    }
+}
+
+void Surface::onDestroy(Display *display)
+{
+    mDestroyed = true;
+    if (mCurrentCount == 0)
+    {
+        destroy(display);
+    }
+}
+
+EGLint Surface::getType() const
+{
+    return mType;
+}
+
+Error Surface::swap(const Display &display)
+{
+    return mImplementation->swap(display.getImplementation());
+}
+
+Error Surface::swapWithDamage(EGLint *rects, EGLint n_rects)
+{
+    return mImplementation->swapWithDamage(rects, n_rects);
+}
+
+Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    return mImplementation->postSubBuffer(x, y, width, height);
+}
+
+Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    return mImplementation->querySurfacePointerANGLE(attribute, value);
+}
+
+EGLint Surface::isPostSubBufferSupported() const
+{
+    return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
+}
+
+void Surface::setSwapInterval(EGLint interval)
+{
+    mImplementation->setSwapInterval(interval);
+}
+
+const Config *Surface::getConfig() const
+{
+    return mState.config;
+}
+
+EGLint Surface::getPixelAspectRatio() const
+{
+    return mPixelAspectRatio;
+}
+
+EGLenum Surface::getRenderBuffer() const
+{
+    return mRenderBuffer;
+}
+
+EGLenum Surface::getSwapBehavior() const
+{
+    return mSwapBehavior;
+}
+
+EGLenum Surface::getTextureFormat() const
+{
+    return mTextureFormat;
+}
+
+EGLenum Surface::getTextureTarget() const
+{
+    return mTextureTarget;
+}
+
+EGLint Surface::isFixedSize() const
+{
+    return mFixedSize;
+}
+
+EGLint Surface::getWidth() const
+{
+    return mFixedSize ? static_cast<EGLint>(mFixedWidth) : mImplementation->getWidth();
+}
+
+EGLint Surface::getHeight() const
+{
+    return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
+}
+
+Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    ASSERT(!mTexture.get());
+    ANGLE_TRY(mImplementation->bindTexImage(texture, buffer));
+
+    texture->bindTexImageFromSurface(this);
+    mTexture.set(texture);
+
+    return Error(EGL_SUCCESS);
+}
+
+Error Surface::releaseTexImage(EGLint buffer)
+{
+    ANGLE_TRY(mImplementation->releaseTexImage(buffer));
+
+    ASSERT(mTexture.get());
+    mTexture->releaseTexImageFromSurface();
+    mTexture.set(nullptr);
+
+    return Error(EGL_SUCCESS);
+}
+
+Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+    return mImplementation->getSyncValues(ust, msc, sbc);
+}
+
+void Surface::releaseTexImageFromTexture()
+{
+    ASSERT(mTexture.get());
+    mTexture.set(nullptr);
+}
+
+gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
+{
+    return gl::Extents(getWidth(), getHeight(), 1);
+}
+
+const gl::Format &Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
+{
+    return (binding == GL_BACK ? mBackFormat : mDSFormat);
+}
+
+GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
+{
+    return getConfig()->samples;
+}
+
+GLuint Surface::getId() const
+{
+    UNREACHABLE();
+    return 0;
+}
+
+gl::Framebuffer *Surface::createDefaultFramebuffer()
+{
+    return new gl::Framebuffer(this);
+}
+
+WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
+                             const egl::Config *config,
+                             EGLNativeWindowType window,
+                             const AttributeMap &attribs)
+    : Surface(EGL_WINDOW_BIT, config, attribs)
+{
+    mImplementation = implFactory->createWindowSurface(mState, window, attribs);
+}
+
+WindowSurface::~WindowSurface()
+{
+}
+
+PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
+                               const Config *config,
+                               const AttributeMap &attribs)
+    : Surface(EGL_PBUFFER_BIT, config, attribs)
+{
+    mImplementation = implFactory->createPbufferSurface(mState, attribs);
+}
+
+PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
+                               const Config *config,
+                               EGLenum buftype,
+                               EGLClientBuffer clientBuffer,
+                               const AttributeMap &attribs)
+    : Surface(EGL_PBUFFER_BIT, config, attribs)
+{
+    mImplementation =
+        implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
+}
+
+PbufferSurface::~PbufferSurface()
+{
+}
+
+PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
+                             const Config *config,
+                             NativePixmapType nativePixmap,
+                             const AttributeMap &attribs)
+    : Surface(EGL_PIXMAP_BIT, config, attribs)
+{
+    mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
+}
+
+PixmapSurface::~PixmapSurface()
+{
+}
+
+}  // namespace egl
diff --git a/src/third_party/angle/src/libANGLE/Surface.h b/src/third_party/angle/src/libANGLE/Surface.h
new file mode 100644
index 0000000..d14bba1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Surface.h
@@ -0,0 +1,187 @@
+//
+// 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.
+//
+
+// Surface.h: Defines the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#ifndef LIBANGLE_SURFACE_H_
+#define LIBANGLE_SURFACE_H_
+
+#include <EGL/egl.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace gl
+{
+class Framebuffer;
+class Texture;
+}
+
+namespace rx
+{
+class EGLImplFactory;
+}
+
+namespace egl
+{
+class AttributeMap;
+class Display;
+struct Config;
+
+struct SurfaceState final : private angle::NonCopyable
+{
+    SurfaceState(const egl::Config *configIn);
+
+    gl::Framebuffer *defaultFramebuffer;
+    const egl::Config *config;
+};
+
+class Surface : public gl::FramebufferAttachmentObject
+{
+  public:
+    virtual ~Surface();
+
+    rx::SurfaceImpl *getImplementation() const { return mImplementation; }
+
+    EGLint getType() const;
+
+    Error initialize(const Display &display);
+    Error swap(const Display &display);
+    Error swapWithDamage(EGLint *rects, EGLint n_rects);
+    Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+    Error querySurfacePointerANGLE(EGLint attribute, void **value);
+    Error bindTexImage(gl::Texture *texture, EGLint buffer);
+    Error releaseTexImage(EGLint buffer);
+
+    Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc);
+
+    EGLint isPostSubBufferSupported() const;
+
+    void setSwapInterval(EGLint interval);
+    void setIsCurrent(Display *display, bool isCurrent);
+    void onDestroy(Display *display);
+
+    const Config *getConfig() const;
+
+    // width and height can change with client window resizing
+    EGLint getWidth() const;
+    EGLint getHeight() const;
+    EGLint getPixelAspectRatio() const;
+    EGLenum getRenderBuffer() const;
+    EGLenum getSwapBehavior() const;
+    EGLenum getTextureFormat() const;
+    EGLenum getTextureTarget() const;
+
+    gl::Texture *getBoundTexture() const { return mTexture.get(); }
+    gl::Framebuffer *getDefaultFramebuffer() { return mState.defaultFramebuffer; }
+
+    EGLint isFixedSize() const;
+
+    // FramebufferAttachmentObject implementation
+    gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override;
+    const gl::Format &getAttachmentFormat(GLenum binding,
+                                          const gl::ImageIndex &imageIndex) const override;
+    GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override;
+
+    void onAttach() override {}
+    void onDetach() override {}
+    GLuint getId() const override;
+
+    bool flexibleSurfaceCompatibilityRequested() const
+    {
+        return mFlexibleSurfaceCompatibilityRequested;
+    }
+    EGLint getOrientation() const { return mOrientation; }
+
+    bool directComposition() const { return mDirectComposition; }
+
+  protected:
+    Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes);
+    rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mImplementation; }
+
+    gl::Framebuffer *createDefaultFramebuffer();
+
+    // ANGLE-only method, used internally
+    friend class gl::Texture;
+    void releaseTexImageFromTexture();
+
+    SurfaceState mState;
+    rx::SurfaceImpl *mImplementation;
+    int mCurrentCount;
+    bool mDestroyed;
+
+    EGLint mType;
+
+    bool mPostSubBufferRequested;
+    bool mFlexibleSurfaceCompatibilityRequested;
+
+    bool mFixedSize;
+    size_t mFixedWidth;
+    size_t mFixedHeight;
+
+    bool mDirectComposition;
+
+    EGLenum mTextureFormat;
+    EGLenum mTextureTarget;
+
+    EGLint mPixelAspectRatio;      // Display aspect ratio
+    EGLenum mRenderBuffer;         // Render buffer
+    EGLenum mSwapBehavior;         // Buffer swap behavior
+
+    EGLint mOrientation;
+
+    BindingPointer<gl::Texture> mTexture;
+
+    gl::Format mBackFormat;
+    gl::Format mDSFormat;
+
+  private:
+    void destroy(const egl::Display *display);
+};
+
+class WindowSurface final : public Surface
+{
+  public:
+    WindowSurface(rx::EGLImplFactory *implFactory,
+                  const Config *config,
+                  EGLNativeWindowType window,
+                  const AttributeMap &attribs);
+    ~WindowSurface() override;
+};
+
+class PbufferSurface final : public Surface
+{
+  public:
+    PbufferSurface(rx::EGLImplFactory *implFactory,
+                   const Config *config,
+                   const AttributeMap &attribs);
+    PbufferSurface(rx::EGLImplFactory *implFactory,
+                   const Config *config,
+                   EGLenum buftype,
+                   EGLClientBuffer clientBuffer,
+                   const AttributeMap &attribs);
+    ~PbufferSurface() override;
+};
+
+class PixmapSurface final : public Surface
+{
+  public:
+    PixmapSurface(rx::EGLImplFactory *implFactory,
+                  const Config *config,
+                  NativePixmapType nativePixmap,
+                  const AttributeMap &attribs);
+    ~PixmapSurface() override;
+};
+
+}  // namespace egl
+
+#endif   // LIBANGLE_SURFACE_H_
diff --git a/src/third_party/angle/src/libANGLE/Surface_unittest.cpp b/src/third_party/angle/src/libANGLE/Surface_unittest.cpp
new file mode 100644
index 0000000..022be38
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Surface_unittest.cpp
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/FramebufferImpl_mock.h"
+#include "libANGLE/renderer/SurfaceImpl.h"
+#include "tests/angle_unittests_utils.h"
+
+using namespace rx;
+using namespace testing;
+
+namespace
+{
+
+class MockSurfaceImpl : public rx::SurfaceImpl
+{
+  public:
+    MockSurfaceImpl() : SurfaceImpl(mockState), mockState(nullptr) {}
+    virtual ~MockSurfaceImpl() { destructor(); }
+
+    MOCK_METHOD1(destroy, void(const DisplayImpl *));
+    MOCK_METHOD1(initialize, egl::Error(const DisplayImpl *));
+    MOCK_METHOD1(createDefaultFramebuffer, rx::FramebufferImpl *(const gl::FramebufferState &data));
+    MOCK_METHOD1(swap, egl::Error(const DisplayImpl *));
+    MOCK_METHOD2(swapWithDamage, egl::Error(EGLint *, EGLint));
+    MOCK_METHOD4(postSubBuffer, egl::Error(EGLint, EGLint, EGLint, EGLint));
+    MOCK_METHOD2(querySurfacePointerANGLE, egl::Error(EGLint, void**));
+    MOCK_METHOD2(bindTexImage, egl::Error(gl::Texture*, EGLint));
+    MOCK_METHOD1(releaseTexImage, egl::Error(EGLint));
+    MOCK_METHOD3(getSyncValues, egl::Error(EGLuint64KHR *, EGLuint64KHR *, EGLuint64KHR *));
+    MOCK_METHOD1(setSwapInterval, void(EGLint));
+    MOCK_CONST_METHOD0(getWidth, EGLint());
+    MOCK_CONST_METHOD0(getHeight, EGLint());
+    MOCK_CONST_METHOD0(isPostSubBufferSupported, EGLint(void));
+    MOCK_CONST_METHOD0(getSwapBehavior, EGLint(void));
+    MOCK_METHOD3(getAttachmentRenderTarget,
+                 gl::Error(GLenum,
+                           const gl::ImageIndex &,
+                           rx::FramebufferAttachmentRenderTarget **));
+
+    MOCK_METHOD0(destructor, void());
+
+    egl::SurfaceState mockState;
+};
+
+TEST(SurfaceTest, DestructionDeletesImpl)
+{
+    NiceMock<MockEGLFactory> factory;
+
+    MockSurfaceImpl *impl = new MockSurfaceImpl;
+    EXPECT_CALL(factory, createWindowSurface(_, _, _)).WillOnce(Return(impl));
+
+    egl::Config config;
+    egl::Surface *surface = new egl::WindowSurface(
+        &factory, &config, static_cast<EGLNativeWindowType>(0), egl::AttributeMap());
+
+    EXPECT_CALL(*impl, destroy(_)).Times(1).RetiresOnSaturation();
+    EXPECT_CALL(*impl, destructor()).Times(1).RetiresOnSaturation();
+
+    surface->onDestroy(nullptr);
+
+    // Only needed because the mock is leaked if bugs are present,
+    // which logs an error, but does not cause the test to fail.
+    // Ordinarily mocks are verified when destroyed.
+    Mock::VerifyAndClear(impl);
+}
+
+} // namespace
diff --git a/src/third_party/angle/src/libANGLE/Texture.cpp b/src/third_party/angle/src/libANGLE/Texture.cpp
new file mode 100644
index 0000000..91b3321
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Texture.cpp
@@ -0,0 +1,1282 @@
+//
+// 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.
+//
+
+// Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#include "libANGLE/Texture.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace gl
+{
+
+namespace
+{
+bool IsPointSampled(const SamplerState &samplerState)
+{
+    return (samplerState.magFilter == GL_NEAREST &&
+            (samplerState.minFilter == GL_NEAREST ||
+             samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
+}
+
+size_t GetImageDescIndex(GLenum target, size_t level)
+{
+    return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target))
+                                          : level;
+}
+}  // namespace
+
+bool IsMipmapFiltered(const SamplerState &samplerState)
+{
+    switch (samplerState.minFilter)
+    {
+        case GL_NEAREST:
+        case GL_LINEAR:
+            return false;
+        case GL_NEAREST_MIPMAP_NEAREST:
+        case GL_LINEAR_MIPMAP_NEAREST:
+        case GL_NEAREST_MIPMAP_LINEAR:
+        case GL_LINEAR_MIPMAP_LINEAR:
+            return true;
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+SwizzleState::SwizzleState()
+    : swizzleRed(GL_INVALID_INDEX),
+      swizzleGreen(GL_INVALID_INDEX),
+      swizzleBlue(GL_INVALID_INDEX),
+      swizzleAlpha(GL_INVALID_INDEX)
+{
+}
+
+SwizzleState::SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha)
+    : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
+{
+}
+
+bool SwizzleState::swizzleRequired() const
+{
+    return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || swizzleBlue != GL_BLUE ||
+           swizzleAlpha != GL_ALPHA;
+}
+
+bool SwizzleState::operator==(const SwizzleState &other) const
+{
+    return swizzleRed == other.swizzleRed && swizzleGreen == other.swizzleGreen &&
+           swizzleBlue == other.swizzleBlue && swizzleAlpha == other.swizzleAlpha;
+}
+
+bool SwizzleState::operator!=(const SwizzleState &other) const
+{
+    return !(*this == other);
+}
+
+TextureState::TextureState(GLenum target)
+    : mTarget(target),
+      mSwizzleState(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA),
+      mSamplerState(SamplerState::CreateDefaultForTarget(target)),
+      mBaseLevel(0),
+      mMaxLevel(1000),
+      mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
+      mImmutableFormat(false),
+      mImmutableLevels(0),
+      mUsage(GL_NONE),
+      mImageDescs((IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) *
+                  (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)),
+      mCompletenessCache()
+{
+}
+
+bool TextureState::swizzleRequired() const
+{
+    return mSwizzleState.swizzleRequired();
+}
+
+GLuint TextureState::getEffectiveBaseLevel() const
+{
+    if (mImmutableFormat)
+    {
+        // GLES 3.0.4 section 3.8.10
+        return std::min(mBaseLevel, mImmutableLevels - 1);
+    }
+    // Some classes use the effective base level to index arrays with level data. By clamping the
+    // effective base level to max levels these arrays need just one extra item to store properties
+    // that should be returned for all out-of-range base level values, instead of needing special
+    // handling for out-of-range base levels.
+    return std::min(mBaseLevel, static_cast<GLuint>(IMPLEMENTATION_MAX_TEXTURE_LEVELS));
+}
+
+GLuint TextureState::getEffectiveMaxLevel() const
+{
+    if (mImmutableFormat)
+    {
+        // GLES 3.0.4 section 3.8.10
+        GLuint clampedMaxLevel = std::max(mMaxLevel, getEffectiveBaseLevel());
+        clampedMaxLevel        = std::min(clampedMaxLevel, mImmutableLevels - 1);
+        return clampedMaxLevel;
+    }
+    return mMaxLevel;
+}
+
+GLuint TextureState::getMipmapMaxLevel() const
+{
+    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+    GLuint expectedMipLevels       = 0;
+    if (mTarget == GL_TEXTURE_3D)
+    {
+        const int maxDim = std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height),
+                                    baseImageDesc.size.depth);
+        expectedMipLevels = static_cast<GLuint>(log2(maxDim));
+    }
+    else
+    {
+        expectedMipLevels = static_cast<GLuint>(
+            log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)));
+    }
+
+    return std::min<GLuint>(getEffectiveBaseLevel() + expectedMipLevels, getEffectiveMaxLevel());
+}
+
+bool TextureState::setBaseLevel(GLuint baseLevel)
+{
+    if (mBaseLevel != baseLevel)
+    {
+        mBaseLevel = baseLevel;
+        invalidateCompletenessCache();
+        return true;
+    }
+    return false;
+}
+
+void TextureState::setMaxLevel(GLuint maxLevel)
+{
+    if (mMaxLevel != maxLevel)
+    {
+        mMaxLevel = maxLevel;
+        invalidateCompletenessCache();
+    }
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureState::isCubeComplete() const
+{
+    ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
+
+    const ImageDesc &baseImageDesc = getImageDesc(FirstCubeMapTextureTarget, 0);
+    if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
+    {
+        return false;
+    }
+
+    for (GLenum face = FirstCubeMapTextureTarget + 1; face <= LastCubeMapTextureTarget; face++)
+    {
+        const ImageDesc &faceImageDesc = getImageDesc(face, 0);
+        if (faceImageDesc.size.width != baseImageDesc.size.width ||
+            faceImageDesc.size.height != baseImageDesc.size.height ||
+            !Format::SameSized(faceImageDesc.format, baseImageDesc.format))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool TextureState::isSamplerComplete(const SamplerState &samplerState,
+                                     const ContextState &data) const
+{
+    bool newEntry  = false;
+    auto cacheIter = mCompletenessCache.find(data.getContextID());
+    if (cacheIter == mCompletenessCache.end())
+    {
+        // Add a new cache entry
+        cacheIter = mCompletenessCache
+                        .insert(std::make_pair(data.getContextID(), SamplerCompletenessCache()))
+                        .first;
+        newEntry = true;
+    }
+
+    SamplerCompletenessCache *cacheEntry = &cacheIter->second;
+    if (newEntry || cacheEntry->samplerState != samplerState)
+    {
+        cacheEntry->samplerState    = samplerState;
+        cacheEntry->samplerComplete = computeSamplerCompleteness(samplerState, data);
+    }
+
+    return cacheEntry->samplerComplete;
+}
+
+void TextureState::invalidateCompletenessCache()
+{
+    mCompletenessCache.clear();
+}
+
+bool TextureState::computeSamplerCompleteness(const SamplerState &samplerState,
+                                              const ContextState &data) const
+{
+    if (mBaseLevel > mMaxLevel)
+    {
+        return false;
+    }
+    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+    if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
+        baseImageDesc.size.depth == 0)
+    {
+        return false;
+    }
+    // The cases where the texture is incomplete because base level is out of range should be
+    // handled by the above condition.
+    ASSERT(mBaseLevel < IMPLEMENTATION_MAX_TEXTURE_LEVELS || mImmutableFormat);
+
+    if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height)
+    {
+        return false;
+    }
+
+    if (!baseImageDesc.format.info->filterSupport(data.getClientVersion(), data.getExtensions()) &&
+        !IsPointSampled(samplerState))
+    {
+        return false;
+    }
+    bool npotSupport = data.getExtensions().textureNPOT || data.getClientMajorVersion() >= 3;
+    if (!npotSupport)
+    {
+        if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(baseImageDesc.size.width)) ||
+            (samplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(baseImageDesc.size.height)))
+        {
+            return false;
+        }
+    }
+
+    if (IsMipmapFiltered(samplerState))
+    {
+        if (!npotSupport)
+        {
+            if (!isPow2(baseImageDesc.size.width) || !isPow2(baseImageDesc.size.height))
+            {
+                return false;
+            }
+        }
+
+        if (!computeMipmapCompleteness())
+        {
+            return false;
+        }
+    }
+    else
+    {
+        if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
+        {
+            return false;
+        }
+    }
+
+    // From GL_OES_EGL_image_external_essl3: If state is present in a sampler object bound to a
+    // texture unit that would have been rejected by a call to TexParameter* for the texture bound
+    // to that unit, the behavior of the implementation is as if the texture were incomplete. For
+    // example, if TEXTURE_WRAP_S or TEXTURE_WRAP_T is set to anything but CLAMP_TO_EDGE on the
+    // sampler object bound to a texture unit and the texture bound to that unit is an external
+    // texture, the texture will be considered incomplete.
+    // Sampler object state which does not affect sampling for the type of texture bound to a
+    // texture unit, such as TEXTURE_WRAP_R for an external texture, does not affect completeness.
+    if (mTarget == GL_TEXTURE_EXTERNAL_OES)
+    {
+        if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE)
+        {
+            return false;
+        }
+
+        if (samplerState.minFilter != GL_LINEAR && samplerState.minFilter != GL_NEAREST)
+        {
+            return false;
+        }
+    }
+
+    // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
+    // The internalformat specified for the texture arrays is a sized internal depth or
+    // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
+    // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
+    // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
+    if (baseImageDesc.format.info->depthBits > 0 && data.getClientMajorVersion() >= 3)
+    {
+        // Note: we restrict this validation to sized types. For the OES_depth_textures
+        // extension, due to some underspecification problems, we must allow linear filtering
+        // for legacy compatibility with WebGL 1.
+        // See http://crbug.com/649200
+        if (samplerState.compareMode == GL_NONE && baseImageDesc.format.info->sized)
+        {
+            if ((samplerState.minFilter != GL_NEAREST &&
+                 samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
+                samplerState.magFilter != GL_NEAREST)
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+bool TextureState::computeMipmapCompleteness() const
+{
+    const GLuint maxLevel = getMipmapMaxLevel();
+
+    for (GLuint level = getEffectiveBaseLevel(); level <= maxLevel; level++)
+    {
+        if (mTarget == GL_TEXTURE_CUBE_MAP)
+        {
+            for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
+            {
+                if (!computeLevelCompleteness(face, level))
+                {
+                    return false;
+                }
+            }
+        }
+        else
+        {
+            if (!computeLevelCompleteness(mTarget, level))
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+bool TextureState::computeLevelCompleteness(GLenum target, size_t level) const
+{
+    ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+    if (mImmutableFormat)
+    {
+        return true;
+    }
+
+    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+    if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
+        baseImageDesc.size.depth == 0)
+    {
+        return false;
+    }
+
+    const ImageDesc &levelImageDesc = getImageDesc(target, level);
+    if (levelImageDesc.size.width == 0 || levelImageDesc.size.height == 0 ||
+        levelImageDesc.size.depth == 0)
+    {
+        return false;
+    }
+
+    if (!Format::SameSized(levelImageDesc.format, baseImageDesc.format))
+    {
+        return false;
+    }
+
+    ASSERT(level >= getEffectiveBaseLevel());
+    const size_t relativeLevel = level - getEffectiveBaseLevel();
+    if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> relativeLevel))
+    {
+        return false;
+    }
+
+    if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> relativeLevel))
+    {
+        return false;
+    }
+
+    if (mTarget == GL_TEXTURE_3D)
+    {
+        if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> relativeLevel))
+        {
+            return false;
+        }
+    }
+    else if (mTarget == GL_TEXTURE_2D_ARRAY)
+    {
+        if (levelImageDesc.size.depth != baseImageDesc.size.depth)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+GLenum TextureState::getBaseImageTarget() const
+{
+    return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
+}
+
+ImageDesc::ImageDesc() : ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE)
+{
+}
+
+ImageDesc::ImageDesc(const Extents &size, const Format &format)
+    : size(size), format(format), samples(0), fixedSampleLocations(GL_TRUE)
+{
+}
+
+ImageDesc::ImageDesc(const Extents &size,
+                     const Format &format,
+                     const GLsizei samples,
+                     const GLboolean fixedSampleLocations)
+    : size(size), format(format), samples(samples), fixedSampleLocations(fixedSampleLocations)
+{
+}
+
+const ImageDesc &TextureState::getImageDesc(GLenum target, size_t level) const
+{
+    size_t descIndex = GetImageDescIndex(target, level);
+    ASSERT(descIndex < mImageDescs.size());
+    return mImageDescs[descIndex];
+}
+
+void TextureState::setImageDesc(GLenum target, size_t level, const ImageDesc &desc)
+{
+    size_t descIndex = GetImageDescIndex(target, level);
+    ASSERT(descIndex < mImageDescs.size());
+    mImageDescs[descIndex] = desc;
+    invalidateCompletenessCache();
+}
+
+const ImageDesc &TextureState::getImageDesc(const ImageIndex &imageIndex) const
+{
+    return getImageDesc(imageIndex.type, imageIndex.mipIndex);
+}
+
+void TextureState::setImageDescChain(GLuint baseLevel,
+                                     GLuint maxLevel,
+                                     Extents baseSize,
+                                     const Format &format)
+{
+    for (GLuint level = baseLevel; level <= maxLevel; level++)
+    {
+        int relativeLevel = (level - baseLevel);
+        Extents levelSize(std::max<int>(baseSize.width >> relativeLevel, 1),
+                          std::max<int>(baseSize.height >> relativeLevel, 1),
+                          (mTarget == GL_TEXTURE_2D_ARRAY)
+                              ? baseSize.depth
+                              : std::max<int>(baseSize.depth >> relativeLevel, 1));
+        ImageDesc levelInfo(levelSize, format);
+
+        if (mTarget == GL_TEXTURE_CUBE_MAP)
+        {
+            for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
+            {
+                setImageDesc(face, level, levelInfo);
+            }
+        }
+        else
+        {
+            setImageDesc(mTarget, level, levelInfo);
+        }
+    }
+}
+
+void TextureState::setImageDescChainMultisample(Extents baseSize,
+                                                const Format &format,
+                                                GLsizei samples,
+                                                GLboolean fixedSampleLocations)
+{
+    ASSERT(mTarget == GL_TEXTURE_2D_MULTISAMPLE);
+    ImageDesc levelInfo(baseSize, format, samples, fixedSampleLocations);
+    setImageDesc(mTarget, 0, levelInfo);
+}
+
+void TextureState::clearImageDesc(GLenum target, size_t level)
+{
+    setImageDesc(target, level, ImageDesc());
+}
+
+void TextureState::clearImageDescs()
+{
+    for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
+    {
+        mImageDescs[descIndex] = ImageDesc();
+    }
+    invalidateCompletenessCache();
+}
+
+TextureState::SamplerCompletenessCache::SamplerCompletenessCache()
+    : samplerState(), samplerComplete(false)
+{
+}
+
+Texture::Texture(rx::GLImplFactory *factory, GLuint id, GLenum target)
+    : egl::ImageSibling(id),
+      mState(target),
+      mTexture(factory->createTexture(mState)),
+      mLabel(),
+      mBoundSurface(nullptr),
+      mBoundStream(nullptr)
+{
+}
+
+Texture::~Texture()
+{
+    if (mBoundSurface)
+    {
+        mBoundSurface->releaseTexImage(EGL_BACK_BUFFER);
+        mBoundSurface = nullptr;
+    }
+    if (mBoundStream)
+    {
+        mBoundStream->releaseTextures();
+        mBoundStream = nullptr;
+    }
+    SafeDelete(mTexture);
+}
+
+void Texture::setLabel(const std::string &label)
+{
+    mLabel = label;
+    mDirtyBits.set(DIRTY_BIT_LABEL);
+}
+
+const std::string &Texture::getLabel() const
+{
+    return mLabel;
+}
+
+GLenum Texture::getTarget() const
+{
+    return mState.mTarget;
+}
+
+void Texture::setSwizzleRed(GLenum swizzleRed)
+{
+    mState.mSwizzleState.swizzleRed = swizzleRed;
+    mDirtyBits.set(DIRTY_BIT_SWIZZLE_RED);
+}
+
+GLenum Texture::getSwizzleRed() const
+{
+    return mState.mSwizzleState.swizzleRed;
+}
+
+void Texture::setSwizzleGreen(GLenum swizzleGreen)
+{
+    mState.mSwizzleState.swizzleGreen = swizzleGreen;
+    mDirtyBits.set(DIRTY_BIT_SWIZZLE_GREEN);
+}
+
+GLenum Texture::getSwizzleGreen() const
+{
+    return mState.mSwizzleState.swizzleGreen;
+}
+
+void Texture::setSwizzleBlue(GLenum swizzleBlue)
+{
+    mState.mSwizzleState.swizzleBlue = swizzleBlue;
+    mDirtyBits.set(DIRTY_BIT_SWIZZLE_BLUE);
+}
+
+GLenum Texture::getSwizzleBlue() const
+{
+    return mState.mSwizzleState.swizzleBlue;
+}
+
+void Texture::setSwizzleAlpha(GLenum swizzleAlpha)
+{
+    mState.mSwizzleState.swizzleAlpha = swizzleAlpha;
+    mDirtyBits.set(DIRTY_BIT_SWIZZLE_ALPHA);
+}
+
+GLenum Texture::getSwizzleAlpha() const
+{
+    return mState.mSwizzleState.swizzleAlpha;
+}
+
+void Texture::setMinFilter(GLenum minFilter)
+{
+    mState.mSamplerState.minFilter = minFilter;
+    mDirtyBits.set(DIRTY_BIT_MIN_FILTER);
+}
+
+GLenum Texture::getMinFilter() const
+{
+    return mState.mSamplerState.minFilter;
+}
+
+void Texture::setMagFilter(GLenum magFilter)
+{
+    mState.mSamplerState.magFilter = magFilter;
+    mDirtyBits.set(DIRTY_BIT_MAG_FILTER);
+}
+
+GLenum Texture::getMagFilter() const
+{
+    return mState.mSamplerState.magFilter;
+}
+
+void Texture::setWrapS(GLenum wrapS)
+{
+    mState.mSamplerState.wrapS = wrapS;
+    mDirtyBits.set(DIRTY_BIT_WRAP_S);
+}
+
+GLenum Texture::getWrapS() const
+{
+    return mState.mSamplerState.wrapS;
+}
+
+void Texture::setWrapT(GLenum wrapT)
+{
+    mState.mSamplerState.wrapT = wrapT;
+    mDirtyBits.set(DIRTY_BIT_WRAP_T);
+}
+
+GLenum Texture::getWrapT() const
+{
+    return mState.mSamplerState.wrapT;
+}
+
+void Texture::setWrapR(GLenum wrapR)
+{
+    mState.mSamplerState.wrapR = wrapR;
+    mDirtyBits.set(DIRTY_BIT_WRAP_R);
+}
+
+GLenum Texture::getWrapR() const
+{
+    return mState.mSamplerState.wrapR;
+}
+
+void Texture::setMaxAnisotropy(float maxAnisotropy)
+{
+    mState.mSamplerState.maxAnisotropy = maxAnisotropy;
+    mDirtyBits.set(DIRTY_BIT_MAX_ANISOTROPY);
+}
+
+float Texture::getMaxAnisotropy() const
+{
+    return mState.mSamplerState.maxAnisotropy;
+}
+
+void Texture::setMinLod(GLfloat minLod)
+{
+    mState.mSamplerState.minLod = minLod;
+    mDirtyBits.set(DIRTY_BIT_MIN_LOD);
+}
+
+GLfloat Texture::getMinLod() const
+{
+    return mState.mSamplerState.minLod;
+}
+
+void Texture::setMaxLod(GLfloat maxLod)
+{
+    mState.mSamplerState.maxLod = maxLod;
+    mDirtyBits.set(DIRTY_BIT_MAX_LOD);
+}
+
+GLfloat Texture::getMaxLod() const
+{
+    return mState.mSamplerState.maxLod;
+}
+
+void Texture::setCompareMode(GLenum compareMode)
+{
+    mState.mSamplerState.compareMode = compareMode;
+    mDirtyBits.set(DIRTY_BIT_COMPARE_MODE);
+}
+
+GLenum Texture::getCompareMode() const
+{
+    return mState.mSamplerState.compareMode;
+}
+
+void Texture::setCompareFunc(GLenum compareFunc)
+{
+    mState.mSamplerState.compareFunc = compareFunc;
+    mDirtyBits.set(DIRTY_BIT_COMPARE_FUNC);
+}
+
+GLenum Texture::getCompareFunc() const
+{
+    return mState.mSamplerState.compareFunc;
+}
+
+void Texture::setSRGBDecode(GLenum sRGBDecode)
+{
+    mState.mSamplerState.sRGBDecode = sRGBDecode;
+    mDirtyBits.set(DIRTY_BIT_SRGB_DECODE);
+}
+
+GLenum Texture::getSRGBDecode() const
+{
+    return mState.mSamplerState.sRGBDecode;
+}
+
+const SamplerState &Texture::getSamplerState() const
+{
+    return mState.mSamplerState;
+}
+
+void Texture::setBaseLevel(GLuint baseLevel)
+{
+    if (mState.setBaseLevel(baseLevel))
+    {
+        mTexture->setBaseLevel(mState.getEffectiveBaseLevel());
+        mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
+    }
+}
+
+GLuint Texture::getBaseLevel() const
+{
+    return mState.mBaseLevel;
+}
+
+void Texture::setMaxLevel(GLuint maxLevel)
+{
+    mState.setMaxLevel(maxLevel);
+    mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
+}
+
+GLuint Texture::getMaxLevel() const
+{
+    return mState.mMaxLevel;
+}
+
+void Texture::setDepthStencilTextureMode(GLenum mode)
+{
+    if (mode != mState.mDepthStencilTextureMode)
+    {
+        // Changing the mode from the default state (GL_DEPTH_COMPONENT) is not implemented yet
+        UNIMPLEMENTED();
+    }
+
+    // TODO(geofflang): add dirty bits
+    mState.mDepthStencilTextureMode = mode;
+}
+
+GLenum Texture::getDepthStencilTextureMode() const
+{
+    return mState.mDepthStencilTextureMode;
+}
+
+bool Texture::getImmutableFormat() const
+{
+    return mState.mImmutableFormat;
+}
+
+GLuint Texture::getImmutableLevels() const
+{
+    return mState.mImmutableLevels;
+}
+
+void Texture::setUsage(GLenum usage)
+{
+    mState.mUsage = usage;
+    mDirtyBits.set(DIRTY_BIT_USAGE);
+}
+
+GLenum Texture::getUsage() const
+{
+    return mState.mUsage;
+}
+
+const TextureState &Texture::getTextureState() const
+{
+    return mState;
+}
+
+size_t Texture::getWidth(GLenum target, size_t level) const
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+    return mState.getImageDesc(target, level).size.width;
+}
+
+size_t Texture::getHeight(GLenum target, size_t level) const
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+    return mState.getImageDesc(target, level).size.height;
+}
+
+size_t Texture::getDepth(GLenum target, size_t level) const
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+    return mState.getImageDesc(target, level).size.depth;
+}
+
+const Format &Texture::getFormat(GLenum target, size_t level) const
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+    return mState.getImageDesc(target, level).format;
+}
+
+GLsizei Texture::getSamples(GLenum target, size_t level) const
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+    return mState.getImageDesc(target, level).samples;
+}
+
+GLboolean Texture::getFixedSampleLocations(GLenum target, size_t level) const
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+    return mState.getImageDesc(target, level).fixedSampleLocations;
+}
+
+bool Texture::isMipmapComplete() const
+{
+    return mState.computeMipmapCompleteness();
+}
+
+egl::Surface *Texture::getBoundSurface() const
+{
+    return mBoundSurface;
+}
+
+egl::Stream *Texture::getBoundStream() const
+{
+    return mBoundStream;
+}
+
+void Texture::invalidateCompletenessCache()
+{
+    mState.invalidateCompletenessCache();
+    mDirtyChannel.signal();
+}
+
+Error Texture::setImage(const Context *context,
+                        const PixelUnpackState &unpackState,
+                        GLenum target,
+                        size_t level,
+                        GLenum internalFormat,
+                        const Extents &size,
+                        GLenum format,
+                        GLenum type,
+                        const uint8_t *pixels)
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+    releaseTexImageInternal();
+    orphanImages();
+
+    ANGLE_TRY(mTexture->setImage(rx::SafeGetImpl(context), target, level, internalFormat, size,
+                                 format, type, unpackState, pixels));
+
+    mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type)));
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+Error Texture::setSubImage(const Context *context,
+                           const PixelUnpackState &unpackState,
+                           GLenum target,
+                           size_t level,
+                           const Box &area,
+                           GLenum format,
+                           GLenum type,
+                           const uint8_t *pixels)
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+    return mTexture->setSubImage(rx::SafeGetImpl(context), target, level, area, format, type,
+                                 unpackState, pixels);
+}
+
+Error Texture::setCompressedImage(const Context *context,
+                                  const PixelUnpackState &unpackState,
+                                  GLenum target,
+                                  size_t level,
+                                  GLenum internalFormat,
+                                  const Extents &size,
+                                  size_t imageSize,
+                                  const uint8_t *pixels)
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+    releaseTexImageInternal();
+    orphanImages();
+
+    ANGLE_TRY(mTexture->setCompressedImage(rx::SafeGetImpl(context), target, level, internalFormat,
+                                           size, unpackState, imageSize, pixels));
+
+    mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat)));
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+Error Texture::setCompressedSubImage(const Context *context,
+                                     const PixelUnpackState &unpackState,
+                                     GLenum target,
+                                     size_t level,
+                                     const Box &area,
+                                     GLenum format,
+                                     size_t imageSize,
+                                     const uint8_t *pixels)
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+    return mTexture->setCompressedSubImage(rx::SafeGetImpl(context), target, level, area, format,
+                                           unpackState, imageSize, pixels);
+}
+
+Error Texture::copyImage(const Context *context,
+                         GLenum target,
+                         size_t level,
+                         const Rectangle &sourceArea,
+                         GLenum internalFormat,
+                         const Framebuffer *source)
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+    releaseTexImageInternal();
+    orphanImages();
+
+    ANGLE_TRY(mTexture->copyImage(rx::SafeGetImpl(context), target, level, sourceArea,
+                                  internalFormat, source));
+
+    const InternalFormat &internalFormatInfo =
+        GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
+    mState.setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
+                                                 Format(internalFormatInfo)));
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+Error Texture::copySubImage(const Context *context,
+                            GLenum target,
+                            size_t level,
+                            const Offset &destOffset,
+                            const Rectangle &sourceArea,
+                            const Framebuffer *source)
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+    return mTexture->copySubImage(rx::SafeGetImpl(context), target, level, destOffset, sourceArea,
+                                  source);
+}
+
+Error Texture::copyTexture(const Context *context,
+                           GLenum target,
+                           size_t level,
+                           GLenum internalFormat,
+                           GLenum type,
+                           size_t sourceLevel,
+                           bool unpackFlipY,
+                           bool unpackPremultiplyAlpha,
+                           bool unpackUnmultiplyAlpha,
+                           const Texture *source)
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+    releaseTexImageInternal();
+    orphanImages();
+
+    ANGLE_TRY(mTexture->copyTexture(rx::SafeGetImpl(context), target, level, internalFormat, type,
+                                    sourceLevel, unpackFlipY, unpackPremultiplyAlpha,
+                                    unpackUnmultiplyAlpha, source));
+
+    const auto &sourceDesc   = source->mState.getImageDesc(source->getTarget(), 0);
+    const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
+    mState.setImageDesc(target, level, ImageDesc(sourceDesc.size, Format(internalFormatInfo)));
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+Error Texture::copySubTexture(const Context *context,
+                              GLenum target,
+                              size_t level,
+                              const Offset &destOffset,
+                              size_t sourceLevel,
+                              const Rectangle &sourceArea,
+                              bool unpackFlipY,
+                              bool unpackPremultiplyAlpha,
+                              bool unpackUnmultiplyAlpha,
+                              const Texture *source)
+{
+    ASSERT(target == mState.mTarget ||
+           (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+    return mTexture->copySubTexture(rx::SafeGetImpl(context), target, level, destOffset,
+                                    sourceLevel, sourceArea, unpackFlipY, unpackPremultiplyAlpha,
+                                    unpackUnmultiplyAlpha, source);
+}
+
+Error Texture::copyCompressedTexture(const Context *context, const Texture *source)
+{
+    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+    releaseTexImageInternal();
+    orphanImages();
+
+    ANGLE_TRY(mTexture->copyCompressedTexture(rx::SafeGetImpl(context), source));
+
+    ASSERT(source->getTarget() != GL_TEXTURE_CUBE_MAP && getTarget() != GL_TEXTURE_CUBE_MAP);
+    const auto &sourceDesc = source->mState.getImageDesc(source->getTarget(), 0);
+    mState.setImageDesc(getTarget(), 0, sourceDesc);
+
+    return NoError();
+}
+
+Error Texture::setStorage(const Context *context,
+                          GLenum target,
+                          GLsizei levels,
+                          GLenum internalFormat,
+                          const Extents &size)
+{
+    ASSERT(target == mState.mTarget);
+
+    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+    releaseTexImageInternal();
+    orphanImages();
+
+    ANGLE_TRY(mTexture->setStorage(rx::SafeGetImpl(context), target, levels, internalFormat, size));
+
+    mState.mImmutableFormat = true;
+    mState.mImmutableLevels = static_cast<GLuint>(levels);
+    mState.clearImageDescs();
+    mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat));
+
+    // Changing the texture to immutable can trigger a change in the base and max levels:
+    // GLES 3.0.4 section 3.8.10 pg 158:
+    // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
+    // clamped to the range[levelbase;levels].
+    mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
+    mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
+
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+Error Texture::setStorageMultisample(const Context *context,
+                                     GLenum target,
+                                     GLsizei samples,
+                                     GLint internalFormat,
+                                     const Extents &size,
+                                     GLboolean fixedSampleLocations)
+{
+    ASSERT(target == mState.mTarget);
+
+    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+    releaseTexImageInternal();
+    orphanImages();
+
+    ANGLE_TRY(mTexture->setStorageMultisample(rx::SafeGetImpl(context), target, samples,
+                                              internalFormat, size, fixedSampleLocations));
+
+    mState.mImmutableFormat = true;
+    mState.mImmutableLevels = static_cast<GLuint>(1);
+    mState.clearImageDescs();
+    mState.setImageDescChainMultisample(size, Format(internalFormat), samples,
+                                        fixedSampleLocations);
+
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+Error Texture::generateMipmap(const Context *context)
+{
+    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+    releaseTexImageInternal();
+
+    // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
+    // is not mip complete.
+    if (!isMipmapComplete())
+    {
+        orphanImages();
+    }
+
+    const GLuint baseLevel = mState.getEffectiveBaseLevel();
+    const GLuint maxLevel  = mState.getMipmapMaxLevel();
+
+    if (maxLevel > baseLevel)
+    {
+        syncImplState();
+        ANGLE_TRY(mTexture->generateMipmap(rx::SafeGetImpl(context)));
+
+        const ImageDesc &baseImageInfo =
+            mState.getImageDesc(mState.getBaseImageTarget(), baseLevel);
+        mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format);
+    }
+
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+void Texture::bindTexImageFromSurface(egl::Surface *surface)
+{
+    ASSERT(surface);
+
+    if (mBoundSurface)
+    {
+        releaseTexImageFromSurface();
+    }
+
+    mTexture->bindTexImage(surface);
+    mBoundSurface = surface;
+
+    // Set the image info to the size and format of the surface
+    ASSERT(mState.mTarget == GL_TEXTURE_2D);
+    Extents size(surface->getWidth(), surface->getHeight(), 1);
+    ImageDesc desc(size, Format(surface->getConfig()->renderTargetFormat));
+    mState.setImageDesc(mState.mTarget, 0, desc);
+    mDirtyChannel.signal();
+}
+
+void Texture::releaseTexImageFromSurface()
+{
+    ASSERT(mBoundSurface);
+    mBoundSurface = nullptr;
+    mTexture->releaseTexImage();
+
+    // Erase the image info for level 0
+    ASSERT(mState.mTarget == GL_TEXTURE_2D);
+    mState.clearImageDesc(mState.mTarget, 0);
+    mDirtyChannel.signal();
+}
+
+void Texture::bindStream(egl::Stream *stream)
+{
+    ASSERT(stream);
+
+    // It should not be possible to bind a texture already bound to another stream
+    ASSERT(mBoundStream == nullptr);
+
+    mBoundStream = stream;
+
+    ASSERT(mState.mTarget == GL_TEXTURE_EXTERNAL_OES);
+}
+
+void Texture::releaseStream()
+{
+    ASSERT(mBoundStream);
+    mBoundStream = nullptr;
+}
+
+void Texture::acquireImageFromStream(const egl::Stream::GLTextureDescription &desc)
+{
+    ASSERT(mBoundStream != nullptr);
+    mTexture->setImageExternal(mState.mTarget, mBoundStream, desc);
+
+    Extents size(desc.width, desc.height, 1);
+    mState.setImageDesc(mState.mTarget, 0, ImageDesc(size, Format(desc.internalFormat)));
+    mDirtyChannel.signal();
+}
+
+void Texture::releaseImageFromStream()
+{
+    ASSERT(mBoundStream != nullptr);
+    mTexture->setImageExternal(mState.mTarget, nullptr, egl::Stream::GLTextureDescription());
+
+    // Set to incomplete
+    mState.clearImageDesc(mState.mTarget, 0);
+    mDirtyChannel.signal();
+}
+
+void Texture::releaseTexImageInternal()
+{
+    if (mBoundSurface)
+    {
+        // Notify the surface
+        mBoundSurface->releaseTexImageFromTexture();
+
+        // Then, call the same method as from the surface
+        releaseTexImageFromSurface();
+    }
+}
+
+Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget)
+{
+    ASSERT(target == mState.mTarget);
+    ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES);
+
+    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+    releaseTexImageInternal();
+    orphanImages();
+
+    ANGLE_TRY(mTexture->setEGLImageTarget(target, imageTarget));
+
+    setTargetImage(imageTarget);
+
+    Extents size(static_cast<int>(imageTarget->getWidth()),
+                 static_cast<int>(imageTarget->getHeight()), 1);
+
+    mState.clearImageDescs();
+    mState.setImageDesc(target, 0, ImageDesc(size, imageTarget->getFormat()));
+    mDirtyChannel.signal();
+
+    return NoError();
+}
+
+Extents Texture::getAttachmentSize(const ImageIndex &imageIndex) const
+{
+    return mState.getImageDesc(imageIndex).size;
+}
+
+const Format &Texture::getAttachmentFormat(GLenum /*binding*/, const ImageIndex &imageIndex) const
+{
+    return mState.getImageDesc(imageIndex).format;
+}
+
+GLsizei Texture::getAttachmentSamples(const ImageIndex &imageIndex) const
+{
+    return getSamples(imageIndex.type, 0);
+}
+
+void Texture::onAttach()
+{
+    addRef();
+}
+
+void Texture::onDetach()
+{
+    release();
+}
+
+GLuint Texture::getId() const
+{
+    return id();
+}
+
+void Texture::syncImplState()
+{
+    mTexture->syncState(mDirtyBits);
+    mDirtyBits.reset();
+}
+
+rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
+{
+    return mTexture;
+}
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/Texture.h b/src/third_party/angle/src/libANGLE/Texture.h
new file mode 100644
index 0000000..fce8590
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Texture.h
@@ -0,0 +1,443 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Texture.h: Defines the gl::Texture class [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#ifndef LIBANGLE_TEXTURE_H_
+#define LIBANGLE_TEXTURE_H_
+
+#include <vector>
+#include <map>
+
+#include "angle_gl.h"
+#include "common/debug.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+
+namespace egl
+{
+class Surface;
+class Stream;
+}
+
+namespace rx
+{
+class GLImplFactory;
+class TextureImpl;
+class TextureGL;
+}
+
+namespace gl
+{
+class ContextState;
+class Framebuffer;
+class Texture;
+
+bool IsMipmapFiltered(const SamplerState &samplerState);
+
+struct ImageDesc final
+{
+    ImageDesc();
+    ImageDesc(const Extents &size, const Format &format);
+    ImageDesc(const Extents &size,
+              const Format &format,
+              const GLsizei samples,
+              const GLboolean fixedSampleLocations);
+
+    ImageDesc(const ImageDesc &other) = default;
+    ImageDesc &operator=(const ImageDesc &other) = default;
+
+    Extents size;
+    Format format;
+    GLsizei samples;
+    GLboolean fixedSampleLocations;
+};
+
+struct SwizzleState final
+{
+    SwizzleState();
+    SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha);
+    SwizzleState(const SwizzleState &other) = default;
+    SwizzleState &operator=(const SwizzleState &other) = default;
+
+    bool swizzleRequired() const;
+
+    bool operator==(const SwizzleState &other) const;
+    bool operator!=(const SwizzleState &other) const;
+
+    GLenum swizzleRed;
+    GLenum swizzleGreen;
+    GLenum swizzleBlue;
+    GLenum swizzleAlpha;
+};
+
+// State from Table 6.9 (state per texture object) in the OpenGL ES 3.0.2 spec.
+struct TextureState final : private angle::NonCopyable
+{
+    TextureState(GLenum target);
+
+    bool swizzleRequired() const;
+    GLuint getEffectiveBaseLevel() const;
+    GLuint getEffectiveMaxLevel() const;
+
+    // Returns the value called "q" in the GLES 3.0.4 spec section 3.8.10.
+    GLuint getMipmapMaxLevel() const;
+
+    // Returns true if base level changed.
+    bool setBaseLevel(GLuint baseLevel);
+    void setMaxLevel(GLuint maxLevel);
+
+    bool isCubeComplete() const;
+    bool isSamplerComplete(const SamplerState &samplerState, const ContextState &data) const;
+
+    void invalidateCompletenessCache();
+
+    const ImageDesc &getImageDesc(GLenum target, size_t level) const;
+    const ImageDesc &getImageDesc(const ImageIndex &imageIndex) const;
+
+    GLenum getTarget() const { return mTarget; }
+    const SwizzleState &getSwizzleState() const { return mSwizzleState; }
+    const SamplerState &getSamplerState() const { return mSamplerState; }
+    GLenum getUsage() const { return mUsage; }
+
+  private:
+    // Texture needs access to the ImageDesc functions.
+    friend class Texture;
+    // TODO(jmadill): Remove TextureGL from friends.
+    friend class rx::TextureGL;
+    friend bool operator==(const TextureState &a, const TextureState &b);
+
+    bool computeSamplerCompleteness(const SamplerState &samplerState,
+                                    const ContextState &data) const;
+    bool computeMipmapCompleteness() const;
+    bool computeLevelCompleteness(GLenum target, size_t level) const;
+
+    GLenum getBaseImageTarget() const;
+
+    void setImageDesc(GLenum target, size_t level, const ImageDesc &desc);
+    void setImageDescChain(GLuint baselevel,
+                           GLuint maxLevel,
+                           Extents baseSize,
+                           const Format &format);
+    void setImageDescChainMultisample(Extents baseSize,
+                                      const Format &format,
+                                      GLsizei samples,
+                                      GLboolean fixedSampleLocations);
+
+    void clearImageDesc(GLenum target, size_t level);
+    void clearImageDescs();
+
+    const GLenum mTarget;
+
+    SwizzleState mSwizzleState;
+
+    SamplerState mSamplerState;
+
+    GLuint mBaseLevel;
+    GLuint mMaxLevel;
+
+    GLenum mDepthStencilTextureMode;
+
+    bool mImmutableFormat;
+    GLuint mImmutableLevels;
+
+    // From GL_ANGLE_texture_usage
+    GLenum mUsage;
+
+    std::vector<ImageDesc> mImageDescs;
+
+    struct SamplerCompletenessCache
+    {
+        SamplerCompletenessCache();
+
+        // All values that affect sampler completeness that are not stored within
+        // the texture itself
+        SamplerState samplerState;
+
+        // Result of the sampler completeness with the above parameters
+        bool samplerComplete;
+    };
+
+    mutable std::unordered_map<ContextID, SamplerCompletenessCache> mCompletenessCache;
+};
+
+bool operator==(const TextureState &a, const TextureState &b);
+bool operator!=(const TextureState &a, const TextureState &b);
+
+class Texture final : public egl::ImageSibling,
+                      public LabeledObject
+{
+  public:
+    Texture(rx::GLImplFactory *factory, GLuint id, GLenum target);
+    ~Texture() override;
+
+    void destroy(const Context *context) override {}
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    GLenum getTarget() const;
+
+    void setSwizzleRed(GLenum swizzleRed);
+    GLenum getSwizzleRed() const;
+
+    void setSwizzleGreen(GLenum swizzleGreen);
+    GLenum getSwizzleGreen() const;
+
+    void setSwizzleBlue(GLenum swizzleBlue);
+    GLenum getSwizzleBlue() const;
+
+    void setSwizzleAlpha(GLenum swizzleAlpha);
+    GLenum getSwizzleAlpha() const;
+
+    void setMinFilter(GLenum minFilter);
+    GLenum getMinFilter() const;
+
+    void setMagFilter(GLenum magFilter);
+    GLenum getMagFilter() const;
+
+    void setWrapS(GLenum wrapS);
+    GLenum getWrapS() const;
+
+    void setWrapT(GLenum wrapT);
+    GLenum getWrapT() const;
+
+    void setWrapR(GLenum wrapR);
+    GLenum getWrapR() const;
+
+    void setMaxAnisotropy(float maxAnisotropy);
+    float getMaxAnisotropy() const;
+
+    void setMinLod(GLfloat minLod);
+    GLfloat getMinLod() const;
+
+    void setMaxLod(GLfloat maxLod);
+    GLfloat getMaxLod() const;
+
+    void setCompareMode(GLenum compareMode);
+    GLenum getCompareMode() const;
+
+    void setCompareFunc(GLenum compareFunc);
+    GLenum getCompareFunc() const;
+
+    void setSRGBDecode(GLenum sRGBDecode);
+    GLenum getSRGBDecode() const;
+
+    const SamplerState &getSamplerState() const;
+
+    void setBaseLevel(GLuint baseLevel);
+    GLuint getBaseLevel() const;
+
+    void setMaxLevel(GLuint maxLevel);
+    GLuint getMaxLevel() const;
+
+    void setDepthStencilTextureMode(GLenum mode);
+    GLenum getDepthStencilTextureMode() const;
+
+    bool getImmutableFormat() const;
+
+    GLuint getImmutableLevels() const;
+
+    void setUsage(GLenum usage);
+    GLenum getUsage() const;
+
+    const TextureState &getTextureState() const;
+
+    size_t getWidth(GLenum target, size_t level) const;
+    size_t getHeight(GLenum target, size_t level) const;
+    size_t getDepth(GLenum target, size_t level) const;
+    GLsizei getSamples(GLenum target, size_t level) const;
+    GLboolean getFixedSampleLocations(GLenum target, size_t level) const;
+    const Format &getFormat(GLenum target, size_t level) const;
+
+    bool isMipmapComplete() const;
+
+    Error setImage(const Context *context,
+                   const PixelUnpackState &unpackState,
+                   GLenum target,
+                   size_t level,
+                   GLenum internalFormat,
+                   const Extents &size,
+                   GLenum format,
+                   GLenum type,
+                   const uint8_t *pixels);
+    Error setSubImage(const Context *context,
+                      const PixelUnpackState &unpackState,
+                      GLenum target,
+                      size_t level,
+                      const Box &area,
+                      GLenum format,
+                      GLenum type,
+                      const uint8_t *pixels);
+
+    Error setCompressedImage(const Context *context,
+                             const PixelUnpackState &unpackState,
+                             GLenum target,
+                             size_t level,
+                             GLenum internalFormat,
+                             const Extents &size,
+                             size_t imageSize,
+                             const uint8_t *pixels);
+    Error setCompressedSubImage(const Context *context,
+                                const PixelUnpackState &unpackState,
+                                GLenum target,
+                                size_t level,
+                                const Box &area,
+                                GLenum format,
+                                size_t imageSize,
+                                const uint8_t *pixels);
+
+    Error copyImage(const Context *context,
+                    GLenum target,
+                    size_t level,
+                    const Rectangle &sourceArea,
+                    GLenum internalFormat,
+                    const Framebuffer *source);
+    Error copySubImage(const Context *context,
+                       GLenum target,
+                       size_t level,
+                       const Offset &destOffset,
+                       const Rectangle &sourceArea,
+                       const Framebuffer *source);
+
+    Error copyTexture(const Context *context,
+                      GLenum target,
+                      size_t level,
+                      GLenum internalFormat,
+                      GLenum type,
+                      size_t sourceLevel,
+                      bool unpackFlipY,
+                      bool unpackPremultiplyAlpha,
+                      bool unpackUnmultiplyAlpha,
+                      const Texture *source);
+    Error copySubTexture(const Context *context,
+                         GLenum target,
+                         size_t level,
+                         const Offset &destOffset,
+                         size_t sourceLevel,
+                         const Rectangle &sourceArea,
+                         bool unpackFlipY,
+                         bool unpackPremultiplyAlpha,
+                         bool unpackUnmultiplyAlpha,
+                         const Texture *source);
+    Error copyCompressedTexture(const Context *context, const Texture *source);
+
+    Error setStorage(const Context *context,
+                     GLenum target,
+                     GLsizei levels,
+                     GLenum internalFormat,
+                     const Extents &size);
+
+    Error setStorageMultisample(const Context *context,
+                                GLenum target,
+                                GLsizei samples,
+                                GLint internalformat,
+                                const Extents &size,
+                                GLboolean fixedSampleLocations);
+
+    Error setEGLImageTarget(GLenum target, egl::Image *imageTarget);
+
+    Error generateMipmap(const Context *context);
+
+    egl::Surface *getBoundSurface() const;
+    egl::Stream *getBoundStream() const;
+
+    void invalidateCompletenessCache();
+
+    rx::TextureImpl *getImplementation() const { return mTexture; }
+
+    // FramebufferAttachmentObject implementation
+    Extents getAttachmentSize(const ImageIndex &imageIndex) const override;
+    const Format &getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const override;
+    GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const override;
+
+    void onAttach() override;
+    void onDetach() override;
+    GLuint getId() const override;
+
+    enum DirtyBitType
+    {
+        // Sampler state
+        DIRTY_BIT_MIN_FILTER,
+        DIRTY_BIT_MAG_FILTER,
+        DIRTY_BIT_WRAP_S,
+        DIRTY_BIT_WRAP_T,
+        DIRTY_BIT_WRAP_R,
+        DIRTY_BIT_MAX_ANISOTROPY,
+        DIRTY_BIT_MIN_LOD,
+        DIRTY_BIT_MAX_LOD,
+        DIRTY_BIT_COMPARE_MODE,
+        DIRTY_BIT_COMPARE_FUNC,
+        DIRTY_BIT_SRGB_DECODE,
+
+        // Texture state
+        DIRTY_BIT_SWIZZLE_RED,
+        DIRTY_BIT_SWIZZLE_GREEN,
+        DIRTY_BIT_SWIZZLE_BLUE,
+        DIRTY_BIT_SWIZZLE_ALPHA,
+        DIRTY_BIT_BASE_LEVEL,
+        DIRTY_BIT_MAX_LEVEL,
+
+        // Misc
+        DIRTY_BIT_LABEL,
+        DIRTY_BIT_USAGE,
+
+        DIRTY_BIT_COUNT,
+    };
+    using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
+
+    void syncImplState();
+    bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+  private:
+    rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
+
+    // ANGLE-only method, used internally
+    friend class egl::Surface;
+    void bindTexImageFromSurface(egl::Surface *surface);
+    void releaseTexImageFromSurface();
+
+    // ANGLE-only methods, used internally
+    friend class egl::Stream;
+    void bindStream(egl::Stream *stream);
+    void releaseStream();
+    void acquireImageFromStream(const egl::Stream::GLTextureDescription &desc);
+    void releaseImageFromStream();
+
+    TextureState mState;
+    DirtyBits mDirtyBits;
+    rx::TextureImpl *mTexture;
+
+    std::string mLabel;
+
+    void releaseTexImageInternal();
+
+    egl::Surface *mBoundSurface;
+    egl::Stream *mBoundStream;
+};
+
+inline bool operator==(const TextureState &a, const TextureState &b)
+{
+    return a.mSwizzleState == b.mSwizzleState && a.mSamplerState == b.mSamplerState &&
+           a.mBaseLevel == b.mBaseLevel && a.mMaxLevel == b.mMaxLevel &&
+           a.mImmutableFormat == b.mImmutableFormat && a.mImmutableLevels == b.mImmutableLevels &&
+           a.mUsage == b.mUsage;
+}
+
+inline bool operator!=(const TextureState &a, const TextureState &b)
+{
+    return !(a == b);
+}
+}
+
+#endif  // LIBANGLE_TEXTURE_H_
diff --git a/src/third_party/angle/src/libANGLE/Thread.cpp b/src/third_party/angle/src/libANGLE/Thread.cpp
new file mode 100644
index 0000000..1abf449
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Thread.cpp
@@ -0,0 +1,88 @@
+//
+// Copyright(c) 2016 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.
+//
+
+// Thread.cpp : Defines the Thread class which represents a global EGL thread.
+
+#include "libANGLE/Thread.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+
+namespace egl
+{
+Thread::Thread()
+    : mError(EGL_SUCCESS),
+      mAPI(EGL_OPENGL_ES_API),
+      mDisplay(static_cast<egl::Display *>(EGL_NO_DISPLAY)),
+      mDrawSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
+      mReadSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
+      mContext(static_cast<gl::Context *>(EGL_NO_CONTEXT))
+{
+}
+
+void Thread::setError(const Error &error)
+{
+    mError = error.getCode();
+}
+
+EGLint Thread::getError() const
+{
+    return mError;
+}
+
+void Thread::setAPI(EGLenum api)
+{
+    mAPI = api;
+}
+
+EGLenum Thread::getAPI() const
+{
+    return mAPI;
+}
+
+void Thread::setCurrent(Display *display,
+                        Surface *drawSurface,
+                        Surface *readSurface,
+                        gl::Context *context)
+{
+    mDisplay     = display;
+    mDrawSurface = drawSurface;
+    mReadSurface = readSurface;
+    mContext     = context;
+}
+
+Display *Thread::getDisplay() const
+{
+    return mDisplay;
+}
+
+Surface *Thread::getDrawSurface() const
+{
+    return mDrawSurface;
+}
+
+Surface *Thread::getReadSurface() const
+{
+    return mReadSurface;
+}
+
+gl::Context *Thread::getContext() const
+{
+    return mContext;
+}
+
+gl::Context *Thread::getValidContext() const
+{
+    if (mContext && mContext->isContextLost())
+    {
+        mContext->handleError(gl::Error(GL_OUT_OF_MEMORY, "Context has been lost."));
+        return nullptr;
+    }
+
+    return mContext;
+}
+
+}  // namespace egl
diff --git a/src/third_party/angle/src/libANGLE/Thread.h b/src/third_party/angle/src/libANGLE/Thread.h
new file mode 100644
index 0000000..7a67dc6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Thread.h
@@ -0,0 +1,57 @@
+//
+// Copyright(c) 2016 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.
+//
+
+// Thread.h : Defines the Thread class which represents a global EGL thread.
+
+#ifndef LIBANGLE_THREAD_H_
+#define LIBANGLE_THREAD_H_
+
+#include <EGL/egl.h>
+
+namespace gl
+{
+class Context;
+}  // namespace gl
+
+namespace egl
+{
+class Error;
+class Display;
+class Surface;
+
+class Thread
+{
+  public:
+    Thread();
+
+    void setError(const Error &error);
+    EGLint getError() const;
+
+    void setAPI(EGLenum api);
+    EGLenum getAPI() const;
+
+    void setCurrent(Display *display,
+                    Surface *drawSurface,
+                    Surface *readSurface,
+                    gl::Context *context);
+    Display *getDisplay() const;
+    Surface *getDrawSurface() const;
+    Surface *getReadSurface() const;
+    gl::Context *getContext() const;
+    gl::Context *getValidContext() const;
+
+  private:
+    EGLint mError;
+    EGLenum mAPI;
+    egl::Display *mDisplay;
+    egl::Surface *mDrawSurface;
+    egl::Surface *mReadSurface;
+    gl::Context *mContext;
+};
+
+}  // namespace egl
+
+#endif  // LIBANGLE_THREAD_H_
diff --git a/src/third_party/angle/src/libANGLE/TransformFeedback.cpp b/src/third_party/angle/src/libANGLE/TransformFeedback.cpp
new file mode 100644
index 0000000..70a12cd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/TransformFeedback.cpp
@@ -0,0 +1,211 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/TransformFeedback.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace gl
+{
+
+TransformFeedbackState::TransformFeedbackState(size_t maxIndexedBuffers)
+    : mLabel(),
+      mActive(false),
+      mPrimitiveMode(GL_NONE),
+      mPaused(false),
+      mProgram(nullptr),
+      mGenericBuffer(),
+      mIndexedBuffers(maxIndexedBuffers)
+{
+}
+
+const BindingPointer<Buffer> &TransformFeedbackState::getGenericBuffer() const
+{
+    return mGenericBuffer;
+}
+
+const OffsetBindingPointer<Buffer> &TransformFeedbackState::getIndexedBuffer(size_t idx) const
+{
+    return mIndexedBuffers[idx];
+}
+
+const std::vector<OffsetBindingPointer<Buffer>> &TransformFeedbackState::getIndexedBuffers() const
+{
+    return mIndexedBuffers;
+}
+
+TransformFeedback::TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps)
+    : RefCountObject(id),
+      mState(caps.maxTransformFeedbackSeparateAttributes),
+      mImplementation(implFactory->createTransformFeedback(mState))
+{
+    ASSERT(mImplementation != nullptr);
+}
+
+void TransformFeedback::destroy(const Context *context)
+{
+    if (mState.mProgram)
+    {
+        mState.mProgram->release(context);
+        mState.mProgram = nullptr;
+    }
+}
+
+TransformFeedback::~TransformFeedback()
+{
+    ASSERT(!mState.mProgram);
+    mState.mGenericBuffer.set(nullptr);
+    for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
+    {
+        mState.mIndexedBuffers[i].set(nullptr);
+    }
+
+    SafeDelete(mImplementation);
+}
+
+void TransformFeedback::setLabel(const std::string &label)
+{
+    mState.mLabel = label;
+}
+
+const std::string &TransformFeedback::getLabel() const
+{
+    return mState.mLabel;
+}
+
+void TransformFeedback::begin(const Context *context, GLenum primitiveMode, Program *program)
+{
+    mState.mActive        = true;
+    mState.mPrimitiveMode = primitiveMode;
+    mState.mPaused        = false;
+    mImplementation->begin(primitiveMode);
+    bindProgram(context, program);
+}
+
+void TransformFeedback::end(const Context *context)
+{
+    mState.mActive        = false;
+    mState.mPrimitiveMode = GL_NONE;
+    mState.mPaused        = false;
+    mImplementation->end();
+    if (mState.mProgram)
+    {
+        mState.mProgram->release(context);
+        mState.mProgram = nullptr;
+    }
+}
+
+void TransformFeedback::pause()
+{
+    mState.mPaused = true;
+    mImplementation->pause();
+}
+
+void TransformFeedback::resume()
+{
+    mState.mPaused = false;
+    mImplementation->resume();
+}
+
+bool TransformFeedback::isActive() const
+{
+    return mState.mActive;
+}
+
+bool TransformFeedback::isPaused() const
+{
+    return mState.mPaused;
+}
+
+GLenum TransformFeedback::getPrimitiveMode() const
+{
+    return mState.mPrimitiveMode;
+}
+
+void TransformFeedback::bindProgram(const Context *context, Program *program)
+{
+    if (mState.mProgram != program)
+    {
+        if (mState.mProgram != nullptr)
+        {
+            mState.mProgram->release(context);
+        }
+        mState.mProgram = program;
+        if (mState.mProgram != nullptr)
+        {
+            mState.mProgram->addRef();
+        }
+    }
+}
+
+bool TransformFeedback::hasBoundProgram(GLuint program) const
+{
+    return mState.mProgram != nullptr && mState.mProgram->id() == program;
+}
+
+void TransformFeedback::bindGenericBuffer(Buffer *buffer)
+{
+    mState.mGenericBuffer.set(buffer);
+    mImplementation->bindGenericBuffer(mState.mGenericBuffer);
+}
+
+void TransformFeedback::detachBuffer(GLuint bufferName)
+{
+    for (size_t index = 0; index < mState.mIndexedBuffers.size(); index++)
+    {
+        if (mState.mIndexedBuffers[index].id() == bufferName)
+        {
+            mState.mIndexedBuffers[index].set(nullptr);
+            mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
+        }
+    }
+
+    if (mState.mGenericBuffer.id() == bufferName)
+    {
+        mState.mGenericBuffer.set(nullptr);
+        mImplementation->bindGenericBuffer(mState.mGenericBuffer);
+    }
+}
+
+const BindingPointer<Buffer> &TransformFeedback::getGenericBuffer() const
+{
+    return mState.mGenericBuffer;
+}
+
+void TransformFeedback::bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size)
+{
+    ASSERT(index < mState.mIndexedBuffers.size());
+    mState.mIndexedBuffers[index].set(buffer, offset, size);
+    mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
+}
+
+const OffsetBindingPointer<Buffer> &TransformFeedback::getIndexedBuffer(size_t index) const
+{
+    ASSERT(index < mState.mIndexedBuffers.size());
+    return mState.mIndexedBuffers[index];
+}
+
+size_t TransformFeedback::getIndexedBufferCount() const
+{
+    return mState.mIndexedBuffers.size();
+}
+
+rx::TransformFeedbackImpl *TransformFeedback::getImplementation()
+{
+    return mImplementation;
+}
+
+const rx::TransformFeedbackImpl *TransformFeedback::getImplementation() const
+{
+    return mImplementation;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/TransformFeedback.h b/src/third_party/angle/src/libANGLE/TransformFeedback.h
new file mode 100644
index 0000000..2c0faff
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/TransformFeedback.h
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_TRANSFORM_FEEDBACK_H_
+#define LIBANGLE_TRANSFORM_FEEDBACK_H_
+
+#include "libANGLE/RefCountObject.h"
+
+#include "common/angleutils.h"
+#include "libANGLE/Debug.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+class GLImplFactory;
+class TransformFeedbackImpl;
+}
+
+namespace gl
+{
+class Buffer;
+struct Caps;
+class Context;
+class Program;
+
+class TransformFeedbackState final : angle::NonCopyable
+{
+  public:
+    TransformFeedbackState(size_t maxIndexedBuffers);
+
+    const BindingPointer<Buffer> &getGenericBuffer() const;
+    const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t idx) const;
+    const std::vector<OffsetBindingPointer<Buffer>> &getIndexedBuffers() const;
+
+  private:
+    friend class TransformFeedback;
+
+    std::string mLabel;
+
+    bool mActive;
+    GLenum mPrimitiveMode;
+    bool mPaused;
+
+    Program *mProgram;
+
+    BindingPointer<Buffer> mGenericBuffer;
+    std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
+};
+
+class TransformFeedback final : public RefCountObject, public LabeledObject
+{
+  public:
+    TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps);
+    virtual ~TransformFeedback();
+    void destroy(const Context *context) override;
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    void begin(const Context *context, GLenum primitiveMode, Program *program);
+    void end(const Context *context);
+    void pause();
+    void resume();
+
+    bool isActive() const;
+    bool isPaused() const;
+    GLenum getPrimitiveMode() const;
+
+    bool hasBoundProgram(GLuint program) const;
+
+    void bindGenericBuffer(Buffer *buffer);
+    const BindingPointer<Buffer> &getGenericBuffer() const;
+
+    void bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size);
+    const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t index) const;
+    size_t getIndexedBufferCount() const;
+
+    void detachBuffer(GLuint bufferName);
+
+    rx::TransformFeedbackImpl *getImplementation();
+    const rx::TransformFeedbackImpl *getImplementation() const;
+
+  private:
+    void bindProgram(const Context *context, Program *program);
+
+    TransformFeedbackState mState;
+    rx::TransformFeedbackImpl* mImplementation;
+};
+
+}
+
+#endif // LIBANGLE_TRANSFORM_FEEDBACK_H_
diff --git a/src/third_party/angle/src/libANGLE/TransformFeedback_unittest.cpp b/src/third_party/angle/src/libANGLE/TransformFeedback_unittest.cpp
new file mode 100644
index 0000000..946db6b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/TransformFeedback_unittest.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/renderer/BufferImpl_mock.h"
+#include "libANGLE/renderer/TransformFeedbackImpl_mock.h"
+#include "tests/angle_unittests_utils.h"
+
+using ::testing::_;
+using ::testing::get;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+
+namespace
+{
+
+ACTION(CreateMockTransformFeedbackImpl)
+{
+    return new rx::MockTransformFeedbackImpl(arg0);
+}
+
+class TransformFeedbackTest : public testing::Test
+{
+  protected:
+    TransformFeedbackTest() : mImpl(nullptr), mFeedback(nullptr) {}
+
+    void SetUp() override
+    {
+        EXPECT_CALL(mMockFactory, createTransformFeedback(_))
+            .WillOnce(CreateMockTransformFeedbackImpl())
+            .RetiresOnSaturation();
+
+        // Set a reasonable number of tf attributes
+        mCaps.maxTransformFeedbackSeparateAttributes = 8;
+
+        mFeedback = new gl::TransformFeedback(&mMockFactory, 1, mCaps);
+        mFeedback->addRef();
+
+        mImpl = rx::GetImplAs<rx::MockTransformFeedbackImpl>(mFeedback);
+        EXPECT_CALL(*mImpl, destructor());
+    }
+
+    void TearDown() override
+    {
+        if (mFeedback)
+        {
+            mFeedback->release();
+        }
+
+        // Only needed because the mock is leaked if bugs are present,
+        // which logs an error, but does not cause the test to fail.
+        // Ordinarily mocks are verified when destroyed.
+        testing::Mock::VerifyAndClear(mImpl);
+    }
+
+    rx::MockGLFactory mMockFactory;
+    rx::MockTransformFeedbackImpl* mImpl;
+    gl::TransformFeedback* mFeedback;
+    gl::Caps mCaps;
+};
+
+TEST_F(TransformFeedbackTest, SideEffectsOfStartAndStop)
+{
+    testing::InSequence seq;
+
+    EXPECT_FALSE(mFeedback->isActive());
+    EXPECT_CALL(*mImpl, begin(GL_TRIANGLES));
+    mFeedback->begin(nullptr, GL_TRIANGLES, nullptr);
+    EXPECT_TRUE(mFeedback->isActive());
+    EXPECT_EQ(static_cast<GLenum>(GL_TRIANGLES), mFeedback->getPrimitiveMode());
+    EXPECT_CALL(*mImpl, end());
+    mFeedback->end(nullptr);
+    EXPECT_FALSE(mFeedback->isActive());
+}
+
+TEST_F(TransformFeedbackTest, SideEffectsOfPauseAndResume)
+{
+    testing::InSequence seq;
+
+    EXPECT_FALSE(mFeedback->isActive());
+    EXPECT_CALL(*mImpl, begin(GL_TRIANGLES));
+    mFeedback->begin(nullptr, GL_TRIANGLES, nullptr);
+    EXPECT_FALSE(mFeedback->isPaused());
+    EXPECT_CALL(*mImpl, pause());
+    mFeedback->pause();
+    EXPECT_TRUE(mFeedback->isPaused());
+    EXPECT_CALL(*mImpl, resume());
+    mFeedback->resume();
+    EXPECT_FALSE(mFeedback->isPaused());
+    EXPECT_CALL(*mImpl, end());
+    mFeedback->end(nullptr);
+}
+
+TEST_F(TransformFeedbackTest, BufferBinding)
+{
+    rx::MockBufferImpl *bufferImpl = new rx::MockBufferImpl;
+    EXPECT_CALL(*bufferImpl, destructor()).Times(1).RetiresOnSaturation();
+
+    rx::MockGLFactory mockGLFactory;
+    EXPECT_CALL(mockGLFactory, createBuffer(_))
+        .Times(1)
+        .WillOnce(Return(bufferImpl))
+        .RetiresOnSaturation();
+
+    gl::Buffer *buffer = new gl::Buffer(&mockGLFactory, 1);
+
+    static const size_t bindIndex = 0;
+
+    EXPECT_EQ(mFeedback->getIndexedBufferCount(), mCaps.maxTransformFeedbackSeparateAttributes);
+
+    EXPECT_CALL(*mImpl, bindGenericBuffer(_));
+    mFeedback->bindGenericBuffer(buffer);
+    EXPECT_EQ(mFeedback->getGenericBuffer().get(), buffer);
+
+    EXPECT_CALL(*mImpl, bindIndexedBuffer(_, _));
+    mFeedback->bindIndexedBuffer(bindIndex, buffer, 0, 1);
+    for (size_t i = 0; i < mFeedback->getIndexedBufferCount(); i++)
+    {
+        if (i == bindIndex)
+        {
+            EXPECT_EQ(mFeedback->getIndexedBuffer(i).get(), buffer);
+        }
+        else
+        {
+            EXPECT_EQ(mFeedback->getIndexedBuffer(i).get(), nullptr);
+        }
+    }
+
+    // force-release the feedback object to ensure the buffer is released.
+    const size_t releaseCount = mFeedback->getRefCount();
+    for (size_t count = 0; count < releaseCount; ++count)
+    {
+        mFeedback->release();
+    }
+
+    mFeedback = nullptr;
+
+    testing::Mock::VerifyAndClear(bufferImpl);
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/libANGLE/Uniform.cpp b/src/third_party/angle/src/libANGLE/Uniform.cpp
new file mode 100644
index 0000000..a531159
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Uniform.cpp
@@ -0,0 +1,169 @@
+//
+// Copyright (c) 2010-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/Uniform.h"
+
+#include "common/utilities.h"
+
+#include <cstring>
+
+namespace gl
+{
+
+LinkedUniform::LinkedUniform()
+    : blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
+{
+}
+
+LinkedUniform::LinkedUniform(GLenum typeIn,
+                             GLenum precisionIn,
+                             const std::string &nameIn,
+                             unsigned int arraySizeIn,
+                             const int bindingIn,
+                             const int locationIn,
+                             const int blockIndexIn,
+                             const sh::BlockMemberInfo &blockInfoIn)
+    : blockIndex(blockIndexIn), blockInfo(blockInfoIn)
+{
+    type      = typeIn;
+    precision = precisionIn;
+    name      = nameIn;
+    arraySize = arraySizeIn;
+    binding   = bindingIn;
+    location  = locationIn;
+}
+
+LinkedUniform::LinkedUniform(const sh::Uniform &uniform)
+    : sh::Uniform(uniform), blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
+{
+}
+
+LinkedUniform::LinkedUniform(const LinkedUniform &uniform)
+    : sh::Uniform(uniform), blockIndex(uniform.blockIndex), blockInfo(uniform.blockInfo)
+{
+    // This function is not intended to be called during runtime.
+    ASSERT(uniform.mLazyData.empty());
+}
+
+LinkedUniform &LinkedUniform::operator=(const LinkedUniform &uniform)
+{
+    // This function is not intended to be called during runtime.
+    ASSERT(uniform.mLazyData.empty());
+
+    sh::Uniform::operator=(uniform);
+    blockIndex           = uniform.blockIndex;
+    blockInfo            = uniform.blockInfo;
+
+    return *this;
+}
+
+LinkedUniform::~LinkedUniform()
+{
+}
+
+bool LinkedUniform::isInDefaultBlock() const
+{
+    return blockIndex == -1;
+}
+
+size_t LinkedUniform::dataSize() const
+{
+    ASSERT(type != GL_STRUCT_ANGLEX);
+    if (mLazyData.empty())
+    {
+        mLazyData.resize(VariableExternalSize(type) * elementCount());
+        ASSERT(!mLazyData.empty());
+    }
+
+    return mLazyData.size();
+}
+
+uint8_t *LinkedUniform::data()
+{
+    if (mLazyData.empty())
+    {
+        // dataSize() will init the data store.
+        size_t size = dataSize();
+        memset(mLazyData.data(), 0, size);
+    }
+
+    return mLazyData.data();
+}
+
+const uint8_t *LinkedUniform::data() const
+{
+    return const_cast<LinkedUniform *>(this)->data();
+}
+
+bool LinkedUniform::isSampler() const
+{
+    return IsSamplerType(type);
+}
+
+bool LinkedUniform::isImage() const
+{
+    return IsImageType(type);
+}
+
+bool LinkedUniform::isField() const
+{
+    return name.find('.') != std::string::npos;
+}
+
+size_t LinkedUniform::getElementSize() const
+{
+    return VariableExternalSize(type);
+}
+
+size_t LinkedUniform::getElementComponents() const
+{
+    return VariableComponentCount(type);
+}
+
+uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex)
+{
+    ASSERT((!isArray() && elementIndex == 0) || (isArray() && elementIndex < arraySize));
+    return data() + (elementIndex > 0 ? (getElementSize() * elementIndex) : 0u);
+}
+
+const uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex) const
+{
+    return const_cast<LinkedUniform *>(this)->getDataPtrToElement(elementIndex);
+}
+
+UniformBlock::UniformBlock()
+    : isArray(false),
+      arrayElement(0),
+      dataSize(0),
+      vertexStaticUse(false),
+      fragmentStaticUse(false),
+      computeStaticUse(false)
+{
+}
+
+UniformBlock::UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn)
+    : name(nameIn),
+      isArray(isArrayIn),
+      arrayElement(arrayElementIn),
+      dataSize(0),
+      vertexStaticUse(false),
+      fragmentStaticUse(false),
+      computeStaticUse(false)
+{
+}
+
+std::string UniformBlock::nameWithArrayIndex() const
+{
+    std::stringstream fullNameStr;
+    fullNameStr << name;
+    if (isArray)
+    {
+        fullNameStr << "[" << arrayElement << "]";
+    }
+
+    return fullNameStr.str();
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/Uniform.h b/src/third_party/angle/src/libANGLE/Uniform.h
new file mode 100644
index 0000000..cfba68e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Uniform.h
@@ -0,0 +1,82 @@
+//
+// Copyright (c) 2010-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_UNIFORM_H_
+#define LIBANGLE_UNIFORM_H_
+
+#include <string>
+#include <vector>
+
+#include "angle_gl.h"
+#include "common/debug.h"
+#include "common/MemoryBuffer.h"
+#include "compiler/translator/blocklayout.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+
+// Helper struct representing a single shader uniform
+struct LinkedUniform : public sh::Uniform
+{
+    LinkedUniform();
+    LinkedUniform(GLenum type,
+                  GLenum precision,
+                  const std::string &name,
+                  unsigned int arraySize,
+                  const int binding,
+                  const int location,
+                  const int blockIndex,
+                  const sh::BlockMemberInfo &blockInfo);
+    LinkedUniform(const sh::Uniform &uniform);
+    LinkedUniform(const LinkedUniform &uniform);
+    LinkedUniform &operator=(const LinkedUniform &uniform);
+    ~LinkedUniform();
+
+    size_t dataSize() const;
+    uint8_t *data();
+    const uint8_t *data() const;
+    bool isSampler() const;
+    bool isImage() const;
+    bool isInDefaultBlock() const;
+    bool isField() const;
+    size_t getElementSize() const;
+    size_t getElementComponents() const;
+    uint8_t *getDataPtrToElement(size_t elementIndex);
+    const uint8_t *getDataPtrToElement(size_t elementIndex) const;
+
+    int blockIndex;
+    sh::BlockMemberInfo blockInfo;
+
+  private:
+    mutable angle::MemoryBuffer mLazyData;
+};
+
+// Helper struct representing a single shader uniform block
+struct UniformBlock
+{
+    UniformBlock();
+    UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn);
+    UniformBlock(const UniformBlock &other) = default;
+    UniformBlock &operator=(const UniformBlock &other) = default;
+
+    std::string nameWithArrayIndex() const;
+
+    std::string name;
+    bool isArray;
+    unsigned int arrayElement;
+    unsigned int dataSize;
+
+    bool vertexStaticUse;
+    bool fragmentStaticUse;
+    bool computeStaticUse;
+
+    std::vector<unsigned int> memberUniformIndexes;
+};
+
+}
+
+#endif   // LIBANGLE_UNIFORM_H_
diff --git a/src/third_party/angle/src/libANGLE/UniformLinker.cpp b/src/third_party/angle/src/libANGLE/UniformLinker.cpp
new file mode 100644
index 0000000..8b735c4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/UniformLinker.cpp
@@ -0,0 +1,491 @@
+//
+// Copyright (c) 2017 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.
+//
+
+// UniformLinker.cpp: implements link-time checks for default block uniforms, and generates uniform
+// locations. Populates data structures related to uniforms so that they can be stored in program
+// state.
+
+#include "libANGLE/UniformLinker.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/features.h"
+
+namespace gl
+{
+
+namespace
+{
+
+LinkedUniform *FindUniform(std::vector<LinkedUniform> &list, const std::string &name)
+{
+    for (LinkedUniform &uniform : list)
+    {
+        if (uniform.name == name)
+            return &uniform;
+    }
+
+    return nullptr;
+}
+
+}  // anonymouse namespace
+
+UniformLinker::UniformLinker(const ProgramState &state) : mState(state)
+{
+}
+
+void UniformLinker::getResults(std::vector<LinkedUniform> *uniforms,
+                               std::vector<VariableLocation> *uniformLocations)
+{
+    uniforms->swap(mUniforms);
+    uniformLocations->swap(mUniformLocations);
+}
+
+bool UniformLinker::link(InfoLog &infoLog,
+                         const Caps &caps,
+                         const Program::Bindings &uniformLocationBindings)
+{
+    if (mState.getAttachedVertexShader() && mState.getAttachedFragmentShader())
+    {
+        ASSERT(mState.getAttachedComputeShader() == nullptr);
+        if (!validateVertexAndFragmentUniforms(infoLog))
+        {
+            return false;
+        }
+    }
+
+    // Flatten the uniforms list (nested fields) into a simple list (no nesting).
+    // Also check the maximum uniform vector and sampler counts.
+    if (!flattenUniformsAndCheckCaps(caps, infoLog))
+    {
+        return false;
+    }
+
+    if (!indexUniforms(infoLog, uniformLocationBindings))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool UniformLinker::validateVertexAndFragmentUniforms(InfoLog &infoLog) const
+{
+    // Check that uniforms defined in the vertex and fragment shaders are identical
+    std::map<std::string, LinkedUniform> linkedUniforms;
+    const std::vector<sh::Uniform> &vertexUniforms =
+        mState.getAttachedVertexShader()->getUniforms();
+    const std::vector<sh::Uniform> &fragmentUniforms =
+        mState.getAttachedFragmentShader()->getUniforms();
+
+    for (const sh::Uniform &vertexUniform : vertexUniforms)
+    {
+        linkedUniforms[vertexUniform.name] = LinkedUniform(vertexUniform);
+    }
+
+    for (const sh::Uniform &fragmentUniform : fragmentUniforms)
+    {
+        auto entry = linkedUniforms.find(fragmentUniform.name);
+        if (entry != linkedUniforms.end())
+        {
+            LinkedUniform *linkedUniform   = &entry->second;
+            const std::string &uniformName = "uniform '" + linkedUniform->name + "'";
+            if (!linkValidateUniforms(infoLog, uniformName, *linkedUniform, fragmentUniform))
+            {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+// GLSL ES Spec 3.00.3, section 4.3.5.
+bool UniformLinker::linkValidateUniforms(InfoLog &infoLog,
+                                         const std::string &uniformName,
+                                         const sh::Uniform &vertexUniform,
+                                         const sh::Uniform &fragmentUniform)
+{
+#if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION == ANGLE_ENABLED
+    const bool validatePrecision = true;
+#else
+    const bool validatePrecision = false;
+#endif
+
+    if (!Program::linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform,
+                                            validatePrecision))
+    {
+        return false;
+    }
+
+    // GLSL ES Spec 3.10.4, section 4.4.5.
+    if (vertexUniform.binding != -1 && fragmentUniform.binding != -1 &&
+        vertexUniform.binding != fragmentUniform.binding)
+    {
+        infoLog << "Binding layout qualifiers for " << uniformName
+                << " differ between vertex and fragment shaders.";
+        return false;
+    }
+
+    // GLSL ES Spec 3.10.4, section 9.2.1.
+    if (vertexUniform.location != -1 && fragmentUniform.location != -1 &&
+        vertexUniform.location != fragmentUniform.location)
+    {
+        infoLog << "Location layout qualifiers for " << uniformName
+                << " differ between vertex and fragment shaders.";
+        return false;
+    }
+
+    return true;
+}
+
+bool UniformLinker::indexUniforms(InfoLog &infoLog,
+                                  const Program::Bindings &uniformLocationBindings)
+{
+    // All the locations where another uniform can't be located.
+    std::set<GLuint> reservedLocations;
+    // Locations which have been allocated for an unused uniform.
+    std::set<GLuint> ignoredLocations;
+
+    int maxUniformLocation = -1;
+
+    // Gather uniform locations that have been set either using the bindUniformLocation API or by
+    // using a location layout qualifier and check conflicts between them.
+    if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings,
+                                                 &reservedLocations, &ignoredLocations,
+                                                 &maxUniformLocation))
+    {
+        return false;
+    }
+
+    // Conflicts have been checked, now we can prune non-statically used uniforms. Code further down
+    // the line relies on only having statically used uniforms in mUniforms.
+    pruneUnusedUniforms();
+
+    // Gather uniforms that have their location pre-set and uniforms that don't yet have a location.
+    std::vector<VariableLocation> unlocatedUniforms;
+    std::map<GLuint, VariableLocation> preLocatedUniforms;
+
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+    {
+        const LinkedUniform &uniform = mUniforms[uniformIndex];
+
+        if (uniform.isBuiltIn())
+        {
+            continue;
+        }
+
+        int preSetLocation = uniformLocationBindings.getBinding(uniform.name);
+        int shaderLocation = uniform.location;
+
+        if (shaderLocation != -1)
+        {
+            preSetLocation = shaderLocation;
+        }
+
+        for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++)
+        {
+            VariableLocation location(uniform.name, arrayIndex,
+                                      static_cast<unsigned int>(uniformIndex));
+
+            if ((arrayIndex == 0 && preSetLocation != -1) || shaderLocation != -1)
+            {
+                int elementLocation                 = preSetLocation + arrayIndex;
+                preLocatedUniforms[elementLocation] = location;
+            }
+            else
+            {
+                unlocatedUniforms.push_back(location);
+            }
+        }
+    }
+
+    // Make enough space for all uniforms, with pre-set locations or not.
+    mUniformLocations.resize(
+        std::max(unlocatedUniforms.size() + preLocatedUniforms.size() + ignoredLocations.size(),
+                 static_cast<size_t>(maxUniformLocation + 1)));
+
+    // Assign uniforms with pre-set locations
+    for (const auto &uniform : preLocatedUniforms)
+    {
+        mUniformLocations[uniform.first] = uniform.second;
+    }
+
+    // Assign ignored uniforms
+    for (const auto &ignoredLocation : ignoredLocations)
+    {
+        mUniformLocations[ignoredLocation].ignored = true;
+    }
+
+    // Automatically assign locations for the rest of the uniforms
+    size_t nextUniformLocation = 0;
+    for (const auto &unlocatedUniform : unlocatedUniforms)
+    {
+        while (mUniformLocations[nextUniformLocation].used ||
+               mUniformLocations[nextUniformLocation].ignored)
+        {
+            nextUniformLocation++;
+        }
+
+        ASSERT(nextUniformLocation < mUniformLocations.size());
+        mUniformLocations[nextUniformLocation] = unlocatedUniform;
+        nextUniformLocation++;
+    }
+
+    return true;
+}
+
+bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
+    InfoLog &infoLog,
+    const Program::Bindings &uniformLocationBindings,
+    std::set<GLuint> *reservedLocations,
+    std::set<GLuint> *ignoredLocations,
+    int *maxUniformLocation)
+{
+    for (const LinkedUniform &uniform : mUniforms)
+    {
+        if (uniform.isBuiltIn())
+        {
+            continue;
+        }
+
+        int apiBoundLocation = uniformLocationBindings.getBinding(uniform.name);
+        int shaderLocation   = uniform.location;
+
+        if (shaderLocation != -1)
+        {
+            for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++)
+            {
+                // GLSL ES 3.10 section 4.4.3
+                int elementLocation = shaderLocation + arrayIndex;
+                *maxUniformLocation = std::max(*maxUniformLocation, elementLocation);
+                if (reservedLocations->find(elementLocation) != reservedLocations->end())
+                {
+                    infoLog << "Multiple uniforms bound to location " << elementLocation << ".";
+                    return false;
+                }
+                reservedLocations->insert(elementLocation);
+                if (!uniform.staticUse)
+                {
+                    ignoredLocations->insert(elementLocation);
+                }
+            }
+        }
+        else if (apiBoundLocation != -1 && uniform.staticUse)
+        {
+            // Only the first location is reserved even if the uniform is an array.
+            *maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation);
+            if (reservedLocations->find(apiBoundLocation) != reservedLocations->end())
+            {
+                infoLog << "Multiple uniforms bound to location " << apiBoundLocation << ".";
+                return false;
+            }
+            reservedLocations->insert(apiBoundLocation);
+        }
+    }
+
+    // Record the uniform locations that were bound using the API for uniforms that were not found
+    // from the shader. Other uniforms should not be assigned to those locations.
+    for (const auto &locationBinding : uniformLocationBindings)
+    {
+        GLuint location = locationBinding.second;
+        if (reservedLocations->find(location) == reservedLocations->end())
+        {
+            ignoredLocations->insert(location);
+            *maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location));
+        }
+    }
+
+    return true;
+}
+
+void UniformLinker::pruneUnusedUniforms()
+{
+    auto uniformIter = mUniforms.begin();
+    while (uniformIter != mUniforms.end())
+    {
+        if (uniformIter->staticUse)
+        {
+            ++uniformIter;
+        }
+        else
+        {
+            uniformIter = mUniforms.erase(uniformIter);
+        }
+    }
+}
+
+bool UniformLinker::flattenUniformsAndCheckCapsForShader(
+    const Shader &shader,
+    GLuint maxUniformComponents,
+    GLuint maxTextureImageUnits,
+    const std::string &componentsErrorMessage,
+    const std::string &samplerErrorMessage,
+    std::vector<LinkedUniform> &samplerUniforms,
+    InfoLog &infoLog)
+{
+    VectorAndSamplerCount vasCount;
+    for (const sh::Uniform &uniform : shader.getUniforms())
+    {
+        vasCount += flattenUniform(uniform, &samplerUniforms);
+    }
+
+    if (vasCount.vectorCount > maxUniformComponents)
+    {
+        infoLog << componentsErrorMessage << maxUniformComponents << ").";
+        return false;
+    }
+
+    if (vasCount.samplerCount > maxTextureImageUnits)
+    {
+        infoLog << samplerErrorMessage << maxTextureImageUnits << ").";
+        return false;
+    }
+
+    return true;
+}
+
+bool UniformLinker::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
+{
+    std::vector<LinkedUniform> samplerUniforms;
+
+    if (mState.getAttachedComputeShader())
+    {
+        const Shader *computeShader = mState.getAttachedComputeShader();
+
+        // TODO (mradev): check whether we need finer-grained component counting
+        if (!flattenUniformsAndCheckCapsForShader(
+                *computeShader, caps.maxComputeUniformComponents / 4,
+                caps.maxComputeTextureImageUnits,
+                "Compute shader active uniforms exceed MAX_COMPUTE_UNIFORM_COMPONENTS (",
+                "Compute shader sampler count exceeds MAX_COMPUTE_TEXTURE_IMAGE_UNITS (",
+                samplerUniforms, infoLog))
+        {
+            return false;
+        }
+    }
+    else
+    {
+        const Shader *vertexShader = mState.getAttachedVertexShader();
+
+        if (!flattenUniformsAndCheckCapsForShader(
+                *vertexShader, caps.maxVertexUniformVectors, caps.maxVertexTextureImageUnits,
+                "Vertex shader active uniforms exceed MAX_VERTEX_UNIFORM_VECTORS (",
+                "Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (",
+                samplerUniforms, infoLog))
+        {
+            return false;
+        }
+        const Shader *fragmentShader = mState.getAttachedFragmentShader();
+
+        if (!flattenUniformsAndCheckCapsForShader(
+                *fragmentShader, caps.maxFragmentUniformVectors, caps.maxTextureImageUnits,
+                "Fragment shader active uniforms exceed MAX_FRAGMENT_UNIFORM_VECTORS (",
+                "Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (", samplerUniforms,
+                infoLog))
+        {
+            return false;
+        }
+    }
+
+    mUniforms.insert(mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end());
+    return true;
+}
+
+UniformLinker::VectorAndSamplerCount UniformLinker::flattenUniform(
+    const sh::Uniform &uniform,
+    std::vector<LinkedUniform> *samplerUniforms)
+{
+    int location                          = uniform.location;
+    VectorAndSamplerCount uniformVasCount = flattenUniformImpl(
+        uniform, uniform.name, samplerUniforms, uniform.staticUse, uniform.binding, &location);
+    if (uniform.staticUse)
+    {
+        return uniformVasCount;
+    }
+    return VectorAndSamplerCount();
+}
+
+UniformLinker::VectorAndSamplerCount UniformLinker::flattenUniformImpl(
+    const sh::ShaderVariable &uniform,
+    const std::string &fullName,
+    std::vector<LinkedUniform> *samplerUniforms,
+    bool markStaticUse,
+    int binding,
+    int *location)
+{
+    ASSERT(location);
+    VectorAndSamplerCount vectorAndSamplerCount;
+
+    if (uniform.isStruct())
+    {
+        for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
+        {
+            const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
+
+            for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
+            {
+                const sh::ShaderVariable &field  = uniform.fields[fieldIndex];
+                const std::string &fieldFullName = (fullName + elementString + "." + field.name);
+
+                vectorAndSamplerCount += flattenUniformImpl(field, fieldFullName, samplerUniforms,
+                                                            markStaticUse, -1, location);
+            }
+        }
+
+        return vectorAndSamplerCount;
+    }
+
+    // Not a struct
+    bool isSampler                              = IsSamplerType(uniform.type);
+    std::vector<gl::LinkedUniform> *uniformList = &mUniforms;
+    if (isSampler)
+    {
+        // Store sampler uniforms separately, so we'll append them to the end of the list.
+        uniformList = samplerUniforms;
+    }
+    LinkedUniform *existingUniform = FindUniform(*uniformList, fullName);
+    if (existingUniform)
+    {
+        if (binding != -1)
+        {
+            existingUniform->binding = binding;
+        }
+        if (*location != -1)
+        {
+            existingUniform->location = *location;
+        }
+        if (markStaticUse)
+        {
+            existingUniform->staticUse = true;
+        }
+    }
+    else
+    {
+        LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
+                                    binding, *location, -1,
+                                    sh::BlockMemberInfo::getDefaultBlockInfo());
+        linkedUniform.staticUse = markStaticUse;
+        uniformList->push_back(linkedUniform);
+    }
+
+    unsigned int elementCount = uniform.elementCount();
+
+    // Samplers aren't "real" uniforms, so they don't count towards register usage.
+    // Likewise, don't count "real" uniforms towards sampler count.
+    vectorAndSamplerCount.vectorCount =
+        (isSampler ? 0 : (VariableRegisterCount(uniform.type) * elementCount));
+    vectorAndSamplerCount.samplerCount = (isSampler ? elementCount : 0);
+
+    if (*location != -1)
+    {
+        *location += elementCount;
+    }
+
+    return vectorAndSamplerCount;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/UniformLinker.h b/src/third_party/angle/src/libANGLE/UniformLinker.h
new file mode 100644
index 0000000..869da52
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/UniformLinker.h
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2017 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.
+//
+
+// UniformLinker.h: implements link-time checks for default block uniforms, and generates uniform
+// locations. Populates data structures related to uniforms so that they can be stored in program
+// state.
+
+#ifndef LIBANGLE_UNIFORMLINKER_H_
+#define LIBANGLE_UNIFORMLINKER_H_
+
+#include "libANGLE/Program.h"
+#include "libANGLE/Uniform.h"
+
+namespace gl
+{
+
+class UniformLinker
+{
+  public:
+    UniformLinker(const ProgramState &state);
+
+    bool link(InfoLog &infoLog, const Caps &caps, const Program::Bindings &uniformLocationBindings);
+
+    void getResults(std::vector<LinkedUniform> *uniforms,
+                    std::vector<VariableLocation> *uniformLocations);
+
+  private:
+    struct VectorAndSamplerCount
+    {
+        VectorAndSamplerCount() : vectorCount(0), samplerCount(0) {}
+        VectorAndSamplerCount(const VectorAndSamplerCount &other) = default;
+        VectorAndSamplerCount &operator=(const VectorAndSamplerCount &other) = default;
+
+        VectorAndSamplerCount &operator+=(const VectorAndSamplerCount &other)
+        {
+            vectorCount += other.vectorCount;
+            samplerCount += other.samplerCount;
+            return *this;
+        }
+
+        unsigned int vectorCount;
+        unsigned int samplerCount;
+    };
+
+    bool validateVertexAndFragmentUniforms(InfoLog &infoLog) const;
+
+    static bool linkValidateUniforms(InfoLog &infoLog,
+                                     const std::string &uniformName,
+                                     const sh::Uniform &vertexUniform,
+                                     const sh::Uniform &fragmentUniform);
+
+    bool flattenUniformsAndCheckCapsForShader(const Shader &shader,
+                                              GLuint maxUniformComponents,
+                                              GLuint maxTextureImageUnits,
+                                              const std::string &componentsErrorMessage,
+                                              const std::string &samplerErrorMessage,
+                                              std::vector<LinkedUniform> &samplerUniforms,
+                                              InfoLog &infoLog);
+    bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog);
+
+    VectorAndSamplerCount flattenUniform(const sh::Uniform &uniform,
+                                         std::vector<LinkedUniform> *samplerUniforms);
+
+    // markStaticUse is given as a separate parameter because it is tracked here at struct
+    // granularity.
+    VectorAndSamplerCount flattenUniformImpl(const sh::ShaderVariable &uniform,
+                                             const std::string &fullName,
+                                             std::vector<LinkedUniform> *samplerUniforms,
+                                             bool markStaticUse,
+                                             int binding,
+                                             int *location);
+
+    bool indexUniforms(InfoLog &infoLog, const Program::Bindings &uniformLocationBindings);
+    bool gatherUniformLocationsAndCheckConflicts(InfoLog &infoLog,
+                                                 const Program::Bindings &uniformLocationBindings,
+                                                 std::set<GLuint> *reservedLocations,
+                                                 std::set<GLuint> *ignoredLocations,
+                                                 int *maxUniformLocation);
+    void pruneUnusedUniforms();
+
+    const ProgramState &mState;
+    std::vector<LinkedUniform> mUniforms;
+    std::vector<VariableLocation> mUniformLocations;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_UNIFORMLINKER_H_
diff --git a/src/third_party/angle/src/libANGLE/VaryingPacking.cpp b/src/third_party/angle/src/libANGLE/VaryingPacking.cpp
new file mode 100644
index 0000000..28afb22
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/VaryingPacking.cpp
@@ -0,0 +1,334 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VaryingPacking:
+//   Class which describes a mapping from varyings to registers, according
+//   to the spec, or using custom packing algorithms. We also keep a register
+//   allocation list for the D3D renderer.
+//
+
+#include "libANGLE/VaryingPacking.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Program.h"
+
+namespace gl
+{
+
+// Implementation of VaryingPacking
+VaryingPacking::VaryingPacking(GLuint maxVaryingVectors, PackMode packMode)
+    : mRegisterMap(maxVaryingVectors), mPackMode(packMode)
+{
+}
+
+// Packs varyings into generic varying registers, using the algorithm from
+// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
+// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
+// Returns false if unsuccessful.
+bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
+{
+    const auto &varying = *packedVarying.varying;
+
+    // "Non - square matrices of type matCxR consume the same space as a square matrix of type matN
+    // where N is the greater of C and R."
+    // Here we are a bit more conservative and allow packing non-square matrices more tightly.
+    // Make sure we use transposed matrix types to count registers correctly.
+    ASSERT(!varying.isStruct());
+    GLenum transposedType       = gl::TransposeMatrixType(varying.type);
+    unsigned int varyingRows    = gl::VariableRowCount(transposedType);
+    unsigned int varyingColumns = gl::VariableColumnCount(transposedType);
+
+    // "Variables of type mat2 occupies 2 complete rows."
+    // For non-WebGL contexts, we allow mat2 to occupy only two columns per row.
+    if (mPackMode == PackMode::WEBGL_STRICT && varying.type == GL_FLOAT_MAT2)
+    {
+        varyingColumns = 4;
+    }
+
+    // "Arrays of size N are assumed to take N times the size of the base type"
+    varyingRows *= (packedVarying.isArrayElement() ? 1 : varying.elementCount());
+
+    unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
+
+    // Fail if we are packing a single over-large varying.
+    if (varyingRows > maxVaryingVectors)
+    {
+        return false;
+    }
+
+    // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row.
+    // Variables are then allocated to successive rows, aligning them to the 1st column."
+    if (varyingColumns >= 2 && varyingColumns <= 4)
+    {
+        for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row)
+        {
+            if (isFree(row, 0, varyingRows, varyingColumns))
+            {
+                insert(row, 0, packedVarying);
+                return true;
+            }
+        }
+
+        // "For 2 component variables, when there are no spare rows, the strategy is switched to
+        // using the highest numbered row and the lowest numbered column where the variable will
+        // fit."
+        if (varyingColumns == 2)
+        {
+            for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;)
+            {
+                if (isFree(r, 2, varyingRows, 2))
+                {
+                    insert(r, 2, packedVarying);
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    // "1 component variables have their own packing rule. They are packed in order of size, largest
+    // first. Each variable is placed in the column that leaves the least amount of space in the
+    // column and aligned to the lowest available rows within that column."
+    ASSERT(varyingColumns == 1);
+    unsigned int contiguousSpace[4]     = {0};
+    unsigned int bestContiguousSpace[4] = {0};
+    unsigned int totalSpace[4]          = {0};
+
+    for (unsigned int row = 0; row < maxVaryingVectors; ++row)
+    {
+        for (unsigned int column = 0; column < 4; ++column)
+        {
+            if (mRegisterMap[row][column])
+            {
+                contiguousSpace[column] = 0;
+            }
+            else
+            {
+                contiguousSpace[column]++;
+                totalSpace[column]++;
+
+                if (contiguousSpace[column] > bestContiguousSpace[column])
+                {
+                    bestContiguousSpace[column] = contiguousSpace[column];
+                }
+            }
+        }
+    }
+
+    unsigned int bestColumn = 0;
+    for (unsigned int column = 1; column < 4; ++column)
+    {
+        if (bestContiguousSpace[column] >= varyingRows &&
+            (bestContiguousSpace[bestColumn] < varyingRows ||
+             totalSpace[column] < totalSpace[bestColumn]))
+        {
+            bestColumn = column;
+        }
+    }
+
+    if (bestContiguousSpace[bestColumn] >= varyingRows)
+    {
+        for (unsigned int row = 0; row < maxVaryingVectors; row++)
+        {
+            if (isFree(row, bestColumn, varyingRows, 1))
+            {
+                for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex)
+                {
+                    // If varyingRows > 1, it must be an array.
+                    PackedVaryingRegister registerInfo;
+                    registerInfo.packedVarying     = &packedVarying;
+                    registerInfo.registerRow       = row + arrayIndex;
+                    registerInfo.registerColumn    = bestColumn;
+                    registerInfo.varyingArrayIndex =
+                        (packedVarying.isArrayElement() ? packedVarying.arrayIndex : arrayIndex);
+                    registerInfo.varyingRowIndex   = 0;
+                    // Do not record register info for builtins.
+                    // TODO(jmadill): Clean this up.
+                    if (!packedVarying.varying->isBuiltIn())
+                    {
+                        mRegisterList.push_back(registerInfo);
+                    }
+                    mRegisterMap[row + arrayIndex][bestColumn] = true;
+                }
+                break;
+            }
+        }
+        return true;
+    }
+
+    return false;
+}
+
+bool VaryingPacking::isFree(unsigned int registerRow,
+                            unsigned int registerColumn,
+                            unsigned int varyingRows,
+                            unsigned int varyingColumns) const
+{
+    for (unsigned int row = 0; row < varyingRows; ++row)
+    {
+        ASSERT(registerRow + row < mRegisterMap.size());
+        for (unsigned int column = 0; column < varyingColumns; ++column)
+        {
+            ASSERT(registerColumn + column < 4);
+            if (mRegisterMap[registerRow + row][registerColumn + column])
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+void VaryingPacking::insert(unsigned int registerRow,
+                            unsigned int registerColumn,
+                            const PackedVarying &packedVarying)
+{
+    unsigned int varyingRows    = 0;
+    unsigned int varyingColumns = 0;
+
+    const auto &varying = *packedVarying.varying;
+    ASSERT(!varying.isStruct());
+    GLenum transposedType = gl::TransposeMatrixType(varying.type);
+    varyingRows           = gl::VariableRowCount(transposedType);
+    varyingColumns        = gl::VariableColumnCount(transposedType);
+
+    PackedVaryingRegister registerInfo;
+    registerInfo.packedVarying  = &packedVarying;
+    registerInfo.registerColumn = registerColumn;
+
+    for (unsigned int arrayElement = 0; arrayElement < varying.elementCount(); ++arrayElement)
+    {
+        if (packedVarying.isArrayElement() && arrayElement != packedVarying.arrayIndex)
+        {
+            continue;
+        }
+        for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow)
+        {
+            registerInfo.registerRow     = registerRow + (arrayElement * varyingRows) + varyingRow;
+            registerInfo.varyingRowIndex = varyingRow;
+            registerInfo.varyingArrayIndex = arrayElement;
+            // Do not record register info for builtins.
+            // TODO(jmadill): Clean this up.
+            if (!packedVarying.varying->isBuiltIn())
+            {
+                mRegisterList.push_back(registerInfo);
+            }
+
+            for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex)
+            {
+                mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true;
+            }
+        }
+    }
+}
+
+// See comment on packVarying.
+bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog,
+                                      const std::vector<PackedVarying> &packedVaryings,
+                                      const std::vector<std::string> &transformFeedbackVaryings)
+{
+    std::set<std::string> uniqueVaryingNames;
+
+    // "Variables are packed into the registers one at a time so that they each occupy a contiguous
+    // subrectangle. No splitting of variables is permitted."
+    for (const PackedVarying &packedVarying : packedVaryings)
+    {
+        const auto &varying = *packedVarying.varying;
+
+        // Do not assign registers to built-in or unreferenced varyings
+        if (!varying.staticUse && !packedVarying.isStructField())
+        {
+            continue;
+        }
+
+        ASSERT(!varying.isStruct());
+        ASSERT(uniqueVaryingNames.count(packedVarying.nameWithArrayIndex()) == 0);
+
+        if (packVarying(packedVarying))
+        {
+            uniqueVaryingNames.insert(packedVarying.nameWithArrayIndex());
+        }
+        else
+        {
+            infoLog << "Could not pack varying " << packedVarying.nameWithArrayIndex();
+            return false;
+        }
+    }
+
+    for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings)
+    {
+        if (transformFeedbackVaryingName.compare(0, 3, "gl_") == 0)
+        {
+            // do not pack builtin XFB varyings
+            continue;
+        }
+
+        bool found = false;
+        for (const PackedVarying &packedVarying : packedVaryings)
+        {
+            const auto &varying = *packedVarying.varying;
+            size_t subscript     = GL_INVALID_INDEX;
+            std::string baseName = ParseResourceName(transformFeedbackVaryingName, &subscript);
+
+            // Make sure transform feedback varyings aren't optimized out.
+            if (uniqueVaryingNames.count(transformFeedbackVaryingName) > 0 ||
+                uniqueVaryingNames.count(baseName) > 0)
+            {
+                found = true;
+                break;
+            }
+
+            if (baseName == varying.name)
+            {
+                if (!packVarying(packedVarying))
+                {
+                    infoLog << "Could not pack varying " << varying.name;
+                    return false;
+                }
+                uniqueVaryingNames.insert(packedVarying.nameWithArrayIndex());
+                found = true;
+                break;
+            }
+        }
+
+        if (!found)
+        {
+            infoLog << "Transform feedback varying " << transformFeedbackVaryingName
+                    << " does not exist in the vertex shader.";
+            return false;
+        }
+    }
+
+    // Sort the packed register list
+    std::sort(mRegisterList.begin(), mRegisterList.end());
+
+    // Assign semantic indices
+    for (unsigned int semanticIndex = 0;
+         semanticIndex < static_cast<unsigned int>(mRegisterList.size()); ++semanticIndex)
+    {
+        mRegisterList[semanticIndex].semanticIndex = semanticIndex;
+    }
+
+    return true;
+}
+
+unsigned int VaryingPacking::getRegisterCount() const
+{
+    unsigned int count = 0;
+
+    for (const Register &reg : mRegisterMap)
+    {
+        if (reg.data[0] || reg.data[1] || reg.data[2] || reg.data[3])
+        {
+            ++count;
+        }
+    }
+
+    return count;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/VaryingPacking.h b/src/third_party/angle/src/libANGLE/VaryingPacking.h
new file mode 100644
index 0000000..6b2f043
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/VaryingPacking.h
@@ -0,0 +1,177 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VaryingPacking:
+//   Class which describes a mapping from varyings to registers, according
+//   to the spec, or using custom packing algorithms. We also keep a register
+//   allocation list for the D3D renderer.
+//
+
+#ifndef LIBANGLE_VARYINGPACKING_H_
+#define LIBANGLE_VARYINGPACKING_H_
+
+#include <GLSLANG/ShaderVars.h>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+namespace gl
+{
+class InfoLog;
+
+struct PackedVarying
+{
+    PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn)
+        : PackedVarying(varyingIn, interpolationIn, "")
+    {
+    }
+    PackedVarying(const sh::ShaderVariable &varyingIn,
+                  sh::InterpolationType interpolationIn,
+                  const std::string &parentStructNameIn)
+        : varying(&varyingIn),
+          vertexOnly(false),
+          interpolation(interpolationIn),
+          parentStructName(parentStructNameIn),
+          arrayIndex(GL_INVALID_INDEX)
+    {
+    }
+
+    bool isStructField() const { return !parentStructName.empty(); }
+
+    bool isArrayElement() const { return arrayIndex != GL_INVALID_INDEX; }
+
+    std::string nameWithArrayIndex() const
+    {
+        std::stringstream fullNameStr;
+        fullNameStr << varying->name;
+        if (arrayIndex != GL_INVALID_INDEX)
+        {
+            fullNameStr << "[" << arrayIndex << "]";
+        }
+        return fullNameStr.str();
+    }
+
+    const sh::ShaderVariable *varying;
+
+    // Transform feedback varyings can be only referenced in the VS.
+    bool vertexOnly;
+
+    // Cached so we can store sh::ShaderVariable to point to varying fields.
+    sh::InterpolationType interpolation;
+
+    // Struct name
+    std::string parentStructName;
+
+    GLuint arrayIndex;
+};
+
+struct PackedVaryingRegister final
+{
+    PackedVaryingRegister()
+        : packedVarying(nullptr),
+          varyingArrayIndex(0),
+          varyingRowIndex(0),
+          registerRow(0),
+          registerColumn(0)
+    {
+    }
+
+    PackedVaryingRegister(const PackedVaryingRegister &) = default;
+    PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
+
+    bool operator<(const PackedVaryingRegister &other) const
+    {
+        return sortOrder() < other.sortOrder();
+    }
+
+    unsigned int sortOrder() const
+    {
+        // TODO(jmadill): Handle interpolation types
+        return registerRow * 4 + registerColumn;
+    }
+
+    bool isStructField() const { return !structFieldName.empty(); }
+
+    // Index to the array of varyings.
+    const PackedVarying *packedVarying;
+
+    // The array element of the packed varying.
+    unsigned int varyingArrayIndex;
+
+    // The row of the array element of the packed varying.
+    unsigned int varyingRowIndex;
+
+    // The register row to which we've assigned this packed varying.
+    unsigned int registerRow;
+
+    // The column of the register row into which we've packed this varying.
+    unsigned int registerColumn;
+
+    // Assigned after packing
+    unsigned int semanticIndex;
+
+    // Struct member this varying corresponds to.
+    std::string structFieldName;
+};
+
+// Supported packing modes:
+enum class PackMode
+{
+    // We treat mat2 arrays as taking two full rows.
+    WEBGL_STRICT,
+
+    // We allow mat2 to take a 2x2 chunk.
+    ANGLE_RELAXED,
+};
+
+class VaryingPacking final : angle::NonCopyable
+{
+  public:
+    VaryingPacking(GLuint maxVaryingVectors, PackMode packMode);
+
+    bool packUserVaryings(gl::InfoLog &infoLog,
+                          const std::vector<PackedVarying> &packedVaryings,
+                          const std::vector<std::string> &transformFeedbackVaryings);
+
+    struct Register
+    {
+        Register() { data[0] = data[1] = data[2] = data[3] = false; }
+
+        bool &operator[](unsigned int index) { return data[index]; }
+        bool operator[](unsigned int index) const { return data[index]; }
+
+        bool data[4];
+    };
+
+    Register &operator[](unsigned int index) { return mRegisterMap[index]; }
+    const Register &operator[](unsigned int index) const { return mRegisterMap[index]; }
+
+    const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; }
+    unsigned int getMaxSemanticIndex() const
+    {
+        return static_cast<unsigned int>(mRegisterList.size());
+    }
+    unsigned int getRegisterCount() const;
+    size_t getRegisterMapSize() const { return mRegisterMap.size(); }
+
+  private:
+    bool packVarying(const PackedVarying &packedVarying);
+    bool isFree(unsigned int registerRow,
+                unsigned int registerColumn,
+                unsigned int varyingRows,
+                unsigned int varyingColumns) const;
+    void insert(unsigned int registerRow,
+                unsigned int registerColumn,
+                const PackedVarying &packedVarying);
+
+    std::vector<Register> mRegisterMap;
+    std::vector<PackedVaryingRegister> mRegisterList;
+
+    PackMode mPackMode;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_VARYINGPACKING_H_
diff --git a/src/third_party/angle/src/libANGLE/VaryingPacking_unittest.cpp b/src/third_party/angle/src/libANGLE/VaryingPacking_unittest.cpp
new file mode 100644
index 0000000..3aeef82
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/VaryingPacking_unittest.cpp
@@ -0,0 +1,160 @@
+//
+// Copyright 2016 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.
+//
+// VaryingPacking_unittest.cpp:
+//   Tests for ANGLE's internal varying packing algorithm.
+//
+
+#include "libANGLE/VaryingPacking.h"
+
+#include <gtest/gtest.h>
+
+#include "libANGLE/Program.h"
+
+using namespace gl;
+
+namespace
+{
+
+class VaryingPackingTest : public ::testing::TestWithParam<GLuint>
+{
+  protected:
+    VaryingPackingTest() {}
+
+    bool testVaryingPacking(const std::vector<sh::Varying> &shVaryings,
+                            VaryingPacking *varyingPacking)
+    {
+        std::vector<PackedVarying> packedVaryings;
+        for (const auto &shVarying : shVaryings)
+        {
+            packedVaryings.push_back(PackedVarying(shVarying, shVarying.interpolation));
+        }
+
+        InfoLog infoLog;
+        std::vector<std::string> transformFeedbackVaryings;
+
+        return varyingPacking->packUserVaryings(infoLog, packedVaryings, transformFeedbackVaryings);
+    }
+
+    // Uses the "relaxed" ANGLE packing mode.
+    bool packVaryings(GLuint maxVaryings, const std::vector<sh::Varying> &shVaryings)
+    {
+        VaryingPacking varyingPacking(maxVaryings, PackMode::ANGLE_RELAXED);
+        return testVaryingPacking(shVaryings, &varyingPacking);
+    }
+
+    // Uses the stricter WebGL style packing rules.
+    bool packVaryingsStrict(GLuint maxVaryings, const std::vector<sh::Varying> &shVaryings)
+    {
+        VaryingPacking varyingPacking(maxVaryings, PackMode::WEBGL_STRICT);
+        return testVaryingPacking(shVaryings, &varyingPacking);
+    }
+
+    const int kMaxVaryings = GetParam();
+};
+
+std::vector<sh::Varying> MakeVaryings(GLenum type, size_t count, size_t arraySize)
+{
+    std::vector<sh::Varying> varyings;
+
+    for (size_t index = 0; index < count; ++index)
+    {
+        std::stringstream strstr;
+        strstr << type << index;
+
+        sh::Varying varying;
+        varying.type          = type;
+        varying.precision     = GL_MEDIUM_FLOAT;
+        varying.name          = strstr.str();
+        varying.mappedName    = strstr.str();
+        varying.arraySize     = static_cast<unsigned int>(arraySize);
+        varying.staticUse     = true;
+        varying.interpolation = sh::INTERPOLATION_FLAT;
+        varying.isInvariant   = false;
+
+        varyings.push_back(varying);
+    }
+
+    return varyings;
+}
+
+void AddVaryings(std::vector<sh::Varying> *varyings, GLenum type, size_t count, size_t arraySize)
+{
+    const auto &newVaryings = MakeVaryings(type, count, arraySize);
+    varyings->insert(varyings->end(), newVaryings.begin(), newVaryings.end());
+}
+
+// Test that a single varying can't overflow the packing.
+TEST_P(VaryingPackingTest, OneVaryingLargerThanMax)
+{
+    ASSERT_FALSE(packVaryings(1, MakeVaryings(GL_FLOAT_MAT4, 1, 0)));
+}
+
+// This will overflow the available varying space.
+TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec3)
+{
+    ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings + 1, 0)));
+}
+
+// This will overflow the available varying space.
+TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec3Array)
+{
+    ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2 + 1, 2)));
+}
+
+// This will overflow the available varying space.
+TEST_P(VaryingPackingTest, MaxVaryingVec3AndOneVec2)
+{
+    std::vector<sh::Varying> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings, 0);
+    AddVaryings(&varyings, GL_FLOAT_VEC2, 1, 0);
+    ASSERT_FALSE(packVaryings(kMaxVaryings, varyings));
+}
+
+// This should work since two vec2s are packed in a single register.
+TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec2)
+{
+    ASSERT_TRUE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings + 1, 0)));
+}
+
+// Same for this one as above.
+TEST_P(VaryingPackingTest, TwiceMaxVaryingVec2)
+{
+    ASSERT_TRUE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings * 2, 0)));
+}
+
+// This should not work since it overflows available varying space.
+TEST_P(VaryingPackingTest, TooManyVaryingVec2)
+{
+    ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings * 2 + 1, 0)));
+}
+
+// This should work according to the example GL packing rules - the float varyings are slotted
+// into the end of the vec3 varying arrays.
+TEST_P(VaryingPackingTest, MaxVaryingVec3ArrayAndFloatArrays)
+{
+    std::vector<sh::Varying> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2, 2);
+    AddVaryings(&varyings, GL_FLOAT, kMaxVaryings / 2, 2);
+    ASSERT_TRUE(packVaryings(kMaxVaryings, varyings));
+}
+
+// This should not work - it has one too many float arrays.
+TEST_P(VaryingPackingTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
+{
+    std::vector<sh::Varying> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2, 2);
+    AddVaryings(&varyings, GL_FLOAT, kMaxVaryings / 2 + 1, 2);
+    ASSERT_FALSE(packVaryings(kMaxVaryings, varyings));
+}
+
+// WebGL should fail to pack max+1 vec2 arrays, unlike our more relaxed packing.
+TEST_P(VaryingPackingTest, MaxPlusOneMat2VaryingsFailsWebGL)
+{
+    auto varyings = MakeVaryings(GL_FLOAT_MAT2, kMaxVaryings / 2 + 1, 0);
+    ASSERT_FALSE(packVaryingsStrict(kMaxVaryings, varyings));
+}
+
+// Makes separate tests for different values of kMaxVaryings.
+INSTANTIATE_TEST_CASE_P(, VaryingPackingTest, ::testing::Values(1, 4, 8));
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/libANGLE/Version.h b/src/third_party/angle/src/libANGLE/Version.h
new file mode 100644
index 0000000..4c9730c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Version.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Version.h: Encapsulation of a GL version.
+
+#ifndef LIBANGLE_VERSION_H_
+#define LIBANGLE_VERSION_H_
+
+#include <angle_gl.h>
+
+namespace gl
+{
+
+struct Version
+{
+    constexpr Version();
+    constexpr Version(GLuint major, GLuint minor);
+
+    GLuint major;
+    GLuint minor;
+};
+
+bool operator==(const Version &a, const Version &b);
+bool operator!=(const Version &a, const Version &b);
+bool operator>=(const Version &a, const Version &b);
+bool operator<=(const Version &a, const Version &b);
+bool operator<(const Version &a, const Version &b);
+bool operator>(const Version &a, const Version &b);
+}
+
+#include "Version.inl"
+
+#endif // LIBANGLE_VERSION_H_
diff --git a/src/third_party/angle/src/libANGLE/Version.inl b/src/third_party/angle/src/libANGLE/Version.inl
new file mode 100644
index 0000000..4952097
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Version.inl
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Version.inl: Encapsulation of a GL version.
+
+#include <tuple>
+
+namespace gl
+{
+
+constexpr Version::Version()
+    : Version(0, 0)
+{
+}
+
+// Avoid conflicts with linux system defines
+#undef major
+#undef minor
+
+constexpr Version::Version(GLuint major_, GLuint minor_)
+    : major(major_),
+      minor(minor_)
+{
+}
+
+inline bool operator==(const Version &a, const Version &b)
+{
+    return std::tie(a.major, a.minor) == std::tie(b.major, b.minor);
+}
+
+inline bool operator!=(const Version &a, const Version &b)
+{
+    return std::tie(a.major, a.minor) != std::tie(b.major, b.minor);
+}
+
+inline bool operator>=(const Version &a, const Version &b)
+{
+    return std::tie(a.major, a.minor) >= std::tie(b.major, b.minor);
+}
+
+inline bool operator<=(const Version &a, const Version &b)
+{
+    return std::tie(a.major, a.minor) <= std::tie(b.major, b.minor);
+}
+
+inline bool operator<(const Version &a, const Version &b)
+{
+    return std::tie(a.major, a.minor) < std::tie(b.major, b.minor);
+}
+
+inline bool operator>(const Version &a, const Version &b)
+{
+    return std::tie(a.major, a.minor) > std::tie(b.major, b.minor);
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/VertexArray.cpp b/src/third_party/angle/src/libANGLE/VertexArray.cpp
new file mode 100644
index 0000000..b19e6ea
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/VertexArray.cpp
@@ -0,0 +1,226 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Implementation of the state class for mananging GLES 3 Vertex Array Objects.
+//
+
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace gl
+{
+
+VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
+    : mLabel(), mVertexBindings(maxAttribBindings), mMaxEnabledAttribute(0)
+{
+    ASSERT(maxAttribs <= maxAttribBindings);
+
+    for (size_t i = 0; i < maxAttribs; i++)
+    {
+        mVertexAttributes.emplace_back(static_cast<GLuint>(i));
+    }
+}
+
+VertexArrayState::~VertexArrayState()
+{
+    for (auto &binding : mVertexBindings)
+    {
+        binding.buffer.set(nullptr);
+    }
+    mElementArrayBuffer.set(nullptr);
+}
+
+VertexArray::VertexArray(rx::GLImplFactory *factory,
+                         GLuint id,
+                         size_t maxAttribs,
+                         size_t maxAttribBindings)
+    : mId(id),
+      mState(maxAttribs, maxAttribBindings),
+      mVertexArray(factory->createVertexArray(mState))
+{
+}
+
+VertexArray::~VertexArray()
+{
+    SafeDelete(mVertexArray);
+}
+
+GLuint VertexArray::id() const
+{
+    return mId;
+}
+
+void VertexArray::setLabel(const std::string &label)
+{
+    mState.mLabel = label;
+}
+
+const std::string &VertexArray::getLabel() const
+{
+    return mState.mLabel;
+}
+
+void VertexArray::detachBuffer(GLuint bufferName)
+{
+    for (auto &binding : mState.mVertexBindings)
+    {
+        if (binding.buffer.id() == bufferName)
+        {
+            binding.buffer.set(nullptr);
+        }
+    }
+
+    if (mState.mElementArrayBuffer.id() == bufferName)
+    {
+        mState.mElementArrayBuffer.set(nullptr);
+    }
+}
+
+const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
+{
+    ASSERT(attribIndex < getMaxAttribs());
+    return mState.mVertexAttributes[attribIndex];
+}
+
+const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
+{
+    ASSERT(bindingIndex < getMaxBindings());
+    return mState.mVertexBindings[bindingIndex];
+}
+
+size_t VertexArray::GetAttribIndex(size_t dirtyBit)
+{
+    static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
+                  "The stride of vertex attributes should equal to that of vertex bindings.");
+    ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
+    return (dirtyBit - DIRTY_BIT_ATTRIB_0_ENABLED) % gl::MAX_VERTEX_ATTRIBS;
+}
+
+void VertexArray::bindVertexBuffer(size_t bindingIndex,
+                                   Buffer *boundBuffer,
+                                   GLintptr offset,
+                                   GLsizei stride)
+{
+    ASSERT(bindingIndex < getMaxBindings());
+
+    VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
+
+    binding->buffer.set(boundBuffer);
+    binding->offset = offset;
+    binding->stride = stride;
+    mDirtyBits.set(DIRTY_BIT_BINDING_0_BUFFER + bindingIndex);
+}
+
+void VertexArray::setVertexAttribBinding(size_t attribIndex, size_t bindingIndex)
+{
+    ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
+
+    mState.mVertexAttributes[attribIndex].bindingIndex = static_cast<GLuint>(bindingIndex);
+    mDirtyBits.set(DIRTY_BIT_ATTRIB_0_BINDING + attribIndex);
+}
+
+void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
+{
+    ASSERT(bindingIndex < getMaxBindings());
+
+    mState.mVertexBindings[bindingIndex].divisor = divisor;
+    mDirtyBits.set(DIRTY_BIT_BINDING_0_DIVISOR + bindingIndex);
+}
+
+void VertexArray::setVertexAttribFormat(size_t attribIndex,
+                                        GLint size,
+                                        GLenum type,
+                                        bool normalized,
+                                        bool pureInteger,
+                                        GLintptr relativeOffset)
+{
+    ASSERT(attribIndex < getMaxAttribs());
+
+    VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
+
+    attrib->size           = size;
+    attrib->type           = type;
+    attrib->normalized     = normalized;
+    attrib->pureInteger    = pureInteger;
+    attrib->relativeOffset = relativeOffset;
+    mDirtyBits.set(DIRTY_BIT_ATTRIB_0_FORMAT + attribIndex);
+}
+
+void VertexArray::setVertexAttribDivisor(size_t index, GLuint divisor)
+{
+    ASSERT(index < getMaxAttribs());
+
+    setVertexAttribBinding(index, index);
+    setVertexBindingDivisor(index, divisor);
+}
+
+void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
+{
+    ASSERT(attribIndex < getMaxAttribs());
+
+    mState.mVertexAttributes[attribIndex].enabled = enabledState;
+    mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attribIndex);
+
+    // Update state cache
+    if (enabledState)
+    {
+        mState.mMaxEnabledAttribute = std::max(attribIndex + 1, mState.mMaxEnabledAttribute);
+    }
+    else if (mState.mMaxEnabledAttribute == attribIndex + 1)
+    {
+        while (mState.mMaxEnabledAttribute > 0 &&
+               !mState.mVertexAttributes[mState.mMaxEnabledAttribute - 1].enabled)
+        {
+            --mState.mMaxEnabledAttribute;
+        }
+    }
+}
+
+void VertexArray::setAttributeState(size_t attribIndex,
+                                    gl::Buffer *boundBuffer,
+                                    GLint size,
+                                    GLenum type,
+                                    bool normalized,
+                                    bool pureInteger,
+                                    GLsizei stride,
+                                    const void *pointer)
+{
+    ASSERT(attribIndex < getMaxAttribs());
+
+    GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
+
+    setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger, 0);
+    setVertexAttribBinding(attribIndex, attribIndex);
+
+    VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
+    GLsizei effectiveStride =
+        stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
+    attrib.pointer                 = pointer;
+    attrib.vertexAttribArrayStride = stride;
+
+    bindVertexBuffer(attribIndex, boundBuffer, offset, effectiveStride);
+
+    mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attribIndex);
+}
+
+void VertexArray::setElementArrayBuffer(Buffer *buffer)
+{
+    mState.mElementArrayBuffer.set(buffer);
+    mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
+}
+
+void VertexArray::syncImplState(const Context *context)
+{
+    if (mDirtyBits.any())
+    {
+        mVertexArray->syncState(rx::SafeGetImpl(context), mDirtyBits);
+        mDirtyBits.reset();
+    }
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/VertexArray.h b/src/third_party/angle/src/libANGLE/VertexArray.h
new file mode 100644
index 0000000..40b1eaa
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/VertexArray.h
@@ -0,0 +1,189 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This class contains prototypes for representing GLES 3 Vertex Array Objects:
+//
+//   The buffer objects that are to be used by the vertex stage of the GL are collected
+//   together to form a vertex array object. All state related to the definition of data used
+//   by the vertex processor is encapsulated in a vertex array object.
+//
+
+#ifndef LIBANGLE_VERTEXARRAY_H_
+#define LIBANGLE_VERTEXARRAY_H_
+
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexAttribute.h"
+
+#include <vector>
+
+namespace rx
+{
+class GLImplFactory;
+class VertexArrayImpl;
+}  // namespace rx
+
+namespace gl
+{
+class Buffer;
+
+class VertexArrayState final : angle::NonCopyable
+{
+  public:
+    VertexArrayState(size_t maxAttribs, size_t maxBindings);
+    ~VertexArrayState();
+
+    const std::string &getLabel() const { return mLabel; }
+
+    const BindingPointer<Buffer> &getElementArrayBuffer() const { return mElementArrayBuffer; }
+    size_t getMaxAttribs() const { return mVertexAttributes.size(); }
+    size_t getMaxBindings() const { return mVertexBindings.size(); }
+    size_t getMaxEnabledAttribute() const { return mMaxEnabledAttribute; }
+    const std::vector<VertexAttribute> &getVertexAttributes() const { return mVertexAttributes; }
+    const VertexAttribute &getVertexAttribute(size_t attribIndex) const
+    {
+        return mVertexAttributes[attribIndex];
+    }
+    const std::vector<VertexBinding> &getVertexBindings() const { return mVertexBindings; }
+    const VertexBinding &getVertexBinding(size_t bindingIndex) const
+    {
+        return mVertexBindings[bindingIndex];
+    }
+    const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
+    {
+        return mVertexBindings[mVertexAttributes[attribIndex].bindingIndex];
+    }
+    size_t getBindingIndexFromAttribIndex(size_t attribIndex) const
+    {
+        return mVertexAttributes[attribIndex].bindingIndex;
+    }
+
+  private:
+    friend class VertexArray;
+    std::string mLabel;
+    std::vector<VertexAttribute> mVertexAttributes;
+    BindingPointer<Buffer> mElementArrayBuffer;
+    std::vector<VertexBinding> mVertexBindings;
+    size_t mMaxEnabledAttribute;
+};
+
+class VertexArray final : public LabeledObject
+{
+  public:
+    VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs, size_t maxAttribBindings);
+    ~VertexArray();
+
+    GLuint id() const;
+
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
+    const VertexBinding &getVertexBinding(size_t bindingIndex) const;
+    const VertexAttribute &getVertexAttribute(size_t attribIndex) const;
+    const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
+    {
+        return mState.getBindingFromAttribIndex(attribIndex);
+    }
+
+    void detachBuffer(GLuint bufferName);
+    void setVertexAttribDivisor(size_t index, GLuint divisor);
+    void enableAttribute(size_t attribIndex, bool enabledState);
+    void setAttributeState(size_t attribIndex,
+                           Buffer *boundBuffer,
+                           GLint size,
+                           GLenum type,
+                           bool normalized,
+                           bool pureInteger,
+                           GLsizei stride,
+                           const void *pointer);
+    void setVertexAttribFormat(size_t attribIndex,
+                               GLint size,
+                               GLenum type,
+                               bool normalized,
+                               bool pureInteger,
+                               GLintptr relativeOffset);
+    void bindVertexBuffer(size_t bindingIndex,
+                          Buffer *boundBuffer,
+                          GLintptr offset,
+                          GLsizei stride);
+    void setVertexAttribBinding(size_t attribIndex, size_t bindingIndex);
+    void setVertexBindingDivisor(size_t bindingIndex, GLuint divisor);
+
+    void setElementArrayBuffer(Buffer *buffer);
+
+    const BindingPointer<Buffer> &getElementArrayBuffer() const
+    {
+        return mState.getElementArrayBuffer();
+    }
+    size_t getMaxAttribs() const { return mState.getMaxAttribs(); }
+    size_t getMaxBindings() const { return mState.getMaxBindings(); }
+
+    const std::vector<VertexAttribute> &getVertexAttributes() const
+    {
+        return mState.getVertexAttributes();
+    }
+    const std::vector<VertexBinding> &getVertexBindings() const
+    {
+        return mState.getVertexBindings();
+    }
+
+    rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
+
+    size_t getMaxEnabledAttribute() const { return mState.getMaxEnabledAttribute(); }
+
+    enum DirtyBitType
+    {
+        DIRTY_BIT_ELEMENT_ARRAY_BUFFER,
+
+        // Reserve bits for enabled flags
+        DIRTY_BIT_ATTRIB_0_ENABLED,
+        DIRTY_BIT_ATTRIB_MAX_ENABLED = DIRTY_BIT_ATTRIB_0_ENABLED + gl::MAX_VERTEX_ATTRIBS,
+
+        // Reserve bits for attrib pointers
+        DIRTY_BIT_ATTRIB_0_POINTER   = DIRTY_BIT_ATTRIB_MAX_ENABLED,
+        DIRTY_BIT_ATTRIB_MAX_POINTER = DIRTY_BIT_ATTRIB_0_POINTER + gl::MAX_VERTEX_ATTRIBS,
+
+        // Reserve bits for changes to VertexAttribFormat
+        DIRTY_BIT_ATTRIB_0_FORMAT   = DIRTY_BIT_ATTRIB_MAX_POINTER,
+        DIRTY_BIT_ATTRIB_MAX_FORMAT = DIRTY_BIT_ATTRIB_0_FORMAT + gl::MAX_VERTEX_ATTRIBS,
+
+        // Reserve bits for changes to VertexAttribBinding
+        DIRTY_BIT_ATTRIB_0_BINDING   = DIRTY_BIT_ATTRIB_MAX_FORMAT,
+        DIRTY_BIT_ATTRIB_MAX_BINDING = DIRTY_BIT_ATTRIB_0_BINDING + gl::MAX_VERTEX_ATTRIBS,
+
+        // Reserve bits for changes to BindVertexBuffer
+        DIRTY_BIT_BINDING_0_BUFFER   = DIRTY_BIT_ATTRIB_MAX_BINDING,
+        DIRTY_BIT_BINDING_MAX_BUFFER = DIRTY_BIT_BINDING_0_BUFFER + gl::MAX_VERTEX_ATTRIB_BINDINGS,
+
+        // Reserve bits for binding divisors
+        DIRTY_BIT_BINDING_0_DIVISOR = DIRTY_BIT_BINDING_MAX_BUFFER,
+        DIRTY_BIT_BINDING_MAX_DIVISOR =
+            DIRTY_BIT_BINDING_0_DIVISOR + gl::MAX_VERTEX_ATTRIB_BINDINGS,
+
+        DIRTY_BIT_UNKNOWN = DIRTY_BIT_BINDING_MAX_DIVISOR,
+        DIRTY_BIT_MAX     = DIRTY_BIT_UNKNOWN,
+    };
+
+    typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits;
+
+    static size_t GetAttribIndex(size_t dirtyBit);
+
+    void syncImplState(const Context *context);
+    bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+  private:
+    GLuint mId;
+
+    VertexArrayState mState;
+    DirtyBits mDirtyBits;
+
+    rx::VertexArrayImpl *mVertexArray;
+};
+
+}  // namespace gl
+
+#endif // LIBANGLE_VERTEXARRAY_H_
diff --git a/src/third_party/angle/src/libANGLE/VertexArray_unittest.cpp b/src/third_party/angle/src/libANGLE/VertexArray_unittest.cpp
new file mode 100644
index 0000000..9c594dc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/VertexArray_unittest.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright 2017 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.
+//
+// Unit tests for VertexArray and related classes.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/VertexArray.h"
+
+using namespace gl;
+
+// Tests that function GetAttribIndex computes the index properly.
+TEST(VertexArrayTest, VerifyGetAttribIndex)
+{
+    VertexArray::DirtyBits dirtyBits;
+    size_t bits[] = {1, 4, 9, 16, 25, 36, 49, 64, 81, 90};
+    int count     = sizeof(bits) / sizeof(size_t);
+    for (int i = 0; i < count; i++)
+    {
+        dirtyBits.set(bits[i]);
+    }
+
+    for (size_t dirtyBit : dirtyBits)
+    {
+        size_t index = VertexArray::GetAttribIndex(dirtyBit);
+        if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
+        {
+            EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED, index);
+        }
+        else if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
+        {
+            EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_POINTER, index);
+        }
+        else if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_FORMAT)
+        {
+            EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_FORMAT, index);
+        }
+        else if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_BINDING)
+        {
+            EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_BINDING, index);
+        }
+        else if (dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_BUFFER)
+        {
+            EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BINDING_0_BUFFER, index);
+        }
+        else if (dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_DIVISOR)
+        {
+            EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BINDING_0_DIVISOR, index);
+        }
+        else
+            ASSERT_TRUE(false);
+    }
+}
diff --git a/src/third_party/angle/src/libANGLE/VertexAttribute.cpp b/src/third_party/angle/src/libANGLE/VertexAttribute.cpp
new file mode 100644
index 0000000..1621075a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/VertexAttribute.cpp
@@ -0,0 +1,135 @@
+//
+// 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.
+//
+// Implementation of the state classes for mananging GLES 3.1 Vertex Array Objects.
+//
+
+#include "libANGLE/VertexAttribute.h"
+
+namespace gl
+{
+
+// [OpenGL ES 3.1] (November 3, 2016) Section 20 Page 361
+// Table 20.2: Vertex Array Object State
+VertexBinding::VertexBinding() : stride(16u), divisor(0), offset(0)
+{
+}
+
+VertexBinding::VertexBinding(VertexBinding &&binding)
+{
+    *this = std::move(binding);
+}
+
+VertexBinding &VertexBinding::operator=(VertexBinding &&binding)
+{
+    if (this != &binding)
+    {
+        stride  = binding.stride;
+        divisor = binding.divisor;
+        offset  = binding.offset;
+
+        buffer.set(binding.buffer.get());
+        binding.buffer.set(nullptr);
+    }
+    return *this;
+}
+
+VertexAttribute::VertexAttribute(GLuint bindingIndex)
+    : enabled(false),
+      type(GL_FLOAT),
+      size(4u),
+      normalized(false),
+      pureInteger(false),
+      pointer(nullptr),
+      relativeOffset(0),
+      vertexAttribArrayStride(0),
+      bindingIndex(bindingIndex)
+{
+}
+
+VertexAttribute::VertexAttribute(VertexAttribute &&attrib)
+    : enabled(attrib.enabled),
+      type(attrib.type),
+      size(attrib.size),
+      normalized(attrib.normalized),
+      pureInteger(attrib.pureInteger),
+      pointer(attrib.pointer),
+      relativeOffset(attrib.relativeOffset),
+      vertexAttribArrayStride(attrib.vertexAttribArrayStride),
+      bindingIndex(attrib.bindingIndex)
+{
+}
+
+VertexAttribute &VertexAttribute::operator=(VertexAttribute &&attrib)
+{
+    if (this != &attrib)
+    {
+        enabled                 = attrib.enabled;
+        type                    = attrib.type;
+        size                    = attrib.size;
+        normalized              = attrib.normalized;
+        pureInteger             = attrib.pureInteger;
+        pointer                 = attrib.pointer;
+        relativeOffset          = attrib.relativeOffset;
+        vertexAttribArrayStride = attrib.vertexAttribArrayStride;
+        bindingIndex            = attrib.bindingIndex;
+    }
+    return *this;
+}
+
+size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib)
+{
+    GLuint size = attrib.size;
+    switch (attrib.type)
+    {
+      case GL_BYTE:                        return size * sizeof(GLbyte);
+      case GL_UNSIGNED_BYTE:               return size * sizeof(GLubyte);
+      case GL_SHORT:                       return size * sizeof(GLshort);
+      case GL_UNSIGNED_SHORT:              return size * sizeof(GLushort);
+      case GL_INT:                         return size * sizeof(GLint);
+      case GL_UNSIGNED_INT:                return size * sizeof(GLuint);
+      case GL_INT_2_10_10_10_REV:          return 4;
+      case GL_UNSIGNED_INT_2_10_10_10_REV: return 4;
+      case GL_FIXED:                       return size * sizeof(GLfixed);
+      case GL_HALF_FLOAT:                  return size * sizeof(GLhalf);
+      case GL_FLOAT:                       return size * sizeof(GLfloat);
+      default: UNREACHABLE();              return size * sizeof(GLfloat);
+    }
+}
+
+size_t ComputeVertexAttributeStride(const VertexAttribute &attrib, const VertexBinding &binding)
+{
+    // In ES 3.1, VertexAttribPointer will store the type size in the binding stride.
+    // Hence, rendering always uses the binding's stride.
+    return attrib.enabled ? binding.stride : 16u;
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+GLintptr ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding)
+{
+    return attrib.relativeOffset + binding.offset;
+}
+
+size_t ComputeVertexBindingElementCount(const VertexBinding &binding,
+                                        size_t drawCount,
+                                        size_t instanceCount)
+{
+    // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
+    //
+    // A vertex attribute with a positive divisor loads one instanced vertex for every set of
+    // non-instanced vertices, and the instanced vertex index advances once every "mDivisor"
+    // instances.
+    if (instanceCount > 0 && binding.divisor > 0)
+    {
+        // When instanceDrawCount is not a multiple attrib.divisor, the division must round up.
+        // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced
+        // vertices.
+        return (instanceCount + binding.divisor - 1u) / binding.divisor;
+    }
+
+    return drawCount;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/VertexAttribute.h b/src/third_party/angle/src/libANGLE/VertexAttribute.h
new file mode 100644
index 0000000..98f36c9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/VertexAttribute.h
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Helper structures about Generic Vertex Attribute.
+//
+
+#ifndef LIBANGLE_VERTEXATTRIBUTE_H_
+#define LIBANGLE_VERTEXATTRIBUTE_H_
+
+#include "libANGLE/Buffer.h"
+
+namespace gl
+{
+class VertexArray;
+
+//
+// Implementation of Generic Vertex Attribute Bindings for ES3.1
+//
+struct VertexBinding final : private angle::NonCopyable
+{
+    VertexBinding();
+    explicit VertexBinding(VertexBinding &&binding);
+    VertexBinding &operator=(VertexBinding &&binding);
+
+    GLuint stride;
+    GLuint divisor;
+    GLintptr offset;
+
+    BindingPointer<Buffer> buffer;
+};
+
+//
+// Implementation of Generic Vertex Attributes for ES3.1
+//
+struct VertexAttribute final : private angle::NonCopyable
+{
+    explicit VertexAttribute(GLuint bindingIndex);
+    explicit VertexAttribute(VertexAttribute &&attrib);
+    VertexAttribute &operator=(VertexAttribute &&attrib);
+
+    bool enabled;  // For glEnable/DisableVertexAttribArray
+    GLenum type;
+    GLuint size;
+    bool normalized;
+    bool pureInteger;
+
+    const void *pointer;
+    GLintptr relativeOffset;
+
+    GLuint vertexAttribArrayStride;  // ONLY for queries of VERTEX_ATTRIB_ARRAY_STRIDE
+    GLuint bindingIndex;
+};
+
+bool operator==(const VertexAttribute &a, const VertexAttribute &b);
+bool operator!=(const VertexAttribute &a, const VertexAttribute &b);
+bool operator==(const VertexBinding &a, const VertexBinding &b);
+bool operator!=(const VertexBinding &a, const VertexBinding &b);
+
+size_t ComputeVertexAttributeTypeSize(const VertexAttribute &attrib);
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+size_t ComputeVertexAttributeStride(const VertexAttribute &attrib, const VertexBinding &binding);
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+GLintptr ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding);
+
+size_t ComputeVertexBindingElementCount(const VertexBinding &binding,
+                                        size_t drawCount,
+                                        size_t instanceCount);
+
+struct VertexAttribCurrentValueData
+{
+    union {
+        GLfloat FloatValues[4];
+        GLint IntValues[4];
+        GLuint UnsignedIntValues[4];
+    };
+    GLenum Type;
+
+    VertexAttribCurrentValueData();
+
+    void setFloatValues(const GLfloat floatValues[4]);
+    void setIntValues(const GLint intValues[4]);
+    void setUnsignedIntValues(const GLuint unsignedIntValues[4]);
+};
+
+bool operator==(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b);
+bool operator!=(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b);
+
+}  // namespace gl
+
+#include "VertexAttribute.inl"
+
+#endif  // LIBANGLE_VERTEXATTRIBUTE_H_
diff --git a/src/third_party/angle/src/libANGLE/VertexAttribute.inl b/src/third_party/angle/src/libANGLE/VertexAttribute.inl
new file mode 100644
index 0000000..c0d2680
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/VertexAttribute.inl
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VertexAttribute.inl: Inline vertex attribute methods
+//
+
+namespace gl
+{
+
+inline bool operator==(const VertexBinding &a, const VertexBinding &b)
+{
+    return a.stride == b.stride &&
+           a.divisor == b.divisor &&
+           a.offset == b.offset &&
+           a.buffer.get() == b.buffer.get();
+}
+
+inline bool operator!=(const VertexBinding &a, const VertexBinding &b)
+{
+    return !(a == b);
+}
+
+inline bool operator==(const VertexAttribute &a, const VertexAttribute &b)
+{
+    return a.enabled == b.enabled &&
+           a.type == b.type &&
+           a.size == b.size &&
+           a.normalized == b.normalized &&
+           a.pureInteger == b.pureInteger &&
+           a.pointer == b.pointer &&
+           a.relativeOffset == b.relativeOffset &&
+           a.vertexAttribArrayStride == b.vertexAttribArrayStride &&
+           a.bindingIndex == b.bindingIndex;
+}
+
+inline bool operator!=(const VertexAttribute &a, const VertexAttribute &b)
+{
+    return !(a == b);
+}
+
+inline VertexAttribCurrentValueData::VertexAttribCurrentValueData()
+    : Type(GL_FLOAT)
+{
+    FloatValues[0] = 0.0f;
+    FloatValues[1] = 0.0f;
+    FloatValues[2] = 0.0f;
+    FloatValues[3] = 1.0f;
+}
+
+inline void VertexAttribCurrentValueData::setFloatValues(const GLfloat floatValues[4])
+{
+    for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+    {
+        FloatValues[valueIndex] = floatValues[valueIndex];
+    }
+    Type = GL_FLOAT;
+}
+
+inline void VertexAttribCurrentValueData::setIntValues(const GLint intValues[4])
+{
+    for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+    {
+        IntValues[valueIndex] = intValues[valueIndex];
+    }
+    Type = GL_INT;
+}
+
+inline void VertexAttribCurrentValueData::setUnsignedIntValues(const GLuint unsignedIntValues[4])
+{
+    for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+    {
+        UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex];
+    }
+    Type = GL_UNSIGNED_INT;
+}
+
+inline bool operator==(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b)
+{
+    return (a.Type == b.Type && memcmp(a.FloatValues, b.FloatValues, sizeof(float) * 4) == 0);
+}
+
+inline bool operator!=(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b)
+{
+    return !(a == b);
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/Workarounds.h b/src/third_party/angle/src/libANGLE/Workarounds.h
new file mode 100644
index 0000000..c5533c1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/Workarounds.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// Workarounds.h: Workarounds for driver bugs and other behaviors seen
+// on all platforms.
+
+#ifndef LIBANGLE_WORKAROUNDS_H_
+#define LIBANGLE_WORKAROUNDS_H_
+
+namespace gl
+{
+
+struct Workarounds
+{
+    // Force the context to be lost (via KHR_robustness) if a GL_OUT_OF_MEMORY error occurs. The
+    // driver may be in an inconsistent state if this happens, and some users of ANGLE rely on this
+    // notification to prevent further execution.
+    bool loseContextOnOutOfMemory = false;
+};
+}  // namespace gl
+
+#endif  // LIBANGLE_WORKAROUNDS_H_
diff --git a/src/third_party/angle/src/libANGLE/WorkerThread.cpp b/src/third_party/angle/src/libANGLE/WorkerThread.cpp
new file mode 100644
index 0000000..b5d789e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/WorkerThread.cpp
@@ -0,0 +1,157 @@
+//
+// Copyright 2016 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.
+//
+// WorkerThread:
+//   Task running thread for ANGLE, similar to a TaskRunner in Chromium.
+//   Might be implemented differently depending on platform.
+//
+
+#include "libANGLE/WorkerThread.h"
+
+namespace angle
+{
+
+namespace priv
+{
+// SingleThreadedWorkerPool implementation.
+SingleThreadedWorkerPool::SingleThreadedWorkerPool(size_t maxThreads)
+    : WorkerThreadPoolBase(maxThreads)
+{
+}
+
+SingleThreadedWorkerPool::~SingleThreadedWorkerPool()
+{
+}
+
+SingleThreadedWaitableEvent SingleThreadedWorkerPool::postWorkerTaskImpl(Closure *task)
+{
+    (*task)();
+    return SingleThreadedWaitableEvent(EventResetPolicy::Automatic, EventInitialState::Signaled);
+}
+
+// SingleThreadedWaitableEvent implementation.
+SingleThreadedWaitableEvent::SingleThreadedWaitableEvent()
+    : SingleThreadedWaitableEvent(EventResetPolicy::Automatic, EventInitialState::NonSignaled)
+{
+}
+
+SingleThreadedWaitableEvent::SingleThreadedWaitableEvent(EventResetPolicy resetPolicy,
+                                                         EventInitialState initialState)
+    : WaitableEventBase(resetPolicy, initialState)
+{
+}
+
+SingleThreadedWaitableEvent::~SingleThreadedWaitableEvent()
+{
+}
+
+SingleThreadedWaitableEvent::SingleThreadedWaitableEvent(SingleThreadedWaitableEvent &&other)
+    : WaitableEventBase(std::move(other))
+{
+}
+
+SingleThreadedWaitableEvent &SingleThreadedWaitableEvent::operator=(
+    SingleThreadedWaitableEvent &&other)
+{
+    return copyBase(std::move(other));
+}
+
+void SingleThreadedWaitableEvent::resetImpl()
+{
+    mSignaled = false;
+}
+
+void SingleThreadedWaitableEvent::waitImpl()
+{
+}
+
+void SingleThreadedWaitableEvent::signalImpl()
+{
+    mSignaled = true;
+}
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+// AsyncWorkerPool implementation.
+AsyncWorkerPool::AsyncWorkerPool(size_t maxThreads) : WorkerThreadPoolBase(maxThreads)
+{
+}
+
+AsyncWorkerPool::~AsyncWorkerPool()
+{
+}
+
+AsyncWaitableEvent AsyncWorkerPool::postWorkerTaskImpl(Closure *task)
+{
+    auto future = std::async(std::launch::async, [task] { (*task)(); });
+
+    AsyncWaitableEvent waitable(EventResetPolicy::Automatic, EventInitialState::NonSignaled);
+
+    waitable.setFuture(std::move(future));
+
+    return waitable;
+}
+
+// AsyncWaitableEvent implementation.
+AsyncWaitableEvent::AsyncWaitableEvent()
+    : AsyncWaitableEvent(EventResetPolicy::Automatic, EventInitialState::NonSignaled)
+{
+}
+
+AsyncWaitableEvent::AsyncWaitableEvent(EventResetPolicy resetPolicy, EventInitialState initialState)
+    : WaitableEventBase(resetPolicy, initialState)
+{
+}
+
+AsyncWaitableEvent::~AsyncWaitableEvent()
+{
+}
+
+AsyncWaitableEvent::AsyncWaitableEvent(AsyncWaitableEvent &&other)
+    : WaitableEventBase(std::move(other)), mFuture(std::move(other.mFuture))
+{
+}
+
+AsyncWaitableEvent &AsyncWaitableEvent::operator=(AsyncWaitableEvent &&other)
+{
+    std::swap(mFuture, other.mFuture);
+    return copyBase(std::move(other));
+}
+
+void AsyncWaitableEvent::setFuture(std::future<void> &&future)
+{
+    mFuture = std::move(future);
+}
+
+void AsyncWaitableEvent::resetImpl()
+{
+    mSignaled = false;
+    mFuture   = std::future<void>();
+}
+
+void AsyncWaitableEvent::waitImpl()
+{
+    if (mSignaled || !mFuture.valid())
+    {
+        return;
+    }
+
+    mFuture.wait();
+    signal();
+}
+
+void AsyncWaitableEvent::signalImpl()
+{
+    mSignaled = true;
+
+    if (mResetPolicy == EventResetPolicy::Automatic)
+    {
+        reset();
+    }
+}
+#endif  // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+}  // namespace priv
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/libANGLE/WorkerThread.h b/src/third_party/angle/src/libANGLE/WorkerThread.h
new file mode 100644
index 0000000..f6b81dc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/WorkerThread.h
@@ -0,0 +1,284 @@
+//
+// Copyright 2016 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.
+//
+// WorkerThread:
+//   Asychronous tasks/threads for ANGLE, similar to a TaskRunner in Chromium.
+//   Can be implemented as different targets, depending on platform.
+//
+
+#ifndef LIBANGLE_WORKER_THREAD_H_
+#define LIBANGLE_WORKER_THREAD_H_
+
+#include <array>
+#include <vector>
+
+#include "common/debug.h"
+#include "libANGLE/features.h"
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+#include <future>
+#endif  // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+namespace angle
+{
+// Indicates whether a WaitableEvent should automatically reset the event state after a single
+// waiting thread has been released or remain signaled until reset() is manually invoked.
+enum class EventResetPolicy
+{
+    Manual,
+    Automatic
+};
+
+// Specify the initial state on creation.
+enum class EventInitialState
+{
+    NonSignaled,
+    Signaled
+};
+
+// A callback function with no return value and no arguments.
+class Closure
+{
+  public:
+    virtual ~Closure()        = default;
+    virtual void operator()() = 0;
+};
+
+namespace priv
+{
+// An event that we can wait on, useful for joining worker threads.
+template <typename Impl>
+class WaitableEventBase : angle::NonCopyable
+{
+  public:
+    WaitableEventBase(EventResetPolicy resetPolicy, EventInitialState initialState);
+
+    WaitableEventBase(WaitableEventBase &&other);
+
+    // Puts the event in the un-signaled state.
+    void reset();
+
+    // Waits indefinitely for the event to be signaled.
+    void wait();
+
+    // Puts the event in the signaled state, causing any thread blocked on Wait to be woken up.
+    // The event state is reset to non-signaled after a waiting thread has been released.
+    void signal();
+
+  protected:
+    Impl &copyBase(Impl &&other);
+
+    template <size_t Count>
+    static size_t WaitManyBase(std::array<Impl, Count> *waitables);
+
+    EventResetPolicy mResetPolicy;
+    bool mSignaled;
+};
+
+template <typename Impl>
+WaitableEventBase<Impl>::WaitableEventBase(EventResetPolicy resetPolicy,
+                                           EventInitialState initialState)
+    : mResetPolicy(resetPolicy), mSignaled(initialState == EventInitialState::Signaled)
+{
+}
+
+template <typename Impl>
+WaitableEventBase<Impl>::WaitableEventBase(WaitableEventBase &&other)
+    : mResetPolicy(other.mResetPolicy), mSignaled(other.mSignaled)
+{
+}
+
+template <typename Impl>
+void WaitableEventBase<Impl>::reset()
+{
+    static_cast<Impl *>(this)->resetImpl();
+}
+
+template <typename Impl>
+void WaitableEventBase<Impl>::wait()
+{
+    static_cast<Impl *>(this)->waitImpl();
+}
+
+template <typename Impl>
+void WaitableEventBase<Impl>::signal()
+{
+    static_cast<Impl *>(this)->signalImpl();
+}
+
+template <typename Impl>
+template <size_t Count>
+// static
+size_t WaitableEventBase<Impl>::WaitManyBase(std::array<Impl, Count> *waitables)
+{
+    ASSERT(Count > 0);
+
+    for (size_t index = 0; index < Count; ++index)
+    {
+        (*waitables)[index].wait();
+    }
+
+    return 0;
+}
+
+template <typename Impl>
+Impl &WaitableEventBase<Impl>::copyBase(Impl &&other)
+{
+    std::swap(mSignaled, other.mSignaled);
+    std::swap(mResetPolicy, other.mResetPolicy);
+    return *static_cast<Impl *>(this);
+}
+
+class SingleThreadedWaitableEvent : public WaitableEventBase<SingleThreadedWaitableEvent>
+{
+  public:
+    SingleThreadedWaitableEvent();
+    SingleThreadedWaitableEvent(EventResetPolicy resetPolicy, EventInitialState initialState);
+    ~SingleThreadedWaitableEvent();
+
+    SingleThreadedWaitableEvent(SingleThreadedWaitableEvent &&other);
+    SingleThreadedWaitableEvent &operator=(SingleThreadedWaitableEvent &&other);
+
+    void resetImpl();
+    void waitImpl();
+    void signalImpl();
+
+    // Wait, synchronously, on multiple events.
+    // returns the index of a WaitableEvent which has been signaled.
+    template <size_t Count>
+    static size_t WaitMany(std::array<SingleThreadedWaitableEvent, Count> *waitables);
+};
+
+template <size_t Count>
+// static
+size_t SingleThreadedWaitableEvent::WaitMany(
+    std::array<SingleThreadedWaitableEvent, Count> *waitables)
+{
+    return WaitableEventBase<SingleThreadedWaitableEvent>::WaitManyBase(waitables);
+}
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+class AsyncWaitableEvent : public WaitableEventBase<AsyncWaitableEvent>
+{
+  public:
+    AsyncWaitableEvent();
+    AsyncWaitableEvent(EventResetPolicy resetPolicy, EventInitialState initialState);
+    ~AsyncWaitableEvent();
+
+    AsyncWaitableEvent(AsyncWaitableEvent &&other);
+    AsyncWaitableEvent &operator=(AsyncWaitableEvent &&other);
+
+    void resetImpl();
+    void waitImpl();
+    void signalImpl();
+
+    // Wait, synchronously, on multiple events.
+    // returns the index of a WaitableEvent which has been signaled.
+    template <size_t Count>
+    static size_t WaitMany(std::array<AsyncWaitableEvent, Count> *waitables);
+
+  private:
+    friend class AsyncWorkerPool;
+    void setFuture(std::future<void> &&future);
+
+    std::future<void> mFuture;
+};
+
+template <size_t Count>
+// static
+size_t AsyncWaitableEvent::WaitMany(std::array<AsyncWaitableEvent, Count> *waitables)
+{
+    return WaitableEventBase<AsyncWaitableEvent>::WaitManyBase(waitables);
+}
+#endif  // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+// The traits class allows the the thread pool to return the "Typed" waitable event from postTask.
+// Otherwise postTask would always think it returns the current active type, so the unit tests
+// could not run on multiple worker types in the same compilation.
+template <typename Impl>
+struct WorkerThreadPoolTraits;
+
+class SingleThreadedWorkerPool;
+template <>
+struct WorkerThreadPoolTraits<SingleThreadedWorkerPool>
+{
+    using WaitableEventType = SingleThreadedWaitableEvent;
+};
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+class AsyncWorkerPool;
+template <>
+struct WorkerThreadPoolTraits<AsyncWorkerPool>
+{
+    using WaitableEventType = AsyncWaitableEvent;
+};
+#endif  // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+// Request WorkerThreads from the WorkerThreadPool. Each pool can keep worker threads around so
+// we avoid the costly spin up and spin down time.
+template <typename Impl>
+class WorkerThreadPoolBase : angle::NonCopyable
+{
+  public:
+    WorkerThreadPoolBase(size_t maxThreads);
+    ~WorkerThreadPoolBase();
+
+    using WaitableEventType = typename WorkerThreadPoolTraits<Impl>::WaitableEventType;
+
+    // Returns an event to wait on for the task to finish.
+    // If the pool fails to create the task, returns null.
+    WaitableEventType postWorkerTask(Closure *task);
+};
+
+template <typename Impl>
+WorkerThreadPoolBase<Impl>::WorkerThreadPoolBase(size_t maxThreads)
+{
+}
+
+template <typename Impl>
+WorkerThreadPoolBase<Impl>::~WorkerThreadPoolBase()
+{
+}
+
+template <typename Impl>
+typename WorkerThreadPoolBase<Impl>::WaitableEventType WorkerThreadPoolBase<Impl>::postWorkerTask(
+    Closure *task)
+{
+    return static_cast<Impl *>(this)->postWorkerTaskImpl(task);
+}
+
+class SingleThreadedWorkerPool : public WorkerThreadPoolBase<SingleThreadedWorkerPool>
+{
+  public:
+    SingleThreadedWorkerPool(size_t maxThreads);
+    ~SingleThreadedWorkerPool();
+
+    SingleThreadedWaitableEvent postWorkerTaskImpl(Closure *task);
+};
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+class AsyncWorkerPool : public WorkerThreadPoolBase<AsyncWorkerPool>
+{
+  public:
+    AsyncWorkerPool(size_t maxThreads);
+    ~AsyncWorkerPool();
+
+    AsyncWaitableEvent postWorkerTaskImpl(Closure *task);
+};
+#endif  // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+}  // namespace priv
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+using WaitableEvent    = priv::AsyncWaitableEvent;
+using WorkerThreadPool = priv::AsyncWorkerPool;
+#else
+using WaitableEvent    = priv::SingleThreadedWaitableEvent;
+using WorkerThreadPool = priv::SingleThreadedWorkerPool;
+#endif  // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+}  // namespace angle
+
+#endif  // LIBANGLE_WORKER_THREAD_H_
diff --git a/src/third_party/angle/src/libANGLE/WorkerThread_unittest.cpp b/src/third_party/angle/src/libANGLE/WorkerThread_unittest.cpp
new file mode 100644
index 0000000..a5b566d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/WorkerThread_unittest.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright 2016 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.
+//
+// WorkerThread_unittest:
+//   Simple tests for the worker thread class.
+
+#include <array>
+#include <gtest/gtest.h>
+
+#include "libANGLE/WorkerThread.h"
+
+using namespace angle;
+
+namespace
+{
+
+template <typename T>
+class WorkerPoolTest : public ::testing::Test
+{
+  public:
+    T workerPool = {4};
+};
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+using WorkerPoolTypes = ::testing::Types<priv::AsyncWorkerPool, priv::SingleThreadedWorkerPool>;
+#else
+using WorkerPoolTypes = ::testing::Types<priv::SingleThreadedWorkerPool>;
+#endif  // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+TYPED_TEST_CASE(WorkerPoolTest, WorkerPoolTypes);
+
+// Tests simple worker pool application.
+TYPED_TEST(WorkerPoolTest, SimpleTask)
+{
+    class TestTask : public Closure
+    {
+      public:
+        void operator()() override { fired = true; }
+
+        bool fired = false;
+    };
+
+    std::array<TestTask, 4> tasks;
+    std::array<typename TypeParam::WaitableEventType, 4> waitables = {{
+        this->workerPool.postWorkerTask(&tasks[0]), this->workerPool.postWorkerTask(&tasks[1]),
+        this->workerPool.postWorkerTask(&tasks[2]), this->workerPool.postWorkerTask(&tasks[3]),
+    }};
+
+    TypeParam::WaitableEventType::WaitMany(&waitables);
+
+    for (const auto &task : tasks)
+    {
+        EXPECT_TRUE(task.fired);
+    }
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/libANGLE/angletypes.cpp b/src/third_party/angle/src/libANGLE/angletypes.cpp
new file mode 100644
index 0000000..70a3ae6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/angletypes.cpp
@@ -0,0 +1,144 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+
+namespace gl
+{
+
+PrimitiveType GetPrimitiveType(GLenum drawMode)
+{
+    switch (drawMode)
+    {
+        case GL_POINTS:
+            return PRIMITIVE_POINTS;
+        case GL_LINES:
+            return PRIMITIVE_LINES;
+        case GL_LINE_STRIP:
+            return PRIMITIVE_LINE_STRIP;
+        case GL_LINE_LOOP:
+            return PRIMITIVE_LINE_LOOP;
+        case GL_TRIANGLES:
+            return PRIMITIVE_TRIANGLES;
+        case GL_TRIANGLE_STRIP:
+            return PRIMITIVE_TRIANGLE_STRIP;
+        case GL_TRIANGLE_FAN:
+            return PRIMITIVE_TRIANGLE_FAN;
+        default:
+            UNREACHABLE();
+            return PRIMITIVE_TYPE_MAX;
+    }
+}
+
+SamplerState::SamplerState()
+    : minFilter(GL_NEAREST_MIPMAP_LINEAR),
+      magFilter(GL_LINEAR),
+      wrapS(GL_REPEAT),
+      wrapT(GL_REPEAT),
+      wrapR(GL_REPEAT),
+      maxAnisotropy(1.0f),
+      minLod(-1000.0f),
+      maxLod(1000.0f),
+      compareMode(GL_NONE),
+      compareFunc(GL_LEQUAL),
+      sRGBDecode(GL_DECODE_EXT)
+{
+}
+
+// static
+SamplerState SamplerState::CreateDefaultForTarget(GLenum target)
+{
+    SamplerState state;
+
+    // According to OES_EGL_image_external: For external textures, the default min filter is
+    // GL_LINEAR and the default s and t wrap modes are GL_CLAMP_TO_EDGE.
+    if (target == GL_TEXTURE_EXTERNAL_OES)
+    {
+        state.minFilter = GL_LINEAR;
+        state.wrapS     = GL_CLAMP_TO_EDGE;
+        state.wrapT     = GL_CLAMP_TO_EDGE;
+    }
+
+    return state;
+}
+
+static void MinMax(int a, int b, int *minimum, int *maximum)
+{
+    if (a < b)
+    {
+        *minimum = a;
+        *maximum = b;
+    }
+    else
+    {
+        *minimum = b;
+        *maximum = a;
+    }
+}
+
+bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection)
+{
+    int minSourceX, maxSourceX, minSourceY, maxSourceY;
+    MinMax(source.x, source.x + source.width, &minSourceX, &maxSourceX);
+    MinMax(source.y, source.y + source.height, &minSourceY, &maxSourceY);
+
+    int minClipX, maxClipX, minClipY, maxClipY;
+    MinMax(clip.x, clip.x + clip.width, &minClipX, &maxClipX);
+    MinMax(clip.y, clip.y + clip.height, &minClipY, &maxClipY);
+
+    if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY || maxSourceY <= minClipY)
+    {
+        if (intersection)
+        {
+            intersection->x = minSourceX;
+            intersection->y = maxSourceY;
+            intersection->width = maxSourceX - minSourceX;
+            intersection->height = maxSourceY - minSourceY;
+        }
+
+        return false;
+    }
+    else
+    {
+        if (intersection)
+        {
+            intersection->x = std::max(minSourceX, minClipX);
+            intersection->y = std::max(minSourceY, minClipY);
+            intersection->width  = std::min(maxSourceX, maxClipX) - std::max(minSourceX, minClipX);
+            intersection->height = std::min(maxSourceY, maxClipY) - std::max(minSourceY, minClipY);
+        }
+
+        return true;
+    }
+}
+
+bool Box::operator==(const Box &other) const
+{
+    return (x == other.x && y == other.y && z == other.z &&
+            width == other.width && height == other.height && depth == other.depth);
+}
+
+bool Box::operator!=(const Box &other) const
+{
+    return !(*this == other);
+}
+
+bool operator==(const Extents &lhs, const Extents &rhs)
+{
+    return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth;
+}
+
+bool operator!=(const Extents &lhs, const Extents &rhs)
+{
+    return !(lhs == rhs);
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/angletypes.h b/src/third_party/angle/src/libANGLE/angletypes.h
new file mode 100644
index 0000000..b6bd162
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/angletypes.h
@@ -0,0 +1,380 @@
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
+
+#ifndef LIBANGLE_ANGLETYPES_H_
+#define LIBANGLE_ANGLETYPES_H_
+
+#include "common/bitset_utils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/RefCountObject.h"
+
+#include <stdint.h>
+
+#include <bitset>
+#include <unordered_map>
+
+namespace gl
+{
+class Buffer;
+
+enum PrimitiveType
+{
+    PRIMITIVE_POINTS,
+    PRIMITIVE_LINES,
+    PRIMITIVE_LINE_STRIP,
+    PRIMITIVE_LINE_LOOP,
+    PRIMITIVE_TRIANGLES,
+    PRIMITIVE_TRIANGLE_STRIP,
+    PRIMITIVE_TRIANGLE_FAN,
+    PRIMITIVE_TYPE_MAX,
+};
+
+PrimitiveType GetPrimitiveType(GLenum drawMode);
+
+enum SamplerType
+{
+    SAMPLER_PIXEL,
+    SAMPLER_VERTEX,
+    SAMPLER_COMPUTE
+};
+
+struct Rectangle
+{
+    Rectangle() : x(0), y(0), width(0), height(0) {}
+    Rectangle(int x_in, int y_in, int width_in, int height_in)
+        : x(x_in), y(y_in), width(width_in), height(height_in)
+    {
+    }
+
+    int x0() const { return x; }
+    int y0() const { return y; }
+    int x1() const { return x + width; }
+    int y1() const { return y + height; }
+
+    int x;
+    int y;
+    int width;
+    int height;
+};
+
+bool operator==(const Rectangle &a, const Rectangle &b);
+bool operator!=(const Rectangle &a, const Rectangle &b);
+
+bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
+
+struct Offset
+{
+    int x;
+    int y;
+    int z;
+
+    Offset() : x(0), y(0), z(0) { }
+    Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) { }
+};
+
+struct Extents
+{
+    int width;
+    int height;
+    int depth;
+
+    Extents() : width(0), height(0), depth(0) { }
+    Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) { }
+
+    Extents(const Extents &other) = default;
+    Extents &operator=(const Extents &other) = default;
+
+    bool empty() const { return (width * height * depth) == 0; }
+};
+
+bool operator==(const Extents &lhs, const Extents &rhs);
+bool operator!=(const Extents &lhs, const Extents &rhs);
+
+struct Box
+{
+    int x;
+    int y;
+    int z;
+    int width;
+    int height;
+    int depth;
+
+    Box() : x(0), y(0), z(0), width(0), height(0), depth(0) { }
+    Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in) : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in) { }
+    Box(const Offset &offset, const Extents &size) : x(offset.x), y(offset.y), z(offset.z), width(size.width), height(size.height), depth(size.depth) { }
+    bool operator==(const Box &other) const;
+    bool operator!=(const Box &other) const;
+};
+
+
+struct RasterizerState
+{
+    bool cullFace;
+    GLenum cullMode;
+    GLenum frontFace;
+
+    bool polygonOffsetFill;
+    GLfloat polygonOffsetFactor;
+    GLfloat polygonOffsetUnits;
+
+    bool pointDrawMode;
+    bool multiSample;
+
+    bool rasterizerDiscard;
+};
+
+struct BlendState
+{
+    bool blend;
+    GLenum sourceBlendRGB;
+    GLenum destBlendRGB;
+    GLenum sourceBlendAlpha;
+    GLenum destBlendAlpha;
+    GLenum blendEquationRGB;
+    GLenum blendEquationAlpha;
+
+    bool colorMaskRed;
+    bool colorMaskGreen;
+    bool colorMaskBlue;
+    bool colorMaskAlpha;
+
+    bool sampleAlphaToCoverage;
+
+    bool dither;
+};
+
+struct DepthStencilState
+{
+    bool depthTest;
+    GLenum depthFunc;
+    bool depthMask;
+
+    bool stencilTest;
+    GLenum stencilFunc;
+    GLuint stencilMask;
+    GLenum stencilFail;
+    GLenum stencilPassDepthFail;
+    GLenum stencilPassDepthPass;
+    GLuint stencilWritemask;
+    GLenum stencilBackFunc;
+    GLuint stencilBackMask;
+    GLenum stencilBackFail;
+    GLenum stencilBackPassDepthFail;
+    GLenum stencilBackPassDepthPass;
+    GLuint stencilBackWritemask;
+};
+
+struct DrawArraysIndirectCommand
+{
+    GLuint count;
+    GLuint instanceCount;
+    GLuint first;
+    GLuint baseInstance;
+};
+static_assert(sizeof(DrawArraysIndirectCommand) == 16,
+              "Unexpected size of DrawArraysIndirectCommand");
+
+struct DrawElementsIndirectCommand
+{
+    GLuint count;
+    GLuint primCount;
+    GLuint firstIndex;
+    GLint baseVertex;
+    GLuint baseInstance;
+};
+static_assert(sizeof(DrawElementsIndirectCommand) == 20,
+              "Unexpected size of DrawElementsIndirectCommand");
+
+// State from Table 6.10 (state per sampler object)
+struct SamplerState
+{
+    SamplerState();
+    static SamplerState CreateDefaultForTarget(GLenum target);
+
+    GLenum minFilter;
+    GLenum magFilter;
+
+    GLenum wrapS;
+    GLenum wrapT;
+    GLenum wrapR;
+
+    // From EXT_texture_filter_anisotropic
+    float maxAnisotropy;
+
+    GLfloat minLod;
+    GLfloat maxLod;
+
+    GLenum compareMode;
+    GLenum compareFunc;
+
+    GLenum sRGBDecode;
+};
+
+bool operator==(const SamplerState &a, const SamplerState &b);
+bool operator!=(const SamplerState &a, const SamplerState &b);
+
+struct PixelStoreStateBase
+{
+    BindingPointer<Buffer> pixelBuffer;
+    GLint alignment   = 4;
+    GLint rowLength   = 0;
+    GLint skipRows    = 0;
+    GLint skipPixels  = 0;
+    GLint imageHeight = 0;
+    GLint skipImages  = 0;
+};
+
+struct PixelUnpackState : PixelStoreStateBase
+{
+    PixelUnpackState() {}
+
+    PixelUnpackState(GLint alignmentIn, GLint rowLengthIn)
+    {
+        alignment = alignmentIn;
+        rowLength = rowLengthIn;
+    }
+};
+
+struct PixelPackState : PixelStoreStateBase
+{
+    PixelPackState() {}
+
+    PixelPackState(GLint alignmentIn, bool reverseRowOrderIn)
+        : reverseRowOrder(reverseRowOrderIn)
+    {
+        alignment = alignmentIn;
+    }
+
+    bool reverseRowOrder = false;
+};
+
+// Used in Program and VertexArray.
+using AttributesMask = angle::BitSet<MAX_VERTEX_ATTRIBS>;
+
+// Use in Program
+using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
+
+// A map of GL objects indexed by object ID. The specific map implementation may change.
+// Client code should treat it as a std::map.
+template <class ResourceT>
+using ResourceMap = std::unordered_map<GLuint, ResourceT *>;
+
+using ContextID = uintptr_t;
+}
+
+namespace rx
+{
+// A macro that determines whether an object has a given runtime type.
+#if defined(__clang__)
+#if __has_feature(cxx_rtti)
+#define ANGLE_HAS_DYNAMIC_CAST 1
+#endif
+#elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || defined(__GXX_RTTI))
+#define ANGLE_HAS_DYNAMIC_CAST 1
+#endif
+
+#ifdef ANGLE_HAS_DYNAMIC_CAST
+#define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type >(obj) != nullptr)
+#undef ANGLE_HAS_DYNAMIC_CAST
+#else
+#define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
+#endif
+
+// Downcast a base implementation object (EG TextureImpl to TextureD3D)
+template <typename DestT, typename SrcT>
+inline DestT *GetAs(SrcT *src)
+{
+    ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT*, src));
+    return static_cast<DestT*>(src);
+}
+
+template <typename DestT, typename SrcT>
+inline const DestT *GetAs(const SrcT *src)
+{
+    ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT*, src));
+    return static_cast<const DestT*>(src);
+}
+
+#undef ANGLE_HAS_DYNAMIC_TYPE
+
+// Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
+template <typename DestT, typename SrcT>
+inline DestT *GetImplAs(SrcT *src)
+{
+    return GetAs<DestT>(src->getImplementation());
+}
+
+template <typename DestT, typename SrcT>
+inline DestT *SafeGetImplAs(SrcT *src)
+{
+    return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
+}
+
+// In some cases we want to retrieve an Impl object, while handling nullptr cases trivially.
+template <typename ObjT>
+auto SafeGetImpl(ObjT *src) -> decltype(src->getImplementation())
+{
+    return src ? src->getImplementation() : nullptr;
+}
+
+}  // namespace rx
+
+#include "angletypes.inl"
+
+namespace angle
+{
+// Zero-based for better array indexing
+enum FramebufferBinding
+{
+    FramebufferBindingRead = 0,
+    FramebufferBindingDraw,
+    FramebufferBindingSingletonMax,
+    FramebufferBindingBoth = FramebufferBindingSingletonMax,
+    FramebufferBindingMax,
+    FramebufferBindingUnknown = FramebufferBindingMax,
+};
+
+inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
+{
+    switch (enumValue)
+    {
+        case GL_READ_FRAMEBUFFER:
+            return FramebufferBindingRead;
+        case GL_DRAW_FRAMEBUFFER:
+            return FramebufferBindingDraw;
+        case GL_FRAMEBUFFER:
+            return FramebufferBindingBoth;
+        default:
+            UNREACHABLE();
+            return FramebufferBindingUnknown;
+    }
+}
+
+inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
+{
+    switch (binding)
+    {
+        case FramebufferBindingRead:
+            return GL_READ_FRAMEBUFFER;
+        case FramebufferBindingDraw:
+            return GL_DRAW_FRAMEBUFFER;
+        case FramebufferBindingBoth:
+            return GL_FRAMEBUFFER;
+        default:
+            UNREACHABLE();
+            return GL_NONE;
+    }
+}
+}  // namespace angle
+
+namespace gl
+{
+class ContextState;
+}  // namespace gl
+
+#endif // LIBANGLE_ANGLETYPES_H_
diff --git a/src/third_party/angle/src/libANGLE/angletypes.inl b/src/third_party/angle/src/libANGLE/angletypes.inl
new file mode 100644
index 0000000..3371286
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/angletypes.inl
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angletypes.inl : Inline definitions of some functions from angletypes.h
+
+namespace gl
+{
+
+inline bool operator==(const Rectangle &a, const Rectangle &b)
+{
+    return a.x == b.x &&
+           a.y == b.y &&
+           a.width == b.width &&
+           a.height == b.height;
+}
+
+inline bool operator!=(const Rectangle &a, const Rectangle &b)
+{
+    return !(a == b);
+}
+
+inline bool operator==(const SamplerState &a, const SamplerState &b)
+{
+    return a.minFilter == b.minFilter &&
+           a.magFilter == b.magFilter &&
+           a.wrapS == b.wrapS &&
+           a.wrapT == b.wrapT &&
+           a.wrapR == b.wrapR &&
+           a.maxAnisotropy == b.maxAnisotropy &&
+           a.minLod == b.minLod &&
+           a.maxLod == b.maxLod &&
+           a.compareMode == b.compareMode &&
+           a.compareFunc == b.compareFunc;
+}
+
+inline bool operator!=(const SamplerState &a, const SamplerState &b)
+{
+    return !(a == b);
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/entry_points_enum_autogen.h b/src/third_party/angle/src/libANGLE/entry_points_enum_autogen.h
new file mode 100644
index 0000000..290e2f4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/entry_points_enum_autogen.h
@@ -0,0 +1,166 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 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.
+//
+// entry_points_enum_autogen.h:
+//   Defines the GLES entry points enumeration.
+
+#ifndef LIBGLESV2_ENTRYPOINTSENUM_AUTOGEN_H_
+#define LIBGLESV2_ENTRYPOINTSENUM_AUTOGEN_H_
+
+namespace gl
+{
+enum class EntryPoint
+{
+    Invalid,
+    ActiveTexture,
+    AttachShader,
+    BindAttribLocation,
+    BindBuffer,
+    BindFramebuffer,
+    BindRenderbuffer,
+    BindTexture,
+    BlendColor,
+    BlendEquation,
+    BlendEquationSeparate,
+    BlendFunc,
+    BlendFuncSeparate,
+    BufferData,
+    BufferSubData,
+    CheckFramebufferStatus,
+    Clear,
+    ClearColor,
+    ClearDepthf,
+    ClearStencil,
+    ColorMask,
+    CompileShader,
+    CompressedTexImage2D,
+    CompressedTexSubImage2D,
+    CopyTexImage2D,
+    CopyTexSubImage2D,
+    CreateProgram,
+    CreateShader,
+    CullFace,
+    DeleteBuffers,
+    DeleteFramebuffers,
+    DeleteProgram,
+    DeleteRenderbuffers,
+    DeleteShader,
+    DeleteTextures,
+    DepthFunc,
+    DepthMask,
+    DepthRangef,
+    DetachShader,
+    Disable,
+    DisableVertexAttribArray,
+    DrawArrays,
+    DrawElements,
+    Enable,
+    EnableVertexAttribArray,
+    Finish,
+    Flush,
+    FramebufferRenderbuffer,
+    FramebufferTexture2D,
+    FrontFace,
+    GenBuffers,
+    GenerateMipmap,
+    GenFramebuffers,
+    GenRenderbuffers,
+    GenTextures,
+    GetActiveAttrib,
+    GetActiveUniform,
+    GetAttachedShaders,
+    GetAttribLocation,
+    GetBooleanv,
+    GetBufferParameteriv,
+    GetError,
+    GetFloatv,
+    GetFramebufferAttachmentParameteriv,
+    GetIntegerv,
+    GetProgramiv,
+    GetProgramInfoLog,
+    GetRenderbufferParameteriv,
+    GetShaderiv,
+    GetShaderInfoLog,
+    GetShaderPrecisionFormat,
+    GetShaderSource,
+    GetString,
+    GetTexParameterfv,
+    GetTexParameteriv,
+    GetUniformfv,
+    GetUniformiv,
+    GetUniformLocation,
+    GetVertexAttribfv,
+    GetVertexAttribiv,
+    GetVertexAttribPointerv,
+    Hint,
+    IsBuffer,
+    IsEnabled,
+    IsFramebuffer,
+    IsProgram,
+    IsRenderbuffer,
+    IsShader,
+    IsTexture,
+    LineWidth,
+    LinkProgram,
+    PixelStorei,
+    PolygonOffset,
+    ReadPixels,
+    ReleaseShaderCompiler,
+    RenderbufferStorage,
+    SampleCoverage,
+    Scissor,
+    ShaderBinary,
+    ShaderSource,
+    StencilFunc,
+    StencilFuncSeparate,
+    StencilMask,
+    StencilMaskSeparate,
+    StencilOp,
+    StencilOpSeparate,
+    TexImage2D,
+    TexParameterf,
+    TexParameterfv,
+    TexParameteri,
+    TexParameteriv,
+    TexSubImage2D,
+    Uniform1f,
+    Uniform1fv,
+    Uniform1i,
+    Uniform1iv,
+    Uniform2f,
+    Uniform2fv,
+    Uniform2i,
+    Uniform2iv,
+    Uniform3f,
+    Uniform3fv,
+    Uniform3i,
+    Uniform3iv,
+    Uniform4f,
+    Uniform4fv,
+    Uniform4i,
+    Uniform4iv,
+    UniformMatrix2fv,
+    UniformMatrix3fv,
+    UniformMatrix4fv,
+    UseProgram,
+    ValidateProgram,
+    VertexAttrib1f,
+    VertexAttrib1fv,
+    VertexAttrib2f,
+    VertexAttrib2fv,
+    VertexAttrib3f,
+    VertexAttrib3fv,
+    VertexAttrib4f,
+    VertexAttrib4fv,
+    VertexAttribPointer,
+    Viewport,
+    DrawElementsInstanced,
+    DrawRangeElements,
+    DrawElementsInstancedANGLE
+};
+}  // namespace gl
+#endif  // LIBGLESV2_ENTRY_POINTS_ENUM_AUTOGEN_H_
diff --git a/src/third_party/angle/src/libANGLE/es3_copy_conversion_formats.json b/src/third_party/angle/src/libANGLE/es3_copy_conversion_formats.json
new file mode 100644
index 0000000..39b71fd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/es3_copy_conversion_formats.json
@@ -0,0 +1,44 @@
+{
+    "From ES 3.0.1 spec, table 3.15":
+    [
+        [ "GL_ALPHA", "GL_RGBA" ],
+        [ "GL_LUMINANCE", "GL_RED" ],
+        [ "GL_LUMINANCE", "GL_RG" ],
+        [ "GL_LUMINANCE", "GL_RGB" ],
+        [ "GL_LUMINANCE", "GL_RGBA" ],
+        [ "GL_LUMINANCE_ALPHA", "GL_RGBA" ],
+        [ "GL_RED", "GL_RED" ],
+        [ "GL_RED", "GL_RG" ],
+        [ "GL_RED", "GL_RGB" ],
+        [ "GL_RED", "GL_RGBA" ],
+        [ "GL_RG", "GL_RG" ],
+        [ "GL_RG", "GL_RGB" ],
+        [ "GL_RG", "GL_RGBA" ],
+        [ "GL_RGB", "GL_RGB" ],
+        [ "GL_RGB", "GL_RGBA" ],
+        [ "GL_RGBA", "GL_RGBA" ]
+    ],
+
+    "Necessary for ANGLE back-buffers":
+    [
+        [ "GL_ALPHA", "GL_BGRA_EXT" ],
+        [ "GL_LUMINANCE", "GL_BGRA_EXT" ],
+        [ "GL_LUMINANCE_ALPHA", "GL_BGRA_EXT" ],
+        [ "GL_RED", "GL_BGRA_EXT" ],
+        [ "GL_RG", "GL_BGRA_EXT" ],
+        [ "GL_RGB", "GL_BGRA_EXT" ],
+        [ "GL_RGBA", "GL_BGRA_EXT" ],
+        [ "GL_BGRA_EXT", "GL_BGRA_EXT" ],
+
+        [ "GL_RED_INTEGER", "GL_RED_INTEGER" ],
+        [ "GL_RED_INTEGER", "GL_RG_INTEGER" ],
+        [ "GL_RED_INTEGER", "GL_RGB_INTEGER" ],
+        [ "GL_RED_INTEGER", "GL_RGBA_INTEGER" ],
+        [ "GL_RG_INTEGER", "GL_RG_INTEGER" ],
+        [ "GL_RG_INTEGER", "GL_RGB_INTEGER" ],
+        [ "GL_RG_INTEGER", "GL_RGBA_INTEGER" ],
+        [ "GL_RGB_INTEGER", "GL_RGB_INTEGER" ],
+        [ "GL_RGB_INTEGER", "GL_RGBA_INTEGER" ],
+        [ "GL_RGBA_INTEGER", "GL_RGBA_INTEGER" ]
+    ]
+}
diff --git a/src/third_party/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp b/src/third_party/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp
new file mode 100644
index 0000000..3647445
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp
@@ -0,0 +1,171 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_copy_conversion_table.py using data from es3_copy_conversion_formats.json.
+//
+// Copyright 2016 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.
+//
+// format_map:
+//   Determining the sized internal format from a (format,type) pair.
+//   Also check es3 format combinations for validity.
+
+#include "angle_gl.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
+{
+    switch (textureFormat)
+    {
+        case GL_ALPHA:
+            switch (framebufferFormat)
+            {
+                case GL_BGRA_EXT:
+                case GL_RGBA:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_BGRA_EXT:
+            switch (framebufferFormat)
+            {
+                case GL_BGRA_EXT:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_LUMINANCE:
+            switch (framebufferFormat)
+            {
+                case GL_BGRA_EXT:
+                case GL_RED:
+                case GL_RG:
+                case GL_RGB:
+                case GL_RGBA:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_LUMINANCE_ALPHA:
+            switch (framebufferFormat)
+            {
+                case GL_BGRA_EXT:
+                case GL_RGBA:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RED:
+            switch (framebufferFormat)
+            {
+                case GL_BGRA_EXT:
+                case GL_RED:
+                case GL_RG:
+                case GL_RGB:
+                case GL_RGBA:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RED_INTEGER:
+            switch (framebufferFormat)
+            {
+                case GL_RED_INTEGER:
+                case GL_RGBA_INTEGER:
+                case GL_RGB_INTEGER:
+                case GL_RG_INTEGER:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RG:
+            switch (framebufferFormat)
+            {
+                case GL_BGRA_EXT:
+                case GL_RG:
+                case GL_RGB:
+                case GL_RGBA:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGB:
+            switch (framebufferFormat)
+            {
+                case GL_BGRA_EXT:
+                case GL_RGB:
+                case GL_RGBA:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGBA:
+            switch (framebufferFormat)
+            {
+                case GL_BGRA_EXT:
+                case GL_RGBA:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGBA_INTEGER:
+            switch (framebufferFormat)
+            {
+                case GL_RGBA_INTEGER:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGB_INTEGER:
+            switch (framebufferFormat)
+            {
+                case GL_RGBA_INTEGER:
+                case GL_RGB_INTEGER:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RG_INTEGER:
+            switch (framebufferFormat)
+            {
+                case GL_RGBA_INTEGER:
+                case GL_RGB_INTEGER:
+                case GL_RG_INTEGER:
+                    return true;
+                default:
+                    break;
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    return false;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/es3_format_type_combinations.json b/src/third_party/angle/src/libANGLE/es3_format_type_combinations.json
new file mode 100644
index 0000000..fb12242
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/es3_format_type_combinations.json
@@ -0,0 +1,171 @@
+{
+    "Format combinations from ES 3.0.1 spec, table 3.2":
+    [
+        [ "GL_RGBA8",              "GL_RGBA",            "GL_UNSIGNED_BYTE" ],
+        [ "GL_RGB5_A1",            "GL_RGBA",            "GL_UNSIGNED_BYTE" ],
+        [ "GL_RGBA4",              "GL_RGBA",            "GL_UNSIGNED_BYTE" ],
+        [ "GL_SRGB8_ALPHA8",       "GL_RGBA",            "GL_UNSIGNED_BYTE" ],
+        [ "GL_RGBA8_SNORM",        "GL_RGBA",            "GL_BYTE" ],
+        [ "GL_RGBA4",              "GL_RGBA",            "GL_UNSIGNED_SHORT_4_4_4_4" ],
+        [ "GL_RGB10_A2",           "GL_RGBA",            "GL_UNSIGNED_INT_2_10_10_10_REV" ],
+        [ "GL_RGB5_A1",            "GL_RGBA",            "GL_UNSIGNED_INT_2_10_10_10_REV" ],
+        [ "GL_RGB5_A1",            "GL_RGBA",            "GL_UNSIGNED_SHORT_5_5_5_1" ],
+        [ "GL_RGBA16F",            "GL_RGBA",            "GL_HALF_FLOAT" ],
+        [ "GL_RGBA16F",            "GL_RGBA",            "GL_HALF_FLOAT_OES" ],
+        [ "GL_RGBA32F",            "GL_RGBA",            "GL_FLOAT" ],
+        [ "GL_RGBA16F",            "GL_RGBA",            "GL_FLOAT" ],
+        [ "GL_RGBA8UI",            "GL_RGBA_INTEGER",    "GL_UNSIGNED_BYTE" ],
+        [ "GL_RGBA8I",             "GL_RGBA_INTEGER",    "GL_BYTE" ],
+        [ "GL_RGBA16UI",           "GL_RGBA_INTEGER",    "GL_UNSIGNED_SHORT" ],
+        [ "GL_RGBA16I",            "GL_RGBA_INTEGER",    "GL_SHORT" ],
+        [ "GL_RGBA32UI",           "GL_RGBA_INTEGER",    "GL_UNSIGNED_INT" ],
+        [ "GL_RGBA32I",            "GL_RGBA_INTEGER",    "GL_INT" ],
+        [ "GL_RGB10_A2UI",         "GL_RGBA_INTEGER",    "GL_UNSIGNED_INT_2_10_10_10_REV" ],
+        [ "GL_RGB8",               "GL_RGB",             "GL_UNSIGNED_BYTE" ],
+        [ "GL_RGB565",             "GL_RGB",             "GL_UNSIGNED_BYTE" ],
+        [ "GL_SRGB8",              "GL_RGB",             "GL_UNSIGNED_BYTE" ],
+        [ "GL_RGB8_SNORM",         "GL_RGB",             "GL_BYTE" ],
+        [ "GL_RGB565",             "GL_RGB",             "GL_UNSIGNED_SHORT_5_6_5" ],
+        [ "GL_R11F_G11F_B10F",     "GL_RGB",             "GL_UNSIGNED_INT_10F_11F_11F_REV" ],
+        [ "GL_RGB9_E5",            "GL_RGB",             "GL_UNSIGNED_INT_5_9_9_9_REV" ],
+        [ "GL_RGB16F",             "GL_RGB",             "GL_HALF_FLOAT" ],
+        [ "GL_RGB16F",             "GL_RGB",             "GL_HALF_FLOAT_OES" ],
+        [ "GL_R11F_G11F_B10F",     "GL_RGB",             "GL_HALF_FLOAT" ],
+        [ "GL_R11F_G11F_B10F",     "GL_RGB",             "GL_HALF_FLOAT_OES" ],
+        [ "GL_RGB9_E5",            "GL_RGB",             "GL_HALF_FLOAT" ],
+        [ "GL_RGB9_E5",            "GL_RGB",             "GL_HALF_FLOAT_OES" ],
+        [ "GL_RGB32F",             "GL_RGB",             "GL_FLOAT" ],
+        [ "GL_RGB16F",             "GL_RGB",             "GL_FLOAT" ],
+        [ "GL_R11F_G11F_B10F",     "GL_RGB",             "GL_FLOAT" ],
+        [ "GL_RGB9_E5",            "GL_RGB",             "GL_FLOAT" ],
+        [ "GL_RGB8UI",             "GL_RGB_INTEGER",     "GL_UNSIGNED_BYTE" ],
+        [ "GL_RGB8I",              "GL_RGB_INTEGER",     "GL_BYTE" ],
+        [ "GL_RGB16UI",            "GL_RGB_INTEGER",     "GL_UNSIGNED_SHORT" ],
+        [ "GL_RGB16I",             "GL_RGB_INTEGER",     "GL_SHORT" ],
+        [ "GL_RGB32UI",            "GL_RGB_INTEGER",     "GL_UNSIGNED_INT" ],
+        [ "GL_RGB32I",             "GL_RGB_INTEGER",     "GL_INT" ],
+        [ "GL_RG8",                "GL_RG",              "GL_UNSIGNED_BYTE" ],
+        [ "GL_RG8_SNORM",          "GL_RG",              "GL_BYTE" ],
+        [ "GL_RG16F",              "GL_RG",              "GL_HALF_FLOAT" ],
+        [ "GL_RG16F",              "GL_RG",              "GL_HALF_FLOAT_OES" ],
+        [ "GL_RG32F",              "GL_RG",              "GL_FLOAT" ],
+        [ "GL_RG16F",              "GL_RG",              "GL_FLOAT" ],
+        [ "GL_RG8UI",              "GL_RG_INTEGER",      "GL_UNSIGNED_BYTE" ],
+        [ "GL_RG8I",               "GL_RG_INTEGER",      "GL_BYTE" ],
+        [ "GL_RG16UI",             "GL_RG_INTEGER",      "GL_UNSIGNED_SHORT" ],
+        [ "GL_RG16I",              "GL_RG_INTEGER",      "GL_SHORT" ],
+        [ "GL_RG32UI",             "GL_RG_INTEGER",      "GL_UNSIGNED_INT" ],
+        [ "GL_RG32I",              "GL_RG_INTEGER",      "GL_INT" ],
+        [ "GL_R8",                 "GL_RED",             "GL_UNSIGNED_BYTE" ],
+        [ "GL_R8_SNORM",           "GL_RED",             "GL_BYTE" ],
+        [ "GL_R16F",               "GL_RED",             "GL_HALF_FLOAT" ],
+        [ "GL_R16F",               "GL_RED",             "GL_HALF_FLOAT_OES" ],
+        [ "GL_R32F",               "GL_RED",             "GL_FLOAT" ],
+        [ "GL_R16F",               "GL_RED",             "GL_FLOAT" ],
+        [ "GL_R8UI",               "GL_RED_INTEGER",     "GL_UNSIGNED_BYTE" ],
+        [ "GL_R8I",                "GL_RED_INTEGER",     "GL_BYTE" ],
+        [ "GL_R16UI",              "GL_RED_INTEGER",     "GL_UNSIGNED_SHORT" ],
+        [ "GL_R16I",               "GL_RED_INTEGER",     "GL_SHORT" ],
+        [ "GL_R32UI",              "GL_RED_INTEGER",     "GL_UNSIGNED_INT" ],
+        [ "GL_R32I",               "GL_RED_INTEGER",     "GL_INT" ]
+    ],
+    "Unsized formats":
+    [
+        [ "GL_RGBA",               "GL_RGBA",            "GL_UNSIGNED_BYTE" ],
+        [ "GL_RGBA",               "GL_RGBA",            "GL_UNSIGNED_SHORT_4_4_4_4" ],
+        [ "GL_RGBA",               "GL_RGBA",            "GL_UNSIGNED_SHORT_5_5_5_1" ],
+        [ "GL_RGB",                "GL_RGB",             "GL_UNSIGNED_BYTE" ],
+        [ "GL_RGB",                "GL_RGB",             "GL_UNSIGNED_SHORT_5_6_5" ],
+        [ "GL_LUMINANCE_ALPHA",    "GL_LUMINANCE_ALPHA", "GL_UNSIGNED_BYTE" ],
+        [ "GL_LUMINANCE",          "GL_LUMINANCE",       "GL_UNSIGNED_BYTE" ],
+        [ "GL_ALPHA",              "GL_ALPHA",           "GL_UNSIGNED_BYTE" ],
+        [ "GL_SRGB_ALPHA_EXT",     "GL_SRGB_ALPHA_EXT",  "GL_UNSIGNED_BYTE" ],
+        [ "GL_SRGB_EXT",           "GL_SRGB_EXT",        "GL_UNSIGNED_BYTE" ],
+        [ "GL_RG",                 "GL_RG",              "GL_UNSIGNED_BYTE" ],
+        [ "GL_RG",                 "GL_RG",              "GL_FLOAT" ],
+        [ "GL_RG",                 "GL_RG",              "GL_HALF_FLOAT" ],
+        [ "GL_RG",                 "GL_RG",              "GL_HALF_FLOAT_OES" ],
+        [ "GL_RED",                "GL_RED",             "GL_UNSIGNED_BYTE" ],
+        [ "GL_RED",                "GL_RED",             "GL_FLOAT" ],
+        [ "GL_RED",                "GL_RED",             "GL_HALF_FLOAT" ],
+        [ "GL_RED",                "GL_RED",             "GL_HALF_FLOAT_OES" ],
+        [ "GL_DEPTH_STENCIL",      "GL_DEPTH_STENCIL",   "GL_UNSIGNED_INT_24_8" ]
+    ],
+    "Depth stencil formats":
+    [
+        [ "GL_DEPTH_COMPONENT16",  "GL_DEPTH_COMPONENT", "GL_UNSIGNED_SHORT" ],
+        [ "GL_DEPTH_COMPONENT24",  "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT" ],
+        [ "GL_DEPTH_COMPONENT16",  "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT" ],
+        [ "GL_DEPTH_COMPONENT32F", "GL_DEPTH_COMPONENT", "GL_FLOAT" ],
+        [ "GL_DEPTH24_STENCIL8",   "GL_DEPTH_STENCIL",   "GL_UNSIGNED_INT_24_8" ],
+        [ "GL_DEPTH32F_STENCIL8",  "GL_DEPTH_STENCIL",   "GL_FLOAT_32_UNSIGNED_INT_24_8_REV" ]
+    ],
+    "From GL_EXT_sRGB":
+    [
+        [ "GL_SRGB8_ALPHA8_EXT",   "GL_SRGB_ALPHA_EXT", "GL_UNSIGNED_BYTE" ],
+        [ "GL_SRGB8",              "GL_SRGB_EXT",       "GL_UNSIGNED_BYTE" ]
+    ],
+    "From GL_OES_texture_float":
+    [
+        [ "GL_RGBA",               "GL_RGBA",            "GL_FLOAT" ],
+        [ "GL_RGB",                "GL_RGB",             "GL_FLOAT" ],
+        [ "GL_LUMINANCE_ALPHA",    "GL_LUMINANCE_ALPHA", "GL_FLOAT" ],
+        [ "GL_LUMINANCE",          "GL_LUMINANCE",       "GL_FLOAT" ],
+        [ "GL_ALPHA",              "GL_ALPHA",           "GL_FLOAT" ]
+    ],
+    "From GL_OES_texture_half_float":
+    [
+        [ "GL_RGBA",               "GL_RGBA",            "GL_HALF_FLOAT_OES" ],
+        [ "GL_RGB",                "GL_RGB",             "GL_HALF_FLOAT_OES" ],
+        [ "GL_LUMINANCE_ALPHA",    "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT" ],
+        [ "GL_LUMINANCE_ALPHA",    "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT_OES" ],
+        [ "GL_LUMINANCE",          "GL_LUMINANCE",       "GL_HALF_FLOAT" ],
+        [ "GL_LUMINANCE",          "GL_LUMINANCE",       "GL_HALF_FLOAT_OES" ],
+        [ "GL_ALPHA",              "GL_ALPHA",           "GL_HALF_FLOAT" ],
+        [ "GL_ALPHA",              "GL_ALPHA",           "GL_HALF_FLOAT_OES" ]
+    ],
+    "From GL_EXT_texture_format_BGRA8888":
+    [
+        [ "GL_BGRA_EXT",           "GL_BGRA_EXT",        "GL_UNSIGNED_BYTE" ]
+    ],
+    "From GL_EXT_texture_storage":
+    [
+        [ "GL_ALPHA8_EXT",             "GL_ALPHA",           "GL_UNSIGNED_BYTE" ],
+        [ "GL_LUMINANCE8_EXT",         "GL_LUMINANCE",       "GL_UNSIGNED_BYTE" ],
+        [ "GL_LUMINANCE8_ALPHA8_EXT",  "GL_LUMINANCE_ALPHA", "GL_UNSIGNED_BYTE" ],
+        [ "GL_ALPHA32F_EXT",           "GL_ALPHA",           "GL_FLOAT" ],
+        [ "GL_LUMINANCE32F_EXT",       "GL_LUMINANCE",       "GL_FLOAT" ],
+        [ "GL_LUMINANCE_ALPHA32F_EXT", "GL_LUMINANCE_ALPHA", "GL_FLOAT" ],
+        [ "GL_ALPHA16F_EXT",           "GL_ALPHA",           "GL_HALF_FLOAT" ],
+        [ "GL_ALPHA16F_EXT",           "GL_ALPHA",           "GL_HALF_FLOAT_OES" ],
+        [ "GL_LUMINANCE16F_EXT",       "GL_LUMINANCE",       "GL_HALF_FLOAT" ],
+        [ "GL_LUMINANCE16F_EXT",       "GL_LUMINANCE",       "GL_HALF_FLOAT_OES" ],
+        [ "GL_LUMINANCE_ALPHA16F_EXT", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT" ],
+        [ "GL_LUMINANCE_ALPHA16F_EXT", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT_OES" ]
+    ],
+    "From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888":
+    [
+        [ "GL_BGRA8_EXT",              "GL_BGRA_EXT",        "GL_UNSIGNED_BYTE" ],
+        [ "GL_BGRA4_ANGLEX",           "GL_BGRA_EXT",        "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT" ],
+        [ "GL_BGRA4_ANGLEX",           "GL_BGRA_EXT",        "GL_UNSIGNED_BYTE" ],
+        [ "GL_BGR5_A1_ANGLEX",         "GL_BGRA_EXT",        "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT" ],
+        [ "GL_BGR5_A1_ANGLEX",         "GL_BGRA_EXT",        "GL_UNSIGNED_BYTE" ]
+    ],
+    "From GL_ANGLE_depth_texture and OES_depth_texture":
+    [
+        [ "GL_DEPTH_COMPONENT32_OES",  "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT_24_8" ],
+        [ "GL_DEPTH_COMPONENT",        "GL_DEPTH_COMPONENT", "GL_UNSIGNED_SHORT" ],
+        [ "GL_DEPTH_COMPONENT",        "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT" ]
+    ],
+    "From GL_EXT_texture_norm16":
+    [
+        [ "GL_R16_EXT",          "GL_RED",  "GL_UNSIGNED_SHORT" ],
+        [ "GL_RG16_EXT",         "GL_RG",   "GL_UNSIGNED_SHORT" ],
+        [ "GL_RGB16_EXT",        "GL_RGB",  "GL_UNSIGNED_SHORT" ],
+        [ "GL_RGBA16_EXT",       "GL_RGBA", "GL_UNSIGNED_SHORT" ],
+        [ "GL_R16_SNORM_EXT",    "GL_RED",  "GL_SHORT" ],
+        [ "GL_RG16_SNORM_EXT",   "GL_RG",   "GL_SHORT" ],
+        [ "GL_RGB16_SNORM_EXT",  "GL_RGB",  "GL_SHORT" ],
+        [ "GL_RGBA16_SNORM_EXT", "GL_RGBA", "GL_SHORT" ]
+    ]
+}
diff --git a/src/third_party/angle/src/libANGLE/features.h b/src/third_party/angle/src/libANGLE/features.h
new file mode 100644
index 0000000..48a194f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/features.h
@@ -0,0 +1,65 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_FEATURES_H_
+#define LIBANGLE_FEATURES_H_
+
+#include "common/platform.h"
+
+#define ANGLE_DISABLED 0
+#define ANGLE_ENABLED 1
+
+// Feature defaults
+
+// Direct3D9EX
+// The "Debug This Pixel..." feature in PIX often fails when using the
+// D3D9Ex interfaces.  In order to get debug pixel to work on a Vista/Win 7
+// machine, define "ANGLE_D3D9EX=0" in your project file.
+#if !defined(ANGLE_D3D9EX)
+#define ANGLE_D3D9EX ANGLE_ENABLED
+#endif
+
+// Vsync
+// ENABLED allows Vsync to be configured at runtime
+// DISABLED disallows Vsync
+#if !defined(ANGLE_VSYNC)
+#define ANGLE_VSYNC ANGLE_ENABLED
+#endif
+
+// Program binary loading
+#if !defined(ANGLE_PROGRAM_BINARY_LOAD)
+#define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED
+#endif
+
+// Append HLSL assembly to shader debug info. Defaults to enabled in Debug and off in Release.
+#if !defined(ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO)
+#if !defined(NDEBUG)
+#define ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO ANGLE_ENABLED
+#else
+#define ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO ANGLE_DISABLED
+#endif  // !defined(NDEBUG)
+#endif  // !defined(ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO)
+
+// Program link validation of precisions for uniforms. This feature was
+// requested by developers to allow non-conformant shaders to be used which
+// contain mismatched precisions.
+// ENABLED validate that precision for uniforms match between vertex and fragment shaders
+// DISABLED allow precision for uniforms to differ between vertex and fragment shaders
+#if !defined(ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION)
+#define ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION ANGLE_ENABLED
+#endif
+
+// Controls if our threading code uses std::async or falls back to single-threaded operations.
+// TODO(jmadill): Enable on Linux once STL chrono headers are updated.
+#if !defined(ANGLE_STD_ASYNC_WORKERS)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+#define ANGLE_STD_ASYNC_WORKERS ANGLE_ENABLED
+#else
+#define ANGLE_STD_ASYNC_WORKERS ANGLE_DISABLED
+#endif  // defined(ANGLE_PLATFORM_WINDOWS)
+#endif  // !defined(ANGLE_STD_ASYNC_WORKERS)
+
+#endif // LIBANGLE_FEATURES_H_
diff --git a/src/third_party/angle/src/libANGLE/format_map_autogen.cpp b/src/third_party/angle/src/libANGLE/format_map_autogen.cpp
new file mode 100644
index 0000000..6899706
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/format_map_autogen.cpp
@@ -0,0 +1,1570 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_format_map.py using data from format_map_data.json.
+// ES3 format info from es3_format_type_combinations.json.
+//
+// Copyright 2016 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.
+//
+// format_map:
+//   Determining the sized internal format from a (format,type) pair.
+//   Also check es3 format combinations for validity.
+
+#include "angle_gl.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+GLenum GetSizedFormatInternal(GLenum format, GLenum type)
+{
+    switch (format)
+    {
+        case GL_ALPHA:
+            switch (type)
+            {
+                case GL_FLOAT:
+                    return GL_ALPHA32F_EXT;
+                case GL_HALF_FLOAT:
+                    return GL_ALPHA16F_EXT;
+                case GL_HALF_FLOAT_OES:
+                    return GL_ALPHA16F_EXT;
+                case GL_UNSIGNED_BYTE:
+                    return GL_ALPHA8_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_BGRA_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_BGRA8_EXT;
+                case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+                    return GL_BGR5_A1_ANGLEX;
+                case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+                    return GL_BGRA4_ANGLEX;
+                case GL_UNSIGNED_SHORT_5_6_5:
+                    return GL_BGR565_ANGLEX;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_DEPTH_COMPONENT:
+            switch (type)
+            {
+                case GL_FLOAT:
+                    return GL_DEPTH_COMPONENT32F;
+                case GL_UNSIGNED_INT:
+                    return GL_DEPTH_COMPONENT32_OES;
+                case GL_UNSIGNED_SHORT:
+                    return GL_DEPTH_COMPONENT16;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_DEPTH_STENCIL:
+            switch (type)
+            {
+                case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+                    return GL_DEPTH32F_STENCIL8;
+                case GL_UNSIGNED_INT_24_8:
+                    return GL_DEPTH24_STENCIL8;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_LUMINANCE:
+            switch (type)
+            {
+                case GL_FLOAT:
+                    return GL_LUMINANCE32F_EXT;
+                case GL_HALF_FLOAT:
+                    return GL_LUMINANCE16F_EXT;
+                case GL_HALF_FLOAT_OES:
+                    return GL_LUMINANCE16F_EXT;
+                case GL_UNSIGNED_BYTE:
+                    return GL_LUMINANCE8_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_LUMINANCE_ALPHA:
+            switch (type)
+            {
+                case GL_FLOAT:
+                    return GL_LUMINANCE_ALPHA32F_EXT;
+                case GL_HALF_FLOAT:
+                    return GL_LUMINANCE_ALPHA16F_EXT;
+                case GL_HALF_FLOAT_OES:
+                    return GL_LUMINANCE_ALPHA16F_EXT;
+                case GL_UNSIGNED_BYTE:
+                    return GL_LUMINANCE8_ALPHA8_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RED:
+            switch (type)
+            {
+                case GL_BYTE:
+                    return GL_R8_SNORM;
+                case GL_FLOAT:
+                    return GL_R32F;
+                case GL_HALF_FLOAT:
+                    return GL_R16F;
+                case GL_HALF_FLOAT_OES:
+                    return GL_R16F;
+                case GL_SHORT:
+                    return GL_R16_SNORM_EXT;
+                case GL_UNSIGNED_BYTE:
+                    return GL_R8;
+                case GL_UNSIGNED_SHORT:
+                    return GL_R16_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RED_INTEGER:
+            switch (type)
+            {
+                case GL_BYTE:
+                    return GL_R8I;
+                case GL_INT:
+                    return GL_R32I;
+                case GL_SHORT:
+                    return GL_R16I;
+                case GL_UNSIGNED_BYTE:
+                    return GL_R8UI;
+                case GL_UNSIGNED_INT:
+                    return GL_R32UI;
+                case GL_UNSIGNED_SHORT:
+                    return GL_R16UI;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RG:
+            switch (type)
+            {
+                case GL_BYTE:
+                    return GL_RG8_SNORM;
+                case GL_FLOAT:
+                    return GL_RG32F;
+                case GL_HALF_FLOAT:
+                    return GL_RG16F;
+                case GL_HALF_FLOAT_OES:
+                    return GL_RG16F;
+                case GL_SHORT:
+                    return GL_RG16_SNORM_EXT;
+                case GL_UNSIGNED_BYTE:
+                    return GL_RG8;
+                case GL_UNSIGNED_SHORT:
+                    return GL_RG16_EXT;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGB:
+            switch (type)
+            {
+                case GL_BYTE:
+                    return GL_RGB8_SNORM;
+                case GL_FLOAT:
+                    return GL_RGB32F;
+                case GL_HALF_FLOAT:
+                    return GL_RGB16F;
+                case GL_HALF_FLOAT_OES:
+                    return GL_RGB16F;
+                case GL_SHORT:
+                    return GL_RGB16_SNORM_EXT;
+                case GL_UNSIGNED_BYTE:
+                    return GL_RGB8;
+                case GL_UNSIGNED_INT_10F_11F_11F_REV:
+                    return GL_R11F_G11F_B10F;
+                case GL_UNSIGNED_INT_5_9_9_9_REV:
+                    return GL_RGB9_E5;
+                case GL_UNSIGNED_SHORT:
+                    return GL_RGB16_EXT;
+                case GL_UNSIGNED_SHORT_5_6_5:
+                    return GL_RGB565;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGBA:
+            switch (type)
+            {
+                case GL_BYTE:
+                    return GL_RGBA8_SNORM;
+                case GL_FLOAT:
+                    return GL_RGBA32F;
+                case GL_HALF_FLOAT:
+                    return GL_RGBA16F;
+                case GL_HALF_FLOAT_OES:
+                    return GL_RGBA16F;
+                case GL_SHORT:
+                    return GL_RGBA16_SNORM_EXT;
+                case GL_UNSIGNED_BYTE:
+                    return GL_RGBA8;
+                case GL_UNSIGNED_INT_2_10_10_10_REV:
+                    return GL_RGB10_A2;
+                case GL_UNSIGNED_SHORT:
+                    return GL_RGBA16_EXT;
+                case GL_UNSIGNED_SHORT_4_4_4_4:
+                    return GL_RGBA4;
+                case GL_UNSIGNED_SHORT_5_5_5_1:
+                    return GL_RGB5_A1;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGBA_INTEGER:
+            switch (type)
+            {
+                case GL_BYTE:
+                    return GL_RGBA8I;
+                case GL_INT:
+                    return GL_RGBA32I;
+                case GL_SHORT:
+                    return GL_RGBA16I;
+                case GL_UNSIGNED_BYTE:
+                    return GL_RGBA8UI;
+                case GL_UNSIGNED_INT:
+                    return GL_RGBA32UI;
+                case GL_UNSIGNED_INT_2_10_10_10_REV:
+                    return GL_RGB10_A2UI;
+                case GL_UNSIGNED_SHORT:
+                    return GL_RGBA16UI;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGB_INTEGER:
+            switch (type)
+            {
+                case GL_BYTE:
+                    return GL_RGB8I;
+                case GL_INT:
+                    return GL_RGB32I;
+                case GL_SHORT:
+                    return GL_RGB16I;
+                case GL_UNSIGNED_BYTE:
+                    return GL_RGB8UI;
+                case GL_UNSIGNED_INT:
+                    return GL_RGB32UI;
+                case GL_UNSIGNED_SHORT:
+                    return GL_RGB16UI;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RG_INTEGER:
+            switch (type)
+            {
+                case GL_BYTE:
+                    return GL_RG8I;
+                case GL_INT:
+                    return GL_RG32I;
+                case GL_SHORT:
+                    return GL_RG16I;
+                case GL_UNSIGNED_BYTE:
+                    return GL_RG8UI;
+                case GL_UNSIGNED_INT:
+                    return GL_RG32UI;
+                case GL_UNSIGNED_SHORT:
+                    return GL_RG16UI;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_SRGB_ALPHA_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_SRGB8_ALPHA8;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_SRGB_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_SRGB8;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_STENCIL:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_STENCIL_INDEX8;
+                default:
+                    break;
+            }
+            break;
+
+        case GL_NONE:
+            return GL_NONE;
+
+        default:
+            break;
+    }
+
+    return GL_NONE;
+}
+
+bool ValidES3Format(GLenum format)
+{
+    switch (format)
+    {
+        case GL_ALPHA:
+        case GL_BGRA_EXT:
+        case GL_DEPTH_COMPONENT:
+        case GL_DEPTH_STENCIL:
+        case GL_LUMINANCE:
+        case GL_LUMINANCE_ALPHA:
+        case GL_RED:
+        case GL_RED_INTEGER:
+        case GL_RG:
+        case GL_RGB:
+        case GL_RGBA:
+        case GL_RGBA_INTEGER:
+        case GL_RGB_INTEGER:
+        case GL_RG_INTEGER:
+        case GL_SRGB_ALPHA_EXT:
+        case GL_SRGB_EXT:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool ValidES3Type(GLenum type)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+        case GL_FLOAT:
+        case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+        case GL_HALF_FLOAT:
+        case GL_HALF_FLOAT_OES:
+        case GL_INT:
+        case GL_SHORT:
+        case GL_UNSIGNED_BYTE:
+        case GL_UNSIGNED_INT:
+        case GL_UNSIGNED_INT_10F_11F_11F_REV:
+        case GL_UNSIGNED_INT_24_8:
+        case GL_UNSIGNED_INT_2_10_10_10_REV:
+        case GL_UNSIGNED_INT_5_9_9_9_REV:
+        case GL_UNSIGNED_SHORT:
+        case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+        case GL_UNSIGNED_SHORT_4_4_4_4:
+        case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+        case GL_UNSIGNED_SHORT_5_5_5_1:
+        case GL_UNSIGNED_SHORT_5_6_5:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat)
+{
+    ASSERT(ValidES3Format(format) && ValidES3Type(type));
+
+    switch (format)
+    {
+        case GL_RGB_INTEGER:
+            switch (type)
+            {
+                case GL_INT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB32I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB16UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB16I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB8UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB8I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_INT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB32UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGBA_INTEGER:
+            switch (type)
+            {
+                case GL_INT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA32I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA16UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_INT_2_10_10_10_REV:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB10_A2UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA16I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA8UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA8I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_INT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA32UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGB:
+            switch (type)
+            {
+                case GL_UNSIGNED_INT_10F_11F_11F_REV:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R11F_G11F_B10F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB16_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB16_SNORM_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB:
+                        case GL_RGB8:
+                        case GL_RGB565:
+                        case GL_SRGB8:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT_5_6_5:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB:
+                        case GL_RGB565:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB:
+                        case GL_RGB16F:
+                        case GL_R11F_G11F_B10F:
+                        case GL_RGB9_E5:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB16F:
+                        case GL_R11F_G11F_B10F:
+                        case GL_RGB9_E5:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB:
+                        case GL_RGB32F:
+                        case GL_RGB16F:
+                        case GL_R11F_G11F_B10F:
+                        case GL_RGB9_E5:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB8_SNORM:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_INT_5_9_9_9_REV:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB9_E5:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_LUMINANCE_ALPHA:
+            switch (type)
+            {
+                case GL_HALF_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_LUMINANCE_ALPHA:
+                        case GL_LUMINANCE_ALPHA16F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_LUMINANCE_ALPHA:
+                        case GL_LUMINANCE_ALPHA32F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_LUMINANCE_ALPHA:
+                        case GL_LUMINANCE8_ALPHA8_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_LUMINANCE_ALPHA:
+                        case GL_LUMINANCE_ALPHA16F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_ALPHA:
+            switch (type)
+            {
+                case GL_HALF_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_ALPHA:
+                        case GL_ALPHA16F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_ALPHA:
+                        case GL_ALPHA32F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_ALPHA:
+                        case GL_ALPHA8_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_ALPHA:
+                        case GL_ALPHA16F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RGBA:
+            switch (type)
+            {
+                case GL_UNSIGNED_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA16_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_INT_2_10_10_10_REV:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGB10_A2:
+                        case GL_RGB5_A1:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA16_SNORM_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT_4_4_4_4:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA:
+                        case GL_RGBA4:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA:
+                        case GL_RGBA8:
+                        case GL_RGB5_A1:
+                        case GL_RGBA4:
+                        case GL_SRGB8_ALPHA8:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA:
+                        case GL_RGBA16F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA16F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA:
+                        case GL_RGBA32F:
+                        case GL_RGBA16F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA8_SNORM:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT_5_5_5_1:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RGBA:
+                        case GL_RGB5_A1:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_LUMINANCE:
+            switch (type)
+            {
+                case GL_HALF_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_LUMINANCE:
+                        case GL_LUMINANCE16F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_LUMINANCE:
+                        case GL_LUMINANCE32F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_LUMINANCE:
+                        case GL_LUMINANCE8_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_LUMINANCE:
+                        case GL_LUMINANCE16F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RG_INTEGER:
+            switch (type)
+            {
+                case GL_INT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG32I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG16UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG16I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG8UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG8I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_INT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG32UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RED_INTEGER:
+            switch (type)
+            {
+                case GL_INT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R32I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R16UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R16I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R8UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R8I:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_INT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R32UI:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RED:
+            switch (type)
+            {
+                case GL_UNSIGNED_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R16_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R16_SNORM_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RED:
+                        case GL_R32F:
+                        case GL_R16F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RED:
+                        case GL_R16F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RED:
+                        case GL_R16F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RED:
+                        case GL_R8:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_R8_SNORM:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_DEPTH_COMPONENT:
+            switch (type)
+            {
+                case GL_UNSIGNED_INT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_DEPTH_COMPONENT:
+                        case GL_DEPTH_COMPONENT24:
+                        case GL_DEPTH_COMPONENT16:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_INT_24_8:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_DEPTH_COMPONENT32_OES:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_DEPTH_COMPONENT32F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_DEPTH_COMPONENT:
+                        case GL_DEPTH_COMPONENT16:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_DEPTH_STENCIL:
+            switch (type)
+            {
+                case GL_UNSIGNED_INT_24_8:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_DEPTH_STENCIL:
+                        case GL_DEPTH24_STENCIL8:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_DEPTH32F_STENCIL8:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_SRGB_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_SRGB_EXT:
+                        case GL_SRGB8:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_SRGB_ALPHA_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_SRGB_ALPHA_EXT:
+                        case GL_SRGB8_ALPHA8_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_RG:
+            switch (type)
+            {
+                case GL_UNSIGNED_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG16_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_SHORT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG16_SNORM_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG:
+                        case GL_RG32F:
+                        case GL_RG16F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG:
+                        case GL_RG16F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG:
+                        case GL_RG16F:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG:
+                        case GL_RG8:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_RG8_SNORM:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        case GL_BGRA_EXT:
+            switch (type)
+            {
+                case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_BGRA4_ANGLEX:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_BYTE:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_BGRA8_EXT:
+                        case GL_BGRA4_ANGLEX:
+                        case GL_BGR5_A1_ANGLEX:
+                        case GL_BGRA_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+                {
+                    switch (internalFormat)
+                    {
+                        case GL_BGR5_A1_ANGLEX:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    return false;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/format_map_data.json b/src/third_party/angle/src/libANGLE/format_map_data.json
new file mode 100644
index 0000000..a4f1c98
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/format_map_data.json
@@ -0,0 +1,142 @@
+{
+    "GL_RGBA": {
+        "GL_UNSIGNED_BYTE": "GL_RGBA8",
+        "GL_UNSIGNED_SHORT": "GL_RGBA16_EXT",
+        "GL_BYTE": "GL_RGBA8_SNORM",
+        "GL_SHORT": "GL_RGBA16_SNORM_EXT",
+        "GL_UNSIGNED_SHORT_4_4_4_4": "GL_RGBA4",
+        "GL_UNSIGNED_SHORT_5_5_5_1": "GL_RGB5_A1",
+        "GL_UNSIGNED_INT_2_10_10_10_REV": "GL_RGB10_A2",
+        "GL_FLOAT": "GL_RGBA32F",
+        "GL_HALF_FLOAT": "GL_RGBA16F",
+        "GL_HALF_FLOAT_OES": "GL_RGBA16F"
+    },
+    "GL_RGBA_INTEGER": {
+        "GL_UNSIGNED_BYTE": "GL_RGBA8UI",
+        "GL_BYTE": "GL_RGBA8I",
+        "GL_UNSIGNED_SHORT": "GL_RGBA16UI",
+        "GL_SHORT": "GL_RGBA16I",
+        "GL_UNSIGNED_INT": "GL_RGBA32UI",
+        "GL_INT": "GL_RGBA32I",
+        "GL_UNSIGNED_INT_2_10_10_10_REV": "GL_RGB10_A2UI"
+    },
+    "GL_RGB": {
+        "GL_UNSIGNED_BYTE": "GL_RGB8",
+        "GL_UNSIGNED_SHORT": "GL_RGB16_EXT",
+        "GL_BYTE": "GL_RGB8_SNORM",
+        "GL_SHORT": "GL_RGB16_SNORM_EXT",
+        "GL_UNSIGNED_SHORT_5_6_5": "GL_RGB565",
+        "GL_UNSIGNED_INT_10F_11F_11F_REV": "GL_R11F_G11F_B10F",
+        "GL_UNSIGNED_INT_5_9_9_9_REV": "GL_RGB9_E5",
+        "GL_FLOAT": "GL_RGB32F",
+        "GL_HALF_FLOAT": "GL_RGB16F",
+        "GL_HALF_FLOAT_OES": "GL_RGB16F"
+    },
+    "GL_RGB_INTEGER": {
+        "GL_UNSIGNED_BYTE": "GL_RGB8UI",
+        "GL_BYTE": "GL_RGB8I", "GL_UNSIGNED_SHORT": "GL_RGB16UI",
+        "GL_SHORT": "GL_RGB16I",
+        "GL_UNSIGNED_INT": "GL_RGB32UI",
+        "GL_INT": "GL_RGB32I"
+    },
+    "GL_RG": {
+        "GL_UNSIGNED_BYTE": "GL_RG8",
+        "GL_UNSIGNED_SHORT": "GL_RG16_EXT",
+        "GL_BYTE": "GL_RG8_SNORM",
+        "GL_SHORT": "GL_RG16_SNORM_EXT",
+        "GL_FLOAT": "GL_RG32F",
+        "GL_HALF_FLOAT": "GL_RG16F",
+        "GL_HALF_FLOAT_OES": "GL_RG16F"
+    },
+    "GL_RG_INTEGER": {
+        "GL_UNSIGNED_BYTE": "GL_RG8UI",
+        "GL_BYTE": "GL_RG8I",
+        "GL_UNSIGNED_SHORT": "GL_RG16UI",
+        "GL_SHORT": "GL_RG16I",
+        "GL_UNSIGNED_INT": "GL_RG32UI",
+        "GL_INT": "GL_RG32I"
+    },
+    "GL_RED": {
+        "GL_UNSIGNED_BYTE": "GL_R8",
+        "GL_UNSIGNED_SHORT": "GL_R16_EXT",
+        "GL_BYTE": "GL_R8_SNORM",
+        "GL_SHORT": "GL_R16_SNORM_EXT",
+        "GL_FLOAT": "GL_R32F",
+        "GL_HALF_FLOAT": "GL_R16F",
+        "GL_HALF_FLOAT_OES": "GL_R16F"
+    },
+    "GL_RED_INTEGER": {
+        "GL_UNSIGNED_BYTE": "GL_R8UI",
+        "GL_BYTE": "GL_R8I",
+        "GL_UNSIGNED_SHORT": "GL_R16UI",
+        "GL_SHORT": "GL_R16I",
+        "GL_UNSIGNED_INT": "GL_R32UI",
+        "GL_INT": "GL_R32I"
+    },
+    "GL_LUMINANCE_ALPHA": {
+        "GL_UNSIGNED_BYTE": "GL_LUMINANCE8_ALPHA8_EXT",
+        "GL_FLOAT": "GL_LUMINANCE_ALPHA32F_EXT",
+        "GL_HALF_FLOAT": "GL_LUMINANCE_ALPHA16F_EXT",
+        "GL_HALF_FLOAT_OES": "GL_LUMINANCE_ALPHA16F_EXT"
+    },
+    "GL_LUMINANCE": {
+        "GL_UNSIGNED_BYTE": "GL_LUMINANCE8_EXT",
+        "GL_FLOAT": "GL_LUMINANCE32F_EXT",
+        "GL_HALF_FLOAT": "GL_LUMINANCE16F_EXT",
+        "GL_HALF_FLOAT_OES": "GL_LUMINANCE16F_EXT"
+    },
+    "GL_ALPHA": {
+        "GL_UNSIGNED_BYTE": "GL_ALPHA8_EXT",
+        "GL_FLOAT": "GL_ALPHA32F_EXT",
+        "GL_HALF_FLOAT": "GL_ALPHA16F_EXT",
+        "GL_HALF_FLOAT_OES": "GL_ALPHA16F_EXT"
+    },
+    "GL_BGRA_EXT": {
+        "GL_UNSIGNED_BYTE": "GL_BGRA8_EXT",
+        "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": "GL_BGRA4_ANGLEX",
+        "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": "GL_BGR5_A1_ANGLEX",
+        "GL_UNSIGNED_SHORT_5_6_5": "GL_BGR565_ANGLEX"
+    },
+    "GL_SRGB_EXT": {
+        "GL_UNSIGNED_BYTE": "GL_SRGB8"
+    },
+    "GL_SRGB_ALPHA_EXT": {
+        "GL_UNSIGNED_BYTE": "GL_SRGB8_ALPHA8"
+    },
+    "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": {
+        "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"
+    },
+    "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": {
+        "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"
+    },
+    "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": {
+        "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE"
+    },
+    "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": {
+        "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE"
+    },
+    "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT": {
+        "GL_UNSIGNED_BYTE": "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT"
+    },
+    "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT": {
+        "GL_UNSIGNED_BYTE": "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT"
+    },
+    "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT": {
+        "GL_UNSIGNED_BYTE": "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT"
+    },
+    "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT": {
+        "GL_UNSIGNED_BYTE": "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT"
+    },
+    "GL_DEPTH_COMPONENT": {
+        "GL_UNSIGNED_SHORT": "GL_DEPTH_COMPONENT16",
+        "GL_UNSIGNED_INT": "GL_DEPTH_COMPONENT32_OES",
+        "GL_FLOAT": "GL_DEPTH_COMPONENT32F"
+    },
+    "GL_STENCIL": {
+        "GL_UNSIGNED_BYTE": "GL_STENCIL_INDEX8"
+    },
+    "GL_DEPTH_STENCIL": {
+        "GL_UNSIGNED_INT_24_8": "GL_DEPTH24_STENCIL8",
+        "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": "GL_DEPTH32F_STENCIL8"
+    }
+}
diff --git a/src/third_party/angle/src/libANGLE/formatutils.cpp b/src/third_party/angle/src/libANGLE/formatutils.cpp
new file mode 100644
index 0000000..f622bf0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/formatutils.cpp
@@ -0,0 +1,1995 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// formatutils.cpp: Queries for GL image formats.
+
+#include "libANGLE/formatutils.h"
+
+#include "common/mathutil.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the implementation
+// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid
+// format and type combinations.
+GLenum GetSizedFormatInternal(GLenum format, GLenum type);
+
+namespace
+{
+using InternalFormatInfoMap =
+    std::unordered_map<GLenum, std::unordered_map<GLenum, InternalFormat>>;
+
+}  // anonymous namespace
+
+FormatType::FormatType() : format(GL_NONE), type(GL_NONE)
+{
+}
+
+FormatType::FormatType(GLenum format_, GLenum type_) : format(format_), type(type_)
+{
+}
+
+bool FormatType::operator<(const FormatType &other) const
+{
+    if (format != other.format)
+        return format < other.format;
+    return type < other.type;
+}
+
+Type::Type()
+    : bytes(0),
+      bytesShift(0),
+      specialInterpretation(false)
+{
+}
+
+static Type GenTypeInfo(GLuint bytes, bool specialInterpretation)
+{
+    Type info;
+    info.bytes = bytes;
+    GLuint i = 0;
+    while ((1u << i) < bytes)
+    {
+        ++i;
+    }
+    info.bytesShift = i;
+    ASSERT((1u << info.bytesShift) == bytes);
+    info.specialInterpretation = specialInterpretation;
+    return info;
+}
+
+bool operator<(const Type& a, const Type& b)
+{
+    return memcmp(&a, &b, sizeof(Type)) < 0;
+}
+
+// Information about internal formats
+static bool AlwaysSupported(const Version &, const Extensions &)
+{
+    return true;
+}
+
+static bool NeverSupported(const Version &, const Extensions &)
+{
+    return false;
+}
+
+template <GLuint minCoreGLMajorVersion, GLuint minCoreGLMinorVersion>
+static bool RequireES(const Version &clientVersion, const Extensions &)
+{
+    return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion);
+}
+
+// Pointer to a boolean memeber of the Extensions struct
+typedef bool(Extensions::*ExtensionBool);
+
+// Check support for a single extension
+template <ExtensionBool bool1>
+static bool RequireExt(const Version &, const Extensions &extensions)
+{
+    return extensions.*bool1;
+}
+
+// Check for a minimum client version or a single extension
+template <GLuint minCoreGLMajorVersion, GLuint minCoreGLMinorVersion, ExtensionBool bool1>
+static bool RequireESOrExt(const Version &clientVersion, const Extensions &extensions)
+{
+    return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) ||
+           extensions.*bool1;
+}
+
+// Check for a minimum client version or two extensions
+template <GLuint minCoreGLMajorVersion,
+          GLuint minCoreGLMinorVersion,
+          ExtensionBool bool1,
+          ExtensionBool bool2>
+static bool RequireESOrExtAndExt(const Version &clientVersion, const Extensions &extensions)
+{
+    return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) ||
+           (extensions.*bool1 && extensions.*bool2);
+}
+
+// Check for a minimum client version or at least one of two extensions
+template <GLuint minCoreGLMajorVersion,
+          GLuint minCoreGLMinorVersion,
+          ExtensionBool bool1,
+          ExtensionBool bool2>
+static bool RequireESOrExtOrExt(const Version &clientVersion, const Extensions &extensions)
+{
+    return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) ||
+           extensions.*bool1 || extensions.*bool2;
+}
+
+// Check support for two extensions
+template <ExtensionBool bool1, ExtensionBool bool2>
+static bool RequireExtAndExt(const Version &, const Extensions &extensions)
+{
+    return extensions.*bool1 && extensions.*bool2;
+}
+
+// Check support for either of two extensions
+template <ExtensionBool bool1, ExtensionBool bool2>
+static bool RequireExtOrExt(const Version &, const Extensions &extensions)
+{
+    return extensions.*bool1 || extensions.*bool2;
+}
+
+// Special function for half float formats with three or four channels.
+static bool HalfFloatSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return clientVersion >= Version(3, 0) || extensions.textureHalfFloat;
+}
+
+static bool HalfFloatRGBRenderableSupport(const Version &clientVersion,
+                                          const Extensions &extensions)
+{
+    return HalfFloatSupport(clientVersion, extensions) && extensions.colorBufferHalfFloat;
+}
+
+static bool HalfFloatRGBARenderableSupport(const Version &clientVersion,
+                                           const Extensions &extensions)
+{
+    return HalfFloatSupport(clientVersion, extensions) &&
+           (extensions.colorBufferHalfFloat || extensions.colorBufferFloat);
+}
+
+// Special function for half float formats with one or two channels.
+
+// R16F, RG16F
+static bool HalfFloatRGSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return clientVersion >= Version(3, 0) || (extensions.textureHalfFloat && extensions.textureRG);
+}
+
+// R16F, RG16F
+static bool HalfFloatRGRenderableSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    // It's unclear if EXT_color_buffer_half_float gives renderability to non-OES half float
+    // textures
+    return HalfFloatRGSupport(clientVersion, extensions) &&
+           (extensions.colorBufferHalfFloat || extensions.colorBufferFloat);
+}
+
+// RED + HALF_FLOAT_OES, RG + HALF_FLOAT_OES
+static bool UnsizedHalfFloatOESRGSupport(const Version &, const Extensions &extensions)
+{
+    return extensions.textureHalfFloat && extensions.textureRG;
+}
+
+// RED + HALF_FLOAT_OES, RG + HALF_FLOAT_OES
+static bool UnsizedHalfFloatOESRGRenderableSupport(const Version &clientVersion,
+                                                   const Extensions &extensions)
+{
+    return UnsizedHalfFloatOESRGSupport(clientVersion, extensions) &&
+           extensions.colorBufferHalfFloat;
+}
+
+// RGB + HALF_FLOAT_OES, RGBA + HALF_FLOAT_OES
+static bool UnsizedHalfFloatOESSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return extensions.textureHalfFloat;
+}
+
+// RGB + HALF_FLOAT_OES, RGBA + HALF_FLOAT_OES
+static bool UnsizedHalfFloatOESRenderableSupport(const Version &clientVersion,
+                                                 const Extensions &extensions)
+{
+    return UnsizedHalfFloatOESSupport(clientVersion, extensions) && extensions.colorBufferHalfFloat;
+}
+
+// Special function for float formats with three or four channels.
+
+// RGB32F, RGBA32F
+static bool FloatSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return clientVersion >= Version(3, 0) || extensions.textureFloat;
+}
+
+// RGB32F
+static bool FloatRGBRenderableSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return FloatSupport(clientVersion, extensions) && extensions.colorBufferFloatRGB;
+}
+
+// RGBA32F
+static bool FloatRGBARenderableSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return FloatSupport(clientVersion, extensions) &&
+           (extensions.colorBufferFloat || extensions.colorBufferFloatRGBA);
+}
+
+// RGB + FLOAT, RGBA + FLOAT
+static bool UnsizedFloatSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return extensions.textureFloat;
+}
+
+// RGB + FLOAT
+static bool UnsizedFloatRGBRenderableSupport(const Version &clientVersion,
+                                             const Extensions &extensions)
+{
+    return UnsizedFloatSupport(clientVersion, extensions) && extensions.colorBufferFloatRGB;
+}
+
+// RGBA + FLOAT
+static bool UnsizedFloatRGBARenderableSupport(const Version &clientVersion,
+                                              const Extensions &extensions)
+{
+    return UnsizedFloatSupport(clientVersion, extensions) &&
+           (extensions.colorBufferFloatRGBA || extensions.colorBufferFloat);
+}
+
+// Special function for float formats with one or two channels.
+
+// R32F, RG32F
+static bool FloatRGSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return clientVersion >= Version(3, 0) || (extensions.textureFloat && extensions.textureRG);
+}
+
+// R32F, RG32F
+static bool FloatRGRenderableSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return FloatRGSupport(clientVersion, extensions) && extensions.colorBufferFloat;
+}
+
+// RED + FLOAT, RG + FLOAT
+static bool UnsizedFloatRGSupport(const Version &clientVersion, const Extensions &extensions)
+{
+    return extensions.textureFloat && extensions.textureRG;
+}
+
+// RED + FLOAT, RG + FLOAT
+static bool UnsizedFloatRGRenderableSupport(const Version &clientVersion,
+                                            const Extensions &extensions)
+{
+    return FloatRGSupport(clientVersion, extensions) && extensions.colorBufferFloat;
+}
+
+InternalFormat::InternalFormat()
+    : internalFormat(GL_NONE),
+      sized(false),
+      sizedInternalFormat(GL_NONE),
+      redBits(0),
+      greenBits(0),
+      blueBits(0),
+      luminanceBits(0),
+      alphaBits(0),
+      sharedBits(0),
+      depthBits(0),
+      stencilBits(0),
+      pixelBytes(0),
+      componentCount(0),
+      compressed(false),
+      compressedBlockWidth(0),
+      compressedBlockHeight(0),
+      format(GL_NONE),
+      type(GL_NONE),
+      componentType(GL_NONE),
+      colorEncoding(GL_NONE),
+      textureSupport(NeverSupported),
+      renderSupport(NeverSupported),
+      filterSupport(NeverSupported)
+{
+}
+
+bool InternalFormat::isLUMA() const
+{
+    return ((redBits + greenBits + blueBits + depthBits + stencilBits) == 0 &&
+            (luminanceBits + alphaBits) > 0);
+}
+
+GLenum InternalFormat::getReadPixelsFormat() const
+{
+    return format;
+}
+
+GLenum InternalFormat::getReadPixelsType() const
+{
+    switch (type)
+    {
+        case GL_HALF_FLOAT:
+            // The internal format may have a type of GL_HALF_FLOAT but when exposing this type as
+            // the IMPLEMENTATION_READ_TYPE, only HALF_FLOAT_OES is allowed by
+            // OES_texture_half_float
+            return GL_HALF_FLOAT_OES;
+
+        default:
+            return type;
+    }
+}
+
+Format::Format(GLenum internalFormat) : Format(GetSizedInternalFormatInfo(internalFormat))
+{
+}
+
+Format::Format(const InternalFormat &internalFormat) : info(&internalFormat)
+{
+}
+
+Format::Format(GLenum internalFormat, GLenum type)
+    : info(&GetInternalFormatInfo(internalFormat, type))
+{
+}
+
+Format::Format(const Format &other) = default;
+Format &Format::operator=(const Format &other) = default;
+
+bool Format::valid() const
+{
+    return info->internalFormat != GL_NONE;
+}
+
+// static
+bool Format::SameSized(const Format &a, const Format &b)
+{
+    return a.info->sizedInternalFormat == b.info->sizedInternalFormat;
+}
+
+// static
+Format Format::Invalid()
+{
+    static Format invalid(GL_NONE, GL_NONE);
+    return invalid;
+}
+
+std::ostream &operator<<(std::ostream &os, const Format &fmt)
+{
+    // TODO(ynovikov): return string representation when available
+    return FmtHexShort(os, fmt.info->sizedInternalFormat);
+}
+
+bool InternalFormat::operator==(const InternalFormat &other) const
+{
+    // We assume all internal formats are unique if they have the same internal format and type
+    return internalFormat == other.internalFormat && type == other.type;
+}
+
+bool InternalFormat::operator!=(const InternalFormat &other) const
+{
+    return !(*this == other);
+}
+
+void InsertFormatInfo(InternalFormatInfoMap *map, const InternalFormat &formatInfo)
+{
+    ASSERT(!formatInfo.sized || (*map).count(formatInfo.internalFormat) == 0);
+    ASSERT((*map)[formatInfo.internalFormat].count(formatInfo.type) == 0);
+    (*map)[formatInfo.internalFormat][formatInfo.type] = formatInfo;
+}
+
+void AddRGBAFormat(InternalFormatInfoMap *map,
+                   GLenum internalFormat,
+                   bool sized,
+                   GLuint red,
+                   GLuint green,
+                   GLuint blue,
+                   GLuint alpha,
+                   GLuint shared,
+                   GLenum format,
+                   GLenum type,
+                   GLenum componentType,
+                   bool srgb,
+                   InternalFormat::SupportCheckFunction textureSupport,
+                   InternalFormat::SupportCheckFunction renderSupport,
+                   InternalFormat::SupportCheckFunction filterSupport)
+{
+    InternalFormat formatInfo;
+    formatInfo.internalFormat = internalFormat;
+    formatInfo.sized          = sized;
+    formatInfo.sizedInternalFormat =
+        sized ? internalFormat : GetSizedFormatInternal(internalFormat, type);
+    formatInfo.redBits = red;
+    formatInfo.greenBits = green;
+    formatInfo.blueBits = blue;
+    formatInfo.alphaBits = alpha;
+    formatInfo.sharedBits = shared;
+    formatInfo.pixelBytes = (red + green + blue + alpha + shared) / 8;
+    formatInfo.componentCount =
+        ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0);
+    formatInfo.format = format;
+    formatInfo.type = type;
+    formatInfo.componentType = componentType;
+    formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR);
+    formatInfo.textureSupport = textureSupport;
+    formatInfo.renderSupport = renderSupport;
+    formatInfo.filterSupport = filterSupport;
+
+    InsertFormatInfo(map, formatInfo);
+}
+
+static void AddLUMAFormat(InternalFormatInfoMap *map,
+                          GLenum internalFormat,
+                          bool sized,
+                          GLuint luminance,
+                          GLuint alpha,
+                          GLenum format,
+                          GLenum type,
+                          GLenum componentType,
+                          InternalFormat::SupportCheckFunction textureSupport,
+                          InternalFormat::SupportCheckFunction renderSupport,
+                          InternalFormat::SupportCheckFunction filterSupport)
+{
+    InternalFormat formatInfo;
+    formatInfo.internalFormat = internalFormat;
+    formatInfo.sized          = sized;
+    formatInfo.sizedInternalFormat =
+        sized ? internalFormat : GetSizedFormatInternal(internalFormat, type);
+    formatInfo.luminanceBits = luminance;
+    formatInfo.alphaBits = alpha;
+    formatInfo.pixelBytes = (luminance + alpha) / 8;
+    formatInfo.componentCount = ((luminance > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0);
+    formatInfo.format = format;
+    formatInfo.type = type;
+    formatInfo.componentType = componentType;
+    formatInfo.colorEncoding = GL_LINEAR;
+    formatInfo.textureSupport = textureSupport;
+    formatInfo.renderSupport = renderSupport;
+    formatInfo.filterSupport = filterSupport;
+
+    InsertFormatInfo(map, formatInfo);
+}
+
+void AddDepthStencilFormat(InternalFormatInfoMap *map,
+                           GLenum internalFormat,
+                           bool sized,
+                           GLuint depthBits,
+                           GLuint stencilBits,
+                           GLuint unusedBits,
+                           GLenum format,
+                           GLenum type,
+                           GLenum componentType,
+                           InternalFormat::SupportCheckFunction textureSupport,
+                           InternalFormat::SupportCheckFunction renderSupport,
+                           InternalFormat::SupportCheckFunction filterSupport)
+{
+    InternalFormat formatInfo;
+    formatInfo.internalFormat = internalFormat;
+    formatInfo.sized          = sized;
+    formatInfo.sizedInternalFormat =
+        sized ? internalFormat : GetSizedFormatInternal(internalFormat, type);
+    formatInfo.depthBits = depthBits;
+    formatInfo.stencilBits = stencilBits;
+    formatInfo.pixelBytes = (depthBits + stencilBits + unusedBits) / 8;
+    formatInfo.componentCount = ((depthBits > 0) ? 1 : 0) + ((stencilBits > 0) ? 1 : 0);
+    formatInfo.format = format;
+    formatInfo.type = type;
+    formatInfo.componentType = componentType;
+    formatInfo.colorEncoding = GL_LINEAR;
+    formatInfo.textureSupport = textureSupport;
+    formatInfo.renderSupport = renderSupport;
+    formatInfo.filterSupport = filterSupport;
+
+    InsertFormatInfo(map, formatInfo);
+}
+
+void AddCompressedFormat(InternalFormatInfoMap *map,
+                         GLenum internalFormat,
+                         GLuint compressedBlockWidth,
+                         GLuint compressedBlockHeight,
+                         GLuint compressedBlockSize,
+                         GLuint componentCount,
+                         GLenum format,
+                         GLenum type,
+                         bool srgb,
+                         InternalFormat::SupportCheckFunction textureSupport,
+                         InternalFormat::SupportCheckFunction renderSupport,
+                         InternalFormat::SupportCheckFunction filterSupport)
+{
+    InternalFormat formatInfo;
+    formatInfo.internalFormat        = internalFormat;
+    formatInfo.sized                 = true;
+    formatInfo.sizedInternalFormat   = internalFormat;
+    formatInfo.compressedBlockWidth = compressedBlockWidth;
+    formatInfo.compressedBlockHeight = compressedBlockHeight;
+    formatInfo.pixelBytes = compressedBlockSize / 8;
+    formatInfo.componentCount = componentCount;
+    formatInfo.format = format;
+    formatInfo.type = type;
+    formatInfo.componentType = GL_UNSIGNED_NORMALIZED;
+    formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR);
+    formatInfo.compressed = true;
+    formatInfo.textureSupport = textureSupport;
+    formatInfo.renderSupport = renderSupport;
+    formatInfo.filterSupport = filterSupport;
+
+    InsertFormatInfo(map, formatInfo);
+}
+
+static InternalFormatInfoMap BuildInternalFormatInfoMap()
+{
+    InternalFormatInfoMap map;
+
+    // From ES 3.0.1 spec, table 3.12
+    map[GL_NONE][GL_NONE] = InternalFormat();
+
+    // clang-format off
+
+    //                 | Internal format    |sized| R | G | B | A |S | Format         | Type                           | Component type        | SRGB | Texture supported                           | Renderable                                  | Filterable    |
+    AddRGBAFormat(&map, GL_R8,               true,  8,  0,  0,  0, 0, GL_RED,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureRG>, RequireESOrExt<3, 0, &Extensions::textureRG>, AlwaysSupported);
+    AddRGBAFormat(&map, GL_R8_SNORM,         true,  8,  0,  0,  0, 0, GL_RED,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireES<3, 0>,                              NeverSupported,                               AlwaysSupported);
+    AddRGBAFormat(&map, GL_RG8,              true,  8,  8,  0,  0, 0, GL_RG,           GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureRG>, RequireESOrExt<3, 0, &Extensions::textureRG>, AlwaysSupported);
+    AddRGBAFormat(&map, GL_RG8_SNORM,        true,  8,  8,  0,  0, 0, GL_RG,           GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireES<3, 0>,                              NeverSupported,                               AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB8,             true,  8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB8_SNORM,       true,  8,  8,  8,  0, 0, GL_RGB,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireES<3, 0>,                              NeverSupported,                               AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB565,           true,  5,  6,  5,  0, 0, GL_RGB,          GL_UNSIGNED_SHORT_5_6_5,         GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>,                              RequireES<2, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA4,            true,  4,  4,  4,  4, 0, GL_RGBA,         GL_UNSIGNED_SHORT_4_4_4_4,       GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>,                              RequireES<2, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB5_A1,          true,  5,  5,  5,  1, 0, GL_RGBA,         GL_UNSIGNED_SHORT_5_5_5_1,       GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>,                              RequireES<2, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA8,            true,  8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA8_SNORM,      true,  8,  8,  8,  8, 0, GL_RGBA,         GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireES<3, 0>,                              NeverSupported,                               AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB10_A2,         true, 10, 10, 10,  2, 0, GL_RGBA,         GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_NORMALIZED, false, RequireES<3, 0>,                              RequireES<3, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB10_A2UI,       true, 10, 10, 10,  2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_SRGB8,            true,  8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireESOrExt<3, 0, &Extensions::sRGB>,      NeverSupported,                               AlwaysSupported);
+    AddRGBAFormat(&map, GL_SRGB8_ALPHA8,     true,  8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireESOrExt<3, 0, &Extensions::sRGB>,      RequireESOrExt<3, 0, &Extensions::sRGB>,      AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB9_E5,          true,  9,  9,  9,  0, 5, GL_RGB,          GL_UNSIGNED_INT_5_9_9_9_REV,     GL_FLOAT,               false, RequireES<3, 0>,                              NeverSupported,                               AlwaysSupported);
+    AddRGBAFormat(&map, GL_R8I,              true,  8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_BYTE,                         GL_INT,                 false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_R8UI,             true,  8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_R16I,             true, 16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_SHORT,                        GL_INT,                 false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_R16UI,            true, 16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_R32I,             true, 32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_INT,                          GL_INT,                 false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_R32UI,            true, 32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RG8I,             true,  8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_BYTE,                         GL_INT,                 false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RG8UI,            true,  8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RG16I,            true, 16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_SHORT,                        GL_INT,                 false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RG16UI,           true, 16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RG32I,            true, 32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_INT,                          GL_INT,                 false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_R11F_G11F_B10F,   true, 11, 11, 10,  0, 0, GL_RGB,          GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT,               false, RequireES<3, 0>,                              RequireExt<&Extensions::colorBufferFloat>,    AlwaysSupported);
+    AddRGBAFormat(&map, GL_RG32UI,           true, 32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RGB8I,            true,  8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_BYTE,                         GL_INT,                 false, RequireES<3, 0>,                              NeverSupported,                               NeverSupported);
+    AddRGBAFormat(&map, GL_RGB8UI,           true,  8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              NeverSupported,                               NeverSupported);
+    AddRGBAFormat(&map, GL_RGB16I,           true, 16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_SHORT,                        GL_INT,                 false, RequireES<3, 0>,                              NeverSupported,                               NeverSupported);
+    AddRGBAFormat(&map, GL_RGB16UI,          true, 16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              NeverSupported,                               NeverSupported);
+    AddRGBAFormat(&map, GL_RGB32I,           true, 32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_INT,                          GL_INT,                 false, RequireES<3, 0>,                              NeverSupported,                               NeverSupported);
+    AddRGBAFormat(&map, GL_RGB32UI,          true, 32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              NeverSupported,                               NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA8I,           true,  8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_BYTE,                         GL_INT,                 false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA8UI,          true,  8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA16I,          true, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT,                        GL_INT,                 false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA16UI,         true, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA32I,          true, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT,                          GL_INT,                 false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA32UI,         true, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireES<3, 0>,                              RequireES<3, 0>,                              NeverSupported);
+
+    AddRGBAFormat(&map, GL_BGRA8_EXT,        true,  8,  8,  8,  8, 0, GL_BGRA_EXT,     GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+    AddRGBAFormat(&map, GL_BGRA4_ANGLEX,     true,  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);
+    AddRGBAFormat(&map, GL_BGR5_A1_ANGLEX,   true,  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);
+
+    // Special format which is not really supported, so always false for all supports.
+    AddRGBAFormat(&map, GL_BGR565_ANGLEX,    true,  5,  6,  5,  1, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_5_6_5,           GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported);
+
+    // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float
+    //                 | Internal format    |sized| D |S | Format             | Type                                   | Comp   | SRGB |  Texture supported | Renderable                    | Filterable                                    |
+    //                 |                    |     |   |  |                    |                                        | type   |      |                    |                               |                                               |
+    AddRGBAFormat(&map, GL_R16F,             true, 16,  0,  0,  0, 0, GL_RED,          GL_HALF_FLOAT,                   GL_FLOAT, false, HalfFloatRGSupport, HalfFloatRGRenderableSupport,   RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddRGBAFormat(&map, GL_RG16F,            true, 16, 16,  0,  0, 0, GL_RG,           GL_HALF_FLOAT,                   GL_FLOAT, false, HalfFloatRGSupport, HalfFloatRGRenderableSupport,   RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddRGBAFormat(&map, GL_RGB16F,           true, 16, 16, 16,  0, 0, GL_RGB,          GL_HALF_FLOAT,                   GL_FLOAT, false, HalfFloatSupport,   HalfFloatRGBRenderableSupport,  RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddRGBAFormat(&map, GL_RGBA16F,          true, 16, 16, 16, 16, 0, GL_RGBA,         GL_HALF_FLOAT,                   GL_FLOAT, false, HalfFloatSupport,   HalfFloatRGBARenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddRGBAFormat(&map, GL_R32F,             true, 32,  0,  0,  0, 0, GL_RED,          GL_FLOAT,                        GL_FLOAT, false, FloatRGSupport,     FloatRGRenderableSupport,       RequireExt<&Extensions::textureFloatLinear>              );
+    AddRGBAFormat(&map, GL_RG32F,            true, 32, 32,  0,  0, 0, GL_RG,           GL_FLOAT,                        GL_FLOAT, false, FloatRGSupport,     FloatRGRenderableSupport,       RequireExt<&Extensions::textureFloatLinear>              );
+    AddRGBAFormat(&map, GL_RGB32F,           true, 32, 32, 32,  0, 0, GL_RGB,          GL_FLOAT,                        GL_FLOAT, false, FloatSupport,       FloatRGBRenderableSupport,      RequireExt<&Extensions::textureFloatLinear>              );
+    AddRGBAFormat(&map, GL_RGBA32F,          true, 32, 32, 32, 32, 0, GL_RGBA,         GL_FLOAT,                        GL_FLOAT, false, FloatSupport,       FloatRGBARenderableSupport,     RequireExt<&Extensions::textureFloatLinear>              );
+
+    // Depth stencil formats
+    //                         | Internal format         |sized| D |S | X | Format            | Type                             | Component type        | Supported                                       | Renderable                                                                            | Filterable                                  |
+    AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT16,     true, 16, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,                 GL_UNSIGNED_NORMALIZED, RequireES<2, 0>,                                  RequireES<2, 0>,                                                                        RequireESOrExt<3, 0, &Extensions::depthTextures>);
+    AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT24,     true, 24, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireES<3, 0>,                                  RequireES<3, 0>,                                                                        RequireESOrExt<3, 0, &Extensions::depthTextures>);
+    AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32F,    true, 32, 0,  0, GL_DEPTH_COMPONENT, GL_FLOAT,                          GL_FLOAT,               RequireES<3, 0>,                                  RequireES<3, 0>,                                                                        RequireESOrExt<3, 0, &Extensions::depthTextures>);
+    AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32_OES, true, 32, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>,     AlwaysSupported                                 );
+    AddDepthStencilFormat(&map, GL_DEPTH24_STENCIL8,      true, 24, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,              GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::depthTextures>, RequireESOrExtOrExt<3, 0, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported                                 );
+    AddDepthStencilFormat(&map, GL_DEPTH32F_STENCIL8,     true, 32, 8, 24, GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT,               RequireES<3, 0>,                                  RequireES<3, 0>,                                                                        AlwaysSupported                                 );
+    // STENCIL_INDEX8 is special-cased, see around the bottom of the list.
+
+    // Luminance alpha formats
+    //                | Internal format           |sized| L | A | Format            | Type             | Component type        | Supported                                                                   | Renderable    | Filterable    |
+    AddLUMAFormat(&map, GL_ALPHA8_EXT,             true,  0,  8, GL_ALPHA,           GL_UNSIGNED_BYTE,  GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>,                                      NeverSupported, AlwaysSupported);
+    AddLUMAFormat(&map, GL_LUMINANCE8_EXT,         true,  8,  0, GL_LUMINANCE,       GL_UNSIGNED_BYTE,  GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>,                                      NeverSupported, AlwaysSupported);
+    AddLUMAFormat(&map, GL_LUMINANCE8_ALPHA8_EXT,  true,  8,  8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,  GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>,                                      NeverSupported, AlwaysSupported);
+    AddLUMAFormat(&map, GL_ALPHA16F_EXT,           true,  0, 16, GL_ALPHA,           GL_HALF_FLOAT_OES, GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddLUMAFormat(&map, GL_LUMINANCE16F_EXT,       true, 16,  0, GL_LUMINANCE,       GL_HALF_FLOAT_OES, GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddLUMAFormat(&map, GL_LUMINANCE_ALPHA16F_EXT, true, 16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddLUMAFormat(&map, GL_ALPHA32F_EXT,           true,  0, 32, GL_ALPHA,           GL_FLOAT,          GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, RequireExt<&Extensions::textureFloatLinear>);
+    AddLUMAFormat(&map, GL_LUMINANCE32F_EXT,       true, 32,  0, GL_LUMINANCE,       GL_FLOAT,          GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, RequireExt<&Extensions::textureFloatLinear>);
+    AddLUMAFormat(&map, GL_LUMINANCE_ALPHA32F_EXT, true, 32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT,          GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, RequireExt<&Extensions::textureFloatLinear>);
+
+    // Compressed formats, From ES 3.0.1 spec, table 3.16
+    //                       | Internal format                             |W |H | BS |CC| Format | Type            | SRGB | Supported      | Renderable    | Filterable    |
+    AddCompressedFormat(&map, GL_COMPRESSED_R11_EAC,                        4, 4,  64, 1, GL_RED,  GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SIGNED_R11_EAC,                 4, 4,  64, 1, GL_RED,  GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RG11_EAC,                       4, 4, 128, 2, GL_RG,   GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SIGNED_RG11_EAC,                4, 4, 128, 2, GL_RG,   GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGB8_ETC2,                      4, 4,  64, 3, GL_RGB,  GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ETC2,                     4, 4,  64, 3, GL_RGB,  GL_UNSIGNED_BYTE, true,  RequireES<3, 0>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  4, 4,  64, 3, GL_RGB,  GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4,  64, 3, GL_RGB,  GL_UNSIGNED_BYTE, true,  RequireES<3, 0>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA8_ETC2_EAC,                 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireES<3, 0>, NeverSupported, AlwaysSupported);
+
+    // From GL_EXT_texture_compression_dxt1
+    //                       | Internal format                   |W |H | BS |CC| Format | Type            | SRGB | Supported                                         | Renderable    | Filterable    |
+    AddCompressedFormat(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    4, 4,  64, 3, GL_RGB,  GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>,    NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   4, 4,  64, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>,    NeverSupported, AlwaysSupported);
+
+    // From GL_ANGLE_texture_compression_dxt3
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>,    NeverSupported, AlwaysSupported);
+
+    // From GL_ANGLE_texture_compression_dxt5
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>,    NeverSupported, AlwaysSupported);
+
+    // From GL_OES_compressed_ETC1_RGB8_texture
+    AddCompressedFormat(&map, GL_ETC1_RGB8_OES,                   4, 4,  64, 3, GL_RGB,  GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::compressedETC1RGB8Texture>, NeverSupported, AlwaysSupported);
+
+    // From GL_EXT_texture_compression_s3tc_srgb
+    //                       | Internal format                       |W |H | BS |CC| Format | Type            | SRGB | Supported                                         | Renderable    | Filterable    |
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,       4, 4,  64, 3, GL_RGB,  GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::textureCompressionS3TCsRGB>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4,  64, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::textureCompressionS3TCsRGB>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::textureCompressionS3TCsRGB>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::textureCompressionS3TCsRGB>, NeverSupported, AlwaysSupported);
+
+    // From KHR_texture_compression_astc_hdr
+    //                       | Internal format                          | W | H | BS |CC| Format | Type            | SRGB | Supported                                                                                     | Renderable     | Filterable    |
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_4x4_KHR,            4,  4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_5x4_KHR,            5,  4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_5x5_KHR,            5,  5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_6x5_KHR,            6,  5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_6x6_KHR,            6,  6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_8x5_KHR,            8,  5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_8x6_KHR,            8,  6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_8x8_KHR,            8,  8, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x5_KHR,          10,  5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x6_KHR,          10,  6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x8_KHR,          10,  8, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x10_KHR,         10, 10, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_12x10_KHR,         12, 10, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_12x12_KHR,         12, 12, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,    4,  4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,    5,  4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,    5,  5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,    6,  5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,    6,  6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,    8,  5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,    8,  6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,    8,  8, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,  10,  5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,  10,  6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,  10,  8, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 10, 10, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 12, 10, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 12, 12, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+
+    // For STENCIL_INDEX8 we chose a normalized component type for the following reasons:
+    // - Multisampled buffer are disallowed for non-normalized integer component types and we want to support it for STENCIL_INDEX8
+    // - All other stencil formats (all depth-stencil) are either float or normalized
+    // - It affects only validation of internalformat in RenderbufferStorageMultisample.
+    //                         | Internal format  |sized|D |S |X | Format    | Type            | Component type        | Supported      | Renderable     | Filterable   |
+    AddDepthStencilFormat(&map, GL_STENCIL_INDEX8, true, 0, 8, 0, GL_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, RequireES<2, 0>, NeverSupported);
+
+    // From GL_ANGLE_lossy_etc_decode
+    //                       | Internal format                                                |W |H |BS |CC| Format | Type            | SRGB | Supported                                                                                     | Renderable     | Filterable    |
+    AddCompressedFormat(&map, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE,                                 4, 4, 64, 3, GL_RGB,  GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE,                      4, 4, 64, 3, GL_RGB,  GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE,                     4, 4, 64, 3, GL_RGB,  GL_UNSIGNED_BYTE, true,  RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,  4, 4, 64, 3, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+    AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4, 4, 64, 3, GL_RGBA, GL_UNSIGNED_BYTE, true,  RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+
+    // From GL_EXT_texture_norm16
+    //                 | Internal format    |sized| R | G | B | A |S | Format         | Type                           | Component type        | SRGB | Texture supported                        | Renderable                               | Filterable    |
+    AddRGBAFormat(&map, GL_R16_EXT,          true, 16,  0,  0,  0, 0, GL_RED,          GL_UNSIGNED_SHORT,               GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>,    RequireExt<&Extensions::textureNorm16>,    AlwaysSupported);
+    AddRGBAFormat(&map, GL_R16_SNORM_EXT,    true, 16,  0,  0,  0, 0, GL_RED,          GL_SHORT,                        GL_SIGNED_NORMALIZED,   false, RequireExt<&Extensions::textureNorm16>,    NeverSupported,                            AlwaysSupported);
+    AddRGBAFormat(&map, GL_RG16_EXT,         true, 16, 16,  0,  0, 0, GL_RG,           GL_UNSIGNED_SHORT,               GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>,    RequireExt<&Extensions::textureNorm16>,    AlwaysSupported);
+    AddRGBAFormat(&map, GL_RG16_SNORM_EXT,   true, 16, 16,  0,  0, 0, GL_RG,           GL_SHORT,                        GL_SIGNED_NORMALIZED,   false, RequireExt<&Extensions::textureNorm16>,    NeverSupported,                            AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB16_EXT,        true, 16, 16, 16,  0, 0, GL_RGB,          GL_UNSIGNED_SHORT,               GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>,    NeverSupported,                            AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB16_SNORM_EXT,  true, 16, 16, 16,  0, 0, GL_RGB,          GL_SHORT,                        GL_SIGNED_NORMALIZED,   false, RequireExt<&Extensions::textureNorm16>,    NeverSupported,                            AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA16_EXT,       true, 16, 16, 16, 16, 0, GL_RGBA,         GL_UNSIGNED_SHORT,               GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>,    RequireExt<&Extensions::textureNorm16>,    AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA16_SNORM_EXT, true, 16, 16, 16, 16, 0, GL_RGBA,         GL_SHORT,                        GL_SIGNED_NORMALIZED,   false, RequireExt<&Extensions::textureNorm16>,    NeverSupported,                            AlwaysSupported);
+
+    // Unsized formats
+    //                 | Internal format    |sized | R | G | B | A |S | Format         | Type                           | Component type        | SRGB | Texture supported                           | Renderable                                  | Filterable    |
+    AddRGBAFormat(&map, GL_RED,              false,  8,  0,  0,  0, 0, GL_RED,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureRG>, NeverSupported, AlwaysSupported);
+    AddRGBAFormat(&map, GL_RG,               false,  8,  8,  0,  0, 0, GL_RG,           GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureRG>, NeverSupported, AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB,              false,  8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB,              false,  5,  6,  5,  0, 0, GL_RGB,          GL_UNSIGNED_SHORT_5_6_5,         GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>,                              RequireES<2, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA,             false,  4,  4,  4,  4, 0, GL_RGBA,         GL_UNSIGNED_SHORT_4_4_4_4,       GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>,                              RequireES<2, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA,             false,  5,  5,  5,  1, 0, GL_RGBA,         GL_UNSIGNED_SHORT_5_5_5_1,       GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>,                              RequireES<2, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA,             false,  8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>,                              RequireES<2, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA,             false, 10, 10, 10,  2, 0, GL_RGBA,         GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>,                              RequireES<2, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_SRGB,             false,  8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireExt<&Extensions::sRGB>,                NeverSupported,                               AlwaysSupported);
+    AddRGBAFormat(&map, GL_SRGB_ALPHA_EXT,   false,  8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireExt<&Extensions::sRGB>,                RequireExt<&Extensions::sRGB>,                AlwaysSupported);
+
+    AddRGBAFormat(&map, GL_BGRA_EXT,         false,  8,  8,  8,  8, 0, GL_BGRA_EXT,     GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+
+    // Unsized integer formats
+    //                 |Internal format |sized | R | G | B | A |S | Format         | Type                          | Component type | SRGB | Texture        | Renderable    | Filterable   |
+    AddRGBAFormat(&map, GL_RED_INTEGER,  false,  8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_BYTE,                        GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RED_INTEGER,  false,  8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_BYTE,               GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RED_INTEGER,  false, 16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_SHORT,                       GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RED_INTEGER,  false, 16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_SHORT,              GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RED_INTEGER,  false, 32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_INT,                         GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RED_INTEGER,  false, 32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_INT,                GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RG_INTEGER,   false,  8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_BYTE,                        GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RG_INTEGER,   false,  8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_BYTE,               GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RG_INTEGER,   false, 16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_SHORT,                       GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RG_INTEGER,   false, 16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_SHORT,              GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RG_INTEGER,   false, 32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_INT,                         GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RG_INTEGER,   false, 32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_INT,                GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGB_INTEGER,  false,  8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_BYTE,                        GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGB_INTEGER,  false,  8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_BYTE,               GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGB_INTEGER,  false, 16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_SHORT,                       GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGB_INTEGER,  false, 16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_SHORT,              GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGB_INTEGER,  false, 32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_INT,                         GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGB_INTEGER,  false, 32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_INT,                GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA_INTEGER, false,  8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_BYTE,                        GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA_INTEGER, false,  8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,               GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT,                       GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT,              GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT,                         GL_INT,          false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT,                GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+    AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 10, 10, 10,  2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+
+    // Unsized floating point formats
+    //                 |Internal format |sized | R | G | B | A |S | Format         | Type                           | Comp    | SRGB | Texture supported           | Renderable                            | Filterable                                              |
+    AddRGBAFormat(&map, GL_RED,          false, 16,  0,  0,  0, 0, GL_RED,          GL_HALF_FLOAT,                   GL_FLOAT, false, NeverSupported,               NeverSupported,                         NeverSupported                                           );
+    AddRGBAFormat(&map, GL_RG,           false, 16, 16,  0,  0, 0, GL_RG,           GL_HALF_FLOAT,                   GL_FLOAT, false, NeverSupported,               NeverSupported,                         NeverSupported                                           );
+    AddRGBAFormat(&map, GL_RGB,          false, 16, 16, 16,  0, 0, GL_RGB,          GL_HALF_FLOAT,                   GL_FLOAT, false, NeverSupported,               NeverSupported,                         NeverSupported                                           );
+    AddRGBAFormat(&map, GL_RGBA,         false, 16, 16, 16, 16, 0, GL_RGBA,         GL_HALF_FLOAT,                   GL_FLOAT, false, NeverSupported,               NeverSupported,                         NeverSupported                                           );
+    AddRGBAFormat(&map, GL_RED,          false, 16,  0,  0,  0, 0, GL_RED,          GL_HALF_FLOAT_OES,               GL_FLOAT, false, UnsizedHalfFloatOESRGSupport, UnsizedHalfFloatOESRGRenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddRGBAFormat(&map, GL_RG,           false, 16, 16,  0,  0, 0, GL_RG,           GL_HALF_FLOAT_OES,               GL_FLOAT, false, UnsizedHalfFloatOESRGSupport, UnsizedHalfFloatOESRGRenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddRGBAFormat(&map, GL_RGB,          false, 16, 16, 16,  0, 0, GL_RGB,          GL_HALF_FLOAT_OES,               GL_FLOAT, false, UnsizedHalfFloatOESSupport,   UnsizedHalfFloatOESRenderableSupport,   RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddRGBAFormat(&map, GL_RGBA,         false, 16, 16, 16, 16, 0, GL_RGBA,         GL_HALF_FLOAT_OES,               GL_FLOAT, false, UnsizedHalfFloatOESSupport,   UnsizedHalfFloatOESRenderableSupport,   RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+    AddRGBAFormat(&map, GL_RED,          false, 32,  0,  0,  0, 0, GL_RED,          GL_FLOAT,                        GL_FLOAT, false, UnsizedFloatRGSupport,        UnsizedFloatRGRenderableSupport,        RequireExt<&Extensions::textureFloatLinear>              );
+    AddRGBAFormat(&map, GL_RG,           false, 32, 32,  0,  0, 0, GL_RG,           GL_FLOAT,                        GL_FLOAT, false, UnsizedFloatRGSupport,        UnsizedFloatRGRenderableSupport,        RequireExt<&Extensions::textureFloatLinear>              );
+    AddRGBAFormat(&map, GL_RGB,          false, 32, 32, 32,  0, 0, GL_RGB,          GL_FLOAT,                        GL_FLOAT, false, UnsizedFloatSupport,          UnsizedFloatRGBRenderableSupport,       RequireExt<&Extensions::textureFloatLinear>              );
+    AddRGBAFormat(&map, GL_RGBA,         false, 32, 32, 32, 32, 0, GL_RGBA,         GL_FLOAT,                        GL_FLOAT, false, UnsizedFloatSupport,          UnsizedFloatRGBARenderableSupport,      RequireExt<&Extensions::textureFloatLinear>              );
+
+    // Unsized luminance alpha formats
+    //                | Internal format    |sized | L | A | Format            | Type             | Component type        | Supported                                | Renderable    | Filterable                                    |
+    AddLUMAFormat(&map, GL_ALPHA,           false,  0,  8, GL_ALPHA,           GL_UNSIGNED_BYTE,  GL_UNSIGNED_NORMALIZED, RequireES<2, 0>,                           NeverSupported, AlwaysSupported                                );
+    AddLUMAFormat(&map, GL_LUMINANCE,       false,  8,  0, GL_LUMINANCE,       GL_UNSIGNED_BYTE,  GL_UNSIGNED_NORMALIZED, RequireES<2, 0>,                           NeverSupported, AlwaysSupported                                );
+    AddLUMAFormat(&map, GL_LUMINANCE_ALPHA, false,  8,  8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,  GL_UNSIGNED_NORMALIZED, RequireES<2, 0>,                           NeverSupported, AlwaysSupported                                );
+    AddLUMAFormat(&map, GL_ALPHA,           false,  0, 16, GL_ALPHA,           GL_HALF_FLOAT_OES, GL_FLOAT,               RequireExt<&Extensions::textureHalfFloat>, NeverSupported, RequireExt<&Extensions::textureHalfFloatLinear>);
+    AddLUMAFormat(&map, GL_LUMINANCE,       false, 16,  0, GL_LUMINANCE,       GL_HALF_FLOAT_OES, GL_FLOAT,               RequireExt<&Extensions::textureHalfFloat>, NeverSupported, RequireExt<&Extensions::textureHalfFloatLinear>);
+    AddLUMAFormat(&map, GL_LUMINANCE_ALPHA ,false, 16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT,               RequireExt<&Extensions::textureHalfFloat>, NeverSupported, RequireExt<&Extensions::textureHalfFloatLinear>);
+    AddLUMAFormat(&map, GL_ALPHA,           false,  0, 32, GL_ALPHA,           GL_FLOAT,          GL_FLOAT,               RequireExt<&Extensions::textureFloat>,     NeverSupported, RequireExt<&Extensions::textureFloatLinear>    );
+    AddLUMAFormat(&map, GL_LUMINANCE,       false, 32,  0, GL_LUMINANCE,       GL_FLOAT,          GL_FLOAT,               RequireExt<&Extensions::textureFloat>,     NeverSupported, RequireExt<&Extensions::textureFloatLinear>    );
+    AddLUMAFormat(&map, GL_LUMINANCE_ALPHA, false, 32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT,          GL_FLOAT,               RequireExt<&Extensions::textureFloat>,     NeverSupported, RequireExt<&Extensions::textureFloatLinear>    );
+
+    // Unsized depth stencil formats
+    //                         | Internal format        |sized | D |S | X | Format            | Type                             | Component type        | Supported                                            | Renderable                                           | Filterable    |
+    AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT,      false, 16, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,                 GL_UNSIGNED_NORMALIZED, RequireES<2, 0>,                                       RequireES<2, 0>,                                       AlwaysSupported);
+    AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT,      false, 24, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireES<2, 0>,                                       RequireES<2, 0>,                                       AlwaysSupported);
+    AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT,      false, 32, 0,  0, GL_DEPTH_COMPONENT, GL_FLOAT,                          GL_FLOAT,               RequireES<2, 0>,                                       RequireES<2, 0>,                                       AlwaysSupported);
+    AddDepthStencilFormat(&map, GL_DEPTH_STENCIL,        false, 24, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,              GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, AlwaysSupported);
+    AddDepthStencilFormat(&map, GL_DEPTH_STENCIL,        false, 32, 8, 24, GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT,               RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, AlwaysSupported);
+    AddDepthStencilFormat(&map, GL_STENCIL,              false,  0, 8,  0, GL_STENCIL,         GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, RequireES<2, 0>,                                       RequireES<2, 0>,                                       NeverSupported);
+    // clang-format on
+
+    return map;
+}
+
+static const InternalFormatInfoMap &GetInternalFormatMap()
+{
+    static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap();
+    return formatMap;
+}
+
+static FormatSet BuildAllSizedInternalFormatSet()
+{
+    FormatSet result;
+
+    for (const auto &internalFormat : GetInternalFormatMap())
+    {
+        for (const auto &type : internalFormat.second)
+        {
+            if (type.second.sized)
+            {
+                // TODO(jmadill): Fix this hack.
+                if (internalFormat.first == GL_BGR565_ANGLEX)
+                    continue;
+
+                result.insert(internalFormat.first);
+            }
+        }
+    }
+
+    return result;
+}
+
+const Type &GetTypeInfo(GLenum type)
+{
+    switch (type)
+    {
+      case GL_UNSIGNED_BYTE:
+      case GL_BYTE:
+        {
+            static const Type info = GenTypeInfo(1, false);
+            return info;
+        }
+      case GL_UNSIGNED_SHORT:
+      case GL_SHORT:
+      case GL_HALF_FLOAT:
+      case GL_HALF_FLOAT_OES:
+        {
+            static const Type info = GenTypeInfo(2, false);
+            return info;
+        }
+      case GL_UNSIGNED_INT:
+      case GL_INT:
+      case GL_FLOAT:
+        {
+            static const Type info = GenTypeInfo(4, false);
+            return info;
+        }
+      case GL_UNSIGNED_SHORT_5_6_5:
+      case GL_UNSIGNED_SHORT_4_4_4_4:
+      case GL_UNSIGNED_SHORT_5_5_5_1:
+      case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+      case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+        {
+            static const Type info = GenTypeInfo(2, true);
+            return info;
+        }
+      case GL_UNSIGNED_INT_2_10_10_10_REV:
+      case GL_UNSIGNED_INT_24_8:
+      case GL_UNSIGNED_INT_10F_11F_11F_REV:
+      case GL_UNSIGNED_INT_5_9_9_9_REV:
+        {
+            ASSERT(GL_UNSIGNED_INT_24_8_OES == GL_UNSIGNED_INT_24_8);
+            static const Type info = GenTypeInfo(4, true);
+            return info;
+        }
+      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+        {
+            static const Type info = GenTypeInfo(8, true);
+            return info;
+        }
+      default:
+        {
+            static const Type defaultInfo;
+            return defaultInfo;
+        }
+    }
+}
+
+const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat)
+{
+    static const InternalFormat defaultInternalFormat;
+    const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+    auto iter                              = formatMap.find(internalFormat);
+
+    // Sized internal formats only have one type per entry
+    if (iter == formatMap.end() || iter->second.size() != 1)
+    {
+        return defaultInternalFormat;
+    }
+
+    const InternalFormat &internalFormatInfo = iter->second.begin()->second;
+    if (!internalFormatInfo.sized)
+    {
+        return defaultInternalFormat;
+    }
+
+    return internalFormatInfo;
+}
+
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type)
+{
+    static const InternalFormat defaultInternalFormat;
+    const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+
+    auto internalFormatIter = formatMap.find(internalFormat);
+    if (internalFormatIter == formatMap.end())
+    {
+        return defaultInternalFormat;
+    }
+
+    // If the internal format is sized, simply return it without the type check.
+    if (internalFormatIter->second.size() == 1 && internalFormatIter->second.begin()->second.sized)
+    {
+        return internalFormatIter->second.begin()->second;
+    }
+
+    auto typeIter = internalFormatIter->second.find(type);
+    if (typeIter == internalFormatIter->second.end())
+    {
+        return defaultInternalFormat;
+    }
+
+    return typeIter->second;
+}
+
+GLuint InternalFormat::computePixelBytes(GLenum formatType) const
+{
+    const auto &typeInfo = GetTypeInfo(formatType);
+    GLuint components    = typeInfo.specialInterpretation ? 1u : componentCount;
+    return components * typeInfo.bytes;
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType,
+                                                          GLsizei width,
+                                                          GLint alignment,
+                                                          GLint rowLength) const
+{
+    // Compressed images do not use pack/unpack parameters.
+    if (compressed)
+    {
+        ASSERT(rowLength == 0);
+        return computeCompressedImageSize(formatType, Extents(width, 1, 1));
+    }
+
+    CheckedNumeric<GLuint> checkedWidth(rowLength > 0 ? rowLength : width);
+    CheckedNumeric<GLuint> checkedRowBytes = checkedWidth * computePixelBytes(formatType);
+
+    ASSERT(alignment > 0 && isPow2(alignment));
+    CheckedNumeric<GLuint> checkedAlignment(alignment);
+    auto aligned = rx::roundUp(checkedRowBytes, checkedAlignment);
+    ANGLE_TRY_CHECKED_MATH(aligned);
+    return aligned.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLsizei height,
+                                                        GLint imageHeight,
+                                                        GLuint rowPitch) const
+{
+    GLuint rows =
+        (imageHeight > 0 ? static_cast<GLuint>(imageHeight) : static_cast<GLuint>(height));
+    CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
+
+    auto depthPitch = checkedRowPitch * rows;
+    ANGLE_TRY_CHECKED_MATH(depthPitch);
+    return depthPitch.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
+                                                            GLsizei width,
+                                                            GLsizei height,
+                                                            GLint alignment,
+                                                            GLint rowLength,
+                                                            GLint imageHeight) const
+{
+    GLuint rowPitch = 0;
+    ANGLE_TRY_RESULT(computeRowPitch(formatType, width, alignment, rowLength), rowPitch);
+    return computeDepthPitch(height, imageHeight, rowPitch);
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(GLenum formatType,
+                                                                     const Extents &size) const
+{
+    CheckedNumeric<GLuint> checkedWidth(size.width);
+    CheckedNumeric<GLuint> checkedHeight(size.height);
+    CheckedNumeric<GLuint> checkedDepth(size.depth);
+    CheckedNumeric<GLuint> checkedBlockWidth(compressedBlockWidth);
+    CheckedNumeric<GLuint> checkedBlockHeight(compressedBlockHeight);
+
+    ASSERT(compressed);
+    auto numBlocksWide = (checkedWidth + checkedBlockWidth - 1u) / checkedBlockWidth;
+    auto numBlocksHigh = (checkedHeight + checkedBlockHeight - 1u) / checkedBlockHeight;
+    auto bytes         = numBlocksWide * numBlocksHigh * pixelBytes * checkedDepth;
+    ANGLE_TRY_CHECKED_MATH(bytes);
+    return bytes.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch,
+                                                           GLuint depthPitch,
+                                                           const PixelStoreStateBase &state,
+                                                           bool is3D) const
+{
+    CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
+    CheckedNumeric<GLuint> checkedDepthPitch(depthPitch);
+    CheckedNumeric<GLuint> checkedSkipImages(static_cast<GLuint>(state.skipImages));
+    CheckedNumeric<GLuint> checkedSkipRows(static_cast<GLuint>(state.skipRows));
+    CheckedNumeric<GLuint> checkedSkipPixels(static_cast<GLuint>(state.skipPixels));
+    CheckedNumeric<GLuint> checkedPixelBytes(pixelBytes);
+    auto checkedSkipImagesBytes = checkedSkipImages * checkedDepthPitch;
+    if (!is3D)
+    {
+        checkedSkipImagesBytes = 0;
+    }
+    auto skipBytes = checkedSkipImagesBytes + checkedSkipRows * checkedRowPitch +
+                     checkedSkipPixels * checkedPixelBytes;
+    ANGLE_TRY_CHECKED_MATH(skipBytes);
+    return skipBytes.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computePackUnpackEndByte(
+    GLenum formatType,
+    const Extents &size,
+    const PixelStoreStateBase &state,
+    bool is3D) const
+{
+    GLuint rowPitch = 0;
+    ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, state.alignment, state.rowLength),
+                     rowPitch);
+
+    GLuint depthPitch = 0;
+    if (is3D)
+    {
+        ANGLE_TRY_RESULT(computeDepthPitch(size.height, state.imageHeight, rowPitch), depthPitch);
+    }
+
+    CheckedNumeric<GLuint> checkedCopyBytes = 0;
+    if (compressed)
+    {
+        ANGLE_TRY_RESULT(computeCompressedImageSize(formatType, size), checkedCopyBytes);
+    }
+    else if (size.height != 0 && (!is3D || size.depth != 0))
+    {
+        CheckedNumeric<GLuint> bytes = computePixelBytes(formatType);
+        checkedCopyBytes += size.width * bytes;
+
+        CheckedNumeric<GLuint> heightMinusOne = size.height - 1;
+        checkedCopyBytes += heightMinusOne * rowPitch;
+
+        if (is3D)
+        {
+            CheckedNumeric<GLuint> depthMinusOne = size.depth - 1;
+            checkedCopyBytes += depthMinusOne * depthPitch;
+        }
+    }
+
+    CheckedNumeric<GLuint> checkedSkipBytes = 0;
+    ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, depthPitch, state, is3D), checkedSkipBytes);
+
+    CheckedNumeric<GLuint> endByte = checkedCopyBytes + checkedSkipBytes;
+
+    ANGLE_TRY_CHECKED_MATH(endByte);
+    return endByte.ValueOrDie();
+}
+
+GLenum GetUnsizedFormat(GLenum internalFormat)
+{
+    auto sizedFormatInfo = GetSizedInternalFormatInfo(internalFormat);
+    if (sizedFormatInfo.internalFormat != GL_NONE)
+    {
+        return sizedFormatInfo.format;
+    }
+
+    return internalFormat;
+}
+
+const FormatSet &GetAllSizedInternalFormats()
+{
+    static FormatSet formatSet = BuildAllSizedInternalFormatSet();
+    return formatSet;
+}
+
+AttributeType GetAttributeType(GLenum enumValue)
+{
+    switch (enumValue)
+    {
+        case GL_FLOAT:
+            return ATTRIBUTE_FLOAT;
+        case GL_FLOAT_VEC2:
+            return ATTRIBUTE_VEC2;
+        case GL_FLOAT_VEC3:
+            return ATTRIBUTE_VEC3;
+        case GL_FLOAT_VEC4:
+            return ATTRIBUTE_VEC4;
+        case GL_INT:
+            return ATTRIBUTE_INT;
+        case GL_INT_VEC2:
+            return ATTRIBUTE_IVEC2;
+        case GL_INT_VEC3:
+            return ATTRIBUTE_IVEC3;
+        case GL_INT_VEC4:
+            return ATTRIBUTE_IVEC4;
+        case GL_UNSIGNED_INT:
+            return ATTRIBUTE_UINT;
+        case GL_UNSIGNED_INT_VEC2:
+            return ATTRIBUTE_UVEC2;
+        case GL_UNSIGNED_INT_VEC3:
+            return ATTRIBUTE_UVEC3;
+        case GL_UNSIGNED_INT_VEC4:
+            return ATTRIBUTE_UVEC4;
+        case GL_FLOAT_MAT2:
+            return ATTRIBUTE_MAT2;
+        case GL_FLOAT_MAT3:
+            return ATTRIBUTE_MAT3;
+        case GL_FLOAT_MAT4:
+            return ATTRIBUTE_MAT4;
+        case GL_FLOAT_MAT2x3:
+            return ATTRIBUTE_MAT2x3;
+        case GL_FLOAT_MAT2x4:
+            return ATTRIBUTE_MAT2x4;
+        case GL_FLOAT_MAT3x2:
+            return ATTRIBUTE_MAT3x2;
+        case GL_FLOAT_MAT3x4:
+            return ATTRIBUTE_MAT3x4;
+        case GL_FLOAT_MAT4x2:
+            return ATTRIBUTE_MAT4x2;
+        case GL_FLOAT_MAT4x3:
+            return ATTRIBUTE_MAT4x3;
+        default:
+            UNREACHABLE();
+            return ATTRIBUTE_FLOAT;
+    }
+}
+
+VertexFormatType GetVertexFormatType(GLenum type, GLboolean normalized, GLuint components, bool pureInteger)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+            switch (components)
+            {
+                case 1:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SBYTE1_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SBYTE1_NORM;
+                    return VERTEX_FORMAT_SBYTE1;
+                case 2:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SBYTE2_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SBYTE2_NORM;
+                    return VERTEX_FORMAT_SBYTE2;
+                case 3:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SBYTE3_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SBYTE3_NORM;
+                    return VERTEX_FORMAT_SBYTE3;
+                case 4:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SBYTE4_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SBYTE4_NORM;
+                    return VERTEX_FORMAT_SBYTE4;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        case GL_UNSIGNED_BYTE:
+            switch (components)
+            {
+                case 1:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_UBYTE1_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_UBYTE1_NORM;
+                    return VERTEX_FORMAT_UBYTE1;
+                case 2:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_UBYTE2_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_UBYTE2_NORM;
+                    return VERTEX_FORMAT_UBYTE2;
+                case 3:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_UBYTE3_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_UBYTE3_NORM;
+                    return VERTEX_FORMAT_UBYTE3;
+                case 4:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_UBYTE4_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_UBYTE4_NORM;
+                    return VERTEX_FORMAT_UBYTE4;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        case GL_SHORT:
+            switch (components)
+            {
+                case 1:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SSHORT1_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SSHORT1_NORM;
+                    return VERTEX_FORMAT_SSHORT1;
+                case 2:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SSHORT2_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SSHORT2_NORM;
+                    return VERTEX_FORMAT_SSHORT2;
+                case 3:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SSHORT3_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SSHORT3_NORM;
+                    return VERTEX_FORMAT_SSHORT3;
+                case 4:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SSHORT4_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SSHORT4_NORM;
+                    return VERTEX_FORMAT_SSHORT4;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        case GL_UNSIGNED_SHORT:
+            switch (components)
+            {
+                case 1:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_USHORT1_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_USHORT1_NORM;
+                    return VERTEX_FORMAT_USHORT1;
+                case 2:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_USHORT2_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_USHORT2_NORM;
+                    return VERTEX_FORMAT_USHORT2;
+                case 3:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_USHORT3_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_USHORT3_NORM;
+                    return VERTEX_FORMAT_USHORT3;
+                case 4:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_USHORT4_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_USHORT4_NORM;
+                    return VERTEX_FORMAT_USHORT4;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        case GL_INT:
+            switch (components)
+            {
+                case 1:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SINT1_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SINT1_NORM;
+                    return VERTEX_FORMAT_SINT1;
+                case 2:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SINT2_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SINT2_NORM;
+                    return VERTEX_FORMAT_SINT2;
+                case 3:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SINT3_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SINT3_NORM;
+                    return VERTEX_FORMAT_SINT3;
+                case 4:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_SINT4_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_SINT4_NORM;
+                    return VERTEX_FORMAT_SINT4;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        case GL_UNSIGNED_INT:
+            switch (components)
+            {
+                case 1:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_UINT1_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_UINT1_NORM;
+                    return VERTEX_FORMAT_UINT1;
+                case 2:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_UINT2_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_UINT2_NORM;
+                    return VERTEX_FORMAT_UINT2;
+                case 3:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_UINT3_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_UINT3_NORM;
+                    return VERTEX_FORMAT_UINT3;
+                case 4:
+                    if (pureInteger)
+                        return VERTEX_FORMAT_UINT4_INT;
+                    if (normalized)
+                        return VERTEX_FORMAT_UINT4_NORM;
+                    return VERTEX_FORMAT_UINT4;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        case GL_FLOAT:
+            switch (components)
+            {
+                case 1:
+                    return VERTEX_FORMAT_FLOAT1;
+                case 2:
+                    return VERTEX_FORMAT_FLOAT2;
+                case 3:
+                    return VERTEX_FORMAT_FLOAT3;
+                case 4:
+                    return VERTEX_FORMAT_FLOAT4;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        case GL_HALF_FLOAT:
+            switch (components)
+            {
+                case 1:
+                    return VERTEX_FORMAT_HALF1;
+                case 2:
+                    return VERTEX_FORMAT_HALF2;
+                case 3:
+                    return VERTEX_FORMAT_HALF3;
+                case 4:
+                    return VERTEX_FORMAT_HALF4;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        case GL_FIXED:
+            switch (components)
+            {
+                case 1:
+                    return VERTEX_FORMAT_FIXED1;
+                case 2:
+                    return VERTEX_FORMAT_FIXED2;
+                case 3:
+                    return VERTEX_FORMAT_FIXED3;
+                case 4:
+                    return VERTEX_FORMAT_FIXED4;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        case GL_INT_2_10_10_10_REV:
+            if (pureInteger)
+                return VERTEX_FORMAT_SINT210_INT;
+            if (normalized)
+                return VERTEX_FORMAT_SINT210_NORM;
+            return VERTEX_FORMAT_SINT210;
+        case GL_UNSIGNED_INT_2_10_10_10_REV:
+            if (pureInteger)
+                return VERTEX_FORMAT_UINT210_INT;
+            if (normalized)
+                return VERTEX_FORMAT_UINT210_NORM;
+            return VERTEX_FORMAT_UINT210;
+        default:
+            UNREACHABLE();
+            break;
+    }
+    return VERTEX_FORMAT_UBYTE1;
+}
+
+VertexFormatType GetVertexFormatType(const VertexAttribute &attrib)
+{
+    return GetVertexFormatType(attrib.type, attrib.normalized, attrib.size, attrib.pureInteger);
+}
+
+VertexFormatType GetVertexFormatType(const VertexAttribute &attrib, GLenum currentValueType)
+{
+    if (!attrib.enabled)
+    {
+        return GetVertexFormatType(currentValueType, GL_FALSE, 4, (currentValueType != GL_FLOAT));
+    }
+    return GetVertexFormatType(attrib);
+}
+
+const VertexFormat &GetVertexFormatFromType(VertexFormatType vertexFormatType)
+{
+    switch (vertexFormatType)
+    {
+        case VERTEX_FORMAT_SBYTE1:
+        {
+            static const VertexFormat format(GL_BYTE, GL_FALSE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE1_NORM:
+        {
+            static const VertexFormat format(GL_BYTE, GL_TRUE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE2:
+        {
+            static const VertexFormat format(GL_BYTE, GL_FALSE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE2_NORM:
+        {
+            static const VertexFormat format(GL_BYTE, GL_TRUE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE3:
+        {
+            static const VertexFormat format(GL_BYTE, GL_FALSE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE3_NORM:
+        {
+            static const VertexFormat format(GL_BYTE, GL_TRUE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE4:
+        {
+            static const VertexFormat format(GL_BYTE, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE4_NORM:
+        {
+            static const VertexFormat format(GL_BYTE, GL_TRUE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE1:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE1_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE2:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE2_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE3:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE3_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE4:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE4_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT1:
+        {
+            static const VertexFormat format(GL_SHORT, GL_FALSE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT1_NORM:
+        {
+            static const VertexFormat format(GL_SHORT, GL_TRUE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT2:
+        {
+            static const VertexFormat format(GL_SHORT, GL_FALSE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT2_NORM:
+        {
+            static const VertexFormat format(GL_SHORT, GL_TRUE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT3:
+        {
+            static const VertexFormat format(GL_SHORT, GL_FALSE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT3_NORM:
+        {
+            static const VertexFormat format(GL_SHORT, GL_TRUE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT4:
+        {
+            static const VertexFormat format(GL_SHORT, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT4_NORM:
+        {
+            static const VertexFormat format(GL_SHORT, GL_TRUE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT1:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT1_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT2:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT2_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT3:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT3_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT4:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT4_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT1:
+        {
+            static const VertexFormat format(GL_INT, GL_FALSE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT1_NORM:
+        {
+            static const VertexFormat format(GL_INT, GL_TRUE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT2:
+        {
+            static const VertexFormat format(GL_INT, GL_FALSE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT2_NORM:
+        {
+            static const VertexFormat format(GL_INT, GL_TRUE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT3:
+        {
+            static const VertexFormat format(GL_INT, GL_FALSE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT3_NORM:
+        {
+            static const VertexFormat format(GL_INT, GL_TRUE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT4:
+        {
+            static const VertexFormat format(GL_INT, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT4_NORM:
+        {
+            static const VertexFormat format(GL_INT, GL_TRUE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT1:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT1_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT2:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT2_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT3:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT3_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT4:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT4_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE1_INT:
+        {
+            static const VertexFormat format(GL_BYTE, GL_FALSE, 1, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE2_INT:
+        {
+            static const VertexFormat format(GL_BYTE, GL_FALSE, 2, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE3_INT:
+        {
+            static const VertexFormat format(GL_BYTE, GL_FALSE, 3, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SBYTE4_INT:
+        {
+            static const VertexFormat format(GL_BYTE, GL_FALSE, 4, true);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE1_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 1, true);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE2_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 2, true);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE3_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 3, true);
+            return format;
+        }
+        case VERTEX_FORMAT_UBYTE4_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 4, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT1_INT:
+        {
+            static const VertexFormat format(GL_SHORT, GL_FALSE, 1, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT2_INT:
+        {
+            static const VertexFormat format(GL_SHORT, GL_FALSE, 2, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT3_INT:
+        {
+            static const VertexFormat format(GL_SHORT, GL_FALSE, 3, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SSHORT4_INT:
+        {
+            static const VertexFormat format(GL_SHORT, GL_FALSE, 4, true);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT1_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 1, true);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT2_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 2, true);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT3_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 3, true);
+            return format;
+        }
+        case VERTEX_FORMAT_USHORT4_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 4, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT1_INT:
+        {
+            static const VertexFormat format(GL_INT, GL_FALSE, 1, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT2_INT:
+        {
+            static const VertexFormat format(GL_INT, GL_FALSE, 2, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT3_INT:
+        {
+            static const VertexFormat format(GL_INT, GL_FALSE, 3, true);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT4_INT:
+        {
+            static const VertexFormat format(GL_INT, GL_FALSE, 4, true);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT1_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 1, true);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT2_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 2, true);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT3_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 3, true);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT4_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 4, true);
+            return format;
+        }
+        case VERTEX_FORMAT_FIXED1:
+        {
+            static const VertexFormat format(GL_FIXED, GL_FALSE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_FIXED2:
+        {
+            static const VertexFormat format(GL_FIXED, GL_FALSE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_FIXED3:
+        {
+            static const VertexFormat format(GL_FIXED, GL_FALSE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_FIXED4:
+        {
+            static const VertexFormat format(GL_FIXED, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_HALF1:
+        {
+            static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_HALF2:
+        {
+            static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_HALF3:
+        {
+            static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_HALF4:
+        {
+            static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_FLOAT1:
+        {
+            static const VertexFormat format(GL_FLOAT, GL_FALSE, 1, false);
+            return format;
+        }
+        case VERTEX_FORMAT_FLOAT2:
+        {
+            static const VertexFormat format(GL_FLOAT, GL_FALSE, 2, false);
+            return format;
+        }
+        case VERTEX_FORMAT_FLOAT3:
+        {
+            static const VertexFormat format(GL_FLOAT, GL_FALSE, 3, false);
+            return format;
+        }
+        case VERTEX_FORMAT_FLOAT4:
+        {
+            static const VertexFormat format(GL_FLOAT, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT210:
+        {
+            static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT210:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT210_NORM:
+        {
+            static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_TRUE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT210_NORM:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, false);
+            return format;
+        }
+        case VERTEX_FORMAT_SINT210_INT:
+        {
+            static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_FALSE, 4, true);
+            return format;
+        }
+        case VERTEX_FORMAT_UINT210_INT:
+        {
+            static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, true);
+            return format;
+        }
+        default:
+        {
+            static const VertexFormat format(GL_NONE, GL_FALSE, 0, false);
+            return format;
+        }
+    }
+}
+
+size_t GetVertexFormatTypeSize(VertexFormatType vertexFormatType)
+{
+    switch (vertexFormatType)
+    {
+        case VERTEX_FORMAT_SBYTE1:
+        case VERTEX_FORMAT_SBYTE1_NORM:
+        case VERTEX_FORMAT_UBYTE1:
+        case VERTEX_FORMAT_UBYTE1_NORM:
+        case VERTEX_FORMAT_SBYTE1_INT:
+        case VERTEX_FORMAT_UBYTE1_INT:
+            return 1;
+
+        case VERTEX_FORMAT_SBYTE2:
+        case VERTEX_FORMAT_SBYTE2_NORM:
+        case VERTEX_FORMAT_UBYTE2:
+        case VERTEX_FORMAT_UBYTE2_NORM:
+        case VERTEX_FORMAT_SBYTE2_INT:
+        case VERTEX_FORMAT_UBYTE2_INT:
+        case VERTEX_FORMAT_SSHORT1:
+        case VERTEX_FORMAT_SSHORT1_NORM:
+        case VERTEX_FORMAT_USHORT1:
+        case VERTEX_FORMAT_USHORT1_NORM:
+        case VERTEX_FORMAT_SSHORT1_INT:
+        case VERTEX_FORMAT_USHORT1_INT:
+        case VERTEX_FORMAT_HALF1:
+            return 2;
+
+        case VERTEX_FORMAT_SBYTE3:
+        case VERTEX_FORMAT_SBYTE3_NORM:
+        case VERTEX_FORMAT_UBYTE3:
+        case VERTEX_FORMAT_UBYTE3_NORM:
+        case VERTEX_FORMAT_SBYTE3_INT:
+        case VERTEX_FORMAT_UBYTE3_INT:
+            return 3;
+
+        case VERTEX_FORMAT_SBYTE4:
+        case VERTEX_FORMAT_SBYTE4_NORM:
+        case VERTEX_FORMAT_UBYTE4:
+        case VERTEX_FORMAT_UBYTE4_NORM:
+        case VERTEX_FORMAT_SBYTE4_INT:
+        case VERTEX_FORMAT_UBYTE4_INT:
+        case VERTEX_FORMAT_SSHORT2:
+        case VERTEX_FORMAT_SSHORT2_NORM:
+        case VERTEX_FORMAT_USHORT2:
+        case VERTEX_FORMAT_USHORT2_NORM:
+        case VERTEX_FORMAT_SSHORT2_INT:
+        case VERTEX_FORMAT_USHORT2_INT:
+        case VERTEX_FORMAT_SINT1:
+        case VERTEX_FORMAT_SINT1_NORM:
+        case VERTEX_FORMAT_UINT1:
+        case VERTEX_FORMAT_UINT1_NORM:
+        case VERTEX_FORMAT_SINT1_INT:
+        case VERTEX_FORMAT_UINT1_INT:
+        case VERTEX_FORMAT_HALF2:
+        case VERTEX_FORMAT_FIXED1:
+        case VERTEX_FORMAT_FLOAT1:
+        case VERTEX_FORMAT_SINT210:
+        case VERTEX_FORMAT_UINT210:
+        case VERTEX_FORMAT_SINT210_NORM:
+        case VERTEX_FORMAT_UINT210_NORM:
+        case VERTEX_FORMAT_SINT210_INT:
+        case VERTEX_FORMAT_UINT210_INT:
+            return 4;
+
+        case VERTEX_FORMAT_SSHORT3:
+        case VERTEX_FORMAT_SSHORT3_NORM:
+        case VERTEX_FORMAT_USHORT3:
+        case VERTEX_FORMAT_USHORT3_NORM:
+        case VERTEX_FORMAT_SSHORT3_INT:
+        case VERTEX_FORMAT_USHORT3_INT:
+        case VERTEX_FORMAT_HALF3:
+            return 6;
+
+        case VERTEX_FORMAT_SSHORT4:
+        case VERTEX_FORMAT_SSHORT4_NORM:
+        case VERTEX_FORMAT_USHORT4:
+        case VERTEX_FORMAT_USHORT4_NORM:
+        case VERTEX_FORMAT_SSHORT4_INT:
+        case VERTEX_FORMAT_USHORT4_INT:
+        case VERTEX_FORMAT_SINT2:
+        case VERTEX_FORMAT_SINT2_NORM:
+        case VERTEX_FORMAT_UINT2:
+        case VERTEX_FORMAT_UINT2_NORM:
+        case VERTEX_FORMAT_SINT2_INT:
+        case VERTEX_FORMAT_UINT2_INT:
+        case VERTEX_FORMAT_HALF4:
+        case VERTEX_FORMAT_FIXED2:
+        case VERTEX_FORMAT_FLOAT2:
+            return 8;
+
+        case VERTEX_FORMAT_SINT3:
+        case VERTEX_FORMAT_SINT3_NORM:
+        case VERTEX_FORMAT_UINT3:
+        case VERTEX_FORMAT_UINT3_NORM:
+        case VERTEX_FORMAT_SINT3_INT:
+        case VERTEX_FORMAT_UINT3_INT:
+        case VERTEX_FORMAT_FIXED3:
+        case VERTEX_FORMAT_FLOAT3:
+            return 12;
+
+        case VERTEX_FORMAT_SINT4:
+        case VERTEX_FORMAT_SINT4_NORM:
+        case VERTEX_FORMAT_UINT4:
+        case VERTEX_FORMAT_UINT4_NORM:
+        case VERTEX_FORMAT_SINT4_INT:
+        case VERTEX_FORMAT_UINT4_INT:
+        case VERTEX_FORMAT_FIXED4:
+        case VERTEX_FORMAT_FLOAT4:
+            return 16;
+
+        case VERTEX_FORMAT_INVALID:
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+bool ValidES3InternalFormat(GLenum internalFormat)
+{
+    const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+    return internalFormat != GL_NONE && formatMap.find(internalFormat) != formatMap.end();
+}
+
+VertexFormat::VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn)
+    : type(typeIn),
+      normalized(normalizedIn),
+      components(componentsIn),
+      pureInteger(pureIntegerIn)
+{
+    // float -> !normalized
+    ASSERT(!(type == GL_FLOAT || type == GL_HALF_FLOAT || type == GL_FIXED) || normalized == GL_FALSE);
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/formatutils.h b/src/third_party/angle/src/libANGLE/formatutils.h
new file mode 100644
index 0000000..68c5aa7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/formatutils.h
@@ -0,0 +1,322 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils.h: Queries for GL image formats.
+
+#ifndef LIBANGLE_FORMATUTILS_H_
+#define LIBANGLE_FORMATUTILS_H_
+
+#include <cstddef>
+#include <ostream>
+#include <stdint.h>
+
+#include "angle_gl.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+struct VertexAttribute;
+
+struct FormatType final
+{
+    FormatType();
+    FormatType(GLenum format_, GLenum type_);
+    FormatType(const FormatType &other) = default;
+    FormatType &operator=(const FormatType &other) = default;
+
+    bool operator<(const FormatType &other) const;
+
+    GLenum format;
+    GLenum type;
+};
+
+struct Type
+{
+    Type();
+
+    GLuint bytes;
+    GLuint bytesShift; // Bit shift by this value to effectively divide/multiply by "bytes" in a more optimal way
+    bool specialInterpretation;
+};
+const Type &GetTypeInfo(GLenum type);
+
+// Information about an OpenGL internal format.  Can be keyed on the internalFormat and type
+// members.
+struct InternalFormat
+{
+    InternalFormat();
+
+    GLuint computePixelBytes(GLenum formatType) const;
+
+    ErrorOrResult<GLuint> computeRowPitch(GLenum formatType,
+                                          GLsizei width,
+                                          GLint alignment,
+                                          GLint rowLength) const;
+    ErrorOrResult<GLuint> computeDepthPitch(GLsizei height,
+                                            GLint imageHeight,
+                                            GLuint rowPitch) const;
+    ErrorOrResult<GLuint> computeDepthPitch(GLenum formatType,
+                                            GLsizei width,
+                                            GLsizei height,
+                                            GLint alignment,
+                                            GLint rowLength,
+                                            GLint imageHeight) const;
+
+    ErrorOrResult<GLuint> computeCompressedImageSize(GLenum formatType,
+                                                     const Extents &size) const;
+
+    ErrorOrResult<GLuint> computeSkipBytes(GLuint rowPitch,
+                                           GLuint depthPitch,
+                                           const PixelStoreStateBase &state,
+                                           bool is3D) const;
+
+    ErrorOrResult<GLuint> computePackUnpackEndByte(GLenum formatType,
+                                                       const Extents &size,
+                                                       const PixelStoreStateBase &state,
+                                                       bool is3D) const;
+
+    bool isLUMA() const;
+    GLenum getReadPixelsFormat() const;
+    GLenum getReadPixelsType() const;
+
+    bool operator==(const InternalFormat &other) const;
+    bool operator!=(const InternalFormat &other) const;
+
+    GLenum internalFormat;
+
+    bool sized;
+    GLenum sizedInternalFormat;
+
+    GLuint redBits;
+    GLuint greenBits;
+    GLuint blueBits;
+
+    GLuint luminanceBits;
+
+    GLuint alphaBits;
+    GLuint sharedBits;
+
+    GLuint depthBits;
+    GLuint stencilBits;
+
+    GLuint pixelBytes;
+
+    GLuint componentCount;
+
+    bool compressed;
+    GLuint compressedBlockWidth;
+    GLuint compressedBlockHeight;
+
+    GLenum format;
+    GLenum type;
+
+    GLenum componentType;
+    GLenum colorEncoding;
+
+    typedef bool (*SupportCheckFunction)(const Version &, const Extensions &);
+    SupportCheckFunction textureSupport;
+    SupportCheckFunction renderSupport;
+    SupportCheckFunction filterSupport;
+};
+
+// A "Format" wraps an InternalFormat struct, querying it from either a sized internal format or
+// unsized internal format and type.
+// TODO(geofflang): Remove this, it doesn't add any more information than the InternalFormat object.
+struct Format
+{
+    // Sized types only.
+    explicit Format(GLenum internalFormat);
+
+    // Sized or unsized types.
+    explicit Format(const InternalFormat &internalFormat);
+    Format(GLenum internalFormat, GLenum type);
+
+    Format(const Format &other);
+    Format &operator=(const Format &other);
+
+    bool valid() const;
+
+    static Format Invalid();
+    static bool SameSized(const Format &a, const Format &b);
+
+    friend std::ostream &operator<<(std::ostream &os, const Format &fmt);
+
+    // This is the sized info.
+    const InternalFormat *info;
+};
+
+const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat);
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type);
+
+// Strip sizing information from an internal format.  Doesn't necessarily validate that the internal
+// format is valid.
+GLenum GetUnsizedFormat(GLenum internalFormat);
+
+typedef std::set<GLenum> FormatSet;
+const FormatSet &GetAllSizedInternalFormats();
+
+// From the ESSL 3.00.4 spec:
+// Vertex shader inputs can only be float, floating-point vectors, matrices, signed and unsigned
+// integers and integer vectors. Vertex shader inputs cannot be arrays or structures.
+
+enum AttributeType
+{
+    ATTRIBUTE_FLOAT,
+    ATTRIBUTE_VEC2,
+    ATTRIBUTE_VEC3,
+    ATTRIBUTE_VEC4,
+    ATTRIBUTE_INT,
+    ATTRIBUTE_IVEC2,
+    ATTRIBUTE_IVEC3,
+    ATTRIBUTE_IVEC4,
+    ATTRIBUTE_UINT,
+    ATTRIBUTE_UVEC2,
+    ATTRIBUTE_UVEC3,
+    ATTRIBUTE_UVEC4,
+    ATTRIBUTE_MAT2,
+    ATTRIBUTE_MAT3,
+    ATTRIBUTE_MAT4,
+    ATTRIBUTE_MAT2x3,
+    ATTRIBUTE_MAT2x4,
+    ATTRIBUTE_MAT3x2,
+    ATTRIBUTE_MAT3x4,
+    ATTRIBUTE_MAT4x2,
+    ATTRIBUTE_MAT4x3,
+};
+
+AttributeType GetAttributeType(GLenum enumValue);
+
+enum VertexFormatType
+{
+    VERTEX_FORMAT_INVALID,
+    VERTEX_FORMAT_SBYTE1,
+    VERTEX_FORMAT_SBYTE1_NORM,
+    VERTEX_FORMAT_SBYTE2,
+    VERTEX_FORMAT_SBYTE2_NORM,
+    VERTEX_FORMAT_SBYTE3,
+    VERTEX_FORMAT_SBYTE3_NORM,
+    VERTEX_FORMAT_SBYTE4,
+    VERTEX_FORMAT_SBYTE4_NORM,
+    VERTEX_FORMAT_UBYTE1,
+    VERTEX_FORMAT_UBYTE1_NORM,
+    VERTEX_FORMAT_UBYTE2,
+    VERTEX_FORMAT_UBYTE2_NORM,
+    VERTEX_FORMAT_UBYTE3,
+    VERTEX_FORMAT_UBYTE3_NORM,
+    VERTEX_FORMAT_UBYTE4,
+    VERTEX_FORMAT_UBYTE4_NORM,
+    VERTEX_FORMAT_SSHORT1,
+    VERTEX_FORMAT_SSHORT1_NORM,
+    VERTEX_FORMAT_SSHORT2,
+    VERTEX_FORMAT_SSHORT2_NORM,
+    VERTEX_FORMAT_SSHORT3,
+    VERTEX_FORMAT_SSHORT3_NORM,
+    VERTEX_FORMAT_SSHORT4,
+    VERTEX_FORMAT_SSHORT4_NORM,
+    VERTEX_FORMAT_USHORT1,
+    VERTEX_FORMAT_USHORT1_NORM,
+    VERTEX_FORMAT_USHORT2,
+    VERTEX_FORMAT_USHORT2_NORM,
+    VERTEX_FORMAT_USHORT3,
+    VERTEX_FORMAT_USHORT3_NORM,
+    VERTEX_FORMAT_USHORT4,
+    VERTEX_FORMAT_USHORT4_NORM,
+    VERTEX_FORMAT_SINT1,
+    VERTEX_FORMAT_SINT1_NORM,
+    VERTEX_FORMAT_SINT2,
+    VERTEX_FORMAT_SINT2_NORM,
+    VERTEX_FORMAT_SINT3,
+    VERTEX_FORMAT_SINT3_NORM,
+    VERTEX_FORMAT_SINT4,
+    VERTEX_FORMAT_SINT4_NORM,
+    VERTEX_FORMAT_UINT1,
+    VERTEX_FORMAT_UINT1_NORM,
+    VERTEX_FORMAT_UINT2,
+    VERTEX_FORMAT_UINT2_NORM,
+    VERTEX_FORMAT_UINT3,
+    VERTEX_FORMAT_UINT3_NORM,
+    VERTEX_FORMAT_UINT4,
+    VERTEX_FORMAT_UINT4_NORM,
+    VERTEX_FORMAT_SBYTE1_INT,
+    VERTEX_FORMAT_SBYTE2_INT,
+    VERTEX_FORMAT_SBYTE3_INT,
+    VERTEX_FORMAT_SBYTE4_INT,
+    VERTEX_FORMAT_UBYTE1_INT,
+    VERTEX_FORMAT_UBYTE2_INT,
+    VERTEX_FORMAT_UBYTE3_INT,
+    VERTEX_FORMAT_UBYTE4_INT,
+    VERTEX_FORMAT_SSHORT1_INT,
+    VERTEX_FORMAT_SSHORT2_INT,
+    VERTEX_FORMAT_SSHORT3_INT,
+    VERTEX_FORMAT_SSHORT4_INT,
+    VERTEX_FORMAT_USHORT1_INT,
+    VERTEX_FORMAT_USHORT2_INT,
+    VERTEX_FORMAT_USHORT3_INT,
+    VERTEX_FORMAT_USHORT4_INT,
+    VERTEX_FORMAT_SINT1_INT,
+    VERTEX_FORMAT_SINT2_INT,
+    VERTEX_FORMAT_SINT3_INT,
+    VERTEX_FORMAT_SINT4_INT,
+    VERTEX_FORMAT_UINT1_INT,
+    VERTEX_FORMAT_UINT2_INT,
+    VERTEX_FORMAT_UINT3_INT,
+    VERTEX_FORMAT_UINT4_INT,
+    VERTEX_FORMAT_FIXED1,
+    VERTEX_FORMAT_FIXED2,
+    VERTEX_FORMAT_FIXED3,
+    VERTEX_FORMAT_FIXED4,
+    VERTEX_FORMAT_HALF1,
+    VERTEX_FORMAT_HALF2,
+    VERTEX_FORMAT_HALF3,
+    VERTEX_FORMAT_HALF4,
+    VERTEX_FORMAT_FLOAT1,
+    VERTEX_FORMAT_FLOAT2,
+    VERTEX_FORMAT_FLOAT3,
+    VERTEX_FORMAT_FLOAT4,
+    VERTEX_FORMAT_SINT210,
+    VERTEX_FORMAT_UINT210,
+    VERTEX_FORMAT_SINT210_NORM,
+    VERTEX_FORMAT_UINT210_NORM,
+    VERTEX_FORMAT_SINT210_INT,
+    VERTEX_FORMAT_UINT210_INT,
+};
+
+typedef std::vector<VertexFormatType> InputLayout;
+
+struct VertexFormat : private angle::NonCopyable
+{
+    VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn);
+
+    GLenum type;
+    GLboolean normalized;
+    GLuint components;
+    bool pureInteger;
+};
+
+VertexFormatType GetVertexFormatType(GLenum type, GLboolean normalized, GLuint components, bool pureInteger);
+VertexFormatType GetVertexFormatType(const VertexAttribute &attrib);
+VertexFormatType GetVertexFormatType(const VertexAttribute &attrib, GLenum currentValueType);
+const VertexFormat &GetVertexFormatFromType(VertexFormatType vertexFormatType);
+size_t GetVertexFormatTypeSize(VertexFormatType vertexFormatType);
+
+// Check if an internal format is ever valid in ES3.  Makes no checks about support for a specific
+// context.
+bool ValidES3InternalFormat(GLenum internalFormat);
+
+// Implemented in format_map_autogen.cpp
+bool ValidES3Format(GLenum format);
+bool ValidES3Type(GLenum type);
+bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat);
+
+// Implemented in es3_copy_conversion_table_autogen.cpp
+bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
+
+}  // namespace gl
+
+#endif // LIBANGLE_FORMATUTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/gen_copy_conversion_table.py b/src/third_party/angle/src/libANGLE/gen_copy_conversion_table.py
new file mode 100644
index 0000000..f2c9603
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/gen_copy_conversion_table.py
@@ -0,0 +1,91 @@
+#!/usr/bin/python
+# Copyright 2016 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.
+#
+# gen_copy_conversion_table.py:
+#  Code generation for ES3 valid copy conversions table format map.
+
+from datetime import date
+import sys
+
+sys.path.append('renderer')
+import angle_format
+
+template_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+//
+// Copyright {copyright_year} 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.
+//
+// format_map:
+//   Determining the sized internal format from a (format,type) pair.
+//   Also check es3 format combinations for validity.
+
+#include "angle_gl.h"
+#include "common/debug.h"
+
+namespace gl
+{{
+
+bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
+{{
+    switch (textureFormat)
+    {{
+{texture_format_cases}        default:
+            break;
+    }}
+
+    return false;
+}}
+
+}}  // namespace gl
+"""
+
+template_format_case = """        case {texture_format}:
+            switch (framebufferFormat)
+            {{
+{framebuffer_format_cases}                    return true;
+                default:
+                    break;
+            }}
+            break;
+
+"""
+
+template_simple_case = """                case {key}:
+"""
+
+def parse_texture_format_case(texture_format, framebuffer_formats):
+    framebuffer_format_cases = ""
+    for framebuffer_format in sorted(framebuffer_formats):
+        framebuffer_format_cases += template_simple_case.format(key = framebuffer_format)
+    return template_format_case.format(
+        texture_format = texture_format, framebuffer_format_cases = framebuffer_format_cases)
+
+data_source_name = 'es3_copy_conversion_formats.json'
+
+json_data = angle_format.load_json(data_source_name)
+
+format_map = {}
+
+for description, data in json_data.iteritems():
+    for texture_format, framebuffer_format in data:
+        if texture_format not in format_map:
+            format_map[texture_format] = []
+        format_map[texture_format] += [ framebuffer_format ]
+
+texture_format_cases = ""
+
+for texture_format, framebuffer_formats in sorted(format_map.iteritems()):
+    texture_format_cases += parse_texture_format_case(texture_format, framebuffer_formats)
+
+with open('es3_copy_conversion_table_autogen.cpp', 'wt') as out_file:
+    output_cpp = template_cpp.format(
+        script_name = sys.argv[0],
+        data_source_name = data_source_name,
+        copyright_year = date.today().year,
+        texture_format_cases = texture_format_cases)
+    out_file.write(output_cpp)
+    out_file.close()
diff --git a/src/third_party/angle/src/libANGLE/gen_format_map.py b/src/third_party/angle/src/libANGLE/gen_format_map.py
new file mode 100644
index 0000000..b67f427
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/gen_format_map.py
@@ -0,0 +1,187 @@
+#!/usr/bin/python
+# Copyright 2016 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.
+#
+# gen_format_map.py:
+#  Code generation for GL format map. The format map matches between
+#  {format,type} and internal format.
+
+from datetime import date
+import sys
+
+sys.path.append('renderer')
+import angle_format
+
+template_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+// ES3 format info from {es3_data_source_name}.
+//
+// Copyright {copyright_year} 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.
+//
+// format_map:
+//   Determining the sized internal format from a (format,type) pair.
+//   Also check es3 format combinations for validity.
+
+#include "angle_gl.h"
+#include "common/debug.h"
+
+namespace gl
+{{
+
+GLenum GetSizedFormatInternal(GLenum format, GLenum type)
+{{
+    switch (format)
+    {{
+{format_cases}        case GL_NONE:
+            return GL_NONE;
+
+        default:
+            break;
+    }}
+
+    return GL_NONE;
+}}
+
+bool ValidES3Format(GLenum format)
+{{
+    switch (format)
+    {{
+{es3_format_cases}            return true;
+
+        default:
+            return false;
+    }}
+}}
+
+bool ValidES3Type(GLenum type)
+{{
+    switch (type)
+    {{
+{es3_type_cases}            return true;
+
+        default:
+            return false;
+    }}
+}}
+
+bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat)
+{{
+    ASSERT(ValidES3Format(format) && ValidES3Type(type));
+
+    switch (format)
+    {{
+{es3_combo_cases}        default:
+            UNREACHABLE();
+            break;
+    }}
+
+    return false;
+}}
+
+}}  // namespace gl
+"""
+
+template_format_case = """        case {format}:
+            switch (type)
+            {{
+{type_cases}                default:
+                    break;
+            }}
+            break;
+
+"""
+
+template_simple_case = """                case {key}:
+                    return {result};
+"""
+
+template_es3_combo_type_case = """                case {type}:
+                {{
+                    switch (internalFormat)
+                    {{
+{internal_format_cases}                            return true;
+                        default:
+                            break;
+                    }}
+                    break;
+                }}
+"""
+
+def parse_type_case(type, result):
+    return template_simple_case.format(
+        key = type, result = result)
+
+def parse_format_case(format, type_map):
+    type_cases = ""
+    for type, internal_format in sorted(type_map.iteritems()):
+        type_cases += parse_type_case(type, internal_format)
+    return template_format_case.format(
+        format = format, type_cases = type_cases)
+
+input_script = 'format_map_data.json'
+
+format_map = angle_format.load_json(input_script)
+
+format_cases = ""
+
+for format, type_map in sorted(format_map.iteritems()):
+    format_cases += parse_format_case(format, type_map)
+
+combo_data_file = 'es3_format_type_combinations.json'
+es3_combo_data = angle_format.load_json(combo_data_file)
+combo_data = [combo for sublist in es3_combo_data.values() for combo in sublist]
+
+types = set()
+formats = set()
+combos = {}
+
+for internal_format, format, type in combo_data:
+    types.update([type])
+    formats.update([format])
+    if format not in combos:
+        combos[format] = {}
+    if type not in combos[format]:
+        combos[format][type] = [internal_format]
+    else:
+        combos[format][type] += [internal_format]
+
+es3_format_cases = ""
+
+for format in sorted(formats):
+    es3_format_cases += "        case " + format + ":\n"
+
+es3_type_cases = ""
+
+for type in sorted(types):
+    es3_type_cases += "        case " + type + ":\n"
+
+es3_combo_cases = ""
+
+for format, type_combos in combos.iteritems():
+    this_type_cases = ""
+    for type, combos in type_combos.iteritems():
+        internal_format_cases = ""
+        for internal_format in combos:
+            internal_format_cases += "                        case " + internal_format + ":\n"
+
+        this_type_cases += template_es3_combo_type_case.format(
+            type = type, internal_format_cases = internal_format_cases)
+
+    es3_combo_cases += template_format_case.format(
+        format = format, type_cases = this_type_cases)
+
+with open('format_map_autogen.cpp', 'wt') as out_file:
+    output_cpp = template_cpp.format(
+        script_name = sys.argv[0],
+        data_source_name = input_script,
+        es3_data_source_name = combo_data_file,
+        copyright_year = date.today().year,
+        format_cases = format_cases,
+        es3_format_cases = es3_format_cases,
+        es3_type_cases = es3_type_cases,
+        es3_combo_cases = es3_combo_cases)
+    out_file.write(output_cpp)
+    out_file.close()
diff --git a/src/third_party/angle/src/libANGLE/histogram_macros.h b/src/third_party/angle/src/libANGLE/histogram_macros.h
new file mode 100644
index 0000000..733b113
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/histogram_macros.h
@@ -0,0 +1,112 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// histogram_macros.h:
+//   Helpers for making histograms, to keep consistency with Chromium's
+//   histogram_macros.h.
+
+#ifndef LIBANGLE_HISTOGRAM_MACROS_H_
+#define LIBANGLE_HISTOGRAM_MACROS_H_
+
+#include <platform/Platform.h>
+
+#define ANGLE_HISTOGRAM_TIMES(name, sample) ANGLE_HISTOGRAM_CUSTOM_TIMES( \
+    name, sample, 1, 10000, 50)
+
+#define ANGLE_HISTOGRAM_MEDIUM_TIMES(name, sample) ANGLE_HISTOGRAM_CUSTOM_TIMES( \
+    name, sample, 10, 180000, 50)
+
+// Use this macro when times can routinely be much longer than 10 seconds.
+#define ANGLE_HISTOGRAM_LONG_TIMES(name, sample) ANGLE_HISTOGRAM_CUSTOM_TIMES( \
+    name, sample, 1, 3600000, 50)
+
+// Use this macro when times can routinely be much longer than 10 seconds and
+// you want 100 buckets.
+#define ANGLE_HISTOGRAM_LONG_TIMES_100(name, sample) ANGLE_HISTOGRAM_CUSTOM_TIMES( \
+    name, sample, 1, 3600000, 100)
+
+// For folks that need real specific times, use this to select a precise range
+// of times you want plotted, and the number of buckets you want used.
+#define ANGLE_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
+    ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count)
+
+#define ANGLE_HISTOGRAM_COUNTS(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \
+    name, sample, 1, 1000000, 50)
+
+#define ANGLE_HISTOGRAM_COUNTS_100(name, sample) \
+    ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 100, 50)
+
+#define ANGLE_HISTOGRAM_COUNTS_10000(name, sample) \
+    ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 10000, 50)
+
+#define ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count)                       \
+    ANGLEPlatformCurrent()->histogramCustomCounts(ANGLEPlatformCurrent(), name, sample, min, max, \
+                                                  bucket_count)
+
+#define ANGLE_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
+    ANGLE_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
+
+#define ANGLE_HISTOGRAM_BOOLEAN(name, sample) \
+    ANGLEPlatformCurrent()->histogramBoolean(ANGLEPlatformCurrent(), name, sample)
+
+#define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value)                      \
+    ANGLEPlatformCurrent()->histogramEnumeration(ANGLEPlatformCurrent(), name, sample, \
+                                                 boundary_value)
+
+#define ANGLE_HISTOGRAM_MEMORY_KB(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \
+    name, sample, 1000, 500000, 50)
+
+#define ANGLE_HISTOGRAM_MEMORY_MB(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \
+    name, sample, 1, 1000, 50)
+
+#define ANGLE_HISTOGRAM_SPARSE_SLOWLY(name, sample) \
+    ANGLEPlatformCurrent()->histogramSparse(ANGLEPlatformCurrent(), name, sample)
+
+// Scoped class which logs its time on this earth as a UMA statistic. This is
+// recommended for when you want a histogram which measures the time it takes
+// for a method to execute. This measures up to 10 seconds.
+#define SCOPED_ANGLE_HISTOGRAM_TIMER(name) \
+    SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, false, __COUNTER__)
+
+// Similar scoped histogram timer, but this uses ANGLE_HISTOGRAM_LONG_TIMES_100,
+// which measures up to an hour, and uses 100 buckets. This is more expensive
+// to store, so only use if this often takes >10 seconds.
+#define SCOPED_ANGLE_HISTOGRAM_LONG_TIMER(name) \
+    SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, true, __COUNTER__)
+
+// This nested macro is necessary to expand __COUNTER__ to an actual value.
+#define SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \
+    SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key)
+
+#define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key)                         \
+    class ScopedHistogramTimer##key                                                     \
+    {                                                                                   \
+      public:                                                                           \
+        ScopedHistogramTimer##key()                                                     \
+            : constructed_(ANGLEPlatformCurrent()->currentTime(ANGLEPlatformCurrent())) \
+        {                                                                               \
+        }                                                                               \
+        ~ScopedHistogramTimer##key()                                                    \
+        {                                                                               \
+            if (constructed_ == 0)                                                      \
+                return;                                                                 \
+            auto *platform = ANGLEPlatformCurrent();                                    \
+            double elapsed = platform->currentTime(platform) - constructed_;            \
+            int elapsedMS  = static_cast<int>(elapsed * 1000.0);                        \
+            if (is_long)                                                                \
+            {                                                                           \
+                ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS);                        \
+            }                                                                           \
+            else                                                                        \
+            {                                                                           \
+                ANGLE_HISTOGRAM_TIMES(name, elapsedMS);                                 \
+            }                                                                           \
+        }                                                                               \
+                                                                                        \
+      private:                                                                          \
+        double constructed_;                                                            \
+    } scoped_histogram_timer_##key
+
+#endif  // BASE_METRICS_HISTOGRAM_MACROS_H_
diff --git a/src/third_party/angle/src/libANGLE/params.cpp b/src/third_party/angle/src/libANGLE/params.cpp
new file mode 100644
index 0000000..18f8faa
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/params.cpp
@@ -0,0 +1,67 @@
+//
+// Copyright 2017 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.
+//
+// params:
+//   Parameter wrapper structs for OpenGL ES. These helpers cache re-used values
+//   in entry point routines.
+
+#include "libANGLE/params.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/VertexArray.h"
+
+namespace gl
+{
+
+// static
+constexpr ParamTypeInfo ParamsBase::TypeInfo;
+constexpr ParamTypeInfo HasIndexRange::TypeInfo;
+
+ParamsBase::ParamsBase(Context *context, ...)
+{
+}
+
+HasIndexRange::HasIndexRange(Context *context, GLsizei count, GLenum type, const void *indices)
+    : ParamsBase(context), mContext(context), mCount(count), mType(type), mIndices(indices)
+{
+}
+
+const Optional<IndexRange> &HasIndexRange::getIndexRange() const
+{
+    if (mIndexRange.valid())
+    {
+        return mIndexRange;
+    }
+
+    const State &state = mContext->getGLState();
+
+    const gl::VertexArray *vao     = state.getVertexArray();
+    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+    if (elementArrayBuffer)
+    {
+        uintptr_t offset = reinterpret_cast<uintptr_t>(mIndices);
+        IndexRange indexRange;
+        Error error =
+            elementArrayBuffer->getIndexRange(mType, static_cast<size_t>(offset), mCount,
+                                              state.isPrimitiveRestartEnabled(), &indexRange);
+        if (error.isError())
+        {
+            mContext->handleError(error);
+            return mIndexRange;
+        }
+
+        mIndexRange = indexRange;
+    }
+    else
+    {
+        mIndexRange = ComputeIndexRange(mType, mIndices, mCount, state.isPrimitiveRestartEnabled());
+    }
+
+    return mIndexRange;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/params.h b/src/third_party/angle/src/libANGLE/params.h
new file mode 100644
index 0000000..32a5795
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/params.h
@@ -0,0 +1,169 @@
+//
+// Copyright 2017 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.
+//
+// params:
+//   Parameter wrapper structs for OpenGL ES. These helpers cache re-used values
+//   in entry point routines.
+
+#ifndef LIBANGLE_PARAMS_H_
+#define LIBANGLE_PARAMS_H_
+
+#include "angle_gl.h"
+#include "common/Optional.h"
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+template <EntryPoint EP>
+struct EntryPointParam;
+
+template <EntryPoint EP>
+using EntryPointParamType = typename EntryPointParam<EP>::Type;
+
+class ParamTypeInfo
+{
+  public:
+    constexpr ParamTypeInfo(const char *selfClass, const ParamTypeInfo *parentType)
+        : mSelfClass(selfClass), mParentTypeInfo(parentType)
+    {
+    }
+
+    constexpr bool hasDynamicType(const ParamTypeInfo &typeInfo) const
+    {
+        return mSelfClass == typeInfo.mSelfClass ||
+               (mParentTypeInfo && mParentTypeInfo->hasDynamicType(typeInfo));
+    }
+
+    constexpr bool isValid() const { return mSelfClass != nullptr; }
+
+  private:
+    const char *mSelfClass;
+    const ParamTypeInfo *mParentTypeInfo;
+};
+
+#define ANGLE_PARAM_TYPE_INFO(NAME, BASENAME) \
+    static constexpr ParamTypeInfo TypeInfo = {#NAME, &BASENAME::TypeInfo}
+
+class ParamsBase : angle::NonCopyable
+{
+  public:
+    ParamsBase(Context *context, ...);
+
+    template <EntryPoint EP, typename... ArgsT>
+    static void Factory(EntryPointParamType<EP> *objBuffer, ArgsT... args);
+
+    static constexpr ParamTypeInfo TypeInfo = {nullptr, nullptr};
+};
+
+// static
+template <EntryPoint EP, typename... ArgsT>
+void ParamsBase::Factory(EntryPointParamType<EP> *objBuffer, ArgsT... args)
+{
+    new (objBuffer) EntryPointParamType<EP>(args...);
+}
+
+class HasIndexRange : public ParamsBase
+{
+  public:
+    HasIndexRange(Context *context, GLsizei count, GLenum type, const void *indices);
+
+    template <EntryPoint EP, typename... ArgsT>
+    static void Factory(HasIndexRange *objBuffer, ArgsT... args);
+
+    const Optional<IndexRange> &getIndexRange() const;
+
+    ANGLE_PARAM_TYPE_INFO(HasIndexRange, ParamsBase);
+
+  private:
+    Context *mContext;
+    GLsizei mCount;
+    GLenum mType;
+    const GLvoid *mIndices;
+    mutable Optional<IndexRange> mIndexRange;
+};
+
+// Entry point funcs essentially re-map different entry point parameter arrays into
+// the format the parameter type class expects. For example, for HasIndexRange, for the
+// various indexed draw calls, they drop parameters that aren't useful and re-arrange
+// the rest.
+#define ANGLE_ENTRY_POINT_FUNC(NAME, CLASS, ...)    \
+    \
+template<> struct EntryPointParam<EntryPoint::NAME> \
+    {                                               \
+        using Type = CLASS;                         \
+    };                                              \
+    \
+template<> inline void CLASS::Factory<EntryPoint::NAME>(__VA_ARGS__)
+
+ANGLE_ENTRY_POINT_FUNC(DrawElements,
+                       HasIndexRange,
+                       HasIndexRange *objBuffer,
+                       Context *context,
+                       GLenum /*mode*/,
+                       GLsizei count,
+                       GLenum type,
+                       const void *indices)
+{
+    return ParamsBase::Factory<EntryPoint::DrawElements>(objBuffer, context, count, type, indices);
+}
+
+ANGLE_ENTRY_POINT_FUNC(DrawElementsInstanced,
+                       HasIndexRange,
+                       HasIndexRange *objBuffer,
+                       Context *context,
+                       GLenum /*mode*/,
+                       GLsizei count,
+                       GLenum type,
+                       const void *indices,
+                       GLsizei /*instanceCount*/)
+{
+    return ParamsBase::Factory<EntryPoint::DrawElementsInstanced>(objBuffer, context, count, type,
+                                                                  indices);
+}
+
+ANGLE_ENTRY_POINT_FUNC(DrawElementsInstancedANGLE,
+                       HasIndexRange,
+                       HasIndexRange *objBuffer,
+                       Context *context,
+                       GLenum /*mode*/,
+                       GLsizei count,
+                       GLenum type,
+                       const void *indices,
+                       GLsizei /*instanceCount*/)
+{
+    return ParamsBase::Factory<EntryPoint::DrawElementsInstancedANGLE>(objBuffer, context, count,
+                                                                       type, indices);
+}
+
+ANGLE_ENTRY_POINT_FUNC(DrawRangeElements,
+                       HasIndexRange,
+                       HasIndexRange *objBuffer,
+                       Context *context,
+                       GLenum /*mode*/,
+                       GLuint /*start*/,
+                       GLuint /*end*/,
+                       GLsizei count,
+                       GLenum type,
+                       const void *indices)
+{
+    return ParamsBase::Factory<EntryPoint::DrawRangeElements>(objBuffer, context, count, type,
+                                                              indices);
+}
+
+#undef ANGLE_ENTRY_POINT_FUNC
+
+template <EntryPoint EP>
+struct EntryPointParam
+{
+    using Type = ParamsBase;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_PARAMS_H_
diff --git a/src/third_party/angle/src/libANGLE/queryconversions.cpp b/src/third_party/angle/src/libANGLE/queryconversions.cpp
new file mode 100644
index 0000000..5beb809
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/queryconversions.cpp
@@ -0,0 +1,219 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// queryconversions.cpp: Implementation of state query cast conversions
+
+#include "libANGLE/queryconversions.h"
+
+#include <vector>
+
+#include "libANGLE/Context.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+namespace
+{
+
+GLint64 ExpandFloatToInteger(GLfloat value)
+{
+    return static_cast<GLint64>((static_cast<double>(0xFFFFFFFFULL) * value - 1.0) / 2.0);
+}
+
+template <typename QueryT>
+QueryT ClampToQueryRange(GLint64 value)
+{
+    const GLint64 min = static_cast<GLint64>(std::numeric_limits<QueryT>::min());
+    const GLint64 max = static_cast<GLint64>(std::numeric_limits<QueryT>::max());
+    return static_cast<QueryT>(clamp(value, min, max));
+}
+
+template <typename QueryT, typename NativeT>
+QueryT CastStateValueToInt(GLenum pname, NativeT value)
+{
+    GLenum queryType  = GLTypeToGLenum<QueryT>::value;
+    GLenum nativeType = GLTypeToGLenum<NativeT>::value;
+
+    if (nativeType == GL_FLOAT)
+    {
+        // RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from Table 4.5
+        if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
+        {
+            return ClampToQueryRange<QueryT>(ExpandFloatToInteger(static_cast<GLfloat>(value)));
+        }
+        else
+        {
+            return gl::iround<QueryT>(static_cast<GLfloat>(value));
+        }
+    }
+
+    // Clamp 64-bit int values when casting to int
+    if (nativeType == GL_INT_64_ANGLEX && queryType == GL_INT)
+    {
+        GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::min());
+        GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::max());
+        GLint64 clampedValue = std::max(std::min(static_cast<GLint64>(value), maxIntValue), minIntValue);
+        return static_cast<QueryT>(clampedValue);
+    }
+
+    return static_cast<QueryT>(value);
+}
+
+template <typename QueryT, typename NativeT>
+QueryT CastStateValue(GLenum pname, NativeT value)
+{
+    GLenum queryType = GLTypeToGLenum<QueryT>::value;
+
+    switch (queryType)
+    {
+        case GL_INT:
+            return CastStateValueToInt<QueryT, NativeT>(pname, value);
+        case GL_INT_64_ANGLEX:
+            return CastStateValueToInt<QueryT, NativeT>(pname, value);
+        case GL_FLOAT:
+            return static_cast<QueryT>(value);
+        case GL_BOOL:
+            return static_cast<QueryT>(value == static_cast<NativeT>(0) ? GL_FALSE : GL_TRUE);
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+}  // anonymous namespace
+
+template <typename QueryT>
+void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
+                     unsigned int numParams, QueryT *outParams)
+{
+    if (nativeType == GL_INT)
+    {
+        std::vector<GLint> intParams(numParams, 0);
+        context->getIntegervImpl(pname, intParams.data());
+
+        for (unsigned int i = 0; i < numParams; ++i)
+        {
+            outParams[i] = CastStateValue<QueryT>(pname, intParams[i]);
+        }
+    }
+    else if (nativeType == GL_BOOL)
+    {
+        std::vector<GLboolean> boolParams(numParams, GL_FALSE);
+        context->getBooleanvImpl(pname, boolParams.data());
+
+        for (unsigned int i = 0; i < numParams; ++i)
+        {
+            outParams[i] = (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
+        }
+    }
+    else if (nativeType == GL_FLOAT)
+    {
+        std::vector<GLfloat> floatParams(numParams, 0.0f);
+        context->getFloatvImpl(pname, floatParams.data());
+
+        for (unsigned int i = 0; i < numParams; ++i)
+        {
+            outParams[i] = CastStateValue<QueryT>(pname, floatParams[i]);
+        }
+    }
+    else if (nativeType == GL_INT_64_ANGLEX)
+    {
+        std::vector<GLint64> int64Params(numParams, 0);
+        context->getInteger64v(pname, int64Params.data());
+
+        for (unsigned int i = 0; i < numParams; ++i)
+        {
+            outParams[i] = CastStateValue<QueryT>(pname, int64Params[i]);
+        }
+    }
+    else UNREACHABLE();
+}
+
+// Explicit template instantiation (how we export template functions in different files)
+// The calls below will make CastStateValues successfully link with the GL state query types
+// The GL state query API types are: bool, int, uint, float, int64
+
+template void CastStateValues<GLboolean>(Context *, GLenum, GLenum, unsigned int, GLboolean *);
+template void CastStateValues<GLint>(Context *, GLenum, GLenum, unsigned int, GLint *);
+template void CastStateValues<GLuint>(Context *, GLenum, GLenum, unsigned int, GLuint *);
+template void CastStateValues<GLfloat>(Context *, GLenum, GLenum, unsigned int, GLfloat *);
+template void CastStateValues<GLint64>(Context *, GLenum, GLenum, unsigned int, GLint64 *);
+
+template <typename QueryT>
+void CastIndexedStateValues(Context *context,
+                            GLenum nativeType,
+                            GLenum pname,
+                            GLuint index,
+                            unsigned int numParams,
+                            QueryT *outParams)
+{
+    if (nativeType == GL_INT)
+    {
+        std::vector<GLint> intParams(numParams, 0);
+        context->getIntegeri_v(pname, index, intParams.data());
+
+        for (unsigned int i = 0; i < numParams; ++i)
+        {
+            outParams[i] = CastStateValue<QueryT>(pname, intParams[i]);
+        }
+    }
+    else if (nativeType == GL_BOOL)
+    {
+        std::vector<GLboolean> boolParams(numParams, GL_FALSE);
+        context->getBooleani_v(pname, index, boolParams.data());
+
+        for (unsigned int i = 0; i < numParams; ++i)
+        {
+            outParams[i] =
+                (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
+        }
+    }
+    else if (nativeType == GL_INT_64_ANGLEX)
+    {
+        std::vector<GLint64> int64Params(numParams, 0);
+        context->getInteger64i_v(pname, index, int64Params.data());
+
+        for (unsigned int i = 0; i < numParams; ++i)
+        {
+            outParams[i] = CastStateValue<QueryT>(pname, int64Params[i]);
+        }
+    }
+    else
+        UNREACHABLE();
+}
+
+template void CastIndexedStateValues<GLboolean>(Context *,
+                                                GLenum,
+                                                GLenum,
+                                                GLuint index,
+                                                unsigned int,
+                                                GLboolean *);
+template void CastIndexedStateValues<GLint>(Context *,
+                                            GLenum,
+                                            GLenum,
+                                            GLuint index,
+                                            unsigned int,
+                                            GLint *);
+template void CastIndexedStateValues<GLuint>(Context *,
+                                             GLenum,
+                                             GLenum,
+                                             GLuint index,
+                                             unsigned int,
+                                             GLuint *);
+template void CastIndexedStateValues<GLfloat>(Context *,
+                                              GLenum,
+                                              GLenum,
+                                              GLuint index,
+                                              unsigned int,
+                                              GLfloat *);
+template void CastIndexedStateValues<GLint64>(Context *,
+                                              GLenum,
+                                              GLenum,
+                                              GLuint index,
+                                              unsigned int,
+                                              GLint64 *);
+}
diff --git a/src/third_party/angle/src/libANGLE/queryconversions.h b/src/third_party/angle/src/libANGLE/queryconversions.h
new file mode 100644
index 0000000..5b96a3e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/queryconversions.h
@@ -0,0 +1,70 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// queryconversions.h: Declaration of state query cast conversions
+
+#ifndef LIBANGLE_QUERY_CONVERSIONS_H_
+#define LIBANGLE_QUERY_CONVERSIONS_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+namespace gl
+{
+class Context;
+
+// Helper class for converting a GL type to a GLenum:
+// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap.
+// We restrict our use to CastStateValue, where it eliminates duplicate parameters.
+
+template <typename GLType>
+struct GLTypeToGLenum
+{
+    // static constexpr GLenum value;
+};
+
+template <>
+struct GLTypeToGLenum<GLint>
+{
+    static constexpr GLenum value = GL_INT;
+};
+template <>
+struct GLTypeToGLenum<GLuint>
+{
+    static constexpr GLenum value = GL_UNSIGNED_INT;
+};
+template <>
+struct GLTypeToGLenum<GLboolean>
+{
+    static constexpr GLenum value = GL_BOOL;
+};
+template <>
+struct GLTypeToGLenum<GLint64>
+{
+    static constexpr GLenum value = GL_INT_64_ANGLEX;
+};
+template <>
+struct GLTypeToGLenum<GLfloat>
+{
+    static constexpr GLenum value = GL_FLOAT;
+};
+
+// The GL state query API types are: bool, int, uint, float, int64
+template <typename QueryT>
+void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
+                     unsigned int numParams, QueryT *outParams);
+
+// The GL state query API types are: bool, int, uint, float, int64
+template <typename QueryT>
+void CastIndexedStateValues(Context *context,
+                            GLenum nativeType,
+                            GLenum pname,
+                            GLuint index,
+                            unsigned int numParams,
+                            QueryT *outParams);
+}
+
+#endif  // LIBANGLE_QUERY_CONVERSIONS_H_
diff --git a/src/third_party/angle/src/libANGLE/queryutils.cpp b/src/third_party/angle/src/libANGLE/queryutils.cpp
new file mode 100644
index 0000000..81cc06c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/queryutils.cpp
@@ -0,0 +1,1199 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// queryutils.cpp: Utilities for querying values from GL objects
+
+#include "libANGLE/queryutils.h"
+
+#include "common/utilities.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexAttribute.h"
+
+namespace gl
+{
+
+namespace
+{
+template <typename ParamType>
+void QueryTexLevelParameterBase(const Texture *texture,
+                                GLenum target,
+                                GLint level,
+                                GLenum pname,
+                                ParamType *params)
+{
+    ASSERT(texture != nullptr);
+    const InternalFormat *info = texture->getTextureState().getImageDesc(target, level).format.info;
+
+    switch (pname)
+    {
+        case GL_TEXTURE_RED_TYPE:
+            *params = ConvertFromGLenum<ParamType>(info->redBits ? info->componentType : GL_NONE);
+            break;
+        case GL_TEXTURE_GREEN_TYPE:
+            *params = ConvertFromGLenum<ParamType>(info->greenBits ? info->componentType : GL_NONE);
+            break;
+        case GL_TEXTURE_BLUE_TYPE:
+            *params = ConvertFromGLenum<ParamType>(info->blueBits ? info->componentType : GL_NONE);
+            break;
+        case GL_TEXTURE_ALPHA_TYPE:
+            *params = ConvertFromGLenum<ParamType>(info->alphaBits ? info->componentType : GL_NONE);
+            break;
+        case GL_TEXTURE_DEPTH_TYPE:
+            *params = ConvertFromGLenum<ParamType>(info->depthBits ? info->componentType : GL_NONE);
+            break;
+        case GL_TEXTURE_RED_SIZE:
+            *params = ConvertFromGLuint<ParamType>(info->redBits);
+            break;
+        case GL_TEXTURE_GREEN_SIZE:
+            *params = ConvertFromGLuint<ParamType>(info->greenBits);
+            break;
+        case GL_TEXTURE_BLUE_SIZE:
+            *params = ConvertFromGLuint<ParamType>(info->blueBits);
+            break;
+        case GL_TEXTURE_ALPHA_SIZE:
+            *params = ConvertFromGLuint<ParamType>(info->alphaBits);
+            break;
+        case GL_TEXTURE_DEPTH_SIZE:
+            *params = ConvertFromGLuint<ParamType>(info->depthBits);
+            break;
+        case GL_TEXTURE_STENCIL_SIZE:
+            *params = ConvertFromGLuint<ParamType>(info->stencilBits);
+            break;
+        case GL_TEXTURE_SHARED_SIZE:
+            *params = ConvertFromGLuint<ParamType>(info->sharedBits);
+            break;
+        case GL_TEXTURE_INTERNAL_FORMAT:
+            *params =
+                ConvertFromGLenum<ParamType>(info->internalFormat ? info->internalFormat : GL_RGBA);
+            break;
+        case GL_TEXTURE_WIDTH:
+            *params =
+                ConvertFromGLint<ParamType>(static_cast<GLint>(texture->getWidth(target, level)));
+            break;
+        case GL_TEXTURE_HEIGHT:
+            *params =
+                ConvertFromGLint<ParamType>(static_cast<GLint>(texture->getHeight(target, level)));
+            break;
+        case GL_TEXTURE_DEPTH:
+            *params =
+                ConvertFromGLint<ParamType>(static_cast<GLint>(texture->getDepth(target, level)));
+            break;
+        case GL_TEXTURE_SAMPLES:
+            *params = ConvertFromGLint<ParamType>(texture->getSamples(target, level));
+            break;
+        case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
+            *params =
+                ConvertFromGLboolean<ParamType>(texture->getFixedSampleLocations(target, level));
+            break;
+        case GL_TEXTURE_COMPRESSED:
+            *params = ConvertFromGLboolean<ParamType>(info->compressed);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+template <typename ParamType>
+void QueryTexParameterBase(const Texture *texture, GLenum pname, ParamType *params)
+{
+    ASSERT(texture != nullptr);
+
+    switch (pname)
+    {
+        case GL_TEXTURE_MAG_FILTER:
+            *params = ConvertFromGLenum<ParamType>(texture->getMagFilter());
+            break;
+        case GL_TEXTURE_MIN_FILTER:
+            *params = ConvertFromGLenum<ParamType>(texture->getMinFilter());
+            break;
+        case GL_TEXTURE_WRAP_S:
+            *params = ConvertFromGLenum<ParamType>(texture->getWrapS());
+            break;
+        case GL_TEXTURE_WRAP_T:
+            *params = ConvertFromGLenum<ParamType>(texture->getWrapT());
+            break;
+        case GL_TEXTURE_WRAP_R:
+            *params = ConvertFromGLenum<ParamType>(texture->getWrapR());
+            break;
+        case GL_TEXTURE_IMMUTABLE_FORMAT:
+            *params = ConvertFromGLboolean<ParamType>(texture->getImmutableFormat());
+            break;
+        case GL_TEXTURE_IMMUTABLE_LEVELS:
+            *params = ConvertFromGLuint<ParamType>(texture->getImmutableLevels());
+            break;
+        case GL_TEXTURE_USAGE_ANGLE:
+            *params = ConvertFromGLenum<ParamType>(texture->getUsage());
+            break;
+        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+            *params = ConvertFromGLfloat<ParamType>(texture->getMaxAnisotropy());
+            break;
+        case GL_TEXTURE_SWIZZLE_R:
+            *params = ConvertFromGLenum<ParamType>(texture->getSwizzleRed());
+            break;
+        case GL_TEXTURE_SWIZZLE_G:
+            *params = ConvertFromGLenum<ParamType>(texture->getSwizzleGreen());
+            break;
+        case GL_TEXTURE_SWIZZLE_B:
+            *params = ConvertFromGLenum<ParamType>(texture->getSwizzleBlue());
+            break;
+        case GL_TEXTURE_SWIZZLE_A:
+            *params = ConvertFromGLenum<ParamType>(texture->getSwizzleAlpha());
+            break;
+        case GL_TEXTURE_BASE_LEVEL:
+            *params = ConvertFromGLuint<ParamType>(texture->getBaseLevel());
+            break;
+        case GL_TEXTURE_MAX_LEVEL:
+            *params = ConvertFromGLuint<ParamType>(texture->getMaxLevel());
+            break;
+        case GL_TEXTURE_MIN_LOD:
+            *params = ConvertFromGLfloat<ParamType>(texture->getSamplerState().minLod);
+            break;
+        case GL_TEXTURE_MAX_LOD:
+            *params = ConvertFromGLfloat<ParamType>(texture->getSamplerState().maxLod);
+            break;
+        case GL_TEXTURE_COMPARE_MODE:
+            *params = ConvertFromGLenum<ParamType>(texture->getCompareMode());
+            break;
+        case GL_TEXTURE_COMPARE_FUNC:
+            *params = ConvertFromGLenum<ParamType>(texture->getCompareFunc());
+            break;
+        case GL_TEXTURE_SRGB_DECODE_EXT:
+            *params = ConvertFromGLenum<ParamType>(texture->getSRGBDecode());
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+template <typename ParamType>
+void SetTexParameterBase(Texture *texture, GLenum pname, const ParamType *params)
+{
+    ASSERT(texture != nullptr);
+
+    switch (pname)
+    {
+        case GL_TEXTURE_WRAP_S:
+            texture->setWrapS(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_WRAP_T:
+            texture->setWrapT(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_WRAP_R:
+            texture->setWrapR(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_MIN_FILTER:
+            texture->setMinFilter(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_MAG_FILTER:
+            texture->setMagFilter(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_USAGE_ANGLE:
+            texture->setUsage(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+            texture->setMaxAnisotropy(ConvertToGLfloat(params[0]));
+            break;
+        case GL_TEXTURE_COMPARE_MODE:
+            texture->setCompareMode(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_COMPARE_FUNC:
+            texture->setCompareFunc(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_SWIZZLE_R:
+            texture->setSwizzleRed(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_SWIZZLE_G:
+            texture->setSwizzleGreen(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_SWIZZLE_B:
+            texture->setSwizzleBlue(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_SWIZZLE_A:
+            texture->setSwizzleAlpha(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_BASE_LEVEL:
+            texture->setBaseLevel(ConvertToGLuint(params[0]));
+            break;
+        case GL_TEXTURE_MAX_LEVEL:
+            texture->setMaxLevel(ConvertToGLuint(params[0]));
+            break;
+        case GL_TEXTURE_MIN_LOD:
+            texture->setMinLod(ConvertToGLfloat(params[0]));
+            break;
+        case GL_TEXTURE_MAX_LOD:
+            texture->setMaxLod(ConvertToGLfloat(params[0]));
+            break;
+        case GL_DEPTH_STENCIL_TEXTURE_MODE:
+            texture->setDepthStencilTextureMode(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_SRGB_DECODE_EXT:
+            texture->setSRGBDecode(ConvertToGLenum(params[0]));
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+template <typename ParamType>
+void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType *params)
+{
+    switch (pname)
+    {
+        case GL_TEXTURE_MIN_FILTER:
+            *params = ConvertFromGLenum<ParamType>(sampler->getMinFilter());
+            break;
+        case GL_TEXTURE_MAG_FILTER:
+            *params = ConvertFromGLenum<ParamType>(sampler->getMagFilter());
+            break;
+        case GL_TEXTURE_WRAP_S:
+            *params = ConvertFromGLenum<ParamType>(sampler->getWrapS());
+            break;
+        case GL_TEXTURE_WRAP_T:
+            *params = ConvertFromGLenum<ParamType>(sampler->getWrapT());
+            break;
+        case GL_TEXTURE_WRAP_R:
+            *params = ConvertFromGLenum<ParamType>(sampler->getWrapR());
+            break;
+        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+            *params = ConvertFromGLfloat<ParamType>(sampler->getMaxAnisotropy());
+            break;
+        case GL_TEXTURE_MIN_LOD:
+            *params = ConvertFromGLfloat<ParamType>(sampler->getMinLod());
+            break;
+        case GL_TEXTURE_MAX_LOD:
+            *params = ConvertFromGLfloat<ParamType>(sampler->getMaxLod());
+            break;
+        case GL_TEXTURE_COMPARE_MODE:
+            *params = ConvertFromGLenum<ParamType>(sampler->getCompareMode());
+            break;
+        case GL_TEXTURE_COMPARE_FUNC:
+            *params = ConvertFromGLenum<ParamType>(sampler->getCompareFunc());
+            break;
+        case GL_TEXTURE_SRGB_DECODE_EXT:
+            *params = ConvertFromGLenum<ParamType>(sampler->getSRGBDecode());
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+template <typename ParamType>
+void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *params)
+{
+    switch (pname)
+    {
+        case GL_TEXTURE_WRAP_S:
+            sampler->setWrapS(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_WRAP_T:
+            sampler->setWrapT(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_WRAP_R:
+            sampler->setWrapR(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_MIN_FILTER:
+            sampler->setMinFilter(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_MAG_FILTER:
+            sampler->setMagFilter(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+            sampler->setMaxAnisotropy(ConvertToGLfloat(params[0]));
+            break;
+        case GL_TEXTURE_COMPARE_MODE:
+            sampler->setCompareMode(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_COMPARE_FUNC:
+            sampler->setCompareFunc(ConvertToGLenum(params[0]));
+            break;
+        case GL_TEXTURE_MIN_LOD:
+            sampler->setMinLod(ConvertToGLfloat(params[0]));
+            break;
+        case GL_TEXTURE_MAX_LOD:
+            sampler->setMaxLod(ConvertToGLfloat(params[0]));
+            break;
+        case GL_TEXTURE_SRGB_DECODE_EXT:
+            sampler->setSRGBDecode(ConvertToGLenum(params[0]));
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+template <typename ParamType, typename CurrentDataType>
+ParamType ConvertCurrentValue(CurrentDataType currentValue)
+{
+    return static_cast<ParamType>(currentValue);
+}
+
+template <>
+GLint ConvertCurrentValue(GLfloat currentValue)
+{
+    return iround<GLint>(currentValue);
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+template <typename ParamType, typename CurrentDataType, size_t CurrentValueCount>
+void QueryVertexAttribBase(const VertexAttribute &attrib,
+                           const VertexBinding &binding,
+                           const CurrentDataType (&currentValueData)[CurrentValueCount],
+                           GLenum pname,
+                           ParamType *params)
+{
+    switch (pname)
+    {
+        case GL_CURRENT_VERTEX_ATTRIB:
+            for (size_t i = 0; i < CurrentValueCount; ++i)
+            {
+                params[i] = ConvertCurrentValue<ParamType>(currentValueData[i]);
+            }
+            break;
+        case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+            *params = ConvertFromGLboolean<ParamType>(attrib.enabled);
+            break;
+        case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+            *params = ConvertFromGLuint<ParamType>(attrib.size);
+            break;
+        case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+            *params = ConvertFromGLuint<ParamType>(attrib.vertexAttribArrayStride);
+            break;
+        case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+            *params = ConvertFromGLenum<ParamType>(attrib.type);
+            break;
+        case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+            *params = ConvertFromGLboolean<ParamType>(attrib.normalized);
+            break;
+        case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+            *params = ConvertFromGLuint<ParamType>(binding.buffer.id());
+            break;
+        case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
+            *params = ConvertFromGLuint<ParamType>(binding.divisor);
+            break;
+        case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+            *params = ConvertFromGLboolean<ParamType>(attrib.pureInteger);
+            break;
+        case GL_VERTEX_ATTRIB_BINDING:
+            *params = ConvertFromGLuint<ParamType>(attrib.bindingIndex);
+            break;
+        case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
+            // attrib.relativeOffset should not be negative or greater than max GLint
+            ASSERT(attrib.relativeOffset >= 0 &&
+                   attrib.relativeOffset <= std::numeric_limits<GLint>::max());
+            *params = ConvertFromGLint<ParamType>(static_cast<GLint>(attrib.relativeOffset));
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+template <typename ParamType>
+void QueryBufferParameterBase(const Buffer *buffer, GLenum pname, ParamType *params)
+{
+    ASSERT(buffer != nullptr);
+
+    switch (pname)
+    {
+        case GL_BUFFER_USAGE:
+            *params = ConvertFromGLenum<ParamType>(buffer->getUsage());
+            break;
+        case GL_BUFFER_SIZE:
+            *params = ConvertFromGLint64<ParamType>(buffer->getSize());
+            break;
+        case GL_BUFFER_ACCESS_FLAGS:
+            *params = ConvertFromGLuint<ParamType>(buffer->getAccessFlags());
+            break;
+        case GL_BUFFER_ACCESS_OES:
+            *params = ConvertFromGLenum<ParamType>(buffer->getAccess());
+            break;
+        case GL_BUFFER_MAPPED:
+            *params = ConvertFromGLboolean<ParamType>(buffer->isMapped());
+            break;
+        case GL_BUFFER_MAP_OFFSET:
+            *params = ConvertFromGLint64<ParamType>(buffer->getMapOffset());
+            break;
+        case GL_BUFFER_MAP_LENGTH:
+            *params = ConvertFromGLint64<ParamType>(buffer->getMapLength());
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+}  // anonymous namespace
+
+void QueryFramebufferAttachmentParameteriv(const Framebuffer *framebuffer,
+                                           GLenum attachment,
+                                           GLenum pname,
+                                           GLint *params)
+{
+    ASSERT(framebuffer);
+
+    const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
+    if (attachmentObject == nullptr)
+    {
+        // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
+        // is NONE, then querying any other pname will generate INVALID_ENUM.
+
+        // ES 3.0.2 spec pg 235 states that if the attachment type is none,
+        // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
+        // INVALID_OPERATION for all other pnames
+
+        switch (pname)
+        {
+            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+                *params = GL_NONE;
+                break;
+
+            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+                *params = 0;
+                break;
+
+            default:
+                UNREACHABLE();
+                break;
+        }
+
+        return;
+    }
+
+    switch (pname)
+    {
+        case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+            *params = attachmentObject->type();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+            *params = attachmentObject->id();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+            *params = attachmentObject->mipLevel();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+            *params = attachmentObject->cubeMapFace();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+            *params = attachmentObject->getRedSize();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+            *params = attachmentObject->getGreenSize();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+            *params = attachmentObject->getBlueSize();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+            *params = attachmentObject->getAlphaSize();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+            *params = attachmentObject->getDepthSize();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+            *params = attachmentObject->getStencilSize();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+            *params = attachmentObject->getComponentType();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+            *params = attachmentObject->getColorEncoding();
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+            *params = attachmentObject->layer();
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void QueryBufferParameteriv(const Buffer *buffer, GLenum pname, GLint *params)
+{
+    QueryBufferParameterBase(buffer, pname, params);
+}
+
+void QueryBufferParameteri64v(const Buffer *buffer, GLenum pname, GLint64 *params)
+{
+    QueryBufferParameterBase(buffer, pname, params);
+}
+
+void QueryBufferPointerv(const Buffer *buffer, GLenum pname, void **params)
+{
+    switch (pname)
+    {
+        case GL_BUFFER_MAP_POINTER:
+            *params = buffer->getMapPointer();
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void QueryProgramiv(const Program *program, GLenum pname, GLint *params)
+{
+    ASSERT(program != nullptr);
+
+    switch (pname)
+    {
+        case GL_DELETE_STATUS:
+            *params = program->isFlaggedForDeletion();
+            return;
+        case GL_LINK_STATUS:
+            *params = program->isLinked();
+            return;
+        case GL_VALIDATE_STATUS:
+            *params = program->isValidated();
+            return;
+        case GL_INFO_LOG_LENGTH:
+            *params = program->getInfoLogLength();
+            return;
+        case GL_ATTACHED_SHADERS:
+            *params = program->getAttachedShadersCount();
+            return;
+        case GL_ACTIVE_ATTRIBUTES:
+            *params = program->getActiveAttributeCount();
+            return;
+        case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+            *params = program->getActiveAttributeMaxLength();
+            return;
+        case GL_ACTIVE_UNIFORMS:
+            *params = program->getActiveUniformCount();
+            return;
+        case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+            *params = program->getActiveUniformMaxLength();
+            return;
+        case GL_PROGRAM_BINARY_LENGTH_OES:
+            *params = program->getBinaryLength();
+            return;
+        case GL_ACTIVE_UNIFORM_BLOCKS:
+            *params = program->getActiveUniformBlockCount();
+            return;
+        case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+            *params = program->getActiveUniformBlockMaxLength();
+            break;
+        case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+            *params = program->getTransformFeedbackBufferMode();
+            break;
+        case GL_TRANSFORM_FEEDBACK_VARYINGS:
+            *params = program->getTransformFeedbackVaryingCount();
+            break;
+        case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+            *params = program->getTransformFeedbackVaryingMaxLength();
+            break;
+        case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+            *params = program->getBinaryRetrievableHint();
+            break;
+        case GL_PROGRAM_SEPARABLE:
+            *params = program->isSeparable();
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void QueryRenderbufferiv(const Context *context,
+                         const Renderbuffer *renderbuffer,
+                         GLenum pname,
+                         GLint *params)
+{
+    ASSERT(renderbuffer != nullptr);
+
+    switch (pname)
+    {
+        case GL_RENDERBUFFER_WIDTH:
+            *params = renderbuffer->getWidth();
+            break;
+        case GL_RENDERBUFFER_HEIGHT:
+            *params = renderbuffer->getHeight();
+            break;
+        case GL_RENDERBUFFER_INTERNAL_FORMAT:
+            // Special case the WebGL 1 DEPTH_STENCIL format.
+            if (context->isWebGL1() &&
+                renderbuffer->getFormat().info->internalFormat == GL_DEPTH24_STENCIL8)
+            {
+                *params = GL_DEPTH_STENCIL;
+            }
+            else
+            {
+                *params = renderbuffer->getFormat().info->internalFormat;
+            }
+            break;
+        case GL_RENDERBUFFER_RED_SIZE:
+            *params = renderbuffer->getRedSize();
+            break;
+        case GL_RENDERBUFFER_GREEN_SIZE:
+            *params = renderbuffer->getGreenSize();
+            break;
+        case GL_RENDERBUFFER_BLUE_SIZE:
+            *params = renderbuffer->getBlueSize();
+            break;
+        case GL_RENDERBUFFER_ALPHA_SIZE:
+            *params = renderbuffer->getAlphaSize();
+            break;
+        case GL_RENDERBUFFER_DEPTH_SIZE:
+            *params = renderbuffer->getDepthSize();
+            break;
+        case GL_RENDERBUFFER_STENCIL_SIZE:
+            *params = renderbuffer->getStencilSize();
+            break;
+        case GL_RENDERBUFFER_SAMPLES_ANGLE:
+            *params = renderbuffer->getSamples();
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void QueryShaderiv(const Shader *shader, GLenum pname, GLint *params)
+{
+    ASSERT(shader != nullptr);
+
+    switch (pname)
+    {
+        case GL_SHADER_TYPE:
+            *params = shader->getType();
+            return;
+        case GL_DELETE_STATUS:
+            *params = shader->isFlaggedForDeletion();
+            return;
+        case GL_COMPILE_STATUS:
+            *params = shader->isCompiled() ? GL_TRUE : GL_FALSE;
+            return;
+        case GL_INFO_LOG_LENGTH:
+            *params = shader->getInfoLogLength();
+            return;
+        case GL_SHADER_SOURCE_LENGTH:
+            *params = shader->getSourceLength();
+            return;
+        case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+            *params = shader->getTranslatedSourceWithDebugInfoLength();
+            return;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void QueryTexLevelParameterfv(const Texture *texture,
+                              GLenum target,
+                              GLint level,
+                              GLenum pname,
+                              GLfloat *params)
+{
+    QueryTexLevelParameterBase(texture, target, level, pname, params);
+}
+
+void QueryTexLevelParameteriv(const Texture *texture,
+                              GLenum target,
+                              GLint level,
+                              GLenum pname,
+                              GLint *params)
+{
+    QueryTexLevelParameterBase(texture, target, level, pname, params);
+}
+
+void QueryTexParameterfv(const Texture *texture, GLenum pname, GLfloat *params)
+{
+    QueryTexParameterBase(texture, pname, params);
+}
+
+void QueryTexParameteriv(const Texture *texture, GLenum pname, GLint *params)
+{
+    QueryTexParameterBase(texture, pname, params);
+}
+
+void QuerySamplerParameterfv(const Sampler *sampler, GLenum pname, GLfloat *params)
+{
+    QuerySamplerParameterBase(sampler, pname, params);
+}
+
+void QuerySamplerParameteriv(const Sampler *sampler, GLenum pname, GLint *params)
+{
+    QuerySamplerParameterBase(sampler, pname, params);
+}
+
+void QueryVertexAttribfv(const VertexAttribute &attrib,
+                         const VertexBinding &binding,
+                         const VertexAttribCurrentValueData &currentValueData,
+                         GLenum pname,
+                         GLfloat *params)
+{
+    QueryVertexAttribBase(attrib, binding, currentValueData.FloatValues, pname, params);
+}
+
+void QueryVertexAttribiv(const VertexAttribute &attrib,
+                         const VertexBinding &binding,
+                         const VertexAttribCurrentValueData &currentValueData,
+                         GLenum pname,
+                         GLint *params)
+{
+    QueryVertexAttribBase(attrib, binding, currentValueData.FloatValues, pname, params);
+}
+
+void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void **pointer)
+{
+    switch (pname)
+    {
+        case GL_VERTEX_ATTRIB_ARRAY_POINTER:
+            *pointer = const_cast<void *>(attrib.pointer);
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void QueryVertexAttribIiv(const VertexAttribute &attrib,
+                          const VertexBinding &binding,
+                          const VertexAttribCurrentValueData &currentValueData,
+                          GLenum pname,
+                          GLint *params)
+{
+    QueryVertexAttribBase(attrib, binding, currentValueData.IntValues, pname, params);
+}
+
+void QueryVertexAttribIuiv(const VertexAttribute &attrib,
+                           const VertexBinding &binding,
+                           const VertexAttribCurrentValueData &currentValueData,
+                           GLenum pname,
+                           GLuint *params)
+{
+    QueryVertexAttribBase(attrib, binding, currentValueData.UnsignedIntValues, pname, params);
+}
+
+void QueryActiveUniformBlockiv(const Program *program,
+                               GLuint uniformBlockIndex,
+                               GLenum pname,
+                               GLint *params)
+{
+    const UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
+    switch (pname)
+    {
+        case GL_UNIFORM_BLOCK_BINDING:
+            *params = ConvertToGLint(program->getUniformBlockBinding(uniformBlockIndex));
+            break;
+        case GL_UNIFORM_BLOCK_DATA_SIZE:
+            *params = ConvertToGLint(uniformBlock.dataSize);
+            break;
+        case GL_UNIFORM_BLOCK_NAME_LENGTH:
+            *params = ConvertToGLint(uniformBlock.nameWithArrayIndex().size() + 1);
+            break;
+        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+            *params = ConvertToGLint(uniformBlock.memberUniformIndexes.size());
+            break;
+        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+            for (size_t blockMemberIndex = 0;
+                 blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
+            {
+                params[blockMemberIndex] =
+                    ConvertToGLint(uniformBlock.memberUniformIndexes[blockMemberIndex]);
+            }
+            break;
+        case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+            *params = ConvertToGLint(uniformBlock.vertexStaticUse);
+            break;
+        case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+            *params = ConvertToGLint(uniformBlock.fragmentStaticUse);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params)
+{
+    switch (pname)
+    {
+        case GL_NUM_SAMPLE_COUNTS:
+            if (bufSize != 0)
+            {
+                *params = static_cast<GLint>(format.sampleCounts.size());
+            }
+            break;
+
+        case GL_SAMPLES:
+        {
+            size_t returnCount   = std::min<size_t>(bufSize, format.sampleCounts.size());
+            auto sampleReverseIt = format.sampleCounts.rbegin();
+            for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex)
+            {
+                params[sampleIndex] = *sampleReverseIt++;
+            }
+        }
+        break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void QueryFramebufferParameteriv(const Framebuffer *framebuffer, GLenum pname, GLint *params)
+{
+    ASSERT(framebuffer);
+
+    switch (pname)
+    {
+        case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+            *params = framebuffer->getDefaultWidth();
+            break;
+        case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+            *params = framebuffer->getDefaultHeight();
+            break;
+        case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+            *params = framebuffer->getDefaultSamples();
+            break;
+        case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+            *params = framebuffer->getDefaultFixedSampleLocations();
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+Error QuerySynciv(const FenceSync *sync,
+                  GLenum pname,
+                  GLsizei bufSize,
+                  GLsizei *length,
+                  GLint *values)
+{
+    ASSERT(sync);
+
+    // All queries return one value, exit early if the buffer can't fit anything.
+    if (bufSize < 1)
+    {
+        if (length != nullptr)
+        {
+            *length = 0;
+        }
+        return NoError();
+    }
+
+    switch (pname)
+    {
+        case GL_OBJECT_TYPE:
+            *values = ConvertToGLint(GL_SYNC_FENCE);
+            break;
+        case GL_SYNC_CONDITION:
+            *values = ConvertToGLint(sync->getCondition());
+            break;
+        case GL_SYNC_FLAGS:
+            *values = ConvertToGLint(sync->getFlags());
+            break;
+        case GL_SYNC_STATUS:
+            ANGLE_TRY(sync->getStatus(values));
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    if (length != nullptr)
+    {
+        *length = 1;
+    }
+
+    return NoError();
+}
+
+void SetTexParameterf(Texture *texture, GLenum pname, GLfloat param)
+{
+    SetTexParameterBase(texture, pname, &param);
+}
+
+void SetTexParameterfv(Texture *texture, GLenum pname, const GLfloat *params)
+{
+    SetTexParameterBase(texture, pname, params);
+}
+
+void SetTexParameteri(Texture *texture, GLenum pname, GLint param)
+{
+    SetTexParameterBase(texture, pname, &param);
+}
+
+void SetTexParameteriv(Texture *texture, GLenum pname, const GLint *params)
+{
+    SetTexParameterBase(texture, pname, params);
+}
+
+void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param)
+{
+    SetSamplerParameterBase(sampler, pname, &param);
+}
+
+void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params)
+{
+    SetSamplerParameterBase(sampler, pname, params);
+}
+
+void SetSamplerParameteri(Sampler *sampler, GLenum pname, GLint param)
+{
+    SetSamplerParameterBase(sampler, pname, &param);
+}
+
+void SetSamplerParameteriv(Sampler *sampler, GLenum pname, const GLint *params)
+{
+    SetSamplerParameterBase(sampler, pname, params);
+}
+
+void SetFramebufferParameteri(Framebuffer *framebuffer, GLenum pname, GLint param)
+{
+    ASSERT(framebuffer);
+
+    switch (pname)
+    {
+        case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+            framebuffer->setDefaultWidth(param);
+            break;
+        case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+            framebuffer->setDefaultHeight(param);
+            break;
+        case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+            framebuffer->setDefaultSamples(param);
+            break;
+        case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+            framebuffer->setDefaultFixedSampleLocations(static_cast<GLboolean>(param));
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void SetProgramParameteri(Program *program, GLenum pname, GLint value)
+{
+    ASSERT(program);
+
+    switch (pname)
+    {
+        case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+            program->setBinaryRetrievableHint(value != GL_FALSE);
+            break;
+        case GL_PROGRAM_SEPARABLE:
+            program->setSeparable(value != GL_FALSE);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+GLuint QueryProgramResourceIndex(const Program *program,
+                                 GLenum programInterface,
+                                 const GLchar *name)
+{
+    switch (programInterface)
+    {
+        case GL_PROGRAM_INPUT:
+            return program->getInputResourceIndex(name);
+
+        case GL_PROGRAM_OUTPUT:
+            return program->getOutputResourceIndex(name);
+
+        // TODO(Jie): more interfaces.
+        case GL_UNIFORM:
+        case GL_UNIFORM_BLOCK:
+        case GL_TRANSFORM_FEEDBACK_VARYING:
+        case GL_BUFFER_VARIABLE:
+        case GL_SHADER_STORAGE_BLOCK:
+            UNIMPLEMENTED();
+            return GL_INVALID_INDEX;
+
+        default:
+            UNREACHABLE();
+            return GL_INVALID_INDEX;
+    }
+}
+
+void QueryProgramResourceName(const Program *program,
+                              GLenum programInterface,
+                              GLuint index,
+                              GLsizei bufSize,
+                              GLsizei *length,
+                              GLchar *name)
+{
+    switch (programInterface)
+    {
+        case GL_PROGRAM_INPUT:
+            program->getInputResourceName(index, bufSize, length, name);
+            break;
+
+        case GL_PROGRAM_OUTPUT:
+            program->getOutputResourceName(index, bufSize, length, name);
+            break;
+
+        // TODO(Jie): more interfaces.
+        case GL_UNIFORM:
+        case GL_UNIFORM_BLOCK:
+        case GL_TRANSFORM_FEEDBACK_VARYING:
+        case GL_BUFFER_VARIABLE:
+        case GL_SHADER_STORAGE_BLOCK:
+            UNIMPLEMENTED();
+            break;
+
+        default:
+            UNREACHABLE();
+    }
+}
+
+}  // namespace gl
+
+namespace egl
+{
+
+void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value)
+{
+    ASSERT(config != nullptr);
+    switch (attribute)
+    {
+        case EGL_BUFFER_SIZE:
+            *value = config->bufferSize;
+            break;
+        case EGL_ALPHA_SIZE:
+            *value = config->alphaSize;
+            break;
+        case EGL_BLUE_SIZE:
+            *value = config->blueSize;
+            break;
+        case EGL_GREEN_SIZE:
+            *value = config->greenSize;
+            break;
+        case EGL_RED_SIZE:
+            *value = config->redSize;
+            break;
+        case EGL_DEPTH_SIZE:
+            *value = config->depthSize;
+            break;
+        case EGL_STENCIL_SIZE:
+            *value = config->stencilSize;
+            break;
+        case EGL_CONFIG_CAVEAT:
+            *value = config->configCaveat;
+            break;
+        case EGL_CONFIG_ID:
+            *value = config->configID;
+            break;
+        case EGL_LEVEL:
+            *value = config->level;
+            break;
+        case EGL_NATIVE_RENDERABLE:
+            *value = config->nativeRenderable;
+            break;
+        case EGL_NATIVE_VISUAL_ID:
+            *value = config->nativeVisualID;
+            break;
+        case EGL_NATIVE_VISUAL_TYPE:
+            *value = config->nativeVisualType;
+            break;
+        case EGL_SAMPLES:
+            *value = config->samples;
+            break;
+        case EGL_SAMPLE_BUFFERS:
+            *value = config->sampleBuffers;
+            break;
+        case EGL_SURFACE_TYPE:
+            *value = config->surfaceType;
+            break;
+        case EGL_TRANSPARENT_TYPE:
+            *value = config->transparentType;
+            break;
+        case EGL_TRANSPARENT_BLUE_VALUE:
+            *value = config->transparentBlueValue;
+            break;
+        case EGL_TRANSPARENT_GREEN_VALUE:
+            *value = config->transparentGreenValue;
+            break;
+        case EGL_TRANSPARENT_RED_VALUE:
+            *value = config->transparentRedValue;
+            break;
+        case EGL_BIND_TO_TEXTURE_RGB:
+            *value = config->bindToTextureRGB;
+            break;
+        case EGL_BIND_TO_TEXTURE_RGBA:
+            *value = config->bindToTextureRGBA;
+            break;
+        case EGL_MIN_SWAP_INTERVAL:
+            *value = config->minSwapInterval;
+            break;
+        case EGL_MAX_SWAP_INTERVAL:
+            *value = config->maxSwapInterval;
+            break;
+        case EGL_LUMINANCE_SIZE:
+            *value = config->luminanceSize;
+            break;
+        case EGL_ALPHA_MASK_SIZE:
+            *value = config->alphaMaskSize;
+            break;
+        case EGL_COLOR_BUFFER_TYPE:
+            *value = config->colorBufferType;
+            break;
+        case EGL_RENDERABLE_TYPE:
+            *value = config->renderableType;
+            break;
+        case EGL_MATCH_NATIVE_PIXMAP:
+            *value = false;
+            UNIMPLEMENTED();
+            break;
+        case EGL_CONFORMANT:
+            *value = config->conformant;
+            break;
+        case EGL_MAX_PBUFFER_WIDTH:
+            *value = config->maxPBufferWidth;
+            break;
+        case EGL_MAX_PBUFFER_HEIGHT:
+            *value = config->maxPBufferHeight;
+            break;
+        case EGL_MAX_PBUFFER_PIXELS:
+            *value = config->maxPBufferPixels;
+            break;
+        case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+            *value = config->optimalOrientation;
+            break;
+        case EGL_COLOR_COMPONENT_TYPE_EXT:
+            *value = config->colorComponentType;
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+}  // namespace egl
diff --git a/src/third_party/angle/src/libANGLE/queryutils.h b/src/third_party/angle/src/libANGLE/queryutils.h
new file mode 100644
index 0000000..3c5953f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/queryutils.h
@@ -0,0 +1,141 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// queryutils.h: Utilities for querying values from GL objects
+
+#ifndef LIBANGLE_QUERYUTILS_H_
+#define LIBANGLE_QUERYUTILS_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+#include <EGL/egl.h>
+
+namespace gl
+{
+class Buffer;
+class Context;
+class Error;
+class FenceSync;
+class Framebuffer;
+class Program;
+class Renderbuffer;
+class Sampler;
+class Shader;
+class Texture;
+struct TextureCaps;
+struct UniformBlock;
+struct VertexAttribute;
+struct VertexBinding;
+struct VertexAttribCurrentValueData;
+
+void QueryFramebufferAttachmentParameteriv(const Framebuffer *framebuffer,
+                                           GLenum attachment,
+                                           GLenum pname,
+                                           GLint *params);
+void QueryBufferParameteriv(const Buffer *buffer, GLenum pname, GLint *params);
+void QueryBufferParameteri64v(const Buffer *buffer, GLenum pname, GLint64 *params);
+void QueryBufferPointerv(const Buffer *buffer, GLenum pname, void **params);
+void QueryProgramiv(const Program *program, GLenum pname, GLint *params);
+void QueryRenderbufferiv(const Context *context,
+                         const Renderbuffer *renderbuffer,
+                         GLenum pname,
+                         GLint *params);
+void QueryShaderiv(const Shader *shader, GLenum pname, GLint *params);
+void QueryTexLevelParameterfv(const Texture *texture,
+                              GLenum target,
+                              GLint level,
+                              GLenum pname,
+                              GLfloat *params);
+void QueryTexLevelParameteriv(const Texture *texture,
+                              GLenum target,
+                              GLint level,
+                              GLenum pname,
+                              GLint *params);
+void QueryTexParameterfv(const Texture *texture, GLenum pname, GLfloat *params);
+void QueryTexParameteriv(const Texture *texture, GLenum pname, GLint *params);
+void QuerySamplerParameterfv(const Sampler *sampler, GLenum pname, GLfloat *params);
+void QuerySamplerParameteriv(const Sampler *sampler, GLenum pname, GLint *params);
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using the following
+// functions.
+void QueryVertexAttribfv(const VertexAttribute &attrib,
+                         const VertexBinding &binding,
+                         const VertexAttribCurrentValueData &currentValueData,
+                         GLenum pname,
+                         GLfloat *params);
+
+void QueryVertexAttribiv(const VertexAttribute &attrib,
+                         const VertexBinding &binding,
+                         const VertexAttribCurrentValueData &currentValueData,
+                         GLenum pname,
+                         GLint *params);
+
+void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void **pointer);
+
+void QueryVertexAttribIiv(const VertexAttribute &attrib,
+                          const VertexBinding &binding,
+                          const VertexAttribCurrentValueData &currentValueData,
+                          GLenum pname,
+                          GLint *params);
+
+void QueryVertexAttribIuiv(const VertexAttribute &attrib,
+                           const VertexBinding &binding,
+                           const VertexAttribCurrentValueData &currentValueData,
+                           GLenum pname,
+                           GLuint *params);
+
+void QueryActiveUniformBlockiv(const Program *program,
+                               GLuint uniformBlockIndex,
+                               GLenum pname,
+                               GLint *params);
+
+void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params);
+
+void QueryFramebufferParameteriv(const Framebuffer *framebuffer, GLenum pname, GLint *params);
+
+Error QuerySynciv(const FenceSync *sync,
+                  GLenum pname,
+                  GLsizei bufSize,
+                  GLsizei *length,
+                  GLint *values);
+
+void SetTexParameterf(Texture *texture, GLenum pname, GLfloat param);
+void SetTexParameterfv(Texture *texture, GLenum pname, const GLfloat *params);
+void SetTexParameteri(Texture *texture, GLenum pname, GLint param);
+void SetTexParameteriv(Texture *texture, GLenum pname, const GLint *params);
+
+void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param);
+void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params);
+void SetSamplerParameteri(Sampler *sampler, GLenum pname, GLint param);
+void SetSamplerParameteriv(Sampler *sampler, GLenum pname, const GLint *params);
+
+void SetFramebufferParameteri(Framebuffer *framebuffer, GLenum pname, GLint param);
+
+void SetProgramParameteri(Program *program, GLenum pname, GLint value);
+
+GLuint QueryProgramResourceIndex(const Program *program,
+                                 GLenum programInterface,
+                                 const GLchar *name);
+
+void QueryProgramResourceName(const Program *program,
+                              GLenum programInterface,
+                              GLuint index,
+                              GLsizei bufSize,
+                              GLsizei *length,
+                              GLchar *name);
+
+}  // namespace gl
+
+namespace egl
+{
+struct Config;
+
+void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value);
+
+}  // namespace egl
+
+#endif  // LIBANGLE_QUERYUTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/BufferImpl.h b/src/third_party/angle/src/libANGLE/renderer/BufferImpl.h
new file mode 100644
index 0000000..73afe37
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/BufferImpl.h
@@ -0,0 +1,68 @@
+//
+// 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.
+//
+
+// BufferImpl.h: Defines the abstract rx::BufferImpl class.
+
+#ifndef LIBANGLE_RENDERER_BUFFERIMPL_H_
+#define LIBANGLE_RENDERER_BUFFERIMPL_H_
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/Error.h"
+
+#include <stdint.h>
+
+namespace gl
+{
+class BufferState;
+}
+
+namespace rx
+{
+class ContextImpl;
+
+class BufferImpl : angle::NonCopyable
+{
+  public:
+    BufferImpl(const gl::BufferState &state) : mState(state) {}
+    virtual ~BufferImpl() {}
+    virtual void destroy(ContextImpl *contextImpl) {}
+
+    virtual gl::Error setData(ContextImpl *context,
+                              GLenum target,
+                              const void *data,
+                              size_t size,
+                              GLenum usage) = 0;
+    virtual gl::Error setSubData(ContextImpl *context,
+                                 GLenum target,
+                                 const void *data,
+                                 size_t size,
+                                 size_t offset) = 0;
+    virtual gl::Error copySubData(ContextImpl *contextImpl,
+                                  BufferImpl *source,
+                                  GLintptr sourceOffset,
+                                  GLintptr destOffset,
+                                  GLsizeiptr size) = 0;
+    virtual gl::Error map(ContextImpl *contextImpl, GLenum access, void **mapPtr) = 0;
+    virtual gl::Error mapRange(ContextImpl *contextImpl,
+                               size_t offset,
+                               size_t length,
+                               GLbitfield access,
+                               void **mapPtr) = 0;
+    virtual gl::Error unmap(ContextImpl *contextImpl, GLboolean *result) = 0;
+
+    virtual gl::Error getIndexRange(GLenum type,
+                                    size_t offset,
+                                    size_t count,
+                                    bool primitiveRestartEnabled,
+                                    gl::IndexRange *outRange) = 0;
+
+  protected:
+    const gl::BufferState &mState;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_BUFFERIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/BufferImpl_mock.h b/src/third_party/angle/src/libANGLE/renderer/BufferImpl_mock.h
new file mode 100644
index 0000000..16a6c1f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/BufferImpl_mock.h
@@ -0,0 +1,43 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferImpl_mock.h: Defines a mock of the BufferImpl class.
+
+#ifndef LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
+#define LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/renderer/BufferImpl.h"
+
+namespace rx
+{
+class MockBufferImpl : public BufferImpl
+{
+  public:
+    MockBufferImpl() : BufferImpl(mMockState) {}
+    ~MockBufferImpl() { destructor(); }
+
+    MOCK_METHOD5(setData, gl::Error(ContextImpl *, GLenum, const void *, size_t, GLenum));
+    MOCK_METHOD5(setSubData, gl::Error(ContextImpl *, GLenum, const void *, size_t, size_t));
+    MOCK_METHOD5(copySubData,
+                 gl::Error(ContextImpl *contextImpl, BufferImpl *, GLintptr, GLintptr, GLsizeiptr));
+    MOCK_METHOD3(map, gl::Error(ContextImpl *contextImpl, GLenum, void **));
+    MOCK_METHOD5(mapRange,
+                 gl::Error(ContextImpl *contextImpl, size_t, size_t, GLbitfield, void **));
+    MOCK_METHOD2(unmap, gl::Error(ContextImpl *contextImpl, GLboolean *result));
+
+    MOCK_METHOD5(getIndexRange, gl::Error(GLenum, size_t, size_t, bool, gl::IndexRange *));
+
+    MOCK_METHOD0(destructor, void());
+
+  protected:
+    gl::BufferState mMockState;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/CompilerImpl.h b/src/third_party/angle/src/libANGLE/renderer/CompilerImpl.h
new file mode 100644
index 0000000..82f1ffe
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/CompilerImpl.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompilerImpl.h: Defines the rx::CompilerImpl class, an implementation interface
+//                 for the gl::Compiler object.
+
+#include "common/angleutils.h"
+#include "GLSLANG/ShaderLang.h"
+#include "libANGLE/Error.h"
+
+#ifndef LIBANGLE_RENDERER_COMPILERIMPL_H_
+#define LIBANGLE_RENDERER_COMPILERIMPL_H_
+
+namespace rx
+{
+
+class CompilerImpl : angle::NonCopyable
+{
+  public:
+    CompilerImpl() {}
+    virtual ~CompilerImpl() {}
+
+    virtual gl::Error release() = 0;
+
+    // TODO(jmadill): Expose translator built-in resources init method.
+    virtual ShShaderOutput getTranslatorOutputType() const = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_COMPILERIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/ContextImpl.cpp b/src/third_party/angle/src/libANGLE/renderer/ContextImpl.cpp
new file mode 100644
index 0000000..0e1c9ff
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/ContextImpl.cpp
@@ -0,0 +1,113 @@
+//
+// Copyright 2016 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.
+//
+// ContextImpl:
+//   Implementation-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+
+ContextImpl::ContextImpl(const gl::ContextState &state) : mState(state)
+{
+}
+
+ContextImpl::~ContextImpl()
+{
+}
+
+void ContextImpl::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::coverFillPath(const gl::Path *path, GLenum coverMode)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::coverStrokePath(const gl::Path *path, GLenum coverMode)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverFillPath(const gl::Path *path,
+                                           GLenum fillMode,
+                                           GLuint mask,
+                                           GLenum coverMode)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverStrokePath(const gl::Path *path,
+                                             GLint reference,
+                                             GLuint mask,
+                                             GLenum coverMode)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                         GLenum coverMode,
+                                         GLenum transformType,
+                                         const GLfloat *transformValues)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                           GLenum coverMode,
+                                           GLenum transformType,
+                                           const GLfloat *transformValues)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                           GLenum fillMode,
+                                           GLuint mask,
+                                           GLenum transformType,
+                                           const GLfloat *transformValues)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                             GLint reference,
+                                             GLuint mask,
+                                             GLenum transformType,
+                                             const GLfloat *transformValues)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                                    GLenum coverMode,
+                                                    GLenum fillMode,
+                                                    GLuint mask,
+                                                    GLenum transformType,
+                                                    const GLfloat *transformValues)
+{
+    UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                                      GLenum coverMode,
+                                                      GLint reference,
+                                                      GLuint mask,
+                                                      GLenum transformType,
+                                                      const GLfloat *transformValues)
+{
+    UNREACHABLE();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/ContextImpl.h b/src/third_party/angle/src/libANGLE/renderer/ContextImpl.h
new file mode 100644
index 0000000..b5f1be9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/ContextImpl.h
@@ -0,0 +1,158 @@
+//
+// Copyright 2016 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.
+//
+// ContextImpl:
+//   Implementation-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_CONTEXTIMPL_H_
+#define LIBANGLE_RENDERER_CONTEXTIMPL_H_
+
+#include <vector>
+
+#include "common/angleutils.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+class Path;
+}
+
+namespace rx
+{
+class ContextImpl : public GLImplFactory
+{
+  public:
+    ContextImpl(const gl::ContextState &state);
+    virtual ~ContextImpl();
+
+    virtual gl::Error initialize() = 0;
+
+    // Flush and finish.
+    virtual gl::Error flush()  = 0;
+    virtual gl::Error finish() = 0;
+
+    // Drawing methods.
+    virtual gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) = 0;
+    virtual gl::Error drawArraysInstanced(GLenum mode,
+                                          GLint first,
+                                          GLsizei count,
+                                          GLsizei instanceCount) = 0;
+
+    virtual gl::Error drawElements(GLenum mode,
+                                   GLsizei count,
+                                   GLenum type,
+                                   const void *indices,
+                                   const gl::IndexRange &indexRange) = 0;
+    virtual gl::Error drawElementsInstanced(GLenum mode,
+                                            GLsizei count,
+                                            GLenum type,
+                                            const void *indices,
+                                            GLsizei instances,
+                                            const gl::IndexRange &indexRange) = 0;
+    virtual gl::Error drawRangeElements(GLenum mode,
+                                        GLuint start,
+                                        GLuint end,
+                                        GLsizei count,
+                                        GLenum type,
+                                        const void *indices,
+                                        const gl::IndexRange &indexRange) = 0;
+
+    virtual gl::Error drawArraysIndirect(GLenum mode, const void *indirect) = 0;
+    virtual gl::Error drawElementsIndirect(GLenum mode, GLenum type, const void *indirect) = 0;
+
+    // CHROMIUM_path_rendering path drawing methods.
+    virtual void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask);
+    virtual void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask);
+    virtual void coverFillPath(const gl::Path *path, GLenum coverMode);
+    virtual void coverStrokePath(const gl::Path *path, GLenum coverMode);
+    virtual void stencilThenCoverFillPath(const gl::Path *path,
+                                          GLenum fillMode,
+                                          GLuint mask,
+                                          GLenum coverMode);
+
+    virtual void stencilThenCoverStrokePath(const gl::Path *path,
+                                            GLint reference,
+                                            GLuint mask,
+                                            GLenum coverMode);
+
+    virtual void coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                        GLenum coverMode,
+                                        GLenum transformType,
+                                        const GLfloat *transformValues);
+    virtual void coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                          GLenum coverMode,
+                                          GLenum transformType,
+                                          const GLfloat *transformValues);
+    virtual void stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                          GLenum fillMode,
+                                          GLuint mask,
+                                          GLenum transformType,
+                                          const GLfloat *transformValues);
+    virtual void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                            GLint reference,
+                                            GLuint mask,
+                                            GLenum transformType,
+                                            const GLfloat *transformValues);
+    virtual void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                                   GLenum coverMode,
+                                                   GLenum fillMode,
+                                                   GLuint mask,
+                                                   GLenum transformType,
+                                                   const GLfloat *transformValues);
+    virtual void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                                     GLenum coverMode,
+                                                     GLint reference,
+                                                     GLuint mask,
+                                                     GLenum transformType,
+                                                     const GLfloat *transformValues);
+
+    // Device loss
+    virtual GLenum getResetStatus() = 0;
+
+    // Vendor and description strings.
+    virtual std::string getVendorString() const        = 0;
+    virtual std::string getRendererDescription() const = 0;
+
+    // Debug markers.
+    virtual void insertEventMarker(GLsizei length, const char *marker) = 0;
+    virtual void pushGroupMarker(GLsizei length, const char *marker)   = 0;
+    virtual void popGroupMarker() = 0;
+
+    // State sync with dirty bits.
+    virtual void syncState(const gl::State::DirtyBits &dirtyBits) = 0;
+
+    // Disjoint timer queries
+    virtual GLint getGPUDisjoint() = 0;
+    virtual GLint64 getTimestamp() = 0;
+
+    // Context switching
+    virtual void onMakeCurrent(const gl::ContextState &data) = 0;
+
+    // Native capabilities, unmodified by gl::Context.
+    virtual const gl::Caps &getNativeCaps() const                  = 0;
+    virtual const gl::TextureCapsMap &getNativeTextureCaps() const = 0;
+    virtual const gl::Extensions &getNativeExtensions() const      = 0;
+    virtual const gl::Limitations &getNativeLimitations() const    = 0;
+
+    virtual gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) = 0;
+
+    const gl::ContextState &getContextState() { return mState; }
+    int getClientMajorVersion() const { return mState.getClientMajorVersion(); }
+    int getClientMinorVersion() const { return mState.getClientMinorVersion(); }
+    const gl::State &getGLState() const { return mState.getState(); }
+    const gl::Caps &getCaps() const { return mState.getCaps(); }
+    const gl::TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); }
+    const gl::Extensions &getExtensions() const { return mState.getExtensions(); }
+    const gl::Limitations &getLimitations() const { return mState.getLimitations(); }
+
+  protected:
+    const gl::ContextState &mState;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_CONTEXTIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/DeviceImpl.cpp b/src/third_party/angle/src/libANGLE/renderer/DeviceImpl.cpp
new file mode 100644
index 0000000..6a16623
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/DeviceImpl.cpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DeviceImpl.cpp: Implementation methods of egl::Device
+
+#include "libANGLE/renderer/DeviceImpl.h"
+
+namespace rx
+{
+
+DeviceImpl::DeviceImpl()
+{
+}
+
+DeviceImpl::~DeviceImpl()
+{
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/DeviceImpl.h b/src/third_party/angle/src/libANGLE/renderer/DeviceImpl.h
new file mode 100644
index 0000000..550bc1e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/DeviceImpl.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DeviceImpl.h: Implementation methods of egl::Device
+
+#ifndef LIBANGLE_RENDERER_DEVICEIMPL_H_
+#define LIBANGLE_RENDERER_DEVICEIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Caps.h"
+
+namespace egl
+{
+class Device;
+}
+
+namespace rx
+{
+class DeviceImpl : angle::NonCopyable
+{
+  public:
+    DeviceImpl();
+    virtual ~DeviceImpl();
+
+    virtual egl::Error getDevice(void **outValue) = 0;
+    virtual EGLint getType() = 0;
+    virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0;
+    virtual bool deviceExternallySourced() = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_DEVICEIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp b/src/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp
new file mode 100644
index 0000000..080af37
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayImpl.cpp: Implementation methods of egl::Display
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+
+namespace rx
+{
+
+DisplayImpl::DisplayImpl(const egl::DisplayState &state)
+    : mState(state), mExtensionsInitialized(false), mCapsInitialized(false)
+{
+}
+
+DisplayImpl::~DisplayImpl()
+{
+    ASSERT(mState.surfaceSet.empty());
+}
+
+const egl::DisplayExtensions &DisplayImpl::getExtensions() const
+{
+    if (!mExtensionsInitialized)
+    {
+        generateExtensions(&mExtensions);
+        mExtensionsInitialized = true;
+    }
+
+    return mExtensions;
+}
+
+egl::Error DisplayImpl::validateClientBuffer(const egl::Config *configuration,
+                                             EGLenum buftype,
+                                             EGLClientBuffer clientBuffer,
+                                             const egl::AttributeMap &attribs) const
+{
+    UNREACHABLE();
+    return egl::Error(EGL_BAD_DISPLAY, "DisplayImpl::validateClientBuffer unimplemented.");
+}
+
+const egl::Caps &DisplayImpl::getCaps() const
+{
+    if (!mCapsInitialized)
+    {
+        generateCaps(&mCaps);
+        mCapsInitialized = true;
+    }
+
+    return mCaps;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/DisplayImpl.h b/src/third_party/angle/src/libANGLE/renderer/DisplayImpl.h
new file mode 100644
index 0000000..0b36758
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/DisplayImpl.h
@@ -0,0 +1,97 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayImpl.h: Implementation methods of egl::Display
+
+#ifndef LIBANGLE_RENDERER_DISPLAYIMPL_H_
+#define LIBANGLE_RENDERER_DISPLAYIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Version.h"
+
+#include <set>
+#include <vector>
+
+namespace egl
+{
+class AttributeMap;
+class Display;
+struct DisplayState;
+struct Config;
+class Surface;
+class ImageSibling;
+}
+
+namespace gl
+{
+class Context;
+}
+
+namespace rx
+{
+class SurfaceImpl;
+class ImageImpl;
+struct ConfigDesc;
+class DeviceImpl;
+class StreamProducerImpl;
+
+class DisplayImpl : public EGLImplFactory
+{
+  public:
+    DisplayImpl(const egl::DisplayState &state);
+    virtual ~DisplayImpl();
+
+    virtual egl::Error initialize(egl::Display *display) = 0;
+    virtual void terminate() = 0;
+
+    virtual egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) = 0;
+
+    virtual egl::ConfigSet generateConfigs() = 0;
+
+    virtual bool testDeviceLost() = 0;
+    virtual egl::Error restoreLostDevice() = 0;
+
+    virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0;
+    virtual egl::Error validateClientBuffer(const egl::Config *configuration,
+                                            EGLenum buftype,
+                                            EGLClientBuffer clientBuffer,
+                                            const egl::AttributeMap &attribs) const;
+
+    virtual std::string getVendorString() const = 0;
+
+    virtual egl::Error getDevice(DeviceImpl **device) = 0;
+
+    virtual egl::Error waitClient() const = 0;
+    virtual egl::Error waitNative(EGLint engine,
+                                  egl::Surface *drawSurface,
+                                  egl::Surface *readSurface) const = 0;
+    virtual gl::Version getMaxSupportedESVersion() const           = 0;
+    const egl::Caps &getCaps() const;
+
+    const egl::DisplayExtensions &getExtensions() const;
+
+  protected:
+    const egl::DisplayState &mState;
+
+  private:
+    virtual void generateExtensions(egl::DisplayExtensions *outExtensions) const = 0;
+    virtual void generateCaps(egl::Caps *outCaps) const = 0;
+
+    mutable bool mExtensionsInitialized;
+    mutable egl::DisplayExtensions mExtensions;
+
+    mutable bool mCapsInitialized;
+    mutable egl::Caps mCaps;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_DISPLAYIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/EGLImplFactory.h b/src/third_party/angle/src/libANGLE/renderer/EGLImplFactory.h
new file mode 100644
index 0000000..0433364
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/EGLImplFactory.h
@@ -0,0 +1,68 @@
+//
+// Copyright 2016 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.
+//
+// EGLImplFactory.h:
+//   Factory interface for EGL Impl objects.
+//
+
+#ifndef LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
+#define LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
+
+#include "libANGLE/Stream.h"
+
+namespace egl
+{
+class AttributeMap;
+struct Config;
+class ImageSibling;
+struct ImageState;
+struct SurfaceState;
+}
+
+namespace gl
+{
+class Context;
+class ContextState;
+}
+
+namespace rx
+{
+class ContextImpl;
+class ImageImpl;
+class SurfaceImpl;
+
+class EGLImplFactory : angle::NonCopyable
+{
+  public:
+    EGLImplFactory() {}
+    virtual ~EGLImplFactory() {}
+
+    virtual SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+                                             EGLNativeWindowType window,
+                                             const egl::AttributeMap &attribs) = 0;
+    virtual SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+                                              const egl::AttributeMap &attribs) = 0;
+    virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                                       EGLenum buftype,
+                                                       EGLClientBuffer clientBuffer,
+                                                       const egl::AttributeMap &attribs) = 0;
+    virtual SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+                                             NativePixmapType nativePixmap,
+                                             const egl::AttributeMap &attribs) = 0;
+
+    virtual ImageImpl *createImage(const egl::ImageState &state,
+                                   EGLenum target,
+                                   const egl::AttributeMap &attribs) = 0;
+
+    virtual ContextImpl *createContext(const gl::ContextState &state) = 0;
+
+    virtual StreamProducerImpl *createStreamProducerD3DTextureNV12(
+        egl::Stream::ConsumerType consumerType,
+        const egl::AttributeMap &attribs) = 0;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/FenceNVImpl.h b/src/third_party/angle/src/libANGLE/renderer/FenceNVImpl.h
new file mode 100644
index 0000000..a534914
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/FenceNVImpl.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FenceNVImpl.h: Defines the rx::FenceNVImpl class.
+
+#ifndef LIBANGLE_RENDERER_FENCENVIMPL_H_
+#define LIBANGLE_RENDERER_FENCENVIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+
+class FenceNVImpl : angle::NonCopyable
+{
+  public:
+    FenceNVImpl() { };
+    virtual ~FenceNVImpl() { };
+
+    virtual gl::Error set(GLenum condition) = 0;
+    virtual gl::Error test(GLboolean *outFinished) = 0;
+    virtual gl::Error finish() = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_FENCENVIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/FenceSyncImpl.h b/src/third_party/angle/src/libANGLE/renderer/FenceSyncImpl.h
new file mode 100644
index 0000000..6b78e69
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/FenceSyncImpl.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FenceSyncImpl.h: Defines the rx::FenceSyncImpl class.
+
+#ifndef LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+#define LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+
+class FenceSyncImpl : angle::NonCopyable
+{
+  public:
+    FenceSyncImpl() { };
+    virtual ~FenceSyncImpl() { };
+
+    virtual gl::Error set(GLenum condition, GLbitfield flags) = 0;
+    virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0;
+    virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0;
+    virtual gl::Error getStatus(GLint *outResult) = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_FENCESYNCIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/Format.h b/src/third_party/angle/src/libANGLE/renderer/Format.h
new file mode 100644
index 0000000..cc86883
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/Format.h
@@ -0,0 +1,101 @@
+//
+// Copyright 2016 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.
+//
+// Format:
+//   A universal description of typed GPU storage. Across multiple
+//   renderer back-ends, there are common formats and some distinct
+//   permutations, this enum encapsulates them all. Formats apply to
+//   textures, but could also apply to any typed data.
+
+#ifndef LIBANGLE_RENDERER_FORMAT_H_
+#define LIBANGLE_RENDERER_FORMAT_H_
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace angle
+{
+
+struct Format final : private angle::NonCopyable
+{
+    enum class ID;
+
+    constexpr Format(ID id,
+                     GLenum glFormat,
+                     GLenum fboFormat,
+                     rx::MipGenerationFunction mipGen,
+                     const rx::FastCopyFunctionMap &fastCopyFunctions,
+                     rx::ColorReadFunction colorRead,
+                     GLenum componentType,
+                     GLuint redBits,
+                     GLuint greenBits,
+                     GLuint blueBits,
+                     GLuint alphaBits,
+                     GLuint depthBits,
+                     GLuint stencilBits);
+
+    static const Format &Get(ID id);
+
+    ID id;
+
+    // The closest matching GL internal format for the storage this format uses. Note that this
+    // may be a different internal format than the one this ANGLE format is used for.
+    GLenum glInternalFormat;
+
+    // The format we should report to the GL layer when querying implementation formats from a FBO.
+    // This might not be the same as the glInternalFormat, since some DXGI formats don't have
+    // matching GL format enums, like BGRA4, BGR5A1 and B5G6R6.
+    GLenum fboImplementationInternalFormat;
+
+    rx::MipGenerationFunction mipGenerationFunction;
+    rx::ColorReadFunction colorReadFunction;
+
+    // A map from a gl::FormatType to a fast pixel copy function for this format.
+    const rx::FastCopyFunctionMap &fastCopyFunctions;
+
+    GLenum componentType;
+
+    GLuint redBits;
+    GLuint greenBits;
+    GLuint blueBits;
+    GLuint alphaBits;
+    GLuint depthBits;
+    GLuint stencilBits;
+};
+
+constexpr Format::Format(ID id,
+                         GLenum glFormat,
+                         GLenum fboFormat,
+                         rx::MipGenerationFunction mipGen,
+                         const rx::FastCopyFunctionMap &fastCopyFunctions,
+                         rx::ColorReadFunction colorRead,
+                         GLenum componentType,
+                         GLuint redBits,
+                         GLuint greenBits,
+                         GLuint blueBits,
+                         GLuint alphaBits,
+                         GLuint depthBits,
+                         GLuint stencilBits)
+    : id(id),
+      glInternalFormat(glFormat),
+      fboImplementationInternalFormat(fboFormat),
+      mipGenerationFunction(mipGen),
+      colorReadFunction(colorRead),
+      fastCopyFunctions(fastCopyFunctions),
+      componentType(componentType),
+      redBits(redBits),
+      greenBits(greenBits),
+      blueBits(blueBits),
+      alphaBits(alphaBits),
+      depthBits(depthBits),
+      stencilBits(stencilBits)
+{
+}
+
+}  // namespace angle
+
+#include "libANGLE/renderer/Format_ID_autogen.inl"
+
+#endif  // LIBANGLE_RENDERER_FORMAT_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/Format_ID_autogen.inl b/src/third_party/angle/src/libANGLE/renderer/Format_ID_autogen.inl
new file mode 100644
index 0000000..5c01b50
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/Format_ID_autogen.inl
@@ -0,0 +1,142 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_angle_format_table.py using data from angle_format_data.json
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLE format enumeration.
+
+namespace angle
+{
+
+enum class Format::ID
+{
+    NONE,
+    A16_FLOAT,
+    A32_FLOAT,
+    A8_UNORM,
+    ASTC_10x10_SRGB_BLOCK,
+    ASTC_10x10_UNORM_BLOCK,
+    ASTC_10x5_SRGB_BLOCK,
+    ASTC_10x5_UNORM_BLOCK,
+    ASTC_10x6_SRGB_BLOCK,
+    ASTC_10x6_UNORM_BLOCK,
+    ASTC_10x8_SRGB_BLOCK,
+    ASTC_10x8_UNORM_BLOCK,
+    ASTC_12x10_SRGB_BLOCK,
+    ASTC_12x10_UNORM_BLOCK,
+    ASTC_12x12_SRGB_BLOCK,
+    ASTC_12x12_UNORM_BLOCK,
+    ASTC_4x4_SRGB_BLOCK,
+    ASTC_4x4_UNORM_BLOCK,
+    ASTC_5x4_SRGB_BLOCK,
+    ASTC_5x4_UNORM_BLOCK,
+    ASTC_5x5_SRGB_BLOCK,
+    ASTC_5x5_UNORM_BLOCK,
+    ASTC_6x5_SRGB_BLOCK,
+    ASTC_6x5_UNORM_BLOCK,
+    ASTC_6x6_SRGB_BLOCK,
+    ASTC_6x6_UNORM_BLOCK,
+    ASTC_8x5_SRGB_BLOCK,
+    ASTC_8x5_UNORM_BLOCK,
+    ASTC_8x6_SRGB_BLOCK,
+    ASTC_8x6_UNORM_BLOCK,
+    ASTC_8x8_SRGB_BLOCK,
+    ASTC_8x8_UNORM_BLOCK,
+    B4G4R4A4_UNORM,
+    B5G5R5A1_UNORM,
+    B5G6R5_UNORM,
+    B8G8R8A8_UNORM,
+    B8G8R8X8_UNORM,
+    BC1_RGBA_UNORM_BLOCK,
+    BC1_RGBA_UNORM_SRGB_BLOCK,
+    BC1_RGB_UNORM_BLOCK,
+    BC1_RGB_UNORM_SRGB_BLOCK,
+    BC2_RGBA_UNORM_BLOCK,
+    BC2_RGBA_UNORM_SRGB_BLOCK,
+    BC3_RGBA_UNORM_BLOCK,
+    BC3_RGBA_UNORM_SRGB_BLOCK,
+    D16_UNORM,
+    D24_UNORM,
+    D24_UNORM_S8_UINT,
+    D32_FLOAT,
+    D32_FLOAT_S8X24_UINT,
+    D32_UNORM,
+    EAC_R11G11_SNORM_BLOCK,
+    EAC_R11G11_UNORM_BLOCK,
+    EAC_R11_SNORM_BLOCK,
+    EAC_R11_UNORM_BLOCK,
+    ETC2_R8G8B8A1_SRGB_BLOCK,
+    ETC2_R8G8B8A1_UNORM_BLOCK,
+    ETC2_R8G8B8A8_SRGB_BLOCK,
+    ETC2_R8G8B8A8_UNORM_BLOCK,
+    ETC2_R8G8B8_SRGB_BLOCK,
+    ETC2_R8G8B8_UNORM_BLOCK,
+    L16A16_FLOAT,
+    L16_FLOAT,
+    L32A32_FLOAT,
+    L32_FLOAT,
+    L8A8_UNORM,
+    L8_UNORM,
+    R10G10B10A2_UINT,
+    R10G10B10A2_UNORM,
+    R11G11B10_FLOAT,
+    R16G16B16A16_FLOAT,
+    R16G16B16A16_SINT,
+    R16G16B16A16_SNORM,
+    R16G16B16A16_UINT,
+    R16G16B16A16_UNORM,
+    R16G16B16_FLOAT,
+    R16G16B16_SINT,
+    R16G16B16_SNORM,
+    R16G16B16_UINT,
+    R16G16B16_UNORM,
+    R16G16_FLOAT,
+    R16G16_SINT,
+    R16G16_SNORM,
+    R16G16_UINT,
+    R16G16_UNORM,
+    R16_FLOAT,
+    R16_SINT,
+    R16_SNORM,
+    R16_UINT,
+    R16_UNORM,
+    R32G32B32A32_FLOAT,
+    R32G32B32A32_SINT,
+    R32G32B32A32_UINT,
+    R32G32B32_FLOAT,
+    R32G32B32_SINT,
+    R32G32B32_UINT,
+    R32G32_FLOAT,
+    R32G32_SINT,
+    R32G32_UINT,
+    R32_FLOAT,
+    R32_SINT,
+    R32_UINT,
+    R4G4B4A4_UNORM,
+    R5G5B5A1_UNORM,
+    R5G6B5_UNORM,
+    R8G8B8A8_SINT,
+    R8G8B8A8_SNORM,
+    R8G8B8A8_UINT,
+    R8G8B8A8_UNORM,
+    R8G8B8A8_UNORM_SRGB,
+    R8G8B8_SINT,
+    R8G8B8_SNORM,
+    R8G8B8_UINT,
+    R8G8B8_UNORM,
+    R8G8B8_UNORM_SRGB,
+    R8G8_SINT,
+    R8G8_SNORM,
+    R8G8_UINT,
+    R8G8_UNORM,
+    R8_SINT,
+    R8_SNORM,
+    R8_UINT,
+    R8_UNORM,
+    R9G9B9E5_SHAREDEXP,
+    S8_UINT
+};
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/libANGLE/renderer/Format_table_autogen.cpp b/src/third_party/angle/src/libANGLE/renderer/Format_table_autogen.cpp
new file mode 100644
index 0000000..13b46f3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/Format_table_autogen.cpp
@@ -0,0 +1,161 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_angle_format_table.py using data from angle_format_data.json
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLE Format table:
+//   Queries for typed format information from the ANGLE format enum.
+
+#include "libANGLE/renderer/Format.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+namespace angle
+{
+
+static constexpr rx::FastCopyFunctionMap::Entry BGRAEntry = {GL_RGBA, GL_UNSIGNED_BYTE,
+                                                             CopyBGRA8ToRGBA8};
+static constexpr rx::FastCopyFunctionMap BGRACopyFunctions = {&BGRAEntry, 1};
+static constexpr rx::FastCopyFunctionMap NoCopyFunctions;
+
+constexpr Format g_formatInfoTable[] = {
+    // clang-format off
+    { Format::ID::NONE, GL_NONE, GL_NONE, nullptr, NoCopyFunctions, nullptr, GL_NONE, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::A16_FLOAT, GL_ALPHA16F_EXT, GL_ALPHA16F_EXT, GenerateMip<A16F>, NoCopyFunctions, ReadColor<A16F, GLfloat>, GL_FLOAT, 0, 0, 0, 16, 0, 0 },
+    { Format::ID::A32_FLOAT, GL_ALPHA32F_EXT, GL_ALPHA32F_EXT, GenerateMip<A32F>, NoCopyFunctions, ReadColor<A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 0, 0 },
+    { Format::ID::A8_UNORM, GL_ALPHA8_EXT, GL_ALPHA8_EXT, GenerateMip<A8>, NoCopyFunctions, ReadColor<A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 8, 0, 0 },
+    { Format::ID::ASTC_10x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_10x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_10x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_10x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_10x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_10x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_10x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_10x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_12x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_12x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_12x12_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_12x12_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_4x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_4x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_5x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_5x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_5x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_5x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_6x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_6x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_6x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_6x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_8x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_8x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_8x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_8x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_8x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::ASTC_8x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::B4G4R4A4_UNORM, GL_BGRA4_ANGLEX, GL_RGBA4, GenerateMip<A4R4G4B4>, NoCopyFunctions, ReadColor<A4R4G4B4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0 },
+    { Format::ID::B5G5R5A1_UNORM, GL_BGR5_A1_ANGLEX, GL_RGB5_A1, GenerateMip<A1R5G5B5>, NoCopyFunctions, ReadColor<A1R5G5B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0 },
+    { Format::ID::B5G6R5_UNORM, GL_BGR565_ANGLEX, GL_RGB565, GenerateMip<B5G6R5>, NoCopyFunctions, ReadColor<B5G6R5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0 },
+    { Format::ID::B8G8R8A8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, BGRACopyFunctions, ReadColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+    { Format::ID::B8G8R8X8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, NoCopyFunctions, ReadColor<B8G8R8X8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+    { Format::ID::BC1_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::BC1_RGB_UNORM_BLOCK, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::BC1_RGB_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::BC2_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::BC3_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::D16_UNORM, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT16, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 16, 0 },
+    { Format::ID::D24_UNORM, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT24, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 24, 0 },
+    { Format::ID::D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 24, 8 },
+    { Format::ID::D32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, nullptr, NoCopyFunctions, nullptr, GL_FLOAT, 0, 0, 0, 0, 32, 0 },
+    { Format::ID::D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, nullptr, NoCopyFunctions, nullptr, GL_FLOAT, 0, 0, 0, 0, 32, 8 },
+    { Format::ID::D32_UNORM, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT32_OES, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 32, 0 },
+    { Format::ID::EAC_R11G11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, GL_SIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0 },
+    { Format::ID::EAC_R11G11_UNORM_BLOCK, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0 },
+    { Format::ID::EAC_R11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, nullptr, NoCopyFunctions, nullptr, GL_SIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0 },
+    { Format::ID::EAC_R11_UNORM_BLOCK, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0 },
+    { Format::ID::ETC2_R8G8B8A1_SRGB_BLOCK, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0 },
+    { Format::ID::ETC2_R8G8B8A1_UNORM_BLOCK, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0 },
+    { Format::ID::ETC2_R8G8B8A8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+    { Format::ID::ETC2_R8G8B8A8_UNORM_BLOCK, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+    { Format::ID::ETC2_R8G8B8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+    { Format::ID::ETC2_R8G8B8_UNORM_BLOCK, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+    { Format::ID::L16A16_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA16F_EXT, GenerateMip<L16A16F>, NoCopyFunctions, ReadColor<L16A16F, GLfloat>, GL_FLOAT, 0, 0, 0, 16, 0, 0 },
+    { Format::ID::L16_FLOAT, GL_LUMINANCE16F_EXT, GL_LUMINANCE16F_EXT, GenerateMip<L16F>, NoCopyFunctions, ReadColor<L16F, GLfloat>, GL_FLOAT, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::L32A32_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA32F_EXT, GenerateMip<L32A32F>, NoCopyFunctions, ReadColor<L32A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 0, 0 },
+    { Format::ID::L32_FLOAT, GL_LUMINANCE32F_EXT, GL_LUMINANCE32F_EXT, GenerateMip<L32F>, NoCopyFunctions, ReadColor<L32F, GLfloat>, GL_FLOAT, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::L8A8_UNORM, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<L8A8>, NoCopyFunctions, ReadColor<L8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 8, 0, 0 },
+    { Format::ID::L8_UNORM, GL_LUMINANCE8_EXT, GL_LUMINANCE8_EXT, GenerateMip<L8>, NoCopyFunctions, ReadColor<L8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+    { Format::ID::R10G10B10A2_UINT, GL_RGB10_A2UI, GL_RGB10_A2UI, GenerateMip<R10G10B10A2>, NoCopyFunctions, ReadColor<R10G10B10A2, GLuint>, GL_UNSIGNED_INT, 10, 10, 10, 2, 0, 0 },
+    { Format::ID::R10G10B10A2_UNORM, GL_RGB10_A2, GL_RGB10_A2, GenerateMip<R10G10B10A2>, NoCopyFunctions, ReadColor<R10G10B10A2, GLfloat>, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 2, 0, 0 },
+    { Format::ID::R11G11B10_FLOAT, GL_R11F_G11F_B10F, GL_R11F_G11F_B10F, GenerateMip<R11G11B10F>, NoCopyFunctions, ReadColor<R11G11B10F, GLfloat>, GL_FLOAT, 11, 11, 10, 0, 0, 0 },
+    { Format::ID::R16G16B16A16_FLOAT, GL_RGBA16F, GL_RGBA16F, GenerateMip<R16G16B16A16F>, NoCopyFunctions, ReadColor<R16G16B16A16F, GLfloat>, GL_FLOAT, 16, 16, 16, 16, 0, 0 },
+    { Format::ID::R16G16B16A16_SINT, GL_RGBA16I, GL_RGBA16I, GenerateMip<R16G16B16A16S>, NoCopyFunctions, ReadColor<R16G16B16A16S, GLint>, GL_INT, 16, 16, 16, 16, 0, 0 },
+    { Format::ID::R16G16B16A16_SNORM, GL_RGBA16_SNORM_EXT, GL_RGBA16_SNORM_EXT, GenerateMip<R16G16B16A16S>, NoCopyFunctions, ReadColor<R16G16B16A16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 16, 16, 0, 0 },
+    { Format::ID::R16G16B16A16_UINT, GL_RGBA16UI, GL_RGBA16UI, GenerateMip<R16G16B16A16>, NoCopyFunctions, ReadColor<R16G16B16A16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 16, 0, 0 },
+    { Format::ID::R16G16B16A16_UNORM, GL_RGBA16_EXT, GL_RGBA16_EXT, GenerateMip<R16G16B16A16>, NoCopyFunctions, ReadColor<R16G16B16A16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 16, 16, 0, 0 },
+    { Format::ID::R16G16B16_FLOAT, GL_RGB16F, GL_RGB16F, GenerateMip<R16G16B16F>, NoCopyFunctions, ReadColor<R16G16B16F, GLfloat>, GL_FLOAT, 16, 16, 16, 0, 0, 0 },
+    { Format::ID::R16G16B16_SINT, GL_RGB16I, GL_RGB16I, GenerateMip<R16G16B16S>, NoCopyFunctions, ReadColor<R16G16B16S, GLint>, GL_INT, 16, 16, 16, 0, 0, 0 },
+    { Format::ID::R16G16B16_SNORM, GL_RGB16_SNORM_EXT, GL_RGB16_SNORM_EXT, GenerateMip<R16G16B16S>, NoCopyFunctions, ReadColor<R16G16B16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 16, 0, 0, 0 },
+    { Format::ID::R16G16B16_UINT, GL_RGB16UI, GL_RGB16UI, GenerateMip<R16G16B16>, NoCopyFunctions, ReadColor<R16G16B16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 0, 0, 0 },
+    { Format::ID::R16G16B16_UNORM, GL_RGB16_EXT, GL_RGB16_EXT, GenerateMip<R16G16B16>, NoCopyFunctions, ReadColor<R16G16B16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 16, 0, 0, 0 },
+    { Format::ID::R16G16_FLOAT, GL_RG16F, GL_RG16F, GenerateMip<R16G16F>, NoCopyFunctions, ReadColor<R16G16F, GLfloat>, GL_FLOAT, 16, 16, 0, 0, 0, 0 },
+    { Format::ID::R16G16_SINT, GL_RG16I, GL_RG16I, GenerateMip<R16G16S>, NoCopyFunctions, ReadColor<R16G16S, GLint>, GL_INT, 16, 16, 0, 0, 0, 0 },
+    { Format::ID::R16G16_SNORM, GL_RG16_SNORM_EXT, GL_RG16_SNORM_EXT, GenerateMip<R16G16S>, NoCopyFunctions, ReadColor<R16G16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 0, 0, 0, 0 },
+    { Format::ID::R16G16_UINT, GL_RG16UI, GL_RG16UI, GenerateMip<R16G16>, NoCopyFunctions, ReadColor<R16G16, GLuint>, GL_UNSIGNED_INT, 16, 16, 0, 0, 0, 0 },
+    { Format::ID::R16G16_UNORM, GL_RG16_EXT, GL_RG16_EXT, GenerateMip<R16G16>, NoCopyFunctions, ReadColor<R16G16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 0, 0, 0, 0 },
+    { Format::ID::R16_FLOAT, GL_R16F, GL_R16F, GenerateMip<R16F>, NoCopyFunctions, ReadColor<R16F, GLfloat>, GL_FLOAT, 16, 0, 0, 0, 0, 0 },
+    { Format::ID::R16_SINT, GL_R16I, GL_R16I, GenerateMip<R16S>, NoCopyFunctions, ReadColor<R16S, GLint>, GL_INT, 16, 0, 0, 0, 0, 0 },
+    { Format::ID::R16_SNORM, GL_R16_SNORM_EXT, GL_R16_SNORM_EXT, GenerateMip<R16S>, NoCopyFunctions, ReadColor<R16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 0, 0, 0, 0, 0 },
+    { Format::ID::R16_UINT, GL_R16UI, GL_R16UI, GenerateMip<R16>, NoCopyFunctions, ReadColor<R16, GLuint>, GL_UNSIGNED_INT, 16, 0, 0, 0, 0, 0 },
+    { Format::ID::R16_UNORM, GL_R16_EXT, GL_R16_EXT, GenerateMip<R16>, NoCopyFunctions, ReadColor<R16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 0, 0, 0, 0, 0 },
+    { Format::ID::R32G32B32A32_FLOAT, GL_RGBA32F, GL_RGBA32F, GenerateMip<R32G32B32A32F>, NoCopyFunctions, ReadColor<R32G32B32A32F, GLfloat>, GL_FLOAT, 32, 32, 32, 32, 0, 0 },
+    { Format::ID::R32G32B32A32_SINT, GL_RGBA32I, GL_RGBA32I, GenerateMip<R32G32B32A32S>, NoCopyFunctions, ReadColor<R32G32B32A32S, GLint>, GL_INT, 32, 32, 32, 32, 0, 0 },
+    { Format::ID::R32G32B32A32_UINT, GL_RGBA32UI, GL_RGBA32UI, GenerateMip<R32G32B32A32>, NoCopyFunctions, ReadColor<R32G32B32A32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 32, 0, 0 },
+    { Format::ID::R32G32B32_FLOAT, GL_RGB32F, GL_RGB32F, GenerateMip<R32G32B32F>, NoCopyFunctions, ReadColor<R32G32B32F, GLfloat>, GL_FLOAT, 32, 32, 32, 0, 0, 0 },
+    { Format::ID::R32G32B32_SINT, GL_RGB32I, GL_RGB32I, GenerateMip<R32G32B32S>, NoCopyFunctions, ReadColor<R32G32B32S, GLint>, GL_INT, 32, 32, 32, 0, 0, 0 },
+    { Format::ID::R32G32B32_UINT, GL_RGB32UI, GL_RGB32UI, GenerateMip<R32G32B32>, NoCopyFunctions, ReadColor<R32G32B32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 0, 0, 0 },
+    { Format::ID::R32G32_FLOAT, GL_RG32F, GL_RG32F, GenerateMip<R32G32F>, NoCopyFunctions, ReadColor<R32G32F, GLfloat>, GL_FLOAT, 32, 32, 0, 0, 0, 0 },
+    { Format::ID::R32G32_SINT, GL_RG32I, GL_RG32I, GenerateMip<R32G32S>, NoCopyFunctions, ReadColor<R32G32S, GLint>, GL_INT, 32, 32, 0, 0, 0, 0 },
+    { Format::ID::R32G32_UINT, GL_RG32UI, GL_RG32UI, GenerateMip<R32G32>, NoCopyFunctions, ReadColor<R32G32, GLuint>, GL_UNSIGNED_INT, 32, 32, 0, 0, 0, 0 },
+    { Format::ID::R32_FLOAT, GL_R32F, GL_R32F, GenerateMip<R32F>, NoCopyFunctions, ReadColor<R32F, GLfloat>, GL_FLOAT, 32, 0, 0, 0, 0, 0 },
+    { Format::ID::R32_SINT, GL_R32I, GL_R32I, GenerateMip<R32S>, NoCopyFunctions, ReadColor<R32S, GLint>, GL_INT, 32, 0, 0, 0, 0, 0 },
+    { Format::ID::R32_UINT, GL_R32UI, GL_R32UI, GenerateMip<R32>, NoCopyFunctions, ReadColor<R32, GLuint>, GL_UNSIGNED_INT, 32, 0, 0, 0, 0, 0 },
+    { Format::ID::R4G4B4A4_UNORM, GL_RGBA4, GL_RGBA4, GenerateMip<R4G4B4A4>, NoCopyFunctions, ReadColor<R4G4B4A4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0 },
+    { Format::ID::R5G5B5A1_UNORM, GL_RGB5_A1, GL_RGB5_A1, GenerateMip<R5G5B5A1>, NoCopyFunctions, ReadColor<R5G5B5A1, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0 },
+    { Format::ID::R5G6B5_UNORM, GL_RGB565, GL_RGB565, GenerateMip<R5G6B5>, NoCopyFunctions, ReadColor<R5G6B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0 },
+    { Format::ID::R8G8B8A8_SINT, GL_RGBA8I, GL_RGBA8I, GenerateMip<R8G8B8A8S>, NoCopyFunctions, ReadColor<R8G8B8A8S, GLint>, GL_INT, 8, 8, 8, 8, 0, 0 },
+    { Format::ID::R8G8B8A8_SNORM, GL_RGBA8_SNORM, GL_RGBA8_SNORM, GenerateMip<R8G8B8A8S>, NoCopyFunctions, ReadColor<R8G8B8A8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+    { Format::ID::R8G8B8A8_UINT, GL_RGBA8UI, GL_RGBA8UI, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 8, 0, 0 },
+    { Format::ID::R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA8, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+    { Format::ID::R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GenerateMip<R8G8B8A8SRGB>, NoCopyFunctions, ReadColor<R8G8B8A8SRGB, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+    { Format::ID::R8G8B8_SINT, GL_RGB8I, GL_RGB8I, GenerateMip<R8G8B8S>, NoCopyFunctions, ReadColor<R8G8B8S, GLint>, GL_INT, 8, 8, 8, 0, 0, 0 },
+    { Format::ID::R8G8B8_SNORM, GL_RGB8_SNORM, GL_RGB8_SNORM, GenerateMip<R8G8B8S>, NoCopyFunctions, ReadColor<R8G8B8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+    { Format::ID::R8G8B8_UINT, GL_RGB8UI, GL_RGB8UI, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 0, 0, 0 },
+    { Format::ID::R8G8B8_UNORM, GL_RGB8, GL_RGB8, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+    { Format::ID::R8G8B8_UNORM_SRGB, GL_SRGB8, GL_SRGB8, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+    { Format::ID::R8G8_SINT, GL_RG8I, GL_RG8I, GenerateMip<R8G8S>, NoCopyFunctions, ReadColor<R8G8S, GLint>, GL_INT, 8, 8, 0, 0, 0, 0 },
+    { Format::ID::R8G8_SNORM, GL_RG8_SNORM, GL_RG8_SNORM, GenerateMip<R8G8S>, NoCopyFunctions, ReadColor<R8G8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 0, 0, 0, 0 },
+    { Format::ID::R8G8_UINT, GL_RG8UI, GL_RG8UI, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLuint>, GL_UNSIGNED_INT, 8, 8, 0, 0, 0, 0 },
+    { Format::ID::R8G8_UNORM, GL_RG8, GL_RG8, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 0, 0, 0, 0 },
+    { Format::ID::R8_SINT, GL_R8I, GL_R8I, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLint>, GL_INT, 8, 0, 0, 0, 0, 0 },
+    { Format::ID::R8_SNORM, GL_R8_SNORM, GL_R8_SNORM, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0 },
+    { Format::ID::R8_UINT, GL_R8UI, GL_R8UI, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLuint>, GL_UNSIGNED_INT, 8, 0, 0, 0, 0, 0 },
+    { Format::ID::R8_UNORM, GL_R8, GL_R8, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0 },
+    { Format::ID::R9G9B9E5_SHAREDEXP, GL_RGB9_E5, GL_RGB9_E5, GenerateMip<R9G9B9E5>, NoCopyFunctions, ReadColor<R9G9B9E5, GLfloat>, GL_FLOAT, 9, 9, 9, 0, 0, 0 },
+    { Format::ID::S8_UINT, GL_STENCIL_INDEX8, GL_STENCIL_INDEX8, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_INT, 0, 0, 0, 0, 0, 8 },
+    // clang-format on
+};
+
+// static
+const Format &Format::Get(ID id)
+{
+    return g_formatInfoTable[static_cast<size_t>(id)];
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h b/src/third_party/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
new file mode 100644
index 0000000..0af12ec
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2016 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.
+//
+// FramebufferAttachmentObjectImpl.h:
+//   Common ancenstor for all implementations of FBO attachable-objects.
+//   This means Surfaces, Textures and Renderbuffers.
+//
+
+#ifndef LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
+#define LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
+
+#include "libANGLE/FramebufferAttachment.h"
+
+namespace rx
+{
+
+class FramebufferAttachmentObjectImpl : angle::NonCopyable
+{
+  public:
+    FramebufferAttachmentObjectImpl() {}
+    virtual ~FramebufferAttachmentObjectImpl() {}
+
+    virtual gl::Error getAttachmentRenderTarget(GLenum binding,
+                                                const gl::ImageIndex &imageIndex,
+                                                FramebufferAttachmentRenderTarget **rtOut)
+    {
+        UNIMPLEMENTED();
+        return gl::OutOfMemory() << "getAttachmentRenderTarget not supported.";
+    }
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h b/src/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h
new file mode 100644
index 0000000..b4438f8
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h
@@ -0,0 +1,90 @@
+//
+// 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.
+//
+
+// FramebufferImpl.h: Defines the abstract rx::FramebufferImpl class.
+
+#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
+#define LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
+
+namespace gl
+{
+class State;
+class Framebuffer;
+class FramebufferAttachment;
+struct Rectangle;
+}
+
+namespace rx
+{
+class DisplayImpl;
+
+class FramebufferImpl : angle::NonCopyable
+{
+  public:
+    explicit FramebufferImpl(const gl::FramebufferState &state) : mState(state) {}
+    virtual ~FramebufferImpl() {}
+    virtual void destroy(ContextImpl *contextImpl) {}
+    virtual void destroyDefault(DisplayImpl *displayImpl) {}
+
+    virtual gl::Error discard(size_t count, const GLenum *attachments)    = 0;
+    virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0;
+    virtual gl::Error invalidateSub(size_t count,
+                                    const GLenum *attachments,
+                                    const gl::Rectangle &area) = 0;
+
+    virtual gl::Error clear(ContextImpl *context, GLbitfield mask) = 0;
+    virtual gl::Error clearBufferfv(ContextImpl *context,
+                                    GLenum buffer,
+                                    GLint drawbuffer,
+                                    const GLfloat *values) = 0;
+    virtual gl::Error clearBufferuiv(ContextImpl *context,
+                                     GLenum buffer,
+                                     GLint drawbuffer,
+                                     const GLuint *values) = 0;
+    virtual gl::Error clearBufferiv(ContextImpl *context,
+                                    GLenum buffer,
+                                    GLint drawbuffer,
+                                    const GLint *values) = 0;
+    virtual gl::Error clearBufferfi(ContextImpl *context,
+                                    GLenum buffer,
+                                    GLint drawbuffer,
+                                    GLfloat depth,
+                                    GLint stencil) = 0;
+
+    virtual GLenum getImplementationColorReadFormat() const = 0;
+    virtual GLenum getImplementationColorReadType() const   = 0;
+    virtual gl::Error readPixels(ContextImpl *context,
+                                 const gl::Rectangle &area,
+                                 GLenum format,
+                                 GLenum type,
+                                 void *pixels) const = 0;
+
+    virtual gl::Error blit(ContextImpl *context,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Rectangle &destArea,
+                           GLbitfield mask,
+                           GLenum filter) = 0;
+
+    virtual bool checkStatus() const = 0;
+
+    virtual void syncState(ContextImpl *contextImpl,
+                           const gl::Framebuffer::DirtyBits &dirtyBits) = 0;
+
+    virtual gl::Error getSamplePosition(size_t index, GLfloat *xy) const = 0;
+
+    const gl::FramebufferState &getState() const { return mState; }
+
+  protected:
+    const gl::FramebufferState &mState;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h b/src/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
new file mode 100644
index 0000000..401ddb4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
@@ -0,0 +1,69 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FramebufferImpl_mock.h:
+//   Defines a mock of the FramebufferImpl class.
+//
+
+#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_
+#define LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace rx
+{
+
+class MockFramebufferImpl : public rx::FramebufferImpl
+{
+  public:
+    MockFramebufferImpl() : rx::FramebufferImpl(gl::FramebufferState()) {}
+    virtual ~MockFramebufferImpl() { destructor(); }
+
+    MOCK_METHOD2(discard, gl::Error(size_t, const GLenum *));
+    MOCK_METHOD2(invalidate, gl::Error(size_t, const GLenum *));
+    MOCK_METHOD3(invalidateSub, gl::Error(size_t, const GLenum *, const gl::Rectangle &));
+
+    MOCK_METHOD2(clear, gl::Error(ContextImpl *, GLbitfield));
+    MOCK_METHOD4(clearBufferfv, gl::Error(ContextImpl *, GLenum, GLint, const GLfloat *));
+    MOCK_METHOD4(clearBufferuiv, gl::Error(ContextImpl *, GLenum, GLint, const GLuint *));
+    MOCK_METHOD4(clearBufferiv, gl::Error(ContextImpl *, GLenum, GLint, const GLint *));
+    MOCK_METHOD5(clearBufferfi, gl::Error(ContextImpl *, GLenum, GLint, GLfloat, GLint));
+
+    MOCK_CONST_METHOD0(getImplementationColorReadFormat, GLenum());
+    MOCK_CONST_METHOD0(getImplementationColorReadType, GLenum());
+    MOCK_CONST_METHOD5(readPixels,
+                       gl::Error(ContextImpl *, const gl::Rectangle &, GLenum, GLenum, void *));
+
+    MOCK_CONST_METHOD2(getSamplePosition, gl::Error(size_t, GLfloat *));
+
+    MOCK_METHOD5(
+        blit,
+        gl::Error(ContextImpl *, const gl::Rectangle &, const gl::Rectangle &, GLbitfield, GLenum));
+
+    MOCK_CONST_METHOD0(checkStatus, bool());
+
+    MOCK_METHOD2(syncState, void(ContextImpl *, const gl::Framebuffer::DirtyBits &));
+
+    MOCK_METHOD0(destructor, void());
+};
+
+inline ::testing::NiceMock<MockFramebufferImpl> *MakeFramebufferMock()
+{
+    ::testing::NiceMock<MockFramebufferImpl> *framebufferImpl =
+        new ::testing::NiceMock<MockFramebufferImpl>();
+    // TODO(jmadill): add ON_CALLS for other returning methods
+    ON_CALL(*framebufferImpl, checkStatus()).WillByDefault(::testing::Return(true));
+
+    // We must mock the destructor since NiceMock doesn't work for destructors.
+    EXPECT_CALL(*framebufferImpl, destructor()).Times(1).RetiresOnSaturation();
+
+    return framebufferImpl;
+}
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/GLImplFactory.h b/src/third_party/angle/src/libANGLE/renderer/GLImplFactory.h
new file mode 100644
index 0000000..20a48fc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/GLImplFactory.h
@@ -0,0 +1,88 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// GLImplFactory.h:
+//   Factory interface for OpenGL ES Impl objects.
+//
+
+#ifndef LIBANGLE_RENDERER_GLIMPLFACTORY_H_
+#define LIBANGLE_RENDERER_GLIMPLFACTORY_H_
+
+#include <vector>
+
+#include "angle_gl.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+
+namespace gl
+{
+class ContextState;
+}
+
+namespace rx
+{
+class BufferImpl;
+class CompilerImpl;
+class ContextImpl;
+class FenceNVImpl;
+class FenceSyncImpl;
+class FramebufferImpl;
+class PathImpl;
+class ProgramImpl;
+class QueryImpl;
+class RenderbufferImpl;
+class SamplerImpl;
+class ShaderImpl;
+class TextureImpl;
+class TransformFeedbackImpl;
+class VertexArrayImpl;
+
+class GLImplFactory : angle::NonCopyable
+{
+  public:
+    GLImplFactory() {}
+    virtual ~GLImplFactory() {}
+
+    // Shader creation
+    virtual CompilerImpl *createCompiler() = 0;
+    virtual ShaderImpl *createShader(const gl::ShaderState &data) = 0;
+    virtual ProgramImpl *createProgram(const gl::ProgramState &data) = 0;
+
+    // Framebuffer creation
+    virtual FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) = 0;
+
+    // Texture creation
+    virtual TextureImpl *createTexture(const gl::TextureState &state) = 0;
+
+    // Renderbuffer creation
+    virtual RenderbufferImpl *createRenderbuffer() = 0;
+
+    // Buffer creation
+    virtual BufferImpl *createBuffer(const gl::BufferState &state) = 0;
+
+    // Vertex Array creation
+    virtual VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) = 0;
+
+    // Query and Fence creation
+    virtual QueryImpl *createQuery(GLenum type) = 0;
+    virtual FenceNVImpl *createFenceNV() = 0;
+    virtual FenceSyncImpl *createFenceSync() = 0;
+
+    // Transform Feedback creation
+    virtual TransformFeedbackImpl *createTransformFeedback(
+        const gl::TransformFeedbackState &state) = 0;
+
+    // Sampler object creation
+    virtual SamplerImpl *createSampler() = 0;
+
+    virtual std::vector<PathImpl *> createPaths(GLsizei range) = 0;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GLIMPLFACTORY_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/ImageImpl.h b/src/third_party/angle/src/libANGLE/renderer/ImageImpl.h
new file mode 100644
index 0000000..206df8b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/ImageImpl.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageImpl.h: Defines the rx::ImageImpl class representing the EGLimage object.
+
+#ifndef LIBANGLE_RENDERER_IMAGEIMPL_H_
+#define LIBANGLE_RENDERER_IMAGEIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace egl
+{
+class ImageSibling;
+struct ImageState;
+}
+
+namespace rx
+{
+class ImageImpl : angle::NonCopyable
+{
+  public:
+    ImageImpl(const egl::ImageState &state) : mState(state) {}
+    virtual ~ImageImpl() {}
+    virtual egl::Error initialize() = 0;
+
+    virtual gl::Error orphan(egl::ImageSibling *sibling) = 0;
+
+  protected:
+    const egl::ImageState &mState;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_IMAGEIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/ImageImpl_mock.h b/src/third_party/angle/src/libANGLE/renderer/ImageImpl_mock.h
new file mode 100644
index 0000000..d430528
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/ImageImpl_mock.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageImpl_mock.h: Defines a mock of the ImageImpl class.
+
+#ifndef LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_
+#define LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace rx
+{
+class MockImageImpl : public ImageImpl
+{
+  public:
+    MockImageImpl(const egl::ImageState &state,
+                  EGLenum /*target*/,
+                  const egl::AttributeMap & /*attribs*/)
+        : ImageImpl(state)
+    {
+    }
+    virtual ~MockImageImpl() { destructor(); }
+    MOCK_METHOD0(initialize, egl::Error(void));
+    MOCK_METHOD1(orphan, gl::Error(egl::ImageSibling *));
+    MOCK_METHOD0(destructor, void());
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/PathImpl.h b/src/third_party/angle/src/libANGLE/renderer/PathImpl.h
new file mode 100644
index 0000000..3607f69
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/PathImpl.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2002-2016 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.
+//
+
+// PathImpl.h: Defines the Path implementation interface for
+// CHROMIUM_path_rendering path objects.
+
+#ifndef LIBANGLE_RENDERER_PATHIMPL_H_
+#define LIBANGLE_RENDERER_PATHIMPL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+
+class PathImpl : angle::NonCopyable
+{
+  public:
+    virtual ~PathImpl() {}
+
+    virtual gl::Error setCommands(GLsizei numCommands,
+                                  const GLubyte *commands,
+                                  GLsizei numCoords,
+                                  GLenum coordType,
+                                  const void *coords) = 0;
+
+    virtual void setPathParameter(GLenum pname, GLfloat value) = 0;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_PATHIMPL_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libANGLE/renderer/ProgramImpl.h b/src/third_party/angle/src/libANGLE/renderer/ProgramImpl.h
new file mode 100644
index 0000000..30a6a26
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/ProgramImpl.h
@@ -0,0 +1,101 @@
+//
+// 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.
+//
+
+// ProgramImpl.h: Defines the abstract rx::ProgramImpl class.
+
+#ifndef LIBANGLE_RENDERER_PROGRAMIMPL_H_
+#define LIBANGLE_RENDERER_PROGRAMIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/BinaryStream.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+
+#include <map>
+
+namespace gl
+{
+class VaryingPacking;
+}
+
+namespace sh
+{
+struct BlockMemberInfo;
+}
+
+namespace rx
+{
+class ContextImpl;
+
+using LinkResult = gl::ErrorOrResult<bool>;
+
+class ProgramImpl : angle::NonCopyable
+{
+  public:
+    ProgramImpl(const gl::ProgramState &state) : mState(state) {}
+    virtual ~ProgramImpl() {}
+    virtual void destroy(const ContextImpl *contextImpl) {}
+
+    virtual LinkResult load(const ContextImpl *contextImpl,
+                            gl::InfoLog &infoLog,
+                            gl::BinaryInputStream *stream)  = 0;
+    virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
+    virtual void setBinaryRetrievableHint(bool retrievable) = 0;
+    virtual void setSeparable(bool separable)               = 0;
+
+    virtual LinkResult link(ContextImpl *contextImpl,
+                            const gl::VaryingPacking &packing,
+                            gl::InfoLog &infoLog) = 0;
+    virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
+
+    virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+    virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+    virtual void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+    virtual void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+    virtual void setUniform1iv(GLint location, GLsizei count, const GLint *v) = 0;
+    virtual void setUniform2iv(GLint location, GLsizei count, const GLint *v) = 0;
+    virtual void setUniform3iv(GLint location, GLsizei count, const GLint *v) = 0;
+    virtual void setUniform4iv(GLint location, GLsizei count, const GLint *v) = 0;
+    virtual void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+    virtual void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+    virtual void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+    virtual void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+    virtual void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+
+    // TODO: synchronize in syncState when dirty bits exist.
+    virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0;
+
+    // May only be called after a successful link operation.
+    // Return false for inactive blocks.
+    virtual bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const = 0;
+
+    // May only be called after a successful link operation.
+    // Returns false for inactive members.
+    virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                           sh::BlockMemberInfo *memberInfoOut) const = 0;
+    // CHROMIUM_path_rendering
+    // Set parameters to control fragment shader input variable interpolation
+    virtual void setPathFragmentInputGen(const std::string &inputName,
+                                         GLenum genMode,
+                                         GLint components,
+                                         const GLfloat *coeffs) = 0;
+
+  protected:
+    const gl::ProgramState &mState;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_PROGRAMIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h b/src/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h
new file mode 100644
index 0000000..9b830c0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h
@@ -0,0 +1,78 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramImpl_mock.h:
+//   Defines a mock of the ProgramImpl class.
+//
+
+#ifndef LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_
+#define LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+class MockProgramImpl : public rx::ProgramImpl
+{
+  public:
+    MockProgramImpl() : ProgramImpl(gl::ProgramState()) {}
+    virtual ~MockProgramImpl() { destructor(); }
+
+    MOCK_METHOD3(load, LinkResult(const ContextImpl *, gl::InfoLog &, gl::BinaryInputStream *));
+    MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *));
+    MOCK_METHOD1(setBinaryRetrievableHint, void(bool));
+    MOCK_METHOD1(setSeparable, void(bool));
+
+    MOCK_METHOD3(link, LinkResult(ContextImpl *, const gl::VaryingPacking &, gl::InfoLog &));
+    MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *));
+
+    MOCK_METHOD3(setUniform1fv, void(GLint, GLsizei, const GLfloat *));
+    MOCK_METHOD3(setUniform2fv, void(GLint, GLsizei, const GLfloat *));
+    MOCK_METHOD3(setUniform3fv, void(GLint, GLsizei, const GLfloat *));
+    MOCK_METHOD3(setUniform4fv, void(GLint, GLsizei, const GLfloat *));
+    MOCK_METHOD3(setUniform1iv, void(GLint, GLsizei, const GLint *));
+    MOCK_METHOD3(setUniform2iv, void(GLint, GLsizei, const GLint *));
+    MOCK_METHOD3(setUniform3iv, void(GLint, GLsizei, const GLint *));
+    MOCK_METHOD3(setUniform4iv, void(GLint, GLsizei, const GLint *));
+    MOCK_METHOD3(setUniform1uiv, void(GLint, GLsizei, const GLuint *));
+    MOCK_METHOD3(setUniform2uiv, void(GLint, GLsizei, const GLuint *));
+    MOCK_METHOD3(setUniform3uiv, void(GLint, GLsizei, const GLuint *));
+    MOCK_METHOD3(setUniform4uiv, void(GLint, GLsizei, const GLuint *));
+
+    MOCK_METHOD4(setUniformMatrix2fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+    MOCK_METHOD4(setUniformMatrix3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+    MOCK_METHOD4(setUniformMatrix4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+    MOCK_METHOD4(setUniformMatrix2x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+    MOCK_METHOD4(setUniformMatrix3x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+    MOCK_METHOD4(setUniformMatrix2x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+    MOCK_METHOD4(setUniformMatrix4x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+    MOCK_METHOD4(setUniformMatrix3x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+    MOCK_METHOD4(setUniformMatrix4x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+
+    MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint));
+    MOCK_CONST_METHOD2(getUniformBlockSize, bool(const std::string &, size_t *));
+    MOCK_CONST_METHOD2(getUniformBlockMemberInfo, bool(const std::string &, sh::BlockMemberInfo *));
+    MOCK_METHOD4(setPathFragmentInputGen,
+                 void(const std::string &, GLenum, GLint, const GLfloat *));
+
+    MOCK_METHOD0(destructor, void());
+};
+
+inline ::testing::NiceMock<MockProgramImpl> *MakeProgramMock()
+{
+    ::testing::NiceMock<MockProgramImpl> *programImpl = new ::testing::NiceMock<MockProgramImpl>();
+    // TODO(jmadill): add ON_CALLS for returning methods
+    // We must mock the destructor since NiceMock doesn't work for destructors.
+    EXPECT_CALL(*programImpl, destructor()).Times(1).RetiresOnSaturation();
+
+    return programImpl;
+}
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/QueryImpl.h b/src/third_party/angle/src/libANGLE/renderer/QueryImpl.h
new file mode 100644
index 0000000..d738eb4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/QueryImpl.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// QueryImpl.h: Defines the abstract rx::QueryImpl class.
+
+#ifndef LIBANGLE_RENDERER_QUERYIMPL_H_
+#define LIBANGLE_RENDERER_QUERYIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include <GLES2/gl2.h>
+
+namespace rx
+{
+
+class QueryImpl : angle::NonCopyable
+{
+  public:
+    explicit QueryImpl(GLenum type) { mType = type; }
+    virtual ~QueryImpl() { }
+
+    virtual gl::Error begin() = 0;
+    virtual gl::Error end() = 0;
+    virtual gl::Error queryCounter() = 0;
+    virtual gl::Error getResult(GLint *params) = 0;
+    virtual gl::Error getResult(GLuint *params) = 0;
+    virtual gl::Error getResult(GLint64 *params) = 0;
+    virtual gl::Error getResult(GLuint64 *params) = 0;
+    virtual gl::Error isResultAvailable(bool *available) = 0;
+
+    GLenum getType() const { return mType;  }
+
+  private:
+    GLenum mType;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_QUERYIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/RenderbufferImpl.h b/src/third_party/angle/src/libANGLE/renderer/RenderbufferImpl.h
new file mode 100644
index 0000000..3f8bad5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/RenderbufferImpl.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl
+
+#ifndef LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
+#define LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace egl
+{
+class Image;
+}
+
+namespace rx
+{
+
+class RenderbufferImpl : public FramebufferAttachmentObjectImpl
+{
+  public:
+    RenderbufferImpl() {}
+    virtual ~RenderbufferImpl() {}
+
+    virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) = 0;
+    virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) = 0;
+    virtual gl::Error setStorageEGLImageTarget(egl::Image *image) = 0;
+};
+
+}
+
+#endif   // LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h b/src/third_party/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h
new file mode 100644
index 0000000..2448534
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferImpl_mock.h: Defines a mock of the RenderbufferImpl class.
+
+#ifndef LIBANGLE_RENDERER_RENDERBUFFERIMPLMOCK_H_
+#define LIBANGLE_RENDERER_RENDERBUFFERIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/Image.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+
+class MockRenderbufferImpl : public RenderbufferImpl
+{
+  public:
+    virtual ~MockRenderbufferImpl() { destructor(); }
+    MOCK_METHOD3(setStorage, gl::Error(GLenum, size_t, size_t));
+    MOCK_METHOD4(setStorageMultisample, gl::Error(size_t, GLenum, size_t, size_t));
+    MOCK_METHOD1(setStorageEGLImageTarget, gl::Error(egl::Image *));
+
+    MOCK_METHOD3(getAttachmentRenderTarget,
+                 gl::Error(GLenum, const gl::ImageIndex &, FramebufferAttachmentRenderTarget **));
+
+    MOCK_METHOD0(destructor, void());
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_RENDERBUFFERIMPLMOCK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/SamplerImpl.h b/src/third_party/angle/src/libANGLE/renderer/SamplerImpl.h
new file mode 100644
index 0000000..741b0da
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/SamplerImpl.h
@@ -0,0 +1,25 @@
+//
+// 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.
+//
+
+// SamplerImpl.h: Defines the abstract rx::SamplerImpl class.
+
+#ifndef LIBANGLE_RENDERER_SAMPLERIMPL_H_
+#define LIBANGLE_RENDERER_SAMPLERIMPL_H_
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+
+class SamplerImpl : angle::NonCopyable
+{
+  public:
+    SamplerImpl() {}
+    virtual ~SamplerImpl() {}
+};
+}
+
+#endif  // LIBANGLE_RENDERER_SAMPLERIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/ShaderImpl.h b/src/third_party/angle/src/libANGLE/renderer/ShaderImpl.h
new file mode 100644
index 0000000..77e02d0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/ShaderImpl.h
@@ -0,0 +1,40 @@
+//
+// 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.
+//
+
+// ShaderImpl.h: Defines the abstract rx::ShaderImpl class.
+
+#ifndef LIBANGLE_RENDERER_SHADERIMPL_H_
+#define LIBANGLE_RENDERER_SHADERIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Shader.h"
+
+namespace rx
+{
+
+class ShaderImpl : angle::NonCopyable
+{
+  public:
+    ShaderImpl(const gl::ShaderState &data) : mData(data) {}
+    virtual ~ShaderImpl() { }
+
+    // Returns additional sh::Compile options.
+    virtual ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+                                                           std::string *sourcePath) = 0;
+    // Returns success for compiling on the driver. Returns success.
+    virtual bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) = 0;
+
+    virtual std::string getDebugInfo() const = 0;
+
+    const gl::ShaderState &getData() const { return mData; }
+
+  protected:
+    const gl::ShaderState &mData;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_SHADERIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/StreamProducerImpl.h b/src/third_party/angle/src/libANGLE/renderer/StreamProducerImpl.h
new file mode 100644
index 0000000..1915bf7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/StreamProducerImpl.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// StreamProducerImpl.h: Defines the abstract rx::StreamProducerImpl class.
+
+#ifndef LIBANGLE_RENDERER_STREAMPRODUCERIMPL_H_
+#define LIBANGLE_RENDERER_STREAMPRODUCERIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Stream.h"
+
+namespace rx
+{
+
+class StreamProducerImpl : angle::NonCopyable
+{
+  public:
+    explicit StreamProducerImpl() {}
+    virtual ~StreamProducerImpl() {}
+
+    // Validates the ability for the producer to accept an arbitrary pointer to a frame. All
+    // pointers should be validated through this function before being used to produce a frame.
+    virtual egl::Error validateD3DNV12Texture(void *pointer) const = 0;
+
+    // Constructs a frame from an arbitrary external pointer that points to producer specific frame
+    // data. Replaces the internal frame with the new one.
+    virtual void postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes) = 0;
+
+    // Returns an OpenGL texture interpretation of some frame attributes for the purpose of
+    // constructing an OpenGL texture from a frame. Depending on the producer and consumer, some
+    // frames may have multiple "planes" with different OpenGL texture representations.
+    virtual egl::Stream::GLTextureDescription getGLFrameDescription(int planeIndex) = 0;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_STREAMPRODUCERIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/SurfaceImpl.cpp b/src/third_party/angle/src/libANGLE/renderer/SurfaceImpl.cpp
new file mode 100644
index 0000000..e4b3d7c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/SurfaceImpl.cpp
@@ -0,0 +1,28 @@
+//
+// 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.
+//
+
+// SurfaceImpl.cpp: Implementation of Surface stub method class
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace rx
+{
+
+SurfaceImpl::SurfaceImpl(const egl::SurfaceState &state) : mState(state)
+{
+}
+
+SurfaceImpl::~SurfaceImpl()
+{
+}
+
+egl::Error SurfaceImpl::swapWithDamage(EGLint *rects, EGLint n_rects)
+{
+    UNREACHABLE();
+    return egl::Error(EGL_BAD_SURFACE, "swapWithDamage implementation missing.");
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h b/src/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h
new file mode 100644
index 0000000..0e4f177
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h
@@ -0,0 +1,69 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceImpl.h: Implementation methods of egl::Surface
+
+#ifndef LIBANGLE_RENDERER_SURFACEIMPL_H_
+#define LIBANGLE_RENDERER_SURFACEIMPL_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace gl
+{
+class FramebufferState;
+}
+
+namespace egl
+{
+class Display;
+struct Config;
+struct SurfaceState;
+}
+
+namespace rx
+{
+class DisplayImpl;
+class FramebufferImpl;
+
+class SurfaceImpl : public FramebufferAttachmentObjectImpl
+{
+  public:
+    SurfaceImpl(const egl::SurfaceState &surfaceState);
+    virtual ~SurfaceImpl();
+    virtual void destroy(const DisplayImpl *displayImpl) {}
+
+    virtual egl::Error initialize(const DisplayImpl *displayImpl)                        = 0;
+    virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0;
+    virtual egl::Error swap(const DisplayImpl *displayImpl)                              = 0;
+    virtual egl::Error swapWithDamage(EGLint *rects, EGLint n_rects);
+    virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
+    virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0;
+    virtual egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) = 0;
+    virtual egl::Error releaseTexImage(EGLint buffer) = 0;
+    virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 0;
+    virtual void setSwapInterval(EGLint interval) = 0;
+
+    // width and height can change with client window resizing
+    virtual EGLint getWidth() const = 0;
+    virtual EGLint getHeight() const = 0;
+
+    virtual EGLint isPostSubBufferSupported() const = 0;
+    virtual EGLint getSwapBehavior() const = 0;
+
+  protected:
+    const egl::SurfaceState &mState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_SURFACEIMPL_H_
+
diff --git a/src/third_party/angle/src/libANGLE/renderer/TextureImpl.cpp b/src/third_party/angle/src/libANGLE/renderer/TextureImpl.cpp
new file mode 100644
index 0000000..47a7390
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/TextureImpl.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright 2016 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.
+//
+
+// TextureImpl.cpp: Defines the abstract rx::TextureImpl classes.
+
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace rx
+{
+
+TextureImpl::TextureImpl(const gl::TextureState &state) : mState(state)
+{
+}
+
+TextureImpl::~TextureImpl()
+{
+}
+
+gl::Error TextureImpl::copyTexture(ContextImpl *contextImpl,
+                                   GLenum target,
+                                   size_t level,
+                                   GLenum internalFormat,
+                                   GLenum type,
+                                   size_t sourceLevel,
+                                   bool unpackFlipY,
+                                   bool unpackPremultiplyAlpha,
+                                   bool unpackUnmultiplyAlpha,
+                                   const gl::Texture *source)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION, "CHROMIUM_copy_texture exposed but not implemented.");
+}
+
+gl::Error TextureImpl::copySubTexture(ContextImpl *contextImpl,
+                                      GLenum target,
+                                      size_t level,
+                                      const gl::Offset &destOffset,
+                                      size_t sourceLevel,
+                                      const gl::Rectangle &sourceArea,
+                                      bool unpackFlipY,
+                                      bool unpackPremultiplyAlpha,
+                                      bool unpackUnmultiplyAlpha,
+                                      const gl::Texture *source)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION, "CHROMIUM_copy_texture exposed but not implemented.");
+}
+
+gl::Error TextureImpl::copyCompressedTexture(ContextImpl *contextImpl, const gl::Texture *source)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION,
+                     "CHROMIUM_copy_compressed_texture exposed but not implemented.");
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/TextureImpl.h b/src/third_party/angle/src/libANGLE/renderer/TextureImpl.h
new file mode 100644
index 0000000..077485c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/TextureImpl.h
@@ -0,0 +1,154 @@
+//
+// 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.
+//
+
+// TextureImpl.h: Defines the abstract rx::TextureImpl classes.
+
+#ifndef LIBANGLE_RENDERER_TEXTUREIMPL_H_
+#define LIBANGLE_RENDERER_TEXTUREIMPL_H_
+
+#include <stdint.h>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace egl
+{
+class Surface;
+class Image;
+}
+
+namespace gl
+{
+struct Box;
+struct Extents;
+struct Offset;
+struct Rectangle;
+class Framebuffer;
+struct PixelUnpackState;
+struct TextureState;
+}
+
+namespace rx
+{
+class ContextImpl;
+
+class TextureImpl : public FramebufferAttachmentObjectImpl
+{
+  public:
+    TextureImpl(const gl::TextureState &state);
+    virtual ~TextureImpl();
+
+    virtual gl::Error setImage(ContextImpl *contextImpl,
+                               GLenum target,
+                               size_t level,
+                               GLenum internalFormat,
+                               const gl::Extents &size,
+                               GLenum format,
+                               GLenum type,
+                               const gl::PixelUnpackState &unpack,
+                               const uint8_t *pixels) = 0;
+    virtual gl::Error setSubImage(ContextImpl *contextImpl,
+                                  GLenum target,
+                                  size_t level,
+                                  const gl::Box &area,
+                                  GLenum format,
+                                  GLenum type,
+                                  const gl::PixelUnpackState &unpack,
+                                  const uint8_t *pixels) = 0;
+
+    virtual gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                         GLenum target,
+                                         size_t level,
+                                         GLenum internalFormat,
+                                         const gl::Extents &size,
+                                         const gl::PixelUnpackState &unpack,
+                                         size_t imageSize,
+                                         const uint8_t *pixels) = 0;
+    virtual gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                            GLenum target,
+                                            size_t level,
+                                            const gl::Box &area,
+                                            GLenum format,
+                                            const gl::PixelUnpackState &unpack,
+                                            size_t imageSize,
+                                            const uint8_t *pixels) = 0;
+
+    virtual gl::Error copyImage(ContextImpl *contextImpl,
+                                GLenum target,
+                                size_t level,
+                                const gl::Rectangle &sourceArea,
+                                GLenum internalFormat,
+                                const gl::Framebuffer *source) = 0;
+    virtual gl::Error copySubImage(ContextImpl *contextImpl,
+                                   GLenum target,
+                                   size_t level,
+                                   const gl::Offset &destOffset,
+                                   const gl::Rectangle &sourceArea,
+                                   const gl::Framebuffer *source) = 0;
+
+    virtual gl::Error copyTexture(ContextImpl *contextImpl,
+                                  GLenum target,
+                                  size_t level,
+                                  GLenum internalFormat,
+                                  GLenum type,
+                                  size_t sourceLevel,
+                                  bool unpackFlipY,
+                                  bool unpackPremultiplyAlpha,
+                                  bool unpackUnmultiplyAlpha,
+                                  const gl::Texture *source);
+    virtual gl::Error copySubTexture(ContextImpl *contextImpl,
+                                     GLenum target,
+                                     size_t level,
+                                     const gl::Offset &destOffset,
+                                     size_t sourceLevel,
+                                     const gl::Rectangle &sourceArea,
+                                     bool unpackFlipY,
+                                     bool unpackPremultiplyAlpha,
+                                     bool unpackUnmultiplyAlpha,
+                                     const gl::Texture *source);
+
+    virtual gl::Error copyCompressedTexture(ContextImpl *contextImpl, const gl::Texture *source);
+
+    virtual gl::Error setStorage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t levels,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size) = 0;
+
+    virtual gl::Error setStorageMultisample(ContextImpl *contextImpl,
+                                            GLenum target,
+                                            GLsizei samples,
+                                            GLint internalformat,
+                                            const gl::Extents &size,
+                                            GLboolean fixedSampleLocations) = 0;
+
+    virtual gl::Error setEGLImageTarget(GLenum target, egl::Image *image) = 0;
+
+    virtual gl::Error setImageExternal(GLenum target,
+                                       egl::Stream *stream,
+                                       const egl::Stream::GLTextureDescription &desc) = 0;
+
+    virtual gl::Error generateMipmap(ContextImpl *contextImpl) = 0;
+
+    virtual void setBaseLevel(GLuint baseLevel) = 0;
+
+    virtual void bindTexImage(egl::Surface *surface) = 0;
+    virtual void releaseTexImage() = 0;
+
+    virtual void syncState(const gl::Texture::DirtyBits &dirtyBits) = 0;
+
+  protected:
+    const gl::TextureState &mState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_TEXTUREIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/TextureImpl_mock.h b/src/third_party/angle/src/libANGLE/renderer/TextureImpl_mock.h
new file mode 100644
index 0000000..83a1d21
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/TextureImpl_mock.h
@@ -0,0 +1,124 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureImpl_mock.h: Defines a mock of the TextureImpl class.
+
+#ifndef LIBANGLE_RENDERER_TEXTUREIMPLMOCK_H_
+#define LIBANGLE_RENDERER_TEXTUREIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace rx
+{
+
+class MockTextureImpl : public TextureImpl
+{
+  public:
+    MockTextureImpl() : TextureImpl(mMockState), mMockState(GL_TEXTURE_2D) {}
+    virtual ~MockTextureImpl() { destructor(); }
+    MOCK_METHOD9(setImage,
+                 gl::Error(ContextImpl *,
+                           GLenum,
+                           size_t,
+                           GLenum,
+                           const gl::Extents &,
+                           GLenum,
+                           GLenum,
+                           const gl::PixelUnpackState &,
+                           const uint8_t *));
+    MOCK_METHOD8(setSubImage,
+                 gl::Error(ContextImpl *,
+                           GLenum,
+                           size_t,
+                           const gl::Box &,
+                           GLenum,
+                           GLenum,
+                           const gl::PixelUnpackState &,
+                           const uint8_t *));
+    MOCK_METHOD8(setCompressedImage,
+                 gl::Error(ContextImpl *,
+                           GLenum,
+                           size_t,
+                           GLenum,
+                           const gl::Extents &,
+                           const gl::PixelUnpackState &,
+                           size_t,
+                           const uint8_t *));
+    MOCK_METHOD8(setCompressedSubImage,
+                 gl::Error(ContextImpl *,
+                           GLenum,
+                           size_t,
+                           const gl::Box &,
+                           GLenum,
+                           const gl::PixelUnpackState &,
+                           size_t,
+                           const uint8_t *));
+    MOCK_METHOD6(copyImage,
+                 gl::Error(ContextImpl *,
+                           GLenum,
+                           size_t,
+                           const gl::Rectangle &,
+                           GLenum,
+                           const gl::Framebuffer *));
+    MOCK_METHOD6(copySubImage,
+                 gl::Error(ContextImpl *,
+                           GLenum,
+                           size_t,
+                           const gl::Offset &,
+                           const gl::Rectangle &,
+                           const gl::Framebuffer *));
+    MOCK_METHOD10(copyTexture,
+                  gl::Error(ContextImpl *,
+                            GLenum,
+                            size_t,
+                            GLenum,
+                            GLenum,
+                            size_t,
+                            bool,
+                            bool,
+                            bool,
+                            const gl::Texture *));
+    MOCK_METHOD10(copySubTexture,
+                  gl::Error(ContextImpl *,
+                            GLenum,
+                            size_t,
+                            const gl::Offset &,
+                            size_t,
+                            const gl::Rectangle &,
+                            bool,
+                            bool,
+                            bool,
+                            const gl::Texture *));
+    MOCK_METHOD2(copyCompressedTexture, gl::Error(ContextImpl *, const gl::Texture *source));
+    MOCK_METHOD5(setStorage, gl::Error(ContextImpl *, GLenum, size_t, GLenum, const gl::Extents &));
+    MOCK_METHOD3(setImageExternal,
+                 gl::Error(GLenum, egl::Stream *, const egl::Stream::GLTextureDescription &));
+    MOCK_METHOD2(setEGLImageTarget, gl::Error(GLenum, egl::Image *));
+    MOCK_METHOD1(generateMipmap, gl::Error(ContextImpl *));
+    MOCK_METHOD1(bindTexImage, void(egl::Surface *));
+    MOCK_METHOD0(releaseTexImage, void(void));
+
+    MOCK_METHOD3(getAttachmentRenderTarget,
+                 gl::Error(GLenum, const gl::ImageIndex &, FramebufferAttachmentRenderTarget **));
+
+    MOCK_METHOD6(setStorageMultisample,
+                 gl::Error(ContextImpl *, GLenum, GLsizei, GLint, const gl::Extents &, GLboolean));
+
+    MOCK_METHOD1(setBaseLevel, void(GLuint));
+
+    MOCK_METHOD1(syncState, void(const gl::Texture::DirtyBits &));
+
+    MOCK_METHOD0(destructor, void());
+
+  protected:
+    gl::TextureState mMockState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_TEXTUREIMPLMOCK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/TransformFeedbackImpl.h b/src/third_party/angle/src/libANGLE/renderer/TransformFeedbackImpl.h
new file mode 100644
index 0000000..71e6374
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/TransformFeedbackImpl.h
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+
+// TransformFeedbackImpl.h: Defines the abstract rx::TransformFeedbackImpl class.
+
+#ifndef LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+#define LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/TransformFeedback.h"
+
+namespace rx
+{
+
+class TransformFeedbackImpl : angle::NonCopyable
+{
+  public:
+    TransformFeedbackImpl(const gl::TransformFeedbackState &state) : mState(state) {}
+    virtual ~TransformFeedbackImpl() { }
+
+    virtual void begin(GLenum primitiveMode) = 0;
+    virtual void end() = 0;
+    virtual void pause() = 0;
+    virtual void resume() = 0;
+
+    virtual void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) = 0;
+    virtual void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) = 0;
+
+  protected:
+    const gl::TransformFeedbackState &mState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h b/src/third_party/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
new file mode 100644
index 0000000..18832ac
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackImpl_mock.h: Defines a mock of the TransformFeedbackImpl class.
+
+#ifndef LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_
+#define LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class MockTransformFeedbackImpl : public TransformFeedbackImpl
+{
+  public:
+    MockTransformFeedbackImpl(const gl::TransformFeedbackState &state)
+        : TransformFeedbackImpl(state)
+    {
+    }
+    ~MockTransformFeedbackImpl() { destructor(); }
+
+    MOCK_METHOD1(begin, void(GLenum primitiveMode));
+    MOCK_METHOD0(end, void());
+    MOCK_METHOD0(pause, void());
+    MOCK_METHOD0(resume, void());
+
+    MOCK_METHOD1(bindGenericBuffer, void(const BindingPointer<gl::Buffer> &));
+    MOCK_METHOD2(bindIndexedBuffer, void(size_t, const OffsetBindingPointer<gl::Buffer> &));
+
+    MOCK_METHOD0(destructor, void());
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/VertexArrayImpl.h b/src/third_party/angle/src/libANGLE/renderer/VertexArrayImpl.h
new file mode 100644
index 0000000..a933ba2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/VertexArrayImpl.h
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+
+// VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class.
+
+#ifndef LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
+#define LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/VertexArray.h"
+
+namespace rx
+{
+class ContextImpl;
+
+class VertexArrayImpl : angle::NonCopyable
+{
+  public:
+    VertexArrayImpl(const gl::VertexArrayState &data) : mData(data) {}
+    virtual ~VertexArrayImpl() { }
+    virtual void syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits) {}
+  protected:
+    const gl::VertexArrayState &mData;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/angle_format.py b/src/third_party/angle/src/libANGLE/renderer/angle_format.py
new file mode 100644
index 0000000..43ca684
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/angle_format.py
@@ -0,0 +1,170 @@
+#!/usr/bin/python
+# Copyright 2016 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# angle_format.py:
+#  Utils for ANGLE formats.
+
+import json
+import os
+import re
+
+def reject_duplicate_keys(pairs):
+    found_keys = {}
+    for key, value in pairs:
+        if key in found_keys:
+           raise ValueError("duplicate key: %r" % (key,))
+        else:
+           found_keys[key] = value
+    return found_keys
+
+def load_json(path):
+    with open(path) as map_file:
+        file_data = map_file.read()
+        map_file.close()
+        return json.loads(file_data, object_pairs_hook=reject_duplicate_keys)
+
+def load_forward_table(path):
+    pairs = load_json(path)
+    reject_duplicate_keys(pairs)
+    return { gl: angle for gl, angle in pairs }
+
+def load_inverse_table(path):
+    pairs = load_json(path)
+    reject_duplicate_keys(pairs)
+    return { angle: gl for gl, angle in pairs }
+
+def load_without_override():
+    map_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'angle_format_map.json')
+    return load_forward_table(map_path)
+
+def load_with_override(override_path):
+    results = load_without_override()
+    overrides = load_json(override_path)
+
+    for k, v in overrides.iteritems():
+        results[k] = v
+
+    return results
+
+def get_component_type(format_id):
+    if "SNORM" in format_id:
+        return "snorm"
+    elif "UNORM" in format_id:
+        return "unorm"
+    elif "FLOAT" in format_id:
+        return "float"
+    elif "UINT" in format_id:
+        return "uint"
+    elif "SINT" in format_id:
+        return "int"
+    elif format_id == "NONE":
+        return "none"
+    elif "SRGB" in format_id:
+        return "unorm"
+    elif format_id == "R9G9B9E5_SHAREDEXP":
+        return "float"
+    else:
+        raise ValueError("Unknown component type for " + format_id)
+
+def get_channel_tokens(format_id):
+    r = re.compile(r'([ABDGLRS][\d]+)')
+    return filter(r.match, r.split(format_id))
+
+def get_channels(format_id):
+    channels = ''
+    tokens = get_channel_tokens(format_id)
+    if len(tokens) == 0:
+        return None
+    for token in tokens:
+        channels += token[0].lower()
+
+    return channels
+
+def get_bits(format_id):
+    bits = {}
+    tokens = get_channel_tokens(format_id)
+    if len(tokens) == 0:
+        return None
+    for token in tokens:
+        bits[token[0]] = int(token[1:])
+    return bits
+
+def get_format_info(format_id):
+    return get_component_type(format_id), get_bits(format_id), get_channels(format_id)
+
+# TODO(oetuaho): Expand this code so that it could generate the gl format info tables as well.
+def gl_format_channels(internal_format):
+    if internal_format == 'GL_BGR5_A1_ANGLEX':
+        return 'bgra'
+    if internal_format == 'GL_R11F_G11F_B10F':
+        return 'rgb'
+    if internal_format == 'GL_RGB5_A1':
+        return 'rgba'
+    if internal_format.find('GL_RGB10_A2') == 0:
+        return 'rgba'
+
+    channels_pattern = re.compile('GL_(COMPRESSED_)?(SIGNED_)?(ETC\d_)?([A-Z]+)')
+    match = re.search(channels_pattern, internal_format)
+    channels_string = match.group(4)
+
+    if channels_string == 'ALPHA':
+        return 'a'
+    if channels_string == 'LUMINANCE':
+        if (internal_format.find('ALPHA') >= 0):
+            return 'la'
+        return 'l'
+    if channels_string == 'SRGB':
+        if (internal_format.find('ALPHA') >= 0):
+            return 'rgba'
+        return 'rgb'
+    if channels_string == 'DEPTH':
+        if (internal_format.find('STENCIL') >= 0):
+            return 'ds'
+        return 'd'
+    if channels_string == 'STENCIL':
+        return 's'
+    return channels_string.lower()
+
+def get_internal_format_initializer(internal_format, format_id):
+    gl_channels = gl_format_channels(internal_format)
+    gl_format_no_alpha = gl_channels == 'rgb' or gl_channels == 'l'
+    component_type, bits, channels = get_format_info(format_id)
+
+    if not gl_format_no_alpha or channels != 'rgba':
+        return 'nullptr'
+
+    elif 'BC1_' in format_id:
+        # BC1 is a special case since the texture data determines whether each block has an alpha channel or not.
+        # This if statement is hit by COMPRESSED_RGB_S3TC_DXT1, which is a bit of a mess.
+        # TODO(oetuaho): Look into whether COMPRESSED_RGB_S3TC_DXT1 works right in general.
+        # Reference: https://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt
+        return 'nullptr'
+
+    elif component_type == 'uint' and bits['R'] == 8:
+        return 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>'
+    elif component_type == 'unorm' and bits['R'] == 8:
+        return 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>'
+    elif component_type == 'unorm' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>'
+    elif component_type == 'int' and bits['R'] == 8:
+        return 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>'
+    elif component_type == 'snorm' and bits['R'] == 8:
+        return 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>'
+    elif component_type == 'snorm' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>'
+    elif component_type == 'float' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>'
+    elif component_type == 'uint' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>'
+    elif component_type == 'int' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>'
+    elif component_type == 'float' and bits['R'] == 32:
+        return 'Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>'
+    elif component_type == 'int' and bits['R'] == 32:
+        return 'Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
+    elif component_type == 'uint' and bits['R'] == 32:
+        return 'Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
+    else:
+        raise ValueError('warning: internal format initializer could not be generated and may be needed for ' + internal_format)
diff --git a/src/third_party/angle/src/libANGLE/renderer/angle_format_data.json b/src/third_party/angle/src/libANGLE/renderer/angle_format_data.json
new file mode 100644
index 0000000..5b3a226
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/angle_format_data.json
@@ -0,0 +1,24 @@
+{
+  "B5G6R5_UNORM": {
+    "fboImplementationInternalFormat": "GL_RGB565"
+  },
+  "B5G5R5A1_UNORM": {
+    "fboImplementationInternalFormat": "GL_RGB5_A1",
+    "channelStruct": "A1R5G5B5"
+  },
+  "B8G8R8X8_UNORM": {
+    "glInternalFormat": "GL_BGRA8_EXT",
+    "channelStruct": "B8G8R8X8"
+  },
+  "R9G9B9E5_SHAREDEXP": {
+    "componentType":  "float",
+    "channelStruct":  "R9G9B9E5"
+  },
+  "B4G4R4A4_UNORM": {
+    "fboImplementationInternalFormat": "GL_RGBA4",
+    "channelStruct":  "A4R4G4B4"
+  },
+  "R8G8B8A8_UNORM_SRGB": {
+    "channelStruct":  "R8G8B8A8SRGB"
+  }
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/angle_format_map.json b/src/third_party/angle/src/libANGLE/renderer/angle_format_map.json
new file mode 100644
index 0000000..f7ad2bd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/angle_format_map.json
@@ -0,0 +1,131 @@
+[
+  [ "GL_ALPHA16F_EXT", "A16_FLOAT" ],
+  [ "GL_ALPHA32F_EXT", "A32_FLOAT" ],
+  [ "GL_ALPHA8_EXT", "A8_UNORM" ],
+  [ "GL_BGR565_ANGLEX", "B5G6R5_UNORM" ],
+  [ "GL_BGR5_A1_ANGLEX", "B5G5R5A1_UNORM" ],
+  [ "GL_BGRA4_ANGLEX", "B4G4R4A4_UNORM" ],
+  [ "GL_BGRA8_EXT", "B8G8R8A8_UNORM" ],
+  [ "GL_BGRX8_ANGLEX", "B8G8R8X8_UNORM" ],
+  [ "GL_COMPRESSED_R11_EAC", "EAC_R11_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RG11_EAC", "EAC_R11G11_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGB8_ETC2", "ETC2_R8G8B8_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", "ETC2_R8G8B8A1_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA8_ETC2_EAC", "ETC2_R8G8B8A8_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT", "BC1_RGBA_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE", "BC2_RGBA_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE", "BC3_RGBA_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_4x4_KHR", "ASTC_4x4_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_5x4_KHR", "ASTC_5x4_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_5x5_KHR", "ASTC_5x5_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_6x5_KHR", "ASTC_6x5_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_6x6_KHR", "ASTC_6x6_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_8x5_KHR", "ASTC_8x5_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_8x6_KHR", "ASTC_8x6_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_8x8_KHR", "ASTC_8x8_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_10x5_KHR", "ASTC_10x5_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_10x6_KHR", "ASTC_10x6_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_10x8_KHR", "ASTC_10x8_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_10x10_KHR", "ASTC_10x10_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_12x10_KHR", "ASTC_12x10_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGBA_ASTC_12x12_KHR", "ASTC_12x12_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT", "BC1_RGB_UNORM_BLOCK" ],
+  [ "GL_COMPRESSED_SIGNED_R11_EAC", "EAC_R11_SNORM_BLOCK" ],
+  [ "GL_COMPRESSED_SIGNED_RG11_EAC", "EAC_R11G11_SNORM_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR", "ASTC_4x4_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR", "ASTC_5x4_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR", "ASTC_5x5_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR", "ASTC_6x5_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR", "ASTC_6x6_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR", "ASTC_8x5_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR", "ASTC_8x6_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR", "ASTC_8x8_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR", "ASTC_10x5_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR", "ASTC_10x6_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR", "ASTC_10x8_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR", "ASTC_10x10_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR", "ASTC_12x10_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR", "ASTC_12x12_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", "ETC2_R8G8B8A8_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_ETC2", "ETC2_R8G8B8_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", "ETC2_R8G8B8A1_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT", "BC1_RGBA_UNORM_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT", "BC2_RGBA_UNORM_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT", "BC3_RGBA_UNORM_SRGB_BLOCK" ],
+  [ "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT", "BC1_RGB_UNORM_SRGB_BLOCK" ],
+  [ "GL_DEPTH24_STENCIL8", "D24_UNORM_S8_UINT" ],
+  [ "GL_DEPTH32F_STENCIL8", "D32_FLOAT_S8X24_UINT" ],
+  [ "GL_DEPTH_COMPONENT16", "D16_UNORM" ],
+  [ "GL_DEPTH_COMPONENT24", "D24_UNORM" ],
+  [ "GL_DEPTH_COMPONENT32F", "D32_FLOAT" ],
+  [ "GL_DEPTH_COMPONENT32_OES", "D32_UNORM" ],
+  [ "GL_ETC1_RGB8_OES", "NONE" ],
+  [ "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE", "NONE" ],
+  [ "GL_LUMINANCE16F_EXT", "L16_FLOAT" ],
+  [ "GL_LUMINANCE32F_EXT", "L32_FLOAT" ],
+  [ "GL_LUMINANCE8_ALPHA8_EXT", "L8A8_UNORM" ],
+  [ "GL_LUMINANCE8_EXT", "L8_UNORM" ],
+  [ "GL_LUMINANCE_ALPHA16F_EXT", "L16A16_FLOAT" ],
+  [ "GL_LUMINANCE_ALPHA32F_EXT", "L32A32_FLOAT" ],
+  [ "GL_NONE", "NONE" ],
+  [ "GL_R11F_G11F_B10F", "R11G11B10_FLOAT" ],
+  [ "GL_R16F", "R16_FLOAT" ],
+  [ "GL_R16I", "R16_SINT" ],
+  [ "GL_R16UI", "R16_UINT" ],
+  [ "GL_R32F", "R32_FLOAT" ],
+  [ "GL_R32I", "R32_SINT" ],
+  [ "GL_R32UI", "R32_UINT" ],
+  [ "GL_R8", "R8_UNORM" ],
+  [ "GL_R8I", "R8_SINT" ],
+  [ "GL_R8UI", "R8_UINT" ],
+  [ "GL_R8_SNORM", "R8_SNORM" ],
+  [ "GL_RG16F", "R16G16_FLOAT" ],
+  [ "GL_RG16I", "R16G16_SINT" ],
+  [ "GL_RG16UI", "R16G16_UINT" ],
+  [ "GL_RG32F", "R32G32_FLOAT" ],
+  [ "GL_RG32I", "R32G32_SINT" ],
+  [ "GL_RG32UI", "R32G32_UINT" ],
+  [ "GL_RG8", "R8G8_UNORM" ],
+  [ "GL_RG8I", "R8G8_SINT" ],
+  [ "GL_RG8UI", "R8G8_UINT" ],
+  [ "GL_RG8_SNORM", "R8G8_SNORM" ],
+  [ "GL_RGB", "R8G8B8_UNORM" ],
+  [ "GL_RGB10_A2", "R10G10B10A2_UNORM" ],
+  [ "GL_RGB10_A2UI", "R10G10B10A2_UINT" ],
+  [ "GL_RGB16F", "R16G16B16_FLOAT" ],
+  [ "GL_RGB16I", "R16G16B16_SINT" ],
+  [ "GL_RGB16UI", "R16G16B16_UINT" ],
+  [ "GL_RGB32F", "R32G32B32_FLOAT" ],
+  [ "GL_RGB32I", "R32G32B32_SINT" ],
+  [ "GL_RGB32UI", "R32G32B32_UINT" ],
+  [ "GL_RGB565", "R5G6B5_UNORM" ],
+  [ "GL_RGB5_A1", "R5G5B5A1_UNORM" ],
+  [ "GL_RGB8", "R8G8B8_UNORM" ],
+  [ "GL_RGB8I", "R8G8B8_SINT" ],
+  [ "GL_RGB8UI", "R8G8B8_UINT" ],
+  [ "GL_RGB8_SNORM", "R8G8B8_SNORM" ],
+  [ "GL_RGB9_E5", "R9G9B9E5_SHAREDEXP" ],
+  [ "GL_RGBA", "R8G8B8A8_UNORM" ],
+  [ "GL_RGBA16F", "R16G16B16A16_FLOAT" ],
+  [ "GL_RGBA16I", "R16G16B16A16_SINT" ],
+  [ "GL_RGBA16UI", "R16G16B16A16_UINT" ],
+  [ "GL_RGBA32F", "R32G32B32A32_FLOAT" ],
+  [ "GL_RGBA32I", "R32G32B32A32_SINT" ],
+  [ "GL_RGBA32UI", "R32G32B32A32_UINT" ],
+  [ "GL_RGBA4", "R4G4B4A4_UNORM" ],
+  [ "GL_RGBA8", "R8G8B8A8_UNORM" ],
+  [ "GL_RGBA8I", "R8G8B8A8_SINT" ],
+  [ "GL_RGBA8UI", "R8G8B8A8_UINT" ],
+  [ "GL_RGBA8_SNORM", "R8G8B8A8_SNORM" ],
+  [ "GL_SRGB8", "R8G8B8_UNORM_SRGB" ],
+  [ "GL_SRGB8_ALPHA8", "R8G8B8A8_UNORM_SRGB" ],
+  [ "GL_STENCIL_INDEX8", "S8_UINT" ],
+  [ "GL_R16_EXT", "R16_UNORM" ],
+  [ "GL_RG16_EXT", "R16G16_UNORM" ],
+  [ "GL_RGB16_EXT", "R16G16B16_UNORM" ],
+  [ "GL_RGBA16_EXT", "R16G16B16A16_UNORM" ],
+  [ "GL_R16_SNORM_EXT", "R16_SNORM" ],
+  [ "GL_RG16_SNORM_EXT", "R16G16_SNORM" ],
+  [ "GL_RGB16_SNORM_EXT", "R16G16B16_SNORM" ],
+  [ "GL_RGBA16_SNORM_EXT", "R16G16B16A16_SNORM" ]
+]
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
new file mode 100644
index 0000000..cb0bd2e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
@@ -0,0 +1,189 @@
+//
+// 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.
+//
+
+// BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes.
+
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+unsigned int BufferD3D::mNextSerial = 1;
+
+BufferD3D::BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory)
+    : BufferImpl(state),
+      mFactory(factory),
+      mStaticIndexBuffer(nullptr),
+      mStaticBufferCacheTotalSize(0),
+      mStaticVertexBufferOutOfDate(false),
+      mUnmodifiedDataUse(0),
+      mUsage(D3DBufferUsage::STATIC)
+{
+    updateSerial();
+}
+
+BufferD3D::~BufferD3D()
+{
+    SafeDelete(mStaticIndexBuffer);
+}
+
+void BufferD3D::emptyStaticBufferCache()
+{
+    mStaticVertexBuffers.clear();
+    mStaticBufferCacheTotalSize = 0;
+}
+
+void BufferD3D::updateSerial()
+{
+    mSerial = mNextSerial++;
+}
+
+void BufferD3D::updateD3DBufferUsage(GLenum usage)
+{
+    switch (usage)
+    {
+        case GL_STATIC_DRAW:
+        case GL_STATIC_READ:
+        case GL_STATIC_COPY:
+            mUsage = D3DBufferUsage::STATIC;
+            initializeStaticData();
+            break;
+
+        case GL_STREAM_DRAW:
+        case GL_STREAM_READ:
+        case GL_STREAM_COPY:
+        case GL_DYNAMIC_READ:
+        case GL_DYNAMIC_COPY:
+        case GL_DYNAMIC_DRAW:
+            mUsage = D3DBufferUsage::DYNAMIC;
+            break;
+        default:
+            UNREACHABLE();
+    }
+}
+
+void BufferD3D::initializeStaticData()
+{
+    if (mStaticVertexBuffers.empty())
+    {
+        auto newStaticBuffer = new StaticVertexBufferInterface(mFactory);
+        mStaticVertexBuffers.push_back(
+            std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer));
+    }
+    if (!mStaticIndexBuffer)
+    {
+        mStaticIndexBuffer = new StaticIndexBufferInterface(mFactory);
+    }
+}
+
+StaticIndexBufferInterface *BufferD3D::getStaticIndexBuffer()
+{
+    return mStaticIndexBuffer;
+}
+
+StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer(const gl::VertexAttribute &attribute,
+                                                              const gl::VertexBinding &binding)
+{
+    if (mStaticVertexBuffers.empty())
+    {
+        // Early out if there aren't any static buffers at all
+        return nullptr;
+    }
+
+    // Early out, the attribute can be added to mStaticVertexBuffer.
+    if (mStaticVertexBuffers.size() == 1 && mStaticVertexBuffers[0]->empty())
+    {
+        return mStaticVertexBuffers[0].get();
+    }
+
+    // Cache size limiting: track the total allocated buffer sizes.
+    size_t currentTotalSize = 0;
+
+    // At this point, see if any of the existing static buffers contains the attribute data
+    // If there is a cached static buffer that already contains the attribute, then return it
+    for (const auto &staticBuffer : mStaticVertexBuffers)
+    {
+        if (staticBuffer->matchesAttribute(attribute, binding))
+        {
+            return staticBuffer.get();
+        }
+
+        currentTotalSize += staticBuffer->getBufferSize();
+    }
+
+    // Cache size limiting: Clean-up threshold is four times the base buffer size, with a minimum.
+    ASSERT(getSize() < std::numeric_limits<size_t>::max() / 4u);
+    size_t sizeThreshold = std::max(getSize() * 4u, static_cast<size_t>(0x1000u));
+
+    // If we're past the threshold, clear the buffer cache. Note that this will release buffers
+    // that are currenly bound, and in an edge case can even translate the same attribute twice
+    // in the same draw call. It will not delete currently bound buffers, however, because they
+    // are ref counted.
+    if (currentTotalSize > sizeThreshold)
+    {
+        emptyStaticBufferCache();
+    }
+
+    // At this point, we must create a new static buffer for the attribute data.
+    auto newStaticBuffer = new StaticVertexBufferInterface(mFactory);
+    newStaticBuffer->setAttribute(attribute, binding);
+    mStaticVertexBuffers.push_back(std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer));
+    return newStaticBuffer;
+}
+
+void BufferD3D::invalidateStaticData()
+{
+    emptyStaticBufferCache();
+
+    if (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)
+    {
+        SafeDelete(mStaticIndexBuffer);
+    }
+
+    // If the buffer was created with a static usage then we recreate the static
+    // buffers so that they are populated the next time we use this buffer.
+    if (mUsage == D3DBufferUsage::STATIC)
+    {
+        initializeStaticData();
+    }
+
+    mUnmodifiedDataUse = 0;
+}
+
+// Creates static buffers if sufficient used data has been left unmodified
+void BufferD3D::promoteStaticUsage(int dataSize)
+{
+    if (mUsage == D3DBufferUsage::DYNAMIC)
+    {
+        mUnmodifiedDataUse += dataSize;
+
+        if (mUnmodifiedDataUse > 3 * getSize())
+        {
+            updateD3DBufferUsage(GL_STATIC_DRAW);
+        }
+    }
+}
+
+gl::Error BufferD3D::getIndexRange(GLenum type,
+                                   size_t offset,
+                                   size_t count,
+                                   bool primitiveRestartEnabled,
+                                   gl::IndexRange *outRange)
+{
+    const uint8_t *data = nullptr;
+    ANGLE_TRY(getData(&data));
+
+    *outRange = gl::ComputeIndexRange(type, data + offset, count, primitiveRestartEnabled);
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h
new file mode 100644
index 0000000..e8abdc3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h
@@ -0,0 +1,88 @@
+//
+// 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.
+//
+
+// BufferD3D.h: Defines the rx::BufferD3D class, an implementation of BufferImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
+#define LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/BufferImpl.h"
+
+#include <stdint.h>
+#include <vector>
+
+namespace gl
+{
+struct VertexAttribute;
+struct VertexBinding;
+}
+
+namespace rx
+{
+class BufferFactoryD3D;
+class StaticIndexBufferInterface;
+class StaticVertexBufferInterface;
+
+enum class D3DBufferUsage
+{
+    STATIC,
+    DYNAMIC,
+};
+
+class BufferD3D : public BufferImpl
+{
+  public:
+    BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory);
+    virtual ~BufferD3D();
+
+    unsigned int getSerial() const { return mSerial; }
+
+    virtual size_t getSize() const = 0;
+    virtual bool supportsDirectBinding() const = 0;
+    virtual gl::Error markTransformFeedbackUsage() = 0;
+    virtual gl::Error getData(const uint8_t **outData) = 0;
+
+    // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+    // function.
+    StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute,
+                                                       const gl::VertexBinding &binding);
+    StaticIndexBufferInterface *getStaticIndexBuffer();
+
+    virtual void initializeStaticData();
+    virtual void invalidateStaticData();
+
+    void promoteStaticUsage(int dataSize);
+
+    gl::Error getIndexRange(GLenum type,
+                            size_t offset,
+                            size_t count,
+                            bool primitiveRestartEnabled,
+                            gl::IndexRange *outRange) override;
+
+    BufferFactoryD3D *getFactory() const { return mFactory; }
+    D3DBufferUsage getUsage() const { return mUsage; }
+
+  protected:
+    void updateSerial();
+    void updateD3DBufferUsage(GLenum usage);
+    void emptyStaticBufferCache();
+
+    BufferFactoryD3D *mFactory;
+    unsigned int mSerial;
+    static unsigned int mNextSerial;
+
+    std::vector<std::unique_ptr<StaticVertexBufferInterface>> mStaticVertexBuffers;
+    StaticIndexBufferInterface *mStaticIndexBuffer;
+    unsigned int mStaticBufferCacheTotalSize;
+    unsigned int mStaticVertexBufferOutOfDate;
+    unsigned int mUnmodifiedDataUse;
+    D3DBufferUsage mUsage;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
new file mode 100644
index 0000000..6f8d171
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CompilerD3D:
+//   Implementation of the D3D compiler methods.
+//
+
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+
+namespace rx
+{
+
+CompilerD3D::CompilerD3D(ShShaderOutput translatorOutputType)
+    : mTranslatorOutputType(translatorOutputType)
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/CompilerD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
new file mode 100644
index 0000000..7ad6f07
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompilerD3D.h: Defines the rx::CompilerD3D class, an implementation of rx::CompilerImpl.
+
+#ifndef LIBANGLE_RENDERER_COMPILERD3D_H_
+#define LIBANGLE_RENDERER_COMPILERD3D_H_
+
+#include "libANGLE/renderer/CompilerImpl.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+class CompilerD3D : public CompilerImpl
+{
+  public:
+    CompilerD3D(ShShaderOutput translatorOutputType);
+    ~CompilerD3D() override {}
+
+    gl::Error release() override { return gl::NoError(); }
+    ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; }
+
+  private:
+    ShShaderOutput mTranslatorOutputType;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_COMPILERD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
new file mode 100644
index 0000000..f40e6e6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
@@ -0,0 +1,102 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DeviceD3D.cpp: D3D implementation of egl::Device
+
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+#include "libANGLE/Device.h"
+#include "libANGLE/Display.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+DeviceD3D::DeviceD3D()
+    : mDevice(0), mDeviceType(0), mDeviceExternallySourced(false), mIsInitialized(false)
+{
+}
+
+DeviceD3D::~DeviceD3D()
+{
+#if defined(ANGLE_ENABLE_D3D11)
+    if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
+    {
+        // DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it.
+        ID3D11Device *device = reinterpret_cast<ID3D11Device *>(mDevice);
+        device->Release();
+    }
+#endif
+}
+
+egl::Error DeviceD3D::getDevice(void **outValue)
+{
+    if (!mIsInitialized)
+    {
+        *outValue = nullptr;
+        return egl::Error(EGL_BAD_DEVICE_EXT);
+    }
+
+    *outValue = mDevice;
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DeviceD3D::initialize(void *device,
+                                 EGLint deviceType,
+                                 EGLBoolean deviceExternallySourced)
+{
+    ASSERT(!mIsInitialized);
+    if (mIsInitialized)
+    {
+        return egl::Error(EGL_BAD_DEVICE_EXT);
+    }
+
+    mDevice                  = device;
+    mDeviceType              = deviceType;
+    mDeviceExternallySourced = !!deviceExternallySourced;
+
+#if defined(ANGLE_ENABLE_D3D11)
+    if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
+    {
+        // Validate the device
+        IUnknown *iunknown = reinterpret_cast<IUnknown *>(device);
+
+        ID3D11Device *d3dDevice = nullptr;
+        HRESULT hr =
+            iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice));
+        if (FAILED(hr))
+        {
+            return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid D3D device passed into EGLDeviceEXT");
+        }
+
+        // The QI to ID3D11Device adds a ref to the D3D11 device.
+        // Deliberately don't release the ref here, so that the DeviceD3D holds a ref to the
+        // D3D11 device.
+    }
+    else
+#endif
+    {
+        ASSERT(!mDeviceExternallySourced);
+    }
+
+    mIsInitialized = true;
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+EGLint DeviceD3D::getType()
+{
+    return mDeviceType;
+}
+
+void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const
+{
+    outExtensions->deviceD3D = true;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
new file mode 100644
index 0000000..1dd9979
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DeviceD3D.h: D3D implementation of egl::Device
+
+#ifndef LIBANGLE_RENDERER_D3D_DEVICED3D_H_
+#define LIBANGLE_RENDERER_D3D_DEVICED3D_H_
+
+#include "libANGLE/Device.h"
+#include "libANGLE/renderer/DeviceImpl.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+class DeviceD3D : public DeviceImpl
+{
+  public:
+    DeviceD3D();
+    ~DeviceD3D() override;
+
+    egl::Error initialize(void *device, EGLint deviceType, EGLBoolean external);
+    egl::Error getDevice(void **outValue) override;
+    EGLint getType() override;
+    void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
+    bool deviceExternallySourced() override { return mDeviceExternallySourced; }
+
+  private:
+    void *mDevice;
+    EGLint mDeviceType;
+    bool mDeviceExternallySourced;
+    bool mIsInitialized;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_DEVICED3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
new file mode 100644
index 0000000..cb8c44e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
@@ -0,0 +1,363 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayD3D.cpp: D3D implementation of egl::Display
+
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+
+#include <EGL/eglext.h>
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+
+#if defined (ANGLE_ENABLE_D3D9)
+#   include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#endif // ANGLE_ENABLE_D3D9
+
+#if defined (ANGLE_ENABLE_D3D11)
+#   include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#endif // ANGLE_ENABLE_D3D11
+
+#if !defined(ANGLE_DEFAULT_D3D11)
+// Enables use of the Direct3D 11 API for a default display, when available
+#   define ANGLE_DEFAULT_D3D11 1
+#endif
+
+namespace rx
+{
+
+typedef RendererD3D *(*CreateRendererD3DFunction)(egl::Display*);
+
+template <typename RendererType>
+static RendererD3D *CreateTypedRendererD3D(egl::Display *display)
+{
+    return new RendererType(display);
+}
+
+egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
+{
+    ASSERT(outRenderer != nullptr);
+
+    std::vector<CreateRendererD3DFunction> rendererCreationFunctions;
+
+    if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
+    {
+        const auto &attribMap              = display->getAttributeMap();
+        EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
+
+        EGLint requestedDisplayType = static_cast<EGLint>(
+            attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
+
+#   if defined(ANGLE_ENABLE_D3D11)
+        if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+            nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE ||
+            requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+        {
+            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+        }
+#   endif
+
+#   if defined(ANGLE_ENABLE_D3D9)
+        if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+            requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
+        {
+            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+        }
+#   endif
+
+        if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
+            nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
+            requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
+        {
+        // The default display is requested, try the D3D9 and D3D11 renderers, order them using
+        // the definition of ANGLE_DEFAULT_D3D11
+#       if ANGLE_DEFAULT_D3D11
+#           if defined(ANGLE_ENABLE_D3D11)
+            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+#           endif
+#           if defined(ANGLE_ENABLE_D3D9)
+            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+#           endif
+#       else
+#           if defined(ANGLE_ENABLE_D3D9)
+            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+#           endif
+#           if defined(ANGLE_ENABLE_D3D11)
+            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+#           endif
+#       endif
+        }
+    }
+    else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
+    {
+#if defined(ANGLE_ENABLE_D3D11)
+        if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE)
+        {
+            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+        }
+#endif
+    }
+    else
+    {
+        UNIMPLEMENTED();
+    }
+
+    for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
+    {
+        RendererD3D *renderer = rendererCreationFunctions[i](display);
+        egl::Error result     = renderer->initialize();
+
+#       if defined(ANGLE_ENABLE_D3D11)
+            if (renderer->getRendererClass() == RENDERER_D3D11)
+            {
+                ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS);
+                ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11InitializeResult",
+                                            result.getID(),
+                                            NUM_D3D11_INIT_ERRORS);
+            }
+#       endif
+
+#       if defined(ANGLE_ENABLE_D3D9)
+            if (renderer->getRendererClass() == RENDERER_D3D9)
+            {
+                ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS);
+                ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D9InitializeResult",
+                                            result.getID(),
+                                            NUM_D3D9_INIT_ERRORS);
+            }
+#       endif
+
+        if (!result.isError())
+        {
+            *outRenderer = renderer;
+            return result;
+        }
+
+        // Failed to create the renderer, try the next
+        SafeDelete(renderer);
+    }
+
+    return egl::Error(EGL_NOT_INITIALIZED, "No available renderers.");
+}
+
+DisplayD3D::DisplayD3D(const egl::DisplayState &state) : DisplayImpl(state), mRenderer(nullptr)
+{
+}
+
+SurfaceImpl *DisplayD3D::createWindowSurface(const egl::SurfaceState &state,
+                                             EGLNativeWindowType window,
+                                             const egl::AttributeMap &attribs)
+{
+    ASSERT(mRenderer != nullptr);
+    return new WindowSurfaceD3D(state, mRenderer, mDisplay, window, attribs);
+}
+
+SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state,
+                                              const egl::AttributeMap &attribs)
+{
+    ASSERT(mRenderer != nullptr);
+    return new PbufferSurfaceD3D(state, mRenderer, mDisplay, 0, nullptr, attribs);
+}
+
+SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                                       EGLenum buftype,
+                                                       EGLClientBuffer clientBuffer,
+                                                       const egl::AttributeMap &attribs)
+{
+    ASSERT(mRenderer != nullptr);
+    return new PbufferSurfaceD3D(state, mRenderer, mDisplay, buftype, clientBuffer, attribs);
+}
+
+SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::SurfaceState &state,
+                                             NativePixmapType nativePixmap,
+                                             const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+ImageImpl *DisplayD3D::createImage(const egl::ImageState &state,
+                                   EGLenum target,
+                                   const egl::AttributeMap &attribs)
+{
+    return new EGLImageD3D(state, target, attribs, mRenderer);
+}
+
+egl::Error DisplayD3D::getDevice(DeviceImpl **device)
+{
+    return mRenderer->getEGLDevice(device);
+}
+
+ContextImpl *DisplayD3D::createContext(const gl::ContextState &state)
+{
+    ASSERT(mRenderer != nullptr);
+    return mRenderer->createContext(state);
+}
+
+StreamProducerImpl *DisplayD3D::createStreamProducerD3DTextureNV12(
+    egl::Stream::ConsumerType consumerType,
+    const egl::AttributeMap &attribs)
+{
+    ASSERT(mRenderer != nullptr);
+    return mRenderer->createStreamProducerD3DTextureNV12(consumerType, attribs);
+}
+
+egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayD3D::initialize(egl::Display *display)
+{
+    ASSERT(mRenderer == nullptr && display != nullptr);
+    mDisplay = display;
+    ANGLE_TRY(CreateRendererD3D(display, &mRenderer));
+    return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayD3D::terminate()
+{
+    SafeDelete(mRenderer);
+}
+
+egl::ConfigSet DisplayD3D::generateConfigs()
+{
+    ASSERT(mRenderer != nullptr);
+    return mRenderer->generateConfigs();
+}
+
+bool DisplayD3D::testDeviceLost()
+{
+    ASSERT(mRenderer != nullptr);
+    return mRenderer->testDeviceLost();
+}
+
+egl::Error DisplayD3D::restoreLostDevice()
+{
+    // Release surface resources to make the Reset() succeed
+    for (auto &surface : mState.surfaceSet)
+    {
+        if (surface->getBoundTexture())
+        {
+            surface->releaseTexImage(EGL_BACK_BUFFER);
+        }
+        SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+        surfaceD3D->releaseSwapChain();
+    }
+
+    if (!mRenderer->resetDevice())
+    {
+        return egl::Error(EGL_BAD_ALLOC);
+    }
+
+    // Restore any surfaces that may have been lost
+    for (const auto &surface : mState.surfaceSet)
+    {
+        SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+
+        egl::Error error = surfaceD3D->resetSwapChain();
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    return mRenderer->isValidNativeWindow(window);
+}
+
+egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration,
+                                            EGLenum buftype,
+                                            EGLClientBuffer clientBuffer,
+                                            const egl::AttributeMap &attribs) const
+{
+    switch (buftype)
+    {
+        case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+            return mRenderer->validateShareHandle(configuration, static_cast<HANDLE>(clientBuffer),
+                                                  attribs);
+
+        case EGL_D3D_TEXTURE_ANGLE:
+            return mRenderer->getD3DTextureInfo(
+                configuration, static_cast<IUnknown *>(clientBuffer), nullptr, nullptr, nullptr);
+
+        default:
+            return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+    }
+}
+
+void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+    mRenderer->generateDisplayExtensions(outExtensions);
+}
+
+std::string DisplayD3D::getVendorString() const
+{
+    std::string vendorString = "Google Inc.";
+    if (mRenderer)
+    {
+        vendorString += " " + mRenderer->getVendorString();
+    }
+
+    return vendorString;
+}
+
+void DisplayD3D::generateCaps(egl::Caps *outCaps) const
+{
+    // Display must be initialized to generate caps
+    ASSERT(mRenderer != nullptr);
+
+    outCaps->textureNPOT = mRenderer->getNativeExtensions().textureNPOT;
+}
+
+egl::Error DisplayD3D::waitClient() const
+{
+    for (auto &surface : mState.surfaceSet)
+    {
+        SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+        surfaceD3D->checkForOutOfDateSwapChain();
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayD3D::waitNative(EGLint engine,
+                                  egl::Surface *drawSurface,
+                                  egl::Surface *readSurface) const
+{
+    if (drawSurface != nullptr)
+    {
+        SurfaceD3D *drawSurfaceD3D = GetImplAs<SurfaceD3D>(drawSurface);
+        drawSurfaceD3D->checkForOutOfDateSwapChain();
+    }
+
+    if (readSurface != nullptr)
+    {
+        SurfaceD3D *readurfaceD3D = GetImplAs<SurfaceD3D>(readSurface);
+        readurfaceD3D->checkForOutOfDateSwapChain();
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+gl::Version DisplayD3D::getMaxSupportedESVersion() const
+{
+    return mRenderer->getMaxSupportedESVersion();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
new file mode 100644
index 0000000..944e623
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
@@ -0,0 +1,85 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayD3D.h: D3D implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
+#define LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
+
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/Device.h"
+
+namespace rx
+{
+class RendererD3D;
+
+class DisplayD3D : public DisplayImpl
+{
+  public:
+    DisplayD3D(const egl::DisplayState &state);
+
+    egl::Error initialize(egl::Display *display) override;
+    virtual void terminate() override;
+
+    // Surface creation
+    SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+                                     EGLNativeWindowType window,
+                                     const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+                                      const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                               EGLenum buftype,
+                                               EGLClientBuffer clientBuffer,
+                                               const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+                                     NativePixmapType nativePixmap,
+                                     const egl::AttributeMap &attribs) override;
+
+    ImageImpl *createImage(const egl::ImageState &state,
+                           EGLenum target,
+                           const egl::AttributeMap &attribs) override;
+
+    ContextImpl *createContext(const gl::ContextState &state) override;
+
+    StreamProducerImpl *createStreamProducerD3DTextureNV12(
+        egl::Stream::ConsumerType consumerType,
+        const egl::AttributeMap &attribs) override;
+
+    egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
+
+    egl::ConfigSet generateConfigs() override;
+
+    bool testDeviceLost() override;
+    egl::Error restoreLostDevice() override;
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+    egl::Error validateClientBuffer(const egl::Config *configuration,
+                                    EGLenum buftype,
+                                    EGLClientBuffer clientBuffer,
+                                    const egl::AttributeMap &attribs) const override;
+
+    egl::Error getDevice(DeviceImpl **device) override;
+
+    std::string getVendorString() const override;
+
+    egl::Error waitClient() const override;
+    egl::Error waitNative(EGLint engine,
+                          egl::Surface *drawSurface,
+                          egl::Surface *readSurface) const override;
+    gl::Version getMaxSupportedESVersion() const override;
+
+  private:
+    void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+    void generateCaps(egl::Caps *outCaps) const override;
+
+    egl::Display *mDisplay;
+
+    rx::RendererD3D *mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
new file mode 100644
index 0000000..b4366e7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -0,0 +1,1247 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DynamicHLSL.cpp: Implementation for link and run-time HLSL generation
+//
+
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+
+#include "common/utilities.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/VaryingPacking.h"
+
+using namespace gl;
+
+namespace rx
+{
+
+namespace
+{
+
+std::string HLSLComponentTypeString(GLenum componentType)
+{
+    switch (componentType)
+    {
+        case GL_UNSIGNED_INT:
+            return "uint";
+        case GL_INT:
+            return "int";
+        case GL_UNSIGNED_NORMALIZED:
+        case GL_SIGNED_NORMALIZED:
+        case GL_FLOAT:
+            return "float";
+        default:
+            UNREACHABLE();
+            return "not-component-type";
+    }
+}
+
+std::string HLSLComponentTypeString(GLenum componentType, int componentCount)
+{
+    return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : "");
+}
+
+std::string HLSLMatrixTypeString(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT_MAT2:
+            return "float2x2";
+        case GL_FLOAT_MAT3:
+            return "float3x3";
+        case GL_FLOAT_MAT4:
+            return "float4x4";
+        case GL_FLOAT_MAT2x3:
+            return "float2x3";
+        case GL_FLOAT_MAT3x2:
+            return "float3x2";
+        case GL_FLOAT_MAT2x4:
+            return "float2x4";
+        case GL_FLOAT_MAT4x2:
+            return "float4x2";
+        case GL_FLOAT_MAT3x4:
+            return "float3x4";
+        case GL_FLOAT_MAT4x3:
+            return "float4x3";
+        default:
+            UNREACHABLE();
+            return "not-matrix-type";
+    }
+}
+
+std::string HLSLTypeString(GLenum type)
+{
+    if (gl::IsMatrixType(type))
+    {
+        return HLSLMatrixTypeString(type);
+    }
+
+    return HLSLComponentTypeString(gl::VariableComponentType(type),
+                                   gl::VariableComponentCount(type));
+}
+
+const PixelShaderOutputVariable *FindOutputAtLocation(
+    const std::vector<PixelShaderOutputVariable> &outputVariables,
+    unsigned int location)
+{
+    for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex)
+    {
+        if (outputVariables[variableIndex].outputIndex == location)
+        {
+            return &outputVariables[variableIndex];
+        }
+    }
+
+    return nullptr;
+}
+
+void WriteArrayString(std::stringstream &strstr, unsigned int i)
+{
+    static_assert(GL_INVALID_INDEX == UINT_MAX,
+                  "GL_INVALID_INDEX must be equal to the max unsigned int.");
+    if (i == UINT_MAX)
+    {
+        return;
+    }
+
+    strstr << "[";
+    strstr << i;
+    strstr << "]";
+}
+
+constexpr const char *VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
+constexpr const char *PIXEL_OUTPUT_STUB_STRING     = "@@ PIXEL OUTPUT @@";
+}  // anonymous namespace
+
+// DynamicHLSL implementation
+
+DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer)
+{
+}
+
+std::string DynamicHLSL::generateVertexShaderForInputLayout(
+    const std::string &sourceShader,
+    const InputLayout &inputLayout,
+    const std::vector<sh::Attribute> &shaderAttributes) const
+{
+    std::stringstream structStream;
+    std::stringstream initStream;
+
+    structStream << "struct VS_INPUT\n"
+                 << "{\n";
+
+    int semanticIndex       = 0;
+    unsigned int inputIndex = 0;
+
+    // If gl_PointSize is used in the shader then pointsprites rendering is expected.
+    // If the renderer does not support Geometry shaders then Instanced PointSprite emulation
+    // must be used.
+    bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos;
+    bool useInstancedPointSpriteEmulation =
+        usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
+
+    // Instanced PointSprite emulation requires additional entries in the
+    // VS_INPUT structure to support the vertices that make up the quad vertices.
+    // These values must be in sync with the cooresponding values added during inputlayout creation
+    // in InputLayoutCache::applyVertexBuffers().
+    //
+    // The additional entries must appear first in the VS_INPUT layout because
+    // Windows Phone 8 era devices require per vertex data to physically come
+    // before per instance data in the shader.
+    if (useInstancedPointSpriteEmulation)
+    {
+        structStream << "    float3 spriteVertexPos : SPRITEPOSITION0;\n"
+                     << "    float2 spriteTexCoord : SPRITETEXCOORD0;\n";
+    }
+
+    for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex)
+    {
+        const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex];
+        if (!shaderAttribute.name.empty())
+        {
+            ASSERT(inputIndex < MAX_VERTEX_ATTRIBS);
+            VertexFormatType vertexFormatType =
+                inputIndex < inputLayout.size() ? inputLayout[inputIndex] : VERTEX_FORMAT_INVALID;
+
+            // HLSL code for input structure
+            if (IsMatrixType(shaderAttribute.type))
+            {
+                // Matrix types are always transposed
+                structStream << "    "
+                             << HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
+            }
+            else
+            {
+                GLenum componentType = mRenderer->getVertexComponentType(vertexFormatType);
+
+                if (shaderAttribute.name == "gl_InstanceID" ||
+                    shaderAttribute.name == "gl_VertexID")
+                {
+                    // The input types of the instance ID and vertex ID in HLSL (uint) differs from
+                    // the ones in ESSL (int).
+                    structStream << " uint";
+                }
+                else
+                {
+                    structStream << "    " << HLSLComponentTypeString(
+                                                  componentType,
+                                                  VariableComponentCount(shaderAttribute.type));
+                }
+            }
+
+            structStream << " " << decorateVariable(shaderAttribute.name) << " : ";
+
+            if (shaderAttribute.name == "gl_InstanceID")
+            {
+                structStream << "SV_InstanceID";
+            }
+            else if (shaderAttribute.name == "gl_VertexID")
+            {
+                structStream << "SV_VertexID";
+            }
+            else
+            {
+                structStream << "TEXCOORD" << semanticIndex;
+                semanticIndex += VariableRegisterCount(shaderAttribute.type);
+            }
+
+            structStream << ";\n";
+
+            // HLSL code for initialization
+            initStream << "    " << decorateVariable(shaderAttribute.name) << " = ";
+
+            // Mismatched vertex attribute to vertex input may result in an undefined
+            // data reinterpretation (eg for pure integer->float, float->pure integer)
+            // TODO: issue warning with gl debug info extension, when supported
+            if (IsMatrixType(shaderAttribute.type) ||
+                (mRenderer->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_GPU) != 0)
+            {
+                initStream << generateAttributeConversionHLSL(vertexFormatType, shaderAttribute);
+            }
+            else
+            {
+                initStream << "input." << decorateVariable(shaderAttribute.name);
+            }
+
+            initStream << ";\n";
+
+            inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type));
+        }
+    }
+
+    structStream << "};\n"
+                    "\n"
+                    "void initAttributes(VS_INPUT input)\n"
+                    "{\n"
+                 << initStream.str() << "}\n";
+
+    std::string vertexHLSL(sourceShader);
+
+    size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING);
+    vertexHLSL.replace(copyInsertionPos, strlen(VERTEX_ATTRIBUTE_STUB_STRING), structStream.str());
+
+    return vertexHLSL;
+}
+
+std::string DynamicHLSL::generatePixelShaderForOutputSignature(
+    const std::string &sourceShader,
+    const std::vector<PixelShaderOutputVariable> &outputVariables,
+    bool usesFragDepth,
+    const std::vector<GLenum> &outputLayout) const
+{
+    const int shaderModel      = mRenderer->getMajorShaderModel();
+    std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR";
+    std::string depthSemantic  = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
+
+    std::stringstream declarationStream;
+    std::stringstream copyStream;
+
+    declarationStream << "struct PS_OUTPUT\n"
+                         "{\n";
+
+    // Workaround for HLSL 3.x: We can't do a depth/stencil only render, the runtime will complain.
+    size_t numOutputs = outputLayout.empty() ? 1u : outputLayout.size();
+    const PixelShaderOutputVariable defaultOutput(GL_FLOAT_VEC4, "dummy", "float4(0, 0, 0, 1)", 0);
+
+    for (size_t layoutIndex = 0; layoutIndex < numOutputs; ++layoutIndex)
+    {
+        GLenum binding = outputLayout.empty() ? GL_COLOR_ATTACHMENT0 : outputLayout[layoutIndex];
+
+        if (binding != GL_NONE)
+        {
+            unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
+
+            const PixelShaderOutputVariable *outputVariable =
+                outputLayout.empty() ? &defaultOutput
+                                     : FindOutputAtLocation(outputVariables, location);
+
+            // OpenGL ES 3.0 spec $4.2.1
+            // If [...] not all user-defined output variables are written, the values of fragment
+            // colors
+            // corresponding to unwritten variables are similarly undefined.
+            if (outputVariable)
+            {
+                declarationStream << "    " + HLSLTypeString(outputVariable->type) << " "
+                                  << outputVariable->name << " : " << targetSemantic
+                                  << static_cast<int>(layoutIndex) << ";\n";
+
+                copyStream << "    output." << outputVariable->name << " = "
+                           << outputVariable->source << ";\n";
+            }
+        }
+    }
+
+    if (usesFragDepth)
+    {
+        declarationStream << "    float gl_Depth : " << depthSemantic << ";\n";
+        copyStream << "    output.gl_Depth = gl_Depth; \n";
+    }
+
+    declarationStream << "};\n"
+                         "\n"
+                         "PS_OUTPUT generateOutput()\n"
+                         "{\n"
+                         "    PS_OUTPUT output;\n"
+                      << copyStream.str() << "    return output;\n"
+                                             "}\n";
+
+    std::string pixelHLSL(sourceShader);
+
+    size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING);
+    pixelHLSL.replace(outputInsertionPos, strlen(PIXEL_OUTPUT_STUB_STRING),
+                      declarationStream.str());
+
+    return pixelHLSL;
+}
+
+void DynamicHLSL::generateVaryingLinkHLSL(const VaryingPacking &varyingPacking,
+                                          const BuiltinInfo &builtins,
+                                          bool programUsesPointSize,
+                                          std::stringstream &hlslStream) const
+{
+    ASSERT(builtins.dxPosition.enabled);
+    hlslStream << "{\n"
+               << "    float4 dx_Position : " << builtins.dxPosition.str() << ";\n";
+
+    if (builtins.glPosition.enabled)
+    {
+        hlslStream << "    float4 gl_Position : " << builtins.glPosition.str() << ";\n";
+    }
+
+    if (builtins.glFragCoord.enabled)
+    {
+        hlslStream << "    float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
+    }
+
+    if (builtins.glPointCoord.enabled)
+    {
+        hlslStream << "    float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
+    }
+
+    if (builtins.glPointSize.enabled)
+    {
+        hlslStream << "    float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
+    }
+
+    std::string varyingSemantic =
+        GetVaryingSemantic(mRenderer->getMajorShaderModel(), programUsesPointSize);
+
+    for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+    {
+        const auto &varying = *registerInfo.packedVarying->varying;
+        ASSERT(!varying.isStruct());
+
+        // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
+        // registers being used.
+        // For example, if there are N registers, and we have N vec3 varyings and 1 float
+        // varying, then D3D will pack them into N registers.
+        // If the float varying has the 'nointerpolation' modifier on it then we would need
+        // N + 1 registers, and D3D compilation will fail.
+
+        switch (registerInfo.packedVarying->interpolation)
+        {
+            case sh::INTERPOLATION_SMOOTH:
+                hlslStream << "    ";
+                break;
+            case sh::INTERPOLATION_FLAT:
+                hlslStream << "    nointerpolation ";
+                break;
+            case sh::INTERPOLATION_CENTROID:
+                hlslStream << "    centroid ";
+                break;
+            default:
+                UNREACHABLE();
+        }
+
+        GLenum transposedType = gl::TransposeMatrixType(varying.type);
+        GLenum componentType  = gl::VariableComponentType(transposedType);
+        int columnCount       = gl::VariableColumnCount(transposedType);
+        hlslStream << HLSLComponentTypeString(componentType, columnCount);
+        unsigned int semanticIndex = registerInfo.semanticIndex;
+        hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n";
+    }
+
+    hlslStream << "};\n";
+}
+
+void DynamicHLSL::generateShaderLinkHLSL(const gl::ContextState &data,
+                                         const gl::ProgramState &programData,
+                                         const ProgramD3DMetadata &programMetadata,
+                                         const VaryingPacking &varyingPacking,
+                                         const BuiltinVaryingsD3D &builtinsD3D,
+                                         std::string *pixelHLSL,
+                                         std::string *vertexHLSL) const
+{
+    ASSERT(pixelHLSL->empty() && vertexHLSL->empty());
+
+    const gl::Shader *vertexShaderGL   = programData.getAttachedVertexShader();
+    const gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader();
+    const ShaderD3D *fragmentShader    = GetImplAs<ShaderD3D>(fragmentShaderGL);
+    const int shaderModel              = mRenderer->getMajorShaderModel();
+
+    // usesViewScale() isn't supported in the D3D9 renderer
+    ASSERT(shaderModel >= 4 || !programMetadata.usesViewScale());
+
+    bool useInstancedPointSpriteEmulation =
+        programMetadata.usesPointSize() &&
+        mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
+
+    // Validation done in the compiler
+    ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData());
+
+    std::stringstream vertexStream;
+    vertexStream << vertexShaderGL->getTranslatedSource();
+
+    // Instanced PointSprite emulation requires additional entries originally generated in the
+    // GeometryShader HLSL. These include pointsize clamp values.
+    if (useInstancedPointSpriteEmulation)
+    {
+        vertexStream << "static float minPointSize = "
+                     << static_cast<int>(data.getCaps().minAliasedPointSize) << ".0f;\n"
+                     << "static float maxPointSize = "
+                     << static_cast<int>(data.getCaps().maxAliasedPointSize) << ".0f;\n";
+    }
+
+    // Add stub string to be replaced when shader is dynamically defined by its layout
+    vertexStream << "\n" << std::string(VERTEX_ATTRIBUTE_STUB_STRING) << "\n";
+
+    const auto &vertexBuiltins = builtinsD3D[SHADER_VERTEX];
+
+    // Write the HLSL input/output declarations
+    vertexStream << "struct VS_OUTPUT\n";
+    generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(),
+                            vertexStream);
+    vertexStream << "\n"
+                 << "VS_OUTPUT main(VS_INPUT input)\n"
+                 << "{\n"
+                 << "    initAttributes(input);\n";
+
+    vertexStream << "\n"
+                 << "    gl_main();\n"
+                 << "\n"
+                 << "    VS_OUTPUT output;\n";
+
+    if (vertexBuiltins.glPosition.enabled)
+    {
+        vertexStream << "    output.gl_Position = gl_Position;\n";
+    }
+
+    // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
+    if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+    {
+        vertexStream << "    output.dx_Position.x = gl_Position.x;\n";
+
+        if (programMetadata.usesViewScale())
+        {
+            // This code assumes that dx_ViewScale.y = -1.0f when rendering to texture, and +1.0f
+            // when rendering to the default framebuffer. No other values are valid.
+            vertexStream << "    output.dx_Position.y = dx_ViewScale.y * gl_Position.y;\n";
+        }
+        else
+        {
+            vertexStream << "    output.dx_Position.y = - gl_Position.y;\n";
+        }
+
+        vertexStream << "    output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+                     << "    output.dx_Position.w = gl_Position.w;\n";
+    }
+    else
+    {
+        vertexStream << "    output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + "
+                        "dx_ViewAdjust.x * gl_Position.w;\n";
+
+        // If usesViewScale() is true and we're using the D3D11 renderer via Feature Level 9_*,
+        // then we need to multiply the gl_Position.y by the viewScale.
+        // usesViewScale() isn't supported when using the D3D9 renderer.
+        if (programMetadata.usesViewScale() &&
+            (shaderModel >= 4 && mRenderer->getShaderModelSuffix() != ""))
+        {
+            vertexStream << "    output.dx_Position.y = dx_ViewScale.y * (gl_Position.y * "
+                            "dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n";
+        }
+        else
+        {
+            vertexStream << "    output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + "
+                            "dx_ViewAdjust.y * gl_Position.w);\n";
+        }
+
+        vertexStream << "    output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+                     << "    output.dx_Position.w = gl_Position.w;\n";
+    }
+
+    // We don't need to output gl_PointSize if we use are emulating point sprites via instancing.
+    if (vertexBuiltins.glPointSize.enabled)
+    {
+        vertexStream << "    output.gl_PointSize = gl_PointSize;\n";
+    }
+
+    if (vertexBuiltins.glFragCoord.enabled)
+    {
+        vertexStream << "    output.gl_FragCoord = gl_Position;\n";
+    }
+
+    for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+    {
+        const auto &packedVarying = *registerInfo.packedVarying;
+        const auto &varying = *packedVarying.varying;
+        ASSERT(!varying.isStruct());
+
+        vertexStream << "    output.v" << registerInfo.semanticIndex << " = ";
+
+        if (packedVarying.isStructField())
+        {
+            vertexStream << decorateVariable(packedVarying.parentStructName) << ".";
+        }
+
+        vertexStream << decorateVariable(varying.name);
+
+        if (varying.isArray())
+        {
+            WriteArrayString(vertexStream, registerInfo.varyingArrayIndex);
+        }
+
+        if (VariableRowCount(varying.type) > 1)
+        {
+            WriteArrayString(vertexStream, registerInfo.varyingRowIndex);
+        }
+
+        vertexStream << ";\n";
+    }
+
+    // Instanced PointSprite emulation requires additional entries to calculate
+    // the final output vertex positions of the quad that represents each sprite.
+    if (useInstancedPointSpriteEmulation)
+    {
+        vertexStream << "\n"
+                     << "    gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n";
+
+        vertexStream << "    output.dx_Position.x += (input.spriteVertexPos.x * gl_PointSize / "
+                        "(dx_ViewCoords.x*2)) * output.dx_Position.w;";
+
+        if (programMetadata.usesViewScale())
+        {
+            // Multiply by ViewScale to invert the rendering when appropriate
+            vertexStream << "    output.dx_Position.y += (-dx_ViewScale.y * "
+                            "input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2)) * "
+                            "output.dx_Position.w;";
+        }
+        else
+        {
+            vertexStream << "    output.dx_Position.y += (input.spriteVertexPos.y * gl_PointSize / "
+                            "(dx_ViewCoords.y*2)) * output.dx_Position.w;";
+        }
+
+        vertexStream
+            << "    output.dx_Position.z += input.spriteVertexPos.z * output.dx_Position.w;\n";
+
+        if (programMetadata.usesPointCoord())
+        {
+            vertexStream << "\n"
+                         << "    output.gl_PointCoord = input.spriteTexCoord;\n";
+        }
+    }
+
+    // Renderers that enable instanced pointsprite emulation require the vertex shader output member
+    // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same
+    // default value used in the generated pixel shader.
+    if (programMetadata.usesInsertedPointCoordValue())
+    {
+        ASSERT(!useInstancedPointSpriteEmulation);
+        vertexStream << "\n"
+                     << "    output.gl_PointCoord = float2(0.5, 0.5);\n";
+    }
+
+    vertexStream << "\n"
+                 << "    return output;\n"
+                 << "}\n";
+
+    const auto &pixelBuiltins = builtinsD3D[SHADER_PIXEL];
+
+    std::stringstream pixelStream;
+    pixelStream << fragmentShaderGL->getTranslatedSource();
+    pixelStream << "struct PS_INPUT\n";
+    generateVaryingLinkHLSL(varyingPacking, pixelBuiltins, builtinsD3D.usesPointSize(),
+                            pixelStream);
+    pixelStream << "\n";
+
+    pixelStream << std::string(PIXEL_OUTPUT_STUB_STRING) << "\n";
+
+    if (fragmentShader->usesFrontFacing())
+    {
+        if (shaderModel >= 4)
+        {
+            pixelStream << "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
+                        << "{\n";
+        }
+        else
+        {
+            pixelStream << "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
+                        << "{\n";
+        }
+    }
+    else
+    {
+        pixelStream << "PS_OUTPUT main(PS_INPUT input)\n"
+                    << "{\n";
+    }
+
+    if (pixelBuiltins.glFragCoord.enabled)
+    {
+        pixelStream << "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
+
+        // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader.
+        // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using
+        // dx_ViewCoords.
+        if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+        {
+            pixelStream << "    gl_FragCoord.x = input.dx_Position.x;\n"
+                        << "    gl_FragCoord.y = input.dx_Position.y;\n";
+        }
+        else if (shaderModel == 3)
+        {
+            pixelStream << "    gl_FragCoord.x = input.dx_Position.x + 0.5;\n"
+                        << "    gl_FragCoord.y = input.dx_Position.y + 0.5;\n";
+        }
+        else
+        {
+            // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See
+            // Renderer::setViewport()
+            pixelStream << "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + "
+                           "dx_ViewCoords.z;\n"
+                        << "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + "
+                           "dx_ViewCoords.w;\n";
+        }
+
+        if (programMetadata.usesViewScale())
+        {
+            // For Feature Level 9_3 and below, we need to correct gl_FragCoord.y to account
+            // for dx_ViewScale. On Feature Level 10_0+, gl_FragCoord.y is calculated above using
+            // dx_ViewCoords and is always correct irrespective of dx_ViewScale's value.
+            // NOTE: usesViewScale() can only be true on D3D11 (i.e. Shader Model 4.0+).
+            if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+            {
+                // Some assumptions:
+                //  - dx_ViewScale.y = -1.0f when rendering to texture
+                //  - dx_ViewScale.y = +1.0f when rendering to the default framebuffer
+                //  - gl_FragCoord.y has been set correctly above.
+                //
+                // When rendering to the backbuffer, the code inverts gl_FragCoord's y coordinate.
+                // This involves subtracting the y coordinate from the height of the area being
+                // rendered to.
+                //
+                // First we calculate the height of the area being rendered to:
+                //    render_area_height = (2.0f / (1.0f - input.gl_FragCoord.y * rhw)) *
+                //    gl_FragCoord.y
+                //
+                // Note that when we're rendering to default FB, we want our output to be
+                // equivalent to:
+                //    "gl_FragCoord.y = render_area_height - gl_FragCoord.y"
+                //
+                // When we're rendering to a texture, we want our output to be equivalent to:
+                //    "gl_FragCoord.y = gl_FragCoord.y;"
+                //
+                // If we set scale_factor = ((1.0f + dx_ViewScale.y) / 2.0f), then notice that
+                //  - When rendering to default FB: scale_factor = 1.0f
+                //  - When rendering to texture:    scale_factor = 0.0f
+                //
+                // Therefore, we can get our desired output by setting:
+                //    "gl_FragCoord.y = scale_factor * render_area_height - dx_ViewScale.y *
+                //    gl_FragCoord.y"
+                //
+                // Simplifying, this becomes:
+                pixelStream
+                    << "    gl_FragCoord.y = (1.0f + dx_ViewScale.y) * gl_FragCoord.y /"
+                       "(1.0f - input.gl_FragCoord.y * rhw)  - dx_ViewScale.y * gl_FragCoord.y;\n";
+            }
+        }
+
+        pixelStream << "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + "
+                       "dx_DepthFront.y;\n"
+                    << "    gl_FragCoord.w = rhw;\n";
+    }
+
+    if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3)
+    {
+        pixelStream << "    gl_PointCoord.x = input.gl_PointCoord.x;\n"
+                    << "    gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
+    }
+
+    if (fragmentShader->usesFrontFacing())
+    {
+        if (shaderModel <= 3)
+        {
+            pixelStream << "    gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
+        }
+        else
+        {
+            pixelStream << "    gl_FrontFacing = isFrontFace;\n";
+        }
+    }
+
+    for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+    {
+        const auto &packedVarying = *registerInfo.packedVarying;
+        const auto &varying = *packedVarying.varying;
+        ASSERT(!varying.isBuiltIn() && !varying.isStruct());
+
+        // Don't reference VS-only transform feedback varyings in the PS.
+        // TODO: Consider updating the fragment shader's varyings with a parameter signaling that a
+        // varying is only used in the vertex shader in MergeVaryings
+        if (packedVarying.vertexOnly || (!varying.staticUse && !packedVarying.isStructField()))
+            continue;
+
+        pixelStream << "    ";
+
+        if (packedVarying.isStructField())
+        {
+            pixelStream << decorateVariable(packedVarying.parentStructName) << ".";
+        }
+
+        pixelStream << decorateVariable(varying.name);
+
+        if (varying.isArray())
+        {
+            WriteArrayString(pixelStream, registerInfo.varyingArrayIndex);
+        }
+
+        GLenum transposedType = TransposeMatrixType(varying.type);
+        if (VariableRowCount(transposedType) > 1)
+        {
+            WriteArrayString(pixelStream, registerInfo.varyingRowIndex);
+        }
+
+        pixelStream << " = input.v" << registerInfo.semanticIndex;
+
+        switch (VariableColumnCount(transposedType))
+        {
+            case 1:
+                pixelStream << ".x";
+                break;
+            case 2:
+                pixelStream << ".xy";
+                break;
+            case 3:
+                pixelStream << ".xyz";
+                break;
+            case 4:
+                break;
+            default:
+                UNREACHABLE();
+        }
+        pixelStream << ";\n";
+    }
+
+    pixelStream << "\n"
+                << "    gl_main();\n"
+                << "\n"
+                << "    return generateOutput();\n"
+                << "}\n";
+
+    *vertexHLSL = vertexStream.str();
+    *pixelHLSL  = pixelStream.str();
+}
+
+std::string DynamicHLSL::generateComputeShaderLinkHLSL(const gl::ProgramState &programData) const
+{
+    const gl::Shader *computeShaderGL = programData.getAttachedComputeShader();
+    std::stringstream computeStream;
+    std::string translatedSource = computeShaderGL->getTranslatedSource();
+    computeStream << translatedSource;
+
+    bool usesWorkGroupID = translatedSource.find("GL_USES_WORK_GROUP_ID") != std::string::npos;
+    bool usesLocalInvocationID =
+        translatedSource.find("GL_USES_LOCAL_INVOCATION_ID") != std::string::npos;
+    bool usesGlobalInvocationID =
+        translatedSource.find("GL_USES_GLOBAL_INVOCATION_ID") != std::string::npos;
+    bool usesLocalInvocationIndex =
+        translatedSource.find("GL_USES_LOCAL_INVOCATION_INDEX") != std::string::npos;
+
+    computeStream << "\nstruct CS_INPUT\n{\n";
+    if (usesWorkGroupID)
+    {
+        computeStream << "    uint3 dx_WorkGroupID : "
+                      << "SV_GroupID;\n";
+    }
+
+    if (usesLocalInvocationID)
+    {
+        computeStream << "    uint3 dx_LocalInvocationID : "
+                      << "SV_GroupThreadID;\n";
+    }
+
+    if (usesGlobalInvocationID)
+    {
+        computeStream << "    uint3 dx_GlobalInvocationID : "
+                      << "SV_DispatchThreadID;\n";
+    }
+
+    if (usesLocalInvocationIndex)
+    {
+        computeStream << "    uint dx_LocalInvocationIndex : "
+                      << "SV_GroupIndex;\n";
+    }
+
+    computeStream << "};\n\n";
+
+    const sh::WorkGroupSize &localSize = computeShaderGL->getWorkGroupSize();
+    computeStream << "[numthreads(" << localSize[0] << ", " << localSize[1] << ", " << localSize[2]
+                  << ")]\n";
+
+    computeStream << "void main(CS_INPUT input)\n"
+                  << "{\n";
+
+    if (usesWorkGroupID)
+    {
+        computeStream << "    gl_WorkGroupID = input.dx_WorkGroupID;\n";
+    }
+    if (usesLocalInvocationID)
+    {
+        computeStream << "    gl_LocalInvocationID = input.dx_LocalInvocationID;\n";
+    }
+    if (usesGlobalInvocationID)
+    {
+        computeStream << "    gl_GlobalInvocationID = input.dx_GlobalInvocationID;\n";
+    }
+    if (usesLocalInvocationIndex)
+    {
+        computeStream << "    gl_LocalInvocationIndex = input.dx_LocalInvocationIndex;\n";
+    }
+
+    computeStream << "\n"
+                  << "    gl_main();\n"
+                  << "}\n";
+
+    return computeStream.str();
+}
+
+std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking,
+                                                        const BuiltinVaryingsD3D &builtinsD3D) const
+{
+    ASSERT(mRenderer->getMajorShaderModel() >= 4);
+
+    std::stringstream preambleStream;
+
+    const auto &vertexBuiltins = builtinsD3D[SHADER_VERTEX];
+
+    preambleStream << "struct GS_INPUT\n";
+    generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(),
+                            preambleStream);
+    preambleStream << "\n"
+                   << "struct GS_OUTPUT\n";
+    generateVaryingLinkHLSL(varyingPacking, builtinsD3D[SHADER_GEOMETRY],
+                            builtinsD3D.usesPointSize(), preambleStream);
+    preambleStream
+        << "\n"
+        << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n"
+        << "{\n"
+        << "    output.gl_Position = input.gl_Position;\n";
+
+    if (vertexBuiltins.glPointSize.enabled)
+    {
+        preambleStream << "    output.gl_PointSize = input.gl_PointSize;\n";
+    }
+
+    for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList())
+    {
+        preambleStream << "    output.v" << varyingRegister.semanticIndex << " = ";
+        if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT)
+        {
+            preambleStream << "flat";
+        }
+        preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n";
+    }
+
+    if (vertexBuiltins.glFragCoord.enabled)
+    {
+        preambleStream << "    output.gl_FragCoord = input.gl_FragCoord;\n";
+    }
+
+    // Only write the dx_Position if we aren't using point sprites
+    preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n"
+                   << "    output.dx_Position = input.dx_Position;\n"
+                   << "#endif  // ANGLE_POINT_SPRITE_SHADER\n"
+                   << "}\n";
+
+    return preambleStream.str();
+}
+
+std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
+                                                    const gl::ContextState &data,
+                                                    const gl::ProgramState &programData,
+                                                    const bool useViewScale,
+                                                    const std::string &preambleString) const
+{
+    ASSERT(mRenderer->getMajorShaderModel() >= 4);
+
+    std::stringstream shaderStream;
+
+    const bool pointSprites   = (primitiveType == PRIMITIVE_POINTS);
+    const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos;
+
+    const char *inputPT  = nullptr;
+    const char *outputPT = nullptr;
+    int inputSize        = 0;
+    int maxVertexOutput  = 0;
+
+    switch (primitiveType)
+    {
+        case PRIMITIVE_POINTS:
+            inputPT         = "point";
+            outputPT        = "Triangle";
+            inputSize       = 1;
+            maxVertexOutput = 4;
+            break;
+
+        case PRIMITIVE_LINES:
+        case PRIMITIVE_LINE_STRIP:
+        case PRIMITIVE_LINE_LOOP:
+            inputPT         = "line";
+            outputPT        = "Line";
+            inputSize       = 2;
+            maxVertexOutput = 2;
+            break;
+
+        case PRIMITIVE_TRIANGLES:
+        case PRIMITIVE_TRIANGLE_STRIP:
+        case PRIMITIVE_TRIANGLE_FAN:
+            inputPT         = "triangle";
+            outputPT        = "Triangle";
+            inputSize       = 3;
+            maxVertexOutput = 3;
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    if (pointSprites)
+    {
+        shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
+                        "\n"
+                        "uniform float4 dx_ViewCoords : register(c1);\n";
+
+        if (useViewScale)
+        {
+            shaderStream << "uniform float2 dx_ViewScale : register(c3);\n";
+        }
+
+        shaderStream << "\n"
+                        "static float2 pointSpriteCorners[] = \n"
+                        "{\n"
+                        "    float2( 0.5f, -0.5f),\n"
+                        "    float2( 0.5f,  0.5f),\n"
+                        "    float2(-0.5f, -0.5f),\n"
+                        "    float2(-0.5f,  0.5f)\n"
+                        "};\n"
+                        "\n"
+                        "static float2 pointSpriteTexcoords[] = \n"
+                        "{\n"
+                        "    float2(1.0f, 1.0f),\n"
+                        "    float2(1.0f, 0.0f),\n"
+                        "    float2(0.0f, 1.0f),\n"
+                        "    float2(0.0f, 0.0f)\n"
+                        "};\n"
+                        "\n"
+                        "static float minPointSize = "
+                     << static_cast<int>(data.getCaps().minAliasedPointSize)
+                     << ".0f;\n"
+                        "static float maxPointSize = "
+                     << static_cast<int>(data.getCaps().maxAliasedPointSize) << ".0f;\n"
+                     << "\n";
+    }
+
+    shaderStream << preambleString << "\n"
+                 << "[maxvertexcount(" << maxVertexOutput << ")]\n"
+                 << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], ";
+
+    if (primitiveType == PRIMITIVE_TRIANGLE_STRIP)
+    {
+        shaderStream << "uint primitiveID : SV_PrimitiveID, ";
+    }
+
+    shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n"
+                 << "{\n"
+                 << "    GS_OUTPUT output = (GS_OUTPUT)0;\n";
+
+    if (primitiveType == PRIMITIVE_TRIANGLE_STRIP)
+    {
+        shaderStream << "    uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n";
+    }
+    else
+    {
+        shaderStream << "    uint lastVertexIndex = " << (inputSize - 1) << ";\n";
+    }
+
+    for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex)
+    {
+        shaderStream << "    copyVertex(output, input[" << vertexIndex
+                     << "], input[lastVertexIndex]);\n";
+
+        if (!pointSprites)
+        {
+            ASSERT(inputSize == maxVertexOutput);
+            shaderStream << "    outStream.Append(output);\n";
+        }
+    }
+
+    if (pointSprites)
+    {
+        shaderStream << "\n"
+                        "    float4 dx_Position = input[0].dx_Position;\n"
+                        "    float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, "
+                        "maxPointSize);\n"
+                        "    float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / "
+                        "dx_ViewCoords.y) * dx_Position.w;\n";
+
+        for (int corner = 0; corner < 4; corner++)
+        {
+            if (useViewScale)
+            {
+                shaderStream << "    \n"
+                                "    output.dx_Position = dx_Position + float4(1.0f, "
+                                "-dx_ViewScale.y, 1.0f, 1.0f)"
+                                "        * float4(pointSpriteCorners["
+                             << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
+            }
+            else
+            {
+                shaderStream << "\n"
+                                "    output.dx_Position = dx_Position + float4(pointSpriteCorners["
+                             << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
+            }
+
+            if (usesPointCoord)
+            {
+                shaderStream << "    output.gl_PointCoord = pointSpriteTexcoords[" << corner
+                             << "];\n";
+            }
+
+            shaderStream << "    outStream.Append(output);\n";
+        }
+    }
+
+    shaderStream << "    \n"
+                    "    outStream.RestartStrip();\n"
+                    "}\n";
+
+    return shaderStream.str();
+}
+
+// This method needs to match OutputHLSL::decorate
+std::string DynamicHLSL::decorateVariable(const std::string &name)
+{
+    if (name.compare(0, 3, "gl_") != 0)
+    {
+        return "_" + name;
+    }
+
+    return name;
+}
+
+std::string DynamicHLSL::generateAttributeConversionHLSL(
+    gl::VertexFormatType vertexFormatType,
+    const sh::ShaderVariable &shaderAttrib) const
+{
+    const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType);
+    std::string attribString             = "input." + decorateVariable(shaderAttrib.name);
+
+    // Matrix
+    if (IsMatrixType(shaderAttrib.type))
+    {
+        return "transpose(" + attribString + ")";
+    }
+
+    GLenum shaderComponentType = VariableComponentType(shaderAttrib.type);
+    int shaderComponentCount   = VariableComponentCount(shaderAttrib.type);
+
+    // Perform integer to float conversion (if necessary)
+    bool requiresTypeConversion =
+        (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT);
+
+    if (requiresTypeConversion)
+    {
+        // TODO: normalization for 32-bit integer formats
+        ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger);
+        return "float" + Str(shaderComponentCount) + "(" + attribString + ")";
+    }
+
+    // No conversion necessary
+    return attribString;
+}
+
+void DynamicHLSL::getPixelShaderOutputKey(const gl::ContextState &data,
+                                          const gl::ProgramState &programData,
+                                          const ProgramD3DMetadata &metadata,
+                                          std::vector<PixelShaderOutputVariable> *outPixelShaderKey)
+{
+    // Two cases when writing to gl_FragColor and using ESSL 1.0:
+    // - with a 3.0 context, the output color is copied to channel 0
+    // - with a 2.0 context, the output color is broadcast to all channels
+    bool broadcast = metadata.usesBroadcast(data);
+    const unsigned int numRenderTargets =
+        (broadcast || metadata.usesMultipleFragmentOuts() ? data.getCaps().maxDrawBuffers : 1);
+
+    if (metadata.getMajorShaderVersion() < 300)
+    {
+        for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets;
+             renderTargetIndex++)
+        {
+            PixelShaderOutputVariable outputKeyVariable;
+            outputKeyVariable.type = GL_FLOAT_VEC4;
+            outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
+            outputKeyVariable.source =
+                broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
+            outputKeyVariable.outputIndex = renderTargetIndex;
+
+            outPixelShaderKey->push_back(outputKeyVariable);
+        }
+    }
+    else
+    {
+        const auto &shaderOutputVars =
+            metadata.getFragmentShader()->getData().getActiveOutputVariables();
+
+        for (auto outputPair : programData.getOutputLocations())
+        {
+            const VariableLocation &outputLocation   = outputPair.second;
+            const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
+            const std::string &variableName = "out_" + outputLocation.name;
+            const std::string &elementString =
+                (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
+
+            ASSERT(outputVariable.staticUse);
+
+            PixelShaderOutputVariable outputKeyVariable;
+            outputKeyVariable.type        = outputVariable.type;
+            outputKeyVariable.name        = variableName + elementString;
+            outputKeyVariable.source      = variableName + ArrayString(outputLocation.element);
+            outputKeyVariable.outputIndex = outputPair.first;
+
+            outPixelShaderKey->push_back(outputKeyVariable);
+        }
+    }
+}
+
+// BuiltinVarying Implementation.
+BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false)
+{
+}
+
+std::string BuiltinVarying::str() const
+{
+    return (systemValue ? semantic : (semantic + Str(index)));
+}
+
+void BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
+{
+    enabled     = true;
+    semantic    = systemValueSemantic;
+    systemValue = true;
+}
+
+void BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
+{
+    enabled  = true;
+    semantic = semanticVal;
+    index    = indexVal;
+}
+
+// BuiltinVaryingsD3D Implementation.
+BuiltinVaryingsD3D::BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata,
+                                       const VaryingPacking &packing)
+{
+    updateBuiltins(SHADER_VERTEX, metadata, packing);
+    updateBuiltins(SHADER_PIXEL, metadata, packing);
+    if (metadata.getRendererMajorShaderModel() >= 4)
+    {
+        updateBuiltins(SHADER_GEOMETRY, metadata, packing);
+    }
+}
+
+void BuiltinVaryingsD3D::updateBuiltins(ShaderType shaderType,
+                                        const ProgramD3DMetadata &metadata,
+                                        const VaryingPacking &packing)
+{
+    const std::string &userSemantic = GetVaryingSemantic(metadata.getRendererMajorShaderModel(),
+                                                         metadata.usesSystemValuePointSize());
+
+    unsigned int reservedSemanticIndex = packing.getMaxSemanticIndex();
+
+    BuiltinInfo *builtins = &mBuiltinInfo[shaderType];
+
+    if (metadata.getRendererMajorShaderModel() >= 4)
+    {
+        builtins->dxPosition.enableSystem("SV_Position");
+    }
+    else if (shaderType == SHADER_PIXEL)
+    {
+        builtins->dxPosition.enableSystem("VPOS");
+    }
+    else
+    {
+        builtins->dxPosition.enableSystem("POSITION");
+    }
+
+    if (metadata.usesTransformFeedbackGLPosition())
+    {
+        builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
+    }
+
+    if (metadata.usesFragCoord())
+    {
+        builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
+    }
+
+    if (shaderType == SHADER_VERTEX ? metadata.addsPointCoordToVertexShader()
+                                    : metadata.usesPointCoord())
+    {
+        // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+        // In D3D11 we manually compute gl_PointCoord in the GS.
+        if (metadata.getRendererMajorShaderModel() >= 4)
+        {
+            builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
+        }
+        else
+        {
+            builtins->glPointCoord.enable("TEXCOORD", 0);
+        }
+    }
+
+    // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
+    if (metadata.usesSystemValuePointSize() &&
+        (shaderType != SHADER_PIXEL || metadata.getRendererMajorShaderModel() >= 4))
+    {
+        builtins->glPointSize.enableSystem("PSIZE");
+    }
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
new file mode 100644
index 0000000..0972a62
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -0,0 +1,160 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DynamicHLSL.h: Interface for link and run-time HLSL generation
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
+#define LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
+
+#include <map>
+#include <vector>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace sh
+{
+struct Attribute;
+struct ShaderVariable;
+}
+
+namespace gl
+{
+class InfoLog;
+struct VariableLocation;
+class VaryingPacking;
+struct VertexAttribute;
+}
+
+namespace rx
+{
+class ProgramD3DMetadata;
+class ShaderD3D;
+
+struct PixelShaderOutputVariable
+{
+    PixelShaderOutputVariable() {}
+    PixelShaderOutputVariable(GLenum typeIn,
+                              const std::string &nameIn,
+                              const std::string &sourceIn,
+                              size_t outputIndexIn)
+        : type(typeIn), name(nameIn), source(sourceIn), outputIndex(outputIndexIn)
+    {
+    }
+
+    GLenum type = GL_NONE;
+    std::string name;
+    std::string source;
+    size_t outputIndex = 0;
+};
+
+struct BuiltinVarying final : private angle::NonCopyable
+{
+    BuiltinVarying();
+
+    std::string str() const;
+    void enableSystem(const std::string &systemValueSemantic);
+    void enable(const std::string &semanticVal, unsigned int indexVal);
+
+    bool enabled;
+    std::string semantic;
+    unsigned int index;
+    bool systemValue;
+};
+
+struct BuiltinInfo
+{
+    BuiltinVarying dxPosition;
+    BuiltinVarying glPosition;
+    BuiltinVarying glFragCoord;
+    BuiltinVarying glPointCoord;
+    BuiltinVarying glPointSize;
+};
+
+inline std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
+{
+    // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+    // In D3D11 we manually compute gl_PointCoord in the GS.
+    return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
+}
+
+class BuiltinVaryingsD3D
+{
+  public:
+    BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata, const gl::VaryingPacking &packing);
+
+    bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; }
+
+    const BuiltinInfo &operator[](ShaderType shaderType) const { return mBuiltinInfo[shaderType]; }
+    BuiltinInfo &operator[](ShaderType shaderType) { return mBuiltinInfo[shaderType]; }
+
+  private:
+    void updateBuiltins(ShaderType shaderType,
+                        const ProgramD3DMetadata &metadata,
+                        const gl::VaryingPacking &packing);
+
+    std::array<BuiltinInfo, SHADER_TYPE_MAX> mBuiltinInfo;
+};
+
+class DynamicHLSL : angle::NonCopyable
+{
+  public:
+    explicit DynamicHLSL(RendererD3D *const renderer);
+
+    std::string generateVertexShaderForInputLayout(
+        const std::string &sourceShader,
+        const gl::InputLayout &inputLayout,
+        const std::vector<sh::Attribute> &shaderAttributes) const;
+    std::string generatePixelShaderForOutputSignature(
+        const std::string &sourceShader,
+        const std::vector<PixelShaderOutputVariable> &outputVariables,
+        bool usesFragDepth,
+        const std::vector<GLenum> &outputLayout) const;
+    void generateShaderLinkHLSL(const gl::ContextState &data,
+                                const gl::ProgramState &programData,
+                                const ProgramD3DMetadata &programMetadata,
+                                const gl::VaryingPacking &varyingPacking,
+                                const BuiltinVaryingsD3D &builtinsD3D,
+                                std::string *pixelHLSL,
+                                std::string *vertexHLSL) const;
+    std::string generateComputeShaderLinkHLSL(const gl::ProgramState &programData) const;
+
+    std::string generateGeometryShaderPreamble(const gl::VaryingPacking &varyingPacking,
+                                               const BuiltinVaryingsD3D &builtinsD3D) const;
+
+    std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
+                                           const gl::ContextState &data,
+                                           const gl::ProgramState &programData,
+                                           const bool useViewScale,
+                                           const std::string &preambleString) const;
+
+    void getPixelShaderOutputKey(const gl::ContextState &data,
+                                 const gl::ProgramState &programData,
+                                 const ProgramD3DMetadata &metadata,
+                                 std::vector<PixelShaderOutputVariable> *outPixelShaderKey);
+
+  private:
+    RendererD3D *const mRenderer;
+
+    void generateVaryingLinkHLSL(const gl::VaryingPacking &varyingPacking,
+                                 const BuiltinInfo &builtins,
+                                 bool programUsesPointSize,
+                                 std::stringstream &hlslStream) const;
+
+    // Prepend an underscore
+    static std::string decorateVariable(const std::string &name);
+
+    std::string generateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType,
+                                                const sh::ShaderVariable &shaderAttrib) const;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
new file mode 100644
index 0000000..caee47d7e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
@@ -0,0 +1,86 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLImageD3D.cpp: Implements the rx::EGLImageD3D class, the D3D implementation of EGL images
+
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+EGLImageD3D::EGLImageD3D(const egl::ImageState &state,
+                         EGLenum target,
+                         const egl::AttributeMap &attribs,
+                         RendererD3D *renderer)
+    : ImageImpl(state), mRenderer(renderer), mRenderTarget(nullptr)
+{
+    ASSERT(renderer != nullptr);
+}
+
+EGLImageD3D::~EGLImageD3D()
+{
+    SafeDelete(mRenderTarget);
+}
+
+egl::Error EGLImageD3D::initialize()
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+gl::Error EGLImageD3D::orphan(egl::ImageSibling *sibling)
+{
+    if (sibling == mState.source.get())
+    {
+        ANGLE_TRY(copyToLocalRendertarget());
+    }
+
+    return gl::NoError();
+}
+
+gl::Error EGLImageD3D::getRenderTarget(RenderTargetD3D **outRT) const
+{
+    if (mState.source.get())
+    {
+        ASSERT(!mRenderTarget);
+        FramebufferAttachmentRenderTarget *rt = nullptr;
+        ANGLE_TRY(mState.source->getAttachmentRenderTarget(GL_NONE, mState.imageIndex, &rt));
+        *outRT = static_cast<RenderTargetD3D *>(rt);
+        return gl::NoError();
+    }
+    else
+    {
+        ASSERT(mRenderTarget);
+        *outRT = mRenderTarget;
+        return gl::NoError();
+    }
+}
+
+gl::Error EGLImageD3D::copyToLocalRendertarget()
+{
+    ASSERT(mState.source.get() != nullptr);
+    ASSERT(mRenderTarget == nullptr);
+
+    RenderTargetD3D *curRenderTarget = nullptr;
+    ANGLE_TRY(getRenderTarget(&curRenderTarget));
+
+    // This only currently applies do D3D11, where it invalidates FBOs with this Image attached.
+    curRenderTarget->signalDirty();
+
+    return mRenderer->createRenderTargetCopy(curRenderTarget, &mRenderTarget);
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h
new file mode 100644
index 0000000..98e78a3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLImageD3D.h: Defines the rx::EGLImageD3D class, the D3D implementation of EGL images
+
+#ifndef LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
+#define LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace egl
+{
+class AttributeMap;
+}
+
+namespace rx
+{
+class FramebufferAttachmentObjectImpl;
+class TextureD3D;
+class RenderbufferD3D;
+class RendererD3D;
+class RenderTargetD3D;
+
+class EGLImageD3D final : public ImageImpl
+{
+  public:
+    EGLImageD3D(const egl::ImageState &state,
+                EGLenum target,
+                const egl::AttributeMap &attribs,
+                RendererD3D *renderer);
+    ~EGLImageD3D() override;
+
+    egl::Error initialize() override;
+
+    gl::Error orphan(egl::ImageSibling *sibling) override;
+
+    gl::Error getRenderTarget(RenderTargetD3D **outRT) const;
+
+  private:
+    gl::Error copyToLocalRendertarget();
+
+    RendererD3D *mRenderer;
+    RenderTargetD3D *mRenderTarget;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
new file mode 100644
index 0000000..86653f6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -0,0 +1,363 @@
+//
+// 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.
+//
+
+// FramebufferD3D.cpp: Implements the DefaultAttachmentD3D and FramebufferD3D classes.
+
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+
+#include "common/bitset_utils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+
+namespace rx
+{
+
+namespace
+{
+
+ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
+{
+    ClearParameters clearParams;
+    memset(&clearParams, 0, sizeof(ClearParameters));
+
+    const auto &blendState = state.getBlendState();
+
+    for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+    {
+        clearParams.clearColor[i] = false;
+    }
+    clearParams.colorF           = state.getColorClearValue();
+    clearParams.colorType        = GL_FLOAT;
+    clearParams.colorMaskRed     = blendState.colorMaskRed;
+    clearParams.colorMaskGreen   = blendState.colorMaskGreen;
+    clearParams.colorMaskBlue    = blendState.colorMaskBlue;
+    clearParams.colorMaskAlpha   = blendState.colorMaskAlpha;
+    clearParams.clearDepth       = false;
+    clearParams.depthValue       = state.getDepthClearValue();
+    clearParams.clearStencil     = false;
+    clearParams.stencilValue     = state.getStencilClearValue();
+    clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
+    clearParams.scissorEnabled   = state.isScissorTestEnabled();
+    clearParams.scissor          = state.getScissor();
+
+    const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
+    if (mask & GL_COLOR_BUFFER_BIT)
+    {
+        if (framebufferObject->hasEnabledDrawBuffer())
+        {
+            for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+            {
+                clearParams.clearColor[i] = true;
+            }
+        }
+    }
+
+    if (mask & GL_DEPTH_BUFFER_BIT)
+    {
+        if (state.getDepthStencilState().depthMask &&
+            framebufferObject->getDepthbuffer() != nullptr)
+        {
+            clearParams.clearDepth = true;
+        }
+    }
+
+    if (mask & GL_STENCIL_BUFFER_BIT)
+    {
+        if (framebufferObject->getStencilbuffer() != nullptr &&
+            framebufferObject->getStencilbuffer()->getStencilSize() > 0)
+        {
+            clearParams.clearStencil = true;
+        }
+    }
+
+    return clearParams;
+}
+}
+
+FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer)
+    : FramebufferImpl(data), mRenderer(renderer)
+{
+}
+
+FramebufferD3D::~FramebufferD3D()
+{
+}
+
+gl::Error FramebufferD3D::clear(ContextImpl *context, GLbitfield mask)
+{
+    ClearParameters clearParams = GetClearParameters(context->getGLState(), mask);
+    return clearImpl(context, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferfv(ContextImpl *context,
+                                        GLenum buffer,
+                                        GLint drawbuffer,
+                                        const GLfloat *values)
+{
+    // glClearBufferfv can be called to clear the color buffer or depth buffer
+    ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
+
+    if (buffer == GL_COLOR)
+    {
+        for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+        {
+            clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+        }
+        clearParams.colorF    = gl::ColorF(values[0], values[1], values[2], values[3]);
+        clearParams.colorType = GL_FLOAT;
+    }
+
+    if (buffer == GL_DEPTH)
+    {
+        clearParams.clearDepth = true;
+        clearParams.depthValue = values[0];
+    }
+
+    return clearImpl(context, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferuiv(ContextImpl *context,
+                                         GLenum buffer,
+                                         GLint drawbuffer,
+                                         const GLuint *values)
+{
+    // glClearBufferuiv can only be called to clear a color buffer
+    ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
+    for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+    {
+        clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+    }
+    clearParams.colorUI   = gl::ColorUI(values[0], values[1], values[2], values[3]);
+    clearParams.colorType = GL_UNSIGNED_INT;
+
+    return clearImpl(context, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferiv(ContextImpl *context,
+                                        GLenum buffer,
+                                        GLint drawbuffer,
+                                        const GLint *values)
+{
+    // glClearBufferiv can be called to clear the color buffer or stencil buffer
+    ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
+
+    if (buffer == GL_COLOR)
+    {
+        for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+        {
+            clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+        }
+        clearParams.colorI    = gl::ColorI(values[0], values[1], values[2], values[3]);
+        clearParams.colorType = GL_INT;
+    }
+
+    if (buffer == GL_STENCIL)
+    {
+        clearParams.clearStencil = true;
+        clearParams.stencilValue = values[1];
+    }
+
+    return clearImpl(context, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferfi(ContextImpl *context,
+                                        GLenum buffer,
+                                        GLint drawbuffer,
+                                        GLfloat depth,
+                                        GLint stencil)
+{
+    // glClearBufferfi can only be called to clear a depth stencil buffer
+    ClearParameters clearParams   = GetClearParameters(context->getGLState(), 0);
+    clearParams.clearDepth        = true;
+    clearParams.depthValue        = depth;
+    clearParams.clearStencil      = true;
+    clearParams.stencilValue      = stencil;
+
+    return clearImpl(context, clearParams);
+}
+
+GLenum FramebufferD3D::getImplementationColorReadFormat() const
+{
+    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+
+    if (readAttachment == nullptr)
+    {
+        return GL_NONE;
+    }
+
+    RenderTargetD3D *attachmentRenderTarget = nullptr;
+    gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
+    if (error.isError())
+    {
+        return GL_NONE;
+    }
+
+    GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
+    const gl::InternalFormat &implementationFormatInfo =
+        gl::GetSizedInternalFormatInfo(implementationFormat);
+
+    return implementationFormatInfo.getReadPixelsFormat();
+}
+
+GLenum FramebufferD3D::getImplementationColorReadType() const
+{
+    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+
+    if (readAttachment == nullptr)
+    {
+        return GL_NONE;
+    }
+
+    RenderTargetD3D *attachmentRenderTarget = nullptr;
+    gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
+    if (error.isError())
+    {
+        return GL_NONE;
+    }
+
+    GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
+    const gl::InternalFormat &implementationFormatInfo =
+        gl::GetSizedInternalFormatInfo(implementationFormat);
+
+    return implementationFormatInfo.getReadPixelsType();
+}
+
+gl::Error FramebufferD3D::readPixels(ContextImpl *context,
+                                     const gl::Rectangle &area,
+                                     GLenum format,
+                                     GLenum type,
+                                     void *pixels) const
+{
+    const gl::PixelPackState &packState = context->getGLState().getPackState();
+
+    const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
+
+    GLuint outputPitch = 0;
+    ANGLE_TRY_RESULT(
+        sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength),
+        outputPitch);
+    GLuint outputSkipBytes = 0;
+    ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false),
+                     outputSkipBytes);
+
+    return readPixelsImpl(area, format, type, outputPitch, packState,
+                          reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
+}
+
+gl::Error FramebufferD3D::blit(ContextImpl *context,
+                               const gl::Rectangle &sourceArea,
+                               const gl::Rectangle &destArea,
+                               GLbitfield mask,
+                               GLenum filter)
+{
+    const auto &glState                      = context->getGLState();
+    const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
+    const gl::Rectangle *scissor = glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
+    ANGLE_TRY(blitImpl(sourceArea, destArea, scissor, (mask & GL_COLOR_BUFFER_BIT) != 0,
+                       (mask & GL_DEPTH_BUFFER_BIT) != 0, (mask & GL_STENCIL_BUFFER_BIT) != 0,
+                       filter, sourceFramebuffer));
+
+    return gl::NoError();
+}
+
+bool FramebufferD3D::checkStatus() const
+{
+    // if we have both a depth and stencil buffer, they must refer to the same object
+    // since we only support packed_depth_stencil and not separate depth and stencil
+    if (mState.getDepthAttachment() != nullptr && mState.getStencilAttachment() != nullptr &&
+        mState.getDepthStencilAttachment() == nullptr)
+    {
+        return false;
+    }
+
+    // D3D11 does not allow for overlapping RenderTargetViews
+    if (!mState.colorAttachmentsAreUniqueImages())
+    {
+        return false;
+    }
+
+    // D3D requires all render targets to have the same dimensions.
+    if (!mState.attachmentsHaveSameDimensions())
+    {
+        return false;
+    }
+
+    return true;
+}
+
+void FramebufferD3D::syncState(ContextImpl *contextImpl,
+                               const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+    bool invalidateColorAttachmentCache = false;
+
+    if (!mColorAttachmentsForRender.valid())
+    {
+        invalidateColorAttachmentCache = true;
+    }
+
+    for (auto dirtyBit : dirtyBits)
+    {
+        if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
+             dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
+            dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
+        {
+            invalidateColorAttachmentCache = true;
+        }
+    }
+
+    if (!invalidateColorAttachmentCache)
+    {
+        return;
+    }
+
+    // Does not actually free memory
+    gl::AttachmentList colorAttachmentsForRender;
+
+    const auto &colorAttachments = mState.getColorAttachments();
+    const auto &drawBufferStates = mState.getDrawBufferStates();
+    const auto &workarounds      = mRenderer->getWorkarounds();
+
+    for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
+    {
+        GLenum drawBufferState                           = drawBufferStates[attachmentIndex];
+        const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
+
+        if (colorAttachment.isAttached() && drawBufferState != GL_NONE)
+        {
+            ASSERT(drawBufferState == GL_BACK ||
+                   drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
+            colorAttachmentsForRender.push_back(&colorAttachment);
+        }
+        else if (!workarounds.mrtPerfWorkaround)
+        {
+            colorAttachmentsForRender.push_back(nullptr);
+        }
+    }
+
+    mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
+}
+
+const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const
+{
+    ASSERT(mColorAttachmentsForRender.valid());
+    return mColorAttachmentsForRender.value();
+}
+
+gl::Error FramebufferD3D::getSamplePosition(size_t index, GLfloat *xy) const
+{
+    return gl::InternalError() << "getSamplePosition is unimplemented.";
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
new file mode 100644
index 0000000..903b3fe
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -0,0 +1,129 @@
+//
+// 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.
+//
+
+// FramebufferD3D.h: Defines the DefaultAttachmentD3D and FramebufferD3D classes.
+
+#ifndef LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
+#define LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
+
+#include <cstdint>
+#include <vector>
+
+#include "common/Color.h"
+#include "common/Optional.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+struct PixelPackState;
+
+typedef std::vector<const FramebufferAttachment *> AttachmentList;
+}
+
+namespace rx
+{
+class RendererD3D;
+class RenderTargetD3D;
+
+struct ClearParameters
+{
+    bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
+    gl::ColorF colorF;
+    gl::ColorI colorI;
+    gl::ColorUI colorUI;
+    GLenum colorType;
+    bool colorMaskRed;
+    bool colorMaskGreen;
+    bool colorMaskBlue;
+    bool colorMaskAlpha;
+
+    bool clearDepth;
+    float depthValue;
+
+    bool clearStencil;
+    GLint stencilValue;
+    GLuint stencilWriteMask;
+
+    bool scissorEnabled;
+    gl::Rectangle scissor;
+};
+
+class FramebufferD3D : public FramebufferImpl
+{
+  public:
+    FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer);
+    virtual ~FramebufferD3D();
+
+    gl::Error clear(ContextImpl *impl, GLbitfield mask) override;
+    gl::Error clearBufferfv(ContextImpl *impl,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLfloat *values) override;
+    gl::Error clearBufferuiv(ContextImpl *impl,
+                             GLenum buffer,
+                             GLint drawbuffer,
+                             const GLuint *values) override;
+    gl::Error clearBufferiv(ContextImpl *impl,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLint *values) override;
+    gl::Error clearBufferfi(ContextImpl *impl,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            GLfloat depth,
+                            GLint stencil) override;
+
+    GLenum getImplementationColorReadFormat() const override;
+    GLenum getImplementationColorReadType() const override;
+    gl::Error readPixels(ContextImpl *impl,
+                         const gl::Rectangle &area,
+                         GLenum format,
+                         GLenum type,
+                         void *pixels) const override;
+
+    gl::Error blit(ContextImpl *impl,
+                   const gl::Rectangle &sourceArea,
+                   const gl::Rectangle &destArea,
+                   GLbitfield mask,
+                   GLenum filter) override;
+
+    bool checkStatus() const override;
+
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
+
+    const gl::AttachmentList &getColorAttachmentsForRender() const;
+
+    gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
+
+  private:
+    virtual gl::Error clearImpl(ContextImpl *impl, const ClearParameters &clearParams) = 0;
+
+    virtual gl::Error readPixelsImpl(const gl::Rectangle &area,
+                                     GLenum format,
+                                     GLenum type,
+                                     size_t outputPitch,
+                                     const gl::PixelPackState &pack,
+                                     uint8_t *pixels) const = 0;
+
+    virtual gl::Error blitImpl(const gl::Rectangle &sourceArea,
+                               const gl::Rectangle &destArea,
+                               const gl::Rectangle *scissor,
+                               bool blitRenderTarget,
+                               bool blitDepth,
+                               bool blitStencil,
+                               GLenum filter,
+                               const gl::Framebuffer *sourceFramebuffer) = 0;
+
+    virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0;
+
+    RendererD3D *mRenderer;
+    Optional<gl::AttachmentList> mColorAttachmentsForRender;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
new file mode 100644
index 0000000..3b4d638
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
@@ -0,0 +1,321 @@
+//
+// 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.
+//
+
+#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/features.h"
+#include "libANGLE/histogram_macros.h"
+#include "third_party/trace_event/trace_event.h"
+
+#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+namespace
+{
+#ifdef CREATE_COMPILER_FLAG_INFO
+    #undef CREATE_COMPILER_FLAG_INFO
+#endif
+
+#define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag }
+
+struct CompilerFlagInfo
+{
+    UINT mFlag;
+    const char *mName;
+};
+
+CompilerFlagInfo CompilerFlagInfos[] =
+{
+    // NOTE: The data below is copied from d3dcompiler.h
+    // If something changes there it should be changed here as well
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_DEBUG),                          // (1 << 0)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_VALIDATION),                // (1 << 1)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_OPTIMIZATION),              // (1 << 2)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_ROW_MAJOR),          // (1 << 3)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR),       // (1 << 4)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PARTIAL_PRECISION),              // (1 << 5)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT),       // (1 << 6)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT),       // (1 << 7)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_NO_PRESHADER),                   // (1 << 8)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_AVOID_FLOW_CONTROL),             // (1 << 9)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PREFER_FLOW_CONTROL),            // (1 << 10)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_STRICTNESS),              // (1 << 11)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY), // (1 << 12)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_IEEE_STRICTNESS),                // (1 << 13)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL0),            // (1 << 14)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL1),            // 0
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL2),            // ((1 << 14) | (1 << 15))
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL3),            // (1 << 15)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED16),                     // (1 << 16)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED17),                     // (1 << 17)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_WARNINGS_ARE_ERRORS)             // (1 << 18)
+};
+
+#undef CREATE_COMPILER_FLAG_INFO
+
+bool IsCompilerFlagSet(UINT mask, UINT flag)
+{
+    bool isFlagSet = IsMaskFlagSet(mask, flag);
+
+    switch(flag)
+    {
+      case D3DCOMPILE_OPTIMIZATION_LEVEL0:
+        return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL3));
+
+      case D3DCOMPILE_OPTIMIZATION_LEVEL1:
+        return (mask & D3DCOMPILE_OPTIMIZATION_LEVEL2) == UINT(0);
+
+      case D3DCOMPILE_OPTIMIZATION_LEVEL3:
+        return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL0));
+
+      default:
+        return isFlagSet;
+    }
+}
+}  // anonymous namespace
+#endif  // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+
+namespace rx
+{
+
+CompileConfig::CompileConfig()
+    : flags(0),
+      name()
+{
+}
+
+CompileConfig::CompileConfig(UINT flags, const std::string &name)
+    : flags(flags),
+      name(name)
+{
+}
+
+HLSLCompiler::HLSLCompiler()
+    : mInitialized(false),
+      mD3DCompilerModule(nullptr),
+      mD3DCompileFunc(nullptr),
+      mD3DDisassembleFunc(nullptr)
+{
+}
+
+HLSLCompiler::~HLSLCompiler()
+{
+    release();
+}
+
+gl::Error HLSLCompiler::ensureInitialized()
+{
+    if (mInitialized)
+    {
+        return gl::NoError();
+    }
+
+    TRACE_EVENT0("gpu.angle", "HLSLCompiler::initialize");
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
+    // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
+    static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
+
+    for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
+    {
+        if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule))
+        {
+            break;
+        }
+    }
+#endif  // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
+
+    if (!mD3DCompilerModule)
+    {
+        // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
+        mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
+    }
+
+    if (!mD3DCompilerModule)
+    {
+        ERR() << "D3D compiler module not found.";
+        return gl::Error(GL_OUT_OF_MEMORY, "D3D compiler module not found.");
+    }
+
+    mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
+    ASSERT(mD3DCompileFunc);
+
+    mD3DDisassembleFunc = reinterpret_cast<pD3DDisassemble>(GetProcAddress(mD3DCompilerModule, "D3DDisassemble"));
+    ASSERT(mD3DDisassembleFunc);
+
+#else
+    // D3D Shader compiler is linked already into this module, so the export
+    // can be directly assigned.
+    mD3DCompilerModule = nullptr;
+    mD3DCompileFunc = reinterpret_cast<pD3DCompile>(D3DCompile);
+    mD3DDisassembleFunc = reinterpret_cast<pD3DDisassemble>(D3DDisassemble);
+#endif
+
+    if (mD3DCompileFunc == nullptr)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Error finding D3DCompile entry point.");
+    }
+
+    mInitialized = true;
+    return gl::NoError();
+}
+
+void HLSLCompiler::release()
+{
+    if (mInitialized)
+    {
+        FreeLibrary(mD3DCompilerModule);
+        mD3DCompilerModule = nullptr;
+        mD3DCompileFunc = nullptr;
+        mD3DDisassembleFunc = nullptr;
+        mInitialized = false;
+    }
+}
+
+gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
+                                        const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros,
+                                        ID3DBlob **outCompiledBlob, std::string *outDebugInfo)
+{
+    ASSERT(mInitialized);
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    ASSERT(mD3DCompilerModule);
+#endif
+    ASSERT(mD3DCompileFunc);
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    if (gl::DebugAnnotationsActive())
+    {
+        std::string sourcePath = getTempPath();
+        std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str());
+        writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
+    }
+#endif
+
+    const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : nullptr;
+
+    for (size_t i = 0; i < configs.size(); ++i)
+    {
+        ID3DBlob *errorMessage = nullptr;
+        ID3DBlob *binary = nullptr;
+        HRESULT result         = S_OK;
+
+        {
+            TRACE_EVENT0("gpu.angle", "D3DCompile");
+            SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3DCompileMS");
+            result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, nullptr,
+                                     "main", profile.c_str(), configs[i].flags, 0, &binary,
+                                     &errorMessage);
+        }
+
+        if (errorMessage)
+        {
+            std::string message = reinterpret_cast<const char*>(errorMessage->GetBufferPointer());
+            SafeRelease(errorMessage);
+
+            infoLog.appendSanitized(message.c_str());
+            WARN() << std::endl << hlsl;
+            WARN() << std::endl << message;
+
+            if ((message.find("error X3531:") != std::string::npos ||  // "can't unroll loops marked with loop attribute"
+                 message.find("error X4014:") != std::string::npos) && // "cannot have gradient operations inside loops with divergent flow control",
+                                                                       // even though it is counter-intuitive to disable unrolling for this error,
+                                                                       // some very long shaders have trouble deciding which loops to unroll and
+                                                                       // turning off forced unrolls allows them to compile properly.
+                macros != nullptr)
+            {
+                macros = nullptr;   // Disable [loop] and [flatten]
+
+                // Retry without changing compiler flags
+                i--;
+                continue;
+            }
+        }
+
+        if (SUCCEEDED(result))
+        {
+            *outCompiledBlob = binary;
+
+            (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n";
+
+#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+            (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n";
+            (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n";
+            for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx)
+            {
+                if (IsCompilerFlagSet(configs[i].flags, CompilerFlagInfos[fIx].mFlag))
+                {
+                    (*outDebugInfo) += std::string("// ") + CompilerFlagInfos[fIx].mName + "\n";
+                }
+            }
+
+            (*outDebugInfo) += "// Macros:\n";
+            if (macros == nullptr)
+            {
+                (*outDebugInfo) += "// - : -\n";
+            }
+            else
+            {
+                for (const D3D_SHADER_MACRO *mIt = macros; mIt->Name != nullptr; ++mIt)
+                {
+                    (*outDebugInfo) += std::string("// ") + mIt->Name + " : " + mIt->Definition + "\n";
+                }
+            }
+
+            std::string disassembly;
+            ANGLE_TRY(disassembleBinary(binary, &disassembly));
+            (*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n";
+#endif  // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+            return gl::NoError();
+        }
+
+        if (result == E_OUTOFMEMORY)
+        {
+            *outCompiledBlob = nullptr;
+            return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
+        }
+
+        infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags. ("
+                << profile << ")";
+
+        if (i + 1 < configs.size())
+        {
+            infoLog << " Retrying with " << configs[i + 1].name;
+        }
+    }
+
+    // None of the configurations succeeded in compiling this shader but the compiler is still intact
+    *outCompiledBlob = nullptr;
+    return gl::NoError();
+}
+
+gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut)
+{
+    ANGLE_TRY(ensureInitialized());
+
+    // Retrieve disassembly
+    UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING;
+    ID3DBlob *disassembly = nullptr;
+    pD3DDisassemble disassembleFunc = reinterpret_cast<pD3DDisassemble>(mD3DDisassembleFunc);
+    LPCVOID buffer = shaderBinary->GetBufferPointer();
+    SIZE_T bufSize = shaderBinary->GetBufferSize();
+    HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly);
+
+    if (SUCCEEDED(result))
+    {
+        *disassemblyOut = std::string(reinterpret_cast<const char*>(disassembly->GetBufferPointer()));
+    }
+    else
+    {
+        *disassemblyOut = "";
+    }
+
+    SafeRelease(disassembly);
+
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h b/src/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h
new file mode 100644
index 0000000..c8f9eac
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2016 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.
+//
+// HLSLCompiler: Wrapper for the D3DCompiler DLL.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
+#define LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+#include "common/platform.h"
+
+#include <vector>
+#include <string>
+
+namespace gl
+{
+class InfoLog;
+}
+
+namespace rx
+{
+
+struct CompileConfig
+{
+    UINT flags;
+    std::string name;
+
+    CompileConfig();
+    CompileConfig(UINT flags, const std::string &name);
+};
+
+class HLSLCompiler : angle::NonCopyable
+{
+  public:
+    HLSLCompiler();
+    ~HLSLCompiler();
+
+    void release();
+
+    // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob
+    // even if no GL errors are returned.
+    gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
+                              const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros,
+                              ID3DBlob **outCompiledBlob, std::string *outDebugInfo);
+
+    gl::Error disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut);
+    gl::Error ensureInitialized();
+
+  private:
+
+    bool mInitialized;
+    HMODULE mD3DCompilerModule;
+    pD3DCompile mD3DCompileFunc;
+    pD3DDisassemble mD3DDisassembleFunc;
+};
+
+}
+
+#endif  // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
new file mode 100644
index 0000000..ead5db6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image.h: Implements the rx::Image class, an abstract base class for the
+// renderer-specific classes which will define the interface to the underlying
+// surfaces or resources.
+
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace rx
+{
+
+ImageD3D::ImageD3D()
+    : mWidth(0),
+      mHeight(0),
+      mDepth(0),
+      mInternalFormat(GL_NONE),
+      mRenderable(false),
+      mTarget(GL_NONE),
+      mDirty(false)
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.h
new file mode 100644
index 0000000..ff60362
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.h
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageD3D.h: Defines the rx::ImageD3D class, an abstract base class for the
+// renderer-specific classes which will define the interface to the underlying
+// surfaces or resources.
+
+#ifndef LIBANGLE_RENDERER_D3D_IMAGED3D_H_
+#define LIBANGLE_RENDERER_D3D_IMAGED3D_H_
+
+#include "common/debug.h"
+
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Framebuffer;
+struct ImageIndex;
+struct Box;
+struct Extents;
+struct Offset;
+struct Rectangle;
+struct PixelUnpackState;
+}
+
+namespace rx
+{
+class TextureStorage;
+class RendererD3D;
+class RenderTargetD3D;
+
+class ImageD3D : angle::NonCopyable
+{
+  public:
+    ImageD3D();
+    virtual ~ImageD3D() {};
+
+    GLsizei getWidth() const { return mWidth; }
+    GLsizei getHeight() const { return mHeight; }
+    GLsizei getDepth() const { return mDepth; }
+    GLenum getInternalFormat() const { return mInternalFormat; }
+    GLenum getTarget() const { return mTarget; }
+    bool isRenderableFormat() const { return mRenderable; }
+
+    void markDirty() { mDirty = true; }
+    void markClean() { mDirty = false; }
+    virtual bool isDirty() const = 0;
+
+    virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0;
+
+    virtual gl::Error loadData(const gl::Box &area,
+                               const gl::PixelUnpackState &unpack,
+                               GLenum type,
+                               const void *input,
+                               bool applySkipImages) = 0;
+    virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0;
+
+    virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level)
+    {
+        return gl::NoError();
+    };
+    virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level)
+    {
+        return gl::NoError();
+    };
+    virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level)
+    {
+        return gl::NoError();
+    };
+    virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level)
+    {
+        return gl::NoError();
+    };
+    virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
+
+    virtual gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex,
+                                         TextureStorage *source) = 0;
+    virtual gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+                                          const gl::Rectangle &sourceArea,
+                                          const gl::Framebuffer *source) = 0;
+
+  protected:
+    GLsizei mWidth;
+    GLsizei mHeight;
+    GLsizei mDepth;
+    GLenum mInternalFormat;
+    bool mRenderable;
+    GLenum mTarget;
+
+    bool mDirty;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_IMAGED3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp
new file mode 100644
index 0000000..e870975
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp
@@ -0,0 +1,196 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface
+// class with derivations, classes that perform graphics API agnostic index buffer operations.
+
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+unsigned int IndexBuffer::mNextSerial = 1;
+
+IndexBuffer::IndexBuffer()
+{
+    updateSerial();
+}
+
+IndexBuffer::~IndexBuffer()
+{
+}
+
+unsigned int IndexBuffer::getSerial() const
+{
+    return mSerial;
+}
+
+void IndexBuffer::updateSerial()
+{
+    mSerial = mNextSerial++;
+}
+
+
+IndexBufferInterface::IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
+{
+    mIndexBuffer = factory->createIndexBuffer();
+
+    mDynamic = dynamic;
+    mWritePosition = 0;
+}
+
+IndexBufferInterface::~IndexBufferInterface()
+{
+    if (mIndexBuffer)
+    {
+        delete mIndexBuffer;
+    }
+}
+
+GLenum IndexBufferInterface::getIndexType() const
+{
+    return mIndexBuffer->getIndexType();
+}
+
+unsigned int IndexBufferInterface::getBufferSize() const
+{
+    return mIndexBuffer->getBufferSize();
+}
+
+unsigned int IndexBufferInterface::getSerial() const
+{
+    return mIndexBuffer->getSerial();
+}
+
+gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMemory, unsigned int *streamOffset)
+{
+    // Protect against integer overflow
+    if (mWritePosition + size < mWritePosition)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow.");
+    }
+
+    gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory);
+    if (error.isError())
+    {
+        if (outMappedMemory)
+        {
+            *outMappedMemory = nullptr;
+        }
+        return error;
+    }
+
+    if (streamOffset)
+    {
+        *streamOffset = mWritePosition;
+    }
+
+    mWritePosition += size;
+    return gl::NoError();
+}
+
+gl::Error IndexBufferInterface::unmapBuffer()
+{
+    return mIndexBuffer->unmapBuffer();
+}
+
+IndexBuffer * IndexBufferInterface::getIndexBuffer() const
+{
+    return mIndexBuffer;
+}
+
+unsigned int IndexBufferInterface::getWritePosition() const
+{
+    return mWritePosition;
+}
+
+void IndexBufferInterface::setWritePosition(unsigned int writePosition)
+{
+    mWritePosition = writePosition;
+}
+
+gl::Error IndexBufferInterface::discard()
+{
+    return mIndexBuffer->discard();
+}
+
+gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
+{
+    if (mIndexBuffer->getBufferSize() == 0)
+    {
+        return mIndexBuffer->initialize(bufferSize, indexType, mDynamic);
+    }
+    else
+    {
+        return mIndexBuffer->setSize(bufferSize, indexType);
+    }
+}
+
+StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory)
+    : IndexBufferInterface(factory, true)
+{
+}
+
+StreamingIndexBufferInterface::~StreamingIndexBufferInterface()
+{
+}
+
+gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
+{
+    unsigned int curBufferSize = getBufferSize();
+    unsigned int writePos = getWritePosition();
+    if (size > curBufferSize)
+    {
+        gl::Error error = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
+        if (error.isError())
+        {
+            return error;
+        }
+        setWritePosition(0);
+    }
+    else if (writePos + size > curBufferSize || writePos + size < writePos)
+    {
+        gl::Error error = discard();
+        if (error.isError())
+        {
+            return error;
+        }
+        setWritePosition(0);
+    }
+
+    return gl::NoError();
+}
+
+
+StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory)
+    : IndexBufferInterface(factory, false)
+{
+}
+
+StaticIndexBufferInterface::~StaticIndexBufferInterface()
+{
+}
+
+gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
+{
+    unsigned int curSize = getBufferSize();
+    if (curSize == 0)
+    {
+        return setBufferSize(size, indexType);
+    }
+    else if (curSize >= size && indexType == getIndexType())
+    {
+        return gl::NoError();
+    }
+    else
+    {
+        UNREACHABLE();
+        return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized");
+    }
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/IndexBuffer.h b/src/third_party/angle/src/libANGLE/renderer/d3d/IndexBuffer.h
new file mode 100644
index 0000000..0b7b28d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/IndexBuffer.h
@@ -0,0 +1,100 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer.h: Defines the abstract IndexBuffer class and IndexBufferInterface
+// class with derivations, classes that perform graphics API agnostic index buffer operations.
+
+#ifndef LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
+#define LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+class BufferFactoryD3D;
+
+class IndexBuffer : angle::NonCopyable
+{
+  public:
+    IndexBuffer();
+    virtual ~IndexBuffer();
+
+    virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0;
+
+    virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0;
+    virtual gl::Error unmapBuffer() = 0;
+
+    virtual gl::Error discard() = 0;
+
+    virtual GLenum getIndexType() const = 0;
+    virtual unsigned int getBufferSize() const = 0;
+    virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType) = 0;
+
+    unsigned int getSerial() const;
+
+  protected:
+    void updateSerial();
+
+  private:
+    unsigned int mSerial;
+    static unsigned int mNextSerial;
+};
+
+class IndexBufferInterface : angle::NonCopyable
+{
+  public:
+    IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic);
+    virtual ~IndexBufferInterface();
+
+    virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0;
+
+    GLenum getIndexType() const;
+    unsigned int getBufferSize() const;
+
+    unsigned int getSerial() const;
+
+    gl::Error mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset);
+    gl::Error unmapBuffer();
+
+    IndexBuffer *getIndexBuffer() const;
+
+  protected:
+    unsigned int getWritePosition() const;
+    void setWritePosition(unsigned int writePosition);
+
+    gl::Error discard();
+
+    gl::Error setBufferSize(unsigned int bufferSize, GLenum indexType);
+
+  private:
+    IndexBuffer *mIndexBuffer;
+
+    unsigned int mWritePosition;
+    bool mDynamic;
+};
+
+class StreamingIndexBufferInterface : public IndexBufferInterface
+{
+  public:
+    explicit StreamingIndexBufferInterface(BufferFactoryD3D *factory);
+    ~StreamingIndexBufferInterface();
+
+    gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override;
+};
+
+class StaticIndexBufferInterface : public IndexBufferInterface
+{
+  public:
+    explicit StaticIndexBufferInterface(BufferFactoryD3D *factory);
+    ~StaticIndexBufferInterface();
+
+    gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
new file mode 100644
index 0000000..184b89c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
@@ -0,0 +1,408 @@
+//
+// 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.
+//
+
+// IndexDataManager.cpp: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+
+namespace rx
+{
+
+namespace
+{
+
+template <typename InputT, typename DestT>
+void ConvertIndexArray(const void *input,
+                       GLenum sourceType,
+                       void *output,
+                       GLenum destinationType,
+                       GLsizei count,
+                       bool usePrimitiveRestartFixedIndex)
+{
+    const InputT *in = static_cast<const InputT *>(input);
+    DestT *out       = static_cast<DestT *>(output);
+
+    if (usePrimitiveRestartFixedIndex)
+    {
+        InputT srcRestartIndex = static_cast<InputT>(gl::GetPrimitiveRestartIndex(sourceType));
+        DestT destRestartIndex = static_cast<DestT>(gl::GetPrimitiveRestartIndex(destinationType));
+        for (GLsizei i = 0; i < count; i++)
+        {
+            out[i] = (in[i] == srcRestartIndex ? destRestartIndex : static_cast<DestT>(in[i]));
+        }
+    }
+    else
+    {
+        for (GLsizei i = 0; i < count; i++)
+        {
+            out[i] = static_cast<DestT>(in[i]);
+        }
+    }
+}
+
+void ConvertIndices(GLenum sourceType,
+                    GLenum destinationType,
+                    const void *input,
+                    GLsizei count,
+                    void *output,
+                    bool usePrimitiveRestartFixedIndex)
+{
+    if (sourceType == destinationType)
+    {
+        const gl::Type &typeInfo = gl::GetTypeInfo(destinationType);
+        memcpy(output, input, count * typeInfo.bytes);
+        return;
+    }
+
+    if (sourceType == GL_UNSIGNED_BYTE)
+    {
+        ASSERT(destinationType == GL_UNSIGNED_SHORT);
+        ConvertIndexArray<GLubyte, GLushort>(input, sourceType, output, destinationType, count,
+                                             usePrimitiveRestartFixedIndex);
+    }
+    else if (sourceType == GL_UNSIGNED_SHORT)
+    {
+        ASSERT(destinationType == GL_UNSIGNED_INT);
+        ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count,
+                                            usePrimitiveRestartFixedIndex);
+    }
+    else
+        UNREACHABLE();
+}
+
+gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer,
+                              const void *data,
+                              unsigned int count,
+                              GLenum srcType,
+                              GLenum dstType,
+                              bool usePrimitiveRestartFixedIndex,
+                              unsigned int *offset)
+{
+    const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
+
+    if (count > (std::numeric_limits<unsigned int>::max() >> dstTypeInfo.bytesShift))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Reserving %u indices of %u bytes each exceeds the maximum buffer size.",
+                         count, dstTypeInfo.bytes);
+    }
+
+    unsigned int bufferSizeRequired = count << dstTypeInfo.bytesShift;
+    gl::Error error                 = buffer->reserveBufferSpace(bufferSizeRequired, dstType);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    void *output = nullptr;
+    error        = buffer->mapBuffer(bufferSizeRequired, &output, offset);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex);
+
+    error = buffer->unmapBuffer();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return gl::NoError();
+}
+
+}  // anonymous namespace
+
+IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass)
+    : mFactory(factory),
+      mRendererClass(rendererClass),
+      mStreamingBufferShort(nullptr),
+      mStreamingBufferInt(nullptr)
+{
+}
+
+IndexDataManager::~IndexDataManager()
+{
+    SafeDelete(mStreamingBufferShort);
+    SafeDelete(mStreamingBufferInt);
+}
+
+bool IndexDataManager::usePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
+                                                     GLenum type)
+{
+    // We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT
+    // indices, since we restrict it via MAX_ELEMENT_INDEX.
+    return (!primitiveRestartFixedIndexEnabled && type == GL_UNSIGNED_SHORT &&
+            mRendererClass == RENDERER_D3D11);
+}
+
+bool IndexDataManager::isStreamingIndexData(bool primitiveRestartWorkaround,
+                                            GLenum srcType,
+                                            gl::Buffer *glBuffer)
+{
+    BufferD3D *buffer = glBuffer ? GetImplAs<BufferD3D>(glBuffer) : nullptr;
+
+    // Case 1: the indices are passed by pointer, which forces the streaming of index data
+    if (glBuffer == nullptr)
+    {
+        return true;
+    }
+
+    const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround)
+                               ? GL_UNSIGNED_INT
+                               : GL_UNSIGNED_SHORT;
+
+    // Case 2a: the buffer can be used directly
+    if (buffer->supportsDirectBinding() && dstType == srcType)
+    {
+        return false;
+    }
+
+    // Case 2b: use a static translated copy or fall back to streaming
+    StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer();
+    if (staticBuffer == nullptr)
+    {
+        return true;
+    }
+
+    if ((staticBuffer->getBufferSize() != 0) && (staticBuffer->getIndexType() != dstType))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+// This function translates a GL-style indices into DX-style indices, with their description
+// returned in translated.
+// GL can specify vertex data in immediate mode (pointer to CPU array of indices), which is not
+// possible in DX and requires streaming (Case 1). If the GL indices are specified with a buffer
+// (Case 2), in a format supported by DX (subcase a) then all is good.
+// When we have a buffer with an unsupported format (subcase b) then we need to do some translation:
+// we will start by falling back to streaming, and after a while will start using a static
+// translated copy of the index buffer.
+gl::Error IndexDataManager::prepareIndexData(GLenum srcType,
+                                             GLsizei count,
+                                             gl::Buffer *glBuffer,
+                                             const void *indices,
+                                             TranslatedIndexData *translated,
+                                             bool primitiveRestartFixedIndexEnabled)
+{
+    // Avoid D3D11's primitive restart index value
+    // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
+    bool hasPrimitiveRestartIndex =
+        translated->indexRange.vertexIndexCount < static_cast<size_t>(count) ||
+        translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType);
+    bool primitiveRestartWorkaround =
+        usePrimitiveRestartWorkaround(primitiveRestartFixedIndexEnabled, srcType) &&
+        hasPrimitiveRestartIndex;
+
+    // We should never have to deal with MAX_UINT indices, since we restrict it via
+    // MAX_ELEMENT_INDEX.
+    ASSERT(!(mRendererClass == RENDERER_D3D11 && !primitiveRestartFixedIndexEnabled &&
+             hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_INT));
+
+    const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround)
+                               ? GL_UNSIGNED_INT
+                               : GL_UNSIGNED_SHORT;
+
+    const gl::Type &srcTypeInfo = gl::GetTypeInfo(srcType);
+    const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
+
+    BufferD3D *buffer = glBuffer ? GetImplAs<BufferD3D>(glBuffer) : nullptr;
+
+    translated->indexType                 = dstType;
+    translated->srcIndexData.srcBuffer    = buffer;
+    translated->srcIndexData.srcIndices   = indices;
+    translated->srcIndexData.srcIndexType = srcType;
+    translated->srcIndexData.srcCount     = count;
+
+    // Case 1: the indices are passed by pointer, which forces the streaming of index data
+    if (glBuffer == nullptr)
+    {
+        translated->storage = nullptr;
+        return streamIndexData(indices, count, srcType, dstType, primitiveRestartFixedIndexEnabled,
+                               translated);
+    }
+
+    // Case 2: the indices are already in a buffer
+    unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
+    ASSERT(srcTypeInfo.bytes * static_cast<unsigned int>(count) + offset <= buffer->getSize());
+
+    bool offsetAligned;
+    switch (srcType)
+    {
+        case GL_UNSIGNED_BYTE:
+            offsetAligned = (offset % sizeof(GLubyte) == 0);
+            break;
+        case GL_UNSIGNED_SHORT:
+            offsetAligned = (offset % sizeof(GLushort) == 0);
+            break;
+        case GL_UNSIGNED_INT:
+            offsetAligned = (offset % sizeof(GLuint) == 0);
+            break;
+        default:
+            UNREACHABLE();
+            offsetAligned = false;
+    }
+
+    // Case 2a: the buffer can be used directly
+    if (offsetAligned && buffer->supportsDirectBinding() && dstType == srcType)
+    {
+        translated->storage     = buffer;
+        translated->indexBuffer = nullptr;
+        translated->serial      = buffer->getSerial();
+        translated->startIndex  = (offset >> srcTypeInfo.bytesShift);
+        translated->startOffset = offset;
+        return gl::NoError();
+    }
+    else
+    {
+        translated->storage = nullptr;
+    }
+
+    // Case 2b: use a static translated copy or fall back to streaming
+    StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer();
+
+    bool staticBufferInitialized = staticBuffer && staticBuffer->getBufferSize() != 0;
+    bool staticBufferUsable =
+        staticBuffer && offsetAligned && staticBuffer->getIndexType() == dstType;
+
+    if (staticBufferInitialized && !staticBufferUsable)
+    {
+        buffer->invalidateStaticData();
+        staticBuffer = nullptr;
+    }
+
+    if (staticBuffer == nullptr || !offsetAligned)
+    {
+        const uint8_t *bufferData = nullptr;
+        gl::Error error           = buffer->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+        ASSERT(bufferData != nullptr);
+
+        error = streamIndexData(bufferData + offset, count, srcType, dstType,
+                                primitiveRestartFixedIndexEnabled, translated);
+        if (error.isError())
+        {
+            return error;
+        }
+        buffer->promoteStaticUsage(count << srcTypeInfo.bytesShift);
+    }
+    else
+    {
+        if (!staticBufferInitialized)
+        {
+            const uint8_t *bufferData = nullptr;
+            gl::Error error           = buffer->getData(&bufferData);
+            if (error.isError())
+            {
+                return error;
+            }
+            ASSERT(bufferData != nullptr);
+
+            unsigned int convertCount =
+                static_cast<unsigned int>(buffer->getSize()) >> srcTypeInfo.bytesShift;
+            error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType,
+                                        primitiveRestartFixedIndexEnabled, nullptr);
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+        ASSERT(offsetAligned && staticBuffer->getIndexType() == dstType);
+
+        translated->indexBuffer = staticBuffer->getIndexBuffer();
+        translated->serial      = staticBuffer->getSerial();
+        translated->startIndex  = (offset >> srcTypeInfo.bytesShift);
+        translated->startOffset = (offset >> srcTypeInfo.bytesShift) << dstTypeInfo.bytesShift;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error IndexDataManager::streamIndexData(const void *data,
+                                            unsigned int count,
+                                            GLenum srcType,
+                                            GLenum dstType,
+                                            bool usePrimitiveRestartFixedIndex,
+                                            TranslatedIndexData *translated)
+{
+    const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
+
+    IndexBufferInterface *indexBuffer = nullptr;
+    gl::Error error                   = getStreamingIndexBuffer(dstType, &indexBuffer);
+    if (error.isError())
+    {
+        return error;
+    }
+    ASSERT(indexBuffer != nullptr);
+
+    unsigned int offset;
+    StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, usePrimitiveRestartFixedIndex,
+                        &offset);
+
+    translated->indexBuffer = indexBuffer->getIndexBuffer();
+    translated->serial      = indexBuffer->getSerial();
+    translated->startIndex  = (offset >> dstTypeInfo.bytesShift);
+    translated->startOffset = offset;
+
+    return gl::NoError();
+}
+
+gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType,
+                                                    IndexBufferInterface **outBuffer)
+{
+    ASSERT(outBuffer);
+    if (destinationIndexType == GL_UNSIGNED_INT)
+    {
+        if (!mStreamingBufferInt)
+        {
+            mStreamingBufferInt = new StreamingIndexBufferInterface(mFactory);
+            gl::Error error =
+                mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+            if (error.isError())
+            {
+                SafeDelete(mStreamingBufferInt);
+                return error;
+            }
+        }
+
+        *outBuffer = mStreamingBufferInt;
+        return gl::NoError();
+    }
+    else
+    {
+        ASSERT(destinationIndexType == GL_UNSIGNED_SHORT);
+
+        if (!mStreamingBufferShort)
+        {
+            mStreamingBufferShort = new StreamingIndexBufferInterface(mFactory);
+            gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE,
+                                                                        GL_UNSIGNED_SHORT);
+            if (error.isError())
+            {
+                SafeDelete(mStreamingBufferShort);
+                return error;
+            }
+        }
+
+        *outBuffer = mStreamingBufferShort;
+        return gl::NoError();
+    }
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h b/src/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
new file mode 100644
index 0000000..84ab219
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
@@ -0,0 +1,99 @@
+//
+// 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.
+//
+
+// IndexDataManager.h: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#ifndef LIBANGLE_INDEXDATAMANAGER_H_
+#define LIBANGLE_INDEXDATAMANAGER_H_
+
+#include <GLES2/gl2.h>
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace
+{
+enum
+{
+    INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint)
+};
+}
+
+namespace gl
+{
+class Buffer;
+}
+
+namespace rx
+{
+class IndexBufferInterface;
+class StaticIndexBufferInterface;
+class StreamingIndexBufferInterface;
+class IndexBuffer;
+class BufferD3D;
+class RendererD3D;
+
+struct SourceIndexData
+{
+    BufferD3D *srcBuffer;
+    const void *srcIndices;
+    unsigned int srcCount;
+    GLenum srcIndexType;
+    bool srcIndicesChanged;
+};
+
+struct TranslatedIndexData
+{
+    gl::IndexRange indexRange;
+    unsigned int startIndex;
+    unsigned int startOffset;  // In bytes
+
+    IndexBuffer *indexBuffer;
+    BufferD3D *storage;
+    GLenum indexType;
+    unsigned int serial;
+
+    SourceIndexData srcIndexData;
+};
+
+class IndexDataManager : angle::NonCopyable
+{
+  public:
+    explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass);
+    virtual ~IndexDataManager();
+
+    bool usePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled, GLenum type);
+    bool isStreamingIndexData(bool primitiveRestartWorkaround,
+                              GLenum srcType,
+                              gl::Buffer *glBuffer);
+    gl::Error prepareIndexData(GLenum srcType,
+                               GLsizei count,
+                               gl::Buffer *glBuffer,
+                               const void *indices,
+                               TranslatedIndexData *translated,
+                               bool primitiveRestartFixedIndexEnabled);
+
+  private:
+    gl::Error streamIndexData(const void *data,
+                              unsigned int count,
+                              GLenum srcType,
+                              GLenum dstType,
+                              bool usePrimitiveRestartFixedIndex,
+                              TranslatedIndexData *translated);
+    gl::Error getStreamingIndexBuffer(GLenum destinationIndexType,
+                                      IndexBufferInterface **outBuffer);
+
+    BufferFactoryD3D *const mFactory;
+    RendererClass mRendererClass;
+    StreamingIndexBufferInterface *mStreamingBufferShort;
+    StreamingIndexBufferInterface *mStreamingBufferInt;
+};
+}
+
+#endif  // LIBANGLE_INDEXDATAMANAGER_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp
new file mode 100644
index 0000000..113bad6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// NativeWindowD3D.cpp: Defines NativeWindowD3D, a class for managing and performing operations on
+// an EGLNativeWindowType for the D3D renderers.
+
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace rx
+{
+
+NativeWindowD3D::NativeWindowD3D(EGLNativeWindowType window) : mWindow(window)
+{
+}
+
+NativeWindowD3D::~NativeWindowD3D()
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h
new file mode 100644
index 0000000..3654484
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// NativeWindowD3D.h: Defines NativeWindowD3D, a class for managing and performing operations on an
+// EGLNativeWindowType for the D3D renderers.
+
+#ifndef LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_
+#define LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include <EGL/eglplatform.h>
+#include "libANGLE/Config.h"
+
+namespace rx
+{
+class NativeWindowD3D : angle::NonCopyable
+{
+  public:
+    NativeWindowD3D(EGLNativeWindowType window);
+    virtual ~NativeWindowD3D();
+
+    virtual bool initialize() = 0;
+    virtual bool getClientRect(LPRECT rect) const = 0;
+    virtual bool isIconic() const = 0;
+
+    inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
+
+  private:
+    EGLNativeWindowType mWindow;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
new file mode 100644
index 0000000..b8df596
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -0,0 +1,2512 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
+
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VaryingPacking.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace
+{
+
+gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
+{
+    gl::InputLayout defaultLayout;
+    for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
+    {
+        if (shaderAttr.type != GL_NONE)
+        {
+            GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
+
+            for (size_t rowIndex = 0;
+                 static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
+            {
+                GLenum componentType = gl::VariableComponentType(transposedType);
+                GLuint components    = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
+                bool pureInt = (componentType != GL_FLOAT);
+                gl::VertexFormatType defaultType =
+                    gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
+
+                defaultLayout.push_back(defaultType);
+            }
+        }
+    }
+
+    return defaultLayout;
+}
+
+std::vector<GLenum> GetDefaultOutputLayoutFromShader(
+    const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
+{
+    std::vector<GLenum> defaultPixelOutput;
+
+    if (!shaderOutputVars.empty())
+    {
+        defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
+                                     static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
+    }
+
+    return defaultPixelOutput;
+}
+
+bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
+{
+    return var.isRowMajorLayout;
+}
+
+bool IsRowMajorLayout(const sh::ShaderVariable &var)
+{
+    return false;
+}
+
+template <typename VarT>
+void GetUniformBlockInfo(const std::vector<VarT> &fields,
+                         const std::string &prefix,
+                         sh::BlockLayoutEncoder *encoder,
+                         bool inRowMajorLayout,
+                         std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
+{
+    for (const VarT &field : fields)
+    {
+        const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
+
+        if (field.isStruct())
+        {
+            bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
+
+            for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
+            {
+                encoder->enterAggregateType();
+
+                const std::string uniformElementName =
+                    fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
+                GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
+                                    blockInfoOut);
+
+                encoder->exitAggregateType();
+            }
+        }
+        else
+        {
+            bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
+            (*blockInfoOut)[fieldName] =
+                encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
+        }
+    }
+}
+
+template <typename T>
+static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
+{
+    ASSERT(dest != nullptr);
+    ASSERT(dirtyFlag != nullptr);
+
+    *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
+    *dest      = source;
+}
+
+template <typename T, int cols, int rows>
+bool TransposeExpandMatrix(T *target, const GLfloat *value)
+{
+    constexpr int targetWidth  = 4;
+    constexpr int targetHeight = rows;
+    constexpr int srcWidth     = rows;
+    constexpr int srcHeight    = cols;
+
+    constexpr int copyWidth  = std::min(targetHeight, srcWidth);
+    constexpr int copyHeight = std::min(targetWidth, srcHeight);
+
+    T staging[targetWidth * targetHeight] = {0};
+
+    for (int x = 0; x < copyWidth; x++)
+    {
+        for (int y = 0; y < copyHeight; y++)
+        {
+            staging[x * targetWidth + y] = static_cast<T>(value[y * srcWidth + x]);
+        }
+    }
+
+    if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0)
+    {
+        return false;
+    }
+
+    memcpy(target, staging, targetWidth * targetHeight * sizeof(T));
+    return true;
+}
+
+template <typename T, int cols, int rows>
+bool ExpandMatrix(T *target, const GLfloat *value)
+{
+    constexpr int targetWidth  = 4;
+    constexpr int targetHeight = rows;
+    constexpr int srcWidth = cols;
+    constexpr int srcHeight = rows;
+
+    constexpr int copyWidth  = std::min(targetWidth, srcWidth);
+    constexpr int copyHeight = std::min(targetHeight, srcHeight);
+
+    T staging[targetWidth * targetHeight] = {0};
+
+    for (int y = 0; y < copyHeight; y++)
+    {
+        for (int x = 0; x < copyWidth; x++)
+        {
+            staging[y * targetWidth + x] = static_cast<T>(value[y * srcWidth + x]);
+        }
+    }
+
+    if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0)
+    {
+        return false;
+    }
+
+    memcpy(target, staging, targetWidth * targetHeight * sizeof(T));
+    return true;
+}
+
+gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
+{
+    switch (drawMode)
+    {
+        // Uses the point sprite geometry shader.
+        case GL_POINTS:
+            return gl::PRIMITIVE_POINTS;
+
+        // All line drawing uses the same geometry shader.
+        case GL_LINES:
+        case GL_LINE_STRIP:
+        case GL_LINE_LOOP:
+            return gl::PRIMITIVE_LINES;
+
+        // The triangle fan primitive is emulated with strips in D3D11.
+        case GL_TRIANGLES:
+        case GL_TRIANGLE_FAN:
+            return gl::PRIMITIVE_TRIANGLES;
+
+        // Special case for triangle strips.
+        case GL_TRIANGLE_STRIP:
+            return gl::PRIMITIVE_TRIANGLE_STRIP;
+
+        default:
+            UNREACHABLE();
+            return gl::PRIMITIVE_TYPE_MAX;
+    }
+}
+
+bool FindFlatInterpolationVarying(const std::vector<sh::Varying> &varyings)
+{
+    // Note: this assumes nested structs can only be packed with one interpolation.
+    for (const auto &varying : varyings)
+    {
+        if (varying.interpolation == sh::INTERPOLATION_FLAT)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+}  // anonymous namespace
+
+// D3DUniform Implementation
+
+D3DUniform::D3DUniform(GLenum typeIn,
+                       const std::string &nameIn,
+                       unsigned int arraySizeIn,
+                       bool defaultBlock)
+    : type(typeIn),
+      name(nameIn),
+      arraySize(arraySizeIn),
+      data(nullptr),
+      dirty(true),
+      vsRegisterIndex(GL_INVALID_INDEX),
+      psRegisterIndex(GL_INVALID_INDEX),
+      csRegisterIndex(GL_INVALID_INDEX),
+      registerCount(0),
+      registerElement(0)
+{
+    // We use data storage for default block uniforms to cache values that are sent to D3D during
+    // rendering
+    // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
+    if (defaultBlock)
+    {
+        size_t bytes = gl::VariableInternalSize(type) * elementCount();
+        data = new uint8_t[bytes];
+        memset(data, 0, bytes);
+
+        // Use the row count as register count, will work for non-square matrices.
+        registerCount = gl::VariableRowCount(type) * elementCount();
+    }
+}
+
+D3DUniform::~D3DUniform()
+{
+    SafeDeleteArray(data);
+}
+
+bool D3DUniform::isSampler() const
+{
+    return gl::IsSamplerType(type);
+}
+
+bool D3DUniform::isReferencedByVertexShader() const
+{
+    return vsRegisterIndex != GL_INVALID_INDEX;
+}
+
+bool D3DUniform::isReferencedByFragmentShader() const
+{
+    return psRegisterIndex != GL_INVALID_INDEX;
+}
+
+bool D3DUniform::isReferencedByComputeShader() const
+{
+    return csRegisterIndex != GL_INVALID_INDEX;
+}
+
+// D3DVarying Implementation
+
+D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0)
+{
+}
+
+D3DVarying::D3DVarying(const std::string &semanticNameIn,
+                       unsigned int semanticIndexIn,
+                       unsigned int componentCountIn,
+                       unsigned int outputSlotIn)
+    : semanticName(semanticNameIn),
+      semanticIndex(semanticIndexIn),
+      componentCount(componentCountIn),
+      outputSlot(outputSlotIn)
+{
+}
+
+// ProgramD3DMetadata Implementation
+
+ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
+                                       const ShaderD3D *vertexShader,
+                                       const ShaderD3D *fragmentShader)
+    : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
+      mShaderModelSuffix(renderer->getShaderModelSuffix()),
+      mUsesInstancedPointSpriteEmulation(
+          renderer->getWorkarounds().useInstancedPointSpriteEmulation),
+      mUsesViewScale(renderer->presentPathFastEnabled()),
+      mVertexShader(vertexShader),
+      mFragmentShader(fragmentShader)
+{
+}
+
+int ProgramD3DMetadata::getRendererMajorShaderModel() const
+{
+    return mRendererMajorShaderModel;
+}
+
+bool ProgramD3DMetadata::usesBroadcast(const gl::ContextState &data) const
+{
+    return (mFragmentShader->usesFragColor() && data.getClientMajorVersion() < 3);
+}
+
+bool ProgramD3DMetadata::usesFragDepth() const
+{
+    return mFragmentShader->usesFragDepth();
+}
+
+bool ProgramD3DMetadata::usesPointCoord() const
+{
+    return mFragmentShader->usesPointCoord();
+}
+
+bool ProgramD3DMetadata::usesFragCoord() const
+{
+    return mFragmentShader->usesFragCoord();
+}
+
+bool ProgramD3DMetadata::usesPointSize() const
+{
+    return mVertexShader->usesPointSize();
+}
+
+bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
+{
+    return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
+           mRendererMajorShaderModel >= 4;
+}
+
+bool ProgramD3DMetadata::usesViewScale() const
+{
+    return mUsesViewScale;
+}
+
+bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
+{
+    // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
+    // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
+    // Even with a geometry shader, the app can render triangles or lines and reference
+    // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For
+    // simplicity, we always add this to the vertex shader when the fragment shader
+    // references gl_PointCoord, even if we could skip it in the geometry shader.
+    return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
+           usesInsertedPointCoordValue();
+}
+
+bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
+{
+    // gl_Position only needs to be outputted from the vertex shader if transform feedback is
+    // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
+    // the vertex shader in this case. This saves us 1 output vector.
+    return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
+}
+
+bool ProgramD3DMetadata::usesSystemValuePointSize() const
+{
+    return !mUsesInstancedPointSpriteEmulation && usesPointSize();
+}
+
+bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
+{
+    return mFragmentShader->usesMultipleRenderTargets();
+}
+
+GLint ProgramD3DMetadata::getMajorShaderVersion() const
+{
+    return mVertexShader->getData().getShaderVersion();
+}
+
+const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
+{
+    return mFragmentShader;
+}
+
+// ProgramD3D Implementation
+
+ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
+                                               const Signature &signature,
+                                               ShaderExecutableD3D *shaderExecutable)
+    : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
+{
+}
+
+ProgramD3D::VertexExecutable::~VertexExecutable()
+{
+    SafeDelete(mShaderExecutable);
+}
+
+// static
+ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
+    GLenum type)
+{
+    switch (type)
+    {
+        case GL_INT:
+            return HLSLAttribType::SIGNED_INT;
+        case GL_UNSIGNED_INT:
+            return HLSLAttribType::UNSIGNED_INT;
+        case GL_SIGNED_NORMALIZED:
+        case GL_UNSIGNED_NORMALIZED:
+        case GL_FLOAT:
+            return HLSLAttribType::FLOAT;
+        default:
+            UNREACHABLE();
+            return HLSLAttribType::FLOAT;
+    }
+}
+
+// static
+void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
+                                                const gl::InputLayout &inputLayout,
+                                                Signature *signatureOut)
+{
+    signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
+
+    for (size_t index = 0; index < inputLayout.size(); ++index)
+    {
+        gl::VertexFormatType vertexFormatType = inputLayout[index];
+        if (vertexFormatType == gl::VERTEX_FORMAT_INVALID)
+            continue;
+
+        VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatType);
+        if ((conversionType & VERTEX_CONVERT_GPU) == 0)
+            continue;
+
+        GLenum componentType = renderer->getVertexComponentType(vertexFormatType);
+        (*signatureOut)[index] = GetAttribType(componentType);
+    }
+}
+
+bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
+{
+    size_t limit = std::max(mSignature.size(), signature.size());
+    for (size_t index = 0; index < limit; ++index)
+    {
+        // treat undefined indexes as FLOAT
+        auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
+        auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
+        if (a != b)
+            return false;
+    }
+
+    return true;
+}
+
+ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
+                                             ShaderExecutableD3D *shaderExecutable)
+    : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
+{
+}
+
+ProgramD3D::PixelExecutable::~PixelExecutable()
+{
+    SafeDelete(mShaderExecutable);
+}
+
+ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
+{
+}
+
+unsigned int ProgramD3D::mCurrentSerial = 1;
+
+ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
+    : ProgramImpl(state),
+      mRenderer(renderer),
+      mDynamicHLSL(nullptr),
+      mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX),
+      mComputeExecutable(nullptr),
+      mUsesPointSize(false),
+      mUsesFlatInterpolation(false),
+      mVertexUniformStorage(nullptr),
+      mFragmentUniformStorage(nullptr),
+      mComputeUniformStorage(nullptr),
+      mUsedVertexSamplerRange(0),
+      mUsedPixelSamplerRange(0),
+      mUsedComputeSamplerRange(0),
+      mDirtySamplerMapping(true),
+      mSerial(issueSerial())
+{
+    mDynamicHLSL = new DynamicHLSL(renderer);
+}
+
+ProgramD3D::~ProgramD3D()
+{
+    reset();
+    SafeDelete(mDynamicHLSL);
+}
+
+bool ProgramD3D::usesPointSpriteEmulation() const
+{
+    return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
+}
+
+bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
+{
+    if (drawMode != GL_POINTS)
+    {
+        return mUsesFlatInterpolation;
+    }
+
+    return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
+}
+
+bool ProgramD3D::usesInstancedPointSpriteEmulation() const
+{
+    return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
+}
+
+GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
+                                    unsigned int samplerIndex,
+                                    const gl::Caps &caps) const
+{
+    GLint logicalTextureUnit = -1;
+
+    switch (type)
+    {
+        case gl::SAMPLER_PIXEL:
+            ASSERT(samplerIndex < caps.maxTextureImageUnits);
+            if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
+            {
+                logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
+            }
+            break;
+        case gl::SAMPLER_VERTEX:
+            ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
+            if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
+            {
+                logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
+            }
+            break;
+        case gl::SAMPLER_COMPUTE:
+            ASSERT(samplerIndex < caps.maxComputeTextureImageUnits);
+            if (samplerIndex < mSamplersCS.size() && mSamplersCS[samplerIndex].active)
+            {
+                logicalTextureUnit = mSamplersCS[samplerIndex].logicalTextureUnit;
+            }
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    if (logicalTextureUnit >= 0 &&
+        logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
+    {
+        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).
+GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
+{
+    switch (type)
+    {
+        case gl::SAMPLER_PIXEL:
+            ASSERT(samplerIndex < mSamplersPS.size());
+            ASSERT(mSamplersPS[samplerIndex].active);
+            return mSamplersPS[samplerIndex].textureType;
+        case gl::SAMPLER_VERTEX:
+            ASSERT(samplerIndex < mSamplersVS.size());
+            ASSERT(mSamplersVS[samplerIndex].active);
+            return mSamplersVS[samplerIndex].textureType;
+        case gl::SAMPLER_COMPUTE:
+            ASSERT(samplerIndex < mSamplersCS.size());
+            ASSERT(mSamplersCS[samplerIndex].active);
+            return mSamplersCS[samplerIndex].textureType;
+        default:
+            UNREACHABLE();
+    }
+
+    return GL_TEXTURE_2D;
+}
+
+GLuint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
+{
+    switch (type)
+    {
+        case gl::SAMPLER_PIXEL:
+            return mUsedPixelSamplerRange;
+        case gl::SAMPLER_VERTEX:
+            return mUsedVertexSamplerRange;
+        case gl::SAMPLER_COMPUTE:
+            return mUsedComputeSamplerRange;
+        default:
+            UNREACHABLE();
+            return 0u;
+    }
+}
+
+void ProgramD3D::updateSamplerMapping()
+{
+    if (!mDirtySamplerMapping)
+    {
+        return;
+    }
+
+    mDirtySamplerMapping = false;
+
+    // Retrieve sampler uniform values
+    for (const D3DUniform *d3dUniform : mD3DUniforms)
+    {
+        if (!d3dUniform->dirty)
+            continue;
+
+        if (!d3dUniform->isSampler())
+            continue;
+
+        int count = d3dUniform->elementCount();
+        const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
+
+        if (d3dUniform->isReferencedByFragmentShader())
+        {
+            unsigned int firstIndex = d3dUniform->psRegisterIndex;
+
+            for (int i = 0; i < count; i++)
+            {
+                unsigned int samplerIndex = firstIndex + i;
+
+                if (samplerIndex < mSamplersPS.size())
+                {
+                    ASSERT(mSamplersPS[samplerIndex].active);
+                    mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
+                }
+            }
+        }
+
+        if (d3dUniform->isReferencedByVertexShader())
+        {
+            unsigned int firstIndex = d3dUniform->vsRegisterIndex;
+
+            for (int i = 0; i < count; i++)
+            {
+                unsigned int samplerIndex = firstIndex + i;
+
+                if (samplerIndex < mSamplersVS.size())
+                {
+                    ASSERT(mSamplersVS[samplerIndex].active);
+                    mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
+                }
+            }
+        }
+
+        if (d3dUniform->isReferencedByComputeShader())
+        {
+            unsigned int firstIndex = d3dUniform->csRegisterIndex;
+
+            for (int i = 0; i < count; i++)
+            {
+                unsigned int samplerIndex = firstIndex + i;
+
+                if (samplerIndex < mSamplersCS.size())
+                {
+                    ASSERT(mSamplersCS[samplerIndex].active);
+                    mSamplersCS[samplerIndex].logicalTextureUnit = v[i][0];
+                }
+            }
+        }
+    }
+}
+
+LinkResult ProgramD3D::load(const ContextImpl *contextImpl,
+                            gl::InfoLog &infoLog,
+                            gl::BinaryInputStream *stream)
+{
+    // TODO(jmadill): Use Renderer from contextImpl.
+
+    reset();
+
+    DeviceIdentifier binaryDeviceIdentifier = {0};
+    stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
+                      sizeof(DeviceIdentifier));
+
+    DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
+    if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
+    {
+        infoLog << "Invalid program binary, device configuration has changed.";
+        return false;
+    }
+
+    int compileFlags = stream->readInt<int>();
+    if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+    {
+        infoLog << "Mismatched compilation flags.";
+        return false;
+    }
+
+    for (int &index : mAttribLocationToD3DSemantic)
+    {
+        stream->readInt(&index);
+    }
+
+    const unsigned int psSamplerCount = stream->readInt<unsigned int>();
+    for (unsigned int i = 0; i < psSamplerCount; ++i)
+    {
+        Sampler sampler;
+        stream->readBool(&sampler.active);
+        stream->readInt(&sampler.logicalTextureUnit);
+        stream->readInt(&sampler.textureType);
+        mSamplersPS.push_back(sampler);
+    }
+    const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
+    for (unsigned int i = 0; i < vsSamplerCount; ++i)
+    {
+        Sampler sampler;
+        stream->readBool(&sampler.active);
+        stream->readInt(&sampler.logicalTextureUnit);
+        stream->readInt(&sampler.textureType);
+        mSamplersVS.push_back(sampler);
+    }
+
+    const unsigned int csSamplerCount = stream->readInt<unsigned int>();
+    for (unsigned int i = 0; i < csSamplerCount; ++i)
+    {
+        Sampler sampler;
+        stream->readBool(&sampler.active);
+        stream->readInt(&sampler.logicalTextureUnit);
+        stream->readInt(&sampler.textureType);
+        mSamplersCS.push_back(sampler);
+    }
+
+    stream->readInt(&mUsedVertexSamplerRange);
+    stream->readInt(&mUsedPixelSamplerRange);
+    stream->readInt(&mUsedComputeSamplerRange);
+
+    const unsigned int uniformCount = stream->readInt<unsigned int>();
+    if (stream->error())
+    {
+        infoLog << "Invalid program binary.";
+        return false;
+    }
+
+    const auto &linkedUniforms = mState.getUniforms();
+    ASSERT(mD3DUniforms.empty());
+    for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
+    {
+        const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
+
+        D3DUniform *d3dUniform =
+            new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
+                           linkedUniform.isInDefaultBlock());
+        stream->readInt(&d3dUniform->psRegisterIndex);
+        stream->readInt(&d3dUniform->vsRegisterIndex);
+        stream->readInt(&d3dUniform->csRegisterIndex);
+        stream->readInt(&d3dUniform->registerCount);
+        stream->readInt(&d3dUniform->registerElement);
+
+        mD3DUniforms.push_back(d3dUniform);
+    }
+
+    const unsigned int blockCount = stream->readInt<unsigned int>();
+    if (stream->error())
+    {
+        infoLog << "Invalid program binary.";
+        return false;
+    }
+
+    ASSERT(mD3DUniformBlocks.empty());
+    for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+    {
+        D3DUniformBlock uniformBlock;
+        stream->readInt(&uniformBlock.psRegisterIndex);
+        stream->readInt(&uniformBlock.vsRegisterIndex);
+        stream->readInt(&uniformBlock.csRegisterIndex);
+        mD3DUniformBlocks.push_back(uniformBlock);
+    }
+
+    const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
+    mStreamOutVaryings.resize(streamOutVaryingCount);
+    for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
+    {
+        D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
+
+        stream->readString(&varying->semanticName);
+        stream->readInt(&varying->semanticIndex);
+        stream->readInt(&varying->componentCount);
+        stream->readInt(&varying->outputSlot);
+    }
+
+    stream->readString(&mVertexHLSL);
+    stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
+                      sizeof(angle::CompilerWorkaroundsD3D));
+    stream->readString(&mPixelHLSL);
+    stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
+                      sizeof(angle::CompilerWorkaroundsD3D));
+    stream->readBool(&mUsesFragDepth);
+    stream->readBool(&mUsesPointSize);
+    stream->readBool(&mUsesFlatInterpolation);
+
+    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);
+    }
+
+    stream->readString(&mGeometryShaderPreamble);
+
+    const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
+
+    bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
+
+    const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
+    for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
+         vertexShaderIndex++)
+    {
+        size_t inputLayoutSize = stream->readInt<size_t>();
+        gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
+
+        for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
+        {
+            inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
+        }
+
+        unsigned int vertexShaderSize             = stream->readInt<unsigned int>();
+        const unsigned char *vertexShaderFunction = binary + stream->offset();
+
+        ShaderExecutableD3D *shaderExecutable = nullptr;
+
+        ANGLE_TRY(mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, SHADER_VERTEX,
+                                            mStreamOutVaryings, separateAttribs,
+                                            &shaderExecutable));
+
+        if (!shaderExecutable)
+        {
+            infoLog << "Could not create vertex shader.";
+            return false;
+        }
+
+        // generated converted input layout
+        VertexExecutable::Signature signature;
+        VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
+
+        // add new binary
+        mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
+            new VertexExecutable(inputLayout, signature, shaderExecutable)));
+
+        stream->skip(vertexShaderSize);
+    }
+
+    const size_t pixelShaderCount = stream->readInt<unsigned int>();
+    for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
+    {
+        const size_t outputCount = stream->readInt<unsigned int>();
+        std::vector<GLenum> outputs(outputCount);
+        for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
+        {
+            stream->readInt(&outputs[outputIndex]);
+        }
+
+        const size_t pixelShaderSize             = stream->readInt<unsigned int>();
+        const unsigned char *pixelShaderFunction = binary + stream->offset();
+        ShaderExecutableD3D *shaderExecutable    = nullptr;
+
+        ANGLE_TRY(mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
+                                            mStreamOutVaryings, separateAttribs,
+                                            &shaderExecutable));
+
+        if (!shaderExecutable)
+        {
+            infoLog << "Could not create pixel shader.";
+            return false;
+        }
+
+        // add new binary
+        mPixelExecutables.push_back(
+            std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable)));
+
+        stream->skip(pixelShaderSize);
+    }
+
+    for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX;
+         ++geometryExeIndex)
+    {
+        unsigned int geometryShaderSize = stream->readInt<unsigned int>();
+        if (geometryShaderSize == 0)
+        {
+            continue;
+        }
+
+        const unsigned char *geometryShaderFunction = binary + stream->offset();
+
+        ShaderExecutableD3D *geometryExecutable = nullptr;
+        ANGLE_TRY(mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize,
+                                            SHADER_GEOMETRY, mStreamOutVaryings, separateAttribs,
+                                            &geometryExecutable));
+
+        if (!geometryExecutable)
+        {
+            infoLog << "Could not create geometry shader.";
+            return false;
+        }
+
+        mGeometryExecutables[geometryExeIndex].reset(geometryExecutable);
+
+        stream->skip(geometryShaderSize);
+    }
+
+    unsigned int computeShaderSize = stream->readInt<unsigned int>();
+    if (computeShaderSize > 0)
+    {
+        const unsigned char *computeShaderFunction = binary + stream->offset();
+
+        ShaderExecutableD3D *computeExecutable = nullptr;
+        ANGLE_TRY(mRenderer->loadExecutable(computeShaderFunction, computeShaderSize,
+                                            SHADER_COMPUTE, std::vector<D3DVarying>(), false,
+                                            &computeExecutable));
+
+        if (!computeExecutable)
+        {
+            infoLog << "Could not create compute shader.";
+            return false;
+        }
+
+        mComputeExecutable.reset(computeExecutable);
+    }
+
+    initializeUniformStorage();
+
+    return true;
+}
+
+gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
+{
+    // Output the DeviceIdentifier before we output any shader code
+    // When we load the binary again later, we can validate the device identifier before trying to
+    // compile any HLSL
+    DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
+    stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
+                       sizeof(DeviceIdentifier));
+
+    stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
+
+    for (int d3dSemantic : mAttribLocationToD3DSemantic)
+    {
+        stream->writeInt(d3dSemantic);
+    }
+
+    stream->writeInt(mSamplersPS.size());
+    for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
+    {
+        stream->writeInt(mSamplersPS[i].active);
+        stream->writeInt(mSamplersPS[i].logicalTextureUnit);
+        stream->writeInt(mSamplersPS[i].textureType);
+    }
+
+    stream->writeInt(mSamplersVS.size());
+    for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
+    {
+        stream->writeInt(mSamplersVS[i].active);
+        stream->writeInt(mSamplersVS[i].logicalTextureUnit);
+        stream->writeInt(mSamplersVS[i].textureType);
+    }
+
+    stream->writeInt(mSamplersCS.size());
+    for (unsigned int i = 0; i < mSamplersCS.size(); ++i)
+    {
+        stream->writeInt(mSamplersCS[i].active);
+        stream->writeInt(mSamplersCS[i].logicalTextureUnit);
+        stream->writeInt(mSamplersCS[i].textureType);
+    }
+
+    stream->writeInt(mUsedVertexSamplerRange);
+    stream->writeInt(mUsedPixelSamplerRange);
+    stream->writeInt(mUsedComputeSamplerRange);
+
+    stream->writeInt(mD3DUniforms.size());
+    for (const D3DUniform *uniform : mD3DUniforms)
+    {
+        // Type, name and arraySize are redundant, so aren't stored in the binary.
+        stream->writeIntOrNegOne(uniform->psRegisterIndex);
+        stream->writeIntOrNegOne(uniform->vsRegisterIndex);
+        stream->writeIntOrNegOne(uniform->csRegisterIndex);
+        stream->writeInt(uniform->registerCount);
+        stream->writeInt(uniform->registerElement);
+    }
+
+    // Ensure we init the uniform block structure data if we should.
+    // http://anglebug.com/1637
+    ensureUniformBlocksInitialized();
+
+    stream->writeInt(mD3DUniformBlocks.size());
+    for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
+    {
+        stream->writeIntOrNegOne(uniformBlock.psRegisterIndex);
+        stream->writeIntOrNegOne(uniformBlock.vsRegisterIndex);
+        stream->writeIntOrNegOne(uniformBlock.csRegisterIndex);
+    }
+
+    stream->writeInt(mStreamOutVaryings.size());
+    for (const auto &varying : mStreamOutVaryings)
+    {
+        stream->writeString(varying.semanticName);
+        stream->writeInt(varying.semanticIndex);
+        stream->writeInt(varying.componentCount);
+        stream->writeInt(varying.outputSlot);
+    }
+
+    stream->writeString(mVertexHLSL);
+    stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
+                       sizeof(angle::CompilerWorkaroundsD3D));
+    stream->writeString(mPixelHLSL);
+    stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
+                       sizeof(angle::CompilerWorkaroundsD3D));
+    stream->writeInt(mUsesFragDepth);
+    stream->writeInt(mUsesPointSize);
+    stream->writeInt(mUsesFlatInterpolation);
+
+    const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
+    stream->writeInt(pixelShaderKey.size());
+    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
+         pixelShaderKeyIndex++)
+    {
+        const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
+        stream->writeInt(variable.type);
+        stream->writeString(variable.name);
+        stream->writeString(variable.source);
+        stream->writeInt(variable.outputIndex);
+    }
+
+    stream->writeString(mGeometryShaderPreamble);
+
+    stream->writeInt(mVertexExecutables.size());
+    for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
+         vertexExecutableIndex++)
+    {
+        VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
+
+        const auto &inputLayout = vertexExecutable->inputs();
+        stream->writeInt(inputLayout.size());
+
+        for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
+        {
+            stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex]));
+        }
+
+        size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
+        stream->writeInt(vertexShaderSize);
+
+        const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
+        stream->writeBytes(vertexBlob, vertexShaderSize);
+    }
+
+    stream->writeInt(mPixelExecutables.size());
+    for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
+         pixelExecutableIndex++)
+    {
+        PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
+
+        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);
+    }
+
+    for (auto const &geometryExecutable : mGeometryExecutables)
+    {
+        if (!geometryExecutable)
+        {
+            stream->writeInt(0);
+            continue;
+        }
+
+        size_t geometryShaderSize = geometryExecutable->getLength();
+        stream->writeInt(geometryShaderSize);
+        stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
+    }
+
+    if (mComputeExecutable)
+    {
+        size_t computeShaderSize = mComputeExecutable->getLength();
+        stream->writeInt(computeShaderSize);
+        stream->writeBytes(mComputeExecutable->getFunction(), computeShaderSize);
+    }
+    else
+    {
+        stream->writeInt(0);
+    }
+
+    return gl::NoError();
+}
+
+void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
+{
+}
+
+void ProgramD3D::setSeparable(bool /* separable */)
+{
+}
+
+gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
+                                                       ShaderExecutableD3D **outExecutable)
+{
+    mPixelShaderOutputFormatCache.clear();
+
+    const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
+    const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender();
+
+    for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
+    {
+        const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
+
+        if (colorbuffer)
+        {
+            mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK
+                                                        ? GL_COLOR_ATTACHMENT0
+                                                        : colorbuffer->getBinding());
+        }
+        else
+        {
+            mPixelShaderOutputFormatCache.push_back(GL_NONE);
+        }
+    }
+
+    return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
+}
+
+gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
+                                                        ShaderExecutableD3D **outExectuable,
+                                                        gl::InfoLog *infoLog)
+{
+    for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
+    {
+        if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
+        {
+            *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
+            return gl::NoError();
+        }
+    }
+
+    std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
+        mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
+
+    // Generate new pixel executable
+    ShaderExecutableD3D *pixelExecutable = nullptr;
+
+    gl::InfoLog tempInfoLog;
+    gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+    ANGLE_TRY(mRenderer->compileToExecutable(
+        *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings,
+        (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
+        &pixelExecutable));
+
+    if (pixelExecutable)
+    {
+        mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
+            new PixelExecutable(outputSignature, pixelExecutable)));
+    }
+    else if (!infoLog)
+    {
+        ERR() << "Error compiling dynamic pixel executable:" << std::endl
+              << tempInfoLog.str() << std::endl;
+    }
+
+    *outExectuable = pixelExecutable;
+    return gl::NoError();
+}
+
+gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
+                                                        ShaderExecutableD3D **outExectuable,
+                                                        gl::InfoLog *infoLog)
+{
+    VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
+
+    for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
+    {
+        if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
+        {
+            *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
+            return gl::NoError();
+        }
+    }
+
+    // Generate new dynamic layout with attribute conversions
+    std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
+        mVertexHLSL, inputLayout, mState.getAttributes());
+
+    // Generate new vertex executable
+    ShaderExecutableD3D *vertexExecutable = nullptr;
+
+    gl::InfoLog tempInfoLog;
+    gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+    ANGLE_TRY(mRenderer->compileToExecutable(
+        *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings,
+        (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
+        &vertexExecutable));
+
+    if (vertexExecutable)
+    {
+        mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
+            new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable)));
+    }
+    else if (!infoLog)
+    {
+        ERR() << "Error compiling dynamic vertex executable:" << std::endl
+              << tempInfoLog.str() << std::endl;
+    }
+
+    *outExectuable = vertexExecutable;
+    return gl::NoError();
+}
+
+gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::ContextState &data,
+                                                            GLenum drawMode,
+                                                            ShaderExecutableD3D **outExecutable,
+                                                            gl::InfoLog *infoLog)
+{
+    if (outExecutable)
+    {
+        *outExecutable = nullptr;
+    }
+
+    // Return a null shader if the current rendering doesn't use a geometry shader
+    if (!usesGeometryShader(drawMode))
+    {
+        return gl::NoError();
+    }
+
+    gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
+
+    if (mGeometryExecutables[geometryShaderType])
+    {
+        if (outExecutable)
+        {
+            *outExecutable = mGeometryExecutables[geometryShaderType].get();
+        }
+        return gl::NoError();
+    }
+
+    std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
+        geometryShaderType, data, mState, mRenderer->presentPathFastEnabled(),
+        mGeometryShaderPreamble);
+
+    gl::InfoLog tempInfoLog;
+    gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+    ShaderExecutableD3D *geometryExecutable = nullptr;
+    gl::Error error                         = mRenderer->compileToExecutable(
+        *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings,
+        (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
+        angle::CompilerWorkaroundsD3D(), &geometryExecutable);
+
+    if (!infoLog && error.isError())
+    {
+        ERR() << "Error compiling dynamic geometry executable:" << std::endl
+              << tempInfoLog.str() << std::endl;
+    }
+
+    if (geometryExecutable != nullptr)
+    {
+        mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
+    }
+
+    if (outExecutable)
+    {
+        *outExecutable = mGeometryExecutables[geometryShaderType].get();
+    }
+    return error;
+}
+
+class ProgramD3D::GetExecutableTask : public Closure
+{
+  public:
+    GetExecutableTask(ProgramD3D *program)
+        : mProgram(program), mError(GL_NO_ERROR), mInfoLog(), mResult(nullptr)
+    {
+    }
+
+    virtual gl::Error run() = 0;
+
+    void operator()() override { mError = run(); }
+
+    const gl::Error &getError() const { return mError; }
+    const gl::InfoLog &getInfoLog() const { return mInfoLog; }
+    ShaderExecutableD3D *getResult() { return mResult; }
+
+  protected:
+    ProgramD3D *mProgram;
+    gl::Error mError;
+    gl::InfoLog mInfoLog;
+    ShaderExecutableD3D *mResult;
+};
+
+class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
+{
+  public:
+    GetVertexExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
+    gl::Error run() override
+    {
+        const auto &defaultInputLayout =
+            GetDefaultInputLayoutFromShader(mProgram->mState.getAttachedVertexShader());
+
+        ANGLE_TRY(
+            mProgram->getVertexExecutableForInputLayout(defaultInputLayout, &mResult, &mInfoLog));
+
+        return gl::NoError();
+    }
+};
+
+class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
+{
+  public:
+    GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
+    gl::Error run() override
+    {
+        const auto &defaultPixelOutput =
+            GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey());
+
+        ANGLE_TRY(
+            mProgram->getPixelExecutableForOutputLayout(defaultPixelOutput, &mResult, &mInfoLog));
+
+        return gl::NoError();
+    }
+};
+
+class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
+{
+  public:
+    GetGeometryExecutableTask(ProgramD3D *program, const gl::ContextState &contextState)
+        : GetExecutableTask(program), mContextState(contextState)
+    {
+    }
+
+    gl::Error run() override
+    {
+        // Auto-generate the geometry shader here, if we expect to be using point rendering in
+        // D3D11.
+        if (mProgram->usesGeometryShader(GL_POINTS))
+        {
+            ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(mContextState, GL_POINTS,
+                                                                      &mResult, &mInfoLog));
+        }
+
+        return gl::NoError();
+    }
+
+  private:
+    const gl::ContextState &mContextState;
+};
+
+gl::Error ProgramD3D::getComputeExecutable(ShaderExecutableD3D **outExecutable)
+{
+    if (outExecutable)
+    {
+        *outExecutable = mComputeExecutable.get();
+    }
+
+    return gl::NoError();
+}
+
+LinkResult ProgramD3D::compileProgramExecutables(const gl::ContextState &contextState,
+                                                 gl::InfoLog &infoLog)
+{
+    // Ensure the compiler is initialized to avoid race conditions.
+    ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
+
+    WorkerThreadPool *workerPool = mRenderer->getWorkerThreadPool();
+
+    GetVertexExecutableTask vertexTask(this);
+    GetPixelExecutableTask pixelTask(this);
+    GetGeometryExecutableTask geometryTask(this, contextState);
+
+    std::array<WaitableEvent, 3> waitEvents = {{workerPool->postWorkerTask(&vertexTask),
+                                                workerPool->postWorkerTask(&pixelTask),
+                                                workerPool->postWorkerTask(&geometryTask)}};
+
+    WaitableEvent::WaitMany(&waitEvents);
+
+    infoLog << vertexTask.getInfoLog().str();
+    infoLog << pixelTask.getInfoLog().str();
+    infoLog << geometryTask.getInfoLog().str();
+
+    ANGLE_TRY(vertexTask.getError());
+    ANGLE_TRY(pixelTask.getError());
+    ANGLE_TRY(geometryTask.getError());
+
+    ShaderExecutableD3D *defaultVertexExecutable = vertexTask.getResult();
+    ShaderExecutableD3D *defaultPixelExecutable  = pixelTask.getResult();
+    ShaderExecutableD3D *pointGS                 = geometryTask.getResult();
+
+    const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
+
+    if (usesGeometryShader(GL_POINTS) && pointGS)
+    {
+        // Geometry shaders are currently only used internally, so there is no corresponding shader
+        // object at the interface level. For now the geometry shader debug info is prepended to
+        // the vertex shader.
+        vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
+        vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo());
+        vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
+    }
+
+    if (defaultVertexExecutable)
+    {
+        vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
+    }
+
+    if (defaultPixelExecutable)
+    {
+        const ShaderD3D *fragmentShaderD3D =
+            GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
+        fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
+    }
+
+    return (defaultVertexExecutable && defaultPixelExecutable &&
+            (!usesGeometryShader(GL_POINTS) || pointGS));
+}
+
+LinkResult ProgramD3D::compileComputeExecutable(gl::InfoLog &infoLog)
+{
+    // Ensure the compiler is initialized to avoid race conditions.
+    ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
+
+    std::string computeShader = mDynamicHLSL->generateComputeShaderLinkHLSL(mState);
+
+    ShaderExecutableD3D *computeExecutable = nullptr;
+    ANGLE_TRY(mRenderer->compileToExecutable(infoLog, computeShader, SHADER_COMPUTE,
+                                             std::vector<D3DVarying>(), false,
+                                             angle::CompilerWorkaroundsD3D(), &computeExecutable));
+
+    if (computeExecutable == nullptr)
+    {
+        ERR() << "Error compiling dynamic compute executable:" << std::endl
+              << infoLog.str() << std::endl;
+    }
+    else
+    {
+        const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
+        computeShaderD3D->appendDebugInfo(computeExecutable->getDebugInfo());
+        mComputeExecutable.reset(computeExecutable);
+    }
+
+    return mComputeExecutable.get() != nullptr;
+}
+
+LinkResult ProgramD3D::link(ContextImpl *contextImpl,
+                            const gl::VaryingPacking &packing,
+                            gl::InfoLog &infoLog)
+{
+    const auto &data = contextImpl->getContextState();
+
+    reset();
+
+    const gl::Shader *computeShader = mState.getAttachedComputeShader();
+    if (computeShader)
+    {
+        mSamplersCS.resize(data.getCaps().maxComputeTextureImageUnits);
+
+        defineUniformsAndAssignRegisters();
+
+        LinkResult result = compileComputeExecutable(infoLog);
+        if (result.isError())
+        {
+            infoLog << result.getError().getMessage();
+            return result;
+        }
+        else if (!result.getResult())
+        {
+            infoLog << "Failed to create D3D compute shader.";
+            return result;
+        }
+
+        initUniformBlockInfo(computeShader);
+    }
+    else
+    {
+        const gl::Shader *vertexShader   = mState.getAttachedVertexShader();
+        const gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
+
+        const ShaderD3D *vertexShaderD3D   = GetImplAs<ShaderD3D>(vertexShader);
+        const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
+
+        mSamplersVS.resize(data.getCaps().maxVertexTextureImageUnits);
+        mSamplersPS.resize(data.getCaps().maxTextureImageUnits);
+
+        vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
+        fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
+
+        if (mRenderer->getNativeLimitations().noFrontFacingSupport)
+        {
+            if (fragmentShaderD3D->usesFrontFacing())
+            {
+                infoLog << "The current renderer doesn't support gl_FrontFacing";
+                return false;
+            }
+        }
+
+        // TODO(jmadill): Implement more sophisticated component packing in D3D9.
+        // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings
+        // intelligently, but D3D9 assumes one semantic per register.
+        if (mRenderer->getRendererClass() == RENDERER_D3D9 &&
+            packing.getMaxSemanticIndex() > data.getCaps().maxVaryingVectors)
+        {
+            infoLog << "Cannot pack these varyings on D3D9.";
+            return false;
+        }
+
+        ProgramD3DMetadata metadata(mRenderer, vertexShaderD3D, fragmentShaderD3D);
+        BuiltinVaryingsD3D builtins(metadata, packing);
+
+        mDynamicHLSL->generateShaderLinkHLSL(data, mState, metadata, packing, builtins, &mPixelHLSL,
+                                             &mVertexHLSL);
+
+        mUsesPointSize = vertexShaderD3D->usesPointSize();
+        mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
+        mUsesFragDepth = metadata.usesFragDepth();
+
+        // Cache if we use flat shading
+        mUsesFlatInterpolation = (FindFlatInterpolationVarying(fragmentShader->getVaryings()) ||
+                                  FindFlatInterpolationVarying(vertexShader->getVaryings()));
+
+        if (mRenderer->getMajorShaderModel() >= 4)
+        {
+            mGeometryShaderPreamble =
+                mDynamicHLSL->generateGeometryShaderPreamble(packing, builtins);
+        }
+
+        initAttribLocationsToD3DSemantic();
+
+        defineUniformsAndAssignRegisters();
+
+        gatherTransformFeedbackVaryings(packing, builtins[SHADER_VERTEX]);
+
+        LinkResult result = compileProgramExecutables(data, infoLog);
+        if (result.isError())
+        {
+            infoLog << result.getError().getMessage();
+            return result;
+        }
+        else if (!result.getResult())
+        {
+            infoLog << "Failed to create D3D shaders.";
+            return result;
+        }
+
+        initUniformBlockInfo(vertexShader);
+        initUniformBlockInfo(fragmentShader);
+    }
+
+    return true;
+}
+
+GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
+{
+    // TODO(jmadill): Do something useful here?
+    return GL_TRUE;
+}
+
+void ProgramD3D::initUniformBlockInfo(const gl::Shader *shader)
+{
+    for (const sh::InterfaceBlock &interfaceBlock : shader->getInterfaceBlocks())
+    {
+        if (!interfaceBlock.staticUse && interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED)
+            continue;
+
+        if (mBlockDataSizes.count(interfaceBlock.name) > 0)
+            continue;
+
+        size_t dataSize                      = getUniformBlockInfo(interfaceBlock);
+        mBlockDataSizes[interfaceBlock.name] = dataSize;
+    }
+}
+
+void ProgramD3D::ensureUniformBlocksInitialized()
+{
+    // Lazy init.
+    if (mState.getUniformBlocks().empty() || !mD3DUniformBlocks.empty())
+    {
+        return;
+    }
+
+    // Assign registers and update sizes.
+    const ShaderD3D *vertexShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
+    const ShaderD3D *fragmentShaderD3D =
+        SafeGetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
+    const ShaderD3D *computeShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
+
+    for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
+    {
+        unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
+
+        D3DUniformBlock d3dUniformBlock;
+
+        if (uniformBlock.vertexStaticUse)
+        {
+            ASSERT(vertexShaderD3D != nullptr);
+            unsigned int baseRegister =
+                vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
+            d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
+        }
+
+        if (uniformBlock.fragmentStaticUse)
+        {
+            ASSERT(fragmentShaderD3D != nullptr);
+            unsigned int baseRegister =
+                fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
+            d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
+        }
+
+        if (uniformBlock.computeStaticUse)
+        {
+            ASSERT(computeShaderD3D != nullptr);
+            unsigned int baseRegister =
+                computeShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
+            d3dUniformBlock.csRegisterIndex = baseRegister + uniformBlockElement;
+        }
+
+        mD3DUniformBlocks.push_back(d3dUniformBlock);
+    }
+}
+
+void ProgramD3D::initializeUniformStorage()
+{
+    // Compute total default block size
+    unsigned int vertexRegisters   = 0;
+    unsigned int fragmentRegisters = 0;
+    unsigned int computeRegisters  = 0;
+    for (const D3DUniform *d3dUniform : mD3DUniforms)
+    {
+        if (!d3dUniform->isSampler())
+        {
+            if (d3dUniform->isReferencedByVertexShader())
+            {
+                vertexRegisters = std::max(vertexRegisters,
+                                           d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
+            }
+            if (d3dUniform->isReferencedByFragmentShader())
+            {
+                fragmentRegisters = std::max(
+                    fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
+            }
+            if (d3dUniform->isReferencedByComputeShader())
+            {
+                computeRegisters = std::max(
+                    computeRegisters, d3dUniform->csRegisterIndex + d3dUniform->registerCount);
+            }
+        }
+    }
+
+    mVertexUniformStorage =
+        std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(vertexRegisters * 16u));
+    mFragmentUniformStorage = std::unique_ptr<UniformStorageD3D>(
+        mRenderer->createUniformStorage(fragmentRegisters * 16u));
+    mComputeUniformStorage =
+        std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(computeRegisters * 16u));
+}
+
+gl::Error ProgramD3D::applyUniforms(GLenum drawMode)
+{
+    ASSERT(!mDirtySamplerMapping);
+
+    ANGLE_TRY(mRenderer->applyUniforms(*this, drawMode, mD3DUniforms));
+
+    for (D3DUniform *d3dUniform : mD3DUniforms)
+    {
+        d3dUniform->dirty = false;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error ProgramD3D::applyComputeUniforms()
+{
+    ASSERT(!mDirtySamplerMapping);
+    ANGLE_TRY(mRenderer->applyComputeUniforms(*this, mD3DUniforms));
+
+    for (D3DUniform *d3dUniform : mD3DUniforms)
+    {
+        d3dUniform->dirty = false;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error ProgramD3D::applyUniformBuffers(const gl::ContextState &data)
+{
+    if (mState.getUniformBlocks().empty())
+    {
+        return gl::NoError();
+    }
+
+    ensureUniformBlocksInitialized();
+
+    mVertexUBOCache.clear();
+    mFragmentUBOCache.clear();
+
+    const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
+    const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
+
+    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
+         uniformBlockIndex++)
+    {
+        const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
+        GLuint blockBinding                 = mState.getUniformBlockBinding(uniformBlockIndex);
+
+        // Unnecessary to apply an unreferenced standard or shared UBO
+        if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
+        {
+            continue;
+        }
+
+        if (uniformBlock.vertexStaticUse())
+        {
+            unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
+            ASSERT(registerIndex < data.getCaps().maxVertexUniformBlocks);
+
+            if (mVertexUBOCache.size() <= registerIndex)
+            {
+                mVertexUBOCache.resize(registerIndex + 1, -1);
+            }
+
+            ASSERT(mVertexUBOCache[registerIndex] == -1);
+            mVertexUBOCache[registerIndex] = blockBinding;
+        }
+
+        if (uniformBlock.fragmentStaticUse())
+        {
+            unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
+            ASSERT(registerIndex < data.getCaps().maxFragmentUniformBlocks);
+
+            if (mFragmentUBOCache.size() <= registerIndex)
+            {
+                mFragmentUBOCache.resize(registerIndex + 1, -1);
+            }
+
+            ASSERT(mFragmentUBOCache[registerIndex] == -1);
+            mFragmentUBOCache[registerIndex] = blockBinding;
+        }
+    }
+
+    return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
+}
+
+void ProgramD3D::dirtyAllUniforms()
+{
+    for (D3DUniform *d3dUniform : mD3DUniforms)
+    {
+        d3dUniform->dirty = true;
+    }
+}
+
+void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    setUniform(location, count, v, GL_FLOAT);
+}
+
+void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    setUniform(location, count, v, GL_FLOAT_VEC2);
+}
+
+void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    setUniform(location, count, v, GL_FLOAT_VEC3);
+}
+
+void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    setUniform(location, count, v, GL_FLOAT_VEC4);
+}
+
+void ProgramD3D::setUniformMatrix2fv(GLint location,
+                                     GLsizei count,
+                                     GLboolean transpose,
+                                     const GLfloat *value)
+{
+    setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
+}
+
+void ProgramD3D::setUniformMatrix3fv(GLint location,
+                                     GLsizei count,
+                                     GLboolean transpose,
+                                     const GLfloat *value)
+{
+    setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
+}
+
+void ProgramD3D::setUniformMatrix4fv(GLint location,
+                                     GLsizei count,
+                                     GLboolean transpose,
+                                     const GLfloat *value)
+{
+    setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
+}
+
+void ProgramD3D::setUniformMatrix2x3fv(GLint location,
+                                       GLsizei count,
+                                       GLboolean transpose,
+                                       const GLfloat *value)
+{
+    setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
+}
+
+void ProgramD3D::setUniformMatrix3x2fv(GLint location,
+                                       GLsizei count,
+                                       GLboolean transpose,
+                                       const GLfloat *value)
+{
+    setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
+}
+
+void ProgramD3D::setUniformMatrix2x4fv(GLint location,
+                                       GLsizei count,
+                                       GLboolean transpose,
+                                       const GLfloat *value)
+{
+    setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
+}
+
+void ProgramD3D::setUniformMatrix4x2fv(GLint location,
+                                       GLsizei count,
+                                       GLboolean transpose,
+                                       const GLfloat *value)
+{
+    setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
+}
+
+void ProgramD3D::setUniformMatrix3x4fv(GLint location,
+                                       GLsizei count,
+                                       GLboolean transpose,
+                                       const GLfloat *value)
+{
+    setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
+}
+
+void ProgramD3D::setUniformMatrix4x3fv(GLint location,
+                                       GLsizei count,
+                                       GLboolean transpose,
+                                       const GLfloat *value)
+{
+    setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
+}
+
+void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+    setUniform(location, count, v, GL_INT);
+}
+
+void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+    setUniform(location, count, v, GL_INT_VEC2);
+}
+
+void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+    setUniform(location, count, v, GL_INT_VEC3);
+}
+
+void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+    setUniform(location, count, v, GL_INT_VEC4);
+}
+
+void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    setUniform(location, count, v, GL_UNSIGNED_INT);
+}
+
+void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
+}
+
+void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
+}
+
+void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
+}
+
+void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
+                                        GLuint /*uniformBlockBinding*/)
+{
+}
+
+void ProgramD3D::defineUniformsAndAssignRegisters()
+{
+    D3DUniformMap uniformMap;
+    const gl::Shader *computeShader = mState.getAttachedComputeShader();
+    if (computeShader)
+    {
+        for (const sh::Uniform &computeUniform : computeShader->getUniforms())
+        {
+            if (computeUniform.staticUse)
+            {
+                defineUniformBase(computeShader, computeUniform, &uniformMap);
+            }
+        }
+    }
+    else
+    {
+        const gl::Shader *vertexShader = mState.getAttachedVertexShader();
+        for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
+        {
+            if (vertexUniform.staticUse)
+            {
+                defineUniformBase(vertexShader, vertexUniform, &uniformMap);
+            }
+        }
+
+        const gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
+        for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
+        {
+            if (fragmentUniform.staticUse)
+            {
+                defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
+            }
+        }
+    }
+
+    // Initialize the D3DUniform list to mirror the indexing of the GL layer.
+    for (const gl::LinkedUniform &glUniform : mState.getUniforms())
+    {
+        if (!glUniform.isInDefaultBlock())
+            continue;
+
+        auto mapEntry = uniformMap.find(glUniform.name);
+        ASSERT(mapEntry != uniformMap.end());
+        mD3DUniforms.push_back(mapEntry->second);
+    }
+
+    assignAllSamplerRegisters();
+    initializeUniformStorage();
+}
+
+void ProgramD3D::defineUniformBase(const gl::Shader *shader,
+                                   const sh::Uniform &uniform,
+                                   D3DUniformMap *uniformMap)
+{
+    // Samplers get their registers assigned in assignAllSamplerRegisters.
+    if (uniform.isBuiltIn() || gl::IsSamplerType(uniform.type))
+    {
+        defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
+        return;
+    }
+
+    const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
+
+    unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
+    ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
+    sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
+    encoder.skipRegisters(startRegister);
+
+    defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
+}
+
+D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
+{
+    for (D3DUniform *d3dUniform : mD3DUniforms)
+    {
+        if (d3dUniform->name == name)
+        {
+            return d3dUniform;
+        }
+    }
+
+    return nullptr;
+}
+
+void ProgramD3D::defineUniform(GLenum shaderType,
+                               const sh::ShaderVariable &uniform,
+                               const std::string &fullName,
+                               sh::HLSLBlockEncoder *encoder,
+                               D3DUniformMap *uniformMap)
+{
+    if (uniform.isStruct())
+    {
+        for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
+        {
+            const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
+
+            if (encoder)
+                encoder->enterAggregateType();
+
+            for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
+            {
+                const sh::ShaderVariable &field  = uniform.fields[fieldIndex];
+                const std::string &fieldFullName = (fullName + elementString + "." + field.name);
+
+                // Samplers get their registers assigned in assignAllSamplerRegisters.
+                // Also they couldn't use the same encoder as the rest of the struct, since they are
+                // extracted out of the struct by the shader translator.
+                if (gl::IsSamplerType(field.type))
+                {
+                    defineUniform(shaderType, field, fieldFullName, nullptr, uniformMap);
+                }
+                else
+                {
+                    defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
+                }
+            }
+
+            if (encoder)
+                encoder->exitAggregateType();
+        }
+        return;
+    }
+
+    // Not a struct. Arrays are treated as aggregate types.
+    if (uniform.isArray() && encoder)
+    {
+        encoder->enterAggregateType();
+    }
+
+    // Advance the uniform offset, to track registers allocation for structs
+    sh::BlockMemberInfo blockInfo =
+        encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
+                : sh::BlockMemberInfo::getDefaultBlockInfo();
+
+    auto uniformMapEntry   = uniformMap->find(fullName);
+    D3DUniform *d3dUniform = nullptr;
+
+    if (uniformMapEntry != uniformMap->end())
+    {
+        d3dUniform = uniformMapEntry->second;
+    }
+    else
+    {
+        d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
+        (*uniformMap)[fullName] = d3dUniform;
+    }
+
+    if (encoder)
+    {
+        d3dUniform->registerElement =
+            static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
+        unsigned int reg =
+            static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
+        if (shaderType == GL_FRAGMENT_SHADER)
+        {
+            d3dUniform->psRegisterIndex = reg;
+        }
+        else if (shaderType == GL_VERTEX_SHADER)
+        {
+            d3dUniform->vsRegisterIndex = reg;
+        }
+        else
+        {
+            ASSERT(shaderType == GL_COMPUTE_SHADER);
+            d3dUniform->csRegisterIndex = reg;
+        }
+
+        // Arrays are treated as aggregate types
+        if (uniform.isArray())
+        {
+            encoder->exitAggregateType();
+        }
+    }
+}
+
+template <typename T>
+void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
+{
+    const int components        = gl::VariableComponentCount(targetUniformType);
+    const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
+
+    D3DUniform *targetUniform = getD3DUniformFromLocation(location);
+
+    unsigned int elementCount = targetUniform->elementCount();
+    unsigned int arrayElement = mState.getUniformLocations()[location].element;
+    unsigned int count        = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
+
+    if (targetUniform->type == targetUniformType)
+    {
+        T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
+
+        for (unsigned int i = 0; i < count; i++)
+        {
+            T *dest         = target + (i * 4);
+            const T *source = v + (i * components);
+
+            for (int c = 0; c < components; c++)
+            {
+                SetIfDirty(dest + c, source[c], &targetUniform->dirty);
+            }
+            for (int c = components; c < 4; c++)
+            {
+                SetIfDirty(dest + c, T(0), &targetUniform->dirty);
+            }
+        }
+    }
+    else if (targetUniform->type == targetBoolType)
+    {
+        GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
+
+        for (unsigned int i = 0; i < count; i++)
+        {
+            GLint *dest     = boolParams + (i * 4);
+            const T *source = v + (i * components);
+
+            for (int c = 0; c < components; c++)
+            {
+                SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE,
+                           &targetUniform->dirty);
+            }
+            for (int c = components; c < 4; c++)
+            {
+                SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
+            }
+        }
+    }
+    else if (targetUniform->isSampler())
+    {
+        ASSERT(targetUniformType == GL_INT);
+
+        GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
+
+        bool wasDirty = targetUniform->dirty;
+
+        for (unsigned int i = 0; i < count; i++)
+        {
+            GLint *dest         = target + (i * 4);
+            const GLint *source = reinterpret_cast<const GLint *>(v) + (i * components);
+
+            SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
+            SetIfDirty(dest + 1, 0, &targetUniform->dirty);
+            SetIfDirty(dest + 2, 0, &targetUniform->dirty);
+            SetIfDirty(dest + 3, 0, &targetUniform->dirty);
+        }
+
+        if (!wasDirty && targetUniform->dirty)
+        {
+            mDirtySamplerMapping = true;
+        }
+    }
+    else
+        UNREACHABLE();
+}
+
+template <int cols, int rows>
+void ProgramD3D::setUniformMatrixfv(GLint location,
+                                    GLsizei countIn,
+                                    GLboolean transpose,
+                                    const GLfloat *value,
+                                    GLenum targetUniformType)
+{
+    D3DUniform *targetUniform = getD3DUniformFromLocation(location);
+
+    unsigned int elementCount = targetUniform->elementCount();
+    unsigned int arrayElement = mState.getUniformLocations()[location].element;
+    unsigned int count        = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
+
+    const unsigned int targetMatrixStride = (4 * rows);
+    GLfloat *target =
+        (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
+
+    for (unsigned int i = 0; i < count; i++)
+    {
+        // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
+        if (transpose == GL_FALSE)
+        {
+            targetUniform->dirty =
+                TransposeExpandMatrix<GLfloat, cols, rows>(target, value) || targetUniform->dirty;
+        }
+        else
+        {
+            targetUniform->dirty =
+                ExpandMatrix<GLfloat, cols, rows>(target, value) || targetUniform->dirty;
+        }
+        target += targetMatrixStride;
+        value += cols * rows;
+    }
+}
+
+size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
+{
+    ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
+
+    // define member uniforms
+    sh::Std140BlockEncoder std140Encoder;
+    sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
+    sh::BlockLayoutEncoder *encoder = nullptr;
+
+    if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
+    {
+        encoder = &std140Encoder;
+    }
+    else
+    {
+        encoder = &hlslEncoder;
+    }
+
+    GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
+                        interfaceBlock.isRowMajorLayout, &mBlockInfo);
+
+    return encoder->getBlockSize();
+}
+
+void ProgramD3D::assignAllSamplerRegisters()
+{
+    for (D3DUniform *d3dUniform : mD3DUniforms)
+    {
+        if (d3dUniform->isSampler())
+        {
+            assignSamplerRegisters(d3dUniform);
+        }
+    }
+}
+
+void ProgramD3D::assignSamplerRegisters(D3DUniform *d3dUniform)
+{
+    ASSERT(d3dUniform->isSampler());
+    const gl::Shader *computeShader = mState.getAttachedComputeShader();
+    if (computeShader)
+    {
+        const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
+        ASSERT(computeShaderD3D->hasUniform(d3dUniform));
+        d3dUniform->csRegisterIndex = computeShaderD3D->getUniformRegister(d3dUniform->name);
+        ASSERT(d3dUniform->csRegisterIndex != GL_INVALID_INDEX);
+        AssignSamplers(d3dUniform->csRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
+                       mSamplersCS, &mUsedComputeSamplerRange);
+    }
+    else
+    {
+        const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
+        const ShaderD3D *fragmentShaderD3D =
+            GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
+        ASSERT(vertexShaderD3D->hasUniform(d3dUniform) ||
+               fragmentShaderD3D->hasUniform(d3dUniform));
+        if (vertexShaderD3D->hasUniform(d3dUniform))
+        {
+            d3dUniform->vsRegisterIndex = vertexShaderD3D->getUniformRegister(d3dUniform->name);
+            ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX);
+            AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
+                           mSamplersVS, &mUsedVertexSamplerRange);
+        }
+        if (fragmentShaderD3D->hasUniform(d3dUniform))
+        {
+            d3dUniform->psRegisterIndex = fragmentShaderD3D->getUniformRegister(d3dUniform->name);
+            ASSERT(d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
+            AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
+                           mSamplersPS, &mUsedPixelSamplerRange);
+        }
+    }
+}
+
+// static
+void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
+                                GLenum samplerType,
+                                unsigned int samplerCount,
+                                std::vector<Sampler> &outSamplers,
+                                GLuint *outUsedRange)
+{
+    unsigned int samplerIndex = startSamplerIndex;
+
+    do
+    {
+        ASSERT(samplerIndex < outSamplers.size());
+        Sampler *sampler            = &outSamplers[samplerIndex];
+        sampler->active             = true;
+        sampler->textureType        = gl::SamplerTypeToTextureType(samplerType);
+        sampler->logicalTextureUnit = 0;
+        *outUsedRange               = std::max(samplerIndex + 1, *outUsedRange);
+        samplerIndex++;
+    } while (samplerIndex < startSamplerIndex + samplerCount);
+}
+
+void ProgramD3D::reset()
+{
+    mVertexExecutables.clear();
+    mPixelExecutables.clear();
+
+    for (auto &geometryExecutable : mGeometryExecutables)
+    {
+        geometryExecutable.reset(nullptr);
+    }
+
+    mComputeExecutable.reset(nullptr);
+
+    mVertexHLSL.clear();
+    mVertexWorkarounds = angle::CompilerWorkaroundsD3D();
+
+    mPixelHLSL.clear();
+    mPixelWorkarounds = angle::CompilerWorkaroundsD3D();
+    mUsesFragDepth = false;
+    mPixelShaderKey.clear();
+    mUsesPointSize = false;
+    mUsesFlatInterpolation = false;
+
+    SafeDeleteContainer(mD3DUniforms);
+    mD3DUniformBlocks.clear();
+
+    mVertexUniformStorage.reset(nullptr);
+    mFragmentUniformStorage.reset(nullptr);
+    mComputeUniformStorage.reset(nullptr);
+
+    mSamplersPS.clear();
+    mSamplersVS.clear();
+    mSamplersCS.clear();
+
+    mUsedVertexSamplerRange = 0;
+    mUsedPixelSamplerRange  = 0;
+    mUsedComputeSamplerRange = 0;
+    mDirtySamplerMapping    = true;
+
+    mAttribLocationToD3DSemantic.fill(-1);
+
+    mStreamOutVaryings.clear();
+
+    mGeometryShaderPreamble.clear();
+}
+
+unsigned int ProgramD3D::getSerial() const
+{
+    return mSerial;
+}
+
+unsigned int ProgramD3D::issueSerial()
+{
+    return mCurrentSerial++;
+}
+
+void ProgramD3D::initAttribLocationsToD3DSemantic()
+{
+    const gl::Shader *vertexShader = mState.getAttachedVertexShader();
+    ASSERT(vertexShader != nullptr);
+
+    // Init semantic index
+    for (const sh::Attribute &attribute : mState.getAttributes())
+    {
+        int d3dSemantic = vertexShader->getSemanticIndex(attribute.name);
+        int regCount    = gl::VariableRegisterCount(attribute.type);
+
+        for (int reg = 0; reg < regCount; ++reg)
+        {
+            mAttribLocationToD3DSemantic[attribute.location + reg] = d3dSemantic + reg;
+        }
+    }
+}
+
+void ProgramD3D::updateCachedInputLayout(const gl::State &state)
+{
+    mCachedInputLayout.clear();
+    const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
+
+    for (size_t locationIndex : mState.getActiveAttribLocationsMask())
+    {
+        int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
+
+        if (d3dSemantic != -1)
+        {
+            if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
+            {
+                mCachedInputLayout.resize(d3dSemantic + 1, gl::VERTEX_FORMAT_INVALID);
+            }
+            mCachedInputLayout[d3dSemantic] =
+                GetVertexFormatType(vertexAttributes[locationIndex],
+                                    state.getVertexAttribCurrentValue(locationIndex).Type);
+        }
+    }
+}
+
+void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
+                                                 const BuiltinInfo &builtins)
+{
+    const std::string &varyingSemantic =
+        GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
+
+    // Gather the linked varyings that are used for transform feedback, they should all exist.
+    mStreamOutVaryings.clear();
+
+    const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames();
+    for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
+         ++outputSlot)
+    {
+        const auto &tfVaryingName = tfVaryingNames[outputSlot];
+        if (tfVaryingName == "gl_Position")
+        {
+            if (builtins.glPosition.enabled)
+            {
+                mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic,
+                                                        builtins.glPosition.index, 4, outputSlot));
+            }
+        }
+        else if (tfVaryingName == "gl_FragCoord")
+        {
+            if (builtins.glFragCoord.enabled)
+            {
+                mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic,
+                                                        builtins.glFragCoord.index, 4, outputSlot));
+            }
+        }
+        else if (tfVaryingName == "gl_PointSize")
+        {
+            if (builtins.glPointSize.enabled)
+            {
+                mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot));
+            }
+        }
+        else
+        {
+            size_t subscript     = GL_INVALID_INDEX;
+            std::string baseName = gl::ParseResourceName(tfVaryingName, &subscript);
+            for (const auto &registerInfo : varyingPacking.getRegisterList())
+            {
+                const auto &varying   = *registerInfo.packedVarying->varying;
+                GLenum transposedType = gl::TransposeMatrixType(varying.type);
+                int componentCount = gl::VariableColumnCount(transposedType);
+                ASSERT(!varying.isBuiltIn());
+
+                // Transform feedback for varying structs is underspecified.
+                // See Khronos bug 9856.
+                // TODO(jmadill): Figure out how to be spec-compliant here.
+                if (registerInfo.packedVarying->isStructField() || varying.isStruct())
+                    continue;
+
+                // There can be more than one register assigned to a particular varying, and each
+                // register needs its own stream out entry.
+                if (baseName == registerInfo.packedVarying->varying->name &&
+                    (subscript == GL_INVALID_INDEX || subscript == registerInfo.varyingArrayIndex))
+                {
+                    mStreamOutVaryings.push_back(D3DVarying(
+                        varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot));
+                }
+            }
+        }
+    }
+}
+
+D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
+{
+    return mD3DUniforms[mState.getUniformLocations()[location].index];
+}
+
+bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+    std::string baseName = blockName;
+    gl::ParseAndStripArrayIndex(&baseName);
+
+    auto sizeIter = mBlockDataSizes.find(baseName);
+    if (sizeIter == mBlockDataSizes.end())
+    {
+        *sizeOut = 0;
+        return false;
+    }
+
+    *sizeOut = sizeIter->second;
+    return true;
+}
+
+bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                           sh::BlockMemberInfo *memberInfoOut) const
+{
+    auto infoIter = mBlockInfo.find(memberUniformName);
+    if (infoIter == mBlockInfo.end())
+    {
+        *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+        return false;
+    }
+
+    *memberInfoOut = infoIter->second;
+    return true;
+}
+
+void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
+                                         GLenum genMode,
+                                         GLint components,
+                                         const GLfloat *coeffs)
+{
+    UNREACHABLE();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
new file mode 100644
index 0000000..19b7dbf
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -0,0 +1,452 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramD3D.h: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
+#define LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
+
+#include <string>
+#include <vector>
+
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "platform/WorkaroundsD3D.h"
+
+namespace rx
+{
+class RendererD3D;
+class UniformStorageD3D;
+class ShaderExecutableD3D;
+
+#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang.
+// It should only be used selectively to work around specific bugs.
+#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1
+#endif
+
+// Helper struct representing a single shader uniform
+struct D3DUniform : private angle::NonCopyable
+{
+    D3DUniform(GLenum typeIn,
+               const std::string &nameIn,
+               unsigned int arraySizeIn,
+               bool defaultBlock);
+    ~D3DUniform();
+
+    bool isSampler() const;
+    unsigned int elementCount() const { return std::max(1u, arraySize); }
+    bool isReferencedByVertexShader() const;
+    bool isReferencedByFragmentShader() const;
+    bool isReferencedByComputeShader() const;
+
+    // Duplicated from the GL layer
+    GLenum type;
+    std::string name;
+    unsigned int arraySize;
+
+    // Pointer to a system copy of the data.
+    // TODO(jmadill): remove this in favor of gl::LinkedUniform::data().
+    uint8_t *data;
+
+    // Has the data been updated since the last sync?
+    bool dirty;
+
+    // Register information.
+    unsigned int vsRegisterIndex;
+    unsigned int psRegisterIndex;
+    unsigned int csRegisterIndex;
+    unsigned int registerCount;
+
+    // Register "elements" are used for uniform structs in ES3, to appropriately identify single
+    // uniforms
+    // inside aggregate types, which are packed according C-like structure rules.
+    unsigned int registerElement;
+};
+
+struct D3DUniformBlock
+{
+    D3DUniformBlock()
+        : vsRegisterIndex(GL_INVALID_INDEX),
+          psRegisterIndex(GL_INVALID_INDEX),
+          csRegisterIndex(GL_INVALID_INDEX)
+    {
+    }
+
+    bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; }
+
+    bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; }
+
+    bool computeStaticUse() const { return csRegisterIndex != GL_INVALID_INDEX; }
+
+    unsigned int vsRegisterIndex;
+    unsigned int psRegisterIndex;
+    unsigned int csRegisterIndex;
+};
+
+struct D3DVarying final
+{
+    D3DVarying();
+    D3DVarying(const std::string &semanticNameIn,
+               unsigned int semanticIndexIn,
+               unsigned int componentCountIn,
+               unsigned int outputSlotIn);
+
+    D3DVarying(const D3DVarying &) = default;
+    D3DVarying &operator=(const D3DVarying &) = default;
+
+    std::string semanticName;
+    unsigned int semanticIndex;
+    unsigned int componentCount;
+    unsigned int outputSlot;
+};
+
+class ProgramD3DMetadata final : angle::NonCopyable
+{
+  public:
+    ProgramD3DMetadata(RendererD3D *renderer,
+                       const ShaderD3D *vertexShader,
+                       const ShaderD3D *fragmentShader);
+
+    int getRendererMajorShaderModel() const;
+    bool usesBroadcast(const gl::ContextState &data) const;
+    bool usesFragDepth() const;
+    bool usesPointCoord() const;
+    bool usesFragCoord() const;
+    bool usesPointSize() const;
+    bool usesInsertedPointCoordValue() const;
+    bool usesViewScale() const;
+    bool addsPointCoordToVertexShader() const;
+    bool usesTransformFeedbackGLPosition() const;
+    bool usesSystemValuePointSize() const;
+    bool usesMultipleFragmentOuts() const;
+    GLint getMajorShaderVersion() const;
+    const ShaderD3D *getFragmentShader() const;
+
+  private:
+    const int mRendererMajorShaderModel;
+    const std::string mShaderModelSuffix;
+    const bool mUsesInstancedPointSpriteEmulation;
+    const bool mUsesViewScale;
+    const ShaderD3D *mVertexShader;
+    const ShaderD3D *mFragmentShader;
+};
+
+class ProgramD3D : public ProgramImpl
+{
+  public:
+    ProgramD3D(const gl::ProgramState &data, RendererD3D *renderer);
+    virtual ~ProgramD3D();
+
+    const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
+
+    GLint getSamplerMapping(gl::SamplerType type,
+                            unsigned int samplerIndex,
+                            const gl::Caps &caps) const;
+    GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const;
+    GLuint getUsedSamplerRange(gl::SamplerType type) const;
+    void updateSamplerMapping();
+
+    bool usesPointSize() const { return mUsesPointSize; }
+    bool usesPointSpriteEmulation() const;
+    bool usesGeometryShader(GLenum drawMode) const;
+    bool usesInstancedPointSpriteEmulation() const;
+
+    LinkResult load(const ContextImpl *contextImpl,
+                    gl::InfoLog &infoLog,
+                    gl::BinaryInputStream *stream) override;
+    gl::Error save(gl::BinaryOutputStream *stream) override;
+    void setBinaryRetrievableHint(bool retrievable) override;
+    void setSeparable(bool separable) override;
+
+    gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
+                                               ShaderExecutableD3D **outExectuable);
+    gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout,
+                                                ShaderExecutableD3D **outExectuable,
+                                                gl::InfoLog *infoLog);
+    gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
+                                                ShaderExecutableD3D **outExectuable,
+                                                gl::InfoLog *infoLog);
+    gl::Error getGeometryExecutableForPrimitiveType(const gl::ContextState &data,
+                                                    GLenum drawMode,
+                                                    ShaderExecutableD3D **outExecutable,
+                                                    gl::InfoLog *infoLog);
+    gl::Error getComputeExecutable(ShaderExecutableD3D **outExecutable);
+    LinkResult link(ContextImpl *contextImpl,
+                    const gl::VaryingPacking &packing,
+                    gl::InfoLog &infoLog) override;
+    GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
+
+    bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+    bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                   sh::BlockMemberInfo *memberInfoOut) const override;
+    void setPathFragmentInputGen(const std::string &inputName,
+                                 GLenum genMode,
+                                 GLint components,
+                                 const GLfloat *coeffs) override;
+
+    void initializeUniformStorage();
+    gl::Error applyUniforms(GLenum drawMode);
+    gl::Error applyComputeUniforms();
+    gl::Error applyUniformBuffers(const gl::ContextState &data);
+    void dirtyAllUniforms();
+
+    void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform1iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform2iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform3iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform4iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniformMatrix2fv(GLint location,
+                             GLsizei count,
+                             GLboolean transpose,
+                             const GLfloat *value);
+    void setUniformMatrix3fv(GLint location,
+                             GLsizei count,
+                             GLboolean transpose,
+                             const GLfloat *value);
+    void setUniformMatrix4fv(GLint location,
+                             GLsizei count,
+                             GLboolean transpose,
+                             const GLfloat *value);
+    void setUniformMatrix2x3fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value);
+    void setUniformMatrix3x2fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value);
+    void setUniformMatrix2x4fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value);
+    void setUniformMatrix4x2fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value);
+    void setUniformMatrix3x4fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value);
+    void setUniformMatrix4x3fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value);
+
+    void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
+
+    const UniformStorageD3D &getVertexUniformStorage() const
+    {
+        return *mVertexUniformStorage.get();
+    }
+    const UniformStorageD3D &getFragmentUniformStorage() const
+    {
+        return *mFragmentUniformStorage.get();
+    }
+    const UniformStorageD3D &getComputeUniformStorage() const
+    {
+        return *mComputeUniformStorage.get();
+    }
+
+    unsigned int getSerial() const;
+
+    const AttribIndexArray &getAttribLocationToD3DSemantics() const
+    {
+        return mAttribLocationToD3DSemantic;
+    }
+
+    void updateCachedInputLayout(const gl::State &state);
+    const gl::InputLayout &getCachedInputLayout() const { return mCachedInputLayout; }
+
+    bool isSamplerMappingDirty() { return mDirtySamplerMapping; }
+
+  private:
+    // These forward-declared tasks are used for multi-thread shader compiles.
+    class GetExecutableTask;
+    class GetVertexExecutableTask;
+    class GetPixelExecutableTask;
+    class GetGeometryExecutableTask;
+
+    class VertexExecutable
+    {
+      public:
+        enum HLSLAttribType
+        {
+            FLOAT,
+            UNSIGNED_INT,
+            SIGNED_INT,
+        };
+
+        typedef std::vector<HLSLAttribType> Signature;
+
+        VertexExecutable(const gl::InputLayout &inputLayout,
+                         const Signature &signature,
+                         ShaderExecutableD3D *shaderExecutable);
+        ~VertexExecutable();
+
+        bool matchesSignature(const Signature &signature) const;
+        static void getSignature(RendererD3D *renderer,
+                                 const gl::InputLayout &inputLayout,
+                                 Signature *signatureOut);
+
+        const gl::InputLayout &inputs() const { return mInputs; }
+        const Signature &signature() const { return mSignature; }
+        ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; }
+
+      private:
+        static HLSLAttribType GetAttribType(GLenum type);
+
+        gl::InputLayout mInputs;
+        Signature mSignature;
+        ShaderExecutableD3D *mShaderExecutable;
+    };
+
+    class PixelExecutable
+    {
+      public:
+        PixelExecutable(const std::vector<GLenum> &outputSignature,
+                        ShaderExecutableD3D *shaderExecutable);
+        ~PixelExecutable();
+
+        bool matchesSignature(const std::vector<GLenum> &signature) const
+        {
+            return mOutputSignature == signature;
+        }
+
+        const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
+        ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; }
+
+      private:
+        std::vector<GLenum> mOutputSignature;
+        ShaderExecutableD3D *mShaderExecutable;
+    };
+
+    struct Sampler
+    {
+        Sampler();
+
+        bool active;
+        GLint logicalTextureUnit;
+        GLenum textureType;
+    };
+
+    typedef std::map<std::string, D3DUniform *> D3DUniformMap;
+
+    void defineUniformsAndAssignRegisters();
+    void defineUniformBase(const gl::Shader *shader,
+                           const sh::Uniform &uniform,
+                           D3DUniformMap *uniformMap);
+    void defineUniform(GLenum shaderType,
+                       const sh::ShaderVariable &uniform,
+                       const std::string &fullName,
+                       sh::HLSLBlockEncoder *encoder,
+                       D3DUniformMap *uniformMap);
+    void assignAllSamplerRegisters();
+    void assignSamplerRegisters(D3DUniform *d3dUniform);
+
+    static void AssignSamplers(unsigned int startSamplerIndex,
+                               GLenum samplerType,
+                               unsigned int samplerCount,
+                               std::vector<Sampler> &outSamplers,
+                               GLuint *outUsedRange);
+
+    template <typename T>
+    void setUniform(GLint location, GLsizei count, const T *v, GLenum targetUniformType);
+
+    template <int cols, int rows>
+    void setUniformMatrixfv(GLint location,
+                            GLsizei count,
+                            GLboolean transpose,
+                            const GLfloat *value,
+                            GLenum targetUniformType);
+
+    LinkResult compileProgramExecutables(const gl::ContextState &data, gl::InfoLog &infoLog);
+    LinkResult compileComputeExecutable(gl::InfoLog &infoLog);
+
+    void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings,
+                                         const BuiltinInfo &builtins);
+    D3DUniform *getD3DUniformByName(const std::string &name);
+    D3DUniform *getD3DUniformFromLocation(GLint location);
+
+    void initAttribLocationsToD3DSemantic();
+
+    void reset();
+    void ensureUniformBlocksInitialized();
+
+    void initUniformBlockInfo(const gl::Shader *shader);
+    size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock);
+
+    RendererD3D *mRenderer;
+    DynamicHLSL *mDynamicHLSL;
+
+    std::vector<std::unique_ptr<VertexExecutable>> mVertexExecutables;
+    std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables;
+    std::vector<std::unique_ptr<ShaderExecutableD3D>> mGeometryExecutables;
+    std::unique_ptr<ShaderExecutableD3D> mComputeExecutable;
+
+    std::string mVertexHLSL;
+    angle::CompilerWorkaroundsD3D mVertexWorkarounds;
+
+    std::string mPixelHLSL;
+    angle::CompilerWorkaroundsD3D mPixelWorkarounds;
+    bool mUsesFragDepth;
+    std::vector<PixelShaderOutputVariable> mPixelShaderKey;
+
+    // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output
+    // structures, built from the linked varying info. We store the string itself instead of the
+    // packed varyings for simplicity.
+    std::string mGeometryShaderPreamble;
+
+    bool mUsesPointSize;
+    bool mUsesFlatInterpolation;
+
+    std::unique_ptr<UniformStorageD3D> mVertexUniformStorage;
+    std::unique_ptr<UniformStorageD3D> mFragmentUniformStorage;
+    std::unique_ptr<UniformStorageD3D> mComputeUniformStorage;
+
+    std::vector<Sampler> mSamplersPS;
+    std::vector<Sampler> mSamplersVS;
+    std::vector<Sampler> mSamplersCS;
+    GLuint mUsedVertexSamplerRange;
+    GLuint mUsedPixelSamplerRange;
+    GLuint mUsedComputeSamplerRange;
+    bool mDirtySamplerMapping;
+
+    // Cache for getPixelExecutableForFramebuffer
+    std::vector<GLenum> mPixelShaderOutputFormatCache;
+
+    AttribIndexArray mAttribLocationToD3DSemantic;
+
+    unsigned int mSerial;
+
+    std::vector<GLint> mVertexUBOCache;
+    std::vector<GLint> mFragmentUBOCache;
+    VertexExecutable::Signature mCachedVertexSignature;
+    gl::InputLayout mCachedInputLayout;
+
+    std::vector<D3DVarying> mStreamOutVaryings;
+    std::vector<D3DUniform *> mD3DUniforms;
+    std::vector<D3DUniformBlock> mD3DUniformBlocks;
+
+    std::map<std::string, sh::BlockMemberInfo> mBlockInfo;
+    std::map<std::string, size_t> mBlockDataSizes;
+
+    static unsigned int issueSerial();
+    static unsigned int mCurrentSerial;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp
new file mode 100644
index 0000000..84b30aa
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTargetD3D.cpp: Implements serial handling for rx::RenderTargetD3D
+
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace rx
+{
+unsigned int RenderTargetD3D::mCurrentSerial = 1;
+
+RenderTargetD3D::RenderTargetD3D()
+    : mSerial(issueSerials(1))
+{
+}
+
+RenderTargetD3D::~RenderTargetD3D()
+{
+}
+
+unsigned int RenderTargetD3D::getSerial() const
+{
+    return mSerial;
+}
+
+unsigned int RenderTargetD3D::issueSerials(unsigned int count)
+{
+    unsigned int firstSerial = mCurrentSerial;
+    mCurrentSerial += count;
+    return firstSerial;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h
new file mode 100644
index 0000000..c96da5c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h
@@ -0,0 +1,46 @@
+//
+// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTargetD3D.h: Defines an abstract wrapper class to manage IDirect3DSurface9
+// and ID3D11View objects belonging to renderbuffers and renderable textures.
+
+#ifndef LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
+#define LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/FramebufferAttachment.h"
+
+namespace rx
+{
+
+class RenderTargetD3D : public FramebufferAttachmentRenderTarget
+{
+  public:
+    RenderTargetD3D();
+    virtual ~RenderTargetD3D();
+
+    virtual GLsizei getWidth() const = 0;
+    virtual GLsizei getHeight() const = 0;
+    virtual GLsizei getDepth() const = 0;
+    virtual GLenum getInternalFormat() const = 0;
+    virtual GLsizei getSamples() const = 0;
+    gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); }
+
+    virtual unsigned int getSerial() const;
+    static unsigned int issueSerials(unsigned int count);
+
+    // Only currently applies to D3D11.
+    virtual void signalDirty() {}
+
+  private:
+    const unsigned int mSerial;
+    static unsigned int mCurrentSerial;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
new file mode 100644
index 0000000..2df0f74
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
@@ -0,0 +1,97 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl
+
+
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+
+#include "libANGLE/Image.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace rx
+{
+RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer)
+    : mRenderer(renderer), mRenderTarget(nullptr), mImage(nullptr)
+{
+}
+
+RenderbufferD3D::~RenderbufferD3D()
+{
+    SafeDelete(mRenderTarget);
+    mImage = nullptr;
+}
+
+gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+    return setStorageMultisample(0, internalformat, width, height);
+}
+
+gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
+{
+    // If the renderbuffer parameters are queried, the calling function
+    // will expect one of the valid renderbuffer formats for use in
+    // glRenderbufferStorage, but we should create depth and stencil buffers
+    // as DEPTH24_STENCIL8
+    GLenum creationFormat = internalformat;
+    if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_STENCIL_INDEX8)
+    {
+        creationFormat = GL_DEPTH24_STENCIL8_OES;
+    }
+
+    // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
+    // the specified storage.
+    // Because ES 3.0 already knows the exact number of supported samples, it would already have been
+    // validated and generated GL_INVALID_VALUE.
+    const gl::TextureCaps &formatCaps = mRenderer->getNativeTextureCaps().get(creationFormat);
+    if (samples > formatCaps.getMaxSamples())
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Renderbuffer format does not support %u samples, %u is the maximum.",
+                         samples, formatCaps.getMaxSamples());
+    }
+
+    RenderTargetD3D *newRT = nullptr;
+    ANGLE_TRY(mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height),
+                                            creationFormat, static_cast<GLsizei>(samples), &newRT));
+
+    SafeDelete(mRenderTarget);
+    mImage        = nullptr;
+    mRenderTarget = newRT;
+
+    return gl::NoError();
+}
+
+gl::Error RenderbufferD3D::setStorageEGLImageTarget(egl::Image *image)
+{
+    mImage = GetImplAs<EGLImageD3D>(image);
+    SafeDelete(mRenderTarget);
+
+    return gl::NoError();
+}
+
+gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget)
+{
+    if (mImage)
+    {
+        return mImage->getRenderTarget(outRenderTarget);
+    }
+    else
+    {
+        *outRenderTarget = mRenderTarget;
+        return gl::NoError();
+    }
+}
+
+gl::Error RenderbufferD3D::getAttachmentRenderTarget(GLenum /*binding*/,
+                                                     const gl::ImageIndex & /*imageIndex*/,
+                                                     FramebufferAttachmentRenderTarget **rtOut)
+{
+    return getRenderTarget(reinterpret_cast<RenderTargetD3D **>(rtOut));
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h
new file mode 100644
index 0000000..15fd583
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
+#define LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
+
+#include "angle_gl.h"
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+class EGLImageD3D;
+class RendererD3D;
+class RenderTargetD3D;
+class SwapChainD3D;
+
+class RenderbufferD3D : public RenderbufferImpl
+{
+  public:
+    RenderbufferD3D(RendererD3D *renderer);
+    virtual ~RenderbufferD3D();
+
+    gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
+    gl::Error setStorageMultisample(size_t samples,
+                                    GLenum internalformat,
+                                    size_t width,
+                                    size_t height) override;
+    gl::Error setStorageEGLImageTarget(egl::Image *image) override;
+
+    gl::Error getRenderTarget(RenderTargetD3D **outRenderTarget);
+    gl::Error getAttachmentRenderTarget(GLenum binding,
+                                        const gl::ImageIndex &imageIndex,
+                                        FramebufferAttachmentRenderTarget **rtOut) override;
+
+  private:
+    RendererD3D *mRenderer;
+    RenderTargetD3D *mRenderTarget;
+    EGLImageD3D *mImage;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
new file mode 100644
index 0000000..e0cb86d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -0,0 +1,383 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RendererD3D.cpp: Implementation of the base D3D Renderer.
+
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+#include "common/MemoryBuffer.h"
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.h"
+
+namespace rx
+{
+
+RendererD3D::RendererD3D(egl::Display *display)
+    : mDisplay(display),
+      mPresentPathFastEnabled(false),
+      mCapsInitialized(false),
+      mWorkaroundsInitialized(false),
+      mDisjoint(false),
+      mDeviceLost(false),
+      mWorkerThreadPool(4)
+{
+}
+
+RendererD3D::~RendererD3D()
+{
+    cleanup();
+}
+
+void RendererD3D::cleanup()
+{
+    for (auto &incompleteTexture : mIncompleteTextures)
+    {
+        incompleteTexture.second.set(nullptr);
+    }
+    mIncompleteTextures.clear();
+}
+
+unsigned int RendererD3D::GetBlendSampleMask(const gl::ContextState &data, int samples)
+{
+    const auto &glState = data.getState();
+    unsigned int mask   = 0;
+    if (glState.isSampleCoverageEnabled())
+    {
+        GLfloat coverageValue = glState.getSampleCoverageValue();
+        if (coverageValue != 0)
+        {
+            float threshold = 0.5f;
+
+            for (int i = 0; i < samples; ++i)
+            {
+                mask <<= 1;
+
+                if ((i + 1) * coverageValue >= threshold)
+                {
+                    threshold += 1.0f;
+                    mask |= 1;
+                }
+            }
+        }
+
+        bool coverageInvert = glState.getSampleCoverageInvert();
+        if (coverageInvert)
+        {
+            mask = ~mask;
+        }
+    }
+    else
+    {
+        mask = 0xFFFFFFFF;
+    }
+
+    return mask;
+}
+
+// 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).
+// Sampler mapping needs to be up-to-date on the program object before this is called.
+gl::Error RendererD3D::applyTextures(GLImplFactory *implFactory,
+                                     const gl::ContextState &data,
+                                     gl::SamplerType shaderType,
+                                     const FramebufferTextureArray &framebufferTextures,
+                                     size_t framebufferTextureCount)
+{
+    const auto &glState    = data.getState();
+    const auto &caps       = data.getCaps();
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+    ASSERT(!programD3D->isSamplerMappingDirty());
+
+    // TODO(jmadill): Use the Program's sampler bindings.
+
+    unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
+    for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+    {
+        GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex);
+        GLint textureUnit  = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
+        if (textureUnit != -1)
+        {
+            gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
+            ASSERT(texture);
+
+            gl::Sampler *samplerObject = glState.getSampler(textureUnit);
+
+            const gl::SamplerState &samplerState =
+                samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
+
+            // TODO: std::binary_search may become unavailable using older versions of GCC
+            if (texture->getTextureState().isSamplerComplete(samplerState, data) &&
+                !std::binary_search(framebufferTextures.begin(),
+                                    framebufferTextures.begin() + framebufferTextureCount, texture))
+            {
+                ANGLE_TRY(setSamplerState(shaderType, samplerIndex, texture, samplerState));
+                ANGLE_TRY(setTexture(shaderType, samplerIndex, texture));
+            }
+            else
+            {
+                // Texture is not sampler complete or it is in use by the framebuffer.  Bind the
+                // incomplete texture.
+                gl::Texture *incompleteTexture = getIncompleteTexture(implFactory, textureType);
+
+                ANGLE_TRY(setSamplerState(shaderType, samplerIndex, incompleteTexture,
+                                          incompleteTexture->getSamplerState()));
+                ANGLE_TRY(setTexture(shaderType, samplerIndex, incompleteTexture));
+            }
+        }
+        else
+        {
+            // No texture bound to this slot even though it is used by the shader, bind a NULL
+            // texture
+            ANGLE_TRY(setTexture(shaderType, samplerIndex, nullptr));
+        }
+    }
+
+    // Set all the remaining textures to NULL
+    size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits
+                                                            : caps.maxVertexTextureImageUnits;
+    clearTextures(shaderType, samplerRange, samplerCount);
+
+    return gl::NoError();
+}
+
+gl::Error RendererD3D::applyTextures(GLImplFactory *implFactory, const gl::ContextState &data)
+{
+    FramebufferTextureArray framebufferTextures;
+    size_t framebufferSerialCount = getBoundFramebufferTextures(data, &framebufferTextures);
+
+    ANGLE_TRY(applyTextures(implFactory, data, gl::SAMPLER_VERTEX, framebufferTextures,
+                            framebufferSerialCount));
+    ANGLE_TRY(applyTextures(implFactory, data, gl::SAMPLER_PIXEL, framebufferTextures,
+                            framebufferSerialCount));
+    return gl::NoError();
+}
+
+bool RendererD3D::skipDraw(const gl::ContextState &data, GLenum drawMode)
+{
+    const gl::State &state = data.getState();
+
+    if (drawMode == GL_POINTS)
+    {
+        bool usesPointSize = GetImplAs<ProgramD3D>(state.getProgram())->usesPointSize();
+
+        // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
+        // which affects varying interpolation. Since the value of gl_PointSize is
+        // undefined when not written, just skip drawing to avoid unexpected results.
+        if (!usesPointSize && !state.isTransformFeedbackActiveUnpaused())
+        {
+            // Notify developers of risking undefined behavior.
+            WARN() << "Point rendering without writing to gl_PointSize.";
+            return true;
+        }
+    }
+    else if (gl::IsTriangleMode(drawMode))
+    {
+        if (state.getRasterizerState().cullFace &&
+            state.getRasterizerState().cullMode == GL_FRONT_AND_BACK)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+gl::Error RendererD3D::markTransformFeedbackUsage(const gl::ContextState &data)
+{
+    const gl::TransformFeedback *transformFeedback = data.getState().getCurrentTransformFeedback();
+    for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
+    {
+        const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
+        if (binding.get() != nullptr)
+        {
+            BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
+            ANGLE_TRY(bufferD3D->markTransformFeedbackUsage());
+        }
+    }
+
+    return gl::NoError();
+}
+
+size_t RendererD3D::getBoundFramebufferTextures(const gl::ContextState &data,
+                                                FramebufferTextureArray *outTextureArray)
+{
+    size_t textureCount = 0;
+
+    const gl::Framebuffer *drawFramebuffer = data.getState().getDrawFramebuffer();
+    for (size_t i = 0; i < drawFramebuffer->getNumColorBuffers(); i++)
+    {
+        const gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i);
+        if (attachment && attachment->type() == GL_TEXTURE)
+        {
+            (*outTextureArray)[textureCount++] = attachment->getTexture();
+        }
+    }
+
+    const gl::FramebufferAttachment *depthStencilAttachment =
+        drawFramebuffer->getDepthOrStencilbuffer();
+    if (depthStencilAttachment && depthStencilAttachment->type() == GL_TEXTURE)
+    {
+        (*outTextureArray)[textureCount++] = depthStencilAttachment->getTexture();
+    }
+
+    std::sort(outTextureArray->begin(), outTextureArray->begin() + textureCount);
+
+    return textureCount;
+}
+
+gl::Texture *RendererD3D::getIncompleteTexture(GLImplFactory *implFactory, GLenum type)
+{
+    if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
+    {
+        const GLubyte color[] = {0, 0, 0, 255};
+        const gl::Extents colorSize(1, 1, 1);
+        const gl::PixelUnpackState unpack(1, 0);
+        const gl::Box area(0, 0, 0, 1, 1, 1);
+
+        // If a texture is external use a 2D texture for the incomplete texture
+        GLenum createType = (type == GL_TEXTURE_EXTERNAL_OES) ? GL_TEXTURE_2D : type;
+
+        // Skip the API layer to avoid needing to pass the Context and mess with dirty bits.
+        gl::Texture *t =
+            new gl::Texture(implFactory, std::numeric_limits<GLuint>::max(), createType);
+        t->setStorage(nullptr, createType, 1, GL_RGBA8, colorSize);
+        if (type == GL_TEXTURE_CUBE_MAP)
+        {
+            for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+                 face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
+            {
+                t->getImplementation()->setSubImage(nullptr, face, 0, area, GL_RGBA8,
+                                                    GL_UNSIGNED_BYTE, unpack, color);
+            }
+        }
+        else
+        {
+            t->getImplementation()->setSubImage(nullptr, createType, 0, area, GL_RGBA8,
+                                                GL_UNSIGNED_BYTE, unpack, color);
+        }
+        mIncompleteTextures[type].set(t);
+    }
+
+    return mIncompleteTextures[type].get();
+}
+
+GLenum RendererD3D::getResetStatus()
+{
+    if (!mDeviceLost)
+    {
+        if (testDeviceLost())
+        {
+            mDeviceLost = true;
+            notifyDeviceLost();
+            return GL_UNKNOWN_CONTEXT_RESET_EXT;
+        }
+        return GL_NO_ERROR;
+    }
+
+    if (testDeviceResettable())
+    {
+        return GL_NO_ERROR;
+    }
+
+    return GL_UNKNOWN_CONTEXT_RESET_EXT;
+}
+
+void RendererD3D::notifyDeviceLost()
+{
+    mDisplay->notifyDeviceLost();
+}
+
+std::string RendererD3D::getVendorString() const
+{
+    LUID adapterLuid = {0};
+
+    if (getLUID(&adapterLuid))
+    {
+        char adapterLuidString[64];
+        sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)",
+                  adapterLuid.HighPart, adapterLuid.LowPart);
+        return std::string(adapterLuidString);
+    }
+
+    return std::string("");
+}
+
+void RendererD3D::setGPUDisjoint()
+{
+    mDisjoint = true;
+}
+
+GLint RendererD3D::getGPUDisjoint()
+{
+    bool disjoint = mDisjoint;
+
+    // Disjoint flag is cleared when read
+    mDisjoint = false;
+
+    return disjoint;
+}
+
+GLint64 RendererD3D::getTimestamp()
+{
+    // D3D has no way to get an actual timestamp reliably so 0 is returned
+    return 0;
+}
+
+void RendererD3D::ensureCapsInitialized() const
+{
+    if (!mCapsInitialized)
+    {
+        generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
+        mCapsInitialized = true;
+    }
+}
+
+const gl::Caps &RendererD3D::getNativeCaps() const
+{
+    ensureCapsInitialized();
+    return mNativeCaps;
+}
+
+const gl::TextureCapsMap &RendererD3D::getNativeTextureCaps() const
+{
+    ensureCapsInitialized();
+    return mNativeTextureCaps;
+}
+
+const gl::Extensions &RendererD3D::getNativeExtensions() const
+{
+    ensureCapsInitialized();
+    return mNativeExtensions;
+}
+
+const gl::Limitations &RendererD3D::getNativeLimitations() const
+{
+    ensureCapsInitialized();
+    return mNativeLimitations;
+}
+
+angle::WorkerThreadPool *RendererD3D::getWorkerThreadPool()
+{
+    return &mWorkerThreadPool;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h
new file mode 100644
index 0000000..1e65249
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -0,0 +1,334 @@
+
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RendererD3D.h: Defines a back-end specific class for the DirectX renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
+#define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
+
+#include <array>
+
+#include "common/debug.h"
+#include "common/MemoryBuffer.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/WorkerThread.h"
+#include "platform/WorkaroundsD3D.h"
+
+namespace egl
+{
+class ConfigSet;
+}
+
+namespace gl
+{
+class FramebufferState;
+class InfoLog;
+class Texture;
+struct LinkedVarying;
+}
+
+namespace rx
+{
+class ContextImpl;
+struct D3DUniform;
+struct D3DVarying;
+class DeviceD3D;
+class EGLImageD3D;
+class FramebufferImpl;
+class ImageD3D;
+class IndexBuffer;
+class NativeWindowD3D;
+class ProgramD3D;
+class RenderTargetD3D;
+class ShaderExecutableD3D;
+class SwapChainD3D;
+class TextureStorage;
+struct TranslatedIndexData;
+class UniformStorageD3D;
+class VertexBuffer;
+
+struct DeviceIdentifier
+{
+    UINT VendorId;
+    UINT DeviceId;
+    UINT SubSysId;
+    UINT Revision;
+    UINT FeatureLevel;
+};
+
+enum RendererClass
+{
+    RENDERER_D3D11,
+    RENDERER_D3D9
+};
+
+enum ShaderType
+{
+    SHADER_VERTEX,
+    SHADER_PIXEL,
+    SHADER_GEOMETRY,
+    SHADER_COMPUTE,
+    SHADER_TYPE_MAX
+};
+
+// Useful for unit testing
+class BufferFactoryD3D : angle::NonCopyable
+{
+  public:
+    BufferFactoryD3D() {}
+    virtual ~BufferFactoryD3D() {}
+
+    virtual VertexBuffer *createVertexBuffer() = 0;
+    virtual IndexBuffer *createIndexBuffer() = 0;
+
+    // TODO(jmadill): add VertexFormatCaps
+    virtual VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const = 0;
+    virtual GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const = 0;
+
+    // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+    // function.
+    virtual gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(
+        const gl::VertexAttribute &attrib,
+        const gl::VertexBinding &binding,
+        GLsizei count,
+        GLsizei instances) const = 0;
+};
+
+using AttribIndexArray = std::array<int, gl::MAX_VERTEX_ATTRIBS>;
+
+class RendererD3D : public BufferFactoryD3D
+{
+  public:
+    explicit RendererD3D(egl::Display *display);
+    virtual ~RendererD3D();
+
+    virtual egl::Error initialize() = 0;
+
+    virtual egl::ConfigSet generateConfigs() = 0;
+    virtual void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const = 0;
+
+    virtual ContextImpl *createContext(const gl::ContextState &state) = 0;
+
+    std::string getVendorString() const;
+
+    virtual int getMinorShaderModel() const = 0;
+    virtual std::string getShaderModelSuffix() const = 0;
+
+    // Direct3D Specific methods
+    virtual DeviceIdentifier getAdapterIdentifier() const = 0;
+
+    virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0;
+    virtual NativeWindowD3D *createNativeWindow(EGLNativeWindowType window,
+                                                const egl::Config *config,
+                                                const egl::AttributeMap &attribs) const = 0;
+
+    virtual SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
+                                          HANDLE shareHandle,
+                                          IUnknown *d3dTexture,
+                                          GLenum backBufferFormat,
+                                          GLenum depthBufferFormat,
+                                          EGLint orientation,
+                                          EGLint samples) = 0;
+    virtual egl::Error getD3DTextureInfo(const egl::Config *configuration,
+                                         IUnknown *d3dTexture,
+                                         EGLint *width,
+                                         EGLint *height,
+                                         GLenum *fboFormat) const = 0;
+    virtual egl::Error validateShareHandle(const egl::Config *config,
+                                           HANDLE shareHandle,
+                                           const egl::AttributeMap &attribs) const = 0;
+
+    virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0;
+    virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
+
+    virtual gl::Error setUniformBuffers(const gl::ContextState &data,
+                                        const std::vector<GLint> &vertexUniformBuffers,
+                                        const std::vector<GLint> &fragmentUniformBuffers) = 0;
+
+    virtual gl::Error applyUniforms(const ProgramD3D &programD3D,
+                                    GLenum drawMode,
+                                    const std::vector<D3DUniform *> &uniformArray) = 0;
+
+    virtual unsigned int getReservedVertexUniformBuffers() const = 0;
+    virtual unsigned int getReservedFragmentUniformBuffers() const = 0;
+
+    virtual int getMajorShaderModel() const = 0;
+
+    const angle::WorkaroundsD3D &getWorkarounds() const;
+
+    // Pixel operations
+    virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                 const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
+    virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                    const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) = 0;
+    virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                  const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
+    virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                       const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
+
+    virtual gl::Error copyTexture(const gl::Texture *source,
+                                  GLint sourceLevel,
+                                  const gl::Rectangle &sourceRect,
+                                  GLenum destFormat,
+                                  const gl::Offset &destOffset,
+                                  TextureStorage *storage,
+                                  GLenum destTarget,
+                                  GLint destLevel,
+                                  bool unpackFlipY,
+                                  bool unpackPremultiplyAlpha,
+                                  bool unpackUnmultiplyAlpha) = 0;
+    virtual gl::Error copyCompressedTexture(const gl::Texture *source,
+                                            GLint sourceLevel,
+                                            TextureStorage *storage,
+                                            GLint destLevel) = 0;
+
+    // RenderTarget creation
+    virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) = 0;
+    virtual gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) = 0;
+
+    // Shader operations
+    virtual gl::Error loadExecutable(const void *function,
+                                     size_t length,
+                                     ShaderType type,
+                                     const std::vector<D3DVarying> &streamOutVaryings,
+                                     bool separatedOutputBuffers,
+                                     ShaderExecutableD3D **outExecutable) = 0;
+    virtual gl::Error compileToExecutable(gl::InfoLog &infoLog,
+                                          const std::string &shaderHLSL,
+                                          ShaderType type,
+                                          const std::vector<D3DVarying> &streamOutVaryings,
+                                          bool separatedOutputBuffers,
+                                          const angle::CompilerWorkaroundsD3D &workarounds,
+                                          ShaderExecutableD3D **outExectuable) = 0;
+    virtual gl::Error ensureHLSLCompilerInitialized()                          = 0;
+
+    virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0;
+
+    // Image operations
+    virtual ImageD3D *createImage() = 0;
+    virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0;
+    virtual gl::Error generateMipmapUsingD3D(TextureStorage *storage,
+                                             const gl::TextureState &textureState) = 0;
+    virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0;
+    virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+                                                         RenderTargetD3D *renderTargetD3D) = 0;
+    virtual TextureStorage *createTextureStorageExternal(
+        egl::Stream *stream,
+        const egl::Stream::GLTextureDescription &desc) = 0;
+    virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0;
+    virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0;
+    virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
+    virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
+
+    // Buffer-to-texture and Texture-to-buffer copies
+    virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
+    virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
+                                              GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0;
+
+    // Device lost
+    GLenum getResetStatus();
+    void notifyDeviceLost();
+    virtual bool resetDevice() = 0;
+    virtual bool testDeviceLost()       = 0;
+    virtual bool testDeviceResettable() = 0;
+
+    virtual RendererClass getRendererClass() const = 0;
+    virtual void *getD3DDevice() = 0;
+
+    void setGPUDisjoint();
+
+    GLint getGPUDisjoint();
+    GLint64 getTimestamp();
+
+    // In D3D11, faster than calling setTexture a jillion times
+    virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0;
+
+    virtual egl::Error getEGLDevice(DeviceImpl **device) = 0;
+
+    bool presentPathFastEnabled() const { return mPresentPathFastEnabled; }
+
+    // Stream creation
+    virtual StreamProducerImpl *createStreamProducerD3DTextureNV12(
+        egl::Stream::ConsumerType consumerType,
+        const egl::AttributeMap &attribs) = 0;
+
+    const gl::Caps &getNativeCaps() const;
+    const gl::TextureCapsMap &getNativeTextureCaps() const;
+    const gl::Extensions &getNativeExtensions() const;
+    const gl::Limitations &getNativeLimitations() const;
+
+    // Necessary hack for default framebuffers in D3D.
+    virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0;
+
+    virtual gl::Version getMaxSupportedESVersion() const = 0;
+
+    angle::WorkerThreadPool *getWorkerThreadPool();
+
+    virtual gl::Error applyComputeUniforms(const ProgramD3D &programD3D,
+                                           const std::vector<D3DUniform *> &uniformArray) = 0;
+
+  protected:
+    virtual bool getLUID(LUID *adapterLuid) const = 0;
+    virtual void generateCaps(gl::Caps *outCaps,
+                              gl::TextureCapsMap *outTextureCaps,
+                              gl::Extensions *outExtensions,
+                              gl::Limitations *outLimitations) const = 0;
+
+    void cleanup();
+
+    static unsigned int GetBlendSampleMask(const gl::ContextState &data, int samples);
+    // dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
+
+    gl::Error applyTextures(GLImplFactory *implFactory, const gl::ContextState &data);
+    bool skipDraw(const gl::ContextState &data, GLenum drawMode);
+    gl::Error markTransformFeedbackUsage(const gl::ContextState &data);
+
+    egl::Display *mDisplay;
+
+    bool mPresentPathFastEnabled;
+
+  private:
+    void ensureCapsInitialized() const;
+
+    typedef std::array<gl::Texture*, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureArray;
+
+    gl::Error applyTextures(GLImplFactory *implFactory,
+                            const gl::ContextState &data,
+                            gl::SamplerType shaderType,
+                            const FramebufferTextureArray &framebufferTextures,
+                            size_t framebufferTextureCount);
+
+    size_t getBoundFramebufferTextures(const gl::ContextState &data,
+                                       FramebufferTextureArray *outTextureArray);
+    gl::Texture *getIncompleteTexture(GLImplFactory *implFactory, GLenum type);
+
+    virtual angle::WorkaroundsD3D generateWorkarounds() const = 0;
+
+    mutable bool mCapsInitialized;
+    mutable gl::Caps mNativeCaps;
+    mutable gl::TextureCapsMap mNativeTextureCaps;
+    mutable gl::Extensions mNativeExtensions;
+    mutable gl::Limitations mNativeLimitations;
+
+    gl::TextureMap mIncompleteTextures;
+
+    mutable bool mWorkaroundsInitialized;
+    mutable angle::WorkaroundsD3D mWorkarounds;
+
+    bool mDisjoint;
+    bool mDeviceLost;
+
+    angle::WorkerThreadPool mWorkerThreadPool;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/SamplerD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/SamplerD3D.h
new file mode 100644
index 0000000..7aabdc8
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/SamplerD3D.h
@@ -0,0 +1,25 @@
+//
+// 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.
+//
+
+// SamplerD3D.h: Defines the rx::SamplerD3D class, an implementation of SamplerImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
+#define LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
+
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace rx
+{
+
+class SamplerD3D : public SamplerImpl
+{
+  public:
+    SamplerD3D() {}
+    ~SamplerD3D() override {}
+};
+}
+
+#endif  // LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
new file mode 100644
index 0000000..4978b92
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -0,0 +1,235 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
+
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+
+// Definitions local to the translation unit
+namespace
+{
+
+const char *GetShaderTypeString(GLenum type)
+{
+    switch (type)
+    {
+        case GL_VERTEX_SHADER:
+            return "VERTEX";
+
+        case GL_FRAGMENT_SHADER:
+            return "FRAGMENT";
+
+        case GL_COMPUTE_SHADER:
+            return "COMPUTE";
+
+        default:
+            UNREACHABLE();
+            return "";
+    }
+}
+
+}  // anonymous namespace
+
+namespace rx
+{
+
+ShaderD3D::ShaderD3D(const gl::ShaderState &data, const angle::WorkaroundsD3D &workarounds)
+    : ShaderImpl(data), mAdditionalOptions(0)
+{
+    uncompile();
+
+    if (workarounds.expandIntegerPowExpressions)
+    {
+        mAdditionalOptions |= SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS;
+    }
+
+    if (workarounds.getDimensionsIgnoresBaseLevel)
+    {
+        mAdditionalOptions |= SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL;
+    }
+
+    if (workarounds.preAddTexelFetchOffsets)
+    {
+        mAdditionalOptions |= SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH;
+    }
+    if (workarounds.rewriteUnaryMinusOperator)
+    {
+        mAdditionalOptions |= SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR;
+    }
+    if (workarounds.emulateIsnanFloat)
+    {
+        mAdditionalOptions |= SH_EMULATE_ISNAN_FLOAT_FUNCTION;
+    }
+}
+
+ShaderD3D::~ShaderD3D()
+{
+}
+
+std::string ShaderD3D::getDebugInfo() const
+{
+    if (mDebugInfo.empty())
+    {
+        return "";
+    }
+
+    return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mData.getShaderType()) +
+           " SHADER END\n";
+}
+
+// initialize/clean up previous state
+void ShaderD3D::uncompile()
+{
+    // set by compileToHLSL
+    mCompilerOutputType = SH_ESSL_OUTPUT;
+
+    mUsesMultipleRenderTargets = false;
+    mUsesFragColor = false;
+    mUsesFragData = false;
+    mUsesFragCoord = false;
+    mUsesFrontFacing = false;
+    mUsesPointSize = false;
+    mUsesPointCoord = false;
+    mUsesDepthRange = false;
+    mUsesFragDepth = false;
+    mUsesDiscardRewriting = false;
+    mUsesNestedBreak = false;
+    mRequiresIEEEStrictCompiling = false;
+
+    mDebugInfo.clear();
+}
+
+void ShaderD3D::generateWorkarounds(angle::CompilerWorkaroundsD3D *workarounds) const
+{
+    if (mUsesDiscardRewriting)
+    {
+        // ANGLE issue 486:
+        // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
+        workarounds->skipOptimization = true;
+    }
+    else if (mUsesNestedBreak)
+    {
+        // ANGLE issue 603:
+        // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
+        // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
+        workarounds->useMaxOptimization = true;
+    }
+
+    if (mRequiresIEEEStrictCompiling)
+    {
+        // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work.
+        workarounds->enableIEEEStrictness = true;
+    }
+}
+
+unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const
+{
+    ASSERT(mUniformRegisterMap.count(uniformName) > 0);
+    return mUniformRegisterMap.find(uniformName)->second;
+}
+
+unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) const
+{
+    ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0);
+    return mInterfaceBlockRegisterMap.find(blockName)->second;
+}
+
+ShShaderOutput ShaderD3D::getCompilerOutputType() const
+{
+    return mCompilerOutputType;
+}
+
+ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream,
+                                                          std::string *sourcePath)
+{
+    uncompile();
+
+    ShCompileOptions additionalOptions = 0;
+
+    const std::string &source = mData.getSource();
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    if (gl::DebugAnnotationsActive())
+    {
+        *sourcePath = getTempPath();
+        writeFile(sourcePath->c_str(), source.c_str(), source.length());
+        additionalOptions |= SH_LINE_DIRECTIVES | SH_SOURCE_PATH;
+    }
+#endif
+
+    additionalOptions |= mAdditionalOptions;
+
+    *shaderSourceStream << source;
+    return additionalOptions;
+}
+
+bool ShaderD3D::hasUniform(const D3DUniform *d3dUniform) const
+{
+    return mUniformRegisterMap.find(d3dUniform->name) != mUniformRegisterMap.end();
+}
+
+const std::map<std::string, unsigned int> &GetUniformRegisterMap(
+    const std::map<std::string, unsigned int> *uniformRegisterMap)
+{
+    ASSERT(uniformRegisterMap);
+    return *uniformRegisterMap;
+}
+
+bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
+{
+    // TODO(jmadill): We shouldn't need to cache this.
+    mCompilerOutputType = compiler->getShaderOutputType();
+
+    const std::string &translatedSource = mData.getTranslatedSource();
+
+    mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos;
+    mUsesFragColor             = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
+    mUsesFragData              = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
+    mUsesFragCoord             = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
+    mUsesFrontFacing           = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
+    mUsesPointSize             = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
+    mUsesPointCoord            = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
+    mUsesDepthRange            = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
+    mUsesFragDepth             = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
+    mUsesDiscardRewriting =
+        translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
+    mUsesNestedBreak  = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
+    mRequiresIEEEStrictCompiling =
+        translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;
+
+    ShHandle compilerHandle = compiler->getCompilerHandle(mData.getShaderType());
+
+    mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle));
+
+    for (const sh::InterfaceBlock &interfaceBlock : mData.getInterfaceBlocks())
+    {
+        if (interfaceBlock.staticUse)
+        {
+            unsigned int index = static_cast<unsigned int>(-1);
+            bool blockRegisterResult =
+                sh::GetInterfaceBlockRegister(compilerHandle, interfaceBlock.name, &index);
+            ASSERT(blockRegisterResult);
+
+            mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
+        }
+    }
+
+    mDebugInfo +=
+        std::string("// ") + GetShaderTypeString(mData.getShaderType()) + " SHADER BEGIN\n";
+    mDebugInfo += "\n// GLSL BEGIN\n\n" + mData.getSource() + "\n\n// GLSL END\n\n\n";
+    mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n";
+    // Successive steps will append more info
+    return true;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
new file mode 100644
index 0000000..dc99ac4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
@@ -0,0 +1,88 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderD3D.h: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_SHADERD3D_H_
+#define LIBANGLE_RENDERER_D3D_SHADERD3D_H_
+
+#include "libANGLE/renderer/ShaderImpl.h"
+
+#include <map>
+
+namespace angle
+{
+struct CompilerWorkaroundsD3D;
+struct WorkaroundsD3D;
+}
+
+namespace rx
+{
+class DynamicHLSL;
+class RendererD3D;
+struct D3DUniform;
+
+class ShaderD3D : public ShaderImpl
+{
+  public:
+    ShaderD3D(const gl::ShaderState &data, const angle::WorkaroundsD3D &workarounds);
+    virtual ~ShaderD3D();
+
+    // ShaderImpl implementation
+    ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+                                                   std::string *sourcePath) override;
+    bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
+    std::string getDebugInfo() const override;
+
+    // D3D-specific methods
+    void uncompile();
+
+    bool hasUniform(const D3DUniform *d3dUniform) const;
+
+    // Query regular uniforms with their name. Query sampler fields of structs with field selection
+    // using dot (.) operator.
+    unsigned int getUniformRegister(const std::string &uniformName) const;
+
+    unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
+    void appendDebugInfo(const std::string &info) const { mDebugInfo += info; }
+
+    void generateWorkarounds(angle::CompilerWorkaroundsD3D *workarounds) const;
+
+    bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; }
+    bool usesFragColor() const { return mUsesFragColor; }
+    bool usesFragData() const { return mUsesFragData; }
+    bool usesFragCoord() const { return mUsesFragCoord; }
+    bool usesFrontFacing() const { return mUsesFrontFacing; }
+    bool usesPointSize() const { return mUsesPointSize; }
+    bool usesPointCoord() const { return mUsesPointCoord; }
+    bool usesDepthRange() const { return mUsesDepthRange; }
+    bool usesFragDepth() const { return mUsesFragDepth; }
+
+    ShShaderOutput getCompilerOutputType() const;
+
+  private:
+    bool mUsesMultipleRenderTargets;
+    bool mUsesFragColor;
+    bool mUsesFragData;
+    bool mUsesFragCoord;
+    bool mUsesFrontFacing;
+    bool mUsesPointSize;
+    bool mUsesPointCoord;
+    bool mUsesDepthRange;
+    bool mUsesFragDepth;
+    bool mUsesDiscardRewriting;
+    bool mUsesNestedBreak;
+    bool mRequiresIEEEStrictCompiling;
+
+    ShShaderOutput mCompilerOutputType;
+    mutable std::string mDebugInfo;
+    std::map<std::string, unsigned int> mUniformRegisterMap;
+    std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
+    ShCompileOptions mAdditionalOptions;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_SHADERD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
new file mode 100644
index 0000000..97ffdf5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable.cpp: Implements a class to contain D3D shader executable
+// implementation details.
+
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+
+ShaderExecutableD3D::ShaderExecutableD3D(const void *function, size_t length)
+    : mFunctionBuffer(length)
+{
+    memcpy(mFunctionBuffer.data(), function, length);
+}
+
+ShaderExecutableD3D::~ShaderExecutableD3D()
+{
+}
+
+const uint8_t *ShaderExecutableD3D::getFunction() const
+{
+    return mFunctionBuffer.data();
+}
+
+size_t ShaderExecutableD3D::getLength() const
+{
+    return mFunctionBuffer.size();
+}
+
+const std::string &ShaderExecutableD3D::getDebugInfo() const
+{
+    return mDebugInfo;
+}
+
+void ShaderExecutableD3D::appendDebugInfo(const std::string &info)
+{
+    mDebugInfo += info;
+}
+
+
+UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mSize(initialSize)
+{
+}
+
+UniformStorageD3D::~UniformStorageD3D()
+{
+}
+
+size_t UniformStorageD3D::size() const
+{
+    return mSize;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
new file mode 100644
index 0000000..71b83b7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable.h: Defines a class to contain D3D shader executable
+// implementation details.
+
+#ifndef LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
+#define LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
+
+#include "common/debug.h"
+
+#include <vector>
+#include <cstdint>
+
+namespace rx
+{
+
+class ShaderExecutableD3D : angle::NonCopyable
+{
+  public:
+    ShaderExecutableD3D(const void *function, size_t length);
+    virtual ~ShaderExecutableD3D();
+
+    const uint8_t *getFunction() const;
+
+    size_t getLength() const;
+
+    const std::string &getDebugInfo() const;
+
+    void appendDebugInfo(const std::string &info);
+
+  private:
+    std::vector<uint8_t> mFunctionBuffer;
+    std::string mDebugInfo;
+};
+
+class UniformStorageD3D : angle::NonCopyable
+{
+  public:
+    UniformStorageD3D(size_t initialSize);
+    virtual ~UniformStorageD3D();
+
+    size_t size() const;
+
+  private:
+    size_t mSize;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
new file mode 100644
index 0000000..4e3252d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -0,0 +1,404 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceD3D.cpp: D3D implementation of an EGL surface
+
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+
+#include <tchar.h>
+#include <EGL/eglext.h>
+#include <algorithm>
+
+namespace rx
+{
+
+SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
+                       RendererD3D *renderer,
+                       egl::Display *display,
+                       EGLNativeWindowType window,
+                       EGLenum buftype,
+                       EGLClientBuffer clientBuffer,
+                       const egl::AttributeMap &attribs)
+    : SurfaceImpl(state),
+      mRenderer(renderer),
+      mDisplay(display),
+      mFixedSize(window == nullptr || attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE),
+      mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))),
+      mRenderTargetFormat(state.config->renderTargetFormat),
+      mDepthStencilFormat(state.config->depthStencilFormat),
+      mSwapChain(nullptr),
+      mSwapIntervalDirty(true),
+      mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)),
+      mWidth(static_cast<EGLint>(attribs.get(EGL_WIDTH, 0))),
+      mHeight(static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0))),
+      mSwapInterval(1),
+      mShareHandle(0),
+      mD3DTexture(nullptr)
+{
+    if (window != nullptr && !mFixedSize)
+    {
+        mWidth  = -1;
+        mHeight = -1;
+    }
+
+    switch (buftype)
+    {
+        case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+            mShareHandle = static_cast<HANDLE>(clientBuffer);
+            break;
+
+        case EGL_D3D_TEXTURE_ANGLE:
+            mD3DTexture = static_cast<IUnknown *>(clientBuffer);
+            ASSERT(mD3DTexture != nullptr);
+            mD3DTexture->AddRef();
+            mRenderer->getD3DTextureInfo(state.config, mD3DTexture, &mWidth, &mHeight,
+                                         &mRenderTargetFormat);
+            break;
+
+        default:
+            break;
+    }
+}
+
+SurfaceD3D::~SurfaceD3D()
+{
+    releaseSwapChain();
+    SafeDelete(mNativeWindow);
+    SafeRelease(mD3DTexture);
+}
+
+void SurfaceD3D::releaseSwapChain()
+{
+    SafeDelete(mSwapChain);
+}
+
+egl::Error SurfaceD3D::initialize(const DisplayImpl *displayImpl)
+{
+    if (mNativeWindow->getNativeWindow())
+    {
+        if (!mNativeWindow->initialize())
+        {
+            return egl::Error(EGL_BAD_SURFACE);
+        }
+    }
+
+    egl::Error error = resetSwapChain();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::FramebufferState &data)
+{
+    return mRenderer->createDefaultFramebuffer(data);
+}
+
+egl::Error SurfaceD3D::bindTexImage(gl::Texture *, EGLint)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::releaseTexImage(EGLint)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+    return mSwapChain->getSyncValues(ust, msc, sbc);
+}
+
+egl::Error SurfaceD3D::resetSwapChain()
+{
+    ASSERT(!mSwapChain);
+
+    int width;
+    int height;
+
+    if (!mFixedSize)
+    {
+        RECT windowRect;
+        if (!mNativeWindow->getClientRect(&windowRect))
+        {
+            ASSERT(false);
+
+            return egl::Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions");
+        }
+
+        width = windowRect.right - windowRect.left;
+        height = windowRect.bottom - windowRect.top;
+    }
+    else
+    {
+        // non-window surface - size is determined at creation
+        width = mWidth;
+        height = mHeight;
+    }
+
+    mSwapChain =
+        mRenderer->createSwapChain(mNativeWindow, mShareHandle, mD3DTexture, mRenderTargetFormat,
+                                   mDepthStencilFormat, mOrientation, mState.config->samples);
+    if (!mSwapChain)
+    {
+        return egl::Error(EGL_BAD_ALLOC);
+    }
+
+    egl::Error error = resetSwapChain(width, height);
+    if (error.isError())
+    {
+        SafeDelete(mSwapChain);
+        return error;
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight)
+{
+    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
+    ASSERT(mSwapChain);
+
+    EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
+
+    if (status == EGL_CONTEXT_LOST)
+    {
+        mDisplay->notifyDeviceLost();
+        return egl::Error(status);
+    }
+    else if (status != EGL_SUCCESS)
+    {
+        return egl::Error(status);
+    }
+
+    mWidth = backbufferWidth;
+    mHeight = backbufferHeight;
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight)
+{
+    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
+    ASSERT(mSwapChain);
+
+    EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval);
+
+    if (status == EGL_CONTEXT_LOST)
+    {
+        mRenderer->notifyDeviceLost();
+        return egl::Error(status);
+    }
+    else if (status != EGL_SUCCESS)
+    {
+        return egl::Error(status);
+    }
+
+    mWidth = backbufferWidth;
+    mHeight = backbufferHeight;
+    mSwapIntervalDirty = false;
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    if (!mSwapChain)
+    {
+        return egl::Error(EGL_SUCCESS);
+    }
+
+    if (x + width > mWidth)
+    {
+        width = mWidth - x;
+    }
+
+    if (y + height > mHeight)
+    {
+        height = mHeight - y;
+    }
+
+    if (width != 0 && height != 0)
+    {
+        EGLint status = mSwapChain->swapRect(x, y, width, height);
+
+        if (status == EGL_CONTEXT_LOST)
+        {
+            mRenderer->notifyDeviceLost();
+            return egl::Error(status);
+        }
+        else if (status != EGL_SUCCESS)
+        {
+            return egl::Error(status);
+        }
+    }
+
+    checkForOutOfDateSwapChain();
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+bool SurfaceD3D::checkForOutOfDateSwapChain()
+{
+    RECT client;
+    int clientWidth = getWidth();
+    int clientHeight = getHeight();
+    bool sizeDirty = false;
+    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 (!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;
+        sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
+    }
+
+    bool wasDirty = (mSwapIntervalDirty || sizeDirty);
+
+    if (mSwapIntervalDirty)
+    {
+        resetSwapChain(clientWidth, clientHeight);
+    }
+    else if (sizeDirty)
+    {
+        resizeSwapChain(clientWidth, clientHeight);
+    }
+
+    return wasDirty;
+}
+
+egl::Error SurfaceD3D::swap(const DisplayImpl *displayImpl)
+{
+    return swapRect(0, 0, mWidth, mHeight);
+}
+
+egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    return swapRect(x, y, width, height);
+}
+
+rx::SwapChainD3D *SurfaceD3D::getSwapChain() const
+{
+    return mSwapChain;
+}
+
+void SurfaceD3D::setSwapInterval(EGLint interval)
+{
+    if (mSwapInterval == interval)
+    {
+        return;
+    }
+
+    mSwapInterval = interval;
+    mSwapIntervalDirty = true;
+}
+
+EGLint SurfaceD3D::getWidth() const
+{
+    return mWidth;
+}
+
+EGLint SurfaceD3D::getHeight() const
+{
+    return mHeight;
+}
+
+EGLint SurfaceD3D::isPostSubBufferSupported() const
+{
+    // post sub buffer is always possible on D3D surfaces
+    return EGL_TRUE;
+}
+
+EGLint SurfaceD3D::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+
+egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
+    {
+        *value = mSwapChain->getShareHandle();
+    }
+    else if (attribute == EGL_DXGI_KEYED_MUTEX_ANGLE)
+    {
+        *value = mSwapChain->getKeyedMutex();
+    }
+    else UNREACHABLE();
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+gl::Error SurfaceD3D::getAttachmentRenderTarget(GLenum binding,
+                                                const gl::ImageIndex &imageIndex,
+                                                FramebufferAttachmentRenderTarget **rtOut)
+{
+    if (binding == GL_BACK)
+    {
+        *rtOut = mSwapChain->getColorRenderTarget();
+    }
+    else
+    {
+        *rtOut = mSwapChain->getDepthStencilRenderTarget();
+    }
+    return gl::NoError();
+}
+
+WindowSurfaceD3D::WindowSurfaceD3D(const egl::SurfaceState &state,
+                                   RendererD3D *renderer,
+                                   egl::Display *display,
+                                   EGLNativeWindowType window,
+                                   const egl::AttributeMap &attribs)
+    : SurfaceD3D(state,
+                 renderer,
+                 display,
+                 window,
+                 0,
+                 static_cast<EGLClientBuffer>(0),
+                 attribs)
+{
+}
+
+WindowSurfaceD3D::~WindowSurfaceD3D()
+{
+}
+
+PbufferSurfaceD3D::PbufferSurfaceD3D(const egl::SurfaceState &state,
+                                     RendererD3D *renderer,
+                                     egl::Display *display,
+                                     EGLenum buftype,
+                                     EGLClientBuffer clientBuffer,
+                                     const egl::AttributeMap &attribs)
+    : SurfaceD3D(state,
+                 renderer,
+                 display,
+                 static_cast<EGLNativeWindowType>(0),
+                 buftype,
+                 clientBuffer,
+                 attribs)
+{
+}
+
+PbufferSurfaceD3D::~PbufferSurfaceD3D()
+{
+}
+
+}  // namespace rc
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
new file mode 100644
index 0000000..3be2888
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceD3D.h: D3D implementation of an EGL surface
+
+#ifndef LIBANGLE_RENDERER_D3D_SURFACED3D_H_
+#define LIBANGLE_RENDERER_D3D_SURFACED3D_H_
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace egl
+{
+class Surface;
+}
+
+namespace rx
+{
+class SwapChainD3D;
+class RendererD3D;
+
+class SurfaceD3D : public SurfaceImpl
+{
+  public:
+    ~SurfaceD3D() override;
+    void releaseSwapChain();
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+    // D3D implementations
+    SwapChainD3D *getSwapChain() const;
+
+    egl::Error resetSwapChain();
+
+    // Returns true if swapchain changed due to resize or interval update
+    bool checkForOutOfDateSwapChain();
+
+    gl::Error getAttachmentRenderTarget(GLenum binding,
+                                        const gl::ImageIndex &imageIndex,
+                                        FramebufferAttachmentRenderTarget **rtOut) override;
+
+  protected:
+    SurfaceD3D(const egl::SurfaceState &state,
+               RendererD3D *renderer,
+               egl::Display *display,
+               EGLNativeWindowType window,
+               EGLenum buftype,
+               EGLClientBuffer clientBuffer,
+               const egl::AttributeMap &attribs);
+
+    egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+    egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight);
+    egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
+
+    RendererD3D *mRenderer;
+    egl::Display *mDisplay;
+
+    bool mFixedSize;
+    GLint mOrientation;
+
+    GLenum mRenderTargetFormat;
+    GLenum mDepthStencilFormat;
+
+    SwapChainD3D *mSwapChain;
+    bool mSwapIntervalDirty;
+
+    NativeWindowD3D *mNativeWindow;  // Handler for the Window that the surface is created for.
+    EGLint mWidth;
+    EGLint mHeight;
+
+    EGLint mSwapInterval;
+
+    HANDLE mShareHandle;
+    IUnknown *mD3DTexture;
+};
+
+class WindowSurfaceD3D : public SurfaceD3D
+{
+  public:
+    WindowSurfaceD3D(const egl::SurfaceState &state,
+                     RendererD3D *renderer,
+                     egl::Display *display,
+                     EGLNativeWindowType window,
+                     const egl::AttributeMap &attribs);
+    ~WindowSurfaceD3D() override;
+};
+
+class PbufferSurfaceD3D : public SurfaceD3D
+{
+  public:
+    PbufferSurfaceD3D(const egl::SurfaceState &state,
+                      RendererD3D *renderer,
+                      egl::Display *display,
+                      EGLenum buftype,
+                      EGLClientBuffer clientBuffer,
+                      const egl::AttributeMap &attribs);
+    ~PbufferSurfaceD3D() override;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp
new file mode 100644
index 0000000..de8534c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SwapChainD3D.cpp: Defines a back-end specific class that hides the details of the
+// implementation-specific swapchain.
+
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+
+namespace rx
+{
+
+SwapChainD3D::SwapChainD3D(HANDLE shareHandle,
+                           IUnknown *d3dTexture,
+                           GLenum backBufferFormat,
+                           GLenum depthBufferFormat)
+    : mOffscreenRenderTargetFormat(backBufferFormat),
+      mDepthBufferFormat(depthBufferFormat),
+      mShareHandle(shareHandle),
+      mD3DTexture(d3dTexture)
+{
+    if (mD3DTexture)
+    {
+        mD3DTexture->AddRef();
+    }
+}
+
+SwapChainD3D::~SwapChainD3D()
+{
+    SafeRelease(mD3DTexture);
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
new file mode 100644
index 0000000..5472864
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChainD3D.h: Defines a back-end specific class that hides the details of the
+// implementation-specific swapchain.
+
+#ifndef LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
+#define LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
+
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "common/angleutils.h"
+#include "common/platform.h"
+#include "libANGLE/Error.h"
+
+#if !defined(ANGLE_FORCE_VSYNC_OFF)
+#define ANGLE_FORCE_VSYNC_OFF 0
+#endif
+
+namespace rx
+{
+class RenderTargetD3D;
+
+class SwapChainD3D : angle::NonCopyable
+{
+  public:
+    SwapChainD3D(HANDLE shareHandle,
+                 IUnknown *d3dTexture,
+                 GLenum backBufferFormat,
+                 GLenum depthBufferFormat);
+    virtual ~SwapChainD3D();
+
+    virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0;
+    virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
+    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
+    virtual void recreate() = 0;
+
+    virtual RenderTargetD3D *getColorRenderTarget() = 0;
+    virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0;
+
+    GLenum getRenderTargetInternalFormat() const { return mOffscreenRenderTargetFormat; }
+    GLenum getDepthBufferInternalFormat() const { return mDepthBufferFormat; }
+
+    HANDLE getShareHandle() { return mShareHandle; }
+    virtual void *getKeyedMutex() = 0;
+
+    virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 0;
+
+  protected:
+    const GLenum mOffscreenRenderTargetFormat;
+    const GLenum mDepthBufferFormat;
+
+    HANDLE mShareHandle;
+    IUnknown *mD3DTexture;
+};
+
+}  // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
new file mode 100644
index 0000000..5c33fc4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -0,0 +1,3413 @@
+//
+// 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.
+//
+
+// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends.
+
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/BufferImpl.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+
+namespace rx
+{
+
+namespace
+{
+
+gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pixels,
+                           ptrdiff_t layerOffset, const uint8_t **pointerOut)
+{
+    if (unpack.pixelBuffer.id() != 0)
+    {
+        // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
+        gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
+        ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
+
+        // TODO: this is the only place outside of renderer that asks for a buffers raw data.
+        // This functionality should be moved into renderer and the getData method of BufferImpl removed.
+        BufferD3D *bufferD3D = GetImplAs<BufferD3D>(pixelBuffer);
+        ASSERT(bufferD3D);
+        const uint8_t *bufferData = nullptr;
+        ANGLE_TRY(bufferD3D->getData(&bufferData));
+        *pointerOut = bufferData + offset;
+    }
+    else
+    {
+        *pointerOut = pixels;
+    }
+
+    // Offset the pointer for 2D array layer (if it's valid)
+    if (*pointerOut != nullptr)
+    {
+        *pointerOut += layerOffset;
+    }
+
+    return gl::NoError();
+}
+
+bool IsRenderTargetUsage(GLenum usage)
+{
+    return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+}
+
+}
+
+TextureD3D::TextureD3D(const gl::TextureState &state, RendererD3D *renderer)
+    : TextureImpl(state),
+      mRenderer(renderer),
+      mDirtyImages(true),
+      mImmutable(false),
+      mTexStorage(nullptr),
+      mBaseLevel(0)
+{
+}
+
+TextureD3D::~TextureD3D()
+{
+}
+
+gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage)
+{
+    // ensure the underlying texture is created
+    ANGLE_TRY(initializeStorage(false));
+
+    if (mTexStorage)
+    {
+        ANGLE_TRY(updateStorage());
+    }
+
+    ASSERT(outStorage);
+
+    *outStorage = mTexStorage;
+    return gl::NoError();
+}
+
+GLint TextureD3D::getLevelZeroWidth() const
+{
+    ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelWidth())) > getBaseLevel());
+    return getBaseLevelWidth() << mBaseLevel;
+}
+
+GLint TextureD3D::getLevelZeroHeight() const
+{
+    ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelHeight())) > getBaseLevel());
+    return getBaseLevelHeight() << mBaseLevel;
+}
+
+GLint TextureD3D::getLevelZeroDepth() const
+{
+    return getBaseLevelDepth();
+}
+
+GLint TextureD3D::getBaseLevelWidth() const
+{
+    const ImageD3D *baseImage = getBaseLevelImage();
+    return (baseImage ? baseImage->getWidth() : 0);
+}
+
+GLint TextureD3D::getBaseLevelHeight() const
+{
+    const ImageD3D *baseImage = getBaseLevelImage();
+    return (baseImage ? baseImage->getHeight() : 0);
+}
+
+GLint TextureD3D::getBaseLevelDepth() const
+{
+    const ImageD3D *baseImage = getBaseLevelImage();
+    return (baseImage ? baseImage->getDepth() : 0);
+}
+
+// Note: "base level image" is loosely defined to be any image from the base level,
+// 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 TextureD3D::getBaseLevelInternalFormat() const
+{
+    const ImageD3D *baseImage = getBaseLevelImage();
+    return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
+}
+
+gl::Error TextureD3D::setStorageMultisample(ContextImpl *contextImpl,
+                                            GLenum target,
+                                            GLsizei samples,
+                                            GLint internalFormat,
+                                            const gl::Extents &size,
+                                            GLboolean fixedSampleLocations)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError() << "setStorageMultisample is unimplemented.";
+}
+
+bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
+{
+    if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload)
+    {
+        return false;
+    }
+
+    gl::InternalFormat internalFormat = gl::GetSizedInternalFormatInfo(image->getInternalFormat());
+
+    // We can only handle full updates for depth-stencil textures, so to avoid complications
+    // disable them entirely.
+    if (internalFormat.depthBits > 0 || internalFormat.stencilBits > 0)
+    {
+        return false;
+    }
+
+    // TODO(jmadill): Handle compressed internal formats
+    return (mTexStorage && !internalFormat.compressed);
+}
+
+gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index,
+                                   GLenum type,
+                                   const gl::PixelUnpackState &unpack,
+                                   const uint8_t *pixels,
+                                   ptrdiff_t layerOffset)
+{
+    ImageD3D *image = getImage(index);
+    ASSERT(image);
+
+    // No-op
+    if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
+    {
+        return gl::NoError();
+    }
+
+    // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
+    // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
+    const uint8_t *pixelData = nullptr;
+    ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData));
+
+    if (pixelData != nullptr)
+    {
+        if (shouldUseSetData(image))
+        {
+            ANGLE_TRY(mTexStorage->setData(index, image, nullptr, type, unpack, pixelData));
+        }
+        else
+        {
+            gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+            ANGLE_TRY(image->loadData(fullImageArea, unpack, type, pixelData, index.is3D()));
+        }
+
+        mDirtyImages = true;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
+                               const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset)
+{
+    // CPU readback & copy where direct GPU copy is not supported
+    const uint8_t *pixelData = nullptr;
+    ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData));
+
+    if (pixelData != nullptr)
+    {
+        ImageD3D *image = getImage(index);
+        ASSERT(image);
+
+        if (shouldUseSetData(image))
+        {
+            return mTexStorage->setData(index, image, &area, type, unpack, pixelData);
+        }
+
+        ANGLE_TRY(image->loadData(area, unpack, type, pixelData, index.is3D()));
+        ANGLE_TRY(commitRegion(index, area));
+        mDirtyImages = true;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D::setCompressedImageImpl(const gl::ImageIndex &index,
+                                             const gl::PixelUnpackState &unpack,
+                                             const uint8_t *pixels,
+                                             ptrdiff_t layerOffset)
+{
+    ImageD3D *image = getImage(index);
+    ASSERT(image);
+
+    if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
+    {
+        return gl::NoError();
+    }
+
+    // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
+    // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
+    const uint8_t *pixelData = nullptr;
+    ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData));
+
+    if (pixelData != nullptr)
+    {
+        gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+        ANGLE_TRY(image->loadCompressedData(fullImageArea, pixelData));
+
+        mDirtyImages = true;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format,
+                                         const gl::PixelUnpackState &unpack, const uint8_t *pixels,
+                                         ptrdiff_t layerOffset)
+{
+    const uint8_t *pixelData = nullptr;
+    ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData));
+
+    if (pixelData != nullptr)
+    {
+        ImageD3D *image = getImage(index);
+        ASSERT(image);
+
+        ANGLE_TRY(image->loadCompressedData(area, pixelData));
+
+        mDirtyImages = true;
+    }
+
+    return gl::NoError();
+}
+
+bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat)
+{
+    return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
+}
+
+gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
+                                       GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget)
+{
+    if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 ||
+        unpack.skipImages != 0)
+    {
+        // TODO(jmadill): additional unpack parameters
+        UNIMPLEMENTED();
+        return gl::Error(GL_INVALID_OPERATION,
+                         "Unimplemented pixel store parameters in fastUnpackPixels");
+    }
+
+    // No-op
+    if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
+    {
+        return gl::NoError();
+    }
+
+    // In order to perform the fast copy through the shader, we must have the right format, and be able
+    // to create a render target.
+    ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));
+
+    uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);
+
+    ANGLE_TRY(mRenderer->fastCopyBufferToTexture(unpack, static_cast<unsigned int>(offset),
+                                                 destRenderTarget, sizedInternalFormat, type,
+                                                 destArea));
+
+    return gl::NoError();
+}
+
+GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
+{
+    if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) ||
+        mRenderer->getNativeExtensions().textureNPOT)
+    {
+        // Maximum number of levels
+        return gl::log2(std::max(std::max(width, height), depth)) + 1;
+    }
+    else
+    {
+        // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
+        return 1;
+    }
+}
+
+TextureStorage *TextureD3D::getStorage()
+{
+    ASSERT(mTexStorage);
+    return mTexStorage;
+}
+
+ImageD3D *TextureD3D::getBaseLevelImage() const
+{
+    if (mBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+    {
+        return nullptr;
+    }
+    return getImage(getImageIndex(mBaseLevel, 0));
+}
+
+gl::Error TextureD3D::setImageExternal(GLenum target,
+                                       egl::Stream *stream,
+                                       const egl::Stream::GLTextureDescription &desc)
+{
+    // Only external images can accept external textures
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D::generateMipmap(ContextImpl *contextImpl)
+{
+    const GLuint baseLevel = mState.getEffectiveBaseLevel();
+    const GLuint maxLevel = mState.getMipmapMaxLevel();
+    ASSERT(maxLevel > baseLevel);  // Should be checked before calling this.
+
+    if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        // Switch to using the mipmapped texture.
+        TextureStorage *textureStorage = nullptr;
+        ANGLE_TRY(getNativeTexture(&textureStorage));
+        ANGLE_TRY(textureStorage->useLevelZeroWorkaroundTexture(false));
+    }
+
+    // Set up proper mipmap chain in our Image array.
+    initMipmapImages();
+
+    if (mTexStorage && mTexStorage->supportsNativeMipmapFunction())
+    {
+        ANGLE_TRY(updateStorage());
+
+        // Generate the mipmap chain using the ad-hoc DirectX function.
+        ANGLE_TRY(mRenderer->generateMipmapUsingD3D(mTexStorage, mState));
+    }
+    else
+    {
+        // Generate the mipmap chain, one level at a time.
+        ANGLE_TRY(generateMipmapUsingImages(maxLevel));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D::generateMipmapUsingImages(const GLuint maxLevel)
+{
+    // We know that all layers have the same dimension, for the texture to be complete
+    GLint layerCount = static_cast<GLint>(getLayerCount(mBaseLevel));
+
+    // When making mipmaps with the setData workaround enabled, the texture storage has
+    // the image data already. For non-render-target storage, we have to pull it out into
+    // an image layer.
+    if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage)
+    {
+        if (!mTexStorage->isRenderTarget())
+        {
+            // Copy from the storage mip 0 to Image mip 0
+            for (GLint layer = 0; layer < layerCount; ++layer)
+            {
+                gl::ImageIndex srcIndex = getImageIndex(mBaseLevel, layer);
+
+                ImageD3D *image = getImage(srcIndex);
+                ANGLE_TRY(image->copyFromTexStorage(srcIndex, mTexStorage));
+            }
+        }
+        else
+        {
+            ANGLE_TRY(updateStorage());
+        }
+    }
+
+    // TODO: Decouple this from zeroMaxLodWorkaround. This is a 9_3 restriction, unrelated to zeroMaxLodWorkaround.
+    // The restriction is because Feature Level 9_3 can't create SRVs on individual levels of the texture.
+    // As a result, even if the storage is a rendertarget, we can't use the GPU to generate the mipmaps without further work.
+    // The D3D9 renderer works around this by copying each level of the texture into its own single-layer GPU texture (in Blit9::boxFilter).
+    // Feature Level 9_3 could do something similar, or it could continue to use CPU-side mipmap generation, or something else.
+    bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget() && !(mRenderer->getWorkarounds().zeroMaxLodWorkaround));
+
+    for (GLint layer = 0; layer < layerCount; ++layer)
+    {
+        for (GLuint mip = mBaseLevel + 1; mip <= maxLevel; ++mip)
+        {
+            ASSERT(getLayerCount(mip) == layerCount);
+
+            gl::ImageIndex sourceIndex = getImageIndex(mip - 1, layer);
+            gl::ImageIndex destIndex = getImageIndex(mip, layer);
+
+            if (renderableStorage)
+            {
+                // GPU-side mipmapping
+                ANGLE_TRY(mTexStorage->generateMipmap(sourceIndex, destIndex));
+            }
+            else
+            {
+                // CPU-side mipmapping
+                ANGLE_TRY(mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex)));
+            }
+        }
+    }
+
+    if (mTexStorage)
+    {
+        updateStorage();
+    }
+
+    return gl::NoError();
+}
+
+bool TextureD3D::isBaseImageZeroSize() const
+{
+    ImageD3D *baseImage = getBaseLevelImage();
+
+    if (!baseImage || baseImage->getWidth() <= 0)
+    {
+        return true;
+    }
+
+    if (!gl::IsCubeMapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0)
+    {
+        return true;
+    }
+
+    if (baseImage->getTarget() == GL_TEXTURE_3D && baseImage->getDepth() <= 0)
+    {
+        return true;
+    }
+
+    if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(getBaseLevel()) <= 0)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+gl::Error TextureD3D::ensureRenderTarget()
+{
+    ANGLE_TRY(initializeStorage(true));
+
+    // initializeStorage can fail with NoError if the texture is not complete. This is not
+    // an error for incomplete sampling, but it is a big problem for rendering.
+    if (!mTexStorage)
+    {
+        UNREACHABLE();
+        return gl::InternalError() << "Cannot render to incomplete texture.";
+    }
+
+    if (!isBaseImageZeroSize())
+    {
+        ASSERT(mTexStorage);
+        if (!mTexStorage->isRenderTarget())
+        {
+            TextureStorage *newRenderTargetStorage = nullptr;
+            ANGLE_TRY(createCompleteStorage(true, &newRenderTargetStorage));
+
+            std::unique_ptr<TextureStorage> newStorageRef(newRenderTargetStorage);
+            ANGLE_TRY(mTexStorage->copyToStorage(newRenderTargetStorage));
+            ANGLE_TRY(setCompleteTexStorage(newRenderTargetStorage));
+            newStorageRef.release();
+        }
+    }
+
+    return gl::NoError();
+}
+
+bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const
+{
+    ImageD3D *image = getImage(index);
+    bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0)));
+    return (image->isRenderableFormat() && levelsComplete);
+}
+
+gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box &region)
+{
+    if (mTexStorage)
+    {
+        ASSERT(isValidIndex(index));
+        ImageD3D *image = getImage(index);
+        ANGLE_TRY(image->copyToStorage(mTexStorage, index, region));
+        image->markClean();
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D::getAttachmentRenderTarget(GLenum /*binding*/,
+                                                const gl::ImageIndex &imageIndex,
+                                                FramebufferAttachmentRenderTarget **rtOut)
+{
+    RenderTargetD3D *rtD3D = nullptr;
+    gl::Error error        = getRenderTarget(imageIndex, &rtD3D);
+    *rtOut = static_cast<FramebufferAttachmentRenderTarget *>(rtD3D);
+    return error;
+}
+
+void TextureD3D::setBaseLevel(GLuint baseLevel)
+{
+    const int oldStorageWidth  = std::max(1, getLevelZeroWidth());
+    const int oldStorageHeight = std::max(1, getLevelZeroHeight());
+    const int oldStorageDepth  = std::max(1, getLevelZeroDepth());
+    const int oldStorageFormat = getBaseLevelInternalFormat();
+    mBaseLevel                 = baseLevel;
+
+    // When the base level changes, the texture storage might not be valid anymore, since it could
+    // have been created based on the dimensions of the previous specified level range.
+    const int newStorageWidth  = std::max(1, getLevelZeroWidth());
+    const int newStorageHeight = std::max(1, getLevelZeroHeight());
+    const int newStorageDepth = std::max(1, getLevelZeroDepth());
+    const int newStorageFormat = getBaseLevelInternalFormat();
+    if (mTexStorage &&
+        (newStorageWidth != oldStorageWidth || newStorageHeight != oldStorageHeight ||
+         newStorageDepth != oldStorageDepth || newStorageFormat != oldStorageFormat))
+    {
+        markAllImagesDirty();
+        SafeDelete(mTexStorage);
+    }
+}
+
+void TextureD3D::syncState(const gl::Texture::DirtyBits &dirtyBits)
+{
+    // TODO(geofflang): Use dirty bits
+}
+
+TextureD3D_2D::TextureD3D_2D(const gl::TextureState &state, RendererD3D *renderer)
+    : TextureD3D(state, renderer)
+{
+    mEGLImageTarget = false;
+    for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+    {
+        mImageArray[i] = renderer->createImage();
+    }
+}
+
+TextureD3D_2DMultisample::TextureD3D_2DMultisample(const gl::TextureState &state,
+                                                   RendererD3D *renderer)
+    : TextureD3D(state, renderer)
+{
+}
+
+TextureD3D_2DMultisample::~TextureD3D_2DMultisample()
+{
+}
+
+ImageD3D *TextureD3D_2DMultisample::getImage(const gl::ImageIndex &index) const
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+gl::Error TextureD3D_2DMultisample::setImage(ContextImpl *contextImpl,
+                                             GLenum target,
+                                             size_t level,
+                                             GLenum internalFormat,
+                                             const gl::Extents &size,
+                                             GLenum format,
+                                             GLenum type,
+                                             const gl::PixelUnpackState &unpack,
+                                             const uint8_t *pixels)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setSubImage(ContextImpl *contextImpl,
+                                                GLenum target,
+                                                size_t level,
+                                                const gl::Box &area,
+                                                GLenum format,
+                                                GLenum type,
+                                                const gl::PixelUnpackState &unpack,
+                                                const uint8_t *pixels)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setCompressedImage(ContextImpl *contextImpl,
+                                                       GLenum target,
+                                                       size_t level,
+                                                       GLenum internalFormat,
+                                                       const gl::Extents &size,
+                                                       const gl::PixelUnpackState &unpack,
+                                                       size_t imageSize,
+                                                       const uint8_t *pixels)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setCompressedSubImage(ContextImpl *contextImpl,
+                                                          GLenum target,
+                                                          size_t level,
+                                                          const gl::Box &area,
+                                                          GLenum format,
+                                                          const gl::PixelUnpackState &unpack,
+                                                          size_t imageSize,
+                                                          const uint8_t *pixels)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::copyImage(ContextImpl *contextImpl,
+                                              GLenum target,
+                                              size_t level,
+                                              const gl::Rectangle &sourceArea,
+                                              GLenum internalFormat,
+                                              const gl::Framebuffer *source)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::copySubImage(ContextImpl *contextImpl,
+                                                 GLenum target,
+                                                 size_t level,
+                                                 const gl::Offset &destOffset,
+                                                 const gl::Rectangle &sourceArea,
+                                                 const gl::Framebuffer *source)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setStorage(ContextImpl *contextImpl,
+                                               GLenum target,
+                                               size_t levels,
+                                               GLenum internalFormat,
+                                               const gl::Extents &size)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setImageExternal(GLenum target,
+                                                     egl::Stream *stream,
+                                                     const egl::Stream::GLTextureDescription &desc)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+void TextureD3D_2DMultisample::bindTexImage(egl::Surface *surface)
+{
+    UNIMPLEMENTED();
+}
+
+void TextureD3D_2DMultisample::releaseTexImage()
+{
+    UNIMPLEMENTED();
+}
+
+gl::Error TextureD3D_2DMultisample::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::getRenderTarget(const gl::ImageIndex &index,
+                                                    RenderTargetD3D **outRT)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::ImageIndexIterator TextureD3D_2DMultisample::imageIterator() const
+{
+    UNIMPLEMENTED();
+    return gl::ImageIndexIterator::Make2DMultisample();
+}
+
+gl::ImageIndex TextureD3D_2DMultisample::getImageIndex(GLint mip, GLint layer) const
+{
+    UNIMPLEMENTED();
+    return gl::ImageIndex::Make2DMultisample();
+}
+
+bool TextureD3D_2DMultisample::isValidIndex(const gl::ImageIndex &index) const
+{
+    UNIMPLEMENTED();
+    return false;
+}
+
+GLsizei TextureD3D_2DMultisample::getLayerCount(int level) const
+{
+    UNIMPLEMENTED();
+    return GLsizei();
+}
+
+void TextureD3D_2DMultisample::markAllImagesDirty()
+{
+    UNIMPLEMENTED();
+}
+
+gl::Error TextureD3D_2DMultisample::initializeStorage(bool renderTarget)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::createCompleteStorage(bool renderTarget,
+                                                          TextureStorage **outTexStorage) const
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::updateStorage()
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+void TextureD3D_2DMultisample::initMipmapImages()
+{
+    UNIMPLEMENTED();
+}
+
+bool TextureD3D_2DMultisample::isImageComplete(const gl::ImageIndex &index) const
+{
+    UNIMPLEMENTED();
+    return false;
+}
+
+TextureD3D_2D::~TextureD3D_2D()
+{
+    // Delete the Images before the TextureStorage.
+    // Images might be relying on the TextureStorage for some of their data.
+    // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
+    for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+    {
+        SafeDelete(mImageArray[i]);
+    }
+
+    SafeDelete(mTexStorage);
+}
+
+ImageD3D *TextureD3D_2D::getImage(int level, int layer) const
+{
+    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(layer == 0);
+    return mImageArray[level];
+}
+
+ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
+{
+    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(!index.hasLayer());
+    ASSERT(index.type == GL_TEXTURE_2D);
+    return mImageArray[index.mipIndex];
+}
+
+GLsizei TextureD3D_2D::getLayerCount(int level) const
+{
+    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    return 1;
+}
+
+GLsizei TextureD3D_2D::getWidth(GLint level) const
+{
+    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level]->getWidth();
+    else
+        return 0;
+}
+
+GLsizei TextureD3D_2D::getHeight(GLint level) const
+{
+    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level]->getHeight();
+    else
+        return 0;
+}
+
+GLenum TextureD3D_2D::getInternalFormat(GLint level) const
+{
+    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level]->getInternalFormat();
+    else
+        return GL_NONE;
+}
+
+bool TextureD3D_2D::isDepth(GLint level) const
+{
+    return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+gl::Error TextureD3D_2D::setImage(ContextImpl *contextImpl,
+                                  GLenum target,
+                                  size_t imageLevel,
+                                  GLenum internalFormat,
+                                  const gl::Extents &size,
+                                  GLenum format,
+                                  GLenum type,
+                                  const gl::PixelUnpackState &unpack,
+                                  const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_2D && size.depth == 1);
+
+    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+
+    bool fastUnpacked = false;
+    GLint level       = static_cast<GLint>(imageLevel);
+
+    redefineImage(level, internalFormatInfo.sizedInternalFormat, size, false);
+
+    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+
+    // Attempt a fast gpu copy of the pixel data to the surface
+    if (isFastUnpackable(unpack, internalFormatInfo.sizedInternalFormat) && isLevelComplete(level))
+    {
+        // Will try to create RT storage if it does not exist
+        RenderTargetD3D *destRenderTarget = nullptr;
+        ANGLE_TRY(getRenderTarget(index, &destRenderTarget));
+
+        gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
+
+        ANGLE_TRY(fastUnpackPixels(unpack, pixels, destArea, internalFormatInfo.sizedInternalFormat,
+                                   type, destRenderTarget));
+
+        // Ensure we don't overwrite our newly initialized data
+        mImageArray[level]->markClean();
+
+        fastUnpacked = true;
+    }
+
+    if (!fastUnpacked)
+    {
+        ANGLE_TRY(setImageImpl(index, type, unpack, pixels, 0));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::setSubImage(ContextImpl *contextImpl,
+                                     GLenum target,
+                                     size_t imageLevel,
+                                     const gl::Box &area,
+                                     GLenum format,
+                                     GLenum type,
+                                     const gl::PixelUnpackState &unpack,
+                                     const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
+
+    GLint level          = static_cast<GLint>(imageLevel);
+    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+    if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
+    {
+        RenderTargetD3D *renderTarget = nullptr;
+        ANGLE_TRY(getRenderTarget(index, &renderTarget));
+        ASSERT(!mImageArray[level]->isDirty());
+
+        return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget);
+    }
+    else
+    {
+        return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+    }
+}
+
+gl::Error TextureD3D_2D::setCompressedImage(ContextImpl *contextImpl,
+                                            GLenum target,
+                                            size_t imageLevel,
+                                            GLenum internalFormat,
+                                            const gl::Extents &size,
+                                            const gl::PixelUnpackState &unpack,
+                                            size_t imageSize,
+                                            const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_2D && size.depth == 1);
+    GLint level = static_cast<GLint>(imageLevel);
+
+    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+    redefineImage(level, internalFormat, size, false);
+
+    return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_2D::setCompressedSubImage(ContextImpl *contextImpl,
+                                               GLenum target,
+                                               size_t level,
+                                               const gl::Box &area,
+                                               GLenum format,
+                                               const gl::PixelUnpackState &unpack,
+                                               size_t imageSize,
+                                               const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
+
+    gl::ImageIndex index = gl::ImageIndex::Make2D(static_cast<GLint>(level));
+    ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
+
+    return commitRegion(index, area);
+}
+
+gl::Error TextureD3D_2D::copyImage(ContextImpl *contextImpl,
+                                   GLenum target,
+                                   size_t imageLevel,
+                                   const gl::Rectangle &sourceArea,
+                                   GLenum internalFormat,
+                                   const gl::Framebuffer *source)
+{
+    ASSERT(target == GL_TEXTURE_2D);
+
+    GLint level                = static_cast<GLint>(imageLevel);
+    const gl::InternalFormat &internalFormatInfo =
+        gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
+    redefineImage(level, internalFormatInfo.sizedInternalFormat,
+                  gl::Extents(sourceArea.width, sourceArea.height, 1), false);
+
+    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+    gl::Offset destOffset(0, 0, 0);
+
+    // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+    // so we should use the non-rendering copy path.
+    if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
+        mDirtyImages = true;
+    }
+    else
+    {
+        ANGLE_TRY(ensureRenderTarget());
+        mImageArray[level]->markClean();
+
+        if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level))
+        {
+            ANGLE_TRY(mRenderer->copyImage2D(source, sourceArea, internalFormat, destOffset,
+                                             mTexStorage, level));
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::copySubImage(ContextImpl *contextImpl,
+                                      GLenum target,
+                                      size_t imageLevel,
+                                      const gl::Offset &destOffset,
+                                      const gl::Rectangle &sourceArea,
+                                      const gl::Framebuffer *source)
+{
+    ASSERT(target == GL_TEXTURE_2D && destOffset.z == 0);
+
+    // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
+    // the current level we're copying to is defined (with appropriate format, width & height)
+
+    GLint level          = static_cast<GLint>(imageLevel);
+    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+
+    // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+    // so we should use the non-rendering copy path.
+    if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
+        mDirtyImages = true;
+    }
+    else
+    {
+        ANGLE_TRY(ensureRenderTarget());
+
+        if (isValidLevel(level))
+        {
+            ANGLE_TRY(updateStorageLevel(level));
+            ANGLE_TRY(mRenderer->copyImage2D(source, sourceArea,
+                                             gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
+                                             destOffset, mTexStorage, level));
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::copyTexture(ContextImpl *contextImpl,
+                                     GLenum target,
+                                     size_t level,
+                                     GLenum internalFormat,
+                                     GLenum type,
+                                     size_t sourceLevel,
+                                     bool unpackFlipY,
+                                     bool unpackPremultiplyAlpha,
+                                     bool unpackUnmultiplyAlpha,
+                                     const gl::Texture *source)
+{
+    ASSERT(target == GL_TEXTURE_2D);
+
+    GLenum sourceTarget = source->getTarget();
+
+    GLint destLevel = static_cast<GLint>(level);
+
+    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+    gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+                     static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+    redefineImage(destLevel, internalFormatInfo.sizedInternalFormat, size, false);
+
+    ASSERT(canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)));
+
+    ANGLE_TRY(ensureRenderTarget());
+    ASSERT(isValidLevel(destLevel));
+    ANGLE_TRY(updateStorageLevel(destLevel));
+
+    gl::Rectangle sourceRect(0, 0, size.width, size.height);
+    gl::Offset destOffset(0, 0, 0);
+    ANGLE_TRY(mRenderer->copyTexture(source, static_cast<GLint>(sourceLevel), sourceRect,
+                                     internalFormatInfo.format, destOffset, mTexStorage, target,
+                                     destLevel, unpackFlipY, unpackPremultiplyAlpha,
+                                     unpackUnmultiplyAlpha));
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::copySubTexture(ContextImpl *contextImpl,
+                                        GLenum target,
+                                        size_t level,
+                                        const gl::Offset &destOffset,
+                                        size_t sourceLevel,
+                                        const gl::Rectangle &sourceArea,
+                                        bool unpackFlipY,
+                                        bool unpackPremultiplyAlpha,
+                                        bool unpackUnmultiplyAlpha,
+                                        const gl::Texture *source)
+{
+    ASSERT(target == GL_TEXTURE_2D);
+
+    GLint destLevel = static_cast<GLint>(level);
+
+    ASSERT(canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)));
+
+    ANGLE_TRY(ensureRenderTarget());
+    ASSERT(isValidLevel(destLevel));
+    ANGLE_TRY(updateStorageLevel(destLevel));
+
+    ANGLE_TRY(mRenderer->copyTexture(source, static_cast<GLint>(sourceLevel), sourceArea,
+                                     gl::GetUnsizedFormat(getBaseLevelInternalFormat()), destOffset,
+                                     mTexStorage, target, destLevel, unpackFlipY,
+                                     unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::copyCompressedTexture(ContextImpl *contextImpl, const gl::Texture *source)
+{
+    GLenum sourceTarget = source->getTarget();
+    GLint sourceLevel   = 0;
+
+    GLint destLevel = 0;
+
+    GLenum sizedInternalFormat =
+        source->getFormat(sourceTarget, sourceLevel).info->sizedInternalFormat;
+    gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+                     static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+    redefineImage(destLevel, sizedInternalFormat, size, false);
+
+    ANGLE_TRY(initializeStorage(false));
+    ASSERT(mTexStorage);
+
+    ANGLE_TRY(mRenderer->copyCompressedTexture(source, sourceLevel, mTexStorage, destLevel));
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::setStorage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t levels,
+                                    GLenum internalFormat,
+                                    const gl::Extents &size)
+{
+    ASSERT(GL_TEXTURE_2D && size.depth == 1);
+
+    for (size_t level = 0; level < levels; level++)
+    {
+        gl::Extents levelSize(std::max(1, size.width >> level),
+                              std::max(1, size.height >> level),
+                              1);
+        redefineImage(level, internalFormat, levelSize, true);
+    }
+
+    for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true);
+    }
+
+    // TODO(geofflang): Verify storage creation had no errors
+    bool renderTarget       = IsRenderTargetUsage(mState.getUsage());
+    TextureStorage *storage = mRenderer->createTextureStorage2D(
+        internalFormat, renderTarget, size.width, size.height, static_cast<int>(levels), false);
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    ANGLE_TRY(updateStorage());
+
+    mImmutable = true;
+
+    return gl::NoError();
+}
+
+void TextureD3D_2D::bindTexImage(egl::Surface *surface)
+{
+    GLenum internalformat = surface->getConfig()->renderTargetFormat;
+
+    gl::Extents size(surface->getWidth(), surface->getHeight(), 1);
+    redefineImage(0, internalformat, size, true);
+
+    if (mTexStorage)
+    {
+        SafeDelete(mTexStorage);
+    }
+
+    SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+    ASSERT(surfaceD3D);
+
+    mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain());
+    mEGLImageTarget = false;
+
+    mDirtyImages = true;
+}
+
+void TextureD3D_2D::releaseTexImage()
+{
+    if (mTexStorage)
+    {
+        SafeDelete(mTexStorage);
+    }
+
+    for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        redefineImage(i, GL_NONE, gl::Extents(0, 0, 1), true);
+    }
+}
+
+gl::Error TextureD3D_2D::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+    EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
+
+    // Set the properties of the base mip level from the EGL image
+    const auto &format = image->getFormat();
+    gl::Extents size(static_cast<int>(image->getWidth()), static_cast<int>(image->getHeight()), 1);
+    redefineImage(0, format.info->sizedInternalFormat, size, true);
+
+    // Clear all other images.
+    for (size_t level = 1; level < ArraySize(mImageArray); level++)
+    {
+        redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true);
+    }
+
+    SafeDelete(mTexStorage);
+    mImageArray[0]->markClean();
+
+    // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
+    RenderTargetD3D *renderTargetD3D = nullptr;
+    ANGLE_TRY(eglImaged3d->getRenderTarget(&renderTargetD3D));
+
+    mTexStorage     = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);
+    mEGLImageTarget = true;
+
+    return gl::NoError();
+}
+
+void TextureD3D_2D::initMipmapImages()
+{
+    const GLuint baseLevel = mState.getEffectiveBaseLevel();
+    const GLuint maxLevel  = mState.getMipmapMaxLevel();
+    // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+    // levels.
+    for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
+    {
+        gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
+                              std::max(getLevelZeroHeight() >> level, 1), 1);
+
+        redefineImage(level, getBaseLevelInternalFormat(), levelSize, false);
+    }
+}
+
+gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+    ASSERT(!index.hasLayer());
+
+    // ensure the underlying texture is created
+    ANGLE_TRY(ensureRenderTarget());
+    ANGLE_TRY(updateStorageLevel(index.mipIndex));
+
+    return mTexStorage->getRenderTarget(index, outRT);
+}
+
+bool TextureD3D_2D::isValidLevel(int level) const
+{
+    return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false);
+}
+
+bool TextureD3D_2D::isLevelComplete(int level) const
+{
+    if (isImmutable())
+    {
+        return true;
+    }
+
+    GLsizei width  = getLevelZeroWidth();
+    GLsizei height = getLevelZeroHeight();
+
+    if (width <= 0 || height <= 0)
+    {
+        return false;
+    }
+
+    // The base image level is complete if the width and height are positive
+    if (level == static_cast<int>(getBaseLevel()))
+    {
+        return true;
+    }
+
+    ASSERT(level >= 0 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != nullptr);
+    ImageD3D *image = mImageArray[level];
+
+    if (image->getInternalFormat() != getBaseLevelInternalFormat())
+    {
+        return false;
+    }
+
+    if (image->getWidth() != std::max(1, width >> level))
+    {
+        return false;
+    }
+
+    if (image->getHeight() != std::max(1, height >> level))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const
+{
+    return isLevelComplete(index.mipIndex);
+}
+
+// Constructs a native texture resource from the texture images
+gl::Error TextureD3D_2D::initializeStorage(bool renderTarget)
+{
+    // Only initialize the first time this texture is used as a render target or shader resource
+    if (mTexStorage)
+    {
+        return gl::NoError();
+    }
+
+    // do not attempt to create storage for nonexistant data
+    if (!isLevelComplete(getBaseLevel()))
+    {
+        return gl::NoError();
+    }
+
+    bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
+
+    TextureStorage *storage = nullptr;
+    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    ASSERT(mTexStorage);
+
+    // flush image data to the storage
+    ANGLE_TRY(updateStorage());
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
+{
+    GLsizei width         = getLevelZeroWidth();
+    GLsizei height        = getLevelZeroHeight();
+    GLenum internalFormat = getBaseLevelInternalFormat();
+
+    ASSERT(width > 0 && height > 0);
+
+    // use existing storage level count, when previously specified by TexStorage*D
+    GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
+
+    bool hintLevelZeroOnly = false;
+    if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        // If any of the CPU images (levels >= 1) are dirty, then the textureStorage2D should use the mipped texture to begin with.
+        // Otherwise, it should use the level-zero-only texture.
+        hintLevelZeroOnly = true;
+        for (int level = 1; level < levels && hintLevelZeroOnly; level++)
+        {
+            hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(level));
+        }
+    }
+
+    // TODO(geofflang): Determine if the texture creation succeeded
+    *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly);
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+    if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
+    {
+        for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
+        {
+            ANGLE_TRY(mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level));
+        }
+    }
+
+    SafeDelete(mTexStorage);
+    mTexStorage = newCompleteTexStorage;
+
+    mDirtyImages = true;
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::updateStorage()
+{
+    ASSERT(mTexStorage != nullptr);
+    GLint storageLevels = mTexStorage->getLevelCount();
+    for (int level = 0; level < storageLevels; level++)
+    {
+        if (mImageArray[level]->isDirty() && isLevelComplete(level))
+        {
+            ANGLE_TRY(updateStorageLevel(level));
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::updateStorageLevel(int level)
+{
+    ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != nullptr);
+    ASSERT(isLevelComplete(level));
+
+    if (mImageArray[level]->isDirty())
+    {
+        gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+        gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
+        ANGLE_TRY(commitRegion(index, region));
+    }
+
+    return gl::NoError();
+}
+
+void TextureD3D_2D::redefineImage(size_t level,
+                                  GLenum internalformat,
+                                  const gl::Extents &size,
+                                  bool forceRelease)
+{
+    ASSERT(size.depth == 1);
+
+    // If there currently is a corresponding storage texture image, it has these parameters
+    const int storageWidth     = std::max(1, getLevelZeroWidth() >> level);
+    const int storageHeight    = std::max(1, getLevelZeroHeight() >> level);
+    const GLenum storageFormat = getBaseLevelInternalFormat();
+
+    mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, forceRelease);
+
+    if (mTexStorage)
+    {
+        const size_t storageLevels = mTexStorage->getLevelCount();
+
+        // If the storage was from an EGL image, copy it back into local images to preserve it
+        // while orphaning
+        if (level != 0 && mEGLImageTarget)
+        {
+            // TODO(jmadill): Don't discard error.
+            mImageArray[0]->copyFromTexStorage(gl::ImageIndex::Make2D(0), mTexStorage);
+        }
+
+        if ((level >= storageLevels && storageLevels != 0) ||
+            size.width != storageWidth ||
+            size.height != storageHeight ||
+            internalformat != storageFormat)   // Discard mismatched storage
+        {
+            SafeDelete(mTexStorage);
+            markAllImagesDirty();
+        }
+    }
+
+    // Can't be an EGL image target after being redefined
+    mEGLImageTarget = false;
+}
+
+gl::ImageIndexIterator TextureD3D_2D::imageIterator() const
+{
+    return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
+}
+
+gl::ImageIndex TextureD3D_2D::getImageIndex(GLint mip, GLint /*layer*/) const
+{
+    // "layer" does not apply to 2D Textures.
+    return gl::ImageIndex::Make2D(mip);
+}
+
+bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const
+{
+    return (mTexStorage && index.type == GL_TEXTURE_2D &&
+            index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
+}
+
+void TextureD3D_2D::markAllImagesDirty()
+{
+    for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        mImageArray[i]->markDirty();
+    }
+    mDirtyImages = true;
+}
+
+gl::Error TextureD3D_2D::setStorageMultisample(ContextImpl *contextImpl,
+                                               GLenum target,
+                                               GLsizei samples,
+                                               GLint internalFormat,
+                                               const gl::Extents &size,
+                                               GLboolean fixedSampleLocations)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError() << "setStorageMultisample is unimplemented.";
+}
+
+TextureD3D_Cube::TextureD3D_Cube(const gl::TextureState &state, RendererD3D *renderer)
+    : TextureD3D(state, renderer)
+{
+    for (int i = 0; i < 6; i++)
+    {
+        for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
+        {
+            mImageArray[i][j] = renderer->createImage();
+        }
+    }
+}
+
+TextureD3D_Cube::~TextureD3D_Cube()
+{
+    // Delete the Images before the TextureStorage.
+    // Images might be relying on the TextureStorage for some of their data.
+    // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
+    for (int i = 0; i < 6; i++)
+    {
+        for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
+        {
+            SafeDelete(mImageArray[i][j]);
+        }
+    }
+
+    SafeDelete(mTexStorage);
+}
+
+ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const
+{
+    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(layer >= 0 && layer < 6);
+    return mImageArray[layer][level];
+}
+
+ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
+{
+    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(index.layerIndex >= 0 && index.layerIndex < 6);
+    return mImageArray[index.layerIndex][index.mipIndex];
+}
+
+GLsizei TextureD3D_Cube::getLayerCount(int level) const
+{
+    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    return 6;
+}
+
+GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const
+{
+    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[layer][level]->getInternalFormat();
+    else
+        return GL_NONE;
+}
+
+bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const
+{
+    return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
+}
+
+gl::Error TextureD3D_Cube::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_Cube::setImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    GLenum internalFormat,
+                                    const gl::Extents &size,
+                                    GLenum format,
+                                    GLenum type,
+                                    const gl::PixelUnpackState &unpack,
+                                    const uint8_t *pixels)
+{
+    ASSERT(size.depth == 1);
+
+    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+    gl::ImageIndex index       = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
+
+    redefineImage(index.layerIndex, static_cast<GLint>(level),
+                  internalFormatInfo.sizedInternalFormat, size);
+
+    return setImageImpl(index, type, unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_Cube::setSubImage(ContextImpl *contextImpl,
+                                       GLenum target,
+                                       size_t level,
+                                       const gl::Box &area,
+                                       GLenum format,
+                                       GLenum type,
+                                       const gl::PixelUnpackState &unpack,
+                                       const uint8_t *pixels)
+{
+    ASSERT(area.depth == 1 && area.z == 0);
+
+    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
+    return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_Cube::setCompressedImage(ContextImpl *contextImpl,
+                                              GLenum target,
+                                              size_t level,
+                                              GLenum internalFormat,
+                                              const gl::Extents &size,
+                                              const gl::PixelUnpackState &unpack,
+                                              size_t imageSize,
+                                              const uint8_t *pixels)
+{
+    ASSERT(size.depth == 1);
+
+    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+    size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target);
+
+    redefineImage(static_cast<int>(faceIndex), static_cast<GLint>(level), internalFormat, size);
+
+    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
+    return setCompressedImageImpl(index, unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_Cube::setCompressedSubImage(ContextImpl *contextImpl,
+                                                 GLenum target,
+                                                 size_t level,
+                                                 const gl::Box &area,
+                                                 GLenum format,
+                                                 const gl::PixelUnpackState &unpack,
+                                                 size_t imageSize,
+                                                 const uint8_t *pixels)
+{
+    ASSERT(area.depth == 1 && area.z == 0);
+
+    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
+
+    ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
+    return commitRegion(index, area);
+}
+
+gl::Error TextureD3D_Cube::copyImage(ContextImpl *contextImpl,
+                                     GLenum target,
+                                     size_t imageLevel,
+                                     const gl::Rectangle &sourceArea,
+                                     GLenum internalFormat,
+                                     const gl::Framebuffer *source)
+{
+    int faceIndex              = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));
+    const gl::InternalFormat &internalFormatInfo =
+        gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
+
+    GLint level = static_cast<GLint>(imageLevel);
+
+    gl::Extents size(sourceArea.width, sourceArea.height, 1);
+    redefineImage(static_cast<int>(faceIndex), level, internalFormatInfo.sizedInternalFormat, size);
+
+    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+    gl::Offset destOffset(0, 0, 0);
+
+    // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+    // so we should use the non-rendering copy path.
+    if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        ANGLE_TRY(
+            mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source));
+        mDirtyImages = true;
+    }
+    else
+    {
+        ANGLE_TRY(ensureRenderTarget());
+        mImageArray[faceIndex][level]->markClean();
+
+        ASSERT(size.width == size.height);
+
+        if (size.width > 0 && isValidFaceLevel(faceIndex, level))
+        {
+            ANGLE_TRY(mRenderer->copyImageCube(source, sourceArea, internalFormat, destOffset,
+                                               mTexStorage, target, level));
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_Cube::copySubImage(ContextImpl *contextImpl,
+                                        GLenum target,
+                                        size_t imageLevel,
+                                        const gl::Offset &destOffset,
+                                        const gl::Rectangle &sourceArea,
+                                        const gl::Framebuffer *source)
+{
+    int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));
+
+    GLint level          = static_cast<GLint>(imageLevel);
+    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+
+    // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+    // so we should use the non-rendering copy path.
+    if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        gl::Error error =
+            mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        mDirtyImages = true;
+    }
+    else
+    {
+        ANGLE_TRY(ensureRenderTarget());
+        if (isValidFaceLevel(faceIndex, level))
+        {
+            ANGLE_TRY(updateStorageFaceLevel(faceIndex, level));
+            ANGLE_TRY(mRenderer->copyImageCube(source, sourceArea,
+                                               gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
+                                               destOffset, mTexStorage, target, level));
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_Cube::setStorage(ContextImpl *contextImpl,
+                                      GLenum target,
+                                      size_t levels,
+                                      GLenum internalFormat,
+                                      const gl::Extents &size)
+{
+    ASSERT(size.width == size.height);
+    ASSERT(size.depth == 1);
+
+    for (size_t level = 0; level < levels; level++)
+    {
+        GLsizei mipSize = std::max(1, size.width >> level);
+        for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+        {
+            mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalFormat, gl::Extents(mipSize, mipSize, 1), true);
+        }
+    }
+
+    for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+        {
+            mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, GL_NONE, gl::Extents(0, 0, 0), true);
+        }
+    }
+
+    // TODO(geofflang): Verify storage creation had no errors
+    bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+
+    TextureStorage *storage = mRenderer->createTextureStorageCube(
+        internalFormat, renderTarget, size.width, static_cast<int>(levels), false);
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    ANGLE_TRY(updateStorage());
+
+    mImmutable = true;
+
+    return gl::NoError();
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureD3D_Cube::isCubeComplete() const
+{
+    int    baseWidth  = getBaseLevelWidth();
+    int    baseHeight = getBaseLevelHeight();
+    GLenum baseFormat = getBaseLevelInternalFormat();
+
+    if (baseWidth <= 0 || baseWidth != baseHeight)
+    {
+        return false;
+    }
+
+    for (int faceIndex = 1; faceIndex < 6; faceIndex++)
+    {
+        const ImageD3D &faceBaseImage = *mImageArray[faceIndex][getBaseLevel()];
+
+        if (faceBaseImage.getWidth()          != baseWidth  ||
+            faceBaseImage.getHeight()         != baseHeight ||
+            faceBaseImage.getInternalFormat() != baseFormat )
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void TextureD3D_Cube::bindTexImage(egl::Surface *surface)
+{
+    UNREACHABLE();
+}
+
+void TextureD3D_Cube::releaseTexImage()
+{
+    UNREACHABLE();
+}
+
+void TextureD3D_Cube::initMipmapImages()
+{
+    const GLuint baseLevel = mState.getEffectiveBaseLevel();
+    const GLuint maxLevel  = mState.getMipmapMaxLevel();
+    // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+    // levels.
+    for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+    {
+        for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
+        {
+            int faceLevelSize =
+                (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1));
+            redefineImage(faceIndex, level, mImageArray[faceIndex][baseLevel]->getInternalFormat(),
+                          gl::Extents(faceLevelSize, faceLevelSize, 1));
+        }
+    }
+}
+
+gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+    ASSERT(gl::IsCubeMapTextureTarget(index.type));
+
+    // ensure the underlying texture is created
+    ANGLE_TRY(ensureRenderTarget());
+    ANGLE_TRY(updateStorageFaceLevel(index.layerIndex, index.mipIndex));
+
+    return mTexStorage->getRenderTarget(index, outRT);
+}
+
+gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget)
+{
+    // Only initialize the first time this texture is used as a render target or shader resource
+    if (mTexStorage)
+    {
+        return gl::NoError();
+    }
+
+    // do not attempt to create storage for nonexistant data
+    if (!isFaceLevelComplete(0, getBaseLevel()))
+    {
+        return gl::NoError();
+    }
+
+    bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
+
+    TextureStorage *storage = nullptr;
+    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    ASSERT(mTexStorage);
+
+    // flush image data to the storage
+    ANGLE_TRY(updateStorage());
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
+{
+    GLsizei size = getLevelZeroWidth();
+
+    ASSERT(size > 0);
+
+    // use existing storage level count, when previously specified by TexStorage*D
+    GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1));
+
+    bool hintLevelZeroOnly = false;
+    if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        // If any of the CPU images (levels >= 1) are dirty, then the textureStorage should use the mipped texture to begin with.
+        // Otherwise, it should use the level-zero-only texture.
+        hintLevelZeroOnly = true;
+        for (int faceIndex = 0; faceIndex < 6 && hintLevelZeroOnly; faceIndex++)
+        {
+            for (int level = 1; level < levels && hintLevelZeroOnly; level++)
+            {
+                hintLevelZeroOnly = !(mImageArray[faceIndex][level]->isDirty() && isFaceLevelComplete(faceIndex, level));
+            }
+        }
+    }
+
+    // TODO (geofflang): detect if storage creation succeeded
+    *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly);
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+    if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
+    {
+        for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+        {
+            for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
+            {
+                ANGLE_TRY(mImageArray[faceIndex][level]->setManagedSurfaceCube(
+                    newCompleteTexStorage, faceIndex, level));
+            }
+        }
+    }
+
+    SafeDelete(mTexStorage);
+    mTexStorage = newCompleteTexStorage;
+
+    mDirtyImages = true;
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_Cube::updateStorage()
+{
+    ASSERT(mTexStorage != nullptr);
+    GLint storageLevels = mTexStorage->getLevelCount();
+    for (int face = 0; face < 6; face++)
+    {
+        for (int level = 0; level < storageLevels; level++)
+        {
+            if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level))
+            {
+                ANGLE_TRY(updateStorageFaceLevel(face, level));
+            }
+        }
+    }
+
+    return gl::NoError();
+}
+
+bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const
+{
+    return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
+}
+
+bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const
+{
+    if (getBaseLevel() >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+    {
+        return false;
+    }
+    ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) &&
+           mImageArray[faceIndex][level] != nullptr);
+
+    if (isImmutable())
+    {
+        return true;
+    }
+
+    int levelZeroSize = getLevelZeroWidth();
+
+    if (levelZeroSize <= 0)
+    {
+        return false;
+    }
+
+    // "isCubeComplete" checks for base level completeness and we must call that
+    // to determine if any face at level 0 is complete. We omit that check here
+    // to avoid re-checking cube-completeness for every face at level 0.
+    if (level == 0)
+    {
+        return true;
+    }
+
+    // Check that non-zero levels are consistent with the base level.
+    const ImageD3D *faceLevelImage = mImageArray[faceIndex][level];
+
+    if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
+    {
+        return false;
+    }
+
+    if (faceLevelImage->getWidth() != std::max(1, levelZeroSize >> level))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const
+{
+    return isFaceLevelComplete(index.layerIndex, index.mipIndex);
+}
+
+gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
+{
+    ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) &&
+           mImageArray[faceIndex][level] != nullptr);
+    ImageD3D *image = mImageArray[faceIndex][level];
+
+    if (image->isDirty())
+    {
+        GLenum faceTarget = gl::LayerIndexToCubeMapTextureTarget(faceIndex);
+        gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level);
+        gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
+        ANGLE_TRY(commitRegion(index, region));
+    }
+
+    return gl::NoError();
+}
+
+void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size)
+{
+    // If there currently is a corresponding storage texture image, it has these parameters
+    const int storageWidth     = std::max(1, getLevelZeroWidth() >> level);
+    const int storageHeight    = std::max(1, getLevelZeroHeight() >> level);
+    const GLenum storageFormat = getBaseLevelInternalFormat();
+
+    mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size, false);
+
+    if (mTexStorage)
+    {
+        const int storageLevels = mTexStorage->getLevelCount();
+
+        if ((level >= storageLevels && storageLevels != 0) ||
+            size.width != storageWidth ||
+            size.height != storageHeight ||
+            internalformat != storageFormat)   // Discard mismatched storage
+        {
+            markAllImagesDirty();
+            SafeDelete(mTexStorage);
+        }
+    }
+}
+
+gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const
+{
+    return gl::ImageIndexIterator::MakeCube(0, mTexStorage->getLevelCount());
+}
+
+gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const
+{
+    // The "layer" of the image index corresponds to the cube face
+    return gl::ImageIndex::MakeCube(gl::LayerIndexToCubeMapTextureTarget(layer), mip);
+}
+
+bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const
+{
+    return (mTexStorage && gl::IsCubeMapTextureTarget(index.type) &&
+            index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
+}
+
+void TextureD3D_Cube::markAllImagesDirty()
+{
+    for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
+    {
+        for (int dirtyFace = 0; dirtyFace < 6; dirtyFace++)
+        {
+            mImageArray[dirtyFace][dirtyLevel]->markDirty();
+        }
+    }
+    mDirtyImages = true;
+}
+
+TextureD3D_3D::TextureD3D_3D(const gl::TextureState &state, RendererD3D *renderer)
+    : TextureD3D(state, renderer)
+{
+    for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+    {
+        mImageArray[i] = renderer->createImage();
+    }
+}
+
+TextureD3D_3D::~TextureD3D_3D()
+{
+    // Delete the Images before the TextureStorage.
+    // Images might be relying on the TextureStorage for some of their data.
+    // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
+    for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+    {
+        delete mImageArray[i];
+    }
+
+    SafeDelete(mTexStorage);
+}
+
+ImageD3D *TextureD3D_3D::getImage(int level, int layer) const
+{
+    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(layer == 0);
+    return mImageArray[level];
+}
+
+ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
+{
+    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(!index.hasLayer());
+    ASSERT(index.type == GL_TEXTURE_3D);
+    return mImageArray[index.mipIndex];
+}
+
+GLsizei TextureD3D_3D::getLayerCount(int level) const
+{
+    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    return 1;
+}
+
+GLsizei TextureD3D_3D::getWidth(GLint level) const
+{
+    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level]->getWidth();
+    else
+        return 0;
+}
+
+GLsizei TextureD3D_3D::getHeight(GLint level) const
+{
+    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level]->getHeight();
+    else
+        return 0;
+}
+
+GLsizei TextureD3D_3D::getDepth(GLint level) const
+{
+    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level]->getDepth();
+    else
+        return 0;
+}
+
+GLenum TextureD3D_3D::getInternalFormat(GLint level) const
+{
+    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level]->getInternalFormat();
+    else
+        return GL_NONE;
+}
+
+bool TextureD3D_3D::isDepth(GLint level) const
+{
+    return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+gl::Error TextureD3D_3D::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_3D::setImage(ContextImpl *contextImpl,
+                                  GLenum target,
+                                  size_t imageLevel,
+                                  GLenum internalFormat,
+                                  const gl::Extents &size,
+                                  GLenum format,
+                                  GLenum type,
+                                  const gl::PixelUnpackState &unpack,
+                                  const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_3D);
+    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+
+    GLint level = static_cast<GLint>(imageLevel);
+    redefineImage(level, internalFormatInfo.sizedInternalFormat, size);
+
+    bool fastUnpacked = false;
+
+    gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+
+    // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
+    if (isFastUnpackable(unpack, internalFormatInfo.sizedInternalFormat) && !size.empty() &&
+        isLevelComplete(level))
+    {
+        // Will try to create RT storage if it does not exist
+        RenderTargetD3D *destRenderTarget = nullptr;
+        ANGLE_TRY(getRenderTarget(index, &destRenderTarget));
+
+        gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
+
+        ANGLE_TRY(fastUnpackPixels(unpack, pixels, destArea, internalFormatInfo.sizedInternalFormat,
+                                   type, destRenderTarget));
+
+        // Ensure we don't overwrite our newly initialized data
+        mImageArray[level]->markClean();
+
+        fastUnpacked = true;
+    }
+
+    if (!fastUnpacked)
+    {
+        ANGLE_TRY(setImageImpl(index, type, unpack, pixels, 0));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_3D::setSubImage(ContextImpl *contextImpl,
+                                     GLenum target,
+                                     size_t imageLevel,
+                                     const gl::Box &area,
+                                     GLenum format,
+                                     GLenum type,
+                                     const gl::PixelUnpackState &unpack,
+                                     const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_3D);
+
+    GLint level          = static_cast<GLint>(imageLevel);
+    gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+
+    // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
+    if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
+    {
+        RenderTargetD3D *destRenderTarget = nullptr;
+        ANGLE_TRY(getRenderTarget(index, &destRenderTarget));
+        ASSERT(!mImageArray[level]->isDirty());
+
+        return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget);
+    }
+    else
+    {
+        return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+    }
+}
+
+gl::Error TextureD3D_3D::setCompressedImage(ContextImpl *contextImpl,
+                                            GLenum target,
+                                            size_t imageLevel,
+                                            GLenum internalFormat,
+                                            const gl::Extents &size,
+                                            const gl::PixelUnpackState &unpack,
+                                            size_t imageSize,
+                                            const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_3D);
+
+    GLint level = static_cast<GLint>(imageLevel);
+    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+    redefineImage(level, internalFormat, size);
+
+    gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+    return setCompressedImageImpl(index, unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_3D::setCompressedSubImage(ContextImpl *contextImpl,
+                                               GLenum target,
+                                               size_t level,
+                                               const gl::Box &area,
+                                               GLenum format,
+                                               const gl::PixelUnpackState &unpack,
+                                               size_t imageSize,
+                                               const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_3D);
+
+    gl::ImageIndex index = gl::ImageIndex::Make3D(static_cast<GLint>(level));
+    ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
+    return commitRegion(index, area);
+}
+
+gl::Error TextureD3D_3D::copyImage(ContextImpl *contextImpl,
+                                   GLenum target,
+                                   size_t level,
+                                   const gl::Rectangle &sourceArea,
+                                   GLenum internalFormat,
+                                   const gl::Framebuffer *source)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented.");
+}
+
+gl::Error TextureD3D_3D::copySubImage(ContextImpl *contextImpl,
+                                      GLenum target,
+                                      size_t imageLevel,
+                                      const gl::Offset &destOffset,
+                                      const gl::Rectangle &sourceArea,
+                                      const gl::Framebuffer *source)
+{
+    ASSERT(target == GL_TEXTURE_3D);
+
+    GLint level          = static_cast<GLint>(imageLevel);
+
+    // Currently, 3D single-layer blits are broken because we don't know how to make an SRV
+    // for a single layer of a 3D texture.
+    // TODO(jmadill): Investigate 3D blits in D3D11.
+    // gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+
+    // if (!canCreateRenderTargetForImage(index))
+    {
+        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
+        mDirtyImages = true;
+    }
+    // else
+    //{
+    //    ANGLE_TRY(ensureRenderTarget());
+    //    if (isValidLevel(level))
+    //    {
+    //        ANGLE_TRY(updateStorageLevel(level));
+    //        ANGLE_TRY(mRenderer->copyImage3D(
+    //            source, sourceArea,
+    //            gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+    //            destOffset, mTexStorage, level));
+    //    }
+    //}
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_3D::setStorage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t levels,
+                                    GLenum internalFormat,
+                                    const gl::Extents &size)
+{
+    ASSERT(target == GL_TEXTURE_3D);
+
+    for (size_t level = 0; level < levels; level++)
+    {
+        gl::Extents levelSize(std::max(1, size.width >> level),
+                              std::max(1, size.height >> level),
+                              std::max(1, size.depth >> level));
+        mImageArray[level]->redefine(GL_TEXTURE_3D, internalFormat, levelSize, true);
+    }
+
+    for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        mImageArray[level]->redefine(GL_TEXTURE_3D, GL_NONE, gl::Extents(0, 0, 0), true);
+    }
+
+    // TODO(geofflang): Verify storage creation had no errors
+    bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+    TextureStorage *storage =
+        mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height,
+                                          size.depth, static_cast<int>(levels));
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    ANGLE_TRY(updateStorage());
+
+    mImmutable = true;
+
+    return gl::NoError();
+}
+
+void TextureD3D_3D::bindTexImage(egl::Surface *surface)
+{
+    UNREACHABLE();
+}
+
+void TextureD3D_3D::releaseTexImage()
+{
+    UNREACHABLE();
+}
+
+void TextureD3D_3D::initMipmapImages()
+{
+    const GLuint baseLevel = mState.getEffectiveBaseLevel();
+    const GLuint maxLevel  = mState.getMipmapMaxLevel();
+    // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+    // levels.
+    for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
+    {
+        gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
+                              std::max(getLevelZeroHeight() >> level, 1),
+                              std::max(getLevelZeroDepth() >> level, 1));
+        redefineImage(level, getBaseLevelInternalFormat(), levelSize);
+    }
+}
+
+gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+    // ensure the underlying texture is created
+    ANGLE_TRY(ensureRenderTarget());
+
+    if (index.hasLayer())
+    {
+        ANGLE_TRY(updateStorage());
+    }
+    else
+    {
+        ANGLE_TRY(updateStorageLevel(index.mipIndex));
+    }
+
+    return mTexStorage->getRenderTarget(index, outRT);
+}
+
+gl::Error TextureD3D_3D::initializeStorage(bool renderTarget)
+{
+    // Only initialize the first time this texture is used as a render target or shader resource
+    if (mTexStorage)
+    {
+        return gl::NoError();
+    }
+
+    // do not attempt to create storage for nonexistant data
+    if (!isLevelComplete(getBaseLevel()))
+    {
+        return gl::NoError();
+    }
+
+    bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
+
+    TextureStorage *storage = nullptr;
+    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    ASSERT(mTexStorage);
+
+    // flush image data to the storage
+    ANGLE_TRY(updateStorage());
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
+{
+    GLsizei width         = getLevelZeroWidth();
+    GLsizei height        = getLevelZeroHeight();
+    GLsizei depth         = getLevelZeroDepth();
+    GLenum internalFormat = getBaseLevelInternalFormat();
+
+    ASSERT(width > 0 && height > 0 && depth > 0);
+
+    // use existing storage level count, when previously specified by TexStorage*D
+    GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));
+
+    // TODO: Verify creation of the storage succeeded
+    *outStorage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels);
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+    SafeDelete(mTexStorage);
+    mTexStorage = newCompleteTexStorage;
+    mDirtyImages = true;
+
+    // We do not support managed 3D storage, as that is D3D9/ES2-only
+    ASSERT(!mTexStorage->isManaged());
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_3D::updateStorage()
+{
+    ASSERT(mTexStorage != nullptr);
+    GLint storageLevels = mTexStorage->getLevelCount();
+    for (int level = 0; level < storageLevels; level++)
+    {
+        if (mImageArray[level]->isDirty() && isLevelComplete(level))
+        {
+            ANGLE_TRY(updateStorageLevel(level));
+        }
+    }
+
+    return gl::NoError();
+}
+
+bool TextureD3D_3D::isValidLevel(int level) const
+{
+    return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
+}
+
+bool TextureD3D_3D::isLevelComplete(int level) const
+{
+    ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != nullptr);
+
+    if (isImmutable())
+    {
+        return true;
+    }
+
+    GLsizei width  = getLevelZeroWidth();
+    GLsizei height = getLevelZeroHeight();
+    GLsizei depth  = getLevelZeroDepth();
+
+    if (width <= 0 || height <= 0 || depth <= 0)
+    {
+        return false;
+    }
+
+    if (level == static_cast<int>(getBaseLevel()))
+    {
+        return true;
+    }
+
+    ImageD3D *levelImage = mImageArray[level];
+
+    if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
+    {
+        return false;
+    }
+
+    if (levelImage->getWidth() != std::max(1, width >> level))
+    {
+        return false;
+    }
+
+    if (levelImage->getHeight() != std::max(1, height >> level))
+    {
+        return false;
+    }
+
+    if (levelImage->getDepth() != std::max(1, depth >> level))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const
+{
+    return isLevelComplete(index.mipIndex);
+}
+
+gl::Error TextureD3D_3D::updateStorageLevel(int level)
+{
+    ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != nullptr);
+    ASSERT(isLevelComplete(level));
+
+    if (mImageArray[level]->isDirty())
+    {
+        gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+        gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
+        ANGLE_TRY(commitRegion(index, region));
+    }
+
+    return gl::NoError();
+}
+
+void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
+{
+    // If there currently is a corresponding storage texture image, it has these parameters
+    const int storageWidth  = std::max(1, getLevelZeroWidth() >> level);
+    const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
+    const int storageDepth  = std::max(1, getLevelZeroDepth() >> level);
+    const GLenum storageFormat = getBaseLevelInternalFormat();
+
+    mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, false);
+
+    if (mTexStorage)
+    {
+        const int storageLevels = mTexStorage->getLevelCount();
+
+        if ((level >= storageLevels && storageLevels != 0) ||
+            size.width != storageWidth ||
+            size.height != storageHeight ||
+            size.depth != storageDepth ||
+            internalformat != storageFormat)   // Discard mismatched storage
+        {
+            markAllImagesDirty();
+            SafeDelete(mTexStorage);
+        }
+    }
+}
+
+gl::ImageIndexIterator TextureD3D_3D::imageIterator() const
+{
+    return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(),
+                                          gl::ImageIndex::ENTIRE_LEVEL, gl::ImageIndex::ENTIRE_LEVEL);
+}
+
+gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const
+{
+    // The "layer" here does not apply to 3D images. We use one Image per mip.
+    return gl::ImageIndex::Make3D(mip);
+}
+
+bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const
+{
+    return (mTexStorage && index.type == GL_TEXTURE_3D &&
+            index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
+}
+
+void TextureD3D_3D::markAllImagesDirty()
+{
+    for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        mImageArray[i]->markDirty();
+    }
+    mDirtyImages = true;
+}
+
+GLint TextureD3D_3D::getLevelZeroDepth() const
+{
+    ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelDepth())) > getBaseLevel());
+    return getBaseLevelDepth() << getBaseLevel();
+}
+
+TextureD3D_2DArray::TextureD3D_2DArray(const gl::TextureState &state, RendererD3D *renderer)
+    : TextureD3D(state, renderer)
+{
+    for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
+    {
+        mLayerCounts[level] = 0;
+        mImageArray[level]  = nullptr;
+    }
+}
+
+TextureD3D_2DArray::~TextureD3D_2DArray()
+{
+    // Delete the Images before the TextureStorage.
+    // Images might be relying on the TextureStorage for some of their data.
+    // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
+    deleteImages();
+    SafeDelete(mTexStorage);
+}
+
+ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const
+{
+    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT((layer == 0 && mLayerCounts[level] == 0) ||
+           layer < mLayerCounts[level]);
+    return (mImageArray[level] ? mImageArray[level][layer] : nullptr);
+}
+
+ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
+{
+    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT((index.layerIndex == 0 && mLayerCounts[index.mipIndex] == 0) ||
+           index.layerIndex < mLayerCounts[index.mipIndex]);
+    ASSERT(index.type == GL_TEXTURE_2D_ARRAY);
+    return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : nullptr);
+}
+
+GLsizei TextureD3D_2DArray::getLayerCount(int level) const
+{
+    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    return mLayerCounts[level];
+}
+
+GLsizei TextureD3D_2DArray::getWidth(GLint level) const
+{
+    return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0;
+}
+
+GLsizei TextureD3D_2DArray::getHeight(GLint level) const
+{
+    return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0;
+}
+
+GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const
+{
+    return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE;
+}
+
+bool TextureD3D_2DArray::isDepth(GLint level) const
+{
+    return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+gl::Error TextureD3D_2DArray::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_2DArray::setImage(ContextImpl *contextImpl,
+                                       GLenum target,
+                                       size_t imageLevel,
+                                       GLenum internalFormat,
+                                       const gl::Extents &size,
+                                       GLenum format,
+                                       GLenum type,
+                                       const gl::PixelUnpackState &unpack,
+                                       const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+
+    GLint level = static_cast<GLint>(imageLevel);
+    redefineImage(level, formatInfo.sizedInternalFormat, size);
+
+    GLsizei inputDepthPitch              = 0;
+    ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment,
+                                                  unpack.rowLength, unpack.imageHeight),
+                     inputDepthPitch);
+
+    for (int i = 0; i < size.depth; i++)
+    {
+        const ptrdiff_t layerOffset = (inputDepthPitch * i);
+        gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
+        ANGLE_TRY(setImageImpl(index, type, unpack, pixels, layerOffset));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::setSubImage(ContextImpl *contextImpl,
+                                          GLenum target,
+                                          size_t imageLevel,
+                                          const gl::Box &area,
+                                          GLenum format,
+                                          GLenum type,
+                                          const gl::PixelUnpackState &unpack,
+                                          const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_2D_ARRAY);
+    GLint level                          = static_cast<GLint>(imageLevel);
+    const gl::InternalFormat &formatInfo =
+        gl::GetInternalFormatInfo(getInternalFormat(level), type);
+    GLsizei inputDepthPitch              = 0;
+    ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment,
+                                                  unpack.rowLength, unpack.imageHeight),
+                     inputDepthPitch);
+
+    for (int i = 0; i < area.depth; i++)
+    {
+        int layer = area.z + i;
+        const ptrdiff_t layerOffset = (inputDepthPitch * i);
+
+        gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
+
+        gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
+        ANGLE_TRY(
+            TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::setCompressedImage(ContextImpl *contextImpl,
+                                                 GLenum target,
+                                                 size_t imageLevel,
+                                                 GLenum internalFormat,
+                                                 const gl::Extents &size,
+                                                 const gl::PixelUnpackState &unpack,
+                                                 size_t imageSize,
+                                                 const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+    GLint level = static_cast<GLint>(imageLevel);
+    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+    redefineImage(level, internalFormat, size);
+
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+    GLsizei inputDepthPitch              = 0;
+    ANGLE_TRY_RESULT(
+        formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0),
+        inputDepthPitch);
+
+    for (int i = 0; i < size.depth; i++)
+    {
+        const ptrdiff_t layerOffset = (inputDepthPitch * i);
+
+        gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
+        ANGLE_TRY(setCompressedImageImpl(index, unpack, pixels, layerOffset));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::setCompressedSubImage(ContextImpl *contextImpl,
+                                                    GLenum target,
+                                                    size_t level,
+                                                    const gl::Box &area,
+                                                    GLenum format,
+                                                    const gl::PixelUnpackState &unpack,
+                                                    size_t imageSize,
+                                                    const uint8_t *pixels)
+{
+    ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
+    GLsizei inputDepthPitch              = 0;
+    ANGLE_TRY_RESULT(
+        formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0),
+        inputDepthPitch);
+
+    for (int i = 0; i < area.depth; i++)
+    {
+        int layer = area.z + i;
+        const ptrdiff_t layerOffset = (inputDepthPitch * i);
+
+        gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
+
+        gl::ImageIndex index = gl::ImageIndex::Make2DArray(static_cast<GLint>(level), layer);
+        ANGLE_TRY(
+            TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset));
+        ANGLE_TRY(commitRegion(index, layerArea));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::copyImage(ContextImpl *contextImpl,
+                                        GLenum target,
+                                        size_t level,
+                                        const gl::Rectangle &sourceArea,
+                                        GLenum internalFormat,
+                                        const gl::Framebuffer *source)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented.");
+}
+
+gl::Error TextureD3D_2DArray::copySubImage(ContextImpl *contextImpl,
+                                           GLenum target,
+                                           size_t imageLevel,
+                                           const gl::Offset &destOffset,
+                                           const gl::Rectangle &sourceArea,
+                                           const gl::Framebuffer *source)
+{
+    ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+    GLint level          = static_cast<GLint>(imageLevel);
+    gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
+
+    if (!canCreateRenderTargetForImage(index))
+    {
+        gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0);
+        ANGLE_TRY(mImageArray[level][destOffset.z]->copyFromFramebuffer(destLayerOffset, sourceArea,
+                                                                        source));
+        mDirtyImages = true;
+    }
+    else
+    {
+        ANGLE_TRY(ensureRenderTarget());
+
+        if (isValidLevel(level))
+        {
+            ANGLE_TRY(updateStorageLevel(level));
+            ANGLE_TRY(mRenderer->copyImage2DArray(
+                source, sourceArea, gl::GetUnsizedFormat(getInternalFormat(getBaseLevel())),
+                destOffset, mTexStorage, level));
+        }
+    }
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::setStorage(ContextImpl *contextImpl,
+                                         GLenum target,
+                                         size_t levels,
+                                         GLenum internalFormat,
+                                         const gl::Extents &size)
+{
+    ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+    deleteImages();
+
+    for (size_t level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        gl::Extents levelLayerSize(std::max(1, size.width >> level),
+                                   std::max(1, size.height >> level),
+                                   1);
+
+        mLayerCounts[level] = (level < levels ? size.depth : 0);
+
+        if (mLayerCounts[level] > 0)
+        {
+            // Create new images for this level
+            mImageArray[level] = new ImageD3D*[mLayerCounts[level]];
+
+            for (int layer = 0; layer < mLayerCounts[level]; layer++)
+            {
+                mImageArray[level][layer] = mRenderer->createImage();
+                mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalFormat, levelLayerSize, true);
+            }
+        }
+    }
+
+    // TODO(geofflang): Verify storage creation had no errors
+    bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+    TextureStorage *storage =
+        mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width,
+                                               size.height, size.depth, static_cast<int>(levels));
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    ANGLE_TRY(updateStorage());
+
+    mImmutable = true;
+
+    return gl::NoError();
+}
+
+void TextureD3D_2DArray::bindTexImage(egl::Surface *surface)
+{
+    UNREACHABLE();
+}
+
+void TextureD3D_2DArray::releaseTexImage()
+{
+    UNREACHABLE();
+}
+
+void TextureD3D_2DArray::initMipmapImages()
+{
+    const GLuint baseLevel = mState.getEffectiveBaseLevel();
+    const GLuint maxLevel  = mState.getMipmapMaxLevel();
+    int baseWidth     = getLevelZeroWidth();
+    int baseHeight    = getLevelZeroHeight();
+    int baseDepth     = getLayerCount(getBaseLevel());
+    GLenum baseFormat = getBaseLevelInternalFormat();
+
+    // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+    // levels.
+    for (GLuint level = baseLevel + 1u; level <= maxLevel; level++)
+    {
+        ASSERT((baseWidth >> level) > 0 || (baseHeight >> level) > 0);
+        gl::Extents levelLayerSize(std::max(baseWidth >> level, 1),
+                                   std::max(baseHeight >> level, 1),
+                                   baseDepth);
+        redefineImage(level, baseFormat, levelLayerSize);
+    }
+}
+
+gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+    // ensure the underlying texture is created
+    ANGLE_TRY(ensureRenderTarget());
+    ANGLE_TRY(updateStorageLevel(index.mipIndex));
+    return mTexStorage->getRenderTarget(index, outRT);
+}
+
+gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget)
+{
+    // Only initialize the first time this texture is used as a render target or shader resource
+    if (mTexStorage)
+    {
+        return gl::NoError();
+    }
+
+    // do not attempt to create storage for nonexistant data
+    if (!isLevelComplete(getBaseLevel()))
+    {
+        return gl::NoError();
+    }
+
+    bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
+
+    TextureStorage *storage = nullptr;
+    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    ASSERT(mTexStorage);
+
+    // flush image data to the storage
+    ANGLE_TRY(updateStorage());
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
+{
+    GLsizei width         = getLevelZeroWidth();
+    GLsizei height        = getLevelZeroHeight();
+    GLsizei depth         = getLayerCount(getBaseLevel());
+    GLenum internalFormat = getBaseLevelInternalFormat();
+
+    ASSERT(width > 0 && height > 0 && depth > 0);
+
+    // use existing storage level count, when previously specified by TexStorage*D
+    GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
+
+    // TODO(geofflang): Verify storage creation succeeds
+    *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels);
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+    SafeDelete(mTexStorage);
+    mTexStorage = newCompleteTexStorage;
+    mDirtyImages = true;
+
+    // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only
+    ASSERT(!mTexStorage->isManaged());
+
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::updateStorage()
+{
+    ASSERT(mTexStorage != nullptr);
+    GLint storageLevels = mTexStorage->getLevelCount();
+    for (int level = 0; level < storageLevels; level++)
+    {
+        if (isLevelComplete(level))
+        {
+            ANGLE_TRY(updateStorageLevel(level));
+        }
+    }
+
+    return gl::NoError();
+}
+
+bool TextureD3D_2DArray::isValidLevel(int level) const
+{
+    return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
+}
+
+bool TextureD3D_2DArray::isLevelComplete(int level) const
+{
+    ASSERT(level >= 0 && level < (int)ArraySize(mImageArray));
+
+    if (isImmutable())
+    {
+        return true;
+    }
+
+    GLsizei width  = getLevelZeroWidth();
+    GLsizei height = getLevelZeroHeight();
+
+    if (width <= 0 || height <= 0)
+    {
+        return false;
+    }
+
+    // Layers check needs to happen after the above checks, otherwise out-of-range base level may be
+    // queried.
+    GLsizei layers = getLayerCount(getBaseLevel());
+
+    if (layers <= 0)
+    {
+        return false;
+    }
+
+    if (level == static_cast<int>(getBaseLevel()))
+    {
+        return true;
+    }
+
+    if (getInternalFormat(level) != getInternalFormat(getBaseLevel()))
+    {
+        return false;
+    }
+
+    if (getWidth(level) != std::max(1, width >> level))
+    {
+        return false;
+    }
+
+    if (getHeight(level) != std::max(1, height >> level))
+    {
+        return false;
+    }
+
+    if (getLayerCount(level) != layers)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const
+{
+    return isLevelComplete(index.mipIndex);
+}
+
+gl::Error TextureD3D_2DArray::updateStorageLevel(int level)
+{
+    ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts));
+    ASSERT(isLevelComplete(level));
+
+    for (int layer = 0; layer < mLayerCounts[level]; layer++)
+    {
+        ASSERT(mImageArray[level] != nullptr && mImageArray[level][layer] != nullptr);
+        if (mImageArray[level][layer]->isDirty())
+        {
+            gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
+            gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
+            ANGLE_TRY(commitRegion(index, region));
+        }
+    }
+
+    return gl::NoError();
+}
+
+void TextureD3D_2DArray::deleteImages()
+{
+    for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
+    {
+        for (int layer = 0; layer < mLayerCounts[level]; ++layer)
+        {
+            delete mImageArray[level][layer];
+        }
+        delete[] mImageArray[level];
+        mImageArray[level]  = nullptr;
+        mLayerCounts[level] = 0;
+    }
+}
+
+void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
+{
+    // If there currently is a corresponding storage texture image, it has these parameters
+    const int storageWidth  = std::max(1, getLevelZeroWidth() >> level);
+    const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
+    const GLuint baseLevel  = getBaseLevel();
+    int storageDepth = 0;
+    if (baseLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+    {
+        storageDepth = getLayerCount(baseLevel);
+    }
+
+    // Only reallocate the layers if the size doesn't match
+    if (size.depth != mLayerCounts[level])
+    {
+        for (int layer = 0; layer < mLayerCounts[level]; layer++)
+        {
+            SafeDelete(mImageArray[level][layer]);
+        }
+        SafeDeleteArray(mImageArray[level]);
+        mLayerCounts[level] = size.depth;
+
+        if (size.depth > 0)
+        {
+            mImageArray[level] = new ImageD3D*[size.depth];
+            for (int layer = 0; layer < mLayerCounts[level]; layer++)
+            {
+                mImageArray[level][layer] = mRenderer->createImage();
+            }
+        }
+    }
+
+    if (size.depth > 0)
+    {
+        for (int layer = 0; layer < mLayerCounts[level]; layer++)
+        {
+            mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat,
+                                                gl::Extents(size.width, size.height, 1), false);
+        }
+    }
+
+    if (mTexStorage)
+    {
+        const GLenum storageFormat = getBaseLevelInternalFormat();
+        const int storageLevels = mTexStorage->getLevelCount();
+
+        if ((level >= storageLevels && storageLevels != 0) ||
+            size.width != storageWidth ||
+            size.height != storageHeight ||
+            size.depth != storageDepth ||
+            internalformat != storageFormat)   // Discard mismatched storage
+        {
+            markAllImagesDirty();
+            SafeDelete(mTexStorage);
+        }
+    }
+}
+
+gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const
+{
+    return gl::ImageIndexIterator::Make2DArray(0, mTexStorage->getLevelCount(), mLayerCounts);
+}
+
+gl::ImageIndex TextureD3D_2DArray::getImageIndex(GLint mip, GLint layer) const
+{
+    return gl::ImageIndex::Make2DArray(mip, layer);
+}
+
+bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const
+{
+    // Check for having a storage and the right type of index
+    if (!mTexStorage || index.type != GL_TEXTURE_2D_ARRAY)
+    {
+        return false;
+    }
+
+    // Check the mip index
+    if (index.mipIndex < 0 || index.mipIndex >= mTexStorage->getLevelCount())
+    {
+        return false;
+    }
+
+    // Check the layer index
+    return (!index.hasLayer() || (index.layerIndex >= 0 && index.layerIndex < mLayerCounts[index.mipIndex]));
+}
+
+void TextureD3D_2DArray::markAllImagesDirty()
+{
+    for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
+    {
+        for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++)
+        {
+            mImageArray[dirtyLevel][dirtyLayer]->markDirty();
+        }
+    }
+    mDirtyImages = true;
+}
+
+TextureD3D_External::TextureD3D_External(const gl::TextureState &state, RendererD3D *renderer)
+    : TextureD3D(state, renderer)
+{
+}
+
+TextureD3D_External::~TextureD3D_External()
+{
+    SafeDelete(mTexStorage);
+}
+
+ImageD3D *TextureD3D_External::getImage(const gl::ImageIndex &index) const
+{
+    UNREACHABLE();
+    return nullptr;
+}
+
+GLsizei TextureD3D_External::getLayerCount(int level) const
+{
+    return 1;
+}
+
+gl::Error TextureD3D_External::setImage(ContextImpl *contextImpl,
+                                        GLenum target,
+                                        size_t imageLevel,
+                                        GLenum internalFormat,
+                                        const gl::Extents &size,
+                                        GLenum format,
+                                        GLenum type,
+                                        const gl::PixelUnpackState &unpack,
+                                        const uint8_t *pixels)
+{
+    // Image setting is not supported for external images
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setSubImage(ContextImpl *contextImpl,
+                                           GLenum target,
+                                           size_t imageLevel,
+                                           const gl::Box &area,
+                                           GLenum format,
+                                           GLenum type,
+                                           const gl::PixelUnpackState &unpack,
+                                           const uint8_t *pixels)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setCompressedImage(ContextImpl *contextImpl,
+                                                  GLenum target,
+                                                  size_t imageLevel,
+                                                  GLenum internalFormat,
+                                                  const gl::Extents &size,
+                                                  const gl::PixelUnpackState &unpack,
+                                                  size_t imageSize,
+                                                  const uint8_t *pixels)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setCompressedSubImage(ContextImpl *contextImpl,
+                                                     GLenum target,
+                                                     size_t level,
+                                                     const gl::Box &area,
+                                                     GLenum format,
+                                                     const gl::PixelUnpackState &unpack,
+                                                     size_t imageSize,
+                                                     const uint8_t *pixels)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::copyImage(ContextImpl *contextImpl,
+                                         GLenum target,
+                                         size_t imageLevel,
+                                         const gl::Rectangle &sourceArea,
+                                         GLenum internalFormat,
+                                         const gl::Framebuffer *source)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::copySubImage(ContextImpl *contextImpl,
+                                            GLenum target,
+                                            size_t imageLevel,
+                                            const gl::Offset &destOffset,
+                                            const gl::Rectangle &sourceArea,
+                                            const gl::Framebuffer *source)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setStorage(ContextImpl *contextImpl,
+                                          GLenum target,
+                                          size_t levels,
+                                          GLenum internalFormat,
+                                          const gl::Extents &size)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setImageExternal(GLenum target,
+                                                egl::Stream *stream,
+                                                const egl::Stream::GLTextureDescription &desc)
+{
+    ASSERT(target == GL_TEXTURE_EXTERNAL_OES);
+
+    SafeDelete(mTexStorage);
+
+    // If the stream is null, the external image is unbound and we release the storage
+    if (stream != nullptr)
+    {
+        mTexStorage = mRenderer->createTextureStorageExternal(stream, desc);
+    }
+
+    return gl::NoError();
+}
+
+void TextureD3D_External::bindTexImage(egl::Surface *surface)
+{
+    UNREACHABLE();
+}
+
+void TextureD3D_External::releaseTexImage()
+{
+    UNREACHABLE();
+}
+
+gl::Error TextureD3D_External::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+    EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
+
+    // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
+    RenderTargetD3D *renderTargetD3D = nullptr;
+    ANGLE_TRY(eglImaged3d->getRenderTarget(&renderTargetD3D));
+
+    SafeDelete(mTexStorage);
+    mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);
+
+    return gl::NoError();
+}
+
+void TextureD3D_External::initMipmapImages()
+{
+    UNREACHABLE();
+}
+
+gl::Error TextureD3D_External::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+bool TextureD3D_External::isImageComplete(const gl::ImageIndex &index) const
+{
+    return (index.mipIndex == 0) ? (mTexStorage != nullptr) : false;
+}
+
+gl::Error TextureD3D_External::initializeStorage(bool renderTarget)
+{
+    // Texture storage is created when an external image is bound
+    ASSERT(mTexStorage);
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_External::createCompleteStorage(bool renderTarget,
+                                                     TextureStorage **outTexStorage) const
+{
+    UNREACHABLE();
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_External::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+    UNREACHABLE();
+    return gl::NoError();
+}
+
+gl::Error TextureD3D_External::updateStorage()
+{
+    // Texture storage does not need to be updated since it is already loaded with the latest
+    // external image
+    ASSERT(mTexStorage);
+    return gl::NoError();
+}
+
+gl::ImageIndexIterator TextureD3D_External::imageIterator() const
+{
+    return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
+}
+
+gl::ImageIndex TextureD3D_External::getImageIndex(GLint mip, GLint /*layer*/) const
+{
+    // "layer" does not apply to 2D Textures.
+    return gl::ImageIndex::Make2D(mip);
+}
+
+bool TextureD3D_External::isValidIndex(const gl::ImageIndex &index) const
+{
+    return (mTexStorage && index.type == GL_TEXTURE_EXTERNAL_OES && index.mipIndex == 0);
+}
+
+void TextureD3D_External::markAllImagesDirty()
+{
+    UNREACHABLE();
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.h
new file mode 100644
index 0000000..4a72fc7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.h
@@ -0,0 +1,776 @@
+//
+// 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.
+//
+
+// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends.
+
+#ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
+#define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
+
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Stream.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class EGLImageD3D;
+class ImageD3D;
+class RendererD3D;
+class RenderTargetD3D;
+class TextureStorage;
+
+class TextureD3D : public TextureImpl
+{
+  public:
+    TextureD3D(const gl::TextureState &data, RendererD3D *renderer);
+    virtual ~TextureD3D();
+
+    gl::Error getNativeTexture(TextureStorage **outStorage);
+
+    bool hasDirtyImages() const { return mDirtyImages; }
+    void resetDirty() { mDirtyImages = false; }
+
+    virtual ImageD3D *getImage(const gl::ImageIndex &index) const = 0;
+    virtual GLsizei getLayerCount(int level) const = 0;
+
+    GLint getBaseLevelWidth() const;
+    GLint getBaseLevelHeight() const;
+    GLenum getBaseLevelInternalFormat() const;
+
+    gl::Error setStorageMultisample(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    GLsizei samples,
+                                    GLint internalFormat,
+                                    const gl::Extents &size,
+                                    GLboolean fixedSampleLocations) override;
+
+    bool isImmutable() const { return mImmutable; }
+
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+
+    // Returns an iterator over all "Images" for this particular Texture.
+    virtual gl::ImageIndexIterator imageIterator() const = 0;
+
+    // Returns an ImageIndex for a particular "Image". 3D Textures do not have images for
+    // slices of their depth texures, so 3D textures ignore the layer parameter.
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const = 0;
+
+    virtual gl::Error setImageExternal(GLenum target,
+                                       egl::Stream *stream,
+                                       const egl::Stream::GLTextureDescription &desc) override;
+    gl::Error generateMipmap(ContextImpl *contextImpl) override;
+    TextureStorage *getStorage();
+    ImageD3D *getBaseLevelImage() const;
+
+    gl::Error getAttachmentRenderTarget(GLenum binding,
+                                        const gl::ImageIndex &imageIndex,
+                                        FramebufferAttachmentRenderTarget **rtOut) override;
+
+    void setBaseLevel(GLuint baseLevel) override;
+
+    void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+
+  protected:
+    gl::Error setImageImpl(const gl::ImageIndex &index,
+                           GLenum type,
+                           const gl::PixelUnpackState &unpack,
+                           const uint8_t *pixels,
+                           ptrdiff_t layerOffset);
+    gl::Error subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
+                       const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset);
+    gl::Error setCompressedImageImpl(const gl::ImageIndex &index,
+                                     const gl::PixelUnpackState &unpack,
+                                     const uint8_t *pixels,
+                                     ptrdiff_t layerOffset);
+    gl::Error subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format,
+                                 const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset);
+    bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat);
+    gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
+                               GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget);
+
+    GLint getLevelZeroWidth() const;
+    GLint getLevelZeroHeight() const;
+    virtual GLint getLevelZeroDepth() const;
+
+    GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
+    virtual void initMipmapImages() = 0;
+    bool isBaseImageZeroSize() const;
+    virtual bool isImageComplete(const gl::ImageIndex &index) const = 0;
+
+    bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const;
+    virtual gl::Error ensureRenderTarget();
+
+    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const = 0;
+    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) = 0;
+    gl::Error commitRegion(const gl::ImageIndex &index, const gl::Box &region);
+
+    GLuint getBaseLevel() const { return mBaseLevel; };
+
+    virtual void markAllImagesDirty() = 0;
+
+    GLint getBaseLevelDepth() const;
+
+    RendererD3D *mRenderer;
+
+    bool mDirtyImages;
+
+    bool mImmutable;
+    TextureStorage *mTexStorage;
+
+  private:
+    virtual gl::Error initializeStorage(bool renderTarget) = 0;
+
+    virtual gl::Error updateStorage() = 0;
+
+    bool shouldUseSetData(const ImageD3D *image) const;
+
+    gl::Error generateMipmapUsingImages(const GLuint maxLevel);
+
+    GLuint mBaseLevel;
+};
+
+class TextureD3D_2D : public TextureD3D
+{
+  public:
+    TextureD3D_2D(const gl::TextureState &data, RendererD3D *renderer);
+    virtual ~TextureD3D_2D();
+
+    virtual ImageD3D *getImage(int level, int layer) const;
+    virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
+    virtual GLsizei getLayerCount(int level) const;
+
+    GLsizei getWidth(GLint level) const;
+    GLsizei getHeight(GLint level) const;
+    GLenum getInternalFormat(GLint level) const;
+    bool isDepth(GLint level) const;
+
+    gl::Error setImage(ContextImpl *contextImpl,
+                       GLenum target,
+                       size_t level,
+                       GLenum internalFormat,
+                       const gl::Extents &size,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels) override;
+    gl::Error setSubImage(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          const gl::Box &area,
+                          GLenum format,
+                          GLenum type,
+                          const gl::PixelUnpackState &unpack,
+                          const uint8_t *pixels) override;
+
+    gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size,
+                                 const gl::PixelUnpackState &unpack,
+                                 size_t imageSize,
+                                 const uint8_t *pixels) override;
+    gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Box &area,
+                                    GLenum format,
+                                    const gl::PixelUnpackState &unpack,
+                                    size_t imageSize,
+                                    const uint8_t *pixels) override;
+
+    gl::Error copyImage(ContextImpl *contextImpl,
+                        GLenum target,
+                        size_t level,
+                        const gl::Rectangle &sourceArea,
+                        GLenum internalFormat,
+                        const gl::Framebuffer *source) override;
+    gl::Error copySubImage(ContextImpl *contextImpl,
+                           GLenum target,
+                           size_t level,
+                           const gl::Offset &destOffset,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Framebuffer *source) override;
+
+    gl::Error copyTexture(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          GLenum internalFormat,
+                          GLenum type,
+                          size_t sourceLevel,
+                          bool unpackFlipY,
+                          bool unpackPremultiplyAlpha,
+                          bool unpackUnmultiplyAlpha,
+                          const gl::Texture *source) override;
+    gl::Error copySubTexture(ContextImpl *contextImpl,
+                             GLenum target,
+                             size_t level,
+                             const gl::Offset &destOffset,
+                             size_t sourceLevel,
+                             const gl::Rectangle &sourceArea,
+                             bool unpackFlipY,
+                             bool unpackPremultiplyAlpha,
+                             bool unpackUnmultiplyAlpha,
+                             const gl::Texture *source) override;
+    gl::Error copyCompressedTexture(ContextImpl *contextImpl, const gl::Texture *source) override;
+
+    gl::Error setStorage(ContextImpl *contextImpl,
+                         GLenum target,
+                         size_t levels,
+                         GLenum internalFormat,
+                         const gl::Extents &size) override;
+
+    virtual void bindTexImage(egl::Surface *surface);
+    virtual void releaseTexImage();
+
+    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+    virtual gl::ImageIndexIterator imageIterator() const;
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
+    gl::Error setStorageMultisample(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    GLsizei samples,
+                                    GLint internalFormat,
+                                    const gl::Extents &size,
+                                    GLboolean fixedSampleLocations) override;
+
+  protected:
+    void markAllImagesDirty() override;
+
+  private:
+    virtual gl::Error initializeStorage(bool renderTarget);
+    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
+    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+    virtual gl::Error updateStorage();
+    virtual void initMipmapImages();
+
+    bool isValidLevel(int level) const;
+    bool isLevelComplete(int level) const;
+    virtual bool isImageComplete(const gl::ImageIndex &index) const;
+
+    gl::Error updateStorageLevel(int level);
+
+    void redefineImage(size_t level,
+                       GLenum internalformat,
+                       const gl::Extents &size,
+                       bool forceRelease);
+
+    bool mEGLImageTarget;
+    ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureD3D_Cube : public TextureD3D
+{
+  public:
+    TextureD3D_Cube(const gl::TextureState &data, RendererD3D *renderer);
+    virtual ~TextureD3D_Cube();
+
+    virtual ImageD3D *getImage(int level, int layer) const;
+    virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
+    virtual GLsizei getLayerCount(int level) const;
+
+    virtual bool hasDirtyImages() const { return mDirtyImages; }
+    virtual void resetDirty() { mDirtyImages = false; }
+
+    GLenum getInternalFormat(GLint level, GLint layer) const;
+    bool isDepth(GLint level, GLint layer) const;
+
+    gl::Error setImage(ContextImpl *contextImpl,
+                       GLenum target,
+                       size_t level,
+                       GLenum internalFormat,
+                       const gl::Extents &size,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels) override;
+    gl::Error setSubImage(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          const gl::Box &area,
+                          GLenum format,
+                          GLenum type,
+                          const gl::PixelUnpackState &unpack,
+                          const uint8_t *pixels) override;
+
+    gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size,
+                                 const gl::PixelUnpackState &unpack,
+                                 size_t imageSize,
+                                 const uint8_t *pixels) override;
+    gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Box &area,
+                                    GLenum format,
+                                    const gl::PixelUnpackState &unpack,
+                                    size_t imageSize,
+                                    const uint8_t *pixels) override;
+
+    gl::Error copyImage(ContextImpl *contextImpl,
+                        GLenum target,
+                        size_t level,
+                        const gl::Rectangle &sourceArea,
+                        GLenum internalFormat,
+                        const gl::Framebuffer *source) override;
+    gl::Error copySubImage(ContextImpl *contextImpl,
+                           GLenum target,
+                           size_t level,
+                           const gl::Offset &destOffset,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Framebuffer *source) override;
+
+    gl::Error setStorage(ContextImpl *contextImpl,
+                         GLenum target,
+                         size_t levels,
+                         GLenum internalFormat,
+                         const gl::Extents &size) override;
+
+    virtual void bindTexImage(egl::Surface *surface);
+    virtual void releaseTexImage();
+
+    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+    virtual gl::ImageIndexIterator imageIterator() const;
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
+  protected:
+    void markAllImagesDirty() override;
+
+  private:
+    virtual gl::Error initializeStorage(bool renderTarget);
+    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
+    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+    virtual gl::Error updateStorage();
+    void initMipmapImages() override;
+
+    bool isValidFaceLevel(int faceIndex, int level) const;
+    bool isFaceLevelComplete(int faceIndex, int level) const;
+    bool isCubeComplete() const;
+    virtual bool isImageComplete(const gl::ImageIndex &index) const;
+    gl::Error updateStorageFaceLevel(int faceIndex, int level);
+
+    void redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size);
+
+    ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureD3D_3D : public TextureD3D
+{
+  public:
+    TextureD3D_3D(const gl::TextureState &data, RendererD3D *renderer);
+    virtual ~TextureD3D_3D();
+
+    virtual ImageD3D *getImage(int level, int layer) const;
+    virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
+    virtual GLsizei getLayerCount(int level) const;
+
+    GLsizei getWidth(GLint level) const;
+    GLsizei getHeight(GLint level) const;
+    GLsizei getDepth(GLint level) const;
+    GLenum getInternalFormat(GLint level) const;
+    bool isDepth(GLint level) const;
+
+    gl::Error setImage(ContextImpl *contextImpl,
+                       GLenum target,
+                       size_t level,
+                       GLenum internalFormat,
+                       const gl::Extents &size,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels) override;
+    gl::Error setSubImage(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          const gl::Box &area,
+                          GLenum format,
+                          GLenum type,
+                          const gl::PixelUnpackState &unpack,
+                          const uint8_t *pixels) override;
+
+    gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size,
+                                 const gl::PixelUnpackState &unpack,
+                                 size_t imageSize,
+                                 const uint8_t *pixels) override;
+    gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Box &area,
+                                    GLenum format,
+                                    const gl::PixelUnpackState &unpack,
+                                    size_t imageSize,
+                                    const uint8_t *pixels) override;
+
+    gl::Error copyImage(ContextImpl *contextImpl,
+                        GLenum target,
+                        size_t level,
+                        const gl::Rectangle &sourceArea,
+                        GLenum internalFormat,
+                        const gl::Framebuffer *source) override;
+    gl::Error copySubImage(ContextImpl *contextImpl,
+                           GLenum target,
+                           size_t level,
+                           const gl::Offset &destOffset,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Framebuffer *source) override;
+
+    gl::Error setStorage(ContextImpl *contextImpl,
+                         GLenum target,
+                         size_t levels,
+                         GLenum internalFormat,
+                         const gl::Extents &size) override;
+
+    virtual void bindTexImage(egl::Surface *surface);
+    virtual void releaseTexImage();
+
+    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+    virtual gl::ImageIndexIterator imageIterator() const;
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
+  protected:
+    void markAllImagesDirty() override;
+    GLint getLevelZeroDepth() const override;
+
+  private:
+    virtual gl::Error initializeStorage(bool renderTarget);
+    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
+    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+    virtual gl::Error updateStorage();
+    void initMipmapImages() override;
+
+    bool isValidLevel(int level) const;
+    bool isLevelComplete(int level) const;
+    virtual bool isImageComplete(const gl::ImageIndex &index) const;
+    gl::Error updateStorageLevel(int level);
+
+    void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size);
+
+    ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureD3D_2DArray : public TextureD3D
+{
+  public:
+    TextureD3D_2DArray(const gl::TextureState &data, RendererD3D *renderer);
+    virtual ~TextureD3D_2DArray();
+
+    virtual ImageD3D *getImage(int level, int layer) const;
+    virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
+    virtual GLsizei getLayerCount(int level) const;
+
+    GLsizei getWidth(GLint level) const;
+    GLsizei getHeight(GLint level) const;
+    GLenum getInternalFormat(GLint level) const;
+    bool isDepth(GLint level) const;
+
+    gl::Error setImage(ContextImpl *contextImpl,
+                       GLenum target,
+                       size_t level,
+                       GLenum internalFormat,
+                       const gl::Extents &size,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels) override;
+    gl::Error setSubImage(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          const gl::Box &area,
+                          GLenum format,
+                          GLenum type,
+                          const gl::PixelUnpackState &unpack,
+                          const uint8_t *pixels) override;
+
+    gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size,
+                                 const gl::PixelUnpackState &unpack,
+                                 size_t imageSize,
+                                 const uint8_t *pixels) override;
+    gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Box &area,
+                                    GLenum format,
+                                    const gl::PixelUnpackState &unpack,
+                                    size_t imageSize,
+                                    const uint8_t *pixels) override;
+
+    gl::Error copyImage(ContextImpl *contextImpl,
+                        GLenum target,
+                        size_t level,
+                        const gl::Rectangle &sourceArea,
+                        GLenum internalFormat,
+                        const gl::Framebuffer *source) override;
+    gl::Error copySubImage(ContextImpl *contextImpl,
+                           GLenum target,
+                           size_t level,
+                           const gl::Offset &destOffset,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Framebuffer *source) override;
+
+    gl::Error setStorage(ContextImpl *contextImpl,
+                         GLenum target,
+                         size_t levels,
+                         GLenum internalFormat,
+                         const gl::Extents &size) override;
+
+    virtual void bindTexImage(egl::Surface *surface);
+    virtual void releaseTexImage();
+
+    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+    virtual gl::ImageIndexIterator imageIterator() const;
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
+  protected:
+    void markAllImagesDirty() override;
+
+  private:
+    virtual gl::Error initializeStorage(bool renderTarget);
+    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
+    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+    virtual gl::Error updateStorage();
+    void initMipmapImages() override;
+
+    bool isValidLevel(int level) const;
+    bool isLevelComplete(int level) const;
+    virtual bool isImageComplete(const gl::ImageIndex &index) const;
+    gl::Error updateStorageLevel(int level);
+
+    void deleteImages();
+    void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size);
+
+    // Storing images as an array of single depth textures since D3D11 treats each array level of a
+    // Texture2D object as a separate subresource.  Each layer would have to be looped over
+    // to update all the texture layers since they cannot all be updated at once and it makes the most
+    // sense for the Image class to not have to worry about layer subresource as well as mip subresources.
+    GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+    ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureD3D_External : public TextureD3D
+{
+  public:
+    TextureD3D_External(const gl::TextureState &data, RendererD3D *renderer);
+    ~TextureD3D_External() override;
+
+    ImageD3D *getImage(const gl::ImageIndex &index) const override;
+    GLsizei getLayerCount(int level) const override;
+
+    gl::Error setImage(ContextImpl *contextImpl,
+                       GLenum target,
+                       size_t level,
+                       GLenum internalFormat,
+                       const gl::Extents &size,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels) override;
+    gl::Error setSubImage(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          const gl::Box &area,
+                          GLenum format,
+                          GLenum type,
+                          const gl::PixelUnpackState &unpack,
+                          const uint8_t *pixels) override;
+
+    gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size,
+                                 const gl::PixelUnpackState &unpack,
+                                 size_t imageSize,
+                                 const uint8_t *pixels) override;
+    gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Box &area,
+                                    GLenum format,
+                                    const gl::PixelUnpackState &unpack,
+                                    size_t imageSize,
+                                    const uint8_t *pixels) override;
+
+    gl::Error copyImage(ContextImpl *contextImpl,
+                        GLenum target,
+                        size_t level,
+                        const gl::Rectangle &sourceArea,
+                        GLenum internalFormat,
+                        const gl::Framebuffer *source) override;
+    gl::Error copySubImage(ContextImpl *contextImpl,
+                           GLenum target,
+                           size_t level,
+                           const gl::Offset &destOffset,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Framebuffer *source) override;
+
+    gl::Error setStorage(ContextImpl *contextImpl,
+                         GLenum target,
+                         size_t levels,
+                         GLenum internalFormat,
+                         const gl::Extents &size) override;
+
+    gl::Error setImageExternal(GLenum target,
+                               egl::Stream *stream,
+                               const egl::Stream::GLTextureDescription &desc) override;
+
+    void bindTexImage(egl::Surface *surface) override;
+    void releaseTexImage() override;
+
+    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+    gl::ImageIndexIterator imageIterator() const override;
+    gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+    bool isValidIndex(const gl::ImageIndex &index) const override;
+
+  protected:
+    void markAllImagesDirty() override;
+
+  private:
+    gl::Error initializeStorage(bool renderTarget) override;
+    gl::Error createCompleteStorage(bool renderTarget,
+                                    TextureStorage **outTexStorage) const override;
+    gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) override;
+
+    gl::Error updateStorage() override;
+    void initMipmapImages() override;
+
+    bool isImageComplete(const gl::ImageIndex &index) const override;
+};
+
+class TextureD3D_2DMultisample : public TextureD3D
+{
+  public:
+    TextureD3D_2DMultisample(const gl::TextureState &data, RendererD3D *renderer);
+    ~TextureD3D_2DMultisample() override;
+
+    ImageD3D *getImage(const gl::ImageIndex &index) const override;
+    gl::Error setImage(ContextImpl *contextImpl,
+                       GLenum target,
+                       size_t level,
+                       GLenum internalFormat,
+                       const gl::Extents &size,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels) override;
+    gl::Error setSubImage(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          const gl::Box &area,
+                          GLenum format,
+                          GLenum type,
+                          const gl::PixelUnpackState &unpack,
+                          const uint8_t *pixels) override;
+
+    gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size,
+                                 const gl::PixelUnpackState &unpack,
+                                 size_t imageSize,
+                                 const uint8_t *pixels) override;
+    gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Box &area,
+                                    GLenum format,
+                                    const gl::PixelUnpackState &unpack,
+                                    size_t imageSize,
+                                    const uint8_t *pixels) override;
+
+    gl::Error copyImage(ContextImpl *contextImpl,
+                        GLenum target,
+                        size_t level,
+                        const gl::Rectangle &sourceArea,
+                        GLenum internalFormat,
+                        const gl::Framebuffer *source) override;
+    gl::Error copySubImage(ContextImpl *contextImpl,
+                           GLenum target,
+                           size_t level,
+                           const gl::Offset &destOffset,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Framebuffer *source) override;
+
+    gl::Error setStorage(ContextImpl *contextImpl,
+                         GLenum target,
+                         size_t levels,
+                         GLenum internalFormat,
+                         const gl::Extents &size) override;
+
+    gl::Error setImageExternal(GLenum target,
+                               egl::Stream *stream,
+                               const egl::Stream::GLTextureDescription &desc) override;
+
+    void bindTexImage(egl::Surface *surface) override;
+    void releaseTexImage() override;
+
+    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+    gl::ImageIndexIterator imageIterator() const override;
+    gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+    bool isValidIndex(const gl::ImageIndex &index) const override;
+
+    virtual GLsizei getLayerCount(int level) const;
+
+  protected:
+    void markAllImagesDirty() override;
+
+  private:
+    gl::Error initializeStorage(bool renderTarget) override;
+    gl::Error createCompleteStorage(bool renderTarget,
+                                    TextureStorage **outTexStorage) const override;
+    gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) override;
+
+    gl::Error updateStorage() override;
+    void initMipmapImages() override;
+
+    bool isImageComplete(const gl::ImageIndex &index) const override;
+};
+}
+
+#endif // LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/TextureStorage.h b/src/third_party/angle/src/libANGLE/renderer/d3d/TextureStorage.h
new file mode 100644
index 0000000..c29e20f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/TextureStorage.h
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage.h: Defines the abstract rx::TextureStorage class.
+
+#ifndef LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
+#define LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/debug.h"
+#include "libANGLE/Error.h"
+
+#include <GLES2/gl2.h>
+#include <stdint.h>
+
+namespace gl
+{
+struct ImageIndex;
+struct Box;
+struct PixelUnpackState;
+}
+
+namespace rx
+{
+class SwapChainD3D;
+class RenderTargetD3D;
+class ImageD3D;
+
+class TextureStorage : angle::NonCopyable
+{
+  public:
+    TextureStorage() {}
+    virtual ~TextureStorage() {}
+
+    virtual int getTopLevel() const = 0;
+    virtual bool isRenderTarget() const = 0;
+    virtual bool isManaged() const = 0;
+    virtual bool supportsNativeMipmapFunction() const = 0;
+    virtual int getLevelCount() const = 0;
+
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+    virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0;
+
+    virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0;
+    virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
+                              const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0;
+
+    // This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D) might override it.
+    virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
+    {
+        return gl::NoError();
+    }
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
new file mode 100644
index 0000000..30d65be
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
@@ -0,0 +1,292 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface
+// class with derivations, classes that perform graphics API agnostic vertex buffer operations.
+
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+#include "common/mathutil.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/VertexAttribute.h"
+
+namespace rx
+{
+
+// VertexBuffer Implementation
+unsigned int VertexBuffer::mNextSerial = 1;
+
+VertexBuffer::VertexBuffer() : mRefCount(1)
+{
+    updateSerial();
+}
+
+VertexBuffer::~VertexBuffer()
+{
+}
+
+void VertexBuffer::updateSerial()
+{
+    mSerial = mNextSerial++;
+}
+
+unsigned int VertexBuffer::getSerial() const
+{
+    return mSerial;
+}
+
+void VertexBuffer::addRef()
+{
+    mRefCount++;
+}
+
+void VertexBuffer::release()
+{
+    ASSERT(mRefCount > 0);
+    mRefCount--;
+
+    if (mRefCount == 0)
+    {
+        delete this;
+    }
+}
+
+// VertexBufferInterface Implementation
+VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
+    : mFactory(factory), mVertexBuffer(factory->createVertexBuffer()), mDynamic(dynamic)
+{
+}
+
+VertexBufferInterface::~VertexBufferInterface()
+{
+    if (mVertexBuffer)
+    {
+        mVertexBuffer->release();
+    }
+}
+
+unsigned int VertexBufferInterface::getSerial() const
+{
+    return mVertexBuffer->getSerial();
+}
+
+unsigned int VertexBufferInterface::getBufferSize() const
+{
+    return mVertexBuffer->getBufferSize();
+}
+
+gl::Error VertexBufferInterface::setBufferSize(unsigned int size)
+{
+    if (mVertexBuffer->getBufferSize() == 0)
+    {
+        return mVertexBuffer->initialize(size, mDynamic);
+    }
+
+    return mVertexBuffer->setBufferSize(size);
+}
+
+gl::ErrorOrResult<unsigned int> VertexBufferInterface::getSpaceRequired(
+    const gl::VertexAttribute &attrib,
+    const gl::VertexBinding &binding,
+    GLsizei count,
+    GLsizei instances) const
+{
+    unsigned int spaceRequired = 0;
+    ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, count, instances),
+                     spaceRequired);
+
+    // Align to 16-byte boundary
+    unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u);
+
+    if (alignedSpaceRequired < spaceRequired)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Vertex buffer overflow in VertexBufferInterface::getSpaceRequired.");
+    }
+
+    return alignedSpaceRequired;
+}
+
+gl::Error VertexBufferInterface::discard()
+{
+    return mVertexBuffer->discard();
+}
+
+VertexBuffer *VertexBufferInterface::getVertexBuffer() const
+{
+    return mVertexBuffer;
+}
+
+// StreamingVertexBufferInterface Implementation
+StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory,
+                                                               std::size_t initialSize)
+    : VertexBufferInterface(factory, true), mWritePosition(0), mReservedSpace(0)
+{
+    setBufferSize(static_cast<unsigned int>(initialSize));
+}
+
+StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
+{
+}
+
+gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
+{
+    unsigned int curBufferSize = getBufferSize();
+    if (size > curBufferSize)
+    {
+        ANGLE_TRY(setBufferSize(std::max(size, 3 * curBufferSize / 2)));
+        mWritePosition = 0;
+    }
+    else if (mWritePosition + size > curBufferSize)
+    {
+        ANGLE_TRY(discard());
+        mWritePosition = 0;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error StreamingVertexBufferInterface::storeDynamicAttribute(const gl::VertexAttribute &attrib,
+                                                                const gl::VertexBinding &binding,
+                                                                GLenum currentValueType,
+                                                                GLint start,
+                                                                GLsizei count,
+                                                                GLsizei instances,
+                                                                unsigned int *outStreamOffset,
+                                                                const uint8_t *sourceData)
+{
+    unsigned int spaceRequired = 0;
+    ANGLE_TRY_RESULT(getSpaceRequired(attrib, binding, count, instances), spaceRequired);
+
+    // Protect against integer overflow
+    angle::CheckedNumeric<unsigned int> checkedPosition(mWritePosition);
+    checkedPosition += spaceRequired;
+    if (!checkedPosition.IsValid())
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow.");
+    }
+
+    ANGLE_TRY(reserveSpace(mReservedSpace));
+    mReservedSpace = 0;
+
+    ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, binding, currentValueType, start, count,
+                                                   instances, mWritePosition, sourceData));
+
+    if (outStreamOffset)
+    {
+        *outStreamOffset = mWritePosition;
+    }
+
+    mWritePosition += spaceRequired;
+
+    return gl::NoError();
+}
+
+gl::Error StreamingVertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib,
+                                                             const gl::VertexBinding &binding,
+                                                             GLsizei count,
+                                                             GLsizei instances)
+{
+    unsigned int requiredSpace = 0;
+    ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, count, instances),
+                     requiredSpace);
+
+    // Align to 16-byte boundary
+    auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u);
+    alignedRequiredSpace += mReservedSpace;
+
+    // Protect against integer overflow
+    if (!alignedRequiredSpace.IsValid())
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Unable to reserve %u extra bytes in internal vertex buffer, "
+                         "it would result in an overflow.",
+                         requiredSpace);
+    }
+
+    mReservedSpace = alignedRequiredSpace.ValueOrDie();
+
+    return gl::NoError();
+}
+
+// StaticVertexBufferInterface Implementation
+StaticVertexBufferInterface::AttributeSignature::AttributeSignature()
+    : type(GL_NONE), size(0), stride(0), normalized(false), pureInteger(false), offset(0)
+{
+}
+
+bool StaticVertexBufferInterface::AttributeSignature::matchesAttribute(
+    const gl::VertexAttribute &attrib,
+    const gl::VertexBinding &binding) const
+{
+    size_t attribStride = ComputeVertexAttributeStride(attrib, binding);
+
+    if (type != attrib.type || size != attrib.size || static_cast<GLuint>(stride) != attribStride ||
+        normalized != attrib.normalized || pureInteger != attrib.pureInteger)
+    {
+        return false;
+    }
+
+    size_t attribOffset =
+        (static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) % attribStride);
+    return (offset == attribOffset);
+}
+
+void StaticVertexBufferInterface::AttributeSignature::set(const gl::VertexAttribute &attrib,
+                                                          const gl::VertexBinding &binding)
+{
+    type        = attrib.type;
+    size        = attrib.size;
+    normalized  = attrib.normalized;
+    pureInteger = attrib.pureInteger;
+    offset = stride = static_cast<GLuint>(ComputeVertexAttributeStride(attrib, binding));
+    offset          = static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) %
+             ComputeVertexAttributeStride(attrib, binding);
+}
+
+StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory)
+    : VertexBufferInterface(factory, false)
+{
+}
+
+StaticVertexBufferInterface::~StaticVertexBufferInterface()
+{
+}
+
+bool StaticVertexBufferInterface::matchesAttribute(const gl::VertexAttribute &attrib,
+                                                   const gl::VertexBinding &binding) const
+{
+    return mSignature.matchesAttribute(attrib, binding);
+}
+
+void StaticVertexBufferInterface::setAttribute(const gl::VertexAttribute &attrib,
+                                               const gl::VertexBinding &binding)
+{
+    return mSignature.set(attrib, binding);
+}
+
+gl::Error StaticVertexBufferInterface::storeStaticAttribute(const gl::VertexAttribute &attrib,
+                                                            const gl::VertexBinding &binding,
+                                                            GLint start,
+                                                            GLsizei count,
+                                                            GLsizei instances,
+                                                            const uint8_t *sourceData)
+{
+    unsigned int spaceRequired = 0;
+    ANGLE_TRY_RESULT(getSpaceRequired(attrib, binding, count, instances), spaceRequired);
+    setBufferSize(spaceRequired);
+
+    ASSERT(attrib.enabled);
+    ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, binding, GL_NONE, start, count,
+                                                   instances, 0, sourceData));
+
+    mSignature.set(attrib, binding);
+    mVertexBuffer->hintUnmapResource();
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/src/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
new file mode 100644
index 0000000..bb749c1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
@@ -0,0 +1,175 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer.h: Defines the abstract VertexBuffer class and VertexBufferInterface
+// class with derivations, classes that perform graphics API agnostic vertex buffer operations.
+
+#ifndef LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
+#define LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+#include <GLES2/gl2.h>
+
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+namespace gl
+{
+struct VertexAttribute;
+struct VertexBinding;
+struct VertexAttribCurrentValueData;
+}
+
+namespace rx
+{
+class BufferFactoryD3D;
+
+// Use a ref-counting scheme with self-deletion on release. We do this so that we can more
+// easily manage the static buffer cache, without deleting currently bound buffers.
+class VertexBuffer : angle::NonCopyable
+{
+  public:
+    VertexBuffer();
+
+    virtual gl::Error initialize(unsigned int size, bool dynamicUsage) = 0;
+
+    // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+    // function.
+    virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
+                                            const gl::VertexBinding &binding,
+                                            GLenum currentValueType,
+                                            GLint start,
+                                            GLsizei count,
+                                            GLsizei instances,
+                                            unsigned int offset,
+                                            const uint8_t *sourceData) = 0;
+
+    virtual unsigned int getBufferSize() const = 0;
+    virtual gl::Error setBufferSize(unsigned int size) = 0;
+    virtual gl::Error discard() = 0;
+
+    unsigned int getSerial() const;
+
+    // This may be overridden (e.g. by VertexBuffer11) if necessary.
+    virtual void hintUnmapResource() { };
+
+    // Reference counting.
+    void addRef();
+    void release();
+
+  protected:
+    void updateSerial();
+    virtual ~VertexBuffer();
+
+  private:
+    unsigned int mSerial;
+    static unsigned int mNextSerial;
+    unsigned int mRefCount;
+};
+
+class VertexBufferInterface : angle::NonCopyable
+{
+  public:
+    VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic);
+    virtual ~VertexBufferInterface();
+
+    unsigned int getBufferSize() const;
+    bool empty() const { return getBufferSize() == 0; }
+
+    unsigned int getSerial() const;
+
+    VertexBuffer *getVertexBuffer() const;
+
+  protected:
+    gl::Error discard();
+
+    gl::Error setBufferSize(unsigned int size);
+
+    gl::ErrorOrResult<unsigned int> getSpaceRequired(const gl::VertexAttribute &attrib,
+                                                     const gl::VertexBinding &binding,
+                                                     GLsizei count,
+                                                     GLsizei instances) const;
+    BufferFactoryD3D *const mFactory;
+    VertexBuffer *mVertexBuffer;
+    bool mDynamic;
+};
+
+class StreamingVertexBufferInterface : public VertexBufferInterface
+{
+  public:
+    StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize);
+    ~StreamingVertexBufferInterface();
+
+    gl::Error storeDynamicAttribute(const gl::VertexAttribute &attrib,
+                                    const gl::VertexBinding &binding,
+                                    GLenum currentValueType,
+                                    GLint start,
+                                    GLsizei count,
+                                    GLsizei instances,
+                                    unsigned int *outStreamOffset,
+                                    const uint8_t *sourceData);
+
+    gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute,
+                                 const gl::VertexBinding &binding,
+                                 GLsizei count,
+                                 GLsizei instances);
+
+  private:
+    gl::Error reserveSpace(unsigned int size);
+
+    unsigned int mWritePosition;
+    unsigned int mReservedSpace;
+};
+
+class StaticVertexBufferInterface : public VertexBufferInterface
+{
+  public:
+    explicit StaticVertexBufferInterface(BufferFactoryD3D *factory);
+    ~StaticVertexBufferInterface();
+
+    // Warning: you should ensure binding really matches attrib.bindingIndex before using these
+    // functions.
+    gl::Error storeStaticAttribute(const gl::VertexAttribute &attrib,
+                                   const gl::VertexBinding &binding,
+                                   GLint start,
+                                   GLsizei count,
+                                   GLsizei instances,
+                                   const uint8_t *sourceData);
+
+    bool matchesAttribute(const gl::VertexAttribute &attribute,
+                          const gl::VertexBinding &binding) const;
+
+    void setAttribute(const gl::VertexAttribute &attribute, const gl::VertexBinding &binding);
+
+  private:
+    class AttributeSignature final : angle::NonCopyable
+    {
+      public:
+        AttributeSignature();
+
+        bool matchesAttribute(const gl::VertexAttribute &attrib,
+                              const gl::VertexBinding &binding) const;
+
+        void set(const gl::VertexAttribute &attrib, const gl::VertexBinding &binding);
+
+      private:
+        GLenum type;
+        GLuint size;
+        GLuint stride;
+        bool normalized;
+        bool pureInteger;
+        size_t offset;
+    };
+
+    AttributeSignature mSignature;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
new file mode 100644
index 0000000..ed59c0e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -0,0 +1,616 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+
+#include "common/bitset_utils.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+using namespace angle;
+
+namespace rx
+{
+namespace
+{
+enum
+{
+    INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024
+};
+// This has to be at least 4k or else it fails on ATI cards.
+enum
+{
+    CONSTANT_VERTEX_BUFFER_SIZE = 4096
+};
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+int ElementsInBuffer(const gl::VertexAttribute &attrib,
+                     const gl::VertexBinding &binding,
+                     unsigned int size)
+{
+    // Size cannot be larger than a GLsizei
+    if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
+    {
+        size = static_cast<unsigned int>(std::numeric_limits<int>::max());
+    }
+
+    GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib, binding));
+    GLsizei offset = static_cast<GLsizei>(ComputeVertexAttributeOffset(attrib, binding));
+    return (size - offset % stride +
+            (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) /
+           stride;
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+bool DirectStoragePossible(const gl::VertexAttribute &attrib, const gl::VertexBinding &binding)
+{
+    // Current value attribs may not use direct storage.
+    if (!attrib.enabled)
+    {
+        return false;
+    }
+
+    gl::Buffer *buffer = binding.buffer.get();
+    if (!buffer)
+    {
+        return false;
+    }
+
+    BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+    ASSERT(bufferD3D);
+    if (!bufferD3D->supportsDirectBinding())
+    {
+        return false;
+    }
+
+    // Alignment restrictions: In D3D, vertex data must be aligned to the format stride, or to a
+    // 4-byte boundary, whichever is smaller. (Undocumented, and experimentally confirmed)
+    size_t alignment = 4;
+
+    // TODO(jmadill): add VertexFormatCaps
+    BufferFactoryD3D *factory = bufferD3D->getFactory();
+
+    gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
+
+    // CPU-converted vertex data must be converted (naturally).
+    if ((factory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0)
+    {
+        return false;
+    }
+
+    if (attrib.type != GL_FLOAT)
+    {
+        auto errorOrElementSize = factory->getVertexSpaceRequired(attrib, binding, 1, 0);
+        if (errorOrElementSize.isError())
+        {
+            ERR() << "Unlogged error in DirectStoragePossible.";
+            return false;
+        }
+
+        alignment = std::min<size_t>(errorOrElementSize.getResult(), 4);
+    }
+
+    GLintptr offset = ComputeVertexAttributeOffset(attrib, binding);
+    // Final alignment check - unaligned data must be converted.
+    return (static_cast<size_t>(ComputeVertexAttributeStride(attrib, binding)) % alignment == 0) &&
+           (static_cast<size_t>(offset) % alignment == 0);
+}
+}  // anonymous namespace
+
+TranslatedAttribute::TranslatedAttribute()
+    : active(false),
+      attribute(nullptr),
+      currentValueType(GL_NONE),
+      baseOffset(0),
+      usesFirstVertexOffset(false),
+      stride(0),
+      vertexBuffer(),
+      storage(nullptr),
+      serial(0),
+      divisor(0)
+{
+}
+
+gl::ErrorOrResult<unsigned int> TranslatedAttribute::computeOffset(GLint startVertex) const
+{
+    if (!usesFirstVertexOffset)
+    {
+        return baseOffset;
+    }
+
+    CheckedNumeric<unsigned int> offset;
+
+    offset = baseOffset + stride * static_cast<unsigned int>(startVertex);
+    ANGLE_TRY_CHECKED_MATH(offset);
+    return offset.ValueOrDie();
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib,
+                                           const gl::VertexBinding &binding)
+{
+    // If attribute is disabled, we use the current value.
+    if (!attrib.enabled)
+    {
+        return VertexStorageType::CURRENT_VALUE;
+    }
+
+    // If specified with immediate data, we must use dynamic storage.
+    auto *buffer = binding.buffer.get();
+    if (!buffer)
+    {
+        return VertexStorageType::DYNAMIC;
+    }
+
+    // Check if the buffer supports direct storage.
+    if (DirectStoragePossible(attrib, binding))
+    {
+        return VertexStorageType::DIRECT;
+    }
+
+    // Otherwise the storage is static or dynamic.
+    BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+    ASSERT(bufferD3D);
+    switch (bufferD3D->getUsage())
+    {
+        case D3DBufferUsage::DYNAMIC:
+            return VertexStorageType::DYNAMIC;
+        case D3DBufferUsage::STATIC:
+            return VertexStorageType::STATIC;
+        default:
+            UNREACHABLE();
+            return VertexStorageType::UNKNOWN;
+    }
+}
+
+VertexDataManager::CurrentValueState::CurrentValueState()
+    : buffer(nullptr),
+      offset(0)
+{
+    data.FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
+    data.FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
+    data.FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
+    data.FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
+    data.Type = GL_FLOAT;
+}
+
+VertexDataManager::CurrentValueState::~CurrentValueState()
+{
+    SafeDelete(buffer);
+}
+
+VertexDataManager::VertexDataManager(BufferFactoryD3D *factory)
+    : mFactory(factory),
+      mStreamingBuffer(nullptr),
+      // TODO(jmadill): use context caps
+      mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS)
+{
+    mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE);
+
+    if (!mStreamingBuffer)
+    {
+        ERR() << "Failed to allocate the streaming vertex buffer.";
+    }
+}
+
+VertexDataManager::~VertexDataManager()
+{
+    SafeDelete(mStreamingBuffer);
+}
+
+gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
+                                               GLint start,
+                                               GLsizei count,
+                                               std::vector<TranslatedAttribute> *translatedAttribs,
+                                               GLsizei instances)
+{
+    ASSERT(mStreamingBuffer);
+
+    const gl::VertexArray *vertexArray = state.getVertexArray();
+    const auto &vertexAttributes       = vertexArray->getVertexAttributes();
+    const auto &vertexBindings         = vertexArray->getVertexBindings();
+
+    mDynamicAttribsMaskCache.reset();
+    const gl::Program *program = state.getProgram();
+
+    translatedAttribs->clear();
+
+    for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
+    {
+        // Skip attrib locations the program doesn't use.
+        if (!program->isAttribLocationActive(attribIndex))
+            continue;
+
+        const auto &attrib = vertexAttributes[attribIndex];
+        const auto &binding = vertexBindings[attrib.bindingIndex];
+
+        // Resize automatically puts in empty attribs
+        translatedAttribs->resize(attribIndex + 1);
+
+        TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
+        auto currentValueData           = state.getVertexAttribCurrentValue(attribIndex);
+
+        // Record the attribute now
+        translated->active           = true;
+        translated->attribute        = &attrib;
+        translated->binding          = &binding;
+        translated->currentValueType = currentValueData.Type;
+        translated->divisor          = binding.divisor;
+
+        switch (ClassifyAttributeStorage(attrib, binding))
+        {
+            case VertexStorageType::STATIC:
+            {
+                // Store static attribute.
+                ANGLE_TRY(StoreStaticAttrib(translated));
+                break;
+            }
+            case VertexStorageType::DYNAMIC:
+                // Dynamic attributes must be handled together.
+                mDynamicAttribsMaskCache.set(attribIndex);
+                break;
+            case VertexStorageType::DIRECT:
+                // Update translated data for direct attributes.
+                StoreDirectAttrib(translated);
+                break;
+            case VertexStorageType::CURRENT_VALUE:
+            {
+                ANGLE_TRY(storeCurrentValue(currentValueData, translated, attribIndex));
+                break;
+            }
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+
+    if (mDynamicAttribsMaskCache.none())
+    {
+        return gl::NoError();
+    }
+
+    ANGLE_TRY(
+        storeDynamicAttribs(translatedAttribs, mDynamicAttribsMaskCache, start, count, instances));
+
+    PromoteDynamicAttribs(*translatedAttribs, mDynamicAttribsMaskCache, count);
+
+    return gl::NoError();
+}
+
+// static
+void VertexDataManager::StoreDirectAttrib(TranslatedAttribute *directAttrib)
+{
+    ASSERT(directAttrib->attribute && directAttrib->binding);
+    const auto &attrib  = *directAttrib->attribute;
+    const auto &binding = *directAttrib->binding;
+
+    gl::Buffer *buffer   = binding.buffer.get();
+    BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
+
+    ASSERT(DirectStoragePossible(attrib, binding));
+    directAttrib->vertexBuffer.set(nullptr);
+    directAttrib->storage = bufferD3D;
+    directAttrib->serial  = bufferD3D->getSerial();
+    directAttrib->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding));
+    directAttrib->baseOffset =
+        static_cast<unsigned int>(ComputeVertexAttributeOffset(attrib, binding));
+
+    // Instanced vertices do not apply the 'start' offset
+    directAttrib->usesFirstVertexOffset = (binding.divisor == 0);
+}
+
+// static
+gl::Error VertexDataManager::StoreStaticAttrib(TranslatedAttribute *translated)
+{
+    ASSERT(translated->attribute && translated->binding);
+    const auto &attrib  = *translated->attribute;
+    const auto &binding = *translated->binding;
+
+    gl::Buffer *buffer = binding.buffer.get();
+    ASSERT(buffer && attrib.enabled && !DirectStoragePossible(attrib, binding));
+    BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+
+    // Compute source data pointer
+    const uint8_t *sourceData = nullptr;
+    const int offset          = static_cast<int>(ComputeVertexAttributeOffset(attrib, binding));
+
+    ANGLE_TRY(bufferD3D->getData(&sourceData));
+    sourceData += offset;
+
+    unsigned int streamOffset = 0;
+
+    translated->storage = nullptr;
+    ANGLE_TRY_RESULT(bufferD3D->getFactory()->getVertexSpaceRequired(attrib, binding, 1, 0),
+                     translated->stride);
+
+    auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib, binding);
+    ASSERT(staticBuffer);
+
+    if (staticBuffer->empty())
+    {
+        // Convert the entire buffer
+        int totalCount =
+            ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize()));
+        int startIndex = offset / static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
+
+        ANGLE_TRY(staticBuffer->storeStaticAttribute(attrib, binding, -startIndex, totalCount, 0,
+                                                     sourceData));
+    }
+
+    unsigned int firstElementOffset =
+        (static_cast<unsigned int>(offset) /
+         static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding))) *
+        translated->stride;
+
+    VertexBuffer *vertexBuffer = staticBuffer->getVertexBuffer();
+
+    CheckedNumeric<unsigned int> checkedOffset(streamOffset);
+    checkedOffset += firstElementOffset;
+
+    if (!checkedOffset.IsValid())
+    {
+        return gl::Error(GL_INVALID_OPERATION,
+                         "Integer overflow in VertexDataManager::StoreStaticAttrib");
+    }
+
+    translated->vertexBuffer.set(vertexBuffer);
+    translated->serial = vertexBuffer->getSerial();
+    translated->baseOffset = streamOffset + firstElementOffset;
+
+    // Instanced vertices do not apply the 'start' offset
+    translated->usesFirstVertexOffset = (binding.divisor == 0);
+
+    return gl::NoError();
+}
+
+gl::Error VertexDataManager::storeDynamicAttribs(
+    std::vector<TranslatedAttribute> *translatedAttribs,
+    const gl::AttributesMask &dynamicAttribsMask,
+    GLint start,
+    GLsizei count,
+    GLsizei instances)
+{
+    // Instantiating this class will ensure the streaming buffer is never left mapped.
+    class StreamingBufferUnmapper final : NonCopyable
+    {
+      public:
+        StreamingBufferUnmapper(StreamingVertexBufferInterface *streamingBuffer)
+            : mStreamingBuffer(streamingBuffer)
+        {
+            ASSERT(mStreamingBuffer);
+        }
+        ~StreamingBufferUnmapper() { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); }
+
+      private:
+        StreamingVertexBufferInterface *mStreamingBuffer;
+    };
+
+    // Will trigger unmapping on return.
+    StreamingBufferUnmapper localUnmapper(mStreamingBuffer);
+
+    // Reserve the required space for the dynamic buffers.
+    for (auto attribIndex : dynamicAttribsMask)
+    {
+        const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
+        ANGLE_TRY(reserveSpaceForAttrib(dynamicAttrib, count, instances));
+    }
+
+    // Store dynamic attributes
+    for (auto attribIndex : dynamicAttribsMask)
+    {
+        auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
+        ANGLE_TRY(storeDynamicAttrib(dynamicAttrib, start, count, instances));
+    }
+
+    return gl::NoError();
+}
+
+void VertexDataManager::PromoteDynamicAttribs(
+    const std::vector<TranslatedAttribute> &translatedAttribs,
+    const gl::AttributesMask &dynamicAttribsMask,
+    GLsizei count)
+{
+    for (auto attribIndex : dynamicAttribsMask)
+    {
+        const auto &dynamicAttrib = translatedAttribs[attribIndex];
+        ASSERT(dynamicAttrib.attribute && dynamicAttrib.binding);
+        const auto &binding       = *dynamicAttrib.binding;
+
+        gl::Buffer *buffer        = binding.buffer.get();
+        if (buffer)
+        {
+            BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+            size_t typeSize      = ComputeVertexAttributeTypeSize(*dynamicAttrib.attribute);
+            bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize));
+        }
+    }
+}
+
+gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
+                                                   GLsizei count,
+                                                   GLsizei instances) const
+{
+    ASSERT(translatedAttrib.attribute && translatedAttrib.binding);
+    const auto &attrib  = *translatedAttrib.attribute;
+    const auto &binding = *translatedAttrib.binding;
+
+    ASSERT(!DirectStoragePossible(attrib, binding));
+
+    gl::Buffer *buffer   = binding.buffer.get();
+    BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
+    ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib, binding) == nullptr);
+
+    size_t totalCount = ComputeVertexBindingElementCount(binding, count, instances);
+    ASSERT(!bufferD3D ||
+           ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize())) >=
+               static_cast<int>(totalCount));
+
+    return mStreamingBuffer->reserveVertexSpace(attrib, binding, static_cast<GLsizei>(totalCount),
+                                                instances);
+}
+
+gl::Error VertexDataManager::storeDynamicAttrib(TranslatedAttribute *translated,
+                                                GLint start,
+                                                GLsizei count,
+                                                GLsizei instances)
+{
+    ASSERT(translated->attribute && translated->binding);
+    const auto &attrib  = *translated->attribute;
+    const auto &binding = *translated->binding;
+
+    gl::Buffer *buffer = binding.buffer.get();
+    ASSERT(buffer || attrib.pointer);
+    ASSERT(attrib.enabled);
+
+    BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
+
+    // Instanced vertices do not apply the 'start' offset
+    GLint firstVertexIndex = (binding.divisor > 0 ? 0 : start);
+
+    // Compute source data pointer
+    const uint8_t *sourceData = nullptr;
+
+    if (buffer)
+    {
+        ANGLE_TRY(storage->getData(&sourceData));
+        sourceData += static_cast<int>(ComputeVertexAttributeOffset(attrib, binding));
+    }
+    else
+    {
+        // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state.
+        // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt
+        sourceData = static_cast<const uint8_t*>(attrib.pointer);
+    }
+
+    unsigned int streamOffset = 0;
+
+    translated->storage = nullptr;
+    ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, 1, 0), translated->stride);
+
+    size_t totalCount = ComputeVertexBindingElementCount(binding, count, instances);
+
+    ANGLE_TRY(mStreamingBuffer->storeDynamicAttribute(
+        attrib, binding, translated->currentValueType, firstVertexIndex,
+        static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData));
+
+    VertexBuffer *vertexBuffer = mStreamingBuffer->getVertexBuffer();
+
+    translated->vertexBuffer.set(vertexBuffer);
+    translated->serial = vertexBuffer->getSerial();
+    translated->baseOffset            = streamOffset;
+    translated->usesFirstVertexOffset = false;
+
+    return gl::NoError();
+}
+
+gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
+                                               TranslatedAttribute *translated,
+                                               size_t attribIndex)
+{
+    CurrentValueState *cachedState = &mCurrentValueCache[attribIndex];
+    auto *&buffer                  = cachedState->buffer;
+
+    if (!buffer)
+    {
+        buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE);
+    }
+
+    if (cachedState->data != currentValue)
+    {
+        ASSERT(translated->attribute && translated->binding);
+        const auto &attrib  = *translated->attribute;
+        const auto &binding = *translated->binding;
+
+        ANGLE_TRY(buffer->reserveVertexSpace(attrib, binding, 1, 0));
+
+        const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
+        unsigned int streamOffset;
+        ANGLE_TRY(buffer->storeDynamicAttribute(attrib, binding, currentValue.Type, 0, 1, 0,
+                                                &streamOffset, sourceData));
+
+        buffer->getVertexBuffer()->hintUnmapResource();
+
+        cachedState->data = currentValue;
+        cachedState->offset = streamOffset;
+    }
+
+    translated->vertexBuffer.set(buffer->getVertexBuffer());
+
+    translated->storage = nullptr;
+    translated->serial  = buffer->getSerial();
+    translated->divisor = 0;
+    translated->stride  = 0;
+    translated->baseOffset            = static_cast<unsigned int>(cachedState->offset);
+    translated->usesFirstVertexOffset = false;
+
+    return gl::NoError();
+}
+
+// VertexBufferBinding implementation
+VertexBufferBinding::VertexBufferBinding() : mBoundVertexBuffer(nullptr)
+{
+}
+
+VertexBufferBinding::VertexBufferBinding(const VertexBufferBinding &other)
+    : mBoundVertexBuffer(other.mBoundVertexBuffer)
+{
+    if (mBoundVertexBuffer)
+    {
+        mBoundVertexBuffer->addRef();
+    }
+}
+
+VertexBufferBinding::~VertexBufferBinding()
+{
+    if (mBoundVertexBuffer)
+    {
+        mBoundVertexBuffer->release();
+    }
+}
+
+VertexBufferBinding &VertexBufferBinding::operator=(const VertexBufferBinding &other)
+{
+    mBoundVertexBuffer = other.mBoundVertexBuffer;
+    if (mBoundVertexBuffer)
+    {
+        mBoundVertexBuffer->addRef();
+    }
+    return *this;
+}
+
+void VertexBufferBinding::set(VertexBuffer *vertexBuffer)
+{
+    if (mBoundVertexBuffer == vertexBuffer)
+        return;
+
+    if (mBoundVertexBuffer)
+    {
+        mBoundVertexBuffer->release();
+    }
+    if (vertexBuffer)
+    {
+        vertexBuffer->addRef();
+    }
+
+    mBoundVertexBuffer = vertexBuffer;
+}
+
+VertexBuffer *VertexBufferBinding::get() const
+{
+    return mBoundVertexBuffer;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h b/src/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
new file mode 100644
index 0000000..c9cb5df
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
@@ -0,0 +1,144 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#ifndef LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
+#define LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/VertexAttribute.h"
+
+namespace gl
+{
+class State;
+struct VertexAttribute;
+struct VertexBinding;
+struct VertexAttribCurrentValueData;
+}
+
+namespace rx
+{
+class BufferD3D;
+class BufferFactoryD3D;
+class StreamingVertexBufferInterface;
+class VertexBuffer;
+
+class VertexBufferBinding final
+{
+  public:
+    VertexBufferBinding();
+    VertexBufferBinding(const VertexBufferBinding &other);
+    ~VertexBufferBinding();
+
+    void set(VertexBuffer *vertexBuffer);
+    VertexBuffer *get() const;
+    VertexBufferBinding &operator=(const VertexBufferBinding &other);
+
+  private:
+    VertexBuffer *mBoundVertexBuffer;
+};
+
+struct TranslatedAttribute
+{
+    TranslatedAttribute();
+
+    // Computes the correct offset from baseOffset, usesFirstVertexOffset, stride and startVertex.
+    // Can throw an error on integer overflow.
+    gl::ErrorOrResult<unsigned int> computeOffset(GLint startVertex) const;
+
+    bool active;
+
+    const gl::VertexAttribute *attribute;
+    const gl::VertexBinding *binding;
+    GLenum currentValueType;
+    unsigned int baseOffset;
+    bool usesFirstVertexOffset;
+    unsigned int stride;   // 0 means not to advance the read pointer at all
+
+    VertexBufferBinding vertexBuffer;
+    BufferD3D *storage;
+    unsigned int serial;
+    unsigned int divisor;
+};
+
+enum class VertexStorageType
+{
+    UNKNOWN,
+    STATIC,         // Translate the vertex data once and re-use it.
+    DYNAMIC,        // Translate the data every frame into a ring buffer.
+    DIRECT,         // Bind a D3D buffer directly without any translation.
+    CURRENT_VALUE,  // Use a single value for the attribute.
+};
+
+// Given a vertex attribute, return the type of storage it will use.
+VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib,
+                                           const gl::VertexBinding &binding);
+
+class VertexDataManager : angle::NonCopyable
+{
+  public:
+    VertexDataManager(BufferFactoryD3D *factory);
+    virtual ~VertexDataManager();
+
+    gl::Error prepareVertexData(const gl::State &state,
+                                GLint start,
+                                GLsizei count,
+                                std::vector<TranslatedAttribute> *translatedAttribs,
+                                GLsizei instances);
+
+    static void StoreDirectAttrib(TranslatedAttribute *directAttrib);
+
+    static gl::Error StoreStaticAttrib(TranslatedAttribute *translated);
+
+    gl::Error storeDynamicAttribs(std::vector<TranslatedAttribute> *translatedAttribs,
+                                  const gl::AttributesMask &dynamicAttribsMask,
+                                  GLint start,
+                                  GLsizei count,
+                                  GLsizei instances);
+
+    // Promote static usage of dynamic buffers.
+    static void PromoteDynamicAttribs(const std::vector<TranslatedAttribute> &translatedAttribs,
+                                      const gl::AttributesMask &dynamicAttribsMask,
+                                      GLsizei count);
+
+    gl::Error storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
+                                TranslatedAttribute *translated,
+                                size_t attribIndex);
+
+  private:
+    struct CurrentValueState
+    {
+        CurrentValueState();
+        ~CurrentValueState();
+
+        StreamingVertexBufferInterface *buffer;
+        gl::VertexAttribCurrentValueData data;
+        size_t offset;
+    };
+
+    gl::Error reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
+                                    GLsizei count,
+                                    GLsizei instances) const;
+
+    gl::Error storeDynamicAttrib(TranslatedAttribute *translated,
+                                 GLint start,
+                                 GLsizei count,
+                                 GLsizei instances);
+
+    BufferFactoryD3D *const mFactory;
+
+    StreamingVertexBufferInterface *mStreamingBuffer;
+    std::vector<CurrentValueState> mCurrentValueCache;
+    gl::AttributesMask mDynamicAttribsMaskCache;
+};
+
+}  // namespace rx
+
+#endif   // LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
new file mode 100644
index 0000000..2e9395c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
@@ -0,0 +1,2233 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit11.cpp: Texture copy utility class.
+
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+
+#include <float.h>
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "third_party/trace_event/trace_event.h"
+
+namespace rx
+{
+
+namespace
+{
+
+// Include inline shaders in the anonymous namespace to make sure no symbols are exported
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
+
+void StretchedBlitNearest_RowByRow(const gl::Box &sourceArea,
+                                   const gl::Box &destArea,
+                                   const gl::Rectangle &clippedDestArea,
+                                   const gl::Extents &sourceSize,
+                                   unsigned int sourceRowPitch,
+                                   unsigned int destRowPitch,
+                                   size_t pixelSize,
+                                   const uint8_t *sourceData,
+                                   uint8_t *destData)
+{
+    int srcHeightSubOne = (sourceArea.height - 1);
+    size_t copySize     = pixelSize * destArea.width;
+    size_t srcOffset    = sourceArea.x * pixelSize;
+    size_t destOffset   = destArea.x * pixelSize;
+
+    for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
+    {
+        float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
+
+        // Interpolate using the original source rectangle to determine which row to sample from
+        // while clamping to the edges
+        unsigned int readRow = static_cast<unsigned int>(
+            gl::clamp(sourceArea.y + floor(yPerc * srcHeightSubOne + 0.5f), 0, srcHeightSubOne));
+        unsigned int writeRow = y;
+
+        const uint8_t *sourceRow = sourceData + readRow * sourceRowPitch + srcOffset;
+        uint8_t *destRow         = destData + writeRow * destRowPitch + destOffset;
+        memcpy(destRow, sourceRow, copySize);
+    }
+}
+
+void StretchedBlitNearest_PixelByPixel(const gl::Box &sourceArea,
+                                       const gl::Box &destArea,
+                                       const gl::Rectangle &clippedDestArea,
+                                       const gl::Extents &sourceSize,
+                                       unsigned int sourceRowPitch,
+                                       unsigned int destRowPitch,
+                                       ptrdiff_t readOffset,
+                                       ptrdiff_t writeOffset,
+                                       size_t copySize,
+                                       size_t srcPixelStride,
+                                       size_t destPixelStride,
+                                       const uint8_t *sourceData,
+                                       uint8_t *destData)
+{
+    auto xMax = clippedDestArea.x + clippedDestArea.width;
+    auto yMax = clippedDestArea.y + clippedDestArea.height;
+
+    for (int writeRow = clippedDestArea.y; writeRow < yMax; writeRow++)
+    {
+        // Interpolate using the original source rectangle to determine which row to sample from
+        // while clamping to the edges
+        float yPerc    = static_cast<float>(writeRow - destArea.y) / (destArea.height - 1);
+        float yRounded = floor(yPerc * (sourceArea.height - 1) + 0.5f);
+        unsigned int readRow =
+            static_cast<unsigned int>(gl::clamp(sourceArea.y + yRounded, 0, sourceSize.height - 1));
+
+        for (int writeColumn = clippedDestArea.x; writeColumn < xMax; writeColumn++)
+        {
+            // Interpolate the original source rectangle to determine which column to sample
+            // from while clamping to the edges
+            float xPerc    = static_cast<float>(writeColumn - destArea.x) / (destArea.width - 1);
+            float xRounded = floor(xPerc * (sourceArea.width - 1) + 0.5f);
+            unsigned int readColumn = static_cast<unsigned int>(
+                gl::clamp(sourceArea.x + xRounded, 0, sourceSize.height - 1));
+
+            const uint8_t *sourcePixel =
+                sourceData + readRow * sourceRowPitch + readColumn * srcPixelStride + readOffset;
+
+            uint8_t *destPixel =
+                destData + writeRow * destRowPitch + writeColumn * destPixelStride + writeOffset;
+
+            memcpy(destPixel, sourcePixel, copySize);
+        }
+    }
+}
+
+void StretchedBlitNearest(const gl::Box &sourceArea,
+                          const gl::Box &destArea,
+                          const gl::Rectangle &clipRect,
+                          const gl::Extents &sourceSize,
+                          unsigned int sourceRowPitch,
+                          unsigned int destRowPitch,
+                          ptrdiff_t readOffset,
+                          ptrdiff_t writeOffset,
+                          size_t copySize,
+                          size_t srcPixelStride,
+                          size_t destPixelStride,
+                          const uint8_t *sourceData,
+                          uint8_t *destData)
+{
+    gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
+    gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea);
+
+    // Determine if entire rows can be copied at once instead of each individual pixel. There
+    // must be no out of bounds lookups, whole rows copies, and no scale.
+    if (sourceArea.width == clippedDestArea.width && sourceArea.x >= 0 &&
+        sourceArea.x + sourceArea.width <= sourceSize.width && copySize == srcPixelStride &&
+        copySize == destPixelStride)
+    {
+        StretchedBlitNearest_RowByRow(sourceArea, destArea, clippedDestArea, sourceSize,
+                                      sourceRowPitch, destRowPitch, srcPixelStride, sourceData,
+                                      destData);
+    }
+    else
+    {
+        StretchedBlitNearest_PixelByPixel(sourceArea, destArea, clippedDestArea, sourceSize,
+                                          sourceRowPitch, destRowPitch, readOffset, writeOffset,
+                                          copySize, srcPixelStride, destPixelStride, sourceData,
+                                          destData);
+    }
+}
+
+using DepthStencilLoader = void(const float *, uint8_t *);
+
+void LoadDepth16(const float *source, uint8_t *dest)
+{
+    uint32_t convertedDepth = gl::floatToNormalized<16, uint32_t>(source[0]);
+    memcpy(dest, &convertedDepth, 2u);
+}
+
+void LoadDepth24(const float *source, uint8_t *dest)
+{
+    uint32_t convertedDepth = gl::floatToNormalized<24, uint32_t>(source[0]);
+    memcpy(dest, &convertedDepth, 3u);
+}
+
+void LoadStencilHelper(const float *source, uint8_t *dest)
+{
+    uint32_t convertedStencil = gl::getShiftedData<8, 0>(static_cast<uint32_t>(source[1]));
+    memcpy(dest, &convertedStencil, 1u);
+}
+
+void LoadStencil8(const float *source, uint8_t *dest)
+{
+    // STENCIL_INDEX8 is implemented with D24S8, with the depth bits unused. Writes zero for safety.
+    float zero = 0.0f;
+    LoadDepth24(&zero, &dest[0]);
+    LoadStencilHelper(source, &dest[3]);
+}
+
+void LoadDepth24Stencil8(const float *source, uint8_t *dest)
+{
+    LoadDepth24(source, &dest[0]);
+    LoadStencilHelper(source, &dest[3]);
+}
+
+void LoadDepth32F(const float *source, uint8_t *dest)
+{
+    memcpy(dest, source, sizeof(float));
+}
+
+void LoadDepth32FStencil8(const float *source, uint8_t *dest)
+{
+    LoadDepth32F(source, &dest[0]);
+    LoadStencilHelper(source, &dest[4]);
+}
+
+template <DepthStencilLoader loader>
+void CopyDepthStencil(const gl::Box &sourceArea,
+                      const gl::Box &destArea,
+                      const gl::Rectangle &clippedDestArea,
+                      const gl::Extents &sourceSize,
+                      unsigned int sourceRowPitch,
+                      unsigned int destRowPitch,
+                      ptrdiff_t readOffset,
+                      ptrdiff_t writeOffset,
+                      size_t copySize,
+                      size_t srcPixelStride,
+                      size_t destPixelStride,
+                      const uint8_t *sourceData,
+                      uint8_t *destData)
+{
+    // No stretching or subregions are supported, only full blits.
+    ASSERT(sourceArea == destArea);
+    ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
+           sourceSize.depth == 1);
+    ASSERT(clippedDestArea.width == sourceSize.width &&
+           clippedDestArea.height == sourceSize.height);
+    ASSERT(readOffset == 0 && writeOffset == 0);
+    ASSERT(destArea.x == 0 && destArea.y == 0);
+
+    for (int row = 0; row < destArea.height; ++row)
+    {
+        for (int column = 0; column < destArea.width; ++column)
+        {
+            ptrdiff_t offset         = row * sourceRowPitch + column * srcPixelStride;
+            const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
+
+            uint8_t *destPixel = destData + row * destRowPitch + column * destPixelStride;
+
+            loader(sourcePixel, destPixel);
+        }
+    }
+}
+
+void Depth32FStencil8ToDepth32F(const float *source, float *dest)
+{
+    *dest = *source;
+}
+
+void Depth24Stencil8ToDepth32F(const uint32_t *source, float *dest)
+{
+    uint32_t normDepth = source[0] & 0x00FFFFFF;
+    float floatDepth   = gl::normalizedToFloat<24>(normDepth);
+    *dest              = floatDepth;
+}
+
+void BlitD24S8ToD32F(const gl::Box &sourceArea,
+                     const gl::Box &destArea,
+                     const gl::Rectangle &clippedDestArea,
+                     const gl::Extents &sourceSize,
+                     unsigned int sourceRowPitch,
+                     unsigned int destRowPitch,
+                     ptrdiff_t readOffset,
+                     ptrdiff_t writeOffset,
+                     size_t copySize,
+                     size_t srcPixelStride,
+                     size_t destPixelStride,
+                     const uint8_t *sourceData,
+                     uint8_t *destData)
+{
+    // No stretching or subregions are supported, only full blits.
+    ASSERT(sourceArea == destArea);
+    ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
+           sourceSize.depth == 1);
+    ASSERT(clippedDestArea.width == sourceSize.width &&
+           clippedDestArea.height == sourceSize.height);
+    ASSERT(readOffset == 0 && writeOffset == 0);
+    ASSERT(destArea.x == 0 && destArea.y == 0);
+
+    for (int row = 0; row < destArea.height; ++row)
+    {
+        for (int column = 0; column < destArea.width; ++column)
+        {
+            ptrdiff_t offset            = row * sourceRowPitch + column * srcPixelStride;
+            const uint32_t *sourcePixel = reinterpret_cast<const uint32_t *>(sourceData + offset);
+
+            float *destPixel =
+                reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
+
+            Depth24Stencil8ToDepth32F(sourcePixel, destPixel);
+        }
+    }
+}
+
+void BlitD32FS8ToD32F(const gl::Box &sourceArea,
+                      const gl::Box &destArea,
+                      const gl::Rectangle &clippedDestArea,
+                      const gl::Extents &sourceSize,
+                      unsigned int sourceRowPitch,
+                      unsigned int destRowPitch,
+                      ptrdiff_t readOffset,
+                      ptrdiff_t writeOffset,
+                      size_t copySize,
+                      size_t srcPixelStride,
+                      size_t destPixelStride,
+                      const uint8_t *sourceData,
+                      uint8_t *destData)
+{
+    // No stretching or subregions are supported, only full blits.
+    ASSERT(sourceArea == destArea);
+    ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
+           sourceSize.depth == 1);
+    ASSERT(clippedDestArea.width == sourceSize.width &&
+           clippedDestArea.height == sourceSize.height);
+    ASSERT(readOffset == 0 && writeOffset == 0);
+    ASSERT(destArea.x == 0 && destArea.y == 0);
+
+    for (int row = 0; row < destArea.height; ++row)
+    {
+        for (int column = 0; column < destArea.width; ++column)
+        {
+            ptrdiff_t offset         = row * sourceRowPitch + column * srcPixelStride;
+            const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
+            float *destPixel =
+                reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
+
+            Depth32FStencil8ToDepth32F(sourcePixel, destPixel);
+        }
+    }
+}
+
+Blit11::BlitConvertFunction *GetCopyDepthStencilFunction(GLenum internalFormat)
+{
+    switch (internalFormat)
+    {
+        case GL_DEPTH_COMPONENT16:
+            return &CopyDepthStencil<LoadDepth16>;
+        case GL_DEPTH_COMPONENT24:
+            return &CopyDepthStencil<LoadDepth24>;
+        case GL_DEPTH_COMPONENT32F:
+            return &CopyDepthStencil<LoadDepth32F>;
+        case GL_STENCIL_INDEX8:
+            return &CopyDepthStencil<LoadStencil8>;
+        case GL_DEPTH24_STENCIL8:
+            return &CopyDepthStencil<LoadDepth24Stencil8>;
+        case GL_DEPTH32F_STENCIL8:
+            return &CopyDepthStencil<LoadDepth32FStencil8>;
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+}
+
+inline void GenerateVertexCoords(const gl::Box &sourceArea,
+                                 const gl::Extents &sourceSize,
+                                 const gl::Box &destArea,
+                                 const gl::Extents &destSize,
+                                 float *x1,
+                                 float *y1,
+                                 float *x2,
+                                 float *y2,
+                                 float *u1,
+                                 float *v1,
+                                 float *u2,
+                                 float *v2)
+{
+    *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
+    *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f;
+    *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f;
+    *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f;
+
+    *u1 = sourceArea.x / float(sourceSize.width);
+    *v1 = sourceArea.y / float(sourceSize.height);
+    *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width);
+    *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height);
+}
+
+void Write2DVertices(const gl::Box &sourceArea,
+                     const gl::Extents &sourceSize,
+                     const gl::Box &destArea,
+                     const gl::Extents &destSize,
+                     void *outVertices,
+                     unsigned int *outStride,
+                     unsigned int *outVertexCount,
+                     D3D11_PRIMITIVE_TOPOLOGY *outTopology)
+{
+    float x1, y1, x2, y2, u1, v1, u2, v2;
+    GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
+                         &u2, &v2);
+
+    d3d11::PositionTexCoordVertex *vertices =
+        static_cast<d3d11::PositionTexCoordVertex *>(outVertices);
+
+    d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
+    d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
+    d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
+    d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
+
+    *outStride      = sizeof(d3d11::PositionTexCoordVertex);
+    *outVertexCount = 4;
+    *outTopology    = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+}
+
+void Write3DVertices(const gl::Box &sourceArea,
+                     const gl::Extents &sourceSize,
+                     const gl::Box &destArea,
+                     const gl::Extents &destSize,
+                     void *outVertices,
+                     unsigned int *outStride,
+                     unsigned int *outVertexCount,
+                     D3D11_PRIMITIVE_TOPOLOGY *outTopology)
+{
+    ASSERT(sourceSize.depth > 0 && destSize.depth > 0);
+
+    float x1, y1, x2, y2, u1, v1, u2, v2;
+    GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
+                         &u2, &v2);
+
+    d3d11::PositionLayerTexCoord3DVertex *vertices =
+        static_cast<d3d11::PositionLayerTexCoord3DVertex *>(outVertices);
+
+    for (int i = 0; i < destSize.depth; i++)
+    {
+        float readDepth = (float)i / std::max(destSize.depth - 1, 1);
+
+        d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth);
+        d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth);
+        d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth);
+
+        d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth);
+        d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth);
+        d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth);
+    }
+
+    *outStride      = sizeof(d3d11::PositionLayerTexCoord3DVertex);
+    *outVertexCount = destSize.depth * 6;
+    *outTopology    = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+}
+
+unsigned int GetSwizzleIndex(GLenum swizzle)
+{
+    unsigned int colorIndex = 0;
+
+    switch (swizzle)
+    {
+        case GL_RED:
+            colorIndex = 0;
+            break;
+        case GL_GREEN:
+            colorIndex = 1;
+            break;
+        case GL_BLUE:
+            colorIndex = 2;
+            break;
+        case GL_ALPHA:
+            colorIndex = 3;
+            break;
+        case GL_ZERO:
+            colorIndex = 4;
+            break;
+        case GL_ONE:
+            colorIndex = 5;
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    return colorIndex;
+}
+
+D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc()
+{
+    D3D11_BLEND_DESC desc;
+    memset(&desc, 0, sizeof(desc));
+    desc.RenderTarget[0].BlendEnable           = TRUE;
+    desc.RenderTarget[0].SrcBlend              = D3D11_BLEND_ONE;
+    desc.RenderTarget[0].DestBlend             = D3D11_BLEND_ZERO;
+    desc.RenderTarget[0].BlendOp               = D3D11_BLEND_OP_ADD;
+    desc.RenderTarget[0].SrcBlendAlpha         = D3D11_BLEND_ZERO;
+    desc.RenderTarget[0].DestBlendAlpha        = D3D11_BLEND_ZERO;
+    desc.RenderTarget[0].BlendOpAlpha          = D3D11_BLEND_OP_ADD;
+    desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED |
+                                                 D3D11_COLOR_WRITE_ENABLE_GREEN |
+                                                 D3D11_COLOR_WRITE_ENABLE_BLUE;
+    return desc;
+}
+
+D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = {
+    {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+    {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
+};
+
+D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = {
+    {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+    {"LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
+    {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
+};
+
+DXGI_FORMAT GetStencilSRVFormat(const d3d11::Format &formatSet)
+{
+    switch (formatSet.texFormat)
+    {
+        case DXGI_FORMAT_R32G8X24_TYPELESS:
+            return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
+        case DXGI_FORMAT_R24G8_TYPELESS:
+            return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
+        default:
+            UNREACHABLE();
+            return DXGI_FORMAT_UNKNOWN;
+    }
+}
+
+}  // namespace
+
+Blit11::Blit11(Renderer11 *renderer)
+    : mRenderer(renderer),
+      mResourcesInitialized(false),
+      mVertexBuffer(nullptr),
+      mPointSampler(nullptr),
+      mLinearSampler(nullptr),
+      mScissorEnabledRasterizerState(nullptr),
+      mScissorDisabledRasterizerState(nullptr),
+      mDepthStencilState(nullptr),
+      mQuad2DIL(quad2DLayout,
+                ArraySize(quad2DLayout),
+                g_VS_Passthrough2D,
+                ArraySize(g_VS_Passthrough2D),
+                "Blit11 2D input layout"),
+      mQuad2DVS(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D vertex shader"),
+      mDepthPS(g_PS_PassthroughDepth2D,
+               ArraySize(g_PS_PassthroughDepth2D),
+               "Blit11 2D depth pixel shader"),
+      mQuad3DIL(quad3DLayout,
+                ArraySize(quad3DLayout),
+                g_VS_Passthrough3D,
+                ArraySize(g_VS_Passthrough3D),
+                "Blit11 3D input layout"),
+      mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"),
+      mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"),
+      mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"),
+      mSwizzleCB(nullptr),
+      mResolveDepthStencilVS(g_VS_ResolveDepthStencil,
+                             ArraySize(g_VS_ResolveDepthStencil),
+                             "Blit11::mResolveDepthStencilVS"),
+      mResolveDepthPS(g_PS_ResolveDepth, ArraySize(g_PS_ResolveDepth), "Blit11::mResolveDepthPS"),
+      mResolveDepthStencilPS(g_PS_ResolveDepthStencil,
+                             ArraySize(g_PS_ResolveDepthStencil),
+                             "Blit11::mResolveDepthStencilPS"),
+      mResolveStencilPS(g_PS_ResolveStencil,
+                        ArraySize(g_PS_ResolveStencil),
+                        "Blit11::mResolveStencilPS"),
+      mStencilSRV(nullptr),
+      mResolvedDepthStencilRTView()
+{
+}
+
+Blit11::~Blit11()
+{
+    mQuad2DIL.release();
+    mQuad2DVS.release();
+    mDepthPS.release();
+
+    mQuad3DIL.release();
+    mQuad3DVS.release();
+    mQuad3DGS.release();
+
+    clearShaderMap();
+    releaseResolveDepthStencilResources();
+}
+
+gl::Error Blit11::initResources()
+{
+    if (mResourcesInitialized)
+    {
+        return gl::NoError();
+    }
+
+    TRACE_EVENT0("gpu.angle", "Blit11::initResources");
+
+    HRESULT result;
+    ID3D11Device *device = mRenderer->getDevice();
+
+    D3D11_BUFFER_DESC vbDesc;
+    vbDesc.ByteWidth =
+        static_cast<unsigned int>(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex),
+                                           sizeof(d3d11::PositionTexCoordVertex)) *
+                                  6 * mRenderer->getNativeCaps().max3DTextureSize);
+    vbDesc.Usage               = D3D11_USAGE_DYNAMIC;
+    vbDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
+    vbDesc.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
+    vbDesc.MiscFlags           = 0;
+    vbDesc.StructureByteStride = 0;
+
+    result = device->CreateBuffer(&vbDesc, nullptr, mVertexBuffer.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to create blit vertex buffer, " << result;
+    }
+    d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer");
+
+    D3D11_SAMPLER_DESC pointSamplerDesc;
+    pointSamplerDesc.Filter         = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
+    pointSamplerDesc.AddressU       = D3D11_TEXTURE_ADDRESS_CLAMP;
+    pointSamplerDesc.AddressV       = D3D11_TEXTURE_ADDRESS_CLAMP;
+    pointSamplerDesc.AddressW       = D3D11_TEXTURE_ADDRESS_CLAMP;
+    pointSamplerDesc.MipLODBias     = 0.0f;
+    pointSamplerDesc.MaxAnisotropy  = 0;
+    pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+    pointSamplerDesc.BorderColor[0] = 0.0f;
+    pointSamplerDesc.BorderColor[1] = 0.0f;
+    pointSamplerDesc.BorderColor[2] = 0.0f;
+    pointSamplerDesc.BorderColor[3] = 0.0f;
+    pointSamplerDesc.MinLOD         = 0.0f;
+    pointSamplerDesc.MaxLOD         = FLT_MAX;
+
+    result = device->CreateSamplerState(&pointSamplerDesc, mPointSampler.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to create blit point sampler state, " << result;
+    }
+    d3d11::SetDebugName(mPointSampler, "Blit11 point sampler");
+
+    D3D11_SAMPLER_DESC linearSamplerDesc;
+    linearSamplerDesc.Filter         = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+    linearSamplerDesc.AddressU       = D3D11_TEXTURE_ADDRESS_CLAMP;
+    linearSamplerDesc.AddressV       = D3D11_TEXTURE_ADDRESS_CLAMP;
+    linearSamplerDesc.AddressW       = D3D11_TEXTURE_ADDRESS_CLAMP;
+    linearSamplerDesc.MipLODBias     = 0.0f;
+    linearSamplerDesc.MaxAnisotropy  = 0;
+    linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+    linearSamplerDesc.BorderColor[0] = 0.0f;
+    linearSamplerDesc.BorderColor[1] = 0.0f;
+    linearSamplerDesc.BorderColor[2] = 0.0f;
+    linearSamplerDesc.BorderColor[3] = 0.0f;
+    linearSamplerDesc.MinLOD         = 0.0f;
+    linearSamplerDesc.MaxLOD         = FLT_MAX;
+
+    result = device->CreateSamplerState(&linearSamplerDesc, mLinearSampler.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to create blit linear sampler state, " << result;
+    }
+    d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler");
+
+    // Use a rasterizer state that will not cull so that inverted quads will not be culled
+    D3D11_RASTERIZER_DESC rasterDesc;
+    rasterDesc.FillMode              = D3D11_FILL_SOLID;
+    rasterDesc.CullMode              = D3D11_CULL_NONE;
+    rasterDesc.FrontCounterClockwise = FALSE;
+    rasterDesc.DepthBias             = 0;
+    rasterDesc.SlopeScaledDepthBias  = 0.0f;
+    rasterDesc.DepthBiasClamp        = 0.0f;
+    rasterDesc.DepthClipEnable       = TRUE;
+    rasterDesc.MultisampleEnable     = FALSE;
+    rasterDesc.AntialiasedLineEnable = FALSE;
+
+    rasterDesc.ScissorEnable = TRUE;
+    result =
+        device->CreateRasterizerState(&rasterDesc, mScissorEnabledRasterizerState.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to create blit scissoring rasterizer state, " << result;
+    }
+    d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
+
+    rasterDesc.ScissorEnable = FALSE;
+    result =
+        device->CreateRasterizerState(&rasterDesc, mScissorDisabledRasterizerState.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to create blit no scissoring rasterizer state, "
+                                 << result;
+    }
+    d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state");
+
+    D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
+    depthStencilDesc.DepthEnable                  = TRUE;
+    depthStencilDesc.DepthWriteMask               = D3D11_DEPTH_WRITE_MASK_ALL;
+    depthStencilDesc.DepthFunc                    = D3D11_COMPARISON_ALWAYS;
+    depthStencilDesc.StencilEnable                = FALSE;
+    depthStencilDesc.StencilReadMask              = D3D11_DEFAULT_STENCIL_READ_MASK;
+    depthStencilDesc.StencilWriteMask             = D3D11_DEFAULT_STENCIL_WRITE_MASK;
+    depthStencilDesc.FrontFace.StencilFailOp      = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.FrontFace.StencilPassOp      = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.FrontFace.StencilFunc        = D3D11_COMPARISON_ALWAYS;
+    depthStencilDesc.BackFace.StencilFailOp       = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.BackFace.StencilDepthFailOp  = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.BackFace.StencilPassOp       = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.BackFace.StencilFunc         = D3D11_COMPARISON_ALWAYS;
+
+    result = device->CreateDepthStencilState(&depthStencilDesc, mDepthStencilState.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to create blit depth stencil state, " << result;
+    }
+    d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state");
+
+    D3D11_BUFFER_DESC swizzleBufferDesc;
+    swizzleBufferDesc.ByteWidth           = sizeof(unsigned int) * 4;
+    swizzleBufferDesc.Usage               = D3D11_USAGE_DYNAMIC;
+    swizzleBufferDesc.BindFlags           = D3D11_BIND_CONSTANT_BUFFER;
+    swizzleBufferDesc.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
+    swizzleBufferDesc.MiscFlags           = 0;
+    swizzleBufferDesc.StructureByteStride = 0;
+
+    result = device->CreateBuffer(&swizzleBufferDesc, nullptr, mSwizzleCB.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to create blit swizzle buffer, " << result;
+    }
+    d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer");
+
+    mResourcesInitialized = true;
+
+    return gl::NoError();
+}
+
+// static
+Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat,
+                                                 bool isSigned,
+                                                 bool unpackPremultiplyAlpha,
+                                                 bool unpackUnmultiplyAlpha,
+                                                 ShaderDimension dimension)
+{
+    if (dimension == SHADER_3D)
+    {
+        ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
+
+        if (isSigned)
+        {
+            switch (destinationFormat)
+            {
+                case GL_RGBA_INTEGER:
+                    return BLITSHADER_3D_RGBAI;
+                case GL_RGB_INTEGER:
+                    return BLITSHADER_3D_RGBI;
+                case GL_RG_INTEGER:
+                    return BLITSHADER_3D_RGI;
+                case GL_RED_INTEGER:
+                    return BLITSHADER_3D_RI;
+                default:
+                    UNREACHABLE();
+                    return BLITSHADER_INVALID;
+            }
+        }
+        else
+        {
+            switch (destinationFormat)
+            {
+                case GL_RGBA:
+                    return BLITSHADER_3D_RGBAF;
+                case GL_RGBA_INTEGER:
+                    return BLITSHADER_3D_RGBAUI;
+                case GL_BGRA_EXT:
+                    return BLITSHADER_3D_BGRAF;
+                case GL_RGB:
+                    return BLITSHADER_3D_RGBF;
+                case GL_RGB_INTEGER:
+                    return BLITSHADER_3D_RGBUI;
+                case GL_RG:
+                    return BLITSHADER_3D_RGF;
+                case GL_RG_INTEGER:
+                    return BLITSHADER_3D_RGUI;
+                case GL_RED:
+                    return BLITSHADER_3D_RF;
+                case GL_RED_INTEGER:
+                    return BLITSHADER_3D_RUI;
+                case GL_ALPHA:
+                    return BLITSHADER_3D_ALPHA;
+                case GL_LUMINANCE:
+                    return BLITSHADER_3D_LUMA;
+                case GL_LUMINANCE_ALPHA:
+                    return BLITSHADER_3D_LUMAALPHA;
+                default:
+                    UNREACHABLE();
+                    return BLITSHADER_INVALID;
+            }
+        }
+    }
+    else if (isSigned)
+    {
+        ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
+
+        switch (destinationFormat)
+        {
+            case GL_RGBA_INTEGER:
+                return BLITSHADER_2D_RGBAI;
+            case GL_RGB_INTEGER:
+                return BLITSHADER_2D_RGBI;
+            case GL_RG_INTEGER:
+                return BLITSHADER_2D_RGI;
+            case GL_RED_INTEGER:
+                return BLITSHADER_2D_RI;
+            default:
+                UNREACHABLE();
+                return BLITSHADER_INVALID;
+        }
+    }
+    else
+    {
+        if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha)
+        {
+            switch (destinationFormat)
+            {
+                case GL_RGBA:
+                    return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_PREMULTIPLY
+                                                  : BLITSHADER_2D_RGBAF_UNMULTIPLY;
+                case GL_BGRA_EXT:
+                    return unpackPremultiplyAlpha ? BLITSHADER_2D_BGRAF_PREMULTIPLY
+                                                  : BLITSHADER_2D_BGRAF_UNMULTIPLY;
+                case GL_RGB:
+                    return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_PREMULTIPLY
+                                                  : BLITSHADER_2D_RGBF_UNMULTIPLY;
+                default:
+                    UNREACHABLE();
+                    return BLITSHADER_INVALID;
+            }
+        }
+        else
+        {
+            switch (destinationFormat)
+            {
+                case GL_RGBA:
+                    return BLITSHADER_2D_RGBAF;
+                case GL_RGBA_INTEGER:
+                    return BLITSHADER_2D_RGBAUI;
+                case GL_BGRA_EXT:
+                    return BLITSHADER_2D_BGRAF;
+                case GL_RGB:
+                    return BLITSHADER_2D_RGBF;
+                case GL_RGB_INTEGER:
+                    return BLITSHADER_2D_RGBUI;
+                case GL_RG:
+                    return BLITSHADER_2D_RGF;
+                case GL_RG_INTEGER:
+                    return BLITSHADER_2D_RGUI;
+                case GL_RED:
+                    return BLITSHADER_2D_RF;
+                case GL_RED_INTEGER:
+                    return BLITSHADER_2D_RUI;
+                case GL_ALPHA:
+                    return BLITSHADER_2D_ALPHA;
+                case GL_LUMINANCE:
+                    return BLITSHADER_2D_LUMA;
+                case GL_LUMINANCE_ALPHA:
+                    return BLITSHADER_2D_LUMAALPHA;
+                default:
+                    UNREACHABLE();
+                    return BLITSHADER_INVALID;
+            }
+        }
+    }
+}
+
+// static
+Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type,
+                                                       D3D11_SRV_DIMENSION dimensionality)
+{
+    switch (dimensionality)
+    {
+        case D3D11_SRV_DIMENSION_TEXTURE2D:
+            switch (type)
+            {
+                case GL_FLOAT:
+                    return SWIZZLESHADER_2D_FLOAT;
+                case GL_UNSIGNED_INT:
+                    return SWIZZLESHADER_2D_UINT;
+                case GL_INT:
+                    return SWIZZLESHADER_2D_INT;
+                default:
+                    UNREACHABLE();
+                    return SWIZZLESHADER_INVALID;
+            }
+        case D3D11_SRV_DIMENSION_TEXTURECUBE:
+            switch (type)
+            {
+                case GL_FLOAT:
+                    return SWIZZLESHADER_CUBE_FLOAT;
+                case GL_UNSIGNED_INT:
+                    return SWIZZLESHADER_CUBE_UINT;
+                case GL_INT:
+                    return SWIZZLESHADER_CUBE_INT;
+                default:
+                    UNREACHABLE();
+                    return SWIZZLESHADER_INVALID;
+            }
+        case D3D11_SRV_DIMENSION_TEXTURE3D:
+            switch (type)
+            {
+                case GL_FLOAT:
+                    return SWIZZLESHADER_3D_FLOAT;
+                case GL_UNSIGNED_INT:
+                    return SWIZZLESHADER_3D_UINT;
+                case GL_INT:
+                    return SWIZZLESHADER_3D_INT;
+                default:
+                    UNREACHABLE();
+                    return SWIZZLESHADER_INVALID;
+            }
+        case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+            switch (type)
+            {
+                case GL_FLOAT:
+                    return SWIZZLESHADER_ARRAY_FLOAT;
+                case GL_UNSIGNED_INT:
+                    return SWIZZLESHADER_ARRAY_UINT;
+                case GL_INT:
+                    return SWIZZLESHADER_ARRAY_INT;
+                default:
+                    UNREACHABLE();
+                    return SWIZZLESHADER_INVALID;
+            }
+        default:
+            UNREACHABLE();
+            return SWIZZLESHADER_INVALID;
+    }
+}
+
+Blit11::ShaderSupport Blit11::getShaderSupport(const Shader &shader)
+{
+    ID3D11Device *device = mRenderer->getDevice();
+    ShaderSupport support;
+
+    if (shader.dimension == SHADER_2D)
+    {
+        support.inputLayout         = mQuad2DIL.resolve(device);
+        support.vertexShader        = mQuad2DVS.resolve(device);
+        support.geometryShader      = nullptr;
+        support.vertexWriteFunction = Write2DVertices;
+    }
+    else
+    {
+        ASSERT(shader.dimension == SHADER_3D);
+        support.inputLayout         = mQuad3DIL.resolve(device);
+        support.vertexShader        = mQuad3DVS.resolve(device);
+        support.geometryShader      = mQuad3DGS.resolve(device);
+        support.vertexWriteFunction = Write3DVertices;
+    }
+
+    return support;
+}
+
+gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
+                                 const d3d11::RenderTargetView &dest,
+                                 const gl::Extents &size,
+                                 const gl::SwizzleState &swizzleTarget)
+{
+    ANGLE_TRY(initResources());
+
+    HRESULT result;
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
+    source->GetDesc(&sourceSRVDesc);
+
+    GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
+    if (componentType == GL_NONE)
+    {
+        // We're swizzling the depth component of a depth-stencil texture.
+        switch (sourceSRVDesc.Format)
+        {
+            case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+                componentType = GL_UNSIGNED_NORMALIZED;
+                break;
+            case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+                componentType = GL_FLOAT;
+                break;
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+
+    GLenum shaderType = GL_NONE;
+    switch (componentType)
+    {
+        case GL_UNSIGNED_NORMALIZED:
+        case GL_SIGNED_NORMALIZED:
+        case GL_FLOAT:
+            shaderType = GL_FLOAT;
+            break;
+        case GL_INT:
+            shaderType = GL_INT;
+            break;
+        case GL_UNSIGNED_INT:
+            shaderType = GL_UNSIGNED_INT;
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    const Shader *shader = nullptr;
+    ANGLE_TRY(getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader));
+
+    // Set vertices
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    result =
+        deviceContext->Map(mVertexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to map internal vertex buffer for swizzle, " << result;
+    }
+
+    const ShaderSupport &support = getShaderSupport(*shader);
+
+    UINT stride    = 0;
+    UINT startIdx  = 0;
+    UINT drawCount = 0;
+    D3D11_PRIMITIVE_TOPOLOGY topology;
+
+    gl::Box area(0, 0, 0, size.width, size.height, size.depth);
+    support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount,
+                                &topology);
+
+    deviceContext->Unmap(mVertexBuffer.Get(), 0);
+
+    // Set constant buffer
+    result = deviceContext->Map(mSwizzleCB.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to map internal constant buffer for swizzle, "
+                                 << result;
+    }
+
+    unsigned int *swizzleIndices = reinterpret_cast<unsigned int *>(mappedResource.pData);
+    swizzleIndices[0]            = GetSwizzleIndex(swizzleTarget.swizzleRed);
+    swizzleIndices[1]            = GetSwizzleIndex(swizzleTarget.swizzleGreen);
+    swizzleIndices[2]            = GetSwizzleIndex(swizzleTarget.swizzleBlue);
+    swizzleIndices[3]            = GetSwizzleIndex(swizzleTarget.swizzleAlpha);
+
+    deviceContext->Unmap(mSwizzleCB.Get(), 0);
+
+    // Apply vertex buffer
+    deviceContext->IASetVertexBuffers(0, 1, mVertexBuffer.GetAddressOf(), &stride, &startIdx);
+
+    // Apply constant buffer
+    deviceContext->PSSetConstantBuffers(0, 1, mSwizzleCB.GetAddressOf());
+
+    // Apply state
+    deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+    deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
+    deviceContext->RSSetState(mScissorDisabledRasterizerState.Get());
+
+    // Apply shaders
+    deviceContext->IASetInputLayout(support.inputLayout);
+    deviceContext->IASetPrimitiveTopology(topology);
+    deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
+
+    deviceContext->PSSetShader(shader->pixelShader, nullptr, 0);
+    deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
+
+    // Unset the currently bound shader resource to avoid conflicts
+    auto stateManager = mRenderer->getStateManager();
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+    // Apply render target
+    stateManager->setOneTimeRenderTarget(dest.get(), nullptr);
+
+    // Set the viewport
+    D3D11_VIEWPORT viewport;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    viewport.Width    = static_cast<FLOAT>(size.width);
+    viewport.Height   = static_cast<FLOAT>(size.height);
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 1.0f;
+    deviceContext->RSSetViewports(1, &viewport);
+
+    // Apply textures
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
+
+    // Apply samplers
+    deviceContext->PSSetSamplers(0, 1, mPointSampler.GetAddressOf());
+
+    // Draw the quad
+    deviceContext->Draw(drawCount, 0);
+
+    // Unbind textures and render targets and vertex buffer
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+    UINT zero                      = 0;
+    ID3D11Buffer *const nullBuffer = nullptr;
+    deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+    mRenderer->markAllStateDirty();
+
+    return gl::NoError();
+}
+
+gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
+                              const gl::Box &sourceArea,
+                              const gl::Extents &sourceSize,
+                              const d3d11::RenderTargetView &dest,
+                              const gl::Box &destArea,
+                              const gl::Extents &destSize,
+                              const gl::Rectangle *scissor,
+                              GLenum destFormat,
+                              GLenum filter,
+                              bool maskOffAlpha,
+                              bool unpackPremultiplyAlpha,
+                              bool unpackUnmultiplyAlpha)
+{
+    ANGLE_TRY(initResources());
+
+    HRESULT result;
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    // Determine if the source format is a signed integer format, the destFormat will already
+    // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned.
+    D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
+    source->GetDesc(&sourceSRVDesc);
+
+    GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
+
+    ASSERT(componentType != GL_NONE);
+    ASSERT(componentType != GL_SIGNED_NORMALIZED);
+    bool isSigned = (componentType == GL_INT);
+
+    ShaderDimension dimension =
+        (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D;
+
+    const Shader *shader = nullptr;
+    ANGLE_TRY(getBlitShader(destFormat, isSigned, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
+                            dimension, &shader));
+
+    const ShaderSupport &support = getShaderSupport(*shader);
+
+    // Set vertices
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    result =
+        deviceContext->Map(mVertexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to map internal vertex buffer for texture copy, "
+                                 << result;
+    }
+
+    UINT stride    = 0;
+    UINT startIdx  = 0;
+    UINT drawCount = 0;
+    D3D11_PRIMITIVE_TOPOLOGY topology;
+
+    support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
+                                &stride, &drawCount, &topology);
+
+    deviceContext->Unmap(mVertexBuffer.Get(), 0);
+
+    // Apply vertex buffer
+    deviceContext->IASetVertexBuffers(0, 1, mVertexBuffer.GetAddressOf(), &stride, &startIdx);
+
+    // Apply state
+    if (maskOffAlpha)
+    {
+        ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice());
+        ASSERT(blendState);
+        deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF);
+    }
+    else
+    {
+        deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+    }
+    deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
+
+    if (scissor)
+    {
+        D3D11_RECT scissorRect;
+        scissorRect.left   = scissor->x;
+        scissorRect.right  = scissor->x + scissor->width;
+        scissorRect.top    = scissor->y;
+        scissorRect.bottom = scissor->y + scissor->height;
+
+        deviceContext->RSSetScissorRects(1, &scissorRect);
+        deviceContext->RSSetState(mScissorEnabledRasterizerState.Get());
+    }
+    else
+    {
+        deviceContext->RSSetState(mScissorDisabledRasterizerState.Get());
+    }
+
+    // Apply shaders
+    deviceContext->IASetInputLayout(support.inputLayout);
+    deviceContext->IASetPrimitiveTopology(topology);
+    deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
+
+    deviceContext->PSSetShader(shader->pixelShader, nullptr, 0);
+    deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
+
+    // Unset the currently bound shader resource to avoid conflicts
+    auto stateManager = mRenderer->getStateManager();
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+    // Apply render target
+    stateManager->setOneTimeRenderTarget(dest.get(), nullptr);
+
+    // Set the viewport
+    D3D11_VIEWPORT viewport;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    viewport.Width    = static_cast<FLOAT>(destSize.width);
+    viewport.Height   = static_cast<FLOAT>(destSize.height);
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 1.0f;
+    deviceContext->RSSetViewports(1, &viewport);
+
+    // Apply textures
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
+
+    // Apply samplers
+    ID3D11SamplerState *sampler = nullptr;
+    switch (filter)
+    {
+        case GL_NEAREST:
+            sampler = mPointSampler.Get();
+            break;
+        case GL_LINEAR:
+            sampler = mLinearSampler.Get();
+            break;
+
+        default:
+            UNREACHABLE();
+            return gl::InternalError() << "Internal error, unknown blit filter mode.";
+    }
+    deviceContext->PSSetSamplers(0, 1, &sampler);
+
+    // Draw the quad
+    deviceContext->Draw(drawCount, 0);
+
+    // Unbind textures and render targets and vertex buffer
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+    UINT zero                      = 0;
+    ID3D11Buffer *const nullBuffer = nullptr;
+    deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+    mRenderer->markAllStateDirty();
+
+    return gl::NoError();
+}
+
+gl::Error Blit11::copyStencil(const TextureHelper11 &source,
+                              unsigned int sourceSubresource,
+                              const gl::Box &sourceArea,
+                              const gl::Extents &sourceSize,
+                              const TextureHelper11 &dest,
+                              unsigned int destSubresource,
+                              const gl::Box &destArea,
+                              const gl::Extents &destSize,
+                              const gl::Rectangle *scissor)
+{
+    return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest,
+                                destSubresource, destArea, destSize, scissor, true);
+}
+
+gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source,
+                            const gl::Box &sourceArea,
+                            const gl::Extents &sourceSize,
+                            ID3D11DepthStencilView *dest,
+                            const gl::Box &destArea,
+                            const gl::Extents &destSize,
+                            const gl::Rectangle *scissor)
+{
+    ANGLE_TRY(initResources());
+
+    HRESULT result;
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    // Set vertices
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    result =
+        deviceContext->Map(mVertexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory() << "Failed to map internal vertex buffer for texture copy, "
+                                 << result;
+    }
+
+    UINT stride    = 0;
+    UINT startIdx  = 0;
+    UINT drawCount = 0;
+    D3D11_PRIMITIVE_TOPOLOGY topology;
+
+    Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride,
+                    &drawCount, &topology);
+
+    deviceContext->Unmap(mVertexBuffer.Get(), 0);
+
+    // Apply vertex buffer
+    deviceContext->IASetVertexBuffers(0, 1, mVertexBuffer.GetAddressOf(), &stride, &startIdx);
+
+    // Apply state
+    deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+    deviceContext->OMSetDepthStencilState(mDepthStencilState.Get(), 0xFFFFFFFF);
+
+    if (scissor)
+    {
+        D3D11_RECT scissorRect;
+        scissorRect.left   = scissor->x;
+        scissorRect.right  = scissor->x + scissor->width;
+        scissorRect.top    = scissor->y;
+        scissorRect.bottom = scissor->y + scissor->height;
+
+        deviceContext->RSSetScissorRects(1, &scissorRect);
+        deviceContext->RSSetState(mScissorEnabledRasterizerState.Get());
+    }
+    else
+    {
+        deviceContext->RSSetState(mScissorDisabledRasterizerState.Get());
+    }
+
+    ID3D11Device *device         = mRenderer->getDevice();
+    ID3D11VertexShader *quad2DVS = mQuad2DVS.resolve(device);
+    if (quad2DVS == nullptr)
+    {
+        return gl::InternalError() << "Error compiling internal 2D blit vertex shader";
+    }
+
+    // Apply shaders
+    deviceContext->IASetInputLayout(mQuad2DIL.resolve(device));
+    deviceContext->IASetPrimitiveTopology(topology);
+    deviceContext->VSSetShader(quad2DVS, nullptr, 0);
+
+    deviceContext->PSSetShader(mDepthPS.resolve(device), nullptr, 0);
+    deviceContext->GSSetShader(nullptr, nullptr, 0);
+
+    // Unset the currently bound shader resource to avoid conflicts
+    auto stateManager = mRenderer->getStateManager();
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+    // Apply render target
+    stateManager->setOneTimeRenderTarget(nullptr, dest);
+
+    // Set the viewport
+    D3D11_VIEWPORT viewport;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    viewport.Width    = static_cast<FLOAT>(destSize.width);
+    viewport.Height   = static_cast<FLOAT>(destSize.height);
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 1.0f;
+    deviceContext->RSSetViewports(1, &viewport);
+
+    // Apply textures
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
+
+    // Apply samplers
+    deviceContext->PSSetSamplers(0, 1, mPointSampler.GetAddressOf());
+
+    // Draw the quad
+    deviceContext->Draw(drawCount, 0);
+
+    // Unbind textures and render targets and vertex buffer
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+    UINT zero                      = 0;
+    ID3D11Buffer *const nullBuffer = nullptr;
+    deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+    mRenderer->markAllStateDirty();
+
+    return gl::NoError();
+}
+
+gl::Error Blit11::copyDepthStencil(const TextureHelper11 &source,
+                                   unsigned int sourceSubresource,
+                                   const gl::Box &sourceArea,
+                                   const gl::Extents &sourceSize,
+                                   const TextureHelper11 &dest,
+                                   unsigned int destSubresource,
+                                   const gl::Box &destArea,
+                                   const gl::Extents &destSize,
+                                   const gl::Rectangle *scissor)
+{
+    return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest,
+                                destSubresource, destArea, destSize, scissor, false);
+}
+
+gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source,
+                                       unsigned int sourceSubresource,
+                                       const gl::Box &sourceArea,
+                                       const gl::Extents &sourceSize,
+                                       const TextureHelper11 &dest,
+                                       unsigned int destSubresource,
+                                       const gl::Box &destArea,
+                                       const gl::Extents &destSize,
+                                       const gl::Rectangle *scissor,
+                                       bool stencilOnly)
+{
+    auto srcDXGIFormat         = source.getFormat();
+    const auto &srcSizeInfo    = d3d11::GetDXGIFormatSizeInfo(srcDXGIFormat);
+    unsigned int srcPixelSize  = srcSizeInfo.pixelBytes;
+    unsigned int copyOffset    = 0;
+    unsigned int copySize      = srcPixelSize;
+    auto destDXGIFormat        = dest.getFormat();
+    const auto &destSizeInfo   = d3d11::GetDXGIFormatSizeInfo(destDXGIFormat);
+    unsigned int destPixelSize = destSizeInfo.pixelBytes;
+
+    ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS);
+
+    if (stencilOnly)
+    {
+        const auto &srcFormat = source.getFormatSet().format();
+
+        // Stencil channel should be right after the depth channel. Some views to depth/stencil
+        // resources have red channel for depth, in which case the depth channel bit width is in
+        // redBits.
+        ASSERT((srcFormat.redBits != 0) != (srcFormat.depthBits != 0));
+        GLuint depthBits = srcFormat.redBits + srcFormat.depthBits;
+        // Known formats have either 24 or 32 bits of depth.
+        ASSERT(depthBits == 24 || depthBits == 32);
+        copyOffset = depthBits / 8;
+
+        // Stencil is assumed to be 8-bit - currently this is true for all possible formats.
+        copySize = 1;
+    }
+
+    if (srcDXGIFormat != destDXGIFormat)
+    {
+        if (srcDXGIFormat == DXGI_FORMAT_R24G8_TYPELESS)
+        {
+            ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr);
+            return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest,
+                                  destSubresource, destArea, destSize, scissor, copyOffset,
+                                  copyOffset, copySize, srcPixelSize, destPixelSize,
+                                  BlitD24S8ToD32F);
+        }
+        ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS);
+        return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest,
+                              destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
+                              copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F);
+    }
+
+    return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource,
+                          destArea, destSize, scissor, copyOffset, copyOffset, copySize,
+                          srcPixelSize, destPixelSize, StretchedBlitNearest);
+}
+
+gl::Error Blit11::copyAndConvertImpl(const TextureHelper11 &source,
+                                     unsigned int sourceSubresource,
+                                     const gl::Box &sourceArea,
+                                     const gl::Extents &sourceSize,
+                                     const TextureHelper11 &destStaging,
+                                     const gl::Box &destArea,
+                                     const gl::Extents &destSize,
+                                     const gl::Rectangle *scissor,
+                                     size_t readOffset,
+                                     size_t writeOffset,
+                                     size_t copySize,
+                                     size_t srcPixelStride,
+                                     size_t destPixelStride,
+                                     BlitConvertFunction *convertFunction)
+{
+    ANGLE_TRY(initResources());
+
+    ID3D11Device *device               = mRenderer->getDevice();
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    TextureHelper11 sourceStaging;
+    ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, source.getFormatSet(), sourceSize,
+                                          StagingAccess::READ, device),
+                     sourceStaging);
+
+    deviceContext->CopySubresourceRegion(sourceStaging.getResource(), 0, 0, 0, 0,
+                                         source.getResource(), sourceSubresource, nullptr);
+
+    D3D11_MAPPED_SUBRESOURCE sourceMapping;
+    HRESULT result =
+        deviceContext->Map(sourceStaging.getResource(), 0, D3D11_MAP_READ, 0, &sourceMapping);
+    if (FAILED(result))
+    {
+        return gl::OutOfMemory()
+               << "Failed to map internal source staging texture for depth stencil blit, "
+               << result;
+    }
+
+    D3D11_MAPPED_SUBRESOURCE destMapping;
+    result = deviceContext->Map(destStaging.getResource(), 0, D3D11_MAP_WRITE, 0, &destMapping);
+    if (FAILED(result))
+    {
+        deviceContext->Unmap(sourceStaging.getResource(), 0);
+        return gl::OutOfMemory()
+               << "Failed to map internal destination staging texture for depth stencil blit, "
+               << result;
+    }
+
+    // Clip dest area to the destination size
+    gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height);
+
+    // Clip dest area to the scissor
+    if (scissor)
+    {
+        gl::ClipRectangle(clipRect, *scissor, &clipRect);
+    }
+
+    convertFunction(sourceArea, destArea, clipRect, sourceSize, sourceMapping.RowPitch,
+                    destMapping.RowPitch, readOffset, writeOffset, copySize, srcPixelStride,
+                    destPixelStride, static_cast<const uint8_t *>(sourceMapping.pData),
+                    static_cast<uint8_t *>(destMapping.pData));
+
+    deviceContext->Unmap(sourceStaging.getResource(), 0);
+    deviceContext->Unmap(destStaging.getResource(), 0);
+
+    return gl::NoError();
+}
+
+gl::Error Blit11::copyAndConvert(const TextureHelper11 &source,
+                                 unsigned int sourceSubresource,
+                                 const gl::Box &sourceArea,
+                                 const gl::Extents &sourceSize,
+                                 const TextureHelper11 &dest,
+                                 unsigned int destSubresource,
+                                 const gl::Box &destArea,
+                                 const gl::Extents &destSize,
+                                 const gl::Rectangle *scissor,
+                                 size_t readOffset,
+                                 size_t writeOffset,
+                                 size_t copySize,
+                                 size_t srcPixelStride,
+                                 size_t destPixelStride,
+                                 BlitConvertFunction *convertFunction)
+{
+    ANGLE_TRY(initResources());
+
+    ID3D11Device *device               = mRenderer->getDevice();
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    // HACK: Create the destination staging buffer as a read/write texture so
+    // ID3D11DevicContext::UpdateSubresource can be called
+    //       using it's mapped data as a source
+    TextureHelper11 destStaging;
+    ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, dest.getFormatSet(), destSize,
+                                          StagingAccess::READ_WRITE, device),
+                     destStaging);
+
+    deviceContext->CopySubresourceRegion(destStaging.getResource(), 0, 0, 0, 0, dest.getResource(),
+                                         destSubresource, nullptr);
+
+    copyAndConvertImpl(source, sourceSubresource, sourceArea, sourceSize, destStaging, destArea,
+                       destSize, scissor, readOffset, writeOffset, copySize, srcPixelStride,
+                       destPixelStride, convertFunction);
+
+    // Work around timeouts/TDRs in older NVIDIA drivers.
+    if (mRenderer->getWorkarounds().depthStencilBlitExtraCopy)
+    {
+        D3D11_MAPPED_SUBRESOURCE mapped;
+        deviceContext->Map(destStaging.getResource(), 0, D3D11_MAP_READ, 0, &mapped);
+        deviceContext->UpdateSubresource(dest.getResource(), destSubresource, nullptr, mapped.pData,
+                                         mapped.RowPitch, mapped.DepthPitch);
+        deviceContext->Unmap(destStaging.getResource(), 0);
+    }
+    else
+    {
+        deviceContext->CopySubresourceRegion(dest.getResource(), destSubresource, 0, 0, 0,
+                                             destStaging.getResource(), 0, nullptr);
+    }
+
+    return gl::NoError();
+}
+
+void Blit11::addBlitShaderToMap(BlitShaderType blitShaderType,
+                                ShaderDimension dimension,
+                                ID3D11PixelShader *ps)
+{
+    ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end());
+    ASSERT(ps);
+
+    Shader shader;
+    shader.dimension   = dimension;
+    shader.pixelShader = ps;
+
+    mBlitShaderMap[blitShaderType] = shader;
+}
+
+void Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType,
+                                   ShaderDimension dimension,
+                                   ID3D11PixelShader *ps)
+{
+    ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end());
+    ASSERT(ps);
+
+    Shader shader;
+    shader.dimension   = dimension;
+    shader.pixelShader = ps;
+
+    mSwizzleShaderMap[swizzleShaderType] = shader;
+}
+
+void Blit11::clearShaderMap()
+{
+    for (auto &blitShader : mBlitShaderMap)
+    {
+        SafeRelease(blitShader.second.pixelShader);
+    }
+    mBlitShaderMap.clear();
+
+    for (auto &swizzleShader : mSwizzleShaderMap)
+    {
+        SafeRelease(swizzleShader.second.pixelShader);
+    }
+    mSwizzleShaderMap.clear();
+}
+
+gl::Error Blit11::getBlitShader(GLenum destFormat,
+                                bool isSigned,
+                                bool unpackPremultiplyAlpha,
+                                bool unpackUnmultiplyAlpha,
+                                ShaderDimension dimension,
+                                const Shader **shader)
+{
+    BlitShaderType blitShaderType = GetBlitShaderType(destFormat, isSigned, unpackPremultiplyAlpha,
+                                                      unpackUnmultiplyAlpha, dimension);
+
+    if (blitShaderType == BLITSHADER_INVALID)
+    {
+        return gl::InternalError() << "Internal blit shader type mismatch";
+    }
+
+    auto blitShaderIt = mBlitShaderMap.find(blitShaderType);
+    if (blitShaderIt != mBlitShaderMap.end())
+    {
+        *shader = &blitShaderIt->second;
+        return gl::NoError();
+    }
+
+    ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable());
+
+    ID3D11Device *device = mRenderer->getDevice();
+
+    switch (blitShaderType)
+    {
+        case BLITSHADER_2D_RGBAF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader"));
+            break;
+        case BLITSHADER_2D_RGBAF_PREMULTIPLY:
+            addBlitShaderToMap(blitShaderType, SHADER_2D,
+                               d3d11::CompilePS(device, g_PS_PassthroughRGBAPremultiply2D,
+                                                "Blit11 2D RGBA premultiply pixel shader"));
+            break;
+        case BLITSHADER_2D_RGBAF_UNMULTIPLY:
+            addBlitShaderToMap(blitShaderType, SHADER_2D,
+                               d3d11::CompilePS(device, g_PS_PassthroughRGBAUnmultiply2D,
+                                                "Blit11 2D RGBA unmultiply pixel shader"));
+            break;
+        case BLITSHADER_2D_BGRAF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader"));
+            break;
+        case BLITSHADER_2D_BGRAF_PREMULTIPLY:
+            addBlitShaderToMap(blitShaderType, SHADER_2D,
+                               d3d11::CompilePS(device, g_PS_PassthroughRGBAPremultiply2D,
+                                                "Blit11 2D BGRA premultiply pixel shader"));
+            break;
+        case BLITSHADER_2D_BGRAF_UNMULTIPLY:
+            addBlitShaderToMap(blitShaderType, SHADER_2D,
+                               d3d11::CompilePS(device, g_PS_PassthroughRGBAUnmultiply2D,
+                                                "Blit11 2D BGRA unmultiply pixel shader"));
+            break;
+        case BLITSHADER_2D_RGBF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader"));
+            break;
+        case BLITSHADER_2D_RGBF_PREMULTIPLY:
+            addBlitShaderToMap(blitShaderType, SHADER_2D,
+                               d3d11::CompilePS(device, g_PS_PassthroughRGBPremultiply2D,
+                                                "Blit11 2D RGB premultiply pixel shader"));
+            break;
+        case BLITSHADER_2D_RGBF_UNMULTIPLY:
+            addBlitShaderToMap(blitShaderType, SHADER_2D,
+                               d3d11::CompilePS(device, g_PS_PassthroughRGBUnmultiply2D,
+                                                "Blit11 2D RGB unmultiply pixel shader"));
+            break;
+        case BLITSHADER_2D_RGF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader"));
+            break;
+        case BLITSHADER_2D_RF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader"));
+            break;
+        case BLITSHADER_2D_ALPHA:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader"));
+            break;
+        case BLITSHADER_2D_LUMA:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader"));
+            break;
+        case BLITSHADER_2D_LUMAALPHA:
+            addBlitShaderToMap(blitShaderType, SHADER_2D,
+                               d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D,
+                                                "Blit11 2D luminance alpha pixel shader"));
+            break;
+        case BLITSHADER_2D_RGBAUI:
+            addBlitShaderToMap(blitShaderType, SHADER_2D,
+                               d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI,
+                                                "Blit11 2D RGBA UI pixel shader"));
+            break;
+        case BLITSHADER_2D_RGBAI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader"));
+            break;
+        case BLITSHADER_2D_RGBUI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader"));
+            break;
+        case BLITSHADER_2D_RGBI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader"));
+            break;
+        case BLITSHADER_2D_RGUI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader"));
+            break;
+        case BLITSHADER_2D_RGI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader"));
+            break;
+        case BLITSHADER_2D_RUI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader"));
+            break;
+        case BLITSHADER_2D_RI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader"));
+            break;
+        case BLITSHADER_3D_RGBAF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader"));
+            break;
+        case BLITSHADER_3D_RGBAUI:
+            addBlitShaderToMap(blitShaderType, SHADER_3D,
+                               d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI,
+                                                "Blit11 3D UI RGBA pixel shader"));
+            break;
+        case BLITSHADER_3D_RGBAI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader"));
+            break;
+        case BLITSHADER_3D_BGRAF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader"));
+            break;
+        case BLITSHADER_3D_RGBF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader"));
+            break;
+        case BLITSHADER_3D_RGBUI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader"));
+            break;
+        case BLITSHADER_3D_RGBI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader"));
+            break;
+        case BLITSHADER_3D_RGF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader"));
+            break;
+        case BLITSHADER_3D_RGUI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader"));
+            break;
+        case BLITSHADER_3D_RGI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader"));
+            break;
+        case BLITSHADER_3D_RF:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader"));
+            break;
+        case BLITSHADER_3D_RUI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader"));
+            break;
+        case BLITSHADER_3D_RI:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader"));
+            break;
+        case BLITSHADER_3D_ALPHA:
+            addBlitShaderToMap(
+                blitShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader"));
+            break;
+        case BLITSHADER_3D_LUMA:
+            addBlitShaderToMap(blitShaderType, SHADER_3D,
+                               d3d11::CompilePS(device, g_PS_PassthroughLum3D,
+                                                "Blit11 3D luminance pixel shader"));
+            break;
+        case BLITSHADER_3D_LUMAALPHA:
+            addBlitShaderToMap(blitShaderType, SHADER_3D,
+                               d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D,
+                                                "Blit11 3D luminance alpha pixel shader"));
+            break;
+        default:
+            UNREACHABLE();
+            return gl::InternalError() << "Internal error";
+    }
+
+    blitShaderIt = mBlitShaderMap.find(blitShaderType);
+    ASSERT(blitShaderIt != mBlitShaderMap.end());
+    *shader = &blitShaderIt->second;
+    return gl::NoError();
+}
+
+gl::Error Blit11::getSwizzleShader(GLenum type,
+                                   D3D11_SRV_DIMENSION viewDimension,
+                                   const Shader **shader)
+{
+    SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension);
+
+    if (swizzleShaderType == SWIZZLESHADER_INVALID)
+    {
+        return gl::InternalError() << "Swizzle shader type not found";
+    }
+
+    auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
+    if (swizzleShaderIt != mSwizzleShaderMap.end())
+    {
+        *shader = &swizzleShaderIt->second;
+        return gl::NoError();
+    }
+
+    // Swizzling shaders (OpenGL ES 3+)
+    ASSERT(mRenderer->isES3Capable());
+
+    ID3D11Device *device = mRenderer->getDevice();
+
+    switch (swizzleShaderType)
+    {
+        case SWIZZLESHADER_2D_FLOAT:
+            addSwizzleShaderToMap(
+                swizzleShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_2D_UINT:
+            addSwizzleShaderToMap(
+                swizzleShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_2D_INT:
+            addSwizzleShaderToMap(
+                swizzleShaderType, SHADER_2D,
+                d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_CUBE_FLOAT:
+            addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+                                  d3d11::CompilePS(device, g_PS_SwizzleF2DArray,
+                                                   "Blit11 2D Cube F swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_CUBE_UINT:
+            addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+                                  d3d11::CompilePS(device, g_PS_SwizzleUI2DArray,
+                                                   "Blit11 2D Cube UI swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_CUBE_INT:
+            addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+                                  d3d11::CompilePS(device, g_PS_SwizzleI2DArray,
+                                                   "Blit11 2D Cube I swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_3D_FLOAT:
+            addSwizzleShaderToMap(
+                swizzleShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_3D_UINT:
+            addSwizzleShaderToMap(
+                swizzleShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_3D_INT:
+            addSwizzleShaderToMap(
+                swizzleShaderType, SHADER_3D,
+                d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_ARRAY_FLOAT:
+            addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+                                  d3d11::CompilePS(device, g_PS_SwizzleF2DArray,
+                                                   "Blit11 2D Array F swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_ARRAY_UINT:
+            addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+                                  d3d11::CompilePS(device, g_PS_SwizzleUI2DArray,
+                                                   "Blit11 2D Array UI swizzle pixel shader"));
+            break;
+        case SWIZZLESHADER_ARRAY_INT:
+            addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+                                  d3d11::CompilePS(device, g_PS_SwizzleI2DArray,
+                                                   "Blit11 2D Array I swizzle pixel shader"));
+            break;
+        default:
+            UNREACHABLE();
+            return gl::InternalError() << "Internal error";
+    }
+
+    swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
+    ASSERT(swizzleShaderIt != mSwizzleShaderMap.end());
+    *shader = &swizzleShaderIt->second;
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureHelper11> Blit11::resolveDepth(RenderTarget11 *depth)
+{
+    // Multisampled depth stencil SRVs are not available in feature level 10.0
+    ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
+
+    const auto &extents          = depth->getExtents();
+    ID3D11Device *device         = mRenderer->getDevice();
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+    ANGLE_TRY(initResolveDepthOnly(depth->getFormatSet(), extents));
+
+    // Notify the Renderer that all state should be invalidated.
+    mRenderer->markAllStateDirty();
+
+    // Apply the necessary state changes to the D3D11 immediate device context.
+    context->IASetInputLayout(nullptr);
+    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+    context->VSSetShader(mResolveDepthStencilVS.resolve(device), nullptr, 0);
+    context->GSSetShader(nullptr, nullptr, 0);
+    context->RSSetState(nullptr);
+    context->OMSetDepthStencilState(mDepthStencilState.Get(), 0xFFFFFFFF);
+    context->OMSetRenderTargets(0, nullptr, mResolvedDepthDSView.Get());
+    context->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+
+    // Set the viewport
+    D3D11_VIEWPORT viewport;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    viewport.Width    = static_cast<FLOAT>(extents.width);
+    viewport.Height   = static_cast<FLOAT>(extents.height);
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 1.0f;
+    context->RSSetViewports(1, &viewport);
+
+    ID3D11ShaderResourceView *pixelViews[] = {depth->getShaderResourceView()};
+
+    context->PSSetShaderResources(0, 1, pixelViews);
+
+    context->PSSetShader(mResolveDepthPS.resolve(device), nullptr, 0);
+
+    // Trigger the blit on the GPU.
+    context->Draw(6, 0);
+
+    return TextureHelper11::MakeAndReference(mResolvedDepth.getResource(),
+                                             mResolvedDepth.getFormatSet());
+}
+
+gl::Error Blit11::initResolveDepthOnly(const d3d11::Format &format, const gl::Extents &extents)
+{
+    if (mResolvedDepth.valid() && extents == mResolvedDepth.getExtents() &&
+        format.texFormat == mResolvedDepth.getFormat())
+    {
+        return gl::NoError();
+    }
+
+    ID3D11Device *device = mRenderer->getDevice();
+
+    D3D11_TEXTURE2D_DESC textureDesc;
+    textureDesc.Width              = extents.width;
+    textureDesc.Height             = extents.height;
+    textureDesc.MipLevels          = 1;
+    textureDesc.ArraySize          = 1;
+    textureDesc.Format             = format.texFormat;
+    textureDesc.SampleDesc.Count   = 1;
+    textureDesc.SampleDesc.Quality = 0;
+    textureDesc.Usage              = D3D11_USAGE_DEFAULT;
+    textureDesc.BindFlags          = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
+    textureDesc.CPUAccessFlags     = 0;
+    textureDesc.MiscFlags          = 0;
+
+    ID3D11Texture2D *resolvedDepth = nullptr;
+    HRESULT hr                     = device->CreateTexture2D(&textureDesc, nullptr, &resolvedDepth);
+    if (FAILED(hr))
+    {
+        return gl::OutOfMemory() << "Failed to allocate resolved depth texture, " << hr;
+    }
+    d3d11::SetDebugName(resolvedDepth, "Blit11::mResolvedDepth");
+
+    mResolvedDepth = TextureHelper11::MakeAndPossess2D(resolvedDepth, format);
+
+    D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+    dsvDesc.Flags              = 0;
+    dsvDesc.Format             = format.dsvFormat;
+    dsvDesc.Texture2D.MipSlice = 0;
+    dsvDesc.ViewDimension      = D3D11_DSV_DIMENSION_TEXTURE2D;
+
+    hr = device->CreateDepthStencilView(mResolvedDepth.getResource(), &dsvDesc,
+                                        mResolvedDepthDSView.ReleaseAndGetAddressOf());
+    if (FAILED(hr))
+    {
+        return gl::OutOfMemory() << "Failed to allocate Blit11::mResolvedDepthDSView, " << hr;
+    }
+    d3d11::SetDebugName(mResolvedDepthDSView, "Blit11::mResolvedDepthDSView");
+
+    // Possibly D3D11 bug or undefined behaviour: Clear the DSV so that our first render
+    // works as expected. Otherwise the results of the first use seem to be incorrect.
+    auto context = mRenderer->getDeviceContext();
+    context->ClearDepthStencilView(mResolvedDepthDSView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
+
+    return gl::NoError();
+}
+
+gl::Error Blit11::initResolveDepthStencil(const gl::Extents &extents)
+{
+    // Check if we need to recreate depth stencil view
+    if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents())
+    {
+        ASSERT(mResolvedDepthStencil.getFormat() == DXGI_FORMAT_R32G32_FLOAT);
+        return gl::NoError();
+    }
+
+    if (mResolvedDepthStencil.valid())
+    {
+        releaseResolveDepthStencilResources();
+    }
+
+    const auto &formatSet = d3d11::Format::Get(GL_RG32F, mRenderer->getRenderer11DeviceCaps());
+
+    D3D11_TEXTURE2D_DESC textureDesc;
+    textureDesc.Width              = extents.width;
+    textureDesc.Height             = extents.height;
+    textureDesc.MipLevels          = 1;
+    textureDesc.ArraySize          = 1;
+    textureDesc.Format             = formatSet.texFormat;
+    textureDesc.SampleDesc.Count   = 1;
+    textureDesc.SampleDesc.Quality = 0;
+    textureDesc.Usage              = D3D11_USAGE_DEFAULT;
+    textureDesc.BindFlags          = D3D11_BIND_RENDER_TARGET;
+    textureDesc.CPUAccessFlags     = 0;
+    textureDesc.MiscFlags          = 0;
+
+    ID3D11Device *device = mRenderer->getDevice();
+
+    ID3D11Texture2D *resolvedDepthStencil = nullptr;
+    HRESULT hr = device->CreateTexture2D(&textureDesc, nullptr, &resolvedDepthStencil);
+    if (FAILED(hr))
+    {
+        return gl::OutOfMemory() << "Failed to allocate resolved depth stencil texture, " << hr;
+    }
+    d3d11::SetDebugName(resolvedDepthStencil, "Blit11::mResolvedDepthStencil");
+
+    ANGLE_TRY(
+        mRenderer->allocateResourceNoDesc(resolvedDepthStencil, &mResolvedDepthStencilRTView));
+    mResolvedDepthStencilRTView.setDebugName("Blit11::mResolvedDepthStencilRTView");
+
+    mResolvedDepthStencil = TextureHelper11::MakeAndPossess2D(resolvedDepthStencil, formatSet);
+
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureHelper11> Blit11::resolveStencil(RenderTarget11 *depthStencil,
+                                                          bool alsoDepth)
+{
+    // Multisampled depth stencil SRVs are not available in feature level 10.0
+    ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
+
+    const auto &extents = depthStencil->getExtents();
+
+    ANGLE_TRY(initResolveDepthStencil(extents));
+
+    ID3D11Device *device         = mRenderer->getDevice();
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+    ID3D11Resource *stencilResource = depthStencil->getTexture();
+
+    // Check if we need to re-create the stencil SRV.
+    if (mStencilSRV)
+    {
+        ID3D11Resource *priorResource = nullptr;
+        mStencilSRV->GetResource(&priorResource);
+
+        if (stencilResource != priorResource)
+        {
+            mStencilSRV.Reset();
+        }
+
+        SafeRelease(priorResource);
+    }
+
+    if (mStencilSRV == nullptr)
+    {
+        D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc;
+        srViewDesc.Format        = GetStencilSRVFormat(depthStencil->getFormatSet());
+        srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+
+        HRESULT hr = device->CreateShaderResourceView(stencilResource, &srViewDesc,
+                                                      mStencilSRV.GetAddressOf());
+        if (FAILED(hr))
+        {
+            return gl::OutOfMemory() << "Error creating Blit11 stencil SRV, " << hr;
+        }
+        d3d11::SetDebugName(mStencilSRV, "Blit11::mStencilSRV");
+    }
+
+    // Notify the Renderer that all state should be invalidated.
+    mRenderer->markAllStateDirty();
+
+    ID3D11RenderTargetView *rtvs[] = {mResolvedDepthStencilRTView.get()};
+
+    // Apply the necessary state changes to the D3D11 immediate device context.
+    context->IASetInputLayout(nullptr);
+    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+    context->VSSetShader(mResolveDepthStencilVS.resolve(device), nullptr, 0);
+    context->GSSetShader(nullptr, nullptr, 0);
+    context->RSSetState(nullptr);
+    context->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
+    context->OMSetRenderTargets(1, rtvs, nullptr);
+    context->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+
+    // Set the viewport
+    D3D11_VIEWPORT viewport;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    viewport.Width    = static_cast<FLOAT>(extents.width);
+    viewport.Height   = static_cast<FLOAT>(extents.height);
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 1.0f;
+    context->RSSetViewports(1, &viewport);
+
+    ID3D11ShaderResourceView *pixelViews[] = {
+        depthStencil->getShaderResourceView(), mStencilSRV.Get(),
+    };
+
+    context->PSSetShaderResources(0, 2, pixelViews);
+
+    // Resolving the depth buffer works by sampling the depth in the shader using a SRV, then
+    // writing to the resolved depth buffer using SV_Depth. We can't use this method for stencil
+    // because SV_StencilRef isn't supported until HLSL 5.1/D3D11.3.
+    if (alsoDepth)
+    {
+        context->PSSetShader(mResolveDepthStencilPS.resolve(device), nullptr, 0);
+    }
+    else
+    {
+        context->PSSetShader(mResolveStencilPS.resolve(device), nullptr, 0);
+    }
+
+    // Trigger the blit on the GPU.
+    context->Draw(6, 0);
+
+    gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
+
+    TextureHelper11 dest;
+    ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, depthStencil->getFormatSet(), extents,
+                                          StagingAccess::READ_WRITE, device),
+                     dest);
+
+    const auto &copyFunction = GetCopyDepthStencilFunction(depthStencil->getInternalFormat());
+    const auto &dsFormatSet  = depthStencil->getFormatSet();
+    const auto &dsDxgiInfo   = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
+
+    ANGLE_TRY(copyAndConvertImpl(mResolvedDepthStencil, 0, copyBox, extents, dest, copyBox, extents,
+                                 nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes, copyFunction));
+
+    // Return the resolved depth texture, which the caller must Release.
+    return dest;
+}
+
+void Blit11::releaseResolveDepthStencilResources()
+{
+    mStencilSRV.Reset();
+    mResolvedDepthStencilRTView.reset();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
new file mode 100644
index 0000000..d8976eb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
@@ -0,0 +1,298 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit11.cpp: Texture copy utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include <map>
+
+namespace rx
+{
+class Renderer11;
+
+class Blit11 : angle::NonCopyable
+{
+  public:
+    explicit Blit11(Renderer11 *renderer);
+    ~Blit11();
+
+    gl::Error swizzleTexture(ID3D11ShaderResourceView *source,
+                             const d3d11::RenderTargetView &dest,
+                             const gl::Extents &size,
+                             const gl::SwizzleState &swizzleTarget);
+
+    gl::Error copyTexture(ID3D11ShaderResourceView *source,
+                          const gl::Box &sourceArea,
+                          const gl::Extents &sourceSize,
+                          const d3d11::RenderTargetView &dest,
+                          const gl::Box &destArea,
+                          const gl::Extents &destSize,
+                          const gl::Rectangle *scissor,
+                          GLenum destFormat,
+                          GLenum filter,
+                          bool maskOffAlpha,
+                          bool unpackPremultiplyAlpha,
+                          bool unpackUnmultiplyAlpha);
+
+    gl::Error copyStencil(const TextureHelper11 &source,
+                          unsigned int sourceSubresource,
+                          const gl::Box &sourceArea,
+                          const gl::Extents &sourceSize,
+                          const TextureHelper11 &dest,
+                          unsigned int destSubresource,
+                          const gl::Box &destArea,
+                          const gl::Extents &destSize,
+                          const gl::Rectangle *scissor);
+
+    gl::Error copyDepth(ID3D11ShaderResourceView *source,
+                        const gl::Box &sourceArea,
+                        const gl::Extents &sourceSize,
+                        ID3D11DepthStencilView *dest,
+                        const gl::Box &destArea,
+                        const gl::Extents &destSize,
+                        const gl::Rectangle *scissor);
+
+    gl::Error copyDepthStencil(const TextureHelper11 &source,
+                               unsigned int sourceSubresource,
+                               const gl::Box &sourceArea,
+                               const gl::Extents &sourceSize,
+                               const TextureHelper11 &dest,
+                               unsigned int destSubresource,
+                               const gl::Box &destArea,
+                               const gl::Extents &destSize,
+                               const gl::Rectangle *scissor);
+
+    gl::ErrorOrResult<TextureHelper11> resolveDepth(RenderTarget11 *depth);
+
+    gl::ErrorOrResult<TextureHelper11> resolveStencil(RenderTarget11 *depthStencil, bool alsoDepth);
+
+    using BlitConvertFunction = void(const gl::Box &sourceArea,
+                                     const gl::Box &destArea,
+                                     const gl::Rectangle &clipRect,
+                                     const gl::Extents &sourceSize,
+                                     unsigned int sourceRowPitch,
+                                     unsigned int destRowPitch,
+                                     ptrdiff_t readOffset,
+                                     ptrdiff_t writeOffset,
+                                     size_t copySize,
+                                     size_t srcPixelStride,
+                                     size_t destPixelStride,
+                                     const uint8_t *sourceData,
+                                     uint8_t *destData);
+
+  private:
+    enum BlitShaderType
+    {
+        BLITSHADER_INVALID,
+        BLITSHADER_2D_RGBAF,
+        BLITSHADER_2D_RGBAF_PREMULTIPLY,
+        BLITSHADER_2D_RGBAF_UNMULTIPLY,
+        BLITSHADER_2D_BGRAF,
+        BLITSHADER_2D_BGRAF_PREMULTIPLY,
+        BLITSHADER_2D_BGRAF_UNMULTIPLY,
+        BLITSHADER_2D_RGBF,
+        BLITSHADER_2D_RGBF_PREMULTIPLY,
+        BLITSHADER_2D_RGBF_UNMULTIPLY,
+        BLITSHADER_2D_RGF,
+        BLITSHADER_2D_RF,
+        BLITSHADER_2D_ALPHA,
+        BLITSHADER_2D_LUMA,
+        BLITSHADER_2D_LUMAALPHA,
+        BLITSHADER_2D_RGBAUI,
+        BLITSHADER_2D_RGBAI,
+        BLITSHADER_2D_RGBUI,
+        BLITSHADER_2D_RGBI,
+        BLITSHADER_2D_RGUI,
+        BLITSHADER_2D_RGI,
+        BLITSHADER_2D_RUI,
+        BLITSHADER_2D_RI,
+        BLITSHADER_3D_RGBAF,
+        BLITSHADER_3D_RGBAUI,
+        BLITSHADER_3D_RGBAI,
+        BLITSHADER_3D_BGRAF,
+        BLITSHADER_3D_RGBF,
+        BLITSHADER_3D_RGBUI,
+        BLITSHADER_3D_RGBI,
+        BLITSHADER_3D_RGF,
+        BLITSHADER_3D_RGUI,
+        BLITSHADER_3D_RGI,
+        BLITSHADER_3D_RF,
+        BLITSHADER_3D_RUI,
+        BLITSHADER_3D_RI,
+        BLITSHADER_3D_ALPHA,
+        BLITSHADER_3D_LUMA,
+        BLITSHADER_3D_LUMAALPHA,
+    };
+
+    enum SwizzleShaderType
+    {
+        SWIZZLESHADER_INVALID,
+        SWIZZLESHADER_2D_FLOAT,
+        SWIZZLESHADER_2D_UINT,
+        SWIZZLESHADER_2D_INT,
+        SWIZZLESHADER_CUBE_FLOAT,
+        SWIZZLESHADER_CUBE_UINT,
+        SWIZZLESHADER_CUBE_INT,
+        SWIZZLESHADER_3D_FLOAT,
+        SWIZZLESHADER_3D_UINT,
+        SWIZZLESHADER_3D_INT,
+        SWIZZLESHADER_ARRAY_FLOAT,
+        SWIZZLESHADER_ARRAY_UINT,
+        SWIZZLESHADER_ARRAY_INT,
+    };
+
+    typedef void (*WriteVertexFunction)(const gl::Box &sourceArea,
+                                        const gl::Extents &sourceSize,
+                                        const gl::Box &destArea,
+                                        const gl::Extents &destSize,
+                                        void *outVertices,
+                                        unsigned int *outStride,
+                                        unsigned int *outVertexCount,
+                                        D3D11_PRIMITIVE_TOPOLOGY *outTopology);
+
+    enum ShaderDimension
+    {
+        SHADER_2D,
+        SHADER_3D,
+    };
+
+    struct Shader
+    {
+        ShaderDimension dimension;
+        ID3D11PixelShader *pixelShader;
+    };
+
+    struct ShaderSupport
+    {
+        ID3D11InputLayout *inputLayout;
+        ID3D11VertexShader *vertexShader;
+        ID3D11GeometryShader *geometryShader;
+        WriteVertexFunction vertexWriteFunction;
+    };
+
+    gl::Error initResources();
+
+    ShaderSupport getShaderSupport(const Shader &shader);
+
+    static BlitShaderType GetBlitShaderType(GLenum destinationFormat,
+                                            bool isSigned,
+                                            bool unpackPremultiplyAlpha,
+                                            bool unpackUnmultiplyAlpha,
+                                            ShaderDimension dimension);
+    static SwizzleShaderType GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality);
+
+    gl::Error copyDepthStencilImpl(const TextureHelper11 &source,
+                                   unsigned int sourceSubresource,
+                                   const gl::Box &sourceArea,
+                                   const gl::Extents &sourceSize,
+                                   const TextureHelper11 &dest,
+                                   unsigned int destSubresource,
+                                   const gl::Box &destArea,
+                                   const gl::Extents &destSize,
+                                   const gl::Rectangle *scissor,
+                                   bool stencilOnly);
+
+    gl::Error copyAndConvertImpl(const TextureHelper11 &source,
+                                 unsigned int sourceSubresource,
+                                 const gl::Box &sourceArea,
+                                 const gl::Extents &sourceSize,
+                                 const TextureHelper11 &destStaging,
+                                 const gl::Box &destArea,
+                                 const gl::Extents &destSize,
+                                 const gl::Rectangle *scissor,
+                                 size_t readOffset,
+                                 size_t writeOffset,
+                                 size_t copySize,
+                                 size_t srcPixelStride,
+                                 size_t destPixelStride,
+                                 BlitConvertFunction *convertFunction);
+
+    gl::Error copyAndConvert(const TextureHelper11 &source,
+                             unsigned int sourceSubresource,
+                             const gl::Box &sourceArea,
+                             const gl::Extents &sourceSize,
+                             const TextureHelper11 &dest,
+                             unsigned int destSubresource,
+                             const gl::Box &destArea,
+                             const gl::Extents &destSize,
+                             const gl::Rectangle *scissor,
+                             size_t readOffset,
+                             size_t writeOffset,
+                             size_t copySize,
+                             size_t srcPixelStride,
+                             size_t destPixelStride,
+                             BlitConvertFunction *convertFunction);
+
+    void addBlitShaderToMap(BlitShaderType blitShaderType,
+                            ShaderDimension dimension,
+                            ID3D11PixelShader *ps);
+
+    gl::Error getBlitShader(GLenum destFormat,
+                            bool isSigned,
+                            bool unpackPremultiplyAlpha,
+                            bool unpackUnmultiplyAlpha,
+                            ShaderDimension dimension,
+                            const Shader **shaderOut);
+    gl::Error getSwizzleShader(GLenum type,
+                               D3D11_SRV_DIMENSION viewDimension,
+                               const Shader **shaderOut);
+
+    void addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType,
+                               ShaderDimension dimension,
+                               ID3D11PixelShader *ps);
+
+    void clearShaderMap();
+    void releaseResolveDepthStencilResources();
+    gl::Error initResolveDepthOnly(const d3d11::Format &format, const gl::Extents &extents);
+    gl::Error initResolveDepthStencil(const gl::Extents &extents);
+
+    Renderer11 *mRenderer;
+
+    std::map<BlitShaderType, Shader> mBlitShaderMap;
+    std::map<SwizzleShaderType, Shader> mSwizzleShaderMap;
+
+    bool mResourcesInitialized;
+    angle::ComPtr<ID3D11Buffer> mVertexBuffer;
+    angle::ComPtr<ID3D11SamplerState> mPointSampler;
+    angle::ComPtr<ID3D11SamplerState> mLinearSampler;
+    angle::ComPtr<ID3D11RasterizerState> mScissorEnabledRasterizerState;
+    angle::ComPtr<ID3D11RasterizerState> mScissorDisabledRasterizerState;
+    angle::ComPtr<ID3D11DepthStencilState> mDepthStencilState;
+
+    d3d11::LazyInputLayout mQuad2DIL;
+    d3d11::LazyShader<ID3D11VertexShader> mQuad2DVS;
+    d3d11::LazyShader<ID3D11PixelShader> mDepthPS;
+
+    d3d11::LazyInputLayout mQuad3DIL;
+    d3d11::LazyShader<ID3D11VertexShader> mQuad3DVS;
+    d3d11::LazyShader<ID3D11GeometryShader> mQuad3DGS;
+
+    d3d11::LazyBlendState mAlphaMaskBlendState;
+
+    angle::ComPtr<ID3D11Buffer> mSwizzleCB;
+
+    d3d11::LazyShader<ID3D11VertexShader> mResolveDepthStencilVS;
+    d3d11::LazyShader<ID3D11PixelShader> mResolveDepthPS;
+    d3d11::LazyShader<ID3D11PixelShader> mResolveDepthStencilPS;
+    d3d11::LazyShader<ID3D11PixelShader> mResolveStencilPS;
+    angle::ComPtr<ID3D11ShaderResourceView> mStencilSRV;
+    TextureHelper11 mResolvedDepthStencil;
+    d3d11::RenderTargetView mResolvedDepthStencilRTView;
+    TextureHelper11 mResolvedDepth;
+    angle::ComPtr<ID3D11DepthStencilView> mResolvedDepthDSView;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
new file mode 100644
index 0000000..c919ab2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -0,0 +1,1575 @@
+//
+// 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.
+//
+
+// Buffer11.cpp Defines the Buffer11 class.
+
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+
+#include <memory>
+
+#include "common/MemoryBuffer.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+
+namespace
+{
+
+template <typename T>
+GLuint ReadIndexValueFromIndices(const uint8_t *data, size_t index)
+{
+    return reinterpret_cast<const T *>(data)[index];
+}
+typedef GLuint (*ReadIndexValueFunction)(const uint8_t *data, size_t index);
+
+enum class CopyResult
+{
+    RECREATED,
+    NOT_RECREATED,
+};
+
+void CalculateConstantBufferParams(GLintptr offset,
+                                   GLsizeiptr size,
+                                   UINT *outFirstConstant,
+                                   UINT *outNumConstants)
+{
+    // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange).
+    ASSERT(offset % 256 == 0);
+
+    // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must
+    // be a multiple of 16 constants.
+    *outFirstConstant = static_cast<UINT>(offset / 16);
+
+    // The GL size is not required to be aligned to a 256 bytes boundary.
+    // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes.
+    *outNumConstants = static_cast<UINT>(rx::roundUp(size, static_cast<GLsizeiptr>(256)) / 16);
+
+    // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size
+    // of the buffer. This behaviour is explictly allowed according to the documentation on
+    // ID3D11DeviceContext1::PSSetConstantBuffers1
+    // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
+}
+
+}  // anonymous namespace
+
+namespace gl_d3d11
+{
+
+D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access)
+{
+    bool readBit  = ((access & GL_MAP_READ_BIT) != 0);
+    bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0);
+
+    ASSERT(readBit || writeBit);
+
+    // Note : we ignore the discard bit, because in D3D11, staging buffers
+    //  don't accept the map-discard flag (discard only works for DYNAMIC usage)
+
+    if (readBit && !writeBit)
+    {
+        return D3D11_MAP_READ;
+    }
+    else if (writeBit && !readBit)
+    {
+        // Special case for uniform storage - we only allow full buffer updates.
+        return usage == BUFFER_USAGE_UNIFORM ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE;
+    }
+    else if (writeBit && readBit)
+    {
+        return D3D11_MAP_READ_WRITE;
+    }
+    else
+    {
+        UNREACHABLE();
+        return D3D11_MAP_READ;
+    }
+}
+}  // namespace gl_d3d11
+
+// Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points
+// - vertex/transform feedback buffers
+// - index buffers
+// - pixel unpack buffers
+// - uniform buffers
+class Buffer11::BufferStorage : angle::NonCopyable
+{
+  public:
+    virtual ~BufferStorage() {}
+
+    DataRevision getDataRevision() const { return mRevision; }
+    BufferUsage getUsage() const { return mUsage; }
+    size_t getSize() const { return mBufferSize; }
+    void setDataRevision(DataRevision rev) { mRevision = rev; }
+
+    virtual bool isMappable(GLbitfield access) const = 0;
+
+    virtual gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+                                                          size_t sourceOffset,
+                                                          size_t size,
+                                                          size_t destOffset) = 0;
+    virtual gl::Error resize(size_t size, bool preserveData) = 0;
+
+    virtual gl::Error map(size_t offset,
+                          size_t length,
+                          GLbitfield access,
+                          uint8_t **mapPointerOut) = 0;
+    virtual void unmap()                           = 0;
+
+    gl::Error setData(const uint8_t *data, size_t offset, size_t size);
+
+  protected:
+    BufferStorage(Renderer11 *renderer, BufferUsage usage);
+
+    Renderer11 *mRenderer;
+    DataRevision mRevision;
+    const BufferUsage mUsage;
+    size_t mBufferSize;
+};
+
+// A native buffer storage represents an underlying D3D11 buffer for a particular
+// type of storage.
+class Buffer11::NativeStorage : public Buffer11::BufferStorage
+{
+  public:
+    NativeStorage(Renderer11 *renderer,
+                  BufferUsage usage,
+                  const OnBufferDataDirtyChannel *onStorageChanged);
+    ~NativeStorage() override;
+
+    bool isMappable(GLbitfield access) const override;
+
+    ID3D11Buffer *getNativeStorage() const { return mNativeStorage; }
+    gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+                                                  size_t sourceOffset,
+                                                  size_t size,
+                                                  size_t destOffset) override;
+    gl::Error resize(size_t size, bool preserveData) override;
+
+    gl::Error map(size_t offset,
+                  size_t length,
+                  GLbitfield access,
+                  uint8_t **mapPointerOut) override;
+    void unmap() override;
+
+    gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRVForFormat(DXGI_FORMAT srvFormat);
+
+  private:
+    static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
+                               Renderer11 *renderer,
+                               BufferUsage usage,
+                               unsigned int bufferSize);
+    void clearSRVs();
+
+    ID3D11Buffer *mNativeStorage;
+    const OnBufferDataDirtyChannel *mOnStorageChanged;
+    std::map<DXGI_FORMAT, ID3D11ShaderResourceView *> mBufferResourceViews;
+};
+
+// A emulated indexed buffer storage represents an underlying D3D11 buffer for data
+// that has been expanded to match the indices list used. This storage is only
+// used for FL9_3 pointsprite rendering emulation.
+class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage
+{
+  public:
+    EmulatedIndexedStorage(Renderer11 *renderer);
+    ~EmulatedIndexedStorage() override;
+
+    bool isMappable(GLbitfield access) const override { return true; }
+
+    gl::ErrorOrResult<ID3D11Buffer *> getNativeStorage(SourceIndexData *indexInfo,
+                                                       const TranslatedAttribute &attribute,
+                                                       GLint startVertex);
+
+    gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+                                                  size_t sourceOffset,
+                                                  size_t size,
+                                                  size_t destOffset) override;
+
+    gl::Error resize(size_t size, bool preserveData) override;
+
+    gl::Error map(size_t offset,
+                  size_t length,
+                  GLbitfield access,
+                  uint8_t **mapPointerOut) override;
+    void unmap() override;
+
+  private:
+    ID3D11Buffer *mNativeStorage;              // contains expanded data for use by D3D
+    angle::MemoryBuffer mMemoryBuffer;         // original data (not expanded)
+    angle::MemoryBuffer mIndicesMemoryBuffer;  // indices data
+};
+
+// Pack storage represents internal storage for pack buffers. We implement pack buffers
+// as CPU memory, tied to a staging texture, for asynchronous texture readback.
+class Buffer11::PackStorage : public Buffer11::BufferStorage
+{
+  public:
+    explicit PackStorage(Renderer11 *renderer);
+    ~PackStorage() override;
+
+    bool isMappable(GLbitfield access) const override { return true; }
+    gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+                                                  size_t sourceOffset,
+                                                  size_t size,
+                                                  size_t destOffset) override;
+    gl::Error resize(size_t size, bool preserveData) override;
+
+    gl::Error map(size_t offset,
+                  size_t length,
+                  GLbitfield access,
+                  uint8_t **mapPointerOut) override;
+    void unmap() override;
+
+    gl::Error packPixels(const gl::FramebufferAttachment &readAttachment,
+                         const PackPixelsParams &params);
+
+  private:
+    gl::Error flushQueuedPackCommand();
+
+    TextureHelper11 mStagingTexture;
+    angle::MemoryBuffer mMemoryBuffer;
+    std::unique_ptr<PackPixelsParams> mQueuedPackCommand;
+    PackPixelsParams mPackParams;
+    bool mDataModified;
+};
+
+// System memory storage stores a CPU memory buffer with our buffer data.
+// For dynamic data, it's much faster to update the CPU memory buffer than
+// it is to update a D3D staging buffer and read it back later.
+class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage
+{
+  public:
+    explicit SystemMemoryStorage(Renderer11 *renderer);
+    ~SystemMemoryStorage() override {}
+
+    bool isMappable(GLbitfield access) const override { return true; }
+    gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+                                                  size_t sourceOffset,
+                                                  size_t size,
+                                                  size_t destOffset) override;
+    gl::Error resize(size_t size, bool preserveData) override;
+
+    gl::Error map(size_t offset,
+                  size_t length,
+                  GLbitfield access,
+                  uint8_t **mapPointerOut) override;
+    void unmap() override;
+
+    angle::MemoryBuffer *getSystemCopy() { return &mSystemCopy; }
+
+  protected:
+    angle::MemoryBuffer mSystemCopy;
+};
+
+Buffer11::Buffer11(const gl::BufferState &state, Renderer11 *renderer)
+    : BufferD3D(state, renderer),
+      mRenderer(renderer),
+      mSize(0),
+      mMappedStorage(nullptr),
+      mBufferStorages({}),
+      mDeallocThresholds({}),
+      mIdleness({}),
+      mConstantBufferStorageAdditionalSize(0),
+      mMaxConstantBufferLruCount(0)
+{
+}
+
+Buffer11::~Buffer11()
+{
+    for (auto &storage : mBufferStorages)
+    {
+        SafeDelete(storage);
+    }
+
+    for (auto &p : mConstantBufferRangeStoragesCache)
+    {
+        SafeDelete(p.second.storage);
+    }
+
+    mRenderer->onBufferDelete(this);
+}
+
+gl::Error Buffer11::setData(ContextImpl *context,
+                            GLenum target,
+                            const void *data,
+                            size_t size,
+                            GLenum usage)
+{
+    updateD3DBufferUsage(usage);
+    ANGLE_TRY(setSubData(context, target, data, size, 0));
+    return gl::NoError();
+}
+
+gl::Error Buffer11::getData(const uint8_t **outData)
+{
+    SystemMemoryStorage *systemMemoryStorage = nullptr;
+    ANGLE_TRY_RESULT(getSystemMemoryStorage(), systemMemoryStorage);
+
+    ASSERT(systemMemoryStorage->getSize() >= mSize);
+
+    *outData = systemMemoryStorage->getSystemCopy()->data();
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<Buffer11::SystemMemoryStorage *> Buffer11::getSystemMemoryStorage()
+{
+    BufferStorage *storage = nullptr;
+    ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_SYSTEM_MEMORY), storage);
+    return GetAs<SystemMemoryStorage>(storage);
+}
+
+gl::Error Buffer11::setSubData(ContextImpl * /*context*/,
+                               GLenum target,
+                               const void *data,
+                               size_t size,
+                               size_t offset)
+{
+    size_t requiredSize = size + offset;
+
+    if (data && size > 0)
+    {
+        // Use system memory storage for dynamic buffers.
+        // Try using a constant storage for constant buffers
+        BufferStorage *writeBuffer = nullptr;
+        if (target == GL_UNIFORM_BUFFER)
+        {
+            // If we are a very large uniform buffer, keep system memory storage around so that we
+            // aren't forced to read back from a constant buffer. We also check the workaround for
+            // Intel - this requires us to use system memory so we don't end up having to copy from
+            // a constant buffer to a staging buffer.
+            // TODO(jmadill): Use Context caps.
+            if (offset == 0 && size >= mSize &&
+                size <= static_cast<UINT>(mRenderer->getNativeCaps().maxUniformBlockSize) &&
+                !mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers)
+            {
+                ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_UNIFORM), writeBuffer);
+            }
+            else
+            {
+                ANGLE_TRY_RESULT(getSystemMemoryStorage(), writeBuffer);
+            }
+        }
+        else if (supportsDirectBinding())
+        {
+            ANGLE_TRY_RESULT(getStagingStorage(), writeBuffer);
+        }
+        else
+        {
+            ANGLE_TRY_RESULT(getSystemMemoryStorage(), writeBuffer);
+        }
+
+        ASSERT(writeBuffer);
+
+        // Explicitly resize the staging buffer, preserving data if the new data will not
+        // completely fill the buffer
+        if (writeBuffer->getSize() < requiredSize)
+        {
+            bool preserveData = (offset > 0);
+            ANGLE_TRY(writeBuffer->resize(requiredSize, preserveData));
+        }
+
+        writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size);
+        writeBuffer->setDataRevision(writeBuffer->getDataRevision() + 1);
+    }
+
+    mSize = std::max(mSize, requiredSize);
+    invalidateStaticData();
+
+    return gl::NoError();
+}
+
+gl::Error Buffer11::copySubData(ContextImpl *context,
+                                BufferImpl *source,
+                                GLintptr sourceOffset,
+                                GLintptr destOffset,
+                                GLsizeiptr size)
+{
+    Buffer11 *sourceBuffer = GetAs<Buffer11>(source);
+    ASSERT(sourceBuffer != nullptr);
+
+    BufferStorage *copyDest = nullptr;
+    ANGLE_TRY_RESULT(getLatestBufferStorage(), copyDest);
+
+    if (!copyDest)
+    {
+        ANGLE_TRY_RESULT(getStagingStorage(), copyDest);
+    }
+
+    BufferStorage *copySource = nullptr;
+    ANGLE_TRY_RESULT(sourceBuffer->getLatestBufferStorage(), copySource);
+
+    if (!copySource || !copyDest)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer.");
+    }
+
+    // If copying to/from a pixel pack buffer, we must have a staging or
+    // pack buffer partner, because other native buffers can't be mapped
+    if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable(GL_MAP_READ_BIT))
+    {
+        ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(), copySource);
+    }
+    else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK &&
+             !copyDest->isMappable(GL_MAP_WRITE_BIT))
+    {
+        ANGLE_TRY_RESULT(getStagingStorage(), copyDest);
+    }
+
+    // D3D11 does not allow overlapped copies until 11.1, and only if the
+    // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap
+    // Get around this via a different source buffer
+    if (copySource == copyDest)
+    {
+        if (copySource->getUsage() == BUFFER_USAGE_STAGING)
+        {
+            ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+                             copySource);
+        }
+        else
+        {
+            ANGLE_TRY_RESULT(getStagingStorage(), copySource);
+        }
+    }
+
+    CopyResult copyResult = CopyResult::NOT_RECREATED;
+    ANGLE_TRY_RESULT(copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset),
+                     copyResult);
+    copyDest->setDataRevision(copyDest->getDataRevision() + 1);
+
+    mSize = std::max<size_t>(mSize, destOffset + size);
+    invalidateStaticData();
+
+    return gl::NoError();
+}
+
+gl::Error Buffer11::map(ContextImpl *context, GLenum access, void **mapPtr)
+{
+    // GL_OES_mapbuffer uses an enum instead of a bitfield for it's access, convert to a bitfield
+    // and call mapRange.
+    ASSERT(access == GL_WRITE_ONLY_OES);
+    return mapRange(context, 0, mSize, GL_MAP_WRITE_BIT, mapPtr);
+}
+
+gl::Error Buffer11::mapRange(ContextImpl *context,
+                             size_t offset,
+                             size_t length,
+                             GLbitfield access,
+                             void **mapPtr)
+{
+    ASSERT(!mMappedStorage);
+
+    BufferStorage *latestStorage = nullptr;
+    ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage);
+
+    if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
+                          latestStorage->getUsage() == BUFFER_USAGE_STAGING))
+    {
+        // Latest storage is mappable.
+        mMappedStorage = latestStorage;
+    }
+    else
+    {
+        // Fall back to using the staging buffer if the latest storage does not exist or is not
+        // CPU-accessible.
+        ANGLE_TRY_RESULT(getStagingStorage(), mMappedStorage);
+    }
+
+    if (!mMappedStorage)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer.");
+    }
+
+    if ((access & GL_MAP_WRITE_BIT) > 0)
+    {
+        // Update the data revision immediately, since the data might be changed at any time
+        mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1);
+        invalidateStaticData();
+    }
+
+    uint8_t *mappedBuffer = nullptr;
+    ANGLE_TRY(mMappedStorage->map(offset, length, access, &mappedBuffer));
+    ASSERT(mappedBuffer);
+
+    *mapPtr = static_cast<void *>(mappedBuffer);
+    return gl::NoError();
+}
+
+gl::Error Buffer11::unmap(ContextImpl *context, GLboolean *result)
+{
+    ASSERT(mMappedStorage);
+    mMappedStorage->unmap();
+    mMappedStorage = nullptr;
+
+    // TODO: detect if we had corruption. if so, return false.
+    *result = GL_TRUE;
+
+    return gl::NoError();
+}
+
+gl::Error Buffer11::markTransformFeedbackUsage()
+{
+    BufferStorage *transformFeedbackStorage = nullptr;
+    ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+                     transformFeedbackStorage);
+
+    if (transformFeedbackStorage)
+    {
+        transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
+    }
+
+    invalidateStaticData();
+    return gl::NoError();
+}
+
+void Buffer11::updateDeallocThreshold(BufferUsage usage)
+{
+    // The following strategy was tuned on the Oort online benchmark (http://oortonline.gl/)
+    // as well as a custom microbenchmark (IndexConversionPerfTest.Run/index_range_d3d11)
+
+    // First readback: 8 unmodified uses before we free buffer memory.
+    // After that, double the threshold each time until we reach the max.
+    if (mDeallocThresholds[usage] == 0)
+    {
+        mDeallocThresholds[usage] = 8;
+    }
+    else if (mDeallocThresholds[usage] < std::numeric_limits<unsigned int>::max() / 2u)
+    {
+        mDeallocThresholds[usage] *= 2u;
+    }
+    else
+    {
+        mDeallocThresholds[usage] = std::numeric_limits<unsigned int>::max();
+    }
+}
+
+// Free the storage if we decide it isn't being used very often.
+gl::Error Buffer11::checkForDeallocation(BufferUsage usage)
+{
+    mIdleness[usage]++;
+
+    BufferStorage *&storage = mBufferStorages[usage];
+    if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage])
+    {
+        BufferStorage *latestStorage = nullptr;
+        ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage);
+        if (latestStorage != storage)
+        {
+            SafeDelete(storage);
+        }
+    }
+
+    return gl::NoError();
+}
+
+// Keep system memory when we are using it for the canonical version of data.
+bool Buffer11::canDeallocateSystemMemory() const
+{
+    // Must keep system memory on Intel.
+    if (mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers)
+    {
+        return false;
+    }
+
+    return (!mBufferStorages[BUFFER_USAGE_UNIFORM] ||
+            mSize <= mRenderer->getNativeCaps().maxUniformBlockSize);
+}
+
+void Buffer11::markBufferUsage(BufferUsage usage)
+{
+    mIdleness[usage] = 0;
+}
+
+gl::Error Buffer11::garbageCollection(BufferUsage currentUsage)
+{
+    if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory())
+    {
+        ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_SYSTEM_MEMORY));
+    }
+
+    if (currentUsage != BUFFER_USAGE_STAGING)
+    {
+        ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_STAGING));
+    }
+
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getBuffer(BufferUsage usage)
+{
+    BufferStorage *storage = nullptr;
+    ANGLE_TRY_RESULT(getBufferStorage(usage), storage);
+    return GetAs<NativeStorage>(storage)->getNativeStorage();
+}
+
+gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer(
+    SourceIndexData *indexInfo,
+    const TranslatedAttribute &attribute,
+    GLint startVertex)
+{
+    ASSERT(indexInfo);
+
+    BufferStorage *untypedStorage = nullptr;
+    ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX), untypedStorage);
+
+    EmulatedIndexedStorage *emulatedStorage = GetAs<EmulatedIndexedStorage>(untypedStorage);
+
+    ID3D11Buffer *nativeStorage = nullptr;
+    ANGLE_TRY_RESULT(emulatedStorage->getNativeStorage(indexInfo, attribute, startVertex),
+                     nativeStorage);
+
+    return nativeStorage;
+}
+
+gl::Error Buffer11::getConstantBufferRange(GLintptr offset,
+                                           GLsizeiptr size,
+                                           ID3D11Buffer **bufferOut,
+                                           UINT *firstConstantOut,
+                                           UINT *numConstantsOut)
+{
+    BufferStorage *bufferStorage = nullptr;
+
+    if (offset == 0 || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets)
+    {
+        ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_UNIFORM), bufferStorage);
+        CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut);
+    }
+    else
+    {
+        ANGLE_TRY_RESULT(getConstantBufferRangeStorage(offset, size), bufferStorage);
+        *firstConstantOut = 0;
+        *numConstantsOut  = 0;
+    }
+
+    *bufferOut = GetAs<NativeStorage>(bufferStorage)->getNativeStorage();
+
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::getSRV(DXGI_FORMAT srvFormat)
+{
+    BufferStorage *storage = nullptr;
+    ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK), storage);
+    NativeStorage *nativeStorage = GetAs<NativeStorage>(storage);
+    return nativeStorage->getSRVForFormat(srvFormat);
+}
+
+gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment,
+                               const PackPixelsParams &params)
+{
+    PackStorage *packStorage = nullptr;
+    ANGLE_TRY_RESULT(getPackStorage(), packStorage);
+
+    BufferStorage *latestStorage = nullptr;
+    ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage);
+
+    ASSERT(packStorage);
+    ANGLE_TRY(packStorage->packPixels(readAttachment, params));
+    packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
+
+    return gl::NoError();
+}
+
+size_t Buffer11::getTotalCPUBufferMemoryBytes() const
+{
+    size_t allocationSize = 0;
+
+    BufferStorage *staging = mBufferStorages[BUFFER_USAGE_STAGING];
+    allocationSize += staging ? staging->getSize() : 0;
+
+    BufferStorage *sysMem = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY];
+    allocationSize += sysMem ? sysMem->getSize() : 0;
+
+    return allocationSize;
+}
+
+gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(BufferUsage usage)
+{
+    ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT);
+    BufferStorage *&newStorage = mBufferStorages[usage];
+
+    if (!newStorage)
+    {
+        newStorage = allocateStorage(usage);
+    }
+
+    markBufferUsage(usage);
+
+    // resize buffer
+    if (newStorage->getSize() < mSize)
+    {
+        ANGLE_TRY(newStorage->resize(mSize, true));
+    }
+
+    ASSERT(newStorage);
+
+    ANGLE_TRY(updateBufferStorage(newStorage, 0, mSize));
+    ANGLE_TRY(garbageCollection(usage));
+
+    return newStorage;
+}
+
+Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage)
+{
+    updateDeallocThreshold(usage);
+    switch (usage)
+    {
+        case BUFFER_USAGE_PIXEL_PACK:
+            return new PackStorage(mRenderer);
+        case BUFFER_USAGE_SYSTEM_MEMORY:
+            return new SystemMemoryStorage(mRenderer);
+        case BUFFER_USAGE_EMULATED_INDEXED_VERTEX:
+            return new EmulatedIndexedStorage(mRenderer);
+        case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
+            return new NativeStorage(mRenderer, usage, &mDirectBroadcastChannel);
+        default:
+            return new NativeStorage(mRenderer, usage, nullptr);
+    }
+}
+
+gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeStorage(
+    GLintptr offset,
+    GLsizeiptr size)
+{
+    BufferStorage *newStorage;
+
+    {
+        // Keep the cacheEntry in a limited scope because it may be invalidated later in the code if
+        // we need to reclaim some space.
+        ConstantBufferCacheEntry *cacheEntry = &mConstantBufferRangeStoragesCache[offset];
+
+        if (!cacheEntry->storage)
+        {
+            cacheEntry->storage  = allocateStorage(BUFFER_USAGE_UNIFORM);
+            cacheEntry->lruCount = ++mMaxConstantBufferLruCount;
+        }
+
+        cacheEntry->lruCount = ++mMaxConstantBufferLruCount;
+        newStorage           = cacheEntry->storage;
+    }
+
+    markBufferUsage(BUFFER_USAGE_UNIFORM);
+
+    if (newStorage->getSize() < static_cast<size_t>(size))
+    {
+        size_t maximumAllowedAdditionalSize = 2 * getSize();
+
+        size_t sizeDelta = size - newStorage->getSize();
+
+        while (mConstantBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize)
+        {
+            auto iter = std::min_element(std::begin(mConstantBufferRangeStoragesCache),
+                                         std::end(mConstantBufferRangeStoragesCache),
+                                         [](const ConstantBufferCache::value_type &a,
+                                            const ConstantBufferCache::value_type &b) {
+                                             return a.second.lruCount < b.second.lruCount;
+                                         });
+
+            ASSERT(iter->second.storage != newStorage);
+            ASSERT(mConstantBufferStorageAdditionalSize >= iter->second.storage->getSize());
+
+            mConstantBufferStorageAdditionalSize -= iter->second.storage->getSize();
+            SafeDelete(iter->second.storage);
+            mConstantBufferRangeStoragesCache.erase(iter);
+        }
+
+        ANGLE_TRY(newStorage->resize(size, false));
+        mConstantBufferStorageAdditionalSize += sizeDelta;
+
+        // We don't copy the old data when resizing the constant buffer because the data may be
+        // out-of-date therefore we reset the data revision and let updateBufferStorage() handle the
+        // copy.
+        newStorage->setDataRevision(0);
+    }
+
+    ANGLE_TRY(updateBufferStorage(newStorage, offset, size));
+    ANGLE_TRY(garbageCollection(BUFFER_USAGE_UNIFORM));
+    return newStorage;
+}
+
+gl::Error Buffer11::updateBufferStorage(BufferStorage *storage,
+                                        size_t sourceOffset,
+                                        size_t storageSize)
+{
+    BufferStorage *latestBuffer = nullptr;
+    ANGLE_TRY_RESULT(getLatestBufferStorage(), latestBuffer);
+
+    ASSERT(storage);
+
+    if (latestBuffer && latestBuffer->getDataRevision() > storage->getDataRevision())
+    {
+        // Copy through a staging buffer if we're copying from or to a non-staging, mappable
+        // buffer storage. This is because we can't map a GPU buffer, and copy CPU
+        // data directly. If we're already using a staging buffer we're fine.
+        if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING &&
+            storage->getUsage() != BUFFER_USAGE_STAGING &&
+            (!latestBuffer->isMappable(GL_MAP_READ_BIT) || !storage->isMappable(GL_MAP_WRITE_BIT)))
+        {
+            NativeStorage *stagingBuffer = nullptr;
+            ANGLE_TRY_RESULT(getStagingStorage(), stagingBuffer);
+
+            CopyResult copyResult = CopyResult::NOT_RECREATED;
+            ANGLE_TRY_RESULT(
+                stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0),
+                copyResult);
+            stagingBuffer->setDataRevision(latestBuffer->getDataRevision());
+
+            latestBuffer = stagingBuffer;
+        }
+
+        CopyResult copyResult = CopyResult::NOT_RECREATED;
+        ANGLE_TRY_RESULT(storage->copyFromStorage(latestBuffer, sourceOffset, storageSize, 0),
+                         copyResult);
+        // If the D3D buffer has been recreated, we should update our serial.
+        if (copyResult == CopyResult::RECREATED)
+        {
+            updateSerial();
+        }
+        storage->setDataRevision(latestBuffer->getDataRevision());
+    }
+
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getLatestBufferStorage() const
+{
+    // Even though we iterate over all the direct buffers, it is expected that only
+    // 1 or 2 will be present.
+    BufferStorage *latestStorage = nullptr;
+    DataRevision latestRevision  = 0;
+    for (auto &storage : mBufferStorages)
+    {
+        if (storage && (!latestStorage || storage->getDataRevision() > latestRevision))
+        {
+            latestStorage  = storage;
+            latestRevision = storage->getDataRevision();
+        }
+    }
+
+    // resize buffer
+    if (latestStorage && latestStorage->getSize() < mSize)
+    {
+        ANGLE_TRY(latestStorage->resize(mSize, true));
+    }
+
+    return latestStorage;
+}
+
+gl::ErrorOrResult<Buffer11::NativeStorage *> Buffer11::getStagingStorage()
+{
+    BufferStorage *stagingStorage = nullptr;
+    ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_STAGING), stagingStorage);
+    return GetAs<NativeStorage>(stagingStorage);
+}
+
+gl::ErrorOrResult<Buffer11::PackStorage *> Buffer11::getPackStorage()
+{
+    BufferStorage *packStorage = nullptr;
+    ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_PIXEL_PACK), packStorage);
+    return GetAs<PackStorage>(packStorage);
+}
+
+bool Buffer11::supportsDirectBinding() const
+{
+    // Do not support direct buffers for dynamic data. The streaming buffer
+    // offers better performance for data which changes every frame.
+    return (mUsage == D3DBufferUsage::STATIC);
+}
+
+void Buffer11::initializeStaticData()
+{
+    BufferD3D::initializeStaticData();
+
+    // Notify when static data changes.
+    mStaticBroadcastChannel.signal();
+}
+
+void Buffer11::invalidateStaticData()
+{
+    BufferD3D::invalidateStaticData();
+
+    // Notify when static data changes.
+    mStaticBroadcastChannel.signal();
+}
+
+OnBufferDataDirtyChannel *Buffer11::getStaticBroadcastChannel()
+{
+    return &mStaticBroadcastChannel;
+}
+
+OnBufferDataDirtyChannel *Buffer11::getDirectBroadcastChannel()
+{
+    return &mDirectBroadcastChannel;
+}
+
+// Buffer11::BufferStorage implementation
+
+Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
+    : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0)
+{
+}
+
+gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size)
+{
+    ASSERT(isMappable(GL_MAP_WRITE_BIT));
+
+    // Uniform storage can have a different internal size than the buffer size. Ensure we don't
+    // overflow.
+    size_t mapSize = std::min(size, mBufferSize - offset);
+
+    uint8_t *writePointer = nullptr;
+    ANGLE_TRY(map(offset, mapSize, GL_MAP_WRITE_BIT, &writePointer));
+
+    memcpy(writePointer, data, mapSize);
+
+    unmap();
+
+    return gl::NoError();
+}
+
+// Buffer11::NativeStorage implementation
+
+Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
+                                       BufferUsage usage,
+                                       const OnBufferDataDirtyChannel *onStorageChanged)
+    : BufferStorage(renderer, usage), mNativeStorage(nullptr), mOnStorageChanged(onStorageChanged)
+{
+}
+
+Buffer11::NativeStorage::~NativeStorage()
+{
+    SafeRelease(mNativeStorage);
+    clearSRVs();
+}
+
+bool Buffer11::NativeStorage::isMappable(GLbitfield access) const
+{
+    if ((access & GL_MAP_READ_BIT) != 0)
+    {
+        // Read is more exclusive than write mappability.
+        return (mUsage == BUFFER_USAGE_STAGING);
+    }
+    ASSERT((access & GL_MAP_WRITE_BIT) != 0);
+    return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_UNIFORM);
+}
+
+// Returns true if it recreates the direct buffer
+gl::ErrorOrResult<CopyResult> Buffer11::NativeStorage::copyFromStorage(BufferStorage *source,
+                                                                       size_t sourceOffset,
+                                                                       size_t size,
+                                                                       size_t destOffset)
+{
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+    size_t requiredSize = destOffset + size;
+    bool createBuffer   = !mNativeStorage || mBufferSize < requiredSize;
+
+    // (Re)initialize D3D buffer if needed
+    bool preserveData = (destOffset > 0);
+    if (createBuffer)
+    {
+        resize(requiredSize, preserveData);
+    }
+
+    size_t clampedSize = size;
+    if (mUsage == BUFFER_USAGE_UNIFORM)
+    {
+        clampedSize = std::min(clampedSize, mBufferSize - destOffset);
+    }
+
+    if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
+        source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
+    {
+        ASSERT(source->isMappable(GL_MAP_READ_BIT) && isMappable(GL_MAP_WRITE_BIT));
+
+        // Uniform buffers must be mapped with write/discard.
+        ASSERT(!(preserveData && mUsage == BUFFER_USAGE_UNIFORM));
+
+        uint8_t *sourcePointer = nullptr;
+        ANGLE_TRY(source->map(sourceOffset, clampedSize, GL_MAP_READ_BIT, &sourcePointer));
+
+        setData(sourcePointer, destOffset, clampedSize);
+
+        source->unmap();
+    }
+    else
+    {
+        D3D11_BOX srcBox;
+        srcBox.left   = static_cast<unsigned int>(sourceOffset);
+        srcBox.right  = static_cast<unsigned int>(sourceOffset + clampedSize);
+        srcBox.top    = 0;
+        srcBox.bottom = 1;
+        srcBox.front  = 0;
+        srcBox.back   = 1;
+
+        ID3D11Buffer *sourceBuffer = GetAs<NativeStorage>(source)->getNativeStorage();
+
+        context->CopySubresourceRegion(mNativeStorage, 0, static_cast<unsigned int>(destOffset), 0,
+                                       0, sourceBuffer, 0, &srcBox);
+    }
+
+    return createBuffer ? CopyResult::RECREATED : CopyResult::NOT_RECREATED;
+}
+
+gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
+{
+    ID3D11Device *device         = mRenderer->getDevice();
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+    D3D11_BUFFER_DESC bufferDesc;
+    FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
+
+    ID3D11Buffer *newBuffer;
+    HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &newBuffer);
+
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.",
+                         result);
+    }
+
+    d3d11::SetDebugName(newBuffer, "Buffer11::NativeStorage");
+
+    if (mNativeStorage && preserveData)
+    {
+        // We don't call resize if the buffer is big enough already.
+        ASSERT(mBufferSize <= size);
+
+        D3D11_BOX srcBox;
+        srcBox.left   = 0;
+        srcBox.right  = static_cast<unsigned int>(mBufferSize);
+        srcBox.top    = 0;
+        srcBox.bottom = 1;
+        srcBox.front  = 0;
+        srcBox.back   = 1;
+
+        context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox);
+    }
+
+    // No longer need the old buffer
+    SafeRelease(mNativeStorage);
+    mNativeStorage = newBuffer;
+
+    mBufferSize = bufferDesc.ByteWidth;
+
+    // Free the SRVs.
+    clearSRVs();
+
+    // Notify that the storage has changed.
+    if (mOnStorageChanged)
+    {
+        mOnStorageChanged->signal();
+    }
+
+    return gl::NoError();
+}
+
+// static
+void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
+                                             Renderer11 *renderer,
+                                             BufferUsage usage,
+                                             unsigned int bufferSize)
+{
+    bufferDesc->ByteWidth           = bufferSize;
+    bufferDesc->MiscFlags           = 0;
+    bufferDesc->StructureByteStride = 0;
+
+    switch (usage)
+    {
+        case BUFFER_USAGE_STAGING:
+            bufferDesc->Usage          = D3D11_USAGE_STAGING;
+            bufferDesc->BindFlags      = 0;
+            bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+            break;
+
+        case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
+            bufferDesc->Usage     = D3D11_USAGE_DEFAULT;
+            bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
+
+            if (renderer->isES3Capable())
+            {
+                bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT;
+            }
+
+            bufferDesc->CPUAccessFlags = 0;
+            break;
+
+        case BUFFER_USAGE_INDEX:
+            bufferDesc->Usage          = D3D11_USAGE_DEFAULT;
+            bufferDesc->BindFlags      = D3D11_BIND_INDEX_BUFFER;
+            bufferDesc->CPUAccessFlags = 0;
+            break;
+
+        case BUFFER_USAGE_INDIRECT:
+            bufferDesc->MiscFlags      = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
+            bufferDesc->Usage          = D3D11_USAGE_DEFAULT;
+            bufferDesc->BindFlags      = 0;
+            bufferDesc->CPUAccessFlags = 0;
+            break;
+
+        case BUFFER_USAGE_PIXEL_UNPACK:
+            bufferDesc->Usage          = D3D11_USAGE_DEFAULT;
+            bufferDesc->BindFlags      = D3D11_BIND_SHADER_RESOURCE;
+            bufferDesc->CPUAccessFlags = 0;
+            break;
+
+        case BUFFER_USAGE_UNIFORM:
+            bufferDesc->Usage          = D3D11_USAGE_DYNAMIC;
+            bufferDesc->BindFlags      = D3D11_BIND_CONSTANT_BUFFER;
+            bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+            // Constant buffers must be of a limited size, and aligned to 16 byte boundaries
+            // For our purposes we ignore any buffer data past the maximum constant buffer size
+            bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u);
+
+            // Note: it seems that D3D11 allows larger buffers on some platforms, but not all.
+            // (Windows 10 seems to allow larger constant buffers, but not Windows 7)
+            bufferDesc->ByteWidth =
+                std::min<UINT>(bufferDesc->ByteWidth,
+                               static_cast<UINT>(renderer->getNativeCaps().maxUniformBlockSize));
+            break;
+
+        default:
+            UNREACHABLE();
+    }
+}
+
+gl::Error Buffer11::NativeStorage::map(size_t offset,
+                                       size_t length,
+                                       GLbitfield access,
+                                       uint8_t **mapPointerOut)
+{
+    ASSERT(isMappable(access));
+
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+    D3D11_MAP d3dMapType         = gl_d3d11::GetD3DMapTypeFromBits(mUsage, access);
+    UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
+
+    HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to map native storage in Buffer11::NativeStorage::map");
+    }
+    ASSERT(mappedResource.pData);
+    *mapPointerOut = static_cast<uint8_t *>(mappedResource.pData) + offset;
+    return gl::NoError();
+}
+
+void Buffer11::NativeStorage::unmap()
+{
+    ASSERT(isMappable(GL_MAP_WRITE_BIT) || isMappable(GL_MAP_READ_BIT));
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+    context->Unmap(mNativeStorage, 0);
+}
+
+gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::NativeStorage::getSRVForFormat(
+    DXGI_FORMAT srvFormat)
+{
+    auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
+
+    if (bufferSRVIt != mBufferResourceViews.end())
+    {
+        return bufferSRVIt->second;
+    }
+
+    ID3D11Device *device                = mRenderer->getDevice();
+    ID3D11ShaderResourceView *bufferSRV = nullptr;
+
+    const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(srvFormat);
+
+    D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
+    bufferSRVDesc.Buffer.ElementOffset = 0;
+    bufferSRVDesc.Buffer.ElementWidth  = static_cast<UINT>(mBufferSize) / dxgiFormatInfo.pixelBytes;
+    bufferSRVDesc.ViewDimension        = D3D11_SRV_DIMENSION_BUFFER;
+    bufferSRVDesc.Format               = srvFormat;
+
+    HRESULT result = device->CreateShaderResourceView(mNativeStorage, &bufferSRVDesc, &bufferSRV);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Error creating buffer SRV in Buffer11::NativeStorage::getSRVForFormat");
+    }
+
+    mBufferResourceViews[srvFormat] = bufferSRV;
+
+    return bufferSRV;
+}
+
+void Buffer11::NativeStorage::clearSRVs()
+{
+    for (auto &srv : mBufferResourceViews)
+    {
+        SafeRelease(srv.second);
+    }
+    mBufferResourceViews.clear();
+}
+
+// Buffer11::EmulatedIndexStorage implementation
+
+Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer)
+    : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr)
+{
+}
+
+Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage()
+{
+    SafeRelease(mNativeStorage);
+}
+
+gl::ErrorOrResult<ID3D11Buffer *> Buffer11::EmulatedIndexedStorage::getNativeStorage(
+    SourceIndexData *indexInfo,
+    const TranslatedAttribute &attribute,
+    GLint startVertex)
+{
+    // If a change in the indices applied from the last draw call is detected, then the emulated
+    // indexed buffer needs to be invalidated.  After invalidation, the change detected flag should
+    // be cleared to avoid unnecessary recreation of the buffer.
+    if (mNativeStorage == nullptr || indexInfo->srcIndicesChanged)
+    {
+        SafeRelease(mNativeStorage);
+
+        // Copy the source index data. This ensures that the lifetime of the indices pointer
+        // stays with this storage until the next time we invalidate.
+        size_t indicesDataSize = 0;
+        switch (indexInfo->srcIndexType)
+        {
+            case GL_UNSIGNED_INT:
+                indicesDataSize = sizeof(GLuint) * indexInfo->srcCount;
+                break;
+            case GL_UNSIGNED_SHORT:
+                indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
+                break;
+            case GL_UNSIGNED_BYTE:
+                indicesDataSize = sizeof(GLubyte) * indexInfo->srcCount;
+                break;
+            default:
+                indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
+                break;
+        }
+
+        if (!mIndicesMemoryBuffer.resize(indicesDataSize))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Error resizing index memory buffer in "
+                             "Buffer11::EmulatedIndexedStorage::getNativeStorage");
+        }
+
+        memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize);
+
+        indexInfo->srcIndicesChanged = false;
+    }
+
+    if (!mNativeStorage)
+    {
+        unsigned int offset = 0;
+        ANGLE_TRY_RESULT(attribute.computeOffset(startVertex), offset);
+
+        // Expand the memory storage upon request and cache the results.
+        unsigned int expandedDataSize =
+            static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + offset);
+        angle::MemoryBuffer expandedData;
+        if (!expandedData.resize(expandedDataSize))
+        {
+            return gl::Error(
+                GL_OUT_OF_MEMORY,
+                "Error resizing buffer in Buffer11::EmulatedIndexedStorage::getNativeStorage");
+        }
+
+        // Clear the contents of the allocated buffer
+        ZeroMemory(expandedData.data(), expandedDataSize);
+
+        uint8_t *curr      = expandedData.data();
+        const uint8_t *ptr = static_cast<const uint8_t *>(indexInfo->srcIndices);
+
+        // Ensure that we start in the correct place for the emulated data copy operation to
+        // maintain offset behaviors.
+        curr += offset;
+
+        ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices<GLushort>;
+
+        switch (indexInfo->srcIndexType)
+        {
+            case GL_UNSIGNED_INT:
+                readIndexValue = ReadIndexValueFromIndices<GLuint>;
+                break;
+            case GL_UNSIGNED_SHORT:
+                readIndexValue = ReadIndexValueFromIndices<GLushort>;
+                break;
+            case GL_UNSIGNED_BYTE:
+                readIndexValue = ReadIndexValueFromIndices<GLubyte>;
+                break;
+        }
+
+        // Iterate over the cached index data and copy entries indicated into the emulated buffer.
+        for (GLuint i = 0; i < indexInfo->srcCount; i++)
+        {
+            GLuint idx = readIndexValue(ptr, i);
+            memcpy(curr, mMemoryBuffer.data() + (attribute.stride * idx), attribute.stride);
+            curr += attribute.stride;
+        }
+
+        // Finally, initialize the emulated indexed native storage object with the newly copied data
+        // and free the temporary buffers used.
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_BUFFER_DESC bufferDesc;
+        bufferDesc.ByteWidth           = expandedDataSize;
+        bufferDesc.MiscFlags           = 0;
+        bufferDesc.StructureByteStride = 0;
+        bufferDesc.Usage               = D3D11_USAGE_DEFAULT;
+        bufferDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
+        bufferDesc.CPUAccessFlags      = 0;
+
+        D3D11_SUBRESOURCE_DATA subResourceData = {expandedData.data(), 0, 0};
+
+        HRESULT result = device->CreateBuffer(&bufferDesc, &subResourceData, &mNativeStorage);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Could not create emulated index data buffer: %08lX",
+                             result);
+        }
+        d3d11::SetDebugName(mNativeStorage, "Buffer11::EmulatedIndexedStorage");
+    }
+
+    return mNativeStorage;
+}
+
+gl::ErrorOrResult<CopyResult> Buffer11::EmulatedIndexedStorage::copyFromStorage(
+    BufferStorage *source,
+    size_t sourceOffset,
+    size_t size,
+    size_t destOffset)
+{
+    ASSERT(source->isMappable(GL_MAP_READ_BIT));
+    uint8_t *sourceData = nullptr;
+    ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+    ASSERT(destOffset + size <= mMemoryBuffer.size());
+    memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
+    source->unmap();
+    return CopyResult::RECREATED;
+}
+
+gl::Error Buffer11::EmulatedIndexedStorage::resize(size_t size, bool preserveData)
+{
+    if (mMemoryBuffer.size() < size)
+    {
+        if (!mMemoryBuffer.resize(size))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize EmulatedIndexedStorage");
+        }
+        mBufferSize = size;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Buffer11::EmulatedIndexedStorage::map(size_t offset,
+                                                size_t length,
+                                                GLbitfield access,
+                                                uint8_t **mapPointerOut)
+{
+    ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size());
+    *mapPointerOut = mMemoryBuffer.data() + offset;
+    return gl::NoError();
+}
+
+void Buffer11::EmulatedIndexedStorage::unmap()
+{
+    // No-op
+}
+
+// Buffer11::PackStorage implementation
+
+Buffer11::PackStorage::PackStorage(Renderer11 *renderer)
+    : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false)
+{
+}
+
+Buffer11::PackStorage::~PackStorage()
+{
+}
+
+gl::ErrorOrResult<CopyResult> Buffer11::PackStorage::copyFromStorage(BufferStorage *source,
+                                                                     size_t sourceOffset,
+                                                                     size_t size,
+                                                                     size_t destOffset)
+{
+    ANGLE_TRY(flushQueuedPackCommand());
+
+    // For all use cases of pack buffers, we must copy through a readable buffer.
+    ASSERT(source->isMappable(GL_MAP_READ_BIT));
+    uint8_t *sourceData = nullptr;
+    ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+    ASSERT(destOffset + size <= mMemoryBuffer.size());
+    memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
+    source->unmap();
+    return CopyResult::NOT_RECREATED;
+}
+
+gl::Error Buffer11::PackStorage::resize(size_t size, bool preserveData)
+{
+    if (size != mBufferSize)
+    {
+        if (!mMemoryBuffer.resize(size))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer storage.");
+        }
+        mBufferSize = size;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Buffer11::PackStorage::map(size_t offset,
+                                     size_t length,
+                                     GLbitfield access,
+                                     uint8_t **mapPointerOut)
+{
+    ASSERT(offset + length <= getSize());
+    // TODO: fast path
+    //  We might be able to optimize out one or more memcpy calls by detecting when
+    //  and if D3D packs the staging texture memory identically to how we would fill
+    //  the pack buffer according to the current pack state.
+
+    ANGLE_TRY(flushQueuedPackCommand());
+
+    mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0);
+
+    *mapPointerOut = mMemoryBuffer.data() + offset;
+    return gl::NoError();
+}
+
+void Buffer11::PackStorage::unmap()
+{
+    // No-op
+}
+
+gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &readAttachment,
+                                            const PackPixelsParams &params)
+{
+    ANGLE_TRY(flushQueuedPackCommand());
+
+    RenderTarget11 *renderTarget = nullptr;
+    ANGLE_TRY(readAttachment.getRenderTarget(&renderTarget));
+
+    ID3D11Resource *renderTargetResource = renderTarget->getTexture();
+    ASSERT(renderTargetResource);
+
+    unsigned int srcSubresource = renderTarget->getSubresourceIndex();
+    TextureHelper11 srcTexture =
+        TextureHelper11::MakeAndReference(renderTargetResource, renderTarget->getFormatSet());
+
+    mQueuedPackCommand.reset(new PackPixelsParams(params));
+
+    gl::Extents srcTextureSize(params.area.width, params.area.height, 1);
+    if (!mStagingTexture.getResource() || mStagingTexture.getFormat() != srcTexture.getFormat() ||
+        mStagingTexture.getExtents() != srcTextureSize)
+    {
+        ANGLE_TRY_RESULT(
+            CreateStagingTexture(srcTexture.getTextureType(), srcTexture.getFormatSet(),
+                                 srcTextureSize, StagingAccess::READ, mRenderer->getDevice()),
+            mStagingTexture);
+    }
+
+    // ReadPixels from multisampled FBOs isn't supported in current GL
+    ASSERT(srcTexture.getSampleCount() <= 1);
+
+    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+    D3D11_BOX srcBox;
+    srcBox.left   = params.area.x;
+    srcBox.right  = params.area.x + params.area.width;
+    srcBox.top    = params.area.y;
+    srcBox.bottom = params.area.y + params.area.height;
+
+    // Select the correct layer from a 3D attachment
+    srcBox.front = 0;
+    if (mStagingTexture.getTextureType() == GL_TEXTURE_3D)
+    {
+        srcBox.front = static_cast<UINT>(readAttachment.layer());
+    }
+    srcBox.back = srcBox.front + 1;
+
+    // Asynchronous copy
+    immediateContext->CopySubresourceRegion(mStagingTexture.getResource(), 0, 0, 0, 0,
+                                            srcTexture.getResource(), srcSubresource, &srcBox);
+
+    return gl::NoError();
+}
+
+gl::Error Buffer11::PackStorage::flushQueuedPackCommand()
+{
+    ASSERT(mMemoryBuffer.size() > 0);
+
+    if (mQueuedPackCommand)
+    {
+        ANGLE_TRY(
+            mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()));
+        mQueuedPackCommand.reset(nullptr);
+    }
+
+    return gl::NoError();
+}
+
+// Buffer11::SystemMemoryStorage implementation
+
+Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer)
+    : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY)
+{
+}
+
+gl::ErrorOrResult<CopyResult> Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source,
+                                                                             size_t sourceOffset,
+                                                                             size_t size,
+                                                                             size_t destOffset)
+{
+    ASSERT(source->isMappable(GL_MAP_READ_BIT));
+    uint8_t *sourceData = nullptr;
+    ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+    ASSERT(destOffset + size <= mSystemCopy.size());
+    memcpy(mSystemCopy.data() + destOffset, sourceData, size);
+    source->unmap();
+    return CopyResult::RECREATED;
+}
+
+gl::Error Buffer11::SystemMemoryStorage::resize(size_t size, bool preserveData)
+{
+    if (mSystemCopy.size() < size)
+    {
+        if (!mSystemCopy.resize(size))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize SystemMemoryStorage");
+        }
+        mBufferSize = size;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Buffer11::SystemMemoryStorage::map(size_t offset,
+                                             size_t length,
+                                             GLbitfield access,
+                                             uint8_t **mapPointerOut)
+{
+    ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size());
+    *mapPointerOut = mSystemCopy.data() + offset;
+    return gl::NoError();
+}
+
+void Buffer11::SystemMemoryStorage::unmap()
+{
+    // No-op
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
new file mode 100644
index 0000000..a198f45
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
@@ -0,0 +1,171 @@
+//
+// 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.
+//
+
+// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
+
+#include <array>
+#include <map>
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+struct PackPixelsParams;
+class Renderer11;
+struct SourceIndexData;
+struct TranslatedAttribute;
+
+// The order of this enum governs priority of 'getLatestBufferStorage'.
+enum BufferUsage
+{
+    BUFFER_USAGE_SYSTEM_MEMORY,
+    BUFFER_USAGE_STAGING,
+    BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK,
+    BUFFER_USAGE_INDEX,
+    // TODO: possibly share this buffer type with shader storage buffers.
+    BUFFER_USAGE_INDIRECT,
+    BUFFER_USAGE_PIXEL_UNPACK,
+    BUFFER_USAGE_PIXEL_PACK,
+    BUFFER_USAGE_UNIFORM,
+    BUFFER_USAGE_EMULATED_INDEXED_VERTEX,
+
+    BUFFER_USAGE_COUNT,
+};
+
+typedef size_t DataRevision;
+
+class Buffer11 : public BufferD3D
+{
+  public:
+    Buffer11(const gl::BufferState &state, Renderer11 *renderer);
+    virtual ~Buffer11();
+
+    gl::ErrorOrResult<ID3D11Buffer *> getBuffer(BufferUsage usage);
+    gl::ErrorOrResult<ID3D11Buffer *> getEmulatedIndexedBuffer(SourceIndexData *indexInfo,
+                                                               const TranslatedAttribute &attribute,
+                                                               GLint startVertex);
+    gl::Error getConstantBufferRange(GLintptr offset,
+                                     GLsizeiptr size,
+                                     ID3D11Buffer **bufferOut,
+                                     UINT *firstConstantOut,
+                                     UINT *numConstantsOut);
+    gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRV(DXGI_FORMAT srvFormat);
+    bool isMapped() const { return mMappedStorage != nullptr; }
+    gl::Error packPixels(const gl::FramebufferAttachment &readAttachment,
+                         const PackPixelsParams &params);
+    size_t getTotalCPUBufferMemoryBytes() const;
+
+    // BufferD3D implementation
+    size_t getSize() const override { return mSize; }
+    bool supportsDirectBinding() const override;
+    gl::Error getData(const uint8_t **outData) override;
+    void initializeStaticData() override;
+    void invalidateStaticData() override;
+
+    // BufferImpl implementation
+    gl::Error setData(ContextImpl *context,
+                      GLenum target,
+                      const void *data,
+                      size_t size,
+                      GLenum usage) override;
+    gl::Error setSubData(ContextImpl *context,
+                         GLenum target,
+                         const void *data,
+                         size_t size,
+                         size_t offset) override;
+    gl::Error copySubData(ContextImpl *contextImpl,
+                          BufferImpl *source,
+                          GLintptr sourceOffset,
+                          GLintptr destOffset,
+                          GLsizeiptr size) override;
+    gl::Error map(ContextImpl *contextImpl, GLenum access, void **mapPtr) override;
+    gl::Error mapRange(ContextImpl *contextImpl,
+                       size_t offset,
+                       size_t length,
+                       GLbitfield access,
+                       void **mapPtr) override;
+    gl::Error unmap(ContextImpl *contextImpl, GLboolean *result) override;
+    gl::Error markTransformFeedbackUsage() override;
+
+    // We use two set of dirty events. Static buffers are marked dirty whenever
+    // data changes, because they must be re-translated. Direct buffers only need to be
+    // updated when the underlying ID3D11Buffer pointer changes - hopefully far less often.
+    OnBufferDataDirtyChannel *getStaticBroadcastChannel();
+    OnBufferDataDirtyChannel *getDirectBroadcastChannel();
+
+  private:
+    class BufferStorage;
+    class EmulatedIndexedStorage;
+    class NativeStorage;
+    class PackStorage;
+    class SystemMemoryStorage;
+
+    struct ConstantBufferCacheEntry
+    {
+        ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) {}
+
+        BufferStorage *storage;
+        unsigned int lruCount;
+    };
+
+    void markBufferUsage(BufferUsage usage);
+    gl::Error garbageCollection(BufferUsage currentUsage);
+    gl::ErrorOrResult<NativeStorage *> getStagingStorage();
+    gl::ErrorOrResult<PackStorage *> getPackStorage();
+    gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage();
+
+    gl::Error updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize);
+    gl::ErrorOrResult<BufferStorage *> getBufferStorage(BufferUsage usage);
+    gl::ErrorOrResult<BufferStorage *> getLatestBufferStorage() const;
+
+    gl::ErrorOrResult<BufferStorage *> getConstantBufferRangeStorage(GLintptr offset,
+                                                                     GLsizeiptr size);
+
+    BufferStorage *allocateStorage(BufferUsage usage);
+    void updateDeallocThreshold(BufferUsage usage);
+
+    // Free the storage if we decide it isn't being used very often.
+    gl::Error checkForDeallocation(BufferUsage usage);
+
+    // For some cases of uniform buffer storage, we can't deallocate system memory storage.
+    bool canDeallocateSystemMemory() const;
+
+    Renderer11 *mRenderer;
+    size_t mSize;
+
+    BufferStorage *mMappedStorage;
+
+    std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages;
+
+    // These two arrays are used to track when to free unused storage.
+    std::array<unsigned int, BUFFER_USAGE_COUNT> mDeallocThresholds;
+    std::array<unsigned int, BUFFER_USAGE_COUNT> mIdleness;
+
+    // Cache of D3D11 constant buffer for specific ranges of buffer data.
+    // This is used to emulate UBO ranges on 11.0 devices.
+    // Constant buffers are indexed by there start offset.
+    typedef std::map<GLintptr /*offset*/, ConstantBufferCacheEntry> ConstantBufferCache;
+    ConstantBufferCache mConstantBufferRangeStoragesCache;
+    size_t mConstantBufferStorageAdditionalSize;
+    unsigned int mMaxConstantBufferLruCount;
+
+    OnBufferDataDirtyChannel mStaticBroadcastChannel;
+    OnBufferDataDirtyChannel mDirectBroadcastChannel;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
new file mode 100644
index 0000000..b2f44a7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -0,0 +1,707 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Clear11.cpp: Framebuffer clear utility class.
+
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+
+#include <algorithm>
+
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "third_party/trace_event/trace_event.h"
+
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h"
+
+namespace rx
+{
+
+namespace
+{
+
+static constexpr uint32_t g_ConstantBufferSize = sizeof(RtvDsvClearInfo<float>);
+static constexpr uint32_t g_VertexSize         = sizeof(d3d11::PositionVertex);
+
+// Updates color, depth and alpha components of cached CB if necessary.
+// Returns true if any constants are updated, false otherwise.
+template <typename T>
+bool UpdateDataCache(RtvDsvClearInfo<T> *dataCache,
+                     const gl::Color<T> &color,
+                     const float *zValue,
+                     const uint32_t numRtvs,
+                     const uint8_t writeMask)
+{
+    bool cacheDirty = false;
+
+    if (numRtvs > 0)
+    {
+        const bool writeRGB = (writeMask & ~D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0;
+        if (writeRGB && memcmp(&dataCache->r, &color.red, sizeof(T) * 3) != 0)
+        {
+            dataCache->r = color.red;
+            dataCache->g = color.green;
+            dataCache->b = color.blue;
+            cacheDirty   = true;
+        }
+
+        const bool writeAlpha = (writeMask & D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0;
+        if (writeAlpha && (dataCache->a != color.alpha))
+        {
+            dataCache->a = color.alpha;
+            cacheDirty   = true;
+        }
+    }
+
+    if (zValue)
+    {
+        const float clampedZValue = gl::clamp01(*zValue);
+
+        if (clampedZValue != dataCache->z)
+        {
+            dataCache->z = clampedZValue;
+            cacheDirty   = true;
+        }
+    }
+
+    return cacheDirty;
+}
+}  // anonymous namespace
+
+Clear11::ShaderManager::ShaderManager()
+    : mIl9(nullptr),
+      mVs9(g_VS_Clear_FL9, ArraySize(g_VS_Clear_FL9), "Clear11 VS FL9"),
+      mPsFloat9(g_PS_ClearFloat_FL9, ArraySize(g_PS_ClearFloat_FL9), "Clear11 PS FloatFL9"),
+      mVs(g_VS_Clear, ArraySize(g_VS_Clear), "Clear11 VS"),
+      mPsFloat(g_PS_ClearFloat, ArraySize(g_PS_ClearFloat), "Clear11 PS Float"),
+      mPsUInt(g_PS_ClearUint, ArraySize(g_PS_ClearUint), "Clear11 PS UINT"),
+      mPsSInt(g_PS_ClearSint, ArraySize(g_PS_ClearSint), "Clear11 PS SINT")
+{
+}
+
+Clear11::ShaderManager::~ShaderManager()
+{
+    mVs9.release();
+    mPsFloat9.release();
+    mVs.release();
+    mPsFloat.release();
+    mPsUInt.release();
+    mPsSInt.release();
+}
+
+void Clear11::ShaderManager::getShadersAndLayout(ID3D11Device *device,
+                                                 D3D_FEATURE_LEVEL featureLevel,
+                                                 const INT clearType,
+                                                 ID3D11InputLayout **il,
+                                                 ID3D11VertexShader **vs,
+                                                 ID3D11PixelShader **ps)
+{
+    if (featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        ASSERT(clearType == GL_FLOAT);
+
+        *vs = mVs9.resolve(device);
+
+        if (mIl9.Get() == nullptr)
+        {
+            const D3D11_INPUT_ELEMENT_DESC ilDesc = {
+                "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0};
+
+            device->CreateInputLayout(&ilDesc, 1, g_VS_Clear_FL9, ArraySize(g_PS_ClearFloat_FL9),
+                                      mIl9.GetAddressOf());
+        }
+
+        *il = mIl9.Get();
+        *ps = mPsFloat9.resolve(device);
+        return;
+    }
+
+    *vs = mVs.resolve(device);
+    *il = nullptr;
+
+    switch (clearType)
+    {
+        case GL_FLOAT:
+            *ps = mPsFloat.resolve(device);
+            break;
+        case GL_UNSIGNED_INT:
+            *ps = mPsUInt.resolve(device);
+            break;
+        case GL_INT:
+            *ps = mPsSInt.resolve(device);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+Clear11::Clear11(Renderer11 *renderer)
+    : mRenderer(renderer),
+      mScissorEnabledRasterizerState(nullptr),
+      mScissorDisabledRasterizerState(nullptr),
+      mShaderManager(),
+      mConstantBuffer(nullptr),
+      mVertexBuffer(nullptr),
+      mShaderData({})
+{
+    TRACE_EVENT0("gpu.angle", "Clear11::Clear11");
+
+    HRESULT result;
+    ID3D11Device *device = renderer->getDevice();
+
+    static_assert((sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<int>)),
+                  "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<int>");
+
+    static_assert(
+        (sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<uint32_t>)),
+        "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<uint32_t>");
+
+    static_assert((sizeof(RtvDsvClearInfo<float>) % 16 == 0),
+                  "The size of RtvDsvClearInfo<float> should be a multiple of 16bytes.");
+
+    // Create constant buffer for color & depth data
+
+    D3D11_BUFFER_DESC bufferDesc;
+    bufferDesc.ByteWidth           = g_ConstantBufferSize;
+    bufferDesc.Usage               = D3D11_USAGE_DYNAMIC;
+    bufferDesc.BindFlags           = D3D11_BIND_CONSTANT_BUFFER;
+    bufferDesc.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
+    bufferDesc.MiscFlags           = 0;
+    bufferDesc.StructureByteStride = 0;
+
+    D3D11_SUBRESOURCE_DATA initialData;
+    initialData.pSysMem          = &mShaderData;
+    initialData.SysMemPitch      = g_ConstantBufferSize;
+    initialData.SysMemSlicePitch = g_ConstantBufferSize;
+
+    result = device->CreateBuffer(&bufferDesc, &initialData, mConstantBuffer.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    d3d11::SetDebugName(mConstantBuffer, "Clear11 Constant Buffer");
+
+    const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
+
+    if (featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        // Create vertex buffer with vertices for a quad covering the entire surface
+
+        static_assert((sizeof(d3d11::PositionVertex) % 16) == 0,
+                      "d3d11::PositionVertex should be a multiple of 16 bytes");
+        const d3d11::PositionVertex vbData[6] = {
+            {-1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, -1.0f, 0.0f, 1.0f},
+            {-1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f},  {1.0f, -1.0f, 0.0f, 1.0f}};
+
+        const UINT vbSize = sizeof(vbData);
+
+        bufferDesc.ByteWidth           = vbSize;
+        bufferDesc.Usage               = D3D11_USAGE_IMMUTABLE;
+        bufferDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
+        bufferDesc.CPUAccessFlags      = 0;
+        bufferDesc.MiscFlags           = 0;
+        bufferDesc.StructureByteStride = 0;
+
+        initialData.pSysMem          = vbData;
+        initialData.SysMemPitch      = vbSize;
+        initialData.SysMemSlicePitch = initialData.SysMemPitch;
+
+        result = device->CreateBuffer(&bufferDesc, &initialData, mVertexBuffer.GetAddressOf());
+        ASSERT(SUCCEEDED(result));
+        d3d11::SetDebugName(mVertexBuffer, "Clear11 Vertex Buffer");
+    }
+
+    // Create Rasterizer States
+    D3D11_RASTERIZER_DESC rsDesc;
+    rsDesc.FillMode              = D3D11_FILL_SOLID;
+    rsDesc.CullMode              = D3D11_CULL_NONE;
+    rsDesc.FrontCounterClockwise = FALSE;
+    rsDesc.DepthBias             = 0;
+    rsDesc.DepthBiasClamp        = 0.0f;
+    rsDesc.SlopeScaledDepthBias  = 0.0f;
+    rsDesc.DepthClipEnable       = TRUE;
+    rsDesc.ScissorEnable         = FALSE;
+    rsDesc.MultisampleEnable     = FALSE;
+    rsDesc.AntialiasedLineEnable = FALSE;
+
+    result = device->CreateRasterizerState(&rsDesc, mScissorDisabledRasterizerState.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    d3d11::SetDebugName(mScissorDisabledRasterizerState,
+                        "Clear11 Rasterizer State with scissor disabled");
+
+    rsDesc.ScissorEnable = TRUE;
+    result = device->CreateRasterizerState(&rsDesc, mScissorEnabledRasterizerState.GetAddressOf());
+    ASSERT(SUCCEEDED(result));
+    d3d11::SetDebugName(mScissorEnabledRasterizerState,
+                        "Clear11 Rasterizer State with scissor enabled");
+
+    // Initialize Depthstencil state with defaults
+    mDepthStencilStateKey.depthTest                = false;
+    mDepthStencilStateKey.depthMask                = false;
+    mDepthStencilStateKey.depthFunc                = GL_ALWAYS;
+    mDepthStencilStateKey.stencilWritemask         = static_cast<GLuint>(-1);
+    mDepthStencilStateKey.stencilBackWritemask     = static_cast<GLuint>(-1);
+    mDepthStencilStateKey.stencilBackMask          = static_cast<GLuint>(-1);
+    mDepthStencilStateKey.stencilTest              = false;
+    mDepthStencilStateKey.stencilMask              = static_cast<GLuint>(-1);
+    mDepthStencilStateKey.stencilFail              = GL_REPLACE;
+    mDepthStencilStateKey.stencilPassDepthFail     = GL_REPLACE;
+    mDepthStencilStateKey.stencilPassDepthPass     = GL_REPLACE;
+    mDepthStencilStateKey.stencilFunc              = GL_ALWAYS;
+    mDepthStencilStateKey.stencilBackFail          = GL_REPLACE;
+    mDepthStencilStateKey.stencilBackPassDepthFail = GL_REPLACE;
+    mDepthStencilStateKey.stencilBackPassDepthPass = GL_REPLACE;
+    mDepthStencilStateKey.stencilBackFunc          = GL_ALWAYS;
+
+    // Initialize BlendStateKey with defaults
+    mBlendStateKey.blendState.blend                 = false;
+    mBlendStateKey.blendState.sourceBlendRGB        = GL_ONE;
+    mBlendStateKey.blendState.sourceBlendAlpha      = GL_ONE;
+    mBlendStateKey.blendState.destBlendRGB          = GL_ZERO;
+    mBlendStateKey.blendState.destBlendAlpha        = GL_ZERO;
+    mBlendStateKey.blendState.blendEquationRGB      = GL_FUNC_ADD;
+    mBlendStateKey.blendState.blendEquationAlpha    = GL_FUNC_ADD;
+    mBlendStateKey.blendState.sampleAlphaToCoverage = false;
+    mBlendStateKey.blendState.dither                = true;
+    mBlendStateKey.mrt                              = false;
+    memset(mBlendStateKey.rtvMasks, 0, sizeof(mBlendStateKey.rtvMasks));
+}
+
+Clear11::~Clear11()
+{
+}
+
+gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
+                                    const gl::FramebufferState &fboData)
+{
+    const auto &colorAttachments  = fboData.getColorAttachments();
+    const auto &drawBufferStates  = fboData.getDrawBufferStates();
+    const gl::FramebufferAttachment *depthStencilAttachment = fboData.getDepthOrStencilAttachment();
+    RenderTarget11 *depthStencilRenderTarget                = nullptr;
+
+    ASSERT(colorAttachments.size() <= drawBufferStates.size());
+
+    if (clearParams.clearDepth || clearParams.clearStencil)
+    {
+        ASSERT(depthStencilAttachment != nullptr);
+        ANGLE_TRY(depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget));
+    }
+
+    // Iterate over the color buffers which require clearing and determine if they can be
+    // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView.
+    // This requires:
+    // 1) The render target is being cleared to a float value (will be cast to integer when clearing
+    // integer render targets as expected but does not work the other way around)
+    // 2) The format of the render target has no color channels that are currently masked out.
+    // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special
+    // work.
+    //
+    // If these conditions are met, and:
+    // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView.
+    // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available.
+    // Otherwise perform a shader based clear.
+    //
+    // Also determine if the DSV can be cleared withID3D11DeviceContext::ClearDepthStencilView by
+    // checking if the stencil write mask covers the entire stencil.
+    //
+    // To clear the remaining buffers, a shader based clear is performed:
+    // - The appropriate ShaderManagers (VS & PS) for the clearType is set
+    // - A CB containing the clear color and Z values is bound
+    // - An IL and VB are bound (for FL93 and below)
+    // - ScissorRect/Raststate/Viewport set as required
+    // - Blendstate set containing appropriate colorMasks
+    // - DepthStencilState set with appropriate parameters for a z or stencil clear if required
+    // - Color and/or Z buffers to be cleared are bound
+    // - Primitive covering entire clear area is drawn
+
+    gl::Extents framebufferSize;
+
+    if (depthStencilRenderTarget != nullptr)
+    {
+        framebufferSize = depthStencilRenderTarget->getExtents();
+    }
+    else
+    {
+        const auto colorAttachment = fboData.getFirstColorAttachment();
+
+        if (!colorAttachment)
+        {
+            UNREACHABLE();
+            return gl::InternalError();
+        }
+
+        framebufferSize = colorAttachment->getSize();
+    }
+
+    bool needScissoredClear = false;
+
+    if (clearParams.scissorEnabled)
+    {
+        if (clearParams.scissor.x >= framebufferSize.width ||
+            clearParams.scissor.y >= framebufferSize.height ||
+            clearParams.scissor.x + clearParams.scissor.width <= 0 ||
+            clearParams.scissor.y + clearParams.scissor.height <= 0 ||
+            clearParams.scissor.width == 0 || clearParams.scissor.height == 0)
+        {
+            // Scissor rect is outside the renderbuffer or is an empty rect
+            return gl::NoError();
+        }
+
+        needScissoredClear =
+            clearParams.scissor.x > 0 || clearParams.scissor.y > 0 ||
+            clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
+            clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height;
+    }
+
+    ID3D11DeviceContext *deviceContext   = mRenderer->getDeviceContext();
+    ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+
+    std::array<ID3D11RenderTargetView *, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvs;
+    std::array<uint8_t, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvMasks;
+    ID3D11DepthStencilView *dsv = nullptr;
+    uint32_t numRtvs            = 0;
+    const uint8_t colorMask =
+        gl_d3d11::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen,
+                                   clearParams.colorMaskBlue, clearParams.colorMaskAlpha);
+
+    for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size();
+         colorAttachmentIndex++)
+    {
+        const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex];
+
+        if (clearParams.clearColor[colorAttachmentIndex] && attachment.isAttached() &&
+            drawBufferStates[colorAttachmentIndex] != GL_NONE)
+        {
+            RenderTarget11 *renderTarget = nullptr;
+            ANGLE_TRY(attachment.getRenderTarget(&renderTarget));
+
+            const gl::InternalFormat &formatInfo = *attachment.getFormat().info;
+
+            if (clearParams.colorType == GL_FLOAT &&
+                !(formatInfo.componentType == GL_FLOAT ||
+                  formatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+                  formatInfo.componentType == GL_SIGNED_NORMALIZED))
+            {
+                ERR() << "It is undefined behaviour to clear a render buffer which is not "
+                         "normalized fixed point or floating-point to floating point values (color "
+                         "attachment "
+                      << colorAttachmentIndex << " has internal format " << attachment.getFormat()
+                      << ").";
+            }
+
+            if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
+                (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
+                (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
+                (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
+            {
+                // Every channel either does not exist in the render target or is masked out
+                continue;
+            }
+
+            const d3d11::RenderTargetView &framebufferRTV = renderTarget->getRenderTargetView();
+            if (!framebufferRTV.valid())
+            {
+                return gl::OutOfMemory()
+                       << "Clear11: Render target view pointer unexpectedly null.";
+            }
+
+            if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) ||
+                clearParams.colorType != GL_FLOAT ||
+                (formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
+                (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
+                (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
+                (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
+            {
+                rtvs[numRtvs]     = framebufferRTV.get();
+                rtvMasks[numRtvs] = gl_d3d11::GetColorMask(&formatInfo) & colorMask;
+                numRtvs++;
+            }
+            else
+            {
+                // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is
+                // possible
+
+                const auto &nativeFormat = renderTarget->getFormatSet().format();
+
+                // Check if the actual format has a channel that the internal format does not and
+                // set them to the default values
+                float clearValues[4] = {
+                    ((formatInfo.redBits == 0 && nativeFormat.redBits > 0)
+                         ? 0.0f
+                         : clearParams.colorF.red),
+                    ((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0)
+                         ? 0.0f
+                         : clearParams.colorF.green),
+                    ((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0)
+                         ? 0.0f
+                         : clearParams.colorF.blue),
+                    ((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0)
+                         ? 1.0f
+                         : clearParams.colorF.alpha),
+                };
+
+                if (formatInfo.alphaBits == 1)
+                {
+                    // Some drivers do not correctly handle calling Clear() on a format with 1-bit
+                    // alpha. They can incorrectly round all non-zero values up to 1.0f. Note that
+                    // WARP does not do this. We should handle the rounding for them instead.
+                    clearValues[3] = (clearParams.colorF.alpha >= 0.5f) ? 1.0f : 0.0f;
+                }
+
+                if (needScissoredClear)
+                {
+                    // We shouldn't reach here if deviceContext1 is unavailable.
+                    ASSERT(deviceContext1);
+
+                    D3D11_RECT rect;
+                    rect.left   = clearParams.scissor.x;
+                    rect.right  = clearParams.scissor.x + clearParams.scissor.width;
+                    rect.top    = clearParams.scissor.y;
+                    rect.bottom = clearParams.scissor.y + clearParams.scissor.height;
+
+                    deviceContext1->ClearView(framebufferRTV.get(), clearValues, &rect, 1);
+                    if (mRenderer->getWorkarounds().callClearTwiceOnSmallTarget)
+                    {
+                        if (clearParams.scissor.width <= 16 || clearParams.scissor.height <= 16)
+                        {
+                            deviceContext1->ClearView(framebufferRTV.get(), clearValues, &rect, 1);
+                        }
+                    }
+                }
+                else
+                {
+                    deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
+                    if (mRenderer->getWorkarounds().callClearTwiceOnSmallTarget)
+                    {
+                        if (framebufferSize.width <= 16 || framebufferSize.height <= 16)
+                        {
+                            deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (depthStencilRenderTarget)
+    {
+        dsv = depthStencilRenderTarget->getDepthStencilView();
+
+        if (!dsv)
+        {
+            return gl::OutOfMemory() << "Clear11: Depth stencil view pointer unexpectedly null.";
+        }
+
+        const auto &nativeFormat = depthStencilRenderTarget->getFormatSet().format();
+        const gl::FramebufferAttachment *stencilAttachment = fboData.getStencilAttachment();
+
+        uint32_t stencilUnmasked =
+            (stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0;
+        bool needMaskedStencilClear =
+            clearParams.clearStencil &&
+            (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+
+        if (!needScissoredClear && !needMaskedStencilClear)
+        {
+            const UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) |
+                                    (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
+            const FLOAT depthClear   = gl::clamp01(clearParams.depthValue);
+            const UINT8 stencilClear = clearParams.stencilValue & 0xFF;
+
+            deviceContext->ClearDepthStencilView(dsv, clearFlags, depthClear, stencilClear);
+
+            dsv = nullptr;
+        }
+    }
+
+    if (numRtvs == 0 && dsv == nullptr)
+    {
+        return gl::NoError();
+    }
+
+    // Clear the remaining render targets and depth stencil in one pass by rendering a quad:
+    //
+    // IA/VS: Vertices containing position and color members are passed through to the next stage.
+    // The vertex position has XY coordinates equal to clip extents and a Z component equal to the
+    // Z clear value. The vertex color contains the clear color.
+    //
+    // Rasterizer: Viewport scales the VS output over the entire surface and depending on whether
+    // or not scissoring is enabled the appropriate scissor rect and rasterizerState with or without
+    // the scissor test enabled is set as well.
+    //
+    // DepthStencilTest: DepthTesting, DepthWrites, StencilMask and StencilWrites will be enabled or
+    // disabled or set depending on what the input depthStencil clear parameters are. Since the PS
+    // is not writing out depth or rejecting pixels, this should happen prior to the PS stage.
+    //
+    // PS: Will write out the color values passed through from the previous stage to all outputs.
+    //
+    // OM: BlendState will perform the required color masking and output to RTV(s).
+
+    //
+    // ======================================================================================
+    //
+    // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render-
+    // buffer that is not normalized fixed point or floating point with floating point values
+    // are undefined so we can just write floats to them and D3D11 will bit cast them to
+    // integers.
+    //
+    // Also, we don't have to worry about attempting to clear a normalized fixed/floating point
+    // buffer with integer values because there is no gl API call which would allow it,
+    // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to
+    // be a compatible clear type.
+
+    ASSERT(numRtvs <= mRenderer->getNativeCaps().maxDrawBuffers);
+
+    const UINT sampleMask        = 0xFFFFFFFF;
+    ID3D11BlendState *blendState = nullptr;
+
+    if (numRtvs > 0)
+    {
+        // Setup BlendStateKey parameters
+        mBlendStateKey.blendState.colorMaskRed   = clearParams.colorMaskRed;
+        mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen;
+        mBlendStateKey.blendState.colorMaskBlue  = clearParams.colorMaskBlue;
+        mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha;
+        mBlendStateKey.mrt                       = numRtvs > 1;
+        memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks));
+
+        // Get BlendState
+        ANGLE_TRY(mRenderer->getStateCache().getBlendState(mBlendStateKey, &blendState));
+    }
+
+    const UINT stencilValue          = clearParams.stencilValue & 0xFF;
+    ID3D11DepthStencilState *dsState = nullptr;
+    const float *zValue              = nullptr;
+
+    if (dsv)
+    {
+        // Setup DepthStencilStateKey
+        mDepthStencilStateKey.depthTest        = clearParams.clearDepth;
+        mDepthStencilStateKey.depthMask        = clearParams.clearDepth;
+        mDepthStencilStateKey.stencilWritemask = clearParams.stencilWriteMask;
+        mDepthStencilStateKey.stencilTest      = clearParams.clearStencil;
+
+        // Get DepthStencilState
+        ANGLE_TRY(mRenderer->getStateCache().getDepthStencilState(mDepthStencilStateKey, &dsState));
+        zValue = clearParams.clearDepth ? &clearParams.depthValue : nullptr;
+    }
+
+    bool dirtyCb = false;
+
+    // Compare the input color/z values against the CB cache and update it if necessary
+    switch (clearParams.colorType)
+    {
+        case GL_FLOAT:
+            dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<float> *>(&mShaderData),
+                                      clearParams.colorF, zValue, numRtvs, colorMask);
+            break;
+        case GL_UNSIGNED_INT:
+            dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<uint32_t> *>(&mShaderData),
+                                      clearParams.colorUI, zValue, numRtvs, colorMask);
+            break;
+        case GL_INT:
+            dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<int> *>(&mShaderData),
+                                      clearParams.colorI, zValue, numRtvs, colorMask);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    if (dirtyCb)
+    {
+        // Update the constant buffer with the updated cache contents
+        // TODO(Shahmeer): Consider using UpdateSubresource1 D3D11_COPY_DISCARD where possible.
+        D3D11_MAPPED_SUBRESOURCE mappedResource;
+        HRESULT result = deviceContext->Map(mConstantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
+                                            &mappedResource);
+        if (FAILED(result))
+        {
+            return gl::OutOfMemory() << "Clear11: Failed to map CB, " << result;
+        }
+
+        memcpy(mappedResource.pData, &mShaderData, g_ConstantBufferSize);
+        deviceContext->Unmap(mConstantBuffer.Get(), 0);
+    }
+
+    // Set the viewport to be the same size as the framebuffer
+    D3D11_VIEWPORT viewport;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    viewport.Width    = static_cast<FLOAT>(framebufferSize.width);
+    viewport.Height   = static_cast<FLOAT>(framebufferSize.height);
+    viewport.MinDepth = 0;
+    viewport.MaxDepth = 1;
+    deviceContext->RSSetViewports(1, &viewport);
+
+    // Apply state
+    deviceContext->OMSetBlendState(blendState, nullptr, sampleMask);
+    deviceContext->OMSetDepthStencilState(dsState, stencilValue);
+
+    if (needScissoredClear)
+    {
+        const D3D11_RECT scissorRect = {clearParams.scissor.x, clearParams.scissor.y,
+                                        clearParams.scissor.x1(), clearParams.scissor.y1()};
+        deviceContext->RSSetScissorRects(1, &scissorRect);
+        deviceContext->RSSetState(mScissorEnabledRasterizerState.Get());
+    }
+    else
+    {
+        deviceContext->RSSetState(mScissorDisabledRasterizerState.Get());
+    }
+
+    // Get Shaders
+    const D3D_FEATURE_LEVEL fl = mRenderer->getRenderer11DeviceCaps().featureLevel;
+    ID3D11Device *device = mRenderer->getDevice();
+    ID3D11VertexShader *vs;
+    ID3D11InputLayout *il;
+    ID3D11PixelShader *ps;
+
+    mShaderManager.getShadersAndLayout(device, fl, clearParams.colorType, &il, &vs, &ps);
+
+    // Apply Shaders
+    deviceContext->VSSetShader(vs, nullptr, 0);
+    deviceContext->GSSetShader(nullptr, nullptr, 0);
+    deviceContext->PSSetShader(ps, nullptr, 0);
+    deviceContext->PSSetConstantBuffers(0, 1, mConstantBuffer.GetAddressOf());
+
+    // Bind IL & VB if needed
+    deviceContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
+    deviceContext->IASetInputLayout(il);
+
+    if (mVertexBuffer.Get())
+    {
+        const UINT offset = 0;
+        deviceContext->IASetVertexBuffers(0, 1, mVertexBuffer.GetAddressOf(), &g_VertexSize,
+                                          &offset);
+    }
+    else
+    {
+        deviceContext->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr);
+    }
+
+    deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+    // Apply render targets
+    mRenderer->getStateManager()->setOneTimeRenderTargets(&rtvs[0], numRtvs, dsv);
+
+    // Draw the fullscreen quad
+    deviceContext->Draw(6, 0);
+
+    // Clean up
+    mRenderer->markAllStateDirty();
+
+    return gl::NoError();
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h
new file mode 100644
index 0000000..c623a8a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h
@@ -0,0 +1,86 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Clear11.h: Framebuffer clear utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
+
+#include <map>
+#include <vector>
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+class Renderer11;
+class RenderTarget11;
+struct ClearParameters;
+
+template <typename T>
+struct RtvDsvClearInfo
+{
+    T r, g, b, a;
+    float z;
+    float c1padding[3];
+};
+
+class Clear11 : angle::NonCopyable
+{
+  public:
+    explicit Clear11(Renderer11 *renderer);
+    ~Clear11();
+
+    // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied.
+    gl::Error clearFramebuffer(const ClearParameters &clearParams,
+                               const gl::FramebufferState &fboData);
+
+  private:
+    class ShaderManager final : angle::NonCopyable
+    {
+      public:
+        ShaderManager();
+        ~ShaderManager();
+        void getShadersAndLayout(ID3D11Device *device,
+                                 D3D_FEATURE_LEVEL featureLevel,
+                                 const INT clearType,
+                                 ID3D11InputLayout **il,
+                                 ID3D11VertexShader **vs,
+                                 ID3D11PixelShader **ps);
+
+      private:
+        angle::ComPtr<ID3D11InputLayout> mIl9;
+        d3d11::LazyShader<ID3D11VertexShader> mVs9;
+        d3d11::LazyShader<ID3D11PixelShader> mPsFloat9;
+        d3d11::LazyShader<ID3D11VertexShader> mVs;
+        d3d11::LazyShader<ID3D11PixelShader> mPsFloat;
+        d3d11::LazyShader<ID3D11PixelShader> mPsUInt;
+        d3d11::LazyShader<ID3D11PixelShader> mPsSInt;
+    };
+
+    Renderer11 *mRenderer;
+
+    // States
+    angle::ComPtr<ID3D11RasterizerState> mScissorEnabledRasterizerState;
+    angle::ComPtr<ID3D11RasterizerState> mScissorDisabledRasterizerState;
+    gl::DepthStencilState mDepthStencilStateKey;
+    d3d11::BlendStateKey mBlendStateKey;
+
+    // Shaders and shader resources
+    ShaderManager mShaderManager;
+    angle::ComPtr<ID3D11Buffer> mConstantBuffer;
+    angle::ComPtr<ID3D11Buffer> mVertexBuffer;
+
+    // Buffer data and draw parameters
+    RtvDsvClearInfo<float> mShaderData;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
new file mode 100644
index 0000000..5a960fe
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
@@ -0,0 +1,288 @@
+//
+// Copyright 2016 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.
+//
+// Context11:
+//   D3D11-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+
+namespace rx
+{
+
+Context11::Context11(const gl::ContextState &state, Renderer11 *renderer)
+    : ContextImpl(state), mRenderer(renderer)
+{
+}
+
+Context11::~Context11()
+{
+}
+
+gl::Error Context11::initialize()
+{
+    return gl::NoError();
+}
+
+CompilerImpl *Context11::createCompiler()
+{
+    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT);
+    }
+    else
+    {
+        return new CompilerD3D(SH_HLSL_4_1_OUTPUT);
+    }
+}
+
+ShaderImpl *Context11::createShader(const gl::ShaderState &data)
+{
+    return new ShaderD3D(data, mRenderer->getWorkarounds());
+}
+
+ProgramImpl *Context11::createProgram(const gl::ProgramState &data)
+{
+    return new ProgramD3D(data, mRenderer);
+}
+
+FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data)
+{
+    return new Framebuffer11(data, mRenderer);
+}
+
+TextureImpl *Context11::createTexture(const gl::TextureState &state)
+{
+    switch (state.getTarget())
+    {
+        case GL_TEXTURE_2D:
+            return new TextureD3D_2D(state, mRenderer);
+        case GL_TEXTURE_CUBE_MAP:
+            return new TextureD3D_Cube(state, mRenderer);
+        case GL_TEXTURE_3D:
+            return new TextureD3D_3D(state, mRenderer);
+        case GL_TEXTURE_2D_ARRAY:
+            return new TextureD3D_2DArray(state, mRenderer);
+        case GL_TEXTURE_EXTERNAL_OES:
+            return new TextureD3D_External(state, mRenderer);
+        case GL_TEXTURE_2D_MULTISAMPLE:
+            return new TextureD3D_2DMultisample(state, mRenderer);
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return nullptr;
+}
+
+RenderbufferImpl *Context11::createRenderbuffer()
+{
+    return new RenderbufferD3D(mRenderer);
+}
+
+BufferImpl *Context11::createBuffer(const gl::BufferState &state)
+{
+    Buffer11 *buffer = new Buffer11(state, mRenderer);
+    mRenderer->onBufferCreate(buffer);
+    return buffer;
+}
+
+VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data)
+{
+    return new VertexArray11(data);
+}
+
+QueryImpl *Context11::createQuery(GLenum type)
+{
+    return new Query11(mRenderer, type);
+}
+
+FenceNVImpl *Context11::createFenceNV()
+{
+    return new FenceNV11(mRenderer);
+}
+
+FenceSyncImpl *Context11::createFenceSync()
+{
+    return new FenceSync11(mRenderer);
+}
+
+TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+    return new TransformFeedback11(state, mRenderer);
+}
+
+SamplerImpl *Context11::createSampler()
+{
+    return new SamplerD3D();
+}
+
+std::vector<PathImpl *> Context11::createPaths(GLsizei)
+{
+    return std::vector<PathImpl *>();
+}
+
+gl::Error Context11::flush()
+{
+    return mRenderer->flush();
+}
+
+gl::Error Context11::finish()
+{
+    return mRenderer->finish();
+}
+
+gl::Error Context11::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    return mRenderer->genericDrawArrays(this, mode, first, count, 0);
+}
+
+gl::Error Context11::drawArraysInstanced(GLenum mode,
+                                         GLint first,
+                                         GLsizei count,
+                                         GLsizei instanceCount)
+{
+    return mRenderer->genericDrawArrays(this, mode, first, count, instanceCount);
+}
+
+gl::Error Context11::drawElements(GLenum mode,
+                                  GLsizei count,
+                                  GLenum type,
+                                  const void *indices,
+                                  const gl::IndexRange &indexRange)
+{
+    return mRenderer->genericDrawElements(this, mode, count, type, indices, 0, indexRange);
+}
+
+gl::Error Context11::drawElementsInstanced(GLenum mode,
+                                           GLsizei count,
+                                           GLenum type,
+                                           const void *indices,
+                                           GLsizei instances,
+                                           const gl::IndexRange &indexRange)
+{
+    return mRenderer->genericDrawElements(this, mode, count, type, indices, instances, indexRange);
+}
+
+gl::Error Context11::drawRangeElements(GLenum mode,
+                                       GLuint start,
+                                       GLuint end,
+                                       GLsizei count,
+                                       GLenum type,
+                                       const void *indices,
+                                       const gl::IndexRange &indexRange)
+{
+    return mRenderer->genericDrawElements(this, mode, count, type, indices, 0, indexRange);
+}
+
+gl::Error Context11::drawArraysIndirect(GLenum mode, const void *indirect)
+{
+    return mRenderer->genericDrawIndirect(this, mode, GL_NONE, indirect);
+}
+
+gl::Error Context11::drawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+    return mRenderer->genericDrawIndirect(this, mode, type, indirect);
+}
+
+GLenum Context11::getResetStatus()
+{
+    return mRenderer->getResetStatus();
+}
+
+std::string Context11::getVendorString() const
+{
+    return mRenderer->getVendorString();
+}
+
+std::string Context11::getRendererDescription() const
+{
+    return mRenderer->getRendererDescription();
+}
+
+void Context11::insertEventMarker(GLsizei length, const char *marker)
+{
+    auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+    if (optionalString.valid())
+    {
+        mRenderer->getAnnotator()->setMarker(optionalString.value().data());
+    }
+}
+
+void Context11::pushGroupMarker(GLsizei length, const char *marker)
+{
+    auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+    if (optionalString.valid())
+    {
+        mRenderer->getAnnotator()->beginEvent(optionalString.value().data());
+    }
+}
+
+void Context11::popGroupMarker()
+{
+    mRenderer->getAnnotator()->endEvent();
+}
+
+void Context11::syncState(const gl::State::DirtyBits &dirtyBits)
+{
+    mRenderer->getStateManager()->syncState(mState.getState(), dirtyBits);
+}
+
+GLint Context11::getGPUDisjoint()
+{
+    return mRenderer->getGPUDisjoint();
+}
+
+GLint64 Context11::getTimestamp()
+{
+    return mRenderer->getTimestamp();
+}
+
+void Context11::onMakeCurrent(const gl::ContextState &data)
+{
+    mRenderer->getStateManager()->onMakeCurrent(data);
+}
+
+const gl::Caps &Context11::getNativeCaps() const
+{
+    return mRenderer->getNativeCaps();
+}
+
+const gl::TextureCapsMap &Context11::getNativeTextureCaps() const
+{
+    return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &Context11::getNativeExtensions() const
+{
+    return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &Context11::getNativeLimitations() const
+{
+    return mRenderer->getNativeLimitations();
+}
+
+gl::Error Context11::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+    return mRenderer->dispatchCompute(this, numGroupsX, numGroupsY, numGroupsZ);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h
new file mode 100644
index 0000000..6947877
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h
@@ -0,0 +1,132 @@
+//
+// Copyright 2016 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.
+//
+// Context11:
+//   D3D11-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Context11 : public ContextImpl
+{
+  public:
+    Context11(const gl::ContextState &state, Renderer11 *renderer);
+    ~Context11() override;
+
+    gl::Error initialize() override;
+
+    // Shader creation
+    CompilerImpl *createCompiler() override;
+    ShaderImpl *createShader(const gl::ShaderState &data) override;
+    ProgramImpl *createProgram(const gl::ProgramState &data) override;
+
+    // Framebuffer creation
+    FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override;
+
+    // Texture creation
+    TextureImpl *createTexture(const gl::TextureState &state) override;
+
+    // Renderbuffer creation
+    RenderbufferImpl *createRenderbuffer() override;
+
+    // Buffer creation
+    BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+    // Vertex Array creation
+    VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override;
+
+    // Query and Fence creation
+    QueryImpl *createQuery(GLenum type) override;
+    FenceNVImpl *createFenceNV() override;
+    FenceSyncImpl *createFenceSync() override;
+
+    // Transform Feedback creation
+    TransformFeedbackImpl *createTransformFeedback(
+        const gl::TransformFeedbackState &state) override;
+
+    // Sampler object creation
+    SamplerImpl *createSampler() override;
+
+    // Path object creation.
+    std::vector<PathImpl *> createPaths(GLsizei) override;
+
+    // Flush and finish.
+    gl::Error flush() override;
+    gl::Error finish() override;
+
+    // Drawing methods.
+    gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+    gl::Error drawArraysInstanced(GLenum mode,
+                                  GLint first,
+                                  GLsizei count,
+                                  GLsizei instanceCount) override;
+
+    gl::Error drawElements(GLenum mode,
+                           GLsizei count,
+                           GLenum type,
+                           const void *indices,
+                           const gl::IndexRange &indexRange) override;
+    gl::Error drawElementsInstanced(GLenum mode,
+                                    GLsizei count,
+                                    GLenum type,
+                                    const void *indices,
+                                    GLsizei instances,
+                                    const gl::IndexRange &indexRange) override;
+    gl::Error drawRangeElements(GLenum mode,
+                                GLuint start,
+                                GLuint end,
+                                GLsizei count,
+                                GLenum type,
+                                const void *indices,
+                                const gl::IndexRange &indexRange) override;
+    gl::Error drawArraysIndirect(GLenum mode, const void *indirect) override;
+    gl::Error drawElementsIndirect(GLenum mode, GLenum type, const void *indirect) override;
+
+    // Device loss
+    GLenum getResetStatus() override;
+
+    // Vendor and description strings.
+    std::string getVendorString() const override;
+    std::string getRendererDescription() const override;
+
+    // Debug markers.
+    void insertEventMarker(GLsizei length, const char *marker) override;
+    void pushGroupMarker(GLsizei length, const char *marker) override;
+    void popGroupMarker() override;
+
+    // State sync with dirty bits.
+    void syncState(const gl::State::DirtyBits &dirtyBits) override;
+
+    // Disjoint timer queries
+    GLint getGPUDisjoint() override;
+    GLint64 getTimestamp() override;
+
+    // Context switching
+    void onMakeCurrent(const gl::ContextState &data) override;
+
+    // Caps queries
+    const gl::Caps &getNativeCaps() const override;
+    const gl::TextureCapsMap &getNativeTextureCaps() const override;
+    const gl::Extensions &getNativeExtensions() const override;
+    const gl::Limitations &getNativeLimitations() const override;
+
+    Renderer11 *getRenderer() const { return mRenderer; }
+
+    gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
+
+  private:
+    Renderer11 *mRenderer;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
new file mode 100644
index 0000000..1e70363
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
@@ -0,0 +1,119 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator11.cpp: D3D11 helpers for adding trace annotations.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+DebugAnnotator11::DebugAnnotator11()
+    : mInitialized(false),
+      mD3d11Module(nullptr),
+      mUserDefinedAnnotation(nullptr)
+{
+    // D3D11 devices can't be created during DllMain.
+    // We defer device creation until the object is actually used.
+}
+
+DebugAnnotator11::~DebugAnnotator11()
+{
+    if (mInitialized)
+    {
+        SafeRelease(mUserDefinedAnnotation);
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+        FreeLibrary(mD3d11Module);
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+    }
+}
+
+void DebugAnnotator11::beginEvent(const wchar_t *eventName)
+{
+    initializeDevice();
+
+    if (mUserDefinedAnnotation != nullptr)
+    {
+        mUserDefinedAnnotation->BeginEvent(eventName);
+    }
+}
+
+void DebugAnnotator11::endEvent()
+{
+    initializeDevice();
+
+    if (mUserDefinedAnnotation != nullptr)
+    {
+        mUserDefinedAnnotation->EndEvent();
+    }
+}
+
+void DebugAnnotator11::setMarker(const wchar_t *markerName)
+{
+    initializeDevice();
+
+    if (mUserDefinedAnnotation != nullptr)
+    {
+        mUserDefinedAnnotation->SetMarker(markerName);
+    }
+}
+
+bool DebugAnnotator11::getStatus()
+{
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+    static_assert(NTDDI_VERSION >= NTDDI_WIN10, "GetStatus only works on Win10 and above");
+    initializeDevice();
+
+    if (mUserDefinedAnnotation != nullptr)
+    {
+        return !!(mUserDefinedAnnotation->GetStatus());
+    }
+
+    return true;  // Default if initializeDevice() failed
+#else
+    // We can't detect GetStatus() on desktop ANGLE builds so always return true.
+    return true;
+#endif  // ANGLE_ENABLE_WINDOWS_STORE
+}
+
+void DebugAnnotator11::initializeDevice()
+{
+    if (!mInitialized)
+    {
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+        mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+        ASSERT(mD3d11Module);
+
+        PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+        ASSERT(D3D11CreateDevice != nullptr);
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+
+        ID3D11Device *device = nullptr;
+        ID3D11DeviceContext *context = nullptr;
+
+        HRESULT hr = E_FAIL;
+
+        // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
+        hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0,
+                               D3D11_SDK_VERSION, &device, nullptr, &context);
+        ASSERT(SUCCEEDED(hr));
+        if (SUCCEEDED(hr))
+        {
+            mUserDefinedAnnotation = d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context);
+            ASSERT(mUserDefinedAnnotation != nullptr);
+            mInitialized = true;
+        }
+
+        SafeRelease(device);
+        SafeRelease(context);
+    }
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
new file mode 100644
index 0000000..62662c4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
@@ -0,0 +1,37 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator11.h: D3D11 helpers for adding trace annotations.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
+
+#include "libANGLE/LoggingAnnotator.h"
+
+namespace rx
+{
+
+class DebugAnnotator11 : public angle::LoggingAnnotator
+{
+  public:
+    DebugAnnotator11();
+    ~DebugAnnotator11() override;
+    void beginEvent(const wchar_t *eventName) override;
+    void endEvent() override;
+    void setMarker(const wchar_t *markerName) override;
+    bool getStatus() override;
+
+  private:
+    void initializeDevice();
+
+    bool mInitialized;
+    HMODULE mD3d11Module;
+    ID3DUserDefinedAnnotation *mUserDefinedAnnotation;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
new file mode 100644
index 0000000..bf980ed
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
@@ -0,0 +1,238 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement
+// rx::FenceNVImpl and rx::FenceSyncImpl.
+
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+#include "common/utilities.h"
+
+namespace rx
+{
+
+static const int kDeviceLostCheckPeriod = 64;
+
+//
+// Template helpers for set and test operations.
+//
+
+template <class FenceClass>
+gl::Error FenceSetHelper(FenceClass *fence)
+{
+    if (!fence->mQuery)
+    {
+        D3D11_QUERY_DESC queryDesc;
+        queryDesc.Query     = D3D11_QUERY_EVENT;
+        queryDesc.MiscFlags = 0;
+
+        HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.",
+                             result);
+        }
+    }
+
+    fence->mRenderer->getDeviceContext()->End(fence->mQuery);
+    return gl::NoError();
+}
+
+template <class FenceClass>
+gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean *outFinished)
+{
+    ASSERT(fence->mQuery);
+
+    UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
+    HRESULT result =
+        fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, nullptr, 0, getDataFlags);
+
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
+    }
+
+    ASSERT(result == S_OK || result == S_FALSE);
+    *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
+    return gl::NoError();
+}
+
+//
+// FenceNV11
+//
+
+FenceNV11::FenceNV11(Renderer11 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(nullptr)
+{
+}
+
+FenceNV11::~FenceNV11()
+{
+    SafeRelease(mQuery);
+}
+
+gl::Error FenceNV11::set(GLenum condition)
+{
+    return FenceSetHelper(this);
+}
+
+gl::Error FenceNV11::test(GLboolean *outFinished)
+{
+    return FenceTestHelper(this, true, outFinished);
+}
+
+gl::Error FenceNV11::finish()
+{
+    GLboolean finished = GL_FALSE;
+
+    int loopCount = 0;
+    while (finished != GL_TRUE)
+    {
+        loopCount++;
+        ANGLE_TRY(FenceTestHelper(this, true, &finished));
+
+        if (loopCount % kDeviceLostCheckPeriod == 0 && mRenderer->testDeviceLost())
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Device was lost while querying result of an event query.");
+        }
+
+        ScheduleYield();
+    }
+
+    return gl::NoError();
+}
+
+//
+// FenceSync11
+//
+
+// Important note on accurate timers in Windows:
+//
+// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call
+// as timeGetTime on laptops and "jumping" during certain hardware events.
+//
+// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc"
+//   https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc
+//
+// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer
+// from buggy implementations.
+
+FenceSync11::FenceSync11(Renderer11 *renderer)
+    : FenceSyncImpl(), mRenderer(renderer), mQuery(nullptr)
+{
+    LARGE_INTEGER counterFreqency = {};
+    BOOL success                  = QueryPerformanceFrequency(&counterFreqency);
+    ASSERT(success);
+
+    mCounterFrequency = counterFreqency.QuadPart;
+}
+
+FenceSync11::~FenceSync11()
+{
+    SafeRelease(mQuery);
+}
+
+gl::Error FenceSync11::set(GLenum condition, GLbitfield flags)
+{
+    ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0);
+    return FenceSetHelper(this);
+}
+
+gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+    ASSERT(outResult);
+
+    bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
+
+    GLboolean result = GL_FALSE;
+    gl::Error error  = FenceTestHelper(this, flushCommandBuffer, &result);
+    if (error.isError())
+    {
+        *outResult = GL_WAIT_FAILED;
+        return error;
+    }
+
+    if (result == GL_TRUE)
+    {
+        *outResult = GL_ALREADY_SIGNALED;
+        return gl::NoError();
+    }
+
+    if (timeout == 0)
+    {
+        *outResult = GL_TIMEOUT_EXPIRED;
+        return gl::NoError();
+    }
+
+    LARGE_INTEGER currentCounter = {};
+    BOOL success                 = QueryPerformanceCounter(&currentCounter);
+    ASSERT(success);
+
+    LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
+    LONGLONG endCounter       = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
+
+    int loopCount = 0;
+    while (currentCounter.QuadPart < endCounter && !result)
+    {
+        loopCount++;
+        ScheduleYield();
+        success = QueryPerformanceCounter(&currentCounter);
+        ASSERT(success);
+
+        error = FenceTestHelper(this, flushCommandBuffer, &result);
+        if (error.isError())
+        {
+            *outResult = GL_WAIT_FAILED;
+            return error;
+        }
+
+        if ((loopCount % kDeviceLostCheckPeriod) == 0 && mRenderer->testDeviceLost())
+        {
+            *outResult = GL_WAIT_FAILED;
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Device was lost while querying result of an event query.");
+        }
+    }
+
+    if (currentCounter.QuadPart >= endCounter)
+    {
+        *outResult = GL_TIMEOUT_EXPIRED;
+    }
+    else
+    {
+        *outResult = GL_CONDITION_SATISFIED;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout)
+{
+    // Because our API is currently designed to be called from a single thread, we don't need to do
+    // extra work for a server-side fence. GPU commands issued after the fence is created will
+    // always be processed after the fence is signaled.
+    return gl::NoError();
+}
+
+gl::Error FenceSync11::getStatus(GLint *outResult)
+{
+    GLboolean result = GL_FALSE;
+    gl::Error error  = FenceTestHelper(this, false, &result);
+    if (error.isError())
+    {
+        // The spec does not specify any way to report errors during the status test (e.g. device
+        // lost) so we report the fence is unblocked in case of error or signaled.
+        *outResult = GL_SIGNALED;
+
+        return error;
+    }
+
+    *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED);
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h
new file mode 100644
index 0000000..5959788
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class FenceNV11 : public FenceNVImpl
+{
+  public:
+    explicit FenceNV11(Renderer11 *renderer);
+    ~FenceNV11() override;
+
+    gl::Error set(GLenum condition) override;
+    gl::Error test(GLboolean *outFinished) override;
+    gl::Error finish() override;
+
+  private:
+    template<class T> friend gl::Error FenceSetHelper(T *fence);
+    template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished);
+
+    Renderer11 *mRenderer;
+    ID3D11Query *mQuery;
+};
+
+class FenceSync11 : public FenceSyncImpl
+{
+  public:
+    explicit FenceSync11(Renderer11 *renderer);
+    ~FenceSync11() override;
+
+    gl::Error set(GLenum condition, GLbitfield flags) override;
+    gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override;
+    gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override;
+    gl::Error getStatus(GLint *outResult) override;
+
+  private:
+    template<class T> friend gl::Error FenceSetHelper(T *fence);
+    template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished);
+
+    Renderer11 *mRenderer;
+    ID3D11Query *mQuery;
+    LONGLONG mCounterFrequency;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
new file mode 100644
index 0000000..4cbabbc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -0,0 +1,446 @@
+//
+// 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.
+//
+
+// Framebuffer11.cpp: Implements the Framebuffer11 class.
+
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+
+#include "common/debug.h"
+#include "common/bitset_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace
+{
+gl::Error MarkAttachmentsDirty(const gl::FramebufferAttachment *attachment)
+{
+    if (attachment && attachment->type() == GL_TEXTURE)
+    {
+        gl::Texture *texture = attachment->getTexture();
+
+        TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+
+        TextureStorage *texStorage = nullptr;
+        ANGLE_TRY(textureD3D->getNativeTexture(&texStorage));
+
+        if (texStorage)
+        {
+            TextureStorage11 *texStorage11 = GetAs<TextureStorage11>(texStorage);
+            ASSERT(texStorage11);
+
+            texStorage11->markLevelDirty(attachment->mipLevel());
+        }
+    }
+
+    return gl::NoError();
+}
+
+void UpdateCachedRenderTarget(const gl::FramebufferAttachment *attachment,
+                              RenderTarget11 *&cachedRenderTarget,
+                              OnRenderTargetDirtyBinding *channelBinding)
+{
+    RenderTarget11 *newRenderTarget = nullptr;
+    if (attachment)
+    {
+        attachment->getRenderTarget(&newRenderTarget);
+    }
+    if (newRenderTarget != cachedRenderTarget)
+    {
+        auto channel = (newRenderTarget ? newRenderTarget->getBroadcastChannel() : nullptr);
+        channelBinding->bind(channel);
+        cachedRenderTarget = newRenderTarget;
+    }
+}
+}  // anonymous namespace
+
+Framebuffer11::Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer)
+    : FramebufferD3D(data, renderer),
+      mRenderer(renderer),
+      mCachedDepthStencilRenderTarget(nullptr),
+      mDepthStencilRenderTargetDirty(this, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS)
+{
+    ASSERT(mRenderer != nullptr);
+    mCachedColorRenderTargets.fill(nullptr);
+    for (size_t colorIndex = 0; colorIndex < data.getColorAttachments().size(); ++colorIndex)
+    {
+        mColorRenderTargetsDirty.emplace_back(this, colorIndex);
+    }
+}
+
+Framebuffer11::~Framebuffer11()
+{
+}
+
+gl::Error Framebuffer11::markAttachmentsDirty() const
+{
+    for (const auto &colorAttachment : mState.getColorAttachments())
+    {
+        if (colorAttachment.isAttached())
+        {
+            ANGLE_TRY(MarkAttachmentsDirty(&colorAttachment));
+        }
+    }
+
+    ANGLE_TRY(MarkAttachmentsDirty(mState.getDepthAttachment()));
+    ANGLE_TRY(MarkAttachmentsDirty(mState.getStencilAttachment()));
+
+    return gl::NoError();
+}
+
+gl::Error Framebuffer11::clearImpl(ContextImpl *context, const ClearParameters &clearParams)
+{
+    Clear11 *clearer = mRenderer->getClearer();
+
+    const gl::FramebufferAttachment *colorAttachment = mState.getFirstColorAttachment();
+    if (clearParams.scissorEnabled == true && colorAttachment != nullptr &&
+        UsePresentPathFast(mRenderer, colorAttachment))
+    {
+        // If the current framebuffer is using the default colorbuffer, and present path fast is
+        // active, and the scissor rect is enabled, then we should invert the scissor rect
+        // vertically
+        ClearParameters presentPathFastClearParams = clearParams;
+        gl::Extents framebufferSize                = colorAttachment->getSize();
+        presentPathFastClearParams.scissor.y       = framebufferSize.height -
+                                               presentPathFastClearParams.scissor.y -
+                                               presentPathFastClearParams.scissor.height;
+        ANGLE_TRY(clearer->clearFramebuffer(presentPathFastClearParams, mState));
+    }
+    else
+    {
+        ANGLE_TRY(clearer->clearFramebuffer(clearParams, mState));
+    }
+
+    ANGLE_TRY(markAttachmentsDirty());
+
+    return gl::NoError();
+}
+
+gl::Error Framebuffer11::invalidate(size_t count, const GLenum *attachments)
+{
+    return invalidateBase(count, attachments, false);
+}
+
+gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments)
+{
+    return invalidateBase(count, attachments, true);
+}
+
+gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const
+{
+    ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+
+    if (!deviceContext1)
+    {
+        // DiscardView() is only supported on ID3D11DeviceContext1
+        return gl::NoError();
+    }
+
+    bool foundDepth = false;
+    bool foundStencil = false;
+
+    for (size_t i = 0; i < count; ++i)
+    {
+        switch (attachments[i])
+        {
+          // Handle depth and stencil attachments. Defer discarding until later.
+          case GL_DEPTH_STENCIL_ATTACHMENT:
+            foundDepth = true;
+            foundStencil = true;
+            break;
+          case GL_DEPTH_EXT:
+          case GL_DEPTH_ATTACHMENT:
+            foundDepth = true;
+            break;
+          case GL_STENCIL_EXT:
+          case GL_STENCIL_ATTACHMENT:
+            foundStencil = true;
+            break;
+          default:
+            {
+                // Handle color attachments
+                ASSERT((attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) ||
+                       (attachments[i] == GL_COLOR));
+
+                size_t colorIndex =
+                    (attachments[i] == GL_COLOR ? 0u : (attachments[i] - GL_COLOR_ATTACHMENT0));
+                auto colorAttachment = mState.getColorAttachment(colorIndex);
+                if (colorAttachment)
+                {
+                    ANGLE_TRY(invalidateAttachment(colorAttachment));
+                }
+                break;
+            }
+        }
+    }
+
+    bool discardDepth = false;
+    bool discardStencil = false;
+
+    // The D3D11 renderer uses the same view for depth and stencil buffers, so we must be careful.
+    if (useEXTBehavior)
+    {
+        // In the extension, if the app discards only one of the depth and stencil attachments, but
+        // those are backed by the same packed_depth_stencil buffer, then both images become undefined.
+        discardDepth = foundDepth;
+
+        // Don't bother discarding the stencil buffer if the depth buffer will already do it
+        discardStencil = foundStencil && (!discardDepth || mState.getDepthAttachment() == nullptr);
+    }
+    else
+    {
+        // In ES 3.0.4, if a specified attachment has base internal format DEPTH_STENCIL but the
+        // attachments list does not include DEPTH_STENCIL_ATTACHMENT or both DEPTH_ATTACHMENT and
+        // STENCIL_ATTACHMENT, then only the specified portion of every pixel in the subregion of pixels
+        // of the DEPTH_STENCIL buffer may be invalidated, and the other portion must be preserved.
+        discardDepth = (foundDepth && foundStencil) ||
+                       (foundDepth && (mState.getStencilAttachment() == nullptr));
+        discardStencil = (foundStencil && (mState.getDepthAttachment() == nullptr));
+    }
+
+    if (discardDepth && mState.getDepthAttachment())
+    {
+        ANGLE_TRY(invalidateAttachment(mState.getDepthAttachment()));
+    }
+
+    if (discardStencil && mState.getStencilAttachment())
+    {
+        ANGLE_TRY(invalidateAttachment(mState.getStencilAttachment()));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+{
+    // A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED()
+    return gl::NoError();
+}
+
+gl::Error Framebuffer11::invalidateAttachment(const gl::FramebufferAttachment *attachment) const
+{
+    ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+    ASSERT(deviceContext1);
+    ASSERT(attachment && attachment->isAttached());
+
+    RenderTarget11 *renderTarget = nullptr;
+    ANGLE_TRY(attachment->getRenderTarget(&renderTarget));
+    const auto &rtv = renderTarget->getRenderTargetView();
+
+    if (rtv.valid())
+    {
+        deviceContext1->DiscardView(rtv.get());
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area,
+                                        GLenum format,
+                                        GLenum type,
+                                        size_t outputPitch,
+                                        const gl::PixelPackState &pack,
+                                        uint8_t *pixels) const
+{
+    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+    ASSERT(readAttachment);
+
+    gl::Buffer *packBuffer = pack.pixelBuffer.get();
+    if (packBuffer != nullptr)
+    {
+        Buffer11 *packBufferStorage = GetImplAs<Buffer11>(packBuffer);
+        PackPixelsParams packParams(area, format, type, static_cast<GLuint>(outputPitch), pack,
+                                    reinterpret_cast<ptrdiff_t>(pixels));
+
+        return packBufferStorage->packPixels(*readAttachment, packParams);
+    }
+
+    return mRenderer->readFromAttachment(*readAttachment, area, format, type,
+                                         static_cast<GLuint>(outputPitch), pack, pixels);
+}
+
+gl::Error Framebuffer11::blitImpl(const gl::Rectangle &sourceArea,
+                                  const gl::Rectangle &destArea,
+                                  const gl::Rectangle *scissor,
+                                  bool blitRenderTarget,
+                                  bool blitDepth,
+                                  bool blitStencil,
+                                  GLenum filter,
+                                  const gl::Framebuffer *sourceFramebuffer)
+{
+    if (blitRenderTarget)
+    {
+        const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getReadColorbuffer();
+        ASSERT(readBuffer);
+
+        RenderTargetD3D *readRenderTarget = nullptr;
+        ANGLE_TRY(readBuffer->getRenderTarget(&readRenderTarget));
+        ASSERT(readRenderTarget);
+
+        const auto &colorAttachments = mState.getColorAttachments();
+        const auto &drawBufferStates = mState.getDrawBufferStates();
+
+        for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++)
+        {
+            const gl::FramebufferAttachment &drawBuffer = colorAttachments[colorAttachment];
+
+            if (drawBuffer.isAttached() &&
+                drawBufferStates[colorAttachment] != GL_NONE)
+            {
+                RenderTargetD3D *drawRenderTarget = nullptr;
+                ANGLE_TRY(drawBuffer.getRenderTarget(&drawRenderTarget));
+                ASSERT(drawRenderTarget);
+
+                const bool invertColorSource   = UsePresentPathFast(mRenderer, readBuffer);
+                gl::Rectangle actualSourceArea = sourceArea;
+                if (invertColorSource)
+                {
+                    RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
+                    actualSourceArea.y                 = readRenderTarget11->getHeight() - sourceArea.y;
+                    actualSourceArea.height            = -sourceArea.height;
+                }
+
+                const bool invertColorDest   = UsePresentPathFast(mRenderer, &drawBuffer);
+                gl::Rectangle actualDestArea = destArea;
+                if (invertColorDest)
+                {
+                    RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
+                    actualDestArea.y                   = drawRenderTarget11->getHeight() - destArea.y;
+                    actualDestArea.height              = -destArea.height;
+                }
+
+                ANGLE_TRY(mRenderer->blitRenderbufferRect(
+                    actualSourceArea, actualDestArea, readRenderTarget, drawRenderTarget, filter,
+                    scissor, blitRenderTarget, false, false));
+            }
+        }
+    }
+
+    if (blitDepth || blitStencil)
+    {
+        const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer();
+        ASSERT(readBuffer);
+
+        RenderTargetD3D *readRenderTarget = nullptr;
+        ANGLE_TRY(readBuffer->getRenderTarget(&readRenderTarget));
+        ASSERT(readRenderTarget);
+
+        const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
+        ASSERT(drawBuffer);
+
+        RenderTargetD3D *drawRenderTarget = nullptr;
+        ANGLE_TRY(drawBuffer->getRenderTarget(&drawRenderTarget));
+        ASSERT(drawRenderTarget);
+
+        ANGLE_TRY(mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget,
+                                                  drawRenderTarget, filter, scissor, false,
+                                                  blitDepth, blitStencil));
+    }
+
+    ANGLE_TRY(markAttachmentsDirty());
+    return gl::NoError();
+}
+
+GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+{
+    RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTarget);
+    return renderTarget11->getFormatSet().format().fboImplementationInternalFormat;
+}
+
+void Framebuffer11::updateColorRenderTarget(size_t colorIndex)
+{
+    UpdateCachedRenderTarget(mState.getColorAttachment(colorIndex),
+                             mCachedColorRenderTargets[colorIndex],
+                             &mColorRenderTargetsDirty[colorIndex]);
+}
+
+void Framebuffer11::updateDepthStencilRenderTarget()
+{
+    UpdateCachedRenderTarget(mState.getDepthOrStencilAttachment(), mCachedDepthStencilRenderTarget,
+                             &mDepthStencilRenderTargetDirty);
+}
+
+void Framebuffer11::syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+    mRenderer->getStateManager()->invalidateRenderTarget();
+
+    const auto &mergedDirtyBits = dirtyBits | mInternalDirtyBits;
+    mInternalDirtyBits.reset();
+
+    for (auto dirtyBit : mergedDirtyBits)
+    {
+        switch (dirtyBit)
+        {
+            case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
+            case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
+                updateDepthStencilRenderTarget();
+                break;
+            case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
+            case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
+                break;
+            default:
+            {
+                ASSERT(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
+                       dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
+                size_t colorIndex =
+                    static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
+                updateColorRenderTarget(colorIndex);
+                break;
+            }
+        }
+    }
+
+    // We should not have dirtied any additional state during our sync.
+    ASSERT(!mInternalDirtyBits.any());
+
+    FramebufferD3D::syncState(contextImpl, dirtyBits);
+}
+
+void Framebuffer11::signal(size_t channelID)
+{
+    if (channelID == gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS)
+    {
+        // Stencil is redundant in this case.
+        mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT);
+        mCachedDepthStencilRenderTarget = nullptr;
+    }
+    else
+    {
+        mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 + channelID);
+        mCachedColorRenderTargets[channelID] = nullptr;
+    }
+}
+
+gl::Error Framebuffer11::getSamplePosition(size_t index, GLfloat *xy) const
+{
+    UNIMPLEMENTED();
+    return gl::InternalError() << "getSamplePosition is unimplemented.";
+}
+
+bool Framebuffer11::hasAnyInternalDirtyBit() const
+{
+    return mInternalDirtyBits.any();
+}
+
+void Framebuffer11::syncInternalState(ContextImpl *contextImpl)
+{
+    syncState(contextImpl, gl::Framebuffer::DirtyBits());
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
new file mode 100644
index 0000000..383caf6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -0,0 +1,90 @@
+//
+// 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.
+//
+
+// Framebuffer11.h: Defines the Framebuffer11 class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
+
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/signal_utils.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Framebuffer11 : public FramebufferD3D, public OnRenderTargetDirtyReceiver
+{
+  public:
+    Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer);
+    virtual ~Framebuffer11();
+
+    gl::Error discard(size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(size_t count, const GLenum *attachments) override;
+    gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+
+    // Invalidate the cached swizzles of all bound texture attachments.
+    gl::Error markAttachmentsDirty() const;
+
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
+
+    const RenderTargetArray &getCachedColorRenderTargets() const
+    {
+        return mCachedColorRenderTargets;
+    }
+    const RenderTarget11 *getCachedDepthStencilRenderTarget() const
+    {
+        return mCachedDepthStencilRenderTarget;
+    }
+
+    bool hasAnyInternalDirtyBit() const;
+    void syncInternalState(ContextImpl *contextImpl);
+
+    void signal(size_t channelID) override;
+
+    gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
+
+  private:
+    gl::Error clearImpl(ContextImpl *context, const ClearParameters &clearParams) override;
+
+    gl::Error readPixelsImpl(const gl::Rectangle &area,
+                             GLenum format,
+                             GLenum type,
+                             size_t outputPitch,
+                             const gl::PixelPackState &pack,
+                             uint8_t *pixels) const override;
+
+    gl::Error blitImpl(const gl::Rectangle &sourceArea,
+                       const gl::Rectangle &destArea,
+                       const gl::Rectangle *scissor,
+                       bool blitRenderTarget,
+                       bool blitDepth,
+                       bool blitStencil,
+                       GLenum filter,
+                       const gl::Framebuffer *sourceFramebuffer) override;
+
+    gl::Error invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const;
+    gl::Error invalidateAttachment(const gl::FramebufferAttachment *attachment) const;
+
+    GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
+
+    void updateColorRenderTarget(size_t colorIndex);
+    void updateDepthStencilRenderTarget();
+
+    Renderer11 *const mRenderer;
+    RenderTargetArray mCachedColorRenderTargets;
+    RenderTarget11 *mCachedDepthStencilRenderTarget;
+
+    std::vector<OnRenderTargetDirtyBinding> mColorRenderTargetsDirty;
+    OnRenderTargetDirtyBinding mDepthStencilRenderTargetDirty;
+
+    gl::Framebuffer::DirtyBits mInternalDirtyBits;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
new file mode 100644
index 0000000..6b9998c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -0,0 +1,633 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image11.h: Implements the rx::Image11 class, which acts as the interface to
+// the actual underlying resources of a Texture
+
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+
+#include "common/utilities.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+
+namespace rx
+{
+
+Image11::Image11(Renderer11 *renderer)
+    : mRenderer(renderer),
+      mDXGIFormat(DXGI_FORMAT_UNKNOWN),
+      mStagingTexture(nullptr),
+      mStagingSubresource(0),
+      mRecoverFromStorage(false),
+      mAssociatedStorage(nullptr),
+      mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()),
+      mRecoveredFromStorageCount(0)
+{
+}
+
+Image11::~Image11()
+{
+    disassociateStorage();
+    releaseStagingTexture();
+}
+
+gl::Error Image11::generateMipmap(Image11 *dest,
+                                  Image11 *src,
+                                  const Renderer11DeviceCaps &rendererCaps)
+{
+    ASSERT(src->getDXGIFormat() == dest->getDXGIFormat());
+    ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth());
+    ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
+
+    D3D11_MAPPED_SUBRESOURCE destMapped;
+    ANGLE_TRY(dest->map(D3D11_MAP_WRITE, &destMapped));
+
+    D3D11_MAPPED_SUBRESOURCE srcMapped;
+    gl::Error error = src->map(D3D11_MAP_READ, &srcMapped);
+    if (error.isError())
+    {
+        dest->unmap();
+        return error;
+    }
+
+    const uint8_t *sourceData = reinterpret_cast<const uint8_t *>(srcMapped.pData);
+    uint8_t *destData         = reinterpret_cast<uint8_t *>(destMapped.pData);
+
+    auto mipGenerationFunction =
+        d3d11::Format::Get(src->getInternalFormat(), rendererCaps).format().mipGenerationFunction;
+    mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), sourceData,
+                          srcMapped.RowPitch, srcMapped.DepthPitch, destData, destMapped.RowPitch,
+                          destMapped.DepthPitch);
+
+    dest->unmap();
+    src->unmap();
+
+    dest->markDirty();
+
+    return gl::NoError();
+}
+
+bool Image11::isDirty() const
+{
+    // If mDirty is true AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be
+    // recovered from TextureStorage AND the texture doesn't require init data (i.e. a blank new
+    // texture will suffice) then isDirty should still return false.
+    if (mDirty && !mStagingTexture && !mRecoverFromStorage)
+    {
+        const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps();
+        const auto &formatInfo                 = d3d11::Format::Get(mInternalFormat, deviceCaps);
+        if (formatInfo.dataInitializerFunction == nullptr)
+        {
+            return false;
+        }
+    }
+
+    return mDirty;
+}
+
+gl::Error Image11::copyToStorage(TextureStorage *storage,
+                                 const gl::ImageIndex &index,
+                                 const gl::Box &region)
+{
+    TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
+
+    // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage
+    // multiple times, then we should just keep the staging texture around to prevent the copying
+    // from impacting perf. We allow the Image11 to copy its data to/from TextureStorage once. This
+    // accounts for an app making a late call to glGenerateMipmap.
+    bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2);
+
+    if (attemptToReleaseStagingTexture)
+    {
+        // If another image is relying on this Storage for its data, then we must let it recover its
+        // data before we overwrite it.
+        ANGLE_TRY(storage11->releaseAssociatedImage(index, this));
+    }
+
+    ID3D11Resource *stagingTexture       = nullptr;
+    unsigned int stagingSubresourceIndex = 0;
+    ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));
+    ANGLE_TRY(
+        storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region));
+
+    // Once the image data has been copied into the Storage, we can release it locally.
+    if (attemptToReleaseStagingTexture)
+    {
+        storage11->associateImage(this, index);
+        releaseStagingTexture();
+        mRecoverFromStorage   = true;
+        mAssociatedStorage    = storage11;
+        mAssociatedImageIndex = index;
+    }
+
+    return gl::NoError();
+}
+
+void Image11::verifyAssociatedStorageValid(TextureStorage11 *textureStorage) const
+{
+    ASSERT(mAssociatedStorage == textureStorage);
+}
+
+gl::Error Image11::recoverFromAssociatedStorage()
+{
+    if (mRecoverFromStorage)
+    {
+        ANGLE_TRY(createStagingTexture());
+
+        mAssociatedStorage->verifyAssociatedImageValid(mAssociatedImageIndex, this);
+
+        // CopySubResource from the Storage to the Staging texture
+        gl::Box region(0, 0, 0, mWidth, mHeight, mDepth);
+        ANGLE_TRY(mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource,
+                                                           mAssociatedImageIndex, region));
+        mRecoveredFromStorageCount += 1;
+
+        // Reset all the recovery parameters, even if the texture storage association is broken.
+        disassociateStorage();
+    }
+
+    return gl::NoError();
+}
+
+void Image11::disassociateStorage()
+{
+    if (mRecoverFromStorage)
+    {
+        // Make the texturestorage release the Image11 too
+        mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this);
+
+        mRecoverFromStorage   = false;
+        mAssociatedStorage    = nullptr;
+        mAssociatedImageIndex = gl::ImageIndex::MakeInvalid();
+    }
+}
+
+bool Image11::redefine(GLenum target,
+                       GLenum internalformat,
+                       const gl::Extents &size,
+                       bool forceRelease)
+{
+    if (mWidth != size.width || mHeight != size.height || mInternalFormat != internalformat ||
+        forceRelease)
+    {
+        // End the association with the TextureStorage, since that data will be out of date.
+        // Also reset mRecoveredFromStorageCount since this Image is getting completely redefined.
+        disassociateStorage();
+        mRecoveredFromStorageCount = 0;
+
+        mWidth          = size.width;
+        mHeight         = size.height;
+        mDepth          = size.depth;
+        mInternalFormat = internalformat;
+        mTarget         = target;
+
+        // compute the d3d format that will be used
+        const d3d11::Format &formatInfo =
+            d3d11::Format::Get(internalformat, mRenderer->getRenderer11DeviceCaps());
+        mDXGIFormat = formatInfo.texFormat;
+        mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
+
+        releaseStagingTexture();
+        mDirty = (formatInfo.dataInitializerFunction != nullptr);
+
+        return true;
+    }
+
+    return false;
+}
+
+DXGI_FORMAT Image11::getDXGIFormat() const
+{
+    // this should only happen if the image hasn't been redefined first
+    // which would be a bug by the caller
+    ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN);
+
+    return mDXGIFormat;
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as
+// format/type at input
+// into the target pixel rectangle.
+gl::Error Image11::loadData(const gl::Box &area,
+                            const gl::PixelUnpackState &unpack,
+                            GLenum type,
+                            const void *input,
+                            bool applySkipImages)
+{
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+    GLuint inputRowPitch                 = 0;
+    ANGLE_TRY_RESULT(
+        formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+        inputRowPitch);
+    GLuint inputDepthPitch = 0;
+    ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, unpack.imageHeight, inputRowPitch),
+                     inputDepthPitch);
+    GLuint inputSkipBytes = 0;
+    ANGLE_TRY_RESULT(
+        formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
+        inputSkipBytes);
+
+    const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
+    GLuint outputPixelSize                      = dxgiFormatInfo.pixelBytes;
+
+    const d3d11::Format &d3dFormatInfo =
+        d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+    LoadImageFunction loadFunction = d3dFormatInfo.getLoadFunctions()(type).loadFunction;
+
+    D3D11_MAPPED_SUBRESOURCE mappedImage;
+    ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage));
+
+    uint8_t *offsetMappedData = (reinterpret_cast<uint8_t *>(mappedImage.pData) +
+                                 (area.y * mappedImage.RowPitch + area.x * outputPixelSize +
+                                  area.z * mappedImage.DepthPitch));
+    loadFunction(area.width, area.height, area.depth,
+                 reinterpret_cast<const uint8_t *>(input) + inputSkipBytes, inputRowPitch,
+                 inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
+
+    unmap();
+
+    return gl::NoError();
+}
+
+gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input)
+{
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+    GLsizei inputRowPitch                = 0;
+    ANGLE_TRY_RESULT(formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0), inputRowPitch);
+    GLsizei inputDepthPitch = 0;
+    ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputRowPitch), inputDepthPitch);
+
+    const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
+    GLuint outputPixelSize                      = dxgiFormatInfo.pixelBytes;
+    GLuint outputBlockWidth                     = dxgiFormatInfo.blockWidth;
+    GLuint outputBlockHeight                    = dxgiFormatInfo.blockHeight;
+
+    ASSERT(area.x % outputBlockWidth == 0);
+    ASSERT(area.y % outputBlockHeight == 0);
+
+    const d3d11::Format &d3dFormatInfo =
+        d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+    LoadImageFunction loadFunction =
+        d3dFormatInfo.getLoadFunctions()(GL_UNSIGNED_BYTE).loadFunction;
+
+    D3D11_MAPPED_SUBRESOURCE mappedImage;
+    ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage));
+
+    uint8_t *offsetMappedData =
+        reinterpret_cast<uint8_t *>(mappedImage.pData) +
+        ((area.y / outputBlockHeight) * mappedImage.RowPitch +
+         (area.x / outputBlockWidth) * outputPixelSize + area.z * mappedImage.DepthPitch);
+
+    loadFunction(area.width, area.height, area.depth, reinterpret_cast<const uint8_t *>(input),
+                 inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch,
+                 mappedImage.DepthPitch);
+
+    unmap();
+
+    return gl::NoError();
+}
+
+gl::Error Image11::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source)
+{
+    TextureStorage11 *storage11 = GetAs<TextureStorage11>(source);
+
+    ID3D11Resource *resource = nullptr;
+    ANGLE_TRY(storage11->getResource(&resource));
+
+    UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex);
+    TextureHelper11 textureHelper =
+        TextureHelper11::MakeAndReference(resource, storage11->getFormatSet());
+
+    gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth);
+    return copyWithoutConversion(gl::Offset(), sourceBox, textureHelper, subresourceIndex);
+}
+
+gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset,
+                                       const gl::Rectangle &sourceArea,
+                                       const gl::Framebuffer *sourceFBO)
+{
+    const gl::FramebufferAttachment *srcAttachment = sourceFBO->getReadColorbuffer();
+    ASSERT(srcAttachment);
+
+    GLenum sourceInternalFormat = srcAttachment->getFormat().info->sizedInternalFormat;
+    const auto &d3d11Format =
+        d3d11::Format::Get(sourceInternalFormat, mRenderer->getRenderer11DeviceCaps());
+
+    if (d3d11Format.texFormat == mDXGIFormat && sourceInternalFormat == mInternalFormat)
+    {
+        RenderTargetD3D *renderTarget = nullptr;
+        ANGLE_TRY(srcAttachment->getRenderTarget(&renderTarget));
+
+        RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
+        ASSERT(rt11->getTexture());
+
+        TextureHelper11 textureHelper =
+            TextureHelper11::MakeAndReference(rt11->getTexture(), rt11->getFormatSet());
+        unsigned int sourceSubResource = rt11->getSubresourceIndex();
+
+        gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1);
+        return copyWithoutConversion(destOffset, sourceBox, textureHelper, sourceSubResource);
+    }
+
+    // This format requires conversion, so we must copy the texture to staging and manually convert
+    // via readPixels
+    D3D11_MAPPED_SUBRESOURCE mappedImage;
+    ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage));
+
+    // determine the offset coordinate into the destination buffer
+    const auto &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
+    GLsizei rowOffset          = dxgiFormatInfo.pixelBytes * destOffset.x;
+
+    uint8_t *dataOffset = static_cast<uint8_t *>(mappedImage.pData) +
+                          mappedImage.RowPitch * destOffset.y + rowOffset +
+                          destOffset.z * mappedImage.DepthPitch;
+
+    const gl::InternalFormat &destFormatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+    const auto &destD3D11Format =
+        d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+
+    auto loadFunction = destD3D11Format.getLoadFunctions()(destFormatInfo.type);
+    gl::Error error   = gl::NoError();
+    if (loadFunction.requiresConversion)
+    {
+        size_t bufferSize = destFormatInfo.pixelBytes * sourceArea.width * sourceArea.height;
+        angle::MemoryBuffer *memoryBuffer = nullptr;
+        mRenderer->getScratchMemoryBuffer(bufferSize, &memoryBuffer);
+        GLuint memoryBufferRowPitch = destFormatInfo.pixelBytes * sourceArea.width;
+
+        error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, destFormatInfo.format,
+                                              destFormatInfo.type, memoryBufferRowPitch,
+                                              gl::PixelPackState(), memoryBuffer->data());
+
+        loadFunction.loadFunction(sourceArea.width, sourceArea.height, 1, memoryBuffer->data(),
+                                  memoryBufferRowPitch, 0, dataOffset, mappedImage.RowPitch,
+                                  mappedImage.DepthPitch);
+    }
+    else
+    {
+        error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, destFormatInfo.format,
+                                              destFormatInfo.type, mappedImage.RowPitch,
+                                              gl::PixelPackState(), dataOffset);
+    }
+
+    unmap();
+    mDirty = true;
+
+    return error;
+}
+
+gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset,
+                                         const gl::Box &sourceArea,
+                                         const TextureHelper11 &textureHelper,
+                                         UINT sourceSubResource)
+{
+    // No conversion needed-- use copyback fastpath
+    ID3D11Resource *stagingTexture       = nullptr;
+    unsigned int stagingSubresourceIndex = 0;
+    ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));
+
+    ID3D11Device *device               = mRenderer->getDevice();
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    UINT subresourceAfterResolve = sourceSubResource;
+
+    ID3D11Resource *srcTex     = nullptr;
+    const gl::Extents &extents = textureHelper.getExtents();
+
+    bool needResolve =
+        (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1);
+
+    if (needResolve)
+    {
+        D3D11_TEXTURE2D_DESC resolveDesc;
+        resolveDesc.Width              = extents.width;
+        resolveDesc.Height             = extents.height;
+        resolveDesc.MipLevels          = 1;
+        resolveDesc.ArraySize          = 1;
+        resolveDesc.Format             = textureHelper.getFormat();
+        resolveDesc.SampleDesc.Count   = 1;
+        resolveDesc.SampleDesc.Quality = 0;
+        resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
+        resolveDesc.BindFlags          = 0;
+        resolveDesc.CPUAccessFlags     = 0;
+        resolveDesc.MiscFlags          = 0;
+
+        ID3D11Texture2D *srcTex2D = nullptr;
+        HRESULT result            = device->CreateTexture2D(&resolveDesc, nullptr, &srcTex2D);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.",
+                             result);
+        }
+        srcTex = srcTex2D;
+
+        deviceContext->ResolveSubresource(srcTex, 0, textureHelper.getTexture2D(),
+                                          sourceSubResource, textureHelper.getFormat());
+        subresourceAfterResolve = 0;
+    }
+    else
+    {
+        srcTex = textureHelper.getResource();
+    }
+
+    D3D11_BOX srcBox;
+    srcBox.left   = sourceArea.x;
+    srcBox.right  = sourceArea.x + sourceArea.width;
+    srcBox.top    = sourceArea.y;
+    srcBox.bottom = sourceArea.y + sourceArea.height;
+    srcBox.front  = sourceArea.z;
+    srcBox.back   = sourceArea.z + sourceArea.depth;
+
+    deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x,
+                                         destOffset.y, destOffset.z, srcTex,
+                                         subresourceAfterResolve, &srcBox);
+
+    if (needResolve)
+    {
+        SafeRelease(srcTex);
+    }
+
+    mDirty = true;
+    return gl::NoError();
+}
+
+gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture,
+                                     unsigned int *outSubresourceIndex)
+{
+    ANGLE_TRY(createStagingTexture());
+
+    *outStagingTexture   = mStagingTexture;
+    *outSubresourceIndex = mStagingSubresource;
+    return gl::NoError();
+}
+
+void Image11::releaseStagingTexture()
+{
+    SafeRelease(mStagingTexture);
+}
+
+gl::Error Image11::createStagingTexture()
+{
+    if (mStagingTexture)
+    {
+        return gl::NoError();
+    }
+
+    ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0);
+
+    const DXGI_FORMAT dxgiFormat = getDXGIFormat();
+
+    ID3D11Device *device = mRenderer->getDevice();
+    HRESULT result;
+
+    int lodOffset  = 1;
+    GLsizei width  = mWidth;
+    GLsizei height = mHeight;
+
+    // adjust size if needed for compressed textures
+    d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset);
+
+    if (mTarget == GL_TEXTURE_3D)
+    {
+        ID3D11Texture3D *newTexture = nullptr;
+
+        D3D11_TEXTURE3D_DESC desc;
+        desc.Width          = width;
+        desc.Height         = height;
+        desc.Depth          = mDepth;
+        desc.MipLevels      = lodOffset + 1;
+        desc.Format         = dxgiFormat;
+        desc.Usage          = D3D11_USAGE_STAGING;
+        desc.BindFlags      = 0;
+        desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+        desc.MiscFlags      = 0;
+
+        if (d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps())
+                .dataInitializerFunction != nullptr)
+        {
+            std::vector<D3D11_SUBRESOURCE_DATA> initialData;
+            std::vector<std::vector<BYTE>> textureData;
+            d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(),
+                                              width, height, mDepth, lodOffset + 1, &initialData,
+                                              &textureData);
+
+            result = device->CreateTexture3D(&desc, initialData.data(), &newTexture);
+        }
+        else
+        {
+            result = device->CreateTexture3D(&desc, nullptr, &newTexture);
+        }
+
+        if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.",
+                             result);
+        }
+
+        mStagingTexture     = newTexture;
+        mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+    }
+    else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY ||
+             mTarget == GL_TEXTURE_CUBE_MAP)
+    {
+        ID3D11Texture2D *newTexture = nullptr;
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width              = width;
+        desc.Height             = height;
+        desc.MipLevels          = lodOffset + 1;
+        desc.ArraySize          = 1;
+        desc.Format             = dxgiFormat;
+        desc.SampleDesc.Count   = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage              = D3D11_USAGE_STAGING;
+        desc.BindFlags          = 0;
+        desc.CPUAccessFlags     = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+        desc.MiscFlags          = 0;
+
+        if (d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps())
+                .dataInitializerFunction != nullptr)
+        {
+            std::vector<D3D11_SUBRESOURCE_DATA> initialData;
+            std::vector<std::vector<BYTE>> textureData;
+            d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(),
+                                              width, height, 1, lodOffset + 1, &initialData,
+                                              &textureData);
+
+            result = device->CreateTexture2D(&desc, initialData.data(), &newTexture);
+        }
+        else
+        {
+            result = device->CreateTexture2D(&desc, nullptr, &newTexture);
+        }
+
+        if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.",
+                             result);
+        }
+
+        mStagingTexture     = newTexture;
+        mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+
+    mDirty = false;
+    return gl::NoError();
+}
+
+gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
+{
+    // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
+    ANGLE_TRY(recoverFromAssociatedStorage());
+
+    ID3D11Resource *stagingTexture = nullptr;
+    unsigned int subresourceIndex  = 0;
+    ANGLE_TRY(getStagingTexture(&stagingTexture, &subresourceIndex));
+
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    ASSERT(mStagingTexture);
+    HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map);
+
+    if (FAILED(result))
+    {
+        // this can fail if the device is removed (from TDR)
+        if (d3d11::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+        }
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result);
+    }
+
+    mDirty = true;
+
+    return gl::NoError();
+}
+
+void Image11::unmap()
+{
+    if (mStagingTexture)
+    {
+        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+        deviceContext->Unmap(mStagingTexture, mStagingSubresource);
+    }
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
new file mode 100644
index 0000000..0373043
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image11.h: Defines the rx::Image11 class, which acts as the interface to
+// the actual underlying resources of a Texture
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
+
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+#include "libANGLE/ImageIndex.h"
+
+#include "common/debug.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer11;
+class TextureHelper11;
+class TextureStorage11;
+struct Renderer11DeviceCaps;
+
+class Image11 : public ImageD3D
+{
+  public:
+    Image11(Renderer11 *renderer);
+    virtual ~Image11();
+
+    static gl::Error generateMipmap(Image11 *dest,
+                                    Image11 *src,
+                                    const Renderer11DeviceCaps &rendererCaps);
+
+    virtual bool isDirty() const;
+
+    virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+
+    bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override;
+
+    DXGI_FORMAT getDXGIFormat() const;
+
+    gl::Error loadData(const gl::Box &area,
+                       const gl::PixelUnpackState &unpack,
+                       GLenum type,
+                       const void *input,
+                       bool applySkipImages) override;
+    gl::Error loadCompressedData(const gl::Box &area, const void *input) override;
+
+    gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override;
+    gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+                                  const gl::Rectangle &sourceArea,
+                                  const gl::Framebuffer *source) override;
+
+    gl::Error recoverFromAssociatedStorage();
+    void verifyAssociatedStorageValid(TextureStorage11 *textureStorage) const;
+    void disassociateStorage();
+
+  protected:
+    gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
+    void unmap();
+
+  private:
+    gl::Error copyWithoutConversion(const gl::Offset &destOffset,
+                                    const gl::Box &sourceArea,
+                                    const TextureHelper11 &textureHelper,
+                                    UINT sourceSubResource);
+
+    gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex);
+    gl::Error createStagingTexture();
+    void releaseStagingTexture();
+
+    Renderer11 *mRenderer;
+
+    DXGI_FORMAT mDXGIFormat;
+    ID3D11Resource *mStagingTexture;
+    unsigned int mStagingSubresource;
+
+    bool mRecoverFromStorage;
+    TextureStorage11 *mAssociatedStorage;
+    gl::ImageIndex mAssociatedImageIndex;
+    unsigned int mRecoveredFromStorageCount;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
new file mode 100644
index 0000000..3238c96
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
@@ -0,0 +1,167 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
+{
+    mBuffer       = nullptr;
+    mBufferSize = 0;
+    mDynamicUsage = false;
+}
+
+IndexBuffer11::~IndexBuffer11()
+{
+    SafeRelease(mBuffer);
+}
+
+gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
+{
+    SafeRelease(mBuffer);
+
+    updateSerial();
+
+    if (bufferSize > 0)
+    {
+        ID3D11Device* dxDevice = mRenderer->getDevice();
+
+        D3D11_BUFFER_DESC bufferDesc;
+        bufferDesc.ByteWidth = bufferSize;
+        bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+        bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+        bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+        bufferDesc.MiscFlags = 0;
+        bufferDesc.StructureByteStride = 0;
+
+        HRESULT result = dxDevice->CreateBuffer(&bufferDesc, nullptr, &mBuffer);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize);
+        }
+
+        if (dynamic)
+        {
+            d3d11::SetDebugName(mBuffer, "IndexBuffer11 (dynamic)");
+        }
+        else
+        {
+            d3d11::SetDebugName(mBuffer, "IndexBuffer11 (static)");
+        }
+    }
+
+    mBufferSize = bufferSize;
+    mIndexType = indexType;
+    mDynamicUsage = dynamic;
+
+    return gl::NoError();
+}
+
+gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
+{
+    if (!mBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+    }
+
+    // Check for integer overflows and out-out-bounds map requests
+    if (offset + size < offset || offset + size > mBufferSize)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Index buffer map range is not inside the buffer.");
+    }
+
+    ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result);
+    }
+
+    *outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset;
+    return gl::NoError();
+}
+
+gl::Error IndexBuffer11::unmapBuffer()
+{
+    if (!mBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+    }
+
+    ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+    dxContext->Unmap(mBuffer, 0);
+    return gl::NoError();
+}
+
+GLenum IndexBuffer11::getIndexType() const
+{
+    return mIndexType;
+}
+
+unsigned int IndexBuffer11::getBufferSize() const
+{
+    return mBufferSize;
+}
+
+gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType)
+{
+    if (bufferSize > mBufferSize || indexType != mIndexType)
+    {
+        return initialize(bufferSize, indexType, mDynamicUsage);
+    }
+    else
+    {
+        return gl::NoError();
+    }
+}
+
+gl::Error IndexBuffer11::discard()
+{
+    if (!mBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+    }
+
+    ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result);
+    }
+
+    dxContext->Unmap(mBuffer, 0);
+
+    return gl::NoError();
+}
+
+DXGI_FORMAT IndexBuffer11::getIndexFormat() const
+{
+    switch (mIndexType)
+    {
+      case GL_UNSIGNED_BYTE:    return DXGI_FORMAT_R16_UINT;
+      case GL_UNSIGNED_SHORT:   return DXGI_FORMAT_R16_UINT;
+      case GL_UNSIGNED_INT:     return DXGI_FORMAT_R32_UINT;
+      default: UNREACHABLE();   return DXGI_FORMAT_UNKNOWN;
+    }
+}
+
+ID3D11Buffer *IndexBuffer11::getBuffer() const
+{
+    return mBuffer;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
new file mode 100644
index 0000000..e730377
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
+
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+
+namespace rx
+{
+class Renderer11;
+
+class IndexBuffer11 : public IndexBuffer
+{
+  public:
+    explicit IndexBuffer11(Renderer11 *const renderer);
+    virtual ~IndexBuffer11();
+
+    virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+
+    virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
+    virtual gl::Error unmapBuffer();
+
+    virtual GLenum getIndexType() const;
+    virtual unsigned int getBufferSize() const;
+    virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType);
+
+    virtual gl::Error discard();
+
+    DXGI_FORMAT getIndexFormat() const;
+    ID3D11Buffer *getBuffer() const;
+
+  private:
+    Renderer11 *const mRenderer;
+
+    ID3D11Buffer *mBuffer;
+    unsigned int mBufferSize;
+    GLenum mIndexType;
+    bool mDynamicUsage;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
new file mode 100644
index 0000000..0008b10
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -0,0 +1,655 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches
+// D3D11 input layouts.
+
+#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "third_party/murmurhash/MurmurHash3.h"
+
+namespace rx
+{
+
+namespace
+{
+
+size_t GetReservedBufferCount(bool usesPointSpriteEmulation)
+{
+    return usesPointSpriteEmulation ? 1 : 0;
+}
+
+gl::InputLayout GetInputLayout(const std::vector<const TranslatedAttribute *> &translatedAttributes)
+{
+    gl::InputLayout inputLayout(translatedAttributes.size(), gl::VERTEX_FORMAT_INVALID);
+
+    for (size_t attributeIndex = 0; attributeIndex < translatedAttributes.size(); ++attributeIndex)
+    {
+        const TranslatedAttribute *translatedAttribute = translatedAttributes[attributeIndex];
+        inputLayout[attributeIndex]                    = gl::GetVertexFormatType(
+            *translatedAttribute->attribute, translatedAttribute->currentValueType);
+    }
+    return inputLayout;
+}
+
+GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, size_t index)
+{
+    // Count matrices differently
+    for (const sh::Attribute &attrib : shaderAttributes)
+    {
+        if (attrib.location == -1)
+        {
+            continue;
+        }
+
+        GLenum transposedType = gl::TransposeMatrixType(attrib.type);
+        int rows              = gl::VariableRowCount(transposedType);
+        int intIndex          = static_cast<int>(index);
+
+        if (intIndex >= attrib.location && intIndex < attrib.location + rows)
+        {
+            return transposedType;
+        }
+    }
+
+    UNREACHABLE();
+    return GL_NONE;
+}
+
+const unsigned int kDefaultCacheSize = 1024;
+
+struct PackedAttribute
+{
+    uint8_t attribType;
+    uint8_t semanticIndex;
+    uint8_t vertexFormatType;
+    uint8_t divisor;
+};
+
+Optional<size_t> FindFirstNonInstanced(
+    const std::vector<const TranslatedAttribute *> &currentAttributes)
+{
+    for (size_t index = 0; index < currentAttributes.size(); ++index)
+    {
+        if (currentAttributes[index]->divisor == 0)
+        {
+            return Optional<size_t>(index);
+        }
+    }
+
+    return Optional<size_t>::Invalid();
+}
+
+void SortAttributesByLayout(const gl::Program *program,
+                            const std::vector<TranslatedAttribute> &vertexArrayAttribs,
+                            const std::vector<TranslatedAttribute> &currentValueAttribs,
+                            AttribIndexArray *sortedD3DSemanticsOut,
+                            std::vector<const TranslatedAttribute *> *sortedAttributesOut)
+{
+    sortedAttributesOut->clear();
+
+    const auto &locationToSemantic =
+        GetImplAs<ProgramD3D>(program)->getAttribLocationToD3DSemantics();
+
+    for (auto locationIndex : program->getActiveAttribLocationsMask())
+    {
+        int d3dSemantic = locationToSemantic[locationIndex];
+        if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic))
+        {
+            sortedAttributesOut->resize(d3dSemantic + 1);
+        }
+
+        (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic;
+
+        const auto *arrayAttrib = &vertexArrayAttribs[locationIndex];
+        if (arrayAttrib->attribute && arrayAttrib->attribute->enabled)
+        {
+            (*sortedAttributesOut)[d3dSemantic] = arrayAttrib;
+        }
+        else
+        {
+            ASSERT(currentValueAttribs[locationIndex].attribute);
+            (*sortedAttributesOut)[d3dSemantic] = &currentValueAttribs[locationIndex];
+        }
+    }
+}
+
+} // anonymous namespace
+
+void InputLayoutCache::PackedAttributeLayout::addAttributeData(
+    GLenum glType,
+    UINT semanticIndex,
+    gl::VertexFormatType vertexFormatType,
+    unsigned int divisor)
+{
+    gl::AttributeType attribType = gl::GetAttributeType(glType);
+
+    PackedAttribute packedAttrib;
+    packedAttrib.attribType = static_cast<uint8_t>(attribType);
+    packedAttrib.semanticIndex = static_cast<uint8_t>(semanticIndex);
+    packedAttrib.vertexFormatType = static_cast<uint8_t>(vertexFormatType);
+    packedAttrib.divisor = static_cast<uint8_t>(divisor);
+
+    ASSERT(static_cast<gl::AttributeType>(packedAttrib.attribType) == attribType);
+    ASSERT(static_cast<UINT>(packedAttrib.semanticIndex) == semanticIndex);
+    ASSERT(static_cast<gl::VertexFormatType>(packedAttrib.vertexFormatType) == vertexFormatType);
+    ASSERT(static_cast<unsigned int>(packedAttrib.divisor) == divisor);
+
+    static_assert(sizeof(uint32_t) == sizeof(PackedAttribute), "PackedAttributes must be 32-bits exactly.");
+
+    attributeData[numAttributes++] = gl::bitCast<uint32_t>(packedAttrib);
+}
+
+bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLayout &other) const
+{
+    if (numAttributes != other.numAttributes)
+    {
+        return numAttributes < other.numAttributes;
+    }
+
+    if (flags != other.flags)
+    {
+        return flags < other.flags;
+    }
+
+    return memcmp(attributeData, other.attributeData, sizeof(uint32_t) * numAttributes) < 0;
+}
+
+InputLayoutCache::InputLayoutCache()
+    : mCurrentIL(nullptr),
+      mPointSpriteVertexBuffer(nullptr),
+      mPointSpriteIndexBuffer(nullptr),
+      mCacheSize(kDefaultCacheSize),
+      mDevice(nullptr),
+      mDeviceContext(nullptr)
+{
+    mCurrentBuffers.fill(nullptr);
+    mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
+    mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max());
+    mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
+}
+
+InputLayoutCache::~InputLayoutCache()
+{
+    clear();
+}
+
+void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context)
+{
+    clear();
+    mDevice = device;
+    mDeviceContext = context;
+    mFeatureLevel = device->GetFeatureLevel();
+}
+
+void InputLayoutCache::clear()
+{
+    for (auto &layout : mLayoutMap)
+    {
+        SafeRelease(layout.second);
+    }
+    mLayoutMap.clear();
+    SafeRelease(mPointSpriteVertexBuffer);
+    SafeRelease(mPointSpriteIndexBuffer);
+    markDirty();
+}
+
+void InputLayoutCache::markDirty()
+{
+    mCurrentIL = nullptr;
+    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        mCurrentBuffers[i]       = nullptr;
+        mCurrentVertexStrides[i] = static_cast<UINT>(-1);
+        mCurrentVertexOffsets[i] = static_cast<UINT>(-1);
+    }
+}
+
+gl::Error InputLayoutCache::applyVertexBuffers(
+    const gl::State &state,
+    const std::vector<TranslatedAttribute> &vertexArrayAttribs,
+    const std::vector<TranslatedAttribute> &currentValueAttribs,
+    GLenum mode,
+    GLint start,
+    TranslatedIndexData *indexInfo,
+    GLsizei numIndicesPerInstance)
+{
+    ASSERT(mDevice && mDeviceContext);
+
+    gl::Program *program   = state.getProgram();
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+    bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
+    bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS);
+
+    AttribIndexArray sortedSemanticIndices;
+    SortAttributesByLayout(program, vertexArrayAttribs, currentValueAttribs, &sortedSemanticIndices,
+                           &mCurrentAttributes);
+
+    // If we are using FL 9_3, make sure the first attribute is not instanced
+    if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty())
+    {
+        if (mCurrentAttributes[0]->divisor > 0)
+        {
+            Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes);
+            if (firstNonInstancedIndex.valid())
+            {
+                size_t index = firstNonInstancedIndex.value();
+                std::swap(mCurrentAttributes[0], mCurrentAttributes[index]);
+                std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
+            }
+        }
+    }
+
+    ANGLE_TRY(updateInputLayout(state, mode, sortedSemanticIndices, numIndicesPerInstance));
+
+    bool dirtyBuffers = false;
+    size_t minDiff    = gl::MAX_VERTEX_ATTRIBS;
+    size_t maxDiff    = 0;
+
+    // Note that if we use instance emulation, we reserve the first buffer slot.
+    size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites);
+
+    for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers);
+         ++attribIndex)
+    {
+        ID3D11Buffer *buffer = nullptr;
+        UINT vertexStride    = 0;
+        UINT vertexOffset    = 0;
+
+        if (attribIndex < mCurrentAttributes.size())
+        {
+            const auto &attrib      = *mCurrentAttributes[attribIndex];
+            Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr;
+
+            // If indexed pointsprite emulation is active, then we need to take a less efficent code path.
+            // Emulated indexed pointsprite rendering requires that the vertex buffers match exactly to
+            // the indices passed by the caller.  This could expand or shrink the vertex buffer depending
+            // on the number of points indicated by the index list or how many duplicates are found on the index list.
+            if (bufferStorage == nullptr)
+            {
+                ASSERT(attrib.vertexBuffer.get());
+                buffer = GetAs<VertexBuffer11>(attrib.vertexBuffer.get())->getBuffer();
+            }
+            else if (instancedPointSpritesActive && (indexInfo != nullptr))
+            {
+                if (indexInfo->srcIndexData.srcBuffer != nullptr)
+                {
+                    const uint8_t *bufferData = nullptr;
+                    ANGLE_TRY(indexInfo->srcIndexData.srcBuffer->getData(&bufferData));
+                    ASSERT(bufferData != nullptr);
+
+                    ptrdiff_t offset =
+                        reinterpret_cast<ptrdiff_t>(indexInfo->srcIndexData.srcIndices);
+                    indexInfo->srcIndexData.srcBuffer  = nullptr;
+                    indexInfo->srcIndexData.srcIndices = bufferData + offset;
+                }
+
+                ANGLE_TRY_RESULT(bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData,
+                                                                         attrib, start),
+                                 buffer);
+            }
+            else
+            {
+                ANGLE_TRY_RESULT(
+                    bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), buffer);
+            }
+
+            vertexStride = attrib.stride;
+            ANGLE_TRY_RESULT(attrib.computeOffset(start), vertexOffset);
+        }
+
+        size_t bufferIndex = reservedBuffers + attribIndex;
+
+        if (buffer != mCurrentBuffers[bufferIndex] ||
+            vertexStride != mCurrentVertexStrides[bufferIndex] ||
+            vertexOffset != mCurrentVertexOffsets[bufferIndex])
+        {
+            dirtyBuffers = true;
+            minDiff      = std::min(minDiff, bufferIndex);
+            maxDiff      = std::max(maxDiff, bufferIndex);
+
+            mCurrentBuffers[bufferIndex]       = buffer;
+            mCurrentVertexStrides[bufferIndex] = vertexStride;
+            mCurrentVertexOffsets[bufferIndex] = vertexOffset;
+        }
+    }
+
+    // Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs
+    // to be created and added to the list of current buffers, strides and offsets collections.
+    // This buffer contains the vertices for a single PointSprite quad.
+    // An index buffer also needs to be created and applied because rendering instanced data on
+    // D3D11 FL9_3 requires DrawIndexedInstanced() to be used. Shaders that contain gl_PointSize and
+    // used without the GL_POINTS rendering mode require a vertex buffer because some drivers cannot
+    // handle missing vertex data and will TDR the system.
+    if (programUsesInstancedPointSprites)
+    {
+        HRESULT result = S_OK;
+        const UINT pointSpriteVertexStride = sizeof(float) * 5;
+
+        if (!mPointSpriteVertexBuffer)
+        {
+            static const float pointSpriteVertices[] =
+            {
+                // Position        // TexCoord
+               -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
+               -1.0f,  1.0f, 0.0f, 0.0f, 0.0f,
+                1.0f,  1.0f, 0.0f, 1.0f, 0.0f,
+                1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
+               -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
+                1.0f,  1.0f, 0.0f, 1.0f, 0.0f,
+            };
+
+            D3D11_SUBRESOURCE_DATA vertexBufferData = { pointSpriteVertices, 0, 0 };
+            D3D11_BUFFER_DESC vertexBufferDesc;
+            vertexBufferDesc.ByteWidth = sizeof(pointSpriteVertices);
+            vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+            vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+            vertexBufferDesc.CPUAccessFlags = 0;
+            vertexBufferDesc.MiscFlags = 0;
+            vertexBufferDesc.StructureByteStride = 0;
+
+            result = mDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &mPointSpriteVertexBuffer);
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation vertex buffer, HRESULT: 0x%08x", result);
+            }
+        }
+
+        mCurrentBuffers[0] = mPointSpriteVertexBuffer;
+        // Set the stride to 0 if GL_POINTS mode is not being used to instruct the driver to avoid
+        // indexing into the vertex buffer.
+        mCurrentVertexStrides[0] = instancedPointSpritesActive ? pointSpriteVertexStride : 0;
+        mCurrentVertexOffsets[0] = 0;
+
+        // Update maxDiff to include the additional point sprite vertex buffer
+        // to ensure that IASetVertexBuffers uses the correct buffer count.
+        minDiff = 0;
+        maxDiff = std::max(maxDiff, static_cast<size_t>(0));
+
+        if (!mPointSpriteIndexBuffer)
+        {
+            // Create an index buffer and set it for pointsprite rendering
+            static const unsigned short pointSpriteIndices[] =
+            {
+                0, 1, 2, 3, 4, 5,
+            };
+
+            D3D11_SUBRESOURCE_DATA indexBufferData = { pointSpriteIndices, 0, 0 };
+            D3D11_BUFFER_DESC indexBufferDesc;
+            indexBufferDesc.ByteWidth = sizeof(pointSpriteIndices);
+            indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+            indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+            indexBufferDesc.CPUAccessFlags = 0;
+            indexBufferDesc.MiscFlags = 0;
+            indexBufferDesc.StructureByteStride = 0;
+
+            result = mDevice->CreateBuffer(&indexBufferDesc, &indexBufferData, &mPointSpriteIndexBuffer);
+            if (FAILED(result))
+            {
+                SafeRelease(mPointSpriteVertexBuffer);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation index buffer, HRESULT: 0x%08x", result);
+            }
+        }
+
+        if (instancedPointSpritesActive)
+        {
+            // The index buffer is applied here because Instanced PointSprite emulation uses the a
+            // non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer()
+            // on the renderer will not be called and setting this buffer here ensures that the
+            // rendering path will contain the correct index buffers.
+            mDeviceContext->IASetIndexBuffer(mPointSpriteIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
+        }
+    }
+
+    if (dirtyBuffers)
+    {
+        ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS);
+        mDeviceContext->IASetVertexBuffers(
+            static_cast<UINT>(minDiff), static_cast<UINT>(maxDiff - minDiff + 1),
+            &mCurrentBuffers[minDiff], &mCurrentVertexStrides[minDiff],
+            &mCurrentVertexOffsets[minDiff]);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
+                                                                        GLsizei emulatedInstanceId)
+{
+    size_t reservedBuffers = GetReservedBufferCount(true);
+    for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
+    {
+        const auto &attrib = *mCurrentAttributes[attribIndex];
+        size_t bufferIndex = reservedBuffers + attribIndex;
+
+        if (attrib.divisor > 0)
+        {
+            unsigned int offset = 0;
+            ANGLE_TRY_RESULT(attrib.computeOffset(startVertex), offset);
+            mCurrentVertexOffsets[bufferIndex] =
+                offset + (attrib.stride * (emulatedInstanceId / attrib.divisor));
+        }
+    }
+
+    mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, mCurrentBuffers.data(),
+                                       mCurrentVertexStrides.data(), mCurrentVertexOffsets.data());
+
+    return gl::NoError();
+}
+
+gl::Error InputLayoutCache::updateInputLayout(const gl::State &state,
+                                              GLenum mode,
+                                              const AttribIndexArray &sortedSemanticIndices,
+                                              GLsizei numIndicesPerInstance)
+{
+    gl::Program *program         = state.getProgram();
+    const auto &shaderAttributes = program->getAttributes();
+    PackedAttributeLayout layout;
+
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+    bool programUsesInstancedPointSprites =
+        programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
+    bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS);
+
+    if (programUsesInstancedPointSprites)
+    {
+        layout.flags |= PackedAttributeLayout::FLAG_USES_INSTANCED_SPRITES;
+    }
+
+    if (instancedPointSpritesActive)
+    {
+        layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE;
+    }
+
+    if (numIndicesPerInstance > 0)
+    {
+        layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE;
+    }
+
+    const auto &attribs            = state.getVertexArray()->getVertexAttributes();
+    const auto &bindings           = state.getVertexArray()->getVertexBindings();
+    const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics();
+
+    for (size_t attribIndex : program->getActiveAttribLocationsMask())
+    {
+        // Record the type of the associated vertex shader vector in our key
+        // This will prevent mismatched vertex shaders from using the same input layout
+        GLenum glslElementType = GetGLSLAttributeType(shaderAttributes, attribIndex);
+
+        const auto &attrib = attribs[attribIndex];
+        const auto &binding = bindings[attrib.bindingIndex];
+        int d3dSemantic    = locationToSemantic[attribIndex];
+
+        const auto &currentValue =
+            state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
+        gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValue.Type);
+
+        layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatType, binding.divisor);
+    }
+
+    ID3D11InputLayout *inputLayout = nullptr;
+    if (layout.numAttributes > 0 || layout.flags != 0)
+    {
+        auto layoutMapIt = mLayoutMap.find(layout);
+        if (layoutMapIt != mLayoutMap.end())
+        {
+            inputLayout = layoutMapIt->second;
+        }
+        else
+        {
+            ANGLE_TRY(createInputLayout(sortedSemanticIndices, mode, program, numIndicesPerInstance,
+                                        &inputLayout));
+            if (mLayoutMap.size() >= mCacheSize)
+            {
+                WARN() << "Overflowed the limit of " << mCacheSize
+                       << " input layouts, purging half the cache.";
+
+                // Randomly release every second element
+                auto it = mLayoutMap.begin();
+                while (it != mLayoutMap.end())
+                {
+                    it++;
+                    if (it != mLayoutMap.end())
+                    {
+                        // c++11 erase allows us to easily delete the current iterator.
+                        SafeRelease(it->second);
+                        it = mLayoutMap.erase(it);
+                    }
+                }
+            }
+
+            mLayoutMap[layout] = inputLayout;
+        }
+    }
+
+    if (inputLayout != mCurrentIL)
+    {
+        mDeviceContext->IASetInputLayout(inputLayout);
+        mCurrentIL = inputLayout;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error InputLayoutCache::createInputLayout(const AttribIndexArray &sortedSemanticIndices,
+                                              GLenum mode,
+                                              gl::Program *program,
+                                              GLsizei numIndicesPerInstance,
+                                              ID3D11InputLayout **inputLayoutOut)
+{
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+    bool programUsesInstancedPointSprites =
+        programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
+
+    unsigned int inputElementCount = 0;
+    std::array<D3D11_INPUT_ELEMENT_DESC, gl::MAX_VERTEX_ATTRIBS> inputElements;
+
+    for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
+    {
+        const auto &attrib    = *mCurrentAttributes[attribIndex];
+        const int sortedIndex = sortedSemanticIndices[attribIndex];
+
+        D3D11_INPUT_CLASSIFICATION inputClass =
+            attrib.divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
+
+        const auto &vertexFormatType =
+            gl::GetVertexFormatType(*attrib.attribute, attrib.currentValueType);
+        const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, mFeatureLevel);
+
+        auto *inputElement = &inputElements[inputElementCount];
+
+        inputElement->SemanticName         = "TEXCOORD";
+        inputElement->SemanticIndex        = sortedIndex;
+        inputElement->Format               = vertexFormatInfo.nativeFormat;
+        inputElement->InputSlot            = static_cast<UINT>(attribIndex);
+        inputElement->AlignedByteOffset    = 0;
+        inputElement->InputSlotClass       = inputClass;
+        inputElement->InstanceDataStepRate = attrib.divisor;
+
+        inputElementCount++;
+    }
+
+    // Instanced PointSprite emulation requires additional entries in the
+    // inputlayout to support the vertices that make up the pointsprite quad.
+    // We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the
+    // input layout must match the shader
+    if (programUsesInstancedPointSprites)
+    {
+        // On 9_3, we must ensure that slot 0 contains non-instanced data.
+        // If slot 0 currently contains instanced data then we swap it with a non-instanced element.
+        // Note that instancing is only available on 9_3 via ANGLE_instanced_arrays, since 9_3
+        // doesn't support OpenGL ES 3.0.
+        // As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced
+        // simultaneously, so a non-instanced element must exist.
+        for (size_t elementIndex = 0; elementIndex < inputElementCount; ++elementIndex)
+        {
+            // If rendering points and instanced pointsprite emulation is being used, the
+            // inputClass is required to be configured as per instance data
+            if (mode == GL_POINTS)
+            {
+                inputElements[elementIndex].InputSlotClass       = D3D11_INPUT_PER_INSTANCE_DATA;
+                inputElements[elementIndex].InstanceDataStepRate = 1;
+                if (numIndicesPerInstance > 0 && mCurrentAttributes[elementIndex]->divisor > 0)
+                {
+                    inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance;
+                }
+            }
+            inputElements[elementIndex].InputSlot++;
+        }
+
+        inputElements[inputElementCount].SemanticName         = "SPRITEPOSITION";
+        inputElements[inputElementCount].SemanticIndex        = 0;
+        inputElements[inputElementCount].Format               = DXGI_FORMAT_R32G32B32_FLOAT;
+        inputElements[inputElementCount].InputSlot            = 0;
+        inputElements[inputElementCount].AlignedByteOffset    = 0;
+        inputElements[inputElementCount].InputSlotClass       = D3D11_INPUT_PER_VERTEX_DATA;
+        inputElements[inputElementCount].InstanceDataStepRate = 0;
+        inputElementCount++;
+
+        inputElements[inputElementCount].SemanticName         = "SPRITETEXCOORD";
+        inputElements[inputElementCount].SemanticIndex        = 0;
+        inputElements[inputElementCount].Format               = DXGI_FORMAT_R32G32_FLOAT;
+        inputElements[inputElementCount].InputSlot            = 0;
+        inputElements[inputElementCount].AlignedByteOffset    = sizeof(float) * 3;
+        inputElements[inputElementCount].InputSlotClass       = D3D11_INPUT_PER_VERTEX_DATA;
+        inputElements[inputElementCount].InstanceDataStepRate = 0;
+        inputElementCount++;
+    }
+
+    const gl::InputLayout &shaderInputLayout = GetInputLayout(mCurrentAttributes);
+
+    ShaderExecutableD3D *shader = nullptr;
+    ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr));
+
+    ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader);
+
+    HRESULT result =
+        mDevice->CreateInputLayout(inputElements.data(), inputElementCount, shader11->getFunction(),
+                                   shader11->getLength(), inputLayoutOut);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to create internal input layout, HRESULT: 0x%08x", result);
+    }
+
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
new file mode 100644
index 0000000..62a1020
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches
+// D3D11 input layouts.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
+
+#include <GLES2/gl2.h>
+
+#include <cstddef>
+
+#include <array>
+#include <map>
+
+#include "common/angleutils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace gl
+{
+class Program;
+}
+
+namespace rx
+{
+struct TranslatedAttribute;
+struct TranslatedIndexData;
+struct SourceIndexData;
+class ProgramD3D;
+
+class InputLayoutCache : angle::NonCopyable
+{
+  public:
+    InputLayoutCache();
+    virtual ~InputLayoutCache();
+
+    void initialize(ID3D11Device *device, ID3D11DeviceContext *context);
+    void clear();
+    void markDirty();
+
+    gl::Error applyVertexBuffers(const gl::State &state,
+                                 const std::vector<TranslatedAttribute> &vertexArrayAttribs,
+                                 const std::vector<TranslatedAttribute> &currentValueAttribs,
+                                 GLenum mode,
+                                 GLint start,
+                                 TranslatedIndexData *indexInfo,
+                                 GLsizei numIndicesPerInstance);
+
+    gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
+                                                          GLsizei emulatedInstanceId);
+
+    // Useful for testing
+    void setCacheSize(unsigned int cacheSize) { mCacheSize = cacheSize; }
+
+  private:
+    struct PackedAttributeLayout
+    {
+        PackedAttributeLayout()
+            : numAttributes(0),
+              flags(0)
+        {
+        }
+
+        void addAttributeData(GLenum glType,
+                              UINT semanticIndex,
+                              gl::VertexFormatType vertexFormatType,
+                              unsigned int divisor);
+
+        bool operator<(const PackedAttributeLayout &other) const;
+
+        enum Flags
+        {
+            FLAG_USES_INSTANCED_SPRITES     = 0x1,
+            FLAG_INSTANCED_SPRITES_ACTIVE   = 0x2,
+            FLAG_INSTANCED_RENDERING_ACTIVE = 0x4,
+        };
+
+        size_t numAttributes;
+        unsigned int flags;
+        uint32_t attributeData[gl::MAX_VERTEX_ATTRIBS];
+    };
+
+    gl::Error updateInputLayout(const gl::State &state,
+                                GLenum mode,
+                                const AttribIndexArray &sortedSemanticIndices,
+                                GLsizei numIndicesPerInstance);
+    gl::Error createInputLayout(const AttribIndexArray &sortedSemanticIndices,
+                                GLenum mode,
+                                gl::Program *program,
+                                GLsizei numIndicesPerInstance,
+                                ID3D11InputLayout **inputLayoutOut);
+
+    std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap;
+
+    ID3D11InputLayout *mCurrentIL;
+    std::array<ID3D11Buffer *, gl::MAX_VERTEX_ATTRIBS> mCurrentBuffers;
+    std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexStrides;
+    std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexOffsets;
+    std::vector<const TranslatedAttribute *> mCurrentAttributes;
+
+    ID3D11Buffer *mPointSpriteVertexBuffer;
+    ID3D11Buffer *mPointSpriteIndexBuffer;
+
+    unsigned int mCacheSize;
+
+    ID3D11Device *mDevice;
+    ID3D11DeviceContext *mDeviceContext;
+    D3D_FEATURE_LEVEL mFeatureLevel;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h
new file mode 100644
index 0000000..ab234d4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// NativeWindow11.h: Defines NativeWindow11, a class for managing and performing operations on an
+// EGLNativeWindowType for the D3D11 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include "libANGLE/Config.h"
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace rx
+{
+
+class NativeWindow11 : public NativeWindowD3D
+{
+  public:
+    NativeWindow11(EGLNativeWindowType window) : NativeWindowD3D(window) {}
+
+    virtual HRESULT createSwapChain(ID3D11Device *device,
+                                    IDXGIFactory *factory,
+                                    DXGI_FORMAT format,
+                                    UINT width,
+                                    UINT height,
+                                    UINT samples,
+                                    IDXGISwapChain **swapChain) = 0;
+    virtual void commitChange() = 0;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
new file mode 100644
index 0000000..e82b7ba
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -0,0 +1,302 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PixelTransfer11.cpp:
+//   Implementation for buffer-to-texture and texture-to-buffer copies.
+//   Used to implement pixel transfers from unpack and to pack buffers.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/Texture.h"
+
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h"
+
+namespace rx
+{
+
+PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
+    : mRenderer(renderer),
+      mResourcesLoaded(false),
+      mBufferToTextureVS(nullptr),
+      mBufferToTextureGS(nullptr),
+      mParamsConstantBuffer(nullptr),
+      mCopyRasterizerState(nullptr),
+      mCopyDepthStencilState(nullptr)
+{
+}
+
+PixelTransfer11::~PixelTransfer11()
+{
+    for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
+    {
+        SafeRelease(shaderMapIt->second);
+    }
+
+    mBufferToTexturePSMap.clear();
+
+    SafeRelease(mBufferToTextureVS);
+    SafeRelease(mBufferToTextureGS);
+    SafeRelease(mParamsConstantBuffer);
+    SafeRelease(mCopyRasterizerState);
+    SafeRelease(mCopyDepthStencilState);
+}
+
+gl::Error PixelTransfer11::loadResources()
+{
+    if (mResourcesLoaded)
+    {
+        return gl::NoError();
+    }
+
+    HRESULT result = S_OK;
+    ID3D11Device *device = mRenderer->getDevice();
+
+    D3D11_RASTERIZER_DESC rasterDesc;
+    rasterDesc.FillMode = D3D11_FILL_SOLID;
+    rasterDesc.CullMode = D3D11_CULL_NONE;
+    rasterDesc.FrontCounterClockwise = FALSE;
+    rasterDesc.DepthBias = 0;
+    rasterDesc.SlopeScaledDepthBias = 0.0f;
+    rasterDesc.DepthBiasClamp = 0.0f;
+    rasterDesc.DepthClipEnable = TRUE;
+    rasterDesc.ScissorEnable = FALSE;
+    rasterDesc.MultisampleEnable = FALSE;
+    rasterDesc.AntialiasedLineEnable = FALSE;
+
+    result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer rasterizer state, result: 0x%X.", result);
+    }
+
+    D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
+    depthStencilDesc.DepthEnable = true;
+    depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+    depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
+    depthStencilDesc.StencilEnable = FALSE;
+    depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
+    depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
+    depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+    depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+    depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+
+    result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer depth stencil state, result: 0x%X.", result);
+    }
+
+    D3D11_BUFFER_DESC constantBufferDesc = { 0 };
+    constantBufferDesc.ByteWidth = roundUp<UINT>(sizeof(CopyShaderParams), 32u);
+    constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+    constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+    constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+    constantBufferDesc.MiscFlags = 0;
+    constantBufferDesc.StructureByteStride = 0;
+
+    result = device->CreateBuffer(&constantBufferDesc, nullptr, &mParamsConstantBuffer);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer constant buffer, result: 0x%X.", result);
+    }
+    d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer");
+
+    // init shaders
+    mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS");
+    if (!mBufferToTextureVS)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader.");
+    }
+
+    mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
+    if (!mBufferToTextureGS)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
+    }
+
+    ANGLE_TRY(buildShaderMap());
+
+    StructZero(&mParamsData);
+
+    mResourcesLoaded = true;
+
+    return gl::NoError();
+}
+
+void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat,
+                                                   const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut)
+{
+    StructZero(parametersOut);
+
+    float texelCenterX = 0.5f / static_cast<float>(destSize.width - 1);
+    float texelCenterY = 0.5f / static_cast<float>(destSize.height - 1);
+
+    unsigned int bytesPerPixel   = gl::GetSizedInternalFormatInfo(internalFormat).pixelBytes;
+    unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment);
+    unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel);
+
+    parametersOut->FirstPixelOffset     = offset / bytesPerPixel;
+    parametersOut->PixelsPerRow         = static_cast<unsigned int>((unpack.rowLength > 0) ? unpack.rowLength : destArea.width);
+    parametersOut->RowStride            = roundUp(parametersOut->PixelsPerRow, alignmentPixels);
+    parametersOut->RowsPerSlice         = static_cast<unsigned int>(destArea.height);
+    parametersOut->PositionOffset[0]    = texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
+    parametersOut->PositionOffset[1]    = texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f;
+    parametersOut->PositionScale[0]     = 2.0f / static_cast<float>(destSize.width);
+    parametersOut->PositionScale[1]     = -2.0f / static_cast<float>(destSize.height);
+    parametersOut->FirstSlice           = destArea.z;
+}
+
+gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
+                                               GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+{
+    ANGLE_TRY(loadResources());
+
+    gl::Extents destSize = destRenderTarget->getExtents();
+
+    ASSERT(destArea.x >= 0 && destArea.x + destArea.width  <= destSize.width  &&
+           destArea.y >= 0 && destArea.y + destArea.height <= destSize.height &&
+           destArea.z >= 0 && destArea.z + destArea.depth  <= destSize.depth  );
+
+    const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get();
+
+    ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat));
+
+    ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat);
+    ASSERT(pixelShader);
+
+    // The SRV must be in the proper read format, which may be different from the destination format
+    // EG: for half float data, we can load full precision floats with implicit conversion
+    GLenum unsizedFormat = gl::GetUnsizedFormat(destinationFormat);
+    const gl::InternalFormat &sourceglFormatInfo =
+        gl::GetInternalFormatInfo(unsizedFormat, sourcePixelsType);
+
+    const d3d11::Format &sourceFormatInfo = d3d11::Format::Get(
+        sourceglFormatInfo.sizedInternalFormat, mRenderer->getRenderer11DeviceCaps());
+    DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat;
+    ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
+    Buffer11 *bufferStorage11 = GetAs<Buffer11>(sourceBuffer.getImplementation());
+    ID3D11ShaderResourceView *bufferSRV = nullptr;
+    ANGLE_TRY_RESULT(bufferStorage11->getSRV(srvFormat), bufferSRV);
+    ASSERT(bufferSRV != nullptr);
+
+    const d3d11::RenderTargetView &textureRTV =
+        GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
+    ASSERT(textureRTV.valid());
+
+    CopyShaderParams shaderParams;
+    setBufferToTextureCopyParams(destArea, destSize, sourceglFormatInfo.sizedInternalFormat, unpack,
+                                 offset, &shaderParams);
+
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    ID3D11Buffer *nullBuffer = nullptr;
+    UINT zero = 0;
+
+    // Are we doing a 2D or 3D copy?
+    ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : nullptr);
+    auto stateManager                    = mRenderer->getStateManager();
+
+    deviceContext->VSSetShader(mBufferToTextureVS, nullptr, 0);
+    deviceContext->GSSetShader(geometryShader, nullptr, 0);
+    deviceContext->PSSetShader(pixelShader, nullptr, 0);
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV);
+    deviceContext->IASetInputLayout(nullptr);
+    deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
+
+    deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+    deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+    deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF);
+    deviceContext->RSSetState(mCopyRasterizerState);
+
+    stateManager->setOneTimeRenderTarget(textureRTV.get(), nullptr);
+
+    if (!StructEquals(mParamsData, shaderParams))
+    {
+        d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams);
+        mParamsData = shaderParams;
+    }
+
+    deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer);
+
+    // Set the viewport
+    D3D11_VIEWPORT viewport;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    viewport.Width = static_cast<FLOAT>(destSize.width);
+    viewport.Height = static_cast<FLOAT>(destSize.height);
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 1.0f;
+    deviceContext->RSSetViewports(1, &viewport);
+
+    UINT numPixels = (destArea.width * destArea.height * destArea.depth);
+    deviceContext->Draw(numPixels, 0);
+
+    // Unbind textures and render targets and vertex buffer
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+    deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer);
+
+    mRenderer->markAllStateDirty();
+
+    return gl::NoError();
+}
+
+gl::Error PixelTransfer11::buildShaderMap()
+{
+    ID3D11Device *device = mRenderer->getDevice();
+
+    mBufferToTexturePSMap[GL_FLOAT]        = d3d11::CompilePS(device, g_PS_BufferToTexture_4F,  "BufferToTexture RGBA ps");
+    mBufferToTexturePSMap[GL_INT]          = d3d11::CompilePS(device, g_PS_BufferToTexture_4I,  "BufferToTexture RGBA-I ps");
+    mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps");
+
+    // Check that all the shaders were created successfully
+    for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
+    {
+        if (shaderMapIt->second == nullptr)
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture pixel shader.");
+        }
+    }
+
+    return gl::NoError();
+}
+
+ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const
+{
+    GLenum componentType = gl::GetSizedInternalFormatInfo(internalFormat).componentType;
+    if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED)
+    {
+        componentType = GL_FLOAT;
+    }
+
+    auto shaderMapIt = mBufferToTexturePSMap.find(componentType);
+    return (shaderMapIt == mBufferToTexturePSMap.end() ? nullptr : shaderMapIt->second);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
new file mode 100644
index 0000000..1672121
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PixelTransfer11.h:
+//   Buffer-to-Texture and Texture-to-Buffer data transfers.
+//   Used to implement pixel unpack and pixel pack buffers in ES3.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/platform.h"
+
+#include <GLES2/gl2.h>
+
+#include <map>
+
+namespace gl
+{
+
+class Buffer;
+struct Box;
+struct Extents;
+struct PixelUnpackState;
+
+}
+
+namespace rx
+{
+class Renderer11;
+class RenderTargetD3D;
+
+class PixelTransfer11
+{
+  public:
+    explicit PixelTransfer11(Renderer11 *renderer);
+    ~PixelTransfer11();
+
+    // unpack: the source buffer is stored in the unpack state, and buffer strides
+    // offset: the start of the data within the unpack buffer
+    // destRenderTarget: individual slice/layer of a target texture
+    // destinationFormat/sourcePixelsType: determines shaders + shader parameters
+    // destArea: the sub-section of destRenderTarget to copy to
+    gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
+                                  GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+
+  private:
+
+    struct CopyShaderParams
+    {
+        unsigned int FirstPixelOffset;
+        unsigned int PixelsPerRow;
+        unsigned int RowStride;
+        unsigned int RowsPerSlice;
+        float PositionOffset[2];
+        float PositionScale[2];
+        int TexLocationOffset[2];
+        int TexLocationScale[2];
+        unsigned int FirstSlice;
+    };
+
+    static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat,
+                                             const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut);
+
+    gl::Error loadResources();
+    gl::Error buildShaderMap();
+    ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const;
+
+    Renderer11 *mRenderer;
+
+    bool mResourcesLoaded;
+    std::map<GLenum, ID3D11PixelShader *> mBufferToTexturePSMap;
+    ID3D11VertexShader *mBufferToTextureVS;
+    ID3D11GeometryShader *mBufferToTextureGS;
+    ID3D11Buffer *mParamsConstantBuffer;
+    CopyShaderParams mParamsData;
+
+    ID3D11RasterizerState *mCopyRasterizerState;
+    ID3D11DepthStencilState *mCopyDepthStencilState;
+
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
new file mode 100644
index 0000000..5c7961d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
@@ -0,0 +1,400 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl.
+
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+
+#include <GLES2/gl2ext.h>
+
+#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace
+{
+
+GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult)
+{
+    switch (type)
+    {
+        case GL_ANY_SAMPLES_PASSED:
+        case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+            return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
+
+        case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+            return currentResult + newResult;
+
+        case GL_TIME_ELAPSED_EXT:
+            return currentResult + newResult;
+
+        case GL_TIMESTAMP_EXT:
+            return newResult;
+
+        case GL_COMMANDS_COMPLETED_CHROMIUM:
+            return newResult;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+}  // anonymous namespace
+
+namespace rx
+{
+
+Query11::QueryState::QueryState()
+    : query(nullptr), beginTimestamp(nullptr), endTimestamp(nullptr), finished(false)
+{
+}
+
+Query11::QueryState::~QueryState()
+{
+    SafeRelease(beginTimestamp);
+    SafeRelease(endTimestamp);
+    SafeRelease(query);
+}
+
+Query11::Query11(Renderer11 *renderer, GLenum type)
+    : QueryImpl(type), mResult(0), mResultSum(0), mRenderer(renderer)
+{
+    mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
+}
+
+Query11::~Query11()
+{
+    mRenderer->getStateManager()->onDeleteQueryObject(this);
+}
+
+gl::Error Query11::begin()
+{
+    mResultSum = 0;
+    mRenderer->getStateManager()->onBeginQuery(this);
+    return resume();
+}
+
+gl::Error Query11::end()
+{
+    return pause();
+}
+
+gl::Error Query11::queryCounter()
+{
+    // This doesn't do anything for D3D11 as we don't support timestamps
+    ASSERT(getType() == GL_TIMESTAMP_EXT);
+    mResultSum = 0;
+    mPendingQueries.push_back(std::unique_ptr<QueryState>(new QueryState()));
+    return gl::NoError();
+}
+
+template <typename T>
+gl::Error Query11::getResultBase(T *params)
+{
+    ASSERT(mActiveQuery->query == nullptr);
+    ANGLE_TRY(flush(true));
+    ASSERT(mPendingQueries.empty());
+    *params = static_cast<T>(mResultSum);
+
+    return gl::NoError();
+}
+
+gl::Error Query11::getResult(GLint *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error Query11::getResult(GLuint *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error Query11::getResult(GLint64 *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error Query11::getResult(GLuint64 *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error Query11::isResultAvailable(bool *available)
+{
+    ANGLE_TRY(flush(false));
+
+    *available = mPendingQueries.empty();
+    return gl::NoError();
+}
+
+gl::Error Query11::pause()
+{
+    if (mActiveQuery->query != nullptr)
+    {
+        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+        GLenum queryType             = getType();
+
+        // If we are doing time elapsed query the end timestamp
+        if (queryType == GL_TIME_ELAPSED_EXT)
+        {
+            context->End(mActiveQuery->endTimestamp);
+        }
+
+        context->End(mActiveQuery->query);
+
+        mPendingQueries.push_back(std::move(mActiveQuery));
+        mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
+    }
+
+    return flush(false);
+}
+
+gl::Error Query11::resume()
+{
+    if (mActiveQuery->query == nullptr)
+    {
+        ANGLE_TRY(flush(false));
+
+        GLenum queryType         = getType();
+        D3D11_QUERY d3dQueryType = gl_d3d11::ConvertQueryType(queryType);
+
+        D3D11_QUERY_DESC queryDesc;
+        queryDesc.Query     = d3dQueryType;
+        queryDesc.MiscFlags = 0;
+
+        ID3D11Device *device = mRenderer->getDevice();
+
+        HRESULT result = device->CreateQuery(&queryDesc, &mActiveQuery->query);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
+                             result);
+        }
+
+        // If we are doing time elapsed we also need a query to actually query the timestamp
+        if (queryType == GL_TIME_ELAPSED_EXT)
+        {
+            D3D11_QUERY_DESC desc;
+            desc.Query     = D3D11_QUERY_TIMESTAMP;
+            desc.MiscFlags = 0;
+            result         = device->CreateQuery(&desc, &mActiveQuery->beginTimestamp);
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
+                                 result);
+            }
+            result = device->CreateQuery(&desc, &mActiveQuery->endTimestamp);
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
+                                 result);
+            }
+        }
+
+        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+        if (d3dQueryType != D3D11_QUERY_EVENT)
+        {
+            context->Begin(mActiveQuery->query);
+        }
+
+        // If we are doing time elapsed, query the begin timestamp
+        if (queryType == GL_TIME_ELAPSED_EXT)
+        {
+            context->End(mActiveQuery->beginTimestamp);
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Query11::flush(bool force)
+{
+    while (!mPendingQueries.empty())
+    {
+        QueryState *query = mPendingQueries.front().get();
+
+        do
+        {
+            ANGLE_TRY(testQuery(query));
+            if (!query->finished && !force)
+            {
+                return gl::NoError();
+            }
+        } while (!query->finished);
+
+        mResultSum = MergeQueryResults(getType(), mResultSum, mResult);
+        mPendingQueries.pop_front();
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Query11::testQuery(QueryState *queryState)
+{
+    if (!queryState->finished)
+    {
+        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+        switch (getType())
+        {
+            case GL_ANY_SAMPLES_PASSED_EXT:
+            case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+            {
+                ASSERT(queryState->query);
+                UINT64 numPixels = 0;
+                HRESULT result =
+                    context->GetData(queryState->query, &numPixels, sizeof(numPixels), 0);
+                if (FAILED(result))
+                {
+                    return gl::Error(GL_OUT_OF_MEMORY,
+                                     "Failed to get the data of an internal query, result: 0x%X.",
+                                     result);
+                }
+
+                if (result == S_OK)
+                {
+                    queryState->finished = true;
+                    mResult              = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+                }
+            }
+            break;
+
+            case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+            {
+                ASSERT(queryState->query);
+                D3D11_QUERY_DATA_SO_STATISTICS soStats = {0};
+                HRESULT result = context->GetData(queryState->query, &soStats, sizeof(soStats), 0);
+                if (FAILED(result))
+                {
+                    return gl::Error(GL_OUT_OF_MEMORY,
+                                     "Failed to get the data of an internal query, result: 0x%X.",
+                                     result);
+                }
+
+                if (result == S_OK)
+                {
+                    queryState->finished = true;
+                    mResult              = static_cast<GLuint64>(soStats.NumPrimitivesWritten);
+                }
+            }
+            break;
+
+            case GL_TIME_ELAPSED_EXT:
+            {
+                ASSERT(queryState->query);
+                ASSERT(queryState->beginTimestamp);
+                ASSERT(queryState->endTimestamp);
+                D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {0};
+                HRESULT result =
+                    context->GetData(queryState->query, &timeStats, sizeof(timeStats), 0);
+                if (FAILED(result))
+                {
+                    return gl::Error(GL_OUT_OF_MEMORY,
+                                     "Failed to get the data of an internal query, result: 0x%X.",
+                                     result);
+                }
+
+                if (result == S_OK)
+                {
+                    UINT64 beginTime = 0;
+                    HRESULT beginRes =
+                        context->GetData(queryState->beginTimestamp, &beginTime, sizeof(UINT64), 0);
+                    if (FAILED(beginRes))
+                    {
+                        return gl::Error(
+                            GL_OUT_OF_MEMORY,
+                            "Failed to get the data of an internal query, result: 0x%X.", beginRes);
+                    }
+                    UINT64 endTime = 0;
+                    HRESULT endRes =
+                        context->GetData(queryState->endTimestamp, &endTime, sizeof(UINT64), 0);
+                    if (FAILED(endRes))
+                    {
+                        return gl::Error(
+                            GL_OUT_OF_MEMORY,
+                            "Failed to get the data of an internal query, result: 0x%X.", endRes);
+                    }
+
+                    if (beginRes == S_OK && endRes == S_OK)
+                    {
+                        queryState->finished = true;
+                        if (timeStats.Disjoint)
+                        {
+                            mRenderer->setGPUDisjoint();
+                        }
+                        static_assert(sizeof(UINT64) == sizeof(unsigned long long),
+                                      "D3D UINT64 isn't 64 bits");
+
+                        angle::CheckedNumeric<UINT64> checkedTime(endTime);
+                        checkedTime -= beginTime;
+                        checkedTime *= 1000000000ull;
+                        checkedTime /= timeStats.Frequency;
+                        if (checkedTime.IsValid())
+                        {
+                            mResult = checkedTime.ValueOrDie();
+                        }
+                        else
+                        {
+                            mResult = std::numeric_limits<GLuint64>::max() / timeStats.Frequency;
+                            // If an overflow does somehow occur, there is no way the elapsed time
+                            // is accurate, so we generate a disjoint event
+                            mRenderer->setGPUDisjoint();
+                        }
+                    }
+                }
+            }
+            break;
+
+            case GL_TIMESTAMP_EXT:
+            {
+                // D3D11 doesn't support GL timestamp queries as D3D timestamps are not guaranteed
+                // to have any sort of continuity outside of a disjoint timestamp query block, which
+                // GL depends on
+                ASSERT(queryState->query == nullptr);
+                mResult              = 0;
+                queryState->finished = true;
+            }
+            break;
+
+            case GL_COMMANDS_COMPLETED_CHROMIUM:
+            {
+                ASSERT(queryState->query);
+                BOOL completed = 0;
+                HRESULT result =
+                    context->GetData(queryState->query, &completed, sizeof(completed), 0);
+                if (FAILED(result))
+                {
+                    return gl::Error(GL_OUT_OF_MEMORY,
+                                     "Failed to get the data of an internal query, result: 0x%X.",
+                                     result);
+                }
+
+                if (result == S_OK)
+                {
+                    queryState->finished = true;
+                    ASSERT(completed == TRUE);
+                    mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE;
+                }
+            }
+            break;
+
+            default:
+                UNREACHABLE();
+                break;
+        }
+
+        if (!queryState->finished && mRenderer->testDeviceLost())
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+        }
+    }
+
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
new file mode 100644
index 0000000..9b6fcf6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
@@ -0,0 +1,67 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
+
+#include <deque>
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Query11 : public QueryImpl
+{
+  public:
+    Query11(Renderer11 *renderer, GLenum type);
+    ~Query11() override;
+
+    gl::Error begin() override;
+    gl::Error end() override;
+    gl::Error queryCounter() override;
+    gl::Error getResult(GLint *params) override;
+    gl::Error getResult(GLuint *params) override;
+    gl::Error getResult(GLint64 *params) override;
+    gl::Error getResult(GLuint64 *params) override;
+    gl::Error isResultAvailable(bool *available) override;
+
+    gl::Error pause();
+    gl::Error resume();
+
+  private:
+    struct QueryState final : private angle::NonCopyable
+    {
+        QueryState();
+        ~QueryState();
+
+        ID3D11Query *query;
+        ID3D11Query *beginTimestamp;
+        ID3D11Query *endTimestamp;
+        bool finished;
+    };
+
+    gl::Error flush(bool force);
+    gl::Error testQuery(QueryState *queryState);
+
+    template <typename T>
+    gl::Error getResultBase(T *params);
+
+    GLuint64 mResult;
+    GLuint64 mResultSum;
+
+    Renderer11 *mRenderer;
+
+    std::unique_ptr<QueryState> mActiveQuery;
+    std::deque<std::unique_ptr<QueryState>> mPendingQueries;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
new file mode 100644
index 0000000..d2885ad
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
@@ -0,0 +1,483 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render
+// state objects.
+
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+
+#include <float.h>
+
+#include "common/debug.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "third_party/murmurhash/MurmurHash3.h"
+
+namespace rx
+{
+using namespace gl_d3d11;
+
+template <typename mapType>
+static void ClearStateMap(mapType &map)
+{
+    for (typename mapType::iterator i = map.begin(); i != map.end(); i++)
+    {
+        SafeRelease(i->second.first);
+    }
+    map.clear();
+}
+
+// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState,
+// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum
+// number of unique states of each type an application can create is 4096
+// TODO(ShahmeerEsmail): Revisit the cache sizes to make sure they are appropriate for most
+// scenarios.
+const unsigned int RenderStateCache::kMaxBlendStates        = 2048;
+const unsigned int RenderStateCache::kMaxRasterizerStates   = 2048;
+const unsigned int RenderStateCache::kMaxDepthStencilStates = 2048;
+const unsigned int RenderStateCache::kMaxSamplerStates      = 2048;
+
+RenderStateCache::RenderStateCache(Renderer11 *renderer)
+    : mRenderer(renderer),
+      mCounter(0),
+      mBlendStateCache(kMaxBlendStates, HashBlendState, CompareBlendStates),
+      mRasterizerStateCache(kMaxRasterizerStates, HashRasterizerState, CompareRasterizerStates),
+      mDepthStencilStateCache(kMaxDepthStencilStates,
+                              HashDepthStencilState,
+                              CompareDepthStencilStates),
+      mSamplerStateCache(kMaxSamplerStates, HashSamplerState, CompareSamplerStates),
+      mDevice(nullptr)
+{
+}
+
+RenderStateCache::~RenderStateCache()
+{
+    clear();
+}
+
+void RenderStateCache::initialize(ID3D11Device *device)
+{
+    clear();
+    mDevice = device;
+}
+
+void RenderStateCache::clear()
+{
+    ClearStateMap(mBlendStateCache);
+    ClearStateMap(mRasterizerStateCache);
+    ClearStateMap(mDepthStencilStateCache);
+    ClearStateMap(mSamplerStateCache);
+}
+
+// static
+std::size_t RenderStateCache::HashBlendState(const d3d11::BlendStateKey &blendState)
+{
+    static const unsigned int seed = 0xABCDEF98;
+
+    std::size_t hash = 0;
+    MurmurHash3_x86_32(&blendState, sizeof(d3d11::BlendStateKey), seed, &hash);
+    return hash;
+}
+
+// static
+bool RenderStateCache::CompareBlendStates(const d3d11::BlendStateKey &a,
+                                          const d3d11::BlendStateKey &b)
+{
+    return memcmp(&a, &b, sizeof(d3d11::BlendStateKey)) == 0;
+}
+
+// static
+d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Framebuffer *framebuffer,
+                                                        const gl::BlendState &blendState)
+{
+    d3d11::BlendStateKey key;
+    const FramebufferD3D *framebufferD3D   = GetImplAs<FramebufferD3D>(framebuffer);
+    const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender();
+    const UINT8 blendStateMask =
+        gl_d3d11::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
+                                   blendState.colorMaskBlue, blendState.colorMaskAlpha);
+
+    key.blendState = blendState;
+    key.mrt        = false;
+
+    for (size_t i = 0; i < colorbuffers.size(); i++)
+    {
+        const gl::FramebufferAttachment *attachment = colorbuffers[i];
+
+        if (attachment)
+        {
+            if (i > 0)
+            {
+                key.mrt = true;
+            }
+
+            key.rtvMasks[i] =
+                (gl_d3d11::GetColorMask(attachment->getFormat().info)) & blendStateMask;
+        }
+        else
+        {
+            key.rtvMasks[i] = 0;
+        }
+    }
+
+    for (size_t i = colorbuffers.size(); i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+    {
+        key.rtvMasks[i] = 0;
+    }
+
+    return key;
+}
+
+gl::Error RenderStateCache::getBlendState(const d3d11::BlendStateKey &key,
+                                          ID3D11BlendState **outBlendState)
+{
+    if (!mDevice)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+    }
+
+    BlendStateMap::iterator keyIter = mBlendStateCache.find(key);
+    if (keyIter != mBlendStateCache.end())
+    {
+        BlendStateCounterPair &state = keyIter->second;
+        state.second = mCounter++;
+        *outBlendState = state.first;
+        return gl::NoError();
+    }
+    else
+    {
+        if (mBlendStateCache.size() >= kMaxBlendStates)
+        {
+            WARN() << "Overflowed the limit of " << kMaxBlendStates
+                   << " blend states, removing the least recently used to make room.";
+
+            BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin();
+            for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
+            {
+                if (i->second.second < leastRecentlyUsed->second.second)
+                {
+                    leastRecentlyUsed = i;
+                }
+            }
+            SafeRelease(leastRecentlyUsed->second.first);
+            mBlendStateCache.erase(leastRecentlyUsed);
+        }
+
+        // Create a new blend state and insert it into the cache
+        D3D11_BLEND_DESC blendDesc;
+        D3D11_RENDER_TARGET_BLEND_DESC &rtDesc0 = blendDesc.RenderTarget[0];
+        const gl::BlendState &blendState        = key.blendState;
+
+        blendDesc.AlphaToCoverageEnable  = blendState.sampleAlphaToCoverage;
+        blendDesc.IndependentBlendEnable = key.mrt ? TRUE : FALSE;
+
+        rtDesc0 = {};
+
+        if (blendState.blend)
+        {
+            rtDesc0.BlendEnable    = true;
+            rtDesc0.SrcBlend       = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
+            rtDesc0.DestBlend      = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
+            rtDesc0.BlendOp        = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
+            rtDesc0.SrcBlendAlpha  = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
+            rtDesc0.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
+            rtDesc0.BlendOpAlpha   = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
+        }
+
+        rtDesc0.RenderTargetWriteMask = key.rtvMasks[0];
+
+        for (unsigned int i = 1; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+        {
+            blendDesc.RenderTarget[i]                       = rtDesc0;
+            blendDesc.RenderTarget[i].RenderTargetWriteMask = key.rtvMasks[i];
+        }
+
+        HRESULT result = mDevice->CreateBlendState(&blendDesc, outBlendState);
+        if (FAILED(result) || !(*outBlendState))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
+        }
+
+        mBlendStateCache.insert(std::make_pair(key, std::make_pair(*outBlendState, mCounter++)));
+
+        return gl::NoError();
+    }
+}
+
+// static
+std::size_t RenderStateCache::HashRasterizerState(const RasterizerStateKey &rasterState)
+{
+    static const unsigned int seed = 0xABCDEF98;
+
+    std::size_t hash = 0;
+    MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash);
+    return hash;
+}
+
+// static
+bool RenderStateCache::CompareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b)
+{
+    return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
+}
+
+gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled,
+                                               ID3D11RasterizerState **outRasterizerState)
+{
+    if (!mDevice)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+    }
+
+    RasterizerStateKey key = {};
+    key.rasterizerState = rasterState;
+    key.scissorEnabled = scissorEnabled;
+
+    RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key);
+    if (keyIter != mRasterizerStateCache.end())
+    {
+        RasterizerStateCounterPair &state = keyIter->second;
+        state.second = mCounter++;
+        *outRasterizerState = state.first;
+        return gl::NoError();
+    }
+    else
+    {
+        if (mRasterizerStateCache.size() >= kMaxRasterizerStates)
+        {
+            WARN() << "Overflowed the limit of " << kMaxRasterizerStates
+                   << " rasterizer states, removing the least recently used to make room.";
+
+            RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin();
+            for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
+            {
+                if (i->second.second < leastRecentlyUsed->second.second)
+                {
+                    leastRecentlyUsed = i;
+                }
+            }
+            SafeRelease(leastRecentlyUsed->second.first);
+            mRasterizerStateCache.erase(leastRecentlyUsed);
+        }
+
+        D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode);
+
+        // Disable culling if drawing points
+        if (rasterState.pointDrawMode)
+        {
+            cullMode = D3D11_CULL_NONE;
+        }
+
+        D3D11_RASTERIZER_DESC rasterDesc;
+        rasterDesc.FillMode = D3D11_FILL_SOLID;
+        rasterDesc.CullMode = cullMode;
+        rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE;
+        rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though.
+        rasterDesc.DepthClipEnable = TRUE;
+        rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
+        rasterDesc.MultisampleEnable = rasterState.multiSample;
+        rasterDesc.AntialiasedLineEnable = FALSE;
+
+        if (rasterState.polygonOffsetFill)
+        {
+            rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
+            rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits;
+        }
+        else
+        {
+            rasterDesc.SlopeScaledDepthBias = 0.0f;
+            rasterDesc.DepthBias = 0;
+        }
+
+        ID3D11RasterizerState *dx11RasterizerState = nullptr;
+        HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState);
+        if (FAILED(result) || !dx11RasterizerState)
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result);
+        }
+
+        mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++)));
+
+        *outRasterizerState = dx11RasterizerState;
+        return gl::NoError();
+    }
+}
+
+// static
+std::size_t RenderStateCache::HashDepthStencilState(const gl::DepthStencilState &dsState)
+{
+    static const unsigned int seed = 0xABCDEF98;
+
+    std::size_t hash = 0;
+    MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash);
+    return hash;
+}
+
+// static
+bool RenderStateCache::CompareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b)
+{
+    return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
+}
+
+gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &glState,
+                                                 ID3D11DepthStencilState **outDSState)
+{
+    if (!mDevice)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+    }
+
+    auto keyIter = mDepthStencilStateCache.find(glState);
+    if (keyIter != mDepthStencilStateCache.end())
+    {
+        DepthStencilStateCounterPair &state = keyIter->second;
+        state.second = mCounter++;
+        *outDSState = state.first;
+        return gl::NoError();
+    }
+
+    if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
+    {
+        WARN() << "Overflowed the limit of " << kMaxDepthStencilStates
+               << " depth stencil states, removing the least recently used to make room.";
+
+        auto leastRecentlyUsed = mDepthStencilStateCache.begin();
+        for (auto i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
+        {
+            if (i->second.second < leastRecentlyUsed->second.second)
+            {
+                leastRecentlyUsed = i;
+            }
+        }
+        SafeRelease(leastRecentlyUsed->second.first);
+        mDepthStencilStateCache.erase(leastRecentlyUsed);
+    }
+
+    D3D11_DEPTH_STENCIL_DESC dsDesc     = {0};
+    dsDesc.DepthEnable                  = glState.depthTest ? TRUE : FALSE;
+    dsDesc.DepthWriteMask               = ConvertDepthMask(glState.depthMask);
+    dsDesc.DepthFunc                    = ConvertComparison(glState.depthFunc);
+    dsDesc.StencilEnable                = glState.stencilTest ? TRUE : FALSE;
+    dsDesc.StencilReadMask              = ConvertStencilMask(glState.stencilMask);
+    dsDesc.StencilWriteMask             = ConvertStencilMask(glState.stencilWritemask);
+    dsDesc.FrontFace.StencilFailOp      = ConvertStencilOp(glState.stencilFail);
+    dsDesc.FrontFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilPassDepthFail);
+    dsDesc.FrontFace.StencilPassOp      = ConvertStencilOp(glState.stencilPassDepthPass);
+    dsDesc.FrontFace.StencilFunc        = ConvertComparison(glState.stencilFunc);
+    dsDesc.BackFace.StencilFailOp       = ConvertStencilOp(glState.stencilBackFail);
+    dsDesc.BackFace.StencilDepthFailOp  = ConvertStencilOp(glState.stencilBackPassDepthFail);
+    dsDesc.BackFace.StencilPassOp       = ConvertStencilOp(glState.stencilBackPassDepthPass);
+    dsDesc.BackFace.StencilFunc         = ConvertComparison(glState.stencilBackFunc);
+
+    ID3D11DepthStencilState *dx11DepthStencilState = nullptr;
+    HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
+    if (FAILED(result) || !dx11DepthStencilState)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
+    }
+
+    mDepthStencilStateCache.insert(
+        std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++)));
+
+    *outDSState = dx11DepthStencilState;
+    return gl::NoError();
+}
+
+// static
+std::size_t RenderStateCache::HashSamplerState(const gl::SamplerState &samplerState)
+{
+    static const unsigned int seed = 0xABCDEF98;
+
+    std::size_t hash = 0;
+    MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash);
+    return hash;
+}
+
+// static
+bool RenderStateCache::CompareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b)
+{
+    return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0;
+}
+
+gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState)
+{
+    if (!mDevice)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+    }
+
+    SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState);
+    if (keyIter != mSamplerStateCache.end())
+    {
+        SamplerStateCounterPair &state = keyIter->second;
+        state.second = mCounter++;
+        *outSamplerState = state.first;
+        return gl::NoError();
+    }
+    else
+    {
+        if (mSamplerStateCache.size() >= kMaxSamplerStates)
+        {
+            WARN() << "Overflowed the limit of " << kMaxSamplerStates
+                   << " sampler states, removing the least recently used to make room.";
+
+            SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin();
+            for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
+            {
+                if (i->second.second < leastRecentlyUsed->second.second)
+                {
+                    leastRecentlyUsed = i;
+                }
+            }
+            SafeRelease(leastRecentlyUsed->second.first);
+            mSamplerStateCache.erase(leastRecentlyUsed);
+        }
+
+        D3D11_SAMPLER_DESC samplerDesc;
+        samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter,
+                                                     samplerState.maxAnisotropy, samplerState.compareMode);
+        samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS);
+        samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT);
+        samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR);
+        samplerDesc.MipLODBias = 0;
+        samplerDesc.MaxAnisotropy =
+            gl_d3d11::ConvertMaxAnisotropy(samplerState.maxAnisotropy, mDevice->GetFeatureLevel());
+        samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc);
+        samplerDesc.BorderColor[0] = 0.0f;
+        samplerDesc.BorderColor[1] = 0.0f;
+        samplerDesc.BorderColor[2] = 0.0f;
+        samplerDesc.BorderColor[3] = 0.0f;
+        samplerDesc.MinLOD = samplerState.minLod;
+        samplerDesc.MaxLOD = samplerState.maxLod;
+
+        if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+        {
+            // Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support anything other than FLT_MAX.
+            // Note that Feature Level 9_* only supports GL ES 2.0, so the consumer of ANGLE can't modify the Max LOD themselves.
+            ASSERT(samplerState.maxLod >= 999.9f);
+
+            // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD workaround) should take account of this.
+            samplerDesc.MaxLOD = FLT_MAX;
+        }
+
+        ID3D11SamplerState *dx11SamplerState = nullptr;
+        HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState);
+        if (FAILED(result) || !dx11SamplerState)
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11SamplerState, HRESULT: 0x%X.", result);
+        }
+
+        mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++)));
+
+        *outSamplerState = dx11SamplerState;
+        return gl::NoError();
+    }
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
new file mode 100644
index 0000000..b998105
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render
+// state objects.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "common/angleutils.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include <unordered_map>
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer11;
+
+class RenderStateCache : angle::NonCopyable
+{
+  public:
+    RenderStateCache(Renderer11 *renderer);
+    virtual ~RenderStateCache();
+
+    void initialize(ID3D11Device *device);
+    void clear();
+
+    static d3d11::BlendStateKey GetBlendStateKey(const gl::Framebuffer *framebuffer,
+                                                 const gl::BlendState &blendState);
+    gl::Error getBlendState(const d3d11::BlendStateKey &key, ID3D11BlendState **outBlendState);
+    gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState);
+    gl::Error getDepthStencilState(const gl::DepthStencilState &dsState,
+                                   ID3D11DepthStencilState **outDSState);
+    gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState);
+
+  private:
+    Renderer11 *mRenderer;
+    unsigned long long mCounter;
+
+    // Blend state cache
+    static std::size_t HashBlendState(const d3d11::BlendStateKey &blendState);
+    static bool CompareBlendStates(const d3d11::BlendStateKey &a, const d3d11::BlendStateKey &b);
+    static const unsigned int kMaxBlendStates;
+
+    typedef std::size_t (*BlendStateHashFunction)(const d3d11::BlendStateKey &);
+    typedef bool (*BlendStateEqualityFunction)(const d3d11::BlendStateKey &,
+                                               const d3d11::BlendStateKey &);
+    typedef std::pair<ID3D11BlendState*, unsigned long long> BlendStateCounterPair;
+    typedef std::unordered_map<d3d11::BlendStateKey,
+                               BlendStateCounterPair,
+                               BlendStateHashFunction,
+                               BlendStateEqualityFunction>
+        BlendStateMap;
+    BlendStateMap mBlendStateCache;
+
+    // Rasterizer state cache
+    struct RasterizerStateKey
+    {
+        gl::RasterizerState rasterizerState;
+        bool scissorEnabled;
+    };
+    static std::size_t HashRasterizerState(const RasterizerStateKey &rasterState);
+    static bool CompareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
+    static const unsigned int kMaxRasterizerStates;
+
+    typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &);
+    typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &);
+    typedef std::pair<ID3D11RasterizerState*, unsigned long long> RasterizerStateCounterPair;
+    typedef std::unordered_map<RasterizerStateKey, RasterizerStateCounterPair, RasterizerStateHashFunction, RasterizerStateEqualityFunction> RasterizerStateMap;
+    RasterizerStateMap mRasterizerStateCache;
+
+    // Depth stencil state cache
+    static std::size_t HashDepthStencilState(const gl::DepthStencilState &dsState);
+    static bool CompareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b);
+    static const unsigned int kMaxDepthStencilStates;
+
+    typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &);
+    typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &);
+    typedef std::pair<ID3D11DepthStencilState*, unsigned long long> DepthStencilStateCounterPair;
+    typedef std::unordered_map<gl::DepthStencilState,
+                               DepthStencilStateCounterPair,
+                               DepthStencilStateHashFunction,
+                               DepthStencilStateEqualityFunction> DepthStencilStateMap;
+    DepthStencilStateMap mDepthStencilStateCache;
+
+    // Sample state cache
+    static std::size_t HashSamplerState(const gl::SamplerState &samplerState);
+    static bool CompareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b);
+    static const unsigned int kMaxSamplerStates;
+
+    typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &);
+    typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &);
+    typedef std::pair<ID3D11SamplerState*, unsigned long long> SamplerStateCounterPair;
+    typedef std::unordered_map<gl::SamplerState,
+                               SamplerStateCounterPair,
+                               SamplerStateHashFunction,
+                               SamplerStateEqualityFunction> SamplerStateMap;
+    SamplerStateMap mSamplerStateCache;
+
+    ID3D11Device *mDevice;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
new file mode 100644
index 0000000..e339bb6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
@@ -0,0 +1,438 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers
+// retained by Renderbuffers.
+
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+namespace rx
+{
+
+namespace
+{
+bool GetTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples)
+{
+    ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject<ID3D11Texture1D>(resource);
+    if (texture1D)
+    {
+        D3D11_TEXTURE1D_DESC texDesc;
+        texture1D->GetDesc(&texDesc);
+        SafeRelease(texture1D);
+
+        *mipLevels = texDesc.MipLevels;
+        *samples = 0;
+
+        return true;
+    }
+
+    ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
+    if (texture2D)
+    {
+        D3D11_TEXTURE2D_DESC texDesc;
+        texture2D->GetDesc(&texDesc);
+        SafeRelease(texture2D);
+
+        *mipLevels = texDesc.MipLevels;
+        *samples = texDesc.SampleDesc.Count > 1 ? texDesc.SampleDesc.Count : 0;
+
+        return true;
+    }
+
+    ID3D11Texture3D *texture3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(resource);
+    if (texture3D)
+    {
+        D3D11_TEXTURE3D_DESC texDesc;
+        texture3D->GetDesc(&texDesc);
+        SafeRelease(texture3D);
+
+        *mipLevels = texDesc.MipLevels;
+        *samples = 0;
+
+        return true;
+    }
+
+    return false;
+}
+
+unsigned int GetRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view)
+{
+    D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+    view->GetDesc(&rtvDesc);
+
+    unsigned int mipSlice = 0;
+    unsigned int arraySlice = 0;
+
+    switch (rtvDesc.ViewDimension)
+    {
+        case D3D11_RTV_DIMENSION_TEXTURE1D:
+            mipSlice   = rtvDesc.Texture1D.MipSlice;
+            arraySlice = 0;
+            break;
+
+        case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
+            mipSlice   = rtvDesc.Texture1DArray.MipSlice;
+            arraySlice = rtvDesc.Texture1DArray.FirstArraySlice;
+            break;
+
+        case D3D11_RTV_DIMENSION_TEXTURE2D:
+            mipSlice   = rtvDesc.Texture2D.MipSlice;
+            arraySlice = 0;
+            break;
+
+        case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+            mipSlice   = rtvDesc.Texture2DArray.MipSlice;
+            arraySlice = rtvDesc.Texture2DArray.FirstArraySlice;
+            break;
+
+        case D3D11_RTV_DIMENSION_TEXTURE2DMS:
+            mipSlice   = 0;
+            arraySlice = 0;
+            break;
+
+        case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
+            mipSlice   = 0;
+            arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice;
+            break;
+
+        case D3D11_RTV_DIMENSION_TEXTURE3D:
+            mipSlice   = rtvDesc.Texture3D.MipSlice;
+            arraySlice = 0;
+            break;
+
+        case D3D11_RTV_DIMENSION_UNKNOWN:
+        case D3D11_RTV_DIMENSION_BUFFER:
+            UNIMPLEMENTED();
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    unsigned int mipLevels, samples;
+    GetTextureProperties(resource, &mipLevels, &samples);
+
+    return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
+}
+
+unsigned int GetDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view)
+{
+    D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+    view->GetDesc(&dsvDesc);
+
+    unsigned int mipSlice = 0;
+    unsigned int arraySlice = 0;
+
+    switch (dsvDesc.ViewDimension)
+    {
+        case D3D11_DSV_DIMENSION_TEXTURE1D:
+            mipSlice   = dsvDesc.Texture1D.MipSlice;
+            arraySlice = 0;
+            break;
+
+        case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
+            mipSlice   = dsvDesc.Texture1DArray.MipSlice;
+            arraySlice = dsvDesc.Texture1DArray.FirstArraySlice;
+            break;
+
+        case D3D11_DSV_DIMENSION_TEXTURE2D:
+            mipSlice   = dsvDesc.Texture2D.MipSlice;
+            arraySlice = 0;
+            break;
+
+        case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
+            mipSlice   = dsvDesc.Texture2DArray.MipSlice;
+            arraySlice = dsvDesc.Texture2DArray.FirstArraySlice;
+            break;
+
+        case D3D11_DSV_DIMENSION_TEXTURE2DMS:
+            mipSlice   = 0;
+            arraySlice = 0;
+            break;
+
+        case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
+            mipSlice   = 0;
+            arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice;
+            break;
+
+        case D3D11_DSV_DIMENSION_UNKNOWN:
+            UNIMPLEMENTED();
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    unsigned int mipLevels, samples;
+    GetTextureProperties(resource, &mipLevels, &samples);
+
+    return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
+}
+
+GLenum GetSurfaceRTFormat(bool depth, SwapChain11 *swapChain)
+{
+    return (depth ? swapChain->getDepthBufferInternalFormat()
+                  : swapChain->getRenderTargetInternalFormat());
+}
+
+const d3d11::Format &GetSurfaceFormatSet(bool depth, SwapChain11 *swapChain, Renderer11 *renderer)
+{
+    return d3d11::Format::Get(GetSurfaceRTFormat(depth, swapChain),
+                              renderer->getRenderer11DeviceCaps());
+}
+
+}  // anonymous namespace
+
+RenderTarget11::RenderTarget11(const d3d11::Format &formatSet) : mFormatSet(formatSet)
+{
+}
+
+RenderTarget11::~RenderTarget11()
+{
+    signalDirty();
+}
+
+void RenderTarget11::signalDirty()
+{
+    mBroadcastChannel.signal();
+
+    // Clear the list. We can't do this in the receiver because it would mutate during iteration.
+    mBroadcastChannel.reset();
+}
+
+TextureRenderTarget11::TextureRenderTarget11(d3d11::RenderTargetView &&rtv,
+                                             ID3D11Resource *resource,
+                                             ID3D11ShaderResourceView *srv,
+                                             ID3D11ShaderResourceView *blitSRV,
+                                             GLenum internalFormat,
+                                             const d3d11::Format &formatSet,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLsizei depth,
+                                             GLsizei samples)
+    : RenderTarget11(formatSet),
+      mWidth(width),
+      mHeight(height),
+      mDepth(depth),
+      mInternalFormat(internalFormat),
+      mSamples(samples),
+      mSubresourceIndex(0),
+      mTexture(resource),
+      mRenderTarget(std::move(rtv)),
+      mDepthStencil(nullptr),
+      mShaderResource(srv),
+      mBlitShaderResource(blitSRV)
+{
+    if (mTexture)
+    {
+        mTexture->AddRef();
+    }
+
+    if (mShaderResource)
+    {
+        mShaderResource->AddRef();
+    }
+
+    if (mBlitShaderResource)
+    {
+        mBlitShaderResource->AddRef();
+    }
+
+    if (mRenderTarget.valid() && mTexture)
+    {
+        mSubresourceIndex = GetRTVSubresourceIndex(mTexture, mRenderTarget.get());
+    }
+    ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0);
+}
+
+TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv,
+                                             ID3D11Resource *resource,
+                                             ID3D11ShaderResourceView *srv,
+                                             GLenum internalFormat,
+                                             const d3d11::Format &formatSet,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLsizei depth,
+                                             GLsizei samples)
+    : RenderTarget11(formatSet),
+      mWidth(width),
+      mHeight(height),
+      mDepth(depth),
+      mInternalFormat(internalFormat),
+      mSamples(samples),
+      mSubresourceIndex(0),
+      mTexture(resource),
+      mRenderTarget(),
+      mDepthStencil(dsv),
+      mShaderResource(srv),
+      mBlitShaderResource(nullptr)
+{
+    if (mTexture)
+    {
+        mTexture->AddRef();
+    }
+
+    if (mDepthStencil)
+    {
+        mDepthStencil->AddRef();
+    }
+
+    if (mShaderResource)
+    {
+        mShaderResource->AddRef();
+    }
+
+    if (mDepthStencil && mTexture)
+    {
+        mSubresourceIndex = GetDSVSubresourceIndex(mTexture, mDepthStencil);
+    }
+    ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0);
+}
+
+TextureRenderTarget11::~TextureRenderTarget11()
+{
+    SafeRelease(mTexture);
+    SafeRelease(mDepthStencil);
+    SafeRelease(mShaderResource);
+    SafeRelease(mBlitShaderResource);
+}
+
+ID3D11Resource *TextureRenderTarget11::getTexture() const
+{
+    return mTexture;
+}
+
+const d3d11::RenderTargetView &TextureRenderTarget11::getRenderTargetView() const
+{
+    return mRenderTarget;
+}
+
+ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const
+{
+    return mDepthStencil;
+}
+
+ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const
+{
+    return mShaderResource;
+}
+
+ID3D11ShaderResourceView *TextureRenderTarget11::getBlitShaderResourceView() const
+{
+    return mBlitShaderResource;
+}
+
+GLsizei TextureRenderTarget11::getWidth() const
+{
+    return mWidth;
+}
+
+GLsizei TextureRenderTarget11::getHeight() const
+{
+    return mHeight;
+}
+
+GLsizei TextureRenderTarget11::getDepth() const
+{
+    return mDepth;
+}
+
+GLenum TextureRenderTarget11::getInternalFormat() const
+{
+    return mInternalFormat;
+}
+
+GLsizei TextureRenderTarget11::getSamples() const
+{
+    return mSamples;
+}
+
+unsigned int TextureRenderTarget11::getSubresourceIndex() const
+{
+    return mSubresourceIndex;
+}
+
+SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain,
+                                             Renderer11 *renderer,
+                                             bool depth)
+    : RenderTarget11(GetSurfaceFormatSet(depth, swapChain, renderer)),
+      mSwapChain(swapChain),
+      mDepth(depth)
+{
+    ASSERT(mSwapChain);
+}
+
+SurfaceRenderTarget11::~SurfaceRenderTarget11()
+{
+}
+
+GLsizei SurfaceRenderTarget11::getWidth() const
+{
+    return mSwapChain->getWidth();
+}
+
+GLsizei SurfaceRenderTarget11::getHeight() const
+{
+    return mSwapChain->getHeight();
+}
+
+GLsizei SurfaceRenderTarget11::getDepth() const
+{
+    return 1;
+}
+
+GLenum SurfaceRenderTarget11::getInternalFormat() const
+{
+    return GetSurfaceRTFormat(mDepth, mSwapChain);
+}
+
+GLsizei SurfaceRenderTarget11::getSamples() const
+{
+    return mSwapChain->getSamples();
+}
+
+ID3D11Resource *SurfaceRenderTarget11::getTexture() const
+{
+    return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture());
+}
+
+const d3d11::RenderTargetView &SurfaceRenderTarget11::getRenderTargetView() const
+{
+    ASSERT(!mDepth);
+    return mSwapChain->getRenderTarget();
+}
+
+ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const
+{
+    return (mDepth ? mSwapChain->getDepthStencil() : nullptr);
+}
+
+ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const
+{
+    return (mDepth ? mSwapChain->getDepthStencilShaderResource()
+                   : mSwapChain->getRenderTargetShaderResource());
+}
+
+ID3D11ShaderResourceView *SurfaceRenderTarget11::getBlitShaderResourceView() const
+{
+    // The SurfaceRenderTargetView format should always be such that the normal SRV works for blits.
+    return getShaderResourceView();
+}
+
+unsigned int SurfaceRenderTarget11::getSubresourceIndex() const
+{
+    return 0;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
new file mode 100644
index 0000000..c1a5715
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers
+// retained by Renderbuffers.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
+
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+namespace rx
+{
+class SwapChain11;
+class Renderer11;
+
+class RenderTarget11 : public RenderTargetD3D
+{
+  public:
+    RenderTarget11(const d3d11::Format &formatSet);
+    virtual ~RenderTarget11();
+
+    virtual ID3D11Resource *getTexture() const = 0;
+    virtual const d3d11::RenderTargetView &getRenderTargetView() const  = 0;
+    virtual ID3D11DepthStencilView *getDepthStencilView() const = 0;
+    virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0;
+    virtual ID3D11ShaderResourceView *getBlitShaderResourceView() const = 0;
+
+    virtual unsigned int getSubresourceIndex() const = 0;
+
+    void signalDirty() override;
+    OnRenderTargetDirtyChannel *getBroadcastChannel() { return &mBroadcastChannel; }
+
+    const d3d11::Format &getFormatSet() const { return mFormatSet; }
+
+  protected:
+    OnRenderTargetDirtyChannel mBroadcastChannel;
+    const d3d11::Format &mFormatSet;
+};
+
+class TextureRenderTarget11 : public RenderTarget11
+{
+  public:
+    // TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them
+    TextureRenderTarget11(d3d11::RenderTargetView &&rtv,
+                          ID3D11Resource *resource,
+                          ID3D11ShaderResourceView *srv,
+                          ID3D11ShaderResourceView *blitSRV,
+                          GLenum internalFormat,
+                          const d3d11::Format &formatSet,
+                          GLsizei width,
+                          GLsizei height,
+                          GLsizei depth,
+                          GLsizei samples);
+    TextureRenderTarget11(ID3D11DepthStencilView *dsv,
+                          ID3D11Resource *resource,
+                          ID3D11ShaderResourceView *srv,
+                          GLenum internalFormat,
+                          const d3d11::Format &formatSet,
+                          GLsizei width,
+                          GLsizei height,
+                          GLsizei depth,
+                          GLsizei samples);
+    virtual ~TextureRenderTarget11();
+
+    GLsizei getWidth() const override;
+    GLsizei getHeight() const override;
+    GLsizei getDepth() const override;
+    GLenum getInternalFormat() const override;
+    GLsizei getSamples() const override;
+
+    ID3D11Resource *getTexture() const override;
+    const d3d11::RenderTargetView &getRenderTargetView() const override;
+    ID3D11DepthStencilView *getDepthStencilView() const override;
+    ID3D11ShaderResourceView *getShaderResourceView() const override;
+    ID3D11ShaderResourceView *getBlitShaderResourceView() const override;
+
+    unsigned int getSubresourceIndex() const override;
+
+  private:
+    GLsizei mWidth;
+    GLsizei mHeight;
+    GLsizei mDepth;
+    GLenum mInternalFormat;
+    GLsizei mSamples;
+
+    unsigned int mSubresourceIndex;
+    ID3D11Resource *mTexture;
+    d3d11::RenderTargetView mRenderTarget;
+    ID3D11DepthStencilView *mDepthStencil;
+    ID3D11ShaderResourceView *mShaderResource;
+
+    // Shader resource view to use with internal blit shaders. Not set for depth/stencil render
+    // targets.
+    ID3D11ShaderResourceView *mBlitShaderResource;
+};
+
+class SurfaceRenderTarget11 : public RenderTarget11
+{
+  public:
+    SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth);
+    virtual ~SurfaceRenderTarget11();
+
+    GLsizei getWidth() const override;
+    GLsizei getHeight() const override;
+    GLsizei getDepth() const override;
+    GLenum getInternalFormat() const override;
+    GLsizei getSamples() const override;
+
+    ID3D11Resource *getTexture() const override;
+    const d3d11::RenderTargetView &getRenderTargetView() const override;
+    ID3D11DepthStencilView *getDepthStencilView() const override;
+    ID3D11ShaderResourceView *getShaderResourceView() const override;
+    ID3D11ShaderResourceView *getBlitShaderResourceView() const override;
+
+    unsigned int getSubresourceIndex() const override;
+
+  private:
+    SwapChain11 *mSwapChain;
+    bool mDepth;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
new file mode 100644
index 0000000..4d7e56a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -0,0 +1,5021 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+#include <EGL/eglext.h>
+#include <versionhelpers.h>
+#include <sstream>
+
+#include "common/tls.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "third_party/trace_event/trace_event.h"
+
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
+#else
+#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
+#endif
+
+// Include the D3D9 debug annotator header for use by the desktop D3D11 renderer
+// because the D3D11 interface method ID3DUserDefinedAnnotation::GetStatus
+// doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
+#ifdef ANGLE_ENABLE_D3D9
+#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
+#endif
+
+// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
+// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
+#ifndef ANGLE_SKIP_DXGI_1_2_CHECK
+#define ANGLE_SKIP_DXGI_1_2_CHECK 0
+#endif
+
+#ifdef _DEBUG
+// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
+// and conformance tests. to enable all warnings, remove this define.
+#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
+#endif
+
+namespace rx
+{
+
+namespace
+{
+
+enum
+{
+    MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
+};
+
+enum ANGLEFeatureLevel
+{
+    ANGLE_FEATURE_LEVEL_INVALID,
+    ANGLE_FEATURE_LEVEL_9_3,
+    ANGLE_FEATURE_LEVEL_10_0,
+    ANGLE_FEATURE_LEVEL_10_1,
+    ANGLE_FEATURE_LEVEL_11_0,
+    ANGLE_FEATURE_LEVEL_11_1,
+    NUM_ANGLE_FEATURE_LEVELS
+};
+
+ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)
+{
+    switch (d3dFeatureLevel)
+    {
+        case D3D_FEATURE_LEVEL_9_3:
+            return ANGLE_FEATURE_LEVEL_9_3;
+        case D3D_FEATURE_LEVEL_10_0:
+            return ANGLE_FEATURE_LEVEL_10_0;
+        case D3D_FEATURE_LEVEL_10_1:
+            return ANGLE_FEATURE_LEVEL_10_1;
+        case D3D_FEATURE_LEVEL_11_0:
+            return ANGLE_FEATURE_LEVEL_11_0;
+        // Note: we don't ever request a 11_1 device, because this gives
+        // an E_INVALIDARG error on systems that don't have the platform update.
+        case D3D_FEATURE_LEVEL_11_1:
+            return ANGLE_FEATURE_LEVEL_11_1;
+        default:
+            return ANGLE_FEATURE_LEVEL_INVALID;
+    }
+}
+
+void SetLineLoopIndices(GLuint *dest, size_t count)
+{
+    for (size_t i = 0; i < count; i++)
+    {
+        dest[i] = static_cast<GLuint>(i);
+    }
+    dest[count] = 0;
+}
+
+template <typename T>
+void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count)
+{
+    const T *srcPtr = static_cast<const T *>(indices);
+    for (size_t i = 0; i < count; ++i)
+    {
+        dest[i] = static_cast<GLuint>(srcPtr[i]);
+    }
+    dest[count] = static_cast<GLuint>(srcPtr[0]);
+}
+
+void SetTriangleFanIndices(GLuint *destPtr, size_t numTris)
+{
+    for (size_t i = 0; i < numTris; i++)
+    {
+        destPtr[i * 3 + 0] = 0;
+        destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1;
+        destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2;
+    }
+}
+
+template <typename T>
+void CopyLineLoopIndicesWithRestart(const void *indices,
+                                    size_t count,
+                                    GLenum indexType,
+                                    std::vector<GLuint> *bufferOut)
+{
+    GLuint restartIndex    = gl::GetPrimitiveRestartIndex(indexType);
+    GLuint d3dRestartIndex = static_cast<GLuint>(d3d11::GetPrimitiveRestartIndex());
+    const T *srcPtr        = static_cast<const T *>(indices);
+    Optional<GLuint> currentLoopStart;
+
+    bufferOut->clear();
+
+    for (size_t indexIdx = 0; indexIdx < count; ++indexIdx)
+    {
+        GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
+
+        if (value == restartIndex)
+        {
+            if (currentLoopStart.valid())
+            {
+                bufferOut->push_back(currentLoopStart.value());
+                bufferOut->push_back(d3dRestartIndex);
+                currentLoopStart.reset();
+            }
+        }
+        else
+        {
+            bufferOut->push_back(value);
+            if (!currentLoopStart.valid())
+            {
+                currentLoopStart = value;
+            }
+        }
+    }
+
+    if (currentLoopStart.valid())
+    {
+        bufferOut->push_back(currentLoopStart.value());
+    }
+}
+
+void GetLineLoopIndices(const void *indices,
+                        GLenum indexType,
+                        GLuint count,
+                        bool usePrimitiveRestartFixedIndex,
+                        std::vector<GLuint> *bufferOut)
+{
+    if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
+    {
+        switch (indexType)
+        {
+            case GL_UNSIGNED_BYTE:
+                CopyLineLoopIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
+                break;
+            case GL_UNSIGNED_SHORT:
+                CopyLineLoopIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
+                break;
+            case GL_UNSIGNED_INT:
+                CopyLineLoopIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
+                break;
+            default:
+                UNREACHABLE();
+                break;
+        }
+        return;
+    }
+
+    // For non-primitive-restart draws, the index count is static.
+    bufferOut->resize(static_cast<size_t>(count) + 1);
+
+    switch (indexType)
+    {
+        // Non-indexed draw
+        case GL_NONE:
+            SetLineLoopIndices(&(*bufferOut)[0], count);
+            break;
+        case GL_UNSIGNED_BYTE:
+            CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count);
+            break;
+        case GL_UNSIGNED_SHORT:
+            CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count);
+            break;
+        case GL_UNSIGNED_INT:
+            CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+template <typename T>
+void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris)
+{
+    const T *srcPtr = static_cast<const T *>(indices);
+
+    for (size_t i = 0; i < numTris; i++)
+    {
+        destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]);
+        destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]);
+        destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]);
+    }
+}
+
+template <typename T>
+void CopyTriangleFanIndicesWithRestart(const void *indices,
+                                       GLuint indexCount,
+                                       GLenum indexType,
+                                       std::vector<GLuint> *bufferOut)
+{
+    GLuint restartIndex    = gl::GetPrimitiveRestartIndex(indexType);
+    GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(GL_UNSIGNED_INT);
+    const T *srcPtr        = static_cast<const T *>(indices);
+    Optional<GLuint> vertexA;
+    Optional<GLuint> vertexB;
+
+    bufferOut->clear();
+
+    for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx)
+    {
+        GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
+
+        if (value == restartIndex)
+        {
+            bufferOut->push_back(d3dRestartIndex);
+            vertexA.reset();
+            vertexB.reset();
+        }
+        else
+        {
+            if (!vertexA.valid())
+            {
+                vertexA = value;
+            }
+            else if (!vertexB.valid())
+            {
+                vertexB = value;
+            }
+            else
+            {
+                bufferOut->push_back(vertexA.value());
+                bufferOut->push_back(vertexB.value());
+                bufferOut->push_back(value);
+                vertexB = value;
+            }
+        }
+    }
+}
+
+void GetTriFanIndices(const void *indices,
+                      GLenum indexType,
+                      GLuint count,
+                      bool usePrimitiveRestartFixedIndex,
+                      std::vector<GLuint> *bufferOut)
+{
+    if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
+    {
+        switch (indexType)
+        {
+            case GL_UNSIGNED_BYTE:
+                CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
+                break;
+            case GL_UNSIGNED_SHORT:
+                CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
+                break;
+            case GL_UNSIGNED_INT:
+                CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
+                break;
+            default:
+                UNREACHABLE();
+                break;
+        }
+        return;
+    }
+
+    // For non-primitive-restart draws, the index count is static.
+    GLuint numTris = count - 2;
+    bufferOut->resize(numTris * 3);
+
+    switch (indexType)
+    {
+        // Non-indexed draw
+        case GL_NONE:
+            SetTriangleFanIndices(&(*bufferOut)[0], numTris);
+            break;
+        case GL_UNSIGNED_BYTE:
+            CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris);
+            break;
+        case GL_UNSIGNED_SHORT:
+            CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris);
+            break;
+        case GL_UNSIGNED_INT:
+            CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+int GetWrapBits(GLenum wrap)
+{
+    switch (wrap)
+    {
+        case GL_CLAMP_TO_EDGE:
+            return 0x1;
+        case GL_REPEAT:
+            return 0x2;
+        case GL_MIRRORED_REPEAT:
+            return 0x3;
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+const uint32_t ScratchMemoryBufferLifetime = 1000;
+
+}  // anonymous namespace
+
+Renderer11::Renderer11(egl::Display *display)
+    : RendererD3D(display),
+      mStateCache(this),
+      mStateManager(this),
+      mLastHistogramUpdateTime(
+          ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())),
+      mDebug(nullptr),
+      mScratchMemoryBuffer(ScratchMemoryBufferLifetime),
+      mAnnotator(nullptr)
+{
+    mVertexDataManager = nullptr;
+    mIndexDataManager  = nullptr;
+
+    mLineLoopIB       = nullptr;
+    mTriangleFanIB    = nullptr;
+    mAppliedIBChanged = false;
+
+    mBlit          = nullptr;
+    mPixelTransfer = nullptr;
+
+    mClear = nullptr;
+
+    mTrim = nullptr;
+
+    mSyncQuery = nullptr;
+
+    mRenderer11DeviceCaps.supportsClearView             = false;
+    mRenderer11DeviceCaps.supportsConstantBufferOffsets = false;
+    mRenderer11DeviceCaps.supportsDXGI1_2               = false;
+    mRenderer11DeviceCaps.B5G6R5support                 = 0;
+    mRenderer11DeviceCaps.B4G4R4A4support               = 0;
+    mRenderer11DeviceCaps.B5G5R5A1support               = 0;
+
+    mD3d11Module          = nullptr;
+    mDxgiModule           = nullptr;
+    mDCompModule          = nullptr;
+    mCreatedWithDeviceEXT = false;
+    mEGLDevice            = nullptr;
+
+    mDevice         = nullptr;
+    mDeviceContext  = nullptr;
+    mDeviceContext1 = nullptr;
+    mDxgiAdapter    = nullptr;
+    mDxgiFactory    = nullptr;
+
+    mDriverConstantBufferVS = nullptr;
+    mDriverConstantBufferPS = nullptr;
+    mDriverConstantBufferCS = nullptr;
+
+    mAppliedVertexShader   = angle::DirtyPointer;
+    mAppliedGeometryShader = angle::DirtyPointer;
+    mAppliedPixelShader    = angle::DirtyPointer;
+    mAppliedComputeShader  = angle::DirtyPointer;
+
+    mAppliedTFObject = angle::DirtyPointer;
+
+    ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
+
+    if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
+    {
+        const auto &attributes = mDisplay->getAttributeMap();
+
+        EGLint requestedMajorVersion = static_cast<EGLint>(
+            attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
+        EGLint requestedMinorVersion = static_cast<EGLint>(
+            attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
+
+        if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
+        {
+            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+            {
+                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
+            }
+        }
+
+        if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
+        {
+            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
+            {
+                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
+            }
+            if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+            {
+                mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
+            }
+        }
+
+        if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
+        {
+            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
+        }
+
+        EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
+            EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
+        switch (requestedDeviceType)
+        {
+            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+                mRequestedDriverType = D3D_DRIVER_TYPE_HARDWARE;
+                break;
+
+            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
+                mRequestedDriverType = D3D_DRIVER_TYPE_WARP;
+                break;
+
+            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+                mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE;
+                break;
+
+            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+                mRequestedDriverType = D3D_DRIVER_TYPE_NULL;
+                break;
+
+            default:
+                UNREACHABLE();
+        }
+
+        const EGLenum presentPath = static_cast<EGLenum>(attributes.get(
+            EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE));
+        mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE);
+    }
+    else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
+    {
+        mEGLDevice = GetImplAs<DeviceD3D>(display->getDevice());
+        ASSERT(mEGLDevice != nullptr);
+        mCreatedWithDeviceEXT = true;
+
+        // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE
+        // mAvailableFeatureLevels defaults to empty
+        mRequestedDriverType    = D3D_DRIVER_TYPE_UNKNOWN;
+        mPresentPathFastEnabled = false;
+    }
+
+// The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface
+// method ID3DUserDefinedAnnotation::GetStatus on desktop builds doesn't work with the Graphics
+// Diagnostics tools in Visual Studio 2013.
+// The D3D9 annotator works properly for both D3D11 and D3D9.
+// Incorrect status reporting can cause ANGLE to log unnecessary debug events.
+#ifdef ANGLE_ENABLE_D3D9
+    mAnnotator = new DebugAnnotator9();
+#else
+    mAnnotator = new DebugAnnotator11();
+#endif
+    ASSERT(mAnnotator);
+    gl::InitializeDebugAnnotations(mAnnotator);
+}
+
+Renderer11::~Renderer11()
+{
+    release();
+}
+
+#ifndef __d3d11_1_h__
+#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
+#endif
+
+egl::Error Renderer11::initialize()
+{
+    HRESULT result = S_OK;
+
+    ANGLE_TRY(initializeD3DDevice());
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+#if !ANGLE_SKIP_DXGI_1_2_CHECK
+    {
+        TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)");
+        // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is
+        // required.
+        // The easiest way to check is to query for a IDXGIDevice2.
+        bool requireDXGI1_2 = false;
+        HWND hwnd           = WindowFromDC(mDisplay->getNativeDisplayId());
+        if (hwnd)
+        {
+            DWORD currentProcessId = GetCurrentProcessId();
+            DWORD wndProcessId;
+            GetWindowThreadProcessId(hwnd, &wndProcessId);
+            requireDXGI1_2 = (currentProcessId != wndProcessId);
+        }
+        else
+        {
+            requireDXGI1_2 = true;
+        }
+
+        if (requireDXGI1_2)
+        {
+            IDXGIDevice2 *dxgiDevice2 = nullptr;
+            result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void **)&dxgiDevice2);
+            if (FAILED(result))
+            {
+                return egl::Error(
+                    EGL_NOT_INITIALIZED, D3D11_INIT_INCOMPATIBLE_DXGI,
+                    "DXGI 1.2 required to present to HWNDs owned by another process.");
+            }
+            SafeRelease(dxgiDevice2);
+        }
+    }
+#endif
+#endif
+
+    {
+        TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)");
+        // Cast the DeviceContext to a DeviceContext1.
+        // This could fail on Windows 7 without the Platform Update.
+        // Don't error in this case- just don't use mDeviceContext1.
+        mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
+
+        IDXGIDevice *dxgiDevice = nullptr;
+        result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
+
+        if (FAILED(result))
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
+                              "Could not query DXGI device.");
+        }
+
+        result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter);
+
+        if (FAILED(result))
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
+                              "Could not retrieve DXGI adapter");
+        }
+
+        SafeRelease(dxgiDevice);
+
+        IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
+
+        // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the
+        // description string.
+        // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual
+        // hardware values.
+        if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != nullptr)
+        {
+            DXGI_ADAPTER_DESC2 adapterDesc2 = {};
+            result                          = dxgiAdapter2->GetDesc2(&adapterDesc2);
+            if (SUCCEEDED(result))
+            {
+                // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a
+                // DXGI_ADAPTER_DESC).
+                memcpy(mAdapterDescription.Description, adapterDesc2.Description,
+                       sizeof(mAdapterDescription.Description));
+                mAdapterDescription.VendorId              = adapterDesc2.VendorId;
+                mAdapterDescription.DeviceId              = adapterDesc2.DeviceId;
+                mAdapterDescription.SubSysId              = adapterDesc2.SubSysId;
+                mAdapterDescription.Revision              = adapterDesc2.Revision;
+                mAdapterDescription.DedicatedVideoMemory  = adapterDesc2.DedicatedVideoMemory;
+                mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory;
+                mAdapterDescription.SharedSystemMemory    = adapterDesc2.SharedSystemMemory;
+                mAdapterDescription.AdapterLuid           = adapterDesc2.AdapterLuid;
+            }
+        }
+        else
+        {
+            result = mDxgiAdapter->GetDesc(&mAdapterDescription);
+        }
+
+        SafeRelease(dxgiAdapter2);
+
+        if (FAILED(result))
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
+                              "Could not read DXGI adaptor description.");
+        }
+
+        memset(mDescription, 0, sizeof(mDescription));
+        wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
+
+        result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory);
+
+        if (!mDxgiFactory || FAILED(result))
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
+                              "Could not create DXGI factory.");
+        }
+    }
+
+// Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
+#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
+    {
+        TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)");
+        ID3D11InfoQueue *infoQueue;
+        result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
+
+        if (SUCCEEDED(result))
+        {
+            D3D11_MESSAGE_ID hideMessages[] = {
+                D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET};
+
+            D3D11_INFO_QUEUE_FILTER filter = {};
+            filter.DenyList.NumIDs         = static_cast<unsigned int>(ArraySize(hideMessages));
+            filter.DenyList.pIDList        = hideMessages;
+
+            infoQueue->AddStorageFilterEntries(&filter);
+            SafeRelease(infoQueue);
+        }
+    }
+#endif
+
+#if !defined(NDEBUG)
+    mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
+#endif
+
+    initializeDevice();
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error Renderer11::initializeD3DDevice()
+{
+    HRESULT result = S_OK;
+
+    if (!mCreatedWithDeviceEXT)
+    {
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+        PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
+        {
+            SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS");
+            TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
+            mDxgiModule  = LoadLibrary(TEXT("dxgi.dll"));
+            mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+            mDCompModule = LoadLibrary(TEXT("dcomp.dll"));
+
+            if (mD3d11Module == nullptr || mDxgiModule == nullptr)
+            {
+                return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
+                                  "Could not load D3D11 or DXGI library.");
+            }
+
+            // create the D3D11 device
+            ASSERT(mDevice == nullptr);
+            D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+                GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
+
+            if (D3D11CreateDevice == nullptr)
+            {
+                return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
+                                  "Could not retrieve D3D11CreateDevice address.");
+            }
+        }
+#endif
+
+#ifdef _DEBUG
+        {
+            TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
+            result = D3D11CreateDevice(nullptr, mRequestedDriverType, nullptr,
+                                       D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(),
+                                       static_cast<unsigned int>(mAvailableFeatureLevels.size()),
+                                       D3D11_SDK_VERSION, &mDevice,
+                                       &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
+        }
+
+        if (!mDevice || FAILED(result))
+        {
+            WARN() << "Failed creating Debug D3D11 device - falling back to release runtime.";
+        }
+
+        if (!mDevice || FAILED(result))
+#endif
+        {
+            SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
+            TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
+
+            result = D3D11CreateDevice(
+                nullptr, mRequestedDriverType, nullptr, 0, mAvailableFeatureLevels.data(),
+                static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION,
+                &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
+
+            // Cleanup done by destructor
+            if (!mDevice || FAILED(result))
+            {
+                ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
+                                              static_cast<int>(result));
+                return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_CREATEDEVICE_ERROR,
+                                  "Could not create D3D11 device.");
+            }
+        }
+    }
+    else
+    {
+        // We should use the inputted D3D11 device instead
+        void *device = nullptr;
+        ANGLE_TRY(mEGLDevice->getDevice(&device));
+
+        ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device);
+        if (FAILED(d3dDevice->GetDeviceRemovedReason()))
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost.");
+        }
+
+        if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED,
+                              "Inputted D3D11 device must be Feature Level 9_3 or greater.");
+        }
+
+        // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
+        mDevice = d3dDevice;
+        mDevice->AddRef();
+        mDevice->GetImmediateContext(&mDeviceContext);
+        mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
+    }
+
+    d3d11::SetDebugName(mDeviceContext, "DeviceContext");
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+// do any one-time device initialization
+// NOTE: this is also needed after a device lost/reset
+// to reset the scene status and ensure the default states are reset.
+void Renderer11::initializeDevice()
+{
+    SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDeviceMS");
+    TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice");
+
+    populateRenderer11DeviceCaps();
+
+    mStateCache.initialize(mDevice);
+    mInputLayoutCache.initialize(mDevice, mDeviceContext);
+
+    ASSERT(!mVertexDataManager && !mIndexDataManager);
+    mVertexDataManager = new VertexDataManager(this);
+    mIndexDataManager  = new IndexDataManager(this, getRendererClass());
+
+    ASSERT(!mBlit);
+    mBlit = new Blit11(this);
+
+    ASSERT(!mClear);
+    mClear = new Clear11(this);
+
+    const auto &attributes = mDisplay->getAttributeMap();
+    // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application
+    // automatically when an application is suspended by the OS. This feature is currently
+    // only supported for Windows Store applications.
+    EGLint enableAutoTrim = static_cast<EGLint>(
+        attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE));
+
+    if (enableAutoTrim == EGL_TRUE)
+    {
+        ASSERT(!mTrim);
+        mTrim = new Trim11(this);
+    }
+
+    ASSERT(!mPixelTransfer);
+    mPixelTransfer = new PixelTransfer11(this);
+
+    const gl::Caps &rendererCaps = getNativeCaps();
+
+    mStateManager.initialize(rendererCaps);
+
+    mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+    mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+    mSamplerMetadataVS.initData(rendererCaps.maxVertexTextureImageUnits);
+
+    mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+    mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+    mSamplerMetadataPS.initData(rendererCaps.maxTextureImageUnits);
+
+    mForceSetComputeSamplerStates.resize(rendererCaps.maxComputeTextureImageUnits);
+    mCurComputeSamplerStates.resize(rendererCaps.maxComputeTextureImageUnits);
+    mSamplerMetadataCS.initData(rendererCaps.maxComputeTextureImageUnits);
+
+    mStateManager.initialize(rendererCaps);
+
+    markAllStateDirty();
+
+    // Gather stats on DXGI and D3D feature level
+    ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2);
+
+    ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel);
+
+    // We don't actually request a 11_1 device, because of complications with the platform
+    // update. Instead we check if the mDeviceContext1 pointer cast succeeded.
+    // Note: we should support D3D11_0 always, but we aren't guaranteed to be at FL11_0
+    // because the app can specify a lower version (such as 9_3) on Display creation.
+    if (mDeviceContext1 != nullptr)
+    {
+        angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1;
+    }
+
+    ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel,
+                                NUM_ANGLE_FEATURE_LEVELS);
+}
+
+void Renderer11::populateRenderer11DeviceCaps()
+{
+    HRESULT hr = S_OK;
+
+    LARGE_INTEGER version;
+    hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
+    if (FAILED(hr))
+    {
+        mRenderer11DeviceCaps.driverVersion.reset();
+        ERR() << "Error querying driver version from DXGI Adapter.";
+    }
+    else
+    {
+        mRenderer11DeviceCaps.driverVersion = version;
+    }
+
+    if (mDeviceContext1)
+    {
+        D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
+        HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options,
+                                                      sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
+        if (SUCCEEDED(result))
+        {
+            mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE);
+            mRenderer11DeviceCaps.supportsConstantBufferOffsets =
+                (d3d11Options.ConstantBufferOffsetting != FALSE);
+        }
+    }
+
+    if (getWorkarounds().disableB5G6R5Support)
+    {
+        mRenderer11DeviceCaps.B5G6R5support = 0;
+    }
+    else
+    {
+        hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G6R5_UNORM,
+                                         &(mRenderer11DeviceCaps.B5G6R5support));
+        if (FAILED(hr))
+        {
+            mRenderer11DeviceCaps.B5G6R5support = 0;
+        }
+    }
+
+    hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B4G4R4A4_UNORM,
+                                     &(mRenderer11DeviceCaps.B4G4R4A4support));
+    if (FAILED(hr))
+    {
+        mRenderer11DeviceCaps.B4G4R4A4support = 0;
+    }
+
+    hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G5R5A1_UNORM,
+                                     &(mRenderer11DeviceCaps.B5G5R5A1support));
+    if (FAILED(hr))
+    {
+        mRenderer11DeviceCaps.B5G5R5A1support = 0;
+    }
+
+    IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
+    mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr);
+    SafeRelease(dxgiAdapter2);
+}
+
+gl::SupportedSampleSet Renderer11::generateSampleSetFromCaps(
+    const gl::TextureCaps &colorBufferFormatCaps,
+    const gl::TextureCaps &depthStencilBufferFormatCaps) const
+{
+    gl::SupportedSampleSet sampleCounts;
+
+    // Generate a new set from the set intersection of sample counts between the color and depth
+    // format caps.
+    std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(),
+                          colorBufferFormatCaps.sampleCounts.end(),
+                          depthStencilBufferFormatCaps.sampleCounts.begin(),
+                          depthStencilBufferFormatCaps.sampleCounts.end(),
+                          std::inserter(sampleCounts, sampleCounts.begin()));
+
+    // Format of GL_NONE results in no supported sample counts.
+    // Add back the color sample counts to the supported sample set.
+    if (depthStencilBufferFormatCaps.sampleCounts.empty())
+    {
+        sampleCounts = colorBufferFormatCaps.sampleCounts;
+    }
+    else if (colorBufferFormatCaps.sampleCounts.empty())
+    {
+        // Likewise, add back the depth sample counts to the supported sample set.
+        sampleCounts = depthStencilBufferFormatCaps.sampleCounts;
+    }
+
+    // In EGL, no multisampling is 0, in D3D its 1, so if 1 exists, insert 0 for EGL to match.
+    if (sampleCounts.find(1) != sampleCounts.end())
+    {
+        sampleCounts.insert(0);
+    }
+
+    return sampleCounts;
+}
+
+egl::ConfigSet Renderer11::generateConfigs()
+{
+    std::vector<GLenum> colorBufferFormats;
+
+    // 32-bit supported formats
+    colorBufferFormats.push_back(GL_BGRA8_EXT);
+    colorBufferFormats.push_back(GL_RGBA8_OES);
+
+    // 24-bit supported formats
+    colorBufferFormats.push_back(GL_RGB8_OES);
+
+    if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
+    {
+        // Additional high bit depth formats added in D3D 10.0
+        // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx
+        colorBufferFormats.push_back(GL_RGBA16F);
+        colorBufferFormats.push_back(GL_RGB10_A2);
+    }
+
+    if (!mPresentPathFastEnabled)
+    {
+        // 16-bit supported formats
+        // These aren't valid D3D11 swapchain formats, so don't expose them as configs
+        // if present path fast is active
+        colorBufferFormats.push_back(GL_RGBA4);
+        colorBufferFormats.push_back(GL_RGB5_A1);
+        colorBufferFormats.push_back(GL_RGB565);
+    }
+
+    static const GLenum depthStencilBufferFormats[] = {
+        GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT16,
+    };
+
+    const gl::Caps &rendererCaps                  = getNativeCaps();
+    const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
+
+    const EGLint optimalSurfaceOrientation =
+        mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
+
+    egl::ConfigSet configs;
+    for (GLenum colorBufferInternalFormat : colorBufferFormats)
+    {
+        const gl::TextureCaps &colorBufferFormatCaps =
+            rendererTextureCaps.get(colorBufferInternalFormat);
+        if (!colorBufferFormatCaps.renderable)
+        {
+            continue;
+        }
+
+        for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats)
+        {
+            const gl::TextureCaps &depthStencilBufferFormatCaps =
+                rendererTextureCaps.get(depthStencilBufferInternalFormat);
+            if (!depthStencilBufferFormatCaps.renderable &&
+                depthStencilBufferInternalFormat != GL_NONE)
+            {
+                continue;
+            }
+
+            const gl::InternalFormat &colorBufferFormatInfo =
+                gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
+            const gl::InternalFormat &depthStencilBufferFormatInfo =
+                gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
+            const gl::Version &maxVersion = getMaxSupportedESVersion();
+
+            const gl::SupportedSampleSet sampleCounts =
+                generateSampleSetFromCaps(colorBufferFormatCaps, depthStencilBufferFormatCaps);
+
+            for (GLuint sampleCount : sampleCounts)
+            {
+                egl::Config config;
+                config.renderTargetFormat = colorBufferInternalFormat;
+                config.depthStencilFormat = depthStencilBufferInternalFormat;
+                config.bufferSize         = colorBufferFormatInfo.pixelBytes * 8;
+                config.redSize            = colorBufferFormatInfo.redBits;
+                config.greenSize          = colorBufferFormatInfo.greenBits;
+                config.blueSize           = colorBufferFormatInfo.blueBits;
+                config.luminanceSize      = colorBufferFormatInfo.luminanceBits;
+                config.alphaSize          = colorBufferFormatInfo.alphaBits;
+                config.alphaMaskSize      = 0;
+                config.bindToTextureRGB =
+                    ((colorBufferFormatInfo.format == GL_RGB) && (sampleCount <= 1));
+                config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) ||
+                                             (colorBufferFormatInfo.format == GL_BGRA_EXT)) &&
+                                            (sampleCount <= 1));
+                config.colorBufferType = EGL_RGB_BUFFER;
+                config.configCaveat    = EGL_NONE;
+                config.configID        = static_cast<EGLint>(configs.size() + 1);
+
+                // PresentPathFast may not be conformant
+                config.conformant = 0;
+                if (!mPresentPathFastEnabled)
+                {
+                    // Can only support a conformant ES2 with feature level greater than 10.0.
+                    if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
+                    {
+                        config.conformant |= EGL_OPENGL_ES2_BIT;
+                    }
+
+                    // We can only support conformant ES3 on FL 10.1+
+                    if (maxVersion.major >= 3)
+                    {
+                        config.conformant |= EGL_OPENGL_ES3_BIT_KHR;
+                    }
+                }
+
+                config.depthSize         = depthStencilBufferFormatInfo.depthBits;
+                config.level             = 0;
+                config.matchNativePixmap = EGL_NONE;
+                config.maxPBufferWidth   = rendererCaps.max2DTextureSize;
+                config.maxPBufferHeight  = rendererCaps.max2DTextureSize;
+                config.maxPBufferPixels =
+                    rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
+                config.maxSwapInterval  = 4;
+                config.minSwapInterval  = 0;
+                config.nativeRenderable = EGL_FALSE;
+                config.nativeVisualID   = 0;
+                config.nativeVisualType = EGL_NONE;
+
+                // Can't support ES3 at all without feature level 10.1
+                config.renderableType = EGL_OPENGL_ES2_BIT;
+                if (maxVersion.major >= 3)
+                {
+                    config.renderableType |= EGL_OPENGL_ES3_BIT_KHR;
+                }
+
+                config.sampleBuffers = (sampleCount == 0) ? 0 : 1;
+                config.samples       = sampleCount;
+                config.stencilSize   = depthStencilBufferFormatInfo.stencilBits;
+                config.surfaceType =
+                    EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+                config.transparentType       = EGL_NONE;
+                config.transparentRedValue   = 0;
+                config.transparentGreenValue = 0;
+                config.transparentBlueValue  = 0;
+                config.optimalOrientation    = optimalSurfaceOrientation;
+                config.colorComponentType    = gl_egl::GLComponentTypeToEGLColorComponentType(
+                    colorBufferFormatInfo.componentType);
+
+                configs.add(config);
+            }
+        }
+    }
+
+    ASSERT(configs.size() > 0);
+    return configs;
+}
+
+void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
+{
+    outExtensions->createContextRobustness = true;
+
+    if (getShareHandleSupport())
+    {
+        outExtensions->d3dShareHandleClientBuffer     = true;
+        outExtensions->surfaceD3DTexture2DShareHandle = true;
+    }
+    outExtensions->d3dTextureClientBuffer = true;
+
+    outExtensions->keyedMutex          = true;
+    outExtensions->querySurfacePointer = true;
+    outExtensions->windowFixedSize     = true;
+
+    // If present path fast is active then the surface orientation extension isn't supported
+    outExtensions->surfaceOrientation = !mPresentPathFastEnabled;
+
+    // D3D11 does not support present with dirty rectangles until DXGI 1.2.
+    outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2;
+
+    outExtensions->deviceQuery = true;
+
+    outExtensions->image                 = true;
+    outExtensions->imageBase             = true;
+    outExtensions->glTexture2DImage      = true;
+    outExtensions->glTextureCubemapImage = true;
+    outExtensions->glRenderbufferImage   = true;
+
+    outExtensions->stream                     = true;
+    outExtensions->streamConsumerGLTexture    = true;
+    outExtensions->streamConsumerGLTextureYUV = true;
+    // Not all D3D11 devices support NV12 textures
+    if (getNV12TextureSupport())
+    {
+        outExtensions->streamProducerD3DTextureNV12 = true;
+    }
+
+    outExtensions->flexibleSurfaceCompatibility = true;
+    outExtensions->directComposition            = !!mDCompModule;
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
+
+    outExtensions->createContextRobustResourceInitialization = true;
+
+    // getSyncValues requires direct composition.
+    outExtensions->getSyncValues = outExtensions->directComposition;
+}
+
+gl::Error Renderer11::flush()
+{
+    mDeviceContext->Flush();
+    return gl::NoError();
+}
+
+gl::Error Renderer11::finish()
+{
+    HRESULT result;
+
+    if (!mSyncQuery)
+    {
+        D3D11_QUERY_DESC queryDesc;
+        queryDesc.Query     = D3D11_QUERY_EVENT;
+        queryDesc.MiscFlags = 0;
+
+        result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.",
+                             result);
+        }
+    }
+
+    mDeviceContext->End(mSyncQuery);
+
+    unsigned int attempt = 0;
+    do
+    {
+        unsigned int flushFrequency = 100;
+        UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
+        attempt++;
+
+        result = mDeviceContext->GetData(mSyncQuery, nullptr, 0, flags);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.",
+                             result);
+        }
+
+        if (result == S_FALSE)
+        {
+            // Keep polling, but allow other threads to do something useful first
+            ScheduleYield();
+        }
+
+        if (testDeviceLost())
+        {
+            mDisplay->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync.");
+        }
+    } while (result == S_FALSE);
+
+    return gl::NoError();
+}
+
+bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const
+{
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    return NativeWindow11WinRT::IsValidNativeWindow(window);
+#else
+    return NativeWindow11Win32::IsValidNativeWindow(window);
+#endif
+}
+
+NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
+                                                const egl::Config *config,
+                                                const egl::AttributeMap &attribs) const
+{
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    UNUSED_VARIABLE(attribs);
+    return new NativeWindow11WinRT(window, config->alphaSize > 0);
+#else
+    return new NativeWindow11Win32(
+        window, config->alphaSize > 0,
+        attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
+#endif
+}
+
+egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
+                                         IUnknown *d3dTexture,
+                                         EGLint *width,
+                                         EGLint *height,
+                                         GLenum *fboFormat) const
+{
+    ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
+    if (texture == nullptr)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "client buffer is not a ID3D11Texture2D");
+    }
+
+    ID3D11Device *textureDevice = nullptr;
+    texture->GetDevice(&textureDevice);
+    if (textureDevice != mDevice)
+    {
+        SafeRelease(texture);
+        return egl::Error(EGL_BAD_PARAMETER, "Texture's device does not match.");
+    }
+    SafeRelease(textureDevice);
+
+    D3D11_TEXTURE2D_DESC desc = {0};
+    texture->GetDesc(&desc);
+    SafeRelease(texture);
+
+    if (width)
+    {
+        *width = static_cast<EGLint>(desc.Width);
+    }
+    if (height)
+    {
+        *height = static_cast<EGLint>(desc.Height);
+    }
+    if (static_cast<EGLint>(desc.SampleDesc.Count) != configuration->samples)
+    {
+        // Both the texture and EGL config sample count may not be the same when multi-sampling
+        // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore,
+        // we must only check for a invalid match when the EGL config is non-zero or the texture is
+        // not one.
+        if (configuration->samples != 0 || desc.SampleDesc.Count != 1)
+        {
+            return egl::Error(EGL_BAD_PARAMETER, "Texture's sample count does not match.");
+        }
+    }
+    // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+    switch (desc.Format)
+    {
+        case DXGI_FORMAT_R8G8B8A8_UNORM:
+        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+        case DXGI_FORMAT_B8G8R8A8_UNORM:
+        case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+        case DXGI_FORMAT_R16G16B16A16_FLOAT:
+        case DXGI_FORMAT_R32G32B32A32_FLOAT:
+            break;
+
+        default:
+            return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+                              desc.Format);
+    }
+
+    if (fboFormat)
+    {
+        const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format);
+        *fboFormat                       = angleFormat.fboImplementationInternalFormat;
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error Renderer11::validateShareHandle(const egl::Config *config,
+                                           HANDLE shareHandle,
+                                           const egl::AttributeMap &attribs) const
+{
+    if (shareHandle == nullptr)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "NULL share handle.");
+    }
+
+    ID3D11Resource *tempResource11 = nullptr;
+    HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
+                                                 (void **)&tempResource11);
+    if (FAILED(result))
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.", result);
+    }
+
+    ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
+    SafeRelease(tempResource11);
+
+    if (texture2D == nullptr)
+    {
+        return egl::Error(EGL_BAD_PARAMETER,
+                          "Failed to query ID3D11Texture2D object from share handle.");
+    }
+
+    D3D11_TEXTURE2D_DESC desc = {0};
+    texture2D->GetDesc(&desc);
+    SafeRelease(texture2D);
+
+    EGLint width  = attribs.getAsInt(EGL_WIDTH, 0);
+    EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
+    ASSERT(width != 0 && height != 0);
+
+    const d3d11::Format &backbufferFormatInfo =
+        d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps());
+
+    if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) ||
+        desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Invalid texture parameters in share handle texture.");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow,
+                                          HANDLE shareHandle,
+                                          IUnknown *d3dTexture,
+                                          GLenum backBufferFormat,
+                                          GLenum depthBufferFormat,
+                                          EGLint orientation,
+                                          EGLint samples)
+{
+    return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture,
+                           backBufferFormat, depthBufferFormat, orientation, samples);
+}
+
+void *Renderer11::getD3DDevice()
+{
+    return reinterpret_cast<void *>(mDevice);
+}
+
+gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
+{
+    if (texture)
+    {
+        TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+        ASSERT(textureD3D);
+
+        TextureStorage *texStorage = nullptr;
+        ANGLE_TRY(textureD3D->getNativeTexture(&texStorage));
+
+        if (texStorage)
+        {
+            TextureStorage11 *storage11          = GetAs<TextureStorage11>(texStorage);
+            const gl::TextureState &textureState = texture->getTextureState();
+            ANGLE_TRY(storage11->generateSwizzles(textureState.getSwizzleState()));
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::generateSwizzles(const gl::ContextState &data, gl::SamplerType type)
+{
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram());
+
+    unsigned int samplerRange = programD3D->getUsedSamplerRange(type);
+
+    for (unsigned int i = 0; i < samplerRange; i++)
+    {
+        GLenum textureType = programD3D->getSamplerTextureType(type, i);
+        GLint textureUnit  = programD3D->getSamplerMapping(type, i, data.getCaps());
+        if (textureUnit != -1)
+        {
+            gl::Texture *texture = data.getState().getSamplerTexture(textureUnit, textureType);
+            ASSERT(texture);
+            if (texture->getTextureState().swizzleRequired())
+            {
+                ANGLE_TRY(generateSwizzle(texture));
+            }
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::generateSwizzles(const gl::ContextState &data)
+{
+    ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_VERTEX));
+    ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_PIXEL));
+    return gl::NoError();
+}
+gl::Error Renderer11::setSamplerState(gl::SamplerType type,
+                                      int index,
+                                      gl::Texture *texture,
+                                      const gl::SamplerState &samplerState)
+{
+#if !defined(NDEBUG)
+    // Make sure to add the level offset for our tiny compressed texture workaround
+    TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+
+    TextureStorage *storage = nullptr;
+    ANGLE_TRY(textureD3D->getNativeTexture(&storage));
+
+    // Storage should exist, texture should be complete
+    ASSERT(storage);
+#endif  // !defined(NDEBUG)
+
+    // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the
+    // sampler state since having it in contiguous memory makes it possible to memcpy to a constant
+    // buffer, and it doesn't affect the state set by PSSetSamplers/VSSetSamplers.
+    SamplerMetadataD3D11 *metadata = nullptr;
+
+    if (type == gl::SAMPLER_PIXEL)
+    {
+        ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxTextureImageUnits);
+
+        if (mForceSetPixelSamplerStates[index] ||
+            memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+        {
+            ID3D11SamplerState *dxSamplerState = nullptr;
+            ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState));
+
+            ASSERT(dxSamplerState != nullptr);
+            mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
+
+            mCurPixelSamplerStates[index] = samplerState;
+        }
+
+        mForceSetPixelSamplerStates[index] = false;
+
+        metadata = &mSamplerMetadataPS;
+    }
+    else if (type == gl::SAMPLER_VERTEX)
+    {
+        ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxVertexTextureImageUnits);
+
+        if (mForceSetVertexSamplerStates[index] ||
+            memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+        {
+            ID3D11SamplerState *dxSamplerState = nullptr;
+            ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState));
+
+            ASSERT(dxSamplerState != nullptr);
+            mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
+
+            mCurVertexSamplerStates[index] = samplerState;
+        }
+
+        mForceSetVertexSamplerStates[index] = false;
+
+        metadata = &mSamplerMetadataVS;
+    }
+    else if (type == gl::SAMPLER_COMPUTE)
+    {
+        ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxComputeTextureImageUnits);
+
+        if (mForceSetComputeSamplerStates[index] ||
+            memcmp(&samplerState, &mCurComputeSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+        {
+            ID3D11SamplerState *dxSamplerState = nullptr;
+            ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState));
+
+            ASSERT(dxSamplerState != nullptr);
+            mDeviceContext->CSSetSamplers(index, 1, &dxSamplerState);
+
+            mCurComputeSamplerStates[index] = samplerState;
+        }
+
+        mForceSetComputeSamplerStates[index] = false;
+
+        metadata = &mSamplerMetadataCS;
+    }
+    else
+        UNREACHABLE();
+
+    ASSERT(metadata != nullptr);
+    metadata->update(index, *texture);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+{
+    ID3D11ShaderResourceView *textureSRV = nullptr;
+
+    if (texture)
+    {
+        TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
+
+        TextureStorage *texStorage = nullptr;
+        ANGLE_TRY(textureImpl->getNativeTexture(&texStorage));
+
+        // Texture should be complete and have a storage
+        ASSERT(texStorage);
+
+        TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
+
+        ANGLE_TRY(storage11->getSRV(texture->getTextureState(), &textureSRV));
+
+        // If we get NULL back from getSRV here, something went wrong in the texture class and we're
+        // unexpectedly missing the shader resource view
+        ASSERT(textureSRV != nullptr);
+
+        textureImpl->resetDirty();
+    }
+
+    ASSERT((type == gl::SAMPLER_PIXEL &&
+            static_cast<unsigned int>(index) < getNativeCaps().maxTextureImageUnits) ||
+           (type == gl::SAMPLER_VERTEX &&
+            static_cast<unsigned int>(index) < getNativeCaps().maxVertexTextureImageUnits));
+
+    mStateManager.setShaderResource(type, index, textureSRV);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::setUniformBuffers(const gl::ContextState &data,
+                                        const std::vector<GLint> &vertexUniformBuffers,
+                                        const std::vector<GLint> &fragmentUniformBuffers)
+{
+    for (size_t uniformBufferIndex = 0; uniformBufferIndex < vertexUniformBuffers.size();
+         uniformBufferIndex++)
+    {
+        GLint binding = vertexUniformBuffers[uniformBufferIndex];
+
+        if (binding == -1)
+        {
+            continue;
+        }
+
+        const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
+            data.getState().getIndexedUniformBuffer(binding);
+        GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+        GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
+
+        if (uniformBuffer.get() == nullptr)
+        {
+            continue;
+        }
+
+        Buffer11 *bufferStorage      = GetImplAs<Buffer11>(uniformBuffer.get());
+        ID3D11Buffer *constantBuffer = nullptr;
+        UINT firstConstant           = 0;
+        UINT numConstants            = 0;
+
+        ANGLE_TRY(bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize,
+                                                        &constantBuffer, &firstConstant,
+                                                        &numConstants));
+
+        if (!constantBuffer)
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Error retrieving constant buffer");
+        }
+
+        if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() ||
+            mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset ||
+            mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize)
+        {
+            if (firstConstant != 0 && uniformBufferSize != 0)
+            {
+                ASSERT(numConstants != 0);
+                mDeviceContext1->VSSetConstantBuffers1(
+                    getReservedVertexUniformBuffers() +
+                        static_cast<unsigned int>(uniformBufferIndex),
+                    1, &constantBuffer, &firstConstant, &numConstants);
+            }
+            else
+            {
+                mDeviceContext->VSSetConstantBuffers(
+                    getReservedVertexUniformBuffers() +
+                        static_cast<unsigned int>(uniformBufferIndex),
+                    1, &constantBuffer);
+            }
+
+            mCurrentConstantBufferVS[uniformBufferIndex]       = bufferStorage->getSerial();
+            mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset;
+            mCurrentConstantBufferVSSize[uniformBufferIndex]   = uniformBufferSize;
+        }
+    }
+
+    for (size_t uniformBufferIndex = 0; uniformBufferIndex < fragmentUniformBuffers.size();
+         uniformBufferIndex++)
+    {
+        GLint binding = fragmentUniformBuffers[uniformBufferIndex];
+
+        if (binding == -1)
+        {
+            continue;
+        }
+
+        const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
+            data.getState().getIndexedUniformBuffer(binding);
+        GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+        GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
+
+        if (uniformBuffer.get() == nullptr)
+        {
+            continue;
+        }
+
+        Buffer11 *bufferStorage      = GetImplAs<Buffer11>(uniformBuffer.get());
+        ID3D11Buffer *constantBuffer = nullptr;
+        UINT firstConstant           = 0;
+        UINT numConstants            = 0;
+
+        ANGLE_TRY(bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize,
+                                                        &constantBuffer, &firstConstant,
+                                                        &numConstants));
+
+        if (!constantBuffer)
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Error retrieving constant buffer");
+        }
+
+        if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() ||
+            mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset ||
+            mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize)
+        {
+            if (firstConstant != 0 && uniformBufferSize != 0)
+            {
+                mDeviceContext1->PSSetConstantBuffers1(
+                    getReservedFragmentUniformBuffers() +
+                        static_cast<unsigned int>(uniformBufferIndex),
+                    1, &constantBuffer, &firstConstant, &numConstants);
+            }
+            else
+            {
+                mDeviceContext->PSSetConstantBuffers(
+                    getReservedFragmentUniformBuffers() +
+                        static_cast<unsigned int>(uniformBufferIndex),
+                    1, &constantBuffer);
+            }
+
+            mCurrentConstantBufferPS[uniformBufferIndex]       = bufferStorage->getSerial();
+            mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset;
+            mCurrentConstantBufferPSSize[uniformBufferIndex]   = uniformBufferSize;
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::updateState(ContextImpl *contextImpl, GLenum drawMode)
+{
+    const auto &data    = contextImpl->getContextState();
+    const auto &glState = data.getState();
+
+    // Applies the render target surface, depth stencil surface, viewport rectangle and
+    // scissor rectangle to the renderer
+    gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+    ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete());
+    ANGLE_TRY(mStateManager.syncFramebuffer(contextImpl, framebuffer));
+
+    // Set the present path state
+    auto firstColorAttachment        = framebuffer->getFirstColorbuffer();
+    const bool presentPathFastActive = UsePresentPathFast(this, firstColorAttachment);
+    mStateManager.updatePresentPath(presentPathFastActive, firstColorAttachment);
+
+    // Setting viewport state
+    mStateManager.setViewport(&data.getCaps(), glState.getViewport(), glState.getNearPlane(),
+                              glState.getFarPlane());
+
+    // Setting scissor state
+    mStateManager.setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
+
+    // Applying rasterizer state to D3D11 device
+    // Since framebuffer->getSamples will return the original samples which may be different with
+    // the sample counts that we set in render target view, here we use renderTarget->getSamples to
+    // get the actual samples.
+    GLsizei samples = 0;
+    if (firstColorAttachment)
+    {
+        ASSERT(firstColorAttachment->isAttached());
+        RenderTarget11 *renderTarget = nullptr;
+        ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
+        samples = renderTarget->getSamples();
+    }
+    gl::RasterizerState rasterizer = glState.getRasterizerState();
+    rasterizer.pointDrawMode       = (drawMode == GL_POINTS);
+    rasterizer.multiSample         = (samples != 0);
+
+    ANGLE_TRY(mStateManager.setRasterizerState(rasterizer));
+
+    // Setting blend state
+    unsigned int mask = GetBlendSampleMask(data, samples);
+    ANGLE_TRY(mStateManager.setBlendState(framebuffer, glState.getBlendState(),
+                                          glState.getBlendColor(), mask));
+
+    // Setting depth stencil state
+    ANGLE_TRY(mStateManager.setDepthStencilState(glState));
+
+    return gl::NoError();
+}
+
+bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
+{
+    D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+
+    GLsizei minCount = 0;
+
+    switch (mode)
+    {
+        case GL_POINTS:
+            primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
+            minCount          = 1;
+            break;
+        case GL_LINES:
+            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
+            minCount          = 2;
+            break;
+        case GL_LINE_LOOP:
+            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
+            minCount          = 2;
+            break;
+        case GL_LINE_STRIP:
+            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
+            minCount          = 2;
+            break;
+        case GL_TRIANGLES:
+            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+            minCount          = 3;
+            break;
+        case GL_TRIANGLE_STRIP:
+            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+            minCount          = 3;
+            break;
+        // emulate fans via rewriting index buffer
+        case GL_TRIANGLE_FAN:
+            primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+            minCount          = 3;
+            break;
+        default:
+            UNREACHABLE();
+            return false;
+    }
+
+    // If instanced pointsprite emulation is being used and  If gl_PointSize is used in the shader,
+    // GL_POINTS mode is expected to render pointsprites.
+    // Instanced PointSprite emulation requires that the topology to be
+    // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
+    if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
+    {
+        primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+    }
+
+    if (primitiveTopology != mCurrentPrimitiveTopology)
+    {
+        mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
+        mCurrentPrimitiveTopology = primitiveTopology;
+    }
+
+    return count >= minCount;
+}
+
+gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
+                                        GLenum mode,
+                                        GLint first,
+                                        GLsizei count,
+                                        GLsizei instances,
+                                        TranslatedIndexData *indexInfo)
+{
+    const auto &vertexArray = state.getVertexArray();
+    auto *vertexArray11     = GetImplAs<VertexArray11>(vertexArray);
+
+    ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(mVertexDataManager, state, first, count,
+                                                          instances));
+
+    ANGLE_TRY(mStateManager.updateCurrentValueAttribs(state, mVertexDataManager));
+
+    // If index information is passed, mark it with the current changed status.
+    if (indexInfo)
+    {
+        indexInfo->srcIndexData.srcIndicesChanged = mAppliedIBChanged;
+    }
+
+    GLsizei numIndicesPerInstance = 0;
+    if (instances > 0)
+    {
+        numIndicesPerInstance = count;
+    }
+    const auto &vertexArrayAttribs  = vertexArray11->getTranslatedAttribs();
+    const auto &currentValueAttribs = mStateManager.getCurrentValueAttribs();
+    ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(state, vertexArrayAttribs, currentValueAttribs,
+                                                   mode, first, indexInfo, numIndicesPerInstance));
+
+    // InputLayoutCache::applyVertexBuffers calls through to the Bufer11 to get the native vertex
+    // buffer (ID3D11Buffer *). Because we allocate these buffers lazily, this will trigger
+    // allocation. This in turn will signal that the buffer is dirty. Since we just resolved the
+    // dirty-ness in VertexArray11::updateDirtyAndDynamicAttribs, this can make us do a needless
+    // update on the second draw call.
+    // Hence we clear the flags here, after we've applied vertex data, since we know everything
+    // is clean. This is a bit of a hack.
+    vertexArray11->clearDirtyAndPromoteDynamicAttribs(state, count);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::applyIndexBuffer(const gl::ContextState &data,
+                                       const void *indices,
+                                       GLsizei count,
+                                       GLenum mode,
+                                       GLenum type,
+                                       TranslatedIndexData *indexInfo)
+{
+    const auto &glState            = data.getState();
+    gl::VertexArray *vao           = glState.getVertexArray();
+    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+    ANGLE_TRY(mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
+                                                  indexInfo, glState.isPrimitiveRestartEnabled()));
+
+    ID3D11Buffer *buffer = nullptr;
+    DXGI_FORMAT bufferFormat =
+        (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
+
+    if (indexInfo->storage)
+    {
+        Buffer11 *storage = GetAs<Buffer11>(indexInfo->storage);
+        ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDEX), buffer);
+    }
+    else
+    {
+        IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo->indexBuffer);
+        buffer                     = indexBuffer->getBuffer();
+    }
+
+    mAppliedIBChanged = false;
+    if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat ||
+        indexInfo->startOffset != mAppliedIBOffset)
+    {
+        mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset);
+
+        mAppliedIB        = buffer;
+        mAppliedIBFormat  = bufferFormat;
+        mAppliedIBOffset  = indexInfo->startOffset;
+        mAppliedIBChanged = true;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::applyTransformFeedbackBuffers(const gl::ContextState &data)
+{
+    const auto &state = data.getState();
+
+    // If transform feedback is not active, unbind all buffers
+    if (!state.isTransformFeedbackActiveUnpaused())
+    {
+        if (mAppliedTFObject != 0)
+        {
+            mDeviceContext->SOSetTargets(0, nullptr, nullptr);
+            mAppliedTFObject = 0;
+        }
+        return gl::NoError();
+    }
+
+    gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
+    TransformFeedback11 *transformFeedback11 = GetImplAs<TransformFeedback11>(transformFeedback);
+    uintptr_t transformFeedbackId            = reinterpret_cast<uintptr_t>(transformFeedback11);
+    if (mAppliedTFObject == transformFeedbackId && !transformFeedback11->isDirty())
+    {
+        return gl::NoError();
+    }
+
+    const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
+    ANGLE_TRY_RESULT(transformFeedback11->getSOBuffers(), soBuffers);
+    const std::vector<UINT> &soOffsets = transformFeedback11->getSOBufferOffsets();
+
+    mDeviceContext->SOSetTargets(transformFeedback11->getNumSOBuffers(), soBuffers->data(),
+                                 soOffsets.data());
+
+    mAppliedTFObject = transformFeedbackId;
+    transformFeedback11->onApply();
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::drawArraysImpl(const gl::ContextState &data,
+                                     GLenum mode,
+                                     GLint startVertex,
+                                     GLsizei count,
+                                     GLsizei instances)
+{
+    const auto &glState    = data.getState();
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+    if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused())
+    {
+        // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback
+        // won't get the correct output. To work around this, draw with *only* the stream out
+        // first (no pixel shader) to feed the stream out buffers and then draw again with the
+        // geometry shader + pixel shader to rasterize the primitives.
+        mDeviceContext->PSSetShader(nullptr, nullptr, 0);
+
+        if (instances > 0)
+        {
+            mDeviceContext->DrawInstanced(count, instances, 0, 0);
+        }
+        else
+        {
+            mDeviceContext->Draw(count, 0);
+        }
+
+        rx::ShaderExecutableD3D *pixelExe = nullptr;
+        ANGLE_TRY(
+            programD3D->getPixelExecutableForFramebuffer(glState.getDrawFramebuffer(), &pixelExe));
+
+        // Skip the draw call if rasterizer discard is enabled (or no fragment shader).
+        if (!pixelExe || glState.getRasterizerState().rasterizerDiscard)
+        {
+            return gl::NoError();
+        }
+
+        ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader();
+        ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader);
+        mDeviceContext->PSSetShader(pixelShader, nullptr, 0);
+
+        // Retrieve the geometry shader.
+        rx::ShaderExecutableD3D *geometryExe = nullptr;
+        ANGLE_TRY(
+            programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr));
+
+        ID3D11GeometryShader *geometryShader =
+            (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
+        mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
+        ASSERT(geometryShader);
+        mDeviceContext->GSSetShader(geometryShader, nullptr, 0);
+
+        if (instances > 0)
+        {
+            mDeviceContext->DrawInstanced(count, instances, 0, 0);
+        }
+        else
+        {
+            mDeviceContext->Draw(count, 0);
+        }
+        return gl::NoError();
+    }
+
+    if (mode == GL_LINE_LOOP)
+    {
+        return drawLineLoop(data, count, GL_NONE, nullptr, 0, instances);
+    }
+
+    if (mode == GL_TRIANGLE_FAN)
+    {
+        return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
+    }
+
+    bool useInstancedPointSpriteEmulation =
+        programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation;
+
+    if (instances > 0)
+    {
+        if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
+        {
+            // If pointsprite emulation is used with glDrawArraysInstanced then we need to take a
+            // less efficent code path.
+            // Instanced rendering of emulated pointsprites requires a loop to draw each batch of
+            // points. An offset into the instanced data buffer is calculated and applied on each
+            // iteration to ensure all instances are rendered correctly.
+
+            // Each instance being rendered requires the inputlayout cache to reapply buffers and
+            // offsets.
+            for (GLsizei i = 0; i < instances; i++)
+            {
+                ANGLE_TRY(
+                    mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
+                mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+            }
+        }
+        else
+        {
+            mDeviceContext->DrawInstanced(count, instances, 0, 0);
+        }
+        return gl::NoError();
+    }
+
+    // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
+    // Emulating instanced point sprites for FL9_3 requires the topology to be
+    // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
+    if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
+    {
+        mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+    }
+    else
+    {
+        mDeviceContext->Draw(count, 0);
+    }
+    return gl::NoError();
+}
+
+gl::Error Renderer11::drawElementsImpl(const gl::ContextState &data,
+                                       const TranslatedIndexData &indexInfo,
+                                       GLenum mode,
+                                       GLsizei count,
+                                       GLenum type,
+                                       const void *indices,
+                                       GLsizei instances)
+{
+    int startVertex = static_cast<int>(indexInfo.indexRange.start);
+    int baseVertex  = -startVertex;
+
+    if (mode == GL_LINE_LOOP)
+    {
+        return drawLineLoop(data, count, type, indices, baseVertex, instances);
+    }
+
+    if (mode == GL_TRIANGLE_FAN)
+    {
+        return drawTriangleFan(data, count, type, indices, baseVertex, instances);
+    }
+
+    const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram());
+    if (instances > 0)
+    {
+        if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
+        {
+            // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a
+            // less efficent code path.
+            // Instanced rendering of emulated pointsprites requires a loop to draw each batch of
+            // points. An offset into the instanced data buffer is calculated and applied on each
+            // iteration to ensure all instances are rendered correctly.
+            GLsizei elementsToRender = static_cast<GLsizei>(indexInfo.indexRange.vertexCount());
+
+            // Each instance being rendered requires the inputlayout cache to reapply buffers and
+            // offsets.
+            for (GLsizei i = 0; i < instances; i++)
+            {
+                ANGLE_TRY(
+                    mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
+                mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0);
+            }
+        }
+        else
+        {
+            mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertex, 0);
+        }
+        return gl::NoError();
+    }
+
+    // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
+    // Emulating instanced point sprites for FL9_3 requires the topology to be
+    // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
+    if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
+    {
+        // The count parameter passed to drawElements represents the total number of instances
+        // to be rendered. Each instance is referenced by the bound index buffer from the
+        // the caller.
+        //
+        // Indexed pointsprite emulation replicates data for duplicate entries found
+        // in the index buffer.
+        // This is not an efficent rendering mechanism and is only used on downlevel renderers
+        // that do not support geometry shaders.
+        mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+    }
+    else
+    {
+        mDeviceContext->DrawIndexed(count, 0, baseVertex);
+    }
+    return gl::NoError();
+}
+
+bool Renderer11::supportsFastIndirectDraw(const gl::State &state, GLenum mode, GLenum type)
+{
+    const auto &vertexArray = state.getVertexArray();
+    auto *vertexArray11     = GetImplAs<VertexArray11>(vertexArray);
+    // Indirect drawing doesn't support dynamic attribute storage since it needs the first and count
+    // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
+    // either since we need to simulate them in D3D.
+    if (vertexArray11->hasDynamicAttrib(state) || mode == GL_LINE_LOOP || mode == GL_TRIANGLE_FAN)
+    {
+        return false;
+    }
+
+    if (type != GL_NONE)
+    {
+        gl::Buffer *elementArrayBuffer = vertexArray->getElementArrayBuffer().get();
+        ASSERT(elementArrayBuffer);
+        // Only non-streaming index data can be directly used to do indirect draw since they don't
+        // need the indices and count informations. Here we don't check whether it really has
+        // primitive restart index in it since it also needs to know the index range and count.
+        // So, for all other situations, we fall back to normal draw instead of indirect draw.
+        bool primitiveRestartWorkaround = mIndexDataManager->usePrimitiveRestartWorkaround(
+            state.isPrimitiveRestartEnabled(), type);
+        return !mIndexDataManager->isStreamingIndexData(primitiveRestartWorkaround, type,
+                                                        elementArrayBuffer);
+    }
+    return true;
+}
+
+gl::Error Renderer11::drawArraysIndirectImpl(const gl::ContextState &data,
+                                             GLenum mode,
+                                             const void *indirect)
+{
+    if (skipDraw(data, mode))
+    {
+        return gl::NoError();
+    }
+
+    const auto &glState            = data.getState();
+    gl::Buffer *drawIndirectBuffer = glState.getDrawIndirectBuffer();
+    ASSERT(drawIndirectBuffer);
+    Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
+    uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);
+
+    if (supportsFastIndirectDraw(glState, mode, GL_NONE))
+    {
+        applyVertexBuffer(glState, mode, 0, 0, 0, nullptr);
+        ID3D11Buffer *buffer = nullptr;
+        ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDIRECT), buffer);
+        mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset));
+        return gl::NoError();
+    }
+
+    const uint8_t *bufferData = nullptr;
+    ANGLE_TRY(storage->getData(&bufferData));
+    ASSERT(bufferData);
+    const gl::DrawArraysIndirectCommand *args =
+        reinterpret_cast<const gl::DrawArraysIndirectCommand *>(bufferData + offset);
+    GLuint count     = args->count;
+    GLuint instances = args->instanceCount;
+    GLuint first     = args->first;
+
+    ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));
+
+    if (mode == GL_LINE_LOOP)
+    {
+        return drawLineLoop(data, count, GL_NONE, nullptr, 0, instances);
+    }
+    if (mode == GL_TRIANGLE_FAN)
+    {
+        return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
+    }
+
+    mDeviceContext->DrawInstanced(count, instances, 0, 0);
+    return gl::NoError();
+}
+
+gl::Error Renderer11::drawElementsIndirectImpl(const gl::ContextState &data,
+                                               GLenum mode,
+                                               GLenum type,
+                                               const void *indirect)
+{
+    if (skipDraw(data, mode))
+    {
+        return gl::NoError();
+    }
+
+    const auto &glState            = data.getState();
+    gl::Buffer *drawIndirectBuffer = glState.getDrawIndirectBuffer();
+    ASSERT(drawIndirectBuffer);
+    Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
+    uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);
+
+    TranslatedIndexData indexInfo;
+    if (supportsFastIndirectDraw(glState, mode, type))
+    {
+        ANGLE_TRY(applyIndexBuffer(data, nullptr, 0, mode, type, &indexInfo));
+        ANGLE_TRY(applyVertexBuffer(glState, mode, 0, 0, 0, &indexInfo));
+        ID3D11Buffer *buffer = nullptr;
+        ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDIRECT), buffer);
+        mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset));
+        return gl::NoError();
+    }
+
+    const uint8_t *bufferData = nullptr;
+    ANGLE_TRY(storage->getData(&bufferData));
+    ASSERT(bufferData);
+
+    const gl::DrawElementsIndirectCommand *cmd =
+        reinterpret_cast<const gl::DrawElementsIndirectCommand *>(bufferData + offset);
+    GLuint count      = cmd->count;
+    GLuint instances  = cmd->primCount;
+    GLuint firstIndex = cmd->firstIndex;
+    GLint baseVertex  = cmd->baseVertex;
+
+    const gl::Type &typeInfo = gl::GetTypeInfo(type);
+    uint8_t *indices         = static_cast<uint8_t *>(0) + firstIndex * typeInfo.bytes;
+
+    gl::Buffer *elementArrayBuffer = glState.getVertexArray()->getElementArrayBuffer().get();
+    ASSERT(elementArrayBuffer);
+    gl::IndexRange indexRange;
+    ANGLE_TRY(elementArrayBuffer->getIndexRange(type, reinterpret_cast<size_t>(indices), count,
+                                                glState.isPrimitiveRestartEnabled(), &indexRange));
+
+    indexInfo.indexRange = indexRange;
+    ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo));
+    size_t vertexCount = indexRange.vertexCount();
+    ANGLE_TRY(applyVertexBuffer(glState, mode, static_cast<GLsizei>(indexRange.start) + baseVertex,
+                                static_cast<GLsizei>(vertexCount), instances, &indexInfo));
+
+    int baseVertexLocation = -static_cast<int>(indexRange.start);
+    if (mode == GL_LINE_LOOP)
+    {
+        return drawLineLoop(data, count, type, indices, baseVertexLocation, instances);
+    }
+
+    if (mode == GL_TRIANGLE_FAN)
+    {
+        return drawTriangleFan(data, count, type, indices, baseVertexLocation, instances);
+    }
+
+    mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertexLocation, 0);
+    return gl::NoError();
+}
+
+gl::Error Renderer11::drawLineLoop(const gl::ContextState &data,
+                                   GLsizei count,
+                                   GLenum type,
+                                   const void *indexPointer,
+                                   int baseVertex,
+                                   int instances)
+{
+    const auto &glState            = data.getState();
+    gl::VertexArray *vao           = glState.getVertexArray();
+    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+    const void *indices = indexPointer;
+
+    // Get the raw indices for an indexed draw
+    if (type != GL_NONE && elementArrayBuffer)
+    {
+        BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+        intptr_t offset    = reinterpret_cast<intptr_t>(indices);
+
+        const uint8_t *bufferData = nullptr;
+        ANGLE_TRY(storage->getData(&bufferData));
+
+        indices = bufferData + offset;
+    }
+
+    if (!mLineLoopIB)
+    {
+        mLineLoopIB = new StreamingIndexBufferInterface(this);
+        gl::Error error =
+            mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+        if (error.isError())
+        {
+            SafeDelete(mLineLoopIB);
+            return error;
+        }
+    }
+
+    // Checked by Renderer11::applyPrimitiveType
+    ASSERT(count >= 0);
+
+    if (static_cast<unsigned int>(count) + 1 >
+        (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too "
+                         "many indices required.");
+    }
+
+    GetLineLoopIndices(indices, type, static_cast<GLuint>(count),
+                       glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer);
+
+    unsigned int spaceNeeded =
+        static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size());
+    ANGLE_TRY(mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
+
+    void *mappedMemory = nullptr;
+    unsigned int offset;
+    ANGLE_TRY(mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
+
+    // Copy over the converted index data.
+    memcpy(mappedMemory, &mScratchIndexDataBuffer[0],
+           sizeof(GLuint) * mScratchIndexDataBuffer.size());
+
+    ANGLE_TRY(mLineLoopIB->unmapBuffer());
+
+    IndexBuffer11 *indexBuffer   = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer());
+    ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
+    DXGI_FORMAT indexFormat      = indexBuffer->getIndexFormat();
+
+    if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
+        mAppliedIBOffset != offset)
+    {
+        mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
+        mAppliedIB       = d3dIndexBuffer;
+        mAppliedIBFormat = indexFormat;
+        mAppliedIBOffset = offset;
+    }
+
+    UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
+
+    if (instances > 0)
+    {
+        mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
+    }
+    else
+    {
+        mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::drawTriangleFan(const gl::ContextState &data,
+                                      GLsizei count,
+                                      GLenum type,
+                                      const void *indices,
+                                      int baseVertex,
+                                      int instances)
+{
+    gl::VertexArray *vao           = data.getState().getVertexArray();
+    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+    const void *indexPointer = indices;
+
+    // Get the raw indices for an indexed draw
+    if (type != GL_NONE && elementArrayBuffer)
+    {
+        BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+        intptr_t offset    = reinterpret_cast<intptr_t>(indices);
+
+        const uint8_t *bufferData = nullptr;
+        ANGLE_TRY(storage->getData(&bufferData));
+
+        indexPointer = bufferData + offset;
+    }
+
+    if (!mTriangleFanIB)
+    {
+        mTriangleFanIB = new StreamingIndexBufferInterface(this);
+        gl::Error error =
+            mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+        if (error.isError())
+        {
+            SafeDelete(mTriangleFanIB);
+            return error;
+        }
+    }
+
+    // Checked by Renderer11::applyPrimitiveType
+    ASSERT(count >= 3);
+
+    const GLuint numTris = count - 2;
+
+    if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many "
+                         "indices required.");
+    }
+
+    GetTriFanIndices(indexPointer, type, count, data.getState().isPrimitiveRestartEnabled(),
+                     &mScratchIndexDataBuffer);
+
+    const unsigned int spaceNeeded =
+        static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int));
+    ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
+
+    void *mappedMemory = nullptr;
+    unsigned int offset;
+    ANGLE_TRY(mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
+
+    memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded);
+
+    ANGLE_TRY(mTriangleFanIB->unmapBuffer());
+
+    IndexBuffer11 *indexBuffer   = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer());
+    ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
+    DXGI_FORMAT indexFormat      = indexBuffer->getIndexFormat();
+
+    if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
+        mAppliedIBOffset != offset)
+    {
+        mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
+        mAppliedIB       = d3dIndexBuffer;
+        mAppliedIBFormat = indexFormat;
+        mAppliedIBOffset = offset;
+    }
+
+    UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
+
+    if (instances > 0)
+    {
+        mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
+    }
+    else
+    {
+        mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::applyShaders(const gl::ContextState &data, GLenum drawMode)
+{
+    // This method is called single-threaded.
+    ANGLE_TRY(ensureHLSLCompilerInitialized());
+
+    const auto &glState    = data.getState();
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+    programD3D->updateCachedInputLayout(glState);
+
+    const auto &inputLayout = programD3D->getCachedInputLayout();
+
+    ShaderExecutableD3D *vertexExe = nullptr;
+    ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr));
+
+    const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+    ShaderExecutableD3D *pixelExe          = nullptr;
+    ANGLE_TRY(programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe));
+
+    ShaderExecutableD3D *geometryExe = nullptr;
+    ANGLE_TRY(
+        programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr));
+
+    ID3D11VertexShader *vertexShader =
+        (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
+
+    ID3D11PixelShader *pixelShader = nullptr;
+    // Skip pixel shader if we're doing rasterizer discard.
+    bool rasterizerDiscard = glState.getRasterizerState().rasterizerDiscard;
+    if (!rasterizerDiscard)
+    {
+        pixelShader = (pixelExe ? GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr);
+    }
+
+    ID3D11GeometryShader *geometryShader = nullptr;
+    bool transformFeedbackActive         = glState.isTransformFeedbackActiveUnpaused();
+    if (transformFeedbackActive)
+    {
+        geometryShader =
+            (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
+    }
+    else
+    {
+        geometryShader =
+            (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
+    }
+
+    bool dirtyUniforms = false;
+
+    if (reinterpret_cast<uintptr_t>(vertexShader) != mAppliedVertexShader)
+    {
+        mDeviceContext->VSSetShader(vertexShader, nullptr, 0);
+        mAppliedVertexShader = reinterpret_cast<uintptr_t>(vertexShader);
+        dirtyUniforms        = true;
+    }
+
+    if (reinterpret_cast<uintptr_t>(geometryShader) != mAppliedGeometryShader)
+    {
+        mDeviceContext->GSSetShader(geometryShader, nullptr, 0);
+        mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
+        dirtyUniforms          = true;
+    }
+
+    if (reinterpret_cast<uintptr_t>(pixelShader) != mAppliedPixelShader)
+    {
+        mDeviceContext->PSSetShader(pixelShader, nullptr, 0);
+        mAppliedPixelShader = reinterpret_cast<uintptr_t>(pixelShader);
+        dirtyUniforms       = true;
+    }
+
+    if (dirtyUniforms)
+    {
+        programD3D->dirtyAllUniforms();
+    }
+
+    return programD3D->applyUniforms(drawMode);
+}
+
+gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
+                                    GLenum drawMode,
+                                    const std::vector<D3DUniform *> &uniformArray)
+{
+    unsigned int totalRegisterCountVS = 0;
+    unsigned int totalRegisterCountPS = 0;
+
+    bool vertexUniformsDirty = false;
+    bool pixelUniformsDirty  = false;
+
+    for (const D3DUniform *uniform : uniformArray)
+    {
+        if (uniform->isReferencedByVertexShader() && !uniform->isSampler())
+        {
+            totalRegisterCountVS += uniform->registerCount;
+            vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty);
+        }
+
+        if (uniform->isReferencedByFragmentShader() && !uniform->isSampler())
+        {
+            totalRegisterCountPS += uniform->registerCount;
+            pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty);
+        }
+    }
+
+    const UniformStorage11 *vertexUniformStorage =
+        GetAs<UniformStorage11>(&programD3D.getVertexUniformStorage());
+    const UniformStorage11 *fragmentUniformStorage =
+        GetAs<UniformStorage11>(&programD3D.getFragmentUniformStorage());
+    ASSERT(vertexUniformStorage);
+    ASSERT(fragmentUniformStorage);
+
+    ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer();
+    ID3D11Buffer *pixelConstantBuffer  = fragmentUniformStorage->getConstantBuffer();
+
+    float(*mapVS)[4] = nullptr;
+    float(*mapPS)[4] = nullptr;
+
+    if (totalRegisterCountVS > 0 && vertexUniformsDirty)
+    {
+        D3D11_MAPPED_SUBRESOURCE map = {0};
+        HRESULT result =
+            mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+        ASSERT(SUCCEEDED(result));
+        mapVS = (float(*)[4])map.pData;
+    }
+
+    if (totalRegisterCountPS > 0 && pixelUniformsDirty)
+    {
+        D3D11_MAPPED_SUBRESOURCE map = {0};
+        HRESULT result =
+            mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+        ASSERT(SUCCEEDED(result));
+        mapPS = (float(*)[4])map.pData;
+    }
+
+    for (const D3DUniform *uniform : uniformArray)
+    {
+        if (uniform->isSampler())
+            continue;
+
+        unsigned int componentCount = (4 - uniform->registerElement);
+
+        // we assume that uniforms from structs are arranged in struct order in our uniforms list.
+        // otherwise we would overwrite previously written regions of memory.
+
+        if (uniform->isReferencedByVertexShader() && mapVS)
+        {
+            memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data,
+                   uniform->registerCount * sizeof(float) * componentCount);
+        }
+
+        if (uniform->isReferencedByFragmentShader() && mapPS)
+        {
+            memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data,
+                   uniform->registerCount * sizeof(float) * componentCount);
+        }
+    }
+
+    if (mapVS)
+    {
+        mDeviceContext->Unmap(vertexConstantBuffer, 0);
+    }
+
+    if (mapPS)
+    {
+        mDeviceContext->Unmap(pixelConstantBuffer, 0);
+    }
+
+    if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
+    {
+        mDeviceContext->VSSetConstantBuffers(
+            d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &vertexConstantBuffer);
+        mCurrentVertexConstantBuffer = vertexConstantBuffer;
+    }
+
+    if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
+    {
+        mDeviceContext->PSSetConstantBuffers(
+            d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &pixelConstantBuffer);
+        mCurrentPixelConstantBuffer = pixelConstantBuffer;
+    }
+
+    if (!mDriverConstantBufferVS)
+    {
+        D3D11_BUFFER_DESC constantBufferDescription = {0};
+        d3d11::InitConstantBufferDesc(
+            &constantBufferDescription,
+            sizeof(dx_VertexConstants11) + mSamplerMetadataVS.sizeBytes());
+        HRESULT result =
+            mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferVS);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create vertex shader constant buffer, result: 0x%X.",
+                             result);
+        }
+        mDeviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+                                             &mDriverConstantBufferVS);
+    }
+    if (!mDriverConstantBufferPS)
+    {
+        D3D11_BUFFER_DESC constantBufferDescription = {0};
+        d3d11::InitConstantBufferDesc(&constantBufferDescription,
+                                      sizeof(dx_PixelConstants11) + mSamplerMetadataPS.sizeBytes());
+        HRESULT result =
+            mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferPS);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create pixel shader constant buffer, result: 0x%X.",
+                             result);
+        }
+        mDeviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+                                             &mDriverConstantBufferPS);
+    }
+
+    // Sampler metadata and driver constants need to coexist in the same constant buffer to conserve
+    // constant buffer slots. We update both in the constant buffer if needed.
+    const dx_VertexConstants11 &vertexConstants = mStateManager.getVertexConstants();
+    size_t samplerMetadataReferencedBytesVS     = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
+                                              programD3D.getUsedSamplerRange(gl::SAMPLER_VERTEX);
+    applyDriverConstantsIfNeeded(&mAppliedVertexConstants, vertexConstants, &mSamplerMetadataVS,
+                                 samplerMetadataReferencedBytesVS, mDriverConstantBufferVS);
+
+    const dx_PixelConstants11 &pixelConstants = mStateManager.getPixelConstants();
+    size_t samplerMetadataReferencedBytesPS   = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
+                                              programD3D.getUsedSamplerRange(gl::SAMPLER_PIXEL);
+    applyDriverConstantsIfNeeded(&mAppliedPixelConstants, pixelConstants, &mSamplerMetadataPS,
+                                 samplerMetadataReferencedBytesPS, mDriverConstantBufferPS);
+
+    // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary
+    if (programD3D.usesGeometryShader(drawMode))
+    {
+        // needed for the point sprite geometry shader
+        if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
+        {
+            ASSERT(mDriverConstantBufferPS != nullptr);
+            mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
+            mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
+        }
+    }
+
+    return gl::NoError();
+}
+
+// SamplerMetadataD3D11 implementation
+
+Renderer11::SamplerMetadataD3D11::SamplerMetadataD3D11() : mDirty(true)
+{
+}
+
+Renderer11::SamplerMetadataD3D11::~SamplerMetadataD3D11()
+{
+}
+
+void Renderer11::SamplerMetadataD3D11::initData(unsigned int samplerCount)
+{
+    mSamplerMetadata.resize(samplerCount);
+}
+
+void Renderer11::SamplerMetadataD3D11::update(unsigned int samplerIndex, const gl::Texture &texture)
+{
+    unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel();
+    GLenum sizedFormat =
+        texture.getFormat(texture.getTarget(), baseLevel).info->sizedInternalFormat;
+    if (mSamplerMetadata[samplerIndex].baseLevel != static_cast<int>(baseLevel))
+    {
+        mSamplerMetadata[samplerIndex].baseLevel = static_cast<int>(baseLevel);
+        mDirty                                   = true;
+    }
+
+    // Some metadata is needed only for integer textures. We avoid updating the constant buffer
+    // unnecessarily by changing the data only in case the texture is an integer texture and
+    // the values have changed.
+    bool needIntegerTextureMetadata = false;
+    // internalFormatBits == 0 means a 32-bit texture in the case of integer textures.
+    int internalFormatBits = 0;
+    switch (sizedFormat)
+    {
+        case GL_RGBA32I:
+        case GL_RGBA32UI:
+        case GL_RGB32I:
+        case GL_RGB32UI:
+        case GL_RG32I:
+        case GL_RG32UI:
+        case GL_R32I:
+        case GL_R32UI:
+            needIntegerTextureMetadata = true;
+            break;
+        case GL_RGBA16I:
+        case GL_RGBA16UI:
+        case GL_RGB16I:
+        case GL_RGB16UI:
+        case GL_RG16I:
+        case GL_RG16UI:
+        case GL_R16I:
+        case GL_R16UI:
+            needIntegerTextureMetadata = true;
+            internalFormatBits         = 16;
+            break;
+        case GL_RGBA8I:
+        case GL_RGBA8UI:
+        case GL_RGB8I:
+        case GL_RGB8UI:
+        case GL_RG8I:
+        case GL_RG8UI:
+        case GL_R8I:
+        case GL_R8UI:
+            needIntegerTextureMetadata = true;
+            internalFormatBits         = 8;
+            break;
+        case GL_RGB10_A2UI:
+            needIntegerTextureMetadata = true;
+            internalFormatBits         = 10;
+            break;
+        default:
+            break;
+    }
+    if (needIntegerTextureMetadata)
+    {
+        if (mSamplerMetadata[samplerIndex].internalFormatBits != internalFormatBits)
+        {
+            mSamplerMetadata[samplerIndex].internalFormatBits = internalFormatBits;
+            mDirty                                            = true;
+        }
+        // Pack the wrap values into one integer so we can fit all the metadata in one 4-integer
+        // vector.
+        GLenum wrapS  = texture.getWrapS();
+        GLenum wrapT  = texture.getWrapT();
+        GLenum wrapR  = texture.getWrapR();
+        int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4);
+        if (mSamplerMetadata[samplerIndex].wrapModes != wrapModes)
+        {
+            mSamplerMetadata[samplerIndex].wrapModes = wrapModes;
+            mDirty                                   = true;
+        }
+    }
+}
+
+const Renderer11::SamplerMetadataD3D11::dx_SamplerMetadata *
+Renderer11::SamplerMetadataD3D11::getData() const
+{
+    return mSamplerMetadata.data();
+}
+
+size_t Renderer11::SamplerMetadataD3D11::sizeBytes() const
+{
+    return sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) * mSamplerMetadata.size();
+}
+
+template <class TShaderConstants>
+void Renderer11::applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants,
+                                              const TShaderConstants &constants,
+                                              SamplerMetadataD3D11 *samplerMetadata,
+                                              size_t samplerMetadataReferencedBytes,
+                                              ID3D11Buffer *driverConstantBuffer)
+{
+    ASSERT(driverConstantBuffer != nullptr);
+    if (memcmp(appliedConstants, &constants, sizeof(TShaderConstants)) != 0 ||
+        samplerMetadata->isDirty())
+    {
+        memcpy(appliedConstants, &constants, sizeof(TShaderConstants));
+
+        D3D11_MAPPED_SUBRESOURCE mapping = {0};
+        HRESULT result =
+            mDeviceContext->Map(driverConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping);
+        ASSERT(SUCCEEDED(result));
+        memcpy(mapping.pData, appliedConstants, sizeof(TShaderConstants));
+        // Previous buffer contents were discarded, so we need to refresh also the area of the
+        // buffer that isn't used by this program.
+        memcpy(&reinterpret_cast<uint8_t *>(mapping.pData)[sizeof(TShaderConstants)],
+               samplerMetadata->getData(), samplerMetadata->sizeBytes());
+        mDeviceContext->Unmap(driverConstantBuffer, 0);
+
+        samplerMetadata->markClean();
+    }
+}
+
+template void Renderer11::applyDriverConstantsIfNeeded<dx_VertexConstants11>(
+    dx_VertexConstants11 *appliedConstants,
+    const dx_VertexConstants11 &constants,
+    SamplerMetadataD3D11 *samplerMetadata,
+    size_t samplerMetadataReferencedBytes,
+    ID3D11Buffer *driverConstantBuffer);
+template void Renderer11::applyDriverConstantsIfNeeded<dx_PixelConstants11>(
+    dx_PixelConstants11 *appliedConstants,
+    const dx_PixelConstants11 &constants,
+    SamplerMetadataD3D11 *samplerMetadata,
+    size_t samplerMetadataReferencedBytes,
+    ID3D11Buffer *driverConstantBuffer);
+template void Renderer11::applyDriverConstantsIfNeeded<dx_ComputeConstants11>(
+    dx_ComputeConstants11 *appliedConstants,
+    const dx_ComputeConstants11 &constants,
+    SamplerMetadataD3D11 *samplerMetadata,
+    size_t samplerMetadataReferencedBytes,
+    ID3D11Buffer *driverConstantBuffer);
+
+void Renderer11::markAllStateDirty()
+{
+    TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty");
+
+    for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId)
+    {
+        mForceSetVertexSamplerStates[vsamplerId] = true;
+    }
+
+    for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId)
+    {
+        mForceSetPixelSamplerStates[fsamplerId] = true;
+    }
+
+    for (size_t csamplerId = 0; csamplerId < mForceSetComputeSamplerStates.size(); ++csamplerId)
+    {
+        mForceSetComputeSamplerStates[csamplerId] = true;
+    }
+
+    mStateManager.invalidateEverything();
+
+    mAppliedIB       = nullptr;
+    mAppliedIBFormat = DXGI_FORMAT_UNKNOWN;
+    mAppliedIBOffset = 0;
+
+    mAppliedVertexShader   = angle::DirtyPointer;
+    mAppliedGeometryShader = angle::DirtyPointer;
+    mAppliedPixelShader    = angle::DirtyPointer;
+    mAppliedComputeShader  = angle::DirtyPointer;
+
+    mAppliedTFObject = angle::DirtyPointer;
+
+    memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11));
+    memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11));
+
+    mInputLayoutCache.markDirty();
+
+    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++)
+    {
+        mCurrentConstantBufferVS[i]       = static_cast<unsigned int>(-1);
+        mCurrentConstantBufferVSOffset[i] = 0;
+        mCurrentConstantBufferVSSize[i]   = 0;
+        mCurrentConstantBufferPS[i]       = static_cast<unsigned int>(-1);
+        mCurrentConstantBufferPSOffset[i] = 0;
+        mCurrentConstantBufferPSSize[i]   = 0;
+    }
+
+    mCurrentVertexConstantBuffer   = nullptr;
+    mCurrentPixelConstantBuffer    = nullptr;
+    mCurrentGeometryConstantBuffer = nullptr;
+    mCurrentComputeConstantBuffer  = nullptr;
+
+    mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+}
+
+void Renderer11::releaseDeviceResources()
+{
+    mStateManager.deinitialize();
+    mStateCache.clear();
+    mInputLayoutCache.clear();
+
+    SafeDelete(mVertexDataManager);
+    SafeDelete(mIndexDataManager);
+    SafeDelete(mLineLoopIB);
+    SafeDelete(mTriangleFanIB);
+    SafeDelete(mBlit);
+    SafeDelete(mClear);
+    SafeDelete(mTrim);
+    SafeDelete(mPixelTransfer);
+
+    SafeRelease(mDriverConstantBufferVS);
+    SafeRelease(mDriverConstantBufferPS);
+    SafeRelease(mDriverConstantBufferCS);
+    SafeRelease(mSyncQuery);
+}
+
+// set notify to true to broadcast a message to all contexts of the device loss
+bool Renderer11::testDeviceLost()
+{
+    bool isLost = false;
+
+    if (!mDevice)
+    {
+        return true;
+    }
+
+    // GetRemovedReason is used to test if the device is removed
+    HRESULT result = mDevice->GetDeviceRemovedReason();
+    isLost         = d3d11::isDeviceLostError(result);
+
+    if (isLost)
+    {
+        ERR() << "The D3D11 device was removed, " << gl::FmtHR(result);
+    }
+
+    return isLost;
+}
+
+bool Renderer11::testDeviceResettable()
+{
+    // determine if the device is resettable by creating a dummy device
+    PFN_D3D11_CREATE_DEVICE D3D11CreateDevice =
+        (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+
+    if (D3D11CreateDevice == nullptr)
+    {
+        return false;
+    }
+
+    ID3D11Device *dummyDevice;
+    D3D_FEATURE_LEVEL dummyFeatureLevel;
+    ID3D11DeviceContext *dummyContext;
+
+    ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN);
+    HRESULT result = D3D11CreateDevice(
+        nullptr, mRequestedDriverType, nullptr,
+#if defined(_DEBUG)
+        D3D11_CREATE_DEVICE_DEBUG,
+#else
+        0,
+#endif
+        mAvailableFeatureLevels.data(), static_cast<unsigned int>(mAvailableFeatureLevels.size()),
+        D3D11_SDK_VERSION, &dummyDevice, &dummyFeatureLevel, &dummyContext);
+
+    if (!mDevice || FAILED(result))
+    {
+        return false;
+    }
+
+    SafeRelease(dummyContext);
+    SafeRelease(dummyDevice);
+
+    return true;
+}
+
+void Renderer11::release()
+{
+    RendererD3D::cleanup();
+
+    mScratchMemoryBuffer.clear();
+
+    if (mAnnotator != nullptr)
+    {
+        gl::UninitializeDebugAnnotations();
+        SafeDelete(mAnnotator);
+    }
+
+    releaseDeviceResources();
+
+    if (!mCreatedWithDeviceEXT)
+    {
+        // Only delete the device if the Renderer11 owns it
+        // Otherwise we should keep it around in case we try to reinitialize the renderer later
+        SafeDelete(mEGLDevice);
+    }
+
+    SafeRelease(mDxgiFactory);
+    SafeRelease(mDxgiAdapter);
+
+    SafeRelease(mDeviceContext1);
+
+    if (mDeviceContext)
+    {
+        mDeviceContext->ClearState();
+        mDeviceContext->Flush();
+        SafeRelease(mDeviceContext);
+    }
+
+    SafeRelease(mDevice);
+    SafeRelease(mDebug);
+
+    if (mD3d11Module)
+    {
+        FreeLibrary(mD3d11Module);
+        mD3d11Module = nullptr;
+    }
+
+    if (mDxgiModule)
+    {
+        FreeLibrary(mDxgiModule);
+        mDxgiModule = nullptr;
+    }
+
+    if (mDCompModule)
+    {
+        FreeLibrary(mDCompModule);
+        mDCompModule = nullptr;
+    }
+
+    mCompiler.release();
+
+    mSupportsShareHandles.reset();
+}
+
+bool Renderer11::resetDevice()
+{
+    // recreate everything
+    release();
+    egl::Error result = initialize();
+
+    if (result.isError())
+    {
+        ERR() << "Could not reinitialize D3D11 device: " << result;
+        return false;
+    }
+
+    return true;
+}
+
+std::string Renderer11::getRendererDescription() const
+{
+    std::ostringstream rendererString;
+
+    rendererString << mDescription;
+    rendererString << " Direct3D11";
+
+    rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel()
+                   << getShaderModelSuffix();
+    rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel()
+                   << getShaderModelSuffix();
+
+    return rendererString.str();
+}
+
+DeviceIdentifier Renderer11::getAdapterIdentifier() const
+{
+    // Don't use the AdapterLuid here, since that doesn't persist across reboot.
+    DeviceIdentifier deviceIdentifier = {0};
+    deviceIdentifier.VendorId         = mAdapterDescription.VendorId;
+    deviceIdentifier.DeviceId         = mAdapterDescription.DeviceId;
+    deviceIdentifier.SubSysId         = mAdapterDescription.SubSysId;
+    deviceIdentifier.Revision         = mAdapterDescription.Revision;
+    deviceIdentifier.FeatureLevel     = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel);
+
+    return deviceIdentifier;
+}
+
+unsigned int Renderer11::getReservedVertexUniformVectors() const
+{
+    // Driver uniforms are stored in a separate constant buffer
+    return d3d11_gl::GetReservedVertexUniformVectors(mRenderer11DeviceCaps.featureLevel);
+}
+
+unsigned int Renderer11::getReservedFragmentUniformVectors() const
+{
+    // Driver uniforms are stored in a separate constant buffer
+    return d3d11_gl::GetReservedFragmentUniformVectors(mRenderer11DeviceCaps.featureLevel);
+}
+
+unsigned int Renderer11::getReservedVertexUniformBuffers() const
+{
+    // we reserve one buffer for the application uniforms, and one for driver uniforms
+    return 2;
+}
+
+unsigned int Renderer11::getReservedFragmentUniformBuffers() const
+{
+    // we reserve one buffer for the application uniforms, and one for driver uniforms
+    return 2;
+}
+
+d3d11::ANGLED3D11DeviceType Renderer11::getDeviceType() const
+{
+    if (mCreatedWithDeviceEXT)
+    {
+        return d3d11::GetDeviceType(mDevice);
+    }
+
+    if ((mRequestedDriverType == D3D_DRIVER_TYPE_SOFTWARE) ||
+        (mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE) ||
+        (mRequestedDriverType == D3D_DRIVER_TYPE_NULL))
+    {
+        return d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
+    }
+
+    if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
+    {
+        return d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP;
+    }
+
+    return d3d11::ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
+}
+
+bool Renderer11::getShareHandleSupport() const
+{
+    if (mSupportsShareHandles.valid())
+    {
+        return mSupportsShareHandles.value();
+    }
+
+    // We only currently support share handles with BGRA surfaces, because
+    // chrome needs BGRA. Once chrome fixes this, we should always support them.
+    if (!getNativeExtensions().textureFormatBGRA8888)
+    {
+        mSupportsShareHandles = false;
+        return false;
+    }
+
+    // PIX doesn't seem to support using share handles, so disable them.
+    if (gl::DebugAnnotationsActive())
+    {
+        mSupportsShareHandles = false;
+        return false;
+    }
+
+    // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on
+    // RGBA8 textures/swapchains.
+    if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        mSupportsShareHandles = false;
+        return false;
+    }
+
+    // Find out which type of D3D11 device the Renderer11 is using
+    d3d11::ANGLED3D11DeviceType deviceType = getDeviceType();
+    if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_UNKNOWN)
+    {
+        mSupportsShareHandles = false;
+        return false;
+    }
+
+    if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL)
+    {
+        // Software/Reference/NULL devices don't support share handles
+        mSupportsShareHandles = false;
+        return false;
+    }
+
+    if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP)
+    {
+#ifndef ANGLE_ENABLE_WINDOWS_STORE
+        if (!IsWindows8OrGreater())
+        {
+            // WARP on Windows 7 doesn't support shared handles
+            mSupportsShareHandles = false;
+            return false;
+        }
+#endif  // ANGLE_ENABLE_WINDOWS_STORE
+
+        // WARP on Windows 8.0+ supports shared handles when shared with another WARP device
+        // TODO: allow applications to query for HARDWARE or WARP-specific share handles,
+        //       to prevent them trying to use a WARP share handle with an a HW device (or
+        //       vice-versa)
+        //       e.g. by creating EGL_D3D11_[HARDWARE/WARP]_DEVICE_SHARE_HANDLE_ANGLE
+        mSupportsShareHandles = true;
+        return true;
+    }
+
+    ASSERT(mCreatedWithDeviceEXT || mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE);
+    mSupportsShareHandles = true;
+    return true;
+}
+
+bool Renderer11::getNV12TextureSupport() const
+{
+    HRESULT result;
+    UINT formatSupport;
+    result = mDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
+    if (result == E_FAIL)
+    {
+        return false;
+    }
+    return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
+}
+
+int Renderer11::getMajorShaderModel() const
+{
+    switch (mRenderer11DeviceCaps.featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_SHADER_MAJOR_VERSION;  // 5
+        case D3D_FEATURE_LEVEL_10_1:
+            return D3D10_1_SHADER_MAJOR_VERSION;  // 4
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_SHADER_MAJOR_VERSION;  // 4
+        case D3D_FEATURE_LEVEL_9_3:
+            return D3D10_SHADER_MAJOR_VERSION;  // 4
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+int Renderer11::getMinorShaderModel() const
+{
+    switch (mRenderer11DeviceCaps.featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_SHADER_MINOR_VERSION;  // 0
+        case D3D_FEATURE_LEVEL_10_1:
+            return D3D10_1_SHADER_MINOR_VERSION;  // 1
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_SHADER_MINOR_VERSION;  // 0
+        case D3D_FEATURE_LEVEL_9_3:
+            return D3D10_SHADER_MINOR_VERSION;  // 0
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+std::string Renderer11::getShaderModelSuffix() const
+{
+    switch (mRenderer11DeviceCaps.featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_0:
+            return "";
+        case D3D_FEATURE_LEVEL_10_1:
+            return "";
+        case D3D_FEATURE_LEVEL_10_0:
+            return "";
+        case D3D_FEATURE_LEVEL_9_3:
+            return "_level_9_3";
+        default:
+            UNREACHABLE();
+            return "";
+    }
+}
+
+const angle::WorkaroundsD3D &RendererD3D::getWorkarounds() const
+{
+    if (!mWorkaroundsInitialized)
+    {
+        mWorkarounds            = generateWorkarounds();
+        mWorkaroundsInitialized = true;
+    }
+
+    return mWorkarounds;
+}
+
+gl::Error Renderer11::copyImageInternal(const gl::Framebuffer *framebuffer,
+                                        const gl::Rectangle &sourceRect,
+                                        GLenum destFormat,
+                                        const gl::Offset &destOffset,
+                                        RenderTargetD3D *destRenderTarget)
+{
+    const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorbuffer();
+    ASSERT(colorAttachment);
+
+    RenderTarget11 *sourceRenderTarget = nullptr;
+    ANGLE_TRY(colorAttachment->getRenderTarget(&sourceRenderTarget));
+    ASSERT(sourceRenderTarget);
+
+    ID3D11ShaderResourceView *source = sourceRenderTarget->getBlitShaderResourceView();
+    ASSERT(source);
+
+    const d3d11::RenderTargetView &dest =
+        GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
+    ASSERT(dest.valid());
+
+    gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
+    gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
+
+    const bool invertSource = UsePresentPathFast(this, colorAttachment);
+    if (invertSource)
+    {
+        sourceArea.y      = sourceSize.height - sourceRect.y;
+        sourceArea.height = -sourceArea.height;
+    }
+
+    gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
+    gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
+
+    // Use nearest filtering because source and destination are the same size for the direct copy.
+    // Convert to the unsized format before calling copyTexture.
+    ANGLE_TRY(mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, nullptr,
+                                 gl::GetUnsizedFormat(destFormat), GL_NEAREST, false, false,
+                                 false));
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer,
+                                  const gl::Rectangle &sourceRect,
+                                  GLenum destFormat,
+                                  const gl::Offset &destOffset,
+                                  TextureStorage *storage,
+                                  GLint level)
+{
+    TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage);
+    ASSERT(storage11);
+
+    gl::ImageIndex index              = gl::ImageIndex::Make2D(level);
+    RenderTargetD3D *destRenderTarget = nullptr;
+    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
+    ASSERT(destRenderTarget);
+
+    ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));
+
+    storage11->markLevelDirty(level);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer,
+                                    const gl::Rectangle &sourceRect,
+                                    GLenum destFormat,
+                                    const gl::Offset &destOffset,
+                                    TextureStorage *storage,
+                                    GLenum target,
+                                    GLint level)
+{
+    TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage);
+    ASSERT(storage11);
+
+    gl::ImageIndex index              = gl::ImageIndex::MakeCube(target, level);
+    RenderTargetD3D *destRenderTarget = nullptr;
+    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
+    ASSERT(destRenderTarget);
+
+    ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));
+
+    storage11->markLevelDirty(level);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer,
+                                  const gl::Rectangle &sourceRect,
+                                  GLenum destFormat,
+                                  const gl::Offset &destOffset,
+                                  TextureStorage *storage,
+                                  GLint level)
+{
+    TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage);
+    ASSERT(storage11);
+
+    gl::ImageIndex index              = gl::ImageIndex::Make3D(level, destOffset.z);
+    RenderTargetD3D *destRenderTarget = nullptr;
+    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
+    ASSERT(destRenderTarget);
+
+    ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));
+
+    storage11->markLevelDirty(level);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer,
+                                       const gl::Rectangle &sourceRect,
+                                       GLenum destFormat,
+                                       const gl::Offset &destOffset,
+                                       TextureStorage *storage,
+                                       GLint level)
+{
+    TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage);
+    ASSERT(storage11);
+
+    gl::ImageIndex index              = gl::ImageIndex::Make2DArray(level, destOffset.z);
+    RenderTargetD3D *destRenderTarget = nullptr;
+    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
+    ASSERT(destRenderTarget);
+
+    ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));
+    storage11->markLevelDirty(level);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::copyTexture(const gl::Texture *source,
+                                  GLint sourceLevel,
+                                  const gl::Rectangle &sourceRect,
+                                  GLenum destFormat,
+                                  const gl::Offset &destOffset,
+                                  TextureStorage *storage,
+                                  GLenum destTarget,
+                                  GLint destLevel,
+                                  bool unpackFlipY,
+                                  bool unpackPremultiplyAlpha,
+                                  bool unpackUnmultiplyAlpha)
+{
+    const TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+
+    TextureStorage *sourceStorage = nullptr;
+    ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(&sourceStorage));
+
+    ASSERT(destTarget == GL_TEXTURE_2D);
+    TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
+    ASSERT(sourceStorage11);
+
+    TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
+    ASSERT(destStorage11);
+
+    // Check for fast path where a CopySubresourceRegion can be used.
+    if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY &&
+        sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat)
+    {
+        ID3D11Resource *sourceResource = nullptr;
+        ANGLE_TRY(sourceStorage11->getResource(&sourceResource));
+
+        gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
+        UINT sourceSubresource     = sourceStorage11->getSubresourceIndex(sourceIndex);
+
+        ID3D11Resource *destResource = nullptr;
+        ANGLE_TRY(destStorage11->getResource(&destResource));
+
+        gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
+        UINT destSubresource     = destStorage11->getSubresourceIndex(destIndex);
+
+        D3D11_BOX sourceBox{
+            static_cast<UINT>(sourceRect.x),
+            static_cast<UINT>(sourceRect.y),
+            0u,
+            static_cast<UINT>(sourceRect.x + sourceRect.width),
+            static_cast<UINT>(sourceRect.y + sourceRect.height),
+            1u,
+        };
+
+        mDeviceContext->CopySubresourceRegion(destResource, destSubresource, destOffset.x,
+                                              destOffset.y, destOffset.z, sourceResource,
+                                              sourceSubresource, &sourceBox);
+    }
+    else
+    {
+        ID3D11ShaderResourceView *sourceSRV = nullptr;
+        ANGLE_TRY(sourceStorage11->getSRVLevels(sourceLevel, sourceLevel, &sourceSRV));
+
+        gl::ImageIndex destIndex             = gl::ImageIndex::Make2D(destLevel);
+        RenderTargetD3D *destRenderTargetD3D = nullptr;
+        ANGLE_TRY(destStorage11->getRenderTarget(destIndex, &destRenderTargetD3D));
+
+        RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D);
+
+        const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView();
+        ASSERT(destRTV.valid());
+
+        gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
+        gl::Extents sourceSize(
+            static_cast<int>(source->getWidth(source->getTarget(), sourceLevel)),
+            static_cast<int>(source->getHeight(source->getTarget(), sourceLevel)), 1);
+        if (unpackFlipY)
+        {
+            sourceArea.y      = sourceSize.height - sourceRect.y;
+            sourceArea.height = -sourceArea.height;
+        }
+
+        gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
+        gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(), 1);
+
+        // Use nearest filtering because source and destination are the same size for the direct
+        // copy
+        ANGLE_TRY(mBlit->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize,
+                                     nullptr, destFormat, GL_NEAREST, false, unpackPremultiplyAlpha,
+                                     unpackUnmultiplyAlpha));
+    }
+
+    destStorage11->markLevelDirty(destLevel);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::copyCompressedTexture(const gl::Texture *source,
+                                            GLint sourceLevel,
+                                            TextureStorage *storage,
+                                            GLint destLevel)
+{
+    TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
+    ASSERT(destStorage11);
+
+    ID3D11Resource *destResource = nullptr;
+    ANGLE_TRY(destStorage11->getResource(&destResource));
+
+    gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
+    UINT destSubresource     = destStorage11->getSubresourceIndex(destIndex);
+
+    TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+    ASSERT(sourceD3D);
+
+    TextureStorage *sourceStorage = nullptr;
+    ANGLE_TRY(sourceD3D->getNativeTexture(&sourceStorage));
+
+    TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
+    ASSERT(sourceStorage11);
+
+    ID3D11Resource *sourceResource = nullptr;
+    ANGLE_TRY(sourceStorage11->getResource(&sourceResource));
+
+    gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
+    UINT sourceSubresource     = sourceStorage11->getSubresourceIndex(sourceIndex);
+
+    mDeviceContext->CopySubresourceRegion(destResource, destSubresource, 0, 0, 0, sourceResource,
+                                          sourceSubresource, nullptr);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::createRenderTarget(int width,
+                                         int height,
+                                         GLenum format,
+                                         GLsizei samples,
+                                         RenderTargetD3D **outRT)
+{
+    const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps);
+
+    const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
+    GLuint supportedSamples            = textureCaps.getNearestSamples(samples);
+
+    if (width > 0 && height > 0)
+    {
+        // Create texture resource
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width              = width;
+        desc.Height             = height;
+        desc.MipLevels          = 1;
+        desc.ArraySize          = 1;
+        desc.Format             = formatInfo.texFormat;
+        desc.SampleDesc.Count   = (supportedSamples == 0) ? 1 : supportedSamples;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage              = D3D11_USAGE_DEFAULT;
+        desc.CPUAccessFlags     = 0;
+        desc.MiscFlags          = 0;
+
+        // If a rendertarget or depthstencil format exists for this texture format,
+        // we'll flag it to allow binding that way. Shader resource views are a little
+        // more complicated.
+        bool bindRTV = false, bindDSV = false, bindSRV = false;
+        bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
+        bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+        bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN);
+
+        // D3D feature level 10.0 no longer allows creation of textures with both the bind SRV and
+        // DSV flags when multisampled.  crbug.com/656989
+        bool supportsMultisampledDepthStencilSRVs =
+            mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0;
+        bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1;
+        if (isMultisampledDepthStencil && !supportsMultisampledDepthStencilSRVs)
+        {
+            bindSRV = false;
+        }
+
+        desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
+                         (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
+                         (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
+
+        // The format must be either an RTV or a DSV
+        ASSERT(bindRTV != bindDSV);
+
+        ID3D11Texture2D *texture = nullptr;
+        HRESULT result           = mDevice->CreateTexture2D(&desc, nullptr, &texture);
+        if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create render target texture, result: 0x%X.", result);
+        }
+
+        ID3D11ShaderResourceView *srv     = nullptr;
+        ID3D11ShaderResourceView *blitSRV = nullptr;
+        if (bindSRV)
+        {
+            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+            srvDesc.Format        = formatInfo.srvFormat;
+            srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D
+                                                            : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+            srvDesc.Texture2D.MostDetailedMip = 0;
+            srvDesc.Texture2D.MipLevels       = 1;
+
+            result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv);
+            if (FAILED(result))
+            {
+                ASSERT(result == E_OUTOFMEMORY);
+                SafeRelease(texture);
+                return gl::Error(
+                    GL_OUT_OF_MEMORY,
+                    "Failed to create render target shader resource view, result: 0x%X.", result);
+            }
+
+            if (formatInfo.blitSRVFormat != formatInfo.srvFormat)
+            {
+                D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc;
+                blitSRVDesc.Format        = formatInfo.blitSRVFormat;
+                blitSRVDesc.ViewDimension = (supportedSamples == 0)
+                                                ? D3D11_SRV_DIMENSION_TEXTURE2D
+                                                : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+                blitSRVDesc.Texture2D.MostDetailedMip = 0;
+                blitSRVDesc.Texture2D.MipLevels       = 1;
+
+                result = mDevice->CreateShaderResourceView(texture, &blitSRVDesc, &blitSRV);
+                if (FAILED(result))
+                {
+                    ASSERT(result == E_OUTOFMEMORY);
+                    SafeRelease(texture);
+                    SafeRelease(srv);
+                    return gl::Error(GL_OUT_OF_MEMORY,
+                                     "Failed to create render target shader resource view for "
+                                     "blits, result: 0x%X.",
+                                     result);
+                }
+            }
+            else
+            {
+                blitSRV = srv;
+                srv->AddRef();
+            }
+        }
+
+        if (bindDSV)
+        {
+            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+            dsvDesc.Format        = formatInfo.dsvFormat;
+            dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D
+                                                            : D3D11_DSV_DIMENSION_TEXTURE2DMS;
+            dsvDesc.Texture2D.MipSlice = 0;
+            dsvDesc.Flags              = 0;
+
+            ID3D11DepthStencilView *dsv = nullptr;
+            result                      = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+            if (FAILED(result))
+            {
+                ASSERT(result == E_OUTOFMEMORY);
+                SafeRelease(texture);
+                SafeRelease(srv);
+                SafeRelease(blitSRV);
+                return gl::Error(GL_OUT_OF_MEMORY,
+                                 "Failed to create render target depth stencil view, result: 0x%X.",
+                                 result);
+            }
+
+            *outRT = new TextureRenderTarget11(dsv, texture, srv, format, formatInfo, width, height,
+                                               1, supportedSamples);
+
+            SafeRelease(dsv);
+        }
+        else if (bindRTV)
+        {
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format        = formatInfo.rtvFormat;
+            rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D
+                                                            : D3D11_RTV_DIMENSION_TEXTURE2DMS;
+            rtvDesc.Texture2D.MipSlice = 0;
+
+            d3d11::RenderTargetView rtv;
+            gl::Error err = allocateResource(rtvDesc, texture, &rtv);
+            if (err.isError())
+            {
+                SafeRelease(texture);
+                SafeRelease(srv);
+                SafeRelease(blitSRV);
+                return err;
+            }
+
+            if (formatInfo.dataInitializerFunction != nullptr)
+            {
+                const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+                mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues);
+            }
+
+            *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format,
+                                               formatInfo, width, height, 1, supportedSamples);
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+
+        SafeRelease(texture);
+        SafeRelease(srv);
+        SafeRelease(blitSRV);
+    }
+    else
+    {
+        *outRT = new TextureRenderTarget11(
+            d3d11::RenderTargetView(), nullptr, nullptr, nullptr, format,
+            d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps), width, height, 1, supportedSamples);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT)
+{
+    ASSERT(source != nullptr);
+
+    RenderTargetD3D *newRT = nullptr;
+    ANGLE_TRY(createRenderTarget(source->getWidth(), source->getHeight(),
+                                 source->getInternalFormat(), source->getSamples(), &newRT));
+
+    RenderTarget11 *source11 = GetAs<RenderTarget11>(source);
+    RenderTarget11 *dest11   = GetAs<RenderTarget11>(newRT);
+
+    mDeviceContext->CopySubresourceRegion(dest11->getTexture(), dest11->getSubresourceIndex(), 0, 0,
+                                          0, source11->getTexture(),
+                                          source11->getSubresourceIndex(), nullptr);
+    *outRT = newRT;
+    return gl::NoError();
+}
+
+gl::Error Renderer11::loadExecutable(const void *function,
+                                     size_t length,
+                                     ShaderType type,
+                                     const std::vector<D3DVarying> &streamOutVaryings,
+                                     bool separatedOutputBuffers,
+                                     ShaderExecutableD3D **outExecutable)
+{
+    switch (type)
+    {
+        case SHADER_VERTEX:
+        {
+            ID3D11VertexShader *vertexShader      = nullptr;
+            ID3D11GeometryShader *streamOutShader = nullptr;
+
+            HRESULT result = mDevice->CreateVertexShader(function, length, nullptr, &vertexShader);
+            ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::OutOfMemory() << "Failed to create vertex shader, " << result;
+            }
+
+            if (!streamOutVaryings.empty())
+            {
+                std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
+                soDeclaration.reserve(streamOutVaryings.size());
+
+                for (const auto &streamOutVarying : streamOutVaryings)
+                {
+                    D3D11_SO_DECLARATION_ENTRY entry = {0};
+                    entry.Stream                     = 0;
+                    entry.SemanticName               = streamOutVarying.semanticName.c_str();
+                    entry.SemanticIndex              = streamOutVarying.semanticIndex;
+                    entry.StartComponent             = 0;
+                    entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
+                    entry.OutputSlot     = static_cast<BYTE>(
+                        (separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
+                    soDeclaration.push_back(entry);
+                }
+
+                result = mDevice->CreateGeometryShaderWithStreamOutput(
+                    function, static_cast<unsigned int>(length), soDeclaration.data(),
+                    static_cast<unsigned int>(soDeclaration.size()), nullptr, 0, 0, nullptr,
+                    &streamOutShader);
+                ASSERT(SUCCEEDED(result));
+                if (FAILED(result))
+                {
+                    return gl::OutOfMemory() << "Failed to create steam output shader, " << result;
+                }
+            }
+
+            *outExecutable =
+                new ShaderExecutable11(function, length, vertexShader, streamOutShader);
+        }
+        break;
+        case SHADER_PIXEL:
+        {
+            ID3D11PixelShader *pixelShader = nullptr;
+
+            HRESULT result = mDevice->CreatePixelShader(function, length, nullptr, &pixelShader);
+            ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::OutOfMemory() << "Failed to create pixel shader, " << result;
+            }
+
+            *outExecutable = new ShaderExecutable11(function, length, pixelShader);
+        }
+        break;
+        case SHADER_GEOMETRY:
+        {
+            ID3D11GeometryShader *geometryShader = nullptr;
+
+            HRESULT result =
+                mDevice->CreateGeometryShader(function, length, nullptr, &geometryShader);
+            ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::OutOfMemory() << "Failed to create geometry shader, " << result;
+            }
+
+            *outExecutable = new ShaderExecutable11(function, length, geometryShader);
+        }
+        break;
+        case SHADER_COMPUTE:
+        {
+            ID3D11ComputeShader *computeShader = nullptr;
+
+            HRESULT result =
+                mDevice->CreateComputeShader(function, length, nullptr, &computeShader);
+            ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::OutOfMemory() << "Failed to create compute shader, " << result;
+            }
+
+            *outExecutable = new ShaderExecutable11(function, length, computeShader);
+        }
+        break;
+        default:
+            UNREACHABLE();
+            return gl::Error(GL_INVALID_OPERATION);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
+                                          const std::string &shaderHLSL,
+                                          ShaderType type,
+                                          const std::vector<D3DVarying> &streamOutVaryings,
+                                          bool separatedOutputBuffers,
+                                          const angle::CompilerWorkaroundsD3D &workarounds,
+                                          ShaderExecutableD3D **outExectuable)
+{
+    std::stringstream profileStream;
+
+    switch (type)
+    {
+        case SHADER_VERTEX:
+            profileStream << "vs";
+            break;
+        case SHADER_PIXEL:
+            profileStream << "ps";
+            break;
+        case SHADER_GEOMETRY:
+            profileStream << "gs";
+            break;
+        case SHADER_COMPUTE:
+            profileStream << "cs";
+            break;
+        default:
+            UNREACHABLE();
+            return gl::Error(GL_INVALID_OPERATION);
+    }
+
+    profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel()
+                  << getShaderModelSuffix();
+    std::string profile = profileStream.str();
+
+    UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
+
+    if (gl::DebugAnnotationsActive())
+    {
+#ifndef NDEBUG
+        flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
+
+        flags |= D3DCOMPILE_DEBUG;
+    }
+
+    if (workarounds.enableIEEEStrictness)
+        flags |= D3DCOMPILE_IEEE_STRICTNESS;
+
+    // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
+    // when it would otherwise pass with alternative options.
+    // Try the default flags first and if compilation fails, try some alternatives.
+    std::vector<CompileConfig> configs;
+    configs.push_back(CompileConfig(flags, "default"));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation"));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
+
+    if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "")
+    {
+        // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader".
+        // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*.
+        // Using the [unroll] directive works around this, as does this D3DCompile flag.
+        configs.push_back(
+            CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
+    }
+
+    D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}};
+
+    ID3DBlob *binary = nullptr;
+    std::string debugInfo;
+    ANGLE_TRY(mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary,
+                                        &debugInfo));
+
+    // It's possible that binary is NULL if the compiler failed in all configurations.  Set the
+    // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
+    // internal state is still OK.
+    if (!binary)
+    {
+        *outExectuable = nullptr;
+        return gl::NoError();
+    }
+
+    gl::Error error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
+                                     streamOutVaryings, separatedOutputBuffers, outExectuable);
+
+    SafeRelease(binary);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!debugInfo.empty())
+    {
+        (*outExectuable)->appendDebugInfo(debugInfo);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::ensureHLSLCompilerInitialized()
+{
+    return mCompiler.ensureInitialized();
+}
+
+UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize)
+{
+    return new UniformStorage11(this, storageSize);
+}
+
+VertexBuffer *Renderer11::createVertexBuffer()
+{
+    return new VertexBuffer11(this);
+}
+
+IndexBuffer *Renderer11::createIndexBuffer()
+{
+    return new IndexBuffer11(this);
+}
+
+StreamProducerImpl *Renderer11::createStreamProducerD3DTextureNV12(
+    egl::Stream::ConsumerType consumerType,
+    const egl::AttributeMap &attribs)
+{
+    return new StreamProducerNV12(this);
+}
+
+bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
+{
+    ASSERT(getNativeExtensions().pixelBufferObject);
+
+    const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+    const d3d11::Format &d3d11FormatInfo =
+        d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps);
+
+    // sRGB formats do not work with D3D11 buffer SRVs
+    if (internalFormatInfo.colorEncoding == GL_SRGB)
+    {
+        return false;
+    }
+
+    // We cannot support direct copies to non-color-renderable formats
+    if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN)
+    {
+        return false;
+    }
+
+    // We skip all 3-channel formats since sometimes format support is missing
+    if (internalFormatInfo.componentCount == 3)
+    {
+        return false;
+    }
+
+    // We don't support formats which we can't represent without conversion
+    if (d3d11FormatInfo.format().glInternalFormat != internalFormat)
+    {
+        return false;
+    }
+
+    // Buffer SRV creation for this format was not working on Windows 10.
+    if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM)
+    {
+        return false;
+    }
+
+    // This format is not supported as a buffer SRV.
+    if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack,
+                                              unsigned int offset,
+                                              RenderTargetD3D *destRenderTarget,
+                                              GLenum destinationFormat,
+                                              GLenum sourcePixelsType,
+                                              const gl::Box &destArea)
+{
+    ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
+    return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat,
+                                               sourcePixelsType, destArea);
+}
+
+ImageD3D *Renderer11::createImage()
+{
+    return new Image11(this);
+}
+
+gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src)
+{
+    Image11 *dest11 = GetAs<Image11>(dest);
+    Image11 *src11  = GetAs<Image11>(src);
+    return Image11::generateMipmap(dest11, src11, mRenderer11DeviceCaps);
+}
+
+gl::Error Renderer11::generateMipmapUsingD3D(TextureStorage *storage,
+                                             const gl::TextureState &textureState)
+{
+    TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
+
+    ASSERT(storage11->isRenderTarget());
+    ASSERT(storage11->supportsNativeMipmapFunction());
+
+    ID3D11ShaderResourceView *srv;
+    ANGLE_TRY(storage11->getSRVLevels(textureState.getEffectiveBaseLevel(),
+                                      textureState.getEffectiveMaxLevel(), &srv));
+
+    mDeviceContext->GenerateMips(srv);
+
+    return gl::NoError();
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
+{
+    SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain);
+    return new TextureStorage11_2D(this, swapChain11);
+}
+
+TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage,
+                                                         RenderTargetD3D *renderTargetD3D)
+{
+    return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D));
+}
+
+TextureStorage *Renderer11::createTextureStorageExternal(
+    egl::Stream *stream,
+    const egl::Stream::GLTextureDescription &desc)
+{
+    return new TextureStorage11_External(this, stream, desc);
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat,
+                                                   bool renderTarget,
+                                                   GLsizei width,
+                                                   GLsizei height,
+                                                   int levels,
+                                                   bool hintLevelZeroOnly)
+{
+    return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels,
+                                   hintLevelZeroOnly);
+}
+
+TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat,
+                                                     bool renderTarget,
+                                                     int size,
+                                                     int levels,
+                                                     bool hintLevelZeroOnly)
+{
+    return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels,
+                                     hintLevelZeroOnly);
+}
+
+TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat,
+                                                   bool renderTarget,
+                                                   GLsizei width,
+                                                   GLsizei height,
+                                                   GLsizei depth,
+                                                   int levels)
+{
+    return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth,
+                                   levels);
+}
+
+TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat,
+                                                        bool renderTarget,
+                                                        GLsizei width,
+                                                        GLsizei height,
+                                                        GLsizei depth,
+                                                        int levels)
+{
+    return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth,
+                                        levels);
+}
+
+gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAttachment,
+                                         const gl::Rectangle &sourceArea,
+                                         GLenum format,
+                                         GLenum type,
+                                         GLuint outputPitch,
+                                         const gl::PixelPackState &pack,
+                                         uint8_t *pixelsOut)
+{
+    ASSERT(sourceArea.width >= 0);
+    ASSERT(sourceArea.height >= 0);
+
+    const bool invertTexture = UsePresentPathFast(this, &srcAttachment);
+
+    RenderTargetD3D *renderTarget = nullptr;
+    ANGLE_TRY(srcAttachment.getRenderTarget(&renderTarget));
+
+    RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
+    ASSERT(rt11->getTexture());
+
+    TextureHelper11 textureHelper =
+        TextureHelper11::MakeAndReference(rt11->getTexture(), rt11->getFormatSet());
+    unsigned int sourceSubResource = rt11->getSubresourceIndex();
+
+    const gl::Extents &texSize = textureHelper.getExtents();
+
+    gl::Rectangle actualArea = sourceArea;
+    if (invertTexture)
+    {
+        actualArea.y = texSize.height - actualArea.y - actualArea.height;
+    }
+
+    // Clamp read region to the defined texture boundaries, preventing out of bounds reads
+    // and reads of uninitialized data.
+    gl::Rectangle safeArea;
+    safeArea.x = gl::clamp(actualArea.x, 0, texSize.width);
+    safeArea.y = gl::clamp(actualArea.y, 0, texSize.height);
+    safeArea.width =
+        gl::clamp(actualArea.width + std::min(actualArea.x, 0), 0, texSize.width - safeArea.x);
+    safeArea.height =
+        gl::clamp(actualArea.height + std::min(actualArea.y, 0), 0, texSize.height - safeArea.y);
+
+    ASSERT(safeArea.x >= 0 && safeArea.y >= 0);
+    ASSERT(safeArea.x + safeArea.width <= texSize.width);
+    ASSERT(safeArea.y + safeArea.height <= texSize.height);
+
+    if (safeArea.width == 0 || safeArea.height == 0)
+    {
+        // no work to do
+        return gl::NoError();
+    }
+
+    gl::Extents safeSize(safeArea.width, safeArea.height, 1);
+    TextureHelper11 stagingHelper;
+    ANGLE_TRY_RESULT(
+        CreateStagingTexture(textureHelper.getTextureType(), textureHelper.getFormatSet(), safeSize,
+                             StagingAccess::READ, mDevice),
+        stagingHelper);
+
+    TextureHelper11 resolvedTextureHelper;
+
+    // "srcTexture" usually points to the source texture.
+    // For 2D multisampled textures, it points to the multisampled resolve texture.
+    const TextureHelper11 *srcTexture = &textureHelper;
+
+    if (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1)
+    {
+        D3D11_TEXTURE2D_DESC resolveDesc;
+        resolveDesc.Width              = static_cast<UINT>(texSize.width);
+        resolveDesc.Height             = static_cast<UINT>(texSize.height);
+        resolveDesc.MipLevels          = 1;
+        resolveDesc.ArraySize          = 1;
+        resolveDesc.Format             = textureHelper.getFormat();
+        resolveDesc.SampleDesc.Count   = 1;
+        resolveDesc.SampleDesc.Quality = 0;
+        resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
+        resolveDesc.BindFlags          = 0;
+        resolveDesc.CPUAccessFlags     = 0;
+        resolveDesc.MiscFlags          = 0;
+
+        ID3D11Texture2D *resolveTex2D = nullptr;
+        HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTex2D);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Renderer11::readTextureData failed to create internal resolve "
+                             "texture for ReadPixels, HRESULT: 0x%X.",
+                             result);
+        }
+
+        mDeviceContext->ResolveSubresource(resolveTex2D, 0, textureHelper.getTexture2D(),
+                                           sourceSubResource, textureHelper.getFormat());
+        resolvedTextureHelper =
+            TextureHelper11::MakeAndReference(resolveTex2D, textureHelper.getFormatSet());
+
+        sourceSubResource = 0;
+        srcTexture        = &resolvedTextureHelper;
+    }
+
+    D3D11_BOX srcBox;
+    srcBox.left   = static_cast<UINT>(safeArea.x);
+    srcBox.right  = static_cast<UINT>(safeArea.x + safeArea.width);
+    srcBox.top    = static_cast<UINT>(safeArea.y);
+    srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height);
+
+    // Select the correct layer from a 3D attachment
+    srcBox.front = 0;
+    if (textureHelper.getTextureType() == GL_TEXTURE_3D)
+    {
+        srcBox.front = static_cast<UINT>(srcAttachment.layer());
+    }
+    srcBox.back = srcBox.front + 1;
+
+    mDeviceContext->CopySubresourceRegion(stagingHelper.getResource(), 0, 0, 0, 0,
+                                          srcTexture->getResource(), sourceSubResource, &srcBox);
+
+    if (!invertTexture)
+    {
+        PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0);
+        return packPixels(stagingHelper, packParams, pixelsOut);
+    }
+
+    gl::PixelPackState invertTexturePack;
+
+    // Create a new PixelPackState with reversed row order. Note that we can't just assign
+    // 'invertTexturePack' to be 'pack' (or memcpy) since that breaks the ref counting/object
+    // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use
+    // pixelBuffer.set() twice, which performs the addRef/release correctly
+    invertTexturePack.alignment = pack.alignment;
+    invertTexturePack.pixelBuffer.set(pack.pixelBuffer.get());
+    invertTexturePack.reverseRowOrder = !pack.reverseRowOrder;
+
+    PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, 0);
+    gl::Error error = packPixels(stagingHelper, packParams, pixelsOut);
+    invertTexturePack.pixelBuffer.set(nullptr);
+    ANGLE_TRY(error);
+    return gl::NoError();
+}
+
+gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper,
+                                 const PackPixelsParams &params,
+                                 uint8_t *pixelsOut)
+{
+    ID3D11Resource *readResource = textureHelper.getResource();
+
+    D3D11_MAPPED_SUBRESOURCE mapping;
+    HRESULT hr = mDeviceContext->Map(readResource, 0, D3D11_MAP_READ, 0, &mapping);
+    if (FAILED(hr))
+    {
+        ASSERT(hr == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to map internal texture for reading, result: 0x%X.", hr);
+    }
+
+    uint8_t *source = static_cast<uint8_t *>(mapping.pData);
+    int inputPitch  = static_cast<int>(mapping.RowPitch);
+
+    const auto &formatInfo = textureHelper.getFormatSet();
+    ASSERT(formatInfo.format().glInternalFormat != GL_NONE);
+
+    PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut);
+
+    mDeviceContext->Unmap(readResource, 0);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
+                                           const gl::Rectangle &drawRectIn,
+                                           RenderTargetD3D *readRenderTarget,
+                                           RenderTargetD3D *drawRenderTarget,
+                                           GLenum filter,
+                                           const gl::Rectangle *scissor,
+                                           bool colorBlit,
+                                           bool depthBlit,
+                                           bool stencilBlit)
+{
+    // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
+    // it should never be the case that both color and depth/stencil need to be blitted at
+    // at the same time.
+    ASSERT(colorBlit != (depthBlit || stencilBlit));
+
+    RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
+    if (!drawRenderTarget11)
+    {
+        return gl::OutOfMemory()
+               << "Failed to retrieve the internal draw render target from the draw framebuffer.";
+    }
+
+    TextureHelper11 drawTexture = TextureHelper11::MakeAndReference(
+        drawRenderTarget11->getTexture(), drawRenderTarget11->getFormatSet());
+    unsigned int drawSubresource    = drawRenderTarget11->getSubresourceIndex();
+    ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView();
+
+    RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
+    if (!readRenderTarget11)
+    {
+        return gl::OutOfMemory()
+               << "Failed to retrieve the internal read render target from the read framebuffer.";
+    }
+
+    TextureHelper11 readTexture;
+    unsigned int readSubresource      = 0;
+    ID3D11ShaderResourceView *readSRV = nullptr;
+
+    if (readRenderTarget->getSamples() > 1)
+    {
+        ANGLE_TRY_RESULT(resolveMultisampledTexture(readRenderTarget11, depthBlit, stencilBlit),
+                         readTexture);
+
+        if (!stencilBlit)
+        {
+            const auto &readFormatSet = readTexture.getFormatSet();
+
+            D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
+            viewDesc.Format                    = readFormatSet.srvFormat;
+            viewDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
+            viewDesc.Texture2D.MipLevels       = 1;
+            viewDesc.Texture2D.MostDetailedMip = 0;
+
+            HRESULT hresult =
+                mDevice->CreateShaderResourceView(readTexture.getResource(), &viewDesc, &readSRV);
+            if (FAILED(hresult))
+            {
+                return gl::OutOfMemory()
+                       << "Renderer11::blitRenderbufferRect: Failed to create temporary SRV, "
+                       << hresult;
+            }
+        }
+    }
+    else
+    {
+        ASSERT(readRenderTarget11);
+        readTexture = TextureHelper11::MakeAndReference(readRenderTarget11->getTexture(),
+                                                        readRenderTarget11->getFormatSet());
+        readSubresource = readRenderTarget11->getSubresourceIndex();
+        readSRV         = readRenderTarget11->getBlitShaderResourceView();
+        if (readSRV == nullptr)
+        {
+            ASSERT(depthBlit || stencilBlit);
+            readSRV = readRenderTarget11->getShaderResourceView();
+        }
+        ASSERT(readSRV);
+        readSRV->AddRef();
+    }
+
+    // Stencil blits don't use shaders.
+    ASSERT(readSRV || stencilBlit);
+
+    const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
+    const gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+
+    // From the spec:
+    // "The actual region taken from the read framebuffer is limited to the intersection of the
+    // source buffers being transferred, which may include the color buffer selected by the read
+    // buffer, the depth buffer, and / or the stencil buffer depending on mask."
+    // This means negative x and y are out of bounds, and not to be read from. We handle this here
+    // by internally scaling the read and draw rectangles.
+    gl::Rectangle readRect = readRectIn;
+    gl::Rectangle drawRect = drawRectIn;
+    auto readToDrawX       = [&drawRectIn, &readRectIn](int readOffset) {
+        double readToDrawScale =
+            static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width);
+        return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
+    };
+    if (readRect.x < 0)
+    {
+        int readOffset = -readRect.x;
+        readRect.x += readOffset;
+        readRect.width -= readOffset;
+
+        int drawOffset = readToDrawX(readOffset);
+        drawRect.x += drawOffset;
+        drawRect.width -= drawOffset;
+    }
+
+    auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) {
+        double readToDrawScale =
+            static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height);
+        return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
+    };
+    if (readRect.y < 0)
+    {
+        int readOffset = -readRect.y;
+        readRect.y += readOffset;
+        readRect.height -= readOffset;
+
+        int drawOffset = readToDrawY(readOffset);
+        drawRect.y += drawOffset;
+        drawRect.height -= drawOffset;
+    }
+
+    if (readRect.x1() < 0)
+    {
+        int readOffset = -readRect.x1();
+        readRect.width += readOffset;
+
+        int drawOffset = readToDrawX(readOffset);
+        drawRect.width += drawOffset;
+    }
+
+    if (readRect.y1() < 0)
+    {
+        int readOffset = -readRect.y1();
+        readRect.height += readOffset;
+
+        int drawOffset = readToDrawY(readOffset);
+        drawRect.height += drawOffset;
+    }
+
+    bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr);
+
+    const auto &destFormatInfo =
+        gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat());
+    const auto &srcFormatInfo =
+        gl::GetSizedInternalFormatInfo(readRenderTarget->getInternalFormat());
+    const auto &formatSet    = drawRenderTarget11->getFormatSet();
+    const auto &nativeFormat = formatSet.format();
+
+    // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
+    // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.
+
+    gl::Color<bool> colorMask;
+    colorMask.red =
+        (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0);
+    colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
+                      (nativeFormat.greenBits > 0);
+    colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
+                     (nativeFormat.blueBits > 0);
+    colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
+                      (nativeFormat.alphaBits > 0);
+
+    // We only currently support masking off the alpha channel.
+    bool colorMaskingNeeded = colorMask.alpha;
+    ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue);
+
+    bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 &&
+                           readRect.width == readSize.width && readRect.y == 0 &&
+                           readRect.height == readSize.height && drawRect.x == 0 &&
+                           drawRect.width == drawSize.width && drawRect.y == 0 &&
+                           drawRect.height == drawSize.height;
+
+    bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
+
+    bool flipRequired =
+        readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0;
+
+    bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
+                       readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
+                       drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
+                       drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
+
+    bool partialDSBlit =
+        (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit);
+
+    if (readRenderTarget11->getFormatSet().formatID ==
+            drawRenderTarget11->getFormatSet().formatID &&
+        !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
+        !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
+    {
+        UINT dstX = drawRect.x;
+        UINT dstY = drawRect.y;
+
+        D3D11_BOX readBox;
+        readBox.left   = readRect.x;
+        readBox.right  = readRect.x + readRect.width;
+        readBox.top    = readRect.y;
+        readBox.bottom = readRect.y + readRect.height;
+        readBox.front  = 0;
+        readBox.back   = 1;
+
+        if (scissorNeeded)
+        {
+            // drawRect is guaranteed to have positive width and height because stretchRequired is
+            // false.
+            ASSERT(drawRect.width >= 0 || drawRect.height >= 0);
+
+            if (drawRect.x < scissor->x)
+            {
+                dstX = scissor->x;
+                readBox.left += (scissor->x - drawRect.x);
+            }
+            if (drawRect.y < scissor->y)
+            {
+                dstY = scissor->y;
+                readBox.top += (scissor->y - drawRect.y);
+            }
+            if (drawRect.x + drawRect.width > scissor->x + scissor->width)
+            {
+                readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width));
+            }
+            if (drawRect.y + drawRect.height > scissor->y + scissor->height)
+            {
+                readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height));
+            }
+        }
+
+        // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
+        // We also require complete framebuffer copies for depth-stencil blit.
+        D3D11_BOX *pSrcBox = wholeBufferCopy ? nullptr : &readBox;
+
+        mDeviceContext->CopySubresourceRegion(drawTexture.getResource(), drawSubresource, dstX,
+                                              dstY, 0, readTexture.getResource(), readSubresource,
+                                              pSrcBox);
+    }
+    else
+    {
+        gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1);
+        gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1);
+
+        if (depthBlit && stencilBlit)
+        {
+            ANGLE_TRY(mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize,
+                                              drawTexture, drawSubresource, drawArea, drawSize,
+                                              scissor));
+        }
+        else if (depthBlit)
+        {
+            ASSERT(readSRV);
+            ANGLE_TRY(mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize,
+                                       scissor));
+        }
+        else if (stencilBlit)
+        {
+            ANGLE_TRY(mBlit->copyStencil(readTexture, readSubresource, readArea, readSize,
+                                         drawTexture, drawSubresource, drawArea, drawSize,
+                                         scissor));
+        }
+        else
+        {
+            const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView();
+
+            // We don't currently support masking off any other channel than alpha
+            bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
+            ASSERT(readSRV);
+            ANGLE_TRY(mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
+                                         scissor, destFormatInfo.format, filter, maskOffAlpha,
+                                         false, false));
+        }
+    }
+
+    SafeRelease(readSRV);
+
+    return gl::NoError();
+}
+
+bool Renderer11::isES3Capable() const
+{
+    return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel).major > 2);
+};
+
+void Renderer11::onSwap()
+{
+    // Send histogram updates every half hour
+    const double kHistogramUpdateInterval = 30 * 60;
+
+    auto *platform                   = ANGLEPlatformCurrent();
+    const double currentTime         = platform->monotonicallyIncreasingTime(platform);
+    const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime;
+
+    if (timeSinceLastUpdate > kHistogramUpdateInterval)
+    {
+        updateHistograms();
+        mLastHistogramUpdateTime = currentTime;
+    }
+}
+
+void Renderer11::updateHistograms()
+{
+    // Update the buffer CPU memory histogram
+    {
+        size_t sizeSum = 0;
+        for (auto &buffer : mAliveBuffers)
+        {
+            sizeSum += buffer->getTotalCPUBufferMemoryBytes();
+        }
+        const int kOneMegaByte = 1024 * 1024;
+        ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB",
+                                  static_cast<int>(sizeSum) / kOneMegaByte);
+    }
+}
+
+void Renderer11::onBufferCreate(const Buffer11 *created)
+{
+    mAliveBuffers.insert(created);
+}
+
+void Renderer11::onBufferDelete(const Buffer11 *deleted)
+{
+    mAliveBuffers.erase(deleted);
+}
+
+gl::ErrorOrResult<TextureHelper11>
+Renderer11::resolveMultisampledTexture(RenderTarget11 *renderTarget, bool depth, bool stencil)
+{
+    if (depth && !stencil)
+    {
+        return mBlit->resolveDepth(renderTarget);
+    }
+
+    if (stencil)
+    {
+        return mBlit->resolveStencil(renderTarget, depth);
+    }
+
+    const auto &formatSet = renderTarget->getFormatSet();
+
+    ASSERT(renderTarget->getSamples() > 1);
+
+    D3D11_TEXTURE2D_DESC resolveDesc;
+    resolveDesc.Width              = renderTarget->getWidth();
+    resolveDesc.Height             = renderTarget->getHeight();
+    resolveDesc.MipLevels          = 1;
+    resolveDesc.ArraySize          = 1;
+    resolveDesc.Format             = formatSet.texFormat;
+    resolveDesc.SampleDesc.Count   = 1;
+    resolveDesc.SampleDesc.Quality = 0;
+    resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
+    resolveDesc.BindFlags          = D3D11_BIND_SHADER_RESOURCE;
+    resolveDesc.CPUAccessFlags     = 0;
+    resolveDesc.MiscFlags          = 0;
+
+    ID3D11Texture2D *resolveTexture = nullptr;
+    HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTexture);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
+    }
+
+    mDeviceContext->ResolveSubresource(resolveTexture, 0, renderTarget->getTexture(),
+                                       renderTarget->getSubresourceIndex(), formatSet.texFormat);
+    return TextureHelper11::MakeAndPossess2D(resolveTexture, renderTarget->getFormatSet());
+}
+
+bool Renderer11::getLUID(LUID *adapterLuid) const
+{
+    adapterLuid->HighPart = 0;
+    adapterLuid->LowPart  = 0;
+
+    if (!mDxgiAdapter)
+    {
+        return false;
+    }
+
+    DXGI_ADAPTER_DESC adapterDesc;
+    if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
+    {
+        return false;
+    }
+
+    *adapterLuid = adapterDesc.AdapterLuid;
+    return true;
+}
+
+VertexConversionType Renderer11::getVertexConversionType(
+    gl::VertexFormatType vertexFormatType) const
+{
+    return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel)
+        .conversionType;
+}
+
+GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const
+{
+    const auto &format =
+        d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel);
+    return d3d11::GetComponentType(format.nativeFormat);
+}
+
+gl::ErrorOrResult<unsigned int> Renderer11::getVertexSpaceRequired(
+    const gl::VertexAttribute &attrib,
+    const gl::VertexBinding &binding,
+    GLsizei count,
+    GLsizei instances) const
+{
+    if (!attrib.enabled)
+    {
+        return 16u;
+    }
+
+    unsigned int elementCount = 0;
+    if (instances == 0 || binding.divisor == 0)
+    {
+        elementCount = count;
+    }
+    else
+    {
+        // Round up to divisor, if possible
+        elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), binding.divisor);
+    }
+
+    gl::VertexFormatType formatType      = gl::GetVertexFormatType(attrib);
+    const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel;
+    const d3d11::VertexFormat &vertexFormatInfo =
+        d3d11::GetVertexFormatInfo(formatType, featureLevel);
+    const d3d11::DXGIFormatSize &dxgiFormatInfo =
+        d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat);
+    unsigned int elementSize = dxgiFormatInfo.pixelBytes;
+    if (elementSize > std::numeric_limits<unsigned int>::max() / elementCount)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
+    }
+
+    return elementSize * elementCount;
+}
+
+void Renderer11::generateCaps(gl::Caps *outCaps,
+                              gl::TextureCapsMap *outTextureCaps,
+                              gl::Extensions *outExtensions,
+                              gl::Limitations *outLimitations) const
+{
+    d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps,
+                           outExtensions, outLimitations);
+}
+
+angle::WorkaroundsD3D Renderer11::generateWorkarounds() const
+{
+    return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription);
+}
+
+gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
+{
+    return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd);
+}
+
+egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
+{
+    if (mEGLDevice == nullptr)
+    {
+        ASSERT(mDevice != nullptr);
+        mEGLDevice       = new DeviceD3D();
+        egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
+                                                  EGL_D3D11_DEVICE_ANGLE, EGL_FALSE);
+
+        if (error.isError())
+        {
+            SafeDelete(mEGLDevice);
+            return error;
+        }
+    }
+
+    *device = static_cast<DeviceImpl *>(mEGLDevice);
+    return egl::Error(EGL_SUCCESS);
+}
+
+ContextImpl *Renderer11::createContext(const gl::ContextState &state)
+{
+    return new Context11(state, this);
+}
+
+gl::Error Renderer11::genericDrawElements(Context11 *context,
+                                          GLenum mode,
+                                          GLsizei count,
+                                          GLenum type,
+                                          const void *indices,
+                                          GLsizei instances,
+                                          const gl::IndexRange &indexRange)
+{
+    const auto &data     = context->getContextState();
+    const auto &glState  = data.getState();
+    gl::Program *program = glState.getProgram();
+    ASSERT(program != nullptr);
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+    bool usesPointSize     = programD3D->usesPointSize();
+
+    programD3D->updateSamplerMapping();
+
+    ANGLE_TRY(generateSwizzles(data));
+
+    if (!applyPrimitiveType(mode, count, usesPointSize))
+    {
+        return gl::NoError();
+    }
+
+    ANGLE_TRY(updateState(context, mode));
+
+    TranslatedIndexData indexInfo;
+    indexInfo.indexRange = indexRange;
+
+    ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo));
+
+    applyTransformFeedbackBuffers(data);
+    // Transform feedback is not allowed for DrawElements, this error should have been caught at the
+    // API validation layer.
+    ASSERT(!glState.isTransformFeedbackActiveUnpaused());
+
+    size_t vertexCount = indexInfo.indexRange.vertexCount();
+    ANGLE_TRY(applyVertexBuffer(glState, mode, static_cast<GLsizei>(indexInfo.indexRange.start),
+                                static_cast<GLsizei>(vertexCount), instances, &indexInfo));
+    ANGLE_TRY(applyTextures(context, data));
+    ANGLE_TRY(applyShaders(data, mode));
+    ANGLE_TRY(programD3D->applyUniformBuffers(data));
+
+    if (!skipDraw(data, mode))
+    {
+        ANGLE_TRY(drawElementsImpl(data, indexInfo, mode, count, type, indices, instances));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::genericDrawArrays(Context11 *context,
+                                        GLenum mode,
+                                        GLint first,
+                                        GLsizei count,
+                                        GLsizei instances)
+{
+    const auto &data     = context->getContextState();
+    const auto &glState  = data.getState();
+    gl::Program *program = glState.getProgram();
+    ASSERT(program != nullptr);
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+    bool usesPointSize     = programD3D->usesPointSize();
+
+    programD3D->updateSamplerMapping();
+
+    ANGLE_TRY(generateSwizzles(data));
+    if (!applyPrimitiveType(mode, count, usesPointSize))
+    {
+        return gl::NoError();
+    }
+
+    ANGLE_TRY(updateState(context, mode));
+    ANGLE_TRY(applyTransformFeedbackBuffers(data));
+    ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));
+    ANGLE_TRY(applyTextures(context, data));
+    ANGLE_TRY(applyShaders(data, mode));
+    ANGLE_TRY(programD3D->applyUniformBuffers(data));
+
+    if (!skipDraw(data, mode))
+    {
+        ANGLE_TRY(drawArraysImpl(data, mode, first, count, instances));
+
+        if (glState.isTransformFeedbackActiveUnpaused())
+        {
+            ANGLE_TRY(markTransformFeedbackUsage(data));
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::genericDrawIndirect(Context11 *context,
+                                          GLenum mode,
+                                          GLenum type,
+                                          const void *indirect)
+{
+    const auto &data     = context->getContextState();
+    const auto &glState  = data.getState();
+    gl::Program *program = glState.getProgram();
+    ASSERT(program != nullptr);
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+    bool usesPointSize     = programD3D->usesPointSize();
+    programD3D->updateSamplerMapping();
+
+    ANGLE_TRY(generateSwizzles(data));
+    applyPrimitiveType(mode, 0, usesPointSize);
+    ANGLE_TRY(updateState(context, mode));
+    ANGLE_TRY(applyTransformFeedbackBuffers(data));
+    ASSERT(!glState.isTransformFeedbackActiveUnpaused());
+    ANGLE_TRY(applyTextures(context, data));
+    ANGLE_TRY(applyShaders(data, mode));
+    ANGLE_TRY(programD3D->applyUniformBuffers(data));
+
+    if (type == GL_NONE)
+    {
+        ANGLE_TRY(drawArraysIndirectImpl(data, mode, indirect));
+    }
+    else
+    {
+        ANGLE_TRY(drawElementsIndirectImpl(data, mode, type, indirect));
+    }
+
+    return gl::NoError();
+}
+
+FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+    return new Framebuffer11(state, this);
+}
+
+gl::Error Renderer11::getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut)
+{
+    if (!mScratchMemoryBuffer.get(requestedSize, bufferOut))
+    {
+        return gl::OutOfMemory() << "Failed to allocate internal buffer.";
+    }
+    return gl::NoError();
+}
+
+gl::Version Renderer11::getMaxSupportedESVersion() const
+{
+    return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel);
+}
+
+gl::DebugAnnotator *Renderer11::getAnnotator()
+{
+    return mAnnotator;
+}
+
+gl::Error Renderer11::applyComputeShader(const gl::ContextState &data)
+{
+    ANGLE_TRY(ensureHLSLCompilerInitialized());
+
+    const auto &glState    = data.getState();
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+    ShaderExecutableD3D *computeExe = nullptr;
+    ANGLE_TRY(programD3D->getComputeExecutable(&computeExe));
+
+    ASSERT(computeExe != nullptr);
+    ID3D11ComputeShader *computeShader = GetAs<ShaderExecutable11>(computeExe)->getComputeShader();
+
+    bool dirtyUniforms = false;
+
+    if (reinterpret_cast<uintptr_t>(computeShader) != mAppliedComputeShader)
+    {
+        mDeviceContext->CSSetShader(computeShader, nullptr, 0);
+        mAppliedComputeShader = reinterpret_cast<uintptr_t>(computeShader);
+        dirtyUniforms         = true;
+    }
+
+    if (dirtyUniforms)
+    {
+        programD3D->dirtyAllUniforms();
+    }
+
+    return programD3D->applyComputeUniforms();
+}
+
+gl::Error Renderer11::dispatchCompute(Context11 *context,
+                                      GLuint numGroupsX,
+                                      GLuint numGroupsY,
+                                      GLuint numGroupsZ)
+{
+    const auto &data     = context->getContextState();
+    gl::Program *program = data.getState().getProgram();
+    ASSERT(program != nullptr);
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+    mStateManager.setComputeConstants(numGroupsX, numGroupsY, numGroupsZ);
+
+    programD3D->updateSamplerMapping();
+
+    ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_COMPUTE));
+    ANGLE_TRY(applyTextures(context, data));
+    ANGLE_TRY(applyComputeShader(data));
+    // TODO(Xinghua): applyUniformBuffers for compute shader.
+    mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer11::applyComputeUniforms(const ProgramD3D &programD3D,
+                                           const std::vector<D3DUniform *> &uniformArray)
+{
+    unsigned int totalRegisterCountCS = 0;
+    bool computeUniformsDirty         = false;
+
+    for (const D3DUniform *uniform : uniformArray)
+    {
+        ASSERT(uniform->isReferencedByComputeShader());
+
+        // TODO(Xinghua): add isImage() and isAtomicCounter().
+        if (uniform->isSampler())
+        {
+            totalRegisterCountCS += uniform->registerCount;
+            computeUniformsDirty = (computeUniformsDirty || uniform->dirty);
+        }
+    }
+
+    const UniformStorage11 *computeUniformStorage =
+        GetAs<UniformStorage11>(&programD3D.getComputeUniformStorage());
+    ASSERT(computeUniformStorage);
+
+    ID3D11Buffer *computeConstantBuffer = computeUniformStorage->getConstantBuffer();
+
+    if (totalRegisterCountCS > 0 && computeUniformsDirty)
+    {
+        D3D11_MAPPED_SUBRESOURCE map = {0};
+        HRESULT result =
+            mDeviceContext->Map(computeConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+        ASSERT(SUCCEEDED(result));
+        auto *mapCS = static_cast<float(*)[4]>(map.pData);
+
+        ASSERT(mapCS);
+        for (const D3DUniform *uniform : uniformArray)
+        {
+            ASSERT(uniform->isReferencedByComputeShader());
+
+            if (uniform->isSampler())
+            {
+                continue;
+            }
+
+            unsigned int componentCount = (4 - uniform->registerCount);
+            memcpy(&mapCS[uniform->csRegisterIndex][uniform->registerElement], uniform->data,
+                   uniform->registerCount * sizeof(float) * componentCount);
+        }
+
+        mDeviceContext->Unmap(computeConstantBuffer, 0);
+    }
+
+    if (mCurrentComputeConstantBuffer != computeConstantBuffer)
+    {
+        mDeviceContext->CSSetConstantBuffers(
+            d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &computeConstantBuffer);
+        mCurrentComputeConstantBuffer = computeConstantBuffer;
+    }
+
+    if (!mDriverConstantBufferCS)
+    {
+        D3D11_BUFFER_DESC constantBufferDescription = {0};
+        d3d11::InitConstantBufferDesc(
+            &constantBufferDescription,
+            sizeof(dx_ComputeConstants11) + mSamplerMetadataCS.sizeBytes());
+        HRESULT result =
+            mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferCS);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::OutOfMemory()
+                   << "Failed to create compute shader constant buffer, " << result;
+        }
+        mDeviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+                                             &mDriverConstantBufferCS);
+    }
+
+    const dx_ComputeConstants11 &computeConstants = mStateManager.getComputeConstants();
+    size_t samplerMetadataReferencedBytesCS = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
+                                              programD3D.getUsedSamplerRange(gl::SAMPLER_COMPUTE);
+    applyDriverConstantsIfNeeded(&mAppliedComputeConstants, computeConstants, &mSamplerMetadataCS,
+                                 samplerMetadataReferencedBytesCS, mDriverConstantBufferCS);
+
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
new file mode 100644
index 0000000..7bd881f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -0,0 +1,646 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// Renderer11.h: Defines a back-end specific class for the D3D11 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
+#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+struct ImageIndex;
+}
+
+namespace rx
+{
+class Blit11;
+class Buffer11;
+class Clear11;
+class Context11;
+class IndexDataManager;
+struct PackPixelsParams;
+class PixelTransfer11;
+class RenderTarget11;
+class StreamingIndexBufferInterface;
+class Trim11;
+class VertexDataManager;
+
+struct Renderer11DeviceCaps
+{
+    D3D_FEATURE_LEVEL featureLevel;
+    bool supportsDXGI1_2;                // Support for DXGI 1.2
+    bool supportsClearView;              // Support for ID3D11DeviceContext1::ClearView
+    bool supportsConstantBufferOffsets;  // Support for Constant buffer offset
+    UINT B5G6R5support;    // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM
+    UINT B4G4R4A4support;  // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM
+    UINT B5G5R5A1support;  // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G5R5A1_UNORM
+    Optional<LARGE_INTEGER> driverVersion;  // Four-part driver version number.
+};
+
+enum
+{
+    MAX_VERTEX_UNIFORM_VECTORS_D3D11   = 1024,
+    MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024
+};
+
+// Possible reasons RendererD3D initialize can fail
+enum D3D11InitError
+{
+    // The renderer loaded successfully
+    D3D11_INIT_SUCCESS = 0,
+    // Failed to load the ANGLE & D3D compiler libraries
+    D3D11_INIT_COMPILER_ERROR,
+    // Failed to load a necessary DLL (non-compiler)
+    D3D11_INIT_MISSING_DEP,
+    // CreateDevice returned E_INVALIDARG
+    D3D11_INIT_CREATEDEVICE_INVALIDARG,
+    // CreateDevice failed with an error other than invalid arg
+    D3D11_INIT_CREATEDEVICE_ERROR,
+    // DXGI 1.2 required but not found
+    D3D11_INIT_INCOMPATIBLE_DXGI,
+    // Other initialization error
+    D3D11_INIT_OTHER_ERROR,
+    // CreateDevice returned E_FAIL
+    D3D11_INIT_CREATEDEVICE_FAIL,
+    // CreateDevice returned E_NOTIMPL
+    D3D11_INIT_CREATEDEVICE_NOTIMPL,
+    // CreateDevice returned E_OUTOFMEMORY
+    D3D11_INIT_CREATEDEVICE_OUTOFMEMORY,
+    // CreateDevice returned DXGI_ERROR_INVALID_CALL
+    D3D11_INIT_CREATEDEVICE_INVALIDCALL,
+    // CreateDevice returned DXGI_ERROR_SDK_COMPONENT_MISSING
+    D3D11_INIT_CREATEDEVICE_COMPONENTMISSING,
+    // CreateDevice returned DXGI_ERROR_WAS_STILL_DRAWING
+    D3D11_INIT_CREATEDEVICE_WASSTILLDRAWING,
+    // CreateDevice returned DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
+    D3D11_INIT_CREATEDEVICE_NOTAVAILABLE,
+    // CreateDevice returned DXGI_ERROR_DEVICE_HUNG
+    D3D11_INIT_CREATEDEVICE_DEVICEHUNG,
+    // CreateDevice returned NULL
+    D3D11_INIT_CREATEDEVICE_NULL,
+    NUM_D3D11_INIT_ERRORS
+};
+
+class Renderer11 : public RendererD3D
+{
+  public:
+    explicit Renderer11(egl::Display *display);
+    virtual ~Renderer11();
+
+    egl::Error initialize() override;
+    bool resetDevice() override;
+
+    egl::ConfigSet generateConfigs() override;
+    void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override;
+
+    ContextImpl *createContext(const gl::ContextState &state) override;
+
+    gl::Error flush();
+    gl::Error finish();
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+    NativeWindowD3D *createNativeWindow(EGLNativeWindowType window,
+                                        const egl::Config *config,
+                                        const egl::AttributeMap &attribs) const override;
+
+    SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
+                                  HANDLE shareHandle,
+                                  IUnknown *d3dTexture,
+                                  GLenum backBufferFormat,
+                                  GLenum depthBufferFormat,
+                                  EGLint orientation,
+                                  EGLint samples) override;
+    egl::Error getD3DTextureInfo(const egl::Config *configuration,
+                                 IUnknown *d3dTexture,
+                                 EGLint *width,
+                                 EGLint *height,
+                                 GLenum *fboFormat) const override;
+    egl::Error validateShareHandle(const egl::Config *config,
+                                   HANDLE shareHandle,
+                                   const egl::AttributeMap &attribs) const override;
+
+    gl::Error setSamplerState(gl::SamplerType type,
+                              int index,
+                              gl::Texture *texture,
+                              const gl::SamplerState &sampler) override;
+    gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) override;
+
+    gl::Error setUniformBuffers(const gl::ContextState &data,
+                                const std::vector<GLint> &vertexUniformBuffers,
+                                const std::vector<GLint> &fragmentUniformBuffers) override;
+
+    gl::Error updateState(ContextImpl *contextImpl, GLenum drawMode);
+
+    bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
+    gl::Error applyUniforms(const ProgramD3D &programD3D,
+                            GLenum drawMode,
+                            const std::vector<D3DUniform *> &uniformArray) override;
+    gl::Error applyVertexBuffer(const gl::State &state,
+                                GLenum mode,
+                                GLint first,
+                                GLsizei count,
+                                GLsizei instances,
+                                TranslatedIndexData *indexInfo);
+    gl::Error applyIndexBuffer(const gl::ContextState &data,
+                               const void *indices,
+                               GLsizei count,
+                               GLenum mode,
+                               GLenum type,
+                               TranslatedIndexData *indexInfo);
+    gl::Error applyTransformFeedbackBuffers(const gl::ContextState &data);
+
+    // lost device
+    bool testDeviceLost() override;
+    bool testDeviceResettable() override;
+
+    std::string getRendererDescription() const;
+    DeviceIdentifier getAdapterIdentifier() const override;
+
+    unsigned int getReservedVertexUniformVectors() const;
+    unsigned int getReservedFragmentUniformVectors() const;
+    unsigned int getReservedVertexUniformBuffers() const override;
+    unsigned int getReservedFragmentUniformBuffers() const override;
+
+    bool getShareHandleSupport() const;
+
+    bool getNV12TextureSupport() const;
+
+    int getMajorShaderModel() const override;
+    int getMinorShaderModel() const override;
+    std::string getShaderModelSuffix() const override;
+
+    // Pixel operations
+    gl::Error copyImage2D(const gl::Framebuffer *framebuffer,
+                          const gl::Rectangle &sourceRect,
+                          GLenum destFormat,
+                          const gl::Offset &destOffset,
+                          TextureStorage *storage,
+                          GLint level) override;
+    gl::Error copyImageCube(const gl::Framebuffer *framebuffer,
+                            const gl::Rectangle &sourceRect,
+                            GLenum destFormat,
+                            const gl::Offset &destOffset,
+                            TextureStorage *storage,
+                            GLenum target,
+                            GLint level) override;
+    gl::Error copyImage3D(const gl::Framebuffer *framebuffer,
+                          const gl::Rectangle &sourceRect,
+                          GLenum destFormat,
+                          const gl::Offset &destOffset,
+                          TextureStorage *storage,
+                          GLint level) override;
+    gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer,
+                               const gl::Rectangle &sourceRect,
+                               GLenum destFormat,
+                               const gl::Offset &destOffset,
+                               TextureStorage *storage,
+                               GLint level) override;
+
+    gl::Error copyTexture(const gl::Texture *source,
+                          GLint sourceLevel,
+                          const gl::Rectangle &sourceRect,
+                          GLenum destFormat,
+                          const gl::Offset &destOffset,
+                          TextureStorage *storage,
+                          GLenum destTarget,
+                          GLint destLevel,
+                          bool unpackFlipY,
+                          bool unpackPremultiplyAlpha,
+                          bool unpackUnmultiplyAlpha) override;
+    gl::Error copyCompressedTexture(const gl::Texture *source,
+                                    GLint sourceLevel,
+                                    TextureStorage *storage,
+                                    GLint destLevel) override;
+
+    // RenderTarget creation
+    gl::Error createRenderTarget(int width,
+                                 int height,
+                                 GLenum format,
+                                 GLsizei samples,
+                                 RenderTargetD3D **outRT) override;
+    gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override;
+
+    // Shader operations
+    gl::Error loadExecutable(const void *function,
+                             size_t length,
+                             ShaderType type,
+                             const std::vector<D3DVarying> &streamOutVaryings,
+                             bool separatedOutputBuffers,
+                             ShaderExecutableD3D **outExecutable) override;
+    gl::Error compileToExecutable(gl::InfoLog &infoLog,
+                                  const std::string &shaderHLSL,
+                                  ShaderType type,
+                                  const std::vector<D3DVarying> &streamOutVaryings,
+                                  bool separatedOutputBuffers,
+                                  const angle::CompilerWorkaroundsD3D &workarounds,
+                                  ShaderExecutableD3D **outExectuable) override;
+    gl::Error ensureHLSLCompilerInitialized() override;
+
+    UniformStorageD3D *createUniformStorage(size_t storageSize) override;
+
+    // Image operations
+    ImageD3D *createImage() override;
+    gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
+    gl::Error generateMipmapUsingD3D(TextureStorage *storage,
+                                     const gl::TextureState &textureState) override;
+    TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) override;
+    TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+                                                 RenderTargetD3D *renderTargetD3D) override;
+    TextureStorage *createTextureStorageExternal(
+        egl::Stream *stream,
+        const egl::Stream::GLTextureDescription &desc) override;
+    TextureStorage *createTextureStorage2D(GLenum internalformat,
+                                           bool renderTarget,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           int levels,
+                                           bool hintLevelZeroOnly) override;
+    TextureStorage *createTextureStorageCube(GLenum internalformat,
+                                             bool renderTarget,
+                                             int size,
+                                             int levels,
+                                             bool hintLevelZeroOnly) override;
+    TextureStorage *createTextureStorage3D(GLenum internalformat,
+                                           bool renderTarget,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLsizei depth,
+                                           int levels) override;
+    TextureStorage *createTextureStorage2DArray(GLenum internalformat,
+                                                bool renderTarget,
+                                                GLsizei width,
+                                                GLsizei height,
+                                                GLsizei depth,
+                                                int levels) override;
+
+    VertexBuffer *createVertexBuffer() override;
+    IndexBuffer *createIndexBuffer() override;
+
+    // Stream Creation
+    StreamProducerImpl *createStreamProducerD3DTextureNV12(
+        egl::Stream::ConsumerType consumerType,
+        const egl::AttributeMap &attribs) override;
+
+    // D3D11-renderer specific methods
+    ID3D11Device *getDevice() { return mDevice; }
+    void *getD3DDevice() override;
+    ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
+    ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; };
+    IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
+
+    RenderStateCache &getStateCache() { return mStateCache; }
+
+    Blit11 *getBlitter() { return mBlit; }
+    Clear11 *getClearer() { return mClear; }
+    gl::DebugAnnotator *getAnnotator();
+
+    // Buffer-to-texture and Texture-to-buffer copies
+    bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
+    gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack,
+                                      unsigned int offset,
+                                      RenderTargetD3D *destRenderTarget,
+                                      GLenum destinationFormat,
+                                      GLenum sourcePixelsType,
+                                      const gl::Box &destArea) override;
+
+    void markAllStateDirty();
+    gl::Error packPixels(const TextureHelper11 &textureHelper,
+                         const PackPixelsParams &params,
+                         uint8_t *pixelsOut);
+
+    bool getLUID(LUID *adapterLuid) const override;
+    VertexConversionType getVertexConversionType(
+        gl::VertexFormatType vertexFormatType) const override;
+    GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override;
+
+    // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+    // function.
+    gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib,
+                                                           const gl::VertexBinding &binding,
+                                                           GLsizei count,
+                                                           GLsizei instances) const override;
+
+    gl::Error readFromAttachment(const gl::FramebufferAttachment &srcAttachment,
+                                 const gl::Rectangle &sourceArea,
+                                 GLenum format,
+                                 GLenum type,
+                                 GLuint outputPitch,
+                                 const gl::PixelPackState &pack,
+                                 uint8_t *pixels);
+
+    gl::Error blitRenderbufferRect(const gl::Rectangle &readRect,
+                                   const gl::Rectangle &drawRect,
+                                   RenderTargetD3D *readRenderTarget,
+                                   RenderTargetD3D *drawRenderTarget,
+                                   GLenum filter,
+                                   const gl::Rectangle *scissor,
+                                   bool colorBlit,
+                                   bool depthBlit,
+                                   bool stencilBlit);
+
+    bool isES3Capable() const;
+    const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; };
+
+    RendererClass getRendererClass() const override { return RENDERER_D3D11; }
+    InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; }
+    StateManager11 *getStateManager() { return &mStateManager; }
+
+    void onSwap();
+    void onBufferCreate(const Buffer11 *created);
+    void onBufferDelete(const Buffer11 *deleted);
+
+    egl::Error getEGLDevice(DeviceImpl **device) override;
+
+    gl::Error genericDrawArrays(Context11 *context,
+                                GLenum mode,
+                                GLint first,
+                                GLsizei count,
+                                GLsizei instances);
+
+    gl::Error genericDrawElements(Context11 *context,
+                                  GLenum mode,
+                                  GLsizei count,
+                                  GLenum type,
+                                  const void *indices,
+                                  GLsizei instances,
+                                  const gl::IndexRange &indexRange);
+
+    gl::Error genericDrawIndirect(Context11 *context,
+                                  GLenum mode,
+                                  GLenum type,
+                                  const void *indirect);
+
+    // Necessary hack for default framebuffers in D3D.
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+    gl::Error getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut);
+
+    gl::Version getMaxSupportedESVersion() const override;
+
+    gl::Error dispatchCompute(Context11 *context,
+                              GLuint numGroupsX,
+                              GLuint numGroupsY,
+                              GLuint numGroupsZ);
+    gl::Error applyComputeUniforms(const ProgramD3D &programD3D,
+                                   const std::vector<D3DUniform *> &uniformArray) override;
+    gl::Error applyComputeShader(const gl::ContextState &data);
+
+    template <typename DescT, typename InitDataT, typename ResourceT>
+    gl::Error allocateResource(const DescT &desc, InitDataT *initData, ResourceT *resourceOut)
+    {
+        return mResourceManager11.allocate(this, &desc, initData, resourceOut);
+    }
+
+    template <typename InitDataT, typename ResourceT>
+    gl::Error allocateResourceNoDesc(InitDataT *initData, ResourceT *resourceOut)
+    {
+        return mResourceManager11.allocate(this, nullptr, initData, resourceOut);
+    }
+
+  protected:
+    gl::Error clearTextures(gl::SamplerType samplerType,
+                            size_t rangeStart,
+                            size_t rangeEnd) override;
+
+  private:
+    gl::Error drawArraysImpl(const gl::ContextState &data,
+                             GLenum mode,
+                             GLint startVertex,
+                             GLsizei count,
+                             GLsizei instances);
+    gl::Error drawElementsImpl(const gl::ContextState &data,
+                               const TranslatedIndexData &indexInfo,
+                               GLenum mode,
+                               GLsizei count,
+                               GLenum type,
+                               const void *indices,
+                               GLsizei instances);
+    gl::Error drawArraysIndirectImpl(const gl::ContextState &data,
+                                     GLenum mode,
+                                     const void *indirect);
+    gl::Error drawElementsIndirectImpl(const gl::ContextState &data,
+                                       GLenum mode,
+                                       GLenum type,
+                                       const void *indirect);
+
+    // Support directly using indirect draw buffer.
+    bool supportsFastIndirectDraw(const gl::State &state, GLenum mode, GLenum type);
+
+    void generateCaps(gl::Caps *outCaps,
+                      gl::TextureCapsMap *outTextureCaps,
+                      gl::Extensions *outExtensions,
+                      gl::Limitations *outLimitations) const override;
+
+    angle::WorkaroundsD3D generateWorkarounds() const override;
+
+    gl::Error drawLineLoop(const gl::ContextState &data,
+                           GLsizei count,
+                           GLenum type,
+                           const void *indices,
+                           int baseVertex,
+                           int instances);
+    gl::Error drawTriangleFan(const gl::ContextState &data,
+                              GLsizei count,
+                              GLenum type,
+                              const void *indices,
+                              int baseVertex,
+                              int instances);
+
+    gl::Error applyShaders(const gl::ContextState &data, GLenum drawMode);
+    gl::Error generateSwizzle(gl::Texture *texture);
+    gl::Error generateSwizzles(const gl::ContextState &data, gl::SamplerType type);
+    gl::Error generateSwizzles(const gl::ContextState &data);
+
+    gl::ErrorOrResult<TextureHelper11> resolveMultisampledTexture(RenderTarget11 *renderTarget,
+                                                                  bool depth,
+                                                                  bool stencil);
+
+    void populateRenderer11DeviceCaps();
+
+    void updateHistograms();
+
+    class SamplerMetadataD3D11 final : angle::NonCopyable
+    {
+      public:
+        SamplerMetadataD3D11();
+        ~SamplerMetadataD3D11();
+
+        struct dx_SamplerMetadata
+        {
+            int baseLevel;
+            int internalFormatBits;
+            int wrapModes;
+            int padding;  // This just pads the struct to 16 bytes
+        };
+        static_assert(sizeof(dx_SamplerMetadata) == 16u,
+                      "Sampler metadata struct must be one 4-vec / 16 bytes.");
+
+        void initData(unsigned int samplerCount);
+        void update(unsigned int samplerIndex, const gl::Texture &texture);
+
+        const dx_SamplerMetadata *getData() const;
+        size_t sizeBytes() const;
+        bool isDirty() const { return mDirty; }
+        void markClean() { mDirty = false; }
+
+      private:
+        std::vector<dx_SamplerMetadata> mSamplerMetadata;
+        bool mDirty;
+    };
+
+    template <class TShaderConstants>
+    void applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants,
+                                      const TShaderConstants &constants,
+                                      SamplerMetadataD3D11 *samplerMetadata,
+                                      size_t samplerMetadataReferencedBytes,
+                                      ID3D11Buffer *driverConstantBuffer);
+
+    gl::Error copyImageInternal(const gl::Framebuffer *framebuffer,
+                                const gl::Rectangle &sourceRect,
+                                GLenum destFormat,
+                                const gl::Offset &destOffset,
+                                RenderTargetD3D *destRenderTarget);
+
+    gl::SupportedSampleSet generateSampleSetFromCaps(
+        const gl::TextureCaps &colorBufferFormatCaps,
+        const gl::TextureCaps &depthStencilBufferFormatCaps) const;
+
+    HMODULE mD3d11Module;
+    HMODULE mDxgiModule;
+    HMODULE mDCompModule;
+    std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
+    D3D_DRIVER_TYPE mRequestedDriverType;
+    bool mCreatedWithDeviceEXT;
+    DeviceD3D *mEGLDevice;
+
+    HLSLCompiler mCompiler;
+
+    egl::Error initializeD3DDevice();
+    void initializeDevice();
+    void releaseDeviceResources();
+    void release();
+
+    d3d11::ANGLED3D11DeviceType getDeviceType() const;
+
+    RenderStateCache mStateCache;
+
+    // Currently applied sampler states
+    std::vector<bool> mForceSetVertexSamplerStates;
+    std::vector<gl::SamplerState> mCurVertexSamplerStates;
+
+    std::vector<bool> mForceSetPixelSamplerStates;
+    std::vector<gl::SamplerState> mCurPixelSamplerStates;
+
+    std::vector<bool> mForceSetComputeSamplerStates;
+    std::vector<gl::SamplerState> mCurComputeSamplerStates;
+
+    StateManager11 mStateManager;
+
+    // Currently applied primitive topology
+    D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
+
+    // Currently applied index buffer
+    ID3D11Buffer *mAppliedIB;
+    DXGI_FORMAT mAppliedIBFormat;
+    unsigned int mAppliedIBOffset;
+    bool mAppliedIBChanged;
+
+    // Currently applied transform feedback buffers
+    uintptr_t mAppliedTFObject;
+
+    // Currently applied shaders
+    uintptr_t mAppliedVertexShader;
+    uintptr_t mAppliedGeometryShader;
+    uintptr_t mAppliedPixelShader;
+    uintptr_t mAppliedComputeShader;
+
+    dx_VertexConstants11 mAppliedVertexConstants;
+    ID3D11Buffer *mDriverConstantBufferVS;
+    SamplerMetadataD3D11 mSamplerMetadataVS;
+    ID3D11Buffer *mCurrentVertexConstantBuffer;
+    unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+    GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+    GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+
+    dx_PixelConstants11 mAppliedPixelConstants;
+    ID3D11Buffer *mDriverConstantBufferPS;
+    SamplerMetadataD3D11 mSamplerMetadataPS;
+    ID3D11Buffer *mCurrentPixelConstantBuffer;
+    unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
+    GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
+    GLsizeiptr mCurrentConstantBufferPSSize[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
+
+    dx_ComputeConstants11 mAppliedComputeConstants;
+    ID3D11Buffer *mDriverConstantBufferCS;
+    SamplerMetadataD3D11 mSamplerMetadataCS;
+    ID3D11Buffer *mCurrentComputeConstantBuffer;
+
+    ID3D11Buffer *mCurrentGeometryConstantBuffer;
+
+    // Vertex, index and input layouts
+    VertexDataManager *mVertexDataManager;
+    IndexDataManager *mIndexDataManager;
+    InputLayoutCache mInputLayoutCache;
+
+    StreamingIndexBufferInterface *mLineLoopIB;
+    StreamingIndexBufferInterface *mTriangleFanIB;
+
+    // Texture copy resources
+    Blit11 *mBlit;
+    PixelTransfer11 *mPixelTransfer;
+
+    // Masked clear resources
+    Clear11 *mClear;
+
+    // Perform trim for D3D resources
+    Trim11 *mTrim;
+
+    // Sync query
+    ID3D11Query *mSyncQuery;
+
+    // Created objects state tracking
+    std::set<const Buffer11 *> mAliveBuffers;
+
+    double mLastHistogramUpdateTime;
+
+    ID3D11Device *mDevice;
+    Renderer11DeviceCaps mRenderer11DeviceCaps;
+    ID3D11DeviceContext *mDeviceContext;
+    ID3D11DeviceContext1 *mDeviceContext1;
+    IDXGIAdapter *mDxgiAdapter;
+    DXGI_ADAPTER_DESC mAdapterDescription;
+    char mDescription[128];
+    IDXGIFactory *mDxgiFactory;
+    ID3D11Debug *mDebug;
+
+    std::vector<GLuint> mScratchIndexDataBuffer;
+
+    angle::ScratchBuffer mScratchMemoryBuffer;
+
+    gl::DebugAnnotator *mAnnotator;
+
+    mutable Optional<bool> mSupportsShareHandles;
+    ResourceManager11 mResourceManager11;
+};
+
+}  // namespace rx
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp
new file mode 100644
index 0000000..3b56434
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp
@@ -0,0 +1,130 @@
+//
+// Copyright 2017 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.
+//
+// ResourceManager11:
+//   Centralized point of allocation for all D3D11 Resources.
+
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
+namespace rx
+{
+
+namespace
+{
+template <typename T>
+size_t ComputeMemoryUsage(const T *desc)
+{
+    return 0;
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+                       const D3D11_RENDER_TARGET_VIEW_DESC *desc,
+                       ID3D11Resource *resource,
+                       ID3D11RenderTargetView **renderTargetView)
+{
+    return device->CreateRenderTargetView(resource, desc, renderTargetView);
+}
+
+#define ANGLE_RESOURCE_STRINGIFY_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) #RESTYPE
+
+constexpr std::array<const char *, NumResourceTypes> kResourceTypeNames = {
+    {ANGLE_RESOURCE_TYPE_OP(Stringify, ANGLE_RESOURCE_STRINGIFY_OP)}};
+}  // anonymous namespace
+
+// ResourceManager11 Implementation.
+ResourceManager11::ResourceManager11()
+    : mAllocatedResourceCounts({{}}), mAllocatedResourceDeviceMemory({{}})
+{
+}
+
+ResourceManager11::~ResourceManager11()
+{
+    for (size_t count : mAllocatedResourceCounts)
+    {
+        ASSERT(count == 0);
+    }
+
+    for (size_t memorySize : mAllocatedResourceDeviceMemory)
+    {
+        ASSERT(memorySize == 0);
+    }
+}
+
+template <typename T>
+gl::Error ResourceManager11::allocate(Renderer11 *renderer,
+                                      const GetDescFromD3D11<T> *desc,
+                                      GetInitDataFromD3D11<T> *initData,
+                                      Resource11<T> *resourceOut)
+{
+    ID3D11Device *device = renderer->getDevice();
+    T *resource          = nullptr;
+
+    HRESULT hr = CreateResource(device, desc, initData, &resource);
+
+    if (FAILED(hr))
+    {
+        ASSERT(!resource);
+        if (d3d11::isDeviceLostError(hr))
+        {
+            renderer->notifyDeviceLost();
+        }
+        return gl::OutOfMemory() << "Error allocating "
+                                 << std::string(kResourceTypeNames[ResourceTypeIndex<T>()]) << ". "
+                                 << gl::FmtHR(hr);
+    }
+
+    ASSERT(resource);
+    incrResource(GetResourceTypeFromD3D11<T>(), ComputeMemoryUsage(desc));
+    *resourceOut = std::move(Resource11<T>(resource, this));
+    return gl::NoError();
+}
+
+void ResourceManager11::incrResource(ResourceType resourceType, size_t memorySize)
+{
+    mAllocatedResourceCounts[ResourceTypeIndex(resourceType)]++;
+    mAllocatedResourceDeviceMemory[ResourceTypeIndex(resourceType)] += memorySize;
+}
+
+void ResourceManager11::decrResource(ResourceType resourceType, size_t memorySize)
+{
+    ASSERT(mAllocatedResourceCounts[ResourceTypeIndex(resourceType)] > 0);
+    mAllocatedResourceCounts[ResourceTypeIndex(resourceType)]--;
+    ASSERT(mAllocatedResourceDeviceMemory[ResourceTypeIndex(resourceType)] >= memorySize);
+    mAllocatedResourceDeviceMemory[ResourceTypeIndex(resourceType)] -= memorySize;
+}
+
+template <typename T>
+void ResourceManager11::onRelease(T *resource)
+{
+    ASSERT(resource);
+
+    GetDescFromD3D11<T> desc;
+    resource->GetDesc(&desc);
+    decrResource(GetResourceTypeFromD3D11<T>(), ComputeMemoryUsage(&desc));
+}
+
+#define ANGLE_INSTANTIATE_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+    \
+template gl::Error                                                             \
+    ResourceManager11::allocate(\
+Renderer11 *,                                                                  \
+                                \
+const DESCTYPE *,                                                              \
+                                \
+INITDATATYPE *,                                                                \
+                                \
+Resource11<D3D11TYPE> *);                                                      \
+    \
+\
+template void                                                                  \
+    ResourceManager11::onRelease(D3D11TYPE *);
+
+ANGLE_RESOURCE_TYPE_OP(Instantitate, ANGLE_INSTANTIATE_OP)
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h
new file mode 100644
index 0000000..6daa9f0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h
@@ -0,0 +1,251 @@
+//
+// Copyright 2017 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.
+//
+// ResourceManager11:
+//   Centralized point of allocation for all D3D11 Resources.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
+
+#include <array>
+#include <memory>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+class Renderer11;
+class ResourceManager11;
+
+// Format: ResourceType, D3D11 type, DESC type, init data type.
+#define ANGLE_RESOURCE_TYPE_OP(NAME, OP)                                              \
+    OP(NAME, RenderTargetView, ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC, \
+       ID3D11Resource)
+
+#define ANGLE_RESOURCE_TYPE_LIST(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) RESTYPE,
+
+enum class ResourceType
+{
+    ANGLE_RESOURCE_TYPE_OP(List, ANGLE_RESOURCE_TYPE_LIST) Last
+};
+
+#undef ANGLE_RESOURCE_TYPE_LIST
+
+constexpr size_t ResourceTypeIndex(ResourceType resourceType)
+{
+    return static_cast<size_t>(resourceType);
+}
+
+constexpr size_t NumResourceTypes = ResourceTypeIndex(ResourceType::Last);
+
+#define ANGLE_RESOURCE_TYPE_TO_D3D11(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+    \
+template<> struct NAME<ResourceType::RESTYPE>                                          \
+    {                                                                                  \
+        using Value = D3D11TYPE;                                                       \
+    };
+
+#define ANGLE_RESOURCE_TYPE_TO_DESC(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+    \
+template<> struct NAME<ResourceType::RESTYPE>                                         \
+    {                                                                                 \
+        using Value = DESCTYPE;                                                       \
+    };
+
+#define ANGLE_RESOURCE_TYPE_TO_INIT_DATA(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+    \
+template<> struct NAME<ResourceType::RESTYPE>                                              \
+    {                                                                                      \
+        using Value = INITDATATYPE;                                                        \
+    };
+
+#define ANGLE_RESOURCE_TYPE_TO_TYPE(NAME, OP) \
+    template <ResourceType Param>             \
+    struct NAME;                              \
+    ANGLE_RESOURCE_TYPE_OP(NAME, OP)          \
+    \
+template<ResourceType Param> struct NAME      \
+    {                                         \
+    };                                        \
+    \
+template<ResourceType Param> using Get##NAME = typename NAME<Param>::Value;
+
+ANGLE_RESOURCE_TYPE_TO_TYPE(D3D11Type, ANGLE_RESOURCE_TYPE_TO_D3D11)
+ANGLE_RESOURCE_TYPE_TO_TYPE(DescType, ANGLE_RESOURCE_TYPE_TO_DESC)
+ANGLE_RESOURCE_TYPE_TO_TYPE(InitDataType, ANGLE_RESOURCE_TYPE_TO_INIT_DATA)
+
+#undef ANGLE_RESOURCE_TYPE_TO_D3D11
+#undef ANGLE_RESOURCE_TYPE_TO_DESC
+#undef ANGLE_RESOURCE_TYPE_TO_INIT_DATA
+#undef ANGLE_RESOURCE_TYPE_TO_TYPE
+
+#define ANGLE_TYPE_TO_RESOURCE_TYPE(NAME, OP)               \
+    template <typename Param>                               \
+    struct NAME;                                            \
+    ANGLE_RESOURCE_TYPE_OP(NAME, OP)                        \
+    \
+template<typename Param> struct NAME                        \
+    {                                                       \
+    };                                                      \
+    \
+template<typename Param> constexpr ResourceType Get##NAME() \
+    {                                                       \
+        return NAME<Param>::Value;                          \
+    }
+
+#define ANGLE_D3D11_TO_RESOURCE_TYPE(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+    \
+template<> struct NAME<D3D11TYPE>                                                      \
+    {                                                                                  \
+        static constexpr ResourceType Value = ResourceType::RESTYPE;                   \
+    };
+
+ANGLE_TYPE_TO_RESOURCE_TYPE(ResourceTypeFromD3D11, ANGLE_D3D11_TO_RESOURCE_TYPE)
+
+#undef ANGLE_D3D11_TO_RESOURCE_TYPE
+#undef ANGLE_TYPE_TO_RESOURCE_TYPE
+
+template <typename T>
+using GetDescFromD3D11 = GetDescType<ResourceTypeFromD3D11<T>::Value>;
+
+template <typename T>
+using GetInitDataFromD3D11 = GetInitDataType<ResourceTypeFromD3D11<T>::Value>;
+
+template <typename T>
+constexpr size_t ResourceTypeIndex()
+{
+    return static_cast<size_t>(GetResourceTypeFromD3D11<T>());
+}
+
+template <typename T>
+struct TypedData
+{
+    TypedData() {}
+    ~TypedData();
+
+    T *object                  = nullptr;
+    ResourceManager11 *manager = nullptr;
+};
+
+// Smart pointer type. Wraps the resource and a factory for safe deletion.
+template <typename T, template <class> class Pointer, typename DataT>
+class Resource11Base : angle::NonCopyable
+{
+  public:
+    T *get() const { return mData->object; }
+
+    void setDebugName(const char *name) { d3d11::SetDebugName(mData->object, name); }
+
+    void set(T *object)
+    {
+        ASSERT(!valid());
+        mData->object = object;
+    }
+
+    bool valid() const { return (mData->object != nullptr); }
+
+    void reset() { mData.reset(new DataT()); }
+
+  protected:
+    friend class TextureHelper11;
+
+    Resource11Base() : mData(new DataT()) {}
+
+    Resource11Base(Resource11Base &&movedObj) : mData(new DataT())
+    {
+        std::swap(mData, movedObj.mData);
+    }
+
+    virtual ~Resource11Base() { mData.reset(); }
+
+    Resource11Base &operator=(Resource11Base &&movedObj)
+    {
+        std::swap(mData, movedObj.mData);
+        return *this;
+    }
+
+    Pointer<DataT> mData;
+};
+
+template <typename T>
+using UniquePtr = typename std::unique_ptr<T, std::default_delete<T>>;
+
+template <typename ResourceT>
+class Resource11 : public Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>>
+{
+  public:
+    Resource11() {}
+    Resource11(Resource11 &&other)
+        : Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>>(std::move(other))
+    {
+    }
+    Resource11 &operator=(Resource11 &&other)
+    {
+        std::swap(this->mData, other.mData);
+        return *this;
+    }
+
+  private:
+    friend class ResourceManager11;
+
+    Resource11(ResourceT *object, ResourceManager11 *manager)
+    {
+        this->mData->object  = object;
+        this->mData->manager = manager;
+    }
+};
+
+class ResourceManager11 final : angle::NonCopyable
+{
+  public:
+    ResourceManager11();
+    ~ResourceManager11();
+
+    template <typename T>
+    gl::Error allocate(Renderer11 *renderer,
+                       const GetDescFromD3D11<T> *desc,
+                       GetInitDataFromD3D11<T> *initData,
+                       Resource11<T> *resourceOut);
+
+    template <typename T>
+    void onRelease(T *resource);
+
+  private:
+    void incrResource(ResourceType resourceType, size_t memorySize);
+    void decrResource(ResourceType resourceType, size_t memorySize);
+
+    std::array<size_t, NumResourceTypes> mAllocatedResourceCounts;
+    std::array<size_t, NumResourceTypes> mAllocatedResourceDeviceMemory;
+};
+
+template <typename ResourceT>
+TypedData<ResourceT>::~TypedData()
+{
+    if (object)
+    {
+        // We can have a nullptr factory when holding passed-in resources.
+        if (manager)
+        {
+            manager->onRelease(object);
+        }
+        object->Release();
+    }
+}
+
+#define ANGLE_RESOURCE_TYPE_CLASS(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+    using RESTYPE = Resource11<D3D11TYPE>;
+
+namespace d3d11
+{
+ANGLE_RESOURCE_TYPE_OP(ClassList, ANGLE_RESOURCE_TYPE_CLASS)
+}  // namespace d3d11
+
+#undef ANGLE_RESOURCE_TYPE_CLASS
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
new file mode 100644
index 0000000..ca0bd3f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
@@ -0,0 +1,118 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader
+// executable implementation details.
+
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable)
+    : ShaderExecutableD3D(function, length)
+{
+    mPixelExecutable = executable;
+    mVertexExecutable    = nullptr;
+    mGeometryExecutable  = nullptr;
+    mStreamOutExecutable = nullptr;
+    mComputeExecutable   = nullptr;
+}
+
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut)
+    : ShaderExecutableD3D(function, length)
+{
+    mVertexExecutable = executable;
+    mPixelExecutable     = nullptr;
+    mGeometryExecutable  = nullptr;
+    mStreamOutExecutable = streamOut;
+    mComputeExecutable   = nullptr;
+}
+
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable)
+    : ShaderExecutableD3D(function, length)
+{
+    mGeometryExecutable = executable;
+    mVertexExecutable    = nullptr;
+    mPixelExecutable     = nullptr;
+    mStreamOutExecutable = nullptr;
+    mComputeExecutable   = nullptr;
+}
+
+ShaderExecutable11::ShaderExecutable11(const void *function,
+                                       size_t length,
+                                       ID3D11ComputeShader *executable)
+    : ShaderExecutableD3D(function, length)
+{
+    mComputeExecutable   = executable;
+    mPixelExecutable     = nullptr;
+    mVertexExecutable    = nullptr;
+    mGeometryExecutable  = nullptr;
+    mStreamOutExecutable = nullptr;
+}
+
+ShaderExecutable11::~ShaderExecutable11()
+{
+    SafeRelease(mVertexExecutable);
+    SafeRelease(mPixelExecutable);
+    SafeRelease(mGeometryExecutable);
+    SafeRelease(mStreamOutExecutable);
+    SafeRelease(mComputeExecutable);
+}
+
+ID3D11VertexShader *ShaderExecutable11::getVertexShader() const
+{
+    return mVertexExecutable;
+}
+
+ID3D11PixelShader *ShaderExecutable11::getPixelShader() const
+{
+    return mPixelExecutable;
+}
+
+ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const
+{
+    return mGeometryExecutable;
+}
+
+ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const
+{
+    return mStreamOutExecutable;
+}
+
+ID3D11ComputeShader *ShaderExecutable11::getComputeShader() const
+{
+    return mComputeExecutable;
+}
+
+UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize)
+    : UniformStorageD3D(initialSize), mConstantBuffer(nullptr)
+{
+    ID3D11Device *d3d11Device = renderer->getDevice();
+
+    if (initialSize > 0)
+    {
+        D3D11_BUFFER_DESC constantBufferDescription = {0};
+        constantBufferDescription.ByteWidth           = static_cast<unsigned int>(initialSize);
+        constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC;
+        constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+        constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+        constantBufferDescription.MiscFlags = 0;
+        constantBufferDescription.StructureByteStride = 0;
+
+        HRESULT result =
+            d3d11Device->CreateBuffer(&constantBufferDescription, nullptr, &mConstantBuffer);
+        ASSERT(SUCCEEDED(result));
+    }
+}
+
+UniformStorage11::~UniformStorage11()
+{
+    SafeRelease(mConstantBuffer);
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
new file mode 100644
index 0000000..1fe1a20
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader
+// executable implementation details.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
+
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+
+namespace rx
+{
+class Renderer11;
+class UniformStorage11;
+
+class ShaderExecutable11 : public ShaderExecutableD3D
+{
+  public:
+    ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable);
+    ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut);
+    ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable);
+    ShaderExecutable11(const void *function, size_t length, ID3D11ComputeShader *executable);
+
+    virtual ~ShaderExecutable11();
+
+    ID3D11PixelShader *getPixelShader() const;
+    ID3D11VertexShader *getVertexShader() const;
+    ID3D11GeometryShader *getGeometryShader() const;
+    ID3D11GeometryShader *getStreamOutShader() const;
+    ID3D11ComputeShader *getComputeShader() const;
+
+  private:
+    ID3D11PixelShader *mPixelExecutable;
+    ID3D11VertexShader *mVertexExecutable;
+    ID3D11GeometryShader *mGeometryExecutable;
+    ID3D11GeometryShader *mStreamOutExecutable;
+    ID3D11ComputeShader *mComputeExecutable;
+};
+
+class UniformStorage11 : public UniformStorageD3D
+{
+  public:
+    UniformStorage11(Renderer11 *renderer, size_t initialSize);
+    virtual ~UniformStorage11();
+
+    ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; }
+
+  private:
+    ID3D11Buffer *mConstantBuffer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
new file mode 100644
index 0000000..22608cb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -0,0 +1,1140 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager11.cpp: Defines a class for caching D3D11 state
+
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+
+namespace rx
+{
+
+namespace
+{
+bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
+{
+    unsigned mipLevel   = index.mipIndex;
+    GLint layerIndex    = index.layerIndex;
+    GLenum type         = index.type;
+
+    switch (desc.ViewDimension)
+    {
+        case D3D11_SRV_DIMENSION_TEXTURE2D:
+        {
+            bool allLevels         = (desc.Texture2D.MipLevels == std::numeric_limits<UINT>::max());
+            unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
+            maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;
+
+            unsigned mipMin = index.mipIndex;
+            unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex;
+
+            return type == GL_TEXTURE_2D &&
+                   gl::RangeUI(mipMin, mipMax)
+                       .intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
+        }
+
+        case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+        {
+            bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max());
+            unsigned int maxSrvMip =
+                desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
+            maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
+
+            unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
+
+            // Cube maps can be mapped to Texture2DArray SRVs
+            return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) &&
+                   desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
+                   desc.Texture2DArray.FirstArraySlice <= static_cast<UINT>(layerIndex) &&
+                   static_cast<UINT>(layerIndex) < maxSlice;
+        }
+
+        case D3D11_SRV_DIMENSION_TEXTURECUBE:
+        {
+            bool allLevels = (desc.TextureCube.MipLevels == std::numeric_limits<UINT>::max());
+            unsigned int maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
+            maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;
+
+            return gl::IsCubeMapTextureTarget(type) &&
+                   desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
+        }
+
+        case D3D11_SRV_DIMENSION_TEXTURE3D:
+        {
+            bool allLevels         = (desc.Texture3D.MipLevels == std::numeric_limits<UINT>::max());
+            unsigned int maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
+            maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;
+
+            return type == GL_TEXTURE_3D && desc.Texture3D.MostDetailedMip <= mipLevel &&
+                   mipLevel < maxSrvMip;
+        }
+        default:
+            // We only handle the cases corresponding to valid image indexes
+            UNIMPLEMENTED();
+    }
+
+    return false;
+}
+
+// Does *not* increment the resource ref count!!
+ID3D11Resource *GetViewResource(ID3D11View *view)
+{
+    ID3D11Resource *resource = nullptr;
+    ASSERT(view);
+    view->GetResource(&resource);
+    resource->Release();
+    return resource;
+}
+
+}  // anonymous namespace
+
+void StateManager11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv)
+{
+    ASSERT(resourceIndex < mCurrentSRVs.size());
+    SRVRecord *record = &mCurrentSRVs[resourceIndex];
+
+    record->srv = reinterpret_cast<uintptr_t>(srv);
+    if (srv)
+    {
+        record->resource = reinterpret_cast<uintptr_t>(GetViewResource(srv));
+        srv->GetDesc(&record->desc);
+        mHighestUsedSRV = std::max(resourceIndex + 1, mHighestUsedSRV);
+    }
+    else
+    {
+        record->resource = 0;
+
+        if (resourceIndex + 1 == mHighestUsedSRV)
+        {
+            do
+            {
+                --mHighestUsedSRV;
+            } while (mHighestUsedSRV > 0 && mCurrentSRVs[mHighestUsedSRV].srv == 0);
+        }
+    }
+}
+
+void StateManager11::SRVCache::clear()
+{
+    if (mCurrentSRVs.empty())
+    {
+        return;
+    }
+
+    memset(&mCurrentSRVs[0], 0, sizeof(SRVRecord) * mCurrentSRVs.size());
+    mHighestUsedSRV = 0;
+}
+
+static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
+                                    GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED_EXT,
+                                    GL_COMMANDS_COMPLETED_CHROMIUM};
+
+StateManager11::StateManager11(Renderer11 *renderer)
+    : mRenderer(renderer),
+      mBlendStateIsDirty(false),
+      mCurBlendColor(0, 0, 0, 0),
+      mCurSampleMask(0),
+      mDepthStencilStateIsDirty(false),
+      mCurStencilRef(0),
+      mCurStencilBackRef(0),
+      mCurStencilSize(0),
+      mRasterizerStateIsDirty(false),
+      mScissorStateIsDirty(false),
+      mCurScissorEnabled(false),
+      mCurScissorRect(),
+      mViewportStateIsDirty(false),
+      mCurViewport(),
+      mCurNear(0.0f),
+      mCurFar(0.0f),
+      mViewportBounds(),
+      mRenderTargetIsDirty(false),
+      mDirtyCurrentValueAttribs(),
+      mCurrentValueAttribs()
+{
+    mCurBlendState.blend                 = false;
+    mCurBlendState.sourceBlendRGB        = GL_ONE;
+    mCurBlendState.destBlendRGB          = GL_ZERO;
+    mCurBlendState.sourceBlendAlpha      = GL_ONE;
+    mCurBlendState.destBlendAlpha        = GL_ZERO;
+    mCurBlendState.blendEquationRGB      = GL_FUNC_ADD;
+    mCurBlendState.blendEquationAlpha    = GL_FUNC_ADD;
+    mCurBlendState.colorMaskRed          = true;
+    mCurBlendState.colorMaskBlue         = true;
+    mCurBlendState.colorMaskGreen        = true;
+    mCurBlendState.colorMaskAlpha        = true;
+    mCurBlendState.sampleAlphaToCoverage = false;
+    mCurBlendState.dither                = false;
+
+    mCurDepthStencilState.depthTest                = false;
+    mCurDepthStencilState.depthFunc                = GL_LESS;
+    mCurDepthStencilState.depthMask                = true;
+    mCurDepthStencilState.stencilTest              = false;
+    mCurDepthStencilState.stencilMask              = true;
+    mCurDepthStencilState.stencilFail              = GL_KEEP;
+    mCurDepthStencilState.stencilPassDepthFail     = GL_KEEP;
+    mCurDepthStencilState.stencilPassDepthPass     = GL_KEEP;
+    mCurDepthStencilState.stencilWritemask         = static_cast<GLuint>(-1);
+    mCurDepthStencilState.stencilBackFunc          = GL_ALWAYS;
+    mCurDepthStencilState.stencilBackMask          = static_cast<GLuint>(-1);
+    mCurDepthStencilState.stencilBackFail          = GL_KEEP;
+    mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP;
+    mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP;
+    mCurDepthStencilState.stencilBackWritemask     = static_cast<GLuint>(-1);
+
+    mCurRasterState.rasterizerDiscard   = false;
+    mCurRasterState.cullFace            = false;
+    mCurRasterState.cullMode            = GL_BACK;
+    mCurRasterState.frontFace           = GL_CCW;
+    mCurRasterState.polygonOffsetFill   = false;
+    mCurRasterState.polygonOffsetFactor = 0.0f;
+    mCurRasterState.polygonOffsetUnits  = 0.0f;
+    mCurRasterState.pointDrawMode       = false;
+    mCurRasterState.multiSample         = false;
+
+    // Initially all current value attributes must be updated on first use.
+    mDirtyCurrentValueAttribs.flip();
+}
+
+StateManager11::~StateManager11()
+{
+}
+
+void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
+                                                unsigned int stencilSize)
+{
+    if (!depthStencilInitialized || stencilSize != mCurStencilSize)
+    {
+        mCurStencilSize           = stencilSize;
+        mDepthStencilStateIsDirty = true;
+    }
+}
+
+void StateManager11::setViewportBounds(const int width, const int height)
+{
+    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 &&
+        (mViewportBounds.width != width || mViewportBounds.height != height))
+    {
+        mViewportBounds       = gl::Extents(width, height, 1);
+        mViewportStateIsDirty = true;
+    }
+}
+
+void StateManager11::updatePresentPath(bool presentPathFastActive,
+                                       const gl::FramebufferAttachment *framebufferAttachment)
+{
+    const int colorBufferHeight =
+        framebufferAttachment ? framebufferAttachment->getSize().height : 0;
+
+    if ((mCurPresentPathFastEnabled != presentPathFastActive) ||
+        (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight)))
+    {
+        mCurPresentPathFastEnabled           = presentPathFastActive;
+        mCurPresentPathFastColorBufferHeight = colorBufferHeight;
+        mViewportStateIsDirty                = true;  // Viewport may need to be vertically inverted
+        mScissorStateIsDirty                 = true;  // Scissor rect may need to be vertically inverted
+        mRasterizerStateIsDirty              = true;  // Cull Mode may need to be inverted
+    }
+}
+
+void StateManager11::setComputeConstants(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+    mComputeConstants.numWorkGroups[0] = numGroupsX;
+    mComputeConstants.numWorkGroups[1] = numGroupsY;
+    mComputeConstants.numWorkGroups[2] = numGroupsZ;
+}
+
+void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+    if (!dirtyBits.any())
+    {
+        return;
+    }
+
+    for (auto dirtyBit : dirtyBits)
+    {
+        switch (dirtyBit)
+        {
+            case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
+            {
+                const gl::BlendState &blendState = state.getBlendState();
+                if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
+                    blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
+                {
+                    mBlendStateIsDirty = true;
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_BLEND_FUNCS:
+            {
+                const gl::BlendState &blendState = state.getBlendState();
+                if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB ||
+                    blendState.destBlendRGB != mCurBlendState.destBlendRGB ||
+                    blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
+                    blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
+                {
+                    mBlendStateIsDirty = true;
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_BLEND_ENABLED:
+                if (state.getBlendState().blend != mCurBlendState.blend)
+                {
+                    mBlendStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
+                if (state.getBlendState().sampleAlphaToCoverage !=
+                    mCurBlendState.sampleAlphaToCoverage)
+                {
+                    mBlendStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_DITHER_ENABLED:
+                if (state.getBlendState().dither != mCurBlendState.dither)
+                {
+                    mBlendStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_COLOR_MASK:
+            {
+                const gl::BlendState &blendState = state.getBlendState();
+                if (blendState.colorMaskRed != mCurBlendState.colorMaskRed ||
+                    blendState.colorMaskGreen != mCurBlendState.colorMaskGreen ||
+                    blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
+                    blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
+                {
+                    mBlendStateIsDirty = true;
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_BLEND_COLOR:
+                if (state.getBlendColor() != mCurBlendColor)
+                {
+                    mBlendStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_MASK:
+                if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
+                if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_FUNC:
+                if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+                if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
+            {
+                const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+                if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc ||
+                    depthStencil.stencilMask != mCurDepthStencilState.stencilMask ||
+                    state.getStencilRef() != mCurStencilRef)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+            {
+                const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+                if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
+                    depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
+                    state.getStencilBackRef() != mCurStencilBackRef)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+                if (state.getDepthStencilState().stencilWritemask !=
+                    mCurDepthStencilState.stencilWritemask)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+                if (state.getDepthStencilState().stencilBackWritemask !=
+                    mCurDepthStencilState.stencilBackWritemask)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+            {
+                const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+                if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail ||
+                    depthStencil.stencilPassDepthFail !=
+                        mCurDepthStencilState.stencilPassDepthFail ||
+                    depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+            {
+                const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+                if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
+                    depthStencil.stencilBackPassDepthFail !=
+                        mCurDepthStencilState.stencilBackPassDepthFail ||
+                    depthStencil.stencilBackPassDepthPass !=
+                        mCurDepthStencilState.stencilBackPassDepthPass)
+                {
+                    mDepthStencilStateIsDirty = true;
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
+                if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
+                {
+                    mRasterizerStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_CULL_FACE:
+                if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
+                {
+                    mRasterizerStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_FRONT_FACE:
+                if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
+                {
+                    mRasterizerStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
+                if (state.getRasterizerState().polygonOffsetFill !=
+                    mCurRasterState.polygonOffsetFill)
+                {
+                    mRasterizerStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_POLYGON_OFFSET:
+            {
+                const gl::RasterizerState &rasterState = state.getRasterizerState();
+                if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
+                    rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
+                {
+                    mRasterizerStateIsDirty = true;
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
+                if (state.getRasterizerState().rasterizerDiscard !=
+                    mCurRasterState.rasterizerDiscard)
+                {
+                    mRasterizerStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_SCISSOR:
+                if (state.getScissor() != mCurScissorRect)
+                {
+                    mScissorStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
+                if (state.isScissorTestEnabled() != mCurScissorEnabled)
+                {
+                    mScissorStateIsDirty = true;
+                    // Rasterizer state update needs mCurScissorsEnabled and updates when it changes
+                    mRasterizerStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_RANGE:
+                if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
+                {
+                    mViewportStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_VIEWPORT:
+                if (state.getViewport() != mCurViewport)
+                {
+                    mViewportStateIsDirty = true;
+                }
+                break;
+            case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
+                mRenderTargetIsDirty = true;
+                break;
+            default:
+                if (dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
+                    dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX)
+                {
+                    size_t attribIndex =
+                        static_cast<size_t>(dirtyBit - gl::State::DIRTY_BIT_CURRENT_VALUE_0);
+                    mDirtyCurrentValueAttribs.set(attribIndex);
+                }
+                break;
+        }
+    }
+}
+
+gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
+                                        const gl::BlendState &blendState,
+                                        const gl::ColorF &blendColor,
+                                        unsigned int sampleMask)
+{
+    if (!mBlendStateIsDirty && sampleMask == mCurSampleMask)
+    {
+        return gl::NoError();
+    }
+
+    ID3D11BlendState *dxBlendState = nullptr;
+    const d3d11::BlendStateKey &key = RenderStateCache::GetBlendStateKey(framebuffer, blendState);
+
+    ANGLE_TRY(mRenderer->getStateCache().getBlendState(key, &dxBlendState));
+
+    ASSERT(dxBlendState != nullptr);
+
+    float blendColors[4] = {0.0f};
+    if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
+        blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+        blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
+        blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+    {
+        blendColors[0] = blendColor.red;
+        blendColors[1] = blendColor.green;
+        blendColors[2] = blendColor.blue;
+        blendColors[3] = blendColor.alpha;
+    }
+    else
+    {
+        blendColors[0] = blendColor.alpha;
+        blendColors[1] = blendColor.alpha;
+        blendColors[2] = blendColor.alpha;
+        blendColors[3] = blendColor.alpha;
+    }
+
+    mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState, blendColors, sampleMask);
+
+    mCurBlendState = blendState;
+    mCurBlendColor = blendColor;
+    mCurSampleMask = sampleMask;
+
+    mBlendStateIsDirty = false;
+
+    return gl::NoError();
+}
+
+gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
+{
+    const auto &fbo = *glState.getDrawFramebuffer();
+
+    // Disable the depth test/depth write if we are using a stencil-only attachment.
+    // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
+    // nor write to the unused depth part of this emulated texture.
+    bool disableDepth = (!fbo.hasDepth() && fbo.hasStencil());
+
+    // Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
+    bool disableStencil = (fbo.hasDepth() && !fbo.hasStencil());
+
+    // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState.
+    if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() &&
+        disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() &&
+        disableStencil == mCurDisableStencil.value())
+    {
+        return gl::NoError();
+    }
+
+    mCurDepthStencilState = glState.getDepthStencilState();
+    mCurStencilRef        = glState.getStencilRef();
+    mCurStencilBackRef    = glState.getStencilBackRef();
+    mCurDisableDepth      = disableDepth;
+    mCurDisableStencil    = disableStencil;
+
+    // get the maximum size of the stencil ref
+    unsigned int maxStencil = 0;
+    if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0)
+    {
+        maxStencil = (1 << mCurStencilSize) - 1;
+    }
+    ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) ==
+           (mCurDepthStencilState.stencilBackWritemask & maxStencil));
+    ASSERT(mCurStencilRef == mCurStencilBackRef);
+    ASSERT((mCurDepthStencilState.stencilMask & maxStencil) ==
+           (mCurDepthStencilState.stencilBackMask & maxStencil));
+
+    ID3D11DepthStencilState *dxDepthStencilState = nullptr;
+    gl::DepthStencilState dsStateKey             = glState.getDepthStencilState();
+
+    if (disableDepth)
+    {
+        dsStateKey.depthTest = false;
+        dsStateKey.depthMask = false;
+    }
+
+    if (disableStencil)
+    {
+        dsStateKey.stencilWritemask     = 0;
+        dsStateKey.stencilBackWritemask = 0;
+        dsStateKey.stencilTest          = false;
+    }
+
+    ANGLE_TRY(mRenderer->getStateCache().getDepthStencilState(dsStateKey, &dxDepthStencilState));
+
+    ASSERT(dxDepthStencilState);
+
+    // Max D3D11 stencil reference value is 0xFF,
+    // corresponding to the max 8 bits in a stencil buffer
+    // GL specifies we should clamp the ref value to the
+    // nearest bit depth when doing stencil ops
+    static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF,
+                  "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
+    static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
+                  "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
+    UINT dxStencilRef = std::min<UINT>(mCurStencilRef, 0xFFu);
+
+    mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
+
+    mDepthStencilStateIsDirty = false;
+
+    return gl::NoError();
+}
+
+gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState)
+{
+    // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState.
+    if (!mRasterizerStateIsDirty && rasterState.pointDrawMode == mCurRasterState.pointDrawMode &&
+        rasterState.multiSample == mCurRasterState.multiSample)
+    {
+        return gl::NoError();
+    }
+
+    ID3D11RasterizerState *dxRasterState = nullptr;
+
+    if (mCurPresentPathFastEnabled)
+    {
+        gl::RasterizerState modifiedRasterState = rasterState;
+
+        // If prseent path fast is active then we need invert the front face state.
+        // This ensures that both gl_FrontFacing is correct, and front/back culling
+        // is performed correctly.
+        if (modifiedRasterState.frontFace == GL_CCW)
+        {
+            modifiedRasterState.frontFace = GL_CW;
+        }
+        else
+        {
+            ASSERT(modifiedRasterState.frontFace == GL_CW);
+            modifiedRasterState.frontFace = GL_CCW;
+        }
+
+        ANGLE_TRY(mRenderer->getStateCache().getRasterizerState(
+            modifiedRasterState, mCurScissorEnabled, &dxRasterState));
+    }
+    else
+    {
+        ANGLE_TRY(mRenderer->getStateCache().getRasterizerState(rasterState, mCurScissorEnabled,
+                                                                &dxRasterState));
+    }
+
+    mRenderer->getDeviceContext()->RSSetState(dxRasterState);
+
+    mCurRasterState         = rasterState;
+    mRasterizerStateIsDirty = false;
+
+    return gl::NoError();
+}
+
+void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+{
+    if (!mScissorStateIsDirty)
+        return;
+
+    int modifiedScissorY = scissor.y;
+    if (mCurPresentPathFastEnabled)
+    {
+        modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
+    }
+
+    if (enabled)
+    {
+        D3D11_RECT rect;
+        rect.left   = std::max(0, scissor.x);
+        rect.top    = std::max(0, modifiedScissorY);
+        rect.right  = scissor.x + std::max(0, scissor.width);
+        rect.bottom = modifiedScissorY + std::max(0, scissor.height);
+
+        mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect);
+    }
+
+    mCurScissorRect      = scissor;
+    mCurScissorEnabled   = enabled;
+    mScissorStateIsDirty = false;
+}
+
+void StateManager11::setViewport(const gl::Caps *caps,
+                                 const gl::Rectangle &viewport,
+                                 float zNear,
+                                 float zFar)
+{
+    if (!mViewportStateIsDirty)
+        return;
+
+    float actualZNear = gl::clamp01(zNear);
+    float actualZFar  = gl::clamp01(zFar);
+
+    int dxMaxViewportBoundsX = static_cast<int>(caps->maxViewportWidth);
+    int dxMaxViewportBoundsY = static_cast<int>(caps->maxViewportHeight);
+    int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
+    int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
+
+    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
+        dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
+        dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height);
+        dxMinViewportBoundsX = 0;
+        dxMinViewportBoundsY = 0;
+    }
+
+    int dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
+    int dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
+    int dxViewportWidth    = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
+    int dxViewportHeight   = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
+
+    D3D11_VIEWPORT dxViewport;
+    dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
+
+    if (mCurPresentPathFastEnabled)
+    {
+        // When present path fast is active and we're rendering to framebuffer 0, we must invert
+        // the viewport in Y-axis.
+        // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave
+        // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the
+        // unaltered dxViewportTopLeftY value.
+        dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight -
+                                                 dxViewportTopLeftY - dxViewportHeight);
+    }
+    else
+    {
+        dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
+    }
+
+    dxViewport.Width    = static_cast<float>(dxViewportWidth);
+    dxViewport.Height   = static_cast<float>(dxViewportHeight);
+    dxViewport.MinDepth = actualZNear;
+    dxViewport.MaxDepth = actualZFar;
+
+    mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport);
+
+    mCurViewport = viewport;
+    mCurNear     = actualZNear;
+    mCurFar      = actualZFar;
+
+    // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
+    // using viewAdjust (like the D3D9 renderer).
+    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        mVertexConstants.viewAdjust[0] = static_cast<float>((viewport.width - dxViewportWidth) +
+                                                            2 * (viewport.x - dxViewportTopLeftX)) /
+                                         dxViewport.Width;
+        mVertexConstants.viewAdjust[1] = static_cast<float>((viewport.height - dxViewportHeight) +
+                                                            2 * (viewport.y - dxViewportTopLeftY)) /
+                                         dxViewport.Height;
+        mVertexConstants.viewAdjust[2] = static_cast<float>(viewport.width) / dxViewport.Width;
+        mVertexConstants.viewAdjust[3] = static_cast<float>(viewport.height) / dxViewport.Height;
+    }
+
+    mPixelConstants.viewCoords[0] = viewport.width * 0.5f;
+    mPixelConstants.viewCoords[1] = viewport.height * 0.5f;
+    mPixelConstants.viewCoords[2] = viewport.x + (viewport.width * 0.5f);
+    mPixelConstants.viewCoords[3] = viewport.y + (viewport.height * 0.5f);
+
+    // Instanced pointsprite emulation requires ViewCoords to be defined in the
+    // the vertex shader.
+    mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
+    mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
+    mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
+    mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
+
+    mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
+    mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
+
+    mVertexConstants.depthRange[0] = actualZNear;
+    mVertexConstants.depthRange[1] = actualZFar;
+    mVertexConstants.depthRange[2] = actualZFar - actualZNear;
+
+    mPixelConstants.depthRange[0] = actualZNear;
+    mPixelConstants.depthRange[1] = actualZFar;
+    mPixelConstants.depthRange[2] = actualZFar - actualZNear;
+
+    mPixelConstants.viewScale[0] = 1.0f;
+    mPixelConstants.viewScale[1] = mCurPresentPathFastEnabled ? 1.0f : -1.0f;
+    mPixelConstants.viewScale[2] = 1.0f;
+    mPixelConstants.viewScale[3] = 1.0f;
+
+    mVertexConstants.viewScale[0] = mPixelConstants.viewScale[0];
+    mVertexConstants.viewScale[1] = mPixelConstants.viewScale[1];
+    mVertexConstants.viewScale[2] = mPixelConstants.viewScale[2];
+    mVertexConstants.viewScale[3] = mPixelConstants.viewScale[3];
+
+    mViewportStateIsDirty = false;
+}
+
+void StateManager11::invalidateRenderTarget()
+{
+    mRenderTargetIsDirty = true;
+}
+
+void StateManager11::invalidateBoundViews()
+{
+    mCurVertexSRVs.clear();
+    mCurPixelSRVs.clear();
+
+    invalidateRenderTarget();
+}
+
+void StateManager11::invalidateEverything()
+{
+    mBlendStateIsDirty        = true;
+    mDepthStencilStateIsDirty = true;
+    mRasterizerStateIsDirty   = true;
+    mScissorStateIsDirty      = true;
+    mViewportStateIsDirty     = true;
+
+    // We reset the current SRV data because it might not be in sync with D3D's state
+    // anymore. For example when a currently used SRV is used as an RTV, D3D silently
+    // remove it from its state.
+    invalidateBoundViews();
+}
+
+void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *rtv,
+                                            ID3D11DepthStencilView *dsv)
+{
+    mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv);
+    mRenderTargetIsDirty = true;
+}
+
+void StateManager11::setOneTimeRenderTargets(ID3D11RenderTargetView **rtvs,
+                                             UINT numRtvs,
+                                             ID3D11DepthStencilView *dsv)
+{
+    mRenderer->getDeviceContext()->OMSetRenderTargets(numRtvs, (numRtvs > 0) ? rtvs : nullptr, dsv);
+    mRenderTargetIsDirty = true;
+}
+
+void StateManager11::onBeginQuery(Query11 *query)
+{
+    mCurrentQueries.insert(query);
+}
+
+void StateManager11::onDeleteQueryObject(Query11 *query)
+{
+    mCurrentQueries.erase(query);
+}
+
+gl::Error StateManager11::onMakeCurrent(const gl::ContextState &data)
+{
+    const gl::State &state = data.getState();
+
+    for (Query11 *query : mCurrentQueries)
+    {
+        query->pause();
+    }
+    mCurrentQueries.clear();
+
+    for (GLenum queryType : QueryTypes)
+    {
+        gl::Query *query = state.getActiveQuery(queryType);
+        if (query != nullptr)
+        {
+            Query11 *query11 = GetImplAs<Query11>(query);
+            query11->resume();
+            mCurrentQueries.insert(query11);
+        }
+    }
+
+    return gl::NoError();
+}
+
+void StateManager11::setShaderResource(gl::SamplerType shaderType,
+                                       UINT resourceSlot,
+                                       ID3D11ShaderResourceView *srv)
+{
+    auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+    ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
+    const SRVRecord &record = currentSRVs[resourceSlot];
+
+    if (record.srv != reinterpret_cast<uintptr_t>(srv))
+    {
+        auto deviceContext = mRenderer->getDeviceContext();
+        if (shaderType == gl::SAMPLER_VERTEX)
+        {
+            deviceContext->VSSetShaderResources(resourceSlot, 1, &srv);
+        }
+        else
+        {
+            deviceContext->PSSetShaderResources(resourceSlot, 1, &srv);
+        }
+
+        currentSRVs.update(resourceSlot, srv);
+    }
+}
+
+gl::Error StateManager11::clearTextures(gl::SamplerType samplerType,
+                                        size_t rangeStart,
+                                        size_t rangeEnd)
+{
+    if (rangeStart == rangeEnd)
+    {
+        return gl::NoError();
+    }
+
+    auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+    gl::Range<size_t> clearRange(rangeStart, rangeStart);
+    clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed()));
+
+    if (clearRange.empty())
+    {
+        return gl::NoError();
+    }
+
+    auto deviceContext = mRenderer->getDeviceContext();
+    if (samplerType == gl::SAMPLER_VERTEX)
+    {
+        deviceContext->VSSetShaderResources(static_cast<unsigned int>(rangeStart),
+                                            static_cast<unsigned int>(rangeEnd - rangeStart),
+                                            &mNullSRVs[0]);
+    }
+    else
+    {
+        deviceContext->PSSetShaderResources(static_cast<unsigned int>(rangeStart),
+                                            static_cast<unsigned int>(rangeEnd - rangeStart),
+                                            &mNullSRVs[0]);
+    }
+
+    for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex)
+    {
+        currentSRVs.update(samplerIndex, nullptr);
+    }
+
+    return gl::NoError();
+}
+
+void StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType,
+                                          uintptr_t resource,
+                                          const gl::ImageIndex &index)
+{
+    auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+    for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
+    {
+        auto &record = currentSRVs[resourceIndex];
+
+        if (record.srv && record.resource == resource &&
+            ImageIndexConflictsWithSRV(index, record.desc))
+        {
+            setShaderResource(samplerType, static_cast<UINT>(resourceIndex), nullptr);
+        }
+    }
+}
+
+void StateManager11::unsetConflictingAttachmentResources(
+    const gl::FramebufferAttachment *attachment,
+    ID3D11Resource *resource)
+{
+    // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
+    if (attachment->type() == GL_TEXTURE)
+    {
+        uintptr_t resourcePtr       = reinterpret_cast<uintptr_t>(resource);
+        const gl::ImageIndex &index = attachment->getTextureImageIndex();
+        // The index doesn't need to be corrected for the small compressed texture workaround
+        // because a rendertarget is never compressed.
+        unsetConflictingSRVs(gl::SAMPLER_VERTEX, resourcePtr, index);
+        unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, index);
+    }
+}
+
+void StateManager11::initialize(const gl::Caps &caps)
+{
+    mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits);
+    mCurPixelSRVs.initialize(caps.maxTextureImageUnits);
+
+    // Initialize cached NULL SRV block
+    mNullSRVs.resize(caps.maxTextureImageUnits, nullptr);
+
+    mCurrentValueAttribs.resize(caps.maxVertexAttributes);
+}
+
+void StateManager11::deinitialize()
+{
+    mCurrentValueAttribs.clear();
+}
+
+gl::Error StateManager11::syncFramebuffer(ContextImpl *contextImpl, gl::Framebuffer *framebuffer)
+{
+    Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
+    ANGLE_TRY(framebuffer11->markAttachmentsDirty());
+
+    if (framebuffer11->hasAnyInternalDirtyBit())
+    {
+        ASSERT(framebuffer->id() != 0);
+        framebuffer11->syncInternalState(contextImpl);
+    }
+
+    if (!mRenderTargetIsDirty)
+    {
+        return gl::NoError();
+    }
+
+    mRenderTargetIsDirty = false;
+
+    // Check for zero-sized default framebuffer, which is a special case.
+    // in this case we do not wish to modify any state and just silently return false.
+    // this will not report any gl error but will cause the calling method to return.
+    if (framebuffer->id() == 0)
+    {
+        ASSERT(!framebuffer11->hasAnyInternalDirtyBit());
+        const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize();
+        if (size.width == 0 || size.height == 0)
+        {
+            return gl::NoError();
+        }
+    }
+
+    // Get the color render buffer and serial
+    // Also extract the render target dimensions and view
+    unsigned int renderTargetWidth  = 0;
+    unsigned int renderTargetHeight = 0;
+    RTVArray framebufferRTVs;
+    bool missingColorRenderTarget = true;
+
+    framebufferRTVs.fill(nullptr);
+
+    const auto &colorRTs = framebuffer11->getCachedColorRenderTargets();
+
+    size_t appliedRTIndex  = 0;
+    bool skipInactiveRTs   = mRenderer->getWorkarounds().mrtPerfWorkaround;
+    const auto &drawStates = framebuffer->getDrawBufferStates();
+    UINT maxExistingRT     = 0;
+
+    for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
+    {
+        const RenderTarget11 *renderTarget = colorRTs[rtIndex];
+
+        // Skip inactive rendertargets if the workaround is enabled.
+        if (skipInactiveRTs && (!renderTarget || drawStates[rtIndex] == GL_NONE))
+        {
+            continue;
+        }
+
+        if (renderTarget)
+        {
+            framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get();
+            ASSERT(framebufferRTVs[appliedRTIndex]);
+            maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1;
+
+            if (missingColorRenderTarget)
+            {
+                renderTargetWidth        = renderTarget->getWidth();
+                renderTargetHeight       = renderTarget->getHeight();
+                missingColorRenderTarget = false;
+            }
+        }
+
+        // Unset conflicting texture SRVs
+        const auto *attachment = framebuffer->getColorbuffer(rtIndex);
+        ASSERT(attachment);
+        unsetConflictingAttachmentResources(attachment, renderTarget->getTexture());
+
+        appliedRTIndex++;
+    }
+
+    // Get the depth stencil buffers
+    ID3D11DepthStencilView *framebufferDSV = nullptr;
+    const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget();
+    if (depthStencilRenderTarget)
+    {
+        framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
+        ASSERT(framebufferDSV);
+
+        // If there is no render buffer, the width, height and format values come from
+        // the depth stencil
+        if (missingColorRenderTarget)
+        {
+            renderTargetWidth  = depthStencilRenderTarget->getWidth();
+            renderTargetHeight = depthStencilRenderTarget->getHeight();
+        }
+
+        // Unset conflicting texture SRVs
+        const auto *attachment = framebuffer->getDepthOrStencilbuffer();
+        ASSERT(attachment);
+        unsetConflictingAttachmentResources(attachment, depthStencilRenderTarget->getTexture());
+    }
+
+    // TODO(jmadill): Use context caps?
+    ASSERT(maxExistingRT <= static_cast<UINT>(mRenderer->getNativeCaps().maxDrawBuffers));
+
+    // Apply the render target and depth stencil
+    mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(),
+                                                      framebufferDSV);
+
+    // The D3D11 blend state is heavily dependent on the current render target.
+    mBlendStateIsDirty = true;
+
+    setViewportBounds(renderTargetWidth, renderTargetHeight);
+
+    return gl::NoError();
+}
+
+gl::Error StateManager11::updateCurrentValueAttribs(const gl::State &state,
+                                                    VertexDataManager *vertexDataManager)
+{
+    const auto &activeAttribsMask  = state.getProgram()->getActiveAttribLocationsMask();
+    const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
+    const auto &vertexAttributes   = state.getVertexArray()->getVertexAttributes();
+    const auto &vertexBindings     = state.getVertexArray()->getVertexBindings();
+
+    for (auto attribIndex : dirtyActiveAttribs)
+    {
+        if (vertexAttributes[attribIndex].enabled)
+            continue;
+
+        mDirtyCurrentValueAttribs.reset(attribIndex);
+
+        const auto *attrib                   = &vertexAttributes[attribIndex];
+        const auto &currentValue             = state.getVertexAttribCurrentValue(attribIndex);
+        auto currentValueAttrib              = &mCurrentValueAttribs[attribIndex];
+        currentValueAttrib->currentValueType = currentValue.Type;
+        currentValueAttrib->attribute        = attrib;
+        currentValueAttrib->binding          = &vertexBindings[attrib->bindingIndex];
+
+        ANGLE_TRY(vertexDataManager->storeCurrentValue(currentValue, currentValueAttrib,
+                                                       static_cast<size_t>(attribIndex)));
+    }
+
+    return gl::NoError();
+}
+
+const std::vector<TranslatedAttribute> &StateManager11::getCurrentValueAttribs() const
+{
+    return mCurrentValueAttribs;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
new file mode 100644
index 0000000..83e8dfa
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
@@ -0,0 +1,213 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager11.h: Defines a class for caching D3D11 state
+
+#ifndef LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
+#define LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
+
+#include <array>
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/State.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+struct RenderTargetDesc;
+struct Renderer11DeviceCaps;
+
+struct dx_VertexConstants11
+{
+    float depthRange[4];
+    float viewAdjust[4];
+    float viewCoords[4];
+    float viewScale[4];
+};
+
+struct dx_PixelConstants11
+{
+    float depthRange[4];
+    float viewCoords[4];
+    float depthFront[4];
+    float viewScale[4];
+};
+
+struct dx_ComputeConstants11
+{
+    unsigned int numWorkGroups[3];
+    unsigned int padding;  // This just pads the struct to 16 bytes
+};
+
+class StateManager11 final : angle::NonCopyable
+{
+  public:
+    StateManager11(Renderer11 *renderer);
+    ~StateManager11();
+
+    void initialize(const gl::Caps &caps);
+    void deinitialize();
+    void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
+
+    gl::Error setBlendState(const gl::Framebuffer *framebuffer,
+                            const gl::BlendState &blendState,
+                            const gl::ColorF &blendColor,
+                            unsigned int sampleMask);
+
+    gl::Error setDepthStencilState(const gl::State &glState);
+
+    gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
+
+    void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+
+    void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar);
+
+    void updatePresentPath(bool presentPathFastActive,
+                           const gl::FramebufferAttachment *framebufferAttachment);
+
+    const dx_VertexConstants11 &getVertexConstants() const { return mVertexConstants; }
+    const dx_PixelConstants11 &getPixelConstants() const { return mPixelConstants; }
+    const dx_ComputeConstants11 &getComputeConstants() const { return mComputeConstants; }
+
+    void setComputeConstants(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
+
+    void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
+
+    void setShaderResource(gl::SamplerType shaderType,
+                           UINT resourceSlot,
+                           ID3D11ShaderResourceView *srv);
+    gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd);
+
+    gl::Error syncFramebuffer(ContextImpl *contextImpl, gl::Framebuffer *framebuffer);
+
+    void invalidateRenderTarget();
+    void invalidateBoundViews();
+    void invalidateEverything();
+
+    void setOneTimeRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv);
+    void setOneTimeRenderTargets(ID3D11RenderTargetView **rtvs,
+                                 UINT numRtvs,
+                                 ID3D11DepthStencilView *dsv);
+
+    void onBeginQuery(Query11 *query);
+    void onDeleteQueryObject(Query11 *query);
+    gl::Error onMakeCurrent(const gl::ContextState &data);
+
+    gl::Error updateCurrentValueAttribs(const gl::State &state,
+                                        VertexDataManager *vertexDataManager);
+
+    const std::vector<TranslatedAttribute> &getCurrentValueAttribs() const;
+
+  private:
+    void setViewportBounds(const int width, const int height);
+    void unsetConflictingSRVs(gl::SamplerType shaderType,
+                              uintptr_t resource,
+                              const gl::ImageIndex &index);
+    void unsetConflictingAttachmentResources(const gl::FramebufferAttachment *attachment,
+                                             ID3D11Resource *resource);
+
+    Renderer11 *mRenderer;
+
+    // Blend State
+    bool mBlendStateIsDirty;
+    // TODO(dianx) temporary representation of a dirty bit. once we move enough states in,
+    // try experimenting with dirty bit instead of a bool
+    gl::BlendState mCurBlendState;
+    gl::ColorF mCurBlendColor;
+    unsigned int mCurSampleMask;
+
+    // Currently applied depth stencil state
+    bool mDepthStencilStateIsDirty;
+    gl::DepthStencilState mCurDepthStencilState;
+    int mCurStencilRef;
+    int mCurStencilBackRef;
+    unsigned int mCurStencilSize;
+    Optional<bool> mCurDisableDepth;
+    Optional<bool> mCurDisableStencil;
+
+    // Currently applied rasterizer state
+    bool mRasterizerStateIsDirty;
+    gl::RasterizerState mCurRasterState;
+
+    // Currently applied scissor rectangle state
+    bool mScissorStateIsDirty;
+    bool mCurScissorEnabled;
+    gl::Rectangle mCurScissorRect;
+
+    // Currently applied viewport state
+    bool mViewportStateIsDirty;
+    gl::Rectangle mCurViewport;
+    float mCurNear;
+    float mCurFar;
+
+    // Things needed in viewport state
+    dx_VertexConstants11 mVertexConstants;
+    dx_PixelConstants11 mPixelConstants;
+
+    dx_ComputeConstants11 mComputeConstants;
+
+    // Render target variables
+    gl::Extents mViewportBounds;
+
+    // EGL_ANGLE_experimental_present_path variables
+    bool mCurPresentPathFastEnabled;
+    int mCurPresentPathFastColorBufferHeight;
+
+    // Current RenderTarget state
+    bool mRenderTargetIsDirty;
+
+    // Queries that are currently active in this state
+    std::set<Query11 *> mCurrentQueries;
+
+    // Currently applied textures
+    struct SRVRecord
+    {
+        uintptr_t srv;
+        uintptr_t resource;
+        D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+    };
+
+    // A cache of current SRVs that also tracks the highest 'used' (non-NULL) SRV
+    // We might want to investigate a more robust approach that is also fast when there's
+    // a large gap between used SRVs (e.g. if SRV 0 and 7 are non-NULL, this approach will
+    // waste time on SRVs 1-6.)
+    class SRVCache : angle::NonCopyable
+    {
+      public:
+        SRVCache() : mHighestUsedSRV(0) {}
+
+        void initialize(size_t size) { mCurrentSRVs.resize(size); }
+
+        size_t size() const { return mCurrentSRVs.size(); }
+        size_t highestUsed() const { return mHighestUsedSRV; }
+
+        const SRVRecord &operator[](size_t index) const { return mCurrentSRVs[index]; }
+        void clear();
+        void update(size_t resourceIndex, ID3D11ShaderResourceView *srv);
+
+      private:
+        std::vector<SRVRecord> mCurrentSRVs;
+        size_t mHighestUsedSRV;
+    };
+
+    SRVCache mCurVertexSRVs;
+    SRVCache mCurPixelSRVs;
+
+    // A block of NULL pointers, cached so we don't re-allocate every draw call
+    std::vector<ID3D11ShaderResourceView *> mNullSRVs;
+
+    // Current translations of "Current-Value" data - owned by Context, not VertexArray.
+    gl::AttributesMask mDirtyCurrentValueAttribs;
+    std::vector<TranslatedAttribute> mCurrentValueAttribs;
+};
+
+}  // namespace rx
+#endif  // LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp
new file mode 100644
index 0000000..fbbdf55
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp
@@ -0,0 +1,102 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// StreamProducerNV12.cpp: Implements the stream producer for NV12 textures
+
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
+
+#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+StreamProducerNV12::StreamProducerNV12(Renderer11 *renderer)
+    : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mTextureWidth(0), mTextureHeight(0)
+{
+}
+
+StreamProducerNV12::~StreamProducerNV12()
+{
+    SafeRelease(mTexture);
+}
+
+egl::Error StreamProducerNV12::validateD3DNV12Texture(void *pointer) const
+{
+    ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
+
+    // Check that the texture originated from our device
+    ID3D11Device *device;
+    textureD3D->GetDevice(&device);
+    if (device != mRenderer->getDevice())
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Texture not created on ANGLE D3D device");
+    }
+
+    // Get the description and validate it
+    D3D11_TEXTURE2D_DESC desc;
+    textureD3D->GetDesc(&desc);
+    if (desc.Format != DXGI_FORMAT_NV12)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Texture format not DXGI_FORMAT_NV12");
+    }
+    if (desc.Width < 1 || desc.Height < 1)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Texture is of size 0");
+    }
+    if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Texture dimensions are not even");
+    }
+    return egl::Error(EGL_SUCCESS);
+}
+
+void StreamProducerNV12::postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes)
+{
+    ASSERT(pointer != nullptr);
+    ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
+
+    // Check that the texture originated from our device
+    ID3D11Device *device;
+    textureD3D->GetDevice(&device);
+
+    // Get the description
+    D3D11_TEXTURE2D_DESC desc;
+    textureD3D->GetDesc(&desc);
+
+    // Release the previous texture if there is one
+    SafeRelease(mTexture);
+
+    mTexture = textureD3D;
+    mTexture->AddRef();
+    mTextureWidth  = desc.Width;
+    mTextureHeight = desc.Height;
+    mArraySlice    = static_cast<UINT>(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0));
+}
+
+egl::Stream::GLTextureDescription StreamProducerNV12::getGLFrameDescription(int planeIndex)
+{
+    // The UV plane of NV12 textures has half the width/height of the Y plane
+    egl::Stream::GLTextureDescription desc;
+    desc.width          = (planeIndex == 0) ? mTextureWidth : (mTextureWidth / 2);
+    desc.height         = (planeIndex == 0) ? mTextureHeight : (mTextureHeight / 2);
+    desc.internalFormat = (planeIndex == 0) ? GL_R8 : GL_RG8;
+    desc.mipLevels      = 0;
+    return desc;
+}
+
+ID3D11Texture2D *StreamProducerNV12::getD3DTexture()
+{
+    return mTexture;
+}
+
+UINT StreamProducerNV12::getArraySlice()
+{
+    return mArraySlice;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h
new file mode 100644
index 0000000..304c9df
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// StreamProducerNV12.h: Interface for a NV12 texture stream producer
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
+
+#include "libANGLE/renderer/StreamProducerImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class StreamProducerNV12 : public StreamProducerImpl
+{
+  public:
+    StreamProducerNV12(Renderer11 *renderer);
+    ~StreamProducerNV12() override;
+
+    egl::Error validateD3DNV12Texture(void *pointer) const override;
+    void postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes) override;
+    egl::Stream::GLTextureDescription getGLFrameDescription(int planeIndex) override;
+
+    // Gets a pointer to the internal D3D texture
+    ID3D11Texture2D *getD3DTexture();
+
+    // Gets the slice index for the D3D texture that the frame is in
+    UINT getArraySlice();
+
+  private:
+    Renderer11 *mRenderer;
+
+    ID3D11Texture2D *mTexture;
+    UINT mArraySlice;
+    UINT mTextureWidth;
+    UINT mTextureHeight;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
new file mode 100644
index 0000000..bf43fe0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -0,0 +1,975 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
+
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+
+#include <EGL/eglext.h>
+
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "third_party/trace_event/trace_event.h"
+
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h"
+
+#ifdef ANGLE_ENABLE_KEYEDMUTEX
+#define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
+#else
+#define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED
+#endif
+
+namespace rx
+{
+
+namespace
+{
+// To avoid overflow in QPC to Microseconds calculations, since we multiply
+// by kMicrosecondsPerSecond, then the QPC value should not exceed
+// (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply.
+static constexpr int64_t kQPCOverflowThreshold  = 0x8637BD05AF7;
+static constexpr int64_t kMicrosecondsPerSecond = 1000000;
+
+bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow11 *nativeWindow, EGLint orientation)
+{
+    // We don't need an offscreen texture if either orientation = INVERT_Y,
+    // or present path fast is enabled and we're not rendering onto an offscreen surface.
+    return orientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE &&
+           !(renderer->presentPathFastEnabled() && nativeWindow->getNativeWindow());
+}
+}  // anonymous namespace
+
+SwapChain11::SwapChain11(Renderer11 *renderer,
+                         NativeWindow11 *nativeWindow,
+                         HANDLE shareHandle,
+                         IUnknown *d3dTexture,
+                         GLenum backBufferFormat,
+                         GLenum depthBufferFormat,
+                         EGLint orientation,
+                         EGLint samples)
+    : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat),
+      mRenderer(renderer),
+      mWidth(-1),
+      mHeight(-1),
+      mOrientation(orientation),
+      mAppCreatedShareHandle(mShareHandle != nullptr),
+      mSwapInterval(0),
+      mPassThroughResourcesInit(false),
+      mNativeWindow(nativeWindow),
+      mFirstSwap(true),
+      mSwapChain(nullptr),
+      mSwapChain1(nullptr),
+      mKeyedMutex(nullptr),
+      mBackBufferTexture(nullptr),
+      mBackBufferRTView(),
+      mBackBufferSRView(nullptr),
+      mNeedsOffscreenTexture(NeedsOffscreenTexture(renderer, nativeWindow, orientation)),
+      mOffscreenTexture(nullptr),
+      mOffscreenRTView(),
+      mOffscreenSRView(nullptr),
+      mDepthStencilTexture(nullptr),
+      mDepthStencilDSView(nullptr),
+      mDepthStencilSRView(nullptr),
+      mQuadVB(nullptr),
+      mPassThroughSampler(nullptr),
+      mPassThroughIL(nullptr),
+      mPassThroughVS(nullptr),
+      mPassThroughPS(nullptr),
+      mPassThroughRS(nullptr),
+      mColorRenderTarget(this, renderer, false),
+      mDepthStencilRenderTarget(this, renderer, true),
+      mEGLSamples(samples)
+{
+    // Sanity check that if present path fast is active then we're using the default orientation
+    ASSERT(!mRenderer->presentPathFastEnabled() || orientation == 0);
+
+    // Get the performance counter
+    LARGE_INTEGER counterFreqency = {};
+    BOOL success                  = QueryPerformanceFrequency(&counterFreqency);
+    ASSERT(success);
+
+    mQPCFrequency = counterFreqency.QuadPart;
+}
+
+SwapChain11::~SwapChain11()
+{
+    release();
+}
+
+void SwapChain11::release()
+{
+    SafeRelease(mSwapChain1);
+    SafeRelease(mSwapChain);
+    SafeRelease(mKeyedMutex);
+    SafeRelease(mBackBufferTexture);
+    mBackBufferRTView.reset();
+    SafeRelease(mBackBufferSRView);
+    SafeRelease(mOffscreenTexture);
+    mOffscreenRTView.reset();
+    SafeRelease(mOffscreenSRView);
+    SafeRelease(mDepthStencilTexture);
+    SafeRelease(mDepthStencilDSView);
+    SafeRelease(mDepthStencilSRView);
+    SafeRelease(mQuadVB);
+    SafeRelease(mPassThroughSampler);
+    SafeRelease(mPassThroughIL);
+    SafeRelease(mPassThroughVS);
+    SafeRelease(mPassThroughPS);
+    SafeRelease(mPassThroughRS);
+
+    if (!mAppCreatedShareHandle)
+    {
+        mShareHandle = nullptr;
+    }
+}
+
+void SwapChain11::releaseOffscreenColorBuffer()
+{
+    SafeRelease(mOffscreenTexture);
+    mOffscreenRTView.reset();
+    SafeRelease(mOffscreenSRView);
+}
+
+void SwapChain11::releaseOffscreenDepthBuffer()
+{
+    SafeRelease(mDepthStencilTexture);
+    SafeRelease(mDepthStencilDSView);
+    SafeRelease(mDepthStencilSRView);
+}
+
+EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight)
+{
+    if (mNeedsOffscreenTexture)
+    {
+        EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight);
+        if (result != EGL_SUCCESS)
+        {
+            return result;
+        }
+    }
+
+    EGLint result = resetOffscreenDepthBuffer(backbufferWidth, backbufferHeight);
+    if (result != EGL_SUCCESS)
+    {
+        return result;
+    }
+
+    mWidth  = backbufferWidth;
+    mHeight = backbufferHeight;
+
+    return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight)
+{
+    ASSERT(mNeedsOffscreenTexture);
+
+    TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture");
+    ID3D11Device *device = mRenderer->getDevice();
+
+    ASSERT(device != nullptr);
+
+    // D3D11 does not allow zero size textures
+    ASSERT(backbufferWidth >= 1);
+    ASSERT(backbufferHeight >= 1);
+
+    // Preserve the render target content
+    ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
+    if (previousOffscreenTexture)
+    {
+        previousOffscreenTexture->AddRef();
+    }
+    const int previousWidth = mWidth;
+    const int previousHeight = mHeight;
+
+    releaseOffscreenColorBuffer();
+
+    const d3d11::Format &backbufferFormatInfo =
+        d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+    D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
+
+    // If the app passed in a share handle or D3D texture, open the resource
+    // See EGL_ANGLE_d3d_share_handle_client_buffer and EGL_ANGLE_d3d_texture_client_buffer
+    if (mAppCreatedShareHandle || mD3DTexture != nullptr)
+    {
+        if (mAppCreatedShareHandle)
+        {
+            ID3D11Resource *tempResource11;
+            HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource),
+                                                        (void **)&tempResource11);
+            ASSERT(SUCCEEDED(result));
+
+            mOffscreenTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
+            SafeRelease(tempResource11);
+        }
+        else if (mD3DTexture != nullptr)
+        {
+            mOffscreenTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(mD3DTexture);
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+        ASSERT(mOffscreenTexture != nullptr);
+        mOffscreenTexture->GetDesc(&offscreenTextureDesc);
+    }
+    else
+    {
+        const bool useSharedResource =
+            !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport();
+
+        offscreenTextureDesc.Width = backbufferWidth;
+        offscreenTextureDesc.Height = backbufferHeight;
+        offscreenTextureDesc.Format               = backbufferFormatInfo.texFormat;
+        offscreenTextureDesc.MipLevels = 1;
+        offscreenTextureDesc.ArraySize = 1;
+        offscreenTextureDesc.SampleDesc.Count     = getD3DSamples();
+        offscreenTextureDesc.SampleDesc.Quality = 0;
+        offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
+        offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+        offscreenTextureDesc.CPUAccessFlags = 0;
+        offscreenTextureDesc.MiscFlags = useSharedResource ? ANGLE_RESOURCE_SHARE_TYPE : 0;
+
+        HRESULT result =
+            device->CreateTexture2D(&offscreenTextureDesc, nullptr, &mOffscreenTexture);
+
+        if (FAILED(result))
+        {
+            ERR() << "Could not create offscreen texture, " << gl::FmtHR(result);
+            release();
+
+            if (d3d11::isDeviceLostError(result))
+            {
+                return EGL_CONTEXT_LOST;
+            }
+            else
+            {
+                return EGL_BAD_ALLOC;
+            }
+        }
+
+        d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture");
+
+        // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
+        if (useSharedResource)
+        {
+            IDXGIResource *offscreenTextureResource = nullptr;
+            result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
+
+            // Fall back to no share handle on failure
+            if (FAILED(result))
+            {
+                ERR() << "Could not query offscreen texture resource, " << gl::FmtHR(result);
+            }
+            else
+            {
+                result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
+                SafeRelease(offscreenTextureResource);
+
+                if (FAILED(result))
+                {
+                    mShareHandle = nullptr;
+                    ERR() << "Could not get offscreen texture shared handle, " << gl::FmtHR(result);
+                }
+            }
+        }
+    }
+
+    // This may return null if the original texture was created without a keyed mutex.
+    mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture);
+
+    D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
+    offscreenRTVDesc.Format             = backbufferFormatInfo.rtvFormat;
+    offscreenRTVDesc.ViewDimension =
+        (mEGLSamples <= 1) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
+    offscreenRTVDesc.Texture2D.MipSlice = 0;
+
+    gl::Error err =
+        mRenderer->allocateResource(offscreenRTVDesc, mOffscreenTexture, &mOffscreenRTView);
+    ASSERT(!err.isError());
+    mOffscreenRTView.setDebugName("Offscreen back buffer render target");
+
+    D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
+    offscreenSRVDesc.Format                    = backbufferFormatInfo.srvFormat;
+    offscreenSRVDesc.ViewDimension =
+        (mEGLSamples <= 1) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+    offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
+    offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
+
+    if (offscreenTextureDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
+    {
+        HRESULT result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc,
+                                                          &mOffscreenSRView);
+        ASSERT(SUCCEEDED(result));
+        d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource");
+    }
+
+    if (previousOffscreenTexture != nullptr)
+    {
+        D3D11_BOX sourceBox = {0};
+        sourceBox.left      = 0;
+        sourceBox.right     = std::min(previousWidth, backbufferWidth);
+        sourceBox.top       = std::max(previousHeight - backbufferHeight, 0);
+        sourceBox.bottom    = previousHeight;
+        sourceBox.front     = 0;
+        sourceBox.back      = 1;
+
+        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+        const int yoffset = std::max(backbufferHeight - previousHeight, 0);
+        deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0,
+                                             previousOffscreenTexture, 0, &sourceBox);
+
+        SafeRelease(previousOffscreenTexture);
+
+        if (mSwapChain)
+        {
+            swapRect(0, 0, backbufferWidth, backbufferHeight);
+        }
+    }
+
+    return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight)
+{
+    releaseOffscreenDepthBuffer();
+
+    if (mDepthBufferFormat != GL_NONE)
+    {
+        const d3d11::Format &depthBufferFormatInfo =
+            d3d11::Format::Get(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
+
+        D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
+        depthStencilTextureDesc.Width = backbufferWidth;
+        depthStencilTextureDesc.Height = backbufferHeight;
+        depthStencilTextureDesc.Format             = depthBufferFormatInfo.texFormat;
+        depthStencilTextureDesc.MipLevels = 1;
+        depthStencilTextureDesc.ArraySize = 1;
+        depthStencilTextureDesc.SampleDesc.Count   = getD3DSamples();
+        depthStencilTextureDesc.SampleDesc.Quality = 0;
+        depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT;
+        depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+        if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+        }
+
+        depthStencilTextureDesc.CPUAccessFlags = 0;
+        depthStencilTextureDesc.MiscFlags = 0;
+
+        ID3D11Device *device = mRenderer->getDevice();
+        HRESULT result =
+            device->CreateTexture2D(&depthStencilTextureDesc, nullptr, &mDepthStencilTexture);
+        if (FAILED(result))
+        {
+            ERR() << "Could not create depthstencil surface for new swap chain, "
+                  << gl::FmtHR(result);
+            release();
+
+            if (d3d11::isDeviceLostError(result))
+            {
+                return EGL_CONTEXT_LOST;
+            }
+            else
+            {
+                return EGL_BAD_ALLOC;
+            }
+        }
+        d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture");
+
+        D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc;
+        depthStencilDesc.Format             = depthBufferFormatInfo.dsvFormat;
+        depthStencilDesc.ViewDimension =
+            (mEGLSamples <= 1) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
+        depthStencilDesc.Flags = 0;
+        depthStencilDesc.Texture2D.MipSlice = 0;
+
+        result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView);
+        ASSERT(SUCCEEDED(result));
+        d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view");
+
+        if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc;
+            depthStencilSRVDesc.Format                    = depthBufferFormatInfo.srvFormat;
+            depthStencilSRVDesc.ViewDimension             = (mEGLSamples <= 1)
+                                                    ? D3D11_SRV_DIMENSION_TEXTURE2D
+                                                    : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+            depthStencilSRVDesc.Texture2D.MostDetailedMip = 0;
+            depthStencilSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
+
+            result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView);
+            ASSERT(SUCCEEDED(result));
+            d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource");
+        }
+    }
+
+    return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
+{
+    TRACE_EVENT0("gpu.angle", "SwapChain11::resize");
+    ID3D11Device *device = mRenderer->getDevice();
+
+    if (device == nullptr)
+    {
+        return EGL_BAD_ACCESS;
+    }
+
+    // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
+    if (backbufferWidth < 1 || backbufferHeight < 1)
+    {
+        return EGL_SUCCESS;
+    }
+
+    // Don't resize unnecessarily
+    if (mWidth == backbufferWidth && mHeight == backbufferHeight)
+    {
+        return EGL_SUCCESS;
+    }
+
+    // Can only call resize if we have already created our swap buffer and resources
+    ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView.valid() && mBackBufferSRView);
+
+    SafeRelease(mBackBufferTexture);
+    mBackBufferRTView.reset();
+    SafeRelease(mBackBufferSRView);
+
+    // Resize swap chain
+    DXGI_SWAP_CHAIN_DESC desc;
+    HRESULT result = mSwapChain->GetDesc(&desc);
+    if (FAILED(result))
+    {
+        ERR() << "Error reading swap chain description, " << gl::FmtHR(result);
+        release();
+        return EGL_BAD_ALLOC;
+    }
+
+    result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, getSwapChainNativeFormat(), 0);
+
+    if (FAILED(result))
+    {
+        ERR() << "Error resizing swap chain buffers, " << gl::FmtHR(result);
+        release();
+
+        if (d3d11::isDeviceLostError(result))
+        {
+            return EGL_CONTEXT_LOST;
+        }
+        else
+        {
+            return EGL_BAD_ALLOC;
+        }
+    }
+
+    result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
+    ASSERT(SUCCEEDED(result));
+    if (SUCCEEDED(result))
+    {
+        d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
+
+        gl::Error err = mRenderer->allocateResourceNoDesc(mBackBufferTexture, &mBackBufferRTView);
+        ASSERT(!err.isError());
+        mBackBufferRTView.setDebugName("Back buffer render target");
+
+        result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
+        ASSERT(SUCCEEDED(result));
+        if (SUCCEEDED(result))
+        {
+            d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource");
+        }
+    }
+
+    mFirstSwap = true;
+
+    return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
+}
+
+DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const
+{
+    // Return a render target format for offscreen rendering is supported by IDXGISwapChain.
+    // MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064(v=vs.85).aspx
+    switch (mOffscreenRenderTargetFormat)
+    {
+        case GL_RGBA8:
+        case GL_RGBA4:
+        case GL_RGB5_A1:
+        case GL_RGB8:
+        case GL_RGB565:
+            return DXGI_FORMAT_R8G8B8A8_UNORM;
+
+        case GL_BGRA8_EXT:
+            return DXGI_FORMAT_B8G8R8A8_UNORM;
+
+        case GL_RGB10_A2:
+            return DXGI_FORMAT_R10G10B10A2_UNORM;
+
+        case GL_RGBA16F:
+            return DXGI_FORMAT_R16G16B16A16_FLOAT;
+
+        default:
+            UNREACHABLE();
+            return DXGI_FORMAT_UNKNOWN;
+    }
+}
+
+EGLint SwapChain11::reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval)
+{
+    mSwapInterval = static_cast<unsigned int>(swapInterval);
+    if (mSwapInterval > 4)
+    {
+        // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4]
+        // range
+        return EGL_BAD_PARAMETER;
+    }
+
+    // If the swap chain already exists, just resize
+    if (mSwapChain != nullptr)
+    {
+        return resize(backbufferWidth, backbufferHeight);
+    }
+
+    TRACE_EVENT0("gpu.angle", "SwapChain11::reset");
+    ID3D11Device *device = mRenderer->getDevice();
+
+    if (device == nullptr)
+    {
+        return EGL_BAD_ACCESS;
+    }
+
+    // Release specific resources to free up memory for the new render target, while the
+    // old render target still exists for the purpose of preserving its contents.
+    SafeRelease(mSwapChain1);
+    SafeRelease(mSwapChain);
+    SafeRelease(mBackBufferTexture);
+    mBackBufferRTView.reset();
+
+    // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
+    if (backbufferWidth < 1 || backbufferHeight < 1)
+    {
+        releaseOffscreenColorBuffer();
+        return EGL_SUCCESS;
+    }
+
+    if (mNativeWindow->getNativeWindow())
+    {
+        HRESULT result = mNativeWindow->createSwapChain(
+            device, mRenderer->getDxgiFactory(), getSwapChainNativeFormat(), backbufferWidth,
+            backbufferHeight, getD3DSamples(), &mSwapChain);
+
+        if (FAILED(result))
+        {
+            ERR() << "Could not create additional swap chains or offscreen surfaces, "
+                  << gl::FmtHR(result);
+            release();
+
+            if (d3d11::isDeviceLostError(result))
+            {
+                return EGL_CONTEXT_LOST;
+            }
+            else
+            {
+                return EGL_BAD_ALLOC;
+            }
+        }
+
+        if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2)
+        {
+            mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain);
+        }
+
+        result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
+        ASSERT(SUCCEEDED(result));
+        d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
+
+        gl::Error err = mRenderer->allocateResourceNoDesc(mBackBufferTexture, &mBackBufferRTView);
+        ASSERT(!err.isError());
+        mBackBufferRTView.setDebugName("Back buffer render target");
+
+        result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
+        ASSERT(SUCCEEDED(result));
+        d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view");
+    }
+
+    mFirstSwap = true;
+
+    return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
+}
+
+void SwapChain11::initPassThroughResources()
+{
+    if (mPassThroughResourcesInit)
+    {
+        return;
+    }
+
+    TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources");
+    ID3D11Device *device = mRenderer->getDevice();
+
+    ASSERT(device != nullptr);
+
+    // Make sure our resources are all not allocated, when we create
+    ASSERT(mQuadVB == nullptr && mPassThroughSampler == nullptr);
+    ASSERT(mPassThroughIL == nullptr && mPassThroughVS == nullptr && mPassThroughPS == nullptr);
+
+    D3D11_BUFFER_DESC vbDesc;
+    vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
+    vbDesc.Usage = D3D11_USAGE_DYNAMIC;
+    vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+    vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+    vbDesc.MiscFlags = 0;
+    vbDesc.StructureByteStride = 0;
+
+    HRESULT result = device->CreateBuffer(&vbDesc, nullptr, &mQuadVB);
+    ASSERT(SUCCEEDED(result));
+    d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
+
+    D3D11_SAMPLER_DESC samplerDesc;
+    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
+    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+    samplerDesc.MipLODBias = 0.0f;
+    samplerDesc.MaxAnisotropy = 0;
+    samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+    samplerDesc.BorderColor[0] = 0.0f;
+    samplerDesc.BorderColor[1] = 0.0f;
+    samplerDesc.BorderColor[2] = 0.0f;
+    samplerDesc.BorderColor[3] = 0.0f;
+    samplerDesc.MinLOD = 0;
+    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
+
+    result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
+    ASSERT(SUCCEEDED(result));
+    d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
+
+    D3D11_INPUT_ELEMENT_DESC quadLayout[] =
+    {
+        { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+    };
+
+    result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL);
+    ASSERT(SUCCEEDED(result));
+    d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
+
+    result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), nullptr,
+                                        &mPassThroughVS);
+    ASSERT(SUCCEEDED(result));
+    d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
+
+    if (mEGLSamples <= 1)
+    {
+        result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D),
+                                           nullptr, &mPassThroughPS);
+    }
+    else
+    {
+        result = device->CreatePixelShader(
+            g_PS_PassthroughRGBA2DMS, sizeof(g_PS_PassthroughRGBA2DMS), nullptr, &mPassThroughPS);
+    }
+
+    ASSERT(SUCCEEDED(result));
+    d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
+
+    // Use the default rasterizer state but without culling
+    D3D11_RASTERIZER_DESC rasterizerDesc;
+    rasterizerDesc.FillMode              = D3D11_FILL_SOLID;
+    rasterizerDesc.CullMode              = D3D11_CULL_NONE;
+    rasterizerDesc.FrontCounterClockwise = FALSE;
+    rasterizerDesc.DepthBias             = 0;
+    rasterizerDesc.SlopeScaledDepthBias  = 0.0f;
+    rasterizerDesc.DepthBiasClamp        = 0.0f;
+    rasterizerDesc.DepthClipEnable       = TRUE;
+    rasterizerDesc.ScissorEnable         = FALSE;
+    rasterizerDesc.MultisampleEnable     = FALSE;
+    rasterizerDesc.AntialiasedLineEnable = FALSE;
+    result = device->CreateRasterizerState(&rasterizerDesc, &mPassThroughRS);
+    ASSERT(SUCCEEDED(result));
+    d3d11::SetDebugName(mPassThroughRS, "Swap chain pass through rasterizer state");
+
+    mPassThroughResourcesInit = true;
+}
+
+// parameters should be validated/clamped by caller
+EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    if (mNeedsOffscreenTexture)
+    {
+        EGLint result = copyOffscreenToBackbuffer(x, y, width, height);
+        if (result != EGL_SUCCESS)
+        {
+            return result;
+        }
+    }
+
+    EGLint result = present(x, y, width, height);
+    if (result != EGL_SUCCESS)
+    {
+        return result;
+    }
+
+    mRenderer->onSwap();
+
+    return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    if (!mSwapChain)
+    {
+        return EGL_SUCCESS;
+    }
+
+    initPassThroughResources();
+
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    // Set vertices
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return EGL_BAD_ACCESS;
+    }
+
+    d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
+
+    // Create a quad in homogeneous coordinates
+    float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
+    float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
+    float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
+    float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
+
+    float u1 = x / float(mWidth);
+    float v1 = y / float(mHeight);
+    float u2 = (x + width) / float(mWidth);
+    float v2 = (y + height) / float(mHeight);
+
+    // Invert the quad vertices depending on the surface orientation.
+    if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0)
+    {
+        std::swap(x1, x2);
+    }
+    if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0)
+    {
+        std::swap(y1, y2);
+    }
+
+    d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
+    d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
+    d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
+    d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
+
+    deviceContext->Unmap(mQuadVB, 0);
+
+    static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
+    static UINT startIdx = 0;
+    deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
+
+    // Apply state
+    deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
+
+    static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+    deviceContext->OMSetBlendState(nullptr, blendFactor, 0xFFFFFFF);
+
+    deviceContext->RSSetState(mPassThroughRS);
+
+    // Apply shaders
+    deviceContext->IASetInputLayout(mPassThroughIL);
+    deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+    deviceContext->VSSetShader(mPassThroughVS, nullptr, 0);
+    deviceContext->PSSetShader(mPassThroughPS, nullptr, 0);
+    deviceContext->GSSetShader(nullptr, nullptr, 0);
+
+    auto stateManager = mRenderer->getStateManager();
+
+    // Apply render targets
+    stateManager->setOneTimeRenderTarget(mBackBufferRTView.get(), nullptr);
+
+    // Set the viewport
+    D3D11_VIEWPORT viewport;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    viewport.Width = static_cast<FLOAT>(mWidth);
+    viewport.Height = static_cast<FLOAT>(mHeight);
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 1.0f;
+    deviceContext->RSSetViewports(1, &viewport);
+
+    // Apply textures
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView);
+    deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
+
+    // Draw
+    deviceContext->Draw(4, 0);
+
+    // Rendering to the swapchain is now complete. Now we can call Present().
+    // Before that, we perform any cleanup on the D3D device. We do this before Present() to make sure the
+    // cleanup is caught under the current eglSwapBuffers() PIX/Graphics Diagnostics call rather than the next one.
+    stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+    mRenderer->markAllStateDirty();
+
+    return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    if (!mSwapChain)
+    {
+        return EGL_SUCCESS;
+    }
+
+    UINT swapInterval = mSwapInterval;
+#if ANGLE_VSYNC == ANGLE_DISABLED
+    swapInterval = 0;
+#endif
+
+    HRESULT result = S_OK;
+
+    // Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available.
+    // Dirty rect present is not supported with a multisampled swapchain.
+    if (mSwapChain1 != nullptr && mEGLSamples <= 1)
+    {
+        if (mFirstSwap)
+        {
+            // Can't swap with a dirty rect if this swap chain has never swapped before
+            DXGI_PRESENT_PARAMETERS params = {0, nullptr, nullptr, nullptr};
+            result                         = mSwapChain1->Present1(swapInterval, 0, &params);
+        }
+        else
+        {
+            RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
+                         static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)};
+            DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr};
+            result                         = mSwapChain1->Present1(swapInterval, 0, &params);
+        }
+    }
+    else
+    {
+        result = mSwapChain->Present(swapInterval, 0);
+    }
+
+    mFirstSwap = false;
+
+    // Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render
+    // target.  Mark it dirty.
+    mRenderer->getStateManager()->invalidateRenderTarget();
+
+    if (result == DXGI_ERROR_DEVICE_REMOVED)
+    {
+        ERR() << "Present failed: the D3D11 device was removed, "
+              << gl::FmtHR(mRenderer->getDevice()->GetDeviceRemovedReason());
+        return EGL_CONTEXT_LOST;
+    }
+    else if (result == DXGI_ERROR_DEVICE_RESET)
+    {
+        ERR() << "Present failed: the D3D11 device was reset from a bad command.";
+        return EGL_CONTEXT_LOST;
+    }
+    else if (FAILED(result))
+    {
+        ERR() << "Present failed with " << gl::FmtHR(result);
+    }
+
+    mNativeWindow->commitChange();
+
+    return EGL_SUCCESS;
+}
+
+ID3D11Texture2D *SwapChain11::getOffscreenTexture()
+{
+    return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture;
+}
+
+const d3d11::RenderTargetView &SwapChain11::getRenderTarget()
+{
+    return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView;
+}
+
+ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
+{
+    return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView;
+}
+
+ID3D11DepthStencilView *SwapChain11::getDepthStencil()
+{
+    return mDepthStencilDSView;
+}
+
+ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource()
+{
+    return mDepthStencilSRView;
+}
+
+ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
+{
+    return mDepthStencilTexture;
+}
+
+void SwapChain11::recreate()
+{
+    // possibly should use this method instead of reset
+}
+
+egl::Error SwapChain11::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+    if (!mSwapChain)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Swap chain uninitialized");
+    }
+
+    DXGI_FRAME_STATISTICS stats = {};
+    HRESULT result              = mSwapChain->GetFrameStatistics(&stats);
+
+    if (FAILED(result))
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to get frame statistics, result: 0x%X", result);
+    }
+
+    // Conversion from DXGI_FRAME_STATISTICS to the output values:
+    // stats.SyncRefreshCount -> msc
+    // stats.PresentCount -> sbc
+    // stats.SyncQPCTime -> ust with conversion to microseconds via QueryPerformanceFrequency
+    *msc = stats.SyncRefreshCount;
+    *sbc = stats.PresentCount;
+
+    LONGLONG syncQPCValue = stats.SyncQPCTime.QuadPart;
+    // If the QPC Value is below the overflow threshold, we proceed with
+    // simple multiply and divide.
+    if (syncQPCValue < kQPCOverflowThreshold)
+    {
+        *ust = syncQPCValue * kMicrosecondsPerSecond / mQPCFrequency;
+    }
+    else
+    {
+        // Otherwise, calculate microseconds in a round about manner to avoid
+        // overflow and precision issues.
+        int64_t wholeSeconds  = syncQPCValue / mQPCFrequency;
+        int64_t leftoverTicks = syncQPCValue - (wholeSeconds * mQPCFrequency);
+        *ust                  = wholeSeconds * kMicrosecondsPerSecond +
+               leftoverTicks * kMicrosecondsPerSecond / mQPCFrequency;
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+UINT SwapChain11::getD3DSamples() const
+{
+    return (mEGLSamples == 0) ? 1 : mEGLSamples;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
new file mode 100644
index 0000000..59fa41a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+
+namespace rx
+{
+class Renderer11;
+class NativeWindow11;
+
+class SwapChain11 final : public SwapChainD3D
+{
+  public:
+    SwapChain11(Renderer11 *renderer,
+                NativeWindow11 *nativeWindow,
+                HANDLE shareHandle,
+                IUnknown *d3dTexture,
+                GLenum backBufferFormat,
+                GLenum depthBufferFormat,
+                EGLint orientation,
+                EGLint samples);
+    virtual ~SwapChain11();
+
+    EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
+    EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) override;
+    EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    void recreate() override;
+
+    RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; }
+    RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; }
+
+    ID3D11Texture2D *getOffscreenTexture();
+    const d3d11::RenderTargetView &getRenderTarget();
+    ID3D11ShaderResourceView *getRenderTargetShaderResource();
+
+    ID3D11Texture2D *getDepthStencilTexture();
+    ID3D11DepthStencilView *getDepthStencil();
+    ID3D11ShaderResourceView *getDepthStencilShaderResource();
+
+    EGLint getWidth() const { return mWidth; }
+    EGLint getHeight() const { return mHeight; }
+    void *getKeyedMutex() override { return mKeyedMutex; }
+    EGLint getSamples() const { return mEGLSamples; }
+
+    egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+
+  private:
+    void release();
+    void initPassThroughResources();
+
+    void releaseOffscreenColorBuffer();
+    void releaseOffscreenDepthBuffer();
+    EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight);
+    EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight);
+    EGLint resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight);
+
+    DXGI_FORMAT getSwapChainNativeFormat() const;
+
+    EGLint copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+    EGLint present(EGLint x, EGLint y, EGLint width, EGLint height);
+    UINT getD3DSamples() const;
+
+    Renderer11 *mRenderer;
+    EGLint mWidth;
+    EGLint mHeight;
+    const EGLint mOrientation;
+    bool mAppCreatedShareHandle;
+    unsigned int mSwapInterval;
+    bool mPassThroughResourcesInit;
+
+    NativeWindow11 *mNativeWindow;  // Handler for the Window that the surface is created for.
+
+    bool mFirstSwap;
+    IDXGISwapChain *mSwapChain;
+    IDXGISwapChain1 *mSwapChain1;
+    IDXGIKeyedMutex *mKeyedMutex;
+
+    ID3D11Texture2D *mBackBufferTexture;
+    d3d11::RenderTargetView mBackBufferRTView;
+    ID3D11ShaderResourceView *mBackBufferSRView;
+
+    const bool mNeedsOffscreenTexture;
+    ID3D11Texture2D *mOffscreenTexture;
+    d3d11::RenderTargetView mOffscreenRTView;
+    ID3D11ShaderResourceView *mOffscreenSRView;
+
+    ID3D11Texture2D *mDepthStencilTexture;
+    ID3D11DepthStencilView *mDepthStencilDSView;
+    ID3D11ShaderResourceView *mDepthStencilSRView;
+
+    ID3D11Buffer *mQuadVB;
+    ID3D11SamplerState *mPassThroughSampler;
+    ID3D11InputLayout *mPassThroughIL;
+    ID3D11VertexShader *mPassThroughVS;
+    ID3D11PixelShader *mPassThroughPS;
+    ID3D11RasterizerState *mPassThroughRS;
+
+    SurfaceRenderTarget11 mColorRenderTarget;
+    SurfaceRenderTarget11 mDepthStencilRenderTarget;
+
+    EGLint mEGLSamples;
+    LONGLONG mQPCFrequency;
+};
+
+}  // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
new file mode 100644
index 0000000..df04525
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -0,0 +1,3164 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
+// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11
+// texture.
+
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+
+#include <tuple>
+
+#include "common/MemoryBuffer.h"
+#include "common/utilities.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+
+namespace rx
+{
+
+TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil)
+    : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil)
+{
+}
+
+bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const
+{
+    return std::tie(baseLevel, mipLevels, swizzle, dropStencil) <
+           std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil);
+}
+
+TextureStorage11::TextureStorage11(Renderer11 *renderer,
+                                   UINT bindFlags,
+                                   UINT miscFlags,
+                                   GLenum internalFormat)
+    : mRenderer(renderer),
+      mTopLevel(0),
+      mMipLevels(0),
+      mFormatInfo(d3d11::Format::Get(internalFormat, mRenderer->getRenderer11DeviceCaps())),
+      mTextureWidth(0),
+      mTextureHeight(0),
+      mTextureDepth(0),
+      mDropStencilTexture(nullptr),
+      mBindFlags(bindFlags),
+      mMiscFlags(miscFlags)
+{
+    mLevelSRVs.fill(nullptr);
+    mLevelBlitSRVs.fill(nullptr);
+}
+
+TextureStorage11::~TextureStorage11()
+{
+    for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        SafeRelease(mLevelSRVs[level]);
+        SafeRelease(mLevelBlitSRVs[level]);
+    }
+
+    for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++)
+    {
+        SafeRelease(i->second);
+    }
+    mSrvCache.clear();
+    SafeRelease(mDropStencilTexture);
+}
+
+DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat,
+                                            const Renderer11DeviceCaps &renderer11DeviceCaps,
+                                            bool renderTarget)
+{
+    UINT bindFlags = 0;
+
+    const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+    if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+    {
+        bindFlags |= D3D11_BIND_SHADER_RESOURCE;
+    }
+    if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
+    {
+        bindFlags |= D3D11_BIND_DEPTH_STENCIL;
+    }
+    if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget)
+    {
+        bindFlags |= D3D11_BIND_RENDER_TARGET;
+    }
+
+    return bindFlags;
+}
+
+DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat,
+                                            const Renderer11DeviceCaps &renderer11DeviceCaps,
+                                            bool renderTarget,
+                                            int levels)
+{
+    UINT miscFlags = 0;
+
+    const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+    if (renderTarget && levels > 1)
+    {
+        if (d3d11::SupportsMipGen(formatInfo.texFormat, renderer11DeviceCaps.featureLevel))
+        {
+            miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
+        }
+    }
+
+    return miscFlags;
+}
+
+UINT TextureStorage11::getBindFlags() const
+{
+    return mBindFlags;
+}
+
+UINT TextureStorage11::getMiscFlags() const
+{
+    return mMiscFlags;
+}
+
+int TextureStorage11::getTopLevel() const
+{
+    // Applying top level is meant to be encapsulated inside TextureStorage11.
+    UNREACHABLE();
+    return mTopLevel;
+}
+
+bool TextureStorage11::isRenderTarget() const
+{
+    return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
+}
+
+bool TextureStorage11::isManaged() const
+{
+    return false;
+}
+
+bool TextureStorage11::supportsNativeMipmapFunction() const
+{
+    return (mMiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) != 0;
+}
+
+int TextureStorage11::getLevelCount() const
+{
+    return mMipLevels - mTopLevel;
+}
+
+int TextureStorage11::getLevelWidth(int mipLevel) const
+{
+    return std::max(static_cast<int>(mTextureWidth) >> mipLevel, 1);
+}
+
+int TextureStorage11::getLevelHeight(int mipLevel) const
+{
+    return std::max(static_cast<int>(mTextureHeight) >> mipLevel, 1);
+}
+
+int TextureStorage11::getLevelDepth(int mipLevel) const
+{
+    return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1);
+}
+
+UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const
+{
+    UINT mipSlice    = static_cast<UINT>(index.mipIndex + mTopLevel);
+    UINT arraySlice  = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+    UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
+    ASSERT(subresource != std::numeric_limits<UINT>::max());
+    return subresource;
+}
+
+gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState,
+                                   ID3D11ShaderResourceView **outSRV)
+{
+    // Make sure to add the level offset for our tiny compressed texture workaround
+    const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel();
+    bool swizzleRequired            = textureState.swizzleRequired();
+    bool mipmapping                 = gl::IsMipmapFiltered(textureState.getSamplerState());
+    unsigned int mipLevels =
+        mipmapping ? (textureState.getEffectiveMaxLevel() - effectiveBaseLevel + 1) : 1;
+
+    // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
+    // which corresponds to GL level 0)
+    mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - effectiveBaseLevel);
+
+    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        ASSERT(!swizzleRequired);
+        ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
+    }
+
+    if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        // We must ensure that the level zero texture is in sync with mipped texture.
+        ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1));
+    }
+
+    if (swizzleRequired)
+    {
+        verifySwizzleExists(textureState.getSwizzleState());
+    }
+
+    // We drop the stencil when sampling from the SRV if three conditions hold:
+    // 1. the drop stencil workaround is enabled.
+    bool workaround = mRenderer->getWorkarounds().emulateTinyStencilTextures;
+    // 2. this is a stencil texture.
+    bool hasStencil = (mFormatInfo.format().stencilBits > 0);
+    // 3. the texture has a 1x1 or 2x2 mip.
+    int effectiveTopLevel = effectiveBaseLevel + mipLevels - 1;
+    bool hasSmallMips =
+        (getLevelWidth(effectiveTopLevel) <= 2 || getLevelHeight(effectiveTopLevel) <= 2);
+
+    bool useDropStencil = (workaround && hasStencil && hasSmallMips);
+    SRVKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil);
+    if (useDropStencil)
+    {
+        // Ensure drop texture gets created.
+        DropStencil result = DropStencil::CREATED;
+        ANGLE_TRY_RESULT(ensureDropStencilTexture(), result);
+
+        // Clear the SRV cache if necessary.
+        // TODO(jmadill): Re-use find query result.
+        auto srvEntry = mSrvCache.find(key);
+        if (result == DropStencil::CREATED && srvEntry != mSrvCache.end())
+        {
+            SafeRelease(srvEntry->second);
+            mSrvCache.erase(key);
+        }
+    }
+
+    ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11::getCachedOrCreateSRV(const SRVKey &key,
+                                                 ID3D11ShaderResourceView **outSRV)
+{
+    auto iter = mSrvCache.find(key);
+    if (iter != mSrvCache.end())
+    {
+        *outSRV = iter->second;
+        return gl::NoError();
+    }
+
+    ID3D11Resource *texture = nullptr;
+    DXGI_FORMAT format      = DXGI_FORMAT_UNKNOWN;
+
+    if (key.swizzle)
+    {
+        const auto &swizzleFormat =
+            mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
+        ASSERT(!key.dropStencil || swizzleFormat.format().stencilBits == 0);
+        ANGLE_TRY(getSwizzleTexture(&texture));
+        format = swizzleFormat.srvFormat;
+    }
+    else if (key.dropStencil)
+    {
+        ASSERT(mDropStencilTexture);
+        texture = mDropStencilTexture;
+        format  = DXGI_FORMAT_R32_FLOAT;
+    }
+    else
+    {
+        ANGLE_TRY(getResource(&texture));
+        format = mFormatInfo.srvFormat;
+    }
+
+    ID3D11ShaderResourceView *srv = nullptr;
+
+    ANGLE_TRY(createSRV(key.baseLevel, key.mipLevels, format, texture, &srv));
+
+    mSrvCache.insert(std::make_pair(key, srv));
+    *outSRV = srv;
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11::getSRVLevel(int mipLevel,
+                                        bool blitSRV,
+                                        ID3D11ShaderResourceView **outSRV)
+{
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+    auto &levelSRVs      = (blitSRV) ? mLevelBlitSRVs : mLevelSRVs;
+    auto &otherLevelSRVs = (blitSRV) ? mLevelSRVs : mLevelBlitSRVs;
+
+    if (!levelSRVs[mipLevel])
+    {
+        // Only create a different SRV for blit if blit format is different from regular srv format
+        if (otherLevelSRVs[mipLevel] && mFormatInfo.srvFormat == mFormatInfo.blitSRVFormat)
+        {
+            levelSRVs[mipLevel] = otherLevelSRVs[mipLevel];
+            levelSRVs[mipLevel]->AddRef();
+        }
+        else
+        {
+            ID3D11Resource *resource = nullptr;
+            ANGLE_TRY(getResource(&resource));
+
+            DXGI_FORMAT resourceFormat =
+                blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat;
+            ANGLE_TRY(createSRV(mipLevel, 1, resourceFormat, resource, &levelSRVs[mipLevel]));
+        }
+    }
+
+    *outSRV = levelSRVs[mipLevel];
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11::getSRVLevels(GLint baseLevel,
+                                         GLint maxLevel,
+                                         ID3D11ShaderResourceView **outSRV)
+{
+    unsigned int mipLevels = maxLevel - baseLevel + 1;
+
+    // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
+    // which corresponds to GL level 0)
+    mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - baseLevel);
+
+    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
+    }
+
+    if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        // We must ensure that the level zero texture is in sync with mipped texture.
+        ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1));
+    }
+
+    // TODO(jmadill): Assert we don't need to drop stencil.
+
+    SRVKey key(baseLevel, mipLevels, false, false);
+    ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
+
+    return gl::NoError();
+}
+
+const d3d11::Format &TextureStorage11::getFormatSet() const
+{
+    return mFormatInfo;
+}
+
+gl::Error TextureStorage11::generateSwizzles(const gl::SwizzleState &swizzleTarget)
+{
+    for (int level = 0; level < getLevelCount(); level++)
+    {
+        // Check if the swizzle for this level is out of date
+        if (mSwizzleCache[level] != swizzleTarget)
+        {
+            // Need to re-render the swizzle for this level
+            ID3D11ShaderResourceView *sourceSRV = nullptr;
+            ANGLE_TRY(getSRVLevel(level, true, &sourceSRV));
+
+            const d3d11::RenderTargetView *destRTV;
+            ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV));
+
+            gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
+
+            Blit11 *blitter = mRenderer->getBlitter();
+
+            ANGLE_TRY(blitter->swizzleTexture(sourceSRV, *destRTV, size, swizzleTarget));
+
+            mSwizzleCache[level] = swizzleTarget;
+        }
+    }
+
+    return gl::NoError();
+}
+
+void TextureStorage11::markLevelDirty(int mipLevel)
+{
+    if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache))
+    {
+        // The default constructor of SwizzleState has GL_INVALID_INDEX for all channels which is
+        // not a valid swizzle combination
+        mSwizzleCache[mipLevel] = gl::SwizzleState();
+    }
+
+    SafeRelease(mDropStencilTexture);
+}
+
+void TextureStorage11::markDirty()
+{
+    for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++)
+    {
+        markLevelDirty(mipLevel);
+    }
+}
+
+gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture,
+                                                   unsigned int sourceSubresource,
+                                                   const gl::ImageIndex &index,
+                                                   const gl::Box &copyArea)
+{
+    ASSERT(srcTexture);
+
+    const GLint level = index.mipIndex;
+
+    markLevelDirty(level);
+
+    gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
+
+    bool fullCopy = copyArea.x == 0 && copyArea.y == 0 && copyArea.z == 0 &&
+                    copyArea.width == texSize.width && copyArea.height == texSize.height &&
+                    copyArea.depth == texSize.depth;
+
+    ID3D11Resource *dstTexture = nullptr;
+
+    // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
+    // should update the mipmapped texture, even if mapmaps are currently disabled.
+    if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        ANGLE_TRY(getMippedResource(&dstTexture));
+    }
+    else
+    {
+        ANGLE_TRY(getResource(&dstTexture));
+    }
+
+    unsigned int dstSubresource = getSubresourceIndex(index);
+
+    ASSERT(dstTexture);
+
+    const d3d11::DXGIFormatSize &dxgiFormatSizeInfo =
+        d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat);
+    if (!fullCopy && mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
+    {
+        // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
+        Blit11 *blitter        = mRenderer->getBlitter();
+        TextureHelper11 source = TextureHelper11::MakeAndReference(srcTexture, getFormatSet());
+        TextureHelper11 dest   = TextureHelper11::MakeAndReference(dstTexture, getFormatSet());
+        return blitter->copyDepthStencil(source, sourceSubresource, copyArea, texSize, dest,
+                                         dstSubresource, copyArea, texSize, nullptr);
+    }
+
+    D3D11_BOX srcBox;
+    srcBox.left = copyArea.x;
+    srcBox.top  = copyArea.y;
+    srcBox.right =
+        copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatSizeInfo.blockWidth);
+    srcBox.bottom =
+        copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatSizeInfo.blockHeight);
+    srcBox.front = copyArea.z;
+    srcBox.back  = copyArea.z + copyArea.depth;
+
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+    context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z,
+                                   srcTexture, sourceSubresource, fullCopy ? nullptr : &srcBox);
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource *dstTexture,
+                                                 unsigned int dstSubresource,
+                                                 const gl::ImageIndex &index,
+                                                 const gl::Box &region)
+{
+    ASSERT(dstTexture);
+
+    ID3D11Resource *srcTexture = nullptr;
+
+    // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
+    // should update the mipmapped texture, even if mapmaps are currently disabled.
+    if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        ANGLE_TRY(getMippedResource(&srcTexture));
+    }
+    else
+    {
+        ANGLE_TRY(getResource(&srcTexture));
+    }
+
+    ASSERT(srcTexture);
+
+    unsigned int srcSubresource = getSubresourceIndex(index);
+
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+    // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox
+    // should be nullptr.
+    D3D11_BOX srcBox;
+    D3D11_BOX *pSrcBox = nullptr;
+    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless the
+        // source box is specified. This is okay, since we don't perform CopySubresourceRegion on
+        // depth/stencil textures on 9_3.
+        ASSERT(mFormatInfo.dsvFormat == DXGI_FORMAT_UNKNOWN);
+        srcBox.left   = region.x;
+        srcBox.right  = region.x + region.width;
+        srcBox.top    = region.y;
+        srcBox.bottom = region.y + region.height;
+        srcBox.front  = region.z;
+        srcBox.back   = region.z + region.depth;
+        pSrcBox       = &srcBox;
+    }
+
+    context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z,
+                                   srcTexture, srcSubresource, pSrcBox);
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex,
+                                           const gl::ImageIndex &destIndex)
+{
+    ASSERT(sourceIndex.layerIndex == destIndex.layerIndex);
+
+    markLevelDirty(destIndex.mipIndex);
+
+    RenderTargetD3D *source = nullptr;
+    ANGLE_TRY(getRenderTarget(sourceIndex, &source));
+
+    RenderTargetD3D *dest = nullptr;
+    ANGLE_TRY(getRenderTarget(destIndex, &dest));
+
+    auto rt11                              = GetAs<RenderTarget11>(source);
+    ID3D11ShaderResourceView *sourceSRV    = rt11->getBlitShaderResourceView();
+    const d3d11::RenderTargetView &destRTV = rt11->getRenderTargetView();
+
+    gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
+    gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth());
+
+    gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth());
+    gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
+
+    Blit11 *blitter = mRenderer->getBlitter();
+    return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize,
+                                nullptr, gl::GetUnsizedFormat(source->getInternalFormat()),
+                                GL_LINEAR, false, false, false);
+}
+
+void TextureStorage11::verifySwizzleExists(const gl::SwizzleState &swizzleState)
+{
+    for (unsigned int level = 0; level < mMipLevels; level++)
+    {
+        ASSERT(mSwizzleCache[level] == swizzleState);
+    }
+}
+
+void TextureStorage11::clearSRVCache()
+{
+    markDirty();
+
+    auto iter = mSrvCache.begin();
+    while (iter != mSrvCache.end())
+    {
+        if (!iter->first.swizzle)
+        {
+            SafeRelease(iter->second);
+            iter = mSrvCache.erase(iter);
+        }
+        else
+        {
+            iter++;
+        }
+    }
+
+    for (size_t level = 0; level < mLevelSRVs.size(); level++)
+    {
+        SafeRelease(mLevelSRVs[level]);
+        SafeRelease(mLevelBlitSRVs[level]);
+    }
+}
+
+gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage)
+{
+    ASSERT(destStorage);
+
+    ID3D11Resource *sourceResouce = nullptr;
+    ANGLE_TRY(getResource(&sourceResouce));
+
+    TextureStorage11 *dest11     = GetAs<TextureStorage11>(destStorage);
+    ID3D11Resource *destResource = nullptr;
+    ANGLE_TRY(dest11->getResource(&destResource));
+
+    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+    immediateContext->CopyResource(destResource, sourceResouce);
+
+    dest11->markDirty();
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
+                                    ImageD3D *image,
+                                    const gl::Box *destBox,
+                                    GLenum type,
+                                    const gl::PixelUnpackState &unpack,
+                                    const uint8_t *pixelData)
+{
+    ASSERT(!image->isDirty());
+
+    markLevelDirty(index.mipIndex);
+
+    ID3D11Resource *resource = nullptr;
+    ANGLE_TRY(getResource(&resource));
+    ASSERT(resource);
+
+    UINT destSubresource = getSubresourceIndex(index);
+
+    const gl::InternalFormat &internalFormatInfo =
+        gl::GetInternalFormatInfo(image->getInternalFormat(), type);
+
+    gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
+                     getLevelDepth(index.mipIndex));
+    bool fullUpdate = (destBox == nullptr || *destBox == levelBox);
+    ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate);
+
+    // TODO(jmadill): Handle compressed formats
+    // Compressed formats have different load syntax, so we'll have to handle them with slightly
+    // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData
+    // with compressed formats in the calling logic.
+    ASSERT(!internalFormatInfo.compressed);
+
+    const int width    = destBox ? destBox->width : static_cast<int>(image->getWidth());
+    const int height   = destBox ? destBox->height : static_cast<int>(image->getHeight());
+    const int depth    = destBox ? destBox->depth : static_cast<int>(image->getDepth());
+    GLuint srcRowPitch = 0;
+    ANGLE_TRY_RESULT(
+        internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength),
+        srcRowPitch);
+    GLuint srcDepthPitch = 0;
+    ANGLE_TRY_RESULT(internalFormatInfo.computeDepthPitch(height, unpack.imageHeight, srcRowPitch),
+                     srcDepthPitch);
+    GLuint srcSkipBytes = 0;
+    ANGLE_TRY_RESULT(
+        internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()),
+        srcSkipBytes);
+
+    const d3d11::Format &d3d11Format =
+        d3d11::Format::Get(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
+    const d3d11::DXGIFormatSize &dxgiFormatInfo =
+        d3d11::GetDXGIFormatSizeInfo(d3d11Format.texFormat);
+
+    const size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
+
+    UINT bufferRowPitch   = static_cast<unsigned int>(outputPixelSize) * width;
+    UINT bufferDepthPitch = bufferRowPitch * height;
+
+    const size_t neededSize        = bufferDepthPitch * depth;
+    angle::MemoryBuffer *conversionBuffer = nullptr;
+    const uint8_t *data            = nullptr;
+
+    LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(type);
+    if (loadFunctionInfo.requiresConversion)
+    {
+        ANGLE_TRY(mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer));
+        loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch,
+                                      srcDepthPitch, conversionBuffer->data(), bufferRowPitch,
+                                      bufferDepthPitch);
+        data = conversionBuffer->data();
+    }
+    else
+    {
+        data             = pixelData + srcSkipBytes;
+        bufferRowPitch   = srcRowPitch;
+        bufferDepthPitch = srcDepthPitch;
+    }
+
+    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+    if (!fullUpdate)
+    {
+        ASSERT(destBox);
+
+        D3D11_BOX destD3DBox;
+        destD3DBox.left   = destBox->x;
+        destD3DBox.right  = destBox->x + destBox->width;
+        destD3DBox.top    = destBox->y;
+        destD3DBox.bottom = destBox->y + destBox->height;
+        destD3DBox.front  = destBox->z;
+        destD3DBox.back   = destBox->z + destBox->depth;
+
+        immediateContext->UpdateSubresource(resource, destSubresource, &destD3DBox, data,
+                                            bufferRowPitch, bufferDepthPitch);
+    }
+    else
+    {
+        immediateContext->UpdateSubresource(resource, destSubresource, nullptr, data,
+                                            bufferRowPitch, bufferDepthPitch);
+    }
+
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11::ensureDropStencilTexture()
+{
+    UNIMPLEMENTED();
+    return gl::InternalError() << "Drop stencil texture not implemented.";
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
+    : TextureStorage11(renderer,
+                       D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
+                       0,
+                       swapchain->getRenderTargetInternalFormat()),
+      mTexture(swapchain->getOffscreenTexture()),
+      mLevelZeroTexture(nullptr),
+      mLevelZeroRenderTarget(nullptr),
+      mUseLevelZeroTexture(false),
+      mSwizzleTexture(nullptr)
+{
+    mTexture->AddRef();
+
+    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        mAssociatedImages[i]     = nullptr;
+        mRenderTarget[i]         = nullptr;
+    }
+
+    D3D11_TEXTURE2D_DESC texDesc;
+    mTexture->GetDesc(&texDesc);
+    mMipLevels     = texDesc.MipLevels;
+    mTextureWidth  = texDesc.Width;
+    mTextureHeight = texDesc.Height;
+    mTextureDepth  = 1;
+    mHasKeyedMutex = (texDesc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer,
+                                         GLenum internalformat,
+                                         bool renderTarget,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         int levels,
+                                         bool hintLevelZeroOnly)
+    : TextureStorage11(
+          renderer,
+          GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+          GetTextureMiscFlags(internalformat,
+                              renderer->getRenderer11DeviceCaps(),
+                              renderTarget,
+                              levels),
+          internalformat),
+      mTexture(nullptr),
+      mHasKeyedMutex(false),
+      mLevelZeroTexture(nullptr),
+      mLevelZeroRenderTarget(nullptr),
+      mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
+      mSwizzleTexture(nullptr)
+{
+    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        mAssociatedImages[i]     = nullptr;
+        mRenderTarget[i]         = nullptr;
+    }
+
+    d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
+    mMipLevels     = mTopLevel + levels;
+    mTextureWidth  = width;
+    mTextureHeight = height;
+    mTextureDepth  = 1;
+
+    // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
+    ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+}
+
+TextureStorage11_2D::~TextureStorage11_2D()
+{
+    for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        if (mAssociatedImages[i] != nullptr)
+        {
+            mAssociatedImages[i]->verifyAssociatedStorageValid(this);
+
+            // We must let the Images recover their data before we delete it from the
+            // TextureStorage.
+            gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage();
+            if (error.isError())
+            {
+                // TODO: Find a way to report this back to the context
+                ERR() << "Error initialization texture storage: " << error;
+            }
+        }
+    }
+
+    SafeRelease(mTexture);
+    SafeRelease(mSwizzleTexture);
+
+    SafeRelease(mLevelZeroTexture);
+    SafeDelete(mLevelZeroRenderTarget);
+
+    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        SafeDelete(mRenderTarget[i]);
+    }
+
+    if (mHasKeyedMutex)
+    {
+        // If the keyed mutex is released that will unbind it and cause the state cache to become
+        // desynchronized.
+        mRenderer->getStateManager()->invalidateBoundViews();
+    }
+}
+
+gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage)
+{
+    ASSERT(destStorage);
+
+    TextureStorage11_2D *dest11           = GetAs<TextureStorage11_2D>(destStorage);
+    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+    if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
+        // corresponding textures in destStorage.
+        if (mTexture)
+        {
+            ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false));
+
+            ID3D11Resource *destResource = nullptr;
+            ANGLE_TRY(dest11->getResource(&destResource));
+
+            immediateContext->CopyResource(destResource, mTexture);
+        }
+
+        if (mLevelZeroTexture)
+        {
+            ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true));
+
+            ID3D11Resource *destResource = nullptr;
+            ANGLE_TRY(dest11->getResource(&destResource));
+
+            immediateContext->CopyResource(destResource, mLevelZeroTexture);
+        }
+
+        return gl::NoError();
+    }
+
+    ID3D11Resource *sourceResouce = nullptr;
+    ANGLE_TRY(getResource(&sourceResouce));
+
+    ID3D11Resource *destResource = nullptr;
+    ANGLE_TRY(dest11->getResource(&destResource));
+
+    immediateContext->CopyResource(destResource, sourceResouce);
+    dest11->markDirty();
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
+{
+    bool lastSetting = mUseLevelZeroTexture;
+
+    if (useLevelZeroTexture && mMipLevels > 1)
+    {
+        if (!mUseLevelZeroTexture && mTexture)
+        {
+            ANGLE_TRY(ensureTextureExists(1));
+
+            // Pull data back from the mipped texture if necessary.
+            ASSERT(mLevelZeroTexture);
+            ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+            context->CopySubresourceRegion(mLevelZeroTexture, 0, 0, 0, 0, mTexture, 0, nullptr);
+        }
+
+        mUseLevelZeroTexture = true;
+    }
+    else
+    {
+        if (mUseLevelZeroTexture && mLevelZeroTexture)
+        {
+            ANGLE_TRY(ensureTextureExists(mMipLevels));
+
+            // Pull data back from the level zero texture if necessary.
+            ASSERT(mTexture);
+            ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+            context->CopySubresourceRegion(mTexture, 0, 0, 0, 0, mLevelZeroTexture, 0, nullptr);
+        }
+
+        mUseLevelZeroTexture = false;
+    }
+
+    if (lastSetting != mUseLevelZeroTexture)
+    {
+        // Mark everything as dirty to be conservative.
+        if (mLevelZeroRenderTarget)
+        {
+            mLevelZeroRenderTarget->signalDirty();
+        }
+        for (auto *renderTarget : mRenderTarget)
+        {
+            if (renderTarget)
+            {
+                renderTarget->signalDirty();
+            }
+        }
+    }
+
+    return gl::NoError();
+}
+
+void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+    const GLint level = index.mipIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+    if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+    {
+        mAssociatedImages[level] = image;
+    }
+}
+
+void TextureStorage11_2D::verifyAssociatedImageValid(const gl::ImageIndex &index,
+                                                     Image11 *expectedImage)
+{
+    const GLint level = index.mipIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    // This validation check should never return false. It means the Image/TextureStorage
+    // association is broken.
+    ASSERT(mAssociatedImages[level] == expectedImage);
+}
+
+// disassociateImage allows an Image to end its association with a Storage.
+void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
+{
+    const GLint level = index.mipIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(mAssociatedImages[level] == expectedImage);
+    mAssociatedImages[level] = nullptr;
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index,
+                                                      Image11 *incomingImage)
+{
+    const GLint level = index.mipIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+    if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+    {
+        // No need to let the old Image recover its data, if it is also the incoming Image.
+        if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
+        {
+            // Ensure that the Image is still associated with this TextureStorage.
+            mAssociatedImages[level]->verifyAssociatedStorageValid(this);
+
+            // Force the image to recover from storage before its data is overwritten.
+            // This will reset mAssociatedImages[level] to nullptr too.
+            ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage());
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
+{
+    if (mUseLevelZeroTexture && mMipLevels > 1)
+    {
+        ANGLE_TRY(ensureTextureExists(1));
+
+        *outResource = mLevelZeroTexture;
+        return gl::NoError();
+    }
+
+    ANGLE_TRY(ensureTextureExists(mMipLevels));
+
+    *outResource = mTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource)
+{
+    // This shouldn't be called unless the zero max LOD workaround is active.
+    ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+
+    ANGLE_TRY(ensureTextureExists(mMipLevels));
+
+    *outResource = mTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels)
+{
+    // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
+    bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround
+                                   ? (mipLevels == 1) && (mMipLevels > 1)
+                                   : false;
+    ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
+
+    // if the width or height is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (*outputTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
+    {
+        ASSERT(mipLevels > 0);
+
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width              = mTextureWidth;  // Compressed texture size constraints?
+        desc.Height             = mTextureHeight;
+        desc.MipLevels          = mipLevels;
+        desc.ArraySize          = 1;
+        desc.Format             = mFormatInfo.texFormat;
+        desc.SampleDesc.Count   = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage              = D3D11_USAGE_DEFAULT;
+        desc.BindFlags          = getBindFlags();
+        desc.CPUAccessFlags     = 0;
+        desc.MiscFlags          = getMiscFlags();
+
+        HRESULT result = device->CreateTexture2D(&desc, nullptr, outputTexture);
+
+        // this can happen from windows TDR
+        if (d3d11::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.",
+                             result);
+        }
+        else if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.",
+                             result);
+        }
+
+        d3d11::SetDebugName(*outputTexture, "TexStorage2D.Texture");
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+    ASSERT(!index.hasLayer());
+
+    const int level = index.mipIndex;
+    ASSERT(level >= 0 && level < getLevelCount());
+
+    // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of
+    // the GLES 2.0 spec, page 113 of version 2.0.25). Other parts of TextureStorage11_2D could
+    // create RTVs on non-zero levels of the texture (e.g. generateMipmap).
+    // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the
+    // individual levels of the texture, so methods like generateMipmap can't do anything useful
+    // with non-zero-level RTVs. Therefore if level > 0 on 9_3 then there's almost certainly
+    // something wrong.
+    ASSERT(
+        !(mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0));
+    ASSERT(outRT);
+    if (mRenderTarget[level])
+    {
+        *outRT = mRenderTarget[level];
+        return gl::NoError();
+    }
+
+    ID3D11Resource *texture = nullptr;
+    ANGLE_TRY(getResource(&texture));
+
+    ID3D11ShaderResourceView *srv = nullptr;
+    ANGLE_TRY(getSRVLevel(level, false, &srv));
+
+    ID3D11ShaderResourceView *blitSRV = nullptr;
+    ANGLE_TRY(getSRVLevel(level, true, &blitSRV));
+
+    ID3D11Device *device = mRenderer->getDevice();
+
+    if (mUseLevelZeroTexture)
+    {
+        if (!mLevelZeroRenderTarget)
+        {
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format             = mFormatInfo.rtvFormat;
+            rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
+            rtvDesc.Texture2D.MipSlice = mTopLevel + level;
+
+            d3d11::RenderTargetView rtv;
+            ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture, &rtv));
+
+            mLevelZeroRenderTarget = new TextureRenderTarget11(
+                std::move(rtv), mLevelZeroTexture, nullptr, nullptr, mFormatInfo.internalFormat,
+                getFormatSet(), getLevelWidth(level), getLevelHeight(level), 1, 0);
+        }
+
+        *outRT = mLevelZeroRenderTarget;
+        return gl::NoError();
+    }
+
+    if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+    {
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format             = mFormatInfo.rtvFormat;
+        rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
+        rtvDesc.Texture2D.MipSlice = mTopLevel + level;
+
+        d3d11::RenderTargetView rtv;
+        ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture, &rtv));
+
+        mRenderTarget[level] = new TextureRenderTarget11(
+            std::move(rtv), texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+            getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+        *outRT = mRenderTarget[level];
+        return gl::NoError();
+    }
+
+    ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+
+    D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+    dsvDesc.Format             = mFormatInfo.dsvFormat;
+    dsvDesc.ViewDimension      = D3D11_DSV_DIMENSION_TEXTURE2D;
+    dsvDesc.Texture2D.MipSlice = mTopLevel + level;
+    dsvDesc.Flags              = 0;
+
+    ID3D11DepthStencilView *dsv;
+    HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(
+            GL_OUT_OF_MEMORY,
+            "Failed to create internal depth stencil view for texture storage, result: 0x%X.",
+            result);
+    }
+
+    mRenderTarget[level] =
+        new TextureRenderTarget11(dsv, texture, srv, mFormatInfo.internalFormat, getFormatSet(),
+                                  getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+    // RenderTarget will take ownership of these resources
+    SafeRelease(dsv);
+
+    *outRT = mRenderTarget[level];
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::createSRV(int baseLevel,
+                                         int mipLevels,
+                                         DXGI_FORMAT format,
+                                         ID3D11Resource *texture,
+                                         ID3D11ShaderResourceView **outSRV) const
+{
+    ASSERT(outSRV);
+
+    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    srvDesc.Format                    = format;
+    srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
+    srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
+    srvDesc.Texture2D.MipLevels       = mipLevels;
+
+    ID3D11Resource *srvTexture = texture;
+
+    if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        ASSERT(mTopLevel == 0);
+        ASSERT(baseLevel == 0);
+        // This code also assumes that the incoming texture equals either mLevelZeroTexture or
+        // mTexture.
+
+        if (mipLevels == 1 && mMipLevels > 1)
+        {
+            // We must use a SRV on the level-zero-only texture.
+            ASSERT(mLevelZeroTexture != nullptr && texture == mLevelZeroTexture);
+            srvTexture = mLevelZeroTexture;
+        }
+        else
+        {
+            ASSERT(mipLevels == static_cast<int>(mMipLevels));
+            ASSERT(mTexture != nullptr && texture == mTexture);
+            srvTexture = mTexture;
+        }
+    }
+
+    ID3D11Device *device = mRenderer->getDevice();
+    HRESULT result       = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
+
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to create internal texture storage SRV, result: 0x%X.", result);
+    }
+
+    d3d11::SetDebugName(*outSRV, "TexStorage2D.SRV");
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+    ASSERT(outTexture);
+
+    if (!mSwizzleTexture)
+    {
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width              = mTextureWidth;
+        desc.Height             = mTextureHeight;
+        desc.MipLevels          = mMipLevels;
+        desc.ArraySize          = 1;
+        desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat;
+        desc.SampleDesc.Count   = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage              = D3D11_USAGE_DEFAULT;
+        desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+        desc.CPUAccessFlags     = 0;
+        desc.MiscFlags          = 0;
+
+        HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture);
+
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create internal swizzle texture, result: 0x%X.", result);
+        }
+
+        d3d11::SetDebugName(mSwizzleTexture, "TexStorage2D.SwizzleTexture");
+    }
+
+    *outTexture = mSwizzleTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel,
+                                                      const d3d11::RenderTargetView **outRTV)
+{
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+    ASSERT(outRTV);
+
+    if (!mSwizzleRenderTargets[mipLevel].valid())
+    {
+        ID3D11Resource *swizzleTexture = nullptr;
+        ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format =
+            mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+        rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
+        rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
+
+        ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture,
+                                              &mSwizzleRenderTargets[mipLevel]));
+    }
+
+    *outRTV = &mSwizzleRenderTargets[mipLevel];
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2D::ensureDropStencilTexture()
+{
+    if (mDropStencilTexture)
+    {
+        return DropStencil::ALREADY_EXISTS;
+    }
+
+    D3D11_TEXTURE2D_DESC dropDesc = {};
+    dropDesc.ArraySize            = 1;
+    dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+    dropDesc.CPUAccessFlags       = 0;
+    dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
+    dropDesc.Height               = mTextureHeight;
+    dropDesc.MipLevels            = mMipLevels;
+    dropDesc.MiscFlags            = 0;
+    dropDesc.SampleDesc.Count     = 1;
+    dropDesc.SampleDesc.Quality   = 0;
+    dropDesc.Usage                = D3D11_USAGE_DEFAULT;
+    dropDesc.Width                = mTextureWidth;
+
+    ID3D11Device *device = mRenderer->getDevice();
+
+    HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture);
+    if (FAILED(hr))
+    {
+        return gl::InternalError() << "Error creating drop stencil texture.";
+    }
+    d3d11::SetDebugName(mDropStencilTexture, "TexStorage2D.DropStencil");
+
+    ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::Make2D(0, mMipLevels)));
+
+    return DropStencil::CREATED;
+}
+
+TextureStorage11_External::TextureStorage11_External(
+    Renderer11 *renderer,
+    egl::Stream *stream,
+    const egl::Stream::GLTextureDescription &glDesc)
+    : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat)
+{
+    ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11TextureNV12);
+    StreamProducerNV12 *producer = static_cast<StreamProducerNV12 *>(stream->getImplementation());
+    mTexture                     = producer->getD3DTexture();
+    mSubresourceIndex            = producer->getArraySlice();
+    mTexture->AddRef();
+    mMipLevels = 1;
+
+    D3D11_TEXTURE2D_DESC desc;
+    mTexture->GetDesc(&desc);
+    mTextureWidth  = desc.Width;
+    mTextureHeight = desc.Height;
+    mTextureDepth  = 1;
+    mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
+}
+
+TextureStorage11_External::~TextureStorage11_External()
+{
+    SafeRelease(mTexture);
+    if (mHasKeyedMutex)
+    {
+        // If the keyed mutex is released that will unbind it and cause the state cache to become
+        // desynchronized.
+        mRenderer->getStateManager()->invalidateBoundViews();
+    }
+}
+
+gl::Error TextureStorage11_External::copyToStorage(TextureStorage *destStorage)
+{
+    UNIMPLEMENTED();
+    return gl::NoError();
+}
+
+void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+    ASSERT(index.mipIndex == 0);
+    mAssociatedImage = image;
+}
+
+void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index,
+                                                           Image11 *expectedImage)
+{
+    ASSERT(index.mipIndex == 0 && mAssociatedImage == expectedImage);
+}
+
+void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index,
+                                                  Image11 *expectedImage)
+{
+    ASSERT(index.mipIndex == 0);
+    ASSERT(mAssociatedImage == expectedImage);
+    mAssociatedImage = nullptr;
+}
+
+gl::Error TextureStorage11_External::releaseAssociatedImage(const gl::ImageIndex &index,
+                                                            Image11 *incomingImage)
+{
+    ASSERT(index.mipIndex == 0);
+
+    if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
+    {
+        mAssociatedImage->verifyAssociatedStorageValid(this);
+
+        ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage());
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_External::getResource(ID3D11Resource **outResource)
+{
+    *outResource = mTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_External::getMippedResource(ID3D11Resource **outResource)
+{
+    *outResource = mTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_External::getRenderTarget(const gl::ImageIndex &index,
+                                                     RenderTargetD3D **outRT)
+{
+    // Render targets are not supported for external textures
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage11_External::createSRV(int baseLevel,
+                                               int mipLevels,
+                                               DXGI_FORMAT format,
+                                               ID3D11Resource *texture,
+                                               ID3D11ShaderResourceView **outSRV) const
+{
+    // Since external textures are treates as non-mipmapped textures, we ignore mipmap levels and
+    // use the specified subresource ID the storage was created with.
+    ASSERT(mipLevels == 1);
+    ASSERT(outSRV);
+
+    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    srvDesc.Format        = format;
+    srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+    // subresource index is equal to the mip level for 2D textures
+    srvDesc.Texture2DArray.MostDetailedMip = 0;
+    srvDesc.Texture2DArray.MipLevels       = 1;
+    srvDesc.Texture2DArray.FirstArraySlice = mSubresourceIndex;
+    srvDesc.Texture2DArray.ArraySize       = 1;
+
+    ID3D11Resource *srvTexture = texture;
+
+    ID3D11Device *device = mRenderer->getDevice();
+    HRESULT result       = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
+
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to create internal texture storage SRV, result: 0x%X.", result);
+    }
+
+    d3d11::SetDebugName(*outSRV, "TexStorage2D.SRV");
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_External::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage11_External::getSwizzleRenderTarget(int mipLevel,
+                                                            const d3d11::RenderTargetView **outRTV)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
+                                                     EGLImageD3D *eglImage,
+                                                     RenderTarget11 *renderTarget11)
+    : TextureStorage11(renderer,
+                       D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
+                       0,
+                       renderTarget11->getInternalFormat()),
+      mImage(eglImage),
+      mCurrentRenderTarget(0),
+      mSwizzleTexture(nullptr),
+      mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+{
+    mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
+
+    mMipLevels     = 1;
+    mTextureWidth  = renderTarget11->getWidth();
+    mTextureHeight = renderTarget11->getHeight();
+    mTextureDepth  = 1;
+}
+
+TextureStorage11_EGLImage::~TextureStorage11_EGLImage()
+{
+    SafeRelease(mSwizzleTexture);
+}
+
+gl::Error TextureStorage11_EGLImage::getResource(ID3D11Resource **outResource)
+{
+    ANGLE_TRY(checkForUpdatedRenderTarget());
+
+    RenderTarget11 *renderTarget11 = nullptr;
+    ANGLE_TRY(getImageRenderTarget(&renderTarget11));
+    *outResource = renderTarget11->getTexture();
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::getSRV(const gl::TextureState &textureState,
+                                            ID3D11ShaderResourceView **outSRV)
+{
+    ANGLE_TRY(checkForUpdatedRenderTarget());
+    return TextureStorage11::getSRV(textureState, outSRV);
+}
+
+gl::Error TextureStorage11_EGLImage::getMippedResource(ID3D11Resource **)
+{
+    // This shouldn't be called unless the zero max LOD workaround is active.
+    // EGL images are unavailable in this configuration.
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::ImageIndex &index,
+                                                     RenderTargetD3D **outRT)
+{
+    ASSERT(!index.hasLayer());
+    ASSERT(index.mipIndex == 0);
+
+    ANGLE_TRY(checkForUpdatedRenderTarget());
+
+    return mImage->getRenderTarget(outRT);
+}
+
+gl::Error TextureStorage11_EGLImage::copyToStorage(TextureStorage *destStorage)
+{
+    ID3D11Resource *sourceResouce = nullptr;
+    ANGLE_TRY(getResource(&sourceResouce));
+
+    ASSERT(destStorage);
+    TextureStorage11_2D *dest11  = GetAs<TextureStorage11_2D>(destStorage);
+    ID3D11Resource *destResource = nullptr;
+    ANGLE_TRY(dest11->getResource(&destResource));
+
+    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+    immediateContext->CopyResource(destResource, sourceResouce);
+
+    dest11->markDirty();
+
+    return gl::NoError();
+}
+
+void TextureStorage11_EGLImage::associateImage(Image11 *, const gl::ImageIndex &)
+{
+}
+
+void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &, Image11 *)
+{
+}
+
+void TextureStorage11_EGLImage::verifyAssociatedImageValid(const gl::ImageIndex &, Image11 *)
+{
+}
+
+gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::ImageIndex &, Image11 *)
+{
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(bool)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+    ASSERT(outTexture);
+
+    if (!mSwizzleTexture)
+    {
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width              = mTextureWidth;
+        desc.Height             = mTextureHeight;
+        desc.MipLevels          = mMipLevels;
+        desc.ArraySize          = 1;
+        desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat;
+        desc.SampleDesc.Count   = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage              = D3D11_USAGE_DEFAULT;
+        desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+        desc.CPUAccessFlags     = 0;
+        desc.MiscFlags          = 0;
+
+        HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture);
+
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create internal swizzle texture, result: 0x%X.", result);
+        }
+
+        d3d11::SetDebugName(mSwizzleTexture, "TexStorageEGLImage.SwizzleTexture");
+    }
+
+    *outTexture = mSwizzleTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::getSwizzleRenderTarget(int mipLevel,
+                                                            const d3d11::RenderTargetView **outRTV)
+{
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+    ASSERT(outRTV);
+
+    if (!mSwizzleRenderTargets[mipLevel].valid())
+    {
+        ID3D11Resource *swizzleTexture = nullptr;
+        ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format =
+            mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+        rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
+        rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
+
+        ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture,
+                                              &mSwizzleRenderTargets[mipLevel]));
+    }
+
+    *outRTV = &mSwizzleRenderTargets[mipLevel];
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget()
+{
+    RenderTarget11 *renderTarget11 = nullptr;
+    ANGLE_TRY(getImageRenderTarget(&renderTarget11));
+
+    if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11))
+    {
+        clearSRVCache();
+        mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel,
+                                               int mipLevels,
+                                               DXGI_FORMAT format,
+                                               ID3D11Resource *texture,
+                                               ID3D11ShaderResourceView **outSRV) const
+{
+    ASSERT(baseLevel == 0);
+    ASSERT(mipLevels == 1);
+    ASSERT(outSRV);
+
+    // Create a new SRV only for the swizzle texture.  Otherwise just return the Image's
+    // RenderTarget's SRV.
+    if (texture == mSwizzleTexture)
+    {
+        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+        srvDesc.Format                    = format;
+        srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
+        srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
+        srvDesc.Texture2D.MipLevels       = mipLevels;
+
+        ID3D11Device *device = mRenderer->getDevice();
+        HRESULT result       = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
+
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create internal texture storage SRV, result: 0x%X.",
+                             result);
+        }
+
+        d3d11::SetDebugName(*outSRV, "TexStorageEGLImage.SRV");
+    }
+    else
+    {
+        RenderTarget11 *renderTarget = nullptr;
+        ANGLE_TRY(getImageRenderTarget(&renderTarget));
+
+        ASSERT(texture == renderTarget->getTexture());
+
+        *outSRV = renderTarget->getShaderResourceView();
+        (*outSRV)->AddRef();
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::getImageRenderTarget(RenderTarget11 **outRT) const
+{
+    RenderTargetD3D *renderTargetD3D = nullptr;
+    ANGLE_TRY(mImage->getRenderTarget(&renderTargetD3D));
+    *outRT = GetAs<RenderTarget11>(renderTargetD3D);
+    return gl::NoError();
+}
+
+TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer,
+                                             GLenum internalformat,
+                                             bool renderTarget,
+                                             int size,
+                                             int levels,
+                                             bool hintLevelZeroOnly)
+    : TextureStorage11(
+          renderer,
+          GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+          GetTextureMiscFlags(internalformat,
+                              renderer->getRenderer11DeviceCaps(),
+                              renderTarget,
+                              levels),
+          internalformat),
+      mTexture(nullptr),
+      mLevelZeroTexture(nullptr),
+      mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
+      mSwizzleTexture(nullptr)
+{
+    for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+        {
+            mAssociatedImages[face][level] = nullptr;
+            mRenderTarget[face][level]     = nullptr;
+        }
+    }
+
+    for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+    {
+        mLevelZeroRenderTarget[face] = nullptr;
+    }
+
+    // adjust size if needed for compressed textures
+    int height = size;
+    d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel);
+
+    mMipLevels     = mTopLevel + levels;
+    mTextureWidth  = size;
+    mTextureHeight = size;
+    mTextureDepth  = 1;
+
+    // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
+    ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+}
+
+TextureStorage11_Cube::~TextureStorage11_Cube()
+{
+    for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+        {
+            if (mAssociatedImages[face][level] != nullptr)
+            {
+                mAssociatedImages[face][level]->verifyAssociatedStorageValid(this);
+
+                // We must let the Images recover their data before we delete it from the
+                // TextureStorage.
+                mAssociatedImages[face][level]->recoverFromAssociatedStorage();
+            }
+        }
+    }
+
+    SafeRelease(mTexture);
+    SafeRelease(mSwizzleTexture);
+    SafeRelease(mLevelZeroTexture);
+
+    for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+    {
+        SafeDelete(mLevelZeroRenderTarget[face]);
+    }
+
+    for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+        {
+            SafeDelete(mRenderTarget[face][level]);
+        }
+    }
+}
+
+UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const
+{
+    if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture &&
+        index.mipIndex == 0)
+    {
+        UINT arraySlice  = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+        UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
+        ASSERT(subresource != std::numeric_limits<UINT>::max());
+        return subresource;
+    }
+    else
+    {
+        UINT mipSlice    = static_cast<UINT>(index.mipIndex + mTopLevel);
+        UINT arraySlice  = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+        UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
+        ASSERT(subresource != std::numeric_limits<UINT>::max());
+        return subresource;
+    }
+}
+
+gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage)
+{
+    ASSERT(destStorage);
+
+    TextureStorage11_Cube *dest11 = GetAs<TextureStorage11_Cube>(destStorage);
+
+    if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+        // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
+        // corresponding textures in destStorage.
+        if (mTexture)
+        {
+            ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false));
+
+            ID3D11Resource *destResource = nullptr;
+            ANGLE_TRY(dest11->getResource(&destResource));
+
+            immediateContext->CopyResource(destResource, mTexture);
+        }
+
+        if (mLevelZeroTexture)
+        {
+            ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true));
+
+            ID3D11Resource *destResource = nullptr;
+            ANGLE_TRY(dest11->getResource(&destResource));
+
+            immediateContext->CopyResource(destResource, mLevelZeroTexture);
+        }
+    }
+    else
+    {
+        ID3D11Resource *sourceResouce = nullptr;
+        ANGLE_TRY(getResource(&sourceResouce));
+
+        ID3D11Resource *destResource = nullptr;
+        ANGLE_TRY(dest11->getResource(&destResource));
+
+        ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+        immediateContext->CopyResource(destResource, sourceResouce);
+    }
+
+    dest11->markDirty();
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
+{
+    if (useLevelZeroTexture && mMipLevels > 1)
+    {
+        if (!mUseLevelZeroTexture && mTexture)
+        {
+            ANGLE_TRY(ensureTextureExists(1));
+
+            // Pull data back from the mipped texture if necessary.
+            ASSERT(mLevelZeroTexture);
+            ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+            for (int face = 0; face < 6; face++)
+            {
+                context->CopySubresourceRegion(mLevelZeroTexture, D3D11CalcSubresource(0, face, 1),
+                                               0, 0, 0, mTexture, face * mMipLevels, nullptr);
+            }
+        }
+
+        mUseLevelZeroTexture = true;
+    }
+    else
+    {
+        if (mUseLevelZeroTexture && mLevelZeroTexture)
+        {
+            ANGLE_TRY(ensureTextureExists(mMipLevels));
+
+            // Pull data back from the level zero texture if necessary.
+            ASSERT(mTexture);
+            ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+            for (int face = 0; face < 6; face++)
+            {
+                context->CopySubresourceRegion(mTexture, D3D11CalcSubresource(0, face, mMipLevels),
+                                               0, 0, 0, mLevelZeroTexture, face, nullptr);
+            }
+        }
+
+        mUseLevelZeroTexture = false;
+    }
+
+    return gl::NoError();
+}
+
+void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+    const GLint level       = index.mipIndex;
+    const GLint layerTarget = index.layerIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT));
+
+    if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+    {
+        if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT))
+        {
+            mAssociatedImages[layerTarget][level] = image;
+        }
+    }
+}
+
+void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index,
+                                                       Image11 *expectedImage)
+{
+    const GLint level       = index.mipIndex;
+    const GLint layerTarget = index.layerIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT));
+    // This validation check should never return false. It means the Image/TextureStorage
+    // association is broken.
+    ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
+}
+
+// disassociateImage allows an Image to end its association with a Storage.
+void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
+{
+    const GLint level       = index.mipIndex;
+    const GLint layerTarget = index.layerIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT));
+    ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
+    mAssociatedImages[layerTarget][level] = nullptr;
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index,
+                                                        Image11 *incomingImage)
+{
+    const GLint level       = index.mipIndex;
+    const GLint layerTarget = index.layerIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT));
+
+    if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
+    {
+        if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT))
+        {
+            // No need to let the old Image recover its data, if it is also the incoming Image.
+            if (mAssociatedImages[layerTarget][level] != nullptr &&
+                mAssociatedImages[layerTarget][level] != incomingImage)
+            {
+                // Ensure that the Image is still associated with this TextureStorage.
+                mAssociatedImages[layerTarget][level]->verifyAssociatedStorageValid(this);
+
+                // Force the image to recover from storage before its data is overwritten.
+                // This will reset mAssociatedImages[level] to nullptr too.
+                ANGLE_TRY(mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage());
+            }
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource)
+{
+    if (mUseLevelZeroTexture && mMipLevels > 1)
+    {
+        ANGLE_TRY(ensureTextureExists(1));
+        *outResource = mLevelZeroTexture;
+        return gl::NoError();
+    }
+    else
+    {
+        ANGLE_TRY(ensureTextureExists(mMipLevels));
+        *outResource = mTexture;
+        return gl::NoError();
+    }
+}
+
+gl::Error TextureStorage11_Cube::getMippedResource(ID3D11Resource **outResource)
+{
+    // This shouldn't be called unless the zero max LOD workaround is active.
+    ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+
+    ANGLE_TRY(ensureTextureExists(mMipLevels));
+    *outResource = mTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels)
+{
+    // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
+    bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround
+                                   ? (mipLevels == 1) && (mMipLevels > 1)
+                                   : false;
+    ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
+
+    // if the size is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (*outputTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
+    {
+        ASSERT(mMipLevels > 0);
+
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width              = mTextureWidth;
+        desc.Height             = mTextureHeight;
+        desc.MipLevels          = mipLevels;
+        desc.ArraySize          = CUBE_FACE_COUNT;
+        desc.Format             = mFormatInfo.texFormat;
+        desc.SampleDesc.Count   = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage              = D3D11_USAGE_DEFAULT;
+        desc.BindFlags          = getBindFlags();
+        desc.CPUAccessFlags     = 0;
+        desc.MiscFlags          = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags();
+
+        HRESULT result = device->CreateTexture2D(&desc, nullptr, outputTexture);
+
+        // this can happen from windows TDR
+        if (d3d11::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create cube texture storage, result: 0x%X.", result);
+        }
+        else if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create cube texture storage, result: 0x%X.", result);
+        }
+
+        d3d11::SetDebugName(*outputTexture, "TexStorageCube.Texture");
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::createRenderTargetSRV(ID3D11Resource *texture,
+                                                       const gl::ImageIndex &index,
+                                                       DXGI_FORMAT resourceFormat,
+                                                       ID3D11ShaderResourceView **srv) const
+{
+    ID3D11Device *device = mRenderer->getDevice();
+    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    srvDesc.Format                         = resourceFormat;
+    srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
+    srvDesc.Texture2DArray.MipLevels       = 1;
+    srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex;
+    srvDesc.Texture2DArray.ArraySize       = 1;
+
+    if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+    {
+        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+    }
+    else
+    {
+        // Will be used with Texture2D sampler, not TextureCube
+        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+    }
+
+    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, srv);
+
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(
+            GL_OUT_OF_MEMORY,
+            "Failed to create internal shader resource view for texture storage, result: 0x%X.",
+            result);
+    }
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index,
+                                                 RenderTargetD3D **outRT)
+{
+    const int faceIndex = index.layerIndex;
+    const int level     = index.mipIndex;
+
+    ASSERT(level >= 0 && level < getLevelCount());
+    ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(CUBE_FACE_COUNT));
+
+    if (!mRenderTarget[faceIndex][level])
+    {
+        ID3D11Device *device = mRenderer->getDevice();
+        HRESULT result;
+
+        ID3D11Resource *texture = nullptr;
+        ANGLE_TRY(getResource(&texture));
+
+        if (mUseLevelZeroTexture)
+        {
+            if (!mLevelZeroRenderTarget[faceIndex])
+            {
+                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+                rtvDesc.Format                         = mFormatInfo.rtvFormat;
+                rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+                rtvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
+                rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+                rtvDesc.Texture2DArray.ArraySize       = 1;
+
+                d3d11::RenderTargetView rtv;
+                ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture, &rtv));
+
+                mLevelZeroRenderTarget[faceIndex] = new TextureRenderTarget11(
+                    std::move(rtv), mLevelZeroTexture, nullptr, nullptr, mFormatInfo.internalFormat,
+                    getFormatSet(), getLevelWidth(level), getLevelHeight(level), 1, 0);
+            }
+
+            ASSERT(outRT);
+            *outRT = mLevelZeroRenderTarget[faceIndex];
+            return gl::NoError();
+        }
+
+        ID3D11ShaderResourceView *srv = nullptr;
+        ANGLE_TRY(createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv));
+        ID3D11ShaderResourceView *blitSRV = nullptr;
+        if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
+        {
+            gl::Error error =
+                createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV);
+            if (error.isError())
+            {
+                SafeRelease(srv);
+                return error;
+            }
+        }
+        else
+        {
+            blitSRV = srv;
+            blitSRV->AddRef();
+        }
+
+        d3d11::SetDebugName(srv, "TexStorageCube.RenderTargetSRV");
+
+        if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format                         = mFormatInfo.rtvFormat;
+            rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+            rtvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
+            rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+            rtvDesc.Texture2DArray.ArraySize       = 1;
+
+            d3d11::RenderTargetView rtv;
+            gl::Error err = mRenderer->allocateResource(rtvDesc, texture, &rtv);
+
+            if (err.isError())
+            {
+                SafeRelease(srv);
+                SafeRelease(blitSRV);
+                return err;
+            }
+
+            rtv.setDebugName("TexStorageCube.RenderTargetRTV");
+
+            mRenderTarget[faceIndex][level] = new TextureRenderTarget11(
+                std::move(rtv), texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+                getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+            SafeRelease(srv);
+            SafeRelease(blitSRV);
+        }
+        else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+            dsvDesc.Format                         = mFormatInfo.dsvFormat;
+            dsvDesc.ViewDimension                  = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+            dsvDesc.Flags                          = 0;
+            dsvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
+            dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+            dsvDesc.Texture2DArray.ArraySize       = 1;
+
+            ID3D11DepthStencilView *dsv;
+            result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+
+            ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                SafeRelease(srv);
+                SafeRelease(blitSRV);
+                return gl::Error(GL_OUT_OF_MEMORY,
+                                 "Failed to create internal depth stencil view for texture "
+                                 "storage, result: 0x%X.",
+                                 result);
+            }
+
+            d3d11::SetDebugName(dsv, "TexStorageCube.RenderTargetDSV");
+
+            mRenderTarget[faceIndex][level] = new TextureRenderTarget11(
+                dsv, texture, srv, mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
+                getLevelHeight(level), 1, 0);
+
+            // RenderTarget will take ownership of these resources
+            SafeRelease(dsv);
+            SafeRelease(srv);
+            SafeRelease(blitSRV);
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+    }
+
+    ASSERT(outRT);
+    *outRT = mRenderTarget[faceIndex][level];
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::createSRV(int baseLevel,
+                                           int mipLevels,
+                                           DXGI_FORMAT format,
+                                           ID3D11Resource *texture,
+                                           ID3D11ShaderResourceView **outSRV) const
+{
+    ASSERT(outSRV);
+
+    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    srvDesc.Format = format;
+
+    // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six
+    // 2D textures
+    const GLenum componentType = d3d11::GetComponentType(format);
+    if (componentType == GL_INT || componentType == GL_UNSIGNED_INT)
+    {
+        srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+        srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
+        srvDesc.Texture2DArray.MipLevels       = mipLevels;
+        srvDesc.Texture2DArray.FirstArraySlice = 0;
+        srvDesc.Texture2DArray.ArraySize       = CUBE_FACE_COUNT;
+    }
+    else
+    {
+        srvDesc.ViewDimension               = D3D11_SRV_DIMENSION_TEXTURECUBE;
+        srvDesc.TextureCube.MipLevels       = mipLevels;
+        srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
+    }
+
+    ID3D11Resource *srvTexture = texture;
+
+    if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    {
+        ASSERT(mTopLevel == 0);
+        ASSERT(baseLevel == 0);
+        // This code also assumes that the incoming texture equals either mLevelZeroTexture or
+        // mTexture.
+
+        if (mipLevels == 1 && mMipLevels > 1)
+        {
+            // We must use a SRV on the level-zero-only texture.
+            ASSERT(mLevelZeroTexture != nullptr && texture == mLevelZeroTexture);
+            srvTexture = mLevelZeroTexture;
+        }
+        else
+        {
+            ASSERT(mipLevels == static_cast<int>(mMipLevels));
+            ASSERT(mTexture != nullptr && texture == mTexture);
+            srvTexture = mTexture;
+        }
+    }
+
+    ID3D11Device *device = mRenderer->getDevice();
+    HRESULT result       = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
+
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to create internal texture storage SRV, result: 0x%X.", result);
+    }
+
+    d3d11::SetDebugName(*outSRV, "TexStorageCube.SRV");
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+    ASSERT(outTexture);
+
+    if (!mSwizzleTexture)
+    {
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width              = mTextureWidth;
+        desc.Height             = mTextureHeight;
+        desc.MipLevels          = mMipLevels;
+        desc.ArraySize          = CUBE_FACE_COUNT;
+        desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat;
+        desc.SampleDesc.Count   = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage              = D3D11_USAGE_DEFAULT;
+        desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+        desc.CPUAccessFlags     = 0;
+        desc.MiscFlags          = D3D11_RESOURCE_MISC_TEXTURECUBE;
+
+        HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture);
+
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create internal swizzle texture, result: 0x%X.", result);
+        }
+
+        d3d11::SetDebugName(*outTexture, "TexStorageCube.SwizzleTexture");
+    }
+
+    *outTexture = mSwizzleTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel,
+                                                        const d3d11::RenderTargetView **outRTV)
+{
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+    ASSERT(outRTV);
+
+    if (!mSwizzleRenderTargets[mipLevel].valid())
+    {
+        ID3D11Resource *swizzleTexture = nullptr;
+        ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format =
+            mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+        rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+        rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
+        rtvDesc.Texture2DArray.FirstArraySlice = 0;
+        rtvDesc.Texture2DArray.ArraySize       = CUBE_FACE_COUNT;
+
+        ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture,
+                                              &mSwizzleRenderTargets[mipLevel]));
+    }
+
+    *outRTV = &mSwizzleRenderTargets[mipLevel];
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11::initDropStencilTexture(const gl::ImageIndexIterator &it)
+{
+    ID3D11Resource *resource = nullptr;
+    ANGLE_TRY(getResource(&resource));
+    TextureHelper11 sourceTexture = TextureHelper11::MakeAndReference(resource, mFormatInfo);
+    TextureHelper11 destTexture   = TextureHelper11::MakeAndReference(
+        mDropStencilTexture,
+        d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps()));
+
+    gl::ImageIndexIterator itCopy = it;
+
+    while (itCopy.hasNext())
+    {
+        gl::ImageIndex index = itCopy.next();
+        gl::Box wholeArea(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
+                          1);
+        gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
+        UINT subresource = getSubresourceIndex(index);
+        ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(sourceTexture, subresource, wholeArea,
+                                                            wholeSize, destTexture, subresource,
+                                                            wholeArea, wholeSize, nullptr));
+    }
+
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_Cube::ensureDropStencilTexture()
+{
+    if (mDropStencilTexture)
+    {
+        return DropStencil::ALREADY_EXISTS;
+    }
+
+    D3D11_TEXTURE2D_DESC dropDesc = {};
+    dropDesc.ArraySize            = 6;
+    dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+    dropDesc.CPUAccessFlags       = 0;
+    dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
+    dropDesc.Height               = mTextureHeight;
+    dropDesc.MipLevels            = mMipLevels;
+    dropDesc.MiscFlags            = D3D11_RESOURCE_MISC_TEXTURECUBE;
+    dropDesc.SampleDesc.Count     = 1;
+    dropDesc.SampleDesc.Quality   = 0;
+    dropDesc.Usage                = D3D11_USAGE_DEFAULT;
+    dropDesc.Width                = mTextureWidth;
+
+    ID3D11Device *device = mRenderer->getDevice();
+
+    HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture);
+    if (FAILED(hr))
+    {
+        return gl::InternalError() << "Error creating drop stencil texture.";
+    }
+    d3d11::SetDebugName(mDropStencilTexture, "TexStorageCube.DropStencil");
+
+    ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
+
+    return DropStencil::CREATED;
+}
+
+TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
+                                         GLenum internalformat,
+                                         bool renderTarget,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLsizei depth,
+                                         int levels)
+    : TextureStorage11(
+          renderer,
+          GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+          GetTextureMiscFlags(internalformat,
+                              renderer->getRenderer11DeviceCaps(),
+                              renderTarget,
+                              levels),
+          internalformat)
+{
+    mTexture        = nullptr;
+    mSwizzleTexture = nullptr;
+
+    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        mAssociatedImages[i]     = nullptr;
+        mLevelRenderTargets[i]   = nullptr;
+    }
+
+    // adjust size if needed for compressed textures
+    d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
+
+    mMipLevels     = mTopLevel + levels;
+    mTextureWidth  = width;
+    mTextureHeight = height;
+    mTextureDepth  = depth;
+}
+
+TextureStorage11_3D::~TextureStorage11_3D()
+{
+    for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        if (mAssociatedImages[i] != nullptr)
+        {
+            mAssociatedImages[i]->verifyAssociatedStorageValid(this);
+
+            // We must let the Images recover their data before we delete it from the
+            // TextureStorage.
+            mAssociatedImages[i]->recoverFromAssociatedStorage();
+        }
+    }
+
+    SafeRelease(mTexture);
+    SafeRelease(mSwizzleTexture);
+
+    for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin();
+         i != mLevelLayerRenderTargets.end(); i++)
+    {
+        SafeDelete(i->second);
+    }
+    mLevelLayerRenderTargets.clear();
+
+    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+    {
+        SafeDelete(mLevelRenderTargets[i]);
+    }
+}
+
+void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+    const GLint level = index.mipIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+    if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+    {
+        mAssociatedImages[level] = image;
+    }
+}
+
+void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index,
+                                                     Image11 *expectedImage)
+{
+    const GLint level = index.mipIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    // This validation check should never return false. It means the Image/TextureStorage
+    // association is broken.
+    ASSERT(mAssociatedImages[level] == expectedImage);
+}
+
+// disassociateImage allows an Image to end its association with a Storage.
+void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
+{
+    const GLint level = index.mipIndex;
+
+    ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(mAssociatedImages[level] == expectedImage);
+    mAssociatedImages[level] = nullptr;
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index,
+                                                      Image11 *incomingImage)
+{
+    const GLint level = index.mipIndex;
+
+    ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
+
+    if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+    {
+        // No need to let the old Image recover its data, if it is also the incoming Image.
+        if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
+        {
+            // Ensure that the Image is still associated with this TextureStorage.
+            mAssociatedImages[level]->verifyAssociatedStorageValid(this);
+
+            // Force the image to recover from storage before its data is overwritten.
+            // This will reset mAssociatedImages[level] to nullptr too.
+            ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage());
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource)
+{
+    // If the width, height or depth are not positive this should be treated as an incomplete
+    // texture. We handle that here by skipping the d3d texture creation.
+    if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+    {
+        ASSERT(mMipLevels > 0);
+
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE3D_DESC desc;
+        desc.Width          = mTextureWidth;
+        desc.Height         = mTextureHeight;
+        desc.Depth          = mTextureDepth;
+        desc.MipLevels      = mMipLevels;
+        desc.Format         = mFormatInfo.texFormat;
+        desc.Usage          = D3D11_USAGE_DEFAULT;
+        desc.BindFlags      = getBindFlags();
+        desc.CPUAccessFlags = 0;
+        desc.MiscFlags      = getMiscFlags();
+
+        HRESULT result = device->CreateTexture3D(&desc, nullptr, &mTexture);
+
+        // this can happen from windows TDR
+        if (d3d11::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.",
+                             result);
+        }
+        else if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.",
+                             result);
+        }
+
+        d3d11::SetDebugName(mTexture, "TexStorage3D.Texture");
+    }
+
+    *outResource = mTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_3D::createSRV(int baseLevel,
+                                         int mipLevels,
+                                         DXGI_FORMAT format,
+                                         ID3D11Resource *texture,
+                                         ID3D11ShaderResourceView **outSRV) const
+{
+    ASSERT(outSRV);
+
+    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    srvDesc.Format                    = format;
+    srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE3D;
+    srvDesc.Texture3D.MostDetailedMip = baseLevel;
+    srvDesc.Texture3D.MipLevels       = mipLevels;
+
+    ID3D11Device *device = mRenderer->getDevice();
+    HRESULT result       = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
+
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to create internal texture storage SRV, result: 0x%X.", result);
+    }
+
+    d3d11::SetDebugName(*outSRV, "TexStorage3D.SRV");
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+    const int mipLevel = index.mipIndex;
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+    ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
+
+    if (!index.hasLayer())
+    {
+        if (!mLevelRenderTargets[mipLevel])
+        {
+            ID3D11Resource *texture = nullptr;
+            ANGLE_TRY(getResource(&texture));
+
+            ID3D11ShaderResourceView *srv = nullptr;
+            ANGLE_TRY(getSRVLevel(mipLevel, false, &srv));
+
+            ID3D11ShaderResourceView *blitSRV = nullptr;
+            ANGLE_TRY(getSRVLevel(mipLevel, true, &blitSRV));
+
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format                = mFormatInfo.rtvFormat;
+            rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
+            rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
+            rtvDesc.Texture3D.FirstWSlice = 0;
+            rtvDesc.Texture3D.WSize       = static_cast<UINT>(-1);
+
+            d3d11::RenderTargetView rtv;
+            gl::Error err = mRenderer->allocateResource(rtvDesc, texture, &rtv);
+            if (err.isError())
+            {
+                SafeRelease(srv);
+                SafeRelease(blitSRV);
+                return err;
+            }
+
+            rtv.setDebugName("TexStorage3D.RTV");
+
+            mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(
+                std::move(rtv), texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+                getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0);
+        }
+
+        ASSERT(outRT);
+        *outRT = mLevelRenderTargets[mipLevel];
+        return gl::NoError();
+    }
+
+    const int layer = index.layerIndex;
+
+    LevelLayerKey key(mipLevel, layer);
+    if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
+    {
+        ID3D11Resource *texture = nullptr;
+        ANGLE_TRY(getResource(&texture));
+
+        // TODO, what kind of SRV is expected here?
+        ID3D11ShaderResourceView *srv     = nullptr;
+        ID3D11ShaderResourceView *blitSRV = nullptr;
+
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format                = mFormatInfo.rtvFormat;
+        rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
+        rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
+        rtvDesc.Texture3D.FirstWSlice = layer;
+        rtvDesc.Texture3D.WSize       = 1;
+
+        d3d11::RenderTargetView rtv;
+        gl::Error err = mRenderer->allocateResource(rtvDesc, texture, &rtv);
+        if (err.isError())
+        {
+            SafeRelease(srv);
+            SafeRelease(blitSRV);
+            return err;
+        }
+
+        rtv.setDebugName("TexStorage3D.LayerRTV");
+
+        mLevelLayerRenderTargets[key] = new TextureRenderTarget11(
+            std::move(rtv), texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+            getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
+    }
+
+    ASSERT(outRT);
+    *outRT = mLevelLayerRenderTargets[key];
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+    ASSERT(outTexture);
+
+    if (!mSwizzleTexture)
+    {
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE3D_DESC desc;
+        desc.Width          = mTextureWidth;
+        desc.Height         = mTextureHeight;
+        desc.Depth          = mTextureDepth;
+        desc.MipLevels      = mMipLevels;
+        desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat;
+        desc.Usage          = D3D11_USAGE_DEFAULT;
+        desc.BindFlags      = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+        desc.CPUAccessFlags = 0;
+        desc.MiscFlags      = 0;
+
+        HRESULT result = device->CreateTexture3D(&desc, nullptr, &mSwizzleTexture);
+
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create internal swizzle texture, result: 0x%X.", result);
+        }
+
+        d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleTexture");
+    }
+
+    *outTexture = mSwizzleTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel,
+                                                      const d3d11::RenderTargetView **outRTV)
+{
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+    ASSERT(outRTV);
+
+    if (!mSwizzleRenderTargets[mipLevel].valid())
+    {
+        ID3D11Resource *swizzleTexture = nullptr;
+        ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format =
+            mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+        rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
+        rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
+        rtvDesc.Texture3D.FirstWSlice = 0;
+        rtvDesc.Texture3D.WSize       = static_cast<UINT>(-1);
+
+        ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture,
+                                              &mSwizzleRenderTargets[mipLevel]));
+        mSwizzleRenderTargets[mipLevel].setDebugName("TexStorage3D.SwizzleRTV");
+    }
+
+    *outRTV = &mSwizzleRenderTargets[mipLevel];
+    return gl::NoError();
+}
+
+TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer,
+                                                   GLenum internalformat,
+                                                   bool renderTarget,
+                                                   GLsizei width,
+                                                   GLsizei height,
+                                                   GLsizei depth,
+                                                   int levels)
+    : TextureStorage11(
+          renderer,
+          GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+          GetTextureMiscFlags(internalformat,
+                              renderer->getRenderer11DeviceCaps(),
+                              renderTarget,
+                              levels),
+          internalformat)
+{
+    mTexture        = nullptr;
+    mSwizzleTexture = nullptr;
+
+    // adjust size if needed for compressed textures
+    d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
+
+    mMipLevels     = mTopLevel + levels;
+    mTextureWidth  = width;
+    mTextureHeight = height;
+    mTextureDepth  = depth;
+}
+
+TextureStorage11_2DArray::~TextureStorage11_2DArray()
+{
+    for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++)
+    {
+        if (i->second)
+        {
+            i->second->verifyAssociatedStorageValid(this);
+
+            // We must let the Images recover their data before we delete it from the
+            // TextureStorage.
+            i->second->recoverFromAssociatedStorage();
+        }
+    }
+    mAssociatedImages.clear();
+
+    SafeRelease(mTexture);
+    SafeRelease(mSwizzleTexture);
+
+    for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
+    {
+        SafeDelete(i->second);
+    }
+    mRenderTargets.clear();
+}
+
+void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+    const GLint level       = index.mipIndex;
+    const GLint layerTarget = index.layerIndex;
+
+    ASSERT(0 <= level && level < getLevelCount());
+
+    if (0 <= level && level < getLevelCount())
+    {
+        LevelLayerKey key(level, layerTarget);
+        mAssociatedImages[key] = image;
+    }
+}
+
+void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index,
+                                                          Image11 *expectedImage)
+{
+    const GLint level       = index.mipIndex;
+    const GLint layerTarget = index.layerIndex;
+
+    LevelLayerKey key(level, layerTarget);
+
+    // This validation check should never return false. It means the Image/TextureStorage
+    // association is broken.
+    bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
+                     (mAssociatedImages[key] == expectedImage));
+    ASSERT(retValue);
+}
+
+// disassociateImage allows an Image to end its association with a Storage.
+void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index,
+                                                 Image11 *expectedImage)
+{
+    const GLint level       = index.mipIndex;
+    const GLint layerTarget = index.layerIndex;
+
+    LevelLayerKey key(level, layerTarget);
+
+    bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
+                                    (mAssociatedImages[key] == expectedImage));
+    ASSERT(imageAssociationCorrect);
+    mAssociatedImages[key] = nullptr;
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index,
+                                                           Image11 *incomingImage)
+{
+    const GLint level       = index.mipIndex;
+    const GLint layerTarget = index.layerIndex;
+
+    LevelLayerKey key(level, layerTarget);
+
+    if (mAssociatedImages.find(key) != mAssociatedImages.end())
+    {
+        if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage)
+        {
+            // Ensure that the Image is still associated with this TextureStorage.
+            mAssociatedImages[key]->verifyAssociatedStorageValid(this);
+
+            // Force the image to recover from storage before its data is overwritten.
+            // This will reset mAssociatedImages[level] to nullptr too.
+            ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage());
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource)
+{
+    // if the width, height or depth is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+    {
+        ASSERT(mMipLevels > 0);
+
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width              = mTextureWidth;
+        desc.Height             = mTextureHeight;
+        desc.MipLevels          = mMipLevels;
+        desc.ArraySize          = mTextureDepth;
+        desc.Format             = mFormatInfo.texFormat;
+        desc.SampleDesc.Count   = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage              = D3D11_USAGE_DEFAULT;
+        desc.BindFlags          = getBindFlags();
+        desc.CPUAccessFlags     = 0;
+        desc.MiscFlags          = getMiscFlags();
+
+        HRESULT result = device->CreateTexture2D(&desc, nullptr, &mTexture);
+
+        // this can happen from windows TDR
+        if (d3d11::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create 2D array texture storage, result: 0x%X.", result);
+        }
+        else if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create 2D array texture storage, result: 0x%X.", result);
+        }
+
+        d3d11::SetDebugName(mTexture, "TexStorage2DArray.Texture");
+    }
+
+    *outResource = mTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::createSRV(int baseLevel,
+                                              int mipLevels,
+                                              DXGI_FORMAT format,
+                                              ID3D11Resource *texture,
+                                              ID3D11ShaderResourceView **outSRV) const
+{
+    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    srvDesc.Format                         = format;
+    srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+    srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
+    srvDesc.Texture2DArray.MipLevels       = mipLevels;
+    srvDesc.Texture2DArray.FirstArraySlice = 0;
+    srvDesc.Texture2DArray.ArraySize       = mTextureDepth;
+
+    ID3D11Device *device = mRenderer->getDevice();
+    HRESULT result       = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
+
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to create internal texture storage SRV, result: 0x%X.", result);
+    }
+
+    d3d11::SetDebugName(*outSRV, "TexStorage2DArray.SRV");
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::createRenderTargetSRV(ID3D11Resource *texture,
+                                                          const gl::ImageIndex &index,
+                                                          DXGI_FORMAT resourceFormat,
+                                                          ID3D11ShaderResourceView **srv) const
+{
+    ID3D11Device *device = mRenderer->getDevice();
+    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    srvDesc.Format                         = resourceFormat;
+    srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+    srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
+    srvDesc.Texture2DArray.MipLevels       = 1;
+    srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex;
+    srvDesc.Texture2DArray.ArraySize       = 1;
+
+    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, srv);
+
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(
+            GL_OUT_OF_MEMORY,
+            "Failed to create internal shader resource view for texture storage, result: 0x%X.",
+            result);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index,
+                                                    RenderTargetD3D **outRT)
+{
+    ASSERT(index.hasLayer());
+
+    const int mipLevel = index.mipIndex;
+    const int layer    = index.layerIndex;
+
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+    LevelLayerKey key(mipLevel, layer);
+    if (mRenderTargets.find(key) == mRenderTargets.end())
+    {
+        ID3D11Device *device = mRenderer->getDevice();
+        HRESULT result;
+
+        ID3D11Resource *texture = nullptr;
+        ANGLE_TRY(getResource(&texture));
+        ID3D11ShaderResourceView *srv;
+        ANGLE_TRY(createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv));
+        ID3D11ShaderResourceView *blitSRV;
+        if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
+        {
+            gl::Error error =
+                createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV);
+            if (error.isError())
+            {
+                SafeRelease(srv);
+                return error;
+            }
+        }
+        else
+        {
+            blitSRV = srv;
+            blitSRV->AddRef();
+        }
+
+        d3d11::SetDebugName(srv, "TexStorage2DArray.RenderTargetSRV");
+
+        if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format                         = mFormatInfo.rtvFormat;
+            rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+            rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
+            rtvDesc.Texture2DArray.FirstArraySlice = layer;
+            rtvDesc.Texture2DArray.ArraySize       = 1;
+
+            d3d11::RenderTargetView rtv;
+            gl::Error err = mRenderer->allocateResource(rtvDesc, texture, &rtv);
+            if (err.isError())
+            {
+                SafeRelease(srv);
+                SafeRelease(blitSRV);
+                return err;
+            }
+
+            rtv.setDebugName("TexStorage2DArray.RenderTargetRTV");
+
+            mRenderTargets[key] = new TextureRenderTarget11(
+                std::move(rtv), texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+                getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
+
+            // RenderTarget will take ownership of these resources
+            SafeRelease(srv);
+            SafeRelease(blitSRV);
+        }
+        else
+        {
+            ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+
+            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+            dsvDesc.Format                         = mFormatInfo.dsvFormat;
+            dsvDesc.ViewDimension                  = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+            dsvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
+            dsvDesc.Texture2DArray.FirstArraySlice = layer;
+            dsvDesc.Texture2DArray.ArraySize       = 1;
+            dsvDesc.Flags                          = 0;
+
+            ID3D11DepthStencilView *dsv;
+            result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+
+            ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                SafeRelease(srv);
+                SafeRelease(blitSRV);
+                return gl::Error(GL_OUT_OF_MEMORY,
+                                 "Failed to create TexStorage2DArray DSV. Result: 0x%X.", result);
+            }
+
+            d3d11::SetDebugName(dsv, "TexStorage2DArray.RenderTargetDSV");
+
+            mRenderTargets[key] = new TextureRenderTarget11(
+                dsv, texture, srv, mFormatInfo.internalFormat, getFormatSet(),
+                getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
+
+            // RenderTarget will take ownership of these resources
+            SafeRelease(dsv);
+            SafeRelease(srv);
+            SafeRelease(blitSRV);
+        }
+    }
+
+    ASSERT(outRT);
+    *outRT = mRenderTargets[key];
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+    if (!mSwizzleTexture)
+    {
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width              = mTextureWidth;
+        desc.Height             = mTextureHeight;
+        desc.MipLevels          = mMipLevels;
+        desc.ArraySize          = mTextureDepth;
+        desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat;
+        desc.SampleDesc.Count   = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage              = D3D11_USAGE_DEFAULT;
+        desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+        desc.CPUAccessFlags     = 0;
+        desc.MiscFlags          = 0;
+
+        HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture);
+
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create internal swizzle texture, result: 0x%X.", result);
+        }
+
+        d3d11::SetDebugName(*outTexture, "TexStorage2DArray.SwizzleTexture");
+    }
+
+    *outTexture = mSwizzleTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel,
+                                                           const d3d11::RenderTargetView **outRTV)
+{
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+    ASSERT(outRTV);
+
+    if (!mSwizzleRenderTargets[mipLevel].valid())
+    {
+        ID3D11Resource *swizzleTexture = nullptr;
+        ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format =
+            mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+        rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+        rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
+        rtvDesc.Texture2DArray.FirstArraySlice = 0;
+        rtvDesc.Texture2DArray.ArraySize       = mTextureDepth;
+
+        ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture,
+                                              &mSwizzleRenderTargets[mipLevel]));
+    }
+
+    *outRTV = &mSwizzleRenderTargets[mipLevel];
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureStorage11::DropStencil>
+TextureStorage11_2DArray::ensureDropStencilTexture()
+{
+    if (mDropStencilTexture)
+    {
+        return DropStencil::ALREADY_EXISTS;
+    }
+
+    D3D11_TEXTURE2D_DESC dropDesc = {};
+    dropDesc.ArraySize            = mTextureDepth;
+    dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+    dropDesc.CPUAccessFlags       = 0;
+    dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
+    dropDesc.Height               = mTextureHeight;
+    dropDesc.MipLevels            = mMipLevels;
+    dropDesc.MiscFlags            = 0;
+    dropDesc.SampleDesc.Count     = 1;
+    dropDesc.SampleDesc.Quality   = 0;
+    dropDesc.Usage                = D3D11_USAGE_DEFAULT;
+    dropDesc.Width                = mTextureWidth;
+
+    ID3D11Device *device = mRenderer->getDevice();
+
+    HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture);
+    if (FAILED(hr))
+    {
+        return gl::InternalError() << "Error creating drop stencil texture.";
+    }
+    d3d11::SetDebugName(mDropStencilTexture, "TexStorage2DArray.DropStencil");
+
+    std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
+
+    ANGLE_TRY(initDropStencilTexture(
+        gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
+
+    return DropStencil::CREATED;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
new file mode 100644
index 0000000..195d432
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
@@ -0,0 +1,441 @@
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived
+// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
+
+#include "libANGLE/Error.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include <array>
+#include <map>
+
+namespace gl
+{
+struct ImageIndex;
+}
+
+namespace rx
+{
+class EGLImageD3D;
+class RenderTargetD3D;
+class RenderTarget11;
+class Renderer11;
+class SwapChain11;
+class Image11;
+struct Renderer11DeviceCaps;
+
+class TextureStorage11 : public TextureStorage
+{
+  public:
+    ~TextureStorage11() override;
+
+    static DWORD GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget);
+    static DWORD GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels);
+
+    UINT getBindFlags() const;
+    UINT getMiscFlags() const;
+    const d3d11::Format &getFormatSet() const;
+    gl::Error getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV);
+    gl::Error generateSwizzles(const gl::SwizzleState &swizzleTarget);
+    void markLevelDirty(int mipLevel);
+    void markDirty();
+
+    gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource,
+                                     const gl::ImageIndex &index, const gl::Box &copyArea);
+
+    gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
+                                   const gl::ImageIndex &index, const gl::Box &region);
+
+    // TextureStorage virtual functions
+    int getTopLevel() const override;
+    bool isRenderTarget() const override;
+    bool isManaged() const override;
+    bool supportsNativeMipmapFunction() const override;
+    int getLevelCount() const override;
+    gl::Error generateMipmap(const gl::ImageIndex &sourceIndex,
+                             const gl::ImageIndex &destIndex) override;
+    gl::Error copyToStorage(TextureStorage *destStorage) override;
+    gl::Error setData(const gl::ImageIndex &index,
+                      ImageD3D *image,
+                      const gl::Box *destBox,
+                      GLenum type,
+                      const gl::PixelUnpackState &unpack,
+                      const uint8_t *pixelData) override;
+
+    virtual gl::Error getSRV(const gl::TextureState &textureState,
+                             ID3D11ShaderResourceView **outSRV);
+    virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
+    virtual gl::Error getResource(ID3D11Resource **outResource) = 0;
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0;
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0;
+    virtual void verifyAssociatedImageValid(const gl::ImageIndex &index,
+                                            Image11 *expectedImage) = 0;
+    virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0;
+
+  protected:
+    TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags, GLenum internalFormat);
+    int getLevelWidth(int mipLevel) const;
+    int getLevelHeight(int mipLevel) const;
+    int getLevelDepth(int mipLevel) const;
+
+    // Some classes (e.g. TextureStorage11_2D) will override getMippedResource.
+    virtual gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); }
+
+    virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0;
+    virtual gl::Error getSwizzleRenderTarget(int mipLevel,
+                                             const d3d11::RenderTargetView **outRTV) = 0;
+    gl::Error getSRVLevel(int mipLevel, bool blitSRV, ID3D11ShaderResourceView **outSRV);
+
+    // Get a version of a depth texture with only depth information, not stencil.
+    enum DropStencil
+    {
+        CREATED,
+        ALREADY_EXISTS
+    };
+    virtual gl::ErrorOrResult<DropStencil> ensureDropStencilTexture();
+    gl::Error initDropStencilTexture(const gl::ImageIndexIterator &it);
+
+    // The baseLevel parameter should *not* have mTopLevel applied.
+    virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                ID3D11ShaderResourceView **outSRV) const = 0;
+
+    void verifySwizzleExists(const gl::SwizzleState &swizzleState);
+
+    // Clear all cached non-swizzle SRVs and invalidate the swizzle cache.
+    void clearSRVCache();
+
+    Renderer11 *mRenderer;
+    int mTopLevel;
+    unsigned int mMipLevels;
+
+    const d3d11::Format &mFormatInfo;
+    unsigned int mTextureWidth;
+    unsigned int mTextureHeight;
+    unsigned int mTextureDepth;
+
+    gl::SwizzleState mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+    ID3D11Texture2D *mDropStencilTexture;
+
+  private:
+    const UINT mBindFlags;
+    const UINT mMiscFlags;
+
+    struct SRVKey
+    {
+        SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil);
+
+        bool operator<(const SRVKey &rhs) const;
+
+        int baseLevel    = 0;  // Without mTopLevel applied.
+        int mipLevels    = 0;
+        bool swizzle     = false;
+        bool dropStencil = false;
+    };
+    typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache;
+
+    gl::Error getCachedOrCreateSRV(const SRVKey &key, ID3D11ShaderResourceView **outSRV);
+
+    SRVCache mSrvCache;
+    std::array<ID3D11ShaderResourceView *, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> mLevelSRVs;
+    std::array<ID3D11ShaderResourceView *, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> mLevelBlitSRVs;
+};
+
+class TextureStorage11_2D : public TextureStorage11
+{
+  public:
+    TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain);
+    TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false);
+    ~TextureStorage11_2D() override;
+
+    gl::Error getResource(ID3D11Resource **outResource) override;
+    gl::Error getMippedResource(ID3D11Resource **outResource) override;
+    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+    gl::Error copyToStorage(TextureStorage *destStorage) override;
+
+    void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+    void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+
+    gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
+
+  protected:
+    gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
+    gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+    gl::ErrorOrResult<DropStencil> ensureDropStencilTexture() override;
+
+    gl::Error ensureTextureExists(int mipLevels);
+
+  private:
+    gl::Error createSRV(int baseLevel,
+                        int mipLevels,
+                        DXGI_FORMAT format,
+                        ID3D11Resource *texture,
+                        ID3D11ShaderResourceView **outSRV) const override;
+
+    ID3D11Texture2D *mTexture;
+    RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+    bool mHasKeyedMutex;
+
+    // These are members related to the zero max-LOD workaround.
+    // D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero).
+    // These members are used to work around this limitation.
+    // Usually only mTexture XOR mLevelZeroTexture will exist.
+    // For example, if an app creates a texture with only one level, then 9_3 will only create mLevelZeroTexture.
+    // However, in some scenarios, both textures have to be created. This incurs additional memory overhead.
+    // One example of this is an application that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture.
+    // A more likely example is an app that creates an empty texture, renders to it, and then calls glGenerateMipmap
+    // TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been created to save memory.
+    ID3D11Texture2D *mLevelZeroTexture;
+    RenderTarget11 *mLevelZeroRenderTarget;
+    bool mUseLevelZeroTexture;
+
+    // Swizzle-related variables
+    ID3D11Texture2D *mSwizzleTexture;
+    d3d11::RenderTargetView mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+    Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_External : public TextureStorage11
+{
+  public:
+    TextureStorage11_External(Renderer11 *renderer,
+                              egl::Stream *stream,
+                              const egl::Stream::GLTextureDescription &glDesc);
+    ~TextureStorage11_External() override;
+
+    gl::Error getResource(ID3D11Resource **outResource) override;
+    gl::Error getMippedResource(ID3D11Resource **outResource) override;
+    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+    gl::Error copyToStorage(TextureStorage *destStorage) override;
+
+    void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+    void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+
+  protected:
+    gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
+    gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+  private:
+    gl::Error createSRV(int baseLevel,
+                        int mipLevels,
+                        DXGI_FORMAT format,
+                        ID3D11Resource *texture,
+                        ID3D11ShaderResourceView **outSRV) const override;
+
+    ID3D11Texture2D *mTexture;
+    int mSubresourceIndex;
+    bool mHasKeyedMutex;
+
+    Image11 *mAssociatedImage;
+};
+
+class TextureStorage11_EGLImage final : public TextureStorage11
+{
+  public:
+    TextureStorage11_EGLImage(Renderer11 *renderer,
+                              EGLImageD3D *eglImage,
+                              RenderTarget11 *renderTarget11);
+    ~TextureStorage11_EGLImage() override;
+
+    gl::Error getResource(ID3D11Resource **outResource) override;
+    gl::Error getSRV(const gl::TextureState &textureState,
+                     ID3D11ShaderResourceView **outSRV) override;
+    gl::Error getMippedResource(ID3D11Resource **outResource) override;
+    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+    gl::Error copyToStorage(TextureStorage *destStorage) override;
+
+    void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+    void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+
+    gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
+
+  protected:
+    gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
+    gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+  private:
+    // Check if the EGL image's render target has been updated due to orphaning and delete
+    // any SRVs and other resources based on the image's old render target.
+    gl::Error checkForUpdatedRenderTarget();
+
+    gl::Error createSRV(int baseLevel,
+                        int mipLevels,
+                        DXGI_FORMAT format,
+                        ID3D11Resource *texture,
+                        ID3D11ShaderResourceView **outSRV) const override;
+
+    gl::Error getImageRenderTarget(RenderTarget11 **outRT) const;
+
+    EGLImageD3D *mImage;
+    uintptr_t mCurrentRenderTarget;
+
+    // Swizzle-related variables
+    ID3D11Texture2D *mSwizzleTexture;
+    std::vector<d3d11::RenderTargetView> mSwizzleRenderTargets;
+};
+
+class TextureStorage11_Cube : public TextureStorage11
+{
+  public:
+    TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
+    ~TextureStorage11_Cube() override;
+
+    UINT getSubresourceIndex(const gl::ImageIndex &index) const override;
+
+    gl::Error getResource(ID3D11Resource **outResource) override;
+    gl::Error getMippedResource(ID3D11Resource **outResource) override;
+    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+    gl::Error copyToStorage(TextureStorage *destStorage) override;
+
+    void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+    void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+
+    gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
+
+  protected:
+    gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
+    gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+    gl::ErrorOrResult<DropStencil> ensureDropStencilTexture() override;
+
+    gl::Error ensureTextureExists(int mipLevels);
+
+  private:
+    gl::Error createSRV(int baseLevel,
+                        int mipLevels,
+                        DXGI_FORMAT format,
+                        ID3D11Resource *texture,
+                        ID3D11ShaderResourceView **outSRV) const override;
+    gl::Error createRenderTargetSRV(ID3D11Resource *texture,
+                                    const gl::ImageIndex &index,
+                                    DXGI_FORMAT resourceFormat,
+                                    ID3D11ShaderResourceView **srv) const;
+
+    static const size_t CUBE_FACE_COUNT = 6;
+
+    ID3D11Texture2D *mTexture;
+    RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+    // Level-zero workaround members. See TextureStorage11_2D's workaround members for a description.
+    ID3D11Texture2D *mLevelZeroTexture;
+    RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT];
+    bool mUseLevelZeroTexture;
+
+    ID3D11Texture2D *mSwizzleTexture;
+    d3d11::RenderTargetView mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+    Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_3D : public TextureStorage11
+{
+  public:
+    TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
+                        GLsizei width, GLsizei height, GLsizei depth, int levels);
+    ~TextureStorage11_3D() override;
+
+    gl::Error getResource(ID3D11Resource **outResource) override;
+
+    // Handles both layer and non-layer RTs
+    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+    void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+    void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+
+  protected:
+    gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
+    gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+  private:
+    gl::Error createSRV(int baseLevel,
+                        int mipLevels,
+                        DXGI_FORMAT format,
+                        ID3D11Resource *texture,
+                        ID3D11ShaderResourceView **outSRV) const override;
+
+    typedef std::pair<int, int> LevelLayerKey;
+    typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
+    RenderTargetMap mLevelLayerRenderTargets;
+
+    RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+    ID3D11Texture3D *mTexture;
+    ID3D11Texture3D *mSwizzleTexture;
+    d3d11::RenderTargetView mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+    Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_2DArray : public TextureStorage11
+{
+  public:
+    TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
+                             GLsizei width, GLsizei height, GLsizei depth, int levels);
+    ~TextureStorage11_2DArray() override;
+
+    gl::Error getResource(ID3D11Resource **outResource) override;
+    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+    void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+    void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+
+  protected:
+    gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
+    gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+    gl::ErrorOrResult<DropStencil> ensureDropStencilTexture() override;
+
+  private:
+    gl::Error createSRV(int baseLevel,
+                        int mipLevels,
+                        DXGI_FORMAT format,
+                        ID3D11Resource *texture,
+                        ID3D11ShaderResourceView **outSRV) const override;
+    gl::Error createRenderTargetSRV(ID3D11Resource *texture,
+                                    const gl::ImageIndex &index,
+                                    DXGI_FORMAT resourceFormat,
+                                    ID3D11ShaderResourceView **srv) const;
+
+    typedef std::pair<int, int> LevelLayerKey;
+    typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
+    RenderTargetMap mRenderTargets;
+
+    ID3D11Texture2D *mTexture;
+
+    ID3D11Texture2D *mSwizzleTexture;
+    d3d11::RenderTargetView mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+    typedef std::map<LevelLayerKey, Image11*> ImageMap;
+    ImageMap mAssociatedImages;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
new file mode 100644
index 0000000..39b293f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
@@ -0,0 +1,102 @@
+//
+// 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.
+//
+
+// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
+
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+TransformFeedback11::TransformFeedback11(const gl::TransformFeedbackState &state,
+                                         Renderer11 *renderer)
+    : TransformFeedbackImpl(state),
+      mRenderer(renderer),
+      mIsDirty(true),
+      mBuffers(state.getIndexedBuffers().size(), nullptr),
+      mBufferOffsets(state.getIndexedBuffers().size(), 0)
+{
+}
+
+TransformFeedback11::~TransformFeedback11()
+{
+}
+
+void TransformFeedback11::begin(GLenum primitiveMode)
+{
+}
+
+void TransformFeedback11::end()
+{
+    if (mRenderer->getWorkarounds().flushAfterEndingTransformFeedback)
+    {
+        mRenderer->getDeviceContext()->Flush();
+    }
+}
+
+void TransformFeedback11::pause()
+{
+}
+
+void TransformFeedback11::resume()
+{
+}
+
+void TransformFeedback11::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+{
+}
+
+void TransformFeedback11::bindIndexedBuffer(size_t index,
+                                            const OffsetBindingPointer<gl::Buffer> &binding)
+{
+    mIsDirty              = true;
+    mBufferOffsets[index] = static_cast<UINT>(binding.getOffset());
+}
+
+void TransformFeedback11::onApply()
+{
+    mIsDirty = false;
+
+    // Change all buffer offsets to -1 so that if any of them need to be re-applied, the are set to
+    // append
+    std::fill(mBufferOffsets.begin(), mBufferOffsets.end(), -1);
+}
+
+bool TransformFeedback11::isDirty() const
+{
+    return mIsDirty;
+}
+
+UINT TransformFeedback11::getNumSOBuffers() const
+{
+    return static_cast<UINT>(mBuffers.size());
+}
+
+gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> TransformFeedback11::getSOBuffers()
+{
+    for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++)
+    {
+        const auto &binding = mState.getIndexedBuffer(bindingIdx);
+        if (binding.get() != nullptr)
+        {
+            Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
+            ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+                             mBuffers[bindingIdx]);
+        }
+    }
+
+    return &mBuffers;
+}
+
+const std::vector<UINT> &TransformFeedback11::getSOBufferOffsets() const
+{
+    return mBufferOffsets;
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
new file mode 100644
index 0000000..01879d6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
@@ -0,0 +1,54 @@
+//
+// 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.
+//
+
+// TransformFeedback11.h: Implements the abstract rx::TransformFeedbackImpl class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
+
+#include "common/platform.h"
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class Renderer11;
+
+class TransformFeedback11 : public TransformFeedbackImpl
+{
+  public:
+    TransformFeedback11(const gl::TransformFeedbackState &state, Renderer11 *renderer);
+    ~TransformFeedback11() override;
+
+    void begin(GLenum primitiveMode) override;
+    void end() override;
+    void pause() override;
+    void resume() override;
+
+    void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
+    void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+
+    void onApply();
+
+    bool isDirty() const;
+
+    UINT getNumSOBuffers() const;
+    gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> getSOBuffers();
+    const std::vector<UINT> &getSOBufferOffsets() const;
+
+  private:
+    Renderer11 *mRenderer;
+
+    bool mIsDirty;
+    std::vector<ID3D11Buffer *> mBuffers;
+    std::vector<UINT> mBufferOffsets;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
new file mode 100644
index 0000000..29185a9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
@@ -0,0 +1,100 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Trim11.cpp: Trim support utility class.
+
+#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#if defined (ANGLE_ENABLE_WINDOWS_STORE)
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+#include <windows.applicationmodel.core.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::ApplicationModel;
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+#endif
+
+namespace rx
+{
+
+Trim11::Trim11(rx::Renderer11 *renderer)
+    : mRenderer(renderer)
+{
+    bool result = true;
+    result = registerForRendererTrimRequest();
+    ASSERT(result);
+}
+
+Trim11::~Trim11()
+{
+    unregisterForRendererTrimRequest();
+}
+
+void Trim11::trim()
+{
+    if (!mRenderer)
+    {
+        return;
+    }
+
+#if defined (ANGLE_ENABLE_WINDOWS_STORE)
+    ID3D11Device* device = mRenderer->getDevice();
+    IDXGIDevice3 *dxgiDevice3 = d3d11::DynamicCastComObject<IDXGIDevice3>(device);
+    if (dxgiDevice3)
+    {
+        dxgiDevice3->Trim();
+    }
+    SafeRelease(dxgiDevice3);
+#endif
+}
+
+bool Trim11::registerForRendererTrimRequest()
+{
+#if defined (ANGLE_ENABLE_WINDOWS_STORE)
+    ICoreApplication* coreApplication = nullptr;
+    HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication);
+    if (SUCCEEDED(result))
+    {
+        auto suspendHandler = Callback<IEventHandler<SuspendingEventArgs*>>(
+            [this](IInspectable*, ISuspendingEventArgs*) -> HRESULT
+        {
+            trim();
+            return S_OK;
+        });
+        result = coreApplication->add_Suspending(suspendHandler.Get(), &mApplicationSuspendedEventToken);
+    }
+    SafeRelease(coreApplication);
+
+    if (FAILED(result))
+    {
+        return false;
+    }
+#endif
+    return true;
+}
+
+void Trim11::unregisterForRendererTrimRequest()
+{
+#if defined (ANGLE_ENABLE_WINDOWS_STORE)
+    if (mApplicationSuspendedEventToken.value != 0)
+    {
+        ICoreApplication* coreApplication = nullptr;
+        if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication)))
+        {
+            coreApplication->remove_Suspending(mApplicationSuspendedEventToken);
+        }
+        mApplicationSuspendedEventToken.value = 0;
+        SafeRelease(coreApplication);
+    }
+#endif
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h
new file mode 100644
index 0000000..69fa05a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Trim11.h: Trim support utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+#include <EventToken.h>
+#endif
+
+namespace rx
+{
+class Renderer11;
+
+class Trim11 : angle::NonCopyable
+{
+  public:
+    explicit Trim11(Renderer11 *renderer);
+    ~Trim11();
+
+  private:
+    Renderer11 *mRenderer;
+#if defined (ANGLE_ENABLE_WINDOWS_STORE)
+    EventRegistrationToken mApplicationSuspendedEventToken;
+#endif
+
+    void trim();
+    bool registerForRendererTrimRequest();
+    void unregisterForRendererTrimRequest();
+};
+
+}
+
+#endif   // LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
new file mode 100644
index 0000000..73814a7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -0,0 +1,239 @@
+//
+// Copyright 2016 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.
+//
+// VertexArray11:
+//   Implementation of rx::VertexArray11.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+
+#include "common/bitset_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+VertexArray11::VertexArray11(const gl::VertexArrayState &data)
+    : VertexArrayImpl(data),
+      mAttributeStorageTypes(data.getMaxAttribs(), VertexStorageType::CURRENT_VALUE),
+      mTranslatedAttribs(data.getMaxAttribs()),
+      mCurrentBuffers(data.getMaxAttribs())
+{
+    for (size_t attribIndex = 0; attribIndex < mCurrentBuffers.size(); ++attribIndex)
+    {
+        mOnBufferDataDirty.emplace_back(this, attribIndex);
+    }
+}
+
+VertexArray11::~VertexArray11()
+{
+    for (auto &buffer : mCurrentBuffers)
+    {
+        if (buffer.get())
+        {
+            buffer.set(nullptr);
+        }
+    }
+}
+
+void VertexArray11::syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits)
+{
+    for (auto dirtyBit : dirtyBits)
+    {
+        if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
+            continue;
+
+        size_t index = gl::VertexArray::GetAttribIndex(dirtyBit);
+        // TODO(jiawei.shao@intel.com): Vertex Attrib Bindings
+        ASSERT(index == mData.getBindingIndexFromAttribIndex(index));
+        mAttribsToUpdate.set(index);
+    }
+}
+
+void VertexArray11::flushAttribUpdates(const gl::State &state)
+{
+    const gl::Program *program  = state.getProgram();
+    const auto &activeLocations = program->getActiveAttribLocationsMask();
+
+    if (mAttribsToUpdate.any())
+    {
+        // Skip attrib locations the program doesn't use.
+        gl::AttributesMask activeToUpdate = mAttribsToUpdate & activeLocations;
+
+        for (auto toUpdateIndex : activeToUpdate)
+        {
+            mAttribsToUpdate.reset(toUpdateIndex);
+            updateVertexAttribStorage(toUpdateIndex);
+        }
+    }
+}
+
+void VertexArray11::updateVertexAttribStorage(size_t attribIndex)
+{
+    const auto &attrib = mData.getVertexAttribute(attribIndex);
+    const auto &binding = mData.getBindingFromAttribIndex(attribIndex);
+
+    // Note: having an unchanged storage type doesn't mean the attribute is clean.
+    auto oldStorageType = mAttributeStorageTypes[attribIndex];
+    auto newStorageType = ClassifyAttributeStorage(attrib, binding);
+
+    mAttributeStorageTypes[attribIndex] = newStorageType;
+
+    if (newStorageType == VertexStorageType::DYNAMIC)
+    {
+        if (oldStorageType != VertexStorageType::DYNAMIC)
+        {
+            // Sync dynamic attribs in a different set.
+            mAttribsToTranslate.reset(attribIndex);
+            mDynamicAttribsMask.set(attribIndex);
+        }
+    }
+    else
+    {
+        mAttribsToTranslate.set(attribIndex);
+
+        if (oldStorageType == VertexStorageType::DYNAMIC)
+        {
+            ASSERT(mDynamicAttribsMask[attribIndex]);
+            mDynamicAttribsMask.reset(attribIndex);
+        }
+    }
+
+    gl::Buffer *oldBufferGL = mCurrentBuffers[attribIndex].get();
+    gl::Buffer *newBufferGL = binding.buffer.get();
+    Buffer11 *oldBuffer11   = oldBufferGL ? GetImplAs<Buffer11>(oldBufferGL) : nullptr;
+    Buffer11 *newBuffer11   = newBufferGL ? GetImplAs<Buffer11>(newBufferGL) : nullptr;
+
+    if (oldBuffer11 != newBuffer11 || oldStorageType != newStorageType)
+    {
+        // Note that for static callbacks, promotion to a static buffer from a dynamic buffer means
+        // we need to tag dynamic buffers with static callbacks.
+        OnBufferDataDirtyChannel *newChannel = nullptr;
+        if (newBuffer11 != nullptr)
+        {
+            switch (newStorageType)
+            {
+                case VertexStorageType::DIRECT:
+                    newChannel = newBuffer11->getDirectBroadcastChannel();
+                    break;
+                case VertexStorageType::STATIC:
+                case VertexStorageType::DYNAMIC:
+                    newChannel = newBuffer11->getStaticBroadcastChannel();
+                    break;
+                default:
+                    break;
+            }
+        }
+        mOnBufferDataDirty[attribIndex].bind(newChannel);
+        mCurrentBuffers[attribIndex] = binding.buffer;
+    }
+}
+
+bool VertexArray11::hasDynamicAttrib(const gl::State &state)
+{
+    flushAttribUpdates(state);
+    return mDynamicAttribsMask.any();
+}
+
+gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
+                                                      const gl::State &state,
+                                                      GLint start,
+                                                      GLsizei count,
+                                                      GLsizei instances)
+{
+    flushAttribUpdates(state);
+
+    const gl::Program *program  = state.getProgram();
+    const auto &activeLocations = program->getActiveAttribLocationsMask();
+    const auto &attribs         = mData.getVertexAttributes();
+    const auto &bindings        = mData.getVertexBindings();
+
+    if (mAttribsToTranslate.any())
+    {
+        // Skip attrib locations the program doesn't use, saving for the next frame.
+        gl::AttributesMask dirtyActiveAttribs = (mAttribsToTranslate & activeLocations);
+
+        for (auto dirtyAttribIndex : dirtyActiveAttribs)
+        {
+            mAttribsToTranslate.reset(dirtyAttribIndex);
+
+            auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex];
+            const auto &currentValue = state.getVertexAttribCurrentValue(dirtyAttribIndex);
+
+            // Record basic attrib info
+            translatedAttrib->attribute = &attribs[dirtyAttribIndex];
+            translatedAttrib->binding   = &bindings[translatedAttrib->attribute->bindingIndex];
+            translatedAttrib->currentValueType = currentValue.Type;
+            translatedAttrib->divisor          = translatedAttrib->binding->divisor;
+
+            switch (mAttributeStorageTypes[dirtyAttribIndex])
+            {
+                case VertexStorageType::DIRECT:
+                    VertexDataManager::StoreDirectAttrib(translatedAttrib);
+                    break;
+                case VertexStorageType::STATIC:
+                {
+                    ANGLE_TRY(VertexDataManager::StoreStaticAttrib(translatedAttrib));
+                    break;
+                }
+                case VertexStorageType::CURRENT_VALUE:
+                    // Current value attribs are managed by the StateManager11.
+                    break;
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        }
+    }
+
+    if (mDynamicAttribsMask.any())
+    {
+        auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+
+        for (auto dynamicAttribIndex : activeDynamicAttribs)
+        {
+            auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex];
+            const auto &currentValue = state.getVertexAttribCurrentValue(dynamicAttribIndex);
+
+            // Record basic attrib info
+            dynamicAttrib->attribute        = &attribs[dynamicAttribIndex];
+            dynamicAttrib->binding          = &bindings[dynamicAttrib->attribute->bindingIndex];
+            dynamicAttrib->currentValueType = currentValue.Type;
+            dynamicAttrib->divisor          = dynamicAttrib->binding->divisor;
+        }
+
+        return vertexDataManager->storeDynamicAttribs(&mTranslatedAttribs, activeDynamicAttribs,
+                                                      start, count, instances);
+    }
+
+    return gl::NoError();
+}
+
+const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() const
+{
+    return mTranslatedAttribs;
+}
+
+void VertexArray11::signal(size_t channelID)
+{
+    ASSERT(mAttributeStorageTypes[channelID] != VertexStorageType::CURRENT_VALUE);
+
+    // This can change a buffer's storage, we'll need to re-check.
+    mAttribsToUpdate.set(channelID);
+}
+
+void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count)
+{
+    const gl::Program *program  = state.getProgram();
+    const auto &activeLocations = program->getActiveAttribLocationsMask();
+    mAttribsToUpdate &= ~activeLocations;
+
+    // Promote to static after we clear the dirty attributes, otherwise we can lose dirtyness.
+    auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+    VertexDataManager::PromoteDynamicAttribs(mTranslatedAttribs, activeDynamicAttribs, count);
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
new file mode 100644
index 0000000..4fda434
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
@@ -0,0 +1,66 @@
+//
+// 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.
+//
+
+// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
+
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/signal_utils.h"
+
+namespace rx
+{
+class Renderer11;
+
+class VertexArray11 : public VertexArrayImpl, public OnBufferDataDirtyReceiver
+{
+  public:
+    VertexArray11(const gl::VertexArrayState &data);
+    ~VertexArray11() override;
+
+    void syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits) override;
+    // This will flush any pending attrib updates and then check the dynamic attribs mask.
+    bool hasDynamicAttrib(const gl::State &state);
+    gl::Error updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
+                                           const gl::State &state,
+                                           GLint start,
+                                           GLsizei count,
+                                           GLsizei instances);
+    void clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count);
+
+    const std::vector<TranslatedAttribute> &getTranslatedAttribs() const;
+
+    // SignalReceiver implementation
+    void signal(size_t channelID) override;
+
+  private:
+    void updateVertexAttribStorage(size_t attribIndex);
+    void flushAttribUpdates(const gl::State &state);
+
+    std::vector<VertexStorageType> mAttributeStorageTypes;
+    std::vector<TranslatedAttribute> mTranslatedAttribs;
+
+    // The mask of attributes marked as dynamic.
+    gl::AttributesMask mDynamicAttribsMask;
+
+    // A mask of attributes that need to be re-evaluated.
+    gl::AttributesMask mAttribsToUpdate;
+
+    // A set of attributes we know are dirty, and need to be re-translated.
+    gl::AttributesMask mAttribsToTranslate;
+
+    // We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks.
+    std::vector<BindingPointer<gl::Buffer>> mCurrentBuffers;
+
+    std::vector<OnBufferDataDirtyBinding> mOnBufferDataDirty;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
new file mode 100644
index 0000000..15ca724
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
@@ -0,0 +1,192 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
+{
+    mBuffer             = nullptr;
+    mBufferSize         = 0;
+    mDynamicUsage       = false;
+    mMappedResourceData = nullptr;
+}
+
+VertexBuffer11::~VertexBuffer11()
+{
+    ASSERT(mMappedResourceData == nullptr);
+    SafeRelease(mBuffer);
+}
+
+gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
+{
+    SafeRelease(mBuffer);
+
+    updateSerial();
+
+    if (size > 0)
+    {
+        ID3D11Device *dxDevice = mRenderer->getDevice();
+
+        D3D11_BUFFER_DESC bufferDesc;
+        bufferDesc.ByteWidth           = size;
+        bufferDesc.Usage               = D3D11_USAGE_DYNAMIC;
+        bufferDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
+        bufferDesc.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
+        bufferDesc.MiscFlags           = 0;
+        bufferDesc.StructureByteStride = 0;
+
+        HRESULT result = dxDevice->CreateBuffer(&bufferDesc, nullptr, &mBuffer);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to allocate internal vertex buffer of size, %lu.", size);
+        }
+
+        if (dynamicUsage)
+        {
+            d3d11::SetDebugName(mBuffer, "VertexBuffer11 (dynamic)");
+        }
+        else
+        {
+            d3d11::SetDebugName(mBuffer, "VertexBuffer11 (static)");
+        }
+    }
+
+    mBufferSize   = size;
+    mDynamicUsage = dynamicUsage;
+
+    return gl::NoError();
+}
+
+gl::Error VertexBuffer11::mapResource()
+{
+    if (mMappedResourceData == nullptr)
+    {
+        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+        D3D11_MAPPED_SUBRESOURCE mappedResource;
+
+        HRESULT result =
+            dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
+        }
+
+        mMappedResourceData = reinterpret_cast<uint8_t *>(mappedResource.pData);
+    }
+
+    return gl::NoError();
+}
+
+void VertexBuffer11::hintUnmapResource()
+{
+    if (mMappedResourceData != nullptr)
+    {
+        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+        dxContext->Unmap(mBuffer, 0);
+
+        mMappedResourceData = nullptr;
+    }
+}
+
+gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib,
+                                                const gl::VertexBinding &binding,
+                                                GLenum currentValueType,
+                                                GLint start,
+                                                GLsizei count,
+                                                GLsizei instances,
+                                                unsigned int offset,
+                                                const uint8_t *sourceData)
+{
+    if (!mBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+    }
+
+    int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
+
+    // This will map the resource if it isn't already mapped.
+    ANGLE_TRY(mapResource());
+
+    uint8_t *output = mMappedResourceData + offset;
+
+    const uint8_t *input = sourceData;
+
+    if (instances == 0 || binding.divisor == 0)
+    {
+        input += inputStride * start;
+    }
+
+    gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
+    const D3D_FEATURE_LEVEL featureLevel  = mRenderer->getRenderer11DeviceCaps().featureLevel;
+    const d3d11::VertexFormat &vertexFormatInfo =
+        d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel);
+    ASSERT(vertexFormatInfo.copyFunction != nullptr);
+    vertexFormatInfo.copyFunction(input, inputStride, count, output);
+
+    return gl::NoError();
+}
+
+unsigned int VertexBuffer11::getBufferSize() const
+{
+    return mBufferSize;
+}
+
+gl::Error VertexBuffer11::setBufferSize(unsigned int size)
+{
+    if (size > mBufferSize)
+    {
+        return initialize(size, mDynamicUsage);
+    }
+    else
+    {
+        return gl::NoError();
+    }
+}
+
+gl::Error VertexBuffer11::discard()
+{
+    if (!mBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+    }
+
+    ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result);
+    }
+
+    dxContext->Unmap(mBuffer, 0);
+
+    return gl::NoError();
+}
+
+ID3D11Buffer *VertexBuffer11::getBuffer() const
+{
+    return mBuffer;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
new file mode 100644
index 0000000..038ba42
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
+
+#include <stdint.h>
+
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+namespace rx
+{
+class Renderer11;
+
+class VertexBuffer11 : public VertexBuffer
+{
+  public:
+    explicit VertexBuffer11(Renderer11 *const renderer);
+
+    gl::Error initialize(unsigned int size, bool dynamicUsage) override;
+
+    // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+    // function.
+    gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
+                                    const gl::VertexBinding &binding,
+                                    GLenum currentValueType,
+                                    GLint start,
+                                    GLsizei count,
+                                    GLsizei instances,
+                                    unsigned int offset,
+                                    const uint8_t *sourceData) override;
+
+    unsigned int getBufferSize() const override;
+    gl::Error setBufferSize(unsigned int size) override;
+    gl::Error discard() override;
+
+    void hintUnmapResource() override;
+
+    ID3D11Buffer *getBuffer() const;
+
+  private:
+    ~VertexBuffer11() override;
+    gl::Error mapResource();
+
+    Renderer11 *const mRenderer;
+
+    ID3D11Buffer *mBuffer;
+    unsigned int mBufferSize;
+    bool mDynamicUsage;
+
+    uint8_t *mMappedResourceData;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h
new file mode 100644
index 0000000..5501e36
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// copyvertex.h: Defines D3D11 vertex buffer copying and conversion functions
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_
+
+#include "common/mathutil.h"
+
+namespace rx
+{
+
+// 'alphaDefaultValueBits' gives the default value for the alpha channel (4th component)
+template <typename T, size_t inputComponentCount, size_t outputComponentCount, uint32_t alphaDefaultValueBits>
+inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t componentCount>
+inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized>
+inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <bool isSigned, bool normalized, bool toFloat>
+inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+}
+
+#include "copyvertex.inl"
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl
new file mode 100644
index 0000000..7c5c157
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl
@@ -0,0 +1,386 @@
+//
+// Copyright (c) 2014-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+namespace rx
+{
+
+template <typename T, size_t inputComponentCount, size_t outputComponentCount, uint32_t alphaDefaultValueBits>
+inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+    const size_t attribSize = sizeof(T)* inputComponentCount;
+
+    if (attribSize == stride && inputComponentCount == outputComponentCount)
+    {
+        memcpy(output, input, count * attribSize);
+        return;
+    }
+
+    if (inputComponentCount == outputComponentCount)
+    {
+        for (size_t i = 0; i < count; i++)
+        {
+            const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride));
+            T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount;
+
+            memcpy(offsetOutput, offsetInput, attribSize);
+        }
+        return;
+    }
+
+    const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits);
+    const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
+
+    for (size_t i = 0; i < count; i++)
+    {
+        const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride));
+        T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount;
+
+        memcpy(offsetOutput, offsetInput, attribSize);
+
+        if (inputComponentCount < lastNonAlphaOutputComponent)
+        {
+            // Set the remaining G/B channels to 0.
+            size_t numComponents = (lastNonAlphaOutputComponent - inputComponentCount);
+            memset(&offsetOutput[inputComponentCount], 0, numComponents * sizeof(T));
+        }
+
+        if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+        {
+            // Set the remaining alpha channel to the defaultAlphaValue.
+            offsetOutput[3] = defaultAlphaValue;
+        }
+    }
+}
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+    const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
+
+    for (size_t i = 0; i < count; i++)
+    {
+        const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride);
+        GLshort *offsetOutput = reinterpret_cast<GLshort*>(output)+i * outputComponentCount;
+
+        for (size_t j = 0; j < inputComponentCount; j++)
+        {
+            offsetOutput[j] = static_cast<GLshort>(offsetInput[j]);
+        }
+
+        for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++)
+        {
+            // Set remaining G/B channels to 0.
+            offsetOutput[j] = 0;
+        }
+
+        if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+        {
+            // On integer formats, we must set the Alpha channel to 1 if it's unused.
+            offsetOutput[3] = 1;
+        }
+    }
+}
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+    for (size_t i = 0; i < count; i++)
+    {
+        const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride);
+        GLshort *offsetOutput = reinterpret_cast<GLshort*>(output) + i * outputComponentCount;
+
+        for (size_t j = 0; j < inputComponentCount; j++)
+        {
+            // The original GLbyte value ranges from -128 to +127 (INT8_MAX).
+            // When converted to GLshort, the value must be scaled to between -32768 and +32767 (INT16_MAX).
+            if (offsetInput[j] > 0)
+            {
+                offsetOutput[j] = offsetInput[j] << 8 | offsetInput[j] << 1 | ((offsetInput[j] & 0x40) >> 6);
+            }
+            else
+            {
+                offsetOutput[j] = offsetInput[j] << 8;
+            }
+        }
+
+        for (size_t j = inputComponentCount; j < std::min<size_t>(outputComponentCount, 3); j++)
+        {
+            // Set remaining G/B channels to 0.
+            offsetOutput[j] = 0;
+        }
+
+        if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+        {
+            // On normalized formats, we must set the Alpha channel to the max value if it's unused.
+            offsetOutput[3] = INT16_MAX;
+        }
+    }
+}
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+    static const float divisor = 1.0f / (1 << 16);
+
+    for (size_t i = 0; i < count; i++)
+    {
+        const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(input + (stride * i));
+        float* offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount;
+
+        for (size_t j = 0; j < inputComponentCount; j++)
+        {
+            offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor;
+        }
+
+        // 4-component output formats would need special padding in the alpha channel.
+        static_assert(!(inputComponentCount < 4 && outputComponentCount == 4),
+                      "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported.");
+
+        for (size_t j = inputComponentCount; j < outputComponentCount; j++)
+        {
+            offsetOutput[j] = 0.0f;
+        }
+    }
+}
+
+template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized>
+inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+    typedef std::numeric_limits<T> NL;
+
+    for (size_t i = 0; i < count; i++)
+    {
+        const T *offsetInput = reinterpret_cast<const T*>(input + (stride * i));
+        float *offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount;
+
+        for (size_t j = 0; j < inputComponentCount; j++)
+        {
+            if (normalized)
+            {
+                if (NL::is_signed)
+                {
+                    const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1);
+                    offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor;
+                }
+                else
+                {
+                    offsetOutput[j] =  static_cast<float>(offsetInput[j]) / NL::max();
+                }
+            }
+            else
+            {
+                offsetOutput[j] =  static_cast<float>(offsetInput[j]);
+            }
+        }
+
+        // This would require special padding.
+        static_assert(!(inputComponentCount < 4 && outputComponentCount == 4),
+                      "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported.");
+
+        for (size_t j = inputComponentCount; j < outputComponentCount; j++)
+        {
+            offsetOutput[j] = 0.0f;
+        }
+    }
+}
+
+namespace priv
+{
+
+template <bool isSigned, bool normalized, bool toFloat>
+static inline void CopyPackedRGB(uint32_t data, uint8_t *output)
+{
+    const uint32_t rgbSignMask = 0x200;       // 1 set at the 9 bit
+    const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1
+
+    if (toFloat)
+    {
+        GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output);
+        if (isSigned)
+        {
+            GLfloat finalValue = 0;
+            if (data & rgbSignMask)
+            {
+                int negativeNumber = data | negativeMask;
+                finalValue = static_cast<GLfloat>(negativeNumber);
+            }
+            else
+            {
+                finalValue = static_cast<GLfloat>(data);
+            }
+
+            if (normalized)
+            {
+                const int32_t maxValue = 0x1FF;      // 1 set in bits 0 through 8
+                const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue
+
+                // A 10-bit two's complement number has the possibility of being minValue - 1 but
+                // OpenGL's normalization rules dictate that it should be clamped to minValue in this
+                // case.
+                if (finalValue < minValue)
+                {
+                    finalValue = minValue;
+                }
+
+                const int32_t halfRange = (maxValue - minValue) >> 1;
+                *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f;
+            }
+            else
+            {
+                *floatOutput = finalValue;
+            }
+        }
+        else
+        {
+            if (normalized)
+            {
+                const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9
+                *floatOutput = static_cast<GLfloat>(data) / static_cast<GLfloat>(maxValue);
+            }
+            else
+            {
+                *floatOutput = static_cast<GLfloat>(data);
+            }
+        }
+    }
+    else
+    {
+        if (isSigned)
+        {
+            GLshort *intOutput = reinterpret_cast<GLshort*>(output);
+
+            if (data & rgbSignMask)
+            {
+                *intOutput = static_cast<GLshort>(data | negativeMask);
+            }
+            else
+            {
+                *intOutput = static_cast<GLshort>(data);
+            }
+        }
+        else
+        {
+            GLushort *uintOutput = reinterpret_cast<GLushort*>(output);
+            *uintOutput = static_cast<GLushort>(data);
+        }
+    }
+}
+
+template <bool isSigned, bool normalized, bool toFloat>
+inline void CopyPackedAlpha(uint32_t data, uint8_t *output)
+{
+    if (toFloat)
+    {
+        GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output);
+        if (isSigned)
+        {
+            if (normalized)
+            {
+                switch (data)
+                {
+                  case 0x0: *floatOutput =  0.0f; break;
+                  case 0x1: *floatOutput =  1.0f; break;
+                  case 0x2: *floatOutput = -1.0f; break;
+                  case 0x3: *floatOutput = -1.0f; break;
+                  default: UNREACHABLE();
+                }
+            }
+            else
+            {
+                switch (data)
+                {
+                  case 0x0: *floatOutput =  0.0f; break;
+                  case 0x1: *floatOutput =  1.0f; break;
+                  case 0x2: *floatOutput = -2.0f; break;
+                  case 0x3: *floatOutput = -1.0f; break;
+                  default: UNREACHABLE();
+                }
+            }
+        }
+        else
+        {
+            if (normalized)
+            {
+                switch (data)
+                {
+                  case 0x0: *floatOutput = 0.0f / 3.0f; break;
+                  case 0x1: *floatOutput = 1.0f / 3.0f; break;
+                  case 0x2: *floatOutput = 2.0f / 3.0f; break;
+                  case 0x3: *floatOutput = 3.0f / 3.0f; break;
+                  default: UNREACHABLE();
+                }
+            }
+            else
+            {
+                switch (data)
+                {
+                  case 0x0: *floatOutput = 0.0f; break;
+                  case 0x1: *floatOutput = 1.0f; break;
+                  case 0x2: *floatOutput = 2.0f; break;
+                  case 0x3: *floatOutput = 3.0f; break;
+                  default: UNREACHABLE();
+                }
+            }
+        }
+    }
+    else
+    {
+        if (isSigned)
+        {
+            GLshort *intOutput = reinterpret_cast<GLshort*>(output);
+            switch (data)
+            {
+              case 0x0: *intOutput =  0; break;
+              case 0x1: *intOutput =  1; break;
+              case 0x2: *intOutput = -2; break;
+              case 0x3: *intOutput = -1; break;
+              default: UNREACHABLE();
+            }
+        }
+        else
+        {
+            GLushort *uintOutput = reinterpret_cast<GLushort*>(output);
+            switch (data)
+            {
+              case 0x0: *uintOutput = 0; break;
+              case 0x1: *uintOutput = 1; break;
+              case 0x2: *uintOutput = 2; break;
+              case 0x3: *uintOutput = 3; break;
+              default: UNREACHABLE();
+            }
+        }
+    }
+}
+
+}
+
+template <bool isSigned, bool normalized, bool toFloat>
+inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+    const size_t outputComponentSize = toFloat ? 4 : 2;
+    const size_t componentCount = 4;
+
+    const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9
+    const size_t redShift = 0;    // red is bits 0 through 9
+    const size_t greenShift = 10; // green is bits 10 through 19
+    const size_t blueShift = 20;  // blue is bits 20 through 29
+
+    const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1
+    const size_t alphaShift = 30; // Alpha is the 30 and 31 bits
+
+    for (size_t i = 0; i < count; i++)
+    {
+        GLuint packedValue = *reinterpret_cast<const GLuint*>(input + (i * stride));
+        uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount);
+
+        priv::CopyPackedRGB<isSigned, normalized, toFloat>(  (packedValue >> redShift)   & rgbMask,   offsetOutput + (0 * outputComponentSize));
+        priv::CopyPackedRGB<isSigned, normalized, toFloat>(  (packedValue >> greenShift) & rgbMask,   offsetOutput + (1 * outputComponentSize));
+        priv::CopyPackedRGB<isSigned, normalized, toFloat>(  (packedValue >> blueShift)  & rgbMask,   offsetOutput + (2 * outputComponentSize));
+        priv::CopyPackedAlpha<isSigned, normalized, toFloat>((packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize));
+    }
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json
new file mode 100644
index 0000000..891d30d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json
@@ -0,0 +1,118 @@
+{
+    "UNKNOWN": "NONE",
+    "R32G32B32A32_TYPELESS": "",
+    "R32G32B32A32_FLOAT": "",
+    "R32G32B32A32_UINT": "",
+    "R32G32B32A32_SINT": "",
+    "R32G32B32_TYPELESS": "",
+    "R32G32B32_FLOAT": "",
+    "R32G32B32_UINT": "",
+    "R32G32B32_SINT": "",
+    "R16G16B16A16_TYPELESS": "",
+    "R16G16B16A16_FLOAT": "",
+    "R16G16B16A16_UNORM": "",
+    "R16G16B16A16_UINT": "",
+    "R16G16B16A16_SNORM": "",
+    "R16G16B16A16_SINT": "",
+    "R32G32_TYPELESS": "",
+    "R32G32_FLOAT": "",
+    "R32G32_UINT": "",
+    "R32G32_SINT": "",
+    "R32G8X24_TYPELESS": "",
+    "D32_FLOAT_S8X24_UINT": "",
+    "R32_FLOAT_X8X24_TYPELESS": "",
+    "X32_TYPELESS_G8X24_UINT": "",
+    "R10G10B10A2_TYPELESS": "",
+    "R10G10B10A2_UNORM": "",
+    "R10G10B10A2_UINT": "",
+    "R11G11B10_FLOAT": "",
+    "R8G8B8A8_TYPELESS": "",
+    "R8G8B8A8_UNORM": "",
+    "R8G8B8A8_UNORM_SRGB": "",
+    "R8G8B8A8_UINT": "",
+    "R8G8B8A8_SNORM": "",
+    "R8G8B8A8_SINT": "",
+    "R16G16_TYPELESS": "",
+    "R16G16_FLOAT": "",
+    "R16G16_UNORM": "",
+    "R16G16_UINT": "",
+    "R16G16_SNORM": "",
+    "R16G16_SINT": "",
+    "R32_TYPELESS": "",
+    "D32_FLOAT": "",
+    "R32_FLOAT": "",
+    "R32_UINT": "",
+    "R32_SINT": "",
+    "R24G8_TYPELESS": "",
+    "D24_UNORM_S8_UINT": "",
+    "R24_UNORM_X8_TYPELESS": "",
+    "X24_TYPELESS_G8_UINT": "",
+    "R8G8_TYPELESS": "",
+    "R8G8_UNORM": "",
+    "R8G8_UINT": "",
+    "R8G8_SNORM": "",
+    "R8G8_SINT": "",
+    "R16_TYPELESS": "",
+    "R16_FLOAT": "",
+    "D16_UNORM": "",
+    "R16_UNORM": "",
+    "R16_UINT": "",
+    "R16_SNORM": "",
+    "R16_SINT": "",
+    "R8_TYPELESS": "",
+    "R8_UNORM": "",
+    "R8_UINT": "",
+    "R8_SNORM": "",
+    "R8_SINT": "",
+    "A8_UNORM": "",
+    "R1_UNORM": "",
+    "R9G9B9E5_SHAREDEXP": "",
+    "R8G8_B8G8_UNORM": "",
+    "G8R8_G8B8_UNORM": "",
+    "BC1_TYPELESS": "",
+    "BC1_UNORM": "BC1_RGBA_UNORM_BLOCK",
+    "BC1_UNORM_SRGB": "BC1_RGBA_UNORM_SRGB_BLOCK",
+    "BC2_TYPELESS": "",
+    "BC2_UNORM": "BC2_RGBA_UNORM_BLOCK",
+    "BC2_UNORM_SRGB": "BC2_RGBA_UNORM_SRGB_BLOCK",
+    "BC3_TYPELESS": "",
+    "BC3_UNORM": "BC3_RGBA_UNORM_BLOCK",
+    "BC3_UNORM_SRGB": "BC3_RGBA_UNORM_SRGB_BLOCK",
+    "BC4_TYPELESS": "",
+    "BC4_UNORM": "",
+    "BC4_SNORM": "",
+    "BC5_TYPELESS": "",
+    "BC5_UNORM": "",
+    "BC5_SNORM": "",
+    "B5G6R5_UNORM": "",
+    "B5G5R5A1_UNORM": "",
+    "B8G8R8A8_UNORM": "",
+    "B8G8R8X8_UNORM": "",
+    "R10G10B10_XR_BIAS_A2_UNORM": "",
+    "B8G8R8A8_TYPELESS": "",
+    "B8G8R8A8_UNORM_SRGB": "",
+    "B8G8R8X8_TYPELESS": "",
+    "B8G8R8X8_UNORM_SRGB": "",
+    "BC6H_TYPELESS": "",
+    "BC6H_UF16": "",
+    "BC6H_SF16": "",
+    "BC7_TYPELESS": "",
+    "BC7_UNORM": "",
+    "BC7_UNORM_SRGB": "",
+    "AYUV": "",
+    "Y410": "",
+    "Y416": "",
+    "NV12": "",
+    "P010": "",
+    "P016": "",
+    "420_OPAQUE": "",
+    "YUY2": "",
+    "Y210": "",
+    "Y216": "",
+    "NV11": "",
+    "AI44": "",
+    "IA44": "",
+    "P8": "",
+    "A8P8": "",
+    "B4G4R4A4_UNORM": ""
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp
new file mode 100644
index 0000000..02513cf
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp
@@ -0,0 +1,516 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_dxgi_format_table.py using data from dxgi_format_data.json.
+//
+// Copyright 2016 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.
+//
+// DXGI format info:
+//   Determining metadata about a DXGI format.
+
+#include "libANGLE/renderer/Format.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+GLenum GetComponentType(DXGI_FORMAT dxgiFormat)
+{
+    switch (dxgiFormat)
+    {
+        case DXGI_FORMAT_420_OPAQUE:
+            break;
+        case DXGI_FORMAT_A8P8:
+            break;
+        case DXGI_FORMAT_A8_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_AI44:
+            break;
+        case DXGI_FORMAT_AYUV:
+            break;
+        case DXGI_FORMAT_B4G4R4A4_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_B5G5R5A1_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_B5G6R5_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+            break;
+        case DXGI_FORMAT_B8G8R8A8_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+            break;
+        case DXGI_FORMAT_B8G8R8X8_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC1_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC1_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC1_UNORM_SRGB:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC2_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC2_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC2_UNORM_SRGB:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC3_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC3_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC3_UNORM_SRGB:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC4_SNORM:
+            return GL_SIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC4_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC4_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC5_SNORM:
+            return GL_SIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC5_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC5_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC6H_SF16:
+            break;
+        case DXGI_FORMAT_BC6H_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC6H_UF16:
+            break;
+        case DXGI_FORMAT_BC7_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC7_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_BC7_UNORM_SRGB:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_D16_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_D24_UNORM_S8_UINT:
+            break;
+        case DXGI_FORMAT_D32_FLOAT:
+            return GL_FLOAT;
+        case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+            break;
+        case DXGI_FORMAT_G8R8_G8B8_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_IA44:
+            break;
+        case DXGI_FORMAT_NV11:
+            break;
+        case DXGI_FORMAT_NV12:
+            break;
+        case DXGI_FORMAT_P010:
+            break;
+        case DXGI_FORMAT_P016:
+            break;
+        case DXGI_FORMAT_P8:
+            break;
+        case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+            break;
+        case DXGI_FORMAT_R10G10B10A2_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R10G10B10A2_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R11G11B10_FLOAT:
+            return GL_FLOAT;
+        case DXGI_FORMAT_R16G16B16A16_FLOAT:
+            return GL_FLOAT;
+        case DXGI_FORMAT_R16G16B16A16_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R16G16B16A16_SNORM:
+            return GL_SIGNED_NORMALIZED;
+        case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+            break;
+        case DXGI_FORMAT_R16G16B16A16_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R16G16B16A16_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R16G16_FLOAT:
+            return GL_FLOAT;
+        case DXGI_FORMAT_R16G16_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R16G16_SNORM:
+            return GL_SIGNED_NORMALIZED;
+        case DXGI_FORMAT_R16G16_TYPELESS:
+            break;
+        case DXGI_FORMAT_R16G16_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R16G16_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R16_FLOAT:
+            return GL_FLOAT;
+        case DXGI_FORMAT_R16_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R16_SNORM:
+            return GL_SIGNED_NORMALIZED;
+        case DXGI_FORMAT_R16_TYPELESS:
+            break;
+        case DXGI_FORMAT_R16_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R16_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R1_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R24G8_TYPELESS:
+            break;
+        case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R32G32B32A32_FLOAT:
+            return GL_FLOAT;
+        case DXGI_FORMAT_R32G32B32A32_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32G32B32A32_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R32G32B32_FLOAT:
+            return GL_FLOAT;
+        case DXGI_FORMAT_R32G32B32_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R32G32B32_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32G32B32_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R32G32_FLOAT:
+            return GL_FLOAT;
+        case DXGI_FORMAT_R32G32_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R32G32_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32G32_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R32G8X24_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32_FLOAT:
+            return GL_FLOAT;
+        case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+            return GL_FLOAT;
+        case DXGI_FORMAT_R32_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R32_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R8G8B8A8_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R8G8B8A8_SNORM:
+            return GL_SIGNED_NORMALIZED;
+        case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+            break;
+        case DXGI_FORMAT_R8G8B8A8_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R8G8B8A8_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R8G8_B8G8_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R8G8_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R8G8_SNORM:
+            return GL_SIGNED_NORMALIZED;
+        case DXGI_FORMAT_R8G8_TYPELESS:
+            break;
+        case DXGI_FORMAT_R8G8_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R8G8_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R8_SINT:
+            return GL_INT;
+        case DXGI_FORMAT_R8_SNORM:
+            return GL_SIGNED_NORMALIZED;
+        case DXGI_FORMAT_R8_TYPELESS:
+            break;
+        case DXGI_FORMAT_R8_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_R8_UNORM:
+            return GL_UNSIGNED_NORMALIZED;
+        case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+            return GL_FLOAT;
+        case DXGI_FORMAT_UNKNOWN:
+            break;
+        case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+            return GL_UNSIGNED_INT;
+        case DXGI_FORMAT_Y210:
+            break;
+        case DXGI_FORMAT_Y216:
+            break;
+        case DXGI_FORMAT_Y410:
+            break;
+        case DXGI_FORMAT_Y416:
+            break;
+        case DXGI_FORMAT_YUY2:
+            break;
+        default:
+            break;
+    }
+
+    UNREACHABLE();
+    return GL_NONE;
+}
+
+}  // namespace d3d11
+
+namespace d3d11_angle
+{
+
+const Format &GetFormat(DXGI_FORMAT dxgiFormat)
+{
+    switch (dxgiFormat)
+    {
+        case DXGI_FORMAT_420_OPAQUE:
+            break;
+        case DXGI_FORMAT_A8P8:
+            break;
+        case DXGI_FORMAT_A8_UNORM:
+            return Format::Get(Format::ID::A8_UNORM);
+        case DXGI_FORMAT_AI44:
+            break;
+        case DXGI_FORMAT_AYUV:
+            break;
+        case DXGI_FORMAT_B4G4R4A4_UNORM:
+            return Format::Get(Format::ID::B4G4R4A4_UNORM);
+        case DXGI_FORMAT_B5G5R5A1_UNORM:
+            return Format::Get(Format::ID::B5G5R5A1_UNORM);
+        case DXGI_FORMAT_B5G6R5_UNORM:
+            return Format::Get(Format::ID::B5G6R5_UNORM);
+        case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+            break;
+        case DXGI_FORMAT_B8G8R8A8_UNORM:
+            return Format::Get(Format::ID::B8G8R8A8_UNORM);
+        case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+            break;
+        case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+            break;
+        case DXGI_FORMAT_B8G8R8X8_UNORM:
+            return Format::Get(Format::ID::B8G8R8X8_UNORM);
+        case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+            break;
+        case DXGI_FORMAT_BC1_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC1_UNORM:
+            return Format::Get(Format::ID::BC1_RGBA_UNORM_BLOCK);
+        case DXGI_FORMAT_BC1_UNORM_SRGB:
+            return Format::Get(Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK);
+        case DXGI_FORMAT_BC2_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC2_UNORM:
+            return Format::Get(Format::ID::BC2_RGBA_UNORM_BLOCK);
+        case DXGI_FORMAT_BC2_UNORM_SRGB:
+            return Format::Get(Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK);
+        case DXGI_FORMAT_BC3_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC3_UNORM:
+            return Format::Get(Format::ID::BC3_RGBA_UNORM_BLOCK);
+        case DXGI_FORMAT_BC3_UNORM_SRGB:
+            return Format::Get(Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK);
+        case DXGI_FORMAT_BC4_SNORM:
+            break;
+        case DXGI_FORMAT_BC4_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC4_UNORM:
+            break;
+        case DXGI_FORMAT_BC5_SNORM:
+            break;
+        case DXGI_FORMAT_BC5_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC5_UNORM:
+            break;
+        case DXGI_FORMAT_BC6H_SF16:
+            break;
+        case DXGI_FORMAT_BC6H_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC6H_UF16:
+            break;
+        case DXGI_FORMAT_BC7_TYPELESS:
+            break;
+        case DXGI_FORMAT_BC7_UNORM:
+            break;
+        case DXGI_FORMAT_BC7_UNORM_SRGB:
+            break;
+        case DXGI_FORMAT_D16_UNORM:
+            return Format::Get(Format::ID::D16_UNORM);
+        case DXGI_FORMAT_D24_UNORM_S8_UINT:
+            return Format::Get(Format::ID::D24_UNORM_S8_UINT);
+        case DXGI_FORMAT_D32_FLOAT:
+            return Format::Get(Format::ID::D32_FLOAT);
+        case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+            return Format::Get(Format::ID::D32_FLOAT_S8X24_UINT);
+        case DXGI_FORMAT_G8R8_G8B8_UNORM:
+            break;
+        case DXGI_FORMAT_IA44:
+            break;
+        case DXGI_FORMAT_NV11:
+            break;
+        case DXGI_FORMAT_NV12:
+            break;
+        case DXGI_FORMAT_P010:
+            break;
+        case DXGI_FORMAT_P016:
+            break;
+        case DXGI_FORMAT_P8:
+            break;
+        case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+            break;
+        case DXGI_FORMAT_R10G10B10A2_UINT:
+            return Format::Get(Format::ID::R10G10B10A2_UINT);
+        case DXGI_FORMAT_R10G10B10A2_UNORM:
+            return Format::Get(Format::ID::R10G10B10A2_UNORM);
+        case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+            break;
+        case DXGI_FORMAT_R11G11B10_FLOAT:
+            return Format::Get(Format::ID::R11G11B10_FLOAT);
+        case DXGI_FORMAT_R16G16B16A16_FLOAT:
+            return Format::Get(Format::ID::R16G16B16A16_FLOAT);
+        case DXGI_FORMAT_R16G16B16A16_SINT:
+            return Format::Get(Format::ID::R16G16B16A16_SINT);
+        case DXGI_FORMAT_R16G16B16A16_SNORM:
+            return Format::Get(Format::ID::R16G16B16A16_SNORM);
+        case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+            break;
+        case DXGI_FORMAT_R16G16B16A16_UINT:
+            return Format::Get(Format::ID::R16G16B16A16_UINT);
+        case DXGI_FORMAT_R16G16B16A16_UNORM:
+            return Format::Get(Format::ID::R16G16B16A16_UNORM);
+        case DXGI_FORMAT_R16G16_FLOAT:
+            return Format::Get(Format::ID::R16G16_FLOAT);
+        case DXGI_FORMAT_R16G16_SINT:
+            return Format::Get(Format::ID::R16G16_SINT);
+        case DXGI_FORMAT_R16G16_SNORM:
+            return Format::Get(Format::ID::R16G16_SNORM);
+        case DXGI_FORMAT_R16G16_TYPELESS:
+            break;
+        case DXGI_FORMAT_R16G16_UINT:
+            return Format::Get(Format::ID::R16G16_UINT);
+        case DXGI_FORMAT_R16G16_UNORM:
+            return Format::Get(Format::ID::R16G16_UNORM);
+        case DXGI_FORMAT_R16_FLOAT:
+            return Format::Get(Format::ID::R16_FLOAT);
+        case DXGI_FORMAT_R16_SINT:
+            return Format::Get(Format::ID::R16_SINT);
+        case DXGI_FORMAT_R16_SNORM:
+            return Format::Get(Format::ID::R16_SNORM);
+        case DXGI_FORMAT_R16_TYPELESS:
+            break;
+        case DXGI_FORMAT_R16_UINT:
+            return Format::Get(Format::ID::R16_UINT);
+        case DXGI_FORMAT_R16_UNORM:
+            return Format::Get(Format::ID::R16_UNORM);
+        case DXGI_FORMAT_R1_UNORM:
+            break;
+        case DXGI_FORMAT_R24G8_TYPELESS:
+            break;
+        case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32G32B32A32_FLOAT:
+            return Format::Get(Format::ID::R32G32B32A32_FLOAT);
+        case DXGI_FORMAT_R32G32B32A32_SINT:
+            return Format::Get(Format::ID::R32G32B32A32_SINT);
+        case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32G32B32A32_UINT:
+            return Format::Get(Format::ID::R32G32B32A32_UINT);
+        case DXGI_FORMAT_R32G32B32_FLOAT:
+            return Format::Get(Format::ID::R32G32B32_FLOAT);
+        case DXGI_FORMAT_R32G32B32_SINT:
+            return Format::Get(Format::ID::R32G32B32_SINT);
+        case DXGI_FORMAT_R32G32B32_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32G32B32_UINT:
+            return Format::Get(Format::ID::R32G32B32_UINT);
+        case DXGI_FORMAT_R32G32_FLOAT:
+            return Format::Get(Format::ID::R32G32_FLOAT);
+        case DXGI_FORMAT_R32G32_SINT:
+            return Format::Get(Format::ID::R32G32_SINT);
+        case DXGI_FORMAT_R32G32_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32G32_UINT:
+            return Format::Get(Format::ID::R32G32_UINT);
+        case DXGI_FORMAT_R32G8X24_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32_FLOAT:
+            return Format::Get(Format::ID::R32_FLOAT);
+        case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32_SINT:
+            return Format::Get(Format::ID::R32_SINT);
+        case DXGI_FORMAT_R32_TYPELESS:
+            break;
+        case DXGI_FORMAT_R32_UINT:
+            return Format::Get(Format::ID::R32_UINT);
+        case DXGI_FORMAT_R8G8B8A8_SINT:
+            return Format::Get(Format::ID::R8G8B8A8_SINT);
+        case DXGI_FORMAT_R8G8B8A8_SNORM:
+            return Format::Get(Format::ID::R8G8B8A8_SNORM);
+        case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+            break;
+        case DXGI_FORMAT_R8G8B8A8_UINT:
+            return Format::Get(Format::ID::R8G8B8A8_UINT);
+        case DXGI_FORMAT_R8G8B8A8_UNORM:
+            return Format::Get(Format::ID::R8G8B8A8_UNORM);
+        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+            return Format::Get(Format::ID::R8G8B8A8_UNORM_SRGB);
+        case DXGI_FORMAT_R8G8_B8G8_UNORM:
+            break;
+        case DXGI_FORMAT_R8G8_SINT:
+            return Format::Get(Format::ID::R8G8_SINT);
+        case DXGI_FORMAT_R8G8_SNORM:
+            return Format::Get(Format::ID::R8G8_SNORM);
+        case DXGI_FORMAT_R8G8_TYPELESS:
+            break;
+        case DXGI_FORMAT_R8G8_UINT:
+            return Format::Get(Format::ID::R8G8_UINT);
+        case DXGI_FORMAT_R8G8_UNORM:
+            return Format::Get(Format::ID::R8G8_UNORM);
+        case DXGI_FORMAT_R8_SINT:
+            return Format::Get(Format::ID::R8_SINT);
+        case DXGI_FORMAT_R8_SNORM:
+            return Format::Get(Format::ID::R8_SNORM);
+        case DXGI_FORMAT_R8_TYPELESS:
+            break;
+        case DXGI_FORMAT_R8_UINT:
+            return Format::Get(Format::ID::R8_UINT);
+        case DXGI_FORMAT_R8_UNORM:
+            return Format::Get(Format::ID::R8_UNORM);
+        case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+            return Format::Get(Format::ID::R9G9B9E5_SHAREDEXP);
+        case DXGI_FORMAT_UNKNOWN:
+            return Format::Get(Format::ID::NONE);
+        case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+            break;
+        case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+            break;
+        case DXGI_FORMAT_Y210:
+            break;
+        case DXGI_FORMAT_Y216:
+            break;
+        case DXGI_FORMAT_Y410:
+            break;
+        case DXGI_FORMAT_Y416:
+            break;
+        case DXGI_FORMAT_YUY2:
+            break;
+        default:
+            break;
+    }
+
+    UNREACHABLE();
+    return Format::Get(Format::ID::NONE);
+}
+
+}  // namespace d3d11_angle
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json
new file mode 100644
index 0000000..9427456
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json
@@ -0,0 +1,1279 @@
+[
+  {
+    "DXGI_FORMAT_UNKNOWN":
+    {
+      "texture2D": "never",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32B32A32_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32B32A32_FLOAT":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0check10_1always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "always"
+    },
+    "DXGI_FORMAT_R32G32B32A32_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32B32A32_SINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32B32_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32B32_FLOAT":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "11_0check",
+      "renderTarget": "check",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32B32_UINT":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "check",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32B32_SINT":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "check",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16G16B16A16_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16G16B16A16_FLOAT":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "9_3check_10_0always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "always"
+    },
+    "DXGI_FORMAT_R16G16B16A16_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "always"
+    },
+    "DXGI_FORMAT_R16G16B16A16_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16G16B16A16_SNORM":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "10_0",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R16G16B16A16_SINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32_FLOAT":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0check10_1always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R32G32_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G32_SINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32G8X24_TYPELESS":
+    {
+      "texture2D": "10_0",
+      "texture3D": "never",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_D32_FLOAT_S8X24_UINT":
+    {
+      "texture2D": "always",
+      "texture3D": "never",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "check",
+      "depthStencil": "10_0",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "never",
+      "textureCube": "always",
+      "shaderSample": "10_0check10_1always",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT":
+    {
+      "texture2D": "always",
+      "texture3D": "never",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R10G10B10A2_TYPELESS":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R10G10B10A2_UNORM":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "10_0",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R10G10B10A2_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R11G11B10_FLOAT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "10_0",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R8G8B8A8_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R8G8B8A8_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "always"
+    },
+    "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "always"
+    },
+    "DXGI_FORMAT_R8G8B8A8_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R8G8B8A8_SNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R8G8B8A8_SINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16G16_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16G16_FLOAT":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "always"
+    },
+    "DXGI_FORMAT_R16G16_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "always"
+    },
+    "DXGI_FORMAT_R16G16_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16G16_SNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R16G16_SINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32_TYPELESS":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_D32_FLOAT":
+    {
+      "texture2D": "always",
+      "texture3D": "never",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "check",
+      "depthStencil": "10_0",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32_FLOAT":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0check10_1always",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "always"
+    },
+    "DXGI_FORMAT_R32_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R32_SINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R24G8_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "never",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_D24_UNORM_S8_UINT":
+    {
+      "texture2D": "always",
+      "texture3D": "never",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "check",
+      "depthStencil": "always"
+    },
+    "DXGI_FORMAT_R24_UNORM_X8_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "never",
+      "textureCube": "always",
+      "shaderSample": "10_0check10_1always",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_X24_TYPELESS_G8_UINT":
+    {
+      "texture2D": "always",
+      "texture3D": "never",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R8G8_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R8G8_UNORM":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "9_3check_10_0always",
+      "renderTarget": "9_3check_10_0always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R8G8_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R8G8_SNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "always",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R8G8_SINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16_FLOAT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "10_0",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_D16_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "never",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "check",
+      "depthStencil": "always",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R16_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R16_SNORM":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "10_0",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R16_SINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R8_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R8_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "9_3check_10_0always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R8_UINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R8_SNORM":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "10_0",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R8_SINT":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "never",
+      "renderTarget": "10_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_A8_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0",
+      "renderTarget": "always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "10_0"
+    },
+    "DXGI_FORMAT_R1_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "11_0",
+      "textureCube": "11_0",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R9G9B9E5_SHAREDEXP":
+    {
+      "texture2D": "10_0",
+      "texture3D": "10_0",
+      "textureCube": "10_0",
+      "shaderSample": "10_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R8G8_B8G8_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_G8R8_G8B8_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC1_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC1_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC1_UNORM_SRGB":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC2_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC2_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC2_UNORM_SRGB":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC3_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC3_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC3_UNORM_SRGB":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "always",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC4_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC4_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC4_SNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC5_TYPELESS":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC5_UNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC5_SNORM":
+    {
+      "texture2D": "always",
+      "texture3D": "always",
+      "textureCube": "always",
+      "shaderSample": "10_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_B5G6R5_UNORM":
+    {
+      "texture2D": "dxgi1_2",
+      "texture3D": "dxgi1_2",
+      "textureCube": "dxgi1_2",
+      "shaderSample": "dxgi1_2",
+      "renderTarget": "dxgi1_2",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "dxgi1_2"
+    },
+    "DXGI_FORMAT_B5G5R5A1_UNORM":
+    {
+      "texture2D": "dxgi1_2",
+      "texture3D": "dxgi1_2",
+      "textureCube": "dxgi1_2",
+      "shaderSample": "dxgi1_2",
+      "renderTarget": "check",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "dxgi1_2"
+    },
+    "DXGI_FORMAT_B8G8R8A8_UNORM":
+    {
+      "texture2D": "check",
+      "texture3D": "check",
+      "textureCube": "check",
+      "shaderSample": "9_3always_10_0check11_0always",
+      "renderTarget": "9_3always_10_0check11_0always",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "always"
+    },
+    "DXGI_FORMAT_B8G8R8X8_UNORM":
+    {
+      "texture2D": "check",
+      "texture3D": "check",
+      "textureCube": "check",
+      "shaderSample": "10_0check11_0always",
+      "renderTarget": "11_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM":
+    {
+      "texture2D": "check",
+      "texture3D": "check",
+      "textureCube": "never",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_B8G8R8A8_TYPELESS":
+    {
+      "texture2D": "check",
+      "texture3D": "check",
+      "textureCube": "check",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB":
+    {
+      "texture2D": "check",
+      "texture3D": "check",
+      "textureCube": "check",
+      "shaderSample": "10_0check11_0always",
+      "renderTarget": "11_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_B8G8R8X8_TYPELESS":
+    {
+      "texture2D": "check",
+      "texture3D": "check",
+      "textureCube": "check",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB":
+    {
+      "texture2D": "check",
+      "texture3D": "check",
+      "textureCube": "check",
+      "shaderSample": "10_0check11_0always",
+      "renderTarget": "11_0",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC6H_TYPELESS":
+    {
+      "texture2D": "11_0",
+      "texture3D": "11_0",
+      "textureCube": "11_0",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC6H_UF16":
+    {
+      "texture2D": "11_0",
+      "texture3D": "11_0",
+      "textureCube": "11_0",
+      "shaderSample": "11_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC6H_SF16":
+    {
+      "texture2D": "11_0",
+      "texture3D": "11_0",
+      "textureCube": "11_0",
+      "shaderSample": "11_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC7_TYPELESS":
+    {
+      "texture2D": "11_0",
+      "texture3D": "11_0",
+      "textureCube": "11_0",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC7_UNORM":
+    {
+      "texture2D": "11_0",
+      "texture3D": "11_0",
+      "textureCube": "11_0",
+      "shaderSample": "11_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_BC7_UNORM_SRGB":
+    {
+      "texture2D": "11_0",
+      "texture3D": "11_0",
+      "textureCube": "11_0",
+      "shaderSample": "11_0",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_AYUV":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "11_1",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_Y410":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_Y416":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_NV12":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "11_1",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_P010":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "11_1",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_P016":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "11_1",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_420_OPAQUE":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_YUY2":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_Y210":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_Y216":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_NV11":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "11_1",
+      "renderTarget": "11_1",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_AI44":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_IA44":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_P8":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_A8P8":
+    {
+      "texture2D": "11_1",
+      "texture3D": "never",
+      "textureCube": "never",
+      "shaderSample": "never",
+      "renderTarget": "never",
+      "multisampleRT": "never",
+      "depthStencil": "never",
+      "mipAutoGen": "never"
+    },
+    "DXGI_FORMAT_B4G4R4A4_UNORM":
+    {
+      "texture2D": "dxgi1_2",
+      "texture3D": "dxgi1_2",
+      "textureCube": "dxgi1_2",
+      "shaderSample": "dxgi1_2",
+      "renderTarget": "check",
+      "multisampleRT": "check",
+      "depthStencil": "never",
+      "mipAutoGen": "dxgi1_2"
+    }
+  }
+]
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp
new file mode 100644
index 0000000..2816a24
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp
@@ -0,0 +1,2447 @@
+// GENERATED FILE - DO NOT EDIT. See dxgi_support_data.json.
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// dxgi_support_table:
+//   Queries for DXGI support of various texture formats. Depends on DXGI
+//   version, D3D feature level, and is sometimes guaranteed or optional.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+#define F_2D D3D11_FORMAT_SUPPORT_TEXTURE2D
+#define F_3D D3D11_FORMAT_SUPPORT_TEXTURE3D
+#define F_CUBE D3D11_FORMAT_SUPPORT_TEXTURECUBE
+#define F_SAMPLE D3D11_FORMAT_SUPPORT_SHADER_SAMPLE
+#define F_RT D3D11_FORMAT_SUPPORT_RENDER_TARGET
+#define F_MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
+#define F_DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
+#define F_MIPGEN D3D11_FORMAT_SUPPORT_MIP_AUTOGEN
+
+namespace
+{
+
+const DXGISupport &GetDefaultSupport()
+{
+    static UINT AllSupportFlags =
+        D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURE3D |
+        D3D11_FORMAT_SUPPORT_TEXTURECUBE | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE |
+        D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET |
+        D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+    static const DXGISupport defaultSupport(0, 0, AllSupportFlags);
+    return defaultSupport;
+}
+
+const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat)
+{
+    // clang-format off
+    switch (dxgiFormat)
+    {
+        case DXGI_FORMAT_420_OPAQUE:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_A8P8:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_A8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_AI44:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_AYUV:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B4G4R4A4_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_B5G5R5A1_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_B5G6R5_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_UNORM:
+        {
+            static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_UNORM:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_SF16:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_UF16:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_UNORM:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_UNORM_SRGB:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_D16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D24_UNORM_S8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_G8R8_G8B8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_IA44:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_NV11:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_NV12:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P010:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P016:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P8:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_UNORM:
+        {
+            static const DXGISupport info(0, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+        {
+            static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+            return info;
+        }
+        case DXGI_FORMAT_R11G11B10_FLOAT:
+        {
+            static const DXGISupport info(0, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_SINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_SNORM:
+        {
+            static const DXGISupport info(0, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_SINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_FLOAT:
+        {
+            static const DXGISupport info(0, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_SINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_SNORM:
+        {
+            static const DXGISupport info(0, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R1_UNORM:
+        {
+            static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R24G8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_SINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_SINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G8X24_TYPELESS:
+        {
+            static const DXGISupport info(0, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_SINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_SINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_B8G8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_SINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_UNORM:
+        {
+            static const DXGISupport info(0, F_DS, F_MS | F_RT | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_R8_SINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_SNORM:
+        {
+            static const DXGISupport info(0, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8_UINT:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_UNKNOWN:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y210:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y216:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y410:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y416:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_YUY2:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+
+        default:
+            UNREACHABLE();
+            return GetDefaultSupport();
+    }
+    // clang-format on
+}
+
+const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
+{
+    // clang-format off
+    switch (dxgiFormat)
+    {
+        case DXGI_FORMAT_420_OPAQUE:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_A8P8:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_A8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_AI44:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_AYUV:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B4G4R4A4_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_B5G5R5A1_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_B5G6R5_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_UNORM:
+        {
+            static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_UNORM:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_SF16:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_UF16:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_UNORM:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_UNORM_SRGB:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_D16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D24_UNORM_S8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_G8R8_G8B8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_IA44:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_NV11:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_NV12:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P010:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P016:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P8:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+        {
+            static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+            return info;
+        }
+        case DXGI_FORMAT_R11G11B10_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R1_UNORM:
+        {
+            static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R24G8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G8X24_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_R32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_B8G8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_UNKNOWN:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y210:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y216:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y410:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y416:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_YUY2:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+
+        default:
+            UNREACHABLE();
+            return GetDefaultSupport();
+    }
+    // clang-format on
+}
+
+const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
+{
+    // clang-format off
+    switch (dxgiFormat)
+    {
+        case DXGI_FORMAT_420_OPAQUE:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_A8P8:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_A8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_AI44:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_AYUV:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B4G4R4A4_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_B5G5R5A1_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_B5G6R5_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_UNORM:
+        {
+            static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_UNORM:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_SF16:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_UF16:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_UNORM:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_UNORM_SRGB:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_D16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D24_UNORM_S8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_G8R8_G8B8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_IA44:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_NV11:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_NV12:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P010:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P016:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P8:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+        {
+            static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+            return info;
+        }
+        case DXGI_FORMAT_R11G11B10_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R1_UNORM:
+        {
+            static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R24G8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G8X24_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_B8G8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_UNKNOWN:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y210:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y216:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y410:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y416:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_YUY2:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+
+        default:
+            UNREACHABLE();
+            return GetDefaultSupport();
+    }
+    // clang-format on
+}
+
+const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
+{
+    // clang-format off
+    switch (dxgiFormat)
+    {
+        case DXGI_FORMAT_420_OPAQUE:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_A8P8:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_A8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_AI44:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_AYUV:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B4G4R4A4_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_B5G5R5A1_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_B5G6R5_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_UNORM:
+        {
+            static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+        {
+            static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_UNORM:
+        {
+            static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC1_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC2_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC3_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC4_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC5_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_SF16:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC6H_UF16:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_BC7_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_D16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D24_UNORM_S8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_G8R8_G8B8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_IA44:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_NV11:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_NV12:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P010:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P016:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_P8:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10A2_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+        {
+            static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+            return info;
+        }
+        case DXGI_FORMAT_R11G11B10_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16B16A16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16G16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R16_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R16_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R1_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R24G8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32A32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32B32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32G32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32G8X24_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_FLOAT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R32_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R32_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_B8G8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8G8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_SINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_SNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_TYPELESS:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_R8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R8_UNORM:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+            return info;
+        }
+        case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+        {
+            static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+            return info;
+        }
+        case DXGI_FORMAT_UNKNOWN:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+        {
+            static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y210:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y216:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y410:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_Y416:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+        case DXGI_FORMAT_YUY2:
+        {
+            static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+            return info;
+        }
+
+        default:
+            UNREACHABLE();
+            return GetDefaultSupport();
+    }
+    // clang-format on
+}
+
+}
+
+#undef F_2D
+#undef F_3D
+#undef F_CUBE
+#undef F_SAMPLE
+#undef F_RT
+#undef F_MS
+#undef F_DS
+#undef F_MIPGEN
+
+const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_9_3:
+            return GetDXGISupport_9_3(dxgiFormat);
+        case D3D_FEATURE_LEVEL_10_0:
+            return GetDXGISupport_10_0(dxgiFormat);
+        case D3D_FEATURE_LEVEL_10_1:
+            return GetDXGISupport_10_1(dxgiFormat);
+        case D3D_FEATURE_LEVEL_11_0:
+            return GetDXGISupport_11_0(dxgiFormat);
+        default:
+            return GetDefaultSupport();
+    }
+}
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h
new file mode 100644
index 0000000..1d8d685
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h
@@ -0,0 +1,44 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// dxgi_support_table:
+//   Queries for DXGI support of various texture formats. Depends on DXGI
+//   version, D3D feature level, and is sometimes guaranteed or optional.
+//
+
+#include "common/platform.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+struct DXGISupport
+{
+    DXGISupport()
+        : alwaysSupportedFlags(0),
+          neverSupportedFlags(0),
+          optionallySupportedFlags(0)
+    {
+    }
+
+    DXGISupport(UINT alwaysSupportedIn, UINT neverSupportedIn, UINT optionallySupportedIn)
+        : alwaysSupportedFlags(alwaysSupportedIn),
+          neverSupportedFlags(neverSupportedIn),
+          optionallySupportedFlags(optionallySupportedIn)
+    {
+    }
+
+    UINT alwaysSupportedFlags;
+    UINT neverSupportedFlags;
+    UINT optionallySupportedFlags;
+};
+
+const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel);
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
new file mode 100644
index 0000000..ce4edd2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
@@ -0,0 +1,1023 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// formatutils11.cpp: Queries for GL image formats and their translations to D3D11
+// formats.
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/copyvertex.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel)
+{
+    const auto &support = GetDXGISupport(dxgiFormat, featureLevel);
+    ASSERT((support.optionallySupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) == 0);
+    return ((support.alwaysSupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0);
+}
+
+DXGIFormatSize::DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight)
+    : pixelBytes(pixelBits / 8), blockWidth(blockWidth), blockHeight(blockHeight)
+{
+}
+
+const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format)
+{
+    static const DXGIFormatSize sizeUnknown(0, 0, 0);
+    static const DXGIFormatSize size128(128, 1, 1);
+    static const DXGIFormatSize size96(96, 1, 1);
+    static const DXGIFormatSize size64(64, 1, 1);
+    static const DXGIFormatSize size32(32, 1, 1);
+    static const DXGIFormatSize size16(16, 1, 1);
+    static const DXGIFormatSize size8(8, 1, 1);
+    static const DXGIFormatSize sizeBC1(64, 4, 4);
+    static const DXGIFormatSize sizeBC2(128, 4, 4);
+    static const DXGIFormatSize sizeBC3(128, 4, 4);
+    static const DXGIFormatSize sizeBC4(64, 4, 4);
+    static const DXGIFormatSize sizeBC5(128, 4, 4);
+    static const DXGIFormatSize sizeBC6H(128, 4, 4);
+    static const DXGIFormatSize sizeBC7(128, 4, 4);
+    switch (format)
+    {
+        case DXGI_FORMAT_UNKNOWN:
+            return sizeUnknown;
+        case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+        case DXGI_FORMAT_R32G32B32A32_FLOAT:
+        case DXGI_FORMAT_R32G32B32A32_UINT:
+        case DXGI_FORMAT_R32G32B32A32_SINT:
+            return size128;
+        case DXGI_FORMAT_R32G32B32_TYPELESS:
+        case DXGI_FORMAT_R32G32B32_FLOAT:
+        case DXGI_FORMAT_R32G32B32_UINT:
+        case DXGI_FORMAT_R32G32B32_SINT:
+            return size96;
+        case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+        case DXGI_FORMAT_R16G16B16A16_FLOAT:
+        case DXGI_FORMAT_R16G16B16A16_UNORM:
+        case DXGI_FORMAT_R16G16B16A16_UINT:
+        case DXGI_FORMAT_R16G16B16A16_SNORM:
+        case DXGI_FORMAT_R16G16B16A16_SINT:
+        case DXGI_FORMAT_R32G32_TYPELESS:
+        case DXGI_FORMAT_R32G32_FLOAT:
+        case DXGI_FORMAT_R32G32_UINT:
+        case DXGI_FORMAT_R32G32_SINT:
+        case DXGI_FORMAT_R32G8X24_TYPELESS:
+        case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+        case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+        case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+            return size64;
+        case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+        case DXGI_FORMAT_R10G10B10A2_UNORM:
+        case DXGI_FORMAT_R10G10B10A2_UINT:
+        case DXGI_FORMAT_R11G11B10_FLOAT:
+        case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+        case DXGI_FORMAT_R8G8B8A8_UNORM:
+        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+        case DXGI_FORMAT_R8G8B8A8_UINT:
+        case DXGI_FORMAT_R8G8B8A8_SNORM:
+        case DXGI_FORMAT_R8G8B8A8_SINT:
+        case DXGI_FORMAT_R16G16_TYPELESS:
+        case DXGI_FORMAT_R16G16_FLOAT:
+        case DXGI_FORMAT_R16G16_UNORM:
+        case DXGI_FORMAT_R16G16_UINT:
+        case DXGI_FORMAT_R16G16_SNORM:
+        case DXGI_FORMAT_R16G16_SINT:
+        case DXGI_FORMAT_R32_TYPELESS:
+        case DXGI_FORMAT_D32_FLOAT:
+        case DXGI_FORMAT_R32_FLOAT:
+        case DXGI_FORMAT_R32_UINT:
+        case DXGI_FORMAT_R32_SINT:
+        case DXGI_FORMAT_R24G8_TYPELESS:
+        case DXGI_FORMAT_D24_UNORM_S8_UINT:
+        case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+        case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+            return size32;
+        case DXGI_FORMAT_R8G8_TYPELESS:
+        case DXGI_FORMAT_R8G8_UNORM:
+        case DXGI_FORMAT_R8G8_UINT:
+        case DXGI_FORMAT_R8G8_SNORM:
+        case DXGI_FORMAT_R8G8_SINT:
+        case DXGI_FORMAT_R16_TYPELESS:
+        case DXGI_FORMAT_R16_FLOAT:
+        case DXGI_FORMAT_D16_UNORM:
+        case DXGI_FORMAT_R16_UNORM:
+        case DXGI_FORMAT_R16_UINT:
+        case DXGI_FORMAT_R16_SNORM:
+        case DXGI_FORMAT_R16_SINT:
+            return size16;
+        case DXGI_FORMAT_R8_TYPELESS:
+        case DXGI_FORMAT_R8_UNORM:
+        case DXGI_FORMAT_R8_UINT:
+        case DXGI_FORMAT_R8_SNORM:
+        case DXGI_FORMAT_R8_SINT:
+        case DXGI_FORMAT_A8_UNORM:
+            return size8;
+        case DXGI_FORMAT_R1_UNORM:
+            UNREACHABLE();
+            return sizeUnknown;
+        case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+        case DXGI_FORMAT_R8G8_B8G8_UNORM:
+        case DXGI_FORMAT_G8R8_G8B8_UNORM:
+            return size32;
+        case DXGI_FORMAT_BC1_TYPELESS:
+        case DXGI_FORMAT_BC1_UNORM:
+        case DXGI_FORMAT_BC1_UNORM_SRGB:
+            return sizeBC1;
+        case DXGI_FORMAT_BC2_TYPELESS:
+        case DXGI_FORMAT_BC2_UNORM:
+        case DXGI_FORMAT_BC2_UNORM_SRGB:
+            return sizeBC2;
+        case DXGI_FORMAT_BC3_TYPELESS:
+        case DXGI_FORMAT_BC3_UNORM:
+        case DXGI_FORMAT_BC3_UNORM_SRGB:
+            return sizeBC3;
+        case DXGI_FORMAT_BC4_TYPELESS:
+        case DXGI_FORMAT_BC4_UNORM:
+        case DXGI_FORMAT_BC4_SNORM:
+            return sizeBC4;
+        case DXGI_FORMAT_BC5_TYPELESS:
+        case DXGI_FORMAT_BC5_UNORM:
+        case DXGI_FORMAT_BC5_SNORM:
+            return sizeBC5;
+        case DXGI_FORMAT_B5G6R5_UNORM:
+        case DXGI_FORMAT_B5G5R5A1_UNORM:
+            return size16;
+        case DXGI_FORMAT_B8G8R8A8_UNORM:
+        case DXGI_FORMAT_B8G8R8X8_UNORM:
+        case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+        case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+        case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+        case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+        case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+            return size32;
+        case DXGI_FORMAT_BC6H_TYPELESS:
+        case DXGI_FORMAT_BC6H_UF16:
+        case DXGI_FORMAT_BC6H_SF16:
+            return sizeBC6H;
+        case DXGI_FORMAT_BC7_TYPELESS:
+        case DXGI_FORMAT_BC7_UNORM:
+        case DXGI_FORMAT_BC7_UNORM_SRGB:
+            return sizeBC7;
+        case DXGI_FORMAT_AYUV:
+        case DXGI_FORMAT_Y410:
+        case DXGI_FORMAT_Y416:
+        case DXGI_FORMAT_NV12:
+        case DXGI_FORMAT_P010:
+        case DXGI_FORMAT_P016:
+        case DXGI_FORMAT_420_OPAQUE:
+        case DXGI_FORMAT_YUY2:
+        case DXGI_FORMAT_Y210:
+        case DXGI_FORMAT_Y216:
+        case DXGI_FORMAT_NV11:
+        case DXGI_FORMAT_AI44:
+        case DXGI_FORMAT_IA44:
+        case DXGI_FORMAT_P8:
+        case DXGI_FORMAT_A8P8:
+            UNREACHABLE();
+            return sizeUnknown;
+        case DXGI_FORMAT_B4G4R4A4_UNORM:
+            return size16;
+        default:
+            UNREACHABLE();
+            return sizeUnknown;
+    }
+}
+
+constexpr VertexFormat::VertexFormat()
+    : conversionType(VERTEX_CONVERT_NONE), nativeFormat(DXGI_FORMAT_UNKNOWN), copyFunction(nullptr)
+{
+}
+
+constexpr VertexFormat::VertexFormat(VertexConversionType conversionTypeIn,
+                                     DXGI_FORMAT nativeFormatIn,
+                                     VertexCopyFunction copyFunctionIn)
+    : conversionType(conversionTypeIn), nativeFormat(nativeFormatIn), copyFunction(copyFunctionIn)
+{
+}
+
+const VertexFormat *GetVertexFormatInfo_FL_9_3(gl::VertexFormatType vertexFormatType)
+{
+    // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature
+    // Level 10_0+.
+    // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx
+
+    switch (vertexFormatType)
+    {
+        // GL_BYTE -- unnormalized
+        case gl::VERTEX_FORMAT_SBYTE1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+                                               &Copy8SintTo16SintVertexData<1, 2>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+                                               &Copy8SintTo16SintVertexData<2, 2>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+                                               &Copy8SintTo16SintVertexData<3, 4>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+                                               &Copy8SintTo16SintVertexData<4, 4>);
+            return &info;
+        }
+
+        // GL_BYTE -- normalized
+        case gl::VERTEX_FORMAT_SBYTE1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+                                               &Copy8SnormTo16SnormVertexData<1, 2>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE2_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+                                               &Copy8SnormTo16SnormVertexData<2, 2>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE3_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+                                               &Copy8SnormTo16SnormVertexData<3, 4>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE4_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+                                               &Copy8SnormTo16SnormVertexData<4, 4>);
+            return &info;
+        }
+
+        // GL_UNSIGNED_BYTE -- un-normalized
+        // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format
+        // table.
+        case gl::VERTEX_FORMAT_UBYTE1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 1, 4, 1>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 2, 4, 1>);
+            return &info;
+        }
+
+        // GL_UNSIGNED_BYTE -- normalized
+        // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table.
+
+        // GL_UNSIGNED_BYTE -- normalized
+        case gl::VERTEX_FORMAT_UBYTE1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+                                               &CopyNativeVertexData<GLubyte, 1, 4, UINT8_MAX>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE2_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+                                               &CopyNativeVertexData<GLubyte, 2, 4, UINT8_MAX>);
+            return &info;
+        }
+
+        // GL_SHORT -- un-normalized
+        // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table.
+        case gl::VERTEX_FORMAT_SSHORT1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+                                               &CopyNativeVertexData<GLshort, 1, 2, 0>);
+            return &info;
+        }
+
+        // GL_SHORT -- normalized
+        // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table.
+        case gl::VERTEX_FORMAT_SSHORT1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+                                               &CopyNativeVertexData<GLshort, 1, 2, 0>);
+            return &info;
+        }
+
+        // GL_UNSIGNED_SHORT -- un-normalized
+        case gl::VERTEX_FORMAT_USHORT1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+                                               &CopyTo32FVertexData<GLushort, 1, 2, false>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_USHORT2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+                                               &CopyTo32FVertexData<GLushort, 2, 2, false>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_USHORT3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+                                               &CopyTo32FVertexData<GLushort, 3, 3, false>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_USHORT4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                               &CopyTo32FVertexData<GLushort, 4, 4, false>);
+            return &info;
+        }
+
+        // GL_UNSIGNED_SHORT -- normalized
+        case gl::VERTEX_FORMAT_USHORT1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+                                               &CopyTo32FVertexData<GLushort, 1, 2, true>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_USHORT2_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+                                               &CopyTo32FVertexData<GLushort, 2, 2, true>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_USHORT3_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+                                               &CopyTo32FVertexData<GLushort, 3, 3, true>);
+            return &info;
+        }
+        case gl::VERTEX_FORMAT_USHORT4_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                               &CopyTo32FVertexData<GLushort, 4, 4, true>);
+            return &info;
+        }
+
+        // GL_FIXED
+        // TODO: Add test to verify that this works correctly.
+        // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table.
+        case gl::VERTEX_FORMAT_FIXED1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+                                               &Copy32FixedTo32FVertexData<1, 2>);
+            return &info;
+        }
+
+        // GL_FLOAT
+        // TODO: Add test to verify that this works correctly.
+        // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table.
+        case gl::VERTEX_FORMAT_FLOAT1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+                                               &CopyNativeVertexData<GLfloat, 1, 2, 0>);
+            return &info;
+        }
+
+        default:
+            return nullptr;
+    }
+}
+
+const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D3D_FEATURE_LEVEL featureLevel)
+{
+    if (featureLevel == D3D_FEATURE_LEVEL_9_3)
+    {
+        const VertexFormat *result = GetVertexFormatInfo_FL_9_3(vertexFormatType);
+        if (result)
+        {
+            return *result;
+        }
+    }
+
+    switch (vertexFormatType)
+    {
+        //
+        // Float formats
+        //
+
+        // GL_BYTE -- un-normalized
+        case gl::VERTEX_FORMAT_SBYTE1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT,
+                                               &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT,
+                                               &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT,
+                                               &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT,
+                                               &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_BYTE -- normalized
+        case gl::VERTEX_FORMAT_SBYTE1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM,
+                                               &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE2_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM,
+                                               &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE3_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM,
+                                               &CopyNativeVertexData<GLbyte, 3, 4, INT8_MAX>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE4_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM,
+                                               &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_UNSIGNED_BYTE -- un-normalized
+        case gl::VERTEX_FORMAT_UBYTE1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_UNSIGNED_BYTE -- normalized
+        case gl::VERTEX_FORMAT_UBYTE1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM,
+                                               &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE2_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM,
+                                               &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE3_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+                                               &CopyNativeVertexData<GLubyte, 3, 4, UINT8_MAX>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE4_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM,
+                                               &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_SHORT -- un-normalized
+        case gl::VERTEX_FORMAT_SSHORT1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT,
+                                               &CopyNativeVertexData<GLshort, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SSHORT2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT,
+                                               &CopyNativeVertexData<GLshort, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SSHORT3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+                                               &CopyNativeVertexData<GLshort, 3, 4, 1>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SSHORT4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT,
+                                               &CopyNativeVertexData<GLshort, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_SHORT -- normalized
+        case gl::VERTEX_FORMAT_SSHORT1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM,
+                                               &CopyNativeVertexData<GLshort, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SSHORT2_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM,
+                                               &CopyNativeVertexData<GLshort, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SSHORT3_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+                                               &CopyNativeVertexData<GLshort, 3, 4, INT16_MAX>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SSHORT4_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM,
+                                               &CopyNativeVertexData<GLshort, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_UNSIGNED_SHORT -- un-normalized
+        case gl::VERTEX_FORMAT_USHORT1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT,
+                                               &CopyNativeVertexData<GLushort, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_USHORT2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT,
+                                               &CopyNativeVertexData<GLushort, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_USHORT3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT,
+                                               &CopyNativeVertexData<GLushort, 3, 4, 1>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_USHORT4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT,
+                                               &CopyNativeVertexData<GLushort, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_UNSIGNED_SHORT -- normalized
+        case gl::VERTEX_FORMAT_USHORT1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM,
+                                               &CopyNativeVertexData<GLushort, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_USHORT2_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM,
+                                               &CopyNativeVertexData<GLushort, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_USHORT3_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM,
+                                               &CopyNativeVertexData<GLushort, 3, 4, UINT16_MAX>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_USHORT4_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM,
+                                               &CopyNativeVertexData<GLushort, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_INT -- un-normalized
+        case gl::VERTEX_FORMAT_SINT1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT,
+                                               &CopyNativeVertexData<GLint, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT,
+                                               &CopyNativeVertexData<GLint, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT,
+                                               &CopyNativeVertexData<GLint, 3, 3, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT,
+                                               &CopyNativeVertexData<GLint, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_INT -- normalized
+        case gl::VERTEX_FORMAT_SINT1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+                                               &CopyTo32FVertexData<GLint, 1, 1, true>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT2_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+                                               &CopyTo32FVertexData<GLint, 2, 2, true>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT3_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+                                               &CopyTo32FVertexData<GLint, 3, 3, true>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT4_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                               &CopyTo32FVertexData<GLint, 4, 4, true>);
+            return info;
+        }
+
+        // GL_UNSIGNED_INT -- un-normalized
+        case gl::VERTEX_FORMAT_UINT1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT,
+                                               &CopyNativeVertexData<GLuint, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT,
+                                               &CopyNativeVertexData<GLuint, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT,
+                                               &CopyNativeVertexData<GLuint, 3, 3, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT,
+                                               &CopyNativeVertexData<GLuint, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_UNSIGNED_INT -- normalized
+        case gl::VERTEX_FORMAT_UINT1_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+                                               &CopyTo32FVertexData<GLuint, 1, 1, true>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT2_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+                                               &CopyTo32FVertexData<GLuint, 2, 2, true>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT3_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+                                               &CopyTo32FVertexData<GLuint, 3, 3, true>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT4_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                               &CopyTo32FVertexData<GLuint, 4, 4, true>);
+            return info;
+        }
+
+        // GL_FIXED
+        case gl::VERTEX_FORMAT_FIXED1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+                                               &Copy32FixedTo32FVertexData<1, 1>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_FIXED2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+                                               &Copy32FixedTo32FVertexData<2, 2>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_FIXED3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+                                               &Copy32FixedTo32FVertexData<3, 3>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_FIXED4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                               &Copy32FixedTo32FVertexData<4, 4>);
+            return info;
+        }
+
+        // GL_HALF_FLOAT
+        case gl::VERTEX_FORMAT_HALF1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT,
+                                               &CopyNativeVertexData<GLhalf, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_HALF2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT,
+                                               &CopyNativeVertexData<GLhalf, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_HALF3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                               &CopyNativeVertexData<GLhalf, 3, 4, gl::Float16One>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_HALF4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                               &CopyNativeVertexData<GLhalf, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_FLOAT
+        case gl::VERTEX_FORMAT_FLOAT1:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT,
+                                               &CopyNativeVertexData<GLfloat, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_FLOAT2:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT,
+                                               &CopyNativeVertexData<GLfloat, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_FLOAT3:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT,
+                                               &CopyNativeVertexData<GLfloat, 3, 3, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_FLOAT4:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                               &CopyNativeVertexData<GLfloat, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_INT_2_10_10_10_REV
+        case gl::VERTEX_FORMAT_SINT210:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                               &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT210_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                               &CopyXYZ10W2ToXYZW32FVertexData<true, true, true>);
+            return info;
+        }
+
+        // GL_UNSIGNED_INT_2_10_10_10_REV
+        case gl::VERTEX_FORMAT_UINT210:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                               &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT210_NORM:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM,
+                                               &CopyNativeVertexData<GLuint, 1, 1, 0>);
+            return info;
+        }
+
+        //
+        // Integer Formats
+        //
+
+        // GL_BYTE
+        case gl::VERTEX_FORMAT_SBYTE1_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT,
+                                               &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE2_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT,
+                                               &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE3_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT,
+                                               &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SBYTE4_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT,
+                                               &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_UNSIGNED_BYTE
+        case gl::VERTEX_FORMAT_UBYTE1_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE2_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE3_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UBYTE4_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT,
+                                               &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_SHORT
+        case gl::VERTEX_FORMAT_SSHORT1_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT,
+                                               &CopyNativeVertexData<GLshort, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SSHORT2_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT,
+                                               &CopyNativeVertexData<GLshort, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SSHORT3_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT,
+                                               &CopyNativeVertexData<GLshort, 3, 4, 1>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SSHORT4_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT,
+                                               &CopyNativeVertexData<GLshort, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_UNSIGNED_SHORT
+        case gl::VERTEX_FORMAT_USHORT1_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT,
+                                               &CopyNativeVertexData<GLushort, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_USHORT2_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT,
+                                               &CopyNativeVertexData<GLushort, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_USHORT3_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT,
+                                               &CopyNativeVertexData<GLushort, 3, 4, 1>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_USHORT4_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT,
+                                               &CopyNativeVertexData<GLushort, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_INT
+        case gl::VERTEX_FORMAT_SINT1_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT,
+                                               &CopyNativeVertexData<GLint, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT2_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT,
+                                               &CopyNativeVertexData<GLint, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT3_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT,
+                                               &CopyNativeVertexData<GLint, 3, 3, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_SINT4_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT,
+                                               &CopyNativeVertexData<GLint, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_UNSIGNED_INT
+        case gl::VERTEX_FORMAT_UINT1_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT,
+                                               &CopyNativeVertexData<GLuint, 1, 1, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT2_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT,
+                                               &CopyNativeVertexData<GLuint, 2, 2, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT3_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT,
+                                               &CopyNativeVertexData<GLuint, 3, 3, 0>);
+            return info;
+        }
+        case gl::VERTEX_FORMAT_UINT4_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT,
+                                               &CopyNativeVertexData<GLuint, 4, 4, 0>);
+            return info;
+        }
+
+        // GL_INT_2_10_10_10_REV
+        case gl::VERTEX_FORMAT_SINT210_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT,
+                                               &CopyXYZ10W2ToXYZW32FVertexData<true, true, false>);
+            return info;
+        }
+
+        // GL_UNSIGNED_INT_2_10_10_10_REV
+        case gl::VERTEX_FORMAT_UINT210_INT:
+        {
+            static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT,
+                                               &CopyNativeVertexData<GLuint, 1, 1, 0>);
+            return info;
+        }
+
+        default:
+        {
+            static constexpr VertexFormat info;
+            return info;
+        }
+    }
+}
+
+}  // namespace d3d11
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
new file mode 100644
index 0000000..883d338
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// formatutils11.h: Queries for GL image formats and their translations to D3D11
+// formats.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
+
+#include <map>
+
+#include "common/platform.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+
+namespace rx
+{
+struct Renderer11DeviceCaps;
+
+namespace d3d11
+{
+
+// A texture might be stored as DXGI_FORMAT_R16_TYPELESS but store integer components,
+// which are accessed through an DXGI_FORMAT_R16_SINT view. It's easy to write code which queries
+// information about the wrong format. Therefore, use of this should be avoided where possible.
+
+bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel);
+
+struct DXGIFormatSize
+{
+    DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight);
+
+    GLuint pixelBytes;
+    GLuint blockWidth;
+    GLuint blockHeight;
+};
+const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format);
+
+struct VertexFormat : private angle::NonCopyable
+{
+    constexpr VertexFormat();
+    constexpr VertexFormat(VertexConversionType conversionType,
+                           DXGI_FORMAT nativeFormat,
+                           VertexCopyFunction copyFunction);
+
+    VertexConversionType conversionType;
+    DXGI_FORMAT nativeFormat;
+    VertexCopyFunction copyFunction;
+};
+
+const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType,
+                                        D3D_FEATURE_LEVEL featureLevel);
+
+// Auto-generated in dxgi_format_map_autogen.cpp.
+GLenum GetComponentType(DXGI_FORMAT dxgiFormat);
+
+}  // namespace d3d11
+
+namespace d3d11_angle
+{
+const angle::Format &GetFormat(DXGI_FORMAT dxgiFormat);
+}
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py
new file mode 100644
index 0000000..6c6d190
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py
@@ -0,0 +1,134 @@
+#!/usr/bin/python
+# Copyright 2016 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.
+#
+# gen_dxgi_format_table.py:
+#  Code generation for DXGI format map.
+
+from datetime import date
+import sys
+
+sys.path.append('../..')
+import angle_format
+
+template_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+//
+// Copyright {copyright_year} 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.
+//
+// DXGI format info:
+//   Determining metadata about a DXGI format.
+
+#include "libANGLE/renderer/Format.h"
+
+using namespace angle;
+
+namespace rx
+{{
+
+namespace d3d11
+{{
+
+GLenum GetComponentType(DXGI_FORMAT dxgiFormat)
+{{
+    switch (dxgiFormat)
+    {{
+{component_type_cases}        default:
+            break;
+    }}
+
+    UNREACHABLE();
+    return GL_NONE;
+}}
+
+}}  // namespace d3d11
+
+namespace d3d11_angle
+{{
+
+const Format &GetFormat(DXGI_FORMAT dxgiFormat)
+{{
+    switch (dxgiFormat)
+    {{
+{format_cases}        default:
+            break;
+    }}
+
+    UNREACHABLE();
+    return Format::Get(Format::ID::NONE);
+}}
+
+}}  // namespace d3d11_angle
+
+}}  // namespace rx
+"""
+
+template_format_case = """        case DXGI_FORMAT_{dxgi_format}:
+            return {result};
+"""
+
+template_undefined_case = """        case DXGI_FORMAT_{dxgi_format}:
+            break;
+"""
+
+def format_case(dxgi_format, result):
+    return template_format_case.format(
+        dxgi_format = dxgi_format,
+        result = result)
+
+def undefined_case(dxgi_format):
+    return template_undefined_case.format(dxgi_format = dxgi_format)
+
+component_cases = ""
+format_cases = ""
+
+input_data = 'dxgi_format_data.json'
+
+dxgi_map = angle_format.load_json(input_data)
+
+types = {
+    'SNORM': 'GL_SIGNED_NORMALIZED',
+    'UNORM': 'GL_UNSIGNED_NORMALIZED',
+    'SINT': 'GL_INT',
+    'UINT': 'GL_UNSIGNED_INT',
+    'FLOAT': 'GL_FLOAT',
+    'SHAREDEXP': 'GL_FLOAT'
+}
+
+angle_to_gl = angle_format.load_inverse_table('../../angle_format_map.json')
+all_angle = angle_to_gl.keys()
+
+for dxgi_format, angle_format in sorted(dxgi_map.iteritems()):
+
+    found = [ctype in dxgi_format for ctype in types.keys()]
+    count = reduce((lambda a, b: int(a) + int(b)), found)
+
+    component_type = 'GL_NONE'
+
+    if count == 1:
+        gltype = next(gltype for ctype, gltype in types.iteritems() if ctype in dxgi_format)
+        component_cases += format_case(dxgi_format, gltype)
+    else:
+        component_cases += undefined_case(dxgi_format)
+
+    if angle_format == "":
+        angle_format = dxgi_format
+
+    if angle_format in all_angle:
+        angle_format = "Format::Get(Format::ID::" + angle_format + ")"
+        format_cases += format_case(dxgi_format, angle_format)
+    else:
+        format_cases += undefined_case(dxgi_format)
+
+with open('dxgi_format_map_autogen.cpp', 'wt') as out_file:
+    output_cpp = template_cpp.format(
+        script_name = sys.argv[0],
+        data_source_name = input_data,
+        copyright_year = date.today().year,
+        component_type_cases = component_cases,
+        format_cases = format_cases)
+    out_file.write(output_cpp)
+    out_file.close()
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py
new file mode 100644
index 0000000..200a505
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py
@@ -0,0 +1,282 @@
+#!/usr/bin/python
+# Copyright 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# gen_dxgi_support_tables.py:
+#  Code generation for the DXGI support tables. Determines which formats
+#  are natively support in D3D10+.
+#
+# MSDN links:
+#  10Level9 9_3: https://msdn.microsoft.com/en-us/library/windows/desktop/mt790740.aspx
+#  10_0: https://msdn.microsoft.com/en-us/library/windows/desktop/cc627090.aspx
+#  10_1: https://msdn.microsoft.com/en-us/library/windows/desktop/cc627091.aspx
+#  11_0: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471325.aspx
+#  11_1: https://msdn.microsoft.com/en-us/library/windows/desktop/hh404483.aspx
+
+import sys
+import json
+
+macro_prefix = 'F_'
+
+template = """// GENERATED FILE - DO NOT EDIT. See dxgi_support_data.json.
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// dxgi_support_table:
+//   Queries for DXGI support of various texture formats. Depends on DXGI
+//   version, D3D feature level, and is sometimes guaranteed or optional.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+
+#include "common/debug.h"
+
+namespace rx
+{{
+
+namespace d3d11
+{{
+
+#define {prefix}2D D3D11_FORMAT_SUPPORT_TEXTURE2D
+#define {prefix}3D D3D11_FORMAT_SUPPORT_TEXTURE3D
+#define {prefix}CUBE D3D11_FORMAT_SUPPORT_TEXTURECUBE
+#define {prefix}SAMPLE D3D11_FORMAT_SUPPORT_SHADER_SAMPLE
+#define {prefix}RT D3D11_FORMAT_SUPPORT_RENDER_TARGET
+#define {prefix}MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
+#define {prefix}DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
+#define {prefix}MIPGEN D3D11_FORMAT_SUPPORT_MIP_AUTOGEN
+
+namespace
+{{
+
+const DXGISupport &GetDefaultSupport()
+{{
+    static UINT AllSupportFlags =
+        D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURE3D |
+        D3D11_FORMAT_SUPPORT_TEXTURECUBE | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE |
+        D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET |
+        D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+    static const DXGISupport defaultSupport(0, 0, AllSupportFlags);
+    return defaultSupport;
+}}
+
+const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat)
+{{
+    // clang-format off
+    switch (dxgiFormat)
+    {{
+{table_data_9_3}
+        default:
+            UNREACHABLE();
+            return GetDefaultSupport();
+    }}
+    // clang-format on
+}}
+
+const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
+{{
+    // clang-format off
+    switch (dxgiFormat)
+    {{
+{table_data_10_0}
+        default:
+            UNREACHABLE();
+            return GetDefaultSupport();
+    }}
+    // clang-format on
+}}
+
+const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
+{{
+    // clang-format off
+    switch (dxgiFormat)
+    {{
+{table_data_10_1}
+        default:
+            UNREACHABLE();
+            return GetDefaultSupport();
+    }}
+    // clang-format on
+}}
+
+const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
+{{
+    // clang-format off
+    switch (dxgiFormat)
+    {{
+{table_data_11_0}
+        default:
+            UNREACHABLE();
+            return GetDefaultSupport();
+    }}
+    // clang-format on
+}}
+
+}}
+
+#undef {prefix}2D
+#undef {prefix}3D
+#undef {prefix}CUBE
+#undef {prefix}SAMPLE
+#undef {prefix}RT
+#undef {prefix}MS
+#undef {prefix}DS
+#undef {prefix}MIPGEN
+
+const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel)
+{{
+    switch (featureLevel)
+    {{
+        case D3D_FEATURE_LEVEL_9_3:
+            return GetDXGISupport_9_3(dxgiFormat);
+        case D3D_FEATURE_LEVEL_10_0:
+            return GetDXGISupport_10_0(dxgiFormat);
+        case D3D_FEATURE_LEVEL_10_1:
+            return GetDXGISupport_10_1(dxgiFormat);
+        case D3D_FEATURE_LEVEL_11_0:
+            return GetDXGISupport_11_0(dxgiFormat);
+        default:
+            return GetDefaultSupport();
+    }}
+}}
+
+}} // namespace d3d11
+
+}} // namespace rx
+"""
+
+table_init = ""
+
+def do_format(format_data):
+    table_data = {'9_3': '', '10_0': '', '10_1': '', '11_0': ''}
+
+    json_flag_to_d3d = {
+        'texture2D': macro_prefix + '2D',
+        'texture3D': macro_prefix + '3D',
+        'textureCube': macro_prefix + 'CUBE',
+        'shaderSample': macro_prefix + 'SAMPLE',
+        'renderTarget': macro_prefix + 'RT',
+        'multisampleRT': macro_prefix + 'MS',
+        'depthStencil': macro_prefix + 'DS',
+        'mipAutoGen': macro_prefix + 'MIPGEN'
+    }
+
+    for format_name, format_support in sorted(format_data.iteritems()):
+
+        always_supported = set()
+        never_supported = set()
+        optionally_supported = set()
+        fl_9_3_supported = set()
+        fl_9_3_check = set()
+        fl_10_0_supported = set()
+        fl_10_1_supported = set()
+        fl_11_0_supported = set()
+        fl_11_0_check = set()
+        fl_10_0_check_10_1_supported = set()
+        fl_10_0_check_11_0_supported = set()
+
+        for json_flag, support in format_support.iteritems():
+
+            d3d_flag = [json_flag_to_d3d[json_flag]]
+
+            if support == 'check':
+                optionally_supported.update(d3d_flag)
+            elif support == 'always':
+                always_supported.update(d3d_flag)
+            elif support == 'never':
+                never_supported.update(d3d_flag)
+            elif support == '10_0':
+                fl_10_0_supported.update(d3d_flag)
+            elif support == '10_1':
+                fl_10_1_supported.update(d3d_flag)
+            elif support == '11_0':
+                fl_11_0_supported.update(d3d_flag)
+            elif support == '11_1':
+                # TODO(jmadill): D3D 11.1 handling
+                never_supported.update(d3d_flag)
+            elif support == 'dxgi1_2':
+                # TODO(jmadill): DXGI 1.2 handling.
+                always_supported.update(d3d_flag)
+            elif support == '10_0check10_1always':
+                fl_10_0_check_10_1_supported.update(d3d_flag)
+            elif support == '10_0check11_0always':
+                fl_10_0_check_11_0_supported.update(d3d_flag)
+            elif support == '11_0check':
+                fl_11_0_check.update(d3d_flag)
+            elif support == '9_3always_10_0check11_0always':
+                fl_9_3_supported.update(d3d_flag)
+                fl_10_0_check_11_0_supported.update(d3d_flag)
+            elif support == '9_3check_10_0always':
+                fl_9_3_check.update(d3d_flag)
+                fl_10_0_supported.update(d3d_flag)
+            else:
+                print("Data specification error: " + support)
+                sys.exit(1)
+
+        for feature_level in ['9_3', '10_0', '10_1', '11_0']:
+            always_for_fl = always_supported
+            optional_for_fl = optionally_supported
+            if feature_level == '9_3':
+                always_for_fl = fl_9_3_supported.union(always_for_fl)
+                optional_for_fl = fl_9_3_check.union(optional_for_fl)
+            elif feature_level == '10_0':
+                always_for_fl = fl_10_0_supported.union(always_for_fl)
+                optional_for_fl = fl_10_0_check_10_1_supported.union(optional_for_fl)
+                optional_for_fl = fl_10_0_check_11_0_supported.union(optional_for_fl)
+            elif feature_level == '10_1':
+                always_for_fl = fl_10_0_supported.union(always_for_fl)
+                always_for_fl = fl_10_1_supported.union(always_for_fl)
+                always_for_fl = fl_10_0_check_10_1_supported.union(always_for_fl)
+                optional_for_fl = fl_10_0_check_11_0_supported.union(optional_for_fl)
+            elif feature_level == '11_0':
+                always_for_fl = fl_10_0_supported.union(always_for_fl)
+                always_for_fl = fl_10_0_check_10_1_supported.union(always_for_fl)
+                always_for_fl = fl_10_0_check_11_0_supported.union(always_for_fl)
+                always_for_fl = fl_10_1_supported.union(always_for_fl)
+                always_for_fl = fl_11_0_supported.union(always_for_fl)
+
+            always = ' | '.join(sorted(always_for_fl))
+            never = ' | '.join(sorted(never_supported))
+            optional = ' | '.join(sorted(optional_for_fl))
+
+            if not always: always = '0'
+            if not never: never = '0'
+            if not optional: optional = '0'
+
+            table_data[feature_level] += '        case ' + format_name + ':\n'
+            table_data[feature_level] += '        {\n'
+            table_data[feature_level] += '            static const DXGISupport info(' + always + ', ' + never + ', ' + optional + ');\n'
+            table_data[feature_level] += '            return info;\n'
+            table_data[feature_level] += '        }\n'
+
+    return table_data
+
+def join_table_data(table_data_1, table_data_2):
+    return {'9_3':  table_data_1['9_3']  + table_data_2['9_3'],
+            '10_0': table_data_1['10_0'] + table_data_2['10_0'],
+            '10_1': table_data_1['10_1'] + table_data_2['10_1'],
+            '11_0': table_data_1['11_0'] + table_data_2['11_0']}
+
+with open('dxgi_support_data.json') as dxgi_file:
+    file_data = dxgi_file.read()
+    dxgi_file.close()
+    json_data = json.loads(file_data)
+
+    table_data = {'9_3': '', '10_0': '', '10_1': '', '11_0': ''}
+
+    for format_data in json_data:
+        table_data = join_table_data(table_data, do_format(format_data))
+
+    out_data = template.format(prefix=macro_prefix,
+                               table_data_9_3=table_data['9_3'],
+                               table_data_10_0=table_data['10_0'],
+                               table_data_10_1=table_data['10_1'],
+                               table_data_11_0=table_data['11_0'])
+
+    with open('dxgi_support_table.cpp', 'wt') as out_file:
+        out_file.write(out_data)
+        out_file.close()
+
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
new file mode 100644
index 0000000..02c600b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
@@ -0,0 +1,272 @@
+#!/usr/bin/python
+# Copyright 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# gen_texture_format_table.py:
+#  Code generation for texture format map
+#
+
+from datetime import date
+import json
+import math
+import pprint
+import os
+import sys
+
+sys.path.append('../..')
+import angle_format
+
+template_texture_format_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}
+//
+// Copyright {copyright_year} 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.
+//
+// texture_format_table:
+//   Queries for full textureFormat information based in internalFormat
+//
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h"
+
+using namespace angle;
+
+namespace rx
+{{
+
+namespace d3d11
+{{
+
+// static
+const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps)
+{{
+    // clang-format off
+    switch (internalFormat)
+    {{
+{angle_format_info_cases}
+        default:
+            break;
+    }}
+    // clang-format on
+
+    UNREACHABLE();
+    static constexpr Format defaultInfo;
+    return defaultInfo;
+}}
+
+}}  // namespace d3d11
+
+}}  // namespace rx
+"""
+
+def get_swizzle_format_id(internal_format, angle_format):
+    angle_format_id = angle_format["formatName"]
+    if (internal_format == 'GL_NONE') or (angle_format_id == 'NONE'):
+        return 'GL_NONE'
+
+    elif 'swizzleFormat' in angle_format:
+        # For some special formats like compressed formats that don't have a clearly defined number
+        # of bits per channel, swizzle format needs to be specified manually.
+        return angle_format['swizzleFormat']
+
+    if 'bits' not in angle_format:
+        raise ValueError('no bits information for determining swizzleformat for format: ' + internal_format)
+
+    bits = angle_format['bits']
+    max_component_bits = max(bits.itervalues())
+    channels_different = not all([component_bits == bits.itervalues().next() for component_bits in bits.itervalues()])
+
+    # The format itself can be used for swizzles if it can be accessed as a render target and
+    # sampled and the bit count for all 4 channels is the same.
+    if "rtvFormat" in angle_format and "srvFormat" in angle_format and not channels_different and len(angle_format['channels']) == 4:
+        return angle_format["glInternalFormat"] if "glInternalFormat" in angle_format else internal_format
+
+    b = int(math.ceil(float(max_component_bits) / 8) * 8)
+
+    # Depth formats need special handling, since combined depth/stencil formats don't have a clearly
+    # defined component type.
+    if angle_format['channels'].find('d') >= 0:
+        if b == 24 or b == 32:
+            return 'GL_RGBA32F'
+        if b == 16:
+            return 'GL_RGBA16_EXT'
+
+    if b == 24:
+        raise ValueError('unexpected 24-bit format when determining swizzleformat for format: ' + internal_format)
+
+    if 'componentType' not in angle_format:
+        raise ValueError('no component type information for determining swizzleformat for format: ' + internal_format)
+
+    component_type = angle_format['componentType']
+
+    swizzle = "GL_RGBA" + str(b)
+
+    if component_type == 'uint':
+        swizzle += "I"
+    elif component_type == 'int':
+        swizzle += "I"
+    elif component_type == 'unorm':
+        if (b == 16):
+            swizzle += "_EXT"
+    elif component_type == 'snorm':
+        swizzle += "_SNORM"
+        if (b == 16):
+            swizzle += "_EXT"
+    elif component_type == 'float':
+        swizzle += "F"
+        if (b == 16):
+            swizzle += "_EXT"
+    else:
+        raise ValueError('could not determine swizzleformat based on componentType for format: ' + internal_format)
+
+    return swizzle
+
+def get_blit_srv_format(angle_format):
+    if 'channels' not in angle_format:
+        return 'DXGI_FORMAT_UNKNOWN'
+    if 'r' in angle_format['channels'] and angle_format['componentType'] in ['int', 'uint']:
+        return angle_format['rtvFormat']
+
+    return angle_format["srvFormat"] if "srvFormat" in angle_format else "DXGI_FORMAT_UNKNOWN"
+
+
+format_entry_template = """{space}{{
+{space}    static constexpr Format info({internalFormat},
+{space}                                 angle::Format::ID::{formatName},
+{space}                                 {texFormat},
+{space}                                 {srvFormat},
+{space}                                 {rtvFormat},
+{space}                                 {dsvFormat},
+{space}                                 {blitSRVFormat},
+{space}                                 {swizzleFormat},
+{space}                                 {initializer});
+{space}    return info;
+{space}}}
+"""
+
+split_format_entry_template = """{space}    {condition}
+{space}    {{
+{space}        static constexpr Format info({internalFormat},
+{space}                                     angle::Format::ID::{formatName},
+{space}                                     {texFormat},
+{space}                                     {srvFormat},
+{space}                                     {rtvFormat},
+{space}                                     {dsvFormat},
+{space}                                     {blitSRVFormat},
+{space}                                     {swizzleFormat},
+{space}                                     {initializer});
+{space}        return info;
+{space}    }}
+"""
+
+def json_to_table_data(internal_format, format_name, prefix, json):
+
+    table_data = ""
+
+    parsed = {
+        "space": "        ",
+        "internalFormat": internal_format,
+        "formatName": format_name,
+        "texFormat": "DXGI_FORMAT_UNKNOWN",
+        "srvFormat": "DXGI_FORMAT_UNKNOWN",
+        "rtvFormat": "DXGI_FORMAT_UNKNOWN",
+        "dsvFormat": "DXGI_FORMAT_UNKNOWN",
+        "condition": prefix,
+    }
+
+    for k, v in json.iteritems():
+        parsed[k] = v
+
+    # Derived values.
+    parsed["blitSRVFormat"] = get_blit_srv_format(parsed)
+    parsed["swizzleFormat"] = get_swizzle_format_id(internal_format, parsed)
+    parsed["initializer"]   = angle_format.get_internal_format_initializer(
+        internal_format, parsed["formatName"])
+
+    if len(prefix) > 0:
+        return split_format_entry_template.format(**parsed)
+    else:
+        return format_entry_template.format(**parsed)
+
+def parse_json_angle_format_case(format_name, angle_format, json_data):
+    supported_case = {}
+    unsupported_case = {}
+    support_test = None
+    fallback = None
+
+    for k, v in angle_format.iteritems():
+        if k == "FL10Plus":
+            assert support_test is None
+            support_test = "OnlyFL10Plus(deviceCaps)"
+            for k2, v2 in v.iteritems():
+                supported_case[k2] = v2
+        elif k == "FL9_3":
+            split = True
+            for k2, v2 in v.iteritems():
+                unsupported_case[k2] = v2
+        elif k == "supportTest":
+            assert support_test is None
+            support_test = v
+        elif k == "fallbackFormat":
+            fallback = v
+        else:
+            supported_case[k] = v
+            unsupported_case[k] = v
+
+    if fallback != None:
+        unsupported_case, _, _ = parse_json_angle_format_case(
+            fallback, json_data[fallback], json_data)
+        unsupported_case["formatName"] = fallback
+
+    if support_test != None:
+        return supported_case, unsupported_case, support_test
+    else:
+        return supported_case, None, None
+
+def parse_json_into_switch_angle_format_string(json_map, json_data):
+    table_data = ''
+
+    for internal_format, format_name in sorted(json_map.iteritems()):
+
+        if format_name not in json_data:
+            continue
+
+        angle_format = json_data[format_name]
+
+        supported_case, unsupported_case, support_test = parse_json_angle_format_case(
+            format_name, angle_format, json_data)
+
+        table_data += '        case ' + internal_format + ':\n'
+
+        if support_test != None:
+            table_data += "        {\n"
+            table_data += json_to_table_data(internal_format, format_name, "if (" + support_test + ")", supported_case)
+            table_data += json_to_table_data(internal_format, format_name, "else", unsupported_case)
+            table_data += "        }\n"
+        else:
+            table_data += json_to_table_data(internal_format, format_name, "", supported_case)
+
+    return table_data
+
+json_map = angle_format.load_with_override(os.path.abspath('texture_format_map.json'))
+data_source_name = 'texture_format_data.json'
+json_data = angle_format.load_json(data_source_name)
+
+angle_format_cases = parse_json_into_switch_angle_format_string(json_map, json_data)
+output_cpp = template_texture_format_table_autogen_cpp.format(
+    script_name = sys.argv[0],
+    copyright_year = date.today().year,
+    angle_format_info_cases = angle_format_cases,
+    data_source_name = data_source_name)
+with open('texture_format_table_autogen.cpp', 'wt') as out_file:
+    out_file.write(output_cpp)
+    out_file.close()
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
new file mode 100644
index 0000000..6c62416
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -0,0 +1,2254 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// renderer11_utils.cpp: Conversion functions and other utility routines
+// specific to the D3D11 renderer.
+
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include <algorithm>
+
+#include "common/debug.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "platform/Platform.h"
+#include "platform/WorkaroundsD3D.h"
+
+namespace rx
+{
+
+namespace d3d11_gl
+{
+namespace
+{
+
+// Helper functor for querying DXGI support. Saves passing the parameters repeatedly.
+class DXGISupportHelper : angle::NonCopyable
+{
+  public:
+    DXGISupportHelper(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel)
+        : mDevice(device), mFeatureLevel(featureLevel)
+    {
+    }
+
+    bool query(DXGI_FORMAT dxgiFormat, UINT supportMask)
+    {
+        if (dxgiFormat == DXGI_FORMAT_UNKNOWN)
+            return false;
+
+        auto dxgiSupport = d3d11::GetDXGISupport(dxgiFormat, mFeatureLevel);
+
+        UINT supportedBits = dxgiSupport.alwaysSupportedFlags;
+
+        if ((dxgiSupport.optionallySupportedFlags & supportMask) != 0)
+        {
+            UINT formatSupport;
+            if (SUCCEEDED(mDevice->CheckFormatSupport(dxgiFormat, &formatSupport)))
+            {
+                supportedBits |= (formatSupport & supportMask);
+            }
+            else
+            {
+                // TODO(jmadill): find out why we fail this call sometimes in FL9_3
+                // ERR() << "Error checking format support for format 0x" << std::hex << dxgiFormat;
+            }
+        }
+
+        return ((supportedBits & supportMask) == supportMask);
+    }
+
+  private:
+    ID3D11Device *mDevice;
+    D3D_FEATURE_LEVEL mFeatureLevel;
+};
+
+gl::TextureCaps GenerateTextureFormatCaps(gl::Version maxClientVersion,
+                                          GLenum internalFormat,
+                                          ID3D11Device *device,
+                                          const Renderer11DeviceCaps &renderer11DeviceCaps)
+{
+    gl::TextureCaps textureCaps;
+
+    DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel);
+    const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+
+    const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+
+    UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D;
+    if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0)
+    {
+        texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE;
+        if (maxClientVersion.major > 2)
+        {
+            texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+        }
+    }
+
+    textureCaps.texturable = support.query(formatInfo.texFormat, texSupportMask);
+    textureCaps.filterable =
+        support.query(formatInfo.srvFormat, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE);
+    textureCaps.renderable =
+        (support.query(formatInfo.rtvFormat, D3D11_FORMAT_SUPPORT_RENDER_TARGET)) ||
+        (support.query(formatInfo.dsvFormat, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL));
+
+    DXGI_FORMAT renderFormat = DXGI_FORMAT_UNKNOWN;
+    if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
+    {
+        renderFormat = formatInfo.dsvFormat;
+    }
+    else if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+    {
+        renderFormat = formatInfo.rtvFormat;
+    }
+    if (renderFormat != DXGI_FORMAT_UNKNOWN &&
+        support.query(renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
+    {
+        // Assume 1x
+        textureCaps.sampleCounts.insert(1);
+
+        for (unsigned int sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
+             sampleCount *= 2)
+        {
+            UINT qualityCount = 0;
+            if (SUCCEEDED(device->CheckMultisampleQualityLevels(renderFormat, sampleCount,
+                                                                &qualityCount)))
+            {
+                // Assume we always support lower sample counts
+                if (qualityCount == 0)
+                {
+                    break;
+                }
+                textureCaps.sampleCounts.insert(sampleCount);
+            }
+        }
+    }
+
+    return textureCaps;
+}
+
+bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return true;
+
+        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return false;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_MAX_MAXANISOTROPY;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_MAX_MAXANISOTROPY;
+
+        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+            return 16;
+
+        case D3D_FEATURE_LEVEL_9_1:
+            return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return true;
+
+        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+        // ID3D11Device::CreateQuery
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+            return true;
+        case D3D_FEATURE_LEVEL_9_1:
+            return false;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+    // ID3D11Device::CreateQuery
+
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return true;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+    // ID3D11Device::CreateInputLayout
+
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return true;
+
+        // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be
+        // instanced.
+        // D3D9 has a similar restriction, where stream 0 must not be instanced.
+        // This restriction can be worked around by remapping any non-instanced slot to slot
+        // 0.
+        // This works because HLSL uses shader semantics to match the vertex inputs to the
+        // elements in the input layout, rather than the slots.
+        // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3
+        // doesn't support OpenGL ES 3.0
+        case D3D_FEATURE_LEVEL_9_3:
+            return true;
+
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return false;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return true;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return false;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return true;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return false;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that
+    // shader model
+    // ps_2_x is required for the ddx (and other derivative functions).
+
+    // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that
+    // feature level
+    // 9.3 supports shader model ps_2_x.
+
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+        case D3D_FEATURE_LEVEL_9_3:
+            return true;
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return false;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return true;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return false;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
+{
+    // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+    // ID3D11Device::CreateInputLayout
+
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+        case D3D_FEATURE_LEVEL_9_3:
+            return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT;
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+        case D3D_FEATURE_LEVEL_9_3:
+            return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_REQ_TEXTURECUBE_DIMENSION;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_REQ_TEXTURECUBE_DIMENSION;
+
+        case D3D_FEATURE_LEVEL_9_3:
+            return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION;
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 0;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_VIEWPORT_BOUNDS_MAX;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_VIEWPORT_BOUNDS_MAX;
+
+        // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum
+        // texture sizes
+        case D3D_FEATURE_LEVEL_9_3:
+            return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
+{
+    // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
+    // that's what's
+    // returned from glGetInteger
+    static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
+                  "Unexpected D3D11 constant value.");
+    static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
+                  "Unexpected D3D11 constant value.");
+
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return std::numeric_limits<GLint>::max();
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+            return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
+        case D3D_FEATURE_LEVEL_9_1:
+            return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
+{
+    // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
+    // that's what's
+    // returned from glGetInteger
+    static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
+    static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
+
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return std::numeric_limits<GLint>::max();
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+            return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
+        case D3D_FEATURE_LEVEL_9_1:
+            return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
+
+        case D3D_FEATURE_LEVEL_10_1:
+            return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT;
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_STANDARD_VERTEX_ELEMENT_COUNT;
+
+        // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
+        // "Max Input Slots"
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 16;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+        // ID3D11DeviceContext::VSSetConstantBuffers
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 255 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel);
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+                   d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+                   d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+        // Uniform blocks not supported on D3D11 Feature Level 9
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 0;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+    // According to The OpenGL ES Shading Language specifications
+    // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21)
+    // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord)
+    // which are statically used in the shader should be included in the variable packing
+    // algorithm.
+    // Therefore, we should not reserve output vectors for them.
+
+    switch (featureLevel)
+    {
+        // We must reserve one output vector for dx_Position.
+        // We also reserve one for gl_Position, which we unconditionally output on Feature
+        // Levels 10_0+,
+        // even if it's unused in the shader (e.g. for transform feedback). TODO: This could
+        // be improved.
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return 2;
+
+        // Just reserve dx_Position on Feature Level 9, since we don't ever need to output
+        // gl_Position.
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 1;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+    static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT,
+                  "Unexpected D3D11 constant value.");
+
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+        case D3D_FEATURE_LEVEL_10_1:
+            return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+        // Use Shader Model 2.X limits
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 8 - GetReservedVertexOutputVectors(featureLevel);
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+        // Vertex textures not supported on D3D11 Feature Level 9 according to
+        // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+        // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 0;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+    // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return 1024;  // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return 1024;  // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+        // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+        // ID3D11DeviceContext::PSSetConstantBuffers
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 32 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel);
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+                   d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+                   d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+        // Uniform blocks not supported on D3D11 Feature Level 9
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 0;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+        // Use Shader Model 2.X limits
+        case D3D_FEATURE_LEVEL_9_3:
+            return 8 - GetReservedVertexOutputVectors(featureLevel);
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 8 - GetReservedVertexOutputVectors(featureLevel);
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+        // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+        // ID3D11DeviceContext::PSSetShaderResources
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 16;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+std::array<GLuint, 3> GetMaxComputeWorkGroupCount(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return {{D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
+                     D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
+                     D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION}};
+            break;
+        default:
+            return {{0, 0, 0}};
+    }
+}
+
+std::array<GLuint, 3> GetMaxComputeWorkGroupSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return {{D3D11_CS_THREAD_GROUP_MAX_X, D3D11_CS_THREAD_GROUP_MAX_Y,
+                     D3D11_CS_THREAD_GROUP_MAX_Z}};
+            break;
+        default:
+            return {{0, 0, 0}};
+    }
+}
+
+size_t GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
+        default:
+            return 0;
+    }
+}
+
+size_t GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+        default:
+            return 0;
+    }
+}
+
+size_t GetMaximumComputeUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+                   d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+        default:
+            return 0;
+    }
+}
+
+size_t GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+        default:
+            return 0;
+    }
+}
+
+int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
+
+        // Sampling functions with offsets are not available below shader model 4.0.
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 0;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
+
+        // Sampling functions with offsets are not available below shader model 4.0.
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 0;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
+{
+    // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum
+    // size of
+    // any buffer that could be allocated.
+
+    const size_t bytesPerComponent = 4 * sizeof(float);
+
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
+
+        // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx
+        // remarks section
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 4096 * bytesPerComponent;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return D3D11_SO_BUFFER_SLOT_COUNT;
+
+        case D3D_FEATURE_LEVEL_10_1:
+            return D3D10_1_SO_BUFFER_SLOT_COUNT;
+        case D3D_FEATURE_LEVEL_10_0:
+            return D3D10_SO_BUFFER_SLOT_COUNT;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 0;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return GetMaximumVertexOutputVectors(featureLevel) * 4;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 0;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
+                   GetMaximumStreamOutputBuffers(featureLevel);
+
+        // D3D 10 and 10.1 only allow one output per output slot if an output slot other
+        // than zero is used.
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return 4;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 0;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+IntelDriverVersion GetIntelDriverVersion(const Optional<LARGE_INTEGER> driverVersion)
+{
+    if (!driverVersion.valid())
+        return IntelDriverVersion(0);
+
+    // According to http://www.intel.com/content/www/us/en/support/graphics-drivers/000005654.html,
+    // only the fourth part is necessary since it stands for the driver specific unique version
+    // number.
+    WORD part = LOWORD(driverVersion.value().LowPart);
+    return IntelDriverVersion(part);
+}
+
+}  // anonymous namespace
+
+unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return 0;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 3;  // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+        case D3D_FEATURE_LEVEL_10_1:
+        case D3D_FEATURE_LEVEL_10_0:
+            return 0;
+
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return 3;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel)
+{
+    switch (featureLevel)
+    {
+        case D3D_FEATURE_LEVEL_11_1:
+        case D3D_FEATURE_LEVEL_11_0:
+            return gl::Version(3, 1);
+        case D3D_FEATURE_LEVEL_10_1:
+            return gl::Version(3, 0);
+
+        case D3D_FEATURE_LEVEL_10_0:
+        case D3D_FEATURE_LEVEL_9_3:
+        case D3D_FEATURE_LEVEL_9_2:
+        case D3D_FEATURE_LEVEL_9_1:
+            return gl::Version(2, 0);
+
+        default:
+            UNREACHABLE();
+            return gl::Version(0, 0);
+    }
+}
+
+void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps,
+                  gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations)
+{
+    GLuint maxSamples = 0;
+    D3D_FEATURE_LEVEL featureLevel = renderer11DeviceCaps.featureLevel;
+    const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
+    for (GLenum internalFormat : allFormats)
+    {
+        gl::TextureCaps textureCaps = GenerateTextureFormatCaps(
+            GetMaximumClientVersion(featureLevel), internalFormat, device, renderer11DeviceCaps);
+        textureCapsMap->insert(internalFormat, textureCaps);
+
+        maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
+
+        if (gl::GetSizedInternalFormatInfo(internalFormat).compressed)
+        {
+            caps->compressedTextureFormats.push_back(internalFormat);
+        }
+    }
+
+    // GL core feature limits
+    // Reserve MAX_UINT for D3D11's primitive restart.
+    caps->maxElementIndex       = static_cast<GLint64>(std::numeric_limits<unsigned int>::max() - 1);
+    caps->max3DTextureSize      = static_cast<GLuint>(GetMaximum3DTextureSize(featureLevel));
+    caps->max2DTextureSize      = static_cast<GLuint>(GetMaximum2DTextureSize(featureLevel));
+    caps->maxCubeMapTextureSize = static_cast<GLuint>(GetMaximumCubeMapTextureSize(featureLevel));
+    caps->maxArrayTextureLayers = static_cast<GLuint>(GetMaximum2DTextureArraySize(featureLevel));
+
+    // Unimplemented, set to minimum required
+    caps->maxLODBias = 2.0f;
+
+    // No specific limits on render target size, maximum 2D texture size is equivalent
+    caps->maxRenderbufferSize = caps->max2DTextureSize;
+
+    // Maximum draw buffers and color attachments are the same, max color attachments could eventually be
+    // increased to 16
+    caps->maxDrawBuffers = static_cast<GLuint>(GetMaximumSimultaneousRenderTargets(featureLevel));
+    caps->maxColorAttachments =
+        static_cast<GLuint>(GetMaximumSimultaneousRenderTargets(featureLevel));
+
+    // D3D11 has the same limit for viewport width and height
+    caps->maxViewportWidth  = static_cast<GLuint>(GetMaximumViewportSize(featureLevel));
+    caps->maxViewportHeight = caps->maxViewportWidth;
+
+    // Choose a reasonable maximum, enforced in the shader.
+    caps->minAliasedPointSize = 1.0f;
+    caps->maxAliasedPointSize = 1024.0f;
+
+    // Wide lines not supported
+    caps->minAliasedLineWidth = 1.0f;
+    caps->maxAliasedLineWidth = 1.0f;
+
+    // Primitive count limits
+    caps->maxElementsIndices  = static_cast<GLuint>(GetMaximumDrawIndexedIndexCount(featureLevel));
+    caps->maxElementsVertices = static_cast<GLuint>(GetMaximumDrawVertexCount(featureLevel));
+
+    // Program and shader binary formats (no supported shader binary formats)
+    caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
+
+    caps->vertexHighpFloat.setIEEEFloat();
+    caps->vertexMediumpFloat.setIEEEFloat();
+    caps->vertexLowpFloat.setIEEEFloat();
+    caps->fragmentHighpFloat.setIEEEFloat();
+    caps->fragmentMediumpFloat.setIEEEFloat();
+    caps->fragmentLowpFloat.setIEEEFloat();
+
+    // 32-bit integers are natively supported
+    caps->vertexHighpInt.setTwosComplementInt(32);
+    caps->vertexMediumpInt.setTwosComplementInt(32);
+    caps->vertexLowpInt.setTwosComplementInt(32);
+    caps->fragmentHighpInt.setTwosComplementInt(32);
+    caps->fragmentMediumpInt.setTwosComplementInt(32);
+    caps->fragmentLowpInt.setTwosComplementInt(32);
+
+    // We do not wait for server fence objects internally, so report a max timeout of zero.
+    caps->maxServerWaitTimeout = 0;
+
+    // Vertex shader limits
+    caps->maxVertexAttributes = static_cast<GLuint>(GetMaximumVertexInputSlots(featureLevel));
+    caps->maxVertexUniformComponents =
+        static_cast<GLuint>(GetMaximumVertexUniformVectors(featureLevel)) * 4;
+    caps->maxVertexUniformVectors =
+        static_cast<GLuint>(GetMaximumVertexUniformVectors(featureLevel));
+    caps->maxVertexUniformBlocks = static_cast<GLuint>(GetMaximumVertexUniformBlocks(featureLevel));
+    caps->maxVertexOutputComponents =
+        static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)) * 4;
+    caps->maxVertexTextureImageUnits =
+        static_cast<GLuint>(GetMaximumVertexTextureUnits(featureLevel));
+
+    // Vertex Attribute Bindings are emulated on D3D11.
+    caps->maxVertexAttribBindings = caps->maxVertexAttributes;
+    // Experimental testing confirmed there is no explicit limit on maximum buffer offset in D3D11.
+    caps->maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max();
+    // Experimental testing confirmed 2048 is the maximum stride that D3D11 can support on all
+    // platforms.
+    caps->maxVertexAttribStride = 2048;
+
+    // Fragment shader limits
+    caps->maxFragmentUniformComponents =
+        static_cast<GLuint>(GetMaximumPixelUniformVectors(featureLevel)) * 4;
+    caps->maxFragmentUniformVectors =
+        static_cast<GLuint>(GetMaximumPixelUniformVectors(featureLevel));
+    caps->maxFragmentUniformBlocks =
+        static_cast<GLuint>(GetMaximumPixelUniformBlocks(featureLevel));
+    caps->maxFragmentInputComponents =
+        static_cast<GLuint>(GetMaximumPixelInputVectors(featureLevel)) * 4;
+    caps->maxTextureImageUnits  = static_cast<GLuint>(GetMaximumPixelTextureUnits(featureLevel));
+    caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel);
+    caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel);
+
+    // Compute shader limits
+    caps->maxComputeWorkGroupCount = GetMaxComputeWorkGroupCount(featureLevel);
+    caps->maxComputeWorkGroupSize  = GetMaxComputeWorkGroupSize(featureLevel);
+    caps->maxComputeWorkGroupInvocations =
+        static_cast<GLuint>(GetMaxComputeWorkGroupInvocations(featureLevel));
+    caps->maxComputeUniformComponents =
+        static_cast<GLuint>(GetMaximumComputeUniformVectors(featureLevel)) * 4;
+    caps->maxComputeUniformBlocks =
+        static_cast<GLuint>(GetMaximumComputeUniformBlocks(featureLevel));
+    caps->maxComputeTextureImageUnits =
+        static_cast<GLuint>(GetMaximumComputeTextureUnits(featureLevel));
+
+    // Aggregate shader limits
+    caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks;
+    caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel);
+
+    // TODO(oetuaho): Get a more accurate limit. For now using the minimum requirement for GLES 3.1.
+    caps->maxUniformLocations = 1024;
+
+    // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16 bytes each.
+    // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
+    // With DirectX 11.0, we emulate UBO offsets using copies of ranges of the UBO however
+    // we still keep the same alignment as 11.1 for consistency.
+    caps->uniformBufferOffsetAlignment = 256;
+
+    caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks;
+    caps->maxCombinedVertexUniformComponents = (static_cast<GLint64>(caps->maxVertexUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) +
+                                               static_cast<GLint64>(caps->maxVertexUniformComponents);
+    caps->maxCombinedFragmentUniformComponents = (static_cast<GLint64>(caps->maxFragmentUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) +
+                                                 static_cast<GLint64>(caps->maxFragmentUniformComponents);
+    caps->maxCombinedComputeUniformComponents =
+        static_cast<GLuint>(caps->maxComputeUniformBlocks * (caps->maxUniformBlockSize / 4) +
+                            caps->maxComputeUniformComponents);
+    caps->maxVaryingComponents =
+        static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)) * 4;
+    caps->maxVaryingVectors            = static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel));
+    caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
+
+    // Transform feedback limits
+    caps->maxTransformFeedbackInterleavedComponents =
+        static_cast<GLuint>(GetMaximumStreamOutputInterleavedComponents(featureLevel));
+    caps->maxTransformFeedbackSeparateAttributes =
+        static_cast<GLuint>(GetMaximumStreamOutputBuffers(featureLevel));
+    caps->maxTransformFeedbackSeparateComponents =
+        static_cast<GLuint>(GetMaximumStreamOutputSeparateComponents(featureLevel));
+
+    // Multisample limits
+    caps->maxSamples = maxSamples;
+
+    // GL extension support
+    extensions->setTextureExtensionSupport(*textureCapsMap);
+    extensions->elementIndexUint = true;
+    extensions->getProgramBinary = true;
+    extensions->rgb8rgba8 = true;
+    extensions->readFormatBGRA = true;
+    extensions->pixelBufferObject = true;
+    extensions->mapBuffer = true;
+    extensions->mapBufferRange = true;
+    extensions->textureNPOT = GetNPOTTextureSupport(featureLevel);
+    extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
+    extensions->textureStorage = true;
+    extensions->textureFilterAnisotropic = true;
+    extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel);
+    extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel);
+    extensions->fence = GetEventQuerySupport(featureLevel);
+    extensions->timerQuery = false; // Unimplemented
+    extensions->disjointTimerQuery          = true;
+    extensions->queryCounterBitsTimeElapsed = 64;
+    extensions->queryCounterBitsTimestamp =
+        0;  // Timestamps cannot be supported due to D3D11 limitations
+    extensions->robustness = true;
+    extensions->blendMinMax = true;
+    extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel);
+    extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel);
+    extensions->instancedArrays = GetInstancingSupport(featureLevel);
+    extensions->packReverseRowOrder = true;
+    extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel);
+    extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel);
+    extensions->fragDepth = true;
+    extensions->textureUsage = true; // This could be false since it has no effect in D3D11
+    extensions->discardFramebuffer = true;
+    extensions->translatedShaderSource = true;
+    extensions->fboRenderMipmap = false;
+    extensions->debugMarker = true;
+    extensions->eglImage                 = true;
+    extensions->eglImageExternal          = true;
+    extensions->eglImageExternalEssl3     = true;
+    extensions->eglStreamConsumerExternal = true;
+    extensions->unpackSubimage           = true;
+    extensions->packSubimage             = true;
+    extensions->lossyETCDecode           = true;
+    extensions->syncQuery                 = GetEventQuerySupport(featureLevel);
+    extensions->copyTexture               = true;
+    extensions->copyCompressedTexture     = true;
+
+    // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
+    // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing.
+    limitations->noFrontFacingSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
+
+    // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage
+    limitations->noSampleAlphaToCoverageSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
+
+    // D3D11 Feature Levels 9_3 and below do not support non-constant loop indexing and require
+    // additional
+    // pre-validation of the shader at compile time to produce a better error message.
+    limitations->shadersRequireIndexedLoopValidation =
+        (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
+
+    // D3D11 has no concept of separate masks and refs for front and back faces in the depth stencil
+    // state.
+    limitations->noSeparateStencilRefsAndMasks = true;
+
+    // D3D11 cannot support constant color and alpha blend funcs together
+    limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true;
+
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    // Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era devices.
+    // We should prevent developers from doing this on ALL Windows Store devices. This will maintain consistency across all Windows devices.
+    // We allow non-zero divisors on attribute zero if the Client Version >= 3, since devices affected by this issue don't support ES3+.
+    limitations->attributeZeroRequiresZeroDivisorInEXT = true;
+#endif
+}
+
+}  // namespace d3d11_gl
+
+namespace gl_d3d11
+{
+
+D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
+{
+    D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
+
+    switch (glBlend)
+    {
+        case GL_ZERO:
+            d3dBlend = D3D11_BLEND_ZERO;
+            break;
+        case GL_ONE:
+            d3dBlend = D3D11_BLEND_ONE;
+            break;
+        case GL_SRC_COLOR:
+            d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR);
+            break;
+        case GL_ONE_MINUS_SRC_COLOR:
+            d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR);
+            break;
+        case GL_DST_COLOR:
+            d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR);
+            break;
+        case GL_ONE_MINUS_DST_COLOR:
+            d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR);
+            break;
+        case GL_SRC_ALPHA:
+            d3dBlend = D3D11_BLEND_SRC_ALPHA;
+            break;
+        case GL_ONE_MINUS_SRC_ALPHA:
+            d3dBlend = D3D11_BLEND_INV_SRC_ALPHA;
+            break;
+        case GL_DST_ALPHA:
+            d3dBlend = D3D11_BLEND_DEST_ALPHA;
+            break;
+        case GL_ONE_MINUS_DST_ALPHA:
+            d3dBlend = D3D11_BLEND_INV_DEST_ALPHA;
+            break;
+        case GL_CONSTANT_COLOR:
+            d3dBlend = D3D11_BLEND_BLEND_FACTOR;
+            break;
+        case GL_ONE_MINUS_CONSTANT_COLOR:
+            d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
+            break;
+        case GL_CONSTANT_ALPHA:
+            d3dBlend = D3D11_BLEND_BLEND_FACTOR;
+            break;
+        case GL_ONE_MINUS_CONSTANT_ALPHA:
+            d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
+            break;
+        case GL_SRC_ALPHA_SATURATE:
+            d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return d3dBlend;
+}
+
+D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
+{
+    D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
+
+    switch (glBlendOp)
+    {
+        case GL_FUNC_ADD:
+            d3dBlendOp = D3D11_BLEND_OP_ADD;
+            break;
+        case GL_FUNC_SUBTRACT:
+            d3dBlendOp = D3D11_BLEND_OP_SUBTRACT;
+            break;
+        case GL_FUNC_REVERSE_SUBTRACT:
+            d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT;
+            break;
+        case GL_MIN:
+            d3dBlendOp = D3D11_BLEND_OP_MIN;
+            break;
+        case GL_MAX:
+            d3dBlendOp = D3D11_BLEND_OP_MAX;
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return d3dBlendOp;
+}
+
+UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+    UINT8 mask = 0;
+    if (red)
+    {
+        mask |= D3D11_COLOR_WRITE_ENABLE_RED;
+    }
+    if (green)
+    {
+        mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
+    }
+    if (blue)
+    {
+        mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
+    }
+    if (alpha)
+    {
+        mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
+    }
+    return mask;
+}
+
+D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode)
+{
+    D3D11_CULL_MODE cull = D3D11_CULL_NONE;
+
+    if (cullEnabled)
+    {
+        switch (cullMode)
+        {
+            case GL_FRONT:
+                cull = D3D11_CULL_FRONT;
+                break;
+            case GL_BACK:
+                cull = D3D11_CULL_BACK;
+                break;
+            case GL_FRONT_AND_BACK:
+                cull = D3D11_CULL_NONE;
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+    else
+    {
+        cull = D3D11_CULL_NONE;
+    }
+
+    return cull;
+}
+
+D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
+{
+    D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
+    switch (comparison)
+    {
+        case GL_NEVER:
+            d3dComp = D3D11_COMPARISON_NEVER;
+            break;
+        case GL_ALWAYS:
+            d3dComp = D3D11_COMPARISON_ALWAYS;
+            break;
+        case GL_LESS:
+            d3dComp = D3D11_COMPARISON_LESS;
+            break;
+        case GL_LEQUAL:
+            d3dComp = D3D11_COMPARISON_LESS_EQUAL;
+            break;
+        case GL_EQUAL:
+            d3dComp = D3D11_COMPARISON_EQUAL;
+            break;
+        case GL_GREATER:
+            d3dComp = D3D11_COMPARISON_GREATER;
+            break;
+        case GL_GEQUAL:
+            d3dComp = D3D11_COMPARISON_GREATER_EQUAL;
+            break;
+        case GL_NOTEQUAL:
+            d3dComp = D3D11_COMPARISON_NOT_EQUAL;
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return d3dComp;
+}
+
+D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
+{
+    return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
+}
+
+UINT8 ConvertStencilMask(GLuint stencilmask)
+{
+    return static_cast<UINT8>(stencilmask);
+}
+
+D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
+{
+    D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
+
+    switch (stencilOp)
+    {
+        case GL_ZERO:
+            d3dStencilOp = D3D11_STENCIL_OP_ZERO;
+            break;
+        case GL_KEEP:
+            d3dStencilOp = D3D11_STENCIL_OP_KEEP;
+            break;
+        case GL_REPLACE:
+            d3dStencilOp = D3D11_STENCIL_OP_REPLACE;
+            break;
+        case GL_INCR:
+            d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT;
+            break;
+        case GL_DECR:
+            d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT;
+            break;
+        case GL_INVERT:
+            d3dStencilOp = D3D11_STENCIL_OP_INVERT;
+            break;
+        case GL_INCR_WRAP:
+            d3dStencilOp = D3D11_STENCIL_OP_INCR;
+            break;
+        case GL_DECR_WRAP:
+            d3dStencilOp = D3D11_STENCIL_OP_DECR;
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return d3dStencilOp;
+}
+
+D3D11_FILTER ConvertFilter(GLenum minFilter,
+                           GLenum magFilter,
+                           float maxAnisotropy,
+                           GLenum comparisonMode)
+{
+    bool comparison = comparisonMode != GL_NONE;
+
+    if (maxAnisotropy > 1.0f)
+    {
+        return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison));
+    }
+    else
+    {
+        D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
+        D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
+        switch (minFilter)
+        {
+            case GL_NEAREST:
+                dxMin = D3D11_FILTER_TYPE_POINT;
+                dxMip = D3D11_FILTER_TYPE_POINT;
+                break;
+            case GL_LINEAR:
+                dxMin = D3D11_FILTER_TYPE_LINEAR;
+                dxMip = D3D11_FILTER_TYPE_POINT;
+                break;
+            case GL_NEAREST_MIPMAP_NEAREST:
+                dxMin = D3D11_FILTER_TYPE_POINT;
+                dxMip = D3D11_FILTER_TYPE_POINT;
+                break;
+            case GL_LINEAR_MIPMAP_NEAREST:
+                dxMin = D3D11_FILTER_TYPE_LINEAR;
+                dxMip = D3D11_FILTER_TYPE_POINT;
+                break;
+            case GL_NEAREST_MIPMAP_LINEAR:
+                dxMin = D3D11_FILTER_TYPE_POINT;
+                dxMip = D3D11_FILTER_TYPE_LINEAR;
+                break;
+            case GL_LINEAR_MIPMAP_LINEAR:
+                dxMin = D3D11_FILTER_TYPE_LINEAR;
+                dxMip = D3D11_FILTER_TYPE_LINEAR;
+                break;
+            default:
+                UNREACHABLE();
+        }
+
+        D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
+        switch (magFilter)
+        {
+            case GL_NEAREST:
+                dxMag = D3D11_FILTER_TYPE_POINT;
+                break;
+            case GL_LINEAR:
+                dxMag = D3D11_FILTER_TYPE_LINEAR;
+                break;
+            default:
+                UNREACHABLE();
+        }
+
+        return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip,
+                                         static_cast<D3D11_COMPARISON_FUNC>(comparison));
+    }
+}
+
+D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
+{
+    switch (wrap)
+    {
+        case GL_REPEAT:
+            return D3D11_TEXTURE_ADDRESS_WRAP;
+        case GL_CLAMP_TO_EDGE:
+            return D3D11_TEXTURE_ADDRESS_CLAMP;
+        case GL_MIRRORED_REPEAT:
+            return D3D11_TEXTURE_ADDRESS_MIRROR;
+        default:
+            UNREACHABLE();
+    }
+
+    return D3D11_TEXTURE_ADDRESS_WRAP;
+}
+
+UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel)
+{
+    return static_cast<UINT>(std::min(maxAnisotropy, d3d11_gl::GetMaximumAnisotropy(featureLevel)));
+}
+
+D3D11_QUERY ConvertQueryType(GLenum queryType)
+{
+    switch (queryType)
+    {
+        case GL_ANY_SAMPLES_PASSED_EXT:
+        case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+            return D3D11_QUERY_OCCLUSION;
+        case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+            return D3D11_QUERY_SO_STATISTICS;
+        case GL_TIME_ELAPSED_EXT:
+            // Two internal queries are also created for begin/end timestamps
+            return D3D11_QUERY_TIMESTAMP_DISJOINT;
+        case GL_COMMANDS_COMPLETED_CHROMIUM:
+            return D3D11_QUERY_EVENT;
+        default:
+            UNREACHABLE();
+            return D3D11_QUERY_EVENT;
+    }
+}
+
+// Get the D3D11 write mask covering all color channels of a given format
+UINT8 GetColorMask(const gl::InternalFormat *formatInfo)
+{
+    UINT8 mask = 0;
+    if (formatInfo->redBits > 0)
+    {
+        mask |= D3D11_COLOR_WRITE_ENABLE_RED;
+    }
+    if (formatInfo->greenBits > 0)
+    {
+        mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
+    }
+    if (formatInfo->blueBits > 0)
+    {
+        mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
+    }
+    if (formatInfo->alphaBits > 0)
+    {
+        mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
+    }
+    return mask;
+}
+
+}  // namespace gl_d3d11
+
+namespace d3d11
+{
+
+ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
+{
+    // Note that this function returns an ANGLED3D11DeviceType rather than a D3D_DRIVER_TYPE value,
+    // since it is difficult to tell Software and Reference devices apart
+
+    IDXGIDevice *dxgiDevice     = nullptr;
+    IDXGIAdapter *dxgiAdapter   = nullptr;
+    IDXGIAdapter2 *dxgiAdapter2 = nullptr;
+
+    ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN;
+
+    HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
+    if (SUCCEEDED(hr))
+    {
+        hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&dxgiAdapter);
+        if (SUCCEEDED(hr))
+        {
+            std::wstring adapterString;
+            HRESULT adapter2hr =
+                dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2);
+            if (SUCCEEDED(adapter2hr))
+            {
+                // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter"
+                // for the description string. Try to use IDXGIAdapter2::GetDesc2 to get the
+                // actual hardware values if possible.
+                DXGI_ADAPTER_DESC2 adapterDesc2;
+                dxgiAdapter2->GetDesc2(&adapterDesc2);
+                adapterString = std::wstring(adapterDesc2.Description);
+            }
+            else
+            {
+                DXGI_ADAPTER_DESC adapterDesc;
+                dxgiAdapter->GetDesc(&adapterDesc);
+                adapterString = std::wstring(adapterDesc.Description);
+            }
+
+            // Both Reference and Software adapters will be 'Software Adapter'
+            const bool isSoftwareDevice =
+                (adapterString.find(std::wstring(L"Software Adapter")) != std::string::npos);
+            const bool isNullDevice = (adapterString == L"");
+            const bool isWARPDevice =
+                (adapterString.find(std::wstring(L"Basic Render")) != std::string::npos);
+
+            if (isSoftwareDevice || isNullDevice)
+            {
+                ASSERT(!isWARPDevice);
+                retDeviceType = ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
+            }
+            else if (isWARPDevice)
+            {
+                retDeviceType = ANGLE_D3D11_DEVICE_TYPE_WARP;
+            }
+            else
+            {
+                retDeviceType = ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
+            }
+        }
+    }
+
+    SafeRelease(dxgiDevice);
+    SafeRelease(dxgiAdapter);
+    SafeRelease(dxgiAdapter2);
+
+    return retDeviceType;
+}
+
+void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
+{
+    const DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(format);
+
+    int upsampleCount = 0;
+    // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
+    if (isImage || *requestWidth  < static_cast<GLsizei>(dxgiFormatInfo.blockWidth) ||
+                   *requestHeight < static_cast<GLsizei>(dxgiFormatInfo.blockHeight))
+    {
+        while (*requestWidth % dxgiFormatInfo.blockWidth != 0 || *requestHeight % dxgiFormatInfo.blockHeight != 0)
+        {
+            *requestWidth <<= 1;
+            *requestHeight <<= 1;
+            upsampleCount++;
+        }
+    }
+    *levelOffset = upsampleCount;
+}
+
+void GenerateInitialTextureData(GLint internalFormat,
+                                const Renderer11DeviceCaps &renderer11DeviceCaps,
+                                GLuint width,
+                                GLuint height,
+                                GLuint depth,
+                                GLuint mipLevels,
+                                std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
+                                std::vector<std::vector<BYTE>> *outData)
+{
+    const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+    ASSERT(d3dFormatInfo.dataInitializerFunction != nullptr);
+
+    const d3d11::DXGIFormatSize &dxgiFormatInfo =
+        d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
+
+    outSubresourceData->resize(mipLevels);
+    outData->resize(mipLevels);
+
+    for (unsigned int i = 0; i < mipLevels; i++)
+    {
+        unsigned int mipWidth = std::max(width >> i, 1U);
+        unsigned int mipHeight = std::max(height >> i, 1U);
+        unsigned int mipDepth = std::max(depth >> i, 1U);
+
+        unsigned int rowWidth = dxgiFormatInfo.pixelBytes * mipWidth;
+        unsigned int imageSize = rowWidth * height;
+
+        outData->at(i).resize(rowWidth * mipHeight * mipDepth);
+        d3dFormatInfo.dataInitializerFunction(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize);
+
+        outSubresourceData->at(i).pSysMem = outData->at(i).data();
+        outSubresourceData->at(i).SysMemPitch = rowWidth;
+        outSubresourceData->at(i).SysMemSlicePitch = imageSize;
+    }
+}
+
+UINT GetPrimitiveRestartIndex()
+{
+    return std::numeric_limits<UINT>::max();
+}
+
+void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v)
+{
+    vertex->x = x;
+    vertex->y = y;
+    vertex->u = u;
+    vertex->v = v;
+}
+
+void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y,
+                                      unsigned int layer, float u, float v, float s)
+{
+    vertex->x = x;
+    vertex->y = y;
+    vertex->l = layer;
+    vertex->u = u;
+    vertex->v = v;
+    vertex->s = s;
+}
+
+HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
+{
+#if defined(_DEBUG)
+    UINT existingDataSize = 0;
+    resource->GetPrivateData(WKPDID_D3DDebugObjectName, &existingDataSize, nullptr);
+    // Don't check the HRESULT- if it failed then that probably just means that no private data
+    // exists yet
+
+    if (existingDataSize > 0)
+    {
+        // In some cases, ANGLE will try to apply two names to one object, which causes
+        // a D3D SDK Layers warning. This can occur if, for example, you 'create' two objects
+        // (e.g.Rasterizer States) with identical DESCs on the same device. D3D11 will optimize
+        // these calls and return the same object both times.
+        static const char *multipleNamesUsed = "Multiple names set by ANGLE";
+
+        // Remove the existing name
+        HRESULT hr = resource->SetPrivateData(WKPDID_D3DDebugObjectName, 0, nullptr);
+        if (FAILED(hr))
+        {
+            return hr;
+        }
+
+        // Apply the new name
+        return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
+                                        static_cast<unsigned int>(strlen(multipleNamesUsed)),
+                                        multipleNamesUsed);
+    }
+    else
+    {
+        return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
+                                        static_cast<unsigned int>(strlen(name)), name);
+    }
+#else
+    return S_OK;
+#endif
+}
+
+LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
+                                 size_t inputDescLen,
+                                 const BYTE *byteCode,
+                                 size_t byteCodeLen,
+                                 const char *debugName)
+    : mInputDesc(inputDescLen),
+      mByteCodeLen(byteCodeLen),
+      mByteCode(byteCode),
+      mDebugName(debugName)
+{
+    if (inputDesc)
+    {
+        memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen);
+    }
+}
+
+ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device)
+{
+    checkAssociatedDevice(device);
+
+    if (mResource == nullptr && mByteCode != nullptr)
+    {
+        HRESULT result =
+            device->CreateInputLayout(&mInputDesc[0], static_cast<UINT>(mInputDesc.size()),
+                                      mByteCode, mByteCodeLen, &mResource);
+        ASSERT(SUCCEEDED(result));
+        d3d11::SetDebugName(mResource, mDebugName);
+    }
+
+    return mResource;
+}
+
+LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
+    : mDesc(desc), mDebugName(debugName)
+{
+}
+
+ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device)
+{
+    checkAssociatedDevice(device);
+
+    if (mResource == nullptr)
+    {
+        HRESULT result = device->CreateBlendState(&mDesc, &mResource);
+        ASSERT(SUCCEEDED(result));
+        d3d11::SetDebugName(mResource, mDebugName);
+    }
+
+    return mResource;
+}
+
+angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
+                                          const DXGI_ADAPTER_DESC &adapterDesc)
+{
+    bool is9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
+
+    angle::WorkaroundsD3D workarounds;
+    workarounds.mrtPerfWorkaround = true;
+    workarounds.setDataFasterThanImageUpload = true;
+    workarounds.zeroMaxLodWorkaround             = is9_3;
+    workarounds.useInstancedPointSpriteEmulation = is9_3;
+
+    // TODO(jmadill): Narrow problematic driver range.
+    if (IsNvidia(adapterDesc.VendorId))
+    {
+        if (deviceCaps.driverVersion.valid())
+        {
+            WORD part1 = HIWORD(deviceCaps.driverVersion.value().LowPart);
+            WORD part2 = LOWORD(deviceCaps.driverVersion.value().LowPart);
+
+            // Disable the workaround to fix a second driver bug on newer NVIDIA.
+            workarounds.depthStencilBlitExtraCopy = (part1 <= 13u && part2 < 6881);
+        }
+        else
+        {
+            workarounds.depthStencilBlitExtraCopy = true;
+        }
+    }
+
+    // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
+    workarounds.expandIntegerPowExpressions = true;
+
+    workarounds.flushAfterEndingTransformFeedback = IsNvidia(adapterDesc.VendorId);
+    workarounds.getDimensionsIgnoresBaseLevel     = IsNvidia(adapterDesc.VendorId);
+
+    if (IsIntel(adapterDesc.VendorId))
+    {
+        workarounds.preAddTexelFetchOffsets           = true;
+        workarounds.useSystemMemoryForConstantBuffers = true;
+        workarounds.disableB5G6R5Support =
+            d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion) < IntelDriverVersion(4539);
+        if (IsSkylake(adapterDesc.DeviceId))
+        {
+            workarounds.callClearTwiceOnSmallTarget = true;
+            workarounds.emulateIsnanFloat =
+                d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion) <
+                IntelDriverVersion(4542);
+        }
+        else if (IsBroadwell(adapterDesc.DeviceId) || IsHaswell(adapterDesc.DeviceId))
+        {
+            workarounds.rewriteUnaryMinusOperator =
+                d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion) <
+                IntelDriverVersion(4624);
+        }
+    }
+
+    // TODO(jmadill): Disable when we have a fixed driver version.
+    workarounds.emulateTinyStencilTextures = IsAMD(adapterDesc.VendorId);
+
+    // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a
+    // depth stencil texture.  This is not allowed until feature level 10.1 but since it is not
+    // possible to support ES3 on these devices, there is no need for the workaround to begin with
+    // (anglebug.com/1572).
+    if (deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1)
+    {
+        workarounds.emulateTinyStencilTextures = false;
+    }
+
+    // Call platform hooks for testing overrides.
+    auto *platform = ANGLEPlatformCurrent();
+    platform->overrideWorkaroundsD3D(platform, &workarounds);
+
+    return workarounds;
+}
+
+void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth)
+{
+    constantBufferDescription->ByteWidth           = static_cast<UINT>(byteWidth);
+    constantBufferDescription->Usage               = D3D11_USAGE_DYNAMIC;
+    constantBufferDescription->BindFlags           = D3D11_BIND_CONSTANT_BUFFER;
+    constantBufferDescription->CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
+    constantBufferDescription->MiscFlags           = 0;
+    constantBufferDescription->StructureByteStride = 0;
+}
+
+}  // namespace d3d11
+
+TextureHelper11::TextureHelper11()
+    : mTextureType(GL_NONE),
+      mFormat(DXGI_FORMAT_UNKNOWN),
+      mFormatSet(nullptr),
+      mSampleCount(0),
+      mTexture2D(nullptr),
+      mTexture3D(nullptr)
+{
+}
+
+TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy)
+    : mTextureType(toCopy.mTextureType),
+      mExtents(toCopy.mExtents),
+      mFormat(toCopy.mFormat),
+      mFormatSet(toCopy.mFormatSet),
+      mSampleCount(toCopy.mSampleCount),
+      mTexture2D(toCopy.mTexture2D),
+      mTexture3D(toCopy.mTexture3D)
+{
+    toCopy.reset();
+}
+
+// static
+TextureHelper11 TextureHelper11::MakeAndReference(ID3D11Resource *genericResource,
+                                                  const d3d11::Format &formatSet)
+{
+    TextureHelper11 newHelper;
+    newHelper.mFormatSet   = &formatSet;
+    newHelper.mTexture2D   = d3d11::DynamicCastComObject<ID3D11Texture2D>(genericResource);
+    newHelper.mTexture3D   = d3d11::DynamicCastComObject<ID3D11Texture3D>(genericResource);
+    newHelper.mTextureType = newHelper.mTexture2D ? GL_TEXTURE_2D : GL_TEXTURE_3D;
+    newHelper.initDesc();
+    return newHelper;
+}
+
+// static
+TextureHelper11 TextureHelper11::MakeAndPossess2D(ID3D11Texture2D *texToOwn,
+                                                  const d3d11::Format &formatSet)
+{
+    TextureHelper11 newHelper;
+    newHelper.mFormatSet   = &formatSet;
+    newHelper.mTexture2D   = texToOwn;
+    newHelper.mTextureType = GL_TEXTURE_2D;
+    newHelper.initDesc();
+    return newHelper;
+}
+
+// static
+TextureHelper11 TextureHelper11::MakeAndPossess3D(ID3D11Texture3D *texToOwn,
+                                                  const d3d11::Format &formatSet)
+{
+    TextureHelper11 newHelper;
+    newHelper.mFormatSet   = &formatSet;
+    newHelper.mTexture3D   = texToOwn;
+    newHelper.mTextureType = GL_TEXTURE_3D;
+    newHelper.initDesc();
+    return newHelper;
+}
+
+void TextureHelper11::initDesc()
+{
+    if (mTextureType == GL_TEXTURE_2D)
+    {
+        ASSERT(!mTexture3D);
+        D3D11_TEXTURE2D_DESC desc2D;
+        mTexture2D->GetDesc(&desc2D);
+
+        mExtents.width  = static_cast<int>(desc2D.Width);
+        mExtents.height = static_cast<int>(desc2D.Height);
+        mExtents.depth  = 1;
+        mFormat         = desc2D.Format;
+        mSampleCount    = desc2D.SampleDesc.Count;
+    }
+    else
+    {
+        ASSERT(mTexture3D && mTextureType == GL_TEXTURE_3D);
+        D3D11_TEXTURE3D_DESC desc3D;
+        mTexture3D->GetDesc(&desc3D);
+
+        mExtents.width  = static_cast<int>(desc3D.Width);
+        mExtents.height = static_cast<int>(desc3D.Height);
+        mExtents.depth  = static_cast<int>(desc3D.Depth);
+        mFormat         = desc3D.Format;
+        mSampleCount    = 1;
+    }
+    ASSERT(mFormatSet && mFormat == mFormatSet->texFormat);
+}
+
+TextureHelper11::~TextureHelper11()
+{
+    SafeRelease(mTexture2D);
+    SafeRelease(mTexture3D);
+}
+
+ID3D11Resource *TextureHelper11::getResource() const
+{
+    return mTexture2D ? static_cast<ID3D11Resource *>(mTexture2D)
+                      : static_cast<ID3D11Resource *>(mTexture3D);
+}
+
+TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&texture)
+{
+    SafeRelease(mTexture2D);
+    SafeRelease(mTexture3D);
+
+    mTextureType = texture.mTextureType;
+    mExtents     = texture.mExtents;
+    mFormat      = texture.mFormat;
+    mFormatSet   = texture.mFormatSet;
+    mSampleCount = texture.mSampleCount;
+    mTexture2D   = texture.mTexture2D;
+    mTexture3D   = texture.mTexture3D;
+    texture.reset();
+    return *this;
+}
+
+void TextureHelper11::reset()
+{
+    mTextureType = GL_NONE;
+    mExtents     = gl::Extents();
+    mFormat      = DXGI_FORMAT_UNKNOWN;
+    mFormatSet   = nullptr;
+    mSampleCount = 0;
+    mTexture2D   = nullptr;
+    mTexture3D   = nullptr;
+}
+
+bool TextureHelper11::valid() const
+{
+    return (mTextureType != GL_NONE);
+}
+
+gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType,
+                                                        const d3d11::Format &formatSet,
+                                                        const gl::Extents &size,
+                                                        StagingAccess readAndWriteAccess,
+                                                        ID3D11Device *device)
+{
+    if (textureType == GL_TEXTURE_2D)
+    {
+        D3D11_TEXTURE2D_DESC stagingDesc;
+        stagingDesc.Width              = size.width;
+        stagingDesc.Height             = size.height;
+        stagingDesc.MipLevels          = 1;
+        stagingDesc.ArraySize          = 1;
+        stagingDesc.Format             = formatSet.texFormat;
+        stagingDesc.SampleDesc.Count   = 1;
+        stagingDesc.SampleDesc.Quality = 0;
+        stagingDesc.Usage              = D3D11_USAGE_STAGING;
+        stagingDesc.BindFlags          = 0;
+        stagingDesc.CPUAccessFlags     = D3D11_CPU_ACCESS_READ;
+        stagingDesc.MiscFlags          = 0;
+
+        if (readAndWriteAccess == StagingAccess::READ_WRITE)
+        {
+            stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE;
+        }
+
+        ID3D11Texture2D *stagingTex = nullptr;
+        HRESULT result = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTex);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.",
+                             result);
+        }
+
+        return TextureHelper11::MakeAndPossess2D(stagingTex, formatSet);
+    }
+    ASSERT(textureType == GL_TEXTURE_3D);
+
+    D3D11_TEXTURE3D_DESC stagingDesc;
+    stagingDesc.Width          = size.width;
+    stagingDesc.Height         = size.height;
+    stagingDesc.Depth          = 1;
+    stagingDesc.MipLevels      = 1;
+    stagingDesc.Format         = formatSet.texFormat;
+    stagingDesc.Usage          = D3D11_USAGE_STAGING;
+    stagingDesc.BindFlags      = 0;
+    stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+    stagingDesc.MiscFlags      = 0;
+
+    ID3D11Texture3D *stagingTex = nullptr;
+    HRESULT result = device->CreateTexture3D(&stagingDesc, nullptr, &stagingTex);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.",
+                         result);
+    }
+
+    return TextureHelper11::MakeAndPossess3D(stagingTex, formatSet);
+}
+
+bool UsePresentPathFast(const Renderer11 *renderer,
+                        const gl::FramebufferAttachment *framebufferAttachment)
+{
+    if (framebufferAttachment == nullptr)
+    {
+        return false;
+    }
+
+    return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT &&
+            renderer->presentPathFastEnabled());
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
new file mode 100644
index 0000000..0767bc9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
@@ -0,0 +1,428 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// renderer11_utils.h: Conversion functions and other utility routines
+// specific to the D3D11 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
+
+#include <array>
+#include <functional>
+#include <vector>
+
+#include "common/Color.h"
+
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+class Renderer11;
+class RenderTarget11;
+struct Renderer11DeviceCaps;
+
+using RenderTargetArray = std::array<RenderTarget11 *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+using RTVArray          = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+
+namespace gl_d3d11
+{
+
+D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha);
+D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp);
+UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha);
+
+D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode);
+
+D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison);
+D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled);
+UINT8 ConvertStencilMask(GLuint stencilmask);
+D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp);
+
+D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode);
+D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap);
+UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel);
+
+D3D11_QUERY ConvertQueryType(GLenum queryType);
+
+UINT8 GetColorMask(const gl::InternalFormat *formatInfo);
+
+}  // namespace gl_d3d11
+
+namespace d3d11_gl
+{
+
+unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel);
+
+unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel);
+
+gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel);
+void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps,
+                  gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations);
+
+}  // namespace d3d11_gl
+
+namespace d3d11
+{
+
+enum ANGLED3D11DeviceType
+{
+    ANGLE_D3D11_DEVICE_TYPE_UNKNOWN,
+    ANGLE_D3D11_DEVICE_TYPE_HARDWARE,
+    ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL,
+    ANGLE_D3D11_DEVICE_TYPE_WARP,
+};
+
+ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device);
+
+void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset);
+
+void GenerateInitialTextureData(GLint internalFormat,
+                                const Renderer11DeviceCaps &renderer11DeviceCaps,
+                                GLuint width,
+                                GLuint height,
+                                GLuint depth,
+                                GLuint mipLevels,
+                                std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
+                                std::vector<std::vector<BYTE>> *outData);
+
+UINT GetPrimitiveRestartIndex();
+
+struct PositionTexCoordVertex
+{
+    float x, y;
+    float u, v;
+};
+void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v);
+
+struct PositionLayerTexCoord3DVertex
+{
+    float x, y;
+    unsigned int l;
+    float u, v, s;
+};
+void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y,
+                                      unsigned int layer, float u, float v, float s);
+
+struct PositionVertex
+{
+    float x, y, z, w;
+};
+
+struct BlendStateKey
+{
+    gl::BlendState blendState;
+    bool mrt;
+    uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
+};
+
+HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name);
+
+template <typename T>
+HRESULT SetDebugName(angle::ComPtr<T> &resource, const char *name)
+{
+    return SetDebugName(resource.Get(), name);
+}
+
+template <typename outType>
+outType* DynamicCastComObject(IUnknown* object)
+{
+    outType *outObject = nullptr;
+    HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast<void**>(&outObject));
+    if (SUCCEEDED(result))
+    {
+        return outObject;
+    }
+    else
+    {
+        SafeRelease(outObject);
+        return nullptr;
+    }
+}
+
+inline bool isDeviceLostError(HRESULT errorCode)
+{
+    switch (errorCode)
+    {
+      case DXGI_ERROR_DEVICE_HUNG:
+      case DXGI_ERROR_DEVICE_REMOVED:
+      case DXGI_ERROR_DEVICE_RESET:
+      case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
+      case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
+        return true;
+      default:
+        return false;
+    }
+}
+
+inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name)
+{
+    ID3D11VertexShader *vs = nullptr;
+    HRESULT result = device->CreateVertexShader(byteCode, N, nullptr, &vs);
+    ASSERT(SUCCEEDED(result));
+    if (SUCCEEDED(result))
+    {
+        SetDebugName(vs, name);
+        return vs;
+    }
+    return nullptr;
+}
+
+template <unsigned int N>
+ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+{
+    return CompileVS(device, byteCode, N, name);
+}
+
+inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name)
+{
+    ID3D11GeometryShader *gs = nullptr;
+    HRESULT result = device->CreateGeometryShader(byteCode, N, nullptr, &gs);
+    ASSERT(SUCCEEDED(result));
+    if (SUCCEEDED(result))
+    {
+        SetDebugName(gs, name);
+        return gs;
+    }
+    return nullptr;
+}
+
+template <unsigned int N>
+ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+{
+    return CompileGS(device, byteCode, N, name);
+}
+
+inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name)
+{
+    ID3D11PixelShader *ps = nullptr;
+    HRESULT result = device->CreatePixelShader(byteCode, N, nullptr, &ps);
+    ASSERT(SUCCEEDED(result));
+    if (SUCCEEDED(result))
+    {
+        SetDebugName(ps, name);
+        return ps;
+    }
+    return nullptr;
+}
+
+template <unsigned int N>
+ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+{
+    return CompilePS(device, byteCode, N, name);
+}
+
+template <typename ResourceType>
+class LazyResource : angle::NonCopyable
+{
+  public:
+    LazyResource() : mResource(nullptr), mAssociatedDevice(nullptr) {}
+    virtual ~LazyResource() { release(); }
+
+    virtual ResourceType *resolve(ID3D11Device *device) = 0;
+    void release() { SafeRelease(mResource); }
+
+  protected:
+    void checkAssociatedDevice(ID3D11Device *device);
+
+    ResourceType *mResource;
+    ID3D11Device *mAssociatedDevice;
+};
+
+template <typename ResourceType>
+void LazyResource<ResourceType>::checkAssociatedDevice(ID3D11Device *device)
+{
+    ASSERT(mAssociatedDevice == nullptr || device == mAssociatedDevice);
+    mAssociatedDevice = device;
+}
+
+template <typename D3D11ShaderType>
+class LazyShader final : public LazyResource<D3D11ShaderType>
+{
+  public:
+    // All parameters must be constexpr. Not supported in VS2013.
+    LazyShader(const BYTE *byteCode,
+               size_t byteCodeSize,
+               const char *name)
+        : mByteCode(byteCode),
+          mByteCodeSize(byteCodeSize),
+          mName(name)
+    {
+    }
+
+    D3D11ShaderType *resolve(ID3D11Device *device) override;
+
+  private:
+    const BYTE *mByteCode;
+    size_t mByteCodeSize;
+    const char *mName;
+};
+
+template <>
+inline ID3D11VertexShader *LazyShader<ID3D11VertexShader>::resolve(ID3D11Device *device)
+{
+    checkAssociatedDevice(device);
+    if (mResource == nullptr)
+    {
+        mResource = CompileVS(device, mByteCode, mByteCodeSize, mName);
+    }
+    return mResource;
+}
+
+template <>
+inline ID3D11GeometryShader *LazyShader<ID3D11GeometryShader>::resolve(ID3D11Device *device)
+{
+    checkAssociatedDevice(device);
+    if (mResource == nullptr)
+    {
+        mResource = CompileGS(device, mByteCode, mByteCodeSize, mName);
+    }
+    return mResource;
+}
+
+template <>
+inline ID3D11PixelShader *LazyShader<ID3D11PixelShader>::resolve(ID3D11Device *device)
+{
+    checkAssociatedDevice(device);
+    if (mResource == nullptr)
+    {
+        mResource = CompilePS(device, mByteCode, mByteCodeSize, mName);
+    }
+    return mResource;
+}
+
+class LazyInputLayout final : public LazyResource<ID3D11InputLayout>
+{
+  public:
+    LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
+                    size_t inputDescLen,
+                    const BYTE *byteCode,
+                    size_t byteCodeLen,
+                    const char *debugName);
+
+    ID3D11InputLayout *resolve(ID3D11Device *device) override;
+
+  private:
+    std::vector<D3D11_INPUT_ELEMENT_DESC> mInputDesc;
+    size_t mByteCodeLen;
+    const BYTE *mByteCode;
+    const char *mDebugName;
+};
+
+class LazyBlendState final : public LazyResource<ID3D11BlendState>
+{
+  public:
+    LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);
+
+    ID3D11BlendState *resolve(ID3D11Device *device) override;
+
+  private:
+    D3D11_BLEND_DESC mDesc;
+    const char *mDebugName;
+};
+
+// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to
+// represent an entire buffer.
+template <class T>
+void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value)
+{
+    D3D11_MAPPED_SUBRESOURCE mappedResource = {};
+    HRESULT result = context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    ASSERT(SUCCEEDED(result));
+    if (SUCCEEDED(result))
+    {
+        memcpy(mappedResource.pData, &value, sizeof(T));
+        context->Unmap(constantBuffer, 0);
+    }
+}
+
+angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
+                                          const DXGI_ADAPTER_DESC &adapterDesc);
+
+enum ReservedConstantBufferSlot
+{
+    RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK = 0,
+    RESERVED_CONSTANT_BUFFER_SLOT_DRIVER                = 1,
+
+    RESERVED_CONSTANT_BUFFER_SLOT_COUNT = 2
+};
+
+void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth);
+}  // namespace d3d11
+
+// A helper class which wraps a 2D or 3D texture.
+class TextureHelper11 : angle::NonCopyable
+{
+  public:
+    TextureHelper11();
+    TextureHelper11(TextureHelper11 &&toCopy);
+    ~TextureHelper11();
+    TextureHelper11 &operator=(TextureHelper11 &&texture);
+
+    static TextureHelper11 MakeAndReference(ID3D11Resource *genericResource,
+                                            const d3d11::Format &formatSet);
+    static TextureHelper11 MakeAndPossess2D(ID3D11Texture2D *texToOwn,
+                                            const d3d11::Format &formatSet);
+    static TextureHelper11 MakeAndPossess3D(ID3D11Texture3D *texToOwn,
+                                            const d3d11::Format &formatSet);
+
+    GLenum getTextureType() const { return mTextureType; }
+    gl::Extents getExtents() const { return mExtents; }
+    DXGI_FORMAT getFormat() const { return mFormat; }
+    const d3d11::Format &getFormatSet() const { return *mFormatSet; }
+    int getSampleCount() const { return mSampleCount; }
+    ID3D11Texture2D *getTexture2D() const { return mTexture2D; }
+    ID3D11Texture3D *getTexture3D() const { return mTexture3D; }
+    ID3D11Resource *getResource() const;
+    bool valid() const;
+
+  private:
+    void reset();
+    void initDesc();
+
+    GLenum mTextureType;
+    gl::Extents mExtents;
+    DXGI_FORMAT mFormat;
+    const d3d11::Format *mFormatSet;
+    int mSampleCount;
+    ID3D11Texture2D *mTexture2D;
+    ID3D11Texture3D *mTexture3D;
+};
+
+enum class StagingAccess
+{
+    READ,
+    READ_WRITE,
+};
+
+gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType,
+                                                        const d3d11::Format &formatSet,
+                                                        const gl::Extents &size,
+                                                        StagingAccess readAndWriteAccess,
+                                                        ID3D11Device *device);
+
+bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer);
+
+// Used for state change notifications between buffers and vertex arrays.
+using OnBufferDataDirtyBinding  = angle::ChannelBinding<size_t>;
+using OnBufferDataDirtyChannel  = angle::BroadcastChannel<size_t>;
+using OnBufferDataDirtyReceiver = angle::SignalReceiver<size_t>;
+
+// Used for state change notifications between RenderTarget11 and Framebuffer11.
+using OnRenderTargetDirtyBinding  = angle::ChannelBinding<size_t>;
+using OnRenderTargetDirtyChannel  = angle::BroadcastChannel<size_t>;
+using OnRenderTargetDirtyReceiver = angle::SignalReceiver<size_t>;
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
new file mode 100644
index 0000000..c43734f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
@@ -0,0 +1,77 @@
+Buffer<float4>    Buffer4F  : register(t0);
+Buffer<int4>      Buffer4I  : register(t0);
+Buffer<uint4>     Buffer4UI : register(t0);
+
+struct VS_OUTPUT
+{
+    float4 position : SV_Position;
+    uint index      : TEXCOORD0;
+    uint slice      : LAYER;
+};
+
+struct GS_OUTPUT
+{
+    float4 position : SV_Position;
+    uint index      : TEXCOORD0;
+    uint slice      : SV_RenderTargetArrayIndex;
+};
+
+cbuffer BufferCopyParams : register(b0)
+{
+    uint FirstPixelOffset;
+    uint PixelsPerRow;
+    uint RowStride;
+    uint RowsPerSlice;
+    float2 PositionOffset;
+    float2 PositionScale;
+    int2 TexLocationOffset;
+    int2 TexLocationScale;
+    uint FirstSlice;
+}
+
+void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex)
+{
+    uint PixelsPerSlice = PixelsPerRow * RowsPerSlice;
+    uint SliceStride    = RowStride * RowsPerSlice;
+
+    uint slice          = vertexID / PixelsPerSlice;
+    uint sliceOffset    = slice * PixelsPerSlice;
+    uint row            = (vertexID - sliceOffset) / PixelsPerRow;
+    uint col            = vertexID - sliceOffset - (row * PixelsPerRow);
+
+    float2 coords       = float2(float(col), float(row));
+
+    outVertex.position  = float4(PositionOffset + PositionScale * coords, 0.0f, 1.0f);
+    outVertex.index     = FirstPixelOffset + slice * SliceStride + row * RowStride + col;
+    outVertex.slice     = FirstSlice + slice;
+}
+
+void VS_BufferToTexture(in uint vertexID : SV_VertexID, out VS_OUTPUT outVertex)
+{
+    ComputePositionAndIndex(vertexID, outVertex);
+}
+
+[maxvertexcount(1)]
+void GS_BufferToTexture(point VS_OUTPUT inVertex[1], inout PointStream<GS_OUTPUT> outStream)
+{
+    GS_OUTPUT outVertex;
+    outVertex.position  = inVertex[0].position;
+    outVertex.index     = inVertex[0].index;
+    outVertex.slice     = inVertex[0].slice;
+    outStream.Append(outVertex);
+}
+
+float4 PS_BufferToTexture_4F(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target
+{
+    return Buffer4F.Load(inIndex);
+}
+
+int4 PS_BufferToTexture_4I(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target
+{
+    return Buffer4I.Load(inIndex);
+}
+
+uint4 PS_BufferToTexture_4UI(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target
+{
+    return Buffer4UI.Load(inIndex);
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
new file mode 100644
index 0000000..771dad3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
@@ -0,0 +1,162 @@
+//
+// Copyright (c) 2017 The ANGLE Project. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Clear11.hlsl: Shaders for clearing RTVs and DSVs using draw calls and
+// specifying float depth values and either float, uint or sint clear colors.
+// Notes:
+//  - UINT & SINT clears can only be compiled with FL10+
+//  - VS_Clear_FL9 requires a VB to be bound with vertices to create
+//    a primitive covering the entire surface (in clip co-ordinates)
+
+// Constants
+static const float2 g_Corners[6] =
+{
+    float2(-1.0f,  1.0f),
+    float2( 1.0f, -1.0f),
+    float2(-1.0f, -1.0f),
+    float2(-1.0f,  1.0f),
+    float2( 1.0f,  1.0f),
+    float2( 1.0f, -1.0f),
+};
+
+// Vertex Shaders
+void VS_Clear(in uint id : SV_VertexID,
+              out float4 outPosition : SV_POSITION)
+{
+    float2 corner = g_Corners[id];
+    outPosition = float4(corner.x, corner.y, 0.0f, 1.0f);
+}
+
+void VS_Clear_FL9( in float4 inPosition : POSITION,
+                   out float4 outPosition : SV_POSITION)
+{
+    outPosition = inPosition;
+}
+
+// Pixel Shader Constant Buffers
+cbuffer ColorAndDepthDataFloat : register(b0)
+{
+    float4 color_Float   : packoffset(c0);
+    float  zValueF_Float : packoffset(c1);
+}
+
+cbuffer ColorAndDepthDataSint : register(b0)
+{
+    int4  color_Sint   : packoffset(c0);
+    float zValueF_Sint : packoffset(c1);
+}
+
+cbuffer ColorAndDepthDataUint : register(b0)
+{
+    uint4 color_Uint   : packoffset(c0);
+    float zValueF_Uint : packoffset(c1);
+}
+
+// Pixel Shader Output Structs
+struct PS_OutputFloat_FL9
+{
+    float4 color0 : SV_TARGET0;
+    float4 color1 : SV_TARGET1;
+    float4 color2 : SV_TARGET2;
+    float4 color3 : SV_TARGET3;
+    float  depth  : SV_DEPTH;
+};
+
+struct PS_OutputFloat
+{
+    float4 color0 : SV_TARGET0;
+    float4 color1 : SV_TARGET1;
+    float4 color2 : SV_TARGET2;
+    float4 color3 : SV_TARGET3;
+    float4 color4 : SV_TARGET4;
+    float4 color5 : SV_TARGET5;
+    float4 color6 : SV_TARGET6;
+    float4 color7 : SV_TARGET7;
+    float  depth  : SV_DEPTH;
+};
+
+struct PS_OutputUint
+{
+    uint4 color0 : SV_TARGET0;
+    uint4 color1 : SV_TARGET1;
+    uint4 color2 : SV_TARGET2;
+    uint4 color3 : SV_TARGET3;
+    uint4 color4 : SV_TARGET4;
+    uint4 color5 : SV_TARGET5;
+    uint4 color6 : SV_TARGET6;
+    uint4 color7 : SV_TARGET7;
+    float depth  : SV_DEPTH;
+};
+
+struct PS_OutputSint
+{
+    int4 color0 : SV_TARGET0;
+    int4 color1 : SV_TARGET1;
+    int4 color2 : SV_TARGET2;
+    int4 color3 : SV_TARGET3;
+    int4 color4 : SV_TARGET4;
+    int4 color5 : SV_TARGET5;
+    int4 color6 : SV_TARGET6;
+    int4 color7 : SV_TARGET7;
+    float depth : SV_DEPTH;
+};
+
+// Pixel Shaders
+PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION)
+{
+    PS_OutputFloat_FL9 outData;
+    outData.color0 = color_Float;
+    outData.color1 = color_Float;
+    outData.color2 = color_Float;
+    outData.color3 = color_Float;
+    outData.depth  = zValueF_Float;
+    return outData;
+}
+
+PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION)
+{
+    PS_OutputFloat outData;
+    outData.color0 = color_Float;
+    outData.color1 = color_Float;
+    outData.color2 = color_Float;
+    outData.color3 = color_Float;
+    outData.color4 = color_Float;
+    outData.color5 = color_Float;
+    outData.color6 = color_Float;
+    outData.color7 = color_Float;
+    outData.depth  = zValueF_Float;
+    return outData;
+}
+
+PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION)
+{
+    PS_OutputUint outData;
+    outData.color0 = color_Uint;
+    outData.color1 = color_Uint;
+    outData.color2 = color_Uint;
+    outData.color3 = color_Uint;
+    outData.color4 = color_Uint;
+    outData.color5 = color_Uint;
+    outData.color6 = color_Uint;
+    outData.color7 = color_Uint;
+    outData.depth = zValueF_Uint;
+    return outData;
+}
+
+PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION)
+{
+    PS_OutputSint outData;
+    outData.color0 = color_Sint;
+    outData.color1 = color_Sint;
+    outData.color2 = color_Sint;
+    outData.color3 = color_Sint;
+    outData.color4 = color_Sint;
+    outData.color5 = color_Sint;
+    outData.color6 = color_Sint;
+    outData.color7 = color_Sint;
+    outData.depth = zValueF_Sint;
+    return outData;
+}
\ No newline at end of file
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
new file mode 100644
index 0000000..730952f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
@@ -0,0 +1,151 @@
+Texture2D<float4> TextureF  : register(t0);
+Texture2DMS<float4> TextureF_MS: register(t0);
+Texture2D<uint4>  TextureUI : register(t0);
+Texture2D<int4>   TextureI  : register(t0);
+
+SamplerState Sampler        : register(s0);
+
+void VS_Passthrough2D( in float2  inPosition :    POSITION,  in float2  inTexCoord : TEXCOORD0,
+                    out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0)
+{
+    outPosition = float4(inPosition, 0.0f, 1.0f);
+    outTexCoord = inTexCoord;
+}
+
+float PS_PassthroughDepth2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_DEPTH
+{
+    return TextureF.Sample(Sampler, inTexCoord).r;
+}
+
+float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    return TextureF.Sample(Sampler, inTexCoord).rgba;
+}
+
+float4 PS_PassthroughRGBA2DMS(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCORD0, in uint inSampleIndex : SV_SAMPLEINDEX) : SV_TARGET0
+{
+    return TextureF_MS.sample[inSampleIndex][inTexCoord].rgba;
+}
+
+float4 PS_PassthroughRGBAPremultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+    color.rgb *= color.a;
+    return color;
+}
+
+float4 PS_PassthroughRGBAUnmultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+    if (color.a > 0.0f)
+    {
+        color.rgb /= color.a;
+    }
+    return color;
+}
+
+uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureUI.GetDimensions(size.x, size.y);
+
+    return TextureUI.Load(int3(size * inTexCoord, 0)).rgba;
+}
+
+int4 PS_PassthroughRGBA2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureI.GetDimensions(size.x, size.y);
+
+    return TextureI.Load(int3(size * inTexCoord, 0)).rgba;
+}
+
+float4 PS_PassthroughRGB2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    return float4(TextureF.Sample(Sampler, inTexCoord).rgb, 1.0f);
+}
+
+float4 PS_PassthroughRGBPremultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+    color.rgb *= color.a;
+    return color;
+}
+
+float4 PS_PassthroughRGBUnmultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+    if (color.a > 0.0f)
+    {
+        color.rgb /= color.a;
+    }
+    return color;
+}
+
+uint4 PS_PassthroughRGB2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureUI.GetDimensions(size.x, size.y);
+
+    return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rgb, 0);
+}
+
+int4 PS_PassthroughRGB2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureI.GetDimensions(size.x, size.y);
+
+    return int4(TextureI.Load(int3(size * inTexCoord, 0)).rgb, 0);
+}
+
+float4 PS_PassthroughRG2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    return float4(TextureF.Sample(Sampler, inTexCoord).rg, 0.0f, 1.0f);
+}
+
+uint4 PS_PassthroughRG2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureUI.GetDimensions(size.x, size.y);
+
+    return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rg, 0, 0);
+}
+
+int4 PS_PassthroughRG2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureI.GetDimensions(size.x, size.y);
+
+    return int4(TextureI.Load(int3(size * inTexCoord, 0)).rg, 0, 0);
+}
+
+float4 PS_PassthroughR2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    return float4(TextureF.Sample(Sampler, inTexCoord).r, 0.0f, 0.0f, 1.0f);
+}
+
+uint4 PS_PassthroughR2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureUI.GetDimensions(size.x, size.y);
+
+    return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0);
+}
+
+int4 PS_PassthroughR2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureI.GetDimensions(size.x, size.y);
+
+    return int4(TextureI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0);
+}
+
+float4 PS_PassthroughLum2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    return float4(TextureF.Sample(Sampler, inTexCoord).rrr, 1.0f);
+}
+
+float4 PS_PassthroughLumAlpha2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    return TextureF.Sample(Sampler, inTexCoord).rrra;
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
new file mode 100644
index 0000000..c23c903
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
@@ -0,0 +1,146 @@
+Texture3D<float4> TextureF  : register(t0);
+Texture3D<uint4>  TextureUI : register(t0);
+Texture3D<int4>   TextureI  : register(t0);
+
+SamplerState      Sampler   : register(s0);
+
+struct VS_INPUT
+{
+    float2 Position : POSITION;
+    uint   Layer    : LAYER;
+    float3 TexCoord : TEXCOORD;
+};
+
+struct VS_OUTPUT
+{
+    float4 Position : SV_POSITION;
+    uint   Layer    : LAYER;
+    float3 TexCoord : TEXCOORD;
+};
+
+struct GS_OUTPUT
+{
+    float4 Position : SV_POSITION;
+    uint   Layer    : SV_RENDERTARGETARRAYINDEX;
+    float3 TexCoord : TEXCOORD;
+};
+
+VS_OUTPUT VS_Passthrough3D(VS_INPUT input)
+{
+    VS_OUTPUT output;
+
+    output.Position = float4(input.Position, 0.0f, 1.0f);
+    output.Layer = input.Layer;
+    output.TexCoord = input.TexCoord;
+
+    return output;
+}
+
+[maxvertexcount(3)]
+void GS_Passthrough3D(triangle VS_OUTPUT input[3], inout TriangleStream<GS_OUTPUT> outputStream)
+{
+    GS_OUTPUT output;
+
+    for (int i = 0; i < 3; i++)
+    {
+        output.Position = input[i].Position;
+        output.Layer = input[i].Layer;
+        output.TexCoord = input[i].TexCoord;
+
+        outputStream.Append(output);
+    }
+}
+
+float4 PS_PassthroughRGBA3D(GS_OUTPUT input) : SV_TARGET0
+{
+    return TextureF.Sample(Sampler, input.TexCoord).rgba;
+}
+
+uint4 PS_PassthroughRGBA3DUI(GS_OUTPUT input) : SV_TARGET0
+{
+    uint3 size;
+    TextureUI.GetDimensions(size.x, size.y, size.z);
+
+    return TextureUI.Load(int4(size * input.TexCoord, 0)).rgba;
+}
+
+int4 PS_PassthroughRGBA3DI(GS_OUTPUT input) : SV_TARGET0
+{
+    uint3 size;
+    TextureI.GetDimensions(size.x, size.y, size.z);
+
+    return TextureI.Load(int4(size * input.TexCoord, 0)).rgba;
+}
+
+float4 PS_PassthroughRGB3D(GS_OUTPUT input) : SV_TARGET0
+{
+    return float4(TextureF.Sample(Sampler, input.TexCoord).rgb, 1.0f);
+}
+
+uint4 PS_PassthroughRGB3DUI(GS_OUTPUT input) : SV_TARGET0
+{
+    uint3 size;
+    TextureUI.GetDimensions(size.x, size.y, size.z);
+
+    return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rgb, 0);
+}
+
+int4 PS_PassthroughRGB3DI(GS_OUTPUT input) : SV_TARGET0
+{
+    uint3 size;
+    TextureI.GetDimensions(size.x, size.y, size.z);
+
+    return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rgb, 0);
+}
+
+float4 PS_PassthroughRG3D(GS_OUTPUT input) : SV_TARGET0
+{
+    return float4(TextureF.Sample(Sampler, input.TexCoord).rg, 0.0f, 1.0f);
+}
+
+uint4 PS_PassthroughRG3DUI(GS_OUTPUT input) : SV_TARGET0
+{
+    uint3 size;
+    TextureUI.GetDimensions(size.x, size.y, size.z);
+
+    return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0);
+}
+
+int4 PS_PassthroughRG3DI(GS_OUTPUT input) : SV_TARGET0
+{
+    uint3 size;
+    TextureI.GetDimensions(size.x, size.y, size.z);
+
+    return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0);
+}
+
+float4 PS_PassthroughR3D(GS_OUTPUT input) : SV_TARGET0
+{
+    return float4(TextureF.Sample(Sampler, input.TexCoord).r, 0.0f, 0.0f, 1.0f);
+}
+
+uint4 PS_PassthroughR3DUI(GS_OUTPUT input) : SV_TARGET0
+{
+    uint3 size;
+    TextureUI.GetDimensions(size.x, size.y, size.z);
+
+    return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0);
+}
+
+int4 PS_PassthroughR3DI(GS_OUTPUT input) : SV_TARGET0
+{
+    uint3 size;
+    TextureI.GetDimensions(size.x, size.y, size.z);
+
+    return int4(TextureI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0);
+}
+
+float4 PS_PassthroughLum3D(GS_OUTPUT input) : SV_TARGET0
+{
+    return float4(TextureF.Sample(Sampler, input.TexCoord).rrr, 1.0f);
+}
+
+float4 PS_PassthroughLumAlpha3D(GS_OUTPUT input) : SV_TARGET0
+{
+    return TextureF.Sample(Sampler, input.TexCoord).rrra;
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl
new file mode 100644
index 0000000..7dc40d4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl
@@ -0,0 +1,56 @@
+static const float2 g_Corners[6] =
+{
+    float2(-1.0f,  1.0f),
+    float2( 1.0f, -1.0f),
+    float2(-1.0f, -1.0f),
+    float2(-1.0f,  1.0f),
+    float2( 1.0f,  1.0f),
+    float2( 1.0f, -1.0f),
+};
+
+void VS_ResolveDepthStencil(in uint id : SV_VertexID,
+                         out float4 position : SV_Position,
+                         out float2 texCoord : TEXCOORD0)
+{
+    float2 corner = g_Corners[id];
+    position = float4(corner.x, corner.y, 0.0f, 1.0f);
+    texCoord = float2((corner.x + 1.0f) * 0.5f, (-corner.y + 1.0f) * 0.5f);
+}
+
+Texture2DMS<float> Depth   : register(t0);
+Texture2DMS<uint2> Stencil : register(t1);
+
+void PS_ResolveDepth(in float4 position : SV_Position,
+                     in float2 texCoord : TEXCOORD0,
+                     out float depth : SV_Depth)
+{
+    // MS samplers must use Load
+    uint width, height, samples;
+    Depth.GetDimensions(width, height, samples);
+    uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height));
+    depth = Depth.Load(coord, 0).r;
+}
+
+void PS_ResolveDepthStencil(in float4 position : SV_Position,
+                            in float2 texCoord : TEXCOORD0,
+                            out float2 depthStencil : SV_Target0)
+{
+    // MS samplers must use Load
+    uint width, height, samples;
+    Depth.GetDimensions(width, height, samples);
+    uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height));
+    depthStencil.r = Depth.Load(coord, 0).r;
+    depthStencil.g = float(Stencil.Load(coord, 0).g);
+}
+
+void PS_ResolveStencil(in float4 position : SV_Position,
+                       in float2 texCoord : TEXCOORD0,
+                       out float2 stencil : SV_Target0)
+{
+    // MS samplers must use Load
+    uint width, height, samples;
+    Stencil.GetDimensions(width, height, samples);
+    uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height));
+    stencil.r = 0.0f;
+    stencil.g = float(Stencil.Load(coord, 0).g);
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl
new file mode 100644
index 0000000..505e222
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl
@@ -0,0 +1,99 @@
+Texture2D<float4> TextureF2D  : register(t0);
+Texture2D<uint4>  TextureUI2D : register(t0);
+Texture2D<int4>   TextureI2D  : register(t0);
+
+Texture3D<float4> TextureF3D  : register(t0);
+Texture3D<uint4>  TextureUI3D : register(t0);
+Texture3D<int4>   TextureI3D  : register(t0);
+
+Texture2DArray<float4> TextureF2DArray  : register(t0);
+Texture2DArray<uint4>  TextureUI2DArray : register(t0);
+Texture2DArray<int4>   TextureI2DArray  : register(t0);
+
+SamplerState Sampler          : register(s0);
+
+cbuffer SwizzleProperties     : register(b0)
+{
+    uint4 SwizzleIndices      : packoffset(c0);
+}
+
+float4 SwizzleLookup(in float4 sample)
+{
+    float lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f };
+    return float4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]);
+}
+
+int4 SwizzleLookup(in int4 sample)
+{
+    int lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f };
+    return int4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]);
+}
+
+uint4 SwizzleLookup(in uint4 sample)
+{
+    uint lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f };
+    return uint4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]);
+}
+
+float4 PS_SwizzleF2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    return SwizzleLookup(TextureF2D.Sample(Sampler, inTexCoord));
+}
+
+int4 PS_SwizzleI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureI2D.GetDimensions(size.x, size.y);
+
+    return SwizzleLookup(TextureI2D.Load(int3(size * inTexCoord, 0)));
+}
+
+uint4 PS_SwizzleUI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint2 size;
+    TextureUI2D.GetDimensions(size.x, size.y);
+
+    return SwizzleLookup(TextureUI2D.Load(int3(size * inTexCoord, 0)));
+}
+
+float4 PS_SwizzleF3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    return SwizzleLookup(TextureF3D.Sample(Sampler, inTexCoord));
+}
+
+int4 PS_SwizzleI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint3 size;
+    TextureI3D.GetDimensions(size.x, size.y, size.z);
+
+    return SwizzleLookup(TextureI3D.Load(int4(size * inTexCoord, 0)));
+}
+
+uint4 PS_SwizzleUI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint3 size;
+    TextureUI3D.GetDimensions(size.x, size.y, size.z);
+
+    return SwizzleLookup(TextureUI3D.Load(int4(size * inTexCoord, 0)));
+}
+
+float4 PS_SwizzleF2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    return SwizzleLookup(TextureF2DArray.Sample(Sampler, float3(inTexCoord.xy, inLayer)));
+}
+
+int4 PS_SwizzleI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint3 size;
+    TextureI2DArray.GetDimensions(size.x, size.y, size.z);
+
+    return SwizzleLookup(TextureI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0)));
+}
+
+uint4 PS_SwizzleUI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+    uint3 size;
+    TextureUI2DArray.GetDimensions(size.x, size.y, size.z);
+
+    return SwizzleLookup(TextureUI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0)));
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h
new file mode 100644
index 0000000..71a2fec
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h
@@ -0,0 +1,165 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float   xyzw

+// TEXCOORD                 0   x           1     NONE    uint   x   

+// LAYER                    0    y          1     NONE    uint    y  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float   xyzw

+// TEXCOORD                 0   x           1     NONE    uint   x   

+// SV_RenderTargetArrayIndex     0    y          1  RTINDEX    uint    y  

+//

+gs_4_0

+dcl_input_siv v[1][0].xyzw, position

+dcl_input v[1][1].x

+dcl_input v[1][1].y

+dcl_inputprimitive point 

+dcl_outputtopology pointlist 

+dcl_output_siv o0.xyzw, position

+dcl_output o1.x

+dcl_output_siv o1.y, rendertarget_array_index

+dcl_maxout 1

+mov o0.xyzw, v[0][0].xyzw

+mov o1.x, v[0][1].x

+mov o1.y, v[0][1].y

+emit 

+ret 

+// Approximately 5 instruction slots used

+#endif

+

+const BYTE g_GS_BufferToTexture[] =

+{

+     68,  88,  66,  67,  79, 166, 

+    191,  97,  16,  63, 142, 167, 

+    231,  92, 119,  74,  86,   7, 

+     58, 165,   1,   0,   0,   0, 

+    212,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    140,   0,   0,   0,   0,   1, 

+      0,   0, 136,   1,   0,   0, 

+     88,   2,   0,   0,  82,  68, 

+     69,  70,  80,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+     83,  71,   0,   1,   0,   0, 

+     28,   0,   0,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+    171, 171,  73,  83,  71,  78, 

+    108,   0,   0,   0,   3,   0, 

+      0,   0,   8,   0,   0,   0, 

+     80,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,  15,   0,   0, 

+     92,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,   1,   1,   0,   0, 

+    101,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,   2,   2,   0,   0, 

+     83,  86,  95,  80, 111, 115, 

+    105, 116, 105, 111, 110,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0,  76,  65,  89, 

+     69,  82,   0, 171,  79,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,  14, 

+      0,   0, 101,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   2,  13, 

+      0,   0,  83,  86,  95,  80, 

+    111, 115, 105, 116, 105, 111, 

+    110,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0,  83, 

+     86,  95,  82, 101, 110, 100, 

+    101, 114,  84,  97, 114, 103, 

+    101, 116,  65, 114, 114,  97, 

+    121,  73, 110, 100, 101, 120, 

+      0, 171,  83,  72,  68,  82, 

+    200,   0,   0,   0,  64,   0, 

+      2,   0,  50,   0,   0,   0, 

+     97,   0,   0,   5, 242,  16, 

+     32,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  95,   0,   0,   4, 

+     18,  16,  32,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+     95,   0,   0,   4,  34,  16, 

+     32,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,  93,   8, 

+      0,   1,  92,   8,   0,   1, 

+    103,   0,   0,   4, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3,  18,  32,  16,   0, 

+      1,   0,   0,   0, 103,   0, 

+      0,   4,  34,  32,  16,   0, 

+      1,   0,   0,   0,   4,   0, 

+      0,   0,  94,   0,   0,   2, 

+      1,   0,   0,   0,  54,   0, 

+      0,   6, 242,  32,  16,   0, 

+      0,   0,   0,   0,  70,  30, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  32,  16,   0, 

+      1,   0,   0,   0,  10,  16, 

+     32,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,  54,   0, 

+      0,   6,  34,  32,  16,   0, 

+      1,   0,   0,   0,  26,  16, 

+     32,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,  19,   0, 

+      0,   1,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,   5,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   6,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h
new file mode 100644
index 0000000..cfc0c3f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h
@@ -0,0 +1,229 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer BufferCopyParams

+// {

+//

+//   uint FirstPixelOffset;             // Offset:    0 Size:     4 [unused]

+//   uint PixelsPerRow;                 // Offset:    4 Size:     4 [unused]

+//   uint RowStride;                    // Offset:    8 Size:     4 [unused]

+//   uint RowsPerSlice;                 // Offset:   12 Size:     4 [unused]

+//   float2 PositionOffset;             // Offset:   16 Size:     8 [unused]

+//   float2 PositionScale;              // Offset:   24 Size:     8 [unused]

+//   int2 TexLocationOffset;            // Offset:   32 Size:     8 [unused]

+//   int2 TexLocationScale;             // Offset:   40 Size:     8 [unused]

+//   uint FirstSlice;                   // Offset:   48 Size:     4 [unused]

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Buffer4F                          texture  float4         buf    0        1

+// BufferCopyParams                  cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float       

+// TEXCOORD                 0   x           1     NONE    uint   x   

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Target                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_resource_buffer (float,float,float,float) t0

+dcl_input_ps constant v1.x

+dcl_output o0.xyzw

+ld o0.xyzw, v1.xxxx, t0.xyzw

+ret 

+// Approximately 2 instruction slots used

+#endif

+

+const BYTE g_PS_BufferToTexture_4F[] =

+{

+     68,  88,  66,  67, 176,  15, 

+     76, 123, 100,  38, 152,  23, 

+    150,  99, 165, 184, 222, 157, 

+    235,  80,   1,   0,   0,   0, 

+    252,   3,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    140,   2,   0,   0, 228,   2, 

+      0,   0,  24,   3,   0,   0, 

+    128,   3,   0,   0,  82,  68, 

+     69,  70,  80,   2,   0,   0, 

+      1,   0,   0,   0, 120,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     28,   2,   0,   0,  92,   0, 

+      0,   0,   2,   0,   0,   0, 

+      5,   0,   0,   0,   1,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+    101,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,  66, 117, 102, 102, 

+    101, 114,  52,  70,   0,  66, 

+    117, 102, 102, 101, 114,  67, 

+    111, 112, 121,  80,  97, 114, 

+     97, 109, 115,   0, 171, 171, 

+    101,   0,   0,   0,   9,   0, 

+      0,   0, 144,   0,   0,   0, 

+     64,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    104,   1,   0,   0,   0,   0, 

+      0,   0,   4,   0,   0,   0, 

+      0,   0,   0,   0, 124,   1, 

+      0,   0,   0,   0,   0,   0, 

+    140,   1,   0,   0,   4,   0, 

+      0,   0,   4,   0,   0,   0, 

+      0,   0,   0,   0, 124,   1, 

+      0,   0,   0,   0,   0,   0, 

+    153,   1,   0,   0,   8,   0, 

+      0,   0,   4,   0,   0,   0, 

+      0,   0,   0,   0, 124,   1, 

+      0,   0,   0,   0,   0,   0, 

+    163,   1,   0,   0,  12,   0, 

+      0,   0,   4,   0,   0,   0, 

+      0,   0,   0,   0, 124,   1, 

+      0,   0,   0,   0,   0,   0, 

+    176,   1,   0,   0,  16,   0, 

+      0,   0,   8,   0,   0,   0, 

+      0,   0,   0,   0, 192,   1, 

+      0,   0,   0,   0,   0,   0, 

+    208,   1,   0,   0,  24,   0, 

+      0,   0,   8,   0,   0,   0, 

+      0,   0,   0,   0, 192,   1, 

+      0,   0,   0,   0,   0,   0, 

+    222,   1,   0,   0,  32,   0, 

+      0,   0,   8,   0,   0,   0, 

+      0,   0,   0,   0, 240,   1, 

+      0,   0,   0,   0,   0,   0, 

+      0,   2,   0,   0,  40,   0, 

+      0,   0,   8,   0,   0,   0, 

+      0,   0,   0,   0, 240,   1, 

+      0,   0,   0,   0,   0,   0, 

+     17,   2,   0,   0,  48,   0, 

+      0,   0,   4,   0,   0,   0, 

+      0,   0,   0,   0, 124,   1, 

+      0,   0,   0,   0,   0,   0, 

+     70, 105, 114, 115, 116,  80, 

+    105, 120, 101, 108,  79, 102, 

+    102, 115, 101, 116,   0, 171, 

+    171, 171,   0,   0,  19,   0, 

+      1,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     80, 105, 120, 101, 108, 115, 

+     80, 101, 114,  82, 111, 119, 

+      0,  82, 111, 119,  83, 116, 

+    114, 105, 100, 101,   0,  82, 

+    111, 119, 115,  80, 101, 114, 

+     83, 108, 105,  99, 101,   0, 

+     80, 111, 115, 105, 116, 105, 

+    111, 110,  79, 102, 102, 115, 

+    101, 116,   0, 171,   1,   0, 

+      3,   0,   1,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  80, 111, 115, 105, 

+    116, 105, 111, 110,  83,  99, 

+     97, 108, 101,   0,  84, 101, 

+    120,  76, 111,  99,  97, 116, 

+    105, 111, 110,  79, 102, 102, 

+    115, 101, 116,   0,   1,   0, 

+      2,   0,   1,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  84, 101, 120,  76, 

+    111,  99,  97, 116, 105, 111, 

+    110,  83,  99,  97, 108, 101, 

+      0,  70, 105, 114, 115, 116, 

+     83, 108, 105,  99, 101,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78,  80,   0,   0,   0, 

+      2,   0,   0,   0,   8,   0, 

+      0,   0,  56,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  68,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,   1, 

+      0,   0,  83,  86,  95,  80, 

+    111, 115, 105, 116, 105, 111, 

+    110,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0, 171, 

+    171, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  97, 114, 

+    103, 101, 116,   0, 171, 171, 

+     83,  72,  68,  82,  96,   0, 

+      0,   0,  64,   0,   0,   0, 

+     24,   0,   0,   0,  89,   0, 

+      0,   4,  70, 142,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  88,   8,   0,   4, 

+      0, 112,  16,   0,   0,   0, 

+      0,   0,  85,  85,   0,   0, 

+     98,   8,   0,   3,  18,  16, 

+     16,   0,   1,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+     45,   0,   0,   7, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+      6,  16,  16,   0,   1,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h
new file mode 100644
index 0000000..ac952f6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h
@@ -0,0 +1,128 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Buffer4I                          texture   sint4         buf    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float       

+// TEXCOORD                 0   x           1     NONE    uint   x   

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Target                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_resource_buffer (sint,sint,sint,sint) t0

+dcl_input_ps constant v1.x

+dcl_output o0.xyzw

+ld o0.xyzw, v1.xxxx, t0.xyzw

+ret 

+// Approximately 2 instruction slots used

+#endif

+

+const BYTE g_PS_BufferToTexture_4I[] =

+{

+     68,  88,  66,  67, 154, 139, 

+     95, 210,  76,  52, 228,  55, 

+      1, 175,  60,  90,  13, 234, 

+    138,   3,   1,   0,   0,   0, 

+     20,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+    152,   1,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     69,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     66, 117, 102, 102, 101, 114, 

+     52,  73,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   1,   0,   0,  83,  86, 

+     95,  80, 111, 115, 105, 116, 

+    105, 111, 110,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     97, 114, 103, 101, 116,   0, 

+    171, 171,  83,  72,  68,  82, 

+     80,   0,   0,   0,  64,   0, 

+      0,   0,  20,   0,   0,   0, 

+     88,   8,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0,  98,   8, 

+      0,   3,  18,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0,  45,   0, 

+      0,   7, 242,  32,  16,   0, 

+      0,   0,   0,   0,   6,  16, 

+     16,   0,   1,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h
new file mode 100644
index 0000000..fe7d6b2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h
@@ -0,0 +1,128 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Buffer4UI                         texture   uint4         buf    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float       

+// TEXCOORD                 0   x           1     NONE    uint   x   

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Target                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_resource_buffer (uint,uint,uint,uint) t0

+dcl_input_ps constant v1.x

+dcl_output o0.xyzw

+ld o0.xyzw, v1.xxxx, t0.xyzw

+ret 

+// Approximately 2 instruction slots used

+#endif

+

+const BYTE g_PS_BufferToTexture_4UI[] =

+{

+     68,  88,  66,  67,  25, 164, 

+      1, 224, 250, 219,  16, 200, 

+     83,  99,  38, 137, 116, 129, 

+    200,  39,   1,   0,   0,   0, 

+     20,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+    152,   1,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     70,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     66, 117, 102, 102, 101, 114, 

+     52,  85,  73,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   1,   0,   0,  83,  86, 

+     95,  80, 111, 115, 105, 116, 

+    105, 111, 110,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     97, 114, 103, 101, 116,   0, 

+    171, 171,  83,  72,  68,  82, 

+     80,   0,   0,   0,  64,   0, 

+      0,   0,  20,   0,   0,   0, 

+     88,   8,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0,  98,   8, 

+      0,   3,  18,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0,  45,   0, 

+      0,   7, 242,  32,  16,   0, 

+      0,   0,   0,   0,   6,  16, 

+     16,   0,   1,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h
new file mode 100644
index 0000000..ac72f4b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h
@@ -0,0 +1,311 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer BufferCopyParams

+// {

+//

+//   uint FirstPixelOffset;             // Offset:    0 Size:     4

+//   uint PixelsPerRow;                 // Offset:    4 Size:     4

+//   uint RowStride;                    // Offset:    8 Size:     4

+//   uint RowsPerSlice;                 // Offset:   12 Size:     4

+//   float2 PositionOffset;             // Offset:   16 Size:     8

+//   float2 PositionScale;              // Offset:   24 Size:     8

+//   int2 TexLocationOffset;            // Offset:   32 Size:     8 [unused]

+//   int2 TexLocationScale;             // Offset:   40 Size:     8 [unused]

+//   uint FirstSlice;                   // Offset:   48 Size:     4

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// BufferCopyParams                  cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_VertexID              0   x           0   VERTID    uint   x   

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float   xyzw

+// TEXCOORD                 0   x           1     NONE    uint   x   

+// LAYER                    0    y          1     NONE    uint    y  

+//

+vs_4_0

+dcl_constantbuffer cb0[4], immediateIndexed

+dcl_input_sgv v0.x, vertex_id

+dcl_output_siv o0.xyzw, position

+dcl_output o1.x

+dcl_output o1.y

+dcl_temps 2

+mov o0.zw, l(0,0,0,1.000000)

+imul null, r0.xy, cb0[0].wwww, cb0[0].yzyy

+udiv r0.z, null, v0.x, r0.x

+imad r0.x, -r0.z, r0.x, v0.x

+imad r0.y, r0.z, r0.y, cb0[0].x

+iadd o1.y, r0.z, cb0[3].x

+udiv r0.z, null, r0.x, cb0[0].y

+imad r0.x, -r0.z, cb0[0].y, r0.x

+utof r1.xy, r0.xzxx

+imad r0.y, r0.z, cb0[0].z, r0.y

+iadd o1.x, r0.x, r0.y

+mad o0.xy, cb0[1].zwzz, r1.xyxx, cb0[1].xyxx

+ret 

+// Approximately 13 instruction slots used

+#endif

+

+const BYTE g_VS_BufferToTexture[] =

+{

+     68,  88,  66,  67,  39, 207, 

+    138,  15,  42, 195, 141, 208, 

+      2, 107, 135, 197, 122,  36, 

+    114, 227,   1,   0,   0,   0, 

+    152,   5,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    100,   2,   0,   0, 152,   2, 

+      0,   0,  12,   3,   0,   0, 

+     28,   5,   0,   0,  82,  68, 

+     69,  70,  40,   2,   0,   0, 

+      1,   0,   0,   0,  80,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    254, 255,   0,   1,   0,   0, 

+    244,   1,   0,   0,  60,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+     66, 117, 102, 102, 101, 114, 

+     67, 111, 112, 121,  80,  97, 

+    114,  97, 109, 115,   0, 171, 

+    171, 171,  60,   0,   0,   0, 

+      9,   0,   0,   0, 104,   0, 

+      0,   0,  64,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  64,   1,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   2,   0,   0,   0, 

+     84,   1,   0,   0,   0,   0, 

+      0,   0, 100,   1,   0,   0, 

+      4,   0,   0,   0,   4,   0, 

+      0,   0,   2,   0,   0,   0, 

+     84,   1,   0,   0,   0,   0, 

+      0,   0, 113,   1,   0,   0, 

+      8,   0,   0,   0,   4,   0, 

+      0,   0,   2,   0,   0,   0, 

+     84,   1,   0,   0,   0,   0, 

+      0,   0, 123,   1,   0,   0, 

+     12,   0,   0,   0,   4,   0, 

+      0,   0,   2,   0,   0,   0, 

+     84,   1,   0,   0,   0,   0, 

+      0,   0, 136,   1,   0,   0, 

+     16,   0,   0,   0,   8,   0, 

+      0,   0,   2,   0,   0,   0, 

+    152,   1,   0,   0,   0,   0, 

+      0,   0, 168,   1,   0,   0, 

+     24,   0,   0,   0,   8,   0, 

+      0,   0,   2,   0,   0,   0, 

+    152,   1,   0,   0,   0,   0, 

+      0,   0, 182,   1,   0,   0, 

+     32,   0,   0,   0,   8,   0, 

+      0,   0,   0,   0,   0,   0, 

+    200,   1,   0,   0,   0,   0, 

+      0,   0, 216,   1,   0,   0, 

+     40,   0,   0,   0,   8,   0, 

+      0,   0,   0,   0,   0,   0, 

+    200,   1,   0,   0,   0,   0, 

+      0,   0, 233,   1,   0,   0, 

+     48,   0,   0,   0,   4,   0, 

+      0,   0,   2,   0,   0,   0, 

+     84,   1,   0,   0,   0,   0, 

+      0,   0,  70, 105, 114, 115, 

+    116,  80, 105, 120, 101, 108, 

+     79, 102, 102, 115, 101, 116, 

+      0, 171, 171, 171,   0,   0, 

+     19,   0,   1,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  80, 105, 120, 101, 

+    108, 115,  80, 101, 114,  82, 

+    111, 119,   0,  82, 111, 119, 

+     83, 116, 114, 105, 100, 101, 

+      0,  82, 111, 119, 115,  80, 

+    101, 114,  83, 108, 105,  99, 

+    101,   0,  80, 111, 115, 105, 

+    116, 105, 111, 110,  79, 102, 

+    102, 115, 101, 116,   0, 171, 

+      1,   0,   3,   0,   1,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  80, 111, 

+    115, 105, 116, 105, 111, 110, 

+     83,  99,  97, 108, 101,   0, 

+     84, 101, 120,  76, 111,  99, 

+     97, 116, 105, 111, 110,  79, 

+    102, 102, 115, 101, 116,   0, 

+      1,   0,   2,   0,   1,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  84, 101, 

+    120,  76, 111,  99,  97, 116, 

+    105, 111, 110,  83,  99,  97, 

+    108, 101,   0,  70, 105, 114, 

+    115, 116,  83, 108, 105,  99, 

+    101,   0,  77, 105,  99, 114, 

+    111, 115, 111, 102, 116,  32, 

+     40,  82,  41,  32,  72,  76, 

+     83,  76,  32,  83, 104,  97, 

+    100, 101, 114,  32,  67, 111, 

+    109, 112, 105, 108, 101, 114, 

+     32,  54,  46,  51,  46,  57, 

+     54,  48,  48,  46,  49,  54, 

+     51,  56,  52,   0, 171, 171, 

+     73,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      6,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   1,   0,   0,  83,  86, 

+     95,  86, 101, 114, 116, 101, 

+    120,  73,  68,   0,  79,  83, 

+     71,  78, 108,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,  14, 

+      0,   0, 101,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   2,  13, 

+      0,   0,  83,  86,  95,  80, 

+    111, 115, 105, 116, 105, 111, 

+    110,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0,  76, 

+     65,  89,  69,  82,   0, 171, 

+     83,  72,  68,  82,   8,   2, 

+      0,   0,  64,   0,   1,   0, 

+    130,   0,   0,   0,  89,   0, 

+      0,   4,  70, 142,  32,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,  96,   0,   0,   4, 

+     18,  16,  16,   0,   0,   0, 

+      0,   0,   6,   0,   0,   0, 

+    103,   0,   0,   4, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3,  18,  32,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3,  34,  32,  16,   0, 

+      1,   0,   0,   0, 104,   0, 

+      0,   2,   2,   0,   0,   0, 

+     54,   0,   0,   8, 194,  32, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    128,  63,  38,   0,   0,  10, 

+      0, 208,   0,   0,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+    246, 143,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    150, 133,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     78,   0,   0,   8,  66,   0, 

+     16,   0,   0,   0,   0,   0, 

+      0, 208,   0,   0,  10,  16, 

+     16,   0,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  35,   0,   0,  10, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  42,   0,  16, 128, 

+     65,   0,   0,   0,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  10,  16, 

+     16,   0,   0,   0,   0,   0, 

+     35,   0,   0,  10,  34,   0, 

+     16,   0,   0,   0,   0,   0, 

+     42,   0,  16,   0,   0,   0, 

+      0,   0,  26,   0,  16,   0, 

+      0,   0,   0,   0,  10, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  30,   0, 

+      0,   8,  34,  32,  16,   0, 

+      1,   0,   0,   0,  42,   0, 

+     16,   0,   0,   0,   0,   0, 

+     10, 128,  32,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+     78,   0,   0,   9,  66,   0, 

+     16,   0,   0,   0,   0,   0, 

+      0, 208,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     26, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     35,   0,   0,  11,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     42,   0,  16, 128,  65,   0, 

+      0,   0,   0,   0,   0,   0, 

+     26, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  86,   0,   0,   5, 

+     50,   0,  16,   0,   1,   0, 

+      0,   0, 134,   0,  16,   0, 

+      0,   0,   0,   0,  35,   0, 

+      0,  10,  34,   0,  16,   0, 

+      0,   0,   0,   0,  42,   0, 

+     16,   0,   0,   0,   0,   0, 

+     42, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     26,   0,  16,   0,   0,   0, 

+      0,   0,  30,   0,   0,   7, 

+     18,  32,  16,   0,   1,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  26,   0, 

+     16,   0,   0,   0,   0,   0, 

+     50,   0,   0,  11,  50,  32, 

+     16,   0,   0,   0,   0,   0, 

+    230, 138,  32,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     70,   0,  16,   0,   1,   0, 

+      0,   0,  70, 128,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,  13,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   4,   0,   0,   0, 

+      1,   0,   0,   0,   7,   0, 

+      0,   0,   2,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h
new file mode 100644
index 0000000..3427ebb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h
@@ -0,0 +1,136 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// POSITION                 0   xyzw        0     NONE   float   xyzw

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float   xyzw

+//

+//

+// Runtime generated constant mappings:

+//

+// Target Reg                               Constant Description

+// ---------- --------------------------------------------------

+// c0                              Vertex Shader position offset

+//

+//

+// Level9 shader bytecode:

+//

+    vs_2_x

+    dcl_texcoord v0

+    mad oPos.xy, v0.w, c0, v0

+    mov oPos.zw, v0

+

+// approximately 2 instruction slots used

+vs_4_0

+dcl_input v0.xyzw

+dcl_output_siv o0.xyzw, position

+mov o0.xyzw, v0.xyzw

+ret 

+// Approximately 2 instruction slots used

+#endif

+

+const BYTE g_VS_Clear_FL9[] =

+{

+     68,  88,  66,  67, 176,  74, 

+    193, 175,  25,  51, 252,  39, 

+    176, 214, 107,  38, 137, 209, 

+    240, 189,   1,   0,   0,   0, 

+     28,   2,   0,   0,   6,   0, 

+      0,   0,  56,   0,   0,   0, 

+    156,   0,   0,   0, 224,   0, 

+      0,   0,  92,   1,   0,   0, 

+    180,   1,   0,   0, 232,   1, 

+      0,   0,  65, 111, 110,  57, 

+     92,   0,   0,   0,  92,   0, 

+      0,   0,   0,   2, 254, 255, 

+     52,   0,   0,   0,  40,   0, 

+      0,   0,   0,   0,  36,   0, 

+      0,   0,  36,   0,   0,   0, 

+     36,   0,   0,   0,  36,   0, 

+      1,   0,  36,   0,   0,   0, 

+      0,   0,   1,   2, 254, 255, 

+     31,   0,   0,   2,   5,   0, 

+      0, 128,   0,   0,  15, 144, 

+      4,   0,   0,   4,   0,   0, 

+      3, 192,   0,   0, 255, 144, 

+      0,   0, 228, 160,   0,   0, 

+    228, 144,   1,   0,   0,   2, 

+      0,   0,  12, 192,   0,   0, 

+    228, 144, 255, 255,   0,   0, 

+     83,  72,  68,  82,  60,   0, 

+      0,   0,  64,   0,   1,   0, 

+     15,   0,   0,   0,  95,   0, 

+      0,   3, 242,  16,  16,   0, 

+      0,   0,   0,   0, 103,   0, 

+      0,   4, 242,  32,  16,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  54,   0,   0,   5, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0,  70,  30,  16,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     82,  68,  69,  70,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  28,   0,   0,   0, 

+      0,   4, 254, 255,   0,   1, 

+      0,   0,  28,   0,   0,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,  15, 

+      0,   0,  80,  79,  83,  73, 

+     84,  73,  79,  78,   0, 171, 

+    171, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h
new file mode 100644
index 0000000..526d0c6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h
@@ -0,0 +1,141 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_VertexID              0   x           0   VERTID    uint   x   

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float   xyzw

+//

+vs_4_0

+dcl_immediateConstantBuffer { { -1.000000, 1.000000, 0, 0},

+                              { 1.000000, -1.000000, 0, 0},

+                              { -1.000000, -1.000000, 0, 0},

+                              { -1.000000, 1.000000, 0, 0},

+                              { 1.000000, 1.000000, 0, 0},

+                              { 1.000000, -1.000000, 0, 0} }

+dcl_input_sgv v0.x, vertex_id

+dcl_output_siv o0.xyzw, position

+dcl_temps 1

+mov r0.x, v0.x

+mov o0.xy, icb[r0.x + 0].xyxx

+mov o0.zw, l(0,0,0,1.000000)

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_VS_Clear[] =

+{

+     68,  88,  66,  67, 170,  97, 

+     47,  88, 112,  76, 249,  40, 

+    248, 151, 133,  76, 228, 131, 

+     60, 115,   1,   0,   0,   0, 

+     96,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    140,   0,   0,   0, 192,   0, 

+      0,   0, 244,   0,   0,   0, 

+    228,   1,   0,   0,  82,  68, 

+     69,  70,  80,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    254, 255,   0,   1,   0,   0, 

+     28,   0,   0,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+    171, 171,  73,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   6,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   1,   1,   0,   0, 

+     83,  86,  95,  86, 101, 114, 

+    116, 101, 120,  73,  68,   0, 

+     79,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  72, 

+     68,  82, 232,   0,   0,   0, 

+     64,   0,   1,   0,  58,   0, 

+      0,   0,  53,  24,   0,   0, 

+     26,   0,   0,   0,   0,   0, 

+    128, 191,   0,   0, 128,  63, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 128,  63, 

+      0,   0, 128, 191,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0, 128, 191,   0,   0, 

+    128, 191,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    128, 191,   0,   0, 128,  63, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 128,  63, 

+      0,   0, 128,  63,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0, 128,  63,   0,   0, 

+    128, 191,   0,   0,   0,   0, 

+      0,   0,   0,   0,  96,   0, 

+      0,   4,  18,  16,  16,   0, 

+      0,   0,   0,   0,   6,   0, 

+      0,   0, 103,   0,   0,   4, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0,  54,   0,   0,   5, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  10,  16,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  50,  32,  16,   0, 

+      0,   0,   0,   0,  70, 144, 

+    144,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   8, 194,  32,  16,   0, 

+      0,   0,   0,   0,   2,  64, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 128,  63, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   6,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h
new file mode 100644
index 0000000..97a8ce7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h
@@ -0,0 +1,244 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer ColorAndDepthDataFloat

+// {

+//

+//   float4 color_Float;                // Offset:    0 Size:    16

+//   float zValueF_Float;               // Offset:   16 Size:     4

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// ColorAndDepthDataFloat            cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+// SV_TARGET                1   xyzw        1   TARGET   float   xyzw

+// SV_TARGET                2   xyzw        2   TARGET   float   xyzw

+// SV_TARGET                3   xyzw        3   TARGET   float   xyzw

+// SV_DEPTH                 0    N/A   oDepth    DEPTH   float    YES

+//

+//

+// Constant buffer to DX9 shader constant mappings:

+//

+// Target Reg Buffer  Start Reg # of Regs        Data Conversion

+// ---------- ------- --------- --------- ----------------------

+// c0         cb0             0         2  ( FLT, FLT, FLT, FLT)

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    mov oC0, c0

+    mov oC1, c0

+    mov oC2, c0

+    mov oC3, c0

+    mov oDepth, c1.x

+

+// approximately 5 instruction slots used

+ps_4_0

+dcl_constantbuffer cb0[2], immediateIndexed

+dcl_output o0.xyzw

+dcl_output o1.xyzw

+dcl_output o2.xyzw

+dcl_output o3.xyzw

+dcl_output oDepth

+mov o0.xyzw, cb0[0].xyzw

+mov o1.xyzw, cb0[0].xyzw

+mov o2.xyzw, cb0[0].xyzw

+mov o3.xyzw, cb0[0].xyzw

+mov oDepth, cb0[1].x

+ret 

+// Approximately 6 instruction slots used

+#endif

+

+const BYTE g_PS_ClearFloat_FL9[] =

+{

+     68,  88,  66,  67,  50, 112, 

+    200, 244,  43, 179,  42,  60, 

+      1,  54, 148, 142, 159,  31, 

+    160, 168,   1,   0,   0,   0, 

+    228,   3,   0,   0,   6,   0, 

+      0,   0,  56,   0,   0,   0, 

+    180,   0,   0,   0, 132,   1, 

+      0,   0,   0,   2,   0,   0, 

+     20,   3,   0,   0,  72,   3, 

+      0,   0,  65, 111, 110,  57, 

+    116,   0,   0,   0, 116,   0, 

+      0,   0,   0,   2, 255, 255, 

+     68,   0,   0,   0,  48,   0, 

+      0,   0,   1,   0,  36,   0, 

+      0,   0,  48,   0,   0,   0, 

+     48,   0,   0,   0,  36,   0, 

+      0,   0,  48,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   1,   2, 

+    255, 255,   1,   0,   0,   2, 

+      0,   8,  15, 128,   0,   0, 

+    228, 160,   1,   0,   0,   2, 

+      1,   8,  15, 128,   0,   0, 

+    228, 160,   1,   0,   0,   2, 

+      2,   8,  15, 128,   0,   0, 

+    228, 160,   1,   0,   0,   2, 

+      3,   8,  15, 128,   0,   0, 

+    228, 160,   1,   0,   0,   2, 

+      0,   8,  15, 144,   1,   0, 

+      0, 160, 255, 255,   0,   0, 

+     83,  72,  68,  82, 200,   0, 

+      0,   0,  64,   0,   0,   0, 

+     50,   0,   0,   0,  89,   0, 

+      0,   4,  70, 142,  32,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   1,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   3,   0, 

+      0,   0, 101,   0,   0,   2, 

+      1, 192,   0,   0,  54,   0, 

+      0,   6, 242,  32,  16,   0, 

+      0,   0,   0,   0,  70, 142, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6, 242,  32,  16,   0, 

+      1,   0,   0,   0,  70, 142, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6, 242,  32,  16,   0, 

+      2,   0,   0,   0,  70, 142, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6, 242,  32,  16,   0, 

+      3,   0,   0,   0,  70, 142, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   5,   1, 192,   0,   0, 

+     10, 128,  32,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      6,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      5,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   5,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  82,  68,  69,  70, 

+     12,   1,   0,   0,   1,   0, 

+      0,   0,  84,   0,   0,   0, 

+      1,   0,   0,   0,  28,   0, 

+      0,   0,   0,   4, 255, 255, 

+      0,   1,   0,   0, 216,   0, 

+      0,   0,  60,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,  67, 111, 

+    108, 111, 114,  65, 110, 100, 

+     68, 101, 112, 116, 104,  68, 

+     97, 116,  97,  70, 108, 111, 

+     97, 116,   0, 171,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+    108,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 156,   0, 

+      0,   0,   0,   0,   0,   0, 

+     16,   0,   0,   0,   2,   0, 

+      0,   0, 168,   0,   0,   0, 

+      0,   0,   0,   0, 184,   0, 

+      0,   0,  16,   0,   0,   0, 

+      4,   0,   0,   0,   2,   0, 

+      0,   0, 200,   0,   0,   0, 

+      0,   0,   0,   0,  99, 111, 

+    108, 111, 114,  95,  70, 108, 

+    111,  97, 116,   0,   1,   0, 

+      3,   0,   1,   0,   4,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0, 122,  86,  97, 108, 

+    117, 101,  70,  95,  70, 108, 

+    111,  97, 116,   0, 171, 171, 

+      0,   0,   3,   0,   1,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+    171, 171,  73,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     79,  83,  71,  78, 148,   0, 

+      0,   0,   5,   0,   0,   0, 

+      8,   0,   0,   0, 128,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0, 128,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+     15,   0,   0,   0, 128,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+     15,   0,   0,   0, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   3,   0,   0,   0, 

+     15,   0,   0,   0, 138,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0, 255, 255, 255, 255, 

+      1,  14,   0,   0,  83,  86, 

+     95,  84,  65,  82,  71,  69, 

+     84,   0,  83,  86,  95,  68, 

+     69,  80,  84,  72,   0, 171

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h
new file mode 100644
index 0000000..250d3cb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h
@@ -0,0 +1,257 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer ColorAndDepthDataFloat

+// {

+//

+//   float4 color_Float;                // Offset:    0 Size:    16

+//   float zValueF_Float;               // Offset:   16 Size:     4

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// ColorAndDepthDataFloat            cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+// SV_TARGET                1   xyzw        1   TARGET   float   xyzw

+// SV_TARGET                2   xyzw        2   TARGET   float   xyzw

+// SV_TARGET                3   xyzw        3   TARGET   float   xyzw

+// SV_TARGET                4   xyzw        4   TARGET   float   xyzw

+// SV_TARGET                5   xyzw        5   TARGET   float   xyzw

+// SV_TARGET                6   xyzw        6   TARGET   float   xyzw

+// SV_TARGET                7   xyzw        7   TARGET   float   xyzw

+// SV_DEPTH                 0    N/A   oDepth    DEPTH   float    YES

+//

+ps_4_0

+dcl_constantbuffer cb0[2], immediateIndexed

+dcl_output o0.xyzw

+dcl_output o1.xyzw

+dcl_output o2.xyzw

+dcl_output o3.xyzw

+dcl_output o4.xyzw

+dcl_output o5.xyzw

+dcl_output o6.xyzw

+dcl_output o7.xyzw

+dcl_output oDepth

+mov o0.xyzw, cb0[0].xyzw

+mov o1.xyzw, cb0[0].xyzw

+mov o2.xyzw, cb0[0].xyzw

+mov o3.xyzw, cb0[0].xyzw

+mov o4.xyzw, cb0[0].xyzw

+mov o5.xyzw, cb0[0].xyzw

+mov o6.xyzw, cb0[0].xyzw

+mov o7.xyzw, cb0[0].xyzw

+mov oDepth, cb0[1].x

+ret 

+// Approximately 10 instruction slots used

+#endif

+

+const BYTE g_PS_ClearFloat[] =

+{

+     68,  88,  66,  67,   0,  45, 

+     15,  86, 227, 217,  47, 173, 

+     72, 182, 197, 224, 178, 165, 

+     77,  73,   1,   0,   0,   0, 

+     84,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+     72,   1,   0,   0, 124,   1, 

+      0,   0, 120,   2,   0,   0, 

+    216,   3,   0,   0,  82,  68, 

+     69,  70,  12,   1,   0,   0, 

+      1,   0,   0,   0,  84,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    216,   0,   0,   0,  60,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+     67, 111, 108, 111, 114,  65, 

+    110, 100,  68, 101, 112, 116, 

+    104,  68,  97, 116,  97,  70, 

+    108, 111,  97, 116,   0, 171, 

+     60,   0,   0,   0,   2,   0, 

+      0,   0, 108,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    156,   0,   0,   0,   0,   0, 

+      0,   0,  16,   0,   0,   0, 

+      2,   0,   0,   0, 168,   0, 

+      0,   0,   0,   0,   0,   0, 

+    184,   0,   0,   0,  16,   0, 

+      0,   0,   4,   0,   0,   0, 

+      2,   0,   0,   0, 200,   0, 

+      0,   0,   0,   0,   0,   0, 

+     99, 111, 108, 111, 114,  95, 

+     70, 108, 111,  97, 116,   0, 

+      1,   0,   3,   0,   1,   0, 

+      4,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 122,  86, 

+     97, 108, 117, 101,  70,  95, 

+     70, 108, 111,  97, 116,   0, 

+    171, 171,   0,   0,   3,   0, 

+      1,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  79,  83,  71,  78, 

+    244,   0,   0,   0,   9,   0, 

+      0,   0,   8,   0,   0,   0, 

+    224,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   2,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   3,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   4,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   4,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   5,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   5,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   6,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   6,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   7,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   7,   0, 

+      0,   0,  15,   0,   0,   0, 

+    234,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0, 255, 255, 

+    255, 255,   1,  14,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0,  83,  86, 

+     95,  68,  69,  80,  84,  72, 

+      0, 171,  83,  72,  68,  82, 

+     88,   1,   0,   0,  64,   0, 

+      0,   0,  86,   0,   0,   0, 

+     89,   0,   0,   4,  70, 142, 

+     32,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      3,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      4,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      5,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      6,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      7,   0,   0,   0, 101,   0, 

+      0,   2,   1, 192,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   1,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   2,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   3,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   4,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   5,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   6,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   7,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,   1, 192, 

+      0,   0,  10, 128,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,  10,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   9,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      9,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h
new file mode 100644
index 0000000..2ab7372
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h
@@ -0,0 +1,257 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer ColorAndDepthDataSint

+// {

+//

+//   int4 color_Sint;                   // Offset:    0 Size:    16

+//   float zValueF_Sint;                // Offset:   16 Size:     4

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// ColorAndDepthDataSint             cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+// SV_TARGET                1   xyzw        1   TARGET     int   xyzw

+// SV_TARGET                2   xyzw        2   TARGET     int   xyzw

+// SV_TARGET                3   xyzw        3   TARGET     int   xyzw

+// SV_TARGET                4   xyzw        4   TARGET     int   xyzw

+// SV_TARGET                5   xyzw        5   TARGET     int   xyzw

+// SV_TARGET                6   xyzw        6   TARGET     int   xyzw

+// SV_TARGET                7   xyzw        7   TARGET     int   xyzw

+// SV_DEPTH                 0    N/A   oDepth    DEPTH   float    YES

+//

+ps_4_0

+dcl_constantbuffer cb0[2], immediateIndexed

+dcl_output o0.xyzw

+dcl_output o1.xyzw

+dcl_output o2.xyzw

+dcl_output o3.xyzw

+dcl_output o4.xyzw

+dcl_output o5.xyzw

+dcl_output o6.xyzw

+dcl_output o7.xyzw

+dcl_output oDepth

+mov o0.xyzw, cb0[0].xyzw

+mov o1.xyzw, cb0[0].xyzw

+mov o2.xyzw, cb0[0].xyzw

+mov o3.xyzw, cb0[0].xyzw

+mov o4.xyzw, cb0[0].xyzw

+mov o5.xyzw, cb0[0].xyzw

+mov o6.xyzw, cb0[0].xyzw

+mov o7.xyzw, cb0[0].xyzw

+mov oDepth, cb0[1].x

+ret 

+// Approximately 10 instruction slots used

+#endif

+

+const BYTE g_PS_ClearSint[] =

+{

+     68,  88,  66,  67,  40,  80, 

+     87,  20, 166, 137,  87,  18, 

+     79,  10,  71, 118,   4,  27, 

+     31, 113,   1,   0,   0,   0, 

+     84,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+     72,   1,   0,   0, 124,   1, 

+      0,   0, 120,   2,   0,   0, 

+    216,   3,   0,   0,  82,  68, 

+     69,  70,  12,   1,   0,   0, 

+      1,   0,   0,   0,  84,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    216,   0,   0,   0,  60,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+     67, 111, 108, 111, 114,  65, 

+    110, 100,  68, 101, 112, 116, 

+    104,  68,  97, 116,  97,  83, 

+    105, 110, 116,   0, 171, 171, 

+     60,   0,   0,   0,   2,   0, 

+      0,   0, 108,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    156,   0,   0,   0,   0,   0, 

+      0,   0,  16,   0,   0,   0, 

+      2,   0,   0,   0, 168,   0, 

+      0,   0,   0,   0,   0,   0, 

+    184,   0,   0,   0,  16,   0, 

+      0,   0,   4,   0,   0,   0, 

+      2,   0,   0,   0, 200,   0, 

+      0,   0,   0,   0,   0,   0, 

+     99, 111, 108, 111, 114,  95, 

+     83, 105, 110, 116,   0, 171, 

+      1,   0,   2,   0,   1,   0, 

+      4,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 122,  86, 

+     97, 108, 117, 101,  70,  95, 

+     83, 105, 110, 116,   0, 171, 

+    171, 171,   0,   0,   3,   0, 

+      1,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  79,  83,  71,  78, 

+    244,   0,   0,   0,   9,   0, 

+      0,   0,   8,   0,   0,   0, 

+    224,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   1,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   2,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   3,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   4,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   4,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   5,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   5,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   6,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   6,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   7,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   7,   0, 

+      0,   0,  15,   0,   0,   0, 

+    234,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0, 255, 255, 

+    255, 255,   1,  14,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0,  83,  86, 

+     95,  68,  69,  80,  84,  72, 

+      0, 171,  83,  72,  68,  82, 

+     88,   1,   0,   0,  64,   0, 

+      0,   0,  86,   0,   0,   0, 

+     89,   0,   0,   4,  70, 142, 

+     32,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      3,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      4,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      5,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      6,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      7,   0,   0,   0, 101,   0, 

+      0,   2,   1, 192,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   1,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   2,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   3,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   4,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   5,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   6,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   7,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,   1, 192, 

+      0,   0,  10, 128,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,  10,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   9,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      9,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h
new file mode 100644
index 0000000..17930fe
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h
@@ -0,0 +1,257 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer ColorAndDepthDataUint

+// {

+//

+//   uint4 color_Uint;                  // Offset:    0 Size:    16

+//   float zValueF_Uint;                // Offset:   16 Size:     4

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// ColorAndDepthDataUint             cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+// SV_TARGET                1   xyzw        1   TARGET    uint   xyzw

+// SV_TARGET                2   xyzw        2   TARGET    uint   xyzw

+// SV_TARGET                3   xyzw        3   TARGET    uint   xyzw

+// SV_TARGET                4   xyzw        4   TARGET    uint   xyzw

+// SV_TARGET                5   xyzw        5   TARGET    uint   xyzw

+// SV_TARGET                6   xyzw        6   TARGET    uint   xyzw

+// SV_TARGET                7   xyzw        7   TARGET    uint   xyzw

+// SV_DEPTH                 0    N/A   oDepth    DEPTH   float    YES

+//

+ps_4_0

+dcl_constantbuffer cb0[2], immediateIndexed

+dcl_output o0.xyzw

+dcl_output o1.xyzw

+dcl_output o2.xyzw

+dcl_output o3.xyzw

+dcl_output o4.xyzw

+dcl_output o5.xyzw

+dcl_output o6.xyzw

+dcl_output o7.xyzw

+dcl_output oDepth

+mov o0.xyzw, cb0[0].xyzw

+mov o1.xyzw, cb0[0].xyzw

+mov o2.xyzw, cb0[0].xyzw

+mov o3.xyzw, cb0[0].xyzw

+mov o4.xyzw, cb0[0].xyzw

+mov o5.xyzw, cb0[0].xyzw

+mov o6.xyzw, cb0[0].xyzw

+mov o7.xyzw, cb0[0].xyzw

+mov oDepth, cb0[1].x

+ret 

+// Approximately 10 instruction slots used

+#endif

+

+const BYTE g_PS_ClearUint[] =

+{

+     68,  88,  66,  67,  31,  50, 

+    232, 254, 182, 197, 174, 161, 

+     39, 175,  44,  65,  71, 251, 

+     37, 230,   1,   0,   0,   0, 

+     84,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+     72,   1,   0,   0, 124,   1, 

+      0,   0, 120,   2,   0,   0, 

+    216,   3,   0,   0,  82,  68, 

+     69,  70,  12,   1,   0,   0, 

+      1,   0,   0,   0,  84,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    216,   0,   0,   0,  60,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+     67, 111, 108, 111, 114,  65, 

+    110, 100,  68, 101, 112, 116, 

+    104,  68,  97, 116,  97,  85, 

+    105, 110, 116,   0, 171, 171, 

+     60,   0,   0,   0,   2,   0, 

+      0,   0, 108,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    156,   0,   0,   0,   0,   0, 

+      0,   0,  16,   0,   0,   0, 

+      2,   0,   0,   0, 168,   0, 

+      0,   0,   0,   0,   0,   0, 

+    184,   0,   0,   0,  16,   0, 

+      0,   0,   4,   0,   0,   0, 

+      2,   0,   0,   0, 200,   0, 

+      0,   0,   0,   0,   0,   0, 

+     99, 111, 108, 111, 114,  95, 

+     85, 105, 110, 116,   0, 171, 

+      1,   0,  19,   0,   1,   0, 

+      4,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 122,  86, 

+     97, 108, 117, 101,  70,  95, 

+     85, 105, 110, 116,   0, 171, 

+    171, 171,   0,   0,   3,   0, 

+      1,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  79,  83,  71,  78, 

+    244,   0,   0,   0,   9,   0, 

+      0,   0,   8,   0,   0,   0, 

+    224,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   2,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   4,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   4,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   5,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   5,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   6,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   6,   0, 

+      0,   0,  15,   0,   0,   0, 

+    224,   0,   0,   0,   7,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   7,   0, 

+      0,   0,  15,   0,   0,   0, 

+    234,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0, 255, 255, 

+    255, 255,   1,  14,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0,  83,  86, 

+     95,  68,  69,  80,  84,  72, 

+      0, 171,  83,  72,  68,  82, 

+     88,   1,   0,   0,  64,   0, 

+      0,   0,  86,   0,   0,   0, 

+     89,   0,   0,   4,  70, 142, 

+     32,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      3,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      4,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      5,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      6,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      7,   0,   0,   0, 101,   0, 

+      0,   2,   1, 192,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   1,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   2,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   3,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   4,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   5,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   6,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6, 242,  32, 

+     16,   0,   7,   0,   0,   0, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,   1, 192, 

+      0,   0,  10, 128,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,  10,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   9,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      9,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h
new file mode 100644
index 0000000..050040e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h
@@ -0,0 +1,177 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// POSITION                 0   xy          0     NONE   float   xy  

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float   xyzw

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Runtime generated constant mappings:

+//

+// Target Reg                               Constant Description

+// ---------- --------------------------------------------------

+// c0                              Vertex Shader position offset

+//

+//

+// Level9 shader bytecode:

+//

+    vs_2_x

+    def c1, 0, 1, 0, 0

+    dcl_texcoord v0

+    dcl_texcoord1 v1

+    add oPos.xy, v0, c0

+    mov oPos.zw, c1.xyxy

+    mov oT0.xy, v1

+

+// approximately 3 instruction slots used

+vs_4_0

+dcl_input v0.xy

+dcl_input v1.xy

+dcl_output_siv o0.xyzw, position

+dcl_output o1.xy

+mov o0.xy, v0.xyxx

+mov o0.zw, l(0,0,0,1.000000)

+mov o1.xy, v1.xyxx

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_VS_Passthrough2D[] =

+{

+     68,  88,  66,  67, 230,  95, 

+    115, 230,  65, 211,  74,  82, 

+    143, 170, 109, 175,  63, 210, 

+     14, 229,   1,   0,   0,   0, 

+    216,   2,   0,   0,   6,   0, 

+      0,   0,  56,   0,   0,   0, 

+    200,   0,   0,   0,  88,   1, 

+      0,   0, 212,   1,   0,   0, 

+     44,   2,   0,   0, 128,   2, 

+      0,   0,  65, 111, 110,  57, 

+    136,   0,   0,   0, 136,   0, 

+      0,   0,   0,   2, 254, 255, 

+     96,   0,   0,   0,  40,   0, 

+      0,   0,   0,   0,  36,   0, 

+      0,   0,  36,   0,   0,   0, 

+     36,   0,   0,   0,  36,   0, 

+      1,   0,  36,   0,   0,   0, 

+      0,   0,   1,   2, 254, 255, 

+     81,   0,   0,   5,   1,   0, 

+     15, 160,   0,   0,   0,   0, 

+      0,   0, 128,  63,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     31,   0,   0,   2,   5,   0, 

+      0, 128,   0,   0,  15, 144, 

+     31,   0,   0,   2,   5,   0, 

+      1, 128,   1,   0,  15, 144, 

+      2,   0,   0,   3,   0,   0, 

+      3, 192,   0,   0, 228, 144, 

+      0,   0, 228, 160,   1,   0, 

+      0,   2,   0,   0,  12, 192, 

+      1,   0,  68, 160,   1,   0, 

+      0,   2,   0,   0,   3, 224, 

+      1,   0, 228, 144, 255, 255, 

+      0,   0,  83,  72,  68,  82, 

+    136,   0,   0,   0,  64,   0, 

+      1,   0,  34,   0,   0,   0, 

+     95,   0,   0,   3,  50,  16, 

+     16,   0,   0,   0,   0,   0, 

+     95,   0,   0,   3,  50,  16, 

+     16,   0,   1,   0,   0,   0, 

+    103,   0,   0,   4, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3,  50,  32,  16,   0, 

+      1,   0,   0,   0,  54,   0, 

+      0,   5,  50,  32,  16,   0, 

+      0,   0,   0,   0,  70,  16, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,  32, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    128,  63,  54,   0,   0,   5, 

+     50,  32,  16,   0,   1,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   4,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     82,  68,  69,  70,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  28,   0,   0,   0, 

+      0,   4, 254, 255,   0,   1, 

+      0,   0,  28,   0,   0,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78,  76,   0,   0,   0, 

+      2,   0,   0,   0,   8,   0, 

+      0,   0,  56,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   3,   3, 

+      0,   0,  65,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,   3,   3, 

+      0,   0,  80,  79,  83,  73, 

+     84,  73,  79,  78,   0,  84, 

+     69,  88,  67,  79,  79,  82, 

+     68,   0, 171, 171,  79,  83, 

+     71,  78,  80,   0,   0,   0, 

+      2,   0,   0,   0,   8,   0, 

+      0,   0,  56,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  68,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,   3,  12, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0, 171, 

+    171, 171

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h
new file mode 100644
index 0000000..ae2d948
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h
@@ -0,0 +1,191 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float   xyzw

+// LAYER                    0   x           1     NONE    uint   x   

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float   xyzw

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint   x   

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+gs_4_0

+dcl_input_siv v[3][0].xyzw, position

+dcl_input v[3][1].x

+dcl_input v[3][2].xyz

+dcl_temps 1

+dcl_inputprimitive triangle 

+dcl_outputtopology trianglestrip 

+dcl_output_siv o0.xyzw, position

+dcl_output_siv o1.x, rendertarget_array_index

+dcl_output o2.xyz

+dcl_maxout 3

+mov r0.x, l(0)

+loop 

+  ige r0.y, r0.x, l(3)

+  breakc_nz r0.y

+  mov o0.xyzw, v[r0.x + 0][0].xyzw

+  mov o1.x, v[r0.x + 0][1].x

+  mov o2.xyz, v[r0.x + 0][2].xyzx

+  emit 

+  iadd r0.x, r0.x, l(1)

+endloop 

+ret 

+// Approximately 11 instruction slots used

+#endif

+

+const BYTE g_GS_Passthrough3D[] =

+{

+     68,  88,  66,  67,  92, 129, 

+     41, 170, 114,  75, 160, 250, 

+     95, 161, 230, 161,  11,  78, 

+    252,  65,   1,   0,   0,   0, 

+     72,   3,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    140,   0,   0,   0,   0,   1, 

+      0,   0, 136,   1,   0,   0, 

+    204,   2,   0,   0,  82,  68, 

+     69,  70,  80,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+     83,  71,   0,   1,   0,   0, 

+     28,   0,   0,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+    171, 171,  73,  83,  71,  78, 

+    108,   0,   0,   0,   3,   0, 

+      0,   0,   8,   0,   0,   0, 

+     80,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,  15,   0,   0, 

+     92,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,   1,   1,   0,   0, 

+     98,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   2,   0, 

+      0,   0,   7,   7,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     76,  65,  89,  69,  82,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,  14, 

+      0,   0, 118,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0,   7,   8, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  83,  86,  95,  82, 

+     69,  78,  68,  69,  82,  84, 

+     65,  82,  71,  69,  84,  65, 

+     82,  82,  65,  89,  73,  78, 

+     68,  69,  88,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  83,  72,  68,  82, 

+     60,   1,   0,   0,  64,   0, 

+      2,   0,  79,   0,   0,   0, 

+     97,   0,   0,   5, 242,  16, 

+     32,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  95,   0,   0,   4, 

+     18,  16,  32,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+     95,   0,   0,   4, 114,  16, 

+     32,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     93,  24,   0,   1,  92,  40, 

+      0,   1, 103,   0,   0,   4, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+    103,   0,   0,   4,  18,  32, 

+     16,   0,   1,   0,   0,   0, 

+      4,   0,   0,   0, 101,   0, 

+      0,   3, 114,  32,  16,   0, 

+      2,   0,   0,   0,  94,   0, 

+      0,   2,   3,   0,   0,   0, 

+     54,   0,   0,   5,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  48,   0,   0,   1, 

+     33,   0,   0,   7,  34,   0, 

+     16,   0,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,   1,  64,   0,   0, 

+      3,   0,   0,   0,   3,   0, 

+      4,   3,  26,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7, 242,  32,  16,   0, 

+      0,   0,   0,   0,  70,  30, 

+    160,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     18,  32,  16,   0,   1,   0, 

+      0,   0,  10,  16, 160,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     54,   0,   0,   7, 114,  32, 

+     16,   0,   2,   0,   0,   0, 

+     70,  18, 160,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,  19,   0, 

+      0,   1,  30,   0,   0,   7, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,   1,  64, 

+      0,   0,   1,   0,   0,   0, 

+     22,   0,   0,   1,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,  11,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   6,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   5,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h
new file mode 100644
index 0000000..5701a40
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h
@@ -0,0 +1,155 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// POSITION                 0   xy          0     NONE   float   xy  

+// LAYER                    0   x           1     NONE    uint   x   

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float   xyzw

+// LAYER                    0   x           1     NONE    uint   x   

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+vs_4_0

+dcl_input v0.xy

+dcl_input v1.x

+dcl_input v2.xyz

+dcl_output_siv o0.xyzw, position

+dcl_output o1.x

+dcl_output o2.xyz

+mov o0.xy, v0.xyxx

+mov o0.zw, l(0,0,0,1.000000)

+mov o1.x, v1.x

+mov o2.xyz, v2.xyzx

+ret 

+// Approximately 5 instruction slots used

+#endif

+

+const BYTE g_VS_Passthrough3D[] =

+{

+     68,  88,  66,  67, 229,  65, 

+    217, 172, 143, 180, 152,  72, 

+     16,  12, 254,  66,   0, 215, 

+     50, 173,   1,   0,   0,   0, 

+    168,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    140,   0,   0,   0, 252,   0, 

+      0,   0, 112,   1,   0,   0, 

+     44,   2,   0,   0,  82,  68, 

+     69,  70,  80,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    254, 255,   0,   1,   0,   0, 

+     28,   0,   0,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+    171, 171,  73,  83,  71,  78, 

+    104,   0,   0,   0,   3,   0, 

+      0,   0,   8,   0,   0,   0, 

+     80,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,   3,   3,   0,   0, 

+     89,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,   1,   1,   0,   0, 

+     95,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   2,   0, 

+      0,   0,   7,   7,   0,   0, 

+     80,  79,  83,  73,  84,  73, 

+     79,  78,   0,  76,  65,  89, 

+     69,  82,   0,  84,  69,  88, 

+     67,  79,  79,  82,  68,   0, 

+     79,  83,  71,  78, 108,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,  14,   0,   0,  98,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   8,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  76,  65, 

+     89,  69,  82,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  83,  72,  68,  82, 

+    180,   0,   0,   0,  64,   0, 

+      1,   0,  45,   0,   0,   0, 

+     95,   0,   0,   3,  50,  16, 

+     16,   0,   0,   0,   0,   0, 

+     95,   0,   0,   3,  18,  16, 

+     16,   0,   1,   0,   0,   0, 

+     95,   0,   0,   3, 114,  16, 

+     16,   0,   2,   0,   0,   0, 

+    103,   0,   0,   4, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3,  18,  32,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 114,  32,  16,   0, 

+      2,   0,   0,   0,  54,   0, 

+      0,   5,  50,  32,  16,   0, 

+      0,   0,   0,   0,  70,  16, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,  32, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    128,  63,  54,   0,   0,   5, 

+     18,  32,  16,   0,   1,   0, 

+      0,   0,  10,  16,  16,   0, 

+      1,   0,   0,   0,  54,   0, 

+      0,   5, 114,  32,  16,   0, 

+      2,   0,   0,   0,  70,  18, 

+     16,   0,   2,   0,   0,   0, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      5,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      6,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h
new file mode 100644
index 0000000..38acea3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h
@@ -0,0 +1,145 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_DEPTH                 0    N/A   oDepth    DEPTH   float    YES

+//

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output oDepth

+dcl_temps 1

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+mov oDepth, r0.x

+ret 

+// Approximately 3 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughDepth2D[] =

+{

+     68,  88,  66,  67,   8,  33, 

+    154,  92, 164,  28, 139, 205, 

+      1, 168,  30, 229,  51, 127, 

+    173, 221,   1,   0,   0,   0, 

+    100,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    220,   0,   0,   0,  52,   1, 

+      0,   0, 104,   1,   0,   0, 

+    232,   1,   0,   0,  82,  68, 

+     69,  70, 160,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    109,   0,   0,   0,  92,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    100,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      4,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0,  83,  97, 109, 112, 

+    108, 101, 114,   0,  84, 101, 

+    120, 116, 117, 114, 101,  70, 

+      0,  77, 105,  99, 114, 111, 

+    115, 111, 102, 116,  32,  40, 

+     82,  41,  32,  72,  76,  83, 

+     76,  32,  83, 104,  97, 100, 

+    101, 114,  32,  67, 111, 109, 

+    112, 105, 108, 101, 114,  32, 

+     54,  46,  51,  46,  57,  54, 

+     48,  48,  46,  49,  54,  51, 

+     56,  52,   0, 171,  73,  83, 

+     71,  78,  80,   0,   0,   0, 

+      2,   0,   0,   0,   8,   0, 

+      0,   0,  56,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  68,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,   3,   3, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0, 171, 

+    171, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0, 255, 255, 

+    255, 255,   1,  14,   0,   0, 

+     83,  86,  95,  68,  69,  80, 

+     84,  72,   0, 171, 171, 171, 

+     83,  72,  68,  82, 120,   0, 

+      0,   0,  64,   0,   0,   0, 

+     30,   0,   0,   0,  90,   0, 

+      0,   3,   0,  96,  16,   0, 

+      0,   0,   0,   0,  88,  24, 

+      0,   4,   0, 112,  16,   0, 

+      0,   0,   0,   0,  85,  85, 

+      0,   0,  98,  16,   0,   3, 

+     50,  16,  16,   0,   1,   0, 

+      0,   0, 101,   0,   0,   2, 

+      1, 192,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     69,   0,   0,   9, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,  16,  16,   0,   1,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,   0,  96, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   4,   1, 192, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h
new file mode 100644
index 0000000..e0bcbc8
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h
@@ -0,0 +1,196 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    def c0, 1, 0, 0, 0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mad r0, r0.x, c0.xxxy, c0.yyyx

+    mov oC0, r0

+

+// approximately 3 instruction slots used (1 texture, 2 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+mov o0.xyz, r0.xxxx

+mov o0.w, l(1.000000)

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughLum2D[] =

+{

+     68,  88,  66,  67, 144,  18, 

+    242,  89, 150, 125,  18, 219, 

+    193, 196, 127, 207,  14, 165, 

+    198, 119,   1,   0,   0,   0, 

+     28,   3,   0,   0,   6,   0, 

+      0,   0,  56,   0,   0,   0, 

+    208,   0,   0,   0, 108,   1, 

+      0,   0, 232,   1,   0,   0, 

+    144,   2,   0,   0, 232,   2, 

+      0,   0,  65, 111, 110,  57, 

+    144,   0,   0,   0, 144,   0, 

+      0,   0,   0,   2, 255, 255, 

+    104,   0,   0,   0,  40,   0, 

+      0,   0,   0,   0,  40,   0, 

+      0,   0,  40,   0,   0,   0, 

+     40,   0,   1,   0,  36,   0, 

+      0,   0,  40,   0,   0,   0, 

+      0,   0,   1,   2, 255, 255, 

+     81,   0,   0,   5,   0,   0, 

+     15, 160,   0,   0, 128,  63, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     31,   0,   0,   2,   0,   0, 

+      0, 128,   0,   0,   3, 176, 

+     31,   0,   0,   2,   0,   0, 

+      0, 144,   0,   8,  15, 160, 

+     66,   0,   0,   3,   0,   0, 

+     15, 128,   0,   0, 228, 176, 

+      0,   8, 228, 160,   4,   0, 

+      0,   4,   0,   0,  15, 128, 

+      0,   0,   0, 128,   0,   0, 

+     64, 160,   0,   0,  21, 160, 

+      1,   0,   0,   2,   0,   8, 

+     15, 128,   0,   0, 228, 128, 

+    255, 255,   0,   0,  83,  72, 

+     68,  82, 148,   0,   0,   0, 

+     64,   0,   0,   0,  37,   0, 

+      0,   0,  90,   0,   0,   3, 

+      0,  96,  16,   0,   0,   0, 

+      0,   0,  88,  24,   0,   4, 

+      0, 112,  16,   0,   0,   0, 

+      0,   0,  85,  85,   0,   0, 

+     98,  16,   0,   3,  50,  16, 

+     16,   0,   1,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0,  69,   0,   0,   9, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+      0,  96,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+    114,  32,  16,   0,   0,   0, 

+      0,   0,   6,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   5, 130,  32,  16,   0, 

+      0,   0,   0,   0,   1,  64, 

+      0,   0,   0,   0, 128,  63, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  82,  68,  69,  70, 

+    160,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,  28,   0, 

+      0,   0,   0,   4, 255, 255, 

+      0,   1,   0,   0, 109,   0, 

+      0,   0,  92,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 100,   0, 

+      0,   0,   2,   0,   0,   0, 

+      5,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     83,  97, 109, 112, 108, 101, 

+    114,   0,  84, 101, 120, 116, 

+    117, 114, 101,  70,   0,  77, 

+    105,  99, 114, 111, 115, 111, 

+    102, 116,  32,  40,  82,  41, 

+     32,  72,  76,  83,  76,  32, 

+     83, 104,  97, 100, 101, 114, 

+     32,  67, 111, 109, 112, 105, 

+    108, 101, 114,  32,  54,  46, 

+     51,  46,  57,  54,  48,  48, 

+     46,  49,  54,  51,  56,  52, 

+      0, 171,  73,  83,  71,  78, 

+     80,   0,   0,   0,   2,   0, 

+      0,   0,   8,   0,   0,   0, 

+     56,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     68,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0,   3,   3,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171, 171, 171, 

+     79,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  83,  86, 

+     95,  84,  65,  82,  71,  69, 

+     84,   0, 171, 171

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h
new file mode 100644
index 0000000..ac2bb40
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h
@@ -0,0 +1,160 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture3d (float,float,float,float) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v2.xyzx, t0.xyzw, s0

+mov o0.xyz, r0.xxxx

+mov o0.w, l(1.000000)

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughLum3D[] =

+{

+     68,  88,  66,  67, 173, 177, 

+    219,  35, 149, 130,  33, 215, 

+    183, 219, 250, 244, 100,  17, 

+     62, 106,   1,   0,   0,   0, 

+    176,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    220,   0,   0,   0, 100,   1, 

+      0,   0, 152,   1,   0,   0, 

+     52,   2,   0,   0,  82,  68, 

+     69,  70, 160,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    109,   0,   0,   0,  92,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    100,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      8,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0,  83,  97, 109, 112, 

+    108, 101, 114,   0,  84, 101, 

+    120, 116, 117, 114, 101,  70, 

+      0,  77, 105,  99, 114, 111, 

+    115, 111, 102, 116,  32,  40, 

+     82,  41,  32,  72,  76,  83, 

+     76,  32,  83, 104,  97, 100, 

+    101, 114,  32,  67, 111, 109, 

+    112, 105, 108, 101, 114,  32, 

+     54,  46,  51,  46,  57,  54, 

+     48,  48,  46,  49,  54,  51, 

+     56,  52,   0, 171,  73,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0, 118,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0,   7,   7, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  83,  86,  95,  82, 

+     69,  78,  68,  69,  82,  84, 

+     65,  82,  71,  69,  84,  65, 

+     82,  82,  65,  89,  73,  78, 

+     68,  69,  88,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82, 148,   0, 

+      0,   0,  64,   0,   0,   0, 

+     37,   0,   0,   0,  90,   0, 

+      0,   3,   0,  96,  16,   0, 

+      0,   0,   0,   0,  88,  40, 

+      0,   4,   0, 112,  16,   0, 

+      0,   0,   0,   0,  85,  85, 

+      0,   0,  98,  16,   0,   3, 

+    114,  16,  16,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0, 104,   0,   0,   2, 

+      1,   0,   0,   0,  69,   0, 

+      0,   9, 242,   0,  16,   0, 

+      0,   0,   0,   0,  70,  18, 

+     16,   0,   2,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,   0,  96,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   5, 114,  32,  16,   0, 

+      0,   0,   0,   0,   6,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,  32, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+    128,  63,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,   4,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h
new file mode 100644
index 0000000..88599fc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h
@@ -0,0 +1,185 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mov r0, r0.xxxw

+    mov oC0, r0

+

+// approximately 3 instruction slots used (1 texture, 2 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+mov o0.xyzw, r0.xxxw

+ret 

+// Approximately 3 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughLumAlpha2D[] =

+{

+     68,  88,  66,  67, 246, 240, 

+    158, 208, 214, 197, 166, 221, 

+     45,  58, 235, 164,  12, 157, 

+     62,  31,   1,   0,   0,   0, 

+    232,   2,   0,   0,   6,   0, 

+      0,   0,  56,   0,   0,   0, 

+    176,   0,   0,   0,  56,   1, 

+      0,   0, 180,   1,   0,   0, 

+     92,   2,   0,   0, 180,   2, 

+      0,   0,  65, 111, 110,  57, 

+    112,   0,   0,   0, 112,   0, 

+      0,   0,   0,   2, 255, 255, 

+     72,   0,   0,   0,  40,   0, 

+      0,   0,   0,   0,  40,   0, 

+      0,   0,  40,   0,   0,   0, 

+     40,   0,   1,   0,  36,   0, 

+      0,   0,  40,   0,   0,   0, 

+      0,   0,   1,   2, 255, 255, 

+     31,   0,   0,   2,   0,   0, 

+      0, 128,   0,   0,   3, 176, 

+     31,   0,   0,   2,   0,   0, 

+      0, 144,   0,   8,  15, 160, 

+     66,   0,   0,   3,   0,   0, 

+     15, 128,   0,   0, 228, 176, 

+      0,   8, 228, 160,   1,   0, 

+      0,   2,   0,   0,  15, 128, 

+      0,   0, 192, 128,   1,   0, 

+      0,   2,   0,   8,  15, 128, 

+      0,   0, 228, 128, 255, 255, 

+      0,   0,  83,  72,  68,  82, 

+    128,   0,   0,   0,  64,   0, 

+      0,   0,  32,   0,   0,   0, 

+     90,   0,   0,   3,   0,  96, 

+     16,   0,   0,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     85,  85,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     69,   0,   0,   9, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,  16,  16,   0,   1,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,   0,  96, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+      6,  12,  16,   0,   0,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  82,  68, 

+     69,  70, 160,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    109,   0,   0,   0,  92,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    100,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      4,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0,  83,  97, 109, 112, 

+    108, 101, 114,   0,  84, 101, 

+    120, 116, 117, 114, 101,  70, 

+      0,  77, 105,  99, 114, 111, 

+    115, 111, 102, 116,  32,  40, 

+     82,  41,  32,  72,  76,  83, 

+     76,  32,  83, 104,  97, 100, 

+    101, 114,  32,  67, 111, 109, 

+    112, 105, 108, 101, 114,  32, 

+     54,  46,  51,  46,  57,  54, 

+     48,  48,  46,  49,  54,  51, 

+     56,  52,   0, 171,  73,  83, 

+     71,  78,  80,   0,   0,   0, 

+      2,   0,   0,   0,   8,   0, 

+      0,   0,  56,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  68,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,   3,   3, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0, 171, 

+    171, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h
new file mode 100644
index 0000000..19091d0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h
@@ -0,0 +1,156 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture3d (float,float,float,float) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v2.xyzx, t0.xyzw, s0

+mov o0.xyzw, r0.xxxw

+ret 

+// Approximately 3 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughLumAlpha3D[] =

+{

+     68,  88,  66,  67, 224, 152, 

+    208, 227,  44, 106,  62, 235, 

+    129,  97, 207, 213,  29, 232, 

+    163,   6,   1,   0,   0,   0, 

+    156,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    220,   0,   0,   0, 100,   1, 

+      0,   0, 152,   1,   0,   0, 

+     32,   2,   0,   0,  82,  68, 

+     69,  70, 160,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    109,   0,   0,   0,  92,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    100,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      8,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0,  83,  97, 109, 112, 

+    108, 101, 114,   0,  84, 101, 

+    120, 116, 117, 114, 101,  70, 

+      0,  77, 105,  99, 114, 111, 

+    115, 111, 102, 116,  32,  40, 

+     82,  41,  32,  72,  76,  83, 

+     76,  32,  83, 104,  97, 100, 

+    101, 114,  32,  67, 111, 109, 

+    112, 105, 108, 101, 114,  32, 

+     54,  46,  51,  46,  57,  54, 

+     48,  48,  46,  49,  54,  51, 

+     56,  52,   0, 171,  73,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0, 118,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0,   7,   7, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  83,  86,  95,  82, 

+     69,  78,  68,  69,  82,  84, 

+     65,  82,  71,  69,  84,  65, 

+     82,  82,  65,  89,  73,  78, 

+     68,  69,  88,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82, 128,   0, 

+      0,   0,  64,   0,   0,   0, 

+     32,   0,   0,   0,  90,   0, 

+      0,   3,   0,  96,  16,   0, 

+      0,   0,   0,   0,  88,  40, 

+      0,   4,   0, 112,  16,   0, 

+      0,   0,   0,   0,  85,  85, 

+      0,   0,  98,  16,   0,   3, 

+    114,  16,  16,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0, 104,   0,   0,   2, 

+      1,   0,   0,   0,  69,   0, 

+      0,   9, 242,   0,  16,   0, 

+      0,   0,   0,   0,  70,  18, 

+     16,   0,   2,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,   0,  96,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   5, 242,  32,  16,   0, 

+      0,   0,   0,   0,   6,  12, 

+     16,   0,   0,   0,   0,   0, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h
new file mode 100644
index 0000000..d421016
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h
@@ -0,0 +1,198 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    def c0, 1, 0, 0, 0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mad r0, r0.x, c0.xyyy, c0.yyyx

+    mov oC0, r0

+

+// approximately 3 instruction slots used (1 texture, 2 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+mov o0.x, r0.x

+mov o0.yzw, l(0,0,0,1.000000)

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughR2D[] =

+{

+     68,  88,  66,  67, 212, 251, 

+    117, 250,  99, 185,  28,  44, 

+    178,  14,  83, 133, 173,   0, 

+    182, 196,   1,   0,   0,   0, 

+     40,   3,   0,   0,   6,   0, 

+      0,   0,  56,   0,   0,   0, 

+    208,   0,   0,   0, 120,   1, 

+      0,   0, 244,   1,   0,   0, 

+    156,   2,   0,   0, 244,   2, 

+      0,   0,  65, 111, 110,  57, 

+    144,   0,   0,   0, 144,   0, 

+      0,   0,   0,   2, 255, 255, 

+    104,   0,   0,   0,  40,   0, 

+      0,   0,   0,   0,  40,   0, 

+      0,   0,  40,   0,   0,   0, 

+     40,   0,   1,   0,  36,   0, 

+      0,   0,  40,   0,   0,   0, 

+      0,   0,   1,   2, 255, 255, 

+     81,   0,   0,   5,   0,   0, 

+     15, 160,   0,   0, 128,  63, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     31,   0,   0,   2,   0,   0, 

+      0, 128,   0,   0,   3, 176, 

+     31,   0,   0,   2,   0,   0, 

+      0, 144,   0,   8,  15, 160, 

+     66,   0,   0,   3,   0,   0, 

+     15, 128,   0,   0, 228, 176, 

+      0,   8, 228, 160,   4,   0, 

+      0,   4,   0,   0,  15, 128, 

+      0,   0,   0, 128,   0,   0, 

+     84, 160,   0,   0,  21, 160, 

+      1,   0,   0,   2,   0,   8, 

+     15, 128,   0,   0, 228, 128, 

+    255, 255,   0,   0,  83,  72, 

+     68,  82, 160,   0,   0,   0, 

+     64,   0,   0,   0,  40,   0, 

+      0,   0,  90,   0,   0,   3, 

+      0,  96,  16,   0,   0,   0, 

+      0,   0,  88,  24,   0,   4, 

+      0, 112,  16,   0,   0,   0, 

+      0,   0,  85,  85,   0,   0, 

+     98,  16,   0,   3,  50,  16, 

+     16,   0,   1,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0,  69,   0,   0,   9, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+      0,  96,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+     18,  32,  16,   0,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   8, 226,  32,  16,   0, 

+      0,   0,   0,   0,   2,  64, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 128,  63, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  82,  68,  69,  70, 

+    160,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,  28,   0, 

+      0,   0,   0,   4, 255, 255, 

+      0,   1,   0,   0, 109,   0, 

+      0,   0,  92,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 100,   0, 

+      0,   0,   2,   0,   0,   0, 

+      5,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     83,  97, 109, 112, 108, 101, 

+    114,   0,  84, 101, 120, 116, 

+    117, 114, 101,  70,   0,  77, 

+    105,  99, 114, 111, 115, 111, 

+    102, 116,  32,  40,  82,  41, 

+     32,  72,  76,  83,  76,  32, 

+     83, 104,  97, 100, 101, 114, 

+     32,  67, 111, 109, 112, 105, 

+    108, 101, 114,  32,  54,  46, 

+     51,  46,  57,  54,  48,  48, 

+     46,  49,  54,  51,  56,  52, 

+      0, 171,  73,  83,  71,  78, 

+     80,   0,   0,   0,   2,   0, 

+      0,   0,   8,   0,   0,   0, 

+     56,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     68,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0,   3,   3,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171, 171, 171, 

+     79,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  83,  86, 

+     95,  84,  65,  82,  71,  69, 

+     84,   0, 171, 171

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h
new file mode 100644
index 0000000..4d8d993
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h
@@ -0,0 +1,167 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI                          texture   sint4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_resource_texture2d (sint,sint,sint,sint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.x, r0.x

+mov o0.yzw, l(0,0,0,0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughR2DI[] =

+{

+     68,  88,  66,  67, 123, 230, 

+     45,  18,  63, 217,  12, 210, 

+    151, 254,  16,  78, 107, 211, 

+     57, 255,   1,   0,   0,   0, 

+    208,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+     84,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     69,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  73,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+     12,   1,   0,   0,  64,   0, 

+      0,   0,  67,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,  18,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   8, 

+    226,  32,  16,   0,   0,   0, 

+      0,   0,   2,  64,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h
new file mode 100644
index 0000000..3f3885a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h
@@ -0,0 +1,167 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI                         texture   uint4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_resource_texture2d (uint,uint,uint,uint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.x, r0.x

+mov o0.yzw, l(0,0,0,0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughR2DUI[] =

+{

+     68,  88,  66,  67,   4,  26, 

+     62, 109,  94,  45, 124, 238, 

+    150, 245,  85, 155, 185,  37, 

+    234, 152,   1,   0,   0,   0, 

+    208,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+     84,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     70,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  85,  73,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+     12,   1,   0,   0,  64,   0, 

+      0,   0,  67,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,  18,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   8, 

+    226,  32,  16,   0,   0,   0, 

+      0,   0,   2,  64,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h
new file mode 100644
index 0000000..506baef
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h
@@ -0,0 +1,162 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture3d (float,float,float,float) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v2.xyzx, t0.xyzw, s0

+mov o0.x, r0.x

+mov o0.yzw, l(0,0,0,1.000000)

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughR3D[] =

+{

+     68,  88,  66,  67,  11, 235, 

+    208, 143, 219, 183, 141,  78, 

+    136, 182,  62, 182, 243,  12, 

+    239, 125,   1,   0,   0,   0, 

+    188,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    220,   0,   0,   0, 100,   1, 

+      0,   0, 152,   1,   0,   0, 

+     64,   2,   0,   0,  82,  68, 

+     69,  70, 160,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    109,   0,   0,   0,  92,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    100,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      8,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0,  83,  97, 109, 112, 

+    108, 101, 114,   0,  84, 101, 

+    120, 116, 117, 114, 101,  70, 

+      0,  77, 105,  99, 114, 111, 

+    115, 111, 102, 116,  32,  40, 

+     82,  41,  32,  72,  76,  83, 

+     76,  32,  83, 104,  97, 100, 

+    101, 114,  32,  67, 111, 109, 

+    112, 105, 108, 101, 114,  32, 

+     54,  46,  51,  46,  57,  54, 

+     48,  48,  46,  49,  54,  51, 

+     56,  52,   0, 171,  73,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0, 118,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0,   7,   7, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  83,  86,  95,  82, 

+     69,  78,  68,  69,  82,  84, 

+     65,  82,  71,  69,  84,  65, 

+     82,  82,  65,  89,  73,  78, 

+     68,  69,  88,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82, 160,   0, 

+      0,   0,  64,   0,   0,   0, 

+     40,   0,   0,   0,  90,   0, 

+      0,   3,   0,  96,  16,   0, 

+      0,   0,   0,   0,  88,  40, 

+      0,   4,   0, 112,  16,   0, 

+      0,   0,   0,   0,  85,  85, 

+      0,   0,  98,  16,   0,   3, 

+    114,  16,  16,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0, 104,   0,   0,   2, 

+      1,   0,   0,   0,  69,   0, 

+      0,   9, 242,   0,  16,   0, 

+      0,   0,   0,   0,  70,  18, 

+     16,   0,   2,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,   0,  96,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   5,  18,  32,  16,   0, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 226,  32, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    128,  63,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,   4,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h
new file mode 100644
index 0000000..89c35d6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h
@@ -0,0 +1,174 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI                          texture   sint4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_resource_texture3d (sint,sint,sint,sint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.x, r0.x

+mov o0.yzw, l(0,0,0,0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughR3DI[] =

+{

+     68,  88,  66,  67, 222, 251, 

+     30,  61,  15,  80,  81, 247, 

+    175, 137,  44,  19,  23,  84, 

+    149, 211,   1,   0,   0,   0, 

+    244,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  60,   1, 

+      0,   0, 112,   1,   0,   0, 

+    120,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     69,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  73,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 118,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   7,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  86, 

+     95,  82,  69,  78,  68,  69, 

+     82,  84,  65,  82,  71,  69, 

+     84,  65,  82,  82,  65,  89, 

+     73,  78,  68,  69,  88,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+      0,   1,   0,   0,  64,   0, 

+      0,   0,  64,   0,   0,   0, 

+     88,  40,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0,  98,  16, 

+      0,   3, 114,  16,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,  18,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   8, 

+    226,  32,  16,   0,   0,   0, 

+      0,   0,   2,  64,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h
new file mode 100644
index 0000000..6438684
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h
@@ -0,0 +1,174 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI                         texture   uint4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_resource_texture3d (uint,uint,uint,uint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.x, r0.x

+mov o0.yzw, l(0,0,0,0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughR3DUI[] =

+{

+     68,  88,  66,  67,  69,   5, 

+     86, 212, 201,  54,  97, 205, 

+     89, 161, 100,  72, 246, 114, 

+     40, 214,   1,   0,   0,   0, 

+    244,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  60,   1, 

+      0,   0, 112,   1,   0,   0, 

+    120,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     70,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  85,  73,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+     73,  83,  71,  78, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 118,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   7,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  86, 

+     95,  82,  69,  78,  68,  69, 

+     82,  84,  65,  82,  71,  69, 

+     84,  65,  82,  82,  65,  89, 

+     73,  78,  68,  69,  88,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+      0,   1,   0,   0,  64,   0, 

+      0,   0,  64,   0,   0,   0, 

+     88,  40,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0,  98,  16, 

+      0,   3, 114,  16,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,  18,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   8, 

+    226,  32,  16,   0,   0,   0, 

+      0,   0,   2,  64,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h
new file mode 100644
index 0000000..201cbff
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h
@@ -0,0 +1,198 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    def c0, 1, 0, 0, 0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mad r0, r0.xyxx, c0.xxyy, c0.yyyx

+    mov oC0, r0

+

+// approximately 3 instruction slots used (1 texture, 2 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+mov o0.xy, r0.xyxx

+mov o0.zw, l(0,0,0,1.000000)

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRG2D[] =

+{

+     68,  88,  66,  67, 217, 171, 

+    153, 248,  26,  15, 102, 119, 

+     86, 174, 121, 245, 223,  83, 

+      2, 181,   1,   0,   0,   0, 

+     40,   3,   0,   0,   6,   0, 

+      0,   0,  56,   0,   0,   0, 

+    208,   0,   0,   0, 120,   1, 

+      0,   0, 244,   1,   0,   0, 

+    156,   2,   0,   0, 244,   2, 

+      0,   0,  65, 111, 110,  57, 

+    144,   0,   0,   0, 144,   0, 

+      0,   0,   0,   2, 255, 255, 

+    104,   0,   0,   0,  40,   0, 

+      0,   0,   0,   0,  40,   0, 

+      0,   0,  40,   0,   0,   0, 

+     40,   0,   1,   0,  36,   0, 

+      0,   0,  40,   0,   0,   0, 

+      0,   0,   1,   2, 255, 255, 

+     81,   0,   0,   5,   0,   0, 

+     15, 160,   0,   0, 128,  63, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     31,   0,   0,   2,   0,   0, 

+      0, 128,   0,   0,   3, 176, 

+     31,   0,   0,   2,   0,   0, 

+      0, 144,   0,   8,  15, 160, 

+     66,   0,   0,   3,   0,   0, 

+     15, 128,   0,   0, 228, 176, 

+      0,   8, 228, 160,   4,   0, 

+      0,   4,   0,   0,  15, 128, 

+      0,   0,   4, 128,   0,   0, 

+     80, 160,   0,   0,  21, 160, 

+      1,   0,   0,   2,   0,   8, 

+     15, 128,   0,   0, 228, 128, 

+    255, 255,   0,   0,  83,  72, 

+     68,  82, 160,   0,   0,   0, 

+     64,   0,   0,   0,  40,   0, 

+      0,   0,  90,   0,   0,   3, 

+      0,  96,  16,   0,   0,   0, 

+      0,   0,  88,  24,   0,   4, 

+      0, 112,  16,   0,   0,   0, 

+      0,   0,  85,  85,   0,   0, 

+     98,  16,   0,   3,  50,  16, 

+     16,   0,   1,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0,  69,   0,   0,   9, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+      0,  96,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+     50,  32,  16,   0,   0,   0, 

+      0,   0,  70,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   8, 194,  32,  16,   0, 

+      0,   0,   0,   0,   2,  64, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 128,  63, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  82,  68,  69,  70, 

+    160,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,  28,   0, 

+      0,   0,   0,   4, 255, 255, 

+      0,   1,   0,   0, 109,   0, 

+      0,   0,  92,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 100,   0, 

+      0,   0,   2,   0,   0,   0, 

+      5,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     83,  97, 109, 112, 108, 101, 

+    114,   0,  84, 101, 120, 116, 

+    117, 114, 101,  70,   0,  77, 

+    105,  99, 114, 111, 115, 111, 

+    102, 116,  32,  40,  82,  41, 

+     32,  72,  76,  83,  76,  32, 

+     83, 104,  97, 100, 101, 114, 

+     32,  67, 111, 109, 112, 105, 

+    108, 101, 114,  32,  54,  46, 

+     51,  46,  57,  54,  48,  48, 

+     46,  49,  54,  51,  56,  52, 

+      0, 171,  73,  83,  71,  78, 

+     80,   0,   0,   0,   2,   0, 

+      0,   0,   8,   0,   0,   0, 

+     56,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     68,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0,   3,   3,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171, 171, 171, 

+     79,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  83,  86, 

+     95,  84,  65,  82,  71,  69, 

+     84,   0, 171, 171

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h
new file mode 100644
index 0000000..a66e530
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h
@@ -0,0 +1,167 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI                          texture   sint4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_resource_texture2d (sint,sint,sint,sint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.xy, r0.xyxx

+mov o0.zw, l(0,0,0,0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRG2DI[] =

+{

+     68,  88,  66,  67,  89, 123, 

+    129, 251, 206, 105, 221, 141, 

+      5, 160, 186, 187, 168, 157, 

+    145, 246,   1,   0,   0,   0, 

+    208,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+     84,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     69,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  73,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+     12,   1,   0,   0,  64,   0, 

+      0,   0,  67,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,  50,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   8, 

+    194,  32,  16,   0,   0,   0, 

+      0,   0,   2,  64,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h
new file mode 100644
index 0000000..5146cd9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h
@@ -0,0 +1,167 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI                         texture   uint4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_resource_texture2d (uint,uint,uint,uint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.xy, r0.xyxx

+mov o0.zw, l(0,0,0,0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRG2DUI[] =

+{

+     68,  88,  66,  67, 253, 188, 

+    138, 153, 226, 194, 182, 197, 

+    184,  36, 111,  24, 198, 171, 

+    241, 145,   1,   0,   0,   0, 

+    208,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+     84,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     70,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  85,  73,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+     12,   1,   0,   0,  64,   0, 

+      0,   0,  67,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,  50,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   8, 

+    194,  32,  16,   0,   0,   0, 

+      0,   0,   2,  64,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h
new file mode 100644
index 0000000..a313011
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h
@@ -0,0 +1,162 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture3d (float,float,float,float) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v2.xyzx, t0.xyzw, s0

+mov o0.xy, r0.xyxx

+mov o0.zw, l(0,0,0,1.000000)

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRG3D[] =

+{

+     68,  88,  66,  67, 117, 159, 

+    238,  81,  51, 223, 126,  31, 

+    223, 171, 227,   2, 248,   7, 

+     72,  91,   1,   0,   0,   0, 

+    188,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    220,   0,   0,   0, 100,   1, 

+      0,   0, 152,   1,   0,   0, 

+     64,   2,   0,   0,  82,  68, 

+     69,  70, 160,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    109,   0,   0,   0,  92,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    100,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      8,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0,  83,  97, 109, 112, 

+    108, 101, 114,   0,  84, 101, 

+    120, 116, 117, 114, 101,  70, 

+      0,  77, 105,  99, 114, 111, 

+    115, 111, 102, 116,  32,  40, 

+     82,  41,  32,  72,  76,  83, 

+     76,  32,  83, 104,  97, 100, 

+    101, 114,  32,  67, 111, 109, 

+    112, 105, 108, 101, 114,  32, 

+     54,  46,  51,  46,  57,  54, 

+     48,  48,  46,  49,  54,  51, 

+     56,  52,   0, 171,  73,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0, 118,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0,   7,   7, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  83,  86,  95,  82, 

+     69,  78,  68,  69,  82,  84, 

+     65,  82,  71,  69,  84,  65, 

+     82,  82,  65,  89,  73,  78, 

+     68,  69,  88,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82, 160,   0, 

+      0,   0,  64,   0,   0,   0, 

+     40,   0,   0,   0,  90,   0, 

+      0,   3,   0,  96,  16,   0, 

+      0,   0,   0,   0,  88,  40, 

+      0,   4,   0, 112,  16,   0, 

+      0,   0,   0,   0,  85,  85, 

+      0,   0,  98,  16,   0,   3, 

+    114,  16,  16,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0, 104,   0,   0,   2, 

+      1,   0,   0,   0,  69,   0, 

+      0,   9, 242,   0,  16,   0, 

+      0,   0,   0,   0,  70,  18, 

+     16,   0,   2,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,   0,  96,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   5,  50,  32,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,  32, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    128,  63,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,   4,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h
new file mode 100644
index 0000000..ef6ec17
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h
@@ -0,0 +1,174 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI                          texture   sint4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_resource_texture3d (sint,sint,sint,sint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.xy, r0.xyxx

+mov o0.zw, l(0,0,0,0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRG3DI[] =

+{

+     68,  88,  66,  67,  62, 119, 

+     61,  21,  83,  42,  80, 125, 

+    121, 208, 247,  10, 223,  62, 

+     33,  18,   1,   0,   0,   0, 

+    244,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  60,   1, 

+      0,   0, 112,   1,   0,   0, 

+    120,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     69,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  73,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 118,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   7,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  86, 

+     95,  82,  69,  78,  68,  69, 

+     82,  84,  65,  82,  71,  69, 

+     84,  65,  82,  82,  65,  89, 

+     73,  78,  68,  69,  88,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+      0,   1,   0,   0,  64,   0, 

+      0,   0,  64,   0,   0,   0, 

+     88,  40,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0,  98,  16, 

+      0,   3, 114,  16,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,  50,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   8, 

+    194,  32,  16,   0,   0,   0, 

+      0,   0,   2,  64,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h
new file mode 100644
index 0000000..d1540ce
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h
@@ -0,0 +1,174 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI                         texture   uint4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_resource_texture3d (uint,uint,uint,uint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.xy, r0.xyxx

+mov o0.zw, l(0,0,0,0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRG3DUI[] =

+{

+     68,  88,  66,  67,  37,  56, 

+     43, 206,  81, 137, 125, 191, 

+    216,  50,  86,  76,  61,  78, 

+     25, 246,   1,   0,   0,   0, 

+    244,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  60,   1, 

+      0,   0, 112,   1,   0,   0, 

+    120,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     70,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  85,  73,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+     73,  83,  71,  78, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 118,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   7,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  86, 

+     95,  82,  69,  78,  68,  69, 

+     82,  84,  65,  82,  71,  69, 

+     84,  65,  82,  82,  65,  89, 

+     73,  78,  68,  69,  88,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+      0,   1,   0,   0,  64,   0, 

+      0,   0,  64,   0,   0,   0, 

+     88,  40,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0,  98,  16, 

+      0,   3, 114,  16,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5,  50,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   8, 

+    194,  32,  16,   0,   0,   0, 

+      0,   0,   2,  64,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h
new file mode 100644
index 0000000..0047ef3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h
@@ -0,0 +1,196 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    def c0, 1, 0, 0, 0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mad r0, r0.xyzx, c0.xxxy, c0.yyyx

+    mov oC0, r0

+

+// approximately 3 instruction slots used (1 texture, 2 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+mov o0.xyz, r0.xyzx

+mov o0.w, l(1.000000)

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGB2D[] =

+{

+     68,  88,  66,  67,  51,  90, 

+     49, 167, 211,  79,  20, 215, 

+     57, 227,  70,  56, 132, 117, 

+     66, 156,   1,   0,   0,   0, 

+     28,   3,   0,   0,   6,   0, 

+      0,   0,  56,   0,   0,   0, 

+    208,   0,   0,   0, 108,   1, 

+      0,   0, 232,   1,   0,   0, 

+    144,   2,   0,   0, 232,   2, 

+      0,   0,  65, 111, 110,  57, 

+    144,   0,   0,   0, 144,   0, 

+      0,   0,   0,   2, 255, 255, 

+    104,   0,   0,   0,  40,   0, 

+      0,   0,   0,   0,  40,   0, 

+      0,   0,  40,   0,   0,   0, 

+     40,   0,   1,   0,  36,   0, 

+      0,   0,  40,   0,   0,   0, 

+      0,   0,   1,   2, 255, 255, 

+     81,   0,   0,   5,   0,   0, 

+     15, 160,   0,   0, 128,  63, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     31,   0,   0,   2,   0,   0, 

+      0, 128,   0,   0,   3, 176, 

+     31,   0,   0,   2,   0,   0, 

+      0, 144,   0,   8,  15, 160, 

+     66,   0,   0,   3,   0,   0, 

+     15, 128,   0,   0, 228, 176, 

+      0,   8, 228, 160,   4,   0, 

+      0,   4,   0,   0,  15, 128, 

+      0,   0,  36, 128,   0,   0, 

+     64, 160,   0,   0,  21, 160, 

+      1,   0,   0,   2,   0,   8, 

+     15, 128,   0,   0, 228, 128, 

+    255, 255,   0,   0,  83,  72, 

+     68,  82, 148,   0,   0,   0, 

+     64,   0,   0,   0,  37,   0, 

+      0,   0,  90,   0,   0,   3, 

+      0,  96,  16,   0,   0,   0, 

+      0,   0,  88,  24,   0,   4, 

+      0, 112,  16,   0,   0,   0, 

+      0,   0,  85,  85,   0,   0, 

+     98,  16,   0,   3,  50,  16, 

+     16,   0,   1,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0,  69,   0,   0,   9, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+      0,  96,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+    114,  32,  16,   0,   0,   0, 

+      0,   0,  70,   2,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   5, 130,  32,  16,   0, 

+      0,   0,   0,   0,   1,  64, 

+      0,   0,   0,   0, 128,  63, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  82,  68,  69,  70, 

+    160,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,  28,   0, 

+      0,   0,   0,   4, 255, 255, 

+      0,   1,   0,   0, 109,   0, 

+      0,   0,  92,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 100,   0, 

+      0,   0,   2,   0,   0,   0, 

+      5,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     83,  97, 109, 112, 108, 101, 

+    114,   0,  84, 101, 120, 116, 

+    117, 114, 101,  70,   0,  77, 

+    105,  99, 114, 111, 115, 111, 

+    102, 116,  32,  40,  82,  41, 

+     32,  72,  76,  83,  76,  32, 

+     83, 104,  97, 100, 101, 114, 

+     32,  67, 111, 109, 112, 105, 

+    108, 101, 114,  32,  54,  46, 

+     51,  46,  57,  54,  48,  48, 

+     46,  49,  54,  51,  56,  52, 

+      0, 171,  73,  83,  71,  78, 

+     80,   0,   0,   0,   2,   0, 

+      0,   0,   8,   0,   0,   0, 

+     56,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     68,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0,   3,   3,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171, 171, 171, 

+     79,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  83,  86, 

+     95,  84,  65,  82,  71,  69, 

+     84,   0, 171, 171

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h
new file mode 100644
index 0000000..0f318fd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h
@@ -0,0 +1,165 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI                          texture   sint4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_resource_texture2d (sint,sint,sint,sint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.xyz, r0.xyzx

+mov o0.w, l(0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGB2DI[] =

+{

+     68,  88,  66,  67,  16, 227, 

+    172, 190, 246, 118, 223, 239, 

+    176,  78,  90,  11, 135, 138, 

+    109, 174,   1,   0,   0,   0, 

+    196,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+     72,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     69,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  73,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+      0,   1,   0,   0,  64,   0, 

+      0,   0,  64,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 114,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+    130,  32,  16,   0,   0,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h
new file mode 100644
index 0000000..943f7a2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h
@@ -0,0 +1,165 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI                         texture   uint4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_resource_texture2d (uint,uint,uint,uint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.xyz, r0.xyzx

+mov o0.w, l(0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGB2DUI[] =

+{

+     68,  88,  66,  67, 245, 219, 

+     46,  32,  34,  74,   2,  47, 

+    124,  96, 216,  40, 253, 243, 

+    104, 178,   1,   0,   0,   0, 

+    196,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+     72,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     70,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  85,  73,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+      0,   1,   0,   0,  64,   0, 

+      0,   0,  64,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 114,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+    130,  32,  16,   0,   0,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h
new file mode 100644
index 0000000..528f273
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h
@@ -0,0 +1,160 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture3d (float,float,float,float) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v2.xyzx, t0.xyzw, s0

+mov o0.xyz, r0.xyzx

+mov o0.w, l(1.000000)

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGB3D[] =

+{

+     68,  88,  66,  67,   3, 213, 

+    227, 200, 132, 255,   7,  95, 

+      0, 252,  77,  33, 254, 184, 

+     83, 110,   1,   0,   0,   0, 

+    176,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    220,   0,   0,   0, 100,   1, 

+      0,   0, 152,   1,   0,   0, 

+     52,   2,   0,   0,  82,  68, 

+     69,  70, 160,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    109,   0,   0,   0,  92,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    100,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      8,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0,  83,  97, 109, 112, 

+    108, 101, 114,   0,  84, 101, 

+    120, 116, 117, 114, 101,  70, 

+      0,  77, 105,  99, 114, 111, 

+    115, 111, 102, 116,  32,  40, 

+     82,  41,  32,  72,  76,  83, 

+     76,  32,  83, 104,  97, 100, 

+    101, 114,  32,  67, 111, 109, 

+    112, 105, 108, 101, 114,  32, 

+     54,  46,  51,  46,  57,  54, 

+     48,  48,  46,  49,  54,  51, 

+     56,  52,   0, 171,  73,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0, 118,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0,   7,   7, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  83,  86,  95,  82, 

+     69,  78,  68,  69,  82,  84, 

+     65,  82,  71,  69,  84,  65, 

+     82,  82,  65,  89,  73,  78, 

+     68,  69,  88,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82, 148,   0, 

+      0,   0,  64,   0,   0,   0, 

+     37,   0,   0,   0,  90,   0, 

+      0,   3,   0,  96,  16,   0, 

+      0,   0,   0,   0,  88,  40, 

+      0,   4,   0, 112,  16,   0, 

+      0,   0,   0,   0,  85,  85, 

+      0,   0,  98,  16,   0,   3, 

+    114,  16,  16,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0, 104,   0,   0,   2, 

+      1,   0,   0,   0,  69,   0, 

+      0,   9, 242,   0,  16,   0, 

+      0,   0,   0,   0,  70,  18, 

+     16,   0,   2,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,   0,  96,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   5, 114,  32,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,  32, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+    128,  63,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,   4,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h
new file mode 100644
index 0000000..fa2a639
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h
@@ -0,0 +1,172 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI                          texture   sint4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_resource_texture3d (sint,sint,sint,sint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.xyz, r0.xyzx

+mov o0.w, l(0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGB3DI[] =

+{

+     68,  88,  66,  67, 194, 157, 

+      8, 194, 167, 235,  14, 127, 

+     69, 198,  32,  35, 167,  35, 

+    213, 248,   1,   0,   0,   0, 

+    232,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  60,   1, 

+      0,   0, 112,   1,   0,   0, 

+    108,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     69,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  73,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 118,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   7,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  86, 

+     95,  82,  69,  78,  68,  69, 

+     82,  84,  65,  82,  71,  69, 

+     84,  65,  82,  82,  65,  89, 

+     73,  78,  68,  69,  88,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+    244,   0,   0,   0,  64,   0, 

+      0,   0,  61,   0,   0,   0, 

+     88,  40,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0,  98,  16, 

+      0,   3, 114,  16,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 114,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+    130,  32,  16,   0,   0,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h
new file mode 100644
index 0000000..e90b40d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h
@@ -0,0 +1,172 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI                         texture   uint4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_resource_texture3d (uint,uint,uint,uint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov o0.xyz, r0.xyzx

+mov o0.w, l(0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGB3DUI[] =

+{

+     68,  88,  66,  67, 253, 147, 

+      1, 158,  41,  31, 253, 138, 

+     52, 213, 103,  41, 188, 192, 

+     79, 199,   1,   0,   0,   0, 

+    232,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  60,   1, 

+      0,   0, 112,   1,   0,   0, 

+    108,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     70,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  85,  73,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+     73,  83,  71,  78, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 118,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   7,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  86, 

+     95,  82,  69,  78,  68,  69, 

+     82,  84,  65,  82,  71,  69, 

+     84,  65,  82,  82,  65,  89, 

+     73,  78,  68,  69,  88,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+    244,   0,   0,   0,  64,   0, 

+      0,   0,  61,   0,   0,   0, 

+     88,  40,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0,  98,  16, 

+      0,   3, 114,  16,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 114,  32, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+    130,  32,  16,   0,   0,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   9,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h
new file mode 100644
index 0000000..a4ee9d5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h
@@ -0,0 +1,176 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mov oC0, r0

+

+// approximately 2 instruction slots used (1 texture, 1 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+sample o0.xyzw, v1.xyxx, t0.xyzw, s0

+ret 

+// Approximately 2 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBA2D[] =

+{

+     68,  88,  66,  67, 240, 186, 

+    163, 221, 151,  45, 139,  68, 

+    172, 121,  30, 230, 203, 102, 

+     92,  33,   1,   0,   0,   0, 

+    192,   2,   0,   0,   6,   0, 

+      0,   0,  56,   0,   0,   0, 

+    164,   0,   0,   0,  16,   1, 

+      0,   0, 140,   1,   0,   0, 

+     52,   2,   0,   0, 140,   2, 

+      0,   0,  65, 111, 110,  57, 

+    100,   0,   0,   0, 100,   0, 

+      0,   0,   0,   2, 255, 255, 

+     60,   0,   0,   0,  40,   0, 

+      0,   0,   0,   0,  40,   0, 

+      0,   0,  40,   0,   0,   0, 

+     40,   0,   1,   0,  36,   0, 

+      0,   0,  40,   0,   0,   0, 

+      0,   0,   1,   2, 255, 255, 

+     31,   0,   0,   2,   0,   0, 

+      0, 128,   0,   0,   3, 176, 

+     31,   0,   0,   2,   0,   0, 

+      0, 144,   0,   8,  15, 160, 

+     66,   0,   0,   3,   0,   0, 

+     15, 128,   0,   0, 228, 176, 

+      0,   8, 228, 160,   1,   0, 

+      0,   2,   0,   8,  15, 128, 

+      0,   0, 228, 128, 255, 255, 

+      0,   0,  83,  72,  68,  82, 

+    100,   0,   0,   0,  64,   0, 

+      0,   0,  25,   0,   0,   0, 

+     90,   0,   0,   3,   0,  96, 

+     16,   0,   0,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     85,  85,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0,  69,   0, 

+      0,   9, 242,  32,  16,   0, 

+      0,   0,   0,   0,  70,  16, 

+     16,   0,   1,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,   0,  96,  16,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     82,  68,  69,  70, 160,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,  28,   0,   0,   0, 

+      0,   4, 255, 255,   0,   1, 

+      0,   0, 109,   0,   0,   0, 

+     92,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0, 100,   0,   0,   0, 

+      2,   0,   0,   0,   5,   0, 

+      0,   0,   4,   0,   0,   0, 

+    255, 255, 255, 255,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     13,   0,   0,   0,  83,  97, 

+    109, 112, 108, 101, 114,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  70,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h
new file mode 100644
index 0000000..d87d043
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h
@@ -0,0 +1,157 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI                          texture   sint4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_resource_texture2d (sint,sint,sint,sint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld o0.xyzw, r0.xyzw, t0.xyzw

+ret 

+// Approximately 7 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBA2DI[] =

+{

+     68,  88,  66,  67,  81, 147, 

+    194, 141,  92, 236, 184, 192, 

+     11, 249,  14, 215, 122, 110, 

+     35, 111,   1,   0,   0,   0, 

+    156,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+     32,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     69,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  73,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+    216,   0,   0,   0,  64,   0, 

+      0,   0,  54,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      7,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h
new file mode 100644
index 0000000..dca98d8
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h
@@ -0,0 +1,80 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureF_MS                       texture  float4        2dMS    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCORD                  0   xy          1     NONE   float   xy  

+// SV_SAMPLEINDEX           0   x           2   SAMPLE    uint   x   

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+// Pixel Shader runs at sample frequency

+//

+ps_4_1

+dcl_globalFlags refactoringAllowed

+dcl_resource_texture2dms(0) (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_input_ps_sgv v2.x, sampleIndex

+dcl_output o0.xyzw

+dcl_temps 1

+ftou r0.xy, v1.xyxx

+mov r0.zw, l(0,0,0,0)

+ldms o0.xyzw, r0.xyzw, t0.xyzw, v2.x

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBA2DMS[] = {

+    68,  88,  66,  67,  24,  185, 64,  224, 216, 192, 107, 84,  140, 208, 46, 210, 75,  20,  1,

+    202, 1,   0,   0,   0,   148, 2,   0,   0,   5,   0,   0,   0,   52,  0,  0,   0,   184, 0,

+    0,   0,   52,  1,   0,   0,   104, 1,   0,   0,   24,  2,   0,   0,   82, 68,  69,  70,  124,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,  28,  0,   0,   0,

+    1,   4,   255, 255, 0,   1,   0,   0,   72,  0,   0,   0,   60,  0,   0,  0,   2,   0,   0,

+    0,   5,   0,   0,   0,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   1,   0,

+    0,   0,   13,  0,   0,   0,   84,  101, 120, 116, 117, 114, 101, 70,  95, 77,  83,  0,   77,

+    105, 99,  114, 111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76, 83,  76,  32,  83,

+    104, 97,  100, 101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32, 54,  46,  51,  46,

+    57,  54,  48,  48,  46,  49,  54,  51,  56,  52,  0,   171, 171, 73,  83, 71,  78,  116, 0,

+    0,   0,   3,   0,   0,   0,   8,   0,   0,   0,   80,  0,   0,   0,   0,  0,   0,   0,   1,

+    0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,   15,  0,   0,   0,  92,  0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   0,   1,   0,   0,  0,   3,   3,   0,

+    0,   100, 0,   0,   0,   0,   0,   0,   0,   10,  0,   0,   0,   1,   0,  0,   0,   2,   0,

+    0,   0,   1,   1,   0,   0,   83,  86,  95,  80,  79,  83,  73,  84,  73, 79,  78,  0,   84,

+    69,  88,  67,  79,  82,  68,  0,   83,  86,  95,  83,  65,  77,  80,  76, 69,  73,  78,  68,

+    69,  88,  0,   171, 79,  83,  71,  78,  44,  0,   0,   0,   1,   0,   0,  0,   8,   0,   0,

+    0,   32,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   0,  0,   0,   0,   0,

+    0,   0,   15,  0,   0,   0,   83,  86,  95,  84,  65,  82,  71,  69,  84, 0,   171, 171, 83,

+    72,  68,  82,  168, 0,   0,   0,   65,  0,   0,   0,   42,  0,   0,   0,  106, 8,   0,   1,

+    88,  32,  0,   4,   0,   112, 16,  0,   0,   0,   0,   0,   85,  85,  0,  0,   98,  16,  0,

+    3,   50,  16,  16,  0,   1,   0,   0,   0,   99,  8,   0,   4,   18,  16, 16,  0,   2,   0,

+    0,   0,   10,  0,   0,   0,   101, 0,   0,   3,   242, 32,  16,  0,   0,  0,   0,   0,   104,

+    0,   0,   2,   1,   0,   0,   0,   28,  0,   0,   5,   50,  0,   16,  0,  0,   0,   0,   0,

+    70,  16,  16,  0,   1,   0,   0,   0,   54,  0,   0,   8,   194, 0,   16, 0,   0,   0,   0,

+    0,   2,   64,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,

+    0,   0,   46,  0,   0,   9,   242, 32,  16,  0,   0,   0,   0,   0,   70, 14,  16,  0,   0,

+    0,   0,   0,   70,  126, 16,  0,   0,   0,   0,   0,   10,  16,  16,  0,  2,   0,   0,   0,

+    62,  0,   0,   1,   83,  84,  65,  84,  116, 0,   0,   0,   4,   0,   0,  0,   1,   0,   0,

+    0,   0,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,

+    0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  1,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,  0,   0,   0,   0,

+    0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h
new file mode 100644
index 0000000..35cff53
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h
@@ -0,0 +1,157 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI                         texture   uint4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_resource_texture2d (uint,uint,uint,uint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld o0.xyzw, r0.xyzw, t0.xyzw

+ret 

+// Approximately 7 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBA2DUI[] =

+{

+     68,  88,  66,  67, 128, 252, 

+    255, 238,  68, 109,  10, 133, 

+    175, 163, 216, 152, 219, 103, 

+    163, 223,   1,   0,   0,   0, 

+    156,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  12,   1, 

+      0,   0,  64,   1,   0,   0, 

+     32,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     70,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  85,  73,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+     73,  83,  71,  78,  80,   0, 

+      0,   0,   2,   0,   0,   0, 

+      8,   0,   0,   0,  56,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  68,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171, 171, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+    216,   0,   0,   0,  64,   0, 

+      0,   0,  54,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      7,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h
new file mode 100644
index 0000000..ac4cbea
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h
@@ -0,0 +1,149 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture3d (float,float,float,float) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+sample o0.xyzw, v2.xyzx, t0.xyzw, s0

+ret 

+// Approximately 2 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBA3D[] =

+{

+     68,  88,  66,  67, 246,  41, 

+     15, 240, 168, 172,  91, 145, 

+    236, 221, 187,  89,  12,   0, 

+     93, 149,   1,   0,   0,   0, 

+    128,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    220,   0,   0,   0, 100,   1, 

+      0,   0, 152,   1,   0,   0, 

+      4,   2,   0,   0,  82,  68, 

+     69,  70, 160,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    109,   0,   0,   0,  92,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    100,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      8,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0,  83,  97, 109, 112, 

+    108, 101, 114,   0,  84, 101, 

+    120, 116, 117, 114, 101,  70, 

+      0,  77, 105,  99, 114, 111, 

+    115, 111, 102, 116,  32,  40, 

+     82,  41,  32,  72,  76,  83, 

+     76,  32,  83, 104,  97, 100, 

+    101, 114,  32,  67, 111, 109, 

+    112, 105, 108, 101, 114,  32, 

+     54,  46,  51,  46,  57,  54, 

+     48,  48,  46,  49,  54,  51, 

+     56,  52,   0, 171,  73,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0, 118,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0,   7,   7, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  83,  86,  95,  82, 

+     69,  78,  68,  69,  82,  84, 

+     65,  82,  71,  69,  84,  65, 

+     82,  82,  65,  89,  73,  78, 

+     68,  69,  88,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82, 100,   0, 

+      0,   0,  64,   0,   0,   0, 

+     25,   0,   0,   0,  90,   0, 

+      0,   3,   0,  96,  16,   0, 

+      0,   0,   0,   0,  88,  40, 

+      0,   4,   0, 112,  16,   0, 

+      0,   0,   0,   0,  85,  85, 

+      0,   0,  98,  16,   0,   3, 

+    114,  16,  16,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0,  69,   0,   0,   9, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+      0,  96,  16,   0,   0,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h
new file mode 100644
index 0000000..1921c9f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h
@@ -0,0 +1,164 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI                          texture   sint4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_resource_texture3d (sint,sint,sint,sint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld o0.xyzw, r0.xyzw, t0.xyzw

+ret 

+// Approximately 7 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBA3DI[] =

+{

+     68,  88,  66,  67, 139, 158, 

+      6, 251, 163, 134,   3, 183, 

+      5, 227, 185, 108,  35,  91, 

+     67, 191,   1,   0,   0,   0, 

+    192,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  60,   1, 

+      0,   0, 112,   1,   0,   0, 

+     68,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     69,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  73,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+     73,  83,  71,  78, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 118,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   7,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  86, 

+     95,  82,  69,  78,  68,  69, 

+     82,  84,  65,  82,  71,  69, 

+     84,  65,  82,  82,  65,  89, 

+     73,  78,  68,  69,  88,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+    204,   0,   0,   0,  64,   0, 

+      0,   0,  51,   0,   0,   0, 

+     88,  40,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0,  98,  16, 

+      0,   3, 114,  16,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      7,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h
new file mode 100644
index 0000000..cba1502
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h
@@ -0,0 +1,164 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI                         texture   uint4          3d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_resource_texture3d (uint,uint,uint,uint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld o0.xyzw, r0.xyzw, t0.xyzw

+ret 

+// Approximately 7 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBA3DUI[] =

+{

+     68,  88,  66,  67,  16, 111, 

+     56, 218, 148, 233, 100, 164, 

+      0, 199,  73, 155, 213, 171, 

+     78,  18,   1,   0,   0,   0, 

+    192,   2,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    180,   0,   0,   0,  60,   1, 

+      0,   0, 112,   1,   0,   0, 

+     68,   2,   0,   0,  82,  68, 

+     69,  70, 120,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+     70,   0,   0,   0,  60,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  85,  73,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+     73,  83,  71,  78, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0, 118,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   7,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  86, 

+     95,  82,  69,  78,  68,  69, 

+     82,  84,  65,  82,  71,  69, 

+     84,  65,  82,  82,  65,  89, 

+     73,  78,  68,  69,  88,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+    204,   0,   0,   0,  64,   0, 

+      0,   0,  51,   0,   0,   0, 

+     88,  40,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0,  98,  16, 

+      0,   3, 114,  16,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     62,   0,   0,   1,  83,  84, 

+     65,  84, 116,   0,   0,   0, 

+      7,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h
new file mode 100644
index 0000000..3ce18ee
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h
@@ -0,0 +1,101 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mul r0.xyz, r0.w, r0

+    mov oC0, r0

+

+// approximately 3 instruction slots used (1 texture, 2 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+mul o0.xyz, r0.wwww, r0.xyzx

+mov o0.w, r0.w

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBAPremultiply2D[] = {

+    68,  88,  66,  67,  139, 254, 84,  241, 202, 33,  132, 221, 123, 19,  241, 182, 75,  155, 177,

+    115, 1,   0,   0,   0,   8,   3,   0,   0,   6,   0,   0,   0,   56,  0,   0,   0,   180, 0,

+    0,   0,   88,  1,   0,   0,   212, 1,   0,   0,   124, 2,   0,   0,   212, 2,   0,   0,   65,

+    111, 110, 57,  116, 0,   0,   0,   116, 0,   0,   0,   0,   2,   255, 255, 76,  0,   0,   0,

+    40,  0,   0,   0,   0,   0,   40,  0,   0,   0,   40,  0,   0,   0,   40,  0,   1,   0,   36,

+    0,   0,   0,   40,  0,   0,   0,   0,   0,   1,   2,   255, 255, 31,  0,   0,   2,   0,   0,

+    0,   128, 0,   0,   3,   176, 31,  0,   0,   2,   0,   0,   0,   144, 0,   8,   15,  160, 66,

+    0,   0,   3,   0,   0,   15,  128, 0,   0,   228, 176, 0,   8,   228, 160, 5,   0,   0,   3,

+    0,   0,   7,   128, 0,   0,   255, 128, 0,   0,   228, 128, 1,   0,   0,   2,   0,   8,   15,

+    128, 0,   0,   228, 128, 255, 255, 0,   0,   83,  72,  68,  82,  156, 0,   0,   0,   64,  0,

+    0,   0,   39,  0,   0,   0,   90,  0,   0,   3,   0,   96,  16,  0,   0,   0,   0,   0,   88,

+    24,  0,   4,   0,   112, 16,  0,   0,   0,   0,   0,   85,  85,  0,   0,   98,  16,  0,   3,

+    50,  16,  16,  0,   1,   0,   0,   0,   101, 0,   0,   3,   242, 32,  16,  0,   0,   0,   0,

+    0,   104, 0,   0,   2,   1,   0,   0,   0,   69,  0,   0,   9,   242, 0,   16,  0,   0,   0,

+    0,   0,   70,  16,  16,  0,   1,   0,   0,   0,   70,  126, 16,  0,   0,   0,   0,   0,   0,

+    96,  16,  0,   0,   0,   0,   0,   56,  0,   0,   7,   114, 32,  16,  0,   0,   0,   0,   0,

+    246, 15,  16,  0,   0,   0,   0,   0,   70,  2,   16,  0,   0,   0,   0,   0,   54,  0,   0,

+    5,   130, 32,  16,  0,   0,   0,   0,   0,   58,  0,   16,  0,   0,   0,   0,   0,   62,  0,

+    0,   1,   83,  84,  65,  84,  116, 0,   0,   0,   4,   0,   0,   0,   1,   0,   0,   0,   0,

+    0,   0,   0,   2,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   82,  68,  69,  70,  160, 0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   28,  0,   0,   0,   0,   4,

+    255, 255, 0,   1,   0,   0,   109, 0,   0,   0,   92,  0,   0,   0,   3,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,

+    1,   0,   0,   0,   100, 0,   0,   0,   2,   0,   0,   0,   5,   0,   0,   0,   4,   0,   0,

+    0,   255, 255, 255, 255, 0,   0,   0,   0,   1,   0,   0,   0,   13,  0,   0,   0,   83,  97,

+    109, 112, 108, 101, 114, 0,   84,  101, 120, 116, 117, 114, 101, 70,  0,   77,  105, 99,  114,

+    111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,  83,  76,  32,  83,  104, 97,  100,

+    101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,  54,  46,  51,  46,  57,  54,  48,

+    48,  46,  49,  54,  51,  56,  52,  0,   171, 73,  83,  71,  78,  80,  0,   0,   0,   2,   0,

+    0,   0,   8,   0,   0,   0,   56,  0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   3,

+    0,   0,   0,   0,   0,   0,   0,   15,  0,   0,   0,   68,  0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   3,   3,   0,   0,   83,  86,  95,

+    80,  79,  83,  73,  84,  73,  79,  78,  0,   84,  69,  88,  67,  79,  79,  82,  68,  0,   171,

+    171, 171, 79,  83,  71,  78,  44,  0,   0,   0,   1,   0,   0,   0,   8,   0,   0,   0,   32,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,

+    15,  0,   0,   0,   83,  86,  95,  84,  65,  82,  71,  69,  84,  0,   171, 171};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h
new file mode 100644
index 0000000..c1354f7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h
@@ -0,0 +1,110 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    rcp r1.w, r0.w

+    mul r1.xyz, r0, r1.w

+    cmp r0.xyz, -r0.w, r0, r1

+    mov oC0, r0

+

+// approximately 5 instruction slots used (1 texture, 4 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 2

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+lt r1.x, l(0.000000), r0.w

+div r1.yzw, r0.xxyz, r0.wwww

+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx

+mov o0.w, r0.w

+ret 

+// Approximately 6 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBAUnmultiply2D[] = {

+    68,  88,  66,  67,  180, 87,  43,  111, 255, 135, 28,  224, 42,  85,  197, 16,  17,  172, 176,

+    70,  1,   0,   0,   0,   104, 3,   0,   0,   6,   0,   0,   0,   56,  0,   0,   0,   212, 0,

+    0,   0,   184, 1,   0,   0,   52,  2,   0,   0,   220, 2,   0,   0,   52,  3,   0,   0,   65,

+    111, 110, 57,  148, 0,   0,   0,   148, 0,   0,   0,   0,   2,   255, 255, 108, 0,   0,   0,

+    40,  0,   0,   0,   0,   0,   40,  0,   0,   0,   40,  0,   0,   0,   40,  0,   1,   0,   36,

+    0,   0,   0,   40,  0,   0,   0,   0,   0,   1,   2,   255, 255, 31,  0,   0,   2,   0,   0,

+    0,   128, 0,   0,   3,   176, 31,  0,   0,   2,   0,   0,   0,   144, 0,   8,   15,  160, 66,

+    0,   0,   3,   0,   0,   15,  128, 0,   0,   228, 176, 0,   8,   228, 160, 6,   0,   0,   2,

+    1,   0,   8,   128, 0,   0,   255, 128, 5,   0,   0,   3,   1,   0,   7,   128, 0,   0,   228,

+    128, 1,   0,   255, 128, 88,  0,   0,   4,   0,   0,   7,   128, 0,   0,   255, 129, 0,   0,

+    228, 128, 1,   0,   228, 128, 1,   0,   0,   2,   0,   8,   15,  128, 0,   0,   228, 128, 255,

+    255, 0,   0,   83,  72,  68,  82,  220, 0,   0,   0,   64,  0,   0,   0,   55,  0,   0,   0,

+    90,  0,   0,   3,   0,   96,  16,  0,   0,   0,   0,   0,   88,  24,  0,   4,   0,   112, 16,

+    0,   0,   0,   0,   0,   85,  85,  0,   0,   98,  16,  0,   3,   50,  16,  16,  0,   1,   0,

+    0,   0,   101, 0,   0,   3,   242, 32,  16,  0,   0,   0,   0,   0,   104, 0,   0,   2,   2,

+    0,   0,   0,   69,  0,   0,   9,   242, 0,   16,  0,   0,   0,   0,   0,   70,  16,  16,  0,

+    1,   0,   0,   0,   70,  126, 16,  0,   0,   0,   0,   0,   0,   96,  16,  0,   0,   0,   0,

+    0,   49,  0,   0,   7,   18,  0,   16,  0,   1,   0,   0,   0,   1,   64,  0,   0,   0,   0,

+    0,   0,   58,  0,   16,  0,   0,   0,   0,   0,   14,  0,   0,   7,   226, 0,   16,  0,   1,

+    0,   0,   0,   6,   9,   16,  0,   0,   0,   0,   0,   246, 15,  16,  0,   0,   0,   0,   0,

+    55,  0,   0,   9,   114, 32,  16,  0,   0,   0,   0,   0,   6,   0,   16,  0,   1,   0,   0,

+    0,   150, 7,   16,  0,   1,   0,   0,   0,   70,  2,   16,  0,   0,   0,   0,   0,   54,  0,

+    0,   5,   130, 32,  16,  0,   0,   0,   0,   0,   58,  0,   16,  0,   0,   0,   0,   0,   62,

+    0,   0,   1,   83,  84,  65,  84,  116, 0,   0,   0,   6,   0,   0,   0,   2,   0,   0,   0,

+    0,   0,   0,   0,   2,   0,   0,   0,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   1,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   82,  68,  69,  70,  160, 0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   28,  0,   0,   0,   0,

+    4,   255, 255, 0,   1,   0,   0,   109, 0,   0,   0,   92,  0,   0,   0,   3,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,

+    0,   1,   0,   0,   0,   100, 0,   0,   0,   2,   0,   0,   0,   5,   0,   0,   0,   4,   0,

+    0,   0,   255, 255, 255, 255, 0,   0,   0,   0,   1,   0,   0,   0,   13,  0,   0,   0,   83,

+    97,  109, 112, 108, 101, 114, 0,   84,  101, 120, 116, 117, 114, 101, 70,  0,   77,  105, 99,

+    114, 111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,  83,  76,  32,  83,  104, 97,

+    100, 101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,  54,  46,  51,  46,  57,  54,

+    48,  48,  46,  49,  54,  51,  56,  52,  0,   171, 73,  83,  71,  78,  80,  0,   0,   0,   2,

+    0,   0,   0,   8,   0,   0,   0,   56,  0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,

+    3,   0,   0,   0,   0,   0,   0,   0,   15,  0,   0,   0,   68,  0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   3,   3,   0,   0,   83,  86,

+    95,  80,  79,  83,  73,  84,  73,  79,  78,  0,   84,  69,  88,  67,  79,  79,  82,  68,  0,

+    171, 171, 171, 79,  83,  71,  78,  44,  0,   0,   0,   1,   0,   0,   0,   8,   0,   0,   0,

+    32,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,

+    0,   15,  0,   0,   0,   83,  86,  95,  84,  65,  82,  71,  69,  84,  0,   171, 171};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h
new file mode 100644
index 0000000..c88a141
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h
@@ -0,0 +1,101 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mul r0.xyz, r0.w, r0

+    mov oC0, r0

+

+// approximately 3 instruction slots used (1 texture, 2 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+mul o0.xyz, r0.wwww, r0.xyzx

+mov o0.w, r0.w

+ret 

+// Approximately 4 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBPremultiply2D[] = {

+    68,  88,  66,  67,  139, 254, 84,  241, 202, 33,  132, 221, 123, 19,  241, 182, 75,  155, 177,

+    115, 1,   0,   0,   0,   8,   3,   0,   0,   6,   0,   0,   0,   56,  0,   0,   0,   180, 0,

+    0,   0,   88,  1,   0,   0,   212, 1,   0,   0,   124, 2,   0,   0,   212, 2,   0,   0,   65,

+    111, 110, 57,  116, 0,   0,   0,   116, 0,   0,   0,   0,   2,   255, 255, 76,  0,   0,   0,

+    40,  0,   0,   0,   0,   0,   40,  0,   0,   0,   40,  0,   0,   0,   40,  0,   1,   0,   36,

+    0,   0,   0,   40,  0,   0,   0,   0,   0,   1,   2,   255, 255, 31,  0,   0,   2,   0,   0,

+    0,   128, 0,   0,   3,   176, 31,  0,   0,   2,   0,   0,   0,   144, 0,   8,   15,  160, 66,

+    0,   0,   3,   0,   0,   15,  128, 0,   0,   228, 176, 0,   8,   228, 160, 5,   0,   0,   3,

+    0,   0,   7,   128, 0,   0,   255, 128, 0,   0,   228, 128, 1,   0,   0,   2,   0,   8,   15,

+    128, 0,   0,   228, 128, 255, 255, 0,   0,   83,  72,  68,  82,  156, 0,   0,   0,   64,  0,

+    0,   0,   39,  0,   0,   0,   90,  0,   0,   3,   0,   96,  16,  0,   0,   0,   0,   0,   88,

+    24,  0,   4,   0,   112, 16,  0,   0,   0,   0,   0,   85,  85,  0,   0,   98,  16,  0,   3,

+    50,  16,  16,  0,   1,   0,   0,   0,   101, 0,   0,   3,   242, 32,  16,  0,   0,   0,   0,

+    0,   104, 0,   0,   2,   1,   0,   0,   0,   69,  0,   0,   9,   242, 0,   16,  0,   0,   0,

+    0,   0,   70,  16,  16,  0,   1,   0,   0,   0,   70,  126, 16,  0,   0,   0,   0,   0,   0,

+    96,  16,  0,   0,   0,   0,   0,   56,  0,   0,   7,   114, 32,  16,  0,   0,   0,   0,   0,

+    246, 15,  16,  0,   0,   0,   0,   0,   70,  2,   16,  0,   0,   0,   0,   0,   54,  0,   0,

+    5,   130, 32,  16,  0,   0,   0,   0,   0,   58,  0,   16,  0,   0,   0,   0,   0,   62,  0,

+    0,   1,   83,  84,  65,  84,  116, 0,   0,   0,   4,   0,   0,   0,   1,   0,   0,   0,   0,

+    0,   0,   0,   2,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   82,  68,  69,  70,  160, 0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   28,  0,   0,   0,   0,   4,

+    255, 255, 0,   1,   0,   0,   109, 0,   0,   0,   92,  0,   0,   0,   3,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,

+    1,   0,   0,   0,   100, 0,   0,   0,   2,   0,   0,   0,   5,   0,   0,   0,   4,   0,   0,

+    0,   255, 255, 255, 255, 0,   0,   0,   0,   1,   0,   0,   0,   13,  0,   0,   0,   83,  97,

+    109, 112, 108, 101, 114, 0,   84,  101, 120, 116, 117, 114, 101, 70,  0,   77,  105, 99,  114,

+    111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,  83,  76,  32,  83,  104, 97,  100,

+    101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,  54,  46,  51,  46,  57,  54,  48,

+    48,  46,  49,  54,  51,  56,  52,  0,   171, 73,  83,  71,  78,  80,  0,   0,   0,   2,   0,

+    0,   0,   8,   0,   0,   0,   56,  0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   3,

+    0,   0,   0,   0,   0,   0,   0,   15,  0,   0,   0,   68,  0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   3,   3,   0,   0,   83,  86,  95,

+    80,  79,  83,  73,  84,  73,  79,  78,  0,   84,  69,  88,  67,  79,  79,  82,  68,  0,   171,

+    171, 171, 79,  83,  71,  78,  44,  0,   0,   0,   1,   0,   0,   0,   8,   0,   0,   0,   32,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,

+    15,  0,   0,   0,   83,  86,  95,  84,  65,  82,  71,  69,  84,  0,   171, 171};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h
new file mode 100644
index 0000000..9dd3c02
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h
@@ -0,0 +1,110 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF                          texture  float4          2d    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+//

+// Sampler/Resource to DX9 shader sampler mappings:

+//

+// Target Sampler Source Sampler  Source Resource

+// -------------- --------------- ----------------

+// s0             s0              t0               

+//

+//

+// Level9 shader bytecode:

+//

+    ps_2_x

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    rcp r1.w, r0.w

+    mul r1.xyz, r0, r1.w

+    cmp r0.xyz, -r0.w, r0, r1

+    mov oC0, r0

+

+// approximately 5 instruction slots used (1 texture, 4 arithmetic)

+ps_4_0

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 2

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+lt r1.x, l(0.000000), r0.w

+div r1.yzw, r0.xxyz, r0.wwww

+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx

+mov o0.w, r0.w

+ret 

+// Approximately 6 instruction slots used

+#endif

+

+const BYTE g_PS_PassthroughRGBUnmultiply2D[] = {

+    68,  88,  66,  67,  180, 87,  43,  111, 255, 135, 28,  224, 42,  85,  197, 16,  17,  172, 176,

+    70,  1,   0,   0,   0,   104, 3,   0,   0,   6,   0,   0,   0,   56,  0,   0,   0,   212, 0,

+    0,   0,   184, 1,   0,   0,   52,  2,   0,   0,   220, 2,   0,   0,   52,  3,   0,   0,   65,

+    111, 110, 57,  148, 0,   0,   0,   148, 0,   0,   0,   0,   2,   255, 255, 108, 0,   0,   0,

+    40,  0,   0,   0,   0,   0,   40,  0,   0,   0,   40,  0,   0,   0,   40,  0,   1,   0,   36,

+    0,   0,   0,   40,  0,   0,   0,   0,   0,   1,   2,   255, 255, 31,  0,   0,   2,   0,   0,

+    0,   128, 0,   0,   3,   176, 31,  0,   0,   2,   0,   0,   0,   144, 0,   8,   15,  160, 66,

+    0,   0,   3,   0,   0,   15,  128, 0,   0,   228, 176, 0,   8,   228, 160, 6,   0,   0,   2,

+    1,   0,   8,   128, 0,   0,   255, 128, 5,   0,   0,   3,   1,   0,   7,   128, 0,   0,   228,

+    128, 1,   0,   255, 128, 88,  0,   0,   4,   0,   0,   7,   128, 0,   0,   255, 129, 0,   0,

+    228, 128, 1,   0,   228, 128, 1,   0,   0,   2,   0,   8,   15,  128, 0,   0,   228, 128, 255,

+    255, 0,   0,   83,  72,  68,  82,  220, 0,   0,   0,   64,  0,   0,   0,   55,  0,   0,   0,

+    90,  0,   0,   3,   0,   96,  16,  0,   0,   0,   0,   0,   88,  24,  0,   4,   0,   112, 16,

+    0,   0,   0,   0,   0,   85,  85,  0,   0,   98,  16,  0,   3,   50,  16,  16,  0,   1,   0,

+    0,   0,   101, 0,   0,   3,   242, 32,  16,  0,   0,   0,   0,   0,   104, 0,   0,   2,   2,

+    0,   0,   0,   69,  0,   0,   9,   242, 0,   16,  0,   0,   0,   0,   0,   70,  16,  16,  0,

+    1,   0,   0,   0,   70,  126, 16,  0,   0,   0,   0,   0,   0,   96,  16,  0,   0,   0,   0,

+    0,   49,  0,   0,   7,   18,  0,   16,  0,   1,   0,   0,   0,   1,   64,  0,   0,   0,   0,

+    0,   0,   58,  0,   16,  0,   0,   0,   0,   0,   14,  0,   0,   7,   226, 0,   16,  0,   1,

+    0,   0,   0,   6,   9,   16,  0,   0,   0,   0,   0,   246, 15,  16,  0,   0,   0,   0,   0,

+    55,  0,   0,   9,   114, 32,  16,  0,   0,   0,   0,   0,   6,   0,   16,  0,   1,   0,   0,

+    0,   150, 7,   16,  0,   1,   0,   0,   0,   70,  2,   16,  0,   0,   0,   0,   0,   54,  0,

+    0,   5,   130, 32,  16,  0,   0,   0,   0,   0,   58,  0,   16,  0,   0,   0,   0,   0,   62,

+    0,   0,   1,   83,  84,  65,  84,  116, 0,   0,   0,   6,   0,   0,   0,   2,   0,   0,   0,

+    0,   0,   0,   0,   2,   0,   0,   0,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   1,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   82,  68,  69,  70,  160, 0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   28,  0,   0,   0,   0,

+    4,   255, 255, 0,   1,   0,   0,   109, 0,   0,   0,   92,  0,   0,   0,   3,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,

+    0,   1,   0,   0,   0,   100, 0,   0,   0,   2,   0,   0,   0,   5,   0,   0,   0,   4,   0,

+    0,   0,   255, 255, 255, 255, 0,   0,   0,   0,   1,   0,   0,   0,   13,  0,   0,   0,   83,

+    97,  109, 112, 108, 101, 114, 0,   84,  101, 120, 116, 117, 114, 101, 70,  0,   77,  105, 99,

+    114, 111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,  83,  76,  32,  83,  104, 97,

+    100, 101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,  54,  46,  51,  46,  57,  54,

+    48,  48,  46,  49,  54,  51,  56,  52,  0,   171, 73,  83,  71,  78,  80,  0,   0,   0,   2,

+    0,   0,   0,   8,   0,   0,   0,   56,  0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,

+    3,   0,   0,   0,   0,   0,   0,   0,   15,  0,   0,   0,   68,  0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   3,   3,   0,   0,   83,  86,

+    95,  80,  79,  83,  73,  84,  73,  79,  78,  0,   84,  69,  88,  67,  79,  79,  82,  68,  0,

+    171, 171, 171, 79,  83,  71,  78,  44,  0,   0,   0,   1,   0,   0,   0,   8,   0,   0,   0,

+    32,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,

+    0,   15,  0,   0,   0,   83,  86,  95,  84,  65,  82,  71,  69,  84,  0,   171, 171};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h
new file mode 100644
index 0000000..0616311
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h
@@ -0,0 +1,82 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Depth                             texture   float        2dMS    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Depth                 0    N/A   oDepth    DEPTH   float    YES

+//

+ps_4_1

+dcl_globalFlags refactoringAllowed

+dcl_resource_texture2dms(0) (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output oDepth

+dcl_temps 1

+resinfo_uint r0.xy, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftou r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ldms r0.x, r0.xyzw, t0.xyzw, l(0)

+mov oDepth, r0.x

+ret 

+// Approximately 8 instruction slots used

+#endif

+

+const BYTE g_PS_ResolveDepth[] = {

+    68,  88,  66,  67,  106, 43,  8,   187, 21,  3,   136, 11,  227, 249, 190, 191, 97,  127, 18,

+    212, 1,   0,   0,   0,   176, 2,   0,   0,   5,   0,   0,   0,   52,  0,   0,   0,   176, 0,

+    0,   0,   8,   1,   0,   0,   60,  1,   0,   0,   52,  2,   0,   0,   82,  68,  69,  70,  116,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   28,  0,   0,   0,

+    1,   4,   255, 255, 0,   1,   0,   0,   66,  0,   0,   0,   60,  0,   0,   0,   2,   0,   0,

+    0,   5,   0,   0,   0,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,

+    0,   0,   1,   0,   0,   0,   68,  101, 112, 116, 104, 0,   77,  105, 99,  114, 111, 115, 111,

+    102, 116, 32,  40,  82,  41,  32,  72,  76,  83,  76,  32,  83,  104, 97,  100, 101, 114, 32,

+    67,  111, 109, 112, 105, 108, 101, 114, 32,  54,  46,  51,  46,  57,  54,  48,  48,  46,  49,

+    54,  51,  56,  52,  0,   73,  83,  71,  78,  80,  0,   0,   0,   2,   0,   0,   0,   8,   0,

+    0,   0,   56,  0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   3,   0,   0,   0,   0,

+    0,   0,   0,   15,  0,   0,   0,   68,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    3,   0,   0,   0,   1,   0,   0,   0,   3,   3,   0,   0,   83,  86,  95,  80,  111, 115, 105,

+    116, 105, 111, 110, 0,   84,  69,  88,  67,  79,  79,  82,  68,  0,   171, 171, 171, 79,  83,

+    71,  78,  44,  0,   0,   0,   1,   0,   0,   0,   8,   0,   0,   0,   32,  0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   0,   255, 255, 255, 255, 1,   14,  0,   0,

+    83,  86,  95,  68,  101, 112, 116, 104, 0,   171, 171, 171, 83,  72,  68,  82,  240, 0,   0,

+    0,   65,  0,   0,   0,   60,  0,   0,   0,   106, 8,   0,   1,   88,  32,  0,   4,   0,   112,

+    16,  0,   0,   0,   0,   0,   85,  85,  0,   0,   98,  16,  0,   3,   50,  16,  16,  0,   1,

+    0,   0,   0,   101, 0,   0,   2,   1,   192, 0,   0,   104, 0,   0,   2,   1,   0,   0,   0,

+    61,  16,  0,   7,   50,  0,   16,  0,   0,   0,   0,   0,   1,   64,  0,   0,   0,   0,   0,

+    0,   70,  126, 16,  0,   0,   0,   0,   0,   86,  0,   0,   5,   50,  0,   16,  0,   0,   0,

+    0,   0,   70,  0,   16,  0,   0,   0,   0,   0,   56,  0,   0,   7,   50,  0,   16,  0,   0,

+    0,   0,   0,   70,  0,   16,  0,   0,   0,   0,   0,   70,  16,  16,  0,   1,   0,   0,   0,

+    28,  0,   0,   5,   50,  0,   16,  0,   0,   0,   0,   0,   70,  0,   16,  0,   0,   0,   0,

+    0,   54,  0,   0,   8,   194, 0,   16,  0,   0,   0,   0,   0,   2,   64,  0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   46,  0,   0,   9,   18,

+    0,   16,  0,   0,   0,   0,   0,   70,  14,  16,  0,   0,   0,   0,   0,   70,  126, 16,  0,

+    0,   0,   0,   0,   1,   64,  0,   0,   0,   0,   0,   0,   54,  0,   0,   4,   1,   192, 0,

+    0,   10,  0,   16,  0,   0,   0,   0,   0,   62,  0,   0,   1,   83,  84,  65,  84,  116, 0,

+    0,   0,   8,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   1,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   2,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h
new file mode 100644
index 0000000..58834eb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h
@@ -0,0 +1,92 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Depth                             texture   float        2dMS    0        1

+// Stencil                           texture   uint2        2dMS    1        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Target                0   xy          0   TARGET   float   xy  

+//

+ps_4_1

+dcl_globalFlags refactoringAllowed

+dcl_resource_texture2dms(0) (float,float,float,float) t0

+dcl_resource_texture2dms(0) (uint,uint,uint,uint) t1

+dcl_input_ps linear v1.xy

+dcl_output o0.xy

+dcl_temps 1

+resinfo_uint r0.xy, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftou r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ldms r0.z, r0.xyzw, t1.xzyw, l(0)

+ldms r0.x, r0.xyww, t0.xyzw, l(0)

+mov o0.x, r0.x

+utof o0.y, r0.z

+ret 

+// Approximately 10 instruction slots used

+#endif

+

+const BYTE g_PS_ResolveDepthStencil[] = {

+    68,  88,  66,  67,  229, 191, 254, 12,  10,  19,  181, 162, 222, 203, 244, 146, 104, 226, 195,

+    177, 1,   0,   0,   0,   40,  3,   0,   0,   5,   0,   0,   0,   52,  0,   0,   0,   216, 0,

+    0,   0,   48,  1,   0,   0,   100, 1,   0,   0,   172, 2,   0,   0,   82,  68,  69,  70,  156,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   28,  0,   0,   0,

+    1,   4,   255, 255, 0,   1,   0,   0,   106, 0,   0,   0,   92,  0,   0,   0,   2,   0,   0,

+    0,   5,   0,   0,   0,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,

+    0,   0,   1,   0,   0,   0,   98,  0,   0,   0,   2,   0,   0,   0,   4,   0,   0,   0,   6,

+    0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   1,   0,   0,   0,   5,   0,   0,   0,

+    68,  101, 112, 116, 104, 0,   83,  116, 101, 110, 99,  105, 108, 0,   77,  105, 99,  114, 111,

+    115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,  83,  76,  32,  83,  104, 97,  100, 101,

+    114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,  54,  46,  51,  46,  57,  54,  48,  48,

+    46,  49,  54,  51,  56,  52,  0,   73,  83,  71,  78,  80,  0,   0,   0,   2,   0,   0,   0,

+    8,   0,   0,   0,   56,  0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   3,   0,   0,

+    0,   0,   0,   0,   0,   15,  0,   0,   0,   68,  0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   3,   3,   0,   0,   83,  86,  95,  80,  111,

+    115, 105, 116, 105, 111, 110, 0,   84,  69,  88,  67,  79,  79,  82,  68,  0,   171, 171, 171,

+    79,  83,  71,  78,  44,  0,   0,   0,   1,   0,   0,   0,   8,   0,   0,   0,   32,  0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,   3,   12,

+    0,   0,   83,  86,  95,  84,  97,  114, 103, 101, 116, 0,   171, 171, 83,  72,  68,  82,  64,

+    1,   0,   0,   65,  0,   0,   0,   80,  0,   0,   0,   106, 8,   0,   1,   88,  32,  0,   4,

+    0,   112, 16,  0,   0,   0,   0,   0,   85,  85,  0,   0,   88,  32,  0,   4,   0,   112, 16,

+    0,   1,   0,   0,   0,   68,  68,  0,   0,   98,  16,  0,   3,   50,  16,  16,  0,   1,   0,

+    0,   0,   101, 0,   0,   3,   50,  32,  16,  0,   0,   0,   0,   0,   104, 0,   0,   2,   1,

+    0,   0,   0,   61,  16,  0,   7,   50,  0,   16,  0,   0,   0,   0,   0,   1,   64,  0,   0,

+    0,   0,   0,   0,   70,  126, 16,  0,   0,   0,   0,   0,   86,  0,   0,   5,   50,  0,   16,

+    0,   0,   0,   0,   0,   70,  0,   16,  0,   0,   0,   0,   0,   56,  0,   0,   7,   50,  0,

+    16,  0,   0,   0,   0,   0,   70,  0,   16,  0,   0,   0,   0,   0,   70,  16,  16,  0,   1,

+    0,   0,   0,   28,  0,   0,   5,   50,  0,   16,  0,   0,   0,   0,   0,   70,  0,   16,  0,

+    0,   0,   0,   0,   54,  0,   0,   8,   194, 0,   16,  0,   0,   0,   0,   0,   2,   64,  0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   46,  0,

+    0,   9,   66,  0,   16,  0,   0,   0,   0,   0,   70,  14,  16,  0,   0,   0,   0,   0,   134,

+    125, 16,  0,   1,   0,   0,   0,   1,   64,  0,   0,   0,   0,   0,   0,   46,  0,   0,   9,

+    18,  0,   16,  0,   0,   0,   0,   0,   70,  15,  16,  0,   0,   0,   0,   0,   70,  126, 16,

+    0,   0,   0,   0,   0,   1,   64,  0,   0,   0,   0,   0,   0,   54,  0,   0,   5,   18,  32,

+    16,  0,   0,   0,   0,   0,   10,  0,   16,  0,   0,   0,   0,   0,   86,  0,   0,   5,   34,

+    32,  16,  0,   0,   0,   0,   0,   42,  0,   16,  0,   0,   0,   0,   0,   62,  0,   0,   1,

+    83,  84,  65,  84,  116, 0,   0,   0,   10,  0,   0,   0,   1,   0,   0,   0,   0,   0,   0,

+    0,   2,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h
new file mode 100644
index 0000000..989a316
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h
@@ -0,0 +1,84 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_VertexID              0   x           0   VERTID    uint   x   

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float   xyzw

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+vs_4_1

+dcl_globalFlags refactoringAllowed

+dcl_immediateConstantBuffer { { -1.000000, 1.000000, 0, 0},

+                              { 1.000000, -1.000000, 0, 0},

+                              { -1.000000, -1.000000, 0, 0},

+                              { -1.000000, 1.000000, 0, 0},

+                              { 1.000000, 1.000000, 0, 0},

+                              { 1.000000, -1.000000, 0, 0} }

+dcl_input_sgv v0.x, vertex_id

+dcl_output_siv o0.xyzw, position

+dcl_output o1.xy

+dcl_temps 1

+mov o0.zw, l(0,0,0,1.000000)

+mov r0.x, v0.x

+mov o0.xy, icb[r0.x + 0].xyxx

+add r0.y, l(1.000000), icb[r0.x + 0].x

+add r0.x, l(1.000000), -icb[r0.x + 0].y

+mul o1.xy, r0.yxyy, l(0.500000, 0.500000, 0.000000, 0.000000)

+ret 

+// Approximately 7 instruction slots used

+#endif

+

+const BYTE g_VS_ResolveDepthStencil[] = {

+    68,  88,  66,  67,  205, 15,  103, 70,  202, 235, 195, 98,  255, 82,  84,  239, 130, 6,   12,

+    104, 1,   0,   0,   0,   0,   3,   0,   0,   5,   0,   0,   0,   52,  0,   0,   0,   140, 0,

+    0,   0,   192, 0,   0,   0,   24,  1,   0,   0,   132, 2,   0,   0,   82,  68,  69,  70,  80,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   28,  0,   0,   0,

+    1,   4,   254, 255, 0,   1,   0,   0,   28,  0,   0,   0,   77,  105, 99,  114, 111, 115, 111,

+    102, 116, 32,  40,  82,  41,  32,  72,  76,  83,  76,  32,  83,  104, 97,  100, 101, 114, 32,

+    67,  111, 109, 112, 105, 108, 101, 114, 32,  54,  46,  51,  46,  57,  54,  48,  48,  46,  49,

+    54,  51,  56,  52,  0,   171, 171, 73,  83,  71,  78,  44,  0,   0,   0,   1,   0,   0,   0,

+    8,   0,   0,   0,   32,  0,   0,   0,   0,   0,   0,   0,   6,   0,   0,   0,   1,   0,   0,

+    0,   0,   0,   0,   0,   1,   1,   0,   0,   83,  86,  95,  86,  101, 114, 116, 101, 120, 73,

+    68,  0,   79,  83,  71,  78,  80,  0,   0,   0,   2,   0,   0,   0,   8,   0,   0,   0,   56,

+    0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,

+    15,  0,   0,   0,   68,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,

+    0,   1,   0,   0,   0,   3,   12,  0,   0,   83,  86,  95,  80,  111, 115, 105, 116, 105, 111,

+    110, 0,   84,  69,  88,  67,  79,  79,  82,  68,  0,   171, 171, 171, 83,  72,  68,  82,  100,

+    1,   0,   0,   65,  0,   1,   0,   89,  0,   0,   0,   106, 8,   0,   1,   53,  24,  0,   0,

+    26,  0,   0,   0,   0,   0,   128, 191, 0,   0,   128, 63,  0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   128, 63,  0,   0,   128, 191, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    128, 191, 0,   0,   128, 191, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   128, 191, 0,

+    0,   128, 63,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   128, 63,  0,   0,   128, 63,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   128, 63,  0,   0,   128, 191, 0,   0,   0,

+    0,   0,   0,   0,   0,   96,  0,   0,   4,   18,  16,  16,  0,   0,   0,   0,   0,   6,   0,

+    0,   0,   103, 0,   0,   4,   242, 32,  16,  0,   0,   0,   0,   0,   1,   0,   0,   0,   101,

+    0,   0,   3,   50,  32,  16,  0,   1,   0,   0,   0,   104, 0,   0,   2,   1,   0,   0,   0,

+    54,  0,   0,   8,   194, 32,  16,  0,   0,   0,   0,   0,   2,   64,  0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   128, 63,  54,  0,   0,   5,   18,  0,

+    16,  0,   0,   0,   0,   0,   10,  16,  16,  0,   0,   0,   0,   0,   54,  0,   0,   6,   50,

+    32,  16,  0,   0,   0,   0,   0,   70,  144, 144, 0,   10,  0,   16,  0,   0,   0,   0,   0,

+    0,   0,   0,   8,   34,  0,   16,  0,   0,   0,   0,   0,   1,   64,  0,   0,   0,   0,   128,

+    63,  10,  144, 144, 0,   10,  0,   16,  0,   0,   0,   0,   0,   0,   0,   0,   9,   18,  0,

+    16,  0,   0,   0,   0,   0,   1,   64,  0,   0,   0,   0,   128, 63,  26,  144, 144, 128, 65,

+    0,   0,   0,   10,  0,   16,  0,   0,   0,   0,   0,   56,  0,   0,   10,  50,  32,  16,  0,

+    1,   0,   0,   0,   22,  5,   16,  0,   0,   0,   0,   0,   2,   64,  0,   0,   0,   0,   0,

+    63,  0,   0,   0,   63,  0,   0,   0,   0,   0,   0,   0,   0,   62,  0,   0,   1,   83,  84,

+    65,  84,  116, 0,   0,   0,   7,   0,   0,   0,   1,   0,   0,   0,   6,   0,   0,   0,   3,

+    0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h
new file mode 100644
index 0000000..1730df3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h
@@ -0,0 +1,84 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Stencil                           texture   uint2        2dMS    1        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Position              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_Target                0   xy          0   TARGET   float   xy  

+//

+ps_4_1

+dcl_globalFlags refactoringAllowed

+dcl_resource_texture2dms(0) (uint,uint,uint,uint) t1

+dcl_input_ps linear v1.xy

+dcl_output o0.xy

+dcl_temps 1

+resinfo_uint r0.xy, l(0), t1.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftou r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ldms r0.x, r0.xyzw, t1.yxzw, l(0)

+utof o0.y, r0.x

+mov o0.x, l(0)

+ret 

+// Approximately 9 instruction slots used

+#endif

+

+const BYTE g_PS_ResolveStencil[] = {

+    68,  88,  66,  67,  122, 29,  34,  146, 254, 203, 175, 97,  151, 254, 255, 190, 91, 40,  55,

+    118, 1,   0,   0,   0,   208, 2,   0,   0,   5,   0,   0,   0,   52,  0,   0,   0,  180, 0,

+    0,   0,   12,  1,   0,   0,   64,  1,   0,   0,   84,  2,   0,   0,   82,  68,  69, 70,  120,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   28,  0,  0,   0,

+    1,   4,   255, 255, 0,   1,   0,   0,   68,  0,   0,   0,   60,  0,   0,   0,   2,  0,   0,

+    0,   4,   0,   0,   0,   6,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,  1,   0,

+    0,   0,   5,   0,   0,   0,   83,  116, 101, 110, 99,  105, 108, 0,   77,  105, 99, 114, 111,

+    115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,  83,  76,  32,  83,  104, 97, 100, 101,

+    114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,  54,  46,  51,  46,  57,  54, 48,  48,

+    46,  49,  54,  51,  56,  52,  0,   171, 171, 73,  83,  71,  78,  80,  0,   0,   0,  2,   0,

+    0,   0,   8,   0,   0,   0,   56,  0,   0,   0,   0,   0,   0,   0,   1,   0,   0,  0,   3,

+    0,   0,   0,   0,   0,   0,   0,   15,  0,   0,   0,   68,  0,   0,   0,   0,   0,  0,   0,

+    0,   0,   0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   3,   3,   0,   0,   83, 86,  95,

+    80,  111, 115, 105, 116, 105, 111, 110, 0,   84,  69,  88,  67,  79,  79,  82,  68, 0,   171,

+    171, 171, 79,  83,  71,  78,  44,  0,   0,   0,   1,   0,   0,   0,   8,   0,   0,  0,   32,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   0,   0,   0,  0,   0,

+    3,   12,  0,   0,   83,  86,  95,  84,  97,  114, 103, 101, 116, 0,   171, 171, 83, 72,  68,

+    82,  12,  1,   0,   0,   65,  0,   0,   0,   67,  0,   0,   0,   106, 8,   0,   1,  88,  32,

+    0,   4,   0,   112, 16,  0,   1,   0,   0,   0,   68,  68,  0,   0,   98,  16,  0,  3,   50,

+    16,  16,  0,   1,   0,   0,   0,   101, 0,   0,   3,   50,  32,  16,  0,   0,   0,  0,   0,

+    104, 0,   0,   2,   1,   0,   0,   0,   61,  16,  0,   7,   50,  0,   16,  0,   0,  0,   0,

+    0,   1,   64,  0,   0,   0,   0,   0,   0,   70,  126, 16,  0,   1,   0,   0,   0,  86,  0,

+    0,   5,   50,  0,   16,  0,   0,   0,   0,   0,   70,  0,   16,  0,   0,   0,   0,  0,   56,

+    0,   0,   7,   50,  0,   16,  0,   0,   0,   0,   0,   70,  0,   16,  0,   0,   0,  0,   0,

+    70,  16,  16,  0,   1,   0,   0,   0,   28,  0,   0,   5,   50,  0,   16,  0,   0,  0,   0,

+    0,   70,  0,   16,  0,   0,   0,   0,   0,   54,  0,   0,   8,   194, 0,   16,  0,  0,   0,

+    0,   0,   2,   64,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,

+    0,   0,   0,   46,  0,   0,   9,   18,  0,   16,  0,   0,   0,   0,   0,   70,  14, 16,  0,

+    0,   0,   0,   0,   22,  126, 16,  0,   1,   0,   0,   0,   1,   64,  0,   0,   0,  0,   0,

+    0,   86,  0,   0,   5,   34,  32,  16,  0,   0,   0,   0,   0,   10,  0,   16,  0,  0,   0,

+    0,   0,   54,  0,   0,   5,   18,  32,  16,  0,   0,   0,   0,   0,   1,   64,  0,  0,   0,

+    0,   0,   0,   62,  0,   0,   1,   83,  84,  65,  84,  116, 0,   0,   0,   9,   0,  0,   0,

+    1,   0,   0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   1,   0,   0,   0,   0,  0,   0,

+    0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   1,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   0,  0,   0,

+    0,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,

+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h
new file mode 100644
index 0000000..b34914b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h
@@ -0,0 +1,278 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer SwizzleProperties

+// {

+//

+//   uint4 SwizzleIndices;              // Offset:    0 Size:    16

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF2DArray                   texture  float4     2darray    0        1

+// SwizzleProperties                 cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint   x   

+// TEXCOORD                 0   xyz         2     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_sampler s0, mode_default

+dcl_resource_texture2darray (float,float,float,float) t0

+dcl_input_ps_siv constant v1.x, rendertarget_array_index

+dcl_input_ps linear v2.xy

+dcl_output o0.xyzw

+dcl_temps 1

+dcl_indexableTemp x0[6], 4

+utof r0.z, v1.x

+mov r0.xy, v2.xyxx

+sample r0.xyzw, r0.xyzx, t0.xyzw, s0

+mov x0[0].x, r0.x

+mov x0[1].x, r0.y

+mov x0[2].x, r0.z

+mov x0[3].x, r0.w

+mov x0[4].x, l(0)

+mov x0[5].x, l(1.000000)

+mov r0.x, cb0[0].x

+mov o0.x, x0[r0.x + 0].x

+mov r0.x, cb0[0].y

+mov o0.y, x0[r0.x + 0].x

+mov r0.x, cb0[0].z

+mov o0.z, x0[r0.x + 0].x

+mov r0.x, cb0[0].w

+mov o0.w, x0[r0.x + 0].x

+ret 

+// Approximately 18 instruction slots used

+#endif

+

+const BYTE g_PS_SwizzleF2DArray[] =

+{

+     68,  88,  66,  67,  39, 232, 

+     91, 166, 165, 217,  22,  39, 

+    183, 202, 191,  64, 238, 104, 

+    217, 199,   1,   0,   0,   0, 

+    204,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    104,   1,   0,   0, 240,   1, 

+      0,   0,  36,   2,   0,   0, 

+     80,   4,   0,   0,  82,  68, 

+     69,  70,  44,   1,   0,   0, 

+      1,   0,   0,   0, 168,   0, 

+      0,   0,   3,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    248,   0,   0,   0, 124,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    132,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      5,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0, 148,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,  83,  97, 

+    109, 112, 108, 101, 114,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  70,  50,  68,  65, 114, 

+    114,  97, 121,   0,  83, 119, 

+    105, 122, 122, 108, 101,  80, 

+    114, 111, 112, 101, 114, 116, 

+    105, 101, 115,   0, 171, 171, 

+    148,   0,   0,   0,   1,   0, 

+      0,   0, 192,   0,   0,   0, 

+     16,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+    216,   0,   0,   0,   0,   0, 

+      0,   0,  16,   0,   0,   0, 

+      2,   0,   0,   0, 232,   0, 

+      0,   0,   0,   0,   0,   0, 

+     83, 119, 105, 122, 122, 108, 

+    101,  73, 110, 100, 105,  99, 

+    101, 115,   0, 171,   1,   0, 

+     19,   0,   1,   0,   4,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  77, 105,  99, 114, 

+    111, 115, 111, 102, 116,  32, 

+     40,  82,  41,  32,  72,  76, 

+     83,  76,  32,  83, 104,  97, 

+    100, 101, 114,  32,  67, 111, 

+    109, 112, 105, 108, 101, 114, 

+     32,  54,  46,  51,  46,  57, 

+     54,  48,  48,  46,  49,  54, 

+     51,  56,  52,   0, 171, 171, 

+     73,  83,  71,  78, 128,   0, 

+      0,   0,   3,   0,   0,   0, 

+      8,   0,   0,   0,  80,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   1,   0,   0, 118,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   2,   0,   0,   0, 

+      7,   3,   0,   0,  83,  86, 

+     95,  80,  79,  83,  73,  84, 

+     73,  79,  78,   0,  83,  86, 

+     95,  82,  69,  78,  68,  69, 

+     82,  84,  65,  82,  71,  69, 

+     84,  65,  82,  82,  65,  89, 

+     73,  78,  68,  69,  88,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171,  79,  83, 

+     71,  78,  44,   0,   0,   0, 

+      1,   0,   0,   0,   8,   0, 

+      0,   0,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  83,  86,  95,  84, 

+     65,  82,  71,  69,  84,   0, 

+    171, 171,  83,  72,  68,  82, 

+     36,   2,   0,   0,  64,   0, 

+      0,   0, 137,   0,   0,   0, 

+     89,   0,   0,   4,  70, 142, 

+     32,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,  90,   0, 

+      0,   3,   0,  96,  16,   0, 

+      0,   0,   0,   0,  88,  64, 

+      0,   4,   0, 112,  16,   0, 

+      0,   0,   0,   0,  85,  85, 

+      0,   0, 100,   8,   0,   4, 

+     18,  16,  16,   0,   1,   0, 

+      0,   0,   4,   0,   0,   0, 

+     98,  16,   0,   3,  50,  16, 

+     16,   0,   2,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0, 105,   0,   0,   4, 

+      0,   0,   0,   0,   6,   0, 

+      0,   0,   4,   0,   0,   0, 

+     86,   0,   0,   5,  66,   0, 

+     16,   0,   0,   0,   0,   0, 

+     10,  16,  16,   0,   1,   0, 

+      0,   0,  54,   0,   0,   5, 

+     50,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      2,   0,   0,   0,  69,   0, 

+      0,   9, 242,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,   0,  96,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  26,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,  42,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,  58,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   5,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0, 128,  63,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  10, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7,  18,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   6, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  26, 128,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     34,  32,  16,   0,   0,   0, 

+      0,   0,  10,  48,  32,   4, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     42, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7,  66,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  58, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7, 130,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,  18,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      6,   0,   0,   0,  10,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      5,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h
new file mode 100644
index 0000000..ea57e87
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h
@@ -0,0 +1,256 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer SwizzleProperties

+// {

+//

+//   uint4 SwizzleIndices;              // Offset:    0 Size:    16

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF2D                        texture  float4          2d    0        1

+// SwizzleProperties                 cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_sampler s0, mode_default

+dcl_resource_texture2d (float,float,float,float) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+dcl_indexableTemp x0[6], 4

+sample r0.xyzw, v1.xyxx, t0.xyzw, s0

+mov x0[0].x, r0.x

+mov x0[1].x, r0.y

+mov x0[2].x, r0.z

+mov x0[3].x, r0.w

+mov x0[4].x, l(0)

+mov x0[5].x, l(1.000000)

+mov r0.x, cb0[0].x

+mov o0.x, x0[r0.x + 0].x

+mov r0.x, cb0[0].y

+mov o0.y, x0[r0.x + 0].x

+mov r0.x, cb0[0].z

+mov o0.z, x0[r0.x + 0].x

+mov r0.x, cb0[0].w

+mov o0.w, x0[r0.x + 0].x

+ret 

+// Approximately 16 instruction slots used

+#endif

+

+const BYTE g_PS_SwizzleF2D[] =

+{

+     68,  88,  66,  67, 187, 204, 

+    160,  39, 195, 158, 245,  72, 

+    125, 249,  70, 140, 158, 199, 

+    246, 220,   1,   0,   0,   0, 

+     96,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    100,   1,   0,   0, 188,   1, 

+      0,   0, 240,   1,   0,   0, 

+    228,   3,   0,   0,  82,  68, 

+     69,  70,  40,   1,   0,   0, 

+      1,   0,   0,   0, 164,   0, 

+      0,   0,   3,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    244,   0,   0,   0, 124,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    132,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      4,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0, 143,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,  83,  97, 

+    109, 112, 108, 101, 114,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  70,  50,  68,   0,  83, 

+    119, 105, 122, 122, 108, 101, 

+     80, 114, 111, 112, 101, 114, 

+    116, 105, 101, 115,   0, 171, 

+    171, 171, 143,   0,   0,   0, 

+      1,   0,   0,   0, 188,   0, 

+      0,   0,  16,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0, 212,   0,   0,   0, 

+      0,   0,   0,   0,  16,   0, 

+      0,   0,   2,   0,   0,   0, 

+    228,   0,   0,   0,   0,   0, 

+      0,   0,  83, 119, 105, 122, 

+    122, 108, 101,  73, 110, 100, 

+    105,  99, 101, 115,   0, 171, 

+      1,   0,  19,   0,   1,   0, 

+      4,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+    171, 171,  73,  83,  71,  78, 

+     80,   0,   0,   0,   2,   0, 

+      0,   0,   8,   0,   0,   0, 

+     56,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     68,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0,   3,   3,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     84,  69,  88,  67,  79,  79, 

+     82,  68,   0, 171, 171, 171, 

+     79,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  83,  86, 

+     95,  84,  65,  82,  71,  69, 

+     84,   0, 171, 171,  83,  72, 

+     68,  82, 236,   1,   0,   0, 

+     64,   0,   0,   0, 123,   0, 

+      0,   0,  89,   0,   0,   4, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     90,   0,   0,   3,   0,  96, 

+     16,   0,   0,   0,   0,   0, 

+     88,  24,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     85,  85,   0,   0,  98,  16, 

+      0,   3,  50,  16,  16,   0, 

+      1,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+    105,   0,   0,   4,   0,   0, 

+      0,   0,   6,   0,   0,   0, 

+      4,   0,   0,   0,  69,   0, 

+      0,   9, 242,   0,  16,   0, 

+      0,   0,   0,   0,  70,  16, 

+     16,   0,   1,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,   0,  96,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  26,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,  42,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,  58,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   5,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0, 128,  63,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  10, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7,  18,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   6, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  26, 128,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     34,  32,  16,   0,   0,   0, 

+      0,   0,  10,  48,  32,   4, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     42, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7,  66,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  58, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7, 130,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,  16,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      6,   0,   0,   0,  10,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h
new file mode 100644
index 0000000..7938639
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h
@@ -0,0 +1,265 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer SwizzleProperties

+// {

+//

+//   uint4 SwizzleIndices;              // Offset:    0 Size:    16

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// Sampler                           sampler      NA          NA    0        1

+// TextureF3D                        texture  float4          3d    0        1

+// SwizzleProperties                 cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET   float   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_sampler s0, mode_default

+dcl_resource_texture3d (float,float,float,float) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+dcl_indexableTemp x0[6], 4

+sample r0.xyzw, v2.xyzx, t0.xyzw, s0

+mov x0[0].x, r0.x

+mov x0[1].x, r0.y

+mov x0[2].x, r0.z

+mov x0[3].x, r0.w

+mov x0[4].x, l(0)

+mov x0[5].x, l(1.000000)

+mov r0.x, cb0[0].x

+mov o0.x, x0[r0.x + 0].x

+mov r0.x, cb0[0].y

+mov o0.y, x0[r0.x + 0].x

+mov r0.x, cb0[0].z

+mov o0.z, x0[r0.x + 0].x

+mov r0.x, cb0[0].w

+mov o0.w, x0[r0.x + 0].x

+ret 

+// Approximately 16 instruction slots used

+#endif

+

+const BYTE g_PS_SwizzleF3D[] =

+{

+     68,  88,  66,  67, 238,  60, 

+     80,  74,  42,  65, 120, 165, 

+    177,  91, 253, 216,  89, 102, 

+      2, 228,   1,   0,   0,   0, 

+    144,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+    100,   1,   0,   0, 236,   1, 

+      0,   0,  32,   2,   0,   0, 

+     20,   4,   0,   0,  82,  68, 

+     69,  70,  40,   1,   0,   0, 

+      1,   0,   0,   0, 164,   0, 

+      0,   0,   3,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    244,   0,   0,   0, 124,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    132,   0,   0,   0,   2,   0, 

+      0,   0,   5,   0,   0,   0, 

+      8,   0,   0,   0, 255, 255, 

+    255, 255,   0,   0,   0,   0, 

+      1,   0,   0,   0,  13,   0, 

+      0,   0, 143,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,  83,  97, 

+    109, 112, 108, 101, 114,   0, 

+     84, 101, 120, 116, 117, 114, 

+    101,  70,  51,  68,   0,  83, 

+    119, 105, 122, 122, 108, 101, 

+     80, 114, 111, 112, 101, 114, 

+    116, 105, 101, 115,   0, 171, 

+    171, 171, 143,   0,   0,   0, 

+      1,   0,   0,   0, 188,   0, 

+      0,   0,  16,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0, 212,   0,   0,   0, 

+      0,   0,   0,   0,  16,   0, 

+      0,   0,   2,   0,   0,   0, 

+    228,   0,   0,   0,   0,   0, 

+      0,   0,  83, 119, 105, 122, 

+    122, 108, 101,  73, 110, 100, 

+    105,  99, 101, 115,   0, 171, 

+      1,   0,  19,   0,   1,   0, 

+      4,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+    171, 171,  73,  83,  71,  78, 

+    128,   0,   0,   0,   3,   0, 

+      0,   0,   8,   0,   0,   0, 

+     80,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     92,   0,   0,   0,   0,   0, 

+      0,   0,   4,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,   1,   0,   0,   0, 

+    118,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   2,   0, 

+      0,   0,   7,   7,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     83,  86,  95,  82,  69,  78, 

+     68,  69,  82,  84,  65,  82, 

+     71,  69,  84,  65,  82,  82, 

+     65,  89,  73,  78,  68,  69, 

+     88,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0, 171, 

+     79,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  83,  86, 

+     95,  84,  65,  82,  71,  69, 

+     84,   0, 171, 171,  83,  72, 

+     68,  82, 236,   1,   0,   0, 

+     64,   0,   0,   0, 123,   0, 

+      0,   0,  89,   0,   0,   4, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     90,   0,   0,   3,   0,  96, 

+     16,   0,   0,   0,   0,   0, 

+     88,  40,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     85,  85,   0,   0,  98,  16, 

+      0,   3, 114,  16,  16,   0, 

+      2,   0,   0,   0, 101,   0, 

+      0,   3, 242,  32,  16,   0, 

+      0,   0,   0,   0, 104,   0, 

+      0,   2,   1,   0,   0,   0, 

+    105,   0,   0,   4,   0,   0, 

+      0,   0,   6,   0,   0,   0, 

+      4,   0,   0,   0,  69,   0, 

+      0,   9, 242,   0,  16,   0, 

+      0,   0,   0,   0,  70,  18, 

+     16,   0,   2,   0,   0,   0, 

+     70, 126,  16,   0,   0,   0, 

+      0,   0,   0,  96,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  26,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,  42,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,  58,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   5,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0, 128,  63,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  10, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7,  18,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   6, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  26, 128,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     34,  32,  16,   0,   0,   0, 

+      0,   0,  10,  48,  32,   4, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     42, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7,  66,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  58, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7, 130,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,  16,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      6,   0,   0,   0,  10,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h
new file mode 100644
index 0000000..76176fc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h
@@ -0,0 +1,286 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer SwizzleProperties

+// {

+//

+//   uint4 SwizzleIndices;              // Offset:    0 Size:    16

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI2DArray                   texture   sint4     2darray    0        1

+// SwizzleProperties                 cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint   x   

+// TEXCOORD                 0   xyz         2     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_resource_texture2darray (sint,sint,sint,sint) t0

+dcl_input_ps_siv constant v1.x, rendertarget_array_index

+dcl_input_ps linear v2.xy

+dcl_output o0.xyzw

+dcl_temps 1

+dcl_indexableTemp x0[6], 4

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v2.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.z, v1.x

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov x0[0].x, r0.x

+mov x0[1].x, r0.y

+mov x0[2].x, r0.z

+mov x0[3].x, r0.w

+mov x0[4].x, l(0)

+mov x0[5].x, l(1)

+mov r0.x, cb0[0].x

+mov o0.x, x0[r0.x + 0].x

+mov r0.x, cb0[0].y

+mov o0.y, x0[r0.x + 0].x

+mov r0.x, cb0[0].z

+mov o0.z, x0[r0.x + 0].x

+mov r0.x, cb0[0].w

+mov o0.w, x0[r0.x + 0].x

+ret 

+// Approximately 22 instruction slots used

+#endif

+

+const BYTE g_PS_SwizzleI2DArray[] =

+{

+     68,  88,  66,  67,  85,  61, 

+     60,  36,  33, 245,  58, 113, 

+    238, 227, 230, 200, 136, 227, 

+     36, 193,   1,   0,   0,   0, 

+    240,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+     64,   1,   0,   0, 200,   1, 

+      0,   0, 252,   1,   0,   0, 

+    116,   4,   0,   0,  82,  68, 

+     69,  70,   4,   1,   0,   0, 

+      1,   0,   0,   0, 128,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    208,   0,   0,   0,  92,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   5,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+    108,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,  84, 101, 120, 116, 

+    117, 114, 101,  73,  50,  68, 

+     65, 114, 114,  97, 121,   0, 

+     83, 119, 105, 122, 122, 108, 

+    101,  80, 114, 111, 112, 101, 

+    114, 116, 105, 101, 115,   0, 

+    171, 171, 108,   0,   0,   0, 

+      1,   0,   0,   0, 152,   0, 

+      0,   0,  16,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0, 176,   0,   0,   0, 

+      0,   0,   0,   0,  16,   0, 

+      0,   0,   2,   0,   0,   0, 

+    192,   0,   0,   0,   0,   0, 

+      0,   0,  83, 119, 105, 122, 

+    122, 108, 101,  73, 110, 100, 

+    105,  99, 101, 115,   0, 171, 

+      1,   0,  19,   0,   1,   0, 

+      4,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+    171, 171,  73,  83,  71,  78, 

+    128,   0,   0,   0,   3,   0, 

+      0,   0,   8,   0,   0,   0, 

+     80,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     92,   0,   0,   0,   0,   0, 

+      0,   0,   4,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,   1,   1,   0,   0, 

+    118,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   2,   0, 

+      0,   0,   7,   3,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     83,  86,  95,  82,  69,  78, 

+     68,  69,  82,  84,  65,  82, 

+     71,  69,  84,  65,  82,  82, 

+     65,  89,  73,  78,  68,  69, 

+     88,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0, 171, 

+     79,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  83,  86, 

+     95,  84,  65,  82,  71,  69, 

+     84,   0, 171, 171,  83,  72, 

+     68,  82, 112,   2,   0,   0, 

+     64,   0,   0,   0, 156,   0, 

+      0,   0,  89,   0,   0,   4, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     88,  64,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     51,  51,   0,   0, 100,   8, 

+      0,   4,  18,  16,  16,   0, 

+      1,   0,   0,   0,   4,   0, 

+      0,   0,  98,  16,   0,   3, 

+     50,  16,  16,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0, 104,   0,   0,   2, 

+      1,   0,   0,   0, 105,   0, 

+      0,   4,   0,   0,   0,   0, 

+      6,   0,   0,   0,   4,   0, 

+      0,   0,  61,  16,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     86,   0,   0,   5,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  56,   0,   0,   7, 

+     50,   0,  16,   0,   0,   0, 

+      0,   0,  70,   0,  16,   0, 

+      0,   0,   0,   0,  70,  16, 

+     16,   0,   2,   0,   0,   0, 

+     27,   0,   0,   5,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+     66,   0,  16,   0,   0,   0, 

+      0,   0,  10,  16,  16,   0, 

+      1,   0,   0,   0,  54,   0, 

+      0,   5, 130,   0,  16,   0, 

+      0,   0,   0,   0,   1,  64, 

+      0,   0,   0,   0,   0,   0, 

+     45,   0,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,  14,  16,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  26,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,  42,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,  58,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   5,   0, 

+      0,   0,   1,  64,   0,   0, 

+      1,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  10, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7,  18,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   6, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  26, 128,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     34,  32,  16,   0,   0,   0, 

+      0,   0,  10,  48,  32,   4, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     42, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7,  66,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  58, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7, 130,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,  22,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      6,   0,   0,   0,  10,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      6,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h
new file mode 100644
index 0000000..1df27a0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h
@@ -0,0 +1,270 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer SwizzleProperties

+// {

+//

+//   uint4 SwizzleIndices;              // Offset:    0 Size:    16

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI2D                        texture   sint4          2d    0        1

+// SwizzleProperties                 cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_resource_texture2d (sint,sint,sint,sint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+dcl_indexableTemp x0[6], 4

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov x0[0].x, r0.x

+mov x0[1].x, r0.y

+mov x0[2].x, r0.z

+mov x0[3].x, r0.w

+mov x0[4].x, l(0)

+mov x0[5].x, l(1)

+mov r0.x, cb0[0].x

+mov o0.x, x0[r0.x + 0].x

+mov r0.x, cb0[0].y

+mov o0.y, x0[r0.x + 0].x

+mov r0.x, cb0[0].z

+mov o0.z, x0[r0.x + 0].x

+mov r0.x, cb0[0].w

+mov o0.w, x0[r0.x + 0].x

+ret 

+// Approximately 21 instruction slots used

+#endif

+

+const BYTE g_PS_SwizzleI2D[] =

+{

+     68,  88,  66,  67, 180,  37, 

+     54,  19,  39, 134, 185, 230, 

+    234,  82, 113, 129,  69, 135, 

+    140,  27,   1,   0,   0,   0, 

+    164,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+     60,   1,   0,   0, 148,   1, 

+      0,   0, 200,   1,   0,   0, 

+     40,   4,   0,   0,  82,  68, 

+     69,  70,   0,   1,   0,   0, 

+      1,   0,   0,   0, 124,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    204,   0,   0,   0,  92,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+    103,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,  84, 101, 120, 116, 

+    117, 114, 101,  73,  50,  68, 

+      0,  83, 119, 105, 122, 122, 

+    108, 101,  80, 114, 111, 112, 

+    101, 114, 116, 105, 101, 115, 

+      0, 171, 171, 171, 103,   0, 

+      0,   0,   1,   0,   0,   0, 

+    148,   0,   0,   0,  16,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 172,   0, 

+      0,   0,   0,   0,   0,   0, 

+     16,   0,   0,   0,   2,   0, 

+      0,   0, 188,   0,   0,   0, 

+      0,   0,   0,   0,  83, 119, 

+    105, 122, 122, 108, 101,  73, 

+    110, 100, 105,  99, 101, 115, 

+      0, 171,   1,   0,  19,   0, 

+      1,   0,   4,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78,  80,   0,   0,   0, 

+      2,   0,   0,   0,   8,   0, 

+      0,   0,  56,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  68,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,   3,   3, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0, 171, 

+    171, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82,  88,   2, 

+      0,   0,  64,   0,   0,   0, 

+    150,   0,   0,   0,  89,   0, 

+      0,   4,  70, 142,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  88,  24,   0,   4, 

+      0, 112,  16,   0,   0,   0, 

+      0,   0,  51,  51,   0,   0, 

+     98,  16,   0,   3,  50,  16, 

+     16,   0,   1,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0, 105,   0,   0,   4, 

+      0,   0,   0,   0,   6,   0, 

+      0,   0,   4,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,  26,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,  42,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,  58,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,  64, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      5,   0,   0,   0,   1,  64, 

+      0,   0,   1,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     10, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7,  18,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  26, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7,  34,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   6, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  42, 128,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     66,  32,  16,   0,   0,   0, 

+      0,   0,  10,  48,  32,   4, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     58, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7, 130,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,  21,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   6,   0,   0,   0, 

+     10,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   5,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h
new file mode 100644
index 0000000..96f042b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h
@@ -0,0 +1,277 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer SwizzleProperties

+// {

+//

+//   uint4 SwizzleIndices;              // Offset:    0 Size:    16

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureI3D                        texture   sint4          3d    0        1

+// SwizzleProperties                 cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET     int   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_resource_texture3d (sint,sint,sint,sint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+dcl_indexableTemp x0[6], 4

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov x0[0].x, r0.x

+mov x0[1].x, r0.y

+mov x0[2].x, r0.z

+mov x0[3].x, r0.w

+mov x0[4].x, l(0)

+mov x0[5].x, l(1)

+mov r0.x, cb0[0].x

+mov o0.x, x0[r0.x + 0].x

+mov r0.x, cb0[0].y

+mov o0.y, x0[r0.x + 0].x

+mov r0.x, cb0[0].z

+mov o0.z, x0[r0.x + 0].x

+mov r0.x, cb0[0].w

+mov o0.w, x0[r0.x + 0].x

+ret 

+// Approximately 21 instruction slots used

+#endif

+

+const BYTE g_PS_SwizzleI3D[] =

+{

+     68,  88,  66,  67,  48,  84, 

+     97, 193, 216, 245, 101, 196, 

+    167,  81, 215, 168,  25, 164, 

+    144,  38,   1,   0,   0,   0, 

+    200,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+     60,   1,   0,   0, 196,   1, 

+      0,   0, 248,   1,   0,   0, 

+     76,   4,   0,   0,  82,  68, 

+     69,  70,   0,   1,   0,   0, 

+      1,   0,   0,   0, 124,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    204,   0,   0,   0,  92,   0, 

+      0,   0,   2,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+    103,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,  84, 101, 120, 116, 

+    117, 114, 101,  73,  51,  68, 

+      0,  83, 119, 105, 122, 122, 

+    108, 101,  80, 114, 111, 112, 

+    101, 114, 116, 105, 101, 115, 

+      0, 171, 171, 171, 103,   0, 

+      0,   0,   1,   0,   0,   0, 

+    148,   0,   0,   0,  16,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 172,   0, 

+      0,   0,   0,   0,   0,   0, 

+     16,   0,   0,   0,   2,   0, 

+      0,   0, 188,   0,   0,   0, 

+      0,   0,   0,   0,  83, 119, 

+    105, 122, 122, 108, 101,  73, 

+    110, 100, 105,  99, 101, 115, 

+      0, 171,   1,   0,  19,   0, 

+      1,   0,   4,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0, 118,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0,   7,   7, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  83,  86,  95,  82, 

+     69,  78,  68,  69,  82,  84, 

+     65,  82,  71,  69,  84,  65, 

+     82,  82,  65,  89,  73,  78, 

+     68,  69,  88,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82,  76,   2, 

+      0,   0,  64,   0,   0,   0, 

+    147,   0,   0,   0,  89,   0, 

+      0,   4,  70, 142,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  88,  40,   0,   4, 

+      0, 112,  16,   0,   0,   0, 

+      0,   0,  51,  51,   0,   0, 

+     98,  16,   0,   3, 114,  16, 

+     16,   0,   2,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0, 105,   0,   0,   4, 

+      0,   0,   0,   0,   6,   0, 

+      0,   0,   4,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,  26,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,  42,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,  58,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,  64, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      5,   0,   0,   0,   1,  64, 

+      0,   0,   1,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     10, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7,  18,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  26, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7,  34,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   6, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  42, 128,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     66,  32,  16,   0,   0,   0, 

+      0,   0,  10,  48,  32,   4, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     58, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7, 130,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,  21,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   6,   0,   0,   0, 

+     10,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   5,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h
new file mode 100644
index 0000000..cca965c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h
@@ -0,0 +1,286 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer SwizzleProperties

+// {

+//

+//   uint4 SwizzleIndices;              // Offset:    0 Size:    16

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI2DArray                  texture   uint4     2darray    0        1

+// SwizzleProperties                 cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint   x   

+// TEXCOORD                 0   xyz         2     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_resource_texture2darray (uint,uint,uint,uint) t0

+dcl_input_ps_siv constant v1.x, rendertarget_array_index

+dcl_input_ps linear v2.xy

+dcl_output o0.xyzw

+dcl_temps 1

+dcl_indexableTemp x0[6], 4

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v2.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.z, v1.x

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov x0[0].x, r0.x

+mov x0[1].x, r0.y

+mov x0[2].x, r0.z

+mov x0[3].x, r0.w

+mov x0[4].x, l(0)

+mov x0[5].x, l(1)

+mov r0.x, cb0[0].x

+mov o0.x, x0[r0.x + 0].x

+mov r0.x, cb0[0].y

+mov o0.y, x0[r0.x + 0].x

+mov r0.x, cb0[0].z

+mov o0.z, x0[r0.x + 0].x

+mov r0.x, cb0[0].w

+mov o0.w, x0[r0.x + 0].x

+ret 

+// Approximately 22 instruction slots used

+#endif

+

+const BYTE g_PS_SwizzleUI2DArray[] =

+{

+     68,  88,  66,  67,  15, 124, 

+    179,  49,  45,  69,  64, 249, 

+    216, 189, 135, 190,  71, 234, 

+     72,  20,   1,   0,   0,   0, 

+    240,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+     64,   1,   0,   0, 200,   1, 

+      0,   0, 252,   1,   0,   0, 

+    116,   4,   0,   0,  82,  68, 

+     69,  70,   4,   1,   0,   0, 

+      1,   0,   0,   0, 128,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    208,   0,   0,   0,  92,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   5,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+    109,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,  84, 101, 120, 116, 

+    117, 114, 101,  85,  73,  50, 

+     68,  65, 114, 114,  97, 121, 

+      0,  83, 119, 105, 122, 122, 

+    108, 101,  80, 114, 111, 112, 

+    101, 114, 116, 105, 101, 115, 

+      0, 171, 109,   0,   0,   0, 

+      1,   0,   0,   0, 152,   0, 

+      0,   0,  16,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0, 176,   0,   0,   0, 

+      0,   0,   0,   0,  16,   0, 

+      0,   0,   2,   0,   0,   0, 

+    192,   0,   0,   0,   0,   0, 

+      0,   0,  83, 119, 105, 122, 

+    122, 108, 101,  73, 110, 100, 

+    105,  99, 101, 115,   0, 171, 

+      1,   0,  19,   0,   1,   0, 

+      4,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  77, 105, 

+     99, 114, 111, 115, 111, 102, 

+    116,  32,  40,  82,  41,  32, 

+     72,  76,  83,  76,  32,  83, 

+    104,  97, 100, 101, 114,  32, 

+     67, 111, 109, 112, 105, 108, 

+    101, 114,  32,  54,  46,  51, 

+     46,  57,  54,  48,  48,  46, 

+     49,  54,  51,  56,  52,   0, 

+    171, 171,  73,  83,  71,  78, 

+    128,   0,   0,   0,   3,   0, 

+      0,   0,   8,   0,   0,   0, 

+     80,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      3,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     92,   0,   0,   0,   0,   0, 

+      0,   0,   4,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,   1,   1,   0,   0, 

+    118,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,   2,   0, 

+      0,   0,   7,   3,   0,   0, 

+     83,  86,  95,  80,  79,  83, 

+     73,  84,  73,  79,  78,   0, 

+     83,  86,  95,  82,  69,  78, 

+     68,  69,  82,  84,  65,  82, 

+     71,  69,  84,  65,  82,  82, 

+     65,  89,  73,  78,  68,  69, 

+     88,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0, 171, 

+     79,  83,  71,  78,  44,   0, 

+      0,   0,   1,   0,   0,   0, 

+      8,   0,   0,   0,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+     15,   0,   0,   0,  83,  86, 

+     95,  84,  65,  82,  71,  69, 

+     84,   0, 171, 171,  83,  72, 

+     68,  82, 112,   2,   0,   0, 

+     64,   0,   0,   0, 156,   0, 

+      0,   0,  89,   0,   0,   4, 

+     70, 142,  32,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+     88,  64,   0,   4,   0, 112, 

+     16,   0,   0,   0,   0,   0, 

+     68,  68,   0,   0, 100,   8, 

+      0,   4,  18,  16,  16,   0, 

+      1,   0,   0,   0,   4,   0, 

+      0,   0,  98,  16,   0,   3, 

+     50,  16,  16,   0,   2,   0, 

+      0,   0, 101,   0,   0,   3, 

+    242,  32,  16,   0,   0,   0, 

+      0,   0, 104,   0,   0,   2, 

+      1,   0,   0,   0, 105,   0, 

+      0,   4,   0,   0,   0,   0, 

+      6,   0,   0,   0,   4,   0, 

+      0,   0,  61,  16,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     86,   0,   0,   5,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  56,   0,   0,   7, 

+     50,   0,  16,   0,   0,   0, 

+      0,   0,  70,   0,  16,   0, 

+      0,   0,   0,   0,  70,  16, 

+     16,   0,   2,   0,   0,   0, 

+     27,   0,   0,   5,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   5, 

+     66,   0,  16,   0,   0,   0, 

+      0,   0,  10,  16,  16,   0, 

+      1,   0,   0,   0,  54,   0, 

+      0,   5, 130,   0,  16,   0, 

+      0,   0,   0,   0,   1,  64, 

+      0,   0,   0,   0,   0,   0, 

+     45,   0,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,  14,  16,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  26,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,  42,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   3,   0, 

+      0,   0,  58,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,  64,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,  48,  32,   0, 

+      0,   0,   0,   0,   5,   0, 

+      0,   0,   1,  64,   0,   0, 

+      1,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  10, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7,  18,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   6, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  26, 128,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     34,  32,  16,   0,   0,   0, 

+      0,   0,  10,  48,  32,   4, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     42, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7,  66,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  58, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7, 130,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  62,   0,   0,   1, 

+     83,  84,  65,  84, 116,   0, 

+      0,   0,  22,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      6,   0,   0,   0,  10,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      6,   0,   0,   0,   0,   0, 

+      0,   0,   2,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h
new file mode 100644
index 0000000..9de8b28
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h
@@ -0,0 +1,270 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer SwizzleProperties

+// {

+//

+//   uint4 SwizzleIndices;              // Offset:    0 Size:    16

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI2D                       texture   uint4          2d    0        1

+// SwizzleProperties                 cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// TEXCOORD                 0   xy          1     NONE   float   xy  

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_resource_texture2d (uint,uint,uint,uint) t0

+dcl_input_ps linear v1.xy

+dcl_output o0.xyzw

+dcl_temps 1

+dcl_indexableTemp x0[6], 4

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xy, r0.xyxx

+mul r0.xy, r0.xyxx, v1.xyxx

+ftoi r0.xy, r0.xyxx

+mov r0.zw, l(0,0,0,0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov x0[0].x, r0.x

+mov x0[1].x, r0.y

+mov x0[2].x, r0.z

+mov x0[3].x, r0.w

+mov x0[4].x, l(0)

+mov x0[5].x, l(1)

+mov r0.x, cb0[0].x

+mov o0.x, x0[r0.x + 0].x

+mov r0.x, cb0[0].y

+mov o0.y, x0[r0.x + 0].x

+mov r0.x, cb0[0].z

+mov o0.z, x0[r0.x + 0].x

+mov r0.x, cb0[0].w

+mov o0.w, x0[r0.x + 0].x

+ret 

+// Approximately 21 instruction slots used

+#endif

+

+const BYTE g_PS_SwizzleUI2D[] =

+{

+     68,  88,  66,  67, 165, 190, 

+     35, 188, 235, 202, 154, 237, 

+    226,  86, 223, 212,  34,  38, 

+     81, 252,   1,   0,   0,   0, 

+    164,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+     60,   1,   0,   0, 148,   1, 

+      0,   0, 200,   1,   0,   0, 

+     40,   4,   0,   0,  82,  68, 

+     69,  70,   0,   1,   0,   0, 

+      1,   0,   0,   0, 124,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    204,   0,   0,   0,  92,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   4,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+    104,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,  84, 101, 120, 116, 

+    117, 114, 101,  85,  73,  50, 

+     68,   0,  83, 119, 105, 122, 

+    122, 108, 101,  80, 114, 111, 

+    112, 101, 114, 116, 105, 101, 

+    115,   0, 171, 171, 104,   0, 

+      0,   0,   1,   0,   0,   0, 

+    148,   0,   0,   0,  16,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 172,   0, 

+      0,   0,   0,   0,   0,   0, 

+     16,   0,   0,   0,   2,   0, 

+      0,   0, 188,   0,   0,   0, 

+      0,   0,   0,   0,  83, 119, 

+    105, 122, 122, 108, 101,  73, 

+    110, 100, 105,  99, 101, 115, 

+      0, 171,   1,   0,  19,   0, 

+      1,   0,   4,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78,  80,   0,   0,   0, 

+      2,   0,   0,   0,   8,   0, 

+      0,   0,  56,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  68,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,   3,   3, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  84,  69,  88,  67, 

+     79,  79,  82,  68,   0, 171, 

+    171, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82,  88,   2, 

+      0,   0,  64,   0,   0,   0, 

+    150,   0,   0,   0,  89,   0, 

+      0,   4,  70, 142,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  88,  24,   0,   4, 

+      0, 112,  16,   0,   0,   0, 

+      0,   0,  68,  68,   0,   0, 

+     98,  16,   0,   3,  50,  16, 

+     16,   0,   1,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0, 105,   0,   0,   4, 

+      0,   0,   0,   0,   6,   0, 

+      0,   0,   4,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7,  50,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   0,  16,   0,   0,   0, 

+      0,   0,  70,  16,  16,   0, 

+      1,   0,   0,   0,  27,   0, 

+      0,   5,  50,   0,  16,   0, 

+      0,   0,   0,   0,  70,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   8, 194,   0, 

+     16,   0,   0,   0,   0,   0, 

+      2,  64,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,  26,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,  42,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,  58,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,  64, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      5,   0,   0,   0,   1,  64, 

+      0,   0,   1,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     10, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7,  18,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  26, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7,  34,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   6, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  42, 128,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     66,  32,  16,   0,   0,   0, 

+      0,   0,  10,  48,  32,   4, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     58, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7, 130,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,  21,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   6,   0,   0,   0, 

+     10,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   5,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h
new file mode 100644
index 0000000..c668216
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h
@@ -0,0 +1,277 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+//

+// Buffer Definitions: 

+//

+// cbuffer SwizzleProperties

+// {

+//

+//   uint4 SwizzleIndices;              // Offset:    0 Size:    16

+//

+// }

+//

+//

+// Resource Bindings:

+//

+// Name                                 Type  Format         Dim Slot Elements

+// ------------------------------ ---------- ------- ----------- ---- --------

+// TextureUI3D                       texture   uint4          3d    0        1

+// SwizzleProperties                 cbuffer      NA          NA    0        1

+//

+//

+//

+// Input signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_POSITION              0   xyzw        0      POS   float       

+// SV_RENDERTARGETARRAYINDEX     0   x           1  RTINDEX    uint       

+// TEXCOORD                 0   xyz         2     NONE   float   xyz 

+//

+//

+// Output signature:

+//

+// Name                 Index   Mask Register SysValue  Format   Used

+// -------------------- ----- ------ -------- -------- ------- ------

+// SV_TARGET                0   xyzw        0   TARGET    uint   xyzw

+//

+ps_4_0

+dcl_constantbuffer cb0[1], immediateIndexed

+dcl_resource_texture3d (uint,uint,uint,uint) t0

+dcl_input_ps linear v2.xyz

+dcl_output o0.xyzw

+dcl_temps 1

+dcl_indexableTemp x0[6], 4

+resinfo_uint r0.xyzw, l(0), t0.xyzw

+utof r0.xyz, r0.xyzx

+mul r0.xyz, r0.xyzx, v2.xyzx

+ftoi r0.xyz, r0.xyzx

+mov r0.w, l(0)

+ld r0.xyzw, r0.xyzw, t0.xyzw

+mov x0[0].x, r0.x

+mov x0[1].x, r0.y

+mov x0[2].x, r0.z

+mov x0[3].x, r0.w

+mov x0[4].x, l(0)

+mov x0[5].x, l(1)

+mov r0.x, cb0[0].x

+mov o0.x, x0[r0.x + 0].x

+mov r0.x, cb0[0].y

+mov o0.y, x0[r0.x + 0].x

+mov r0.x, cb0[0].z

+mov o0.z, x0[r0.x + 0].x

+mov r0.x, cb0[0].w

+mov o0.w, x0[r0.x + 0].x

+ret 

+// Approximately 21 instruction slots used

+#endif

+

+const BYTE g_PS_SwizzleUI3D[] =

+{

+     68,  88,  66,  67, 186, 124, 

+    222, 110, 186, 145, 165,  56, 

+    152,  97, 247, 114, 115, 197, 

+    159, 190,   1,   0,   0,   0, 

+    200,   4,   0,   0,   5,   0, 

+      0,   0,  52,   0,   0,   0, 

+     60,   1,   0,   0, 196,   1, 

+      0,   0, 248,   1,   0,   0, 

+     76,   4,   0,   0,  82,  68, 

+     69,  70,   0,   1,   0,   0, 

+      1,   0,   0,   0, 124,   0, 

+      0,   0,   2,   0,   0,   0, 

+     28,   0,   0,   0,   0,   4, 

+    255, 255,   0,   1,   0,   0, 

+    204,   0,   0,   0,  92,   0, 

+      0,   0,   2,   0,   0,   0, 

+      4,   0,   0,   0,   8,   0, 

+      0,   0, 255, 255, 255, 255, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  13,   0,   0,   0, 

+    104,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0,  84, 101, 120, 116, 

+    117, 114, 101,  85,  73,  51, 

+     68,   0,  83, 119, 105, 122, 

+    122, 108, 101,  80, 114, 111, 

+    112, 101, 114, 116, 105, 101, 

+    115,   0, 171, 171, 104,   0, 

+      0,   0,   1,   0,   0,   0, 

+    148,   0,   0,   0,  16,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0, 172,   0, 

+      0,   0,   0,   0,   0,   0, 

+     16,   0,   0,   0,   2,   0, 

+      0,   0, 188,   0,   0,   0, 

+      0,   0,   0,   0,  83, 119, 

+    105, 122, 122, 108, 101,  73, 

+    110, 100, 105,  99, 101, 115, 

+      0, 171,   1,   0,  19,   0, 

+      1,   0,   4,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     77, 105,  99, 114, 111, 115, 

+    111, 102, 116,  32,  40,  82, 

+     41,  32,  72,  76,  83,  76, 

+     32,  83, 104,  97, 100, 101, 

+    114,  32,  67, 111, 109, 112, 

+    105, 108, 101, 114,  32,  54, 

+     46,  51,  46,  57,  54,  48, 

+     48,  46,  49,  54,  51,  56, 

+     52,   0, 171, 171,  73,  83, 

+     71,  78, 128,   0,   0,   0, 

+      3,   0,   0,   0,   8,   0, 

+      0,   0,  80,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   3,   0,   0,   0, 

+      0,   0,   0,   0,  15,   0, 

+      0,   0,  92,   0,   0,   0, 

+      0,   0,   0,   0,   4,   0, 

+      0,   0,   1,   0,   0,   0, 

+      1,   0,   0,   0,   1,   0, 

+      0,   0, 118,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   3,   0,   0,   0, 

+      2,   0,   0,   0,   7,   7, 

+      0,   0,  83,  86,  95,  80, 

+     79,  83,  73,  84,  73,  79, 

+     78,   0,  83,  86,  95,  82, 

+     69,  78,  68,  69,  82,  84, 

+     65,  82,  71,  69,  84,  65, 

+     82,  82,  65,  89,  73,  78, 

+     68,  69,  88,   0,  84,  69, 

+     88,  67,  79,  79,  82,  68, 

+      0, 171,  79,  83,  71,  78, 

+     44,   0,   0,   0,   1,   0, 

+      0,   0,   8,   0,   0,   0, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0,  15,   0,   0,   0, 

+     83,  86,  95,  84,  65,  82, 

+     71,  69,  84,   0, 171, 171, 

+     83,  72,  68,  82,  76,   2, 

+      0,   0,  64,   0,   0,   0, 

+    147,   0,   0,   0,  89,   0, 

+      0,   4,  70, 142,  32,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,  88,  40,   0,   4, 

+      0, 112,  16,   0,   0,   0, 

+      0,   0,  68,  68,   0,   0, 

+     98,  16,   0,   3, 114,  16, 

+     16,   0,   2,   0,   0,   0, 

+    101,   0,   0,   3, 242,  32, 

+     16,   0,   0,   0,   0,   0, 

+    104,   0,   0,   2,   1,   0, 

+      0,   0, 105,   0,   0,   4, 

+      0,   0,   0,   0,   6,   0, 

+      0,   0,   4,   0,   0,   0, 

+     61,  16,   0,   7, 242,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  70, 126,  16,   0, 

+      0,   0,   0,   0,  86,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     56,   0,   0,   7, 114,   0, 

+     16,   0,   0,   0,   0,   0, 

+     70,   2,  16,   0,   0,   0, 

+      0,   0,  70,  18,  16,   0, 

+      2,   0,   0,   0,  27,   0, 

+      0,   5, 114,   0,  16,   0, 

+      0,   0,   0,   0,  70,   2, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   5, 130,   0, 

+     16,   0,   0,   0,   0,   0, 

+      1,  64,   0,   0,   0,   0, 

+      0,   0,  45,   0,   0,   7, 

+    242,   0,  16,   0,   0,   0, 

+      0,   0,  70,  14,  16,   0, 

+      0,   0,   0,   0,  70, 126, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      1,   0,   0,   0,  26,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      2,   0,   0,   0,  42,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      3,   0,   0,   0,  58,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      4,   0,   0,   0,   1,  64, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,  48, 

+     32,   0,   0,   0,   0,   0, 

+      5,   0,   0,   0,   1,  64, 

+      0,   0,   1,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     10, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7,  18,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   6,  18,   0,  16,   0, 

+      0,   0,   0,   0,  26, 128, 

+     32,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,  54,   0, 

+      0,   7,  34,  32,  16,   0, 

+      0,   0,   0,   0,  10,  48, 

+     32,   4,   0,   0,   0,   0, 

+     10,   0,  16,   0,   0,   0, 

+      0,   0,  54,   0,   0,   6, 

+     18,   0,  16,   0,   0,   0, 

+      0,   0,  42, 128,  32,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,  54,   0,   0,   7, 

+     66,  32,  16,   0,   0,   0, 

+      0,   0,  10,  48,  32,   4, 

+      0,   0,   0,   0,  10,   0, 

+     16,   0,   0,   0,   0,   0, 

+     54,   0,   0,   6,  18,   0, 

+     16,   0,   0,   0,   0,   0, 

+     58, 128,  32,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+     54,   0,   0,   7, 130,  32, 

+     16,   0,   0,   0,   0,   0, 

+     10,  48,  32,   4,   0,   0, 

+      0,   0,  10,   0,  16,   0, 

+      0,   0,   0,   0,  62,   0, 

+      0,   1,  83,  84,  65,  84, 

+    116,   0,   0,   0,  21,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   6,   0,   0,   0, 

+     10,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   5,   0,   0,   0, 

+      0,   0,   0,   0,   2,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0, 

+      0,   0,   0,   0,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat
new file mode 100644
index 0000000..3426bdb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat
@@ -0,0 +1,133 @@
+@ECHO OFF

+REM

+REM Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.

+REM Use of this source code is governed by a BSD-style license that can be

+REM found in the LICENSE file.

+REM

+

+PATH %PATH%;%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86;%DXSDK_DIR%\Utilities\bin\x86

+

+setlocal

+set errorCount=0

+set successCount=0

+set debug=0

+

+if "%1" == "debug" (

+    set debug=1

+)

+if "%1" == "release" (

+    set debug=0

+)

+

+:: Shaders for OpenGL ES 2.0 and OpenGL ES 3.0+

+::              | Input file         | Entry point            | Type            | Output file                        | Debug |

+call:BuildShader Passthrough2D11.hlsl VS_Passthrough2D         vs_4_0_level_9_3  compiled\passthrough2d11vs.h         %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBA2D     ps_4_0_level_9_3  compiled\passthroughrgba2d11ps.h     %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBA2DMS   ps_4_1            compiled\passthroughrgba2dms11ps.h   %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGB2D      ps_4_0_level_9_3  compiled\passthroughrgb2d11ps.h      %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRG2D       ps_4_0_level_9_3  compiled\passthroughrg2d11ps.h       %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughR2D        ps_4_0_level_9_3  compiled\passthroughr2d11ps.h        %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughLum2D      ps_4_0_level_9_3  compiled\passthroughlum2d11ps.h      %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughLumAlpha2D ps_4_0_level_9_3  compiled\passthroughlumalpha2d11ps.h %debug%

+

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBAPremultiply2D ps_4_0_level_9_3 compiled\passthroughrgbapremultiply2d11ps.h %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBAUnmultiply2D  ps_4_0_level_9_3 compiled\passthroughrgbaunmultiply2d11ps.h  %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBPremultiply2D  ps_4_0_level_9_3 compiled\passthroughrgbpremultiply2d11ps.h  %debug%

+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBUnmultiply2D   ps_4_0_level_9_3 compiled\passthroughrgbunmultiply2d11ps.h   %debug%

+

+call:BuildShader Clear11.hlsl           VS_Clear_FL9             vs_4_0_level_9_3  compiled\clear11_fl9vs.h             %debug%

+call:BuildShader Clear11.hlsl           PS_ClearFloat_FL9        ps_4_0_level_9_3  compiled\clearfloat11_fl9ps.h        %debug%

+

+call:BuildShader Clear11.hlsl           VS_Clear                 vs_4_0            compiled\clear11vs.h                 %debug%

+call:BuildShader Clear11.hlsl           PS_ClearFloat            ps_4_0            compiled\clearfloat11ps.h            %debug%

+

+:: Shaders for OpenGL ES 3.0+ only

+::              | Input file               | Entry point            | Type   | Output file                        | Debug |

+call:BuildShader Passthrough2D11.hlsl       PS_PassthroughDepth2D    ps_4_0   compiled\passthroughdepth2d11ps.h    %debug%

+call:BuildShader Passthrough2D11.hlsl       PS_PassthroughRGBA2DUI   ps_4_0   compiled\passthroughrgba2dui11ps.h   %debug%

+call:BuildShader Passthrough2D11.hlsl       PS_PassthroughRGBA2DI    ps_4_0   compiled\passthroughrgba2di11ps.h    %debug%

+call:BuildShader Passthrough2D11.hlsl       PS_PassthroughRGB2DUI    ps_4_0   compiled\passthroughrgb2dui11ps.h    %debug%

+call:BuildShader Passthrough2D11.hlsl       PS_PassthroughRGB2DI     ps_4_0   compiled\passthroughrgb2di11ps.h     %debug%

+call:BuildShader Passthrough2D11.hlsl       PS_PassthroughRG2DUI     ps_4_0   compiled\passthroughrg2dui11ps.h     %debug%

+call:BuildShader Passthrough2D11.hlsl       PS_PassthroughRG2DI      ps_4_0   compiled\passthroughrg2di11ps.h      %debug%

+call:BuildShader Passthrough2D11.hlsl       PS_PassthroughR2DUI      ps_4_0   compiled\passthroughr2dui11ps.h      %debug%

+call:BuildShader Passthrough2D11.hlsl       PS_PassthroughR2DI       ps_4_0   compiled\passthroughr2di11ps.h       %debug%

+

+call:BuildShader Passthrough3D11.hlsl       VS_Passthrough3D         vs_4_0   compiled\passthrough3d11vs.h         %debug%

+call:BuildShader Passthrough3D11.hlsl       GS_Passthrough3D         gs_4_0   compiled\passthrough3d11gs.h         %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughRGBA3D     ps_4_0   compiled\passthroughrgba3d11ps.h     %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughRGBA3DUI   ps_4_0   compiled\passthroughrgba3dui11ps.h   %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughRGBA3DI    ps_4_0   compiled\passthroughrgba3di11ps.h    %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughRGB3D      ps_4_0   compiled\passthroughrgb3d11ps.h      %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughRGB3DUI    ps_4_0   compiled\passthroughrgb3dui11ps.h    %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughRGB3DI     ps_4_0   compiled\passthroughrgb3di11ps.h     %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughRG3D       ps_4_0   compiled\passthroughrg3d11ps.h       %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughRG3DUI     ps_4_0   compiled\passthroughrg3dui11ps.h     %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughRG3DI      ps_4_0   compiled\passthroughrg3di11ps.h      %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughR3D        ps_4_0   compiled\passthroughr3d11ps.h        %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughR3DUI      ps_4_0   compiled\passthroughr3dui11ps.h      %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughR3DI       ps_4_0   compiled\passthroughr3di11ps.h       %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughLum3D      ps_4_0   compiled\passthroughlum3d11ps.h      %debug%

+call:BuildShader Passthrough3D11.hlsl       PS_PassthroughLumAlpha3D ps_4_0   compiled\passthroughlumalpha3d11ps.h %debug%

+

+call:BuildShader Swizzle11.hlsl             PS_SwizzleF2D            ps_4_0   compiled\swizzlef2dps.h              %debug%

+call:BuildShader Swizzle11.hlsl             PS_SwizzleI2D            ps_4_0   compiled\swizzlei2dps.h              %debug%

+call:BuildShader Swizzle11.hlsl             PS_SwizzleUI2D           ps_4_0   compiled\swizzleui2dps.h             %debug%

+

+call:BuildShader Swizzle11.hlsl             PS_SwizzleF3D            ps_4_0   compiled\swizzlef3dps.h              %debug%

+call:BuildShader Swizzle11.hlsl             PS_SwizzleI3D            ps_4_0   compiled\swizzlei3dps.h              %debug%

+call:BuildShader Swizzle11.hlsl             PS_SwizzleUI3D           ps_4_0   compiled\swizzleui3dps.h             %debug%

+

+call:BuildShader Swizzle11.hlsl             PS_SwizzleF2DArray       ps_4_0   compiled\swizzlef2darrayps.h         %debug%

+call:BuildShader Swizzle11.hlsl             PS_SwizzleI2DArray       ps_4_0   compiled\swizzlei2darrayps.h         %debug%

+call:BuildShader Swizzle11.hlsl             PS_SwizzleUI2DArray      ps_4_0   compiled\swizzleui2darrayps.h        %debug%

+

+call:BuildShader Clear11.hlsl               PS_ClearUint             ps_4_0   compiled\clearuint11ps.h             %debug%

+call:BuildShader Clear11.hlsl               PS_ClearSint             ps_4_0   compiled\clearsint11ps.h             %debug%

+

+call:BuildShader BufferToTexture11.hlsl     VS_BufferToTexture       vs_4_0   compiled/buffertotexture11_vs.h      %debug%

+call:BuildShader BufferToTexture11.hlsl     GS_BufferToTexture       gs_4_0   compiled/buffertotexture11_gs.h      %debug%

+call:BuildShader BufferToTexture11.hlsl     PS_BufferToTexture_4F    ps_4_0   compiled/buffertotexture11_ps_4f.h   %debug%

+call:BuildShader BufferToTexture11.hlsl     PS_BufferToTexture_4I    ps_4_0   compiled/buffertotexture11_ps_4i.h   %debug%

+call:BuildShader BufferToTexture11.hlsl     PS_BufferToTexture_4UI   ps_4_0   compiled/buffertotexture11_ps_4ui.h  %debug%

+

+call:BuildShader ResolveDepthStencil.hlsl   VS_ResolveDepthStencil   vs_4_1   compiled/resolvedepthstencil11_vs.h  %debug%

+call:BuildShader ResolveDepthStencil.hlsl   PS_ResolveDepth          ps_4_1   compiled/resolvedepth11_ps.h         %debug%

+call:BuildShader ResolveDepthStencil.hlsl   PS_ResolveDepthStencil   ps_4_1   compiled/resolvedepthstencil11_ps.h  %debug%

+call:BuildShader ResolveDepthStencil.hlsl   PS_ResolveStencil        ps_4_1   compiled/resolvestencil11_ps.h       %debug%

+

+echo.

+

+if %successCount% GTR 0 (

+   echo %successCount% shaders compiled successfully.

+)

+if %errorCount% GTR 0 (

+   echo There were %errorCount% shader compilation errors.

+)

+

+endlocal

+exit /b

+

+:BuildShader

+set input=%~1

+set entry=%~2

+set type=%~3

+set output=%~4

+set debug=%~5

+

+if %debug% == 0 (

+    set "buildCMD=fxc /nologo /E %entry% /T %type% /Fh %output% %input%"

+) else (

+    set "buildCMD=fxc /nologo /Zi /Od /E %entry% /T %type% /Fh %output% %input%"

+)

+

+set error=0

+%buildCMD% || set error=1

+

+if %error% == 0 (

+    set /a successCount=%successCount%+1

+) else (

+    set /a errorCount=%errorCount%+1

+)

+

+exit /b

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
new file mode 100644
index 0000000..6d481ec
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
@@ -0,0 +1,514 @@
+{
+  "NONE": {
+  },
+  "A8_UNORM": {
+    "texFormat": "DXGI_FORMAT_A8_UNORM",
+    "srvFormat": "DXGI_FORMAT_A8_UNORM",
+    "rtvFormat": "DXGI_FORMAT_A8_UNORM",
+    "channels": "a",
+    "componentType": "unorm",
+    "bits": { "alpha": 8 },
+    "supportTest": "OnlyFL10Plus(deviceCaps)",
+    "fallbackFormat": "R8G8B8A8_UNORM"
+  },
+  "R8G8B8A8_UNORM": {
+    "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+    "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+    "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+    "glInternalFormat": "GL_RGBA8"
+  },
+  "R16G16B16A16_UNORM": {
+    "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+    "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+    "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+    "glInternalFormat": "GL_RGBA16_EXT"
+  },
+  "R16G16B16A16_FLOAT": {
+    "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+    "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+    "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+    "channels": "rgba",
+    "componentType": "float",
+    "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+    "glInternalFormat": "GL_RGBA16F"
+  },
+  "R32G32B32A32_FLOAT": {
+    "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+    "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+    "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+    "channels": "rgba",
+    "componentType": "float",
+    "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 },
+    "glInternalFormat": "GL_RGBA32F"
+  },
+  "B8G8R8A8_UNORM": {
+    "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+    "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+    "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+    "channels": "bgra",
+    "componentType": "unorm",
+    "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+    "glInternalFormat": "GL_BGRA8_EXT"
+  },
+  "BC1_RGBA_UNORM_BLOCK": {
+    "texFormat": "DXGI_FORMAT_BC1_UNORM",
+    "srvFormat": "DXGI_FORMAT_BC1_UNORM",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "swizzleFormat": "GL_RGBA8"
+  },
+  "BC1_RGB_UNORM_BLOCK": {
+    "texFormat": "DXGI_FORMAT_BC1_UNORM",
+    "srvFormat": "DXGI_FORMAT_BC1_UNORM",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "swizzleFormat": "GL_RGBA8"
+  },
+  "BC2_RGBA_UNORM_BLOCK": {
+    "texFormat": "DXGI_FORMAT_BC2_UNORM",
+    "srvFormat": "DXGI_FORMAT_BC2_UNORM",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "swizzleFormat": "GL_RGBA8"
+  },
+  "BC3_RGBA_UNORM_BLOCK": {
+    "texFormat": "DXGI_FORMAT_BC3_UNORM",
+    "srvFormat": "DXGI_FORMAT_BC3_UNORM",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "swizzleFormat": "GL_RGBA8"
+  },
+  "BC1_RGBA_UNORM_SRGB_BLOCK": {
+    "texFormat": "DXGI_FORMAT_BC1_UNORM_SRGB",
+    "srvFormat": "DXGI_FORMAT_BC1_UNORM_SRGB",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "swizzleFormat": "GL_RGBA8"
+  },
+  "BC1_RGB_UNORM_SRGB_BLOCK": {
+    "texFormat": "DXGI_FORMAT_BC1_UNORM_SRGB",
+    "srvFormat": "DXGI_FORMAT_BC1_UNORM_SRGB",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "swizzleFormat": "GL_RGBA8"
+  },
+  "BC2_RGBA_UNORM_SRGB_BLOCK": {
+    "texFormat": "DXGI_FORMAT_BC2_UNORM_SRGB",
+    "srvFormat": "DXGI_FORMAT_BC2_UNORM_SRGB",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "swizzleFormat": "GL_RGBA8"
+  },
+  "BC3_RGBA_UNORM_SRGB_BLOCK": {
+    "texFormat": "DXGI_FORMAT_BC3_UNORM_SRGB",
+    "srvFormat": "DXGI_FORMAT_BC3_UNORM_SRGB",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "swizzleFormat": "GL_RGBA8"
+  },
+  "D24_UNORM_S8_UINT": {
+    "FL10Plus": {
+      "texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
+      "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS"
+    },
+    "FL9_3": {
+      "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT"
+    },
+    "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+    "channels": "ds",
+    "bits": { "depth": 24, "stencil": 8 },
+    "glInternalFormat": "GL_DEPTH24_STENCIL8_OES"
+  },
+  "D32_FLOAT_S8X24_UINT": {
+    "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS",
+    "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
+    "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
+    "channels": "ds",
+    "bits": { "depth": 32, "stencil": 8 },
+    "glInternalFormat": "GL_DEPTH32F_STENCIL8"
+  },
+  "D16_UNORM": {
+    "FL10Plus": {
+      "texFormat": "DXGI_FORMAT_R16_TYPELESS",
+      "srvFormat": "DXGI_FORMAT_R16_UNORM"
+    },
+    "FL9_3": {
+      "texFormat": "DXGI_FORMAT_D16_UNORM"
+    },
+    "dsvFormat": "DXGI_FORMAT_D16_UNORM",
+    "channels": "d",
+    "componentType": "unorm",
+    "bits": { "depth": 16 },
+    "glInternalFormat": "GL_DEPTH_COMPONENT16"
+  },
+  "D32_FLOAT": {
+    "texFormat": "DXGI_FORMAT_R32_TYPELESS",
+    "srvFormat": "DXGI_FORMAT_R32_FLOAT",
+    "dsvFormat": "DXGI_FORMAT_D32_FLOAT",
+    "channels": "d",
+    "componentType": "float",
+    "bits": { "depth": 32 },
+    "glInternalFormat": "GL_DEPTH_COMPONENT32F"
+  },
+  "R11G11B10_FLOAT": {
+    "texFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+    "srvFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+    "rtvFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+    "channels": "rgb",
+    "componentType":  "float",
+    "bits": { "red": 11, "green": 11, "blue": 10 },
+    "glInternalFormat": "GL_R11F_G11F_B10F"
+  },
+  "R16_FLOAT": {
+    "texFormat": "DXGI_FORMAT_R16_FLOAT",
+    "srvFormat": "DXGI_FORMAT_R16_FLOAT",
+    "rtvFormat": "DXGI_FORMAT_R16_FLOAT",
+    "channels": "r",
+    "componentType": "float",
+    "bits": { "red": 16 },
+    "glInternalFormat": "GL_R16F"
+  },
+  "R16_SINT": {
+    "texFormat": "DXGI_FORMAT_R16_SINT",
+    "srvFormat": "DXGI_FORMAT_R16_SINT",
+    "rtvFormat": "DXGI_FORMAT_R16_SINT",
+    "channels": "r",
+    "componentType": "int",
+    "bits": { "red": 16 },
+    "glInternalFormat": "GL_R16I"
+  },
+  "R16_UINT": {
+    "texFormat": "DXGI_FORMAT_R16_UINT",
+    "srvFormat": "DXGI_FORMAT_R16_UINT",
+    "rtvFormat": "DXGI_FORMAT_R16_UINT",
+    "channels": "r",
+    "componentType": "uint",
+    "bits": { "red": 16 },
+    "glInternalFormat": "GL_R16UI"
+  },
+  "R32_FLOAT": {
+    "texFormat": "DXGI_FORMAT_R32_FLOAT",
+    "srvFormat": "DXGI_FORMAT_R32_FLOAT",
+    "rtvFormat": "DXGI_FORMAT_R32_FLOAT",
+    "channels": "r",
+    "componentType": "float",
+    "bits": { "red": 32 },
+    "glInternalFormat": "GL_R32F"
+  },
+  "R32_SINT": {
+    "texFormat": "DXGI_FORMAT_R32_SINT",
+    "srvFormat": "DXGI_FORMAT_R32_SINT",
+    "rtvFormat": "DXGI_FORMAT_R32_SINT",
+    "channels": "r",
+    "componentType": "int",
+    "bits": { "red": 32 },
+    "glInternalFormat": "GL_R32I"
+  },
+  "R32_UINT": {
+    "texFormat": "DXGI_FORMAT_R32_UINT",
+    "srvFormat": "DXGI_FORMAT_R32_UINT",
+    "rtvFormat": "DXGI_FORMAT_R32_UINT",
+    "channels": "r",
+    "componentType": "uint",
+    "bits": { "red": 32 },
+    "glInternalFormat": "GL_R32UI"
+  },
+  "R8_UNORM": {
+    "texFormat": "DXGI_FORMAT_R8_UNORM",
+    "srvFormat": "DXGI_FORMAT_R8_UNORM",
+    "rtvFormat": "DXGI_FORMAT_R8_UNORM",
+    "channels": "r",
+    "componentType": "unorm",
+    "bits": { "red": 8 },
+    "glInternalFormat": "GL_R8"
+  },
+  "R8_SINT": {
+    "texFormat": "DXGI_FORMAT_R8_SINT",
+    "srvFormat": "DXGI_FORMAT_R8_SINT",
+    "rtvFormat": "DXGI_FORMAT_R8_SINT",
+    "channels": "r",
+    "componentType": "int",
+    "bits": { "red": 8 },
+    "glInternalFormat": "GL_R8I"
+  },
+  "R8_UINT": {
+    "texFormat": "DXGI_FORMAT_R8_UINT",
+    "srvFormat": "DXGI_FORMAT_R8_UINT",
+    "rtvFormat": "DXGI_FORMAT_R8_UINT",
+    "channels": "r",
+    "componentType": "uint",
+    "bits": { "red": 8 },
+    "glInternalFormat": "GL_R8UI"
+  },
+  "R8_SNORM": {
+    "texFormat": "DXGI_FORMAT_R8_SNORM",
+    "srvFormat": "DXGI_FORMAT_R8_SNORM",
+    "channels": "r",
+    "componentType": "snorm",
+    "bits": { "red": 8 },
+    "glInternalFormat": "GL_R8_SNORM"
+  },
+  "R16G16_FLOAT": {
+    "texFormat": "DXGI_FORMAT_R16G16_FLOAT",
+    "srvFormat": "DXGI_FORMAT_R16G16_FLOAT",
+    "rtvFormat": "DXGI_FORMAT_R16G16_FLOAT",
+    "channels": "rg",
+    "componentType": "float",
+    "bits": { "red": 16, "green": 16 },
+    "glInternalFormat": "GL_RG16F"
+  },
+  "R16G16_SINT": {
+    "texFormat": "DXGI_FORMAT_R16G16_SINT",
+    "srvFormat": "DXGI_FORMAT_R16G16_SINT",
+    "rtvFormat": "DXGI_FORMAT_R16G16_SINT",
+    "channels": "rg",
+    "componentType": "int",
+    "bits": { "red": 16, "green": 16 },
+    "glInternalFormat": "GL_RG16I"
+  },
+  "R16G16_UINT": {
+    "texFormat": "DXGI_FORMAT_R16G16_UINT",
+    "srvFormat": "DXGI_FORMAT_R16G16_UINT",
+    "rtvFormat": "DXGI_FORMAT_R16G16_UINT",
+    "channels": "rg",
+    "componentType": "uint",
+    "bits": { "red": 16, "green": 16 },
+    "glInternalFormat": "GL_RG16UI"
+  },
+  "R32G32_FLOAT": {
+    "texFormat": "DXGI_FORMAT_R32G32_FLOAT",
+    "srvFormat": "DXGI_FORMAT_R32G32_FLOAT",
+    "rtvFormat": "DXGI_FORMAT_R32G32_FLOAT",
+    "channels": "rg",
+    "componentType": "float",
+    "bits": { "red": 32, "green": 32 },
+    "glInternalFormat": "GL_RG32F"
+  },
+  "R32G32_SINT": {
+    "texFormat": "DXGI_FORMAT_R32G32_SINT",
+    "srvFormat": "DXGI_FORMAT_R32G32_SINT",
+    "rtvFormat": "DXGI_FORMAT_R32G32_SINT",
+    "channels": "rg",
+    "componentType": "int",
+    "bits": { "red": 32, "green": 32 },
+    "glInternalFormat": "GL_RG32I"
+  },
+  "R32G32_UINT": {
+    "texFormat": "DXGI_FORMAT_R32G32_UINT",
+    "srvFormat": "DXGI_FORMAT_R32G32_UINT",
+    "rtvFormat": "DXGI_FORMAT_R32G32_UINT",
+    "channels": "rg",
+    "componentType": "uint",
+    "bits": { "red": 32, "green": 32 },
+    "glInternalFormat": "GL_RG32UI"
+  },
+  "R8G8_UNORM": {
+    "texFormat": "DXGI_FORMAT_R8G8_UNORM",
+    "srvFormat": "DXGI_FORMAT_R8G8_UNORM",
+    "rtvFormat": "DXGI_FORMAT_R8G8_UNORM",
+    "channels": "rg",
+    "componentType": "unorm",
+    "bits": { "red": 8, "green": 8 },
+    "glInternalFormat": "GL_RG8"
+  },
+  "R8G8_SINT": {
+    "texFormat": "DXGI_FORMAT_R8G8_SINT",
+    "srvFormat": "DXGI_FORMAT_R8G8_SINT",
+    "rtvFormat": "DXGI_FORMAT_R8G8_SINT",
+    "channels": "rg",
+    "componentType": "int",
+    "bits": { "red": 8, "green": 8 },
+    "glInternalFormat": "GL_RG8I"
+  },
+  "R8G8_UINT": {
+    "texFormat": "DXGI_FORMAT_R8G8_UINT",
+    "srvFormat": "DXGI_FORMAT_R8G8_UINT",
+    "rtvFormat": "DXGI_FORMAT_R8G8_UINT",
+    "channels": "rg",
+    "componentType": "uint",
+    "bits": { "red": 8, "green": 8 },
+    "glInternalFormat": "GL_RG8UI"
+  },
+  "R8G8_SNORM": {
+    "texFormat": "DXGI_FORMAT_R8G8_SNORM",
+    "srvFormat": "DXGI_FORMAT_R8G8_SNORM",
+    "channels": "rg",
+    "componentType": "snorm",
+    "bits": { "red": 8, "green": 8 },
+    "glInternalFormat": "GL_RG8_SNORM"
+  },
+  "R10G10B10A2_UNORM": {
+    "texFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+    "srvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+    "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 },
+    "glInternalFormat": "GL_RGB10_A2"
+  },
+  "R10G10B10A2_UINT": {
+    "texFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+    "srvFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+    "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+    "channels": "rgba",
+    "componentType": "uint",
+    "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 },
+    "glInternalFormat": "GL_RGB10_A2UI"
+  },
+  "R16G16B16A16_SINT": {
+    "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+    "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+    "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+    "channels": "rgba",
+    "componentType": "int",
+    "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+    "glInternalFormat": "GL_RGBA16I"
+  },
+  "R16G16B16A16_UINT": {
+    "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+    "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+    "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+    "channels": "rgba",
+    "componentType": "uint",
+    "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+    "glInternalFormat": "GL_RGBA16UI"
+  },
+  "R32G32B32A32_SINT": {
+    "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+    "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+    "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+    "channels": "rgba",
+    "componentType": "int",
+    "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 },
+    "glInternalFormat": "GL_RGBA32I"
+  },
+  "R32G32B32A32_UINT": {
+    "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+    "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+    "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+    "channels": "rgba",
+    "componentType": "uint",
+    "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 },
+    "glInternalFormat": "GL_RGBA32UI"
+  },
+  "B5G6R5_UNORM": {
+    "texFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+    "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+    "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+    "channels": "bgr",
+    "componentType":  "unorm",
+    "bits": { "red": 5, "green": 6, "blue": 5 },
+    "supportTest": "SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)",
+    "fallbackFormat": "R8G8B8A8_UNORM"
+  },
+  "B5G5R5A1_UNORM": {
+    "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+    "srvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+    "rtvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+    "channels": "bgra",
+    "componentType": "unorm",
+    "bits": { "red": 5, "green": 5, "blue": 5, "alpha": 1 },
+    "supportTest": "SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps)",
+    "fallbackFormat": "R8G8B8A8_UNORM"
+  },
+  "R8G8B8A8_SINT": {
+    "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+    "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+    "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+    "channels": "rgba",
+    "componentType": "int",
+    "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+    "glInternalFormat": "GL_RGBA8I"
+  },
+  "R8G8B8A8_UINT": {
+    "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+    "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+    "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+    "channels": "rgba",
+    "componentType": "uint",
+    "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+    "glInternalFormat": "GL_RGBA8UI"
+  },
+  "R8G8B8A8_SNORM": {
+    "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+    "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+    "channels": "rgba",
+    "componentType": "snorm",
+    "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+    "glInternalFormat": "GL_RGBA8_SNORM"
+  },
+  "R9G9B9E5_SHAREDEXP": {
+    "texFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+    "srvFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+    "channels": "rgb",
+    "componentType":  "float",
+    "bits": { "red": 9, "green": 9, "blue": 9, "shared": 5 }
+  },
+  "B4G4R4A4_UNORM": {
+    "texFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+    "srvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+    "rtvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+    "channels": "bgra",
+    "componentType":  "unorm",
+    "bits": { "red": 4, "green": 4, "blue": 4, "alpha": 4 },
+    "supportTest": "SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps)",
+    "fallbackFormat": "R8G8B8A8_UNORM"
+  },
+  "R8G8B8A8_UNORM_SRGB": {
+    "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+    "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+    "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+    "channels": "rgba",
+    "componentType": "unorm",
+    "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+    "glInternalFormat": "GL_SRGB8_ALPHA8"
+  },
+  "R16_UNORM": {
+    "texFormat": "DXGI_FORMAT_R16_UNORM",
+    "srvFormat": "DXGI_FORMAT_R16_UNORM",
+    "rtvFormat": "DXGI_FORMAT_R16_UNORM",
+    "channels": "r",
+    "componentType": "unorm",
+    "bits": { "red": 16 },
+    "glInternalFormat": "GL_R16_EXT"
+  },
+  "R16G16_UNORM": {
+    "texFormat": "DXGI_FORMAT_R16G16_UNORM",
+    "srvFormat": "DXGI_FORMAT_R16G16_UNORM",
+    "rtvFormat": "DXGI_FORMAT_R16G16_UNORM",
+    "channels": "rg",
+    "componentType": "unorm",
+    "bits": { "red": 16, "green": 16 },
+    "glInternalFormat": "GL_RG16_EXT"
+  },
+  "R16_SNORM": {
+    "texFormat": "DXGI_FORMAT_R16_SNORM",
+    "srvFormat": "DXGI_FORMAT_R16_SNORM",
+    "channels": "r",
+    "componentType": "snorm",
+    "bits": { "red": 16 },
+    "glInternalFormat": "GL_R16_SNORM_EXT"
+  },
+  "R16G16_SNORM": {
+    "texFormat": "DXGI_FORMAT_R16G16_SNORM",
+    "srvFormat": "DXGI_FORMAT_R16G16_SNORM",
+    "channels": "rg",
+    "componentType": "snorm",
+    "bits": { "red": 16, "green": 16 },
+    "glInternalFormat": "GL_RG16_SNORM_EXT"
+  },
+  "R16G16B16A16_SNORM": {
+    "texFormat": "DXGI_FORMAT_R16G16B16A16_SNORM",
+    "srvFormat": "DXGI_FORMAT_R16G16B16A16_SNORM",
+    "channels": "rgba",
+    "componentType": "snorm",
+    "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+    "glInternalFormat": "GL_RGBA16_SNORM_EXT"
+  }
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
new file mode 100644
index 0000000..932214e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
@@ -0,0 +1,77 @@
+{
+  "GL_ALPHA16F_EXT": "R16G16B16A16_FLOAT",
+  "GL_ALPHA32F_EXT": "R32G32B32A32_FLOAT",
+  "GL_BGR5_A1_ANGLEX": "B8G8R8A8_UNORM",
+  "GL_BGRA4_ANGLEX": "B8G8R8A8_UNORM",
+  "GL_COMPRESSED_R11_EAC": "R8_UNORM",
+  "GL_COMPRESSED_RG11_EAC": "R8G8_UNORM",
+  "GL_COMPRESSED_RGB8_ETC2": "R8G8B8A8_UNORM",
+  "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM",
+  "GL_COMPRESSED_RGBA8_ETC2_EAC": "R8G8B8A8_UNORM",
+  "GL_COMPRESSED_RGBA_ASTC_4x4_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_5x4_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_5x5_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_6x5_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_6x6_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_8x5_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_8x6_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_8x8_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_10x5_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_10x6_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_10x8_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_10x10_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_12x10_KHR": "NONE",
+  "GL_COMPRESSED_RGBA_ASTC_12x12_KHR": "NONE",
+  "GL_COMPRESSED_SIGNED_R11_EAC": "R8_SNORM",
+  "GL_COMPRESSED_SIGNED_RG11_EAC": "R8G8_SNORM",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR": "NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": "R8G8B8A8_UNORM_SRGB",
+  "GL_COMPRESSED_SRGB8_ETC2": "R8G8B8A8_UNORM_SRGB",
+  "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM_SRGB",
+  "GL_DEPTH_COMPONENT24": "D24_UNORM_S8_UINT",
+  "GL_DEPTH_COMPONENT32_OES": "D24_UNORM_S8_UINT",
+  "GL_ETC1_RGB8_OES": "R8G8B8A8_UNORM",
+  "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": "BC1_RGB_UNORM_BLOCK",
+  "GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_BLOCK",
+  "GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_SRGB_BLOCK",
+  "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_BLOCK",
+  "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_SRGB_BLOCK",
+  "GL_LUMINANCE16F_EXT": "R16G16B16A16_FLOAT",
+  "GL_LUMINANCE32F_EXT": "R32G32B32A32_FLOAT",
+  "GL_LUMINANCE8_ALPHA8_EXT": "R8G8B8A8_UNORM",
+  "GL_LUMINANCE8_EXT": "R8G8B8A8_UNORM",
+  "GL_LUMINANCE_ALPHA16F_EXT": "R16G16B16A16_FLOAT",
+  "GL_LUMINANCE_ALPHA32F_EXT": "R32G32B32A32_FLOAT",
+  "GL_RGB": "R8G8B8A8_UNORM",
+  "GL_RGB16F": "R16G16B16A16_FLOAT",
+  "GL_RGB16I": "R16G16B16A16_SINT",
+  "GL_RGB16UI": "R16G16B16A16_UINT",
+  "GL_RGB565": "B5G6R5_UNORM",
+  "GL_RGB5_A1": "B5G5R5A1_UNORM",
+  "GL_RGB8": "R8G8B8A8_UNORM",
+  "GL_RGB8I": "R8G8B8A8_SINT",
+  "GL_RGB8UI": "R8G8B8A8_UINT",
+  "GL_RGB8_SNORM": "R8G8B8A8_SNORM",
+  "GL_RGBA4": "B4G4R4A4_UNORM",
+  "GL_SRGB8": "R8G8B8A8_UNORM_SRGB",
+  "GL_STENCIL_INDEX8": "D24_UNORM_S8_UINT",
+  "GL_RGB16_EXT": "R16G16B16A16_UNORM",
+  "GL_RGBA16_EXT": "R16G16B16A16_UNORM",
+  "GL_RGB16_SNORM_EXT": "R16G16B16A16_SNORM",
+  "GL_RGB32F": "R32G32B32A32_FLOAT",
+  "GL_RGB32I": "R32G32B32A32_SINT",
+  "GL_RGB32UI": "R32G32B32A32_UINT"
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
new file mode 100644
index 0000000..a9dfec5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 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.
+//
+// Helper routines for the D3D11 texture format table.
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include "libANGLE/renderer/load_functions_table.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+const Format &Format::getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const
+{
+    return (swizzleFormat == internalFormat ? *this : Format::Get(swizzleFormat, deviceCaps));
+}
+
+LoadFunctionMap Format::getLoadFunctions() const
+{
+    return GetLoadFunctionsMap(internalFormat, formatID);
+}
+
+const angle::Format &Format::format() const
+{
+    return angle::Format::Get(formatID);
+}
+
+}  // namespace d3d11
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
new file mode 100644
index 0000000..3efcb81
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
@@ -0,0 +1,105 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// texture_format_table:
+//   Queries for full textureFormat information based on internalFormat
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
+
+#include <map>
+
+#include "common/angleutils.h"
+#include "common/platform.h"
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+
+namespace rx
+{
+
+struct Renderer11DeviceCaps;
+
+namespace d3d11
+{
+
+// For sized GL internal formats, there are several possible corresponding D3D11 formats depending
+// on device capabilities.
+// This structure allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and
+// DSVs given a GL internal format.
+struct Format final : private angle::NonCopyable
+{
+    constexpr Format();
+    constexpr Format(GLenum internalFormat,
+                     angle::Format::ID formatID,
+                     DXGI_FORMAT texFormat,
+                     DXGI_FORMAT srvFormat,
+                     DXGI_FORMAT rtvFormat,
+                     DXGI_FORMAT dsvFormat,
+                     DXGI_FORMAT blitSRVFormat,
+                     GLenum swizzleFormat,
+                     InitializeTextureDataFunction internalFormatInitializer);
+
+    static const Format &Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps);
+
+    const Format &getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const;
+    LoadFunctionMap getLoadFunctions() const;
+    const angle::Format &format() const;
+
+    GLenum internalFormat;
+    angle::Format::ID formatID;
+
+    DXGI_FORMAT texFormat;
+    DXGI_FORMAT srvFormat;
+    DXGI_FORMAT rtvFormat;
+    DXGI_FORMAT dsvFormat;
+
+    DXGI_FORMAT blitSRVFormat;
+
+    GLenum swizzleFormat;
+
+    InitializeTextureDataFunction dataInitializerFunction;
+};
+
+constexpr Format::Format()
+    : internalFormat(GL_NONE),
+      formatID(angle::Format::ID::NONE),
+      texFormat(DXGI_FORMAT_UNKNOWN),
+      srvFormat(DXGI_FORMAT_UNKNOWN),
+      rtvFormat(DXGI_FORMAT_UNKNOWN),
+      dsvFormat(DXGI_FORMAT_UNKNOWN),
+      blitSRVFormat(DXGI_FORMAT_UNKNOWN),
+      swizzleFormat(GL_NONE),
+      dataInitializerFunction(nullptr)
+{
+}
+
+constexpr Format::Format(GLenum internalFormat,
+                         angle::Format::ID formatID,
+                         DXGI_FORMAT texFormat,
+                         DXGI_FORMAT srvFormat,
+                         DXGI_FORMAT rtvFormat,
+                         DXGI_FORMAT dsvFormat,
+                         DXGI_FORMAT blitSRVFormat,
+                         GLenum swizzleFormat,
+                         InitializeTextureDataFunction internalFormatInitializer)
+    : internalFormat(internalFormat),
+      formatID(formatID),
+      texFormat(texFormat),
+      srvFormat(srvFormat),
+      rtvFormat(rtvFormat),
+      dsvFormat(dsvFormat),
+      blitSRVFormat(blitSRVFormat),
+      swizzleFormat(swizzleFormat),
+      dataInitializerFunction(internalFormatInitializer)
+{
+}
+
+}  // namespace d3d11
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
new file mode 100644
index 0000000..3ab3337
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
@@ -0,0 +1,1925 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_texture_format_table.py using data from texture_format_data.json
+//
+// Copyright 2016 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.
+//
+// texture_format_table:
+//   Queries for full textureFormat information based in internalFormat
+//
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+// static
+const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps)
+{
+    // clang-format off
+    switch (internalFormat)
+    {
+        case GL_ALPHA16F_EXT:
+        {
+            static constexpr Format info(GL_ALPHA16F_EXT,
+                                         angle::Format::ID::R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         GL_RGBA16F,
+                                         nullptr);
+            return info;
+        }
+        case GL_ALPHA32F_EXT:
+        {
+            static constexpr Format info(GL_ALPHA32F_EXT,
+                                         angle::Format::ID::R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         GL_RGBA32F,
+                                         nullptr);
+            return info;
+        }
+        case GL_ALPHA8_EXT:
+        {
+            if (OnlyFL10Plus(deviceCaps))
+            {
+                static constexpr Format info(GL_ALPHA8_EXT,
+                                             angle::Format::ID::A8_UNORM,
+                                             DXGI_FORMAT_A8_UNORM,
+                                             DXGI_FORMAT_A8_UNORM,
+                                             DXGI_FORMAT_A8_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_A8_UNORM,
+                                             GL_RGBA8,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_ALPHA8_EXT,
+                                             angle::Format::ID::R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             GL_RGBA8,
+                                             nullptr);
+                return info;
+            }
+        }
+        case GL_BGR565_ANGLEX:
+        {
+            if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps))
+            {
+                static constexpr Format info(GL_BGR565_ANGLEX,
+                                             angle::Format::ID::B5G6R5_UNORM,
+                                             DXGI_FORMAT_B5G6R5_UNORM,
+                                             DXGI_FORMAT_B5G6R5_UNORM,
+                                             DXGI_FORMAT_B5G6R5_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_B5G6R5_UNORM,
+                                             GL_RGBA8,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_BGR565_ANGLEX,
+                                             angle::Format::ID::R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             GL_RGBA8,
+                                             nullptr);
+                return info;
+            }
+        }
+        case GL_BGR5_A1_ANGLEX:
+        {
+            static constexpr Format info(GL_BGR5_A1_ANGLEX,
+                                         angle::Format::ID::B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         GL_BGRA8_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_BGRA4_ANGLEX:
+        {
+            static constexpr Format info(GL_BGRA4_ANGLEX,
+                                         angle::Format::ID::B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         GL_BGRA8_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_BGRA8_EXT:
+        {
+            static constexpr Format info(GL_BGRA8_EXT,
+                                         angle::Format::ID::B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_B8G8R8A8_UNORM,
+                                         GL_BGRA8_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_R11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_R11_EAC,
+                                         angle::Format::ID::R8_UNORM,
+                                         DXGI_FORMAT_R8_UNORM,
+                                         DXGI_FORMAT_R8_UNORM,
+                                         DXGI_FORMAT_R8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RG11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_RG11_EAC,
+                                         angle::Format::ID::R8G8_UNORM,
+                                         DXGI_FORMAT_R8G8_UNORM,
+                                         DXGI_FORMAT_R8G8_UNORM,
+                                         DXGI_FORMAT_R8G8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGB8_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB8_ETC2,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE,
+                                         angle::Format::ID::BC1_RGB_UNORM_BLOCK,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
+                                         angle::Format::ID::BC1_RGBA_UNORM_BLOCK,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA8_ETC2_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA8_ETC2_EAC,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x5_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x8_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x10_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x5_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x6_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x6_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+                                         angle::Format::ID::BC1_RGBA_UNORM_BLOCK,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
+                                         angle::Format::ID::BC2_RGBA_UNORM_BLOCK,
+                                         DXGI_FORMAT_BC2_UNORM,
+                                         DXGI_FORMAT_BC2_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC2_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
+                                         angle::Format::ID::BC3_RGBA_UNORM_BLOCK,
+                                         DXGI_FORMAT_BC3_UNORM,
+                                         DXGI_FORMAT_BC3_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC3_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+                                         angle::Format::ID::BC1_RGB_UNORM_BLOCK,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SIGNED_R11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_SIGNED_R11_EAC,
+                                         angle::Format::ID::R8_SNORM,
+                                         DXGI_FORMAT_R8_SNORM,
+                                         DXGI_FORMAT_R8_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8_SNORM,
+                                         GL_RGBA8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SIGNED_RG11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_SIGNED_RG11_EAC,
+                                         angle::Format::ID::R8G8_SNORM,
+                                         DXGI_FORMAT_R8G8_SNORM,
+                                         DXGI_FORMAT_R8G8_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8_SNORM,
+                                         GL_RGBA8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
+                                         angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         GL_SRGB8_ALPHA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ETC2,
+                                         angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         GL_SRGB8_ALPHA8,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE,
+                                         angle::Format::ID::BC1_RGB_UNORM_SRGB_BLOCK,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+                                         angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         GL_SRGB8_ALPHA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
+                                         angle::Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
+                                         angle::Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
+                                         angle::Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK,
+                                         DXGI_FORMAT_BC2_UNORM_SRGB,
+                                         DXGI_FORMAT_BC2_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC2_UNORM_SRGB,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
+                                         angle::Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK,
+                                         DXGI_FORMAT_BC3_UNORM_SRGB,
+                                         DXGI_FORMAT_BC3_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC3_UNORM_SRGB,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
+                                         angle::Format::ID::BC1_RGB_UNORM_SRGB_BLOCK,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC1_UNORM_SRGB,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_DEPTH24_STENCIL8:
+        {
+            if (OnlyFL10Plus(deviceCaps))
+            {
+                static constexpr Format info(GL_DEPTH24_STENCIL8,
+                                             angle::Format::ID::D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_R24G8_TYPELESS,
+                                             DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+                                             GL_RGBA32F,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_DEPTH24_STENCIL8,
+                                             angle::Format::ID::D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             GL_RGBA32F,
+                                             nullptr);
+                return info;
+            }
+        }
+        case GL_DEPTH32F_STENCIL8:
+        {
+            static constexpr Format info(GL_DEPTH32F_STENCIL8,
+                                         angle::Format::ID::D32_FLOAT_S8X24_UINT,
+                                         DXGI_FORMAT_R32G8X24_TYPELESS,
+                                         DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
+                                         DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+                                         GL_RGBA32F,
+                                         nullptr);
+            return info;
+        }
+        case GL_DEPTH_COMPONENT16:
+        {
+            if (OnlyFL10Plus(deviceCaps))
+            {
+                static constexpr Format info(GL_DEPTH_COMPONENT16,
+                                             angle::Format::ID::D16_UNORM,
+                                             DXGI_FORMAT_R16_TYPELESS,
+                                             DXGI_FORMAT_R16_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D16_UNORM,
+                                             DXGI_FORMAT_R16_UNORM,
+                                             GL_RGBA16_EXT,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_DEPTH_COMPONENT16,
+                                             angle::Format::ID::D16_UNORM,
+                                             DXGI_FORMAT_D16_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D16_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             GL_RGBA16_EXT,
+                                             nullptr);
+                return info;
+            }
+        }
+        case GL_DEPTH_COMPONENT24:
+        {
+            if (OnlyFL10Plus(deviceCaps))
+            {
+                static constexpr Format info(GL_DEPTH_COMPONENT24,
+                                             angle::Format::ID::D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_R24G8_TYPELESS,
+                                             DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+                                             GL_RGBA32F,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_DEPTH_COMPONENT24,
+                                             angle::Format::ID::D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             GL_RGBA32F,
+                                             nullptr);
+                return info;
+            }
+        }
+        case GL_DEPTH_COMPONENT32F:
+        {
+            static constexpr Format info(GL_DEPTH_COMPONENT32F,
+                                         angle::Format::ID::D32_FLOAT,
+                                         DXGI_FORMAT_R32_TYPELESS,
+                                         DXGI_FORMAT_R32_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_D32_FLOAT,
+                                         DXGI_FORMAT_R32_FLOAT,
+                                         GL_RGBA32F,
+                                         nullptr);
+            return info;
+        }
+        case GL_DEPTH_COMPONENT32_OES:
+        {
+            if (OnlyFL10Plus(deviceCaps))
+            {
+                static constexpr Format info(GL_DEPTH_COMPONENT32_OES,
+                                             angle::Format::ID::D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_R24G8_TYPELESS,
+                                             DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+                                             GL_RGBA32F,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_DEPTH_COMPONENT32_OES,
+                                             angle::Format::ID::D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             GL_RGBA32F,
+                                             nullptr);
+                return info;
+            }
+        }
+        case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+        {
+            static constexpr Format info(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE,
+                                         angle::Format::ID::BC1_RGB_UNORM_BLOCK,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_BC1_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_ETC1_RGB8_OES:
+        {
+            static constexpr Format info(GL_ETC1_RGB8_OES,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_LUMINANCE16F_EXT:
+        {
+            static constexpr Format info(GL_LUMINANCE16F_EXT,
+                                         angle::Format::ID::R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         GL_RGBA16F,
+                                         Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>);
+            return info;
+        }
+        case GL_LUMINANCE32F_EXT:
+        {
+            static constexpr Format info(GL_LUMINANCE32F_EXT,
+                                         angle::Format::ID::R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         GL_RGBA32F,
+                                         Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>);
+            return info;
+        }
+        case GL_LUMINANCE8_ALPHA8_EXT:
+        {
+            static constexpr Format info(GL_LUMINANCE8_ALPHA8_EXT,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_LUMINANCE8_EXT:
+        {
+            static constexpr Format info(GL_LUMINANCE8_EXT,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_LUMINANCE_ALPHA16F_EXT:
+        {
+            static constexpr Format info(GL_LUMINANCE_ALPHA16F_EXT,
+                                         angle::Format::ID::R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         GL_RGBA16F,
+                                         nullptr);
+            return info;
+        }
+        case GL_LUMINANCE_ALPHA32F_EXT:
+        {
+            static constexpr Format info(GL_LUMINANCE_ALPHA32F_EXT,
+                                         angle::Format::ID::R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         GL_RGBA32F,
+                                         nullptr);
+            return info;
+        }
+        case GL_NONE:
+        {
+            static constexpr Format info(GL_NONE,
+                                         angle::Format::ID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
+        case GL_R11F_G11F_B10F:
+        {
+            static constexpr Format info(GL_R11F_G11F_B10F,
+                                         angle::Format::ID::R11G11B10_FLOAT,
+                                         DXGI_FORMAT_R11G11B10_FLOAT,
+                                         DXGI_FORMAT_R11G11B10_FLOAT,
+                                         DXGI_FORMAT_R11G11B10_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R11G11B10_FLOAT,
+                                         GL_RGBA16F_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16F:
+        {
+            static constexpr Format info(GL_R16F,
+                                         angle::Format::ID::R16_FLOAT,
+                                         DXGI_FORMAT_R16_FLOAT,
+                                         DXGI_FORMAT_R16_FLOAT,
+                                         DXGI_FORMAT_R16_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16_FLOAT,
+                                         GL_RGBA16F_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16I:
+        {
+            static constexpr Format info(GL_R16I,
+                                         angle::Format::ID::R16_SINT,
+                                         DXGI_FORMAT_R16_SINT,
+                                         DXGI_FORMAT_R16_SINT,
+                                         DXGI_FORMAT_R16_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16_SINT,
+                                         GL_RGBA16I,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16UI:
+        {
+            static constexpr Format info(GL_R16UI,
+                                         angle::Format::ID::R16_UINT,
+                                         DXGI_FORMAT_R16_UINT,
+                                         DXGI_FORMAT_R16_UINT,
+                                         DXGI_FORMAT_R16_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16_UINT,
+                                         GL_RGBA16I,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16_EXT:
+        {
+            static constexpr Format info(GL_R16_EXT,
+                                         angle::Format::ID::R16_UNORM,
+                                         DXGI_FORMAT_R16_UNORM,
+                                         DXGI_FORMAT_R16_UNORM,
+                                         DXGI_FORMAT_R16_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16_UNORM,
+                                         GL_RGBA16_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_R16_SNORM_EXT,
+                                         angle::Format::ID::R16_SNORM,
+                                         DXGI_FORMAT_R16_SNORM,
+                                         DXGI_FORMAT_R16_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16_SNORM,
+                                         GL_RGBA16_SNORM_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R32F:
+        {
+            static constexpr Format info(GL_R32F,
+                                         angle::Format::ID::R32_FLOAT,
+                                         DXGI_FORMAT_R32_FLOAT,
+                                         DXGI_FORMAT_R32_FLOAT,
+                                         DXGI_FORMAT_R32_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32_FLOAT,
+                                         GL_RGBA32F,
+                                         nullptr);
+            return info;
+        }
+        case GL_R32I:
+        {
+            static constexpr Format info(GL_R32I,
+                                         angle::Format::ID::R32_SINT,
+                                         DXGI_FORMAT_R32_SINT,
+                                         DXGI_FORMAT_R32_SINT,
+                                         DXGI_FORMAT_R32_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32_SINT,
+                                         GL_RGBA32I,
+                                         nullptr);
+            return info;
+        }
+        case GL_R32UI:
+        {
+            static constexpr Format info(GL_R32UI,
+                                         angle::Format::ID::R32_UINT,
+                                         DXGI_FORMAT_R32_UINT,
+                                         DXGI_FORMAT_R32_UINT,
+                                         DXGI_FORMAT_R32_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32_UINT,
+                                         GL_RGBA32I,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8:
+        {
+            static constexpr Format info(GL_R8,
+                                         angle::Format::ID::R8_UNORM,
+                                         DXGI_FORMAT_R8_UNORM,
+                                         DXGI_FORMAT_R8_UNORM,
+                                         DXGI_FORMAT_R8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8I:
+        {
+            static constexpr Format info(GL_R8I,
+                                         angle::Format::ID::R8_SINT,
+                                         DXGI_FORMAT_R8_SINT,
+                                         DXGI_FORMAT_R8_SINT,
+                                         DXGI_FORMAT_R8_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8_SINT,
+                                         GL_RGBA8I,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8UI:
+        {
+            static constexpr Format info(GL_R8UI,
+                                         angle::Format::ID::R8_UINT,
+                                         DXGI_FORMAT_R8_UINT,
+                                         DXGI_FORMAT_R8_UINT,
+                                         DXGI_FORMAT_R8_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8_UINT,
+                                         GL_RGBA8I,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8_SNORM:
+        {
+            static constexpr Format info(GL_R8_SNORM,
+                                         angle::Format::ID::R8_SNORM,
+                                         DXGI_FORMAT_R8_SNORM,
+                                         DXGI_FORMAT_R8_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8_SNORM,
+                                         GL_RGBA8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16F:
+        {
+            static constexpr Format info(GL_RG16F,
+                                         angle::Format::ID::R16G16_FLOAT,
+                                         DXGI_FORMAT_R16G16_FLOAT,
+                                         DXGI_FORMAT_R16G16_FLOAT,
+                                         DXGI_FORMAT_R16G16_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16_FLOAT,
+                                         GL_RGBA16F_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16I:
+        {
+            static constexpr Format info(GL_RG16I,
+                                         angle::Format::ID::R16G16_SINT,
+                                         DXGI_FORMAT_R16G16_SINT,
+                                         DXGI_FORMAT_R16G16_SINT,
+                                         DXGI_FORMAT_R16G16_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16_SINT,
+                                         GL_RGBA16I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16UI:
+        {
+            static constexpr Format info(GL_RG16UI,
+                                         angle::Format::ID::R16G16_UINT,
+                                         DXGI_FORMAT_R16G16_UINT,
+                                         DXGI_FORMAT_R16G16_UINT,
+                                         DXGI_FORMAT_R16G16_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16_UINT,
+                                         GL_RGBA16I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16_EXT:
+        {
+            static constexpr Format info(GL_RG16_EXT,
+                                         angle::Format::ID::R16G16_UNORM,
+                                         DXGI_FORMAT_R16G16_UNORM,
+                                         DXGI_FORMAT_R16G16_UNORM,
+                                         DXGI_FORMAT_R16G16_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16_UNORM,
+                                         GL_RGBA16_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_RG16_SNORM_EXT,
+                                         angle::Format::ID::R16G16_SNORM,
+                                         DXGI_FORMAT_R16G16_SNORM,
+                                         DXGI_FORMAT_R16G16_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16_SNORM,
+                                         GL_RGBA16_SNORM_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG32F:
+        {
+            static constexpr Format info(GL_RG32F,
+                                         angle::Format::ID::R32G32_FLOAT,
+                                         DXGI_FORMAT_R32G32_FLOAT,
+                                         DXGI_FORMAT_R32G32_FLOAT,
+                                         DXGI_FORMAT_R32G32_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32_FLOAT,
+                                         GL_RGBA32F,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG32I:
+        {
+            static constexpr Format info(GL_RG32I,
+                                         angle::Format::ID::R32G32_SINT,
+                                         DXGI_FORMAT_R32G32_SINT,
+                                         DXGI_FORMAT_R32G32_SINT,
+                                         DXGI_FORMAT_R32G32_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32_SINT,
+                                         GL_RGBA32I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG32UI:
+        {
+            static constexpr Format info(GL_RG32UI,
+                                         angle::Format::ID::R32G32_UINT,
+                                         DXGI_FORMAT_R32G32_UINT,
+                                         DXGI_FORMAT_R32G32_UINT,
+                                         DXGI_FORMAT_R32G32_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32_UINT,
+                                         GL_RGBA32I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8:
+        {
+            static constexpr Format info(GL_RG8,
+                                         angle::Format::ID::R8G8_UNORM,
+                                         DXGI_FORMAT_R8G8_UNORM,
+                                         DXGI_FORMAT_R8G8_UNORM,
+                                         DXGI_FORMAT_R8G8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8I:
+        {
+            static constexpr Format info(GL_RG8I,
+                                         angle::Format::ID::R8G8_SINT,
+                                         DXGI_FORMAT_R8G8_SINT,
+                                         DXGI_FORMAT_R8G8_SINT,
+                                         DXGI_FORMAT_R8G8_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8_SINT,
+                                         GL_RGBA8I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8UI:
+        {
+            static constexpr Format info(GL_RG8UI,
+                                         angle::Format::ID::R8G8_UINT,
+                                         DXGI_FORMAT_R8G8_UINT,
+                                         DXGI_FORMAT_R8G8_UINT,
+                                         DXGI_FORMAT_R8G8_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8_UINT,
+                                         GL_RGBA8I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8_SNORM:
+        {
+            static constexpr Format info(GL_RG8_SNORM,
+                                         angle::Format::ID::R8G8_SNORM,
+                                         DXGI_FORMAT_R8G8_SNORM,
+                                         DXGI_FORMAT_R8G8_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8_SNORM,
+                                         GL_RGBA8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB:
+        {
+            static constexpr Format info(GL_RGB,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_RGB10_A2:
+        {
+            static constexpr Format info(GL_RGB10_A2,
+                                         angle::Format::ID::R10G10B10A2_UNORM,
+                                         DXGI_FORMAT_R10G10B10A2_UNORM,
+                                         DXGI_FORMAT_R10G10B10A2_UNORM,
+                                         DXGI_FORMAT_R10G10B10A2_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R10G10B10A2_UNORM,
+                                         GL_RGBA16_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB10_A2UI:
+        {
+            static constexpr Format info(GL_RGB10_A2UI,
+                                         angle::Format::ID::R10G10B10A2_UINT,
+                                         DXGI_FORMAT_R10G10B10A2_UINT,
+                                         DXGI_FORMAT_R10G10B10A2_UINT,
+                                         DXGI_FORMAT_R10G10B10A2_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R10G10B10A2_UINT,
+                                         GL_RGBA16I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16F:
+        {
+            static constexpr Format info(GL_RGB16F,
+                                         angle::Format::ID::R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         GL_RGBA16F,
+                                         Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>);
+            return info;
+        }
+        case GL_RGB16I:
+        {
+            static constexpr Format info(GL_RGB16I,
+                                         angle::Format::ID::R16G16B16A16_SINT,
+                                         DXGI_FORMAT_R16G16B16A16_SINT,
+                                         DXGI_FORMAT_R16G16B16A16_SINT,
+                                         DXGI_FORMAT_R16G16B16A16_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_SINT,
+                                         GL_RGBA16I,
+                                         Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>);
+            return info;
+        }
+        case GL_RGB16UI:
+        {
+            static constexpr Format info(GL_RGB16UI,
+                                         angle::Format::ID::R16G16B16A16_UINT,
+                                         DXGI_FORMAT_R16G16B16A16_UINT,
+                                         DXGI_FORMAT_R16G16B16A16_UINT,
+                                         DXGI_FORMAT_R16G16B16A16_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_UINT,
+                                         GL_RGBA16UI,
+                                         Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>);
+            return info;
+        }
+        case GL_RGB16_EXT:
+        {
+            static constexpr Format info(GL_RGB16_EXT,
+                                         angle::Format::ID::R16G16B16A16_UNORM,
+                                         DXGI_FORMAT_R16G16B16A16_UNORM,
+                                         DXGI_FORMAT_R16G16B16A16_UNORM,
+                                         DXGI_FORMAT_R16G16B16A16_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_UNORM,
+                                         GL_RGBA16_EXT,
+                                         Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>);
+            return info;
+        }
+        case GL_RGB16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_RGB16_SNORM_EXT,
+                                         angle::Format::ID::R16G16B16A16_SNORM,
+                                         DXGI_FORMAT_R16G16B16A16_SNORM,
+                                         DXGI_FORMAT_R16G16B16A16_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_SNORM,
+                                         GL_RGBA16_SNORM_EXT,
+                                         Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>);
+            return info;
+        }
+        case GL_RGB32F:
+        {
+            static constexpr Format info(GL_RGB32F,
+                                         angle::Format::ID::R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         GL_RGBA32F,
+                                         Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>);
+            return info;
+        }
+        case GL_RGB32I:
+        {
+            static constexpr Format info(GL_RGB32I,
+                                         angle::Format::ID::R32G32B32A32_SINT,
+                                         DXGI_FORMAT_R32G32B32A32_SINT,
+                                         DXGI_FORMAT_R32G32B32A32_SINT,
+                                         DXGI_FORMAT_R32G32B32A32_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32B32A32_SINT,
+                                         GL_RGBA32I,
+                                         Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>);
+            return info;
+        }
+        case GL_RGB32UI:
+        {
+            static constexpr Format info(GL_RGB32UI,
+                                         angle::Format::ID::R32G32B32A32_UINT,
+                                         DXGI_FORMAT_R32G32B32A32_UINT,
+                                         DXGI_FORMAT_R32G32B32A32_UINT,
+                                         DXGI_FORMAT_R32G32B32A32_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32B32A32_UINT,
+                                         GL_RGBA32UI,
+                                         Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>);
+            return info;
+        }
+        case GL_RGB565:
+        {
+            if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps))
+            {
+                static constexpr Format info(GL_RGB565,
+                                             angle::Format::ID::B5G6R5_UNORM,
+                                             DXGI_FORMAT_B5G6R5_UNORM,
+                                             DXGI_FORMAT_B5G6R5_UNORM,
+                                             DXGI_FORMAT_B5G6R5_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_B5G6R5_UNORM,
+                                             GL_RGBA8,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_RGB565,
+                                             angle::Format::ID::R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             GL_RGBA8,
+                                             Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+                return info;
+            }
+        }
+        case GL_RGB5_A1:
+        {
+            if (SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps))
+            {
+                static constexpr Format info(GL_RGB5_A1,
+                                             angle::Format::ID::B5G5R5A1_UNORM,
+                                             DXGI_FORMAT_B5G5R5A1_UNORM,
+                                             DXGI_FORMAT_B5G5R5A1_UNORM,
+                                             DXGI_FORMAT_B5G5R5A1_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_B5G5R5A1_UNORM,
+                                             GL_RGBA8,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_RGB5_A1,
+                                             angle::Format::ID::R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             GL_RGBA8,
+                                             nullptr);
+                return info;
+            }
+        }
+        case GL_RGB8:
+        {
+            static constexpr Format info(GL_RGB8,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_RGB8I:
+        {
+            static constexpr Format info(GL_RGB8I,
+                                         angle::Format::ID::R8G8B8A8_SINT,
+                                         DXGI_FORMAT_R8G8B8A8_SINT,
+                                         DXGI_FORMAT_R8G8B8A8_SINT,
+                                         DXGI_FORMAT_R8G8B8A8_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_SINT,
+                                         GL_RGBA8I,
+                                         Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>);
+            return info;
+        }
+        case GL_RGB8UI:
+        {
+            static constexpr Format info(GL_RGB8UI,
+                                         angle::Format::ID::R8G8B8A8_UINT,
+                                         DXGI_FORMAT_R8G8B8A8_UINT,
+                                         DXGI_FORMAT_R8G8B8A8_UINT,
+                                         DXGI_FORMAT_R8G8B8A8_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UINT,
+                                         GL_RGBA8UI,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>);
+            return info;
+        }
+        case GL_RGB8_SNORM:
+        {
+            static constexpr Format info(GL_RGB8_SNORM,
+                                         angle::Format::ID::R8G8B8A8_SNORM,
+                                         DXGI_FORMAT_R8G8B8A8_SNORM,
+                                         DXGI_FORMAT_R8G8B8A8_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_SNORM,
+                                         GL_RGBA8_SNORM,
+                                         Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>);
+            return info;
+        }
+        case GL_RGB9_E5:
+        {
+            static constexpr Format info(GL_RGB9_E5,
+                                         angle::Format::ID::R9G9B9E5_SHAREDEXP,
+                                         DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+                                         DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+                                         GL_RGBA16F_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA:
+        {
+            static constexpr Format info(GL_RGBA,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16F:
+        {
+            static constexpr Format info(GL_RGBA16F,
+                                         angle::Format::ID::R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_FLOAT,
+                                         GL_RGBA16F,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16I:
+        {
+            static constexpr Format info(GL_RGBA16I,
+                                         angle::Format::ID::R16G16B16A16_SINT,
+                                         DXGI_FORMAT_R16G16B16A16_SINT,
+                                         DXGI_FORMAT_R16G16B16A16_SINT,
+                                         DXGI_FORMAT_R16G16B16A16_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_SINT,
+                                         GL_RGBA16I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16UI:
+        {
+            static constexpr Format info(GL_RGBA16UI,
+                                         angle::Format::ID::R16G16B16A16_UINT,
+                                         DXGI_FORMAT_R16G16B16A16_UINT,
+                                         DXGI_FORMAT_R16G16B16A16_UINT,
+                                         DXGI_FORMAT_R16G16B16A16_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_UINT,
+                                         GL_RGBA16UI,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16_EXT:
+        {
+            static constexpr Format info(GL_RGBA16_EXT,
+                                         angle::Format::ID::R16G16B16A16_UNORM,
+                                         DXGI_FORMAT_R16G16B16A16_UNORM,
+                                         DXGI_FORMAT_R16G16B16A16_UNORM,
+                                         DXGI_FORMAT_R16G16B16A16_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_UNORM,
+                                         GL_RGBA16_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_RGBA16_SNORM_EXT,
+                                         angle::Format::ID::R16G16B16A16_SNORM,
+                                         DXGI_FORMAT_R16G16B16A16_SNORM,
+                                         DXGI_FORMAT_R16G16B16A16_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R16G16B16A16_SNORM,
+                                         GL_RGBA16_SNORM_EXT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA32F:
+        {
+            static constexpr Format info(GL_RGBA32F,
+                                         angle::Format::ID::R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32B32A32_FLOAT,
+                                         GL_RGBA32F,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA32I:
+        {
+            static constexpr Format info(GL_RGBA32I,
+                                         angle::Format::ID::R32G32B32A32_SINT,
+                                         DXGI_FORMAT_R32G32B32A32_SINT,
+                                         DXGI_FORMAT_R32G32B32A32_SINT,
+                                         DXGI_FORMAT_R32G32B32A32_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32B32A32_SINT,
+                                         GL_RGBA32I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA32UI:
+        {
+            static constexpr Format info(GL_RGBA32UI,
+                                         angle::Format::ID::R32G32B32A32_UINT,
+                                         DXGI_FORMAT_R32G32B32A32_UINT,
+                                         DXGI_FORMAT_R32G32B32A32_UINT,
+                                         DXGI_FORMAT_R32G32B32A32_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R32G32B32A32_UINT,
+                                         GL_RGBA32UI,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA4:
+        {
+            if (SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps))
+            {
+                static constexpr Format info(GL_RGBA4,
+                                             angle::Format::ID::B4G4R4A4_UNORM,
+                                             DXGI_FORMAT_B4G4R4A4_UNORM,
+                                             DXGI_FORMAT_B4G4R4A4_UNORM,
+                                             DXGI_FORMAT_B4G4R4A4_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_B4G4R4A4_UNORM,
+                                             GL_RGBA4,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_RGBA4,
+                                             angle::Format::ID::R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_R8G8B8A8_UNORM,
+                                             GL_RGBA8,
+                                             nullptr);
+                return info;
+            }
+        }
+        case GL_RGBA8:
+        {
+            static constexpr Format info(GL_RGBA8,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM,
+                                         GL_RGBA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8I:
+        {
+            static constexpr Format info(GL_RGBA8I,
+                                         angle::Format::ID::R8G8B8A8_SINT,
+                                         DXGI_FORMAT_R8G8B8A8_SINT,
+                                         DXGI_FORMAT_R8G8B8A8_SINT,
+                                         DXGI_FORMAT_R8G8B8A8_SINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_SINT,
+                                         GL_RGBA8I,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8UI:
+        {
+            static constexpr Format info(GL_RGBA8UI,
+                                         angle::Format::ID::R8G8B8A8_UINT,
+                                         DXGI_FORMAT_R8G8B8A8_UINT,
+                                         DXGI_FORMAT_R8G8B8A8_UINT,
+                                         DXGI_FORMAT_R8G8B8A8_UINT,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UINT,
+                                         GL_RGBA8UI,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8_SNORM:
+        {
+            static constexpr Format info(GL_RGBA8_SNORM,
+                                         angle::Format::ID::R8G8B8A8_SNORM,
+                                         DXGI_FORMAT_R8G8B8A8_SNORM,
+                                         DXGI_FORMAT_R8G8B8A8_SNORM,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_SNORM,
+                                         GL_RGBA8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_SRGB8:
+        {
+            static constexpr Format info(GL_SRGB8,
+                                         angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         GL_SRGB8_ALPHA8,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_SRGB8_ALPHA8:
+        {
+            static constexpr Format info(GL_SRGB8_ALPHA8,
+                                         angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+                                         GL_SRGB8_ALPHA8,
+                                         nullptr);
+            return info;
+        }
+        case GL_STENCIL_INDEX8:
+        {
+            if (OnlyFL10Plus(deviceCaps))
+            {
+                static constexpr Format info(GL_STENCIL_INDEX8,
+                                             angle::Format::ID::D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_R24G8_TYPELESS,
+                                             DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+                                             GL_RGBA32F,
+                                             nullptr);
+                return info;
+            }
+            else
+            {
+                static constexpr Format info(GL_STENCIL_INDEX8,
+                                             angle::Format::ID::D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             DXGI_FORMAT_D24_UNORM_S8_UINT,
+                                             DXGI_FORMAT_UNKNOWN,
+                                             GL_RGBA32F,
+                                             nullptr);
+                return info;
+            }
+        }
+
+        default:
+            break;
+    }
+    // clang-format on
+
+    UNREACHABLE();
+    static constexpr Format defaultInfo;
+    return defaultInfo;
+}
+
+}  // namespace d3d11
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h
new file mode 100644
index 0000000..14af8a7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h
@@ -0,0 +1,77 @@
+//
+// Copyright 2016 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.
+//
+// Helper routines for the D3D11 texture format table.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+using FormatSupportFunction = bool (*)(const Renderer11DeviceCaps &);
+
+inline bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps)
+{
+    return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0);
+}
+
+inline bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps)
+{
+    return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3);
+}
+
+inline bool SupportsFormat(DXGI_FORMAT format, const Renderer11DeviceCaps &deviceCaps)
+{
+    // Must support texture, SRV and RTV support
+    UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE |
+                       D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP |
+                       D3D11_FORMAT_SUPPORT_RENDER_TARGET;
+
+    if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel).major > 2)
+    {
+        mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+    }
+
+    bool fullSupport = false;
+    if (format == DXGI_FORMAT_B5G6R5_UNORM)
+    {
+        // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but
+        // check anyway.
+        mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+        fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport);
+    }
+    else if (format == DXGI_FORMAT_B4G4R4A4_UNORM)
+    {
+        fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport);
+    }
+    else if (format == DXGI_FORMAT_B5G5R5A1_UNORM)
+    {
+        fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport);
+    }
+    else
+    {
+        UNREACHABLE();
+        return false;
+    }
+
+    // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
+    // *IS* supported.
+    // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if
+    // DXGI_FORMAT_B5G5R5A1 is supported.
+    // In this case, we should only return 'true' if the format *IS* supported.
+    return fullSupport;
+}
+
+}  // namespace d3d11
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp
new file mode 100644
index 0000000..5394e3d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp
@@ -0,0 +1,217 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// NativeWindow11Win32.cpp: Implementation of NativeWindow11 using win32 window APIs.
+
+#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include "common/debug.h"
+
+#include <initguid.h>
+#include <dcomp.h>
+
+namespace rx
+{
+
+NativeWindow11Win32::NativeWindow11Win32(EGLNativeWindowType window,
+                                         bool hasAlpha,
+                                         bool directComposition)
+    : NativeWindow11(window),
+      mDirectComposition(directComposition),
+      mHasAlpha(hasAlpha),
+      mDevice(nullptr),
+      mCompositionTarget(nullptr),
+      mVisual(nullptr)
+{
+}
+
+NativeWindow11Win32::~NativeWindow11Win32()
+{
+    SafeRelease(mCompositionTarget);
+    SafeRelease(mDevice);
+    SafeRelease(mVisual);
+}
+
+bool NativeWindow11Win32::initialize()
+{
+    return true;
+}
+
+bool NativeWindow11Win32::getClientRect(LPRECT rect) const
+{
+    return GetClientRect(getNativeWindow(), rect) == TRUE;
+}
+
+bool NativeWindow11Win32::isIconic() const
+{
+    return IsIconic(getNativeWindow()) == TRUE;
+}
+
+HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device,
+                                             IDXGIFactory *factory,
+                                             DXGI_FORMAT format,
+                                             UINT width,
+                                             UINT height,
+                                             UINT samples,
+                                             IDXGISwapChain **swapChain)
+{
+    if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
+        height == 0)
+    {
+        return E_INVALIDARG;
+    }
+
+    if (mDirectComposition)
+    {
+        HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll"));
+        if (!dcomp)
+        {
+            return E_INVALIDARG;
+        }
+
+        typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)(
+            IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice);
+        PFN_DCOMPOSITION_CREATE_DEVICE createDComp =
+            reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>(
+                GetProcAddress(dcomp, "DCompositionCreateDevice"));
+        if (!createDComp)
+        {
+            return E_INVALIDARG;
+        }
+
+        if (!mDevice)
+        {
+            IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject<IDXGIDevice>(device);
+            HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice),
+                                         reinterpret_cast<void **>(&mDevice));
+            SafeRelease(dxgiDevice);
+
+            if (FAILED(result))
+            {
+                return result;
+            }
+        }
+
+        if (!mCompositionTarget)
+        {
+            HRESULT result =
+                mDevice->CreateTargetForHwnd(getNativeWindow(), TRUE, &mCompositionTarget);
+            if (FAILED(result))
+            {
+                return result;
+            }
+        }
+
+        if (!mVisual)
+        {
+            HRESULT result = mDevice->CreateVisual(&mVisual);
+            if (FAILED(result))
+            {
+                return result;
+            }
+        }
+
+        IDXGIFactory2 *factory2             = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+        swapChainDesc.Width                 = width;
+        swapChainDesc.Height                = height;
+        swapChainDesc.Format                = format;
+        swapChainDesc.Stereo                = FALSE;
+        swapChainDesc.SampleDesc.Count      = 1;
+        swapChainDesc.SampleDesc.Quality = 0;
+        swapChainDesc.BufferUsage =
+            DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT;
+        swapChainDesc.BufferCount = 2;
+        swapChainDesc.Scaling     = DXGI_SCALING_STRETCH;
+        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+        swapChainDesc.AlphaMode =
+            mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
+        swapChainDesc.Flags         = 0;
+        IDXGISwapChain1 *swapChain1 = nullptr;
+        HRESULT result =
+            factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
+        if (SUCCEEDED(result))
+        {
+            *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
+        }
+        mVisual->SetContent(swapChain1);
+        mCompositionTarget->SetRoot(mVisual);
+        SafeRelease(factory2);
+        return result;
+    }
+
+    // Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a
+    // DXGI_SWAP_EFFECT_SEQUENTIAL swap chain.
+    IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+    if (factory2 != nullptr)
+    {
+        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+        swapChainDesc.Width                 = width;
+        swapChainDesc.Height                = height;
+        swapChainDesc.Format                = format;
+        swapChainDesc.Stereo                = FALSE;
+        swapChainDesc.SampleDesc.Count      = samples;
+        swapChainDesc.SampleDesc.Quality    = 0;
+        swapChainDesc.BufferUsage =
+            DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+        swapChainDesc.BufferCount   = 1;
+        swapChainDesc.Scaling       = DXGI_SCALING_STRETCH;
+        swapChainDesc.SwapEffect    = DXGI_SWAP_EFFECT_SEQUENTIAL;
+        swapChainDesc.AlphaMode     = DXGI_ALPHA_MODE_UNSPECIFIED;
+        swapChainDesc.Flags         = 0;
+        IDXGISwapChain1 *swapChain1 = nullptr;
+        HRESULT result = factory2->CreateSwapChainForHwnd(device, getNativeWindow(), &swapChainDesc,
+                                                          nullptr, nullptr, &swapChain1);
+        if (SUCCEEDED(result))
+        {
+            factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER);
+            *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
+        }
+        SafeRelease(factory2);
+        return result;
+    }
+
+    DXGI_SWAP_CHAIN_DESC swapChainDesc               = {};
+    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_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+    swapChainDesc.Flags              = 0;
+    swapChainDesc.OutputWindow       = getNativeWindow();
+    swapChainDesc.SampleDesc.Count   = samples;
+    swapChainDesc.SampleDesc.Quality = 0;
+    swapChainDesc.Windowed           = TRUE;
+    swapChainDesc.SwapEffect         = DXGI_SWAP_EFFECT_DISCARD;
+
+    HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain);
+    if (SUCCEEDED(result))
+    {
+        factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER);
+    }
+    return result;
+}
+
+void NativeWindow11Win32::commitChange()
+{
+    if (mDevice)
+    {
+        mDevice->Commit();
+    }
+}
+
+// static
+bool NativeWindow11Win32::IsValidNativeWindow(EGLNativeWindowType window)
+{
+    return IsWindow(window) == TRUE;
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h
new file mode 100644
index 0000000..baeba6a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// NativeWindow11Win32.h: Implementation of NativeWindow11 using win32 window APIs.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_
+
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+
+typedef interface IDCompositionDevice IDCompositionDevice;
+typedef interface IDCompositionTarget IDCompositionTarget;
+typedef interface IDCompositionVisual IDCompositionVisual;
+
+namespace rx
+{
+
+class NativeWindow11Win32 : public NativeWindow11
+{
+  public:
+    NativeWindow11Win32(EGLNativeWindowType window, bool hasAlpha, bool directComposition);
+    ~NativeWindow11Win32() override;
+
+    bool initialize() override;
+    bool getClientRect(LPRECT rect) const override;
+    bool isIconic() const override;
+
+    HRESULT createSwapChain(ID3D11Device *device,
+                            IDXGIFactory *factory,
+                            DXGI_FORMAT format,
+                            UINT width,
+                            UINT height,
+                            UINT samples,
+                            IDXGISwapChain **swapChain) override;
+
+    void commitChange() override;
+
+    static bool IsValidNativeWindow(EGLNativeWindowType window);
+
+  private:
+    bool mDirectComposition;
+    bool mHasAlpha;
+    IDCompositionDevice *mDevice;
+    IDCompositionTarget *mCompositionTarget;
+    IDCompositionVisual *mVisual;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
new file mode 100644
index 0000000..dd37ace
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
@@ -0,0 +1,231 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types.
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+
+#include <windows.graphics.display.h>
+
+using namespace ABI::Windows::Foundation::Collections;
+
+namespace rx
+{
+CoreWindowNativeWindow::~CoreWindowNativeWindow()
+{
+    unregisterForSizeChangeEvents();
+}
+
+bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
+{
+    ComPtr<IPropertySet> props = propertySet;
+    ComPtr<IInspectable> win = window;
+    SIZE swapChainSize = {};
+    HRESULT result = S_OK;
+
+    // IPropertySet is an optional parameter and can be null.
+    // If one is specified, cache as an IMap and read the properties
+    // used for initial host initialization.
+    if (propertySet)
+    {
+        result = props.As(&mPropertyMap);
+        if (FAILED(result))
+        {
+            return false;
+        }
+
+        // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet
+        // was prevalidated to contain the EGLNativeWindowType before being passed to
+        // this host.
+        result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &mSwapChainSizeSpecified);
+        if (FAILED(result))
+        {
+            return false;
+        }
+
+        // The EGLRenderResolutionScaleProperty is optional and may be missing. The IPropertySet
+        // was prevalidated to contain the EGLNativeWindowType before being passed to
+        // this host.
+        result = GetOptionalSinglePropertyValue(mPropertyMap, EGLRenderResolutionScaleProperty, &mSwapChainScale, &mSwapChainScaleSpecified);
+        if (FAILED(result))
+        {
+            return false;
+        }
+
+        if (!mSwapChainScaleSpecified)
+        {
+            // Default value for the scale is 1.0f
+            mSwapChainScale = 1.0f;
+        }
+
+        // A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified
+        if (mSwapChainScaleSpecified && mSwapChainSizeSpecified)
+        {
+            ERR() << "It is invalid to specify both an EGLRenderSurfaceSizeProperty and a "
+                     "EGLRenderResolutionScaleProperty.";
+            return false;
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = win.As(&mCoreWindow);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        // If a swapchain size is specfied, then the automatic resize
+        // behaviors implemented by the host should be disabled.  The swapchain
+        // will be still be scaled when being rendered to fit the bounds
+        // of the host.
+        // Scaling of the swapchain output occurs automatically because if
+        // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain.
+        if (mSwapChainSizeSpecified)
+        {
+            mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
+        }
+        else
+        {
+            Size coreWindowSize;
+            result = GetCoreWindowSizeInPixels(mCoreWindow, &coreWindowSize);
+
+            if (SUCCEEDED(result))
+            {
+                mClientRect = clientRect(coreWindowSize);
+            }
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        mNewClientRect = mClientRect;
+        mClientRectChanged = false;
+        return registerForSizeChangeEvents();
+    }
+
+    return false;
+}
+
+bool CoreWindowNativeWindow::registerForSizeChangeEvents()
+{
+    ComPtr<IWindowSizeChangedEventHandler> sizeChangedHandler;
+    HRESULT result = Microsoft::WRL::MakeAndInitialize<CoreWindowSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
+    if (SUCCEEDED(result))
+    {
+        result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+void CoreWindowNativeWindow::unregisterForSizeChangeEvents()
+{
+    if (mCoreWindow)
+    {
+        (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken);
+    }
+    mSizeChangedEventToken.value = 0;
+}
+
+HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device,
+                                                IDXGIFactory2 *factory,
+                                                DXGI_FORMAT format,
+                                                unsigned int width,
+                                                unsigned int height,
+                                                bool containsAlpha,
+                                                IDXGISwapChain1 **swapChain)
+{
+    if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
+        height == 0)
+    {
+        return E_INVALIDARG;
+    }
+
+    DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
+    swapChainDesc.Width = width;
+    swapChainDesc.Height = height;
+    swapChainDesc.Format = format;
+    swapChainDesc.Stereo = FALSE;
+    swapChainDesc.SampleDesc.Count = 1;
+    swapChainDesc.SampleDesc.Quality = 0;
+    swapChainDesc.BufferUsage =
+        DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+    swapChainDesc.BufferCount = 2;
+    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+    swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+    swapChainDesc.AlphaMode             = DXGI_ALPHA_MODE_UNSPECIFIED;
+
+    *swapChain = nullptr;
+
+    ComPtr<IDXGISwapChain1> newSwapChain;
+    HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
+    if (SUCCEEDED(result))
+    {
+        result = newSwapChain.CopyTo(swapChain);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        // If automatic swapchain resize behaviors have been disabled, then
+        // unregister for the resize change events.
+        if (mSupportsSwapChainResize == false)
+        {
+            unregisterForSizeChangeEvents();
+        }
+    }
+
+    return result;
+}
+
+inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const Size &windowSize,
+                                                      const RECT &clientRect)
+{
+    // We don't need to do any additional work to scale CoreWindow swapchains.
+    // Using DXGI_SCALING_STRETCH to create the swapchain above does all the necessary work.
+    return S_OK;
+}
+
+HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow,
+                                  Size *windowSize)
+{
+    ABI::Windows::Foundation::Rect bounds;
+    HRESULT result = coreWindow->get_Bounds(&bounds);
+    if (SUCCEEDED(result))
+    {
+        *windowSize = { ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) };
+    }
+
+    return result;
+}
+
+static float GetLogicalDpi()
+{
+    ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
+
+    if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
+    {
+        float dpi = 96.0f;
+        if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
+        {
+            return dpi;
+        }
+    }
+
+    // Return 96 dpi as a default if display properties cannot be obtained.
+    return 96.0f;
+}
+
+float ConvertDipsToPixels(float dips)
+{
+    static const float dipsPerInch = 96.0f;
+    return dips * GetLogicalDpi() / dipsPerInch;
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
new file mode 100644
index 0000000..d43bf0b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+
+#include <memory>
+
+#include <EGL/eglplatform.h>
+
+typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler;
+
+namespace rx
+{
+float ConvertDipsToPixels(float dips);
+
+class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
+{
+  public:
+    ~CoreWindowNativeWindow();
+
+    bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override;
+    HRESULT createSwapChain(ID3D11Device *device,
+                            IDXGIFactory2 *factory,
+                            DXGI_FORMAT format,
+                            unsigned int width,
+                            unsigned int height,
+                            bool containsAlpha,
+                            IDXGISwapChain1 **swapChain) override;
+
+  protected:
+    HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override;
+
+    bool registerForSizeChangeEvents();
+    void unregisterForSizeChangeEvents();
+
+  private:
+    ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
+    ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
+};
+
+[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)]
+class CoreWindowSizeChangedHandler :
+    public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler>
+{
+  public:
+    CoreWindowSizeChangedHandler() { }
+    HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
+    {
+        if (!host)
+        {
+            return E_INVALIDARG;
+        }
+
+        mHost = host;
+        return S_OK;
+    }
+
+    // IWindowSizeChangedEventHandler
+    IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs)
+    {
+        std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
+        if (host)
+        {
+            ABI::Windows::Foundation::Size windowSize;
+            if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize)))
+            {
+                Size windowSizeInPixels = {ConvertDipsToPixels(windowSize.Width),
+                                           ConvertDipsToPixels(windowSize.Height)};
+                host->setNewClientSize(windowSizeInPixels);
+            }
+        }
+
+        return S_OK;
+    }
+
+  private:
+    std::weak_ptr<InspectableNativeWindow> mHost;
+};
+
+HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow,
+                                  Size *windowSize);
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp
new file mode 100644
index 0000000..a79d173
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp
@@ -0,0 +1,356 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+// WINAPI_FAMILY is required to be defined as WINAPI_FAMILY_PC_APP
+// to ensure that the proper defines are set when including additional
+// headers which rely on Windows Store specific configuration.
+// This would normally be defined already but this unittest exe is compiled
+// as a desktop application which results in WINAPI_FAMILY being
+// set to WINAPI_FAMILY_DESKTOP_APP
+#undef WINAPI_FAMILY
+#define WINAPI_FAMILY WINAPI_FAMILY_PC_APP
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+#include <angle_windowsstore.h>
+
+using namespace rx;
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::System;
+
+namespace
+{
+
+// Mock Generic interfaces which are NOT ICoreWindow or
+// IPropertySet
+MIDL_INTERFACE("A4D67D0A-0E7F-4DF7-918B-7A1395413AF2")
+IAmInspectable : public IInspectable
+{
+};
+
+class GenericIInspectable : public RuntimeClass <
+    RuntimeClassFlags<WinRtClassicComMix>,
+    IAmInspectable >
+{
+};
+
+MIDL_INTERFACE("3CBCFE7A-E000-4094-B2D2-B7C9A4D67A2C")
+IAmUnknown : public IUnknown
+{
+};
+
+class GenericIUnknown : public RuntimeClass <
+    RuntimeClassFlags<ClassicCom>,
+    IAmUnknown >
+{
+};
+
+// Mock ICoreWindow
+class MockCoreWindow : public ABI::Windows::UI::Core::ICoreWindow
+{
+  public:
+    // IUnknown
+    STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
+    {
+        *ppvObject = nullptr;
+
+        if (IsEqualIID(IID_IUnknown, riid))
+        {
+            *ppvObject = static_cast<IUnknown*>(this);
+            return S_OK;
+        }
+
+        if (IsEqualIID(IID_IInspectable, riid))
+        {
+            *ppvObject = static_cast<IInspectable*>(this);
+            return S_OK;
+        }
+
+        if (IsEqualIID(IID_ICoreWindow, riid))
+        {
+            *ppvObject = static_cast<ABI::Windows::UI::Core::ICoreWindow*>(this);
+            return S_OK;
+        }
+
+        return E_NOINTERFACE;
+    }
+
+    STDMETHOD_(ULONG, AddRef)(){ return 1; }
+    STDMETHOD_(ULONG, Release)(){ return 1; }
+
+    // IInspectable
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetIids, HRESULT(ULONG *, IID**));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetRuntimeClassName, HRESULT(HSTRING *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTrustLevel, HRESULT(TrustLevel *));
+
+    // ICoreWindow
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_AutomationHostProvider, HRESULT(IInspectable **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Bounds, HRESULT(Rect *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CustomProperties, HRESULT(IPropertySet **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Dispatcher, HRESULT(ICoreDispatcher **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_FlowDirection, HRESULT(CoreWindowFlowDirection *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_FlowDirection, HRESULT(CoreWindowFlowDirection));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsInputEnabled, HRESULT(boolean *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsInputEnabled, HRESULT(boolean));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_PointerCursor, HRESULT(ICoreCursor**));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_PointerCursor, HRESULT(ICoreCursor*));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_PointerPosition, HRESULT(Point*));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Visible, HRESULT(boolean *));
+    MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Activate, HRESULT());
+    MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Close , HRESULT());
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetAsyncKeyState, HRESULT(ABI::Windows::System::VirtualKey, ABI::Windows::UI::Core::CoreVirtualKeyStates*));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetKeyState, HRESULT(ABI::Windows::System::VirtualKey, ABI::Windows::UI::Core::CoreVirtualKeyStates*));
+    MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, ReleasePointerCapture, HRESULT());
+    MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, SetPointerCapture, HRESULT());
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Activated, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowActivatedEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Activated, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_AutomationProviderRequested, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CAutomationProviderRequestedEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_AutomationProviderRequested, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_CharacterReceived, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CCharacterReceivedEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_CharacterReceived, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Closed, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CCoreWindowEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Closed, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_InputEnabled, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CInputEnabledEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_InputEnabled, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyDown, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CKeyEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyDown, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyUp, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CKeyEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyUp, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerCaptureLost, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerCaptureLost, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerEntered, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerEntered, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerExited, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerExited, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerMoved, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerMoved, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerPressed, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerPressed, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerReleased, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerReleased, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_TouchHitTesting, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CTouchHitTestingEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_TouchHitTesting, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerWheelChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerWheelChanged, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_SizeChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_SizeChanged, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_VisibilityChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CVisibilityChangedEventArgs*, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_VisibilityChanged, HRESULT(EventRegistrationToken));
+};
+
+HRESULT CreatePropertyMap(IMap<HSTRING, IInspectable*>** propertyMap)
+{
+    HRESULT result = S_OK;
+    ComPtr<IPropertySet> propertySet;
+    ComPtr<IActivationFactory> propertySetFactory;
+    result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Collections_PropertySet).Get(), &propertySetFactory);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    result = propertySetFactory->ActivateInstance(&propertySet);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    result = propertySet.CopyTo(propertyMap);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    return result;
+}
+
+HRESULT CreatePropertyValueStatics(IPropertyValueStatics** propertyStatics)
+{
+    ComPtr<IPropertyValueStatics> propertyValueStatics;
+    HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), &propertyValueStatics);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    result = propertyValueStatics.CopyTo(propertyStatics);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    return result;
+}
+
+HRESULT SetInspectablePropertyValue(const ComPtr<IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t* propertyName, IInspectable* inspectable)
+{
+    boolean propertyReplaced = false;
+    return propertyMap->Insert(HStringReference(propertyName).Get(), inspectable, &propertyReplaced);
+}
+
+void expectNativeWindowInitCalls(MockCoreWindow &coreWindow, bool expectBounds)
+{
+    if (expectBounds)
+    {
+        EXPECT_CALL(coreWindow, get_Bounds(testing::_)).Times(1);
+    }
+
+    EXPECT_CALL(coreWindow, add_SizeChanged(testing::_, testing::_)).Times(1);
+    EXPECT_CALL(coreWindow, remove_SizeChanged(testing::_)).Times(1);
+}
+
+TEST(NativeWindowTest, NativeWindowNull)
+{
+    NativeWindow nativeWindow(nullptr);
+    EXPECT_FALSE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, NativeWindowBadInspectable)
+{
+    ComPtr<IAmInspectable> notCoreWindow = Make<GenericIInspectable>();
+    NativeWindow nativeWindow(notCoreWindow.Get());
+    EXPECT_FALSE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, NativeWindowNotInspectable)
+{
+    ComPtr<IAmUnknown> notIInspectable = Make<GenericIUnknown>();
+    NativeWindow nativeWindow((IInspectable*)notIInspectable.Get());
+    EXPECT_FALSE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, NativeWindowValidCoreWindow)
+{
+    MockCoreWindow mockCoreWindow;
+    expectNativeWindowInitCalls(mockCoreWindow, true);
+    NativeWindow nativeWindow(&mockCoreWindow);
+    EXPECT_TRUE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, NativeWindowValidCoreWindowInPropertySet)
+{
+    // COM is required to be initialized for creation of the property set
+    EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
+    {
+        MockCoreWindow mockCoreWindow;
+        ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+
+        // Add the CoreWindow to the property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, &mockCoreWindow));
+
+        expectNativeWindowInitCalls(mockCoreWindow, true);
+        NativeWindow nativeWindow(propertySet.Get());
+        EXPECT_TRUE(nativeWindow.initialize());
+    }
+    CoUninitialize();
+}
+
+TEST(NativeWindowTest, NativeWindowMissingCoreWindowInPropertySet)
+{
+    // COM is required to be initialized for creation of the property set
+    EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
+    {
+        MockCoreWindow mockCoreWindow;
+        ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+
+        NativeWindow nativeWindow(propertySet.Get());
+        EXPECT_FALSE(nativeWindow.initialize());
+    }
+    CoUninitialize();
+}
+
+// Tests that the scale property works as expected in a property set with a SwapChainPanel
+class CoreWindowScaleTest : public testing::TestWithParam<std::pair<float, bool>>
+{
+};
+
+TEST_P(CoreWindowScaleTest, ValidateScale)
+{
+    float scale = GetParam().first;
+    bool expectedResult = GetParam().second;
+
+    // COM is required to be initialized for creation of the property set
+    EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
+    {
+        MockCoreWindow mockCoreWindow;
+        ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+        ComPtr<IPropertyValueStatics> propertyValueStatics;
+        ComPtr<IPropertyValue> singleValue;
+
+        // Create a simple property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockCoreWindow)));
+
+        // Add a valid scale factor to the property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+        propertyValueStatics->CreateSingle(scale, reinterpret_cast<IInspectable**>(singleValue.GetAddressOf()));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderResolutionScaleProperty, reinterpret_cast<IInspectable*>(singleValue.Get())));
+
+        // Check native window init status and calls to the mock swapchainpanel
+        NativeWindow nativeWindow(propertySet.Get());
+        if (expectedResult)
+        {
+            expectNativeWindowInitCalls(mockCoreWindow, true);
+        }
+
+        EXPECT_EQ(nativeWindow.initialize(), expectedResult);
+    }
+    CoUninitialize();
+}
+
+typedef std::pair<float, bool> scaleValidPair;
+static const scaleValidPair scales[] = { scaleValidPair(1.0f,   true),
+                                         scaleValidPair(0.5f,   true),
+                                         scaleValidPair(0.0f,   false),
+                                         scaleValidPair(0.01f,  true),
+                                         scaleValidPair(2.00f,  true) };
+
+INSTANTIATE_TEST_CASE_P(NativeWindowTest,
+                        CoreWindowScaleTest,
+                        testing::ValuesIn(scales));
+
+// Tests that the size property works as expected in a property set with a SwapChainPanel
+class CoreWindowSizeTest : public testing::TestWithParam<std::tuple<float, float, bool>>
+{
+};
+
+TEST_P(CoreWindowSizeTest, ValidateSize)
+{
+    Size renderSize = { std::get<0>(GetParam()), std::get<1>(GetParam()) };
+    bool expectedResult = std::get<2>(GetParam());
+
+    // COM is required to be initialized for creation of the property set
+    EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
+    {
+        MockCoreWindow mockCoreWindow;
+        ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+        ComPtr<IPropertyValueStatics> propertyValueStatics;
+        ComPtr<IPropertyValue> sizeValue;
+
+        // Create a simple property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockCoreWindow)));
+
+        // Add a valid size to the property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+        propertyValueStatics->CreateSize(renderSize, reinterpret_cast<IInspectable**>(sizeValue.GetAddressOf()));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderSurfaceSizeProperty, reinterpret_cast<IInspectable*>(sizeValue.Get())));
+
+        // Check native window init status and calls to the mock swapchainpanel
+        NativeWindow nativeWindow(propertySet.Get());
+        if (expectedResult)
+        {
+            expectNativeWindowInitCalls(mockCoreWindow, false);
+        }
+
+        EXPECT_EQ(nativeWindow.initialize(), expectedResult);
+    }
+    CoUninitialize();
+}
+
+typedef std::tuple<float, float, bool> sizeValidPair;
+static const sizeValidPair sizes[] = { sizeValidPair( 800,  480, true),
+                                       sizeValidPair(   0,  480, false),
+                                       sizeValidPair( 800,    0, false),
+                                       sizeValidPair(   0,    0, false) };
+
+INSTANTIATE_TEST_CASE_P(NativeWindowTest,
+                        CoreWindowSizeTest,
+                        testing::ValuesIn(sizes));
+
+} // namespace
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
new file mode 100644
index 0000000..cc81521
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
@@ -0,0 +1,277 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types.
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
+
+namespace rx
+{
+
+bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow)
+{
+    if (!window)
+    {
+        return false;
+    }
+
+    ComPtr<IInspectable> win = window;
+    ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin;
+    if (SUCCEEDED(win.As(&coreWin)))
+    {
+        if (coreWindow != nullptr)
+        {
+            *coreWindow = coreWin;
+        }
+        return true;
+    }
+
+    return false;
+}
+
+bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel)
+{
+    if (!window)
+    {
+        return false;
+    }
+
+    ComPtr<IInspectable> win = window;
+    ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel;
+    if (SUCCEEDED(win.As(&panel)))
+    {
+        if (swapChainPanel != nullptr)
+        {
+            *swapChainPanel = panel;
+        }
+        return true;
+    }
+
+    return false;
+}
+
+bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow)
+{
+    if (!window)
+    {
+        return false;
+    }
+
+    ComPtr<IInspectable> props = window;
+    ComPtr<IPropertySet> propSet;
+    ComPtr<IInspectable> nativeWindow;
+    ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> propMap;
+    boolean hasEglNativeWindowPropertyKey = false;
+
+    HRESULT result = props.As(&propSet);
+    if (SUCCEEDED(result))
+    {
+        result = propSet.As(&propMap);
+    }
+
+    // Look for the presence of the EGLNativeWindowType in the property set
+    if (SUCCEEDED(result))
+    {
+        result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey);
+    }
+
+    // If the IPropertySet does not contain the required EglNativeWindowType key, the property set is
+    // considered invalid.
+    if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey)
+    {
+        ERR() << "Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid "
+                 "EGLNativeWindowTypeProperty values include ICoreWindow";
+        return false;
+    }
+
+    // The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType
+    if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey)
+    {
+        result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        if (propertySet != nullptr)
+        {
+            result = propSet.CopyTo(propertySet);
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        if (eglNativeWindow != nullptr)
+        {
+            result = nativeWindow.CopyTo(eglNativeWindow);
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+// Retrieve an optional property from a property set
+HRESULT GetOptionalPropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+                                 const wchar_t *propertyName,
+                                 boolean *hasKey,
+                                 ComPtr<ABI::Windows::Foundation::IPropertyValue> &propertyValue)
+{
+    if (!propertyMap || !hasKey)
+    {
+        return E_INVALIDARG;
+    }
+
+    // Assume that the value does not exist
+    *hasKey = false;
+
+    HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), hasKey);
+    if (SUCCEEDED(result) && !(*hasKey))
+    {
+        // Value does not exist, so return S_OK and set the exists parameter to false to indicate
+        // that a the optional property does not exist.
+        return S_OK;
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue);
+    }
+
+    return result;
+}
+
+// Attempts to read an optional SIZE property value that is assumed to be in the form of
+// an ABI::Windows::Foundation::Size.  This function validates the Size value before returning
+// it to the caller.
+//
+// Possible return values are:
+// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated
+// S_OK, valueExists == false - optional SIZE value was not found
+// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set.
+//    * Incorrect property type ( must be PropertyType_Size)
+//    * Invalid property value (width/height must be > 0)
+// Additional errors may be returned from IMap or IPropertyValue
+//
+HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+                                     const wchar_t *propertyName, SIZE *value, bool *valueExists)
+{
+    ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
+    ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
+    Size sizeValue = { 0, 0 };
+    boolean hasKey = false;
+
+    if (!propertyMap || !value || !valueExists)
+    {
+        return E_INVALIDARG;
+    }
+
+    // Assume that the value does not exist
+    *valueExists = false;
+    *value = { 0, 0 };
+
+    HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue);
+    if (SUCCEEDED(result) && hasKey)
+    {
+        result = propertyValue->get_Type(&propertyType);
+
+        // Check if the expected Size property is of PropertyType_Size type.
+        if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size)
+        {
+            if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0))
+            {
+                // A valid property value exists
+                *value = { static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height) };
+                *valueExists = true;
+                result = S_OK;
+            }
+            else
+            {
+                // An invalid Size property was detected. Width/Height values must > 0
+                result = E_INVALIDARG;
+            }
+        }
+        else
+        {
+            // An invalid property type was detected. Size property must be of PropertyType_Size
+            result = E_INVALIDARG;
+        }
+    }
+
+    return result;
+}
+
+// Attempts to read an optional float property value that is assumed to be in the form of
+// an ABI::Windows::Foundation::Single.  This function validates the Single value before returning
+// it to the caller.
+//
+// Possible return values are:
+// S_OK, valueExists == true - optional Single value was successfully retrieved and validated
+// S_OK, valueExists == false - optional Single value was not found
+// E_INVALIDARG, valueExists = false - optional Single value was malformed in the property set.
+//    * Incorrect property type ( must be PropertyType_Single)
+//    * Invalid property value (must be > 0)
+// Additional errors may be returned from IMap or IPropertyValue
+//
+HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+                                       const wchar_t *propertyName, float *value, bool *valueExists)
+{
+    ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
+    ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
+    float scaleValue = 0.0f;
+    boolean hasKey = false;
+
+    if (!propertyMap || !value || !valueExists)
+    {
+        return E_INVALIDARG;
+    }
+
+    // Assume that the value does not exist
+    *valueExists = false;
+    *value = 0.0f;
+
+    HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue);
+    if (SUCCEEDED(result) && hasKey)
+    {
+        result = propertyValue->get_Type(&propertyType);
+
+        // Check if the expected Scale property is of PropertyType_Single type.
+        if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Single)
+        {
+            if (SUCCEEDED(propertyValue->GetSingle(&scaleValue)) && (scaleValue > 0.0f))
+            {
+                // A valid property value exists
+                *value = scaleValue;
+                *valueExists = true;
+                result = S_OK;
+            }
+            else
+            {
+                // An invalid scale was set
+                result = E_INVALIDARG;
+            }
+        }
+        else
+        {
+            // An invalid property type was detected. Size property must be of PropertyType_Single
+            result = E_INVALIDARG;
+        }
+    }
+
+    return result;
+}
+
+RECT InspectableNativeWindow::clientRect(const Size &size)
+{
+    // We don't have to check if a swapchain scale was specified here; the default value is 1.0f
+    // which will have no effect.
+    return {0, 0, lround(size.Width * mSwapChainScale), lround(size.Height * mSwapChainScale)};
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
new file mode 100644
index 0000000..3e67269
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InspectableNativeWindow.h: Host specific implementation interface for
+// managing IInspectable native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include "angle_windowsstore.h"
+
+#include <EGL/eglplatform.h>
+
+#include <windows.applicationmodel.core.h>
+#include <windows.ui.xaml.h>
+#include <windows.ui.xaml.media.dxinterop.h>
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+
+namespace rx
+{
+class InspectableNativeWindow
+{
+  public:
+    InspectableNativeWindow() :
+        mSupportsSwapChainResize(true),
+        mSwapChainSizeSpecified(false),
+        mSwapChainScaleSpecified(false),
+        mSwapChainScale(1.0f),
+        mClientRectChanged(false),
+        mClientRect({0,0,0,0}),
+        mNewClientRect({0,0,0,0})
+    {
+        mSizeChangedEventToken.value = 0;
+    }
+    virtual ~InspectableNativeWindow(){}
+
+    virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0;
+    virtual HRESULT createSwapChain(ID3D11Device *device,
+                                    IDXGIFactory2 *factory,
+                                    DXGI_FORMAT format,
+                                    unsigned int width,
+                                    unsigned int height,
+                                    bool containsAlpha,
+                                    IDXGISwapChain1 **swapChain) = 0;
+
+    bool getClientRect(RECT *rect)
+    {
+        if (mClientRectChanged)
+        {
+            mClientRect = mNewClientRect;
+        }
+
+        *rect = mClientRect;
+
+        return true;
+    }
+
+    // setNewClientSize is used by the WinRT size change handler. It isn't used by the rest of ANGLE.
+    void setNewClientSize(const Size &newWindowSize)
+    {
+        // If the client doesn't support swapchain resizing then we should have already unregistered from size change handler
+        ASSERT(mSupportsSwapChainResize);
+
+        if (mSupportsSwapChainResize)
+        {
+            // If the swapchain size was specified then we should ignore this call too
+            if (!mSwapChainSizeSpecified)
+            {
+                mNewClientRect     = clientRect(newWindowSize);
+                mClientRectChanged = true;
+
+                // If a scale was specified, then now is the time to apply the scale matrix for the new swapchain size and window size
+                if (mSwapChainScaleSpecified)
+                {
+                    scaleSwapChain(newWindowSize, mNewClientRect);
+                }
+            }
+
+            // Even if the swapchain size was fixed, the window might have changed size.
+            // In this case, we should recalculate the scale matrix to account for the new window size
+            if (mSwapChainSizeSpecified)
+            {
+                scaleSwapChain(newWindowSize, mClientRect);
+            }
+        }
+    }
+
+  protected:
+    virtual HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) = 0;
+    RECT clientRect(const Size &size);
+
+    bool mSupportsSwapChainResize; // Support for IDXGISwapChain::ResizeBuffers method
+    bool mSwapChainSizeSpecified;  // If an EGLRenderSurfaceSizeProperty was specified
+    bool mSwapChainScaleSpecified; // If an EGLRenderResolutionScaleProperty was specified
+    float mSwapChainScale;         // The scale value specified by the EGLRenderResolutionScaleProperty property
+    RECT mClientRect;
+    RECT mNewClientRect;
+    bool mClientRectChanged;
+
+    EventRegistrationToken mSizeChangedEventToken;
+};
+
+bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr);
+bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr);
+bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr);
+
+HRESULT GetOptionalPropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+                                 const wchar_t *propertyName,
+                                 boolean *hasKey,
+                                 ComPtr<ABI::Windows::Foundation::IPropertyValue> &propertyValue);
+
+HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+                                     const wchar_t *propertyName, SIZE *value, bool *valueExists);
+
+HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+                                       const wchar_t *propertyName, float *value, bool *valueExists);
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp
new file mode 100644
index 0000000..2ef2235
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp
@@ -0,0 +1,125 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// NativeWindow11WinRT.cpp: NativeWindow base class for managing IInspectable native window types.
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
+
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+namespace rx
+{
+NativeWindow11WinRT::NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha)
+    : NativeWindow11(window), mHasAlpha(hasAlpha)
+{
+}
+
+bool NativeWindow11WinRT::initialize()
+{
+    EGLNativeWindowType window = getNativeWindow();
+
+    // If the native window type is a IPropertySet, extract the
+    // EGLNativeWindowType (IInspectable) and initialize the
+    // proper host with this IPropertySet.
+    ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet;
+    ComPtr<IInspectable> eglNativeWindow;
+    if (IsEGLConfiguredPropertySet(window, &propertySet, &eglNativeWindow))
+    {
+        // A property set was found and the EGLNativeWindowType was
+        // retrieved. The mWindow member of the host to must be updated
+        // to use the EGLNativeWindowType specified in the property set.
+        // mWindow is treated as a raw pointer not an AddRef'd interface, so
+        // the old mWindow does not need a Release() before this assignment.
+        window = eglNativeWindow.Get();
+    }
+
+    ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
+    ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
+    if (IsCoreWindow(window, &coreWindow))
+    {
+        mImpl = std::make_shared<CoreWindowNativeWindow>();
+        if (mImpl)
+        {
+            return mImpl->initialize(window, propertySet.Get());
+        }
+    }
+    else if (IsSwapChainPanel(window, &swapChainPanel))
+    {
+        mImpl = std::make_shared<SwapChainPanelNativeWindow>();
+        if (mImpl)
+        {
+            return mImpl->initialize(window, propertySet.Get());
+        }
+    }
+    else
+    {
+        ERR() << "Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include "
+                 "ICoreWindow, ISwapChainPanel and IPropertySet";
+    }
+
+    return false;
+}
+
+bool NativeWindow11WinRT::getClientRect(LPRECT rect) const
+{
+    if (mImpl)
+    {
+        return mImpl->getClientRect(rect);
+    }
+
+    return false;
+}
+
+bool NativeWindow11WinRT::isIconic() const
+{
+    return false;
+}
+
+HRESULT NativeWindow11WinRT::createSwapChain(ID3D11Device *device,
+                                             IDXGIFactory *factory,
+                                             DXGI_FORMAT format,
+                                             UINT width,
+                                             UINT height,
+                                             IDXGISwapChain **swapChain)
+{
+    if (mImpl)
+    {
+        IDXGIFactory2 *factory2     = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+        IDXGISwapChain1 *swapChain1 = nullptr;
+        HRESULT result =
+            mImpl->createSwapChain(device, factory2, format, width, height, mHasAlpha, &swapChain1);
+        SafeRelease(factory2);
+        *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
+        return result;
+    }
+
+    return E_UNEXPECTED;
+}
+
+void NativeWindow11WinRT::commitChange()
+{
+}
+
+// static
+bool NativeWindow11WinRT::IsValidNativeWindow(EGLNativeWindowType window)
+{
+    // A Valid EGLNativeWindowType IInspectable can only be:
+    //
+    // ICoreWindow
+    // ISwapChainPanel
+    // IPropertySet
+    //
+    // Anything else will be rejected as an invalid IInspectable.
+    return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h
new file mode 100644
index 0000000..996fd3a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// NativeWindow11WinRT.h: NativeWindow base class for managing IInspectable native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_
+
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+
+#include <memory>
+#include <windows.applicationmodel.core.h>
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+
+namespace rx
+{
+class InspectableNativeWindow;
+
+class NativeWindow11WinRT : public NativeWindow11
+{
+  public:
+    NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha);
+
+    bool initialize() override;
+    bool getClientRect(LPRECT rect) const override;
+    bool isIconic() const override;
+
+    HRESULT createSwapChain(ID3D11Device *device,
+                            IDXGIFactory *factory,
+                            DXGI_FORMAT format,
+                            UINT width,
+                            UINT height,
+                            IDXGISwapChain **swapChain) override;
+
+    void commitChange() override;
+
+    static bool IsValidNativeWindow(EGLNativeWindowType window);
+
+  private:
+    bool mHasAlpha;
+    std::shared_ptr<InspectableNativeWindow> mImpl;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
new file mode 100644
index 0000000..c6d07fc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
@@ -0,0 +1,359 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types.
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
+
+#include <algorithm>
+#include <math.h>
+
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::UI::Xaml;
+using namespace Microsoft::WRL;
+
+namespace rx
+{
+SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow()
+{
+    unregisterForSizeChangeEvents();
+}
+
+template <typename T>
+struct AddFtmBase
+{
+    typedef Implements<RuntimeClassFlags<ClassicCom>, T, FtmBase> Type;
+};
+
+template <typename CODE>
+HRESULT RunOnUIThread(CODE &&code, const ComPtr<ICoreDispatcher> &dispatcher)
+{
+    ComPtr<IAsyncAction> asyncAction;
+    HRESULT result = S_OK;
+
+    boolean hasThreadAccess;
+    result = dispatcher->get_HasThreadAccess(&hasThreadAccess);
+    if (FAILED(result))
+    {
+        return result;
+    }
+
+    if (hasThreadAccess)
+    {
+        return code();
+    }
+    else
+    {
+        Event waitEvent(
+            CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS));
+        if (!waitEvent.IsValid())
+        {
+            return E_FAIL;
+        }
+
+        HRESULT codeResult = E_FAIL;
+        auto handler =
+            Callback<AddFtmBase<IDispatchedHandler>::Type>([&codeResult, &code, &waitEvent]
+                                                           {
+                                                               codeResult = code();
+                                                               SetEvent(waitEvent.Get());
+                                                               return S_OK;
+                                                           });
+
+        result = dispatcher->RunAsync(CoreDispatcherPriority_Normal, handler.Get(),
+                                      asyncAction.GetAddressOf());
+        if (FAILED(result))
+        {
+            return result;
+        }
+
+        auto waitResult = WaitForSingleObjectEx(waitEvent.Get(), 10 * 1000, true);
+        if (waitResult != WAIT_OBJECT_0)
+        {
+            // Wait 10 seconds before giving up. At this point, the application is in an
+            // unrecoverable state (probably deadlocked). We therefore terminate the application
+            // entirely. This also prevents stack corruption if the async operation is eventually
+            // run.
+            ERR()
+                << "Timeout waiting for async action on UI thread. The UI thread might be blocked.";
+            std::terminate();
+            return E_FAIL;
+        }
+
+        return codeResult;
+    }
+}
+
+bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
+{
+    ComPtr<IPropertySet> props = propertySet;
+    ComPtr<IInspectable> win = window;
+    SIZE swapChainSize = {};
+    HRESULT result = S_OK;
+
+    // IPropertySet is an optional parameter and can be null.
+    // If one is specified, cache as an IMap and read the properties
+    // used for initial host initialization.
+    if (propertySet)
+    {
+        result = props.As(&mPropertyMap);
+        if (FAILED(result))
+        {
+            return false;
+        }
+
+        // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet
+        // was prevalidated to contain the EGLNativeWindowType before being passed to
+        // this host.
+        result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &mSwapChainSizeSpecified);
+        if (FAILED(result))
+        {
+            return false;
+        }
+
+        // The EGLRenderResolutionScaleProperty is optional and may be missing. The IPropertySet
+        // was prevalidated to contain the EGLNativeWindowType before being passed to
+        // this host.
+        result = GetOptionalSinglePropertyValue(mPropertyMap, EGLRenderResolutionScaleProperty, &mSwapChainScale, &mSwapChainScaleSpecified);
+        if (FAILED(result))
+        {
+            return false;
+        }
+
+        if (!mSwapChainScaleSpecified)
+        {
+            // Default value for the scale is 1.0f
+            mSwapChainScale = 1.0f;
+        }
+
+        // A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified
+        if (mSwapChainScaleSpecified && mSwapChainSizeSpecified)
+        {
+            ERR() << "It is invalid to specify both an EGLRenderSurfaceSizeProperty and a "
+                     "EGLRenderResolutionScaleProperty.";
+            return false;
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = win.As(&mSwapChainPanel);
+    }
+
+    ComPtr<IDependencyObject> swapChainPanelDependencyObject;
+    if (SUCCEEDED(result))
+    {
+        result = mSwapChainPanel.As(&swapChainPanelDependencyObject);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = swapChainPanelDependencyObject->get_Dispatcher(
+            mSwapChainPanelDispatcher.GetAddressOf());
+    }
+
+    if (SUCCEEDED(result))
+    {
+        // If a swapchain size is specfied, then the automatic resize
+        // behaviors implemented by the host should be disabled.  The swapchain
+        // will be still be scaled when being rendered to fit the bounds
+        // of the host.
+        // Scaling of the swapchain output needs to be handled by the
+        // host for swapchain panels even though the scaling mode setting
+        // DXGI_SCALING_STRETCH is configured on the swapchain.
+        if (mSwapChainSizeSpecified)
+        {
+            mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
+        }
+        else
+        {
+            Size swapChainPanelSize;
+            result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
+                                           &swapChainPanelSize);
+
+            if (SUCCEEDED(result))
+            {
+                // Update the client rect to account for any swapchain scale factor
+                mClientRect = clientRect(swapChainPanelSize);
+            }
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        mNewClientRect = mClientRect;
+        mClientRectChanged = false;
+        return registerForSizeChangeEvents();
+    }
+
+    return false;
+}
+
+bool SwapChainPanelNativeWindow::registerForSizeChangeEvents()
+{
+    ComPtr<ISizeChangedEventHandler> sizeChangedHandler;
+    ComPtr<IFrameworkElement> frameworkElement;
+    HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
+
+    if (SUCCEEDED(result))
+    {
+        result = mSwapChainPanel.As(&frameworkElement);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = RunOnUIThread(
+            [this, frameworkElement, sizeChangedHandler]
+            {
+                return frameworkElement->add_SizeChanged(sizeChangedHandler.Get(),
+                                                         &mSizeChangedEventToken);
+            },
+            mSwapChainPanelDispatcher);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents()
+{
+    ComPtr<IFrameworkElement> frameworkElement;
+    if (mSwapChainPanel && SUCCEEDED(mSwapChainPanel.As(&frameworkElement)))
+    {
+        RunOnUIThread(
+            [this, frameworkElement]
+            {
+                return frameworkElement->remove_SizeChanged(mSizeChangedEventToken);
+            },
+            mSwapChainPanelDispatcher);
+    }
+
+    mSizeChangedEventToken.value = 0;
+}
+
+HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
+                                                    IDXGIFactory2 *factory,
+                                                    DXGI_FORMAT format,
+                                                    unsigned int width,
+                                                    unsigned int height,
+                                                    bool containsAlpha,
+                                                    IDXGISwapChain1 **swapChain)
+{
+    if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
+        height == 0)
+    {
+        return E_INVALIDARG;
+    }
+
+    DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
+    swapChainDesc.Width = width;
+    swapChainDesc.Height = height;
+    swapChainDesc.Format = format;
+    swapChainDesc.Stereo = FALSE;
+    swapChainDesc.SampleDesc.Count = 1;
+    swapChainDesc.SampleDesc.Quality = 0;
+    swapChainDesc.BufferUsage =
+        DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+    swapChainDesc.BufferCount = 2;
+    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+    swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+    swapChainDesc.AlphaMode =
+        containsAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
+
+    *swapChain = nullptr;
+
+    ComPtr<IDXGISwapChain1> newSwapChain;
+    ComPtr<ISwapChainPanelNative> swapChainPanelNative;
+    Size currentPanelSize = {};
+
+    HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
+
+    if (SUCCEEDED(result))
+    {
+        result = mSwapChainPanel.As(&swapChainPanelNative);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = RunOnUIThread(
+            [swapChainPanelNative, newSwapChain]
+            {
+                return swapChainPanelNative->SetSwapChain(newSwapChain.Get());
+            },
+            mSwapChainPanelDispatcher);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel
+        // to perform the runtime-scale behavior.  This swapchain is cached here because there are
+        // no methods for retreiving the currently configured on from ISwapChainPanelNative.
+        mSwapChain = newSwapChain;
+        result = newSwapChain.CopyTo(swapChain);
+    }
+
+    // If the host is responsible for scaling the output of the swapchain, then
+    // scale it now before returning an instance to the caller.  This is done by
+    // first reading the current size of the swapchain panel, then scaling
+    if (SUCCEEDED(result))
+    {
+        if (mSwapChainSizeSpecified || mSwapChainScaleSpecified)
+        {
+            result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
+                                           &currentPanelSize);
+
+            // Scale the swapchain to fit inside the contents of the panel.
+            if (SUCCEEDED(result))
+            {
+                result = scaleSwapChain(currentPanelSize, mClientRect);
+            }
+        }
+    }
+
+    return result;
+}
+
+HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect)
+{
+    Size renderScale = {windowSize.Width / (float)clientRect.right,
+                        windowSize.Height / (float)clientRect.bottom};
+    // Setup a scale matrix for the swap chain
+    DXGI_MATRIX_3X2_F scaleMatrix = {};
+    scaleMatrix._11 = renderScale.Width;
+    scaleMatrix._22 = renderScale.Height;
+
+    ComPtr<IDXGISwapChain2> swapChain2;
+    HRESULT result = mSwapChain.As(&swapChain2);
+    if (SUCCEEDED(result))
+    {
+        result = swapChain2->SetMatrixTransform(&scaleMatrix);
+    }
+
+    return result;
+}
+
+HRESULT GetSwapChainPanelSize(
+    const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
+    const ComPtr<ICoreDispatcher> &dispatcher,
+    Size *windowSize)
+{
+    ComPtr<IUIElement> uiElement;
+    HRESULT result = swapChainPanel.As(&uiElement);
+    if (SUCCEEDED(result))
+    {
+        result = RunOnUIThread(
+            [uiElement, windowSize] { return uiElement->get_RenderSize(windowSize); }, dispatcher);
+    }
+
+    return result;
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
new file mode 100644
index 0000000..f9a2fc0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+
+#include <memory>
+
+namespace rx
+{
+class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow>
+{
+  public:
+    ~SwapChainPanelNativeWindow();
+
+    bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override;
+    HRESULT createSwapChain(ID3D11Device *device,
+                            IDXGIFactory2 *factory,
+                            DXGI_FORMAT format,
+                            unsigned int width,
+                            unsigned int height,
+                            bool containsAlpha,
+                            IDXGISwapChain1 **swapChain) override;
+
+  protected:
+    HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override;
+
+    bool registerForSizeChangeEvents();
+    void unregisterForSizeChangeEvents();
+
+  private:
+    ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel;
+    ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> mSwapChainPanelDispatcher;
+    ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
+    ComPtr<IDXGISwapChain1> mSwapChain;
+};
+
+[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)]
+class SwapChainPanelSizeChangedHandler :
+    public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::UI::Xaml::ISizeChangedEventHandler>
+{
+  public:
+    SwapChainPanelSizeChangedHandler() { }
+    HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
+    {
+        if (!host)
+        {
+            return E_INVALIDARG;
+        }
+
+        mHost = host;
+        return S_OK;
+    }
+
+    // ISizeChangedEventHandler
+    IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs)
+    {
+        std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
+        if (host)
+        {
+            // The size of the ISwapChainPanel control is returned in DIPs.
+            // We are keeping these in dips because the swapchain created for composition
+            // also uses dip units. This keeps dimensions, viewports, etc in the same unit.
+            // XAML Clients of the ISwapChainPanel are required to use dips to define their
+            // layout sizes as well.
+            ABI::Windows::Foundation::Size newSize;
+            HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize);
+            if (SUCCEEDED(result))
+            {
+                host->setNewClientSize(newSize);
+            }
+        }
+
+        return S_OK;
+    }
+
+  private:
+    std::weak_ptr<InspectableNativeWindow> mHost;
+};
+
+HRESULT GetSwapChainPanelSize(
+    const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
+    const ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> &dispatcher,
+    Size *windowSize);
+}
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp
new file mode 100644
index 0000000..6e20594
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp
@@ -0,0 +1,460 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+// WINAPI_FAMILY is required to be defined as WINAPI_FAMILY_PC_APP
+// to ensure that the proper defines are set when including additional
+// headers which rely on Windows Store specific configuration.
+// This would normally be defined already but this unittest exe is compiled
+// as a desktop application which results in WINAPI_FAMILY being
+// set to WINAPI_FAMILY_DESKTOP_APP
+#undef WINAPI_FAMILY
+#define WINAPI_FAMILY WINAPI_FAMILY_PC_APP
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+#include <angle_windowsstore.h>
+#include <windows.ui.xaml.h>
+#include <windows.ui.xaml.media.dxinterop.h>
+
+using namespace rx;
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::System;
+using namespace ABI::Windows::UI::Xaml::Controls;
+using namespace ABI::Windows::UI::Xaml::Data;
+using namespace ABI::Windows::UI::Xaml::Media;
+using namespace ABI::Windows::UI::Xaml::Input;
+using namespace ABI::Windows::UI::Xaml;
+
+namespace
+{
+
+// Mock ISwapChainPanel
+class MockSwapChainPanel : public ISwapChainPanel,
+                                  IFrameworkElement,
+                                  IUIElement,
+                                  ISwapChainPanelNative
+{
+  public:
+    // IUnknown
+    STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
+    {
+        *ppvObject = nullptr;
+
+        if (IsEqualIID(IID_IUnknown, riid))
+        {
+            *ppvObject = reinterpret_cast<IUnknown*>(this);
+            return S_OK;
+        }
+
+        if (IsEqualIID(IID_IInspectable, riid))
+        {
+            *ppvObject = reinterpret_cast<IInspectable*>(this);
+            return S_OK;
+        }
+
+        if (IsEqualIID(IID_ISwapChainPanel, riid))
+        {
+            *ppvObject = static_cast<ISwapChainPanel*>(this);
+            return S_OK;
+        }
+
+        if (IsEqualIID(IID_IFrameworkElement, riid))
+        {
+            *ppvObject = static_cast<IFrameworkElement*>(this);
+            return S_OK;
+        }
+
+        if (IsEqualIID(IID_IUIElement, riid))
+        {
+            *ppvObject = static_cast<IUIElement*>(this);
+            return S_OK;
+        }
+
+        if (IsEqualIID(__uuidof(ISwapChainPanelNative), riid))
+        {
+            *ppvObject = static_cast<ISwapChainPanelNative*>(this);
+            return S_OK;
+        }
+
+        return E_NOINTERFACE;
+    }
+
+    STDMETHOD_(ULONG, AddRef)(){ return 1; }
+    STDMETHOD_(ULONG, Release)(){ return 1; }
+
+    // IInspectable
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetIids, HRESULT(ULONG *, IID**));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetRuntimeClassName, HRESULT(HSTRING *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTrustLevel, HRESULT(TrustLevel *));
+
+    // ISwapChainPanelNative
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, SetSwapChain, HRESULT(IDXGISwapChain *));
+
+    // ISwapChainPanel
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CompositionScaleX, HRESULT(FLOAT *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CompositionScaleY, HRESULT(FLOAT *));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_CompositionScaleChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CXaml__CControls__CSwapChainPanel_IInspectable*, EventRegistrationToken*));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_CompositionScaleChanged, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, CreateCoreIndependentInputSource, HRESULT(CoreInputDeviceTypes, ICoreInputSourceBase**));
+
+    // IFrameworkElement
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Triggers, HRESULT(__FIVector_1_Windows__CUI__CXaml__CTriggerBase **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Resources, HRESULT(IResourceDictionary **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Resources, HRESULT(IResourceDictionary *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Tag, HRESULT(IInspectable **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Tag, HRESULT(IInspectable *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Language, HRESULT(HSTRING *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Language, HRESULT(HSTRING));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_ActualWidth, HRESULT(DOUBLE *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_ActualHeight, HRESULT(DOUBLE *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Width, HRESULT(DOUBLE *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Width, HRESULT(DOUBLE));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Height, HRESULT(DOUBLE *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Height, HRESULT(DOUBLE));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MinWidth, HRESULT(DOUBLE *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MinWidth, HRESULT(DOUBLE));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MaxWidth, HRESULT(DOUBLE *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MaxWidth, HRESULT(DOUBLE));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MinHeight, HRESULT(DOUBLE *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MinHeight, HRESULT(DOUBLE));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MaxHeight, HRESULT(DOUBLE *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MaxHeight, HRESULT(DOUBLE));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_HorizontalAlignment, HRESULT(HorizontalAlignment *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_HorizontalAlignment, HRESULT(HorizontalAlignment));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_VerticalAlignment, HRESULT(VerticalAlignment *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_VerticalAlignment, HRESULT(VerticalAlignment));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Margin, HRESULT(Thickness *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Margin, HRESULT(Thickness));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Name, HRESULT(HSTRING*));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Name, HRESULT(HSTRING));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_BaseUri, HRESULT(IUriRuntimeClass **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_DataContext, HRESULT(IInspectable **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_DataContext, HRESULT(IInspectable *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Style, HRESULT(IStyle **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Style, HRESULT(IStyle *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Parent, HRESULT(IDependencyObject **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_FlowDirection, HRESULT(FlowDirection *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_FlowDirection, HRESULT(FlowDirection));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Loaded, HRESULT(IRoutedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Loaded, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Unloaded, HRESULT(IRoutedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Unloaded, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_SizeChanged, HRESULT(ISizeChangedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_SizeChanged, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_LayoutUpdated, HRESULT(__FIEventHandler_1_IInspectable *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_LayoutUpdated, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, FindName, HRESULT(HSTRING, IInspectable **));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, SetBinding, HRESULT(IDependencyProperty *, IBindingBase *));
+
+    // IUIElement
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_DesiredSize, HRESULT(ABI::Windows::Foundation::Size *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_AllowDrop, HRESULT(boolean *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_AllowDrop, HRESULT(boolean));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Opacity, HRESULT(DOUBLE *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Opacity, HRESULT(DOUBLE));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Clip, HRESULT(IRectangleGeometry **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Clip, HRESULT(IRectangleGeometry *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_RenderTransform, HRESULT(ITransform **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_RenderTransform, HRESULT(ITransform *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Projection, HRESULT(IProjection **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Projection, HRESULT(IProjection *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_RenderTransformOrigin, HRESULT(Point *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_RenderTransformOrigin, HRESULT(Point));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsHitTestVisible, HRESULT(boolean *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsHitTestVisible, HRESULT(boolean));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Visibility, HRESULT(Visibility *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Visibility, HRESULT(Visibility));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_RenderSize, HRESULT(Size *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_UseLayoutRounding, HRESULT(boolean *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_UseLayoutRounding, HRESULT(boolean));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Transitions, HRESULT(__FIVector_1_Windows__CUI__CXaml__CMedia__CAnimation__CTransition **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Transitions, HRESULT(__FIVector_1_Windows__CUI__CXaml__CMedia__CAnimation__CTransition *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CacheMode, HRESULT(ICacheMode **));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_CacheMode, HRESULT(ICacheMode *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsTapEnabled, HRESULT(boolean *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsTapEnabled, HRESULT(boolean));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsDoubleTapEnabled, HRESULT(boolean *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsDoubleTapEnabled, HRESULT(boolean));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsRightTapEnabled, HRESULT(boolean *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsRightTapEnabled, HRESULT(boolean));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsHoldingEnabled, HRESULT(boolean *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsHoldingEnabled, HRESULT(boolean));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_ManipulationMode, HRESULT(ManipulationModes *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_ManipulationMode, HRESULT(ManipulationModes));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_PointerCaptures, HRESULT(__FIVectorView_1_Windows__CUI__CXaml__CInput__CPointer **));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyUp, HRESULT(IKeyEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyUp, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyDown, HRESULT(IKeyEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyDown, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_GotFocus, HRESULT(IRoutedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_GotFocus, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_LostFocus, HRESULT(IRoutedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_LostFocus, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DragEnter, HRESULT(IDragEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DragEnter, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DragLeave, HRESULT(IDragEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DragLeave, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DragOver, HRESULT(IDragEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DragOver, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Drop, HRESULT(IDragEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Drop, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerPressed, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerPressed, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerMoved, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerMoved, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerReleased, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerReleased, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerExited, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerExited, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerCaptureLost, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerCaptureLost, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerCanceled, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerCanceled, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerWheelChanged, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerWheelChanged, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerEntered, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerEntered, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Tapped, HRESULT(ITappedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Tapped, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DoubleTapped, HRESULT(IDoubleTappedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DoubleTapped, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Holding, HRESULT(IHoldingEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Holding, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_RightTapped, HRESULT(IRightTappedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_RightTapped, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationStarting, HRESULT(IManipulationStartingEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationStarting, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationInertiaStarting, HRESULT(IManipulationInertiaStartingEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationInertiaStarting, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationStarted, HRESULT(IManipulationStartedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationStarted, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationDelta, HRESULT(IManipulationDeltaEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationDelta, HRESULT(EventRegistrationToken));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationCompleted, HRESULT(IManipulationCompletedEventHandler *, EventRegistrationToken *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationCompleted, HRESULT(EventRegistrationToken));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Measure, HRESULT(Size));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Arrange, HRESULT(Rect));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, CapturePointer, HRESULT(IPointer *, boolean *));
+    MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, ReleasePointerCapture, HRESULT(IPointer *));
+    MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, ReleasePointerCaptures, HRESULT());
+    MOCK_METHOD3_WITH_CALLTYPE(STDMETHODCALLTYPE, AddHandler, HRESULT(IRoutedEvent *, IInspectable *, boolean));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, RemoveHandler, HRESULT(IRoutedEvent *, IInspectable *));
+    MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, TransformToVisual, HRESULT(IUIElement *, IGeneralTransform **));
+    MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, InvalidateMeasure, HRESULT());
+    MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, InvalidateArrange, HRESULT());
+    MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, UpdateLayout, HRESULT());
+};
+
+HRESULT CreatePropertyMap(IMap<HSTRING, IInspectable*>** propertyMap)
+{
+    HRESULT result = S_OK;
+    ComPtr<IPropertySet> propertySet;
+    ComPtr<IActivationFactory> propertySetFactory;
+    result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Collections_PropertySet).Get(), &propertySetFactory);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    result = propertySetFactory->ActivateInstance(&propertySet);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    result = propertySet.CopyTo(propertyMap);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    return result;
+}
+
+HRESULT CreatePropertyValueStatics(IPropertyValueStatics** propertyStatics)
+{
+    ComPtr<IPropertyValueStatics> propertyValueStatics;
+    HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), &propertyValueStatics);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    result = propertyValueStatics.CopyTo(propertyStatics);
+    EXPECT_HRESULT_SUCCEEDED(result);
+
+    return result;
+}
+
+HRESULT SetInspectablePropertyValue(const ComPtr<IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t* propertyName, IInspectable* inspectable)
+{
+    boolean propertyReplaced = false;
+    return propertyMap->Insert(HStringReference(propertyName).Get(), inspectable, &propertyReplaced);
+}
+
+void expectNativeWindowInitCalls(MockSwapChainPanel &panel, bool expectRenderSize)
+{
+    if (expectRenderSize)
+    {
+        EXPECT_CALL(panel, get_RenderSize(testing::_)).Times(1);
+    }
+
+    EXPECT_CALL(panel, add_SizeChanged(testing::_, testing::_)).Times(1);
+    EXPECT_CALL(panel, remove_SizeChanged(testing::_)).Times(1);
+}
+
+TEST(NativeWindowTest, SwapChainPanelByItself)
+{
+    MockSwapChainPanel mockSwapChainPanel;
+    NativeWindow nativeWindow(reinterpret_cast<IInspectable*>(&mockSwapChainPanel));
+    expectNativeWindowInitCalls(mockSwapChainPanel, true);
+    EXPECT_TRUE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, SwapChainPanelInPropertySet)
+{
+    // COM is required to be initialized for creation of the property set
+    EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
+    {
+        MockSwapChainPanel mockSwapChainPanel;
+        ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+
+        // Create a simple property set with the swapchainpanel
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel)));
+
+        // Check native window init calls
+        NativeWindow nativeWindow(propertySet.Get());
+        expectNativeWindowInitCalls(mockSwapChainPanel, true);
+        EXPECT_TRUE(nativeWindow.initialize());
+    }
+    CoUninitialize();
+}
+
+TEST(NativeWindowTest, SwapChainPanelInPropertySetWithSizeAndScale)
+{
+    // COM is required to be initialized for creation of the property set
+    EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
+    {
+        MockSwapChainPanel mockSwapChainPanel;
+        ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+        ComPtr<IPropertyValueStatics> propertyValueStatics;
+        ComPtr<IPropertyValue> singleValue;
+        ComPtr<IPropertyValue> sizeValue;
+
+        // Create a simple property set with the swapchainpanel
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel)));
+
+        // Add a valid scale factor to the property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+        propertyValueStatics->CreateSingle(0.5f, reinterpret_cast<IInspectable**>(singleValue.GetAddressOf()));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderResolutionScaleProperty, reinterpret_cast<IInspectable*>(singleValue.Get())));
+
+        // Add a valid size to the property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+        propertyValueStatics->CreateSize({ 480, 800 }, reinterpret_cast<IInspectable**>(sizeValue.GetAddressOf()));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderSurfaceSizeProperty, reinterpret_cast<IInspectable*>(sizeValue.Get())));
+
+        // Check native window init fails, since we shouldn't be able to set a size and a scale together
+        NativeWindow nativeWindow(propertySet.Get());
+        EXPECT_FALSE(nativeWindow.initialize());
+    }
+    CoUninitialize();
+}
+
+// Tests that the scale property works as expected in a property set with a SwapChainPanel
+class SwapChainPanelScaleTest : public testing::TestWithParam<std::pair<float, bool>>
+{
+};
+
+TEST_P(SwapChainPanelScaleTest, ValidateScale)
+{
+    float scale = GetParam().first;
+    bool expectedResult = GetParam().second;
+
+    // COM is required to be initialized for creation of the property set
+    EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
+    {
+        MockSwapChainPanel mockSwapChainPanel;
+        ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+        ComPtr<IPropertyValueStatics> propertyValueStatics;
+        ComPtr<IPropertyValue> singleValue;
+
+        // Create a simple property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel)));
+
+        // Add a valid scale factor to the property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+        propertyValueStatics->CreateSingle(scale, reinterpret_cast<IInspectable**>(singleValue.GetAddressOf()));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderResolutionScaleProperty, reinterpret_cast<IInspectable*>(singleValue.Get())));
+
+        // Check native window init status and calls to the mock swapchainpanel
+        NativeWindow nativeWindow(propertySet.Get());
+        if (expectedResult)
+        {
+            expectNativeWindowInitCalls(mockSwapChainPanel, true);
+        }
+
+        EXPECT_EQ(nativeWindow.initialize(), expectedResult);
+    }
+    CoUninitialize();
+}
+
+typedef std::pair<float, bool> scaleValidPair;
+static const scaleValidPair scales[] = { scaleValidPair(1.0f,   true),
+                                         scaleValidPair(0.5f,   true),
+                                         scaleValidPair(0.0f,   false),
+                                         scaleValidPair(0.01f,  true),
+                                         scaleValidPair(2.00f,  true) };
+
+INSTANTIATE_TEST_CASE_P(NativeWindowTest,
+                        SwapChainPanelScaleTest,
+                        testing::ValuesIn(scales));
+
+// Tests that the size property works as expected in a property set with a SwapChainPanel
+class SwapChainPanelSizeTest : public testing::TestWithParam<std::tuple<float, float, bool>>
+{
+};
+
+TEST_P(SwapChainPanelSizeTest, ValidateSize)
+{
+    Size renderSize = { std::get<0>(GetParam()), std::get<1>(GetParam()) };
+    bool expectedResult = std::get<2>(GetParam());
+
+    // COM is required to be initialized for creation of the property set
+    EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
+    {
+        MockSwapChainPanel mockSwapChainPanel;
+        ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+        ComPtr<IPropertyValueStatics> propertyValueStatics;
+        ComPtr<IPropertyValue> sizeValue;
+
+        // Create a simple property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel)));
+
+        // Add a valid size to the property set
+        EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+        propertyValueStatics->CreateSize(renderSize, reinterpret_cast<IInspectable**>(sizeValue.GetAddressOf()));
+        EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderSurfaceSizeProperty, reinterpret_cast<IInspectable*>(sizeValue.Get())));
+
+        // Check native window init status and calls to the mock swapchainpanel
+        NativeWindow nativeWindow(propertySet.Get());
+        if (expectedResult)
+        {
+            expectNativeWindowInitCalls(mockSwapChainPanel, false);
+        }
+
+        EXPECT_EQ(nativeWindow.initialize(), expectedResult);
+    }
+    CoUninitialize();
+}
+
+typedef std::tuple<float, float, bool> sizeValidPair;
+static const sizeValidPair sizes[] = { sizeValidPair( 800,  480, true),
+                                       sizeValidPair(   0,  480, false),
+                                       sizeValidPair( 800,    0, false),
+                                       sizeValidPair(   0,    0, false) };
+
+INSTANTIATE_TEST_CASE_P(NativeWindowTest,
+                        SwapChainPanelSizeTest,
+                        testing::ValuesIn(sizes));
+
+} // namespace
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
new file mode 100644
index 0000000..5e46afb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
@@ -0,0 +1,805 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit9.cpp: Surface copy utility class.
+
+#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
+
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+
+namespace
+{
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h"
+
+const BYTE *const g_shaderCode[] = {
+    g_vs20_standardvs,
+    g_ps20_passthroughps,
+    g_ps20_luminanceps,
+    g_ps20_luminancepremultps,
+    g_ps20_luminanceunmultps,
+    g_ps20_componentmaskps,
+    g_ps20_componentmaskpremultps,
+    g_ps20_componentmaskunmultps,
+};
+
+const size_t g_shaderSize[] = {
+    sizeof(g_vs20_standardvs),
+    sizeof(g_ps20_passthroughps),
+    sizeof(g_ps20_luminanceps),
+    sizeof(g_ps20_luminancepremultps),
+    sizeof(g_ps20_luminanceunmultps),
+    sizeof(g_ps20_componentmaskps),
+    sizeof(g_ps20_componentmaskpremultps),
+    sizeof(g_ps20_componentmaskunmultps),
+};
+}
+
+namespace rx
+{
+
+Blit9::Blit9(Renderer9 *renderer)
+    : mRenderer(renderer),
+      mGeometryLoaded(false),
+      mQuadVertexBuffer(nullptr),
+      mQuadVertexDeclaration(nullptr),
+      mSavedStateBlock(nullptr),
+      mSavedRenderTarget(nullptr),
+      mSavedDepthStencil(nullptr)
+{
+    memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
+}
+
+Blit9::~Blit9()
+{
+    SafeRelease(mSavedStateBlock);
+    SafeRelease(mQuadVertexBuffer);
+    SafeRelease(mQuadVertexDeclaration);
+
+    for (int i = 0; i < SHADER_COUNT; i++)
+    {
+        SafeRelease(mCompiledShaders[i]);
+    }
+}
+
+gl::Error Blit9::initialize()
+{
+    if (mGeometryLoaded)
+    {
+        return gl::NoError();
+    }
+
+    static const float quad[] =
+    {
+        -1, -1,
+        -1,  1,
+         1, -1,
+         1,  1
+    };
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0,
+                                                D3DPOOL_DEFAULT, &mQuadVertexBuffer, nullptr);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal blit vertex shader, result: 0x%X.", result);
+    }
+
+    void *lockPtr = nullptr;
+    result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
+
+    if (FAILED(result) || lockPtr == nullptr)
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        SafeRelease(mQuadVertexBuffer);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex shader, result: 0x%X.", result);
+    }
+
+    memcpy(lockPtr, quad, sizeof(quad));
+    mQuadVertexBuffer->Unlock();
+
+    static const D3DVERTEXELEMENT9 elements[] =
+    {
+        { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
+        D3DDECL_END()
+    };
+
+    result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        SafeRelease(mQuadVertexBuffer);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex declaration, result: 0x%X.", result);
+    }
+
+    mGeometryLoaded = true;
+    return gl::NoError();
+}
+
+template <class D3DShaderType>
+gl::Error Blit9::setShader(ShaderId source, const char *profile,
+                           gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader),
+                           HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
+{
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    D3DShaderType *shader = nullptr;
+
+    if (mCompiledShaders[source] != nullptr)
+    {
+        shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
+    }
+    else
+    {
+        const BYTE* shaderCode = g_shaderCode[source];
+        size_t shaderSize = g_shaderSize[source];
+        ANGLE_TRY((mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize, &shader));
+        mCompiledShaders[source] = shader;
+    }
+
+    HRESULT hr = (device->*setShader)(shader);
+    if (FAILED(hr))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to set shader for blit operation, result: 0x%X.", hr);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Blit9::setVertexShader(ShaderId shader)
+{
+    return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
+}
+
+gl::Error Blit9::setPixelShader(ShaderId shader)
+{
+    return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
+}
+
+RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const
+{
+    D3DSURFACE_DESC desc;
+    surface->GetDesc(&desc);
+
+    RECT rect;
+    rect.left = 0;
+    rect.top = 0;
+    rect.right = desc.Width;
+    rect.bottom = desc.Height;
+
+    return rect;
+}
+
+gl::Extents Blit9::getSurfaceSize(IDirect3DSurface9 *surface) const
+{
+    D3DSURFACE_DESC desc;
+    surface->GetDesc(&desc);
+
+    return gl::Extents(desc.Width, desc.Height, 1);
+}
+
+gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+{
+    ANGLE_TRY(initialize());
+
+    IDirect3DBaseTexture9 *texture = nullptr;
+    ANGLE_TRY(copySurfaceToTexture(source, getSurfaceRect(source), &texture));
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    saveState();
+
+    device->SetTexture(0, texture);
+    device->SetRenderTarget(0, dest);
+
+    setVertexShader(SHADER_VS_STANDARD);
+    setPixelShader(SHADER_PS_PASSTHROUGH);
+
+    setCommonBlitState();
+    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
+    setViewportAndShaderConstants(getSurfaceRect(source), getSurfaceSize(source),
+                                  getSurfaceRect(dest), false);
+
+    render();
+
+    SafeRelease(texture);
+
+    restoreState();
+
+    return gl::NoError();
+}
+
+gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level)
+{
+    ANGLE_TRY(initialize());
+
+    const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
+    ASSERT(colorbuffer);
+
+    RenderTarget9 *renderTarget9 = nullptr;
+    ANGLE_TRY(colorbuffer->getRenderTarget(&renderTarget9));
+    ASSERT(renderTarget9);
+
+    IDirect3DSurface9 *source = renderTarget9->getSurface();
+    ASSERT(source);
+
+    IDirect3DSurface9 *destSurface = nullptr;
+    TextureStorage9 *storage9      = GetAs<TextureStorage9>(storage);
+    gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, true, &destSurface);
+    if (error.isError())
+    {
+        SafeRelease(source);
+        return error;
+    }
+    ASSERT(destSurface);
+
+    gl::Error result =
+        copy(source, nullptr, sourceRect, destFormat, destOffset, destSurface, false, false, false);
+
+    SafeRelease(destSurface);
+    SafeRelease(source);
+
+    return result;
+}
+
+gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level)
+{
+    gl::Error error = initialize();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
+    ASSERT(colorbuffer);
+
+    RenderTarget9 *renderTarget9 = nullptr;
+    error = colorbuffer->getRenderTarget(&renderTarget9);
+    if (error.isError())
+    {
+        return error;
+    }
+    ASSERT(renderTarget9);
+
+    IDirect3DSurface9 *source = renderTarget9->getSurface();
+    ASSERT(source);
+
+    IDirect3DSurface9 *destSurface = nullptr;
+    TextureStorage9 *storage9      = GetAs<TextureStorage9>(storage);
+    error = storage9->getSurfaceLevel(target, level, true, &destSurface);
+    if (error.isError())
+    {
+        SafeRelease(source);
+        return error;
+    }
+    ASSERT(destSurface);
+
+    gl::Error result =
+        copy(source, nullptr, sourceRect, destFormat, destOffset, destSurface, false, false, false);
+
+    SafeRelease(destSurface);
+    SafeRelease(source);
+
+    return result;
+}
+
+gl::Error Blit9::copyTexture2D(const gl::Texture *source,
+                               GLint sourceLevel,
+                               const RECT &sourceRect,
+                               GLenum destFormat,
+                               const gl::Offset &destOffset,
+                               TextureStorage *storage,
+                               GLint destLevel,
+                               bool flipY,
+                               bool premultiplyAlpha,
+                               bool unmultiplyAlpha)
+{
+    ANGLE_TRY(initialize());
+
+    const TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+
+    TextureStorage *sourceStorage = nullptr;
+    ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(&sourceStorage));
+
+    TextureStorage9_2D *sourceStorage9 = GetAs<TextureStorage9_2D>(sourceStorage);
+    ASSERT(sourceStorage9);
+
+    TextureStorage9_2D *destStorage9 = GetAs<TextureStorage9_2D>(storage);
+    ASSERT(destStorage9);
+
+    ASSERT(sourceLevel == 0);
+    IDirect3DBaseTexture9 *sourceTexture = nullptr;
+    ANGLE_TRY(sourceStorage9->getBaseTexture(&sourceTexture));
+
+    IDirect3DSurface9 *sourceSurface = nullptr;
+    ANGLE_TRY(sourceStorage9->getSurfaceLevel(GL_TEXTURE_2D, sourceLevel, true, &sourceSurface));
+
+    IDirect3DSurface9 *destSurface = nullptr;
+    gl::Error error = destStorage9->getSurfaceLevel(GL_TEXTURE_2D, destLevel, true, &destSurface);
+    if (error.isError())
+    {
+        SafeRelease(sourceSurface);
+        return error;
+    }
+
+    error = copy(sourceSurface, sourceTexture, sourceRect, destFormat, destOffset, destSurface,
+                 flipY, premultiplyAlpha, unmultiplyAlpha);
+
+    SafeRelease(sourceSurface);
+    SafeRelease(destSurface);
+
+    return error;
+}
+
+gl::Error Blit9::copy(IDirect3DSurface9 *source,
+                      IDirect3DBaseTexture9 *sourceTexture,
+                      const RECT &sourceRect,
+                      GLenum destFormat,
+                      const gl::Offset &destOffset,
+                      IDirect3DSurface9 *dest,
+                      bool flipY,
+                      bool premultiplyAlpha,
+                      bool unmultiplyAlpha)
+{
+    ASSERT(source != nullptr && dest != nullptr);
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    D3DSURFACE_DESC sourceDesc;
+    D3DSURFACE_DESC destDesc;
+    source->GetDesc(&sourceDesc);
+    dest->GetDesc(&destDesc);
+
+    // Check if it's possible to use StetchRect
+    if (sourceDesc.Format == destDesc.Format && (destDesc.Usage & D3DUSAGE_RENDERTARGET) &&
+        d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat) && !flipY &&
+        premultiplyAlpha == unmultiplyAlpha)
+    {
+        RECT destRect = { destOffset.x, destOffset.y, destOffset.x + (sourceRect.right - sourceRect.left), destOffset.y + (sourceRect.bottom - sourceRect.top)};
+        HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit between textures, StretchRect result: 0x%X.", result);
+        }
+
+        return gl::NoError();
+    }
+    else
+    {
+        IDirect3DBaseTexture9 *texture = sourceTexture;
+        RECT adjustedSourceRect        = sourceRect;
+        gl::Extents sourceSize(sourceDesc.Width, sourceDesc.Height, 1);
+
+        if (texture == nullptr)
+        {
+            ANGLE_TRY(copySurfaceToTexture(source, sourceRect, &texture));
+
+            // copySurfaceToTexture only copies in the sourceRect area of the source surface.
+            // Adjust sourceRect so that it is now covering the entire source texture
+            adjustedSourceRect.left   = 0;
+            adjustedSourceRect.right  = sourceRect.right - sourceRect.left;
+            adjustedSourceRect.top    = 0;
+            adjustedSourceRect.bottom = sourceRect.bottom - sourceRect.top;
+
+            sourceSize.width  = sourceRect.right - sourceRect.left;
+            sourceSize.height = sourceRect.bottom - sourceRect.top;
+        }
+        else
+        {
+            texture->AddRef();
+        }
+
+        gl::Error error = formatConvert(texture, adjustedSourceRect, sourceSize, destFormat,
+                                        destOffset, dest, flipY, premultiplyAlpha, unmultiplyAlpha);
+
+        SafeRelease(texture);
+
+        return error;
+    }
+}
+
+gl::Error Blit9::formatConvert(IDirect3DBaseTexture9 *source,
+                               const RECT &sourceRect,
+                               const gl::Extents &sourceSize,
+                               GLenum destFormat,
+                               const gl::Offset &destOffset,
+                               IDirect3DSurface9 *dest,
+                               bool flipY,
+                               bool premultiplyAlpha,
+                               bool unmultiplyAlpha)
+{
+    ANGLE_TRY(initialize());
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    saveState();
+
+    device->SetTexture(0, source);
+    device->SetRenderTarget(0, dest);
+
+    RECT destRect;
+    destRect.left   = destOffset.x;
+    destRect.right  = destOffset.x + (sourceRect.right - sourceRect.left);
+    destRect.top    = destOffset.y;
+    destRect.bottom = destOffset.y + (sourceRect.bottom - sourceRect.top);
+
+    setViewportAndShaderConstants(sourceRect, sourceSize, destRect, flipY);
+
+    setCommonBlitState();
+
+    gl::Error error = setFormatConvertShaders(destFormat, flipY, premultiplyAlpha, unmultiplyAlpha);
+    if (!error.isError())
+    {
+        render();
+    }
+
+    restoreState();
+
+    return error;
+}
+
+gl::Error Blit9::setFormatConvertShaders(GLenum destFormat,
+                                         bool flipY,
+                                         bool premultiplyAlpha,
+                                         bool unmultiplyAlpha)
+{
+    ANGLE_TRY(setVertexShader(SHADER_VS_STANDARD));
+
+    switch (destFormat)
+    {
+      case GL_RGBA:
+      case GL_BGRA_EXT:
+      case GL_RGB:
+      case GL_RG_EXT:
+      case GL_RED_EXT:
+      case GL_ALPHA:
+          if (premultiplyAlpha == unmultiplyAlpha)
+          {
+              ANGLE_TRY(setPixelShader(SHADER_PS_COMPONENTMASK));
+          }
+          else if (premultiplyAlpha)
+          {
+              ANGLE_TRY(setPixelShader(SHADER_PS_COMPONENTMASK_PREMULTIPLY_ALPHA));
+          }
+          else
+          {
+              ASSERT(unmultiplyAlpha);
+              ANGLE_TRY(setPixelShader(SHADER_PS_COMPONENTMASK_UNMULTIPLY_ALPHA));
+          }
+          break;
+
+      case GL_LUMINANCE:
+      case GL_LUMINANCE_ALPHA:
+          if (premultiplyAlpha == unmultiplyAlpha)
+          {
+              ANGLE_TRY(setPixelShader(SHADER_PS_LUMINANCE));
+          }
+          else if (premultiplyAlpha)
+          {
+              ANGLE_TRY(setPixelShader(SHADER_PS_LUMINANCE_PREMULTIPLY_ALPHA));
+          }
+          else
+          {
+              ASSERT(unmultiplyAlpha);
+              ANGLE_TRY(setPixelShader(SHADER_PS_LUMINANCE_UNMULTIPLY_ALPHA));
+          }
+          break;
+
+      default:
+          UNREACHABLE();
+    }
+
+    enum { X = 0, Y = 1, Z = 2, W = 3 };
+
+    // The meaning of this constant depends on the shader that was selected.
+    // See the shader assembly code above for details.
+    // Allocate one array for both registers and split it into two float4's.
+    float psConst[8] = { 0 };
+    float *multConst = &psConst[0];
+    float *addConst = &psConst[4];
+
+    switch (destFormat)
+    {
+      default: UNREACHABLE();
+      case GL_RGBA:
+      case GL_BGRA_EXT:
+        multConst[X] = 1;
+        multConst[Y] = 1;
+        multConst[Z] = 1;
+        multConst[W] = 1;
+        addConst[X] = 0;
+        addConst[Y] = 0;
+        addConst[Z] = 0;
+        addConst[W] = 0;
+        break;
+
+      case GL_RGB:
+        multConst[X] = 1;
+        multConst[Y] = 1;
+        multConst[Z] = 1;
+        multConst[W] = 0;
+        addConst[X] = 0;
+        addConst[Y] = 0;
+        addConst[Z] = 0;
+        addConst[W] = 1;
+        break;
+
+      case GL_RG_EXT:
+        multConst[X] = 1;
+        multConst[Y] = 1;
+        multConst[Z] = 0;
+        multConst[W] = 0;
+        addConst[X] = 0;
+        addConst[Y] = 0;
+        addConst[Z] = 0;
+        addConst[W] = 1;
+        break;
+
+      case GL_RED_EXT:
+        multConst[X] = 1;
+        multConst[Y] = 0;
+        multConst[Z] = 0;
+        multConst[W] = 0;
+        addConst[X] = 0;
+        addConst[Y] = 0;
+        addConst[Z] = 0;
+        addConst[W] = 1;
+        break;
+
+      case GL_ALPHA:
+        multConst[X] = 0;
+        multConst[Y] = 0;
+        multConst[Z] = 0;
+        multConst[W] = 1;
+        addConst[X] = 0;
+        addConst[Y] = 0;
+        addConst[Z] = 0;
+        addConst[W] = 0;
+        break;
+
+      case GL_LUMINANCE:
+        multConst[X] = 1;
+        multConst[Y] = 0;
+        multConst[Z] = 0;
+        multConst[W] = 0;
+        addConst[X] = 0;
+        addConst[Y] = 0;
+        addConst[Z] = 0;
+        addConst[W] = 1;
+        break;
+
+      case GL_LUMINANCE_ALPHA:
+        multConst[X] = 1;
+        multConst[Y] = 0;
+        multConst[Z] = 0;
+        multConst[W] = 1;
+        addConst[X] = 0;
+        addConst[Y] = 0;
+        addConst[Z] = 0;
+        addConst[W] = 0;
+        break;
+    }
+
+    mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2);
+
+    return gl::NoError();
+}
+
+gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface,
+                                      const RECT &sourceRect,
+                                      IDirect3DBaseTexture9 **outTexture)
+{
+    ASSERT(surface);
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    D3DSURFACE_DESC sourceDesc;
+    surface->GetDesc(&sourceDesc);
+
+    // Copy the render target into a texture
+    IDirect3DTexture9 *texture;
+    HRESULT result = device->CreateTexture(
+        sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1,
+        D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, nullptr);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for blit, result: 0x%X.", result);
+    }
+
+    IDirect3DSurface9 *textureSurface;
+    result = texture->GetSurfaceLevel(0, &textureSurface);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        SafeRelease(texture);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result);
+    }
+
+    mRenderer->endScene();
+    result = device->StretchRect(surface, &sourceRect, textureSurface, nullptr, D3DTEXF_NONE);
+
+    SafeRelease(textureSurface);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        SafeRelease(texture);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result);
+    }
+
+    *outTexture = texture;
+    return gl::NoError();
+}
+
+void Blit9::setViewportAndShaderConstants(const RECT &sourceRect,
+                                          const gl::Extents &sourceSize,
+                                          const RECT &destRect,
+                                          bool flipY)
+{
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    D3DVIEWPORT9 vp;
+    vp.X      = destRect.left;
+    vp.Y      = destRect.top;
+    vp.Width  = destRect.right - destRect.left;
+    vp.Height = destRect.bottom - destRect.top;
+    vp.MinZ   = 0.0f;
+    vp.MaxZ   = 1.0f;
+    device->SetViewport(&vp);
+
+    float vertexConstants[8] = {
+        // halfPixelAdjust
+        -1.0f / vp.Width, 1.0f / vp.Height, 0, 0,
+        // texcoordOffset
+        static_cast<float>(sourceRect.left) / sourceSize.width,
+        static_cast<float>(flipY ? sourceRect.bottom : sourceRect.top) / sourceSize.height,
+        static_cast<float>(sourceRect.right - sourceRect.left) / sourceSize.width,
+        static_cast<float>(flipY ? sourceRect.top - sourceRect.bottom
+                                 : sourceRect.bottom - sourceRect.top) /
+            sourceSize.height,
+    };
+
+    device->SetVertexShaderConstantF(0, vertexConstants, 2);
+}
+
+void Blit9::setCommonBlitState()
+{
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    device->SetDepthStencilSurface(nullptr);
+
+    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+    device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+
+    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+    device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+
+    RECT scissorRect = {0};   // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
+    device->SetScissorRect(&scissorRect);
+
+    for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        device->SetStreamSourceFreq(i, 1);
+    }
+}
+
+void Blit9::render()
+{
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
+    hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+    mRenderer->startScene();
+    hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
+
+void Blit9::saveState()
+{
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    HRESULT hr;
+
+    device->GetDepthStencilSurface(&mSavedDepthStencil);
+    device->GetRenderTarget(0, &mSavedRenderTarget);
+
+    if (mSavedStateBlock == nullptr)
+    {
+        hr = device->BeginStateBlock();
+        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+        setCommonBlitState();
+
+        static const float dummyConst[8] = { 0 };
+
+        device->SetVertexShader(nullptr);
+        device->SetVertexShaderConstantF(0, dummyConst, 2);
+        device->SetPixelShader(nullptr);
+        device->SetPixelShaderConstantF(0, dummyConst, 2);
+
+        D3DVIEWPORT9 dummyVp;
+        dummyVp.X = 0;
+        dummyVp.Y = 0;
+        dummyVp.Width = 1;
+        dummyVp.Height = 1;
+        dummyVp.MinZ = 0;
+        dummyVp.MaxZ = 1;
+
+        device->SetViewport(&dummyVp);
+
+        device->SetTexture(0, nullptr);
+
+        device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
+
+        device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+        hr = device->EndStateBlock(&mSavedStateBlock);
+        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+    }
+
+    ASSERT(mSavedStateBlock != nullptr);
+
+    if (mSavedStateBlock != nullptr)
+    {
+        hr = mSavedStateBlock->Capture();
+        ASSERT(SUCCEEDED(hr));
+    }
+}
+
+void Blit9::restoreState()
+{
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    device->SetDepthStencilSurface(mSavedDepthStencil);
+    SafeRelease(mSavedDepthStencil);
+
+    device->SetRenderTarget(0, mSavedRenderTarget);
+    SafeRelease(mSavedRenderTarget);
+
+    ASSERT(mSavedStateBlock != nullptr);
+
+    if (mSavedStateBlock != nullptr)
+    {
+        mSavedStateBlock->Apply();
+    }
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h
new file mode 100644
index 0000000..65fbcf4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit9.cpp: Surface copy utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+#include <GLES2/gl2.h>
+
+namespace gl
+{
+class Framebuffer;
+class Texture;
+struct Extents;
+struct Offset;
+}
+
+namespace rx
+{
+class Renderer9;
+class TextureStorage;
+
+class Blit9 : angle::NonCopyable
+{
+  public:
+    explicit Blit9(Renderer9 *renderer);
+    ~Blit9();
+
+    gl::Error initialize();
+
+    // Copy from source surface to dest surface.
+    // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+    gl::Error copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level);
+    gl::Error copyCube(const gl::Framebuffer *framebuffer,
+                       const RECT &sourceRect,
+                       GLenum destFormat,
+                       const gl::Offset &destOffset,
+                       TextureStorage *storage,
+                       GLenum target,
+                       GLint level);
+    gl::Error copyTexture2D(const gl::Texture *source,
+                            GLint sourceLevel,
+                            const RECT &sourceRect,
+                            GLenum destFormat,
+                            const gl::Offset &destOffset,
+                            TextureStorage *storage,
+                            GLint destLevel,
+                            bool flipY,
+                            bool premultiplyAlpha,
+                            bool unmultiplyAlpha);
+
+    // 2x2 box filter sample from source to dest.
+    // Requires that source is RGB(A) and dest has the same format as source.
+    gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+  private:
+    Renderer9 *mRenderer;
+
+    bool mGeometryLoaded;
+    IDirect3DVertexBuffer9 *mQuadVertexBuffer;
+    IDirect3DVertexDeclaration9 *mQuadVertexDeclaration;
+
+    // Copy from source texture to dest surface.
+    // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+    // source is interpreted as RGBA and destFormat specifies the desired result format. For
+    // example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
+    gl::Error formatConvert(IDirect3DBaseTexture9 *source,
+                            const RECT &sourceRect,
+                            const gl::Extents &sourceSize,
+                            GLenum destFormat,
+                            const gl::Offset &destOffset,
+                            IDirect3DSurface9 *dest,
+                            bool flipY,
+                            bool premultiplyAlpha,
+                            bool unmultiplyAlpha);
+    gl::Error setFormatConvertShaders(GLenum destFormat,
+                                      bool flipY,
+                                      bool premultiplyAlpha,
+                                      bool unmultiplyAlpha);
+
+    gl::Error copy(IDirect3DSurface9 *source,
+                   IDirect3DBaseTexture9 *sourceTexture,
+                   const RECT &sourceRect,
+                   GLenum destFormat,
+                   const gl::Offset &destOffset,
+                   IDirect3DSurface9 *dest,
+                   bool flipY,
+                   bool premultiplyAlpha,
+                   bool unmultiplyAlpha);
+    gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface,
+                                   const RECT &sourceRect,
+                                   IDirect3DBaseTexture9 **outTexture);
+    void setViewportAndShaderConstants(const RECT &sourceRect,
+                                       const gl::Extents &sourceSize,
+                                       const RECT &destRect,
+                                       bool flipY);
+    void setCommonBlitState();
+    RECT getSurfaceRect(IDirect3DSurface9 *surface) const;
+    gl::Extents getSurfaceSize(IDirect3DSurface9 *surface) const;
+
+    // This enum is used to index mCompiledShaders and mShaderSource.
+    enum ShaderId
+    {
+        SHADER_VS_STANDARD,
+        SHADER_PS_PASSTHROUGH,
+        SHADER_PS_LUMINANCE,
+        SHADER_PS_LUMINANCE_PREMULTIPLY_ALPHA,
+        SHADER_PS_LUMINANCE_UNMULTIPLY_ALPHA,
+        SHADER_PS_COMPONENTMASK,
+        SHADER_PS_COMPONENTMASK_PREMULTIPLY_ALPHA,
+        SHADER_PS_COMPONENTMASK_UNMULTIPLY_ALPHA,
+        SHADER_COUNT,
+    };
+
+    // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown.
+    IUnknown *mCompiledShaders[SHADER_COUNT];
+
+    template <class D3DShaderType>
+    gl::Error setShader(ShaderId source, const char *profile,
+                        gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader),
+                        HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*));
+
+    gl::Error setVertexShader(ShaderId shader);
+    gl::Error setPixelShader(ShaderId shader);
+    void render();
+
+    void saveState();
+    void restoreState();
+    IDirect3DStateBlock9 *mSavedStateBlock;
+    IDirect3DSurface9 *mSavedRenderTarget;
+    IDirect3DSurface9 *mSavedDepthStencil;
+};
+
+}
+
+#endif   // LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
new file mode 100644
index 0000000..534a252
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
@@ -0,0 +1,129 @@
+//
+// 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.
+//
+
+// Buffer9.cpp Defines the Buffer9 class.
+
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+Buffer9::Buffer9(const gl::BufferState &state, Renderer9 *renderer)
+    : BufferD3D(state, renderer), mSize(0)
+{
+}
+
+Buffer9::~Buffer9()
+{
+    mSize = 0;
+}
+
+gl::Error Buffer9::setData(ContextImpl * /*context*/,
+                           GLenum /*target*/,
+                           const void *data,
+                           size_t size,
+                           GLenum usage)
+{
+    if (size > mMemory.size())
+    {
+        if (!mMemory.resize(size))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer.");
+        }
+    }
+
+    mSize = size;
+    if (data && size > 0)
+    {
+        memcpy(mMemory.data(), data, size);
+    }
+
+    updateD3DBufferUsage(usage);
+
+    invalidateStaticData();
+
+    return gl::NoError();
+}
+
+gl::Error Buffer9::getData(const uint8_t **outData)
+{
+    *outData = mMemory.data();
+    return gl::NoError();
+}
+
+gl::Error Buffer9::setSubData(ContextImpl * /*context*/,
+                              GLenum /*target*/,
+                              const void *data,
+                              size_t size,
+                              size_t offset)
+{
+    if (offset + size > mMemory.size())
+    {
+        if (!mMemory.resize(offset + size))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer.");
+        }
+    }
+
+    mSize = std::max(mSize, offset + size);
+    if (data && size > 0)
+    {
+        memcpy(mMemory.data() + offset, data, size);
+    }
+
+    invalidateStaticData();
+
+    return gl::NoError();
+}
+
+gl::Error Buffer9::copySubData(ContextImpl *context,
+                               BufferImpl *source,
+                               GLintptr sourceOffset,
+                               GLintptr destOffset,
+                               GLsizeiptr size)
+{
+    // Note: this method is currently unreachable
+    Buffer9 *sourceBuffer = GetAs<Buffer9>(source);
+    ASSERT(sourceBuffer);
+
+    memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size);
+
+    invalidateStaticData();
+
+    return gl::NoError();
+}
+
+// We do not support buffer mapping in D3D9
+gl::Error Buffer9::map(ContextImpl *context, GLenum access, void **mapPtr)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Buffer9::mapRange(ContextImpl *context,
+                            size_t offset,
+                            size_t length,
+                            GLbitfield access,
+                            void **mapPtr)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Buffer9::unmap(ContextImpl *context, GLboolean *result)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Buffer9::markTransformFeedbackUsage()
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
new file mode 100644
index 0000000..a0a6ccc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
@@ -0,0 +1,63 @@
+//
+// 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.
+//
+
+// Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
+
+#include "common/MemoryBuffer.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Buffer9 : public BufferD3D
+{
+  public:
+    Buffer9(const gl::BufferState &state, Renderer9 *renderer);
+    virtual ~Buffer9();
+
+    // BufferD3D implementation
+    virtual size_t getSize() const { return mSize; }
+    virtual bool supportsDirectBinding() const { return false; }
+    gl::Error getData(const uint8_t **outData) override;
+
+    // BufferImpl implementation
+    gl::Error setData(ContextImpl *context,
+                      GLenum target,
+                      const void *data,
+                      size_t size,
+                      GLenum usage) override;
+    gl::Error setSubData(ContextImpl *context,
+                         GLenum target,
+                         const void *data,
+                         size_t size,
+                         size_t offset) override;
+    gl::Error copySubData(ContextImpl *context,
+                          BufferImpl *source,
+                          GLintptr sourceOffset,
+                          GLintptr destOffset,
+                          GLsizeiptr size) override;
+    gl::Error map(ContextImpl *context, GLenum access, void **mapPtr) override;
+    gl::Error mapRange(ContextImpl *context,
+                       size_t offset,
+                       size_t length,
+                       GLbitfield access,
+                       void **mapPtr) override;
+    gl::Error unmap(ContextImpl *context, GLboolean *result) override;
+    gl::Error markTransformFeedbackUsage() override;
+
+  private:
+    angle::MemoryBuffer mMemory;
+    size_t mSize;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
new file mode 100644
index 0000000..3263980
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
@@ -0,0 +1,276 @@
+//
+// Copyright 2016 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.
+//
+// Context9:
+//   D3D9-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
+
+namespace rx
+{
+
+Context9::Context9(const gl::ContextState &state, Renderer9 *renderer)
+    : ContextImpl(state), mRenderer(renderer)
+{
+}
+
+Context9::~Context9()
+{
+}
+
+gl::Error Context9::initialize()
+{
+    return gl::NoError();
+}
+
+CompilerImpl *Context9::createCompiler()
+{
+    return new CompilerD3D(SH_HLSL_3_0_OUTPUT);
+}
+
+ShaderImpl *Context9::createShader(const gl::ShaderState &data)
+{
+    return new ShaderD3D(data, mRenderer->getWorkarounds());
+}
+
+ProgramImpl *Context9::createProgram(const gl::ProgramState &data)
+{
+    return new ProgramD3D(data, mRenderer);
+}
+
+FramebufferImpl *Context9::createFramebuffer(const gl::FramebufferState &data)
+{
+    return new Framebuffer9(data, mRenderer);
+}
+
+TextureImpl *Context9::createTexture(const gl::TextureState &state)
+{
+    switch (state.getTarget())
+    {
+        case GL_TEXTURE_2D:
+            return new TextureD3D_2D(state, mRenderer);
+        case GL_TEXTURE_CUBE_MAP:
+            return new TextureD3D_Cube(state, mRenderer);
+        case GL_TEXTURE_EXTERNAL_OES:
+            return new TextureD3D_External(state, mRenderer);
+        default:
+            UNREACHABLE();
+    }
+    return nullptr;
+}
+
+RenderbufferImpl *Context9::createRenderbuffer()
+{
+    return new RenderbufferD3D(mRenderer);
+}
+
+BufferImpl *Context9::createBuffer(const gl::BufferState &state)
+{
+    return new Buffer9(state, mRenderer);
+}
+
+VertexArrayImpl *Context9::createVertexArray(const gl::VertexArrayState &data)
+{
+    return new VertexArray9(data);
+}
+
+QueryImpl *Context9::createQuery(GLenum type)
+{
+    return new Query9(mRenderer, type);
+}
+
+FenceNVImpl *Context9::createFenceNV()
+{
+    return new FenceNV9(mRenderer);
+}
+
+FenceSyncImpl *Context9::createFenceSync()
+{
+    // D3D9 doesn't support ES 3.0 and its sync objects.
+    UNREACHABLE();
+    return nullptr;
+}
+
+TransformFeedbackImpl *Context9::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+    UNREACHABLE();
+    return nullptr;
+}
+
+SamplerImpl *Context9::createSampler()
+{
+    return new SamplerD3D();
+}
+
+std::vector<PathImpl *> Context9::createPaths(GLsizei)
+{
+    return std::vector<PathImpl *>();
+}
+
+gl::Error Context9::flush()
+{
+    return mRenderer->flush();
+}
+
+gl::Error Context9::finish()
+{
+    return mRenderer->finish();
+}
+
+gl::Error Context9::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    return mRenderer->genericDrawArrays(this, mode, first, count, 0);
+}
+
+gl::Error Context9::drawArraysInstanced(GLenum mode,
+                                        GLint first,
+                                        GLsizei count,
+                                        GLsizei instanceCount)
+{
+    return mRenderer->genericDrawArrays(this, mode, first, count, instanceCount);
+}
+
+gl::Error Context9::drawElements(GLenum mode,
+                                 GLsizei count,
+                                 GLenum type,
+                                 const void *indices,
+                                 const gl::IndexRange &indexRange)
+{
+    return mRenderer->genericDrawElements(this, mode, count, type, indices, 0, indexRange);
+}
+
+gl::Error Context9::drawElementsInstanced(GLenum mode,
+                                          GLsizei count,
+                                          GLenum type,
+                                          const void *indices,
+                                          GLsizei instances,
+                                          const gl::IndexRange &indexRange)
+{
+    return mRenderer->genericDrawElements(this, mode, count, type, indices, instances, indexRange);
+}
+
+gl::Error Context9::drawRangeElements(GLenum mode,
+                                      GLuint start,
+                                      GLuint end,
+                                      GLsizei count,
+                                      GLenum type,
+                                      const void *indices,
+                                      const gl::IndexRange &indexRange)
+{
+    return mRenderer->genericDrawElements(this, mode, count, type, indices, 0, indexRange);
+}
+
+gl::Error Context9::drawArraysIndirect(GLenum mode, const void *indirect)
+{
+    UNREACHABLE();
+    return gl::InternalError() << "D3D9 doesn't support ES 3.1 DrawArraysIndirect API";
+}
+
+gl::Error Context9::drawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+    UNREACHABLE();
+    return gl::InternalError() << "D3D9 doesn't support ES 3.1 DrawElementsIndirect API";
+}
+
+GLenum Context9::getResetStatus()
+{
+    return mRenderer->getResetStatus();
+}
+
+std::string Context9::getVendorString() const
+{
+    return mRenderer->getVendorString();
+}
+
+std::string Context9::getRendererDescription() const
+{
+    return mRenderer->getRendererDescription();
+}
+
+void Context9::insertEventMarker(GLsizei length, const char *marker)
+{
+    auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+    if (optionalString.valid())
+    {
+        mRenderer->getAnnotator()->setMarker(optionalString.value().data());
+    }
+}
+
+void Context9::pushGroupMarker(GLsizei length, const char *marker)
+{
+    auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+    if (optionalString.valid())
+    {
+        mRenderer->getAnnotator()->beginEvent(optionalString.value().data());
+    }
+}
+
+void Context9::popGroupMarker()
+{
+    mRenderer->getAnnotator()->endEvent();
+}
+
+void Context9::syncState(const gl::State::DirtyBits &dirtyBits)
+{
+    mRenderer->getStateManager()->syncState(mState.getState(), dirtyBits);
+}
+
+GLint Context9::getGPUDisjoint()
+{
+    return mRenderer->getGPUDisjoint();
+}
+
+GLint64 Context9::getTimestamp()
+{
+    return mRenderer->getTimestamp();
+}
+
+void Context9::onMakeCurrent(const gl::ContextState &data)
+{
+}
+
+const gl::Caps &Context9::getNativeCaps() const
+{
+    return mRenderer->getNativeCaps();
+}
+
+const gl::TextureCapsMap &Context9::getNativeTextureCaps() const
+{
+    return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &Context9::getNativeExtensions() const
+{
+    return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &Context9::getNativeLimitations() const
+{
+    return mRenderer->getNativeLimitations();
+}
+
+gl::Error Context9::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+    UNREACHABLE();
+    return gl::InternalError() << "D3D9 doesn't support ES 3.1 DispatchCompute API";
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h
new file mode 100644
index 0000000..f69ed97
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h
@@ -0,0 +1,130 @@
+//
+// Copyright 2016 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.
+//
+// Context9:
+//   D3D9-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Context9 : public ContextImpl
+{
+  public:
+    Context9(const gl::ContextState &state, Renderer9 *renderer);
+    ~Context9() override;
+
+    gl::Error initialize() override;
+
+    // Shader creation
+    CompilerImpl *createCompiler() override;
+    ShaderImpl *createShader(const gl::ShaderState &data) override;
+    ProgramImpl *createProgram(const gl::ProgramState &data) override;
+
+    // Framebuffer creation
+    FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override;
+
+    // Texture creation
+    TextureImpl *createTexture(const gl::TextureState &state) override;
+
+    // Renderbuffer creation
+    RenderbufferImpl *createRenderbuffer() override;
+
+    // Buffer creation
+    BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+    // Vertex Array creation
+    VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override;
+
+    // Query and Fence creation
+    QueryImpl *createQuery(GLenum type) override;
+    FenceNVImpl *createFenceNV() override;
+    FenceSyncImpl *createFenceSync() override;
+
+    // Transform Feedback creation
+    TransformFeedbackImpl *createTransformFeedback(
+        const gl::TransformFeedbackState &state) override;
+
+    // Sampler object creation
+    SamplerImpl *createSampler() override;
+
+    // Path object creation
+    std::vector<PathImpl *> createPaths(GLsizei) override;
+
+    // Flush and finish.
+    gl::Error flush() override;
+    gl::Error finish() override;
+
+    // Drawing methods.
+    gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+    gl::Error drawArraysInstanced(GLenum mode,
+                                  GLint first,
+                                  GLsizei count,
+                                  GLsizei instanceCount) override;
+
+    gl::Error drawElements(GLenum mode,
+                           GLsizei count,
+                           GLenum type,
+                           const void *indices,
+                           const gl::IndexRange &indexRange) override;
+    gl::Error drawElementsInstanced(GLenum mode,
+                                    GLsizei count,
+                                    GLenum type,
+                                    const void *indices,
+                                    GLsizei instances,
+                                    const gl::IndexRange &indexRange) override;
+    gl::Error drawRangeElements(GLenum mode,
+                                GLuint start,
+                                GLuint end,
+                                GLsizei count,
+                                GLenum type,
+                                const void *indices,
+                                const gl::IndexRange &indexRange) override;
+    gl::Error drawArraysIndirect(GLenum mode, const void *indirect) override;
+    gl::Error drawElementsIndirect(GLenum mode, GLenum type, const void *indirect) override;
+
+    // Device loss
+    GLenum getResetStatus() override;
+
+    // Vendor and description strings.
+    std::string getVendorString() const override;
+    std::string getRendererDescription() const override;
+
+    // Debug markers.
+    void insertEventMarker(GLsizei length, const char *marker) override;
+    void pushGroupMarker(GLsizei length, const char *marker) override;
+    void popGroupMarker() override;
+
+    // State sync with dirty bits.
+    void syncState(const gl::State::DirtyBits &dirtyBits) override;
+
+    // Disjoint timer queries
+    GLint getGPUDisjoint() override;
+    GLint64 getTimestamp() override;
+
+    // Context switching
+    void onMakeCurrent(const gl::ContextState &data) override;
+
+    // Caps queries
+    const gl::Caps &getNativeCaps() const override;
+    const gl::TextureCapsMap &getNativeTextureCaps() const override;
+    const gl::Extensions &getNativeExtensions() const override;
+    const gl::Limitations &getNativeLimitations() const override;
+
+    gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
+
+  private:
+    Renderer9 *mRenderer;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp
new file mode 100644
index 0000000..6ec35e1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator9.h: D3D9 helpers for adding trace annotations.
+//
+
+#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
+
+#include "common/platform.h"
+
+namespace rx
+{
+
+void DebugAnnotator9::beginEvent(const wchar_t *eventName)
+{
+    D3DPERF_BeginEvent(0, eventName);
+}
+
+void DebugAnnotator9::endEvent()
+{
+    D3DPERF_EndEvent();
+}
+
+void DebugAnnotator9::setMarker(const wchar_t *markerName)
+{
+    D3DPERF_SetMarker(0, markerName);
+}
+
+bool DebugAnnotator9::getStatus()
+{
+    return !!D3DPERF_GetStatus();
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
new file mode 100644
index 0000000..b280083
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
@@ -0,0 +1,29 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator9.h: D3D9 helpers for adding trace annotations.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
+
+#include "libANGLE/LoggingAnnotator.h"
+
+namespace rx
+{
+
+class DebugAnnotator9 : public angle::LoggingAnnotator
+{
+  public:
+    DebugAnnotator9() {}
+    void beginEvent(const wchar_t *eventName) override;
+    void endEvent() override;
+    void setMarker(const wchar_t *markerName) override;
+    bool getStatus() override;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
new file mode 100644
index 0000000..6779f56
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence9.cpp: Defines the rx::FenceNV9 class.
+
+#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+FenceNV9::FenceNV9(Renderer9 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(nullptr)
+{
+}
+
+FenceNV9::~FenceNV9()
+{
+    SafeRelease(mQuery);
+}
+
+gl::Error FenceNV9::set(GLenum condition)
+{
+    if (!mQuery)
+    {
+        gl::Error error = mRenderer->allocateEventQuery(&mQuery);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    HRESULT result = mQuery->Issue(D3DISSUE_END);
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        SafeRelease(mQuery);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to end event query, result: 0x%X.", result);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error FenceNV9::test(GLboolean *outFinished)
+{
+    return testHelper(true, outFinished);
+}
+
+gl::Error FenceNV9::finish()
+{
+    GLboolean finished = GL_FALSE;
+    while (finished != GL_TRUE)
+    {
+        gl::Error error = testHelper(true, &finished);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        Sleep(0);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error FenceNV9::testHelper(bool flushCommandBuffer, GLboolean *outFinished)
+{
+    ASSERT(mQuery);
+
+    DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0);
+    HRESULT result     = mQuery->GetData(nullptr, 0, getDataFlags);
+
+    if (d3d9::isDeviceLostError(result))
+    {
+        mRenderer->notifyDeviceLost();
+        return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query.");
+    }
+    else if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
+    }
+
+    ASSERT(result == S_OK || result == S_FALSE);
+    *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
+    return gl::NoError();
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h
new file mode 100644
index 0000000..200ac68
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence9.h: Defines the rx::FenceNV9 class which implements rx::FenceNVImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace rx
+{
+class Renderer9;
+
+class FenceNV9 : public FenceNVImpl
+{
+  public:
+    explicit FenceNV9(Renderer9 *renderer);
+    ~FenceNV9() override;
+
+    gl::Error set(GLenum condition) override;
+    gl::Error test(GLboolean *outFinished) override;
+    gl::Error finish() override;
+
+  private:
+    gl::Error testHelper(bool flushCommandBuffer, GLboolean *outFinished);
+
+    Renderer9 *mRenderer;
+    IDirect3DQuery9 *mQuery;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
new file mode 100644
index 0000000..9155c98
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -0,0 +1,410 @@
+//
+// 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.
+//
+
+// Framebuffer9.cpp: Implements the Framebuffer9 class.
+
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace rx
+{
+
+Framebuffer9::Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer)
+    : FramebufferD3D(data, renderer), mRenderer(renderer)
+{
+    ASSERT(mRenderer != nullptr);
+}
+
+Framebuffer9::~Framebuffer9()
+{
+}
+
+gl::Error Framebuffer9::discard(size_t, const GLenum *)
+{
+    // Extension not implemented in D3D9 renderer
+    UNREACHABLE();
+    return gl::NoError();
+}
+
+gl::Error Framebuffer9::invalidate(size_t, const GLenum *)
+{
+    // Shouldn't ever reach here in D3D9
+    UNREACHABLE();
+    return gl::NoError();
+}
+
+gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+{
+    // Shouldn't ever reach here in D3D9
+    UNREACHABLE();
+    return gl::NoError();
+}
+
+gl::Error Framebuffer9::clearImpl(ContextImpl *context, const ClearParameters &clearParams)
+{
+    const gl::FramebufferAttachment *colorAttachment        = mState.getColorAttachment(0);
+    const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthOrStencilAttachment();
+
+    gl::Error error =
+        mRenderer->applyRenderTarget(context, colorAttachment, depthStencilAttachment);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    const gl::State &glState = context->getGLState();
+    float nearZ              = glState.getNearPlane();
+    float farZ = glState.getFarPlane();
+    mRenderer->setViewport(glState.getViewport(), nearZ, farZ, GL_TRIANGLES,
+                           glState.getRasterizerState().frontFace, true);
+
+    mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
+
+    return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment);
+}
+
+gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
+                                       GLenum format,
+                                       GLenum type,
+                                       size_t outputPitch,
+                                       const gl::PixelPackState &pack,
+                                       uint8_t *pixels) const
+{
+    ASSERT(pack.pixelBuffer.get() == nullptr);
+
+    const gl::FramebufferAttachment *colorbuffer = mState.getColorAttachment(0);
+    ASSERT(colorbuffer);
+
+    RenderTarget9 *renderTarget = nullptr;
+    gl::Error error = colorbuffer->getRenderTarget(&renderTarget);
+    if (error.isError())
+    {
+        return error;
+    }
+    ASSERT(renderTarget);
+
+    IDirect3DSurface9 *surface = renderTarget->getSurface();
+    ASSERT(surface);
+
+    D3DSURFACE_DESC desc;
+    surface->GetDesc(&desc);
+
+    if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+    {
+        UNIMPLEMENTED();   // FIXME: Requires resolve using StretchRect into non-multisampled render target
+        SafeRelease(surface);
+        return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments.");
+    }
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+    ASSERT(device);
+
+    HRESULT result;
+    IDirect3DSurface9 *systemSurface = nullptr;
+    bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() &&
+                          area.x == 0 && area.y == 0 &&
+                          static_cast<UINT>(area.width) == desc.Width && static_cast<UINT>(area.height) == desc.Height &&
+                          desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
+    if (directToPixels)
+    {
+        // Use the pixels ptr as a shared handle to write directly into client's memory
+        result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+                                                     D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast<void**>(&pixels));
+        if (FAILED(result))
+        {
+            // Try again without the shared handle
+            directToPixels = false;
+        }
+    }
+
+    if (!directToPixels)
+    {
+        result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+                                                     D3DPOOL_SYSTEMMEM, &systemSurface, nullptr);
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            SafeRelease(surface);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels.");
+        }
+    }
+
+    result = device->GetRenderTargetData(surface, systemSurface);
+    SafeRelease(surface);
+
+    if (FAILED(result))
+    {
+        SafeRelease(systemSurface);
+
+        // It turns out that D3D will sometimes produce more error
+        // codes than those documented.
+        if (d3d9::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data.");
+    }
+
+    if (directToPixels)
+    {
+        SafeRelease(systemSurface);
+        return gl::NoError();
+    }
+
+    RECT rect;
+    rect.left = gl::clamp(area.x, 0L, static_cast<LONG>(desc.Width));
+    rect.top = gl::clamp(area.y, 0L, static_cast<LONG>(desc.Height));
+    rect.right = gl::clamp(area.x + area.width, 0L, static_cast<LONG>(desc.Width));
+    rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast<LONG>(desc.Height));
+
+    D3DLOCKED_RECT lock;
+    result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
+
+    if (FAILED(result))
+    {
+        UNREACHABLE();
+        SafeRelease(systemSurface);
+
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target.");
+    }
+
+    uint8_t *source = reinterpret_cast<uint8_t *>(lock.pBits);
+    int inputPitch  = lock.Pitch;
+
+    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+    gl::FormatType formatType(format, type);
+
+    // TODO(jmadill): Maybe we can avoid a copy of pack parameters here?
+    PackPixelsParams packParams;
+    packParams.area.x      = rect.left;
+    packParams.area.y      = rect.top;
+    packParams.area.width  = rect.right - rect.left;
+    packParams.area.height = rect.bottom - rect.top;
+    packParams.format      = format;
+    packParams.type        = type;
+    packParams.outputPitch = static_cast<GLuint>(outputPitch);
+    packParams.pack        = pack;
+
+    PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels);
+
+    systemSurface->UnlockRect();
+    SafeRelease(systemSurface);
+
+    return gl::NoError();
+}
+
+gl::Error Framebuffer9::blitImpl(const gl::Rectangle &sourceArea,
+                                 const gl::Rectangle &destArea,
+                                 const gl::Rectangle *scissor,
+                                 bool blitRenderTarget,
+                                 bool blitDepth,
+                                 bool blitStencil,
+                                 GLenum filter,
+                                 const gl::Framebuffer *sourceFramebuffer)
+{
+    ASSERT(filter == GL_NEAREST);
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+    ASSERT(device);
+
+    mRenderer->endScene();
+
+    if (blitRenderTarget)
+    {
+        const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorbuffer(0);
+        ASSERT(readBuffer);
+
+        RenderTarget9 *readRenderTarget = nullptr;
+        gl::Error error = readBuffer->getRenderTarget(&readRenderTarget);
+        if (error.isError())
+        {
+            return error;
+        }
+        ASSERT(readRenderTarget);
+
+        const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0);
+        ASSERT(drawBuffer);
+
+        RenderTarget9 *drawRenderTarget = nullptr;
+        error = drawBuffer->getRenderTarget(&drawRenderTarget);
+        if (error.isError())
+        {
+            return error;
+        }
+        ASSERT(drawRenderTarget);
+
+        // The getSurface calls do an AddRef so save them until after no errors are possible
+        IDirect3DSurface9* readSurface = readRenderTarget->getSurface();
+        ASSERT(readSurface);
+
+        IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface();
+        ASSERT(drawSurface);
+
+        gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
+        gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+
+        RECT srcRect;
+        srcRect.left = sourceArea.x;
+        srcRect.right = sourceArea.x + sourceArea.width;
+        srcRect.top = sourceArea.y;
+        srcRect.bottom = sourceArea.y + sourceArea.height;
+
+        RECT dstRect;
+        dstRect.left = destArea.x;
+        dstRect.right = destArea.x + destArea.width;
+        dstRect.top = destArea.y;
+        dstRect.bottom = destArea.y + destArea.height;
+
+        // Clip the rectangles to the scissor rectangle
+        if (scissor)
+        {
+            if (dstRect.left < scissor->x)
+            {
+                srcRect.left += (scissor->x - dstRect.left);
+                dstRect.left = scissor->x;
+            }
+            if (dstRect.top < scissor->y)
+            {
+                srcRect.top += (scissor->y - dstRect.top);
+                dstRect.top = scissor->y;
+            }
+            if (dstRect.right > scissor->x + scissor->width)
+            {
+                srcRect.right -= (dstRect.right - (scissor->x + scissor->width));
+                dstRect.right = scissor->x + scissor->width;
+            }
+            if (dstRect.bottom > scissor->y + scissor->height)
+            {
+                srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height));
+                dstRect.bottom = scissor->y + scissor->height;
+            }
+        }
+
+        // Clip the rectangles to the destination size
+        if (dstRect.left < 0)
+        {
+            srcRect.left += -dstRect.left;
+            dstRect.left = 0;
+        }
+        if (dstRect.right > dstSize.width)
+        {
+            srcRect.right -= (dstRect.right - dstSize.width);
+            dstRect.right = dstSize.width;
+        }
+        if (dstRect.top < 0)
+        {
+            srcRect.top += -dstRect.top;
+            dstRect.top = 0;
+        }
+        if (dstRect.bottom > dstSize.height)
+        {
+            srcRect.bottom -= (dstRect.bottom - dstSize.height);
+            dstRect.bottom = dstSize.height;
+        }
+
+        // Clip the rectangles to the source size
+        if (srcRect.left < 0)
+        {
+            dstRect.left += -srcRect.left;
+            srcRect.left = 0;
+        }
+        if (srcRect.right > srcSize.width)
+        {
+            dstRect.right -= (srcRect.right - srcSize.width);
+            srcRect.right = srcSize.width;
+        }
+        if (srcRect.top < 0)
+        {
+            dstRect.top += -srcRect.top;
+            srcRect.top = 0;
+        }
+        if (srcRect.bottom > srcSize.height)
+        {
+            dstRect.bottom -= (srcRect.bottom - srcSize.height);
+            srcRect.bottom = srcSize.height;
+        }
+
+        HRESULT result = device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
+
+        SafeRelease(readSurface);
+        SafeRelease(drawSurface);
+
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
+        }
+    }
+
+    if (blitDepth || blitStencil)
+    {
+        const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer();
+        ASSERT(readBuffer);
+
+        RenderTarget9 *readDepthStencil = nullptr;
+        gl::Error error = readBuffer->getRenderTarget(&readDepthStencil);
+        if (error.isError())
+        {
+            return error;
+        }
+        ASSERT(readDepthStencil);
+
+        const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
+        ASSERT(drawBuffer);
+
+        RenderTarget9 *drawDepthStencil = nullptr;
+        error = drawBuffer->getRenderTarget(&drawDepthStencil);
+        if (error.isError())
+        {
+            return error;
+        }
+        ASSERT(drawDepthStencil);
+
+        // The getSurface calls do an AddRef so save them until after no errors are possible
+        IDirect3DSurface9* readSurface = readDepthStencil->getSurface();
+        ASSERT(readDepthStencil);
+
+        IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface();
+        ASSERT(drawDepthStencil);
+
+        HRESULT result = device->StretchRect(readSurface, nullptr, drawSurface, nullptr, D3DTEXF_NONE);
+
+        SafeRelease(readSurface);
+        SafeRelease(drawSurface);
+
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
+        }
+    }
+
+    return gl::NoError();
+}
+
+GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+{
+    RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTarget);
+    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat());
+    return d3dFormatInfo.info().glInternalFormat;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
new file mode 100644
index 0000000..8401350
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
@@ -0,0 +1,54 @@
+//
+// 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.
+//
+
+// Framebuffer9.h: Defines the Framebuffer9 class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
+
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Framebuffer9 : public FramebufferD3D
+{
+  public:
+    Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer);
+    virtual ~Framebuffer9();
+
+    gl::Error discard(size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(size_t count, const GLenum *attachments) override;
+    gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+
+  private:
+    gl::Error clearImpl(ContextImpl *context, const ClearParameters &clearParams) override;
+
+    gl::Error readPixelsImpl(const gl::Rectangle &area,
+                             GLenum format,
+                             GLenum type,
+                             size_t outputPitch,
+                             const gl::PixelPackState &pack,
+                             uint8_t *pixels) const override;
+
+    gl::Error blitImpl(const gl::Rectangle &sourceArea,
+                       const gl::Rectangle &destArea,
+                       const gl::Rectangle *scissor,
+                       bool blitRenderTarget,
+                       bool blitDepth,
+                       bool blitStencil,
+                       GLenum filter,
+                       const gl::Framebuffer *sourceFramebuffer) override;
+
+    GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
+
+    Renderer9 *const mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
new file mode 100644
index 0000000..d3b4dc2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -0,0 +1,827 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to
+// the actual underlying surfaces of a Texture.
+
+#include "libANGLE/renderer/d3d/d3d9/Image9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "common/utilities.h"
+
+namespace rx
+{
+
+Image9::Image9(Renderer9 *renderer)
+{
+    mSurface  = nullptr;
+    mRenderer = nullptr;
+
+    mD3DPool = D3DPOOL_SYSTEMMEM;
+    mD3DFormat = D3DFMT_UNKNOWN;
+
+    mRenderer = renderer;
+}
+
+Image9::~Image9()
+{
+    SafeRelease(mSurface);
+}
+
+gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
+{
+    D3DSURFACE_DESC destDesc;
+    HRESULT result = destSurface->GetDesc(&destDesc);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the source surface description for mipmap generation, result: 0x%X.", result);
+    }
+
+    D3DSURFACE_DESC sourceDesc;
+    result = sourceSurface->GetDesc(&sourceDesc);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the destination surface description for mipmap generation, result: 0x%X.", result);
+    }
+
+    ASSERT(sourceDesc.Format == destDesc.Format);
+    ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width);
+    ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height);
+
+    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format);
+    ASSERT(d3dFormatInfo.info().mipGenerationFunction != nullptr);
+
+    D3DLOCKED_RECT sourceLocked = {0};
+    result                      = sourceSurface->LockRect(&sourceLocked, nullptr, D3DLOCK_READONLY);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface for mipmap generation, result: 0x%X.", result);
+    }
+
+    D3DLOCKED_RECT destLocked = {0};
+    result                    = destSurface->LockRect(&destLocked, nullptr, 0);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        sourceSurface->UnlockRect();
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the destination surface for mipmap generation, result: 0x%X.", result);
+    }
+
+    const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(sourceLocked.pBits);
+    uint8_t *destData = reinterpret_cast<uint8_t*>(destLocked.pBits);
+
+    ASSERT(sourceData && destData);
+
+    d3dFormatInfo.info().mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData,
+                                               sourceLocked.Pitch, 0, destData, destLocked.Pitch,
+                                               0);
+
+    destSurface->UnlockRect();
+    sourceSurface->UnlockRect();
+
+    return gl::NoError();
+}
+
+gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source)
+{
+    IDirect3DSurface9 *sourceSurface = nullptr;
+    gl::Error error = source->getSurface(&sourceSurface);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DSurface9 *destSurface = nullptr;
+    error = dest->getSurface(&destSurface);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = generateMip(destSurface, sourceSurface);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    dest->markDirty();
+
+    return gl::NoError();
+}
+
+gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
+{
+    D3DLOCKED_RECT sourceLock = {0};
+    D3DLOCKED_RECT destLock = {0};
+
+    HRESULT result;
+
+    result = source->LockRect(&sourceLock, nullptr, 0);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result);
+    }
+
+    result = dest->LockRect(&destLock, nullptr, 0);
+    if (FAILED(result))
+    {
+        source->UnlockRect();
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result);
+    }
+
+    ASSERT(sourceLock.pBits && destLock.pBits);
+
+    D3DSURFACE_DESC desc;
+    source->GetDesc(&desc);
+
+    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+    unsigned int rows = desc.Height / d3dFormatInfo.blockHeight;
+
+    unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight);
+    ASSERT(bytes <= static_cast<unsigned int>(sourceLock.Pitch) &&
+           bytes <= static_cast<unsigned int>(destLock.Pitch));
+
+    for(unsigned int i = 0; i < rows; i++)
+    {
+        memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
+    }
+
+    source->UnlockRect();
+    dest->UnlockRect();
+
+    return gl::NoError();
+}
+
+bool Image9::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease)
+{
+    // 3D textures are not supported by the D3D9 backend.
+    ASSERT(size.depth <= 1);
+
+    // Only 2D and cube texture are supported by the D3D9 backend.
+    ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
+
+    if (mWidth != size.width ||
+        mHeight != size.height ||
+        mDepth != size.depth ||
+        mInternalFormat != internalformat ||
+        forceRelease)
+    {
+        mWidth = size.width;
+        mHeight = size.height;
+        mDepth = size.depth;
+        mInternalFormat = internalformat;
+
+        // compute the d3d format that will be used
+        const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+        mD3DFormat = d3d9FormatInfo.texFormat;
+        mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN);
+
+        SafeRelease(mSurface);
+        mDirty = (d3d9FormatInfo.dataInitializerFunction != nullptr);
+
+        return true;
+    }
+
+    return false;
+}
+
+gl::Error Image9::createSurface()
+{
+    if (mSurface)
+    {
+        return gl::NoError();
+    }
+
+    IDirect3DTexture9 *newTexture = nullptr;
+    IDirect3DSurface9 *newSurface = nullptr;
+    const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
+    const D3DFORMAT d3dFormat = getD3DFormat();
+
+    if (mWidth != 0 && mHeight != 0)
+    {
+        int levelToFetch = 0;
+        GLsizei requestWidth = mWidth;
+        GLsizei requestHeight = mHeight;
+        d3d9::MakeValidSize(true, d3dFormat, &requestWidth, &requestHeight, &levelToFetch);
+
+        IDirect3DDevice9 *device = mRenderer->getDevice();
+
+        HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0,
+                                               d3dFormat, poolToUse, &newTexture, nullptr);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create image surface, result: 0x%X.", result);
+        }
+
+        newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
+        SafeRelease(newTexture);
+
+        const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
+        if (d3dFormatInfo.dataInitializerFunction != nullptr)
+        {
+            RECT entireRect;
+            entireRect.left = 0;
+            entireRect.right = mWidth;
+            entireRect.top = 0;
+            entireRect.bottom = mHeight;
+
+            D3DLOCKED_RECT lockedRect;
+            result = newSurface->LockRect(&lockedRect, &entireRect, 0);
+            ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result);
+            }
+
+            d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast<uint8_t*>(lockedRect.pBits),
+                                                  lockedRect.Pitch, 0);
+
+            result = newSurface->UnlockRect();
+            ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock image surface, result: 0x%X.", result);
+            }
+        }
+    }
+
+    mSurface = newSurface;
+    mDirty = false;
+    mD3DPool = poolToUse;
+
+    return gl::NoError();
+}
+
+gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect)
+{
+    gl::Error error = createSurface();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (mSurface)
+    {
+        HRESULT result = mSurface->LockRect(lockedRect, &rect, 0);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result);
+        }
+
+        mDirty = true;
+    }
+
+    return gl::NoError();
+}
+
+void Image9::unlock()
+{
+    if (mSurface)
+    {
+        HRESULT result = mSurface->UnlockRect();
+        ASSERT(SUCCEEDED(result));
+    }
+}
+
+D3DFORMAT Image9::getD3DFormat() const
+{
+    // this should only happen if the image hasn't been redefined first
+    // which would be a bug by the caller
+    ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
+
+    return mD3DFormat;
+}
+
+bool Image9::isDirty() const
+{
+    // Make sure to that this image is marked as dirty even if the staging texture hasn't been created yet
+    // if initialization is required before use.
+    return (mSurface ||
+            d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != nullptr) &&
+           mDirty;
+}
+
+gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface)
+{
+    gl::Error error = createSurface();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    *outSurface = mSurface;
+    return gl::NoError();
+}
+
+gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level)
+{
+    IDirect3DSurface9 *surface = nullptr;
+    TextureStorage9 *storage9  = GetAs<TextureStorage9>(storage);
+    gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, false, &surface);
+    if (error.isError())
+    {
+        return error;
+    }
+    return setManagedSurface(surface);
+}
+
+gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level)
+{
+    IDirect3DSurface9 *surface = nullptr;
+    TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+    gl::Error error =
+        storage9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface);
+    if (error.isError())
+    {
+        return error;
+    }
+    return setManagedSurface(surface);
+}
+
+gl::Error Image9::setManagedSurface(IDirect3DSurface9 *surface)
+{
+    D3DSURFACE_DESC desc;
+    surface->GetDesc(&desc);
+    ASSERT(desc.Pool == D3DPOOL_MANAGED);
+
+    if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
+    {
+        if (mSurface)
+        {
+            gl::Error error = copyLockableSurfaces(surface, mSurface);
+            SafeRelease(mSurface);
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+
+        mSurface = surface;
+        mD3DPool = desc.Pool;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
+{
+    gl::Error error = createSurface();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+
+    IDirect3DSurface9 *destSurface = nullptr;
+
+    if (index.type == GL_TEXTURE_2D)
+    {
+        error = storage9->getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, true, &destSurface);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+    else
+    {
+        ASSERT(gl::IsCubeMapTextureTarget(index.type));
+        error = storage9->getSurfaceLevel(index.type, index.mipIndex, true, &destSurface);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    error = copyToSurface(destSurface, region);
+    SafeRelease(destSurface);
+    return error;
+}
+
+gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &area)
+{
+    ASSERT(area.width > 0 && area.height > 0 && area.depth == 1);
+    ASSERT(destSurface);
+
+    IDirect3DSurface9 *sourceSurface = nullptr;
+    gl::Error error = getSurface(&sourceSurface);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ASSERT(sourceSurface && sourceSurface != destSurface);
+
+    RECT rect;
+    rect.left = area.x;
+    rect.top = area.y;
+    rect.right = area.x + area.width;
+    rect.bottom = area.y + area.height;
+
+    POINT point = {rect.left, rect.top};
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    if (mD3DPool == D3DPOOL_MANAGED)
+    {
+        D3DSURFACE_DESC desc;
+        sourceSurface->GetDesc(&desc);
+
+        IDirect3DSurface9 *surf = 0;
+        HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+                                                             D3DPOOL_SYSTEMMEM, &surf, nullptr);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal CreateOffscreenPlainSurface call failed, result: 0x%X.", result);
+        }
+
+        copyLockableSurfaces(surf, sourceSurface);
+        result = device->UpdateSurface(surf, &rect, destSurface, &point);
+        SafeRelease(surf);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result);
+        }
+    }
+    else
+    {
+        // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
+        HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result);
+        }
+    }
+
+    return gl::NoError();
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
+// into the target pixel rectangle.
+gl::Error Image9::loadData(const gl::Box &area,
+                           const gl::PixelUnpackState &unpack,
+                           GLenum type,
+                           const void *input,
+                           bool applySkipImages)
+{
+    // 3D textures are not supported by the D3D9 backend.
+    ASSERT(area.z == 0 && area.depth == 1);
+
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+    GLuint inputRowPitch                 = 0;
+    ANGLE_TRY_RESULT(
+        formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+        inputRowPitch);
+    ASSERT(!applySkipImages);
+    ASSERT(unpack.skipPixels == 0);
+    ASSERT(unpack.skipRows == 0);
+
+    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
+    ASSERT(d3dFormatInfo.loadFunction != nullptr);
+
+    RECT lockRect =
+    {
+        area.x, area.y,
+        area.x + area.width, area.y + area.height
+    };
+
+    D3DLOCKED_RECT locked;
+    gl::Error error = lock(&locked, lockRect);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    d3dFormatInfo.loadFunction(area.width, area.height, area.depth,
+                               reinterpret_cast<const uint8_t *>(input), inputRowPitch, 0,
+                               reinterpret_cast<uint8_t *>(locked.pBits), locked.Pitch, 0);
+
+    unlock();
+
+    return gl::NoError();
+}
+
+gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
+{
+    // 3D textures are not supported by the D3D9 backend.
+    ASSERT(area.z == 0 && area.depth == 1);
+
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+    GLsizei inputRowPitch                = 0;
+    ANGLE_TRY_RESULT(formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0), inputRowPitch);
+    GLsizei inputDepthPitch = 0;
+    ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputDepthPitch),
+                     inputDepthPitch);
+
+    const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
+
+    ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0);
+    ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0);
+
+    ASSERT(d3d9FormatInfo.loadFunction != nullptr);
+
+    RECT lockRect =
+    {
+        area.x, area.y,
+        area.x + area.width, area.y + area.height
+    };
+
+    D3DLOCKED_RECT locked;
+    gl::Error error = lock(&locked, lockRect);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    d3d9FormatInfo.loadFunction(area.width, area.height, area.depth,
+                                reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
+                                reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
+
+    unlock();
+
+    return gl::NoError();
+}
+
+// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
+gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset,
+                                     const gl::Rectangle &sourceArea,
+                                     RenderTargetD3D *source)
+{
+    ASSERT(source);
+
+    // ES3.0 only behaviour to copy into a 3d texture
+    ASSERT(destOffset.z == 0);
+
+    RenderTarget9 *renderTarget = GetAs<RenderTarget9>(source);
+
+    IDirect3DSurface9 *surface = renderTarget->getSurface();
+    ASSERT(surface);
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    IDirect3DSurface9 *renderTargetData = nullptr;
+    D3DSURFACE_DESC description;
+    surface->GetDesc(&description);
+
+    HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height,
+                                                         description.Format, D3DPOOL_SYSTEMMEM,
+                                                         &renderTargetData, nullptr);
+
+    if (FAILED(result))
+    {
+        SafeRelease(surface);
+        return gl::Error(GL_OUT_OF_MEMORY, "Could not create matching destination surface, result: 0x%X.", result);
+    }
+
+    result = device->GetRenderTargetData(surface, renderTargetData);
+
+    if (FAILED(result))
+    {
+        SafeRelease(renderTargetData);
+        SafeRelease(surface);
+        return gl::Error(GL_OUT_OF_MEMORY, "GetRenderTargetData unexpectedly failed, result: 0x%X.", result);
+    }
+
+    int width = sourceArea.width;
+    int height = sourceArea.height;
+
+    RECT sourceRect = { sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height };
+    RECT destRect = { destOffset.x, destOffset.y, destOffset.x + width, destOffset.y + height };
+
+    D3DLOCKED_RECT sourceLock = {0};
+    result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
+
+    if (FAILED(result))
+    {
+        SafeRelease(renderTargetData);
+        SafeRelease(surface);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface (rectangle might be invalid), result: 0x%X.", result);
+    }
+
+    D3DLOCKED_RECT destLock = {0};
+    gl::Error error = lock(&destLock, destRect);
+    if (error.isError())
+    {
+        renderTargetData->UnlockRect();
+        SafeRelease(renderTargetData);
+        SafeRelease(surface);
+        return error;
+    }
+
+    ASSERT(destLock.pBits && sourceLock.pBits);
+
+    unsigned char *sourcePixels = (unsigned char*)sourceLock.pBits;
+    unsigned char *destPixels = (unsigned char*)destLock.pBits;
+
+    switch (description.Format)
+    {
+      case D3DFMT_X8R8G8B8:
+      case D3DFMT_A8R8G8B8:
+        switch (getD3DFormat())
+        {
+          case D3DFMT_X8R8G8B8:
+          case D3DFMT_A8R8G8B8:
+            for (int y = 0; y < height; y++)
+            {
+                memcpy(destPixels, sourcePixels, 4 * width);
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    destPixels[x] = sourcePixels[x * 4 + 2];
+                }
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_A8L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    destPixels[x * 2 + 0] = sourcePixels[x * 4 + 2];
+                    destPixels[x * 2 + 1] = sourcePixels[x * 4 + 3];
+                }
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          default:
+            UNREACHABLE();
+        }
+        break;
+      case D3DFMT_R5G6B5:
+        switch (getD3DFormat())
+        {
+          case D3DFMT_X8R8G8B8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    unsigned short rgb = ((unsigned short*)sourcePixels)[x];
+                    unsigned char red = static_cast<unsigned char>((rgb & 0xF800) >> 8);
+                    unsigned char green = static_cast<unsigned char>((rgb & 0x07E0) >> 3);
+                    unsigned char blue = static_cast<unsigned char>((rgb & 0x001F) << 3);
+                    destPixels[x + 0] = blue | (blue >> 5);
+                    destPixels[x + 1] = green | (green >> 6);
+                    destPixels[x + 2] = red | (red >> 5);
+                    destPixels[x + 3] = 0xFF;
+                }
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    unsigned char red = sourcePixels[x * 2 + 1] & 0xF8;
+                    destPixels[x] = red | (red >> 5);
+                }
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          default:
+            UNREACHABLE();
+        }
+        break;
+      case D3DFMT_A1R5G5B5:
+        switch (getD3DFormat())
+        {
+          case D3DFMT_X8R8G8B8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    unsigned short argb = ((unsigned short*)sourcePixels)[x];
+                    unsigned char red = static_cast<unsigned char>((argb & 0x7C00) >> 7);
+                    unsigned char green = static_cast<unsigned char>((argb & 0x03E0) >> 2);
+                    unsigned char blue = static_cast<unsigned char>((argb & 0x001F) << 3);
+                    destPixels[x + 0] = blue | (blue >> 5);
+                    destPixels[x + 1] = green | (green >> 5);
+                    destPixels[x + 2] = red | (red >> 5);
+                    destPixels[x + 3] = 0xFF;
+                }
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_A8R8G8B8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    unsigned short argb = ((unsigned short*)sourcePixels)[x];
+                    unsigned char red = static_cast<unsigned char>((argb & 0x7C00) >> 7);
+                    unsigned char green = static_cast<unsigned char>((argb & 0x03E0) >> 2);
+                    unsigned char blue = static_cast<unsigned char>((argb & 0x001F) << 3);
+                    unsigned char alpha = (signed short)argb >> 15;
+                    destPixels[x + 0] = blue | (blue >> 5);
+                    destPixels[x + 1] = green | (green >> 5);
+                    destPixels[x + 2] = red | (red >> 5);
+                    destPixels[x + 3] = alpha;
+                }
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    unsigned char red = sourcePixels[x * 2 + 1] & 0x7C;
+                    destPixels[x] = (red << 1) | (red >> 4);
+                }
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_A8L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    unsigned char red = sourcePixels[x * 2 + 1] & 0x7C;
+                    destPixels[x * 2 + 0] = (red << 1) | (red >> 4);
+                    destPixels[x * 2 + 1] = (signed char)sourcePixels[x * 2 + 1] >> 7;
+                }
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          default:
+            UNREACHABLE();
+        }
+        break;
+      default:
+        UNREACHABLE();
+    }
+
+    unlock();
+    renderTargetData->UnlockRect();
+
+    SafeRelease(renderTargetData);
+    SafeRelease(surface);
+
+    mDirty = true;
+    return gl::NoError();
+}
+
+gl::Error Image9::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source)
+{
+    RenderTargetD3D *renderTarget = nullptr;
+    gl::Error error = source->getRenderTarget(imageIndex, &renderTarget);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    gl::Rectangle sourceArea(0, 0, mWidth, mHeight);
+    return copyFromRTInternal(gl::Offset(), sourceArea, renderTarget);
+}
+
+gl::Error Image9::copyFromFramebuffer(const gl::Offset &destOffset,
+                                      const gl::Rectangle &sourceArea,
+                                      const gl::Framebuffer *source)
+{
+    const gl::FramebufferAttachment *srcAttachment = source->getReadColorbuffer();
+    ASSERT(srcAttachment);
+
+    RenderTargetD3D *renderTarget = nullptr;
+    gl::Error error = srcAttachment->getRenderTarget(&renderTarget);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ASSERT(renderTarget);
+    return copyFromRTInternal(destOffset, sourceArea, renderTarget);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
new file mode 100644
index 0000000..068a67f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
@@ -0,0 +1,80 @@
+//
+// 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.
+//
+
+// Image9.h: Defines the rx::Image9 class, which acts as the interface to
+// the actual underlying surfaces of a Texture.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
+
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+#include "common/debug.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer9;
+
+class Image9 : public ImageD3D
+{
+  public:
+    Image9(Renderer9 *renderer);
+    ~Image9();
+
+    static gl::Error generateMipmap(Image9 *dest, Image9 *source);
+    static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
+    static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
+
+    bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override;
+
+    D3DFORMAT getD3DFormat() const;
+
+    virtual bool isDirty() const;
+
+    virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level);
+    virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level);
+    virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+
+    gl::Error loadData(const gl::Box &area,
+                       const gl::PixelUnpackState &unpack,
+                       GLenum type,
+                       const void *input,
+                       bool applySkipImages) override;
+    gl::Error loadCompressedData(const gl::Box &area, const void *input) override;
+
+    gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override;
+    gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+                                  const gl::Rectangle &sourceArea,
+                                  const gl::Framebuffer *source) override;
+
+  private:
+    gl::Error getSurface(IDirect3DSurface9 **outSurface);
+
+    gl::Error createSurface();
+    gl::Error setManagedSurface(IDirect3DSurface9 *surface);
+    gl::Error copyToSurface(IDirect3DSurface9 *dest, const gl::Box &area);
+
+    gl::Error lock(D3DLOCKED_RECT *lockedRect, const RECT &rect);
+    void unlock();
+
+    gl::Error copyFromRTInternal(const gl::Offset &destOffset,
+                                 const gl::Rectangle &sourceArea,
+                                 RenderTargetD3D *source);
+
+    Renderer9 *mRenderer;
+
+    D3DPOOL mD3DPool;   // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable.
+    D3DFORMAT mD3DFormat;
+
+    IDirect3DSurface9 *mSurface;
+};
+}
+
+#endif   // LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
new file mode 100644
index 0000000..378ceeb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
@@ -0,0 +1,167 @@
+//
+// 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.
+//
+
+// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
+{
+    mIndexBuffer = nullptr;
+    mBufferSize = 0;
+    mIndexType = 0;
+    mDynamic = false;
+}
+
+IndexBuffer9::~IndexBuffer9()
+{
+    SafeRelease(mIndexBuffer);
+}
+
+gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
+{
+    SafeRelease(mIndexBuffer);
+
+    updateSerial();
+
+    if (bufferSize > 0)
+    {
+        D3DFORMAT format = D3DFMT_UNKNOWN;
+        if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE)
+        {
+            format = D3DFMT_INDEX16;
+        }
+        else if (indexType == GL_UNSIGNED_INT)
+        {
+            ASSERT(mRenderer->getNativeExtensions().elementIndexUint);
+            format = D3DFMT_INDEX32;
+        }
+        else UNREACHABLE();
+
+        DWORD usageFlags = D3DUSAGE_WRITEONLY;
+        if (dynamic)
+        {
+            usageFlags |= D3DUSAGE_DYNAMIC;
+        }
+
+        HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize);
+        }
+    }
+
+    mBufferSize = bufferSize;
+    mIndexType = indexType;
+    mDynamic = dynamic;
+
+    return gl::NoError();
+}
+
+gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
+{
+    if (!mIndexBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+    }
+
+    DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
+
+    void *mapPtr   = nullptr;
+    HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
+    }
+
+    *outMappedMemory = mapPtr;
+    return gl::NoError();
+}
+
+gl::Error IndexBuffer9::unmapBuffer()
+{
+    if (!mIndexBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+    }
+
+    HRESULT result = mIndexBuffer->Unlock();
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
+    }
+
+    return gl::NoError();
+}
+
+GLenum IndexBuffer9::getIndexType() const
+{
+    return mIndexType;
+}
+
+unsigned int IndexBuffer9::getBufferSize() const
+{
+    return mBufferSize;
+}
+
+gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType)
+{
+    if (bufferSize > mBufferSize || indexType != mIndexType)
+    {
+        return initialize(bufferSize, indexType, mDynamic);
+    }
+    else
+    {
+        return gl::NoError();
+    }
+}
+
+gl::Error IndexBuffer9::discard()
+{
+    if (!mIndexBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+    }
+
+    void *dummy;
+    HRESULT result;
+
+    result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
+    }
+
+    result = mIndexBuffer->Unlock();
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
+    }
+
+    return gl::NoError();
+}
+
+D3DFORMAT IndexBuffer9::getIndexFormat() const
+{
+    switch (mIndexType)
+    {
+      case GL_UNSIGNED_BYTE:    return D3DFMT_INDEX16;
+      case GL_UNSIGNED_SHORT:   return D3DFMT_INDEX16;
+      case GL_UNSIGNED_INT:     return D3DFMT_INDEX32;
+      default: UNREACHABLE();   return D3DFMT_UNKNOWN;
+    }
+}
+
+IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const
+{
+    return mIndexBuffer;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
new file mode 100644
index 0000000..ba03ba7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Indexffer9.h: Defines the D3D9 IndexBuffer implementation.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
+
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+
+namespace rx
+{
+class Renderer9;
+
+class IndexBuffer9 : public IndexBuffer
+{
+  public:
+    explicit IndexBuffer9(Renderer9 *const renderer);
+    virtual ~IndexBuffer9();
+
+    virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+
+    virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
+    virtual gl::Error unmapBuffer();
+
+    virtual GLenum getIndexType() const;
+    virtual unsigned int getBufferSize() const;
+    virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType);
+
+    virtual gl::Error discard();
+
+    D3DFORMAT getIndexFormat() const;
+    IDirect3DIndexBuffer9 *getBuffer() const;
+
+  private:
+    Renderer9 *const mRenderer;
+
+    IDirect3DIndexBuffer9 *mIndexBuffer;
+    unsigned int mBufferSize;
+    GLenum mIndexType;
+    bool mDynamic;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp
new file mode 100644
index 0000000..388b8aa
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// NativeWindow9.cpp: Defines NativeWindow9, a class for managing and
+// performing operations on an EGLNativeWindowType for the D3D9 renderer.
+
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
+
+namespace rx
+{
+NativeWindow9::NativeWindow9(EGLNativeWindowType window) : NativeWindowD3D(window)
+{
+}
+
+bool NativeWindow9::initialize()
+{
+    return true;
+}
+
+bool NativeWindow9::getClientRect(LPRECT rect) const
+{
+    return GetClientRect(getNativeWindow(), rect) == TRUE;
+}
+
+bool NativeWindow9::isIconic() const
+{
+    return IsIconic(getNativeWindow()) == TRUE;
+}
+
+// static
+bool NativeWindow9::IsValidNativeWindow(EGLNativeWindowType window)
+{
+    return IsWindow(window) == TRUE;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h
new file mode 100644
index 0000000..a56b08d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// NativeWindow9.h: Defines NativeWindow9, a class for managing and
+// performing operations on an EGLNativeWindowType for the D3D9 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace rx
+{
+
+class NativeWindow9 : public NativeWindowD3D
+{
+  public:
+    explicit NativeWindow9(EGLNativeWindowType window);
+
+    bool initialize() override;
+    bool getClientRect(LPRECT rect) const override;
+    bool isIconic() const override;
+
+    static bool IsValidNativeWindow(EGLNativeWindowType window);
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
new file mode 100644
index 0000000..0305720
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
@@ -0,0 +1,189 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl.
+
+#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+#include <GLES2/gl2ext.h>
+
+namespace rx
+{
+Query9::Query9(Renderer9 *renderer, GLenum type)
+    : QueryImpl(type),
+      mResult(GL_FALSE),
+      mQueryFinished(false),
+      mRenderer(renderer),
+      mQuery(nullptr)
+{
+}
+
+Query9::~Query9()
+{
+    SafeRelease(mQuery);
+}
+
+gl::Error Query9::begin()
+{
+    D3DQUERYTYPE d3dQueryType = gl_d3d9::ConvertQueryType(getType());
+    if (mQuery == nullptr)
+    {
+        HRESULT result = mRenderer->getDevice()->CreateQuery(d3dQueryType, &mQuery);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result);
+        }
+    }
+
+    if (d3dQueryType != D3DQUERYTYPE_EVENT)
+    {
+        HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to begin internal query, result: 0x%X.",
+                             result);
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Query9::end()
+{
+    ASSERT(mQuery);
+
+    HRESULT result = mQuery->Issue(D3DISSUE_END);
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to end internal query, result: 0x%X.", result);
+    }
+
+    mQueryFinished = false;
+    mResult = GL_FALSE;
+
+    return gl::NoError();
+}
+
+gl::Error Query9::queryCounter()
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION, "Unimplemented");
+}
+
+template <typename T>
+gl::Error Query9::getResultBase(T *params)
+{
+    while (!mQueryFinished)
+    {
+        gl::Error error = testQuery();
+        if (error.isError())
+        {
+            return error;
+        }
+
+        if (!mQueryFinished)
+        {
+            Sleep(0);
+        }
+    }
+
+    ASSERT(mQueryFinished);
+    *params = static_cast<T>(mResult);
+    return gl::NoError();
+}
+
+gl::Error Query9::getResult(GLint *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error Query9::getResult(GLuint *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error Query9::getResult(GLint64 *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error Query9::getResult(GLuint64 *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error Query9::isResultAvailable(bool *available)
+{
+    gl::Error error = testQuery();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    *available = mQueryFinished;
+
+    return gl::NoError();
+}
+
+gl::Error Query9::testQuery()
+{
+    if (!mQueryFinished)
+    {
+        ASSERT(mQuery);
+
+        HRESULT result = S_OK;
+        switch (getType())
+        {
+            case GL_ANY_SAMPLES_PASSED_EXT:
+            case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+            {
+                DWORD numPixels = 0;
+                result = mQuery->GetData(&numPixels, sizeof(numPixels), D3DGETDATA_FLUSH);
+                if (result == S_OK)
+                {
+                    mQueryFinished = true;
+                    mResult        = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+                }
+                break;
+            }
+
+            case GL_COMMANDS_COMPLETED_CHROMIUM:
+            {
+                BOOL completed = FALSE;
+                result = mQuery->GetData(&completed, sizeof(completed), D3DGETDATA_FLUSH);
+                if (result == S_OK)
+                {
+                    mQueryFinished = true;
+                    mResult        = (completed == TRUE) ? GL_TRUE : GL_FALSE;
+                }
+                break;
+            }
+
+            default:
+                UNREACHABLE();
+                break;
+        }
+
+        if (d3d9::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+        }
+        else if (mRenderer->testDeviceLost())
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+        }
+    }
+
+    return gl::NoError();
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
new file mode 100644
index 0000000..9d17711
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Query9 : public QueryImpl
+{
+  public:
+    Query9(Renderer9 *renderer, GLenum type);
+    virtual ~Query9();
+
+    virtual gl::Error begin();
+    virtual gl::Error end();
+    virtual gl::Error queryCounter();
+    virtual gl::Error getResult(GLint *params);
+    virtual gl::Error getResult(GLuint *params);
+    virtual gl::Error getResult(GLint64 *params);
+    virtual gl::Error getResult(GLuint64 *params);
+    virtual gl::Error isResultAvailable(bool *available);
+
+  private:
+    gl::Error testQuery();
+
+    template <typename T>
+    gl::Error getResultBase(T *params);
+
+    GLuint64 mResult;
+    bool mQueryFinished;
+
+    Renderer9 *mRenderer;
+    IDirect3DQuery9 *mQuery;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
new file mode 100644
index 0000000..3e54c27
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
@@ -0,0 +1,163 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9
+// pointers retained by renderbuffers.
+
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+
+namespace rx
+{
+
+// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given.
+TextureRenderTarget9::TextureRenderTarget9(IDirect3DBaseTexture9 *texture,
+                                           size_t textureLevel,
+                                           IDirect3DSurface9 *surface,
+                                           GLenum internalFormat,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLsizei depth,
+                                           GLsizei samples)
+    : mWidth(width),
+      mHeight(height),
+      mDepth(depth),
+      mInternalFormat(internalFormat),
+      mD3DFormat(D3DFMT_UNKNOWN),
+      mSamples(samples),
+      mTexture(texture),
+      mTextureLevel(textureLevel),
+      mRenderTarget(surface)
+{
+    ASSERT(mDepth == 1);
+
+    if (mRenderTarget)
+    {
+        D3DSURFACE_DESC description;
+        mRenderTarget->GetDesc(&description);
+        mD3DFormat = description.Format;
+    }
+}
+
+TextureRenderTarget9::~TextureRenderTarget9()
+{
+    SafeRelease(mTexture);
+    SafeRelease(mRenderTarget);
+}
+
+GLsizei TextureRenderTarget9::getWidth() const
+{
+    return mWidth;
+}
+
+GLsizei TextureRenderTarget9::getHeight() const
+{
+    return mHeight;
+}
+
+GLsizei TextureRenderTarget9::getDepth() const
+{
+    return mDepth;
+}
+
+GLenum TextureRenderTarget9::getInternalFormat() const
+{
+    return mInternalFormat;
+}
+
+GLsizei TextureRenderTarget9::getSamples() const
+{
+    return mSamples;
+}
+
+IDirect3DBaseTexture9 *TextureRenderTarget9::getTexture() const
+{
+    return mTexture;
+}
+
+size_t TextureRenderTarget9::getTextureLevel() const
+{
+    return mTextureLevel;
+}
+
+IDirect3DSurface9 *TextureRenderTarget9::getSurface() const
+{
+    // Caller is responsible for releasing the returned surface reference.
+    // TODO: remove the AddRef to match RenderTarget11
+    if (mRenderTarget)
+    {
+        mRenderTarget->AddRef();
+    }
+
+    return mRenderTarget;
+}
+
+D3DFORMAT TextureRenderTarget9::getD3DFormat() const
+{
+    return mD3DFormat;
+}
+
+SurfaceRenderTarget9::SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth)
+    : mSwapChain(swapChain),
+      mDepth(depth)
+{
+}
+
+SurfaceRenderTarget9::~SurfaceRenderTarget9()
+{
+}
+
+GLsizei SurfaceRenderTarget9::getWidth() const
+{
+    return mSwapChain->getWidth();
+}
+
+GLsizei SurfaceRenderTarget9::getHeight() const
+{
+    return mSwapChain->getHeight();
+}
+
+GLsizei SurfaceRenderTarget9::getDepth() const
+{
+    return 1;
+}
+
+GLenum SurfaceRenderTarget9::getInternalFormat() const
+{
+    return (mDepth ? mSwapChain->getDepthBufferInternalFormat()
+                   : mSwapChain->getRenderTargetInternalFormat());
+}
+
+GLsizei SurfaceRenderTarget9::getSamples() const
+{
+    // Our EGL surfaces do not support multisampling.
+    return 0;
+}
+
+IDirect3DSurface9 *SurfaceRenderTarget9::getSurface() const
+{
+    return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget());
+}
+
+IDirect3DBaseTexture9 *SurfaceRenderTarget9::getTexture() const
+{
+    return (mDepth ? nullptr : mSwapChain->getOffscreenTexture());
+}
+
+size_t SurfaceRenderTarget9::getTextureLevel() const
+{
+    return 0;
+}
+
+D3DFORMAT SurfaceRenderTarget9::getD3DFormat() const
+{
+    return d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
new file mode 100644
index 0000000..f19c54d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers
+// retained by Renderbuffers.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
+
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace rx
+{
+class Renderer9;
+class SwapChain9;
+
+class RenderTarget9 : public RenderTargetD3D
+{
+  public:
+    RenderTarget9() { }
+    virtual ~RenderTarget9() { }
+    // Retrieve the texture that backs this render target, may be null for swap chain render
+    // targets.
+    virtual IDirect3DBaseTexture9 *getTexture() const = 0;
+    virtual size_t getTextureLevel() const = 0;
+
+    virtual IDirect3DSurface9 *getSurface() const = 0;
+
+    virtual D3DFORMAT getD3DFormat() const = 0;
+};
+
+class TextureRenderTarget9 : public RenderTarget9
+{
+  public:
+    TextureRenderTarget9(IDirect3DBaseTexture9 *texture,
+                         size_t textureLevel,
+                         IDirect3DSurface9 *surface,
+                         GLenum internalFormat,
+                         GLsizei width,
+                         GLsizei height,
+                         GLsizei depth,
+                         GLsizei samples);
+    virtual ~TextureRenderTarget9();
+
+    GLsizei getWidth() const override;
+    GLsizei getHeight() const override;
+    GLsizei getDepth() const override;
+    GLenum getInternalFormat() const override;
+    GLsizei getSamples() const override;
+
+    IDirect3DBaseTexture9 *getTexture() const override;
+    size_t getTextureLevel() const override;
+    IDirect3DSurface9 *getSurface() const override;
+
+    D3DFORMAT getD3DFormat() const override;
+
+  private:
+    GLsizei mWidth;
+    GLsizei mHeight;
+    GLsizei mDepth;
+    GLenum mInternalFormat;
+    D3DFORMAT mD3DFormat;
+    GLsizei mSamples;
+
+    IDirect3DBaseTexture9 *mTexture;
+    size_t mTextureLevel;
+    IDirect3DSurface9 *mRenderTarget;
+};
+
+class SurfaceRenderTarget9 : public RenderTarget9
+{
+  public:
+    SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth);
+    virtual ~SurfaceRenderTarget9();
+
+    GLsizei getWidth() const override;
+    GLsizei getHeight() const override;
+    GLsizei getDepth() const override;
+    GLenum getInternalFormat() const override;
+    GLsizei getSamples() const override;
+
+    IDirect3DBaseTexture9 *getTexture() const override;
+    size_t getTextureLevel() const override;
+    IDirect3DSurface9 *getSurface() const override;
+
+    D3DFORMAT getD3DFormat() const override;
+
+  private:
+    SwapChain9 *mSwapChain;
+    bool mDepth;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
new file mode 100644
index 0000000..4236b99
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -0,0 +1,3213 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
+
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+#include <EGL/eglext.h>
+#include <sstream>
+
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/features.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Image9.h"
+#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
+#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "third_party/trace_event/trace_event.h"
+
+#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
+#endif
+
+// Enable ANGLE_SUPPORT_SHADER_MODEL_2 if you wish devices with only shader model 2.
+// Such a device would not be conformant.
+#ifndef ANGLE_SUPPORT_SHADER_MODEL_2
+#define ANGLE_SUPPORT_SHADER_MODEL_2 0
+#endif
+
+namespace rx
+{
+
+enum
+{
+    MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
+    MAX_PIXEL_CONSTANT_VECTORS_SM2   = 32,
+    MAX_PIXEL_CONSTANT_VECTORS_SM3   = 224,
+    MAX_VARYING_VECTORS_SM2          = 8,
+    MAX_VARYING_VECTORS_SM3          = 10,
+
+    MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
+};
+
+Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this)
+{
+    mD3d9Module = nullptr;
+
+    mD3d9         = nullptr;
+    mD3d9Ex       = nullptr;
+    mDevice       = nullptr;
+    mDeviceEx     = nullptr;
+    mDeviceWindow = nullptr;
+    mBlit         = nullptr;
+
+    mAdapter = D3DADAPTER_DEFAULT;
+
+    const egl::AttributeMap &attributes = display->getAttributeMap();
+    EGLint requestedDeviceType          = static_cast<EGLint>(attributes.get(
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
+    switch (requestedDeviceType)
+    {
+        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+            mDeviceType = D3DDEVTYPE_HAL;
+            break;
+
+        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+            mDeviceType = D3DDEVTYPE_REF;
+            break;
+
+        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+            mDeviceType = D3DDEVTYPE_NULLREF;
+            break;
+
+        default:
+            UNREACHABLE();
+    }
+
+    mMaskedClearSavedState = nullptr;
+
+    mVertexDataManager = nullptr;
+    mIndexDataManager  = nullptr;
+    mLineLoopIB        = nullptr;
+    mCountingIB        = nullptr;
+
+    mMaxNullColorbufferLRU = 0;
+    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+    {
+        mNullColorbufferCache[i].lruCount = 0;
+        mNullColorbufferCache[i].width    = 0;
+        mNullColorbufferCache[i].height   = 0;
+        mNullColorbufferCache[i].buffer   = nullptr;
+    }
+
+    mAppliedVertexShader  = nullptr;
+    mAppliedPixelShader   = nullptr;
+    mAppliedProgramSerial = 0;
+
+    gl::InitializeDebugAnnotations(&mAnnotator);
+
+    mEGLDevice = nullptr;
+}
+
+Renderer9::~Renderer9()
+{
+    if (mDevice)
+    {
+        // If the device is lost, reset it first to prevent leaving the driver in an unstable state
+        if (testDeviceLost())
+        {
+            resetDevice();
+        }
+    }
+
+    release();
+}
+
+void Renderer9::release()
+{
+    RendererD3D::cleanup();
+
+    gl::UninitializeDebugAnnotations();
+
+    mTranslatedAttribCache.clear();
+
+    releaseDeviceResources();
+
+    SafeDelete(mEGLDevice);
+    SafeRelease(mDevice);
+    SafeRelease(mDeviceEx);
+    SafeRelease(mD3d9);
+    SafeRelease(mD3d9Ex);
+
+    mCompiler.release();
+
+    if (mDeviceWindow)
+    {
+        DestroyWindow(mDeviceWindow);
+        mDeviceWindow = nullptr;
+    }
+
+    mD3d9Module = nullptr;
+}
+
+egl::Error Renderer9::initialize()
+{
+    TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9");
+    mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
+
+    if (mD3d9Module == nullptr)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "No D3D9 module found.");
+    }
+
+    typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
+    Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
+        reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+
+    // Use Direct3D9Ex if available. Among other things, this version is less
+    // inclined to report a lost context, for example when the user switches
+    // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are
+    // available.
+    if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr &&
+        SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
+    {
+        TRACE_EVENT0("gpu.angle", "D3d9Ex_QueryInterface");
+        ASSERT(mD3d9Ex);
+        mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void **>(&mD3d9));
+        ASSERT(mD3d9);
+    }
+    else
+    {
+        TRACE_EVENT0("gpu.angle", "Direct3DCreate9");
+        mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+    }
+
+    if (!mD3d9)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP,
+                          "Could not create D3D9 device.");
+    }
+
+    if (mDisplay->getNativeDisplayId() != nullptr)
+    {
+        //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context
+        //  corresponds to
+    }
+
+    HRESULT result;
+
+    // Give up on getting device caps after about one second.
+    {
+        TRACE_EVENT0("gpu.angle", "GetDeviceCaps");
+        for (int i = 0; i < 10; ++i)
+        {
+            result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
+            if (SUCCEEDED(result))
+            {
+                break;
+            }
+            else if (result == D3DERR_NOTAVAILABLE)
+            {
+                Sleep(100);  // Give the driver some time to initialize/recover
+            }
+            else if (FAILED(result))  // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY,
+                                      // D3DERR_INVALIDDEVICE, or another error we can't recover
+                                      // from
+            {
+                return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_OTHER_ERROR,
+                                  "Failed to get device caps: Error code 0x%x\n", result);
+            }
+        }
+    }
+
+#if ANGLE_SUPPORT_SHADER_MODEL_2
+    size_t minShaderModel = 2;
+#else
+    size_t minShaderModel = 3;
+#endif
+
+    if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(minShaderModel, 0))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_UNSUPPORTED_VERSION,
+                          "Renderer does not support PS %u.%u.aborting!", minShaderModel, 0);
+    }
+
+    // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture
+    // to a render target texture is not supported. This is required by
+    // Texture2D::ensureRenderTarget.
+    if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_UNSUPPORTED_STRETCHRECT,
+                          "Renderer does not support StretctRect from textures.");
+    }
+
+    {
+        TRACE_EVENT0("gpu.angle", "GetAdapterIdentifier");
+        mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
+    }
+
+    static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
+    static const TCHAR className[]  = TEXT("STATIC");
+
+    {
+        TRACE_EVENT0("gpu.angle", "CreateWindowEx");
+        mDeviceWindow =
+            CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1,
+                           1, HWND_MESSAGE, nullptr, GetModuleHandle(nullptr), nullptr);
+    }
+
+    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+    DWORD behaviorFlags =
+        D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED;
+
+    {
+        TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice");
+        result = mD3d9->CreateDevice(
+            mAdapter, mDeviceType, mDeviceWindow,
+            behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
+            &presentParameters, &mDevice);
+    }
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
+    {
+        return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY,
+                          "CreateDevice failed: device lost of out of memory");
+    }
+
+    if (FAILED(result))
+    {
+        TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice2");
+        result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow,
+                                     behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
+                                     &presentParameters, &mDevice);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
+                   result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
+            return egl::Error(
+                EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY,
+                "CreateDevice2 failed: device lost, not available, or of out of memory");
+        }
+    }
+
+    if (mD3d9Ex)
+    {
+        TRACE_EVENT0("gpu.angle", "mDevice_QueryInterface");
+        result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void **)&mDeviceEx);
+        ASSERT(SUCCEEDED(result));
+    }
+
+    {
+        TRACE_EVENT0("gpu.angle", "ShaderCache initialize");
+        mVertexShaderCache.initialize(mDevice);
+        mPixelShaderCache.initialize(mDevice);
+    }
+
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    // Check vertex texture support
+    // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
+    // We test this using D3D9 by checking support for the R16F format.
+    mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
+                            SUCCEEDED(mD3d9->CheckDeviceFormat(
+                                mAdapter, mDeviceType, currentDisplayMode.Format,
+                                D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
+
+    initializeDevice();
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+// do any one-time device initialization
+// NOTE: this is also needed after a device lost/reset
+// to reset the scene status and ensure the default states are reset.
+void Renderer9::initializeDevice()
+{
+    // Permanent non-default states
+    mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
+    mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
+
+    if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
+    {
+        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD &)mDeviceCaps.MaxPointSize);
+    }
+    else
+    {
+        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000);  // 1.0f
+    }
+
+    const gl::Caps &rendererCaps = getNativeCaps();
+
+    mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+    mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+
+    mCurVertexTextures.resize(rendererCaps.maxVertexTextureImageUnits);
+    mCurPixelTextures.resize(rendererCaps.maxTextureImageUnits);
+
+    markAllStateDirty();
+
+    mSceneStarted = false;
+
+    ASSERT(!mBlit);
+    mBlit = new Blit9(this);
+    mBlit->initialize();
+
+    ASSERT(!mVertexDataManager && !mIndexDataManager);
+    mVertexDataManager = new VertexDataManager(this);
+    mIndexDataManager  = new IndexDataManager(this, getRendererClass());
+
+    mTranslatedAttribCache.resize(getNativeCaps().maxVertexAttributes);
+
+    mStateManager.initialize();
+}
+
+D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
+{
+    D3DPRESENT_PARAMETERS presentParameters = {0};
+
+    // The default swap chain is never actually used. Surface will create a new swap chain with the
+    // proper parameters.
+    presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
+    presentParameters.BackBufferCount        = 1;
+    presentParameters.BackBufferFormat       = D3DFMT_UNKNOWN;
+    presentParameters.BackBufferWidth        = 1;
+    presentParameters.BackBufferHeight       = 1;
+    presentParameters.EnableAutoDepthStencil = FALSE;
+    presentParameters.Flags                  = 0;
+    presentParameters.hDeviceWindow          = mDeviceWindow;
+    presentParameters.MultiSampleQuality     = 0;
+    presentParameters.MultiSampleType        = D3DMULTISAMPLE_NONE;
+    presentParameters.PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
+    presentParameters.SwapEffect             = D3DSWAPEFFECT_DISCARD;
+    presentParameters.Windowed               = TRUE;
+
+    return presentParameters;
+}
+
+egl::ConfigSet Renderer9::generateConfigs()
+{
+    static const GLenum colorBufferFormats[] = {
+        GL_BGR5_A1_ANGLEX, GL_BGRA8_EXT, GL_RGB565,
+
+    };
+
+    static const GLenum depthStencilBufferFormats[] = {
+        GL_NONE,
+        GL_DEPTH_COMPONENT32_OES,
+        GL_DEPTH24_STENCIL8_OES,
+        GL_DEPTH_COMPONENT24_OES,
+        GL_DEPTH_COMPONENT16,
+    };
+
+    const gl::Caps &rendererCaps                  = getNativeCaps();
+    const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
+
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    // Determine the min and max swap intervals
+    int minSwapInterval = 4;
+    int maxSwapInterval = 0;
+
+    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+    {
+        minSwapInterval = std::min(minSwapInterval, 0);
+        maxSwapInterval = std::max(maxSwapInterval, 0);
+    }
+    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+    {
+        minSwapInterval = std::min(minSwapInterval, 1);
+        maxSwapInterval = std::max(maxSwapInterval, 1);
+    }
+    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
+    {
+        minSwapInterval = std::min(minSwapInterval, 2);
+        maxSwapInterval = std::max(maxSwapInterval, 2);
+    }
+    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
+    {
+        minSwapInterval = std::min(minSwapInterval, 3);
+        maxSwapInterval = std::max(maxSwapInterval, 3);
+    }
+    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
+    {
+        minSwapInterval = std::min(minSwapInterval, 4);
+        maxSwapInterval = std::max(maxSwapInterval, 4);
+    }
+
+    egl::ConfigSet configs;
+    for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++)
+    {
+        GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex];
+        const gl::TextureCaps &colorBufferFormatCaps =
+            rendererTextureCaps.get(colorBufferInternalFormat);
+        if (colorBufferFormatCaps.renderable)
+        {
+            for (size_t depthStencilIndex = 0;
+                 depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++)
+            {
+                GLenum depthStencilBufferInternalFormat =
+                    depthStencilBufferFormats[depthStencilIndex];
+                const gl::TextureCaps &depthStencilBufferFormatCaps =
+                    rendererTextureCaps.get(depthStencilBufferInternalFormat);
+                if (depthStencilBufferFormatCaps.renderable ||
+                    depthStencilBufferInternalFormat == GL_NONE)
+                {
+                    const gl::InternalFormat &colorBufferFormatInfo =
+                        gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
+                    const gl::InternalFormat &depthStencilBufferFormatInfo =
+                        gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
+                    const d3d9::TextureFormat &d3d9ColorBufferFormatInfo =
+                        d3d9::GetTextureFormatInfo(colorBufferInternalFormat);
+
+                    egl::Config config;
+                    config.renderTargetFormat = colorBufferInternalFormat;
+                    config.depthStencilFormat = depthStencilBufferInternalFormat;
+                    config.bufferSize         = colorBufferFormatInfo.pixelBytes * 8;
+                    config.redSize            = colorBufferFormatInfo.redBits;
+                    config.greenSize          = colorBufferFormatInfo.greenBits;
+                    config.blueSize           = colorBufferFormatInfo.blueBits;
+                    config.luminanceSize      = colorBufferFormatInfo.luminanceBits;
+                    config.alphaSize          = colorBufferFormatInfo.alphaBits;
+                    config.alphaMaskSize      = 0;
+                    config.bindToTextureRGB   = (colorBufferFormatInfo.format == GL_RGB);
+                    config.bindToTextureRGBA  = (colorBufferFormatInfo.format == GL_RGBA ||
+                                                colorBufferFormatInfo.format == GL_BGRA_EXT);
+                    config.colorBufferType = EGL_RGB_BUFFER;
+                    // Mark as slow if blits to the back-buffer won't be straight forward
+                    config.configCaveat =
+                        (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat)
+                            ? EGL_NONE
+                            : EGL_SLOW_CONFIG;
+                    config.configID          = static_cast<EGLint>(configs.size() + 1);
+                    config.conformant        = EGL_OPENGL_ES2_BIT;
+                    config.depthSize         = depthStencilBufferFormatInfo.depthBits;
+                    config.level             = 0;
+                    config.matchNativePixmap = EGL_NONE;
+                    config.maxPBufferWidth   = rendererCaps.max2DTextureSize;
+                    config.maxPBufferHeight  = rendererCaps.max2DTextureSize;
+                    config.maxPBufferPixels =
+                        rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
+                    config.maxSwapInterval  = maxSwapInterval;
+                    config.minSwapInterval  = minSwapInterval;
+                    config.nativeRenderable = EGL_FALSE;
+                    config.nativeVisualID   = 0;
+                    config.nativeVisualType = EGL_NONE;
+                    config.renderableType   = EGL_OPENGL_ES2_BIT;
+                    config.sampleBuffers    = 0;  // FIXME: enumerate multi-sampling
+                    config.samples          = 0;
+                    config.stencilSize      = depthStencilBufferFormatInfo.stencilBits;
+                    config.surfaceType =
+                        EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+                    config.transparentType       = EGL_NONE;
+                    config.transparentRedValue   = 0;
+                    config.transparentGreenValue = 0;
+                    config.transparentBlueValue  = 0;
+                    config.colorComponentType    = gl_egl::GLComponentTypeToEGLColorComponentType(
+                        colorBufferFormatInfo.componentType);
+
+                    configs.add(config);
+                }
+            }
+        }
+    }
+
+    ASSERT(configs.size() > 0);
+    return configs;
+}
+
+void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
+{
+    outExtensions->createContextRobustness = true;
+
+    if (getShareHandleSupport())
+    {
+        outExtensions->d3dShareHandleClientBuffer     = true;
+        outExtensions->surfaceD3DTexture2DShareHandle = true;
+    }
+    outExtensions->d3dTextureClientBuffer = true;
+
+    outExtensions->querySurfacePointer = true;
+    outExtensions->windowFixedSize     = true;
+    outExtensions->postSubBuffer       = true;
+    outExtensions->deviceQuery         = true;
+
+    outExtensions->image               = true;
+    outExtensions->imageBase           = true;
+    outExtensions->glTexture2DImage    = true;
+    outExtensions->glRenderbufferImage = true;
+
+    outExtensions->flexibleSurfaceCompatibility = true;
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
+}
+
+void Renderer9::startScene()
+{
+    if (!mSceneStarted)
+    {
+        long result = mDevice->BeginScene();
+        if (SUCCEEDED(result))
+        {
+            // This is defensive checking against the device being
+            // lost at unexpected times.
+            mSceneStarted = true;
+        }
+    }
+}
+
+void Renderer9::endScene()
+{
+    if (mSceneStarted)
+    {
+        // EndScene can fail if the device was lost, for example due
+        // to a TDR during a draw call.
+        mDevice->EndScene();
+        mSceneStarted = false;
+    }
+}
+
+gl::Error Renderer9::flush()
+{
+    IDirect3DQuery9 *query = nullptr;
+    gl::Error error        = allocateEventQuery(&query);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    HRESULT result = query->Issue(D3DISSUE_END);
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result);
+    }
+
+    // Grab the query data once
+    result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
+    freeEventQuery(query);
+    if (FAILED(result))
+    {
+        if (d3d9::isDeviceLostError(result))
+        {
+            notifyDeviceLost();
+        }
+
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer9::finish()
+{
+    IDirect3DQuery9 *query = nullptr;
+    gl::Error error        = allocateEventQuery(&query);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    HRESULT result = query->Issue(D3DISSUE_END);
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result);
+    }
+
+    // Grab the query data once
+    result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
+    if (FAILED(result))
+    {
+        if (d3d9::isDeviceLostError(result))
+        {
+            notifyDeviceLost();
+        }
+
+        freeEventQuery(query);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+    }
+
+    // Loop until the query completes
+    while (result == S_FALSE)
+    {
+        // Keep polling, but allow other threads to do something useful first
+        ScheduleYield();
+
+        result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
+
+        // explicitly check for device loss
+        // some drivers seem to return S_FALSE even if the device is lost
+        // instead of D3DERR_DEVICELOST like they should
+        if (result == S_FALSE && testDeviceLost())
+        {
+            result = D3DERR_DEVICELOST;
+        }
+
+        if (FAILED(result))
+        {
+            if (d3d9::isDeviceLostError(result))
+            {
+                notifyDeviceLost();
+            }
+
+            freeEventQuery(query);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.",
+                             result);
+        }
+    }
+
+    freeEventQuery(query);
+
+    return gl::NoError();
+}
+
+bool Renderer9::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    return NativeWindow9::IsValidNativeWindow(window);
+}
+
+NativeWindowD3D *Renderer9::createNativeWindow(EGLNativeWindowType window,
+                                               const egl::Config *,
+                                               const egl::AttributeMap &) const
+{
+    return new NativeWindow9(window);
+}
+
+SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow,
+                                         HANDLE shareHandle,
+                                         IUnknown *d3dTexture,
+                                         GLenum backBufferFormat,
+                                         GLenum depthBufferFormat,
+                                         EGLint orientation,
+                                         EGLint samples)
+{
+    return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, d3dTexture,
+                          backBufferFormat, depthBufferFormat, orientation);
+}
+
+egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config,
+                                        IUnknown *d3dTexture,
+                                        EGLint *width,
+                                        EGLint *height,
+                                        GLenum *fboFormat) const
+{
+    IDirect3DTexture9 *texture = nullptr;
+    if (FAILED(d3dTexture->QueryInterface(&texture)))
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "client buffer is not a IDirect3DTexture9");
+    }
+
+    IDirect3DDevice9 *textureDevice = nullptr;
+    texture->GetDevice(&textureDevice);
+    if (textureDevice != mDevice)
+    {
+        SafeRelease(texture);
+        return egl::Error(EGL_BAD_PARAMETER, "Texture's device does not match.");
+    }
+    SafeRelease(textureDevice);
+
+    D3DSURFACE_DESC desc;
+    texture->GetLevelDesc(0, &desc);
+    SafeRelease(texture);
+
+    if (width)
+    {
+        *width = static_cast<EGLint>(desc.Width);
+    }
+    if (height)
+    {
+        *height = static_cast<EGLint>(desc.Height);
+    }
+
+    // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+    switch (desc.Format)
+    {
+        case D3DFMT_R8G8B8:
+        case D3DFMT_A8R8G8B8:
+        case D3DFMT_A16B16G16R16F:
+        case D3DFMT_A32B32G32R32F:
+            break;
+
+        default:
+            return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+                              desc.Format);
+    }
+
+    if (fboFormat)
+    {
+        const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+        ASSERT(d3dFormatInfo.info().id != angle::Format::ID::NONE);
+        *fboFormat = d3dFormatInfo.info().fboImplementationInternalFormat;
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error Renderer9::validateShareHandle(const egl::Config *config,
+                                          HANDLE shareHandle,
+                                          const egl::AttributeMap &attribs) const
+{
+    if (shareHandle == nullptr)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "NULL share handle.");
+    }
+
+    EGLint width  = attribs.getAsInt(EGL_WIDTH, 0);
+    EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
+    ASSERT(width != 0 && height != 0);
+
+    const d3d9::TextureFormat &backBufferd3dFormatInfo =
+        d3d9::GetTextureFormatInfo(config->renderTargetFormat);
+
+    IDirect3DTexture9 *texture = nullptr;
+    HRESULT result             = mDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET,
+                                            backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
+                                            &texture, &shareHandle);
+    if (FAILED(result))
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.", result);
+    }
+
+    DWORD levelCount = texture->GetLevelCount();
+
+    D3DSURFACE_DESC desc;
+    texture->GetLevelDesc(0, &desc);
+    SafeRelease(texture);
+
+    if (levelCount != 1 || desc.Width != static_cast<UINT>(width) ||
+        desc.Height != static_cast<UINT>(height) ||
+        desc.Format != backBufferd3dFormatInfo.texFormat)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Invalid texture parameters in share handle texture.");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+ContextImpl *Renderer9::createContext(const gl::ContextState &state)
+{
+    return new Context9(state, this);
+}
+
+void *Renderer9::getD3DDevice()
+{
+    return reinterpret_cast<void *>(mDevice);
+}
+
+gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery)
+{
+    if (mEventQueryPool.empty())
+    {
+        HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery);
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate event query, result: 0x%X.",
+                             result);
+        }
+    }
+    else
+    {
+        *outQuery = mEventQueryPool.back();
+        mEventQueryPool.pop_back();
+    }
+
+    return gl::NoError();
+}
+
+void Renderer9::freeEventQuery(IDirect3DQuery9 *query)
+{
+    if (mEventQueryPool.size() > 1000)
+    {
+        SafeRelease(query);
+    }
+    else
+    {
+        mEventQueryPool.push_back(query);
+    }
+}
+
+gl::Error Renderer9::createVertexShader(const DWORD *function,
+                                        size_t length,
+                                        IDirect3DVertexShader9 **outShader)
+{
+    return mVertexShaderCache.create(function, length, outShader);
+}
+
+gl::Error Renderer9::createPixelShader(const DWORD *function,
+                                       size_t length,
+                                       IDirect3DPixelShader9 **outShader)
+{
+    return mPixelShaderCache.create(function, length, outShader);
+}
+
+HRESULT Renderer9::createVertexBuffer(UINT Length,
+                                      DWORD Usage,
+                                      IDirect3DVertexBuffer9 **ppVertexBuffer)
+{
+    D3DPOOL Pool = getBufferPool(Usage);
+    return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, nullptr);
+}
+
+VertexBuffer *Renderer9::createVertexBuffer()
+{
+    return new VertexBuffer9(this);
+}
+
+HRESULT Renderer9::createIndexBuffer(UINT Length,
+                                     DWORD Usage,
+                                     D3DFORMAT Format,
+                                     IDirect3DIndexBuffer9 **ppIndexBuffer)
+{
+    D3DPOOL Pool = getBufferPool(Usage);
+    return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, nullptr);
+}
+
+IndexBuffer *Renderer9::createIndexBuffer()
+{
+    return new IndexBuffer9(this);
+}
+
+StreamProducerImpl *Renderer9::createStreamProducerD3DTextureNV12(
+    egl::Stream::ConsumerType consumerType,
+    const egl::AttributeMap &attribs)
+{
+    // Streams are not supported under D3D9
+    UNREACHABLE();
+    return nullptr;
+}
+
+bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
+{
+    // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
+    return false;
+}
+
+gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack,
+                                             unsigned int offset,
+                                             RenderTargetD3D *destRenderTarget,
+                                             GLenum destinationFormat,
+                                             GLenum sourcePixelsType,
+                                             const gl::Box &destArea)
+{
+    // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::setSamplerState(gl::SamplerType type,
+                                     int index,
+                                     gl::Texture *texture,
+                                     const gl::SamplerState &samplerState)
+{
+    CurSamplerState &appliedSampler = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates[index]
+                                                                  : mCurVertexSamplerStates[index];
+
+    // Make sure to add the level offset for our tiny compressed texture workaround
+    TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+
+    TextureStorage *storage = nullptr;
+    gl::Error error         = textureD3D->getNativeTexture(&storage);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    // Storage should exist, texture should be complete
+    ASSERT(storage);
+
+    DWORD baseLevel = texture->getBaseLevel() + storage->getTopLevel();
+
+    if (appliedSampler.forceSet || appliedSampler.baseLevel != baseLevel ||
+        memcmp(&samplerState, &appliedSampler, sizeof(gl::SamplerState)) != 0)
+    {
+        int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+        int d3dSampler       = index + d3dSamplerOffset;
+
+        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU,
+                                 gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
+        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV,
+                                 gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
+
+        mDevice->SetSamplerState(
+            d3dSampler, D3DSAMP_MAGFILTER,
+            gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
+
+        D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
+        float lodBias;
+        gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, &lodBias,
+                                  samplerState.maxAnisotropy, baseLevel);
+        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
+        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel);
+        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPMAPLODBIAS, static_cast<DWORD>(lodBias));
+        if (getNativeExtensions().textureFilterAnisotropic)
+        {
+            DWORD maxAnisotropy =
+                std::min(mDeviceCaps.MaxAnisotropy, static_cast<DWORD>(samplerState.maxAnisotropy));
+            mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, maxAnisotropy);
+        }
+    }
+
+    appliedSampler.forceSet     = false;
+    appliedSampler.samplerState = samplerState;
+    appliedSampler.baseLevel    = baseLevel;
+
+    return gl::NoError();
+}
+
+gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+{
+    int d3dSamplerOffset              = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+    int d3dSampler                    = index + d3dSamplerOffset;
+    IDirect3DBaseTexture9 *d3dTexture = nullptr;
+    bool forceSetTexture              = false;
+
+    std::vector<uintptr_t> &appliedTextures =
+        (type == gl::SAMPLER_PIXEL) ? mCurPixelTextures : mCurVertexTextures;
+
+    if (texture)
+    {
+        TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
+
+        TextureStorage *texStorage = nullptr;
+        gl::Error error            = textureImpl->getNativeTexture(&texStorage);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        // Texture should be complete and have a storage
+        ASSERT(texStorage);
+
+        TextureStorage9 *storage9 = GetAs<TextureStorage9>(texStorage);
+        error                     = storage9->getBaseTexture(&d3dTexture);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        // If we get NULL back from getBaseTexture here, something went wrong
+        // in the texture class and we're unexpectedly missing the d3d texture
+        ASSERT(d3dTexture != nullptr);
+
+        forceSetTexture = textureImpl->hasDirtyImages();
+        textureImpl->resetDirty();
+    }
+
+    if (forceSetTexture || appliedTextures[index] != reinterpret_cast<uintptr_t>(d3dTexture))
+    {
+        mDevice->SetTexture(d3dSampler, d3dTexture);
+    }
+
+    appliedTextures[index] = reinterpret_cast<uintptr_t>(d3dTexture);
+
+    return gl::NoError();
+}
+
+gl::Error Renderer9::setUniformBuffers(const gl::ContextState & /*data*/,
+                                       const std::vector<GLint> & /*vertexUniformBuffers*/,
+                                       const std::vector<GLint> & /*fragmentUniformBuffers*/)
+{
+    // No effect in ES2/D3D9
+    return gl::NoError();
+}
+
+gl::Error Renderer9::updateState(Context9 *context, GLenum drawMode)
+{
+    const auto &data    = context->getContextState();
+    const auto &glState = data.getState();
+
+    // Applies the render target surface, depth stencil surface, viewport rectangle and
+    // scissor rectangle to the renderer
+    gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+    ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete());
+
+    ANGLE_TRY(applyRenderTarget(context, framebuffer));
+
+    // Setting viewport state
+    setViewport(glState.getViewport(), glState.getNearPlane(), glState.getFarPlane(), drawMode,
+                glState.getRasterizerState().frontFace, false);
+
+    // Setting scissors state
+    setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
+
+    // Setting blend, depth stencil, and rasterizer states
+    // Since framebuffer->getSamples will return the original samples which may be different with
+    // the sample counts that we set in render target view, here we use renderTarget->getSamples to
+    // get the actual samples.
+    GLsizei samples           = 0;
+    auto firstColorAttachment = framebuffer->getFirstColorbuffer();
+    if (firstColorAttachment)
+    {
+        ASSERT(firstColorAttachment->isAttached());
+        RenderTarget9 *renderTarget = nullptr;
+        ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
+        samples = renderTarget->getSamples();
+    }
+    gl::RasterizerState rasterizer = glState.getRasterizerState();
+    rasterizer.pointDrawMode       = (drawMode == GL_POINTS);
+    rasterizer.multiSample         = (samples != 0);
+
+    unsigned int mask = GetBlendSampleMask(data, samples);
+    ANGLE_TRY(setBlendDepthRasterStates(data, mask));
+
+    mStateManager.resetDirtyBits();
+
+    return gl::NoError();
+}
+
+void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+{
+    mStateManager.setScissorState(scissor, enabled);
+}
+
+gl::Error Renderer9::setBlendDepthRasterStates(const gl::ContextState &glData, GLenum drawMode)
+{
+    const auto &glState  = glData.getState();
+    auto drawFramebuffer = glState.getDrawFramebuffer();
+    ASSERT(!drawFramebuffer->hasAnyDirtyBit());
+    // Since framebuffer->getSamples will return the original samples which may be different with
+    // the sample counts that we set in render target view, here we use renderTarget->getSamples to
+    // get the actual samples.
+    GLsizei samples           = 0;
+    auto firstColorAttachment = drawFramebuffer->getFirstColorbuffer();
+    if (firstColorAttachment)
+    {
+        ASSERT(firstColorAttachment->isAttached());
+        RenderTarget9 *renderTarget = nullptr;
+        ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
+        samples = renderTarget->getSamples();
+    }
+    gl::RasterizerState rasterizer = glState.getRasterizerState();
+    rasterizer.pointDrawMode       = (drawMode == GL_POINTS);
+    rasterizer.multiSample         = (samples != 0);
+
+    unsigned int mask = GetBlendSampleMask(glData, samples);
+    return mStateManager.setBlendDepthRasterStates(glState, mask);
+}
+
+void Renderer9::setViewport(const gl::Rectangle &viewport,
+                            float zNear,
+                            float zFar,
+                            GLenum drawMode,
+                            GLenum frontFace,
+                            bool ignoreViewport)
+{
+    mStateManager.setViewportState(viewport, zNear, zFar, drawMode, frontFace, ignoreViewport);
+}
+
+bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
+{
+    switch (mode)
+    {
+        case GL_POINTS:
+            mPrimitiveType  = D3DPT_POINTLIST;
+            mPrimitiveCount = count;
+            break;
+        case GL_LINES:
+            mPrimitiveType  = D3DPT_LINELIST;
+            mPrimitiveCount = count / 2;
+            break;
+        case GL_LINE_LOOP:
+            mPrimitiveType = D3DPT_LINESTRIP;
+            mPrimitiveCount =
+                count - 1;  // D3D doesn't support line loops, so we draw the last line separately
+            break;
+        case GL_LINE_STRIP:
+            mPrimitiveType  = D3DPT_LINESTRIP;
+            mPrimitiveCount = count - 1;
+            break;
+        case GL_TRIANGLES:
+            mPrimitiveType  = D3DPT_TRIANGLELIST;
+            mPrimitiveCount = count / 3;
+            break;
+        case GL_TRIANGLE_STRIP:
+            mPrimitiveType  = D3DPT_TRIANGLESTRIP;
+            mPrimitiveCount = count - 2;
+            break;
+        case GL_TRIANGLE_FAN:
+            mPrimitiveType  = D3DPT_TRIANGLEFAN;
+            mPrimitiveCount = count - 2;
+            break;
+        default:
+            UNREACHABLE();
+            return false;
+    }
+
+    return mPrimitiveCount > 0;
+}
+
+gl::Error Renderer9::getNullColorbuffer(GLImplFactory *implFactory,
+                                        const gl::FramebufferAttachment *depthbuffer,
+                                        const gl::FramebufferAttachment **outColorBuffer)
+{
+    ASSERT(depthbuffer);
+
+    const gl::Extents &size = depthbuffer->getSize();
+
+    // search cached nullcolorbuffers
+    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+    {
+        if (mNullColorbufferCache[i].buffer != nullptr &&
+            mNullColorbufferCache[i].width == size.width &&
+            mNullColorbufferCache[i].height == size.height)
+        {
+            mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
+            *outColorBuffer                   = mNullColorbufferCache[i].buffer;
+            return gl::NoError();
+        }
+    }
+
+    gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(implFactory->createRenderbuffer(), 0);
+    gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height);
+    if (error.isError())
+    {
+        SafeDelete(nullRenderbuffer);
+        return error;
+    }
+
+    gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment(
+        GL_RENDERBUFFER, GL_NONE, gl::ImageIndex::MakeInvalid(), nullRenderbuffer);
+
+    // add nullbuffer to the cache
+    NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
+    for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+    {
+        if (mNullColorbufferCache[i].lruCount < oldest->lruCount)
+        {
+            oldest = &mNullColorbufferCache[i];
+        }
+    }
+
+    delete oldest->buffer;
+    oldest->buffer   = nullbuffer;
+    oldest->lruCount = ++mMaxNullColorbufferLRU;
+    oldest->width    = size.width;
+    oldest->height   = size.height;
+
+    *outColorBuffer = nullbuffer;
+    return gl::NoError();
+}
+
+gl::Error Renderer9::applyRenderTarget(GLImplFactory *implFactory,
+                                       const gl::FramebufferAttachment *colorAttachment,
+                                       const gl::FramebufferAttachment *depthStencilAttachment)
+{
+    const gl::FramebufferAttachment *renderAttachment = colorAttachment;
+    gl::Error error(GL_NO_ERROR);
+
+    // if there is no color attachment we must synthesize a NULL colorattachment
+    // to keep the D3D runtime happy.  This should only be possible if depth texturing.
+    if (renderAttachment == nullptr)
+    {
+        error = getNullColorbuffer(implFactory, depthStencilAttachment, &renderAttachment);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+    ASSERT(renderAttachment != nullptr);
+
+    size_t renderTargetWidth     = 0;
+    size_t renderTargetHeight    = 0;
+    D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN;
+
+    RenderTarget9 *renderTarget = nullptr;
+    error                       = renderAttachment->getRenderTarget(&renderTarget);
+    if (error.isError())
+    {
+        return error;
+    }
+    ASSERT(renderTarget);
+
+    bool renderTargetChanged        = false;
+    unsigned int renderTargetSerial = renderTarget->getSerial();
+    if (renderTargetSerial != mAppliedRenderTargetSerial)
+    {
+        // Apply the render target on the device
+        IDirect3DSurface9 *renderTargetSurface = renderTarget->getSurface();
+        ASSERT(renderTargetSurface);
+
+        mDevice->SetRenderTarget(0, renderTargetSurface);
+        SafeRelease(renderTargetSurface);
+
+        renderTargetWidth  = renderTarget->getWidth();
+        renderTargetHeight = renderTarget->getHeight();
+        renderTargetFormat = renderTarget->getD3DFormat();
+
+        mAppliedRenderTargetSerial = renderTargetSerial;
+        renderTargetChanged        = true;
+    }
+
+    RenderTarget9 *depthStencilRenderTarget = nullptr;
+    unsigned int depthStencilSerial         = 0;
+
+    if (depthStencilAttachment != nullptr)
+    {
+        error = depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget);
+        if (error.isError())
+        {
+            return error;
+        }
+        ASSERT(depthStencilRenderTarget);
+
+        depthStencilSerial = depthStencilRenderTarget->getSerial();
+    }
+
+    if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized)
+    {
+        unsigned int depthSize   = 0;
+        unsigned int stencilSize = 0;
+
+        // Apply the depth stencil on the device
+        if (depthStencilRenderTarget)
+        {
+            IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface();
+            ASSERT(depthStencilSurface);
+
+            mDevice->SetDepthStencilSurface(depthStencilSurface);
+            SafeRelease(depthStencilSurface);
+
+            depthSize   = depthStencilAttachment->getDepthSize();
+            stencilSize = depthStencilAttachment->getStencilSize();
+        }
+        else
+        {
+            mDevice->SetDepthStencilSurface(nullptr);
+        }
+
+        mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize);
+        mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize);
+
+        mAppliedDepthStencilSerial = depthStencilSerial;
+        mDepthStencilInitialized   = true;
+    }
+
+    if (renderTargetChanged || !mRenderTargetDescInitialized)
+    {
+        mStateManager.forceSetBlendState();
+        mStateManager.forceSetScissorState();
+        mStateManager.setRenderTargetBounds(renderTargetWidth, renderTargetHeight);
+        mRenderTargetDescInitialized = true;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer9::applyRenderTarget(GLImplFactory *implFactory,
+                                       const gl::Framebuffer *framebuffer)
+{
+    return applyRenderTarget(implFactory, framebuffer->getColorbuffer(0),
+                             framebuffer->getDepthOrStencilbuffer());
+}
+
+gl::Error Renderer9::applyVertexBuffer(const gl::State &state,
+                                       GLenum mode,
+                                       GLint first,
+                                       GLsizei count,
+                                       GLsizei instances,
+                                       TranslatedIndexData * /*indexInfo*/)
+{
+    gl::Error error = mVertexDataManager->prepareVertexData(state, first, count,
+                                                            &mTranslatedAttribCache, instances);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return mVertexDeclarationCache.applyDeclaration(
+        mDevice, mTranslatedAttribCache, state.getProgram(), first, instances, &mRepeatDraw);
+}
+
+// Applies the indices and element array bindings to the Direct3D 9 device
+gl::Error Renderer9::applyIndexBuffer(const gl::ContextState &data,
+                                      const void *indices,
+                                      GLsizei count,
+                                      GLenum mode,
+                                      GLenum type,
+                                      TranslatedIndexData *indexInfo)
+{
+    gl::VertexArray *vao           = data.getState().getVertexArray();
+    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+    gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
+                                                          indexInfo, false);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    // Directly binding the storage buffer is not supported for d3d9
+    ASSERT(indexInfo->storage == nullptr);
+
+    if (indexInfo->serial != mAppliedIBSerial)
+    {
+        IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer);
+
+        mDevice->SetIndices(indexBuffer->getBuffer());
+        mAppliedIBSerial = indexInfo->serial;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer9::applyTransformFeedbackBuffers(const gl::State &state)
+{
+    ASSERT(!state.isTransformFeedbackActiveUnpaused());
+    return gl::NoError();
+}
+
+gl::Error Renderer9::drawArraysImpl(const gl::ContextState &data,
+                                    GLenum mode,
+                                    GLint startVertex,
+                                    GLsizei count,
+                                    GLsizei instances)
+{
+    ASSERT(!data.getState().isTransformFeedbackActiveUnpaused());
+
+    startScene();
+
+    if (mode == GL_LINE_LOOP)
+    {
+        return drawLineLoop(count, GL_NONE, nullptr, 0, nullptr);
+    }
+    else if (instances > 0)
+    {
+        StaticIndexBufferInterface *countingIB = nullptr;
+        gl::Error error                        = getCountingIB(count, &countingIB);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        if (mAppliedIBSerial != countingIB->getSerial())
+        {
+            IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(countingIB->getIndexBuffer());
+
+            mDevice->SetIndices(indexBuffer->getBuffer());
+            mAppliedIBSerial = countingIB->getSerial();
+        }
+
+        for (int i = 0; i < mRepeatDraw; i++)
+        {
+            mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
+        }
+
+        return gl::NoError();
+    }
+    else  // Regular case
+    {
+        mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
+        return gl::NoError();
+    }
+}
+
+gl::Error Renderer9::drawElementsImpl(const gl::ContextState &data,
+                                      const TranslatedIndexData &indexInfo,
+                                      GLenum mode,
+                                      GLsizei count,
+                                      GLenum type,
+                                      const void *indices,
+                                      GLsizei /*instances*/)
+{
+    startScene();
+
+    int minIndex = static_cast<int>(indexInfo.indexRange.start);
+
+    gl::VertexArray *vao           = data.getState().getVertexArray();
+    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+    if (mode == GL_POINTS)
+    {
+        return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer);
+    }
+    else if (mode == GL_LINE_LOOP)
+    {
+        return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer);
+    }
+    else
+    {
+        size_t vertexCount = indexInfo.indexRange.vertexCount();
+        for (int i = 0; i < mRepeatDraw; i++)
+        {
+            mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex,
+                                          static_cast<UINT>(vertexCount), indexInfo.startIndex,
+                                          mPrimitiveCount);
+        }
+        return gl::NoError();
+    }
+}
+
+gl::Error Renderer9::drawLineLoop(GLsizei count,
+                                  GLenum type,
+                                  const void *indices,
+                                  int minIndex,
+                                  gl::Buffer *elementArrayBuffer)
+{
+    // Get the raw indices for an indexed draw
+    if (type != GL_NONE && elementArrayBuffer)
+    {
+        BufferD3D *storage        = GetImplAs<BufferD3D>(elementArrayBuffer);
+        intptr_t offset           = reinterpret_cast<intptr_t>(indices);
+        const uint8_t *bufferData = nullptr;
+        gl::Error error           = storage->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+        indices = bufferData + offset;
+    }
+
+    unsigned int startIndex = 0;
+
+    if (getNativeExtensions().elementIndexUint)
+    {
+        if (!mLineLoopIB)
+        {
+            mLineLoopIB = new StreamingIndexBufferInterface(this);
+            gl::Error error =
+                mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+            if (error.isError())
+            {
+                SafeDelete(mLineLoopIB);
+                return error;
+            }
+        }
+
+        // Checked by Renderer9::applyPrimitiveType
+        ASSERT(count >= 0);
+
+        if (static_cast<unsigned int>(count) + 1 >
+            (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too "
+                             "many indices required.");
+        }
+
+        const unsigned int spaceNeeded =
+            (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
+        gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        void *mappedMemory  = nullptr;
+        unsigned int offset = 0;
+        error               = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        startIndex         = static_cast<unsigned int>(offset) / 4;
+        unsigned int *data = reinterpret_cast<unsigned int *>(mappedMemory);
+
+        switch (type)
+        {
+            case GL_NONE:  // Non-indexed draw
+                for (int i = 0; i < count; i++)
+                {
+                    data[i] = i;
+                }
+                data[count] = 0;
+                break;
+            case GL_UNSIGNED_BYTE:
+                for (int i = 0; i < count; i++)
+                {
+                    data[i] = static_cast<const GLubyte *>(indices)[i];
+                }
+                data[count] = static_cast<const GLubyte *>(indices)[0];
+                break;
+            case GL_UNSIGNED_SHORT:
+                for (int i = 0; i < count; i++)
+                {
+                    data[i] = static_cast<const GLushort *>(indices)[i];
+                }
+                data[count] = static_cast<const GLushort *>(indices)[0];
+                break;
+            case GL_UNSIGNED_INT:
+                for (int i = 0; i < count; i++)
+                {
+                    data[i] = static_cast<const GLuint *>(indices)[i];
+                }
+                data[count] = static_cast<const GLuint *>(indices)[0];
+                break;
+            default:
+                UNREACHABLE();
+        }
+
+        error = mLineLoopIB->unmapBuffer();
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+    else
+    {
+        if (!mLineLoopIB)
+        {
+            mLineLoopIB = new StreamingIndexBufferInterface(this);
+            gl::Error error =
+                mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
+            if (error.isError())
+            {
+                SafeDelete(mLineLoopIB);
+                return error;
+            }
+        }
+
+        // Checked by Renderer9::applyPrimitiveType
+        ASSERT(count >= 0);
+
+        if (static_cast<unsigned int>(count) + 1 >
+            (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY,
+                             "Failed to create a 16-bit looping index buffer for GL_LINE_LOOP, too "
+                             "many indices required.");
+        }
+
+        const unsigned int spaceNeeded =
+            (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
+        gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        void *mappedMemory = nullptr;
+        unsigned int offset;
+        error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        startIndex           = static_cast<unsigned int>(offset) / 2;
+        unsigned short *data = reinterpret_cast<unsigned short *>(mappedMemory);
+
+        switch (type)
+        {
+            case GL_NONE:  // Non-indexed draw
+                for (int i = 0; i < count; i++)
+                {
+                    data[i] = static_cast<unsigned short>(i);
+                }
+                data[count] = 0;
+                break;
+            case GL_UNSIGNED_BYTE:
+                for (int i = 0; i < count; i++)
+                {
+                    data[i] = static_cast<const GLubyte *>(indices)[i];
+                }
+                data[count] = static_cast<const GLubyte *>(indices)[0];
+                break;
+            case GL_UNSIGNED_SHORT:
+                for (int i = 0; i < count; i++)
+                {
+                    data[i] = static_cast<const GLushort *>(indices)[i];
+                }
+                data[count] = static_cast<const GLushort *>(indices)[0];
+                break;
+            case GL_UNSIGNED_INT:
+                for (int i = 0; i < count; i++)
+                {
+                    data[i] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[i]);
+                }
+                data[count] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[0]);
+                break;
+            default:
+                UNREACHABLE();
+        }
+
+        error = mLineLoopIB->unmapBuffer();
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    if (mAppliedIBSerial != mLineLoopIB->getSerial())
+    {
+        IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(mLineLoopIB->getIndexBuffer());
+
+        mDevice->SetIndices(indexBuffer->getBuffer());
+        mAppliedIBSerial = mLineLoopIB->getSerial();
+    }
+
+    mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
+
+    return gl::NoError();
+}
+
+template <typename T>
+static gl::Error drawPoints(IDirect3DDevice9 *device,
+                            GLsizei count,
+                            const void *indices,
+                            int minIndex)
+{
+    for (int i = 0; i < count; i++)
+    {
+        unsigned int indexValue =
+            static_cast<unsigned int>(static_cast<const T *>(indices)[i]) - minIndex;
+        device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer9::drawIndexedPoints(GLsizei count,
+                                       GLenum type,
+                                       const void *indices,
+                                       int minIndex,
+                                       gl::Buffer *elementArrayBuffer)
+{
+    // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
+    // for each individual point. This call is not expected to happen often.
+
+    if (elementArrayBuffer)
+    {
+        BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+        intptr_t offset    = reinterpret_cast<intptr_t>(indices);
+
+        const uint8_t *bufferData = nullptr;
+        gl::Error error           = storage->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        indices = bufferData + offset;
+    }
+
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return drawPoints<GLubyte>(mDevice, count, indices, minIndex);
+        case GL_UNSIGNED_SHORT:
+            return drawPoints<GLushort>(mDevice, count, indices, minIndex);
+        case GL_UNSIGNED_INT:
+            return drawPoints<GLuint>(mDevice, count, indices, minIndex);
+        default:
+            UNREACHABLE();
+            return gl::Error(GL_INVALID_OPERATION);
+    }
+}
+
+gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **outIB)
+{
+    // Update the counting index buffer if it is not large enough or has not been created yet.
+    if (count <= 65536)  // 16-bit indices
+    {
+        const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned short);
+
+        if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
+        {
+            SafeDelete(mCountingIB);
+            mCountingIB = new StaticIndexBufferInterface(this);
+            mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+
+            void *mappedMemory = nullptr;
+            gl::Error error    = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, nullptr);
+            if (error.isError())
+            {
+                return error;
+            }
+
+            unsigned short *data = reinterpret_cast<unsigned short *>(mappedMemory);
+            for (size_t i = 0; i < count; i++)
+            {
+                data[i] = static_cast<unsigned short>(i);
+            }
+
+            error = mCountingIB->unmapBuffer();
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+    }
+    else if (getNativeExtensions().elementIndexUint)
+    {
+        const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned int);
+
+        if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
+        {
+            SafeDelete(mCountingIB);
+            mCountingIB = new StaticIndexBufferInterface(this);
+            mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
+
+            void *mappedMemory = nullptr;
+            gl::Error error    = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, nullptr);
+            if (error.isError())
+            {
+                return error;
+            }
+
+            unsigned int *data = reinterpret_cast<unsigned int *>(mappedMemory);
+            for (unsigned int i = 0; i < count; i++)
+            {
+                data[i] = i;
+            }
+
+            error = mCountingIB->unmapBuffer();
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+    }
+    else
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Could not create a counting index buffer for glDrawArraysInstanced.");
+    }
+
+    *outIB = mCountingIB;
+    return gl::NoError();
+}
+
+gl::Error Renderer9::applyShaders(const gl::ContextState &data, GLenum drawMode)
+{
+    // This method is called single-threaded.
+    ANGLE_TRY(ensureHLSLCompilerInitialized());
+
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram());
+    programD3D->updateCachedInputLayout(data.getState());
+
+    const auto &inputLayout = programD3D->getCachedInputLayout();
+
+    ShaderExecutableD3D *vertexExe = nullptr;
+    ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr));
+
+    const gl::Framebuffer *drawFramebuffer = data.getState().getDrawFramebuffer();
+    ShaderExecutableD3D *pixelExe          = nullptr;
+    ANGLE_TRY(programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe));
+
+    IDirect3DVertexShader9 *vertexShader =
+        (vertexExe ? GetAs<ShaderExecutable9>(vertexExe)->getVertexShader() : nullptr);
+    IDirect3DPixelShader9 *pixelShader =
+        (pixelExe ? GetAs<ShaderExecutable9>(pixelExe)->getPixelShader() : nullptr);
+
+    if (vertexShader != mAppliedVertexShader)
+    {
+        mDevice->SetVertexShader(vertexShader);
+        mAppliedVertexShader = vertexShader;
+    }
+
+    if (pixelShader != mAppliedPixelShader)
+    {
+        mDevice->SetPixelShader(pixelShader);
+        mAppliedPixelShader = pixelShader;
+    }
+
+    // D3D9 has a quirk where creating multiple shaders with the same content
+    // can return the same shader pointer. Because GL programs store different data
+    // per-program, checking the program serial guarantees we upload fresh
+    // uniform data even if our shader pointers are the same.
+    // https://code.google.com/p/angleproject/issues/detail?id=661
+    unsigned int programSerial = programD3D->getSerial();
+    if (programSerial != mAppliedProgramSerial)
+    {
+        programD3D->dirtyAllUniforms();
+        mStateManager.forceSetDXUniformsState();
+        mAppliedProgramSerial = programSerial;
+    }
+
+    return programD3D->applyUniforms(drawMode);
+}
+
+gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
+                                   GLenum /*drawMode*/,
+                                   const std::vector<D3DUniform *> &uniformArray)
+{
+    for (const D3DUniform *targetUniform : uniformArray)
+    {
+        if (!targetUniform->dirty)
+            continue;
+
+        GLfloat *f = (GLfloat *)targetUniform->data;
+        GLint *i   = (GLint *)targetUniform->data;
+
+        switch (targetUniform->type)
+        {
+            case GL_SAMPLER_2D:
+            case GL_SAMPLER_CUBE:
+            case GL_SAMPLER_EXTERNAL_OES:
+                break;
+            case GL_BOOL:
+            case GL_BOOL_VEC2:
+            case GL_BOOL_VEC3:
+            case GL_BOOL_VEC4:
+                applyUniformnbv(targetUniform, i);
+                break;
+            case GL_FLOAT:
+            case GL_FLOAT_VEC2:
+            case GL_FLOAT_VEC3:
+            case GL_FLOAT_VEC4:
+            case GL_FLOAT_MAT2:
+            case GL_FLOAT_MAT3:
+            case GL_FLOAT_MAT4:
+                applyUniformnfv(targetUniform, f);
+                break;
+            case GL_INT:
+            case GL_INT_VEC2:
+            case GL_INT_VEC3:
+            case GL_INT_VEC4:
+                applyUniformniv(targetUniform, i);
+                break;
+            default:
+                UNREACHABLE();
+        }
+    }
+
+    // Driver uniforms
+    mStateManager.setShaderConstants();
+
+    return gl::NoError();
+}
+
+void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v)
+{
+    if (targetUniform->isReferencedByFragmentShader())
+    {
+        mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v,
+                                         targetUniform->registerCount);
+    }
+
+    if (targetUniform->isReferencedByVertexShader())
+    {
+        mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v,
+                                          targetUniform->registerCount);
+    }
+}
+
+void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v)
+{
+    ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
+    GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
+
+    for (unsigned int i = 0; i < targetUniform->registerCount; i++)
+    {
+        vector[i][0] = (GLfloat)v[4 * i + 0];
+        vector[i][1] = (GLfloat)v[4 * i + 1];
+        vector[i][2] = (GLfloat)v[4 * i + 2];
+        vector[i][3] = (GLfloat)v[4 * i + 3];
+    }
+
+    applyUniformnfv(targetUniform, (GLfloat *)vector);
+}
+
+void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v)
+{
+    ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
+    GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
+
+    for (unsigned int i = 0; i < targetUniform->registerCount; i++)
+    {
+        vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f;
+        vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f;
+        vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f;
+        vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
+    }
+
+    applyUniformnfv(targetUniform, (GLfloat *)vector);
+}
+
+gl::Error Renderer9::clear(const ClearParameters &clearParams,
+                           const gl::FramebufferAttachment *colorBuffer,
+                           const gl::FramebufferAttachment *depthStencilBuffer)
+{
+    if (clearParams.colorType != GL_FLOAT)
+    {
+        // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0
+        UNREACHABLE();
+        return gl::Error(GL_INVALID_OPERATION);
+    }
+
+    bool clearColor = clearParams.clearColor[0];
+    for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+    {
+        if (clearParams.clearColor[i] != clearColor)
+        {
+            // Clearing individual buffers other than buffer zero is not supported by Renderer9 and
+            // ES 2.0
+            UNREACHABLE();
+            return gl::Error(GL_INVALID_OPERATION);
+        }
+    }
+
+    float depth   = gl::clamp01(clearParams.depthValue);
+    DWORD stencil = clearParams.stencilValue & 0x000000FF;
+
+    unsigned int stencilUnmasked = 0x0;
+    if (clearParams.clearStencil && depthStencilBuffer->getStencilSize() > 0)
+    {
+        ASSERT(depthStencilBuffer != nullptr);
+
+        RenderTargetD3D *stencilRenderTarget = nullptr;
+        gl::Error error = depthStencilBuffer->getRenderTarget(&stencilRenderTarget);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        RenderTarget9 *stencilRenderTarget9 = GetAs<RenderTarget9>(stencilRenderTarget);
+        ASSERT(stencilRenderTarget9);
+
+        const d3d9::D3DFormat &d3dFormatInfo =
+            d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat());
+        stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1;
+    }
+
+    const bool needMaskedStencilClear =
+        clearParams.clearStencil &&
+        (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+
+    bool needMaskedColorClear = false;
+    D3DCOLOR color            = D3DCOLOR_ARGB(255, 0, 0, 0);
+    if (clearColor)
+    {
+        ASSERT(colorBuffer != nullptr);
+
+        RenderTargetD3D *colorRenderTarget = nullptr;
+        gl::Error error                    = colorBuffer->getRenderTarget(&colorRenderTarget);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        RenderTarget9 *colorRenderTarget9 = GetAs<RenderTarget9>(colorRenderTarget);
+        ASSERT(colorRenderTarget9);
+
+        const gl::InternalFormat &formatInfo = *colorBuffer->getFormat().info;
+        const d3d9::D3DFormat &d3dFormatInfo =
+            d3d9::GetD3DFormatInfo(colorRenderTarget9->getD3DFormat());
+
+        color =
+            D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0)
+                                           ? 1.0f
+                                           : clearParams.colorF.alpha),
+                          gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0)
+                                           ? 0.0f
+                                           : clearParams.colorF.red),
+                          gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0)
+                                           ? 0.0f
+                                           : clearParams.colorF.green),
+                          gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0)
+                                           ? 0.0f
+                                           : clearParams.colorF.blue));
+
+        if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
+            (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
+            (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
+            (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
+        {
+            needMaskedColorClear = true;
+        }
+    }
+
+    if (needMaskedColorClear || needMaskedStencilClear)
+    {
+        // State which is altered in all paths from this point to the clear call is saved.
+        // State which is altered in only some paths will be flagged dirty in the case that
+        //  that path is taken.
+        HRESULT hr;
+        if (mMaskedClearSavedState == nullptr)
+        {
+            hr = mDevice->BeginStateBlock();
+            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+            mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+            mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+            mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+            mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+            mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+            mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+            mDevice->SetPixelShader(nullptr);
+            mDevice->SetVertexShader(nullptr);
+            mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
+            mDevice->SetStreamSource(0, nullptr, 0, 0);
+            mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+            mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+            mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+            mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+            mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+            mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+            mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+
+            for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+            {
+                mDevice->SetStreamSourceFreq(i, 1);
+            }
+
+            hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
+            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+        }
+
+        ASSERT(mMaskedClearSavedState != nullptr);
+
+        if (mMaskedClearSavedState != nullptr)
+        {
+            hr = mMaskedClearSavedState->Capture();
+            ASSERT(SUCCEEDED(hr));
+        }
+
+        mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+        mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+        mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+        mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+        mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+        mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+        mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+        mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+
+        if (clearColor)
+        {
+            mDevice->SetRenderState(
+                D3DRS_COLORWRITEENABLE,
+                gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen,
+                                          clearParams.colorMaskBlue, clearParams.colorMaskAlpha));
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+        }
+
+        if (stencilUnmasked != 0x0 && clearParams.clearStencil)
+        {
+            mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+            mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
+            mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
+            mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
+            mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask);
+            mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
+            mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
+            mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+        }
+
+        mDevice->SetPixelShader(nullptr);
+        mDevice->SetVertexShader(nullptr);
+        mDevice->SetFVF(D3DFVF_XYZRHW);
+        mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+        mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+        mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+        mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+        mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+        mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+        mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+
+        for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+        {
+            mDevice->SetStreamSourceFreq(i, 1);
+        }
+
+        int renderTargetWidth  = mStateManager.getRenderTargetWidth();
+        int renderTargetHeight = mStateManager.getRenderTargetHeight();
+
+        float quad[4][4];  // A quadrilateral covering the target, aligned to match the edges
+        quad[0][0] = -0.5f;
+        quad[0][1] = renderTargetHeight - 0.5f;
+        quad[0][2] = 0.0f;
+        quad[0][3] = 1.0f;
+
+        quad[1][0] = renderTargetWidth - 0.5f;
+        quad[1][1] = renderTargetHeight - 0.5f;
+        quad[1][2] = 0.0f;
+        quad[1][3] = 1.0f;
+
+        quad[2][0] = -0.5f;
+        quad[2][1] = -0.5f;
+        quad[2][2] = 0.0f;
+        quad[2][3] = 1.0f;
+
+        quad[3][0] = renderTargetWidth - 0.5f;
+        quad[3][1] = -0.5f;
+        quad[3][2] = 0.0f;
+        quad[3][3] = 1.0f;
+
+        startScene();
+        mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
+
+        if (clearParams.clearDepth)
+        {
+            mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
+            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
+            mDevice->Clear(0, nullptr, D3DCLEAR_ZBUFFER, color, depth, stencil);
+        }
+
+        if (mMaskedClearSavedState != nullptr)
+        {
+            mMaskedClearSavedState->Apply();
+        }
+    }
+    else if (clearColor || clearParams.clearDepth || clearParams.clearStencil)
+    {
+        DWORD dxClearFlags = 0;
+        if (clearColor)
+        {
+            dxClearFlags |= D3DCLEAR_TARGET;
+        }
+        if (clearParams.clearDepth)
+        {
+            dxClearFlags |= D3DCLEAR_ZBUFFER;
+        }
+        if (clearParams.clearStencil)
+        {
+            dxClearFlags |= D3DCLEAR_STENCIL;
+        }
+
+        mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil);
+    }
+
+    return gl::NoError();
+}
+
+void Renderer9::markAllStateDirty()
+{
+    mAppliedRenderTargetSerial   = 0;
+    mAppliedDepthStencilSerial   = 0;
+    mDepthStencilInitialized     = false;
+    mRenderTargetDescInitialized = false;
+
+    mStateManager.forceSetRasterState();
+    mStateManager.forceSetDepthStencilState();
+    mStateManager.forceSetBlendState();
+    mStateManager.forceSetScissorState();
+    mStateManager.forceSetViewportState();
+
+    ASSERT(mCurVertexSamplerStates.size() == mCurVertexTextures.size());
+    for (unsigned int i = 0; i < mCurVertexTextures.size(); i++)
+    {
+        mCurVertexSamplerStates[i].forceSet = true;
+        mCurVertexTextures[i]               = angle::DirtyPointer;
+    }
+
+    ASSERT(mCurPixelSamplerStates.size() == mCurPixelTextures.size());
+    for (unsigned int i = 0; i < mCurPixelSamplerStates.size(); i++)
+    {
+        mCurPixelSamplerStates[i].forceSet = true;
+        mCurPixelTextures[i]               = angle::DirtyPointer;
+    }
+
+    mAppliedIBSerial      = 0;
+    mAppliedVertexShader  = nullptr;
+    mAppliedPixelShader   = nullptr;
+    mAppliedProgramSerial = 0;
+    mStateManager.forceSetDXUniformsState();
+
+    mVertexDeclarationCache.markStateDirty();
+}
+
+void Renderer9::releaseDeviceResources()
+{
+    for (size_t i = 0; i < mEventQueryPool.size(); i++)
+    {
+        SafeRelease(mEventQueryPool[i]);
+    }
+    mEventQueryPool.clear();
+
+    SafeRelease(mMaskedClearSavedState);
+
+    mVertexShaderCache.clear();
+    mPixelShaderCache.clear();
+
+    SafeDelete(mBlit);
+    SafeDelete(mVertexDataManager);
+    SafeDelete(mIndexDataManager);
+    SafeDelete(mLineLoopIB);
+    SafeDelete(mCountingIB);
+
+    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+    {
+        SafeDelete(mNullColorbufferCache[i].buffer);
+    }
+}
+
+// set notify to true to broadcast a message to all contexts of the device loss
+bool Renderer9::testDeviceLost()
+{
+    HRESULT status = getDeviceStatusCode();
+    return FAILED(status);
+}
+
+HRESULT Renderer9::getDeviceStatusCode()
+{
+    HRESULT status = D3D_OK;
+
+    if (mDeviceEx)
+    {
+        status = mDeviceEx->CheckDeviceState(nullptr);
+    }
+    else if (mDevice)
+    {
+        status = mDevice->TestCooperativeLevel();
+    }
+
+    return status;
+}
+
+bool Renderer9::testDeviceResettable()
+{
+    // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted
+    // DEVICEREMOVED indicates the device has been stopped and must be recreated
+    switch (getDeviceStatusCode())
+    {
+        case D3DERR_DEVICENOTRESET:
+        case D3DERR_DEVICEHUNG:
+            return true;
+        case D3DERR_DEVICELOST:
+            return (mDeviceEx != nullptr);
+        case D3DERR_DEVICEREMOVED:
+            ASSERT(mDeviceEx != nullptr);
+            return isRemovedDeviceResettable();
+        default:
+            return false;
+    }
+}
+
+bool Renderer9::resetDevice()
+{
+    releaseDeviceResources();
+
+    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+
+    HRESULT result     = D3D_OK;
+    bool lost          = testDeviceLost();
+    bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
+
+    // Device Removed is a feature which is only present with D3D9Ex
+    ASSERT(mDeviceEx != nullptr || !removedDevice);
+
+    for (int attempts = 3; lost && attempts > 0; attempts--)
+    {
+        if (removedDevice)
+        {
+            // Device removed, which may trigger on driver reinstallation,
+            // may cause a longer wait other reset attempts before the
+            // system is ready to handle creating a new device.
+            Sleep(800);
+            lost = !resetRemovedDevice();
+        }
+        else if (mDeviceEx)
+        {
+            Sleep(500);  // Give the graphics driver some CPU time
+            result = mDeviceEx->ResetEx(&presentParameters, nullptr);
+            lost   = testDeviceLost();
+        }
+        else
+        {
+            result = mDevice->TestCooperativeLevel();
+            while (result == D3DERR_DEVICELOST)
+            {
+                Sleep(100);  // Give the graphics driver some CPU time
+                result = mDevice->TestCooperativeLevel();
+            }
+
+            if (result == D3DERR_DEVICENOTRESET)
+            {
+                result = mDevice->Reset(&presentParameters);
+            }
+            lost = testDeviceLost();
+        }
+    }
+
+    if (FAILED(result))
+    {
+        ERR() << "Reset/ResetEx failed multiple times, " << gl::FmtHR(result);
+        return false;
+    }
+
+    if (removedDevice && lost)
+    {
+        ERR() << "Device lost reset failed multiple times";
+        return false;
+    }
+
+    // If the device was removed, we already finished re-initialization in resetRemovedDevice
+    if (!removedDevice)
+    {
+        // reset device defaults
+        initializeDevice();
+    }
+
+    return true;
+}
+
+bool Renderer9::isRemovedDeviceResettable() const
+{
+    bool success = false;
+
+#if ANGLE_D3D9EX == ANGLE_ENABLED
+    IDirect3D9Ex *d3d9Ex = nullptr;
+    typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
+    Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
+        reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+
+    if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex)))
+    {
+        D3DCAPS9 deviceCaps;
+        HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps);
+        success        = SUCCEEDED(result);
+    }
+
+    SafeRelease(d3d9Ex);
+#else
+    ASSERT(UNREACHABLE());
+#endif
+
+    return success;
+}
+
+bool Renderer9::resetRemovedDevice()
+{
+    // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx:
+    // The hardware adapter has been removed. Application must destroy the device, do enumeration of
+    // adapters and create another Direct3D device. If application continues rendering without
+    // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only.
+    release();
+    return !initialize().isError();
+}
+
+VendorID Renderer9::getVendorId() const
+{
+    return static_cast<VendorID>(mAdapterIdentifier.VendorId);
+}
+
+std::string Renderer9::getRendererDescription() const
+{
+    std::ostringstream rendererString;
+
+    rendererString << mAdapterIdentifier.Description;
+    if (getShareHandleSupport())
+    {
+        rendererString << " Direct3D9Ex";
+    }
+    else
+    {
+        rendererString << " Direct3D9";
+    }
+
+    rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_"
+                   << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
+    rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_"
+                   << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
+
+    return rendererString.str();
+}
+
+DeviceIdentifier Renderer9::getAdapterIdentifier() const
+{
+    DeviceIdentifier deviceIdentifier = {0};
+    deviceIdentifier.VendorId         = static_cast<UINT>(mAdapterIdentifier.VendorId);
+    deviceIdentifier.DeviceId         = static_cast<UINT>(mAdapterIdentifier.DeviceId);
+    deviceIdentifier.SubSysId         = static_cast<UINT>(mAdapterIdentifier.SubSysId);
+    deviceIdentifier.Revision         = static_cast<UINT>(mAdapterIdentifier.Revision);
+    deviceIdentifier.FeatureLevel     = 0;
+
+    return deviceIdentifier;
+}
+
+unsigned int Renderer9::getReservedVertexUniformVectors() const
+{
+    return d3d9_gl::GetReservedVertexUniformVectors();
+}
+
+unsigned int Renderer9::getReservedFragmentUniformVectors() const
+{
+    return d3d9_gl::GetReservedFragmentUniformVectors();
+}
+
+unsigned int Renderer9::getReservedVertexUniformBuffers() const
+{
+    return 0;
+}
+
+unsigned int Renderer9::getReservedFragmentUniformBuffers() const
+{
+    return 0;
+}
+
+bool Renderer9::getShareHandleSupport() const
+{
+    // PIX doesn't seem to support using share handles, so disable them.
+    return (mD3d9Ex != nullptr) && !gl::DebugAnnotationsActive();
+}
+
+int Renderer9::getMajorShaderModel() const
+{
+    return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
+}
+
+int Renderer9::getMinorShaderModel() const
+{
+    return D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
+}
+
+std::string Renderer9::getShaderModelSuffix() const
+{
+    return "";
+}
+
+DWORD Renderer9::getCapsDeclTypes() const
+{
+    return mDeviceCaps.DeclTypes;
+}
+
+D3DPOOL Renderer9::getBufferPool(DWORD usage) const
+{
+    if (mD3d9Ex != nullptr)
+    {
+        return D3DPOOL_DEFAULT;
+    }
+    else
+    {
+        if (!(usage & D3DUSAGE_DYNAMIC))
+        {
+            return D3DPOOL_MANAGED;
+        }
+    }
+
+    return D3DPOOL_DEFAULT;
+}
+
+gl::Error Renderer9::copyImage2D(const gl::Framebuffer *framebuffer,
+                                 const gl::Rectangle &sourceRect,
+                                 GLenum destFormat,
+                                 const gl::Offset &destOffset,
+                                 TextureStorage *storage,
+                                 GLint level)
+{
+    RECT rect;
+    rect.left   = sourceRect.x;
+    rect.top    = sourceRect.y;
+    rect.right  = sourceRect.x + sourceRect.width;
+    rect.bottom = sourceRect.y + sourceRect.height;
+
+    return mBlit->copy2D(framebuffer, rect, destFormat, destOffset, storage, level);
+}
+
+gl::Error Renderer9::copyImageCube(const gl::Framebuffer *framebuffer,
+                                   const gl::Rectangle &sourceRect,
+                                   GLenum destFormat,
+                                   const gl::Offset &destOffset,
+                                   TextureStorage *storage,
+                                   GLenum target,
+                                   GLint level)
+{
+    RECT rect;
+    rect.left   = sourceRect.x;
+    rect.top    = sourceRect.y;
+    rect.right  = sourceRect.x + sourceRect.width;
+    rect.bottom = sourceRect.y + sourceRect.height;
+
+    return mBlit->copyCube(framebuffer, rect, destFormat, destOffset, storage, target, level);
+}
+
+gl::Error Renderer9::copyImage3D(const gl::Framebuffer *framebuffer,
+                                 const gl::Rectangle &sourceRect,
+                                 GLenum destFormat,
+                                 const gl::Offset &destOffset,
+                                 TextureStorage *storage,
+                                 GLint level)
+{
+    // 3D textures are not available in the D3D9 backend.
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::copyImage2DArray(const gl::Framebuffer *framebuffer,
+                                      const gl::Rectangle &sourceRect,
+                                      GLenum destFormat,
+                                      const gl::Offset &destOffset,
+                                      TextureStorage *storage,
+                                      GLint level)
+{
+    // 2D array textures are not available in the D3D9 backend.
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::copyTexture(const gl::Texture *source,
+                                 GLint sourceLevel,
+                                 const gl::Rectangle &sourceRect,
+                                 GLenum destFormat,
+                                 const gl::Offset &destOffset,
+                                 TextureStorage *storage,
+                                 GLenum destTarget,
+                                 GLint destLevel,
+                                 bool unpackFlipY,
+                                 bool unpackPremultiplyAlpha,
+                                 bool unpackUnmultiplyAlpha)
+{
+    ASSERT(destTarget == GL_TEXTURE_2D);
+
+    RECT rect;
+    rect.left   = sourceRect.x;
+    rect.top    = sourceRect.y;
+    rect.right  = sourceRect.x + sourceRect.width;
+    rect.bottom = sourceRect.y + sourceRect.height;
+
+    return mBlit->copyTexture2D(source, sourceLevel, rect, destFormat, destOffset, storage,
+                                destLevel, unpackFlipY, unpackPremultiplyAlpha,
+                                unpackUnmultiplyAlpha);
+}
+
+gl::Error Renderer9::copyCompressedTexture(const gl::Texture *source,
+                                           GLint sourceLevel,
+                                           TextureStorage *storage,
+                                           GLint destLevel)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::createRenderTarget(int width,
+                                        int height,
+                                        GLenum format,
+                                        GLsizei samples,
+                                        RenderTargetD3D **outRT)
+{
+    const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);
+
+    const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
+    GLuint supportedSamples            = textureCaps.getNearestSamples(samples);
+
+    IDirect3DTexture9 *texture      = nullptr;
+    IDirect3DSurface9 *renderTarget = nullptr;
+    if (width > 0 && height > 0)
+    {
+        bool requiresInitialization = false;
+        HRESULT result              = D3DERR_INVALIDCALL;
+
+        const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
+        if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+        {
+            result = mDevice->CreateDepthStencilSurface(
+                width, height, d3d9FormatInfo.renderFormat,
+                gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &renderTarget, nullptr);
+        }
+        else
+        {
+            requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != nullptr);
+            if (supportedSamples > 0)
+            {
+                result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat,
+                                                     gl_d3d9::GetMultisampleType(supportedSamples),
+                                                     0, FALSE, &renderTarget, nullptr);
+            }
+            else
+            {
+                result = mDevice->CreateTexture(
+                    width, height, 1, D3DUSAGE_RENDERTARGET, d3d9FormatInfo.texFormat,
+                    getTexturePool(D3DUSAGE_RENDERTARGET), &texture, nullptr);
+                if (!FAILED(result))
+                {
+                    result = texture->GetSurfaceLevel(0, &renderTarget);
+                }
+            }
+        }
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.",
+                             result);
+        }
+
+        if (requiresInitialization)
+        {
+            // This format requires that the data be initialized before the render target can be
+            // used Unfortunately this requires a Get call on the d3d device but it is far better
+            // than having to mark the render target as lockable and copy data to the gpu.
+            IDirect3DSurface9 *prevRenderTarget = nullptr;
+            mDevice->GetRenderTarget(0, &prevRenderTarget);
+            mDevice->SetRenderTarget(0, renderTarget);
+            mDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
+            mDevice->SetRenderTarget(0, prevRenderTarget);
+        }
+    }
+
+    *outRT = new TextureRenderTarget9(texture, 0, renderTarget, format, width, height, 1,
+                                      supportedSamples);
+    return gl::NoError();
+}
+
+gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT)
+{
+    ASSERT(source != nullptr);
+
+    RenderTargetD3D *newRT = nullptr;
+    gl::Error error        = createRenderTarget(source->getWidth(), source->getHeight(),
+                                         source->getInternalFormat(), source->getSamples(), &newRT);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    RenderTarget9 *source9 = GetAs<RenderTarget9>(source);
+    RenderTarget9 *dest9   = GetAs<RenderTarget9>(newRT);
+
+    HRESULT result = mDevice->StretchRect(source9->getSurface(), nullptr, dest9->getSurface(),
+                                          nullptr, D3DTEXF_NONE);
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy render target, result: 0x%X.", result);
+    }
+
+    *outRT = newRT;
+    return gl::NoError();
+}
+
+gl::Error Renderer9::loadExecutable(const void *function,
+                                    size_t length,
+                                    ShaderType type,
+                                    const std::vector<D3DVarying> &streamOutVaryings,
+                                    bool separatedOutputBuffers,
+                                    ShaderExecutableD3D **outExecutable)
+{
+    // Transform feedback is not supported in ES2 or D3D9
+    ASSERT(streamOutVaryings.empty());
+
+    switch (type)
+    {
+        case SHADER_VERTEX:
+        {
+            IDirect3DVertexShader9 *vshader = nullptr;
+            gl::Error error = createVertexShader((DWORD *)function, length, &vshader);
+            if (error.isError())
+            {
+                return error;
+            }
+            *outExecutable = new ShaderExecutable9(function, length, vshader);
+        }
+        break;
+        case SHADER_PIXEL:
+        {
+            IDirect3DPixelShader9 *pshader = nullptr;
+            gl::Error error                = createPixelShader((DWORD *)function, length, &pshader);
+            if (error.isError())
+            {
+                return error;
+            }
+            *outExecutable = new ShaderExecutable9(function, length, pshader);
+        }
+        break;
+        default:
+            UNREACHABLE();
+            return gl::Error(GL_INVALID_OPERATION);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
+                                         const std::string &shaderHLSL,
+                                         ShaderType type,
+                                         const std::vector<D3DVarying> &streamOutVaryings,
+                                         bool separatedOutputBuffers,
+                                         const angle::CompilerWorkaroundsD3D &workarounds,
+                                         ShaderExecutableD3D **outExectuable)
+{
+    // Transform feedback is not supported in ES2 or D3D9
+    ASSERT(streamOutVaryings.empty());
+
+    std::stringstream profileStream;
+
+    switch (type)
+    {
+        case SHADER_VERTEX:
+            profileStream << "vs";
+            break;
+        case SHADER_PIXEL:
+            profileStream << "ps";
+            break;
+        default:
+            UNREACHABLE();
+            return gl::Error(GL_INVALID_OPERATION);
+    }
+
+    profileStream << "_" << ((getMajorShaderModel() >= 3) ? 3 : 2);
+    profileStream << "_"
+                  << "0";
+
+    std::string profile = profileStream.str();
+
+    UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
+
+    if (workarounds.skipOptimization)
+    {
+        flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+    }
+    else if (workarounds.useMaxOptimization)
+    {
+        flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
+    }
+
+    if (gl::DebugAnnotationsActive())
+    {
+#ifndef NDEBUG
+        flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
+
+        flags |= D3DCOMPILE_DEBUG;
+    }
+
+    // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
+    // when it would otherwise pass with alternative options. Try the default flags first and if
+    // compilation fails, try some alternatives.
+    std::vector<CompileConfig> configs;
+    configs.push_back(CompileConfig(flags, "default"));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control"));
+
+    ID3DBlob *binary = nullptr;
+    std::string debugInfo;
+    gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, nullptr,
+                                                &binary, &debugInfo);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    // It's possible that binary is NULL if the compiler failed in all configurations.  Set the
+    // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
+    // internal state is still OK.
+    if (!binary)
+    {
+        *outExectuable = nullptr;
+        return gl::NoError();
+    }
+
+    error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
+                           streamOutVaryings, separatedOutputBuffers, outExectuable);
+
+    SafeRelease(binary);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!debugInfo.empty())
+    {
+        (*outExectuable)->appendDebugInfo(debugInfo);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer9::ensureHLSLCompilerInitialized()
+{
+    return mCompiler.ensureInitialized();
+}
+
+UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize)
+{
+    return new UniformStorageD3D(storageSize);
+}
+
+gl::Error Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+{
+    return mBlit->boxFilter(source, dest);
+}
+
+D3DPOOL Renderer9::getTexturePool(DWORD usage) const
+{
+    if (mD3d9Ex != nullptr)
+    {
+        return D3DPOOL_DEFAULT;
+    }
+    else
+    {
+        if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
+        {
+            return D3DPOOL_MANAGED;
+        }
+    }
+
+    return D3DPOOL_DEFAULT;
+}
+
+gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest,
+                                        IDirect3DSurface9 *source,
+                                        bool fromManaged)
+{
+    ASSERT(source && dest);
+
+    HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
+
+    if (fromManaged)
+    {
+        D3DSURFACE_DESC desc;
+        source->GetDesc(&desc);
+
+        IDirect3DSurface9 *surf = 0;
+        result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+                                                      D3DPOOL_SYSTEMMEM, &surf, nullptr);
+
+        if (SUCCEEDED(result))
+        {
+            Image9::copyLockableSurfaces(surf, source);
+            result = mDevice->UpdateSurface(surf, nullptr, dest, nullptr);
+            SafeRelease(surf);
+        }
+    }
+    else
+    {
+        endScene();
+        result = mDevice->StretchRect(source, nullptr, dest, nullptr, D3DTEXF_NONE);
+    }
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit internal texture, result: 0x%X.",
+                         result);
+    }
+
+    return gl::NoError();
+}
+
+ImageD3D *Renderer9::createImage()
+{
+    return new Image9(this);
+}
+
+gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src)
+{
+    Image9 *src9 = GetAs<Image9>(src);
+    Image9 *dst9 = GetAs<Image9>(dest);
+    return Image9::generateMipmap(dst9, src9);
+}
+
+gl::Error Renderer9::generateMipmapUsingD3D(TextureStorage *storage,
+                                            const gl::TextureState &textureState)
+{
+    UNREACHABLE();
+    return gl::NoError();
+}
+
+TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain)
+{
+    SwapChain9 *swapChain9 = GetAs<SwapChain9>(swapChain);
+    return new TextureStorage9_2D(this, swapChain9);
+}
+
+TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage,
+                                                        RenderTargetD3D *renderTargetD3D)
+{
+    return new TextureStorage9_EGLImage(this, eglImage, GetAs<RenderTarget9>(renderTargetD3D));
+}
+
+TextureStorage *Renderer9::createTextureStorageExternal(
+    egl::Stream *stream,
+    const egl::Stream::GLTextureDescription &desc)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat,
+                                                  bool renderTarget,
+                                                  GLsizei width,
+                                                  GLsizei height,
+                                                  int levels,
+                                                  bool hintLevelZeroOnly)
+{
+    return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels);
+}
+
+TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat,
+                                                    bool renderTarget,
+                                                    int size,
+                                                    int levels,
+                                                    bool hintLevelZeroOnly)
+{
+    return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels,
+                                    hintLevelZeroOnly);
+}
+
+TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat,
+                                                  bool renderTarget,
+                                                  GLsizei width,
+                                                  GLsizei height,
+                                                  GLsizei depth,
+                                                  int levels)
+{
+    // 3D textures are not supported by the D3D9 backend.
+    UNREACHABLE();
+
+    return nullptr;
+}
+
+TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat,
+                                                       bool renderTarget,
+                                                       GLsizei width,
+                                                       GLsizei height,
+                                                       GLsizei depth,
+                                                       int levels)
+{
+    // 2D array textures are not supported by the D3D9 backend.
+    UNREACHABLE();
+
+    return nullptr;
+}
+
+bool Renderer9::getLUID(LUID *adapterLuid) const
+{
+    adapterLuid->HighPart = 0;
+    adapterLuid->LowPart  = 0;
+
+    if (mD3d9Ex)
+    {
+        mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
+        return true;
+    }
+
+    return false;
+}
+
+VertexConversionType Renderer9::getVertexConversionType(gl::VertexFormatType vertexFormatType) const
+{
+    return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).conversionType;
+}
+
+GLenum Renderer9::getVertexComponentType(gl::VertexFormatType vertexFormatType) const
+{
+    return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).componentType;
+}
+
+gl::ErrorOrResult<unsigned int> Renderer9::getVertexSpaceRequired(const gl::VertexAttribute &attrib,
+                                                                  const gl::VertexBinding &binding,
+                                                                  GLsizei count,
+                                                                  GLsizei instances) const
+{
+    if (!attrib.enabled)
+    {
+        return 16u;
+    }
+
+    gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, GL_FLOAT);
+    const d3d9::VertexFormat &d3d9VertexInfo =
+        d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType);
+
+    unsigned int elementCount = 0;
+    if (instances == 0 || binding.divisor == 0)
+    {
+        elementCount = static_cast<unsigned int>(count);
+    }
+    else
+    {
+        // Round up to divisor, if possible
+        elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), binding.divisor);
+    }
+
+    if (d3d9VertexInfo.outputElementSize > std::numeric_limits<unsigned int>::max() / elementCount)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
+    }
+
+    return static_cast<unsigned int>(d3d9VertexInfo.outputElementSize) * elementCount;
+}
+
+void Renderer9::generateCaps(gl::Caps *outCaps,
+                             gl::TextureCapsMap *outTextureCaps,
+                             gl::Extensions *outExtensions,
+                             gl::Limitations *outLimitations) const
+{
+    d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps,
+                          outExtensions, outLimitations);
+}
+
+angle::WorkaroundsD3D Renderer9::generateWorkarounds() const
+{
+    return d3d9::GenerateWorkarounds();
+}
+
+gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
+{
+    // TODO(jmadill): faster way?
+    for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; samplerIndex++)
+    {
+        gl::Error error = setTexture(samplerType, static_cast<int>(samplerIndex), nullptr);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    return gl::NoError();
+}
+
+egl::Error Renderer9::getEGLDevice(DeviceImpl **device)
+{
+    if (mEGLDevice == nullptr)
+    {
+        ASSERT(mDevice != nullptr);
+        mEGLDevice       = new DeviceD3D();
+        egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
+                                                  EGL_D3D9_DEVICE_ANGLE, EGL_FALSE);
+
+        if (error.isError())
+        {
+            SafeDelete(mEGLDevice);
+            return error;
+        }
+    }
+
+    *device = static_cast<DeviceImpl *>(mEGLDevice);
+    return egl::Error(EGL_SUCCESS);
+}
+
+Renderer9::CurSamplerState::CurSamplerState()
+    : forceSet(true), baseLevel(std::numeric_limits<size_t>::max()), samplerState()
+{
+}
+
+gl::Error Renderer9::genericDrawElements(Context9 *context,
+                                         GLenum mode,
+                                         GLsizei count,
+                                         GLenum type,
+                                         const void *indices,
+                                         GLsizei instances,
+                                         const gl::IndexRange &indexRange)
+{
+    const auto &data     = context->getContextState();
+    gl::Program *program = context->getGLState().getProgram();
+    ASSERT(program != nullptr);
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+    bool usesPointSize     = programD3D->usesPointSize();
+
+    programD3D->updateSamplerMapping();
+
+    if (!applyPrimitiveType(mode, count, usesPointSize))
+    {
+        return gl::NoError();
+    }
+
+    ANGLE_TRY(updateState(context, mode));
+
+    TranslatedIndexData indexInfo;
+    indexInfo.indexRange = indexRange;
+
+    ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo));
+
+    applyTransformFeedbackBuffers(data.getState());
+    // Transform feedback is not allowed for DrawElements, this error should have been caught at the
+    // API validation
+    // layer.
+    ASSERT(!data.getState().isTransformFeedbackActiveUnpaused());
+
+    size_t vertexCount = indexInfo.indexRange.vertexCount();
+    ANGLE_TRY(applyVertexBuffer(data.getState(), mode,
+                                static_cast<GLsizei>(indexInfo.indexRange.start),
+                                static_cast<GLsizei>(vertexCount), instances, &indexInfo));
+    ANGLE_TRY(applyTextures(context, data));
+    ANGLE_TRY(applyShaders(data, mode));
+    ANGLE_TRY(programD3D->applyUniformBuffers(data));
+
+    if (!skipDraw(data, mode))
+    {
+        ANGLE_TRY(drawElementsImpl(data, indexInfo, mode, count, type, indices, instances));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error Renderer9::genericDrawArrays(Context9 *context,
+                                       GLenum mode,
+                                       GLint first,
+                                       GLsizei count,
+                                       GLsizei instances)
+{
+    const auto &data     = context->getContextState();
+    gl::Program *program = context->getGLState().getProgram();
+    ASSERT(program != nullptr);
+    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+    bool usesPointSize     = programD3D->usesPointSize();
+
+    programD3D->updateSamplerMapping();
+
+    if (!applyPrimitiveType(mode, count, usesPointSize))
+    {
+        return gl::NoError();
+    }
+
+    ANGLE_TRY(updateState(context, mode));
+    ANGLE_TRY(applyTransformFeedbackBuffers(data.getState()));
+    ANGLE_TRY(applyVertexBuffer(data.getState(), mode, first, count, instances, nullptr));
+    ANGLE_TRY(applyTextures(context, data));
+    ANGLE_TRY(applyShaders(data, mode));
+    ANGLE_TRY(programD3D->applyUniformBuffers(data));
+
+    if (!skipDraw(data, mode))
+    {
+        ANGLE_TRY(drawArraysImpl(data, mode, first, count, instances));
+
+        if (data.getState().isTransformFeedbackActiveUnpaused())
+        {
+            ANGLE_TRY(markTransformFeedbackUsage(data));
+        }
+    }
+
+    return gl::NoError();
+}
+
+FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+    return new Framebuffer9(state, this);
+}
+
+gl::Version Renderer9::getMaxSupportedESVersion() const
+{
+    return gl::Version(2, 0);
+}
+
+gl::Error Renderer9::applyComputeUniforms(const ProgramD3D &programD3D,
+                                          const std::vector<D3DUniform *> &uniformArray)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError() << "Compute shader is not implemented on D3D9";
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
new file mode 100644
index 0000000..ce7fb71
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -0,0 +1,523 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// Renderer9.h: Defines a back-end specific class for the D3D9 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
+#include "libANGLE/renderer/d3d/d3d9/ShaderCache.h"
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
+#include "libANGLE/renderer/driver_utils.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace egl
+{
+class AttributeMap;
+}
+
+namespace rx
+{
+class Blit9;
+class Context9;
+class IndexDataManager;
+class ProgramD3D;
+class StreamingIndexBufferInterface;
+class StaticIndexBufferInterface;
+class VertexDataManager;
+struct ClearParameters;
+struct D3DUniform;
+struct TranslatedAttribute;
+
+enum D3D9InitError
+{
+    D3D9_INIT_SUCCESS = 0,
+    // Failed to load the D3D or ANGLE compiler
+    D3D9_INIT_COMPILER_ERROR,
+    // Failed to load a necessary DLL
+    D3D9_INIT_MISSING_DEP,
+    // Device creation error
+    D3D9_INIT_CREATE_DEVICE_ERROR,
+    // System does not meet minimum shader spec
+    D3D9_INIT_UNSUPPORTED_VERSION,
+    // System does not support stretchrect from textures
+    D3D9_INIT_UNSUPPORTED_STRETCHRECT,
+    // A call returned out of memory or device lost
+    D3D9_INIT_OUT_OF_MEMORY,
+    // Other unspecified error
+    D3D9_INIT_OTHER_ERROR,
+    NUM_D3D9_INIT_ERRORS
+};
+
+class Renderer9 : public RendererD3D
+{
+  public:
+    explicit Renderer9(egl::Display *display);
+    virtual ~Renderer9();
+
+    egl::Error initialize() override;
+    bool resetDevice() override;
+
+    egl::ConfigSet generateConfigs() override;
+    void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override;
+
+    void startScene();
+    void endScene();
+
+    gl::Error flush();
+    gl::Error finish();
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+    NativeWindowD3D *createNativeWindow(EGLNativeWindowType window,
+                                        const egl::Config *config,
+                                        const egl::AttributeMap &attribs) const override;
+
+    SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
+                                  HANDLE shareHandle,
+                                  IUnknown *d3dTexture,
+                                  GLenum backBufferFormat,
+                                  GLenum depthBufferFormat,
+                                  EGLint orientation,
+                                  EGLint samples) override;
+    egl::Error getD3DTextureInfo(const egl::Config *configuration,
+                                 IUnknown *d3dTexture,
+                                 EGLint *width,
+                                 EGLint *height,
+                                 GLenum *fboFormat) const override;
+    egl::Error validateShareHandle(const egl::Config *config,
+                                   HANDLE shareHandle,
+                                   const egl::AttributeMap &attribs) const override;
+
+    ContextImpl *createContext(const gl::ContextState &state) override;
+
+    gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery);
+    void freeEventQuery(IDirect3DQuery9 *query);
+
+    // resource creation
+    gl::Error createVertexShader(const DWORD *function,
+                                 size_t length,
+                                 IDirect3DVertexShader9 **outShader);
+    gl::Error createPixelShader(const DWORD *function,
+                                size_t length,
+                                IDirect3DPixelShader9 **outShader);
+    HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
+    HRESULT createIndexBuffer(UINT Length,
+                              DWORD Usage,
+                              D3DFORMAT Format,
+                              IDirect3DIndexBuffer9 **ppIndexBuffer);
+    gl::Error setSamplerState(gl::SamplerType type,
+                              int index,
+                              gl::Texture *texture,
+                              const gl::SamplerState &sampler) override;
+    gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) override;
+
+    gl::Error setUniformBuffers(const gl::ContextState &data,
+                                const std::vector<GLint> &vertexUniformBuffers,
+                                const std::vector<GLint> &fragmentUniformBuffers) override;
+
+    gl::Error updateState(Context9 *context, GLenum drawMode);
+
+    void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+    void setViewport(const gl::Rectangle &viewport,
+                     float zNear,
+                     float zFar,
+                     GLenum drawMode,
+                     GLenum frontFace,
+                     bool ignoreViewport);
+
+    gl::Error applyRenderTarget(GLImplFactory *implFactory, const gl::Framebuffer *frameBuffer);
+    gl::Error applyRenderTarget(GLImplFactory *implFactory,
+                                const gl::FramebufferAttachment *colorAttachment,
+                                const gl::FramebufferAttachment *depthStencilAttachment);
+    gl::Error applyUniforms(const ProgramD3D &programD3D,
+                            GLenum drawMode,
+                            const std::vector<D3DUniform *> &uniformArray) override;
+    bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
+    gl::Error applyVertexBuffer(const gl::State &state,
+                                GLenum mode,
+                                GLint first,
+                                GLsizei count,
+                                GLsizei instances,
+                                TranslatedIndexData *indexInfo);
+    gl::Error applyIndexBuffer(const gl::ContextState &data,
+                               const void *indices,
+                               GLsizei count,
+                               GLenum mode,
+                               GLenum type,
+                               TranslatedIndexData *indexInfo);
+
+    gl::Error applyTransformFeedbackBuffers(const gl::State &state);
+
+    gl::Error clear(const ClearParameters &clearParams,
+                    const gl::FramebufferAttachment *colorBuffer,
+                    const gl::FramebufferAttachment *depthStencilBuffer);
+
+    void markAllStateDirty();
+
+    // lost device
+    bool testDeviceLost() override;
+    bool testDeviceResettable();
+
+    VendorID getVendorId() const;
+    std::string getRendererDescription() const;
+    DeviceIdentifier getAdapterIdentifier() const override;
+
+    IDirect3DDevice9 *getDevice() { return mDevice; }
+    void *getD3DDevice() override;
+
+    unsigned int getReservedVertexUniformVectors() const;
+    unsigned int getReservedFragmentUniformVectors() const;
+    unsigned int getReservedVertexUniformBuffers() const override;
+    unsigned int getReservedFragmentUniformBuffers() const override;
+
+    bool getShareHandleSupport() const;
+
+    int getMajorShaderModel() const override;
+    int getMinorShaderModel() const override;
+    std::string getShaderModelSuffix() const override;
+
+    DWORD getCapsDeclTypes() const;
+
+    // Pixel operations
+    gl::Error copyImage2D(const gl::Framebuffer *framebuffer,
+                          const gl::Rectangle &sourceRect,
+                          GLenum destFormat,
+                          const gl::Offset &destOffset,
+                          TextureStorage *storage,
+                          GLint level) override;
+    gl::Error copyImageCube(const gl::Framebuffer *framebuffer,
+                            const gl::Rectangle &sourceRect,
+                            GLenum destFormat,
+                            const gl::Offset &destOffset,
+                            TextureStorage *storage,
+                            GLenum target,
+                            GLint level) override;
+    gl::Error copyImage3D(const gl::Framebuffer *framebuffer,
+                          const gl::Rectangle &sourceRect,
+                          GLenum destFormat,
+                          const gl::Offset &destOffset,
+                          TextureStorage *storage,
+                          GLint level) override;
+    gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer,
+                               const gl::Rectangle &sourceRect,
+                               GLenum destFormat,
+                               const gl::Offset &destOffset,
+                               TextureStorage *storage,
+                               GLint level) override;
+
+    gl::Error copyTexture(const gl::Texture *source,
+                          GLint sourceLevel,
+                          const gl::Rectangle &sourceRect,
+                          GLenum destFormat,
+                          const gl::Offset &destOffset,
+                          TextureStorage *storage,
+                          GLenum destTarget,
+                          GLint destLevel,
+                          bool unpackFlipY,
+                          bool unpackPremultiplyAlpha,
+                          bool unpackUnmultiplyAlpha) override;
+    gl::Error copyCompressedTexture(const gl::Texture *source,
+                                    GLint sourceLevel,
+                                    TextureStorage *storage,
+                                    GLint destLevel) override;
+
+    // RenderTarget creation
+    gl::Error createRenderTarget(int width,
+                                 int height,
+                                 GLenum format,
+                                 GLsizei samples,
+                                 RenderTargetD3D **outRT) override;
+    gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override;
+
+    // Shader operations
+    gl::Error loadExecutable(const void *function,
+                             size_t length,
+                             ShaderType type,
+                             const std::vector<D3DVarying> &streamOutVaryings,
+                             bool separatedOutputBuffers,
+                             ShaderExecutableD3D **outExecutable) override;
+    gl::Error compileToExecutable(gl::InfoLog &infoLog,
+                                  const std::string &shaderHLSL,
+                                  ShaderType type,
+                                  const std::vector<D3DVarying> &streamOutVaryings,
+                                  bool separatedOutputBuffers,
+                                  const angle::CompilerWorkaroundsD3D &workarounds,
+                                  ShaderExecutableD3D **outExectuable) override;
+    gl::Error ensureHLSLCompilerInitialized() override;
+
+    UniformStorageD3D *createUniformStorage(size_t storageSize) override;
+
+    // Image operations
+    ImageD3D *createImage() override;
+    gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
+    gl::Error generateMipmapUsingD3D(TextureStorage *storage,
+                                     const gl::TextureState &textureState) override;
+    TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) override;
+    TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+                                                 RenderTargetD3D *renderTargetD3D) override;
+    TextureStorage *createTextureStorageExternal(
+        egl::Stream *stream,
+        const egl::Stream::GLTextureDescription &desc) override;
+    TextureStorage *createTextureStorage2D(GLenum internalformat,
+                                           bool renderTarget,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           int levels,
+                                           bool hintLevelZeroOnly) override;
+    TextureStorage *createTextureStorageCube(GLenum internalformat,
+                                             bool renderTarget,
+                                             int size,
+                                             int levels,
+                                             bool hintLevelZeroOnly) override;
+    TextureStorage *createTextureStorage3D(GLenum internalformat,
+                                           bool renderTarget,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLsizei depth,
+                                           int levels) override;
+    TextureStorage *createTextureStorage2DArray(GLenum internalformat,
+                                                bool renderTarget,
+                                                GLsizei width,
+                                                GLsizei height,
+                                                GLsizei depth,
+                                                int levels) override;
+
+    // Buffer creation
+    VertexBuffer *createVertexBuffer() override;
+    IndexBuffer *createIndexBuffer() override;
+
+    // Stream Creation
+    StreamProducerImpl *createStreamProducerD3DTextureNV12(
+        egl::Stream::ConsumerType consumerType,
+        const egl::AttributeMap &attribs) override;
+
+    // Buffer-to-texture and Texture-to-buffer copies
+    bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
+    gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack,
+                                      unsigned int offset,
+                                      RenderTargetD3D *destRenderTarget,
+                                      GLenum destinationFormat,
+                                      GLenum sourcePixelsType,
+                                      const gl::Box &destArea) override;
+
+    // D3D9-renderer specific methods
+    gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+    D3DPOOL getTexturePool(DWORD usage) const;
+
+    bool getLUID(LUID *adapterLuid) const override;
+    VertexConversionType getVertexConversionType(
+        gl::VertexFormatType vertexFormatType) const override;
+    GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override;
+
+    // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+    // function.
+    gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib,
+                                                           const gl::VertexBinding &binding,
+                                                           GLsizei count,
+                                                           GLsizei instances) const override;
+
+    gl::Error copyToRenderTarget(IDirect3DSurface9 *dest,
+                                 IDirect3DSurface9 *source,
+                                 bool fromManaged);
+
+    RendererClass getRendererClass() const override { return RENDERER_D3D9; }
+
+    D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; }
+
+    egl::Error getEGLDevice(DeviceImpl **device) override;
+
+    StateManager9 *getStateManager() { return &mStateManager; }
+
+    gl::Error genericDrawArrays(Context9 *context,
+                                GLenum mode,
+                                GLint first,
+                                GLsizei count,
+                                GLsizei instances);
+
+    gl::Error genericDrawElements(Context9 *context,
+                                  GLenum mode,
+                                  GLsizei count,
+                                  GLenum type,
+                                  const void *indices,
+                                  GLsizei instances,
+                                  const gl::IndexRange &indexRange);
+
+    // Necessary hack for default framebuffers in D3D.
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+    DebugAnnotator9 *getAnnotator() { return &mAnnotator; }
+
+    gl::Version getMaxSupportedESVersion() const override;
+
+    gl::Error applyComputeUniforms(const ProgramD3D &programD3D,
+                                   const std::vector<D3DUniform *> &uniformArray) override;
+
+  protected:
+    gl::Error clearTextures(gl::SamplerType samplerType,
+                            size_t rangeStart,
+                            size_t rangeEnd) override;
+
+  private:
+    gl::Error drawArraysImpl(const gl::ContextState &data,
+                             GLenum mode,
+                             GLint startVertex,
+                             GLsizei count,
+                             GLsizei instances);
+    gl::Error drawElementsImpl(const gl::ContextState &data,
+                               const TranslatedIndexData &indexInfo,
+                               GLenum mode,
+                               GLsizei count,
+                               GLenum type,
+                               const void *indices,
+                               GLsizei instances);
+
+    gl::Error applyShaders(const gl::ContextState &data, GLenum drawMode);
+
+    void generateCaps(gl::Caps *outCaps,
+                      gl::TextureCapsMap *outTextureCaps,
+                      gl::Extensions *outExtensions,
+                      gl::Limitations *outLimitations) const override;
+
+    angle::WorkaroundsD3D generateWorkarounds() const override;
+
+    gl::Error setBlendDepthRasterStates(const gl::ContextState &glData, GLenum drawMode);
+
+    void release();
+
+    void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v);
+    void applyUniformniv(const D3DUniform *targetUniform, const GLint *v);
+    void applyUniformnbv(const D3DUniform *targetUniform, const GLint *v);
+
+    gl::Error drawLineLoop(GLsizei count,
+                           GLenum type,
+                           const void *indices,
+                           int minIndex,
+                           gl::Buffer *elementArrayBuffer);
+    gl::Error drawIndexedPoints(GLsizei count,
+                                GLenum type,
+                                const void *indices,
+                                int minIndex,
+                                gl::Buffer *elementArrayBuffer);
+
+    gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB);
+
+    gl::Error getNullColorbuffer(GLImplFactory *implFactory,
+                                 const gl::FramebufferAttachment *depthbuffer,
+                                 const gl::FramebufferAttachment **outColorBuffer);
+
+    D3DPOOL getBufferPool(DWORD usage) const;
+
+    HMODULE mD3d9Module;
+
+    void initializeDevice();
+    D3DPRESENT_PARAMETERS getDefaultPresentParameters();
+    void releaseDeviceResources();
+
+    HRESULT getDeviceStatusCode();
+    bool isRemovedDeviceResettable() const;
+    bool resetRemovedDevice();
+
+    UINT mAdapter;
+    D3DDEVTYPE mDeviceType;
+    IDirect3D9 *mD3d9;      // Always valid after successful initialization.
+    IDirect3D9Ex *mD3d9Ex;  // Might be null if D3D9Ex is not supported.
+    IDirect3DDevice9 *mDevice;
+    IDirect3DDevice9Ex *mDeviceEx;  // Might be null if D3D9Ex is not supported.
+
+    HLSLCompiler mCompiler;
+
+    Blit9 *mBlit;
+
+    HWND mDeviceWindow;
+
+    D3DCAPS9 mDeviceCaps;
+    D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
+
+    D3DPRIMITIVETYPE mPrimitiveType;
+    int mPrimitiveCount;
+    GLsizei mRepeatDraw;
+
+    bool mSceneStarted;
+
+    bool mVertexTextureSupport;
+
+    // current render target states
+    unsigned int mAppliedRenderTargetSerial;
+    unsigned int mAppliedDepthStencilSerial;
+    bool mDepthStencilInitialized;
+    bool mRenderTargetDescInitialized;
+
+    IDirect3DStateBlock9 *mMaskedClearSavedState;
+
+    StateManager9 mStateManager;
+
+    // Currently applied sampler states
+    struct CurSamplerState
+    {
+        CurSamplerState();
+
+        bool forceSet;
+        size_t baseLevel;
+        gl::SamplerState samplerState;
+    };
+    std::vector<CurSamplerState> mCurVertexSamplerStates;
+    std::vector<CurSamplerState> mCurPixelSamplerStates;
+
+    // Currently applied textures
+    std::vector<uintptr_t> mCurVertexTextures;
+    std::vector<uintptr_t> mCurPixelTextures;
+
+    unsigned int mAppliedIBSerial;
+    IDirect3DVertexShader9 *mAppliedVertexShader;
+    IDirect3DPixelShader9 *mAppliedPixelShader;
+    unsigned int mAppliedProgramSerial;
+
+    // A pool of event queries that are currently unused.
+    std::vector<IDirect3DQuery9 *> mEventQueryPool;
+    VertexShaderCache mVertexShaderCache;
+    PixelShaderCache mPixelShaderCache;
+
+    VertexDataManager *mVertexDataManager;
+    VertexDeclarationCache mVertexDeclarationCache;
+
+    IndexDataManager *mIndexDataManager;
+    StreamingIndexBufferInterface *mLineLoopIB;
+    StaticIndexBufferInterface *mCountingIB;
+
+    enum
+    {
+        NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12
+    };
+    struct NullColorbufferCacheEntry
+    {
+        UINT lruCount;
+        int width;
+        int height;
+        gl::FramebufferAttachment *buffer;
+    } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES];
+    UINT mMaxNullColorbufferLRU;
+
+    DeviceD3D *mEGLDevice;
+    std::vector<TranslatedAttribute> mTranslatedAttribCache;
+
+    DebugAnnotator9 mAnnotator;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
new file mode 100644
index 0000000..079e5f0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
@@ -0,0 +1,106 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects
+// keyed by their byte code.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/debug.h"
+
+#include <cstddef>
+#include <unordered_map>
+#include <string>
+
+namespace rx
+{
+template <typename ShaderObject>
+class ShaderCache : angle::NonCopyable
+{
+  public:
+    ShaderCache() : mDevice(nullptr) {}
+
+    ~ShaderCache()
+    {
+        // Call clear while the device is still valid.
+        ASSERT(mMap.empty());
+    }
+
+    void initialize(IDirect3DDevice9* device)
+    {
+        mDevice = device;
+    }
+
+    gl::Error create(const DWORD *function, size_t length, ShaderObject **outShaderObject)
+    {
+        std::string key(reinterpret_cast<const char*>(function), length);
+        typename Map::iterator it = mMap.find(key);
+        if (it != mMap.end())
+        {
+            it->second->AddRef();
+            *outShaderObject = it->second;
+            return gl::NoError();
+        }
+
+        ShaderObject *shader;
+        HRESULT result = createShader(function, &shader);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result);
+        }
+
+        // Random eviction policy.
+        if (mMap.size() >= kMaxMapSize)
+        {
+            SafeRelease(mMap.begin()->second);
+            mMap.erase(mMap.begin());
+        }
+
+        shader->AddRef();
+        mMap[key] = shader;
+
+        *outShaderObject = shader;
+        return gl::NoError();
+    }
+
+    void clear()
+    {
+        for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it)
+        {
+            SafeRelease(it->second);
+        }
+
+        mMap.clear();
+    }
+
+  private:
+    const static size_t kMaxMapSize = 100;
+
+    HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader)
+    {
+        return mDevice->CreateVertexShader(function, shader);
+    }
+
+    HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader)
+    {
+        return mDevice->CreatePixelShader(function, shader);
+    }
+
+    typedef std::unordered_map<std::string, ShaderObject*> Map;
+    Map mMap;
+
+    IDirect3DDevice9 *mDevice;
+};
+
+typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache;
+typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache;
+
+}
+
+#endif   // LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
new file mode 100644
index 0000000..362c6c6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader
+// executable implementation details.
+
+#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable)
+    : ShaderExecutableD3D(function, length)
+{
+    mPixelExecutable = executable;
+    mVertexExecutable = nullptr;
+}
+
+ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable)
+    : ShaderExecutableD3D(function, length)
+{
+    mVertexExecutable = executable;
+    mPixelExecutable  = nullptr;
+}
+
+ShaderExecutable9::~ShaderExecutable9()
+{
+    SafeRelease(mVertexExecutable);
+    SafeRelease(mPixelExecutable);
+}
+
+IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const
+{
+    return mVertexExecutable;
+}
+
+IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const
+{
+    return mPixelExecutable;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
new file mode 100644
index 0000000..382a68c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader
+// executable implementation details.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
+
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+
+namespace rx
+{
+
+class ShaderExecutable9 : public ShaderExecutableD3D
+{
+  public:
+    ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable);
+    ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable);
+    virtual ~ShaderExecutable9();
+
+    IDirect3DPixelShader9 *getPixelShader() const;
+    IDirect3DVertexShader9 *getVertexShader() const;
+
+  private:
+    IDirect3DPixelShader9 *mPixelExecutable;
+    IDirect3DVertexShader9 *mVertexExecutable;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
new file mode 100644
index 0000000..829fc41
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
@@ -0,0 +1,945 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager9.cpp: Defines a class for caching D3D9 state
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
+
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+StateManager9::StateManager9(Renderer9 *renderer9)
+    : mUsingZeroColorMaskWorkaround(false),
+      mCurBlendState(),
+      mCurBlendColor(0, 0, 0, 0),
+      mCurSampleMask(0),
+      mCurRasterState(),
+      mCurDepthSize(0),
+      mCurDepthStencilState(),
+      mCurStencilRef(0),
+      mCurStencilBackRef(0),
+      mCurFrontFaceCCW(0),
+      mCurStencilSize(0),
+      mCurScissorRect(),
+      mCurScissorEnabled(false),
+      mCurViewport(),
+      mCurNear(0.0f),
+      mCurFar(0.0f),
+      mCurDepthFront(0.0f),
+      mCurIgnoreViewport(false),
+      mRenderer9(renderer9),
+      mDirtyBits()
+{
+    mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+    mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+    mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+    mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE);
+    mBlendStateDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+    mBlendStateDirtyBits.set(DIRTY_BIT_DITHER);
+    mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_MASK);
+
+    mRasterizerStateDirtyBits.set(DIRTY_BIT_CULL_MODE);
+    mRasterizerStateDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
+
+    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK);
+    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
+    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+
+    mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED);
+    mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
+}
+
+StateManager9::~StateManager9()
+{
+}
+
+void StateManager9::initialize()
+{
+    mUsingZeroColorMaskWorkaround = IsAMD(mRenderer9->getVendorId());
+}
+
+void StateManager9::forceSetBlendState()
+{
+    mDirtyBits |= mBlendStateDirtyBits;
+}
+
+void StateManager9::forceSetRasterState()
+{
+    mDirtyBits |= mRasterizerStateDirtyBits;
+}
+
+void StateManager9::forceSetDepthStencilState()
+{
+    mDirtyBits |= mDepthStencilStateDirtyBits;
+}
+
+void StateManager9::forceSetScissorState()
+{
+    mDirtyBits |= mScissorStateDirtyBits;
+}
+
+void StateManager9::forceSetViewportState()
+{
+    mForceSetViewport = true;
+}
+
+void StateManager9::forceSetDXUniformsState()
+{
+    mDxUniformsDirty = true;
+}
+
+void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized,
+                                               unsigned int stencilSize)
+{
+    if (!depthStencilInitialized || stencilSize != mCurStencilSize)
+    {
+        mCurStencilSize = stencilSize;
+        forceSetDepthStencilState();
+    }
+}
+
+void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+    if (!dirtyBits.any())
+    {
+        return;
+    }
+
+    for (auto dirtyBit : dirtyBits)
+    {
+        switch (dirtyBit)
+        {
+            case gl::State::DIRTY_BIT_BLEND_ENABLED:
+                if (state.getBlendState().blend != mCurBlendState.blend)
+                {
+                    mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+                    // BlendColor and funcs and equations has to be set if blend is enabled
+                    mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+                    mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+
+                    // The color mask may have to be updated if the blend state changes
+                    if (mUsingZeroColorMaskWorkaround)
+                    {
+                        mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+                    }
+                }
+                break;
+            case gl::State::DIRTY_BIT_BLEND_FUNCS:
+            {
+                const gl::BlendState &blendState = state.getBlendState();
+                if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB ||
+                    blendState.destBlendRGB != mCurBlendState.destBlendRGB ||
+                    blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
+                    blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
+                {
+                    mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+                    // BlendColor depends on the values of blend funcs
+                    mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+
+                    // The color mask may have to be updated if the blend funcs change
+                    if (mUsingZeroColorMaskWorkaround)
+                    {
+                        mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+                    }
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
+            {
+                const gl::BlendState &blendState = state.getBlendState();
+                if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
+                    blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
+                {
+                    mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+
+                    // The color mask may have to be updated if the blend funcs change
+                    if (mUsingZeroColorMaskWorkaround)
+                    {
+                        mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+                    }
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
+                if (state.getBlendState().sampleAlphaToCoverage !=
+                    mCurBlendState.sampleAlphaToCoverage)
+                {
+                    mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE);
+                }
+                break;
+            case gl::State::DIRTY_BIT_COLOR_MASK:
+            {
+                const gl::BlendState &blendState = state.getBlendState();
+                if (blendState.colorMaskRed != mCurBlendState.colorMaskRed ||
+                    blendState.colorMaskGreen != mCurBlendState.colorMaskGreen ||
+                    blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
+                    blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
+                {
+                    mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+
+                    // The color mask can cause the blend state to get out of sync when using the
+                    // zero color mask workaround
+                    if (mUsingZeroColorMaskWorkaround)
+                    {
+                        mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+                        mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+                    }
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_DITHER_ENABLED:
+                if (state.getBlendState().dither != mCurBlendState.dither)
+                {
+                    mDirtyBits.set(DIRTY_BIT_DITHER);
+                }
+                break;
+            case gl::State::DIRTY_BIT_BLEND_COLOR:
+                if (state.getBlendColor() != mCurBlendColor)
+                {
+                    mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+                }
+                break;
+            case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
+                if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
+                {
+                    mDirtyBits.set(DIRTY_BIT_CULL_MODE);
+                }
+                break;
+            case gl::State::DIRTY_BIT_CULL_FACE:
+                if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
+                {
+                    mDirtyBits.set(DIRTY_BIT_CULL_MODE);
+                }
+                break;
+            case gl::State::DIRTY_BIT_FRONT_FACE:
+                if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
+                {
+                    mDirtyBits.set(DIRTY_BIT_CULL_MODE);
+
+                    // Viewport state depends on rasterizer.frontface
+                    mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+                }
+                break;
+            case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
+                if (state.getRasterizerState().polygonOffsetFill !=
+                    mCurRasterState.polygonOffsetFill)
+                {
+                    mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
+                }
+                break;
+            case gl::State::DIRTY_BIT_POLYGON_OFFSET:
+            {
+                const gl::RasterizerState &rasterizerState = state.getRasterizerState();
+                if (rasterizerState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
+                    rasterizerState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
+                {
+                    mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
+                }
+            }
+            case gl::State::DIRTY_BIT_DEPTH_MASK:
+                if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK);
+                }
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
+                if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+                }
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_FUNC:
+                if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+                }
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+                if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
+                    // If we enable the stencil test, all of these must be set
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+                }
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
+            {
+                const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+                if (depthStencilState.stencilFunc != mCurDepthStencilState.stencilFunc ||
+                    depthStencilState.stencilMask != mCurDepthStencilState.stencilMask ||
+                    state.getStencilRef() != mCurStencilRef)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+            {
+                const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+                if (depthStencilState.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
+                    depthStencilState.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
+                    state.getStencilBackRef() != mCurStencilBackRef)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+                if (state.getDepthStencilState().stencilWritemask !=
+                    mCurDepthStencilState.stencilWritemask)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+                }
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+                if (state.getDepthStencilState().stencilBackWritemask !=
+                    mCurDepthStencilState.stencilBackWritemask)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+                }
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+            {
+                const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+                if (depthStencilState.stencilFail != mCurDepthStencilState.stencilFail ||
+                    depthStencilState.stencilPassDepthFail !=
+                        mCurDepthStencilState.stencilPassDepthFail ||
+                    depthStencilState.stencilPassDepthPass !=
+                        mCurDepthStencilState.stencilPassDepthPass)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+            {
+                const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+                if (depthStencilState.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
+                    depthStencilState.stencilBackPassDepthFail !=
+                        mCurDepthStencilState.stencilBackPassDepthFail ||
+                    depthStencilState.stencilBackPassDepthPass !=
+                        mCurDepthStencilState.stencilBackPassDepthPass)
+                {
+                    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+                }
+                break;
+            }
+            case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
+                if (state.isScissorTestEnabled() != mCurScissorEnabled)
+                {
+                    mDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED);
+                    // If scissor is enabled, we have to set the scissor rect
+                    mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
+                }
+                break;
+            case gl::State::DIRTY_BIT_SCISSOR:
+                if (state.getScissor() != mCurScissorRect)
+                {
+                    mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
+                }
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_RANGE:
+                if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
+                {
+                    mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+                }
+                break;
+            case gl::State::DIRTY_BIT_VIEWPORT:
+                if (state.getViewport() != mCurViewport)
+                {
+                    mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+                }
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState,
+                                                   unsigned int sampleMask)
+{
+    const gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+
+    const gl::BlendState &blendState       = glState.getBlendState();
+    const gl::ColorF &blendColor           = glState.getBlendColor();
+    const gl::RasterizerState &rasterState = glState.getRasterizerState();
+
+    const auto &depthStencilState = glState.getDepthStencilState();
+    bool frontFaceCCW             = (glState.getRasterizerState().frontFace == GL_CCW);
+    unsigned int maxStencil       = (1 << mCurStencilSize) - 1;
+
+    // All the depth stencil states depends on the front face ccw variable
+    if (frontFaceCCW != mCurFrontFaceCCW)
+    {
+        forceSetDepthStencilState();
+        mCurFrontFaceCCW = frontFaceCCW;
+    }
+
+    for (auto dirtyBit : mDirtyBits)
+    {
+        switch (dirtyBit)
+        {
+            case DIRTY_BIT_BLEND_ENABLED:
+                setBlendEnabled(blendState.blend);
+                break;
+            case DIRTY_BIT_BLEND_COLOR:
+                setBlendColor(blendState, blendColor);
+                break;
+            case DIRTY_BIT_BLEND_FUNCS_EQUATIONS:
+                setBlendFuncsEquations(blendState);
+                break;
+            case DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE:
+                setSampleAlphaToCoverage(blendState.sampleAlphaToCoverage);
+                break;
+            case DIRTY_BIT_COLOR_MASK:
+                setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue,
+                             blendState.colorMaskGreen, blendState.colorMaskAlpha);
+                break;
+            case DIRTY_BIT_DITHER:
+                setDither(blendState.dither);
+                break;
+            case DIRTY_BIT_CULL_MODE:
+                setCullMode(rasterState.cullFace, rasterState.cullMode, rasterState.frontFace);
+                break;
+            case DIRTY_BIT_DEPTH_BIAS:
+                setDepthBias(rasterState.polygonOffsetFill, rasterState.polygonOffsetFactor,
+                             rasterState.polygonOffsetUnits);
+                break;
+            case DIRTY_BIT_STENCIL_DEPTH_MASK:
+                setDepthMask(depthStencilState.depthMask);
+                break;
+            case DIRTY_BIT_STENCIL_DEPTH_FUNC:
+                setDepthFunc(depthStencilState.depthTest, depthStencilState.depthFunc);
+                break;
+            case DIRTY_BIT_STENCIL_TEST_ENABLED:
+                setStencilTestEnabled(depthStencilState.stencilTest);
+                break;
+            case DIRTY_BIT_STENCIL_FUNCS_FRONT:
+                setStencilFuncsFront(depthStencilState.stencilFunc, depthStencilState.stencilMask,
+                                     glState.getStencilRef(), frontFaceCCW, maxStencil);
+                break;
+            case DIRTY_BIT_STENCIL_FUNCS_BACK:
+                setStencilFuncsBack(depthStencilState.stencilBackFunc,
+                                    depthStencilState.stencilBackMask, glState.getStencilBackRef(),
+                                    frontFaceCCW, maxStencil);
+                break;
+            case DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+                setStencilWriteMask(depthStencilState.stencilWritemask, frontFaceCCW);
+                break;
+            case DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+                setStencilBackWriteMask(depthStencilState.stencilBackWritemask, frontFaceCCW);
+                break;
+            case DIRTY_BIT_STENCIL_OPS_FRONT:
+                setStencilOpsFront(depthStencilState.stencilFail,
+                                   depthStencilState.stencilPassDepthFail,
+                                   depthStencilState.stencilPassDepthPass, frontFaceCCW);
+                break;
+            case DIRTY_BIT_STENCIL_OPS_BACK:
+                setStencilOpsBack(depthStencilState.stencilBackFail,
+                                  depthStencilState.stencilBackPassDepthFail,
+                                  depthStencilState.stencilBackPassDepthPass, frontFaceCCW);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (sampleMask != mCurSampleMask)
+    {
+        setSampleMask(sampleMask);
+    }
+
+    return gl::NoError();
+}
+
+void StateManager9::setViewportState(const gl::Rectangle &viewport,
+                                     float zNear,
+                                     float zFar,
+                                     GLenum drawMode,
+                                     GLenum frontFace,
+                                     bool ignoreViewport)
+{
+    if (!mDirtyBits.test(DIRTY_BIT_VIEWPORT) && mCurIgnoreViewport == ignoreViewport)
+        return;
+
+    gl::Rectangle actualViewport = viewport;
+    float actualZNear            = gl::clamp01(zNear);
+    float actualZFar             = gl::clamp01(zFar);
+
+    if (ignoreViewport)
+    {
+        actualViewport.x      = 0;
+        actualViewport.y      = 0;
+        actualViewport.width  = static_cast<int>(mRenderTargetBounds.width);
+        actualViewport.height = static_cast<int>(mRenderTargetBounds.height);
+        actualZNear           = 0.0f;
+        actualZFar            = 1.0f;
+    }
+
+    D3DVIEWPORT9 dxViewport;
+    dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetBounds.width));
+    dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetBounds.height));
+    dxViewport.Width =
+        gl::clamp(actualViewport.width, 0,
+                  static_cast<int>(mRenderTargetBounds.width) - static_cast<int>(dxViewport.X));
+    dxViewport.Height =
+        gl::clamp(actualViewport.height, 0,
+                  static_cast<int>(mRenderTargetBounds.height) - static_cast<int>(dxViewport.Y));
+    dxViewport.MinZ = actualZNear;
+    dxViewport.MaxZ = actualZFar;
+
+    float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);
+
+    mRenderer9->getDevice()->SetViewport(&dxViewport);
+
+    mCurViewport       = actualViewport;
+    mCurNear           = actualZNear;
+    mCurFar            = actualZFar;
+    mCurDepthFront     = depthFront;
+    mCurIgnoreViewport = ignoreViewport;
+
+    // Setting shader constants
+    dx_VertexConstants9 vc = {};
+    dx_PixelConstants9 pc  = {};
+
+    vc.viewAdjust[0] =
+        static_cast<float>((actualViewport.width - static_cast<int>(dxViewport.Width)) +
+                           2 * (actualViewport.x - static_cast<int>(dxViewport.X)) - 1) /
+        dxViewport.Width;
+    vc.viewAdjust[1] =
+        static_cast<float>((actualViewport.height - static_cast<int>(dxViewport.Height)) +
+                           2 * (actualViewport.y - static_cast<int>(dxViewport.Y)) - 1) /
+        dxViewport.Height;
+    vc.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width;
+    vc.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height;
+
+    pc.viewCoords[0] = actualViewport.width * 0.5f;
+    pc.viewCoords[1] = actualViewport.height * 0.5f;
+    pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
+    pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
+
+    pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
+    pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
+    pc.depthFront[2] = depthFront;
+
+    vc.depthRange[0] = actualZNear;
+    vc.depthRange[1] = actualZFar;
+    vc.depthRange[2] = actualZFar - actualZNear;
+
+    pc.depthRange[0] = actualZNear;
+    pc.depthRange[1] = actualZFar;
+    pc.depthRange[2] = actualZFar - actualZNear;
+
+    if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants9)) != 0)
+    {
+        mVertexConstants = vc;
+        mDxUniformsDirty = true;
+    }
+
+    if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants9)) != 0)
+    {
+        mPixelConstants  = pc;
+        mDxUniformsDirty = true;
+    }
+
+    mForceSetViewport = false;
+}
+
+void StateManager9::setShaderConstants()
+{
+    if (!mDxUniformsDirty)
+        return;
+
+    IDirect3DDevice9 *device = mRenderer9->getDevice();
+    device->SetVertexShaderConstantF(0, reinterpret_cast<float *>(&mVertexConstants),
+                                     sizeof(dx_VertexConstants9) / sizeof(float[4]));
+    device->SetPixelShaderConstantF(0, reinterpret_cast<float *>(&mPixelConstants),
+                                    sizeof(dx_PixelConstants9) / sizeof(float[4]));
+    mDxUniformsDirty = false;
+}
+
+// This is separate from the main state loop because other functions
+// outside call only setScissorState to update scissor state
+void StateManager9::setScissorState(const gl::Rectangle &scissor, bool enabled)
+{
+    if (mDirtyBits.test(DIRTY_BIT_SCISSOR_ENABLED))
+        setScissorEnabled(enabled);
+
+    if (mDirtyBits.test(DIRTY_BIT_SCISSOR_RECT))
+        setScissorRect(scissor, enabled);
+}
+
+void StateManager9::setRenderTargetBounds(size_t width, size_t height)
+{
+    mRenderTargetBounds.width  = (int)width;
+    mRenderTargetBounds.height = (int)height;
+    forceSetViewportState();
+}
+
+void StateManager9::setScissorEnabled(bool scissorEnabled)
+{
+    mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE);
+    mCurScissorEnabled = scissorEnabled;
+}
+
+void StateManager9::setScissorRect(const gl::Rectangle &scissor, bool enabled)
+{
+    if (!enabled)
+        return;
+
+    RECT rect;
+    rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetBounds.width));
+    rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetBounds.height));
+    rect.right =
+        gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetBounds.width));
+    rect.bottom =
+        gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetBounds.height));
+    mRenderer9->getDevice()->SetScissorRect(&rect);
+}
+
+void StateManager9::setDepthFunc(bool depthTest, GLenum depthFunc)
+{
+    if (depthTest)
+    {
+        IDirect3DDevice9 *device = mRenderer9->getDevice();
+        device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
+        device->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthFunc));
+    }
+    else
+    {
+        mRenderer9->getDevice()->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+    }
+
+    mCurDepthStencilState.depthTest = depthTest;
+    mCurDepthStencilState.depthFunc = depthFunc;
+}
+
+void StateManager9::setStencilOpsFront(GLenum stencilFail,
+                                       GLenum stencilPassDepthFail,
+                                       GLenum stencilPassDepthPass,
+                                       bool frontFaceCCW)
+{
+    // TODO(dianx) It may be slightly more efficient todo these and other similar areas
+    // with separate dirty bits.
+    IDirect3DDevice9 *device = mRenderer9->getDevice();
+    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+                           gl_d3d9::ConvertStencilOp(stencilFail));
+    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+                           gl_d3d9::ConvertStencilOp(stencilPassDepthFail));
+    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+                           gl_d3d9::ConvertStencilOp(stencilPassDepthPass));
+
+    mCurDepthStencilState.stencilFail          = stencilFail;
+    mCurDepthStencilState.stencilPassDepthFail = stencilPassDepthFail;
+    mCurDepthStencilState.stencilPassDepthPass = stencilPassDepthPass;
+}
+
+void StateManager9::setStencilOpsBack(GLenum stencilBackFail,
+                                      GLenum stencilBackPassDepthFail,
+                                      GLenum stencilBackPassDepthPass,
+                                      bool frontFaceCCW)
+{
+    IDirect3DDevice9 *device = mRenderer9->getDevice();
+    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+                           gl_d3d9::ConvertStencilOp(stencilBackFail));
+    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+                           gl_d3d9::ConvertStencilOp(stencilBackPassDepthFail));
+    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+                           gl_d3d9::ConvertStencilOp(stencilBackPassDepthPass));
+
+    mCurDepthStencilState.stencilBackFail          = stencilBackFail;
+    mCurDepthStencilState.stencilBackPassDepthFail = stencilBackPassDepthFail;
+    mCurDepthStencilState.stencilBackPassDepthPass = stencilBackPassDepthPass;
+}
+
+void StateManager9::setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW)
+{
+    mRenderer9->getDevice()->SetRenderState(
+        !frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWriteMask);
+
+    mCurDepthStencilState.stencilBackWritemask = stencilBackWriteMask;
+}
+
+void StateManager9::setStencilFuncsBack(GLenum stencilBackFunc,
+                                        GLuint stencilBackMask,
+                                        GLint stencilBackRef,
+                                        bool frontFaceCCW,
+                                        unsigned int maxStencil)
+{
+    IDirect3DDevice9 *device = mRenderer9->getDevice();
+    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+                           gl_d3d9::ConvertComparison(stencilBackFunc));
+    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
+                           (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
+    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
+                           stencilBackMask);
+
+    mCurDepthStencilState.stencilBackFunc = stencilBackFunc;
+    mCurStencilBackRef                    = stencilBackRef;
+    mCurDepthStencilState.stencilBackMask = stencilBackMask;
+}
+
+void StateManager9::setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW)
+{
+    mRenderer9->getDevice()->SetRenderState(
+        frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWriteMask);
+    mCurDepthStencilState.stencilWritemask = stencilWriteMask;
+}
+
+void StateManager9::setStencilFuncsFront(GLenum stencilFunc,
+                                         GLuint stencilMask,
+                                         GLint stencilRef,
+                                         bool frontFaceCCW,
+                                         unsigned int maxStencil)
+{
+    IDirect3DDevice9 *device = mRenderer9->getDevice();
+    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+                           gl_d3d9::ConvertComparison(stencilFunc));
+    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
+                           (stencilRef < static_cast<int>(maxStencil)) ? stencilRef : maxStencil);
+    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
+
+    mCurDepthStencilState.stencilFunc = stencilFunc;
+    mCurStencilRef                    = stencilRef;
+    mCurDepthStencilState.stencilMask = stencilMask;
+}
+void StateManager9::setStencilTestEnabled(bool stencilTestEnabled)
+{
+    if (stencilTestEnabled && mCurStencilSize > 0)
+    {
+        mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+        mRenderer9->getDevice()->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
+    }
+    else
+    {
+        mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+    }
+
+    mCurDepthStencilState.stencilTest = stencilTestEnabled;
+}
+
+void StateManager9::setDepthMask(bool depthMask)
+{
+    mRenderer9->getDevice()->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
+    mCurDepthStencilState.depthMask = depthMask;
+}
+
+// TODO(dianx) one bit for sampleAlphaToCoverage
+void StateManager9::setSampleAlphaToCoverage(bool enabled)
+{
+    if (enabled)
+    {
+        UNREACHABLE();
+    }
+}
+
+void StateManager9::setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor)
+{
+    if (!blendState.blend)
+        return;
+
+    if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
+        blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+        blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
+        blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+    {
+        mRenderer9->getDevice()->SetRenderState(D3DRS_BLENDFACTOR,
+                                                gl_d3d9::ConvertColor(blendColor));
+    }
+    else
+    {
+        mRenderer9->getDevice()->SetRenderState(
+            D3DRS_BLENDFACTOR,
+            D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha),
+                          gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha)));
+    }
+    mCurBlendColor = blendColor;
+}
+
+void StateManager9::setBlendFuncsEquations(const gl::BlendState &blendState)
+{
+    if (!blendState.blend)
+        return;
+
+    IDirect3DDevice9 *device = mRenderer9->getDevice();
+
+    device->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
+    device->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
+    device->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));
+
+    if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
+        blendState.destBlendRGB != blendState.destBlendAlpha ||
+        blendState.blendEquationRGB != blendState.blendEquationAlpha)
+    {
+        device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+
+        device->SetRenderState(D3DRS_SRCBLENDALPHA,
+                               gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
+        device->SetRenderState(D3DRS_DESTBLENDALPHA,
+                               gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
+        device->SetRenderState(D3DRS_BLENDOPALPHA,
+                               gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
+    }
+    else
+    {
+        device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+    }
+
+    mCurBlendState.sourceBlendRGB     = blendState.sourceBlendRGB;
+    mCurBlendState.destBlendRGB       = blendState.destBlendRGB;
+    mCurBlendState.blendEquationRGB   = blendState.blendEquationRGB;
+    mCurBlendState.blendEquationAlpha = blendState.blendEquationAlpha;
+}
+
+void StateManager9::setBlendEnabled(bool enabled)
+{
+    mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE);
+    mCurBlendState.blend = enabled;
+}
+
+void StateManager9::setDither(bool dither)
+{
+    mRenderer9->getDevice()->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
+    mCurBlendState.dither = dither;
+}
+
+// TODO(dianx) one bit for color mask
+void StateManager9::setColorMask(const gl::Framebuffer *framebuffer,
+                                 bool red,
+                                 bool blue,
+                                 bool green,
+                                 bool alpha)
+{
+    // Set the color mask
+
+    const auto *attachment = framebuffer->getFirstColorbuffer();
+    const auto &format     = attachment ? attachment->getFormat() : gl::Format::Invalid();
+
+    DWORD colorMask = gl_d3d9::ConvertColorMask(
+        format.info->redBits > 0 && red, format.info->greenBits > 0 && green,
+        format.info->blueBits > 0 && blue, format.info->alphaBits > 0 && alpha);
+
+    // Apparently some ATI cards have a bug where a draw with a zero color write mask can cause
+    // later draws to have incorrect results. Instead, set a nonzero color write mask but modify the
+    // blend state so that no drawing is done.
+    // http://anglebug.com/169
+    if (colorMask == 0 && mUsingZeroColorMaskWorkaround)
+    {
+        IDirect3DDevice9 *device = mRenderer9->getDevice();
+        // Enable green channel, but set blending so nothing will be drawn.
+        device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
+
+        device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+        device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+        device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+        device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+
+        mCurBlendState.colorMaskRed   = false;
+        mCurBlendState.colorMaskGreen = true;
+        mCurBlendState.colorMaskBlue  = false;
+        mCurBlendState.colorMaskAlpha = false;
+
+        mCurBlendState.blend              = true;
+        mCurBlendState.sourceBlendRGB     = GL_ZERO;
+        mCurBlendState.sourceBlendAlpha   = GL_ZERO;
+        mCurBlendState.destBlendRGB       = GL_ONE;
+        mCurBlendState.destBlendAlpha     = GL_ONE;
+        mCurBlendState.blendEquationRGB   = GL_FUNC_ADD;
+        mCurBlendState.blendEquationAlpha = GL_FUNC_ADD;
+    }
+    else
+    {
+        mRenderer9->getDevice()->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
+
+        mCurBlendState.colorMaskRed   = red;
+        mCurBlendState.colorMaskGreen = green;
+        mCurBlendState.colorMaskBlue  = blue;
+        mCurBlendState.colorMaskAlpha = alpha;
+    }
+}
+
+void StateManager9::setSampleMask(unsigned int sampleMask)
+{
+    IDirect3DDevice9 *device = mRenderer9->getDevice();
+    // Set the multisample mask
+    device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
+    device->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));
+
+    mCurSampleMask = sampleMask;
+}
+
+void StateManager9::setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace)
+{
+    if (cullFace)
+    {
+        mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE,
+                                                gl_d3d9::ConvertCullMode(cullMode, frontFace));
+    }
+    else
+    {
+        mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+    }
+
+    mCurRasterState.cullFace  = cullFace;
+    mCurRasterState.cullMode  = cullMode;
+    mCurRasterState.frontFace = frontFace;
+}
+
+void StateManager9::setDepthBias(bool polygonOffsetFill,
+                                 GLfloat polygonOffsetFactor,
+                                 GLfloat polygonOffsetUnits)
+{
+    if (polygonOffsetFill)
+    {
+        if (mCurDepthSize > 0)
+        {
+            IDirect3DDevice9 *device = mRenderer9->getDevice();
+            device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD *)&polygonOffsetFactor);
+
+            float depthBias = ldexp(polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
+            device->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD *)&depthBias);
+        }
+    }
+    else
+    {
+        IDirect3DDevice9 *device = mRenderer9->getDevice();
+        device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
+        device->SetRenderState(D3DRS_DEPTHBIAS, 0);
+    }
+
+    mCurRasterState.polygonOffsetFill   = polygonOffsetFill;
+    mCurRasterState.polygonOffsetFactor = polygonOffsetFactor;
+    mCurRasterState.polygonOffsetUnits  = polygonOffsetUnits;
+}
+
+void StateManager9::updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize)
+{
+    if (!depthStencilInitialized || depthSize != mCurDepthSize)
+    {
+        mCurDepthSize = depthSize;
+        forceSetRasterState();
+    }
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
new file mode 100644
index 0000000..ea4f91c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
@@ -0,0 +1,209 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager9.h: Defines a class for caching D3D9 state
+
+#ifndef LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
+#define LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/State.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+class Renderer9;
+
+struct dx_VertexConstants9
+{
+    float depthRange[4];
+    float viewAdjust[4];
+    float viewCoords[4];
+};
+
+struct dx_PixelConstants9
+{
+    float depthRange[4];
+    float viewCoords[4];
+    float depthFront[4];
+};
+
+class StateManager9 final : angle::NonCopyable
+{
+  public:
+    StateManager9(Renderer9 *renderer9);
+    ~StateManager9();
+
+    void initialize();
+
+    void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
+
+    gl::Error setBlendDepthRasterStates(const gl::State &glState, unsigned int sampleMask);
+    void setScissorState(const gl::Rectangle &scissor, bool enabled);
+    void setViewportState(const gl::Rectangle &viewport,
+                          float zNear,
+                          float zFar,
+                          GLenum drawMode,
+                          GLenum frontFace,
+                          bool ignoreViewport);
+
+    void setShaderConstants();
+
+    void forceSetBlendState();
+    void forceSetRasterState();
+    void forceSetDepthStencilState();
+    void forceSetScissorState();
+    void forceSetViewportState();
+    void forceSetDXUniformsState();
+
+    void updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize);
+    void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
+
+    void setRenderTargetBounds(size_t width, size_t height);
+
+    int getRenderTargetWidth() const { return mRenderTargetBounds.width; }
+    int getRenderTargetHeight() const { return mRenderTargetBounds.height; }
+
+    void resetDirtyBits() { mDirtyBits.reset(); }
+
+  private:
+    // Blend state functions
+    void setBlendEnabled(bool enabled);
+    void setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor);
+    void setBlendFuncsEquations(const gl::BlendState &blendState);
+    void setColorMask(const gl::Framebuffer *framebuffer,
+                      bool red,
+                      bool blue,
+                      bool green,
+                      bool alpha);
+    void setSampleAlphaToCoverage(bool enabled);
+    void setDither(bool dither);
+    void setSampleMask(unsigned int sampleMask);
+
+    // Current raster state functions
+    void setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace);
+    void setDepthBias(bool polygonOffsetFill,
+                      GLfloat polygonOffsetFactor,
+                      GLfloat polygonOffsetUnits);
+
+    // Depth stencil state functions
+    void setStencilOpsFront(GLenum stencilFail,
+                            GLenum stencilPassDepthFail,
+                            GLenum stencilPassDepthPass,
+                            bool frontFaceCCW);
+    void setStencilOpsBack(GLenum stencilBackFail,
+                           GLenum stencilBackPassDepthFail,
+                           GLenum stencilBackPassDepthPass,
+                           bool frontFaceCCW);
+    void setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW);
+    void setDepthFunc(bool depthTest, GLenum depthFunc);
+    void setStencilTestEnabled(bool enabled);
+    void setDepthMask(bool depthMask);
+    void setStencilFuncsFront(GLenum stencilFunc,
+                              GLuint stencilMask,
+                              GLint stencilRef,
+                              bool frontFaceCCW,
+                              unsigned int maxStencil);
+    void setStencilFuncsBack(GLenum stencilBackFunc,
+                             GLuint stencilBackMask,
+                             GLint stencilBackRef,
+                             bool frontFaceCCW,
+                             unsigned int maxStencil);
+    void setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW);
+
+    void setScissorEnabled(bool scissorEnabled);
+    void setScissorRect(const gl::Rectangle &scissor, bool enabled);
+
+    enum DirtyBitType
+    {
+        // Blend dirty bits
+        DIRTY_BIT_BLEND_ENABLED,
+        DIRTY_BIT_BLEND_COLOR,
+        DIRTY_BIT_BLEND_FUNCS_EQUATIONS,
+        DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE,
+        DIRTY_BIT_COLOR_MASK,
+        DIRTY_BIT_DITHER,
+        DIRTY_BIT_SAMPLE_MASK,
+
+        // Rasterizer dirty bits
+        DIRTY_BIT_CULL_MODE,
+        DIRTY_BIT_DEPTH_BIAS,
+
+        // Depth stencil dirty bits
+        DIRTY_BIT_STENCIL_DEPTH_MASK,
+        DIRTY_BIT_STENCIL_DEPTH_FUNC,
+        DIRTY_BIT_STENCIL_TEST_ENABLED,
+        DIRTY_BIT_STENCIL_FUNCS_FRONT,
+        DIRTY_BIT_STENCIL_FUNCS_BACK,
+        DIRTY_BIT_STENCIL_WRITEMASK_FRONT,
+        DIRTY_BIT_STENCIL_WRITEMASK_BACK,
+        DIRTY_BIT_STENCIL_OPS_FRONT,
+        DIRTY_BIT_STENCIL_OPS_BACK,
+
+        // Scissor dirty bits
+        DIRTY_BIT_SCISSOR_ENABLED,
+        DIRTY_BIT_SCISSOR_RECT,
+
+        // Viewport dirty bits
+        DIRTY_BIT_VIEWPORT,
+
+        DIRTY_BIT_MAX
+    };
+
+    using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
+
+    bool mUsingZeroColorMaskWorkaround;
+
+    // Currently applied blend state
+    gl::BlendState mCurBlendState;
+    gl::ColorF mCurBlendColor;
+    unsigned int mCurSampleMask;
+    DirtyBits mBlendStateDirtyBits;
+
+    // Currently applied raster state
+    gl::RasterizerState mCurRasterState;
+    unsigned int mCurDepthSize;
+    DirtyBits mRasterizerStateDirtyBits;
+
+    // Currently applied depth stencil state
+    gl::DepthStencilState mCurDepthStencilState;
+    int mCurStencilRef;
+    int mCurStencilBackRef;
+    bool mCurFrontFaceCCW;
+    unsigned int mCurStencilSize;
+    DirtyBits mDepthStencilStateDirtyBits;
+
+    // Currently applied scissor states
+    gl::Rectangle mCurScissorRect;
+    bool mCurScissorEnabled;
+    gl::Extents mRenderTargetBounds;
+    DirtyBits mScissorStateDirtyBits;
+
+    // Currently applied viewport states
+    bool mForceSetViewport;
+    gl::Rectangle mCurViewport;
+    float mCurNear;
+    float mCurFar;
+    float mCurDepthFront;
+    bool mCurIgnoreViewport;
+
+    dx_VertexConstants9 mVertexConstants;
+    dx_PixelConstants9 mPixelConstants;
+    bool mDxUniformsDirty;
+
+    // FIXME: Unsupported by D3D9
+    static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF       = D3DRS_STENCILREF;
+    static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK      = D3DRS_STENCILMASK;
+    static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
+
+    Renderer9 *mRenderer9;
+    DirtyBits mDirtyBits;
+};
+
+}  // namespace rx
+#endif  // LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
new file mode 100644
index 0000000..6556667
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
@@ -0,0 +1,451 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.
+
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace rx
+{
+
+SwapChain9::SwapChain9(Renderer9 *renderer,
+                       NativeWindow9 *nativeWindow,
+                       HANDLE shareHandle,
+                       IUnknown *d3dTexture,
+                       GLenum backBufferFormat,
+                       GLenum depthBufferFormat,
+                       EGLint orientation)
+    : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat),
+      mRenderer(renderer),
+      mWidth(-1),
+      mHeight(-1),
+      mSwapInterval(-1),
+      mNativeWindow(nativeWindow),
+      mSwapChain(nullptr),
+      mBackBuffer(nullptr),
+      mRenderTarget(nullptr),
+      mDepthStencil(nullptr),
+      mOffscreenTexture(nullptr),
+      mColorRenderTarget(this, false),
+      mDepthStencilRenderTarget(this, true)
+{
+    ASSERT(orientation == 0);
+}
+
+SwapChain9::~SwapChain9()
+{
+    release();
+}
+
+void SwapChain9::release()
+{
+    SafeRelease(mSwapChain);
+    SafeRelease(mBackBuffer);
+    SafeRelease(mDepthStencil);
+    SafeRelease(mRenderTarget);
+    SafeRelease(mOffscreenTexture);
+
+    if (mNativeWindow->getNativeWindow())
+    {
+        mShareHandle = nullptr;
+    }
+}
+
+static DWORD convertInterval(EGLint interval)
+{
+#if ANGLE_VSYNC == ANGLE_DISABLED
+    return D3DPRESENT_INTERVAL_IMMEDIATE;
+#else
+    switch(interval)
+    {
+      case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
+      case 1: return D3DPRESENT_INTERVAL_ONE;
+      case 2: return D3DPRESENT_INTERVAL_TWO;
+      case 3: return D3DPRESENT_INTERVAL_THREE;
+      case 4: return D3DPRESENT_INTERVAL_FOUR;
+      default: UNREACHABLE();
+    }
+
+    return D3DPRESENT_INTERVAL_DEFAULT;
+#endif
+}
+
+EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight)
+{
+    // D3D9 does not support resizing swap chains without recreating them
+    return reset(backbufferWidth, backbufferHeight, mSwapInterval);
+}
+
+EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
+{
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    if (device == nullptr)
+    {
+        return EGL_BAD_ACCESS;
+    }
+
+    // Evict all non-render target textures to system memory and release all resources
+    // before reallocating them to free up as much video memory as possible.
+    device->EvictManagedResources();
+
+    HRESULT result;
+
+    // Release specific resources to free up memory for the new render target, while the
+    // old render target still exists for the purpose of preserving its contents.
+    SafeRelease(mSwapChain);
+    SafeRelease(mBackBuffer);
+    SafeRelease(mOffscreenTexture);
+    SafeRelease(mDepthStencil);
+
+    const d3d9::TextureFormat &backBufferd3dFormatInfo =
+        d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat);
+    if (mD3DTexture != nullptr)
+    {
+        result = mD3DTexture->QueryInterface(&mOffscreenTexture);
+        ASSERT(SUCCEEDED(result));
+    }
+    else
+    {
+        HANDLE *pShareHandle = nullptr;
+        if (!mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport())
+        {
+            pShareHandle = &mShareHandle;
+        }
+
+        result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
+                                       backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
+                                       &mOffscreenTexture, pShareHandle);
+        if (FAILED(result))
+        {
+            ERR() << "Could not create offscreen texture, " << gl::FmtHR(result);
+            release();
+
+            if (d3d9::isDeviceLostError(result))
+            {
+                return EGL_CONTEXT_LOST;
+            }
+            else
+            {
+                return EGL_BAD_ALLOC;
+            }
+        }
+    }
+
+    IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
+
+    result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
+    ASSERT(SUCCEEDED(result));
+
+    if (oldRenderTarget)
+    {
+        RECT rect =
+        {
+            0, 0,
+            mWidth, mHeight
+        };
+
+        if (rect.right > static_cast<LONG>(backbufferWidth))
+        {
+            rect.right = backbufferWidth;
+        }
+
+        if (rect.bottom > static_cast<LONG>(backbufferHeight))
+        {
+            rect.bottom = backbufferHeight;
+        }
+
+        mRenderer->endScene();
+
+        result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
+        ASSERT(SUCCEEDED(result));
+
+        SafeRelease(oldRenderTarget);
+    }
+
+    const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat);
+
+    // Don't create a swapchain for NULLREF devices
+    D3DDEVTYPE deviceType = mRenderer->getD3D9DeviceType();
+    EGLNativeWindowType window = mNativeWindow->getNativeWindow();
+    if (window && deviceType != D3DDEVTYPE_NULLREF)
+    {
+        D3DPRESENT_PARAMETERS presentParameters = {0};
+        presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat;
+        presentParameters.BackBufferCount = 1;
+        presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat;
+        presentParameters.EnableAutoDepthStencil = FALSE;
+        presentParameters.Flags = 0;
+        presentParameters.hDeviceWindow = window;
+        presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
+        presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
+        presentParameters.PresentationInterval = convertInterval(swapInterval);
+        presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+        presentParameters.Windowed = TRUE;
+        presentParameters.BackBufferWidth = backbufferWidth;
+        presentParameters.BackBufferHeight = backbufferHeight;
+
+        // http://crbug.com/140239
+        // http://crbug.com/143434
+        //
+        // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width
+        // when using the integrated Intel. This rounds the width up rather than down.
+        //
+        // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
+        // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
+        if (IsIntel(mRenderer->getVendorId()))
+        {
+            presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
+        }
+
+        result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
+
+            ERR() << "Could not create additional swap chains or offscreen surfaces, "
+                  << gl::FmtHR(result);
+            release();
+
+            if (d3d9::isDeviceLostError(result))
+            {
+                return EGL_CONTEXT_LOST;
+            }
+            else
+            {
+                return EGL_BAD_ALLOC;
+            }
+        }
+
+        result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
+        ASSERT(SUCCEEDED(result));
+        InvalidateRect(window, nullptr, FALSE);
+    }
+
+    if (mDepthBufferFormat != GL_NONE)
+    {
+        result = device->CreateDepthStencilSurface(
+            backbufferWidth, backbufferHeight, depthBufferd3dFormatInfo.renderFormat,
+            D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, nullptr);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
+
+            ERR() << "Could not create depthstencil surface for new swap chain, "
+                  << gl::FmtHR(result);
+            release();
+
+            if (d3d9::isDeviceLostError(result))
+            {
+                return EGL_CONTEXT_LOST;
+            }
+            else
+            {
+                return EGL_BAD_ALLOC;
+            }
+        }
+    }
+
+    mWidth = backbufferWidth;
+    mHeight = backbufferHeight;
+    mSwapInterval = swapInterval;
+
+    return EGL_SUCCESS;
+}
+
+// parameters should be validated/clamped by caller
+EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    if (!mSwapChain)
+    {
+        return EGL_SUCCESS;
+    }
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+
+    // Disable all pipeline operations
+    device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+    device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+    device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+    device->SetPixelShader(nullptr);
+    device->SetVertexShader(nullptr);
+
+    device->SetRenderTarget(0, mBackBuffer);
+    device->SetDepthStencilSurface(nullptr);
+
+    device->SetTexture(0, mOffscreenTexture);
+    device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+    device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+    device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+    device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
+
+    for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++)
+    {
+        device->SetStreamSourceFreq(streamIndex, 1);
+    }
+
+    D3DVIEWPORT9 viewport = {0, 0, static_cast<DWORD>(mWidth), static_cast<DWORD>(mHeight), 0.0f, 1.0f};
+    device->SetViewport(&viewport);
+
+    float x1 = x - 0.5f;
+    float y1 = (mHeight - y - height) - 0.5f;
+    float x2 = (x + width) - 0.5f;
+    float y2 = (mHeight - y) - 0.5f;
+
+    float u1 = x / float(mWidth);
+    float v1 = y / float(mHeight);
+    float u2 = (x + width) / float(mWidth);
+    float v2 = (y + height) / float(mHeight);
+
+    float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
+                        {x2, y1, 0.0f, 1.0f, u2, v2},
+                        {x2, y2, 0.0f, 1.0f, u2, v1},
+                        {x1, y2, 0.0f, 1.0f, u1, v1}};   // x, y, z, rhw, u, v
+
+    mRenderer->startScene();
+    device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
+    mRenderer->endScene();
+
+    device->SetTexture(0, nullptr);
+
+    RECT rect =
+    {
+        static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
+        static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)
+    };
+
+    HRESULT result = mSwapChain->Present(&rect, &rect, nullptr, nullptr, 0);
+
+    mRenderer->markAllStateDirty();
+
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
+    {
+        return EGL_BAD_ALLOC;
+    }
+
+    // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the windows is
+    // in the process of entering/exiting fullscreen. This code doesn't seem to have any documentation.  The
+    // device appears to be ok after emitting this error so simply return a failure to swap.
+    if (result == static_cast<HRESULT>(0x88760873))
+    {
+        return EGL_BAD_MATCH;
+    }
+
+    // http://crbug.com/313210
+    // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific
+    // device removed bug with lost contexts when reinstalling drivers.
+    if (FAILED(result))
+    {
+        mRenderer->notifyDeviceLost();
+        return EGL_CONTEXT_LOST;
+    }
+
+    return EGL_SUCCESS;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+// TODO: remove the AddRef to match SwapChain11
+IDirect3DSurface9 *SwapChain9::getRenderTarget()
+{
+    if (mRenderTarget)
+    {
+        mRenderTarget->AddRef();
+    }
+
+    return mRenderTarget;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+// TODO: remove the AddRef to match SwapChain11
+IDirect3DSurface9 *SwapChain9::getDepthStencil()
+{
+    if (mDepthStencil)
+    {
+        mDepthStencil->AddRef();
+    }
+
+    return mDepthStencil;
+}
+
+// Increments refcount on texture.
+// caller must Release() the returned texture
+// TODO: remove the AddRef to match SwapChain11
+IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
+{
+    if (mOffscreenTexture)
+    {
+        mOffscreenTexture->AddRef();
+    }
+
+    return mOffscreenTexture;
+}
+
+void *SwapChain9::getKeyedMutex()
+{
+    UNREACHABLE();
+    return nullptr;
+}
+
+egl::Error SwapChain9::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+    UNREACHABLE();
+    return egl::Error(EGL_BAD_SURFACE);
+}
+
+void SwapChain9::recreate()
+{
+    if (!mSwapChain)
+    {
+        return;
+    }
+
+    IDirect3DDevice9 *device = mRenderer->getDevice();
+    if (device == nullptr)
+    {
+        return;
+    }
+
+    D3DPRESENT_PARAMETERS presentParameters;
+    HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
+    ASSERT(SUCCEEDED(result));
+
+    IDirect3DSwapChain9 *newSwapChain = nullptr;
+    result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain);
+    if (FAILED(result))
+    {
+        return;
+    }
+
+    SafeRelease(mSwapChain);
+    mSwapChain = newSwapChain;
+
+    SafeRelease(mBackBuffer);
+    result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
+    ASSERT(SUCCEEDED(result));
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
new file mode 100644
index 0000000..11fde1a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+
+namespace rx
+{
+class NativeWindow9;
+class Renderer9;
+
+class SwapChain9 : public SwapChainD3D
+{
+  public:
+    SwapChain9(Renderer9 *renderer,
+               NativeWindow9 *nativeWindow,
+               HANDLE shareHandle,
+               IUnknown *d3dTexture,
+               GLenum backBufferFormat,
+               GLenum depthBufferFormat,
+               EGLint orientation);
+    virtual ~SwapChain9();
+
+    EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
+    virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
+    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+    virtual void recreate();
+
+    RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; }
+    RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; }
+
+    virtual IDirect3DSurface9 *getRenderTarget();
+    virtual IDirect3DSurface9 *getDepthStencil();
+    virtual IDirect3DTexture9 *getOffscreenTexture();
+
+    EGLint getWidth() const { return mWidth; }
+    EGLint getHeight() const { return mHeight; }
+
+    void *getKeyedMutex() override;
+
+    egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+
+  private:
+    void release();
+
+    Renderer9 *mRenderer;
+    EGLint mWidth;
+    EGLint mHeight;
+    EGLint mSwapInterval;
+
+    NativeWindow9 *mNativeWindow;
+
+    IDirect3DSwapChain9 *mSwapChain;
+    IDirect3DSurface9 *mBackBuffer;
+    IDirect3DSurface9 *mRenderTarget;
+    IDirect3DSurface9 *mDepthStencil;
+    IDirect3DTexture9* mOffscreenTexture;
+
+    SurfaceRenderTarget9 mColorRenderTarget;
+    SurfaceRenderTarget9 mDepthStencilRenderTarget;
+};
+
+}
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
new file mode 100644
index 0000000..fd3e2c8
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -0,0 +1,617 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived
+// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
+// D3D9 texture.
+
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+
+namespace rx
+{
+TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage)
+    : mTopLevel(0),
+      mMipLevels(0),
+      mTextureWidth(0),
+      mTextureHeight(0),
+      mInternalFormat(GL_NONE),
+      mTextureFormat(D3DFMT_UNKNOWN),
+      mRenderer(renderer),
+      mD3DUsage(usage),
+      mD3DPool(mRenderer->getTexturePool(usage))
+{
+}
+
+TextureStorage9::~TextureStorage9()
+{
+}
+
+DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget)
+{
+    DWORD d3dusage = 0;
+
+    const gl::InternalFormat &formatInfo     = gl::GetSizedInternalFormatInfo(internalformat);
+    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+    if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+    {
+        d3dusage |= D3DUSAGE_DEPTHSTENCIL;
+    }
+    else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN))
+    {
+        d3dusage |= D3DUSAGE_RENDERTARGET;
+    }
+
+    return d3dusage;
+}
+
+
+bool TextureStorage9::isRenderTarget() const
+{
+    return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
+}
+
+bool TextureStorage9::isManaged() const
+{
+    return (mD3DPool == D3DPOOL_MANAGED);
+}
+
+bool TextureStorage9::supportsNativeMipmapFunction() const
+{
+    return false;
+}
+
+D3DPOOL TextureStorage9::getPool() const
+{
+    return mD3DPool;
+}
+
+DWORD TextureStorage9::getUsage() const
+{
+    return mD3DUsage;
+}
+
+int TextureStorage9::getTopLevel() const
+{
+    return mTopLevel;
+}
+
+int TextureStorage9::getLevelCount() const
+{
+    return static_cast<int>(mMipLevels) - mTopLevel;
+}
+
+gl::Error TextureStorage9::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
+                                   const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain)
+    : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
+{
+    IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
+    mTexture = surfaceTexture;
+    mMipLevels = surfaceTexture->GetLevelCount();
+
+    mInternalFormat = swapchain->getRenderTargetInternalFormat();
+
+    D3DSURFACE_DESC surfaceDesc;
+    surfaceTexture->GetLevelDesc(0, &surfaceDesc);
+    mTextureWidth = surfaceDesc.Width;
+    mTextureHeight = surfaceDesc.Height;
+    mTextureFormat = surfaceDesc.Format;
+
+    mRenderTargets.resize(mMipLevels, nullptr);
+}
+
+TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
+    : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
+{
+    mTexture = nullptr;
+
+    mInternalFormat = internalformat;
+
+    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+    mTextureFormat = d3dFormatInfo.texFormat;
+
+    d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
+    mTextureWidth = width;
+    mTextureHeight = height;
+    mMipLevels = mTopLevel + levels;
+
+    mRenderTargets.resize(levels, nullptr);
+}
+
+TextureStorage9_2D::~TextureStorage9_2D()
+{
+    SafeRelease(mTexture);
+    for (auto &renderTarget : mRenderTargets)
+    {
+        SafeDelete(renderTarget);
+    }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target,
+                                              int level,
+                                              bool dirty,
+                                              IDirect3DSurface9 **outSurface)
+{
+    ASSERT(target == GL_TEXTURE_2D);
+
+    IDirect3DBaseTexture9 *baseTexture = nullptr;
+    gl::Error error = getBaseTexture(&baseTexture);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9*>(baseTexture);
+
+    HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);
+
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+    }
+
+    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+    if (level + mTopLevel != 0 && isManaged() && dirty)
+    {
+        texture->AddDirtyRect(nullptr);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+    ASSERT(index.mipIndex < getLevelCount());
+
+    if (!mRenderTargets[index.mipIndex] && isRenderTarget())
+    {
+        IDirect3DBaseTexture9 *baseTexture = nullptr;
+        gl::Error error = getBaseTexture(&baseTexture);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        IDirect3DSurface9 *surface = nullptr;
+        error = getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, false, &surface);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        size_t textureMipLevel = mTopLevel + index.mipIndex;
+        size_t mipWidth        = std::max<size_t>(mTextureWidth >> textureMipLevel, 1u);
+        size_t mipHeight       = std::max<size_t>(mTextureHeight >> textureMipLevel, 1u);
+
+        baseTexture->AddRef();
+        mRenderTargets[index.mipIndex] = new TextureRenderTarget9(
+            baseTexture, textureMipLevel, surface, mInternalFormat, static_cast<GLsizei>(mipWidth),
+            static_cast<GLsizei>(mipHeight), 1, 0);
+    }
+
+    ASSERT(outRT);
+    *outRT = mRenderTargets[index.mipIndex];
+    return gl::NoError();
+}
+
+gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
+{
+    IDirect3DSurface9 *upper = nullptr;
+    gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DSurface9 *lower = nullptr;
+    error = getSurfaceLevel(GL_TEXTURE_2D, destIndex.mipIndex, true, &lower);
+    if (error.isError())
+    {
+        SafeRelease(upper);
+        return error;
+    }
+
+    ASSERT(upper && lower);
+    error = mRenderer->boxFilter(upper, lower);
+
+    SafeRelease(upper);
+    SafeRelease(lower);
+
+    return error;
+}
+
+gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+{
+    // if the width or height is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
+    {
+        ASSERT(mMipLevels > 0);
+
+        IDirect3DDevice9 *device = mRenderer->getDevice();
+        HRESULT result           = device->CreateTexture(static_cast<unsigned int>(mTextureWidth),
+                                               static_cast<unsigned int>(mTextureHeight),
+                                               static_cast<unsigned int>(mMipLevels), getUsage(),
+                                               mTextureFormat, getPool(), &mTexture, nullptr);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result);
+        }
+    }
+
+    *outTexture = mTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
+{
+    ASSERT(destStorage);
+
+    TextureStorage9_2D *dest9 = GetAs<TextureStorage9_2D>(destStorage);
+
+    int levels = getLevelCount();
+    for (int i = 0; i < levels; ++i)
+    {
+        IDirect3DSurface9 *srcSurf = nullptr;
+        gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, i, false, &srcSurf);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        IDirect3DSurface9 *dstSurf = nullptr;
+        error = dest9->getSurfaceLevel(GL_TEXTURE_2D, i, true, &dstSurf);
+        if (error.isError())
+        {
+            SafeRelease(srcSurf);
+            return error;
+        }
+
+        error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
+
+        SafeRelease(srcSurf);
+        SafeRelease(dstSurf);
+
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    return gl::NoError();
+}
+
+TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer,
+                                                   EGLImageD3D *image,
+                                                   RenderTarget9 *renderTarget9)
+    : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET), mImage(image)
+{
+    mInternalFormat = renderTarget9->getInternalFormat();
+    mTextureFormat  = renderTarget9->getD3DFormat();
+    mTextureWidth   = renderTarget9->getWidth();
+    mTextureHeight  = renderTarget9->getHeight();
+    mTopLevel       = static_cast<int>(renderTarget9->getTextureLevel());
+    mMipLevels      = mTopLevel + 1;
+}
+
+TextureStorage9_EGLImage::~TextureStorage9_EGLImage()
+{
+}
+
+gl::Error TextureStorage9_EGLImage::getSurfaceLevel(GLenum target,
+                                                    int level,
+                                                    bool,
+                                                    IDirect3DSurface9 **outSurface)
+{
+    ASSERT(target == GL_TEXTURE_2D);
+    ASSERT(level == 0);
+
+    RenderTargetD3D *renderTargetD3D = nullptr;
+    gl::Error error = mImage->getRenderTarget(&renderTargetD3D);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
+
+    *outSurface = renderTarget9->getSurface();
+    return gl::NoError();
+}
+
+gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::ImageIndex &index,
+                                                    RenderTargetD3D **outRT)
+{
+    ASSERT(!index.hasLayer());
+    ASSERT(index.mipIndex == 0);
+
+    return mImage->getRenderTarget(outRT);
+}
+
+gl::Error TextureStorage9_EGLImage::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+{
+    RenderTargetD3D *renderTargetD3D = nullptr;
+    gl::Error error = mImage->getRenderTarget(&renderTargetD3D);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
+    *outTexture = renderTarget9->getTexture();
+    ASSERT(*outTexture != nullptr);
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage9_EGLImage::generateMipmap(const gl::ImageIndex &, const gl::ImageIndex &)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage)
+{
+    ASSERT(destStorage);
+    ASSERT(getLevelCount() == 1);
+
+    TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage);
+
+    IDirect3DBaseTexture9 *destBaseTexture9 = nullptr;
+    gl::Error error = dest9->getBaseTexture(&destBaseTexture9);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DTexture9 *destTexture9 = static_cast<IDirect3DTexture9 *>(destBaseTexture9);
+
+    IDirect3DSurface9 *destSurface = nullptr;
+    HRESULT result = destTexture9->GetSurfaceLevel(destStorage->getTopLevel(), &destSurface);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY,
+                         "Failed to get the surface from a texture, result: 0x%X.", result);
+    }
+
+    RenderTargetD3D *sourceRenderTarget = nullptr;
+    error = mImage->getRenderTarget(&sourceRenderTarget);
+    if (error.isError())
+    {
+        SafeRelease(destSurface);
+        return error;
+    }
+
+    RenderTarget9 *sourceRenderTarget9 = GetAs<RenderTarget9>(sourceRenderTarget);
+    error =
+        mRenderer->copyToRenderTarget(destSurface, sourceRenderTarget9->getSurface(), isManaged());
+    if (error.isError())
+    {
+        SafeRelease(destSurface);
+        return error;
+    }
+
+    if (destStorage->getTopLevel() != 0)
+    {
+        destTexture9->AddDirtyRect(nullptr);
+    }
+
+    SafeRelease(destSurface);
+    return gl::NoError();
+}
+
+TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
+    : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
+{
+    mTexture = nullptr;
+    for (size_t i = 0; i < CUBE_FACE_COUNT; ++i)
+    {
+        mRenderTarget[i] = nullptr;
+    }
+
+    mInternalFormat = internalformat;
+
+    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+    mTextureFormat = d3dFormatInfo.texFormat;
+
+    int height = size;
+    d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
+    mTextureWidth = size;
+    mTextureHeight = size;
+    mMipLevels = mTopLevel + levels;
+}
+
+TextureStorage9_Cube::~TextureStorage9_Cube()
+{
+    SafeRelease(mTexture);
+
+    for (size_t i = 0; i < CUBE_FACE_COUNT; ++i)
+    {
+        SafeDelete(mRenderTarget[i]);
+    }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+gl::Error TextureStorage9_Cube::getSurfaceLevel(GLenum target,
+                                                int level,
+                                                bool dirty,
+                                                IDirect3DSurface9 **outSurface)
+{
+    IDirect3DBaseTexture9 *baseTexture = nullptr;
+    gl::Error error = getBaseTexture(&baseTexture);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9*>(baseTexture);
+
+    D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(target);
+    HRESULT result        = texture->GetCubeMapSurface(face, level, outSurface);
+
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+    }
+
+    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+    if (level != 0 && isManaged() && dirty)
+    {
+        texture->AddDirtyRect(face, nullptr);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+    ASSERT(outRT);
+    ASSERT(index.mipIndex == 0);
+    ASSERT(index.layerIndex >= 0 && static_cast<size_t>(index.layerIndex) < CUBE_FACE_COUNT);
+
+    if (mRenderTarget[index.layerIndex] == nullptr && isRenderTarget())
+    {
+        IDirect3DBaseTexture9 *baseTexture = nullptr;
+        gl::Error error = getBaseTexture(&baseTexture);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        IDirect3DSurface9 *surface = nullptr;
+        error = getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex,
+                                mTopLevel + index.mipIndex, false, &surface);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        baseTexture->AddRef();
+        mRenderTarget[index.layerIndex] = new TextureRenderTarget9(
+            baseTexture, mTopLevel + index.mipIndex, surface, mInternalFormat,
+            static_cast<GLsizei>(mTextureWidth), static_cast<GLsizei>(mTextureHeight), 1, 0);
+    }
+
+    *outRT = mRenderTarget[index.layerIndex];
+    return gl::NoError();
+}
+
+gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
+{
+    IDirect3DSurface9 *upper = nullptr;
+    gl::Error error = getSurfaceLevel(sourceIndex.type, sourceIndex.mipIndex, false, &upper);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DSurface9 *lower = nullptr;
+    error = getSurfaceLevel(destIndex.type, destIndex.mipIndex, true, &lower);
+    if (error.isError())
+    {
+        SafeRelease(upper);
+        return error;
+    }
+
+    ASSERT(upper && lower);
+    error = mRenderer->boxFilter(upper, lower);
+
+    SafeRelease(upper);
+    SafeRelease(lower);
+
+    return error;
+}
+
+gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+{
+    // if the size is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
+    {
+        ASSERT(mMipLevels > 0);
+        ASSERT(mTextureWidth == mTextureHeight);
+
+        IDirect3DDevice9 *device = mRenderer->getDevice();
+        HRESULT result           = device->CreateCubeTexture(
+            static_cast<unsigned int>(mTextureWidth), static_cast<unsigned int>(mMipLevels),
+            getUsage(), mTextureFormat, getPool(), &mTexture, nullptr);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result);
+        }
+    }
+
+    *outTexture = mTexture;
+    return gl::NoError();
+}
+
+gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage)
+{
+    ASSERT(destStorage);
+
+    TextureStorage9_Cube *dest9 = GetAs<TextureStorage9_Cube>(destStorage);
+
+    int levels = getLevelCount();
+    for (int f = 0; f < static_cast<int>(CUBE_FACE_COUNT); f++)
+    {
+        for (int i = 0; i < levels; i++)
+        {
+            IDirect3DSurface9 *srcSurf = nullptr;
+            gl::Error error =
+                getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
+            if (error.isError())
+            {
+                return error;
+            }
+
+            IDirect3DSurface9 *dstSurf = nullptr;
+            error = dest9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf);
+            if (error.isError())
+            {
+                SafeRelease(srcSurf);
+                return error;
+            }
+
+            error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
+
+            SafeRelease(srcSurf);
+            SafeRelease(dstSurf);
+
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+    }
+
+    return gl::NoError();
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
new file mode 100644
index 0000000..f0455a9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
@@ -0,0 +1,134 @@
+//
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived
+// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
+// D3D9 texture.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
+
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+#include "common/debug.h"
+
+namespace rx
+{
+class EGLImageD3D;
+class Renderer9;
+class SwapChain9;
+class RenderTargetD3D;
+class RenderTarget9;
+
+class TextureStorage9 : public TextureStorage
+{
+  public:
+    virtual ~TextureStorage9();
+
+    static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget);
+
+    D3DPOOL getPool() const;
+    DWORD getUsage() const;
+
+    virtual gl::Error getSurfaceLevel(GLenum target,
+                                      int level,
+                                      bool dirty,
+                                      IDirect3DSurface9 **outSurface) = 0;
+    virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0;
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+
+    virtual int getTopLevel() const;
+    virtual bool isRenderTarget() const;
+    virtual bool isManaged() const;
+    bool supportsNativeMipmapFunction() const override;
+    virtual int getLevelCount() const;
+
+    virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
+                              const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
+
+  protected:
+    int mTopLevel;
+    size_t mMipLevels;
+    size_t mTextureWidth;
+    size_t mTextureHeight;
+    GLenum mInternalFormat;
+    D3DFORMAT mTextureFormat;
+
+    Renderer9 *mRenderer;
+
+    TextureStorage9(Renderer9 *renderer, DWORD usage);
+
+  private:
+    const DWORD mD3DUsage;
+    const D3DPOOL mD3DPool;
+};
+
+class TextureStorage9_2D : public TextureStorage9
+{
+  public:
+    TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain);
+    TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
+    virtual ~TextureStorage9_2D();
+
+    gl::Error getSurfaceLevel(GLenum target,
+                              int level,
+                              bool dirty,
+                              IDirect3DSurface9 **outSurface) override;
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+    virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
+    virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
+    virtual gl::Error copyToStorage(TextureStorage *destStorage);
+
+  private:
+    IDirect3DTexture9 *mTexture;
+    std::vector<RenderTarget9 *> mRenderTargets;
+};
+
+class TextureStorage9_EGLImage final : public TextureStorage9
+{
+  public:
+    TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image, RenderTarget9 *renderTarget9);
+    ~TextureStorage9_EGLImage() override;
+
+    gl::Error getSurfaceLevel(GLenum target,
+                              int level,
+                              bool dirty,
+                              IDirect3DSurface9 **outSurface) override;
+    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+    gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) override;
+    gl::Error generateMipmap(const gl::ImageIndex &sourceIndex,
+                             const gl::ImageIndex &destIndex) override;
+    gl::Error copyToStorage(TextureStorage *destStorage) override;
+
+  private:
+    EGLImageD3D *mImage;
+};
+
+class TextureStorage9_Cube : public TextureStorage9
+{
+  public:
+    TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
+    virtual ~TextureStorage9_Cube();
+
+    gl::Error getSurfaceLevel(GLenum target,
+                              int level,
+                              bool dirty,
+                              IDirect3DSurface9 **outSurface) override;
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+    virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
+    virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
+    virtual gl::Error copyToStorage(TextureStorage *destStorage);
+
+  private:
+    static const size_t CUBE_FACE_COUNT = 6;
+
+    IDirect3DCubeTexture9 *mTexture;
+    RenderTarget9 *mRenderTarget[CUBE_FACE_COUNT];
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
+
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
new file mode 100644
index 0000000..28b8717
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
+
+#include "libANGLE/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+class Renderer9;
+
+class VertexArray9 : public VertexArrayImpl
+{
+  public:
+    VertexArray9(const gl::VertexArrayState &data) : VertexArrayImpl(data) {}
+
+    virtual ~VertexArray9() { }
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
new file mode 100644
index 0000000..e9c6930
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
@@ -0,0 +1,166 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/Buffer.h"
+
+namespace rx
+{
+
+VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer)
+{
+    mVertexBuffer = nullptr;
+    mBufferSize = 0;
+    mDynamicUsage = false;
+}
+
+VertexBuffer9::~VertexBuffer9()
+{
+    SafeRelease(mVertexBuffer);
+}
+
+gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
+{
+    SafeRelease(mVertexBuffer);
+
+    updateSerial();
+
+    if (size > 0)
+    {
+        DWORD flags = D3DUSAGE_WRITEONLY;
+        if (dynamicUsage)
+        {
+            flags |= D3DUSAGE_DYNAMIC;
+        }
+
+        HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
+
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
+        }
+    }
+
+    mBufferSize = size;
+    mDynamicUsage = dynamicUsage;
+    return gl::NoError();
+}
+
+gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib,
+                                               const gl::VertexBinding &binding,
+                                               GLenum currentValueType,
+                                               GLint start,
+                                               GLsizei count,
+                                               GLsizei instances,
+                                               unsigned int offset,
+                                               const uint8_t *sourceData)
+{
+    if (!mVertexBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+    }
+
+    int inputStride = static_cast<int>(gl::ComputeVertexAttributeStride(attrib, binding));
+    int elementSize = static_cast<int>(gl::ComputeVertexAttributeTypeSize(attrib));
+
+    DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
+
+    uint8_t *mapPtr = nullptr;
+
+    auto errorOrMapSize = mRenderer->getVertexSpaceRequired(attrib, binding, count, instances);
+    if (errorOrMapSize.isError())
+    {
+        return errorOrMapSize.getError();
+    }
+
+    unsigned int mapSize = errorOrMapSize.getResult();
+
+    HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void**>(&mapPtr), lockFlags);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result);
+    }
+
+    const uint8_t *input = sourceData;
+
+    if (instances == 0 || binding.divisor == 0)
+    {
+        input += inputStride * start;
+    }
+
+    gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
+    const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatType);
+    bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0;
+
+    if (!needsConversion && inputStride == elementSize)
+    {
+        size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride);
+        memcpy(mapPtr, input, copySize);
+    }
+    else
+    {
+        d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr);
+    }
+
+    mVertexBuffer->Unlock();
+
+    return gl::NoError();
+}
+
+unsigned int VertexBuffer9::getBufferSize() const
+{
+    return mBufferSize;
+}
+
+gl::Error VertexBuffer9::setBufferSize(unsigned int size)
+{
+    if (size > mBufferSize)
+    {
+        return initialize(size, mDynamicUsage);
+    }
+    else
+    {
+        return gl::NoError();
+    }
+}
+
+gl::Error VertexBuffer9::discard()
+{
+    if (!mVertexBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+    }
+
+    void *dummy;
+    HRESULT result;
+
+    result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result);
+    }
+
+    result = mVertexBuffer->Unlock();
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result);
+    }
+
+    return gl::NoError();
+}
+
+IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
+{
+    return mVertexBuffer;
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
new file mode 100644
index 0000000..983616f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
+
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+namespace rx
+{
+class Renderer9;
+
+class VertexBuffer9 : public VertexBuffer
+{
+  public:
+    explicit VertexBuffer9(Renderer9 *renderer);
+
+    gl::Error initialize(unsigned int size, bool dynamicUsage) override;
+
+    // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+    // function.
+    gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
+                                    const gl::VertexBinding &binding,
+                                    GLenum currentValueType,
+                                    GLint start,
+                                    GLsizei count,
+                                    GLsizei instances,
+                                    unsigned int offset,
+                                    const uint8_t *sourceData) override;
+
+    unsigned int getBufferSize() const override;
+    gl::Error setBufferSize(unsigned int size) override;
+    gl::Error discard() override;
+
+    IDirect3DVertexBuffer9 *getBuffer() const;
+
+  private:
+    ~VertexBuffer9() override;
+    Renderer9 *mRenderer;
+
+    IDirect3DVertexBuffer9 *mVertexBuffer;
+    unsigned int mBufferSize;
+    bool mDynamicUsage;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
new file mode 100644
index 0000000..c9555d4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
@@ -0,0 +1,256 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.
+
+#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
+
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+
+namespace rx
+{
+
+VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
+{
+    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+    {
+        mVertexDeclCache[i].vertexDeclaration = nullptr;
+        mVertexDeclCache[i].lruCount = 0;
+    }
+
+    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        mAppliedVBs[i].serial = 0;
+    }
+
+    mLastSetVDecl      = nullptr;
+    mInstancingEnabled = true;
+}
+
+VertexDeclarationCache::~VertexDeclarationCache()
+{
+    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+    {
+        SafeRelease(mVertexDeclCache[i].vertexDeclaration);
+    }
+}
+
+gl::Error VertexDeclarationCache::applyDeclaration(
+    IDirect3DDevice9 *device,
+    const std::vector<TranslatedAttribute> &attributes,
+    gl::Program *program,
+    GLint start,
+    GLsizei instances,
+    GLsizei *repeatDraw)
+{
+    ASSERT(gl::MAX_VERTEX_ATTRIBS >= attributes.size());
+
+    *repeatDraw = 1;
+
+    const size_t invalidAttribIndex = attributes.size();
+    size_t indexedAttribute = invalidAttribIndex;
+    size_t instancedAttribute = invalidAttribIndex;
+
+    if (instances == 0)
+    {
+        for (size_t i = 0; i < attributes.size(); ++i)
+        {
+            if (attributes[i].divisor != 0)
+            {
+                // If a divisor is set, it still applies even if an instanced draw was not used, so treat
+                // as a single-instance draw.
+                instances = 1;
+                break;
+            }
+        }
+    }
+
+    if (instances > 0)
+    {
+        // Find an indexed attribute to be mapped to D3D stream 0
+        for (size_t i = 0; i < attributes.size(); i++)
+        {
+            if (attributes[i].active)
+            {
+                if (indexedAttribute == invalidAttribIndex && attributes[i].divisor == 0)
+                {
+                    indexedAttribute = i;
+                }
+                else if (instancedAttribute == invalidAttribIndex && attributes[i].divisor != 0)
+                {
+                    instancedAttribute = i;
+                }
+                if (indexedAttribute != invalidAttribIndex && instancedAttribute != invalidAttribIndex)
+                    break;   // Found both an indexed and instanced attribute
+            }
+        }
+
+        // The validation layer checks that there is at least one active attribute with a zero divisor as per
+        // the GL_ANGLE_instanced_arrays spec.
+        ASSERT(indexedAttribute != invalidAttribIndex);
+    }
+
+    D3DCAPS9 caps;
+    device->GetDeviceCaps(&caps);
+
+    D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1];
+    D3DVERTEXELEMENT9 *element = &elements[0];
+
+    ProgramD3D *programD3D      = GetImplAs<ProgramD3D>(program);
+    const auto &semanticIndexes = programD3D->getAttribLocationToD3DSemantics();
+
+    for (size_t i = 0; i < attributes.size(); i++)
+    {
+        if (attributes[i].active)
+        {
+            // Directly binding the storage buffer is not supported for d3d9
+            ASSERT(attributes[i].storage == nullptr);
+
+            int stream = static_cast<int>(i);
+
+            if (instances > 0)
+            {
+                // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
+                if (instancedAttribute == invalidAttribIndex)
+                {
+                    *repeatDraw = instances;
+                }
+                else
+                {
+                    if (i == indexedAttribute)
+                    {
+                        stream = 0;
+                    }
+                    else if (i == 0)
+                    {
+                        stream = static_cast<int>(indexedAttribute);
+                    }
+
+                    UINT frequency = 1;
+                    
+                    if (attributes[i].divisor == 0)
+                    {
+                        frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
+                    }
+                    else
+                    {
+                        frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
+                    }
+                    
+                    device->SetStreamSourceFreq(stream, frequency);
+                    mInstancingEnabled = true;
+                }
+            }
+
+            VertexBuffer9 *vertexBuffer = GetAs<VertexBuffer9>(attributes[i].vertexBuffer.get());
+
+            unsigned int offset = 0;
+            ANGLE_TRY_RESULT(attributes[i].computeOffset(start), offset);
+
+            if (mAppliedVBs[stream].serial != attributes[i].serial ||
+                mAppliedVBs[stream].stride != attributes[i].stride ||
+                mAppliedVBs[stream].offset != offset)
+            {
+                device->SetStreamSource(stream, vertexBuffer->getBuffer(), offset,
+                                        attributes[i].stride);
+                mAppliedVBs[stream].serial = attributes[i].serial;
+                mAppliedVBs[stream].stride = attributes[i].stride;
+                mAppliedVBs[stream].offset = offset;
+            }
+
+            gl::VertexFormatType vertexformatType =
+                gl::GetVertexFormatType(*attributes[i].attribute, GL_FLOAT);
+            const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexformatType);
+
+            element->Stream = static_cast<WORD>(stream);
+            element->Offset = 0;
+            element->Type = static_cast<BYTE>(d3d9VertexInfo.nativeFormat);
+            element->Method = D3DDECLMETHOD_DEFAULT;
+            element->Usage = D3DDECLUSAGE_TEXCOORD;
+            element->UsageIndex = static_cast<BYTE>(semanticIndexes[i]);
+            element++;
+        }
+    }
+
+    if (instances == 0 || instancedAttribute == invalidAttribIndex)
+    {
+        if (mInstancingEnabled)
+        {
+            for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+            {
+                device->SetStreamSourceFreq(i, 1);
+            }
+
+            mInstancingEnabled = false;
+        }
+    }
+
+    static const D3DVERTEXELEMENT9 end = D3DDECL_END();
+    *(element++) = end;
+
+    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+    {
+        VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
+        if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
+        {
+            entry->lruCount = ++mMaxLru;
+            if(entry->vertexDeclaration != mLastSetVDecl)
+            {
+                device->SetVertexDeclaration(entry->vertexDeclaration);
+                mLastSetVDecl = entry->vertexDeclaration;
+            }
+
+            return gl::NoError();
+        }
+    }
+
+    VertexDeclCacheEntry *lastCache = mVertexDeclCache;
+
+    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+    {
+        if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
+        {
+            lastCache = &mVertexDeclCache[i];
+        }
+    }
+
+    if (lastCache->vertexDeclaration != nullptr)
+    {
+        SafeRelease(lastCache->vertexDeclaration);
+        // mLastSetVDecl is set to the replacement, so we don't have to worry
+        // about it.
+    }
+
+    memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
+    HRESULT result = device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal vertex declaration, result: 0x%X.", result);
+    }
+
+    device->SetVertexDeclaration(lastCache->vertexDeclaration);
+    mLastSetVDecl = lastCache->vertexDeclaration;
+    lastCache->lruCount = ++mMaxLru;
+
+    return gl::NoError();
+}
+
+void VertexDeclarationCache::markStateDirty()
+{
+    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        mAppliedVBs[i].serial = 0;
+    }
+
+    mLastSetVDecl      = nullptr;
+    mInstancingEnabled = true;   // Forces it to be disabled when not used
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
new file mode 100644
index 0000000..7bd7cab
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
@@ -0,0 +1,65 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
+
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+
+namespace gl
+{
+class VertexDataManager;
+class Program;
+}
+
+namespace rx
+{
+
+class VertexDeclarationCache
+{
+  public:
+    VertexDeclarationCache();
+    ~VertexDeclarationCache();
+
+    gl::Error applyDeclaration(IDirect3DDevice9 *device,
+                               const std::vector<TranslatedAttribute> &attributes,
+                               gl::Program *program,
+                               GLint start,
+                               GLsizei instances,
+                               GLsizei *repeatDraw);
+
+    void markStateDirty();
+
+  private:
+    UINT mMaxLru;
+
+    enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 };
+
+    struct VBData
+    {
+        unsigned int serial;
+        unsigned int stride;
+        unsigned int offset;
+    };
+
+    VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS];
+    IDirect3DVertexDeclaration9 *mLastSetVDecl;
+    bool mInstancingEnabled;
+
+    struct VertexDeclCacheEntry
+    {
+        D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1];
+        UINT lruCount;
+        IDirect3DVertexDeclaration9 *vertexDeclaration;
+    } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
new file mode 100644
index 0000000..08c26e7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
@@ -0,0 +1,660 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// formatutils9.cpp: Queries for GL image formats and their translations to D3D9
+// formats.
+
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace d3d9
+{
+
+constexpr D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z')));
+constexpr D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L')));
+
+// A map to determine the pixel size and mip generation function of a given D3D format
+typedef std::map<D3DFORMAT, D3DFormat> D3D9FormatInfoMap;
+
+constexpr D3DFormat::D3DFormat()
+    : pixelBytes(0),
+      blockWidth(0),
+      blockHeight(0),
+      redBits(0),
+      greenBits(0),
+      blueBits(0),
+      alphaBits(0),
+      luminanceBits(0),
+      depthBits(0),
+      stencilBits(0),
+      formatID(angle::Format::ID::NONE)
+{
+}
+
+constexpr D3DFormat::D3DFormat(GLuint bits,
+                               GLuint blockWidth,
+                               GLuint blockHeight,
+                               GLuint redBits,
+                               GLuint greenBits,
+                               GLuint blueBits,
+                               GLuint alphaBits,
+                               GLuint lumBits,
+                               GLuint depthBits,
+                               GLuint stencilBits,
+                               Format::ID formatID)
+    : pixelBytes(bits / 8),
+      blockWidth(blockWidth),
+      blockHeight(blockHeight),
+      redBits(redBits),
+      greenBits(greenBits),
+      blueBits(blueBits),
+      alphaBits(alphaBits),
+      luminanceBits(lumBits),
+      depthBits(depthBits),
+      stencilBits(stencilBits),
+      formatID(formatID)
+{
+}
+
+const D3DFormat &GetD3DFormatInfo(D3DFORMAT format)
+{
+    if (format == D3DFMT_NULL)
+    {
+        static constexpr D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE);
+        return info;
+    }
+
+    if (format == D3DFMT_INTZ)
+    {
+        static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8,
+                                        Format::ID::D24_UNORM_S8_UINT);
+        return info;
+    }
+
+    switch (format)
+    {
+        case D3DFMT_UNKNOWN:
+        {
+            static constexpr D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE);
+            return info;
+        }
+
+        case D3DFMT_L8:
+        {
+            static constexpr D3DFormat info(8, 1, 1, 0, 0, 0, 0, 8, 0, 0, Format::ID::L8_UNORM);
+            return info;
+        }
+        case D3DFMT_A8:
+        {
+            static constexpr D3DFormat info(8, 1, 1, 0, 0, 0, 8, 0, 0, 0, Format::ID::A8_UNORM);
+            return info;
+        }
+        case D3DFMT_A8L8:
+        {
+            static constexpr D3DFormat info(16, 1, 1, 0, 0, 0, 8, 8, 0, 0, Format::ID::L8A8_UNORM);
+            return info;
+        }
+
+        case D3DFMT_A4R4G4B4:
+        {
+            static constexpr D3DFormat info(16, 1, 1, 4, 4, 4, 4, 0, 0, 0,
+                                            Format::ID::B4G4R4A4_UNORM);
+            return info;
+        }
+        case D3DFMT_A1R5G5B5:
+        {
+            static constexpr D3DFormat info(16, 1, 1, 5, 5, 5, 1, 0, 0, 0,
+                                            Format::ID::B5G5R5A1_UNORM);
+            return info;
+        }
+        case D3DFMT_R5G6B5:
+        {
+            static constexpr D3DFormat info(16, 1, 1, 5, 6, 5, 0, 0, 0, 0,
+                                            Format::ID::R5G6B5_UNORM);
+            return info;
+        }
+        case D3DFMT_X8R8G8B8:
+        {
+            static constexpr D3DFormat info(32, 1, 1, 8, 8, 8, 0, 0, 0, 0,
+                                            Format::ID::B8G8R8X8_UNORM);
+            return info;
+        }
+        case D3DFMT_A8R8G8B8:
+        {
+            static constexpr D3DFormat info(32, 1, 1, 8, 8, 8, 8, 0, 0, 0,
+                                            Format::ID::B8G8R8A8_UNORM);
+            return info;
+        }
+
+        case D3DFMT_R16F:
+        {
+            static constexpr D3DFormat info(16, 1, 1, 16, 0, 0, 0, 0, 0, 0, Format::ID::R16_FLOAT);
+            return info;
+        }
+        case D3DFMT_G16R16F:
+        {
+            static constexpr D3DFormat info(32, 1, 1, 16, 16, 0, 0, 0, 0, 0,
+                                            Format::ID::R16G16_FLOAT);
+            return info;
+        }
+        case D3DFMT_A16B16G16R16F:
+        {
+            static constexpr D3DFormat info(64, 1, 1, 16, 16, 16, 16, 0, 0, 0,
+                                            Format::ID::R16G16B16A16_FLOAT);
+            return info;
+        }
+        case D3DFMT_R32F:
+        {
+            static constexpr D3DFormat info(32, 1, 1, 32, 0, 0, 0, 0, 0, 0, Format::ID::R32_FLOAT);
+            return info;
+        }
+        case D3DFMT_G32R32F:
+        {
+            static constexpr D3DFormat info(64, 1, 1, 32, 32, 0, 0, 0, 0, 0,
+                                            Format::ID::R32G32_FLOAT);
+            return info;
+        }
+        case D3DFMT_A32B32G32R32F:
+        {
+            static constexpr D3DFormat info(128, 1, 1, 32, 32, 32, 32, 0, 0, 0,
+                                            Format::ID::R32G32B32A32_FLOAT);
+            return info;
+        }
+
+        case D3DFMT_D16:
+        {
+            static constexpr D3DFormat info(16, 1, 1, 0, 0, 0, 0, 0, 16, 0, Format::ID::D16_UNORM);
+            return info;
+        }
+        case D3DFMT_D24S8:
+        {
+            static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8,
+                                            Format::ID::D24_UNORM_S8_UINT);
+            return info;
+        }
+        case D3DFMT_D24X8:
+        {
+            static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 0, Format::ID::D16_UNORM);
+            return info;
+        }
+        case D3DFMT_D32:
+        {
+            static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 32, 0, Format::ID::D32_UNORM);
+            return info;
+        }
+
+        case D3DFMT_DXT1:
+        {
+            static constexpr D3DFormat info(64, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+                                            Format::ID::BC1_RGBA_UNORM_BLOCK);
+            return info;
+        }
+        case D3DFMT_DXT3:
+        {
+            static constexpr D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+                                            Format::ID::BC2_RGBA_UNORM_BLOCK);
+            return info;
+        }
+        case D3DFMT_DXT5:
+        {
+            static constexpr D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+                                            Format::ID::BC3_RGBA_UNORM_BLOCK);
+            return info;
+        }
+
+        default:
+        {
+            static constexpr D3DFormat defaultInfo;
+            return defaultInfo;
+        }
+    }
+}
+
+typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitialzerPair;
+typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitialzerMap;
+
+static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap()
+{
+    using namespace angle;  // For image initialization functions
+
+    InternalFormatInitialzerMap map;
+
+    map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData<GLhalf,   0x0000,     0x0000,     0x0000,     gl::Float16One>));
+    map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData<GLfloat,  0x00000000, 0x00000000, 0x00000000, gl::Float32One>));
+
+    return map;
+}
+
+static void UnreachableLoad(size_t width, size_t height, size_t depth,
+                            const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+                            uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+    UNREACHABLE();
+}
+
+typedef std::pair<GLenum, TextureFormat> D3D9FormatPair;
+typedef std::map<GLenum, TextureFormat> D3D9FormatMap;
+
+TextureFormat::TextureFormat()
+    : texFormat(D3DFMT_UNKNOWN),
+      renderFormat(D3DFMT_UNKNOWN),
+      dataInitializerFunction(nullptr),
+      loadFunction(UnreachableLoad)
+{
+}
+
+static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalFormat, D3DFORMAT texFormat,
+                                        D3DFORMAT renderFormat, LoadImageFunction loadFunction)
+{
+    TextureFormat info;
+    info.texFormat = texFormat;
+    info.renderFormat = renderFormat;
+
+    static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap();
+    InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat);
+    info.dataInitializerFunction =
+        (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : nullptr;
+
+    info.loadFunction = loadFunction;
+
+    map->insert(std::make_pair(internalFormat, info));
+}
+
+static D3D9FormatMap BuildD3D9FormatMap()
+{
+    using namespace angle;  // For image loading functions
+
+    D3D9FormatMap map;
+
+    // clang-format off
+    //                       | Internal format                     | Texture format      | Render format        | Load function                           |
+    InsertD3D9FormatInfo(&map, GL_NONE,                             D3DFMT_NULL,          D3DFMT_NULL,           UnreachableLoad                          );
+
+    // We choose to downsample the GL_DEPTH_COMPONENT32_OES format to a 24-bit format because D3DFMT_D32 is not widely
+    // supported.  We're allowed to do this because:
+    //  - The ES spec 2.0.25 sec 3.7.1 states that we're allowed to store texture formats with internal format
+    //    resolutions of our own choosing.
+    //  - OES_depth_texture states that downsampling of the depth formats is allowed.
+    //  - ANGLE_depth_texture does not state minimum required resolutions of the depth texture formats it
+    //    introduces.
+    // In ES3 however, there are minimum resolutions for the texture formats and this would not be allowed.
+
+    InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16,                D3DFMT_INTZ,          D3DFMT_D24S8,          UnreachableLoad                          );
+    InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES,            D3DFMT_INTZ,          D3DFMT_D24X8,          UnreachableLoad                          );
+    InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES,             D3DFMT_INTZ,          D3DFMT_D24S8,          UnreachableLoad                          );
+    InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8,                   D3DFMT_UNKNOWN,       D3DFMT_D24S8,          UnreachableLoad                          ); // TODO: What's the texture format?
+
+    InsertD3D9FormatInfo(&map, GL_RGBA32F_EXT,                      D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F,  LoadToNative<GLfloat, 4>                 );
+    InsertD3D9FormatInfo(&map, GL_RGB32F_EXT,                       D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F,  LoadToNative3To4<GLfloat, gl::Float32One>);
+    InsertD3D9FormatInfo(&map, GL_RG32F_EXT,                        D3DFMT_G32R32F,       D3DFMT_G32R32F,        LoadToNative<GLfloat, 2>                 );
+    InsertD3D9FormatInfo(&map, GL_R32F_EXT,                         D3DFMT_R32F,          D3DFMT_R32F,           LoadToNative<GLfloat, 1>                 );
+    InsertD3D9FormatInfo(&map, GL_ALPHA32F_EXT,                     D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN,        LoadA32FToRGBA32F                        );
+    InsertD3D9FormatInfo(&map, GL_LUMINANCE32F_EXT,                 D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN,        LoadL32FToRGBA32F                        );
+    InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT,           D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN,        LoadLA32FToRGBA32F                       );
+
+    InsertD3D9FormatInfo(&map, GL_RGBA16F_EXT,                      D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F,  LoadToNative<GLhalf, 4>                  );
+    InsertD3D9FormatInfo(&map, GL_RGB16F_EXT,                       D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F,  LoadToNative3To4<GLhalf, gl::Float16One> );
+    InsertD3D9FormatInfo(&map, GL_RG16F_EXT,                        D3DFMT_G16R16F,       D3DFMT_G16R16F,        LoadToNative<GLhalf, 2>                  );
+    InsertD3D9FormatInfo(&map, GL_R16F_EXT,                         D3DFMT_R16F,          D3DFMT_R16F,           LoadToNative<GLhalf, 1>                  );
+    InsertD3D9FormatInfo(&map, GL_ALPHA16F_EXT,                     D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN,        LoadA16FToRGBA16F                        );
+    InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT,                 D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN,        LoadL16FToRGBA16F                        );
+    InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT,           D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN,        LoadLA16FToRGBA16F                       );
+
+    InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT,                       D3DFMT_A8R8G8B8,      D3DFMT_A8R8G8B8,       LoadA8ToBGRA8                            );
+
+    InsertD3D9FormatInfo(&map, GL_RGB8_OES,                         D3DFMT_X8R8G8B8,      D3DFMT_X8R8G8B8,       LoadRGB8ToBGRX8                           );
+    InsertD3D9FormatInfo(&map, GL_RGB565,                           D3DFMT_X8R8G8B8,      D3DFMT_X8R8G8B8,       LoadR5G6B5ToBGRA8                         );
+    InsertD3D9FormatInfo(&map, GL_RGBA8_OES,                        D3DFMT_A8R8G8B8,      D3DFMT_A8R8G8B8,       LoadRGBA8ToBGRA8                          );
+    InsertD3D9FormatInfo(&map, GL_RGBA4,                            D3DFMT_A8R8G8B8,      D3DFMT_A8R8G8B8,       LoadRGBA4ToBGRA8                          );
+    InsertD3D9FormatInfo(&map, GL_RGB5_A1,                          D3DFMT_A8R8G8B8,      D3DFMT_A8R8G8B8,       LoadRGB5A1ToBGRA8                         );
+    InsertD3D9FormatInfo(&map, GL_R8_EXT,                           D3DFMT_X8R8G8B8,      D3DFMT_X8R8G8B8,       LoadR8ToBGRX8                             );
+    InsertD3D9FormatInfo(&map, GL_RG8_EXT,                          D3DFMT_X8R8G8B8,      D3DFMT_X8R8G8B8,       LoadRG8ToBGRX8                            );
+
+    InsertD3D9FormatInfo(&map, GL_BGRA8_EXT,                        D3DFMT_A8R8G8B8,      D3DFMT_A8R8G8B8,       LoadToNative<GLubyte, 4>                  );
+    InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX,                     D3DFMT_A8R8G8B8,      D3DFMT_A8R8G8B8,       LoadBGRA4ToBGRA8                          );
+    InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX,                   D3DFMT_A8R8G8B8,      D3DFMT_A8R8G8B8,       LoadBGR5A1ToBGRA8                         );
+
+    InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,     D3DFMT_DXT1,          D3DFMT_UNKNOWN,        LoadCompressedToNative<4, 4,  8>          );
+    InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,    D3DFMT_DXT1,          D3DFMT_UNKNOWN,        LoadCompressedToNative<4, 4,  8>          );
+    InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,  D3DFMT_DXT3,          D3DFMT_UNKNOWN,        LoadCompressedToNative<4, 4, 16>          );
+    InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,  D3DFMT_DXT5,          D3DFMT_UNKNOWN,        LoadCompressedToNative<4, 4, 16>          );
+
+    // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and
+    // then changing the format and loading function appropriately.
+    InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT,                   D3DFMT_L8,            D3DFMT_UNKNOWN,        LoadToNative<GLubyte, 1>                  );
+    InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT,            D3DFMT_A8L8,          D3DFMT_UNKNOWN,        LoadToNative<GLubyte, 2>                  );
+    // clang-format on
+
+    return map;
+}
+
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat)
+{
+    static const D3D9FormatMap formatMap = BuildD3D9FormatMap();
+    D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat);
+    if (iter != formatMap.end())
+    {
+        return iter->second;
+    }
+    else
+    {
+        static const TextureFormat defaultInfo;
+        return defaultInfo;
+    }
+}
+
+static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType)
+{
+    switch (declType)
+    {
+      case D3DDECLTYPE_FLOAT1:   return GL_FLOAT;
+      case D3DDECLTYPE_FLOAT2:   return GL_FLOAT;
+      case D3DDECLTYPE_FLOAT3:   return GL_FLOAT;
+      case D3DDECLTYPE_FLOAT4:   return GL_FLOAT;
+      case D3DDECLTYPE_UBYTE4:   return GL_UNSIGNED_INT;
+      case D3DDECLTYPE_SHORT2:   return GL_INT;
+      case D3DDECLTYPE_SHORT4:   return GL_INT;
+      case D3DDECLTYPE_UBYTE4N:  return GL_UNSIGNED_NORMALIZED;
+      case D3DDECLTYPE_SHORT4N:  return GL_SIGNED_NORMALIZED;
+      case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED;
+      case D3DDECLTYPE_SHORT2N:  return GL_SIGNED_NORMALIZED;
+      case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED;
+      default: UNREACHABLE();    return GL_NONE;
+    }
+}
+
+// Attribute format conversion
+enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
+
+struct TranslationDescription
+{
+    DWORD capsFlag;
+    VertexFormat preferredConversion;
+    VertexFormat fallbackConversion;
+};
+
+// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
+//
+// BYTE                 SHORT (Cast)
+// BYTE-norm            FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
+// UNSIGNED_BYTE        UBYTE4 (Identity) or SHORT (Cast)
+// UNSIGNED_BYTE-norm   UBYTE4N (Identity) or FLOAT (Normalize)
+// SHORT                SHORT (Identity)
+// SHORT-norm           SHORT-norm (Identity) or FLOAT (Normalize)
+// UNSIGNED_SHORT       FLOAT (Cast)
+// UNSIGNED_SHORT-norm  USHORT-norm (Identity) or FLOAT (Normalize)
+// FIXED (not in WebGL) FLOAT (FixedToFloat)
+// FLOAT                FLOAT (Identity)
+
+// GLToCType maps from GL type (as GLenum) to the C typedef.
+template <GLenum GLType> struct GLToCType { };
+
+template <> struct GLToCType<GL_BYTE>           { typedef GLbyte type;      };
+template <> struct GLToCType<GL_UNSIGNED_BYTE>  { typedef GLubyte type;     };
+template <> struct GLToCType<GL_SHORT>          { typedef GLshort type;     };
+template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type;    };
+template <> struct GLToCType<GL_FIXED>          { typedef GLuint type;      };
+template <> struct GLToCType<GL_FLOAT>          { typedef GLfloat type;     };
+
+// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
+enum D3DVertexType
+{
+    D3DVT_FLOAT,
+    D3DVT_SHORT,
+    D3DVT_SHORT_NORM,
+    D3DVT_UBYTE,
+    D3DVT_UBYTE_NORM,
+    D3DVT_USHORT_NORM
+};
+
+// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
+template <unsigned int D3DType> struct D3DToCType { };
+
+template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
+template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
+template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
+template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
+
+// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
+template <unsigned int type, int size> struct WidenRule { };
+
+template <int size> struct WidenRule<D3DVT_FLOAT, size>          : NoWiden<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT, size>          : WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT_NORM, size>     : WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE, size>          : WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size>     : WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_USHORT_NORM, size>    : WidenToEven<size> { };
+
+// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
+template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
+
+template <unsigned int _capflag, unsigned int _declflag>
+struct VertexTypeFlagsHelper
+{
+    enum { capflag = _capflag };
+    enum { declflag = _declflag };
+};
+
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
+
+
+// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
+template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
+
+template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
+struct VertexTypeMappingBase
+{
+    enum { preferred = Preferred };
+    enum { fallback = Fallback };
+};
+
+template <> struct VertexTypeMapping<GL_BYTE, false>                        : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Cast
+template <> struct VertexTypeMapping<GL_BYTE, true>                         : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false>               : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { };          // Identity, Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true>                : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { };     // Identity, Normalize
+template <> struct VertexTypeMapping<GL_SHORT, false>                       : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Identity
+template <> struct VertexTypeMapping<GL_SHORT, true>                        : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { };     // Cast, Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false>              : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true>               : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { };    // Cast, Normalize
+template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // FixedToFloat
+template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Identity
+
+
+// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
+// The conversion rules themselves are defined in vertexconversion.h.
+
+// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
+template <GLenum fromType, bool normalized, unsigned int toType>
+struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
+
+// All conversions from normalized types to float use the Normalize operator.
+template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
+
+// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
+template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT>  : FixedToFloat<GLint, 16> { };
+template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
+
+// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
+// whether it is normalized or not.
+template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
+
+template <class T> struct DefaultVertexValuesStage2<T, true>  : NormalizedDefaultValues<T> { };
+template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
+
+// Work out the default value rule for a D3D type (expressed as the C type) and
+template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
+template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
+
+// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
+// The fallback conversion produces an output that all D3D9 devices must support.
+template <class T> struct UsePreferred { enum { type = T::preferred }; };
+template <class T> struct UseFallback { enum { type = T::fallback }; };
+
+// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
+// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
+// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
+template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
+struct Converter
+    : VertexDataConverter<
+          typename GLToCType<fromType>::type,
+          WidenRule<PreferenceRule<VertexTypeMapping<fromType, normalized>>::type, size>,
+          ConversionRule<fromType,
+                         normalized,
+                         PreferenceRule<VertexTypeMapping<fromType, normalized>>::type>,
+          DefaultVertexValues<typename D3DToCType<PreferenceRule<
+                                  VertexTypeMapping<fromType, normalized>>::type>::type,
+                              normalized>>
+{
+private:
+  enum
+  {
+      d3dtype = PreferenceRule<VertexTypeMapping<fromType, normalized>>::type
+  };
+  enum
+  {
+      d3dsize = WidenRule<d3dtype, size>::finalWidth
+  };
+
+public:
+    enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
+    enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
+};
+
+VertexFormat::VertexFormat()
+    : conversionType(VERTEX_CONVERT_NONE),
+      outputElementSize(0),
+      copyFunction(nullptr),
+      nativeFormat(D3DDECLTYPE_UNUSED),
+      componentType(GL_NONE)
+{
+}
+
+// Initialize a TranslationInfo
+VertexFormat CreateVertexFormatInfo(bool identity, size_t elementSize, VertexCopyFunction copyFunc, D3DDECLTYPE nativeFormat)
+{
+    VertexFormat formatInfo;
+    formatInfo.conversionType = identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU;
+    formatInfo.outputElementSize = elementSize;
+    formatInfo.copyFunction = copyFunc;
+    formatInfo.nativeFormat = nativeFormat;
+    formatInfo.componentType = GetDeclTypeComponentType(nativeFormat);
+    return formatInfo;
+}
+
+#define TRANSLATION(type, norm, size, preferred)                                    \
+    CreateVertexFormatInfo                                                          \
+    (                                                                               \
+        Converter<type, norm, size, preferred>::identity,                           \
+        Converter<type, norm, size, preferred>::finalSize,                          \
+        Converter<type, norm, size, preferred>::convertArray,                       \
+        static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag)  \
+    )
+
+#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size)    \
+    {                                                       \
+        Converter<type, norm, size, UsePreferred>::capflag, \
+        TRANSLATION(type, norm, size, UsePreferred),        \
+        TRANSLATION(type, norm, size, UseFallback)          \
+    }
+
+#define TRANSLATIONS_FOR_TYPE(type)                                                                                                                                                                         \
+    {                                                                                                                                                                                                       \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) },     \
+    }
+
+#define TRANSLATIONS_FOR_TYPE_NO_NORM(type)                                                                                                                                                                 \
+    {                                                                                                                                                                                                       \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+    }
+
+static inline unsigned int ComputeTypeIndex(GLenum type)
+{
+    switch (type)
+    {
+      case GL_BYTE:           return 0;
+      case GL_UNSIGNED_BYTE:  return 1;
+      case GL_SHORT:          return 2;
+      case GL_UNSIGNED_SHORT: return 3;
+      case GL_FIXED:          return 4;
+      case GL_FLOAT:          return 5;
+
+      default: UNREACHABLE(); return 5;
+    }
+}
+
+const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, gl::VertexFormatType vertexFormatType)
+{
+    static bool initialized = false;
+    static DWORD initializedDeclTypes = 0;
+    static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
+    if (initializedDeclTypes != supportedDeclTypes)
+    {
+        const TranslationDescription translations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
+        {
+            TRANSLATIONS_FOR_TYPE(GL_BYTE),
+            TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
+            TRANSLATIONS_FOR_TYPE(GL_SHORT),
+            TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
+            TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
+            TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
+        };
+        for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
+        {
+            for (unsigned int j = 0; j < 2; j++)
+            {
+                for (unsigned int k = 0; k < 4; k++)
+                {
+                    if (translations[i][j][k].capsFlag == 0 || (supportedDeclTypes & translations[i][j][k].capsFlag) != 0)
+                    {
+                        formatConverters[i][j][k] = translations[i][j][k].preferredConversion;
+                    }
+                    else
+                    {
+                        formatConverters[i][j][k] = translations[i][j][k].fallbackConversion;
+                    }
+                }
+            }
+        }
+        initialized = true;
+        initializedDeclTypes = supportedDeclTypes;
+    }
+
+    const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType);
+
+    // Pure integer attributes only supported in ES3.0
+    ASSERT(!vertexFormat.pureInteger);
+    return formatConverters[ComputeTypeIndex(vertexFormat.type)][vertexFormat.normalized][vertexFormat.components - 1];
+}
+
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
new file mode 100644
index 0000000..828252d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// formatutils9.h: Queries for GL image formats and their translations to D3D9
+// formats.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
+
+#include <map>
+
+#include "common/platform.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+
+namespace rx
+{
+
+class Renderer9;
+
+namespace d3d9
+{
+
+struct D3DFormat
+{
+    constexpr D3DFormat();
+    constexpr D3DFormat(GLuint pixelBytes,
+                        GLuint blockWidth,
+                        GLuint blockHeight,
+                        GLuint redBits,
+                        GLuint greenBits,
+                        GLuint blueBits,
+                        GLuint alphaBits,
+                        GLuint luminanceBits,
+                        GLuint depthBits,
+                        GLuint stencilBits,
+                        angle::Format::ID formatID);
+
+    const angle::Format &info() const { return angle::Format::Get(formatID); }
+
+    GLuint pixelBytes;
+    GLuint blockWidth;
+    GLuint blockHeight;
+
+    GLuint redBits;
+    GLuint greenBits;
+    GLuint blueBits;
+    GLuint alphaBits;
+    GLuint luminanceBits;
+
+    GLuint depthBits;
+    GLuint stencilBits;
+
+    angle::Format::ID formatID;
+};
+
+const D3DFormat &GetD3DFormatInfo(D3DFORMAT format);
+
+struct VertexFormat
+{
+    VertexFormat();
+
+    VertexConversionType conversionType;
+    size_t outputElementSize;
+    VertexCopyFunction copyFunction;
+    D3DDECLTYPE nativeFormat;
+    GLenum componentType;
+};
+const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, gl::VertexFormatType vertexFormatType);
+
+struct TextureFormat
+{
+    TextureFormat();
+
+    D3DFORMAT texFormat;
+    D3DFORMAT renderFormat;
+
+    InitializeTextureDataFunction dataInitializerFunction;
+
+    LoadImageFunction loadFunction;
+};
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat);
+
+}
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
new file mode 100644
index 0000000..bed71ac
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -0,0 +1,667 @@
+//
+// 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.
+//
+
+// renderer9_utils.cpp: Conversion functions and other utility routines
+// specific to the D3D9 renderer.
+
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+#include "common/mathutil.h"
+#include "common/debug.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "platform/Platform.h"
+#include "platform/WorkaroundsD3D.h"
+
+#include "third_party/systeminfo/SystemInfo.h"
+
+namespace rx
+{
+
+namespace gl_d3d9
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison)
+{
+    D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
+    switch (comparison)
+    {
+      case GL_NEVER:    d3dComp = D3DCMP_NEVER;        break;
+      case GL_ALWAYS:   d3dComp = D3DCMP_ALWAYS;       break;
+      case GL_LESS:     d3dComp = D3DCMP_LESS;         break;
+      case GL_LEQUAL:   d3dComp = D3DCMP_LESSEQUAL;    break;
+      case GL_EQUAL:    d3dComp = D3DCMP_EQUAL;        break;
+      case GL_GREATER:  d3dComp = D3DCMP_GREATER;      break;
+      case GL_GEQUAL:   d3dComp = D3DCMP_GREATEREQUAL; break;
+      case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL;     break;
+      default: UNREACHABLE();
+    }
+
+    return d3dComp;
+}
+
+D3DCOLOR ConvertColor(gl::ColorF color)
+{
+    return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
+                         gl::unorm<8>(color.green),
+                         gl::unorm<8>(color.blue),
+                         gl::unorm<8>(color.alpha));
+}
+
+D3DBLEND ConvertBlendFunc(GLenum blend)
+{
+    D3DBLEND d3dBlend = D3DBLEND_ZERO;
+
+    switch (blend)
+    {
+      case GL_ZERO:                     d3dBlend = D3DBLEND_ZERO;           break;
+      case GL_ONE:                      d3dBlend = D3DBLEND_ONE;            break;
+      case GL_SRC_COLOR:                d3dBlend = D3DBLEND_SRCCOLOR;       break;
+      case GL_ONE_MINUS_SRC_COLOR:      d3dBlend = D3DBLEND_INVSRCCOLOR;    break;
+      case GL_DST_COLOR:                d3dBlend = D3DBLEND_DESTCOLOR;      break;
+      case GL_ONE_MINUS_DST_COLOR:      d3dBlend = D3DBLEND_INVDESTCOLOR;   break;
+      case GL_SRC_ALPHA:                d3dBlend = D3DBLEND_SRCALPHA;       break;
+      case GL_ONE_MINUS_SRC_ALPHA:      d3dBlend = D3DBLEND_INVSRCALPHA;    break;
+      case GL_DST_ALPHA:                d3dBlend = D3DBLEND_DESTALPHA;      break;
+      case GL_ONE_MINUS_DST_ALPHA:      d3dBlend = D3DBLEND_INVDESTALPHA;   break;
+      case GL_CONSTANT_COLOR:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
+      case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+      case GL_CONSTANT_ALPHA:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
+      case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+      case GL_SRC_ALPHA_SATURATE:       d3dBlend = D3DBLEND_SRCALPHASAT;    break;
+      default: UNREACHABLE();
+    }
+
+    return d3dBlend;
+}
+
+D3DBLENDOP ConvertBlendOp(GLenum blendOp)
+{
+    D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
+
+    switch (blendOp)
+    {
+      case GL_FUNC_ADD:              d3dBlendOp = D3DBLENDOP_ADD;         break;
+      case GL_FUNC_SUBTRACT:         d3dBlendOp = D3DBLENDOP_SUBTRACT;    break;
+      case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
+      case GL_MIN_EXT:               d3dBlendOp = D3DBLENDOP_MIN;         break;
+      case GL_MAX_EXT:               d3dBlendOp = D3DBLENDOP_MAX;         break;
+      default: UNREACHABLE();
+    }
+
+    return d3dBlendOp;
+}
+
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
+{
+    D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
+
+    switch (stencilOp)
+    {
+      case GL_ZERO:      d3dStencilOp = D3DSTENCILOP_ZERO;    break;
+      case GL_KEEP:      d3dStencilOp = D3DSTENCILOP_KEEP;    break;
+      case GL_REPLACE:   d3dStencilOp = D3DSTENCILOP_REPLACE; break;
+      case GL_INCR:      d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
+      case GL_DECR:      d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
+      case GL_INVERT:    d3dStencilOp = D3DSTENCILOP_INVERT;  break;
+      case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR;    break;
+      case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR;    break;
+      default: UNREACHABLE();
+    }
+
+    return d3dStencilOp;
+}
+
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
+{
+    D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
+
+    switch (wrap)
+    {
+      case GL_REPEAT:            d3dWrap = D3DTADDRESS_WRAP;   break;
+      case GL_CLAMP_TO_EDGE:     d3dWrap = D3DTADDRESS_CLAMP;  break;
+      case GL_MIRRORED_REPEAT:   d3dWrap = D3DTADDRESS_MIRROR; break;
+      default: UNREACHABLE();
+    }
+
+    return d3dWrap;
+}
+
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
+{
+    D3DCULL cull = D3DCULL_CCW;
+    switch (cullFace)
+    {
+      case GL_FRONT:
+        cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
+        break;
+      case GL_BACK:
+        cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
+        break;
+      case GL_FRONT_AND_BACK:
+        cull = D3DCULL_NONE; // culling will be handled during draw
+        break;
+      default: UNREACHABLE();
+    }
+
+    return cull;
+}
+
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
+{
+    D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
+
+    switch (cubeFace)
+    {
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+        face = D3DCUBEMAP_FACE_POSITIVE_X;
+        break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+        face = D3DCUBEMAP_FACE_NEGATIVE_X;
+        break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+        face = D3DCUBEMAP_FACE_POSITIVE_Y;
+        break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+        face = D3DCUBEMAP_FACE_NEGATIVE_Y;
+        break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+        face = D3DCUBEMAP_FACE_POSITIVE_Z;
+        break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+        face = D3DCUBEMAP_FACE_NEGATIVE_Z;
+        break;
+      default: UNREACHABLE();
+    }
+
+    return face;
+}
+
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+    return (red   ? D3DCOLORWRITEENABLE_RED   : 0) |
+           (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
+           (blue  ? D3DCOLORWRITEENABLE_BLUE  : 0) |
+           (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
+}
+
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
+{
+    if (maxAnisotropy > 1.0f)
+    {
+        return D3DTEXF_ANISOTROPIC;
+    }
+
+    D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
+    switch (magFilter)
+    {
+      case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT;  break;
+      case GL_LINEAR:  d3dMagFilter = D3DTEXF_LINEAR; break;
+      default: UNREACHABLE();
+    }
+
+    return d3dMagFilter;
+}
+
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter,
+                      float *d3dLodBias, float maxAnisotropy, size_t baseLevel)
+{
+    switch (minFilter)
+    {
+      case GL_NEAREST:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_NONE;
+        break;
+      case GL_LINEAR:
+        *d3dMinFilter = D3DTEXF_LINEAR;
+        *d3dMipFilter = D3DTEXF_NONE;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_POINT;
+        break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+        *d3dMinFilter = D3DTEXF_LINEAR;
+        *d3dMipFilter = D3DTEXF_POINT;
+        break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_LINEAR;
+        break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+        *d3dMinFilter = D3DTEXF_LINEAR;
+        *d3dMipFilter = D3DTEXF_LINEAR;
+        break;
+      default:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_NONE;
+        UNREACHABLE();
+    }
+
+    // Disabling mipmapping will always sample from level 0 of the texture. It is possible to work
+    // around this by modifying D3DSAMP_MAXMIPLEVEL to force a specific mip level to become the
+    // lowest sampled mip level and using a large negative value for D3DSAMP_MIPMAPLODBIAS to
+    // ensure that only the base mip level is sampled.
+    if (baseLevel > 0 && *d3dMipFilter == D3DTEXF_NONE)
+    {
+        *d3dMipFilter = D3DTEXF_POINT;
+        *d3dLodBias = -static_cast<float>(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    }
+    else
+    {
+        *d3dLodBias = 0.0f;
+    }
+
+    if (maxAnisotropy > 1.0f)
+    {
+        *d3dMinFilter = D3DTEXF_ANISOTROPIC;
+    }
+}
+
+D3DQUERYTYPE ConvertQueryType(GLenum queryType)
+{
+    switch (queryType)
+    {
+        case GL_ANY_SAMPLES_PASSED_EXT:
+        case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+            return D3DQUERYTYPE_OCCLUSION;
+        case GL_COMMANDS_COMPLETED_CHROMIUM:
+            return D3DQUERYTYPE_EVENT;
+        default:
+            UNREACHABLE();
+            return static_cast<D3DQUERYTYPE>(0);
+    }
+}
+
+D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples)
+{
+    return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE;
+}
+
+}
+
+namespace d3d9_gl
+{
+
+unsigned int GetReservedVertexUniformVectors()
+{
+    return 3;  // dx_ViewCoords, dx_ViewAdjust and dx_DepthRange.
+}
+
+unsigned int GetReservedFragmentUniformVectors()
+{
+    return 3;  // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
+}
+
+GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type)
+{
+    return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0;
+}
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
+{
+    GLenum internalFormat  = d3d9::GetD3DFormatInfo(d3dformat).info().glInternalFormat;
+    GLenum convertedFormat = gl::GetSizedInternalFormatInfo(internalFormat).format;
+    return convertedFormat == format;
+}
+
+static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType,
+                                                 UINT adapter, D3DFORMAT adapterFormat)
+{
+    gl::TextureCaps textureCaps;
+
+    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
+    const gl::InternalFormat &formatInfo     = gl::GetSizedInternalFormatInfo(internalFormat);
+
+    if (d3dFormatInfo.texFormat != D3DFMT_UNKNOWN)
+    {
+        if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+        {
+            textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
+        }
+        else
+        {
+            textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) &&
+                                     SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat));
+        }
+
+        textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
+    }
+
+    if (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN)
+    {
+        textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
+
+        if ((formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) && !textureCaps.renderable)
+        {
+            textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
+        }
+
+        textureCaps.sampleCounts.insert(1);
+        for (unsigned int i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++)
+        {
+            D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i);
+
+            HRESULT result = d3d9->CheckDeviceMultiSampleType(
+                adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, nullptr);
+            if (SUCCEEDED(result))
+            {
+                textureCaps.sampleCounts.insert(i);
+            }
+        }
+    }
+
+    return textureCaps;
+}
+
+void GenerateCaps(IDirect3D9 *d3d9,
+                  IDirect3DDevice9 *device,
+                  D3DDEVTYPE deviceType,
+                  UINT adapter,
+                  gl::Caps *caps,
+                  gl::TextureCapsMap *textureCapsMap,
+                  gl::Extensions *extensions,
+                  gl::Limitations *limitations)
+{
+    D3DCAPS9 deviceCaps;
+    if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps)))
+    {
+        // Can't continue with out device caps
+        return;
+    }
+
+    D3DDISPLAYMODE currentDisplayMode;
+    d3d9->GetAdapterDisplayMode(adapter, &currentDisplayMode);
+
+    GLuint maxSamples = 0;
+    for (GLenum internalFormat : gl::GetAllSizedInternalFormats())
+    {
+        gl::TextureCaps textureCaps = GenerateTextureFormatCaps(internalFormat, d3d9, deviceType,
+                                                                adapter, currentDisplayMode.Format);
+        textureCapsMap->insert(internalFormat, textureCaps);
+
+        maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
+
+        if (gl::GetSizedInternalFormatInfo(internalFormat).compressed)
+        {
+            caps->compressedTextureFormats.push_back(internalFormat);
+        }
+    }
+
+    // GL core feature limits
+    caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+
+    // 3D textures are unimplemented in D3D9
+    caps->max3DTextureSize = 1;
+
+    // Only one limit in GL, use the minimum dimension
+    caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight);
+
+    // D3D treats cube maps as a special case of 2D textures
+    caps->maxCubeMapTextureSize = caps->max2DTextureSize;
+
+    // Array textures are not available in D3D9
+    caps->maxArrayTextureLayers = 1;
+
+    // ES3-only feature
+    caps->maxLODBias = 0.0f;
+
+    // No specific limits on render target size, maximum 2D texture size is equivalent
+    caps->maxRenderbufferSize = caps->max2DTextureSize;
+
+    // Draw buffers are not supported in D3D9
+    caps->maxDrawBuffers = 1;
+    caps->maxColorAttachments = 1;
+
+    // No specific limits on viewport size, maximum 2D texture size is equivalent
+    caps->maxViewportWidth = caps->max2DTextureSize;
+    caps->maxViewportHeight = caps->maxViewportWidth;
+
+    // Point size is clamped to 1.0f when the shader model is less than 3
+    caps->minAliasedPointSize = 1.0f;
+    caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f);
+
+    // Wide lines not supported
+    caps->minAliasedLineWidth = 1.0f;
+    caps->maxAliasedLineWidth = 1.0f;
+
+    // Primitive count limits (unused in ES2)
+    caps->maxElementsIndices = 0;
+    caps->maxElementsVertices = 0;
+
+    // Program and shader binary formats (no supported shader binary formats)
+    caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
+
+    caps->vertexHighpFloat.setIEEEFloat();
+    caps->vertexMediumpFloat.setIEEEFloat();
+    caps->vertexLowpFloat.setIEEEFloat();
+    caps->fragmentHighpFloat.setIEEEFloat();
+    caps->fragmentMediumpFloat.setIEEEFloat();
+    caps->fragmentLowpFloat.setIEEEFloat();
+
+    // Some (most) hardware only supports single-precision floating-point numbers,
+    // which can accurately represent integers up to +/-16777216
+    caps->vertexHighpInt.setSimulatedInt(24);
+    caps->vertexMediumpInt.setSimulatedInt(24);
+    caps->vertexLowpInt.setSimulatedInt(24);
+    caps->fragmentHighpInt.setSimulatedInt(24);
+    caps->fragmentMediumpInt.setSimulatedInt(24);
+    caps->fragmentLowpInt.setSimulatedInt(24);
+
+    // WaitSync is ES3-only, set to zero
+    caps->maxServerWaitTimeout = 0;
+
+    // Vertex shader limits
+    caps->maxVertexAttributes = 16;
+    // Vertex Attrib Binding not supported.
+    caps->maxVertexAttribBindings = caps->maxVertexAttributes;
+
+    const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256;
+    caps->maxVertexUniformVectors =
+        MAX_VERTEX_CONSTANT_VECTORS_D3D9 - GetReservedVertexUniformVectors();
+    caps->maxVertexUniformComponents = caps->maxVertexUniformVectors * 4;
+
+    caps->maxVertexUniformBlocks = 0;
+
+    // SM3 only supports 11 output variables, with a special 12th register for PSIZE.
+    const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 9;
+    const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 7;
+    caps->maxVertexOutputComponents = ((deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) ? MAX_VERTEX_OUTPUT_VECTORS_SM3
+                                                                                               : MAX_VERTEX_OUTPUT_VECTORS_SM2) * 4;
+
+    // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
+    // We test this using D3D9 by checking support for the R16F format.
+    if (deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0) &&
+        SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, currentDisplayMode.Format,
+                                          D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)))
+    {
+        const size_t MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4;
+        caps->maxVertexTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS_VTF_SM3;
+    }
+    else
+    {
+        caps->maxVertexTextureImageUnits = 0;
+    }
+
+    // Fragment shader limits
+    const size_t MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224;
+    const size_t MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32;
+    caps->maxFragmentUniformVectors =
+        ((deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) ? MAX_PIXEL_CONSTANT_VECTORS_SM3
+                                                                : MAX_PIXEL_CONSTANT_VECTORS_SM2) -
+        GetReservedFragmentUniformVectors();
+    caps->maxFragmentUniformComponents = caps->maxFragmentUniformVectors * 4;
+    caps->maxFragmentUniformBlocks = 0;
+    caps->maxFragmentInputComponents = caps->maxVertexOutputComponents;
+    caps->maxTextureImageUnits = 16;
+    caps->minProgramTexelOffset = 0;
+    caps->maxProgramTexelOffset = 0;
+
+    // Aggregate shader limits (unused in ES2)
+    caps->maxUniformBufferBindings = 0;
+    caps->maxUniformBlockSize = 0;
+    caps->uniformBufferOffsetAlignment = 0;
+    caps->maxCombinedUniformBlocks = 0;
+    caps->maxCombinedVertexUniformComponents = 0;
+    caps->maxCombinedFragmentUniformComponents = 0;
+    caps->maxVaryingComponents = 0;
+
+    // Aggregate shader limits
+    caps->maxVaryingVectors = caps->maxVertexOutputComponents / 4;
+    caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
+
+    // Transform feedback limits
+    caps->maxTransformFeedbackInterleavedComponents = 0;
+    caps->maxTransformFeedbackSeparateAttributes = 0;
+    caps->maxTransformFeedbackSeparateComponents = 0;
+
+    // Multisample limits
+    caps->maxSamples = maxSamples;
+
+    // GL extension support
+    extensions->setTextureExtensionSupport(*textureCapsMap);
+    extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16);
+    extensions->getProgramBinary = true;
+    extensions->rgb8rgba8 = true;
+    extensions->readFormatBGRA = true;
+    extensions->pixelBufferObject = false;
+    extensions->mapBuffer = false;
+    extensions->mapBufferRange = false;
+
+    // textureRG is emulated and not performant.
+    extensions->textureRG = false;
+
+    D3DADAPTER_IDENTIFIER9 adapterId = {};
+    if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId)))
+    {
+        // ATI cards on XP have problems with non-power-of-two textures.
+        extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
+                                  !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
+                                  !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
+                                  !(!isWindowsVistaOrGreater() && IsAMD(adapterId.VendorId));
+
+        // Disable depth texture support on AMD cards (See ANGLE issue 839)
+        if (IsAMD(adapterId.VendorId))
+        {
+            extensions->depthTextures = false;
+        }
+    }
+    else
+    {
+        extensions->textureNPOT = false;
+    }
+
+    extensions->drawBuffers = false;
+    extensions->textureStorage = true;
+
+    // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
+    extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2;
+    extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy);
+
+    // Check occlusion query support by trying to create one
+    IDirect3DQuery9 *occlusionQuery = nullptr;
+    extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery;
+    SafeRelease(occlusionQuery);
+
+    // Check event query support by trying to create one
+    IDirect3DQuery9 *eventQuery = nullptr;
+    extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery;
+    SafeRelease(eventQuery);
+
+    extensions->timerQuery = false; // Unimplemented
+    extensions->disjointTimerQuery     = false;
+    extensions->robustness = true;
+    extensions->blendMinMax = true;
+    extensions->framebufferBlit = true;
+    extensions->framebufferMultisample = true;
+    extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+    extensions->packReverseRowOrder = true;
+    extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
+    extensions->shaderTextureLOD = true;
+    extensions->fragDepth = true;
+    extensions->textureUsage = true;
+    extensions->translatedShaderSource = true;
+    extensions->fboRenderMipmap = false;
+    extensions->discardFramebuffer = false; // It would be valid to set this to true, since glDiscardFramebufferEXT is just a hint
+    extensions->colorBufferFloat = false;
+    extensions->debugMarker = true;
+    extensions->eglImage               = true;
+    extensions->eglImageExternal       = true;
+    extensions->unpackSubimage         = true;
+    extensions->packSubimage           = true;
+    extensions->syncQuery              = extensions->fence;
+    extensions->copyTexture            = true;
+
+    // D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil
+    // state.
+    limitations->noSeparateStencilRefsAndMasks = true;
+
+    // D3D9 shader models have limited support for looping, so the Appendix A
+    // index/loop limitations are necessary. Workarounds that are needed to
+    // support dynamic indexing of vectors on HLSL also don't work on D3D9.
+    limitations->shadersRequireIndexedLoopValidation = true;
+
+    // D3D9 cannot support constant color and alpha blend funcs together
+    limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true;
+}
+
+}
+
+namespace d3d9
+{
+
+GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height)
+{
+    const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format);
+    GLuint numBlocksWide = (width + d3dFormatInfo.blockWidth - 1) / d3dFormatInfo.blockWidth;
+    GLuint numBlocksHight = (height + d3dFormatInfo.blockHeight - 1) / d3dFormatInfo.blockHeight;
+    return (d3dFormatInfo.pixelBytes * numBlocksWide * numBlocksHight);
+}
+
+void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
+{
+    const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format);
+
+    int upsampleCount = 0;
+    // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
+    if (isImage || *requestWidth < static_cast<GLsizei>(d3dFormatInfo.blockWidth) ||
+        *requestHeight < static_cast<GLsizei>(d3dFormatInfo.blockHeight))
+    {
+        while (*requestWidth % d3dFormatInfo.blockWidth != 0 || *requestHeight % d3dFormatInfo.blockHeight != 0)
+        {
+            *requestWidth <<= 1;
+            *requestHeight <<= 1;
+            upsampleCount++;
+        }
+    }
+    *levelOffset = upsampleCount;
+}
+
+angle::WorkaroundsD3D GenerateWorkarounds()
+{
+    angle::WorkaroundsD3D workarounds;
+    workarounds.mrtPerfWorkaround = true;
+    workarounds.setDataFasterThanImageUpload = false;
+    workarounds.useInstancedPointSpriteEmulation = false;
+
+    // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
+    workarounds.expandIntegerPowExpressions = true;
+
+    // Call platform hooks for testing overrides.
+    auto *platform = ANGLEPlatformCurrent();
+    platform->overrideWorkaroundsD3D(platform, &workarounds);
+
+    return workarounds;
+}
+
+}  // namespace d3d9
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
new file mode 100644
index 0000000..eaf3108
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
@@ -0,0 +1,95 @@
+//
+// 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.
+//
+
+// renderer9_utils.h: Conversion functions and other utility routines
+// specific to the D3D9 renderer
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
+
+#include "common/Color.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "platform/WorkaroundsD3D.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+class RenderTarget9;
+
+namespace gl_d3d9
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison);
+D3DCOLOR ConvertColor(gl::ColorF color);
+D3DBLEND ConvertBlendFunc(GLenum blend);
+D3DBLENDOP ConvertBlendOp(GLenum blendOp);
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace);
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace);
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy);
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter,
+                      float *d3dLodBias, float maxAnisotropy, size_t baseLevel);
+D3DQUERYTYPE ConvertQueryType(GLenum queryType);
+
+D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples);
+
+}
+
+namespace d3d9_gl
+{
+
+unsigned int GetReservedVertexUniformVectors();
+
+unsigned int GetReservedFragmentUniformVectors();
+
+GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type);
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format);
+
+void GenerateCaps(IDirect3D9 *d3d9,
+                  IDirect3DDevice9 *device,
+                  D3DDEVTYPE deviceType,
+                  UINT adapter,
+                  gl::Caps *caps,
+                  gl::TextureCapsMap *textureCapsMap,
+                  gl::Extensions *extensions,
+                  gl::Limitations *limitations);
+}
+
+namespace d3d9
+{
+
+GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height);
+
+void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset);
+
+inline bool isDeviceLostError(HRESULT errorCode)
+{
+    switch (errorCode)
+    {
+      case D3DERR_DRIVERINTERNALERROR:
+      case D3DERR_DEVICELOST:
+      case D3DERR_DEVICEHUNG:
+      case D3DERR_DEVICEREMOVED:
+        return true;
+      default:
+        return false;
+    }
+}
+
+angle::WorkaroundsD3D GenerateWorkarounds();
+}
+
+}  // namespace d3d9
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
new file mode 100644
index 0000000..0c565c3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
@@ -0,0 +1,67 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+sampler2D tex : s0;
+
+uniform float4 mult : c0;
+uniform float4 add  : c1;
+
+// Passthrough Pixel Shader
+// Outputs texture 0 sampled at texcoord 0.
+float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR
+{
+    return tex2D(tex, texcoord.xy);
+};
+
+// Luminance Conversion Pixel Shader
+// Performs a mad operation using the LA data from the texture with mult.xw and add.xw.
+// Returns data in the form of llla
+float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
+{
+    return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy;
+};
+
+float4 luminancepremultps(float4 texcoord : TEXCOORD0) : COLOR
+{
+    float4 luma = (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy;
+    luma.rgb *= luma.a;
+    return luma;
+};
+
+float4 luminanceunmultps(float4 texcoord : TEXCOORD0) : COLOR
+{
+    float4 luma = (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy;
+    if (luma.a > 0.0f)
+    {
+        luma.rgb /= luma.a;
+    }
+    return luma;
+};
+
+// RGB/A Component Mask Pixel Shader
+// Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw.
+// Returns data in the form of rgba
+float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR
+{
+    return tex2D(tex, texcoord.xy) * mult + add;
+};
+
+float4 componentmaskpremultps(float4 texcoord : TEXCOORD0) : COLOR
+{
+    float4 color = tex2D(tex, texcoord.xy) * mult + add;
+    color.rgb *= color.a;
+    return color;
+};
+
+float4 componentmaskunmultps(float4 texcoord : TEXCOORD0) : COLOR
+{
+    float4 color =  tex2D(tex, texcoord.xy) * mult + add;
+    if (color.a > 0.0f)
+    {
+        color.rgb /= color.a;
+    }
+    return color;
+};
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
new file mode 100644
index 0000000..c68395a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+struct VS_OUTPUT
+{
+    float4 position : POSITION;
+    float4 texcoord : TEXCOORD0;
+};
+
+uniform float4 halfPixelSize : c0;
+uniform float4 texcoordOffset : c1;
+
+// Standard Vertex Shader
+// Input 0 is the homogenous position.
+// Outputs the homogenous position as-is.
+// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right.
+// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0.
+VS_OUTPUT standardvs(in float4 position : POSITION)
+{
+    VS_OUTPUT Out;
+
+    Out.position = position + halfPixelSize;
+    Out.texcoord = ((position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0)) * float4(texcoordOffset.zw, 1.0, 1.0)) + float4(texcoordOffset.xy, 0, 0);
+
+    return Out;
+};
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h
new file mode 100644
index 0000000..6aadab6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h
@@ -0,0 +1,50 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+// Parameters:

+//

+//   float4 add;

+//   float4 mult;

+//   sampler2D tex;

+//

+//

+// Registers:

+//

+//   Name         Reg   Size

+//   ------------ ----- ----

+//   mult         c0       1

+//   add          c1       1

+//   tex          s0       1

+//

+

+    ps_2_0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mov r1, c0

+    mad r0, r0, r1, c1

+    mul r0.xyz, r0.w, r0

+    mov oC0, r0

+

+// approximately 5 instruction slots used (1 texture, 4 arithmetic)

+#endif

+

+const BYTE g_ps20_componentmaskpremultps[] = {

+    0,   2,   255, 255, 254, 255, 50,  0,   67,  84,  65,  66,  28,  0,   0,   0,   143, 0,   0,

+    0,   0,   2,   255, 255, 3,   0,   0,   0,   28,  0,   0,   0,   0,   1,   0,   0,   136, 0,

+    0,   0,   88,  0,   0,   0,   2,   0,   1,   0,   1,   0,   0,   0,   92,  0,   0,   0,   0,

+    0,   0,   0,   108, 0,   0,   0,   2,   0,   0,   0,   1,   0,   0,   0,   92,  0,   0,   0,

+    0,   0,   0,   0,   113, 0,   0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   120, 0,   0,

+    0,   0,   0,   0,   0,   97,  100, 100, 0,   1,   0,   3,   0,   1,   0,   4,   0,   1,   0,

+    0,   0,   0,   0,   0,   0,   109, 117, 108, 116, 0,   116, 101, 120, 0,   171, 171, 171, 4,

+    0,   12,  0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   112, 115, 95,  50,

+    95,  48,  0,   77,  105, 99,  114, 111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,

+    83,  76,  32,  83,  104, 97,  100, 101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,

+    54,  46,  51,  46,  57,  54,  48,  48,  46,  49,  54,  51,  56,  52,  0,   171, 171, 171, 31,

+    0,   0,   2,   0,   0,   0,   128, 0,   0,   3,   176, 31,  0,   0,   2,   0,   0,   0,   144,

+    0,   8,   15,  160, 66,  0,   0,   3,   0,   0,   15,  128, 0,   0,   228, 176, 0,   8,   228,

+    160, 1,   0,   0,   2,   1,   0,   15,  128, 0,   0,   228, 160, 4,   0,   0,   4,   0,   0,

+    15,  128, 0,   0,   228, 128, 1,   0,   228, 128, 1,   0,   228, 160, 5,   0,   0,   3,   0,

+    0,   7,   128, 0,   0,   255, 128, 0,   0,   228, 128, 1,   0,   0,   2,   0,   8,   15,  128,

+    0,   0,   228, 128, 255, 255, 0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h
new file mode 100644
index 0000000..24482d7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h
@@ -0,0 +1,84 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+// Parameters:

+//

+//   float4 add;

+//   float4 mult;

+//   sampler2D tex;

+//

+//

+// Registers:

+//

+//   Name         Reg   Size

+//   ------------ ----- ----

+//   mult         c0       1

+//   add          c1       1

+//   tex          s0       1

+//

+

+    ps_2_0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mov r1, c0

+    mad r0, r0, r1, c1

+    mov oC0, r0

+

+// approximately 4 instruction slots used (1 texture, 3 arithmetic)

+#endif

+

+const BYTE g_ps20_componentmaskps[] =

+{

+      0,   2, 255, 255, 254, 255, 

+     50,   0,  67,  84,  65,  66, 

+     28,   0,   0,   0, 143,   0, 

+      0,   0,   0,   2, 255, 255, 

+      3,   0,   0,   0,  28,   0, 

+      0,   0,   0,   1,   0,   0, 

+    136,   0,   0,   0,  88,   0, 

+      0,   0,   2,   0,   1,   0, 

+      1,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+    108,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+     92,   0,   0,   0,   0,   0, 

+      0,   0, 113,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0, 120,   0,   0,   0, 

+      0,   0,   0,   0,  97, 100, 

+    100,   0,   1,   0,   3,   0, 

+      1,   0,   4,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+    109, 117, 108, 116,   0, 116, 

+    101, 120,   0, 171, 171, 171, 

+      4,   0,  12,   0,   1,   0, 

+      1,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0, 112, 115, 

+     95,  50,  95,  48,   0,  77, 

+    105,  99, 114, 111, 115, 111, 

+    102, 116,  32,  40,  82,  41, 

+     32,  72,  76,  83,  76,  32, 

+     83, 104,  97, 100, 101, 114, 

+     32,  67, 111, 109, 112, 105, 

+    108, 101, 114,  32,  54,  46, 

+     51,  46,  57,  54,  48,  48, 

+     46,  49,  54,  51,  56,  52, 

+      0, 171, 171, 171,  31,   0, 

+      0,   2,   0,   0,   0, 128, 

+      0,   0,   3, 176,  31,   0, 

+      0,   2,   0,   0,   0, 144, 

+      0,   8,  15, 160,  66,   0, 

+      0,   3,   0,   0,  15, 128, 

+      0,   0, 228, 176,   0,   8, 

+    228, 160,   1,   0,   0,   2, 

+      1,   0,  15, 128,   0,   0, 

+    228, 160,   4,   0,   0,   4, 

+      0,   0,  15, 128,   0,   0, 

+    228, 128,   1,   0, 228, 128, 

+      1,   0, 228, 160,   1,   0, 

+      0,   2,   0,   8,  15, 128, 

+      0,   0, 228, 128, 255, 255, 

+      0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h
new file mode 100644
index 0000000..72fae36
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h
@@ -0,0 +1,54 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+// Parameters:

+//

+//   float4 add;

+//   float4 mult;

+//   sampler2D tex;

+//

+//

+// Registers:

+//

+//   Name         Reg   Size

+//   ------------ ----- ----

+//   mult         c0       1

+//   add          c1       1

+//   tex          s0       1

+//

+

+    ps_2_0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mov r1, c0

+    mad r0, r0, r1, c1

+    rcp r1.x, r0.w

+    mul r1.xyz, r0, r1.x

+    cmp r0.xyz, -r0.w, r0, r1

+    mov oC0, r0

+

+// approximately 7 instruction slots used (1 texture, 6 arithmetic)

+#endif

+

+const BYTE g_ps20_componentmaskunmultps[] = {

+    0,   2,   255, 255, 254, 255, 50,  0,   67,  84,  65,  66,  28,  0,   0,   0,   143, 0,   0,

+    0,   0,   2,   255, 255, 3,   0,   0,   0,   28,  0,   0,   0,   0,   1,   0,   0,   136, 0,

+    0,   0,   88,  0,   0,   0,   2,   0,   1,   0,   1,   0,   0,   0,   92,  0,   0,   0,   0,

+    0,   0,   0,   108, 0,   0,   0,   2,   0,   0,   0,   1,   0,   0,   0,   92,  0,   0,   0,

+    0,   0,   0,   0,   113, 0,   0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   120, 0,   0,

+    0,   0,   0,   0,   0,   97,  100, 100, 0,   1,   0,   3,   0,   1,   0,   4,   0,   1,   0,

+    0,   0,   0,   0,   0,   0,   109, 117, 108, 116, 0,   116, 101, 120, 0,   171, 171, 171, 4,

+    0,   12,  0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   112, 115, 95,  50,

+    95,  48,  0,   77,  105, 99,  114, 111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,

+    83,  76,  32,  83,  104, 97,  100, 101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,

+    54,  46,  51,  46,  57,  54,  48,  48,  46,  49,  54,  51,  56,  52,  0,   171, 171, 171, 31,

+    0,   0,   2,   0,   0,   0,   128, 0,   0,   3,   176, 31,  0,   0,   2,   0,   0,   0,   144,

+    0,   8,   15,  160, 66,  0,   0,   3,   0,   0,   15,  128, 0,   0,   228, 176, 0,   8,   228,

+    160, 1,   0,   0,   2,   1,   0,   15,  128, 0,   0,   228, 160, 4,   0,   0,   4,   0,   0,

+    15,  128, 0,   0,   228, 128, 1,   0,   228, 128, 1,   0,   228, 160, 6,   0,   0,   2,   1,

+    0,   1,   128, 0,   0,   255, 128, 5,   0,   0,   3,   1,   0,   7,   128, 0,   0,   228, 128,

+    1,   0,   0,   128, 88,  0,   0,   4,   0,   0,   7,   128, 0,   0,   255, 129, 0,   0,   228,

+    128, 1,   0,   228, 128, 1,   0,   0,   2,   0,   8,   15,  128, 0,   0,   228, 128, 255, 255,

+    0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h
new file mode 100644
index 0000000..d3a5c98
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h
@@ -0,0 +1,54 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+// Parameters:

+//

+//   float4 add;

+//   float4 mult;

+//   sampler2D tex;

+//

+//

+// Registers:

+//

+//   Name         Reg   Size

+//   ------------ ----- ----

+//   mult         c0       1

+//   add          c1       1

+//   tex          s0       1

+//

+

+    ps_2_0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mov r1.xw, c0

+    mad r0.x, r0.x, r1.x, c1.x

+    mad r0.y, r0.w, r1.w, c1.w

+    mul r1.xyz, r0.y, r0.x

+    mov r1.w, r0.y

+    mov oC0, r1

+

+// approximately 7 instruction slots used (1 texture, 6 arithmetic)

+#endif

+

+const BYTE g_ps20_luminancepremultps[] = {

+    0,   2,   255, 255, 254, 255, 50,  0,   67,  84,  65,  66,  28,  0,   0,   0,   143, 0,   0,

+    0,   0,   2,   255, 255, 3,   0,   0,   0,   28,  0,   0,   0,   0,   1,   0,   0,   136, 0,

+    0,   0,   88,  0,   0,   0,   2,   0,   1,   0,   1,   0,   0,   0,   92,  0,   0,   0,   0,

+    0,   0,   0,   108, 0,   0,   0,   2,   0,   0,   0,   1,   0,   0,   0,   92,  0,   0,   0,

+    0,   0,   0,   0,   113, 0,   0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   120, 0,   0,

+    0,   0,   0,   0,   0,   97,  100, 100, 0,   1,   0,   3,   0,   1,   0,   4,   0,   1,   0,

+    0,   0,   0,   0,   0,   0,   109, 117, 108, 116, 0,   116, 101, 120, 0,   171, 171, 171, 4,

+    0,   12,  0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   112, 115, 95,  50,

+    95,  48,  0,   77,  105, 99,  114, 111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,

+    83,  76,  32,  83,  104, 97,  100, 101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,

+    54,  46,  51,  46,  57,  54,  48,  48,  46,  49,  54,  51,  56,  52,  0,   171, 171, 171, 31,

+    0,   0,   2,   0,   0,   0,   128, 0,   0,   3,   176, 31,  0,   0,   2,   0,   0,   0,   144,

+    0,   8,   15,  160, 66,  0,   0,   3,   0,   0,   15,  128, 0,   0,   228, 176, 0,   8,   228,

+    160, 1,   0,   0,   2,   1,   0,   9,   128, 0,   0,   228, 160, 4,   0,   0,   4,   0,   0,

+    1,   128, 0,   0,   0,   128, 1,   0,   0,   128, 1,   0,   0,   160, 4,   0,   0,   4,   0,

+    0,   2,   128, 0,   0,   255, 128, 1,   0,   255, 128, 1,   0,   255, 160, 5,   0,   0,   3,

+    1,   0,   7,   128, 0,   0,   85,  128, 0,   0,   0,   128, 1,   0,   0,   2,   1,   0,   8,

+    128, 0,   0,   85,  128, 1,   0,   0,   2,   0,   8,   15,  128, 1,   0,   228, 128, 255, 255,

+    0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h
new file mode 100644
index 0000000..bdd25ac
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h
@@ -0,0 +1,94 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+// Parameters:

+//

+//   float4 add;

+//   float4 mult;

+//   sampler2D tex;

+//

+//

+// Registers:

+//

+//   Name         Reg   Size

+//   ------------ ----- ----

+//   mult         c0       1

+//   add          c1       1

+//   tex          s0       1

+//

+

+    ps_2_0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mov r1.xw, c0

+    mad r0.x, r0.x, r1.x, c1.x

+    mad r0.y, r0.w, r1.w, c1.w

+    mov r1.xyz, r0.x

+    mov r1.w, r0.y

+    mov oC0, r1

+

+// approximately 7 instruction slots used (1 texture, 6 arithmetic)

+#endif

+

+const BYTE g_ps20_luminanceps[] =

+{

+      0,   2, 255, 255, 254, 255, 

+     50,   0,  67,  84,  65,  66, 

+     28,   0,   0,   0, 143,   0, 

+      0,   0,   0,   2, 255, 255, 

+      3,   0,   0,   0,  28,   0, 

+      0,   0,   0,   1,   0,   0, 

+    136,   0,   0,   0,  88,   0, 

+      0,   0,   2,   0,   1,   0, 

+      1,   0,   0,   0,  92,   0, 

+      0,   0,   0,   0,   0,   0, 

+    108,   0,   0,   0,   2,   0, 

+      0,   0,   1,   0,   0,   0, 

+     92,   0,   0,   0,   0,   0, 

+      0,   0, 113,   0,   0,   0, 

+      3,   0,   0,   0,   1,   0, 

+      0,   0, 120,   0,   0,   0, 

+      0,   0,   0,   0,  97, 100, 

+    100,   0,   1,   0,   3,   0, 

+      1,   0,   4,   0,   1,   0, 

+      0,   0,   0,   0,   0,   0, 

+    109, 117, 108, 116,   0, 116, 

+    101, 120,   0, 171, 171, 171, 

+      4,   0,  12,   0,   1,   0, 

+      1,   0,   1,   0,   0,   0, 

+      0,   0,   0,   0, 112, 115, 

+     95,  50,  95,  48,   0,  77, 

+    105,  99, 114, 111, 115, 111, 

+    102, 116,  32,  40,  82,  41, 

+     32,  72,  76,  83,  76,  32, 

+     83, 104,  97, 100, 101, 114, 

+     32,  67, 111, 109, 112, 105, 

+    108, 101, 114,  32,  54,  46, 

+     51,  46,  57,  54,  48,  48, 

+     46,  49,  54,  51,  56,  52, 

+      0, 171, 171, 171,  31,   0, 

+      0,   2,   0,   0,   0, 128, 

+      0,   0,   3, 176,  31,   0, 

+      0,   2,   0,   0,   0, 144, 

+      0,   8,  15, 160,  66,   0, 

+      0,   3,   0,   0,  15, 128, 

+      0,   0, 228, 176,   0,   8, 

+    228, 160,   1,   0,   0,   2, 

+      1,   0,   9, 128,   0,   0, 

+    228, 160,   4,   0,   0,   4, 

+      0,   0,   1, 128,   0,   0, 

+      0, 128,   1,   0,   0, 128, 

+      1,   0,   0, 160,   4,   0, 

+      0,   4,   0,   0,   2, 128, 

+      0,   0, 255, 128,   1,   0, 

+    255, 128,   1,   0, 255, 160, 

+      1,   0,   0,   2,   1,   0, 

+      7, 128,   0,   0,   0, 128, 

+      1,   0,   0,   2,   1,   0, 

+      8, 128,   0,   0,  85, 128, 

+      1,   0,   0,   2,   0,   8, 

+     15, 128,   1,   0, 228, 128, 

+    255, 255,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h
new file mode 100644
index 0000000..d0794b5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h
@@ -0,0 +1,57 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+// Parameters:

+//

+//   float4 add;

+//   float4 mult;

+//   sampler2D tex;

+//

+//

+// Registers:

+//

+//   Name         Reg   Size

+//   ------------ ----- ----

+//   mult         c0       1

+//   add          c1       1

+//   tex          s0       1

+//

+

+    ps_2_0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mov r1.xw, c0

+    mad r0.x, r0.x, r1.x, c1.x

+    mad r0.y, r0.w, r1.w, c1.w

+    rcp r0.z, r0.y

+    mul r0.z, r0.z, r0.x

+    cmp r1.xyz, -r0.y, r0.x, r0.z

+    mov r1.w, r0.y

+    mov oC0, r1

+

+// approximately 9 instruction slots used (1 texture, 8 arithmetic)

+#endif

+

+const BYTE g_ps20_luminanceunmultps[] = {

+    0,   2,   255, 255, 254, 255, 50,  0,   67,  84,  65,  66,  28,  0,   0,   0,   143, 0,   0,

+    0,   0,   2,   255, 255, 3,   0,   0,   0,   28,  0,   0,   0,   0,   1,   0,   0,   136, 0,

+    0,   0,   88,  0,   0,   0,   2,   0,   1,   0,   1,   0,   0,   0,   92,  0,   0,   0,   0,

+    0,   0,   0,   108, 0,   0,   0,   2,   0,   0,   0,   1,   0,   0,   0,   92,  0,   0,   0,

+    0,   0,   0,   0,   113, 0,   0,   0,   3,   0,   0,   0,   1,   0,   0,   0,   120, 0,   0,

+    0,   0,   0,   0,   0,   97,  100, 100, 0,   1,   0,   3,   0,   1,   0,   4,   0,   1,   0,

+    0,   0,   0,   0,   0,   0,   109, 117, 108, 116, 0,   116, 101, 120, 0,   171, 171, 171, 4,

+    0,   12,  0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   112, 115, 95,  50,

+    95,  48,  0,   77,  105, 99,  114, 111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,

+    83,  76,  32,  83,  104, 97,  100, 101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,

+    54,  46,  51,  46,  57,  54,  48,  48,  46,  49,  54,  51,  56,  52,  0,   171, 171, 171, 31,

+    0,   0,   2,   0,   0,   0,   128, 0,   0,   3,   176, 31,  0,   0,   2,   0,   0,   0,   144,

+    0,   8,   15,  160, 66,  0,   0,   3,   0,   0,   15,  128, 0,   0,   228, 176, 0,   8,   228,

+    160, 1,   0,   0,   2,   1,   0,   9,   128, 0,   0,   228, 160, 4,   0,   0,   4,   0,   0,

+    1,   128, 0,   0,   0,   128, 1,   0,   0,   128, 1,   0,   0,   160, 4,   0,   0,   4,   0,

+    0,   2,   128, 0,   0,   255, 128, 1,   0,   255, 128, 1,   0,   255, 160, 6,   0,   0,   2,

+    0,   0,   4,   128, 0,   0,   85,  128, 5,   0,   0,   3,   0,   0,   4,   128, 0,   0,   170,

+    128, 0,   0,   0,   128, 88,  0,   0,   4,   1,   0,   7,   128, 0,   0,   85,  129, 0,   0,

+    0,   128, 0,   0,   170, 128, 1,   0,   0,   2,   1,   0,   8,   128, 0,   0,   85,  128, 1,

+    0,   0,   2,   0,   8,   15,  128, 1,   0,   228, 128, 255, 255, 0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h
new file mode 100644
index 0000000..337af92
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h
@@ -0,0 +1,61 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+// Parameters:

+//

+//   sampler2D tex;

+//

+//

+// Registers:

+//

+//   Name         Reg   Size

+//   ------------ ----- ----

+//   tex          s0       1

+//

+

+    ps_2_0

+    dcl t0.xy

+    dcl_2d s0

+    texld r0, t0, s0

+    mov oC0, r0

+

+// approximately 2 instruction slots used (1 texture, 1 arithmetic)

+#endif

+

+const BYTE g_ps20_passthroughps[] =

+{

+      0,   2, 255, 255, 254, 255, 

+     33,   0,  67,  84,  65,  66, 

+     28,   0,   0,   0,  75,   0, 

+      0,   0,   0,   2, 255, 255, 

+      1,   0,   0,   0,  28,   0, 

+      0,   0,   0,   1,   0,   0, 

+     68,   0,   0,   0,  48,   0, 

+      0,   0,   3,   0,   0,   0, 

+      1,   0,   0,   0,  52,   0, 

+      0,   0,   0,   0,   0,   0, 

+    116, 101, 120,   0,   4,   0, 

+     12,   0,   1,   0,   1,   0, 

+      1,   0,   0,   0,   0,   0, 

+      0,   0, 112, 115,  95,  50, 

+     95,  48,   0,  77, 105,  99, 

+    114, 111, 115, 111, 102, 116, 

+     32,  40,  82,  41,  32,  72, 

+     76,  83,  76,  32,  83, 104, 

+     97, 100, 101, 114,  32,  67, 

+    111, 109, 112, 105, 108, 101, 

+    114,  32,  54,  46,  51,  46, 

+     57,  54,  48,  48,  46,  49, 

+     54,  51,  56,  52,   0, 171, 

+    171, 171,  31,   0,   0,   2, 

+      0,   0,   0, 128,   0,   0, 

+      3, 176,  31,   0,   0,   2, 

+      0,   0,   0, 144,   0,   8, 

+     15, 160,  66,   0,   0,   3, 

+      0,   0,  15, 128,   0,   0, 

+    228, 176,   0,   8, 228, 160, 

+      1,   0,   0,   2,   0,   8, 

+     15, 128,   0,   0, 228, 128, 

+    255, 255,   0,   0

+};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h
new file mode 100644
index 0000000..350b2eb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h
@@ -0,0 +1,46 @@
+#if 0

+//

+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384

+//

+// Parameters:

+//

+//   float4 halfPixelSize;

+//   float4 texcoordOffset;

+//

+//

+// Registers:

+//

+//   Name           Reg   Size

+//   -------------- ----- ----

+//   halfPixelSize  c0       1

+//   texcoordOffset c1       1

+//

+

+    vs_2_0

+    def c2, 0.5, -0.5, 1, 0

+    dcl_position v0

+    add oPos, v0, c0

+    mad r0, v0, c2.xyzz, c2.xxww

+    mov oT0.zw, r0

+    mad oT0.xy, r0, c1.zwzw, c1

+

+// approximately 4 instruction slots used

+#endif

+

+const BYTE g_vs20_standardvs[] = {

+    0,   2,   254, 255, 254, 255, 44,  0,   67,  84,  65,  66,  28,  0,   0,   0,   122, 0,   0,

+    0,   0,   2,   254, 255, 2,   0,   0,   0,   28,  0,   0,   0,   0,   1,   0,   0,   115, 0,

+    0,   0,   68,  0,   0,   0,   2,   0,   0,   0,   1,   0,   0,   0,   84,  0,   0,   0,   0,

+    0,   0,   0,   100, 0,   0,   0,   2,   0,   1,   0,   1,   0,   0,   0,   84,  0,   0,   0,

+    0,   0,   0,   0,   104, 97,  108, 102, 80,  105, 120, 101, 108, 83,  105, 122, 101, 0,   171,

+    171, 1,   0,   3,   0,   1,   0,   4,   0,   1,   0,   0,   0,   0,   0,   0,   0,   116, 101,

+    120, 99,  111, 111, 114, 100, 79,  102, 102, 115, 101, 116, 0,   118, 115, 95,  50,  95,  48,

+    0,   77,  105, 99,  114, 111, 115, 111, 102, 116, 32,  40,  82,  41,  32,  72,  76,  83,  76,

+    32,  83,  104, 97,  100, 101, 114, 32,  67,  111, 109, 112, 105, 108, 101, 114, 32,  54,  46,

+    51,  46,  57,  54,  48,  48,  46,  49,  54,  51,  56,  52,  0,   81,  0,   0,   5,   2,   0,

+    15,  160, 0,   0,   0,   63,  0,   0,   0,   191, 0,   0,   128, 63,  0,   0,   0,   0,   31,

+    0,   0,   2,   0,   0,   0,   128, 0,   0,   15,  144, 2,   0,   0,   3,   0,   0,   15,  192,

+    0,   0,   228, 144, 0,   0,   228, 160, 4,   0,   0,   4,   0,   0,   15,  128, 0,   0,   228,

+    144, 2,   0,   164, 160, 2,   0,   240, 160, 1,   0,   0,   2,   0,   0,   12,  224, 0,   0,

+    228, 128, 4,   0,   0,   4,   0,   0,   3,   224, 0,   0,   228, 128, 1,   0,   238, 160, 1,

+    0,   228, 160, 255, 255, 0,   0};

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat
new file mode 100644
index 0000000..d320e27
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat
@@ -0,0 +1,66 @@
+@ECHO OFF

+REM

+REM Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.

+REM Use of this source code is governed by a BSD-style license that can be

+REM found in the LICENSE file.

+REM

+

+PATH %PATH%;%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86;%DXSDK_DIR%\Utilities\bin\x86

+

+setlocal

+set errorCount=0

+set successCount=0

+set debug=0

+

+if "%1" == "debug" (

+    set debug=1

+)

+if "%1" == "release" (

+    set debug=0

+)

+

+::              | Input file          | Entry point           | Type | Output file                        | Debug |

+call:BuildShader Blit.vs               standardvs              vs_2_0 compiled\standardvs.h                %debug%

+call:BuildShader Blit.ps               passthroughps           ps_2_0 compiled\passthroughps.h             %debug%

+call:BuildShader Blit.ps               luminanceps             ps_2_0 compiled\luminanceps.h               %debug%

+call:BuildShader Blit.ps               luminancepremultps      ps_2_0 compiled\luminancepremultps.h        %debug%

+call:BuildShader Blit.ps               luminanceunmultps       ps_2_0 compiled\luminanceunmultps.h         %debug%

+call:BuildShader Blit.ps               componentmaskps         ps_2_0 compiled\componentmaskps.h           %debug%

+call:BuildShader Blit.ps               componentmaskpremultps  ps_2_0 compiled\componentmaskpremultps.h    %debug%

+call:BuildShader Blit.ps               componentmaskunmultps   ps_2_0 compiled\componentmaskunmultps.h     %debug%

+

+echo.

+

+if %successCount% GTR 0 (

+   echo %successCount% shaders compiled successfully.

+)

+if %errorCount% GTR 0 (

+   echo There were %errorCount% shader compilation errors.

+)

+

+endlocal

+exit /b

+

+:BuildShader

+set input=%~1

+set entry=%~2

+set type=%~3

+set output=%~4

+set debug=%~5

+

+if %debug% == 0 (

+    set "buildCMD=fxc /nologo /E %entry% /T %type% /Fh %output% %input%"

+) else (

+    set "buildCMD=fxc /nologo /Zi /Od /E %entry% /T %type% /Fh %output% %input%"

+)

+

+set error=0

+%buildCMD% || set error=1

+

+if %error% == 0 (

+    set /a successCount=%successCount%+1

+) else (

+    set /a errorCount=%errorCount%+1

+)

+

+exit /b

diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h
new file mode 100644
index 0000000..aa05934
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h
@@ -0,0 +1,200 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// vertexconversion.h: A library of vertex conversion classes that can be used to build
+// the FormatConverter objects used by the buffer conversion system.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
+
+#include <limits>
+#include <cstdint>
+#include <cstddef>
+
+namespace rx
+{
+
+// Conversion types:
+// static const bool identity: true if this is an identity transform, false otherwise
+// static U convert(T): convert a single element from the input type to the output type
+// typedef ... OutputType: the type produced by this conversion
+
+template <class T>
+struct Identity
+{
+    static const bool identity = true;
+
+    typedef T OutputType;
+
+    static T convert(T x)
+    {
+        return x;
+    }
+};
+
+template <class FromT, class ToT>
+struct Cast
+{
+    static const bool identity = false;
+
+    typedef ToT OutputType;
+
+    static ToT convert(FromT x)
+    {
+        return static_cast<ToT>(x);
+    }
+};
+
+template <class T>
+struct Cast<T, T>
+{
+    static const bool identity = true;
+
+    typedef T OutputType;
+
+    static T convert(T x)
+    {
+        return static_cast<T>(x);
+    }
+};
+
+template <class T>
+struct Normalize
+{
+    static const bool identity = false;
+
+    typedef float OutputType;
+
+    static float convert(T x)
+    {
+        typedef std::numeric_limits<T> NL;
+        float f = static_cast<float>(x);
+
+        if (NL::is_signed)
+        {
+            // const float => VC2008 computes it at compile time
+            // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
+            const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
+            return (2*f+1)*divisor;
+        }
+        else
+        {
+            return f/NL::max();
+        }
+    }
+};
+
+template <class FromType, std::size_t ScaleBits>
+struct FixedToFloat
+{
+    static const bool identity = false;
+
+    typedef float OutputType;
+
+    static float convert(FromType x)
+    {
+        const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
+        return static_cast<float>(x) * divisor;
+    }
+};
+
+// Widen types:
+// static const unsigned int initialWidth: number of components before conversion
+// static const unsigned int finalWidth: number of components after conversion
+
+// Float is supported at any size.
+template <std::size_t N>
+struct NoWiden
+{
+    static const std::size_t initialWidth = N;
+    static const std::size_t finalWidth = N;
+};
+
+// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
+template <std::size_t N>
+struct WidenToEven
+{
+    static const std::size_t initialWidth = N;
+    static const std::size_t finalWidth = N+(N&1);
+};
+
+template <std::size_t N>
+struct WidenToFour
+{
+    static const std::size_t initialWidth = N;
+    static const std::size_t finalWidth = 4;
+};
+
+// Most types have 0 and 1 that are just that.
+template <class T>
+struct SimpleDefaultValues
+{
+    static T zero() { return static_cast<T>(0); }
+    static T one() { return static_cast<T>(1); }
+};
+
+// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
+template <class T>
+struct NormalizedDefaultValues
+{
+    static T zero() { return static_cast<T>(0); }
+    static T one() { return std::numeric_limits<T>::max(); }
+};
+
+// Converter:
+// static const bool identity: true if this is an identity transform (with no widening)
+// static const std::size_t finalSize: number of bytes per output vertex
+// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided.
+
+template <class InT,
+          class WidenRule,
+          class Converter,
+          class DefaultValueRule = SimpleDefaultValues<InT>>
+struct VertexDataConverter
+{
+    typedef typename Converter::OutputType OutputType;
+    typedef InT InputType;
+
+    static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
+    static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
+
+    static void convertArray(const uint8_t *input, size_t stride, size_t n, uint8_t *output)
+    {
+        OutputType *out = reinterpret_cast<OutputType*>(output);
+
+        for (std::size_t i = 0; i < n; i++)
+        {
+            const InputType *ein = reinterpret_cast<const InputType*>(input + i * stride);
+
+            copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
+            copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
+            copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
+            copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
+
+            out += WidenRule::finalWidth;
+        }
+    }
+
+  private:
+    static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
+    {
+        if (WidenRule::finalWidth > elementindex)
+        {
+            if (WidenRule::initialWidth > elementindex)
+            {
+                out[elementindex] = Converter::convert(in[elementindex]);
+            }
+            else
+            {
+                out[elementindex] = defaultvalue;
+            }
+        }
+    }
+};
+
+}
+
+#endif   // LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h b/src/third_party/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h
new file mode 100644
index 0000000..a245a04
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils9.h: Queries for GL image formats and their translations to D3D
+// formats.
+
+#ifndef LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
+#define LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
+
+#include "angle_gl.h"
+
+#include <cstddef>
+#include <stdint.h>
+
+#include <map>
+
+namespace gl
+{
+struct FormatType;
+}
+
+namespace rx
+{
+typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+enum VertexConversionType
+{
+    VERTEX_CONVERT_NONE = 0,
+    VERTEX_CONVERT_CPU = 1,
+    VERTEX_CONVERT_GPU = 2,
+    VERTEX_CONVERT_BOTH = 3
+};
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/driver_utils.cpp b/src/third_party/angle/src/libANGLE/renderer/driver_utils.cpp
new file mode 100644
index 0000000..d97b8e7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/driver_utils.cpp
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// driver_utils.h : provides more information about current driver.
+
+#include <algorithm>
+
+#include "libANGLE/renderer/driver_utils.h"
+
+namespace rx
+{
+// Intel
+// Referenced from https://cgit.freedesktop.org/vaapi/intel-driver/tree/src/i965_pciids.h
+namespace
+{
+// gen7
+const uint32_t Haswell[] = {
+    0x0402, 0x0406, 0x040A, 0x040B, 0x040E, 0x0C02, 0x0C06, 0x0C0A, 0x0C0B, 0x0C0E,
+    0x0A02, 0x0A06, 0x0A0A, 0x0A0B, 0x0A0E, 0x0D02, 0x0D06, 0x0D0A, 0x0D0B, 0x0D0E,  // hsw_gt1
+    0x0412, 0x0416, 0x041A, 0x041B, 0x041E, 0x0C12, 0x0C16, 0x0C1A, 0x0C1B, 0x0C1E,
+    0x0A12, 0x0A16, 0x0A1A, 0x0A1B, 0x0A1E, 0x0D12, 0x0D16, 0x0D1A, 0x0D1B, 0x0D1E,  // hsw_gt2
+    0x0422, 0x0426, 0x042A, 0x042B, 0x042E, 0x0C22, 0x0C26, 0x0C2A, 0x0C2B, 0x0C2E,
+    0x0A22, 0x0A26, 0x0A2A, 0x0A2B, 0x0A2E, 0x0D22, 0x0D26, 0x0D2A, 0x0D2B, 0x0D2E  // hsw_gt3
+};
+
+// gen8
+const uint32_t Broadwell[] = {0x1602, 0x1606, 0x160A, 0x160B, 0x160D, 0x160E,
+                              0x1612, 0x1616, 0x161A, 0x161B, 0x161D, 0x161E,
+                              0x1622, 0x1626, 0x162A, 0x162B, 0x162D, 0x162E};
+
+const uint32_t CherryView[] = {0x22B0, 0x22B1, 0x22B2, 0x22B3};
+
+// gen9
+const uint32_t Skylake[] = {0x1902, 0x1906, 0x190A, 0x190B, 0x190E, 0x1912, 0x1913, 0x1915, 0x1916,
+                            0x1917, 0x191A, 0x191B, 0x191D, 0x191E, 0x1921, 0x1923, 0x1926, 0x1927,
+                            0x192A, 0x192B, 0x192D, 0x1932, 0x193A, 0x193B, 0x193D};
+
+const uint32_t Broxton[] = {0x0A84, 0x1A84, 0x1A85, 0x5A84, 0x5A85};
+
+// gen9p5
+const uint32_t Kabylake[] = {0x5916, 0x5913, 0x5906, 0x5926, 0x5921, 0x5915, 0x590E,
+                             0x591E, 0x5912, 0x5917, 0x5902, 0x591B, 0x593B, 0x590B,
+                             0x591A, 0x590A, 0x591D, 0x5908, 0x5923, 0x5927};
+
+}  // anonymous namespace
+
+IntelDriverVersion::IntelDriverVersion(uint16_t lastPart) : mVersionPart(lastPart)
+{
+}
+
+bool IntelDriverVersion::operator==(const IntelDriverVersion &version)
+{
+    return mVersionPart == version.mVersionPart;
+}
+
+bool IntelDriverVersion::operator!=(const IntelDriverVersion &version)
+{
+    return !(*this == version);
+}
+
+bool IntelDriverVersion::operator<(const IntelDriverVersion &version)
+{
+    // See http://www.intel.com/content/www/us/en/support/graphics-drivers/000005654.html to
+    // understand the Intel graphics driver version number on Windows.
+    // mVersionPart1 changes with OS version. mVersionPart2 changes with DirectX version.
+    // mVersionPart3 stands for release year. mVersionPart4 is driver specific unique version
+    // number.
+    // For example: Intel driver version '20.19.15.4539'
+    //              20   -> windows 10 driver
+    //              19   -> DirectX 12 first version(12.0) supported
+    //              15   -> Driver released in 2015
+    //              4539 -> Driver specific unique version number
+    // For linux, Intel graphics driver version is the mesa version. The version number has three
+    // parts: major revision, minor revision, release number. So, for linux, we need to compare
+    // three parts.
+    // Currently, it's only used in windows. So, checking the last part is enough. Once it's needed
+    // in other platforms, it's easy to be extended.
+    return mVersionPart < version.mVersionPart;
+}
+
+bool IntelDriverVersion::operator>=(const IntelDriverVersion &version)
+{
+    return !(*this < version);
+}
+
+bool IsHaswell(uint32_t DeviceId)
+{
+    return std::find(std::begin(Haswell), std::end(Haswell), DeviceId) != std::end(Haswell);
+}
+
+bool IsBroadwell(uint32_t DeviceId)
+{
+    return std::find(std::begin(Broadwell), std::end(Broadwell), DeviceId) != std::end(Broadwell);
+}
+
+bool IsCherryView(uint32_t DeviceId)
+{
+    return std::find(std::begin(CherryView), std::end(CherryView), DeviceId) !=
+           std::end(CherryView);
+}
+
+bool IsSkylake(uint32_t DeviceId)
+{
+    return std::find(std::begin(Skylake), std::end(Skylake), DeviceId) != std::end(Skylake);
+}
+
+bool IsBroxton(uint32_t DeviceId)
+{
+    return std::find(std::begin(Broxton), std::end(Broxton), DeviceId) != std::end(Broxton);
+}
+
+bool IsKabylake(uint32_t DeviceId)
+{
+    return std::find(std::begin(Kabylake), std::end(Kabylake), DeviceId) != std::end(Kabylake);
+}
+
+}  // namespace rx
\ No newline at end of file
diff --git a/src/third_party/angle/src/libANGLE/renderer/driver_utils.h b/src/third_party/angle/src/libANGLE/renderer/driver_utils.h
new file mode 100644
index 0000000..62bdc50
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/driver_utils.h
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// driver_utils.h : provides more information about current driver.
+
+#ifndef LIBANGLE_RENDERER_DRIVER_UTILS_H_
+#define LIBANGLE_RENDERER_DRIVER_UTILS_H_
+
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+
+enum VendorID : uint32_t
+{
+    VENDOR_ID_UNKNOWN = 0x0,
+    VENDOR_ID_AMD     = 0x1002,
+    VENDOR_ID_INTEL   = 0x8086,
+    VENDOR_ID_NVIDIA  = 0x10DE,
+    // This is Qualcomm PCI Vendor ID.
+    // Android doesn't have a PCI bus, but all we need is a unique id.
+    VENDOR_ID_QUALCOMM = 0x5143,
+};
+
+inline bool IsAMD(uint32_t vendor_id)
+{
+    return vendor_id == VENDOR_ID_AMD;
+}
+
+inline bool IsIntel(uint32_t vendor_id)
+{
+    return vendor_id == VENDOR_ID_INTEL;
+}
+
+inline bool IsNvidia(uint32_t vendor_id)
+{
+    return vendor_id == VENDOR_ID_NVIDIA;
+}
+
+inline bool IsQualcomm(uint32_t vendor_id)
+{
+    return vendor_id == VENDOR_ID_QUALCOMM;
+}
+
+// Intel
+class IntelDriverVersion
+{
+  public:
+    // Currently, We only provide the constructor with one parameter. It mainly used in Intel
+    // version number on windows. If you want to use this class on other platforms, it's easy to
+    // be extended.
+    IntelDriverVersion(uint16_t lastPart);
+    bool operator==(const IntelDriverVersion &);
+    bool operator!=(const IntelDriverVersion &);
+    bool operator<(const IntelDriverVersion &);
+    bool operator>=(const IntelDriverVersion &);
+
+  private:
+    uint16_t mVersionPart;
+};
+
+bool IsHaswell(uint32_t DeviceId);
+bool IsBroadwell(uint32_t DeviceId);
+bool IsCherryView(uint32_t DeviceId);
+bool IsSkylake(uint32_t DeviceId);
+bool IsBroxton(uint32_t DeviceId);
+bool IsKabylake(uint32_t DeviceId);
+
+}  // namespace rx
+#endif  // LIBANGLE_RENDERER_DRIVER_UTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gen_angle_format_table.py b/src/third_party/angle/src/libANGLE/renderer/gen_angle_format_table.py
new file mode 100644
index 0000000..f47a024
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gen_angle_format_table.py
@@ -0,0 +1,231 @@
+#!/usr/bin/python
+# Copyright 2016 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.
+#
+# gen_angle_format_table.py:
+#  Code generation for ANGLE format map.
+#
+
+import angle_format
+from datetime import date
+import json
+import math
+import pprint
+import re
+import sys
+
+template_autogen_h = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}
+//
+// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLE format enumeration.
+
+namespace angle
+{{
+
+enum class Format::ID
+{{
+{angle_format_enum}
+}};
+
+}}  // namespace angle
+"""
+
+template_autogen_inl = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}
+//
+// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLE Format table:
+//   Queries for typed format information from the ANGLE format enum.
+
+#include "libANGLE/renderer/Format.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+namespace angle
+{{
+
+static constexpr rx::FastCopyFunctionMap::Entry BGRAEntry = {{GL_RGBA, GL_UNSIGNED_BYTE,
+                                                             CopyBGRA8ToRGBA8}};
+static constexpr rx::FastCopyFunctionMap BGRACopyFunctions = {{&BGRAEntry, 1}};
+static constexpr rx::FastCopyFunctionMap NoCopyFunctions;
+
+constexpr Format g_formatInfoTable[] = {{
+    // clang-format off
+    {{ Format::ID::NONE, GL_NONE, GL_NONE, nullptr, NoCopyFunctions, nullptr, GL_NONE, 0, 0, 0, 0, 0, 0 }},
+{angle_format_info_cases}    // clang-format on
+}};
+
+// static
+const Format &Format::Get(ID id)
+{{
+    return g_formatInfoTable[static_cast<size_t>(id)];
+}}
+
+}}  // namespace angle
+"""
+
+def get_channel_struct(angle_format):
+    if 'bits' not in angle_format or angle_format['bits'] is None:
+        return None
+    if 'BLOCK' in angle_format['id']:
+        return None
+    bits = angle_format['bits']
+    if 'D' in bits or 'S' in bits:
+        return None
+
+    if 'channelStruct' in angle_format:
+        return angle_format['channelStruct']
+
+    struct_name = ''
+    for channel in angle_format['channels']:
+        if channel == 'r':
+            struct_name += 'R{}'.format(bits['R'])
+        if channel == 'g':
+            struct_name += 'G{}'.format(bits['G'])
+        if channel == 'b':
+            struct_name += 'B{}'.format(bits['B'])
+        if channel == 'a':
+            struct_name += 'A{}'.format(bits['A'])
+        if channel == 'l':
+            struct_name += 'L{}'.format(bits['L'])
+    if angle_format['componentType'] == 'float':
+        struct_name += 'F'
+    if angle_format['componentType'] == 'int' or angle_format['componentType'] == 'snorm':
+        struct_name += 'S'
+    return struct_name
+
+def get_mip_generation_function(angle_format):
+    channel_struct = get_channel_struct(angle_format)
+    if channel_struct == None or "BLOCK" in angle_format["id"]:
+        return 'nullptr'
+    return 'GenerateMip<' + channel_struct + '>'
+
+def get_color_read_function(angle_format):
+    channel_struct = get_channel_struct(angle_format)
+    if channel_struct == None:
+        return 'nullptr'
+    component_type_map = {
+        'uint': 'GLuint',
+        'int': 'GLint',
+        'unorm': 'GLfloat',
+        'snorm': 'GLfloat',
+        'float': 'GLfloat'
+    }
+    return 'ReadColor<' + channel_struct + ', '+ component_type_map[angle_format['componentType']] + '>'
+
+format_entry_template = """    {{ Format::ID::{id}, {glInternalFormat}, {fboImplementationInternalFormat}, {mipGenerationFunction}, {fastCopyFunctions}, {colorReadFunction}, {namedComponentType}, {R}, {G}, {B}, {A}, {D}, {S} }},
+"""
+
+def get_named_component_type(component_type):
+    if component_type == "snorm":
+        return "GL_SIGNED_NORMALIZED"
+    elif component_type == "unorm":
+        return "GL_UNSIGNED_NORMALIZED"
+    elif component_type == "float":
+        return "GL_FLOAT"
+    elif component_type == "uint":
+        return "GL_UNSIGNED_INT"
+    elif component_type == "int":
+        return "GL_INT"
+    elif component_type == "none":
+        return "GL_NONE"
+    else:
+        raise ValueError("Unknown component type for " + component_type)
+
+def json_to_table_data(format_id, json, angle_to_gl):
+
+    table_data = ""
+
+    parsed = {
+        "id": format_id,
+        "fastCopyFunctions": "NoCopyFunctions",
+    }
+
+    for k, v in json.iteritems():
+        parsed[k] = v
+
+    if "glInternalFormat" not in parsed:
+        parsed["glInternalFormat"] = angle_to_gl[format_id]
+
+    if "fboImplementationInternalFormat" not in parsed:
+        parsed["fboImplementationInternalFormat"] = parsed["glInternalFormat"]
+
+    if "componentType" not in parsed:
+        parsed["componentType"] = angle_format.get_component_type(format_id)
+
+    if "channels" not in parsed:
+        parsed["channels"] = angle_format.get_channels(format_id)
+
+    if "bits" not in parsed:
+        parsed["bits"] = angle_format.get_bits(format_id)
+
+    # Derived values.
+    parsed["mipGenerationFunction"] = get_mip_generation_function(parsed)
+    parsed["colorReadFunction"] = get_color_read_function(parsed)
+
+    for channel in "ABDGLRS":
+        if parsed["bits"] != None and channel in parsed["bits"]:
+            parsed[channel] = parsed["bits"][channel]
+        else:
+            parsed[channel] = "0"
+
+    parsed["namedComponentType"] = get_named_component_type(parsed["componentType"])
+
+    if format_id == "B8G8R8A8_UNORM":
+        parsed["fastCopyFunctions"] = "BGRACopyFunctions"
+
+    return format_entry_template.format(**parsed)
+
+def parse_angle_format_table(all_angle, json_data, angle_to_gl):
+    table_data = ''
+    for format_id in sorted(all_angle):
+        if format_id != "NONE":
+            format_info = json_data[format_id] if format_id in json_data else {}
+            table_data += json_to_table_data(format_id, format_info, angle_to_gl)
+
+    return table_data
+
+def gen_enum_string(all_angle):
+    enum_data = '    NONE'
+    for format_id in sorted(all_angle):
+        if format_id == 'NONE':
+            continue
+        enum_data += ',\n    ' + format_id
+    return enum_data
+
+gl_to_angle = angle_format.load_forward_table('angle_format_map.json')
+angle_to_gl = angle_format.load_inverse_table('angle_format_map.json')
+data_source_name = 'angle_format_data.json'
+json_data = angle_format.load_json(data_source_name)
+all_angle = angle_to_gl.keys()
+
+angle_format_cases = parse_angle_format_table(
+    all_angle, json_data, angle_to_gl)
+output_cpp = template_autogen_inl.format(
+    script_name = sys.argv[0],
+    copyright_year = date.today().year,
+    angle_format_info_cases = angle_format_cases,
+    data_source_name = data_source_name)
+with open('Format_table_autogen.cpp', 'wt') as out_file:
+    out_file.write(output_cpp)
+    out_file.close()
+
+enum_data = gen_enum_string(all_angle)
+output_h = template_autogen_h.format(
+    script_name = sys.argv[0],
+    copyright_year = date.today().year,
+    angle_format_enum = enum_data,
+    data_source_name = data_source_name)
+with open('Format_ID_autogen.inl', 'wt') as out_file:
+    out_file.write(output_h)
+    out_file.close()
diff --git a/src/third_party/angle/src/libANGLE/renderer/gen_load_functions_table.py b/src/third_party/angle/src/libANGLE/renderer/gen_load_functions_table.py
new file mode 100644
index 0000000..eb3e4c5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gen_load_functions_table.py
@@ -0,0 +1,191 @@
+#!/usr/bin/python
+# Copyright 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# gen_load_functions_table.py:
+#  Code generation for the load function tables used for texture formats
+#
+
+import json, sys
+from datetime import date
+
+sys.path.append('../..')
+import angle_format
+
+template = """// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_load_functions_table.py using data from load_functions_data.json
+//
+// Copyright {copyright_year} 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.
+//
+// load_functions_table:
+//   Contains the GetLoadFunctionsMap for texture_format_util.h
+//
+
+#include "libANGLE/renderer/load_functions_table.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+using namespace rx;
+
+namespace angle
+{{
+
+namespace
+{{
+
+// ES3 image loading functions vary based on:
+//    - the GL internal format (supplied to glTex*Image*D)
+//    - the GL data type given (supplied to glTex*Image*D)
+//    - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D
+//    device's capabilities)
+// This map type determines which loading function to use, based on these three parameters.
+// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
+void UnimplementedLoadFunction(size_t width,
+                               size_t height,
+                               size_t depth,
+                               const uint8_t *input,
+                               size_t inputRowPitch,
+                               size_t inputDepthPitch,
+                               uint8_t *output,
+                               size_t outputRowPitch,
+                               size_t outputDepthPitch)
+{{
+    UNIMPLEMENTED();
+}}
+
+void UnreachableLoadFunction(size_t width,
+                             size_t height,
+                             size_t depth,
+                             const uint8_t *input,
+                             size_t inputRowPitch,
+                             size_t inputDepthPitch,
+                             uint8_t *output,
+                             size_t outputRowPitch,
+                             size_t outputDepthPitch)
+{{
+    UNREACHABLE();
+}}
+
+{load_functions_data}}}  // namespace
+
+LoadFunctionMap GetLoadFunctionsMap(GLenum {internal_format}, Format::ID {angle_format})
+{{
+    // clang-format off
+    switch ({internal_format})
+    {{
+{switch_data}
+        default:
+        {{
+            static LoadFunctionMap emptyLoadFunctionsMap;
+            return emptyLoadFunctionsMap;
+        }}
+    }}
+    // clang-format on
+
+}}  // GetLoadFunctionsMap
+
+}}  // namespace angle
+"""
+
+internal_format_param = 'internalFormat'
+angle_format_param = 'angleFormat'
+angle_format_unknown = 'NONE'
+
+def load_functions_name(internal_format, angle_format):
+    return internal_format[3:] + "_to_" + angle_format
+
+def unknown_func_name(internal_format):
+    return load_functions_name(internal_format, "default")
+
+def get_load_func(func_name, type_functions):
+    snippet = "LoadImageFunctionInfo " + func_name + "(GLenum type)\n"
+    snippet += "{\n"
+    snippet += "    switch (type)\n"
+    snippet += "    {\n"
+    for gl_type, load_function in sorted(type_functions.iteritems()):
+        snippet += "        case " + gl_type + ":\n"
+        requiresConversion = str('LoadToNative<' not in load_function).lower()
+        snippet += "            return LoadImageFunctionInfo(" + load_function + ", " + requiresConversion + ");\n"
+    snippet += "        default:\n"
+    snippet += "            UNREACHABLE();\n"
+    snippet += "            return LoadImageFunctionInfo(UnreachableLoadFunction, true);\n"
+    snippet += "    }\n"
+    snippet += "}\n"
+    snippet += "\n"
+
+    return snippet
+
+def get_unknown_load_func(angle_to_type_map, internal_format):
+    assert angle_format_unknown in angle_to_type_map
+    return get_load_func(unknown_func_name(internal_format), angle_to_type_map[angle_format_unknown])
+
+def parse_json(json_data):
+    table_data = ''
+    load_functions_data = ''
+    for internal_format, angle_to_type_map in sorted(json_data.iteritems()):
+
+        s = '        '
+
+        table_data += s + 'case ' + internal_format + ':\n'
+
+        do_switch = len(angle_to_type_map) > 1 or angle_to_type_map.keys()[0] != angle_format_unknown
+
+        if do_switch:
+            table_data += s + '{\n'
+            s += '    '
+            table_data += s + 'switch (' + angle_format_param + ')\n'
+            table_data += s + '{\n'
+            s += '    '
+
+        for angle_format, type_functions in sorted(angle_to_type_map.iteritems()):
+
+            if angle_format == angle_format_unknown:
+                continue
+
+            func_name = load_functions_name(internal_format, angle_format)
+
+            # Main case statements
+            table_data += s + 'case Format::ID::' + angle_format + ':\n'
+            table_data += s + '    return ' + func_name + ';\n'
+
+            if angle_format_unknown in angle_to_type_map:
+                for gl_type, load_function in angle_to_type_map[angle_format_unknown].iteritems():
+                    if gl_type not in type_functions:
+                        type_functions[gl_type] = load_function
+
+            load_functions_data += get_load_func(func_name, type_functions)
+
+        if do_switch:
+            table_data += s + 'default:\n'
+
+        if angle_format_unknown in angle_to_type_map:
+            table_data += s + '    return ' + unknown_func_name(internal_format) + ';\n'
+            load_functions_data += get_unknown_load_func(angle_to_type_map, internal_format)
+        else:
+            table_data += s + '    break;\n'
+
+        if do_switch:
+            s = s[4:]
+            table_data += s + '}\n'
+            s = s[4:]
+            table_data += s + '}\n'
+
+    return table_data, load_functions_data
+
+json_data = angle_format.load_json('load_functions_data.json')
+
+switch_data, load_functions_data = parse_json(json_data)
+output = template.format(internal_format = internal_format_param,
+                         angle_format = angle_format_param,
+                         switch_data = switch_data,
+                         load_functions_data = load_functions_data,
+                         copyright_year = date.today().year)
+
+with open('load_functions_table_autogen.cpp', 'wt') as out_file:
+    out_file.write(output)
+    out_file.close()
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp
new file mode 100644
index 0000000..a3c771a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp
@@ -0,0 +1,668 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BlitGL.cpp: Implements the BlitGL class, a helper for blitting textures
+
+#include "libANGLE/renderer/gl/BlitGL.h"
+
+#include "common/vector_utils.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+
+using angle::Vector2;
+
+namespace rx
+{
+
+namespace
+{
+
+gl::Error CheckCompileStatus(const rx::FunctionsGL *functions, GLuint shader)
+{
+    GLint compileStatus = GL_FALSE;
+    functions->getShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
+
+    ASSERT(compileStatus == GL_TRUE);
+    if (compileStatus == GL_FALSE)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to compile internal blit shader.");
+    }
+
+    return gl::NoError();
+}
+
+gl::Error CheckLinkStatus(const rx::FunctionsGL *functions, GLuint program)
+{
+    GLint linkStatus = GL_FALSE;
+    functions->getProgramiv(program, GL_LINK_STATUS, &linkStatus);
+    ASSERT(linkStatus == GL_TRUE);
+    if (linkStatus == GL_FALSE)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to link internal blit program.");
+    }
+
+    return gl::NoError();
+}
+
+class ScopedGLState : angle::NonCopyable
+{
+  public:
+    enum
+    {
+        KEEP_SCISSOR = 1,
+    };
+
+    ScopedGLState(StateManagerGL *stateManager,
+                  const FunctionsGL *functions,
+                  gl::Rectangle viewport,
+                  int keepState = 0)
+        : mStateManager(stateManager), mFunctions(functions)
+    {
+        if (!(keepState & KEEP_SCISSOR))
+        {
+            mStateManager->setScissorTestEnabled(false);
+        }
+        mStateManager->setViewport(viewport);
+        mStateManager->setDepthRange(0.0f, 1.0f);
+        mStateManager->setBlendEnabled(false);
+        mStateManager->setColorMask(true, true, true, true);
+        mStateManager->setSampleAlphaToCoverageEnabled(false);
+        mStateManager->setSampleCoverageEnabled(false);
+        mStateManager->setDepthTestEnabled(false);
+        mStateManager->setStencilTestEnabled(false);
+        mStateManager->setCullFaceEnabled(false);
+        mStateManager->setPolygonOffsetFillEnabled(false);
+        mStateManager->setRasterizerDiscardEnabled(false);
+
+        mStateManager->pauseTransformFeedback();
+        mStateManager->pauseAllQueries();
+    }
+
+    ~ScopedGLState()
+    {
+        // XFB resuming will be done automatically
+        mStateManager->resumeAllQueries();
+    }
+
+    void willUseTextureUnit(int unit)
+    {
+        if (mFunctions->bindSampler)
+        {
+            mStateManager->bindSampler(unit, 0);
+        }
+    }
+
+  private:
+    StateManagerGL *mStateManager;
+    const FunctionsGL *mFunctions;
+};
+
+}  // anonymous namespace
+
+BlitGL::BlitGL(const FunctionsGL *functions,
+               const WorkaroundsGL &workarounds,
+               StateManagerGL *stateManager)
+    : mFunctions(functions),
+      mWorkarounds(workarounds),
+      mStateManager(stateManager),
+      mBlitProgram(0),
+      mSourceTextureLocation(-1),
+      mScaleLocation(-1),
+      mOffsetLocation(-1),
+      mMultiplyAlphaLocation(-1),
+      mUnMultiplyAlphaLocation(-1),
+      mScratchFBO(0),
+      mVAO(0),
+      mVertexBuffer(0)
+{
+    for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
+    {
+        mScratchTextures[i] = 0;
+    }
+
+    ASSERT(mFunctions);
+    ASSERT(mStateManager);
+}
+
+BlitGL::~BlitGL()
+{
+    if (mBlitProgram != 0)
+    {
+        mStateManager->deleteProgram(mBlitProgram);
+        mBlitProgram = 0;
+    }
+
+    for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
+    {
+        if (mScratchTextures[i] != 0)
+        {
+            mStateManager->deleteTexture(mScratchTextures[i]);
+            mScratchTextures[i] = 0;
+        }
+    }
+
+    if (mScratchFBO != 0)
+    {
+        mStateManager->deleteFramebuffer(mScratchFBO);
+        mScratchFBO = 0;
+    }
+
+    if (mVAO != 0)
+    {
+        mStateManager->deleteVertexArray(mVAO);
+        mVAO = 0;
+    }
+}
+
+gl::Error BlitGL::copyImageToLUMAWorkaroundTexture(GLuint texture,
+                                                   GLenum textureType,
+                                                   GLenum target,
+                                                   GLenum lumaFormat,
+                                                   size_t level,
+                                                   const gl::Rectangle &sourceArea,
+                                                   GLenum internalFormat,
+                                                   const gl::Framebuffer *source)
+{
+    mStateManager->bindTexture(textureType, texture);
+
+    // Allocate the texture memory
+    GLenum format = gl::GetUnsizedFormat(internalFormat);
+
+    gl::PixelUnpackState unpack;
+    mStateManager->setPixelUnpackState(unpack);
+    mFunctions->texImage2D(target, static_cast<GLint>(level), internalFormat, sourceArea.width,
+                           sourceArea.height, 0, format, source->getImplementationColorReadType(),
+                           nullptr);
+
+    return copySubImageToLUMAWorkaroundTexture(texture, textureType, target, lumaFormat, level,
+                                               gl::Offset(0, 0, 0), sourceArea, source);
+}
+
+gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
+                                                      GLenum textureType,
+                                                      GLenum target,
+                                                      GLenum lumaFormat,
+                                                      size_t level,
+                                                      const gl::Offset &destOffset,
+                                                      const gl::Rectangle &sourceArea,
+                                                      const gl::Framebuffer *source)
+{
+    ANGLE_TRY(initializeResources());
+
+    // Blit the framebuffer to the first scratch texture
+    const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
+
+    nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
+        mFunctions, mWorkarounds, source->getImplementationColorReadFormat(),
+        source->getImplementationColorReadType());
+
+    mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
+    mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.x,
+                               sourceArea.y, sourceArea.width, sourceArea.height, 0);
+
+    // Set the swizzle of the scratch texture so that the channels sample into the correct emulated
+    // LUMA channels.
+    GLint swizzle[4] = {
+        (lumaFormat == GL_ALPHA) ? GL_ALPHA : GL_RED,
+        (lumaFormat == GL_LUMINANCE_ALPHA) ? GL_ALPHA : GL_ZERO, GL_ZERO, GL_ZERO,
+    };
+    mFunctions->texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+
+    // Make a temporary framebuffer using the second scratch texture to render the swizzled result
+    // to.
+    mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[1]);
+    mFunctions->texImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.width,
+                           sourceArea.height, 0,
+                           gl::GetUnsizedFormat(copyTexImageFormat.internalFormat),
+                           source->getImplementationColorReadType(), nullptr);
+
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
+    mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                                     mScratchTextures[1], 0);
+
+    // Render to the destination texture, sampling from the scratch texture
+    ScopedGLState scopedState(mStateManager, mFunctions,
+                              gl::Rectangle(0, 0, sourceArea.width, sourceArea.height));
+    scopedState.willUseTextureUnit(0);
+
+    setScratchTextureParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    setScratchTextureParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    mStateManager->activeTexture(0);
+    mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
+
+    mStateManager->useProgram(mBlitProgram);
+    mFunctions->uniform1i(mSourceTextureLocation, 0);
+    mFunctions->uniform2f(mScaleLocation, 1.0, 1.0);
+    mFunctions->uniform2f(mOffsetLocation, 0.0, 0.0);
+    mFunctions->uniform1i(mMultiplyAlphaLocation, 0);
+    mFunctions->uniform1i(mUnMultiplyAlphaLocation, 0);
+
+    mStateManager->bindVertexArray(mVAO, 0);
+    mFunctions->drawArrays(GL_TRIANGLES, 0, 3);
+
+    // Copy the swizzled texture to the destination texture
+    mStateManager->bindTexture(textureType, texture);
+
+    if (target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY)
+    {
+        mFunctions->copyTexSubImage3D(target, static_cast<GLint>(level), destOffset.x, destOffset.y,
+                                      destOffset.z, 0, 0, sourceArea.width, sourceArea.height);
+    }
+    else
+    {
+        mFunctions->copyTexSubImage2D(target, static_cast<GLint>(level), destOffset.x, destOffset.y,
+                                      0, 0, sourceArea.width, sourceArea.height);
+    }
+
+    // Finally orphan the scratch textures so they can be GCed by the driver.
+    orphanScratchTextures();
+
+    return gl::NoError();
+}
+
+gl::Error BlitGL::blitColorBufferWithShader(const gl::Framebuffer *source,
+                                            const gl::Framebuffer *dest,
+                                            const gl::Rectangle &sourceAreaIn,
+                                            const gl::Rectangle &destAreaIn,
+                                            GLenum filter)
+{
+    ANGLE_TRY(initializeResources());
+
+    // Normalize the destination area to have positive width and height because we will use
+    // glViewport to set it, which doesn't allow negative width or height.
+    gl::Rectangle sourceArea = sourceAreaIn;
+    gl::Rectangle destArea   = destAreaIn;
+    if (destArea.width < 0)
+    {
+        destArea.x += destArea.width;
+        destArea.width = -destArea.width;
+        sourceArea.x += sourceArea.width;
+        sourceArea.width = -sourceArea.width;
+    }
+    if (destArea.height < 0)
+    {
+        destArea.y += destArea.height;
+        destArea.height = -destArea.height;
+        sourceArea.y += sourceArea.height;
+        sourceArea.height = -sourceArea.height;
+    }
+
+    const gl::FramebufferAttachment *readAttachment = source->getReadColorbuffer();
+    ASSERT(readAttachment->getSamples() <= 1);
+
+    // Compute the part of the source that will be sampled.
+    gl::Rectangle inBoundsSource;
+    {
+        gl::Extents sourceSize = readAttachment->getSize();
+        gl::Rectangle sourceBounds(0, 0, sourceSize.width, sourceSize.height);
+        gl::ClipRectangle(sourceArea, sourceBounds, &inBoundsSource);
+
+        // Note that inBoundsSource will have lost the orientation information.
+        ASSERT(inBoundsSource.width >= 0 && inBoundsSource.height >= 0);
+
+        // Early out when the sampled part is empty as the blit will be a noop,
+        // and it prevents a division by zero in later computations.
+        if (inBoundsSource.width == 0 || inBoundsSource.height == 0)
+        {
+            return gl::NoError();
+        }
+    }
+
+    // The blit will be emulated by getting the source of the blit in a texture and sampling it
+    // with CLAMP_TO_EDGE. The quad used to draw can trivially compute texture coordinates going
+    // from (0, 0) to (1, 1). These texture coordinates will need to be transformed to make two
+    // regions match:
+    //  - The region of the texture representing the source framebuffer region that will be sampled
+    //  - The region of the drawn quad that corresponds to non-clamped blit, this is the same as the
+    //    region of the source rectangle that is inside the source attachment.
+    //
+    //  These two regions, T (texture) and D (dest) are defined by their offset in texcoord space
+    //  in (0, 1)^2 and their size in texcoord space in (-1, 1)^2. The size can be negative to
+    //  represent the orientation of the blit.
+    //
+    //  Then if P is the quad texcoord, Q the texcoord inside T, and R the texture texcoord:
+    //    - Q = (P - D.offset) / D.size
+    //    - Q = (R - T.offset) / T.size
+    //  Hence R = (P - D.offset) / D.size * T.size - T.offset
+    //          = P * (T.size / D.size) + (T.offset - D.offset * T.size / D.size)
+
+    GLuint textureId;
+    Vector2 TOffset;
+    Vector2 TSize;
+
+    // TODO(cwallez) once texture dirty bits are landed, reuse attached texture instead of using
+    // CopyTexImage2D
+    {
+        textureId = mScratchTextures[0];
+        TOffset   = Vector2(0.0);
+        TSize     = Vector2(1.0);
+        if (sourceArea.width < 0)
+        {
+            TOffset.x() = 1.0;
+            TSize.x()   = -1.0;
+        }
+        if (sourceArea.height < 0)
+        {
+            TOffset.y() = 1.0;
+            TSize.y()   = -1.0;
+        }
+
+        GLenum format                 = readAttachment->getFormat().info->internalFormat;
+        const FramebufferGL *sourceGL = GetImplAs<FramebufferGL>(source);
+        mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceGL->getFramebufferID());
+        mStateManager->bindTexture(GL_TEXTURE_2D, textureId);
+
+        mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, format, inBoundsSource.x, inBoundsSource.y,
+                                   inBoundsSource.width, inBoundsSource.height, 0);
+
+        setScratchTextureParameter(GL_TEXTURE_MIN_FILTER, filter);
+        setScratchTextureParameter(GL_TEXTURE_MAG_FILTER, filter);
+        setScratchTextureParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        setScratchTextureParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    }
+
+    // Compute normalized sampled draw quad region
+    // It is the same as the region of the source rectangle that is in bounds.
+    Vector2 DOffset;
+    Vector2 DSize;
+    {
+        ASSERT(sourceArea.width != 0 && sourceArea.height != 0);
+        gl::Rectangle orientedInBounds = inBoundsSource;
+        if (sourceArea.width < 0)
+        {
+            orientedInBounds.x += orientedInBounds.width;
+            orientedInBounds.width = -orientedInBounds.width;
+        }
+        if (sourceArea.height < 0)
+        {
+            orientedInBounds.y += orientedInBounds.height;
+            orientedInBounds.height = -orientedInBounds.height;
+        }
+
+        DOffset =
+            Vector2(static_cast<float>(orientedInBounds.x - sourceArea.x) / sourceArea.width,
+                    static_cast<float>(orientedInBounds.y - sourceArea.y) / sourceArea.height);
+        DSize = Vector2(static_cast<float>(orientedInBounds.width) / sourceArea.width,
+                        static_cast<float>(orientedInBounds.height) / sourceArea.height);
+    }
+
+    ASSERT(DSize.x() != 0.0 && DSize.y() != 0.0);
+    Vector2 texCoordScale  = TSize / DSize;
+    Vector2 texCoordOffset = TOffset - DOffset * texCoordScale;
+
+    // Reset all the state except scissor and use the viewport to draw exactly to the destination
+    // rectangle
+    ScopedGLState scopedState(mStateManager, mFunctions, destArea, ScopedGLState::KEEP_SCISSOR);
+    scopedState.willUseTextureUnit(0);
+
+    // Set uniforms
+    mStateManager->activeTexture(0);
+    mStateManager->bindTexture(GL_TEXTURE_2D, textureId);
+
+    mStateManager->useProgram(mBlitProgram);
+    mFunctions->uniform1i(mSourceTextureLocation, 0);
+    mFunctions->uniform2f(mScaleLocation, texCoordScale.x(), texCoordScale.y());
+    mFunctions->uniform2f(mOffsetLocation, texCoordOffset.x(), texCoordOffset.y());
+    mFunctions->uniform1i(mMultiplyAlphaLocation, 0);
+    mFunctions->uniform1i(mUnMultiplyAlphaLocation, 0);
+
+    const FramebufferGL *destGL = GetImplAs<FramebufferGL>(dest);
+    mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, destGL->getFramebufferID());
+
+    mStateManager->bindVertexArray(mVAO, 0);
+    mFunctions->drawArrays(GL_TRIANGLES, 0, 3);
+
+    return gl::NoError();
+}
+
+gl::Error BlitGL::copySubTexture(TextureGL *source,
+                                 size_t sourceLevel,
+                                 TextureGL *dest,
+                                 GLenum destTarget,
+                                 size_t destLevel,
+                                 const gl::Extents &sourceSize,
+                                 const gl::Rectangle &sourceArea,
+                                 const gl::Offset &destOffset,
+                                 bool needsLumaWorkaround,
+                                 GLenum lumaFormat,
+                                 bool unpackFlipY,
+                                 bool unpackPremultiplyAlpha,
+                                 bool unpackUnmultiplyAlpha)
+{
+    ANGLE_TRY(initializeResources());
+
+    // Setup the source texture
+    if (needsLumaWorkaround)
+    {
+        GLint luminance = (lumaFormat == GL_ALPHA) ? GL_ZERO : GL_RED;
+
+        GLint alpha = GL_RED;
+        if (lumaFormat == GL_LUMINANCE)
+        {
+            alpha = GL_ONE;
+        }
+        else if (lumaFormat == GL_LUMINANCE_ALPHA)
+        {
+            alpha = GL_GREEN;
+        }
+        else
+        {
+            ASSERT(lumaFormat == GL_ALPHA);
+        }
+
+        GLint swizzle[4] = {luminance, luminance, luminance, alpha};
+        source->setSwizzle(swizzle);
+    }
+    source->setMinFilter(GL_NEAREST);
+    source->setMagFilter(GL_NEAREST);
+    source->setBaseLevel(static_cast<GLuint>(sourceLevel));
+
+    // Render to the destination texture, sampling from the source texture
+    ScopedGLState scopedState(
+        mStateManager, mFunctions,
+        gl::Rectangle(destOffset.x, destOffset.y, sourceArea.width, sourceArea.height));
+    scopedState.willUseTextureUnit(0);
+
+    mStateManager->activeTexture(0);
+    mStateManager->bindTexture(GL_TEXTURE_2D, source->getTextureID());
+
+    Vector2 scale(sourceArea.width / static_cast<float>(sourceSize.width),
+                  sourceArea.height / static_cast<float>(sourceSize.height));
+    Vector2 offset(sourceArea.x / static_cast<float>(sourceSize.width),
+                   sourceArea.y / static_cast<float>(sourceSize.height));
+    if (unpackFlipY)
+    {
+        offset.y() += scale.y();
+        scale.y() = -scale.y();
+    }
+
+    mStateManager->useProgram(mBlitProgram);
+    mFunctions->uniform1i(mSourceTextureLocation, 0);
+    mFunctions->uniform2f(mScaleLocation, scale.x(), scale.y());
+    mFunctions->uniform2f(mOffsetLocation, offset.x(), offset.y());
+    if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+    {
+        mFunctions->uniform1i(mMultiplyAlphaLocation, 0);
+        mFunctions->uniform1i(mUnMultiplyAlphaLocation, 0);
+    }
+    else
+    {
+        mFunctions->uniform1i(mMultiplyAlphaLocation, unpackPremultiplyAlpha);
+        mFunctions->uniform1i(mUnMultiplyAlphaLocation, unpackUnmultiplyAlpha);
+    }
+
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
+    mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destTarget,
+                                     dest->getTextureID(), static_cast<GLint>(destLevel));
+
+    mStateManager->bindVertexArray(mVAO, 0);
+    mFunctions->drawArrays(GL_TRIANGLES, 0, 3);
+
+    return gl::NoError();
+}
+
+gl::Error BlitGL::copyTexSubImage(TextureGL *source,
+                                  TextureGL *dest,
+                                  const gl::Rectangle &sourceArea,
+                                  const gl::Offset &destOffset)
+{
+    ANGLE_TRY(initializeResources());
+
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
+    mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                                     source->getTextureID(), 0);
+
+    mStateManager->bindTexture(dest->getTarget(), dest->getTextureID());
+
+    mFunctions->copyTexSubImage2D(dest->getTarget(), 0, destOffset.x, destOffset.y, sourceArea.x,
+                                  sourceArea.y, sourceArea.width, sourceArea.height);
+
+    return gl::NoError();
+}
+
+gl::Error BlitGL::initializeResources()
+{
+    if (mBlitProgram == 0)
+    {
+        mBlitProgram = mFunctions->createProgram();
+
+        // Compile the fragment shader
+        const char *vsSource =
+            "#version 100\n"
+            "varying vec2 v_texcoord;\n"
+            "uniform vec2 u_scale;\n"
+            "uniform vec2 u_offset;\n"
+            "attribute vec2 a_texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4((a_texcoord * 2.0) - 1.0, 0.0, 1.0);\n"
+            "    v_texcoord = a_texcoord * u_scale + u_offset;\n"
+            "}\n";
+
+        GLuint vs = mFunctions->createShader(GL_VERTEX_SHADER);
+        mFunctions->shaderSource(vs, 1, &vsSource, nullptr);
+        mFunctions->compileShader(vs);
+        ANGLE_TRY(CheckCompileStatus(mFunctions, vs));
+
+        mFunctions->attachShader(mBlitProgram, vs);
+        mFunctions->deleteShader(vs);
+
+        // Compile the vertex shader
+        // It discards if the texcoord is outside (0, 1)^2 so the blitframebuffer workaround
+        // doesn't write when the point sampled is outside of the source framebuffer.
+        const char *fsSource =
+            "#version 100\n"
+            "precision highp float;"
+            "uniform sampler2D u_source_texture;\n"
+            "uniform bool u_multiply_alpha;\n"
+            "uniform bool u_unmultiply_alpha;\n"
+            "varying vec2 v_texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    if (clamp(v_texcoord, vec2(0.0), vec2(1.0)) != v_texcoord)\n"
+            "    {\n"
+            "        discard;\n"
+            "    }\n"
+            "    vec4 color = texture2D(u_source_texture, v_texcoord);\n"
+            "    if (u_multiply_alpha) {color.xyz = color.xyz * color.a;}"
+            "    if (u_unmultiply_alpha && color.a != 0.0) {color.xyz = color.xyz / color.a;}"
+            "    gl_FragColor = color;"
+            "}\n";
+
+        GLuint fs = mFunctions->createShader(GL_FRAGMENT_SHADER);
+        mFunctions->shaderSource(fs, 1, &fsSource, nullptr);
+        mFunctions->compileShader(fs);
+        ANGLE_TRY(CheckCompileStatus(mFunctions, fs));
+
+        mFunctions->attachShader(mBlitProgram, fs);
+        mFunctions->deleteShader(fs);
+
+        mFunctions->linkProgram(mBlitProgram);
+        ANGLE_TRY(CheckLinkStatus(mFunctions, mBlitProgram));
+
+        mTexCoordAttributeLocation = mFunctions->getAttribLocation(mBlitProgram, "a_texcoord");
+        mSourceTextureLocation = mFunctions->getUniformLocation(mBlitProgram, "u_source_texture");
+        mScaleLocation         = mFunctions->getUniformLocation(mBlitProgram, "u_scale");
+        mOffsetLocation        = mFunctions->getUniformLocation(mBlitProgram, "u_offset");
+        mMultiplyAlphaLocation = mFunctions->getUniformLocation(mBlitProgram, "u_multiply_alpha");
+        mUnMultiplyAlphaLocation =
+            mFunctions->getUniformLocation(mBlitProgram, "u_unmultiply_alpha");
+    }
+
+    for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
+    {
+        if (mScratchTextures[i] == 0)
+        {
+            mFunctions->genTextures(1, &mScratchTextures[i]);
+        }
+    }
+
+    if (mScratchFBO == 0)
+    {
+        mFunctions->genFramebuffers(1, &mScratchFBO);
+    }
+
+    if (mVertexBuffer == 0)
+    {
+        mFunctions->genBuffers(1, &mVertexBuffer);
+        mStateManager->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+
+        // Use a single, large triangle, to avoid arithmetic precision issues where fragments
+        // with the same Y coordinate don't get exactly the same interpolated texcoord Y.
+        float vertexData[] = {
+            -0.5f, 0.0f, 1.5f, 0.0f, 0.5f, 2.0f,
+        };
+
+        mFunctions->bufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, vertexData, GL_STATIC_DRAW);
+    }
+
+    if (mVAO == 0)
+    {
+        mFunctions->genVertexArrays(1, &mVAO);
+
+        mStateManager->bindVertexArray(mVAO, 0);
+        mStateManager->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+        mFunctions->enableVertexAttribArray(mTexCoordAttributeLocation);
+        mFunctions->vertexAttribPointer(mTexCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0,
+                                        nullptr);
+    }
+
+    return gl::NoError();
+}
+
+void BlitGL::orphanScratchTextures()
+{
+    for (auto texture : mScratchTextures)
+    {
+        mStateManager->bindTexture(GL_TEXTURE_2D, texture);
+        gl::PixelUnpackState unpack;
+        mStateManager->setPixelUnpackState(unpack);
+        mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                               nullptr);
+    }
+}
+
+void BlitGL::setScratchTextureParameter(GLenum param, GLenum value)
+{
+    for (auto texture : mScratchTextures)
+    {
+        mStateManager->bindTexture(GL_TEXTURE_2D, texture);
+        mFunctions->texParameteri(GL_TEXTURE_2D, param, value);
+        mFunctions->texParameteri(GL_TEXTURE_2D, param, value);
+    }
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h
new file mode 100644
index 0000000..b7ea9e2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h
@@ -0,0 +1,108 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BlitGL.h: Defines the BlitGL class, a helper for blitting textures
+
+#ifndef LIBANGLE_RENDERER_GL_BLITGL_H_
+#define LIBANGLE_RENDERER_GL_BLITGL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+
+class FramebufferGL;
+class FunctionsGL;
+class StateManagerGL;
+class TextureGL;
+struct WorkaroundsGL;
+
+class BlitGL : angle::NonCopyable
+{
+  public:
+    BlitGL(const FunctionsGL *functions,
+           const WorkaroundsGL &workarounds,
+           StateManagerGL *stateManager);
+    ~BlitGL();
+
+    gl::Error copyImageToLUMAWorkaroundTexture(GLuint texture,
+                                               GLenum textureType,
+                                               GLenum target,
+                                               GLenum lumaFormat,
+                                               size_t level,
+                                               const gl::Rectangle &sourceArea,
+                                               GLenum internalFormat,
+                                               const gl::Framebuffer *source);
+
+    gl::Error copySubImageToLUMAWorkaroundTexture(GLuint texture,
+                                                  GLenum textureType,
+                                                  GLenum target,
+                                                  GLenum lumaFormat,
+                                                  size_t level,
+                                                  const gl::Offset &destOffset,
+                                                  const gl::Rectangle &sourceArea,
+                                                  const gl::Framebuffer *source);
+
+    gl::Error blitColorBufferWithShader(const gl::Framebuffer *source,
+                                        const gl::Framebuffer *dest,
+                                        const gl::Rectangle &sourceArea,
+                                        const gl::Rectangle &destArea,
+                                        GLenum filter);
+
+    gl::Error copySubTexture(TextureGL *source,
+                             size_t sourceLevel,
+                             TextureGL *dest,
+                             GLenum destTarget,
+                             size_t destLevel,
+                             const gl::Extents &sourceSize,
+                             const gl::Rectangle &sourceArea,
+                             const gl::Offset &destOffset,
+                             bool needsLumaWorkaround,
+                             GLenum lumaFormat,
+                             bool unpackFlipY,
+                             bool unpackPremultiplyAlpha,
+                             bool unpackUnmultiplyAlpha);
+
+    gl::Error copyTexSubImage(TextureGL *source,
+                              TextureGL *dest,
+                              const gl::Rectangle &sourceArea,
+                              const gl::Offset &destOffset);
+
+    gl::Error initializeResources();
+
+  private:
+    void orphanScratchTextures();
+    void setScratchTextureParameter(GLenum param, GLenum value);
+
+    const FunctionsGL *mFunctions;
+    const WorkaroundsGL &mWorkarounds;
+    StateManagerGL *mStateManager;
+
+    GLuint mBlitProgram;
+    GLint mTexCoordAttributeLocation;
+    GLint mSourceTextureLocation;
+    GLint mScaleLocation;
+    GLint mOffsetLocation;
+    GLint mMultiplyAlphaLocation;
+    GLint mUnMultiplyAlphaLocation;
+
+    GLuint mScratchTextures[2];
+    GLuint mScratchFBO;
+
+    GLuint mVAO;
+    GLuint mVertexBuffer;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_GL_BLITGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/BufferGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/BufferGL.cpp
new file mode 100644
index 0000000..91c8757
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/BufferGL.cpp
@@ -0,0 +1,227 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferGL.cpp: Implements the class methods for BufferGL.
+
+#include "libANGLE/renderer/gl/BufferGL.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace rx
+{
+
+// Use the GL_COPY_READ_BUFFER binding when two buffers need to be bound simultaneously.
+// GL_ELEMENT_ARRAY_BUFFER is supported on more versions but can modify the state of the currently
+// bound VAO.  Two simultaneous buffer bindings are only needed for glCopyBufferSubData which also
+// adds the GL_COPY_READ_BUFFER binding.
+static const GLenum SourceBufferOperationTarget = GL_COPY_READ_BUFFER;
+
+// Use the GL_ELEMENT_ARRAY_BUFFER binding for most operations since it's available on all
+// supported GL versions and doesn't affect any current state when it changes.
+static const GLenum DestBufferOperationTarget = GL_ARRAY_BUFFER;
+
+BufferGL::BufferGL(const gl::BufferState &state,
+                   const FunctionsGL *functions,
+                   StateManagerGL *stateManager)
+    : BufferImpl(state),
+      mIsMapped(false),
+      mMapOffset(0),
+      mMapSize(0),
+      mShadowBufferData(!CanMapBufferForRead(functions)),
+      mShadowCopy(),
+      mBufferSize(0),
+      mFunctions(functions),
+      mStateManager(stateManager),
+      mBufferID(0)
+{
+    ASSERT(mFunctions);
+    ASSERT(mStateManager);
+
+    mFunctions->genBuffers(1, &mBufferID);
+}
+
+BufferGL::~BufferGL()
+{
+    mStateManager->deleteBuffer(mBufferID);
+    mBufferID = 0;
+}
+
+gl::Error BufferGL::setData(ContextImpl * /*context*/,
+                            GLenum /*target*/,
+                            const void *data,
+                            size_t size,
+                            GLenum usage)
+{
+    mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+    mFunctions->bufferData(DestBufferOperationTarget, size, data, usage);
+
+    if (mShadowBufferData)
+    {
+        if (!mShadowCopy.resize(size))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize buffer data shadow copy.");
+        }
+
+        if (size > 0 && data != nullptr)
+        {
+            memcpy(mShadowCopy.data(), data, size);
+        }
+    }
+
+    mBufferSize = size;
+
+    return gl::NoError();
+}
+
+gl::Error BufferGL::setSubData(ContextImpl * /*context*/,
+                               GLenum /*target*/,
+                               const void *data,
+                               size_t size,
+                               size_t offset)
+{
+    mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+    mFunctions->bufferSubData(DestBufferOperationTarget, offset, size, data);
+
+    if (mShadowBufferData && size > 0)
+    {
+        memcpy(mShadowCopy.data() + offset, data, size);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error BufferGL::copySubData(ContextImpl *context,
+                                BufferImpl *source,
+                                GLintptr sourceOffset,
+                                GLintptr destOffset,
+                                GLsizeiptr size)
+{
+    BufferGL *sourceGL = GetAs<BufferGL>(source);
+
+    mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+    mStateManager->bindBuffer(SourceBufferOperationTarget, sourceGL->getBufferID());
+
+    mFunctions->copyBufferSubData(SourceBufferOperationTarget, DestBufferOperationTarget,
+                                  sourceOffset, destOffset, size);
+
+    if (mShadowBufferData && size > 0)
+    {
+        ASSERT(sourceGL->mShadowBufferData);
+        memcpy(mShadowCopy.data() + destOffset, sourceGL->mShadowCopy.data() + sourceOffset, size);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error BufferGL::map(ContextImpl *context, GLenum access, void **mapPtr)
+{
+    if (mShadowBufferData)
+    {
+        *mapPtr = mShadowCopy.data();
+    }
+    else if (mFunctions->mapBuffer)
+    {
+        mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+        *mapPtr = mFunctions->mapBuffer(DestBufferOperationTarget, access);
+    }
+    else
+    {
+        ASSERT(mFunctions->mapBufferRange && access == GL_WRITE_ONLY_OES);
+        mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+        *mapPtr =
+            mFunctions->mapBufferRange(DestBufferOperationTarget, 0, mBufferSize, GL_MAP_WRITE_BIT);
+    }
+
+    mIsMapped  = true;
+    mMapOffset = 0;
+    mMapSize   = mBufferSize;
+
+    return gl::NoError();
+}
+
+gl::Error BufferGL::mapRange(ContextImpl *context,
+                             size_t offset,
+                             size_t length,
+                             GLbitfield access,
+                             void **mapPtr)
+{
+    if (mShadowBufferData)
+    {
+        *mapPtr = mShadowCopy.data() + offset;
+    }
+    else
+    {
+        mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+        *mapPtr = mFunctions->mapBufferRange(DestBufferOperationTarget, offset, length, access);
+    }
+
+    mIsMapped  = true;
+    mMapOffset = offset;
+    mMapSize   = length;
+
+    return gl::NoError();
+}
+
+gl::Error BufferGL::unmap(ContextImpl *context, GLboolean *result)
+{
+    ASSERT(result);
+    ASSERT(mIsMapped);
+
+    if (mShadowBufferData)
+    {
+        mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+        mFunctions->bufferSubData(DestBufferOperationTarget, mMapOffset, mMapSize,
+                                  mShadowCopy.data() + mMapOffset);
+        *result = GL_TRUE;
+    }
+    else
+    {
+        mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+        *result = mFunctions->unmapBuffer(DestBufferOperationTarget);
+    }
+
+    mIsMapped = false;
+    return gl::NoError();
+}
+
+gl::Error BufferGL::getIndexRange(GLenum type,
+                                  size_t offset,
+                                  size_t count,
+                                  bool primitiveRestartEnabled,
+                                  gl::IndexRange *outRange)
+{
+    ASSERT(!mIsMapped);
+
+    if (mShadowBufferData)
+    {
+        *outRange = gl::ComputeIndexRange(type, mShadowCopy.data() + offset, count,
+                                          primitiveRestartEnabled);
+    }
+    else
+    {
+        mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+
+        const gl::Type &typeInfo  = gl::GetTypeInfo(type);
+        const uint8_t *bufferData = MapBufferRangeWithFallback(
+            mFunctions, DestBufferOperationTarget, offset, count * typeInfo.bytes, GL_MAP_READ_BIT);
+        *outRange = gl::ComputeIndexRange(type, bufferData, count, primitiveRestartEnabled);
+        mFunctions->unmapBuffer(DestBufferOperationTarget);
+    }
+
+    return gl::NoError();
+}
+
+GLuint BufferGL::getBufferID() const
+{
+    return mBufferID;
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/BufferGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/BufferGL.h
new file mode 100644
index 0000000..2114ddb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/BufferGL.h
@@ -0,0 +1,78 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferGL.h: Defines the class interface for BufferGL.
+
+#ifndef LIBANGLE_RENDERER_GL_BUFFERGL_H_
+#define LIBANGLE_RENDERER_GL_BUFFERGL_H_
+
+#include "common/MemoryBuffer.h"
+#include "libANGLE/renderer/BufferImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class BufferGL : public BufferImpl
+{
+  public:
+    BufferGL(const gl::BufferState &state,
+             const FunctionsGL *functions,
+             StateManagerGL *stateManager);
+    ~BufferGL() override;
+
+    gl::Error setData(ContextImpl *context,
+                      GLenum target,
+                      const void *data,
+                      size_t size,
+                      GLenum usage) override;
+    gl::Error setSubData(ContextImpl *context,
+                         GLenum target,
+                         const void *data,
+                         size_t size,
+                         size_t offset) override;
+    gl::Error copySubData(ContextImpl *contextImpl,
+                          BufferImpl *source,
+                          GLintptr sourceOffset,
+                          GLintptr destOffset,
+                          GLsizeiptr size) override;
+    gl::Error map(ContextImpl *contextImpl, GLenum access, void **mapPtr) override;
+    gl::Error mapRange(ContextImpl *contextImpl,
+                       size_t offset,
+                       size_t length,
+                       GLbitfield access,
+                       void **mapPtr) override;
+    gl::Error unmap(ContextImpl *contextImpl, GLboolean *result) override;
+
+    gl::Error getIndexRange(GLenum type,
+                            size_t offset,
+                            size_t count,
+                            bool primitiveRestartEnabled,
+                            gl::IndexRange *outRange) override;
+
+    GLuint getBufferID() const;
+
+  private:
+    bool mIsMapped;
+    size_t mMapOffset;
+    size_t mMapSize;
+
+    bool mShadowBufferData;
+    angle::MemoryBuffer mShadowCopy;
+
+    size_t mBufferSize;
+
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+
+    GLuint mBufferID;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_BUFFERGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/CompilerGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/CompilerGL.cpp
new file mode 100644
index 0000000..71be156
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/CompilerGL.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CompilerGL:
+//   Implementation of the GL compiler methods.
+//
+
+#include "libANGLE/renderer/gl/CompilerGL.h"
+
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+namespace rx
+{
+
+namespace
+{
+
+ShShaderOutput GetShaderOutputType(const FunctionsGL *functions)
+{
+    ASSERT(functions);
+
+    if (functions->standard == STANDARD_GL_DESKTOP)
+    {
+        // GLSL outputs
+        if (functions->isAtLeastGL(gl::Version(4, 5)))
+        {
+            return SH_GLSL_450_CORE_OUTPUT;
+        }
+        else if (functions->isAtLeastGL(gl::Version(4, 4)))
+        {
+            return SH_GLSL_440_CORE_OUTPUT;
+        }
+        else if (functions->isAtLeastGL(gl::Version(4, 3)))
+        {
+            return SH_GLSL_430_CORE_OUTPUT;
+        }
+        else if (functions->isAtLeastGL(gl::Version(4, 2)))
+        {
+            return SH_GLSL_420_CORE_OUTPUT;
+        }
+        else if (functions->isAtLeastGL(gl::Version(4, 1)))
+        {
+            return SH_GLSL_410_CORE_OUTPUT;
+        }
+        else if (functions->isAtLeastGL(gl::Version(4, 0)))
+        {
+            return SH_GLSL_400_CORE_OUTPUT;
+        }
+        else if (functions->isAtLeastGL(gl::Version(3, 3)))
+        {
+            return SH_GLSL_330_CORE_OUTPUT;
+        }
+        else if (functions->isAtLeastGL(gl::Version(3, 2)))
+        {
+            return SH_GLSL_150_CORE_OUTPUT;
+        }
+        else if (functions->isAtLeastGL(gl::Version(3, 1)))
+        {
+            return SH_GLSL_140_OUTPUT;
+        }
+        else if (functions->isAtLeastGL(gl::Version(3, 0)))
+        {
+            return SH_GLSL_130_OUTPUT;
+        }
+        else
+        {
+            return SH_GLSL_COMPATIBILITY_OUTPUT;
+        }
+    }
+    else if (functions->standard == STANDARD_GL_ES)
+    {
+        // ESSL outputs
+        return SH_ESSL_OUTPUT;
+    }
+    else
+    {
+        UNREACHABLE();
+        return ShShaderOutput(0);
+    }
+}
+
+}  // anonymous namespace
+
+CompilerGL::CompilerGL(const FunctionsGL *functions)
+    : mTranslatorOutputType(GetShaderOutputType(functions))
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/CompilerGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/CompilerGL.h
new file mode 100644
index 0000000..4c4104f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/CompilerGL.h
@@ -0,0 +1,33 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompilerGL.h: Defines the class interface for CompilerGL.
+
+#ifndef LIBANGLE_RENDERER_GL_COMPILERGL_H_
+#define LIBANGLE_RENDERER_GL_COMPILERGL_H_
+
+#include "libANGLE/renderer/CompilerImpl.h"
+
+namespace rx
+{
+class FunctionsGL;
+
+class CompilerGL : public CompilerImpl
+{
+  public:
+    CompilerGL(const FunctionsGL *functions);
+    ~CompilerGL() override {}
+
+    gl::Error release() override { return gl::NoError(); }
+    ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; }
+
+  private:
+    ShShaderOutput mTranslatorOutputType;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_COMPILERGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/ContextGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/ContextGL.cpp
new file mode 100644
index 0000000..7093caf
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/ContextGL.cpp
@@ -0,0 +1,392 @@
+//
+// Copyright 2016 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.
+//
+// ContextGL:
+//   OpenGL-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/gl/ContextGL.h"
+
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/CompilerGL.h"
+#include "libANGLE/renderer/gl/FenceNVGL.h"
+#include "libANGLE/renderer/gl/FenceSyncGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/PathGL.h"
+#include "libANGLE/renderer/gl/ProgramGL.h"
+#include "libANGLE/renderer/gl/QueryGL.h"
+#include "libANGLE/renderer/gl/RenderbufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/SamplerGL.h"
+#include "libANGLE/renderer/gl/ShaderGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
+#include "libANGLE/renderer/gl/VertexArrayGL.h"
+
+namespace rx
+{
+
+ContextGL::ContextGL(const gl::ContextState &state, RendererGL *renderer)
+    : ContextImpl(state), mRenderer(renderer)
+{
+}
+
+ContextGL::~ContextGL()
+{
+}
+
+gl::Error ContextGL::initialize()
+{
+    return gl::NoError();
+}
+
+CompilerImpl *ContextGL::createCompiler()
+{
+    return new CompilerGL(getFunctions());
+}
+
+ShaderImpl *ContextGL::createShader(const gl::ShaderState &data)
+{
+    return new ShaderGL(data, getFunctions(), getWorkaroundsGL());
+}
+
+ProgramImpl *ContextGL::createProgram(const gl::ProgramState &data)
+{
+    return new ProgramGL(data, getFunctions(), getWorkaroundsGL(), getStateManager(),
+                         getExtensions().pathRendering);
+}
+
+FramebufferImpl *ContextGL::createFramebuffer(const gl::FramebufferState &data)
+{
+    return new FramebufferGL(data, getFunctions(), getStateManager(), getWorkaroundsGL(),
+                             mRenderer->getBlitter(), false);
+}
+
+TextureImpl *ContextGL::createTexture(const gl::TextureState &state)
+{
+    return new TextureGL(state, getFunctions(), getWorkaroundsGL(), getStateManager(),
+                         mRenderer->getBlitter());
+}
+
+RenderbufferImpl *ContextGL::createRenderbuffer()
+{
+    return new RenderbufferGL(getFunctions(), getWorkaroundsGL(), getStateManager(),
+                              getNativeTextureCaps());
+}
+
+BufferImpl *ContextGL::createBuffer(const gl::BufferState &state)
+{
+    return new BufferGL(state, getFunctions(), getStateManager());
+}
+
+VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data)
+{
+    return new VertexArrayGL(data, getFunctions(), getStateManager());
+}
+
+QueryImpl *ContextGL::createQuery(GLenum type)
+{
+    switch (type)
+    {
+        case GL_COMMANDS_COMPLETED_CHROMIUM:
+            return new SyncQueryGL(type, getFunctions(), getStateManager());
+
+        default:
+            return new StandardQueryGL(type, getFunctions(), getStateManager());
+    }
+}
+
+FenceNVImpl *ContextGL::createFenceNV()
+{
+    return new FenceNVGL(getFunctions());
+}
+
+FenceSyncImpl *ContextGL::createFenceSync()
+{
+    return new FenceSyncGL(getFunctions());
+}
+
+TransformFeedbackImpl *ContextGL::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+    return new TransformFeedbackGL(state, getFunctions(), getStateManager());
+}
+
+SamplerImpl *ContextGL::createSampler()
+{
+    return new SamplerGL(getFunctions(), getStateManager());
+}
+
+std::vector<PathImpl *> ContextGL::createPaths(GLsizei range)
+{
+    const FunctionsGL *funcs = getFunctions();
+
+    std::vector<PathImpl *> ret;
+    ret.reserve(range);
+
+    const GLuint first = funcs->genPathsNV(range);
+    if (first == 0)
+        return ret;
+
+    for (GLsizei i = 0; i < range; ++i)
+    {
+        const auto id = first + i;
+        ret.push_back(new PathGL(funcs, id));
+    }
+
+    return ret;
+}
+
+gl::Error ContextGL::flush()
+{
+    return mRenderer->flush();
+}
+
+gl::Error ContextGL::finish()
+{
+    return mRenderer->finish();
+}
+
+gl::Error ContextGL::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    return mRenderer->drawArrays(mState, mode, first, count);
+}
+
+gl::Error ContextGL::drawArraysInstanced(GLenum mode,
+                                         GLint first,
+                                         GLsizei count,
+                                         GLsizei instanceCount)
+{
+    return mRenderer->drawArraysInstanced(mState, mode, first, count, instanceCount);
+}
+
+gl::Error ContextGL::drawElements(GLenum mode,
+                                  GLsizei count,
+                                  GLenum type,
+                                  const void *indices,
+                                  const gl::IndexRange &indexRange)
+{
+    return mRenderer->drawElements(mState, mode, count, type, indices, indexRange);
+}
+
+gl::Error ContextGL::drawElementsInstanced(GLenum mode,
+                                           GLsizei count,
+                                           GLenum type,
+                                           const void *indices,
+                                           GLsizei instances,
+                                           const gl::IndexRange &indexRange)
+{
+    return mRenderer->drawElementsInstanced(mState, mode, count, type, indices, instances,
+                                            indexRange);
+}
+
+gl::Error ContextGL::drawRangeElements(GLenum mode,
+                                       GLuint start,
+                                       GLuint end,
+                                       GLsizei count,
+                                       GLenum type,
+                                       const void *indices,
+                                       const gl::IndexRange &indexRange)
+{
+    return mRenderer->drawRangeElements(mState, mode, start, end, count, type, indices, indexRange);
+}
+
+gl::Error ContextGL::drawArraysIndirect(GLenum mode, const void *indirect)
+{
+    return mRenderer->drawArraysIndirect(mState, mode, indirect);
+}
+
+gl::Error ContextGL::drawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+    return mRenderer->drawElementsIndirect(mState, mode, type, indirect);
+}
+
+void ContextGL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
+{
+    mRenderer->stencilFillPath(mState, path, fillMode, mask);
+}
+
+void ContextGL::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
+{
+    mRenderer->stencilStrokePath(mState, path, reference, mask);
+}
+
+void ContextGL::coverFillPath(const gl::Path *path, GLenum coverMode)
+{
+    mRenderer->coverFillPath(mState, path, coverMode);
+}
+
+void ContextGL::coverStrokePath(const gl::Path *path, GLenum coverMode)
+{
+    mRenderer->coverStrokePath(mState, path, coverMode);
+}
+
+void ContextGL::stencilThenCoverFillPath(const gl::Path *path,
+                                         GLenum fillMode,
+                                         GLuint mask,
+                                         GLenum coverMode)
+{
+    mRenderer->stencilThenCoverFillPath(mState, path, fillMode, mask, coverMode);
+}
+
+void ContextGL::stencilThenCoverStrokePath(const gl::Path *path,
+                                           GLint reference,
+                                           GLuint mask,
+                                           GLenum coverMode)
+{
+    mRenderer->stencilThenCoverStrokePath(mState, path, reference, mask, coverMode);
+}
+
+void ContextGL::coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                       GLenum coverMode,
+                                       GLenum transformType,
+                                       const GLfloat *transformValues)
+{
+    mRenderer->coverFillPathInstanced(mState, paths, coverMode, transformType, transformValues);
+}
+
+void ContextGL::coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                         GLenum coverMode,
+                                         GLenum transformType,
+                                         const GLfloat *transformValues)
+{
+    mRenderer->coverStrokePathInstanced(mState, paths, coverMode, transformType, transformValues);
+}
+
+void ContextGL::stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                         GLenum fillMode,
+                                         GLuint mask,
+                                         GLenum transformType,
+                                         const GLfloat *transformValues)
+{
+    mRenderer->stencilFillPathInstanced(mState, paths, fillMode, mask, transformType,
+                                        transformValues);
+}
+
+void ContextGL::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                           GLint reference,
+                                           GLuint mask,
+                                           GLenum transformType,
+                                           const GLfloat *transformValues)
+{
+    mRenderer->stencilStrokePathInstanced(mState, paths, reference, mask, transformType,
+                                          transformValues);
+}
+
+void ContextGL::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                                  GLenum coverMode,
+                                                  GLenum fillMode,
+                                                  GLuint mask,
+                                                  GLenum transformType,
+                                                  const GLfloat *transformValues)
+{
+    mRenderer->stencilThenCoverFillPathInstanced(mState, paths, coverMode, fillMode, mask,
+                                                 transformType, transformValues);
+}
+
+void ContextGL::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                                    GLenum coverMode,
+                                                    GLint reference,
+                                                    GLuint mask,
+                                                    GLenum transformType,
+                                                    const GLfloat *transformValues)
+{
+    mRenderer->stencilThenCoverStrokePathInstanced(mState, paths, coverMode, reference, mask,
+                                                   transformType, transformValues);
+}
+
+GLenum ContextGL::getResetStatus()
+{
+    return mRenderer->getResetStatus();
+}
+
+std::string ContextGL::getVendorString() const
+{
+    return mRenderer->getVendorString();
+}
+
+std::string ContextGL::getRendererDescription() const
+{
+    return mRenderer->getRendererDescription();
+}
+
+void ContextGL::insertEventMarker(GLsizei length, const char *marker)
+{
+    mRenderer->insertEventMarker(length, marker);
+}
+
+void ContextGL::pushGroupMarker(GLsizei length, const char *marker)
+{
+    mRenderer->pushGroupMarker(length, marker);
+}
+
+void ContextGL::popGroupMarker()
+{
+    mRenderer->popGroupMarker();
+}
+
+void ContextGL::syncState(const gl::State::DirtyBits &dirtyBits)
+{
+    mRenderer->getStateManager()->syncState(mState, dirtyBits);
+}
+
+GLint ContextGL::getGPUDisjoint()
+{
+    return mRenderer->getGPUDisjoint();
+}
+
+GLint64 ContextGL::getTimestamp()
+{
+    return mRenderer->getTimestamp();
+}
+
+void ContextGL::onMakeCurrent(const gl::ContextState &data)
+{
+    // Queries need to be paused/resumed on context switches
+    mRenderer->getStateManager()->onMakeCurrent(data);
+}
+
+const gl::Caps &ContextGL::getNativeCaps() const
+{
+    return mRenderer->getNativeCaps();
+}
+
+const gl::TextureCapsMap &ContextGL::getNativeTextureCaps() const
+{
+    return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &ContextGL::getNativeExtensions() const
+{
+    return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &ContextGL::getNativeLimitations() const
+{
+    return mRenderer->getNativeLimitations();
+}
+
+const FunctionsGL *ContextGL::getFunctions() const
+{
+    return mRenderer->getFunctions();
+}
+
+StateManagerGL *ContextGL::getStateManager()
+{
+    return mRenderer->getStateManager();
+}
+
+const WorkaroundsGL &ContextGL::getWorkaroundsGL() const
+{
+    return mRenderer->getWorkarounds();
+}
+
+gl::Error ContextGL::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+    return mRenderer->dispatchCompute(mState, numGroupsX, numGroupsY, numGroupsZ);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/ContextGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/ContextGL.h
new file mode 100644
index 0000000..2e8a162
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/ContextGL.h
@@ -0,0 +1,187 @@
+//
+// Copyright 2016 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.
+//
+// ContextGL:
+//   OpenGL-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_GL_CONTEXTGL_H_
+#define LIBANGLE_RENDERER_GL_CONTEXTGL_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace sh
+{
+struct BlockMemberInfo;
+}
+
+namespace rx
+{
+class FunctionsGL;
+class RendererGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class ContextGL : public ContextImpl
+{
+  public:
+    ContextGL(const gl::ContextState &state, RendererGL *renderer);
+    ~ContextGL() override;
+
+    gl::Error initialize() override;
+
+    // Shader creation
+    CompilerImpl *createCompiler() override;
+    ShaderImpl *createShader(const gl::ShaderState &data) override;
+    ProgramImpl *createProgram(const gl::ProgramState &data) override;
+
+    // Framebuffer creation
+    FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override;
+
+    // Texture creation
+    TextureImpl *createTexture(const gl::TextureState &state) override;
+
+    // Renderbuffer creation
+    RenderbufferImpl *createRenderbuffer() override;
+
+    // Buffer creation
+    BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+    // Vertex Array creation
+    VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override;
+
+    // Query and Fence creation
+    QueryImpl *createQuery(GLenum type) override;
+    FenceNVImpl *createFenceNV() override;
+    FenceSyncImpl *createFenceSync() override;
+
+    // Transform Feedback creation
+    TransformFeedbackImpl *createTransformFeedback(
+        const gl::TransformFeedbackState &state) override;
+
+    // Sampler object creation
+    SamplerImpl *createSampler() override;
+
+    // Path object creation
+    std::vector<PathImpl *> createPaths(GLsizei range) override;
+
+    // Flush and finish.
+    gl::Error flush() override;
+    gl::Error finish() override;
+
+    // Drawing methods.
+    gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+    gl::Error drawArraysInstanced(GLenum mode,
+                                  GLint first,
+                                  GLsizei count,
+                                  GLsizei instanceCount) override;
+
+    gl::Error drawElements(GLenum mode,
+                           GLsizei count,
+                           GLenum type,
+                           const void *indices,
+                           const gl::IndexRange &indexRange) override;
+    gl::Error drawElementsInstanced(GLenum mode,
+                                    GLsizei count,
+                                    GLenum type,
+                                    const void *indices,
+                                    GLsizei instances,
+                                    const gl::IndexRange &indexRange) override;
+    gl::Error drawRangeElements(GLenum mode,
+                                GLuint start,
+                                GLuint end,
+                                GLsizei count,
+                                GLenum type,
+                                const void *indices,
+                                const gl::IndexRange &indexRange) override;
+    gl::Error drawArraysIndirect(GLenum mode, const void *indirect) override;
+    gl::Error drawElementsIndirect(GLenum mode, GLenum type, const void *indirect) override;
+
+    // CHROMIUM_path_rendering implementation
+    void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override;
+    void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask) override;
+    void coverFillPath(const gl::Path *path, GLenum coverMode) override;
+    void coverStrokePath(const gl::Path *path, GLenum coverMode) override;
+    void stencilThenCoverFillPath(const gl::Path *path,
+                                  GLenum fillMode,
+                                  GLuint mask,
+                                  GLenum coverMode) override;
+    void stencilThenCoverStrokePath(const gl::Path *path,
+                                    GLint reference,
+                                    GLuint mask,
+                                    GLenum coverMode) override;
+    void coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                GLenum coverMode,
+                                GLenum transformType,
+                                const GLfloat *transformValues) override;
+    void coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                  GLenum coverMode,
+                                  GLenum transformType,
+                                  const GLfloat *transformValues) override;
+    void stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                  GLenum fillMode,
+                                  GLuint mask,
+                                  GLenum transformType,
+                                  const GLfloat *transformValues) override;
+    void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                    GLint reference,
+                                    GLuint mask,
+                                    GLenum transformType,
+                                    const GLfloat *transformValues) override;
+    void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                           GLenum coverMode,
+                                           GLenum fillMode,
+                                           GLuint mask,
+                                           GLenum transformType,
+                                           const GLfloat *transformValues) override;
+    void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                             GLenum coverMode,
+                                             GLint reference,
+                                             GLuint mask,
+                                             GLenum transformType,
+                                             const GLfloat *transformValues) override;
+
+    // Device loss
+    GLenum getResetStatus() override;
+
+    // Vendor and description strings.
+    std::string getVendorString() const override;
+    std::string getRendererDescription() const override;
+
+    // Debug markers.
+    void insertEventMarker(GLsizei length, const char *marker) override;
+    void pushGroupMarker(GLsizei length, const char *marker) override;
+    void popGroupMarker() override;
+
+    // State sync with dirty bits.
+    void syncState(const gl::State::DirtyBits &dirtyBits) override;
+
+    // Disjoint timer queries
+    GLint getGPUDisjoint() override;
+    GLint64 getTimestamp() override;
+
+    // Context switching
+    void onMakeCurrent(const gl::ContextState &data) override;
+
+    // Caps queries
+    const gl::Caps &getNativeCaps() const override;
+    const gl::TextureCapsMap &getNativeTextureCaps() const override;
+    const gl::Extensions &getNativeExtensions() const override;
+    const gl::Limitations &getNativeLimitations() const override;
+
+    // Handle helpers
+    const FunctionsGL *getFunctions() const;
+    StateManagerGL *getStateManager();
+    const WorkaroundsGL &getWorkaroundsGL() const;
+
+    gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
+
+  private:
+    RendererGL *mRenderer;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_CONTEXTGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp
new file mode 100644
index 0000000..f951c23
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp
@@ -0,0 +1,117 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayGL.h: GL implementation of egl::Display
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/ContextGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+DisplayGL::DisplayGL(const egl::DisplayState &state)
+    : DisplayImpl(state), mRenderer(nullptr), mCurrentDrawSurface(nullptr)
+{
+}
+
+DisplayGL::~DisplayGL()
+{
+}
+
+egl::Error DisplayGL::initialize(egl::Display *display)
+{
+    mRenderer = new RendererGL(getFunctionsGL(), display->getAttributeMap());
+
+    const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
+    if (maxVersion < gl::Version(2, 0))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "OpenGL ES 2.0 is not supportable.");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayGL::terminate()
+{
+    SafeDelete(mRenderer);
+}
+
+ImageImpl *DisplayGL::createImage(const egl::ImageState &state,
+                                  EGLenum target,
+                                  const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+ContextImpl *DisplayGL::createContext(const gl::ContextState &state)
+{
+    ASSERT(mRenderer != nullptr);
+    return new ContextGL(state, mRenderer);
+}
+
+StreamProducerImpl *DisplayGL::createStreamProducerD3DTextureNV12(
+    egl::Stream::ConsumerType consumerType,
+    const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+{
+    // Notify the previous surface (if it still exists) that it is no longer current
+    if (mCurrentDrawSurface &&
+        mState.surfaceSet.find(mCurrentDrawSurface) != mState.surfaceSet.end())
+    {
+        ANGLE_TRY(GetImplAs<SurfaceGL>(mCurrentDrawSurface)->unMakeCurrent());
+    }
+    mCurrentDrawSurface = nullptr;
+
+    if (!context)
+    {
+        return egl::Error(EGL_SUCCESS);
+    }
+
+    // Pause transform feedback before making a new surface current, to workaround anglebug.com/1426
+    ContextGL *glContext = GetImplAs<ContextGL>(context);
+    glContext->getStateManager()->pauseTransformFeedback();
+
+    if (drawSurface != nullptr)
+    {
+        SurfaceGL *glDrawSurface = GetImplAs<SurfaceGL>(drawSurface);
+        ANGLE_TRY(glDrawSurface->makeCurrent());
+        mCurrentDrawSurface = drawSurface;
+        return egl::Error(EGL_SUCCESS);
+    }
+    else
+    {
+        return makeCurrentSurfaceless(context);
+    }
+}
+
+gl::Version DisplayGL::getMaxSupportedESVersion() const
+{
+    ASSERT(mRenderer != nullptr);
+    return mRenderer->getMaxSupportedESVersion();
+}
+
+egl::Error DisplayGL::makeCurrentSurfaceless(gl::Context *context)
+{
+    UNIMPLEMENTED();
+    return egl::NoError();
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.h
new file mode 100644
index 0000000..0f4f2aa
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.h
@@ -0,0 +1,62 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayGL.h: Defines the class interface for DisplayGL.
+
+#ifndef LIBANGLE_RENDERER_GL_DISPLAYGL_H_
+#define LIBANGLE_RENDERER_GL_DISPLAYGL_H_
+
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+namespace egl
+{
+class Surface;
+}
+
+namespace rx
+{
+
+class RendererGL;
+
+class DisplayGL : public DisplayImpl
+{
+  public:
+    DisplayGL(const egl::DisplayState &state);
+    ~DisplayGL() override;
+
+    egl::Error initialize(egl::Display *display) override;
+    void terminate() override;
+
+    ImageImpl *createImage(const egl::ImageState &state,
+                           EGLenum target,
+                           const egl::AttributeMap &attribs) override;
+
+    ContextImpl *createContext(const gl::ContextState &state) override;
+
+    StreamProducerImpl *createStreamProducerD3DTextureNV12(
+        egl::Stream::ConsumerType consumerType,
+        const egl::AttributeMap &attribs) override;
+
+    egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
+
+    gl::Version getMaxSupportedESVersion() const override;
+
+  protected:
+    RendererGL *getRenderer() const { return mRenderer; };
+
+  private:
+    virtual const FunctionsGL *getFunctionsGL() const = 0;
+    virtual egl::Error makeCurrentSurfaceless(gl::Context *context);
+
+    RendererGL *mRenderer;
+
+    egl::Surface *mCurrentDrawSurface;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_DISPLAYGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md b/src/third_party/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md
new file mode 100644
index 0000000..edc2353
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md
@@ -0,0 +1,107 @@
+# ANGLE RendererGL feature support
+Documentation of OpenGL ES and EGL features, caps and formats and required extensions.
+
+## OpenGL ES Feature Support
+|Feature|OpenGL version|OpenGL extension|OpenGL ES version|OpenGL ES extension|Notes|
+|---|---|---|---|---|---|
+|Framebuffer/renderbuffer objects|3.0|[GL_EXT_framebuffer_object](https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt)|2.0|--|Can potentially be emulated with Pbuffers but realistically this extension is always required.|
+|Blit framebuffer|3.0|[GL_EXT_framebuffer_blit](https://www.opengl.org/registry/specs/EXT/framebuffer_blit.txt)|3.0|[GL_ANGLE_framebuffer_blit](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_blit.txt) or [GL_NV_framebuffer_blit](https://www.khronos.org/registry/gles/extensions/NV/NV_framebuffer_blit.txt)||
+|Multisampling|3.0|[GL_EXT_framebuffer_multisample](https://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt)|3.0|[GL_EXT_multisampled_render_to_texture](https://www.khronos.org/registry/gles/extensions/EXT/EXT_multisampled_render_to_texture.txt) or [GL_ANGLE_framebuffer_multisample](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_multisample.txt)||
+|Depth textures|3.0|[GL_ARB_depth_texture](https://www.opengl.org/registry/specs/ARB/depth_texture.txt)|3.0|[GL_OES_depth_texture](https://www.khronos.org/registry/gles/extensions/OES/OES_depth_texture.txt) or [GL_ANGLE_depth_texture](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_depth_texture.txt)
+|Draw buffers (MRT)|2.0?|[GL_ARB_draw_buffers](https://www.opengl.org/registry/specs/ARB/draw_buffers.txt) or [GL_EXT_draw_buffers2](https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt)|3.0|[GL_EXT_draw_buffers](https://www.khronos.org/registry/gles/extensions/EXT/EXT_draw_buffers.txt)||
+|3D textures|1.2|[GL_EXT_texture3D](https://www.opengl.org/registry/specs/EXT/texture3D.txt)|3.0|[GL_OES_texture_3D](https://www.khronos.org/registry/gles/extensions/OES/OES_texture_3D.txt)||
+|Array textures|3.0|[GL_EXT_texture_array](https://www.opengl.org/registry/specs/EXT/texture_array.txt)|3.0|--||
+|Texture storage|4.2|[GL_EXT_texture_storage](https://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_storage.txt)|3.0|[GL_EXT_texture_storage](https://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_storage.txt)|Can be emulated with TexImage calls.|
+|Uniform buffer object|3.1|[GL_ARB_uniform_buffer_object](https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt)|3.0|--||
+|Sync objects|3.2|[GL_ARB_sync](https://www.opengl.org/registry/specs/ARB/sync.txt)|3.0|--||
+|Fence objects|--|[GL_NV_fence](https://www.opengl.org/registry/specs/NV/fence.txt)|--|[GL_NV_fence](https://www.opengl.org/registry/specs/NV/fence.txt)||
+|MapBuffer|1.5|--|--|[GL_OES_mapbuffer](https://www.khronos.org/registry/gles/extensions/OES/OES_mapbuffer.txt)||
+|MapBufferRange|3.0|[GL_ARB_map_buffer_range](https://www.opengl.org/registry/specs/ARB/map_buffer_range.txt)|3.0|[GL_EXT_map_buffer_range](https://www.khronos.org/registry/gles/extensions/EXT/EXT_map_buffer_range.txt)||
+|Transform feedback|3.0|[GL_EXT_transform_feedback](GL_EXT_transform_feedback) or [GL_EXT_transform_feedback2](http://developer.download.nvidia.com/opengl/specs/GL_EXT_transform_feedback2.txt) or [GL_ARB_transform_feedback3](https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt)|3.0|--||
+|Sampler object|3.3|[GL_ARB_sampler_objects](https://www.opengl.org/registry/specs/ARB/sampler_objects.txt)|3.0|--||
+|Occlusion query|1.5|[GL_ARB_occlusion_query](https://www.opengl.org/registry/specs/ARB/occlusion_query.txt)|2.0|--||
+|Timer query|3.3|[GL_ARB_timer_query](https://www.opengl.org/registry/specs/ARB/timer_query.txt)|--|[GL_EXT_disjoint_timer_query](https://www.khronos.org/registry/gles/extensions/EXT/EXT_disjoint_timer_query.txt)||
+|Vertex array object|3.0|[GL_ARB_vertex_array_object](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt)|3.0|[GL_OES_vertex_array_object](https://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt)|Can be emulated but costsmany extra API calls.  Virtualized contexts also require some kind of emulation of the default attribute state.|
+|Anisotropic filtering|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|Ubiquitous extension.|
+
+## OpenGL ES Caps
+|Cap(s)|OpenGL version|OpenGL extension|OpenGL ES version|OpenGL ES extension|Notes|
+|---|---|---|---|---|---|
+|GL_MAX_ELEMENT_INDEX|4.3|[GL_ARB_ES3_compatibility](https://www.opengl.org/registry/specs/ARB/ES3_compatibility.txt)|3.0|--|Seems pretty safe to use an arbitrary limit, all implementations tested return 0xFFFFFFFF.|
+|GL_MAX_3D_TEXTURE_SIZE|1.2|[GL_EXT_texture3D](https://www.opengl.org/registry/specs/EXT/texture3D.txt)|3.0|[GL_OES_texture_3D](https://www.khronos.org/registry/gles/extensions/OES/OES_texture_3D.txt)||
+|GL_MAX_TEXTURE_SIZE|1.0|--|2.0|--||
+|GL_MAX_CUBE_MAP_TEXTURE_SIZE|1.3|--|2.0||
+|GL_MAX_ARRAY_TEXTURE_LAYERS|3.0|[GL_EXT_texture_array](https://www.opengl.org/registry/specs/EXT/texture_array.txt)|3.0|--||
+|GL_MAX_TEXTURE_LOD_BIAS|1.5|[GL_EXT_texture_lod_bias](https://www.opengl.org/registry/specs/EXT/texture_lod_bias.txt)|3.0|--||
+|GL_MAX_RENDERBUFFER_SIZE GL_MAX_COLOR_ATTACHMENTS|3.0|[GL_EXT_framebuffer_object](https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt) |2.0|--||
+|GL_MAX_DRAW_BUFFERS|2.0?|[GL_ARB_draw_buffers](https://www.opengl.org/registry/specs/ARB/draw_buffers.txt) or [GL_EXT_draw_buffers2](https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt)|3.0|[GL_EXT_draw_buffers](https://www.khronos.org/registry/gles/extensions/EXT/EXT_draw_buffers.txt)||
+|GL_MAX_VIEWPORT_DIMS|1.0|--|2.0|--||
+|GL_ALIASED_POINT_SIZE_RANGE|1.0?|--|2.0|--||
+|GL_ALIASED_LINE_WIDTH_RANGE|1.2|--|2.0|--||
+|GL_ALIASED_LINE_WIDTH_RANGE|1.2|--|2.0|--||
+|GL_MAX_ELEMENTS_INDICES|1.2|--|3.0|--||
+|GL_MAX_ELEMENTS_VERTICES|1.2|--|3.0|--||
+|Shader format precision (glGetShaderPrecisionFormat)|4.1|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Can use reasonable default values (IEEE float and twos complement integer).|
+|GL_MAX_VERTEX_ATTRIBS|2.0|--|2.0|--||
+|GL_MAX_VERTEX_UNIFORM_COMPONENTS|2.0|--|2.0|--||
+|GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS|2.0|--|2.0|--||
+|GL_MAX_VERTEX_UNIFORM_VECTORS GL_MAX_FRAGMENT_UNIFORM_VECTORS|4.1|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Defined as GL_MAX_VERTEX_UNIFORM_COMPONENTS / 4 and GL_MAX_FRAGMENT_UNIFORM_COMPONENTS / 4.  Can simply use those values when the cap is not available.|
+|GL_MAX_VERTEX_UNIFORM_BLOCKS GL_MAX_FRAGMENT_UNIFORM_BLOCKS GL_MAX_UNIFORM_BUFFER_BINDINGS GL_MAX_UNIFORM_BLOCK_SIZE GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT GL_MAX_COMBINED_UNIFORM_BLOCKS GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS |3.1|[GL_ARB_uniform_buffer_object](https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt)|3.0|--||
+|GL_MAX_VERTEX_OUTPUT_COMPONENTS|3.2|--|3.0|--|Doesn't seem to be a desktop extension for this cap, it may be possible to use the minimum ES3 value (64) if lower than GL 3.2.|
+|GL_MAX_FRAGMENT_UNIFORM_COMPONENTS|2.0|--|2.0|--||
+|GL_MAX_TEXTURE_IMAGE_UNITS|2.0|--|2.0|--||
+|GL_MAX_FRAGMENT_INPUT_COMPONENTS|3.2|--|3.0|--|Doesn't seem to be a desktop extension for this cap either, it may be possible to use the minimum ES3 value (60) if lower than GL 3.2.|
+|GL_MIN_PROGRAM_TEXEL_OFFSET GL_MAX_PROGRAM_TEXEL_OFFSET|3.0|--|3.0|--|Could potentially be emulated in the shader by adding the offsets in normalized texture coordinates before sampling.|
+|GL_MAX_VARYING_COMPONENTS|3.0|[GL_ARB_ES3_compatibility](https://www.opengl.org/registry/specs/ARB/ES3_compatibility.txt)|3.0|--|Was depricated in the OpenGL core spec but re-added in GL_ARB_ES3_compatibility|
+|GL_MAX_VARYING_VECTORS|4.1|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Defined as GL_MAX_VARYING_COMPONENTS / 4.|
+|GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS|3.0|[GL_EXT_transform_feedback](GL_EXT_transform_feedback) or [GL_EXT_transform_feedback2](http://developer.download.nvidia.com/opengl/specs/GL_EXT_transform_feedback2.txt) or [GL_ARB_transform_feedback3](https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt)|3.0|--
+|GL_MAX_SAMPLES|3.0|[GL_EXT_framebuffer_multisample](https://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt)|3.0|[GL_EXT_multisampled_render_to_texture](https://www.khronos.org/registry/gles/extensions/EXT/EXT_multisampled_render_to_texture.txt) or [GL_ANGLE_framebuffer_multisample](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_multisample.txt)||
+|GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|Ubiquitous extension.|
+|IMPLEMENTATION_COLOR_READ_FORMAT IMPLEMENTATION_COLOR_READ_TYPE|--|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Desktop GL doesn't as many limitations as ES for ReadPixels, can either always return GL_RGBA/GL_UNSIGNED_BYTE or return the format and type of the read buffer.|
+
+##OpenGL ES Formats (TODO)
+|Format|OpenGL version|OpenGL extension|OpenGL ES version|OpenGL ES extension|Notes|
+|---|---|---|---|---|---|
+|GL_RGBA8<br>GL_RGB8 |1.0|--|3.0|[GL_OES_rgb8_rgba8](https://www.khronos.org/registry/gles/extensions/OES/OES_rgb8_rgba8.txt)||
+
+## ESSL Features (TODO)
+|Feature|GLSL version|Notes|
+|---|---|---|
+|Unsigned integers|1.30||
+|Pack layout std140|1.40||
+
+## ESSL3 Builtins
+Builtins that are added going from ESSL1 to ESSL3.
+
+|Function|GLSL version|Extension|Notes|
+|---|---|---|---|
+|sinh<br>cosh<br>tanh<br>asinh<br>acosh|1.30|||
+|atanh|1.10|||
+|abs (genIType)|1.30|[GL_EXT_gpu_shader4](https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt)||
+|sign (genIType)|1.50|[GL_EXT_gpu_shader4](https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt)|Can be emulated easily.|
+|trunc|1.30|||
+|round<br>roundEven|1.30|||
+|min (genIType, genUType)<br>max (genIType, genUType)<br>clamp (genIType, genUType)|1.30||
+|mix (genBType)|4.50|[GL_EXT_shader_integer_mix](https://www.opengl.org/registry/specs/EXT/shader_integer_mix.txt)|Should be possible to emulate with a ternery operation.|
+|modf|1.30|||
+|isnan|1.30|||
+|isinf|1.10|||
+|floatBitsToInt<br>floatBitsToUint<br>intBitsToFloat<br>uintBitsToFloat|3.30|[GL_ARB_shader_bit_encoding](https://www.opengl.org/registry/specs/ARB/shader_bit_encoding.txt) or [ARB_gpu_shader5](https://www.opengl.org/registry/specs/ARB/gpu_shader5.txt)||
+|packSnorm2x16<br>packHalf2x16<br>unpackSnorm2x16<br>unpackHalf2x16|4.20|[GL_ARB_shading_language_packing](https://www.opengl.org/registry/specs/ARB/shading_language_packing.txt)|Can be emulated using bit casting functions.|
+|packUnorm2x16<br>unpackUnorm2x16|4.10|[GL_ARB_shading_language_packing](https://www.opengl.org/registry/specs/ARB/shading_language_packing.txt)|Can be emulated using bit casting functions.|
+|matrixCompMult (NxM matrices)|1.10|||
+|outerProduct|1.20|||
+|transpose|1.20|||
+|determinant|1.50||Can be emulated.|
+|inverse|1.40||Can be emulated.|
+|lessThan (uvec)<br>lessThanEqual (uvec)<br>greaterThan (uvec)<br>greaterThanEqual (uvec)<br>equal (uvec)<br>notEqual (uvec)|1.30|||
+|texture<br>textureProj<br>textureLod<br>textureOffset<br>textureProjOffset<br>textureLodOffset<br>textureProjLod<br>textureProjLodOffset<br>texelFetch<br>texelFetchOffset<br>textureGrad<br>textureGradOffset<br>textureProjGrad<br>textureProjGradOffset<br>textureSize|1.30||Equivalent to texture2D, textureCube, etc|
+|dFdx<br>dFdy<br>fwidth|1.10||
+
+## EGL Feature Support (TODO)
+|Feature|EGL version|EGL extension|WGL core|WGL extension|GLX version|GLX extensions|Notes|
+|---|---|---|---|---|---|---|---|
+|Pbuffers|||No|[WGL_ARB_pbuffer](https://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt)||||
+|BindTexImage|||No|[WGL_ARB_render_texture](https://www.opengl.org/registry/specs/ARB/wgl_render_texture.txt)|||Possibly to emulate with OpenGL textures but not strictly required, it is possible only export EGL configs without EGL_BIND_TO_TEXTURE_RGB and EGL_BIND_TO_TEXTURE_RGBA. Bindable pbuffers may be required by Chrome though.|
+|Pixmaps||||||||
+|Swap control|||No|[WGL_EXT_swap_control](https://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt)|No|[GLX_EXT_swap_control](https://www.opengl.org/registry/specs/EXT/swap_control.txt)||
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp
new file mode 100644
index 0000000..f4c3778
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp
@@ -0,0 +1,51 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FenceNVGL.cpp: Implements the class methods for FenceNVGL.
+
+#include "libANGLE/renderer/gl/FenceNVGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+
+namespace rx
+{
+
+FenceNVGL::FenceNVGL(const FunctionsGL *functions)
+    : FenceNVImpl(),
+      mFunctions(functions)
+{
+    mFunctions->genFencesNV(1, &mFence);
+}
+
+FenceNVGL::~FenceNVGL()
+{
+    mFunctions->deleteFencesNV(1, &mFence);
+    mFence = 0;
+}
+
+gl::Error FenceNVGL::set(GLenum condition)
+{
+    ASSERT(condition == GL_ALL_COMPLETED_NV);
+    mFunctions->setFenceNV(mFence, condition);
+    return gl::NoError();
+}
+
+gl::Error FenceNVGL::test(GLboolean *outFinished)
+{
+    ASSERT(outFinished);
+    *outFinished = mFunctions->testFenceNV(mFence);
+    return gl::NoError();
+}
+
+gl::Error FenceNVGL::finish()
+{
+    mFunctions->finishFenceNV(mFence);
+    return gl::NoError();
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/FenceNVGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/FenceNVGL.h
new file mode 100644
index 0000000..ffeca85
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/FenceNVGL.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FenceNVGL.h: Defines the class interface for FenceNVGL.
+
+#ifndef LIBANGLE_RENDERER_GL_FENCENVGL_H_
+#define LIBANGLE_RENDERER_GL_FENCENVGL_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+
+namespace rx
+{
+class FunctionsGL;
+
+class FenceNVGL : public FenceNVImpl
+{
+  public:
+    explicit FenceNVGL(const FunctionsGL *functions);
+    ~FenceNVGL() override;
+
+    gl::Error set(GLenum condition) override;
+    gl::Error test(GLboolean *outFinished) override;
+    gl::Error finish() override;
+
+  private:
+    GLuint mFence;
+
+    const FunctionsGL *mFunctions;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FENCENVGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp
new file mode 100644
index 0000000..8b6e34e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp
@@ -0,0 +1,67 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FenceSyncGL.cpp: Implements the class methods for FenceSyncGL.
+
+#include "libANGLE/renderer/gl/FenceSyncGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+namespace rx
+{
+
+FenceSyncGL::FenceSyncGL(const FunctionsGL *functions)
+    : FenceSyncImpl(),
+      mFunctions(functions),
+      mSyncObject(0)
+{
+    ASSERT(mFunctions);
+}
+
+FenceSyncGL::~FenceSyncGL()
+{
+    if (mSyncObject != 0)
+    {
+        mFunctions->deleteSync(mSyncObject);
+    }
+}
+
+gl::Error FenceSyncGL::set(GLenum condition, GLbitfield flags)
+{
+    ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0);
+    mSyncObject = mFunctions->fenceSync(condition, flags);
+    if (mSyncObject == 0)
+    {
+        // if glFenceSync fails, it returns 0.
+        return gl::Error(GL_OUT_OF_MEMORY, "glFenceSync failed to create a GLsync object.");
+    }
+
+    return gl::NoError();
+}
+
+gl::Error FenceSyncGL::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+    ASSERT(mSyncObject != 0);
+    *outResult = mFunctions->clientWaitSync(mSyncObject, flags, timeout);
+    return gl::NoError();
+}
+
+gl::Error FenceSyncGL::serverWait(GLbitfield flags, GLuint64 timeout)
+{
+    ASSERT(mSyncObject != 0);
+    mFunctions->waitSync(mSyncObject, flags, timeout);
+    return gl::NoError();
+}
+
+gl::Error FenceSyncGL::getStatus(GLint *outResult)
+{
+    ASSERT(mSyncObject != 0);
+    mFunctions->getSynciv(mSyncObject, GL_SYNC_STATUS, 1, nullptr, outResult);
+    return gl::NoError();
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/FenceSyncGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/FenceSyncGL.h
new file mode 100644
index 0000000..8dfd663
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/FenceSyncGL.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FenceSyncGL.h: Defines the class interface for FenceSyncGL.
+
+#ifndef LIBANGLE_RENDERER_GL_FENCESYNCGL_H_
+#define LIBANGLE_RENDERER_GL_FENCESYNCGL_H_
+
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace rx
+{
+class FunctionsGL;
+
+class FenceSyncGL : public FenceSyncImpl
+{
+  public:
+    explicit FenceSyncGL(const FunctionsGL *functions);
+    ~FenceSyncGL() override;
+
+    gl::Error set(GLenum condition, GLbitfield flags) override;
+    gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override;
+    gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override;
+    gl::Error getStatus(GLint *outResult) override;
+
+  private:
+    const FunctionsGL *mFunctions;
+    GLsync mSyncObject;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FENCESYNCGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
new file mode 100644
index 0000000..15f23d4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -0,0 +1,650 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferGL.cpp: Implements the class methods for FramebufferGL.
+
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+
+#include "common/bitset_utils.h"
+#include "common/debug.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/gl/BlitGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/RenderbufferGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "platform/Platform.h"
+
+using namespace gl;
+using angle::CheckedNumeric;
+
+namespace rx
+{
+
+FramebufferGL::FramebufferGL(const FramebufferState &state,
+                             const FunctionsGL *functions,
+                             StateManagerGL *stateManager,
+                             const WorkaroundsGL &workarounds,
+                             BlitGL *blitter,
+                             bool isDefault)
+    : FramebufferImpl(state),
+      mFunctions(functions),
+      mStateManager(stateManager),
+      mWorkarounds(workarounds),
+      mBlitter(blitter),
+      mFramebufferID(0),
+      mIsDefault(isDefault)
+{
+    if (!mIsDefault)
+    {
+        mFunctions->genFramebuffers(1, &mFramebufferID);
+    }
+}
+
+FramebufferGL::FramebufferGL(GLuint id,
+                             const FramebufferState &state,
+                             const FunctionsGL *functions,
+                             const WorkaroundsGL &workarounds,
+                             BlitGL *blitter,
+                             StateManagerGL *stateManager)
+    : FramebufferImpl(state),
+      mFunctions(functions),
+      mStateManager(stateManager),
+      mWorkarounds(workarounds),
+      mBlitter(blitter),
+      mFramebufferID(id),
+      mIsDefault(true)
+{
+}
+
+FramebufferGL::~FramebufferGL()
+{
+    mStateManager->deleteFramebuffer(mFramebufferID);
+    mFramebufferID = 0;
+}
+
+static void BindFramebufferAttachment(const FunctionsGL *functions,
+                                      GLenum attachmentPoint,
+                                      const FramebufferAttachment *attachment)
+{
+    if (attachment)
+    {
+        if (attachment->type() == GL_TEXTURE)
+        {
+            const Texture *texture     = attachment->getTexture();
+            const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+
+            if (texture->getTarget() == GL_TEXTURE_2D ||
+                texture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE)
+            {
+                functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
+                                                texture->getTarget(), textureGL->getTextureID(),
+                                                attachment->mipLevel());
+            }
+            else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
+            {
+                functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
+                                                attachment->cubeMapFace(),
+                                                textureGL->getTextureID(), attachment->mipLevel());
+            }
+            else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY ||
+                     texture->getTarget() == GL_TEXTURE_3D)
+            {
+                functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint,
+                                                   textureGL->getTextureID(),
+                                                   attachment->mipLevel(), attachment->layer());
+            }
+            else
+            {
+                UNREACHABLE();
+            }
+        }
+        else if (attachment->type() == GL_RENDERBUFFER)
+        {
+            const Renderbuffer *renderbuffer     = attachment->getRenderbuffer();
+            const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
+
+            functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
+                                               renderbufferGL->getRenderbufferID());
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+    }
+    else
+    {
+        // Unbind this attachment
+        functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
+    }
+}
+
+Error FramebufferGL::discard(size_t count, const GLenum *attachments)
+{
+    // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
+    return invalidate(count, attachments);
+}
+
+Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
+{
+    const GLenum *finalAttachmentsPtr = attachments;
+
+    std::vector<GLenum> modifiedAttachments;
+    if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
+    {
+        finalAttachmentsPtr = modifiedAttachments.data();
+    }
+
+    // Since this function is just a hint, only call a native function if it exists.
+    if (mFunctions->invalidateFramebuffer)
+    {
+        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+        mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
+                                          finalAttachmentsPtr);
+    }
+    else if (mFunctions->discardFramebuffer)
+    {
+        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+        mFunctions->discardFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
+                                       finalAttachmentsPtr);
+    }
+
+    return gl::NoError();
+}
+
+Error FramebufferGL::invalidateSub(size_t count,
+                                   const GLenum *attachments,
+                                   const gl::Rectangle &area)
+{
+
+    const GLenum *finalAttachmentsPtr = attachments;
+
+    std::vector<GLenum> modifiedAttachments;
+    if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
+    {
+        finalAttachmentsPtr = modifiedAttachments.data();
+    }
+
+    // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
+    // available.
+    if (mFunctions->invalidateSubFramebuffer)
+    {
+        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+        mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
+                                             finalAttachmentsPtr, area.x, area.y, area.width,
+                                             area.height);
+    }
+
+    return NoError();
+}
+
+Error FramebufferGL::clear(ContextImpl *context, GLbitfield mask)
+{
+    syncClearState(context, mask);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+    mFunctions->clear(mask);
+
+    return NoError();
+}
+
+Error FramebufferGL::clearBufferfv(ContextImpl *context,
+                                   GLenum buffer,
+                                   GLint drawbuffer,
+                                   const GLfloat *values)
+{
+    syncClearBufferState(context, buffer, drawbuffer);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+    mFunctions->clearBufferfv(buffer, drawbuffer, values);
+
+    return NoError();
+}
+
+Error FramebufferGL::clearBufferuiv(ContextImpl *context,
+                                    GLenum buffer,
+                                    GLint drawbuffer,
+                                    const GLuint *values)
+{
+    syncClearBufferState(context, buffer, drawbuffer);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+    mFunctions->clearBufferuiv(buffer, drawbuffer, values);
+
+    return NoError();
+}
+
+Error FramebufferGL::clearBufferiv(ContextImpl *context,
+                                   GLenum buffer,
+                                   GLint drawbuffer,
+                                   const GLint *values)
+{
+    syncClearBufferState(context, buffer, drawbuffer);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+    mFunctions->clearBufferiv(buffer, drawbuffer, values);
+
+    return NoError();
+}
+
+Error FramebufferGL::clearBufferfi(ContextImpl *context,
+                                   GLenum buffer,
+                                   GLint drawbuffer,
+                                   GLfloat depth,
+                                   GLint stencil)
+{
+    syncClearBufferState(context, buffer, drawbuffer);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+    mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
+
+    return NoError();
+}
+
+GLenum FramebufferGL::getImplementationColorReadFormat() const
+{
+    const auto *readAttachment = mState.getReadAttachment();
+    const Format &format       = readAttachment->getFormat();
+    return format.info->getReadPixelsFormat();
+}
+
+GLenum FramebufferGL::getImplementationColorReadType() const
+{
+    const auto *readAttachment = mState.getReadAttachment();
+    const Format &format       = readAttachment->getFormat();
+    return format.info->getReadPixelsType();
+}
+
+Error FramebufferGL::readPixels(ContextImpl *context,
+                                const gl::Rectangle &area,
+                                GLenum format,
+                                GLenum type,
+                                void *pixels) const
+{
+    // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
+    // binding
+    const PixelPackState &packState = context->getGLState().getPackState();
+    mStateManager->setPixelPackState(packState);
+
+    nativegl::ReadPixelsFormat readPixelsFormat =
+        nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
+    GLenum readFormat = readPixelsFormat.format;
+    GLenum readType   = readPixelsFormat.type;
+
+    mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
+
+    if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
+        packState.rowLength != 0 && packState.rowLength < area.width)
+    {
+        return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
+    }
+
+    if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
+    {
+        gl::Extents size(area.width, area.height, 1);
+
+        bool apply;
+        ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
+                                                             false, pixels),
+                         apply);
+
+        if (apply)
+        {
+            return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
+        }
+    }
+
+    mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels);
+
+    return gl::NoError();
+}
+
+Error FramebufferGL::blit(ContextImpl *context,
+                          const gl::Rectangle &sourceArea,
+                          const gl::Rectangle &destArea,
+                          GLbitfield mask,
+                          GLenum filter)
+{
+    const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
+    const Framebuffer *destFramebuffer   = context->getGLState().getDrawFramebuffer();
+
+    const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
+
+    GLsizei readAttachmentSamples = 0;
+    if (colorReadAttachment != nullptr)
+    {
+        readAttachmentSamples = colorReadAttachment->getSamples();
+    }
+
+    bool needManualColorBlit = false;
+
+    // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
+    // could avoid doing a manual blit.
+
+    // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
+    //      When values are taken from the read buffer, no linearization is performed, even
+    //      if the format of the buffer is SRGB.
+    // Starting from OpenGL 4.4 (section 18.3.1) it reads:
+    //      When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
+    //      value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
+    //      corresponding to the read buffer is SRGB, the red, green, and blue components are
+    //      converted from the non-linear sRGB color space according [...].
+    {
+        bool sourceSRGB =
+            colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
+        needManualColorBlit =
+            needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
+    }
+
+    // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
+    //      Blit operations bypass the fragment pipeline. The only fragment operations which
+    //      affect a blit are the pixel ownership test and scissor test.
+    // Starting from OpenGL 4.2 (section 4.3.2) it reads:
+    //      When values are written to the draw buffers, blit operations bypass the fragment
+    //      pipeline. The only fragment operations which affect a blit are the pixel ownership
+    //      test,  the scissor test and sRGB conversion.
+    if (!needManualColorBlit)
+    {
+        bool destSRGB = false;
+        for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
+        {
+            const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
+            if (attachment && attachment->getColorEncoding() == GL_SRGB)
+            {
+                destSRGB = true;
+                break;
+            }
+        }
+
+        needManualColorBlit =
+            needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
+    }
+
+    // Enable FRAMEBUFFER_SRGB if needed
+    mStateManager->setFramebufferSRGBEnabledForFramebuffer(context->getContextState(), true, this);
+
+    GLenum blitMask = mask;
+    if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
+    {
+        ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
+                                                      sourceArea, destArea, filter));
+        blitMask &= ~GL_COLOR_BUFFER_BIT;
+    }
+
+    if (blitMask == 0)
+    {
+        return gl::NoError();
+    }
+
+    const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
+    mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
+    mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
+
+    mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
+                                destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
+                                filter);
+
+    return gl::NoError();
+}
+
+gl::Error FramebufferGL::getSamplePosition(size_t index, GLfloat *xy) const
+{
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+    mFunctions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
+    return gl::NoError();
+}
+
+bool FramebufferGL::checkStatus() const
+{
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+    GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
+    if (status != GL_FRAMEBUFFER_COMPLETE)
+    {
+        WARN() << "GL framebuffer returned incomplete.";
+    }
+    return (status == GL_FRAMEBUFFER_COMPLETE);
+}
+
+void FramebufferGL::syncState(ContextImpl *contextImpl, const Framebuffer::DirtyBits &dirtyBits)
+{
+    // Don't need to sync state for the default FBO.
+    if (mIsDefault)
+    {
+        return;
+    }
+
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+
+    for (auto dirtyBit : dirtyBits)
+    {
+        switch (dirtyBit)
+        {
+            case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
+                BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
+                                          mState.getDepthAttachment());
+                break;
+            case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
+                BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
+                                          mState.getStencilAttachment());
+                break;
+            case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
+            {
+                const auto &drawBuffers = mState.getDrawBufferStates();
+                mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
+                                        drawBuffers.data());
+                break;
+            }
+            case Framebuffer::DIRTY_BIT_READ_BUFFER:
+                mFunctions->readBuffer(mState.getReadBufferState());
+                break;
+            case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
+                mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
+                                                  mState.getDefaultWidth());
+                break;
+            case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
+                mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
+                                                  mState.getDefaultHeight());
+                break;
+            case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
+                mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
+                                                  mState.getDefaultSamples());
+                break;
+            case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+                mFunctions->framebufferParameteri(GL_FRAMEBUFFER,
+                                                  GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
+                                                  mState.getDefaultFixedSampleLocations());
+                break;
+            default:
+            {
+                ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
+                       dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
+                size_t index =
+                    static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
+                BindFramebufferAttachment(mFunctions,
+                                          static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
+                                          mState.getColorAttachment(index));
+                break;
+            }
+        }
+    }
+}
+
+GLuint FramebufferGL::getFramebufferID() const
+{
+    return mFramebufferID;
+}
+
+bool FramebufferGL::isDefault() const
+{
+    return mIsDefault;
+}
+
+void FramebufferGL::syncClearState(ContextImpl *context, GLbitfield mask)
+{
+    if (mFunctions->standard == STANDARD_GL_DESKTOP)
+    {
+        if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
+            (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
+        {
+            bool hasSRGBAttachment = false;
+            for (const auto &attachment : mState.getColorAttachments())
+            {
+                if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
+                {
+                    hasSRGBAttachment = true;
+                    break;
+                }
+            }
+
+            mStateManager->setFramebufferSRGBEnabled(context->getContextState(), hasSRGBAttachment);
+        }
+        else
+        {
+            mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
+        }
+    }
+}
+
+void FramebufferGL::syncClearBufferState(ContextImpl *context, GLenum buffer, GLint drawBuffer)
+{
+    if (mFunctions->standard == STANDARD_GL_DESKTOP)
+    {
+        if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
+            !mIsDefault)
+        {
+            // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
+            // is an SRGB format.
+            const auto &drawbufferState  = mState.getDrawBufferStates();
+            const auto &colorAttachments = mState.getColorAttachments();
+
+            const FramebufferAttachment *attachment = nullptr;
+            if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
+                drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
+            {
+                size_t attachmentIdx =
+                    static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
+                attachment = &colorAttachments[attachmentIdx];
+            }
+
+            if (attachment != nullptr)
+            {
+                mStateManager->setFramebufferSRGBEnabled(context->getContextState(),
+                                                         attachment->getColorEncoding() == GL_SRGB);
+            }
+        }
+        else
+        {
+            mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
+        }
+    }
+}
+
+bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
+    size_t count,
+    const GLenum *attachments,
+    std::vector<GLenum> *modifiedAttachments) const
+{
+    bool needsModification = mIsDefault && mFramebufferID != 0;
+    if (!needsModification)
+    {
+        return false;
+    }
+
+    modifiedAttachments->resize(count);
+    for (size_t i = 0; i < count; i++)
+    {
+        switch (attachments[i])
+        {
+            case GL_COLOR:
+                (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
+                break;
+
+            case GL_DEPTH:
+                (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
+                break;
+
+            case GL_STENCIL:
+                (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
+                break;
+
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+
+    return true;
+}
+
+gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
+                                                      GLenum format,
+                                                      GLenum type,
+                                                      const gl::PixelPackState &pack,
+                                                      void *pixels) const
+{
+    intptr_t offset = reinterpret_cast<intptr_t>(pixels);
+
+    const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
+    GLuint rowBytes                    = 0;
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
+                     rowBytes);
+    GLuint skipBytes = 0;
+    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
+
+    gl::PixelPackState directPack;
+    directPack.pixelBuffer = pack.pixelBuffer;
+    directPack.alignment   = 1;
+    mStateManager->setPixelPackState(directPack);
+    directPack.pixelBuffer.set(nullptr);
+
+    offset += skipBytes;
+    for (GLint row = 0; row < area.height; ++row)
+    {
+        mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
+                               reinterpret_cast<void *>(offset));
+        offset += row * rowBytes;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
+                                                     GLenum format,
+                                                     GLenum type,
+                                                     const gl::PixelPackState &pack,
+                                                     void *pixels) const
+{
+    const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
+    GLuint rowBytes                    = 0;
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
+                     rowBytes);
+    GLuint skipBytes = 0;
+    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
+
+    // Get all by the last row
+    if (area.height > 1)
+    {
+        mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
+    }
+
+    // Get the last row manually
+    gl::PixelPackState directPack;
+    directPack.pixelBuffer = pack.pixelBuffer;
+    directPack.alignment   = 1;
+    mStateManager->setPixelPackState(directPack);
+    directPack.pixelBuffer.set(nullptr);
+
+    intptr_t lastRowOffset =
+        reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
+    mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
+                           reinterpret_cast<void *>(lastRowOffset));
+
+    return gl::NoError();
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h
new file mode 100644
index 0000000..b8abb5c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h
@@ -0,0 +1,121 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferGL.h: Defines the class interface for FramebufferGL.
+
+#ifndef LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_
+#define LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace rx
+{
+
+class BlitGL;
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class FramebufferGL : public FramebufferImpl
+{
+  public:
+    FramebufferGL(const gl::FramebufferState &data,
+                  const FunctionsGL *functions,
+                  StateManagerGL *stateManager,
+                  const WorkaroundsGL &workarounds,
+                  BlitGL *blitter,
+                  bool isDefault);
+    // Constructor called when we need to create a FramebufferGL from an
+    // existing framebuffer name, for example for the default framebuffer
+    // on the Mac EGL CGL backend.
+    FramebufferGL(GLuint id,
+                  const gl::FramebufferState &data,
+                  const FunctionsGL *functions,
+                  const WorkaroundsGL &workarounds,
+                  BlitGL *blitter,
+                  StateManagerGL *stateManager);
+    ~FramebufferGL() override;
+
+    gl::Error discard(size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(size_t count, const GLenum *attachments) override;
+    gl::Error invalidateSub(size_t count,
+                            const GLenum *attachments,
+                            const gl::Rectangle &area) override;
+
+    gl::Error clear(ContextImpl *context, GLbitfield mask) override;
+    gl::Error clearBufferfv(ContextImpl *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLfloat *values) override;
+    gl::Error clearBufferuiv(ContextImpl *context,
+                             GLenum buffer,
+                             GLint drawbuffer,
+                             const GLuint *values) override;
+    gl::Error clearBufferiv(ContextImpl *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLint *values) override;
+    gl::Error clearBufferfi(ContextImpl *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            GLfloat depth,
+                            GLint stencil) override;
+
+    GLenum getImplementationColorReadFormat() const override;
+    GLenum getImplementationColorReadType() const override;
+    gl::Error readPixels(ContextImpl *context,
+                         const gl::Rectangle &area,
+                         GLenum format,
+                         GLenum type,
+                         void *pixels) const override;
+
+    gl::Error blit(ContextImpl *context,
+                   const gl::Rectangle &sourceArea,
+                   const gl::Rectangle &destArea,
+                   GLbitfield mask,
+                   GLenum filter) override;
+
+    gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
+
+    bool checkStatus() const override;
+
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
+
+    GLuint getFramebufferID() const;
+    bool isDefault() const;
+
+  private:
+    void syncClearState(ContextImpl *context, GLbitfield mask);
+    void syncClearBufferState(ContextImpl *context, GLenum buffer, GLint drawBuffer);
+
+    bool modifyInvalidateAttachmentsForEmulatedDefaultFBO(
+        size_t count,
+        const GLenum *attachments,
+        std::vector<GLenum> *modifiedAttachments) const;
+
+    gl::Error readPixelsRowByRowWorkaround(const gl::Rectangle &area,
+                                           GLenum format,
+                                           GLenum type,
+                                           const gl::PixelPackState &pack,
+                                           void *pixels) const;
+
+    gl::Error readPixelsPaddingWorkaround(const gl::Rectangle &area,
+                                          GLenum format,
+                                          GLenum type,
+                                          const gl::PixelPackState &pack,
+                                          void *pixels) const;
+
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+    const WorkaroundsGL &mWorkarounds;
+    BlitGL *mBlitter;
+
+    GLuint mFramebufferID;
+    bool mIsDefault;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
new file mode 100644
index 0000000..2cf269d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
@@ -0,0 +1,2336 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsGL.cpp: Implements the FuntionsGL class to contain loaded GL functions
+
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+#include <algorithm>
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace rx
+{
+
+static void GetGLVersion(PFNGLGETSTRINGPROC getStringFunction, gl::Version *outVersion, StandardGL *outStandard)
+{
+    const std::string version = reinterpret_cast<const char*>(getStringFunction(GL_VERSION));
+    if (version.find("OpenGL ES") == std::string::npos)
+    {
+        // OpenGL spec states the GL_VERSION string will be in the following format:
+        // <version number><space><vendor-specific information>
+        // The version number is either of the form major number.minor number or major
+        // number.minor number.release number, where the numbers all have one or more
+        // digits
+        *outStandard = STANDARD_GL_DESKTOP;
+        *outVersion = gl::Version(version[0] - '0', version[2] - '0');
+    }
+    else
+    {
+        // ES spec states that the GL_VERSION string will be in the following format:
+        // "OpenGL ES N.M vendor-specific information"
+        *outStandard = STANDARD_GL_ES;
+        *outVersion = gl::Version(version[10] - '0', version[12] - '0');
+    }
+}
+
+static std::vector<std::string> GetIndexedExtensions(PFNGLGETINTEGERVPROC getIntegerFunction, PFNGLGETSTRINGIPROC getStringIFunction)
+{
+    std::vector<std::string> result;
+
+    GLint numExtensions;
+    getIntegerFunction(GL_NUM_EXTENSIONS, &numExtensions);
+
+    result.reserve(numExtensions);
+
+    for (GLint i = 0; i < numExtensions; i++)
+    {
+        result.push_back(reinterpret_cast<const char*>(getStringIFunction(GL_EXTENSIONS, i)));
+    }
+
+    return result;
+}
+
+static void AssignGLExtensionEntryPoint(const std::vector<std::string> &extensions,
+                                        const char *requiredExtensionString,
+                                        void *function,
+                                        void **outFunction)
+{
+    std::vector<std::string> requiredExtensions;
+    angle::SplitStringAlongWhitespace(requiredExtensionString, &requiredExtensions);
+    for (const std::string& requiredExtension : requiredExtensions)
+    {
+        if (std::find(extensions.begin(), extensions.end(), requiredExtension) == extensions.end())
+        {
+            return;
+        }
+    }
+
+    *outFunction = function;
+}
+
+#define ASSIGN_WITH_EXT(EXT, NAME, FP)                                  \
+    AssignGLExtensionEntryPoint(extensions, EXT, loadProcAddress(NAME), \
+                                reinterpret_cast<void **>(&FP))
+#define ASSIGN(NAME, FP) *reinterpret_cast<void **>(&FP) = loadProcAddress(NAME)
+
+FunctionsGL::FunctionsGL()
+    : version(),
+      standard(),
+      extensions(),
+
+      blendFunc(nullptr),
+      clear(nullptr),
+      clearColor(nullptr),
+      clearDepth(nullptr),
+      clearStencil(nullptr),
+      colorMask(nullptr),
+      cullFace(nullptr),
+      depthFunc(nullptr),
+      depthMask(nullptr),
+      depthRange(nullptr),
+      disable(nullptr),
+      drawBuffer(nullptr),
+      enable(nullptr),
+      finish(nullptr),
+      flush(nullptr),
+      frontFace(nullptr),
+      getBooleanv(nullptr),
+      getDoublev(nullptr),
+      getError(nullptr),
+      getFloatv(nullptr),
+      getIntegerv(nullptr),
+      getString(nullptr),
+      getTexImage(nullptr),
+      getTexLevelParameterfv(nullptr),
+      getTexLevelParameteriv(nullptr),
+      getTexParameterfv(nullptr),
+      getTexParameteriv(nullptr),
+      hint(nullptr),
+      isEnabled(nullptr),
+      lineWidth(nullptr),
+      logicOp(nullptr),
+      pixelStoref(nullptr),
+      pixelStorei(nullptr),
+      pointSize(nullptr),
+      polygonMode(nullptr),
+      readBuffer(nullptr),
+      readPixels(nullptr),
+      scissor(nullptr),
+      stencilFunc(nullptr),
+      stencilMask(nullptr),
+      stencilOp(nullptr),
+      texImage1D(nullptr),
+      texImage2D(nullptr),
+      texParameterf(nullptr),
+      texParameterfv(nullptr),
+      texParameteri(nullptr),
+      texParameteriv(nullptr),
+      viewport(nullptr),
+
+      bindTexture(nullptr),
+      copyTexImage1D(nullptr),
+      copyTexImage2D(nullptr),
+      copyTexSubImage1D(nullptr),
+      copyTexSubImage2D(nullptr),
+      deleteTextures(nullptr),
+      drawArrays(nullptr),
+      drawElements(nullptr),
+      genTextures(nullptr),
+      isTexture(nullptr),
+      polygonOffset(nullptr),
+      texSubImage1D(nullptr),
+      texSubImage2D(nullptr),
+
+      blendColor(nullptr),
+      blendEquation(nullptr),
+      copyTexSubImage3D(nullptr),
+      drawRangeElements(nullptr),
+      texImage3D(nullptr),
+      texSubImage3D(nullptr),
+
+      deleteFencesNV(nullptr),
+      genFencesNV(nullptr),
+      isFenceNV(nullptr),
+      testFenceNV(nullptr),
+      getFenceivNV(nullptr),
+      finishFenceNV(nullptr),
+      setFenceNV(nullptr),
+
+      activeTexture(nullptr),
+      compressedTexImage1D(nullptr),
+      compressedTexImage2D(nullptr),
+      compressedTexImage3D(nullptr),
+      compressedTexSubImage1D(nullptr),
+      compressedTexSubImage2D(nullptr),
+      compressedTexSubImage3D(nullptr),
+      getCompressedTexImage(nullptr),
+      sampleCoverage(nullptr),
+
+      blendFuncSeparate(nullptr),
+      multiDrawArrays(nullptr),
+      multiDrawElements(nullptr),
+      pointParameterf(nullptr),
+      pointParameterfv(nullptr),
+      pointParameteri(nullptr),
+      pointParameteriv(nullptr),
+
+      beginQuery(nullptr),
+      bindBuffer(nullptr),
+      bufferData(nullptr),
+      bufferSubData(nullptr),
+      deleteBuffers(nullptr),
+      deleteQueries(nullptr),
+      endQuery(nullptr),
+      genBuffers(nullptr),
+      genQueries(nullptr),
+      getBufferParameteriv(nullptr),
+      getBufferPointerv(nullptr),
+      getBufferSubData(nullptr),
+      getQueryObjectiv(nullptr),
+      getQueryObjectuiv(nullptr),
+      getQueryiv(nullptr),
+      isBuffer(nullptr),
+      isQuery(nullptr),
+      mapBuffer(nullptr),
+      unmapBuffer(nullptr),
+
+      attachShader(nullptr),
+      bindAttribLocation(nullptr),
+      blendEquationSeparate(nullptr),
+      compileShader(nullptr),
+      createProgram(nullptr),
+      createShader(nullptr),
+      deleteProgram(nullptr),
+      deleteShader(nullptr),
+      detachShader(nullptr),
+      disableVertexAttribArray(nullptr),
+      drawBuffers(nullptr),
+      enableVertexAttribArray(nullptr),
+      getActiveAttrib(nullptr),
+      getActiveUniform(nullptr),
+      getAttachedShaders(nullptr),
+      getAttribLocation(nullptr),
+      getProgramInfoLog(nullptr),
+      getProgramiv(nullptr),
+      getShaderInfoLog(nullptr),
+      getShaderSource(nullptr),
+      getShaderiv(nullptr),
+      getUniformLocation(nullptr),
+      getUniformfv(nullptr),
+      getUniformiv(nullptr),
+      getVertexAttribPointerv(nullptr),
+      getVertexAttribdv(nullptr),
+      getVertexAttribfv(nullptr),
+      getVertexAttribiv(nullptr),
+      isProgram(nullptr),
+      isShader(nullptr),
+      linkProgram(nullptr),
+      shaderSource(nullptr),
+      stencilFuncSeparate(nullptr),
+      stencilMaskSeparate(nullptr),
+      stencilOpSeparate(nullptr),
+      uniform1f(nullptr),
+      uniform1fv(nullptr),
+      uniform1i(nullptr),
+      uniform1iv(nullptr),
+      uniform2f(nullptr),
+      uniform2fv(nullptr),
+      uniform2i(nullptr),
+      uniform2iv(nullptr),
+      uniform3f(nullptr),
+      uniform3fv(nullptr),
+      uniform3i(nullptr),
+      uniform3iv(nullptr),
+      uniform4f(nullptr),
+      uniform4fv(nullptr),
+      uniform4i(nullptr),
+      uniform4iv(nullptr),
+      uniformMatrix2fv(nullptr),
+      uniformMatrix3fv(nullptr),
+      uniformMatrix4fv(nullptr),
+      useProgram(nullptr),
+      validateProgram(nullptr),
+      vertexAttrib1d(nullptr),
+      vertexAttrib1dv(nullptr),
+      vertexAttrib1f(nullptr),
+      vertexAttrib1fv(nullptr),
+      vertexAttrib1s(nullptr),
+      vertexAttrib1sv(nullptr),
+      vertexAttrib2d(nullptr),
+      vertexAttrib2dv(nullptr),
+      vertexAttrib2f(nullptr),
+      vertexAttrib2fv(nullptr),
+      vertexAttrib2s(nullptr),
+      vertexAttrib2sv(nullptr),
+      vertexAttrib3d(nullptr),
+      vertexAttrib3dv(nullptr),
+      vertexAttrib3f(nullptr),
+      vertexAttrib3fv(nullptr),
+      vertexAttrib3s(nullptr),
+      vertexAttrib3sv(nullptr),
+      vertexAttrib4Nbv(nullptr),
+      vertexAttrib4Niv(nullptr),
+      vertexAttrib4Nsv(nullptr),
+      vertexAttrib4Nub(nullptr),
+      vertexAttrib4Nubv(nullptr),
+      vertexAttrib4Nuiv(nullptr),
+      vertexAttrib4Nusv(nullptr),
+      vertexAttrib4bv(nullptr),
+      vertexAttrib4d(nullptr),
+      vertexAttrib4dv(nullptr),
+      vertexAttrib4f(nullptr),
+      vertexAttrib4fv(nullptr),
+      vertexAttrib4iv(nullptr),
+      vertexAttrib4s(nullptr),
+      vertexAttrib4sv(nullptr),
+      vertexAttrib4ubv(nullptr),
+      vertexAttrib4uiv(nullptr),
+      vertexAttrib4usv(nullptr),
+      vertexAttribPointer(nullptr),
+
+      uniformMatrix2x3fv(nullptr),
+      uniformMatrix2x4fv(nullptr),
+      uniformMatrix3x2fv(nullptr),
+      uniformMatrix3x4fv(nullptr),
+      uniformMatrix4x2fv(nullptr),
+      uniformMatrix4x3fv(nullptr),
+
+      beginConditionalRender(nullptr),
+      beginTransformFeedback(nullptr),
+      bindBufferBase(nullptr),
+      bindBufferRange(nullptr),
+      bindFragDataLocation(nullptr),
+      bindFramebuffer(nullptr),
+      bindRenderbuffer(nullptr),
+      bindVertexArray(nullptr),
+      blitFramebuffer(nullptr),
+      checkFramebufferStatus(nullptr),
+      clampColor(nullptr),
+      clearBufferfi(nullptr),
+      clearBufferfv(nullptr),
+      clearBufferiv(nullptr),
+      clearBufferuiv(nullptr),
+      colorMaski(nullptr),
+      deleteFramebuffers(nullptr),
+      deleteRenderbuffers(nullptr),
+      deleteVertexArrays(nullptr),
+      disablei(nullptr),
+      enablei(nullptr),
+      endConditionalRender(nullptr),
+      endTransformFeedback(nullptr),
+      flushMappedBufferRange(nullptr),
+      framebufferRenderbuffer(nullptr),
+      framebufferTexture1D(nullptr),
+      framebufferTexture2D(nullptr),
+      framebufferTexture3D(nullptr),
+      framebufferTextureLayer(nullptr),
+      genFramebuffers(nullptr),
+      genRenderbuffers(nullptr),
+      genVertexArrays(nullptr),
+      generateMipmap(nullptr),
+      getBooleani_v(nullptr),
+      getFragDataLocation(nullptr),
+      getFramebufferAttachmentParameteriv(nullptr),
+      getIntegeri_v(nullptr),
+      getRenderbufferParameteriv(nullptr),
+      getStringi(nullptr),
+      getTexParameterIiv(nullptr),
+      getTexParameterIuiv(nullptr),
+      getTransformFeedbackVarying(nullptr),
+      getUniformuiv(nullptr),
+      getVertexAttribIiv(nullptr),
+      getVertexAttribIuiv(nullptr),
+      isEnabledi(nullptr),
+      isFramebuffer(nullptr),
+      isRenderbuffer(nullptr),
+      isVertexArray(nullptr),
+      mapBufferRange(nullptr),
+      renderbufferStorage(nullptr),
+      renderbufferStorageMultisample(nullptr),
+      texParameterIiv(nullptr),
+      texParameterIuiv(nullptr),
+      transformFeedbackVaryings(nullptr),
+      uniform1ui(nullptr),
+      uniform1uiv(nullptr),
+      uniform2ui(nullptr),
+      uniform2uiv(nullptr),
+      uniform3ui(nullptr),
+      uniform3uiv(nullptr),
+      uniform4ui(nullptr),
+      uniform4uiv(nullptr),
+      vertexAttribI1i(nullptr),
+      vertexAttribI1iv(nullptr),
+      vertexAttribI1ui(nullptr),
+      vertexAttribI1uiv(nullptr),
+      vertexAttribI2i(nullptr),
+      vertexAttribI2iv(nullptr),
+      vertexAttribI2ui(nullptr),
+      vertexAttribI2uiv(nullptr),
+      vertexAttribI3i(nullptr),
+      vertexAttribI3iv(nullptr),
+      vertexAttribI3ui(nullptr),
+      vertexAttribI3uiv(nullptr),
+      vertexAttribI4bv(nullptr),
+      vertexAttribI4i(nullptr),
+      vertexAttribI4iv(nullptr),
+      vertexAttribI4sv(nullptr),
+      vertexAttribI4ubv(nullptr),
+      vertexAttribI4ui(nullptr),
+      vertexAttribI4uiv(nullptr),
+      vertexAttribI4usv(nullptr),
+      vertexAttribIPointer(nullptr),
+
+      copyBufferSubData(nullptr),
+      drawArraysInstanced(nullptr),
+      drawElementsInstanced(nullptr),
+      getActiveUniformBlockName(nullptr),
+      getActiveUniformBlockiv(nullptr),
+      getActiveUniformName(nullptr),
+      getActiveUniformsiv(nullptr),
+      getUniformBlockIndex(nullptr),
+      getUniformIndices(nullptr),
+      primitiveRestartIndex(nullptr),
+      texBuffer(nullptr),
+      uniformBlockBinding(nullptr),
+
+      clientWaitSync(nullptr),
+      deleteSync(nullptr),
+      drawElementsBaseVertex(nullptr),
+      drawElementsInstancedBaseVertex(nullptr),
+      drawRangeElementsBaseVertex(nullptr),
+      fenceSync(nullptr),
+      framebufferTexture(nullptr),
+      getBufferParameteri64v(nullptr),
+      getInteger64i_v(nullptr),
+      getInteger64v(nullptr),
+      getMultisamplefv(nullptr),
+      getSynciv(nullptr),
+      isSync(nullptr),
+      multiDrawElementsBaseVertex(nullptr),
+      provokingVertex(nullptr),
+      sampleMaski(nullptr),
+      texImage2DMultisample(nullptr),
+      texImage3DMultisample(nullptr),
+      waitSync(nullptr),
+
+      matrixLoadEXT(nullptr),
+      genPathsNV(nullptr),
+      delPathsNV(nullptr),
+      pathCommandsNV(nullptr),
+      setPathParameterfNV(nullptr),
+      setPathParameteriNV(nullptr),
+      getPathParameterfNV(nullptr),
+      getPathParameteriNV(nullptr),
+      pathStencilFuncNV(nullptr),
+      stencilFillPathNV(nullptr),
+      stencilStrokePathNV(nullptr),
+      coverFillPathNV(nullptr),
+      coverStrokePathNV(nullptr),
+      stencilThenCoverFillPathNV(nullptr),
+      stencilThenCoverStrokePathNV(nullptr),
+      coverFillPathInstancedNV(nullptr),
+      coverStrokePathInstancedNV(nullptr),
+      stencilFillPathInstancedNV(nullptr),
+      stencilStrokePathInstancedNV(nullptr),
+      stencilThenCoverFillPathInstancedNV(nullptr),
+      stencilThenCoverStrokePathInstancedNV(nullptr),
+      programPathFragmentInputGenNV(nullptr),
+
+      bindFragDataLocationIndexed(nullptr),
+      bindSampler(nullptr),
+      deleteSamplers(nullptr),
+      genSamplers(nullptr),
+      getFragDataIndex(nullptr),
+      getQueryObjecti64v(nullptr),
+      getQueryObjectui64v(nullptr),
+      getSamplerParameterIiv(nullptr),
+      getSamplerParameterIuiv(nullptr),
+      getSamplerParameterfv(nullptr),
+      getSamplerParameteriv(nullptr),
+      isSampler(nullptr),
+      queryCounter(nullptr),
+      samplerParameterIiv(nullptr),
+      samplerParameterIuiv(nullptr),
+      samplerParameterf(nullptr),
+      samplerParameterfv(nullptr),
+      samplerParameteri(nullptr),
+      samplerParameteriv(nullptr),
+      vertexAttribDivisor(nullptr),
+      vertexAttribP1ui(nullptr),
+      vertexAttribP1uiv(nullptr),
+      vertexAttribP2ui(nullptr),
+      vertexAttribP2uiv(nullptr),
+      vertexAttribP3ui(nullptr),
+      vertexAttribP3uiv(nullptr),
+      vertexAttribP4ui(nullptr),
+      vertexAttribP4uiv(nullptr),
+
+      beginQueryIndexed(nullptr),
+      bindTransformFeedback(nullptr),
+      blendEquationSeparatei(nullptr),
+      blendEquationi(nullptr),
+      blendFuncSeparatei(nullptr),
+      blendFunci(nullptr),
+      deleteTransformFeedbacks(nullptr),
+      drawArraysIndirect(nullptr),
+      drawElementsIndirect(nullptr),
+      drawTransformFeedback(nullptr),
+      drawTransformFeedbackStream(nullptr),
+      endQueryIndexed(nullptr),
+      genTransformFeedbacks(nullptr),
+      getActiveSubroutineName(nullptr),
+      getActiveSubroutineUniformName(nullptr),
+      getActiveSubroutineUniformiv(nullptr),
+      getProgramStageiv(nullptr),
+      getQueryIndexediv(nullptr),
+      getSubroutineIndex(nullptr),
+      getSubroutineUniformLocation(nullptr),
+      getUniformSubroutineuiv(nullptr),
+      getUniformdv(nullptr),
+      isTransformFeedback(nullptr),
+      minSampleShading(nullptr),
+      patchParameterfv(nullptr),
+      patchParameteri(nullptr),
+      pauseTransformFeedback(nullptr),
+      resumeTransformFeedback(nullptr),
+      uniform1d(nullptr),
+      uniform1dv(nullptr),
+      uniform2d(nullptr),
+      uniform2dv(nullptr),
+      uniform3d(nullptr),
+      uniform3dv(nullptr),
+      uniform4d(nullptr),
+      uniform4dv(nullptr),
+      uniformMatrix2dv(nullptr),
+      uniformMatrix2x3dv(nullptr),
+      uniformMatrix2x4dv(nullptr),
+      uniformMatrix3dv(nullptr),
+      uniformMatrix3x2dv(nullptr),
+      uniformMatrix3x4dv(nullptr),
+      uniformMatrix4dv(nullptr),
+      uniformMatrix4x2dv(nullptr),
+      uniformMatrix4x3dv(nullptr),
+      uniformSubroutinesuiv(nullptr),
+
+      activeShaderProgram(nullptr),
+      bindProgramPipeline(nullptr),
+      clearDepthf(nullptr),
+      createShaderProgramv(nullptr),
+      deleteProgramPipelines(nullptr),
+      depthRangeArrayv(nullptr),
+      depthRangeIndexed(nullptr),
+      depthRangef(nullptr),
+      genProgramPipelines(nullptr),
+      getDoublei_v(nullptr),
+      getFloati_v(nullptr),
+      getProgramBinary(nullptr),
+      getProgramPipelineInfoLog(nullptr),
+      getProgramPipelineiv(nullptr),
+      getShaderPrecisionFormat(nullptr),
+      getVertexAttribLdv(nullptr),
+      isProgramPipeline(nullptr),
+      programBinary(nullptr),
+      programParameteri(nullptr),
+      programUniform1d(nullptr),
+      programUniform1dv(nullptr),
+      programUniform1f(nullptr),
+      programUniform1fv(nullptr),
+      programUniform1i(nullptr),
+      programUniform1iv(nullptr),
+      programUniform1ui(nullptr),
+      programUniform1uiv(nullptr),
+      programUniform2d(nullptr),
+      programUniform2dv(nullptr),
+      programUniform2f(nullptr),
+      programUniform2fv(nullptr),
+      programUniform2i(nullptr),
+      programUniform2iv(nullptr),
+      programUniform2ui(nullptr),
+      programUniform2uiv(nullptr),
+      programUniform3d(nullptr),
+      programUniform3dv(nullptr),
+      programUniform3f(nullptr),
+      programUniform3fv(nullptr),
+      programUniform3i(nullptr),
+      programUniform3iv(nullptr),
+      programUniform3ui(nullptr),
+      programUniform3uiv(nullptr),
+      programUniform4d(nullptr),
+      programUniform4dv(nullptr),
+      programUniform4f(nullptr),
+      programUniform4fv(nullptr),
+      programUniform4i(nullptr),
+      programUniform4iv(nullptr),
+      programUniform4ui(nullptr),
+      programUniform4uiv(nullptr),
+      programUniformMatrix2dv(nullptr),
+      programUniformMatrix2fv(nullptr),
+      programUniformMatrix2x3dv(nullptr),
+      programUniformMatrix2x3fv(nullptr),
+      programUniformMatrix2x4dv(nullptr),
+      programUniformMatrix2x4fv(nullptr),
+      programUniformMatrix3dv(nullptr),
+      programUniformMatrix3fv(nullptr),
+      programUniformMatrix3x2dv(nullptr),
+      programUniformMatrix3x2fv(nullptr),
+      programUniformMatrix3x4dv(nullptr),
+      programUniformMatrix3x4fv(nullptr),
+      programUniformMatrix4dv(nullptr),
+      programUniformMatrix4fv(nullptr),
+      programUniformMatrix4x2dv(nullptr),
+      programUniformMatrix4x2fv(nullptr),
+      programUniformMatrix4x3dv(nullptr),
+      programUniformMatrix4x3fv(nullptr),
+      releaseShaderCompiler(nullptr),
+      scissorArrayv(nullptr),
+      scissorIndexed(nullptr),
+      scissorIndexedv(nullptr),
+      shaderBinary(nullptr),
+      useProgramStages(nullptr),
+      validateProgramPipeline(nullptr),
+      vertexAttribL1d(nullptr),
+      vertexAttribL1dv(nullptr),
+      vertexAttribL2d(nullptr),
+      vertexAttribL2dv(nullptr),
+      vertexAttribL3d(nullptr),
+      vertexAttribL3dv(nullptr),
+      vertexAttribL4d(nullptr),
+      vertexAttribL4dv(nullptr),
+      vertexAttribLPointer(nullptr),
+      viewportArrayv(nullptr),
+      viewportIndexedf(nullptr),
+      viewportIndexedfv(nullptr),
+
+      bindImageTexture(nullptr),
+      drawArraysInstancedBaseInstance(nullptr),
+      drawElementsInstancedBaseInstance(nullptr),
+      drawElementsInstancedBaseVertexBaseInstance(nullptr),
+      drawTransformFeedbackInstanced(nullptr),
+      drawTransformFeedbackStreamInstanced(nullptr),
+      getActiveAtomicCounterBufferiv(nullptr),
+      getInternalformativ(nullptr),
+      memoryBarrier(nullptr),
+      texStorage1D(nullptr),
+      texStorage2D(nullptr),
+      texStorage3D(nullptr),
+
+      bindVertexBuffer(nullptr),
+      clearBufferData(nullptr),
+      clearBufferSubData(nullptr),
+      copyImageSubData(nullptr),
+      debugMessageCallback(nullptr),
+      debugMessageControl(nullptr),
+      debugMessageInsert(nullptr),
+      dispatchCompute(nullptr),
+      dispatchComputeIndirect(nullptr),
+      framebufferParameteri(nullptr),
+      getDebugMessageLog(nullptr),
+      getFramebufferParameteriv(nullptr),
+      getInternalformati64v(nullptr),
+      getPointerv(nullptr),
+      getObjectLabel(nullptr),
+      getObjectPtrLabel(nullptr),
+      getProgramInterfaceiv(nullptr),
+      getProgramResourceIndex(nullptr),
+      getProgramResourceLocation(nullptr),
+      getProgramResourceLocationIndex(nullptr),
+      getProgramResourceName(nullptr),
+      getProgramResourceiv(nullptr),
+      invalidateBufferData(nullptr),
+      invalidateBufferSubData(nullptr),
+      invalidateFramebuffer(nullptr),
+      invalidateSubFramebuffer(nullptr),
+      invalidateTexImage(nullptr),
+      invalidateTexSubImage(nullptr),
+      multiDrawArraysIndirect(nullptr),
+      multiDrawElementsIndirect(nullptr),
+      objectLabel(nullptr),
+      objectPtrLabel(nullptr),
+      popDebugGroup(nullptr),
+      pushDebugGroup(nullptr),
+      shaderStorageBlockBinding(nullptr),
+      texBufferRange(nullptr),
+      texStorage2DMultisample(nullptr),
+      texStorage3DMultisample(nullptr),
+      textureView(nullptr),
+      vertexAttribBinding(nullptr),
+      vertexAttribFormat(nullptr),
+      vertexAttribIFormat(nullptr),
+      vertexAttribLFormat(nullptr),
+      vertexBindingDivisor(nullptr),
+      coverageModulationNV(nullptr),
+
+      bindBuffersBase(nullptr),
+      bindBuffersRange(nullptr),
+      bindImageTextures(nullptr),
+      bindSamplers(nullptr),
+      bindTextures(nullptr),
+      bindVertexBuffers(nullptr),
+      bufferStorage(nullptr),
+      clearTexImage(nullptr),
+      clearTexSubImage(nullptr),
+
+      bindTextureUnit(nullptr),
+      blitNamedFramebuffer(nullptr),
+      checkNamedFramebufferStatus(nullptr),
+      clearNamedBufferData(nullptr),
+      clearNamedBufferSubData(nullptr),
+      clearNamedFramebufferfi(nullptr),
+      clearNamedFramebufferfv(nullptr),
+      clearNamedFramebufferiv(nullptr),
+      clearNamedFramebufferuiv(nullptr),
+      clipControl(nullptr),
+      compressedTextureSubImage1D(nullptr),
+      compressedTextureSubImage2D(nullptr),
+      compressedTextureSubImage3D(nullptr),
+      copyNamedBufferSubData(nullptr),
+      copyTextureSubImage1D(nullptr),
+      copyTextureSubImage2D(nullptr),
+      copyTextureSubImage3D(nullptr),
+      createBuffers(nullptr),
+      createFramebuffers(nullptr),
+      createProgramPipelines(nullptr),
+      createQueries(nullptr),
+      createRenderbuffers(nullptr),
+      createSamplers(nullptr),
+      createTextures(nullptr),
+      createTransformFeedbacks(nullptr),
+      createVertexArrays(nullptr),
+      disableVertexArrayAttrib(nullptr),
+      enableVertexArrayAttrib(nullptr),
+      flushMappedNamedBufferRange(nullptr),
+      generateTextureMipmap(nullptr),
+      getCompressedTextureImage(nullptr),
+      getCompressedTextureSubImage(nullptr),
+      getGraphicsResetStatus(nullptr),
+      getNamedBufferParameteri64v(nullptr),
+      getNamedBufferParameteriv(nullptr),
+      getNamedBufferPointerv(nullptr),
+      getNamedBufferSubData(nullptr),
+      getNamedFramebufferAttachmentParameteriv(nullptr),
+      getNamedFramebufferParameteriv(nullptr),
+      getNamedRenderbufferParameteriv(nullptr),
+      getQueryBufferObjecti64v(nullptr),
+      getQueryBufferObjectiv(nullptr),
+      getQueryBufferObjectui64v(nullptr),
+      getQueryBufferObjectuiv(nullptr),
+      getTextureImage(nullptr),
+      getTextureLevelParameterfv(nullptr),
+      getTextureLevelParameteriv(nullptr),
+      getTextureParameterIiv(nullptr),
+      getTextureParameterIuiv(nullptr),
+      getTextureParameterfv(nullptr),
+      getTextureParameteriv(nullptr),
+      getTextureSubImage(nullptr),
+      getTransformFeedbacki64_v(nullptr),
+      getTransformFeedbacki_v(nullptr),
+      getTransformFeedbackiv(nullptr),
+      getVertexArrayIndexed64iv(nullptr),
+      getVertexArrayIndexediv(nullptr),
+      getVertexArrayiv(nullptr),
+      getnCompressedTexImage(nullptr),
+      getnTexImage(nullptr),
+      getnUniformdv(nullptr),
+      getnUniformfv(nullptr),
+      getnUniformiv(nullptr),
+      getnUniformuiv(nullptr),
+      invalidateNamedFramebufferData(nullptr),
+      invalidateNamedFramebufferSubData(nullptr),
+      mapNamedBuffer(nullptr),
+      mapNamedBufferRange(nullptr),
+      memoryBarrierByRegion(nullptr),
+      namedBufferData(nullptr),
+      namedBufferStorage(nullptr),
+      namedBufferSubData(nullptr),
+      namedFramebufferDrawBuffer(nullptr),
+      namedFramebufferDrawBuffers(nullptr),
+      namedFramebufferParameteri(nullptr),
+      namedFramebufferReadBuffer(nullptr),
+      namedFramebufferRenderbuffer(nullptr),
+      namedFramebufferTexture(nullptr),
+      namedFramebufferTextureLayer(nullptr),
+      namedRenderbufferStorage(nullptr),
+      namedRenderbufferStorageMultisample(nullptr),
+      readnPixels(nullptr),
+      textureBarrier(nullptr),
+      textureBuffer(nullptr),
+      textureBufferRange(nullptr),
+      textureParameterIiv(nullptr),
+      textureParameterIuiv(nullptr),
+      textureParameterf(nullptr),
+      textureParameterfv(nullptr),
+      textureParameteri(nullptr),
+      textureParameteriv(nullptr),
+      textureStorage1D(nullptr),
+      textureStorage2D(nullptr),
+      textureStorage2DMultisample(nullptr),
+      textureStorage3D(nullptr),
+      textureStorage3DMultisample(nullptr),
+      textureSubImage1D(nullptr),
+      textureSubImage2D(nullptr),
+      textureSubImage3D(nullptr),
+      transformFeedbackBufferBase(nullptr),
+      transformFeedbackBufferRange(nullptr),
+      unmapNamedBuffer(nullptr),
+      vertexArrayAttribBinding(nullptr),
+      vertexArrayAttribFormat(nullptr),
+      vertexArrayAttribIFormat(nullptr),
+      vertexArrayAttribLFormat(nullptr),
+      vertexArrayBindingDivisor(nullptr),
+      vertexArrayElementBuffer(nullptr),
+      vertexArrayVertexBuffer(nullptr),
+      vertexArrayVertexBuffers(nullptr),
+      blendBarrier(nullptr),
+      primitiveBoundingBox(nullptr),
+      eglImageTargetRenderbufferStorageOES(nullptr),
+      eglImageTargetTexture2DOES(nullptr),
+      discardFramebuffer(nullptr)
+{
+}
+
+FunctionsGL::~FunctionsGL()
+{
+}
+
+void FunctionsGL::initialize()
+{
+    // Grab the version number
+    ASSIGN("glGetString", getString);
+    ASSIGN("glGetIntegerv", getIntegerv);
+    GetGLVersion(getString, &version, &standard);
+
+    // Grab the GL extensions
+    if (isAtLeastGL(gl::Version(3, 0)) || isAtLeastGLES(gl::Version(3, 0)))
+    {
+        ASSIGN("glGetStringi", getStringi);
+        extensions = GetIndexedExtensions(getIntegerv, getStringi);
+    }
+    else
+    {
+        const char *exts = reinterpret_cast<const char*>(getString(GL_EXTENSIONS));
+        angle::SplitStringAlongWhitespace(std::string(exts), &extensions);
+    }
+
+    // Load the entry points
+    switch (standard)
+    {
+        case STANDARD_GL_DESKTOP:
+            initializeProcsDesktopGL();
+            break;
+
+        case STANDARD_GL_ES:
+            initializeProcsGLES();
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void FunctionsGL::initializeProcsDesktopGL()
+{
+    // Check the context profile
+    profile = 0;
+    if (isAtLeastGL(gl::Version(3, 2)))
+    {
+        getIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
+    }
+
+    // clang-format off
+
+    // Load extensions
+    // Even though extensions are written against specific versions of GL, many drivers expose the extensions
+    // in even older versions.  Always try loading the extensions regardless of GL version.
+
+    // GL_ARB_program_interface_query (loading only functions relevant to GL_NV_path_rendering here)
+    ASSIGN_WITH_EXT("GL_ARB_program_interface_query", "glGetProgramInterfaceiv", getProgramInterfaceiv);
+    ASSIGN_WITH_EXT("GL_ARB_program_interface_query", "glGetProgramResourceName", getProgramResourceName);
+    ASSIGN_WITH_EXT("GL_ARB_program_interface_query", "glGetProgramResourceiv", getProgramResourceiv);
+
+    // GL_NV_path_rendering
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glMatrixLoadfEXT", matrixLoadEXT);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glGenPathsNV", genPathsNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glDeletePathsNV", delPathsNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glPathCommandsNV", pathCommandsNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glIsPathNV", isPathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glPathParameterfNV", setPathParameterfNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glPathParameteriNV", setPathParameteriNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glGetPathParameterfvNV", getPathParameterfNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glGetPathParameterivNV", getPathParameteriNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glPathStencilFuncNV", pathStencilFuncNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilFillPathNV", stencilFillPathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilStrokePathNV", stencilStrokePathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glCoverFillPathNV", coverFillPathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glCoverStrokePathNV", coverStrokePathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilThenCoverFillPathNV", stencilThenCoverFillPathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilThenCoverStrokePathNV", stencilThenCoverStrokePathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glCoverFillPathInstancedNV", coverFillPathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glCoverStrokePathInstancedNV", coverStrokePathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilFillPathInstancedNV", stencilFillPathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilStrokePathInstancedNV", stencilStrokePathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilThenCoverFillPathInstancedNV", stencilThenCoverFillPathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilThenCoverStrokePathInstancedNV", stencilThenCoverStrokePathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glProgramPathFragmentInputGenNV", programPathFragmentInputGenNV);
+
+    // GL_NV_framebuffer_mixed_samples
+    ASSIGN_WITH_EXT("GL_NV_framebuffer_mixed_samples", "glCoverageModulationNV", coverageModulationNV);
+
+    // GL_NV_fence
+    ASSIGN_WITH_EXT("GL_NV_fence", "glDeleteFencesNV", deleteFencesNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glGenFencesNV", genFencesNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glIsFenceNV", isFenceNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glTestFenceNV", testFenceNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glGetFenceivNV", getFenceivNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glFinishFenceNV", finishFenceNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glSetFenceNV", setFenceNV);
+
+    // GL_EXT_texture_storage
+    ASSIGN_WITH_EXT("GL_EXT_texture_storage", "glTexStorage1DEXT", texStorage1D);
+    ASSIGN_WITH_EXT("GL_EXT_texture_storage", "glTexStorage2DEXT", texStorage2D);
+    ASSIGN_WITH_EXT("GL_EXT_texture_storage GL_EXT_texture3D", "glTexStorage3DEXT", texStorage3D);
+    ASSIGN_WITH_EXT("GL_EXT_texture_storage GL_EXT_texture3D", "glTextureStorage1DEXT", textureStorage1D);
+    ASSIGN_WITH_EXT("GL_EXT_texture_storage GL_EXT_direct_state_access", "glTextureStorage2DEXT", textureStorage2D);
+    ASSIGN_WITH_EXT("GL_EXT_texture_storage GL_EXT_direct_state_access GL_EXT_texture3D", "glTextureStorage3DEXT", textureStorage3D);
+
+    // GL_ARB_vertex_array_object
+    ASSIGN_WITH_EXT("GL_ARB_vertex_array_object", "glBindVertexArray", bindVertexArray);
+    ASSIGN_WITH_EXT("GL_ARB_vertex_array_object", "glDeleteVertexArrays", deleteVertexArrays);
+    ASSIGN_WITH_EXT("GL_ARB_vertex_array_object", "glGenVertexArrays", genVertexArrays);
+    ASSIGN_WITH_EXT("GL_ARB_vertex_array_object", "glIsVertexArray", isVertexArray);
+
+    // GL_ARB_vertex_attrib_binding
+    ASSIGN_WITH_EXT("GL_ARB_vertex_attrib_binding", "glBindVertexBuffer", bindVertexBuffer);
+    ASSIGN_WITH_EXT("GL_ARB_vertex_attrib_binding", "glVertexAttribFormat", vertexAttribFormat);
+    ASSIGN_WITH_EXT("GL_ARB_vertex_attrib_binding", "glVertexAttribIFormat", vertexAttribIFormat);
+    ASSIGN_WITH_EXT("GL_ARB_vertex_attrib_binding", "glVertexAttribLFormat", vertexAttribLFormat);
+    ASSIGN_WITH_EXT("GL_ARB_vertex_attrib_binding", "glVertexAttribBinding", vertexAttribBinding);
+    ASSIGN_WITH_EXT("GL_ARB_vertex_attrib_binding", "glVertexBindingDivisor", vertexBindingDivisor);
+
+    // GL_ARB_sync
+    ASSIGN_WITH_EXT("GL_ARB_sync", "glClientWaitSync", clientWaitSync);
+    ASSIGN_WITH_EXT("GL_ARB_sync", "glDeleteSync", deleteSync);
+    ASSIGN_WITH_EXT("GL_ARB_sync", "glFenceSync", fenceSync);
+    ASSIGN_WITH_EXT("GL_ARB_sync", "glGetInteger64i_v", getInteger64i_v);
+    ASSIGN_WITH_EXT("GL_ARB_sync", "glGetInteger64v", getInteger64v);
+    ASSIGN_WITH_EXT("GL_ARB_sync", "glGetSynciv", getSynciv);
+    ASSIGN_WITH_EXT("GL_ARB_sync", "glIsSync", isSync);
+    ASSIGN_WITH_EXT("GL_ARB_sync", "glWaitSync", waitSync);
+
+    // GL_EXT_framebuffer_object
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glIsRenderbufferEXT", isRenderbuffer);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glBindRenderbufferEXT", bindRenderbuffer);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glDeleteRenderbuffersEXT", deleteRenderbuffers);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glGenRenderbuffersEXT", genRenderbuffers);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glRenderbufferStorageEXT", renderbufferStorage);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glGetRenderbufferParameterivEXT", getRenderbufferParameteriv);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glIsFramebufferEXT", isFramebuffer);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glBindFramebufferEXT", bindFramebuffer);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glDeleteFramebuffersEXT", deleteFramebuffers);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glGenFramebuffersEXT", genFramebuffers);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glCheckFramebufferStatusEXT", checkFramebufferStatus);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glFramebufferTexture1DEXT", framebufferTexture1D);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glFramebufferTexture2DEXT", framebufferTexture2D);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glFramebufferTexture3DEXT", framebufferTexture3D);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glFramebufferRenderbufferEXT", framebufferRenderbuffer);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glGetFramebufferAttachmentParameterivEXT", getFramebufferAttachmentParameteriv);
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_object", "glGenerateMipmapEXT", generateMipmap);
+
+    // GL_EXT_framebuffer_blit
+    ASSIGN_WITH_EXT("GL_EXT_framebuffer_blit", "glBlitFramebufferEXT", blitFramebuffer);
+
+    // GL_KHR_debug
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glDebugMessageControl", debugMessageControl);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glDebugMessageInsert", debugMessageInsert);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glDebugMessageCallback", debugMessageCallback);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glGetDebugMessageLog", getDebugMessageLog);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glGetPointerv", getPointerv);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glPushDebugGroup", pushDebugGroup);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glPopDebugGroup", popDebugGroup);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glObjectLabel", objectLabel);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glGetObjectLabel", getObjectLabel);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glObjectPtrLabel", objectPtrLabel);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glGetObjectPtrLabel", getObjectPtrLabel);
+
+    // GL_ARB_internalformat_query
+    ASSIGN_WITH_EXT("GL_ARB_internalformat_query", "glGetInternalformativ", getInternalformativ);
+
+    // GL_ARB_ES2_compatibility
+    ASSIGN_WITH_EXT("GL_ARB_ES2_compatibility", "glReleaseShaderCompiler", releaseShaderCompiler);
+    ASSIGN_WITH_EXT("GL_ARB_ES2_compatibility", "glShaderBinary", shaderBinary);
+    ASSIGN_WITH_EXT("GL_ARB_ES2_compatibility", "glGetShaderPrecisionFormat", getShaderPrecisionFormat);
+    ASSIGN_WITH_EXT("GL_ARB_ES2_compatibility", "glDepthRangef", depthRangef);
+    ASSIGN_WITH_EXT("GL_ARB_ES2_compatibility", "glClearDepthf", clearDepthf);
+
+    // GL_ARB_instanced_arrays
+    ASSIGN_WITH_EXT("GL_ARB_instanced_arrays", "glVertexAttribDivisorARB", vertexAttribDivisor);
+
+    // GL_EXT_draw_instanced
+    ASSIGN_WITH_EXT("GL_EXT_draw_instanced", "glDrawArraysInstancedEXT", drawArraysInstanced);
+    ASSIGN_WITH_EXT("GL_EXT_draw_instanced", "glDrawElementsInstancedEXT", drawElementsInstanced);
+
+    // GL_ARB_draw_instanced
+    ASSIGN_WITH_EXT("GL_ARB_draw_instanced", "glDrawArraysInstancedARB", drawArraysInstanced);
+    ASSIGN_WITH_EXT("GL_ARB_draw_instanced", "glDrawElementsInstancedARB", drawElementsInstanced);
+
+    // GL_ARB_sampler_objects
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glGenSamplers", genSamplers);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glDeleteSamplers", deleteSamplers);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glIsSampler", isSampler);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glBindSampler", bindSampler);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glSamplerParameteri", samplerParameteri);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glSamplerParameterf", samplerParameterf);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glSamplerParameteriv", samplerParameteriv);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glSamplerParameterfv", samplerParameterfv);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glSamplerParameterIiv", samplerParameterIiv);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glSamplerParameterIuiv", samplerParameterIuiv);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glGetSamplerParameteriv", getSamplerParameteriv);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glGetSamplerParameterfv", getSamplerParameterfv);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glGetSamplerParameterIiv", getSamplerParameterIiv);
+    ASSIGN_WITH_EXT("GL_ARB_sampler_objects", "glGetSamplerParameterIuiv", getSamplerParameterIuiv);
+
+    // GL_ARB_occlusion_query
+    ASSIGN_WITH_EXT("GL_ARB_occlusion_query", "glGenQueriesARB", genQueries);
+    ASSIGN_WITH_EXT("GL_ARB_occlusion_query", "glDeleteQueriesARB", deleteQueries);
+    ASSIGN_WITH_EXT("GL_ARB_occlusion_query", "glIsQueryARB", isQuery);
+    ASSIGN_WITH_EXT("GL_ARB_occlusion_query", "glBeginQueryARB", beginQuery);
+    ASSIGN_WITH_EXT("GL_ARB_occlusion_query", "glEndQueryARB", endQuery);
+    ASSIGN_WITH_EXT("GL_ARB_occlusion_query", "glGetQueryivARB", getQueryiv);
+    ASSIGN_WITH_EXT("GL_ARB_occlusion_query", "glGetQueryObjectivARB", getQueryObjectiv);
+    ASSIGN_WITH_EXT("GL_ARB_occlusion_query", "glGetQueryObjectuivARB", getQueryObjectuiv);
+
+    // EXT_transform_feedback
+    ASSIGN_WITH_EXT("EXT_transform_feedback", "glBindBufferRangeEXT", bindBufferRange);
+    ASSIGN_WITH_EXT("EXT_transform_feedback", "glBindBufferBaseEXT", bindBufferBase);
+    ASSIGN_WITH_EXT("EXT_transform_feedback", "glBeginTransformFeedbackEXT", beginTransformFeedback);
+    ASSIGN_WITH_EXT("EXT_transform_feedback", "glEndTransformFeedbackEXT", endTransformFeedback);
+    ASSIGN_WITH_EXT("EXT_transform_feedback", "glTransformFeedbackVaryingsEXT", transformFeedbackVaryings);
+    ASSIGN_WITH_EXT("EXT_transform_feedback", "glGetTransformFeedbackVaryingEXT", getTransformFeedbackVarying);
+
+    // GL_ARB_transform_feedback2
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback2", "glBindTransformFeedback", bindTransformFeedback);
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback2", "glDeleteTransformFeedbacks", deleteTransformFeedbacks);
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback2", "glGenTransformFeedbacks", genTransformFeedbacks);
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback2", "glIsTransformFeedback", isTransformFeedback);
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback2", "glPauseTransformFeedback", pauseTransformFeedback);
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback2", "glResumeTransformFeedback", resumeTransformFeedback);
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback2", "glDrawTransformFeedback", drawTransformFeedback);
+
+    // GL_ARB_transform_feedback3
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback3", "glDrawTransformFeedbackStream", drawTransformFeedbackStream);
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback3", "glBeginQueryIndexed", beginQueryIndexed);
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback3", "glEndQueryIndexed", endQueryIndexed);
+    ASSIGN_WITH_EXT("GL_ARB_transform_feedback3", "glGetQueryIndexediv", getQueryIndexediv);
+
+    // GL_ARB_get_program_binary
+    ASSIGN_WITH_EXT("GL_ARB_get_program_binary", "glGetProgramBinary", getProgramBinary);
+    ASSIGN_WITH_EXT("GL_ARB_get_program_binary", "glProgramBinary", programBinary);
+    ASSIGN_WITH_EXT("GL_ARB_get_program_binary", "glProgramParameteri", programParameteri);
+
+    // GL_ARB_robustness
+    ASSIGN_WITH_EXT("GL_ARB_robustness", "glGetGraphicsResetStatusARB", getGraphicsResetStatus);
+
+    // GL_KHR_robustness
+    ASSIGN_WITH_EXT("GL_KHR_robustness", "glGetGraphicsResetStatus", getGraphicsResetStatus);
+
+    // GL_ARB_invalidate_subdata
+    ASSIGN_WITH_EXT("GL_ARB_invalidate_subdata", "glInvalidateTexSubImage", invalidateTexSubImage);
+    ASSIGN_WITH_EXT("GL_ARB_invalidate_subdata", "glInvalidateTexImage", invalidateTexImage);
+    ASSIGN_WITH_EXT("GL_ARB_invalidate_subdata", "glInvalidateBufferSubData", invalidateBufferSubData);
+    ASSIGN_WITH_EXT("GL_ARB_invalidate_subdata", "glInvalidateBufferData", invalidateBufferData);
+    ASSIGN_WITH_EXT("GL_ARB_invalidate_subdata", "glInvalidateFramebuffer", invalidateFramebuffer);
+    ASSIGN_WITH_EXT("GL_ARB_invalidate_subdata", "glInvalidateSubFramebuffer", invalidateSubFramebuffer);
+
+    // 1.0
+    if (isAtLeastGL(gl::Version(1, 0)))
+    {
+        ASSIGN("glBlendFunc", blendFunc);
+        ASSIGN("glClear", clear);
+        ASSIGN("glClearColor", clearColor);
+        ASSIGN("glClearDepth", clearDepth);
+        ASSIGN("glClearStencil", clearStencil);
+        ASSIGN("glColorMask", colorMask);
+        ASSIGN("glCullFace", cullFace);
+        ASSIGN("glDepthFunc", depthFunc);
+        ASSIGN("glDepthMask", depthMask);
+        ASSIGN("glDepthRange", depthRange);
+        ASSIGN("glDisable", disable);
+        ASSIGN("glDrawBuffer", drawBuffer);
+        ASSIGN("glEnable", enable);
+        ASSIGN("glFinish", finish);
+        ASSIGN("glFlush", flush);
+        ASSIGN("glFrontFace", frontFace);
+        ASSIGN("glGetBooleanv", getBooleanv);
+        ASSIGN("glGetDoublev", getDoublev);
+        ASSIGN("glGetError", getError);
+        ASSIGN("glGetFloatv", getFloatv);
+        ASSIGN("glGetIntegerv", getIntegerv);
+        ASSIGN("glGetString", getString);
+        ASSIGN("glGetTexImage", getTexImage);
+        ASSIGN("glGetTexLevelParameterfv", getTexLevelParameterfv);
+        ASSIGN("glGetTexLevelParameteriv", getTexLevelParameteriv);
+        ASSIGN("glGetTexParameterfv", getTexParameterfv);
+        ASSIGN("glGetTexParameteriv", getTexParameteriv);
+        ASSIGN("glHint", hint);
+        ASSIGN("glIsEnabled", isEnabled);
+        ASSIGN("glLineWidth", lineWidth);
+        ASSIGN("glLogicOp", logicOp);
+        ASSIGN("glPixelStoref", pixelStoref);
+        ASSIGN("glPixelStorei", pixelStorei);
+        ASSIGN("glPointSize", pointSize);
+        ASSIGN("glPolygonMode", polygonMode);
+        ASSIGN("glReadBuffer", readBuffer);
+        ASSIGN("glReadPixels", readPixels);
+        ASSIGN("glScissor", scissor);
+        ASSIGN("glStencilFunc", stencilFunc);
+        ASSIGN("glStencilMask", stencilMask);
+        ASSIGN("glStencilOp", stencilOp);
+        ASSIGN("glTexImage1D", texImage1D);
+        ASSIGN("glTexImage2D", texImage2D);
+        ASSIGN("glTexParameterf", texParameterf);
+        ASSIGN("glTexParameterfv", texParameterfv);
+        ASSIGN("glTexParameteri", texParameteri);
+        ASSIGN("glTexParameteriv", texParameteriv);
+        ASSIGN("glViewport", viewport);
+    }
+
+    // 1.1
+    if (isAtLeastGL(gl::Version(1, 1)))
+    {
+        ASSIGN("glBindTexture", bindTexture);
+        ASSIGN("glCopyTexImage1D", copyTexImage1D);
+        ASSIGN("glCopyTexImage2D", copyTexImage2D);
+        ASSIGN("glCopyTexSubImage1D", copyTexSubImage1D);
+        ASSIGN("glCopyTexSubImage2D", copyTexSubImage2D);
+        ASSIGN("glDeleteTextures", deleteTextures);
+        ASSIGN("glDrawArrays", drawArrays);
+        ASSIGN("glDrawElements", drawElements);
+        ASSIGN("glGenTextures", genTextures);
+        ASSIGN("glIsTexture", isTexture);
+        ASSIGN("glPolygonOffset", polygonOffset);
+        ASSIGN("glTexSubImage1D", texSubImage1D);
+        ASSIGN("glTexSubImage2D", texSubImage2D);
+    }
+
+    // 1.2
+    if (isAtLeastGL(gl::Version(1, 2)))
+    {
+        ASSIGN("glBlendColor", blendColor);
+        ASSIGN("glBlendEquation", blendEquation);
+        ASSIGN("glCopyTexSubImage3D", copyTexSubImage3D);
+        ASSIGN("glDrawRangeElements", drawRangeElements);
+        ASSIGN("glTexImage3D", texImage3D);
+        ASSIGN("glTexSubImage3D", texSubImage3D);
+    }
+
+    // 1.3
+    if (isAtLeastGL(gl::Version(1, 3)))
+    {
+        ASSIGN("glActiveTexture", activeTexture);
+        ASSIGN("glCompressedTexImage1D", compressedTexImage1D);
+        ASSIGN("glCompressedTexImage2D", compressedTexImage2D);
+        ASSIGN("glCompressedTexImage3D", compressedTexImage3D);
+        ASSIGN("glCompressedTexSubImage1D", compressedTexSubImage1D);
+        ASSIGN("glCompressedTexSubImage2D", compressedTexSubImage2D);
+        ASSIGN("glCompressedTexSubImage3D", compressedTexSubImage3D);
+        ASSIGN("glGetCompressedTexImage", getCompressedTexImage);
+        ASSIGN("glSampleCoverage", sampleCoverage);
+    }
+
+    // 1.4
+    if (isAtLeastGL(gl::Version(1, 4)))
+    {
+        ASSIGN("glBlendFuncSeparate", blendFuncSeparate);
+        ASSIGN("glMultiDrawArrays", multiDrawArrays);
+        ASSIGN("glMultiDrawElements", multiDrawElements);
+        ASSIGN("glPointParameterf", pointParameterf);
+        ASSIGN("glPointParameterfv", pointParameterfv);
+        ASSIGN("glPointParameteri", pointParameteri);
+        ASSIGN("glPointParameteriv", pointParameteriv);
+    }
+
+    // 1.5
+    if (isAtLeastGL(gl::Version(1, 5)))
+    {
+        ASSIGN("glBeginQuery", beginQuery);
+        ASSIGN("glBindBuffer", bindBuffer);
+        ASSIGN("glBufferData", bufferData);
+        ASSIGN("glBufferSubData", bufferSubData);
+        ASSIGN("glDeleteBuffers", deleteBuffers);
+        ASSIGN("glDeleteQueries", deleteQueries);
+        ASSIGN("glEndQuery", endQuery);
+        ASSIGN("glGenBuffers", genBuffers);
+        ASSIGN("glGenQueries", genQueries);
+        ASSIGN("glGetBufferParameteriv", getBufferParameteriv);
+        ASSIGN("glGetBufferPointerv", getBufferPointerv);
+        ASSIGN("glGetBufferSubData", getBufferSubData);
+        ASSIGN("glGetQueryObjectiv", getQueryObjectiv);
+        ASSIGN("glGetQueryObjectuiv", getQueryObjectuiv);
+        ASSIGN("glGetQueryiv", getQueryiv);
+        ASSIGN("glIsBuffer", isBuffer);
+        ASSIGN("glIsQuery", isQuery);
+        ASSIGN("glMapBuffer", mapBuffer);
+        ASSIGN("glUnmapBuffer", unmapBuffer);
+    }
+
+    // 2.0
+    if (isAtLeastGL(gl::Version(2, 0)))
+    {
+        ASSIGN("glAttachShader", attachShader);
+        ASSIGN("glBindAttribLocation", bindAttribLocation);
+        ASSIGN("glBlendEquationSeparate", blendEquationSeparate);
+        ASSIGN("glCompileShader", compileShader);
+        ASSIGN("glCreateProgram", createProgram);
+        ASSIGN("glCreateShader", createShader);
+        ASSIGN("glDeleteProgram", deleteProgram);
+        ASSIGN("glDeleteShader", deleteShader);
+        ASSIGN("glDetachShader", detachShader);
+        ASSIGN("glDisableVertexAttribArray", disableVertexAttribArray);
+        ASSIGN("glDrawBuffers", drawBuffers);
+        ASSIGN("glEnableVertexAttribArray", enableVertexAttribArray);
+        ASSIGN("glGetActiveAttrib", getActiveAttrib);
+        ASSIGN("glGetActiveUniform", getActiveUniform);
+        ASSIGN("glGetAttachedShaders", getAttachedShaders);
+        ASSIGN("glGetAttribLocation", getAttribLocation);
+        ASSIGN("glGetProgramInfoLog", getProgramInfoLog);
+        ASSIGN("glGetProgramiv", getProgramiv);
+        ASSIGN("glGetShaderInfoLog", getShaderInfoLog);
+        ASSIGN("glGetShaderSource", getShaderSource);
+        ASSIGN("glGetShaderiv", getShaderiv);
+        ASSIGN("glGetUniformLocation", getUniformLocation);
+        ASSIGN("glGetUniformfv", getUniformfv);
+        ASSIGN("glGetUniformiv", getUniformiv);
+        ASSIGN("glGetVertexAttribPointerv", getVertexAttribPointerv);
+        ASSIGN("glGetVertexAttribdv", getVertexAttribdv);
+        ASSIGN("glGetVertexAttribfv", getVertexAttribfv);
+        ASSIGN("glGetVertexAttribiv", getVertexAttribiv);
+        ASSIGN("glIsProgram", isProgram);
+        ASSIGN("glIsShader", isShader);
+        ASSIGN("glLinkProgram", linkProgram);
+        ASSIGN("glShaderSource", shaderSource);
+        ASSIGN("glStencilFuncSeparate", stencilFuncSeparate);
+        ASSIGN("glStencilMaskSeparate", stencilMaskSeparate);
+        ASSIGN("glStencilOpSeparate", stencilOpSeparate);
+        ASSIGN("glUniform1f", uniform1f);
+        ASSIGN("glUniform1fv", uniform1fv);
+        ASSIGN("glUniform1i", uniform1i);
+        ASSIGN("glUniform1iv", uniform1iv);
+        ASSIGN("glUniform2f", uniform2f);
+        ASSIGN("glUniform2fv", uniform2fv);
+        ASSIGN("glUniform2i", uniform2i);
+        ASSIGN("glUniform2iv", uniform2iv);
+        ASSIGN("glUniform3f", uniform3f);
+        ASSIGN("glUniform3fv", uniform3fv);
+        ASSIGN("glUniform3i", uniform3i);
+        ASSIGN("glUniform3iv", uniform3iv);
+        ASSIGN("glUniform4f", uniform4f);
+        ASSIGN("glUniform4fv", uniform4fv);
+        ASSIGN("glUniform4i", uniform4i);
+        ASSIGN("glUniform4iv", uniform4iv);
+        ASSIGN("glUniformMatrix2fv", uniformMatrix2fv);
+        ASSIGN("glUniformMatrix3fv", uniformMatrix3fv);
+        ASSIGN("glUniformMatrix4fv", uniformMatrix4fv);
+        ASSIGN("glUseProgram", useProgram);
+        ASSIGN("glValidateProgram", validateProgram);
+        ASSIGN("glVertexAttrib1d", vertexAttrib1d);
+        ASSIGN("glVertexAttrib1dv", vertexAttrib1dv);
+        ASSIGN("glVertexAttrib1f", vertexAttrib1f);
+        ASSIGN("glVertexAttrib1fv", vertexAttrib1fv);
+        ASSIGN("glVertexAttrib1s", vertexAttrib1s);
+        ASSIGN("glVertexAttrib1sv", vertexAttrib1sv);
+        ASSIGN("glVertexAttrib2d", vertexAttrib2d);
+        ASSIGN("glVertexAttrib2dv", vertexAttrib2dv);
+        ASSIGN("glVertexAttrib2f", vertexAttrib2f);
+        ASSIGN("glVertexAttrib2fv", vertexAttrib2fv);
+        ASSIGN("glVertexAttrib2s", vertexAttrib2s);
+        ASSIGN("glVertexAttrib2sv", vertexAttrib2sv);
+        ASSIGN("glVertexAttrib3d", vertexAttrib3d);
+        ASSIGN("glVertexAttrib3dv", vertexAttrib3dv);
+        ASSIGN("glVertexAttrib3f", vertexAttrib3f);
+        ASSIGN("glVertexAttrib3fv", vertexAttrib3fv);
+        ASSIGN("glVertexAttrib3s", vertexAttrib3s);
+        ASSIGN("glVertexAttrib3sv", vertexAttrib3sv);
+        ASSIGN("glVertexAttrib4Nbv", vertexAttrib4Nbv);
+        ASSIGN("glVertexAttrib4Niv", vertexAttrib4Niv);
+        ASSIGN("glVertexAttrib4Nsv", vertexAttrib4Nsv);
+        ASSIGN("glVertexAttrib4Nub", vertexAttrib4Nub);
+        ASSIGN("glVertexAttrib4Nubv", vertexAttrib4Nubv);
+        ASSIGN("glVertexAttrib4Nuiv", vertexAttrib4Nuiv);
+        ASSIGN("glVertexAttrib4Nusv", vertexAttrib4Nusv);
+        ASSIGN("glVertexAttrib4bv", vertexAttrib4bv);
+        ASSIGN("glVertexAttrib4d", vertexAttrib4d);
+        ASSIGN("glVertexAttrib4dv", vertexAttrib4dv);
+        ASSIGN("glVertexAttrib4f", vertexAttrib4f);
+        ASSIGN("glVertexAttrib4fv", vertexAttrib4fv);
+        ASSIGN("glVertexAttrib4iv", vertexAttrib4iv);
+        ASSIGN("glVertexAttrib4s", vertexAttrib4s);
+        ASSIGN("glVertexAttrib4sv", vertexAttrib4sv);
+        ASSIGN("glVertexAttrib4ubv", vertexAttrib4ubv);
+        ASSIGN("glVertexAttrib4uiv", vertexAttrib4uiv);
+        ASSIGN("glVertexAttrib4usv", vertexAttrib4usv);
+        ASSIGN("glVertexAttribPointer", vertexAttribPointer);
+    }
+
+    // 2.1
+    if (isAtLeastGL(gl::Version(2, 1)))
+    {
+        ASSIGN("glUniformMatrix2x3fv", uniformMatrix2x3fv);
+        ASSIGN("glUniformMatrix2x4fv", uniformMatrix2x4fv);
+        ASSIGN("glUniformMatrix3x2fv", uniformMatrix3x2fv);
+        ASSIGN("glUniformMatrix3x4fv", uniformMatrix3x4fv);
+        ASSIGN("glUniformMatrix4x2fv", uniformMatrix4x2fv);
+        ASSIGN("glUniformMatrix4x3fv", uniformMatrix4x3fv);
+    }
+
+    // 3.0
+    if (isAtLeastGL(gl::Version(3, 0)))
+    {
+        ASSIGN("glBeginConditionalRender", beginConditionalRender);
+        ASSIGN("glBeginTransformFeedback", beginTransformFeedback);
+        ASSIGN("glBindBufferBase", bindBufferBase);
+        ASSIGN("glBindBufferRange", bindBufferRange);
+        ASSIGN("glBindFragDataLocation", bindFragDataLocation);
+        ASSIGN("glBindFramebuffer", bindFramebuffer);
+        ASSIGN("glBindRenderbuffer", bindRenderbuffer);
+        ASSIGN("glBindVertexArray", bindVertexArray);
+        ASSIGN("glBlitFramebuffer", blitFramebuffer);
+        ASSIGN("glCheckFramebufferStatus", checkFramebufferStatus);
+        ASSIGN("glClampColor", clampColor);
+        ASSIGN("glClearBufferfi", clearBufferfi);
+        ASSIGN("glClearBufferfv", clearBufferfv);
+        ASSIGN("glClearBufferiv", clearBufferiv);
+        ASSIGN("glClearBufferuiv", clearBufferuiv);
+        ASSIGN("glColorMaski", colorMaski);
+        ASSIGN("glDeleteFramebuffers", deleteFramebuffers);
+        ASSIGN("glDeleteRenderbuffers", deleteRenderbuffers);
+        ASSIGN("glDeleteVertexArrays", deleteVertexArrays);
+        ASSIGN("glDisablei", disablei);
+        ASSIGN("glEnablei", enablei);
+        ASSIGN("glEndConditionalRender", endConditionalRender);
+        ASSIGN("glEndTransformFeedback", endTransformFeedback);
+        ASSIGN("glFlushMappedBufferRange", flushMappedBufferRange);
+        ASSIGN("glFramebufferRenderbuffer", framebufferRenderbuffer);
+        ASSIGN("glFramebufferTexture1D", framebufferTexture1D);
+        ASSIGN("glFramebufferTexture2D", framebufferTexture2D);
+        ASSIGN("glFramebufferTexture3D", framebufferTexture3D);
+        ASSIGN("glFramebufferTextureLayer", framebufferTextureLayer);
+        ASSIGN("glGenFramebuffers", genFramebuffers);
+        ASSIGN("glGenRenderbuffers", genRenderbuffers);
+        ASSIGN("glGenVertexArrays", genVertexArrays);
+        ASSIGN("glGenerateMipmap", generateMipmap);
+        ASSIGN("glGetBooleani_v", getBooleani_v);
+        ASSIGN("glGetFragDataLocation", getFragDataLocation);
+        ASSIGN("glGetFramebufferAttachmentParameteriv", getFramebufferAttachmentParameteriv);
+        ASSIGN("glGetIntegeri_v", getIntegeri_v);
+        ASSIGN("glGetRenderbufferParameteriv", getRenderbufferParameteriv);
+        ASSIGN("glGetStringi", getStringi);
+        ASSIGN("glGetTexParameterIiv", getTexParameterIiv);
+        ASSIGN("glGetTexParameterIuiv", getTexParameterIuiv);
+        ASSIGN("glGetTransformFeedbackVarying", getTransformFeedbackVarying);
+        ASSIGN("glGetUniformuiv", getUniformuiv);
+        ASSIGN("glGetVertexAttribIiv", getVertexAttribIiv);
+        ASSIGN("glGetVertexAttribIuiv", getVertexAttribIuiv);
+        ASSIGN("glIsEnabledi", isEnabledi);
+        ASSIGN("glIsFramebuffer", isFramebuffer);
+        ASSIGN("glIsRenderbuffer", isRenderbuffer);
+        ASSIGN("glIsVertexArray", isVertexArray);
+        ASSIGN("glMapBufferRange", mapBufferRange);
+        ASSIGN("glRenderbufferStorage", renderbufferStorage);
+        ASSIGN("glRenderbufferStorageMultisample", renderbufferStorageMultisample);
+        ASSIGN("glTexParameterIiv", texParameterIiv);
+        ASSIGN("glTexParameterIuiv", texParameterIuiv);
+        ASSIGN("glTransformFeedbackVaryings", transformFeedbackVaryings);
+        ASSIGN("glUniform1ui", uniform1ui);
+        ASSIGN("glUniform1uiv", uniform1uiv);
+        ASSIGN("glUniform2ui", uniform2ui);
+        ASSIGN("glUniform2uiv", uniform2uiv);
+        ASSIGN("glUniform3ui", uniform3ui);
+        ASSIGN("glUniform3uiv", uniform3uiv);
+        ASSIGN("glUniform4ui", uniform4ui);
+        ASSIGN("glUniform4uiv", uniform4uiv);
+        ASSIGN("glVertexAttribI1i", vertexAttribI1i);
+        ASSIGN("glVertexAttribI1iv", vertexAttribI1iv);
+        ASSIGN("glVertexAttribI1ui", vertexAttribI1ui);
+        ASSIGN("glVertexAttribI1uiv", vertexAttribI1uiv);
+        ASSIGN("glVertexAttribI2i", vertexAttribI2i);
+        ASSIGN("glVertexAttribI2iv", vertexAttribI2iv);
+        ASSIGN("glVertexAttribI2ui", vertexAttribI2ui);
+        ASSIGN("glVertexAttribI2uiv", vertexAttribI2uiv);
+        ASSIGN("glVertexAttribI3i", vertexAttribI3i);
+        ASSIGN("glVertexAttribI3iv", vertexAttribI3iv);
+        ASSIGN("glVertexAttribI3ui", vertexAttribI3ui);
+        ASSIGN("glVertexAttribI3uiv", vertexAttribI3uiv);
+        ASSIGN("glVertexAttribI4bv", vertexAttribI4bv);
+        ASSIGN("glVertexAttribI4i", vertexAttribI4i);
+        ASSIGN("glVertexAttribI4iv", vertexAttribI4iv);
+        ASSIGN("glVertexAttribI4sv", vertexAttribI4sv);
+        ASSIGN("glVertexAttribI4ubv", vertexAttribI4ubv);
+        ASSIGN("glVertexAttribI4ui", vertexAttribI4ui);
+        ASSIGN("glVertexAttribI4uiv", vertexAttribI4uiv);
+        ASSIGN("glVertexAttribI4usv", vertexAttribI4usv);
+        ASSIGN("glVertexAttribIPointer", vertexAttribIPointer);
+    }
+
+    // 3.1
+    if (isAtLeastGL(gl::Version(3, 1)))
+    {
+        ASSIGN("glCopyBufferSubData", copyBufferSubData);
+        ASSIGN("glDrawArraysInstanced", drawArraysInstanced);
+        ASSIGN("glDrawElementsInstanced", drawElementsInstanced);
+        ASSIGN("glGetActiveUniformBlockName", getActiveUniformBlockName);
+        ASSIGN("glGetActiveUniformBlockiv", getActiveUniformBlockiv);
+        ASSIGN("glGetActiveUniformName", getActiveUniformName);
+        ASSIGN("glGetActiveUniformsiv", getActiveUniformsiv);
+        ASSIGN("glGetUniformBlockIndex", getUniformBlockIndex);
+        ASSIGN("glGetUniformIndices", getUniformIndices);
+        ASSIGN("glPrimitiveRestartIndex", primitiveRestartIndex);
+        ASSIGN("glTexBuffer", texBuffer);
+        ASSIGN("glUniformBlockBinding", uniformBlockBinding);
+    }
+
+    // 3.2
+    if (isAtLeastGL(gl::Version(3, 2)))
+    {
+        ASSIGN("glClientWaitSync", clientWaitSync);
+        ASSIGN("glDeleteSync", deleteSync);
+        ASSIGN("glDrawElementsBaseVertex", drawElementsBaseVertex);
+        ASSIGN("glDrawElementsInstancedBaseVertex", drawElementsInstancedBaseVertex);
+        ASSIGN("glDrawRangeElementsBaseVertex", drawRangeElementsBaseVertex);
+        ASSIGN("glFenceSync", fenceSync);
+        ASSIGN("glFramebufferTexture", framebufferTexture);
+        ASSIGN("glGetBufferParameteri64v", getBufferParameteri64v);
+        ASSIGN("glGetInteger64i_v", getInteger64i_v);
+        ASSIGN("glGetInteger64v", getInteger64v);
+        ASSIGN("glGetMultisamplefv", getMultisamplefv);
+        ASSIGN("glGetSynciv", getSynciv);
+        ASSIGN("glIsSync", isSync);
+        ASSIGN("glMultiDrawElementsBaseVertex", multiDrawElementsBaseVertex);
+        ASSIGN("glProvokingVertex", provokingVertex);
+        ASSIGN("glSampleMaski", sampleMaski);
+        ASSIGN("glTexImage2DMultisample", texImage2DMultisample);
+        ASSIGN("glTexImage3DMultisample", texImage3DMultisample);
+        ASSIGN("glWaitSync", waitSync);
+    }
+
+    // 3.3
+    if (isAtLeastGL(gl::Version(3, 3)))
+    {
+        ASSIGN("glBindFragDataLocationIndexed", bindFragDataLocationIndexed);
+        ASSIGN("glBindSampler", bindSampler);
+        ASSIGN("glDeleteSamplers", deleteSamplers);
+        ASSIGN("glGenSamplers", genSamplers);
+        ASSIGN("glGetFragDataIndex", getFragDataIndex);
+        ASSIGN("glGetQueryObjecti64v", getQueryObjecti64v);
+        ASSIGN("glGetQueryObjectui64v", getQueryObjectui64v);
+        ASSIGN("glGetSamplerParameterIiv", getSamplerParameterIiv);
+        ASSIGN("glGetSamplerParameterIuiv", getSamplerParameterIuiv);
+        ASSIGN("glGetSamplerParameterfv", getSamplerParameterfv);
+        ASSIGN("glGetSamplerParameteriv", getSamplerParameteriv);
+        ASSIGN("glIsSampler", isSampler);
+        ASSIGN("glQueryCounter", queryCounter);
+        ASSIGN("glSamplerParameterIiv", samplerParameterIiv);
+        ASSIGN("glSamplerParameterIuiv", samplerParameterIuiv);
+        ASSIGN("glSamplerParameterf", samplerParameterf);
+        ASSIGN("glSamplerParameterfv", samplerParameterfv);
+        ASSIGN("glSamplerParameteri", samplerParameteri);
+        ASSIGN("glSamplerParameteriv", samplerParameteriv);
+        ASSIGN("glVertexAttribDivisor", vertexAttribDivisor);
+        ASSIGN("glVertexAttribP1ui", vertexAttribP1ui);
+        ASSIGN("glVertexAttribP1uiv", vertexAttribP1uiv);
+        ASSIGN("glVertexAttribP2ui", vertexAttribP2ui);
+        ASSIGN("glVertexAttribP2uiv", vertexAttribP2uiv);
+        ASSIGN("glVertexAttribP3ui", vertexAttribP3ui);
+        ASSIGN("glVertexAttribP3uiv", vertexAttribP3uiv);
+        ASSIGN("glVertexAttribP4ui", vertexAttribP4ui);
+        ASSIGN("glVertexAttribP4uiv", vertexAttribP4uiv);
+    }
+
+    // 4.0
+    if (isAtLeastGL(gl::Version(4, 0)))
+    {
+        ASSIGN("glBeginQueryIndexed", beginQueryIndexed);
+        ASSIGN("glBindTransformFeedback", bindTransformFeedback);
+        ASSIGN("glBlendEquationSeparatei", blendEquationSeparatei);
+        ASSIGN("glBlendEquationi", blendEquationi);
+        ASSIGN("glBlendFuncSeparatei", blendFuncSeparatei);
+        ASSIGN("glBlendFunci", blendFunci);
+        ASSIGN("glDeleteTransformFeedbacks", deleteTransformFeedbacks);
+        ASSIGN("glDrawArraysIndirect", drawArraysIndirect);
+        ASSIGN("glDrawElementsIndirect", drawElementsIndirect);
+        ASSIGN("glDrawTransformFeedback", drawTransformFeedback);
+        ASSIGN("glDrawTransformFeedbackStream", drawTransformFeedbackStream);
+        ASSIGN("glEndQueryIndexed", endQueryIndexed);
+        ASSIGN("glGenTransformFeedbacks", genTransformFeedbacks);
+        ASSIGN("glGetActiveSubroutineName", getActiveSubroutineName);
+        ASSIGN("glGetActiveSubroutineUniformName", getActiveSubroutineUniformName);
+        ASSIGN("glGetActiveSubroutineUniformiv", getActiveSubroutineUniformiv);
+        ASSIGN("glGetProgramStageiv", getProgramStageiv);
+        ASSIGN("glGetQueryIndexediv", getQueryIndexediv);
+        ASSIGN("glGetSubroutineIndex", getSubroutineIndex);
+        ASSIGN("glGetSubroutineUniformLocation", getSubroutineUniformLocation);
+        ASSIGN("glGetUniformSubroutineuiv", getUniformSubroutineuiv);
+        ASSIGN("glGetUniformdv", getUniformdv);
+        ASSIGN("glIsTransformFeedback", isTransformFeedback);
+        ASSIGN("glMinSampleShading", minSampleShading);
+        ASSIGN("glPatchParameterfv", patchParameterfv);
+        ASSIGN("glPatchParameteri", patchParameteri);
+        ASSIGN("glPauseTransformFeedback", pauseTransformFeedback);
+        ASSIGN("glResumeTransformFeedback", resumeTransformFeedback);
+        ASSIGN("glUniform1d", uniform1d);
+        ASSIGN("glUniform1dv", uniform1dv);
+        ASSIGN("glUniform2d", uniform2d);
+        ASSIGN("glUniform2dv", uniform2dv);
+        ASSIGN("glUniform3d", uniform3d);
+        ASSIGN("glUniform3dv", uniform3dv);
+        ASSIGN("glUniform4d", uniform4d);
+        ASSIGN("glUniform4dv", uniform4dv);
+        ASSIGN("glUniformMatrix2dv", uniformMatrix2dv);
+        ASSIGN("glUniformMatrix2x3dv", uniformMatrix2x3dv);
+        ASSIGN("glUniformMatrix2x4dv", uniformMatrix2x4dv);
+        ASSIGN("glUniformMatrix3dv", uniformMatrix3dv);
+        ASSIGN("glUniformMatrix3x2dv", uniformMatrix3x2dv);
+        ASSIGN("glUniformMatrix3x4dv", uniformMatrix3x4dv);
+        ASSIGN("glUniformMatrix4dv", uniformMatrix4dv);
+        ASSIGN("glUniformMatrix4x2dv", uniformMatrix4x2dv);
+        ASSIGN("glUniformMatrix4x3dv", uniformMatrix4x3dv);
+        ASSIGN("glUniformSubroutinesuiv", uniformSubroutinesuiv);
+    }
+
+    // 4.1
+    if (isAtLeastGL(gl::Version(4, 1)))
+    {
+        ASSIGN("glActiveShaderProgram", activeShaderProgram);
+        ASSIGN("glBindProgramPipeline", bindProgramPipeline);
+        ASSIGN("glClearDepthf", clearDepthf);
+        ASSIGN("glCreateShaderProgramv", createShaderProgramv);
+        ASSIGN("glDeleteProgramPipelines", deleteProgramPipelines);
+        ASSIGN("glDepthRangeArrayv", depthRangeArrayv);
+        ASSIGN("glDepthRangeIndexed", depthRangeIndexed);
+        ASSIGN("glDepthRangef", depthRangef);
+        ASSIGN("glGenProgramPipelines", genProgramPipelines);
+        ASSIGN("glGetDoublei_v", getDoublei_v);
+        ASSIGN("glGetFloati_v", getFloati_v);
+        ASSIGN("glGetProgramBinary", getProgramBinary);
+        ASSIGN("glGetProgramPipelineInfoLog", getProgramPipelineInfoLog);
+        ASSIGN("glGetProgramPipelineiv", getProgramPipelineiv);
+        ASSIGN("glGetShaderPrecisionFormat", getShaderPrecisionFormat);
+        ASSIGN("glGetVertexAttribLdv", getVertexAttribLdv);
+        ASSIGN("glIsProgramPipeline", isProgramPipeline);
+        ASSIGN("glProgramBinary", programBinary);
+        ASSIGN("glProgramParameteri", programParameteri);
+        ASSIGN("glProgramUniform1d", programUniform1d);
+        ASSIGN("glProgramUniform1dv", programUniform1dv);
+        ASSIGN("glProgramUniform1f", programUniform1f);
+        ASSIGN("glProgramUniform1fv", programUniform1fv);
+        ASSIGN("glProgramUniform1i", programUniform1i);
+        ASSIGN("glProgramUniform1iv", programUniform1iv);
+        ASSIGN("glProgramUniform1ui", programUniform1ui);
+        ASSIGN("glProgramUniform1uiv", programUniform1uiv);
+        ASSIGN("glProgramUniform2d", programUniform2d);
+        ASSIGN("glProgramUniform2dv", programUniform2dv);
+        ASSIGN("glProgramUniform2f", programUniform2f);
+        ASSIGN("glProgramUniform2fv", programUniform2fv);
+        ASSIGN("glProgramUniform2i", programUniform2i);
+        ASSIGN("glProgramUniform2iv", programUniform2iv);
+        ASSIGN("glProgramUniform2ui", programUniform2ui);
+        ASSIGN("glProgramUniform2uiv", programUniform2uiv);
+        ASSIGN("glProgramUniform3d", programUniform3d);
+        ASSIGN("glProgramUniform3dv", programUniform3dv);
+        ASSIGN("glProgramUniform3f", programUniform3f);
+        ASSIGN("glProgramUniform3fv", programUniform3fv);
+        ASSIGN("glProgramUniform3i", programUniform3i);
+        ASSIGN("glProgramUniform3iv", programUniform3iv);
+        ASSIGN("glProgramUniform3ui", programUniform3ui);
+        ASSIGN("glProgramUniform3uiv", programUniform3uiv);
+        ASSIGN("glProgramUniform4d", programUniform4d);
+        ASSIGN("glProgramUniform4dv", programUniform4dv);
+        ASSIGN("glProgramUniform4f", programUniform4f);
+        ASSIGN("glProgramUniform4fv", programUniform4fv);
+        ASSIGN("glProgramUniform4i", programUniform4i);
+        ASSIGN("glProgramUniform4iv", programUniform4iv);
+        ASSIGN("glProgramUniform4ui", programUniform4ui);
+        ASSIGN("glProgramUniform4uiv", programUniform4uiv);
+        ASSIGN("glProgramUniformMatrix2dv", programUniformMatrix2dv);
+        ASSIGN("glProgramUniformMatrix2fv", programUniformMatrix2fv);
+        ASSIGN("glProgramUniformMatrix2x3dv", programUniformMatrix2x3dv);
+        ASSIGN("glProgramUniformMatrix2x3fv", programUniformMatrix2x3fv);
+        ASSIGN("glProgramUniformMatrix2x4dv", programUniformMatrix2x4dv);
+        ASSIGN("glProgramUniformMatrix2x4fv", programUniformMatrix2x4fv);
+        ASSIGN("glProgramUniformMatrix3dv", programUniformMatrix3dv);
+        ASSIGN("glProgramUniformMatrix3fv", programUniformMatrix3fv);
+        ASSIGN("glProgramUniformMatrix3x2dv", programUniformMatrix3x2dv);
+        ASSIGN("glProgramUniformMatrix3x2fv", programUniformMatrix3x2fv);
+        ASSIGN("glProgramUniformMatrix3x4dv", programUniformMatrix3x4dv);
+        ASSIGN("glProgramUniformMatrix3x4fv", programUniformMatrix3x4fv);
+        ASSIGN("glProgramUniformMatrix4dv", programUniformMatrix4dv);
+        ASSIGN("glProgramUniformMatrix4fv", programUniformMatrix4fv);
+        ASSIGN("glProgramUniformMatrix4x2dv", programUniformMatrix4x2dv);
+        ASSIGN("glProgramUniformMatrix4x2fv", programUniformMatrix4x2fv);
+        ASSIGN("glProgramUniformMatrix4x3dv", programUniformMatrix4x3dv);
+        ASSIGN("glProgramUniformMatrix4x3fv", programUniformMatrix4x3fv);
+        ASSIGN("glReleaseShaderCompiler", releaseShaderCompiler);
+        ASSIGN("glScissorArrayv", scissorArrayv);
+        ASSIGN("glScissorIndexed", scissorIndexed);
+        ASSIGN("glScissorIndexedv", scissorIndexedv);
+        ASSIGN("glShaderBinary", shaderBinary);
+        ASSIGN("glUseProgramStages", useProgramStages);
+        ASSIGN("glValidateProgramPipeline", validateProgramPipeline);
+        ASSIGN("glVertexAttribL1d", vertexAttribL1d);
+        ASSIGN("glVertexAttribL1dv", vertexAttribL1dv);
+        ASSIGN("glVertexAttribL2d", vertexAttribL2d);
+        ASSIGN("glVertexAttribL2dv", vertexAttribL2dv);
+        ASSIGN("glVertexAttribL3d", vertexAttribL3d);
+        ASSIGN("glVertexAttribL3dv", vertexAttribL3dv);
+        ASSIGN("glVertexAttribL4d", vertexAttribL4d);
+        ASSIGN("glVertexAttribL4dv", vertexAttribL4dv);
+        ASSIGN("glVertexAttribLPointer", vertexAttribLPointer);
+        ASSIGN("glViewportArrayv", viewportArrayv);
+        ASSIGN("glViewportIndexedf", viewportIndexedf);
+        ASSIGN("glViewportIndexedfv", viewportIndexedfv);
+    }
+
+    // 4.2
+    if (isAtLeastGL(gl::Version(4, 2)))
+    {
+        ASSIGN("glBindImageTexture", bindImageTexture);
+        ASSIGN("glDrawArraysInstancedBaseInstance", drawArraysInstancedBaseInstance);
+        ASSIGN("glDrawElementsInstancedBaseInstance", drawElementsInstancedBaseInstance);
+        ASSIGN("glDrawElementsInstancedBaseVertexBaseInstance", drawElementsInstancedBaseVertexBaseInstance);
+        ASSIGN("glDrawTransformFeedbackInstanced", drawTransformFeedbackInstanced);
+        ASSIGN("glDrawTransformFeedbackStreamInstanced", drawTransformFeedbackStreamInstanced);
+        ASSIGN("glGetActiveAtomicCounterBufferiv", getActiveAtomicCounterBufferiv);
+        ASSIGN("glGetInternalformativ", getInternalformativ);
+        ASSIGN("glMemoryBarrier", memoryBarrier);
+        ASSIGN("glTexStorage1D", texStorage1D);
+        ASSIGN("glTexStorage2D", texStorage2D);
+        ASSIGN("glTexStorage3D", texStorage3D);
+    }
+
+    // 4.3
+    if (isAtLeastGL(gl::Version(4, 3)))
+    {
+        ASSIGN("glBindVertexBuffer", bindVertexBuffer);
+        ASSIGN("glClearBufferData", clearBufferData);
+        ASSIGN("glClearBufferSubData", clearBufferSubData);
+        ASSIGN("glCopyImageSubData", copyImageSubData);
+        ASSIGN("glDebugMessageCallback", debugMessageCallback);
+        ASSIGN("glDebugMessageControl", debugMessageControl);
+        ASSIGN("glDebugMessageInsert", debugMessageInsert);
+        ASSIGN("glDispatchCompute", dispatchCompute);
+        ASSIGN("glDispatchComputeIndirect", dispatchComputeIndirect);
+        ASSIGN("glFramebufferParameteri", framebufferParameteri);
+        ASSIGN("glGetDebugMessageLog", getDebugMessageLog);
+        ASSIGN("glGetFramebufferParameteriv", getFramebufferParameteriv);
+        ASSIGN("glGetInternalformati64v", getInternalformati64v);
+        ASSIGN("glGetPointerv", getPointerv);
+        ASSIGN("glGetObjectLabel", getObjectLabel);
+        ASSIGN("glGetObjectPtrLabel", getObjectPtrLabel);
+        ASSIGN("glGetProgramInterfaceiv", getProgramInterfaceiv);
+        ASSIGN("glGetProgramResourceIndex", getProgramResourceIndex);
+        ASSIGN("glGetProgramResourceLocation", getProgramResourceLocation);
+        ASSIGN("glGetProgramResourceLocationIndex", getProgramResourceLocationIndex);
+        ASSIGN("glGetProgramResourceName", getProgramResourceName);
+        ASSIGN("glGetProgramResourceiv", getProgramResourceiv);
+        ASSIGN("glInvalidateBufferData", invalidateBufferData);
+        ASSIGN("glInvalidateBufferSubData", invalidateBufferSubData);
+        ASSIGN("glInvalidateFramebuffer", invalidateFramebuffer);
+        ASSIGN("glInvalidateSubFramebuffer", invalidateSubFramebuffer);
+        ASSIGN("glInvalidateTexImage", invalidateTexImage);
+        ASSIGN("glInvalidateTexSubImage", invalidateTexSubImage);
+        ASSIGN("glMultiDrawArraysIndirect", multiDrawArraysIndirect);
+        ASSIGN("glMultiDrawElementsIndirect", multiDrawElementsIndirect);
+        ASSIGN("glObjectLabel", objectLabel);
+        ASSIGN("glObjectPtrLabel", objectPtrLabel);
+        ASSIGN("glPopDebugGroup", popDebugGroup);
+        ASSIGN("glPushDebugGroup", pushDebugGroup);
+        ASSIGN("glShaderStorageBlockBinding", shaderStorageBlockBinding);
+        ASSIGN("glTexBufferRange", texBufferRange);
+        ASSIGN("glTexStorage2DMultisample", texStorage2DMultisample);
+        ASSIGN("glTexStorage3DMultisample", texStorage3DMultisample);
+        ASSIGN("glTextureView", textureView);
+        ASSIGN("glVertexAttribBinding", vertexAttribBinding);
+        ASSIGN("glVertexAttribFormat", vertexAttribFormat);
+        ASSIGN("glVertexAttribIFormat", vertexAttribIFormat);
+        ASSIGN("glVertexAttribLFormat", vertexAttribLFormat);
+        ASSIGN("glVertexBindingDivisor", vertexBindingDivisor);
+    }
+
+    // 4.4
+    if (isAtLeastGL(gl::Version(4, 4)))
+    {
+        ASSIGN("glBindBuffersBase", bindBuffersBase);
+        ASSIGN("glBindBuffersRange", bindBuffersRange);
+        ASSIGN("glBindImageTextures", bindImageTextures);
+        ASSIGN("glBindSamplers", bindSamplers);
+        ASSIGN("glBindTextures", bindTextures);
+        ASSIGN("glBindVertexBuffers", bindVertexBuffers);
+        ASSIGN("glBufferStorage", bufferStorage);
+        ASSIGN("glClearTexImage", clearTexImage);
+        ASSIGN("glClearTexSubImage", clearTexSubImage);
+    }
+
+    // 4.5
+    if (isAtLeastGL(gl::Version(4, 5)))
+    {
+        ASSIGN("glBindTextureUnit", bindTextureUnit);
+        ASSIGN("glBlitNamedFramebuffer", blitNamedFramebuffer);
+        ASSIGN("glCheckNamedFramebufferStatus", checkNamedFramebufferStatus);
+        ASSIGN("glClearNamedBufferData", clearNamedBufferData);
+        ASSIGN("glClearNamedBufferSubData", clearNamedBufferSubData);
+        ASSIGN("glClearNamedFramebufferfi", clearNamedFramebufferfi);
+        ASSIGN("glClearNamedFramebufferfv", clearNamedFramebufferfv);
+        ASSIGN("glClearNamedFramebufferiv", clearNamedFramebufferiv);
+        ASSIGN("glClearNamedFramebufferuiv", clearNamedFramebufferuiv);
+        ASSIGN("glClipControl", clipControl);
+        ASSIGN("glCompressedTextureSubImage1D", compressedTextureSubImage1D);
+        ASSIGN("glCompressedTextureSubImage2D", compressedTextureSubImage2D);
+        ASSIGN("glCompressedTextureSubImage3D", compressedTextureSubImage3D);
+        ASSIGN("glCopyNamedBufferSubData", copyNamedBufferSubData);
+        ASSIGN("glCopyTextureSubImage1D", copyTextureSubImage1D);
+        ASSIGN("glCopyTextureSubImage2D", copyTextureSubImage2D);
+        ASSIGN("glCopyTextureSubImage3D", copyTextureSubImage3D);
+        ASSIGN("glCreateBuffers", createBuffers);
+        ASSIGN("glCreateFramebuffers", createFramebuffers);
+        ASSIGN("glCreateProgramPipelines", createProgramPipelines);
+        ASSIGN("glCreateQueries", createQueries);
+        ASSIGN("glCreateRenderbuffers", createRenderbuffers);
+        ASSIGN("glCreateSamplers", createSamplers);
+        ASSIGN("glCreateTextures", createTextures);
+        ASSIGN("glCreateTransformFeedbacks", createTransformFeedbacks);
+        ASSIGN("glCreateVertexArrays", createVertexArrays);
+        ASSIGN("glDisableVertexArrayAttrib", disableVertexArrayAttrib);
+        ASSIGN("glEnableVertexArrayAttrib", enableVertexArrayAttrib);
+        ASSIGN("glFlushMappedNamedBufferRange", flushMappedNamedBufferRange);
+        ASSIGN("glGenerateTextureMipmap", generateTextureMipmap);
+        ASSIGN("glGetCompressedTextureImage", getCompressedTextureImage);
+        ASSIGN("glGetCompressedTextureSubImage", getCompressedTextureSubImage);
+        ASSIGN("glGetGraphicsResetStatus", getGraphicsResetStatus);
+        ASSIGN("glGetNamedBufferParameteri64v", getNamedBufferParameteri64v);
+        ASSIGN("glGetNamedBufferParameteriv", getNamedBufferParameteriv);
+        ASSIGN("glGetNamedBufferPointerv", getNamedBufferPointerv);
+        ASSIGN("glGetNamedBufferSubData", getNamedBufferSubData);
+        ASSIGN("glGetNamedFramebufferAttachmentParameteriv", getNamedFramebufferAttachmentParameteriv);
+        ASSIGN("glGetNamedFramebufferParameteriv", getNamedFramebufferParameteriv);
+        ASSIGN("glGetNamedRenderbufferParameteriv", getNamedRenderbufferParameteriv);
+        ASSIGN("glGetQueryBufferObjecti64v", getQueryBufferObjecti64v);
+        ASSIGN("glGetQueryBufferObjectiv", getQueryBufferObjectiv);
+        ASSIGN("glGetQueryBufferObjectui64v", getQueryBufferObjectui64v);
+        ASSIGN("glGetQueryBufferObjectuiv", getQueryBufferObjectuiv);
+        ASSIGN("glGetTextureImage", getTextureImage);
+        ASSIGN("glGetTextureLevelParameterfv", getTextureLevelParameterfv);
+        ASSIGN("glGetTextureLevelParameteriv", getTextureLevelParameteriv);
+        ASSIGN("glGetTextureParameterIiv", getTextureParameterIiv);
+        ASSIGN("glGetTextureParameterIuiv", getTextureParameterIuiv);
+        ASSIGN("glGetTextureParameterfv", getTextureParameterfv);
+        ASSIGN("glGetTextureParameteriv", getTextureParameteriv);
+        ASSIGN("glGetTextureSubImage", getTextureSubImage);
+        ASSIGN("glGetTransformFeedbacki64_v", getTransformFeedbacki64_v);
+        ASSIGN("glGetTransformFeedbacki_v", getTransformFeedbacki_v);
+        ASSIGN("glGetTransformFeedbackiv", getTransformFeedbackiv);
+        ASSIGN("glGetVertexArrayIndexed64iv", getVertexArrayIndexed64iv);
+        ASSIGN("glGetVertexArrayIndexediv", getVertexArrayIndexediv);
+        ASSIGN("glGetVertexArrayiv", getVertexArrayiv);
+        ASSIGN("glGetnCompressedTexImage", getnCompressedTexImage);
+        ASSIGN("glGetnTexImage", getnTexImage);
+        ASSIGN("glGetnUniformdv", getnUniformdv);
+        ASSIGN("glGetnUniformfv", getnUniformfv);
+        ASSIGN("glGetnUniformiv", getnUniformiv);
+        ASSIGN("glGetnUniformuiv", getnUniformuiv);
+        ASSIGN("glInvalidateNamedFramebufferData", invalidateNamedFramebufferData);
+        ASSIGN("glInvalidateNamedFramebufferSubData", invalidateNamedFramebufferSubData);
+        ASSIGN("glMapNamedBuffer", mapNamedBuffer);
+        ASSIGN("glMapNamedBufferRange", mapNamedBufferRange);
+        ASSIGN("glMemoryBarrierByRegion", memoryBarrierByRegion);
+        ASSIGN("glNamedBufferData", namedBufferData);
+        ASSIGN("glNamedBufferStorage", namedBufferStorage);
+        ASSIGN("glNamedBufferSubData", namedBufferSubData);
+        ASSIGN("glNamedFramebufferDrawBuffer", namedFramebufferDrawBuffer);
+        ASSIGN("glNamedFramebufferDrawBuffers", namedFramebufferDrawBuffers);
+        ASSIGN("glNamedFramebufferParameteri", namedFramebufferParameteri);
+        ASSIGN("glNamedFramebufferReadBuffer", namedFramebufferReadBuffer);
+        ASSIGN("glNamedFramebufferRenderbuffer", namedFramebufferRenderbuffer);
+        ASSIGN("glNamedFramebufferTexture", namedFramebufferTexture);
+        ASSIGN("glNamedFramebufferTextureLayer", namedFramebufferTextureLayer);
+        ASSIGN("glNamedRenderbufferStorage", namedRenderbufferStorage);
+        ASSIGN("glNamedRenderbufferStorageMultisample", namedRenderbufferStorageMultisample);
+        ASSIGN("glReadnPixels", readnPixels);
+        ASSIGN("glTextureBarrier", textureBarrier);
+        ASSIGN("glTextureBuffer", textureBuffer);
+        ASSIGN("glTextureBufferRange", textureBufferRange);
+        ASSIGN("glTextureParameterIiv", textureParameterIiv);
+        ASSIGN("glTextureParameterIuiv", textureParameterIuiv);
+        ASSIGN("glTextureParameterf", textureParameterf);
+        ASSIGN("glTextureParameterfv", textureParameterfv);
+        ASSIGN("glTextureParameteri", textureParameteri);
+        ASSIGN("glTextureParameteriv", textureParameteriv);
+        ASSIGN("glTextureStorage1D", textureStorage1D);
+        ASSIGN("glTextureStorage2D", textureStorage2D);
+        ASSIGN("glTextureStorage2DMultisample", textureStorage2DMultisample);
+        ASSIGN("glTextureStorage3D", textureStorage3D);
+        ASSIGN("glTextureStorage3DMultisample", textureStorage3DMultisample);
+        ASSIGN("glTextureSubImage1D", textureSubImage1D);
+        ASSIGN("glTextureSubImage2D", textureSubImage2D);
+        ASSIGN("glTextureSubImage3D", textureSubImage3D);
+        ASSIGN("glTransformFeedbackBufferBase", transformFeedbackBufferBase);
+        ASSIGN("glTransformFeedbackBufferRange", transformFeedbackBufferRange);
+        ASSIGN("glUnmapNamedBuffer", unmapNamedBuffer);
+        ASSIGN("glVertexArrayAttribBinding", vertexArrayAttribBinding);
+        ASSIGN("glVertexArrayAttribFormat", vertexArrayAttribFormat);
+        ASSIGN("glVertexArrayAttribIFormat", vertexArrayAttribIFormat);
+        ASSIGN("glVertexArrayAttribLFormat", vertexArrayAttribLFormat);
+        ASSIGN("glVertexArrayBindingDivisor", vertexArrayBindingDivisor);
+        ASSIGN("glVertexArrayElementBuffer", vertexArrayElementBuffer);
+        ASSIGN("glVertexArrayVertexBuffer", vertexArrayVertexBuffer);
+        ASSIGN("glVertexArrayVertexBuffers", vertexArrayVertexBuffers);
+    }
+
+    // clang-format on
+}
+
+void FunctionsGL::initializeProcsGLES()
+{
+    // No profiles in GLES
+    profile = 0;
+
+    // clang-format off
+
+    // GL_NV_path_rendering
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glMatrixLoadfEXT", matrixLoadEXT);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glGenPathsNV", genPathsNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glDeletePathsNV", delPathsNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glPathCommandsNV", pathCommandsNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glIsPathNV", isPathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glPathParameterfNV", setPathParameterfNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glPathParameteriNV", setPathParameteriNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glGetPathParameterfvNV", getPathParameterfNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glGetPathParameterivNV", getPathParameteriNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glPathStencilFuncNV", pathStencilFuncNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilFillPathNV", stencilFillPathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilStrokePathNV", stencilStrokePathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glCoverFillPathNV", coverFillPathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glCoverStrokePathNV", coverStrokePathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilThenCoverFillPathNV", stencilThenCoverFillPathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilThenCoverStrokePathNV", stencilThenCoverStrokePathNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glCoverFillPathInstancedNV", coverFillPathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glCoverStrokePathInstancedNV", coverStrokePathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilFillPathInstancedNV", stencilFillPathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilStrokePathInstancedNV", stencilStrokePathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilThenCoverFillPathInstancedNV", stencilThenCoverFillPathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glStencilThenCoverStrokePathInstancedNV", stencilThenCoverStrokePathInstancedNV);
+    ASSIGN_WITH_EXT("GL_NV_path_rendering", "glProgramPathFragmentInputGenNV", programPathFragmentInputGenNV);
+
+    // GL_OES_texture_3D
+    ASSIGN_WITH_EXT("GL_OES_texture_3D", "glTexImage3DOES", texImage3D);
+    ASSIGN_WITH_EXT("GL_OES_texture_3D", "glTexSubImage3DOES", texSubImage3D);
+    ASSIGN_WITH_EXT("GL_OES_texture_3D", "glCopyTexSubImage3DOES", copyTexSubImage3D);
+
+    // GL_NV_framebuffer_mixed_samples
+    ASSIGN_WITH_EXT("GL_NV_framebuffer_mixed_samples", "glCoverageModulationNV", coverageModulationNV);
+
+    // GL_NV_fence
+    ASSIGN_WITH_EXT("GL_NV_fence", "glDeleteFencesNV", deleteFencesNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glGenFencesNV", genFencesNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glIsFenceNV", isFenceNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glTestFenceNV", testFenceNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glGetFenceivNV", getFenceivNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glFinishFenceNV", finishFenceNV);
+    ASSIGN_WITH_EXT("GL_NV_fence", "glSetFenceNV", setFenceNV);
+
+    // GL_EXT_texture_storage
+    ASSIGN_WITH_EXT("GL_EXT_texture_storage", "glTexStorage2DEXT", texStorage2D);
+    ASSIGN_WITH_EXT("GL_EXT_texture_storage GL_OES_texture3D", "glTexStorage3DEXT", texStorage3D);
+
+    // GL_OES_vertex_array_object
+    ASSIGN_WITH_EXT("GL_OES_vertex_array_object", "glBindVertexArray", bindVertexArray);
+    ASSIGN_WITH_EXT("GL_OES_vertex_array_object", "glDeleteVertexArrays", deleteVertexArrays);
+    ASSIGN_WITH_EXT("GL_OES_vertex_array_object", "glGenVertexArrays", genVertexArrays);
+    ASSIGN_WITH_EXT("GL_OES_vertex_array_object", "glIsVertexArray", isVertexArray);
+
+    // GL_EXT_map_buffer_range
+    ASSIGN_WITH_EXT("GL_EXT_map_buffer_range", "glMapBufferRangeEXT", mapBufferRange);
+    ASSIGN_WITH_EXT("GL_EXT_map_buffer_range", "glFlushMappedBufferRangeEXT", flushMappedBufferRange);
+    ASSIGN_WITH_EXT("GL_EXT_map_buffer_range", "glUnmapBufferOES", unmapBuffer);
+
+    // GL_OES_mapbuffer
+    ASSIGN_WITH_EXT("GL_OES_mapbuffer", "glMapBufferOES", mapBuffer);
+    ASSIGN_WITH_EXT("GL_OES_mapbuffer", "glUnmapBufferOES", unmapBuffer);
+
+    // GL_KHR_debug
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glDebugMessageControlKHR", debugMessageControl);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glDebugMessageInsertKHR", debugMessageInsert);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glDebugMessageCallbackKHR", debugMessageCallback);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glGetDebugMessageLogKHR", getDebugMessageLog);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glGetPointervKHR", getPointerv);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glPushDebugGroupKHR", pushDebugGroup);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glPopDebugGroupKHR", popDebugGroup);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glObjectLabelKHR", objectLabel);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glGetObjectLabelKHR", getObjectLabel);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glObjectPtrLabelKHR", objectPtrLabel);
+    ASSIGN_WITH_EXT("GL_KHR_debug", "glGetObjectPtrLabelKHR", getObjectPtrLabel);
+
+    // GL_EXT_draw_instanced
+    ASSIGN_WITH_EXT("GL_EXT_draw_instanced", "glVertexAttribDivisorEXT", vertexAttribDivisor);
+    ASSIGN_WITH_EXT("GL_EXT_draw_instanced", "glDrawArraysInstancedEXT", drawArraysInstanced);
+    ASSIGN_WITH_EXT("GL_EXT_draw_instanced", "glDrawElementsInstancedEXT", drawElementsInstanced);
+
+    // GL_EXT_occlusion_query_boolean
+    ASSIGN_WITH_EXT("GL_EXT_occlusion_query_boolean", "glGenQueriesEXT", genQueries);
+    ASSIGN_WITH_EXT("GL_EXT_occlusion_query_boolean", "glDeleteQueriesEXT", deleteQueries);
+    ASSIGN_WITH_EXT("GL_EXT_occlusion_query_boolean", "glIsQueryEXT", isQuery);
+    ASSIGN_WITH_EXT("GL_EXT_occlusion_query_boolean", "glBeginQueryEXT", beginQuery);
+    ASSIGN_WITH_EXT("GL_EXT_occlusion_query_boolean", "glEndQueryEXT", endQuery);
+    ASSIGN_WITH_EXT("GL_EXT_occlusion_query_boolean", "glGetQueryivEXT", getQueryiv);
+    ASSIGN_WITH_EXT("GL_EXT_occlusion_query_boolean", "glGetQueryObjectuivEXT", getQueryObjectuiv);
+
+    // GL_EXT_disjoint_timer_query
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glGenQueriesEXT", genQueries);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glDeleteQueriesEXT", deleteQueries);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glIsQueryEXT", isQuery);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glBeginQueryEXT", beginQuery);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glEndQueryEXT", endQuery);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glQueryCounterEXT", queryCounter);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glGetQueryivEXT", getQueryiv);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glGetQueryObjectivEXT", getQueryObjectiv);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glGetQueryObjectuivEXT", getQueryObjectuiv);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glGetQueryObjecti64vEXT", getQueryObjecti64v);
+    ASSIGN_WITH_EXT("GL_EXT_disjoint_timer_query", "glGetQueryObjectui64vEXT", getQueryObjectui64v);
+
+    // GL_OES_EGL_image
+    ASSIGN_WITH_EXT("GL_OES_EGL_image", "glEGLImageTargetRenderbufferStorageOES", eglImageTargetRenderbufferStorageOES);
+    ASSIGN_WITH_EXT("GL_OES_EGL_image", "glEGLImageTargetTexture2DOES", eglImageTargetTexture2DOES);
+
+    // GL_OES_get_program_binary
+    ASSIGN_WITH_EXT("GL_OES_get_program_binary", "glGetProgramBinaryOES", getProgramBinary);
+    ASSIGN_WITH_EXT("GL_OES_get_program_binary", "glProgramBinaryOES", programBinary);
+
+    // GL_EXT_robustness
+    ASSIGN_WITH_EXT("GL_EXT_robustness", "glGetGraphicsResetStatusEXT", getGraphicsResetStatus);
+
+    // GL_KHR_robustness
+    ASSIGN_WITH_EXT("GL_KHR_robustness", "glGetGraphicsResetStatusKHR", getGraphicsResetStatus);
+
+    // GL_EXT_discard_framebuffer
+    ASSIGN_WITH_EXT("GL_EXT_discard_framebuffer", "glDiscardFramebufferEXT", discardFramebuffer);
+
+    // 2.0
+    if (isAtLeastGLES(gl::Version(2, 0)))
+    {
+        ASSIGN("glActiveTexture", activeTexture);
+        ASSIGN("glAttachShader", attachShader);
+        ASSIGN("glBindAttribLocation", bindAttribLocation);
+        ASSIGN("glBindBuffer", bindBuffer);
+        ASSIGN("glBindFramebuffer", bindFramebuffer);
+        ASSIGN("glBindRenderbuffer", bindRenderbuffer);
+        ASSIGN("glBindTexture", bindTexture);
+        ASSIGN("glBlendColor", blendColor);
+        ASSIGN("glBlendEquation", blendEquation);
+        ASSIGN("glBlendEquationSeparate", blendEquationSeparate);
+        ASSIGN("glBlendFunc", blendFunc);
+        ASSIGN("glBlendFuncSeparate", blendFuncSeparate);
+        ASSIGN("glBufferData", bufferData);
+        ASSIGN("glBufferSubData", bufferSubData);
+        ASSIGN("glCheckFramebufferStatus", checkFramebufferStatus);
+        ASSIGN("glClear", clear);
+        ASSIGN("glClearColor", clearColor);
+        ASSIGN("glClearDepthf", clearDepthf);
+        ASSIGN("glClearStencil", clearStencil);
+        ASSIGN("glColorMask", colorMask);
+        ASSIGN("glCompileShader", compileShader);
+        ASSIGN("glCompressedTexImage2D", compressedTexImage2D);
+        ASSIGN("glCompressedTexSubImage2D", compressedTexSubImage2D);
+        ASSIGN("glCopyTexImage2D", copyTexImage2D);
+        ASSIGN("glCopyTexSubImage2D", copyTexSubImage2D);
+        ASSIGN("glCreateProgram", createProgram);
+        ASSIGN("glCreateShader", createShader);
+        ASSIGN("glCullFace", cullFace);
+        ASSIGN("glDeleteBuffers", deleteBuffers);
+        ASSIGN("glDeleteFramebuffers", deleteFramebuffers);
+        ASSIGN("glDeleteProgram", deleteProgram);
+        ASSIGN("glDeleteRenderbuffers", deleteRenderbuffers);
+        ASSIGN("glDeleteShader", deleteShader);
+        ASSIGN("glDeleteTextures", deleteTextures);
+        ASSIGN("glDepthFunc", depthFunc);
+        ASSIGN("glDepthMask", depthMask);
+        ASSIGN("glDepthRangef", depthRangef);
+        ASSIGN("glDetachShader", detachShader);
+        ASSIGN("glDisable", disable);
+        ASSIGN("glDisableVertexAttribArray", disableVertexAttribArray);
+        ASSIGN("glDrawArrays", drawArrays);
+        ASSIGN("glDrawElements", drawElements);
+        ASSIGN("glEnable", enable);
+        ASSIGN("glEnableVertexAttribArray", enableVertexAttribArray);
+        ASSIGN("glFinish", finish);
+        ASSIGN("glFlush", flush);
+        ASSIGN("glFramebufferRenderbuffer", framebufferRenderbuffer);
+        ASSIGN("glFramebufferTexture2D", framebufferTexture2D);
+        ASSIGN("glFrontFace", frontFace);
+        ASSIGN("glGenBuffers", genBuffers);
+        ASSIGN("glGenerateMipmap", generateMipmap);
+        ASSIGN("glGenFramebuffers", genFramebuffers);
+        ASSIGN("glGenRenderbuffers", genRenderbuffers);
+        ASSIGN("glGenTextures", genTextures);
+        ASSIGN("glGetActiveAttrib", getActiveAttrib);
+        ASSIGN("glGetActiveUniform", getActiveUniform);
+        ASSIGN("glGetAttachedShaders", getAttachedShaders);
+        ASSIGN("glGetAttribLocation", getAttribLocation);
+        ASSIGN("glGetBooleanv", getBooleanv);
+        ASSIGN("glGetBufferParameteriv", getBufferParameteriv);
+        ASSIGN("glGetError", getError);
+        ASSIGN("glGetFloatv", getFloatv);
+        ASSIGN("glGetFramebufferAttachmentParameteriv", getFramebufferAttachmentParameteriv);
+        ASSIGN("glGetIntegerv", getIntegerv);
+        ASSIGN("glGetProgramiv", getProgramiv);
+        ASSIGN("glGetProgramInfoLog", getProgramInfoLog);
+        ASSIGN("glGetRenderbufferParameteriv", getRenderbufferParameteriv);
+        ASSIGN("glGetShaderiv", getShaderiv);
+        ASSIGN("glGetShaderInfoLog", getShaderInfoLog);
+        ASSIGN("glGetShaderPrecisionFormat", getShaderPrecisionFormat);
+        ASSIGN("glGetShaderSource", getShaderSource);
+        ASSIGN("glGetString", getString);
+        ASSIGN("glGetTexParameterfv", getTexParameterfv);
+        ASSIGN("glGetTexParameteriv", getTexParameteriv);
+        ASSIGN("glGetUniformfv", getUniformfv);
+        ASSIGN("glGetUniformiv", getUniformiv);
+        ASSIGN("glGetUniformLocation", getUniformLocation);
+        ASSIGN("glGetVertexAttribfv", getVertexAttribfv);
+        ASSIGN("glGetVertexAttribiv", getVertexAttribiv);
+        ASSIGN("glGetVertexAttribPointerv", getVertexAttribPointerv);
+        ASSIGN("glHint", hint);
+        ASSIGN("glIsBuffer", isBuffer);
+        ASSIGN("glIsEnabled", isEnabled);
+        ASSIGN("glIsFramebuffer", isFramebuffer);
+        ASSIGN("glIsProgram", isProgram);
+        ASSIGN("glIsRenderbuffer", isRenderbuffer);
+        ASSIGN("glIsShader", isShader);
+        ASSIGN("glIsTexture", isTexture);
+        ASSIGN("glLineWidth", lineWidth);
+        ASSIGN("glLinkProgram", linkProgram);
+        ASSIGN("glPixelStorei", pixelStorei);
+        ASSIGN("glPolygonOffset", polygonOffset);
+        ASSIGN("glReadPixels", readPixels);
+        ASSIGN("glReleaseShaderCompiler", releaseShaderCompiler);
+        ASSIGN("glRenderbufferStorage", renderbufferStorage);
+        ASSIGN("glSampleCoverage", sampleCoverage);
+        ASSIGN("glScissor", scissor);
+        ASSIGN("glShaderBinary", shaderBinary);
+        ASSIGN("glShaderSource", shaderSource);
+        ASSIGN("glStencilFunc", stencilFunc);
+        ASSIGN("glStencilFuncSeparate", stencilFuncSeparate);
+        ASSIGN("glStencilMask", stencilMask);
+        ASSIGN("glStencilMaskSeparate", stencilMaskSeparate);
+        ASSIGN("glStencilOp", stencilOp);
+        ASSIGN("glStencilOpSeparate", stencilOpSeparate);
+        ASSIGN("glTexImage2D", texImage2D);
+        ASSIGN("glTexParameterf", texParameterf);
+        ASSIGN("glTexParameterfv", texParameterfv);
+        ASSIGN("glTexParameteri", texParameteri);
+        ASSIGN("glTexParameteriv", texParameteriv);
+        ASSIGN("glTexSubImage2D", texSubImage2D);
+        ASSIGN("glUniform1f", uniform1f);
+        ASSIGN("glUniform1fv", uniform1fv);
+        ASSIGN("glUniform1i", uniform1i);
+        ASSIGN("glUniform1iv", uniform1iv);
+        ASSIGN("glUniform2f", uniform2f);
+        ASSIGN("glUniform2fv", uniform2fv);
+        ASSIGN("glUniform2i", uniform2i);
+        ASSIGN("glUniform2iv", uniform2iv);
+        ASSIGN("glUniform3f", uniform3f);
+        ASSIGN("glUniform3fv", uniform3fv);
+        ASSIGN("glUniform3i", uniform3i);
+        ASSIGN("glUniform3iv", uniform3iv);
+        ASSIGN("glUniform4f", uniform4f);
+        ASSIGN("glUniform4fv", uniform4fv);
+        ASSIGN("glUniform4i", uniform4i);
+        ASSIGN("glUniform4iv", uniform4iv);
+        ASSIGN("glUniformMatrix2fv", uniformMatrix2fv);
+        ASSIGN("glUniformMatrix3fv", uniformMatrix3fv);
+        ASSIGN("glUniformMatrix4fv", uniformMatrix4fv);
+        ASSIGN("glUseProgram", useProgram);
+        ASSIGN("glValidateProgram", validateProgram);
+        ASSIGN("glVertexAttrib1f", vertexAttrib1f);
+        ASSIGN("glVertexAttrib1fv", vertexAttrib1fv);
+        ASSIGN("glVertexAttrib2f", vertexAttrib2f);
+        ASSIGN("glVertexAttrib2fv", vertexAttrib2fv);
+        ASSIGN("glVertexAttrib3f", vertexAttrib3f);
+        ASSIGN("glVertexAttrib3fv", vertexAttrib3fv);
+        ASSIGN("glVertexAttrib4f", vertexAttrib4f);
+        ASSIGN("glVertexAttrib4fv", vertexAttrib4fv);
+        ASSIGN("glVertexAttribPointer", vertexAttribPointer);
+        ASSIGN("glViewport", viewport);
+    }
+
+    // 3.0
+    if (isAtLeastGLES(gl::Version(3, 0)))
+    {
+        ASSIGN("glReadBuffer", readBuffer);
+        ASSIGN("glDrawRangeElements", drawRangeElements);
+        ASSIGN("glTexImage3D", texImage3D);
+        ASSIGN("glTexSubImage3D", texSubImage3D);
+        ASSIGN("glCopyTexSubImage3D", copyTexSubImage3D);
+        ASSIGN("glCompressedTexImage3D", compressedTexImage3D);
+        ASSIGN("glCompressedTexSubImage3D", compressedTexSubImage3D);
+        ASSIGN("glGenQueries", genQueries);
+        ASSIGN("glDeleteQueries", deleteQueries);
+        ASSIGN("glIsQuery", isQuery);
+        ASSIGN("glBeginQuery", beginQuery);
+        ASSIGN("glEndQuery", endQuery);
+        ASSIGN("glGetQueryiv", getQueryiv);
+        ASSIGN("glGetQueryObjectuiv", getQueryObjectuiv);
+        ASSIGN("glUnmapBuffer", unmapBuffer);
+        ASSIGN("glGetBufferPointerv", getBufferPointerv);
+        ASSIGN("glDrawBuffers", drawBuffers);
+        ASSIGN("glUniformMatrix2x3fv", uniformMatrix2x3fv);
+        ASSIGN("glUniformMatrix3x2fv", uniformMatrix3x2fv);
+        ASSIGN("glUniformMatrix2x4fv", uniformMatrix2x4fv);
+        ASSIGN("glUniformMatrix4x2fv", uniformMatrix4x2fv);
+        ASSIGN("glUniformMatrix3x4fv", uniformMatrix3x4fv);
+        ASSIGN("glUniformMatrix4x3fv", uniformMatrix4x3fv);
+        ASSIGN("glBlitFramebuffer", blitFramebuffer);
+        ASSIGN("glRenderbufferStorageMultisample", renderbufferStorageMultisample);
+        ASSIGN("glFramebufferTextureLayer", framebufferTextureLayer);
+        ASSIGN("glMapBufferRange", mapBufferRange);
+        ASSIGN("glFlushMappedBufferRange", flushMappedBufferRange);
+        ASSIGN("glBindVertexArray", bindVertexArray);
+        ASSIGN("glDeleteVertexArrays", deleteVertexArrays);
+        ASSIGN("glGenVertexArrays", genVertexArrays);
+        ASSIGN("glIsVertexArray", isVertexArray);
+        ASSIGN("glGetIntegeri_v", getIntegeri_v);
+        ASSIGN("glBeginTransformFeedback", beginTransformFeedback);
+        ASSIGN("glEndTransformFeedback", endTransformFeedback);
+        ASSIGN("glBindBufferRange", bindBufferRange);
+        ASSIGN("glBindBufferBase", bindBufferBase);
+        ASSIGN("glTransformFeedbackVaryings", transformFeedbackVaryings);
+        ASSIGN("glGetTransformFeedbackVarying", getTransformFeedbackVarying);
+        ASSIGN("glVertexAttribIPointer", vertexAttribIPointer);
+        ASSIGN("glGetVertexAttribIiv", getVertexAttribIiv);
+        ASSIGN("glGetVertexAttribIuiv", getVertexAttribIuiv);
+        ASSIGN("glVertexAttribI4i", vertexAttribI4i);
+        ASSIGN("glVertexAttribI4ui", vertexAttribI4ui);
+        ASSIGN("glVertexAttribI4iv", vertexAttribI4iv);
+        ASSIGN("glVertexAttribI4uiv", vertexAttribI4uiv);
+        ASSIGN("glGetUniformuiv", getUniformuiv);
+        ASSIGN("glGetFragDataLocation", getFragDataLocation);
+        ASSIGN("glUniform1ui", uniform1ui);
+        ASSIGN("glUniform2ui", uniform2ui);
+        ASSIGN("glUniform3ui", uniform3ui);
+        ASSIGN("glUniform4ui", uniform4ui);
+        ASSIGN("glUniform1uiv", uniform1uiv);
+        ASSIGN("glUniform2uiv", uniform2uiv);
+        ASSIGN("glUniform3uiv", uniform3uiv);
+        ASSIGN("glUniform4uiv", uniform4uiv);
+        ASSIGN("glClearBufferiv", clearBufferiv);
+        ASSIGN("glClearBufferuiv", clearBufferuiv);
+        ASSIGN("glClearBufferfv", clearBufferfv);
+        ASSIGN("glClearBufferfi", clearBufferfi);
+        ASSIGN("glGetStringi", getStringi);
+        ASSIGN("glCopyBufferSubData", copyBufferSubData);
+        ASSIGN("glGetUniformIndices", getUniformIndices);
+        ASSIGN("glGetActiveUniformsiv", getActiveUniformsiv);
+        ASSIGN("glGetUniformBlockIndex", getUniformBlockIndex);
+        ASSIGN("glGetActiveUniformBlockiv", getActiveUniformBlockiv);
+        ASSIGN("glGetActiveUniformBlockName", getActiveUniformBlockName);
+        ASSIGN("glUniformBlockBinding", uniformBlockBinding);
+        ASSIGN("glDrawArraysInstanced", drawArraysInstanced);
+        ASSIGN("glDrawElementsInstanced", drawElementsInstanced);
+        ASSIGN("glFenceSync", fenceSync);
+        ASSIGN("glIsSync", isSync);
+        ASSIGN("glDeleteSync", deleteSync);
+        ASSIGN("glClientWaitSync", clientWaitSync);
+        ASSIGN("glWaitSync", waitSync);
+        ASSIGN("glGetInteger64v", getInteger64v);
+        ASSIGN("glGetSynciv", getSynciv);
+        ASSIGN("glGetInteger64i_v", getInteger64i_v);
+        ASSIGN("glGetBufferParameteri64v", getBufferParameteri64v);
+        ASSIGN("glGenSamplers", genSamplers);
+        ASSIGN("glDeleteSamplers", deleteSamplers);
+        ASSIGN("glIsSampler", isSampler);
+        ASSIGN("glBindSampler", bindSampler);
+        ASSIGN("glSamplerParameteri", samplerParameteri);
+        ASSIGN("glSamplerParameteriv", samplerParameteriv);
+        ASSIGN("glSamplerParameterf", samplerParameterf);
+        ASSIGN("glSamplerParameterfv", samplerParameterfv);
+        ASSIGN("glGetSamplerParameteriv", getSamplerParameteriv);
+        ASSIGN("glGetSamplerParameterfv", getSamplerParameterfv);
+        ASSIGN("glVertexAttribDivisor", vertexAttribDivisor);
+        ASSIGN("glBindTransformFeedback", bindTransformFeedback);
+        ASSIGN("glDeleteTransformFeedbacks", deleteTransformFeedbacks);
+        ASSIGN("glGenTransformFeedbacks", genTransformFeedbacks);
+        ASSIGN("glIsTransformFeedback", isTransformFeedback);
+        ASSIGN("glPauseTransformFeedback", pauseTransformFeedback);
+        ASSIGN("glResumeTransformFeedback", resumeTransformFeedback);
+        ASSIGN("glGetProgramBinary", getProgramBinary);
+        ASSIGN("glProgramBinary", programBinary);
+        ASSIGN("glProgramParameteri", programParameteri);
+        ASSIGN("glInvalidateFramebuffer", invalidateFramebuffer);
+        ASSIGN("glInvalidateSubFramebuffer", invalidateSubFramebuffer);
+        ASSIGN("glTexStorage2D", texStorage2D);
+        ASSIGN("glTexStorage3D", texStorage3D);
+        ASSIGN("glGetInternalformativ", getInternalformativ);
+    }
+
+    // 3.1
+    if (isAtLeastGLES(gl::Version(3, 1)))
+    {
+        ASSIGN("glDispatchCompute", dispatchCompute);
+        ASSIGN("glDispatchComputeIndirect", dispatchComputeIndirect);
+        ASSIGN("glDrawArraysIndirect", drawArraysIndirect);
+        ASSIGN("glDrawElementsIndirect", drawElementsIndirect);
+        ASSIGN("glFramebufferParameteri", framebufferParameteri);
+        ASSIGN("glGetFramebufferParameteriv", getFramebufferParameteriv);
+        ASSIGN("glGetProgramInterfaceiv", getProgramInterfaceiv);
+        ASSIGN("glGetProgramResourceIndex", getProgramResourceIndex);
+        ASSIGN("glGetProgramResourceName", getProgramResourceName);
+        ASSIGN("glGetProgramResourceiv", getProgramResourceiv);
+        ASSIGN("glGetProgramResourceLocation", getProgramResourceLocation);
+        ASSIGN("glUseProgramStages", useProgramStages);
+        ASSIGN("glActiveShaderProgram", activeShaderProgram);
+        ASSIGN("glCreateShaderProgramv", createShaderProgramv);
+        ASSIGN("glBindProgramPipeline", bindProgramPipeline);
+        ASSIGN("glDeleteProgramPipelines", deleteProgramPipelines);
+        ASSIGN("glGenProgramPipelines", genProgramPipelines);
+        ASSIGN("glIsProgramPipeline", isProgramPipeline);
+        ASSIGN("glGetProgramPipelineiv", getProgramPipelineiv);
+        ASSIGN("glProgramUniform1i", programUniform1i);
+        ASSIGN("glProgramUniform2i", programUniform2i);
+        ASSIGN("glProgramUniform3i", programUniform3i);
+        ASSIGN("glProgramUniform4i", programUniform4i);
+        ASSIGN("glProgramUniform1ui", programUniform1ui);
+        ASSIGN("glProgramUniform2ui", programUniform2ui);
+        ASSIGN("glProgramUniform3ui", programUniform3ui);
+        ASSIGN("glProgramUniform4ui", programUniform4ui);
+        ASSIGN("glProgramUniform1f", programUniform1f);
+        ASSIGN("glProgramUniform2f", programUniform2f);
+        ASSIGN("glProgramUniform3f", programUniform3f);
+        ASSIGN("glProgramUniform4f", programUniform4f);
+        ASSIGN("glProgramUniform1iv", programUniform1iv);
+        ASSIGN("glProgramUniform2iv", programUniform2iv);
+        ASSIGN("glProgramUniform3iv", programUniform3iv);
+        ASSIGN("glProgramUniform4iv", programUniform4iv);
+        ASSIGN("glProgramUniform1uiv", programUniform1uiv);
+        ASSIGN("glProgramUniform2uiv", programUniform2uiv);
+        ASSIGN("glProgramUniform3uiv", programUniform3uiv);
+        ASSIGN("glProgramUniform4uiv", programUniform4uiv);
+        ASSIGN("glProgramUniform1fv", programUniform1fv);
+        ASSIGN("glProgramUniform2fv", programUniform2fv);
+        ASSIGN("glProgramUniform3fv", programUniform3fv);
+        ASSIGN("glProgramUniform4fv", programUniform4fv);
+        ASSIGN("glProgramUniformMatrix2fv", programUniformMatrix2fv);
+        ASSIGN("glProgramUniformMatrix3fv", programUniformMatrix3fv);
+        ASSIGN("glProgramUniformMatrix4fv", programUniformMatrix4fv);
+        ASSIGN("glProgramUniformMatrix2x3fv", programUniformMatrix2x3fv);
+        ASSIGN("glProgramUniformMatrix3x2fv", programUniformMatrix3x2fv);
+        ASSIGN("glProgramUniformMatrix2x4fv", programUniformMatrix2x4fv);
+        ASSIGN("glProgramUniformMatrix4x2fv", programUniformMatrix4x2fv);
+        ASSIGN("glProgramUniformMatrix3x4fv", programUniformMatrix3x4fv);
+        ASSIGN("glProgramUniformMatrix4x3fv", programUniformMatrix4x3fv);
+        ASSIGN("glValidateProgramPipeline", validateProgramPipeline);
+        ASSIGN("glGetProgramPipelineInfoLog", getProgramPipelineInfoLog);
+        ASSIGN("glBindImageTexture", bindImageTexture);
+        ASSIGN("glGetBooleani_v", getBooleani_v);
+        ASSIGN("glMemoryBarrier", memoryBarrier);
+        ASSIGN("glMemoryBarrierByRegion", memoryBarrierByRegion);
+        ASSIGN("glTexStorage2DMultisample", texStorage2DMultisample);
+        ASSIGN("glGetMultisamplefv", getMultisamplefv);
+        ASSIGN("glSampleMaski", sampleMaski);
+        ASSIGN("glGetTexLevelParameteriv", getTexLevelParameteriv);
+        ASSIGN("glGetTexLevelParameterfv", getTexLevelParameterfv);
+        ASSIGN("glBindVertexBuffer", bindVertexBuffer);
+        ASSIGN("glVertexAttribFormat", vertexAttribFormat);
+        ASSIGN("glVertexAttribIFormat", vertexAttribIFormat);
+        ASSIGN("glVertexAttribBinding", vertexAttribBinding);
+        ASSIGN("glVertexBindingDivisor", vertexBindingDivisor);
+    }
+
+    // 3.2
+    if (isAtLeastGLES(gl::Version(3, 2)))
+    {
+        ASSIGN("glBlendBarrier", blendBarrier);
+        ASSIGN("glCopyImageSubData", copyImageSubData);
+        ASSIGN("glDebugMessageControl", debugMessageControl);
+        ASSIGN("glDebugMessageInsert", debugMessageInsert);
+        ASSIGN("glDebugMessageCallback", debugMessageCallback);
+        ASSIGN("glGetDebugMessageLog", getDebugMessageLog);
+        ASSIGN("glPushDebugGroup", pushDebugGroup);
+        ASSIGN("glPopDebugGroup", popDebugGroup);
+        ASSIGN("glObjectLabel", objectLabel);
+        ASSIGN("glGetObjectLabel", getObjectLabel);
+        ASSIGN("glObjectPtrLabel", objectPtrLabel);
+        ASSIGN("glGetObjectPtrLabel", getObjectPtrLabel);
+        ASSIGN("glGetPointerv", getPointerv);
+        ASSIGN("glEnablei", enablei);
+        ASSIGN("glDisablei", disablei);
+        ASSIGN("glBlendEquationi", blendEquationi);
+        ASSIGN("glBlendEquationSeparatei", blendEquationSeparatei);
+        ASSIGN("glBlendFunci", blendFunci);
+        ASSIGN("glBlendFuncSeparatei", blendFuncSeparatei);
+        ASSIGN("glColorMaski", colorMaski);
+        ASSIGN("glIsEnabledi", isEnabledi);
+        ASSIGN("glDrawElementsBaseVertex", drawElementsBaseVertex);
+        ASSIGN("glDrawRangeElementsBaseVertex", drawRangeElementsBaseVertex);
+        ASSIGN("glDrawElementsInstancedBaseVertex", drawElementsInstancedBaseVertex);
+        ASSIGN("glFramebufferTexture", framebufferTexture);
+        ASSIGN("glPrimitiveBoundingBox", primitiveBoundingBox);
+        ASSIGN("glGetGraphicsResetStatus", getGraphicsResetStatus);
+        ASSIGN("glReadnPixels", readnPixels);
+        ASSIGN("glGetnUniformfv", getnUniformfv);
+        ASSIGN("glGetnUniformiv", getnUniformiv);
+        ASSIGN("glGetnUniformuiv", getnUniformuiv);
+        ASSIGN("glMinSampleShading", minSampleShading);
+        ASSIGN("glPatchParameteri", patchParameteri);
+        ASSIGN("glTexParameterIiv", texParameterIiv);
+        ASSIGN("glTexParameterIuiv", texParameterIuiv);
+        ASSIGN("glGetTexParameterIiv", getTexParameterIiv);
+        ASSIGN("glGetTexParameterIuiv", getTexParameterIuiv);
+        ASSIGN("glSamplerParameterIiv", samplerParameterIiv);
+        ASSIGN("glSamplerParameterIuiv", samplerParameterIuiv);
+        ASSIGN("glGetSamplerParameterIiv", getSamplerParameterIiv);
+        ASSIGN("glGetSamplerParameterIuiv", getSamplerParameterIuiv);
+        ASSIGN("glTexBuffer", texBuffer);
+        ASSIGN("glTexBufferRange", texBufferRange);
+        ASSIGN("glTexStorage3DMultisample", texStorage3DMultisample);
+    }
+
+    // clang-format on
+}
+
+bool FunctionsGL::isAtLeastGL(const gl::Version &glVersion) const
+{
+    return standard == STANDARD_GL_DESKTOP && version >= glVersion;
+}
+
+bool FunctionsGL::isAtMostGL(const gl::Version &glVersion) const
+{
+    return standard == STANDARD_GL_DESKTOP && glVersion >= version;
+}
+
+bool FunctionsGL::isAtLeastGLES(const gl::Version &glesVersion) const
+{
+    return standard == STANDARD_GL_ES && version >= glesVersion;
+}
+
+bool FunctionsGL::isAtMostGLES(const gl::Version &glesVersion) const
+{
+    return standard == STANDARD_GL_ES && glesVersion >= version;
+}
+
+bool FunctionsGL::hasExtension(const std::string &ext) const
+{
+    return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
+}
+
+bool FunctionsGL::hasGLExtension(const std::string &ext) const
+{
+    return standard == STANDARD_GL_DESKTOP && hasExtension(ext);
+}
+
+bool FunctionsGL::hasGLESExtension(const std::string &ext) const
+{
+    return standard == STANDARD_GL_ES && hasExtension(ext);
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.h
new file mode 100644
index 0000000..a629a9c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.h
@@ -0,0 +1,794 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsGL.h: Defines the FuntionsGL class to contain loaded GL functions
+
+#ifndef LIBANGLE_RENDERER_GL_FUNCTIONSGL_H_
+#define LIBANGLE_RENDERER_GL_FUNCTIONSGL_H_
+
+#include "common/debug.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/renderer/gl/functionsgl_enums.h"
+#include "libANGLE/renderer/gl/functionsgl_typedefs.h"
+
+namespace rx
+{
+
+enum StandardGL
+{
+    STANDARD_GL_DESKTOP,
+    STANDARD_GL_ES,
+};
+
+class FunctionsGL
+{
+  public:
+    FunctionsGL();
+    virtual ~FunctionsGL();
+
+    void initialize();
+
+    // Version information
+    gl::Version version;
+    StandardGL standard;
+    GLint profile;
+    bool isAtLeastGL(const gl::Version &glVersion) const;
+    bool isAtMostGL(const gl::Version &glVersion) const;
+    bool isAtLeastGLES(const gl::Version &glesVersion) const;
+    bool isAtMostGLES(const gl::Version &glesVersion) const;
+
+    // Extensions
+    std::vector<std::string> extensions;
+    bool hasExtension(const std::string &ext) const;
+    bool hasGLExtension(const std::string &ext) const;
+    bool hasGLESExtension(const std::string &ext) const;
+
+    // Entry Points
+    // 1.0
+    PFNGLBLENDFUNCPROC blendFunc;
+    PFNGLCLEARPROC clear;
+    PFNGLCLEARCOLORPROC clearColor;
+    PFNGLCLEARDEPTHPROC clearDepth;
+    PFNGLCLEARSTENCILPROC clearStencil;
+    PFNGLCOLORMASKPROC colorMask;
+    PFNGLCULLFACEPROC cullFace;
+    PFNGLDEPTHFUNCPROC depthFunc;
+    PFNGLDEPTHMASKPROC depthMask;
+    PFNGLDEPTHRANGEPROC depthRange;
+    PFNGLDISABLEPROC disable;
+    PFNGLDRAWBUFFERPROC drawBuffer;
+    PFNGLENABLEPROC enable;
+    PFNGLFINISHPROC finish;
+    PFNGLFLUSHPROC flush;
+    PFNGLFRONTFACEPROC frontFace;
+    PFNGLGETBOOLEANVPROC getBooleanv;
+    PFNGLGETDOUBLEVPROC getDoublev;
+    PFNGLGETERRORPROC getError;
+    PFNGLGETFLOATVPROC getFloatv;
+    PFNGLGETINTEGERVPROC getIntegerv;
+    PFNGLGETSTRINGPROC getString;
+    PFNGLGETTEXIMAGEPROC getTexImage;
+    PFNGLGETTEXLEVELPARAMETERFVPROC getTexLevelParameterfv;
+    PFNGLGETTEXLEVELPARAMETERIVPROC getTexLevelParameteriv;
+    PFNGLGETTEXPARAMETERFVPROC getTexParameterfv;
+    PFNGLGETTEXPARAMETERIVPROC getTexParameteriv;
+    PFNGLHINTPROC hint;
+    PFNGLISENABLEDPROC isEnabled;
+    PFNGLLINEWIDTHPROC lineWidth;
+    PFNGLLOGICOPPROC logicOp;
+    PFNGLPIXELSTOREFPROC pixelStoref;
+    PFNGLPIXELSTOREIPROC pixelStorei;
+    PFNGLPOINTSIZEPROC pointSize;
+    PFNGLPOLYGONMODEPROC polygonMode;
+    PFNGLREADBUFFERPROC readBuffer;
+    PFNGLREADPIXELSPROC readPixels;
+    PFNGLSCISSORPROC scissor;
+    PFNGLSTENCILFUNCPROC stencilFunc;
+    PFNGLSTENCILMASKPROC stencilMask;
+    PFNGLSTENCILOPPROC stencilOp;
+    PFNGLTEXIMAGE1DPROC texImage1D;
+    PFNGLTEXIMAGE2DPROC texImage2D;
+    PFNGLTEXPARAMETERFPROC texParameterf;
+    PFNGLTEXPARAMETERFVPROC texParameterfv;
+    PFNGLTEXPARAMETERIPROC texParameteri;
+    PFNGLTEXPARAMETERIVPROC texParameteriv;
+    PFNGLVIEWPORTPROC viewport;
+
+    // 1.1
+    PFNGLBINDTEXTUREPROC bindTexture;
+    PFNGLCOPYTEXIMAGE1DPROC copyTexImage1D;
+    PFNGLCOPYTEXIMAGE2DPROC copyTexImage2D;
+    PFNGLCOPYTEXSUBIMAGE1DPROC copyTexSubImage1D;
+    PFNGLCOPYTEXSUBIMAGE2DPROC copyTexSubImage2D;
+    PFNGLDELETETEXTURESPROC deleteTextures;
+    PFNGLDRAWARRAYSPROC drawArrays;
+    PFNGLDRAWELEMENTSPROC drawElements;
+    PFNGLGENTEXTURESPROC genTextures;
+    PFNGLISTEXTUREPROC isTexture;
+    PFNGLPOLYGONOFFSETPROC polygonOffset;
+    PFNGLTEXSUBIMAGE1DPROC texSubImage1D;
+    PFNGLTEXSUBIMAGE2DPROC texSubImage2D;
+
+    // 1.2
+    PFNGLBLENDCOLORPROC blendColor;
+    PFNGLBLENDEQUATIONPROC blendEquation;
+    PFNGLCOPYTEXSUBIMAGE3DPROC copyTexSubImage3D;
+    PFNGLDRAWRANGEELEMENTSPROC drawRangeElements;
+    PFNGLTEXIMAGE3DPROC texImage3D;
+    PFNGLTEXSUBIMAGE3DPROC texSubImage3D;
+
+    // 1.2 Extensions
+    PFNGLDELETEFENCESNVPROC deleteFencesNV;
+    PFNGLGENFENCESNVPROC genFencesNV;
+    PFNGLISFENCENVPROC isFenceNV;
+    PFNGLTESTFENCENVPROC testFenceNV;
+    PFNGLGETFENCEIVNVPROC getFenceivNV;
+    PFNGLFINISHFENCENVPROC finishFenceNV;
+    PFNGLSETFENCENVPROC setFenceNV;
+
+    // 1.3
+    PFNGLACTIVETEXTUREPROC activeTexture;
+    PFNGLCOMPRESSEDTEXIMAGE1DPROC compressedTexImage1D;
+    PFNGLCOMPRESSEDTEXIMAGE2DPROC compressedTexImage2D;
+    PFNGLCOMPRESSEDTEXIMAGE3DPROC compressedTexImage3D;
+    PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC compressedTexSubImage1D;
+    PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC compressedTexSubImage2D;
+    PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC compressedTexSubImage3D;
+    PFNGLGETCOMPRESSEDTEXIMAGEPROC getCompressedTexImage;
+    PFNGLSAMPLECOVERAGEPROC sampleCoverage;
+
+    // 1.4
+    PFNGLBLENDFUNCSEPARATEPROC blendFuncSeparate;
+    PFNGLMULTIDRAWARRAYSPROC multiDrawArrays;
+    PFNGLMULTIDRAWELEMENTSPROC multiDrawElements;
+    PFNGLPOINTPARAMETERFPROC pointParameterf;
+    PFNGLPOINTPARAMETERFVPROC pointParameterfv;
+    PFNGLPOINTPARAMETERIPROC pointParameteri;
+    PFNGLPOINTPARAMETERIVPROC pointParameteriv;
+
+    // 1.5
+    PFNGLBEGINQUERYPROC beginQuery;
+    PFNGLBINDBUFFERPROC bindBuffer;
+    PFNGLBUFFERDATAPROC bufferData;
+    PFNGLBUFFERSUBDATAPROC bufferSubData;
+    PFNGLDELETEBUFFERSPROC deleteBuffers;
+    PFNGLDELETEQUERIESPROC deleteQueries;
+    PFNGLENDQUERYPROC endQuery;
+    PFNGLGENBUFFERSPROC genBuffers;
+    PFNGLGENQUERIESPROC genQueries;
+    PFNGLGETBUFFERPARAMETERIVPROC getBufferParameteriv;
+    PFNGLGETBUFFERPOINTERVPROC getBufferPointerv;
+    PFNGLGETBUFFERSUBDATAPROC getBufferSubData;
+    PFNGLGETQUERYOBJECTIVPROC getQueryObjectiv;
+    PFNGLGETQUERYOBJECTUIVPROC getQueryObjectuiv;
+    PFNGLGETQUERYIVPROC getQueryiv;
+    PFNGLISBUFFERPROC isBuffer;
+    PFNGLISQUERYPROC isQuery;
+    PFNGLMAPBUFFERPROC mapBuffer;
+    PFNGLUNMAPBUFFERPROC unmapBuffer;
+
+    // 2.0
+    PFNGLATTACHSHADERPROC attachShader;
+    PFNGLBINDATTRIBLOCATIONPROC bindAttribLocation;
+    PFNGLBLENDEQUATIONSEPARATEPROC blendEquationSeparate;
+    PFNGLCOMPILESHADERPROC compileShader;
+    PFNGLCREATEPROGRAMPROC createProgram;
+    PFNGLCREATESHADERPROC createShader;
+    PFNGLDELETEPROGRAMPROC deleteProgram;
+    PFNGLDELETESHADERPROC deleteShader;
+    PFNGLDETACHSHADERPROC detachShader;
+    PFNGLDISABLEVERTEXATTRIBARRAYPROC disableVertexAttribArray;
+    PFNGLDRAWBUFFERSPROC drawBuffers;
+    PFNGLENABLEVERTEXATTRIBARRAYPROC enableVertexAttribArray;
+    PFNGLGETACTIVEATTRIBPROC getActiveAttrib;
+    PFNGLGETACTIVEUNIFORMPROC getActiveUniform;
+    PFNGLGETATTACHEDSHADERSPROC getAttachedShaders;
+    PFNGLGETATTRIBLOCATIONPROC getAttribLocation;
+    PFNGLGETPROGRAMINFOLOGPROC getProgramInfoLog;
+    PFNGLGETPROGRAMIVPROC getProgramiv;
+    PFNGLGETSHADERINFOLOGPROC getShaderInfoLog;
+    PFNGLGETSHADERSOURCEPROC getShaderSource;
+    PFNGLGETSHADERIVPROC getShaderiv;
+    PFNGLGETUNIFORMLOCATIONPROC getUniformLocation;
+    PFNGLGETUNIFORMFVPROC getUniformfv;
+    PFNGLGETUNIFORMIVPROC getUniformiv;
+    PFNGLGETVERTEXATTRIBPOINTERVPROC getVertexAttribPointerv;
+    PFNGLGETVERTEXATTRIBDVPROC getVertexAttribdv;
+    PFNGLGETVERTEXATTRIBFVPROC getVertexAttribfv;
+    PFNGLGETVERTEXATTRIBIVPROC getVertexAttribiv;
+    PFNGLISPROGRAMPROC isProgram;
+    PFNGLISSHADERPROC isShader;
+    PFNGLLINKPROGRAMPROC linkProgram;
+    PFNGLSHADERSOURCEPROC shaderSource;
+    PFNGLSTENCILFUNCSEPARATEPROC stencilFuncSeparate;
+    PFNGLSTENCILMASKSEPARATEPROC stencilMaskSeparate;
+    PFNGLSTENCILOPSEPARATEPROC stencilOpSeparate;
+    PFNGLUNIFORM1FPROC uniform1f;
+    PFNGLUNIFORM1FVPROC uniform1fv;
+    PFNGLUNIFORM1IPROC uniform1i;
+    PFNGLUNIFORM1IVPROC uniform1iv;
+    PFNGLUNIFORM2FPROC uniform2f;
+    PFNGLUNIFORM2FVPROC uniform2fv;
+    PFNGLUNIFORM2IPROC uniform2i;
+    PFNGLUNIFORM2IVPROC uniform2iv;
+    PFNGLUNIFORM3FPROC uniform3f;
+    PFNGLUNIFORM3FVPROC uniform3fv;
+    PFNGLUNIFORM3IPROC uniform3i;
+    PFNGLUNIFORM3IVPROC uniform3iv;
+    PFNGLUNIFORM4FPROC uniform4f;
+    PFNGLUNIFORM4FVPROC uniform4fv;
+    PFNGLUNIFORM4IPROC uniform4i;
+    PFNGLUNIFORM4IVPROC uniform4iv;
+    PFNGLUNIFORMMATRIX2FVPROC uniformMatrix2fv;
+    PFNGLUNIFORMMATRIX3FVPROC uniformMatrix3fv;
+    PFNGLUNIFORMMATRIX4FVPROC uniformMatrix4fv;
+    PFNGLUSEPROGRAMPROC useProgram;
+    PFNGLVALIDATEPROGRAMPROC validateProgram;
+    PFNGLVERTEXATTRIB1DPROC vertexAttrib1d;
+    PFNGLVERTEXATTRIB1DVPROC vertexAttrib1dv;
+    PFNGLVERTEXATTRIB1FPROC vertexAttrib1f;
+    PFNGLVERTEXATTRIB1FVPROC vertexAttrib1fv;
+    PFNGLVERTEXATTRIB1SPROC vertexAttrib1s;
+    PFNGLVERTEXATTRIB1SVPROC vertexAttrib1sv;
+    PFNGLVERTEXATTRIB2DPROC vertexAttrib2d;
+    PFNGLVERTEXATTRIB2DVPROC vertexAttrib2dv;
+    PFNGLVERTEXATTRIB2FPROC vertexAttrib2f;
+    PFNGLVERTEXATTRIB2FVPROC vertexAttrib2fv;
+    PFNGLVERTEXATTRIB2SPROC vertexAttrib2s;
+    PFNGLVERTEXATTRIB2SVPROC vertexAttrib2sv;
+    PFNGLVERTEXATTRIB3DPROC vertexAttrib3d;
+    PFNGLVERTEXATTRIB3DVPROC vertexAttrib3dv;
+    PFNGLVERTEXATTRIB3FPROC vertexAttrib3f;
+    PFNGLVERTEXATTRIB3FVPROC vertexAttrib3fv;
+    PFNGLVERTEXATTRIB3SPROC vertexAttrib3s;
+    PFNGLVERTEXATTRIB3SVPROC vertexAttrib3sv;
+    PFNGLVERTEXATTRIB4NBVPROC vertexAttrib4Nbv;
+    PFNGLVERTEXATTRIB4NIVPROC vertexAttrib4Niv;
+    PFNGLVERTEXATTRIB4NSVPROC vertexAttrib4Nsv;
+    PFNGLVERTEXATTRIB4NUBPROC vertexAttrib4Nub;
+    PFNGLVERTEXATTRIB4NUBVPROC vertexAttrib4Nubv;
+    PFNGLVERTEXATTRIB4NUIVPROC vertexAttrib4Nuiv;
+    PFNGLVERTEXATTRIB4NUSVPROC vertexAttrib4Nusv;
+    PFNGLVERTEXATTRIB4BVPROC vertexAttrib4bv;
+    PFNGLVERTEXATTRIB4DPROC vertexAttrib4d;
+    PFNGLVERTEXATTRIB4DVPROC vertexAttrib4dv;
+    PFNGLVERTEXATTRIB4FPROC vertexAttrib4f;
+    PFNGLVERTEXATTRIB4FVPROC vertexAttrib4fv;
+    PFNGLVERTEXATTRIB4IVPROC vertexAttrib4iv;
+    PFNGLVERTEXATTRIB4SPROC vertexAttrib4s;
+    PFNGLVERTEXATTRIB4SVPROC vertexAttrib4sv;
+    PFNGLVERTEXATTRIB4UBVPROC vertexAttrib4ubv;
+    PFNGLVERTEXATTRIB4UIVPROC vertexAttrib4uiv;
+    PFNGLVERTEXATTRIB4USVPROC vertexAttrib4usv;
+    PFNGLVERTEXATTRIBPOINTERPROC vertexAttribPointer;
+
+    // 2.1
+    PFNGLUNIFORMMATRIX2X3FVPROC uniformMatrix2x3fv;
+    PFNGLUNIFORMMATRIX2X4FVPROC uniformMatrix2x4fv;
+    PFNGLUNIFORMMATRIX3X2FVPROC uniformMatrix3x2fv;
+    PFNGLUNIFORMMATRIX3X4FVPROC uniformMatrix3x4fv;
+    PFNGLUNIFORMMATRIX4X2FVPROC uniformMatrix4x2fv;
+    PFNGLUNIFORMMATRIX4X3FVPROC uniformMatrix4x3fv;
+
+    // 3.0
+    PFNGLBEGINCONDITIONALRENDERPROC beginConditionalRender;
+    PFNGLBEGINTRANSFORMFEEDBACKPROC beginTransformFeedback;
+    PFNGLBINDBUFFERBASEPROC bindBufferBase;
+    PFNGLBINDBUFFERRANGEPROC bindBufferRange;
+    PFNGLBINDFRAGDATALOCATIONPROC bindFragDataLocation;
+    PFNGLBINDFRAMEBUFFERPROC bindFramebuffer;
+    PFNGLBINDRENDERBUFFERPROC bindRenderbuffer;
+    PFNGLBINDVERTEXARRAYPROC bindVertexArray;
+    PFNGLBLITFRAMEBUFFERPROC blitFramebuffer;
+    PFNGLCHECKFRAMEBUFFERSTATUSPROC checkFramebufferStatus;
+    PFNGLCLAMPCOLORPROC clampColor;
+    PFNGLCLEARBUFFERFIPROC clearBufferfi;
+    PFNGLCLEARBUFFERFVPROC clearBufferfv;
+    PFNGLCLEARBUFFERIVPROC clearBufferiv;
+    PFNGLCLEARBUFFERUIVPROC clearBufferuiv;
+    PFNGLCOLORMASKIPROC colorMaski;
+    PFNGLDELETEFRAMEBUFFERSPROC deleteFramebuffers;
+    PFNGLDELETERENDERBUFFERSPROC deleteRenderbuffers;
+    PFNGLDELETEVERTEXARRAYSPROC deleteVertexArrays;
+    PFNGLDISABLEIPROC disablei;
+    PFNGLENABLEIPROC enablei;
+    PFNGLENDCONDITIONALRENDERPROC endConditionalRender;
+    PFNGLENDTRANSFORMFEEDBACKPROC endTransformFeedback;
+    PFNGLFLUSHMAPPEDBUFFERRANGEPROC flushMappedBufferRange;
+    PFNGLFRAMEBUFFERRENDERBUFFERPROC framebufferRenderbuffer;
+    PFNGLFRAMEBUFFERTEXTURE1DPROC framebufferTexture1D;
+    PFNGLFRAMEBUFFERTEXTURE2DPROC framebufferTexture2D;
+    PFNGLFRAMEBUFFERTEXTURE3DPROC framebufferTexture3D;
+    PFNGLFRAMEBUFFERTEXTURELAYERPROC framebufferTextureLayer;
+    PFNGLGENFRAMEBUFFERSPROC genFramebuffers;
+    PFNGLGENRENDERBUFFERSPROC genRenderbuffers;
+    PFNGLGENVERTEXARRAYSPROC genVertexArrays;
+    PFNGLGENERATEMIPMAPPROC generateMipmap;
+    PFNGLGETBOOLEANI_VPROC getBooleani_v;
+    PFNGLGETFRAGDATALOCATIONPROC getFragDataLocation;
+    PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC getFramebufferAttachmentParameteriv;
+    PFNGLGETINTEGERI_VPROC getIntegeri_v;
+    PFNGLGETRENDERBUFFERPARAMETERIVPROC getRenderbufferParameteriv;
+    PFNGLGETSTRINGIPROC getStringi;
+    PFNGLGETTEXPARAMETERIIVPROC getTexParameterIiv;
+    PFNGLGETTEXPARAMETERIUIVPROC getTexParameterIuiv;
+    PFNGLGETTRANSFORMFEEDBACKVARYINGPROC getTransformFeedbackVarying;
+    PFNGLGETUNIFORMUIVPROC getUniformuiv;
+    PFNGLGETVERTEXATTRIBIIVPROC getVertexAttribIiv;
+    PFNGLGETVERTEXATTRIBIUIVPROC getVertexAttribIuiv;
+    PFNGLISENABLEDIPROC isEnabledi;
+    PFNGLISFRAMEBUFFERPROC isFramebuffer;
+    PFNGLISRENDERBUFFERPROC isRenderbuffer;
+    PFNGLISVERTEXARRAYPROC isVertexArray;
+    PFNGLMAPBUFFERRANGEPROC mapBufferRange;
+    PFNGLRENDERBUFFERSTORAGEPROC renderbufferStorage;
+    PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC renderbufferStorageMultisample;
+    PFNGLTEXPARAMETERIIVPROC texParameterIiv;
+    PFNGLTEXPARAMETERIUIVPROC texParameterIuiv;
+    PFNGLTRANSFORMFEEDBACKVARYINGSPROC transformFeedbackVaryings;
+    PFNGLUNIFORM1UIPROC uniform1ui;
+    PFNGLUNIFORM1UIVPROC uniform1uiv;
+    PFNGLUNIFORM2UIPROC uniform2ui;
+    PFNGLUNIFORM2UIVPROC uniform2uiv;
+    PFNGLUNIFORM3UIPROC uniform3ui;
+    PFNGLUNIFORM3UIVPROC uniform3uiv;
+    PFNGLUNIFORM4UIPROC uniform4ui;
+    PFNGLUNIFORM4UIVPROC uniform4uiv;
+    PFNGLVERTEXATTRIBI1IPROC vertexAttribI1i;
+    PFNGLVERTEXATTRIBI1IVPROC vertexAttribI1iv;
+    PFNGLVERTEXATTRIBI1UIPROC vertexAttribI1ui;
+    PFNGLVERTEXATTRIBI1UIVPROC vertexAttribI1uiv;
+    PFNGLVERTEXATTRIBI2IPROC vertexAttribI2i;
+    PFNGLVERTEXATTRIBI2IVPROC vertexAttribI2iv;
+    PFNGLVERTEXATTRIBI2UIPROC vertexAttribI2ui;
+    PFNGLVERTEXATTRIBI2UIVPROC vertexAttribI2uiv;
+    PFNGLVERTEXATTRIBI3IPROC vertexAttribI3i;
+    PFNGLVERTEXATTRIBI3IVPROC vertexAttribI3iv;
+    PFNGLVERTEXATTRIBI3UIPROC vertexAttribI3ui;
+    PFNGLVERTEXATTRIBI3UIVPROC vertexAttribI3uiv;
+    PFNGLVERTEXATTRIBI4BVPROC vertexAttribI4bv;
+    PFNGLVERTEXATTRIBI4IPROC vertexAttribI4i;
+    PFNGLVERTEXATTRIBI4IVPROC vertexAttribI4iv;
+    PFNGLVERTEXATTRIBI4SVPROC vertexAttribI4sv;
+    PFNGLVERTEXATTRIBI4UBVPROC vertexAttribI4ubv;
+    PFNGLVERTEXATTRIBI4UIPROC vertexAttribI4ui;
+    PFNGLVERTEXATTRIBI4UIVPROC vertexAttribI4uiv;
+    PFNGLVERTEXATTRIBI4USVPROC vertexAttribI4usv;
+    PFNGLVERTEXATTRIBIPOINTERPROC vertexAttribIPointer;
+
+    // 3.1
+    PFNGLCOPYBUFFERSUBDATAPROC copyBufferSubData;
+    PFNGLDRAWARRAYSINSTANCEDPROC drawArraysInstanced;
+    PFNGLDRAWELEMENTSINSTANCEDPROC drawElementsInstanced;
+    PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC getActiveUniformBlockName;
+    PFNGLGETACTIVEUNIFORMBLOCKIVPROC getActiveUniformBlockiv;
+    PFNGLGETACTIVEUNIFORMNAMEPROC getActiveUniformName;
+    PFNGLGETACTIVEUNIFORMSIVPROC getActiveUniformsiv;
+    PFNGLGETUNIFORMBLOCKINDEXPROC getUniformBlockIndex;
+    PFNGLGETUNIFORMINDICESPROC getUniformIndices;
+    PFNGLPRIMITIVERESTARTINDEXPROC primitiveRestartIndex;
+    PFNGLTEXBUFFERPROC texBuffer;
+    PFNGLUNIFORMBLOCKBINDINGPROC uniformBlockBinding;
+
+    // 3.2
+    PFNGLCLIENTWAITSYNCPROC clientWaitSync;
+    PFNGLDELETESYNCPROC deleteSync;
+    PFNGLDRAWELEMENTSBASEVERTEXPROC drawElementsBaseVertex;
+    PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC drawElementsInstancedBaseVertex;
+    PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC drawRangeElementsBaseVertex;
+    PFNGLFENCESYNCPROC fenceSync;
+    PFNGLFRAMEBUFFERTEXTUREPROC framebufferTexture;
+    PFNGLGETBUFFERPARAMETERI64VPROC getBufferParameteri64v;
+    PFNGLGETINTEGER64I_VPROC getInteger64i_v;
+    PFNGLGETINTEGER64VPROC getInteger64v;
+    PFNGLGETMULTISAMPLEFVPROC getMultisamplefv;
+    PFNGLGETSYNCIVPROC getSynciv;
+    PFNGLISSYNCPROC isSync;
+    PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC multiDrawElementsBaseVertex;
+    PFNGLPROVOKINGVERTEXPROC provokingVertex;
+    PFNGLSAMPLEMASKIPROC sampleMaski;
+    PFNGLTEXIMAGE2DMULTISAMPLEPROC texImage2DMultisample;
+    PFNGLTEXIMAGE3DMULTISAMPLEPROC texImage3DMultisample;
+    PFNGLWAITSYNCPROC waitSync;
+
+    // NV_path_rendering (originally written against 3.2 compatibility profile)
+    PFNGLMATRIXLOADFEXTPROC matrixLoadEXT;
+    PFNGLGENPATHSNVPROC genPathsNV;
+    PFNGLDELETEPATHSNVPROC delPathsNV;
+    PFNGLPATHCOMMANDSNVPROC pathCommandsNV;
+    PFNGLISPATHNVPROC isPathNV;
+    PFNGLPATHPARAMETERFNVPROC setPathParameterfNV;
+    PFNGLPATHPARAMETERINVPROC setPathParameteriNV;
+    PFNGLGETPATHPARAMETERFVNVPROC getPathParameterfNV;
+    PFNGLGETPATHPARAMETERIVNVPROC getPathParameteriNV;
+    PFNGLPATHSTENCILFUNCNVPROC pathStencilFuncNV;
+    PFNGLSTENCILFILLPATHNVPROC stencilFillPathNV;
+    PFNGLSTENCILSTROKEPATHNVPROC stencilStrokePathNV;
+    PFNGLCOVERFILLPATHNVPROC coverFillPathNV;
+    PFNGLCOVERSTROKEPATHNVPROC coverStrokePathNV;
+    PFNGLSTENCILTHENCOVERFILLPATHNVPROC stencilThenCoverFillPathNV;
+    PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC stencilThenCoverStrokePathNV;
+    PFNGLCOVERFILLPATHINSTANCEDNVPROC coverFillPathInstancedNV;
+    PFNGLCOVERSTROKEPATHINSTANCEDNVPROC coverStrokePathInstancedNV;
+    PFNGLSTENCILFILLPATHINSTANCEDNVPROC stencilFillPathInstancedNV;
+    PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC stencilStrokePathInstancedNV;
+    PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC stencilThenCoverFillPathInstancedNV;
+    PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC stencilThenCoverStrokePathInstancedNV;
+    PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC programPathFragmentInputGenNV;
+
+    // 3.3
+    PFNGLBINDFRAGDATALOCATIONINDEXEDPROC bindFragDataLocationIndexed;
+    PFNGLBINDSAMPLERPROC bindSampler;
+    PFNGLDELETESAMPLERSPROC deleteSamplers;
+    PFNGLGENSAMPLERSPROC genSamplers;
+    PFNGLGETFRAGDATAINDEXPROC getFragDataIndex;
+    PFNGLGETQUERYOBJECTI64VPROC getQueryObjecti64v;
+    PFNGLGETQUERYOBJECTUI64VPROC getQueryObjectui64v;
+    PFNGLGETSAMPLERPARAMETERIIVPROC getSamplerParameterIiv;
+    PFNGLGETSAMPLERPARAMETERIUIVPROC getSamplerParameterIuiv;
+    PFNGLGETSAMPLERPARAMETERFVPROC getSamplerParameterfv;
+    PFNGLGETSAMPLERPARAMETERIVPROC getSamplerParameteriv;
+    PFNGLISSAMPLERPROC isSampler;
+    PFNGLQUERYCOUNTERPROC queryCounter;
+    PFNGLSAMPLERPARAMETERIIVPROC samplerParameterIiv;
+    PFNGLSAMPLERPARAMETERIUIVPROC samplerParameterIuiv;
+    PFNGLSAMPLERPARAMETERFPROC samplerParameterf;
+    PFNGLSAMPLERPARAMETERFVPROC samplerParameterfv;
+    PFNGLSAMPLERPARAMETERIPROC samplerParameteri;
+    PFNGLSAMPLERPARAMETERIVPROC samplerParameteriv;
+    PFNGLVERTEXATTRIBDIVISORPROC vertexAttribDivisor;
+    PFNGLVERTEXATTRIBP1UIPROC vertexAttribP1ui;
+    PFNGLVERTEXATTRIBP1UIVPROC vertexAttribP1uiv;
+    PFNGLVERTEXATTRIBP2UIPROC vertexAttribP2ui;
+    PFNGLVERTEXATTRIBP2UIVPROC vertexAttribP2uiv;
+    PFNGLVERTEXATTRIBP3UIPROC vertexAttribP3ui;
+    PFNGLVERTEXATTRIBP3UIVPROC vertexAttribP3uiv;
+    PFNGLVERTEXATTRIBP4UIPROC vertexAttribP4ui;
+    PFNGLVERTEXATTRIBP4UIVPROC vertexAttribP4uiv;
+
+    // 4.0
+    PFNGLBEGINQUERYINDEXEDPROC beginQueryIndexed;
+    PFNGLBINDTRANSFORMFEEDBACKPROC bindTransformFeedback;
+    PFNGLBLENDEQUATIONSEPARATEIPROC blendEquationSeparatei;
+    PFNGLBLENDEQUATIONIPROC blendEquationi;
+    PFNGLBLENDFUNCSEPARATEIPROC blendFuncSeparatei;
+    PFNGLBLENDFUNCIPROC blendFunci;
+    PFNGLDELETETRANSFORMFEEDBACKSPROC deleteTransformFeedbacks;
+    PFNGLDRAWARRAYSINDIRECTPROC drawArraysIndirect;
+    PFNGLDRAWELEMENTSINDIRECTPROC drawElementsIndirect;
+    PFNGLDRAWTRANSFORMFEEDBACKPROC drawTransformFeedback;
+    PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC drawTransformFeedbackStream;
+    PFNGLENDQUERYINDEXEDPROC endQueryIndexed;
+    PFNGLGENTRANSFORMFEEDBACKSPROC genTransformFeedbacks;
+    PFNGLGETACTIVESUBROUTINENAMEPROC getActiveSubroutineName;
+    PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC getActiveSubroutineUniformName;
+    PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC getActiveSubroutineUniformiv;
+    PFNGLGETPROGRAMSTAGEIVPROC getProgramStageiv;
+    PFNGLGETQUERYINDEXEDIVPROC getQueryIndexediv;
+    PFNGLGETSUBROUTINEINDEXPROC getSubroutineIndex;
+    PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC getSubroutineUniformLocation;
+    PFNGLGETUNIFORMSUBROUTINEUIVPROC getUniformSubroutineuiv;
+    PFNGLGETUNIFORMDVPROC getUniformdv;
+    PFNGLISTRANSFORMFEEDBACKPROC isTransformFeedback;
+    PFNGLMINSAMPLESHADINGPROC minSampleShading;
+    PFNGLPATCHPARAMETERFVPROC patchParameterfv;
+    PFNGLPATCHPARAMETERIPROC patchParameteri;
+    PFNGLPAUSETRANSFORMFEEDBACKPROC pauseTransformFeedback;
+    PFNGLRESUMETRANSFORMFEEDBACKPROC resumeTransformFeedback;
+    PFNGLUNIFORM1DPROC uniform1d;
+    PFNGLUNIFORM1DVPROC uniform1dv;
+    PFNGLUNIFORM2DPROC uniform2d;
+    PFNGLUNIFORM2DVPROC uniform2dv;
+    PFNGLUNIFORM3DPROC uniform3d;
+    PFNGLUNIFORM3DVPROC uniform3dv;
+    PFNGLUNIFORM4DPROC uniform4d;
+    PFNGLUNIFORM4DVPROC uniform4dv;
+    PFNGLUNIFORMMATRIX2DVPROC uniformMatrix2dv;
+    PFNGLUNIFORMMATRIX2X3DVPROC uniformMatrix2x3dv;
+    PFNGLUNIFORMMATRIX2X4DVPROC uniformMatrix2x4dv;
+    PFNGLUNIFORMMATRIX3DVPROC uniformMatrix3dv;
+    PFNGLUNIFORMMATRIX3X2DVPROC uniformMatrix3x2dv;
+    PFNGLUNIFORMMATRIX3X4DVPROC uniformMatrix3x4dv;
+    PFNGLUNIFORMMATRIX4DVPROC uniformMatrix4dv;
+    PFNGLUNIFORMMATRIX4X2DVPROC uniformMatrix4x2dv;
+    PFNGLUNIFORMMATRIX4X3DVPROC uniformMatrix4x3dv;
+    PFNGLUNIFORMSUBROUTINESUIVPROC uniformSubroutinesuiv;
+
+    // 4.1
+    PFNGLACTIVESHADERPROGRAMPROC activeShaderProgram;
+    PFNGLBINDPROGRAMPIPELINEPROC bindProgramPipeline;
+    PFNGLCLEARDEPTHFPROC clearDepthf;
+    PFNGLCREATESHADERPROGRAMVPROC createShaderProgramv;
+    PFNGLDELETEPROGRAMPIPELINESPROC deleteProgramPipelines;
+    PFNGLDEPTHRANGEARRAYVPROC depthRangeArrayv;
+    PFNGLDEPTHRANGEINDEXEDPROC depthRangeIndexed;
+    PFNGLDEPTHRANGEFPROC depthRangef;
+    PFNGLGENPROGRAMPIPELINESPROC genProgramPipelines;
+    PFNGLGETDOUBLEI_VPROC getDoublei_v;
+    PFNGLGETFLOATI_VPROC getFloati_v;
+    PFNGLGETPROGRAMBINARYPROC getProgramBinary;
+    PFNGLGETPROGRAMPIPELINEINFOLOGPROC getProgramPipelineInfoLog;
+    PFNGLGETPROGRAMPIPELINEIVPROC getProgramPipelineiv;
+    PFNGLGETSHADERPRECISIONFORMATPROC getShaderPrecisionFormat;
+    PFNGLGETVERTEXATTRIBLDVPROC getVertexAttribLdv;
+    PFNGLISPROGRAMPIPELINEPROC isProgramPipeline;
+    PFNGLPROGRAMBINARYPROC programBinary;
+    PFNGLPROGRAMPARAMETERIPROC programParameteri;
+    PFNGLPROGRAMUNIFORM1DPROC programUniform1d;
+    PFNGLPROGRAMUNIFORM1DVPROC programUniform1dv;
+    PFNGLPROGRAMUNIFORM1FPROC programUniform1f;
+    PFNGLPROGRAMUNIFORM1FVPROC programUniform1fv;
+    PFNGLPROGRAMUNIFORM1IPROC programUniform1i;
+    PFNGLPROGRAMUNIFORM1IVPROC programUniform1iv;
+    PFNGLPROGRAMUNIFORM1UIPROC programUniform1ui;
+    PFNGLPROGRAMUNIFORM1UIVPROC programUniform1uiv;
+    PFNGLPROGRAMUNIFORM2DPROC programUniform2d;
+    PFNGLPROGRAMUNIFORM2DVPROC programUniform2dv;
+    PFNGLPROGRAMUNIFORM2FPROC programUniform2f;
+    PFNGLPROGRAMUNIFORM2FVPROC programUniform2fv;
+    PFNGLPROGRAMUNIFORM2IPROC programUniform2i;
+    PFNGLPROGRAMUNIFORM2IVPROC programUniform2iv;
+    PFNGLPROGRAMUNIFORM2UIPROC programUniform2ui;
+    PFNGLPROGRAMUNIFORM2UIVPROC programUniform2uiv;
+    PFNGLPROGRAMUNIFORM3DPROC programUniform3d;
+    PFNGLPROGRAMUNIFORM3DVPROC programUniform3dv;
+    PFNGLPROGRAMUNIFORM3FPROC programUniform3f;
+    PFNGLPROGRAMUNIFORM3FVPROC programUniform3fv;
+    PFNGLPROGRAMUNIFORM3IPROC programUniform3i;
+    PFNGLPROGRAMUNIFORM3IVPROC programUniform3iv;
+    PFNGLPROGRAMUNIFORM3UIPROC programUniform3ui;
+    PFNGLPROGRAMUNIFORM3UIVPROC programUniform3uiv;
+    PFNGLPROGRAMUNIFORM4DPROC programUniform4d;
+    PFNGLPROGRAMUNIFORM4DVPROC programUniform4dv;
+    PFNGLPROGRAMUNIFORM4FPROC programUniform4f;
+    PFNGLPROGRAMUNIFORM4FVPROC programUniform4fv;
+    PFNGLPROGRAMUNIFORM4IPROC programUniform4i;
+    PFNGLPROGRAMUNIFORM4IVPROC programUniform4iv;
+    PFNGLPROGRAMUNIFORM4UIPROC programUniform4ui;
+    PFNGLPROGRAMUNIFORM4UIVPROC programUniform4uiv;
+    PFNGLPROGRAMUNIFORMMATRIX2DVPROC programUniformMatrix2dv;
+    PFNGLPROGRAMUNIFORMMATRIX2FVPROC programUniformMatrix2fv;
+    PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC programUniformMatrix2x3dv;
+    PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC programUniformMatrix2x3fv;
+    PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC programUniformMatrix2x4dv;
+    PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC programUniformMatrix2x4fv;
+    PFNGLPROGRAMUNIFORMMATRIX3DVPROC programUniformMatrix3dv;
+    PFNGLPROGRAMUNIFORMMATRIX3FVPROC programUniformMatrix3fv;
+    PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC programUniformMatrix3x2dv;
+    PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC programUniformMatrix3x2fv;
+    PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC programUniformMatrix3x4dv;
+    PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC programUniformMatrix3x4fv;
+    PFNGLPROGRAMUNIFORMMATRIX4DVPROC programUniformMatrix4dv;
+    PFNGLPROGRAMUNIFORMMATRIX4FVPROC programUniformMatrix4fv;
+    PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC programUniformMatrix4x2dv;
+    PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC programUniformMatrix4x2fv;
+    PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC programUniformMatrix4x3dv;
+    PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC programUniformMatrix4x3fv;
+    PFNGLRELEASESHADERCOMPILERPROC releaseShaderCompiler;
+    PFNGLSCISSORARRAYVPROC scissorArrayv;
+    PFNGLSCISSORINDEXEDPROC scissorIndexed;
+    PFNGLSCISSORINDEXEDVPROC scissorIndexedv;
+    PFNGLSHADERBINARYPROC shaderBinary;
+    PFNGLUSEPROGRAMSTAGESPROC useProgramStages;
+    PFNGLVALIDATEPROGRAMPIPELINEPROC validateProgramPipeline;
+    PFNGLVERTEXATTRIBL1DPROC vertexAttribL1d;
+    PFNGLVERTEXATTRIBL1DVPROC vertexAttribL1dv;
+    PFNGLVERTEXATTRIBL2DPROC vertexAttribL2d;
+    PFNGLVERTEXATTRIBL2DVPROC vertexAttribL2dv;
+    PFNGLVERTEXATTRIBL3DPROC vertexAttribL3d;
+    PFNGLVERTEXATTRIBL3DVPROC vertexAttribL3dv;
+    PFNGLVERTEXATTRIBL4DPROC vertexAttribL4d;
+    PFNGLVERTEXATTRIBL4DVPROC vertexAttribL4dv;
+    PFNGLVERTEXATTRIBLPOINTERPROC vertexAttribLPointer;
+    PFNGLVIEWPORTARRAYVPROC viewportArrayv;
+    PFNGLVIEWPORTINDEXEDFPROC viewportIndexedf;
+    PFNGLVIEWPORTINDEXEDFVPROC viewportIndexedfv;
+
+    // 4.2
+    PFNGLBINDIMAGETEXTUREPROC bindImageTexture;
+    PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC drawArraysInstancedBaseInstance;
+    PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC drawElementsInstancedBaseInstance;
+    PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC drawElementsInstancedBaseVertexBaseInstance;
+    PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC drawTransformFeedbackInstanced;
+    PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC drawTransformFeedbackStreamInstanced;
+    PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC getActiveAtomicCounterBufferiv;
+    PFNGLGETINTERNALFORMATIVPROC getInternalformativ;
+    PFNGLMEMORYBARRIERPROC memoryBarrier;
+    PFNGLTEXSTORAGE1DPROC texStorage1D;
+    PFNGLTEXSTORAGE2DPROC texStorage2D;
+    PFNGLTEXSTORAGE3DPROC texStorage3D;
+
+    // 4.3
+    PFNGLBINDVERTEXBUFFERPROC bindVertexBuffer;
+    PFNGLCLEARBUFFERDATAPROC clearBufferData;
+    PFNGLCLEARBUFFERSUBDATAPROC clearBufferSubData;
+    PFNGLCOPYIMAGESUBDATAPROC copyImageSubData;
+    PFNGLDEBUGMESSAGECALLBACKPROC debugMessageCallback;
+    PFNGLDEBUGMESSAGECONTROLPROC debugMessageControl;
+    PFNGLDEBUGMESSAGEINSERTPROC debugMessageInsert;
+    PFNGLDISPATCHCOMPUTEPROC dispatchCompute;
+    PFNGLDISPATCHCOMPUTEINDIRECTPROC dispatchComputeIndirect;
+    PFNGLFRAMEBUFFERPARAMETERIPROC framebufferParameteri;
+    PFNGLGETDEBUGMESSAGELOGPROC getDebugMessageLog;
+    PFNGLGETFRAMEBUFFERPARAMETERIVPROC getFramebufferParameteriv;
+    PFNGLGETINTERNALFORMATI64VPROC getInternalformati64v;
+    PFNGLGETPOINTERVPROC getPointerv;
+    PFNGLGETOBJECTLABELPROC getObjectLabel;
+    PFNGLGETOBJECTPTRLABELPROC getObjectPtrLabel;
+    PFNGLGETPROGRAMINTERFACEIVPROC getProgramInterfaceiv;
+    PFNGLGETPROGRAMRESOURCEINDEXPROC getProgramResourceIndex;
+    PFNGLGETPROGRAMRESOURCELOCATIONPROC getProgramResourceLocation;
+    PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC getProgramResourceLocationIndex;
+    PFNGLGETPROGRAMRESOURCENAMEPROC getProgramResourceName;
+    PFNGLGETPROGRAMRESOURCEIVPROC getProgramResourceiv;
+    PFNGLINVALIDATEBUFFERDATAPROC invalidateBufferData;
+    PFNGLINVALIDATEBUFFERSUBDATAPROC invalidateBufferSubData;
+    PFNGLINVALIDATEFRAMEBUFFERPROC invalidateFramebuffer;
+    PFNGLINVALIDATESUBFRAMEBUFFERPROC invalidateSubFramebuffer;
+    PFNGLINVALIDATETEXIMAGEPROC invalidateTexImage;
+    PFNGLINVALIDATETEXSUBIMAGEPROC invalidateTexSubImage;
+    PFNGLMULTIDRAWARRAYSINDIRECTPROC multiDrawArraysIndirect;
+    PFNGLMULTIDRAWELEMENTSINDIRECTPROC multiDrawElementsIndirect;
+    PFNGLOBJECTLABELPROC objectLabel;
+    PFNGLOBJECTPTRLABELPROC objectPtrLabel;
+    PFNGLPOPDEBUGGROUPPROC popDebugGroup;
+    PFNGLPUSHDEBUGGROUPPROC pushDebugGroup;
+    PFNGLSHADERSTORAGEBLOCKBINDINGPROC shaderStorageBlockBinding;
+    PFNGLTEXBUFFERRANGEPROC texBufferRange;
+    PFNGLTEXSTORAGE2DMULTISAMPLEPROC texStorage2DMultisample;
+    PFNGLTEXSTORAGE3DMULTISAMPLEPROC texStorage3DMultisample;
+    PFNGLTEXTUREVIEWPROC textureView;
+    PFNGLVERTEXATTRIBBINDINGPROC vertexAttribBinding;
+    PFNGLVERTEXATTRIBFORMATPROC vertexAttribFormat;
+    PFNGLVERTEXATTRIBIFORMATPROC vertexAttribIFormat;
+    PFNGLVERTEXATTRIBLFORMATPROC vertexAttribLFormat;
+    PFNGLVERTEXBINDINGDIVISORPROC vertexBindingDivisor;
+    PFNGLCOVERAGEMODULATIONNVPROC coverageModulationNV;
+
+    // 4.4
+    PFNGLBINDBUFFERSBASEPROC bindBuffersBase;
+    PFNGLBINDBUFFERSRANGEPROC bindBuffersRange;
+    PFNGLBINDIMAGETEXTURESPROC bindImageTextures;
+    PFNGLBINDSAMPLERSPROC bindSamplers;
+    PFNGLBINDTEXTURESPROC bindTextures;
+    PFNGLBINDVERTEXBUFFERSPROC bindVertexBuffers;
+    PFNGLBUFFERSTORAGEPROC bufferStorage;
+    PFNGLCLEARTEXIMAGEPROC clearTexImage;
+    PFNGLCLEARTEXSUBIMAGEPROC clearTexSubImage;
+
+    // 4.5
+    PFNGLBINDTEXTUREUNITPROC bindTextureUnit;
+    PFNGLBLITNAMEDFRAMEBUFFERPROC blitNamedFramebuffer;
+    PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC checkNamedFramebufferStatus;
+    PFNGLCLEARNAMEDBUFFERDATAPROC clearNamedBufferData;
+    PFNGLCLEARNAMEDBUFFERSUBDATAPROC clearNamedBufferSubData;
+    PFNGLCLEARNAMEDFRAMEBUFFERFIPROC clearNamedFramebufferfi;
+    PFNGLCLEARNAMEDFRAMEBUFFERFVPROC clearNamedFramebufferfv;
+    PFNGLCLEARNAMEDFRAMEBUFFERIVPROC clearNamedFramebufferiv;
+    PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC clearNamedFramebufferuiv;
+    PFNGLCLIPCONTROLPROC clipControl;
+    PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC compressedTextureSubImage1D;
+    PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC compressedTextureSubImage2D;
+    PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC compressedTextureSubImage3D;
+    PFNGLCOPYNAMEDBUFFERSUBDATAPROC copyNamedBufferSubData;
+    PFNGLCOPYTEXTURESUBIMAGE1DPROC copyTextureSubImage1D;
+    PFNGLCOPYTEXTURESUBIMAGE2DPROC copyTextureSubImage2D;
+    PFNGLCOPYTEXTURESUBIMAGE3DPROC copyTextureSubImage3D;
+    PFNGLCREATEBUFFERSPROC createBuffers;
+    PFNGLCREATEFRAMEBUFFERSPROC createFramebuffers;
+    PFNGLCREATEPROGRAMPIPELINESPROC createProgramPipelines;
+    PFNGLCREATEQUERIESPROC createQueries;
+    PFNGLCREATERENDERBUFFERSPROC createRenderbuffers;
+    PFNGLCREATESAMPLERSPROC createSamplers;
+    PFNGLCREATETEXTURESPROC createTextures;
+    PFNGLCREATETRANSFORMFEEDBACKSPROC createTransformFeedbacks;
+    PFNGLCREATEVERTEXARRAYSPROC createVertexArrays;
+    PFNGLDISABLEVERTEXARRAYATTRIBPROC disableVertexArrayAttrib;
+    PFNGLENABLEVERTEXARRAYATTRIBPROC enableVertexArrayAttrib;
+    PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC flushMappedNamedBufferRange;
+    PFNGLGENERATETEXTUREMIPMAPPROC generateTextureMipmap;
+    PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC getCompressedTextureImage;
+    PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC getCompressedTextureSubImage;
+    PFNGLGETGRAPHICSRESETSTATUSPROC getGraphicsResetStatus;
+    PFNGLGETNAMEDBUFFERPARAMETERI64VPROC getNamedBufferParameteri64v;
+    PFNGLGETNAMEDBUFFERPARAMETERIVPROC getNamedBufferParameteriv;
+    PFNGLGETNAMEDBUFFERPOINTERVPROC getNamedBufferPointerv;
+    PFNGLGETNAMEDBUFFERSUBDATAPROC getNamedBufferSubData;
+    PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC getNamedFramebufferAttachmentParameteriv;
+    PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC getNamedFramebufferParameteriv;
+    PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC getNamedRenderbufferParameteriv;
+    PFNGLGETQUERYBUFFEROBJECTI64VPROC getQueryBufferObjecti64v;
+    PFNGLGETQUERYBUFFEROBJECTIVPROC getQueryBufferObjectiv;
+    PFNGLGETQUERYBUFFEROBJECTUI64VPROC getQueryBufferObjectui64v;
+    PFNGLGETQUERYBUFFEROBJECTUIVPROC getQueryBufferObjectuiv;
+    PFNGLGETTEXTUREIMAGEPROC getTextureImage;
+    PFNGLGETTEXTURELEVELPARAMETERFVPROC getTextureLevelParameterfv;
+    PFNGLGETTEXTURELEVELPARAMETERIVPROC getTextureLevelParameteriv;
+    PFNGLGETTEXTUREPARAMETERIIVPROC getTextureParameterIiv;
+    PFNGLGETTEXTUREPARAMETERIUIVPROC getTextureParameterIuiv;
+    PFNGLGETTEXTUREPARAMETERFVPROC getTextureParameterfv;
+    PFNGLGETTEXTUREPARAMETERIVPROC getTextureParameteriv;
+    PFNGLGETTEXTURESUBIMAGEPROC getTextureSubImage;
+    PFNGLGETTRANSFORMFEEDBACKI64_VPROC getTransformFeedbacki64_v;
+    PFNGLGETTRANSFORMFEEDBACKI_VPROC getTransformFeedbacki_v;
+    PFNGLGETTRANSFORMFEEDBACKIVPROC getTransformFeedbackiv;
+    PFNGLGETVERTEXARRAYINDEXED64IVPROC getVertexArrayIndexed64iv;
+    PFNGLGETVERTEXARRAYINDEXEDIVPROC getVertexArrayIndexediv;
+    PFNGLGETVERTEXARRAYIVPROC getVertexArrayiv;
+    PFNGLGETNCOMPRESSEDTEXIMAGEPROC getnCompressedTexImage;
+    PFNGLGETNTEXIMAGEPROC getnTexImage;
+    PFNGLGETNUNIFORMDVPROC getnUniformdv;
+    PFNGLGETNUNIFORMFVPROC getnUniformfv;
+    PFNGLGETNUNIFORMIVPROC getnUniformiv;
+    PFNGLGETNUNIFORMUIVPROC getnUniformuiv;
+    PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC invalidateNamedFramebufferData;
+    PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC invalidateNamedFramebufferSubData;
+    PFNGLMAPNAMEDBUFFERPROC mapNamedBuffer;
+    PFNGLMAPNAMEDBUFFERRANGEPROC mapNamedBufferRange;
+    PFNGLMEMORYBARRIERBYREGIONPROC memoryBarrierByRegion;
+    PFNGLNAMEDBUFFERDATAPROC namedBufferData;
+    PFNGLNAMEDBUFFERSTORAGEPROC namedBufferStorage;
+    PFNGLNAMEDBUFFERSUBDATAPROC namedBufferSubData;
+    PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC namedFramebufferDrawBuffer;
+    PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC namedFramebufferDrawBuffers;
+    PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC namedFramebufferParameteri;
+    PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC namedFramebufferReadBuffer;
+    PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC namedFramebufferRenderbuffer;
+    PFNGLNAMEDFRAMEBUFFERTEXTUREPROC namedFramebufferTexture;
+    PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC namedFramebufferTextureLayer;
+    PFNGLNAMEDRENDERBUFFERSTORAGEPROC namedRenderbufferStorage;
+    PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC namedRenderbufferStorageMultisample;
+    PFNGLREADNPIXELSPROC readnPixels;
+    PFNGLTEXTUREBARRIERPROC textureBarrier;
+    PFNGLTEXTUREBUFFERPROC textureBuffer;
+    PFNGLTEXTUREBUFFERRANGEPROC textureBufferRange;
+    PFNGLTEXTUREPARAMETERIIVPROC textureParameterIiv;
+    PFNGLTEXTUREPARAMETERIUIVPROC textureParameterIuiv;
+    PFNGLTEXTUREPARAMETERFPROC textureParameterf;
+    PFNGLTEXTUREPARAMETERFVPROC textureParameterfv;
+    PFNGLTEXTUREPARAMETERIPROC textureParameteri;
+    PFNGLTEXTUREPARAMETERIVPROC textureParameteriv;
+    PFNGLTEXTURESTORAGE1DPROC textureStorage1D;
+    PFNGLTEXTURESTORAGE2DPROC textureStorage2D;
+    PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC textureStorage2DMultisample;
+    PFNGLTEXTURESTORAGE3DPROC textureStorage3D;
+    PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC textureStorage3DMultisample;
+    PFNGLTEXTURESUBIMAGE1DPROC textureSubImage1D;
+    PFNGLTEXTURESUBIMAGE2DPROC textureSubImage2D;
+    PFNGLTEXTURESUBIMAGE3DPROC textureSubImage3D;
+    PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC transformFeedbackBufferBase;
+    PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC transformFeedbackBufferRange;
+    PFNGLUNMAPNAMEDBUFFERPROC unmapNamedBuffer;
+    PFNGLVERTEXARRAYATTRIBBINDINGPROC vertexArrayAttribBinding;
+    PFNGLVERTEXARRAYATTRIBFORMATPROC vertexArrayAttribFormat;
+    PFNGLVERTEXARRAYATTRIBIFORMATPROC vertexArrayAttribIFormat;
+    PFNGLVERTEXARRAYATTRIBLFORMATPROC vertexArrayAttribLFormat;
+    PFNGLVERTEXARRAYBINDINGDIVISORPROC vertexArrayBindingDivisor;
+    PFNGLVERTEXARRAYELEMENTBUFFERPROC vertexArrayElementBuffer;
+    PFNGLVERTEXARRAYVERTEXBUFFERPROC vertexArrayVertexBuffer;
+    PFNGLVERTEXARRAYVERTEXBUFFERSPROC vertexArrayVertexBuffers;
+
+    // ES 3.2
+    PFNGLBLENDBARRIERPROC blendBarrier;
+    PFNGLPRIMITIVEBOUNDINGBOXPROC primitiveBoundingBox;
+
+    // GL_OES_EGL_image
+    PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC eglImageTargetRenderbufferStorageOES;
+    PFNGLEGLIMAGETARGETTEXTURE2DOESPROC eglImageTargetTexture2DOES;
+
+    // GL_EXT_discard_framebuffer
+    PFNGLDISCARDFRAMEBUFFEREXTPROC discardFramebuffer;
+
+  private:
+    void initializeProcsDesktopGL();
+    void initializeProcsGLES();
+
+    virtual void *loadProcAddress(const std::string &function) = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/PathGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/PathGL.cpp
new file mode 100644
index 0000000..5348674
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/PathGL.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// PathGL.cpp: Implementation for PathGL class.
+
+#include "libANGLE/renderer/gl/PathGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+namespace rx
+{
+
+PathGL::PathGL(const FunctionsGL *functions, GLuint path) : mFunctions(functions), mPathID(path)
+{
+}
+
+PathGL::~PathGL()
+{
+}
+
+gl::Error PathGL::setCommands(GLsizei numCommands,
+                              const GLubyte *commands,
+                              GLsizei numCoords,
+                              GLenum coordType,
+                              const void *coords)
+{
+    mFunctions->pathCommandsNV(mPathID, numCommands, commands, numCoords, coordType, coords);
+    return gl::NoError();
+}
+
+void PathGL::setPathParameter(GLenum pname, GLfloat value)
+{
+    mFunctions->setPathParameterfNV(mPathID, pname, value);
+}
+
+}  // rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/PathGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/PathGL.h
new file mode 100644
index 0000000..461d39a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/PathGL.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// PathGL.h: Class definition for CHROMIUM_path_rendering path object for the
+// GL backend.
+
+#ifndef LIBANGLE_RENDERER_GL_PATHIMPL_H_
+#define LIBANGLE_RENDERER_GL_PATHIMPL_H_
+
+#include "libANGLE/renderer/PathImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+
+class PathGL : public PathImpl
+{
+  public:
+    PathGL(const FunctionsGL *functions, GLuint path);
+    ~PathGL();
+
+    gl::Error setCommands(GLsizei numCommands,
+                          const GLubyte *commands,
+                          GLsizei numCoords,
+                          GLenum coordType,
+                          const void *coords) override;
+
+    void setPathParameter(GLenum pname, GLfloat value) override;
+
+    GLuint getPathID() const { return mPathID; }
+
+  private:
+    const FunctionsGL *mFunctions;
+
+    GLuint mPathID;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_PATHIMPL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
new file mode 100644
index 0000000..b3e5546
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -0,0 +1,722 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramGL.cpp: Implements the class methods for ProgramGL.
+
+#include "libANGLE/renderer/gl/ProgramGL.h"
+
+#include "common/bitset_utils.h"
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/renderer/gl/ContextGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/ShaderGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/Uniform.h"
+#include "platform/Platform.h"
+
+namespace rx
+{
+
+ProgramGL::ProgramGL(const gl::ProgramState &data,
+                     const FunctionsGL *functions,
+                     const WorkaroundsGL &workarounds,
+                     StateManagerGL *stateManager,
+                     bool enablePathRendering)
+    : ProgramImpl(data),
+      mFunctions(functions),
+      mWorkarounds(workarounds),
+      mStateManager(stateManager),
+      mEnablePathRendering(enablePathRendering),
+      mProgramID(0)
+{
+    ASSERT(mFunctions);
+    ASSERT(mStateManager);
+
+    mProgramID = mFunctions->createProgram();
+}
+
+ProgramGL::~ProgramGL()
+{
+    mFunctions->deleteProgram(mProgramID);
+    mProgramID = 0;
+}
+
+LinkResult ProgramGL::load(const ContextImpl *contextImpl,
+                           gl::InfoLog &infoLog,
+                           gl::BinaryInputStream *stream)
+{
+    preLink();
+
+    // Read the binary format, size and blob
+    GLenum binaryFormat   = stream->readInt<GLenum>();
+    GLint binaryLength    = stream->readInt<GLint>();
+    const uint8_t *binary = stream->data() + stream->offset();
+    stream->skip(binaryLength);
+
+    // Load the binary
+    mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
+
+    // Verify that the program linked
+    if (!checkLinkStatus(infoLog))
+    {
+        return false;
+    }
+
+    postLink();
+
+    // Re-apply UBO bindings to work around driver bugs.
+    const WorkaroundsGL &workaroundsGL = GetAs<ContextGL>(contextImpl)->getWorkaroundsGL();
+    if (workaroundsGL.reapplyUBOBindingsAfterLoadingBinaryProgram)
+    {
+        for (size_t bindingIndex : mState.getActiveUniformBlockBindingsMask())
+        {
+            GLuint uintIndex = static_cast<GLuint>(bindingIndex);
+            setUniformBlockBinding(uintIndex, mState.getUniformBlockBinding(uintIndex));
+        }
+    }
+
+    return true;
+}
+
+gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
+{
+    GLint binaryLength = 0;
+    mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
+
+    std::vector<uint8_t> binary(binaryLength);
+    GLenum binaryFormat = GL_NONE;
+    mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
+                                 &binary[0]);
+
+    stream->writeInt(binaryFormat);
+    stream->writeInt(binaryLength);
+    stream->writeBytes(&binary[0], binaryLength);
+
+    return gl::NoError();
+}
+
+void ProgramGL::setBinaryRetrievableHint(bool retrievable)
+{
+    // glProgramParameteri isn't always available on ES backends.
+    if (mFunctions->programParameteri)
+    {
+        mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
+                                      retrievable ? GL_TRUE : GL_FALSE);
+    }
+}
+
+void ProgramGL::setSeparable(bool separable)
+{
+    mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
+}
+
+LinkResult ProgramGL::link(ContextImpl *contextImpl,
+                           const gl::VaryingPacking &packing,
+                           gl::InfoLog &infoLog)
+{
+    preLink();
+
+    if (mState.getAttachedComputeShader())
+    {
+        const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
+
+        mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
+
+        // Link and verify
+        mFunctions->linkProgram(mProgramID);
+
+        // Detach the shaders
+        mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
+    }
+    else
+    {
+        // Set the transform feedback state
+        std::vector<const GLchar *> transformFeedbackVaryings;
+        for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
+        {
+            transformFeedbackVaryings.push_back(tfVarying.c_str());
+        }
+
+        if (transformFeedbackVaryings.empty())
+        {
+            if (mFunctions->transformFeedbackVaryings)
+            {
+                mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
+                                                      mState.getTransformFeedbackBufferMode());
+            }
+        }
+        else
+        {
+            ASSERT(mFunctions->transformFeedbackVaryings);
+            mFunctions->transformFeedbackVaryings(
+                mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
+                &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
+        }
+
+        const ShaderGL *vertexShaderGL   = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
+        const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
+
+        // Attach the shaders
+        mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
+        mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
+
+        // Bind attribute locations to match the GL layer.
+        for (const sh::Attribute &attribute : mState.getAttributes())
+        {
+            if (!attribute.staticUse || attribute.isBuiltIn())
+            {
+                continue;
+            }
+
+            mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
+        }
+
+        // Link and verify
+        mFunctions->linkProgram(mProgramID);
+
+        // Detach the shaders
+        mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
+        mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
+    }
+
+    // Verify the link
+    if (!checkLinkStatus(infoLog))
+    {
+        return false;
+    }
+
+    if (mWorkarounds.alwaysCallUseProgramAfterLink)
+    {
+        mStateManager->forceUseProgram(mProgramID);
+    }
+
+    postLink();
+
+    return true;
+}
+
+GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
+{
+    // TODO(jmadill): implement validate
+    return true;
+}
+
+void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (mFunctions->programUniform1fv != nullptr)
+    {
+        mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform1fv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (mFunctions->programUniform2fv != nullptr)
+    {
+        mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform2fv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (mFunctions->programUniform3fv != nullptr)
+    {
+        mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform3fv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (mFunctions->programUniform4fv != nullptr)
+    {
+        mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform4fv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+    if (mFunctions->programUniform1iv != nullptr)
+    {
+        mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform1iv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+    if (mFunctions->programUniform2iv != nullptr)
+    {
+        mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform2iv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+    if (mFunctions->programUniform3iv != nullptr)
+    {
+        mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform3iv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+    if (mFunctions->programUniform4iv != nullptr)
+    {
+        mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform4iv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    if (mFunctions->programUniform1uiv != nullptr)
+    {
+        mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform1uiv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    if (mFunctions->programUniform2uiv != nullptr)
+    {
+        mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform2uiv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    if (mFunctions->programUniform3uiv != nullptr)
+    {
+        mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform3uiv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    if (mFunctions->programUniform4uiv != nullptr)
+    {
+        mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniform4uiv(uniLoc(location), count, v);
+    }
+}
+
+void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    if (mFunctions->programUniformMatrix2fv != nullptr)
+    {
+        mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
+    }
+}
+
+void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    if (mFunctions->programUniformMatrix3fv != nullptr)
+    {
+        mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
+    }
+}
+
+void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    if (mFunctions->programUniformMatrix4fv != nullptr)
+    {
+        mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
+    }
+}
+
+void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    if (mFunctions->programUniformMatrix2x3fv != nullptr)
+    {
+        mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
+                                              value);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
+    }
+}
+
+void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    if (mFunctions->programUniformMatrix3x2fv != nullptr)
+    {
+        mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
+                                              value);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
+    }
+}
+
+void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    if (mFunctions->programUniformMatrix2x4fv != nullptr)
+    {
+        mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
+                                              value);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
+    }
+}
+
+void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    if (mFunctions->programUniformMatrix4x2fv != nullptr)
+    {
+        mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
+                                              value);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
+    }
+}
+
+void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    if (mFunctions->programUniformMatrix3x4fv != nullptr)
+    {
+        mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
+                                              value);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
+    }
+}
+
+void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    if (mFunctions->programUniformMatrix4x3fv != nullptr)
+    {
+        mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
+                                              value);
+    }
+    else
+    {
+        mStateManager->useProgram(mProgramID);
+        mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
+    }
+}
+
+void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+    // Lazy init
+    if (mUniformBlockRealLocationMap.empty())
+    {
+        mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
+        for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
+        {
+            const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
+            GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
+            mUniformBlockRealLocationMap.push_back(blockIndex);
+        }
+    }
+
+    GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
+    if (realBlockIndex != GL_INVALID_INDEX)
+    {
+        mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
+    }
+}
+
+GLuint ProgramGL::getProgramID() const
+{
+    return mProgramID;
+}
+
+bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+    ASSERT(mProgramID != 0u);
+
+    GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
+    if (blockIndex == GL_INVALID_INDEX)
+    {
+        *sizeOut = 0;
+        return false;
+    }
+
+    GLint dataSize = 0;
+    mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
+                                        &dataSize);
+    *sizeOut = static_cast<size_t>(dataSize);
+    return true;
+}
+
+bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                          sh::BlockMemberInfo *memberInfoOut) const
+{
+    GLuint uniformIndex;
+    const GLchar *memberNameGLStr = memberUniformName.c_str();
+    mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
+
+    if (uniformIndex == GL_INVALID_INDEX)
+    {
+        *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+        return false;
+    }
+
+    mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
+                                    &memberInfoOut->offset);
+    mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
+                                    &memberInfoOut->arrayStride);
+    mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
+                                    &memberInfoOut->matrixStride);
+
+    // TODO(jmadill): possibly determine this at the gl::Program level.
+    GLint isRowMajorMatrix = 0;
+    mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
+                                    &isRowMajorMatrix);
+    memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
+    return true;
+}
+
+void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
+                                        GLenum genMode,
+                                        GLint components,
+                                        const GLfloat *coeffs)
+{
+    ASSERT(mEnablePathRendering);
+
+    for (const auto &input : mPathRenderingFragmentInputs)
+    {
+        if (input.name == inputName)
+        {
+            mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
+                                                      components, coeffs);
+            ASSERT(mFunctions->getError() == GL_NO_ERROR);
+            return;
+        }
+    }
+
+}
+
+void ProgramGL::preLink()
+{
+    // Reset the program state
+    mUniformRealLocationMap.clear();
+    mUniformBlockRealLocationMap.clear();
+    mPathRenderingFragmentInputs.clear();
+}
+
+bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
+{
+    GLint linkStatus = GL_FALSE;
+    mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
+    if (linkStatus == GL_FALSE)
+    {
+        // Linking failed, put the error into the info log
+        GLint infoLogLength = 0;
+        mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+        // Info log length includes the null terminator, so 1 means that the info log is an empty
+        // string.
+        if (infoLogLength > 1)
+        {
+            std::vector<char> buf(infoLogLength);
+            mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
+
+            mFunctions->deleteProgram(mProgramID);
+            mProgramID = 0;
+
+            infoLog << buf.data();
+
+            WARN() << "Program link failed unexpectedly: " << buf.data();
+        }
+        else
+        {
+            WARN() << "Program link failed unexpectedly with no info log.";
+        }
+
+        // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
+        return false;
+    }
+
+    return true;
+}
+
+void ProgramGL::postLink()
+{
+    // Query the uniform information
+    ASSERT(mUniformRealLocationMap.empty());
+    const auto &uniformLocations = mState.getUniformLocations();
+    const auto &uniforms = mState.getUniforms();
+    mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
+    for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
+    {
+        const auto &entry = uniformLocations[uniformLocation];
+        if (!entry.used)
+        {
+            continue;
+        }
+
+        // From the spec:
+        // "Locations for sequential array indices are not required to be sequential."
+        const gl::LinkedUniform &uniform = uniforms[entry.index];
+        std::stringstream fullNameStr;
+        fullNameStr << uniform.name;
+        if (uniform.isArray())
+        {
+            fullNameStr << "[" << entry.element << "]";
+        }
+        const std::string &fullName = fullNameStr.str();
+
+        GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
+        mUniformRealLocationMap[uniformLocation] = realLocation;
+    }
+
+    // Discover CHROMIUM_path_rendering fragment inputs if enabled.
+    if (!mEnablePathRendering)
+        return;
+
+    GLint numFragmentInputs = 0;
+    mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
+                                      &numFragmentInputs);
+    if (numFragmentInputs <= 0)
+        return;
+
+    GLint maxNameLength = 0;
+    mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
+                                      &maxNameLength);
+    ASSERT(maxNameLength);
+
+    for (GLint i = 0; i < numFragmentInputs; ++i)
+    {
+        std::string name;
+        name.resize(maxNameLength);
+
+        GLsizei nameLen = 0;
+        mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
+                                           &nameLen, &name[0]);
+        name.resize(nameLen);
+
+        // Ignore built-ins
+        if (angle::BeginsWith(name, "gl_"))
+            continue;
+
+        const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
+        GLint queryResults[ArraySize(kQueryProperties)];
+        GLsizei queryLength = 0;
+
+        mFunctions->getProgramResourceiv(
+            mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
+            kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
+            queryResults);
+
+        ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
+
+        PathRenderingFragmentInput baseElementInput;
+        baseElementInput.name     = name;
+        baseElementInput.location = queryResults[0];
+        mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
+
+        // If the input is an array it's denoted by [0] suffix on the variable
+        // name. We'll then create an entry per each array index where index > 0
+        if (angle::EndsWith(name, "[0]"))
+        {
+            // drop the suffix
+            name.resize(name.size() - 3);
+
+            const auto arraySize    = queryResults[1];
+            const auto baseLocation = queryResults[0];
+
+            for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
+            {
+                PathRenderingFragmentInput arrayElementInput;
+                arrayElementInput.name     = name + "[" + ToString(arrayIndex) + "]";
+                arrayElementInput.location = baseLocation + arrayIndex;
+                mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
+            }
+        }
+    }
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h
new file mode 100644
index 0000000..fa5a7c4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h
@@ -0,0 +1,110 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramGL.h: Defines the class interface for ProgramGL.
+
+#ifndef LIBANGLE_RENDERER_GL_PROGRAMGL_H_
+#define LIBANGLE_RENDERER_GL_PROGRAMGL_H_
+
+#include <string>
+#include <vector>
+
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class ProgramGL : public ProgramImpl
+{
+  public:
+    ProgramGL(const gl::ProgramState &data,
+              const FunctionsGL *functions,
+              const WorkaroundsGL &workarounds,
+              StateManagerGL *stateManager,
+              bool enablePathRendering);
+    ~ProgramGL() override;
+
+    LinkResult load(const ContextImpl *contextImpl,
+                    gl::InfoLog &infoLog,
+                    gl::BinaryInputStream *stream) override;
+    gl::Error save(gl::BinaryOutputStream *stream) override;
+    void setBinaryRetrievableHint(bool retrievable) override;
+    void setSeparable(bool separable) override;
+
+    LinkResult link(ContextImpl *contextImpl,
+                    const gl::VaryingPacking &packing,
+                    gl::InfoLog &infoLog) override;
+    GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
+
+    void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform1iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform2iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform3iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform4iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
+    void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
+    void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
+    void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
+    void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
+    void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
+    void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
+    void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
+    void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
+
+    void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
+
+    bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+    bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                   sh::BlockMemberInfo *memberInfoOut) const override;
+
+    void setPathFragmentInputGen(const std::string &inputName,
+                                 GLenum genMode,
+                                 GLint components,
+                                 const GLfloat *coeffs) override;
+
+    GLuint getProgramID() const;
+
+  private:
+    void preLink();
+    bool checkLinkStatus(gl::InfoLog &infoLog);
+    void postLink();
+
+    // Helper function, makes it simpler to type.
+    GLint uniLoc(GLint glLocation) const { return mUniformRealLocationMap[glLocation]; }
+
+    const FunctionsGL *mFunctions;
+    const WorkaroundsGL &mWorkarounds;
+    StateManagerGL *mStateManager;
+
+    std::vector<GLint> mUniformRealLocationMap;
+    std::vector<GLuint> mUniformBlockRealLocationMap;
+
+    struct PathRenderingFragmentInput
+    {
+        std::string name;
+        GLint location;
+    };
+    std::vector<PathRenderingFragmentInput> mPathRenderingFragmentInputs;
+
+    bool mEnablePathRendering;
+
+    GLuint mProgramID;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_PROGRAMGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp
new file mode 100644
index 0000000..9ed36be
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp
@@ -0,0 +1,423 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// QueryGL.cpp: Implements the class methods for QueryGL.
+
+#include "libANGLE/renderer/gl/QueryGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace
+{
+
+GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult)
+{
+    switch (type)
+    {
+        case GL_ANY_SAMPLES_PASSED:
+        case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+            return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
+
+        case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+            return currentResult + newResult;
+
+        case GL_TIME_ELAPSED:
+            return currentResult + newResult;
+
+        case GL_TIMESTAMP:
+            return newResult;
+
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+}  // anonymous namespace
+
+namespace rx
+{
+
+QueryGL::QueryGL(GLenum type) : QueryImpl(type)
+{
+}
+
+QueryGL::~QueryGL()
+{
+}
+
+StandardQueryGL::StandardQueryGL(GLenum type,
+                                 const FunctionsGL *functions,
+                                 StateManagerGL *stateManager)
+    : QueryGL(type),
+      mType(type),
+      mFunctions(functions),
+      mStateManager(stateManager),
+      mActiveQuery(0),
+      mPendingQueries(),
+      mResultSum(0)
+{
+}
+
+StandardQueryGL::~StandardQueryGL()
+{
+    mStateManager->deleteQuery(mActiveQuery);
+    mStateManager->onDeleteQueryObject(this);
+    while (!mPendingQueries.empty())
+    {
+        mStateManager->deleteQuery(mPendingQueries.front());
+        mPendingQueries.pop_front();
+    }
+}
+
+gl::Error StandardQueryGL::begin()
+{
+    mResultSum = 0;
+    mStateManager->onBeginQuery(this);
+    return resume();
+}
+
+gl::Error StandardQueryGL::end()
+{
+    return pause();
+}
+
+gl::Error StandardQueryGL::queryCounter()
+{
+    ASSERT(mType == GL_TIMESTAMP);
+
+    // Directly create a query for the timestamp and add it to the pending query queue, as timestamp
+    // queries do not have the traditional begin/end block and never need to be paused/resumed
+    GLuint query;
+    mFunctions->genQueries(1, &query);
+    mFunctions->queryCounter(query, GL_TIMESTAMP);
+    mPendingQueries.push_back(query);
+
+    return gl::NoError();
+}
+
+template <typename T>
+gl::Error StandardQueryGL::getResultBase(T *params)
+{
+    ASSERT(mActiveQuery == 0);
+
+    gl::Error error = flush(true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ASSERT(mPendingQueries.empty());
+    *params = static_cast<T>(mResultSum);
+
+    return gl::NoError();
+}
+
+gl::Error StandardQueryGL::getResult(GLint *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error StandardQueryGL::getResult(GLuint *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error StandardQueryGL::getResult(GLint64 *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error StandardQueryGL::getResult(GLuint64 *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error StandardQueryGL::isResultAvailable(bool *available)
+{
+    ASSERT(mActiveQuery == 0);
+
+    gl::Error error = flush(false);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    *available = mPendingQueries.empty();
+    return gl::NoError();
+}
+
+gl::Error StandardQueryGL::pause()
+{
+    if (mActiveQuery != 0)
+    {
+        mStateManager->endQuery(mType, mActiveQuery);
+
+        mPendingQueries.push_back(mActiveQuery);
+        mActiveQuery = 0;
+    }
+
+    // Flush to make sure the pending queries don't add up too much.
+    gl::Error error = flush(false);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return gl::NoError();
+}
+
+gl::Error StandardQueryGL::resume()
+{
+    if (mActiveQuery == 0)
+    {
+        // Flush to make sure the pending queries don't add up too much.
+        gl::Error error = flush(false);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        mFunctions->genQueries(1, &mActiveQuery);
+        mStateManager->beginQuery(mType, mActiveQuery);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error StandardQueryGL::flush(bool force)
+{
+    while (!mPendingQueries.empty())
+    {
+        GLuint id = mPendingQueries.front();
+        if (!force)
+        {
+            GLuint resultAvailable = 0;
+            mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
+            if (resultAvailable == GL_FALSE)
+            {
+                return gl::NoError();
+            }
+        }
+
+        // Even though getQueryObjectui64v was introduced for timer queries, there is nothing in the
+        // standard that says that it doesn't work for any other queries. It also passes on all the
+        // trybots, so we use it if it is available
+        if (mFunctions->getQueryObjectui64v != nullptr)
+        {
+            GLuint64 result = 0;
+            mFunctions->getQueryObjectui64v(id, GL_QUERY_RESULT, &result);
+            mResultSum = MergeQueryResults(mType, mResultSum, result);
+        }
+        else
+        {
+            GLuint result = 0;
+            mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result);
+            mResultSum = MergeQueryResults(mType, mResultSum, static_cast<GLuint64>(result));
+        }
+
+        mStateManager->deleteQuery(id);
+
+        mPendingQueries.pop_front();
+    }
+
+    return gl::NoError();
+}
+
+class SyncProviderGL
+{
+  public:
+    virtual ~SyncProviderGL() {}
+    virtual gl::Error flush(bool force, bool *finished) = 0;
+};
+
+class SyncProviderGLSync : public SyncProviderGL
+{
+  public:
+    SyncProviderGLSync(const FunctionsGL *functions) : mFunctions(functions), mSync(nullptr)
+    {
+        mSync = mFunctions->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+    }
+
+    virtual ~SyncProviderGLSync() { mFunctions->deleteSync(mSync); }
+
+    gl::Error flush(bool force, bool *finished) override
+    {
+        if (force)
+        {
+            mFunctions->clientWaitSync(mSync, 0, 0);
+            *finished = true;
+        }
+        else
+        {
+            GLint value = 0;
+            mFunctions->getSynciv(mSync, GL_SYNC_STATUS, 1, nullptr, &value);
+            *finished = (value == GL_SIGNALED);
+        }
+
+        return gl::NoError();
+    }
+
+  private:
+    const FunctionsGL *mFunctions;
+    GLsync mSync;
+};
+
+class SyncProviderGLQuery : public SyncProviderGL
+{
+  public:
+    SyncProviderGLQuery(const FunctionsGL *functions,
+                        StateManagerGL *stateManager,
+                        GLenum queryType)
+        : mFunctions(functions), mQuery(0)
+    {
+        mFunctions->genQueries(1, &mQuery);
+        stateManager->pauseQuery(queryType);
+        mFunctions->beginQuery(queryType, mQuery);
+        mFunctions->endQuery(queryType);
+        stateManager->resumeQuery(queryType);
+    }
+
+    virtual ~SyncProviderGLQuery() { mFunctions->deleteQueries(1, &mQuery); }
+
+    gl::Error flush(bool force, bool *finished) override
+    {
+        if (force)
+        {
+            GLint result = 0;
+            mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT, &result);
+            *finished = true;
+        }
+        else
+        {
+            GLint available = 0;
+            mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &available);
+            *finished = (available == GL_TRUE);
+        }
+
+        return gl::NoError();
+    }
+
+  private:
+    const FunctionsGL *mFunctions;
+    GLuint mQuery;
+};
+
+SyncQueryGL::SyncQueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
+    : QueryGL(type),
+      mFunctions(functions),
+      mStateManager(stateManager),
+      mSyncProvider(nullptr),
+      mFinished(false)
+{
+    ASSERT(IsSupported(mFunctions));
+    ASSERT(type == GL_COMMANDS_COMPLETED_CHROMIUM);
+}
+
+SyncQueryGL::~SyncQueryGL()
+{
+}
+
+bool SyncQueryGL::IsSupported(const FunctionsGL *functions)
+{
+    return nativegl::SupportsFenceSync(functions) || nativegl::SupportsOcclusionQueries(functions);
+}
+
+gl::Error SyncQueryGL::begin()
+{
+    return gl::NoError();
+}
+
+gl::Error SyncQueryGL::end()
+{
+    if (nativegl::SupportsFenceSync(mFunctions))
+    {
+        mSyncProvider.reset(new SyncProviderGLSync(mFunctions));
+    }
+    else if (nativegl::SupportsOcclusionQueries(mFunctions))
+    {
+        mSyncProvider.reset(
+            new SyncProviderGLQuery(mFunctions, mStateManager, GL_ANY_SAMPLES_PASSED));
+    }
+    else
+    {
+        ASSERT(false);
+        return gl::Error(GL_INVALID_OPERATION, "No native support for sync queries.");
+    }
+    return gl::NoError();
+}
+
+gl::Error SyncQueryGL::queryCounter()
+{
+    UNREACHABLE();
+    return gl::NoError();
+}
+
+gl::Error SyncQueryGL::getResult(GLint *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error SyncQueryGL::getResult(GLuint *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error SyncQueryGL::getResult(GLint64 *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error SyncQueryGL::getResult(GLuint64 *params)
+{
+    return getResultBase(params);
+}
+
+gl::Error SyncQueryGL::isResultAvailable(bool *available)
+{
+    ANGLE_TRY(flush(false));
+    *available = mFinished;
+    return gl::NoError();
+}
+
+gl::Error SyncQueryGL::pause()
+{
+    return gl::NoError();
+}
+
+gl::Error SyncQueryGL::resume()
+{
+    return gl::NoError();
+}
+
+gl::Error SyncQueryGL::flush(bool force)
+{
+    if (mSyncProvider == nullptr)
+    {
+        ASSERT(mFinished);
+        return gl::NoError();
+    }
+
+    ANGLE_TRY(mSyncProvider->flush(force, &mFinished));
+    if (mFinished)
+    {
+        mSyncProvider.reset();
+    }
+
+    return gl::NoError();
+}
+
+template <typename T>
+gl::Error SyncQueryGL::getResultBase(T *params)
+{
+    ANGLE_TRY(flush(true));
+    *params = static_cast<T>(mFinished ? GL_TRUE : GL_FALSE);
+    return gl::NoError();
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h
new file mode 100644
index 0000000..887665a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h
@@ -0,0 +1,107 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// QueryGL.h: Defines the class interface for QueryGL.
+
+#ifndef LIBANGLE_RENDERER_GL_QUERYGL_H_
+#define LIBANGLE_RENDERER_GL_QUERYGL_H_
+
+#include <deque>
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class QueryGL : public QueryImpl
+{
+  public:
+    QueryGL(GLenum type);
+    ~QueryGL() override;
+
+    // OpenGL is only allowed to have one query of each type active at any given time. Since ANGLE
+    // virtualizes contexts, queries need to be able to be paused and resumed.
+    // A query is "paused" by ending it and pushing the ID into a list of queries awaiting readback.
+    // When it is "resumed", a new query is generated and started.
+    // When a result is required, the queries are "flushed" by iterating over the list of pending
+    // queries and merging their results.
+    virtual gl::Error pause()  = 0;
+    virtual gl::Error resume() = 0;
+};
+
+class StandardQueryGL : public QueryGL
+{
+  public:
+    StandardQueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager);
+    ~StandardQueryGL() override;
+
+    gl::Error begin() override;
+    gl::Error end() override;
+    gl::Error queryCounter() override;
+    gl::Error getResult(GLint *params) override;
+    gl::Error getResult(GLuint *params) override;
+    gl::Error getResult(GLint64 *params) override;
+    gl::Error getResult(GLuint64 *params) override;
+    gl::Error isResultAvailable(bool *available) override;
+
+    gl::Error pause() override;
+    gl::Error resume() override;
+
+  private:
+    gl::Error flush(bool force);
+
+    template <typename T>
+    gl::Error getResultBase(T *params);
+
+    GLenum mType;
+
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+
+    GLuint mActiveQuery;
+    std::deque<GLuint> mPendingQueries;
+    GLuint64 mResultSum;
+};
+
+class SyncProviderGL;
+class SyncQueryGL : public QueryGL
+{
+  public:
+    SyncQueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager);
+    ~SyncQueryGL() override;
+
+    static bool IsSupported(const FunctionsGL *functions);
+
+    gl::Error begin() override;
+    gl::Error end() override;
+    gl::Error queryCounter() override;
+    gl::Error getResult(GLint *params) override;
+    gl::Error getResult(GLuint *params) override;
+    gl::Error getResult(GLint64 *params) override;
+    gl::Error getResult(GLuint64 *params) override;
+    gl::Error isResultAvailable(bool *available) override;
+
+    gl::Error pause() override;
+    gl::Error resume() override;
+
+  private:
+    gl::Error flush(bool force);
+
+    template <typename T>
+    gl::Error getResultBase(T *params);
+
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+
+    std::unique_ptr<SyncProviderGL> mSyncProvider;
+    bool mFinished;
+};
+}
+
+#endif // LIBANGLE_RENDERER_GL_QUERYGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp
new file mode 100644
index 0000000..1c4d35d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp
@@ -0,0 +1,96 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferGL.cpp: Implements the class methods for RenderbufferGL.
+
+#include "libANGLE/renderer/gl/RenderbufferGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace rx
+{
+RenderbufferGL::RenderbufferGL(const FunctionsGL *functions,
+                               const WorkaroundsGL &workarounds,
+                               StateManagerGL *stateManager,
+                               const gl::TextureCapsMap &textureCaps)
+    : RenderbufferImpl(),
+      mFunctions(functions),
+      mWorkarounds(workarounds),
+      mStateManager(stateManager),
+      mTextureCaps(textureCaps),
+      mRenderbufferID(0)
+{
+    mFunctions->genRenderbuffers(1, &mRenderbufferID);
+    mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
+}
+
+RenderbufferGL::~RenderbufferGL()
+{
+    mStateManager->deleteRenderbuffer(mRenderbufferID);
+    mRenderbufferID = 0;
+}
+
+gl::Error RenderbufferGL::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+    mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
+
+    nativegl::RenderbufferFormat renderbufferFormat =
+        nativegl::GetRenderbufferFormat(mFunctions, mWorkarounds, internalformat);
+    mFunctions->renderbufferStorage(GL_RENDERBUFFER, renderbufferFormat.internalFormat,
+                                    static_cast<GLsizei>(width), static_cast<GLsizei>(height));
+
+    return gl::NoError();
+}
+
+gl::Error RenderbufferGL::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
+{
+    mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
+
+    nativegl::RenderbufferFormat renderbufferFormat =
+        nativegl::GetRenderbufferFormat(mFunctions, mWorkarounds, internalformat);
+    mFunctions->renderbufferStorageMultisample(
+        GL_RENDERBUFFER, static_cast<GLsizei>(samples), renderbufferFormat.internalFormat,
+        static_cast<GLsizei>(width), static_cast<GLsizei>(height));
+
+    const gl::TextureCaps &formatCaps = mTextureCaps.get(internalformat);
+    if (samples > formatCaps.getMaxSamples())
+    {
+        // Before version 4.2, it is unknown if the specific internal format can support the requested number
+        // of samples.  It is expected that GL_OUT_OF_MEMORY is returned if the renderbuffer cannot be created.
+        GLenum error = GL_NO_ERROR;
+        do
+        {
+            error = mFunctions->getError();
+            if (error == GL_OUT_OF_MEMORY)
+            {
+                return gl::Error(GL_OUT_OF_MEMORY);
+            }
+
+            ASSERT(error == GL_NO_ERROR);
+        } while (error != GL_NO_ERROR);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error RenderbufferGL::setStorageEGLImageTarget(egl::Image *image)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+GLuint RenderbufferGL::getRenderbufferID() const
+{
+    return mRenderbufferID;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/RenderbufferGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/RenderbufferGL.h
new file mode 100644
index 0000000..0ff0fae
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/RenderbufferGL.h
@@ -0,0 +1,52 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferGL.h: Defines the class interface for RenderbufferGL.
+
+#ifndef LIBANGLE_RENDERER_GL_RENDERBUFFERGL_H_
+#define LIBANGLE_RENDERER_GL_RENDERBUFFERGL_H_
+
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace gl
+{
+class TextureCapsMap;
+}
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class RenderbufferGL : public RenderbufferImpl
+{
+  public:
+    RenderbufferGL(const FunctionsGL *functions,
+                   const WorkaroundsGL &workarounds,
+                   StateManagerGL *stateManager,
+                   const gl::TextureCapsMap &textureCaps);
+    ~RenderbufferGL() override;
+
+    virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
+    virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) override;
+    virtual gl::Error setStorageEGLImageTarget(egl::Image *image) override;
+
+    GLuint getRenderbufferID() const;
+
+  private:
+    const FunctionsGL *mFunctions;
+    const WorkaroundsGL &mWorkarounds;
+    StateManagerGL *mStateManager;
+    const gl::TextureCapsMap &mTextureCaps;
+
+    GLuint mRenderbufferID;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_RENDERBUFFERGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp
new file mode 100644
index 0000000..85d84cd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp
@@ -0,0 +1,668 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RendererGL.cpp: Implements the class methods for RendererGL.
+
+#include "libANGLE/renderer/gl/RendererGL.h"
+
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Path.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/BlitGL.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/CompilerGL.h"
+#include "libANGLE/renderer/gl/ContextGL.h"
+#include "libANGLE/renderer/gl/FenceNVGL.h"
+#include "libANGLE/renderer/gl/FenceSyncGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/PathGL.h"
+#include "libANGLE/renderer/gl/ProgramGL.h"
+#include "libANGLE/renderer/gl/QueryGL.h"
+#include "libANGLE/renderer/gl/RenderbufferGL.h"
+#include "libANGLE/renderer/gl/SamplerGL.h"
+#include "libANGLE/renderer/gl/ShaderGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
+#include "libANGLE/renderer/gl/VertexArrayGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace
+{
+
+std::vector<GLuint> GatherPaths(const std::vector<gl::Path *> &paths)
+{
+    std::vector<GLuint> ret;
+    ret.reserve(paths.size());
+
+    for (const auto *p : paths)
+    {
+        const auto *pathObj = rx::GetImplAs<rx::PathGL>(p);
+        ret.push_back(pathObj->getPathID());
+    }
+    return ret;
+}
+
+}  // namespace
+
+#ifndef NDEBUG
+static void INTERNAL_GL_APIENTRY LogGLDebugMessage(GLenum source,
+                                                   GLenum type,
+                                                   GLuint id,
+                                                   GLenum severity,
+                                                   GLsizei length,
+                                                   const GLchar *message,
+                                                   const void *userParam)
+{
+    std::string sourceText;
+    switch (source)
+    {
+        case GL_DEBUG_SOURCE_API:
+            sourceText = "OpenGL";
+            break;
+        case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+            sourceText = "Windows";
+            break;
+        case GL_DEBUG_SOURCE_SHADER_COMPILER:
+            sourceText = "Shader Compiler";
+            break;
+        case GL_DEBUG_SOURCE_THIRD_PARTY:
+            sourceText = "Third Party";
+            break;
+        case GL_DEBUG_SOURCE_APPLICATION:
+            sourceText = "Application";
+            break;
+        case GL_DEBUG_SOURCE_OTHER:
+            sourceText = "Other";
+            break;
+        default:
+            sourceText = "UNKNOWN";
+            break;
+    }
+
+    std::string typeText;
+    switch (type)
+    {
+        case GL_DEBUG_TYPE_ERROR:
+            typeText = "Error";
+            break;
+        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+            typeText = "Deprecated behavior";
+            break;
+        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+            typeText = "Undefined behavior";
+            break;
+        case GL_DEBUG_TYPE_PORTABILITY:
+            typeText = "Portability";
+            break;
+        case GL_DEBUG_TYPE_PERFORMANCE:
+            typeText = "Performance";
+            break;
+        case GL_DEBUG_TYPE_OTHER:
+            typeText = "Other";
+            break;
+        case GL_DEBUG_TYPE_MARKER:
+            typeText = "Marker";
+            break;
+        default:
+            typeText = "UNKNOWN";
+            break;
+    }
+
+    std::string severityText;
+    switch (severity)
+    {
+        case GL_DEBUG_SEVERITY_HIGH:
+            severityText = "High";
+            break;
+        case GL_DEBUG_SEVERITY_MEDIUM:
+            severityText = "Medium";
+            break;
+        case GL_DEBUG_SEVERITY_LOW:
+            severityText = "Low";
+            break;
+        case GL_DEBUG_SEVERITY_NOTIFICATION:
+            severityText = "Notification";
+            break;
+        default:
+            severityText = "UNKNOWN";
+            break;
+    }
+
+    if (type == GL_DEBUG_TYPE_ERROR)
+    {
+        ERR() << std::endl
+              << "\tSource: " << sourceText << std::endl
+              << "\tType: " << typeText << std::endl
+              << "\tID: " << gl::Error(id) << std::endl
+              << "\tSeverity: " << severityText << std::endl
+              << "\tMessage: " << message;
+    }
+    else
+    {
+        // TODO(ynovikov): filter into WARN and INFO if INFO is ever implemented
+        WARN() << std::endl
+               << "\tSource: " << sourceText << std::endl
+               << "\tType: " << typeText << std::endl
+               << "\tID: " << gl::Error(id) << std::endl
+               << "\tSeverity: " << severityText << std::endl
+               << "\tMessage: " << message;
+    }
+}
+#endif
+
+namespace rx
+{
+
+RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &attribMap)
+    : mMaxSupportedESVersion(0, 0),
+      mFunctions(functions),
+      mStateManager(nullptr),
+      mBlitter(nullptr),
+      mHasDebugOutput(false),
+      mSkipDrawCalls(false),
+      mCapsInitialized(false)
+{
+    ASSERT(mFunctions);
+    nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds);
+    mStateManager = new StateManagerGL(mFunctions, getNativeCaps());
+    mBlitter      = new BlitGL(functions, mWorkarounds, mStateManager);
+
+    mHasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) ||
+                      mFunctions->hasGLExtension("GL_KHR_debug") ||
+                      mFunctions->isAtLeastGLES(gl::Version(3, 2)) ||
+                      mFunctions->hasGLESExtension("GL_KHR_debug");
+#ifndef NDEBUG
+    if (mHasDebugOutput)
+    {
+        mFunctions->enable(GL_DEBUG_OUTPUT);
+        mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+        mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0,
+                                        nullptr, GL_TRUE);
+        mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0,
+                                        nullptr, GL_TRUE);
+        mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0,
+                                        nullptr, GL_FALSE);
+        mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION,
+                                        0, nullptr, GL_FALSE);
+        mFunctions->debugMessageCallback(&LogGLDebugMessage, nullptr);
+    }
+#endif
+
+    EGLint deviceType =
+        static_cast<EGLint>(attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_NONE));
+    if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
+    {
+        mSkipDrawCalls = true;
+    }
+
+    if (mWorkarounds.initializeCurrentVertexAttributes)
+    {
+        GLint maxVertexAttribs = 0;
+        mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
+
+        for (GLint i = 0; i < maxVertexAttribs; ++i)
+        {
+            mFunctions->vertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 1.0f);
+        }
+    }
+}
+
+RendererGL::~RendererGL()
+{
+    SafeDelete(mBlitter);
+    SafeDelete(mStateManager);
+}
+
+gl::Error RendererGL::flush()
+{
+    mFunctions->flush();
+    return gl::NoError();
+}
+
+gl::Error RendererGL::finish()
+{
+#ifdef NDEBUG
+    if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput)
+    {
+        mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+    }
+#endif
+
+    mFunctions->finish();
+
+#ifdef NDEBUG
+    if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput)
+    {
+        mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+    }
+#endif
+
+    return gl::NoError();
+}
+
+gl::Error RendererGL::drawArrays(const gl::ContextState &data,
+                                 GLenum mode,
+                                 GLint first,
+                                 GLsizei count)
+{
+    ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, 0));
+
+    if (!mSkipDrawCalls)
+    {
+        mFunctions->drawArrays(mode, first, count);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error RendererGL::drawArraysInstanced(const gl::ContextState &data,
+                                          GLenum mode,
+                                          GLint first,
+                                          GLsizei count,
+                                          GLsizei instanceCount)
+{
+    ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, instanceCount));
+
+    if (!mSkipDrawCalls)
+    {
+        mFunctions->drawArraysInstanced(mode, first, count, instanceCount);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error RendererGL::drawElements(const gl::ContextState &data,
+                                   GLenum mode,
+                                   GLsizei count,
+                                   GLenum type,
+                                   const void *indices,
+                                   const gl::IndexRange &indexRange)
+{
+    const void *drawIndexPtr = nullptr;
+    ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPtr));
+
+    if (!mSkipDrawCalls)
+    {
+        mFunctions->drawElements(mode, count, type, drawIndexPtr);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error RendererGL::drawElementsInstanced(const gl::ContextState &data,
+                                            GLenum mode,
+                                            GLsizei count,
+                                            GLenum type,
+                                            const void *indices,
+                                            GLsizei instances,
+                                            const gl::IndexRange &indexRange)
+{
+    const void *drawIndexPointer = nullptr;
+    ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, instances,
+                                                  &drawIndexPointer));
+
+    if (!mSkipDrawCalls)
+    {
+        mFunctions->drawElementsInstanced(mode, count, type, drawIndexPointer, instances);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error RendererGL::drawRangeElements(const gl::ContextState &data,
+                                        GLenum mode,
+                                        GLuint start,
+                                        GLuint end,
+                                        GLsizei count,
+                                        GLenum type,
+                                        const void *indices,
+                                        const gl::IndexRange &indexRange)
+{
+    const void *drawIndexPointer = nullptr;
+    ANGLE_TRY(
+        mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPointer));
+
+    if (!mSkipDrawCalls)
+    {
+        mFunctions->drawRangeElements(mode, start, end, count, type, drawIndexPointer);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error RendererGL::drawArraysIndirect(const gl::ContextState &data,
+                                         GLenum mode,
+                                         const void *indirect)
+{
+    ANGLE_TRY(mStateManager->setDrawIndirectState(data, GL_NONE));
+
+    if (!mSkipDrawCalls)
+    {
+        mFunctions->drawArraysIndirect(mode, indirect);
+    }
+    return gl::NoError();
+}
+
+gl::Error RendererGL::drawElementsIndirect(const gl::ContextState &data,
+                                           GLenum mode,
+                                           GLenum type,
+                                           const void *indirect)
+{
+    ANGLE_TRY(mStateManager->setDrawIndirectState(data, type));
+
+    if (!mSkipDrawCalls)
+    {
+        mFunctions->drawElementsIndirect(mode, type, indirect);
+    }
+    return gl::NoError();
+}
+
+void RendererGL::stencilFillPath(const gl::ContextState &state,
+                                 const gl::Path *path,
+                                 GLenum fillMode,
+                                 GLuint mask)
+{
+    const auto *pathObj = GetImplAs<PathGL>(path);
+
+    mFunctions->stencilFillPathNV(pathObj->getPathID(), fillMode, mask);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::stencilStrokePath(const gl::ContextState &state,
+                                   const gl::Path *path,
+                                   GLint reference,
+                                   GLuint mask)
+{
+    const auto *pathObj = GetImplAs<PathGL>(path);
+
+    mFunctions->stencilStrokePathNV(pathObj->getPathID(), reference, mask);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::coverFillPath(const gl::ContextState &state,
+                               const gl::Path *path,
+                               GLenum coverMode)
+{
+
+    const auto *pathObj = GetImplAs<PathGL>(path);
+    mFunctions->coverFillPathNV(pathObj->getPathID(), coverMode);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::coverStrokePath(const gl::ContextState &state,
+                                 const gl::Path *path,
+                                 GLenum coverMode)
+{
+    const auto *pathObj = GetImplAs<PathGL>(path);
+    mFunctions->coverStrokePathNV(pathObj->getPathID(), coverMode);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::stencilThenCoverFillPath(const gl::ContextState &state,
+                                          const gl::Path *path,
+                                          GLenum fillMode,
+                                          GLuint mask,
+                                          GLenum coverMode)
+{
+
+    const auto *pathObj = GetImplAs<PathGL>(path);
+    mFunctions->stencilThenCoverFillPathNV(pathObj->getPathID(), fillMode, mask, coverMode);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::stencilThenCoverStrokePath(const gl::ContextState &state,
+                                            const gl::Path *path,
+                                            GLint reference,
+                                            GLuint mask,
+                                            GLenum coverMode)
+{
+
+    const auto *pathObj = GetImplAs<PathGL>(path);
+    mFunctions->stencilThenCoverStrokePathNV(pathObj->getPathID(), reference, mask, coverMode);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::coverFillPathInstanced(const gl::ContextState &state,
+                                        const std::vector<gl::Path *> &paths,
+                                        GLenum coverMode,
+                                        GLenum transformType,
+                                        const GLfloat *transformValues)
+{
+    const auto &pathObjs = GatherPaths(paths);
+
+    mFunctions->coverFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
+                                         &pathObjs[0], 0, coverMode, transformType,
+                                         transformValues);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+void RendererGL::coverStrokePathInstanced(const gl::ContextState &state,
+                                          const std::vector<gl::Path *> &paths,
+                                          GLenum coverMode,
+                                          GLenum transformType,
+                                          const GLfloat *transformValues)
+{
+    const auto &pathObjs = GatherPaths(paths);
+
+    mFunctions->coverStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
+                                           &pathObjs[0], 0, coverMode, transformType,
+                                           transformValues);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+void RendererGL::stencilFillPathInstanced(const gl::ContextState &state,
+                                          const std::vector<gl::Path *> &paths,
+                                          GLenum fillMode,
+                                          GLuint mask,
+                                          GLenum transformType,
+                                          const GLfloat *transformValues)
+{
+    const auto &pathObjs = GatherPaths(paths);
+
+    mFunctions->stencilFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
+                                           &pathObjs[0], 0, fillMode, mask, transformType,
+                                           transformValues);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+void RendererGL::stencilStrokePathInstanced(const gl::ContextState &state,
+                                            const std::vector<gl::Path *> &paths,
+                                            GLint reference,
+                                            GLuint mask,
+                                            GLenum transformType,
+                                            const GLfloat *transformValues)
+{
+    const auto &pathObjs = GatherPaths(paths);
+
+    mFunctions->stencilStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
+                                             &pathObjs[0], 0, reference, mask, transformType,
+                                             transformValues);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::stencilThenCoverFillPathInstanced(const gl::ContextState &state,
+                                                   const std::vector<gl::Path *> &paths,
+                                                   GLenum coverMode,
+                                                   GLenum fillMode,
+                                                   GLuint mask,
+                                                   GLenum transformType,
+                                                   const GLfloat *transformValues)
+{
+    const auto &pathObjs = GatherPaths(paths);
+
+    mFunctions->stencilThenCoverFillPathInstancedNV(
+        static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, fillMode, mask,
+        coverMode, transformType, transformValues);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+void RendererGL::stencilThenCoverStrokePathInstanced(const gl::ContextState &state,
+                                                     const std::vector<gl::Path *> &paths,
+                                                     GLenum coverMode,
+                                                     GLint reference,
+                                                     GLuint mask,
+                                                     GLenum transformType,
+                                                     const GLfloat *transformValues)
+{
+    const auto &pathObjs = GatherPaths(paths);
+
+    mFunctions->stencilThenCoverStrokePathInstancedNV(
+        static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, reference, mask,
+        coverMode, transformType, transformValues);
+
+    ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+GLenum RendererGL::getResetStatus()
+{
+    return mFunctions->getGraphicsResetStatus();
+}
+
+ContextImpl *RendererGL::createContext(const gl::ContextState &state)
+{
+    return new ContextGL(state, this);
+}
+
+void RendererGL::insertEventMarker(GLsizei length, const char *marker)
+{
+    mFunctions->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
+                                   GL_DEBUG_SEVERITY_NOTIFICATION, length, marker);
+}
+
+void RendererGL::pushGroupMarker(GLsizei length, const char *marker)
+{
+    mFunctions->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, length, marker);
+}
+
+void RendererGL::popGroupMarker()
+{
+    mFunctions->popDebugGroup();
+}
+
+std::string RendererGL::getVendorString() const
+{
+    return std::string(reinterpret_cast<const char *>(mFunctions->getString(GL_VENDOR)));
+}
+
+std::string RendererGL::getRendererDescription() const
+{
+    std::string nativeVendorString(
+        reinterpret_cast<const char *>(mFunctions->getString(GL_VENDOR)));
+    std::string nativeRendererString(
+        reinterpret_cast<const char *>(mFunctions->getString(GL_RENDERER)));
+
+    std::ostringstream rendererString;
+    rendererString << nativeVendorString << " " << nativeRendererString << " OpenGL";
+    if (mFunctions->standard == STANDARD_GL_ES)
+    {
+        rendererString << " ES";
+    }
+    rendererString << " " << mFunctions->version.major << "." << mFunctions->version.minor;
+    if (mFunctions->standard == STANDARD_GL_DESKTOP)
+    {
+        // Some drivers (NVIDIA) use a profile mask of 0 when in compatibility profile.
+        if ((mFunctions->profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0 ||
+            (mFunctions->isAtLeastGL(gl::Version(3, 2)) && mFunctions->profile == 0))
+        {
+            rendererString << " compatibility";
+        }
+        else if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+        {
+            rendererString << " core";
+        }
+    }
+
+    return rendererString.str();
+}
+
+const gl::Version &RendererGL::getMaxSupportedESVersion() const
+{
+    // Force generation of caps
+    getNativeCaps();
+
+    return mMaxSupportedESVersion;
+}
+
+void RendererGL::generateCaps(gl::Caps *outCaps,
+                              gl::TextureCapsMap *outTextureCaps,
+                              gl::Extensions *outExtensions,
+                              gl::Limitations * /* outLimitations */) const
+{
+    nativegl_gl::GenerateCaps(mFunctions, mWorkarounds, outCaps, outTextureCaps, outExtensions,
+                              &mMaxSupportedESVersion);
+}
+
+GLint RendererGL::getGPUDisjoint()
+{
+    // TODO(ewell): On GLES backends we should find a way to reliably query disjoint events
+    return 0;
+}
+
+GLint64 RendererGL::getTimestamp()
+{
+    GLint64 result = 0;
+    mFunctions->getInteger64v(GL_TIMESTAMP, &result);
+    return result;
+}
+
+void RendererGL::ensureCapsInitialized() const
+{
+    if (!mCapsInitialized)
+    {
+        generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
+        mCapsInitialized = true;
+    }
+}
+
+const gl::Caps &RendererGL::getNativeCaps() const
+{
+    ensureCapsInitialized();
+    return mNativeCaps;
+}
+
+const gl::TextureCapsMap &RendererGL::getNativeTextureCaps() const
+{
+    ensureCapsInitialized();
+    return mNativeTextureCaps;
+}
+
+const gl::Extensions &RendererGL::getNativeExtensions() const
+{
+    ensureCapsInitialized();
+    return mNativeExtensions;
+}
+
+const gl::Limitations &RendererGL::getNativeLimitations() const
+{
+    ensureCapsInitialized();
+    return mNativeLimitations;
+}
+
+gl::Error RendererGL::dispatchCompute(const gl::ContextState &data,
+                                      GLuint numGroupsX,
+                                      GLuint numGroupsY,
+                                      GLuint numGroupsZ)
+{
+    ANGLE_TRY(mStateManager->setDispatchComputeState(data));
+    mFunctions->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h
new file mode 100644
index 0000000..82539f7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h
@@ -0,0 +1,204 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RendererGL.h: Defines the class interface for RendererGL.
+
+#ifndef LIBANGLE_RENDERER_GL_RENDERERGL_H_
+#define LIBANGLE_RENDERER_GL_RENDERERGL_H_
+
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+
+namespace gl
+{
+class ContextState;
+struct IndexRange;
+class Path;
+}
+
+namespace egl
+{
+class AttributeMap;
+}
+
+namespace sh
+{
+struct BlockMemberInfo;
+}
+
+namespace rx
+{
+class BlitGL;
+class ContextImpl;
+class FunctionsGL;
+class StateManagerGL;
+
+class RendererGL : angle::NonCopyable
+{
+  public:
+    RendererGL(const FunctionsGL *functions, const egl::AttributeMap &attribMap);
+    ~RendererGL();
+
+    ContextImpl *createContext(const gl::ContextState &state);
+
+    gl::Error flush();
+    gl::Error finish();
+
+    gl::Error drawArrays(const gl::ContextState &data, GLenum mode, GLint first, GLsizei count);
+    gl::Error drawArraysInstanced(const gl::ContextState &data,
+                                  GLenum mode,
+                                  GLint first,
+                                  GLsizei count,
+                                  GLsizei instanceCount);
+
+    gl::Error drawElements(const gl::ContextState &data,
+                           GLenum mode,
+                           GLsizei count,
+                           GLenum type,
+                           const void *indices,
+                           const gl::IndexRange &indexRange);
+    gl::Error drawElementsInstanced(const gl::ContextState &data,
+                                    GLenum mode,
+                                    GLsizei count,
+                                    GLenum type,
+                                    const void *indices,
+                                    GLsizei instances,
+                                    const gl::IndexRange &indexRange);
+    gl::Error drawRangeElements(const gl::ContextState &data,
+                                GLenum mode,
+                                GLuint start,
+                                GLuint end,
+                                GLsizei count,
+                                GLenum type,
+                                const void *indices,
+                                const gl::IndexRange &indexRange);
+    gl::Error drawArraysIndirect(const gl::ContextState &data, GLenum mode, const void *indirect);
+    gl::Error drawElementsIndirect(const gl::ContextState &data,
+                                   GLenum mode,
+                                   GLenum type,
+                                   const void *indirect);
+
+    // CHROMIUM_path_rendering implementation
+    void stencilFillPath(const gl::ContextState &state,
+                         const gl::Path *path,
+                         GLenum fillMode,
+                         GLuint mask);
+    void stencilStrokePath(const gl::ContextState &state,
+                           const gl::Path *path,
+                           GLint reference,
+                           GLuint mask);
+    void coverFillPath(const gl::ContextState &state, const gl::Path *path, GLenum coverMode);
+    void coverStrokePath(const gl::ContextState &state, const gl::Path *path, GLenum coverMode);
+    void stencilThenCoverFillPath(const gl::ContextState &state,
+                                  const gl::Path *path,
+                                  GLenum fillMode,
+                                  GLuint mask,
+                                  GLenum coverMode);
+    void stencilThenCoverStrokePath(const gl::ContextState &state,
+                                    const gl::Path *path,
+                                    GLint reference,
+                                    GLuint mask,
+                                    GLenum coverMode);
+    void coverFillPathInstanced(const gl::ContextState &state,
+                                const std::vector<gl::Path *> &paths,
+                                GLenum coverMode,
+                                GLenum transformType,
+                                const GLfloat *transformValues);
+    void coverStrokePathInstanced(const gl::ContextState &state,
+                                  const std::vector<gl::Path *> &paths,
+                                  GLenum coverMode,
+                                  GLenum transformType,
+                                  const GLfloat *transformValues);
+    void stencilFillPathInstanced(const gl::ContextState &state,
+                                  const std::vector<gl::Path *> &paths,
+                                  GLenum fillMode,
+                                  GLuint mask,
+                                  GLenum transformType,
+                                  const GLfloat *transformValues);
+    void stencilStrokePathInstanced(const gl::ContextState &state,
+                                    const std::vector<gl::Path *> &paths,
+                                    GLint reference,
+                                    GLuint mask,
+                                    GLenum transformType,
+                                    const GLfloat *transformValues);
+
+    void stencilThenCoverFillPathInstanced(const gl::ContextState &state,
+                                           const std::vector<gl::Path *> &paths,
+                                           GLenum coverMode,
+                                           GLenum fillMode,
+                                           GLuint mask,
+                                           GLenum transformType,
+                                           const GLfloat *transformValues);
+    void stencilThenCoverStrokePathInstanced(const gl::ContextState &state,
+                                             const std::vector<gl::Path *> &paths,
+                                             GLenum coverMode,
+                                             GLint reference,
+                                             GLuint mask,
+                                             GLenum transformType,
+                                             const GLfloat *transformValues);
+
+    GLenum getResetStatus();
+
+    // EXT_debug_marker
+    void insertEventMarker(GLsizei length, const char *marker);
+    void pushGroupMarker(GLsizei length, const char *marker);
+    void popGroupMarker();
+
+    std::string getVendorString() const;
+    std::string getRendererDescription() const;
+
+    GLint getGPUDisjoint();
+    GLint64 getTimestamp();
+
+    const gl::Version &getMaxSupportedESVersion() const;
+    const FunctionsGL *getFunctions() const { return mFunctions; }
+    StateManagerGL *getStateManager() const { return mStateManager; }
+    const WorkaroundsGL &getWorkarounds() const { return mWorkarounds; }
+    BlitGL *getBlitter() const { return mBlitter; }
+
+    const gl::Caps &getNativeCaps() const;
+    const gl::TextureCapsMap &getNativeTextureCaps() const;
+    const gl::Extensions &getNativeExtensions() const;
+    const gl::Limitations &getNativeLimitations() const;
+
+    gl::Error dispatchCompute(const gl::ContextState &data,
+                              GLuint numGroupsX,
+                              GLuint numGroupsY,
+                              GLuint numGroupsZ);
+
+  private:
+    void ensureCapsInitialized() const;
+    void generateCaps(gl::Caps *outCaps,
+                      gl::TextureCapsMap *outTextureCaps,
+                      gl::Extensions *outExtensions,
+                      gl::Limitations *outLimitations) const;
+
+    mutable gl::Version mMaxSupportedESVersion;
+
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+
+    BlitGL *mBlitter;
+
+    WorkaroundsGL mWorkarounds;
+
+    bool mHasDebugOutput;
+
+    // For performance debugging
+    bool mSkipDrawCalls;
+
+    mutable bool mCapsInitialized;
+    mutable gl::Caps mNativeCaps;
+    mutable gl::TextureCapsMap mNativeTextureCaps;
+    mutable gl::Extensions mNativeExtensions;
+    mutable gl::Limitations mNativeLimitations;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_RENDERERGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/SamplerGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/SamplerGL.cpp
new file mode 100644
index 0000000..2a6d815
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/SamplerGL.cpp
@@ -0,0 +1,73 @@
+//
+// 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.
+//
+
+// SamplerGL.cpp: Defines the rx::SamplerGL class, an implementation of SamplerImpl.
+
+#include "libANGLE/renderer/gl/SamplerGL.h"
+
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+namespace
+{
+
+template <typename T>
+static inline void SyncSamplerStateMember(const rx::FunctionsGL *functions,
+                                          GLuint sampler,
+                                          const gl::SamplerState &newState,
+                                          gl::SamplerState &curState,
+                                          GLenum name,
+                                          T(gl::SamplerState::*samplerMember))
+{
+    if (curState.*samplerMember != newState.*samplerMember)
+    {
+        curState.*samplerMember = newState.*samplerMember;
+        functions->samplerParameterf(sampler, name, static_cast<GLfloat>(curState.*samplerMember));
+    }
+}
+}
+
+namespace rx
+{
+
+SamplerGL::SamplerGL(const FunctionsGL *functions, StateManagerGL *stateManager)
+    : SamplerImpl(),
+      mFunctions(functions),
+      mStateManager(stateManager),
+      mAppliedSamplerState(),
+      mSamplerID(0)
+{
+    mFunctions->genSamplers(1, &mSamplerID);
+}
+
+SamplerGL::~SamplerGL()
+{
+    mStateManager->deleteSampler(mSamplerID);
+    mSamplerID = 0;
+}
+
+void SamplerGL::syncState(const gl::SamplerState &samplerState) const
+{
+    // clang-format off
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MIN_FILTER, &gl::SamplerState::minFilter);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAG_FILTER, &gl::SamplerState::magFilter);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_S, &gl::SamplerState::wrapS);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_T, &gl::SamplerState::wrapT);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_R, &gl::SamplerState::wrapR);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl::SamplerState::maxAnisotropy);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MIN_LOD, &gl::SamplerState::minLod);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
+    SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_SRGB_DECODE_EXT, &gl::SamplerState::sRGBDecode);
+    // clang-format on
+}
+
+GLuint SamplerGL::getSamplerID() const
+{
+    return mSamplerID;
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/SamplerGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/SamplerGL.h
new file mode 100644
index 0000000..c3fcfde
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/SamplerGL.h
@@ -0,0 +1,40 @@
+//
+// 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.
+//
+
+// SamplerGL.h: Defines the rx::SamplerGL class, an implementation of SamplerImpl.
+
+#ifndef LIBANGLE_RENDERER_GL_SAMPLERGL_H_
+#define LIBANGLE_RENDERER_GL_SAMPLERGL_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class SamplerGL : public SamplerImpl
+{
+  public:
+    SamplerGL(const FunctionsGL *functions, StateManagerGL *stateManager);
+    ~SamplerGL() override;
+
+    void syncState(const gl::SamplerState &samplerState) const;
+
+    GLuint getSamplerID() const;
+
+  private:
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+
+    mutable gl::SamplerState mAppliedSamplerState;
+    GLuint mSamplerID;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_GL_SAMPLERGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
new file mode 100644
index 0000000..8fc7d46
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
@@ -0,0 +1,153 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderGL.cpp: Implements the class methods for ShaderGL.
+
+#include "libANGLE/renderer/gl/ShaderGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+
+#include <iostream>
+
+namespace rx
+{
+
+ShaderGL::ShaderGL(const gl::ShaderState &data,
+                   const FunctionsGL *functions,
+                   const WorkaroundsGL &workarounds)
+    : ShaderImpl(data), mFunctions(functions), mWorkarounds(workarounds), mShaderID(0)
+{
+    ASSERT(mFunctions);
+}
+
+ShaderGL::~ShaderGL()
+{
+    if (mShaderID != 0)
+    {
+        mFunctions->deleteShader(mShaderID);
+        mShaderID = 0;
+    }
+}
+
+ShCompileOptions ShaderGL::prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+                                                         std::string * /*sourcePath*/)
+{
+    // Reset the previous state
+    if (mShaderID != 0)
+    {
+        mFunctions->deleteShader(mShaderID);
+        mShaderID = 0;
+    }
+
+    *sourceStream << mData.getSource();
+
+    ShCompileOptions options = SH_INIT_GL_POSITION;
+
+    if (mWorkarounds.doWhileGLSLCausesGPUHang)
+    {
+        options |= SH_REWRITE_DO_WHILE_LOOPS;
+    }
+
+    if (mWorkarounds.emulateAbsIntFunction)
+    {
+        options |= SH_EMULATE_ABS_INT_FUNCTION;
+    }
+
+    if (mWorkarounds.addAndTrueToLoopCondition)
+    {
+        options |= SH_ADD_AND_TRUE_TO_LOOP_CONDITION;
+    }
+
+    if (mWorkarounds.emulateIsnanFloat)
+    {
+        options |= SH_EMULATE_ISNAN_FLOAT_FUNCTION;
+    }
+
+    if (mWorkarounds.emulateAtan2Float)
+    {
+        options |= SH_EMULATE_ATAN2_FLOAT_FUNCTION;
+    }
+
+    if (mWorkarounds.useUnusedBlocksWithStandardOrSharedLayout)
+    {
+        options |= SH_USE_UNUSED_STANDARD_SHARED_BLOCKS;
+    }
+
+    if (mWorkarounds.dontRemoveInvariantForFragmentInput)
+    {
+        options |= SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT;
+    }
+
+    if (mWorkarounds.removeInvariantAndCentroidForESSL3)
+    {
+        options |= SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3;
+    }
+
+    if (mWorkarounds.rewriteFloatUnaryMinusOperator)
+    {
+        options |= SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR;
+    }
+
+    return options;
+}
+
+bool ShaderGL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
+{
+    // Translate the ESSL into GLSL
+    const char *translatedSourceCString = mData.getTranslatedSource().c_str();
+
+    // Generate a shader object and set the source
+    mShaderID = mFunctions->createShader(mData.getShaderType());
+    mFunctions->shaderSource(mShaderID, 1, &translatedSourceCString, nullptr);
+    mFunctions->compileShader(mShaderID);
+
+    // Check for compile errors from the native driver
+    GLint compileStatus = GL_FALSE;
+    mFunctions->getShaderiv(mShaderID, GL_COMPILE_STATUS, &compileStatus);
+    if (compileStatus == GL_FALSE)
+    {
+        // Compilation failed, put the error into the info log
+        GLint infoLogLength = 0;
+        mFunctions->getShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+        // Info log length includes the null terminator, so 1 means that the info log is an empty
+        // string.
+        if (infoLogLength > 1)
+        {
+            std::vector<char> buf(infoLogLength);
+            mFunctions->getShaderInfoLog(mShaderID, infoLogLength, nullptr, &buf[0]);
+
+            mFunctions->deleteShader(mShaderID);
+            mShaderID = 0;
+
+            *infoLog = &buf[0];
+            WARN() << std::endl << *infoLog;
+        }
+        else
+        {
+            WARN() << std::endl << "Shader compilation failed with no info log.";
+        }
+        return false;
+    }
+
+    return true;
+}
+
+std::string ShaderGL::getDebugInfo() const
+{
+    return mData.getTranslatedSource();
+}
+
+GLuint ShaderGL::getShaderID() const
+{
+    return mShaderID;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h
new file mode 100644
index 0000000..0ecd89c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h
@@ -0,0 +1,44 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderGL.h: Defines the class interface for ShaderGL.
+
+#ifndef LIBANGLE_RENDERER_GL_SHADERGL_H_
+#define LIBANGLE_RENDERER_GL_SHADERGL_H_
+
+#include "libANGLE/renderer/ShaderImpl.h"
+
+namespace rx
+{
+class FunctionsGL;
+struct WorkaroundsGL;
+
+class ShaderGL : public ShaderImpl
+{
+  public:
+    ShaderGL(const gl::ShaderState &data,
+             const FunctionsGL *functions,
+             const WorkaroundsGL &workarounds);
+    ~ShaderGL() override;
+
+    // ShaderImpl implementation
+    ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+                                                   std::string *sourcePath) override;
+    bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
+    std::string getDebugInfo() const override;
+
+    GLuint getShaderID() const;
+
+  private:
+    const FunctionsGL *mFunctions;
+    const WorkaroundsGL &mWorkarounds;
+
+    GLuint mShaderID;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_SHADERGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
new file mode 100644
index 0000000..2e5e58c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -0,0 +1,1832 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManagerGL.h: Defines a class for caching applied OpenGL state
+
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+#include <string.h>
+#include <limits>
+
+#include "common/bitset_utils.h"
+#include "common/mathutil.h"
+#include "common/matrix_utils.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/ProgramGL.h"
+#include "libANGLE/renderer/gl/QueryGL.h"
+#include "libANGLE/renderer/gl/SamplerGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
+#include "libANGLE/renderer/gl/VertexArrayGL.h"
+
+namespace rx
+{
+
+static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
+                                    GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED,
+                                    GL_COMMANDS_COMPLETED_CHROMIUM};
+
+StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0)
+{
+}
+
+StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &rendererCaps)
+    : mFunctions(functions),
+      mProgram(0),
+      mVAO(0),
+      mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
+      mBuffers(),
+      mIndexedBuffers(),
+      mTextureUnitIndex(0),
+      mTextures(),
+      mSamplers(rendererCaps.maxCombinedTextureImageUnits, 0),
+      mTransformFeedback(0),
+      mQueries(),
+      mPrevDrawTransformFeedback(nullptr),
+      mCurrentQueries(),
+      mPrevDrawContext(0),
+      mUnpackAlignment(4),
+      mUnpackRowLength(0),
+      mUnpackSkipRows(0),
+      mUnpackSkipPixels(0),
+      mUnpackImageHeight(0),
+      mUnpackSkipImages(0),
+      mPackAlignment(4),
+      mPackRowLength(0),
+      mPackSkipRows(0),
+      mPackSkipPixels(0),
+      mFramebuffers(angle::FramebufferBindingSingletonMax, 0),
+      mRenderbuffer(0),
+      mScissorTestEnabled(false),
+      mScissor(0, 0, 0, 0),
+      mViewport(0, 0, 0, 0),
+      mNear(0.0f),
+      mFar(1.0f),
+      mBlendEnabled(false),
+      mBlendColor(0, 0, 0, 0),
+      mSourceBlendRGB(GL_ONE),
+      mDestBlendRGB(GL_ZERO),
+      mSourceBlendAlpha(GL_ONE),
+      mDestBlendAlpha(GL_ZERO),
+      mBlendEquationRGB(GL_FUNC_ADD),
+      mBlendEquationAlpha(GL_FUNC_ADD),
+      mColorMaskRed(true),
+      mColorMaskGreen(true),
+      mColorMaskBlue(true),
+      mColorMaskAlpha(true),
+      mSampleAlphaToCoverageEnabled(false),
+      mSampleCoverageEnabled(false),
+      mSampleCoverageValue(1.0f),
+      mSampleCoverageInvert(false),
+      mDepthTestEnabled(false),
+      mDepthFunc(GL_LESS),
+      mDepthMask(true),
+      mStencilTestEnabled(false),
+      mStencilFrontFunc(GL_ALWAYS),
+      mStencilFrontRef(0),
+      mStencilFrontValueMask(static_cast<GLuint>(-1)),
+      mStencilFrontStencilFailOp(GL_KEEP),
+      mStencilFrontStencilPassDepthFailOp(GL_KEEP),
+      mStencilFrontStencilPassDepthPassOp(GL_KEEP),
+      mStencilFrontWritemask(static_cast<GLuint>(-1)),
+      mStencilBackFunc(GL_ALWAYS),
+      mStencilBackRef(0),
+      mStencilBackValueMask(static_cast<GLuint>(-1)),
+      mStencilBackStencilFailOp(GL_KEEP),
+      mStencilBackStencilPassDepthFailOp(GL_KEEP),
+      mStencilBackStencilPassDepthPassOp(GL_KEEP),
+      mStencilBackWritemask(static_cast<GLuint>(-1)),
+      mCullFaceEnabled(false),
+      mCullFace(GL_BACK),
+      mFrontFace(GL_CCW),
+      mPolygonOffsetFillEnabled(false),
+      mPolygonOffsetFactor(0.0f),
+      mPolygonOffsetUnits(0.0f),
+      mRasterizerDiscardEnabled(false),
+      mLineWidth(1.0f),
+      mPrimitiveRestartEnabled(false),
+      mClearColor(0.0f, 0.0f, 0.0f, 0.0f),
+      mClearDepth(1.0f),
+      mClearStencil(0),
+      mFramebufferSRGBEnabled(false),
+      mDitherEnabled(true),
+      mTextureCubemapSeamlessEnabled(false),
+      mMultisamplingEnabled(true),
+      mSampleAlphaToOneEnabled(false),
+      mCoverageModulation(GL_NONE),
+      mPathStencilFunc(GL_ALWAYS),
+      mPathStencilRef(0),
+      mPathStencilMask(std::numeric_limits<GLuint>::max()),
+      mLocalDirtyBits()
+{
+    ASSERT(mFunctions);
+
+    mTextures[GL_TEXTURE_2D].resize(rendererCaps.maxCombinedTextureImageUnits);
+    mTextures[GL_TEXTURE_CUBE_MAP].resize(rendererCaps.maxCombinedTextureImageUnits);
+    mTextures[GL_TEXTURE_2D_ARRAY].resize(rendererCaps.maxCombinedTextureImageUnits);
+    mTextures[GL_TEXTURE_3D].resize(rendererCaps.maxCombinedTextureImageUnits);
+    mTextures[GL_TEXTURE_2D_MULTISAMPLE].resize(rendererCaps.maxCombinedTextureImageUnits);
+
+    mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks);
+
+    for (GLenum queryType : QueryTypes)
+    {
+        mQueries[queryType] = 0;
+    }
+
+    // Initialize point sprite state for desktop GL
+    if (mFunctions->standard == STANDARD_GL_DESKTOP)
+    {
+        mFunctions->enable(GL_PROGRAM_POINT_SIZE);
+
+        // GL_POINT_SPRITE was deprecated in the core profile. Point rasterization is always
+        // performed
+        // as though POINT_SPRITE were enabled.
+        if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) == 0)
+        {
+            mFunctions->enable(GL_POINT_SPRITE);
+        }
+    }
+
+    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+}
+
+void StateManagerGL::deleteProgram(GLuint program)
+{
+    if (program != 0)
+    {
+        if (mProgram == program)
+        {
+            useProgram(0);
+        }
+
+        mFunctions->deleteProgram(program);
+    }
+}
+
+void StateManagerGL::deleteVertexArray(GLuint vao)
+{
+    if (vao != 0)
+    {
+        if (mVAO == vao)
+        {
+            bindVertexArray(0, 0);
+        }
+
+        mFunctions->deleteVertexArrays(1, &vao);
+    }
+}
+
+void StateManagerGL::deleteTexture(GLuint texture)
+{
+    if (texture != 0)
+    {
+        for (const auto &textureTypeIter : mTextures)
+        {
+            const std::vector<GLuint> &textureVector = textureTypeIter.second;
+            for (size_t textureUnitIndex = 0; textureUnitIndex < textureVector.size();
+                 textureUnitIndex++)
+            {
+                if (textureVector[textureUnitIndex] == texture)
+                {
+                    activeTexture(textureUnitIndex);
+                    bindTexture(textureTypeIter.first, 0);
+                }
+            }
+        }
+
+        mFunctions->deleteTextures(1, &texture);
+    }
+}
+
+void StateManagerGL::deleteSampler(GLuint sampler)
+{
+    if (sampler != 0)
+    {
+        for (size_t unit = 0; unit < mSamplers.size(); unit++)
+        {
+            if (mSamplers[unit] == sampler)
+            {
+                bindSampler(unit, 0);
+            }
+        }
+
+        mFunctions->deleteSamplers(1, &sampler);
+    }
+}
+
+void StateManagerGL::deleteBuffer(GLuint buffer)
+{
+    if (buffer != 0)
+    {
+        for (const auto &bufferTypeIter : mBuffers)
+        {
+            if (bufferTypeIter.second == buffer)
+            {
+                bindBuffer(bufferTypeIter.first, 0);
+            }
+        }
+
+        for (const auto &bufferTypeIter : mIndexedBuffers)
+        {
+            for (size_t bindIndex = 0; bindIndex < bufferTypeIter.second.size(); bindIndex++)
+            {
+                if (bufferTypeIter.second[bindIndex].buffer == buffer)
+                {
+                    bindBufferBase(bufferTypeIter.first, bindIndex, 0);
+                }
+            }
+        }
+
+        mFunctions->deleteBuffers(1, &buffer);
+    }
+}
+
+void StateManagerGL::deleteFramebuffer(GLuint fbo)
+{
+    if (fbo != 0)
+    {
+        for (size_t binding = 0; binding < mFramebuffers.size(); ++binding)
+        {
+            if (mFramebuffers[binding] == fbo)
+            {
+                GLenum enumValue = angle::FramebufferBindingToEnum(
+                    static_cast<angle::FramebufferBinding>(binding));
+                bindFramebuffer(enumValue, 0);
+            }
+            mFunctions->deleteFramebuffers(1, &fbo);
+        }
+    }
+}
+
+void StateManagerGL::deleteRenderbuffer(GLuint rbo)
+{
+    if (rbo != 0)
+    {
+        if (mRenderbuffer == rbo)
+        {
+            bindRenderbuffer(GL_RENDERBUFFER, 0);
+        }
+
+        mFunctions->deleteRenderbuffers(1, &rbo);
+    }
+}
+
+void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback)
+{
+    if (transformFeedback != 0)
+    {
+        if (mTransformFeedback == transformFeedback)
+        {
+            bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+        }
+
+        if (mPrevDrawTransformFeedback != nullptr &&
+            mPrevDrawTransformFeedback->getTransformFeedbackID() == transformFeedback)
+        {
+            mPrevDrawTransformFeedback = nullptr;
+        }
+
+        mFunctions->deleteTransformFeedbacks(1, &transformFeedback);
+    }
+}
+
+void StateManagerGL::deleteQuery(GLuint query)
+{
+    if (query != 0)
+    {
+        for (auto &activeQuery : mQueries)
+        {
+            GLuint activeQueryID = activeQuery.second;
+            if (activeQueryID == query)
+            {
+                GLenum type = activeQuery.first;
+                endQuery(type, query);
+            }
+        }
+    }
+}
+
+void StateManagerGL::useProgram(GLuint program)
+{
+    if (mProgram != program)
+    {
+        forceUseProgram(program);
+    }
+}
+
+void StateManagerGL::forceUseProgram(GLuint program)
+{
+    mProgram = program;
+    mFunctions->useProgram(mProgram);
+}
+
+void StateManagerGL::bindVertexArray(GLuint vao, GLuint elementArrayBuffer)
+{
+    if (mVAO != vao)
+    {
+        mVAO                              = vao;
+        mBuffers[GL_ELEMENT_ARRAY_BUFFER] = elementArrayBuffer;
+        mFunctions->bindVertexArray(vao);
+    }
+}
+
+void StateManagerGL::bindBuffer(GLenum type, GLuint buffer)
+{
+    if (mBuffers[type] != buffer)
+    {
+        mBuffers[type] = buffer;
+        mFunctions->bindBuffer(type, buffer);
+    }
+}
+
+void StateManagerGL::bindBufferBase(GLenum type, size_t index, GLuint buffer)
+{
+    auto &binding = mIndexedBuffers[type][index];
+    if (binding.buffer != buffer || binding.offset != static_cast<size_t>(-1) ||
+        binding.size != static_cast<size_t>(-1))
+    {
+        binding.buffer = buffer;
+        binding.offset = static_cast<size_t>(-1);
+        binding.size   = static_cast<size_t>(-1);
+        mFunctions->bindBufferBase(type, static_cast<GLuint>(index), buffer);
+    }
+}
+
+void StateManagerGL::bindBufferRange(GLenum type,
+                                     size_t index,
+                                     GLuint buffer,
+                                     size_t offset,
+                                     size_t size)
+{
+    auto &binding = mIndexedBuffers[type][index];
+    if (binding.buffer != buffer || binding.offset != offset || binding.size != size)
+    {
+        binding.buffer = buffer;
+        binding.offset = offset;
+        binding.size   = size;
+        mFunctions->bindBufferRange(type, static_cast<GLuint>(index), buffer, offset, size);
+    }
+}
+
+void StateManagerGL::activeTexture(size_t unit)
+{
+    if (mTextureUnitIndex != unit)
+    {
+        mTextureUnitIndex = unit;
+        mFunctions->activeTexture(GL_TEXTURE0 + static_cast<GLenum>(mTextureUnitIndex));
+    }
+}
+
+void StateManagerGL::bindTexture(GLenum type, GLuint texture)
+{
+    if (mTextures[type][mTextureUnitIndex] != texture)
+    {
+        mTextures[type][mTextureUnitIndex] = texture;
+        mFunctions->bindTexture(type, texture);
+    }
+}
+
+void StateManagerGL::bindSampler(size_t unit, GLuint sampler)
+{
+    if (mSamplers[unit] != sampler)
+    {
+        mSamplers[unit] = sampler;
+        mFunctions->bindSampler(static_cast<GLuint>(unit), sampler);
+    }
+}
+
+void StateManagerGL::setPixelUnpackState(const gl::PixelUnpackState &unpack)
+{
+    GLuint unpackBufferID          = 0;
+    const gl::Buffer *unpackBuffer = unpack.pixelBuffer.get();
+    if (unpackBuffer != nullptr)
+    {
+        unpackBufferID = GetImplAs<BufferGL>(unpackBuffer)->getBufferID();
+    }
+    setPixelUnpackState(unpack.alignment, unpack.rowLength, unpack.skipRows, unpack.skipPixels,
+                        unpack.imageHeight, unpack.skipImages, unpackBufferID);
+}
+
+void StateManagerGL::setPixelUnpackState(GLint alignment,
+                                         GLint rowLength,
+                                         GLint skipRows,
+                                         GLint skipPixels,
+                                         GLint imageHeight,
+                                         GLint skipImages,
+                                         GLuint unpackBuffer)
+{
+    if (mUnpackAlignment != alignment)
+    {
+        mUnpackAlignment = alignment;
+        mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, mUnpackAlignment);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ALIGNMENT);
+    }
+
+    if (mUnpackRowLength != rowLength)
+    {
+        mUnpackRowLength = rowLength;
+        mFunctions->pixelStorei(GL_UNPACK_ROW_LENGTH, mUnpackRowLength);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH);
+    }
+
+    if (mUnpackSkipRows != skipRows)
+    {
+        mUnpackSkipRows = skipRows;
+        mFunctions->pixelStorei(GL_UNPACK_SKIP_ROWS, mUnpackSkipRows);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS);
+    }
+
+    if (mUnpackSkipPixels != skipPixels)
+    {
+        mUnpackSkipPixels = skipPixels;
+        mFunctions->pixelStorei(GL_UNPACK_SKIP_PIXELS, mUnpackSkipPixels);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS);
+    }
+
+    if (mUnpackImageHeight != imageHeight)
+    {
+        mUnpackImageHeight = imageHeight;
+        mFunctions->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, mUnpackImageHeight);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+    }
+
+    if (mUnpackSkipImages != skipImages)
+    {
+        mUnpackSkipImages = skipImages;
+        mFunctions->pixelStorei(GL_UNPACK_SKIP_IMAGES, mUnpackSkipImages);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES);
+    }
+
+    bindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
+}
+
+void StateManagerGL::setPixelPackState(const gl::PixelPackState &pack)
+{
+    GLuint packBufferID          = 0;
+    const gl::Buffer *packBuffer = pack.pixelBuffer.get();
+    if (packBuffer != nullptr)
+    {
+        packBufferID = GetImplAs<BufferGL>(packBuffer)->getBufferID();
+    }
+    setPixelPackState(pack.alignment, pack.rowLength, pack.skipRows, pack.skipPixels, packBufferID);
+}
+
+void StateManagerGL::setPixelPackState(GLint alignment,
+                                       GLint rowLength,
+                                       GLint skipRows,
+                                       GLint skipPixels,
+                                       GLuint packBuffer)
+{
+    if (mPackAlignment != alignment)
+    {
+        mPackAlignment = alignment;
+        mFunctions->pixelStorei(GL_PACK_ALIGNMENT, mPackAlignment);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_ALIGNMENT);
+    }
+
+    if (mPackRowLength != rowLength)
+    {
+        mPackRowLength = rowLength;
+        mFunctions->pixelStorei(GL_PACK_ROW_LENGTH, mPackRowLength);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH);
+    }
+
+    if (mPackSkipRows != skipRows)
+    {
+        mPackSkipRows = skipRows;
+        mFunctions->pixelStorei(GL_PACK_SKIP_ROWS, mPackSkipRows);
+
+        // TODO: set dirty bit once one exists
+    }
+
+    if (mPackSkipPixels != skipPixels)
+    {
+        mPackSkipPixels = skipPixels;
+        mFunctions->pixelStorei(GL_PACK_SKIP_PIXELS, mPackSkipPixels);
+
+        // TODO: set dirty bit once one exists
+    }
+
+    bindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer);
+}
+
+void StateManagerGL::bindFramebuffer(GLenum type, GLuint framebuffer)
+{
+    if (type == GL_FRAMEBUFFER)
+    {
+        if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer ||
+            mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
+        {
+            mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
+            mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
+            mFunctions->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+        }
+    }
+    else
+    {
+        angle::FramebufferBinding binding = angle::EnumToFramebufferBinding(type);
+
+        if (mFramebuffers[binding] != framebuffer)
+        {
+            mFramebuffers[binding] = framebuffer;
+            mFunctions->bindFramebuffer(type, framebuffer);
+        }
+    }
+}
+
+void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer)
+{
+    ASSERT(type == GL_RENDERBUFFER);
+    if (mRenderbuffer != renderbuffer)
+    {
+        mRenderbuffer = renderbuffer;
+        mFunctions->bindRenderbuffer(type, mRenderbuffer);
+    }
+}
+
+void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
+{
+    ASSERT(type == GL_TRANSFORM_FEEDBACK);
+    if (mTransformFeedback != transformFeedback)
+    {
+        // Pause the current transform feedback if one is active.
+        // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform
+        // feedback at any time, even if there is one active.
+        if (mPrevDrawTransformFeedback != nullptr &&
+            mPrevDrawTransformFeedback->getTransformFeedbackID() != transformFeedback)
+        {
+            mPrevDrawTransformFeedback->syncPausedState(true);
+            mPrevDrawTransformFeedback = nullptr;
+        }
+
+        mTransformFeedback = transformFeedback;
+        mFunctions->bindTransformFeedback(type, mTransformFeedback);
+    }
+}
+
+void StateManagerGL::beginQuery(GLenum type, GLuint query)
+{
+    // Make sure this is a valid query type and there is no current active query of this type
+    ASSERT(mQueries.find(type) != mQueries.end());
+    ASSERT(mQueries[type] == 0);
+    ASSERT(query != 0);
+
+    mQueries[type] = query;
+    mFunctions->beginQuery(type, query);
+}
+
+void StateManagerGL::endQuery(GLenum type, GLuint query)
+{
+    ASSERT(mQueries[type] == query);
+    mQueries[type] = 0;
+    mFunctions->endQuery(type);
+}
+
+void StateManagerGL::onBeginQuery(QueryGL *query)
+{
+    mCurrentQueries.insert(query);
+}
+
+void StateManagerGL::onDeleteQueryObject(QueryGL *query)
+{
+    mCurrentQueries.erase(query);
+}
+
+gl::Error StateManagerGL::setDrawArraysState(const gl::ContextState &data,
+                                             GLint first,
+                                             GLsizei count,
+                                             GLsizei instanceCount)
+{
+    const gl::State &state = data.getState();
+
+    const gl::Program *program = state.getProgram();
+
+    const gl::VertexArray *vao = state.getVertexArray();
+    const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
+
+    gl::Error error = vaoGL->syncDrawArraysState(program->getActiveAttribLocationsMask(), first,
+                                                 count, instanceCount);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
+
+    return setGenericDrawState(data);
+}
+
+gl::Error StateManagerGL::setDrawElementsState(const gl::ContextState &data,
+                                               GLsizei count,
+                                               GLenum type,
+                                               const void *indices,
+                                               GLsizei instanceCount,
+                                               const void **outIndices)
+{
+    const gl::State &state = data.getState();
+
+    const gl::Program *program = state.getProgram();
+
+    const gl::VertexArray *vao = state.getVertexArray();
+    const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
+
+    gl::Error error =
+        vaoGL->syncDrawElementsState(program->getActiveAttribLocationsMask(), count, type, indices,
+                                     instanceCount, state.isPrimitiveRestartEnabled(), outIndices);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
+
+    return setGenericDrawState(data);
+}
+
+gl::Error StateManagerGL::setDrawIndirectState(const gl::ContextState &data, GLenum type)
+{
+    const gl::State &state = data.getState();
+
+    const gl::VertexArray *vao = state.getVertexArray();
+    const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
+
+    if (type != GL_NONE)
+    {
+        ANGLE_TRY(vaoGL->syncElementArrayState());
+    }
+    bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
+
+    gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
+    ASSERT(drawIndirectBuffer);
+    const BufferGL *bufferGL = GetImplAs<BufferGL>(drawIndirectBuffer);
+    bindBuffer(GL_DRAW_INDIRECT_BUFFER, bufferGL->getBufferID());
+
+    return setGenericDrawState(data);
+}
+
+gl::Error StateManagerGL::setDispatchComputeState(const gl::ContextState &data)
+{
+    setGenericShaderState(data);
+    return gl::NoError();
+}
+
+void StateManagerGL::pauseTransformFeedback()
+{
+    if (mPrevDrawTransformFeedback != nullptr)
+    {
+        mPrevDrawTransformFeedback->syncPausedState(true);
+    }
+}
+
+void StateManagerGL::pauseAllQueries()
+{
+    for (QueryGL *prevQuery : mCurrentQueries)
+    {
+        prevQuery->pause();
+    }
+}
+
+void StateManagerGL::pauseQuery(GLenum type)
+{
+    for (QueryGL *prevQuery : mCurrentQueries)
+    {
+        if (prevQuery->getType() == type)
+        {
+            prevQuery->pause();
+        }
+    }
+}
+
+void StateManagerGL::resumeAllQueries()
+{
+    for (QueryGL *prevQuery : mCurrentQueries)
+    {
+        prevQuery->resume();
+    }
+}
+
+void StateManagerGL::resumeQuery(GLenum type)
+{
+    for (QueryGL *prevQuery : mCurrentQueries)
+    {
+        if (prevQuery->getType() == type)
+        {
+            prevQuery->resume();
+        }
+    }
+}
+
+gl::Error StateManagerGL::onMakeCurrent(const gl::ContextState &data)
+{
+    const gl::State &state = data.getState();
+
+    // If the context has changed, pause the previous context's queries
+    if (data.getContextID() != mPrevDrawContext)
+    {
+        pauseAllQueries();
+    }
+    mCurrentQueries.clear();
+    mPrevDrawTransformFeedback = nullptr;
+    mPrevDrawContext           = data.getContextID();
+
+    // Set the current query state
+    for (GLenum queryType : QueryTypes)
+    {
+        gl::Query *query = state.getActiveQuery(queryType);
+        if (query != nullptr)
+        {
+            QueryGL *queryGL = GetImplAs<QueryGL>(query);
+            queryGL->resume();
+
+            mCurrentQueries.insert(queryGL);
+        }
+    }
+
+    // Seamless cubemaps are required for ES3 and higher contexts. It should be the cheapest to set
+    // this state here since MakeCurrent is expected to be called less frequently than draw calls.
+    setTextureCubemapSeamlessEnabled(data.getClientMajorVersion() >= 3);
+
+    return gl::NoError();
+}
+
+void StateManagerGL::setGenericShaderState(const gl::ContextState &data)
+{
+    const gl::State &state = data.getState();
+
+    // Sync the current program state
+    const gl::Program *program = state.getProgram();
+    const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
+    useProgram(programGL->getProgramID());
+
+    for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
+         uniformBlockIndex++)
+    {
+        GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
+        const auto &uniformBuffer = state.getIndexedUniformBuffer(binding);
+
+        if (uniformBuffer.get() != nullptr)
+        {
+            BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
+
+            if (uniformBuffer.getSize() == 0)
+            {
+                bindBufferBase(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID());
+            }
+            else
+            {
+                bindBufferRange(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID(),
+                                uniformBuffer.getOffset(), uniformBuffer.getSize());
+            }
+        }
+    }
+
+    for (const gl::SamplerBinding &samplerUniform : program->getSamplerBindings())
+    {
+        GLenum textureType = samplerUniform.textureType;
+        for (GLuint textureUnitIndex : samplerUniform.boundTextureUnits)
+        {
+            gl::Texture *texture       = state.getSamplerTexture(textureUnitIndex, textureType);
+            const gl::Sampler *sampler = state.getSampler(textureUnitIndex);
+
+            const gl::SamplerState &samplerState =
+                sampler ? sampler->getSamplerState() : texture->getSamplerState();
+
+            if (texture != nullptr &&
+                texture->getTextureState().isSamplerComplete(samplerState, data))
+            {
+                const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+
+                if (mTextures[textureType][textureUnitIndex] != textureGL->getTextureID() ||
+                    texture->hasAnyDirtyBit() || textureGL->hasAnyDirtyBit())
+                {
+                    activeTexture(textureUnitIndex);
+                    bindTexture(textureType, textureGL->getTextureID());
+
+                    // TODO: Call this from the gl:: layer once other backends use dirty bits for
+                    // texture state.
+                    texture->syncImplState();
+                }
+            }
+            else
+            {
+                if (mTextures[textureType][textureUnitIndex] != 0)
+                {
+                    activeTexture(textureUnitIndex);
+                    bindTexture(textureType, 0);
+                }
+            }
+
+            if (sampler != nullptr)
+            {
+                const SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
+                samplerGL->syncState(sampler->getSamplerState());
+                bindSampler(textureUnitIndex, samplerGL->getSamplerID());
+            }
+            else
+            {
+                bindSampler(textureUnitIndex, 0);
+            }
+        }
+    }
+}
+
+gl::Error StateManagerGL::setGenericDrawState(const gl::ContextState &data)
+{
+    setGenericShaderState(data);
+
+    const gl::State &state = data.getState();
+
+    const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
+    const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
+    bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferGL->getFramebufferID());
+
+    // Set the current transform feedback state
+    gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
+    if (transformFeedback)
+    {
+        TransformFeedbackGL *transformFeedbackGL =
+            GetImplAs<TransformFeedbackGL>(transformFeedback);
+        bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
+        transformFeedbackGL->syncActiveState(transformFeedback->isActive(),
+                                             transformFeedback->getPrimitiveMode());
+        transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
+        mPrevDrawTransformFeedback = transformFeedbackGL;
+    }
+    else
+    {
+        bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+        mPrevDrawTransformFeedback = nullptr;
+    }
+
+    return gl::NoError();
+}
+
+void StateManagerGL::setAttributeCurrentData(size_t index,
+                                             const gl::VertexAttribCurrentValueData &data)
+{
+    if (mVertexAttribCurrentValues[index] != data)
+    {
+        mVertexAttribCurrentValues[index] = data;
+        switch (mVertexAttribCurrentValues[index].Type)
+        {
+            case GL_FLOAT:
+                mFunctions->vertexAttrib4fv(static_cast<GLuint>(index),
+                                            mVertexAttribCurrentValues[index].FloatValues);
+                break;
+            case GL_INT:
+                mFunctions->vertexAttribI4iv(static_cast<GLuint>(index),
+                                             mVertexAttribCurrentValues[index].IntValues);
+                break;
+            case GL_UNSIGNED_INT:
+                mFunctions->vertexAttribI4uiv(static_cast<GLuint>(index),
+                                              mVertexAttribCurrentValues[index].UnsignedIntValues);
+                break;
+            default:
+                UNREACHABLE();
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CURRENT_VALUE_0 + index);
+    }
+}
+
+void StateManagerGL::setScissorTestEnabled(bool enabled)
+{
+    if (mScissorTestEnabled != enabled)
+    {
+        mScissorTestEnabled = enabled;
+        if (mScissorTestEnabled)
+        {
+            mFunctions->enable(GL_SCISSOR_TEST);
+        }
+        else
+        {
+            mFunctions->disable(GL_SCISSOR_TEST);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
+    }
+}
+
+void StateManagerGL::setScissor(const gl::Rectangle &scissor)
+{
+    if (scissor != mScissor)
+    {
+        mScissor = scissor;
+        mFunctions->scissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
+    }
+}
+
+void StateManagerGL::setViewport(const gl::Rectangle &viewport)
+{
+    if (viewport != mViewport)
+    {
+        mViewport = viewport;
+        mFunctions->viewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
+    }
+}
+
+void StateManagerGL::setDepthRange(float near, float far)
+{
+    if (mNear != near || mFar != far)
+    {
+        mNear = near;
+        mFar  = far;
+
+        // The glDepthRangef function isn't available until OpenGL 4.1.  Prefer it when it is
+        // available because OpenGL ES only works in floats.
+        if (mFunctions->depthRangef)
+        {
+            mFunctions->depthRangef(mNear, mFar);
+        }
+        else
+        {
+            ASSERT(mFunctions->depthRange);
+            mFunctions->depthRange(mNear, mFar);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE);
+    }
+}
+
+void StateManagerGL::setBlendEnabled(bool enabled)
+{
+    if (mBlendEnabled != enabled)
+    {
+        mBlendEnabled = enabled;
+        if (mBlendEnabled)
+        {
+            mFunctions->enable(GL_BLEND);
+        }
+        else
+        {
+            mFunctions->disable(GL_BLEND);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
+    }
+}
+
+void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
+{
+    if (mBlendColor != blendColor)
+    {
+        mBlendColor = blendColor;
+        mFunctions->blendColor(mBlendColor.red, mBlendColor.green, mBlendColor.blue,
+                               mBlendColor.alpha);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR);
+    }
+}
+
+void StateManagerGL::setBlendFuncs(GLenum sourceBlendRGB,
+                                   GLenum destBlendRGB,
+                                   GLenum sourceBlendAlpha,
+                                   GLenum destBlendAlpha)
+{
+    if (mSourceBlendRGB != sourceBlendRGB || mDestBlendRGB != destBlendRGB ||
+        mSourceBlendAlpha != sourceBlendAlpha || mDestBlendAlpha != destBlendAlpha)
+    {
+        mSourceBlendRGB   = sourceBlendRGB;
+        mDestBlendRGB     = destBlendRGB;
+        mSourceBlendAlpha = sourceBlendAlpha;
+        mDestBlendAlpha   = destBlendAlpha;
+
+        mFunctions->blendFuncSeparate(mSourceBlendRGB, mDestBlendRGB, mSourceBlendAlpha,
+                                      mDestBlendAlpha);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
+    }
+}
+
+void StateManagerGL::setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha)
+{
+    if (mBlendEquationRGB != blendEquationRGB || mBlendEquationAlpha != blendEquationAlpha)
+    {
+        mBlendEquationRGB   = blendEquationRGB;
+        mBlendEquationAlpha = blendEquationAlpha;
+
+        mFunctions->blendEquationSeparate(mBlendEquationRGB, mBlendEquationAlpha);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_EQUATIONS);
+    }
+}
+
+void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha)
+{
+    if (mColorMaskRed != red || mColorMaskGreen != green || mColorMaskBlue != blue ||
+        mColorMaskAlpha != alpha)
+    {
+        mColorMaskRed   = red;
+        mColorMaskGreen = green;
+        mColorMaskBlue  = blue;
+        mColorMaskAlpha = alpha;
+        mFunctions->colorMask(mColorMaskRed, mColorMaskGreen, mColorMaskBlue, mColorMaskAlpha);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
+    }
+}
+
+void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled)
+{
+    if (mSampleAlphaToCoverageEnabled != enabled)
+    {
+        mSampleAlphaToCoverageEnabled = enabled;
+        if (mSampleAlphaToCoverageEnabled)
+        {
+            mFunctions->enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+        }
+        else
+        {
+            mFunctions->disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
+    }
+}
+
+void StateManagerGL::setSampleCoverageEnabled(bool enabled)
+{
+    if (mSampleCoverageEnabled != enabled)
+    {
+        mSampleCoverageEnabled = enabled;
+        if (mSampleCoverageEnabled)
+        {
+            mFunctions->enable(GL_SAMPLE_COVERAGE);
+        }
+        else
+        {
+            mFunctions->disable(GL_SAMPLE_COVERAGE);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
+    }
+}
+
+void StateManagerGL::setSampleCoverage(float value, bool invert)
+{
+    if (mSampleCoverageValue != value || mSampleCoverageInvert != invert)
+    {
+        mSampleCoverageValue  = value;
+        mSampleCoverageInvert = invert;
+        mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE);
+    }
+}
+
+void StateManagerGL::setDepthTestEnabled(bool enabled)
+{
+    if (mDepthTestEnabled != enabled)
+    {
+        mDepthTestEnabled = enabled;
+        if (mDepthTestEnabled)
+        {
+            mFunctions->enable(GL_DEPTH_TEST);
+        }
+        else
+        {
+            mFunctions->disable(GL_DEPTH_TEST);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED);
+    }
+}
+
+void StateManagerGL::setDepthFunc(GLenum depthFunc)
+{
+    if (mDepthFunc != depthFunc)
+    {
+        mDepthFunc = depthFunc;
+        mFunctions->depthFunc(mDepthFunc);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC);
+    }
+}
+
+void StateManagerGL::setDepthMask(bool mask)
+{
+    if (mDepthMask != mask)
+    {
+        mDepthMask = mask;
+        mFunctions->depthMask(mDepthMask);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK);
+    }
+}
+
+void StateManagerGL::setStencilTestEnabled(bool enabled)
+{
+    if (mStencilTestEnabled != enabled)
+    {
+        mStencilTestEnabled = enabled;
+        if (mStencilTestEnabled)
+        {
+            mFunctions->enable(GL_STENCIL_TEST);
+        }
+        else
+        {
+            mFunctions->disable(GL_STENCIL_TEST);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED);
+    }
+}
+
+void StateManagerGL::setStencilFrontWritemask(GLuint mask)
+{
+    if (mStencilFrontWritemask != mask)
+    {
+        mStencilFrontWritemask = mask;
+        mFunctions->stencilMaskSeparate(GL_FRONT, mStencilFrontWritemask);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+    }
+}
+
+void StateManagerGL::setStencilBackWritemask(GLuint mask)
+{
+    if (mStencilBackWritemask != mask)
+    {
+        mStencilBackWritemask = mask;
+        mFunctions->stencilMaskSeparate(GL_BACK, mStencilBackWritemask);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+    }
+}
+
+void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask)
+{
+    if (mStencilFrontFunc != func || mStencilFrontRef != ref || mStencilFrontValueMask != mask)
+    {
+        mStencilFrontFunc      = func;
+        mStencilFrontRef       = ref;
+        mStencilFrontValueMask = mask;
+        mFunctions->stencilFuncSeparate(GL_FRONT, mStencilFrontFunc, mStencilFrontRef,
+                                        mStencilFrontValueMask);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT);
+    }
+}
+
+void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask)
+{
+    if (mStencilBackFunc != func || mStencilBackRef != ref || mStencilBackValueMask != mask)
+    {
+        mStencilBackFunc      = func;
+        mStencilBackRef       = ref;
+        mStencilBackValueMask = mask;
+        mFunctions->stencilFuncSeparate(GL_BACK, mStencilBackFunc, mStencilBackRef,
+                                        mStencilBackValueMask);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK);
+    }
+}
+
+void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass)
+{
+    if (mStencilFrontStencilFailOp != sfail || mStencilFrontStencilPassDepthFailOp != dpfail ||
+        mStencilFrontStencilPassDepthPassOp != dppass)
+    {
+        mStencilFrontStencilFailOp          = sfail;
+        mStencilFrontStencilPassDepthFailOp = dpfail;
+        mStencilFrontStencilPassDepthPassOp = dppass;
+        mFunctions->stencilOpSeparate(GL_FRONT, mStencilFrontStencilFailOp,
+                                      mStencilFrontStencilPassDepthFailOp,
+                                      mStencilFrontStencilPassDepthPassOp);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT);
+    }
+}
+
+void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass)
+{
+    if (mStencilBackStencilFailOp != sfail || mStencilBackStencilPassDepthFailOp != dpfail ||
+        mStencilBackStencilPassDepthPassOp != dppass)
+    {
+        mStencilBackStencilFailOp          = sfail;
+        mStencilBackStencilPassDepthFailOp = dpfail;
+        mStencilBackStencilPassDepthPassOp = dppass;
+        mFunctions->stencilOpSeparate(GL_BACK, mStencilBackStencilFailOp,
+                                      mStencilBackStencilPassDepthFailOp,
+                                      mStencilBackStencilPassDepthPassOp);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK);
+    }
+}
+
+void StateManagerGL::setCullFaceEnabled(bool enabled)
+{
+    if (mCullFaceEnabled != enabled)
+    {
+        mCullFaceEnabled = enabled;
+        if (mCullFaceEnabled)
+        {
+            mFunctions->enable(GL_CULL_FACE);
+        }
+        else
+        {
+            mFunctions->disable(GL_CULL_FACE);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED);
+    }
+}
+
+void StateManagerGL::setCullFace(GLenum cullFace)
+{
+    if (mCullFace != cullFace)
+    {
+        mCullFace = cullFace;
+        mFunctions->cullFace(mCullFace);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE);
+    }
+}
+
+void StateManagerGL::setFrontFace(GLenum frontFace)
+{
+    if (mFrontFace != frontFace)
+    {
+        mFrontFace = frontFace;
+        mFunctions->frontFace(mFrontFace);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE);
+    }
+}
+
+void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled)
+{
+    if (mPolygonOffsetFillEnabled != enabled)
+    {
+        mPolygonOffsetFillEnabled = enabled;
+        if (mPolygonOffsetFillEnabled)
+        {
+            mFunctions->enable(GL_POLYGON_OFFSET_FILL);
+        }
+        else
+        {
+            mFunctions->disable(GL_POLYGON_OFFSET_FILL);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
+    }
+}
+
+void StateManagerGL::setPolygonOffset(float factor, float units)
+{
+    if (mPolygonOffsetFactor != factor || mPolygonOffsetUnits != units)
+    {
+        mPolygonOffsetFactor = factor;
+        mPolygonOffsetUnits  = units;
+        mFunctions->polygonOffset(mPolygonOffsetFactor, mPolygonOffsetUnits);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET);
+    }
+}
+
+void StateManagerGL::setRasterizerDiscardEnabled(bool enabled)
+{
+    if (mRasterizerDiscardEnabled != enabled)
+    {
+        mRasterizerDiscardEnabled = enabled;
+        if (mRasterizerDiscardEnabled)
+        {
+            mFunctions->enable(GL_RASTERIZER_DISCARD);
+        }
+        else
+        {
+            mFunctions->disable(GL_RASTERIZER_DISCARD);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
+    }
+}
+
+void StateManagerGL::setLineWidth(float width)
+{
+    if (mLineWidth != width)
+    {
+        mLineWidth = width;
+        mFunctions->lineWidth(mLineWidth);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH);
+    }
+}
+
+void StateManagerGL::setPrimitiveRestartEnabled(bool enabled)
+{
+    if (mPrimitiveRestartEnabled != enabled)
+    {
+        mPrimitiveRestartEnabled = enabled;
+
+        if (mPrimitiveRestartEnabled)
+        {
+            mFunctions->enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
+        }
+        else
+        {
+            mFunctions->disable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
+    }
+}
+
+void StateManagerGL::setClearDepth(float clearDepth)
+{
+    if (mClearDepth != clearDepth)
+    {
+        mClearDepth = clearDepth;
+
+        // The glClearDepthf function isn't available until OpenGL 4.1.  Prefer it when it is
+        // available because OpenGL ES only works in floats.
+        if (mFunctions->clearDepthf)
+        {
+            mFunctions->clearDepthf(mClearDepth);
+        }
+        else
+        {
+            ASSERT(mFunctions->clearDepth);
+            mFunctions->clearDepth(mClearDepth);
+        }
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH);
+    }
+}
+
+void StateManagerGL::setClearColor(const gl::ColorF &clearColor)
+{
+    if (mClearColor != clearColor)
+    {
+        mClearColor = clearColor;
+        mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue,
+                               mClearColor.alpha);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR);
+    }
+}
+
+void StateManagerGL::setClearStencil(GLint clearStencil)
+{
+    if (mClearStencil != clearStencil)
+    {
+        mClearStencil = clearStencil;
+        mFunctions->clearStencil(mClearStencil);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL);
+    }
+}
+
+void StateManagerGL::syncState(const gl::ContextState &data,
+                               const gl::State::DirtyBits &glDirtyBits)
+{
+    const gl::State &state = data.getState();
+
+    // The the current framebuffer binding sometimes requires resetting the srgb blending
+    if (glDirtyBits[gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING] &&
+        mFunctions->standard == STANDARD_GL_DESKTOP)
+    {
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
+    }
+
+    const gl::State::DirtyBits &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits);
+
+    if (!glAndLocalDirtyBits.any())
+    {
+        return;
+    }
+
+    // TODO(jmadill): Investigate only syncing vertex state for active attributes
+    for (auto dirtyBit : glAndLocalDirtyBits)
+    {
+        switch (dirtyBit)
+        {
+            case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
+                setScissorTestEnabled(state.isScissorTestEnabled());
+                break;
+            case gl::State::DIRTY_BIT_SCISSOR:
+                setScissor(state.getScissor());
+                break;
+            case gl::State::DIRTY_BIT_VIEWPORT:
+                setViewport(state.getViewport());
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_RANGE:
+                setDepthRange(state.getNearPlane(), state.getFarPlane());
+                break;
+            case gl::State::DIRTY_BIT_BLEND_ENABLED:
+                setBlendEnabled(state.isBlendEnabled());
+                break;
+            case gl::State::DIRTY_BIT_BLEND_COLOR:
+                setBlendColor(state.getBlendColor());
+                break;
+            case gl::State::DIRTY_BIT_BLEND_FUNCS:
+            {
+                const auto &blendState = state.getBlendState();
+                setBlendFuncs(blendState.sourceBlendRGB, blendState.destBlendRGB,
+                              blendState.sourceBlendAlpha, blendState.destBlendAlpha);
+                break;
+            }
+            case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
+            {
+                const auto &blendState = state.getBlendState();
+                setBlendEquations(blendState.blendEquationRGB, blendState.blendEquationAlpha);
+                break;
+            }
+            case gl::State::DIRTY_BIT_COLOR_MASK:
+            {
+                const auto &blendState = state.getBlendState();
+                setColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
+                             blendState.colorMaskBlue, blendState.colorMaskAlpha);
+                break;
+            }
+            case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
+                setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled());
+                break;
+            case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
+                setSampleCoverageEnabled(state.isSampleCoverageEnabled());
+                break;
+            case gl::State::DIRTY_BIT_SAMPLE_COVERAGE:
+                setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert());
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
+                setDepthTestEnabled(state.isDepthTestEnabled());
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_FUNC:
+                setDepthFunc(state.getDepthStencilState().depthFunc);
+                break;
+            case gl::State::DIRTY_BIT_DEPTH_MASK:
+                setDepthMask(state.getDepthStencilState().depthMask);
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+                setStencilTestEnabled(state.isStencilTestEnabled());
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
+            {
+                const auto &depthStencilState = state.getDepthStencilState();
+                setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(),
+                                     depthStencilState.stencilMask);
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+            {
+                const auto &depthStencilState = state.getDepthStencilState();
+                setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(),
+                                    depthStencilState.stencilBackMask);
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+            {
+                const auto &depthStencilState = state.getDepthStencilState();
+                setStencilFrontOps(depthStencilState.stencilFail,
+                                   depthStencilState.stencilPassDepthFail,
+                                   depthStencilState.stencilPassDepthPass);
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+            {
+                const auto &depthStencilState = state.getDepthStencilState();
+                setStencilBackOps(depthStencilState.stencilBackFail,
+                                  depthStencilState.stencilBackPassDepthFail,
+                                  depthStencilState.stencilBackPassDepthPass);
+                break;
+            }
+            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+                setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask);
+                break;
+            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+                setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask);
+                break;
+            case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
+                setCullFaceEnabled(state.isCullFaceEnabled());
+                break;
+            case gl::State::DIRTY_BIT_CULL_FACE:
+                setCullFace(state.getRasterizerState().cullMode);
+                break;
+            case gl::State::DIRTY_BIT_FRONT_FACE:
+                setFrontFace(state.getRasterizerState().frontFace);
+                break;
+            case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
+                setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled());
+                break;
+            case gl::State::DIRTY_BIT_POLYGON_OFFSET:
+            {
+                const auto &rasterizerState = state.getRasterizerState();
+                setPolygonOffset(rasterizerState.polygonOffsetFactor,
+                                 rasterizerState.polygonOffsetUnits);
+                break;
+            }
+            case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
+                setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled());
+                break;
+            case gl::State::DIRTY_BIT_LINE_WIDTH:
+                setLineWidth(state.getLineWidth());
+                break;
+            case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
+                setPrimitiveRestartEnabled(state.isPrimitiveRestartEnabled());
+                break;
+            case gl::State::DIRTY_BIT_CLEAR_COLOR:
+                setClearColor(state.getColorClearValue());
+                break;
+            case gl::State::DIRTY_BIT_CLEAR_DEPTH:
+                setClearDepth(state.getDepthClearValue());
+                break;
+            case gl::State::DIRTY_BIT_CLEAR_STENCIL:
+                setClearStencil(state.getStencilClearValue());
+                break;
+            case gl::State::DIRTY_BIT_UNPACK_ALIGNMENT:
+                // TODO(jmadill): split this
+                setPixelUnpackState(state.getUnpackState());
+                break;
+            case gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH:
+                // TODO(jmadill): split this
+                setPixelUnpackState(state.getUnpackState());
+                break;
+            case gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT:
+                // TODO(jmadill): split this
+                setPixelUnpackState(state.getUnpackState());
+                break;
+            case gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES:
+                // TODO(jmadill): split this
+                setPixelUnpackState(state.getUnpackState());
+                break;
+            case gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS:
+                // TODO(jmadill): split this
+                setPixelUnpackState(state.getUnpackState());
+                break;
+            case gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS:
+                // TODO(jmadill): split this
+                setPixelUnpackState(state.getUnpackState());
+                break;
+            case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
+                // TODO(jmadill): split this
+                setPixelUnpackState(state.getUnpackState());
+                break;
+            case gl::State::DIRTY_BIT_PACK_ALIGNMENT:
+                // TODO(jmadill): split this
+                setPixelPackState(state.getPackState());
+                break;
+            case gl::State::DIRTY_BIT_PACK_REVERSE_ROW_ORDER:
+                // TODO(jmadill): split this
+                setPixelPackState(state.getPackState());
+                break;
+            case gl::State::DIRTY_BIT_PACK_ROW_LENGTH:
+                // TODO(jmadill): split this
+                setPixelPackState(state.getPackState());
+                break;
+            case gl::State::DIRTY_BIT_PACK_SKIP_ROWS:
+                // TODO(jmadill): split this
+                setPixelPackState(state.getPackState());
+                break;
+            case gl::State::DIRTY_BIT_PACK_SKIP_PIXELS:
+                // TODO(jmadill): split this
+                setPixelPackState(state.getPackState());
+                break;
+            case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING:
+                // TODO(jmadill): split this
+                setPixelPackState(state.getPackState());
+                break;
+            case gl::State::DIRTY_BIT_DITHER_ENABLED:
+                setDitherEnabled(state.isDitherEnabled());
+                break;
+            case gl::State::DIRTY_BIT_GENERATE_MIPMAP_HINT:
+                // TODO(jmadill): implement this
+                break;
+            case gl::State::DIRTY_BIT_SHADER_DERIVATIVE_HINT:
+                // TODO(jmadill): implement this
+                break;
+            case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
+                // TODO(jmadill): implement this
+                break;
+            case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
+                // TODO(jmadill): implement this
+                break;
+            case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
+                // TODO(jmadill): implement this
+                break;
+            case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
+                // TODO(jmadill): implement this
+                break;
+            case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
+                // TODO: implement this
+                break;
+            case gl::State::DIRTY_BIT_PROGRAM_BINDING:
+                // TODO(jmadill): implement this
+                break;
+            case gl::State::DIRTY_BIT_MULTISAMPLING:
+                setMultisamplingStateEnabled(state.isMultisamplingEnabled());
+                break;
+            case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
+                setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled());
+            case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
+                setCoverageModulation(state.getCoverageModulation());
+                break;
+            case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV:
+                setPathRenderingModelViewMatrix(
+                    state.getPathRenderingMatrix(GL_PATH_MODELVIEW_MATRIX_CHROMIUM));
+                break;
+            case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ:
+                setPathRenderingProjectionMatrix(
+                    state.getPathRenderingMatrix(GL_PATH_PROJECTION_MATRIX_CHROMIUM));
+                break;
+            case gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE:
+                setPathRenderingStencilState(state.getPathStencilFunc(), state.getPathStencilRef(),
+                                             state.getPathStencilMask());
+                break;
+            case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
+                setFramebufferSRGBEnabledForFramebuffer(
+                    data, state.getFramebufferSRGB(),
+                    GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
+                break;
+            default:
+            {
+                ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
+                       dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX);
+                size_t attribIndex =
+                    static_cast<size_t>(dirtyBit) - gl::State::DIRTY_BIT_CURRENT_VALUE_0;
+                setAttributeCurrentData(attribIndex,
+                                        state.getVertexAttribCurrentValue(attribIndex));
+                break;
+            }
+        }
+
+        mLocalDirtyBits.reset();
+    }
+}
+
+void StateManagerGL::setFramebufferSRGBEnabled(const gl::ContextState &data, bool enabled)
+{
+    if (!data.getExtensions().sRGBWriteControl)
+    {
+        return;
+    }
+
+    if (mFramebufferSRGBEnabled != enabled)
+    {
+        mFramebufferSRGBEnabled = enabled;
+        if (mFramebufferSRGBEnabled)
+        {
+            mFunctions->enable(GL_FRAMEBUFFER_SRGB);
+        }
+        else
+        {
+            mFunctions->disable(GL_FRAMEBUFFER_SRGB);
+        }
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
+    }
+}
+
+void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::ContextState &data,
+                                                             bool enabled,
+                                                             const FramebufferGL *framebuffer)
+{
+    if (mFunctions->standard == STANDARD_GL_DESKTOP && framebuffer->isDefault())
+    {
+        // Obey the framebuffer sRGB state for blending on all framebuffers except the default
+        // framebuffer on Desktop OpenGL.
+        // When SRGB blending is enabled, only SRGB capable formats will use it but the default
+        // framebuffer will always use it if it is enabled.
+        // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
+        setFramebufferSRGBEnabled(data, false);
+    }
+    else
+    {
+        setFramebufferSRGBEnabled(data, enabled);
+    }
+}
+
+void StateManagerGL::setDitherEnabled(bool enabled)
+{
+    if (mDitherEnabled != enabled)
+    {
+        mDitherEnabled = enabled;
+        if (mDitherEnabled)
+        {
+            mFunctions->enable(GL_DITHER);
+        }
+        else
+        {
+            mFunctions->disable(GL_DITHER);
+        }
+    }
+}
+
+void StateManagerGL::setMultisamplingStateEnabled(bool enabled)
+{
+    if (mMultisamplingEnabled != enabled)
+    {
+        mMultisamplingEnabled = enabled;
+        if (mMultisamplingEnabled)
+        {
+            mFunctions->enable(GL_MULTISAMPLE_EXT);
+        }
+        else
+        {
+            mFunctions->disable(GL_MULTISAMPLE_EXT);
+        }
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING);
+    }
+}
+
+void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
+{
+    if (mSampleAlphaToOneEnabled != enabled)
+    {
+        mSampleAlphaToOneEnabled = enabled;
+        if (mSampleAlphaToOneEnabled)
+        {
+            mFunctions->enable(GL_SAMPLE_ALPHA_TO_ONE);
+        }
+        else
+        {
+            mFunctions->disable(GL_SAMPLE_ALPHA_TO_ONE);
+        }
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
+    }
+}
+
+void StateManagerGL::setCoverageModulation(GLenum components)
+{
+    if (mCoverageModulation != components)
+    {
+        mCoverageModulation = components;
+        mFunctions->coverageModulationNV(components);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_COVERAGE_MODULATION);
+    }
+}
+
+void StateManagerGL::setPathRenderingModelViewMatrix(const GLfloat *m)
+{
+    if (memcmp(mPathMatrixMV, m, sizeof(mPathMatrixMV)) != 0)
+    {
+        memcpy(mPathMatrixMV, m, sizeof(mPathMatrixMV));
+        mFunctions->matrixLoadEXT(GL_PATH_MODELVIEW_CHROMIUM, m);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV);
+    }
+}
+
+void StateManagerGL::setPathRenderingProjectionMatrix(const GLfloat *m)
+{
+    if (memcmp(mPathMatrixProj, m, sizeof(mPathMatrixProj)) != 0)
+    {
+        memcpy(mPathMatrixProj, m, sizeof(mPathMatrixProj));
+        mFunctions->matrixLoadEXT(GL_PATH_PROJECTION_CHROMIUM, m);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ);
+    }
+}
+
+void StateManagerGL::setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask)
+{
+    if (func != mPathStencilFunc || ref != mPathStencilRef || mask != mPathStencilMask)
+    {
+        mPathStencilFunc = func;
+        mPathStencilRef  = ref;
+        mPathStencilMask = mask;
+        mFunctions->pathStencilFuncNV(func, ref, mask);
+
+        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE);
+    }
+}
+
+void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
+{
+    if (mTextureCubemapSeamlessEnabled != enabled)
+    {
+        mTextureCubemapSeamlessEnabled = enabled;
+        if (mTextureCubemapSeamlessEnabled)
+        {
+            mFunctions->enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+        }
+        else
+        {
+            mFunctions->disable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+        }
+    }
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h
new file mode 100644
index 0000000..43dab84
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -0,0 +1,300 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManagerGL.h: Defines a class for caching applied OpenGL state
+
+#ifndef LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_
+#define LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_
+
+#include "common/debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/gl/functionsgl_typedefs.h"
+
+#include <map>
+
+namespace gl
+{
+struct Caps;
+class ContextState;
+class State;
+}
+
+namespace rx
+{
+
+class FramebufferGL;
+class FunctionsGL;
+class TransformFeedbackGL;
+class QueryGL;
+
+class StateManagerGL final : angle::NonCopyable
+{
+  public:
+    StateManagerGL(const FunctionsGL *functions, const gl::Caps &rendererCaps);
+
+    void deleteProgram(GLuint program);
+    void deleteVertexArray(GLuint vao);
+    void deleteTexture(GLuint texture);
+    void deleteSampler(GLuint sampler);
+    void deleteBuffer(GLuint buffer);
+    void deleteFramebuffer(GLuint fbo);
+    void deleteRenderbuffer(GLuint rbo);
+    void deleteTransformFeedback(GLuint transformFeedback);
+    void deleteQuery(GLuint query);
+
+    void useProgram(GLuint program);
+    void forceUseProgram(GLuint program);
+    void bindVertexArray(GLuint vao, GLuint elementArrayBuffer);
+    void bindBuffer(GLenum type, GLuint buffer);
+    void bindBufferBase(GLenum type, size_t index, GLuint buffer);
+    void bindBufferRange(GLenum type, size_t index, GLuint buffer, size_t offset, size_t size);
+    void activeTexture(size_t unit);
+    void bindTexture(GLenum type, GLuint texture);
+    void bindSampler(size_t unit, GLuint sampler);
+    void bindFramebuffer(GLenum type, GLuint framebuffer);
+    void bindRenderbuffer(GLenum type, GLuint renderbuffer);
+    void bindTransformFeedback(GLenum type, GLuint transformFeedback);
+    void beginQuery(GLenum type, GLuint query);
+    void endQuery(GLenum type, GLuint query);
+    void onBeginQuery(QueryGL *query);
+
+    void setAttributeCurrentData(size_t index, const gl::VertexAttribCurrentValueData &data);
+
+    void setScissorTestEnabled(bool enabled);
+    void setScissor(const gl::Rectangle &scissor);
+
+    void setViewport(const gl::Rectangle &viewport);
+    void setDepthRange(float near, float far);
+
+    void setBlendEnabled(bool enabled);
+    void setBlendColor(const gl::ColorF &blendColor);
+    void setBlendFuncs(GLenum sourceBlendRGB,
+                       GLenum destBlendRGB,
+                       GLenum sourceBlendAlpha,
+                       GLenum destBlendAlpha);
+    void setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha);
+    void setColorMask(bool red, bool green, bool blue, bool alpha);
+    void setSampleAlphaToCoverageEnabled(bool enabled);
+    void setSampleCoverageEnabled(bool enabled);
+    void setSampleCoverage(float value, bool invert);
+
+    void setDepthTestEnabled(bool enabled);
+    void setDepthFunc(GLenum depthFunc);
+    void setDepthMask(bool mask);
+    void setStencilTestEnabled(bool enabled);
+    void setStencilFrontWritemask(GLuint mask);
+    void setStencilBackWritemask(GLuint mask);
+    void setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask);
+    void setStencilBackFuncs(GLenum func, GLint ref, GLuint mask);
+    void setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass);
+    void setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass);
+
+    void setCullFaceEnabled(bool enabled);
+    void setCullFace(GLenum cullFace);
+    void setFrontFace(GLenum frontFace);
+    void setPolygonOffsetFillEnabled(bool enabled);
+    void setPolygonOffset(float factor, float units);
+    void setRasterizerDiscardEnabled(bool enabled);
+    void setLineWidth(float width);
+
+    void setPrimitiveRestartEnabled(bool enabled);
+
+    void setClearColor(const gl::ColorF &clearColor);
+    void setClearDepth(float clearDepth);
+    void setClearStencil(GLint clearStencil);
+
+    void setPixelUnpackState(const gl::PixelUnpackState &unpack);
+    void setPixelUnpackState(GLint alignment,
+                             GLint rowLength,
+                             GLint skipRows,
+                             GLint skipPixels,
+                             GLint imageHeight,
+                             GLint skipImages,
+                             GLuint unpackBuffer);
+    void setPixelPackState(const gl::PixelPackState &pack);
+    void setPixelPackState(GLint alignment,
+                           GLint rowLength,
+                           GLint skipRows,
+                           GLint skipPixels,
+                           GLuint packBuffer);
+
+    void setFramebufferSRGBEnabled(const gl::ContextState &data, bool enabled);
+    void setFramebufferSRGBEnabledForFramebuffer(const gl::ContextState &data,
+                                                 bool enabled,
+                                                 const FramebufferGL *framebuffer);
+
+    void setDitherEnabled(bool enabled);
+
+    void setMultisamplingStateEnabled(bool enabled);
+    void setSampleAlphaToOneStateEnabled(bool enabled);
+
+    void setCoverageModulation(GLenum components);
+
+    void setPathRenderingModelViewMatrix(const GLfloat *m);
+    void setPathRenderingProjectionMatrix(const GLfloat *m);
+    void setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask);
+
+    void onDeleteQueryObject(QueryGL *query);
+
+    gl::Error setDrawArraysState(const gl::ContextState &data,
+                                 GLint first,
+                                 GLsizei count,
+                                 GLsizei instanceCount);
+    gl::Error setDrawElementsState(const gl::ContextState &data,
+                                   GLsizei count,
+                                   GLenum type,
+                                   const void *indices,
+                                   GLsizei instanceCount,
+                                   const void **outIndices);
+    gl::Error setDrawIndirectState(const gl::ContextState &data, GLenum type);
+
+    gl::Error setDispatchComputeState(const gl::ContextState &data);
+
+    void pauseTransformFeedback();
+    void pauseAllQueries();
+    void pauseQuery(GLenum type);
+    void resumeAllQueries();
+    void resumeQuery(GLenum type);
+    gl::Error onMakeCurrent(const gl::ContextState &data);
+
+    void syncState(const gl::ContextState &data, const gl::State::DirtyBits &glDirtyBits);
+
+  private:
+    // Set state that's common among draw commands and compute invocations.
+    void setGenericShaderState(const gl::ContextState &data);
+
+    // Set state that's common among draw commands.
+    gl::Error setGenericDrawState(const gl::ContextState &data);
+
+    void setTextureCubemapSeamlessEnabled(bool enabled);
+
+    const FunctionsGL *mFunctions;
+
+    GLuint mProgram;
+
+    GLuint mVAO;
+    std::vector<gl::VertexAttribCurrentValueData> mVertexAttribCurrentValues;
+
+    std::map<GLenum, GLuint> mBuffers;
+
+    struct IndexedBufferBinding
+    {
+        IndexedBufferBinding();
+
+        size_t offset;
+        size_t size;
+        GLuint buffer;
+    };
+    std::map<GLenum, std::vector<IndexedBufferBinding>> mIndexedBuffers;
+
+    size_t mTextureUnitIndex;
+    std::map<GLenum, std::vector<GLuint>> mTextures;
+    std::vector<GLuint> mSamplers;
+
+    GLuint mTransformFeedback;
+
+    std::map<GLenum, GLuint> mQueries;
+
+    TransformFeedbackGL *mPrevDrawTransformFeedback;
+    std::set<QueryGL *> mCurrentQueries;
+    gl::ContextID mPrevDrawContext;
+
+    GLint mUnpackAlignment;
+    GLint mUnpackRowLength;
+    GLint mUnpackSkipRows;
+    GLint mUnpackSkipPixels;
+    GLint mUnpackImageHeight;
+    GLint mUnpackSkipImages;
+
+    GLint mPackAlignment;
+    GLint mPackRowLength;
+    GLint mPackSkipRows;
+    GLint mPackSkipPixels;
+
+    // TODO(jmadill): Convert to std::array when available
+    std::vector<GLenum> mFramebuffers;
+    GLuint mRenderbuffer;
+
+    bool mScissorTestEnabled;
+    gl::Rectangle mScissor;
+
+    gl::Rectangle mViewport;
+    float mNear;
+    float mFar;
+
+    bool mBlendEnabled;
+    gl::ColorF mBlendColor;
+    GLenum mSourceBlendRGB;
+    GLenum mDestBlendRGB;
+    GLenum mSourceBlendAlpha;
+    GLenum mDestBlendAlpha;
+    GLenum mBlendEquationRGB;
+    GLenum mBlendEquationAlpha;
+    bool mColorMaskRed;
+    bool mColorMaskGreen;
+    bool mColorMaskBlue;
+    bool mColorMaskAlpha;
+    bool mSampleAlphaToCoverageEnabled;
+    bool mSampleCoverageEnabled;
+    float mSampleCoverageValue;
+    bool mSampleCoverageInvert;
+
+    bool mDepthTestEnabled;
+    GLenum mDepthFunc;
+    bool mDepthMask;
+    bool mStencilTestEnabled;
+    GLenum mStencilFrontFunc;
+    GLint mStencilFrontRef;
+    GLuint mStencilFrontValueMask;
+    GLenum mStencilFrontStencilFailOp;
+    GLenum mStencilFrontStencilPassDepthFailOp;
+    GLenum mStencilFrontStencilPassDepthPassOp;
+    GLuint mStencilFrontWritemask;
+    GLenum mStencilBackFunc;
+    GLint mStencilBackRef;
+    GLuint mStencilBackValueMask;
+    GLenum mStencilBackStencilFailOp;
+    GLenum mStencilBackStencilPassDepthFailOp;
+    GLenum mStencilBackStencilPassDepthPassOp;
+    GLuint mStencilBackWritemask;
+
+    bool mCullFaceEnabled;
+    GLenum mCullFace;
+    GLenum mFrontFace;
+    bool mPolygonOffsetFillEnabled;
+    GLfloat mPolygonOffsetFactor;
+    GLfloat mPolygonOffsetUnits;
+    bool mRasterizerDiscardEnabled;
+    float mLineWidth;
+
+    bool mPrimitiveRestartEnabled;
+
+    gl::ColorF mClearColor;
+    float mClearDepth;
+    GLint mClearStencil;
+
+    bool mFramebufferSRGBEnabled;
+    bool mDitherEnabled;
+    bool mTextureCubemapSeamlessEnabled;
+
+    bool mMultisamplingEnabled;
+    bool mSampleAlphaToOneEnabled;
+
+    GLenum mCoverageModulation;
+
+    GLfloat mPathMatrixMV[16];
+    GLfloat mPathMatrixProj[16];
+    GLenum mPathStencilFunc;
+    GLint mPathStencilRef;
+    GLuint mPathStencilMask;
+
+    gl::State::DirtyBits mLocalDirtyBits;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp
new file mode 100644
index 0000000..bba938b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceGL.cpp: OpenGL implementation of egl::Surface
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+
+namespace rx
+{
+
+SurfaceGL::SurfaceGL(const egl::SurfaceState &state, RendererGL *renderer)
+    : SurfaceImpl(state), mRenderer(renderer)
+{
+}
+
+SurfaceGL::~SurfaceGL()
+{
+}
+
+FramebufferImpl *SurfaceGL::createDefaultFramebuffer(const gl::FramebufferState &data)
+{
+    return new FramebufferGL(data, mRenderer->getFunctions(), mRenderer->getStateManager(),
+                             mRenderer->getWorkarounds(), mRenderer->getBlitter(), true);
+}
+
+egl::Error SurfaceGL::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+    UNREACHABLE();
+    return egl::Error(EGL_BAD_SURFACE);
+}
+
+egl::Error SurfaceGL::unMakeCurrent()
+{
+    return egl::Error(EGL_SUCCESS);
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/SurfaceGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/SurfaceGL.h
new file mode 100644
index 0000000..7b805dd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/SurfaceGL.h
@@ -0,0 +1,37 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceGL.h: Defines the class interface for SurfaceGL.
+
+#ifndef LIBANGLE_RENDERER_GL_SURFACEGL_H_
+#define LIBANGLE_RENDERER_GL_SURFACEGL_H_
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace rx
+{
+
+class RendererGL;
+
+class SurfaceGL : public SurfaceImpl
+{
+  public:
+    SurfaceGL(const egl::SurfaceState &state, RendererGL *renderer);
+    ~SurfaceGL() override;
+
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
+    egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+
+    virtual egl::Error makeCurrent() = 0;
+    virtual egl::Error unMakeCurrent();
+
+  private:
+    RendererGL *mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_SURFACEGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/TextureGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/TextureGL.cpp
new file mode 100644
index 0000000..23a48a7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -0,0 +1,1255 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureGL.cpp: Implements the class methods for TextureGL.
+
+#include "libANGLE/renderer/gl/TextureGL.h"
+
+#include "common/bitset_utils.h"
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/BlitGL.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+using angle::CheckedNumeric;
+
+namespace rx
+{
+
+namespace
+{
+
+bool UseTexImage2D(GLenum textureType)
+{
+    return textureType == GL_TEXTURE_2D || textureType == GL_TEXTURE_CUBE_MAP;
+}
+
+bool UseTexImage3D(GLenum textureType)
+{
+    return textureType == GL_TEXTURE_2D_ARRAY || textureType == GL_TEXTURE_3D;
+}
+
+bool CompatibleTextureTarget(GLenum textureType, GLenum textureTarget)
+{
+    if (textureType != GL_TEXTURE_CUBE_MAP)
+    {
+        return textureType == textureTarget;
+    }
+    else
+    {
+        return gl::IsCubeMapTextureTarget(textureTarget);
+    }
+}
+
+bool IsLUMAFormat(GLenum format)
+{
+    return format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA;
+}
+
+LUMAWorkaroundGL GetLUMAWorkaroundInfo(GLenum originalFormat, GLenum destinationFormat)
+{
+    if (IsLUMAFormat(originalFormat))
+    {
+        return LUMAWorkaroundGL(!IsLUMAFormat(destinationFormat), destinationFormat);
+    }
+    else
+    {
+        return LUMAWorkaroundGL(false, GL_NONE);
+    }
+}
+
+bool GetDepthStencilWorkaround(GLenum format)
+{
+    return format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL;
+}
+
+LevelInfoGL GetLevelInfo(GLenum originalInternalFormat, GLenum destinationInternalFormat)
+{
+    GLenum originalFormat    = gl::GetUnsizedFormat(originalInternalFormat);
+    GLenum destinationFormat = gl::GetUnsizedFormat(destinationInternalFormat);
+    return LevelInfoGL(originalFormat, GetDepthStencilWorkaround(originalFormat),
+                       GetLUMAWorkaroundInfo(originalFormat, destinationFormat));
+}
+
+gl::Texture::DirtyBits GetLevelWorkaroundDirtyBits()
+{
+    gl::Texture::DirtyBits bits;
+    bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_RED);
+    bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN);
+    bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE);
+    bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA);
+    return bits;
+}
+
+}  // anonymous namespace
+
+LUMAWorkaroundGL::LUMAWorkaroundGL() : LUMAWorkaroundGL(false, GL_NONE)
+{
+}
+
+LUMAWorkaroundGL::LUMAWorkaroundGL(bool enabled_, GLenum workaroundFormat_)
+    : enabled(enabled_), workaroundFormat(workaroundFormat_)
+{
+}
+
+LevelInfoGL::LevelInfoGL() : LevelInfoGL(GL_NONE, false, LUMAWorkaroundGL())
+{
+}
+
+LevelInfoGL::LevelInfoGL(GLenum sourceFormat_,
+                         bool depthStencilWorkaround_,
+                         const LUMAWorkaroundGL &lumaWorkaround_)
+    : sourceFormat(sourceFormat_),
+      depthStencilWorkaround(depthStencilWorkaround_),
+      lumaWorkaround(lumaWorkaround_)
+{
+}
+
+TextureGL::TextureGL(const gl::TextureState &state,
+                     const FunctionsGL *functions,
+                     const WorkaroundsGL &workarounds,
+                     StateManagerGL *stateManager,
+                     BlitGL *blitter)
+    : TextureImpl(state),
+      mFunctions(functions),
+      mWorkarounds(workarounds),
+      mStateManager(stateManager),
+      mBlitter(blitter),
+      mLevelInfo(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1),
+      mAppliedSwizzle(state.getSwizzleState()),
+      mAppliedSampler(state.getSamplerState()),
+      mAppliedBaseLevel(state.getEffectiveBaseLevel()),
+      mAppliedMaxLevel(state.getEffectiveMaxLevel()),
+      mTextureID(0)
+{
+    ASSERT(mFunctions);
+    ASSERT(mStateManager);
+    ASSERT(mBlitter);
+
+    mFunctions->genTextures(1, &mTextureID);
+    mStateManager->bindTexture(getTarget(), mTextureID);
+}
+
+TextureGL::~TextureGL()
+{
+    mStateManager->deleteTexture(mTextureID);
+    mTextureID = 0;
+}
+
+gl::Error TextureGL::setImage(ContextImpl *contextImpl,
+                              GLenum target,
+                              size_t level,
+                              GLenum internalFormat,
+                              const gl::Extents &size,
+                              GLenum format,
+                              GLenum type,
+                              const gl::PixelUnpackState &unpack,
+                              const uint8_t *pixels)
+{
+    if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpack.pixelBuffer.get() &&
+        unpack.rowLength != 0 && unpack.rowLength < size.width)
+    {
+        // The rows overlap in unpack memory. Upload the texture row by row to work around
+        // driver bug.
+        reserveTexImageToBeFilled(target, level, internalFormat, size, format, type);
+
+        if (size.width == 0 || size.height == 0 || size.depth == 0)
+        {
+            return gl::NoError();
+        }
+
+        gl::Box area(0, 0, 0, size.width, size.height, size.depth);
+        return setSubImageRowByRowWorkaround(target, level, area, format, type, unpack, pixels);
+    }
+
+    if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
+    {
+        bool apply;
+        ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type,
+                                                             UseTexImage3D(getTarget()), pixels),
+                         apply);
+
+        // The driver will think the pixel buffer doesn't have enough data, work around this bug
+        // by uploading the last row (and last level if 3D) separately.
+        if (apply)
+        {
+            reserveTexImageToBeFilled(target, level, internalFormat, size, format, type);
+
+            if (size.width == 0 || size.height == 0 || size.depth == 0)
+            {
+                return gl::NoError();
+            }
+
+            gl::Box area(0, 0, 0, size.width, size.height, size.depth);
+            return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels);
+        }
+    }
+
+    setImageHelper(target, level, internalFormat, size, format, type, pixels);
+
+    return gl::NoError();
+}
+
+void TextureGL::setImageHelper(GLenum target,
+                               size_t level,
+                               GLenum internalFormat,
+                               const gl::Extents &size,
+                               GLenum format,
+                               GLenum type,
+                               const uint8_t *pixels)
+{
+    ASSERT(CompatibleTextureTarget(getTarget(), target));
+
+    nativegl::TexImageFormat texImageFormat =
+        nativegl::GetTexImageFormat(mFunctions, mWorkarounds, internalFormat, format, type);
+
+    mStateManager->bindTexture(getTarget(), mTextureID);
+
+    if (UseTexImage2D(getTarget()))
+    {
+        ASSERT(size.depth == 1);
+        mFunctions->texImage2D(target, static_cast<GLint>(level), texImageFormat.internalFormat,
+                               size.width, size.height, 0, texImageFormat.format,
+                               texImageFormat.type, pixels);
+    }
+    else if (UseTexImage3D(getTarget()))
+    {
+        mFunctions->texImage3D(target, static_cast<GLint>(level), texImageFormat.internalFormat,
+                               size.width, size.height, size.depth, 0, texImageFormat.format,
+                               texImageFormat.type, pixels);
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+
+    setLevelInfo(level, 1, GetLevelInfo(internalFormat, texImageFormat.internalFormat));
+}
+
+void TextureGL::reserveTexImageToBeFilled(GLenum target,
+                                          size_t level,
+                                          GLenum internalFormat,
+                                          const gl::Extents &size,
+                                          GLenum format,
+                                          GLenum type)
+{
+    gl::PixelUnpackState unpack;
+    mStateManager->setPixelUnpackState(unpack);
+    setImageHelper(target, level, internalFormat, size, format, type, nullptr);
+}
+
+gl::Error TextureGL::setSubImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 const gl::Box &area,
+                                 GLenum format,
+                                 GLenum type,
+                                 const gl::PixelUnpackState &unpack,
+                                 const uint8_t *pixels)
+{
+    ASSERT(CompatibleTextureTarget(getTarget(), target));
+
+    nativegl::TexSubImageFormat texSubImageFormat =
+        nativegl::GetTexSubImageFormat(mFunctions, mWorkarounds, format, type);
+
+    ASSERT(mLevelInfo[level].lumaWorkaround.enabled ==
+           GetLevelInfo(format, texSubImageFormat.format).lumaWorkaround.enabled);
+
+    mStateManager->bindTexture(getTarget(), mTextureID);
+    if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpack.pixelBuffer.get() &&
+        unpack.rowLength != 0 && unpack.rowLength < area.width)
+    {
+        return setSubImageRowByRowWorkaround(target, level, area, format, type, unpack, pixels);
+    }
+
+    if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
+    {
+        gl::Extents size(area.width, area.height, area.depth);
+
+        bool apply;
+        ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type,
+                                                             UseTexImage3D(getTarget()), pixels),
+                         apply);
+
+        // The driver will think the pixel buffer doesn't have enough data, work around this bug
+        // by uploading the last row (and last level if 3D) separately.
+        if (apply)
+        {
+            return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels);
+        }
+    }
+
+    if (UseTexImage2D(getTarget()))
+    {
+        ASSERT(area.z == 0 && area.depth == 1);
+        mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, area.y, area.width,
+                                  area.height, texSubImageFormat.format, texSubImageFormat.type,
+                                  pixels);
+    }
+    else
+    {
+        ASSERT(UseTexImage3D(getTarget()));
+        mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, area.y, area.z,
+                                  area.width, area.height, area.depth, texSubImageFormat.format,
+                                  texSubImageFormat.type, pixels);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureGL::setSubImageRowByRowWorkaround(GLenum target,
+                                                   size_t level,
+                                                   const gl::Box &area,
+                                                   GLenum format,
+                                                   GLenum type,
+                                                   const gl::PixelUnpackState &unpack,
+                                                   const uint8_t *pixels)
+{
+    gl::PixelUnpackState directUnpack;
+    directUnpack.pixelBuffer = unpack.pixelBuffer;
+    directUnpack.alignment   = 1;
+    mStateManager->setPixelUnpackState(directUnpack);
+    directUnpack.pixelBuffer.set(nullptr);
+
+    const gl::InternalFormat &glFormat   = gl::GetInternalFormatInfo(format, type);
+    GLuint rowBytes                      = 0;
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+                     rowBytes);
+    GLuint imageBytes = 0;
+    ANGLE_TRY_RESULT(glFormat.computeDepthPitch(area.height, unpack.imageHeight, rowBytes),
+                     imageBytes);
+    bool useTexImage3D = UseTexImage3D(getTarget());
+    GLuint skipBytes   = 0;
+    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
+                     skipBytes);
+
+    const uint8_t *pixelsWithSkip = pixels + skipBytes;
+    if (useTexImage3D)
+    {
+        for (GLint image = 0; image < area.depth; ++image)
+        {
+            GLint imageByteOffset = image * imageBytes;
+            for (GLint row = 0; row < area.height; ++row)
+            {
+                GLint byteOffset         = imageByteOffset + row * rowBytes;
+                const GLubyte *rowPixels = pixelsWithSkip + byteOffset;
+                mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, row + area.y,
+                                          image + area.z, area.width, 1, 1, format, type,
+                                          rowPixels);
+            }
+        }
+    }
+    else
+    {
+        ASSERT(UseTexImage2D(getTarget()));
+        for (GLint row = 0; row < area.height; ++row)
+        {
+            GLint byteOffset         = row * rowBytes;
+            const GLubyte *rowPixels = pixelsWithSkip + byteOffset;
+            mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, row + area.y,
+                                      area.width, 1, format, type, rowPixels);
+        }
+    }
+    return gl::NoError();
+}
+
+gl::Error TextureGL::setSubImagePaddingWorkaround(GLenum target,
+                                                  size_t level,
+                                                  const gl::Box &area,
+                                                  GLenum format,
+                                                  GLenum type,
+                                                  const gl::PixelUnpackState &unpack,
+                                                  const uint8_t *pixels)
+{
+    const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
+    GLuint rowBytes = 0;
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+                     rowBytes);
+    GLuint imageBytes = 0;
+    ANGLE_TRY_RESULT(glFormat.computeDepthPitch(area.height, unpack.imageHeight, rowBytes),
+                     imageBytes);
+    bool useTexImage3D = UseTexImage3D(getTarget());
+    GLuint skipBytes   = 0;
+    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
+                     skipBytes);
+
+    mStateManager->setPixelUnpackState(unpack);
+
+    gl::PixelUnpackState directUnpack;
+    directUnpack.pixelBuffer = unpack.pixelBuffer;
+    directUnpack.alignment   = 1;
+
+    if (useTexImage3D)
+    {
+        // Upload all but the last slice
+        if (area.depth > 1)
+        {
+            mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, area.y, area.z,
+                                      area.width, area.height, area.depth - 1, format, type,
+                                      pixels);
+        }
+
+        // Upload the last slice but its last row
+        if (area.height > 1)
+        {
+            // Do not include skipBytes in the last image pixel start offset as it will be done by
+            // the driver
+            GLint lastImageOffset          = (area.depth - 1) * imageBytes;
+            const GLubyte *lastImagePixels = pixels + lastImageOffset;
+            mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, area.y,
+                                      area.z + area.depth - 1, area.width, area.height - 1, 1,
+                                      format, type, lastImagePixels);
+        }
+
+        // Upload the last row of the last slice "manually"
+        mStateManager->setPixelUnpackState(directUnpack);
+
+        GLint lastRowOffset =
+            skipBytes + (area.depth - 1) * imageBytes + (area.height - 1) * rowBytes;
+        const GLubyte *lastRowPixels = pixels + lastRowOffset;
+        mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x,
+                                  area.y + area.height - 1, area.z + area.depth - 1, area.width, 1,
+                                  1, format, type, lastRowPixels);
+    }
+    else
+    {
+        ASSERT(UseTexImage2D(getTarget()));
+
+        // Upload all but the last row
+        if (area.height > 1)
+        {
+            mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, area.y, area.width,
+                                      area.height - 1, format, type, pixels);
+        }
+
+        // Upload the last row "manually"
+        mStateManager->setPixelUnpackState(directUnpack);
+
+        GLint lastRowOffset          = skipBytes + (area.height - 1) * rowBytes;
+        const GLubyte *lastRowPixels = pixels + lastRowOffset;
+        mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x,
+                                  area.y + area.height - 1, area.width, 1, format, type,
+                                  lastRowPixels);
+    }
+
+    directUnpack.pixelBuffer.set(nullptr);
+
+    return gl::NoError();
+}
+
+gl::Error TextureGL::setCompressedImage(ContextImpl *contextImpl,
+                                        GLenum target,
+                                        size_t level,
+                                        GLenum internalFormat,
+                                        const gl::Extents &size,
+                                        const gl::PixelUnpackState &unpack,
+                                        size_t imageSize,
+                                        const uint8_t *pixels)
+{
+    ASSERT(CompatibleTextureTarget(getTarget(), target));
+
+    nativegl::CompressedTexImageFormat compressedTexImageFormat =
+        nativegl::GetCompressedTexImageFormat(mFunctions, mWorkarounds, internalFormat);
+
+    mStateManager->bindTexture(getTarget(), mTextureID);
+    if (UseTexImage2D(getTarget()))
+    {
+        ASSERT(size.depth == 1);
+        mFunctions->compressedTexImage2D(target, static_cast<GLint>(level),
+                                         compressedTexImageFormat.internalFormat, size.width,
+                                         size.height, 0, static_cast<GLsizei>(imageSize), pixels);
+    }
+    else if (UseTexImage3D(getTarget()))
+    {
+        mFunctions->compressedTexImage3D(
+            target, static_cast<GLint>(level), compressedTexImageFormat.internalFormat, size.width,
+            size.height, size.depth, 0, static_cast<GLsizei>(imageSize), pixels);
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+
+    setLevelInfo(level, 1, GetLevelInfo(internalFormat, compressedTexImageFormat.internalFormat));
+    ASSERT(!mLevelInfo[level].lumaWorkaround.enabled);
+
+    return gl::NoError();
+}
+
+gl::Error TextureGL::setCompressedSubImage(ContextImpl *contextImpl,
+                                           GLenum target,
+                                           size_t level,
+                                           const gl::Box &area,
+                                           GLenum format,
+                                           const gl::PixelUnpackState &unpack,
+                                           size_t imageSize,
+                                           const uint8_t *pixels)
+{
+    ASSERT(CompatibleTextureTarget(getTarget(), target));
+
+    nativegl::CompressedTexSubImageFormat compressedTexSubImageFormat =
+        nativegl::GetCompressedSubTexImageFormat(mFunctions, mWorkarounds, format);
+
+    mStateManager->bindTexture(getTarget(), mTextureID);
+    if (UseTexImage2D(getTarget()))
+    {
+        ASSERT(area.z == 0 && area.depth == 1);
+        mFunctions->compressedTexSubImage2D(
+            target, static_cast<GLint>(level), area.x, area.y, area.width, area.height,
+            compressedTexSubImageFormat.format, static_cast<GLsizei>(imageSize), pixels);
+    }
+    else if (UseTexImage3D(getTarget()))
+    {
+        mFunctions->compressedTexSubImage3D(target, static_cast<GLint>(level), area.x, area.y,
+                                            area.z, area.width, area.height, area.depth,
+                                            compressedTexSubImageFormat.format,
+                                            static_cast<GLsizei>(imageSize), pixels);
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+
+    ASSERT(!mLevelInfo[level].lumaWorkaround.enabled &&
+           !GetLevelInfo(format, compressedTexSubImageFormat.format).lumaWorkaround.enabled);
+
+    return gl::NoError();
+}
+
+gl::Error TextureGL::copyImage(ContextImpl *contextImpl,
+                               GLenum target,
+                               size_t level,
+                               const gl::Rectangle &sourceArea,
+                               GLenum internalFormat,
+                               const gl::Framebuffer *source)
+{
+    nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
+        mFunctions, mWorkarounds, internalFormat, source->getImplementationColorReadType());
+
+    LevelInfoGL levelInfo = GetLevelInfo(internalFormat, copyTexImageFormat.internalFormat);
+    if (levelInfo.lumaWorkaround.enabled)
+    {
+        gl::Error error = mBlitter->copyImageToLUMAWorkaroundTexture(
+            mTextureID, getTarget(), target, levelInfo.sourceFormat, level, sourceArea,
+            copyTexImageFormat.internalFormat, source);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+    else
+    {
+        const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
+
+        mStateManager->bindTexture(getTarget(), mTextureID);
+        mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER,
+                                       sourceFramebufferGL->getFramebufferID());
+
+        if (UseTexImage2D(getTarget()))
+        {
+            mFunctions->copyTexImage2D(target, static_cast<GLint>(level),
+                                       copyTexImageFormat.internalFormat, sourceArea.x,
+                                       sourceArea.y, sourceArea.width, sourceArea.height, 0);
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+    }
+
+    setLevelInfo(level, 1, levelInfo);
+
+    return gl::NoError();
+}
+
+gl::Error TextureGL::copySubImage(ContextImpl *contextImpl,
+                                  GLenum target,
+                                  size_t level,
+                                  const gl::Offset &destOffset,
+                                  const gl::Rectangle &sourceArea,
+                                  const gl::Framebuffer *source)
+{
+    const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
+
+    mStateManager->bindTexture(getTarget(), mTextureID);
+    mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
+
+    const LevelInfoGL &levelInfo = mLevelInfo[level];
+    if (levelInfo.lumaWorkaround.enabled)
+    {
+        gl::Error error = mBlitter->copySubImageToLUMAWorkaroundTexture(
+            mTextureID, getTarget(), target, levelInfo.sourceFormat, level, destOffset, sourceArea,
+            source);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+    else
+    {
+        if (UseTexImage2D(getTarget()))
+        {
+            ASSERT(destOffset.z == 0);
+            mFunctions->copyTexSubImage2D(target, static_cast<GLint>(level), destOffset.x,
+                                          destOffset.y, sourceArea.x, sourceArea.y,
+                                          sourceArea.width, sourceArea.height);
+        }
+        else if (UseTexImage3D(getTarget()))
+        {
+            mFunctions->copyTexSubImage3D(target, static_cast<GLint>(level), destOffset.x,
+                                          destOffset.y, destOffset.z, sourceArea.x, sourceArea.y,
+                                          sourceArea.width, sourceArea.height);
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error TextureGL::copyTexture(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 GLenum type,
+                                 size_t sourceLevel,
+                                 bool unpackFlipY,
+                                 bool unpackPremultiplyAlpha,
+                                 bool unpackUnmultiplyAlpha,
+                                 const gl::Texture *source)
+{
+    const TextureGL *sourceGL            = GetImplAs<TextureGL>(source);
+    const gl::ImageDesc &sourceImageDesc = sourceGL->mState.getImageDesc(source->getTarget(), 0);
+    gl::Rectangle sourceArea(0, 0, sourceImageDesc.size.width, sourceImageDesc.size.height);
+
+    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+    reserveTexImageToBeFilled(getTarget(), 0, internalFormatInfo.sizedInternalFormat,
+                              sourceImageDesc.size, internalFormat, type);
+
+    return copySubTextureHelper(target, level, gl::Offset(0, 0, 0), sourceLevel, sourceArea,
+                                internalFormat, unpackFlipY, unpackPremultiplyAlpha,
+                                unpackUnmultiplyAlpha, source);
+}
+
+gl::Error TextureGL::copySubTexture(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Offset &destOffset,
+                                    size_t sourceLevel,
+                                    const gl::Rectangle &sourceArea,
+                                    bool unpackFlipY,
+                                    bool unpackPremultiplyAlpha,
+                                    bool unpackUnmultiplyAlpha,
+                                    const gl::Texture *source)
+{
+    GLenum destFormat = mState.getImageDesc(mState.mTarget, 0).format.info->format;
+    return copySubTextureHelper(target, level, destOffset, sourceLevel, sourceArea, destFormat,
+                                unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha, source);
+}
+
+gl::Error TextureGL::copySubTextureHelper(GLenum target,
+                                          size_t level,
+                                          const gl::Offset &destOffset,
+                                          size_t sourceLevel,
+                                          const gl::Rectangle &sourceArea,
+                                          GLenum destFormat,
+                                          bool unpackFlipY,
+                                          bool unpackPremultiplyAlpha,
+                                          bool unpackUnmultiplyAlpha,
+                                          const gl::Texture *source)
+{
+    TextureGL *sourceGL                  = GetImplAs<TextureGL>(source);
+    const gl::ImageDesc &sourceImageDesc = sourceGL->mState.getImageDesc(source->getTarget(), 0);
+
+    // Check is this is a simple copySubTexture that can be done with a copyTexSubImage
+    bool needsLumaWorkaround = sourceGL->mLevelInfo[0].lumaWorkaround.enabled;
+
+    GLenum sourceFormat = sourceImageDesc.format.info->format;
+    bool sourceFormatContainSupersetOfDestFormat =
+        (sourceFormat == destFormat && sourceFormat != GL_BGRA_EXT) ||
+        (sourceFormat == GL_RGBA && destFormat == GL_RGB);
+
+    if (source->getTarget() == GL_TEXTURE_2D && getTarget() == GL_TEXTURE_2D && !unpackFlipY &&
+        unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !needsLumaWorkaround &&
+        sourceFormatContainSupersetOfDestFormat)
+    {
+        return mBlitter->copyTexSubImage(sourceGL, this, sourceArea, destOffset);
+    }
+
+    // We can't use copyTexSubImage, do a manual copy
+    return mBlitter->copySubTexture(
+        sourceGL, sourceLevel, this, target, level, sourceImageDesc.size, sourceArea, destOffset,
+        needsLumaWorkaround, sourceGL->mLevelInfo[sourceLevel].sourceFormat, unpackFlipY,
+        unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+}
+
+gl::Error TextureGL::setStorage(ContextImpl *contextImpl,
+                                GLenum target,
+                                size_t levels,
+                                GLenum internalFormat,
+                                const gl::Extents &size)
+{
+    nativegl::TexStorageFormat texStorageFormat =
+        nativegl::GetTexStorageFormat(mFunctions, mWorkarounds, internalFormat);
+
+    mStateManager->bindTexture(getTarget(), mTextureID);
+    if (UseTexImage2D(getTarget()))
+    {
+        ASSERT(size.depth == 1);
+        if (mFunctions->texStorage2D)
+        {
+            mFunctions->texStorage2D(target, static_cast<GLsizei>(levels),
+                                     texStorageFormat.internalFormat, size.width, size.height);
+        }
+        else
+        {
+            // Make sure no pixel unpack buffer is bound
+            mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+            const gl::InternalFormat &internalFormatInfo =
+                gl::GetSizedInternalFormatInfo(internalFormat);
+
+            // Internal format must be sized
+            ASSERT(internalFormatInfo.sized);
+
+            for (size_t level = 0; level < levels; level++)
+            {
+                gl::Extents levelSize(std::max(size.width >> level, 1),
+                                      std::max(size.height >> level, 1),
+                                      1);
+
+                if (getTarget() == GL_TEXTURE_2D)
+                {
+                    if (internalFormatInfo.compressed)
+                    {
+                        nativegl::CompressedTexSubImageFormat compressedTexImageFormat =
+                            nativegl::GetCompressedSubTexImageFormat(mFunctions, mWorkarounds,
+                                                                     internalFormat);
+
+                        GLuint dataSize = 0;
+                        ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(
+                                             GL_UNSIGNED_BYTE, levelSize),
+                                         dataSize);
+                        mFunctions->compressedTexImage2D(target, static_cast<GLint>(level),
+                                                         compressedTexImageFormat.format,
+                                                         levelSize.width, levelSize.height, 0,
+                                                         static_cast<GLsizei>(dataSize), nullptr);
+                    }
+                    else
+                    {
+                        nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
+                            mFunctions, mWorkarounds, internalFormat, internalFormatInfo.format,
+                            internalFormatInfo.type);
+
+                        mFunctions->texImage2D(target, static_cast<GLint>(level),
+                                               texImageFormat.internalFormat, levelSize.width,
+                                               levelSize.height, 0, texImageFormat.format,
+                                               texImageFormat.type, nullptr);
+                    }
+                }
+                else if (getTarget() == GL_TEXTURE_CUBE_MAP)
+                {
+                    for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; face++)
+                    {
+                        if (internalFormatInfo.compressed)
+                        {
+                            nativegl::CompressedTexSubImageFormat compressedTexImageFormat =
+                                nativegl::GetCompressedSubTexImageFormat(mFunctions, mWorkarounds,
+                                                                         internalFormat);
+
+                            GLuint dataSize = 0;
+                            ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(
+                                                 GL_UNSIGNED_BYTE, levelSize),
+                                             dataSize);
+                            mFunctions->compressedTexImage2D(
+                                face, static_cast<GLint>(level), compressedTexImageFormat.format,
+                                levelSize.width, levelSize.height, 0,
+                                static_cast<GLsizei>(dataSize), nullptr);
+                        }
+                        else
+                        {
+                            nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
+                                mFunctions, mWorkarounds, internalFormat, internalFormatInfo.format,
+                                internalFormatInfo.type);
+
+                            mFunctions->texImage2D(face, static_cast<GLint>(level),
+                                                   texImageFormat.internalFormat, levelSize.width,
+                                                   levelSize.height, 0, texImageFormat.format,
+                                                   texImageFormat.type, nullptr);
+                        }
+                    }
+                }
+                else
+                {
+                    UNREACHABLE();
+                }
+            }
+        }
+    }
+    else if (UseTexImage3D(getTarget()))
+    {
+        if (mFunctions->texStorage3D)
+        {
+            mFunctions->texStorage3D(target, static_cast<GLsizei>(levels),
+                                     texStorageFormat.internalFormat, size.width, size.height,
+                                     size.depth);
+        }
+        else
+        {
+            // Make sure no pixel unpack buffer is bound
+            mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+            const gl::InternalFormat &internalFormatInfo =
+                gl::GetSizedInternalFormatInfo(internalFormat);
+
+            // Internal format must be sized
+            ASSERT(internalFormatInfo.sized);
+
+            for (GLsizei i = 0; i < static_cast<GLsizei>(levels); i++)
+            {
+                gl::Extents levelSize(
+                    std::max(size.width >> i, 1), std::max(size.height >> i, 1),
+                    getTarget() == GL_TEXTURE_3D ? std::max(size.depth >> i, 1) : size.depth);
+
+                if (internalFormatInfo.compressed)
+                {
+                    nativegl::CompressedTexSubImageFormat compressedTexImageFormat =
+                        nativegl::GetCompressedSubTexImageFormat(mFunctions, mWorkarounds,
+                                                                 internalFormat);
+
+                    GLuint dataSize = 0;
+                    ANGLE_TRY_RESULT(
+                        internalFormatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, levelSize),
+                        dataSize);
+                    mFunctions->compressedTexImage3D(target, i, compressedTexImageFormat.format,
+                                                     levelSize.width, levelSize.height,
+                                                     levelSize.depth, 0,
+                                                     static_cast<GLsizei>(dataSize), nullptr);
+                }
+                else
+                {
+                    nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
+                        mFunctions, mWorkarounds, internalFormat, internalFormatInfo.format,
+                        internalFormatInfo.type);
+
+                    mFunctions->texImage3D(target, i, texImageFormat.internalFormat,
+                                           levelSize.width, levelSize.height, levelSize.depth, 0,
+                                           texImageFormat.format, texImageFormat.type, nullptr);
+                }
+            }
+        }
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+
+    setLevelInfo(0, levels, GetLevelInfo(internalFormat, texStorageFormat.internalFormat));
+
+    return gl::NoError();
+}
+
+gl::Error TextureGL::setStorageMultisample(ContextImpl *contextImpl,
+                                           GLenum target,
+                                           GLsizei samples,
+                                           GLint internalFormat,
+                                           const gl::Extents &size,
+                                           GLboolean fixedSampleLocations)
+{
+    nativegl::TexStorageFormat texStorageFormat =
+        nativegl::GetTexStorageFormat(mFunctions, mWorkarounds, internalFormat);
+
+    mStateManager->bindTexture(mState.mTarget, mTextureID);
+
+    ASSERT(size.depth == 1);
+
+    mFunctions->texStorage2DMultisample(target, samples, texStorageFormat.internalFormat,
+                                        size.width, size.height, fixedSampleLocations);
+
+    setLevelInfo(0, 1, GetLevelInfo(internalFormat, texStorageFormat.internalFormat));
+
+    return gl::NoError();
+}
+
+gl::Error TextureGL::setImageExternal(GLenum target,
+                                      egl::Stream *stream,
+                                      const egl::Stream::GLTextureDescription &desc)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureGL::generateMipmap(ContextImpl *contextImpl)
+{
+    mStateManager->bindTexture(getTarget(), mTextureID);
+    mFunctions->generateMipmap(getTarget());
+
+    const GLuint effectiveBaseLevel = mState.getEffectiveBaseLevel();
+    const GLuint maxLevel           = mState.getMipmapMaxLevel();
+
+    ASSERT(maxLevel < mLevelInfo.size());
+
+    setLevelInfo(effectiveBaseLevel, maxLevel - effectiveBaseLevel, mLevelInfo[effectiveBaseLevel]);
+
+    return gl::NoError();
+}
+
+void TextureGL::bindTexImage(egl::Surface *surface)
+{
+    ASSERT(getTarget() == GL_TEXTURE_2D);
+
+    // Make sure this texture is bound
+    mStateManager->bindTexture(getTarget(), mTextureID);
+
+    setLevelInfo(0, 1, LevelInfoGL());
+}
+
+void TextureGL::releaseTexImage()
+{
+    // Not all Surface implementations reset the size of mip 0 when releasing, do it manually
+    ASSERT(getTarget() == GL_TEXTURE_2D);
+
+    mStateManager->bindTexture(getTarget(), mTextureID);
+    if (UseTexImage2D(getTarget()))
+    {
+        mFunctions->texImage2D(getTarget(), 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                               nullptr);
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+}
+
+gl::Error TextureGL::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+void TextureGL::syncState(const gl::Texture::DirtyBits &dirtyBits)
+{
+    if (dirtyBits.none() && mLocalDirtyBits.none())
+    {
+        return;
+    }
+
+    mStateManager->bindTexture(getTarget(), mTextureID);
+
+    if (dirtyBits[gl::Texture::DIRTY_BIT_BASE_LEVEL] || dirtyBits[gl::Texture::DIRTY_BIT_MAX_LEVEL])
+    {
+        // Don't know if the previous base level was using any workarounds, always re-sync the
+        // workaround dirty bits
+        mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
+    }
+
+    for (auto dirtyBit : (dirtyBits | mLocalDirtyBits))
+    {
+        switch (dirtyBit)
+        {
+            case gl::Texture::DIRTY_BIT_MIN_FILTER:
+                mAppliedSampler.minFilter = mState.getSamplerState().minFilter;
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_MIN_FILTER,
+                                          mAppliedSampler.minFilter);
+                break;
+            case gl::Texture::DIRTY_BIT_MAG_FILTER:
+                mAppliedSampler.magFilter = mState.getSamplerState().magFilter;
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_MAG_FILTER,
+                                          mAppliedSampler.magFilter);
+                break;
+            case gl::Texture::DIRTY_BIT_WRAP_S:
+                mAppliedSampler.wrapS = mState.getSamplerState().wrapS;
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_WRAP_S, mAppliedSampler.wrapS);
+                break;
+            case gl::Texture::DIRTY_BIT_WRAP_T:
+                mAppliedSampler.wrapT = mState.getSamplerState().wrapT;
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_WRAP_T, mAppliedSampler.wrapT);
+                break;
+            case gl::Texture::DIRTY_BIT_WRAP_R:
+                mAppliedSampler.wrapR = mState.getSamplerState().wrapR;
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_WRAP_R, mAppliedSampler.wrapR);
+                break;
+            case gl::Texture::DIRTY_BIT_MAX_ANISOTROPY:
+                mAppliedSampler.maxAnisotropy = mState.getSamplerState().maxAnisotropy;
+                mFunctions->texParameterf(getTarget(), GL_TEXTURE_MAX_ANISOTROPY_EXT,
+                                          mAppliedSampler.maxAnisotropy);
+                break;
+            case gl::Texture::DIRTY_BIT_MIN_LOD:
+                mAppliedSampler.minLod = mState.getSamplerState().minLod;
+                mFunctions->texParameterf(getTarget(), GL_TEXTURE_MIN_LOD, mAppliedSampler.minLod);
+                break;
+            case gl::Texture::DIRTY_BIT_MAX_LOD:
+                mAppliedSampler.maxLod = mState.getSamplerState().maxLod;
+                mFunctions->texParameterf(getTarget(), GL_TEXTURE_MAX_LOD, mAppliedSampler.maxLod);
+                break;
+            case gl::Texture::DIRTY_BIT_COMPARE_MODE:
+                mAppliedSampler.compareMode = mState.getSamplerState().compareMode;
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_COMPARE_MODE,
+                                          mAppliedSampler.compareMode);
+                break;
+            case gl::Texture::DIRTY_BIT_COMPARE_FUNC:
+                mAppliedSampler.compareFunc = mState.getSamplerState().compareFunc;
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_COMPARE_FUNC,
+                                          mAppliedSampler.compareFunc);
+                break;
+            case gl::Texture::DIRTY_BIT_SRGB_DECODE:
+                mAppliedSampler.sRGBDecode = mState.getSamplerState().sRGBDecode;
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_SRGB_DECODE_EXT,
+                                          mAppliedSampler.sRGBDecode);
+                break;
+
+            // Texture state
+            case gl::Texture::DIRTY_BIT_SWIZZLE_RED:
+                syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_R,
+                                        mState.getSwizzleState().swizzleRed,
+                                        &mAppliedSwizzle.swizzleRed);
+                break;
+            case gl::Texture::DIRTY_BIT_SWIZZLE_GREEN:
+                syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_G,
+                                        mState.getSwizzleState().swizzleGreen,
+                                        &mAppliedSwizzle.swizzleGreen);
+                break;
+            case gl::Texture::DIRTY_BIT_SWIZZLE_BLUE:
+                syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_B,
+                                        mState.getSwizzleState().swizzleBlue,
+                                        &mAppliedSwizzle.swizzleBlue);
+                break;
+            case gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA:
+                syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_A,
+                                        mState.getSwizzleState().swizzleAlpha,
+                                        &mAppliedSwizzle.swizzleAlpha);
+                break;
+            case gl::Texture::DIRTY_BIT_BASE_LEVEL:
+                mAppliedBaseLevel = mState.getEffectiveBaseLevel();
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_BASE_LEVEL, mAppliedBaseLevel);
+                break;
+            case gl::Texture::DIRTY_BIT_MAX_LEVEL:
+                mAppliedMaxLevel = mState.getEffectiveMaxLevel();
+                mFunctions->texParameteri(getTarget(), GL_TEXTURE_MAX_LEVEL, mAppliedMaxLevel);
+                break;
+            case gl::Texture::DIRTY_BIT_USAGE:
+                break;
+
+            default:
+                UNREACHABLE();
+        }
+    }
+
+    mLocalDirtyBits.reset();
+}
+
+bool TextureGL::hasAnyDirtyBit() const
+{
+    return mLocalDirtyBits.any();
+}
+
+void TextureGL::setBaseLevel(GLuint baseLevel)
+{
+    if (baseLevel != mAppliedBaseLevel)
+    {
+        mAppliedBaseLevel = baseLevel;
+        mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_BASE_LEVEL);
+
+        mStateManager->bindTexture(getTarget(), mTextureID);
+        mFunctions->texParameteri(getTarget(), GL_TEXTURE_BASE_LEVEL, baseLevel);
+    }
+}
+
+void TextureGL::setMinFilter(GLenum filter)
+{
+    if (filter != mAppliedSampler.minFilter)
+    {
+        mAppliedSampler.minFilter = filter;
+        mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MIN_FILTER);
+
+        mStateManager->bindTexture(getTarget(), mTextureID);
+        mFunctions->texParameteri(getTarget(), GL_TEXTURE_MIN_FILTER, filter);
+    }
+}
+void TextureGL::setMagFilter(GLenum filter)
+{
+    if (filter != mAppliedSampler.magFilter)
+    {
+        mAppliedSampler.magFilter = filter;
+        mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MAG_FILTER);
+
+        mStateManager->bindTexture(getTarget(), mTextureID);
+        mFunctions->texParameteri(getTarget(), GL_TEXTURE_MAG_FILTER, filter);
+    }
+}
+
+void TextureGL::setSwizzle(GLint swizzle[4])
+{
+    gl::SwizzleState resultingSwizzle =
+        gl::SwizzleState(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
+
+    if (resultingSwizzle != mAppliedSwizzle)
+    {
+        mAppliedSwizzle = resultingSwizzle;
+        mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_RED);
+        mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN);
+        mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE);
+        mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA);
+
+        mStateManager->bindTexture(getTarget(), mTextureID);
+        mFunctions->texParameteriv(getTarget(), GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+    }
+}
+
+void TextureGL::syncTextureStateSwizzle(const FunctionsGL *functions,
+                                        GLenum name,
+                                        GLenum value,
+                                        GLenum *outValue)
+{
+    const LevelInfoGL &levelInfo = mLevelInfo[mState.getEffectiveBaseLevel()];
+    GLenum resultSwizzle         = value;
+    if (levelInfo.lumaWorkaround.enabled || levelInfo.depthStencilWorkaround)
+    {
+        if (levelInfo.lumaWorkaround.enabled)
+        {
+            switch (value)
+            {
+            case GL_RED:
+            case GL_GREEN:
+            case GL_BLUE:
+                if (levelInfo.sourceFormat == GL_LUMINANCE ||
+                    levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
+                {
+                    // Texture is backed by a RED or RG texture, point all color channels at the red
+                    // channel.
+                    ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED ||
+                           levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
+                    resultSwizzle = GL_RED;
+                }
+                else if (levelInfo.sourceFormat == GL_ALPHA)
+                {
+                    // Color channels are not supposed to exist, make them always sample 0.
+                    resultSwizzle = GL_ZERO;
+                }
+                else
+                {
+                    UNREACHABLE();
+                }
+                break;
+
+            case GL_ALPHA:
+                if (levelInfo.sourceFormat == GL_LUMINANCE)
+                {
+                    // Alpha channel is not supposed to exist, make it always sample 1.
+                    resultSwizzle = GL_ONE;
+                }
+                else if (levelInfo.sourceFormat == GL_ALPHA)
+                {
+                    // Texture is backed by a RED texture, point the alpha channel at the red
+                    // channel.
+                    ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED);
+                    resultSwizzle = GL_RED;
+                }
+                else if (levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
+                {
+                    // Texture is backed by an RG texture, point the alpha channel at the green
+                    // channel.
+                    ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
+                    resultSwizzle = GL_GREEN;
+                }
+                else
+                {
+                    UNREACHABLE();
+                }
+                break;
+
+            case GL_ZERO:
+            case GL_ONE:
+                // Don't modify the swizzle state when requesting ZERO or ONE.
+                resultSwizzle = value;
+                break;
+
+            default:
+                UNREACHABLE();
+                break;
+            }
+        }
+        else if (levelInfo.depthStencilWorkaround)
+        {
+            switch (value)
+            {
+                case GL_RED:
+                    // Don't modify the swizzle state when requesting the red channel.
+                    resultSwizzle = value;
+                    break;
+
+                case GL_GREEN:
+                case GL_BLUE:
+                    // Depth textures should sample 0 from the green and blue channels.
+                    resultSwizzle = GL_ZERO;
+                    break;
+
+                case GL_ALPHA:
+                    // Depth textures should sample 1 from the alpha channel.
+                    resultSwizzle = GL_ONE;
+                    break;
+
+                case GL_ZERO:
+                case GL_ONE:
+                    // Don't modify the swizzle state when requesting ZERO or ONE.
+                    resultSwizzle = value;
+                    break;
+
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+
+    }
+
+    *outValue = resultSwizzle;
+    functions->texParameteri(getTarget(), name, resultSwizzle);
+}
+
+void TextureGL::setLevelInfo(size_t level, size_t levelCount, const LevelInfoGL &levelInfo)
+{
+    ASSERT(levelCount > 0 && level + levelCount < mLevelInfo.size());
+
+    GLuint baseLevel              = mState.getEffectiveBaseLevel();
+    bool needsResync              = level <= baseLevel && level + levelCount >= baseLevel &&
+                       (levelInfo.depthStencilWorkaround || levelInfo.lumaWorkaround.enabled);
+    if (needsResync)
+    {
+        mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
+    }
+
+    for (size_t i = level; i < level + levelCount; i++)
+    {
+        mLevelInfo[i] = levelInfo;
+    }
+}
+
+GLuint TextureGL::getTextureID() const
+{
+    return mTextureID;
+}
+
+GLenum TextureGL::getTarget() const
+{
+    return mState.mTarget;
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/TextureGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/TextureGL.h
new file mode 100644
index 0000000..e302f93
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/TextureGL.h
@@ -0,0 +1,234 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureGL.h: Defines the class interface for TextureGL.
+
+#ifndef LIBANGLE_RENDERER_GL_TEXTUREGL_H_
+#define LIBANGLE_RENDERER_GL_TEXTUREGL_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/Texture.h"
+
+namespace rx
+{
+
+class BlitGL;
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+struct LUMAWorkaroundGL
+{
+    bool enabled;
+    GLenum workaroundFormat;
+
+    LUMAWorkaroundGL();
+    LUMAWorkaroundGL(bool enabled, GLenum workaroundFormat);
+};
+
+// Structure containing information about format and workarounds for each mip level of the
+// TextureGL.
+struct LevelInfoGL
+{
+    // Format of the data used in this mip level.
+    GLenum sourceFormat;
+
+    // If this mip level requires sampler-state re-writing so that only a red channel is exposed.
+    bool depthStencilWorkaround;
+
+    // Information about luminance alpha texture workarounds in the core profile.
+    LUMAWorkaroundGL lumaWorkaround;
+
+    LevelInfoGL();
+    LevelInfoGL(GLenum sourceFormat,
+                bool depthStencilWorkaround,
+                const LUMAWorkaroundGL &lumaWorkaround);
+};
+
+class TextureGL : public TextureImpl
+{
+  public:
+    TextureGL(const gl::TextureState &state,
+              const FunctionsGL *functions,
+              const WorkaroundsGL &workarounds,
+              StateManagerGL *stateManager,
+              BlitGL *blitter);
+    ~TextureGL() override;
+
+    gl::Error setImage(ContextImpl *contextImpl,
+                       GLenum target,
+                       size_t level,
+                       GLenum internalFormat,
+                       const gl::Extents &size,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels) override;
+    gl::Error setSubImage(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          const gl::Box &area,
+                          GLenum format,
+                          GLenum type,
+                          const gl::PixelUnpackState &unpack,
+                          const uint8_t *pixels) override;
+
+    gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size,
+                                 const gl::PixelUnpackState &unpack,
+                                 size_t imageSize,
+                                 const uint8_t *pixels) override;
+    gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Box &area,
+                                    GLenum format,
+                                    const gl::PixelUnpackState &unpack,
+                                    size_t imageSize,
+                                    const uint8_t *pixels) override;
+
+    gl::Error copyImage(ContextImpl *contextImpl,
+                        GLenum target,
+                        size_t level,
+                        const gl::Rectangle &sourceArea,
+                        GLenum internalFormat,
+                        const gl::Framebuffer *source) override;
+    gl::Error copySubImage(ContextImpl *contextImpl,
+                           GLenum target,
+                           size_t level,
+                           const gl::Offset &destOffset,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Framebuffer *source) override;
+
+    gl::Error copyTexture(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          GLenum internalFormat,
+                          GLenum type,
+                          size_t sourceLevel,
+                          bool unpackFlipY,
+                          bool unpackPremultiplyAlpha,
+                          bool unpackUnmultiplyAlpha,
+                          const gl::Texture *source) override;
+    gl::Error copySubTexture(ContextImpl *contextImpl,
+                             GLenum target,
+                             size_t level,
+                             const gl::Offset &destOffset,
+                             size_t sourceLevel,
+                             const gl::Rectangle &sourceArea,
+                             bool unpackFlipY,
+                             bool unpackPremultiplyAlpha,
+                             bool unpackUnmultiplyAlpha,
+                             const gl::Texture *source) override;
+    gl::Error copySubTextureHelper(GLenum target,
+                                   size_t level,
+                                   const gl::Offset &destOffset,
+                                   size_t sourceLevel,
+                                   const gl::Rectangle &sourceArea,
+                                   GLenum destFormat,
+                                   bool unpackFlipY,
+                                   bool unpackPremultiplyAlpha,
+                                   bool unpackUnmultiplyAlpha,
+                                   const gl::Texture *source);
+
+    gl::Error setStorage(ContextImpl *contextImpl,
+                         GLenum target,
+                         size_t levels,
+                         GLenum internalFormat,
+                         const gl::Extents &size) override;
+
+    gl::Error setStorageMultisample(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    GLsizei samples,
+                                    GLint internalFormat,
+                                    const gl::Extents &size,
+                                    GLboolean fixedSampleLocations) override;
+
+    gl::Error setImageExternal(GLenum target,
+                               egl::Stream *stream,
+                               const egl::Stream::GLTextureDescription &desc) override;
+
+    gl::Error generateMipmap(ContextImpl *contextImpl) override;
+
+    void bindTexImage(egl::Surface *surface) override;
+    void releaseTexImage() override;
+
+    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+    GLuint getTextureID() const;
+    GLenum getTarget() const;
+
+    void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+    bool hasAnyDirtyBit() const;
+
+    void setBaseLevel(GLuint baseLevel) override;
+
+    void setMinFilter(GLenum filter);
+    void setMagFilter(GLenum filter);
+
+    void setSwizzle(GLint swizzle[4]);
+
+  private:
+    void setImageHelper(GLenum target,
+                        size_t level,
+                        GLenum internalFormat,
+                        const gl::Extents &size,
+                        GLenum format,
+                        GLenum type,
+                        const uint8_t *pixels);
+    // This changes the current pixel unpack state that will have to be reapplied.
+    void reserveTexImageToBeFilled(GLenum target,
+                                   size_t level,
+                                   GLenum internalFormat,
+                                   const gl::Extents &size,
+                                   GLenum format,
+                                   GLenum type);
+    gl::Error setSubImageRowByRowWorkaround(GLenum target,
+                                            size_t level,
+                                            const gl::Box &area,
+                                            GLenum format,
+                                            GLenum type,
+                                            const gl::PixelUnpackState &unpack,
+                                            const uint8_t *pixels);
+
+    gl::Error setSubImagePaddingWorkaround(GLenum target,
+                                           size_t level,
+                                           const gl::Box &area,
+                                           GLenum format,
+                                           GLenum type,
+                                           const gl::PixelUnpackState &unpack,
+                                           const uint8_t *pixels);
+
+    void syncTextureStateSwizzle(const FunctionsGL *functions,
+                                 GLenum name,
+                                 GLenum value,
+                                 GLenum *outValue);
+
+    void setLevelInfo(size_t level, size_t levelCount, const LevelInfoGL &levelInfo);
+
+    const FunctionsGL *mFunctions;
+    const WorkaroundsGL &mWorkarounds;
+    StateManagerGL *mStateManager;
+    BlitGL *mBlitter;
+
+    std::vector<LevelInfoGL> mLevelInfo;
+    gl::Texture::DirtyBits mLocalDirtyBits;
+
+    gl::SwizzleState mAppliedSwizzle;
+    gl::SamplerState mAppliedSampler;
+    GLuint mAppliedBaseLevel;
+    GLuint mAppliedMaxLevel;
+
+    GLuint mTextureID;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_TEXTUREGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
new file mode 100644
index 0000000..ae75a0f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
@@ -0,0 +1,131 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackGL.cpp: Implements the class methods for TransformFeedbackGL.
+
+#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+namespace rx
+{
+
+TransformFeedbackGL::TransformFeedbackGL(const gl::TransformFeedbackState &state,
+                                         const FunctionsGL *functions,
+                                         StateManagerGL *stateManager)
+    : TransformFeedbackImpl(state),
+      mFunctions(functions),
+      mStateManager(stateManager),
+      mTransformFeedbackID(0),
+      mIsActive(false),
+      mIsPaused(false)
+{
+    mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID);
+}
+
+TransformFeedbackGL::~TransformFeedbackGL()
+{
+    mStateManager->deleteTransformFeedback(mTransformFeedbackID);
+    mTransformFeedbackID = 0;
+}
+
+void TransformFeedbackGL::begin(GLenum primitiveMode)
+{
+    // Do not begin directly, StateManagerGL will handle beginning and resuming transform feedback.
+}
+
+void TransformFeedbackGL::end()
+{
+    syncActiveState(false, GL_NONE);
+}
+
+void TransformFeedbackGL::pause()
+{
+    syncPausedState(true);
+}
+
+void TransformFeedbackGL::resume()
+{
+    // Do not resume directly, StateManagerGL will handle beginning and resuming transform feedback.
+}
+
+void TransformFeedbackGL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+{
+}
+
+void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding)
+{
+    // Directly bind buffer (not through the StateManager methods) because the buffer bindings are
+    // tracked per transform feedback object
+    mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
+    if (binding.get() != nullptr)
+    {
+        const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get());
+        if (binding.getSize() != 0)
+        {
+            mFunctions->bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
+                                        bufferGL->getBufferID(), binding.getOffset(),
+                                        binding.getSize());
+        }
+        else
+        {
+            mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
+                                       bufferGL->getBufferID());
+        }
+    }
+    else
+    {
+        mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0);
+    }
+}
+
+GLuint TransformFeedbackGL::getTransformFeedbackID() const
+{
+    return mTransformFeedbackID;
+}
+
+void TransformFeedbackGL::syncActiveState(bool active, GLenum primitiveMode) const
+{
+    if (mIsActive != active)
+    {
+        mIsActive = active;
+        mIsPaused = false;
+
+        mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
+        if (mIsActive)
+        {
+            mFunctions->beginTransformFeedback(primitiveMode);
+        }
+        else
+        {
+            mFunctions->endTransformFeedback();
+        }
+    }
+}
+
+void TransformFeedbackGL::syncPausedState(bool paused) const
+{
+    if (mIsActive && mIsPaused != paused)
+    {
+        mIsPaused = paused;
+
+        mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
+        if (mIsPaused)
+        {
+            mFunctions->pauseTransformFeedback();
+        }
+        else
+        {
+            mFunctions->resumeTransformFeedback();
+        }
+    }
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
new file mode 100644
index 0000000..f84edc0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
@@ -0,0 +1,53 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackGL.h: Defines the class interface for TransformFeedbackGL.
+
+#ifndef LIBANGLE_RENDERER_GL_TRANSFORMFEEDBACKGL_H_
+#define LIBANGLE_RENDERER_GL_TRANSFORMFEEDBACKGL_H_
+
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class TransformFeedbackGL : public TransformFeedbackImpl
+{
+  public:
+    TransformFeedbackGL(const gl::TransformFeedbackState &state,
+                        const FunctionsGL *functions,
+                        StateManagerGL *stateManager);
+    ~TransformFeedbackGL() override;
+
+    void begin(GLenum primitiveMode) override;
+    void end() override;
+    void pause() override;
+    void resume() override;
+
+    void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
+    void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+
+    GLuint getTransformFeedbackID() const;
+
+    void syncActiveState(bool active, GLenum primitiveMode) const;
+    void syncPausedState(bool paused) const;
+
+  private:
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+
+    GLuint mTransformFeedbackID;
+
+    mutable bool mIsActive;
+    mutable bool mIsPaused;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_TRANSFORMFEEDBACKGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
new file mode 100644
index 0000000..b56b058
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
@@ -0,0 +1,567 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexArrayGL.cpp: Implements the class methods for VertexArrayGL.
+
+#include "libANGLE/renderer/gl/VertexArrayGL.h"
+
+#include "common/bitset_utils.h"
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+using namespace gl;
+
+namespace rx
+{
+namespace
+{
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+bool AttributeNeedsStreaming(const VertexAttribute &attrib, const VertexBinding &binding)
+{
+    return (attrib.enabled && binding.buffer.get() == nullptr);
+}
+}  // anonymous namespace
+
+VertexArrayGL::VertexArrayGL(const VertexArrayState &state,
+                             const FunctionsGL *functions,
+                             StateManagerGL *stateManager)
+    : VertexArrayImpl(state),
+      mFunctions(functions),
+      mStateManager(stateManager),
+      mVertexArrayID(0),
+      mAppliedElementArrayBuffer(),
+      mAppliedBindings(state.getMaxBindings()),
+      mStreamingElementArrayBufferSize(0),
+      mStreamingElementArrayBuffer(0),
+      mStreamingArrayBufferSize(0),
+      mStreamingArrayBuffer(0)
+{
+    ASSERT(mFunctions);
+    ASSERT(mStateManager);
+    mFunctions->genVertexArrays(1, &mVertexArrayID);
+
+    // Set the cached vertex attribute array and vertex attribute binding array size
+    GLuint maxVertexAttribs = static_cast<GLuint>(state.getMaxAttribs());
+    for (GLuint i = 0; i < maxVertexAttribs; i++)
+    {
+        mAppliedAttributes.emplace_back(i);
+    }
+}
+
+VertexArrayGL::~VertexArrayGL()
+{
+    mStateManager->deleteVertexArray(mVertexArrayID);
+    mVertexArrayID = 0;
+
+    mStateManager->deleteBuffer(mStreamingElementArrayBuffer);
+    mStreamingElementArrayBufferSize = 0;
+    mStreamingElementArrayBuffer     = 0;
+
+    mStateManager->deleteBuffer(mStreamingArrayBuffer);
+    mStreamingArrayBufferSize = 0;
+    mStreamingArrayBuffer     = 0;
+
+    mAppliedElementArrayBuffer.set(nullptr);
+    for (auto &binding : mAppliedBindings)
+    {
+        binding.buffer.set(nullptr);
+    }
+}
+
+gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
+                                             GLint first,
+                                             GLsizei count,
+                                             GLsizei instanceCount) const
+{
+    return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount, false,
+                         nullptr);
+}
+
+gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
+                                               GLsizei count,
+                                               GLenum type,
+                                               const void *indices,
+                                               GLsizei instanceCount,
+                                               bool primitiveRestartEnabled,
+                                               const void **outIndices) const
+{
+    return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount,
+                         primitiveRestartEnabled, outIndices);
+}
+
+gl::Error VertexArrayGL::syncElementArrayState() const
+{
+    gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
+    ASSERT(elementArrayBuffer);
+    if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
+    {
+        const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
+        mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
+        mAppliedElementArrayBuffer.set(elementArrayBuffer);
+    }
+
+    return gl::NoError();
+}
+
+gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
+                                       GLint first,
+                                       GLsizei count,
+                                       GLenum type,
+                                       const void *indices,
+                                       GLsizei instanceCount,
+                                       bool primitiveRestartEnabled,
+                                       const void **outIndices) const
+{
+    mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
+
+    // Check if any attributes need to be streamed, determines if the index range needs to be
+    // computed
+    bool attributesNeedStreaming = mAttributesNeedStreaming.any();
+
+    // Determine if an index buffer needs to be streamed and the range of vertices that need to be
+    // copied
+    IndexRange indexRange;
+    if (type != GL_NONE)
+    {
+        Error error = syncIndexData(count, type, indices, primitiveRestartEnabled,
+                                    attributesNeedStreaming, &indexRange, outIndices);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+    else
+    {
+        // Not an indexed call, set the range to [first, first + count - 1]
+        indexRange.start = first;
+        indexRange.end   = first + count - 1;
+    }
+
+    if (attributesNeedStreaming)
+    {
+        Error error = streamAttributes(activeAttributesMask, instanceCount, indexRange);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    return NoError();
+}
+
+gl::Error VertexArrayGL::syncIndexData(GLsizei count,
+                                       GLenum type,
+                                       const void *indices,
+                                       bool primitiveRestartEnabled,
+                                       bool attributesNeedStreaming,
+                                       IndexRange *outIndexRange,
+                                       const void **outIndices) const
+{
+    ASSERT(outIndices);
+
+    gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
+
+    // Need to check the range of indices if attributes need to be streamed
+    if (elementArrayBuffer != nullptr)
+    {
+        if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
+        {
+            const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
+            mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
+            mAppliedElementArrayBuffer.set(elementArrayBuffer);
+        }
+
+        // Only compute the index range if the attributes also need to be streamed
+        if (attributesNeedStreaming)
+        {
+            ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
+            Error error                        = mData.getElementArrayBuffer()->getIndexRange(
+                type, elementArrayBufferOffset, count, primitiveRestartEnabled, outIndexRange);
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+
+        // Indices serves as an offset into the index buffer in this case, use the same value for
+        // the draw call
+        *outIndices = indices;
+    }
+    else
+    {
+        // Need to stream the index buffer
+        // TODO: if GLES, nothing needs to be streamed
+
+        // Only compute the index range if the attributes also need to be streamed
+        if (attributesNeedStreaming)
+        {
+            *outIndexRange = ComputeIndexRange(type, indices, count, primitiveRestartEnabled);
+        }
+
+        // Allocate the streaming element array buffer
+        if (mStreamingElementArrayBuffer == 0)
+        {
+            mFunctions->genBuffers(1, &mStreamingElementArrayBuffer);
+            mStreamingElementArrayBufferSize = 0;
+        }
+
+        mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer);
+        mAppliedElementArrayBuffer.set(nullptr);
+
+        // Make sure the element array buffer is large enough
+        const Type &indexTypeInfo          = GetTypeInfo(type);
+        size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count;
+        if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
+        {
+            // Copy the indices in while resizing the buffer
+            mFunctions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize, indices,
+                                   GL_DYNAMIC_DRAW);
+            mStreamingElementArrayBufferSize = requiredStreamingBufferSize;
+        }
+        else
+        {
+            // Put the indices at the beginning of the buffer
+            mFunctions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, requiredStreamingBufferSize,
+                                      indices);
+        }
+
+        // Set the index offset for the draw call to zero since the supplied index pointer is to
+        // client data
+        *outIndices = nullptr;
+    }
+
+    return NoError();
+}
+
+void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
+                                                   GLsizei instanceCount,
+                                                   const gl::IndexRange &indexRange,
+                                                   size_t *outStreamingDataSize,
+                                                   size_t *outMaxAttributeDataSize) const
+{
+    *outStreamingDataSize    = 0;
+    *outMaxAttributeDataSize = 0;
+
+    ASSERT(mAttributesNeedStreaming.any());
+
+    const auto &attribs  = mData.getVertexAttributes();
+    const auto &bindings = mData.getVertexBindings();
+
+    gl::AttributesMask attribsToStream = (mAttributesNeedStreaming & activeAttributesMask);
+
+    for (auto idx : attribsToStream)
+    {
+        const auto &attrib  = attribs[idx];
+        const auto &binding = bindings[attrib.bindingIndex];
+        ASSERT(AttributeNeedsStreaming(attrib, binding));
+
+        // If streaming is going to be required, compute the size of the required buffer
+        // and how much slack space at the beginning of the buffer will be required by determining
+        // the attribute with the largest data size.
+        size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
+        *outStreamingDataSize += typeSize * ComputeVertexBindingElementCount(
+                                                binding, indexRange.vertexCount(), instanceCount);
+        *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
+    }
+}
+
+gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
+                                          GLsizei instanceCount,
+                                          const gl::IndexRange &indexRange) const
+{
+    // Sync the vertex attribute state and track what data needs to be streamed
+    size_t streamingDataSize    = 0;
+    size_t maxAttributeDataSize = 0;
+
+    computeStreamingAttributeSizes(activeAttributesMask, instanceCount, indexRange,
+                                   &streamingDataSize, &maxAttributeDataSize);
+
+    if (streamingDataSize == 0)
+    {
+        return gl::NoError();
+    }
+
+    if (mStreamingArrayBuffer == 0)
+    {
+        mFunctions->genBuffers(1, &mStreamingArrayBuffer);
+        mStreamingArrayBufferSize = 0;
+    }
+
+    // If first is greater than zero, a slack space needs to be left at the beginning of the buffer
+    // so that the same 'first' argument can be passed into the draw call.
+    const size_t bufferEmptySpace   = maxAttributeDataSize * indexRange.start;
+    const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace;
+
+    mStateManager->bindBuffer(GL_ARRAY_BUFFER, mStreamingArrayBuffer);
+    if (requiredBufferSize > mStreamingArrayBufferSize)
+    {
+        mFunctions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW);
+        mStreamingArrayBufferSize = requiredBufferSize;
+    }
+
+    // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
+    // somehow (such as by a screen change), retry writing the data a few times and return
+    // OUT_OF_MEMORY if that fails.
+    GLboolean unmapResult     = GL_FALSE;
+    size_t unmapRetryAttempts = 5;
+    while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0)
+    {
+        uint8_t *bufferPointer = MapBufferRangeWithFallback(mFunctions, GL_ARRAY_BUFFER, 0,
+                                                            requiredBufferSize, GL_MAP_WRITE_BIT);
+        size_t curBufferOffset = bufferEmptySpace;
+
+        const auto &attribs  = mData.getVertexAttributes();
+        const auto &bindings = mData.getVertexBindings();
+
+        gl::AttributesMask attribsToStream = (mAttributesNeedStreaming & activeAttributesMask);
+
+        for (auto idx : attribsToStream)
+        {
+            const auto &attrib  = attribs[idx];
+            const auto &binding = bindings[attrib.bindingIndex];
+            ASSERT(AttributeNeedsStreaming(attrib, binding));
+
+            const size_t streamedVertexCount =
+                ComputeVertexBindingElementCount(binding, indexRange.vertexCount(), instanceCount);
+
+            const size_t sourceStride = ComputeVertexAttributeStride(attrib, binding);
+            const size_t destStride   = ComputeVertexAttributeTypeSize(attrib);
+
+            // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
+            // a non-instanced draw call
+            const size_t firstIndex = binding.divisor == 0 ? indexRange.start : 0;
+
+            // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state.
+            // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt
+            const uint8_t *inputPointer = reinterpret_cast<const uint8_t *>(attrib.pointer);
+
+            // Pack the data when copying it, user could have supplied a very large stride that
+            // would cause the buffer to be much larger than needed.
+            if (destStride == sourceStride)
+            {
+                // Can copy in one go, the data is packed
+                memcpy(bufferPointer + curBufferOffset, inputPointer + (sourceStride * firstIndex),
+                       destStride * streamedVertexCount);
+            }
+            else
+            {
+                // Copy each vertex individually
+                for (size_t vertexIdx = 0; vertexIdx < streamedVertexCount; vertexIdx++)
+                {
+                    uint8_t *out      = bufferPointer + curBufferOffset + (destStride * vertexIdx);
+                    const uint8_t *in = inputPointer + sourceStride * (vertexIdx + firstIndex);
+                    memcpy(out, in, destStride);
+                }
+            }
+
+            // Compute where the 0-index vertex would be.
+            const size_t vertexStartOffset = curBufferOffset - (firstIndex * destStride);
+
+            if (attrib.pureInteger)
+            {
+                ASSERT(!attrib.normalized);
+                mFunctions->vertexAttribIPointer(static_cast<GLuint>(idx), attrib.size, attrib.type,
+                                                 static_cast<GLsizei>(destStride),
+                                                 reinterpret_cast<const void *>(vertexStartOffset));
+            }
+            else
+            {
+                mFunctions->vertexAttribPointer(static_cast<GLuint>(idx), attrib.size, attrib.type,
+                                                attrib.normalized, static_cast<GLsizei>(destStride),
+                                                reinterpret_cast<const void *>(vertexStartOffset));
+            }
+
+            curBufferOffset += destStride * streamedVertexCount;
+
+            // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
+            // need to be streamed later, there is no chance that the caching will skip it.
+            mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
+        }
+
+        unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
+    }
+
+    if (unmapResult != GL_TRUE)
+    {
+        return Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
+    }
+
+    return NoError();
+}
+
+GLuint VertexArrayGL::getVertexArrayID() const
+{
+    return mVertexArrayID;
+}
+
+GLuint VertexArrayGL::getAppliedElementArrayBufferID() const
+{
+    if (mAppliedElementArrayBuffer.get() == nullptr)
+    {
+        return mStreamingElementArrayBuffer;
+    }
+
+    return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID();
+}
+
+void VertexArrayGL::updateNeedsStreaming(size_t attribIndex)
+{
+    const auto &attrib  = mData.getVertexAttribute(attribIndex);
+    const auto &binding = mData.getBindingFromAttribIndex(attribIndex);
+    mAttributesNeedStreaming.set(attribIndex, AttributeNeedsStreaming(attrib, binding));
+}
+
+void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
+{
+    const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
+    if (mAppliedAttributes[attribIndex].enabled == attrib.enabled)
+    {
+        return;
+    }
+
+    updateNeedsStreaming(attribIndex);
+
+    mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
+    if (attrib.enabled)
+    {
+        mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex));
+    }
+    else
+    {
+        mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex));
+    }
+    mAppliedAttributes[attribIndex].enabled = attrib.enabled;
+}
+
+void VertexArrayGL::updateAttribPointer(size_t attribIndex)
+{
+    const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
+    ASSERT(attribIndex == attrib.bindingIndex);
+
+    GLuint bindingIndex          = attrib.bindingIndex;
+    const VertexBinding &binding = mData.getVertexBinding(bindingIndex);
+
+    if (mAppliedAttributes[attribIndex] == attrib && mAppliedBindings[bindingIndex] == binding)
+    {
+        return;
+    }
+
+    updateNeedsStreaming(attribIndex);
+
+    // If we need to stream, defer the attribPointer to the draw call.
+    if (mAttributesNeedStreaming[attribIndex])
+    {
+        return;
+    }
+
+    // Skip the attribute that is disabled and uses a client memory pointer.
+    const Buffer *arrayBuffer = binding.buffer.get();
+    if (arrayBuffer == nullptr)
+    {
+        ASSERT(!attrib.enabled);
+
+        // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
+        // use a client memory pointer later, there is no chance that the caching will skip it.
+        mAppliedAttributes[attribIndex].size = static_cast<GLuint>(-1);
+        return;
+    }
+
+    mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
+
+    // Since ANGLE always uses a non-zero VAO, we cannot use a client memory pointer on it:
+    // [OpenGL ES 3.0.2] Section 2.8 page 24:
+    // An INVALID_OPERATION error is generated when a non-zero vertex array object is bound,
+    // zero is bound to the ARRAY_BUFFER buffer object binding point, and the pointer argument
+    // is not NULL.
+    ASSERT(arrayBuffer != nullptr);
+    const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
+    mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
+    const void *inputPointer =
+        reinterpret_cast<const uint8_t *>(binding.offset + attrib.relativeOffset);
+
+    if (attrib.pureInteger)
+    {
+        mFunctions->vertexAttribIPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
+                                         binding.stride, inputPointer);
+    }
+    else
+    {
+        mFunctions->vertexAttribPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
+                                        attrib.normalized, binding.stride, inputPointer);
+    }
+    mAppliedAttributes[attribIndex].size                    = attrib.size;
+    mAppliedAttributes[attribIndex].type                    = attrib.type;
+    mAppliedAttributes[attribIndex].normalized              = attrib.normalized;
+    mAppliedAttributes[attribIndex].pureInteger             = attrib.pureInteger;
+    mAppliedAttributes[attribIndex].pointer                 = attrib.pointer;
+    mAppliedAttributes[attribIndex].relativeOffset          = attrib.relativeOffset;
+    mAppliedAttributes[attribIndex].vertexAttribArrayStride = attrib.vertexAttribArrayStride;
+
+    mAppliedBindings[bindingIndex].stride = binding.stride;
+    mAppliedBindings[bindingIndex].offset = binding.offset;
+    mAppliedBindings[bindingIndex].buffer = binding.buffer;
+}
+
+void VertexArrayGL::updateAttribDivisor(size_t attribIndex)
+{
+    ASSERT(attribIndex == mData.getBindingIndexFromAttribIndex(attribIndex));
+
+    const VertexBinding &binding = mData.getVertexBinding(attribIndex);
+    if (mAppliedBindings[attribIndex].divisor != binding.divisor)
+    {
+        mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
+        mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), binding.divisor);
+
+        mAppliedBindings[attribIndex].divisor = binding.divisor;
+    }
+}
+
+void VertexArrayGL::syncState(ContextImpl *contextImpl, const VertexArray::DirtyBits &dirtyBits)
+{
+    for (size_t dirtyBit : dirtyBits)
+    {
+        if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
+        {
+            // TODO(jmadill): Element array buffer bindings
+            continue;
+        }
+
+        size_t index = VertexArray::GetAttribIndex(dirtyBit);
+        if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED &&
+            dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
+        {
+            updateAttribEnabled(index);
+        }
+        else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
+                 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
+        {
+            updateAttribPointer(index);
+        }
+        else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_FORMAT &&
+                 dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_BUFFER)
+        {
+            // TODO(jiawei.shao@intel.com): Vertex Attrib Bindings
+            ASSERT(index == mData.getBindingIndexFromAttribIndex(index));
+        }
+        else if (dirtyBit >= VertexArray::DIRTY_BIT_BINDING_0_DIVISOR &&
+                 dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_DIVISOR)
+        {
+            updateAttribDivisor(index);
+        }
+        else
+            UNREACHABLE();
+    }
+}
+
+}  // rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.h
new file mode 100644
index 0000000..64c2efa
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.h
@@ -0,0 +1,103 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexArrayGL.h: Defines the class interface for VertexArrayGL.
+
+#ifndef LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_
+#define LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_
+
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class VertexArrayGL : public VertexArrayImpl
+{
+  public:
+    VertexArrayGL(const gl::VertexArrayState &data,
+                  const FunctionsGL *functions,
+                  StateManagerGL *stateManager);
+    ~VertexArrayGL() override;
+
+    gl::Error syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
+                                  GLint first,
+                                  GLsizei count,
+                                  GLsizei instanceCount) const;
+    gl::Error syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
+                                    GLsizei count,
+                                    GLenum type,
+                                    const void *indices,
+                                    GLsizei instanceCount,
+                                    bool primitiveRestartEnabled,
+                                    const void **outIndices) const;
+    gl::Error syncElementArrayState() const;
+
+    GLuint getVertexArrayID() const;
+    GLuint getAppliedElementArrayBufferID() const;
+
+    void syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits) override;
+
+  private:
+    gl::Error syncDrawState(const gl::AttributesMask &activeAttributesMask,
+                            GLint first,
+                            GLsizei count,
+                            GLenum type,
+                            const void *indices,
+                            GLsizei instanceCount,
+                            bool primitiveRestartEnabled,
+                            const void **outIndices) const;
+
+    // Apply index data, only sets outIndexRange if attributesNeedStreaming is true
+    gl::Error syncIndexData(GLsizei count,
+                            GLenum type,
+                            const void *indices,
+                            bool primitiveRestartEnabled,
+                            bool attributesNeedStreaming,
+                            gl::IndexRange *outIndexRange,
+                            const void **outIndices) const;
+
+    // Returns the amount of space needed to stream all attributes that need streaming
+    // and the data size of the largest attribute
+    void computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
+                                        GLsizei instanceCount,
+                                        const gl::IndexRange &indexRange,
+                                        size_t *outStreamingDataSize,
+                                        size_t *outMaxAttributeDataSize) const;
+
+    // Stream attributes that have client data
+    gl::Error streamAttributes(const gl::AttributesMask &activeAttributesMask,
+                               GLsizei instanceCount,
+                               const gl::IndexRange &indexRange) const;
+
+    void updateNeedsStreaming(size_t attribIndex);
+    void updateAttribEnabled(size_t attribIndex);
+    void updateAttribPointer(size_t attribIndex);
+    void updateAttribDivisor(size_t attribIndex);
+
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+
+    GLuint mVertexArrayID;
+
+    mutable BindingPointer<gl::Buffer> mAppliedElementArrayBuffer;
+
+    mutable std::vector<gl::VertexAttribute> mAppliedAttributes;
+    mutable std::vector<gl::VertexBinding> mAppliedBindings;
+
+    mutable size_t mStreamingElementArrayBufferSize;
+    mutable GLuint mStreamingElementArrayBuffer;
+
+    mutable size_t mStreamingArrayBufferSize;
+    mutable GLuint mStreamingArrayBuffer;
+
+    gl::AttributesMask mAttributesNeedStreaming;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h
new file mode 100644
index 0000000..85bcdb1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WorkaroundsGL.h: Workarounds for GL driver bugs and other issues.
+
+#ifndef LIBANGLE_RENDERER_GL_WORKAROUNDSGL_H_
+#define LIBANGLE_RENDERER_GL_WORKAROUNDSGL_H_
+
+namespace rx
+{
+
+struct WorkaroundsGL
+{
+    // When writing a float to a normalized integer framebuffer, desktop OpenGL is allowed to write
+    // one of the two closest normalized integer representations (although round to nearest is
+    // preferred) (see section 2.3.5.2 of the GL 4.5 core specification). OpenGL ES requires that
+    // round-to-nearest is used (see "Conversion from Floating-Point to Framebuffer Fixed-Point" in
+    // section 2.1.2 of the OpenGL ES 2.0.25 spec).  This issue only shows up on Intel and AMD
+    // drivers on framebuffer formats that have 1-bit alpha, work around this by using higher
+    // precision formats instead.
+    bool avoid1BitAlphaTextureFormats = false;
+
+    // On some older Intel drivers, GL_RGBA4 is not color renderable, glCheckFramebufferStatus
+    // returns GL_FRAMEBUFFER_UNSUPPORTED. Work around this by using a known color-renderable
+    // format.
+    bool rgba4IsNotSupportedForColorRendering = false;
+
+    // When clearing a framebuffer on Intel or AMD drivers, when GL_FRAMEBUFFER_SRGB is enabled, the
+    // driver clears to the linearized clear color despite the framebuffer not supporting SRGB
+    // blending.  It only seems to do this when the framebuffer has only linear attachments, mixed
+    // attachments appear to get the correct clear color.
+    bool doesSRGBClearsOnLinearFramebufferAttachments = false;
+
+    // On Mac some GLSL constructs involving do-while loops cause GPU hangs, such as the following:
+    //  int i = 1;
+    //  do {
+    //      i --;
+    //      continue;
+    //  } while (i > 0)
+    // Work around this by rewriting the do-while to use another GLSL construct (block + while)
+    bool doWhileGLSLCausesGPUHang = false;
+
+    // Calling glFinish doesn't cause all queries to report that the result is available on some
+    // (NVIDIA) drivers.  It was found that enabling GL_DEBUG_OUTPUT_SYNCHRONOUS before the finish
+    // causes it to fully finish.
+    bool finishDoesNotCauseQueriesToBeAvailable = false;
+
+    // Always call useProgram after a successful link to avoid a driver bug.
+    // This workaround is meant to reproduce the use_current_program_after_successful_link
+    // workaround in Chromium (http://crbug.com/110263). It has been shown that this workaround is
+    // not necessary for MacOSX 10.9 and higher (http://crrev.com/39eb535b).
+    bool alwaysCallUseProgramAfterLink = false;
+
+    // In the case of unpacking from a pixel unpack buffer, unpack overlapping rows row by row.
+    bool unpackOverlappingRowsSeparatelyUnpackBuffer = false;
+    // In the case of packing to a pixel pack buffer, pack overlapping rows row by row.
+    bool packOverlappingRowsSeparatelyPackBuffer = false;
+
+    // During initialization, assign the current vertex attributes to the spec-mandated defaults.
+    bool initializeCurrentVertexAttributes = false;
+
+    // abs(i) where i is an integer returns unexpected result on Intel Mac.
+    // Emulate abs(i) with i * sign(i).
+    bool emulateAbsIntFunction = false;
+
+    // On Intel Mac, calculation of loop conditions in for and while loop has bug.
+    // Add "&& true" to the end of the condition expression to work around the bug.
+    bool addAndTrueToLoopCondition = false;
+
+    // When uploading textures from an unpack buffer, some drivers count an extra row padding when
+    // checking if the pixel unpack buffer is big enough. Tracking bug: http://anglebug.com/1512
+    // For example considering the pixel buffer below where in memory, each row data (D) of the
+    // texture is followed by some unused data (the dots):
+    //     +-------+--+
+    //     |DDDDDDD|..|
+    //     |DDDDDDD|..|
+    //     |DDDDDDD|..|
+    //     |DDDDDDD|..|
+    //     +-------A--B
+    // The last pixel read will be A, but the driver will think it is B, causing it to generate an
+    // error when the pixel buffer is just big enough.
+    bool unpackLastRowSeparatelyForPaddingInclusion = false;
+
+    // Equivalent workaround when uploading data from a pixel pack buffer.
+    bool packLastRowSeparatelyForPaddingInclusion = false;
+
+    // On some Intel drivers, using isnan() on highp float will get wrong answer. To work around
+    // this bug, we use an expression to emulate function isnan().
+    // Tracking bug: http://crbug.com/650547
+    bool emulateIsnanFloat = false;
+
+    // On Mac with OpenGL version 4.1, unused std140 or shared uniform blocks will be
+    // treated as inactive which is not consistent with WebGL2.0 spec. Reference all members in a
+    // unused std140 or shared uniform block at the beginning of main to work around it.
+    // Also used on Linux AMD.
+    bool useUnusedBlocksWithStandardOrSharedLayout = false;
+
+    // This flag will keep invariant declaration for input in fragment shader for GLSL >=4.20
+    // on AMD.
+    bool dontRemoveInvariantForFragmentInput = false;
+
+    // This flag is used to fix spec difference between GLSL 4.1 or lower and ESSL3.
+    bool removeInvariantAndCentroidForESSL3 = false;
+
+    // On Intel Mac OSX 10.11 driver, using "-float" will get wrong answer. Use "0.0 - float" to
+    // replace "-float".
+    // Tracking bug: http://crbug.com/308366
+    bool rewriteFloatUnaryMinusOperator = false;
+
+    // On NVIDIA drivers, atan(y, x) may return a wrong answer.
+    // Tracking bug: http://crbug.com/672380
+    bool emulateAtan2Float = false;
+
+    // Some drivers seem to forget about UBO bindings when loading program binaries. Work around
+    // this by re-applying the bindings after the program binary is loaded.
+    // This only seems to affect AMD OpenGL drivers, and some Android devices.
+    // http://anglebug.com/1637
+    bool reapplyUBOBindingsAfterLoadingBinaryProgram = false;
+
+    // Some OpenGL drivers return 0 when we query MAX_VERTEX_ATTRIB_STRIDE in an OpenGL 4.4 or
+    // higher context.
+    // This only seems to affect AMD OpenGL drivers.
+    // Tracking bug: http://anglebug.com/1936
+    bool emulateMaxVertexAttribStride = false;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_WORKAROUNDSGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h
new file mode 100644
index 0000000..407837a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h
@@ -0,0 +1,72 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayCGL.h: CGL implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_
+#define LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+
+struct _CGLContextObject;
+typedef _CGLContextObject *CGLContextObj;
+
+namespace rx
+{
+
+class DisplayCGL : public DisplayGL
+{
+  public:
+    DisplayCGL(const egl::DisplayState &state);
+    ~DisplayCGL() override;
+
+    egl::Error initialize(egl::Display *display) override;
+    void terminate() override;
+
+    SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+                                     EGLNativeWindowType window,
+                                     const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+                                      const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                               EGLenum buftype,
+                                               EGLClientBuffer clientBuffer,
+                                               const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+                                     NativePixmapType nativePixmap,
+                                     const egl::AttributeMap &attribs) override;
+
+    egl::ConfigSet generateConfigs() override;
+
+    bool testDeviceLost() override;
+    egl::Error restoreLostDevice() override;
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+    egl::Error getDevice(DeviceImpl **device) override;
+
+    std::string getVendorString() const override;
+
+    egl::Error waitClient() const override;
+    egl::Error waitNative(EGLint engine,
+                          egl::Surface *drawSurface,
+                          egl::Surface *readSurface) const override;
+
+  private:
+    const FunctionsGL *getFunctionsGL() const override;
+    egl::Error makeCurrentSurfaceless(gl::Context *context) override;
+
+    void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+    void generateCaps(egl::Caps *outCaps) const override;
+
+    egl::Display *mEGLDisplay;
+    FunctionsGL *mFunctions;
+    CGLContextObj mContext;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
new file mode 100644
index 0000000..8c75101
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
@@ -0,0 +1,279 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayCGL.mm: CGL implementation of egl::Display
+
+#include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
+
+#import <Cocoa/Cocoa.h>
+#include <dlfcn.h>
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h"
+#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h"
+
+namespace
+{
+
+const char *kDefaultOpenGLDylibName =
+    "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
+const char *kFallbackOpenGLDylibName = "GL";
+
+}
+
+namespace rx
+{
+
+class FunctionsGLCGL : public FunctionsGL
+{
+  public:
+    FunctionsGLCGL(void *dylibHandle) : mDylibHandle(dylibHandle) {}
+
+    ~FunctionsGLCGL() override { dlclose(mDylibHandle); }
+
+  private:
+    void *loadProcAddress(const std::string &function) override
+    {
+        return dlsym(mDylibHandle, function.c_str());
+    }
+
+    void *mDylibHandle;
+};
+
+DisplayCGL::DisplayCGL(const egl::DisplayState &state)
+    : DisplayGL(state), mEGLDisplay(nullptr), mFunctions(nullptr), mContext(nullptr)
+{
+}
+
+DisplayCGL::~DisplayCGL()
+{
+}
+
+egl::Error DisplayCGL::initialize(egl::Display *display)
+{
+    mEGLDisplay = display;
+
+    CGLPixelFormatObj pixelFormat;
+    {
+        // TODO(cwallez) investigate which pixel format we want
+        CGLPixelFormatAttribute attribs[] = {
+            kCGLPFAOpenGLProfile, static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_3_2_Core),
+            static_cast<CGLPixelFormatAttribute>(0)};
+        GLint nVirtualScreens = 0;
+        CGLChoosePixelFormat(attribs, &pixelFormat, &nVirtualScreens);
+
+        if (pixelFormat == nullptr)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, "Could not create the context's pixel format.");
+        }
+    }
+
+    CGLCreateContext(pixelFormat, nullptr, &mContext);
+    if (mContext == nullptr)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not create the CGL context.");
+    }
+    CGLSetCurrentContext(mContext);
+
+    // There is no equivalent getProcAddress in CGL so we open the dylib directly
+    void *handle = dlopen(kDefaultOpenGLDylibName, RTLD_NOW);
+    if (!handle)
+    {
+        handle = dlopen(kFallbackOpenGLDylibName, RTLD_NOW);
+    }
+    if (!handle)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not open the OpenGL Framework.");
+    }
+
+    mFunctions = new FunctionsGLCGL(handle);
+    mFunctions->initialize();
+
+    return DisplayGL::initialize(display);
+}
+
+void DisplayCGL::terminate()
+{
+    DisplayGL::terminate();
+
+    if (mContext != nullptr)
+    {
+        CGLSetCurrentContext(nullptr);
+        CGLReleaseContext(mContext);
+        mContext = nullptr;
+    }
+
+    SafeDelete(mFunctions);
+}
+
+SurfaceImpl *DisplayCGL::createWindowSurface(const egl::SurfaceState &state,
+                                             EGLNativeWindowType window,
+                                             const egl::AttributeMap &attribs)
+{
+    return new WindowSurfaceCGL(state, this->getRenderer(), window, mFunctions, mContext);
+}
+
+SurfaceImpl *DisplayCGL::createPbufferSurface(const egl::SurfaceState &state,
+                                              const egl::AttributeMap &attribs)
+{
+    EGLint width  = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
+    EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
+    return new PbufferSurfaceCGL(state, this->getRenderer(), width, height, mFunctions);
+}
+
+SurfaceImpl *DisplayCGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                                       EGLenum buftype,
+                                                       EGLClientBuffer clientBuffer,
+                                                       const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+SurfaceImpl *DisplayCGL::createPixmapSurface(const egl::SurfaceState &state,
+                                             NativePixmapType nativePixmap,
+                                             const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+egl::Error DisplayCGL::getDevice(DeviceImpl **device)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::ConfigSet DisplayCGL::generateConfigs()
+{
+    // TODO(cwallez): generate more config permutations
+    egl::ConfigSet configs;
+
+    const gl::Version &maxVersion = getMaxSupportedESVersion();
+    ASSERT(maxVersion >= gl::Version(2, 0));
+    bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
+    egl::Config config;
+
+    // Native stuff
+    config.nativeVisualID   = 0;
+    config.nativeVisualType = 0;
+    config.nativeRenderable = EGL_TRUE;
+
+    // Buffer sizes
+    config.redSize     = 8;
+    config.greenSize   = 8;
+    config.blueSize    = 8;
+    config.alphaSize   = 8;
+    config.depthSize   = 24;
+    config.stencilSize = 8;
+
+    config.colorBufferType = EGL_RGB_BUFFER;
+    config.luminanceSize   = 0;
+    config.alphaMaskSize   = 0;
+
+    config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize;
+
+    config.transparentType = EGL_NONE;
+
+    // Pbuffer
+    config.maxPBufferWidth  = 4096;
+    config.maxPBufferHeight = 4096;
+    config.maxPBufferPixels = 4096 * 4096;
+
+    // Caveat
+    config.configCaveat = EGL_NONE;
+
+    // Misc
+    config.sampleBuffers     = 0;
+    config.samples           = 0;
+    config.level             = 0;
+    config.bindToTextureRGB  = EGL_FALSE;
+    config.bindToTextureRGBA = EGL_FALSE;
+
+    config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
+
+    config.minSwapInterval = 1;
+    config.maxSwapInterval = 1;
+
+    config.renderTargetFormat = GL_RGBA8;
+    config.depthStencilFormat = GL_DEPTH24_STENCIL8;
+
+    config.conformant     = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+    config.renderableType = config.conformant;
+
+    config.matchNativePixmap = EGL_NONE;
+
+    config.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+
+    configs.add(config);
+    return configs;
+}
+
+bool DisplayCGL::testDeviceLost()
+{
+    // TODO(cwallez) investigate implementing this
+    return false;
+}
+
+egl::Error DisplayCGL::restoreLostDevice()
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayCGL::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    NSObject *layer = reinterpret_cast<NSObject *>(window);
+    return [layer isKindOfClass:[CALayer class]];
+}
+
+std::string DisplayCGL::getVendorString() const
+{
+    // TODO(cwallez) find a useful vendor string
+    return "";
+}
+
+const FunctionsGL *DisplayCGL::getFunctionsGL() const
+{
+    return mFunctions;
+}
+
+void DisplayCGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+    outExtensions->surfacelessContext = true;
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
+}
+
+void DisplayCGL::generateCaps(egl::Caps *outCaps) const
+{
+    outCaps->textureNPOT = true;
+}
+
+egl::Error DisplayCGL::waitClient() const
+{
+    // TODO(cwallez) UNIMPLEMENTED()
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayCGL::waitNative(EGLint engine,
+                                  egl::Surface *drawSurface,
+                                  egl::Surface *readSurface) const
+{
+    // TODO(cwallez) UNIMPLEMENTED()
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayCGL::makeCurrentSurfaceless(gl::Context *context)
+{
+    // We have nothing to do as mContext is always current, and that CGL is surfaceless by
+    // default.
+    return egl::NoError();
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h
new file mode 100644
index 0000000..f2c60dd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h
@@ -0,0 +1,65 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PBufferSurfaceCGL.h: an implementation of egl::Surface for PBuffers for the CLG backend,
+//                      currently implemented using renderbuffers
+
+#ifndef LIBANGLE_RENDERER_GL_CGL_PBUFFERSURFACECGL_H_
+#define LIBANGLE_RENDERER_GL_CGL_PBUFFERSURFACECGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class PbufferSurfaceCGL : public SurfaceGL
+{
+  public:
+    PbufferSurfaceCGL(const egl::SurfaceState &state,
+                      RendererGL *renderer,
+                      EGLint width,
+                      EGLint height,
+                      const FunctionsGL *functions);
+    ~PbufferSurfaceCGL() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    egl::Error makeCurrent() override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+  private:
+    unsigned mWidth;
+    unsigned mHeight;
+
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+    RendererGL *mRenderer;
+
+    GLuint mFramebuffer;
+    GLuint mColorRenderbuffer;
+    GLuint mDSRenderbuffer;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_CGL_PBUFFERSURFACECGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm
new file mode 100644
index 0000000..4c3d172
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PBufferSurfaceCGL.cpp: an implementation of egl::Surface for PBuffers for the CLG backend,
+//                      currently implemented using renderbuffers
+
+#include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+namespace rx
+{
+
+PbufferSurfaceCGL::PbufferSurfaceCGL(const egl::SurfaceState &state,
+                                     RendererGL *renderer,
+                                     EGLint width,
+                                     EGLint height,
+                                     const FunctionsGL *functions)
+    : SurfaceGL(state, renderer),
+      mWidth(width),
+      mHeight(height),
+      mFunctions(functions),
+      mStateManager(renderer->getStateManager()),
+      mRenderer(renderer),
+      mFramebuffer(0),
+      mColorRenderbuffer(0),
+      mDSRenderbuffer(0)
+{
+}
+
+PbufferSurfaceCGL::~PbufferSurfaceCGL()
+{
+    if (mFramebuffer != 0)
+    {
+        mFunctions->deleteFramebuffers(1, &mFramebuffer);
+        mFramebuffer = 0;
+    }
+
+    if (mColorRenderbuffer != 0)
+    {
+        mFunctions->deleteRenderbuffers(1, &mColorRenderbuffer);
+        mColorRenderbuffer = 0;
+    }
+    if (mDSRenderbuffer != 0)
+    {
+        mFunctions->deleteRenderbuffers(1, &mDSRenderbuffer);
+        mDSRenderbuffer = 0;
+    }
+}
+
+egl::Error PbufferSurfaceCGL::initialize(const DisplayImpl *displayImpl)
+{
+    mFunctions->genRenderbuffers(1, &mColorRenderbuffer);
+    mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer);
+    mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, mWidth, mHeight);
+
+    mFunctions->genRenderbuffers(1, &mDSRenderbuffer);
+    mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
+    mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mWidth, mHeight);
+
+    mFunctions->genFramebuffers(1, &mFramebuffer);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                                        mColorRenderbuffer);
+    mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+                                        GL_RENDERBUFFER, mDSRenderbuffer);
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::makeCurrent()
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::swap(const DisplayImpl *displayImpl)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::releaseTexImage(EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+void PbufferSurfaceCGL::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint PbufferSurfaceCGL::getWidth() const
+{
+    return mWidth;
+}
+
+EGLint PbufferSurfaceCGL::getHeight() const
+{
+    return mHeight;
+}
+
+EGLint PbufferSurfaceCGL::isPostSubBufferSupported() const
+{
+    UNIMPLEMENTED();
+    return EGL_FALSE;
+}
+
+EGLint PbufferSurfaceCGL::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+
+FramebufferImpl *PbufferSurfaceCGL::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+    // TODO(cwallez) assert it happens only once?
+    return new FramebufferGL(mFramebuffer, state, mFunctions, mRenderer->getWorkarounds(),
+                             mRenderer->getBlitter(), mStateManager);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
new file mode 100644
index 0000000..44a5bf7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
@@ -0,0 +1,100 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowSurfaceCGL.h: CGL implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_CGL_WINDOWSURFACECGL_H_
+#define LIBANGLE_RENDERER_GL_CGL_WINDOWSURFACECGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+struct _CGLContextObject;
+typedef _CGLContextObject *CGLContextObj;
+@class CALayer;
+struct __IOSurface;
+typedef __IOSurface *IOSurfaceRef;
+
+@class SwapLayer;
+
+namespace rx
+{
+
+class DisplayCGL;
+class FramebufferGL;
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+struct SharedSwapState
+{
+    struct SwapTexture
+    {
+        GLuint texture;
+        unsigned int width;
+        unsigned int height;
+        uint64_t swapId;
+    };
+
+    SwapTexture textures[3];
+
+    // This code path is not going to be used by Chrome so we take the liberty
+    // to use pthreads directly instead of using mutexes and condition variables
+    // via the Platform API.
+    pthread_mutex_t mutex;
+    // The following members should be accessed only when holding the mutex
+    // (or doing construction / destruction)
+    SwapTexture *beingRendered;
+    SwapTexture *lastRendered;
+    SwapTexture *beingPresented;
+};
+
+class WindowSurfaceCGL : public SurfaceGL
+{
+  public:
+    WindowSurfaceCGL(const egl::SurfaceState &state,
+                     RendererGL *renderer,
+                     EGLNativeWindowType layer,
+                     const FunctionsGL *functions,
+                     CGLContextObj context);
+    ~WindowSurfaceCGL() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    egl::Error makeCurrent() override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+  private:
+    SwapLayer *mSwapLayer;
+    SharedSwapState mSwapState;
+    uint64_t mCurrentSwapId;
+
+    CALayer *mLayer;
+    CGLContextObj mContext;
+    const FunctionsGL *mFunctions;
+    StateManagerGL *mStateManager;
+    RendererGL *mRenderer;
+    const WorkaroundsGL &mWorkarounds;
+
+    GLuint mFramebuffer;
+    GLuint mDSRenderbuffer;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_CGL_WINDOWSURFACECGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
new file mode 100644
index 0000000..ea87919
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
@@ -0,0 +1,332 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowSurfaceCGL.cpp: CGL implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h"
+
+#import <Cocoa/Cocoa.h>
+#include <OpenGL/OpenGL.h>
+#import <QuartzCore/QuartzCore.h>
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+@interface SwapLayer : CAOpenGLLayer
+{
+    CGLContextObj mDisplayContext;
+
+    bool initialized;
+    rx::SharedSwapState *mSwapState;
+    const rx::FunctionsGL *mFunctions;
+
+    GLuint mReadFramebuffer;
+}
+- (id)initWithSharedState:(rx::SharedSwapState *)swapState
+              withContext:(CGLContextObj)displayContext
+            withFunctions:(const rx::FunctionsGL *)functions;
+@end
+
+@implementation SwapLayer
+- (id)initWithSharedState:(rx::SharedSwapState *)swapState
+              withContext:(CGLContextObj)displayContext
+            withFunctions:(const rx::FunctionsGL *)functions
+    {
+        self = [super init];
+        if (self != nil)
+        {
+            self.asynchronous = YES;
+            mDisplayContext   = displayContext;
+
+            initialized = false;
+            mSwapState  = swapState;
+            mFunctions  = functions;
+
+            [self setFrame:CGRectMake(0, 0, mSwapState->textures[0].width,
+                                      mSwapState->textures[0].height)];
+        }
+        return self;
+    }
+
+    - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
+    {
+        CGLPixelFormatAttribute attribs[] = {
+            kCGLPFADisplayMask, static_cast<CGLPixelFormatAttribute>(mask), kCGLPFAOpenGLProfile,
+            static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_3_2_Core),
+            static_cast<CGLPixelFormatAttribute>(0)};
+
+        CGLPixelFormatObj pixelFormat = nullptr;
+        GLint numFormats = 0;
+        CGLChoosePixelFormat(attribs, &pixelFormat, &numFormats);
+
+        return pixelFormat;
+    }
+
+    - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
+    {
+        CGLContextObj context = nullptr;
+        CGLCreateContext(pixelFormat, mDisplayContext, &context);
+        return context;
+    }
+
+    - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
+                    pixelFormat:(CGLPixelFormatObj)pixelFormat
+                   forLayerTime:(CFTimeInterval)timeInterval
+                    displayTime:(const CVTimeStamp *)timeStamp
+    {
+        BOOL result = NO;
+
+        pthread_mutex_lock(&mSwapState->mutex);
+        {
+            if (mSwapState->lastRendered->swapId > mSwapState->beingPresented->swapId)
+            {
+                std::swap(mSwapState->lastRendered, mSwapState->beingPresented);
+                result = YES;
+            }
+        }
+        pthread_mutex_unlock(&mSwapState->mutex);
+
+        return result;
+    }
+
+    - (void)drawInCGLContext:(CGLContextObj)glContext
+                 pixelFormat:(CGLPixelFormatObj)pixelFormat
+                forLayerTime:(CFTimeInterval)timeInterval
+                 displayTime:(const CVTimeStamp *)timeStamp
+    {
+        CGLSetCurrentContext(glContext);
+        if (!initialized)
+        {
+            initialized = true;
+
+            mFunctions->genFramebuffers(1, &mReadFramebuffer);
+        }
+
+        const auto &texture = *mSwapState->beingPresented;
+        if ([self frame].size.width != texture.width || [self frame].size.height != texture.height)
+        {
+            [self setFrame:CGRectMake(0, 0, texture.width, texture.height)];
+
+            // Without this, the OSX compositor / window system doesn't see the resize.
+            [self setNeedsDisplay];
+        }
+
+        // TODO(cwallez) support 2.1 contexts too that don't have blitFramebuffer nor the
+        // GL_DRAW_FRAMEBUFFER_BINDING query
+        GLint drawFBO;
+        mFunctions->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFBO);
+
+        mFunctions->bindFramebuffer(GL_FRAMEBUFFER, mReadFramebuffer);
+        mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                                         texture.texture, 0);
+
+        mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer);
+        mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
+        mFunctions->blitFramebuffer(0, 0, texture.width, texture.height, 0, 0, texture.width,
+                                    texture.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+        // Call the super method to flush the context
+        [super drawInCGLContext:glContext
+                    pixelFormat:pixelFormat
+                   forLayerTime:timeInterval
+                    displayTime:timeStamp];
+    }
+    @end
+
+    namespace rx
+    {
+
+    WindowSurfaceCGL::WindowSurfaceCGL(const egl::SurfaceState &state,
+                                       RendererGL *renderer,
+                                       EGLNativeWindowType layer,
+                                       const FunctionsGL *functions,
+                                       CGLContextObj context)
+        : SurfaceGL(state, renderer),
+          mSwapLayer(nil),
+          mCurrentSwapId(0),
+          mLayer(reinterpret_cast<CALayer *>(layer)),
+          mContext(context),
+          mFunctions(functions),
+          mStateManager(renderer->getStateManager()),
+          mRenderer(renderer),
+          mWorkarounds(renderer->getWorkarounds()),
+          mFramebuffer(0),
+          mDSRenderbuffer(0)
+    {
+        pthread_mutex_init(&mSwapState.mutex, nullptr);
+}
+
+WindowSurfaceCGL::~WindowSurfaceCGL()
+{
+    pthread_mutex_destroy(&mSwapState.mutex);
+    if (mFramebuffer != 0)
+    {
+        mFunctions->deleteFramebuffers(1, &mFramebuffer);
+        mFramebuffer = 0;
+    }
+
+    if (mDSRenderbuffer != 0)
+    {
+        mFunctions->deleteRenderbuffers(1, &mDSRenderbuffer);
+        mDSRenderbuffer = 0;
+    }
+
+    if (mSwapLayer != nil)
+    {
+        [mSwapLayer removeFromSuperlayer];
+        [mSwapLayer release];
+        mSwapLayer = nil;
+    }
+
+    for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i)
+    {
+        if (mSwapState.textures[i].texture != 0)
+        {
+            mFunctions->deleteTextures(1, &mSwapState.textures[i].texture);
+            mSwapState.textures[i].texture = 0;
+        }
+    }
+}
+
+egl::Error WindowSurfaceCGL::initialize(const DisplayImpl *displayImpl)
+{
+    unsigned width  = getWidth();
+    unsigned height = getHeight();
+
+    for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i)
+    {
+        mFunctions->genTextures(1, &mSwapState.textures[i].texture);
+        mStateManager->bindTexture(GL_TEXTURE_2D, mSwapState.textures[i].texture);
+        mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
+                               GL_UNSIGNED_BYTE, nullptr);
+        mSwapState.textures[i].width  = width;
+        mSwapState.textures[i].height = height;
+        mSwapState.textures[i].swapId = 0;
+    }
+    mSwapState.beingRendered  = &mSwapState.textures[0];
+    mSwapState.lastRendered   = &mSwapState.textures[1];
+    mSwapState.beingPresented = &mSwapState.textures[2];
+
+    mSwapLayer = [[SwapLayer alloc] initWithSharedState:&mSwapState
+                                            withContext:mContext
+                                          withFunctions:mFunctions];
+    [mLayer addSublayer:mSwapLayer];
+
+    mFunctions->genRenderbuffers(1, &mDSRenderbuffer);
+    mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
+    mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+
+    mFunctions->genFramebuffers(1, &mFramebuffer);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                                     mSwapState.beingRendered->texture, 0);
+    mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                                        mDSRenderbuffer);
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::makeCurrent()
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::swap(const DisplayImpl *displayImpl)
+{
+    mFunctions->flush();
+    mSwapState.beingRendered->swapId = ++mCurrentSwapId;
+
+    pthread_mutex_lock(&mSwapState.mutex);
+    {
+        std::swap(mSwapState.beingRendered, mSwapState.lastRendered);
+    }
+    pthread_mutex_unlock(&mSwapState.mutex);
+
+    unsigned width  = getWidth();
+    unsigned height = getHeight();
+    auto &texture   = *mSwapState.beingRendered;
+
+    if (texture.width != width || texture.height != height)
+    {
+        mStateManager->bindTexture(GL_TEXTURE_2D, texture.texture);
+        mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
+                               GL_UNSIGNED_BYTE, nullptr);
+
+        mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
+        mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+
+        texture.width  = width;
+        texture.height = height;
+    }
+
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                                     mSwapState.beingRendered->texture, 0);
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::releaseTexImage(EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+void WindowSurfaceCGL::setSwapInterval(EGLint interval)
+{
+    // TODO(cwallez) investigate implementing swap intervals other than 0
+}
+
+EGLint WindowSurfaceCGL::getWidth() const
+{
+    return CGRectGetWidth([mLayer frame]);
+}
+
+EGLint WindowSurfaceCGL::getHeight() const
+{
+    return CGRectGetHeight([mLayer frame]);
+}
+
+EGLint WindowSurfaceCGL::isPostSubBufferSupported() const
+{
+    UNIMPLEMENTED();
+    return EGL_FALSE;
+}
+
+EGLint WindowSurfaceCGL::getSwapBehavior() const
+{
+    return EGL_BUFFER_DESTROYED;
+}
+
+FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+    // TODO(cwallez) assert it happens only once?
+    return new FramebufferGL(mFramebuffer, state, mFunctions, mWorkarounds, mRenderer->getBlitter(),
+                             mStateManager);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
new file mode 100644
index 0000000..d7215d0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
@@ -0,0 +1,119 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayEGL.cpp: Common across EGL parts of platform specific egl::Display implementations
+
+#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+
+namespace rx
+{
+
+#define EGL_NO_CONFIG ((EGLConfig)0)
+
+DisplayEGL::DisplayEGL(const egl::DisplayState &state)
+    : DisplayGL(state),
+      mEGL(nullptr),
+      mConfig(EGL_NO_CONFIG),
+      mContext(EGL_NO_CONTEXT),
+      mFunctionsGL(nullptr)
+{
+}
+
+DisplayEGL::~DisplayEGL()
+{
+}
+
+std::string DisplayEGL::getVendorString() const
+{
+    const char *vendor = mEGL->queryString(EGL_VENDOR);
+    ASSERT(vendor);
+    return vendor;
+}
+
+egl::Error DisplayEGL::initializeContext(const egl::AttributeMap &eglAttributes)
+{
+    gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
+
+    EGLint requestedMajor =
+        eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
+    EGLint requestedMinor =
+        eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
+    bool initializeRequested = requestedMajor != EGL_DONT_CARE && requestedMinor != EGL_DONT_CARE;
+
+    static_assert(EGL_CONTEXT_MAJOR_VERSION == EGL_CONTEXT_MAJOR_VERSION_KHR,
+                  "Major Version define should match");
+    static_assert(EGL_CONTEXT_MINOR_VERSION == EGL_CONTEXT_MINOR_VERSION_KHR,
+                  "Minor Version define should match");
+
+    std::vector<std::vector<EGLint>> contextAttribLists;
+    if (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context"))
+    {
+        if (initializeRequested)
+        {
+            contextAttribLists.push_back({EGL_CONTEXT_MAJOR_VERSION, requestedMajor,
+                                          EGL_CONTEXT_MINOR_VERSION, requestedMinor, EGL_NONE});
+        }
+        else
+        {
+            // clang-format off
+            const gl::Version esVersionsFrom2_0[] = {
+                gl::Version(3, 2),
+                gl::Version(3, 1),
+                gl::Version(3, 0),
+                gl::Version(2, 0),
+            };
+            // clang-format on
+
+            for (const auto &version : esVersionsFrom2_0)
+            {
+                contextAttribLists.push_back(
+                    {EGL_CONTEXT_MAJOR_VERSION, static_cast<EGLint>(version.major),
+                     EGL_CONTEXT_MINOR_VERSION, static_cast<EGLint>(version.minor), EGL_NONE});
+            }
+        }
+    }
+    else
+    {
+        if (initializeRequested && (requestedMajor != 2 || requestedMinor != 0))
+        {
+            return egl::Error(EGL_BAD_ATTRIBUTE, "Unsupported requested context version");
+        }
+        contextAttribLists.push_back({EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE});
+    }
+
+    for (auto &attribList : contextAttribLists)
+    {
+        mContext = mEGL->createContext(mConfig, EGL_NO_CONTEXT, attribList.data());
+        if (mContext != EGL_NO_CONTEXT)
+        {
+            return egl::Error(EGL_SUCCESS);
+        }
+    }
+
+    return egl::Error(mEGL->getError(), "eglCreateContext failed");
+}
+
+void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+    outExtensions->createContextRobustness =
+        mEGL->hasExtension("EGL_EXT_create_context_robustness");
+
+    outExtensions->postSubBuffer = false;  // Since SurfaceEGL::postSubBuffer is not implemented
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
+}
+
+void DisplayEGL::generateCaps(egl::Caps *outCaps) const
+{
+    outCaps->textureNPOT = true;  // Since we request GLES >= 2
+}
+
+const FunctionsGL *DisplayEGL::getFunctionsGL() const
+{
+    return mFunctionsGL;
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h
new file mode 100644
index 0000000..54f8a5a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayEGL.h: Common across EGL parts of platform specific egl::Display implementations
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+
+namespace rx
+{
+
+class DisplayEGL : public DisplayGL
+{
+  public:
+    DisplayEGL(const egl::DisplayState &state);
+    ~DisplayEGL() override;
+
+    std::string getVendorString() const override;
+
+  protected:
+    egl::Error initializeContext(const egl::AttributeMap &eglAttributes);
+
+    FunctionsEGL *mEGL;
+    EGLConfig mConfig;
+    EGLContext mContext;
+    FunctionsGL *mFunctionsGL;
+
+  private:
+    void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+    void generateCaps(egl::Caps *outCaps) const override;
+
+    const FunctionsGL *getFunctionsGL() const override;
+};
+
+}  // namespace rx
+
+#endif /* LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_ */
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp
new file mode 100644
index 0000000..7be9e71
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp
@@ -0,0 +1,340 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// FunctionsEGL.cpp: Implements the FunctionsEGL class.
+
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+
+#include <algorithm>
+
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/egl/functionsegl_typedefs.h"
+#include "common/string_utils.h"
+
+namespace
+{
+
+template <typename T>
+bool SetPtr(T *dst, void *src)
+{
+    if (src)
+    {
+        *dst = reinterpret_cast<T>(src);
+        return true;
+    }
+    return false;
+}
+}  // namespace
+
+namespace rx
+{
+
+struct FunctionsEGL::EGLDispatchTable
+{
+    EGLDispatchTable()
+        : bindAPIPtr(nullptr),
+          chooseConfigPtr(nullptr),
+          createContextPtr(nullptr),
+          createPbufferSurfacePtr(nullptr),
+          createWindowSurfacePtr(nullptr),
+          destroyContextPtr(nullptr),
+          destroySurfacePtr(nullptr),
+          getConfigAttribPtr(nullptr),
+          getDisplayPtr(nullptr),
+          getErrorPtr(nullptr),
+          initializePtr(nullptr),
+          makeCurrentPtr(nullptr),
+          queryStringPtr(nullptr),
+          querySurfacePtr(nullptr),
+          swapBuffersPtr(nullptr),
+          terminatePtr(nullptr),
+
+          bindTexImagePtr(nullptr),
+          releaseTexImagePtr(nullptr),
+          swapIntervalPtr(nullptr),
+
+          createImageKHRPtr(nullptr),
+          destroyImageKHRPtr(nullptr),
+
+          clientWaitSyncKHRPtr(nullptr),
+          createSyncKHRPtr(nullptr),
+          destroySyncKHRPtr(nullptr),
+          getSyncAttribKHRPtr(nullptr)
+    {
+    }
+
+    // 1.0
+    PFNEGLBINDAPIPROC bindAPIPtr;
+    PFNEGLCHOOSECONFIGPROC chooseConfigPtr;
+    PFNEGLCREATECONTEXTPROC createContextPtr;
+    PFNEGLCREATEPBUFFERSURFACEPROC createPbufferSurfacePtr;
+    PFNEGLCREATEWINDOWSURFACEPROC createWindowSurfacePtr;
+    PFNEGLDESTROYCONTEXTPROC destroyContextPtr;
+    PFNEGLDESTROYSURFACEPROC destroySurfacePtr;
+    PFNEGLGETCONFIGATTRIBPROC getConfigAttribPtr;
+    PFNEGLGETDISPLAYPROC getDisplayPtr;
+    PFNEGLGETERRORPROC getErrorPtr;
+    PFNEGLINITIALIZEPROC initializePtr;
+    PFNEGLMAKECURRENTPROC makeCurrentPtr;
+    PFNEGLQUERYSTRINGPROC queryStringPtr;
+    PFNEGLQUERYSURFACEPROC querySurfacePtr;
+    PFNEGLSWAPBUFFERSPROC swapBuffersPtr;
+    PFNEGLTERMINATEPROC terminatePtr;
+
+    // 1.1
+    PFNEGLBINDTEXIMAGEPROC bindTexImagePtr;
+    PFNEGLRELEASETEXIMAGEPROC releaseTexImagePtr;
+    PFNEGLSWAPINTERVALPROC swapIntervalPtr;
+
+    // EGL_KHR_image
+    PFNEGLCREATEIMAGEKHRPROC createImageKHRPtr;
+    PFNEGLDESTROYIMAGEKHRPROC destroyImageKHRPtr;
+
+    // EGL_KHR_fence_sync
+    PFNEGLCLIENTWAITSYNCKHRPROC clientWaitSyncKHRPtr;
+    PFNEGLCREATESYNCKHRPROC createSyncKHRPtr;
+    PFNEGLDESTROYSYNCKHRPROC destroySyncKHRPtr;
+    PFNEGLGETSYNCATTRIBKHRPROC getSyncAttribKHRPtr;
+};
+
+FunctionsEGL::FunctionsEGL()
+    : majorVersion(0), minorVersion(0), mFnPtrs(new EGLDispatchTable()), mEGLDisplay(EGL_NO_DISPLAY)
+{
+}
+
+FunctionsEGL::~FunctionsEGL()
+{
+    SafeDelete(mFnPtrs);
+}
+
+egl::Error FunctionsEGL::initialize(EGLNativeDisplayType nativeDisplay)
+{
+#define ANGLE_GET_PROC_OR_ERROR(MEMBER, NAME)                                            \
+    if (!SetPtr(MEMBER, getProcAddress(#NAME)))                                          \
+    {                                                                                    \
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not load EGL entry point " #NAME); \
+    }
+
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->bindAPIPtr, eglBindAPI);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->chooseConfigPtr, eglChooseConfig);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createContextPtr, eglCreateContext);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createPbufferSurfacePtr, eglCreatePbufferSurface);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createWindowSurfacePtr, eglCreateWindowSurface);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyContextPtr, eglDestroyContext);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySurfacePtr, eglDestroySurface);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getConfigAttribPtr, eglGetConfigAttrib);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getDisplayPtr, eglGetDisplay);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getErrorPtr, eglGetError);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->initializePtr, eglInitialize);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->makeCurrentPtr, eglMakeCurrent);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->queryStringPtr, eglQueryString);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->querySurfacePtr, eglQuerySurface);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->swapBuffersPtr, eglSwapBuffers);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->terminatePtr, eglTerminate);
+
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->bindTexImagePtr, eglBindTexImage);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->releaseTexImagePtr, eglReleaseTexImage);
+    ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalPtr, eglSwapInterval);
+
+    mEGLDisplay = mFnPtrs->getDisplayPtr(nativeDisplay);
+    if (mEGLDisplay == EGL_NO_DISPLAY)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to get system egl display");
+    }
+    if (mFnPtrs->initializePtr(mEGLDisplay, &majorVersion, &minorVersion) != EGL_TRUE)
+    {
+        return egl::Error(mFnPtrs->getErrorPtr(), "Failed to initialize system egl");
+    }
+    if (majorVersion < 1 || (majorVersion == 1 && minorVersion < 4))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Unsupported EGL version (require at least 1.4).");
+    }
+    if (mFnPtrs->bindAPIPtr(EGL_OPENGL_ES_API) != EGL_TRUE)
+    {
+        return egl::Error(mFnPtrs->getErrorPtr(), "Failed to bind API in system egl");
+    }
+
+    const char *extensions = queryString(EGL_EXTENSIONS);
+    if (!extensions)
+    {
+        return egl::Error(mFnPtrs->getErrorPtr(), "Faild to query extensions in system egl");
+    }
+    angle::SplitStringAlongWhitespace(extensions, &mExtensions);
+
+    if (hasExtension("EGL_KHR_image_base"))
+    {
+        ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createImageKHRPtr, eglCreateImageKHR);
+        ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyImageKHRPtr, eglDestroyImageKHR);
+    }
+    if (hasExtension("EGL_KHR_fence_sync"))
+    {
+        ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->clientWaitSyncKHRPtr, eglClientWaitSyncKHR);
+        ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createSyncKHRPtr, eglCreateSyncKHR);
+        ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySyncKHRPtr, eglDestroySyncKHR);
+        ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getSyncAttribKHRPtr, eglGetSyncAttribKHR);
+    }
+
+#undef ANGLE_GET_PROC_OR_ERROR
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error FunctionsEGL::terminate()
+{
+    if (mFnPtrs->terminatePtr == nullptr || mFnPtrs->terminatePtr(mEGLDisplay) == EGL_TRUE)
+    {
+        mEGLDisplay = nullptr;
+        return egl::Error(EGL_SUCCESS);
+    }
+    return egl::Error(mFnPtrs->getErrorPtr());
+}
+
+class FunctionsGLEGL : public FunctionsGL
+{
+  public:
+    FunctionsGLEGL(const FunctionsEGL &egl) : mEGL(egl) {}
+
+    ~FunctionsGLEGL() override {}
+
+  private:
+    void *loadProcAddress(const std::string &function) override
+    {
+        return mEGL.getProcAddress(function.c_str());
+    }
+
+    const FunctionsEGL &mEGL;
+};
+
+FunctionsGL *FunctionsEGL::makeFunctionsGL(void) const
+{
+    return new FunctionsGLEGL(*this);
+}
+
+bool FunctionsEGL::hasExtension(const char *extension) const
+{
+    return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
+}
+
+EGLDisplay FunctionsEGL::getDisplay() const
+{
+    return mEGLDisplay;
+}
+
+EGLint FunctionsEGL::getError() const
+{
+    return mFnPtrs->getErrorPtr();
+}
+
+EGLBoolean FunctionsEGL::chooseConfig(EGLint const *attribList,
+                                      EGLConfig *configs,
+                                      EGLint configSize,
+                                      EGLint *numConfig) const
+{
+    return mFnPtrs->chooseConfigPtr(mEGLDisplay, attribList, configs, configSize, numConfig);
+}
+
+EGLBoolean FunctionsEGL::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const
+{
+    return mFnPtrs->getConfigAttribPtr(mEGLDisplay, config, attribute, value);
+}
+
+EGLContext FunctionsEGL::createContext(EGLConfig config,
+                                       EGLContext share_context,
+                                       EGLint const *attrib_list) const
+{
+    return mFnPtrs->createContextPtr(mEGLDisplay, config, share_context, attrib_list);
+}
+
+EGLSurface FunctionsEGL::createPbufferSurface(EGLConfig config, const EGLint *attrib_list) const
+{
+    return mFnPtrs->createPbufferSurfacePtr(mEGLDisplay, config, attrib_list);
+}
+
+EGLSurface FunctionsEGL::createWindowSurface(EGLConfig config,
+                                             EGLNativeWindowType win,
+                                             const EGLint *attrib_list) const
+{
+    return mFnPtrs->createWindowSurfacePtr(mEGLDisplay, config, win, attrib_list);
+}
+
+EGLBoolean FunctionsEGL::destroyContext(EGLContext context) const
+{
+    return mFnPtrs->destroyContextPtr(mEGLDisplay, context);
+}
+
+EGLBoolean FunctionsEGL::destroySurface(EGLSurface surface) const
+{
+    return mFnPtrs->destroySurfacePtr(mEGLDisplay, surface);
+}
+
+EGLBoolean FunctionsEGL::makeCurrent(EGLSurface surface, EGLContext context) const
+{
+    return mFnPtrs->makeCurrentPtr(mEGLDisplay, surface, surface, context);
+}
+
+char const *FunctionsEGL::queryString(EGLint name) const
+{
+    return mFnPtrs->queryStringPtr(mEGLDisplay, name);
+}
+
+EGLBoolean FunctionsEGL::querySurface(EGLSurface surface, EGLint attribute, EGLint *value) const
+{
+    return mFnPtrs->querySurfacePtr(mEGLDisplay, surface, attribute, value);
+}
+
+EGLBoolean FunctionsEGL::swapBuffers(EGLSurface surface) const
+{
+    return mFnPtrs->swapBuffersPtr(mEGLDisplay, surface);
+}
+
+EGLBoolean FunctionsEGL::bindTexImage(EGLSurface surface, EGLint buffer) const
+{
+    return mFnPtrs->bindTexImagePtr(mEGLDisplay, surface, buffer);
+}
+
+EGLBoolean FunctionsEGL::releaseTexImage(EGLSurface surface, EGLint buffer) const
+{
+    return mFnPtrs->releaseTexImagePtr(mEGLDisplay, surface, buffer);
+}
+
+EGLBoolean FunctionsEGL::swapInterval(EGLint interval) const
+{
+    return mFnPtrs->swapIntervalPtr(mEGLDisplay, interval);
+}
+
+EGLImageKHR FunctionsEGL::createImageKHR(EGLContext context,
+                                         EGLenum target,
+                                         EGLClientBuffer buffer,
+                                         const EGLint *attrib_list) const
+{
+    return mFnPtrs->createImageKHRPtr(mEGLDisplay, context, target, buffer, attrib_list);
+}
+
+EGLBoolean FunctionsEGL::destroyImageKHR(EGLImageKHR image) const
+{
+    return mFnPtrs->destroyImageKHRPtr(mEGLDisplay, image);
+}
+
+EGLSyncKHR FunctionsEGL::createSyncKHR(EGLenum type, const EGLint *attrib_list)
+{
+    return mFnPtrs->createSyncKHRPtr(mEGLDisplay, type, attrib_list);
+}
+
+EGLBoolean FunctionsEGL::destroySyncKHR(EGLSyncKHR sync)
+{
+    return mFnPtrs->destroySyncKHRPtr(mEGLDisplay, sync);
+}
+
+EGLint FunctionsEGL::clientWaitSyncKHR(EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
+{
+    return mFnPtrs->clientWaitSyncKHRPtr(mEGLDisplay, sync, flags, timeout);
+}
+
+EGLBoolean FunctionsEGL::getSyncAttribKHR(EGLSyncKHR sync, EGLint attribute, EGLint *value)
+{
+    return mFnPtrs->getSyncAttribKHRPtr(mEGLDisplay, sync, attribute, value);
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h
new file mode 100644
index 0000000..43d5622
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// FunctionsEGL.h: Defines the FunctionsEGL class to load functions and data from EGL
+
+#ifndef LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_
+#define LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <string>
+#include <vector>
+
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+
+class FunctionsEGL
+{
+  public:
+    FunctionsEGL();
+    virtual ~FunctionsEGL();
+
+    int majorVersion;
+    int minorVersion;
+
+    egl::Error initialize(EGLNativeDisplayType nativeDisplay);
+    egl::Error terminate();
+
+    virtual void *getProcAddress(const char *name) const = 0;
+
+    FunctionsGL *makeFunctionsGL() const;
+    bool hasExtension(const char *extension) const;
+    EGLDisplay getDisplay() const;
+    EGLint getError() const;
+
+    EGLBoolean chooseConfig(EGLint const *attrib_list,
+                            EGLConfig *configs,
+                            EGLint config_size,
+                            EGLint *num_config) const;
+    EGLBoolean getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const;
+    EGLContext createContext(EGLConfig config,
+                             EGLContext share_context,
+                             EGLint const *attrib_list) const;
+    EGLSurface createPbufferSurface(EGLConfig config, const EGLint *attrib_list) const;
+    EGLSurface createWindowSurface(EGLConfig config,
+                                   EGLNativeWindowType win,
+                                   const EGLint *attrib_list) const;
+    EGLBoolean destroyContext(EGLContext context) const;
+    EGLBoolean destroySurface(EGLSurface surface) const;
+    EGLBoolean makeCurrent(EGLSurface surface, EGLContext context) const;
+    const char *queryString(EGLint name) const;
+    EGLBoolean querySurface(EGLSurface surface, EGLint attribute, EGLint *value) const;
+    EGLBoolean swapBuffers(EGLSurface surface) const;
+
+    EGLBoolean bindTexImage(EGLSurface surface, EGLint buffer) const;
+    EGLBoolean releaseTexImage(EGLSurface surface, EGLint buffer) const;
+    EGLBoolean swapInterval(EGLint interval) const;
+
+    EGLImageKHR createImageKHR(EGLContext context,
+                               EGLenum target,
+                               EGLClientBuffer buffer,
+                               const EGLint *attrib_list) const;
+    EGLBoolean destroyImageKHR(EGLImageKHR image) const;
+
+    EGLSyncKHR createSyncKHR(EGLenum type, const EGLint *attrib_list);
+    EGLBoolean destroySyncKHR(EGLSyncKHR sync);
+    EGLint clientWaitSyncKHR(EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+    EGLBoolean getSyncAttribKHR(EGLSyncKHR sync, EGLint attribute, EGLint *value);
+
+  private:
+    // So as to isolate from angle we do not include angleutils.h and cannot
+    // use angle::NonCopyable so we replicated it here instead.
+    FunctionsEGL(const FunctionsEGL &) = delete;
+    void operator=(const FunctionsEGL &) = delete;
+
+    struct EGLDispatchTable;
+    EGLDispatchTable *mFnPtrs;
+    EGLDisplay mEGLDisplay;
+    std::vector<std::string> mExtensions;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp
new file mode 100644
index 0000000..e6ef45d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// FunctionsEGLDL.cpp: Implements the FunctionsEGLDL class.
+
+#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
+
+#include <dlfcn.h>
+
+namespace rx
+{
+
+DynamicLib::DynamicLib() : handle(nullptr)
+{
+}
+
+DynamicLib::~DynamicLib()
+{
+    if (handle)
+    {
+        dlclose(handle);
+        handle = nullptr;
+    }
+}
+
+// Due to a bug in Mesa (or maybe libdl) it's not possible to close and re-open libEGL.so
+// an arbitrary number of times.  End2end tests would die after a couple hundred tests.
+// So we use a static object with a destructor to close the library when the program exits.
+// TODO(fjhenigman) File a bug and put a link here.
+DynamicLib FunctionsEGLDL::sNativeLib;
+
+FunctionsEGLDL::FunctionsEGLDL() : mGetProcAddressPtr(nullptr)
+{
+}
+
+FunctionsEGLDL::~FunctionsEGLDL()
+{
+}
+
+egl::Error FunctionsEGLDL::initialize(EGLNativeDisplayType nativeDisplay, const char *libName)
+{
+    if (!sNativeLib.handle)
+    {
+        sNativeLib.handle = dlopen(libName, RTLD_NOW);
+        if (!sNativeLib.handle)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, "Could not dlopen native EGL: %s", dlerror());
+        }
+    }
+
+    mGetProcAddressPtr =
+        reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(dlsym(sNativeLib.handle, "eglGetProcAddress"));
+    if (!mGetProcAddressPtr)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not find eglGetProcAddress");
+    }
+
+    return FunctionsEGL::initialize(nativeDisplay);
+}
+
+void *FunctionsEGLDL::getProcAddress(const char *name) const
+{
+    void *f = reinterpret_cast<void *>(mGetProcAddressPtr(name));
+    if (f)
+    {
+        return f;
+    }
+    return dlsym(sNativeLib.handle, name);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h
new file mode 100644
index 0000000..d69df77
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// FunctionsEGL.h: Implements FunctionsEGL with dlopen/dlsym/dlclose
+
+#ifndef LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_
+#define LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_
+
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+#include "libANGLE/renderer/gl/egl/functionsegl_typedefs.h"
+
+namespace rx
+{
+
+class DynamicLib final
+{
+  public:
+    void *handle;
+
+    DynamicLib();
+    ~DynamicLib();
+};
+
+class FunctionsEGLDL : public FunctionsEGL
+{
+  public:
+    FunctionsEGLDL();
+    ~FunctionsEGLDL() override;
+
+    egl::Error initialize(EGLNativeDisplayType nativeDisplay, const char *libName);
+    void *getProcAddress(const char *name) const override;
+
+  private:
+    PFNEGLGETPROCADDRESSPROC mGetProcAddressPtr;
+    static DynamicLib sNativeLib;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp
new file mode 100644
index 0000000..4dd6370
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// PbufferSurfaceEGL.h: EGL implementation of egl::Surface for pbuffers
+
+#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
+
+namespace rx
+{
+
+PbufferSurfaceEGL::PbufferSurfaceEGL(const egl::SurfaceState &state,
+                                     const FunctionsEGL *egl,
+                                     EGLConfig config,
+                                     const std::vector<EGLint> &attribList,
+                                     EGLContext context,
+                                     RendererGL *renderer)
+    : SurfaceEGL(state, egl, config, attribList, context, renderer)
+{
+}
+
+PbufferSurfaceEGL::~PbufferSurfaceEGL()
+{
+}
+
+egl::Error PbufferSurfaceEGL::initialize(const DisplayImpl *displayImpl)
+{
+    mSurface = mEGL->createPbufferSurface(mConfig, mAttribList.data());
+    if (mSurface == EGL_NO_SURFACE)
+    {
+        return egl::Error(mEGL->getError(), "eglCreatePbufferSurface failed");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h
new file mode 100644
index 0000000..fb4fe6b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// PbufferSurfaceEGL.h: EGL implementation of egl::Surface for pbuffers
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_
+
+#include <vector>
+#include <EGL/egl.h>
+
+#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
+
+namespace rx
+{
+
+class PbufferSurfaceEGL : public SurfaceEGL
+{
+  public:
+    PbufferSurfaceEGL(const egl::SurfaceState &state,
+                      const FunctionsEGL *egl,
+                      EGLConfig config,
+                      const std::vector<EGLint> &attribList,
+                      EGLContext context,
+                      RendererGL *renderer);
+    ~PbufferSurfaceEGL() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp
new file mode 100644
index 0000000..364def9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SurfaceEGL.cpp: EGL implementation of egl::Surface
+
+#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+SurfaceEGL::SurfaceEGL(const egl::SurfaceState &state,
+                       const FunctionsEGL *egl,
+                       EGLConfig config,
+                       const std::vector<EGLint> &attribList,
+                       EGLContext context,
+                       RendererGL *renderer)
+    : SurfaceGL(state, renderer),
+      mEGL(egl),
+      mConfig(config),
+      mAttribList(attribList),
+      mSurface(EGL_NO_SURFACE),
+      mContext(context)
+{
+}
+
+SurfaceEGL::~SurfaceEGL()
+{
+    if (mSurface != EGL_NO_SURFACE)
+    {
+        EGLBoolean success = mEGL->destroySurface(mSurface);
+        ASSERT(success == EGL_TRUE);
+    }
+}
+
+egl::Error SurfaceEGL::makeCurrent()
+{
+    EGLBoolean success = mEGL->makeCurrent(mSurface, mContext);
+    if (success == EGL_FALSE)
+    {
+        return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
+    }
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceEGL::swap(const DisplayImpl *displayImpl)
+{
+    EGLBoolean success = mEGL->swapBuffers(mSurface);
+    if (success == EGL_FALSE)
+    {
+        return egl::Error(mEGL->getError(), "eglSwapBuffers failed");
+    }
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceEGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_SURFACE);
+}
+
+egl::Error SurfaceEGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_SURFACE);
+}
+
+egl::Error SurfaceEGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    EGLBoolean success = mEGL->bindTexImage(mSurface, buffer);
+    if (success == EGL_FALSE)
+    {
+        return egl::Error(mEGL->getError(), "eglBindTexImage failed");
+    }
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceEGL::releaseTexImage(EGLint buffer)
+{
+    EGLBoolean success = mEGL->releaseTexImage(mSurface, buffer);
+    if (success == EGL_FALSE)
+    {
+        return egl::Error(mEGL->getError(), "eglReleaseTexImage failed");
+    }
+    return egl::Error(EGL_SUCCESS);
+}
+
+void SurfaceEGL::setSwapInterval(EGLint interval)
+{
+    EGLBoolean success = mEGL->swapInterval(interval);
+    if (success == EGL_FALSE)
+    {
+        ERR() << "eglSwapInterval error " << egl::Error(mEGL->getError());
+        ASSERT(false);
+    }
+}
+
+EGLint SurfaceEGL::getWidth() const
+{
+    EGLint value;
+    EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, &value);
+    ASSERT(success == EGL_TRUE);
+    return value;
+}
+
+EGLint SurfaceEGL::getHeight() const
+{
+    EGLint value;
+    EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, &value);
+    ASSERT(success == EGL_TRUE);
+    return value;
+}
+
+EGLint SurfaceEGL::isPostSubBufferSupported() const
+{
+    UNIMPLEMENTED();
+    return 0;
+}
+
+EGLint SurfaceEGL::getSwapBehavior() const
+{
+    EGLint value;
+    EGLBoolean success = mEGL->querySurface(mSurface, EGL_SWAP_BEHAVIOR, &value);
+    ASSERT(success == EGL_TRUE);
+    return value;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h
new file mode 100644
index 0000000..6033ace
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SurfaceEGL.h: common interface for EGL surfaces
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_
+
+#include <EGL/egl.h>
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+
+namespace rx
+{
+
+class SurfaceEGL : public SurfaceGL
+{
+  public:
+    SurfaceEGL(const egl::SurfaceState &state,
+               const FunctionsEGL *egl,
+               EGLConfig config,
+               const std::vector<EGLint> &attribList,
+               EGLContext context,
+               RendererGL *renderer);
+    ~SurfaceEGL() override;
+
+    egl::Error makeCurrent() override;
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+  protected:
+    const FunctionsEGL *mEGL;
+    EGLConfig mConfig;
+    std::vector<EGLint> mAttribList;
+    EGLSurface mSurface;
+
+  private:
+    EGLContext mContext;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp
new file mode 100644
index 0000000..c4d3853
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// WindowSurfaceEGL.h: EGL implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
+
+namespace rx
+{
+
+WindowSurfaceEGL::WindowSurfaceEGL(const egl::SurfaceState &state,
+                                   const FunctionsEGL *egl,
+                                   EGLConfig config,
+                                   EGLNativeWindowType window,
+                                   const std::vector<EGLint> &attribList,
+                                   EGLContext context,
+                                   RendererGL *renderer)
+    : SurfaceEGL(state, egl, config, attribList, context, renderer), mWindow(window)
+{
+}
+
+WindowSurfaceEGL::~WindowSurfaceEGL()
+{
+}
+
+egl::Error WindowSurfaceEGL::initialize(const DisplayImpl *displayImpl)
+{
+    mSurface = mEGL->createWindowSurface(mConfig, mWindow, mAttribList.data());
+    if (mSurface == EGL_NO_SURFACE)
+    {
+        return egl::Error(mEGL->getError(), "eglCreateWindowSurface failed");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h
new file mode 100644
index 0000000..51f8945
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// WindowSurfaceEGL.h: EGL implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_
+
+#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
+
+namespace rx
+{
+
+class WindowSurfaceEGL : public SurfaceEGL
+{
+  public:
+    WindowSurfaceEGL(const egl::SurfaceState &state,
+                     const FunctionsEGL *egl,
+                     EGLConfig config,
+                     EGLNativeWindowType window,
+                     const std::vector<EGLint> &attribList,
+                     EGLContext context,
+                     RendererGL *renderer);
+    ~WindowSurfaceEGL() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+
+  private:
+    EGLNativeWindowType mWindow;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
new file mode 100644
index 0000000..d013276
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
@@ -0,0 +1,397 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayAndroid.cpp: Android implementation of egl::Display
+
+#include <android/native_window.h>
+
+#include "common/debug.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
+#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
+#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
+
+namespace
+{
+const char *GetEGLPath()
+{
+#if defined(__LP64__)
+    return "/system/lib64/libEGL.so";
+#else
+    return "/system/lib/libEGL.so";
+#endif
+}
+}  // namespace
+
+namespace rx
+{
+
+DisplayAndroid::DisplayAndroid(const egl::DisplayState &state)
+    : DisplayEGL(state), mDummyPbuffer(EGL_NO_SURFACE)
+{
+}
+
+DisplayAndroid::~DisplayAndroid()
+{
+}
+
+egl::Error DisplayAndroid::initialize(egl::Display *display)
+{
+    FunctionsEGLDL *egl = new FunctionsEGLDL();
+    mEGL = egl;
+    ANGLE_TRY(egl->initialize(display->getNativeDisplayId(), GetEGLPath()));
+
+    gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
+    ASSERT(eglVersion >= gl::Version(1, 4));
+
+    static_assert(EGL_OPENGL_ES3_BIT == EGL_OPENGL_ES3_BIT_KHR, "Extension define must match core");
+    EGLint esBit = (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context"))
+                       ? EGL_OPENGL_ES3_BIT
+                       : EGL_OPENGL_ES2_BIT;
+
+    // clang-format off
+    mConfigAttribList =
+    {
+        // Choose RGBA8888
+        EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
+        EGL_RED_SIZE, 8,
+        EGL_GREEN_SIZE, 8,
+        EGL_BLUE_SIZE, 8,
+        EGL_ALPHA_SIZE, 8,
+        // EGL1.5 spec Section 2.2 says that depth, multisample and stencil buffer depths
+        // must match for contexts to be compatible.
+        EGL_DEPTH_SIZE, 24,
+        EGL_STENCIL_SIZE, 8,
+        EGL_SAMPLE_BUFFERS, 0,
+        // Android doesn't support pixmaps
+        EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+        EGL_CONFIG_CAVEAT, EGL_NONE,
+        EGL_CONFORMANT, esBit,
+        EGL_RENDERABLE_TYPE, esBit,
+    };
+
+    if (mEGL->hasExtension("EGL_EXT_pixel_format_float"))
+    {
+        // Don't request floating point configs
+        mConfigAttribList.push_back(EGL_COLOR_COMPONENT_TYPE_EXT);
+        mConfigAttribList.push_back(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
+    }
+
+    // Complete the attrib list
+    mConfigAttribList.push_back(EGL_NONE);
+
+    // clang-format on
+    EGLint numConfig;
+
+    EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), &mConfig, 1, &numConfig);
+    if (success == EGL_FALSE)
+    {
+        return egl::Error(mEGL->getError(), "eglChooseConfig failed");
+    }
+
+    ANGLE_TRY(initializeContext(display->getAttributeMap()));
+
+    int dummyPbufferAttribs[] = {
+        EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE,
+    };
+    mDummyPbuffer = mEGL->createPbufferSurface(mConfig, dummyPbufferAttribs);
+    if (mDummyPbuffer == EGL_NO_SURFACE)
+    {
+        return egl::Error(mEGL->getError(), "eglCreatePbufferSurface failed");
+    }
+
+    success = mEGL->makeCurrent(mDummyPbuffer, mContext);
+    if (success == EGL_FALSE)
+    {
+        return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
+    }
+
+    mFunctionsGL = mEGL->makeFunctionsGL();
+    mFunctionsGL->initialize();
+
+    return DisplayGL::initialize(display);
+}
+
+void DisplayAndroid::terminate()
+{
+    DisplayGL::terminate();
+
+    EGLBoolean success = mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    if (success == EGL_FALSE)
+    {
+        ERR() << "eglMakeCurrent error " << egl::Error(mEGL->getError());
+    }
+
+    if (mDummyPbuffer != EGL_NO_SURFACE)
+    {
+        success = mEGL->destroySurface(mDummyPbuffer);
+        mDummyPbuffer = EGL_NO_SURFACE;
+        if (success == EGL_FALSE)
+        {
+            ERR() << "eglDestroySurface error " << egl::Error(mEGL->getError());
+        }
+    }
+
+    if (mContext != EGL_NO_CONTEXT)
+    {
+        success = mEGL->destroyContext(mContext);
+        mContext = EGL_NO_CONTEXT;
+        if (success == EGL_FALSE)
+        {
+            ERR() << "eglDestroyContext error " << egl::Error(mEGL->getError());
+        }
+    }
+
+    egl::Error result = mEGL->terminate();
+    if (result.isError())
+    {
+        ERR() << "eglTerminate error " << result;
+    }
+
+    SafeDelete(mEGL);
+    SafeDelete(mFunctionsGL);
+}
+
+SurfaceImpl *DisplayAndroid::createWindowSurface(const egl::SurfaceState &state,
+                                                 EGLNativeWindowType window,
+                                                 const egl::AttributeMap &attribs)
+{
+    EGLConfig config;
+    EGLint numConfig;
+    EGLBoolean success;
+
+    const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[state.config->configID], EGL_NONE};
+    success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
+    ASSERT(success && numConfig == 1);
+
+    return new WindowSurfaceEGL(state, mEGL, config, window, attribs.toIntVector(), mContext,
+                                getRenderer());
+}
+
+SurfaceImpl *DisplayAndroid::createPbufferSurface(const egl::SurfaceState &state,
+                                                  const egl::AttributeMap &attribs)
+{
+    EGLConfig config;
+    EGLint numConfig;
+    EGLBoolean success;
+
+    const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[state.config->configID], EGL_NONE};
+    success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
+    ASSERT(success && numConfig == 1);
+
+    return new PbufferSurfaceEGL(state, mEGL, config, attribs.toIntVector(), mContext,
+                                 getRenderer());
+}
+
+SurfaceImpl *DisplayAndroid::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                                           EGLenum buftype,
+                                                           EGLClientBuffer clientBuffer,
+                                                           const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+SurfaceImpl *DisplayAndroid::createPixmapSurface(const egl::SurfaceState &state,
+                                                 NativePixmapType nativePixmap,
+                                                 const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+ImageImpl *DisplayAndroid::createImage(const egl::ImageState &state,
+                                       EGLenum target,
+                                       const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return DisplayGL::createImage(state, target, attribs);
+}
+
+template <typename T>
+void DisplayAndroid::getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const
+{
+    EGLint tmp;
+    EGLBoolean success = mEGL->getConfigAttrib(config, attribute, &tmp);
+    ASSERT(success == EGL_TRUE);
+    *value = tmp;
+}
+
+template <typename T, typename U>
+void DisplayAndroid::getConfigAttribIfExtension(EGLConfig config,
+                                                EGLint attribute,
+                                                T *value,
+                                                const char *extension,
+                                                const U &defaultValue) const
+{
+    if (mEGL->hasExtension(extension))
+    {
+        getConfigAttrib(config, attribute, value);
+    }
+    else
+    {
+        *value = static_cast<T>(defaultValue);
+    }
+}
+
+egl::ConfigSet DisplayAndroid::generateConfigs()
+{
+    egl::ConfigSet configSet;
+    mConfigIds.clear();
+
+    EGLint numConfigs;
+    EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), nullptr, 0, &numConfigs);
+    ASSERT(success == EGL_TRUE && numConfigs > 0);
+
+    std::vector<EGLConfig> configs(numConfigs);
+    EGLint numConfigs2;
+    success =
+        mEGL->chooseConfig(mConfigAttribList.data(), configs.data(), numConfigs, &numConfigs2);
+    ASSERT(success == EGL_TRUE && numConfigs2 == numConfigs);
+
+    for (int i = 0; i < numConfigs; i++)
+    {
+        egl::Config config;
+
+        getConfigAttrib(configs[i], EGL_BUFFER_SIZE, &config.bufferSize);
+        getConfigAttrib(configs[i], EGL_RED_SIZE, &config.redSize);
+        getConfigAttrib(configs[i], EGL_GREEN_SIZE, &config.greenSize);
+        getConfigAttrib(configs[i], EGL_BLUE_SIZE, &config.blueSize);
+        getConfigAttrib(configs[i], EGL_LUMINANCE_SIZE, &config.luminanceSize);
+        getConfigAttrib(configs[i], EGL_ALPHA_SIZE, &config.alphaSize);
+        getConfigAttrib(configs[i], EGL_ALPHA_MASK_SIZE, &config.alphaMaskSize);
+        getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGB, &config.bindToTextureRGB);
+        getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGBA, &config.bindToTextureRGBA);
+        getConfigAttrib(configs[i], EGL_COLOR_BUFFER_TYPE, &config.colorBufferType);
+        getConfigAttrib(configs[i], EGL_CONFIG_CAVEAT, &config.configCaveat);
+        getConfigAttrib(configs[i], EGL_CONFIG_ID, &config.configID);
+        getConfigAttrib(configs[i], EGL_CONFORMANT, &config.conformant);
+        getConfigAttrib(configs[i], EGL_DEPTH_SIZE, &config.depthSize);
+        getConfigAttrib(configs[i], EGL_LEVEL, &config.level);
+        getConfigAttrib(configs[i], EGL_MAX_PBUFFER_WIDTH, &config.maxPBufferWidth);
+        getConfigAttrib(configs[i], EGL_MAX_PBUFFER_HEIGHT, &config.maxPBufferHeight);
+        getConfigAttrib(configs[i], EGL_MAX_PBUFFER_PIXELS, &config.maxPBufferPixels);
+        getConfigAttrib(configs[i], EGL_MAX_SWAP_INTERVAL, &config.maxSwapInterval);
+        getConfigAttrib(configs[i], EGL_MIN_SWAP_INTERVAL, &config.minSwapInterval);
+        getConfigAttrib(configs[i], EGL_NATIVE_RENDERABLE, &config.nativeRenderable);
+        getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_ID, &config.nativeVisualID);
+        getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_TYPE, &config.nativeVisualType);
+        getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE, &config.renderableType);
+        getConfigAttrib(configs[i], EGL_SAMPLE_BUFFERS, &config.sampleBuffers);
+        getConfigAttrib(configs[i], EGL_SAMPLES, &config.samples);
+        getConfigAttrib(configs[i], EGL_STENCIL_SIZE, &config.stencilSize);
+        getConfigAttrib(configs[i], EGL_SURFACE_TYPE, &config.surfaceType);
+        getConfigAttrib(configs[i], EGL_TRANSPARENT_TYPE, &config.transparentType);
+        getConfigAttrib(configs[i], EGL_TRANSPARENT_RED_VALUE, &config.transparentRedValue);
+        getConfigAttrib(configs[i], EGL_TRANSPARENT_GREEN_VALUE, &config.transparentGreenValue);
+        getConfigAttrib(configs[i], EGL_TRANSPARENT_BLUE_VALUE, &config.transparentBlueValue);
+        getConfigAttribIfExtension(configs[i], EGL_COLOR_COMPONENT_TYPE_EXT,
+                                   &config.colorComponentType, "EGL_EXT_pixel_format_float",
+                                   EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
+
+        if (config.colorBufferType == EGL_RGB_BUFFER)
+        {
+            ASSERT(config.colorComponentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
+            if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
+                config.alphaSize == 8)
+            {
+                config.renderTargetFormat = GL_RGBA8;
+            }
+            else if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
+                     config.alphaSize == 0)
+            {
+                config.renderTargetFormat = GL_RGB8;
+            }
+            else if (config.redSize == 5 && config.greenSize == 6 && config.blueSize == 5 &&
+                     config.alphaSize == 0)
+            {
+                config.renderTargetFormat = GL_RGB565;
+            }
+            else
+            {
+                UNREACHABLE();
+            }
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+
+        if (config.depthSize == 0 && config.stencilSize == 0)
+        {
+            config.depthStencilFormat = GL_ZERO;
+        }
+        else if (config.depthSize == 16 && config.stencilSize == 0)
+        {
+            config.depthStencilFormat = GL_DEPTH_COMPONENT16;
+        }
+        else if (config.depthSize == 24 && config.stencilSize == 0)
+        {
+            config.depthStencilFormat = GL_DEPTH_COMPONENT24;
+        }
+        else if (config.depthSize == 24 && config.stencilSize == 8)
+        {
+            config.depthStencilFormat = GL_DEPTH24_STENCIL8;
+        }
+        else if (config.depthSize == 0 && config.stencilSize == 8)
+        {
+            config.depthStencilFormat = GL_STENCIL_INDEX8;
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+
+        config.matchNativePixmap = EGL_NONE;
+        config.optimalOrientation = 0;
+
+        int internalId = configSet.add(config);
+        mConfigIds[internalId] = config.configID;
+    }
+
+    return configSet;
+}
+
+bool DisplayAndroid::testDeviceLost()
+{
+    return false;
+}
+
+egl::Error DisplayAndroid::restoreLostDevice()
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+bool DisplayAndroid::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    return ANativeWindow_getFormat(window) >= 0;
+}
+
+egl::Error DisplayAndroid::getDevice(DeviceImpl **device)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayAndroid::waitClient() const
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayAndroid::waitNative(EGLint engine,
+                                      egl::Surface *drawSurface,
+                                      egl::Surface *readSurface) const
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
new file mode 100644
index 0000000..87ae21e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayAndroid.h: Android implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_
+#define LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+
+namespace rx
+{
+
+class DisplayAndroid : public DisplayEGL
+{
+  public:
+    DisplayAndroid(const egl::DisplayState &state);
+    ~DisplayAndroid() override;
+
+    egl::Error initialize(egl::Display *display) override;
+    void terminate() override;
+
+    SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+                                     EGLNativeWindowType window,
+                                     const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+                                      const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                               EGLenum buftype,
+                                               EGLClientBuffer clientBuffer,
+                                               const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+                                     NativePixmapType nativePixmap,
+                                     const egl::AttributeMap &attribs) override;
+
+    ImageImpl *createImage(const egl::ImageState &state,
+                           EGLenum target,
+                           const egl::AttributeMap &attribs) override;
+
+    egl::ConfigSet generateConfigs() override;
+
+    bool testDeviceLost() override;
+    egl::Error restoreLostDevice() override;
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+    egl::Error getDevice(DeviceImpl **device) override;
+
+    egl::Error waitClient() const override;
+    egl::Error waitNative(EGLint engine,
+                          egl::Surface *drawSurface,
+                          egl::Surface *readSurface) const override;
+
+  private:
+    template <typename T>
+    void getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const;
+
+    template <typename T, typename U>
+    void getConfigAttribIfExtension(EGLConfig config,
+                                    EGLint attribute,
+                                    T *value,
+                                    const char *extension,
+                                    const U &defaultValue) const;
+
+    std::vector<EGLint> mConfigAttribList;
+    std::map<EGLint, EGLint> mConfigIds;
+    EGLSurface mDummyPbuffer;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h
new file mode 100644
index 0000000..78f9009
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// functionsegl_typedefs.h: Typedefs of EGL functions.
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_
+
+#include <EGL/egl.h>
+
+namespace rx
+{
+// EGL 1.0
+typedef EGLBoolean (*PFNEGLCHOOSECONFIGPROC)(EGLDisplay dpy,
+                                             const EGLint *attrib_list,
+                                             EGLConfig *configs,
+                                             EGLint config_size,
+                                             EGLint *num_config);
+typedef EGLBoolean (*PFNEGLCOPYBUFFERSPROC)(EGLDisplay dpy,
+                                            EGLSurface surface,
+                                            EGLNativePixmapType target);
+typedef EGLContext (*PFNEGLCREATECONTEXTPROC)(EGLDisplay dpy,
+                                              EGLConfig config,
+                                              EGLContext share_context,
+                                              const EGLint *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPBUFFERSURFACEPROC)(EGLDisplay dpy,
+                                                     EGLConfig config,
+                                                     const EGLint *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPIXMAPSURFACEPROC)(EGLDisplay dpy,
+                                                    EGLConfig config,
+                                                    EGLNativePixmapType pixmap,
+                                                    const EGLint *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy,
+                                                    EGLConfig config,
+                                                    EGLNativeWindowType win,
+                                                    const EGLint *attrib_list);
+typedef EGLBoolean (*PFNEGLDESTROYCONTEXTPROC)(EGLDisplay dpy, EGLContext ctx);
+typedef EGLBoolean (*PFNEGLDESTROYSURFACEPROC)(EGLDisplay dpy, EGLSurface surface);
+typedef EGLBoolean (*PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay dpy,
+                                                EGLConfig config,
+                                                EGLint attribute,
+                                                EGLint *value);
+typedef EGLBoolean (*PFNEGLGETCONFIGSPROC)(EGLDisplay dpy,
+                                           EGLConfig *configs,
+                                           EGLint config_size,
+                                           EGLint *num_config);
+typedef EGLDisplay (*PFNEGLGETCURRENTDISPLAYPROC)(void);
+typedef EGLSurface (*PFNEGLGETCURRENTSURFACEPROC)(EGLint readdraw);
+typedef EGLDisplay (*PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType display_id);
+typedef EGLint (*PFNEGLGETERRORPROC)(void);
+typedef __eglMustCastToProperFunctionPointerType (*PFNEGLGETPROCADDRESSPROC)(const char *procname);
+typedef EGLBoolean (*PFNEGLINITIALIZEPROC)(EGLDisplay dpy, EGLint *major, EGLint *minor);
+typedef EGLBoolean (*PFNEGLMAKECURRENTPROC)(EGLDisplay dpy,
+                                            EGLSurface draw,
+                                            EGLSurface read,
+                                            EGLContext ctx);
+typedef EGLBoolean (*PFNEGLQUERYCONTEXTPROC)(EGLDisplay dpy,
+                                             EGLContext ctx,
+                                             EGLint attribute,
+                                             EGLint *value);
+typedef const char *(*PFNEGLQUERYSTRINGPROC)(EGLDisplay dpy, EGLint name);
+typedef EGLBoolean (*PFNEGLQUERYSURFACEPROC)(EGLDisplay dpy,
+                                             EGLSurface surface,
+                                             EGLint attribute,
+                                             EGLint *value);
+typedef EGLBoolean (*PFNEGLSWAPBUFFERSPROC)(EGLDisplay dpy, EGLSurface surface);
+typedef EGLBoolean (*PFNEGLTERMINATEPROC)(EGLDisplay dpy);
+typedef EGLBoolean (*PFNEGLWAITGLPROC)(void);
+typedef EGLBoolean (*PFNEGLWAITNATIVEPROC)(EGLint engine);
+
+// EGL 1.1
+typedef EGLBoolean (*PFNEGLBINDTEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+typedef EGLBoolean (*PFNEGLRELEASETEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+typedef EGLBoolean (*PFNEGLSURFACEATTRIBPROC)(EGLDisplay dpy,
+                                              EGLSurface surface,
+                                              EGLint attribute,
+                                              EGLint value);
+typedef EGLBoolean (*PFNEGLSWAPINTERVALPROC)(EGLDisplay dpy, EGLint interval);
+
+// EGL 1.2
+typedef EGLBoolean (*PFNEGLBINDAPIPROC)(EGLenum api);
+typedef EGLenum (*PFNEGLQUERYAPIPROC)(void);
+typedef EGLSurface (*PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC)(EGLDisplay dpy,
+                                                              EGLenum buftype,
+                                                              EGLClientBuffer buffer,
+                                                              EGLConfig config,
+                                                              const EGLint *attrib_list);
+typedef EGLBoolean (*PFNEGLRELEASETHREADPROC)(void);
+typedef EGLBoolean (*PFNEGLWAITCLIENTPROC)(void);
+
+// EGL 1.3
+
+// EGL 1.4
+typedef EGLContext (*PFNEGLGETCURRENTCONTEXTPROC)(void);
+
+// EGL 1.5
+typedef EGLSync (*PFNEGLCREATESYNCPROC)(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+typedef EGLBoolean (*PFNEGLDESTROYSYNCPROC)(EGLDisplay dpy, EGLSync sync);
+typedef EGLint (*PFNEGLCLIENTWAITSYNCPROC)(EGLDisplay dpy,
+                                           EGLSync sync,
+                                           EGLint flags,
+                                           EGLTime timeout);
+typedef EGLBoolean (*PFNEGLGETSYNCATTRIBPROC)(EGLDisplay dpy,
+                                              EGLSync sync,
+                                              EGLint attribute,
+                                              EGLAttrib *value);
+typedef EGLImage (*PFNEGLCREATEIMAGEPROC)(EGLDisplay dpy,
+                                          EGLContext ctx,
+                                          EGLenum target,
+                                          EGLClientBuffer buffer,
+                                          const EGLAttrib *attrib_list);
+typedef EGLBoolean (*PFNEGLDESTROYIMAGEPROC)(EGLDisplay dpy, EGLImage image);
+typedef EGLDisplay (*PFNEGLGETPLATFORMDISPLAYPROC)(EGLenum platform,
+                                                   void *native_display,
+                                                   const EGLAttrib *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPLATFORMWINDOWSURFACEPROC)(EGLDisplay dpy,
+                                                            EGLConfig config,
+                                                            void *native_window,
+                                                            const EGLAttrib *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC)(EGLDisplay dpy,
+                                                            EGLConfig config,
+                                                            void *native_pixmap,
+                                                            const EGLAttrib *attrib_list);
+typedef EGLBoolean (*PFNEGLWAITSYNCPROC)(EGLDisplay dpy, EGLSync sync, EGLint flags);
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp
new file mode 100644
index 0000000..6d89d9a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp
@@ -0,0 +1,959 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayOzone.cpp: Ozone implementation of egl::Display
+
+#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+
+#include <fcntl.h>
+#include <poll.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include <EGL/eglext.h>
+
+#include <gbm.h>
+#include <drm_fourcc.h>
+
+#include "common/debug.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
+#include "libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h"
+#include "platform/Platform.h"
+
+// ARM-specific extension needed to make Mali GPU behave - not in any
+// published header file.
+#ifndef EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM
+#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
+#endif
+
+#ifndef EGL_NO_CONFIG_MESA
+#define EGL_NO_CONFIG_MESA ((EGLConfig)0)
+#endif
+
+namespace
+{
+
+EGLint UnsignedToSigned(uint32_t u)
+{
+    return *reinterpret_cast<const EGLint *>(&u);
+}
+
+drmModeModeInfoPtr ChooseMode(drmModeConnectorPtr conn)
+{
+    drmModeModeInfoPtr mode = nullptr;
+    ASSERT(conn);
+    ASSERT(conn->connection == DRM_MODE_CONNECTED);
+    // use first preferred mode if any, else end up with last mode in list
+    for (int i = 0; i < conn->count_modes; ++i)
+    {
+        mode = conn->modes + i;
+        if (mode->type & DRM_MODE_TYPE_PREFERRED)
+        {
+            break;
+        }
+    }
+    return mode;
+}
+
+int ChooseCRTC(int fd, drmModeConnectorPtr conn)
+{
+    for (int i = 0; i < conn->count_encoders; ++i)
+    {
+        drmModeEncoderPtr enc = drmModeGetEncoder(fd, conn->encoders[i]);
+        unsigned long crtcs = enc->possible_crtcs;
+        drmModeFreeEncoder(enc);
+        if (crtcs)
+        {
+            return __builtin_ctzl(crtcs);
+        }
+    }
+    return -1;
+}
+}  // namespace
+
+namespace rx
+{
+
+// TODO(fjhenigman) Implement swap control.  Until then this is unused.
+SwapControlData::SwapControlData()
+    : targetSwapInterval(0), maxSwapInterval(-1), currentSwapInterval(-1)
+{
+}
+
+DisplayOzone::Buffer::Buffer(DisplayOzone *display,
+                             uint32_t useFlags,
+                             uint32_t gbmFormat,
+                             uint32_t drmFormat,
+                             uint32_t drmFormatFB,
+                             int depthBits,
+                             int stencilBits)
+    : mDisplay(display),
+      mNative(nullptr),
+      mWidth(0),
+      mHeight(0),
+      mDepthBits(depthBits),
+      mStencilBits(stencilBits),
+      mUseFlags(useFlags),
+      mGBMFormat(gbmFormat),
+      mDRMFormat(drmFormat),
+      mDRMFormatFB(drmFormatFB),
+      mBO(nullptr),
+      mDMABuf(-1),
+      mHasDRMFB(false),
+      mDRMFB(0),
+      mImage(EGL_NO_IMAGE_KHR),
+      mColorBuffer(0),
+      mDSBuffer(0),
+      mGLFB(0),
+      mTexture(0)
+{
+}
+
+DisplayOzone::Buffer::~Buffer()
+{
+    mDisplay->mFunctionsGL->deleteFramebuffers(1, &mGLFB);
+    reset();
+}
+
+void DisplayOzone::Buffer::reset()
+{
+    if (mHasDRMFB)
+    {
+        int fd = gbm_device_get_fd(mDisplay->mGBM);
+        drmModeRmFB(fd, mDRMFB);
+        mHasDRMFB = false;
+    }
+
+    FunctionsGL *gl = mDisplay->mFunctionsGL;
+    gl->deleteRenderbuffers(1, &mColorBuffer);
+    mColorBuffer = 0;
+    gl->deleteRenderbuffers(1, &mDSBuffer);
+    mDSBuffer = 0;
+
+    // Here we might destroy the GL framebuffer (mGLFB) but unlike every other resource in Buffer,
+    // it does not get destroyed (and recreated) because when it is the default framebuffer for
+    // an ANGLE surface then ANGLE expects it to have the same lifetime as that surface.
+
+    if (mImage != EGL_NO_IMAGE_KHR)
+    {
+        mDisplay->mEGL->destroyImageKHR(mImage);
+        mImage = EGL_NO_IMAGE_KHR;
+    }
+
+    if (mTexture)
+    {
+        gl->deleteTextures(1, &mTexture);
+        mTexture = 0;
+    }
+
+    if (mDMABuf >= 0)
+    {
+        close(mDMABuf);
+        mDMABuf = -1;
+    }
+
+    if (mBO)
+    {
+        gbm_bo_destroy(mBO);
+        mBO = nullptr;
+    }
+}
+
+bool DisplayOzone::Buffer::resize(int32_t width, int32_t height)
+{
+    if (mWidth == width && mHeight == height)
+    {
+        return true;
+    }
+
+    reset();
+
+    if (width <= 0 || height <= 0)
+    {
+        return true;
+    }
+
+    mBO = gbm_bo_create(mDisplay->mGBM, width, height, mGBMFormat, mUseFlags);
+    if (!mBO)
+    {
+        return false;
+    }
+
+    mDMABuf = gbm_bo_get_fd(mBO);
+    if (mDMABuf < 0)
+    {
+        return false;
+    }
+
+    // clang-format off
+    const EGLint attr[] =
+    {
+        EGL_WIDTH, width,
+        EGL_HEIGHT, height,
+        EGL_LINUX_DRM_FOURCC_EXT, UnsignedToSigned(mDRMFormat),
+        EGL_DMA_BUF_PLANE0_FD_EXT, mDMABuf,
+        EGL_DMA_BUF_PLANE0_PITCH_EXT, UnsignedToSigned(gbm_bo_get_stride(mBO)),
+        EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
+        EGL_NONE,
+    };
+    // clang-format on
+
+    mImage = mDisplay->mEGL->createImageKHR(EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attr);
+    if (mImage == EGL_NO_IMAGE_KHR)
+    {
+        return false;
+    }
+
+    FunctionsGL *gl    = mDisplay->mFunctionsGL;
+    StateManagerGL *sm = mDisplay->getRenderer()->getStateManager();
+
+    gl->genRenderbuffers(1, &mColorBuffer);
+    sm->bindRenderbuffer(GL_RENDERBUFFER, mColorBuffer);
+    gl->eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mImage);
+
+    sm->bindFramebuffer(GL_FRAMEBUFFER, mGLFB);
+    gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER,
+                                mColorBuffer);
+
+    if (mDepthBits || mStencilBits)
+    {
+        gl->genRenderbuffers(1, &mDSBuffer);
+        sm->bindRenderbuffer(GL_RENDERBUFFER, mDSBuffer);
+        gl->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height);
+    }
+
+    if (mDepthBits)
+    {
+        gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+                                    mDSBuffer);
+    }
+
+    if (mStencilBits)
+    {
+        gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                                    mDSBuffer);
+    }
+
+    mWidth  = width;
+    mHeight = height;
+    return true;
+}
+
+bool DisplayOzone::Buffer::initialize(const NativeWindow *native)
+{
+    mNative = native;
+    mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB);
+    return resize(native->width, native->height);
+}
+
+bool DisplayOzone::Buffer::initialize(int width, int height)
+{
+    mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB);
+    return resize(width, height);
+}
+
+void DisplayOzone::Buffer::bindTexImage()
+{
+    mDisplay->mFunctionsGL->eglImageTargetTexture2DOES(GL_TEXTURE_2D, mImage);
+}
+
+GLuint DisplayOzone::Buffer::getTexture()
+{
+    // TODO(fjhenigman) Try not to create a new texture every time.  That already works on Intel
+    // and should work on Mali with proper fences.
+    FunctionsGL *gl    = mDisplay->mFunctionsGL;
+    StateManagerGL *sm = mDisplay->getRenderer()->getStateManager();
+
+    gl->genTextures(1, &mTexture);
+    sm->bindTexture(GL_TEXTURE_2D, mTexture);
+    gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    ASSERT(mImage != EGL_NO_IMAGE_KHR);
+    gl->eglImageTargetTexture2DOES(GL_TEXTURE_2D, mImage);
+    return mTexture;
+}
+
+uint32_t DisplayOzone::Buffer::getDRMFB()
+{
+    if (!mHasDRMFB)
+    {
+        int fd              = gbm_device_get_fd(mDisplay->mGBM);
+        uint32_t handles[4] = {gbm_bo_get_handle(mBO).u32};
+        uint32_t pitches[4] = {gbm_bo_get_stride(mBO)};
+        uint32_t offsets[4] = {0};
+        if (drmModeAddFB2(fd, mWidth, mHeight, mDRMFormatFB, handles, pitches, offsets, &mDRMFB, 0))
+        {
+            WARN() << "drmModeAddFB2 failed: " << errno << " " << strerror(errno);
+        }
+        else
+        {
+            mHasDRMFB = true;
+        }
+    }
+
+    return mDRMFB;
+}
+
+FramebufferGL *DisplayOzone::Buffer::framebufferGL(const gl::FramebufferState &state)
+{
+    return new FramebufferGL(
+        mGLFB, state, mDisplay->mFunctionsGL, mDisplay->getRenderer()->getWorkarounds(),
+        mDisplay->getRenderer()->getBlitter(), mDisplay->getRenderer()->getStateManager());
+}
+
+void DisplayOzone::Buffer::present()
+{
+    if (mNative)
+    {
+        if (mNative->visible)
+        {
+            mDisplay->drawBuffer(this);
+        }
+        resize(mNative->width, mNative->height);
+    }
+}
+
+DisplayOzone::DisplayOzone(const egl::DisplayState &state)
+    : DisplayEGL(state),
+      mSwapControl(SwapControl::ABSENT),
+      mMinSwapInterval(0),
+      mMaxSwapInterval(0),
+      mCurrentSwapInterval(-1),
+      mGBM(nullptr),
+      mConnector(nullptr),
+      mMode(nullptr),
+      mCRTC(nullptr),
+      mSetCRTC(true),
+      mWidth(1280),
+      mHeight(1024),
+      mScanning(nullptr),
+      mPending(nullptr),
+      mDrawing(nullptr),
+      mUnused(nullptr),
+      mProgram(0),
+      mVertexShader(0),
+      mFragmentShader(0),
+      mVertexBuffer(0),
+      mIndexBuffer(0),
+      mCenterUniform(0),
+      mWindowSizeUniform(0),
+      mBorderSizeUniform(0),
+      mDepthUniform(0)
+{
+}
+
+DisplayOzone::~DisplayOzone()
+{
+}
+
+bool DisplayOzone::hasUsableScreen(int fd)
+{
+    drmModeResPtr resources = drmModeGetResources(fd);
+    if (!resources)
+    {
+        return false;
+    }
+    if (resources->count_connectors < 1)
+    {
+        drmModeFreeResources(resources);
+        return false;
+    }
+
+    mConnector = nullptr;
+    for (int i = 0; i < resources->count_connectors; ++i)
+    {
+        drmModeFreeConnector(mConnector);
+        mConnector = drmModeGetConnector(fd, resources->connectors[i]);
+        if (!mConnector || mConnector->connection != DRM_MODE_CONNECTED)
+        {
+            continue;
+        }
+        mMode = ChooseMode(mConnector);
+        if (!mMode)
+        {
+            continue;
+        }
+        int n = ChooseCRTC(fd, mConnector);
+        if (n < 0)
+        {
+            continue;
+        }
+        mCRTC = drmModeGetCrtc(fd, resources->crtcs[n]);
+        if (mCRTC)
+        {
+            // found a screen
+            mGBM = gbm_create_device(fd);
+            if (mGBM)
+            {
+                mWidth  = mMode->hdisplay;
+                mHeight = mMode->vdisplay;
+                drmModeFreeResources(resources);
+                return true;
+            }
+            // can't use this screen
+            drmModeFreeCrtc(mCRTC);
+            mCRTC = nullptr;
+        }
+    }
+
+    drmModeFreeResources(resources);
+    return false;
+}
+
+egl::Error DisplayOzone::initialize(egl::Display *display)
+{
+    int fd;
+    char deviceName[30];
+
+    for (int i = 0; i < 64; ++i)
+    {
+        snprintf(deviceName, sizeof(deviceName), "/dev/dri/card%d", i);
+        fd = open(deviceName, O_RDWR | O_CLOEXEC);
+        if (fd >= 0)
+        {
+            if (hasUsableScreen(fd))
+            {
+                break;
+            }
+            close(fd);
+        }
+    }
+
+    if (!mGBM)
+    {
+        // there's no usable screen so try to proceed without one
+        for (int i = 128; i < 192; ++i)
+        {
+            snprintf(deviceName, sizeof(deviceName), "/dev/dri/renderD%d", i);
+            fd = open(deviceName, O_RDWR | O_CLOEXEC);
+            if (fd >= 0)
+            {
+                mGBM = gbm_create_device(fd);
+                if (mGBM)
+                {
+                    break;
+                }
+                close(fd);
+            }
+        }
+    }
+
+    if (!mGBM)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not open drm device.");
+    }
+
+    // ANGLE builds its executables with an RPATH so they pull in ANGLE's libGL and libEGL.
+    // Here we need to open the native libEGL.  An absolute path would work, but then we
+    // couldn't use LD_LIBRARY_PATH which is often useful during development.  Instead we take
+    // advantage of the fact that the system lib is available under multiple names (for example
+    // with a .1 suffix) while Angle only installs libEGL.so.
+    FunctionsEGLDL *egl = new FunctionsEGLDL();
+    mEGL = egl;
+    ANGLE_TRY(egl->initialize(display->getNativeDisplayId(), "libEGL.so.1"));
+
+    const char *necessaryExtensions[] = {
+        "EGL_KHR_image_base", "EGL_EXT_image_dma_buf_import", "EGL_KHR_surfaceless_context",
+    };
+    for (auto &ext : necessaryExtensions)
+    {
+        if (!mEGL->hasExtension(ext))
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, "need %s", ext);
+        }
+    }
+
+    if (mEGL->hasExtension("EGL_MESA_configless_context"))
+    {
+        mConfig = EGL_NO_CONFIG_MESA;
+    }
+    else
+    {
+        // clang-format off
+        const EGLint attrib[] =
+        {
+            // We want RGBA8 and DEPTH24_STENCIL8
+            EGL_RED_SIZE, 8,
+            EGL_GREEN_SIZE, 8,
+            EGL_BLUE_SIZE, 8,
+            EGL_ALPHA_SIZE, 8,
+            EGL_DEPTH_SIZE, 24,
+            EGL_STENCIL_SIZE, 8,
+            EGL_NONE,
+        };
+        // clang-format on
+        EGLint numConfig;
+        EGLConfig config[1];
+        if (!mEGL->chooseConfig(attrib, config, 1, &numConfig) || numConfig < 1)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, "Could not get EGL config.");
+        }
+        mConfig = config[0];
+    }
+
+    ANGLE_TRY(initializeContext(display->getAttributeMap()));
+
+    if (!mEGL->makeCurrent(EGL_NO_SURFACE, mContext))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not make context current.");
+    }
+
+    mFunctionsGL = mEGL->makeFunctionsGL();
+    mFunctionsGL->initialize();
+
+    return DisplayGL::initialize(display);
+}
+
+void DisplayOzone::pageFlipHandler(int fd,
+                                   unsigned int sequence,
+                                   unsigned int tv_sec,
+                                   unsigned int tv_usec,
+                                   void *data)
+{
+    DisplayOzone *display = reinterpret_cast<DisplayOzone *>(data);
+    uint64_t tv = tv_sec;
+    display->pageFlipHandler(sequence, tv * 1000000 + tv_usec);
+}
+
+void DisplayOzone::pageFlipHandler(unsigned int sequence, uint64_t tv)
+{
+    ASSERT(mPending);
+    mUnused   = mScanning;
+    mScanning = mPending;
+    mPending  = nullptr;
+}
+
+void DisplayOzone::presentScreen()
+{
+    if (!mCRTC)
+    {
+        // no monitor
+        return;
+    }
+
+    // see if pending flip has finished, without blocking
+    int fd = gbm_device_get_fd(mGBM);
+    if (mPending)
+    {
+        pollfd pfd;
+        pfd.fd     = fd;
+        pfd.events = POLLIN;
+        if (poll(&pfd, 1, 0) < 0)
+        {
+            WARN() << "poll failed: " << errno << " " << strerror(errno);
+        }
+        if (pfd.revents & POLLIN)
+        {
+            drmEventContext event;
+            event.version           = DRM_EVENT_CONTEXT_VERSION;
+            event.page_flip_handler = pageFlipHandler;
+            drmHandleEvent(fd, &event);
+        }
+    }
+
+    // if pending flip has finished, schedule next one
+    if (!mPending && mDrawing)
+    {
+        flushGL();
+        if (mSetCRTC)
+        {
+            if (drmModeSetCrtc(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), 0, 0,
+                               &mConnector->connector_id, 1, mMode))
+            {
+                WARN() << "set crtc failed: " << errno << " " << strerror(errno);
+            }
+            mSetCRTC = false;
+        }
+        if (drmModePageFlip(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), DRM_MODE_PAGE_FLIP_EVENT,
+                            this))
+        {
+            WARN() << "page flip failed: " << errno << " " << strerror(errno);
+        }
+        mPending = mDrawing;
+        mDrawing = nullptr;
+    }
+}
+
+GLuint DisplayOzone::makeShader(GLuint type, const char *src)
+{
+    FunctionsGL *gl = mFunctionsGL;
+    GLuint shader = gl->createShader(type);
+    gl->shaderSource(shader, 1, &src, nullptr);
+    gl->compileShader(shader);
+
+    GLchar buf[999];
+    GLsizei len;
+    GLint compiled;
+    gl->getShaderInfoLog(shader, sizeof(buf), &len, buf);
+    gl->getShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+    if (compiled != GL_TRUE)
+    {
+        WARN() << "DisplayOzone shader compilation error: " << buf;
+    }
+
+    return shader;
+}
+
+void DisplayOzone::drawWithTexture(Buffer *buffer)
+{
+    FunctionsGL *gl    = mFunctionsGL;
+    StateManagerGL *sm = getRenderer()->getStateManager();
+
+    if (!mProgram)
+    {
+        const GLchar *vertexSource =
+            "#version 100\n"
+            "attribute vec3 vertex;\n"
+            "uniform vec2 center;\n"
+            "uniform vec2 windowSize;\n"
+            "uniform vec2 borderSize;\n"
+            "uniform float depth;\n"
+            "varying vec3 texCoord;\n"
+            "void main()\n"
+            "{\n"
+            "    vec2 pos = vertex.xy * (windowSize + borderSize * vertex.z);\n"
+            "    gl_Position = vec4(center + pos, depth, 1);\n"
+            "    texCoord = vec3(pos / windowSize * vec2(.5, -.5) + vec2(.5, .5), vertex.z);\n"
+            "}\n";
+
+        const GLchar *fragmentSource =
+            "#version 100\n"
+            "precision mediump float;\n"
+            "uniform sampler2D tex;\n"
+            "varying vec3 texCoord;\n"
+            "void main()\n"
+            "{\n"
+            "    if (texCoord.z > 0.)\n"
+            "    {\n"
+            "        float c = abs((texCoord.z * 2.) - 1.);\n"
+            "        gl_FragColor = vec4(c, c, c, 1);\n"
+            "    }\n"
+            "    else\n"
+            "    {\n"
+            "        gl_FragColor = texture2D(tex, texCoord.xy);\n"
+            "    }\n"
+            "}\n";
+
+        mVertexShader   = makeShader(GL_VERTEX_SHADER, vertexSource);
+        mFragmentShader = makeShader(GL_FRAGMENT_SHADER, fragmentSource);
+        mProgram = gl->createProgram();
+        gl->attachShader(mProgram, mVertexShader);
+        gl->attachShader(mProgram, mFragmentShader);
+        gl->bindAttribLocation(mProgram, 0, "vertex");
+        gl->linkProgram(mProgram);
+        GLint linked;
+        gl->getProgramiv(mProgram, GL_LINK_STATUS, &linked);
+        if (!linked)
+        {
+            WARN() << "shader link failed: cannot display buffer";
+            return;
+        }
+        mCenterUniform     = gl->getUniformLocation(mProgram, "center");
+        mWindowSizeUniform = gl->getUniformLocation(mProgram, "windowSize");
+        mBorderSizeUniform = gl->getUniformLocation(mProgram, "borderSize");
+        mDepthUniform      = gl->getUniformLocation(mProgram, "depth");
+        GLint texUniform = gl->getUniformLocation(mProgram, "tex");
+        sm->useProgram(mProgram);
+        gl->uniform1i(texUniform, 0);
+
+        // clang-format off
+        const GLfloat vertices[] =
+        {
+             // window corners, and window border inside corners
+             1, -1, 0,
+            -1, -1, 0,
+             1,  1, 0,
+            -1,  1, 0,
+             // window border outside corners
+             1, -1, 1,
+            -1, -1, 1,
+             1,  1, 1,
+            -1,  1, 1,
+        };
+        // clang-format on
+        gl->genBuffers(1, &mVertexBuffer);
+        sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+        gl->bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+        // window border triangle strip
+        const GLuint borderStrip[] = {5, 0, 4, 2, 6, 3, 7, 1, 5, 0};
+
+        gl->genBuffers(1, &mIndexBuffer);
+        sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+        gl->bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(borderStrip), borderStrip, GL_STATIC_DRAW);
+    }
+    else
+    {
+        sm->useProgram(mProgram);
+        sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+        sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+    }
+
+    // convert from pixels to "-1 to 1" space
+    const NativeWindow *n = buffer->getNative();
+    double x              = n->x * 2. / mWidth - 1;
+    double y              = n->y * 2. / mHeight - 1;
+    double halfw          = n->width * 1. / mWidth;
+    double halfh          = n->height * 1. / mHeight;
+    double borderw        = n->borderWidth * 2. / mWidth;
+    double borderh        = n->borderHeight * 2. / mHeight;
+
+    gl->uniform2f(mCenterUniform, x + halfw, y + halfh);
+    gl->uniform2f(mWindowSizeUniform, halfw, halfh);
+    gl->uniform2f(mBorderSizeUniform, borderw, borderh);
+    gl->uniform1f(mDepthUniform, n->depth / 1e6);
+
+    sm->setBlendEnabled(false);
+    sm->setCullFaceEnabled(false);
+    sm->setStencilTestEnabled(false);
+    sm->setScissorTestEnabled(false);
+    sm->setDepthTestEnabled(true);
+    sm->setColorMask(true, true, true, true);
+    sm->setDepthMask(true);
+    sm->setDepthRange(0, 1);
+    sm->setDepthFunc(GL_LESS);
+    sm->setViewport(gl::Rectangle(0, 0, mWidth, mHeight));
+    sm->activeTexture(0);
+    GLuint tex = buffer->getTexture();
+    sm->bindTexture(GL_TEXTURE_2D, tex);
+    gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    gl->enableVertexAttribArray(0);
+    sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB());
+    gl->drawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    gl->drawElements(GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, 0);
+    sm->deleteTexture(tex);
+}
+
+void DisplayOzone::drawBuffer(Buffer *buffer)
+{
+    if (!mDrawing)
+    {
+        // get buffer on which to draw window
+        if (mUnused)
+        {
+            mDrawing = mUnused;
+            mUnused  = nullptr;
+        }
+        else
+        {
+            mDrawing = new Buffer(this, GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT,
+                                  GBM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888,
+                                  true, true);  // XXX shouldn't need stencil
+            if (!mDrawing || !mDrawing->initialize(mWidth, mHeight))
+            {
+                return;
+            }
+        }
+
+        StateManagerGL *sm = getRenderer()->getStateManager();
+        sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB());
+        sm->setClearColor(gl::ColorF(0, 0, 0, 1));
+        sm->setClearDepth(1);
+        sm->setScissorTestEnabled(false);
+        sm->setColorMask(true, true, true, true);
+        sm->setDepthMask(true);
+        mFunctionsGL->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    }
+
+    drawWithTexture(buffer);
+    presentScreen();
+}
+
+void DisplayOzone::flushGL()
+{
+    mFunctionsGL->flush();
+    if (mEGL->hasExtension("EGL_KHR_fence_sync"))
+    {
+        const EGLint attrib[] = {EGL_SYNC_CONDITION_KHR,
+                                 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, EGL_NONE};
+        EGLSyncKHR fence = mEGL->createSyncKHR(EGL_SYNC_FENCE_KHR, attrib);
+        if (fence)
+        {
+            // TODO(fjhenigman) Figure out the right way to use fences on Mali GPU
+            // to maximize throughput and avoid hangs when a program is interrupted.
+            // This busy wait was an attempt to reduce hangs when interrupted by SIGINT,
+            // but we still get some.
+            for (;;)
+            {
+                EGLint r = mEGL->clientWaitSyncKHR(fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 0);
+                if (r != EGL_TIMEOUT_EXPIRED_KHR)
+                {
+                    break;
+                }
+                usleep(99);
+            }
+            mEGL->destroySyncKHR(fence);
+            return;
+        }
+    }
+}
+
+void DisplayOzone::terminate()
+{
+    SafeDelete(mScanning);
+    SafeDelete(mPending);
+    SafeDelete(mDrawing);
+    SafeDelete(mUnused);
+
+    if (mProgram)
+    {
+        mFunctionsGL->deleteProgram(mProgram);
+        mFunctionsGL->deleteShader(mVertexShader);
+        mFunctionsGL->deleteShader(mFragmentShader);
+        mFunctionsGL->deleteBuffers(1, &mVertexBuffer);
+        mFunctionsGL->deleteBuffers(1, &mIndexBuffer);
+        mProgram = 0;
+    }
+
+    DisplayGL::terminate();
+
+    if (mContext)
+    {
+        // Mesa might crash if you terminate EGL with a context current
+        // then re-initialize EGL, so make our context not current.
+        mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        mEGL->destroyContext(mContext);
+        mContext = nullptr;
+    }
+
+    SafeDelete(mFunctionsGL);
+
+    if (mEGL)
+    {
+        mEGL->terminate();
+        SafeDelete(mEGL);
+    }
+
+    drmModeFreeConnector(mConnector);
+    mConnector = nullptr;
+    mMode      = nullptr;
+    drmModeFreeCrtc(mCRTC);
+    mCRTC = nullptr;
+
+    if (mGBM)
+    {
+        int fd = gbm_device_get_fd(mGBM);
+        gbm_device_destroy(mGBM);
+        mGBM = nullptr;
+        close(fd);
+    }
+}
+
+SurfaceImpl *DisplayOzone::createWindowSurface(const egl::SurfaceState &state,
+                                               EGLNativeWindowType window,
+                                               const egl::AttributeMap &attribs)
+{
+    Buffer *buffer = new Buffer(this, GBM_BO_USE_RENDERING, GBM_FORMAT_ARGB8888,
+                                DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, true, true);
+    if (!buffer || !buffer->initialize(reinterpret_cast<const NativeWindow *>(window)))
+    {
+        return nullptr;
+    }
+    return new SurfaceOzone(state, getRenderer(), buffer);
+}
+
+SurfaceImpl *DisplayOzone::createPbufferSurface(const egl::SurfaceState &state,
+                                                const egl::AttributeMap &attribs)
+{
+    EGLAttrib width  = attribs.get(EGL_WIDTH, 0);
+    EGLAttrib height = attribs.get(EGL_HEIGHT, 0);
+    Buffer *buffer = new Buffer(this, GBM_BO_USE_RENDERING, GBM_FORMAT_ARGB8888,
+                                DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, true, true);
+    if (!buffer || !buffer->initialize(width, height))
+    {
+        return nullptr;
+    }
+    return new SurfaceOzone(state, getRenderer(), buffer);
+}
+
+SurfaceImpl *DisplayOzone::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                                         EGLenum buftype,
+                                                         EGLClientBuffer clientBuffer,
+                                                         const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+SurfaceImpl *DisplayOzone::createPixmapSurface(const egl::SurfaceState &state,
+                                               NativePixmapType nativePixmap,
+                                               const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+egl::Error DisplayOzone::getDevice(DeviceImpl **device)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::ConfigSet DisplayOzone::generateConfigs()
+{
+    egl::ConfigSet configs;
+
+    egl::Config config;
+    config.redSize           = 8;
+    config.greenSize         = 8;
+    config.blueSize          = 8;
+    config.alphaSize         = 8;
+    config.depthSize         = 24;
+    config.stencilSize       = 8;
+    config.bindToTextureRGBA = EGL_TRUE;
+    config.renderableType    = EGL_OPENGL_ES2_BIT;
+    config.surfaceType       = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
+    config.renderTargetFormat = GL_RGBA8;
+    config.depthStencilFormat = GL_DEPTH24_STENCIL8;
+
+    configs.add(config);
+    return configs;
+}
+
+bool DisplayOzone::testDeviceLost()
+{
+    return false;
+}
+
+egl::Error DisplayOzone::restoreLostDevice()
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayOzone::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    return true;
+}
+
+egl::Error DisplayOzone::waitClient() const
+{
+    // TODO(fjhenigman) Implement this.
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayOzone::waitNative(EGLint engine,
+                                    egl::Surface *drawSurface,
+                                    egl::Surface *readSurface) const
+{
+    // TODO(fjhenigman) Implement this.
+    return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayOzone::setSwapInterval(EGLSurface drawable, SwapControlData *data)
+{
+    ASSERT(data != nullptr);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h
new file mode 100644
index 0000000..c867ac1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h
@@ -0,0 +1,206 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayOzone.h: Ozone implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
+#define LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <string>
+
+#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+
+struct gbm_device;
+struct gbm_bo;
+
+namespace gl
+{
+class FramebufferState;
+}
+
+namespace rx
+{
+
+class FramebufferGL;
+
+// TODO(fjhenigman) Implement swap control.  The following struct will be used for that.
+// State-tracking data for the swap control to allow DisplayOzone to remember per
+// drawable information for swap control.
+struct SwapControlData final
+{
+    SwapControlData();
+
+    // Set by the drawable
+    int targetSwapInterval;
+
+    // DisplayOzone-side state-tracking
+    int maxSwapInterval;
+    int currentSwapInterval;
+};
+
+class DisplayOzone final : public DisplayEGL
+{
+  public:
+    struct NativeWindow
+    {
+        int32_t x;
+        int32_t y;
+        int32_t width;
+        int32_t height;
+        int32_t borderWidth;
+        int32_t borderHeight;
+        int32_t visible;
+        int32_t depth;
+    };
+
+    class Buffer final : angle::NonCopyable
+    {
+      public:
+        Buffer(DisplayOzone *display,
+               uint32_t useFlags,
+               uint32_t gbmFormat,
+               uint32_t drmFormat,
+               uint32_t drmFormatFB,
+               int depthBits,
+               int stencilBits);
+
+        ~Buffer();
+        bool initialize(const NativeWindow *window);
+        bool initialize(int32_t width, int32_t height);
+        void reset();
+        bool resize(int32_t width, int32_t height);
+        FramebufferGL *framebufferGL(const gl::FramebufferState &state);
+        void present();
+        uint32_t getDRMFB();
+        void bindTexImage();
+        GLuint getTexture();
+        int32_t getWidth() const { return mWidth; }
+        int32_t getHeight() const { return mHeight; }
+        GLuint getGLFB() const { return mGLFB; }
+        const NativeWindow *getNative() const { return mNative; }
+
+      private:
+        DisplayOzone *mDisplay;
+        const NativeWindow *mNative;
+        int mWidth;
+        int mHeight;
+        const int mDepthBits;
+        const int mStencilBits;
+        const uint32_t mUseFlags;
+        const uint32_t mGBMFormat;
+        const uint32_t mDRMFormat;
+        const uint32_t mDRMFormatFB;
+        gbm_bo *mBO;
+        int mDMABuf;
+        bool mHasDRMFB;
+        uint32_t mDRMFB;
+        EGLImageKHR mImage;
+        GLuint mColorBuffer;
+        GLuint mDSBuffer;
+        GLuint mGLFB;
+        GLuint mTexture;
+    };
+
+    DisplayOzone(const egl::DisplayState &state);
+    ~DisplayOzone() override;
+
+    egl::Error initialize(egl::Display *display) override;
+    void terminate() override;
+
+    SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+                                     EGLNativeWindowType window,
+                                     const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+                                      const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                               EGLenum buftype,
+                                               EGLClientBuffer clientBuffer,
+                                               const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+                                     NativePixmapType nativePixmap,
+                                     const egl::AttributeMap &attribs) override;
+
+    egl::ConfigSet generateConfigs() override;
+
+    bool testDeviceLost() override;
+    egl::Error restoreLostDevice() override;
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+    egl::Error getDevice(DeviceImpl **device) override;
+
+    egl::Error waitClient() const override;
+    egl::Error waitNative(EGLint engine,
+                          egl::Surface *drawSurface,
+                          egl::Surface *readSurface) const override;
+
+    // TODO(fjhenigman) Implement this.
+    // Swap interval can be set globally or per drawable.
+    // This function will make sure the drawable's swap interval is the
+    // one required so that the subsequent swapBuffers acts as expected.
+    void setSwapInterval(EGLSurface drawable, SwapControlData *data);
+
+  private:
+    GLuint makeShader(GLuint type, const char *src);
+    void drawBuffer(Buffer *buffer);
+    void drawWithBlit(Buffer *buffer);
+    void drawWithTexture(Buffer *buffer);
+    void flushGL();
+    bool hasUsableScreen(int fd);
+    void presentScreen();
+    static void pageFlipHandler(int fd,
+                                unsigned int sequence,
+                                unsigned int tv_sec,
+                                unsigned int tv_usec,
+                                void *data);
+    void pageFlipHandler(unsigned int sequence, uint64_t tv);
+
+    // TODO(fjhenigman) Implement swap control.  The following stuff will be used for that.
+    enum class SwapControl
+    {
+        ABSENT,
+        EXT,
+        MESA,
+        SGI,
+    };
+    SwapControl mSwapControl;
+    int mMinSwapInterval;
+    int mMaxSwapInterval;
+    int mCurrentSwapInterval;
+
+    gbm_device *mGBM;
+    drmModeConnectorPtr mConnector;
+    drmModeModeInfoPtr mMode;
+    drmModeCrtcPtr mCRTC;
+    bool mSetCRTC;
+
+    int32_t mWidth;
+    int32_t mHeight;
+
+    // Three scanout buffers cycle through four states.  The state of a buffer
+    // is indicated by which of these pointers points to it.
+    // TODO(fjhenigman) It might be simpler/clearer to use a ring buffer.
+    Buffer *mScanning;
+    Buffer *mPending;
+    Buffer *mDrawing;
+    Buffer *mUnused;
+
+    GLuint mProgram;
+    GLuint mVertexShader;
+    GLuint mFragmentShader;
+    GLuint mVertexBuffer;
+    GLuint mIndexBuffer;
+    GLint mCenterUniform;
+    GLint mWindowSizeUniform;
+    GLint mBorderSizeUniform;
+    GLint mDepthUniform;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp
new file mode 100644
index 0000000..f1b056c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SurfaceOzone.cpp: Ozone implementation of egl::SurfaceGL
+
+#include "libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h"
+
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+
+namespace rx
+{
+
+SurfaceOzone::SurfaceOzone(const egl::SurfaceState &state,
+                           RendererGL *renderer,
+                           DisplayOzone::Buffer *buffer)
+    : SurfaceGL(state, renderer), mBuffer(buffer)
+{
+}
+
+SurfaceOzone::~SurfaceOzone()
+{
+    delete mBuffer;
+}
+
+egl::Error SurfaceOzone::initialize(const DisplayImpl *displayImpl)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+FramebufferImpl *SurfaceOzone::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+    return mBuffer->framebufferGL(state);
+}
+
+egl::Error SurfaceOzone::makeCurrent()
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::swap(const DisplayImpl *displayImpl)
+{
+    mBuffer->present();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    mBuffer->bindTexImage();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::releaseTexImage(EGLint buffer)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+void SurfaceOzone::setSwapInterval(EGLint interval)
+{
+    mSwapControl.targetSwapInterval = interval;
+}
+
+EGLint SurfaceOzone::getWidth() const
+{
+    return mBuffer->getWidth();
+}
+
+EGLint SurfaceOzone::getHeight() const
+{
+    return mBuffer->getHeight();
+}
+
+EGLint SurfaceOzone::isPostSubBufferSupported() const
+{
+    UNIMPLEMENTED();
+    return EGL_FALSE;
+}
+
+EGLint SurfaceOzone::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h b/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h
new file mode 100644
index 0000000..918b72b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SurfaceOzone.h: Ozone implementation of egl::SurfaceGL
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_
+#define LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+
+namespace rx
+{
+
+class SurfaceOzone : public SurfaceGL
+{
+  public:
+    SurfaceOzone(const egl::SurfaceState &state,
+                 RendererGL *renderer,
+                 DisplayOzone::Buffer *buffer);
+    ~SurfaceOzone() override;
+
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    egl::Error makeCurrent() override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+  private:
+    DisplayOzone::Buffer *mBuffer;
+
+    // TODO(fjhenigman) Implement swap control.  This will be used for that.
+    SwapControlData mSwapControl;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp
new file mode 100644
index 0000000..e9035ab
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp
@@ -0,0 +1,551 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutilsgl.cpp: Queries for GL image formats and their translations to native
+// GL formats.
+
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+
+#include <limits>
+
+#include "common/string_utils.h"
+#include "libANGLE/formatutils.h"
+
+namespace rx
+{
+
+namespace nativegl
+{
+
+SupportRequirement::SupportRequirement()
+    : version(std::numeric_limits<GLuint>::max(), std::numeric_limits<GLuint>::max()),
+      versionExtensions(),
+      requiredExtensions()
+{
+}
+
+InternalFormat::InternalFormat()
+    : texture(),
+      filter(),
+      renderbuffer(),
+      framebufferAttachment()
+{
+}
+
+// supported = version || vertexExt
+static inline SupportRequirement VersionOrExts(GLuint major, GLuint minor, const std::string &versionExt)
+{
+    SupportRequirement requirement;
+    requirement.version.major = major;
+    requirement.version.minor = minor;
+    angle::SplitStringAlongWhitespace(versionExt, &requirement.versionExtensions);
+    return requirement;
+}
+
+// supported = (version || vertexExt) && requiredExt
+static inline SupportRequirement VersionOrExtsAndExts(GLuint major,
+                                                      GLuint minor,
+                                                      const std::string &versionExt,
+                                                      const std::string &requiredExt)
+{
+    SupportRequirement requirement;
+    requirement.version.major = major;
+    requirement.version.minor = minor;
+    angle::SplitStringAlongWhitespace(versionExt, &requirement.versionExtensions);
+    angle::SplitStringAlongWhitespace(requiredExt, &requirement.requiredExtensions);
+    return requirement;
+}
+
+// supported = version
+static inline SupportRequirement VersionOnly(GLuint major, GLuint minor)
+{
+    SupportRequirement requirement;
+    requirement.version.major = major;
+    requirement.version.minor = minor;
+    return requirement;
+}
+
+// supported = ext
+static inline SupportRequirement ExtsOnly(const std::string &ext)
+{
+    SupportRequirement requirement;
+    requirement.version.major = 0;
+    requirement.version.minor = 0;
+    angle::SplitStringAlongWhitespace(ext, &requirement.requiredExtensions);
+    return requirement;
+}
+
+// supported = true
+static inline SupportRequirement AlwaysSupported()
+{
+    SupportRequirement requirement;
+    requirement.version.major = 0;
+    requirement.version.minor = 0;
+    return requirement;
+}
+
+// supported = false
+static inline SupportRequirement NeverSupported()
+{
+    SupportRequirement requirement;
+    requirement.version.major = std::numeric_limits<GLuint>::max();
+    requirement.version.minor = std::numeric_limits<GLuint>::max();
+    return requirement;
+}
+
+struct InternalFormatInfo
+{
+    InternalFormat glesInfo;
+    InternalFormat glInfo;
+};
+
+typedef std::pair<GLenum, InternalFormatInfo> InternalFormatInfoPair;
+typedef std::map<GLenum, InternalFormatInfo> InternalFormatInfoMap;
+
+// A helper function to insert data into the format map with fewer characters.
+static inline void InsertFormatMapping(InternalFormatInfoMap *map, GLenum internalFormat,
+                                       const SupportRequirement &desktopTexture, const SupportRequirement &desktopFilter, const SupportRequirement &desktopRender,
+                                       const SupportRequirement &esTexture, const SupportRequirement &esFilter, const SupportRequirement &esRender)
+{
+    InternalFormatInfo formatInfo;
+    formatInfo.glInfo.texture = desktopTexture;
+    formatInfo.glInfo.filter = desktopFilter;
+    formatInfo.glInfo.renderbuffer = desktopRender;
+    formatInfo.glInfo.framebufferAttachment = desktopRender;
+    formatInfo.glesInfo.texture = esTexture;
+    formatInfo.glesInfo.filter = esTexture;
+    formatInfo.glesInfo.renderbuffer = esFilter;
+    formatInfo.glesInfo.framebufferAttachment = esRender;
+    map->insert(std::make_pair(internalFormat, formatInfo));
+}
+
+static InternalFormatInfoMap BuildInternalFormatInfoMap()
+{
+    InternalFormatInfoMap map;
+
+    // clang-format off
+    //                       | Format              | OpenGL texture support                          | Filter           | OpenGL render support                        | OpenGL ES texture support                 | Filter           | OpenGL ES render support                 |
+    InsertFormatMapping(&map, GL_R8,                VersionOrExts(3, 0, "GL_ARB_texture_rg"),         AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOrExts(3, 0, "GL_EXT_texture_rg"),   AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_texture_rg")  );
+    InsertFormatMapping(&map, GL_R8_SNORM,          VersionOnly(3, 1),                                AlwaysSupported(), NeverSupported(),                              VersionOnly(3, 0),                          AlwaysSupported(), NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RG8,               VersionOrExts(3, 0, "GL_ARB_texture_rg"),         AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOrExts(3, 0, "GL_EXT_texture_rg"),   AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg")  );
+    InsertFormatMapping(&map, GL_RG8_SNORM,         VersionOnly(3, 1),                                AlwaysSupported(), NeverSupported(),                              VersionOnly(3, 0),                          AlwaysSupported(), NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGB8,              AlwaysSupported(),                                AlwaysSupported(), AlwaysSupported(),                             VersionOrExts(3, 0, "GL_OES_rgb8_rgba8"),   AlwaysSupported(), AlwaysSupported()                         );
+    InsertFormatMapping(&map, GL_RGB8_SNORM,        VersionOnly(3, 1),                                AlwaysSupported(), NeverSupported(),                              VersionOnly(3, 0),                          AlwaysSupported(), NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGB565,            AlwaysSupported(),                                AlwaysSupported(), AlwaysSupported(),                             AlwaysSupported(),                          AlwaysSupported(), AlwaysSupported()                         );
+    InsertFormatMapping(&map, GL_RGBA4,             AlwaysSupported(),                                AlwaysSupported(), AlwaysSupported(),                             AlwaysSupported(),                          AlwaysSupported(), AlwaysSupported()                         );
+    InsertFormatMapping(&map, GL_RGB5_A1,           AlwaysSupported(),                                AlwaysSupported(), AlwaysSupported(),                             AlwaysSupported(),                          AlwaysSupported(), AlwaysSupported()                         );
+    InsertFormatMapping(&map, GL_RGBA8,             AlwaysSupported(),                                AlwaysSupported(), AlwaysSupported(),                             VersionOrExts(3, 0, "GL_OES_rgb8_rgba8"),   AlwaysSupported(), VersionOrExts(3, 0, "GL_OES_rgb8_rgba8")  );
+    InsertFormatMapping(&map, GL_RGBA8_SNORM,       VersionOnly(3, 1),                                AlwaysSupported(), NeverSupported(),                              VersionOnly(3, 0),                          AlwaysSupported(), NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGB10_A2,          AlwaysSupported(),                                AlwaysSupported(), AlwaysSupported(),                             VersionOnly(3, 0),                          AlwaysSupported(), VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RGB10_A2UI,        VersionOrExts(3, 3, "GL_ARB_texture_rgb10_a2ui"), NeverSupported(),  AlwaysSupported(),                             VersionOnly(3, 0),                          NeverSupported(),  AlwaysSupported()                         );
+    InsertFormatMapping(&map, GL_SRGB8,             VersionOrExts(2, 1, "GL_EXT_texture_sRGB"),       AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"),    VersionOnly(3, 0),                          AlwaysSupported(), NeverSupported()                          );
+    InsertFormatMapping(&map, GL_SRGB8_ALPHA8,      VersionOrExts(2, 1, "GL_EXT_texture_sRGB"),       AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"),    VersionOnly(3, 0),                          AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_sRGB")        );
+    InsertFormatMapping(&map, GL_R8I,               VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_R8UI,              VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_R16I,              VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_R16UI,             VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_R32I,              VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_R32UI,             VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RG8I,              VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RG8UI,             VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RG16I,             VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RG16UI,            VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RG32I,             VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RG32UI,            VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RGB8I,             VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  NeverSupported(),                              VersionOnly(3, 0),                          NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGB8UI,            VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  NeverSupported(),                              VersionOnly(3, 0),                          NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGB16I,            VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  NeverSupported(),                              VersionOnly(3, 0),                          NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGB16UI,           VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  NeverSupported(),                              VersionOnly(3, 0),                          NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGB32I,            VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  NeverSupported(),                              VersionOnly(3, 0),                          NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGB32UI,           VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  NeverSupported(),                              VersionOnly(3, 0),                          NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGBA8I,            VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RGBA8UI,           VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RGBA16I,           VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RGBA16UI,          VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RGBA32I,           VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RGBA32UI,          VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+
+    // Unsized formats
+    InsertFormatMapping(&map, GL_ALPHA,             NeverSupported(),                                 NeverSupported(),  NeverSupported(),                              NeverSupported(),                           NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_LUMINANCE,         NeverSupported(),                                 NeverSupported(),  NeverSupported(),                              NeverSupported(),                           NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_LUMINANCE_ALPHA,   NeverSupported(),                                 NeverSupported(),  NeverSupported(),                              NeverSupported(),                           NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RED,               VersionOrExts(3, 0, "GL_ARB_texture_rg"),         AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOrExts(3, 0, "GL_EXT_texture_rg"),   AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg")  );
+    InsertFormatMapping(&map, GL_RG,                VersionOrExts(3, 0, "GL_ARB_texture_rg"),         AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOrExts(3, 0, "GL_EXT_texture_rg"),   AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg")  );
+    InsertFormatMapping(&map, GL_RGB,               AlwaysSupported(),                                AlwaysSupported(), AlwaysSupported(),                             AlwaysSupported(),                          AlwaysSupported(), AlwaysSupported()                         );
+    InsertFormatMapping(&map, GL_RGBA,              AlwaysSupported(),                                AlwaysSupported(), AlwaysSupported(),                             AlwaysSupported(),                          AlwaysSupported(), AlwaysSupported()                         );
+    InsertFormatMapping(&map, GL_RED_INTEGER,       VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RG_INTEGER,        VersionOrExts(3, 0, "GL_ARB_texture_rg"),         NeverSupported(),  VersionOrExts(3, 0, "GL_ARB_texture_rg"),      VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_RGB_INTEGER,       VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  NeverSupported(),                              VersionOnly(3, 0),                          NeverSupported(),  NeverSupported()                          );
+    InsertFormatMapping(&map, GL_RGBA_INTEGER,      VersionOrExts(3, 0, "GL_EXT_texture_integer"),    NeverSupported(),  VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0),                          NeverSupported(),  VersionOnly(3, 0)                         );
+    InsertFormatMapping(&map, GL_SRGB,              VersionOrExts(2, 1, "GL_EXT_texture_sRGB"),       AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"),    ExtsOnly("GL_EXT_sRGB"),                    AlwaysSupported(), NeverSupported()                          );
+    InsertFormatMapping(&map, GL_SRGB_ALPHA,        VersionOrExts(2, 1, "GL_EXT_texture_sRGB"),       AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"),    ExtsOnly("GL_EXT_sRGB"),                    AlwaysSupported(), NeverSupported()                          );
+
+    // From GL_EXT_texture_format_BGRA8888
+    InsertFormatMapping(&map, GL_BGRA8_EXT,         VersionOrExts(1, 2, "GL_EXT_bgra"),               AlwaysSupported(), VersionOrExts(1, 2, "GL_EXT_bgra"),            ExtsOnly("GL_EXT_texture_format_BGRA8888"), AlwaysSupported(), NeverSupported()                          );
+    InsertFormatMapping(&map, GL_BGRA_EXT,          VersionOrExts(1, 2, "GL_EXT_bgra"),               AlwaysSupported(), VersionOrExts(1, 2, "GL_EXT_bgra"),            ExtsOnly("GL_EXT_texture_format_BGRA8888"), AlwaysSupported(), NeverSupported()                          );
+
+    // Floating point formats
+    //                       | Format              | OpenGL texture support                                       | Filter           | OpenGL render support                                                                  | OpenGL ES texture support                                         | Filter                                                 | OpenGL ES render support                                                        |
+    InsertFormatMapping(&map, GL_R11F_G11F_B10F,    VersionOrExts(3, 0, "GL_EXT_packed_float"),                    AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_packed_float GL_ARB_color_buffer_float"),                    VersionOnly(3, 0),                                                  AlwaysSupported(),                                       ExtsOnly("GL_EXT_color_buffer_float")                                            );
+    InsertFormatMapping(&map, GL_RGB9_E5,           VersionOrExts(3, 0, "GL_EXT_texture_shared_exponent"),         AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_texture_shared_exponent GL_ARB_color_buffer_float"),         VersionOnly(3, 0),                                                  AlwaysSupported(),                                       NeverSupported()                                                                 );
+    InsertFormatMapping(&map, GL_R16F,              VersionOrExts(3, 0, "GL_ARB_texture_rg ARB_texture_float"),    AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), VersionOrExtsAndExts(3, 0, "GL_EXT_texture_rg", "GL_EXT_color_buffer_half_float"));
+    InsertFormatMapping(&map, GL_RG16F,             VersionOrExts(3, 0, "GL_ARB_texture_rg ARB_texture_float"),    AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), VersionOrExtsAndExts(3, 0, "GL_EXT_texture_rg", "GL_EXT_color_buffer_half_float"));
+    InsertFormatMapping(&map, GL_RGB16F,            VersionOrExts(3, 0, "GL_ARB_texture_float"),                   AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"),                   VersionOrExts(3, 0, "GL_OES_texture_half_float"),                   VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), ExtsOnly("GL_EXT_color_buffer_half_float")                                       );
+    InsertFormatMapping(&map, GL_RGBA16F,           VersionOrExts(3, 0, "GL_ARB_texture_float"),                   AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"),                   VersionOrExts(3, 0, "GL_OES_texture_half_float"),                   VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), ExtsOnly("GL_EXT_color_buffer_half_float")                                       );
+    InsertFormatMapping(&map, GL_R32F,              VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float GL_EXT_texture_rg"),      ExtsOnly("GL_OES_texture_float_linear"),                 ExtsOnly("GL_EXT_color_buffer_float")                                            );
+    InsertFormatMapping(&map, GL_RG32F,             VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float GL_EXT_texture_rg"),      ExtsOnly("GL_OES_texture_float_linear"),                 ExtsOnly("GL_EXT_color_buffer_float")                                            );
+    InsertFormatMapping(&map, GL_RGB32F,            VersionOrExts(3, 0, "GL_ARB_texture_float"),                   AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"),                   VersionOrExts(3, 0, "GL_OES_texture_float"),                        ExtsOnly("GL_OES_texture_float_linear"),                 NeverSupported()                                                                 );
+    InsertFormatMapping(&map, GL_RGBA32F,           VersionOrExts(3, 0, "GL_ARB_texture_float"),                   AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"),                   VersionOrExts(3, 0, "GL_OES_texture_float"),                        ExtsOnly("GL_OES_texture_float_linear"),                 ExtsOnly("GL_EXT_color_buffer_float")                                            );
+
+    // Depth stencil formats
+    //                       | Format                  | OpenGL texture support                            | Filter                                     | OpenGL render support                             | OpenGL ES texture support                  | Filter                                     | OpenGL ES render support                                              |
+    InsertFormatMapping(&map, GL_DEPTH_COMPONENT16,     VersionOnly(1, 5),                                  VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5),                                  VersionOnly(2, 0),                           VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0)                                                      );
+    InsertFormatMapping(&map, GL_DEPTH_COMPONENT24,     VersionOnly(1, 5),                                  VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5),                                  VersionOnly(2, 0),                           VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0)                                                      );
+    InsertFormatMapping(&map, GL_DEPTH_COMPONENT32_OES, VersionOnly(1, 5),                                  VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5),                                  ExtsOnly("GL_OES_depth_texture"),            AlwaysSupported(),                           ExtsOnly("GL_OES_depth32")                                             );
+    InsertFormatMapping(&map, GL_DEPTH_COMPONENT32F,    VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"),   AlwaysSupported(),                           VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"),   VersionOnly(3, 0),                           VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(3, 0)                                                      );
+    InsertFormatMapping(&map, GL_STENCIL_INDEX8,        VersionOrExts(3, 0, "GL_EXT_packed_depth_stencil"), NeverSupported(),                            VersionOrExts(3, 0, "GL_EXT_packed_depth_stencil"), VersionOnly(2, 0),                           NeverSupported(),                            VersionOnly(2, 0)                                                      );
+    InsertFormatMapping(&map, GL_DEPTH24_STENCIL8,      VersionOrExts(3, 0, "GL_ARB_framebuffer_object"),   VersionOrExts(3, 0, "GL_ARB_depth_texture"), VersionOrExts(3, 0, "GL_ARB_framebuffer_object"),   VersionOrExts(3, 0, "GL_OES_depth_texture"), AlwaysSupported(),                           VersionOrExts(3, 0, "GL_OES_depth_texture GL_OES_packed_depth_stencil"));
+    InsertFormatMapping(&map, GL_DEPTH32F_STENCIL8,     VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"),   AlwaysSupported(),                           VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"),   VersionOnly(3, 0),                           AlwaysSupported(),                           VersionOnly(3, 0)                                                      );
+    InsertFormatMapping(&map, GL_DEPTH_COMPONENT,       VersionOnly(1, 5),                                  VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5),                                  VersionOnly(2, 0),                           VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0)                                                      );
+    InsertFormatMapping(&map, GL_DEPTH_STENCIL,         VersionOnly(1, 5),                                  VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5),                                  VersionOnly(2, 0),                           VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0)                                                      );
+
+    // Luminance alpha formats
+    //                       | Format                  | OpenGL texture support                      | Filter           | Render          | OpenGL ES texture support                                | Filter                                                 | Render          |
+    InsertFormatMapping(&map, GL_ALPHA8_EXT,             AlwaysSupported(),                           AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"),                        AlwaysSupported(),                                       NeverSupported());
+    InsertFormatMapping(&map, GL_LUMINANCE8_EXT,         AlwaysSupported(),                           AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"),                        AlwaysSupported(),                                       NeverSupported());
+    InsertFormatMapping(&map, GL_LUMINANCE8_ALPHA8_EXT,  AlwaysSupported(),                           AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"),                        AlwaysSupported(),                                       NeverSupported());
+    InsertFormatMapping(&map, GL_ALPHA16F_EXT,           VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage OES_texture_half_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), NeverSupported());
+    InsertFormatMapping(&map, GL_LUMINANCE16F_EXT,       VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage OES_texture_half_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), NeverSupported());
+    InsertFormatMapping(&map, GL_LUMINANCE_ALPHA16F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage OES_texture_half_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), NeverSupported());
+    InsertFormatMapping(&map, GL_ALPHA32F_EXT,           VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage OES_texture_float"),      ExtsOnly("GL_OES_texture_float_linear"),                 NeverSupported());
+    InsertFormatMapping(&map, GL_LUMINANCE32F_EXT,       VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage OES_texture_float"),      ExtsOnly("GL_OES_texture_float_linear"),                 NeverSupported());
+    InsertFormatMapping(&map, GL_LUMINANCE_ALPHA32F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage OES_texture_float"),      ExtsOnly("GL_OES_texture_float_linear"),                 NeverSupported());
+
+    // Compressed formats, From ES 3.0.1 spec, table 3.16
+    InsertFormatMapping(&map, GL_COMPRESSED_R11_EAC,                        VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_SIGNED_R11_EAC,                 VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_RG11_EAC,                       VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_SIGNED_RG11_EAC,                VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_RGB8_ETC2,                      VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_ETC2,                     VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_RGBA8_ETC2_EAC,                 VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+
+    // From GL_EXT_texture_compression_dxt1
+    //                       | Format                            | OpenGL texture support                         | Filter           | Render          | OpenGL ES texture support                    | Filter           | Render           |
+    InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    ExtsOnly("GL_EXT_texture_compression_s3tc"),     AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_compression_dxt1"),   AlwaysSupported(), NeverSupported());
+    InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   ExtsOnly("GL_EXT_texture_compression_s3tc"),     AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_compression_dxt1"),   AlwaysSupported(), NeverSupported());
+
+    // From GL_ANGLE_texture_compression_dxt3
+    InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"),     AlwaysSupported(), NeverSupported(), ExtsOnly("GL_ANGLE_texture_compression_dxt3"), AlwaysSupported(), NeverSupported());
+
+    // From GL_ANGLE_texture_compression_dxt5
+    InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"),     AlwaysSupported(), NeverSupported(), ExtsOnly("GL_ANGLE_texture_compression_dxt5"), AlwaysSupported(), NeverSupported());
+
+    // From GL_ETC1_RGB8_OES
+    InsertFormatMapping(&map, GL_ETC1_RGB8_OES,                   VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOrExts(3, 0, "GL_ETC1_RGB8_OES"),       AlwaysSupported(), NeverSupported());
+
+    // clang-format on
+
+    return map;
+}
+
+static const InternalFormatInfoMap &GetInternalFormatMap()
+{
+    static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap();
+    return formatMap;
+}
+
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL standard)
+{
+    const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+    InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat);
+    if (iter != formatMap.end())
+    {
+        const InternalFormatInfo &info = iter->second;
+        switch (standard)
+        {
+          case STANDARD_GL_ES:      return info.glesInfo;
+          case STANDARD_GL_DESKTOP: return info.glInfo;
+          default: UNREACHABLE();   break;
+        }
+    }
+
+    static const InternalFormat defaultInternalFormat;
+    return defaultInternalFormat;
+}
+
+static GLenum GetNativeInternalFormat(const FunctionsGL *functions,
+                                      const WorkaroundsGL &workarounds,
+                                      const gl::InternalFormat &internalFormat)
+{
+    GLenum result = internalFormat.internalFormat;
+
+    if (functions->standard == STANDARD_GL_DESKTOP)
+    {
+        // Use sized internal formats whenever possible to guarantee the requested precision.
+        // On Desktop GL, passing an internal format of GL_RGBA will generate a GL_RGBA8 texture
+        // even if the provided type is GL_FLOAT.
+        result = internalFormat.sizedInternalFormat;
+
+        if (workarounds.avoid1BitAlphaTextureFormats && internalFormat.alphaBits == 1)
+        {
+            // Use an 8-bit format instead
+            result = GL_RGBA8;
+        }
+
+        if (workarounds.rgba4IsNotSupportedForColorRendering &&
+            internalFormat.sizedInternalFormat == GL_RGBA4)
+        {
+            // Use an 8-bit format instead
+            result = GL_RGBA8;
+        }
+
+        if (internalFormat.sizedInternalFormat == GL_RGB565 &&
+            !functions->isAtLeastGL(gl::Version(4, 1)) &&
+            !functions->hasGLExtension("GL_ARB_ES2_compatibility"))
+        {
+            // GL_RGB565 is required for basic ES2 functionality but was not added to desktop GL
+            // until 4.1.
+            // Work around this by using an 8-bit format instead.
+            result = GL_RGB8;
+        }
+
+        if (internalFormat.sizedInternalFormat == GL_BGRA8_EXT)
+        {
+            // GLES accepts GL_BGRA as an internal format but desktop GL only accepts it as a type.
+            // Update the internal format to GL_RGBA.
+            result = GL_RGBA8;
+        }
+
+        if ((functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+        {
+            // Work around deprecated luminance alpha formats in the OpenGL core profile by backing
+            // them with R or RG textures.
+            if (internalFormat.format == GL_LUMINANCE || internalFormat.format == GL_ALPHA)
+            {
+                result = gl::GetInternalFormatInfo(GL_RED, internalFormat.type).sizedInternalFormat;
+            }
+
+            if (internalFormat.format == GL_LUMINANCE_ALPHA)
+            {
+                result = gl::GetInternalFormatInfo(GL_RG, internalFormat.type).sizedInternalFormat;
+            }
+        }
+    }
+    else if (functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        if (internalFormat.componentType == GL_FLOAT && !internalFormat.isLUMA())
+        {
+            // Use sized internal formats for floating point textures.  Extensions such as
+            // EXT_color_buffer_float require the sized formats to be renderable.
+            result = internalFormat.sizedInternalFormat;
+        }
+    }
+
+    return result;
+}
+
+static GLenum GetNativeFormat(const FunctionsGL *functions,
+                              const WorkaroundsGL &workarounds,
+                              GLenum format)
+{
+    GLenum result = format;
+
+    if (functions->standard == STANDARD_GL_DESKTOP)
+    {
+        // The ES SRGB extensions require that the provided format is GL_SRGB or SRGB_ALPHA but
+        // the desktop GL extensions only accept GL_RGB or GL_RGBA.  Convert them.
+        if (format == GL_SRGB)
+        {
+            result = GL_RGB;
+        }
+
+        if (format == GL_SRGB_ALPHA)
+        {
+            result = GL_RGBA;
+        }
+
+        if ((functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+        {
+            // Work around deprecated luminance alpha formats in the OpenGL core profile by backing
+            // them with R or RG textures.
+            if (format == GL_LUMINANCE || format == GL_ALPHA)
+            {
+                result = GL_RED;
+            }
+
+            if (format == GL_LUMINANCE_ALPHA)
+            {
+                result = GL_RG;
+            }
+        }
+    }
+
+    return result;
+}
+
+static GLenum GetNativeCompressedFormat(const FunctionsGL *functions,
+                                        const WorkaroundsGL &workarounds,
+                                        GLenum format)
+{
+    GLenum result = format;
+
+    if (functions->standard == STANDARD_GL_DESKTOP)
+    {
+        if (format == GL_ETC1_RGB8_OES)
+        {
+            // GL_ETC1_RGB8_OES is not available in any desktop GL extension but the compression
+            // format is forwards compatible so just use the ETC2 format.
+            result = GL_COMPRESSED_RGB8_ETC2;
+        }
+    }
+
+    if (functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        if (format == GL_ETC1_RGB8_OES)
+        {
+            // Pass GL_COMPRESSED_RGB8_ETC2 as the target format in ES3 and higher because it
+            // becomes a core format.
+            result = GL_COMPRESSED_RGB8_ETC2;
+        }
+    }
+
+    return result;
+}
+
+static GLenum GetNativeType(const FunctionsGL *functions,
+                            const WorkaroundsGL &workarounds,
+                            GLenum type)
+{
+    GLenum result = type;
+
+    if (functions->standard == STANDARD_GL_DESKTOP)
+    {
+        if (type == GL_HALF_FLOAT_OES)
+        {
+            // The enums differ for the OES half float extensions and desktop GL spec. Update it.
+            result = GL_HALF_FLOAT;
+        }
+    }
+
+    return result;
+}
+
+static GLenum GetNativeReadType(const FunctionsGL *functions,
+                                const WorkaroundsGL &workarounds,
+                                GLenum type)
+{
+    GLenum result = type;
+
+    if (functions->standard == STANDARD_GL_DESKTOP)
+    {
+        if (type == GL_HALF_FLOAT_OES)
+        {
+            // The enums differ for the OES half float extensions and desktop GL spec. Update it.
+            result = GL_HALF_FLOAT;
+        }
+    }
+
+    return result;
+}
+
+static GLenum GetNativeReadFormat(const FunctionsGL *functions,
+                                  const WorkaroundsGL &workarounds,
+                                  GLenum format)
+{
+    GLenum result = format;
+    return result;
+}
+
+TexImageFormat GetTexImageFormat(const FunctionsGL *functions,
+                                 const WorkaroundsGL &workarounds,
+                                 GLenum internalFormat,
+                                 GLenum format,
+                                 GLenum type)
+{
+    TexImageFormat result;
+    result.internalFormat = GetNativeInternalFormat(
+        functions, workarounds, gl::GetInternalFormatInfo(internalFormat, type));
+    result.format = GetNativeFormat(functions, workarounds, format);
+    result.type   = GetNativeType(functions, workarounds, type);
+    return result;
+}
+
+TexSubImageFormat GetTexSubImageFormat(const FunctionsGL *functions,
+                                       const WorkaroundsGL &workarounds,
+                                       GLenum format,
+                                       GLenum type)
+{
+    TexSubImageFormat result;
+    result.format = GetNativeFormat(functions, workarounds, format);
+    result.type   = GetNativeType(functions, workarounds, type);
+    return result;
+}
+
+CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *functions,
+                                                     const WorkaroundsGL &workarounds,
+                                                     GLenum internalFormat)
+{
+    CompressedTexImageFormat result;
+    result.internalFormat = GetNativeCompressedFormat(functions, workarounds, internalFormat);
+    return result;
+}
+
+CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *functions,
+                                                           const WorkaroundsGL &workarounds,
+                                                           GLenum format)
+{
+    CompressedTexSubImageFormat result;
+    result.format = GetNativeCompressedFormat(functions, workarounds, format);
+    return result;
+}
+
+CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions,
+                                                   const WorkaroundsGL &workarounds,
+                                                   GLenum internalFormat,
+                                                   GLenum framebufferType)
+{
+    CopyTexImageImageFormat result;
+    result.internalFormat = GetNativeInternalFormat(
+        functions, workarounds, gl::GetInternalFormatInfo(internalFormat, framebufferType));
+    return result;
+}
+
+TexStorageFormat GetTexStorageFormat(const FunctionsGL *functions,
+                                     const WorkaroundsGL &workarounds,
+                                     GLenum internalFormat)
+{
+    TexStorageFormat result;
+    result.internalFormat = GetNativeInternalFormat(functions, workarounds,
+                                                    gl::GetSizedInternalFormatInfo(internalFormat));
+    return result;
+}
+
+RenderbufferFormat GetRenderbufferFormat(const FunctionsGL *functions,
+                                         const WorkaroundsGL &workarounds,
+                                         GLenum internalFormat)
+{
+    RenderbufferFormat result;
+    result.internalFormat = GetNativeInternalFormat(functions, workarounds,
+                                                    gl::GetSizedInternalFormatInfo(internalFormat));
+    return result;
+}
+ReadPixelsFormat GetReadPixelsFormat(const FunctionsGL *functions,
+                                     const WorkaroundsGL &workarounds,
+                                     GLenum format,
+                                     GLenum type)
+{
+    ReadPixelsFormat result;
+    result.format = GetNativeReadFormat(functions, workarounds, format);
+    result.type   = GetNativeReadType(functions, workarounds, type);
+    return result;
+}
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.h b/src/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.h
new file mode 100644
index 0000000..616f37a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.h
@@ -0,0 +1,129 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutilsgl.h: Queries for GL image formats and their translations to native
+// GL formats.
+
+#ifndef LIBANGLE_RENDERER_GL_FORMATUTILSGL_H_
+#define LIBANGLE_RENDERER_GL_FORMATUTILSGL_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "angle_gl.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+
+namespace rx
+{
+
+namespace nativegl
+{
+
+struct SupportRequirement
+{
+    SupportRequirement();
+
+    // Version that this format became supported without extensions
+    gl::Version version;
+
+    // Extensions that are required if the minimum version is not met
+    std::vector<std::string> versionExtensions;
+
+    // Extensions that are always required to support this format
+    std::vector<std::string> requiredExtensions;
+};
+
+struct InternalFormat
+{
+    InternalFormat();
+
+    SupportRequirement texture;
+    SupportRequirement filter;
+    SupportRequirement renderbuffer;
+    SupportRequirement framebufferAttachment;
+};
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL standard);
+
+struct TexImageFormat
+{
+    GLenum internalFormat;
+    GLenum format;
+    GLenum type;
+};
+TexImageFormat GetTexImageFormat(const FunctionsGL *functions,
+                                 const WorkaroundsGL &workarounds,
+                                 GLenum internalFormat,
+                                 GLenum format,
+                                 GLenum type);
+
+struct TexSubImageFormat
+{
+    GLenum format;
+    GLenum type;
+};
+TexSubImageFormat GetTexSubImageFormat(const FunctionsGL *functions,
+                                       const WorkaroundsGL &workarounds,
+                                       GLenum format,
+                                       GLenum type);
+
+struct CompressedTexImageFormat
+{
+    GLenum internalFormat;
+};
+CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *functions,
+                                                     const WorkaroundsGL &workarounds,
+                                                     GLenum internalFormat);
+
+struct CompressedTexSubImageFormat
+{
+    GLenum format;
+};
+CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *functions,
+                                                           const WorkaroundsGL &workarounds,
+                                                           GLenum format);
+
+struct CopyTexImageImageFormat
+{
+    GLenum internalFormat;
+};
+CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions,
+                                                   const WorkaroundsGL &workarounds,
+                                                   GLenum internalFormat,
+                                                   GLenum framebufferType);
+
+struct TexStorageFormat
+{
+    GLenum internalFormat;
+};
+TexStorageFormat GetTexStorageFormat(const FunctionsGL *functions,
+                                     const WorkaroundsGL &workarounds,
+                                     GLenum internalFormat);
+
+struct RenderbufferFormat
+{
+    GLenum internalFormat;
+};
+RenderbufferFormat GetRenderbufferFormat(const FunctionsGL *functions,
+                                         const WorkaroundsGL &workarounds,
+                                         GLenum internalFormat);
+
+struct ReadPixelsFormat
+{
+    GLenum format;
+    GLenum type;
+};
+ReadPixelsFormat GetReadPixelsFormat(const FunctionsGL *functions,
+                                     const WorkaroundsGL &workarounds,
+                                     GLenum format,
+                                     GLenum type);
+}
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FORMATUTILSGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/functionsgl_enums.h b/src/third_party/angle/src/libANGLE/renderer/gl/functionsgl_enums.h
new file mode 100644
index 0000000..918a7a1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/functionsgl_enums.h
@@ -0,0 +1,1375 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// functionsgl_enums.h: OpenGL enums for versions 1.0 through 4.5.
+
+#ifndef LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_
+#define LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_
+
+// 1.0
+#define GL_ALPHA 0x1906
+#define GL_ALWAYS 0x0207
+#define GL_AND 0x1501
+#define GL_AND_INVERTED 0x1504
+#define GL_AND_REVERSE 0x1502
+#define GL_BACK 0x0405
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLUE 0x1905
+#define GL_BYTE 0x1400
+#define GL_CCW 0x0901
+#define GL_CLEAR 0x1500
+#define GL_COLOR 0x1800
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_COPY 0x1503
+#define GL_COPY_INVERTED 0x150C
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_CW 0x0900
+#define GL_DECR 0x1E03
+#define GL_DEPTH 0x1801
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DITHER 0x0BD0
+#define GL_DONT_CARE 0x1100
+#define GL_DOUBLE 0x140A
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_DST_ALPHA 0x0304
+#define GL_DST_COLOR 0x0306
+#define GL_EQUAL 0x0202
+#define GL_EQUIV 0x1509
+#define GL_EXTENSIONS 0x1F03
+#define GL_FALSE 0
+#define GL_FASTEST 0x1101
+#define GL_FILL 0x1B02
+#define GL_FLOAT 0x1406
+#define GL_FRONT 0x0404
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_FRONT_FACE 0x0B46
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_GEQUAL 0x0206
+#define GL_GREATER 0x0204
+#define GL_GREEN 0x1904
+#define GL_INCR 0x1E02
+#define GL_INT 0x1404
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_OPERATION 0x0502
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVERT 0x150A
+#define GL_KEEP 0x1E00
+#define GL_LEFT 0x0406
+#define GL_LEQUAL 0x0203
+#define GL_LESS 0x0201
+#define GL_LINE 0x1B01
+#define GL_LINEAR 0x2601
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_NAND 0x150E
+#define GL_NEAREST 0x2600
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEVER 0x0200
+#define GL_NICEST 0x1102
+#define GL_NONE 0
+#define GL_NOOP 0x1505
+#define GL_NOR 0x1508
+#define GL_NOTEQUAL 0x0205
+#define GL_NO_ERROR 0
+#define GL_ONE 1
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_OR 0x1507
+#define GL_OR_INVERTED 0x150D
+#define GL_OR_REVERSE 0x150B
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_POINT 0x1B00
+#define GL_POINTS 0x0000
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_QUADS 0x0007
+#define GL_R3_G3_B2 0x2A10
+#define GL_READ_BUFFER 0x0C02
+#define GL_RED 0x1903
+#define GL_RENDERER 0x1F01
+#define GL_REPEAT 0x2901
+#define GL_REPLACE 0x1E01
+#define GL_RGB 0x1907
+#define GL_RGB10 0x8052
+#define GL_RGB10_A2 0x8059
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB5_A1 0x8057
+#define GL_RGB8 0x8051
+#define GL_RGBA 0x1908
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGBA8 0x8058
+#define GL_RIGHT 0x0407
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_SET 0x150F
+#define GL_SHORT 0x1402
+#define GL_SRC_ALPHA 0x0302
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_SRC_COLOR 0x0300
+#define GL_STENCIL 0x1802
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_INDEX 0x1901
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STEREO 0x0C33
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRUE 1
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_VENDOR 0x1F00
+#define GL_VERSION 0x1F02
+#define GL_VIEWPORT 0x0BA2
+#define GL_XOR 0x1506
+#define GL_ZERO 0
+
+// 1.2
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+
+// 1.2 Extensions
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+
+// 1.3
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_MULTISAMPLE 0x809D
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+
+// 1.5
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_DECR_WRAP 0x8508
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_INCR_WRAP 0x8507
+#define GL_MAX 0x8008
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_MIN 0x8007
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_LOD_BIAS 0x8501
+
+// 1.5
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_CURRENT_QUERY 0x8865
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_READ_ONLY 0x88B8
+#define GL_READ_WRITE 0x88BA
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SRC1_ALPHA 0x8589
+#define GL_STATIC_COPY 0x88E6
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STREAM_COPY 0x88E2
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_WRITE_ONLY 0x88B9
+
+// 2.0
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_DELETE_STATUS 0x8B80
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_LINK_STATUS 0x8B82
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_POINT_SPRITE 0x8861
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_SHADER 0x8B31
+
+// 2.1
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_SRGB_ALPHA 0x8C42
+
+// 3.0
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_RG 0x8226
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FIXED_ONLY 0x891D
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_HALF_FLOAT 0x140B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_MINOR_VERSION 0x821C
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_WAIT 0x8E13
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_R16 0x822A
+#define GL_R16F 0x822D
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32F 0x822E
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_R8 0x8229
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RED_INTEGER 0x8D94
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RG 0x8227
+#define GL_RG16 0x822C
+#define GL_RG16F 0x822F
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32F 0x8230
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_RG8 0x822B
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RGB16F 0x881B
+#define GL_RGB16I 0x8D89
+#define GL_RGB16UI 0x8D77
+#define GL_RGB32F 0x8815
+#define GL_RGB32I 0x8D83
+#define GL_RGB32UI 0x8D71
+#define GL_RGB8I 0x8D8F
+#define GL_RGB8UI 0x8D7D
+#define GL_RGB9_E5 0x8C3D
+#define GL_RGBA16F 0x881A
+#define GL_RGBA16I 0x8D88
+#define GL_RGBA16UI 0x8D76
+#define GL_RGBA32F 0x8814
+#define GL_RGBA32I 0x8D82
+#define GL_RGBA32UI 0x8D70
+#define GL_RGBA8I 0x8D8E
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RG_INTEGER 0x8228
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+
+// 3.1
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_R16_SNORM 0x8F98
+#define GL_R8_SNORM 0x8F94
+#define GL_RG16_SNORM 0x8F99
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+
+// 3.2
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_OBJECT_TYPE 0x9112
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SIGNALED 0x9119
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_SYNC_STATUS 0x9114
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_UNSIGNALED 0x9118
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_WAIT_FAILED 0x911D
+
+// 3.3
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_RGB10_A2UI 0x906F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_SRC1_COLOR 0x88F9
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TIMESTAMP 0x8E28
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+
+// 4.0
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#define GL_FRACTIONAL_EVEN 0x8E7C
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_ISOLINES 0x8E7A
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_PATCHES 0x000E
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+
+// 4.1
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_FIXED 0x140C
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_HIGH_INT 0x8DF5
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_LOW_INT 0x8DF3
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_RGB565 0x8D62
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_UNDEFINED_VERTEX 0x8260
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+
+// 4.2
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_IMAGE_SAMPLES 0x906D
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+
+// 4.3
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_AUTO_GENERATE_MIPMAP 0x8295
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_BUFFER 0x82E0
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_CAVEAT_SUPPORT 0x82B8
+#define GL_CLEAR_BUFFER 0x82B4
+#define GL_COLOR_COMPONENTS 0x8283
+#define GL_COLOR_ENCODING 0x8296
+#define GL_COLOR_RENDERABLE 0x8286
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#define GL_COMPUTE_SUBROUTINE 0x92ED
+#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define GL_COMPUTE_TEXTURE 0x82A0
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEPTH_COMPONENTS 0x8284
+#define GL_DEPTH_RENDERABLE 0x8287
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_FILTER 0x829A
+#define GL_FRAGMENT_SUBROUTINE 0x92EC
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define GL_FRAGMENT_TEXTURE 0x829F
+#define GL_FRAMEBUFFER_BLEND 0x828B
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FULL_SUPPORT 0x82B7
+#define GL_GEOMETRY_SUBROUTINE 0x92EB
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define GL_GEOMETRY_TEXTURE 0x829E
+#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define GL_IMAGE_CLASS_11_11_10 0x82C2
+#define GL_IMAGE_CLASS_1_X_16 0x82BE
+#define GL_IMAGE_CLASS_1_X_32 0x82BB
+#define GL_IMAGE_CLASS_1_X_8 0x82C1
+#define GL_IMAGE_CLASS_2_X_16 0x82BD
+#define GL_IMAGE_CLASS_2_X_32 0x82BA
+#define GL_IMAGE_CLASS_2_X_8 0x82C0
+#define GL_IMAGE_CLASS_4_X_16 0x82BC
+#define GL_IMAGE_CLASS_4_X_32 0x82B9
+#define GL_IMAGE_CLASS_4_X_8 0x82BF
+#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define GL_IMAGE_PIXEL_TYPE 0x82AA
+#define GL_IMAGE_TEXEL_SIZE 0x82A7
+#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define GL_INTERNALFORMAT_PREFERRED 0x8270
+#define GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define GL_IS_PER_PATCH 0x92E7
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_INDEX 0x930F
+#define GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEPTH 0x8280
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_HEIGHT 0x827F
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_LAYERS 0x8281
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_WIDTH 0x827E
+#define GL_MIPMAP 0x8293
+#define GL_NAME_LENGTH 0x92F9
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#define GL_OFFSET 0x92FC
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_PROGRAM 0x82E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_QUERY 0x82E3
+#define GL_READ_PIXELS 0x828C
+#define GL_READ_PIXELS_FORMAT 0x828D
+#define GL_READ_PIXELS_TYPE 0x828E
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_SAMPLER 0x82E6
+#define GL_SHADER 0x82E1
+#define GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define GL_SHADER_IMAGE_LOAD 0x82A4
+#define GL_SHADER_IMAGE_STORE 0x82A5
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_SRGB_READ 0x8297
+#define GL_SRGB_WRITE 0x8298
+#define GL_STENCIL_COMPONENTS 0x8285
+#define GL_STENCIL_RENDERABLE 0x8288
+#define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_CONTROL_TEXTURE 0x829C
+#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_TESS_EVALUATION_TEXTURE 0x829D
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_GATHER 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define GL_TEXTURE_IMAGE_TYPE 0x8290
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_TEXTURE_SHADOW 0x82A1
+#define GL_TEXTURE_VIEW 0x82B5
+#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_TYPE 0x92FA
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_BUFFER 0x8F4F
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_VERTEX_SUBROUTINE 0x92E8
+#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define GL_VERTEX_TEXTURE 0x829B
+#define GL_VIEW_CLASS_128_BITS 0x82C4
+#define GL_VIEW_CLASS_16_BITS 0x82CA
+#define GL_VIEW_CLASS_24_BITS 0x82C9
+#define GL_VIEW_CLASS_32_BITS 0x82C8
+#define GL_VIEW_CLASS_48_BITS 0x82C7
+#define GL_VIEW_CLASS_64_BITS 0x82C6
+#define GL_VIEW_CLASS_8_BITS 0x82CB
+#define GL_VIEW_CLASS_96_BITS 0x82C5
+#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+
+// 4.4
+#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F
+#define GL_BUFFER_STORAGE_FLAGS 0x8220
+#define GL_CLEAR_TEXTURE 0x9365
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000
+#define GL_CLIENT_STORAGE_BIT 0x0200
+#define GL_DYNAMIC_STORAGE_BIT 0x0100
+#define GL_LOCATION_COMPONENT 0x934A
+#define GL_MAP_COHERENT_BIT 0x0080
+#define GL_MAP_PERSISTENT_BIT 0x0040
+#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
+#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_QUERY_BUFFER 0x9192
+#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+#define GL_QUERY_BUFFER_BINDING 0x9193
+#define GL_QUERY_RESULT_NO_WAIT 0x9194
+#define GL_TEXTURE_BUFFER_BINDING 0x8C2A
+#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B
+#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C
+
+// 4.5
+#define GL_CLIP_DEPTH_MODE 0x935D
+#define GL_CLIP_ORIGIN 0x935C
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
+#define GL_CONTEXT_LOST 0x0507
+#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
+#define GL_GUILTY_CONTEXT_RESET 0x8253
+#define GL_INNOCENT_CONTEXT_RESET 0x8254
+#define GL_LOSE_CONTEXT_ON_RESET 0x8252
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA
+#define GL_MAX_CULL_DISTANCES 0x82F9
+#define GL_NEGATIVE_ONE_TO_ONE 0x935E
+#define GL_NO_RESET_NOTIFICATION 0x8261
+#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A
+#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19
+#define GL_QUERY_NO_WAIT_INVERTED 0x8E18
+#define GL_QUERY_TARGET 0x82EA
+#define GL_QUERY_WAIT_INVERTED 0x8E17
+#define GL_RESET_NOTIFICATION_STRATEGY 0x8256
+#define GL_TEXTURE_TARGET 0x1006
+#define GL_UNKNOWN_CONTEXT_RESET 0x8255
+#define GL_ZERO_TO_ONE 0x935F
+
+#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h b/src/third_party/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h
new file mode 100644
index 0000000..daf7ff7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h
@@ -0,0 +1,758 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// functionsgl_typedefs.h: Typedefs of OpenGL types and functions for versions 1.0 through 4.5.
+
+#ifndef LIBANGLE_RENDERER_GL_FUNCTIONSGLTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_FUNCTIONSGLTYPEDEFS_H_
+
+#include "common/platform.h"
+
+#include <KHR/khrplatform.h>
+#include <stdint.h>
+
+#ifndef INTERNAL_GL_APIENTRY
+#   ifdef ANGLE_PLATFORM_WINDOWS
+#       define INTERNAL_GL_APIENTRY __stdcall
+#   else
+#       define INTERNAL_GL_APIENTRY
+#   endif
+#endif
+
+typedef void             GLvoid;
+typedef char             GLchar;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef double           GLdouble;
+typedef double           GLclampd;
+typedef khronos_int32_t  GLfixed;
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+typedef unsigned short   GLhalf;
+typedef khronos_int64_t  GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+
+namespace rx
+{
+typedef void (INTERNAL_GL_APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam);
+typedef void (INTERNAL_GL_APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam);
+typedef void (INTERNAL_GL_APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar *message, void *userParam);
+
+// 1.0
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARPROC)(GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARCOLORPROC)(GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARDEPTHPROC)(GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARSTENCILPROC)(GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOLORMASKPROC)(GLboolean, GLboolean, GLboolean, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCULLFACEPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHFUNCPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHMASKPROC)(GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEPROC)(GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWBUFFERPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFINISHPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFLUSHPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRONTFACEPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBOOLEANVPROC)(GLenum, GLboolean *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETDOUBLEVPROC)(GLenum, GLdouble *);
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLGETERRORPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFLOATVPROC)(GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGERVPROC)(GLenum, GLint *);
+typedef const GLubyte * (INTERNAL_GL_APIENTRY *PFNGLGETSTRINGPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXIMAGEPROC)(GLenum, GLint, GLenum, GLenum, GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum, GLint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum, GLint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERFVPROC)(GLenum, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERIVPROC)(GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLHINTPROC)(GLenum, GLenum);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISENABLEDPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLLINEWIDTHPROC)(GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLLOGICOPPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPIXELSTOREFPROC)(GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPIXELSTOREIPROC)(GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTSIZEPROC)(GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOLYGONMODEPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLREADBUFFERPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLREADPIXELSPROC)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORPROC)(GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILFUNCPROC)(GLenum, GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILMASKPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILOPPROC)(GLenum, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE2DPROC)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERFPROC)(GLenum, GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERFVPROC)(GLenum, GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIPROC)(GLenum, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIVPROC)(GLenum, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTPROC)(GLint, GLint, GLsizei, GLsizei);
+
+// 1.1
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTEXTUREPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXIMAGE1DPROC)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXIMAGE2DPROC)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETETEXTURESPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSPROC)(GLenum, GLint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSPROC)(GLenum, GLsizei, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENTEXTURESPROC)(GLsizei, GLuint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISTEXTUREPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOLYGONOFFSETPROC)(GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+
+// 1.2
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDCOLORPROC)(GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWRANGEELEMENTSPROC)(GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE3DPROC)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+
+// 1.2 Extensions
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEFENCESNVPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENFENCESNVPROC)(GLsizei, GLuint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISFENCENVPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLTESTFENCENVPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFENCEIVNVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFINISHFENCENVPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSETFENCENVPROC)(GLuint, GLenum);
+
+// 1.3
+typedef void (INTERNAL_GL_APIENTRY *PFNGLACTIVETEXTUREPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum, GLint, GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLECOVERAGEPROC)(GLfloat, GLboolean);
+
+// 1.4
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCSEPARATEPROC)(GLenum, GLenum, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWARRAYSPROC)(GLenum, const GLint *, const GLsizei *, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWELEMENTSPROC)(GLenum, const GLsizei *, GLenum, const GLvoid *const*, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERFPROC)(GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERFVPROC)(GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERIPROC)(GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERIVPROC)(GLenum, const GLint *);
+
+// 1.5
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINQUERYPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBUFFERDATAPROC)(GLenum, GLsizeiptr, const GLvoid *, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBUFFERSUBDATAPROC)(GLenum, GLintptr, GLsizeiptr, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEBUFFERSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEQUERIESPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENDQUERYPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENQUERIESPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERPOINTERVPROC)(GLenum, GLenum, GLvoid **);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERSUBDATAPROC)(GLenum, GLintptr, GLsizeiptr, GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTUIVPROC)(GLuint, GLenum, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYIVPROC)(GLenum, GLenum, GLint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISBUFFERPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISQUERYPROC)(GLuint);
+typedef void * (INTERNAL_GL_APIENTRY *PFNGLMAPBUFFERPROC)(GLenum, GLenum);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLUNMAPBUFFERPROC)(GLenum);
+
+// 2.0
+typedef void (INTERNAL_GL_APIENTRY *PFNGLATTACHSHADERPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDATTRIBLOCATIONPROC)(GLuint, GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPILESHADERPROC)(GLuint);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLCREATEPROGRAMPROC)();
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLCREATESHADERPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEPROGRAMPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETESHADERPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDETACHSHADERPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWBUFFERSPROC)(GLsizei, const GLenum *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEATTRIBPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETATTACHEDSHADERSPROC)(GLuint, GLsizei, GLsizei *, GLuint *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETATTRIBLOCATIONPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMINFOLOGPROC)(GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERINFOLOGPROC)(GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERSOURCEPROC)(GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERIVPROC)(GLuint, GLenum, GLint *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMLOCATIONPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMFVPROC)(GLuint, GLint, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMIVPROC)(GLuint, GLint, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint, GLenum, GLvoid **);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint, GLenum, GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBFVPROC)(GLuint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBIVPROC)(GLuint, GLenum, GLint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISPROGRAMPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISSHADERPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLLINKPROGRAMPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSHADERSOURCEPROC)(GLuint, GLsizei, const GLchar *const*, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum, GLenum, GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILMASKSEPARATEPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILOPSEPARATEPROC)(GLenum, GLenum, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1FPROC)(GLint, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1FVPROC)(GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1IPROC)(GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1IVPROC)(GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2FPROC)(GLint, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2FVPROC)(GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2IPROC)(GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2IVPROC)(GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3FPROC)(GLint, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3FVPROC)(GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3IPROC)(GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3IVPROC)(GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4FPROC)(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4FVPROC)(GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4IPROC)(GLint, GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4IVPROC)(GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUSEPROGRAMPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVALIDATEPROGRAMPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1DPROC)(GLuint, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1FPROC)(GLuint, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1FVPROC)(GLuint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1SPROC)(GLuint, GLshort);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2DPROC)(GLuint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2FPROC)(GLuint, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2FVPROC)(GLuint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2SPROC)(GLuint, GLshort, GLshort);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3DPROC)(GLuint, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3FPROC)(GLuint, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3FVPROC)(GLuint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3SPROC)(GLuint, GLshort, GLshort, GLshort);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NBVPROC)(GLuint, const GLbyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NIVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NSVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUBPROC)(GLuint, GLubyte, GLubyte, GLubyte, GLubyte);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint, const GLubyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint, const GLushort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4BVPROC)(GLuint, const GLbyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4DPROC)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4FPROC)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4FVPROC)(GLuint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4SPROC)(GLuint, GLshort, GLshort, GLshort, GLshort);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4UBVPROC)(GLuint, const GLubyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4USVPROC)(GLuint, const GLushort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+
+// 2.1
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+
+// 3.0
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERBASEPROC)(GLenum, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERRANGEPROC)(GLenum, GLuint, GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint, GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDFRAMEBUFFERPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDRENDERBUFFERPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDVERTEXARRAYPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLITFRAMEBUFFERPROC)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLAMPCOLORPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERFIPROC)(GLenum, GLint, GLfloat, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERFVPROC)(GLenum, GLint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERIVPROC)(GLenum, GLint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERUIVPROC)(GLenum, GLint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOLORMASKIPROC)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETERENDERBUFFERSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEIPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEIPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENDCONDITIONALRENDERPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENDTRANSFORMFEEDBACKPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum, GLenum, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum, GLenum, GLenum, GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum, GLenum, GLenum, GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum, GLenum, GLenum, GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum, GLenum, GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENFRAMEBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENRENDERBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENVERTEXARRAYSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENERATEMIPMAPPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBOOLEANI_VPROC)(GLenum, GLuint, GLboolean *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETFRAGDATALOCATIONPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum, GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGERI_VPROC)(GLenum, GLuint, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint *);
+typedef const GLubyte * (INTERNAL_GL_APIENTRY *PFNGLGETSTRINGIPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERIIVPROC)(GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum, GLenum, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMUIVPROC)(GLuint, GLint, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint, GLenum, GLuint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISENABLEDIPROC)(GLenum, GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISFRAMEBUFFERPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISRENDERBUFFERPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISVERTEXARRAYPROC)(GLuint);
+typedef void * (INTERNAL_GL_APIENTRY *PFNGLMAPBUFFERRANGEPROC)(GLenum, GLintptr, GLsizeiptr, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIIVPROC)(GLenum, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIUIVPROC)(GLenum, GLenum, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint, GLsizei, const GLchar *const*, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1UIPROC)(GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1UIVPROC)(GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2UIPROC)(GLint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2UIVPROC)(GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3UIPROC)(GLint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3UIVPROC)(GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4UIPROC)(GLint, GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4UIVPROC)(GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1IPROC)(GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1UIPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2IPROC)(GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2UIPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3IPROC)(GLuint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3UIPROC)(GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4BVPROC)(GLuint, const GLbyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4IPROC)(GLuint, GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint, const GLubyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4UIPROC)(GLuint, GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4USVPROC)(GLuint, const GLushort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint, GLint, GLenum, GLsizei, const GLvoid *);
+
+// 3.1
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum, GLsizei, GLenum, const GLvoid *, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint, GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint, GLsizei, const GLuint *, GLenum, GLint *);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMINDICESPROC)(GLuint, GLsizei, const GLchar *const*, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXBUFFERPROC)(GLenum, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint, GLuint, GLuint);
+
+// 3.2
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLCLIENTWAITSYNCPROC)(GLsync, GLbitfield, GLuint64);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETESYNCPROC)(GLsync);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum, GLsizei, GLenum, const GLvoid *, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum, GLsizei, GLenum, const GLvoid *, GLsizei, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *, GLint);
+typedef GLsync (INTERNAL_GL_APIENTRY *PFNGLFENCESYNCPROC)(GLenum, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum, GLenum, GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum, GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGER64I_VPROC)(GLenum, GLuint, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGER64VPROC)(GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETMULTISAMPLEFVPROC)(GLenum, GLuint, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSYNCIVPROC)(GLsync, GLenum, GLsizei, GLsizei *, GLint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISSYNCPROC)(GLsync);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum, const GLsizei *, GLenum, const GLvoid *const*, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROVOKINGVERTEXPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLEMASKIPROC)(GLuint, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum, GLsizei, GLint, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLint, GLsizei, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLWAITSYNCPROC)(GLsync, GLbitfield, GLuint64);
+
+// 3.3
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint, GLuint, GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDSAMPLERPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETESAMPLERSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENSAMPLERSPROC)(GLsizei, GLuint *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETFRAGDATAINDEXPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTI64VPROC)(GLuint, GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint, GLenum, GLuint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint, GLenum, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISSAMPLERPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLQUERYCOUNTERPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint, GLenum, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERFPROC)(GLuint, GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERFVPROC)(GLuint, GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIVPROC)(GLuint, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP1UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP2UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP3UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP4UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *);
+
+// 4.0
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINQUERYINDEXEDPROC)(GLenum, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTRANSFORMFEEDBACKPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONSEPARATEIPROC)(GLuint, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONIPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCSEPARATEIPROC)(GLuint, GLenum, GLenum, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCIPROC)(GLuint, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETETRANSFORMFEEDBACKSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSINDIRECTPROC)(GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINDIRECTPROC)(GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC)(GLenum, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENDQUERYINDEXEDPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENTRANSFORMFEEDBACKSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVESUBROUTINENAMEPROC)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC)(GLuint, GLenum, GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMSTAGEIVPROC)(GLuint, GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYINDEXEDIVPROC)(GLenum, GLuint, GLenum, GLint *);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETSUBROUTINEINDEXPROC)(GLuint, GLenum, const GLchar *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC)(GLuint, GLenum, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMSUBROUTINEUIVPROC)(GLenum, GLint, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMDVPROC)(GLuint, GLint, GLdouble *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISTRANSFORMFEEDBACKPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMINSAMPLESHADINGPROC)(GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPATCHPARAMETERFVPROC)(GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPATCHPARAMETERIPROC)(GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPAUSETRANSFORMFEEDBACKPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLRESUMETRANSFORMFEEDBACKPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1DPROC)(GLint, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1DVPROC)(GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2DPROC)(GLint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2DVPROC)(GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3DPROC)(GLint, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3DVPROC)(GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4DPROC)(GLint, GLdouble, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4DVPROC)(GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X3DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X4DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X2DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X4DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X2DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X3DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMSUBROUTINESUIVPROC)(GLenum, GLsizei, const GLuint *);
+
+// 4.1
+typedef void (INTERNAL_GL_APIENTRY *PFNGLACTIVESHADERPROGRAMPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDPROGRAMPIPELINEPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARDEPTHFPROC)(GLfloat);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLCREATESHADERPROGRAMVPROC)(GLenum, GLsizei, const GLchar *const*);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEPROGRAMPIPELINESPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEARRAYVPROC)(GLuint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEINDEXEDPROC)(GLuint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEFPROC)(GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENPROGRAMPIPELINESPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETDOUBLEI_VPROC)(GLenum, GLuint, GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFLOATI_VPROC)(GLenum, GLuint, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMBINARYPROC)(GLuint, GLsizei, GLsizei *, GLenum *, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMPIPELINEINFOLOGPROC)(GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMPIPELINEIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum, GLenum, GLint *, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBLDVPROC)(GLuint, GLenum, GLdouble *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISPROGRAMPIPELINEPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMBINARYPROC)(GLuint, GLenum, const void *, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1DPROC)(GLuint, GLint, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1DVPROC)(GLuint, GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1FPROC)(GLuint, GLint, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1FVPROC)(GLuint, GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1IPROC)(GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1IVPROC)(GLuint, GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1UIPROC)(GLuint, GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1UIVPROC)(GLuint, GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2DPROC)(GLuint, GLint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2DVPROC)(GLuint, GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2FPROC)(GLuint, GLint, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2FVPROC)(GLuint, GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2IPROC)(GLuint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2IVPROC)(GLuint, GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2UIPROC)(GLuint, GLint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2UIVPROC)(GLuint, GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3DPROC)(GLuint, GLint, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3DVPROC)(GLuint, GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3FPROC)(GLuint, GLint, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3FVPROC)(GLuint, GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3IPROC)(GLuint, GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3IVPROC)(GLuint, GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3UIPROC)(GLuint, GLint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3UIVPROC)(GLuint, GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4DPROC)(GLuint, GLint, GLdouble, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4DVPROC)(GLuint, GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4FPROC)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4FVPROC)(GLuint, GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4IPROC)(GLuint, GLint, GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4IVPROC)(GLuint, GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4UIPROC)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4UIVPROC)(GLuint, GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLRELEASESHADERCOMPILERPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORARRAYVPROC)(GLuint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORINDEXEDPROC)(GLuint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORINDEXEDVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSHADERBINARYPROC)(GLsizei, const GLuint *, GLenum, const void *, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUSEPROGRAMSTAGESPROC)(GLuint, GLbitfield, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVALIDATEPROGRAMPIPELINEPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL1DPROC)(GLuint, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL1DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL2DPROC)(GLuint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL2DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL3DPROC)(GLuint, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL3DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL4DPROC)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL4DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBLPOINTERPROC)(GLuint, GLint, GLenum, GLsizei, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTARRAYVPROC)(GLuint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTINDEXEDFPROC)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTINDEXEDFVPROC)(GLuint, const GLfloat *);
+
+// 4.2
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDIMAGETEXTUREPROC)(GLuint, GLuint, GLint, GLboolean, GLint, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)(GLenum, GLint, GLsizei, GLsizei, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)(GLenum, GLsizei, GLenum, const void *, GLsizei, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)(GLenum, GLsizei, GLenum, const void *, GLsizei, GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)(GLenum, GLuint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)(GLenum, GLuint, GLuint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC)(GLuint, GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTERNALFORMATIVPROC)(GLenum, GLenum, GLenum, GLsizei, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMEMORYBARRIERPROC)(GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE1DPROC)(GLenum, GLsizei, GLenum, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE2DPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE3DPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei);
+
+// 4.3
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDVERTEXBUFFERPROC)(GLuint, GLuint, GLintptr, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERDATAPROC)(GLenum, GLenum, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERSUBDATAPROC)(GLenum, GLenum, GLintptr, GLsizeiptr, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYIMAGESUBDATAPROC)(GLuint, GLenum, GLint, GLint, GLint, GLint, GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEBUGMESSAGECONTROLPROC)(GLenum, GLenum, GLenum, GLsizei, const GLuint *, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEBUGMESSAGEINSERTPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISPATCHCOMPUTEPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISPATCHCOMPUTEINDIRECTPROC)(GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERPARAMETERIPROC)(GLenum, GLenum, GLint);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETDEBUGMESSAGELOGPROC)(GLuint, GLsizei, GLenum *, GLenum *, GLuint *, GLenum *, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFRAMEBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTERNALFORMATI64VPROC)(GLenum, GLenum, GLenum, GLsizei, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPOINTERVPROC)(GLenum, void **);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETOBJECTLABELPROC)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETOBJECTPTRLABELPROC)(const void *, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMINTERFACEIVPROC)(GLuint, GLenum, GLenum, GLint *);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCEINDEXPROC)(GLuint, GLenum, const GLchar *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCELOCATIONPROC)(GLuint, GLenum, const GLchar *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)(GLuint, GLenum, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCENAMEPROC)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCEIVPROC)(GLuint, GLenum, GLuint, GLsizei, const GLenum *, GLsizei, GLsizei *, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATEBUFFERDATAPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATEBUFFERSUBDATAPROC)(GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATEFRAMEBUFFERPROC)(GLenum, GLsizei, const GLenum *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATESUBFRAMEBUFFERPROC)(GLenum, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATETEXIMAGEPROC)(GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATETEXSUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWARRAYSINDIRECTPROC)(GLenum, const void *, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWELEMENTSINDIRECTPROC)(GLenum, GLenum, const void *, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLOBJECTLABELPROC)(GLenum, GLuint, GLsizei, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLOBJECTPTRLABELPROC)(const void *, GLsizei, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOPDEBUGGROUPPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPUSHDEBUGGROUPPROC)(GLenum, GLuint, GLsizei, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSHADERSTORAGEBLOCKBINDINGPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXBUFFERRANGEPROC)(GLenum, GLenum, GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE2DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREVIEWPROC)(GLuint, GLenum, GLuint, GLenum, GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBBINDINGPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBFORMATPROC)(GLuint, GLint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBIFORMATPROC)(GLuint, GLint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBLFORMATPROC)(GLuint, GLint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXBINDINGDIVISORPROC)(GLuint, GLuint);
+
+// NV_framebuffer_mixed_samples
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOVERAGEMODULATIONNVPROC)(GLenum);
+
+// 4.4
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERSBASEPROC)(GLenum, GLuint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERSRANGEPROC)(GLenum, GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizeiptr *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDIMAGETEXTURESPROC)(GLuint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDSAMPLERSPROC)(GLuint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTEXTURESPROC)(GLuint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDVERTEXBUFFERSPROC)(GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizei *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBUFFERSTORAGEPROC)(GLenum, GLsizeiptr, const void *, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARTEXIMAGEPROC)(GLuint, GLint, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARTEXSUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *);
+
+// 4.5
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTEXTUREUNITPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLITNAMEDFRAMEBUFFERPROC)(GLuint, GLuint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDBUFFERDATAPROC)(GLuint, GLenum, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDBUFFERSUBDATAPROC)(GLuint, GLenum, GLintptr, GLsizeiptr, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERFIPROC)(GLuint, GLenum, const GLfloat, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)(GLuint, GLenum, GLint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERIVPROC)(GLuint, GLenum, GLint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC)(GLuint, GLenum, GLint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLIPCONTROLPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC)(GLuint, GLint, GLint, GLsizei, GLenum, GLsizei, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC)(GLuint, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYNAMEDBUFFERSUBDATAPROC)(GLuint, GLuint, GLintptr, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXTURESUBIMAGE1DPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXTURESUBIMAGE2DPROC)(GLuint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXTURESUBIMAGE3DPROC)(GLuint, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEFRAMEBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEPROGRAMPIPELINESPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEQUERIESPROC)(GLenum, GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATERENDERBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATESAMPLERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATETEXTURESPROC)(GLenum, GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATETRANSFORMFEEDBACKSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEVERTEXARRAYSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEVERTEXARRAYATTRIBPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEVERTEXARRAYATTRIBPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC)(GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENERATETEXTUREMIPMAPPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC)(GLuint, GLint, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, void *);
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLGETGRAPHICSRESETSTATUSPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERPARAMETERI64VPROC)(GLuint, GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERPOINTERVPROC)(GLuint, GLenum, void **);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERSUBDATAPROC)(GLuint, GLintptr, GLsizeiptr, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLuint, GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTI64VPROC)(GLuint, GLuint, GLenum, GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTIVPROC)(GLuint, GLuint, GLenum, GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTUI64VPROC)(GLuint, GLuint, GLenum, GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTUIVPROC)(GLuint, GLuint, GLenum, GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREIMAGEPROC)(GLuint, GLint, GLenum, GLenum, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTURELEVELPARAMETERFVPROC)(GLuint, GLint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTURELEVELPARAMETERIVPROC)(GLuint, GLint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERIIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERIUIVPROC)(GLuint, GLenum, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERFVPROC)(GLuint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTURESUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKI64_VPROC)(GLuint, GLenum, GLuint, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKI_VPROC)(GLuint, GLenum, GLuint, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXARRAYINDEXED64IVPROC)(GLuint, GLuint, GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXARRAYINDEXEDIVPROC)(GLuint, GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXARRAYIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNCOMPRESSEDTEXIMAGEPROC)(GLenum, GLint, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNTEXIMAGEPROC)(GLenum, GLint, GLenum, GLenum, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMDVPROC)(GLuint, GLint, GLsizei, GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMFVPROC)(GLuint, GLint, GLsizei, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMIVPROC)(GLuint, GLint, GLsizei, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMUIVPROC)(GLuint, GLint, GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC)(GLuint, GLsizei, const GLenum *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC)(GLuint, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei);
+typedef void *(INTERNAL_GL_APIENTRY *PFNGLMAPNAMEDBUFFERPROC)(GLuint, GLenum);
+typedef void *(INTERNAL_GL_APIENTRY *PFNGLMAPNAMEDBUFFERRANGEPROC)(GLuint, GLintptr, GLsizeiptr, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDBUFFERDATAPROC)(GLuint, GLsizeiptr, const void *, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDBUFFERSTORAGEPROC)(GLuint, GLsizeiptr, const void *, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDBUFFERSUBDATAPROC)(GLuint, GLintptr, GLsizeiptr, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC)(GLuint, GLsizei, const GLenum *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC)(GLuint, GLenum, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERTEXTUREPROC)(GLuint, GLenum, GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC)(GLuint, GLenum, GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDRENDERBUFFERSTORAGEPROC)(GLuint, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLREADNPIXELSPROC)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREBARRIERPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREBUFFERPROC)(GLuint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREBUFFERRANGEPROC)(GLuint, GLenum, GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIIVPROC)(GLuint, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIUIVPROC)(GLuint, GLenum, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERFPROC)(GLuint, GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERFVPROC)(GLuint, GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIVPROC)(GLuint, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE1DPROC)(GLuint, GLsizei, GLenum, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE2DPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE3DPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESUBIMAGE1DPROC)(GLuint, GLint, GLint, GLsizei, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESUBIMAGE2DPROC)(GLuint, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESUBIMAGE3DPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC)(GLuint, GLuint, GLuint, GLintptr, GLsizeiptr);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLUNMAPNAMEDBUFFERPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBBINDINGPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBFORMATPROC)(GLuint, GLuint, GLint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBIFORMATPROC)(GLuint, GLuint, GLint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBLFORMATPROC)(GLuint, GLuint, GLint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYBINDINGDIVISORPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYELEMENTBUFFERPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYVERTEXBUFFERPROC)(GLuint, GLuint, GLuint, GLintptr, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYVERTEXBUFFERSPROC)(GLuint, GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizei *);
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGLTYPEDEFS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
new file mode 100644
index 0000000..8e7607d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
@@ -0,0 +1,885 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayGLX.cpp: GLX implementation of egl::Display
+
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+
+#include <EGL/eglext.h>
+#include <algorithm>
+#include <cstring>
+#include <fstream>
+
+#include "common/debug.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h"
+#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace rx
+{
+
+static int IgnoreX11Errors(Display *, XErrorEvent *)
+{
+    return 0;
+}
+
+SwapControlData::SwapControlData()
+  : targetSwapInterval(0),
+    maxSwapInterval(-1),
+    currentSwapInterval(-1)
+{
+}
+
+class FunctionsGLGLX : public FunctionsGL
+{
+  public:
+    FunctionsGLGLX(PFNGETPROCPROC getProc)
+      : mGetProc(getProc)
+    {
+    }
+
+    ~FunctionsGLGLX() override {}
+
+  private:
+    void *loadProcAddress(const std::string &function) override
+    {
+        return reinterpret_cast<void*>(mGetProc(function.c_str()));
+    }
+
+    PFNGETPROCPROC mGetProc;
+};
+
+DisplayGLX::DisplayGLX(const egl::DisplayState &state)
+    : DisplayGL(state),
+      mFunctionsGL(nullptr),
+      mRequestedVisual(-1),
+      mContextConfig(nullptr),
+      mContext(nullptr),
+      mDummyPbuffer(0),
+      mUsesNewXDisplay(false),
+      mIsMesa(false),
+      mHasMultisample(false),
+      mHasARBCreateContext(false),
+      mHasARBCreateContextProfile(false),
+      mHasARBCreateContextRobustness(false),
+      mHasEXTCreateContextES2Profile(false),
+      mSwapControl(SwapControl::Absent),
+      mMinSwapInterval(0),
+      mMaxSwapInterval(0),
+      mCurrentSwapInterval(-1),
+      mXDisplay(nullptr),
+      mEGLDisplay(nullptr)
+{
+}
+
+DisplayGLX::~DisplayGLX()
+{
+}
+
+egl::Error DisplayGLX::initialize(egl::Display *display)
+{
+    mEGLDisplay = display;
+    mXDisplay             = display->getNativeDisplayId();
+    const auto &attribMap = display->getAttributeMap();
+
+    // ANGLE_platform_angle allows the creation of a default display
+    // using EGL_DEFAULT_DISPLAY (= nullptr). In this case just open
+    // the display specified by the DISPLAY environment variable.
+    if (mXDisplay == EGL_DEFAULT_DISPLAY)
+    {
+        mUsesNewXDisplay = true;
+        mXDisplay        = XOpenDisplay(nullptr);
+        if (!mXDisplay)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, "Could not open the default X display.");
+        }
+    }
+
+    std::string glxInitError;
+    if (!mGLX.initialize(mXDisplay, DefaultScreen(mXDisplay), &glxInitError))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, glxInitError.c_str());
+    }
+
+    mHasMultisample      = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample");
+    mHasARBCreateContext = mGLX.hasExtension("GLX_ARB_create_context");
+    mHasARBCreateContextProfile    = mGLX.hasExtension("GLX_ARB_create_context_profile");
+    mHasARBCreateContextRobustness = mGLX.hasExtension("GLX_ARB_create_context_robustness");
+    mHasEXTCreateContextES2Profile = mGLX.hasExtension("GLX_EXT_create_context_es2_profile");
+
+    std::string clientVendor = mGLX.getClientString(GLX_VENDOR);
+    mIsMesa                  = clientVendor.find("Mesa") != std::string::npos;
+
+    // Choose the swap_control extension to use, if any.
+    // The EXT version is better as it allows glXSwapInterval to be called per
+    // window, while we'll potentially need to change the swap interval on each
+    // swap buffers when using the SGI or MESA versions.
+    if (mGLX.hasExtension("GLX_EXT_swap_control"))
+    {
+        mSwapControl = SwapControl::EXT;
+
+        // In GLX_EXT_swap_control querying these is done on a GLXWindow so we just
+        // set default values.
+        mMinSwapInterval = 0;
+        mMaxSwapInterval = 4;
+    }
+    else if (mGLX.hasExtension("GLX_MESA_swap_control"))
+    {
+        // If we have the Mesa or SGI extension, assume that you can at least set
+        // a swap interval of 0 or 1.
+        mSwapControl = SwapControl::Mesa;
+        mMinSwapInterval = 0;
+        mMinSwapInterval = 1;
+    }
+    else if (mGLX.hasExtension("GLX_SGI_swap_control"))
+    {
+        mSwapControl = SwapControl::SGI;
+        mMinSwapInterval = 0;
+        mMinSwapInterval = 1;
+    }
+    else
+    {
+        mSwapControl = SwapControl::Absent;
+        mMinSwapInterval = 1;
+        mMinSwapInterval = 1;
+    }
+
+    if (attribMap.contains(EGL_X11_VISUAL_ID_ANGLE))
+    {
+        mRequestedVisual = static_cast<EGLint>(attribMap.get(EGL_X11_VISUAL_ID_ANGLE, -1));
+
+        // There is no direct way to get the GLXFBConfig matching an X11 visual ID
+        // so we have to iterate over all the GLXFBConfigs to find the right one.
+        int nConfigs;
+        int attribList[] = {
+            None,
+        };
+        glx::FBConfig *allConfigs = mGLX.chooseFBConfig(attribList, &nConfigs);
+
+        for (int i = 0; i < nConfigs; ++i)
+        {
+            if (getGLXFBConfigAttrib(allConfigs[i], GLX_VISUAL_ID) == mRequestedVisual)
+            {
+                mContextConfig = allConfigs[i];
+                break;
+            }
+        }
+        XFree(allConfigs);
+
+        if (mContextConfig == nullptr)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, "Invalid visual ID requested.");
+        }
+    }
+    else
+    {
+        // When glXMakeCurrent is called, the context and the surface must be
+        // compatible which in glX-speak means that their config have the same
+        // color buffer type, are both RGBA or ColorIndex, and their buffers have
+        // the same depth, if they exist.
+        // Since our whole EGL implementation is backed by only one GL context, this
+        // context must be compatible with all the GLXFBConfig corresponding to the
+        // EGLconfigs that we will be exposing.
+        int nConfigs;
+        int attribList[] =
+        {
+            // We want RGBA8 and DEPTH24_STENCIL8
+            GLX_RED_SIZE, 8,
+            GLX_GREEN_SIZE, 8,
+            GLX_BLUE_SIZE, 8,
+            GLX_ALPHA_SIZE, 8,
+            GLX_DEPTH_SIZE, 24,
+            GLX_STENCIL_SIZE, 8,
+            // We want RGBA rendering (vs COLOR_INDEX) and doublebuffer
+            GLX_RENDER_TYPE, GLX_RGBA_BIT,
+            // Double buffer is not strictly required as a non-doublebuffer
+            // context can work with a doublebuffered surface, but it still
+            // flickers and all applications want doublebuffer anyway.
+            GLX_DOUBLEBUFFER, True,
+            // All of these must be supported for full EGL support
+            GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER_BIT | GLX_PIXMAP_BIT,
+            // This makes sure the config have an associated visual Id
+            GLX_X_RENDERABLE, True,
+            GLX_CONFIG_CAVEAT, GLX_NONE,
+            None
+        };
+        glx::FBConfig *candidates = mGLX.chooseFBConfig(attribList, &nConfigs);
+        if (nConfigs == 0)
+        {
+            XFree(candidates);
+            return egl::Error(EGL_NOT_INITIALIZED, "Could not find a decent GLX FBConfig to create the context.");
+        }
+        mContextConfig = candidates[0];
+        XFree(candidates);
+    }
+
+    const auto &eglAttributes = display->getAttributeMap();
+    if (mHasARBCreateContext)
+    {
+        egl::Error error = initializeContext(mContextConfig, eglAttributes, &mContext);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+    else
+    {
+        if (eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE,
+                              EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) ==
+            EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED,
+                              "Cannot create an OpenGL ES platform on GLX without the "
+                              "GLX_ARB_create_context extension.");
+        }
+
+        XVisualInfo visualTemplate;
+        visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID);
+
+        int numVisuals       = 0;
+        XVisualInfo *visuals =
+            XGetVisualInfo(mXDisplay, VisualIDMask, &visualTemplate, &numVisuals);
+        if (numVisuals <= 0)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED,
+                              "Could not get the visual info from the fb config");
+        }
+        ASSERT(numVisuals == 1);
+
+        mContext = mGLX.createContext(&visuals[0], nullptr, true);
+        XFree(visuals);
+
+        if (!mContext)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
+        }
+    }
+    ASSERT(mContext);
+
+    // FunctionsGL and DisplayGL need to make a few GL calls, for example to
+    // query the version of the context so we need to make the context current.
+    // glXMakeCurrent requires a GLXDrawable so we create a temporary Pbuffer
+    // (of size 1, 1) for the duration of these calls.
+    // Ideally we would want to unset the current context and destroy the pbuffer
+    // before going back to the application but this is TODO
+    // We could use a pbuffer of size (0, 0) but it fails on the Intel Mesa driver
+    // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we
+    // use (1, 1) instead.
+
+    int dummyPbufferAttribs[] =
+    {
+        GLX_PBUFFER_WIDTH, 1,
+        GLX_PBUFFER_HEIGHT, 1,
+        None,
+    };
+    mDummyPbuffer = mGLX.createPbuffer(mContextConfig, dummyPbufferAttribs);
+    if (!mDummyPbuffer)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not create the dummy pbuffer.");
+    }
+
+    if (!mGLX.makeCurrent(mDummyPbuffer, mContext))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not make the dummy pbuffer current.");
+    }
+
+    mFunctionsGL = new FunctionsGLGLX(mGLX.getProc);
+    mFunctionsGL->initialize();
+
+    // TODO(cwallez, angleproject:1303) Disable the OpenGL ES backend on Linux NVIDIA and Intel as
+    // it has problems on our automated testing. An OpenGL ES backend might not trigger this test if
+    // there is no Desktop OpenGL support, but that's not the case in our automated testing.
+    VendorID vendor = GetVendorID(mFunctionsGL);
+    bool isOpenGLES =
+        eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) ==
+        EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
+    if (isOpenGLES && (IsIntel(vendor) || IsNvidia(vendor)))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Intel or NVIDIA OpenGL ES drivers are not supported.");
+    }
+
+    syncXCommands();
+
+    return DisplayGL::initialize(display);
+}
+
+void DisplayGLX::terminate()
+{
+    DisplayGL::terminate();
+
+    if (mDummyPbuffer)
+    {
+        mGLX.destroyPbuffer(mDummyPbuffer);
+        mDummyPbuffer = 0;
+    }
+
+    if (mContext)
+    {
+        mGLX.destroyContext(mContext);
+        mContext = nullptr;
+    }
+
+    mGLX.terminate();
+
+    SafeDelete(mFunctionsGL);
+}
+
+SurfaceImpl *DisplayGLX::createWindowSurface(const egl::SurfaceState &state,
+                                             EGLNativeWindowType window,
+                                             const egl::AttributeMap &attribs)
+{
+    ASSERT(configIdToGLXConfig.count(state.config->configID) > 0);
+    glx::FBConfig fbConfig = configIdToGLXConfig[state.config->configID];
+
+    return new WindowSurfaceGLX(state, mGLX, this, getRenderer(), window, mGLX.getDisplay(),
+                                mContext, fbConfig);
+}
+
+SurfaceImpl *DisplayGLX::createPbufferSurface(const egl::SurfaceState &state,
+                                              const egl::AttributeMap &attribs)
+{
+    ASSERT(configIdToGLXConfig.count(state.config->configID) > 0);
+    glx::FBConfig fbConfig = configIdToGLXConfig[state.config->configID];
+
+    EGLint width  = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
+    EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
+    bool largest = (attribs.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
+
+    return new PbufferSurfaceGLX(state, getRenderer(), width, height, largest, mGLX, mContext,
+                                 fbConfig);
+}
+
+SurfaceImpl *DisplayGLX::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                                       EGLenum buftype,
+                                                       EGLClientBuffer clientBuffer,
+                                                       const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+SurfaceImpl *DisplayGLX::createPixmapSurface(const egl::SurfaceState &state,
+                                             NativePixmapType nativePixmap,
+                                             const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+egl::Error DisplayGLX::getDevice(DeviceImpl **device)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::Error DisplayGLX::initializeContext(glx::FBConfig config,
+                                         const egl::AttributeMap &eglAttributes,
+                                         glx::Context *context)
+{
+    int profileMask = 0;
+
+    EGLint requestedDisplayType = static_cast<EGLint>(
+        eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
+    if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+    {
+        if (!mHasEXTCreateContextES2Profile)
+        {
+            return egl::Error(EGL_NOT_INITIALIZED,
+                              "Cannot create an OpenGL ES platform on GLX without the "
+                              "GLX_EXT_create_context_es_profile extension.");
+        }
+
+        ASSERT(mHasARBCreateContextProfile);
+        profileMask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
+    }
+
+    // Create a context of the requested version, if any.
+    gl::Version requestedVersion(static_cast<EGLint>(eglAttributes.get(
+                                     EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)),
+                                 static_cast<EGLint>(eglAttributes.get(
+                                     EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)));
+    if (static_cast<EGLint>(requestedVersion.major) != EGL_DONT_CARE &&
+        static_cast<EGLint>(requestedVersion.minor) != EGL_DONT_CARE)
+    {
+        if (!(profileMask & GLX_CONTEXT_ES2_PROFILE_BIT_EXT) &&
+            requestedVersion >= gl::Version(3, 2))
+        {
+            profileMask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+        }
+        return createContextAttribs(config, requestedVersion, profileMask, context);
+    }
+
+    // The only way to get a core profile context of the highest version using
+    // glXCreateContextAttrib is to try creationg contexts in decreasing version
+    // numbers. It might look that asking for a core context of version (0, 0)
+    // works on some driver but it create a _compatibility_ context of the highest
+    // version instead. The cost of failing a context creation is small (< 0.1 ms)
+    // on Mesa but is unfortunately a bit expensive on the Nvidia driver (~3ms).
+    // Also try to get any Desktop GL context, but if that fails fallback to
+    // asking for OpenGL ES contexts.
+
+    struct ContextCreationInfo
+    {
+        ContextCreationInfo(EGLint displayType, int profileFlag, gl::Version version)
+            : displayType(displayType), profileFlag(profileFlag), version(version)
+        {
+        }
+
+        EGLint displayType;
+        int profileFlag;
+        gl::Version version;
+    };
+
+    // clang-format off
+    std::vector<ContextCreationInfo> contextsToTry;
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 5));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 4));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 3));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 2));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 1));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 0));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(3, 3));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(3, 2));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(3, 3));
+
+    // On Mesa, do not try to create OpenGL context versions between 3.0 and
+    // 3.2 because of compatibility problems. See crbug.com/659030
+    if (!mIsMesa)
+    {
+        contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(3, 2));
+        contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(3, 1));
+        contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(3, 0));
+    }
+
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(2, 1));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(2, 0));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 5));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 4));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 3));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 2));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 1));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 0));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, gl::Version(3, 2));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, gl::Version(3, 1));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, gl::Version(3, 0));
+    contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, gl::Version(2, 0));
+    // clang-format on
+
+    // NOTE: below we return as soon as we're able to create a context so the
+    // "error" variable is EGL_SUCCESS when returned contrary to the common idiom
+    // of returning "error" when there is an actual error.
+    for (const auto &info : contextsToTry)
+    {
+        if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE &&
+            requestedDisplayType != info.displayType)
+        {
+            continue;
+        }
+
+        egl::Error error = createContextAttribs(config, info.version, info.profileFlag, context);
+        if (!error.isError())
+        {
+            return error;
+        }
+    }
+
+    return egl::Error(EGL_NOT_INITIALIZED, "Could not create a backing OpenGL context.");
+}
+
+egl::ConfigSet DisplayGLX::generateConfigs()
+{
+    egl::ConfigSet configs;
+    configIdToGLXConfig.clear();
+
+    const gl::Version &maxVersion = getMaxSupportedESVersion();
+    ASSERT(maxVersion >= gl::Version(2, 0));
+    bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
+    int contextRedSize   = getGLXFBConfigAttrib(mContextConfig, GLX_RED_SIZE);
+    int contextGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_GREEN_SIZE);
+    int contextBlueSize  = getGLXFBConfigAttrib(mContextConfig, GLX_BLUE_SIZE);
+    int contextAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ALPHA_SIZE);
+
+    int contextDepthSize   = getGLXFBConfigAttrib(mContextConfig, GLX_DEPTH_SIZE);
+    int contextStencilSize = getGLXFBConfigAttrib(mContextConfig, GLX_STENCIL_SIZE);
+
+    int contextSamples = mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES) : 0;
+    int contextSampleBuffers =
+        mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS) : 0;
+
+    int contextAccumRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_RED_SIZE);
+    int contextAccumGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_GREEN_SIZE);
+    int contextAccumBlueSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_BLUE_SIZE);
+    int contextAccumAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_ALPHA_SIZE);
+
+    int attribList[] =
+    {
+        GLX_RENDER_TYPE, GLX_RGBA_BIT,
+        GLX_X_RENDERABLE, True,
+        GLX_DOUBLEBUFFER, True,
+        None,
+    };
+
+    int glxConfigCount;
+    glx::FBConfig *glxConfigs = mGLX.chooseFBConfig(attribList, &glxConfigCount);
+
+    for (int i = 0; i < glxConfigCount; i++)
+    {
+        glx::FBConfig glxConfig = glxConfigs[i];
+        egl::Config config;
+
+        // Native stuff
+        config.nativeVisualID = getGLXFBConfigAttrib(glxConfig, GLX_VISUAL_ID);
+        config.nativeVisualType = getGLXFBConfigAttrib(glxConfig, GLX_X_VISUAL_TYPE);
+        config.nativeRenderable = EGL_TRUE;
+
+        // When a visual ID has been specified with EGL_ANGLE_x11_visual we should
+        // only return configs with this visual: it will maximize performance by avoid
+        // blits in the driver when showing the window on the screen.
+        if (mRequestedVisual != -1 && config.nativeVisualID != mRequestedVisual)
+        {
+            continue;
+        }
+
+        // Buffer sizes
+        config.redSize = getGLXFBConfigAttrib(glxConfig, GLX_RED_SIZE);
+        config.greenSize = getGLXFBConfigAttrib(glxConfig, GLX_GREEN_SIZE);
+        config.blueSize = getGLXFBConfigAttrib(glxConfig, GLX_BLUE_SIZE);
+        config.alphaSize = getGLXFBConfigAttrib(glxConfig, GLX_ALPHA_SIZE);
+        config.depthSize = getGLXFBConfigAttrib(glxConfig, GLX_DEPTH_SIZE);
+        config.stencilSize = getGLXFBConfigAttrib(glxConfig, GLX_STENCIL_SIZE);
+
+        // We require RGBA8 and the D24S8 (or no DS buffer)
+        if (config.redSize != contextRedSize || config.greenSize != contextGreenSize ||
+            config.blueSize != contextBlueSize || config.alphaSize != contextAlphaSize)
+        {
+            continue;
+        }
+        // The GLX spec says that it is ok for a whole buffer to not be present
+        // however the Mesa Intel driver (and probably on other Mesa drivers)
+        // fails to make current when the Depth stencil doesn't exactly match the
+        // configuration.
+        bool hasSameDepthStencil =
+            config.depthSize == contextDepthSize && config.stencilSize == contextStencilSize;
+        bool hasNoDepthStencil = config.depthSize == 0 && config.stencilSize == 0;
+        if (!hasSameDepthStencil && (mIsMesa || !hasNoDepthStencil))
+        {
+            continue;
+        }
+
+        config.colorBufferType = EGL_RGB_BUFFER;
+        config.luminanceSize = 0;
+        config.alphaMaskSize = 0;
+
+        config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize;
+
+        // Multisample and accumulation buffers
+        int samples = mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES) : 0;
+        int sampleBuffers =
+            mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS) : 0;
+
+        int accumRedSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_RED_SIZE);
+        int accumGreenSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_GREEN_SIZE);
+        int accumBlueSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_BLUE_SIZE);
+        int accumAlphaSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_ALPHA_SIZE);
+
+        if (samples != contextSamples ||
+            sampleBuffers != contextSampleBuffers ||
+            accumRedSize != contextAccumRedSize ||
+            accumGreenSize != contextAccumGreenSize ||
+            accumBlueSize != contextAccumBlueSize ||
+            accumAlphaSize != contextAccumAlphaSize)
+        {
+            continue;
+        }
+
+        config.samples = samples;
+        config.sampleBuffers = sampleBuffers;
+
+        // Transparency
+        if (getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_TYPE) == GLX_TRANSPARENT_RGB)
+        {
+            config.transparentType = EGL_TRANSPARENT_RGB;
+            config.transparentRedValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_RED_VALUE);
+            config.transparentGreenValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_GREEN_VALUE);
+            config.transparentBlueValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_BLUE_VALUE);
+        }
+        else
+        {
+            config.transparentType = EGL_NONE;
+        }
+
+        // Pbuffer
+        config.maxPBufferWidth = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_WIDTH);
+        config.maxPBufferHeight = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_HEIGHT);
+        config.maxPBufferPixels = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_PIXELS);
+
+        // Caveat
+        config.configCaveat = EGL_NONE;
+
+        int caveat = getGLXFBConfigAttrib(glxConfig, GLX_CONFIG_CAVEAT);
+        if (caveat == GLX_SLOW_CONFIG)
+        {
+            config.configCaveat = EGL_SLOW_CONFIG;
+        }
+        else if (caveat == GLX_NON_CONFORMANT_CONFIG)
+        {
+            continue;
+        }
+
+        // Misc
+        config.level = getGLXFBConfigAttrib(glxConfig, GLX_LEVEL);
+
+        config.bindToTextureRGB = EGL_FALSE;
+        config.bindToTextureRGBA = EGL_FALSE;
+
+        int glxDrawable = getGLXFBConfigAttrib(glxConfig, GLX_DRAWABLE_TYPE);
+        config.surfaceType = 0 |
+            (glxDrawable & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0) |
+            (glxDrawable & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0) |
+            (glxDrawable & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0);
+
+        config.minSwapInterval = mMinSwapInterval;
+        config.maxSwapInterval = mMaxSwapInterval;
+
+        // TODO(cwallez) wildly guessing these formats, another TODO says they should be removed anyway
+        config.renderTargetFormat = GL_RGBA8;
+        config.depthStencilFormat = GL_DEPTH24_STENCIL8;
+
+        config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+        config.renderableType = config.conformant;
+
+        // TODO(cwallez) I have no idea what this is
+        config.matchNativePixmap = EGL_NONE;
+
+        config.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+
+        int id = configs.add(config);
+        configIdToGLXConfig[id] = glxConfig;
+    }
+
+    XFree(glxConfigs);
+
+    return configs;
+}
+
+bool DisplayGLX::testDeviceLost()
+{
+    if (mHasARBCreateContextRobustness)
+    {
+        return getRenderer()->getResetStatus() != GL_NO_ERROR;
+    }
+
+    return false;
+}
+
+egl::Error DisplayGLX::restoreLostDevice()
+{
+    return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayGLX::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    // There is no function in Xlib to check the validity of a Window directly.
+    // However a small number of functions used to obtain window information
+    // return a status code (0 meaning failure) and guarantee that they will
+    // fail if the window doesn't exist (the rational is that these function
+    // are used by window managers). Out of these function we use XQueryTree
+    // as it seems to be the simplest; a drawback is that it will allocate
+    // memory for the list of children, because we use a child window for
+    // WindowSurface.
+    Window root;
+    Window parent;
+    Window *children = nullptr;
+    unsigned nChildren;
+    int status = XQueryTree(mGLX.getDisplay(), window, &root, &parent, &children, &nChildren);
+    if (children)
+    {
+        XFree(children);
+    }
+    return status != 0;
+}
+
+std::string DisplayGLX::getVendorString() const
+{
+    // UNIMPLEMENTED();
+    return "";
+}
+
+egl::Error DisplayGLX::waitClient() const
+{
+    mGLX.waitGL();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayGLX::waitNative(EGLint engine,
+                                  egl::Surface *drawSurface,
+                                  egl::Surface *readSurface) const
+{
+    // eglWaitNative is used to notice the driver of changes in X11 for the current surface, such as
+    // changes of the window size. We use this event to update the child window of WindowSurfaceGLX
+    // to match its parent window's size.
+    // Handling eglWaitNative this way helps the application control when resize happens. This is
+    // important because drivers have a tendency to clobber the back buffer when the windows are
+    // resized. See http://crbug.com/326995
+    if (drawSurface != nullptr)
+    {
+        SurfaceGLX *glxDrawSurface = GetImplAs<SurfaceGLX>(drawSurface);
+        egl::Error error = glxDrawSurface->checkForResize();
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    if (readSurface != drawSurface && readSurface != nullptr)
+    {
+        SurfaceGLX *glxReadSurface = GetImplAs<SurfaceGLX>(readSurface);
+        egl::Error error = glxReadSurface->checkForResize();
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    // We still need to forward the resizing of the child window to the driver.
+    mGLX.waitX();
+    return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayGLX::syncXCommands() const
+{
+    if (mUsesNewXDisplay)
+    {
+        XSync(mGLX.getDisplay(), False);
+    }
+}
+
+void DisplayGLX::setSwapInterval(glx::Drawable drawable, SwapControlData *data)
+{
+    ASSERT(data != nullptr);
+
+    // TODO(cwallez) error checking?
+    if (mSwapControl == SwapControl::EXT)
+    {
+        // Prefer the EXT extension, it gives per-drawable swap intervals, which will
+        // minimize the number of driver calls.
+        if (data->maxSwapInterval < 0)
+        {
+            unsigned int maxSwapInterval = 0;
+            mGLX.queryDrawable(drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxSwapInterval);
+            data->maxSwapInterval = static_cast<int>(maxSwapInterval);
+        }
+
+        // When the egl configs were generated we had to guess what the max swap interval
+        // was because we didn't have a window to query it one (and that this max could
+        // depend on the monitor). This means that the target interval might be higher
+        // than the max interval and needs to be clamped.
+        const int realInterval = std::min(data->targetSwapInterval, data->maxSwapInterval);
+        if (data->currentSwapInterval != realInterval)
+        {
+            mGLX.swapIntervalEXT(drawable, realInterval);
+            data->currentSwapInterval = realInterval;
+        }
+    }
+    else if (mCurrentSwapInterval != data->targetSwapInterval)
+    {
+        // With the Mesa or SGI extensions we can still do per-drawable swap control
+        // manually but it is more expensive in number of driver calls.
+        if (mSwapControl == SwapControl::Mesa)
+        {
+            mGLX.swapIntervalMESA(data->targetSwapInterval);
+        }
+        else if (mSwapControl == SwapControl::SGI)
+        {
+            mGLX.swapIntervalSGI(data->targetSwapInterval);
+        }
+        mCurrentSwapInterval = data->targetSwapInterval;
+    }
+}
+
+bool DisplayGLX::isValidWindowVisualId(unsigned long visualId) const
+{
+    return mRequestedVisual == -1 || static_cast<unsigned long>(mRequestedVisual) == visualId;
+}
+
+const FunctionsGL *DisplayGLX::getFunctionsGL() const
+{
+    return mFunctionsGL;
+}
+
+void DisplayGLX::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+    outExtensions->createContextRobustness = mHasARBCreateContextRobustness;
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
+}
+
+void DisplayGLX::generateCaps(egl::Caps *outCaps) const
+{
+    outCaps->textureNPOT = true;
+}
+
+int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const
+{
+    int result;
+    mGLX.getFBConfigAttrib(config, attrib, &result);
+    return result;
+}
+
+egl::Error DisplayGLX::createContextAttribs(glx::FBConfig,
+                                            const Optional<gl::Version> &version,
+                                            int profileMask,
+                                            glx::Context *context) const
+{
+    std::vector<int> attribs;
+
+    if (mHasARBCreateContextRobustness)
+    {
+        attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+        attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB);
+    }
+
+    if (version.valid())
+    {
+        attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
+        attribs.push_back(version.value().major);
+
+        attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
+        attribs.push_back(version.value().minor);
+    }
+
+    if (profileMask != 0 && mHasARBCreateContextProfile)
+    {
+        attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
+        attribs.push_back(profileMask);
+    }
+
+    attribs.push_back(None);
+
+    // When creating a context with glXCreateContextAttribsARB, a variety of X11 errors can
+    // be generated. To prevent these errors from crashing our process, we simply ignore
+    // them and only look if GLXContext was created.
+    // Process all events before setting the error handler to avoid desynchronizing XCB instances
+    // (the error handler is NOT per-display).
+    XSync(mXDisplay, False);
+    auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
+    *context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data());
+    XSetErrorHandler(oldErrorHandler);
+
+    if (!*context)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
+    }
+    return egl::Error(EGL_SUCCESS);
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h b/src/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
new file mode 100644
index 0000000..cd542cc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayGLX.h: GLX implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_
+
+#include <string>
+#include <vector>
+
+#include "common/Optional.h"
+#include "libANGLE/renderer/gl/DisplayGL.h"
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+
+namespace rx
+{
+
+class FunctionsGLX;
+
+// State-tracking data for the swap control to allow DisplayGLX to remember per
+// drawable information for swap control.
+struct SwapControlData
+{
+    SwapControlData();
+
+    // Set by the drawable
+    int targetSwapInterval;
+
+    // DisplayGLX-side state-tracking
+    int maxSwapInterval;
+    int currentSwapInterval;
+};
+
+class DisplayGLX : public DisplayGL
+{
+  public:
+    DisplayGLX(const egl::DisplayState &state);
+    ~DisplayGLX() override;
+
+    egl::Error initialize(egl::Display *display) override;
+    void terminate() override;
+
+    SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+                                     EGLNativeWindowType window,
+                                     const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+                                      const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                               EGLenum buftype,
+                                               EGLClientBuffer clientBuffer,
+                                               const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+                                     NativePixmapType nativePixmap,
+                                     const egl::AttributeMap &attribs) override;
+
+    egl::ConfigSet generateConfigs() override;
+
+    bool testDeviceLost() override;
+    egl::Error restoreLostDevice() override;
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+    egl::Error getDevice(DeviceImpl **device) override;
+
+    std::string getVendorString() const override;
+
+    egl::Error waitClient() const override;
+    egl::Error waitNative(EGLint engine,
+                          egl::Surface *drawSurface,
+                          egl::Surface *readSurface) const override;
+
+    // Synchronizes with the X server, if the display has been opened by ANGLE.
+    // Calling this is required at the end of every functions that does buffered
+    // X calls (not for glX calls) otherwise there might be race conditions
+    // between the application's display and ANGLE's one.
+    void syncXCommands() const;
+
+    // Depending on the supported GLX extension, swap interval can be set
+    // globally or per drawable. This function will make sure the drawable's
+    // swap interval is the one required so that the subsequent swapBuffers
+    // acts as expected.
+    void setSwapInterval(glx::Drawable drawable, SwapControlData *data);
+
+    bool isValidWindowVisualId(unsigned long visualId) const;
+
+  private:
+    const FunctionsGL *getFunctionsGL() const override;
+
+    egl::Error initializeContext(glx::FBConfig config,
+                                 const egl::AttributeMap &eglAttributes,
+                                 glx::Context *context);
+
+    void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+    void generateCaps(egl::Caps *outCaps) const override;
+
+    int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const;
+    egl::Error createContextAttribs(glx::FBConfig,
+                                    const Optional<gl::Version> &version,
+                                    int profileMask,
+                                    glx::Context *context) const;
+
+    FunctionsGL *mFunctionsGL;
+
+    std::map<int, glx::FBConfig> configIdToGLXConfig;
+
+    EGLint mRequestedVisual;
+    glx::FBConfig mContextConfig;
+    glx::Context mContext;
+    // A pbuffer the context is current on during ANGLE initialization
+    glx::Pbuffer mDummyPbuffer;
+
+    bool mUsesNewXDisplay;
+    bool mIsMesa;
+    bool mHasMultisample;
+    bool mHasARBCreateContext;
+    bool mHasARBCreateContextProfile;
+    bool mHasARBCreateContextRobustness;
+    bool mHasEXTCreateContextES2Profile;
+
+    enum class SwapControl
+    {
+        Absent,
+        EXT,
+        Mesa,
+        SGI,
+    };
+    SwapControl mSwapControl;
+    int mMinSwapInterval;
+    int mMaxSwapInterval;
+    int mCurrentSwapInterval;
+
+    FunctionsGLX mGLX;
+    Display *mXDisplay;
+    egl::Display *mEGLDisplay;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md b/src/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md
new file mode 100644
index 0000000..2343ad0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md
@@ -0,0 +1,204 @@
+GLX Framebuffer Compatibility investigation
+===========================================
+
+In GLX and EGL, contexts are created with respect to a config that
+describes the type of surfaces they will be used to render to.
+Likewise surfaces are created with respect to a config and for
+a context to be able to render to a surface, both their configs
+must be compatible. Compatibility is losely described in both
+the GLX and EGL specs but the following is clear:
+ * In GLX the config's color buffer must have the same type, including
+RGBA vs. ColorIndex and the buffers must have the same depth, if they
+exist.
+ * In EGL the config's color buffer must have the same type and the
+buffers must have the same depth (not clear if it is only if they exist)
+
+Obviously the EGLconfig we will expose will have a one-to-one
+correspondance with GLXFBConfigs.
+
+Our EGL implementation uses a single OpenGL context to back all
+the EGLcontexts created by the application. Since our GL context
+and GLXContext are the same object but in two APIs, we will make
+the confusion and call the GLX context our backing context.
+
+The problem we have is that the the GLX context is created before
+the application can choose what type of context it wants to use,
+that means we have to expose EGLconfigs whose respective GLXFBConfigs
+are compatible with the GLXFBConfig of our GLX context; we also need
+to choose the GLXFBConfig of our GLX context so that it matches the
+most common needs of application.
+
+Choice of the GLX context GLXFBConfig
+-------------------------------------
+
+We decided that our GLX context's configuration must satisfy the following:
+ * Have a RGBA8 color buffer and D24S8 depth-stencil buffer which is what
+the vast majority of applications use.
+ * It must render in direct colors, i.e. not in a color indexed format.
+ * It must be double-buffered (see later)
+ * It must support rendering to all the types of GLX surfaces so that we can
+use it for all types of EGL surfaces
+ * It must have an associated visual ID so that we can use it with X, it seems
+like this would be strongly tied to it having the ```WINDOW_BIT``` set.
+ * We would like a conformant context.
+
+Study of compatible GLXFBConfigs
+--------------------------------
+
+When using the condition of compatibility defined in the GLX spec and filtering
+out the non-conformant GLXFBConfig we got the following list (see function
+```print_visual_attribs_short``` in [glxinfo's source code](http://cgit.freedesktop.org/mesa/demos/tree/src/xdemos/glxinfo.c)
+to understand how to read the table):
+
+```
+    visual  x   bf lv rg d st  colorbuffer  sr ax dp st accumbuffer  ms  cav
+  id dep cl sp  sz l  ci b ro  r  g  b  a F gb bf th cl  r  g  b  a ns b eat  Result
+----------------------------------------------------------------------------
+0x02e 24 tc  0  32  0 r  . .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Fail
+0x0e4 32 tc  0  32  0 r  . .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None BadMatch
+0x02c 24 tc  0  32  0 r  y .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Pass
+0x0e2 32 tc  0  32  0 r  y .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None BadMatch
+0x089 24 dc  0  32  0 r  . .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Fail
+0x087 24 dc  0  32  0 r  y .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Pass
+0x026 24 tc  0  32  0 r  . .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Fail
+0x0dc 32 tc  0  32  0 r  . .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None BadMatch
+0x024 24 tc  0  32  0 r  y .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Pass
+0x0da 32 tc  0  32  0 r  y .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None BadMatch
+0x081 24 dc  0  32  0 r  . .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Fail
+0x07f 24 dc  0  32  0 r  y .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Pass
+```
+
+The last column shows the result of trying to render on a window using the config,
+with a GLX context using config 0x024. The first thing we see is that BadMatch is
+thrown by the X server when creating the subwindow for rendering. This was because
+we didn't set the border pixel of the subwindow *shake fist at X11* (see this [StackOverflow question](http://stackoverflow.com/questions/3645632/how-to-create-a-window-with-a-bit-depth-of-32)).
+The result updated with this fix give:
+
+```
+    visual  x   bf lv rg d st  colorbuffer  sr ax dp st accumbuffer  ms  cav
+  id dep cl sp  sz l  ci b ro  r  g  b  a F gb bf th cl  r  g  b  a ns b eat
+----------------------------------------------------------------------------
+0x02e 24 tc  0  32  0 r  . .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Fail
+0x0e4 32 tc  0  32  0 r  . .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Fail
+0x02c 24 tc  0  32  0 r  y .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Pass
+0x0e2 32 tc  0  32  0 r  y .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Pass
+0x089 24 dc  0  32  0 r  . .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Fail
+0x087 24 dc  0  32  0 r  y .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None Pass
+0x026 24 tc  0  32  0 r  . .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Fail
+0x0dc 32 tc  0  32  0 r  . .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Fail
+0x024 24 tc  0  32  0 r  y .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Pass
+0x0da 32 tc  0  32  0 r  y .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Pass
+0x081 24 dc  0  32  0 r  . .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Fail
+0x07f 24 dc  0  32  0 r  y .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None Pass
+```
+
+From this we see that our rendering test passed if and only if the config was double
+buffered like 0x024 which is our GLX context config. The compatible configs are then:
+
+```
+    visual  x   bf lv rg d st  colorbuffer  sr ax dp st accumbuffer  ms  cav
+  id dep cl sp  sz l  ci b ro  r  g  b  a F gb bf th cl  r  g  b  a ns b eat
+----------------------------------------------------------------------------
+0x02c 24 tc  0  32  0 r  y .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None
+0x0e2 32 tc  0  32  0 r  y .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None
+0x087 24 dc  0  32  0 r  y .   8  8  8  8 .  s  4  0  0 16 16 16 16  0 0 None
+0x024 24 tc  0  32  0 r  y .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None
+0x0da 32 tc  0  32  0 r  y .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None
+0x07f 24 dc  0  32  0 r  y .   8  8  8  8 .  s  4 24  8 16 16 16 16  0 0 None
+```
+
+We can see two dimensions, with our without a depth-stencil buffer and with TrueColor
+or DirectColor. The depth-stencil will be useful to expose to application.
+
+More on double buffering
+------------------------
+The tests above show that double-buffered contexts are not compatible with single-
+buffered surfaces; however other tests show that single-buffered contexts are
+compatible with both single and double-buffered surfaces. The problem is that in
+that case, we can see some flickering even with double-buffered surfaces. If we
+can find a trick to avoid that flicker, then we would be able to expose single
+and double-buffered surfaces at the EGL level. Not exposing them isn't too much
+of a problem though as the vast majority of application want double-buffering.
+
+AMD and extra buffers
+---------------------
+As can be seen above, NVIDIA does not expose conformant context with multisampled
+buffers or non RGBA16 accumulation buffers. The behavior is different on AMD that
+exposes them as conformant, which gives the following list after filtering as
+explained above:
+
+```
+    visual  x   bf lv rg d st  colorbuffer  sr ax dp st accumbuffer  ms  cav
+  id dep cl sp  sz l  ci b ro  r  g  b  a F gb bf th cl  r  g  b  a ns b eat
+----------------------------------------------------------------------------
+0x023 24 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8 16 16 16 16  0 0 None
+0x027 24 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+0x02b 24 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  2 1 None
+0x02f 24 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  4 1 None
+0x03b 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8 16 16 16 16  0 0 None
+0x03f 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+0x043 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  2 1 None
+0x047 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  4 1 None
+```
+
+ANGLE's context is created using 0x027 and experimentation shows it is only compatible
+with 0x03f which is the only other config lacking both an accumulation buffer and a
+multisample buffer. The GLX spec seems to hint it should still work ("should have the
+same size, if they exist") but it doesn't work in this case. Filtering the configs to
+have the same multisample and accumulation buffers gives the following:
+
+```
+    visual  x   bf lv rg d st  colorbuffer  sr ax dp st accumbuffer  ms  cav
+  id dep cl sp  sz l  ci b ro  r  g  b  a F gb bf th cl  r  g  b  a ns b eat
+----------------------------------------------------------------------------
+0x027 24 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+0x03f 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+```
+
+Mesa Intel driver
+-----------------
+In GLX, a criterium for context and surface compatibility is that buffers
+should have the same depth, if they exist at all in the surface. This means
+that it should be possible to make a context with a D24S8 depth-stencil
+buffer to a surface without a depth-stencil buffer. This doesn't work on the
+Mesa Intel driver. The list before the workaround was the following, with
+0x020 being the fbconfig chosen for the context:
+
+```
+    visual  x   bf lv rg d st  colorbuffer  sr ax dp st accumbuffer  ms  cav
+  id dep cl sp  sz l  ci b ro  r  g  b  a F gb bf th cl  r  g  b  a ns b eat
+----------------------------------------------------------------------------
+0x020 24 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+0x021 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+0x08f 32 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+0x0d0 24 tc  0  32  0 r  y .   8  8  8  8 .  .  0  0  0  0  0  0  0  0 0 None
+0x0e2 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0  0  0  0  0  0  0  0 0 None
+0x0e9 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+```
+
+After the workaround that list becomes the following:
+
+```
+    visual  x   bf lv rg d st  colorbuffer  sr ax dp st accumbuffer  ms  cav
+  id dep cl sp  sz l  ci b ro  r  g  b  a F gb bf th cl  r  g  b  a ns b eat
+----------------------------------------------------------------------------
+0x020 24 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+0x021 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+0x08f 32 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+0x0e9 24 dc  0  32  0 r  y .   8  8  8  8 .  .  0 24  8  0  0  0  0  0 0 None
+```
+
+Future investigation
+--------------------
+All the non-conformant configs have a multisampled buffer, so it could be interesting
+to see if we can use them to expose another EGL extension.
+
+Finally this document is written with respect to a small number of drivers, before
+using the GLX EGL implementation in the wild it would be good to test it on other
+drivers and hardware.
+
+The drivers tested were:
+
+ - the proprietary NVIDIA driver
+ - the proprietary AMD driver
+ - the open source Intel (Broadwell) Mesa driver
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
new file mode 100644
index 0000000..4ec38dd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
@@ -0,0 +1,398 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsGLX.cpp: Implements the FunctionsGLX class.
+
+#define ANGLE_SKIP_GLX_DEFINES 1
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+#undef ANGLE_SKIP_GLX_DEFINES
+
+// We can only include glx.h in files which do not include ANGLE's GLES
+// headers, to avoid doubly-defined GLenum macros, typedefs, etc.
+#include <GL/glx.h>
+
+#include <dlfcn.h>
+#include <algorithm>
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/gl/glx/functionsglx_typedefs.h"
+
+namespace rx
+{
+
+void* FunctionsGLX::sLibHandle = nullptr;
+
+template<typename T>
+static bool GetProc(PFNGETPROCPROC getProc, T *member, const char *name)
+{
+    *member = reinterpret_cast<T>(getProc(name));
+    return *member != nullptr;
+}
+
+struct FunctionsGLX::GLXFunctionTable
+{
+    GLXFunctionTable()
+        : createContextPtr(nullptr),
+          destroyContextPtr(nullptr),
+          makeCurrentPtr(nullptr),
+          swapBuffersPtr(nullptr),
+          queryExtensionPtr(nullptr),
+          queryVersionPtr(nullptr),
+          getCurrentContextPtr(nullptr),
+          getCurrentDrawablePtr(nullptr),
+          waitXPtr(nullptr),
+          waitGLPtr(nullptr),
+          getClientStringPtr(nullptr),
+          queryExtensionsStringPtr(nullptr),
+          getFBConfigsPtr(nullptr),
+          chooseFBConfigPtr(nullptr),
+          getFBConfigAttribPtr(nullptr),
+          getVisualFromFBConfigPtr(nullptr),
+          createWindowPtr(nullptr),
+          destroyWindowPtr(nullptr),
+          createPbufferPtr(nullptr),
+          destroyPbufferPtr(nullptr),
+          queryDrawablePtr(nullptr),
+          createContextAttribsARBPtr(nullptr),
+          swapIntervalEXTPtr(nullptr),
+          swapIntervalMESAPtr(nullptr),
+          swapIntervalSGIPtr(nullptr)
+    {
+    }
+
+    // GLX 1.0
+    PFNGLXCREATECONTEXTPROC createContextPtr;
+    PFNGLXDESTROYCONTEXTPROC destroyContextPtr;
+    PFNGLXMAKECURRENTPROC makeCurrentPtr;
+    PFNGLXSWAPBUFFERSPROC swapBuffersPtr;
+    PFNGLXQUERYEXTENSIONPROC queryExtensionPtr;
+    PFNGLXQUERYVERSIONPROC queryVersionPtr;
+    PFNGLXGETCURRENTCONTEXTPROC getCurrentContextPtr;
+    PFNGLXGETCURRENTDRAWABLEPROC getCurrentDrawablePtr;
+    PFNGLXWAITXPROC waitXPtr;
+    PFNGLXWAITGLPROC waitGLPtr;
+
+    // GLX 1.1
+    PFNGLXGETCLIENTSTRINGPROC getClientStringPtr;
+    PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsStringPtr;
+
+    //GLX 1.3
+    PFNGLXGETFBCONFIGSPROC getFBConfigsPtr;
+    PFNGLXCHOOSEFBCONFIGPROC chooseFBConfigPtr;
+    PFNGLXGETFBCONFIGATTRIBPROC getFBConfigAttribPtr;
+    PFNGLXGETVISUALFROMFBCONFIGPROC getVisualFromFBConfigPtr;
+    PFNGLXCREATEWINDOWPROC createWindowPtr;
+    PFNGLXDESTROYWINDOWPROC destroyWindowPtr;
+    PFNGLXCREATEPBUFFERPROC createPbufferPtr;
+    PFNGLXDESTROYPBUFFERPROC destroyPbufferPtr;
+    PFNGLXQUERYDRAWABLEPROC queryDrawablePtr;
+
+    // GLX_ARB_create_context
+    PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARBPtr;
+
+    // GLX_EXT_swap_control
+    PFNGLXSWAPINTERVALEXTPROC swapIntervalEXTPtr;
+
+    // GLX_MESA_swap_control
+    PFNGLXSWAPINTERVALMESAPROC swapIntervalMESAPtr;
+
+    // GLX_SGI_swap_control
+    PFNGLXSWAPINTERVALSGIPROC swapIntervalSGIPtr;
+};
+
+FunctionsGLX::FunctionsGLX()
+  : majorVersion(0),
+    minorVersion(0),
+    mXDisplay(nullptr),
+    mXScreen(-1),
+    mFnPtrs(new GLXFunctionTable())
+{
+}
+
+FunctionsGLX::~FunctionsGLX()
+{
+    delete mFnPtrs;
+    terminate();
+}
+
+bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorString)
+{
+    terminate();
+    mXDisplay = xDisplay;
+    mXScreen = screen;
+
+#if !defined(ANGLE_LINK_GLX)
+    // Some OpenGL implementations can't handle having this library
+    // handle closed while there's any X window still open against
+    // which a GLXWindow was ever created.
+    if (!sLibHandle)
+    {
+        sLibHandle = dlopen("libGL.so.1", RTLD_NOW);
+        if (!sLibHandle)
+        {
+            *errorString = std::string("Could not dlopen libGL.so.1: ") + dlerror();
+            return false;
+        }
+    }
+
+    getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddress"));
+    if (!getProc)
+    {
+        getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddressARB"));
+    }
+    if (!getProc)
+    {
+        *errorString = "Could not retrieve glXGetProcAddress";
+        return false;
+    }
+#else
+    getProc = reinterpret_cast<PFNGETPROCPROC>(glXGetProcAddress);
+#endif
+
+#define GET_PROC_OR_ERROR(MEMBER, NAME) \
+    if (!GetProc(getProc, MEMBER, #NAME)) \
+    { \
+        *errorString = "Could not load GLX entry point " #NAME; \
+        return false; \
+    }
+#if !defined(ANGLE_LINK_GLX)
+#define GET_FNPTR_OR_ERROR(MEMBER, NAME) GET_PROC_OR_ERROR(MEMBER, NAME)
+#else
+#define GET_FNPTR_OR_ERROR(MEMBER, NAME) *MEMBER = NAME;
+#endif
+
+    // GLX 1.0
+    GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionPtr, glXQueryExtension);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->queryVersionPtr, glXQueryVersion);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentContextPtr, glXGetCurrentContext);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentDrawablePtr, glXGetCurrentDrawable);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->waitXPtr, glXWaitX);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL);
+
+    // GLX 1.1
+    GET_FNPTR_OR_ERROR(&mFnPtrs->getClientStringPtr, glXGetClientString);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionsStringPtr, glXQueryExtensionsString);
+
+    // Check we have a working GLX
+    {
+        int errorBase;
+        int eventBase;
+        if (!queryExtension(&errorBase, &eventBase))
+        {
+            *errorString = "GLX is not present.";
+            return false;
+        }
+    }
+
+    // Check we have a supported version of GLX
+    if (!queryVersion(&majorVersion, &minorVersion))
+    {
+        *errorString = "Could not query the GLX version.";
+        return false;
+    }
+    if (majorVersion != 1 || minorVersion < 3)
+    {
+        *errorString = "Unsupported GLX version (requires at least 1.3).";
+        return false;
+    }
+
+    const char *extensions = queryExtensionsString();
+    if (!extensions)
+    {
+        *errorString = "glXQueryExtensionsString returned NULL";
+        return false;
+    }
+    angle::SplitStringAlongWhitespace(extensions, &mExtensions);
+
+    // GLX 1.3
+    GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigsPtr, glXGetFBConfigs);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->chooseFBConfigPtr, glXChooseFBConfig);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigAttribPtr, glXGetFBConfigAttrib);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->getVisualFromFBConfigPtr, glXGetVisualFromFBConfig);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->createWindowPtr, glXCreateWindow);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->destroyWindowPtr, glXDestroyWindow);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->createPbufferPtr, glXCreatePbuffer);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPbufferPtr, glXDestroyPbuffer);
+    GET_FNPTR_OR_ERROR(&mFnPtrs->queryDrawablePtr, glXQueryDrawable);
+
+    // Extensions
+    if (hasExtension("GLX_ARB_create_context"))
+    {
+        GET_PROC_OR_ERROR(&mFnPtrs->createContextAttribsARBPtr, glXCreateContextAttribsARB);
+    }
+    if (hasExtension("GLX_EXT_swap_control"))
+    {
+        GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalEXTPtr, glXSwapIntervalEXT);
+    }
+    if (hasExtension("GLX_MESA_swap_control"))
+    {
+        GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalMESAPtr, glXSwapIntervalMESA);
+    }
+    if (hasExtension("GLX_SGI_swap_control"))
+    {
+        GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalSGIPtr, glXSwapIntervalSGI);
+    }
+
+#undef GET_FNPTR_OR_ERROR
+#undef GET_PROC_OR_ERROR
+
+    *errorString = "";
+    return true;
+}
+
+void FunctionsGLX::terminate()
+{
+}
+
+bool FunctionsGLX::hasExtension(const char *extension) const
+{
+    return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
+}
+
+Display *FunctionsGLX::getDisplay() const
+{
+    return mXDisplay;
+}
+
+int FunctionsGLX::getScreen() const
+{
+    return mXScreen;
+}
+
+// GLX functions
+
+// GLX 1.0
+glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const
+{
+    GLXContext shareCtx = reinterpret_cast<GLXContext>(share);
+    GLXContext context = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct);
+    return reinterpret_cast<glx::Context>(context);
+}
+void FunctionsGLX::destroyContext(glx::Context context) const
+{
+    GLXContext ctx = reinterpret_cast<GLXContext>(context);
+    mFnPtrs->destroyContextPtr(mXDisplay, ctx);
+}
+Bool FunctionsGLX::makeCurrent(glx::Drawable drawable, glx::Context context) const
+{
+    GLXContext ctx = reinterpret_cast<GLXContext>(context);
+    return mFnPtrs->makeCurrentPtr(mXDisplay, drawable, ctx);
+}
+void FunctionsGLX::swapBuffers(glx::Drawable drawable) const
+{
+    mFnPtrs->swapBuffersPtr(mXDisplay, drawable);
+}
+Bool FunctionsGLX::queryExtension(int *errorBase, int *event) const
+{
+    return mFnPtrs->queryExtensionPtr(mXDisplay, errorBase, event);
+}
+Bool FunctionsGLX::queryVersion(int *major, int *minor) const
+{
+    return mFnPtrs->queryVersionPtr(mXDisplay, major, minor);
+}
+glx::Context FunctionsGLX::getCurrentContext() const
+{
+    GLXContext context = mFnPtrs->getCurrentContextPtr();
+    return reinterpret_cast<glx::Context>(context);
+}
+glx::Drawable FunctionsGLX::getCurrentDrawable() const
+{
+    GLXDrawable drawable = mFnPtrs->getCurrentDrawablePtr();
+    return reinterpret_cast<glx::Drawable>(drawable);
+}
+void FunctionsGLX::waitX() const
+{
+    mFnPtrs->waitXPtr();
+}
+void FunctionsGLX::waitGL() const
+{
+    mFnPtrs->waitGLPtr();
+}
+
+// GLX 1.1
+const char *FunctionsGLX::getClientString(int name) const
+{
+    return mFnPtrs->getClientStringPtr(mXDisplay, name);
+}
+
+const char *FunctionsGLX::queryExtensionsString() const
+{
+    return mFnPtrs->queryExtensionsStringPtr(mXDisplay, mXScreen);
+}
+
+// GLX 1.4
+glx::FBConfig *FunctionsGLX::getFBConfigs(int *nElements) const
+{
+    GLXFBConfig *configs = mFnPtrs->getFBConfigsPtr(mXDisplay, mXScreen, nElements);
+    return reinterpret_cast<glx::FBConfig*>(configs);
+}
+glx::FBConfig *FunctionsGLX::chooseFBConfig(const int *attribList, int *nElements) const
+{
+    GLXFBConfig *configs = mFnPtrs->chooseFBConfigPtr(mXDisplay, mXScreen, attribList, nElements);
+    return reinterpret_cast<glx::FBConfig*>(configs);
+}
+int FunctionsGLX::getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const
+{
+    GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+    return mFnPtrs->getFBConfigAttribPtr(mXDisplay, cfg, attribute, value);
+}
+XVisualInfo *FunctionsGLX::getVisualFromFBConfig(glx::FBConfig config) const
+{
+    GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+    return mFnPtrs->getVisualFromFBConfigPtr(mXDisplay, cfg);
+}
+GLXWindow FunctionsGLX::createWindow(glx::FBConfig config, Window window, const int *attribList) const
+{
+    GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+    return mFnPtrs->createWindowPtr(mXDisplay, cfg, window, attribList);
+}
+void FunctionsGLX::destroyWindow(glx::Window window) const
+{
+    mFnPtrs->destroyWindowPtr(mXDisplay, window);
+}
+glx::Pbuffer FunctionsGLX::createPbuffer(glx::FBConfig config, const int *attribList) const
+{
+    GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+    return mFnPtrs->createPbufferPtr(mXDisplay, cfg, attribList);
+}
+void FunctionsGLX::destroyPbuffer(glx::Pbuffer pbuffer) const
+{
+    mFnPtrs->destroyPbufferPtr(mXDisplay, pbuffer);
+}
+void FunctionsGLX::queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const
+{
+    mFnPtrs->queryDrawablePtr(mXDisplay, drawable, attribute, value);
+}
+
+// GLX_ARB_create_context
+glx::Context FunctionsGLX::createContextAttribsARB(glx::FBConfig config, glx::Context shareContext, Bool direct, const int *attribList) const
+{
+    GLXContext shareCtx = reinterpret_cast<GLXContext>(shareContext);
+    GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+    GLXContext ctx = mFnPtrs->createContextAttribsARBPtr(mXDisplay, cfg, shareCtx, direct, attribList);
+    return reinterpret_cast<glx::Context>(ctx);
+}
+
+void FunctionsGLX::swapIntervalEXT(glx::Drawable drawable, int intervals) const
+{
+    mFnPtrs->swapIntervalEXTPtr(mXDisplay, drawable, intervals);
+}
+
+int FunctionsGLX::swapIntervalMESA(int intervals) const
+{
+    return mFnPtrs->swapIntervalMESAPtr(intervals);
+}
+
+int FunctionsGLX::swapIntervalSGI(int intervals) const
+{
+    return mFnPtrs->swapIntervalSGIPtr(intervals);
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h b/src/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h
new file mode 100644
index 0000000..98c2fef
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsGLX.h: Defines the FunctionsGLX class to load functions and data from GLX
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
+
+#include <string>
+#include <vector>
+
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+
+namespace rx
+{
+
+class FunctionsGLX
+{
+  public:
+    FunctionsGLX();
+    ~FunctionsGLX();
+
+    // Load data from GLX, can be called multiple times
+    bool initialize(Display *xDisplay, int screen, std::string *errorString);
+    void terminate();
+
+    bool hasExtension(const char *extension) const;
+    int majorVersion;
+    int minorVersion;
+
+    Display *getDisplay() const;
+    int getScreen() const;
+
+    PFNGETPROCPROC getProc;
+
+    // GLX 1.0
+    glx::Context createContext(XVisualInfo *visual, glx::Context share, bool direct) const;
+    void destroyContext(glx::Context context) const;
+    Bool makeCurrent(glx::Drawable drawable, glx::Context context) const;
+    void swapBuffers(glx::Drawable drawable) const;
+    Bool queryExtension(int *errorBase, int *event) const;
+    Bool queryVersion(int *major, int *minor) const;
+    glx::Context getCurrentContext() const;
+    glx::Drawable getCurrentDrawable() const;
+    void waitX() const;
+    void waitGL() const;
+
+    // GLX 1.1
+    const char *getClientString(int name) const;
+    const char *queryExtensionsString() const;
+
+    // GLX 1.3
+    glx::FBConfig *getFBConfigs(int *nElements) const;
+    glx::FBConfig *chooseFBConfig(const int *attribList, int *nElements) const;
+    int getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const;
+    XVisualInfo *getVisualFromFBConfig(glx::FBConfig config) const;
+    glx::Window createWindow(glx::FBConfig config, Window window, const int *attribList) const;
+    void destroyWindow(glx::Window window) const;
+    glx::Pbuffer createPbuffer(glx::FBConfig config, const int *attribList) const;
+    void destroyPbuffer(glx::Pbuffer pbuffer) const;
+    void queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const;
+
+    // GLX_ARB_create_context
+    glx::Context createContextAttribsARB(glx::FBConfig config, glx::Context shareContext, Bool direct, const int *attribList) const;
+
+    // GLX_EXT_swap_control
+    void swapIntervalEXT(glx::Drawable drawable, int interval) const;
+
+    // GLX_MESA_swap_control
+    int swapIntervalMESA(int interval) const;
+
+    // GLX_SGI_swap_control
+    int swapIntervalSGI(int interval) const;
+
+  private:
+    // So as to isolate GLX from angle we do not include angleutils.h and cannot
+    // use angle::NonCopyable so we replicated it here instead.
+    FunctionsGLX(const FunctionsGLX&) = delete;
+    void operator=(const FunctionsGLX&) = delete;
+
+    struct GLXFunctionTable;
+
+    static void *sLibHandle;
+    Display *mXDisplay;
+    int mXScreen;
+
+    GLXFunctionTable *mFnPtrs;
+    std::vector<std::string> mExtensions;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
new file mode 100644
index 0000000..57e2283
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PbufferSurfaceGLX.cpp: GLX implementation of egl::Surface for PBuffers
+
+#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+
+namespace rx
+{
+
+PbufferSurfaceGLX::PbufferSurfaceGLX(const egl::SurfaceState &state,
+                                     RendererGL *renderer,
+                                     EGLint width,
+                                     EGLint height,
+                                     bool largest,
+                                     const FunctionsGLX &glx,
+                                     glx::Context context,
+                                     glx::FBConfig fbConfig)
+    : SurfaceGLX(state, renderer),
+      mWidth(width),
+      mHeight(height),
+      mLargest(largest),
+      mGLX(glx),
+      mContext(context),
+      mFBConfig(fbConfig),
+      mPbuffer(0)
+{
+}
+
+PbufferSurfaceGLX::~PbufferSurfaceGLX()
+{
+    if (mPbuffer)
+    {
+        mGLX.destroyPbuffer(mPbuffer);
+    }
+}
+
+egl::Error PbufferSurfaceGLX::initialize(const DisplayImpl *displayImpl)
+{
+    // Avoid creating 0-sized PBuffers as it fails on the Intel Mesa driver
+    // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we
+    // use (w, 1) or (1, h) instead.
+    int width = std::max(1, static_cast<int>(mWidth));
+    int height = std::max(1, static_cast<int>(mHeight));
+
+    const int attribs[] =
+    {
+        GLX_PBUFFER_WIDTH, width,
+        GLX_PBUFFER_HEIGHT, height,
+        GLX_LARGEST_PBUFFER, mLargest,
+        None
+    };
+
+    mPbuffer = mGLX.createPbuffer(mFBConfig, attribs);
+    if (!mPbuffer)
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to create a native GLX pbuffer.");
+    }
+
+    if (mLargest)
+    {
+        mGLX.queryDrawable(mPbuffer, GLX_WIDTH, &mWidth);
+        mGLX.queryDrawable(mPbuffer, GLX_HEIGHT, &mHeight);
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::makeCurrent()
+{
+    if (mGLX.makeCurrent(mPbuffer, mContext) != True)
+    {
+        return egl::Error(EGL_BAD_DISPLAY);
+    }
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::swap(const DisplayImpl *displayImpl)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::releaseTexImage(EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+void PbufferSurfaceGLX::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint PbufferSurfaceGLX::getWidth() const
+{
+    return mWidth;
+}
+
+EGLint PbufferSurfaceGLX::getHeight() const
+{
+    return mHeight;
+}
+
+EGLint PbufferSurfaceGLX::isPostSubBufferSupported() const
+{
+    UNIMPLEMENTED();
+    return EGL_FALSE;
+}
+
+EGLint PbufferSurfaceGLX::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+
+egl::Error PbufferSurfaceGLX::checkForResize()
+{
+    // The size of pbuffers never change
+    return egl::Error(EGL_SUCCESS);
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h b/src/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
new file mode 100644
index 0000000..cf390e5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PBufferSurfaceGLX.h: GLX implementation of egl::Surface for PBuffers
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_
+
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+#include "libANGLE/renderer/gl/glx/SurfaceGLX.h"
+
+namespace rx
+{
+
+class FunctionsGLX;
+
+class PbufferSurfaceGLX : public SurfaceGLX
+{
+  public:
+    PbufferSurfaceGLX(const egl::SurfaceState &state,
+                      RendererGL *renderer,
+                      EGLint width,
+                      EGLint height,
+                      bool largest,
+                      const FunctionsGLX &glx,
+                      glx::Context context,
+                      glx::FBConfig fbConfig);
+    ~PbufferSurfaceGLX() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    egl::Error makeCurrent() override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+    egl::Error checkForResize() override;
+
+  private:
+    unsigned mWidth;
+    unsigned mHeight;
+    bool mLargest;
+
+    const FunctionsGLX &mGLX;
+    glx::Context mContext;
+    glx::FBConfig mFBConfig;
+    glx::Pbuffer mPbuffer;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h b/src/third_party/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h
new file mode 100644
index 0000000..813516e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SurfaceGLX.h: common interface for GLX surfaces
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+namespace rx
+{
+
+class SurfaceGLX : public SurfaceGL
+{
+  public:
+    SurfaceGLX(const egl::SurfaceState &state, RendererGL *renderer) : SurfaceGL(state, renderer) {}
+
+    virtual egl::Error checkForResize() = 0;
+};
+}
+
+#endif  // LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
new file mode 100644
index 0000000..c357f9d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
@@ -0,0 +1,244 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowSurfaceGLX.cpp: GLX implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"
+
+#include "common/debug.h"
+
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+
+namespace rx
+{
+
+static int IgnoreX11Errors(Display *, XErrorEvent *)
+{
+    return 0;
+}
+
+WindowSurfaceGLX::WindowSurfaceGLX(const egl::SurfaceState &state,
+                                   const FunctionsGLX &glx,
+                                   DisplayGLX *glxDisplay,
+                                   RendererGL *renderer,
+                                   Window window,
+                                   Display *display,
+                                   glx::Context context,
+                                   glx::FBConfig fbConfig)
+    : SurfaceGLX(state, renderer),
+      mParent(window),
+      mWindow(0),
+      mDisplay(display),
+      mGLX(glx),
+      mGLXDisplay(glxDisplay),
+      mContext(context),
+      mFBConfig(fbConfig),
+      mGLXWindow(0)
+{
+}
+
+WindowSurfaceGLX::~WindowSurfaceGLX()
+{
+    if (mGLXWindow)
+    {
+        mGLX.destroyWindow(mGLXWindow);
+    }
+
+    if (mWindow)
+    {
+        // When destroying the window, it may happen that the window has already been
+        // destroyed by the application (this happens in Chromium). There is no way to
+        // atomically check that a window exists and to destroy it so instead we call
+        // XDestroyWindow, ignoring any errors.
+        auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
+        XDestroyWindow(mDisplay, mWindow);
+        XSync(mDisplay, False);
+        XSetErrorHandler(oldErrorHandler);
+    }
+
+    mGLXDisplay->syncXCommands();
+}
+
+egl::Error WindowSurfaceGLX::initialize(const DisplayImpl *displayImpl)
+{
+    // Check that the window's visual ID is valid, as part of the AMGLE_x11_visual
+    // extension.
+    {
+        XWindowAttributes windowAttributes;
+        XGetWindowAttributes(mDisplay, mParent, &windowAttributes);
+        unsigned long visualId = windowAttributes.visual->visualid;
+
+        if (!mGLXDisplay->isValidWindowVisualId(visualId))
+        {
+            return egl::Error(EGL_BAD_MATCH,
+                              "The visual of native_window doesn't match the visual given with "
+                              "ANGLE_X11_VISUAL_ID");
+        }
+    }
+
+    // The visual of the X window, GLX window and GLX context must match,
+    // however we received a user-created window that can have any visual
+    // and wouldn't work with our GLX context. To work in all cases, we
+    // create a child window with the right visual that covers all of its
+    // parent.
+    XVisualInfo *visualInfo = mGLX.getVisualFromFBConfig(mFBConfig);
+    if (!visualInfo)
+    {
+        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the XVisualInfo for the child window.");
+    }
+    Visual* visual = visualInfo->visual;
+
+    if (!getWindowDimensions(mParent, &mParentWidth, &mParentHeight))
+    {
+        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the parent window's dimensions.");
+    }
+
+    // The depth, colormap and visual must match otherwise we get a X error
+    // so we specify the colormap attribute. Also we do not want the window
+    // to be taken into account for input so we specify the event and
+    // do-not-propagate masks to 0 (the defaults). Finally we specify the
+    // border pixel attribute so that we can use a different visual depth
+    // than our parent (seems like X uses that as a condition to render
+    // the subwindow in a different buffer)
+    XSetWindowAttributes attributes;
+    unsigned long attributeMask = CWColormap | CWBorderPixel;
+
+    Colormap colormap = XCreateColormap(mDisplay, mParent, visual, AllocNone);
+    if(!colormap)
+    {
+        XFree(visualInfo);
+        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to create the Colormap for the child window.");
+    }
+    attributes.colormap = colormap;
+    attributes.border_pixel = 0;
+
+    //TODO(cwallez) set up our own error handler to see if the call failed
+    mWindow = XCreateWindow(mDisplay, mParent, 0, 0, mParentWidth, mParentHeight,
+                            0, visualInfo->depth, InputOutput, visual, attributeMask, &attributes);
+    mGLXWindow = mGLX.createWindow(mFBConfig, mWindow, nullptr);
+
+    XMapWindow(mDisplay, mWindow);
+    XFlush(mDisplay);
+
+    XFree(visualInfo);
+    XFreeColormap(mDisplay, colormap);
+
+    mGLXDisplay->syncXCommands();
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::makeCurrent()
+{
+    if (mGLX.makeCurrent(mGLXWindow, mContext) != True)
+    {
+        return egl::Error(EGL_BAD_DISPLAY);
+    }
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::swap(const DisplayImpl *displayImpl)
+{
+    // We need to swap before resizing as some drivers clobber the back buffer
+    // when the window is resized.
+    mGLXDisplay->setSwapInterval(mGLXWindow, &mSwapControl);
+    mGLX.swapBuffers(mGLXWindow);
+
+    egl::Error error = checkForResize();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::releaseTexImage(EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+void WindowSurfaceGLX::setSwapInterval(EGLint interval)
+{
+    mSwapControl.targetSwapInterval = interval;
+}
+
+EGLint WindowSurfaceGLX::getWidth() const
+{
+    // The size of the window is always the same as the cached size of its parent.
+    return mParentWidth;
+}
+
+EGLint WindowSurfaceGLX::getHeight() const
+{
+    // The size of the window is always the same as the cached size of its parent.
+    return mParentHeight;
+}
+
+EGLint WindowSurfaceGLX::isPostSubBufferSupported() const
+{
+    UNIMPLEMENTED();
+    return EGL_FALSE;
+}
+
+EGLint WindowSurfaceGLX::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+
+egl::Error WindowSurfaceGLX::checkForResize()
+{
+    // TODO(cwallez) set up our own error handler to see if the call failed
+    unsigned int newParentWidth, newParentHeight;
+    if (!getWindowDimensions(mParent, &newParentWidth, &newParentHeight))
+    {
+        return egl::Error(EGL_BAD_CURRENT_SURFACE,
+                          "Failed to retrieve the size of the parent window.");
+    }
+
+    if (mParentWidth != newParentWidth || mParentHeight != newParentHeight)
+    {
+        mParentWidth  = newParentWidth;
+        mParentHeight = newParentHeight;
+
+        mGLX.waitGL();
+        XResizeWindow(mDisplay, mWindow, mParentWidth, mParentHeight);
+        mGLX.waitX();
+        XSync(mDisplay, False);
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+bool WindowSurfaceGLX::getWindowDimensions(Window window, unsigned int *width, unsigned int *height) const
+{
+    Window root;
+    int x, y;
+    unsigned int border, depth;
+    return XGetGeometry(mDisplay, window, &root, &x, &y, width, height, &border, &depth) != 0;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h b/src/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
new file mode 100644
index 0000000..00515cc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowSurfaceGLX.h: GLX implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
+
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+#include "libANGLE/renderer/gl/glx/SurfaceGLX.h"
+
+namespace rx
+{
+
+class DisplayGLX;
+class FunctionsGLX;
+
+class WindowSurfaceGLX : public SurfaceGLX
+{
+  public:
+    WindowSurfaceGLX(const egl::SurfaceState &state,
+                     const FunctionsGLX &glx,
+                     DisplayGLX *glxDisplay,
+                     RendererGL *renderer,
+                     Window window,
+                     Display *display,
+                     glx::Context context,
+                     glx::FBConfig fbConfig);
+    ~WindowSurfaceGLX() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    egl::Error makeCurrent() override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+    egl::Error checkForResize() override;
+
+  private:
+    bool getWindowDimensions(Window window, unsigned int *width, unsigned int *height) const;
+
+    Window mParent;
+    unsigned int mParentWidth, mParentHeight;
+    Window mWindow;
+    Display *mDisplay;
+
+    const FunctionsGLX &mGLX;
+    DisplayGLX *mGLXDisplay;
+
+    glx::Context mContext;
+    glx::FBConfig mFBConfig;
+    glx::Window mGLXWindow;
+
+    SwapControlData mSwapControl;
+};
+
+}  // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h b/src/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h
new file mode 100644
index 0000000..b0ba033
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// functionsglx_typedefs.h: Typedefs of GLX functions.
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
+
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+
+namespace rx
+{
+
+// Only the functions of GLX 1.2 and earlier need to be typdefed; the other
+// functions are already typedefed in glx.h
+
+// GLX 1.0
+typedef XVisualInfo *(*PFNGLXCHOOSEVISUALPROC) (Display *dpy, int screen, int *attribList);
+typedef GLXContext (*PFNGLXCREATECONTEXTPROC) (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+typedef void (*PFNGLXDESTROYCONTEXTPROC) (Display *dpy, GLXContext ctx);
+typedef Bool (*PFNGLXMAKECURRENTPROC) (Display *dpy, GLXDrawable drawable, GLXContext ctx);
+typedef void (*PFNGLXCOPYCONTEXTPROC) (Display *dpy, GLXContext src, GLXContext dst, unsigned long mask);
+typedef void (*PFNGLXSWAPBUFFERSPROC) (Display *dpy, GLXDrawable drawable);
+typedef GLXPixmap (*PFNGLXCREATEGLXPIXMAPPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap);
+typedef void (*PFNGLXDESTROYGLXPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);
+typedef Bool (*PFNGLXQUERYEXTENSIONPROC) (Display *dpy, int *errorb, int *event);
+typedef Bool (*PFNGLXQUERYVERSIONPROC) (Display *dpy, int *maj, int *min);
+typedef Bool (*PFNGLXISDIRECTPROC) (Display *dpy, GLXContext ctx);
+typedef int (*PFNGLXGETCONFIGPROC) (Display *dpy, XVisualInfo *visual, int attrib, int *value);
+typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) ();
+typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) ();
+typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) ();
+typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) ();
+typedef void (*PFNGLXWAITGLPROC) ();
+typedef void (*PFNGLXWAITXPROC) ();
+typedef void (*PFNGLXUSEXFONT) (Font font, int first, int count, int list);
+
+// GLX 1.1
+typedef const char *(*PFNGLXQUERYEXTENSIONSSTRINGPROC) (Display *dpy, int screen);
+typedef const char *(*PFNGLXQUERYSERVERSTRINGPROC) (Display *dpy, int screen, int name);
+typedef const char *(*PFNGLXGETCLIENTSTRINGPROC) (Display *dpy, int name);
+
+
+// GLX 1.2
+typedef Display *(*PFNGLXGETCURRENTDISPLAYPROC) ();
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h b/src/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
new file mode 100644
index 0000000..3ffb609
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
@@ -0,0 +1,190 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// platform_glx.h: Includes specific to GLX.
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
+
+#if !defined(ANGLE_SKIP_GLX_DEFINES)
+// GLX 1.0
+#define GLX_USE_GL 1
+#define GLX_BUFFER_SIZE 2
+#define GLX_LEVEL 3
+#define GLX_RGBA 4
+#define GLX_DOUBLEBUFFER 5
+#define GLX_STEREO 6
+#define GLX_AUX_BUFFERS 7
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_STENCIL_SIZE 13
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_ALPHA_SIZE 17
+
+#define GLX_BAD_SCREEN 1
+#define GLX_BAD_ATTRIBUTE 2
+#define GLX_NO_EXTENSION 3
+#define GLX_BAD_VISUAL 4
+#define GLX_BAD_CONTEXT 5
+#define GLX_BAD_VALUE 6
+#define GLX_BAD_ENUM 7
+
+// GLX 1.1
+#define GLX_VENDOR 1
+#define GLX_VERSION 2
+#define GLX_EXTENSIONS 3
+
+// GLX 1.3
+#define GLX_CONFIG_CAVEAT 0x20
+#define GLX_DONT_CARE 0xFFFFFFFF
+#define GLX_X_VISUAL_TYPE 0x22
+#define GLX_TRANSPARENT_TYPE 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define GLX_TRANSPARENT_RED_VALUE 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_PIXMAP_BIT 0x00000002
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_AUX_BUFFERS_BIT 0x00000010
+#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define GLX_DEPTH_BUFFER_BIT 0x00000020
+#define GLX_STENCIL_BUFFER_BIT 0x00000040
+#define GLX_ACCUM_BUFFER_BIT 0x00000080
+#define GLX_NONE 0x8000
+#define GLX_SLOW_CONFIG 0x8001
+#define GLX_TRUE_COLOR 0x8002
+#define GLX_DIRECT_COLOR 0x8003
+#define GLX_PSEUDO_COLOR 0x8004
+#define GLX_STATIC_COLOR 0x8005
+#define GLX_GRAY_SCALE 0x8006
+#define GLX_STATIC_GRAY 0x8007
+#define GLX_TRANSPARENT_RGB 0x8008
+#define GLX_TRANSPARENT_INDEX 0x8009
+#define GLX_VISUAL_ID 0x800B
+#define GLX_SCREEN 0x800C
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_X_RENDERABLE 0x8012
+#define GLX_FBCONFIG_ID 0x8013
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_COLOR_INDEX_TYPE 0x8015
+#define GLX_MAX_PBUFFER_WIDTH 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define GLX_MAX_PBUFFER_PIXELS 0x8018
+#define GLX_PRESERVED_CONTENTS 0x801B
+#define GLX_LARGEST_PBUFFER 0x801C
+#define GLX_WIDTH 0x801D
+#define GLX_HEIGHT 0x801E
+#define GLX_EVENT_MASK 0x801F
+#define GLX_DAMAGED 0x8020
+#define GLX_SAVED 0x8021
+#define GLX_WINDOW 0x8022
+#define GLX_PBUFFER 0x8023
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
+
+// GLX 1.4
+#define GLX_SAMPLE_BUFFERS 0x186a0
+#define GLX_SAMPLES 0x186a1
+
+// GLX_ARB_create_context
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+
+// GLX_ARB_create_context_profile
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+// GLX_ARB_create_context_robustness
+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
+
+// GLX_EXT_create_context_es2_profile
+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
+// GLX_EXT_texture_from_pixmap
+#define GLX_TEXTURE_1D_BIT_EXT 0x00000001
+#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
+#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
+#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
+#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1
+#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2
+#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3
+#define GLX_Y_INVERTED_EXT 0x20D4
+#define GLX_TEXTURE_FORMAT_EXT 0x20D5
+#define GLX_TEXTURE_TARGET_EXT 0x20D6
+#define GLX_MIPMAP_TEXTURE_EXT 0x20D7
+#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8
+#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9
+#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA
+#define GLX_TEXTURE_1D_EXT 0x20DB
+#define GLX_TEXTURE_2D_EXT 0x20DC
+#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD
+#define GLX_FRONT_LEFT_EXT 0x20DE
+#define GLX_FRONT_RIGHT_EXT 0x20DF
+#define GLX_BACK_LEFT_EXT 0x20E0
+#define GLX_BACK_RIGHT_EXT 0x20E1
+#define GLX_FRONT_EXT 0x20DE
+#define GLX_BACK_EXT 0x20E0
+#define GLX_AUX0_EXT 0x20E2
+#define GLX_AUX1_EXT 0x20E3
+#define GLX_AUX2_EXT 0x20E4
+#define GLX_AUX3_EXT 0x20E5
+#define GLX_AUX4_EXT 0x20E6
+#define GLX_AUX5_EXT 0x20E7
+#define GLX_AUX6_EXT 0x20E8
+#define GLX_AUX7_EXT 0x20E9
+#define GLX_AUX8_EXT 0x20EA
+#define GLX_AUX9_EXT 0x20EB
+
+// GLX_EXT_swap_control
+#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+#endif // !defined(ANGLE_SKIP_GLX_DEFINES)
+
+// GLX typedefs depend on the X headers
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+#include <X11/Xutil.h>
+
+// GLX typedefs
+namespace glx
+{
+
+typedef void *Context;
+typedef void *FBConfig;
+typedef XID FBConfigID;
+typedef XID ContextID;
+typedef XID Window;
+typedef XID Pbuffer;
+typedef XID Pixmap;
+typedef XID Drawable;
+
+}
+
+typedef void* (*PFNGETPROCPROC) (const char *name);
+
+#endif // LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
new file mode 100644
index 0000000..68ead9a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -0,0 +1,1112 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// renderergl_utils.cpp: Conversion functions and other utility routines
+// specific to the OpenGL renderer.
+
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+#include <limits>
+
+#include "common/mathutil.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/QueryGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+
+#include <algorithm>
+#include <sstream>
+
+using angle::CheckedNumeric;
+
+namespace rx
+{
+VendorID GetVendorID(const FunctionsGL *functions)
+{
+    std::string nativeVendorString(reinterpret_cast<const char *>(functions->getString(GL_VENDOR)));
+    if (nativeVendorString.find("Intel") != std::string::npos)
+    {
+        return VENDOR_ID_INTEL;
+    }
+    else if (nativeVendorString.find("NVIDIA") != std::string::npos)
+    {
+        return VENDOR_ID_NVIDIA;
+    }
+    else if (nativeVendorString.find("ATI") != std::string::npos ||
+             nativeVendorString.find("AMD") != std::string::npos)
+    {
+        return VENDOR_ID_AMD;
+    }
+    else if (nativeVendorString.find("Qualcomm") != std::string::npos)
+    {
+        return VENDOR_ID_QUALCOMM;
+    }
+    else
+    {
+        return VENDOR_ID_UNKNOWN;
+    }
+}
+
+namespace nativegl_gl
+{
+
+static bool MeetsRequirements(const FunctionsGL *functions, const nativegl::SupportRequirement &requirements)
+{
+    for (const std::string &extension : requirements.requiredExtensions)
+    {
+        if (!functions->hasExtension(extension))
+        {
+            return false;
+        }
+    }
+
+    if (functions->version >= requirements.version)
+    {
+        return true;
+    }
+    else if (!requirements.versionExtensions.empty())
+    {
+        for (const std::string &extension : requirements.versionExtensions)
+        {
+            if (!functions->hasExtension(extension))
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, GLenum internalFormat)
+{
+    gl::TextureCaps textureCaps;
+
+    const nativegl::InternalFormat &formatInfo = nativegl::GetInternalFormatInfo(internalFormat, functions->standard);
+    textureCaps.texturable = MeetsRequirements(functions, formatInfo.texture);
+    textureCaps.filterable = textureCaps.texturable && MeetsRequirements(functions, formatInfo.filter);
+    textureCaps.renderable = MeetsRequirements(functions, formatInfo.framebufferAttachment);
+
+    // glGetInternalformativ is not available until version 4.2 but may be available through the 3.0
+    // extension GL_ARB_internalformat_query
+    if (textureCaps.renderable && functions->getInternalformativ)
+    {
+        GLint numSamples = 0;
+        functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &numSamples);
+
+        if (numSamples > 0)
+        {
+            std::vector<GLint> samples(numSamples);
+            functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_SAMPLES,
+                                           static_cast<GLsizei>(samples.size()), &samples[0]);
+            for (size_t sampleIndex = 0; sampleIndex < samples.size(); sampleIndex++)
+            {
+                textureCaps.sampleCounts.insert(samples[sampleIndex]);
+            }
+        }
+    }
+
+    return textureCaps;
+}
+
+static GLint QuerySingleGLInt(const FunctionsGL *functions, GLenum name)
+{
+    GLint result = 0;
+    functions->getIntegerv(name, &result);
+    return result;
+}
+
+static GLint QuerySingleIndexGLInt(const FunctionsGL *functions, GLenum name, GLuint index)
+{
+    GLint result;
+    functions->getIntegeri_v(name, index, &result);
+    return result;
+}
+
+static GLint QueryGLIntRange(const FunctionsGL *functions, GLenum name, size_t index)
+{
+    GLint result[2] = {};
+    functions->getIntegerv(name, result);
+    return result[index];
+}
+
+static GLint64 QuerySingleGLInt64(const FunctionsGL *functions, GLenum name)
+{
+    GLint64 result = 0;
+    functions->getInteger64v(name, &result);
+    return result;
+}
+
+static GLfloat QuerySingleGLFloat(const FunctionsGL *functions, GLenum name)
+{
+    GLfloat result = 0.0f;
+    functions->getFloatv(name, &result);
+    return result;
+}
+
+static GLfloat QueryGLFloatRange(const FunctionsGL *functions, GLenum name, size_t index)
+{
+    GLfloat result[2] = {};
+    functions->getFloatv(name, result);
+    return result[index];
+}
+
+static gl::TypePrecision QueryTypePrecision(const FunctionsGL *functions, GLenum shaderType, GLenum precisionType)
+{
+    gl::TypePrecision precision;
+    functions->getShaderPrecisionFormat(shaderType, precisionType, precision.range.data(),
+                                        &precision.precision);
+    return precision;
+}
+
+static GLint QueryQueryValue(const FunctionsGL *functions, GLenum target, GLenum name)
+{
+    GLint result;
+    functions->getQueryiv(target, name, &result);
+    return result;
+}
+
+static void LimitVersion(gl::Version *curVersion, const gl::Version &maxVersion)
+{
+    if (*curVersion >= maxVersion)
+    {
+        *curVersion = maxVersion;
+    }
+}
+
+void GenerateCaps(const FunctionsGL *functions,
+                  const WorkaroundsGL &workarounds,
+                  gl::Caps *caps,
+                  gl::TextureCapsMap *textureCapsMap,
+                  gl::Extensions *extensions,
+                  gl::Version *maxSupportedESVersion)
+{
+    // Texture format support checks
+    const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
+    for (GLenum internalFormat : allFormats)
+    {
+        gl::TextureCaps textureCaps = GenerateTextureFormatCaps(functions, internalFormat);
+        textureCapsMap->insert(internalFormat, textureCaps);
+
+        if (gl::GetSizedInternalFormatInfo(internalFormat).compressed)
+        {
+            caps->compressedTextureFormats.push_back(internalFormat);
+        }
+    }
+
+    // Start by assuming ES3.1 support and work down
+    *maxSupportedESVersion = gl::Version(3, 1);
+
+    // Table 6.28, implementation dependent values
+    if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->hasGLExtension("GL_ARB_ES3_compatibility") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxElementIndex = QuerySingleGLInt64(functions, GL_MAX_ELEMENT_INDEX);
+    }
+    else
+    {
+        // Doesn't affect ES3 support, can use a pre-defined limit
+        caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+    }
+
+    if (functions->isAtLeastGL(gl::Version(1, 2)) ||
+        functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_texture_3D"))
+    {
+        caps->max3DTextureSize = QuerySingleGLInt(functions, GL_MAX_3D_TEXTURE_SIZE);
+    }
+    else
+    {
+        // Can't support ES3 without 3D textures
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    caps->max2DTextureSize = QuerySingleGLInt(functions, GL_MAX_TEXTURE_SIZE); // GL 1.0 / ES 2.0
+    caps->maxCubeMapTextureSize = QuerySingleGLInt(functions, GL_MAX_CUBE_MAP_TEXTURE_SIZE); // GL 1.3 / ES 2.0
+
+    if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_texture_array") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxArrayTextureLayers = QuerySingleGLInt(functions, GL_MAX_ARRAY_TEXTURE_LAYERS);
+    }
+    else
+    {
+        // Can't support ES3 without array textures
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(1, 5)) || functions->hasGLExtension("GL_EXT_texture_lod_bias") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxLODBias = QuerySingleGLFloat(functions, GL_MAX_TEXTURE_LOD_BIAS);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_object") ||
+        functions->isAtLeastGLES(gl::Version(2, 0)))
+    {
+        caps->maxRenderbufferSize = QuerySingleGLInt(functions, GL_MAX_RENDERBUFFER_SIZE);
+        caps->maxColorAttachments = QuerySingleGLInt(functions, GL_MAX_COLOR_ATTACHMENTS);
+    }
+    else
+    {
+        // Can't support ES2 without framebuffers and renderbuffers
+        LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(2, 0)) || functions->hasGLExtension("ARB_draw_buffers") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_draw_buffers"))
+    {
+        caps->maxDrawBuffers = QuerySingleGLInt(functions, GL_MAX_DRAW_BUFFERS);
+    }
+    else
+    {
+        // Framebuffer is required to have at least one drawbuffer even if the extension is not
+        // supported
+        caps->maxDrawBuffers = 1;
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    caps->maxViewportWidth = QueryGLIntRange(functions, GL_MAX_VIEWPORT_DIMS, 0); // GL 1.0 / ES 2.0
+    caps->maxViewportHeight = QueryGLIntRange(functions, GL_MAX_VIEWPORT_DIMS, 1); // GL 1.0 / ES 2.0
+
+    if (functions->standard == STANDARD_GL_DESKTOP &&
+        (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+    {
+        // Desktop GL core profile deprecated the GL_ALIASED_POINT_SIZE_RANGE query.  Use
+        // GL_POINT_SIZE_RANGE instead.
+        caps->minAliasedPointSize = QueryGLFloatRange(functions, GL_POINT_SIZE_RANGE, 0);
+        caps->maxAliasedPointSize = QueryGLFloatRange(functions, GL_POINT_SIZE_RANGE, 1);
+    }
+    else
+    {
+        caps->minAliasedPointSize = QueryGLFloatRange(functions, GL_ALIASED_POINT_SIZE_RANGE, 0);
+        caps->maxAliasedPointSize = QueryGLFloatRange(functions, GL_ALIASED_POINT_SIZE_RANGE, 1);
+    }
+
+    caps->minAliasedLineWidth = QueryGLFloatRange(functions, GL_ALIASED_LINE_WIDTH_RANGE, 0); // GL 1.2 / ES 2.0
+    caps->maxAliasedLineWidth = QueryGLFloatRange(functions, GL_ALIASED_LINE_WIDTH_RANGE, 1); // GL 1.2 / ES 2.0
+
+    // Table 6.29, implementation dependent values (cont.)
+    if (functions->isAtLeastGL(gl::Version(1, 2)) ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxElementsIndices = QuerySingleGLInt(functions, GL_MAX_ELEMENTS_INDICES);
+        caps->maxElementsVertices = QuerySingleGLInt(functions, GL_MAX_ELEMENTS_VERTICES);
+    }
+    else
+    {
+        // Doesn't impact supported version
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 1)) ||
+        functions->hasGLExtension("GL_ARB_get_program_binary") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)) ||
+        functions->hasGLExtension("GL_OES_get_program_binary"))
+    {
+        // Able to support the GL_PROGRAM_BINARY_ANGLE format as long as another program binary
+        // format is available.
+        GLint numBinaryFormats = QuerySingleGLInt(functions, GL_NUM_PROGRAM_BINARY_FORMATS_OES);
+        if (numBinaryFormats > 0)
+        {
+            caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
+        }
+    }
+    else
+    {
+        // Doesn't impact supported version
+    }
+
+    // glGetShaderPrecisionFormat is not available until desktop GL version 4.1 or GL_ARB_ES2_compatibility exists
+    if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+        functions->isAtLeastGLES(gl::Version(2, 0)))
+    {
+        caps->vertexHighpFloat = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_HIGH_FLOAT);
+        caps->vertexMediumpFloat = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_MEDIUM_FLOAT);
+        caps->vertexLowpFloat = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_LOW_FLOAT);
+        caps->fragmentHighpFloat = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_HIGH_FLOAT);
+        caps->fragmentMediumpFloat = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT);
+        caps->fragmentLowpFloat = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_LOW_FLOAT);
+        caps->vertexHighpInt = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_HIGH_INT);
+        caps->vertexMediumpInt = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_MEDIUM_INT);
+        caps->vertexLowpInt = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_LOW_INT);
+        caps->fragmentHighpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_HIGH_INT);
+        caps->fragmentMediumpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_MEDIUM_INT);
+        caps->fragmentLowpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_LOW_INT);
+    }
+    else
+    {
+        // Doesn't impact supported version, set some default values
+        caps->vertexHighpFloat.setIEEEFloat();
+        caps->vertexMediumpFloat.setIEEEFloat();
+        caps->vertexLowpFloat.setIEEEFloat();
+        caps->fragmentHighpFloat.setIEEEFloat();
+        caps->fragmentMediumpFloat.setIEEEFloat();
+        caps->fragmentLowpFloat.setIEEEFloat();
+        caps->vertexHighpInt.setTwosComplementInt(32);
+        caps->vertexMediumpInt.setTwosComplementInt(32);
+        caps->vertexLowpInt.setTwosComplementInt(32);
+        caps->fragmentHighpInt.setTwosComplementInt(32);
+        caps->fragmentMediumpInt.setTwosComplementInt(32);
+        caps->fragmentLowpInt.setTwosComplementInt(32);
+    }
+
+    if (functions->isAtLeastGL(gl::Version(3, 2)) || functions->hasGLExtension("GL_ARB_sync") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxServerWaitTimeout = QuerySingleGLInt64(functions, GL_MAX_SERVER_WAIT_TIMEOUT);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    // Table 6.31, implementation dependent vertex shader limits
+    if (functions->isAtLeastGL(gl::Version(2, 0)) ||
+        functions->isAtLeastGLES(gl::Version(2, 0)))
+    {
+        caps->maxVertexAttributes = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIBS);
+        caps->maxVertexUniformComponents = QuerySingleGLInt(functions, GL_MAX_VERTEX_UNIFORM_COMPONENTS);
+        caps->maxVertexTextureImageUnits = QuerySingleGLInt(functions, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+    }
+    else
+    {
+        // Can't support ES2 version without these caps
+        LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+        functions->isAtLeastGLES(gl::Version(2, 0)))
+    {
+        caps->maxVertexUniformVectors = QuerySingleGLInt(functions, GL_MAX_VERTEX_UNIFORM_VECTORS);
+    }
+    else
+    {
+        // Doesn't limit ES version, GL_MAX_VERTEX_UNIFORM_COMPONENTS / 4 is acceptable.
+        caps->maxVertexUniformVectors = caps->maxVertexUniformComponents / 4;
+    }
+
+    if (functions->isAtLeastGL(gl::Version(3, 1)) || functions->hasGLExtension("GL_ARB_uniform_buffer_object") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxVertexUniformBlocks = QuerySingleGLInt(functions, GL_MAX_VERTEX_UNIFORM_BLOCKS);
+    }
+    else
+    {
+        // Can't support ES3 without uniform blocks
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(3, 2)) ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxVertexOutputComponents = QuerySingleGLInt(functions, GL_MAX_VERTEX_OUTPUT_COMPONENTS);
+    }
+    else
+    {
+        // There doesn't seem, to be a desktop extension to add this cap, maybe it could be given a safe limit
+        // instead of limiting the supported ES version.
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    // Table 6.32, implementation dependent fragment shader limits
+    if (functions->isAtLeastGL(gl::Version(2, 0)) ||
+        functions->isAtLeastGLES(gl::Version(2, 0)))
+    {
+        caps->maxFragmentUniformComponents = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
+        caps->maxTextureImageUnits = QuerySingleGLInt(functions, GL_MAX_TEXTURE_IMAGE_UNITS);
+    }
+    else
+    {
+        // Can't support ES2 version without these caps
+        LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+        functions->isAtLeastGLES(gl::Version(2, 0)))
+    {
+        caps->maxFragmentUniformVectors = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_UNIFORM_VECTORS);
+    }
+    else
+    {
+        // Doesn't limit ES version, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS / 4 is acceptable.
+        caps->maxFragmentUniformVectors = caps->maxFragmentUniformComponents / 4;
+    }
+
+    if (functions->isAtLeastGL(gl::Version(3, 1)) || functions->hasGLExtension("GL_ARB_uniform_buffer_object") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxFragmentUniformBlocks = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_UNIFORM_BLOCKS);
+    }
+    else
+    {
+        // Can't support ES3 without uniform blocks
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(3, 2)) ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxFragmentInputComponents = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_INPUT_COMPONENTS);
+    }
+    else
+    {
+        // There doesn't seem, to be a desktop extension to add this cap, maybe it could be given a safe limit
+        // instead of limiting the supported ES version.
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(3, 0)) ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->minProgramTexelOffset = QuerySingleGLInt(functions, GL_MIN_PROGRAM_TEXEL_OFFSET);
+        caps->maxProgramTexelOffset = QuerySingleGLInt(functions, GL_MAX_PROGRAM_TEXEL_OFFSET);
+    }
+    else
+    {
+        // Can't support ES3 without texel offset, could possibly be emulated in the shader
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    // Table 6.33, implementation dependent aggregate shader limits
+    if (functions->isAtLeastGL(gl::Version(3, 1)) || functions->hasGLExtension("GL_ARB_uniform_buffer_object") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxUniformBufferBindings = QuerySingleGLInt(functions, GL_MAX_UNIFORM_BUFFER_BINDINGS);
+        caps->maxUniformBlockSize = QuerySingleGLInt64(functions, GL_MAX_UNIFORM_BLOCK_SIZE);
+        caps->uniformBufferOffsetAlignment = QuerySingleGLInt(functions, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+        caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentInputComponents;
+        caps->maxCombinedVertexUniformComponents = QuerySingleGLInt64(functions, GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS);
+        caps->maxCombinedFragmentUniformComponents = QuerySingleGLInt64(functions, GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS);
+    }
+    else
+    {
+        // Can't support ES3 without uniform blocks
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(3, 0)) ||
+        functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+        functions->isAtLeastGLES(gl::Version(2, 0)))
+    {
+        caps->maxVaryingComponents = QuerySingleGLInt(functions, GL_MAX_VARYING_COMPONENTS);
+    }
+    else if (functions->isAtLeastGL(gl::Version(2, 0)))
+    {
+        caps->maxVaryingComponents = QuerySingleGLInt(functions, GL_MAX_VARYING_FLOATS);
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+        functions->isAtLeastGLES(gl::Version(2, 0)))
+    {
+        caps->maxVaryingVectors = QuerySingleGLInt(functions, GL_MAX_VARYING_VECTORS);
+    }
+    else
+    {
+        // Doesn't limit ES version, GL_MAX_VARYING_COMPONENTS / 4 is acceptable.
+        caps->maxVaryingVectors = caps->maxVaryingComponents / 4;
+    }
+
+    // Determine the max combined texture image units by adding the vertex and fragment limits.  If
+    // the real cap is queried, it would contain the limits for shader types that are not available to ES.
+    caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
+
+    // Table 6.34, implementation dependent transform feedback limits
+    if (functions->isAtLeastGL(gl::Version(4, 0)) ||
+        functions->hasGLExtension("GL_ARB_transform_feedback2") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        caps->maxTransformFeedbackInterleavedComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
+        caps->maxTransformFeedbackSeparateAttributes = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
+        caps->maxTransformFeedbackSeparateComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
+    }
+    else
+    {
+        // Can't support ES3 without transform feedback
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    // Table 6.35, Framebuffer Dependent Values
+    if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_multisample") ||
+        functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_multisampled_render_to_texture"))
+    {
+        caps->maxSamples = QuerySingleGLInt(functions, GL_MAX_SAMPLES);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    // Non-constant sampler array indexing is required for OpenGL ES 2 and OpenGL ES after 3.2.
+    // However having it available on OpenGL ES 2 is a specification bug, and using this
+    // indexing in WebGL is undefined. Requiring this feature would break WebGL 1 for some users
+    // so we don't check for it. (it is present with ESSL 100, ESSL >= 320, GLSL >= 400 and
+    // GL_ARB_gpu_shader5)
+
+    // Check if sampler objects are supported
+    if (!functions->isAtLeastGL(gl::Version(3, 3)) &&
+        !functions->hasGLExtension("GL_ARB_sampler_objects") &&
+        !functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        // Can't support ES3 without sampler objects
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    // Can't support ES3 without texture swizzling
+    if (!functions->isAtLeastGL(gl::Version(3, 3)) &&
+        !functions->hasGLExtension("GL_ARB_texture_swizzle") &&
+        !functions->hasGLExtension("GL_EXT_texture_swizzle") &&
+        !functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+
+        // Texture swizzling is required to work around the luminance texture format not being
+        // present in the core profile
+        if (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT)
+        {
+            LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+        }
+    }
+
+    // Can't support ES3 without the GLSL packing builtins. We have a workaround for all
+    // desktop OpenGL versions starting from 3.3 with the bit packing extension.
+    if (!functions->isAtLeastGL(gl::Version(4, 2)) &&
+        !(functions->isAtLeastGL(gl::Version(3, 2)) &&
+          functions->hasGLExtension("GL_ARB_shader_bit_encoding")) &&
+        !functions->hasGLExtension("GL_ARB_shading_language_packing") &&
+        !functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    // ES3 needs to support explicit layout location qualifiers, while it might be possible to
+    // fake them in our side, we currently don't support that.
+    if (!functions->isAtLeastGL(gl::Version(3, 3)) &&
+        !functions->hasGLExtension("GL_ARB_explicit_attrib_location") &&
+        !functions->isAtLeastGLES(gl::Version(3, 0)))
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+        functions->hasGLExtension("GL_ARB_texture_multisample"))
+    {
+        caps->maxFramebufferWidth   = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_WIDTH);
+        caps->maxFramebufferHeight  = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_HEIGHT);
+        caps->maxFramebufferSamples = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_SAMPLES);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(3, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+        functions->hasGLExtension("GL_ARB_texture_multisample"))
+    {
+        caps->maxSampleMaskWords     = QuerySingleGLInt(functions, GL_MAX_SAMPLE_MASK_WORDS);
+        caps->maxColorTextureSamples = QuerySingleGLInt(functions, GL_MAX_COLOR_TEXTURE_SAMPLES);
+        caps->maxDepthTextureSamples = QuerySingleGLInt(functions, GL_MAX_DEPTH_TEXTURE_SAMPLES);
+        caps->maxIntegerSamples      = QuerySingleGLInt(functions, GL_MAX_INTEGER_SAMPLES);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+        functions->hasGLExtension("GL_ARB_vertex_attrib_binding"))
+    {
+        caps->maxVertexAttribRelativeOffset =
+            QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET);
+        caps->maxVertexAttribBindings = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_BINDINGS);
+
+        // OpenGL 4.3 has no limit on maximum value of stride.
+        // [OpenGL 4.3 (Core Profile) - February 14, 2013] Chapter 10.3.1 Page 298
+        if (workarounds.emulateMaxVertexAttribStride ||
+            (functions->standard == STANDARD_GL_DESKTOP && functions->version == gl::Version(4, 3)))
+        {
+            caps->maxVertexAttribStride = 2048;
+        }
+        else
+        {
+            caps->maxVertexAttribStride = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_STRIDE);
+        }
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+        functions->hasGLExtension("GL_ARB_shader_storage_buffer_object"))
+    {
+        caps->maxCombinedShaderOutputResources =
+            QuerySingleGLInt(functions, GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES);
+        caps->maxFragmentShaderStorageBlocks =
+            QuerySingleGLInt(functions, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
+        caps->maxVertexShaderStorageBlocks =
+            QuerySingleGLInt(functions, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
+        caps->maxShaderStorageBufferBindings =
+            QuerySingleGLInt(functions, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
+        caps->maxShaderStorageBlockSize =
+            QuerySingleGLInt64(functions, GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
+        caps->maxCombinedShaderStorageBlocks =
+            QuerySingleGLInt(functions, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS);
+        caps->shaderStorageBufferOffsetAlignment =
+            QuerySingleGLInt(functions, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+    }
+
+    // OpenGL 4.2 is required for GL_ARB_compute_shader, some platform drivers have the extension,
+    // but their maximum supported GL versions are less than 4.2. Explicitly limit the minimum
+    // GL version to 4.2.
+    if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+        (functions->isAtLeastGL(gl::Version(4, 2)) &&
+         functions->hasGLExtension("GL_ARB_compute_shader")))
+    {
+        for (GLuint index = 0u; index < 3u; ++index)
+        {
+            caps->maxComputeWorkGroupCount[index] =
+                QuerySingleIndexGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_COUNT, index);
+
+            caps->maxComputeWorkGroupSize[index] =
+                QuerySingleIndexGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_SIZE, index);
+        }
+        caps->maxComputeWorkGroupInvocations =
+            QuerySingleGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS);
+        caps->maxComputeUniformBlocks = QuerySingleGLInt(functions, GL_MAX_COMPUTE_UNIFORM_BLOCKS);
+        caps->maxComputeTextureImageUnits =
+            QuerySingleGLInt(functions, GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS);
+        caps->maxComputeSharedMemorySize =
+            QuerySingleGLInt(functions, GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
+        caps->maxComputeUniformComponents =
+            QuerySingleGLInt(functions, GL_MAX_COMPUTE_UNIFORM_COMPONENTS);
+        caps->maxComputeAtomicCounterBuffers =
+            QuerySingleGLInt(functions, GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS);
+        caps->maxComputeAtomicCounters =
+            QuerySingleGLInt(functions, GL_MAX_COMPUTE_ATOMIC_COUNTERS);
+        caps->maxComputeImageUniforms = QuerySingleGLInt(functions, GL_MAX_COMPUTE_IMAGE_UNIFORMS);
+        caps->maxCombinedComputeUniformComponents =
+            QuerySingleGLInt(functions, GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS);
+        caps->maxComputeShaderStorageBlocks =
+            QuerySingleGLInt(functions, GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+        functions->hasGLExtension("GL_ARB_explicit_uniform_location"))
+    {
+        caps->maxUniformLocations = QuerySingleGLInt(functions, GL_MAX_UNIFORM_LOCATIONS);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 0)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+        functions->hasGLExtension("GL_ARB_texture_gather"))
+    {
+        caps->minProgramTextureGatherOffset =
+            QuerySingleGLInt(functions, GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET);
+        caps->maxProgramTextureGatherOffset =
+            QuerySingleGLInt(functions, GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+        functions->hasGLExtension("GL_ARB_shader_image_load_store"))
+    {
+        caps->maxVertexImageUniforms = QuerySingleGLInt(functions, GL_MAX_VERTEX_IMAGE_UNIFORMS);
+        caps->maxFragmentImageUniforms =
+            QuerySingleGLInt(functions, GL_MAX_FRAGMENT_IMAGE_UNIFORMS);
+        caps->maxImageUnits = QuerySingleGLInt(functions, GL_MAX_IMAGE_UNITS);
+        caps->maxCombinedImageUniforms =
+            QuerySingleGLInt(functions, GL_MAX_COMBINED_IMAGE_UNIFORMS);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+    }
+
+    if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+        functions->hasGLExtension("GL_ARB_shader_atomic_counters"))
+    {
+        caps->maxVertexAtomicCounterBuffers =
+            QuerySingleGLInt(functions, GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS);
+        caps->maxVertexAtomicCounters = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATOMIC_COUNTERS);
+        caps->maxFragmentAtomicCounterBuffers =
+            QuerySingleGLInt(functions, GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS);
+        caps->maxFragmentAtomicCounters =
+            QuerySingleGLInt(functions, GL_MAX_FRAGMENT_ATOMIC_COUNTERS);
+        caps->maxAtomicCounterBufferBindings =
+            QuerySingleGLInt(functions, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
+        caps->maxAtomicCounterBufferSize =
+            QuerySingleGLInt(functions, GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE);
+        caps->maxCombinedAtomicCounterBuffers =
+            QuerySingleGLInt(functions, GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS);
+        caps->maxCombinedAtomicCounters =
+            QuerySingleGLInt(functions, GL_MAX_COMBINED_ATOMIC_COUNTERS);
+    }
+    else
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+    }
+
+    // TODO(geofflang): The gl-uniform-arrays WebGL conformance test struggles to complete on time
+    // if the max uniform vectors is too large.  Artificially limit the maximum until the test is
+    // updated.
+    caps->maxVertexUniformVectors = std::min(1024u, caps->maxVertexUniformVectors);
+    caps->maxVertexUniformComponents =
+        std::min(caps->maxVertexUniformVectors * 4, caps->maxVertexUniformComponents);
+    caps->maxFragmentUniformVectors = std::min(1024u, caps->maxFragmentUniformVectors);
+    caps->maxFragmentUniformComponents =
+        std::min(caps->maxFragmentUniformVectors * 4, caps->maxFragmentUniformComponents);
+
+    // If it is not possible to support reading buffer data back, a shadow copy of the buffers must
+    // be held. This disallows writing to buffers indirectly through transform feedback, thus
+    // disallowing ES3.
+    if (!CanMapBufferForRead(functions))
+    {
+        LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+    }
+
+    // Extension support
+    extensions->setTextureExtensionSupport(*textureCapsMap);
+    extensions->elementIndexUint = functions->standard == STANDARD_GL_DESKTOP ||
+                                   functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_element_index_uint");
+    extensions->getProgramBinary = caps->programBinaryFormats.size() > 0;
+    extensions->readFormatBGRA = functions->isAtLeastGL(gl::Version(1, 2)) || functions->hasGLExtension("GL_EXT_bgra") ||
+                                 functions->hasGLESExtension("GL_EXT_read_format_bgra");
+    extensions->mapBuffer = functions->isAtLeastGL(gl::Version(1, 5)) ||
+                            functions->isAtLeastGLES(gl::Version(3, 0)) ||
+                            functions->hasGLESExtension("GL_OES_mapbuffer");
+    extensions->mapBufferRange = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_ARB_map_buffer_range") ||
+                                 functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_map_buffer_range");
+    extensions->textureNPOT = functions->standard == STANDARD_GL_DESKTOP ||
+                              functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_texture_npot");
+    // TODO(jmadill): Investigate emulating EXT_draw_buffers on ES 3.0's core functionality.
+    extensions->drawBuffers = functions->isAtLeastGL(gl::Version(2, 0)) ||
+                              functions->hasGLExtension("ARB_draw_buffers") ||
+                              functions->hasGLESExtension("GL_EXT_draw_buffers");
+    extensions->textureStorage = functions->standard == STANDARD_GL_DESKTOP ||
+                                 functions->hasGLESExtension("GL_EXT_texture_storage");
+    extensions->textureFilterAnisotropic = functions->hasGLExtension("GL_EXT_texture_filter_anisotropic") || functions->hasGLESExtension("GL_EXT_texture_filter_anisotropic");
+    extensions->occlusionQueryBoolean    = nativegl::SupportsOcclusionQueries(functions);
+    extensions->maxTextureAnisotropy = extensions->textureFilterAnisotropic ? QuerySingleGLFloat(functions, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0.0f;
+    extensions->fence = functions->hasGLExtension("GL_NV_fence") || functions->hasGLESExtension("GL_NV_fence");
+    extensions->blendMinMax = functions->isAtLeastGL(gl::Version(1, 5)) || functions->hasGLExtension("GL_EXT_blend_minmax") ||
+                              functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_blend_minmax");
+    extensions->framebufferBlit = (functions->blitFramebuffer != nullptr);
+    extensions->framebufferMultisample = caps->maxSamples > 0;
+    extensions->standardDerivatives    = functions->isAtLeastGL(gl::Version(2, 0)) ||
+                                      functions->hasGLExtension("GL_ARB_fragment_shader") ||
+                                      functions->hasGLESExtension("GL_OES_standard_derivatives");
+    extensions->shaderTextureLOD = functions->isAtLeastGL(gl::Version(3, 0)) ||
+                                   functions->hasGLExtension("GL_ARB_shader_texture_lod") ||
+                                   functions->hasGLESExtension("GL_EXT_shader_texture_lod");
+    extensions->fragDepth = functions->standard == STANDARD_GL_DESKTOP ||
+                            functions->hasGLESExtension("GL_EXT_frag_depth");
+    extensions->fboRenderMipmap = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_object") ||
+                                  functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_fbo_render_mipmap");
+    extensions->instancedArrays = functions->isAtLeastGL(gl::Version(3, 1)) ||
+                                  (functions->hasGLExtension("GL_ARB_instanced_arrays") &&
+                                   (functions->hasGLExtension("GL_ARB_draw_instanced") ||
+                                    functions->hasGLExtension("GL_EXT_draw_instanced"))) ||
+                                  functions->isAtLeastGLES(gl::Version(3, 0)) ||
+                                  functions->hasGLESExtension("GL_EXT_instanced_arrays");
+    extensions->unpackSubimage = functions->standard == STANDARD_GL_DESKTOP ||
+                                 functions->isAtLeastGLES(gl::Version(3, 0)) ||
+                                 functions->hasGLESExtension("GL_EXT_unpack_subimage");
+    extensions->packSubimage = functions->standard == STANDARD_GL_DESKTOP ||
+                               functions->isAtLeastGLES(gl::Version(3, 0)) ||
+                               functions->hasGLESExtension("GL_NV_pack_subimage");
+    extensions->debugMarker =
+        functions->isAtLeastGL(gl::Version(4, 3)) || functions->hasGLExtension("GL_KHR_debug") ||
+        functions->isAtLeastGLES(gl::Version(3, 2)) || functions->hasGLESExtension("GL_KHR_debug");
+    if (functions->isAtLeastGL(gl::Version(3, 3)) ||
+        functions->hasGLExtension("GL_ARB_timer_query") ||
+        functions->hasGLESExtension("GL_EXT_disjoint_timer_query"))
+    {
+        extensions->disjointTimerQuery = true;
+        extensions->queryCounterBitsTimeElapsed =
+            QueryQueryValue(functions, GL_TIME_ELAPSED, GL_QUERY_COUNTER_BITS);
+        extensions->queryCounterBitsTimestamp =
+            QueryQueryValue(functions, GL_TIMESTAMP, GL_QUERY_COUNTER_BITS);
+    }
+
+    // the EXT_multisample_compatibility is written against ES3.1 but can apply
+    // to earlier versions so therefore we're only checking for the extension string
+    // and not the specific GLES version.
+    extensions->multisampleCompatibility = functions->isAtLeastGL(gl::Version(1, 3)) ||
+        functions->hasGLESExtension("GL_EXT_multisample_compatibility");
+
+    extensions->framebufferMixedSamples =
+        functions->hasGLExtension("GL_NV_framebuffer_mixed_samples") ||
+        functions->hasGLESExtension("GL_NV_framebuffer_mixed_samples");
+
+    extensions->robustness = functions->isAtLeastGL(gl::Version(4, 5)) ||
+                             functions->hasGLExtension("GL_KHR_robustness") ||
+                             functions->hasGLExtension("GL_ARB_robustness") ||
+                             functions->isAtLeastGLES(gl::Version(3, 2)) ||
+                             functions->hasGLESExtension("GL_KHR_robustness") ||
+                             functions->hasGLESExtension("GL_EXT_robustness");
+
+    extensions->copyTexture = true;
+    extensions->syncQuery   = SyncQueryGL::IsSupported(functions);
+
+    // NV_path_rendering
+    // We also need interface query which is available in
+    // >= 4.3 core or ARB_interface_query or >= GLES 3.1
+    const bool canEnableGLPathRendering =
+        functions->hasGLExtension("GL_NV_path_rendering") &&
+        (functions->hasGLExtension("GL_ARB_program_interface_query") ||
+         functions->isAtLeastGL(gl::Version(4, 3)));
+
+    const bool canEnableESPathRendering =
+        functions->hasGLESExtension("GL_NV_path_rendering") &&
+        functions->isAtLeastGLES(gl::Version(3, 1));
+
+    extensions->pathRendering = canEnableGLPathRendering || canEnableESPathRendering;
+
+    extensions->textureSRGBDecode = functions->hasGLExtension("GL_EXT_texture_sRGB_decode") ||
+                                    functions->hasGLESExtension("GL_EXT_texture_sRGB_decode");
+
+#if defined(ANGLE_PLATFORM_APPLE)
+    VendorID vendor = GetVendorID(functions);
+    if ((IsAMD(vendor) || IsIntel(vendor)) && *maxSupportedESVersion >= gl::Version(3, 0))
+    {
+        // Apple Intel/AMD drivers do not correctly use the TEXTURE_SRGB_DECODE property of sampler
+        // states.  Disable this extension when we would advertise any ES version that has samplers.
+        extensions->textureSRGBDecode = false;
+    }
+#endif
+
+    extensions->sRGBWriteControl = functions->isAtLeastGL(gl::Version(3, 0)) ||
+                                   functions->hasGLExtension("GL_EXT_framebuffer_sRGB") ||
+                                   functions->hasGLExtension("GL_ARB_framebuffer_sRGB") ||
+                                   functions->hasGLESExtension("GL_EXT_sRGB_write_control");
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+    // SRGB blending does not appear to work correctly on the Nexus 5. Writing to an SRGB
+    // framebuffer with GL_FRAMEBUFFER_SRGB enabled and then reading back returns the same value.
+    // Disabling GL_FRAMEBUFFER_SRGB will then convert in the wrong direction.
+    extensions->sRGBWriteControl = false;
+#endif
+
+    // EXT_discard_framebuffer can be implemented as long as glDiscardFramebufferEXT or
+    // glInvalidateFramebuffer is available
+    extensions->discardFramebuffer = functions->isAtLeastGL(gl::Version(4, 3)) ||
+                                     functions->hasGLExtension("GL_ARB_invalidate_subdata") ||
+                                     functions->isAtLeastGLES(gl::Version(3, 0)) ||
+                                     functions->hasGLESExtension("GL_EXT_discard_framebuffer") ||
+                                     functions->hasGLESExtension("GL_ARB_invalidate_subdata");
+
+    extensions->translatedShaderSource = true;
+}
+
+void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
+{
+    VendorID vendor = GetVendorID(functions);
+
+    workarounds->dontRemoveInvariantForFragmentInput =
+        functions->standard == STANDARD_GL_DESKTOP && IsAMD(vendor);
+
+    // Don't use 1-bit alpha formats on desktop GL with AMD or Intel drivers.
+    workarounds->avoid1BitAlphaTextureFormats =
+        functions->standard == STANDARD_GL_DESKTOP && (IsAMD(vendor) || IsIntel(vendor));
+
+    workarounds->rgba4IsNotSupportedForColorRendering =
+        functions->standard == STANDARD_GL_DESKTOP && IsIntel(vendor);
+
+    workarounds->emulateAbsIntFunction = IsIntel(vendor);
+
+    workarounds->addAndTrueToLoopCondition = IsIntel(vendor);
+
+    workarounds->emulateIsnanFloat = IsIntel(vendor);
+
+    workarounds->doesSRGBClearsOnLinearFramebufferAttachments =
+        functions->standard == STANDARD_GL_DESKTOP && (IsIntel(vendor) || IsAMD(vendor));
+
+#if defined(ANGLE_PLATFORM_LINUX)
+    workarounds->emulateMaxVertexAttribStride =
+        functions->standard == STANDARD_GL_DESKTOP && IsAMD(vendor);
+    workarounds->useUnusedBlocksWithStandardOrSharedLayout = IsAMD(vendor);
+#endif
+
+#if defined(ANGLE_PLATFORM_APPLE)
+    workarounds->doWhileGLSLCausesGPUHang = true;
+    workarounds->useUnusedBlocksWithStandardOrSharedLayout = true;
+    workarounds->rewriteFloatUnaryMinusOperator            = IsIntel(vendor);
+#endif
+
+    workarounds->finishDoesNotCauseQueriesToBeAvailable =
+        functions->standard == STANDARD_GL_DESKTOP && IsNvidia(vendor);
+
+    // TODO(cwallez): Disable this workaround for MacOSX versions 10.9 or later.
+    workarounds->alwaysCallUseProgramAfterLink = true;
+
+    workarounds->unpackOverlappingRowsSeparatelyUnpackBuffer = IsNvidia(vendor);
+    workarounds->packOverlappingRowsSeparatelyPackBuffer     = IsNvidia(vendor);
+
+    workarounds->initializeCurrentVertexAttributes = IsNvidia(vendor);
+
+#if defined(ANGLE_PLATFORM_APPLE)
+    workarounds->unpackLastRowSeparatelyForPaddingInclusion = true;
+    workarounds->packLastRowSeparatelyForPaddingInclusion   = true;
+#else
+    workarounds->unpackLastRowSeparatelyForPaddingInclusion = IsNvidia(vendor);
+    workarounds->packLastRowSeparatelyForPaddingInclusion   = IsNvidia(vendor);
+#endif
+
+    workarounds->removeInvariantAndCentroidForESSL3 =
+        functions->isAtMostGL(gl::Version(4, 1)) ||
+        (functions->standard == STANDARD_GL_DESKTOP && IsAMD(vendor));
+
+    // TODO(oetuaho): Make this specific to the affected driver versions. Versions that came after
+    // 364 are known to be affected, at least up to 375.
+    workarounds->emulateAtan2Float = IsNvidia(vendor);
+
+    workarounds->reapplyUBOBindingsAfterLoadingBinaryProgram = IsAMD(vendor);
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+    // TODO(jmadill): Narrow workaround range for specific devices.
+    workarounds->reapplyUBOBindingsAfterLoadingBinaryProgram = true;
+#endif
+}
+
+}  // namespace nativegl_gl
+
+namespace nativegl
+{
+bool SupportsFenceSync(const FunctionsGL *functions)
+{
+    return functions->isAtLeastGL(gl::Version(3, 2)) || functions->hasGLExtension("GL_ARB_sync") ||
+           functions->isAtLeastGLES(gl::Version(3, 0));
+}
+
+bool SupportsOcclusionQueries(const FunctionsGL *functions)
+{
+    return functions->isAtLeastGL(gl::Version(1, 5)) ||
+           functions->hasGLExtension("GL_ARB_occlusion_query2") ||
+           functions->isAtLeastGLES(gl::Version(3, 0)) ||
+           functions->hasGLESExtension("GL_EXT_occlusion_query_boolean");
+}
+}
+
+bool CanMapBufferForRead(const FunctionsGL *functions)
+{
+    return (functions->mapBufferRange != nullptr) ||
+           (functions->mapBuffer != nullptr && functions->standard == STANDARD_GL_DESKTOP);
+}
+
+uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions,
+                                    GLenum target,
+                                    size_t offset,
+                                    size_t length,
+                                    GLbitfield access)
+{
+    if (functions->mapBufferRange != nullptr)
+    {
+        return reinterpret_cast<uint8_t *>(
+            functions->mapBufferRange(target, offset, length, access));
+    }
+    else if (functions->mapBuffer != nullptr &&
+             (functions->standard == STANDARD_GL_DESKTOP || access == GL_MAP_WRITE_BIT))
+    {
+        // Only the read and write bits are supported
+        ASSERT((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) != 0);
+
+        GLenum accessEnum = 0;
+        if (access == (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))
+        {
+            accessEnum = GL_READ_WRITE;
+        }
+        else if (access == GL_MAP_READ_BIT)
+        {
+            accessEnum = GL_READ_ONLY;
+        }
+        else if (access == GL_MAP_WRITE_BIT)
+        {
+            accessEnum = GL_WRITE_ONLY;
+        }
+        else
+        {
+            UNREACHABLE();
+            return nullptr;
+        }
+
+        return reinterpret_cast<uint8_t *>(functions->mapBuffer(target, accessEnum)) + offset;
+    }
+    else
+    {
+        // No options available
+        UNREACHABLE();
+        return nullptr;
+    }
+}
+
+gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &size,
+                                                            const gl::PixelStoreStateBase &state,
+                                                            GLenum format,
+                                                            GLenum type,
+                                                            bool is3D,
+                                                            const void *pixels)
+{
+    if (state.pixelBuffer.get() == nullptr)
+    {
+        return false;
+    }
+
+    // We are using an pack or unpack buffer, compute what the driver thinks is going to be the
+    // last byte read or written. If it is past the end of the buffer, we will need to use the
+    // workaround otherwise the driver will generate INVALID_OPERATION and not do the operation.
+    CheckedNumeric<size_t> checkedEndByte;
+    CheckedNumeric<size_t> pixelBytes;
+    size_t rowPitch;
+
+    const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
+    ANGLE_TRY_RESULT(glFormat.computePackUnpackEndByte(type, size, state, is3D), checkedEndByte);
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, size.width, state.alignment, state.rowLength),
+                     rowPitch);
+    pixelBytes = glFormat.computePixelBytes(type);
+
+    checkedEndByte += reinterpret_cast<intptr_t>(pixels);
+
+    // At this point checkedEndByte is the actual last byte read.
+    // The driver adds an extra row padding (if any), mimic it.
+    ANGLE_TRY_CHECKED_MATH(pixelBytes);
+    if (pixelBytes.ValueOrDie() * size.width < rowPitch)
+    {
+        checkedEndByte += rowPitch - pixelBytes * size.width;
+    }
+
+    ANGLE_TRY_CHECKED_MATH(checkedEndByte);
+
+    return checkedEndByte.ValueOrDie() > static_cast<size_t>(state.pixelBuffer->getSize());
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.h b/src/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.h
new file mode 100644
index 0000000..98716db
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.h
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// renderergl_utils.h: Conversion functions and other utility routines
+// specific to the OpenGL renderer.
+
+#ifndef LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
+#define LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "libANGLE/renderer/gl/functionsgl_typedefs.h"
+
+#include <string>
+#include <vector>
+
+namespace gl
+{
+struct Caps;
+class TextureCapsMap;
+struct Extensions;
+struct Version;
+}
+
+namespace rx
+{
+class FunctionsGL;
+struct WorkaroundsGL;
+
+VendorID GetVendorID(const FunctionsGL *functions);
+std::string GetDriverVersion(const FunctionsGL *functions);
+
+namespace nativegl_gl
+{
+
+void GenerateCaps(const FunctionsGL *functions,
+                  const WorkaroundsGL &workarounds,
+                  gl::Caps *caps,
+                  gl::TextureCapsMap *textureCapsMap,
+                  gl::Extensions *extensions,
+                  gl::Version *maxSupportedESVersion);
+
+void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds);
+}
+
+namespace nativegl
+{
+bool SupportsFenceSync(const FunctionsGL *functions);
+bool SupportsOcclusionQueries(const FunctionsGL *functions);
+}
+
+bool CanMapBufferForRead(const FunctionsGL *functions);
+uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions,
+                                    GLenum target,
+                                    size_t offset,
+                                    size_t length,
+                                    GLbitfield access);
+
+gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &size,
+                                                            const gl::PixelStoreStateBase &state,
+                                                            GLenum format,
+                                                            GLenum type,
+                                                            bool is3D,
+                                                            const void *pixels);
+}
+
+#endif // LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp
new file mode 100644
index 0000000..b60f981
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp
@@ -0,0 +1,482 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// D3DTextureSurfaceWGL.cpp: WGL implementation of egl::Surface for D3D texture interop.
+
+#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
+
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+namespace rx
+{
+
+namespace
+{
+
+egl::Error GetD3D11TextureInfo(EGLenum buftype,
+                               ID3D11Texture2D *texture11,
+                               size_t *width,
+                               size_t *height,
+                               IUnknown **object,
+                               IUnknown **device)
+{
+    D3D11_TEXTURE2D_DESC textureDesc;
+    texture11->GetDesc(&textureDesc);
+
+    if (buftype == EGL_D3D_TEXTURE_ANGLE)
+    {
+        // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+        switch (textureDesc.Format)
+        {
+            case DXGI_FORMAT_R8G8B8A8_UNORM:
+            case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+            case DXGI_FORMAT_B8G8R8A8_UNORM:
+            case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+            case DXGI_FORMAT_R16G16B16A16_FLOAT:
+            case DXGI_FORMAT_R32G32B32A32_FLOAT:
+                break;
+
+            default:
+                SafeRelease(texture11);
+                return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+                                  textureDesc.Format);
+        }
+    }
+
+    ID3D11Device *d3d11Device = nullptr;
+    texture11->GetDevice(&d3d11Device);
+    if (d3d11Device == nullptr)
+    {
+        SafeRelease(texture11);
+        return egl::Error(EGL_BAD_PARAMETER,
+                          "Could not query the D3D11 device from the client buffer.");
+    }
+
+    if (width)
+    {
+        *width = textureDesc.Width;
+    }
+    if (height)
+    {
+        *height = textureDesc.Height;
+    }
+
+    if (device)
+    {
+        *device = d3d11Device;
+    }
+    else
+    {
+        SafeRelease(d3d11Device);
+    }
+
+    if (object)
+    {
+        *object = texture11;
+    }
+    else
+    {
+        SafeRelease(texture11);
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error GetD3D9TextureInfo(EGLenum buftype,
+                              IDirect3DTexture9 *texture9,
+                              size_t *width,
+                              size_t *height,
+                              IUnknown **object,
+                              IUnknown **device)
+{
+    D3DSURFACE_DESC surfaceDesc;
+    if (FAILED(texture9->GetLevelDesc(0, &surfaceDesc)))
+    {
+        SafeRelease(texture9);
+        return egl::Error(EGL_BAD_PARAMETER, "Could not query description of the D3D9 surface.");
+    }
+
+    if (buftype == EGL_D3D_TEXTURE_ANGLE)
+    {
+        // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+        switch (surfaceDesc.Format)
+        {
+            case D3DFMT_R8G8B8:
+            case D3DFMT_A8R8G8B8:
+            case D3DFMT_A16B16G16R16F:
+            case D3DFMT_A32B32G32R32F:
+                break;
+
+            default:
+                SafeRelease(texture9);
+                return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+                                  surfaceDesc.Format);
+        }
+    }
+
+    if (width)
+    {
+        *width = surfaceDesc.Width;
+    }
+    if (height)
+    {
+        *height = surfaceDesc.Height;
+    }
+
+    IDirect3DDevice9 *d3d9Device = nullptr;
+    HRESULT result               = texture9->GetDevice(&d3d9Device);
+    if (FAILED(result))
+    {
+        SafeRelease(texture9);
+        return egl::Error(EGL_BAD_PARAMETER,
+                          "Could not query the D3D9 device from the client buffer.");
+    }
+
+    if (device)
+    {
+        *device = d3d9Device;
+    }
+    else
+    {
+        SafeRelease(d3d9Device);
+    }
+
+    if (object)
+    {
+        *object = texture9;
+    }
+    else
+    {
+        SafeRelease(texture9);
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error GetD3DTextureInfo(EGLenum buftype,
+                             EGLClientBuffer clientBuffer,
+                             ID3D11Device *d3d11Device,
+                             size_t *width,
+                             size_t *height,
+                             IUnknown **object,
+                             IUnknown **device)
+{
+    if (buftype == EGL_D3D_TEXTURE_ANGLE)
+    {
+        IUnknown *buffer            = static_cast<IUnknown *>(clientBuffer);
+        ID3D11Texture2D *texture11  = nullptr;
+        IDirect3DTexture9 *texture9 = nullptr;
+        if (SUCCEEDED(buffer->QueryInterface<ID3D11Texture2D>(&texture11)))
+        {
+            return GetD3D11TextureInfo(buftype, texture11, width, height, object, device);
+        }
+        else if (SUCCEEDED(buffer->QueryInterface<IDirect3DTexture9>(&texture9)))
+        {
+            return GetD3D9TextureInfo(buftype, texture9, width, height, object, device);
+        }
+        else
+        {
+            return egl::Error(EGL_BAD_PARAMETER,
+                              "Provided buffer is not a IDirect3DTexture9 or ID3D11Texture2D.");
+        }
+    }
+    else if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
+    {
+        ASSERT(d3d11Device);
+        HANDLE shareHandle         = static_cast<HANDLE>(clientBuffer);
+        ID3D11Texture2D *texture11 = nullptr;
+        HRESULT result = d3d11Device->OpenSharedResource(shareHandle, __uuidof(ID3D11Texture2D),
+                                                         reinterpret_cast<void **>(&texture11));
+        if (FAILED(result))
+        {
+            return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.",
+                              result);
+        }
+
+        return GetD3D11TextureInfo(buftype, texture11, width, height, object, device);
+    }
+    else
+    {
+        UNREACHABLE();
+        return egl::Error(EGL_BAD_DISPLAY, "Unknown buftype for D3DTextureSurfaceWGL.");
+    }
+}
+
+}  // anonymous namespace
+
+D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state,
+                                           RendererGL *renderer,
+                                           EGLenum buftype,
+                                           EGLClientBuffer clientBuffer,
+                                           DisplayWGL *display,
+                                           HGLRC wglContext,
+                                           HDC deviceContext,
+                                           ID3D11Device *displayD3D11Device,
+                                           const FunctionsGL *functionsGL,
+                                           const FunctionsWGL *functionsWGL)
+    : SurfaceGL(state, renderer),
+      mBuftype(buftype),
+      mClientBuffer(clientBuffer),
+      mRenderer(renderer),
+      mDisplayD3D11Device(displayD3D11Device),
+      mDisplay(display),
+      mStateManager(renderer->getStateManager()),
+      mWorkarounds(renderer->getWorkarounds()),
+      mFunctionsGL(functionsGL),
+      mFunctionsWGL(functionsWGL),
+      mWGLContext(wglContext),
+      mDeviceContext(deviceContext),
+      mWidth(0),
+      mHeight(0),
+      mDeviceHandle(nullptr),
+      mObject(nullptr),
+      mKeyedMutex(nullptr),
+      mBoundObjectTextureHandle(nullptr),
+      mBoundObjectRenderbufferHandle(nullptr),
+      mColorRenderbufferID(0),
+      mDepthStencilRenderbufferID(0),
+      mFramebufferID(0)
+{
+}
+
+D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL()
+{
+    ASSERT(mBoundObjectTextureHandle == nullptr);
+
+    SafeRelease(mObject);
+    SafeRelease(mKeyedMutex);
+
+    if (mDeviceHandle)
+    {
+        if (mBoundObjectRenderbufferHandle)
+        {
+            mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectRenderbufferHandle);
+            mBoundObjectRenderbufferHandle = nullptr;
+        }
+        mStateManager->deleteRenderbuffer(mColorRenderbufferID);
+        mStateManager->deleteRenderbuffer(mDepthStencilRenderbufferID);
+
+        if (mBoundObjectTextureHandle)
+        {
+            mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle);
+            mBoundObjectTextureHandle = nullptr;
+        }
+
+        // GL framebuffer is deleted by the default framebuffer object
+        mFramebufferID = 0;
+
+        mDisplay->releaseD3DDevice(mDeviceHandle);
+        mDeviceHandle = nullptr;
+    }
+}
+
+egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLenum buftype,
+                                                                EGLClientBuffer clientBuffer,
+                                                                ID3D11Device *d3d11Device)
+{
+    return GetD3DTextureInfo(buftype, clientBuffer, d3d11Device, nullptr, nullptr, nullptr,
+                             nullptr);
+}
+
+egl::Error D3DTextureSurfaceWGL::initialize(const DisplayImpl *displayImpl)
+{
+    IUnknown *device = nullptr;
+    ANGLE_TRY(GetD3DTextureInfo(mBuftype, mClientBuffer, mDisplayD3D11Device, &mWidth, &mHeight,
+                                &mObject, &device));
+
+    // Grab the keyed mutex, if one exists
+    mObject->QueryInterface(&mKeyedMutex);
+
+    ASSERT(device != nullptr);
+    egl::Error error = mDisplay->registerD3DDevice(device, &mDeviceHandle);
+    SafeRelease(device);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
+    mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID);
+    mBoundObjectRenderbufferHandle = mFunctionsWGL->dxRegisterObjectNV(
+        mDeviceHandle, mObject, mColorRenderbufferID, GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV);
+    if (mBoundObjectRenderbufferHandle == nullptr)
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
+                          HRESULT_CODE(GetLastError()));
+    }
+
+    const egl::Config *config = mState.config;
+    if (config->depthStencilFormat != GL_NONE)
+    {
+        mFunctionsGL->genRenderbuffers(1, &mDepthStencilRenderbufferID);
+        mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDepthStencilRenderbufferID);
+        mFunctionsGL->renderbufferStorage(GL_RENDERBUFFER, config->depthStencilFormat,
+                                          static_cast<GLsizei>(mWidth),
+                                          static_cast<GLsizei>(mHeight));
+    }
+
+    mFunctionsGL->genFramebuffers(1, &mFramebufferID);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+    mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                                          mColorRenderbufferID);
+    if (config->depthSize > 0)
+    {
+        mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+                                              mDepthStencilRenderbufferID);
+    }
+    if (config->stencilSize > 0)
+    {
+        mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                              GL_RENDERBUFFER, mDepthStencilRenderbufferID);
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::makeCurrent()
+{
+    if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
+    {
+        // TODO(geofflang): What error type here?
+        return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+    }
+
+    if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle))
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+                          HRESULT_CODE(error));
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::unMakeCurrent()
+{
+    if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle))
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.",
+                          HRESULT_CODE(error));
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::swap(const DisplayImpl *displayImpl)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    switch (attribute)
+    {
+        case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+            *value = (mBuftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) ? mClientBuffer : nullptr;
+            break;
+
+        case EGL_DXGI_KEYED_MUTEX_ANGLE:
+            *value = mKeyedMutex;
+            break;
+
+        default:
+            UNREACHABLE();
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    ASSERT(mBoundObjectTextureHandle == nullptr);
+
+    const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+    GLuint textureID           = textureGL->getTextureID();
+
+    mBoundObjectTextureHandle = mFunctionsWGL->dxRegisterObjectNV(
+        mDeviceHandle, mObject, textureID, GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
+    if (mBoundObjectTextureHandle == nullptr)
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
+                          HRESULT_CODE(error));
+    }
+
+    if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle))
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+                          HRESULT_CODE(error));
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+    ASSERT(mBoundObjectTextureHandle != nullptr);
+    if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle))
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.",
+                          HRESULT_CODE(error));
+    }
+
+    if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle))
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_ALLOC, "Failed to unregister D3D object, error: 0x%08x.",
+                          HRESULT_CODE(error));
+    }
+    mBoundObjectTextureHandle = nullptr;
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+void D3DTextureSurfaceWGL::setSwapInterval(EGLint interval)
+{
+    UNIMPLEMENTED();
+}
+
+EGLint D3DTextureSurfaceWGL::getWidth() const
+{
+    return static_cast<EGLint>(mWidth);
+}
+
+EGLint D3DTextureSurfaceWGL::getHeight() const
+{
+    return static_cast<EGLint>(mHeight);
+}
+
+EGLint D3DTextureSurfaceWGL::isPostSubBufferSupported() const
+{
+    return EGL_FALSE;
+}
+
+EGLint D3DTextureSurfaceWGL::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+
+FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::FramebufferState &data)
+{
+    return new FramebufferGL(mFramebufferID, data, mFunctionsGL, mWorkarounds,
+                             mRenderer->getBlitter(), mStateManager);
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h
new file mode 100644
index 0000000..2ce2b05
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h
@@ -0,0 +1,95 @@
+
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// D3DTextureSurfaceWGL.h: WGL implementation of egl::Surface for D3D texture interop.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsGL;
+class FunctionsWGL;
+class DisplayWGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class D3DTextureSurfaceWGL : public SurfaceGL
+{
+  public:
+    D3DTextureSurfaceWGL(const egl::SurfaceState &state,
+                         RendererGL *renderer,
+                         EGLenum buftype,
+                         EGLClientBuffer clientBuffer,
+                         DisplayWGL *display,
+                         HGLRC wglContext,
+                         HDC deviceContext,
+                         ID3D11Device *displayD3D11Device,
+                         const FunctionsGL *functionsGL,
+                         const FunctionsWGL *functionsWGL);
+    ~D3DTextureSurfaceWGL() override;
+
+    static egl::Error ValidateD3DTextureClientBuffer(EGLenum buftype,
+                                                     EGLClientBuffer clientBuffer,
+                                                     ID3D11Device *d3d11Device);
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    egl::Error makeCurrent() override;
+    egl::Error unMakeCurrent() override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
+
+  private:
+    EGLenum mBuftype;
+    EGLClientBuffer mClientBuffer;
+
+    RendererGL *mRenderer;
+
+    ID3D11Device *mDisplayD3D11Device;
+
+    DisplayWGL *mDisplay;
+    StateManagerGL *mStateManager;
+    const WorkaroundsGL &mWorkarounds;
+    const FunctionsGL *mFunctionsGL;
+    const FunctionsWGL *mFunctionsWGL;
+
+    HGLRC mWGLContext;
+    HDC mDeviceContext;
+
+    size_t mWidth;
+    size_t mHeight;
+
+    HANDLE mDeviceHandle;
+    IUnknown *mObject;
+    IDXGIKeyedMutex *mKeyedMutex;
+    HANDLE mBoundObjectTextureHandle;
+    HANDLE mBoundObjectRenderbufferHandle;
+
+    GLuint mColorRenderbufferID;
+    GLuint mDepthStencilRenderbufferID;
+    GLuint mFramebufferID;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp
new file mode 100644
index 0000000..068ea99
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp
@@ -0,0 +1,553 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DXGISwapChainWindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows using a DXGI
+// swapchain.
+
+#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+DXGISwapChainWindowSurfaceWGL::DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState &state,
+                                                             RendererGL *renderer,
+                                                             EGLNativeWindowType window,
+                                                             ID3D11Device *device,
+                                                             HANDLE deviceHandle,
+                                                             HGLRC wglContext,
+                                                             HDC deviceContext,
+                                                             const FunctionsGL *functionsGL,
+                                                             const FunctionsWGL *functionsWGL,
+                                                             EGLint orientation)
+    : SurfaceGL(state, renderer),
+      mWindow(window),
+      mStateManager(renderer->getStateManager()),
+      mWorkarounds(renderer->getWorkarounds()),
+      mRenderer(renderer),
+      mFunctionsGL(functionsGL),
+      mFunctionsWGL(functionsWGL),
+      mDevice(device),
+      mDeviceHandle(deviceHandle),
+      mWGLDevice(deviceContext),
+      mWGLContext(wglContext),
+      mSwapChainFormat(DXGI_FORMAT_UNKNOWN),
+      mSwapChainFlags(0),
+      mDepthBufferFormat(GL_NONE),
+      mFirstSwap(true),
+      mSwapChain(nullptr),
+      mSwapChain1(nullptr),
+      mColorRenderbufferID(0),
+      mRenderbufferBufferHandle(nullptr),
+      mDepthRenderbufferID(0),
+      mFramebufferID(0),
+      mTextureID(0),
+      mTextureHandle(nullptr),
+      mWidth(0),
+      mHeight(0),
+      mSwapInterval(1),
+      mOrientation(orientation)
+{
+}
+
+DXGISwapChainWindowSurfaceWGL::~DXGISwapChainWindowSurfaceWGL()
+{
+    if (mRenderbufferBufferHandle != nullptr)
+    {
+        mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mRenderbufferBufferHandle);
+        mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle);
+    }
+
+    if (mColorRenderbufferID != 0)
+    {
+        mStateManager->deleteRenderbuffer(mColorRenderbufferID);
+        mColorRenderbufferID = 0;
+    }
+
+    if (mDepthRenderbufferID != 0)
+    {
+        mStateManager->deleteRenderbuffer(mDepthRenderbufferID);
+        mDepthRenderbufferID = 0;
+    }
+
+    SafeRelease(mSwapChain);
+    SafeRelease(mSwapChain1);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::initialize(const DisplayImpl *displayImpl)
+{
+    if (mOrientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE)
+    {
+        // TODO(geofflang): Support the orientation extensions fully.  Currently only inverting Y is
+        // supported.  To support all orientations, an intermediate framebuffer will be needed with
+        // a blit before swap.
+        return egl::Error(EGL_BAD_ATTRIBUTE,
+                          "DXGISwapChainWindowSurfaceWGL requires an orientation of "
+                          "EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE.");
+    }
+
+    RECT rect;
+    if (!GetClientRect(mWindow, &rect))
+    {
+        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size.");
+    }
+    mWidth  = rect.right - rect.left;
+    mHeight = rect.bottom - rect.top;
+
+    mSwapChainFormat   = DXGI_FORMAT_R8G8B8A8_UNORM;
+    mSwapChainFlags    = 0;
+    mDepthBufferFormat = GL_DEPTH24_STENCIL8;
+
+    mFunctionsGL->genFramebuffers(1, &mFramebufferID);
+    mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
+    mFunctionsGL->genRenderbuffers(1, &mDepthRenderbufferID);
+
+    return createSwapChain();
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::makeCurrent()
+{
+    if (!mFunctionsWGL->makeCurrent(mWGLDevice, mWGLContext))
+    {
+        // TODO: What error type here?
+        return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::swap(const DisplayImpl *displayImpl)
+{
+    mFunctionsGL->flush();
+
+    egl::Error error = setObjectsLocked(false);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    HRESULT result = mSwapChain->Present(mSwapInterval, 0);
+    mFirstSwap     = false;
+
+    error = setObjectsLocked(true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (FAILED(result))
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result);
+    }
+
+    return checkForResize();
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::postSubBuffer(EGLint x,
+                                                        EGLint y,
+                                                        EGLint width,
+                                                        EGLint height)
+{
+    ASSERT(mSwapChain1 != nullptr);
+
+    mFunctionsGL->flush();
+
+    egl::Error error = setObjectsLocked(false);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    HRESULT result = S_OK;
+    if (mFirstSwap)
+    {
+        result     = mSwapChain1->Present(mSwapInterval, 0);
+        mFirstSwap = false;
+    }
+    else
+    {
+        RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
+                     static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)};
+        DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr};
+        result                         = mSwapChain1->Present1(mSwapInterval, 0, &params);
+    }
+
+    error = setObjectsLocked(true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (FAILED(result))
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result);
+    }
+
+    return checkForResize();
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    UNREACHABLE();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    ASSERT(mTextureHandle == nullptr);
+
+    const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+    GLuint textureID           = textureGL->getTextureID();
+
+    ID3D11Texture2D *colorBuffer = nullptr;
+    HRESULT result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+                                           reinterpret_cast<void **>(&colorBuffer));
+    if (FAILED(result))
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to query texture from swap chain, result: 0x%X",
+                          result);
+    }
+
+    mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, textureID,
+                                                       GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
+    SafeRelease(colorBuffer);
+    if (mTextureHandle == nullptr)
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
+                          HRESULT_CODE(GetLastError()));
+    }
+
+    if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mTextureHandle))
+    {
+        mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle);
+        mTextureHandle = nullptr;
+
+        return egl::Error(EGL_BAD_ALLOC, "Failed to lock D3D object, error: 0x%08x.",
+                          HRESULT_CODE(GetLastError()));
+    }
+
+    mTextureID = textureID;
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+    ASSERT(mTextureHandle != nullptr);
+
+    if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mTextureHandle))
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to unlock D3D object, error: 0x%08x.",
+                          HRESULT_CODE(GetLastError()));
+    }
+
+    if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle))
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to unregister D3D object, error: 0x%08x.",
+                          HRESULT_CODE(GetLastError()));
+    }
+
+    mTextureID     = 0;
+    mTextureHandle = nullptr;
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+void DXGISwapChainWindowSurfaceWGL::setSwapInterval(EGLint interval)
+{
+    mSwapInterval = interval;
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::getWidth() const
+{
+    return static_cast<EGLint>(mWidth);
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::getHeight() const
+{
+    return static_cast<EGLint>(mHeight);
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::isPostSubBufferSupported() const
+{
+    return mSwapChain1 != nullptr;
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::getSwapBehavior() const
+{
+    return EGL_BUFFER_DESTROYED;
+}
+
+FramebufferImpl *DXGISwapChainWindowSurfaceWGL::createDefaultFramebuffer(
+    const gl::FramebufferState &data)
+{
+    return new FramebufferGL(mFramebufferID, data, mFunctionsGL, mWorkarounds,
+                             mRenderer->getBlitter(), mStateManager);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::setObjectsLocked(bool locked)
+{
+    if (mRenderbufferBufferHandle == nullptr)
+    {
+        ASSERT(mTextureHandle == nullptr);
+        return egl::Error(EGL_SUCCESS);
+    }
+
+    HANDLE resources[] = {
+        mRenderbufferBufferHandle, mTextureHandle,
+    };
+    GLint count = (mTextureHandle != nullptr) ? 2 : 1;
+
+    if (locked)
+    {
+        if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, count, resources))
+        {
+            return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+                              HRESULT_CODE(GetLastError()));
+        }
+    }
+    else
+    {
+        if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, count, resources))
+        {
+            return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+                              HRESULT_CODE(GetLastError()));
+        }
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::checkForResize()
+{
+    RECT rect;
+    if (!GetClientRect(mWindow, &rect))
+    {
+        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size.");
+    }
+
+    size_t newWidth  = rect.right - rect.left;
+    size_t newHeight = rect.bottom - rect.top;
+    if (newWidth != mWidth || newHeight != mHeight)
+    {
+        mWidth  = newWidth;
+        mHeight = newHeight;
+
+        // TODO(geofflang): Handle resize by resizing the swap chain instead of re-creating it.
+        egl::Error error = createSwapChain();
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+static IDXGIFactory *GetDXGIFactoryFromDevice(ID3D11Device *device)
+{
+    IDXGIDevice *dxgiDevice = nullptr;
+    HRESULT result =
+        device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDevice));
+    if (FAILED(result))
+    {
+        return nullptr;
+    }
+
+    IDXGIAdapter *dxgiAdapter = nullptr;
+    result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void **>(&dxgiAdapter));
+    SafeRelease(dxgiDevice);
+    if (FAILED(result))
+    {
+        return nullptr;
+    }
+
+    IDXGIFactory *dxgiFactory = nullptr;
+    result =
+        dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&dxgiFactory));
+    SafeRelease(dxgiAdapter);
+    if (FAILED(result))
+    {
+        return nullptr;
+    }
+
+    return dxgiFactory;
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::createSwapChain()
+{
+    egl::Error error = setObjectsLocked(false);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (mRenderbufferBufferHandle)
+    {
+        mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle);
+        mRenderbufferBufferHandle = nullptr;
+    }
+
+    // If this surface is bound to a texture, unregister it.
+    bool hadBoundSurface = (mTextureHandle != nullptr);
+    if (hadBoundSurface)
+    {
+        mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle);
+        mTextureHandle = nullptr;
+    }
+
+    IDXGIFactory *dxgiFactory = GetDXGIFactoryFromDevice(mDevice);
+    if (dxgiFactory == nullptr)
+    {
+        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the DXGIFactory.");
+    }
+
+    IDXGIFactory2 *dxgiFactory2 = nullptr;
+    HRESULT result = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2),
+                                                 reinterpret_cast<void **>(&dxgiFactory2));
+    if (SUCCEEDED(result))
+    {
+        ASSERT(dxgiFactory2 != nullptr);
+
+        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+        swapChainDesc.BufferCount           = 1;
+        swapChainDesc.Format                = mSwapChainFormat;
+        swapChainDesc.Width                 = static_cast<UINT>(mWidth);
+        swapChainDesc.Height                = static_cast<UINT>(mHeight);
+        swapChainDesc.Format                = mSwapChainFormat;
+        swapChainDesc.Stereo                = FALSE;
+        swapChainDesc.SampleDesc.Count      = 1;
+        swapChainDesc.SampleDesc.Quality = 0;
+        swapChainDesc.BufferUsage =
+            DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+        swapChainDesc.BufferCount = 1;
+        swapChainDesc.Scaling     = DXGI_SCALING_STRETCH;
+        swapChainDesc.SwapEffect  = DXGI_SWAP_EFFECT_SEQUENTIAL;
+        swapChainDesc.AlphaMode   = DXGI_ALPHA_MODE_UNSPECIFIED;
+        swapChainDesc.Flags       = mSwapChainFlags;
+
+        result = dxgiFactory2->CreateSwapChainForHwnd(mDevice, mWindow, &swapChainDesc, nullptr,
+                                                      nullptr, &mSwapChain1);
+        SafeRelease(dxgiFactory2);
+        SafeRelease(dxgiFactory);
+        if (FAILED(result))
+        {
+            return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X",
+                              result);
+        }
+
+        mSwapChain = mSwapChain1;
+        mSwapChain->AddRef();
+    }
+    else
+    {
+        DXGI_SWAP_CHAIN_DESC swapChainDesc               = {};
+        swapChainDesc.BufferCount                        = 1;
+        swapChainDesc.BufferDesc.Format                  = mSwapChainFormat;
+        swapChainDesc.BufferDesc.Width                   = static_cast<UINT>(mWidth);
+        swapChainDesc.BufferDesc.Height                  = static_cast<UINT>(mHeight);
+        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_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+        swapChainDesc.Flags              = mSwapChainFlags;
+        swapChainDesc.OutputWindow       = mWindow;
+        swapChainDesc.SampleDesc.Count   = 1;
+        swapChainDesc.SampleDesc.Quality = 0;
+        swapChainDesc.Windowed           = TRUE;
+        swapChainDesc.SwapEffect         = DXGI_SWAP_EFFECT_DISCARD;
+
+        result = dxgiFactory->CreateSwapChain(mDevice, &swapChainDesc, &mSwapChain);
+        SafeRelease(dxgiFactory);
+        if (FAILED(result))
+        {
+            return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X",
+                              result);
+        }
+    }
+
+    ID3D11Texture2D *colorBuffer = nullptr;
+    result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+                                   reinterpret_cast<void **>(&colorBuffer));
+    if (FAILED(result))
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to query texture from swap chain, result: 0x%X",
+                          result);
+    }
+
+    mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
+    mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID);
+    mRenderbufferBufferHandle =
+        mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mColorRenderbufferID,
+                                          GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV);
+    SafeRelease(colorBuffer);
+    if (mRenderbufferBufferHandle == nullptr)
+    {
+        return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.",
+                          HRESULT_CODE(GetLastError()));
+    }
+
+    // Rebind the surface to the texture if needed.
+    if (hadBoundSurface)
+    {
+        mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mTextureID,
+                                                           GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
+        if (mTextureHandle == nullptr)
+        {
+            return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.",
+                              HRESULT_CODE(GetLastError()));
+        }
+    }
+
+    error = setObjectsLocked(true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ASSERT(mFramebufferID != 0);
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+    mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                                          mColorRenderbufferID);
+
+    if (mDepthBufferFormat != GL_NONE)
+    {
+        ASSERT(mDepthRenderbufferID != 0);
+        mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferID);
+        mFunctionsGL->renderbufferStorage(GL_RENDERBUFFER, mDepthBufferFormat,
+                                          static_cast<GLsizei>(mWidth),
+                                          static_cast<GLsizei>(mHeight));
+
+        const gl::InternalFormat &depthStencilFormatInfo =
+            gl::GetSizedInternalFormatInfo(mDepthBufferFormat);
+        if (depthStencilFormatInfo.depthBits > 0)
+        {
+            mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                                                  GL_RENDERBUFFER, mDepthRenderbufferID);
+        }
+        if (depthStencilFormatInfo.stencilBits > 0)
+        {
+            mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                                  GL_RENDERBUFFER, mDepthRenderbufferID);
+        }
+    }
+
+    mFirstSwap = true;
+
+    return egl::Error(EGL_SUCCESS);
+}
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h
new file mode 100644
index 0000000..a4c34a7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h
@@ -0,0 +1,106 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DXGISwapChainWindowSurfaceWGL.h: WGL implementation of egl::Surface for windows using a DXGI
+// swapchain.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsGL;
+class FunctionsWGL;
+class DisplayWGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class DXGISwapChainWindowSurfaceWGL : public SurfaceGL
+{
+  public:
+    DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState &state,
+                                  RendererGL *renderer,
+                                  EGLNativeWindowType window,
+                                  ID3D11Device *device,
+                                  HANDLE deviceHandle,
+                                  HGLRC wglContext,
+                                  HDC deviceContext,
+                                  const FunctionsGL *functionsGL,
+                                  const FunctionsWGL *functionsWGL,
+                                  EGLint orientation);
+    ~DXGISwapChainWindowSurfaceWGL() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    egl::Error makeCurrent() override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
+
+  private:
+    egl::Error setObjectsLocked(bool locked);
+    egl::Error checkForResize();
+
+    egl::Error createSwapChain();
+
+    EGLNativeWindowType mWindow;
+
+    StateManagerGL *mStateManager;
+    const WorkaroundsGL &mWorkarounds;
+    RendererGL *mRenderer;
+    const FunctionsGL *mFunctionsGL;
+    const FunctionsWGL *mFunctionsWGL;
+
+    ID3D11Device *mDevice;
+    HANDLE mDeviceHandle;
+
+    HDC mWGLDevice;
+    HGLRC mWGLContext;
+
+    DXGI_FORMAT mSwapChainFormat;
+    UINT mSwapChainFlags;
+    GLenum mDepthBufferFormat;
+
+    bool mFirstSwap;
+    IDXGISwapChain *mSwapChain;
+    IDXGISwapChain1 *mSwapChain1;
+
+    GLuint mColorRenderbufferID;
+    HANDLE mRenderbufferBufferHandle;
+
+    GLuint mDepthRenderbufferID;
+
+    GLuint mFramebufferID;
+
+    GLuint mTextureID;
+    HANDLE mTextureHandle;
+
+    size_t mWidth;
+    size_t mHeight;
+
+    EGLint mSwapInterval;
+
+    EGLint mOrientation;
+};
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
new file mode 100644
index 0000000..daa6363
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
@@ -0,0 +1,760 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayWGL.h: WGL implementation of egl::Display
+
+#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+#include "platform/Platform.h"
+
+#include <EGL/eglext.h>
+#include <string>
+#include <sstream>
+
+namespace rx
+{
+
+class FunctionsGLWindows : public FunctionsGL
+{
+  public:
+    FunctionsGLWindows(HMODULE openGLModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL)
+        : mOpenGLModule(openGLModule),
+          mGetProcAddressWGL(getProcAddressWGL)
+    {
+        ASSERT(mOpenGLModule);
+        ASSERT(mGetProcAddressWGL);
+    }
+
+    ~FunctionsGLWindows() override {}
+
+  private:
+    void *loadProcAddress(const std::string &function) override
+    {
+        void *proc = reinterpret_cast<void*>(mGetProcAddressWGL(function.c_str()));
+        if (!proc)
+        {
+            proc = reinterpret_cast<void*>(GetProcAddress(mOpenGLModule, function.c_str()));
+        }
+        return proc;
+    }
+
+    HMODULE mOpenGLModule;
+    PFNWGLGETPROCADDRESSPROC mGetProcAddressWGL;
+};
+
+DisplayWGL::DisplayWGL(const egl::DisplayState &state)
+    : DisplayGL(state),
+      mOpenGLModule(nullptr),
+      mFunctionsWGL(nullptr),
+      mFunctionsGL(nullptr),
+      mHasRobustness(false),
+      mWindowClass(0),
+      mWindow(nullptr),
+      mDeviceContext(nullptr),
+      mPixelFormat(0),
+      mWGLContext(nullptr),
+      mUseDXGISwapChains(false),
+      mHasDXInterop(false),
+      mDxgiModule(nullptr),
+      mD3d11Module(nullptr),
+      mD3D11DeviceHandle(nullptr),
+      mD3D11Device(nullptr),
+      mDisplay(nullptr)
+{
+}
+
+DisplayWGL::~DisplayWGL()
+{
+}
+
+egl::Error DisplayWGL::initialize(egl::Display *display)
+{
+    mDisplay = display;
+
+    mOpenGLModule = LoadLibraryA("opengl32.dll");
+    if (!mOpenGLModule)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to load OpenGL library.");
+    }
+
+    mFunctionsWGL = new FunctionsWGL();
+    mFunctionsWGL->initialize(mOpenGLModule, nullptr);
+
+    // WGL can't grab extensions until it creates a context because it needs to load the driver's DLLs first.
+    // Create a dummy context to load the driver and determine which GL versions are available.
+
+    // Work around compile error from not defining "UNICODE" while Chromium does
+    const LPSTR idcArrow = MAKEINTRESOURCEA(32512);
+
+    std::string className = FormatString("ANGLE DisplayWGL 0x%0.8p Intermediate Window Class", mDisplay);
+
+    WNDCLASSA intermediateClassDesc = { 0 };
+    intermediateClassDesc.style = CS_OWNDC;
+    intermediateClassDesc.lpfnWndProc = DefWindowProc;
+    intermediateClassDesc.cbClsExtra = 0;
+    intermediateClassDesc.cbWndExtra = 0;
+    intermediateClassDesc.hInstance = GetModuleHandle(nullptr);
+    intermediateClassDesc.hIcon = nullptr;
+    intermediateClassDesc.hCursor = LoadCursorA(nullptr, idcArrow);
+    intermediateClassDesc.hbrBackground = 0;
+    intermediateClassDesc.lpszMenuName = nullptr;
+    intermediateClassDesc.lpszClassName = className.c_str();
+    mWindowClass = RegisterClassA(&intermediateClassDesc);
+    if (!mWindowClass)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to register intermediate OpenGL window class.");
+    }
+
+    HWND dummyWindow = CreateWindowExA(0,
+                                       reinterpret_cast<const char *>(mWindowClass),
+                                       "ANGLE Dummy Window",
+                                       WS_OVERLAPPEDWINDOW,
+                                       CW_USEDEFAULT,
+                                       CW_USEDEFAULT,
+                                       CW_USEDEFAULT,
+                                       CW_USEDEFAULT,
+                                       nullptr,
+                                       nullptr,
+                                       nullptr,
+                                       nullptr);
+    if (!dummyWindow)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to create dummy OpenGL window.");
+    }
+
+    HDC dummyDeviceContext = GetDC(dummyWindow);
+    if (!dummyDeviceContext)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to get the device context of the dummy OpenGL window.");
+    }
+
+    const PIXELFORMATDESCRIPTOR pixelFormatDescriptor = wgl::GetDefaultPixelFormatDescriptor();
+
+    int dummyPixelFormat = ChoosePixelFormat(dummyDeviceContext, &pixelFormatDescriptor);
+    if (dummyPixelFormat == 0)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not find a compatible pixel format for the dummy OpenGL window.");
+    }
+
+    if (!SetPixelFormat(dummyDeviceContext, dummyPixelFormat, &pixelFormatDescriptor))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window.");
+    }
+
+    HGLRC dummyWGLContext = mFunctionsWGL->createContext(dummyDeviceContext);
+    if (!dummyDeviceContext)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to create a WGL context for the dummy OpenGL window.");
+    }
+
+    if (!mFunctionsWGL->makeCurrent(dummyDeviceContext, dummyWGLContext))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the dummy WGL context current.");
+    }
+
+    // Grab the GL version from this context and use it as the maximum version available.
+    typedef const GLubyte* (GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+    PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(GetProcAddress(mOpenGLModule, "glGetString"));
+    if (!getString)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to get glGetString pointer.");
+    }
+
+    // Reinitialize the wgl functions to grab the extensions
+    mFunctionsWGL->initialize(mOpenGLModule, dummyDeviceContext);
+
+    bool hasWGLCreateContextRobustness =
+        mFunctionsWGL->hasExtension("WGL_ARB_create_context_robustness");
+
+    // Destroy the dummy window and context
+    mFunctionsWGL->makeCurrent(dummyDeviceContext, nullptr);
+    mFunctionsWGL->deleteContext(dummyWGLContext);
+    ReleaseDC(dummyWindow, dummyDeviceContext);
+    DestroyWindow(dummyWindow);
+
+    const egl::AttributeMap &displayAttributes = display->getAttributeMap();
+    EGLint requestedDisplayType = static_cast<EGLint>(displayAttributes.get(
+        EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
+    if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
+        !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es2_profile") &&
+        !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es_profile"))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED,
+                          "Cannot create an OpenGL ES platform on Windows without "
+                          "the WGL_EXT_create_context_es(2)_profile extension.");
+    }
+
+    // Create the real intermediate context and windows
+    mWindow = CreateWindowExA(0,
+                              reinterpret_cast<const char *>(mWindowClass),
+                              "ANGLE Intermediate Window",
+                              WS_OVERLAPPEDWINDOW,
+                              CW_USEDEFAULT,
+                              CW_USEDEFAULT,
+                              CW_USEDEFAULT,
+                              CW_USEDEFAULT,
+                              nullptr,
+                              nullptr,
+                              nullptr,
+                              nullptr);
+    if (!mWindow)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to create intermediate OpenGL window.");
+    }
+
+    mDeviceContext = GetDC(mWindow);
+    if (!mDeviceContext)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to get the device context of the intermediate OpenGL window.");
+    }
+
+    if (mFunctionsWGL->choosePixelFormatARB)
+    {
+        std::vector<int> attribs = wgl::GetDefaultPixelFormatAttributes(false);
+
+        UINT matchingFormats = 0;
+        mFunctionsWGL->choosePixelFormatARB(mDeviceContext, &attribs[0], nullptr, 1u, &mPixelFormat,
+                                            &matchingFormats);
+    }
+
+    if (mPixelFormat == 0)
+    {
+        mPixelFormat = ChoosePixelFormat(mDeviceContext, &pixelFormatDescriptor);
+    }
+
+    if (mPixelFormat == 0)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not find a compatible pixel format for the intermediate OpenGL window.");
+    }
+
+    if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window.");
+    }
+
+    if (mFunctionsWGL->createContextAttribsARB)
+    {
+        int flags = 0;
+        // TODO: allow debug contexts
+        // TODO: handle robustness
+
+        int mask = 0;
+
+        if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+        {
+            mask |= WGL_CONTEXT_ES_PROFILE_BIT_EXT;
+        }
+        else
+        {
+            // Request core profile
+            mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+        }
+
+        std::vector<int> contextCreationAttributes;
+
+        if (hasWGLCreateContextRobustness)
+        {
+            contextCreationAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+            contextCreationAttributes.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
+        }
+
+        // Don't request a specific version unless the user wants one.  WGL will return the highest version
+        // that the driver supports if no version is requested.
+        EGLint requestedMajorVersion = static_cast<EGLint>(
+            displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
+        EGLint requestedMinorVersion = static_cast<EGLint>(
+            displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
+        if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE)
+        {
+            contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
+            contextCreationAttributes.push_back(requestedMajorVersion);
+
+            contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+            contextCreationAttributes.push_back(requestedMinorVersion);
+        }
+        else
+        {
+            // the ES profile will give us ES version 1.1 unless a higher version is requested.
+            // Requesting version 2.0 will give us the highest compatible version available (2.0,
+            // 3.0, 3.1, etc).
+            if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+            {
+                contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
+                contextCreationAttributes.push_back(2);
+
+                contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+                contextCreationAttributes.push_back(0);
+            }
+        }
+
+        // Set the flag attributes
+        if (flags != 0)
+        {
+            contextCreationAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
+            contextCreationAttributes.push_back(flags);
+        }
+
+        // Set the mask attribute
+        if (mask != 0)
+        {
+            contextCreationAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
+            contextCreationAttributes.push_back(mask);
+        }
+
+        // Signal the end of the attributes
+        contextCreationAttributes.push_back(0);
+        contextCreationAttributes.push_back(0);
+
+        mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, nullptr,
+                                                             &contextCreationAttributes[0]);
+    }
+
+    // If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext
+    if (!mWGLContext)
+    {
+        // Don't have control over GL versions
+        mWGLContext = mFunctionsWGL->createContext(mDeviceContext);
+    }
+
+    if (!mWGLContext)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to create a WGL context for the intermediate OpenGL window.");
+    }
+
+    if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the intermediate WGL context current.");
+    }
+
+    mFunctionsGL = new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress);
+    mFunctionsGL->initialize();
+
+    mHasRobustness = mFunctionsGL->getGraphicsResetStatus != nullptr;
+    if (hasWGLCreateContextRobustness != mHasRobustness)
+    {
+        WARN() << "WGL_ARB_create_context_robustness exists but unable to OpenGL context with "
+                  "robustness.";
+    }
+
+    // Intel OpenGL ES drivers are not currently supported due to bugs in the driver and ANGLE
+    VendorID vendor = GetVendorID(mFunctionsGL);
+    if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE && IsIntel(vendor))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Intel OpenGL ES drivers are not supported.");
+    }
+
+    // Create DXGI swap chains for windows that come from other processes.  Windows is unable to
+    // SetPixelFormat on windows from other processes when a sandbox is enabled.
+    HDC nativeDisplay = display->getNativeDisplayId();
+    HWND nativeWindow = WindowFromDC(nativeDisplay);
+    if (nativeWindow != nullptr)
+    {
+        DWORD currentProcessId = GetCurrentProcessId();
+        DWORD windowProcessId;
+        GetWindowThreadProcessId(nativeWindow, &windowProcessId);
+
+        // AMD drivers advertise the WGL_NV_DX_interop and WGL_NV_DX_interop2 extensions but fail
+        mUseDXGISwapChains = !IsAMD(vendor) && (currentProcessId != windowProcessId);
+    }
+    else
+    {
+        mUseDXGISwapChains = false;
+    }
+
+    mHasDXInterop = mFunctionsWGL->hasExtension("WGL_NV_DX_interop2");
+
+    if (mUseDXGISwapChains)
+    {
+        if (mHasDXInterop)
+        {
+            ANGLE_TRY(initializeD3DDevice());
+        }
+        else
+        {
+            // Want to use DXGI swap chains but WGL_NV_DX_interop2 is not present, fail initialization
+            return egl::Error(EGL_NOT_INITIALIZED, "WGL_NV_DX_interop2 is required but not present.");
+        }
+    }
+
+    return DisplayGL::initialize(display);
+}
+
+void DisplayWGL::terminate()
+{
+    DisplayGL::terminate();
+
+    releaseD3DDevice(mD3D11DeviceHandle);
+
+    mFunctionsWGL->makeCurrent(mDeviceContext, nullptr);
+    mFunctionsWGL->deleteContext(mWGLContext);
+    mWGLContext = nullptr;
+
+    ReleaseDC(mWindow, mDeviceContext);
+    mDeviceContext = nullptr;
+
+    DestroyWindow(mWindow);
+    mWindow = nullptr;
+
+    UnregisterClassA(reinterpret_cast<const char *>(mWindowClass), nullptr);
+    mWindowClass = NULL;
+
+    SafeDelete(mFunctionsWGL);
+    SafeDelete(mFunctionsGL);
+
+    FreeLibrary(mOpenGLModule);
+    mOpenGLModule = nullptr;
+
+    SafeRelease(mD3D11Device);
+
+    if (mDxgiModule)
+    {
+        FreeLibrary(mDxgiModule);
+        mDxgiModule = nullptr;
+    }
+
+    if (mD3d11Module)
+    {
+        FreeLibrary(mD3d11Module);
+        mD3d11Module = nullptr;
+    }
+
+    ASSERT(mRegisteredD3DDevices.empty());
+}
+
+SurfaceImpl *DisplayWGL::createWindowSurface(const egl::SurfaceState &state,
+                                             EGLNativeWindowType window,
+                                             const egl::AttributeMap &attribs)
+{
+    EGLint orientation = static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
+    if (mUseDXGISwapChains)
+    {
+        egl::Error error = initializeD3DDevice();
+        if (error.isError())
+        {
+            return nullptr;
+        }
+
+        return new DXGISwapChainWindowSurfaceWGL(state, getRenderer(), window, mD3D11Device,
+                                                 mD3D11DeviceHandle, mWGLContext, mDeviceContext,
+                                                 mFunctionsGL, mFunctionsWGL, orientation);
+    }
+    else
+    {
+        return new WindowSurfaceWGL(state, getRenderer(), window, mPixelFormat, mWGLContext,
+                                    mFunctionsWGL, orientation);
+    }
+}
+
+SurfaceImpl *DisplayWGL::createPbufferSurface(const egl::SurfaceState &state,
+                                              const egl::AttributeMap &attribs)
+{
+    EGLint width          = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
+    EGLint height         = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
+    bool largest = (attribs.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
+    EGLenum textureFormat = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
+    EGLenum textureTarget = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
+
+    return new PbufferSurfaceWGL(state, getRenderer(), width, height, textureFormat, textureTarget,
+                                 largest, mPixelFormat, mDeviceContext, mWGLContext, mFunctionsWGL);
+}
+
+SurfaceImpl *DisplayWGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                                       EGLenum buftype,
+                                                       EGLClientBuffer clientBuffer,
+                                                       const egl::AttributeMap &attribs)
+{
+    egl::Error error = initializeD3DDevice();
+    if (error.isError())
+    {
+        return nullptr;
+    }
+
+    return new D3DTextureSurfaceWGL(state, getRenderer(), buftype, clientBuffer, this, mWGLContext,
+                                    mDeviceContext, mD3D11Device, mFunctionsGL, mFunctionsWGL);
+}
+
+SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state,
+                                             NativePixmapType nativePixmap,
+                                             const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+egl::Error DisplayWGL::getDevice(DeviceImpl **device)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::ConfigSet DisplayWGL::generateConfigs()
+{
+    egl::ConfigSet configs;
+
+    int minSwapInterval = 1;
+    int maxSwapInterval = 1;
+    if (mFunctionsWGL->swapIntervalEXT)
+    {
+        // No defined maximum swap interval in WGL_EXT_swap_control, use a reasonable number
+        minSwapInterval = 0;
+        maxSwapInterval = 8;
+    }
+
+    const gl::Version &maxVersion = getMaxSupportedESVersion();
+    ASSERT(maxVersion >= gl::Version(2, 0));
+    bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
+    PIXELFORMATDESCRIPTOR pixelFormatDescriptor;
+    DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor), &pixelFormatDescriptor);
+
+    auto getAttrib = [this](int attrib)
+    {
+        return wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, attrib, mFunctionsWGL);
+    };
+
+    const EGLint optimalSurfaceOrientation =
+        mUseDXGISwapChains ? EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE : 0;
+
+    egl::Config config;
+    config.renderTargetFormat = GL_RGBA8; // TODO: use the bit counts to determine the format
+    config.depthStencilFormat = GL_DEPTH24_STENCIL8; // TODO: use the bit counts to determine the format
+    config.bufferSize = pixelFormatDescriptor.cColorBits;
+    config.redSize = pixelFormatDescriptor.cRedBits;
+    config.greenSize = pixelFormatDescriptor.cGreenBits;
+    config.blueSize = pixelFormatDescriptor.cBlueBits;
+    config.luminanceSize = 0;
+    config.alphaSize = pixelFormatDescriptor.cAlphaBits;
+    config.alphaMaskSize = 0;
+    config.bindToTextureRGB   = (getAttrib(WGL_BIND_TO_TEXTURE_RGB_ARB) == TRUE);
+    config.bindToTextureRGBA  = (getAttrib(WGL_BIND_TO_TEXTURE_RGBA_ARB) == TRUE);
+    config.colorBufferType = EGL_RGB_BUFFER;
+    config.configCaveat = EGL_NONE;
+    config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+    config.depthSize = pixelFormatDescriptor.cDepthBits;
+    config.level = 0;
+    config.matchNativePixmap = EGL_NONE;
+    config.maxPBufferWidth    = getAttrib(WGL_MAX_PBUFFER_WIDTH_ARB);
+    config.maxPBufferHeight   = getAttrib(WGL_MAX_PBUFFER_HEIGHT_ARB);
+    config.maxPBufferPixels   = getAttrib(WGL_MAX_PBUFFER_PIXELS_ARB);
+    config.maxSwapInterval = maxSwapInterval;
+    config.minSwapInterval = minSwapInterval;
+    config.nativeRenderable = EGL_TRUE; // Direct rendering
+    config.nativeVisualID = 0;
+    config.nativeVisualType = EGL_NONE;
+    config.renderableType = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+    config.sampleBuffers = 0; // FIXME: enumerate multi-sampling
+    config.samples = 0;
+    config.stencilSize = pixelFormatDescriptor.cStencilBits;
+    config.surfaceType =
+        ((pixelFormatDescriptor.dwFlags & PFD_DRAW_TO_WINDOW) ? EGL_WINDOW_BIT : 0) |
+        ((getAttrib(WGL_DRAW_TO_PBUFFER_ARB) == TRUE) ? EGL_PBUFFER_BIT : 0) |
+        ((getAttrib(WGL_SWAP_METHOD_ARB) == WGL_SWAP_COPY_ARB) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT
+                                                               : 0);
+    config.optimalOrientation = optimalSurfaceOrientation;
+    config.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+
+    config.transparentType = EGL_NONE;
+    config.transparentRedValue = 0;
+    config.transparentGreenValue = 0;
+    config.transparentBlueValue = 0;
+
+    configs.add(config);
+
+    return configs;
+}
+
+bool DisplayWGL::testDeviceLost()
+{
+    if (mHasRobustness)
+    {
+        return getRenderer()->getResetStatus() != GL_NO_ERROR;
+    }
+
+    return false;
+}
+
+egl::Error DisplayWGL::restoreLostDevice()
+{
+    return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayWGL::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    return (IsWindow(window) == TRUE);
+}
+
+egl::Error DisplayWGL::validateClientBuffer(const egl::Config *configuration,
+                                            EGLenum buftype,
+                                            EGLClientBuffer clientBuffer,
+                                            const egl::AttributeMap &attribs) const
+{
+    switch (buftype)
+    {
+        case EGL_D3D_TEXTURE_ANGLE:
+        case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+            ANGLE_TRY(const_cast<DisplayWGL*>(this)->initializeD3DDevice());
+            return D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(buftype, clientBuffer,
+                                                                        mD3D11Device);
+
+        default:
+            return DisplayGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+    }
+}
+
+std::string DisplayWGL::getVendorString() const
+{
+    //UNIMPLEMENTED();
+    return "";
+}
+
+const FunctionsGL *DisplayWGL::getFunctionsGL() const
+{
+    return mFunctionsGL;
+}
+
+egl::Error DisplayWGL::initializeD3DDevice()
+{
+    if (mD3D11Device != nullptr)
+    {
+        return egl::Error(EGL_SUCCESS);
+    }
+
+    mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
+    if (!mDxgiModule)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to load DXGI library.");
+    }
+
+    mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+    if (!mD3d11Module)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Failed to load d3d11 library.");
+    }
+
+    PFN_D3D11_CREATE_DEVICE d3d11CreateDevice = nullptr;
+    d3d11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+        GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
+    if (d3d11CreateDevice == nullptr)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not retrieve D3D11CreateDevice address.");
+    }
+
+    HRESULT result = d3d11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0,
+                                       D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr);
+    if (FAILED(result))
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Could not create D3D11 device, error: 0x%X",
+                          result);
+    }
+
+    egl::Error error = registerD3DDevice(mD3D11Device, &mD3D11DeviceHandle);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+    // Only enable the surface orientation  and post sub buffer for DXGI swap chain surfaces, they
+    // prefer to swap with inverted Y.
+    outExtensions->postSubBuffer      = mUseDXGISwapChains;
+    outExtensions->surfaceOrientation = mUseDXGISwapChains;
+
+    outExtensions->createContextRobustness = mHasRobustness;
+
+    outExtensions->d3dTextureClientBuffer         = mHasDXInterop;
+    outExtensions->d3dShareHandleClientBuffer     = mHasDXInterop;
+    outExtensions->surfaceD3DTexture2DShareHandle = true;
+    outExtensions->querySurfacePointer            = true;
+    outExtensions->keyedMutex                     = true;
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
+}
+
+void DisplayWGL::generateCaps(egl::Caps *outCaps) const
+{
+    outCaps->textureNPOT = true;
+}
+
+egl::Error DisplayWGL::waitClient() const
+{
+    // Unimplemented as this is not needed for WGL
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayWGL::waitNative(EGLint engine,
+                                  egl::Surface *drawSurface,
+                                  egl::Surface *readSurface) const
+{
+    // Unimplemented as this is not needed for WGL
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayWGL::registerD3DDevice(IUnknown *device, HANDLE *outHandle)
+{
+    ASSERT(device != nullptr);
+    ASSERT(outHandle != nullptr);
+
+    auto iter = mRegisteredD3DDevices.find(device);
+    if (iter != mRegisteredD3DDevices.end())
+    {
+        iter->second.refCount++;
+        *outHandle = iter->second.handle;
+        return egl::Error(EGL_SUCCESS);
+    }
+
+    HANDLE handle = mFunctionsWGL->dxOpenDeviceNV(device);
+    if (!handle)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Failed to open D3D device.");
+    }
+
+    device->AddRef();
+
+    D3DObjectHandle newDeviceInfo;
+    newDeviceInfo.handle          = handle;
+    newDeviceInfo.refCount        = 1;
+    mRegisteredD3DDevices[device] = newDeviceInfo;
+
+    *outHandle = handle;
+    return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayWGL::releaseD3DDevice(HANDLE deviceHandle)
+{
+    for (auto iter = mRegisteredD3DDevices.begin(); iter != mRegisteredD3DDevices.end(); iter++)
+    {
+        if (iter->second.handle == deviceHandle)
+        {
+            iter->second.refCount--;
+            if (iter->second.refCount == 0)
+            {
+                mFunctionsWGL->dxCloseDeviceNV(iter->second.handle);
+                iter->first->Release();
+                mRegisteredD3DDevices.erase(iter);
+                break;
+            }
+        }
+    }
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
new file mode 100644
index 0000000..9e7477d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
@@ -0,0 +1,107 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayWGL.h: WGL implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+class DisplayWGL : public DisplayGL
+{
+  public:
+    DisplayWGL(const egl::DisplayState &state);
+    ~DisplayWGL() override;
+
+    egl::Error initialize(egl::Display *display) override;
+    void terminate() override;
+
+    // Surface creation
+    SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+                                     EGLNativeWindowType window,
+                                     const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+                                      const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                               EGLenum buftype,
+                                               EGLClientBuffer clientBuffer,
+                                               const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+                                     NativePixmapType nativePixmap,
+                                     const egl::AttributeMap &attribs) override;
+
+    egl::ConfigSet generateConfigs() override;
+
+    bool testDeviceLost() override;
+    egl::Error restoreLostDevice() override;
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+    egl::Error validateClientBuffer(const egl::Config *configuration,
+                                    EGLenum buftype,
+                                    EGLClientBuffer clientBuffer,
+                                    const egl::AttributeMap &attribs) const override;
+
+    egl::Error getDevice(DeviceImpl **device) override;
+
+    std::string getVendorString() const override;
+
+    egl::Error waitClient() const override;
+    egl::Error waitNative(EGLint engine,
+                          egl::Surface *drawSurface,
+                          egl::Surface *readSurface) const override;
+
+    egl::Error registerD3DDevice(IUnknown *device, HANDLE *outHandle);
+    void releaseD3DDevice(HANDLE handle);
+
+  private:
+    const FunctionsGL *getFunctionsGL() const override;
+
+    egl::Error initializeD3DDevice();
+
+    void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+    void generateCaps(egl::Caps *outCaps) const override;
+
+    HMODULE mOpenGLModule;
+
+    FunctionsWGL *mFunctionsWGL;
+    FunctionsGL *mFunctionsGL;
+
+    bool mHasRobustness;
+
+    ATOM mWindowClass;
+    HWND mWindow;
+    HDC mDeviceContext;
+    int mPixelFormat;
+    HGLRC mWGLContext;
+
+    bool mUseDXGISwapChains;
+    bool mHasDXInterop;
+    HMODULE mDxgiModule;
+    HMODULE mD3d11Module;
+    HANDLE mD3D11DeviceHandle;
+    ID3D11Device *mD3D11Device;
+
+    struct D3DObjectHandle
+    {
+        HANDLE handle;
+        size_t refCount;
+    };
+    std::map<IUnknown *, D3DObjectHandle> mRegisteredD3DDevices;
+
+    egl::Display *mDisplay;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
new file mode 100644
index 0000000..2cfe6e9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
@@ -0,0 +1,181 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsWGL.h: Implements the FuntionsWGL class.
+
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+#include <algorithm>
+
+#include "common/string_utils.h"
+
+namespace rx
+{
+
+template <typename T>
+static void GetWGLProcAddress(HMODULE glModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL,
+                              const std::string &procName, T *outProcAddress)
+{
+    T proc = nullptr;
+    if (getProcAddressWGL)
+    {
+        proc = reinterpret_cast<T>(getProcAddressWGL(procName.c_str()));
+    }
+
+    if (!proc)
+    {
+        proc = reinterpret_cast<T>(GetProcAddress(glModule, procName.c_str()));
+    }
+
+    *outProcAddress = proc;
+}
+
+template <typename T>
+static void GetWGLExtensionProcAddress(HMODULE glModule,
+                                       PFNWGLGETPROCADDRESSPROC getProcAddressWGL,
+                                       const std::vector<std::string> &extensions,
+                                       const std::string &extensionName,
+                                       const std::string &procName,
+                                       T *outProcAddress)
+{
+    T proc = nullptr;
+    if (std::find(extensions.begin(), extensions.end(), extensionName) != extensions.end())
+    {
+        GetWGLProcAddress(glModule, getProcAddressWGL, procName, &proc);
+    }
+
+    *outProcAddress = proc;
+}
+
+FunctionsWGL::FunctionsWGL()
+    : copyContext(nullptr),
+      createContext(nullptr),
+      createLayerContext(nullptr),
+      deleteContext(nullptr),
+      getCurrentContext(nullptr),
+      getCurrentDC(nullptr),
+      getProcAddress(nullptr),
+      makeCurrent(nullptr),
+      shareLists(nullptr),
+      useFontBitmapsA(nullptr),
+      useFontBitmapsW(nullptr),
+      swapBuffers(nullptr),
+      useFontOutlinesA(nullptr),
+      useFontOutlinesW(nullptr),
+      describeLayerPlane(nullptr),
+      setLayerPaletteEntries(nullptr),
+      getLayerPaletteEntries(nullptr),
+      realizeLayerPalette(nullptr),
+      swapLayerBuffers(nullptr),
+      swapMultipleBuffers(nullptr),
+      getExtensionStringEXT(nullptr),
+      getExtensionStringARB(nullptr),
+      createContextAttribsARB(nullptr),
+      getPixelFormatAttribivARB(nullptr),
+      getPixelFormatAttribfvARB(nullptr),
+      choosePixelFormatARB(nullptr),
+      swapIntervalEXT(nullptr),
+      createPbufferARB(nullptr),
+      getPbufferDCARB(nullptr),
+      releasePbufferDCARB(nullptr),
+      destroyPbufferARB(nullptr),
+      queryPbufferARB(nullptr),
+      bindTexImageARB(nullptr),
+      releaseTexImageARB(nullptr),
+      setPbufferAttribARB(nullptr),
+      dxSetResourceShareHandleNV(nullptr),
+      dxOpenDeviceNV(nullptr),
+      dxCloseDeviceNV(nullptr),
+      dxRegisterObjectNV(nullptr),
+      dxUnregisterObjectNV(nullptr),
+      dxObjectAccessNV(nullptr),
+      dxLockObjectsNV(nullptr),
+      dxUnlockObjectsNV(nullptr)
+{
+}
+
+void FunctionsWGL::initialize(HMODULE glModule, HDC context)
+{
+    // First grab the wglGetProcAddress function from the gl module
+    GetWGLProcAddress(glModule, nullptr, "wglGetProcAddress", &getProcAddress);
+
+    // Load the core wgl functions
+    GetWGLProcAddress(glModule, getProcAddress, "wglCopyContext", &copyContext);
+    GetWGLProcAddress(glModule, getProcAddress, "wglCreateContext", &createContext);
+    GetWGLProcAddress(glModule, getProcAddress, "wglCreateLayerContext", &createLayerContext);
+    GetWGLProcAddress(glModule, getProcAddress, "wglDeleteContext", &deleteContext);
+    GetWGLProcAddress(glModule, getProcAddress, "wglGetCurrentContext", &getCurrentContext);
+    GetWGLProcAddress(glModule, getProcAddress, "wglGetCurrentDC", &getCurrentDC);
+    GetWGLProcAddress(glModule, getProcAddress, "wglMakeCurrent", &makeCurrent);
+    GetWGLProcAddress(glModule, getProcAddress, "wglShareLists", &shareLists);
+    GetWGLProcAddress(glModule, getProcAddress, "wglUseFontBitmapsA", &useFontBitmapsA);
+    GetWGLProcAddress(glModule, getProcAddress, "wglUseFontBitmapsW", &useFontBitmapsW);
+    swapBuffers = SwapBuffers; // SwapBuffers is statically linked from GDI
+    GetWGLProcAddress(glModule, getProcAddress, "wglUseFontOutlinesA", &useFontOutlinesA);
+    GetWGLProcAddress(glModule, getProcAddress, "wglUseFontOutlinesW", &useFontOutlinesW);
+    GetWGLProcAddress(glModule, getProcAddress, "wglDescribeLayerPlane", &describeLayerPlane);
+    GetWGLProcAddress(glModule, getProcAddress, "wglSetLayerPaletteEntries", &setLayerPaletteEntries);
+    GetWGLProcAddress(glModule, getProcAddress, "wglGetLayerPaletteEntries", &getLayerPaletteEntries);
+    GetWGLProcAddress(glModule, getProcAddress, "wglRealizeLayerPalette", &realizeLayerPalette);
+    GetWGLProcAddress(glModule, getProcAddress, "wglSwapLayerBuffers", &swapLayerBuffers);
+    GetWGLProcAddress(glModule, getProcAddress, "wglSwapMultipleBuffers", &swapMultipleBuffers);
+
+    // Load extension string getter functions
+    GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringEXT", &getExtensionStringEXT);
+    GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringARB", &getExtensionStringARB);
+
+    std::string extensionString = "";
+    if (getExtensionStringEXT)
+    {
+        extensionString = getExtensionStringEXT();
+    }
+    else if (getExtensionStringARB && context)
+    {
+        extensionString = getExtensionStringARB(context);
+    }
+    angle::SplitStringAlongWhitespace(extensionString, &extensions);
+
+    // Load the wgl extension functions by checking if the context supports the extension first
+
+    // WGL_ARB_create_context
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_create_context", "wglCreateContextAttribsARB", &createContextAttribsARB);
+
+    // WGL_ARB_pixel_format
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglGetPixelFormatAttribivARB", &getPixelFormatAttribivARB);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglGetPixelFormatAttribfvARB", &getPixelFormatAttribfvARB);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglChoosePixelFormatARB", &choosePixelFormatARB);
+
+    // WGL_EXT_swap_control
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_EXT_swap_control", "wglSwapIntervalEXT", &swapIntervalEXT);
+
+    // WGL_ARB_pbuffer
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglCreatePbufferARB", &createPbufferARB);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglGetPbufferDCARB", &getPbufferDCARB);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglReleasePbufferDCARB", &releasePbufferDCARB);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglDestroyPbufferARB", &destroyPbufferARB);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglQueryPbufferARB", &queryPbufferARB);
+
+    // WGL_ARB_render_texture
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglBindTexImageARB", &bindTexImageARB);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglReleaseTexImageARB", &releaseTexImageARB);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglSetPbufferAttribARB", &setPbufferAttribARB);
+
+    // WGL_NV_DX_interop
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXSetResourceShareHandleNV", &dxSetResourceShareHandleNV);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXOpenDeviceNV", &dxOpenDeviceNV);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXCloseDeviceNV", &dxCloseDeviceNV);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXRegisterObjectNV", &dxRegisterObjectNV);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnregisterObjectNV", &dxUnregisterObjectNV);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXObjectAccessNV", &dxObjectAccessNV);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXLockObjectsNV", &dxLockObjectsNV);
+    GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnlockObjectsNV", &dxUnlockObjectsNV);
+}
+
+bool FunctionsWGL::hasExtension(const std::string &ext) const
+{
+    return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
+}
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
new file mode 100644
index 0000000..30cf9eb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsWGL.h: Defines the FuntionsWGL class to contain loaded WGL functions
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
+#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/gl/wgl/functionswgl_typedefs.h"
+
+namespace rx
+{
+
+class FunctionsWGL : angle::NonCopyable
+{
+  public:
+    FunctionsWGL();
+
+    // Loads all available wgl functions, may be called multiple times
+    void initialize(HMODULE glModule, HDC context);
+
+    // Extension information
+    std::vector<std::string> extensions;
+    bool hasExtension(const std::string &ext) const;
+
+    // Base WGL functions
+    PFNWGLCOPYCONTEXTPROC copyContext;
+    PFNWGLCREATECONTEXTPROC createContext;
+    PFNWGLCREATELAYERCONTEXTPROC createLayerContext;
+    PFNWGLDELETECONTEXTPROC deleteContext;
+    PFNWGLGETCURRENTCONTEXTPROC getCurrentContext;
+    PFNWGLGETCURRENTDCPROC getCurrentDC;
+    PFNWGLGETPROCADDRESSPROC getProcAddress;
+    PFNWGLMAKECURRENTPROC makeCurrent;
+    PFNWGLSHARELISTSPROC shareLists;
+    PFNWGLUSEFONTBITMAPSAPROC useFontBitmapsA;
+    PFNWGLUSEFONTBITMAPSWPROC useFontBitmapsW;
+    PFNSWAPBUFFERSPROC swapBuffers;
+    PFNWGLUSEFONTOUTLINESAPROC useFontOutlinesA;
+    PFNWGLUSEFONTOUTLINESWPROC useFontOutlinesW;
+    PFNWGLDESCRIBELAYERPLANEPROC describeLayerPlane;
+    PFNWGLSETLAYERPALETTEENTRIESPROC setLayerPaletteEntries;
+    PFNWGLGETLAYERPALETTEENTRIESPROC getLayerPaletteEntries;
+    PFNWGLREALIZELAYERPALETTEPROC realizeLayerPalette;
+    PFNWGLSWAPLAYERBUFFERSPROC swapLayerBuffers;
+    PFNWGLSWAPMULTIPLEBUFFERSPROC swapMultipleBuffers;
+
+    // WGL_EXT_extensions_string
+    PFNWGLGETEXTENSIONSSTRINGEXTPROC getExtensionStringEXT;
+
+    // WGL_ARB_extensions_string
+    PFNWGLGETEXTENSIONSSTRINGARBPROC getExtensionStringARB;
+
+    // WGL_ARB_create_context
+    PFNWGLCREATECONTEXTATTRIBSARBPROC createContextAttribsARB;
+
+    // WGL_ARB_pixel_format
+    PFNWGLGETPIXELFORMATATTRIBIVARBPROC getPixelFormatAttribivARB;
+    PFNWGLGETPIXELFORMATATTRIBFVARBPROC getPixelFormatAttribfvARB;
+    PFNWGLCHOOSEPIXELFORMATARBPROC choosePixelFormatARB;
+
+    // WGL_EXT_swap_control
+    PFNWGLSWAPINTERVALEXTPROC swapIntervalEXT;
+
+    // WGL_ARB_pbuffer
+    PFNWGLCREATEPBUFFERARBPROC createPbufferARB;
+    PFNWGLGETPBUFFERDCARBPROC getPbufferDCARB;
+    PFNWGLRELEASEPBUFFERDCARBPROC releasePbufferDCARB;
+    PFNWGLDESTROYPBUFFERARBPROC destroyPbufferARB;
+    PFNWGLQUERYPBUFFERARBPROC queryPbufferARB;
+
+    // WGL_ARB_render_texture
+    PFNWGLBINDTEXIMAGEARBPROC bindTexImageARB;
+    PFNWGLRELEASETEXIMAGEARBPROC releaseTexImageARB;
+    PFNWGLSETPBUFFERATTRIBARBPROC setPbufferAttribARB;
+
+    // WGL_NV_DX_interop
+    PFNWGLDXSETRESOURCESHAREHANDLENVPROC dxSetResourceShareHandleNV;
+    PFNWGLDXOPENDEVICENVPROC dxOpenDeviceNV;
+    PFNWGLDXCLOSEDEVICENVPROC dxCloseDeviceNV;
+    PFNWGLDXREGISTEROBJECTNVPROC dxRegisterObjectNV;
+    PFNWGLDXUNREGISTEROBJECTNVPROC dxUnregisterObjectNV;
+    PFNWGLDXOBJECTACCESSNVPROC dxObjectAccessNV;
+    PFNWGLDXLOCKOBJECTSNVPROC dxLockObjectsNV;
+    PFNWGLDXUNLOCKOBJECTSNVPROC dxUnlockObjectsNV;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp
new file mode 100644
index 0000000..0650e91e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp
@@ -0,0 +1,196 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceWGL.cpp: WGL implementation of egl::Surface
+
+#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+namespace rx
+{
+
+PbufferSurfaceWGL::PbufferSurfaceWGL(const egl::SurfaceState &state,
+                                     RendererGL *renderer,
+                                     EGLint width,
+                                     EGLint height,
+                                     EGLenum textureFormat,
+                                     EGLenum textureTarget,
+                                     bool largest,
+                                     int pixelFormat,
+                                     HDC deviceContext,
+                                     HGLRC wglContext,
+                                     const FunctionsWGL *functions)
+    : SurfaceGL(state, renderer),
+      mWidth(width),
+      mHeight(height),
+      mLargest(largest),
+      mTextureFormat(textureFormat),
+      mTextureTarget(textureTarget),
+      mPixelFormat(pixelFormat),
+      mShareWGLContext(wglContext),
+      mParentDeviceContext(deviceContext),
+      mPbuffer(nullptr),
+      mPbufferDeviceContext(nullptr),
+      mFunctionsWGL(functions)
+{
+}
+
+PbufferSurfaceWGL::~PbufferSurfaceWGL()
+{
+    mFunctionsWGL->releasePbufferDCARB(mPbuffer, mPbufferDeviceContext);
+    mPbufferDeviceContext = nullptr;
+
+    mFunctionsWGL->destroyPbufferARB(mPbuffer);
+    mPbuffer = nullptr;
+}
+
+static int GetWGLTextureType(EGLenum eglTextureType)
+{
+    switch (eglTextureType)
+    {
+      case EGL_NO_TEXTURE:    return WGL_NO_TEXTURE_ARB;
+      case EGL_TEXTURE_RGB:   return WGL_TEXTURE_RGB_ARB;
+      case EGL_TEXTURE_RGBA:  return WGL_TEXTURE_RGBA_ARB;
+      default: UNREACHABLE(); return 0;
+    }
+}
+
+static int GetWGLTextureTarget(EGLenum eglTextureTarget)
+{
+    switch (eglTextureTarget)
+    {
+      case EGL_NO_TEXTURE:    return WGL_NO_TEXTURE_ARB;
+      case EGL_TEXTURE_2D:    return WGL_TEXTURE_2D_ARB;
+      default: UNREACHABLE(); return 0;
+    }
+}
+
+egl::Error PbufferSurfaceWGL::initialize(const DisplayImpl *displayImpl)
+{
+    const int pbufferCreationAttributes[] =
+    {
+        WGL_PBUFFER_LARGEST_ARB, mLargest ? 1 : 0,
+        WGL_TEXTURE_FORMAT_ARB, GetWGLTextureType(mTextureFormat),
+        WGL_TEXTURE_TARGET_ARB, GetWGLTextureTarget(mTextureTarget),
+        0, 0,
+    };
+
+    mPbuffer = mFunctionsWGL->createPbufferARB(mParentDeviceContext, mPixelFormat, mWidth, mHeight,
+                                               pbufferCreationAttributes);
+    if (mPbuffer == nullptr)
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_ALLOC, "Failed to create a native WGL pbuffer, error: 0x%08x.", HRESULT_CODE(error));
+    }
+
+    // The returned pbuffer may not be as large as requested, update the size members.
+    if (mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_WIDTH_ARB, &mWidth) != TRUE ||
+        mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_HEIGHT_ARB, &mHeight) != TRUE)
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_ALLOC, "Failed to query the WGL pbuffer's dimensions, error: 0x%08x.", HRESULT_CODE(error));
+    }
+
+    mPbufferDeviceContext = mFunctionsWGL->getPbufferDCARB(mPbuffer);
+    if (mPbufferDeviceContext == nullptr)
+    {
+        mFunctionsWGL->destroyPbufferARB(mPbuffer);
+        mPbuffer = nullptr;
+
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_ALLOC, "Failed to get the WGL pbuffer handle, error: 0x%08x.", HRESULT_CODE(error));
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::makeCurrent()
+{
+    if (!mFunctionsWGL->makeCurrent(mPbufferDeviceContext, mShareWGLContext))
+    {
+        // TODO: What error type here?
+        return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::swap(const DisplayImpl *displayImpl)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    *value = nullptr;
+    return egl::Error(EGL_SUCCESS);
+}
+
+static int GetWGLBufferBindTarget(EGLint buffer)
+{
+    switch (buffer)
+    {
+      case EGL_BACK_BUFFER:   return WGL_BACK_LEFT_ARB;
+      default: UNREACHABLE(); return 0;
+    }
+}
+
+egl::Error PbufferSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_SURFACE, "Failed to bind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error));
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+    if (!mFunctionsWGL->releaseTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
+    {
+        DWORD error = GetLastError();
+        return egl::Error(EGL_BAD_SURFACE, "Failed to unbind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error));
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+void PbufferSurfaceWGL::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint PbufferSurfaceWGL::getWidth() const
+{
+    return mWidth;
+}
+
+EGLint PbufferSurfaceWGL::getHeight() const
+{
+    return mHeight;
+}
+
+EGLint PbufferSurfaceWGL::isPostSubBufferSupported() const
+{
+    return EGL_FALSE;
+}
+
+EGLint PbufferSurfaceWGL::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h
new file mode 100644
index 0000000..aed4279
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PBufferSurfaceWGL.h: WGL implementation of egl::Surface for PBuffers
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+class PbufferSurfaceWGL : public SurfaceGL
+{
+  public:
+    PbufferSurfaceWGL(const egl::SurfaceState &state,
+                      RendererGL *renderer,
+                      EGLint width,
+                      EGLint height,
+                      EGLenum textureFormat,
+                      EGLenum textureTarget,
+                      bool largest,
+                      int pixelFormat,
+                      HDC deviceContext,
+                      HGLRC wglContext,
+                      const FunctionsWGL *functions);
+    ~PbufferSurfaceWGL() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    egl::Error makeCurrent() override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+  private:
+    EGLint mWidth;
+    EGLint mHeight;
+    bool mLargest;
+    EGLenum mTextureFormat;
+    EGLenum mTextureTarget;
+
+    int mPixelFormat;
+
+    HGLRC mShareWGLContext;
+
+    HDC mParentDeviceContext;
+
+    HPBUFFERARB mPbuffer;
+    HDC mPbufferDeviceContext;
+
+    const FunctionsWGL *mFunctionsWGL;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
new file mode 100644
index 0000000..b686547
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
@@ -0,0 +1,178 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+namespace rx
+{
+
+WindowSurfaceWGL::WindowSurfaceWGL(const egl::SurfaceState &state,
+                                   RendererGL *renderer,
+                                   EGLNativeWindowType window,
+                                   int pixelFormat,
+                                   HGLRC wglContext,
+                                   const FunctionsWGL *functions,
+                                   EGLint orientation)
+    : SurfaceGL(state, renderer),
+      mPixelFormat(pixelFormat),
+      mWGLContext(wglContext),
+      mWindow(window),
+      mDeviceContext(nullptr),
+      mFunctionsWGL(functions),
+      mSwapBehavior(0)
+{
+    // EGL_ANGLE_surface_orientation is not supported for regular WGL window surfaces
+    ASSERT(orientation == 0);
+}
+
+WindowSurfaceWGL::~WindowSurfaceWGL()
+{
+    ReleaseDC(mWindow, mDeviceContext);
+    mDeviceContext = nullptr;
+}
+
+egl::Error WindowSurfaceWGL::initialize(const DisplayImpl *displayImpl)
+{
+    mDeviceContext = GetDC(mWindow);
+    if (!mDeviceContext)
+    {
+        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the device context from the native window, "
+                                                 "error: 0x%X.", GetLastError());
+    }
+
+    // Require that the pixel format for this window has not been set yet or is equal to the Display's pixel format.
+    int windowPixelFormat = GetPixelFormat(mDeviceContext);
+    if (windowPixelFormat == 0)
+    {
+        PIXELFORMATDESCRIPTOR pixelFormatDescriptor = { 0 };
+        if (!DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor), &pixelFormatDescriptor))
+        {
+            return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to DescribePixelFormat, error: 0x%X.", GetLastError());
+        }
+
+        if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
+        {
+            return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the device context, "
+                                                   "error: 0x%X.", GetLastError());
+        }
+    }
+    else if (windowPixelFormat != mPixelFormat)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED, "Pixel format of the NativeWindow and NativeDisplayType must match.");
+    }
+
+    // Check for the swap behavior of this pixel format
+    switch (
+        wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, WGL_SWAP_METHOD_ARB, mFunctionsWGL))
+    {
+        case WGL_SWAP_COPY_ARB:
+            mSwapBehavior = EGL_BUFFER_PRESERVED;
+            break;
+
+        case WGL_SWAP_EXCHANGE_ARB:
+        case WGL_SWAP_UNDEFINED_ARB:
+        default:
+            mSwapBehavior = EGL_BUFFER_DESTROYED;
+            break;
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::makeCurrent()
+{
+    if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
+    {
+        // TODO: What error type here?
+        return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::swap(const DisplayImpl *displayImpl)
+{
+    if (!mFunctionsWGL->swapBuffers(mDeviceContext))
+    {
+        // TODO: What error type here?
+        return egl::Error(EGL_CONTEXT_LOST, "Failed to swap buffers on the child window.");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    *value = nullptr;
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_SUCCESS);
+}
+
+void WindowSurfaceWGL::setSwapInterval(EGLint interval)
+{
+    if (mFunctionsWGL->swapIntervalEXT)
+    {
+        mFunctionsWGL->swapIntervalEXT(interval);
+    }
+}
+
+EGLint WindowSurfaceWGL::getWidth() const
+{
+    RECT rect;
+    if (!GetClientRect(mWindow, &rect))
+    {
+        return 0;
+    }
+    return rect.right - rect.left;
+}
+
+EGLint WindowSurfaceWGL::getHeight() const
+{
+    RECT rect;
+    if (!GetClientRect(mWindow, &rect))
+    {
+        return 0;
+    }
+    return rect.bottom - rect.top;
+}
+
+EGLint WindowSurfaceWGL::isPostSubBufferSupported() const
+{
+    // PostSubBuffer extension not exposed on WGL.
+    UNIMPLEMENTED();
+    return EGL_FALSE;
+}
+
+EGLint WindowSurfaceWGL::getSwapBehavior() const
+{
+    return mSwapBehavior;
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
new file mode 100644
index 0000000..981ef41
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowSurfaceWGL.h: WGL implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+class WindowSurfaceWGL : public SurfaceGL
+{
+  public:
+    WindowSurfaceWGL(const egl::SurfaceState &state,
+                     RendererGL *renderer,
+                     EGLNativeWindowType window,
+                     int pixelFormat,
+                     HGLRC wglContext,
+                     const FunctionsWGL *functions,
+                     EGLint orientation);
+    ~WindowSurfaceWGL() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    egl::Error makeCurrent() override;
+
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    void setSwapInterval(EGLint interval) override;
+
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+  private:
+    int mPixelFormat;
+
+    HGLRC mWGLContext;
+
+    HWND mWindow;
+    HDC mDeviceContext;
+
+    const FunctionsWGL *mFunctionsWGL;
+
+    EGLint mSwapBehavior;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h
new file mode 100644
index 0000000..c4b79ee
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// functionswgl_typedefs.h: Typedefs of WGL functions.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_
+
+#include "common/platform.h"
+
+#include <angle_gl.h>
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+typedef BOOL(WINAPI *PFNWGLCOPYCONTEXTPROC)(HGLRC, HGLRC, UINT);
+typedef HGLRC(WINAPI *PFNWGLCREATECONTEXTPROC)(HDC);
+typedef HGLRC(WINAPI *PFNWGLCREATELAYERCONTEXTPROC)(HDC, int);
+typedef BOOL(WINAPI *PFNWGLDELETECONTEXTPROC)(HGLRC);
+typedef HGLRC(WINAPI *PFNWGLGETCURRENTCONTEXTPROC)(VOID);
+typedef HDC(WINAPI *PFNWGLGETCURRENTDCPROC)(VOID);
+typedef PROC(WINAPI *PFNWGLGETPROCADDRESSPROC)(LPCSTR);
+typedef BOOL(WINAPI *PFNWGLMAKECURRENTPROC)(HDC, HGLRC);
+typedef BOOL(WINAPI *PFNWGLSHARELISTSPROC)(HGLRC, HGLRC);
+typedef BOOL(WINAPI *PFNWGLUSEFONTBITMAPSAPROC)(HDC, DWORD, DWORD, DWORD);
+typedef BOOL(WINAPI *PFNWGLUSEFONTBITMAPSWPROC)(HDC, DWORD, DWORD, DWORD);
+typedef BOOL(WINAPI *PFNSWAPBUFFERSPROC)(HDC);
+typedef BOOL(WINAPI *PFNWGLUSEFONTOUTLINESAPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
+typedef BOOL(WINAPI *PFNWGLUSEFONTOUTLINESWPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
+typedef BOOL(WINAPI *PFNWGLDESCRIBELAYERPLANEPROC)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
+typedef int(WINAPI *PFNWGLSETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, CONST COLORREF *);
+typedef int(WINAPI *PFNWGLGETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, COLORREF *);
+typedef BOOL(WINAPI *PFNWGLREALIZELAYERPALETTEPROC)(HDC, int, BOOL);
+typedef BOOL(WINAPI *PFNWGLSWAPLAYERBUFFERSPROC)(HDC, UINT);
+typedef DWORD(WINAPI *PFNWGLSWAPMULTIPLEBUFFERSPROC)(UINT, CONST WGLSWAP *);
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp
new file mode 100644
index 0000000..641c3fb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp
@@ -0,0 +1,85 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// wgl_utils.cpp: Utility routines specific to the WGL->EGL implementation.
+
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+namespace rx
+{
+
+namespace wgl
+{
+
+PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor()
+{
+    PIXELFORMATDESCRIPTOR pixelFormatDescriptor = { 0 };
+    pixelFormatDescriptor.nSize = sizeof(pixelFormatDescriptor);
+    pixelFormatDescriptor.nVersion = 1;
+    pixelFormatDescriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_GENERIC_ACCELERATED | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+    pixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA;
+    pixelFormatDescriptor.cColorBits = 24;
+    pixelFormatDescriptor.cAlphaBits = 8;
+    pixelFormatDescriptor.cDepthBits = 24;
+    pixelFormatDescriptor.cStencilBits = 8;
+    pixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE;
+
+    return pixelFormatDescriptor;
+}
+
+std::vector<int> GetDefaultPixelFormatAttributes(bool preservedSwap)
+{
+    std::vector<int> attribs;
+    attribs.push_back(WGL_DRAW_TO_WINDOW_ARB);
+    attribs.push_back(TRUE);
+
+    attribs.push_back(WGL_ACCELERATION_ARB);
+    attribs.push_back(WGL_FULL_ACCELERATION_ARB);
+
+    attribs.push_back(WGL_SUPPORT_OPENGL_ARB);
+    attribs.push_back(TRUE);
+
+    attribs.push_back(WGL_DOUBLE_BUFFER_ARB);
+    attribs.push_back(TRUE);
+
+    attribs.push_back(WGL_PIXEL_TYPE_ARB);
+    attribs.push_back(WGL_TYPE_RGBA_ARB);
+
+    attribs.push_back(WGL_COLOR_BITS_ARB);
+    attribs.push_back(24);
+
+    attribs.push_back(WGL_ALPHA_BITS_ARB);
+    attribs.push_back(8);
+
+    attribs.push_back(WGL_DEPTH_BITS_ARB);
+    attribs.push_back(24);
+
+    attribs.push_back(WGL_STENCIL_BITS_ARB);
+    attribs.push_back(8);
+
+    attribs.push_back(WGL_SWAP_METHOD_ARB);
+    attribs.push_back(preservedSwap ? WGL_SWAP_COPY_ARB : WGL_SWAP_UNDEFINED_ARB);
+
+    attribs.push_back(0);
+
+    return attribs;
+}
+
+int QueryWGLFormatAttrib(HDC dc, int format, int attribName, const FunctionsWGL *functions)
+{
+    int result = 0;
+    if (functions->getPixelFormatAttribivARB == nullptr ||
+        !functions->getPixelFormatAttribivARB(dc, format, 0, 1, &attribName, &result))
+    {
+        return 0;
+    }
+    return result;
+}
+}
+
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h
new file mode 100644
index 0000000..d4914b5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// wgl_utils.h: Utility routines specific to the WGL->EGL implementation.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_
+#define LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_
+
+#include <vector>
+
+#include "common/platform.h"
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+namespace wgl
+{
+
+PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor();
+std::vector<int> GetDefaultPixelFormatAttributes(bool preservedSwap);
+
+int QueryWGLFormatAttrib(HDC dc, int format, int attribName, const FunctionsWGL *functions);
+}
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/load_functions_data.json b/src/third_party/angle/src/libANGLE/renderer/load_functions_data.json
new file mode 100644
index 0000000..1982749
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/load_functions_data.json
@@ -0,0 +1,602 @@
+{
+  "GL_RG8_SNORM": {
+    "R8G8_SNORM": {
+      "GL_BYTE": "LoadToNative<GLbyte, 2>"
+    }
+  },
+  "GL_SRGB8": {
+    "R8G8B8A8_UNORM_SRGB": {
+      "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0xFF>"
+    }
+  },
+  "GL_RGBA8I": {
+    "R8G8B8A8_SINT": {
+      "GL_BYTE": "LoadToNative<GLbyte, 4>"
+    }
+  },
+  "GL_R8_SNORM": {
+    "R8_SNORM": {
+      "GL_BYTE": "LoadToNative<GLbyte, 1>"
+    }
+  },
+  "GL_RGBA8_SNORM": {
+    "R8G8B8A8_SNORM": {
+      "GL_BYTE": "LoadToNative<GLbyte, 4>"
+    }
+  },
+  "GL_R16I": {
+    "R16_SINT": {
+      "GL_SHORT": "LoadToNative<GLshort, 1>"
+    }
+  },
+  "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": {
+    "R8G8B8A8_UNORM_SRGB": {
+      "GL_UNSIGNED_BYTE": "LoadETC2SRGBA8ToSRGBA8"
+    }
+  },
+  "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadETC2RGB8A1ToRGBA8"
+    }
+  },
+  "GL_RGB32UI": {
+    "R32G32B32A32_UINT": {
+      "GL_UNSIGNED_INT": "LoadToNative3To4<GLuint, 0x00000001>"
+    }
+  },
+  "GL_ALPHA32F_EXT": {
+    "NONE": {
+      "GL_FLOAT": "LoadA32FToRGBA32F"
+    }
+  },
+  "GL_R16UI": {
+    "R16_UINT": {
+      "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
+    }
+  },
+  "GL_RGB9_E5": {
+    "R9G9B9E5_SHAREDEXP": {
+      "GL_HALF_FLOAT": "LoadRGB16FToRGB9E5",
+      "GL_UNSIGNED_INT_5_9_9_9_REV": "LoadToNative<GLuint, 1>",
+      "GL_FLOAT": "LoadRGB32FToRGB9E5",
+      "GL_HALF_FLOAT_OES": "LoadRGB16FToRGB9E5"
+    }
+  },
+  "GL_COMPRESSED_R11_EAC": {
+    "R8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadEACR11ToR8"
+    }
+  },
+  "GL_RGBA32UI": {
+    "R32G32B32A32_UINT": {
+      "GL_UNSIGNED_INT": "LoadToNative<GLuint, 4>"
+    }
+  },
+  "GL_RG8UI": {
+    "R8G8_UINT": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 2>"
+    }
+  },
+  "GL_LUMINANCE32F_EXT": {
+    "NONE": {
+      "GL_FLOAT": "LoadL32FToRGBA32F"
+    }
+  },
+  "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
+    "R8G8B8A8_UNORM_SRGB": {
+      "GL_UNSIGNED_BYTE": "LoadETC2SRGB8A1ToRGBA8"
+    }
+  },
+  "GL_R16F": {
+    "R16_FLOAT": {
+      "GL_HALF_FLOAT": "LoadToNative<GLhalf, 1>",
+      "GL_FLOAT": "Load32FTo16F<1>",
+      "GL_HALF_FLOAT_OES": "LoadToNative<GLhalf, 1>"
+    }
+  },
+  "GL_RGBA8UI": {
+    "R8G8B8A8_UINT": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+    }
+  },
+  "GL_BGRA4_ANGLEX": {
+    "NONE": {
+      "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": "LoadRGBA4ToRGBA8",
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+    }
+  },
+  "GL_RGBA16F": {
+    "R16G16B16A16_FLOAT": {
+      "GL_HALF_FLOAT": "LoadToNative<GLhalf, 4>",
+      "GL_FLOAT": "Load32FTo16F<4>",
+      "GL_HALF_FLOAT_OES": "LoadToNative<GLhalf, 4>"
+    }
+  },
+  "GL_LUMINANCE8_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadL8ToRGBA8"
+    }
+  },
+  "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+    }
+  },
+  "GL_RGB": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "UnreachableLoadFunction",
+      "GL_UNSIGNED_SHORT_5_6_5": "UnreachableLoadFunction"
+    }
+  },
+  "GL_RGB5_A1": {
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadRGB10A2ToRGBA8",
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>",
+      "GL_UNSIGNED_SHORT_5_5_5_1": "LoadRGB5A1ToRGBA8"
+    },
+    "B5G5R5A1_UNORM": {
+      "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadRGB10A2ToBGR5A1",
+      "GL_UNSIGNED_BYTE": "LoadRGBA8ToBGR5A1",
+      "GL_UNSIGNED_SHORT_5_5_5_1": "LoadRGB5A1ToA1RGB5"
+    }
+  },
+  "GL_RGB16UI": {
+    "R16G16B16A16_UINT": {
+      "GL_UNSIGNED_SHORT": "LoadToNative3To4<GLushort, 0x0001>"
+    }
+  },
+  "GL_BGRA_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+    }
+  },
+  "GL_COMPRESSED_RGB8_ETC2": {
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadETC2RGB8ToRGBA8"
+    }
+  },
+  "GL_RGBA32F": {
+    "R32G32B32A32_FLOAT": {
+      "GL_FLOAT": "LoadToNative<GLfloat, 4>"
+    }
+  },
+  "GL_RGBA32I": {
+    "R32G32B32A32_SINT": {
+      "GL_INT": "LoadToNative<GLint, 4>"
+    }
+  },
+  "GL_LUMINANCE8_ALPHA8_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadLA8ToRGBA8"
+    }
+  },
+  "GL_RG8": {
+    "R8G8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 2>"
+    }
+  },
+  "GL_RGB10_A2": {
+    "R10G10B10A2_UNORM": {
+      "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadToNative<GLuint, 1>"
+    }
+  },
+  "GL_COMPRESSED_SIGNED_RG11_EAC": {
+    "R8G8_SNORM": {
+      "GL_UNSIGNED_BYTE": "LoadEACRG11SToRG8"
+    }
+  },
+  "GL_DEPTH_COMPONENT16": {
+    "D16_UNORM": {
+      "GL_UNSIGNED_INT": "LoadR32ToR16",
+      "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
+    }
+  },
+  "GL_RGB32I": {
+    "R32G32B32A32_SINT": {
+      "GL_INT": "LoadToNative3To4<GLint, 0x00000001>"
+    }
+  },
+  "GL_R8": {
+    "R8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 1>"
+    }
+  },
+  "GL_RGB32F": {
+    "R32G32B32A32_FLOAT": {
+      "GL_FLOAT": "LoadToNative3To4<GLfloat, gl::Float32One>"
+    }
+  },
+  "GL_R11F_G11F_B10F": {
+    "R11G11B10_FLOAT": {
+      "GL_UNSIGNED_INT_10F_11F_11F_REV": "LoadToNative<GLuint, 1>",
+      "GL_HALF_FLOAT": "LoadRGB16FToRG11B10F",
+      "GL_FLOAT": "LoadRGB32FToRG11B10F",
+      "GL_HALF_FLOAT_OES": "LoadRGB16FToRG11B10F"
+    }
+  },
+  "GL_RGB8": {
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0xFF>"
+    }
+  },
+  "GL_LUMINANCE_ALPHA": {
+    "R16G16B16A16_FLOAT": {
+      "GL_HALF_FLOAT": "LoadLA16FToRGBA16F",
+      "GL_HALF_FLOAT_OES": "LoadLA16FToRGBA16F"
+    },
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+    },
+    "R32G32B32A32_FLOAT": {
+      "GL_FLOAT": "LoadLA32FToRGBA32F"
+    }
+  },
+  "GL_RGBA16I": {
+    "R16G16B16A16_SINT": {
+      "GL_SHORT": "LoadToNative<GLshort, 4>"
+    }
+  },
+  "GL_R8I": {
+    "R8_SINT": {
+      "GL_BYTE": "LoadToNative<GLbyte, 1>"
+    }
+  },
+  "GL_RGB8_SNORM": {
+    "R8G8B8A8_SNORM": {
+      "GL_BYTE": "LoadToNative3To4<GLbyte, 0x7F>"
+    }
+  },
+  "GL_RG32F": {
+    "R32G32_FLOAT": {
+      "GL_FLOAT": "LoadToNative<GLfloat, 2>"
+    }
+  },
+  "GL_DEPTH_COMPONENT32F": {
+    "D32_FLOAT": {
+      "GL_FLOAT": "LoadD32FToD32F"
+    }
+  },
+  "GL_RG32I": {
+    "R32G32_SINT": {
+      "GL_INT": "LoadToNative<GLint, 2>"
+    }
+  },
+  "GL_ALPHA8_EXT": {
+    "A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 1>"
+    },
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadA8ToRGBA8"
+    }
+  },
+  "GL_RG32UI": {
+    "R32G32_UINT": {
+      "GL_UNSIGNED_INT": "LoadToNative<GLuint, 2>"
+    }
+  },
+  "GL_RGBA16UI": {
+    "R16G16B16A16_UINT": {
+      "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 4>"
+    }
+  },
+  "GL_COMPRESSED_RGBA8_ETC2_EAC": {
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadETC2RGBA8ToRGBA8"
+    }
+  },
+  "GL_RGB8I": {
+    "R8G8B8A8_SINT": {
+      "GL_BYTE": "LoadToNative3To4<GLbyte, 0x01>"
+    }
+  },
+  "GL_COMPRESSED_SRGB8_ETC2": {
+    "R8G8B8A8_UNORM_SRGB": {
+      "GL_UNSIGNED_BYTE": "LoadETC2SRGB8ToRGBA8"
+    }
+  },
+  "GL_DEPTH32F_STENCIL8": {
+    "D32_FLOAT_S8X24_UINT": {
+      "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": "LoadD32FS8X24ToD32FS8X24"
+    }
+  },
+  "GL_RG8I": {
+    "R8G8_SINT": {
+      "GL_BYTE": "LoadToNative<GLbyte, 2>"
+    }
+  },
+  "GL_R32UI": {
+    "R32_UINT": {
+      "GL_UNSIGNED_INT": "LoadToNative<GLuint, 1>"
+    }
+  },
+  "GL_BGR5_A1_ANGLEX": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>",
+      "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": "LoadRGB5A1ToRGBA8"
+    }
+  },
+  "GL_BGR565_ANGLEX": {
+    "B5G6R5_UNORM": {
+      "GL_UNSIGNED_SHORT_5_6_5": "LoadRGB565ToBGR565",
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLushort, 1>"
+    }
+  },
+  "GL_COMPRESSED_RG11_EAC": {
+    "R8G8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadEACRG11ToRG8"
+    }
+  },
+  "GL_SRGB8_ALPHA8": {
+    "R8G8B8A8_UNORM_SRGB": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+    }
+  },
+  "GL_LUMINANCE_ALPHA16F_EXT": {
+    "NONE": {
+      "GL_HALF_FLOAT": "LoadLA16FToRGBA16F",
+      "GL_HALF_FLOAT_OES": "LoadLA16FToRGBA16F"
+    }
+  },
+  "GL_RGBA": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "UnreachableLoadFunction",
+      "GL_UNSIGNED_SHORT_4_4_4_4": "UnreachableLoadFunction",
+      "GL_UNSIGNED_SHORT_5_5_5_1": "UnreachableLoadFunction"
+    }
+  },
+  "GL_DEPTH24_STENCIL8": {
+    "D24_UNORM_S8_UINT": {
+      "GL_UNSIGNED_INT_24_8": "LoadR32ToR24G8"
+    }
+  },
+  "GL_RGB16I": {
+    "R16G16B16A16_SINT": {
+      "GL_SHORT": "LoadToNative3To4<GLshort, 0x0001>"
+    }
+  },
+  "GL_R8UI": {
+    "R8_UINT": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 1>"
+    }
+  },
+  "GL_ALPHA": {
+    "R16G16B16A16_FLOAT": {
+      "GL_HALF_FLOAT": "LoadA16FToRGBA16F",
+      "GL_HALF_FLOAT_OES": "LoadA16FToRGBA16F"
+    },
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+    },
+    "R32G32B32A32_FLOAT": {
+      "GL_FLOAT": "LoadA32FToRGBA32F"
+    }
+  },
+  "GL_RGB16F": {
+    "R16G16B16A16_FLOAT": {
+      "GL_HALF_FLOAT": "LoadToNative3To4<GLhalf, gl::Float16One>",
+      "GL_FLOAT": "LoadRGB32FToRGBA16F",
+      "GL_HALF_FLOAT_OES": "LoadToNative3To4<GLhalf, gl::Float16One>"
+    }
+  },
+  "GL_COMPRESSED_SIGNED_R11_EAC": {
+    "R8_SNORM": {
+      "GL_UNSIGNED_BYTE": "LoadEACR11SToR8"
+    }
+  },
+  "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+    }
+  },
+  "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+    }
+  },
+  "GL_STENCIL_INDEX8": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "UnimplementedLoadFunction"
+    }
+  },
+  "GL_LUMINANCE_ALPHA32F_EXT": {
+    "NONE": {
+      "GL_FLOAT": "LoadLA32FToRGBA32F"
+    }
+  },
+  "GL_RGB8UI": {
+    "R8G8B8A8_UINT": {
+      "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0x01>"
+    }
+  },
+  "GL_DEPTH_COMPONENT24": {
+    "D24_UNORM_S8_UINT": {
+      "GL_UNSIGNED_INT": "LoadR32ToR24G8"
+    }
+  },
+  "GL_R32I": {
+    "R32_SINT": {
+      "GL_INT": "LoadToNative<GLint, 1>"
+    }
+  },
+  "GL_DEPTH_COMPONENT32_OES": {
+    "NONE": {
+      "GL_UNSIGNED_INT": "LoadR32ToR24G8"
+    }
+  },
+  "GL_R32F": {
+    "R32_FLOAT": {
+      "GL_FLOAT": "LoadToNative<GLfloat, 1>"
+    }
+  },
+  "GL_RG16F": {
+    "R16G16_FLOAT": {
+      "GL_HALF_FLOAT": "LoadToNative<GLhalf, 2>",
+      "GL_FLOAT": "Load32FTo16F<2>",
+      "GL_HALF_FLOAT_OES": "LoadToNative<GLhalf, 2>"
+    }
+  },
+  "GL_RGB565": {
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0xFF>",
+      "GL_UNSIGNED_SHORT_5_6_5": "LoadR5G6B5ToRGBA8"
+    },
+    "B5G6R5_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadRGB8ToBGR565",
+      "GL_UNSIGNED_SHORT_5_6_5": "LoadToNative<GLushort, 1>"
+    }
+  },
+  "GL_LUMINANCE16F_EXT": {
+    "NONE": {
+      "GL_HALF_FLOAT": "LoadL16FToRGBA16F",
+      "GL_HALF_FLOAT_OES": "LoadL16FToRGBA16F"
+    }
+  },
+  "GL_RG16UI": {
+    "R16G16_UINT": {
+      "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 2>"
+    }
+  },
+  "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+    }
+  },
+  "GL_RG16I": {
+    "R16G16_SINT": {
+      "GL_SHORT": "LoadToNative<GLshort, 2>"
+    }
+  },
+  "GL_BGRA8_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+    }
+  },
+  "GL_ALPHA16F_EXT": {
+    "NONE": {
+      "GL_HALF_FLOAT": "LoadA16FToRGBA16F",
+      "GL_HALF_FLOAT_OES": "LoadA16FToRGBA16F"
+    }
+  },
+  "GL_RGBA4": {
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>",
+      "GL_UNSIGNED_SHORT_4_4_4_4": "LoadRGBA4ToRGBA8"
+    },
+    "B4G4R4A4_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadRGBA8ToBGRA4",
+      "GL_UNSIGNED_SHORT_4_4_4_4": "LoadRGBA4ToARGB4"
+    }
+  },
+  "GL_RGBA8": {
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+    }
+  },
+  "GL_LUMINANCE": {
+    "R16G16B16A16_FLOAT": {
+      "GL_HALF_FLOAT": "LoadL16FToRGBA16F",
+      "GL_HALF_FLOAT_OES": "LoadL16FToRGBA16F"
+    },
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+    },
+    "R32G32B32A32_FLOAT": {
+      "GL_FLOAT": "LoadL32FToRGBA32F"
+    }
+  },
+  "GL_RGB10_A2UI": {
+    "R10G10B10A2_UINT": {
+      "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadToNative<GLuint, 1>"
+    }
+  },
+  "GL_ETC1_RGB8_OES": {
+    "R8G8B8A8_UNORM": {
+      "GL_UNSIGNED_BYTE": "LoadETC1RGB8ToRGBA8"
+    }
+  },
+  "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": {
+    "BC1_RGB_UNORM_BLOCK": {
+      "GL_UNSIGNED_BYTE": "LoadETC1RGB8ToBC1"
+    }
+  },
+  "GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE": {
+    "BC1_RGB_UNORM_BLOCK": {
+      "GL_UNSIGNED_BYTE": "LoadETC2RGB8ToBC1"
+    }
+  },
+  "GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE": {
+    "BC1_RGB_UNORM_SRGB_BLOCK": {
+      "GL_UNSIGNED_BYTE": "LoadETC2SRGB8ToBC1"
+    }
+  },
+  "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": {
+    "BC1_RGBA_UNORM_BLOCK": {
+      "GL_UNSIGNED_BYTE": "LoadETC2RGB8A1ToBC1"
+    }
+  },
+  "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": {
+    "BC1_RGBA_UNORM_SRGB_BLOCK": {
+      "GL_UNSIGNED_BYTE": "LoadETC2SRGB8A1ToBC1"
+    }
+  },
+  "GL_R16_EXT": {
+    "R16_UNORM": {
+      "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
+    }
+  },
+  "GL_RG16_EXT": {
+    "R16G16_UNORM": {
+      "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 2>"
+    }
+  },
+  "GL_RGB16_EXT": {
+    "R16G16B16A16_UNORM": {
+      "GL_UNSIGNED_SHORT": "LoadToNative3To4<GLushort, 0xFFFF>"
+    }
+  },
+  "GL_RGBA16_EXT": {
+    "R16G16B16A16_UNORM": {
+      "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 4>"
+    }
+  },
+  "GL_R16_SNORM_EXT": {
+    "R16_SNORM": {
+      "GL_SHORT": "LoadToNative<GLushort, 1>"
+    }
+  },
+  "GL_RG16_SNORM_EXT": {
+    "R16G16_SNORM": {
+      "GL_SHORT": "LoadToNative<GLushort, 2>"
+    }
+  },
+  "GL_RGB16_SNORM_EXT": {
+    "R16G16B16A16_SNORM": {
+      "GL_SHORT": "LoadToNative3To4<GLushort, 0x7FFF>"
+    }
+  },
+  "GL_RGBA16_SNORM_EXT": {
+    "R16G16B16A16_SNORM": {
+      "GL_SHORT": "LoadToNative<GLushort, 4>"
+    }
+  },
+  "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+    }
+  },
+  "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+    }
+  },
+  "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+    }
+  },
+  "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT": {
+    "NONE": {
+      "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+    }
+  }
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/load_functions_table.h b/src/third_party/angle/src/libANGLE/renderer/load_functions_table.h
new file mode 100644
index 0000000..f3da31c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/load_functions_table.h
@@ -0,0 +1,22 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// load_functions_table:
+//   Contains load functions table depending on internal format and ANGLE format.
+//
+
+#ifndef LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
+#define LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
+
+#include "libANGLE/renderer/Format.h"
+
+namespace angle
+{
+
+rx::LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, Format::ID angleFormat);
+
+}  // namespace angle
+
+#endif  // LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp b/src/third_party/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp
new file mode 100644
index 0000000..ed9fe28
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp
@@ -0,0 +1,2459 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_load_functions_table.py using data from load_functions_data.json
+//
+// Copyright 2016 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.
+//
+// load_functions_table:
+//   Contains the GetLoadFunctionsMap for texture_format_util.h
+//
+
+#include "libANGLE/renderer/load_functions_table.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+using namespace rx;
+
+namespace angle
+{
+
+namespace
+{
+
+// ES3 image loading functions vary based on:
+//    - the GL internal format (supplied to glTex*Image*D)
+//    - the GL data type given (supplied to glTex*Image*D)
+//    - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D
+//    device's capabilities)
+// This map type determines which loading function to use, based on these three parameters.
+// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
+void UnimplementedLoadFunction(size_t width,
+                               size_t height,
+                               size_t depth,
+                               const uint8_t *input,
+                               size_t inputRowPitch,
+                               size_t inputDepthPitch,
+                               uint8_t *output,
+                               size_t outputRowPitch,
+                               size_t outputDepthPitch)
+{
+    UNIMPLEMENTED();
+}
+
+void UnreachableLoadFunction(size_t width,
+                             size_t height,
+                             size_t depth,
+                             const uint8_t *input,
+                             size_t inputRowPitch,
+                             size_t inputDepthPitch,
+                             uint8_t *output,
+                             size_t outputRowPitch,
+                             size_t outputDepthPitch)
+{
+    UNREACHABLE();
+}
+
+LoadImageFunctionInfo ALPHA_to_R16G16B16A16_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo ALPHA_to_R32G32B32A32_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadA32FToRGBA32F, true);
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo ALPHA_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo ALPHA16F_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo ALPHA32F_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadA32FToRGBA32F, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo ALPHA8_EXT_to_A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo ALPHA8_EXT_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadA8ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo BGR565_ANGLEX_to_B5G6R5_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+        case GL_UNSIGNED_SHORT_5_6_5:
+            return LoadImageFunctionInfo(LoadRGB565ToBGR565, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo BGR5_A1_ANGLEX_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+        case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+            return LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo BGRA4_ANGLEX_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+        case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+            return LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo BGRA8_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo BGRA_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_R11_EAC_to_R8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadEACR11ToR8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_RG11_EAC_to_R8G8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadEACRG11ToRG8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_ETC2_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2RGB8ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_BLOCK(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2RGB8ToBC1, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2RGB8A1ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo
+COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_BLOCK(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2RGB8A1ToBC1, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA8_ETC2_EAC_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2RGBA8ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 8>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_S3TC_DXT3_ANGLE_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 16>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_S3TC_DXT5_ANGLE_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 16>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 8>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_R11_EAC_to_R8_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadEACR11SToR8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_RG11_EAC_to_R8G8_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadEACRG11SToRG8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2SRGBA8ToSRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ETC2_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2SRGB8ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_SRGB_BLOCK(
+    GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2SRGB8ToBC1, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2SRGB8A1ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo
+COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_SRGB_BLOCK(
+    GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC2SRGB8A1ToBC1, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 8>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 16>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 16>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 8>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo DEPTH24_STENCIL8_to_D24_UNORM_S8_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT_24_8:
+            return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo DEPTH32F_STENCIL8_to_D32_FLOAT_S8X24_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+            return LoadImageFunctionInfo(LoadD32FS8X24ToD32FS8X24, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT16_to_D16_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT:
+            return LoadImageFunctionInfo(LoadR32ToR16, true);
+        case GL_UNSIGNED_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT24_to_D24_UNORM_S8_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT:
+            return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT32F_to_D32_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadD32FToD32F, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT32_OES_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT:
+            return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo ETC1_RGB8_LOSSY_DECODE_ANGLE_to_BC1_RGB_UNORM_BLOCK(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC1RGB8ToBC1, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo ETC1_RGB8_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadETC1RGB8ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE_to_R16G16B16A16_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE_to_R32G32B32A32_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE16F_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE32F_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE8_ALPHA8_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadLA8ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE8_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadL8ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA_to_R16G16B16A16_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA_to_R32G32B32A32_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadLA32FToRGBA32F, true);
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA16F_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA32F_EXT_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadLA32FToRGBA32F, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R11F_G11F_B10F_to_R11G11B10_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadRGB32FToRG11B10F, true);
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true);
+        case GL_UNSIGNED_INT_10F_11F_11F_REV:
+            return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R16F_to_R16_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(Load32FTo16F<1>, true);
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R16I_to_R16_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLshort, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R16UI_to_R16_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R16_EXT_to_R16_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R16_SNORM_EXT_to_R16_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R32F_to_R32_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadToNative<GLfloat, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R32I_to_R32_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_INT:
+            return LoadImageFunctionInfo(LoadToNative<GLint, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R32UI_to_R32_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT:
+            return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R8_to_R8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R8I_to_R8_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLbyte, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R8UI_to_R8_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo R8_SNORM_to_R8_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLbyte, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG16F_to_R16G16_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(Load32FTo16F<2>, true);
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadToNative<GLhalf, 2>, false);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadToNative<GLhalf, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG16I_to_R16G16_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLshort, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG16UI_to_R16G16_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG16_EXT_to_R16G16_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG16_SNORM_EXT_to_R16G16_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG32F_to_R32G32_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadToNative<GLfloat, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG32I_to_R32G32_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_INT:
+            return LoadImageFunctionInfo(LoadToNative<GLint, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG32UI_to_R32G32_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT:
+            return LoadImageFunctionInfo(LoadToNative<GLuint, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG8_to_R8G8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG8I_to_R8G8_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLbyte, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG8UI_to_R8G8_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RG8_SNORM_to_R8G8_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLbyte, 2>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        case GL_UNSIGNED_SHORT_5_6_5:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB10_A2_to_R10G10B10A2_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT_2_10_10_10_REV:
+            return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB10_A2UI_to_R10G10B10A2_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT_2_10_10_10_REV:
+            return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB16F_to_R16G16B16A16_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadRGB32FToRGBA16F, true);
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLhalf, gl::Float16One>, true);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLhalf, gl::Float16One>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB16I_to_R16G16B16A16_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_SHORT:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLshort, 0x0001>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB16UI_to_R16G16B16A16_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_SHORT:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLushort, 0x0001>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB16_EXT_to_R16G16B16A16_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_SHORT:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLushort, 0xFFFF>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB16_SNORM_EXT_to_R16G16B16A16_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_SHORT:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLushort, 0x7FFF>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB32F_to_R32G32B32A32_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLfloat, gl::Float32One>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB32I_to_R32G32B32A32_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_INT:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLint, 0x00000001>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB32UI_to_R32G32B32A32_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLuint, 0x00000001>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB565_to_B5G6R5_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadRGB8ToBGR565, true);
+        case GL_UNSIGNED_SHORT_5_6_5:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB565_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+        case GL_UNSIGNED_SHORT_5_6_5:
+            return LoadImageFunctionInfo(LoadR5G6B5ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB5_A1_to_B5G5R5A1_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadRGBA8ToBGR5A1, true);
+        case GL_UNSIGNED_INT_2_10_10_10_REV:
+            return LoadImageFunctionInfo(LoadRGB10A2ToBGR5A1, true);
+        case GL_UNSIGNED_SHORT_5_5_5_1:
+            return LoadImageFunctionInfo(LoadRGB5A1ToA1RGB5, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB5_A1_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+        case GL_UNSIGNED_INT_2_10_10_10_REV:
+            return LoadImageFunctionInfo(LoadRGB10A2ToRGBA8, true);
+        case GL_UNSIGNED_SHORT_5_5_5_1:
+            return LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB8_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB8I_to_R8G8B8A8_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLbyte, 0x01>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB8UI_to_R8G8B8A8_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0x01>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB8_SNORM_to_R8G8B8A8_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLbyte, 0x7F>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGB9_E5_to_R9G9B9E5_SHAREDEXP(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadRGB32FToRGB9E5, true);
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true);
+        case GL_UNSIGNED_INT_5_9_9_9_REV:
+            return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        case GL_UNSIGNED_SHORT_4_4_4_4:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        case GL_UNSIGNED_SHORT_5_5_5_1:
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA16F_to_R16G16B16A16_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(Load32FTo16F<4>, true);
+        case GL_HALF_FLOAT:
+            return LoadImageFunctionInfo(LoadToNative<GLhalf, 4>, false);
+        case GL_HALF_FLOAT_OES:
+            return LoadImageFunctionInfo(LoadToNative<GLhalf, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA16I_to_R16G16B16A16_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLshort, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA16UI_to_R16G16B16A16_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA16_EXT_to_R16G16B16A16_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA16_SNORM_EXT_to_R16G16B16A16_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_SHORT:
+            return LoadImageFunctionInfo(LoadToNative<GLushort, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA32F_to_R32G32B32A32_FLOAT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_FLOAT:
+            return LoadImageFunctionInfo(LoadToNative<GLfloat, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA32I_to_R32G32B32A32_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_INT:
+            return LoadImageFunctionInfo(LoadToNative<GLint, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA32UI_to_R32G32B32A32_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_INT:
+            return LoadImageFunctionInfo(LoadToNative<GLuint, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA4_to_B4G4R4A4_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadRGBA8ToBGRA4, true);
+        case GL_UNSIGNED_SHORT_4_4_4_4:
+            return LoadImageFunctionInfo(LoadRGBA4ToARGB4, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA4_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+        case GL_UNSIGNED_SHORT_4_4_4_4:
+            return LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA8_to_R8G8B8A8_UNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA8I_to_R8G8B8A8_SINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLbyte, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA8UI_to_R8G8B8A8_UINT(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo RGBA8_SNORM_to_R8G8B8A8_SNORM(GLenum type)
+{
+    switch (type)
+    {
+        case GL_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLbyte, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo SRGB8_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo SRGB8_ALPHA8_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+LoadImageFunctionInfo STENCIL_INDEX8_to_default(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(UnimplementedLoadFunction, true);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
+}  // namespace
+
+LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, Format::ID angleFormat)
+{
+    // clang-format off
+    switch (internalFormat)
+    {
+        case GL_ALPHA:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_FLOAT:
+                    return ALPHA_to_R16G16B16A16_FLOAT;
+                case Format::ID::R32G32B32A32_FLOAT:
+                    return ALPHA_to_R32G32B32A32_FLOAT;
+                default:
+                    return ALPHA_to_default;
+            }
+        }
+        case GL_ALPHA16F_EXT:
+            return ALPHA16F_EXT_to_default;
+        case GL_ALPHA32F_EXT:
+            return ALPHA32F_EXT_to_default;
+        case GL_ALPHA8_EXT:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::A8_UNORM:
+                    return ALPHA8_EXT_to_A8_UNORM;
+                case Format::ID::R8G8B8A8_UNORM:
+                    return ALPHA8_EXT_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_BGR565_ANGLEX:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::B5G6R5_UNORM:
+                    return BGR565_ANGLEX_to_B5G6R5_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_BGR5_A1_ANGLEX:
+            return BGR5_A1_ANGLEX_to_default;
+        case GL_BGRA4_ANGLEX:
+            return BGRA4_ANGLEX_to_default;
+        case GL_BGRA8_EXT:
+            return BGRA8_EXT_to_default;
+        case GL_BGRA_EXT:
+            return BGRA_EXT_to_default;
+        case GL_COMPRESSED_R11_EAC:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8_UNORM:
+                    return COMPRESSED_R11_EAC_to_R8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_RG11_EAC:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8_UNORM:
+                    return COMPRESSED_RG11_EAC_to_R8G8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_RGB8_ETC2:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM:
+                    return COMPRESSED_RGB8_ETC2_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::BC1_RGB_UNORM_BLOCK:
+                    return COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_BLOCK;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM:
+                    return COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::BC1_RGBA_UNORM_BLOCK:
+                    return COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_BLOCK;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_RGBA8_ETC2_EAC:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM:
+                    return COMPRESSED_RGBA8_ETC2_EAC_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+            return COMPRESSED_RGBA_S3TC_DXT1_EXT_to_default;
+        case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+            return COMPRESSED_RGBA_S3TC_DXT3_ANGLE_to_default;
+        case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+            return COMPRESSED_RGBA_S3TC_DXT5_ANGLE_to_default;
+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+            return COMPRESSED_RGB_S3TC_DXT1_EXT_to_default;
+        case GL_COMPRESSED_SIGNED_R11_EAC:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8_SNORM:
+                    return COMPRESSED_SIGNED_R11_EAC_to_R8_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_SIGNED_RG11_EAC:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8_SNORM:
+                    return COMPRESSED_SIGNED_RG11_EAC_to_R8G8_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM_SRGB:
+                    return COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_to_R8G8B8A8_UNORM_SRGB;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_SRGB8_ETC2:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM_SRGB:
+                    return COMPRESSED_SRGB8_ETC2_to_R8G8B8A8_UNORM_SRGB;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::BC1_RGB_UNORM_SRGB_BLOCK:
+                    return COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_SRGB_BLOCK;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM_SRGB:
+                    return COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM_SRGB;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK:
+                    return COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_SRGB_BLOCK;
+                default:
+                    break;
+            }
+        }
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+            return COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT_to_default;
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+            return COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT_to_default;
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+            return COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT_to_default;
+        case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+            return COMPRESSED_SRGB_S3TC_DXT1_EXT_to_default;
+        case GL_DEPTH24_STENCIL8:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::D24_UNORM_S8_UINT:
+                    return DEPTH24_STENCIL8_to_D24_UNORM_S8_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_DEPTH32F_STENCIL8:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::D32_FLOAT_S8X24_UINT:
+                    return DEPTH32F_STENCIL8_to_D32_FLOAT_S8X24_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_DEPTH_COMPONENT16:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::D16_UNORM:
+                    return DEPTH_COMPONENT16_to_D16_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_DEPTH_COMPONENT24:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::D24_UNORM_S8_UINT:
+                    return DEPTH_COMPONENT24_to_D24_UNORM_S8_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_DEPTH_COMPONENT32F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::D32_FLOAT:
+                    return DEPTH_COMPONENT32F_to_D32_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_DEPTH_COMPONENT32_OES:
+            return DEPTH_COMPONENT32_OES_to_default;
+        case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::BC1_RGB_UNORM_BLOCK:
+                    return ETC1_RGB8_LOSSY_DECODE_ANGLE_to_BC1_RGB_UNORM_BLOCK;
+                default:
+                    break;
+            }
+        }
+        case GL_ETC1_RGB8_OES:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM:
+                    return ETC1_RGB8_OES_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_LUMINANCE:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_FLOAT:
+                    return LUMINANCE_to_R16G16B16A16_FLOAT;
+                case Format::ID::R32G32B32A32_FLOAT:
+                    return LUMINANCE_to_R32G32B32A32_FLOAT;
+                default:
+                    return LUMINANCE_to_default;
+            }
+        }
+        case GL_LUMINANCE16F_EXT:
+            return LUMINANCE16F_EXT_to_default;
+        case GL_LUMINANCE32F_EXT:
+            return LUMINANCE32F_EXT_to_default;
+        case GL_LUMINANCE8_ALPHA8_EXT:
+            return LUMINANCE8_ALPHA8_EXT_to_default;
+        case GL_LUMINANCE8_EXT:
+            return LUMINANCE8_EXT_to_default;
+        case GL_LUMINANCE_ALPHA:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_FLOAT:
+                    return LUMINANCE_ALPHA_to_R16G16B16A16_FLOAT;
+                case Format::ID::R32G32B32A32_FLOAT:
+                    return LUMINANCE_ALPHA_to_R32G32B32A32_FLOAT;
+                default:
+                    return LUMINANCE_ALPHA_to_default;
+            }
+        }
+        case GL_LUMINANCE_ALPHA16F_EXT:
+            return LUMINANCE_ALPHA16F_EXT_to_default;
+        case GL_LUMINANCE_ALPHA32F_EXT:
+            return LUMINANCE_ALPHA32F_EXT_to_default;
+        case GL_R11F_G11F_B10F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R11G11B10_FLOAT:
+                    return R11F_G11F_B10F_to_R11G11B10_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_R16F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16_FLOAT:
+                    return R16F_to_R16_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_R16I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16_SINT:
+                    return R16I_to_R16_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_R16UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16_UINT:
+                    return R16UI_to_R16_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_R16_EXT:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16_UNORM:
+                    return R16_EXT_to_R16_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_R16_SNORM_EXT:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16_SNORM:
+                    return R16_SNORM_EXT_to_R16_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_R32F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32_FLOAT:
+                    return R32F_to_R32_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_R32I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32_SINT:
+                    return R32I_to_R32_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_R32UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32_UINT:
+                    return R32UI_to_R32_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_R8:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8_UNORM:
+                    return R8_to_R8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_R8I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8_SINT:
+                    return R8I_to_R8_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_R8UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8_UINT:
+                    return R8UI_to_R8_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_R8_SNORM:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8_SNORM:
+                    return R8_SNORM_to_R8_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RG16F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16_FLOAT:
+                    return RG16F_to_R16G16_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_RG16I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16_SINT:
+                    return RG16I_to_R16G16_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RG16UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16_UINT:
+                    return RG16UI_to_R16G16_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RG16_EXT:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16_UNORM:
+                    return RG16_EXT_to_R16G16_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RG16_SNORM_EXT:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16_SNORM:
+                    return RG16_SNORM_EXT_to_R16G16_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RG32F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32G32_FLOAT:
+                    return RG32F_to_R32G32_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_RG32I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32G32_SINT:
+                    return RG32I_to_R32G32_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RG32UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32G32_UINT:
+                    return RG32UI_to_R32G32_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RG8:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8_UNORM:
+                    return RG8_to_R8G8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RG8I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8_SINT:
+                    return RG8I_to_R8G8_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RG8UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8_UINT:
+                    return RG8UI_to_R8G8_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RG8_SNORM:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8_SNORM:
+                    return RG8_SNORM_to_R8G8_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB:
+            return RGB_to_default;
+        case GL_RGB10_A2:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R10G10B10A2_UNORM:
+                    return RGB10_A2_to_R10G10B10A2_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB10_A2UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R10G10B10A2_UINT:
+                    return RGB10_A2UI_to_R10G10B10A2_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB16F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_FLOAT:
+                    return RGB16F_to_R16G16B16A16_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB16I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_SINT:
+                    return RGB16I_to_R16G16B16A16_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB16UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_UINT:
+                    return RGB16UI_to_R16G16B16A16_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB16_EXT:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_UNORM:
+                    return RGB16_EXT_to_R16G16B16A16_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB16_SNORM_EXT:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_SNORM:
+                    return RGB16_SNORM_EXT_to_R16G16B16A16_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB32F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32G32B32A32_FLOAT:
+                    return RGB32F_to_R32G32B32A32_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB32I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32G32B32A32_SINT:
+                    return RGB32I_to_R32G32B32A32_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB32UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32G32B32A32_UINT:
+                    return RGB32UI_to_R32G32B32A32_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB565:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::B5G6R5_UNORM:
+                    return RGB565_to_B5G6R5_UNORM;
+                case Format::ID::R8G8B8A8_UNORM:
+                    return RGB565_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB5_A1:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::B5G5R5A1_UNORM:
+                    return RGB5_A1_to_B5G5R5A1_UNORM;
+                case Format::ID::R8G8B8A8_UNORM:
+                    return RGB5_A1_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB8:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM:
+                    return RGB8_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB8I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_SINT:
+                    return RGB8I_to_R8G8B8A8_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB8UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UINT:
+                    return RGB8UI_to_R8G8B8A8_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB8_SNORM:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_SNORM:
+                    return RGB8_SNORM_to_R8G8B8A8_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGB9_E5:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R9G9B9E5_SHAREDEXP:
+                    return RGB9_E5_to_R9G9B9E5_SHAREDEXP;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA:
+            return RGBA_to_default;
+        case GL_RGBA16F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_FLOAT:
+                    return RGBA16F_to_R16G16B16A16_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA16I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_SINT:
+                    return RGBA16I_to_R16G16B16A16_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA16UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_UINT:
+                    return RGBA16UI_to_R16G16B16A16_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA16_EXT:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_UNORM:
+                    return RGBA16_EXT_to_R16G16B16A16_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA16_SNORM_EXT:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R16G16B16A16_SNORM:
+                    return RGBA16_SNORM_EXT_to_R16G16B16A16_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA32F:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32G32B32A32_FLOAT:
+                    return RGBA32F_to_R32G32B32A32_FLOAT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA32I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32G32B32A32_SINT:
+                    return RGBA32I_to_R32G32B32A32_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA32UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R32G32B32A32_UINT:
+                    return RGBA32UI_to_R32G32B32A32_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA4:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::B4G4R4A4_UNORM:
+                    return RGBA4_to_B4G4R4A4_UNORM;
+                case Format::ID::R8G8B8A8_UNORM:
+                    return RGBA4_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA8:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM:
+                    return RGBA8_to_R8G8B8A8_UNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA8I:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_SINT:
+                    return RGBA8I_to_R8G8B8A8_SINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA8UI:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UINT:
+                    return RGBA8UI_to_R8G8B8A8_UINT;
+                default:
+                    break;
+            }
+        }
+        case GL_RGBA8_SNORM:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_SNORM:
+                    return RGBA8_SNORM_to_R8G8B8A8_SNORM;
+                default:
+                    break;
+            }
+        }
+        case GL_SRGB8:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM_SRGB:
+                    return SRGB8_to_R8G8B8A8_UNORM_SRGB;
+                default:
+                    break;
+            }
+        }
+        case GL_SRGB8_ALPHA8:
+        {
+            switch (angleFormat)
+            {
+                case Format::ID::R8G8B8A8_UNORM_SRGB:
+                    return SRGB8_ALPHA8_to_R8G8B8A8_UNORM_SRGB;
+                default:
+                    break;
+            }
+        }
+        case GL_STENCIL_INDEX8:
+            return STENCIL_INDEX8_to_default;
+
+        default:
+        {
+            static LoadFunctionMap emptyLoadFunctionsMap;
+            return emptyLoadFunctionsMap;
+        }
+    }
+    // clang-format on
+
+}  // GetLoadFunctionsMap
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/BufferNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/BufferNULL.cpp
new file mode 100644
index 0000000..0c5300d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/BufferNULL.cpp
@@ -0,0 +1,110 @@
+//
+// Copyright 2016 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.
+//
+// BufferNULL.cpp:
+//    Implements the class methods for BufferNULL.
+//
+
+#include "libANGLE/renderer/null/BufferNULL.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/null/ContextNULL.h"
+
+namespace rx
+{
+
+BufferNULL::BufferNULL(const gl::BufferState &state, AllocationTrackerNULL *allocationTracker)
+    : BufferImpl(state), mAllocationTracker(allocationTracker)
+{
+    ASSERT(mAllocationTracker != nullptr);
+}
+
+BufferNULL::~BufferNULL()
+{
+    bool memoryReleaseResult = mAllocationTracker->updateMemoryAllocation(mData.size(), 0);
+    ASSERT(memoryReleaseResult);
+}
+
+gl::Error BufferNULL::setData(ContextImpl *context,
+                              GLenum target,
+                              const void *data,
+                              size_t size,
+                              GLenum usage)
+{
+    if (!mAllocationTracker->updateMemoryAllocation(mData.size(), size))
+    {
+        return gl::OutOfMemory() << "Unable to allocate internal buffer storage.";
+    }
+
+    mData.resize(size, 0);
+    if (size > 0 && data != nullptr)
+    {
+        memcpy(mData.data(), data, size);
+    }
+    return gl::NoError();
+}
+
+gl::Error BufferNULL::setSubData(ContextImpl *context,
+                                 GLenum target,
+                                 const void *data,
+                                 size_t size,
+                                 size_t offset)
+{
+    if (size > 0)
+    {
+        memcpy(mData.data() + offset, data, size);
+    }
+    return gl::NoError();
+}
+
+gl::Error BufferNULL::copySubData(ContextImpl *context,
+                                  BufferImpl *source,
+                                  GLintptr sourceOffset,
+                                  GLintptr destOffset,
+                                  GLsizeiptr size)
+{
+    BufferNULL *sourceNULL = GetAs<BufferNULL>(source);
+    if (size > 0)
+    {
+        memcpy(mData.data() + destOffset, sourceNULL->mData.data() + sourceOffset, size);
+    }
+    return gl::NoError();
+}
+
+gl::Error BufferNULL::map(ContextImpl *context, GLenum access, void **mapPtr)
+{
+    *mapPtr = mData.data();
+    return gl::NoError();
+}
+
+gl::Error BufferNULL::mapRange(ContextImpl *context,
+                               size_t offset,
+                               size_t length,
+                               GLbitfield access,
+                               void **mapPtr)
+{
+    *mapPtr = mData.data() + offset;
+    return gl::NoError();
+}
+
+gl::Error BufferNULL::unmap(ContextImpl *context, GLboolean *result)
+{
+    *result = GL_TRUE;
+    return gl::NoError();
+}
+
+gl::Error BufferNULL::getIndexRange(GLenum type,
+                                    size_t offset,
+                                    size_t count,
+                                    bool primitiveRestartEnabled,
+                                    gl::IndexRange *outRange)
+{
+    *outRange = gl::ComputeIndexRange(type, mData.data() + offset, count, primitiveRestartEnabled);
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/BufferNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/BufferNULL.h
new file mode 100644
index 0000000..6ba23cd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/BufferNULL.h
@@ -0,0 +1,63 @@
+//
+// Copyright 2016 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.
+//
+// BufferNULL.h:
+//    Defines the class interface for BufferNULL, implementing BufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_BUFFERNULL_H_
+#define LIBANGLE_RENDERER_NULL_BUFFERNULL_H_
+
+#include "libANGLE/renderer/BufferImpl.h"
+
+namespace rx
+{
+
+class AllocationTrackerNULL;
+
+class BufferNULL : public BufferImpl
+{
+  public:
+    BufferNULL(const gl::BufferState &state, AllocationTrackerNULL *allocationTracker);
+    ~BufferNULL() override;
+
+    gl::Error setData(ContextImpl *context,
+                      GLenum target,
+                      const void *data,
+                      size_t size,
+                      GLenum usage) override;
+    gl::Error setSubData(ContextImpl *context,
+                         GLenum target,
+                         const void *data,
+                         size_t size,
+                         size_t offset) override;
+    gl::Error copySubData(ContextImpl *contextImpl,
+                          BufferImpl *source,
+                          GLintptr sourceOffset,
+                          GLintptr destOffset,
+                          GLsizeiptr size) override;
+    gl::Error map(ContextImpl *contextImpl, GLenum access, void **mapPtr) override;
+    gl::Error mapRange(ContextImpl *contextImpl,
+                       size_t offset,
+                       size_t length,
+                       GLbitfield access,
+                       void **mapPtr) override;
+    gl::Error unmap(ContextImpl *contextImpl, GLboolean *result) override;
+
+    gl::Error getIndexRange(GLenum type,
+                            size_t offset,
+                            size_t count,
+                            bool primitiveRestartEnabled,
+                            gl::IndexRange *outRange) override;
+
+  private:
+    std::vector<uint8_t> mData;
+
+    AllocationTrackerNULL *mAllocationTracker;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_BUFFERNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/CompilerNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/CompilerNULL.cpp
new file mode 100644
index 0000000..802c5cd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/CompilerNULL.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 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.
+//
+// CompilerNULL.cpp:
+//    Implements the class methods for CompilerNULL.
+//
+
+#include "libANGLE/renderer/null/CompilerNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+CompilerNULL::CompilerNULL() : CompilerImpl()
+{
+}
+
+CompilerNULL::~CompilerNULL()
+{
+}
+
+gl::Error CompilerNULL::release()
+{
+    return gl::NoError();
+}
+
+ShShaderOutput CompilerNULL::getTranslatorOutputType() const
+{
+    return SH_ESSL_OUTPUT;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/CompilerNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/CompilerNULL.h
new file mode 100644
index 0000000..5cd85e8
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/CompilerNULL.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2016 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.
+//
+// CompilerNULL.h:
+//    Defines the class interface for CompilerNULL, implementing CompilerImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_COMPILERNULL_H_
+#define LIBANGLE_RENDERER_NULL_COMPILERNULL_H_
+
+#include "libANGLE/renderer/CompilerImpl.h"
+
+namespace rx
+{
+
+class CompilerNULL : public CompilerImpl
+{
+  public:
+    CompilerNULL();
+    ~CompilerNULL() override;
+
+    gl::Error release() override;
+
+    // TODO(jmadill): Expose translator built-in resources init method.
+    ShShaderOutput getTranslatorOutputType() const override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_COMPILERNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/ContextNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/ContextNULL.cpp
new file mode 100644
index 0000000..4532541
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/ContextNULL.cpp
@@ -0,0 +1,371 @@
+//
+// Copyright 2016 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.
+//
+// ContextNULL.cpp:
+//    Implements the class methods for ContextNULL.
+//
+
+#include "libANGLE/renderer/null/ContextNULL.h"
+
+#include "common/debug.h"
+
+#include "libANGLE/renderer/null/BufferNULL.h"
+#include "libANGLE/renderer/null/CompilerNULL.h"
+#include "libANGLE/renderer/null/DisplayNULL.h"
+#include "libANGLE/renderer/null/FenceNVNULL.h"
+#include "libANGLE/renderer/null/FenceSyncNULL.h"
+#include "libANGLE/renderer/null/FramebufferNULL.h"
+#include "libANGLE/renderer/null/ImageNULL.h"
+#include "libANGLE/renderer/null/PathNULL.h"
+#include "libANGLE/renderer/null/ProgramNULL.h"
+#include "libANGLE/renderer/null/QueryNULL.h"
+#include "libANGLE/renderer/null/RenderbufferNULL.h"
+#include "libANGLE/renderer/null/SamplerNULL.h"
+#include "libANGLE/renderer/null/ShaderNULL.h"
+#include "libANGLE/renderer/null/TextureNULL.h"
+#include "libANGLE/renderer/null/TransformFeedbackNULL.h"
+#include "libANGLE/renderer/null/VertexArrayNULL.h"
+
+namespace rx
+{
+
+AllocationTrackerNULL::AllocationTrackerNULL(size_t maxTotalAllocationSize)
+    : mAllocatedBytes(0), mMaxBytes(maxTotalAllocationSize)
+{
+}
+
+AllocationTrackerNULL::~AllocationTrackerNULL()
+{
+    // ASSERT that all objects with the NULL renderer clean up after themselves
+    ASSERT(mAllocatedBytes == 0);
+}
+
+bool AllocationTrackerNULL::updateMemoryAllocation(size_t oldSize, size_t newSize)
+{
+    ASSERT(mAllocatedBytes >= oldSize);
+
+    size_t sizeAfterRelease    = mAllocatedBytes - oldSize;
+    size_t sizeAfterReallocate = sizeAfterRelease + newSize;
+    if (sizeAfterReallocate < sizeAfterRelease || sizeAfterReallocate > mMaxBytes)
+    {
+        // Overflow or allocation would be too large
+        return false;
+    }
+
+    mAllocatedBytes = sizeAfterReallocate;
+    return true;
+}
+
+ContextNULL::ContextNULL(const gl::ContextState &state, AllocationTrackerNULL *allocationTracker)
+    : ContextImpl(state), mAllocationTracker(allocationTracker)
+{
+    ASSERT(mAllocationTracker != nullptr);
+
+    const gl::Version maxClientVersion(3, 1);
+    mCaps = GenerateMinimumCaps(maxClientVersion);
+
+    mExtensions                       = gl::Extensions();
+    mExtensions.copyTexture           = true;
+    mExtensions.copyCompressedTexture = true;
+
+    mTextureCaps = GenerateMinimumTextureCapsMap(maxClientVersion, mExtensions);
+}
+
+ContextNULL::~ContextNULL()
+{
+}
+
+gl::Error ContextNULL::initialize()
+{
+    return gl::NoError();
+}
+
+gl::Error ContextNULL::flush()
+{
+    return gl::NoError();
+}
+
+gl::Error ContextNULL::finish()
+{
+    return gl::NoError();
+}
+
+gl::Error ContextNULL::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    return gl::NoError();
+}
+
+gl::Error ContextNULL::drawArraysInstanced(GLenum mode,
+                                           GLint first,
+                                           GLsizei count,
+                                           GLsizei instanceCount)
+{
+    return gl::NoError();
+}
+
+gl::Error ContextNULL::drawElements(GLenum mode,
+                                    GLsizei count,
+                                    GLenum type,
+                                    const void *indices,
+                                    const gl::IndexRange &indexRange)
+{
+    return gl::NoError();
+}
+
+gl::Error ContextNULL::drawElementsInstanced(GLenum mode,
+                                             GLsizei count,
+                                             GLenum type,
+                                             const void *indices,
+                                             GLsizei instances,
+                                             const gl::IndexRange &indexRange)
+{
+    return gl::NoError();
+}
+
+gl::Error ContextNULL::drawRangeElements(GLenum mode,
+                                         GLuint start,
+                                         GLuint end,
+                                         GLsizei count,
+                                         GLenum type,
+                                         const void *indices,
+                                         const gl::IndexRange &indexRange)
+{
+    return gl::NoError();
+}
+
+gl::Error ContextNULL::drawArraysIndirect(GLenum mode, const void *indirect)
+{
+    return gl::NoError();
+}
+
+gl::Error ContextNULL::drawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+    return gl::NoError();
+}
+
+void ContextNULL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
+{
+}
+
+void ContextNULL::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
+{
+}
+
+void ContextNULL::coverFillPath(const gl::Path *path, GLenum coverMode)
+{
+}
+
+void ContextNULL::coverStrokePath(const gl::Path *path, GLenum coverMode)
+{
+}
+
+void ContextNULL::stencilThenCoverFillPath(const gl::Path *path,
+                                           GLenum fillMode,
+                                           GLuint mask,
+                                           GLenum coverMode)
+{
+}
+
+void ContextNULL::stencilThenCoverStrokePath(const gl::Path *path,
+                                             GLint reference,
+                                             GLuint mask,
+                                             GLenum coverMode)
+{
+}
+
+void ContextNULL::coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                         GLenum coverMode,
+                                         GLenum transformType,
+                                         const GLfloat *transformValues)
+{
+}
+
+void ContextNULL::coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                           GLenum coverMode,
+                                           GLenum transformType,
+                                           const GLfloat *transformValues)
+{
+}
+
+void ContextNULL::stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                           GLenum fillMode,
+                                           GLuint mask,
+                                           GLenum transformType,
+                                           const GLfloat *transformValues)
+{
+}
+
+void ContextNULL::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                             GLint reference,
+                                             GLuint mask,
+                                             GLenum transformType,
+                                             const GLfloat *transformValues)
+{
+}
+
+void ContextNULL::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                                    GLenum coverMode,
+                                                    GLenum fillMode,
+                                                    GLuint mask,
+                                                    GLenum transformType,
+                                                    const GLfloat *transformValues)
+{
+}
+
+void ContextNULL::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                                      GLenum coverMode,
+                                                      GLint reference,
+                                                      GLuint mask,
+                                                      GLenum transformType,
+                                                      const GLfloat *transformValues)
+{
+}
+
+GLenum ContextNULL::getResetStatus()
+{
+    return GL_NO_ERROR;
+}
+
+std::string ContextNULL::getVendorString() const
+{
+    return "NULL";
+}
+
+std::string ContextNULL::getRendererDescription() const
+{
+    return "NULL";
+}
+
+void ContextNULL::insertEventMarker(GLsizei length, const char *marker)
+{
+}
+
+void ContextNULL::pushGroupMarker(GLsizei length, const char *marker)
+{
+}
+
+void ContextNULL::popGroupMarker()
+{
+}
+
+void ContextNULL::syncState(const gl::State::DirtyBits &dirtyBits)
+{
+}
+
+GLint ContextNULL::getGPUDisjoint()
+{
+    return 0;
+}
+
+GLint64 ContextNULL::getTimestamp()
+{
+    return 0;
+}
+
+void ContextNULL::onMakeCurrent(const gl::ContextState &data)
+{
+}
+
+const gl::Caps &ContextNULL::getNativeCaps() const
+{
+    return mCaps;
+}
+
+const gl::TextureCapsMap &ContextNULL::getNativeTextureCaps() const
+{
+    return mTextureCaps;
+}
+
+const gl::Extensions &ContextNULL::getNativeExtensions() const
+{
+    return mExtensions;
+}
+
+const gl::Limitations &ContextNULL::getNativeLimitations() const
+{
+    return mLimitations;
+}
+
+CompilerImpl *ContextNULL::createCompiler()
+{
+    return new CompilerNULL();
+}
+
+ShaderImpl *ContextNULL::createShader(const gl::ShaderState &data)
+{
+    return new ShaderNULL(data);
+}
+
+ProgramImpl *ContextNULL::createProgram(const gl::ProgramState &data)
+{
+    return new ProgramNULL(data);
+}
+
+FramebufferImpl *ContextNULL::createFramebuffer(const gl::FramebufferState &data)
+{
+    return new FramebufferNULL(data);
+}
+
+TextureImpl *ContextNULL::createTexture(const gl::TextureState &state)
+{
+    return new TextureNULL(state);
+}
+
+RenderbufferImpl *ContextNULL::createRenderbuffer()
+{
+    return new RenderbufferNULL();
+}
+
+BufferImpl *ContextNULL::createBuffer(const gl::BufferState &state)
+{
+    return new BufferNULL(state, mAllocationTracker);
+}
+
+VertexArrayImpl *ContextNULL::createVertexArray(const gl::VertexArrayState &data)
+{
+    return new VertexArrayNULL(data);
+}
+
+QueryImpl *ContextNULL::createQuery(GLenum type)
+{
+    return new QueryNULL(type);
+}
+
+FenceNVImpl *ContextNULL::createFenceNV()
+{
+    return new FenceNVNULL();
+}
+
+FenceSyncImpl *ContextNULL::createFenceSync()
+{
+    return new FenceSyncNULL();
+}
+
+TransformFeedbackImpl *ContextNULL::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+    return new TransformFeedbackNULL(state);
+}
+
+SamplerImpl *ContextNULL::createSampler()
+{
+    return new SamplerNULL();
+}
+
+std::vector<PathImpl *> ContextNULL::createPaths(GLsizei range)
+{
+    std::vector<PathImpl *> result(range);
+    for (GLsizei idx = 0; idx < range; idx++)
+    {
+        result[idx] = new PathNULL();
+    }
+    return result;
+}
+
+gl::Error ContextNULL::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/ContextNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/ContextNULL.h
new file mode 100644
index 0000000..0da4880
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/ContextNULL.h
@@ -0,0 +1,194 @@
+//
+// Copyright 2016 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.
+//
+// ContextNULL.h:
+//    Defines the class interface for ContextNULL, implementing ContextImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_CONTEXTNULL_H_
+#define LIBANGLE_RENDERER_NULL_CONTEXTNULL_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+
+class AllocationTrackerNULL : angle::NonCopyable
+{
+  public:
+    explicit AllocationTrackerNULL(size_t maxTotalAllocationSize);
+    ~AllocationTrackerNULL();
+
+    // Check if it is possible to change an allocation from oldSize to newSize.  If it is possible,
+    // the allocation is registered and true is returned else false is returned.
+    bool updateMemoryAllocation(size_t oldSize, size_t newSize);
+
+  private:
+    size_t mAllocatedBytes;
+    const size_t mMaxBytes;
+};
+
+class ContextNULL : public ContextImpl
+{
+  public:
+    ContextNULL(const gl::ContextState &state, AllocationTrackerNULL *allocationTracker);
+    ~ContextNULL() override;
+
+    gl::Error initialize() override;
+
+    // Flush and finish.
+    gl::Error flush() override;
+    gl::Error finish() override;
+
+    // Drawing methods.
+    gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+    gl::Error drawArraysInstanced(GLenum mode,
+                                  GLint first,
+                                  GLsizei count,
+                                  GLsizei instanceCount) override;
+
+    gl::Error drawElements(GLenum mode,
+                           GLsizei count,
+                           GLenum type,
+                           const void *indices,
+                           const gl::IndexRange &indexRange) override;
+    gl::Error drawElementsInstanced(GLenum mode,
+                                    GLsizei count,
+                                    GLenum type,
+                                    const void *indices,
+                                    GLsizei instances,
+                                    const gl::IndexRange &indexRange) override;
+    gl::Error drawRangeElements(GLenum mode,
+                                GLuint start,
+                                GLuint end,
+                                GLsizei count,
+                                GLenum type,
+                                const void *indices,
+                                const gl::IndexRange &indexRange) override;
+    gl::Error drawArraysIndirect(GLenum mode, const void *indirect) override;
+    gl::Error drawElementsIndirect(GLenum mode, GLenum type, const void *indirect) override;
+
+    // CHROMIUM_path_rendering path drawing methods.
+    void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override;
+    void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask) override;
+    void coverFillPath(const gl::Path *path, GLenum coverMode) override;
+    void coverStrokePath(const gl::Path *path, GLenum coverMode) override;
+    void stencilThenCoverFillPath(const gl::Path *path,
+                                  GLenum fillMode,
+                                  GLuint mask,
+                                  GLenum coverMode) override;
+
+    void stencilThenCoverStrokePath(const gl::Path *path,
+                                    GLint reference,
+                                    GLuint mask,
+                                    GLenum coverMode) override;
+
+    void coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                GLenum coverMode,
+                                GLenum transformType,
+                                const GLfloat *transformValues) override;
+    void coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                  GLenum coverMode,
+                                  GLenum transformType,
+                                  const GLfloat *transformValues) override;
+    void stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                  GLenum fillMode,
+                                  GLuint mask,
+                                  GLenum transformType,
+                                  const GLfloat *transformValues) override;
+    void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                    GLint reference,
+                                    GLuint mask,
+                                    GLenum transformType,
+                                    const GLfloat *transformValues) override;
+    void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+                                           GLenum coverMode,
+                                           GLenum fillMode,
+                                           GLuint mask,
+                                           GLenum transformType,
+                                           const GLfloat *transformValues) override;
+    void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+                                             GLenum coverMode,
+                                             GLint reference,
+                                             GLuint mask,
+                                             GLenum transformType,
+                                             const GLfloat *transformValues) override;
+
+    // Device loss
+    GLenum getResetStatus() override;
+
+    // Vendor and description strings.
+    std::string getVendorString() const override;
+    std::string getRendererDescription() const override;
+
+    // Debug markers.
+    void insertEventMarker(GLsizei length, const char *marker) override;
+    void pushGroupMarker(GLsizei length, const char *marker) override;
+    void popGroupMarker() override;
+
+    // State sync with dirty bits.
+    void syncState(const gl::State::DirtyBits &dirtyBits) override;
+
+    // Disjoint timer queries
+    GLint getGPUDisjoint() override;
+    GLint64 getTimestamp() override;
+
+    // Context switching
+    void onMakeCurrent(const gl::ContextState &data) override;
+
+    // Native capabilities, unmodified by gl::Context.
+    const gl::Caps &getNativeCaps() const override;
+    const gl::TextureCapsMap &getNativeTextureCaps() const override;
+    const gl::Extensions &getNativeExtensions() const override;
+    const gl::Limitations &getNativeLimitations() const override;
+
+    // Shader creation
+    CompilerImpl *createCompiler() override;
+    ShaderImpl *createShader(const gl::ShaderState &data) override;
+    ProgramImpl *createProgram(const gl::ProgramState &data) override;
+
+    // Framebuffer creation
+    FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override;
+
+    // Texture creation
+    TextureImpl *createTexture(const gl::TextureState &state) override;
+
+    // Renderbuffer creation
+    RenderbufferImpl *createRenderbuffer() override;
+
+    // Buffer creation
+    BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+    // Vertex Array creation
+    VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override;
+
+    // Query and Fence creation
+    QueryImpl *createQuery(GLenum type) override;
+    FenceNVImpl *createFenceNV() override;
+    FenceSyncImpl *createFenceSync() override;
+
+    // Transform Feedback creation
+    TransformFeedbackImpl *createTransformFeedback(
+        const gl::TransformFeedbackState &state) override;
+
+    // Sampler object creation
+    SamplerImpl *createSampler() override;
+
+    std::vector<PathImpl *> createPaths(GLsizei range) override;
+
+    gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
+
+  private:
+    gl::Caps mCaps;
+    gl::TextureCapsMap mTextureCaps;
+    gl::Extensions mExtensions;
+    gl::Limitations mLimitations;
+
+    AllocationTrackerNULL *mAllocationTracker;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_CONTEXTNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/DeviceNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/DeviceNULL.cpp
new file mode 100644
index 0000000..4735eea
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/DeviceNULL.cpp
@@ -0,0 +1,45 @@
+//
+// Copyright 2016 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.
+//
+// DeviceNULL.cpp:
+//    Implements the class methods for DeviceNULL.
+//
+
+#include "libANGLE/renderer/null/DeviceNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+DeviceNULL::DeviceNULL() : DeviceImpl()
+{
+}
+
+DeviceNULL::~DeviceNULL()
+{
+}
+
+egl::Error DeviceNULL::getDevice(void **outValue)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+EGLint DeviceNULL::getType()
+{
+    return 0;
+}
+
+void DeviceNULL::generateExtensions(egl::DeviceExtensions *outExtensions) const
+{
+}
+
+bool DeviceNULL::deviceExternallySourced()
+{
+    return false;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/DeviceNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/DeviceNULL.h
new file mode 100644
index 0000000..ed92103
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/DeviceNULL.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2016 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.
+//
+// DeviceNULL.h:
+//    Defines the class interface for DeviceNULL, implementing DeviceImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_DEVICENULL_H_
+#define LIBANGLE_RENDERER_NULL_DEVICENULL_H_
+
+#include "libANGLE/renderer/DeviceImpl.h"
+
+namespace rx
+{
+
+class DeviceNULL : public DeviceImpl
+{
+  public:
+    DeviceNULL();
+    ~DeviceNULL() override;
+
+    egl::Error getDevice(void **outValue) override;
+    EGLint getType() override;
+    void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
+    bool deviceExternallySourced() override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_DEVICENULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/DisplayNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/DisplayNULL.cpp
new file mode 100644
index 0000000..61b3a8a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/DisplayNULL.cpp
@@ -0,0 +1,213 @@
+//
+// Copyright 2016 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.
+//
+// DisplayNULL.cpp:
+//    Implements the class methods for DisplayNULL.
+//
+
+#include "libANGLE/renderer/null/DisplayNULL.h"
+
+#include "common/debug.h"
+
+#include "libANGLE/renderer/null/ContextNULL.h"
+#include "libANGLE/renderer/null/DeviceNULL.h"
+#include "libANGLE/renderer/null/ImageNULL.h"
+#include "libANGLE/renderer/null/SurfaceNULL.h"
+
+namespace rx
+{
+
+DisplayNULL::DisplayNULL(const egl::DisplayState &state) : DisplayImpl(state), mDevice(nullptr)
+{
+}
+
+DisplayNULL::~DisplayNULL()
+{
+}
+
+egl::Error DisplayNULL::initialize(egl::Display *display)
+{
+    mDevice = new DeviceNULL();
+
+    constexpr size_t kMaxTotalAllocationSize = 1 << 28;  // 256MB
+    mAllocationTracker.reset(new AllocationTrackerNULL(kMaxTotalAllocationSize));
+
+    return egl::NoError();
+}
+
+void DisplayNULL::terminate()
+{
+    mAllocationTracker.reset();
+    SafeDelete(mDevice);
+}
+
+egl::Error DisplayNULL::makeCurrent(egl::Surface *drawSurface,
+                                    egl::Surface *readSurface,
+                                    gl::Context *context)
+{
+    return egl::NoError();
+}
+
+egl::ConfigSet DisplayNULL::generateConfigs()
+{
+    egl::Config config;
+    config.renderTargetFormat    = GL_RGBA8;
+    config.depthStencilFormat    = GL_DEPTH24_STENCIL8;
+    config.bufferSize            = 32;
+    config.redSize               = 8;
+    config.greenSize             = 8;
+    config.blueSize              = 8;
+    config.alphaSize             = 8;
+    config.alphaMaskSize         = 0;
+    config.bindToTextureRGB      = EGL_TRUE;
+    config.bindToTextureRGBA     = EGL_TRUE;
+    config.colorBufferType       = EGL_RGB_BUFFER;
+    config.configCaveat          = EGL_NONE;
+    config.conformant            = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
+    config.depthSize             = 24;
+    config.level                 = 0;
+    config.matchNativePixmap     = EGL_NONE;
+    config.maxPBufferWidth       = 0;
+    config.maxPBufferHeight      = 0;
+    config.maxPBufferPixels      = 0;
+    config.maxSwapInterval       = 1;
+    config.minSwapInterval       = 1;
+    config.nativeRenderable      = EGL_TRUE;
+    config.nativeVisualID        = 0;
+    config.nativeVisualType      = EGL_NONE;
+    config.renderableType        = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
+    config.sampleBuffers         = 0;
+    config.samples               = 0;
+    config.stencilSize           = 8;
+    config.surfaceType           = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
+    config.optimalOrientation    = 0;
+    config.transparentType       = EGL_NONE;
+    config.transparentRedValue   = 0;
+    config.transparentGreenValue = 0;
+    config.transparentBlueValue  = 0;
+
+    egl::ConfigSet configSet;
+    configSet.add(config);
+    return configSet;
+}
+
+bool DisplayNULL::testDeviceLost()
+{
+    return false;
+}
+
+egl::Error DisplayNULL::restoreLostDevice()
+{
+    return egl::NoError();
+}
+
+bool DisplayNULL::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    return true;
+}
+
+std::string DisplayNULL::getVendorString() const
+{
+    return "NULL";
+}
+
+egl::Error DisplayNULL::getDevice(DeviceImpl **device)
+{
+    *device = mDevice;
+    return egl::NoError();
+}
+
+egl::Error DisplayNULL::waitClient() const
+{
+    return egl::NoError();
+}
+
+egl::Error DisplayNULL::waitNative(EGLint engine,
+                                   egl::Surface *drawSurface,
+                                   egl::Surface *readSurface) const
+{
+    return egl::NoError();
+}
+
+gl::Version DisplayNULL::getMaxSupportedESVersion() const
+{
+    return gl::Version(3, 2);
+}
+
+SurfaceImpl *DisplayNULL::createWindowSurface(const egl::SurfaceState &state,
+                                              EGLNativeWindowType window,
+                                              const egl::AttributeMap &attribs)
+{
+    return new SurfaceNULL(state);
+}
+
+SurfaceImpl *DisplayNULL::createPbufferSurface(const egl::SurfaceState &state,
+                                               const egl::AttributeMap &attribs)
+{
+    return new SurfaceNULL(state);
+}
+
+SurfaceImpl *DisplayNULL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                                        EGLenum buftype,
+                                                        EGLClientBuffer buffer,
+                                                        const egl::AttributeMap &attribs)
+{
+    return new SurfaceNULL(state);
+}
+
+SurfaceImpl *DisplayNULL::createPixmapSurface(const egl::SurfaceState &state,
+                                              NativePixmapType nativePixmap,
+                                              const egl::AttributeMap &attribs)
+{
+    return new SurfaceNULL(state);
+}
+
+ImageImpl *DisplayNULL::createImage(const egl::ImageState &state,
+                                    EGLenum target,
+                                    const egl::AttributeMap &attribs)
+{
+    return new ImageNULL(state);
+}
+
+ContextImpl *DisplayNULL::createContext(const gl::ContextState &state)
+{
+    return new ContextNULL(state, mAllocationTracker.get());
+}
+
+StreamProducerImpl *DisplayNULL::createStreamProducerD3DTextureNV12(
+    egl::Stream::ConsumerType consumerType,
+    const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
+
+void DisplayNULL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+    outExtensions->createContextRobustness            = true;
+    outExtensions->postSubBuffer                      = true;
+    outExtensions->createContext                      = true;
+    outExtensions->deviceQuery                        = true;
+    outExtensions->image                              = true;
+    outExtensions->imageBase                          = true;
+    outExtensions->glTexture2DImage                   = true;
+    outExtensions->glTextureCubemapImage              = true;
+    outExtensions->glTexture3DImage                   = true;
+    outExtensions->glRenderbufferImage                = true;
+    outExtensions->getAllProcAddresses                = true;
+    outExtensions->flexibleSurfaceCompatibility       = true;
+    outExtensions->directComposition                  = true;
+    outExtensions->createContextNoError               = true;
+    outExtensions->createContextWebGLCompatibility    = true;
+    outExtensions->createContextBindGeneratesResource = true;
+    outExtensions->swapBuffersWithDamage              = true;
+}
+
+void DisplayNULL::generateCaps(egl::Caps *outCaps) const
+{
+    outCaps->textureNPOT = true;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/DisplayNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/DisplayNULL.h
new file mode 100644
index 0000000..a91c215
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/DisplayNULL.h
@@ -0,0 +1,84 @@
+//
+// Copyright 2016 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.
+//
+// DisplayNULL.h:
+//    Defines the class interface for DisplayNULL, implementing DisplayImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_DISPLAYNULL_H_
+#define LIBANGLE_RENDERER_NULL_DISPLAYNULL_H_
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+namespace rx
+{
+
+class AllocationTrackerNULL;
+
+class DisplayNULL : public DisplayImpl
+{
+  public:
+    DisplayNULL(const egl::DisplayState &state);
+    ~DisplayNULL() override;
+
+    egl::Error initialize(egl::Display *display) override;
+    void terminate() override;
+
+    egl::Error makeCurrent(egl::Surface *drawSurface,
+                           egl::Surface *readSurface,
+                           gl::Context *context) override;
+
+    egl::ConfigSet generateConfigs() override;
+
+    bool testDeviceLost() override;
+    egl::Error restoreLostDevice() override;
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+    std::string getVendorString() const override;
+
+    egl::Error getDevice(DeviceImpl **device) override;
+
+    egl::Error waitClient() const override;
+    egl::Error waitNative(EGLint engine,
+                          egl::Surface *drawSurface,
+                          egl::Surface *readSurface) const override;
+    gl::Version getMaxSupportedESVersion() const override;
+
+    SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+                                     EGLNativeWindowType window,
+                                     const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+                                      const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                               EGLenum buftype,
+                                               EGLClientBuffer buffer,
+                                               const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+                                     NativePixmapType nativePixmap,
+                                     const egl::AttributeMap &attribs) override;
+
+    ImageImpl *createImage(const egl::ImageState &state,
+                           EGLenum target,
+                           const egl::AttributeMap &attribs) override;
+
+    ContextImpl *createContext(const gl::ContextState &state) override;
+
+    StreamProducerImpl *createStreamProducerD3DTextureNV12(
+        egl::Stream::ConsumerType consumerType,
+        const egl::AttributeMap &attribs) override;
+
+  private:
+    void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+    void generateCaps(egl::Caps *outCaps) const override;
+
+    DeviceImpl *mDevice;
+
+    std::unique_ptr<AllocationTrackerNULL> mAllocationTracker;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_DISPLAYNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/FenceNVNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/FenceNVNULL.cpp
new file mode 100644
index 0000000..9d7f260
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/FenceNVNULL.cpp
@@ -0,0 +1,43 @@
+//
+// Copyright 2016 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.
+//
+// FenceNVNULL.cpp:
+//    Implements the class methods for FenceNVNULL.
+//
+
+#include "libANGLE/renderer/null/FenceNVNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FenceNVNULL::FenceNVNULL() : FenceNVImpl()
+{
+}
+
+FenceNVNULL::~FenceNVNULL()
+{
+}
+
+gl::Error FenceNVNULL::set(GLenum condition)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceNVNULL::test(GLboolean *outFinished)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceNVNULL::finish()
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/FenceNVNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/FenceNVNULL.h
new file mode 100644
index 0000000..10cf5c2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/FenceNVNULL.h
@@ -0,0 +1,31 @@
+//
+// Copyright 2016 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.
+//
+// FenceNVNULL.h:
+//    Defines the class interface for FenceNVNULL, implementing FenceNVImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_FENCENVNULL_H_
+#define LIBANGLE_RENDERER_NULL_FENCENVNULL_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+
+namespace rx
+{
+
+class FenceNVNULL : public FenceNVImpl
+{
+  public:
+    FenceNVNULL();
+    ~FenceNVNULL() override;
+
+    gl::Error set(GLenum condition) override;
+    gl::Error test(GLboolean *outFinished) override;
+    gl::Error finish() override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_FENCENVNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/FenceSyncNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/FenceSyncNULL.cpp
new file mode 100644
index 0000000..ae65c0b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/FenceSyncNULL.cpp
@@ -0,0 +1,47 @@
+//
+// Copyright 2016 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.
+//
+// FenceSyncNULL.cpp:
+//    Implements the class methods for FenceSyncNULL.
+//
+
+#include "libANGLE/renderer/null/FenceSyncNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FenceSyncNULL::FenceSyncNULL() : FenceSyncImpl()
+{
+}
+
+FenceSyncNULL::~FenceSyncNULL()
+{
+}
+
+gl::Error FenceSyncNULL::set(GLenum condition, GLbitfield flags)
+{
+    return gl::NoError();
+}
+
+gl::Error FenceSyncNULL::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+    *outResult = GL_ALREADY_SIGNALED;
+    return gl::NoError();
+}
+
+gl::Error FenceSyncNULL::serverWait(GLbitfield flags, GLuint64 timeout)
+{
+    return gl::NoError();
+}
+
+gl::Error FenceSyncNULL::getStatus(GLint *outResult)
+{
+    *outResult = GL_SIGNALED;
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/FenceSyncNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/FenceSyncNULL.h
new file mode 100644
index 0000000..28a12f7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/FenceSyncNULL.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2016 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.
+//
+// FenceSyncNULL.h:
+//    Defines the class interface for FenceSyncNULL, implementing FenceSyncImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_FENCESYNCNULL_H_
+#define LIBANGLE_RENDERER_NULL_FENCESYNCNULL_H_
+
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace rx
+{
+
+class FenceSyncNULL : public FenceSyncImpl
+{
+  public:
+    FenceSyncNULL();
+    ~FenceSyncNULL() override;
+
+    gl::Error set(GLenum condition, GLbitfield flags) override;
+    gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override;
+    gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override;
+    gl::Error getStatus(GLint *outResult) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_FENCESYNCNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/FramebufferNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/FramebufferNULL.cpp
new file mode 100644
index 0000000..4744fa7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/FramebufferNULL.cpp
@@ -0,0 +1,141 @@
+//
+// Copyright 2016 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.
+//
+// FramebufferNULL.cpp:
+//    Implements the class methods for FramebufferNULL.
+//
+
+#include "libANGLE/renderer/null/FramebufferNULL.h"
+
+#include "libANGLE/formatutils.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FramebufferNULL::FramebufferNULL(const gl::FramebufferState &state) : FramebufferImpl(state)
+{
+}
+
+FramebufferNULL::~FramebufferNULL()
+{
+}
+
+gl::Error FramebufferNULL::discard(size_t count, const GLenum *attachments)
+{
+    return gl::NoError();
+}
+
+gl::Error FramebufferNULL::invalidate(size_t count, const GLenum *attachments)
+{
+    return gl::NoError();
+}
+
+gl::Error FramebufferNULL::invalidateSub(size_t count,
+                                         const GLenum *attachments,
+                                         const gl::Rectangle &area)
+{
+    return gl::NoError();
+}
+
+gl::Error FramebufferNULL::clear(ContextImpl *context, GLbitfield mask)
+{
+    return gl::NoError();
+}
+
+gl::Error FramebufferNULL::clearBufferfv(ContextImpl *context,
+                                         GLenum buffer,
+                                         GLint drawbuffer,
+                                         const GLfloat *values)
+{
+    return gl::NoError();
+}
+
+gl::Error FramebufferNULL::clearBufferuiv(ContextImpl *context,
+                                          GLenum buffer,
+                                          GLint drawbuffer,
+                                          const GLuint *values)
+{
+    return gl::NoError();
+}
+
+gl::Error FramebufferNULL::clearBufferiv(ContextImpl *context,
+                                         GLenum buffer,
+                                         GLint drawbuffer,
+                                         const GLint *values)
+{
+    return gl::NoError();
+}
+
+gl::Error FramebufferNULL::clearBufferfi(ContextImpl *context,
+                                         GLenum buffer,
+                                         GLint drawbuffer,
+                                         GLfloat depth,
+                                         GLint stencil)
+{
+    return gl::NoError();
+}
+
+GLenum FramebufferNULL::getImplementationColorReadFormat() const
+{
+    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+    if (readAttachment == nullptr)
+    {
+        return GL_NONE;
+    }
+
+    const gl::Format &format = readAttachment->getFormat();
+    ASSERT(format.info != nullptr);
+    return format.info->getReadPixelsFormat();
+}
+
+GLenum FramebufferNULL::getImplementationColorReadType() const
+{
+    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+    if (readAttachment == nullptr)
+    {
+        return GL_NONE;
+    }
+
+    const gl::Format &format = readAttachment->getFormat();
+    ASSERT(format.info != nullptr);
+    return format.info->getReadPixelsType();
+}
+
+gl::Error FramebufferNULL::readPixels(ContextImpl *context,
+                                      const gl::Rectangle &area,
+                                      GLenum format,
+                                      GLenum type,
+                                      void *pixels) const
+{
+    return gl::NoError();
+}
+
+gl::Error FramebufferNULL::blit(ContextImpl *context,
+                                const gl::Rectangle &sourceArea,
+                                const gl::Rectangle &destArea,
+                                GLbitfield mask,
+                                GLenum filter)
+{
+    return gl::NoError();
+}
+
+bool FramebufferNULL::checkStatus() const
+{
+    return true;
+}
+
+void FramebufferNULL::syncState(ContextImpl *contextImpl,
+                                const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+}
+
+gl::Error FramebufferNULL::getSamplePosition(size_t index, GLfloat *xy) const
+{
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/FramebufferNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/FramebufferNULL.h
new file mode 100644
index 0000000..93756d7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/FramebufferNULL.h
@@ -0,0 +1,72 @@
+//
+// Copyright 2016 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.
+//
+// FramebufferNULL.h:
+//    Defines the class interface for FramebufferNULL, implementing FramebufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_FRAMEBUFFERNULL_H_
+#define LIBANGLE_RENDERER_NULL_FRAMEBUFFERNULL_H_
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace rx
+{
+
+class FramebufferNULL : public FramebufferImpl
+{
+  public:
+    FramebufferNULL(const gl::FramebufferState &state);
+    ~FramebufferNULL() override;
+
+    gl::Error discard(size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(size_t count, const GLenum *attachments) override;
+    gl::Error invalidateSub(size_t count,
+                            const GLenum *attachments,
+                            const gl::Rectangle &area) override;
+
+    gl::Error clear(ContextImpl *context, GLbitfield mask) override;
+    gl::Error clearBufferfv(ContextImpl *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLfloat *values) override;
+    gl::Error clearBufferuiv(ContextImpl *context,
+                             GLenum buffer,
+                             GLint drawbuffer,
+                             const GLuint *values) override;
+    gl::Error clearBufferiv(ContextImpl *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLint *values) override;
+    gl::Error clearBufferfi(ContextImpl *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            GLfloat depth,
+                            GLint stencil) override;
+
+    GLenum getImplementationColorReadFormat() const override;
+    GLenum getImplementationColorReadType() const override;
+    gl::Error readPixels(ContextImpl *context,
+                         const gl::Rectangle &area,
+                         GLenum format,
+                         GLenum type,
+                         void *pixels) const override;
+
+    gl::Error blit(ContextImpl *context,
+                   const gl::Rectangle &sourceArea,
+                   const gl::Rectangle &destArea,
+                   GLbitfield mask,
+                   GLenum filter) override;
+
+    bool checkStatus() const override;
+
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
+
+    gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_FRAMEBUFFERNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/ImageNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/ImageNULL.cpp
new file mode 100644
index 0000000..86ba25f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/ImageNULL.cpp
@@ -0,0 +1,37 @@
+//
+// Copyright 2016 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.
+//
+// ImageNULL.cpp:
+//    Implements the class methods for ImageNULL.
+//
+
+#include "libANGLE/renderer/null/ImageNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ImageNULL::ImageNULL(const egl::ImageState &state) : ImageImpl(state)
+{
+}
+
+ImageNULL::~ImageNULL()
+{
+}
+
+egl::Error ImageNULL::initialize()
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+gl::Error ImageNULL::orphan(egl::ImageSibling *sibling)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/ImageNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/ImageNULL.h
new file mode 100644
index 0000000..e332d00
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/ImageNULL.h
@@ -0,0 +1,30 @@
+//
+// Copyright 2016 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.
+//
+// ImageNULL.h:
+//    Defines the class interface for ImageNULL, implementing ImageImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_IMAGENULL_H_
+#define LIBANGLE_RENDERER_NULL_IMAGENULL_H_
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace rx
+{
+
+class ImageNULL : public ImageImpl
+{
+  public:
+    ImageNULL(const egl::ImageState &state);
+    ~ImageNULL() override;
+    egl::Error initialize() override;
+
+    gl::Error orphan(egl::ImageSibling *sibling) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_IMAGENULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/PathNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/PathNULL.cpp
new file mode 100644
index 0000000..bb52ea2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/PathNULL.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright 2016 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.
+//
+// PathNULL.cpp:
+//    Implements the class methods for PathNULL.
+//
+
+#include "libANGLE/renderer/null/PathNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+PathNULL::PathNULL() : PathImpl()
+{
+}
+
+PathNULL::~PathNULL()
+{
+}
+
+gl::Error PathNULL::setCommands(GLsizei numCommands,
+                                const GLubyte *commands,
+                                GLsizei numCoords,
+                                GLenum coordType,
+                                const void *coords)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+void PathNULL::setPathParameter(GLenum pname, GLfloat value)
+{
+    UNIMPLEMENTED();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/PathNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/PathNULL.h
new file mode 100644
index 0000000..4c80c1c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/PathNULL.h
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 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.
+//
+// PathNULL.h:
+//    Defines the class interface for PathNULL, implementing PathImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_PATHNULL_H_
+#define LIBANGLE_RENDERER_NULL_PATHNULL_H_
+
+#include "libANGLE/renderer/PathImpl.h"
+
+namespace rx
+{
+
+class PathNULL : public PathImpl
+{
+  public:
+    PathNULL();
+    ~PathNULL() override;
+
+    gl::Error setCommands(GLsizei numCommands,
+                          const GLubyte *commands,
+                          GLsizei numCoords,
+                          GLenum coordType,
+                          const void *coords) override;
+
+    void setPathParameter(GLenum pname, GLfloat value) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_PATHNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.cpp
new file mode 100644
index 0000000..35bd46d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.cpp
@@ -0,0 +1,193 @@
+//
+// Copyright 2016 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.
+//
+// ProgramNULL.cpp:
+//    Implements the class methods for ProgramNULL.
+//
+
+#include "libANGLE/renderer/null/ProgramNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ProgramNULL::ProgramNULL(const gl::ProgramState &state) : ProgramImpl(state)
+{
+}
+
+ProgramNULL::~ProgramNULL()
+{
+}
+
+LinkResult ProgramNULL::load(const ContextImpl *contextImpl,
+                             gl::InfoLog &infoLog,
+                             gl::BinaryInputStream *stream)
+{
+    return true;
+}
+
+gl::Error ProgramNULL::save(gl::BinaryOutputStream *stream)
+{
+    return gl::NoError();
+}
+
+void ProgramNULL::setBinaryRetrievableHint(bool retrievable)
+{
+}
+
+void ProgramNULL::setSeparable(bool separable)
+{
+}
+
+LinkResult ProgramNULL::link(ContextImpl *contextImpl,
+                             const gl::VaryingPacking &packing,
+                             gl::InfoLog &infoLog)
+{
+    return true;
+}
+
+GLboolean ProgramNULL::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
+{
+    return GL_TRUE;
+}
+
+void ProgramNULL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+}
+
+void ProgramNULL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+}
+
+void ProgramNULL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+}
+
+void ProgramNULL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+}
+
+void ProgramNULL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+}
+
+void ProgramNULL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+}
+
+void ProgramNULL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+}
+
+void ProgramNULL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+}
+
+void ProgramNULL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+}
+
+void ProgramNULL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+}
+
+void ProgramNULL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+}
+
+void ProgramNULL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+}
+
+void ProgramNULL::setUniformMatrix2fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+}
+
+void ProgramNULL::setUniformMatrix3fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+}
+
+void ProgramNULL::setUniformMatrix4fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+}
+
+void ProgramNULL::setUniformMatrix2x3fv(GLint location,
+                                        GLsizei count,
+                                        GLboolean transpose,
+                                        const GLfloat *value)
+{
+}
+
+void ProgramNULL::setUniformMatrix3x2fv(GLint location,
+                                        GLsizei count,
+                                        GLboolean transpose,
+                                        const GLfloat *value)
+{
+}
+
+void ProgramNULL::setUniformMatrix2x4fv(GLint location,
+                                        GLsizei count,
+                                        GLboolean transpose,
+                                        const GLfloat *value)
+{
+}
+
+void ProgramNULL::setUniformMatrix4x2fv(GLint location,
+                                        GLsizei count,
+                                        GLboolean transpose,
+                                        const GLfloat *value)
+{
+}
+
+void ProgramNULL::setUniformMatrix3x4fv(GLint location,
+                                        GLsizei count,
+                                        GLboolean transpose,
+                                        const GLfloat *value)
+{
+}
+
+void ProgramNULL::setUniformMatrix4x3fv(GLint location,
+                                        GLsizei count,
+                                        GLboolean transpose,
+                                        const GLfloat *value)
+{
+}
+
+void ProgramNULL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+}
+
+bool ProgramNULL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+    // TODO(geofflang): Compute reasonable sizes?
+    *sizeOut = 0;
+    return true;
+}
+
+bool ProgramNULL::getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                            sh::BlockMemberInfo *memberInfoOut) const
+{
+    // TODO(geofflang): Compute reasonable values?
+    return true;
+}
+
+void ProgramNULL::setPathFragmentInputGen(const std::string &inputName,
+                                          GLenum genMode,
+                                          GLint components,
+                                          const GLfloat *coeffs)
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.h
new file mode 100644
index 0000000..88c0598
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.h
@@ -0,0 +1,106 @@
+//
+// Copyright 2016 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.
+//
+// ProgramNULL.h:
+//    Defines the class interface for ProgramNULL, implementing ProgramImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_PROGRAMNULL_H_
+#define LIBANGLE_RENDERER_NULL_PROGRAMNULL_H_
+
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+class ProgramNULL : public ProgramImpl
+{
+  public:
+    ProgramNULL(const gl::ProgramState &state);
+    ~ProgramNULL() override;
+
+    LinkResult load(const ContextImpl *contextImpl,
+                    gl::InfoLog &infoLog,
+                    gl::BinaryInputStream *stream) override;
+    gl::Error save(gl::BinaryOutputStream *stream) override;
+    void setBinaryRetrievableHint(bool retrievable) override;
+    void setSeparable(bool separable) override;
+
+    LinkResult link(ContextImpl *contextImpl,
+                    const gl::VaryingPacking &packing,
+                    gl::InfoLog &infoLog) override;
+    GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
+
+    void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform1iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform2iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform3iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform4iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniformMatrix2fv(GLint location,
+                             GLsizei count,
+                             GLboolean transpose,
+                             const GLfloat *value) override;
+    void setUniformMatrix3fv(GLint location,
+                             GLsizei count,
+                             GLboolean transpose,
+                             const GLfloat *value) override;
+    void setUniformMatrix4fv(GLint location,
+                             GLsizei count,
+                             GLboolean transpose,
+                             const GLfloat *value) override;
+    void setUniformMatrix2x3fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix3x2fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix2x4fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix4x2fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix3x4fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix4x3fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+
+    // TODO: synchronize in syncState when dirty bits exist.
+    void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
+
+    // May only be called after a successful link operation.
+    // Return false for inactive blocks.
+    bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+
+    // May only be called after a successful link operation.
+    // Returns false for inactive members.
+    bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                   sh::BlockMemberInfo *memberInfoOut) const override;
+    // CHROMIUM_path_rendering
+    // Set parameters to control fragment shader input variable interpolation
+    void setPathFragmentInputGen(const std::string &inputName,
+                                 GLenum genMode,
+                                 GLint components,
+                                 const GLfloat *coeffs) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_PROGRAMNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/QueryNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/QueryNULL.cpp
new file mode 100644
index 0000000..8888028
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/QueryNULL.cpp
@@ -0,0 +1,70 @@
+//
+// Copyright 2016 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.
+//
+// QueryNULL.cpp:
+//    Implements the class methods for QueryNULL.
+//
+
+#include "libANGLE/renderer/null/QueryNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+QueryNULL::QueryNULL(GLenum type) : QueryImpl(type)
+{
+}
+
+QueryNULL::~QueryNULL()
+{
+}
+
+gl::Error QueryNULL::begin()
+{
+    return gl::NoError();
+}
+
+gl::Error QueryNULL::end()
+{
+    return gl::NoError();
+}
+
+gl::Error QueryNULL::queryCounter()
+{
+    return gl::NoError();
+}
+
+gl::Error QueryNULL::getResult(GLint *params)
+{
+    *params = 0;
+    return gl::NoError();
+}
+
+gl::Error QueryNULL::getResult(GLuint *params)
+{
+    *params = 0;
+    return gl::NoError();
+}
+
+gl::Error QueryNULL::getResult(GLint64 *params)
+{
+    *params = 0;
+    return gl::NoError();
+}
+
+gl::Error QueryNULL::getResult(GLuint64 *params)
+{
+    *params = 0;
+    return gl::NoError();
+}
+
+gl::Error QueryNULL::isResultAvailable(bool *available)
+{
+    *available = true;
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/QueryNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/QueryNULL.h
new file mode 100644
index 0000000..40082a9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/QueryNULL.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2016 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.
+//
+// QueryNULL.h:
+//    Defines the class interface for QueryNULL, implementing QueryImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_QUERYNULL_H_
+#define LIBANGLE_RENDERER_NULL_QUERYNULL_H_
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+
+class QueryNULL : public QueryImpl
+{
+  public:
+    QueryNULL(GLenum type);
+    ~QueryNULL() override;
+
+    gl::Error begin() override;
+    gl::Error end() override;
+    gl::Error queryCounter() override;
+    gl::Error getResult(GLint *params) override;
+    gl::Error getResult(GLuint *params) override;
+    gl::Error getResult(GLint64 *params) override;
+    gl::Error getResult(GLuint64 *params) override;
+    gl::Error isResultAvailable(bool *available) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_QUERYNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/RenderbufferNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/RenderbufferNULL.cpp
new file mode 100644
index 0000000..22b90e1
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/RenderbufferNULL.cpp
@@ -0,0 +1,43 @@
+//
+// Copyright 2016 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.
+//
+// RenderbufferNULL.cpp:
+//    Implements the class methods for RenderbufferNULL.
+//
+
+#include "libANGLE/renderer/null/RenderbufferNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+RenderbufferNULL::RenderbufferNULL() : RenderbufferImpl()
+{
+}
+
+RenderbufferNULL::~RenderbufferNULL()
+{
+}
+
+gl::Error RenderbufferNULL::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+    return gl::NoError();
+}
+
+gl::Error RenderbufferNULL::setStorageMultisample(size_t samples,
+                                                  GLenum internalformat,
+                                                  size_t width,
+                                                  size_t height)
+{
+    return gl::NoError();
+}
+
+gl::Error RenderbufferNULL::setStorageEGLImageTarget(egl::Image *image)
+{
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/RenderbufferNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/RenderbufferNULL.h
new file mode 100644
index 0000000..79e529c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/RenderbufferNULL.h
@@ -0,0 +1,34 @@
+//
+// Copyright 2016 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.
+//
+// RenderbufferNULL.h:
+//    Defines the class interface for RenderbufferNULL, implementing RenderbufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_RENDERBUFFERNULL_H_
+#define LIBANGLE_RENDERER_NULL_RENDERBUFFERNULL_H_
+
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+
+class RenderbufferNULL : public RenderbufferImpl
+{
+  public:
+    RenderbufferNULL();
+    ~RenderbufferNULL() override;
+
+    gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
+    gl::Error setStorageMultisample(size_t samples,
+                                    GLenum internalformat,
+                                    size_t width,
+                                    size_t height) override;
+    gl::Error setStorageEGLImageTarget(egl::Image *image) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_RENDERBUFFERNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/SamplerNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/SamplerNULL.cpp
new file mode 100644
index 0000000..e1e8c7c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/SamplerNULL.cpp
@@ -0,0 +1,25 @@
+//
+// Copyright 2016 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.
+//
+// SamplerNULL.cpp:
+//    Implements the class methods for SamplerNULL.
+//
+
+#include "libANGLE/renderer/null/SamplerNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+SamplerNULL::SamplerNULL() : SamplerImpl()
+{
+}
+
+SamplerNULL::~SamplerNULL()
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/SamplerNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/SamplerNULL.h
new file mode 100644
index 0000000..031fafa
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/SamplerNULL.h
@@ -0,0 +1,27 @@
+//
+// Copyright 2016 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.
+//
+// SamplerNULL.h:
+//    Defines the class interface for SamplerNULL, implementing SamplerImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_SAMPLERNULL_H_
+#define LIBANGLE_RENDERER_NULL_SAMPLERNULL_H_
+
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace rx
+{
+
+class SamplerNULL : public SamplerImpl
+{
+  public:
+    SamplerNULL();
+    ~SamplerNULL() override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_SAMPLERNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/ShaderNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/ShaderNULL.cpp
new file mode 100644
index 0000000..e7d8383
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/ShaderNULL.cpp
@@ -0,0 +1,42 @@
+//
+// Copyright 2016 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.
+//
+// ShaderNULL.cpp:
+//    Implements the class methods for ShaderNULL.
+//
+
+#include "libANGLE/renderer/null/ShaderNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ShaderNULL::ShaderNULL(const gl::ShaderState &data) : ShaderImpl(data)
+{
+}
+
+ShaderNULL::~ShaderNULL()
+{
+}
+
+ShCompileOptions ShaderNULL::prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+                                                           std::string *sourcePath)
+{
+    *sourceStream << mData.getSource();
+    return 0;
+}
+
+bool ShaderNULL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
+{
+    return true;
+}
+
+std::string ShaderNULL::getDebugInfo() const
+{
+    return "";
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/ShaderNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/ShaderNULL.h
new file mode 100644
index 0000000..d29b4cf
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/ShaderNULL.h
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 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.
+//
+// ShaderNULL.h:
+//    Defines the class interface for ShaderNULL, implementing ShaderImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_SHADERNULL_H_
+#define LIBANGLE_RENDERER_NULL_SHADERNULL_H_
+
+#include "libANGLE/renderer/ShaderImpl.h"
+
+namespace rx
+{
+
+class ShaderNULL : public ShaderImpl
+{
+  public:
+    ShaderNULL(const gl::ShaderState &data);
+    ~ShaderNULL() override;
+
+    // Returns additional sh::Compile options.
+    ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+                                                   std::string *sourcePath) override;
+    // Returns success for compiling on the driver. Returns success.
+    bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
+
+    std::string getDebugInfo() const override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_SHADERNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/SurfaceNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/SurfaceNULL.cpp
new file mode 100644
index 0000000..868269b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/SurfaceNULL.cpp
@@ -0,0 +1,95 @@
+//
+// Copyright 2016 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.
+//
+// SurfaceNULL.cpp:
+//    Implements the class methods for SurfaceNULL.
+//
+
+#include "libANGLE/renderer/null/SurfaceNULL.h"
+
+#include "common/debug.h"
+
+#include "libANGLE/renderer/null/FramebufferNULL.h"
+
+namespace rx
+{
+
+SurfaceNULL::SurfaceNULL(const egl::SurfaceState &surfaceState) : SurfaceImpl(surfaceState)
+{
+}
+
+SurfaceNULL::~SurfaceNULL()
+{
+}
+
+egl::Error SurfaceNULL::initialize(const DisplayImpl *displayImpl)
+{
+    return egl::NoError();
+}
+
+FramebufferImpl *SurfaceNULL::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+    return new FramebufferNULL(state);
+}
+
+egl::Error SurfaceNULL::swap(const DisplayImpl *displayImpl)
+{
+    return egl::NoError();
+}
+
+egl::Error SurfaceNULL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    return egl::NoError();
+}
+
+egl::Error SurfaceNULL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    UNREACHABLE();
+    return egl::NoError();
+}
+
+egl::Error SurfaceNULL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    return egl::NoError();
+}
+
+egl::Error SurfaceNULL::releaseTexImage(EGLint buffer)
+{
+    return egl::NoError();
+}
+
+egl::Error SurfaceNULL::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+void SurfaceNULL::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint SurfaceNULL::getWidth() const
+{
+    // TODO(geofflang): Read from an actual window?
+    return 100;
+}
+
+EGLint SurfaceNULL::getHeight() const
+{
+    // TODO(geofflang): Read from an actual window?
+    return 100;
+}
+
+EGLint SurfaceNULL::isPostSubBufferSupported() const
+{
+    return EGL_TRUE;
+}
+
+EGLint SurfaceNULL::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/SurfaceNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/SurfaceNULL.h
new file mode 100644
index 0000000..4b084a3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/SurfaceNULL.h
@@ -0,0 +1,44 @@
+//
+// Copyright 2016 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.
+//
+// SurfaceNULL.h:
+//    Defines the class interface for SurfaceNULL, implementing SurfaceImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_SURFACENULL_H_
+#define LIBANGLE_RENDERER_NULL_SURFACENULL_H_
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace rx
+{
+
+class SurfaceNULL : public SurfaceImpl
+{
+  public:
+    SurfaceNULL(const egl::SurfaceState &surfaceState);
+    ~SurfaceNULL() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+    void setSwapInterval(EGLint interval) override;
+
+    // width and height can change with client window resizing
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_SURFACENULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/TextureNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/TextureNULL.cpp
new file mode 100644
index 0000000..16ef4cc
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/TextureNULL.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright 2016 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.
+//
+// TextureNULL.cpp:
+//    Implements the class methods for TextureNULL.
+//
+
+#include "libANGLE/renderer/null/TextureNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+TextureNULL::TextureNULL(const gl::TextureState &state) : TextureImpl(state)
+{
+}
+
+TextureNULL::~TextureNULL()
+{
+}
+
+gl::Error TextureNULL::setImage(ContextImpl *contextImpl,
+                                GLenum target,
+                                size_t level,
+                                GLenum internalFormat,
+                                const gl::Extents &size,
+                                GLenum format,
+                                GLenum type,
+                                const gl::PixelUnpackState &unpack,
+                                const uint8_t *pixels)
+{
+    // TODO(geofflang): Read all incoming pixel data (maybe hash it?) to make sure we don't read out
+    // of bounds due to validation bugs.
+    return gl::NoError();
+}
+
+gl::Error TextureNULL::setSubImage(ContextImpl *contextImpl,
+                                   GLenum target,
+                                   size_t level,
+                                   const gl::Box &area,
+                                   GLenum format,
+                                   GLenum type,
+                                   const gl::PixelUnpackState &unpack,
+                                   const uint8_t *pixels)
+{
+    return gl::NoError();
+}
+
+gl::Error TextureNULL::setCompressedImage(ContextImpl *contextImpl,
+                                          GLenum target,
+                                          size_t level,
+                                          GLenum internalFormat,
+                                          const gl::Extents &size,
+                                          const gl::PixelUnpackState &unpack,
+                                          size_t imageSize,
+                                          const uint8_t *pixels)
+{
+    return gl::NoError();
+}
+
+gl::Error TextureNULL::setCompressedSubImage(ContextImpl *contextImpl,
+                                             GLenum target,
+                                             size_t level,
+                                             const gl::Box &area,
+                                             GLenum format,
+                                             const gl::PixelUnpackState &unpack,
+                                             size_t imageSize,
+                                             const uint8_t *pixels)
+{
+    return gl::NoError();
+}
+
+gl::Error TextureNULL::copyImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 const gl::Rectangle &sourceArea,
+                                 GLenum internalFormat,
+                                 const gl::Framebuffer *source)
+{
+    return gl::NoError();
+}
+
+gl::Error TextureNULL::copySubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Offset &destOffset,
+                                    const gl::Rectangle &sourceArea,
+                                    const gl::Framebuffer *source)
+{
+    return gl::NoError();
+}
+
+gl::Error TextureNULL::setStorage(ContextImpl *contextImpl,
+                                  GLenum target,
+                                  size_t levels,
+                                  GLenum internalFormat,
+                                  const gl::Extents &size)
+{
+    return gl::NoError();
+}
+
+gl::Error TextureNULL::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+    return gl::NoError();
+}
+
+gl::Error TextureNULL::setImageExternal(GLenum target,
+                                        egl::Stream *stream,
+                                        const egl::Stream::GLTextureDescription &desc)
+{
+    return gl::NoError();
+}
+
+gl::Error TextureNULL::generateMipmap(ContextImpl *contextImpl)
+{
+    return gl::NoError();
+}
+
+void TextureNULL::setBaseLevel(GLuint baseLevel)
+{
+}
+
+void TextureNULL::bindTexImage(egl::Surface *surface)
+{
+}
+
+void TextureNULL::releaseTexImage()
+{
+}
+
+void TextureNULL::syncState(const gl::Texture::DirtyBits &dirtyBits)
+{
+}
+
+gl::Error TextureNULL::setStorageMultisample(ContextImpl *contextImpl,
+                                             GLenum target,
+                                             GLsizei samples,
+                                             GLint internalformat,
+                                             const gl::Extents &size,
+                                             GLboolean fixedSampleLocations)
+{
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/TextureNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/TextureNULL.h
new file mode 100644
index 0000000..c529090f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/TextureNULL.h
@@ -0,0 +1,103 @@
+//
+// Copyright 2016 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.
+//
+// TextureNULL.h:
+//    Defines the class interface for TextureNULL, implementing TextureImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_TEXTURENULL_H_
+#define LIBANGLE_RENDERER_NULL_TEXTURENULL_H_
+
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace rx
+{
+
+class TextureNULL : public TextureImpl
+{
+  public:
+    TextureNULL(const gl::TextureState &state);
+    ~TextureNULL() override;
+
+    gl::Error setImage(ContextImpl *contextImpl,
+                       GLenum target,
+                       size_t level,
+                       GLenum internalFormat,
+                       const gl::Extents &size,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels) override;
+    gl::Error setSubImage(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          const gl::Box &area,
+                          GLenum format,
+                          GLenum type,
+                          const gl::PixelUnpackState &unpack,
+                          const uint8_t *pixels) override;
+
+    gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size,
+                                 const gl::PixelUnpackState &unpack,
+                                 size_t imageSize,
+                                 const uint8_t *pixels) override;
+    gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Box &area,
+                                    GLenum format,
+                                    const gl::PixelUnpackState &unpack,
+                                    size_t imageSize,
+                                    const uint8_t *pixels) override;
+
+    gl::Error copyImage(ContextImpl *contextImpl,
+                        GLenum target,
+                        size_t level,
+                        const gl::Rectangle &sourceArea,
+                        GLenum internalFormat,
+                        const gl::Framebuffer *source) override;
+    gl::Error copySubImage(ContextImpl *contextImpl,
+                           GLenum target,
+                           size_t level,
+                           const gl::Offset &destOffset,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Framebuffer *source) override;
+
+    gl::Error setStorage(ContextImpl *contextImpl,
+                         GLenum target,
+                         size_t levels,
+                         GLenum internalFormat,
+                         const gl::Extents &size) override;
+
+    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+    gl::Error setImageExternal(GLenum target,
+                               egl::Stream *stream,
+                               const egl::Stream::GLTextureDescription &desc) override;
+
+    gl::Error generateMipmap(ContextImpl *contextImpl) override;
+
+    void setBaseLevel(GLuint baseLevel) override;
+
+    void bindTexImage(egl::Surface *surface) override;
+    void releaseTexImage() override;
+
+    void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+
+    gl::Error setStorageMultisample(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    GLsizei samples,
+                                    GLint internalformat,
+                                    const gl::Extents &size,
+                                    GLboolean fixedSampleLocations) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_TEXTURENULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp
new file mode 100644
index 0000000..b26f29a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp
@@ -0,0 +1,51 @@
+//
+// Copyright 2016 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.
+//
+// TransformFeedbackNULL.cpp:
+//    Implements the class methods for TransformFeedbackNULL.
+//
+
+#include "libANGLE/renderer/null/TransformFeedbackNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+TransformFeedbackNULL::TransformFeedbackNULL(const gl::TransformFeedbackState &state)
+    : TransformFeedbackImpl(state)
+{
+}
+
+TransformFeedbackNULL::~TransformFeedbackNULL()
+{
+}
+
+void TransformFeedbackNULL::begin(GLenum primitiveMode)
+{
+}
+
+void TransformFeedbackNULL::end()
+{
+}
+
+void TransformFeedbackNULL::pause()
+{
+}
+
+void TransformFeedbackNULL::resume()
+{
+}
+
+void TransformFeedbackNULL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+{
+}
+
+void TransformFeedbackNULL::bindIndexedBuffer(size_t index,
+                                              const OffsetBindingPointer<gl::Buffer> &binding)
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.h
new file mode 100644
index 0000000..477e81d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.h
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 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.
+//
+// TransformFeedbackNULL.h:
+//    Defines the class interface for TransformFeedbackNULL, implementing TransformFeedbackImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_TRANSFORMFEEDBACKNULL_H_
+#define LIBANGLE_RENDERER_NULL_TRANSFORMFEEDBACKNULL_H_
+
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class TransformFeedbackNULL : public TransformFeedbackImpl
+{
+  public:
+    TransformFeedbackNULL(const gl::TransformFeedbackState &state);
+    ~TransformFeedbackNULL() override;
+
+    void begin(GLenum primitiveMode) override;
+    void end() override;
+    void pause() override;
+    void resume() override;
+
+    void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
+    void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_TRANSFORMFEEDBACKNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/VertexArrayNULL.cpp b/src/third_party/angle/src/libANGLE/renderer/null/VertexArrayNULL.cpp
new file mode 100644
index 0000000..95a835d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/VertexArrayNULL.cpp
@@ -0,0 +1,25 @@
+//
+// Copyright 2016 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.
+//
+// VertexArrayNULL.cpp:
+//    Implements the class methods for VertexArrayNULL.
+//
+
+#include "libANGLE/renderer/null/VertexArrayNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+VertexArrayNULL::VertexArrayNULL(const gl::VertexArrayState &data) : VertexArrayImpl(data)
+{
+}
+
+VertexArrayNULL::~VertexArrayNULL()
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/null/VertexArrayNULL.h b/src/third_party/angle/src/libANGLE/renderer/null/VertexArrayNULL.h
new file mode 100644
index 0000000..f8b2b04
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/null/VertexArrayNULL.h
@@ -0,0 +1,27 @@
+//
+// Copyright 2016 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.
+//
+// VertexArrayNULL.h:
+//    Defines the class interface for VertexArrayNULL, implementing VertexArrayImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_VERTEXARRAYNULL_H_
+#define LIBANGLE_RENDERER_NULL_VERTEXARRAYNULL_H_
+
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace rx
+{
+
+class VertexArrayNULL : public VertexArrayImpl
+{
+  public:
+    VertexArrayNULL(const gl::VertexArrayState &data);
+    ~VertexArrayNULL() override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_NULL_VERTEXARRAYNULL_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/renderer_utils.cpp b/src/third_party/angle/src/libANGLE/renderer/renderer_utils.cpp
new file mode 100644
index 0000000..7773e35
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/renderer_utils.cpp
@@ -0,0 +1,291 @@
+//
+// Copyright 2016 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.
+//
+// renderer_utils:
+//   Helper methods pertaining to most or all back-ends.
+//
+
+#include "libANGLE/renderer/renderer_utils.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/imageformats.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/Format.h"
+
+#include <string.h>
+
+namespace rx
+{
+
+namespace
+{
+typedef std::pair<gl::FormatType, ColorWriteFunction> FormatWriteFunctionPair;
+typedef std::map<gl::FormatType, ColorWriteFunction> FormatWriteFunctionMap;
+
+static inline void InsertFormatWriteFunctionMapping(FormatWriteFunctionMap *map,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    ColorWriteFunction writeFunc)
+{
+    map->insert(FormatWriteFunctionPair(gl::FormatType(format, type), writeFunc));
+}
+
+static FormatWriteFunctionMap BuildFormatWriteFunctionMap()
+{
+    using namespace angle;  //  For image writing functions
+
+    FormatWriteFunctionMap map;
+
+    // clang-format off
+    //                                    | Format               | Type                             | Color write function             |
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA,               GL_UNSIGNED_BYTE,                  WriteColor<R8G8B8A8, GLfloat>     );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA,               GL_BYTE,                           WriteColor<R8G8B8A8S, GLfloat>    );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA,               GL_UNSIGNED_SHORT_4_4_4_4,         WriteColor<R4G4B4A4, GLfloat>     );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA,               GL_UNSIGNED_SHORT_5_5_5_1,         WriteColor<R5G5B5A1, GLfloat>     );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA,               GL_UNSIGNED_INT_2_10_10_10_REV,    WriteColor<R10G10B10A2, GLfloat>  );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA,               GL_FLOAT,                          WriteColor<R32G32B32A32F, GLfloat>);
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA,               GL_HALF_FLOAT,                     WriteColor<R16G16B16A16F, GLfloat>);
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA,               GL_HALF_FLOAT_OES,                 WriteColor<R16G16B16A16F, GLfloat>);
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT,
+                                     WriteColor<R16G16B16A16, GLfloat>);
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_SHORT, WriteColor<R16G16B16A16S, GLfloat>);
+
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER,       GL_UNSIGNED_BYTE,                  WriteColor<R8G8B8A8, GLuint>      );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER,       GL_BYTE,                           WriteColor<R8G8B8A8S, GLint>      );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER,       GL_UNSIGNED_SHORT,                 WriteColor<R16G16B16A16, GLuint>  );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER,       GL_SHORT,                          WriteColor<R16G16B16A16S, GLint>  );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER,       GL_UNSIGNED_INT,                   WriteColor<R32G32B32A32, GLuint>  );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER,       GL_INT,                            WriteColor<R32G32B32A32S, GLint>  );
+    InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER,       GL_UNSIGNED_INT_2_10_10_10_REV,    WriteColor<R10G10B10A2, GLuint>   );
+
+    InsertFormatWriteFunctionMapping(&map, GL_RGB,                GL_UNSIGNED_BYTE,                  WriteColor<R8G8B8, GLfloat>       );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB,                GL_BYTE,                           WriteColor<R8G8B8S, GLfloat>      );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB,                GL_UNSIGNED_SHORT_5_6_5,           WriteColor<R5G6B5, GLfloat>       );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB,                GL_UNSIGNED_INT_10F_11F_11F_REV,   WriteColor<R11G11B10F, GLfloat>   );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB,                GL_UNSIGNED_INT_5_9_9_9_REV,       WriteColor<R9G9B9E5, GLfloat>     );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB,                GL_FLOAT,                          WriteColor<R32G32B32F, GLfloat>   );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB,                GL_HALF_FLOAT,                     WriteColor<R16G16B16F, GLfloat>   );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB,                GL_HALF_FLOAT_OES,                 WriteColor<R16G16B16F, GLfloat>   );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT,
+                                     WriteColor<R16G16B16, GLfloat>);
+    InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_SHORT, WriteColor<R16G16B16S, GLfloat>);
+
+    InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER,        GL_UNSIGNED_BYTE,                  WriteColor<R8G8B8, GLuint>        );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER,        GL_BYTE,                           WriteColor<R8G8B8S, GLint>        );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER,        GL_UNSIGNED_SHORT,                 WriteColor<R16G16B16, GLuint>     );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER,        GL_SHORT,                          WriteColor<R16G16B16S, GLint>     );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER,        GL_UNSIGNED_INT,                   WriteColor<R32G32B32, GLuint>     );
+    InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER,        GL_INT,                            WriteColor<R32G32B32S, GLint>     );
+
+    InsertFormatWriteFunctionMapping(&map, GL_RG,                 GL_UNSIGNED_BYTE,                  WriteColor<R8G8, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_RG,                 GL_BYTE,                           WriteColor<R8G8S, GLfloat>        );
+    InsertFormatWriteFunctionMapping(&map, GL_RG,                 GL_FLOAT,                          WriteColor<R32G32F, GLfloat>      );
+    InsertFormatWriteFunctionMapping(&map, GL_RG,                 GL_HALF_FLOAT,                     WriteColor<R16G16F, GLfloat>      );
+    InsertFormatWriteFunctionMapping(&map, GL_RG,                 GL_HALF_FLOAT_OES,                 WriteColor<R16G16F, GLfloat>      );
+    InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_SHORT, WriteColor<R16G16, GLfloat>);
+    InsertFormatWriteFunctionMapping(&map, GL_RG, GL_SHORT, WriteColor<R16G16S, GLfloat>);
+
+    InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER,         GL_UNSIGNED_BYTE,                  WriteColor<R8G8, GLuint>          );
+    InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER,         GL_BYTE,                           WriteColor<R8G8S, GLint>          );
+    InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER,         GL_UNSIGNED_SHORT,                 WriteColor<R16G16, GLuint>        );
+    InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER,         GL_SHORT,                          WriteColor<R16G16S, GLint>        );
+    InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER,         GL_UNSIGNED_INT,                   WriteColor<R32G32, GLuint>        );
+    InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER,         GL_INT,                            WriteColor<R32G32S, GLint>        );
+
+    InsertFormatWriteFunctionMapping(&map, GL_RED,                GL_UNSIGNED_BYTE,                  WriteColor<R8, GLfloat>           );
+    InsertFormatWriteFunctionMapping(&map, GL_RED,                GL_BYTE,                           WriteColor<R8S, GLfloat>          );
+    InsertFormatWriteFunctionMapping(&map, GL_RED,                GL_FLOAT,                          WriteColor<R32F, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_RED,                GL_HALF_FLOAT,                     WriteColor<R16F, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_RED,                GL_HALF_FLOAT_OES,                 WriteColor<R16F, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_SHORT, WriteColor<R16, GLfloat>);
+    InsertFormatWriteFunctionMapping(&map, GL_RED, GL_SHORT, WriteColor<R16S, GLfloat>);
+
+    InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER,        GL_UNSIGNED_BYTE,                  WriteColor<R8, GLuint>            );
+    InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER,        GL_BYTE,                           WriteColor<R8S, GLint>            );
+    InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER,        GL_UNSIGNED_SHORT,                 WriteColor<R16, GLuint>           );
+    InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER,        GL_SHORT,                          WriteColor<R16S, GLint>           );
+    InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER,        GL_UNSIGNED_INT,                   WriteColor<R32, GLuint>           );
+    InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER,        GL_INT,                            WriteColor<R32S, GLint>           );
+
+    InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA,    GL_UNSIGNED_BYTE,                  WriteColor<L8A8, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE,          GL_UNSIGNED_BYTE,                  WriteColor<L8, GLfloat>           );
+    InsertFormatWriteFunctionMapping(&map, GL_ALPHA,              GL_UNSIGNED_BYTE,                  WriteColor<A8, GLfloat>           );
+    InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA,    GL_FLOAT,                          WriteColor<L32A32F, GLfloat>      );
+    InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE,          GL_FLOAT,                          WriteColor<L32F, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_ALPHA,              GL_FLOAT,                          WriteColor<A32F, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA,    GL_HALF_FLOAT,                     WriteColor<L16A16F, GLfloat>      );
+    InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA,    GL_HALF_FLOAT_OES,                 WriteColor<L16A16F, GLfloat>      );
+    InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE,          GL_HALF_FLOAT,                     WriteColor<L16F, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE,          GL_HALF_FLOAT_OES,                 WriteColor<L16F, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_ALPHA,              GL_HALF_FLOAT,                     WriteColor<A16F, GLfloat>         );
+    InsertFormatWriteFunctionMapping(&map, GL_ALPHA,              GL_HALF_FLOAT_OES,                 WriteColor<A16F, GLfloat>         );
+
+    InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT,           GL_UNSIGNED_BYTE,                  WriteColor<B8G8R8A8, GLfloat>     );
+    InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT,           GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor<A4R4G4B4, GLfloat>     );
+    InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT,           GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor<A1R5G5B5, GLfloat>     );
+
+    InsertFormatWriteFunctionMapping(&map, GL_SRGB_EXT,           GL_UNSIGNED_BYTE,                  WriteColor<R8G8B8, GLfloat>       );
+    InsertFormatWriteFunctionMapping(&map, GL_SRGB_ALPHA_EXT,     GL_UNSIGNED_BYTE,                  WriteColor<R8G8B8A8, GLfloat>     );
+
+    InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    GL_UNSIGNED_BYTE,     nullptr                              );
+    InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   GL_UNSIGNED_BYTE,     nullptr                              );
+    InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE,     nullptr                              );
+    InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE,     nullptr                              );
+
+    InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT,    GL_UNSIGNED_SHORT,                 nullptr                              );
+    InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT,    GL_UNSIGNED_INT,                   nullptr                              );
+    InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT,    GL_FLOAT,                          nullptr                              );
+
+    InsertFormatWriteFunctionMapping(&map, GL_STENCIL,            GL_UNSIGNED_BYTE,                  nullptr                              );
+
+    InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL,      GL_UNSIGNED_INT_24_8,              nullptr                              );
+    InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL,      GL_FLOAT_32_UNSIGNED_INT_24_8_REV, nullptr                              );
+    // clang-format on
+
+    return map;
+}
+}  // anonymous namespace
+
+PackPixelsParams::PackPixelsParams()
+    : format(GL_NONE), type(GL_NONE), outputPitch(0), packBuffer(nullptr), offset(0)
+{
+}
+
+PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn,
+                                   GLenum formatIn,
+                                   GLenum typeIn,
+                                   GLuint outputPitchIn,
+                                   const gl::PixelPackState &packIn,
+                                   ptrdiff_t offsetIn)
+    : area(areaIn),
+      format(formatIn),
+      type(typeIn),
+      outputPitch(outputPitchIn),
+      packBuffer(packIn.pixelBuffer.get()),
+      pack(packIn.alignment, packIn.reverseRowOrder),
+      offset(offsetIn)
+{
+}
+
+void PackPixels(const PackPixelsParams &params,
+                const angle::Format &sourceFormat,
+                int inputPitchIn,
+                const uint8_t *sourceIn,
+                uint8_t *destWithoutOffset)
+{
+    uint8_t *destWithOffset = destWithoutOffset + params.offset;
+
+    const uint8_t *source = sourceIn;
+    int inputPitch        = inputPitchIn;
+
+    if (params.pack.reverseRowOrder)
+    {
+        source += inputPitch * (params.area.height - 1);
+        inputPitch = -inputPitch;
+    }
+
+    const auto &sourceGLInfo = gl::GetSizedInternalFormatInfo(sourceFormat.glInternalFormat);
+
+    if (sourceGLInfo.format == params.format && sourceGLInfo.type == params.type)
+    {
+        // Direct copy possible
+        for (int y = 0; y < params.area.height; ++y)
+        {
+            memcpy(destWithOffset + y * params.outputPitch, source + y * inputPitch,
+                   params.area.width * sourceGLInfo.pixelBytes);
+        }
+        return;
+    }
+
+    ASSERT(sourceGLInfo.sized);
+
+    gl::FormatType formatType(params.format, params.type);
+    ColorCopyFunction fastCopyFunc =
+        GetFastCopyFunction(sourceFormat.fastCopyFunctions, formatType);
+    const auto &destFormatInfo = gl::GetInternalFormatInfo(formatType.format, formatType.type);
+
+    if (fastCopyFunc)
+    {
+        // Fast copy is possible through some special function
+        for (int y = 0; y < params.area.height; ++y)
+        {
+            for (int x = 0; x < params.area.width; ++x)
+            {
+                uint8_t *dest =
+                    destWithOffset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+                const uint8_t *src = source + y * inputPitch + x * sourceGLInfo.pixelBytes;
+
+                fastCopyFunc(src, dest);
+            }
+        }
+        return;
+    }
+
+    ColorWriteFunction colorWriteFunction = GetColorWriteFunction(formatType);
+
+    // Maximum size of any Color<T> type used.
+    uint8_t temp[16];
+    static_assert(sizeof(temp) >= sizeof(gl::ColorF) && sizeof(temp) >= sizeof(gl::ColorUI) &&
+                      sizeof(temp) >= sizeof(gl::ColorI),
+                  "Unexpected size of gl::Color struct.");
+
+    const auto &colorReadFunction = sourceFormat.colorReadFunction;
+
+    for (int y = 0; y < params.area.height; ++y)
+    {
+        for (int x = 0; x < params.area.width; ++x)
+        {
+            uint8_t *dest      = destWithOffset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+            const uint8_t *src = source + y * inputPitch + x * sourceGLInfo.pixelBytes;
+
+            // readFunc and writeFunc will be using the same type of color, CopyTexImage
+            // will not allow the copy otherwise.
+            colorReadFunction(src, temp);
+            colorWriteFunction(temp, dest);
+        }
+    }
+}
+
+ColorWriteFunction GetColorWriteFunction(const gl::FormatType &formatType)
+{
+    static const FormatWriteFunctionMap formatTypeMap = BuildFormatWriteFunctionMap();
+    auto iter = formatTypeMap.find(formatType);
+    ASSERT(iter != formatTypeMap.end());
+    if (iter != formatTypeMap.end())
+    {
+        return iter->second;
+    }
+    else
+    {
+        return nullptr;
+    }
+}
+
+ColorCopyFunction GetFastCopyFunction(const FastCopyFunctionMap &fastCopyFunctions,
+                                      const gl::FormatType &formatType)
+{
+    return fastCopyFunctions.get(formatType);
+}
+
+bool FastCopyFunctionMap::has(const gl::FormatType &formatType) const
+{
+    return (get(formatType) != nullptr);
+}
+
+ColorCopyFunction FastCopyFunctionMap::get(const gl::FormatType &formatType) const
+{
+    for (size_t index = 0; index < mSize; ++index)
+    {
+        if (mData[index].format == formatType.format && mData[index].type == formatType.type)
+        {
+            return mData[index].func;
+        }
+    }
+
+    return nullptr;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/renderer_utils.h b/src/third_party/angle/src/libANGLE/renderer/renderer_utils.h
new file mode 100644
index 0000000..803c8c2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/renderer_utils.h
@@ -0,0 +1,131 @@
+//
+// Copyright 2016 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.
+//
+// renderer_utils:
+//   Helper methods pertaining to most or all back-ends.
+//
+
+#ifndef LIBANGLE_RENDERER_RENDERER_UTILS_H_
+#define LIBANGLE_RENDERER_RENDERER_UTILS_H_
+
+#include <cstdint>
+
+#include <map>
+
+#include "libANGLE/angletypes.h"
+
+namespace angle
+{
+struct Format;
+}
+
+namespace gl
+{
+struct FormatType;
+struct InternalFormat;
+}
+
+namespace rx
+{
+
+using MipGenerationFunction = void (*)(size_t sourceWidth,
+                                       size_t sourceHeight,
+                                       size_t sourceDepth,
+                                       const uint8_t *sourceData,
+                                       size_t sourceRowPitch,
+                                       size_t sourceDepthPitch,
+                                       uint8_t *destData,
+                                       size_t destRowPitch,
+                                       size_t destDepthPitch);
+
+typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest);
+
+class FastCopyFunctionMap
+{
+  public:
+    struct Entry
+    {
+        GLenum format;
+        GLenum type;
+        ColorCopyFunction func;
+    };
+
+    constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {}
+
+    constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {}
+
+    bool has(const gl::FormatType &formatType) const;
+    ColorCopyFunction get(const gl::FormatType &formatType) const;
+
+  private:
+    size_t mSize;
+    const Entry *mData;
+};
+
+struct PackPixelsParams
+{
+    PackPixelsParams();
+    PackPixelsParams(const gl::Rectangle &area,
+                     GLenum format,
+                     GLenum type,
+                     GLuint outputPitch,
+                     const gl::PixelPackState &pack,
+                     ptrdiff_t offset);
+
+    gl::Rectangle area;
+    GLenum format;
+    GLenum type;
+    GLuint outputPitch;
+    gl::Buffer *packBuffer;
+    gl::PixelPackState pack;
+    ptrdiff_t offset;
+};
+
+void PackPixels(const PackPixelsParams &params,
+                const angle::Format &sourceFormat,
+                int inputPitch,
+                const uint8_t *source,
+                uint8_t *destination);
+
+ColorWriteFunction GetColorWriteFunction(const gl::FormatType &formatType);
+ColorCopyFunction GetFastCopyFunction(const FastCopyFunctionMap &fastCopyFunctions,
+                                      const gl::FormatType &formatType);
+
+using InitializeTextureDataFunction = void (*)(size_t width,
+                                               size_t height,
+                                               size_t depth,
+                                               uint8_t *output,
+                                               size_t outputRowPitch,
+                                               size_t outputDepthPitch);
+
+using LoadImageFunction = void (*)(size_t width,
+                                   size_t height,
+                                   size_t depth,
+                                   const uint8_t *input,
+                                   size_t inputRowPitch,
+                                   size_t inputDepthPitch,
+                                   uint8_t *output,
+                                   size_t outputRowPitch,
+                                   size_t outputDepthPitch);
+
+struct LoadImageFunctionInfo
+{
+    LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {}
+    LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion)
+        : loadFunction(loadFunction), requiresConversion(requiresConversion)
+    {
+    }
+
+    LoadImageFunction loadFunction;
+    bool requiresConversion;
+};
+
+using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum);
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_RENDERER_UTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp
new file mode 100644
index 0000000..bdfa32c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp
@@ -0,0 +1,192 @@
+//
+// Copyright 2016 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.
+//
+// BufferVk.cpp:
+//    Implements the class methods for BufferVk.
+//
+
+#include "libANGLE/renderer/vulkan/BufferVk.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+
+namespace rx
+{
+
+BufferVk::BufferVk(const gl::BufferState &state) : BufferImpl(state), mRequiredSize(0)
+{
+}
+
+BufferVk::~BufferVk()
+{
+}
+
+void BufferVk::destroy(ContextImpl *contextImpl)
+{
+    VkDevice device = GetAs<ContextVk>(contextImpl)->getDevice();
+
+    mBuffer.destroy(device);
+}
+
+gl::Error BufferVk::setData(ContextImpl *context,
+                            GLenum target,
+                            const void *data,
+                            size_t size,
+                            GLenum usage)
+{
+    ContextVk *contextVk = GetAs<ContextVk>(context);
+    auto device          = contextVk->getDevice();
+
+    // TODO(jmadill): Proper usage bit implementation. Likely will involve multiple backing buffers
+    // like in D3D11.
+    VkBufferCreateInfo createInfo;
+    createInfo.sType                 = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+    createInfo.pNext                 = nullptr;
+    createInfo.flags                 = 0;
+    createInfo.size                  = size;
+    createInfo.usage                 = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+    createInfo.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
+    createInfo.queueFamilyIndexCount = 0;
+    createInfo.pQueueFamilyIndices   = nullptr;
+
+    vk::Buffer newBuffer;
+    ANGLE_TRY(newBuffer.init(device, createInfo));
+
+    // Find a compatible memory pool index. If the index doesn't change, we could cache it.
+    // Not finding a valid memory pool means an out-of-spec driver, or internal error.
+    // TODO(jmadill): More efficient memory allocation.
+    VkMemoryRequirements memoryRequirements;
+    vkGetBufferMemoryRequirements(device, newBuffer.getHandle(), &memoryRequirements);
+
+    // The requirements size is not always equal to the specified API size.
+    ASSERT(memoryRequirements.size >= size);
+    mRequiredSize = static_cast<size_t>(memoryRequirements.size);
+
+    VkPhysicalDeviceMemoryProperties memoryProperties;
+    vkGetPhysicalDeviceMemoryProperties(contextVk->getRenderer()->getPhysicalDevice(),
+                                        &memoryProperties);
+
+    auto memoryTypeIndex =
+        FindMemoryType(memoryProperties, memoryRequirements,
+                       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+    ANGLE_VK_CHECK(memoryTypeIndex.valid(), VK_ERROR_INCOMPATIBLE_DRIVER);
+
+    VkMemoryAllocateInfo allocInfo;
+    allocInfo.sType           = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+    allocInfo.pNext           = nullptr;
+    allocInfo.memoryTypeIndex = memoryTypeIndex.value();
+    allocInfo.allocationSize  = memoryRequirements.size;
+
+    ANGLE_TRY(newBuffer.getMemory().allocate(device, allocInfo));
+    ANGLE_TRY(newBuffer.bindMemory(device));
+
+    mBuffer.retain(device, std::move(newBuffer));
+
+    if (data)
+    {
+        ANGLE_TRY(setDataImpl(device, static_cast<const uint8_t *>(data), size, 0));
+    }
+
+    return gl::NoError();
+}
+
+gl::Error BufferVk::setSubData(ContextImpl *context,
+                               GLenum target,
+                               const void *data,
+                               size_t size,
+                               size_t offset)
+{
+    ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE);
+    ASSERT(mBuffer.getMemory().getHandle() != VK_NULL_HANDLE);
+
+    VkDevice device = GetAs<ContextVk>(context)->getDevice();
+
+    ANGLE_TRY(setDataImpl(device, static_cast<const uint8_t *>(data), size, offset));
+
+    return gl::NoError();
+}
+
+gl::Error BufferVk::copySubData(ContextImpl *context,
+                                BufferImpl *source,
+                                GLintptr sourceOffset,
+                                GLintptr destOffset,
+                                GLsizeiptr size)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferVk::map(ContextImpl *context, GLenum access, void **mapPtr)
+{
+    ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE);
+    ASSERT(mBuffer.getMemory().getHandle() != VK_NULL_HANDLE);
+
+    VkDevice device = GetAs<ContextVk>(context)->getDevice();
+
+    ANGLE_TRY(mBuffer.getMemory().map(device, 0, mState.getSize(), 0,
+                                      reinterpret_cast<uint8_t **>(mapPtr)));
+
+    return gl::NoError();
+}
+
+gl::Error BufferVk::mapRange(ContextImpl *context,
+                             size_t offset,
+                             size_t length,
+                             GLbitfield access,
+                             void **mapPtr)
+{
+    ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE);
+    ASSERT(mBuffer.getMemory().getHandle() != VK_NULL_HANDLE);
+
+    VkDevice device = GetAs<ContextVk>(context)->getDevice();
+
+    ANGLE_TRY(
+        mBuffer.getMemory().map(device, offset, length, 0, reinterpret_cast<uint8_t **>(mapPtr)));
+
+    return gl::NoError();
+}
+
+gl::Error BufferVk::unmap(ContextImpl *context, GLboolean *result)
+{
+    ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE);
+    ASSERT(mBuffer.getMemory().getHandle() != VK_NULL_HANDLE);
+
+    VkDevice device = GetAs<ContextVk>(context)->getDevice();
+
+    mBuffer.getMemory().unmap(device);
+
+    return gl::NoError();
+}
+
+gl::Error BufferVk::getIndexRange(GLenum type,
+                                  size_t offset,
+                                  size_t count,
+                                  bool primitiveRestartEnabled,
+                                  gl::IndexRange *outRange)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+vk::Error BufferVk::setDataImpl(VkDevice device, const uint8_t *data, size_t size, size_t offset)
+{
+    uint8_t *mapPointer = nullptr;
+    ANGLE_TRY(mBuffer.getMemory().map(device, offset, size, 0, &mapPointer));
+    ASSERT(mapPointer);
+
+    memcpy(mapPointer, data, size);
+
+    mBuffer.getMemory().unmap(device);
+
+    return vk::NoError();
+}
+
+const vk::Buffer &BufferVk::getVkBuffer() const
+{
+    return mBuffer;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.h
new file mode 100644
index 0000000..410b500
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.h
@@ -0,0 +1,66 @@
+//
+// Copyright 2016 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.
+//
+// BufferVk.h:
+//    Defines the class interface for BufferVk, implementing BufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
+
+#include "libANGLE/renderer/BufferImpl.h"
+#include "libANGLE/renderer/vulkan/renderervk_utils.h"
+
+namespace rx
+{
+
+class BufferVk : public BufferImpl, public ResourceVk
+{
+  public:
+    BufferVk(const gl::BufferState &state);
+    ~BufferVk() override;
+    void destroy(ContextImpl *contextImpl) override;
+
+    gl::Error setData(ContextImpl *context,
+                      GLenum target,
+                      const void *data,
+                      size_t size,
+                      GLenum usage) override;
+    gl::Error setSubData(ContextImpl *context,
+                         GLenum target,
+                         const void *data,
+                         size_t size,
+                         size_t offset) override;
+    gl::Error copySubData(ContextImpl *contextImpl,
+                          BufferImpl *source,
+                          GLintptr sourceOffset,
+                          GLintptr destOffset,
+                          GLsizeiptr size) override;
+    gl::Error map(ContextImpl *contextImpl, GLenum access, void **mapPtr) override;
+    gl::Error mapRange(ContextImpl *contextImpl,
+                       size_t offset,
+                       size_t length,
+                       GLbitfield access,
+                       void **mapPtr) override;
+    gl::Error unmap(ContextImpl *contextImpl, GLboolean *result) override;
+
+    gl::Error getIndexRange(GLenum type,
+                            size_t offset,
+                            size_t count,
+                            bool primitiveRestartEnabled,
+                            gl::IndexRange *outRange) override;
+
+    const vk::Buffer &getVkBuffer() const;
+
+  private:
+    vk::Error setDataImpl(VkDevice device, const uint8_t *data, size_t size, size_t offset);
+
+    vk::Buffer mBuffer;
+    size_t mRequiredSize;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/CompilerVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/CompilerVk.cpp
new file mode 100644
index 0000000..f781c07
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/CompilerVk.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 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.
+//
+// CompilerVk.cpp:
+//    Implements the class methods for CompilerVk.
+//
+
+#include "libANGLE/renderer/vulkan/CompilerVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+CompilerVk::CompilerVk() : CompilerImpl()
+{
+}
+
+CompilerVk::~CompilerVk()
+{
+}
+
+gl::Error CompilerVk::release()
+{
+    return gl::NoError();
+}
+
+ShShaderOutput CompilerVk::getTranslatorOutputType() const
+{
+    return SH_GLSL_VULKAN_OUTPUT;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/CompilerVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/CompilerVk.h
new file mode 100644
index 0000000..2246a27
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/CompilerVk.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2016 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.
+//
+// CompilerVk.h:
+//    Defines the class interface for CompilerVk, implementing CompilerImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_COMPILERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_COMPILERVK_H_
+
+#include "libANGLE/renderer/CompilerImpl.h"
+
+namespace rx
+{
+
+class CompilerVk : public CompilerImpl
+{
+  public:
+    CompilerVk();
+    ~CompilerVk() override;
+
+    gl::Error release() override;
+
+    // TODO(jmadill): Expose translator built-in resources init method.
+    ShShaderOutput getTranslatorOutputType() const override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_COMPILERVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp
new file mode 100644
index 0000000..2a2c699
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -0,0 +1,559 @@
+//
+// Copyright 2016 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.
+//
+// ContextVk.cpp:
+//    Implements the class methods for ContextVk.
+//
+
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+
+#include "common/bitset_utils.h"
+#include "common/debug.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/renderer/vulkan/BufferVk.h"
+#include "libANGLE/renderer/vulkan/CompilerVk.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/DeviceVk.h"
+#include "libANGLE/renderer/vulkan/FenceNVVk.h"
+#include "libANGLE/renderer/vulkan/FenceSyncVk.h"
+#include "libANGLE/renderer/vulkan/FramebufferVk.h"
+#include "libANGLE/renderer/vulkan/ImageVk.h"
+#include "libANGLE/renderer/vulkan/ProgramVk.h"
+#include "libANGLE/renderer/vulkan/QueryVk.h"
+#include "libANGLE/renderer/vulkan/RenderbufferVk.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/SamplerVk.h"
+#include "libANGLE/renderer/vulkan/ShaderVk.h"
+#include "libANGLE/renderer/vulkan/TextureVk.h"
+#include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
+#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+
+namespace rx
+{
+
+ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
+    : ContextImpl(state), mRenderer(renderer), mCurrentDrawMode(GL_NONE)
+{
+}
+
+ContextVk::~ContextVk()
+{
+    invalidateCurrentPipeline();
+}
+
+gl::Error ContextVk::initialize()
+{
+    return gl::NoError();
+}
+
+gl::Error ContextVk::flush()
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::finish()
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::initPipeline()
+{
+    ASSERT(!mCurrentPipeline.valid());
+
+    VkDevice device       = mRenderer->getDevice();
+    const auto &state     = mState.getState();
+    const auto &programGL = state.getProgram();
+    const auto &vao       = state.getVertexArray();
+    const auto &attribs   = vao->getVertexAttributes();
+    const auto &bindings  = vao->getVertexBindings();
+    const auto &programVk = GetImplAs<ProgramVk>(programGL);
+    const auto *drawFBO   = state.getDrawFramebuffer();
+    FramebufferVk *vkFBO  = GetImplAs<FramebufferVk>(drawFBO);
+
+    // { vertex, fragment }
+    VkPipelineShaderStageCreateInfo shaderStages[2];
+
+    shaderStages[0].sType               = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+    shaderStages[0].pNext               = nullptr;
+    shaderStages[0].flags               = 0;
+    shaderStages[0].stage               = VK_SHADER_STAGE_VERTEX_BIT;
+    shaderStages[0].module              = programVk->getLinkedVertexModule().getHandle();
+    shaderStages[0].pName               = "main";
+    shaderStages[0].pSpecializationInfo = nullptr;
+
+    shaderStages[1].sType               = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+    shaderStages[1].pNext               = nullptr;
+    shaderStages[1].flags               = 0;
+    shaderStages[1].stage               = VK_SHADER_STAGE_FRAGMENT_BIT;
+    shaderStages[1].module              = programVk->getLinkedFragmentModule().getHandle();
+    shaderStages[1].pName               = "main";
+    shaderStages[1].pSpecializationInfo = nullptr;
+
+    // Process vertex attributes
+    // TODO(jmadill): Caching with dirty bits.
+    std::vector<VkVertexInputBindingDescription> vertexBindings;
+    std::vector<VkVertexInputAttributeDescription> vertexAttribs;
+
+    for (auto attribIndex : programGL->getActiveAttribLocationsMask())
+    {
+        const auto &attrib  = attribs[attribIndex];
+        const auto &binding = bindings[attrib.bindingIndex];
+        if (attrib.enabled)
+        {
+            VkVertexInputBindingDescription bindingDesc;
+            bindingDesc.binding = static_cast<uint32_t>(vertexBindings.size());
+            bindingDesc.stride  = static_cast<uint32_t>(gl::ComputeVertexAttributeTypeSize(attrib));
+            bindingDesc.inputRate =
+                (binding.divisor > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
+
+            gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
+
+            VkVertexInputAttributeDescription attribDesc;
+            attribDesc.binding  = bindingDesc.binding;
+            attribDesc.format   = vk::GetNativeVertexFormat(vertexFormatType);
+            attribDesc.location = static_cast<uint32_t>(attribIndex);
+            attribDesc.offset =
+                static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
+
+            vertexBindings.push_back(bindingDesc);
+            vertexAttribs.push_back(attribDesc);
+        }
+        else
+        {
+            UNIMPLEMENTED();
+        }
+    }
+
+    // TODO(jmadill): Validate with ASSERT against physical device limits/caps?
+    VkPipelineVertexInputStateCreateInfo vertexInputState;
+    vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+    vertexInputState.pNext = nullptr;
+    vertexInputState.flags = 0;
+    vertexInputState.vertexBindingDescriptionCount   = static_cast<uint32_t>(vertexBindings.size());
+    vertexInputState.pVertexBindingDescriptions      = vertexBindings.data();
+    vertexInputState.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertexAttribs.size());
+    vertexInputState.pVertexAttributeDescriptions    = vertexAttribs.data();
+
+    VkPipelineInputAssemblyStateCreateInfo inputAssemblyState;
+    inputAssemblyState.sType    = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+    inputAssemblyState.pNext    = nullptr;
+    inputAssemblyState.flags    = 0;
+    inputAssemblyState.topology = gl_vk::GetPrimitiveTopology(mCurrentDrawMode);
+    inputAssemblyState.primitiveRestartEnable = VK_FALSE;
+
+    const gl::Rectangle &viewportGL = state.getViewport();
+    VkViewport viewportVk;
+    viewportVk.x        = static_cast<float>(viewportGL.x);
+    viewportVk.y        = static_cast<float>(viewportGL.y);
+    viewportVk.width    = static_cast<float>(viewportGL.width);
+    viewportVk.height   = static_cast<float>(viewportGL.height);
+    viewportVk.minDepth = state.getNearPlane();
+    viewportVk.maxDepth = state.getFarPlane();
+
+    // TODO(jmadill): Scissor.
+    VkRect2D scissorVk;
+    scissorVk.offset.x      = viewportGL.x;
+    scissorVk.offset.y      = viewportGL.y;
+    scissorVk.extent.width  = viewportGL.width;
+    scissorVk.extent.height = viewportGL.height;
+
+    VkPipelineViewportStateCreateInfo viewportState;
+    viewportState.sType         = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+    viewportState.pNext         = nullptr;
+    viewportState.flags         = 0;
+    viewportState.viewportCount = 1;
+    viewportState.pViewports    = &viewportVk;
+    viewportState.scissorCount  = 1;
+    viewportState.pScissors     = &scissorVk;
+
+    // TODO(jmadill): Extra rasterizer state features.
+    VkPipelineRasterizationStateCreateInfo rasterState;
+    rasterState.sType            = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+    rasterState.pNext            = nullptr;
+    rasterState.flags            = 0;
+    rasterState.depthClampEnable = VK_FALSE;
+    rasterState.rasterizerDiscardEnable = VK_FALSE;
+    rasterState.polygonMode             = VK_POLYGON_MODE_FILL;
+    rasterState.cullMode                = gl_vk::GetCullMode(state.getRasterizerState());
+    rasterState.frontFace               = gl_vk::GetFrontFace(state.getRasterizerState().frontFace);
+    rasterState.depthBiasEnable         = VK_FALSE;
+    rasterState.depthBiasConstantFactor = 0.0f;
+    rasterState.depthBiasClamp          = 0.0f;
+    rasterState.depthBiasSlopeFactor    = 0.0f;
+    rasterState.lineWidth               = state.getLineWidth();
+
+    // TODO(jmadill): Multisample state.
+    VkPipelineMultisampleStateCreateInfo multisampleState;
+    multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+    multisampleState.pNext = nullptr;
+    multisampleState.flags = 0;
+    multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+    multisampleState.sampleShadingEnable  = VK_FALSE;
+    multisampleState.minSampleShading     = 0.0f;
+    multisampleState.pSampleMask          = nullptr;
+    multisampleState.alphaToCoverageEnable = VK_FALSE;
+    multisampleState.alphaToOneEnable      = VK_FALSE;
+
+    // TODO(jmadill): Depth/stencil state.
+
+    // TODO(jmadill): Blend state/MRT.
+    VkPipelineColorBlendAttachmentState blendAttachmentState;
+    blendAttachmentState.blendEnable         = VK_FALSE;
+    blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
+    blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
+    blendAttachmentState.colorBlendOp        = VK_BLEND_OP_ADD;
+    blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+    blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+    blendAttachmentState.alphaBlendOp        = VK_BLEND_OP_ADD;
+    blendAttachmentState.colorWriteMask = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
+                                           VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
+
+    VkPipelineColorBlendStateCreateInfo blendState;
+    blendState.sType             = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+    blendState.pNext             = 0;
+    blendState.flags             = 0;
+    blendState.logicOpEnable     = VK_FALSE;
+    blendState.logicOp           = VK_LOGIC_OP_CLEAR;
+    blendState.attachmentCount   = 1;
+    blendState.pAttachments      = &blendAttachmentState;
+    blendState.blendConstants[0] = 0.0f;
+    blendState.blendConstants[1] = 0.0f;
+    blendState.blendConstants[2] = 0.0f;
+    blendState.blendConstants[3] = 0.0f;
+
+    // TODO(jmadill): Dynamic state.
+    vk::RenderPass *renderPass = nullptr;
+    ANGLE_TRY_RESULT(vkFBO->getRenderPass(device), renderPass);
+    ASSERT(renderPass && renderPass->valid());
+
+    vk::PipelineLayout *pipelineLayout = nullptr;
+    ANGLE_TRY_RESULT(programVk->getPipelineLayout(device), pipelineLayout);
+    ASSERT(pipelineLayout && pipelineLayout->valid());
+
+    VkGraphicsPipelineCreateInfo pipelineInfo;
+    pipelineInfo.sType               = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+    pipelineInfo.pNext               = nullptr;
+    pipelineInfo.flags               = 0;
+    pipelineInfo.stageCount          = 2;
+    pipelineInfo.pStages             = shaderStages;
+    pipelineInfo.pVertexInputState   = &vertexInputState;
+    pipelineInfo.pInputAssemblyState = &inputAssemblyState;
+    pipelineInfo.pTessellationState  = nullptr;
+    pipelineInfo.pViewportState      = &viewportState;
+    pipelineInfo.pRasterizationState = &rasterState;
+    pipelineInfo.pMultisampleState   = &multisampleState;
+    pipelineInfo.pDepthStencilState  = nullptr;
+    pipelineInfo.pColorBlendState    = &blendState;
+    pipelineInfo.pDynamicState       = nullptr;
+    pipelineInfo.layout              = pipelineLayout->getHandle();
+    pipelineInfo.renderPass          = renderPass->getHandle();
+    pipelineInfo.subpass             = 0;
+    pipelineInfo.basePipelineHandle  = VK_NULL_HANDLE;
+    pipelineInfo.basePipelineIndex   = 0;
+
+    vk::Pipeline newPipeline;
+    ANGLE_TRY(newPipeline.initGraphics(device, pipelineInfo));
+
+    mCurrentPipeline.retain(device, std::move(newPipeline));
+
+    return gl::NoError();
+}
+
+gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    if (mode != mCurrentDrawMode)
+    {
+        invalidateCurrentPipeline();
+        mCurrentDrawMode = mode;
+    }
+
+    if (!mCurrentPipeline.valid())
+    {
+        ANGLE_TRY(initPipeline());
+        ASSERT(mCurrentPipeline.valid());
+    }
+
+    VkDevice device       = mRenderer->getDevice();
+    const auto &state     = mState.getState();
+    const auto &programGL = state.getProgram();
+    const auto &vao       = state.getVertexArray();
+    const auto &attribs   = vao->getVertexAttributes();
+    const auto &bindings  = vao->getVertexBindings();
+    const auto *drawFBO   = state.getDrawFramebuffer();
+    FramebufferVk *vkFBO  = GetImplAs<FramebufferVk>(drawFBO);
+    Serial queueSerial    = mRenderer->getCurrentQueueSerial();
+
+    // Process vertex attributes
+    // TODO(jmadill): Caching with dirty bits.
+    std::vector<VkBuffer> vertexHandles;
+    std::vector<VkDeviceSize> vertexOffsets;
+
+    for (auto attribIndex : programGL->getActiveAttribLocationsMask())
+    {
+        const auto &attrib  = attribs[attribIndex];
+        const auto &binding = bindings[attrib.bindingIndex];
+        if (attrib.enabled)
+        {
+            // TODO(jmadill): Offset handling.
+            gl::Buffer *bufferGL = binding.buffer.get();
+            ASSERT(bufferGL);
+            BufferVk *bufferVk = GetImplAs<BufferVk>(bufferGL);
+            vertexHandles.push_back(bufferVk->getVkBuffer().getHandle());
+            vertexOffsets.push_back(0);
+
+            bufferVk->setQueueSerial(queueSerial);
+        }
+        else
+        {
+            UNIMPLEMENTED();
+        }
+    }
+
+    vk::CommandBuffer *commandBuffer = nullptr;
+    ANGLE_TRY(mRenderer->getStartedCommandBuffer(&commandBuffer));
+    ANGLE_TRY(vkFBO->beginRenderPass(device, commandBuffer, queueSerial, state));
+
+    commandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline);
+    commandBuffer->bindVertexBuffers(0, vertexHandles, vertexOffsets);
+    commandBuffer->draw(count, 1, first, 0);
+    commandBuffer->endRenderPass();
+
+    return gl::NoError();
+}
+
+gl::Error ContextVk::drawArraysInstanced(GLenum mode,
+                                         GLint first,
+                                         GLsizei count,
+                                         GLsizei instanceCount)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::drawElements(GLenum mode,
+                                  GLsizei count,
+                                  GLenum type,
+                                  const void *indices,
+                                  const gl::IndexRange &indexRange)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::drawElementsInstanced(GLenum mode,
+                                           GLsizei count,
+                                           GLenum type,
+                                           const void *indices,
+                                           GLsizei instances,
+                                           const gl::IndexRange &indexRange)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::drawRangeElements(GLenum mode,
+                                       GLuint start,
+                                       GLuint end,
+                                       GLsizei count,
+                                       GLenum type,
+                                       const void *indices,
+                                       const gl::IndexRange &indexRange)
+{
+    return gl::NoError();
+}
+
+VkDevice ContextVk::getDevice() const
+{
+    return mRenderer->getDevice();
+}
+
+vk::Error ContextVk::getStartedCommandBuffer(vk::CommandBuffer **commandBufferOut)
+{
+    return mRenderer->getStartedCommandBuffer(commandBufferOut);
+}
+
+vk::Error ContextVk::submitCommands(vk::CommandBuffer *commandBuffer)
+{
+    setQueueSerial(mRenderer->getCurrentQueueSerial());
+    ANGLE_TRY(mRenderer->submitCommandBuffer(commandBuffer));
+    return vk::NoError();
+}
+
+gl::Error ContextVk::drawArraysIndirect(GLenum mode, const void *indirect)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError() << "DrawArraysIndirect hasn't been implemented for vulkan backend.";
+}
+
+gl::Error ContextVk::drawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError()
+           << "DrawElementsIndirect hasn't been implemented for vulkan backend.";
+}
+
+GLenum ContextVk::getResetStatus()
+{
+    UNIMPLEMENTED();
+    return GL_NO_ERROR;
+}
+
+std::string ContextVk::getVendorString() const
+{
+    UNIMPLEMENTED();
+    return std::string();
+}
+
+std::string ContextVk::getRendererDescription() const
+{
+    return mRenderer->getRendererDescription();
+}
+
+void ContextVk::insertEventMarker(GLsizei length, const char *marker)
+{
+    UNIMPLEMENTED();
+}
+
+void ContextVk::pushGroupMarker(GLsizei length, const char *marker)
+{
+    UNIMPLEMENTED();
+}
+
+void ContextVk::popGroupMarker()
+{
+    UNIMPLEMENTED();
+}
+
+void ContextVk::syncState(const gl::State::DirtyBits &dirtyBits)
+{
+    // TODO(jmadill): Vulkan dirty bits.
+    if (dirtyBits.any())
+    {
+        invalidateCurrentPipeline();
+    }
+}
+
+GLint ContextVk::getGPUDisjoint()
+{
+    UNIMPLEMENTED();
+    return GLint();
+}
+
+GLint64 ContextVk::getTimestamp()
+{
+    UNIMPLEMENTED();
+    return GLint64();
+}
+
+void ContextVk::onMakeCurrent(const gl::ContextState & /*data*/)
+{
+}
+
+const gl::Caps &ContextVk::getNativeCaps() const
+{
+    return mRenderer->getNativeCaps();
+}
+
+const gl::TextureCapsMap &ContextVk::getNativeTextureCaps() const
+{
+    return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &ContextVk::getNativeExtensions() const
+{
+    return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &ContextVk::getNativeLimitations() const
+{
+    return mRenderer->getNativeLimitations();
+}
+
+CompilerImpl *ContextVk::createCompiler()
+{
+    return new CompilerVk();
+}
+
+ShaderImpl *ContextVk::createShader(const gl::ShaderState &state)
+{
+    return new ShaderVk(state);
+}
+
+ProgramImpl *ContextVk::createProgram(const gl::ProgramState &state)
+{
+    return new ProgramVk(state);
+}
+
+FramebufferImpl *ContextVk::createFramebuffer(const gl::FramebufferState &state)
+{
+    return FramebufferVk::CreateUserFBO(state);
+}
+
+TextureImpl *ContextVk::createTexture(const gl::TextureState &state)
+{
+    return new TextureVk(state);
+}
+
+RenderbufferImpl *ContextVk::createRenderbuffer()
+{
+    return new RenderbufferVk();
+}
+
+BufferImpl *ContextVk::createBuffer(const gl::BufferState &state)
+{
+    return new BufferVk(state);
+}
+
+VertexArrayImpl *ContextVk::createVertexArray(const gl::VertexArrayState &state)
+{
+    return new VertexArrayVk(state);
+}
+
+QueryImpl *ContextVk::createQuery(GLenum type)
+{
+    return new QueryVk(type);
+}
+
+FenceNVImpl *ContextVk::createFenceNV()
+{
+    return new FenceNVVk();
+}
+
+FenceSyncImpl *ContextVk::createFenceSync()
+{
+    return new FenceSyncVk();
+}
+
+TransformFeedbackImpl *ContextVk::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+    return new TransformFeedbackVk(state);
+}
+
+SamplerImpl *ContextVk::createSampler()
+{
+    return new SamplerVk();
+}
+
+std::vector<PathImpl *> ContextVk::createPaths(GLsizei)
+{
+    return std::vector<PathImpl *>();
+}
+
+// TODO(jmadill): Use pipeline cache.
+void ContextVk::invalidateCurrentPipeline()
+{
+    mRenderer->enqueueGarbageOrDeleteNow(*this, mCurrentPipeline);
+}
+
+gl::Error ContextVk::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.h
new file mode 100644
index 0000000..07d0810
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.h
@@ -0,0 +1,146 @@
+//
+// Copyright 2016 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.
+//
+// ContextVk.h:
+//    Defines the class interface for ContextVk, implementing ContextImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
+#define LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
+
+#include <vulkan/vulkan.h>
+
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/vulkan/renderervk_utils.h"
+
+namespace rx
+{
+class RendererVk;
+
+class ContextVk : public ContextImpl, public ResourceVk
+{
+  public:
+    ContextVk(const gl::ContextState &state, RendererVk *renderer);
+    ~ContextVk() override;
+
+    gl::Error initialize() override;
+
+    // Flush and finish.
+    gl::Error flush() override;
+    gl::Error finish() override;
+
+    // Drawing methods.
+    gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+    gl::Error drawArraysInstanced(GLenum mode,
+                                  GLint first,
+                                  GLsizei count,
+                                  GLsizei instanceCount) override;
+
+    gl::Error drawElements(GLenum mode,
+                           GLsizei count,
+                           GLenum type,
+                           const void *indices,
+                           const gl::IndexRange &indexRange) override;
+    gl::Error drawElementsInstanced(GLenum mode,
+                                    GLsizei count,
+                                    GLenum type,
+                                    const void *indices,
+                                    GLsizei instances,
+                                    const gl::IndexRange &indexRange) override;
+    gl::Error drawRangeElements(GLenum mode,
+                                GLuint start,
+                                GLuint end,
+                                GLsizei count,
+                                GLenum type,
+                                const void *indices,
+                                const gl::IndexRange &indexRange) override;
+    gl::Error drawArraysIndirect(GLenum mode, const void *indirect) override;
+    gl::Error drawElementsIndirect(GLenum mode, GLenum type, const void *indirect) override;
+
+    // Device loss
+    GLenum getResetStatus() override;
+
+    // Vendor and description strings.
+    std::string getVendorString() const override;
+    std::string getRendererDescription() const override;
+
+    // Debug markers.
+    void insertEventMarker(GLsizei length, const char *marker) override;
+    void pushGroupMarker(GLsizei length, const char *marker) override;
+    void popGroupMarker() override;
+
+    // State sync with dirty bits.
+    void syncState(const gl::State::DirtyBits &dirtyBits) override;
+
+    // Disjoint timer queries
+    GLint getGPUDisjoint() override;
+    GLint64 getTimestamp() override;
+
+    // Context switching
+    void onMakeCurrent(const gl::ContextState &data) override;
+
+    // Native capabilities, unmodified by gl::Context.
+    const gl::Caps &getNativeCaps() const override;
+    const gl::TextureCapsMap &getNativeTextureCaps() const override;
+    const gl::Extensions &getNativeExtensions() const override;
+    const gl::Limitations &getNativeLimitations() const override;
+
+    // Shader creation
+    CompilerImpl *createCompiler() override;
+    ShaderImpl *createShader(const gl::ShaderState &state) override;
+    ProgramImpl *createProgram(const gl::ProgramState &state) override;
+
+    // Framebuffer creation
+    FramebufferImpl *createFramebuffer(const gl::FramebufferState &state) override;
+
+    // Texture creation
+    TextureImpl *createTexture(const gl::TextureState &state) override;
+
+    // Renderbuffer creation
+    RenderbufferImpl *createRenderbuffer() override;
+
+    // Buffer creation
+    BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+    // Vertex Array creation
+    VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override;
+
+    // Query and Fence creation
+    QueryImpl *createQuery(GLenum type) override;
+    FenceNVImpl *createFenceNV() override;
+    FenceSyncImpl *createFenceSync() override;
+
+    // Transform Feedback creation
+    TransformFeedbackImpl *createTransformFeedback(
+        const gl::TransformFeedbackState &state) override;
+
+    // Sampler object creation
+    SamplerImpl *createSampler() override;
+
+    // Path object creation
+    std::vector<PathImpl *> createPaths(GLsizei) override;
+
+    VkDevice getDevice() const;
+    vk::Error getStartedCommandBuffer(vk::CommandBuffer **commandBufferOut);
+    vk::Error submitCommands(vk::CommandBuffer *commandBuffer);
+
+    RendererVk *getRenderer() { return mRenderer; }
+
+    // TODO(jmadill): Use pipeline cache.
+    void invalidateCurrentPipeline();
+
+    gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
+
+  private:
+    gl::Error initPipeline();
+
+    RendererVk *mRenderer;
+    vk::Pipeline mCurrentPipeline;
+    GLenum mCurrentDrawMode;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/DeviceVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/DeviceVk.cpp
new file mode 100644
index 0000000..f4f60b9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/DeviceVk.cpp
@@ -0,0 +1,48 @@
+//
+// Copyright 2016 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.
+//
+// DeviceVk.cpp:
+//    Implements the class methods for DeviceVk.
+//
+
+#include "libANGLE/renderer/vulkan/DeviceVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+DeviceVk::DeviceVk() : DeviceImpl()
+{
+}
+
+DeviceVk::~DeviceVk()
+{
+}
+
+egl::Error DeviceVk::getDevice(void **outValue)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+EGLint DeviceVk::getType()
+{
+    UNIMPLEMENTED();
+    return EGLint();
+}
+
+void DeviceVk::generateExtensions(egl::DeviceExtensions *outExtensions) const
+{
+    UNIMPLEMENTED();
+}
+
+bool DeviceVk::deviceExternallySourced()
+{
+    UNIMPLEMENTED();
+    return bool();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/DeviceVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/DeviceVk.h
new file mode 100644
index 0000000..4613c17
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/DeviceVk.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2016 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.
+//
+// DeviceVk.h:
+//    Defines the class interface for DeviceVk, implementing DeviceImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_DEVICEVK_H_
+#define LIBANGLE_RENDERER_VULKAN_DEVICEVK_H_
+
+#include "libANGLE/renderer/DeviceImpl.h"
+
+namespace rx
+{
+
+class DeviceVk : public DeviceImpl
+{
+  public:
+    DeviceVk();
+    ~DeviceVk() override;
+
+    egl::Error getDevice(void **outValue) override;
+    EGLint getType() override;
+    void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
+    bool deviceExternallySourced() override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_DEVICEVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp
new file mode 100644
index 0000000..eccc78e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp
@@ -0,0 +1,211 @@
+//
+// Copyright 2016 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.
+//
+// DisplayVk.cpp:
+//    Implements the class methods for DisplayVk.
+//
+
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
+
+#include "common/debug.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/SurfaceVk.h"
+
+namespace rx
+{
+
+DisplayVk::DisplayVk(const egl::DisplayState &state) : DisplayImpl(state), mRenderer(nullptr)
+{
+}
+
+DisplayVk::~DisplayVk()
+{
+}
+
+egl::Error DisplayVk::initialize(egl::Display *display)
+{
+    ASSERT(!mRenderer && display != nullptr);
+    mRenderer.reset(new RendererVk());
+    return mRenderer->initialize(display->getAttributeMap(), getWSIName())
+        .toEGL(EGL_NOT_INITIALIZED);
+}
+
+void DisplayVk::terminate()
+{
+    mRenderer.reset(nullptr);
+}
+
+egl::Error DisplayVk::makeCurrent(egl::Surface * /*drawSurface*/,
+                                  egl::Surface * /*readSurface*/,
+                                  gl::Context * /*context*/)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::ConfigSet DisplayVk::generateConfigs()
+{
+    // TODO(jmadill): Multiple configs, pbuffers, and proper checking of config attribs.
+    egl::Config singleton;
+    singleton.renderTargetFormat    = GL_RGBA8;
+    singleton.depthStencilFormat    = GL_NONE;
+    singleton.bufferSize            = 32;
+    singleton.redSize               = 8;
+    singleton.greenSize             = 8;
+    singleton.blueSize              = 8;
+    singleton.alphaSize             = 8;
+    singleton.alphaMaskSize         = 0;
+    singleton.bindToTextureRGB      = EGL_FALSE;
+    singleton.bindToTextureRGBA     = EGL_FALSE;
+    singleton.colorBufferType       = EGL_RGB_BUFFER;
+    singleton.configCaveat          = EGL_NONE;
+    singleton.conformant            = 0;
+    singleton.depthSize             = 0;
+    singleton.stencilSize           = 0;
+    singleton.level                 = 0;
+    singleton.matchNativePixmap     = EGL_NONE;
+    singleton.maxPBufferWidth       = 0;
+    singleton.maxPBufferHeight      = 0;
+    singleton.maxPBufferPixels      = 0;
+    singleton.maxSwapInterval       = 1;
+    singleton.minSwapInterval       = 1;
+    singleton.nativeRenderable      = EGL_TRUE;
+    singleton.nativeVisualID        = 0;
+    singleton.nativeVisualType      = EGL_NONE;
+    singleton.renderableType        = EGL_OPENGL_ES2_BIT;
+    singleton.sampleBuffers         = 0;
+    singleton.samples               = 0;
+    singleton.surfaceType           = EGL_WINDOW_BIT;
+    singleton.optimalOrientation    = 0;
+    singleton.transparentType       = EGL_NONE;
+    singleton.transparentRedValue   = 0;
+    singleton.transparentGreenValue = 0;
+    singleton.transparentBlueValue  = 0;
+    singleton.colorComponentType    = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+
+    egl::ConfigSet configSet;
+    configSet.add(singleton);
+    return configSet;
+}
+
+bool DisplayVk::testDeviceLost()
+{
+    // TODO(jmadill): Figure out how to do device lost in Vulkan.
+    return false;
+}
+
+egl::Error DisplayVk::restoreLostDevice()
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+std::string DisplayVk::getVendorString() const
+{
+    std::string vendorString = "Google Inc.";
+    if (mRenderer)
+    {
+        vendorString += " " + mRenderer->getVendorString();
+    }
+
+    return vendorString;
+}
+
+egl::Error DisplayVk::getDevice(DeviceImpl **device)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayVk::waitClient() const
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error DisplayVk::waitNative(EGLint engine,
+                                 egl::Surface *drawSurface,
+                                 egl::Surface *readSurface) const
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+SurfaceImpl *DisplayVk::createWindowSurface(const egl::SurfaceState &state,
+                                            EGLNativeWindowType window,
+                                            const egl::AttributeMap &attribs)
+{
+    EGLint width  = attribs.getAsInt(EGL_WIDTH, 0);
+    EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
+
+    return createWindowSurfaceVk(state, window, width, height);
+}
+
+SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
+                                             const egl::AttributeMap &attribs)
+{
+    ASSERT(mRenderer);
+
+    EGLint width  = attribs.getAsInt(EGL_WIDTH, 0);
+    EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
+
+    return new OffscreenSurfaceVk(state, width, height);
+}
+
+SurfaceImpl *DisplayVk::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                                      EGLenum buftype,
+                                                      EGLClientBuffer clientBuffer,
+                                                      const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return static_cast<SurfaceImpl *>(0);
+}
+
+SurfaceImpl *DisplayVk::createPixmapSurface(const egl::SurfaceState &state,
+                                            NativePixmapType nativePixmap,
+                                            const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return static_cast<SurfaceImpl *>(0);
+}
+
+ImageImpl *DisplayVk::createImage(const egl::ImageState &state,
+                                  EGLenum target,
+                                  const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return static_cast<ImageImpl *>(0);
+}
+
+ContextImpl *DisplayVk::createContext(const gl::ContextState &state)
+{
+    return new ContextVk(state, mRenderer.get());
+}
+
+StreamProducerImpl *DisplayVk::createStreamProducerD3DTextureNV12(
+    egl::Stream::ConsumerType consumerType,
+    const egl::AttributeMap &attribs)
+{
+    UNIMPLEMENTED();
+    return static_cast<StreamProducerImpl *>(0);
+}
+
+gl::Version DisplayVk::getMaxSupportedESVersion() const
+{
+    UNIMPLEMENTED();
+    return gl::Version(0, 0);
+}
+
+void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+}
+
+void DisplayVk::generateCaps(egl::Caps *outCaps) const
+{
+    outCaps->textureNPOT = true;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.h
new file mode 100644
index 0000000..f514efd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.h
@@ -0,0 +1,87 @@
+//
+// Copyright 2016 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.
+//
+// DisplayVk.h:
+//    Defines the class interface for DisplayVk, implementing DisplayImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
+#define LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+namespace rx
+{
+class RendererVk;
+
+class DisplayVk : public DisplayImpl
+{
+  public:
+    DisplayVk(const egl::DisplayState &state);
+    ~DisplayVk() override;
+
+    egl::Error initialize(egl::Display *display) override;
+    void terminate() override;
+
+    egl::Error makeCurrent(egl::Surface *drawSurface,
+                           egl::Surface *readSurface,
+                           gl::Context *context) override;
+
+    egl::ConfigSet generateConfigs() override;
+
+    bool testDeviceLost() override;
+    egl::Error restoreLostDevice() override;
+
+    std::string getVendorString() const override;
+
+    egl::Error getDevice(DeviceImpl **device) override;
+
+    egl::Error waitClient() const override;
+    egl::Error waitNative(EGLint engine,
+                          egl::Surface *drawSurface,
+                          egl::Surface *readSurface) const override;
+
+    SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+                                     EGLNativeWindowType window,
+                                     const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+                                      const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+                                               EGLenum buftype,
+                                               EGLClientBuffer clientBuffer,
+                                               const egl::AttributeMap &attribs) override;
+    SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+                                     NativePixmapType nativePixmap,
+                                     const egl::AttributeMap &attribs) override;
+
+    ImageImpl *createImage(const egl::ImageState &state,
+                           EGLenum target,
+                           const egl::AttributeMap &attribs) override;
+
+    ContextImpl *createContext(const gl::ContextState &state) override;
+
+    StreamProducerImpl *createStreamProducerD3DTextureNV12(
+        egl::Stream::ConsumerType consumerType,
+        const egl::AttributeMap &attribs) override;
+    gl::Version getMaxSupportedESVersion() const override;
+
+    RendererVk *getRenderer() const { return mRenderer.get(); }
+
+    virtual const char *getWSIName() const = 0;
+
+  private:
+    virtual SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
+                                               EGLNativeWindowType window,
+                                               EGLint width,
+                                               EGLint height) = 0;
+    void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+    void generateCaps(egl::Caps *outCaps) const override;
+
+    std::unique_ptr<RendererVk> mRenderer;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceNVVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceNVVk.cpp
new file mode 100644
index 0000000..c46bd01
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceNVVk.cpp
@@ -0,0 +1,43 @@
+//
+// Copyright 2016 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.
+//
+// FenceNVVk.cpp:
+//    Implements the class methods for FenceNVVk.
+//
+
+#include "libANGLE/renderer/vulkan/FenceNVVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FenceNVVk::FenceNVVk() : FenceNVImpl()
+{
+}
+
+FenceNVVk::~FenceNVVk()
+{
+}
+
+gl::Error FenceNVVk::set(GLenum condition)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceNVVk::test(GLboolean *outFinished)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceNVVk::finish()
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceNVVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceNVVk.h
new file mode 100644
index 0000000..be05471
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceNVVk.h
@@ -0,0 +1,31 @@
+//
+// Copyright 2016 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.
+//
+// FenceNVVk.h:
+//    Defines the class interface for FenceNVVk, implementing FenceNVImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FENCENVVK_H_
+#define LIBANGLE_RENDERER_VULKAN_FENCENVVK_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+
+namespace rx
+{
+
+class FenceNVVk : public FenceNVImpl
+{
+  public:
+    FenceNVVk();
+    ~FenceNVVk() override;
+
+    gl::Error set(GLenum condition) override;
+    gl::Error test(GLboolean *outFinished) override;
+    gl::Error finish() override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_FENCENVVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.cpp
new file mode 100644
index 0000000..d27f130
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.cpp
@@ -0,0 +1,49 @@
+//
+// Copyright 2016 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.
+//
+// FenceSyncVk.cpp:
+//    Implements the class methods for FenceSyncVk.
+//
+
+#include "libANGLE/renderer/vulkan/FenceSyncVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FenceSyncVk::FenceSyncVk() : FenceSyncImpl()
+{
+}
+
+FenceSyncVk::~FenceSyncVk()
+{
+}
+
+gl::Error FenceSyncVk::set(GLenum condition, GLbitfield flags)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceSyncVk::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceSyncVk::serverWait(GLbitfield flags, GLuint64 timeout)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceSyncVk::getStatus(GLint *outResult)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.h
new file mode 100644
index 0000000..ab9a107
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2016 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.
+//
+// FenceSyncVk.h:
+//    Defines the class interface for FenceSyncVk, implementing FenceSyncImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_
+#define LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_
+
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace rx
+{
+
+class FenceSyncVk : public FenceSyncImpl
+{
+  public:
+    FenceSyncVk();
+    ~FenceSyncVk() override;
+
+    gl::Error set(GLenum condition, GLbitfield flags) override;
+    gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override;
+    gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override;
+    gl::Error getStatus(GLint *outResult) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
new file mode 100644
index 0000000..84b8907
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -0,0 +1,598 @@
+//
+// Copyright 2016 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.
+//
+// FramebufferVk.cpp:
+//    Implements the class methods for FramebufferVk.
+//
+
+#include "libANGLE/renderer/vulkan/FramebufferVk.h"
+
+#include <vulkan/vulkan.h>
+#include <array>
+
+#include "common/debug.h"
+#include "image_util/imageformats.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
+#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/SurfaceVk.h"
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+
+namespace rx
+{
+
+namespace
+{
+
+gl::ErrorOrResult<const gl::InternalFormat *> GetReadAttachmentInfo(
+    const gl::FramebufferAttachment *readAttachment)
+{
+    RenderTargetVk *renderTarget = nullptr;
+    ANGLE_TRY(readAttachment->getRenderTarget(&renderTarget));
+
+    GLenum implFormat = renderTarget->format->format().fboImplementationInternalFormat;
+    return &gl::GetSizedInternalFormatInfo(implFormat);
+}
+
+VkSampleCountFlagBits ConvertSamples(GLint sampleCount)
+{
+    switch (sampleCount)
+    {
+        case 0:
+        case 1:
+            return VK_SAMPLE_COUNT_1_BIT;
+        case 2:
+            return VK_SAMPLE_COUNT_2_BIT;
+        case 4:
+            return VK_SAMPLE_COUNT_4_BIT;
+        case 8:
+            return VK_SAMPLE_COUNT_8_BIT;
+        case 16:
+            return VK_SAMPLE_COUNT_16_BIT;
+        case 32:
+            return VK_SAMPLE_COUNT_32_BIT;
+        default:
+            UNREACHABLE();
+            return VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
+    }
+}
+
+}  // anonymous namespace
+
+// static
+FramebufferVk *FramebufferVk::CreateUserFBO(const gl::FramebufferState &state)
+{
+    return new FramebufferVk(state);
+}
+
+// static
+FramebufferVk *FramebufferVk::CreateDefaultFBO(const gl::FramebufferState &state,
+                                               WindowSurfaceVk *backbuffer)
+{
+    return new FramebufferVk(state, backbuffer);
+}
+
+FramebufferVk::FramebufferVk(const gl::FramebufferState &state)
+    : FramebufferImpl(state), mBackbuffer(nullptr), mRenderPass(), mFramebuffer()
+{
+}
+
+FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer)
+    : FramebufferImpl(state), mBackbuffer(backbuffer), mRenderPass(), mFramebuffer()
+{
+}
+
+FramebufferVk::~FramebufferVk()
+{
+}
+
+void FramebufferVk::destroy(ContextImpl *contextImpl)
+{
+    VkDevice device = GetAs<ContextVk>(contextImpl)->getDevice();
+
+    mRenderPass.destroy(device);
+    mFramebuffer.destroy(device);
+}
+
+void FramebufferVk::destroyDefault(DisplayImpl *displayImpl)
+{
+    VkDevice device = GetAs<DisplayVk>(displayImpl)->getRenderer()->getDevice();
+
+    mRenderPass.destroy(device);
+    mFramebuffer.destroy(device);
+}
+
+gl::Error FramebufferVk::discard(size_t count, const GLenum *attachments)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::invalidate(size_t count, const GLenum *attachments)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::invalidateSub(size_t count,
+                                       const GLenum *attachments,
+                                       const gl::Rectangle &area)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::clear(ContextImpl *context, GLbitfield mask)
+{
+    ContextVk *contextVk = GetAs<ContextVk>(context);
+
+    if (mState.getDepthAttachment() && (mask & GL_DEPTH_BUFFER_BIT) != 0)
+    {
+        // TODO(jmadill): Depth clear
+        UNIMPLEMENTED();
+    }
+
+    if (mState.getStencilAttachment() && (mask & GL_STENCIL_BUFFER_BIT) != 0)
+    {
+        // TODO(jmadill): Stencil clear
+        UNIMPLEMENTED();
+    }
+
+    if ((mask & GL_COLOR_BUFFER_BIT) == 0)
+    {
+        return gl::NoError();
+    }
+
+    const auto &glState    = context->getGLState();
+    const auto &clearColor = glState.getColorClearValue();
+    VkClearColorValue clearColorValue;
+    clearColorValue.float32[0] = clearColor.red;
+    clearColorValue.float32[1] = clearColor.green;
+    clearColorValue.float32[2] = clearColor.blue;
+    clearColorValue.float32[3] = clearColor.alpha;
+
+    // TODO(jmadill): Scissored clears.
+    const auto *attachment = mState.getFirstNonNullAttachment();
+    ASSERT(attachment && attachment->isAttached());
+    const auto &size = attachment->getSize();
+    const gl::Rectangle renderArea(0, 0, size.width, size.height);
+
+    vk::CommandBuffer *commandBuffer = nullptr;
+    ANGLE_TRY(contextVk->getStartedCommandBuffer(&commandBuffer));
+
+    for (const auto &colorAttachment : mState.getColorAttachments())
+    {
+        if (colorAttachment.isAttached())
+        {
+            RenderTargetVk *renderTarget = nullptr;
+            ANGLE_TRY(colorAttachment.getRenderTarget(&renderTarget));
+            renderTarget->image->changeLayoutTop(
+                VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, commandBuffer);
+            commandBuffer->clearSingleColorImage(*renderTarget->image, clearColorValue);
+        }
+    }
+
+    return gl::NoError();
+}
+
+gl::Error FramebufferVk::clearBufferfv(ContextImpl *context,
+                                       GLenum buffer,
+                                       GLint drawbuffer,
+                                       const GLfloat *values)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::clearBufferuiv(ContextImpl *context,
+                                        GLenum buffer,
+                                        GLint drawbuffer,
+                                        const GLuint *values)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::clearBufferiv(ContextImpl *context,
+                                       GLenum buffer,
+                                       GLint drawbuffer,
+                                       const GLint *values)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::clearBufferfi(ContextImpl *context,
+                                       GLenum buffer,
+                                       GLint drawbuffer,
+                                       GLfloat depth,
+                                       GLint stencil)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+GLenum FramebufferVk::getImplementationColorReadFormat() const
+{
+    auto errOrResult = GetReadAttachmentInfo(mState.getReadAttachment());
+
+    // TODO(jmadill): Handle getRenderTarget error.
+    if (errOrResult.isError())
+    {
+        ERR() << "Internal error in FramebufferVk::getImplementationColorReadFormat.";
+        return GL_NONE;
+    }
+
+    return errOrResult.getResult()->format;
+}
+
+GLenum FramebufferVk::getImplementationColorReadType() const
+{
+    auto errOrResult = GetReadAttachmentInfo(mState.getReadAttachment());
+
+    // TODO(jmadill): Handle getRenderTarget error.
+    if (errOrResult.isError())
+    {
+        ERR() << "Internal error in FramebufferVk::getImplementationColorReadFormat.";
+        return GL_NONE;
+    }
+
+    return errOrResult.getResult()->type;
+}
+
+gl::Error FramebufferVk::readPixels(ContextImpl *context,
+                                    const gl::Rectangle &area,
+                                    GLenum format,
+                                    GLenum type,
+                                    void *pixels) const
+{
+    const auto &glState         = context->getGLState();
+    const auto *readFramebuffer = glState.getReadFramebuffer();
+    const auto *readAttachment  = readFramebuffer->getReadColorbuffer();
+
+    RenderTargetVk *renderTarget = nullptr;
+    ANGLE_TRY(readAttachment->getRenderTarget(&renderTarget));
+
+    ContextVk *contextVk = GetAs<ContextVk>(context);
+    RendererVk *renderer = contextVk->getRenderer();
+    VkDevice device      = renderer->getDevice();
+
+    vk::Image *readImage = renderTarget->image;
+    vk::StagingImage stagingImage;
+    ANGLE_TRY(renderer->createStagingImage(TextureDimension::TEX_2D, *renderTarget->format,
+                                           renderTarget->extents, &stagingImage));
+
+    vk::CommandBuffer *commandBuffer = nullptr;
+    ANGLE_TRY(contextVk->getStartedCommandBuffer(&commandBuffer));
+
+    stagingImage.getImage().changeLayoutTop(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL,
+                                            commandBuffer);
+
+    gl::Box copyRegion;
+    copyRegion.x      = area.x;
+    copyRegion.y      = area.y;
+    copyRegion.z      = 0;
+    copyRegion.width  = area.width;
+    copyRegion.height = area.height;
+    copyRegion.depth  = 1;
+
+    readImage->changeLayoutTop(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                               commandBuffer);
+    commandBuffer->copySingleImage(*readImage, stagingImage.getImage(), copyRegion,
+                                   VK_IMAGE_ASPECT_COLOR_BIT);
+
+    ANGLE_TRY(renderer->submitAndFinishCommandBuffer(commandBuffer));
+
+    // TODO(jmadill): parameters
+    uint8_t *mapPointer = nullptr;
+    ANGLE_TRY(
+        stagingImage.getDeviceMemory().map(device, 0, stagingImage.getSize(), 0, &mapPointer));
+
+    const auto &angleFormat = renderTarget->format->format();
+
+    // TODO(jmadill): Use pixel bytes from the ANGLE format directly.
+    const auto &glFormat = gl::GetSizedInternalFormatInfo(angleFormat.glInternalFormat);
+    int inputPitch       = glFormat.pixelBytes * area.width;
+
+    PackPixelsParams params;
+    params.area        = area;
+    params.format      = format;
+    params.type        = type;
+    params.outputPitch = inputPitch;
+    params.pack        = glState.getPackState();
+
+    PackPixels(params, angleFormat, inputPitch, mapPointer, reinterpret_cast<uint8_t *>(pixels));
+
+    stagingImage.getDeviceMemory().unmap(device);
+    renderer->enqueueGarbage(renderer->getCurrentQueueSerial(), std::move(stagingImage));
+
+    stagingImage.getImage().destroy(renderer->getDevice());
+
+    stagingImage.destroy(device);
+
+    return vk::NoError();
+}
+
+gl::Error FramebufferVk::blit(ContextImpl *context,
+                              const gl::Rectangle &sourceArea,
+                              const gl::Rectangle &destArea,
+                              GLbitfield mask,
+                              GLenum filter)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+bool FramebufferVk::checkStatus() const
+{
+    UNIMPLEMENTED();
+    return bool();
+}
+
+void FramebufferVk::syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+    auto contextVk = GetAs<ContextVk>(contextImpl);
+
+    ASSERT(dirtyBits.any());
+
+    // TODO(jmadill): Smarter update.
+    mRenderPass.destroy(contextVk->getDevice());
+    mFramebuffer.destroy(contextVk->getDevice());
+
+    // TODO(jmadill): Use pipeline cache.
+    contextVk->invalidateCurrentPipeline();
+}
+
+gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(VkDevice device)
+{
+    if (mRenderPass.valid())
+    {
+        return &mRenderPass;
+    }
+
+    // TODO(jmadill): Can we use stack-only memory?
+    std::vector<VkAttachmentDescription> attachmentDescs;
+    std::vector<VkAttachmentReference> colorAttachmentRefs;
+
+    const auto &colorAttachments = mState.getColorAttachments();
+    for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
+    {
+        const auto &colorAttachment = colorAttachments[attachmentIndex];
+        if (colorAttachment.isAttached())
+        {
+            VkAttachmentDescription colorDesc;
+            VkAttachmentReference colorRef;
+
+            RenderTargetVk *renderTarget = nullptr;
+            ANGLE_TRY(colorAttachment.getRenderTarget(&renderTarget));
+
+            // TODO(jmadill): We would only need this flag for duplicated attachments.
+            colorDesc.flags   = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
+            colorDesc.format  = renderTarget->format->native;
+            colorDesc.samples = ConvertSamples(colorAttachment.getSamples());
+
+            // The load op controls the prior existing depth/color attachment data.
+            // TODO(jmadill): Proper load ops. Should not be hard coded to clear.
+            colorDesc.loadOp         = VK_ATTACHMENT_LOAD_OP_CLEAR;
+            colorDesc.storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
+            colorDesc.stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            colorDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            colorDesc.initialLayout  = VK_IMAGE_LAYOUT_UNDEFINED;
+
+            // We might want to transition directly to PRESENT_SRC for Surface attachments.
+            colorDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            colorRef.attachment = static_cast<uint32_t>(colorAttachments.size()) - 1u;
+            colorRef.layout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            attachmentDescs.push_back(colorDesc);
+            colorAttachmentRefs.push_back(colorRef);
+        }
+    }
+
+    const auto *depthStencilAttachment = mState.getDepthStencilAttachment();
+    VkAttachmentReference depthStencilAttachmentRef;
+    bool useDepth = depthStencilAttachment && depthStencilAttachment->isAttached();
+
+    if (useDepth)
+    {
+        VkAttachmentDescription depthStencilDesc;
+
+        RenderTargetVk *renderTarget = nullptr;
+        ANGLE_TRY(depthStencilAttachment->getRenderTarget(&renderTarget));
+
+        depthStencilDesc.flags          = 0;
+        depthStencilDesc.format         = renderTarget->format->native;
+        depthStencilDesc.samples        = ConvertSamples(depthStencilAttachment->getSamples());
+        depthStencilDesc.loadOp         = VK_ATTACHMENT_LOAD_OP_CLEAR;
+        depthStencilDesc.storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
+        depthStencilDesc.stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+        depthStencilDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        depthStencilDesc.initialLayout  = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+        depthStencilDesc.finalLayout    = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+        depthStencilAttachmentRef.attachment = static_cast<uint32_t>(attachmentDescs.size());
+        depthStencilAttachmentRef.layout     = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+        attachmentDescs.push_back(depthStencilDesc);
+    }
+
+    ASSERT(!attachmentDescs.empty());
+
+    VkSubpassDescription subpassDesc;
+
+    subpassDesc.flags                   = 0;
+    subpassDesc.pipelineBindPoint       = VK_PIPELINE_BIND_POINT_GRAPHICS;
+    subpassDesc.inputAttachmentCount    = 0;
+    subpassDesc.pInputAttachments       = nullptr;
+    subpassDesc.colorAttachmentCount    = static_cast<uint32_t>(colorAttachmentRefs.size());
+    subpassDesc.pColorAttachments       = colorAttachmentRefs.data();
+    subpassDesc.pResolveAttachments     = nullptr;
+    subpassDesc.pDepthStencilAttachment = (useDepth ? &depthStencilAttachmentRef : nullptr);
+    subpassDesc.preserveAttachmentCount = 0;
+    subpassDesc.pPreserveAttachments    = nullptr;
+
+    VkRenderPassCreateInfo renderPassInfo;
+
+    renderPassInfo.sType           = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+    renderPassInfo.pNext           = nullptr;
+    renderPassInfo.flags           = 0;
+    renderPassInfo.attachmentCount = static_cast<uint32_t>(attachmentDescs.size());
+    renderPassInfo.pAttachments    = attachmentDescs.data();
+    renderPassInfo.subpassCount    = 1;
+    renderPassInfo.pSubpasses      = &subpassDesc;
+    renderPassInfo.dependencyCount = 0;
+    renderPassInfo.pDependencies   = nullptr;
+
+    vk::RenderPass renderPass;
+    ANGLE_TRY(renderPass.init(device, renderPassInfo));
+
+    mRenderPass.retain(device, std::move(renderPass));
+
+    return &mRenderPass;
+}
+
+gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(VkDevice device)
+{
+    // If we've already created our cached Framebuffer, return it.
+    if (mFramebuffer.valid())
+    {
+        return &mFramebuffer;
+    }
+
+    vk::RenderPass *renderPass = nullptr;
+    ANGLE_TRY_RESULT(getRenderPass(device), renderPass);
+
+    // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
+    if (mBackbuffer)
+    {
+        return mBackbuffer->getCurrentFramebuffer(device, *renderPass);
+    }
+
+    // Gather VkImageViews over all FBO attachments, also size of attached region.
+    std::vector<VkImageView> attachments;
+    gl::Extents attachmentsSize;
+
+    const auto &colorAttachments = mState.getColorAttachments();
+    for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
+    {
+        const auto &colorAttachment = colorAttachments[attachmentIndex];
+        if (colorAttachment.isAttached())
+        {
+            RenderTargetVk *renderTarget = nullptr;
+            ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(&renderTarget));
+            attachments.push_back(renderTarget->imageView->getHandle());
+
+            ASSERT(attachmentsSize.empty() || attachmentsSize == colorAttachment.getSize());
+            attachmentsSize = colorAttachment.getSize();
+        }
+    }
+
+    const auto *depthStencilAttachment = mState.getDepthStencilAttachment();
+    if (depthStencilAttachment && depthStencilAttachment->isAttached())
+    {
+        RenderTargetVk *renderTarget = nullptr;
+        ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(&renderTarget));
+        attachments.push_back(renderTarget->imageView->getHandle());
+
+        ASSERT(attachmentsSize.empty() || attachmentsSize == depthStencilAttachment->getSize());
+        attachmentsSize = depthStencilAttachment->getSize();
+    }
+
+    ASSERT(!attachments.empty());
+
+    VkFramebufferCreateInfo framebufferInfo;
+
+    framebufferInfo.sType           = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+    framebufferInfo.pNext           = nullptr;
+    framebufferInfo.flags           = 0;
+    framebufferInfo.renderPass      = mRenderPass.getHandle();
+    framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
+    framebufferInfo.pAttachments    = attachments.data();
+    framebufferInfo.width           = static_cast<uint32_t>(attachmentsSize.width);
+    framebufferInfo.height          = static_cast<uint32_t>(attachmentsSize.height);
+    framebufferInfo.layers          = 1;
+
+    vk::Framebuffer framebuffer;
+    ANGLE_TRY(static_cast<gl::Error>(framebuffer.init(device, framebufferInfo)));
+
+    mFramebuffer.retain(device, std::move(framebuffer));
+
+    return &mFramebuffer;
+}
+
+gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const
+{
+    UNIMPLEMENTED();
+    return gl::InternalError() << "getSamplePosition is unimplemented.";
+}
+
+gl::Error FramebufferVk::beginRenderPass(VkDevice device,
+                                         vk::CommandBuffer *commandBuffer,
+                                         Serial queueSerial,
+                                         const gl::State &glState)
+{
+    // TODO(jmadill): Cache render targets.
+    for (const auto &colorAttachment : mState.getColorAttachments())
+    {
+        if (colorAttachment.isAttached())
+        {
+            RenderTargetVk *renderTarget = nullptr;
+            ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(&renderTarget));
+            renderTarget->resource->setQueueSerial(queueSerial);
+        }
+    }
+
+    const auto *depthStencilAttachment = mState.getDepthStencilAttachment();
+    if (depthStencilAttachment && depthStencilAttachment->isAttached())
+    {
+        RenderTargetVk *renderTarget = nullptr;
+        ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(&renderTarget));
+        renderTarget->resource->setQueueSerial(queueSerial);
+    }
+
+    vk::Framebuffer *framebuffer = nullptr;
+    ANGLE_TRY_RESULT(getFramebuffer(device), framebuffer);
+    ASSERT(framebuffer && framebuffer->valid());
+
+    vk::RenderPass *renderPass = nullptr;
+    ANGLE_TRY_RESULT(getRenderPass(device), renderPass);
+    ASSERT(renderPass && renderPass->valid());
+
+    // TODO(jmadill): Proper clear value implementation.
+    VkClearColorValue colorClear;
+    memset(&colorClear, 0, sizeof(VkClearColorValue));
+    colorClear.float32[0] = glState.getColorClearValue().red;
+    colorClear.float32[1] = glState.getColorClearValue().green;
+    colorClear.float32[2] = glState.getColorClearValue().blue;
+    colorClear.float32[3] = glState.getColorClearValue().alpha;
+
+    std::vector<VkClearValue> attachmentClearValues;
+    attachmentClearValues.push_back({colorClear});
+
+    // Updated the cached image layout of the attachments in this FBO.
+    // For a default FBO, we need to call through to the WindowSurfaceVk
+    // TODO(jmadill): Iterate over all attachments.
+    ASSERT(mBackbuffer);
+    RenderTargetVk *renderTarget = nullptr;
+    ANGLE_TRY(mState.getFirstColorAttachment()->getRenderTarget(&renderTarget));
+    renderTarget->image->updateLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+
+    commandBuffer->beginRenderPass(*renderPass, *framebuffer, glState.getViewport(),
+                                   attachmentClearValues);
+
+    setQueueSerial(queueSerial);
+    if (mBackbuffer)
+    {
+        mBackbuffer->setQueueSerial(queueSerial);
+    }
+
+    return gl::NoError();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.h
new file mode 100644
index 0000000..b28ffbd
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.h
@@ -0,0 +1,103 @@
+//
+// Copyright 2016 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.
+//
+// FramebufferVk.h:
+//    Defines the class interface for FramebufferVk, implementing FramebufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+#include "libANGLE/renderer/vulkan/renderervk_utils.h"
+
+namespace rx
+{
+class RenderTargetVk;
+class WindowSurfaceVk;
+
+class FramebufferVk : public FramebufferImpl, public ResourceVk
+{
+  public:
+    // Factory methods so we don't have to use constructors with overloads.
+    static FramebufferVk *CreateUserFBO(const gl::FramebufferState &state);
+
+    // The passed-in SurfaceVK must be destroyed after this FBO is destroyed. Our Surface code is
+    // ref-counted on the number of 'current' contexts, so we shouldn't get any dangling surface
+    // references. See Surface::setIsCurrent(bool).
+    static FramebufferVk *CreateDefaultFBO(const gl::FramebufferState &state,
+                                           WindowSurfaceVk *backbuffer);
+
+    ~FramebufferVk() override;
+    void destroy(ContextImpl *contextImpl) override;
+    void destroyDefault(DisplayImpl *displayImpl) override;
+
+    gl::Error discard(size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(size_t count, const GLenum *attachments) override;
+    gl::Error invalidateSub(size_t count,
+                            const GLenum *attachments,
+                            const gl::Rectangle &area) override;
+
+    gl::Error clear(ContextImpl *context, GLbitfield mask) override;
+    gl::Error clearBufferfv(ContextImpl *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLfloat *values) override;
+    gl::Error clearBufferuiv(ContextImpl *context,
+                             GLenum buffer,
+                             GLint drawbuffer,
+                             const GLuint *values) override;
+    gl::Error clearBufferiv(ContextImpl *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLint *values) override;
+    gl::Error clearBufferfi(ContextImpl *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            GLfloat depth,
+                            GLint stencil) override;
+
+    GLenum getImplementationColorReadFormat() const override;
+    GLenum getImplementationColorReadType() const override;
+    gl::Error readPixels(ContextImpl *context,
+                         const gl::Rectangle &area,
+                         GLenum format,
+                         GLenum type,
+                         void *pixels) const override;
+
+    gl::Error blit(ContextImpl *context,
+                   const gl::Rectangle &sourceArea,
+                   const gl::Rectangle &destArea,
+                   GLbitfield mask,
+                   GLenum filter) override;
+
+    bool checkStatus() const override;
+
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
+
+    gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
+
+    gl::Error beginRenderPass(VkDevice device,
+                              vk::CommandBuffer *commandBuffer,
+                              Serial queueSerial,
+                              const gl::State &glState);
+
+    gl::ErrorOrResult<vk::RenderPass *> getRenderPass(VkDevice device);
+
+  private:
+    FramebufferVk(const gl::FramebufferState &state);
+    FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer);
+
+    gl::ErrorOrResult<vk::Framebuffer *> getFramebuffer(VkDevice device);
+
+    WindowSurfaceVk *mBackbuffer;
+
+    vk::RenderPass mRenderPass;
+    vk::Framebuffer mFramebuffer;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
new file mode 100644
index 0000000..5871c54
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
@@ -0,0 +1,121 @@
+//
+// Copyright (c) 2016 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.
+//
+// GlslangWrapper: Wrapper for Vulkan's glslang compiler.
+//
+
+#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
+
+// glslang's version of ShaderLang.h, not to be confused with ANGLE's.
+// Our function defs conflict with theirs, but we carefully manage our includes to prevent this.
+#include <ShaderLang.h>
+
+// Other glslang includes.
+#include <StandAlone/ResourceLimits.h>
+#include <SPIRV/GlslangToSpv.h>
+
+#include <array>
+
+namespace rx
+{
+
+// static
+GlslangWrapper *GlslangWrapper::mInstance = nullptr;
+
+// static
+GlslangWrapper *GlslangWrapper::GetReference()
+{
+    if (!mInstance)
+    {
+        mInstance = new GlslangWrapper();
+    }
+
+    mInstance->addRef();
+
+    return mInstance;
+}
+
+// static
+void GlslangWrapper::ReleaseReference()
+{
+    if (mInstance->getRefCount() == 1)
+    {
+        mInstance->release();
+        mInstance = nullptr;
+    }
+    else
+    {
+        mInstance->release();
+    }
+}
+
+GlslangWrapper::GlslangWrapper()
+{
+    int result = ShInitialize();
+    ASSERT(result != 0);
+}
+
+GlslangWrapper::~GlslangWrapper()
+{
+    int result = ShFinalize();
+    ASSERT(result != 0);
+}
+
+LinkResult GlslangWrapper::linkProgram(const std::string &vertexSource,
+                                       const std::string &fragmentSource,
+                                       std::vector<uint32_t> *vertexCodeOut,
+                                       std::vector<uint32_t> *fragmentCodeOut)
+{
+    std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}};
+
+    std::array<int, 2> lengths = {
+        {static_cast<int>(vertexSource.length()), static_cast<int>(fragmentSource.length())}};
+
+    // Enable SPIR-V and Vulkan rules when parsing GLSL
+    EShMessages messages = static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules);
+
+    glslang::TShader vertexShader(EShLangVertex);
+    vertexShader.setStringsWithLengths(&strings[0], &lengths[0], 1);
+    vertexShader.setEntryPoint("main");
+    bool vertexResult = vertexShader.parse(&glslang::DefaultTBuiltInResource, 450, ECoreProfile,
+                                           false, false, messages);
+    if (!vertexResult)
+    {
+        return gl::InternalError() << "Internal error parsing Vulkan vertex shader:\n"
+                                   << vertexShader.getInfoLog() << "\n"
+                                   << vertexShader.getInfoDebugLog() << "\n";
+    }
+
+    glslang::TShader fragmentShader(EShLangFragment);
+    fragmentShader.setStringsWithLengths(&strings[1], &lengths[1], 1);
+    fragmentShader.setEntryPoint("main");
+    bool fragmentResult = fragmentShader.parse(&glslang::DefaultTBuiltInResource, 450, ECoreProfile,
+                                               false, false, messages);
+    if (!fragmentResult)
+    {
+        return gl::InternalError() << "Internal error parsing Vulkan fragment shader:\n"
+                                   << fragmentShader.getInfoLog() << "\n"
+                                   << fragmentShader.getInfoDebugLog() << "\n";
+    }
+
+    glslang::TProgram program;
+    program.addShader(&vertexShader);
+    program.addShader(&fragmentShader);
+    bool linkResult = program.link(messages);
+    if (!linkResult)
+    {
+        return gl::InternalError() << "Internal error linking Vulkan shaders:\n"
+                                   << program.getInfoLog() << "\n";
+    }
+
+    glslang::TIntermediate *vertexStage   = program.getIntermediate(EShLangVertex);
+    glslang::TIntermediate *fragmentStage = program.getIntermediate(EShLangFragment);
+    glslang::GlslangToSpv(*vertexStage, *vertexCodeOut);
+    glslang::GlslangToSpv(*fragmentStage, *fragmentCodeOut);
+
+    return true;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.h
new file mode 100644
index 0000000..da848b7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.h
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2016 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.
+//
+// GlslangWrapper: Wrapper for Vulkan's glslang compiler.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_GLSLANG_WRAPPER_H_
+#define LIBANGLE_RENDERER_VULKAN_GLSLANG_WRAPPER_H_
+
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+class GlslangWrapper : public RefCountObjectNoID
+{
+  public:
+    // Increases the reference count.
+    // TODO(jmadill): Determine how to handle this atomically.
+    static GlslangWrapper *GetReference();
+    static void ReleaseReference();
+
+    LinkResult linkProgram(const std::string &vertexSource,
+                           const std::string &fragmentSource,
+                           std::vector<uint32_t> *vertexCodeOut,
+                           std::vector<uint32_t> *fragmentCodeOut);
+
+  private:
+    GlslangWrapper();
+    ~GlslangWrapper() override;
+
+    static GlslangWrapper *mInstance;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_GLSLANG_WRAPPER_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp
new file mode 100644
index 0000000..d83119d
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp
@@ -0,0 +1,37 @@
+//
+// Copyright 2016 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.
+//
+// ImageVk.cpp:
+//    Implements the class methods for ImageVk.
+//
+
+#include "libANGLE/renderer/vulkan/ImageVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ImageVk::ImageVk(const egl::ImageState &state) : ImageImpl(state)
+{
+}
+
+ImageVk::~ImageVk()
+{
+}
+
+egl::Error ImageVk::initialize()
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+gl::Error ImageVk::orphan(egl::ImageSibling *sibling)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.h
new file mode 100644
index 0000000..85672f9
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.h
@@ -0,0 +1,30 @@
+//
+// Copyright 2016 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.
+//
+// ImageVk.h:
+//    Defines the class interface for ImageVk, implementing ImageImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_IMAGEVK_H_
+#define LIBANGLE_RENDERER_VULKAN_IMAGEVK_H_
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace rx
+{
+
+class ImageVk : public ImageImpl
+{
+  public:
+    ImageVk(const egl::ImageState &state);
+    ~ImageVk() override;
+    egl::Error initialize() override;
+
+    gl::Error orphan(egl::ImageSibling *sibling) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_IMAGEVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp
new file mode 100644
index 0000000..6e53883
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -0,0 +1,313 @@
+//
+// Copyright 2016 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.
+//
+// ProgramVk.cpp:
+//    Implements the class methods for ProgramVk.
+//
+
+#include "libANGLE/renderer/vulkan/ProgramVk.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+
+namespace rx
+{
+
+ProgramVk::ProgramVk(const gl::ProgramState &state) : ProgramImpl(state)
+{
+}
+
+ProgramVk::~ProgramVk()
+{
+}
+
+void ProgramVk::destroy(const ContextImpl *contextImpl)
+{
+    VkDevice device = GetAs<ContextVk>(contextImpl)->getDevice();
+
+    mLinkedFragmentModule.destroy(device);
+    mLinkedVertexModule.destroy(device);
+    mPipelineLayout.destroy(device);
+}
+
+LinkResult ProgramVk::load(const ContextImpl *contextImpl,
+                           gl::InfoLog &infoLog,
+                           gl::BinaryInputStream *stream)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ProgramVk::save(gl::BinaryOutputStream *stream)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+void ProgramVk::setBinaryRetrievableHint(bool retrievable)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setSeparable(bool separable)
+{
+    UNIMPLEMENTED();
+}
+
+LinkResult ProgramVk::link(ContextImpl *contextImpl,
+                           const gl::VaryingPacking &packing,
+                           gl::InfoLog &infoLog)
+{
+    ContextVk *context             = GetAs<ContextVk>(contextImpl);
+    RendererVk *renderer           = context->getRenderer();
+    GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
+
+    const std::string &vertexSource   = mState.getAttachedVertexShader()->getTranslatedSource();
+    const std::string &fragmentSource = mState.getAttachedFragmentShader()->getTranslatedSource();
+
+    std::vector<uint32_t> vertexCode;
+    std::vector<uint32_t> fragmentCode;
+    bool linkSuccess = false;
+    ANGLE_TRY_RESULT(
+        glslangWrapper->linkProgram(vertexSource, fragmentSource, &vertexCode, &fragmentCode),
+        linkSuccess);
+    if (!linkSuccess)
+    {
+        return false;
+    }
+
+    vk::ShaderModule vertexModule;
+    vk::ShaderModule fragmentModule;
+    VkDevice device = renderer->getDevice();
+
+    {
+        VkShaderModuleCreateInfo vertexShaderInfo;
+        vertexShaderInfo.sType    = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+        vertexShaderInfo.pNext    = nullptr;
+        vertexShaderInfo.flags    = 0;
+        vertexShaderInfo.codeSize = vertexCode.size() * sizeof(uint32_t);
+        vertexShaderInfo.pCode    = vertexCode.data();
+        ANGLE_TRY(vertexModule.init(device, vertexShaderInfo));
+    }
+
+    {
+        VkShaderModuleCreateInfo fragmentShaderInfo;
+        fragmentShaderInfo.sType    = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+        fragmentShaderInfo.pNext    = nullptr;
+        fragmentShaderInfo.flags    = 0;
+        fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
+        fragmentShaderInfo.pCode    = fragmentCode.data();
+
+        ANGLE_TRY(fragmentModule.init(device, fragmentShaderInfo));
+    }
+
+    mLinkedVertexModule.retain(device, std::move(vertexModule));
+    mLinkedFragmentModule.retain(device, std::move(fragmentModule));
+
+    // TODO(jmadill): Use pipeline cache.
+    context->invalidateCurrentPipeline();
+
+    return true;
+}
+
+GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
+{
+    UNIMPLEMENTED();
+    return GLboolean();
+}
+
+void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix2fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix3fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix4fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix2x3fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix3x2fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix2x4fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix4x2fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix3x4fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix4x3fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+    UNIMPLEMENTED();
+}
+
+bool ProgramVk::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+    UNIMPLEMENTED();
+    return bool();
+}
+
+bool ProgramVk::getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                          sh::BlockMemberInfo *memberInfoOut) const
+{
+    UNIMPLEMENTED();
+    return bool();
+}
+
+void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
+                                        GLenum genMode,
+                                        GLint components,
+                                        const GLfloat *coeffs)
+{
+    UNIMPLEMENTED();
+}
+
+const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
+{
+    ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
+    return mLinkedVertexModule;
+}
+
+const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
+{
+    ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
+    return mLinkedFragmentModule;
+}
+
+gl::ErrorOrResult<vk::PipelineLayout *> ProgramVk::getPipelineLayout(VkDevice device)
+{
+    vk::PipelineLayout newLayout;
+
+    // TODO(jmadill): Descriptor sets.
+    VkPipelineLayoutCreateInfo createInfo;
+    createInfo.sType                  = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+    createInfo.pNext                  = nullptr;
+    createInfo.flags                  = 0;
+    createInfo.setLayoutCount         = 0;
+    createInfo.pSetLayouts            = nullptr;
+    createInfo.pushConstantRangeCount = 0;
+    createInfo.pPushConstantRanges    = nullptr;
+
+    ANGLE_TRY(newLayout.init(device, createInfo));
+    mPipelineLayout.retain(device, std::move(newLayout));
+
+    return &mPipelineLayout;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.h
new file mode 100644
index 0000000..ff8efc5
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.h
@@ -0,0 +1,116 @@
+//
+// Copyright 2016 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.
+//
+// ProgramVk.h:
+//    Defines the class interface for ProgramVk, implementing ProgramImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
+#define LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
+
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "libANGLE/renderer/vulkan/renderervk_utils.h"
+
+namespace rx
+{
+
+class ProgramVk : public ProgramImpl
+{
+  public:
+    ProgramVk(const gl::ProgramState &state);
+    ~ProgramVk() override;
+    void destroy(const ContextImpl *contextImpl) override;
+
+    LinkResult load(const ContextImpl *contextImpl,
+                    gl::InfoLog &infoLog,
+                    gl::BinaryInputStream *stream) override;
+    gl::Error save(gl::BinaryOutputStream *stream) override;
+    void setBinaryRetrievableHint(bool retrievable) override;
+    void setSeparable(bool separable) override;
+
+    LinkResult link(ContextImpl *contextImpl,
+                    const gl::VaryingPacking &packing,
+                    gl::InfoLog &infoLog) override;
+    GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
+
+    void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override;
+    void setUniform1iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform2iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform3iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform4iv(GLint location, GLsizei count, const GLint *v) override;
+    void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override;
+    void setUniformMatrix2fv(GLint location,
+                             GLsizei count,
+                             GLboolean transpose,
+                             const GLfloat *value) override;
+    void setUniformMatrix3fv(GLint location,
+                             GLsizei count,
+                             GLboolean transpose,
+                             const GLfloat *value) override;
+    void setUniformMatrix4fv(GLint location,
+                             GLsizei count,
+                             GLboolean transpose,
+                             const GLfloat *value) override;
+    void setUniformMatrix2x3fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix3x2fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix2x4fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix4x2fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix3x4fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+    void setUniformMatrix4x3fv(GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat *value) override;
+
+    // TODO: synchronize in syncState when dirty bits exist.
+    void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
+
+    // May only be called after a successful link operation.
+    // Return false for inactive blocks.
+    bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+
+    // May only be called after a successful link operation.
+    // Returns false for inactive members.
+    bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                   sh::BlockMemberInfo *memberInfoOut) const override;
+
+    void setPathFragmentInputGen(const std::string &inputName,
+                                 GLenum genMode,
+                                 GLint components,
+                                 const GLfloat *coeffs) override;
+
+    const vk::ShaderModule &getLinkedVertexModule() const;
+    const vk::ShaderModule &getLinkedFragmentModule() const;
+    gl::ErrorOrResult<vk::PipelineLayout *> getPipelineLayout(VkDevice device);
+
+  private:
+    vk::ShaderModule mLinkedVertexModule;
+    vk::ShaderModule mLinkedFragmentModule;
+    vk::PipelineLayout mPipelineLayout;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp
new file mode 100644
index 0000000..01fd0c4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp
@@ -0,0 +1,73 @@
+//
+// Copyright 2016 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.
+//
+// QueryVk.cpp:
+//    Implements the class methods for QueryVk.
+//
+
+#include "libANGLE/renderer/vulkan/QueryVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+QueryVk::QueryVk(GLenum type) : QueryImpl(type)
+{
+}
+
+QueryVk::~QueryVk()
+{
+}
+
+gl::Error QueryVk::begin()
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::end()
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::queryCounter()
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::getResult(GLint *params)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::getResult(GLuint *params)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::getResult(GLint64 *params)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::getResult(GLuint64 *params)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::isResultAvailable(bool *available)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.h
new file mode 100644
index 0000000..7c92734
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2016 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.
+//
+// QueryVk.h:
+//    Defines the class interface for QueryVk, implementing QueryImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_QUERYVK_H_
+#define LIBANGLE_RENDERER_VULKAN_QUERYVK_H_
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+
+class QueryVk : public QueryImpl
+{
+  public:
+    QueryVk(GLenum type);
+    ~QueryVk() override;
+
+    gl::Error begin() override;
+    gl::Error end() override;
+    gl::Error queryCounter() override;
+    gl::Error getResult(GLint *params) override;
+    gl::Error getResult(GLuint *params) override;
+    gl::Error getResult(GLint64 *params) override;
+    gl::Error getResult(GLuint64 *params) override;
+    gl::Error isResultAvailable(bool *available) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_QUERYVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp
new file mode 100644
index 0000000..b559320
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp
@@ -0,0 +1,25 @@
+//
+// Copyright 2016 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.
+//
+// RenderTargetVk:
+//   Wrapper around a Vulkan renderable resource, using an ImageView.
+//
+
+#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
+
+namespace rx
+{
+
+RenderTargetVk::RenderTargetVk()
+    : format(nullptr),
+      image(nullptr),
+      imageView(nullptr),
+      extents(),
+      samples(VK_SAMPLE_COUNT_1_BIT),
+      resource(nullptr)
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.h
new file mode 100644
index 0000000..6de9e07
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.h
@@ -0,0 +1,46 @@
+//
+// Copyright 2016 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.
+//
+// RenderTargetVk:
+//   Wrapper around a Vulkan renderable resource, using an ImageView.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
+#define LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
+
+#include <vulkan/vulkan.h>
+
+#include "libANGLE/FramebufferAttachment.h"
+
+namespace rx
+{
+class ResourceVk;
+
+namespace vk
+{
+struct Format;
+class Image;
+class ImageView;
+}
+
+// This is a very light-weight class that does not own to the resources it points to.
+// It's meant only to copy across some information from a FramebufferAttachment to the
+// business rendering logic.
+class RenderTargetVk final : public FramebufferAttachmentRenderTarget
+{
+  public:
+    RenderTargetVk();
+
+    const vk::Format *format;
+    vk::Image *image;
+    vk::ImageView *imageView;
+    gl::Extents extents;
+    VkSampleCountFlagBits samples;
+    ResourceVk *resource;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
new file mode 100644
index 0000000..d873e27
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
@@ -0,0 +1,54 @@
+//
+// Copyright 2016 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.
+//
+// RenderbufferVk.cpp:
+//    Implements the class methods for RenderbufferVk.
+//
+
+#include "libANGLE/renderer/vulkan/RenderbufferVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+RenderbufferVk::RenderbufferVk() : RenderbufferImpl()
+{
+}
+
+RenderbufferVk::~RenderbufferVk()
+{
+}
+
+gl::Error RenderbufferVk::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error RenderbufferVk::setStorageMultisample(size_t samples,
+                                                GLenum internalformat,
+                                                size_t width,
+                                                size_t height)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error RenderbufferVk::setStorageEGLImageTarget(egl::Image *image)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error RenderbufferVk::getAttachmentRenderTarget(GLenum binding,
+                                                    const gl::ImageIndex &imageIndex,
+                                                    FramebufferAttachmentRenderTarget **rtOut)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h
new file mode 100644
index 0000000..95ce8bb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2016 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.
+//
+// RenderbufferVk.h:
+//    Defines the class interface for RenderbufferVk, implementing RenderbufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_RENDERBUFFERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_RENDERBUFFERVK_H_
+
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+
+class RenderbufferVk : public RenderbufferImpl
+{
+  public:
+    RenderbufferVk();
+    ~RenderbufferVk() override;
+
+    gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
+    gl::Error setStorageMultisample(size_t samples,
+                                    GLenum internalformat,
+                                    size_t width,
+                                    size_t height) override;
+    gl::Error setStorageEGLImageTarget(egl::Image *image) override;
+
+    gl::Error getAttachmentRenderTarget(GLenum binding,
+                                        const gl::ImageIndex &imageIndex,
+                                        FramebufferAttachmentRenderTarget **rtOut) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_RENDERBUFFERVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp
new file mode 100644
index 0000000..1f51cd6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -0,0 +1,790 @@
+//
+// Copyright 2016 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.
+//
+// RendererVk.cpp:
+//    Implements the class methods for RendererVk.
+//
+
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+
+// Placing this first seems to solve an intellisense bug.
+#include "libANGLE/renderer/vulkan/renderervk_utils.h"
+
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "common/system_utils.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "libANGLE/renderer/vulkan/CompilerVk.h"
+#include "libANGLE/renderer/vulkan/FramebufferVk.h"
+#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
+#include "libANGLE/renderer/vulkan/TextureVk.h"
+#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+#include "platform/Platform.h"
+
+namespace rx
+{
+
+namespace
+{
+
+VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &extensionProps,
+                                 const std::vector<const char *> &enabledExtensionNames)
+{
+    // Compile the extensions names into a set.
+    std::set<std::string> extensionNames;
+    for (const auto &extensionProp : extensionProps)
+    {
+        extensionNames.insert(extensionProp.extensionName);
+    }
+
+    for (const auto &extensionName : enabledExtensionNames)
+    {
+        if (extensionNames.count(extensionName) == 0)
+        {
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+    }
+
+    return VK_SUCCESS;
+}
+
+VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
+                                        VkDebugReportObjectTypeEXT objectType,
+                                        uint64_t object,
+                                        size_t location,
+                                        int32_t messageCode,
+                                        const char *layerPrefix,
+                                        const char *message,
+                                        void *userData)
+{
+    if ((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0)
+    {
+        ERR() << message;
+#if !defined(NDEBUG)
+        // Abort the call in Debug builds.
+        return VK_TRUE;
+#endif
+    }
+    else if ((flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0)
+    {
+        WARN() << message;
+    }
+    else
+    {
+        // Uncomment this if you want Vulkan spam.
+        // WARN() << message;
+    }
+
+    return VK_FALSE;
+}
+
+}  // anonymous namespace
+
+RendererVk::RendererVk()
+    : mCapsInitialized(false),
+      mInstance(VK_NULL_HANDLE),
+      mEnableValidationLayers(false),
+      mDebugReportCallback(VK_NULL_HANDLE),
+      mPhysicalDevice(VK_NULL_HANDLE),
+      mQueue(VK_NULL_HANDLE),
+      mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
+      mDevice(VK_NULL_HANDLE),
+      mHostVisibleMemoryIndex(std::numeric_limits<uint32_t>::max()),
+      mGlslangWrapper(nullptr),
+      mCurrentQueueSerial(),
+      mLastCompletedQueueSerial(),
+      mInFlightCommands()
+{
+    ++mCurrentQueueSerial;
+}
+
+RendererVk::~RendererVk()
+{
+    if (!mInFlightCommands.empty() || !mInFlightFences.empty() || !mGarbage.empty())
+    {
+        vk::Error error = finish();
+        if (error.isError())
+        {
+            ERR() << "Error during VK shutdown: " << error;
+        }
+    }
+
+    if (mGlslangWrapper)
+    {
+        GlslangWrapper::ReleaseReference();
+        mGlslangWrapper = nullptr;
+    }
+
+    if (mCommandBuffer.valid())
+    {
+        mCommandBuffer.destroy(mDevice);
+    }
+
+    if (mCommandPool.valid())
+    {
+        mCommandPool.destroy(mDevice);
+    }
+
+    if (mDevice)
+    {
+        vkDestroyDevice(mDevice, nullptr);
+        mDevice = VK_NULL_HANDLE;
+    }
+
+    if (mDebugReportCallback)
+    {
+        ASSERT(mInstance);
+        auto destroyDebugReportCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+            vkGetInstanceProcAddr(mInstance, "vkDestroyDebugReportCallbackEXT"));
+        ASSERT(destroyDebugReportCallback);
+        destroyDebugReportCallback(mInstance, mDebugReportCallback, nullptr);
+    }
+
+    if (mInstance)
+    {
+        vkDestroyInstance(mInstance, nullptr);
+        mInstance = VK_NULL_HANDLE;
+    }
+
+    mPhysicalDevice = VK_NULL_HANDLE;
+}
+
+vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *wsiName)
+{
+#if !defined(NDEBUG)
+    // Validation layers enabled by default in Debug.
+    mEnableValidationLayers = true;
+#endif
+
+    // If specified in the attributes, override the default.
+    if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
+    {
+        mEnableValidationLayers =
+            (attribs.get(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE, EGL_FALSE) == EGL_TRUE);
+    }
+
+    // If we're loading the validation layers, we could be running from any random directory.
+    // Change to the executable directory so we can find the layers, then change back to the
+    // previous directory to be safe we don't disrupt the application.
+    std::string previousCWD;
+
+    if (mEnableValidationLayers)
+    {
+        const auto &cwd = angle::GetCWD();
+        if (!cwd.valid())
+        {
+            ERR() << "Error getting CWD for Vulkan layers init.";
+            mEnableValidationLayers = false;
+        }
+        else
+        {
+            previousCWD = cwd.value();
+        }
+        const char *exeDir = angle::GetExecutableDirectory();
+        angle::SetCWD(exeDir);
+    }
+
+    // Gather global layer properties.
+    uint32_t instanceLayerCount = 0;
+    ANGLE_VK_TRY(vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr));
+
+    std::vector<VkLayerProperties> instanceLayerProps(instanceLayerCount);
+    if (instanceLayerCount > 0)
+    {
+        ANGLE_VK_TRY(
+            vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayerProps.data()));
+    }
+
+    uint32_t instanceExtensionCount = 0;
+    ANGLE_VK_TRY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount, nullptr));
+
+    std::vector<VkExtensionProperties> instanceExtensionProps(instanceExtensionCount);
+    if (instanceExtensionCount > 0)
+    {
+        ANGLE_VK_TRY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount,
+                                                            instanceExtensionProps.data()));
+    }
+
+    if (mEnableValidationLayers)
+    {
+        // Verify the standard validation layers are available.
+        if (!HasStandardValidationLayer(instanceLayerProps))
+        {
+            // Generate an error if the attribute was requested, warning otherwise.
+            if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
+            {
+                ERR() << "Vulkan standard validation layers are missing.";
+            }
+            else
+            {
+                WARN() << "Vulkan standard validation layers are missing.";
+            }
+            mEnableValidationLayers = false;
+        }
+    }
+
+    std::vector<const char *> enabledInstanceExtensions;
+    enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
+    enabledInstanceExtensions.push_back(wsiName);
+
+    // TODO(jmadill): Should be able to continue initialization if debug report ext missing.
+    if (mEnableValidationLayers)
+    {
+        enabledInstanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+    }
+
+    // Verify the required extensions are in the extension names set. Fail if not.
+    ANGLE_VK_TRY(VerifyExtensionsPresent(instanceExtensionProps, enabledInstanceExtensions));
+
+    VkApplicationInfo applicationInfo;
+    applicationInfo.sType              = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+    applicationInfo.pNext              = nullptr;
+    applicationInfo.pApplicationName   = "ANGLE";
+    applicationInfo.applicationVersion = 1;
+    applicationInfo.pEngineName        = "ANGLE";
+    applicationInfo.engineVersion      = 1;
+    applicationInfo.apiVersion         = VK_API_VERSION_1_0;
+
+    VkInstanceCreateInfo instanceInfo;
+    instanceInfo.sType            = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+    instanceInfo.pNext            = nullptr;
+    instanceInfo.flags            = 0;
+    instanceInfo.pApplicationInfo = &applicationInfo;
+
+    // Enable requested layers and extensions.
+    instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
+    instanceInfo.ppEnabledExtensionNames =
+        enabledInstanceExtensions.empty() ? nullptr : enabledInstanceExtensions.data();
+    instanceInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u;
+    instanceInfo.ppEnabledLayerNames =
+        mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
+
+    ANGLE_VK_TRY(vkCreateInstance(&instanceInfo, nullptr, &mInstance));
+
+    if (mEnableValidationLayers)
+    {
+        // Change back to the previous working directory now that we've loaded the instance -
+        // the validation layers should be loaded at this point.
+        angle::SetCWD(previousCWD.c_str());
+
+        VkDebugReportCallbackCreateInfoEXT debugReportInfo;
+
+        debugReportInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+        debugReportInfo.pNext = nullptr;
+        debugReportInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT |
+                                VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
+                                VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+        debugReportInfo.pfnCallback = &DebugReportCallback;
+        debugReportInfo.pUserData   = this;
+
+        auto createDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+            vkGetInstanceProcAddr(mInstance, "vkCreateDebugReportCallbackEXT"));
+        ASSERT(createDebugReportCallback);
+        ANGLE_VK_TRY(
+            createDebugReportCallback(mInstance, &debugReportInfo, nullptr, &mDebugReportCallback));
+    }
+
+    uint32_t physicalDeviceCount = 0;
+    ANGLE_VK_TRY(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr));
+    ANGLE_VK_CHECK(physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED);
+
+    // TODO(jmadill): Handle multiple physical devices. For now, use the first device.
+    physicalDeviceCount = 1;
+    ANGLE_VK_TRY(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, &mPhysicalDevice));
+
+    vkGetPhysicalDeviceProperties(mPhysicalDevice, &mPhysicalDeviceProperties);
+
+    // Ensure we can find a graphics queue family.
+    uint32_t queueCount = 0;
+    vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr);
+
+    ANGLE_VK_CHECK(queueCount > 0, VK_ERROR_INITIALIZATION_FAILED);
+
+    mQueueFamilyProperties.resize(queueCount);
+    vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount,
+                                             mQueueFamilyProperties.data());
+
+    size_t graphicsQueueFamilyCount   = false;
+    uint32_t firstGraphicsQueueFamily = 0;
+    for (uint32_t familyIndex = 0; familyIndex < queueCount; ++familyIndex)
+    {
+        const auto &queueInfo = mQueueFamilyProperties[familyIndex];
+        if ((queueInfo.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
+        {
+            ASSERT(queueInfo.queueCount > 0);
+            graphicsQueueFamilyCount++;
+            if (firstGraphicsQueueFamily == 0)
+            {
+                firstGraphicsQueueFamily = familyIndex;
+            }
+            break;
+        }
+    }
+
+    ANGLE_VK_CHECK(graphicsQueueFamilyCount > 0, VK_ERROR_INITIALIZATION_FAILED);
+
+    // If only one queue family, go ahead and initialize the device. If there is more than one
+    // queue, we'll have to wait until we see a WindowSurface to know which supports present.
+    if (graphicsQueueFamilyCount == 1)
+    {
+        ANGLE_TRY(initializeDevice(firstGraphicsQueueFamily));
+    }
+
+    VkPhysicalDeviceMemoryProperties memoryProperties;
+    vkGetPhysicalDeviceMemoryProperties(mPhysicalDevice, &memoryProperties);
+
+    for (uint32_t memoryIndex = 0; memoryIndex < memoryProperties.memoryTypeCount; ++memoryIndex)
+    {
+        if ((memoryProperties.memoryTypes[memoryIndex].propertyFlags &
+             VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+        {
+            mHostVisibleMemoryIndex = memoryIndex;
+            break;
+        }
+    }
+
+    ANGLE_VK_CHECK(mHostVisibleMemoryIndex < std::numeric_limits<uint32_t>::max(),
+                   VK_ERROR_INITIALIZATION_FAILED);
+
+    mGlslangWrapper = GlslangWrapper::GetReference();
+
+    return vk::NoError();
+}
+
+vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
+{
+    uint32_t deviceLayerCount = 0;
+    ANGLE_VK_TRY(vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount, nullptr));
+
+    std::vector<VkLayerProperties> deviceLayerProps(deviceLayerCount);
+    if (deviceLayerCount > 0)
+    {
+        ANGLE_VK_TRY(vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount,
+                                                      deviceLayerProps.data()));
+    }
+
+    uint32_t deviceExtensionCount = 0;
+    ANGLE_VK_TRY(vkEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr,
+                                                      &deviceExtensionCount, nullptr));
+
+    std::vector<VkExtensionProperties> deviceExtensionProps(deviceExtensionCount);
+    if (deviceExtensionCount > 0)
+    {
+        ANGLE_VK_TRY(vkEnumerateDeviceExtensionProperties(
+            mPhysicalDevice, nullptr, &deviceExtensionCount, deviceExtensionProps.data()));
+    }
+
+    if (mEnableValidationLayers)
+    {
+        if (!HasStandardValidationLayer(deviceLayerProps))
+        {
+            WARN() << "Vulkan standard validation layer is missing.";
+            mEnableValidationLayers = false;
+        }
+    }
+
+    std::vector<const char *> enabledDeviceExtensions;
+    enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
+
+    ANGLE_VK_TRY(VerifyExtensionsPresent(deviceExtensionProps, enabledDeviceExtensions));
+
+    VkDeviceQueueCreateInfo queueCreateInfo;
+
+    float zeroPriority = 0.0f;
+
+    queueCreateInfo.sType            = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+    queueCreateInfo.pNext            = nullptr;
+    queueCreateInfo.flags            = 0;
+    queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
+    queueCreateInfo.queueCount       = 1;
+    queueCreateInfo.pQueuePriorities = &zeroPriority;
+
+    // Initialize the device
+    VkDeviceCreateInfo createInfo;
+
+    createInfo.sType                = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+    createInfo.pNext                = nullptr;
+    createInfo.flags                = 0;
+    createInfo.queueCreateInfoCount = 1;
+    createInfo.pQueueCreateInfos    = &queueCreateInfo;
+    createInfo.enabledLayerCount    = mEnableValidationLayers ? 1u : 0u;
+    createInfo.ppEnabledLayerNames =
+        mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
+    createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
+    createInfo.ppEnabledExtensionNames =
+        enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
+    createInfo.pEnabledFeatures = nullptr;  // TODO(jmadill): features
+
+    ANGLE_VK_TRY(vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
+
+    mCurrentQueueFamilyIndex = queueFamilyIndex;
+
+    vkGetDeviceQueue(mDevice, mCurrentQueueFamilyIndex, 0, &mQueue);
+
+    // Initialize the command pool now that we know the queue family index.
+    VkCommandPoolCreateInfo commandPoolInfo;
+    commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+    commandPoolInfo.pNext = nullptr;
+    // TODO(jmadill): Investigate transient command buffers.
+    commandPoolInfo.flags            = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+    commandPoolInfo.queueFamilyIndex = mCurrentQueueFamilyIndex;
+
+    ANGLE_TRY(mCommandPool.init(mDevice, commandPoolInfo));
+
+    mCommandBuffer.setCommandPool(&mCommandPool);
+
+    return vk::NoError();
+}
+
+vk::ErrorOrResult<uint32_t> RendererVk::selectPresentQueueForSurface(VkSurfaceKHR surface)
+{
+    // We've already initialized a device, and can't re-create it unless it's never been used.
+    // TODO(jmadill): Handle the re-creation case if necessary.
+    if (mDevice != VK_NULL_HANDLE)
+    {
+        ASSERT(mCurrentQueueFamilyIndex != std::numeric_limits<uint32_t>::max());
+
+        // Check if the current device supports present on this surface.
+        VkBool32 supportsPresent = VK_FALSE;
+        ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, mCurrentQueueFamilyIndex,
+                                                          surface, &supportsPresent));
+
+        return (supportsPresent == VK_TRUE);
+    }
+
+    // Find a graphics and present queue.
+    Optional<uint32_t> newPresentQueue;
+    uint32_t queueCount = static_cast<uint32_t>(mQueueFamilyProperties.size());
+    for (uint32_t queueIndex = 0; queueIndex < queueCount; ++queueIndex)
+    {
+        const auto &queueInfo = mQueueFamilyProperties[queueIndex];
+        if ((queueInfo.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
+        {
+            VkBool32 supportsPresent = VK_FALSE;
+            ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, queueIndex, surface,
+                                                              &supportsPresent));
+
+            if (supportsPresent == VK_TRUE)
+            {
+                newPresentQueue = queueIndex;
+                break;
+            }
+        }
+    }
+
+    ANGLE_VK_CHECK(newPresentQueue.valid(), VK_ERROR_INITIALIZATION_FAILED);
+    ANGLE_TRY(initializeDevice(newPresentQueue.value()));
+
+    return newPresentQueue.value();
+}
+
+std::string RendererVk::getVendorString() const
+{
+    switch (mPhysicalDeviceProperties.vendorID)
+    {
+        case VENDOR_ID_AMD:
+            return "Advanced Micro Devices";
+        case VENDOR_ID_NVIDIA:
+            return "NVIDIA";
+        case VENDOR_ID_INTEL:
+            return "Intel";
+        default:
+        {
+            // TODO(jmadill): More vendor IDs.
+            std::stringstream strstr;
+            strstr << "Vendor ID: " << mPhysicalDeviceProperties.vendorID;
+            return strstr.str();
+        }
+    }
+}
+
+std::string RendererVk::getRendererDescription() const
+{
+    std::stringstream strstr;
+
+    uint32_t apiVersion = mPhysicalDeviceProperties.apiVersion;
+
+    strstr << "Vulkan ";
+    strstr << VK_VERSION_MAJOR(apiVersion) << ".";
+    strstr << VK_VERSION_MINOR(apiVersion) << ".";
+    strstr << VK_VERSION_PATCH(apiVersion);
+
+    strstr << "(" << mPhysicalDeviceProperties.deviceName << ")";
+
+    return strstr.str();
+}
+
+void RendererVk::ensureCapsInitialized() const
+{
+    if (!mCapsInitialized)
+    {
+        generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
+        mCapsInitialized = true;
+    }
+}
+
+void RendererVk::generateCaps(gl::Caps *outCaps,
+                              gl::TextureCapsMap * /*outTextureCaps*/,
+                              gl::Extensions *outExtensions,
+                              gl::Limitations * /* outLimitations */) const
+{
+    // TODO(jmadill): Caps.
+    outCaps->maxDrawBuffers      = 1;
+    outCaps->maxVertexAttributes     = gl::MAX_VERTEX_ATTRIBS;
+    outCaps->maxVertexAttribBindings = gl::MAX_VERTEX_ATTRIB_BINDINGS;
+
+    // Enable this for simple buffer readback testing, but some functionality is missing.
+    // TODO(jmadill): Support full mapBufferRange extension.
+    outExtensions->mapBuffer      = true;
+    outExtensions->mapBufferRange = true;
+}
+
+const gl::Caps &RendererVk::getNativeCaps() const
+{
+    ensureCapsInitialized();
+    return mNativeCaps;
+}
+
+const gl::TextureCapsMap &RendererVk::getNativeTextureCaps() const
+{
+    ensureCapsInitialized();
+    return mNativeTextureCaps;
+}
+
+const gl::Extensions &RendererVk::getNativeExtensions() const
+{
+    ensureCapsInitialized();
+    return mNativeExtensions;
+}
+
+const gl::Limitations &RendererVk::getNativeLimitations() const
+{
+    ensureCapsInitialized();
+    return mNativeLimitations;
+}
+
+vk::Error RendererVk::getStartedCommandBuffer(vk::CommandBuffer **commandBufferOut)
+{
+    ANGLE_TRY(mCommandBuffer.begin(mDevice));
+    *commandBufferOut = &mCommandBuffer;
+    return vk::NoError();
+}
+
+vk::Error RendererVk::submitCommandBuffer(vk::CommandBuffer *commandBuffer)
+{
+    ANGLE_TRY(commandBuffer->end());
+
+    VkFenceCreateInfo fenceInfo;
+    fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+    fenceInfo.pNext = nullptr;
+    fenceInfo.flags = 0;
+
+    VkSubmitInfo submitInfo;
+    submitInfo.sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+    submitInfo.pNext                = nullptr;
+    submitInfo.waitSemaphoreCount   = 0;
+    submitInfo.pWaitSemaphores      = nullptr;
+    submitInfo.pWaitDstStageMask    = nullptr;
+    submitInfo.commandBufferCount   = 1;
+    submitInfo.pCommandBuffers      = commandBuffer->ptr();
+    submitInfo.signalSemaphoreCount = 0;
+    submitInfo.pSignalSemaphores    = nullptr;
+
+    // TODO(jmadill): Investigate how to properly submit command buffers.
+    ANGLE_TRY(submit(submitInfo));
+
+    return vk::NoError();
+}
+
+vk::Error RendererVk::submitAndFinishCommandBuffer(vk::CommandBuffer *commandBuffer)
+{
+    ANGLE_TRY(submitCommandBuffer(commandBuffer));
+    ANGLE_TRY(finish());
+
+    return vk::NoError();
+}
+
+vk::Error RendererVk::submitCommandsWithSync(vk::CommandBuffer *commandBuffer,
+                                             const vk::Semaphore &waitSemaphore,
+                                             const vk::Semaphore &signalSemaphore)
+{
+    ANGLE_TRY(commandBuffer->end());
+
+    VkPipelineStageFlags waitStageMask  = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+
+    VkSubmitInfo submitInfo;
+    submitInfo.sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+    submitInfo.pNext                = nullptr;
+    submitInfo.waitSemaphoreCount   = 1;
+    submitInfo.pWaitSemaphores      = waitSemaphore.ptr();
+    submitInfo.pWaitDstStageMask    = &waitStageMask;
+    submitInfo.commandBufferCount   = 1;
+    submitInfo.pCommandBuffers      = commandBuffer->ptr();
+    submitInfo.signalSemaphoreCount = 1;
+    submitInfo.pSignalSemaphores    = signalSemaphore.ptr();
+
+    // TODO(jmadill): Investigate how to properly queue command buffer work.
+    ANGLE_TRY(submitFrame(submitInfo));
+
+    return vk::NoError();
+}
+
+vk::Error RendererVk::finish()
+{
+    ASSERT(mQueue != VK_NULL_HANDLE);
+    ANGLE_VK_TRY(vkQueueWaitIdle(mQueue));
+    freeAllInFlightResources();
+    return vk::NoError();
+}
+
+void RendererVk::freeAllInFlightResources()
+{
+    for (auto &fence : mInFlightFences)
+    {
+        fence.destroy(mDevice);
+    }
+    mInFlightFences.clear();
+
+    for (auto &command : mInFlightCommands)
+    {
+        command.destroy(mDevice);
+    }
+    mInFlightCommands.clear();
+
+    for (auto &garbage : mGarbage)
+    {
+        garbage->destroy(mDevice);
+    }
+    mGarbage.clear();
+}
+
+vk::Error RendererVk::checkInFlightCommands()
+{
+    size_t finishedIndex = 0;
+
+    // Check if any in-flight command buffers are finished.
+    for (size_t index = 0; index < mInFlightFences.size(); index++)
+    {
+        auto *inFlightFence = &mInFlightFences[index];
+
+        VkResult result = inFlightFence->get().getStatus(mDevice);
+        if (result == VK_NOT_READY)
+            break;
+        ANGLE_VK_TRY(result);
+        finishedIndex = index + 1;
+
+        // Release the fence handle.
+        // TODO(jmadill): Re-use fences.
+        inFlightFence->destroy(mDevice);
+    }
+
+    if (finishedIndex == 0)
+        return vk::NoError();
+
+    Serial finishedSerial = mInFlightFences[finishedIndex - 1].queueSerial();
+    mInFlightFences.erase(mInFlightFences.begin(), mInFlightFences.begin() + finishedIndex);
+
+    size_t completedCBIndex = 0;
+    for (size_t cbIndex = 0; cbIndex < mInFlightCommands.size(); ++cbIndex)
+    {
+        auto *inFlightCB = &mInFlightCommands[cbIndex];
+        if (inFlightCB->queueSerial() > finishedSerial)
+            break;
+
+        completedCBIndex = cbIndex + 1;
+        inFlightCB->destroy(mDevice);
+    }
+
+    if (completedCBIndex == 0)
+        return vk::NoError();
+
+    mInFlightCommands.erase(mInFlightCommands.begin(),
+                            mInFlightCommands.begin() + completedCBIndex);
+
+    size_t freeIndex = 0;
+    for (; freeIndex < mGarbage.size(); ++freeIndex)
+    {
+        if (!mGarbage[freeIndex]->destroyIfComplete(mDevice, finishedSerial))
+            break;
+    }
+
+    // Remove the entries from the garbage list - they should be ready to go.
+    if (freeIndex > 0)
+    {
+        mGarbage.erase(mGarbage.begin(), mGarbage.begin() + freeIndex);
+    }
+
+    return vk::NoError();
+}
+
+vk::Error RendererVk::submit(const VkSubmitInfo &submitInfo)
+{
+    ANGLE_VK_TRY(vkQueueSubmit(mQueue, 1, &submitInfo, VK_NULL_HANDLE));
+
+    // Store this command buffer in the in-flight list.
+    mInFlightCommands.emplace_back(std::move(mCommandBuffer), mCurrentQueueSerial);
+
+    // Sanity check.
+    ASSERT(mInFlightCommands.size() < 1000u);
+
+    // Increment the queue serial. If this fails, we should restart ANGLE.
+    ANGLE_VK_CHECK(++mCurrentQueueSerial, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+    return vk::NoError();
+}
+
+vk::Error RendererVk::submitFrame(const VkSubmitInfo &submitInfo)
+{
+    VkFenceCreateInfo createInfo;
+    createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+    createInfo.pNext = nullptr;
+    createInfo.flags = 0;
+
+    vk::Fence fence;
+    ANGLE_TRY(fence.init(mDevice, createInfo));
+
+    ANGLE_VK_TRY(vkQueueSubmit(mQueue, 1, &submitInfo, fence.getHandle()));
+
+    // Store this command buffer in the in-flight list.
+    mInFlightFences.emplace_back(std::move(fence), mCurrentQueueSerial);
+    mInFlightCommands.emplace_back(std::move(mCommandBuffer), mCurrentQueueSerial);
+
+    // Sanity check.
+    ASSERT(mInFlightCommands.size() < 1000u);
+
+    // Increment the queue serial. If this fails, we should restart ANGLE.
+    ANGLE_VK_CHECK(++mCurrentQueueSerial, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+    ANGLE_TRY(checkInFlightCommands());
+
+    return vk::NoError();
+}
+
+vk::Error RendererVk::createStagingImage(TextureDimension dimension,
+                                         const vk::Format &format,
+                                         const gl::Extents &extent,
+                                         vk::StagingImage *imageOut)
+{
+    ASSERT(mHostVisibleMemoryIndex != std::numeric_limits<uint32_t>::max());
+
+    ANGLE_TRY(imageOut->init(mDevice, mCurrentQueueFamilyIndex, mHostVisibleMemoryIndex, dimension,
+                             format.native, extent));
+
+    return vk::NoError();
+}
+
+GlslangWrapper *RendererVk::getGlslangWrapper()
+{
+    return mGlslangWrapper;
+}
+
+Serial RendererVk::getCurrentQueueSerial() const
+{
+    return mCurrentQueueSerial;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.h
new file mode 100644
index 0000000..48d3933
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.h
@@ -0,0 +1,136 @@
+//
+// Copyright 2016 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.
+//
+// RendererVk.h:
+//    Defines the class interface for RendererVk.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
+
+#include <memory>
+#include <vulkan/vulkan.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/renderer/vulkan/renderervk_utils.h"
+
+namespace egl
+{
+class AttributeMap;
+}
+
+namespace rx
+{
+class GlslangWrapper;
+
+namespace vk
+{
+struct Format;
+}
+
+class RendererVk : angle::NonCopyable
+{
+  public:
+    RendererVk();
+    ~RendererVk();
+
+    vk::Error initialize(const egl::AttributeMap &attribs, const char *wsiName);
+
+    std::string getVendorString() const;
+    std::string getRendererDescription() const;
+
+    VkInstance getInstance() const { return mInstance; }
+    VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; }
+    VkQueue getQueue() const { return mQueue; }
+    VkDevice getDevice() const { return mDevice; }
+
+    vk::ErrorOrResult<uint32_t> selectPresentQueueForSurface(VkSurfaceKHR surface);
+
+    // TODO(jmadill): Use ContextImpl for command buffers to enable threaded contexts.
+    vk::Error getStartedCommandBuffer(vk::CommandBuffer **commandBufferOut);
+    vk::Error submitCommandBuffer(vk::CommandBuffer *commandBuffer);
+    vk::Error submitAndFinishCommandBuffer(vk::CommandBuffer *commandBuffer);
+    vk::Error submitCommandsWithSync(vk::CommandBuffer *commandBuffer,
+                                     const vk::Semaphore &waitSemaphore,
+                                     const vk::Semaphore &signalSemaphore);
+    vk::Error finish();
+
+    const gl::Caps &getNativeCaps() const;
+    const gl::TextureCapsMap &getNativeTextureCaps() const;
+    const gl::Extensions &getNativeExtensions() const;
+    const gl::Limitations &getNativeLimitations() const;
+
+    vk::Error createStagingImage(TextureDimension dimension,
+                                 const vk::Format &format,
+                                 const gl::Extents &extent,
+                                 vk::StagingImage *imageOut);
+
+    GlslangWrapper *getGlslangWrapper();
+
+    Serial getCurrentQueueSerial() const;
+
+    template <typename T>
+    void enqueueGarbage(Serial serial, T &&object)
+    {
+        mGarbage.emplace_back(std::unique_ptr<vk::GarbageObject<T>>(
+            new vk::GarbageObject<T>(serial, std::move(object))));
+    }
+
+    template <typename T>
+    void enqueueGarbageOrDeleteNow(const ResourceVk &resouce, T &&object)
+    {
+        if (resouce.getDeleteSchedule(mLastCompletedQueueSerial) == DeleteSchedule::NOW)
+        {
+            object.destroy(mDevice);
+        }
+        else
+        {
+            enqueueGarbage(resouce.getStoredQueueSerial(), std::move(object));
+        }
+    }
+
+  private:
+    void ensureCapsInitialized() const;
+    void generateCaps(gl::Caps *outCaps,
+                      gl::TextureCapsMap *outTextureCaps,
+                      gl::Extensions *outExtensions,
+                      gl::Limitations *outLimitations) const;
+    vk::Error submit(const VkSubmitInfo &submitInfo);
+    vk::Error submitFrame(const VkSubmitInfo &submitInfo);
+    vk::Error checkInFlightCommands();
+    void freeAllInFlightResources();
+
+    mutable bool mCapsInitialized;
+    mutable gl::Caps mNativeCaps;
+    mutable gl::TextureCapsMap mNativeTextureCaps;
+    mutable gl::Extensions mNativeExtensions;
+    mutable gl::Limitations mNativeLimitations;
+
+    vk::Error initializeDevice(uint32_t queueFamilyIndex);
+
+    VkInstance mInstance;
+    bool mEnableValidationLayers;
+    VkDebugReportCallbackEXT mDebugReportCallback;
+    VkPhysicalDevice mPhysicalDevice;
+    VkPhysicalDeviceProperties mPhysicalDeviceProperties;
+    std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
+    VkQueue mQueue;
+    uint32_t mCurrentQueueFamilyIndex;
+    VkDevice mDevice;
+    vk::CommandPool mCommandPool;
+    vk::CommandBuffer mCommandBuffer;
+    uint32_t mHostVisibleMemoryIndex;
+    GlslangWrapper *mGlslangWrapper;
+    Serial mCurrentQueueSerial;
+    Serial mLastCompletedQueueSerial;
+    std::vector<vk::CommandBufferAndSerial> mInFlightCommands;
+    std::vector<vk::FenceAndSerial> mInFlightFences;
+    std::vector<std::unique_ptr<vk::IGarbageObject>> mGarbage;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/SamplerVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/SamplerVk.cpp
new file mode 100644
index 0000000..00bb81b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/SamplerVk.cpp
@@ -0,0 +1,25 @@
+//
+// Copyright 2016 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.
+//
+// SamplerVk.cpp:
+//    Implements the class methods for SamplerVk.
+//
+
+#include "libANGLE/renderer/vulkan/SamplerVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+SamplerVk::SamplerVk() : SamplerImpl()
+{
+}
+
+SamplerVk::~SamplerVk()
+{
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/SamplerVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/SamplerVk.h
new file mode 100644
index 0000000..1111f40
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/SamplerVk.h
@@ -0,0 +1,27 @@
+//
+// Copyright 2016 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.
+//
+// SamplerVk.h:
+//    Defines the class interface for SamplerVk, implementing SamplerImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_SAMPLERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_SAMPLERVK_H_
+
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace rx
+{
+
+class SamplerVk : public SamplerImpl
+{
+  public:
+    SamplerVk();
+    ~SamplerVk() override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_SAMPLERVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/ShaderVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/ShaderVk.cpp
new file mode 100644
index 0000000..78024a6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/ShaderVk.cpp
@@ -0,0 +1,43 @@
+//
+// Copyright 2016 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.
+//
+// ShaderVk.cpp:
+//    Implements the class methods for ShaderVk.
+//
+
+#include "libANGLE/renderer/vulkan/ShaderVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ShaderVk::ShaderVk(const gl::ShaderState &data) : ShaderImpl(data)
+{
+}
+
+ShaderVk::~ShaderVk()
+{
+}
+
+ShCompileOptions ShaderVk::prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+                                                         std::string *sourcePath)
+{
+    *sourceStream << mData.getSource();
+    return 0;
+}
+
+bool ShaderVk::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
+{
+    // No work to do here.
+    return true;
+}
+
+std::string ShaderVk::getDebugInfo() const
+{
+    return std::string();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/ShaderVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/ShaderVk.h
new file mode 100644
index 0000000..10f8fe4
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/ShaderVk.h
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 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.
+//
+// ShaderVk.h:
+//    Defines the class interface for ShaderVk, implementing ShaderImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_SHADERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_SHADERVK_H_
+
+#include "libANGLE/renderer/ShaderImpl.h"
+
+namespace rx
+{
+
+class ShaderVk : public ShaderImpl
+{
+  public:
+    ShaderVk(const gl::ShaderState &data);
+    ~ShaderVk() override;
+
+    // Returns additional sh::Compile options.
+    ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+                                                   std::string *sourcePath) override;
+    // Returns success for compiling on the driver. Returns success.
+    bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
+
+    std::string getDebugInfo() const override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_SHADERVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
new file mode 100644
index 0000000..09de86e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -0,0 +1,573 @@
+//
+// Copyright 2016 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.
+//
+// SurfaceVk.cpp:
+//    Implements the class methods for SurfaceVk.
+//
+
+#include "libANGLE/renderer/vulkan/SurfaceVk.h"
+
+#include "common/debug.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
+#include "libANGLE/renderer/vulkan/FramebufferVk.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+
+namespace rx
+{
+
+namespace
+{
+
+const vk::Format &GetVkFormatFromConfig(const egl::Config &config)
+{
+    // TODO(jmadill): Properly handle format interpretation.
+    return vk::Format::Get(GL_BGRA8_EXT);
+}
+
+VkPresentModeKHR GetDesiredPresentMode(const std::vector<VkPresentModeKHR> &presentModes,
+                                       EGLint minSwapInterval,
+                                       EGLint maxSwapInterval)
+{
+    ASSERT(!presentModes.empty());
+
+    // Use FIFO mode for v-sync, since it throttles you to the display rate. Mailbox is more
+    // similar to triple-buffering. For now we hard-code Mailbox for perf tseting.
+    // TODO(jmadill): Properly select present mode and re-create display if changed.
+    VkPresentModeKHR bestChoice = VK_PRESENT_MODE_MAILBOX_KHR;
+
+    for (auto presentMode : presentModes)
+    {
+        if (presentMode == bestChoice)
+        {
+            return bestChoice;
+        }
+    }
+
+    ERR() << "Desired present mode not available. Falling back to " << presentModes[0];
+    return presentModes[0];
+}
+
+}  // namespace
+
+OffscreenSurfaceVk::OffscreenSurfaceVk(const egl::SurfaceState &surfaceState,
+                                       EGLint width,
+                                       EGLint height)
+    : SurfaceImpl(surfaceState), mWidth(width), mHeight(height)
+{
+}
+
+OffscreenSurfaceVk::~OffscreenSurfaceVk()
+{
+}
+
+egl::Error OffscreenSurfaceVk::initialize(const DisplayImpl *displayImpl)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+FramebufferImpl *OffscreenSurfaceVk::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+    // Use a user FBO for an offscreen RT.
+    return FramebufferVk::CreateUserFBO(state);
+}
+
+egl::Error OffscreenSurfaceVk::swap(const DisplayImpl *displayImpl)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error OffscreenSurfaceVk::postSubBuffer(EGLint /*x*/,
+                                             EGLint /*y*/,
+                                             EGLint /*width*/,
+                                             EGLint /*height*/)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error OffscreenSurfaceVk::querySurfacePointerANGLE(EGLint /*attribute*/, void ** /*value*/)
+{
+    UNREACHABLE();
+    return egl::Error(EGL_BAD_CURRENT_SURFACE);
+}
+
+egl::Error OffscreenSurfaceVk::bindTexImage(gl::Texture * /*texture*/, EGLint /*buffer*/)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error OffscreenSurfaceVk::releaseTexImage(EGLint /*buffer*/)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error OffscreenSurfaceVk::getSyncValues(EGLuint64KHR * /*ust*/,
+                                             EGLuint64KHR * /*msc*/,
+                                             EGLuint64KHR * /*sbc*/)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+void OffscreenSurfaceVk::setSwapInterval(EGLint /*interval*/)
+{
+}
+
+EGLint OffscreenSurfaceVk::getWidth() const
+{
+    return mWidth;
+}
+
+EGLint OffscreenSurfaceVk::getHeight() const
+{
+    return mHeight;
+}
+
+EGLint OffscreenSurfaceVk::isPostSubBufferSupported() const
+{
+    return EGL_FALSE;
+}
+
+EGLint OffscreenSurfaceVk::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+
+gl::Error OffscreenSurfaceVk::getAttachmentRenderTarget(
+    GLenum /*binding*/,
+    const gl::ImageIndex & /*imageIndex*/,
+    FramebufferAttachmentRenderTarget ** /*rtOut*/)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState,
+                                 EGLNativeWindowType window,
+                                 EGLint width,
+                                 EGLint height)
+    : SurfaceImpl(surfaceState),
+      mNativeWindowType(window),
+      mSurface(VK_NULL_HANDLE),
+      mInstance(VK_NULL_HANDLE),
+      mSwapchain(VK_NULL_HANDLE),
+      mRenderTarget(),
+      mCurrentSwapchainImageIndex(0)
+{
+    mRenderTarget.extents.width  = static_cast<GLint>(width);
+    mRenderTarget.extents.height = static_cast<GLint>(height);
+    mRenderTarget.extents.depth  = 1;
+    mRenderTarget.resource       = this;
+}
+
+WindowSurfaceVk::~WindowSurfaceVk()
+{
+    ASSERT(mSurface == VK_NULL_HANDLE);
+    ASSERT(mSwapchain == VK_NULL_HANDLE);
+}
+
+void WindowSurfaceVk::destroy(const DisplayImpl *displayImpl)
+{
+    const DisplayVk *displayVk = GetAs<DisplayVk>(displayImpl);
+    RendererVk *rendererVk     = displayVk->getRenderer();
+    VkDevice device            = rendererVk->getDevice();
+    VkInstance instance        = rendererVk->getInstance();
+
+    rendererVk->finish();
+
+    mImageAvailableSemaphore.destroy(device);
+    mRenderingCompleteSemaphore.destroy(device);
+
+    for (auto &imageView : mSwapchainImageViews)
+    {
+        imageView.destroy(device);
+    }
+
+    // Although we don't own the swapchain image handles, we need to keep our shutdown clean.
+    for (auto &image : mSwapchainImages)
+    {
+        image.reset();
+    }
+
+    for (auto &framebuffer : mSwapchainFramebuffers)
+    {
+        framebuffer.destroy(device);
+    }
+
+    if (mSwapchain)
+    {
+        vkDestroySwapchainKHR(device, mSwapchain, nullptr);
+        mSwapchain = VK_NULL_HANDLE;
+    }
+
+    if (mSurface)
+    {
+        vkDestroySurfaceKHR(instance, mSurface, nullptr);
+        mSurface = VK_NULL_HANDLE;
+    }
+}
+
+egl::Error WindowSurfaceVk::initialize(const DisplayImpl *displayImpl)
+{
+    const DisplayVk *displayVk = GetAs<DisplayVk>(displayImpl);
+    return initializeImpl(displayVk->getRenderer()).toEGL(EGL_BAD_SURFACE);
+}
+
+vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
+{
+    gl::Extents windowSize;
+    ANGLE_TRY_RESULT(createSurfaceVk(renderer), windowSize);
+
+    uint32_t presentQueue = 0;
+    ANGLE_TRY_RESULT(renderer->selectPresentQueueForSurface(mSurface), presentQueue);
+
+    const auto &physicalDevice = renderer->getPhysicalDevice();
+
+    VkSurfaceCapabilitiesKHR surfaceCaps;
+    ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, &surfaceCaps));
+
+    // Adjust width and height to the swapchain if necessary.
+    uint32_t width  = surfaceCaps.currentExtent.width;
+    uint32_t height = surfaceCaps.currentExtent.height;
+
+    // TODO(jmadill): Support devices which don't support copy. We use this for ReadPixels.
+    ANGLE_VK_CHECK((surfaceCaps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) != 0,
+                   VK_ERROR_INITIALIZATION_FAILED);
+
+    if (surfaceCaps.currentExtent.width == 0xFFFFFFFFu)
+    {
+        ASSERT(surfaceCaps.currentExtent.height == 0xFFFFFFFFu);
+
+        if (mRenderTarget.extents.width == 0)
+        {
+            width = windowSize.width;
+        }
+        if (mRenderTarget.extents.height == 0)
+        {
+            height = windowSize.height;
+        }
+    }
+
+    mRenderTarget.extents.width  = static_cast<int>(width);
+    mRenderTarget.extents.height = static_cast<int>(height);
+
+    uint32_t presentModeCount = 0;
+    ANGLE_VK_TRY(vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, mSurface,
+                                                           &presentModeCount, nullptr));
+    ASSERT(presentModeCount > 0);
+
+    std::vector<VkPresentModeKHR> presentModes(presentModeCount);
+    ANGLE_VK_TRY(vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, mSurface,
+                                                           &presentModeCount, presentModes.data()));
+
+    // Select appropriate present mode based on vsync parameter.
+    // TODO(jmadill): More complete implementation, which allows for changing and more values.
+    const EGLint minSwapInterval = mState.config->minSwapInterval;
+    const EGLint maxSwapInterval = mState.config->maxSwapInterval;
+    ASSERT(minSwapInterval == 0 || minSwapInterval == 1);
+    ASSERT(maxSwapInterval == 0 || maxSwapInterval == 1);
+
+    VkPresentModeKHR swapchainPresentMode =
+        GetDesiredPresentMode(presentModes, minSwapInterval, maxSwapInterval);
+
+    // Determine number of swapchain images. Aim for one more than the minimum.
+    uint32_t minImageCount = surfaceCaps.minImageCount + 1;
+    if (surfaceCaps.maxImageCount > 0 && minImageCount > surfaceCaps.maxImageCount)
+    {
+        minImageCount = surfaceCaps.maxImageCount;
+    }
+
+    // Default to identity transform.
+    VkSurfaceTransformFlagBitsKHR preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+    if ((surfaceCaps.supportedTransforms & preTransform) == 0)
+    {
+        preTransform = surfaceCaps.currentTransform;
+    }
+
+    uint32_t surfaceFormatCount = 0;
+    ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &surfaceFormatCount,
+                                                      nullptr));
+
+    std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);
+    ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &surfaceFormatCount,
+                                                      surfaceFormats.data()));
+
+    mRenderTarget.format = &GetVkFormatFromConfig(*mState.config);
+    auto nativeFormat    = mRenderTarget.format->native;
+
+    if (surfaceFormatCount == 1u && surfaceFormats[0].format == VK_FORMAT_UNDEFINED)
+    {
+        // This is fine.
+    }
+    else
+    {
+        bool foundFormat = false;
+        for (const auto &surfaceFormat : surfaceFormats)
+        {
+            if (surfaceFormat.format == nativeFormat)
+            {
+                foundFormat = true;
+                break;
+            }
+        }
+
+        ANGLE_VK_CHECK(foundFormat, VK_ERROR_INITIALIZATION_FAILED);
+    }
+
+    VkSwapchainCreateInfoKHR swapchainInfo;
+    swapchainInfo.sType              = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+    swapchainInfo.pNext              = nullptr;
+    swapchainInfo.flags              = 0;
+    swapchainInfo.surface            = mSurface;
+    swapchainInfo.minImageCount      = minImageCount;
+    swapchainInfo.imageFormat        = nativeFormat;
+    swapchainInfo.imageColorSpace    = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+    swapchainInfo.imageExtent.width  = width;
+    swapchainInfo.imageExtent.height = height;
+    swapchainInfo.imageArrayLayers   = 1;
+    swapchainInfo.imageUsage         = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+                                VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+    swapchainInfo.imageSharingMode      = VK_SHARING_MODE_EXCLUSIVE;
+    swapchainInfo.queueFamilyIndexCount = 0;
+    swapchainInfo.pQueueFamilyIndices   = nullptr;
+    swapchainInfo.preTransform          = preTransform;
+    swapchainInfo.compositeAlpha        = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+    swapchainInfo.presentMode           = swapchainPresentMode;
+    swapchainInfo.clipped               = VK_TRUE;
+    swapchainInfo.oldSwapchain          = VK_NULL_HANDLE;
+
+    const auto &device = renderer->getDevice();
+    ANGLE_VK_TRY(vkCreateSwapchainKHR(device, &swapchainInfo, nullptr, &mSwapchain));
+
+    // Intialize the swapchain image views.
+    uint32_t imageCount = 0;
+    ANGLE_VK_TRY(vkGetSwapchainImagesKHR(device, mSwapchain, &imageCount, nullptr));
+
+    std::vector<VkImage> swapchainImages(imageCount);
+    ANGLE_VK_TRY(vkGetSwapchainImagesKHR(device, mSwapchain, &imageCount, swapchainImages.data()));
+
+    // CommandBuffer is a singleton in the Renderer.
+    vk::CommandBuffer *commandBuffer = nullptr;
+    ANGLE_TRY(renderer->getStartedCommandBuffer(&commandBuffer));
+
+    VkClearColorValue transparentBlack;
+    transparentBlack.float32[0] = 0.0f;
+    transparentBlack.float32[1] = 0.0f;
+    transparentBlack.float32[2] = 0.0f;
+    transparentBlack.float32[3] = 0.0f;
+
+    mSwapchainImages.resize(imageCount);
+    mSwapchainImageViews.resize(imageCount);
+
+    for (uint32_t imageIndex = 0; imageIndex < imageCount; ++imageIndex)
+    {
+        VkImage swapchainImage = swapchainImages[imageIndex];
+
+        VkImageViewCreateInfo imageViewInfo;
+        imageViewInfo.sType                           = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+        imageViewInfo.pNext                           = nullptr;
+        imageViewInfo.flags                           = 0;
+        imageViewInfo.image                           = swapchainImage;
+        imageViewInfo.viewType                        = VK_IMAGE_VIEW_TYPE_2D;
+        imageViewInfo.format                          = nativeFormat;
+        imageViewInfo.components.r                    = VK_COMPONENT_SWIZZLE_R;
+        imageViewInfo.components.g                    = VK_COMPONENT_SWIZZLE_G;
+        imageViewInfo.components.b                    = VK_COMPONENT_SWIZZLE_B;
+        imageViewInfo.components.a                    = VK_COMPONENT_SWIZZLE_A;
+        imageViewInfo.subresourceRange.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
+        imageViewInfo.subresourceRange.baseMipLevel   = 0;
+        imageViewInfo.subresourceRange.levelCount     = 1;
+        imageViewInfo.subresourceRange.baseArrayLayer = 0;
+        imageViewInfo.subresourceRange.layerCount     = 1;
+
+        vk::Image image(swapchainImage);
+        vk::ImageView imageView;
+        ANGLE_TRY(imageView.init(device, imageViewInfo));
+
+        // Set transfer dest layout, and clear the image to black.
+        image.changeLayoutTop(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                              commandBuffer);
+        commandBuffer->clearSingleColorImage(image, transparentBlack);
+
+        mSwapchainImages[imageIndex].retain(device, std::move(image));
+        mSwapchainImageViews[imageIndex].retain(device, std::move(imageView));
+    }
+
+    ANGLE_TRY(renderer->submitAndFinishCommandBuffer(commandBuffer));
+
+    ANGLE_TRY(mImageAvailableSemaphore.init(device));
+    ANGLE_TRY(mRenderingCompleteSemaphore.init(device));
+
+    // Get the first available swapchain iamge.
+    ANGLE_TRY(nextSwapchainImage(renderer));
+
+    return vk::NoError();
+}
+
+FramebufferImpl *WindowSurfaceVk::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+    return FramebufferVk::CreateDefaultFBO(state, this);
+}
+
+egl::Error WindowSurfaceVk::swap(const DisplayImpl *displayImpl)
+{
+    const DisplayVk *displayVk = GetAs<DisplayVk>(displayImpl);
+    return swapImpl(displayVk->getRenderer()).toEGL(EGL_BAD_ALLOC);
+}
+
+vk::Error WindowSurfaceVk::swapImpl(RendererVk *renderer)
+{
+    vk::CommandBuffer *currentCB = nullptr;
+    ANGLE_TRY(renderer->getStartedCommandBuffer(&currentCB));
+
+    auto *image = &mSwapchainImages[mCurrentSwapchainImageIndex];
+
+    image->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+                                  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+                                  VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, currentCB);
+
+    ANGLE_TRY(renderer->submitCommandsWithSync(currentCB, mImageAvailableSemaphore,
+                                               mRenderingCompleteSemaphore));
+
+    VkPresentInfoKHR presentInfo;
+    presentInfo.sType              = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+    presentInfo.pNext              = nullptr;
+    presentInfo.waitSemaphoreCount = 1;
+    presentInfo.pWaitSemaphores    = mRenderingCompleteSemaphore.ptr();
+    presentInfo.swapchainCount     = 1;
+    presentInfo.pSwapchains        = &mSwapchain;
+    presentInfo.pImageIndices      = &mCurrentSwapchainImageIndex;
+    presentInfo.pResults           = nullptr;
+
+    ANGLE_VK_TRY(vkQueuePresentKHR(renderer->getQueue(), &presentInfo));
+
+    // Get the next available swapchain image.
+    ANGLE_TRY(nextSwapchainImage(renderer));
+
+    return vk::NoError();
+}
+
+vk::Error WindowSurfaceVk::nextSwapchainImage(RendererVk *renderer)
+{
+    VkDevice device = renderer->getDevice();
+
+    ANGLE_VK_TRY(vkAcquireNextImageKHR(device, mSwapchain, std::numeric_limits<uint64_t>::max(),
+                                       mImageAvailableSemaphore.getHandle(), VK_NULL_HANDLE,
+                                       &mCurrentSwapchainImageIndex));
+
+    // Update RenderTarget pointers.
+    mRenderTarget.image     = &mSwapchainImages[mCurrentSwapchainImageIndex];
+    mRenderTarget.imageView = &mSwapchainImageViews[mCurrentSwapchainImageIndex];
+
+    return vk::NoError();
+}
+
+egl::Error WindowSurfaceVk::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    // TODO(jmadill)
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceVk::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+    UNREACHABLE();
+    return egl::Error(EGL_BAD_CURRENT_SURFACE);
+}
+
+egl::Error WindowSurfaceVk::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceVk::releaseTexImage(EGLint buffer)
+{
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceVk::getSyncValues(EGLuint64KHR * /*ust*/,
+                                          EGLuint64KHR * /*msc*/,
+                                          EGLuint64KHR * /*sbc*/)
+{
+    UNIMPLEMENTED();
+    return egl::Error(EGL_BAD_ACCESS);
+}
+
+void WindowSurfaceVk::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint WindowSurfaceVk::getWidth() const
+{
+    return static_cast<EGLint>(mRenderTarget.extents.width);
+}
+
+EGLint WindowSurfaceVk::getHeight() const
+{
+    return static_cast<EGLint>(mRenderTarget.extents.height);
+}
+
+EGLint WindowSurfaceVk::isPostSubBufferSupported() const
+{
+    // TODO(jmadill)
+    return EGL_FALSE;
+}
+
+EGLint WindowSurfaceVk::getSwapBehavior() const
+{
+    // TODO(jmadill)
+    return EGL_BUFFER_DESTROYED;
+}
+
+gl::Error WindowSurfaceVk::getAttachmentRenderTarget(GLenum /*binding*/,
+                                                     const gl::ImageIndex & /*target*/,
+                                                     FramebufferAttachmentRenderTarget **rtOut)
+{
+    *rtOut = &mRenderTarget;
+    return gl::NoError();
+}
+
+gl::ErrorOrResult<vk::Framebuffer *> WindowSurfaceVk::getCurrentFramebuffer(
+    VkDevice device,
+    const vk::RenderPass &compatibleRenderPass)
+{
+    if (!mSwapchainFramebuffers.empty())
+    {
+        // Validation layers should detect if the render pass is really compatible.
+        return &mSwapchainFramebuffers[mCurrentSwapchainImageIndex];
+    }
+
+    VkFramebufferCreateInfo framebufferInfo;
+
+    // TODO(jmadill): Depth/Stencil attachments.
+    framebufferInfo.sType           = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+    framebufferInfo.pNext           = nullptr;
+    framebufferInfo.flags           = 0;
+    framebufferInfo.renderPass      = compatibleRenderPass.getHandle();
+    framebufferInfo.attachmentCount = 1u;
+    framebufferInfo.pAttachments    = nullptr;
+    framebufferInfo.width           = static_cast<uint32_t>(mRenderTarget.extents.width);
+    framebufferInfo.height          = static_cast<uint32_t>(mRenderTarget.extents.height);
+    framebufferInfo.layers          = 1;
+
+    mSwapchainFramebuffers.resize(mSwapchainImageViews.size());
+    for (size_t imageIndex = 0; imageIndex < mSwapchainFramebuffers.size(); ++imageIndex)
+    {
+        const auto &imageView        = mSwapchainImageViews[imageIndex];
+        VkImageView imageViewHandle  = imageView.getHandle();
+        framebufferInfo.pAttachments = &imageViewHandle;
+
+        vk::Framebuffer framebuffer;
+        ANGLE_TRY(framebuffer.init(device, framebufferInfo));
+
+        mSwapchainFramebuffers[imageIndex].retain(device, std::move(framebuffer));
+    }
+
+    // We should only initialize framebuffers on the first swap.
+    ASSERT(mCurrentSwapchainImageIndex == 0u);
+    return &mSwapchainFramebuffers[mCurrentSwapchainImageIndex];
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h
new file mode 100644
index 0000000..e42696b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h
@@ -0,0 +1,116 @@
+//
+// Copyright 2016 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.
+//
+// SurfaceVk.h:
+//    Defines the class interface for SurfaceVk, implementing SurfaceImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
+#define LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
+
+#include <vulkan/vulkan.h>
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
+#include "libANGLE/renderer/vulkan/renderervk_utils.h"
+
+namespace rx
+{
+class RendererVk;
+
+class OffscreenSurfaceVk : public SurfaceImpl
+{
+  public:
+    OffscreenSurfaceVk(const egl::SurfaceState &surfaceState, EGLint width, EGLint height);
+    ~OffscreenSurfaceVk() override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+    void setSwapInterval(EGLint interval) override;
+
+    // width and height can change with client window resizing
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+    gl::Error getAttachmentRenderTarget(GLenum binding,
+                                        const gl::ImageIndex &imageIndex,
+                                        FramebufferAttachmentRenderTarget **rtOut) override;
+
+  private:
+    EGLint mWidth;
+    EGLint mHeight;
+};
+
+class WindowSurfaceVk : public SurfaceImpl, public ResourceVk
+{
+  public:
+    WindowSurfaceVk(const egl::SurfaceState &surfaceState,
+                    EGLNativeWindowType window,
+                    EGLint width,
+                    EGLint height);
+    ~WindowSurfaceVk() override;
+
+    void destroy(const DisplayImpl *contextImpl) override;
+
+    egl::Error initialize(const DisplayImpl *displayImpl) override;
+    FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+    egl::Error swap(const DisplayImpl *displayImpl) override;
+    egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+    egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+    egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+    egl::Error releaseTexImage(EGLint buffer) override;
+    egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+    void setSwapInterval(EGLint interval) override;
+
+    // width and height can change with client window resizing
+    EGLint getWidth() const override;
+    EGLint getHeight() const override;
+
+    EGLint isPostSubBufferSupported() const override;
+    EGLint getSwapBehavior() const override;
+
+    gl::Error getAttachmentRenderTarget(GLenum binding,
+                                        const gl::ImageIndex &imageIndex,
+                                        FramebufferAttachmentRenderTarget **rtOut) override;
+
+    gl::ErrorOrResult<vk::Framebuffer *> getCurrentFramebuffer(
+        VkDevice device,
+        const vk::RenderPass &compatibleRenderPass);
+
+  protected:
+    EGLNativeWindowType mNativeWindowType;
+    VkSurfaceKHR mSurface;
+    VkInstance mInstance;
+
+  private:
+    virtual vk::ErrorOrResult<gl::Extents> createSurfaceVk(RendererVk *renderer) = 0;
+    vk::Error initializeImpl(RendererVk *renderer);
+    vk::Error nextSwapchainImage(RendererVk *renderer);
+    vk::Error swapImpl(RendererVk *renderer);
+
+    VkSwapchainKHR mSwapchain;
+
+    RenderTargetVk mRenderTarget;
+    vk::Semaphore mImageAvailableSemaphore;
+    vk::Semaphore mRenderingCompleteSemaphore;
+
+    uint32_t mCurrentSwapchainImageIndex;
+    std::vector<vk::Image> mSwapchainImages;
+    std::vector<vk::ImageView> mSwapchainImageViews;
+    std::vector<vk::Framebuffer> mSwapchainFramebuffers;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
new file mode 100644
index 0000000..7c3bf4b
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -0,0 +1,169 @@
+//
+// Copyright 2016 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.
+//
+// TextureVk.cpp:
+//    Implements the class methods for TextureVk.
+//
+
+#include "libANGLE/renderer/vulkan/TextureVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+TextureVk::TextureVk(const gl::TextureState &state) : TextureImpl(state)
+{
+}
+
+TextureVk::~TextureVk()
+{
+}
+
+gl::Error TextureVk::setImage(ContextImpl *contextImpl,
+                              GLenum target,
+                              size_t level,
+                              GLenum internalFormat,
+                              const gl::Extents &size,
+                              GLenum format,
+                              GLenum type,
+                              const gl::PixelUnpackState &unpack,
+                              const uint8_t *pixels)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setSubImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 const gl::Box &area,
+                                 GLenum format,
+                                 GLenum type,
+                                 const gl::PixelUnpackState &unpack,
+                                 const uint8_t *pixels)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setCompressedImage(ContextImpl *contextImpl,
+                                        GLenum target,
+                                        size_t level,
+                                        GLenum internalFormat,
+                                        const gl::Extents &size,
+                                        const gl::PixelUnpackState &unpack,
+                                        size_t imageSize,
+                                        const uint8_t *pixels)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setCompressedSubImage(ContextImpl *contextImpl,
+                                           GLenum target,
+                                           size_t level,
+                                           const gl::Box &area,
+                                           GLenum format,
+                                           const gl::PixelUnpackState &unpack,
+                                           size_t imageSize,
+                                           const uint8_t *pixels)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::copyImage(ContextImpl *contextImpl,
+                               GLenum target,
+                               size_t level,
+                               const gl::Rectangle &sourceArea,
+                               GLenum internalFormat,
+                               const gl::Framebuffer *source)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::copySubImage(ContextImpl *contextImpl,
+                                  GLenum target,
+                                  size_t level,
+                                  const gl::Offset &destOffset,
+                                  const gl::Rectangle &sourceArea,
+                                  const gl::Framebuffer *source)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setStorage(ContextImpl *contextImpl,
+                                GLenum target,
+                                size_t levels,
+                                GLenum internalFormat,
+                                const gl::Extents &size)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setImageExternal(GLenum target,
+                                      egl::Stream *stream,
+                                      const egl::Stream::GLTextureDescription &desc)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::generateMipmap(ContextImpl *contextImpl)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+void TextureVk::setBaseLevel(GLuint baseLevel)
+{
+    UNIMPLEMENTED();
+}
+
+void TextureVk::bindTexImage(egl::Surface *surface)
+{
+    UNIMPLEMENTED();
+}
+
+void TextureVk::releaseTexImage()
+{
+    UNIMPLEMENTED();
+}
+
+gl::Error TextureVk::getAttachmentRenderTarget(GLenum binding,
+                                               const gl::ImageIndex &imageIndex,
+                                               FramebufferAttachmentRenderTarget **rtOut)
+{
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+void TextureVk::syncState(const gl::Texture::DirtyBits &dirtyBits)
+{
+    UNIMPLEMENTED();
+}
+
+gl::Error TextureVk::setStorageMultisample(ContextImpl *contextImpl,
+                                           GLenum target,
+                                           GLsizei samples,
+                                           GLint internalformat,
+                                           const gl::Extents &size,
+                                           GLboolean fixedSampleLocations)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError() << "setStorageMultisample is unimplemented.";
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.h
new file mode 100644
index 0000000..4ad6a30
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -0,0 +1,107 @@
+//
+// Copyright 2016 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.
+//
+// TextureVk.h:
+//    Defines the class interface for TextureVk, implementing TextureImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
+#define LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
+
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace rx
+{
+
+class TextureVk : public TextureImpl
+{
+  public:
+    TextureVk(const gl::TextureState &state);
+    ~TextureVk() override;
+
+    gl::Error setImage(ContextImpl *contextImpl,
+                       GLenum target,
+                       size_t level,
+                       GLenum internalFormat,
+                       const gl::Extents &size,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels) override;
+    gl::Error setSubImage(ContextImpl *contextImpl,
+                          GLenum target,
+                          size_t level,
+                          const gl::Box &area,
+                          GLenum format,
+                          GLenum type,
+                          const gl::PixelUnpackState &unpack,
+                          const uint8_t *pixels) override;
+
+    gl::Error setCompressedImage(ContextImpl *contextImpl,
+                                 GLenum target,
+                                 size_t level,
+                                 GLenum internalFormat,
+                                 const gl::Extents &size,
+                                 const gl::PixelUnpackState &unpack,
+                                 size_t imageSize,
+                                 const uint8_t *pixels) override;
+    gl::Error setCompressedSubImage(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    size_t level,
+                                    const gl::Box &area,
+                                    GLenum format,
+                                    const gl::PixelUnpackState &unpack,
+                                    size_t imageSize,
+                                    const uint8_t *pixels) override;
+
+    gl::Error copyImage(ContextImpl *contextImpl,
+                        GLenum target,
+                        size_t level,
+                        const gl::Rectangle &sourceArea,
+                        GLenum internalFormat,
+                        const gl::Framebuffer *source) override;
+    gl::Error copySubImage(ContextImpl *contextImpl,
+                           GLenum target,
+                           size_t level,
+                           const gl::Offset &destOffset,
+                           const gl::Rectangle &sourceArea,
+                           const gl::Framebuffer *source) override;
+
+    gl::Error setStorage(ContextImpl *contextImpl,
+                         GLenum target,
+                         size_t levels,
+                         GLenum internalFormat,
+                         const gl::Extents &size) override;
+
+    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+    gl::Error setImageExternal(GLenum target,
+                               egl::Stream *stream,
+                               const egl::Stream::GLTextureDescription &desc) override;
+
+    gl::Error generateMipmap(ContextImpl *contextImpl) override;
+
+    void setBaseLevel(GLuint baseLevel) override;
+
+    void bindTexImage(egl::Surface *surface) override;
+    void releaseTexImage() override;
+
+    gl::Error getAttachmentRenderTarget(GLenum binding,
+                                        const gl::ImageIndex &imageIndex,
+                                        FramebufferAttachmentRenderTarget **rtOut) override;
+
+    void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+
+    gl::Error setStorageMultisample(ContextImpl *contextImpl,
+                                    GLenum target,
+                                    GLsizei samples,
+                                    GLint internalformat,
+                                    const gl::Extents &size,
+                                    GLboolean fixedSampleLocations) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
new file mode 100644
index 0000000..ea445c7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
@@ -0,0 +1,57 @@
+//
+// Copyright 2016 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.
+//
+// TransformFeedbackVk.cpp:
+//    Implements the class methods for TransformFeedbackVk.
+//
+
+#include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+TransformFeedbackVk::TransformFeedbackVk(const gl::TransformFeedbackState &state)
+    : TransformFeedbackImpl(state)
+{
+}
+
+TransformFeedbackVk::~TransformFeedbackVk()
+{
+}
+
+void TransformFeedbackVk::begin(GLenum primitiveMode)
+{
+    UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::end()
+{
+    UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::pause()
+{
+    UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::resume()
+{
+    UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+{
+    UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::bindIndexedBuffer(size_t index,
+                                            const OffsetBindingPointer<gl::Buffer> &binding)
+{
+    UNIMPLEMENTED();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h
new file mode 100644
index 0000000..ed8522c
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 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.
+//
+// TransformFeedbackVk.h:
+//    Defines the class interface for TransformFeedbackVk, implementing TransformFeedbackImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_TRANSFORMFEEDBACKVK_H_
+#define LIBANGLE_RENDERER_VULKAN_TRANSFORMFEEDBACKVK_H_
+
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class TransformFeedbackVk : public TransformFeedbackImpl
+{
+  public:
+    TransformFeedbackVk(const gl::TransformFeedbackState &state);
+    ~TransformFeedbackVk() override;
+
+    void begin(GLenum primitiveMode) override;
+    void end() override;
+    void pause() override;
+    void resume() override;
+
+    void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
+    void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_TRANSFORMFEEDBACKVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
new file mode 100644
index 0000000..e835be7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright 2016 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.
+//
+// VertexArrayVk.cpp:
+//    Implements the class methods for VertexArrayVk.
+//
+
+#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
+
+#include "common/debug.h"
+
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+
+namespace rx
+{
+
+VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &data) : VertexArrayImpl(data)
+{
+}
+
+VertexArrayVk::~VertexArrayVk()
+{
+}
+
+void VertexArrayVk::syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits)
+{
+    ASSERT(dirtyBits.any());
+
+    // TODO(jmadill): Use pipeline cache.
+    auto contextVk = GetAs<ContextVk>(contextImpl);
+    contextVk->invalidateCurrentPipeline();
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h
new file mode 100644
index 0000000..7592bc0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h
@@ -0,0 +1,29 @@
+//
+// Copyright 2016 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.
+//
+// VertexArrayVk.h:
+//    Defines the class interface for VertexArrayVk, implementing VertexArrayImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
+#define LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
+
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace rx
+{
+
+class VertexArrayVk : public VertexArrayImpl
+{
+  public:
+    VertexArrayVk(const gl::VertexArrayState &data);
+    ~VertexArrayVk() override;
+
+    void syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/formatutilsvk.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/formatutilsvk.cpp
new file mode 100644
index 0000000..5018044
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/formatutilsvk.cpp
@@ -0,0 +1,311 @@
+//
+// Copyright 2016 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.
+//
+// formatutilsvk:
+//   Helper for Vulkan format code.
+
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+
+#include "libANGLE/renderer/load_functions_table.h"
+
+namespace rx
+{
+
+namespace vk
+{
+
+const angle::Format &Format::format() const
+{
+    return angle::Format::Get(formatID);
+}
+
+LoadFunctionMap Format::getLoadFunctions() const
+{
+    return GetLoadFunctionsMap(internalFormat, formatID);
+}
+
+// TODO(jmadill): This is temporary. Figure out how to handle format conversions.
+VkFormat GetNativeVertexFormat(gl::VertexFormatType vertexFormat)
+{
+    switch (vertexFormat)
+    {
+        case gl::VERTEX_FORMAT_INVALID:
+            UNREACHABLE();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE1:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE1_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE2:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE2_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE3:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE3_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE4:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE4_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE1:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE1_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE2:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE2_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE3:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE3_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE4:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE4_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT1:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT1_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT2:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT2_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT3:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT3_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT4:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT4_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT1:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT1_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT2:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT2_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT3:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT3_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT4:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT4_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT1:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT1_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT2:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT2_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT3:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT3_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT4:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT4_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT1:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT1_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT2:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT2_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT3:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT3_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT4:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT4_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE1_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE2_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE3_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SBYTE4_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE1_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE2_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE3_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UBYTE4_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT1_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT2_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT3_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SSHORT4_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT1_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT2_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT3_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_USHORT4_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT1_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT2_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT3_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT4_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT1_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT2_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT3_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT4_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_FIXED1:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_FIXED2:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_FIXED3:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_FIXED4:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_HALF1:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_HALF2:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_HALF3:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_HALF4:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_FLOAT1:
+            return VK_FORMAT_R32_SFLOAT;
+        case gl::VERTEX_FORMAT_FLOAT2:
+            return VK_FORMAT_R32G32_SFLOAT;
+        case gl::VERTEX_FORMAT_FLOAT3:
+            return VK_FORMAT_R32G32B32_SFLOAT;
+        case gl::VERTEX_FORMAT_FLOAT4:
+            return VK_FORMAT_R32G32B32A32_SFLOAT;
+        case gl::VERTEX_FORMAT_SINT210:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT210:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT210_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT210_NORM:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_SINT210_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        case gl::VERTEX_FORMAT_UINT210_INT:
+            UNIMPLEMENTED();
+            return VK_FORMAT_UNDEFINED;
+        default:
+            UNREACHABLE();
+            return VK_FORMAT_UNDEFINED;
+    }
+}
+
+}  // namespace vk
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/formatutilsvk.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/formatutilsvk.h
new file mode 100644
index 0000000..7dae0ef
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/formatutilsvk.h
@@ -0,0 +1,59 @@
+//
+// Copyright 2016 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.
+//
+// Vk::Format:
+//   Vulkan implementation of a storage format.
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FORMAT_H_
+#define LIBANGLE_RENDERER_VULKAN_FORMAT_H_
+
+#include <vulkan/vulkan.h>
+
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+
+namespace vk
+{
+
+struct Format final : private angle::NonCopyable
+{
+    constexpr Format(GLenum internalFormat,
+                     angle::Format::ID formatID,
+                     VkFormat native,
+                     InitializeTextureDataFunction initFunction);
+
+    static const Format &Get(GLenum internalFormat);
+
+    const angle::Format &format() const;
+    LoadFunctionMap getLoadFunctions() const;
+
+    GLenum internalFormat;
+    angle::Format::ID formatID;
+    VkFormat native;
+    InitializeTextureDataFunction dataInitializerFunction;
+};
+
+constexpr Format::Format(GLenum internalFormat,
+                         angle::Format::ID formatID,
+                         VkFormat native,
+                         InitializeTextureDataFunction initFunction)
+    : internalFormat(internalFormat),
+      formatID(formatID),
+      native(native),
+      dataInitializerFunction(initFunction)
+{
+}
+
+// TODO(jmadill): This is temporary. Figure out how to handle format conversions.
+VkFormat GetNativeVertexFormat(gl::VertexFormatType vertexFormat);
+
+}  // namespace vk
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_FORMAT_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/gen_vk_format_table.py b/src/third_party/angle/src/libANGLE/renderer/vulkan/gen_vk_format_table.py
new file mode 100644
index 0000000..38e7c58
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/gen_vk_format_table.py
@@ -0,0 +1,123 @@
+#!/usr/bin/python
+# Copyright 2016 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.
+#
+# gen_vk_format_table.py:
+#  Code generation for vk format map
+
+from datetime import date
+import json
+import math
+import pprint
+import os
+import re
+import sys
+
+sys.path.append('..')
+import angle_format
+
+template_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {input_file_name}
+//
+// Copyright {copyright_year} 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.
+//
+// {out_file_name}:
+//   Queries for full Vulkan format information based on GL format.
+
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+using namespace angle;
+
+namespace rx
+{{
+
+namespace vk
+{{
+
+// static
+const Format &Format::Get(GLenum internalFormat)
+{{
+    // clang-format off
+    switch (internalFormat)
+    {{
+{format_case_data}
+        default:
+            break;
+    }}
+    // clang-format on
+
+    UNREACHABLE();
+    static const Format noInfo(GL_NONE, angle::Format::ID::NONE, VK_FORMAT_UNDEFINED, nullptr);
+    return noInfo;
+}}
+
+}}  // namespace vk
+
+}}  // namespace rx
+"""
+
+format_entry_template = """{space}{{
+{space}    static constexpr Format info({internalFormat},
+{space}                                 angle::Format::ID::{formatName},
+{space}                                 {vkFormat},
+{space}                                 {initializer});
+{space}    return info;
+{space}}}
+"""
+
+def parse_format_case(internal_format, format_name, native_format):
+
+    table_data = ""
+
+    parsed = {
+        "space": "        ",
+        "internalFormat": internal_format,
+        "formatName": format_name,
+        "vkFormat": native_format,
+    }
+
+    # Derived values.
+    parsed["initializer"] = angle_format.get_internal_format_initializer(
+        internal_format, format_name)
+
+    return format_entry_template.format(**parsed)
+
+def parse_json_into_cases(json_map, vk_map):
+    table_data = ''
+
+    for internal_format, format_name in sorted(json_map.iteritems()):
+
+        if format_name not in vk_map:
+            continue
+
+        native_format = vk_map[format_name]
+
+        table_data += '        case ' + internal_format + ':\n'
+        table_data += parse_format_case(internal_format, format_name, native_format)
+
+    return table_data
+
+input_file_name = 'vk_format_map.json'
+out_file_name = 'vk_format_table'
+
+json_map = angle_format.load_without_override()
+vk_map = angle_format.load_json(input_file_name)
+
+format_case_data = parse_json_into_cases(json_map, vk_map)
+output_cpp = template_table_autogen_cpp.format(
+    copyright_year = date.today().year,
+    format_case_data = format_case_data,
+    script_name = __file__,
+    out_file_name = out_file_name,
+    input_file_name = input_file_name)
+
+with open(out_file_name + '_autogen.cpp', 'wt') as out_file:
+    out_file.write(output_cpp)
+    out_file.close()
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/renderervk_utils.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/renderervk_utils.cpp
new file mode 100644
index 0000000..2b5b1a0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/renderervk_utils.cpp
@@ -0,0 +1,965 @@
+//
+// Copyright 2016 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.
+//
+// renderervk_utils:
+//    Helper functions for the Vulkan Renderer.
+//
+
+#include "renderervk_utils.h"
+
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+
+namespace rx
+{
+
+namespace
+{
+GLenum DefaultGLErrorCode(VkResult result)
+{
+    switch (result)
+    {
+        case VK_ERROR_OUT_OF_HOST_MEMORY:
+        case VK_ERROR_OUT_OF_DEVICE_MEMORY:
+        case VK_ERROR_TOO_MANY_OBJECTS:
+            return GL_OUT_OF_MEMORY;
+        default:
+            return GL_INVALID_OPERATION;
+    }
+}
+
+EGLint DefaultEGLErrorCode(VkResult result)
+{
+    switch (result)
+    {
+        case VK_ERROR_OUT_OF_HOST_MEMORY:
+        case VK_ERROR_OUT_OF_DEVICE_MEMORY:
+        case VK_ERROR_TOO_MANY_OBJECTS:
+            return EGL_BAD_ALLOC;
+        case VK_ERROR_INITIALIZATION_FAILED:
+            return EGL_NOT_INITIALIZED;
+        case VK_ERROR_SURFACE_LOST_KHR:
+        case VK_ERROR_DEVICE_LOST:
+            return EGL_CONTEXT_LOST;
+        default:
+            return EGL_BAD_ACCESS;
+    }
+}
+
+// Gets access flags that are common between source and dest layouts.
+VkAccessFlags GetBasicLayoutAccessFlags(VkImageLayout layout)
+{
+    switch (layout)
+    {
+        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+            return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+            return VK_ACCESS_TRANSFER_WRITE_BIT;
+        case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
+            return VK_ACCESS_MEMORY_READ_BIT;
+        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+            return VK_ACCESS_TRANSFER_READ_BIT;
+        case VK_IMAGE_LAYOUT_UNDEFINED:
+        case VK_IMAGE_LAYOUT_GENERAL:
+            return 0;
+        default:
+            // TODO(jmadill): Investigate other flags.
+            UNREACHABLE();
+            return 0;
+    }
+}
+}  // anonymous namespace
+
+// Mirrors std_validation_str in loader.h
+// TODO(jmadill): Possibly wrap the loader into a safe source file. Can't be included trivially.
+const char *g_VkStdValidationLayerName = "VK_LAYER_LUNARG_standard_validation";
+
+const char *VulkanResultString(VkResult result)
+{
+    switch (result)
+    {
+        case VK_SUCCESS:
+            return "Command successfully completed.";
+        case VK_NOT_READY:
+            return "A fence or query has not yet completed.";
+        case VK_TIMEOUT:
+            return "A wait operation has not completed in the specified time.";
+        case VK_EVENT_SET:
+            return "An event is signaled.";
+        case VK_EVENT_RESET:
+            return "An event is unsignaled.";
+        case VK_INCOMPLETE:
+            return "A return array was too small for the result.";
+        case VK_SUBOPTIMAL_KHR:
+            return "A swapchain no longer matches the surface properties exactly, but can still be "
+                   "used to present to the surface successfully.";
+        case VK_ERROR_OUT_OF_HOST_MEMORY:
+            return "A host memory allocation has failed.";
+        case VK_ERROR_OUT_OF_DEVICE_MEMORY:
+            return "A device memory allocation has failed.";
+        case VK_ERROR_INITIALIZATION_FAILED:
+            return "Initialization of an object could not be completed for implementation-specific "
+                   "reasons.";
+        case VK_ERROR_DEVICE_LOST:
+            return "The logical or physical device has been lost.";
+        case VK_ERROR_MEMORY_MAP_FAILED:
+            return "Mapping of a memory object has failed.";
+        case VK_ERROR_LAYER_NOT_PRESENT:
+            return "A requested layer is not present or could not be loaded.";
+        case VK_ERROR_EXTENSION_NOT_PRESENT:
+            return "A requested extension is not supported.";
+        case VK_ERROR_FEATURE_NOT_PRESENT:
+            return "A requested feature is not supported.";
+        case VK_ERROR_INCOMPATIBLE_DRIVER:
+            return "The requested version of Vulkan is not supported by the driver or is otherwise "
+                   "incompatible for implementation-specific reasons.";
+        case VK_ERROR_TOO_MANY_OBJECTS:
+            return "Too many objects of the type have already been created.";
+        case VK_ERROR_FORMAT_NOT_SUPPORTED:
+            return "A requested format is not supported on this device.";
+        case VK_ERROR_SURFACE_LOST_KHR:
+            return "A surface is no longer available.";
+        case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
+            return "The requested window is already connected to a VkSurfaceKHR, or to some other "
+                   "non-Vulkan API.";
+        case VK_ERROR_OUT_OF_DATE_KHR:
+            return "A surface has changed in such a way that it is no longer compatible with the "
+                   "swapchain.";
+        case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
+            return "The display used by a swapchain does not use the same presentable image "
+                   "layout, or is incompatible in a way that prevents sharing an image.";
+        case VK_ERROR_VALIDATION_FAILED_EXT:
+            return "The validation layers detected invalid API usage.";
+        default:
+            return "Unknown vulkan error code.";
+    }
+}
+
+bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps)
+{
+    for (const auto &layerProp : layerProps)
+    {
+        if (std::string(layerProp.layerName) == g_VkStdValidationLayerName)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+namespace vk
+{
+
+Error::Error(VkResult result) : mResult(result), mFile(nullptr), mLine(0)
+{
+    ASSERT(result == VK_SUCCESS);
+}
+
+Error::Error(VkResult result, const char *file, unsigned int line)
+    : mResult(result), mFile(file), mLine(line)
+{
+}
+
+Error::~Error()
+{
+}
+
+Error::Error(const Error &other) = default;
+Error &Error::operator=(const Error &other) = default;
+
+gl::Error Error::toGL(GLenum glErrorCode) const
+{
+    if (!isError())
+    {
+        return gl::NoError();
+    }
+
+    // TODO(jmadill): Set extended error code to 'vulkan internal error'.
+    const std::string &message = toString();
+    return gl::Error(glErrorCode, message.c_str());
+}
+
+egl::Error Error::toEGL(EGLint eglErrorCode) const
+{
+    if (!isError())
+    {
+        return egl::Error(EGL_SUCCESS);
+    }
+
+    // TODO(jmadill): Set extended error code to 'vulkan internal error'.
+    const std::string &message = toString();
+    return egl::Error(eglErrorCode, message.c_str());
+}
+
+std::string Error::toString() const
+{
+    std::stringstream errorStream;
+    errorStream << "Internal Vulkan error: " << VulkanResultString(mResult) << ", in " << mFile
+                << ", line " << mLine << ".";
+    return errorStream.str();
+}
+
+Error::operator gl::Error() const
+{
+    return toGL(DefaultGLErrorCode(mResult));
+}
+
+Error::operator egl::Error() const
+{
+    return toEGL(DefaultEGLErrorCode(mResult));
+}
+
+bool Error::isError() const
+{
+    return (mResult != VK_SUCCESS);
+}
+
+// CommandPool implementation.
+CommandPool::CommandPool()
+{
+}
+
+void CommandPool::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkDestroyCommandPool(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error CommandPool::init(VkDevice device, const VkCommandPoolCreateInfo &createInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(vkCreateCommandPool(device, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+// CommandBuffer implementation.
+CommandBuffer::CommandBuffer() : mStarted(false), mCommandPool(nullptr)
+{
+}
+
+void CommandBuffer::setCommandPool(CommandPool *commandPool)
+{
+    ASSERT(!mCommandPool && commandPool->valid());
+    mCommandPool = commandPool;
+}
+
+Error CommandBuffer::begin(VkDevice device)
+{
+    if (mStarted)
+    {
+        return NoError();
+    }
+
+    if (mHandle == VK_NULL_HANDLE)
+    {
+        VkCommandBufferAllocateInfo commandBufferInfo;
+        commandBufferInfo.sType              = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+        commandBufferInfo.pNext              = nullptr;
+        commandBufferInfo.commandPool        = mCommandPool->getHandle();
+        commandBufferInfo.level              = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+        commandBufferInfo.commandBufferCount = 1;
+
+        ANGLE_VK_TRY(vkAllocateCommandBuffers(device, &commandBufferInfo, &mHandle));
+    }
+    else
+    {
+        reset();
+    }
+
+    mStarted = true;
+
+    VkCommandBufferBeginInfo beginInfo;
+    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+    beginInfo.pNext = nullptr;
+    // TODO(jmadill): Use other flags?
+    beginInfo.flags            = 0;
+    beginInfo.pInheritanceInfo = nullptr;
+
+    ANGLE_VK_TRY(vkBeginCommandBuffer(mHandle, &beginInfo));
+
+    return NoError();
+}
+
+Error CommandBuffer::end()
+{
+    mStarted = false;
+
+    ASSERT(valid());
+    ANGLE_VK_TRY(vkEndCommandBuffer(mHandle));
+    return NoError();
+}
+
+Error CommandBuffer::reset()
+{
+    mStarted = false;
+
+    ASSERT(valid());
+    ANGLE_VK_TRY(vkResetCommandBuffer(mHandle, 0));
+    return NoError();
+}
+
+void CommandBuffer::singleImageBarrier(VkPipelineStageFlags srcStageMask,
+                                       VkPipelineStageFlags dstStageMask,
+                                       VkDependencyFlags dependencyFlags,
+                                       const VkImageMemoryBarrier &imageMemoryBarrier)
+{
+    ASSERT(valid());
+    vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, dependencyFlags, 0, nullptr, 0,
+                         nullptr, 1, &imageMemoryBarrier);
+}
+
+void CommandBuffer::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        ASSERT(mCommandPool && mCommandPool->valid());
+        vkFreeCommandBuffers(device, mCommandPool->getHandle(), 1, &mHandle);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+void CommandBuffer::clearSingleColorImage(const vk::Image &image, const VkClearColorValue &color)
+{
+    ASSERT(valid());
+    ASSERT(image.getCurrentLayout() == VK_IMAGE_LAYOUT_GENERAL ||
+           image.getCurrentLayout() == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+
+    VkImageSubresourceRange range;
+    range.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
+    range.baseMipLevel   = 0;
+    range.levelCount     = 1;
+    range.baseArrayLayer = 0;
+    range.layerCount     = 1;
+
+    vkCmdClearColorImage(mHandle, image.getHandle(), image.getCurrentLayout(), &color, 1, &range);
+}
+
+void CommandBuffer::copySingleImage(const vk::Image &srcImage,
+                                    const vk::Image &destImage,
+                                    const gl::Box &copyRegion,
+                                    VkImageAspectFlags aspectMask)
+{
+    ASSERT(valid());
+    ASSERT(srcImage.getCurrentLayout() == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
+           srcImage.getCurrentLayout() == VK_IMAGE_LAYOUT_GENERAL);
+    ASSERT(destImage.getCurrentLayout() == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
+           destImage.getCurrentLayout() == VK_IMAGE_LAYOUT_GENERAL);
+
+    VkImageCopy region;
+    region.srcSubresource.aspectMask     = aspectMask;
+    region.srcSubresource.mipLevel       = 0;
+    region.srcSubresource.baseArrayLayer = 0;
+    region.srcSubresource.layerCount     = 1;
+    region.srcOffset.x                   = copyRegion.x;
+    region.srcOffset.y                   = copyRegion.y;
+    region.srcOffset.z                   = copyRegion.z;
+    region.dstSubresource.aspectMask     = aspectMask;
+    region.dstSubresource.mipLevel       = 0;
+    region.dstSubresource.baseArrayLayer = 0;
+    region.dstSubresource.layerCount     = 1;
+    region.dstOffset.x                   = copyRegion.x;
+    region.dstOffset.y                   = copyRegion.y;
+    region.dstOffset.z                   = copyRegion.z;
+    region.extent.width                  = copyRegion.width;
+    region.extent.height                 = copyRegion.height;
+    region.extent.depth                  = copyRegion.depth;
+
+    vkCmdCopyImage(mHandle, srcImage.getHandle(), srcImage.getCurrentLayout(),
+                   destImage.getHandle(), destImage.getCurrentLayout(), 1, &region);
+}
+
+void CommandBuffer::beginRenderPass(const RenderPass &renderPass,
+                                    const Framebuffer &framebuffer,
+                                    const gl::Rectangle &renderArea,
+                                    const std::vector<VkClearValue> &clearValues)
+{
+    ASSERT(!clearValues.empty());
+    ASSERT(mHandle != VK_NULL_HANDLE);
+
+    VkRenderPassBeginInfo beginInfo;
+    beginInfo.sType                    = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+    beginInfo.pNext                    = nullptr;
+    beginInfo.renderPass               = renderPass.getHandle();
+    beginInfo.framebuffer              = framebuffer.getHandle();
+    beginInfo.renderArea.offset.x      = static_cast<uint32_t>(renderArea.x);
+    beginInfo.renderArea.offset.y      = static_cast<uint32_t>(renderArea.y);
+    beginInfo.renderArea.extent.width  = static_cast<uint32_t>(renderArea.width);
+    beginInfo.renderArea.extent.height = static_cast<uint32_t>(renderArea.height);
+    beginInfo.clearValueCount          = static_cast<uint32_t>(clearValues.size());
+    beginInfo.pClearValues             = clearValues.data();
+
+    vkCmdBeginRenderPass(mHandle, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
+}
+
+void CommandBuffer::endRenderPass()
+{
+    ASSERT(mHandle != VK_NULL_HANDLE);
+    vkCmdEndRenderPass(mHandle);
+}
+
+void CommandBuffer::draw(uint32_t vertexCount,
+                         uint32_t instanceCount,
+                         uint32_t firstVertex,
+                         uint32_t firstInstance)
+{
+    ASSERT(valid());
+    vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint,
+                                 const vk::Pipeline &pipeline)
+{
+    ASSERT(valid() && pipeline.valid());
+    vkCmdBindPipeline(mHandle, pipelineBindPoint, pipeline.getHandle());
+}
+
+void CommandBuffer::bindVertexBuffers(uint32_t firstBinding,
+                                      const std::vector<VkBuffer> &buffers,
+                                      const std::vector<VkDeviceSize> &offsets)
+{
+    ASSERT(valid() && buffers.size() == offsets.size());
+    vkCmdBindVertexBuffers(mHandle, firstBinding, static_cast<uint32_t>(buffers.size()),
+                           buffers.data(), offsets.data());
+}
+
+// Image implementation.
+Image::Image() : mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED)
+{
+}
+
+Image::Image(VkImage image) : WrappedObject(image), mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED)
+{
+}
+
+void Image::retain(VkDevice device, Image &&other)
+{
+    WrappedObject::retain(device, std::move(other));
+    std::swap(mCurrentLayout, other.mCurrentLayout);
+}
+
+void Image::reset()
+{
+    mHandle = VK_NULL_HANDLE;
+}
+
+void Image::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkDestroyImage(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error Image::init(VkDevice device, const VkImageCreateInfo &createInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(vkCreateImage(device, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+void Image::changeLayoutTop(VkImageAspectFlags aspectMask,
+                            VkImageLayout newLayout,
+                            CommandBuffer *commandBuffer)
+{
+    if (newLayout == mCurrentLayout)
+    {
+        // No-op.
+        return;
+    }
+
+    changeLayoutWithStages(aspectMask, newLayout, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                           VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, commandBuffer);
+}
+
+void Image::changeLayoutWithStages(VkImageAspectFlags aspectMask,
+                                   VkImageLayout newLayout,
+                                   VkPipelineStageFlags srcStageMask,
+                                   VkPipelineStageFlags dstStageMask,
+                                   CommandBuffer *commandBuffer)
+{
+    VkImageMemoryBarrier imageMemoryBarrier;
+    imageMemoryBarrier.sType               = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+    imageMemoryBarrier.pNext               = nullptr;
+    imageMemoryBarrier.srcAccessMask       = 0;
+    imageMemoryBarrier.dstAccessMask       = 0;
+    imageMemoryBarrier.oldLayout           = mCurrentLayout;
+    imageMemoryBarrier.newLayout           = newLayout;
+    imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    imageMemoryBarrier.image               = mHandle;
+
+    // TODO(jmadill): Is this needed for mipped/layer images?
+    imageMemoryBarrier.subresourceRange.aspectMask     = aspectMask;
+    imageMemoryBarrier.subresourceRange.baseMipLevel   = 0;
+    imageMemoryBarrier.subresourceRange.levelCount     = 1;
+    imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
+    imageMemoryBarrier.subresourceRange.layerCount     = 1;
+
+    // TODO(jmadill): Test all the permutations of the access flags.
+    imageMemoryBarrier.srcAccessMask = GetBasicLayoutAccessFlags(mCurrentLayout);
+
+    if (mCurrentLayout == VK_IMAGE_LAYOUT_PREINITIALIZED)
+    {
+        imageMemoryBarrier.srcAccessMask |= VK_ACCESS_HOST_WRITE_BIT;
+    }
+
+    imageMemoryBarrier.dstAccessMask = GetBasicLayoutAccessFlags(newLayout);
+
+    if (newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
+    {
+        imageMemoryBarrier.srcAccessMask |=
+            (VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT);
+        imageMemoryBarrier.dstAccessMask |= VK_ACCESS_SHADER_READ_BIT;
+    }
+
+    if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
+    {
+        imageMemoryBarrier.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+    }
+
+    commandBuffer->singleImageBarrier(srcStageMask, dstStageMask, 0, imageMemoryBarrier);
+
+    mCurrentLayout = newLayout;
+}
+
+void Image::getMemoryRequirements(VkDevice device, VkMemoryRequirements *requirementsOut) const
+{
+    ASSERT(valid());
+    vkGetImageMemoryRequirements(device, mHandle, requirementsOut);
+}
+
+Error Image::bindMemory(VkDevice device, const vk::DeviceMemory &deviceMemory)
+{
+    ASSERT(valid() && deviceMemory.valid());
+    ANGLE_VK_TRY(vkBindImageMemory(device, mHandle, deviceMemory.getHandle(), 0));
+    return NoError();
+}
+
+// ImageView implementation.
+ImageView::ImageView()
+{
+}
+
+void ImageView::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkDestroyImageView(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error ImageView::init(VkDevice device, const VkImageViewCreateInfo &createInfo)
+{
+    ANGLE_VK_TRY(vkCreateImageView(device, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+// Semaphore implementation.
+Semaphore::Semaphore()
+{
+}
+
+void Semaphore::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkDestroySemaphore(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error Semaphore::init(VkDevice device)
+{
+    ASSERT(!valid());
+
+    VkSemaphoreCreateInfo semaphoreInfo;
+    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+    semaphoreInfo.pNext = nullptr;
+    semaphoreInfo.flags = 0;
+
+    ANGLE_VK_TRY(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &mHandle));
+
+    return NoError();
+}
+
+// Framebuffer implementation.
+Framebuffer::Framebuffer()
+{
+}
+
+void Framebuffer::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkDestroyFramebuffer(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error Framebuffer::init(VkDevice device, const VkFramebufferCreateInfo &createInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(vkCreateFramebuffer(device, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+// DeviceMemory implementation.
+DeviceMemory::DeviceMemory()
+{
+}
+
+void DeviceMemory::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkFreeMemory(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error DeviceMemory::allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(vkAllocateMemory(device, &allocInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+Error DeviceMemory::map(VkDevice device,
+                        VkDeviceSize offset,
+                        VkDeviceSize size,
+                        VkMemoryMapFlags flags,
+                        uint8_t **mapPointer)
+{
+    ASSERT(valid());
+    ANGLE_VK_TRY(
+        vkMapMemory(device, mHandle, offset, size, flags, reinterpret_cast<void **>(mapPointer)));
+    return NoError();
+}
+
+void DeviceMemory::unmap(VkDevice device)
+{
+    ASSERT(valid());
+    vkUnmapMemory(device, mHandle);
+}
+
+// RenderPass implementation.
+RenderPass::RenderPass()
+{
+}
+
+void RenderPass::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkDestroyRenderPass(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error RenderPass::init(VkDevice device, const VkRenderPassCreateInfo &createInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(vkCreateRenderPass(device, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+// StagingImage implementation.
+StagingImage::StagingImage() : mSize(0)
+{
+}
+
+StagingImage::StagingImage(StagingImage &&other)
+    : mImage(std::move(other.mImage)),
+      mDeviceMemory(std::move(other.mDeviceMemory)),
+      mSize(other.mSize)
+{
+    other.mSize = 0;
+}
+
+void StagingImage::destroy(VkDevice device)
+{
+    mImage.destroy(device);
+    mDeviceMemory.destroy(device);
+}
+
+void StagingImage::retain(VkDevice device, StagingImage &&other)
+{
+    mImage.retain(device, std::move(other.mImage));
+    mDeviceMemory.retain(device, std::move(other.mDeviceMemory));
+    std::swap(mSize, other.mSize);
+}
+
+Error StagingImage::init(VkDevice device,
+                         uint32_t queueFamilyIndex,
+                         uint32_t hostVisibleMemoryIndex,
+                         TextureDimension dimension,
+                         VkFormat format,
+                         const gl::Extents &extent)
+{
+    VkImageCreateInfo createInfo;
+
+    createInfo.sType         = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+    createInfo.pNext         = nullptr;
+    createInfo.flags         = 0;
+    createInfo.imageType     = VK_IMAGE_TYPE_2D;
+    createInfo.format        = format;
+    createInfo.extent.width  = static_cast<uint32_t>(extent.width);
+    createInfo.extent.height = static_cast<uint32_t>(extent.height);
+    createInfo.extent.depth  = static_cast<uint32_t>(extent.depth);
+    createInfo.mipLevels     = 1;
+    createInfo.arrayLayers   = 1;
+    createInfo.samples       = VK_SAMPLE_COUNT_1_BIT;
+    createInfo.tiling        = VK_IMAGE_TILING_LINEAR;
+    createInfo.usage         = (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+    createInfo.sharingMode   = VK_SHARING_MODE_EXCLUSIVE;
+    createInfo.queueFamilyIndexCount = 1;
+    createInfo.pQueueFamilyIndices   = &queueFamilyIndex;
+    createInfo.initialLayout         = VK_IMAGE_LAYOUT_UNDEFINED;
+
+    ANGLE_TRY(mImage.init(device, createInfo));
+
+    VkMemoryRequirements memoryRequirements;
+    mImage.getMemoryRequirements(device, &memoryRequirements);
+
+    // Ensure we can read this memory.
+    ANGLE_VK_CHECK((memoryRequirements.memoryTypeBits & (1 << hostVisibleMemoryIndex)) != 0,
+                   VK_ERROR_VALIDATION_FAILED_EXT);
+
+    VkMemoryAllocateInfo allocateInfo;
+    allocateInfo.sType           = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+    allocateInfo.pNext           = nullptr;
+    allocateInfo.allocationSize  = memoryRequirements.size;
+    allocateInfo.memoryTypeIndex = hostVisibleMemoryIndex;
+
+    ANGLE_TRY(mDeviceMemory.allocate(device, allocateInfo));
+    ANGLE_TRY(mImage.bindMemory(device, mDeviceMemory));
+
+    mSize = memoryRequirements.size;
+
+    return NoError();
+}
+
+// Buffer implementation.
+Buffer::Buffer()
+{
+}
+
+void Buffer::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        mMemory.destroy(device);
+
+        vkDestroyBuffer(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+void Buffer::retain(VkDevice device, Buffer &&other)
+{
+    WrappedObject::retain(device, std::move(other));
+    mMemory.retain(device, std::move(other.mMemory));
+}
+
+Error Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(vkCreateBuffer(device, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+Error Buffer::bindMemory(VkDevice device)
+{
+    ASSERT(valid() && mMemory.valid());
+    ANGLE_VK_TRY(vkBindBufferMemory(device, mHandle, mMemory.getHandle(), 0));
+    return NoError();
+}
+
+// ShaderModule implementation.
+ShaderModule::ShaderModule()
+{
+}
+
+void ShaderModule::destroy(VkDevice device)
+{
+    if (mHandle != VK_NULL_HANDLE)
+    {
+        vkDestroyShaderModule(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error ShaderModule::init(VkDevice device, const VkShaderModuleCreateInfo &createInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(vkCreateShaderModule(device, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+// Pipeline implementation.
+Pipeline::Pipeline()
+{
+}
+
+void Pipeline::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkDestroyPipeline(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error Pipeline::initGraphics(VkDevice device, const VkGraphicsPipelineCreateInfo &createInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(
+        vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+// PipelineLayout implementation.
+PipelineLayout::PipelineLayout()
+{
+}
+
+void PipelineLayout::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkDestroyPipelineLayout(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error PipelineLayout::init(VkDevice device, const VkPipelineLayoutCreateInfo &createInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(vkCreatePipelineLayout(device, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+// Fence implementation.
+Fence::Fence()
+{
+}
+
+void Fence::destroy(VkDevice device)
+{
+    if (valid())
+    {
+        vkDestroyFence(device, mHandle, nullptr);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+Error Fence::init(VkDevice device, const VkFenceCreateInfo &createInfo)
+{
+    ASSERT(!valid());
+    ANGLE_VK_TRY(vkCreateFence(device, &createInfo, nullptr, &mHandle));
+    return NoError();
+}
+
+VkResult Fence::getStatus(VkDevice device) const
+{
+    return vkGetFenceStatus(device, mHandle);
+}
+
+}  // namespace vk
+
+Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
+                                  const VkMemoryRequirements &requirements,
+                                  uint32_t propertyFlagMask)
+{
+    for (uint32_t typeIndex = 0; typeIndex < memoryProps.memoryTypeCount; ++typeIndex)
+    {
+        if ((requirements.memoryTypeBits & (1u << typeIndex)) != 0 &&
+            ((memoryProps.memoryTypes[typeIndex].propertyFlags & propertyFlagMask) ==
+             propertyFlagMask))
+        {
+            return typeIndex;
+        }
+    }
+
+    return Optional<uint32_t>::Invalid();
+}
+
+namespace gl_vk
+{
+VkPrimitiveTopology GetPrimitiveTopology(GLenum mode)
+{
+    switch (mode)
+    {
+        case GL_TRIANGLES:
+            return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+        case GL_POINTS:
+            return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
+        case GL_LINES:
+            return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
+        case GL_LINE_STRIP:
+            return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
+        case GL_TRIANGLE_FAN:
+            return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
+        case GL_TRIANGLE_STRIP:
+            return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+        case GL_LINE_LOOP:
+            // TODO(jmadill): Implement line loop support.
+            UNIMPLEMENTED();
+            return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
+        default:
+            UNREACHABLE();
+            return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
+    }
+}
+
+VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState)
+{
+    if (!rasterState.cullFace)
+    {
+        return VK_CULL_MODE_NONE;
+    }
+
+    switch (rasterState.cullMode)
+    {
+        case GL_FRONT:
+            return VK_CULL_MODE_FRONT_BIT;
+        case GL_BACK:
+            return VK_CULL_MODE_BACK_BIT;
+        case GL_FRONT_AND_BACK:
+            return VK_CULL_MODE_FRONT_AND_BACK;
+        default:
+            UNREACHABLE();
+            return VK_CULL_MODE_NONE;
+    }
+}
+
+VkFrontFace GetFrontFace(GLenum frontFace)
+{
+    switch (frontFace)
+    {
+        case GL_CW:
+            return VK_FRONT_FACE_CLOCKWISE;
+        case GL_CCW:
+            return VK_FRONT_FACE_COUNTER_CLOCKWISE;
+        default:
+            UNREACHABLE();
+            return VK_FRONT_FACE_COUNTER_CLOCKWISE;
+    }
+}
+
+}  // namespace gl_vk
+
+}  // namespace rx
+
+std::ostream &operator<<(std::ostream &stream, const rx::vk::Error &error)
+{
+    stream << error.toString();
+    return stream;
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/renderervk_utils.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/renderervk_utils.h
new file mode 100644
index 0000000..20f8f2e
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/renderervk_utils.h
@@ -0,0 +1,531 @@
+//
+// Copyright 2016 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.
+//
+// renderervk_utils:
+//    Helper functions for the Vulkan Renderer.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_RENDERERVK_UTILS_H_
+#define LIBANGLE_RENDERER_VULKAN_RENDERERVK_UTILS_H_
+
+#include <limits>
+
+#include <vulkan/vulkan.h>
+
+#include "common/debug.h"
+#include "common/Optional.h"
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+struct Box;
+struct Extents;
+struct RasterizerState;
+struct Rectangle;
+}
+
+namespace rx
+{
+const char *VulkanResultString(VkResult result);
+bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps);
+
+extern const char *g_VkStdValidationLayerName;
+
+enum class TextureDimension
+{
+    TEX_2D,
+    TEX_CUBE,
+    TEX_3D,
+    TEX_2D_ARRAY,
+};
+
+enum DeleteSchedule
+{
+    NOW,
+    LATER,
+};
+
+// A serial supports a few operations - comparison, increment, and assignment.
+// TODO(jmadill): Verify it's not easy to overflow the queue serial.
+class Serial final
+{
+  public:
+    Serial() : mValue(0) {}
+    Serial(const Serial &other) : mValue(other.mValue) {}
+    Serial(Serial &&other) : mValue(other.mValue) { other.mValue = 0; }
+    Serial &operator=(const Serial &other)
+    {
+        mValue = other.mValue;
+        return *this;
+    }
+    bool operator>=(Serial other) const { return mValue >= other.mValue; }
+    bool operator>(Serial other) const { return mValue > other.mValue; }
+
+    // This function fails if we're at the limits of our counting.
+    bool operator++()
+    {
+        if (mValue == std::numeric_limits<uint32_t>::max())
+            return false;
+        mValue++;
+        return true;
+    }
+
+  private:
+    uint32_t mValue;
+};
+
+// This is a small helper mixin for any GL object used in Vk command buffers. It records a serial
+// at command submission times indicating it's order in the queue. We will use Fences to detect
+// when commands are finished, and then handle lifetime management for the resources.
+// Note that we use a queue order serial instead of a command buffer id serial since a queue can
+// submit multiple command buffers in one API call.
+class ResourceVk
+{
+  public:
+    void setQueueSerial(Serial queueSerial)
+    {
+        ASSERT(queueSerial >= mStoredQueueSerial);
+        mStoredQueueSerial = queueSerial;
+    }
+
+    DeleteSchedule getDeleteSchedule(Serial lastCompletedQueueSerial) const
+    {
+        if (lastCompletedQueueSerial >= mStoredQueueSerial)
+        {
+            return DeleteSchedule::NOW;
+        }
+        else
+        {
+            return DeleteSchedule::LATER;
+        }
+    }
+
+    Serial getStoredQueueSerial() const { return mStoredQueueSerial; }
+
+  private:
+    Serial mStoredQueueSerial;
+};
+
+namespace vk
+{
+class DeviceMemory;
+class Framebuffer;
+class Image;
+class Pipeline;
+class RenderPass;
+
+class Error final
+{
+  public:
+    Error(VkResult result);
+    Error(VkResult result, const char *file, unsigned int line);
+    ~Error();
+
+    Error(const Error &other);
+    Error &operator=(const Error &other);
+
+    gl::Error toGL(GLenum glErrorCode) const;
+    egl::Error toEGL(EGLint eglErrorCode) const;
+
+    operator gl::Error() const;
+    operator egl::Error() const;
+    template <typename T>
+    operator gl::ErrorOrResult<T>() const
+    {
+        return static_cast<gl::Error>(*this);
+    }
+
+    bool isError() const;
+
+    std::string toString() const;
+
+  private:
+    VkResult mResult;
+    const char *mFile;
+    unsigned int mLine;
+};
+
+template <typename ResultT>
+using ErrorOrResult = angle::ErrorOrResultBase<Error, ResultT, VkResult, VK_SUCCESS>;
+
+// Avoid conflicting with X headers which define "Success".
+inline Error NoError()
+{
+    return Error(VK_SUCCESS);
+}
+
+template <typename DerivedT, typename HandleT>
+class WrappedObject : angle::NonCopyable
+{
+  public:
+    HandleT getHandle() const { return mHandle; }
+    bool valid() const { return (mHandle != VK_NULL_HANDLE); }
+
+    const HandleT *ptr() const { return &mHandle; }
+
+  protected:
+    WrappedObject() : mHandle(VK_NULL_HANDLE) {}
+    WrappedObject(HandleT handle) : mHandle(handle) {}
+    ~WrappedObject() { ASSERT(!valid()); }
+
+    WrappedObject(WrappedObject &&other) : mHandle(other.mHandle)
+    {
+        other.mHandle = VK_NULL_HANDLE;
+    }
+
+    // Only works to initialize empty objects, since we don't have the device handle.
+    WrappedObject &operator=(WrappedObject &&other)
+    {
+        ASSERT(!valid());
+        std::swap(mHandle, other.mHandle);
+        return *this;
+    }
+
+    void retain(VkDevice device, DerivedT &&other)
+    {
+        if (valid())
+        {
+            static_cast<DerivedT *>(this)->destroy(device);
+        }
+        std::swap(mHandle, other.mHandle);
+    }
+
+    HandleT mHandle;
+};
+
+class CommandPool final : public WrappedObject<CommandPool, VkCommandPool>
+{
+  public:
+    CommandPool();
+
+    void destroy(VkDevice device);
+
+    Error init(VkDevice device, const VkCommandPoolCreateInfo &createInfo);
+};
+
+// Helper class that wraps a Vulkan command buffer.
+class CommandBuffer final : public WrappedObject<CommandBuffer, VkCommandBuffer>
+{
+  public:
+    CommandBuffer();
+
+    bool started() const { return mStarted; }
+
+    void destroy(VkDevice device);
+    using WrappedObject::operator=;
+
+    void setCommandPool(CommandPool *commandPool);
+    Error begin(VkDevice device);
+    Error end();
+    Error reset();
+
+    void singleImageBarrier(VkPipelineStageFlags srcStageMask,
+                            VkPipelineStageFlags dstStageMask,
+                            VkDependencyFlags dependencyFlags,
+                            const VkImageMemoryBarrier &imageMemoryBarrier);
+
+    void clearSingleColorImage(const vk::Image &image, const VkClearColorValue &color);
+
+    void copySingleImage(const vk::Image &srcImage,
+                         const vk::Image &destImage,
+                         const gl::Box &copyRegion,
+                         VkImageAspectFlags aspectMask);
+
+    void beginRenderPass(const RenderPass &renderPass,
+                         const Framebuffer &framebuffer,
+                         const gl::Rectangle &renderArea,
+                         const std::vector<VkClearValue> &clearValues);
+    void endRenderPass();
+
+    void draw(uint32_t vertexCount,
+              uint32_t instanceCount,
+              uint32_t firstVertex,
+              uint32_t firstInstance);
+
+    void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const vk::Pipeline &pipeline);
+    void bindVertexBuffers(uint32_t firstBinding,
+                           const std::vector<VkBuffer> &buffers,
+                           const std::vector<VkDeviceSize> &offsets);
+
+  private:
+    bool mStarted;
+    CommandPool *mCommandPool;
+};
+
+class Image final : public WrappedObject<Image, VkImage>
+{
+  public:
+    // Use this constructor if the lifetime of the image is not controlled by ANGLE. (SwapChain)
+    Image();
+    explicit Image(VkImage image);
+
+    // Called on shutdown when the helper class *doesn't* own the handle to the image resource.
+    void reset();
+
+    // Called on shutdown when the helper class *does* own the handle to the image resource.
+    void destroy(VkDevice device);
+
+    void retain(VkDevice device, Image &&other);
+
+    Error init(VkDevice device, const VkImageCreateInfo &createInfo);
+
+    void changeLayoutTop(VkImageAspectFlags aspectMask,
+                         VkImageLayout newLayout,
+                         CommandBuffer *commandBuffer);
+
+    void changeLayoutWithStages(VkImageAspectFlags aspectMask,
+                                VkImageLayout newLayout,
+                                VkPipelineStageFlags srcStageMask,
+                                VkPipelineStageFlags dstStageMask,
+                                CommandBuffer *commandBuffer);
+
+    void getMemoryRequirements(VkDevice device, VkMemoryRequirements *requirementsOut) const;
+    Error bindMemory(VkDevice device, const vk::DeviceMemory &deviceMemory);
+
+    VkImageLayout getCurrentLayout() const { return mCurrentLayout; }
+    void updateLayout(VkImageLayout layout) { mCurrentLayout = layout; }
+
+  private:
+    VkImageLayout mCurrentLayout;
+};
+
+class ImageView final : public WrappedObject<ImageView, VkImageView>
+{
+  public:
+    ImageView();
+    void destroy(VkDevice device);
+    using WrappedObject::retain;
+
+    Error init(VkDevice device, const VkImageViewCreateInfo &createInfo);
+};
+
+class Semaphore final : public WrappedObject<Semaphore, VkSemaphore>
+{
+  public:
+    Semaphore();
+    void destroy(VkDevice device);
+    using WrappedObject::retain;
+
+    Error init(VkDevice device);
+};
+
+class Framebuffer final : public WrappedObject<Framebuffer, VkFramebuffer>
+{
+  public:
+    Framebuffer();
+    void destroy(VkDevice device);
+    using WrappedObject::retain;
+
+    Error init(VkDevice device, const VkFramebufferCreateInfo &createInfo);
+};
+
+class DeviceMemory final : public WrappedObject<DeviceMemory, VkDeviceMemory>
+{
+  public:
+    DeviceMemory();
+    void destroy(VkDevice device);
+    using WrappedObject::retain;
+
+    Error allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo);
+    Error map(VkDevice device,
+              VkDeviceSize offset,
+              VkDeviceSize size,
+              VkMemoryMapFlags flags,
+              uint8_t **mapPointer);
+    void unmap(VkDevice device);
+};
+
+class RenderPass final : public WrappedObject<RenderPass, VkRenderPass>
+{
+  public:
+    RenderPass();
+    void destroy(VkDevice device);
+    using WrappedObject::retain;
+
+    Error init(VkDevice device, const VkRenderPassCreateInfo &createInfo);
+};
+
+class StagingImage final : angle::NonCopyable
+{
+  public:
+    StagingImage();
+    StagingImage(StagingImage &&other);
+    void destroy(VkDevice device);
+    void retain(VkDevice device, StagingImage &&other);
+
+    vk::Error init(VkDevice device,
+                   uint32_t queueFamilyIndex,
+                   uint32_t hostVisibleMemoryIndex,
+                   TextureDimension dimension,
+                   VkFormat format,
+                   const gl::Extents &extent);
+
+    Image &getImage() { return mImage; }
+    const Image &getImage() const { return mImage; }
+    DeviceMemory &getDeviceMemory() { return mDeviceMemory; }
+    const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
+    VkDeviceSize getSize() const { return mSize; }
+
+  private:
+    Image mImage;
+    DeviceMemory mDeviceMemory;
+    VkDeviceSize mSize;
+};
+
+class Buffer final : public WrappedObject<Buffer, VkBuffer>
+{
+  public:
+    Buffer();
+    void destroy(VkDevice device);
+    void retain(VkDevice device, Buffer &&other);
+
+    Error init(VkDevice device, const VkBufferCreateInfo &createInfo);
+    Error bindMemory(VkDevice device);
+
+    DeviceMemory &getMemory() { return mMemory; }
+    const DeviceMemory &getMemory() const { return mMemory; }
+
+  private:
+    DeviceMemory mMemory;
+};
+
+class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule>
+{
+  public:
+    ShaderModule();
+    void destroy(VkDevice device);
+    using WrappedObject::retain;
+
+    Error init(VkDevice device, const VkShaderModuleCreateInfo &createInfo);
+};
+
+class Pipeline final : public WrappedObject<Pipeline, VkPipeline>
+{
+  public:
+    Pipeline();
+    void destroy(VkDevice device);
+    using WrappedObject::retain;
+
+    Error initGraphics(VkDevice device, const VkGraphicsPipelineCreateInfo &createInfo);
+};
+
+class PipelineLayout final : public WrappedObject<PipelineLayout, VkPipelineLayout>
+{
+  public:
+    PipelineLayout();
+    void destroy(VkDevice device);
+    using WrappedObject::retain;
+
+    Error init(VkDevice device, const VkPipelineLayoutCreateInfo &createInfo);
+};
+
+class Fence final : public WrappedObject<Fence, VkFence>
+{
+  public:
+    Fence();
+    void destroy(VkDevice fence);
+    using WrappedObject::retain;
+    using WrappedObject::operator=;
+
+    Error init(VkDevice device, const VkFenceCreateInfo &createInfo);
+    VkResult getStatus(VkDevice device) const;
+};
+
+template <typename ObjT>
+class ObjectAndSerial final : angle::NonCopyable
+{
+  public:
+    ObjectAndSerial(ObjT &&object, Serial queueSerial)
+        : mObject(std::move(object)), mQueueSerial(queueSerial)
+    {
+    }
+
+    ObjectAndSerial(ObjectAndSerial &&other)
+        : mObject(std::move(other.mObject)), mQueueSerial(std::move(other.mQueueSerial))
+    {
+    }
+    ObjectAndSerial &operator=(ObjectAndSerial &&other)
+    {
+        mObject      = std::move(other.mObject);
+        mQueueSerial = std::move(other.mQueueSerial);
+        return *this;
+    }
+
+    void destroy(VkDevice device) { mObject.destroy(device); }
+
+    Serial queueSerial() const { return mQueueSerial; }
+
+    const ObjT &get() const { return mObject; }
+
+  private:
+    ObjT mObject;
+    Serial mQueueSerial;
+};
+
+using CommandBufferAndSerial = ObjectAndSerial<CommandBuffer>;
+using FenceAndSerial         = ObjectAndSerial<Fence>;
+
+class IGarbageObject : angle::NonCopyable
+{
+  public:
+    virtual ~IGarbageObject() {}
+    virtual bool destroyIfComplete(VkDevice device, Serial completedSerial) = 0;
+    virtual void destroy(VkDevice device) = 0;
+};
+
+template <typename T>
+class GarbageObject final : public IGarbageObject
+{
+  public:
+    GarbageObject(Serial serial, T &&object) : mSerial(serial), mObject(std::move(object)) {}
+
+    bool destroyIfComplete(VkDevice device, Serial completedSerial) override
+    {
+        if (completedSerial >= mSerial)
+        {
+            mObject.destroy(device);
+            return true;
+        }
+
+        return false;
+    }
+
+    void destroy(VkDevice device) override { mObject.destroy(device); }
+
+  private:
+    Serial mSerial;
+    T mObject;
+};
+
+}  // namespace vk
+
+Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
+                                  const VkMemoryRequirements &requirements,
+                                  uint32_t propertyFlagMask);
+
+namespace gl_vk
+{
+VkPrimitiveTopology GetPrimitiveTopology(GLenum mode);
+VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState);
+VkFrontFace GetFrontFace(GLenum frontFace);
+}  // namespace gl_vk
+
+}  // namespace rx
+
+#define ANGLE_VK_TRY(command)                                          \
+    {                                                                  \
+        auto ANGLE_LOCAL_VAR = command;                                \
+        if (ANGLE_LOCAL_VAR != VK_SUCCESS)                             \
+        {                                                              \
+            return rx::vk::Error(ANGLE_LOCAL_VAR, __FILE__, __LINE__); \
+        }                                                              \
+    }                                                                  \
+    ANGLE_EMPTY_STATEMENT
+
+#define ANGLE_VK_CHECK(test, error) ANGLE_VK_TRY(test ? VK_SUCCESS : error)
+
+std::ostream &operator<<(std::ostream &stream, const rx::vk::Error &error);
+
+#endif  // LIBANGLE_RENDERER_VULKAN_RENDERERVK_UTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_map.json b/src/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_map.json
new file mode 100644
index 0000000..dce60b7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_map.json
@@ -0,0 +1,161 @@
+{
+    "NONE": "VK_FORMAT_UNDEFINED",
+    "R4G4B4A4_UNORM": "VK_FORMAT_R4G4B4A4_UNORM_PACK16",
+    "B4G4R4A4_UNORM": "VK_FORMAT_B4G4R4A4_UNORM_PACK16",
+    "R5G6B5_UNORM": "VK_FORMAT_R5G6B5_UNORM_PACK16",
+    "B5G6R5_UNORM": "VK_FORMAT_B5G6R5_UNORM_PACK16",
+    "R5G5B5A1_UNORM": "VK_FORMAT_R5G5B5A1_UNORM_PACK16",
+    "B5G5R5A1_UNORM": "VK_FORMAT_B5G5R5A1_UNORM_PACK16",
+    "A1R5G5B5_UNORM": "VK_FORMAT_A1R5G5B5_UNORM_PACK16",
+    "R8_UNORM": "VK_FORMAT_R8_UNORM",
+    "R8_SNORM": "VK_FORMAT_R8_SNORM",
+    "R8_UINT": "VK_FORMAT_R8_UINT",
+    "R8_SINT": "VK_FORMAT_R8_SINT",
+    "R8_SRGB": "VK_FORMAT_R8_SRGB",
+    "R8G8_UNORM": "VK_FORMAT_R8G8_UNORM",
+    "R8G8_SNORM": "VK_FORMAT_R8G8_SNORM",
+    "R8G8_UINT": "VK_FORMAT_R8G8_UINT",
+    "R8G8_SINT": "VK_FORMAT_R8G8_SINT",
+    "R8G8_SRGB": "VK_FORMAT_R8G8_SRGB",
+    "R8G8B8_UNORM": "VK_FORMAT_R8G8B8_UNORM",
+    "R8G8B8_SNORM": "VK_FORMAT_R8G8B8_SNORM",
+    "R8G8B8_UINT": "VK_FORMAT_R8G8B8_UINT",
+    "R8G8B8_SINT": "VK_FORMAT_R8G8B8_SINT",
+    "R8G8B8_SRGB": "VK_FORMAT_R8G8B8_SRGB",
+    "B8G8R8_UNORM": "VK_FORMAT_B8G8R8_UNORM",
+    "B8G8R8_SNORM": "VK_FORMAT_B8G8R8_SNORM",
+    "B8G8R8_UINT": "VK_FORMAT_B8G8R8_UINT",
+    "B8G8R8_SINT": "VK_FORMAT_B8G8R8_SINT",
+    "B8G8R8_SRGB": "VK_FORMAT_B8G8R8_SRGB",
+    "R8G8B8A8_UNORM": "VK_FORMAT_R8G8B8A8_UNORM",
+    "R8G8B8A8_SNORM": "VK_FORMAT_R8G8B8A8_SNORM",
+    "R8G8B8A8_UINT": "VK_FORMAT_R8G8B8A8_UINT",
+    "R8G8B8A8_SINT": "VK_FORMAT_R8G8B8A8_SINT",
+    "R8G8B8A8_SRGB": "VK_FORMAT_R8G8B8A8_SRGB",
+    "B8G8R8A8_UNORM": "VK_FORMAT_B8G8R8A8_UNORM",
+    "B8G8R8A8_SNORM": "VK_FORMAT_B8G8R8A8_SNORM",
+    "B8G8R8A8_USCALED": "VK_FORMAT_B8G8R8A8_USCALED",
+    "B8G8R8A8_SSCALED": "VK_FORMAT_B8G8R8A8_SSCALED",
+    "B8G8R8A8_UINT": "VK_FORMAT_B8G8R8A8_UINT",
+    "B8G8R8A8_SINT": "VK_FORMAT_B8G8R8A8_SINT",
+    "B8G8R8A8_SRGB": "VK_FORMAT_B8G8R8A8_SRGB",
+    "A2R10G10B10_UNORM_PACK32": "VK_FORMAT_A2R10G10B10_UNORM_PACK32",
+    "A2R10G10B10_SNORM_PACK32": "VK_FORMAT_A2R10G10B10_SNORM_PACK32",
+    "A2R10G10B10_USCALED_PACK32": "VK_FORMAT_A2R10G10B10_USCALED_PACK32",
+    "A2R10G10B10_SSCALED_PACK32": "VK_FORMAT_A2R10G10B10_SSCALED_PACK32",
+    "A2R10G10B10_UINT_PACK32": "VK_FORMAT_A2R10G10B10_UINT_PACK32",
+    "A2R10G10B10_SINT_PACK32": "VK_FORMAT_A2R10G10B10_SINT_PACK32",
+    "A2B10G10R10_UNORM_PACK32": "VK_FORMAT_A2B10G10R10_UNORM_PACK32",
+    "A2B10G10R10_SNORM_PACK32": "VK_FORMAT_A2B10G10R10_SNORM_PACK32",
+    "A2B10G10R10_USCALED_PACK32": "VK_FORMAT_A2B10G10R10_USCALED_PACK32",
+    "A2B10G10R10_SSCALED_PACK32": "VK_FORMAT_A2B10G10R10_SSCALED_PACK32",
+    "A2B10G10R10_UINT_PACK32": "VK_FORMAT_A2B10G10R10_UINT_PACK32",
+    "A2B10G10R10_SINT_PACK32": "VK_FORMAT_A2B10G10R10_SINT_PACK32",
+    "R16_UNORM": "VK_FORMAT_R16_UNORM",
+    "R16_SNORM": "VK_FORMAT_R16_SNORM",
+    "R16_UINT": "VK_FORMAT_R16_UINT",
+    "R16_SINT": "VK_FORMAT_R16_SINT",
+    "R16_FLOAT": "VK_FORMAT_R16_SFLOAT",
+    "R16G16_UNORM": "VK_FORMAT_R16G16_UNORM",
+    "R16G16_SNORM": "VK_FORMAT_R16G16_SNORM",
+    "R16G16_UINT": "VK_FORMAT_R16G16_UINT",
+    "R16G16_SINT": "VK_FORMAT_R16G16_SINT",
+    "R16G16_FLOAT": "VK_FORMAT_R16G16_SFLOAT",
+    "R16G16B16_UNORM": "VK_FORMAT_R16G16B16_UNORM",
+    "R16G16B16_SNORM": "VK_FORMAT_R16G16B16_SNORM",
+    "R16G16B16_UINT": "VK_FORMAT_R16G16B16_UINT",
+    "R16G16B16_SINT": "VK_FORMAT_R16G16B16_SINT",
+    "R16G16B16_FLOAT": "VK_FORMAT_R16G16B16_SFLOAT",
+    "R16G16B16A16_UNORM": "VK_FORMAT_R16G16B16A16_UNORM",
+    "R16G16B16A16_SNORM": "VK_FORMAT_R16G16B16A16_SNORM",
+    "R16G16B16A16_UINT": "VK_FORMAT_R16G16B16A16_UINT",
+    "R16G16B16A16_SINT": "VK_FORMAT_R16G16B16A16_SINT",
+    "R16G16B16A16_FLOAT": "VK_FORMAT_R16G16B16A16_SFLOAT",
+    "R32_UINT": "VK_FORMAT_R32_UINT",
+    "R32_SINT": "VK_FORMAT_R32_SINT",
+    "R32_FLOAT": "VK_FORMAT_R32_SFLOAT",
+    "R32G32_UINT": "VK_FORMAT_R32G32_UINT",
+    "R32G32_SINT": "VK_FORMAT_R32G32_SINT",
+    "R32G32_FLOAT": "VK_FORMAT_R32G32_SFLOAT",
+    "R32G32B32_UINT": "VK_FORMAT_R32G32B32_UINT",
+    "R32G32B32_SINT": "VK_FORMAT_R32G32B32_SINT",
+    "R32G32B32_FLOAT": "VK_FORMAT_R32G32B32_SFLOAT",
+    "R32G32B32A32_UINT": "VK_FORMAT_R32G32B32A32_UINT",
+    "R32G32B32A32_SINT": "VK_FORMAT_R32G32B32A32_SINT",
+    "R32G32B32A32_FLOAT": "VK_FORMAT_R32G32B32A32_SFLOAT",
+    "R64_UINT": "VK_FORMAT_R64_UINT",
+    "R64_SINT": "VK_FORMAT_R64_SINT",
+    "R64_FLOAT": "VK_FORMAT_R64_SFLOAT",
+    "R64G64_UINT": "VK_FORMAT_R64G64_UINT",
+    "R64G64_SINT": "VK_FORMAT_R64G64_SINT",
+    "R64G64_FLOAT": "VK_FORMAT_R64G64_SFLOAT",
+    "R64G64B64_UINT": "VK_FORMAT_R64G64B64_UINT",
+    "R64G64B64_SINT": "VK_FORMAT_R64G64B64_SINT",
+    "R64G64B64_FLOAT": "VK_FORMAT_R64G64B64_SFLOAT",
+    "R64G64B64A64_UINT": "VK_FORMAT_R64G64B64A64_UINT",
+    "R64G64B64A64_SINT": "VK_FORMAT_R64G64B64A64_SINT",
+    "R64G64B64A64_FLOAT": "VK_FORMAT_R64G64B64A64_SFLOAT",
+    "B10G11R11_UFLOAT_PACK32": "VK_FORMAT_B10G11R11_UFLOAT_PACK32",
+    "E5B9G9R9_UFLOAT_PACK32": "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32",
+    "D16_UNORM": "VK_FORMAT_D16_UNORM",
+    "X8_D24_UNORM_PACK32": "VK_FORMAT_X8_D24_UNORM_PACK32",
+    "D32_FLOAT": "VK_FORMAT_D32_SFLOAT",
+    "S8_UINT": "VK_FORMAT_S8_UINT",
+    "D16_UNORM_S8_UINT": "VK_FORMAT_D16_UNORM_S8_UINT",
+    "D24_UNORM_S8_UINT": "VK_FORMAT_D24_UNORM_S8_UINT",
+    "D32_SFLOAT_S8_UINT": "VK_FORMAT_D32_SFLOAT_S8_UINT",
+    "BC1_RGB_UNORM_BLOCK": "VK_FORMAT_BC1_RGB_UNORM_BLOCK",
+    "BC1_RGB_SRGB_BLOCK": "VK_FORMAT_BC1_RGB_SRGB_BLOCK",
+    "BC1_RGBA_UNORM_BLOCK": "VK_FORMAT_BC1_RGBA_UNORM_BLOCK",
+    "BC1_RGBA_SRGB_BLOCK": "VK_FORMAT_BC1_RGBA_SRGB_BLOCK",
+    "BC2_UNORM_BLOCK": "VK_FORMAT_BC2_UNORM_BLOCK",
+    "BC2_SRGB_BLOCK": "VK_FORMAT_BC2_SRGB_BLOCK",
+    "BC3_UNORM_BLOCK": "VK_FORMAT_BC3_UNORM_BLOCK",
+    "BC3_SRGB_BLOCK": "VK_FORMAT_BC3_SRGB_BLOCK",
+    "BC4_UNORM_BLOCK": "VK_FORMAT_BC4_UNORM_BLOCK",
+    "BC4_SNORM_BLOCK": "VK_FORMAT_BC4_SNORM_BLOCK",
+    "BC5_UNORM_BLOCK": "VK_FORMAT_BC5_UNORM_BLOCK",
+    "BC5_SNORM_BLOCK": "VK_FORMAT_BC5_SNORM_BLOCK",
+    "BC6H_UFLOAT_BLOCK": "VK_FORMAT_BC6H_UFLOAT_BLOCK",
+    "BC6H_SFLOAT_BLOCK": "VK_FORMAT_BC6H_SFLOAT_BLOCK",
+    "BC7_UNORM_BLOCK": "VK_FORMAT_BC7_UNORM_BLOCK",
+    "BC7_SRGB_BLOCK": "VK_FORMAT_BC7_SRGB_BLOCK",
+    "ETC2_R8G8B8_UNORM_BLOCK": "VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK",
+    "ETC2_R8G8B8_SRGB_BLOCK": "VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK",
+    "ETC2_R8G8B8A1_UNORM_BLOCK": "VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK",
+    "ETC2_R8G8B8A1_SRGB_BLOCK": "VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK",
+    "ETC2_R8G8B8A8_UNORM_BLOCK": "VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK",
+    "ETC2_R8G8B8A8_SRGB_BLOCK": "VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK",
+    "EAC_R11_UNORM_BLOCK": "VK_FORMAT_EAC_R11_UNORM_BLOCK",
+    "EAC_R11_SNORM_BLOCK": "VK_FORMAT_EAC_R11_SNORM_BLOCK",
+    "EAC_R11G11_UNORM_BLOCK": "VK_FORMAT_EAC_R11G11_UNORM_BLOCK",
+    "EAC_R11G11_SNORM_BLOCK": "VK_FORMAT_EAC_R11G11_SNORM_BLOCK",
+    "ASTC_4x4_UNORM_BLOCK": "VK_FORMAT_ASTC_4x4_UNORM_BLOCK",
+    "ASTC_4x4_SRGB_BLOCK": "VK_FORMAT_ASTC_4x4_SRGB_BLOCK",
+    "ASTC_5x4_UNORM_BLOCK": "VK_FORMAT_ASTC_5x4_UNORM_BLOCK",
+    "ASTC_5x4_SRGB_BLOCK": "VK_FORMAT_ASTC_5x4_SRGB_BLOCK",
+    "ASTC_5x5_UNORM_BLOCK": "VK_FORMAT_ASTC_5x5_UNORM_BLOCK",
+    "ASTC_5x5_SRGB_BLOCK": "VK_FORMAT_ASTC_5x5_SRGB_BLOCK",
+    "ASTC_6x5_UNORM_BLOCK": "VK_FORMAT_ASTC_6x5_UNORM_BLOCK",
+    "ASTC_6x5_SRGB_BLOCK": "VK_FORMAT_ASTC_6x5_SRGB_BLOCK",
+    "ASTC_6x6_UNORM_BLOCK": "VK_FORMAT_ASTC_6x6_UNORM_BLOCK",
+    "ASTC_6x6_SRGB_BLOCK": "VK_FORMAT_ASTC_6x6_SRGB_BLOCK",
+    "ASTC_8x5_UNORM_BLOCK": "VK_FORMAT_ASTC_8x5_UNORM_BLOCK",
+    "ASTC_8x5_SRGB_BLOCK": "VK_FORMAT_ASTC_8x5_SRGB_BLOCK",
+    "ASTC_8x6_UNORM_BLOCK": "VK_FORMAT_ASTC_8x6_UNORM_BLOCK",
+    "ASTC_8x6_SRGB_BLOCK": "VK_FORMAT_ASTC_8x6_SRGB_BLOCK",
+    "ASTC_8x8_UNORM_BLOCK": "VK_FORMAT_ASTC_8x8_UNORM_BLOCK",
+    "ASTC_8x8_SRGB_BLOCK": "VK_FORMAT_ASTC_8x8_SRGB_BLOCK",
+    "ASTC_10x5_UNORM_BLOCK": "VK_FORMAT_ASTC_10x5_UNORM_BLOCK",
+    "ASTC_10x5_SRGB_BLOCK": "VK_FORMAT_ASTC_10x5_SRGB_BLOCK",
+    "ASTC_10x6_UNORM_BLOCK": "VK_FORMAT_ASTC_10x6_UNORM_BLOCK",
+    "ASTC_10x6_SRGB_BLOCK": "VK_FORMAT_ASTC_10x6_SRGB_BLOCK",
+    "ASTC_10x8_UNORM_BLOCK": "VK_FORMAT_ASTC_10x8_UNORM_BLOCK",
+    "ASTC_10x8_SRGB_BLOCK": "VK_FORMAT_ASTC_10x8_SRGB_BLOCK",
+    "ASTC_10x10_UNORM_BLOCK": "VK_FORMAT_ASTC_10x10_UNORM_BLOCK",
+    "ASTC_10x10_SRGB_BLOCK": "VK_FORMAT_ASTC_10x10_SRGB_BLOCK",
+    "ASTC_12x10_UNORM_BLOCK": "VK_FORMAT_ASTC_12x10_UNORM_BLOCK",
+    "ASTC_12x10_SRGB_BLOCK": "VK_FORMAT_ASTC_12x10_SRGB_BLOCK",
+    "ASTC_12x12_UNORM_BLOCK": "VK_FORMAT_ASTC_12x12_UNORM_BLOCK",
+    "ASTC_12x12_SRGB_BLOC": "VK_FORMAT_ASTC_12x12_SRGB_BLOCK"
+}
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
new file mode 100644
index 0000000..40778d2
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
@@ -0,0 +1,868 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_vk_format_table.py using data from vk_format_map.json
+//
+// Copyright 2016 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.
+//
+// vk_format_table:
+//   Queries for full Vulkan format information based on GL format.
+
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace vk
+{
+
+// static
+const Format &Format::Get(GLenum internalFormat)
+{
+    // clang-format off
+    switch (internalFormat)
+    {
+        case GL_BGR565_ANGLEX:
+        {
+            static constexpr Format info(GL_BGR565_ANGLEX,
+                                         angle::Format::ID::B5G6R5_UNORM,
+                                         VK_FORMAT_B5G6R5_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_BGR5_A1_ANGLEX:
+        {
+            static constexpr Format info(GL_BGR5_A1_ANGLEX,
+                                         angle::Format::ID::B5G5R5A1_UNORM,
+                                         VK_FORMAT_B5G5R5A1_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_BGRA4_ANGLEX:
+        {
+            static constexpr Format info(GL_BGRA4_ANGLEX,
+                                         angle::Format::ID::B4G4R4A4_UNORM,
+                                         VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_BGRA8_EXT:
+        {
+            static constexpr Format info(GL_BGRA8_EXT,
+                                         angle::Format::ID::B8G8R8A8_UNORM,
+                                         VK_FORMAT_B8G8R8A8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_R11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_R11_EAC,
+                                         angle::Format::ID::EAC_R11_UNORM_BLOCK,
+                                         VK_FORMAT_EAC_R11_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RG11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_RG11_EAC,
+                                         angle::Format::ID::EAC_R11G11_UNORM_BLOCK,
+                                         VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGB8_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB8_ETC2,
+                                         angle::Format::ID::ETC2_R8G8B8_UNORM_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+                                         angle::Format::ID::ETC2_R8G8B8A1_UNORM_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA8_ETC2_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA8_ETC2_EAC,
+                                         angle::Format::ID::ETC2_R8G8B8A8_UNORM_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
+                                         angle::Format::ID::ASTC_10x10_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x5_KHR,
+                                         angle::Format::ID::ASTC_10x5_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
+                                         angle::Format::ID::ASTC_10x6_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x8_KHR,
+                                         angle::Format::ID::ASTC_10x8_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x10_KHR,
+                                         angle::Format::ID::ASTC_12x10_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
+                                         angle::Format::ID::ASTC_12x12_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
+                                         angle::Format::ID::ASTC_4x4_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
+                                         angle::Format::ID::ASTC_5x4_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x5_KHR,
+                                         angle::Format::ID::ASTC_5x5_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
+                                         angle::Format::ID::ASTC_6x5_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x6_KHR,
+                                         angle::Format::ID::ASTC_6x6_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
+                                         angle::Format::ID::ASTC_8x5_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x6_KHR,
+                                         angle::Format::ID::ASTC_8x6_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
+                                         angle::Format::ID::ASTC_8x8_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+                                         angle::Format::ID::BC1_RGBA_UNORM_BLOCK,
+                                         VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+                                         angle::Format::ID::BC1_RGB_UNORM_BLOCK,
+                                         VK_FORMAT_BC1_RGB_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SIGNED_R11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_SIGNED_R11_EAC,
+                                         angle::Format::ID::EAC_R11_SNORM_BLOCK,
+                                         VK_FORMAT_EAC_R11_SNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SIGNED_RG11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_SIGNED_RG11_EAC,
+                                         angle::Format::ID::EAC_R11G11_SNORM_BLOCK,
+                                         VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+                                         angle::Format::ID::ASTC_10x10_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
+                                         angle::Format::ID::ASTC_10x5_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
+                                         angle::Format::ID::ASTC_10x6_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
+                                         angle::Format::ID::ASTC_10x8_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
+                                         angle::Format::ID::ASTC_12x10_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
+                                         angle::Format::ID::ASTC_4x4_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
+                                         angle::Format::ID::ASTC_5x4_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
+                                         angle::Format::ID::ASTC_5x5_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
+                                         angle::Format::ID::ASTC_6x5_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
+                                         angle::Format::ID::ASTC_6x6_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
+                                         angle::Format::ID::ASTC_8x5_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
+                                         angle::Format::ID::ASTC_8x6_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
+                                         angle::Format::ID::ASTC_8x8_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
+                                         angle::Format::ID::ETC2_R8G8B8A8_SRGB_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ETC2,
+                                         angle::Format::ID::ETC2_R8G8B8_SRGB_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+                                         angle::Format::ID::ETC2_R8G8B8A1_SRGB_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_DEPTH24_STENCIL8:
+        {
+            static constexpr Format info(GL_DEPTH24_STENCIL8,
+                                         angle::Format::ID::D24_UNORM_S8_UINT,
+                                         VK_FORMAT_D24_UNORM_S8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_DEPTH_COMPONENT16:
+        {
+            static constexpr Format info(GL_DEPTH_COMPONENT16,
+                                         angle::Format::ID::D16_UNORM,
+                                         VK_FORMAT_D16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_DEPTH_COMPONENT32F:
+        {
+            static constexpr Format info(GL_DEPTH_COMPONENT32F,
+                                         angle::Format::ID::D32_FLOAT,
+                                         VK_FORMAT_D32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+        {
+            static constexpr Format info(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE,
+                                         angle::Format::ID::NONE,
+                                         VK_FORMAT_UNDEFINED,
+                                         nullptr);
+            return info;
+        }
+        case GL_ETC1_RGB8_OES:
+        {
+            static constexpr Format info(GL_ETC1_RGB8_OES,
+                                         angle::Format::ID::NONE,
+                                         VK_FORMAT_UNDEFINED,
+                                         nullptr);
+            return info;
+        }
+        case GL_NONE:
+        {
+            static constexpr Format info(GL_NONE,
+                                         angle::Format::ID::NONE,
+                                         VK_FORMAT_UNDEFINED,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16F:
+        {
+            static constexpr Format info(GL_R16F,
+                                         angle::Format::ID::R16_FLOAT,
+                                         VK_FORMAT_R16_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16I:
+        {
+            static constexpr Format info(GL_R16I,
+                                         angle::Format::ID::R16_SINT,
+                                         VK_FORMAT_R16_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16UI:
+        {
+            static constexpr Format info(GL_R16UI,
+                                         angle::Format::ID::R16_UINT,
+                                         VK_FORMAT_R16_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16_EXT:
+        {
+            static constexpr Format info(GL_R16_EXT,
+                                         angle::Format::ID::R16_UNORM,
+                                         VK_FORMAT_R16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_R16_SNORM_EXT,
+                                         angle::Format::ID::R16_SNORM,
+                                         VK_FORMAT_R16_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_R32F:
+        {
+            static constexpr Format info(GL_R32F,
+                                         angle::Format::ID::R32_FLOAT,
+                                         VK_FORMAT_R32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R32I:
+        {
+            static constexpr Format info(GL_R32I,
+                                         angle::Format::ID::R32_SINT,
+                                         VK_FORMAT_R32_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R32UI:
+        {
+            static constexpr Format info(GL_R32UI,
+                                         angle::Format::ID::R32_UINT,
+                                         VK_FORMAT_R32_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8:
+        {
+            static constexpr Format info(GL_R8,
+                                         angle::Format::ID::R8_UNORM,
+                                         VK_FORMAT_R8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8I:
+        {
+            static constexpr Format info(GL_R8I,
+                                         angle::Format::ID::R8_SINT,
+                                         VK_FORMAT_R8_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8UI:
+        {
+            static constexpr Format info(GL_R8UI,
+                                         angle::Format::ID::R8_UINT,
+                                         VK_FORMAT_R8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8_SNORM:
+        {
+            static constexpr Format info(GL_R8_SNORM,
+                                         angle::Format::ID::R8_SNORM,
+                                         VK_FORMAT_R8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16F:
+        {
+            static constexpr Format info(GL_RG16F,
+                                         angle::Format::ID::R16G16_FLOAT,
+                                         VK_FORMAT_R16G16_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16I:
+        {
+            static constexpr Format info(GL_RG16I,
+                                         angle::Format::ID::R16G16_SINT,
+                                         VK_FORMAT_R16G16_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16UI:
+        {
+            static constexpr Format info(GL_RG16UI,
+                                         angle::Format::ID::R16G16_UINT,
+                                         VK_FORMAT_R16G16_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16_EXT:
+        {
+            static constexpr Format info(GL_RG16_EXT,
+                                         angle::Format::ID::R16G16_UNORM,
+                                         VK_FORMAT_R16G16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_RG16_SNORM_EXT,
+                                         angle::Format::ID::R16G16_SNORM,
+                                         VK_FORMAT_R16G16_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG32F:
+        {
+            static constexpr Format info(GL_RG32F,
+                                         angle::Format::ID::R32G32_FLOAT,
+                                         VK_FORMAT_R32G32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG32I:
+        {
+            static constexpr Format info(GL_RG32I,
+                                         angle::Format::ID::R32G32_SINT,
+                                         VK_FORMAT_R32G32_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG32UI:
+        {
+            static constexpr Format info(GL_RG32UI,
+                                         angle::Format::ID::R32G32_UINT,
+                                         VK_FORMAT_R32G32_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8:
+        {
+            static constexpr Format info(GL_RG8,
+                                         angle::Format::ID::R8G8_UNORM,
+                                         VK_FORMAT_R8G8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8I:
+        {
+            static constexpr Format info(GL_RG8I,
+                                         angle::Format::ID::R8G8_SINT,
+                                         VK_FORMAT_R8G8_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8UI:
+        {
+            static constexpr Format info(GL_RG8UI,
+                                         angle::Format::ID::R8G8_UINT,
+                                         VK_FORMAT_R8G8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8_SNORM:
+        {
+            static constexpr Format info(GL_RG8_SNORM,
+                                         angle::Format::ID::R8G8_SNORM,
+                                         VK_FORMAT_R8G8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB:
+        {
+            static constexpr Format info(GL_RGB,
+                                         angle::Format::ID::R8G8B8_UNORM,
+                                         VK_FORMAT_R8G8B8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16F:
+        {
+            static constexpr Format info(GL_RGB16F,
+                                         angle::Format::ID::R16G16B16_FLOAT,
+                                         VK_FORMAT_R16G16B16_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16I:
+        {
+            static constexpr Format info(GL_RGB16I,
+                                         angle::Format::ID::R16G16B16_SINT,
+                                         VK_FORMAT_R16G16B16_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16UI:
+        {
+            static constexpr Format info(GL_RGB16UI,
+                                         angle::Format::ID::R16G16B16_UINT,
+                                         VK_FORMAT_R16G16B16_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16_EXT:
+        {
+            static constexpr Format info(GL_RGB16_EXT,
+                                         angle::Format::ID::R16G16B16_UNORM,
+                                         VK_FORMAT_R16G16B16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_RGB16_SNORM_EXT,
+                                         angle::Format::ID::R16G16B16_SNORM,
+                                         VK_FORMAT_R16G16B16_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB32F:
+        {
+            static constexpr Format info(GL_RGB32F,
+                                         angle::Format::ID::R32G32B32_FLOAT,
+                                         VK_FORMAT_R32G32B32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB32I:
+        {
+            static constexpr Format info(GL_RGB32I,
+                                         angle::Format::ID::R32G32B32_SINT,
+                                         VK_FORMAT_R32G32B32_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB32UI:
+        {
+            static constexpr Format info(GL_RGB32UI,
+                                         angle::Format::ID::R32G32B32_UINT,
+                                         VK_FORMAT_R32G32B32_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB565:
+        {
+            static constexpr Format info(GL_RGB565,
+                                         angle::Format::ID::R5G6B5_UNORM,
+                                         VK_FORMAT_R5G6B5_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB5_A1:
+        {
+            static constexpr Format info(GL_RGB5_A1,
+                                         angle::Format::ID::R5G5B5A1_UNORM,
+                                         VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB8:
+        {
+            static constexpr Format info(GL_RGB8,
+                                         angle::Format::ID::R8G8B8_UNORM,
+                                         VK_FORMAT_R8G8B8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB8I:
+        {
+            static constexpr Format info(GL_RGB8I,
+                                         angle::Format::ID::R8G8B8_SINT,
+                                         VK_FORMAT_R8G8B8_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB8UI:
+        {
+            static constexpr Format info(GL_RGB8UI,
+                                         angle::Format::ID::R8G8B8_UINT,
+                                         VK_FORMAT_R8G8B8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB8_SNORM:
+        {
+            static constexpr Format info(GL_RGB8_SNORM,
+                                         angle::Format::ID::R8G8B8_SNORM,
+                                         VK_FORMAT_R8G8B8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA:
+        {
+            static constexpr Format info(GL_RGBA,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         VK_FORMAT_R8G8B8A8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16F:
+        {
+            static constexpr Format info(GL_RGBA16F,
+                                         angle::Format::ID::R16G16B16A16_FLOAT,
+                                         VK_FORMAT_R16G16B16A16_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16I:
+        {
+            static constexpr Format info(GL_RGBA16I,
+                                         angle::Format::ID::R16G16B16A16_SINT,
+                                         VK_FORMAT_R16G16B16A16_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16UI:
+        {
+            static constexpr Format info(GL_RGBA16UI,
+                                         angle::Format::ID::R16G16B16A16_UINT,
+                                         VK_FORMAT_R16G16B16A16_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16_EXT:
+        {
+            static constexpr Format info(GL_RGBA16_EXT,
+                                         angle::Format::ID::R16G16B16A16_UNORM,
+                                         VK_FORMAT_R16G16B16A16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_RGBA16_SNORM_EXT,
+                                         angle::Format::ID::R16G16B16A16_SNORM,
+                                         VK_FORMAT_R16G16B16A16_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA32F:
+        {
+            static constexpr Format info(GL_RGBA32F,
+                                         angle::Format::ID::R32G32B32A32_FLOAT,
+                                         VK_FORMAT_R32G32B32A32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA32I:
+        {
+            static constexpr Format info(GL_RGBA32I,
+                                         angle::Format::ID::R32G32B32A32_SINT,
+                                         VK_FORMAT_R32G32B32A32_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA32UI:
+        {
+            static constexpr Format info(GL_RGBA32UI,
+                                         angle::Format::ID::R32G32B32A32_UINT,
+                                         VK_FORMAT_R32G32B32A32_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA4:
+        {
+            static constexpr Format info(GL_RGBA4,
+                                         angle::Format::ID::R4G4B4A4_UNORM,
+                                         VK_FORMAT_R4G4B4A4_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8:
+        {
+            static constexpr Format info(GL_RGBA8,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         VK_FORMAT_R8G8B8A8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8I:
+        {
+            static constexpr Format info(GL_RGBA8I,
+                                         angle::Format::ID::R8G8B8A8_SINT,
+                                         VK_FORMAT_R8G8B8A8_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8UI:
+        {
+            static constexpr Format info(GL_RGBA8UI,
+                                         angle::Format::ID::R8G8B8A8_UINT,
+                                         VK_FORMAT_R8G8B8A8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8_SNORM:
+        {
+            static constexpr Format info(GL_RGBA8_SNORM,
+                                         angle::Format::ID::R8G8B8A8_SNORM,
+                                         VK_FORMAT_R8G8B8A8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_STENCIL_INDEX8:
+        {
+            static constexpr Format info(GL_STENCIL_INDEX8,
+                                         angle::Format::ID::S8_UINT,
+                                         VK_FORMAT_S8_UINT,
+                                         nullptr);
+            return info;
+        }
+
+        default:
+            break;
+    }
+    // clang-format on
+
+    UNREACHABLE();
+    static const Format noInfo(GL_NONE, angle::Format::ID::NONE, VK_FORMAT_UNDEFINED, nullptr);
+    return noInfo;
+}
+
+}  // namespace vk
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp
new file mode 100644
index 0000000..48a7bba
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp
@@ -0,0 +1,41 @@
+//
+// Copyright 2016 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.
+//
+// DisplayVkWin32.cpp:
+//    Implements the class methods for DisplayVkWin32.
+//
+
+#include "libANGLE/renderer/vulkan/win32/DisplayVkWin32.h"
+
+#include <vulkan/vulkan.h>
+
+#include "libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h"
+
+namespace rx
+{
+
+DisplayVkWin32::DisplayVkWin32(const egl::DisplayState &state) : DisplayVk(state)
+{
+}
+
+bool DisplayVkWin32::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    return (IsWindow(window) == TRUE);
+}
+
+SurfaceImpl *DisplayVkWin32::createWindowSurfaceVk(const egl::SurfaceState &state,
+                                                   EGLNativeWindowType window,
+                                                   EGLint width,
+                                                   EGLint height)
+{
+    return new WindowSurfaceVkWin32(state, window, width, height);
+}
+
+const char *DisplayVkWin32::getWSIName() const
+{
+    return VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.h
new file mode 100644
index 0000000..5942155
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.h
@@ -0,0 +1,34 @@
+//
+// Copyright 2016 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.
+//
+// DisplayVkWin32.h:
+//    Defines the class interface for DisplayVkWin32, implementing DisplayVk for Windows.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_WIN32_DISPLAYVKWIN32_H_
+#define LIBANGLE_RENDERER_VULKAN_WIN32_DISPLAYVKWIN32_H_
+
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
+
+namespace rx
+{
+class DisplayVkWin32 : public DisplayVk
+{
+  public:
+    DisplayVkWin32(const egl::DisplayState &state);
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+    SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
+                                       EGLNativeWindowType window,
+                                       EGLint width,
+                                       EGLint height) override;
+
+    const char *getWSIName() const override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_WIN32_DISPLAYVKWIN32_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp
new file mode 100644
index 0000000..b9de8d8
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp
@@ -0,0 +1,42 @@
+//
+// Copyright 2016 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.
+//
+// WindowSurfaceVkWin32.cpp:
+//    Implements the class methods for WindowSurfaceVkWin32.
+//
+
+#include "libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h"
+
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+
+namespace rx
+{
+
+WindowSurfaceVkWin32::WindowSurfaceVkWin32(const egl::SurfaceState &surfaceState,
+                                           EGLNativeWindowType window,
+                                           EGLint width,
+                                           EGLint height)
+    : WindowSurfaceVk(surfaceState, window, width, height)
+{
+}
+
+vk::ErrorOrResult<gl::Extents> WindowSurfaceVkWin32::createSurfaceVk(RendererVk *renderer)
+{
+    VkWin32SurfaceCreateInfoKHR createInfo;
+
+    createInfo.sType     = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+    createInfo.pNext     = nullptr;
+    createInfo.flags     = 0;
+    createInfo.hinstance = GetModuleHandle(nullptr);
+    createInfo.hwnd      = mNativeWindowType;
+    ANGLE_VK_TRY(vkCreateWin32SurfaceKHR(renderer->getInstance(), &createInfo, nullptr, &mSurface));
+
+    RECT rect;
+    ANGLE_VK_CHECK(GetClientRect(mNativeWindowType, &rect) == TRUE, VK_ERROR_INITIALIZATION_FAILED);
+
+    return gl::Extents(rect.right - rect.left, rect.bottom - rect.top, 0);
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h
new file mode 100644
index 0000000..5d0c978
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2016 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.
+//
+// WindowSurfaceVkWin32.h:
+//    Defines the class interface for WindowSurfaceVkWin32, implementing WindowSurfaceVk.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_WIN32_WINDOWSURFACEVKWIN32_H_
+#define LIBANGLE_RENDERER_VULKAN_WIN32_WINDOWSURFACEVKWIN32_H_
+
+#include "libANGLE/renderer/vulkan/SurfaceVk.h"
+
+namespace rx
+{
+
+class WindowSurfaceVkWin32 : public WindowSurfaceVk
+{
+  public:
+    WindowSurfaceVkWin32(const egl::SurfaceState &surfaceState,
+                         EGLNativeWindowType window,
+                         EGLint width,
+                         EGLint height);
+
+  private:
+    vk::ErrorOrResult<gl::Extents> createSurfaceVk(RendererVk *renderer) override;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_WIN32_WINDOWSURFACEVKWIN32_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.cpp
new file mode 100644
index 0000000..bd4d013
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.cpp
@@ -0,0 +1,69 @@
+//
+// Copyright 2016 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.
+//
+// DisplayVkXcb.cpp:
+//    Implements the class methods for DisplayVkXcb.
+//
+
+#include "libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h"
+
+#include <xcb/xcb.h>
+
+#include "libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h"
+
+namespace rx
+{
+
+DisplayVkXcb::DisplayVkXcb(const egl::DisplayState &state)
+    : DisplayVk(state), mXcbConnection(nullptr)
+{
+}
+
+egl::Error DisplayVkXcb::initialize(egl::Display *display)
+{
+    mXcbConnection = xcb_connect(nullptr, nullptr);
+    if (mXcbConnection == nullptr)
+    {
+        return egl::Error(EGL_NOT_INITIALIZED);
+    }
+    return DisplayVk::initialize(display);
+}
+
+void DisplayVkXcb::terminate()
+{
+    ASSERT(mXcbConnection != nullptr);
+    xcb_disconnect(mXcbConnection);
+    mXcbConnection = nullptr;
+    DisplayVk::terminate();
+}
+
+bool DisplayVkXcb::isValidNativeWindow(EGLNativeWindowType window) const
+{
+    // There doesn't appear to be an xcb function explicitly for checking the validity of a
+    // window ID, but xcb_query_tree_reply will return nullptr if the window doesn't exist.
+    xcb_query_tree_cookie_t cookie = xcb_query_tree(mXcbConnection, window);
+    xcb_query_tree_reply_t *reply  = xcb_query_tree_reply(mXcbConnection, cookie, nullptr);
+    if (reply)
+    {
+        free(reply);
+        return true;
+    }
+    return false;
+}
+
+SurfaceImpl *DisplayVkXcb::createWindowSurfaceVk(const egl::SurfaceState &state,
+                                                 EGLNativeWindowType window,
+                                                 EGLint width,
+                                                 EGLint height)
+{
+    return new WindowSurfaceVkXcb(state, window, width, height, mXcbConnection);
+}
+
+const char *DisplayVkXcb::getWSIName() const
+{
+    return VK_KHR_XCB_SURFACE_EXTENSION_NAME;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h
new file mode 100644
index 0000000..eea95bb
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h
@@ -0,0 +1,43 @@
+//
+// Copyright 2016 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.
+//
+// DisplayVkXcb.h:
+//    Defines the class interface for DisplayVkXcb, implementing DisplayVk for X via XCB.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_XCB_DISPLAYVKXCB_H_
+#define LIBANGLE_RENDERER_VULKAN_XCB_DISPLAYVKXCB_H_
+
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
+
+struct xcb_connection_t;
+
+namespace rx
+{
+
+class DisplayVkXcb : public DisplayVk
+{
+  public:
+    DisplayVkXcb(const egl::DisplayState &state);
+
+    egl::Error initialize(egl::Display *display) override;
+    void terminate() override;
+
+    bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+    SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
+                                       EGLNativeWindowType window,
+                                       EGLint width,
+                                       EGLint height) override;
+
+    const char *getWSIName() const override;
+
+  private:
+    xcb_connection_t *mXcbConnection;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_XCB_DISPLAYVKXCB_H_
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.cpp b/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.cpp
new file mode 100644
index 0000000..b486b74
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.cpp
@@ -0,0 +1,45 @@
+//
+// Copyright 2016 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.
+//
+// WindowSurfaceVkXcb.cpp:
+//    Implements the class methods for WindowSurfaceVkXcb.
+//
+
+#include "libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h"
+
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+
+namespace rx
+{
+
+WindowSurfaceVkXcb::WindowSurfaceVkXcb(const egl::SurfaceState &surfaceState,
+                                       EGLNativeWindowType window,
+                                       EGLint width,
+                                       EGLint height,
+                                       xcb_connection_t *conn)
+    : WindowSurfaceVk(surfaceState, window, width, height), mXcbConnection(conn)
+{
+}
+
+vk::ErrorOrResult<gl::Extents> WindowSurfaceVkXcb::createSurfaceVk(RendererVk *renderer)
+{
+    VkXcbSurfaceCreateInfoKHR createInfo;
+
+    createInfo.sType      = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+    createInfo.pNext      = nullptr;
+    createInfo.flags      = 0;
+    createInfo.connection = mXcbConnection;
+    createInfo.window     = mNativeWindowType;
+    ANGLE_VK_TRY(vkCreateXcbSurfaceKHR(renderer->getInstance(), &createInfo, nullptr, &mSurface));
+
+    xcb_get_geometry_cookie_t cookie = xcb_get_geometry(mXcbConnection, mNativeWindowType);
+    xcb_get_geometry_reply_t *reply  = xcb_get_geometry_reply(mXcbConnection, cookie, nullptr);
+    ASSERT(reply);
+    gl::Extents result(reply->width, reply->height, 0);
+    free(reply);
+    return result;
+}
+
+}  // namespace rx
diff --git a/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h b/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h
new file mode 100644
index 0000000..1d3cdc0
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h
@@ -0,0 +1,37 @@
+//
+// Copyright 2016 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.
+//
+// WindowSurfaceVkXcb.h:
+//    Defines the class interface for WindowSurfaceVkXcb, implementing WindowSurfaceVk.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_XCB_WINDOWSURFACEVKXCB_H_
+#define LIBANGLE_RENDERER_VULKAN_XCB_WINDOWSURFACEVKXCB_H_
+
+#include "libANGLE/renderer/vulkan/SurfaceVk.h"
+
+struct xcb_connection_t;
+
+namespace rx
+{
+
+class WindowSurfaceVkXcb : public WindowSurfaceVk
+{
+  public:
+    WindowSurfaceVkXcb(const egl::SurfaceState &surfaceState,
+                       EGLNativeWindowType window,
+                       EGLint width,
+                       EGLint height,
+                       xcb_connection_t *conn);
+
+  private:
+    vk::ErrorOrResult<gl::Extents> createSurfaceVk(RendererVk *renderer) override;
+
+    xcb_connection_t *mXcbConnection;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_XCB_WINDOWSURFACEVKXCB_H_
diff --git a/src/third_party/angle/src/libANGLE/signal_utils.h b/src/third_party/angle/src/libANGLE/signal_utils.h
new file mode 100644
index 0000000..84d7478
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/signal_utils.h
@@ -0,0 +1,177 @@
+//
+// Copyright 2016 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.
+//
+// signal_utils:
+//   Helper classes for tracking dependent state changes between objects.
+//   These changes are signaled to the dependent class via channels.
+
+#ifndef LIBANGLE_SIGNAL_UTILS_H_
+#define LIBANGLE_SIGNAL_UTILS_H_
+
+#include <set>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+namespace angle
+{
+
+// Interface that the depending class inherits from.
+template <typename ChannelID = uint32_t, typename... MessageT>
+class SignalReceiver
+{
+  public:
+    virtual ~SignalReceiver() = default;
+    virtual void signal(ChannelID channelID, MessageT... message) = 0;
+};
+
+template <typename ChannelID, typename... MessageT>
+class ChannelBinding;
+
+// The host class owns the channel. It uses the channel to fire signals to the receiver.
+template <typename ChannelID = uint32_t, typename... MessageT>
+class BroadcastChannel final : NonCopyable
+{
+  public:
+    BroadcastChannel();
+    ~BroadcastChannel();
+
+    void signal(MessageT... message) const;
+
+    void reset();
+
+  private:
+    // Only the ChannelBinding class should add or remove receivers.
+    friend class ChannelBinding<ChannelID, MessageT...>;
+    void addReceiver(ChannelBinding<ChannelID, MessageT...> *receiver);
+    void removeReceiver(ChannelBinding<ChannelID, MessageT...> *receiver);
+
+    std::vector<ChannelBinding<ChannelID, MessageT...> *> mReceivers;
+};
+
+template <typename ChannelID, typename... MessageT>
+BroadcastChannel<ChannelID, MessageT...>::BroadcastChannel()
+{
+}
+
+template <typename ChannelID, typename... MessageT>
+BroadcastChannel<ChannelID, MessageT...>::~BroadcastChannel()
+{
+    reset();
+}
+
+template <typename ChannelID, typename... MessageT>
+void BroadcastChannel<ChannelID, MessageT...>::addReceiver(
+    ChannelBinding<ChannelID, MessageT...> *receiver)
+{
+    ASSERT(std::find(mReceivers.begin(), mReceivers.end(), receiver) == mReceivers.end());
+    mReceivers.push_back(receiver);
+}
+
+template <typename ChannelID, typename... MessageT>
+void BroadcastChannel<ChannelID, MessageT...>::removeReceiver(
+    ChannelBinding<ChannelID, MessageT...> *receiver)
+{
+    auto iter = std::find(mReceivers.begin(), mReceivers.end(), receiver);
+    ASSERT(iter != mReceivers.end());
+    mReceivers.erase(iter);
+}
+
+template <typename ChannelID, typename... MessageT>
+void BroadcastChannel<ChannelID, MessageT...>::signal(MessageT... message) const
+{
+    if (mReceivers.empty())
+        return;
+
+    for (const auto *receiver : mReceivers)
+    {
+        receiver->signal(message...);
+    }
+}
+
+template <typename ChannelID, typename... MessageT>
+void BroadcastChannel<ChannelID, MessageT...>::reset()
+{
+    for (auto receiver : mReceivers)
+    {
+        receiver->onChannelClosed();
+    }
+    mReceivers.clear();
+}
+
+// The dependent class keeps bindings to the host's BroadcastChannel.
+template <typename ChannelID = uint32_t, typename... MessageT>
+class ChannelBinding final
+{
+  public:
+    ChannelBinding(SignalReceiver<ChannelID, MessageT...> *receiver, ChannelID channelID);
+    ~ChannelBinding();
+    ChannelBinding(const ChannelBinding &other) = default;
+    ChannelBinding &operator=(const ChannelBinding &other) = default;
+
+    void bind(BroadcastChannel<ChannelID, MessageT...> *channel);
+    void reset();
+    void signal(MessageT... message) const;
+    void onChannelClosed();
+
+  private:
+    BroadcastChannel<ChannelID, MessageT...> *mChannel;
+    SignalReceiver<ChannelID, MessageT...> *mReceiver;
+    ChannelID mChannelID;
+};
+
+template <typename ChannelID, typename... MessageT>
+ChannelBinding<ChannelID, MessageT...>::ChannelBinding(
+    SignalReceiver<ChannelID, MessageT...> *receiver,
+    ChannelID channelID)
+    : mChannel(nullptr), mReceiver(receiver), mChannelID(channelID)
+{
+    ASSERT(receiver);
+}
+
+template <typename ChannelID, typename... MessageT>
+ChannelBinding<ChannelID, MessageT...>::~ChannelBinding()
+{
+    reset();
+}
+
+template <typename ChannelID, typename... MessageT>
+void ChannelBinding<ChannelID, MessageT...>::bind(BroadcastChannel<ChannelID, MessageT...> *channel)
+{
+    ASSERT(mReceiver);
+    if (mChannel)
+    {
+        mChannel->removeReceiver(this);
+    }
+
+    mChannel = channel;
+
+    if (mChannel)
+    {
+        mChannel->addReceiver(this);
+    }
+}
+
+template <typename ChannelID, typename... MessageT>
+void ChannelBinding<ChannelID, MessageT...>::reset()
+{
+    bind(nullptr);
+}
+
+template <typename ChannelID, typename... MessageT>
+void ChannelBinding<ChannelID, MessageT...>::signal(MessageT... message) const
+{
+    mReceiver->signal(mChannelID, message...);
+}
+
+template <typename ChannelID, typename... MessageT>
+void ChannelBinding<ChannelID, MessageT...>::onChannelClosed()
+{
+    mChannel = nullptr;
+}
+
+}  // namespace angle
+
+#endif  // LIBANGLE_SIGNAL_UTILS_H_
diff --git a/src/third_party/angle/src/libANGLE/signal_utils_unittest.cpp b/src/third_party/angle/src/libANGLE/signal_utils_unittest.cpp
new file mode 100644
index 0000000..06cb392
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/signal_utils_unittest.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2016 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.
+//
+// signal_utils_unittest:
+//   Unit tests for signals and related utils.
+
+#include <gtest/gtest.h>
+
+#include "libANGLE/signal_utils.h"
+
+using namespace angle;
+using namespace testing;
+
+namespace
+{
+
+struct SignalThing : public SignalReceiver<>
+{
+    void signal(uint32_t channelID) override { wasSignaled = true; }
+    bool wasSignaled = false;
+};
+
+// Test that broadcast signals work.
+TEST(SignalTest, BroadcastSignals)
+{
+    BroadcastChannel<> channel;
+    SignalThing thing;
+    ChannelBinding<> binding(&thing, 0u);
+
+    binding.bind(&channel);
+    ASSERT_FALSE(thing.wasSignaled);
+    channel.signal();
+    ASSERT_TRUE(thing.wasSignaled);
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/libANGLE/validationEGL.cpp b/src/third_party/angle/src/libANGLE/validationEGL.cpp
new file mode 100644
index 0000000..2619a3a
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationEGL.cpp
@@ -0,0 +1,1964 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// validationEGL.cpp: Validation functions for generic EGL entry point parameters
+
+#include "libANGLE/validationEGL.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+
+#include <EGL/eglext.h>
+
+namespace
+{
+size_t GetMaximumMipLevel(const gl::Context *context, GLenum target)
+{
+    const gl::Caps &caps = context->getCaps();
+
+    size_t maxDimension = 0;
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+            maxDimension = caps.max2DTextureSize;
+            break;
+        case GL_TEXTURE_CUBE_MAP:
+            maxDimension = caps.maxCubeMapTextureSize;
+            break;
+        case GL_TEXTURE_3D:
+            maxDimension = caps.max3DTextureSize;
+            break;
+        case GL_TEXTURE_2D_ARRAY:
+            maxDimension = caps.max2DTextureSize;
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return gl::log2(static_cast<int>(maxDimension));
+}
+
+bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::Texture *texture)
+{
+    size_t maxMip = GetMaximumMipLevel(context, texture->getTarget());
+    for (size_t level = 1; level < maxMip; level++)
+    {
+        if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
+        {
+            for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget;
+                 face++)
+            {
+                if (texture->getFormat(face, level).valid())
+                {
+                    return true;
+                }
+            }
+        }
+        else
+        {
+            if (texture->getFormat(texture->getTarget(), level).valid())
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture)
+{
+    ASSERT(texture->getTarget() == GL_TEXTURE_CUBE_MAP);
+    for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; face++)
+    {
+        if (!texture->getFormat(face, 0).valid())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+egl::Error ValidateStreamAttribute(const EGLAttrib attribute,
+                                   const EGLAttrib value,
+                                   const egl::DisplayExtensions &extensions)
+{
+    switch (attribute)
+    {
+        case EGL_STREAM_STATE_KHR:
+        case EGL_PRODUCER_FRAME_KHR:
+        case EGL_CONSUMER_FRAME_KHR:
+            return egl::Error(EGL_BAD_ACCESS, "Attempt to initialize readonly parameter");
+        case EGL_CONSUMER_LATENCY_USEC_KHR:
+            // Technically not in spec but a latency < 0 makes no sense so we check it
+            if (value < 0)
+            {
+                return egl::Error(EGL_BAD_PARAMETER, "Latency must be positive");
+            }
+            break;
+        case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+            if (!extensions.streamConsumerGLTexture)
+            {
+                return egl::Error(EGL_BAD_ATTRIBUTE, "Consumer GL extension not enabled");
+            }
+            // Again not in spec but it should be positive anyways
+            if (value < 0)
+            {
+                return egl::Error(EGL_BAD_PARAMETER, "Timeout must be positive");
+            }
+            break;
+        default:
+            return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid stream attribute");
+    }
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error ValidateCreateImageKHRMipLevelCommon(gl::Context *context,
+                                                const gl::Texture *texture,
+                                                EGLAttrib level)
+{
+    // Note that the spec EGL_KHR_create_image spec does not explicitly specify an error
+    // when the level is outside the base/max level range, but it does mention that the
+    // level "must be a part of the complete texture object <buffer>". It can be argued
+    // that out-of-range levels are not a part of the complete texture.
+    const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
+    if (level > 0 &&
+        (!texture->isMipmapComplete() || static_cast<GLuint>(level) < effectiveBaseLevel ||
+         static_cast<GLuint>(level) > texture->getTextureState().getMipmapMaxLevel()))
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero.");
+    }
+
+    if (level == 0 && !texture->isMipmapComplete() &&
+        TextureHasNonZeroMipLevelsSpecified(context, texture))
+    {
+        return egl::Error(EGL_BAD_PARAMETER,
+                          "if level is zero and the texture is incomplete, it must have no mip "
+                          "levels specified except zero.");
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error ValidateConfigAttribute(const egl::Display *display, EGLAttrib attribute)
+{
+    switch (attribute)
+    {
+        case EGL_BUFFER_SIZE:
+        case EGL_ALPHA_SIZE:
+        case EGL_BLUE_SIZE:
+        case EGL_GREEN_SIZE:
+        case EGL_RED_SIZE:
+        case EGL_DEPTH_SIZE:
+        case EGL_STENCIL_SIZE:
+        case EGL_CONFIG_CAVEAT:
+        case EGL_CONFIG_ID:
+        case EGL_LEVEL:
+        case EGL_NATIVE_RENDERABLE:
+        case EGL_NATIVE_VISUAL_ID:
+        case EGL_NATIVE_VISUAL_TYPE:
+        case EGL_SAMPLES:
+        case EGL_SAMPLE_BUFFERS:
+        case EGL_SURFACE_TYPE:
+        case EGL_TRANSPARENT_TYPE:
+        case EGL_TRANSPARENT_BLUE_VALUE:
+        case EGL_TRANSPARENT_GREEN_VALUE:
+        case EGL_TRANSPARENT_RED_VALUE:
+        case EGL_BIND_TO_TEXTURE_RGB:
+        case EGL_BIND_TO_TEXTURE_RGBA:
+        case EGL_MIN_SWAP_INTERVAL:
+        case EGL_MAX_SWAP_INTERVAL:
+        case EGL_LUMINANCE_SIZE:
+        case EGL_ALPHA_MASK_SIZE:
+        case EGL_COLOR_BUFFER_TYPE:
+        case EGL_RENDERABLE_TYPE:
+        case EGL_MATCH_NATIVE_PIXMAP:
+        case EGL_CONFORMANT:
+        case EGL_MAX_PBUFFER_WIDTH:
+        case EGL_MAX_PBUFFER_HEIGHT:
+        case EGL_MAX_PBUFFER_PIXELS:
+            break;
+
+        case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+            if (!display->getExtensions().surfaceOrientation)
+            {
+                return egl::Error(EGL_BAD_ATTRIBUTE,
+                                  "EGL_ANGLE_surface_orientation is not enabled.");
+            }
+            break;
+
+        case EGL_COLOR_COMPONENT_TYPE_EXT:
+            if (!display->getExtensions().pixelFormatFloat)
+            {
+                return egl::Error(EGL_BAD_ATTRIBUTE, "EGL_EXT_pixel_format_float is not enabled.");
+            }
+            break;
+
+        default:
+            return egl::Error(EGL_BAD_ATTRIBUTE, "Unknown attribute.");
+    }
+
+    return egl::NoError();
+}
+
+egl::Error ValidateConfigAttributes(const egl::Display *display,
+                                    const egl::AttributeMap &attributes)
+{
+    for (const auto &attrib : attributes)
+    {
+        ANGLE_TRY(ValidateConfigAttribute(display, attrib.first));
+    }
+
+    return egl::NoError();
+}
+
+}  // namespace
+
+namespace egl
+{
+
+Error ValidateDisplay(const Display *display)
+{
+    if (display == EGL_NO_DISPLAY)
+    {
+        return Error(EGL_BAD_DISPLAY, "display is EGL_NO_DISPLAY.");
+    }
+
+    if (!Display::isValidDisplay(display))
+    {
+        return Error(EGL_BAD_DISPLAY, "display is not a valid display.");
+    }
+
+    if (!display->isInitialized())
+    {
+        return Error(EGL_NOT_INITIALIZED, "display is not initialized.");
+    }
+
+    if (display->isDeviceLost())
+    {
+        return Error(EGL_CONTEXT_LOST, "display had a context loss");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateSurface(const Display *display, const Surface *surface)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    if (!display->isValidSurface(surface))
+    {
+        return Error(EGL_BAD_SURFACE);
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateConfig(const Display *display, const Config *config)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    if (!display->isValidConfig(config))
+    {
+        return Error(EGL_BAD_CONFIG);
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateContext(const Display *display, const gl::Context *context)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    if (!display->isValidContext(context))
+    {
+        return Error(EGL_BAD_CONTEXT);
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateImage(const Display *display, const Image *image)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    if (!display->isValidImage(image))
+    {
+        return Error(EGL_BAD_PARAMETER, "image is not valid.");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateStream(const Display *display, const Stream *stream)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.stream)
+    {
+        return Error(EGL_BAD_ACCESS, "Stream extension not active");
+    }
+
+    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+    {
+        return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
+                            const AttributeMap& attributes)
+{
+    ANGLE_TRY(ValidateConfig(display, configuration));
+
+    // Get the requested client version (default is 1) and check it is 2 or 3.
+    EGLAttrib clientMajorVersion = 1;
+    EGLAttrib clientMinorVersion = 0;
+    EGLAttrib contextFlags       = 0;
+    bool resetNotification = false;
+    for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+    {
+        EGLAttrib attribute = attributeIter->first;
+        EGLAttrib value     = attributeIter->second;
+
+        switch (attribute)
+        {
+          case EGL_CONTEXT_CLIENT_VERSION:
+            clientMajorVersion = value;
+            break;
+
+          case EGL_CONTEXT_MINOR_VERSION:
+            clientMinorVersion = value;
+            break;
+
+          case EGL_CONTEXT_FLAGS_KHR:
+            contextFlags = value;
+            break;
+
+          case EGL_CONTEXT_OPENGL_DEBUG:
+              break;
+
+          case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
+            // Only valid for OpenGL (non-ES) contexts
+            return Error(EGL_BAD_ATTRIBUTE);
+
+          case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+            if (!display->getExtensions().createContextRobustness)
+            {
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            if (value != EGL_TRUE && value != EGL_FALSE)
+            {
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            break;
+
+          case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
+            static_assert(EGL_LOSE_CONTEXT_ON_RESET_EXT == EGL_LOSE_CONTEXT_ON_RESET_KHR, "EGL extension enums not equal.");
+            static_assert(EGL_NO_RESET_NOTIFICATION_EXT == EGL_NO_RESET_NOTIFICATION_KHR, "EGL extension enums not equal.");
+            // same as EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, fall through
+          case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+            if (!display->getExtensions().createContextRobustness)
+            {
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            if (value == EGL_LOSE_CONTEXT_ON_RESET_EXT)
+            {
+                resetNotification = true;
+            }
+            else if (value != EGL_NO_RESET_NOTIFICATION_EXT)
+            {
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            break;
+
+          case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
+              if (!display->getExtensions().createContextNoError)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE, "Invalid Context attribute.");
+              }
+              if (value != EGL_TRUE && value != EGL_FALSE)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE, "Attribute must be EGL_TRUE or EGL_FALSE.");
+              }
+              break;
+
+          case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
+              if (!display->getExtensions().createContextWebGLCompatibility)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "Attribute EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
+                               "EGL_ANGLE_create_context_webgl_compatibility.");
+              }
+              if (value != EGL_TRUE && value != EGL_FALSE)
+              {
+                  return Error(
+                      EGL_BAD_ATTRIBUTE,
+                      "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be EGL_TRUE or EGL_FALSE.");
+              }
+              break;
+
+          case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
+              if (!display->getExtensions().createContextBindGeneratesResource)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
+                               "EGL_CHROMIUM_create_context_bind_generates_resource.");
+              }
+              if (value != EGL_TRUE && value != EGL_FALSE)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM must be EGL_TRUE or "
+                               "EGL_FALSE.");
+              }
+              break;
+
+          case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
+              if (!display->getExtensions().displayTextureShareGroup)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "Attribute EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE requires "
+                               "EGL_ANGLE_display_texture_share_group.");
+              }
+              if (value != EGL_TRUE && value != EGL_FALSE)
+              {
+                  return Error(
+                      EGL_BAD_ATTRIBUTE,
+                      "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE must be EGL_TRUE or EGL_FALSE.");
+              }
+              if (shareContext &&
+                  (shareContext->usingDisplayTextureShareGroup() != (value == EGL_TRUE)))
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "All contexts within a share group must be created with the same "
+                               "value of EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.");
+              }
+              break;
+
+          case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
+              if (!display->getExtensions().createContextClientArrays)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "Attribute EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE requires "
+                               "EGL_ANGLE_create_context_client_arrays.");
+              }
+              if (value != EGL_TRUE && value != EGL_FALSE)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE must be EGL_TRUE or "
+                               "EGL_FALSE.");
+              }
+              break;
+
+          case EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+              if (!display->getExtensions().createContextRobustResourceInitialization)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "Attribute EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
+                               "requires EGL_ANGLE_create_context_robust_resource_initialization.");
+              }
+              if (value != EGL_TRUE && value != EGL_FALSE)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
+                               "either EGL_TRUE or EGL_FALSE.");
+              }
+              break;
+
+          default:
+              return Error(EGL_BAD_ATTRIBUTE, "Unknown attribute.");
+        }
+    }
+
+    switch (clientMajorVersion)
+    {
+        case 2:
+            if (clientMinorVersion != 0)
+            {
+                return Error(EGL_BAD_CONFIG);
+            }
+            break;
+        case 3:
+            if (clientMinorVersion != 0 && clientMinorVersion != 1)
+            {
+                return Error(EGL_BAD_CONFIG);
+            }
+            if (!(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR))
+            {
+                return Error(EGL_BAD_CONFIG);
+            }
+            if (display->getMaxSupportedESVersion() <
+                gl::Version(static_cast<GLuint>(clientMajorVersion),
+                            static_cast<GLuint>(clientMinorVersion)))
+            {
+                return Error(EGL_BAD_CONFIG, "Requested GLES version is not supported.");
+            }
+            break;
+        default:
+            return Error(EGL_BAD_CONFIG);
+            break;
+    }
+
+    // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
+    const EGLint validContextFlags = (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
+                                      EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
+    if ((contextFlags & ~validContextFlags) != 0)
+    {
+        return Error(EGL_BAD_ATTRIBUTE);
+    }
+
+    if (shareContext)
+    {
+        // Shared context is invalid or is owned by another display
+        if (!display->isValidContext(shareContext))
+        {
+            return Error(EGL_BAD_MATCH);
+        }
+
+        if (shareContext->isResetNotificationEnabled() != resetNotification)
+        {
+            return Error(EGL_BAD_MATCH);
+        }
+
+        if (shareContext->getClientMajorVersion() != clientMajorVersion ||
+            shareContext->getClientMinorVersion() != clientMinorVersion)
+        {
+            return Error(EGL_BAD_CONTEXT);
+        }
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window,
+                                  const AttributeMap& attributes)
+{
+    ANGLE_TRY(ValidateConfig(display, config));
+
+    if (!display->isValidNativeWindow(window))
+    {
+        return Error(EGL_BAD_NATIVE_WINDOW);
+    }
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+
+    for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+    {
+        EGLAttrib attribute = attributeIter->first;
+        EGLAttrib value     = attributeIter->second;
+
+        switch (attribute)
+        {
+          case EGL_RENDER_BUFFER:
+            switch (value)
+            {
+              case EGL_BACK_BUFFER:
+                break;
+              case EGL_SINGLE_BUFFER:
+                return Error(EGL_BAD_MATCH);   // Rendering directly to front buffer not supported
+              default:
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            break;
+
+          case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+            if (!displayExtensions.postSubBuffer)
+            {
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            break;
+
+          case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
+              if (!displayExtensions.flexibleSurfaceCompatibility)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE);
+              }
+              break;
+
+          case EGL_WIDTH:
+          case EGL_HEIGHT:
+            if (!displayExtensions.windowFixedSize)
+            {
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            if (value < 0)
+            {
+                return Error(EGL_BAD_PARAMETER);
+            }
+            break;
+
+          case EGL_FIXED_SIZE_ANGLE:
+            if (!displayExtensions.windowFixedSize)
+            {
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            break;
+
+          case EGL_SURFACE_ORIENTATION_ANGLE:
+              if (!displayExtensions.surfaceOrientation)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_surface_orientation is not enabled.");
+              }
+              break;
+
+          case EGL_VG_COLORSPACE:
+            return Error(EGL_BAD_MATCH);
+
+          case EGL_VG_ALPHA_FORMAT:
+            return Error(EGL_BAD_MATCH);
+
+          case EGL_DIRECT_COMPOSITION_ANGLE:
+              if (!displayExtensions.directComposition)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE);
+              }
+              break;
+
+          default:
+            return Error(EGL_BAD_ATTRIBUTE);
+        }
+    }
+
+    if (Display::hasExistingWindowSurface(window))
+    {
+        return Error(EGL_BAD_ALLOC);
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes)
+{
+    ANGLE_TRY(ValidateConfig(display, config));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+
+    for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+    {
+        EGLAttrib attribute = attributeIter->first;
+        EGLAttrib value     = attributeIter->second;
+
+        switch (attribute)
+        {
+          case EGL_WIDTH:
+          case EGL_HEIGHT:
+            if (value < 0)
+            {
+                return Error(EGL_BAD_PARAMETER);
+            }
+            break;
+
+          case EGL_LARGEST_PBUFFER:
+            break;
+
+          case EGL_TEXTURE_FORMAT:
+            switch (value)
+            {
+              case EGL_NO_TEXTURE:
+              case EGL_TEXTURE_RGB:
+              case EGL_TEXTURE_RGBA:
+                break;
+              default:
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            break;
+
+          case EGL_TEXTURE_TARGET:
+            switch (value)
+            {
+              case EGL_NO_TEXTURE:
+              case EGL_TEXTURE_2D:
+                break;
+              default:
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            break;
+
+          case EGL_MIPMAP_TEXTURE:
+            break;
+
+          case EGL_VG_COLORSPACE:
+            break;
+
+          case EGL_VG_ALPHA_FORMAT:
+            break;
+
+          case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
+              if (!displayExtensions.flexibleSurfaceCompatibility)
+              {
+                  return Error(
+                      EGL_BAD_ATTRIBUTE,
+                      "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without "
+                      "EGL_ANGLE_flexible_surface_compatibility support.");
+              }
+              break;
+
+          default:
+            return Error(EGL_BAD_ATTRIBUTE);
+        }
+    }
+
+    if (!(config->surfaceType & EGL_PBUFFER_BIT))
+    {
+        return Error(EGL_BAD_MATCH);
+    }
+
+    const Caps &caps = display->getCaps();
+
+    EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
+    EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+
+    if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
+        (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
+    {
+        return Error(EGL_BAD_MATCH);
+    }
+
+    if ((textureFormat == EGL_TEXTURE_RGB  && config->bindToTextureRGB != EGL_TRUE) ||
+        (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
+    {
+        return Error(EGL_BAD_ATTRIBUTE);
+    }
+
+    EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
+    EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
+    if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
+    {
+        return Error(EGL_BAD_MATCH);
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer,
+                                            Config *config, const AttributeMap& attributes)
+{
+    ANGLE_TRY(ValidateConfig(display, config));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+
+    switch (buftype)
+    {
+      case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+        if (!displayExtensions.d3dShareHandleClientBuffer)
+        {
+            return Error(EGL_BAD_PARAMETER);
+        }
+        if (buffer == nullptr)
+        {
+            return Error(EGL_BAD_PARAMETER);
+        }
+        break;
+
+      case EGL_D3D_TEXTURE_ANGLE:
+          if (!displayExtensions.d3dTextureClientBuffer)
+          {
+              return Error(EGL_BAD_PARAMETER);
+          }
+          if (buffer == nullptr)
+          {
+              return Error(EGL_BAD_PARAMETER);
+          }
+          break;
+
+      default:
+        return Error(EGL_BAD_PARAMETER);
+    }
+
+    for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+    {
+        EGLAttrib attribute = attributeIter->first;
+        EGLAttrib value     = attributeIter->second;
+
+        switch (attribute)
+        {
+          case EGL_WIDTH:
+          case EGL_HEIGHT:
+            if (!displayExtensions.d3dShareHandleClientBuffer)
+            {
+                return Error(EGL_BAD_PARAMETER);
+            }
+            if (value < 0)
+            {
+                return Error(EGL_BAD_PARAMETER);
+            }
+            break;
+
+          case EGL_TEXTURE_FORMAT:
+            switch (value)
+            {
+              case EGL_NO_TEXTURE:
+              case EGL_TEXTURE_RGB:
+              case EGL_TEXTURE_RGBA:
+                break;
+              default:
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            break;
+
+          case EGL_TEXTURE_TARGET:
+            switch (value)
+            {
+              case EGL_NO_TEXTURE:
+              case EGL_TEXTURE_2D:
+                break;
+              default:
+                return Error(EGL_BAD_ATTRIBUTE);
+            }
+            break;
+
+          case EGL_MIPMAP_TEXTURE:
+            break;
+
+          case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
+              if (!displayExtensions.flexibleSurfaceCompatibility)
+              {
+                  return Error(
+                      EGL_BAD_ATTRIBUTE,
+                      "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without "
+                      "EGL_ANGLE_flexible_surface_compatibility support.");
+              }
+              break;
+
+          default:
+            return Error(EGL_BAD_ATTRIBUTE);
+        }
+    }
+
+    if (!(config->surfaceType & EGL_PBUFFER_BIT))
+    {
+        return Error(EGL_BAD_MATCH);
+    }
+
+    EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
+    EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+    if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
+        (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
+    {
+        return Error(EGL_BAD_MATCH);
+    }
+
+    if ((textureFormat == EGL_TEXTURE_RGB  && config->bindToTextureRGB  != EGL_TRUE) ||
+        (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
+    {
+        return Error(EGL_BAD_ATTRIBUTE);
+    }
+
+    if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
+    {
+        EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
+        EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
+
+        if (width == 0 || height == 0)
+        {
+            return Error(EGL_BAD_ATTRIBUTE);
+        }
+
+        const Caps &caps = display->getCaps();
+        if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
+        {
+            return Error(EGL_BAD_MATCH);
+        }
+    }
+
+    ANGLE_TRY(display->validateClientBuffer(config, buftype, buffer, attributes));
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateMakeCurrent(Display *display, EGLSurface draw, EGLSurface read, gl::Context *context)
+{
+    if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
+    {
+        return Error(EGL_BAD_MATCH, "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE");
+    }
+
+    // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
+    // error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
+    if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
+    {
+        if (display->getExtensions().surfacelessContext)
+        {
+            if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
+            {
+                return Error(EGL_BAD_MATCH,
+                             "If ctx is not EGL_NOT_CONTEXT, draw or read must both be "
+                             "EGL_NO_SURFACE, or both not");
+            }
+        }
+        else
+        {
+            return Error(EGL_BAD_MATCH,
+                         "If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE");
+        }
+    }
+
+    // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
+    // EGL_BAD_MATCH error is generated.
+    if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
+    {
+        return Error(EGL_BAD_MATCH,
+                     "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE");
+    }
+
+    if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
+    {
+        return Error(EGL_BAD_DISPLAY, "'dpy' not a valid EGLDisplay handle");
+    }
+
+    // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
+    if (!display->isInitialized() &&
+        (context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
+    {
+        return Error(EGL_NOT_INITIALIZED, "'dpy' not initialized");
+    }
+
+    if (context != EGL_NO_CONTEXT)
+    {
+        ANGLE_TRY(ValidateContext(display, context));
+    }
+
+    if (display->isInitialized() && display->testDeviceLost())
+    {
+        return Error(EGL_CONTEXT_LOST);
+    }
+
+    Surface *drawSurface = static_cast<Surface *>(draw);
+    if (draw != EGL_NO_SURFACE)
+    {
+        ANGLE_TRY(ValidateSurface(display, drawSurface));
+    }
+
+    Surface *readSurface = static_cast<Surface *>(read);
+    if (read != EGL_NO_SURFACE)
+    {
+        ANGLE_TRY(ValidateSurface(display, readSurface));
+    }
+
+    if (readSurface)
+    {
+        ANGLE_TRY(ValidateCompatibleConfigs(display, readSurface->getConfig(), readSurface,
+                                            context->getConfig(), readSurface->getType()));
+    }
+
+    if (draw != read)
+    {
+        UNIMPLEMENTED();  // FIXME
+
+        if (drawSurface)
+        {
+            ANGLE_TRY(ValidateCompatibleConfigs(display, drawSurface->getConfig(), drawSurface,
+                                                context->getConfig(), drawSurface->getType()));
+        }
+    }
+    return egl::NoError();
+}
+
+Error ValidateCompatibleConfigs(const Display *display,
+                                const Config *config1,
+                                const Surface *surface,
+                                const Config *config2,
+                                EGLint surfaceType)
+{
+
+    if (!surface->flexibleSurfaceCompatibilityRequested())
+    {
+        // Config compatibility is defined in section 2.2 of the EGL 1.5 spec
+
+        bool colorBufferCompat = config1->colorBufferType == config2->colorBufferType;
+        if (!colorBufferCompat)
+        {
+            return Error(EGL_BAD_MATCH, "Color buffer types are not compatible.");
+        }
+
+        bool colorCompat =
+            config1->redSize == config2->redSize && config1->greenSize == config2->greenSize &&
+            config1->blueSize == config2->blueSize && config1->alphaSize == config2->alphaSize &&
+            config1->luminanceSize == config2->luminanceSize;
+        if (!colorCompat)
+        {
+            return Error(EGL_BAD_MATCH, "Color buffer sizes are not compatible.");
+        }
+
+        bool componentTypeCompat = config1->colorComponentType == config2->colorComponentType;
+        if (!componentTypeCompat)
+        {
+            return Error(EGL_BAD_MATCH, "Color buffer component types are not compatible.");
+        }
+
+        bool dsCompat = config1->depthSize == config2->depthSize &&
+                        config1->stencilSize == config2->stencilSize;
+        if (!dsCompat)
+        {
+            return Error(EGL_BAD_MATCH, "Depth-stencil buffer types are not compatible.");
+        }
+    }
+
+    bool surfaceTypeCompat = (config1->surfaceType & config2->surfaceType & surfaceType) != 0;
+    if (!surfaceTypeCompat)
+    {
+        return Error(EGL_BAD_MATCH, "Surface types are not compatible.");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateImageKHR(const Display *display,
+                             gl::Context *context,
+                             EGLenum target,
+                             EGLClientBuffer buffer,
+                             const AttributeMap &attributes)
+{
+    ANGLE_TRY(ValidateContext(display, context));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+
+    if (!displayExtensions.imageBase && !displayExtensions.image)
+    {
+        // It is out of spec what happens when calling an extension function when the extension is
+        // not available.
+        // EGL_BAD_DISPLAY seems like a reasonable error.
+        return Error(EGL_BAD_DISPLAY, "EGL_KHR_image not supported.");
+    }
+
+    // TODO(geofflang): Complete validation from EGL_KHR_image_base:
+    // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> is itself an
+    // EGLImage sibling, the error EGL_BAD_ACCESS is generated.
+
+    for (AttributeMap::const_iterator attributeIter = attributes.begin();
+         attributeIter != attributes.end(); attributeIter++)
+    {
+        EGLAttrib attribute = attributeIter->first;
+        EGLAttrib value     = attributeIter->second;
+
+        switch (attribute)
+        {
+            case EGL_IMAGE_PRESERVED_KHR:
+                switch (value)
+                {
+                    case EGL_TRUE:
+                    case EGL_FALSE:
+                        break;
+
+                    default:
+                        return Error(EGL_BAD_PARAMETER,
+                                     "EGL_IMAGE_PRESERVED_KHR must be EGL_TRUE or EGL_FALSE.");
+                }
+                break;
+
+            case EGL_GL_TEXTURE_LEVEL_KHR:
+                if (!displayExtensions.glTexture2DImage &&
+                    !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
+                {
+                    return Error(EGL_BAD_PARAMETER,
+                                 "EGL_GL_TEXTURE_LEVEL_KHR cannot be used without "
+                                 "KHR_gl_texture_*_image support.");
+                }
+
+                if (value < 0)
+                {
+                    return Error(EGL_BAD_PARAMETER, "EGL_GL_TEXTURE_LEVEL_KHR cannot be negative.");
+                }
+                break;
+
+            case EGL_GL_TEXTURE_ZOFFSET_KHR:
+                if (!displayExtensions.glTexture3DImage)
+                {
+                    return Error(EGL_BAD_PARAMETER,
+                                 "EGL_GL_TEXTURE_ZOFFSET_KHR cannot be used without "
+                                 "KHR_gl_texture_3D_image support.");
+                }
+                break;
+
+            default:
+                return Error(EGL_BAD_PARAMETER, "invalid attribute: 0x%X", attribute);
+        }
+    }
+
+    switch (target)
+    {
+        case EGL_GL_TEXTURE_2D_KHR:
+        {
+            if (!displayExtensions.glTexture2DImage)
+            {
+                return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_2D_image not supported.");
+            }
+
+            if (buffer == 0)
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "buffer cannot reference a 2D texture with the name 0.");
+            }
+
+            const gl::Texture *texture =
+                context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+            if (texture == nullptr || texture->getTarget() != GL_TEXTURE_2D)
+            {
+                return Error(EGL_BAD_PARAMETER, "target is not a 2D texture.");
+            }
+
+            if (texture->getBoundSurface() != nullptr)
+            {
+                return Error(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+            }
+
+            EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+            if (texture->getWidth(GL_TEXTURE_2D, static_cast<size_t>(level)) == 0 ||
+                texture->getHeight(GL_TEXTURE_2D, static_cast<size_t>(level)) == 0)
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "target 2D texture does not have a valid size at specified level.");
+            }
+
+            ANGLE_TRY(ValidateCreateImageKHRMipLevelCommon(context, texture, level));
+        }
+        break;
+
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+        {
+            if (!displayExtensions.glTextureCubemapImage)
+            {
+                return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_cubemap_image not supported.");
+            }
+
+            if (buffer == 0)
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "buffer cannot reference a cubemap texture with the name 0.");
+            }
+
+            const gl::Texture *texture =
+                context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+            if (texture == nullptr || texture->getTarget() != GL_TEXTURE_CUBE_MAP)
+            {
+                return Error(EGL_BAD_PARAMETER, "target is not a cubemap texture.");
+            }
+
+            if (texture->getBoundSurface() != nullptr)
+            {
+                return Error(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+            }
+
+            EGLAttrib level    = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+            GLenum cubeMapFace = egl_gl::EGLCubeMapTargetToGLCubeMapTarget(target);
+            if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
+                texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "target cubemap texture does not have a valid size at specified level "
+                             "and face.");
+            }
+
+            ANGLE_TRY(ValidateCreateImageKHRMipLevelCommon(context, texture, level));
+
+            if (level == 0 && !texture->isMipmapComplete() &&
+                CubeTextureHasUnspecifiedLevel0Face(texture))
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "if level is zero and the texture is incomplete, it must have all of "
+                             "its faces specified at level zero.");
+            }
+        }
+        break;
+
+        case EGL_GL_TEXTURE_3D_KHR:
+        {
+            if (!displayExtensions.glTexture3DImage)
+            {
+                return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_3D_image not supported.");
+            }
+
+            if (buffer == 0)
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "buffer cannot reference a 3D texture with the name 0.");
+            }
+
+            const gl::Texture *texture =
+                context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+            if (texture == nullptr || texture->getTarget() != GL_TEXTURE_3D)
+            {
+                return Error(EGL_BAD_PARAMETER, "target is not a 3D texture.");
+            }
+
+            if (texture->getBoundSurface() != nullptr)
+            {
+                return Error(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+            }
+
+            EGLAttrib level   = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+            EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0);
+            if (texture->getWidth(GL_TEXTURE_3D, static_cast<size_t>(level)) == 0 ||
+                texture->getHeight(GL_TEXTURE_3D, static_cast<size_t>(level)) == 0 ||
+                texture->getDepth(GL_TEXTURE_3D, static_cast<size_t>(level)) == 0)
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "target 3D texture does not have a valid size at specified level.");
+            }
+
+            if (static_cast<size_t>(zOffset) >=
+                texture->getDepth(GL_TEXTURE_3D, static_cast<size_t>(level)))
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "target 3D texture does not have enough layers for the specified Z "
+                             "offset at the specified level.");
+            }
+
+            ANGLE_TRY(ValidateCreateImageKHRMipLevelCommon(context, texture, level));
+        }
+        break;
+
+        case EGL_GL_RENDERBUFFER_KHR:
+        {
+            if (!displayExtensions.glRenderbufferImage)
+            {
+                return Error(EGL_BAD_PARAMETER, "KHR_gl_renderbuffer_image not supported.");
+            }
+
+            if (attributes.contains(EGL_GL_TEXTURE_LEVEL_KHR))
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "EGL_GL_TEXTURE_LEVEL_KHR cannot be used in conjunction with a "
+                             "renderbuffer target.");
+            }
+
+            if (buffer == 0)
+            {
+                return Error(EGL_BAD_PARAMETER,
+                             "buffer cannot reference a renderbuffer with the name 0.");
+            }
+
+            const gl::Renderbuffer *renderbuffer =
+                context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+            if (renderbuffer == nullptr)
+            {
+                return Error(EGL_BAD_PARAMETER, "target is not a renderbuffer.");
+            }
+
+            if (renderbuffer->getSamples() > 0)
+            {
+                return Error(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled.");
+            }
+        }
+        break;
+
+        default:
+            return Error(EGL_BAD_PARAMETER, "invalid target: 0x%X", target);
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateDestroyImageKHR(const Display *display, const Image *image)
+{
+    ANGLE_TRY(ValidateImage(display, image));
+
+    if (!display->getExtensions().imageBase && !display->getExtensions().image)
+    {
+        // It is out of spec what happens when calling an extension function when the extension is
+        // not available.
+        // EGL_BAD_DISPLAY seems like a reasonable error.
+        return Error(EGL_BAD_DISPLAY);
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateDeviceANGLE(EGLint device_type,
+                                void *native_device,
+                                const EGLAttrib *attrib_list)
+{
+    const ClientExtensions &clientExtensions = Display::getClientExtensions();
+    if (!clientExtensions.deviceCreation)
+    {
+        return Error(EGL_BAD_ACCESS, "Device creation extension not active");
+    }
+
+    if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
+    {
+        return Error(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter");
+    }
+
+    switch (device_type)
+    {
+        case EGL_D3D11_DEVICE_ANGLE:
+            if (!clientExtensions.deviceCreationD3D11)
+            {
+                return Error(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active");
+            }
+            break;
+        default:
+            return Error(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateReleaseDeviceANGLE(Device *device)
+{
+    const ClientExtensions &clientExtensions = Display::getClientExtensions();
+    if (!clientExtensions.deviceCreation)
+    {
+        return Error(EGL_BAD_ACCESS, "Device creation extension not active");
+    }
+
+    if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
+    {
+        return Error(EGL_BAD_DEVICE_EXT, "Invalid device parameter");
+    }
+
+    Display *owningDisplay = device->getOwningDisplay();
+    if (owningDisplay != nullptr)
+    {
+        return Error(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.stream)
+    {
+        return Error(EGL_BAD_ALLOC, "Stream extension not active");
+    }
+
+    for (const auto &attributeIter : attributes)
+    {
+        EGLAttrib attribute = attributeIter.first;
+        EGLAttrib value     = attributeIter.second;
+
+        ANGLE_TRY(ValidateStreamAttribute(attribute, value, displayExtensions));
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream)
+{
+    ANGLE_TRY(ValidateStream(display, stream));
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamAttribKHR(const Display *display,
+                              const Stream *stream,
+                              EGLint attribute,
+                              EGLint value)
+{
+    ANGLE_TRY(ValidateStream(display, stream));
+
+    if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
+    {
+        return Error(EGL_BAD_STATE_KHR, "Bad stream state");
+    }
+
+    return ValidateStreamAttribute(attribute, value, display->getExtensions());
+}
+
+Error ValidateQueryStreamKHR(const Display *display,
+                             const Stream *stream,
+                             EGLenum attribute,
+                             EGLint *value)
+{
+    ANGLE_TRY(ValidateStream(display, stream));
+
+    switch (attribute)
+    {
+        case EGL_STREAM_STATE_KHR:
+        case EGL_CONSUMER_LATENCY_USEC_KHR:
+            break;
+        case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+            if (!display->getExtensions().streamConsumerGLTexture)
+            {
+                return Error(EGL_BAD_ATTRIBUTE, "Consumer GLTexture extension not active");
+            }
+            break;
+        default:
+            return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateQueryStreamu64KHR(const Display *display,
+                                const Stream *stream,
+                                EGLenum attribute,
+                                EGLuint64KHR *value)
+{
+    ANGLE_TRY(ValidateStream(display, stream));
+
+    switch (attribute)
+    {
+        case EGL_CONSUMER_FRAME_KHR:
+        case EGL_PRODUCER_FRAME_KHR:
+            break;
+        default:
+            return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamConsumerGLTextureExternalKHR(const Display *display,
+                                                 gl::Context *context,
+                                                 const Stream *stream)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+    ANGLE_TRY(ValidateContext(display, context));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.streamConsumerGLTexture)
+    {
+        return Error(EGL_BAD_ACCESS, "Stream consumer extension not active");
+    }
+
+    if (!context->getExtensions().eglStreamConsumerExternal)
+    {
+        return Error(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
+    }
+
+    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+    {
+        return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+    }
+
+    if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
+    {
+        return Error(EGL_BAD_STATE_KHR, "Invalid stream state");
+    }
+
+    // Lookup the texture and ensure it is correct
+    gl::Texture *texture = context->getGLState().getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
+    if (texture == nullptr || texture->getId() == 0)
+    {
+        return Error(EGL_BAD_ACCESS, "No external texture bound");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamConsumerAcquireKHR(const Display *display,
+                                       gl::Context *context,
+                                       const Stream *stream)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.streamConsumerGLTexture)
+    {
+        return Error(EGL_BAD_ACCESS, "Stream consumer extension not active");
+    }
+
+    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+    {
+        return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+    }
+
+    if (!context)
+    {
+        return Error(EGL_BAD_ACCESS, "No GL context current to calling thread.");
+    }
+
+    ANGLE_TRY(ValidateContext(display, context));
+
+    if (!stream->isConsumerBoundToContext(context))
+    {
+        return Error(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
+    }
+
+    if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
+        stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
+    {
+        return Error(EGL_BAD_ACCESS, "Invalid stream consumer type");
+    }
+
+    // Note: technically EGL_STREAM_STATE_EMPTY_KHR is a valid state when the timeout is non-zero.
+    // However, the timeout is effectively ignored since it has no useful functionality with the
+    // current producers that are implemented, so we don't allow that state
+    if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+        stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+    {
+        return Error(EGL_BAD_STATE_KHR, "Invalid stream state");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamConsumerReleaseKHR(const Display *display,
+                                       gl::Context *context,
+                                       const Stream *stream)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.streamConsumerGLTexture)
+    {
+        return Error(EGL_BAD_ACCESS, "Stream consumer extension not active");
+    }
+
+    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+    {
+        return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+    }
+
+    if (!context)
+    {
+        return Error(EGL_BAD_ACCESS, "No GL context current to calling thread.");
+    }
+
+    ANGLE_TRY(ValidateContext(display, context));
+
+    if (!stream->isConsumerBoundToContext(context))
+    {
+        return Error(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
+    }
+
+    if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
+        stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
+    {
+        return Error(EGL_BAD_ACCESS, "Invalid stream consumer type");
+    }
+
+    if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+        stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+    {
+        return Error(EGL_BAD_STATE_KHR, "Invalid stream state");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamConsumerGLTextureExternalAttribsNV(const Display *display,
+                                                       gl::Context *context,
+                                                       const Stream *stream,
+                                                       const AttributeMap &attribs)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.streamConsumerGLTexture)
+    {
+        return Error(EGL_BAD_ACCESS, "Stream consumer extension not active");
+    }
+
+    // Although technically not a requirement in spec, the context needs to be checked for support
+    // for external textures or future logic will cause assertations. This extension is also
+    // effectively useless without external textures.
+    if (!context->getExtensions().eglStreamConsumerExternal)
+    {
+        return Error(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
+    }
+
+    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+    {
+        return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+    }
+
+    if (!context)
+    {
+        return Error(EGL_BAD_ACCESS, "No GL context current to calling thread.");
+    }
+
+    ANGLE_TRY(ValidateContext(display, context));
+
+    if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
+    {
+        return Error(EGL_BAD_STATE_KHR, "Invalid stream state");
+    }
+
+    const gl::Caps &glCaps = context->getCaps();
+
+    EGLAttrib colorBufferType = EGL_RGB_BUFFER;
+    EGLAttrib planeCount      = -1;
+    EGLAttrib plane[3];
+    for (int i = 0; i < 3; i++)
+    {
+        plane[i] = -1;
+    }
+    for (const auto &attributeIter : attribs)
+    {
+        EGLAttrib attribute = attributeIter.first;
+        EGLAttrib value     = attributeIter.second;
+
+        switch (attribute)
+        {
+            case EGL_COLOR_BUFFER_TYPE:
+                if (value != EGL_RGB_BUFFER && value != EGL_YUV_BUFFER_EXT)
+                {
+                    return Error(EGL_BAD_PARAMETER, "Invalid color buffer type");
+                }
+                colorBufferType = value;
+                break;
+            case EGL_YUV_NUMBER_OF_PLANES_EXT:
+                // planeCount = -1 is a tag for the default plane count so the value must be checked
+                // to be positive here to ensure future logic doesn't break on invalid negative
+                // inputs
+                if (value < 0)
+                {
+                    return Error(EGL_BAD_MATCH, "Invalid plane count");
+                }
+                planeCount = value;
+                break;
+            default:
+                if (attribute >= EGL_YUV_PLANE0_TEXTURE_UNIT_NV &&
+                    attribute <= EGL_YUV_PLANE2_TEXTURE_UNIT_NV)
+                {
+                    if ((value < 0 ||
+                         value >= static_cast<EGLAttrib>(glCaps.maxCombinedTextureImageUnits)) &&
+                        value != EGL_NONE)
+                    {
+                        return Error(EGL_BAD_ACCESS, "Invalid texture unit");
+                    }
+                    plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
+                }
+                else
+                {
+                    return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+                }
+        }
+    }
+
+    if (colorBufferType == EGL_RGB_BUFFER)
+    {
+        if (planeCount > 0)
+        {
+            return Error(EGL_BAD_MATCH, "Plane count must be 0 for RGB buffer");
+        }
+        for (int i = 0; i < 3; i++)
+        {
+            if (plane[i] != -1)
+            {
+                return Error(EGL_BAD_MATCH, "Planes cannot be specified");
+            }
+        }
+
+        // Lookup the texture and ensure it is correct
+        gl::Texture *texture = context->getGLState().getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
+        if (texture == nullptr || texture->getId() == 0)
+        {
+            return Error(EGL_BAD_ACCESS, "No external texture bound");
+        }
+    }
+    else
+    {
+        if (planeCount == -1)
+        {
+            planeCount = 2;
+        }
+        if (planeCount < 1 || planeCount > 3)
+        {
+            return Error(EGL_BAD_MATCH, "Invalid YUV plane count");
+        }
+        for (EGLAttrib i = planeCount; i < 3; i++)
+        {
+            if (plane[i] != -1)
+            {
+                return Error(EGL_BAD_MATCH, "Invalid plane specified");
+            }
+        }
+
+        // Set to ensure no texture is referenced more than once
+        std::set<gl::Texture *> textureSet;
+        for (EGLAttrib i = 0; i < planeCount; i++)
+        {
+            if (plane[i] == -1)
+            {
+                return Error(EGL_BAD_MATCH, "Not all planes specified");
+            }
+            if (plane[i] != EGL_NONE)
+            {
+                gl::Texture *texture = context->getGLState().getSamplerTexture(
+                    static_cast<unsigned int>(plane[i]), GL_TEXTURE_EXTERNAL_OES);
+                if (texture == nullptr || texture->getId() == 0)
+                {
+                    return Error(
+                        EGL_BAD_ACCESS,
+                        "No external texture bound at one or more specified texture units");
+                }
+                if (textureSet.find(texture) != textureSet.end())
+                {
+                    return Error(EGL_BAD_ACCESS, "Multiple planes bound to same texture object");
+                }
+                textureSet.insert(texture);
+            }
+        }
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateStreamProducerD3DTextureNV12ANGLE(const Display *display,
+                                                      const Stream *stream,
+                                                      const AttributeMap &attribs)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.streamProducerD3DTextureNV12)
+    {
+        return Error(EGL_BAD_ACCESS, "Stream producer extension not active");
+    }
+
+    ANGLE_TRY(ValidateStream(display, stream));
+
+    if (!attribs.isEmpty())
+    {
+        return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+    }
+
+    if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
+    {
+        return Error(EGL_BAD_STATE_KHR, "Stream not in connecting state");
+    }
+
+    if (stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV ||
+        stream->getPlaneCount() != 2)
+    {
+        return Error(EGL_BAD_MATCH, "Incompatible stream consumer type");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamPostD3DTextureNV12ANGLE(const Display *display,
+                                            const Stream *stream,
+                                            void *texture,
+                                            const AttributeMap &attribs)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.streamProducerD3DTextureNV12)
+    {
+        return Error(EGL_BAD_ACCESS, "Stream producer extension not active");
+    }
+
+    ANGLE_TRY(ValidateStream(display, stream));
+
+    for (auto &attributeIter : attribs)
+    {
+        EGLAttrib attribute = attributeIter.first;
+        EGLAttrib value     = attributeIter.second;
+
+        switch (attribute)
+        {
+            case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
+                if (value < 0)
+                {
+                    return Error(EGL_BAD_PARAMETER, "Invalid subresource index");
+                }
+                break;
+            default:
+                return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+        }
+    }
+
+    if (stream->getState() != EGL_STREAM_STATE_EMPTY_KHR &&
+        stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+        stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+    {
+        return Error(EGL_BAD_STATE_KHR, "Stream not fully configured");
+    }
+
+    if (stream->getProducerType() != Stream::ProducerType::D3D11TextureNV12)
+    {
+        return Error(EGL_BAD_MATCH, "Incompatible stream producer");
+    }
+
+    if (texture == nullptr)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "Texture is null");
+    }
+
+    return stream->validateD3D11NV12Texture(texture);
+}
+
+Error ValidateGetSyncValuesCHROMIUM(const Display *display,
+                                    const Surface *surface,
+                                    const EGLuint64KHR *ust,
+                                    const EGLuint64KHR *msc,
+                                    const EGLuint64KHR *sbc)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.getSyncValues)
+    {
+        return Error(EGL_BAD_ACCESS, "getSyncValues extension not active");
+    }
+
+    if (display->isDeviceLost())
+    {
+        return Error(EGL_CONTEXT_LOST, "Context is lost.");
+    }
+
+    if (surface == EGL_NO_SURFACE)
+    {
+        return Error(EGL_BAD_SURFACE, "getSyncValues surface cannot be EGL_NO_SURFACE");
+    }
+
+    if (!surface->directComposition())
+    {
+        return Error(EGL_BAD_SURFACE,
+                     "getSyncValues surface requires Direct Composition to be enabled");
+    }
+
+    if (ust == nullptr)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "ust is null");
+    }
+
+    if (msc == nullptr)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "msc is null");
+    }
+
+    if (sbc == nullptr)
+    {
+        return egl::Error(EGL_BAD_PARAMETER, "sbc is null");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateSwapBuffersWithDamageEXT(const Display *display,
+                                       const Surface *surface,
+                                       EGLint *rects,
+                                       EGLint n_rects)
+{
+    Error error = ValidateSurface(display, surface);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!display->getExtensions().swapBuffersWithDamage)
+    {
+        // It is out of spec what happens when calling an extension function when the extension is
+        // not available. EGL_BAD_DISPLAY seems like a reasonable error.
+        return Error(EGL_BAD_DISPLAY, "EGL_EXT_swap_buffers_with_damage is not available.");
+    }
+
+    if (surface == EGL_NO_SURFACE)
+    {
+        return Error(EGL_BAD_SURFACE, "Swap surface cannot be EGL_NO_SURFACE.");
+    }
+
+    if (n_rects < 0)
+    {
+        return Error(EGL_BAD_PARAMETER, "n_rects cannot be negative.");
+    }
+
+    if (n_rects > 0 && rects == nullptr)
+    {
+        return Error(EGL_BAD_PARAMETER, "n_rects cannot be greater than zero when rects is NULL.");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+Error ValidateGetConfigAttrib(const Display *display, const Config *config, EGLint attribute)
+{
+    ANGLE_TRY(ValidateConfig(display, config));
+    ANGLE_TRY(ValidateConfigAttribute(display, static_cast<EGLAttrib>(attribute)));
+    return NoError();
+}
+
+Error ValidateChooseConfig(const Display *display,
+                           const AttributeMap &attribs,
+                           EGLint configSize,
+                           EGLint *numConfig)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+    ANGLE_TRY(ValidateConfigAttributes(display, attribs));
+
+    if (numConfig == nullptr)
+    {
+        return Error(EGL_BAD_PARAMETER, "num_config cannot be null.");
+    }
+
+    return NoError();
+}
+
+Error ValidateGetConfigs(const Display *display, EGLint configSize, EGLint *numConfig)
+{
+    ANGLE_TRY(ValidateDisplay(display));
+
+    if (numConfig == nullptr)
+    {
+        return Error(EGL_BAD_PARAMETER, "num_config cannot be null.");
+    }
+
+    return NoError();
+}
+
+Error ValidatePlatformType(const ClientExtensions &clientExtensions, EGLint platformType)
+{
+    switch (platformType)
+    {
+        case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+        case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+            if (!clientExtensions.platformANGLED3D)
+            {
+                return Error(EGL_BAD_ATTRIBUTE, "Direct3D platform is unsupported.");
+            }
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+            if (!clientExtensions.platformANGLEOpenGL)
+            {
+                return Error(EGL_BAD_ATTRIBUTE, "OpenGL platform is unsupported.");
+            }
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
+            if (!clientExtensions.platformANGLENULL)
+            {
+                return Error(EGL_BAD_ATTRIBUTE,
+                             "Display type "
+                             "EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE "
+                             "requires EGL_ANGLE_platform_angle_null.");
+            }
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+            if (!clientExtensions.platformANGLEVulkan)
+            {
+                return Error(EGL_BAD_ATTRIBUTE, "Vulkan platform is unsupported.");
+            }
+            break;
+
+        default:
+            return Error(EGL_BAD_ATTRIBUTE, "Unknown platform type.");
+    }
+
+    return Error(EGL_SUCCESS);
+}
+
+}  // namespace egl
diff --git a/src/third_party/angle/src/libANGLE/validationEGL.h b/src/third_party/angle/src/libANGLE/validationEGL.h
new file mode 100644
index 0000000..7c5dbe6
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationEGL.h
@@ -0,0 +1,129 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationEGL.h: Validation functions for generic EGL entry point parameters
+
+#ifndef LIBANGLE_VALIDATIONEGL_H_
+#define LIBANGLE_VALIDATIONEGL_H_
+
+#include "libANGLE/Error.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+namespace gl
+{
+class Context;
+}
+
+namespace egl
+{
+
+class AttributeMap;
+struct ClientExtensions;
+struct Config;
+class Device;
+class Display;
+class Image;
+class Stream;
+class Surface;
+
+// Object validation
+Error ValidateDisplay(const Display *display);
+Error ValidateSurface(const Display *display, const Surface *surface);
+Error ValidateConfig(const Display *display, const Config *config);
+Error ValidateContext(const Display *display, const gl::Context *context);
+Error ValidateImage(const Display *display, const Image *image);
+
+// Entry point validation
+Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
+                            const AttributeMap& attributes);
+
+Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window,
+                                  const AttributeMap& attributes);
+
+Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes);
+Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer,
+                                            Config *config, const AttributeMap& attributes);
+
+Error ValidateMakeCurrent(Display *display, EGLSurface draw, EGLSurface read, gl::Context *context);
+
+Error ValidateCreateImageKHR(const Display *display,
+                             gl::Context *context,
+                             EGLenum target,
+                             EGLClientBuffer buffer,
+                             const AttributeMap &attributes);
+Error ValidateDestroyImageKHR(const Display *display, const Image *image);
+
+Error ValidateCreateDeviceANGLE(EGLint device_type,
+                                void *native_device,
+                                const EGLAttrib *attrib_list);
+Error ValidateReleaseDeviceANGLE(Device *device);
+
+Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes);
+Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream);
+Error ValidateStreamAttribKHR(const Display *display,
+                              const Stream *stream,
+                              EGLint attribute,
+                              EGLint value);
+Error ValidateQueryStreamKHR(const Display *display,
+                             const Stream *stream,
+                             EGLenum attribute,
+                             EGLint *value);
+Error ValidateQueryStreamu64KHR(const Display *display,
+                                const Stream *stream,
+                                EGLenum attribute,
+                                EGLuint64KHR *value);
+Error ValidateStreamConsumerGLTextureExternalKHR(const Display *display,
+                                                 gl::Context *context,
+                                                 const Stream *stream);
+Error ValidateStreamConsumerAcquireKHR(const Display *display,
+                                       gl::Context *context,
+                                       const Stream *stream);
+Error ValidateStreamConsumerReleaseKHR(const Display *display,
+                                       gl::Context *context,
+                                       const Stream *stream);
+Error ValidateStreamConsumerGLTextureExternalAttribsNV(const Display *display,
+                                                       gl::Context *context,
+                                                       const Stream *stream,
+                                                       const AttributeMap &attribs);
+Error ValidateCreateStreamProducerD3DTextureNV12ANGLE(const Display *display,
+                                                      const Stream *stream,
+                                                      const AttributeMap &attribs);
+Error ValidateStreamPostD3DTextureNV12ANGLE(const Display *display,
+                                            const Stream *stream,
+                                            void *texture,
+                                            const AttributeMap &attribs);
+
+Error ValidateGetSyncValuesCHROMIUM(const Display *display,
+                                    const Surface *surface,
+                                    const EGLuint64KHR *ust,
+                                    const EGLuint64KHR *msc,
+                                    const EGLuint64KHR *sbc);
+
+Error ValidateSwapBuffersWithDamageEXT(const Display *display,
+                                       const Surface *surface,
+                                       EGLint *rects,
+                                       EGLint n_rects);
+
+Error ValidateGetConfigAttrib(const Display *display, const Config *config, EGLint attribute);
+Error ValidateChooseConfig(const Display *display,
+                           const AttributeMap &attribs,
+                           EGLint configSize,
+                           EGLint *numConfig);
+Error ValidateGetConfigs(const Display *display, EGLint configSize, EGLint *numConfig);
+
+// Other validation
+Error ValidateCompatibleConfigs(const Display *display,
+                                const Config *config1,
+                                const Surface *surface,
+                                const Config *config2,
+                                EGLint surfaceType);
+
+Error ValidatePlatformType(const ClientExtensions &clientExtensions, EGLint platformType);
+}  // namespace gl
+
+#endif // LIBANGLE_VALIDATIONEGL_H_
diff --git a/src/third_party/angle/src/libANGLE/validationES.cpp b/src/third_party/angle/src/libANGLE/validationES.cpp
new file mode 100644
index 0000000..0bfdc24
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationES.cpp
@@ -0,0 +1,5566 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// validationES.h: Validation functions for generic OpenGL ES entry point parameters
+
+#include "libANGLE/validationES.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+using namespace angle;
+
+namespace gl
+{
+const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
+
+namespace
+{
+bool ValidateDrawAttribs(ValidationContext *context,
+                         GLint primcount,
+                         GLint maxVertex,
+                         GLint vertexCount)
+{
+    const gl::State &state     = context->getGLState();
+    const gl::Program *program = state.getProgram();
+
+    bool webglCompatibility = context->getExtensions().webglCompatibility;
+
+    const VertexArray *vao     = state.getVertexArray();
+    const auto &vertexAttribs  = vao->getVertexAttributes();
+    const auto &vertexBindings = vao->getVertexBindings();
+    size_t maxEnabledAttrib    = vao->getMaxEnabledAttribute();
+    for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
+    {
+        const VertexAttribute &attrib = vertexAttribs[attributeIndex];
+        if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
+        {
+            continue;
+        }
+
+        const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
+        // If we have no buffer, then we either get an error, or there are no more checks to be
+        // done.
+        gl::Buffer *buffer = binding.buffer.get();
+        if (!buffer)
+        {
+            if (webglCompatibility || !state.areClientArraysEnabled())
+            {
+                // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
+                // If a vertex attribute is enabled as an array via enableVertexAttribArray but
+                // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
+                // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
+                // error.
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
+                return false;
+            }
+            else if (attrib.pointer == nullptr)
+            {
+                // This is an application error that would normally result in a crash,
+                // but we catch it and return an error
+                context->handleError(Error(
+                    GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
+                return false;
+            }
+            continue;
+        }
+
+        // If we're drawing zero vertices, we have enough data.
+        if (vertexCount <= 0 || primcount <= 0)
+        {
+            continue;
+        }
+
+        GLint maxVertexElement = 0;
+        if (binding.divisor == 0)
+        {
+            maxVertexElement = maxVertex;
+        }
+        else
+        {
+            maxVertexElement = (primcount - 1) / binding.divisor;
+        }
+
+        // We do manual overflow checks here instead of using safe_math.h because it was
+        // a bottleneck. Thanks to some properties of GL we know inequalities that can
+        // help us make the overflow checks faster.
+
+        // The max possible attribSize is 16 for a vector of 4 32 bit values.
+        constexpr uint64_t kMaxAttribSize = 16;
+        constexpr uint64_t kIntMax        = std::numeric_limits<int>::max();
+        constexpr uint64_t kUint64Max     = std::numeric_limits<uint64_t>::max();
+
+        // We know attribStride is given as a GLsizei which is typedefed to int.
+        // We also know an upper bound for attribSize.
+        static_assert(std::is_same<int, GLsizei>::value, "");
+        uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
+        uint64_t attribSize   = ComputeVertexAttributeTypeSize(attrib);
+        ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
+
+        // Computing the max offset using uint64_t without attrib.offset is overflow
+        // safe. Note: Last vertex element does not take the full stride!
+        static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
+        uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
+
+        // An overflow can happen when adding the offset, check for it.
+        uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
+        if (attribDataSizeNoOffset > kUint64Max - attribOffset)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
+            return false;
+        }
+        uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
+
+        // [OpenGL ES 3.0.2] section 2.9.4 page 40:
+        // We can return INVALID_OPERATION if our vertex attribute does not have
+        // enough backing data.
+        if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "Vertex buffer is not big enough for the draw call"));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidReadPixelsFormatType(ValidationContext *context,
+                               GLenum framebufferComponentType,
+                               GLenum format,
+                               GLenum type)
+{
+    switch (framebufferComponentType)
+    {
+        case GL_UNSIGNED_NORMALIZED:
+            // TODO(geofflang): Don't accept BGRA here.  Some chrome internals appear to try to use
+            // ReadPixels with BGRA even if the extension is not present
+            return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
+                   (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
+                    type == GL_UNSIGNED_BYTE);
+
+        case GL_SIGNED_NORMALIZED:
+            return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
+
+        case GL_INT:
+            return (format == GL_RGBA_INTEGER && type == GL_INT);
+
+        case GL_UNSIGNED_INT:
+            return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
+
+        case GL_FLOAT:
+            return (format == GL_RGBA && type == GL_FLOAT);
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+template <typename ParamType>
+bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
+{
+    switch (ConvertToGLenum(params[0]))
+    {
+        case GL_CLAMP_TO_EDGE:
+            break;
+
+        case GL_REPEAT:
+        case GL_MIRRORED_REPEAT:
+            if (isExternalTextureTarget)
+            {
+                // OES_EGL_image_external specifies this error.
+                context->handleError(Error(
+                    GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+            return false;
+    }
+
+    return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureMinFilterValue(Context *context,
+                                   ParamType *params,
+                                   bool isExternalTextureTarget)
+{
+    switch (ConvertToGLenum(params[0]))
+    {
+        case GL_NEAREST:
+        case GL_LINEAR:
+            break;
+
+        case GL_NEAREST_MIPMAP_NEAREST:
+        case GL_LINEAR_MIPMAP_NEAREST:
+        case GL_NEAREST_MIPMAP_LINEAR:
+        case GL_LINEAR_MIPMAP_LINEAR:
+            if (isExternalTextureTarget)
+            {
+                // OES_EGL_image_external specifies this error.
+                context->handleError(
+                    Error(GL_INVALID_ENUM,
+                          "external textures only support NEAREST and LINEAR filtering"));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+            return false;
+    }
+
+    return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
+{
+    switch (ConvertToGLenum(params[0]))
+    {
+        case GL_NEAREST:
+        case GL_LINEAR:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+            return false;
+    }
+
+    return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
+{
+    // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
+    switch (ConvertToGLenum(params[0]))
+    {
+        case GL_NONE:
+        case GL_COMPARE_REF_TO_TEXTURE:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+            return false;
+    }
+
+    return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
+{
+    // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
+    switch (ConvertToGLenum(params[0]))
+    {
+        case GL_LEQUAL:
+        case GL_GEQUAL:
+        case GL_LESS:
+        case GL_GREATER:
+        case GL_EQUAL:
+        case GL_NOTEQUAL:
+        case GL_ALWAYS:
+        case GL_NEVER:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+            return false;
+    }
+
+    return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
+{
+    if (!context->getExtensions().textureSRGBDecode)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
+        return false;
+    }
+
+    switch (ConvertToGLenum(params[0]))
+    {
+        case GL_DECODE_EXT:
+        case GL_SKIP_DECODE_EXT:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+            return false;
+    }
+
+    return true;
+}
+
+template <typename ParamType>
+bool ValidateSamplerParameterBase(Context *context,
+                                  GLuint sampler,
+                                  GLenum pname,
+                                  GLsizei bufSize,
+                                  ParamType *params)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+        return false;
+    }
+
+    if (!context->isSampler(sampler))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
+        return false;
+    }
+
+    const GLsizei minBufSize = 1;
+    if (bufSize >= 0 && bufSize < minBufSize)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_TEXTURE_WRAP_S:
+        case GL_TEXTURE_WRAP_T:
+        case GL_TEXTURE_WRAP_R:
+            if (!ValidateTextureWrapModeValue(context, params, false))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_MIN_FILTER:
+            if (!ValidateTextureMinFilterValue(context, params, false))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_MAG_FILTER:
+            if (!ValidateTextureMagFilterValue(context, params))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_MIN_LOD:
+        case GL_TEXTURE_MAX_LOD:
+            // any value is permissible
+            break;
+
+        case GL_TEXTURE_COMPARE_MODE:
+            if (!ValidateTextureCompareModeValue(context, params))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_COMPARE_FUNC:
+            if (!ValidateTextureCompareFuncValue(context, params))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_SRGB_DECODE_EXT:
+            if (!ValidateTextureSRGBDecodeValue(context, params))
+            {
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetSamplerParameterBase(Context *context,
+                                     GLuint sampler,
+                                     GLenum pname,
+                                     GLsizei *length)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+        return false;
+    }
+
+    if (!context->isSampler(sampler))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_TEXTURE_WRAP_S:
+        case GL_TEXTURE_WRAP_T:
+        case GL_TEXTURE_WRAP_R:
+        case GL_TEXTURE_MIN_FILTER:
+        case GL_TEXTURE_MAG_FILTER:
+        case GL_TEXTURE_MIN_LOD:
+        case GL_TEXTURE_MAX_LOD:
+        case GL_TEXTURE_COMPARE_MODE:
+        case GL_TEXTURE_COMPARE_FUNC:
+            break;
+
+        case GL_TEXTURE_SRGB_DECODE_EXT:
+            if (!context->getExtensions().textureSRGBDecode)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    if (length)
+    {
+        *length = 1;
+    }
+    return true;
+}
+
+bool ValidateGetActiveUniformBlockivBase(Context *context,
+                                         GLuint program,
+                                         GLuint uniformBlockIndex,
+                                         GLenum pname,
+                                         GLsizei *length)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+    if (!programObject)
+    {
+        return false;
+    }
+
+    if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_UNIFORM_BLOCK_BINDING:
+        case GL_UNIFORM_BLOCK_DATA_SIZE:
+        case GL_UNIFORM_BLOCK_NAME_LENGTH:
+        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+        case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+        case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    if (length)
+    {
+        if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
+        {
+            const UniformBlock &uniformBlock =
+                programObject->getUniformBlockByIndex(uniformBlockIndex);
+            *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
+        }
+        else
+        {
+            *length = 1;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateGetInternalFormativBase(Context *context,
+                                     GLenum target,
+                                     GLenum internalformat,
+                                     GLenum pname,
+                                     GLsizei bufSize,
+                                     GLsizei *numParams)
+{
+    if (numParams)
+    {
+        *numParams = 0;
+    }
+
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+        return false;
+    }
+
+    const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+    if (!formatCaps.renderable)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
+        return false;
+    }
+
+    switch (target)
+    {
+        case GL_RENDERBUFFER:
+            break;
+
+        case GL_TEXTURE_2D_MULTISAMPLE:
+            if (context->getClientVersion() < ES_3_1)
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
+            return false;
+    }
+
+    if (bufSize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+        return false;
+    }
+
+    GLsizei maxWriteParams = 0;
+    switch (pname)
+    {
+        case GL_NUM_SAMPLE_COUNTS:
+            maxWriteParams = 1;
+            break;
+
+        case GL_SAMPLES:
+            maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    if (numParams)
+    {
+        // glGetInternalFormativ will not overflow bufSize
+        *numParams = std::min(bufSize, maxWriteParams);
+    }
+
+    return true;
+}
+
+bool ValidateUniformCommonBase(ValidationContext *context,
+                               gl::Program *program,
+                               GLint location,
+                               GLsizei count,
+                               const LinkedUniform **uniformOut)
+{
+    // TODO(Jiajia): Add image uniform check in future.
+    if (count < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (!program || !program->isLinked())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (location == -1)
+    {
+        // Silently ignore the uniform command
+        return false;
+    }
+
+    const auto &uniformLocations = program->getUniformLocations();
+    size_t castedLocation        = static_cast<size_t>(location);
+    if (castedLocation >= uniformLocations.size())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
+        return false;
+    }
+
+    const auto &uniformLocation = uniformLocations[castedLocation];
+    if (uniformLocation.ignored)
+    {
+        // Silently ignore the uniform command
+        return false;
+    }
+
+    if (!uniformLocation.used)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const auto &uniform = program->getUniformByIndex(uniformLocation.index);
+
+    // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+    if (!uniform.isArray() && count > 1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    *uniformOut = &uniform;
+    return true;
+}
+
+bool ValidateUniform1ivValue(ValidationContext *context,
+                             GLenum uniformType,
+                             GLsizei count,
+                             const GLint *value)
+{
+    // Value type is GL_INT, because we only get here from glUniform1i{v}.
+    // It is compatible with INT or BOOL.
+    // Do these cheap tests first, for a little extra speed.
+    if (GL_INT == uniformType || GL_BOOL == uniformType)
+    {
+        return true;
+    }
+
+    if (IsSamplerType(uniformType))
+    {
+        // Check that the values are in range.
+        const GLint max = context->getCaps().maxCombinedTextureImageUnits;
+        for (GLsizei i = 0; i < count; ++i)
+        {
+            if (value[i] < 0 || value[i] >= max)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
+                return false;
+            }
+        }
+        return true;
+    }
+
+    context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
+    return false;
+}
+
+bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
+{
+    // Check that the value type is compatible with uniform type.
+    // Do the cheaper test first, for a little extra speed.
+    if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
+    {
+        return true;
+    }
+
+    context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
+    return false;
+}
+
+bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
+{
+    // Check that the value type is compatible with uniform type.
+    if (valueType == uniformType)
+    {
+        return true;
+    }
+
+    context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
+    return false;
+}
+
+}  // anonymous namespace
+
+bool ValidTextureTarget(const ValidationContext *context, GLenum target)
+{
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+        case GL_TEXTURE_CUBE_MAP:
+            return true;
+
+        case GL_TEXTURE_3D:
+        case GL_TEXTURE_2D_ARRAY:
+            return (context->getClientMajorVersion() >= 3);
+
+        case GL_TEXTURE_2D_MULTISAMPLE:
+            return (context->getClientVersion() >= Version(3, 1));
+
+        default:
+            return false;
+    }
+}
+
+bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
+{
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+        case GL_TEXTURE_CUBE_MAP:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
+{
+    switch (target)
+    {
+        case GL_TEXTURE_3D:
+        case GL_TEXTURE_2D_ARRAY:
+            return (context->getClientMajorVersion() >= 3);
+
+        default:
+            return false;
+    }
+}
+
+// Most texture GL calls are not compatible with external textures, so we have a separate validation
+// function for use in the GL calls that do
+bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
+{
+    return (target == GL_TEXTURE_EXTERNAL_OES) &&
+           (context->getExtensions().eglImageExternal ||
+            context->getExtensions().eglStreamConsumerExternal);
+}
+
+// This function differs from ValidTextureTarget in that the target must be
+// usable as the destination of a 2D operation-- so a cube face is valid, but
+// GL_TEXTURE_CUBE_MAP is not.
+// Note: duplicate of IsInternalTextureTarget
+bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
+{
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool ValidateDrawElementsInstancedBase(ValidationContext *context,
+                                       GLenum mode,
+                                       GLsizei count,
+                                       GLenum type,
+                                       const GLvoid *indices,
+                                       GLsizei primcount)
+{
+    if (primcount < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
+        return false;
+    }
+
+    if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
+    {
+        return false;
+    }
+
+    // No-op zero primitive count
+    return (primcount > 0);
+}
+
+bool ValidateDrawArraysInstancedBase(Context *context,
+                                     GLenum mode,
+                                     GLint first,
+                                     GLsizei count,
+                                     GLsizei primcount)
+{
+    if (primcount < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
+        return false;
+    }
+
+    if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
+    {
+        return false;
+    }
+
+    // No-op if zero primitive count
+    return (primcount > 0);
+}
+
+bool ValidateDrawInstancedANGLEAndWebGL(ValidationContext *context)
+{
+    // Verify there is at least one active attribute with a divisor of zero
+    const State &state = context->getGLState();
+
+    Program *program = state.getProgram();
+
+    const auto &attribs  = state.getVertexArray()->getVertexAttributes();
+    const auto &bindings = state.getVertexArray()->getVertexBindings();
+    for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        const VertexAttribute &attrib = attribs[attributeIndex];
+        const VertexBinding &binding  = bindings[attrib.bindingIndex];
+        if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
+        {
+            return true;
+        }
+    }
+
+    context->handleError(
+        Error(GL_INVALID_OPERATION, "At least one attribute must have a divisor of zero."));
+    return false;
+}
+
+bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
+{
+    switch (target)
+    {
+        case GL_TEXTURE_3D:
+        case GL_TEXTURE_2D_ARRAY:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
+{
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+        case GL_TEXTURE_3D:
+        case GL_TEXTURE_2D_ARRAY:
+        case GL_TEXTURE_2D_MULTISAMPLE:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool ValidFramebufferTarget(GLenum target)
+{
+    static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
+                      GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
+                  "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
+
+    switch (target)
+    {
+        case GL_FRAMEBUFFER:
+            return true;
+        case GL_READ_FRAMEBUFFER:
+            return true;
+        case GL_DRAW_FRAMEBUFFER:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool ValidBufferTarget(const ValidationContext *context, GLenum target)
+{
+    switch (target)
+    {
+        case GL_ARRAY_BUFFER:
+        case GL_ELEMENT_ARRAY_BUFFER:
+            return true;
+
+        case GL_PIXEL_PACK_BUFFER:
+        case GL_PIXEL_UNPACK_BUFFER:
+            return (context->getExtensions().pixelBufferObject ||
+                    context->getClientMajorVersion() >= 3);
+
+        case GL_COPY_READ_BUFFER:
+        case GL_COPY_WRITE_BUFFER:
+        case GL_TRANSFORM_FEEDBACK_BUFFER:
+        case GL_UNIFORM_BUFFER:
+            return (context->getClientMajorVersion() >= 3);
+
+        case GL_ATOMIC_COUNTER_BUFFER:
+        case GL_SHADER_STORAGE_BUFFER:
+        case GL_DRAW_INDIRECT_BUFFER:
+        case GL_DISPATCH_INDIRECT_BUFFER:
+            return context->getClientVersion() >= Version(3, 1);
+
+        default:
+            return false;
+    }
+}
+
+bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
+{
+    const auto &caps    = context->getCaps();
+    size_t maxDimension = 0;
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+            maxDimension = caps.max2DTextureSize;
+            break;
+        case GL_TEXTURE_CUBE_MAP:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+            maxDimension = caps.maxCubeMapTextureSize;
+            break;
+        case GL_TEXTURE_3D:
+            maxDimension = caps.max3DTextureSize;
+            break;
+        case GL_TEXTURE_2D_ARRAY:
+            maxDimension = caps.max2DTextureSize;
+            break;
+        case GL_TEXTURE_2D_MULTISAMPLE:
+            maxDimension = caps.max2DTextureSize;
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return level <= gl::log2(static_cast<int>(maxDimension));
+}
+
+bool ValidImageSizeParameters(const ValidationContext *context,
+                              GLenum target,
+                              GLint level,
+                              GLsizei width,
+                              GLsizei height,
+                              GLsizei depth,
+                              bool isSubImage)
+{
+    if (level < 0 || width < 0 || height < 0 || depth < 0)
+    {
+        return false;
+    }
+
+    // TexSubImage parameters can be NPOT without textureNPOT extension,
+    // as long as the destination texture is POT.
+    bool hasNPOTSupport =
+        context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
+    if (!isSubImage && !hasNPOTSupport &&
+        (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
+    {
+        return false;
+    }
+
+    if (!ValidMipLevel(context, target, level))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
+{
+    // List of compressed format that require that the texture size is smaller than or a multiple of
+    // the compressed block size.
+    switch (internalFormat)
+    {
+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+        case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+        case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+        case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+        case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+        case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+        case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
+        case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
+{
+    return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
+           (size % blockSize == 0);
+}
+
+bool ValidCompressedImageSize(const ValidationContext *context,
+                              GLenum internalFormat,
+                              GLint level,
+                              GLsizei width,
+                              GLsizei height)
+{
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+    if (!formatInfo.compressed)
+    {
+        return false;
+    }
+
+    if (width < 0 || height < 0)
+    {
+        return false;
+    }
+
+    if (CompressedTextureFormatRequiresExactSize(internalFormat))
+    {
+        // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
+        // block size for level 0 but WebGL disallows this.
+        bool smallerThanBlockSizeAllowed =
+            level > 0 || !context->getExtensions().webglCompatibility;
+
+        if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
+                                      smallerThanBlockSizeAllowed) ||
+            !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
+                                      smallerThanBlockSizeAllowed))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidCompressedSubImageSize(const ValidationContext *context,
+                                 GLenum internalFormat,
+                                 GLint xoffset,
+                                 GLint yoffset,
+                                 GLsizei width,
+                                 GLsizei height,
+                                 size_t textureWidth,
+                                 size_t textureHeight)
+{
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+    if (!formatInfo.compressed)
+    {
+        return false;
+    }
+
+    if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+    {
+        return false;
+    }
+
+    if (CompressedTextureFormatRequiresExactSize(internalFormat))
+    {
+        if (xoffset % formatInfo.compressedBlockWidth != 0 ||
+            yoffset % formatInfo.compressedBlockHeight != 0)
+        {
+            return false;
+        }
+
+        // Allowed to either have data that is a multiple of block size or is smaller than the block
+        // size but fills the entire mip
+        bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
+                              static_cast<size_t>(width) == textureWidth &&
+                              static_cast<size_t>(height) == textureHeight;
+        bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
+                                       (height % formatInfo.compressedBlockHeight) == 0;
+        if (!sizeMultipleOfBlockSize && !fillsEntireMip)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidImageDataSize(ValidationContext *context,
+                        GLenum textureTarget,
+                        GLsizei width,
+                        GLsizei height,
+                        GLsizei depth,
+                        GLenum internalFormat,
+                        GLenum type,
+                        const void *pixels,
+                        GLsizei imageSize)
+{
+    gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
+    if (pixelUnpackBuffer == nullptr && imageSize < 0)
+    {
+        // Checks are not required
+        return true;
+    }
+
+    // ...the data would be unpacked from the buffer object such that the memory reads required
+    // would exceed the data store size.
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+    const gl::Extents size(width, height, depth);
+    const auto &unpack = context->getGLState().getUnpackState();
+
+    bool targetIs3D   = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
+    auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
+    if (endByteOrErr.isError())
+    {
+        context->handleError(endByteOrErr.getError());
+        return false;
+    }
+
+    GLuint endByte = endByteOrErr.getResult();
+
+    if (pixelUnpackBuffer)
+    {
+        CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
+        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
+        checkedEndByte += checkedOffset;
+
+        if (!checkedEndByte.IsValid() ||
+            (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
+        {
+            // Overflow past the end of the buffer
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+    else
+    {
+        ASSERT(imageSize >= 0);
+        if (pixels == nullptr && imageSize != 0)
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
+            return false;
+        }
+
+        if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidQueryType(const Context *context, GLenum queryType)
+{
+    static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
+                  "GL extension enums not equal.");
+    static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
+                  "GL extension enums not equal.");
+
+    switch (queryType)
+    {
+        case GL_ANY_SAMPLES_PASSED:
+        case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+            return true;
+        case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+            return (context->getClientMajorVersion() >= 3);
+        case GL_TIME_ELAPSED_EXT:
+            return context->getExtensions().disjointTimerQuery;
+        case GL_COMMANDS_COMPLETED_CHROMIUM:
+            return context->getExtensions().syncQuery;
+        default:
+            return false;
+    }
+}
+
+bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
+                                      GLenum type,
+                                      GLboolean normalized,
+                                      GLsizei stride,
+                                      const void *ptr,
+                                      bool pureInteger)
+{
+    ASSERT(context->getExtensions().webglCompatibility);
+
+    // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
+    // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
+    // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
+    // parameter exceeds 255.
+    constexpr GLsizei kMaxWebGLStride = 255;
+    if (stride > kMaxWebGLStride)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
+        return false;
+    }
+
+    // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
+    // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
+    // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
+    // or an INVALID_OPERATION error is generated.
+    VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
+    size_t typeSize               = GetVertexFormatTypeSize(internalType);
+
+    ASSERT(isPow2(typeSize) && typeSize > 0);
+    size_t sizeMask = (typeSize - 1);
+    if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
+        return false;
+    }
+
+    if ((stride & sizeMask) != 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
+        return false;
+    }
+
+    return true;
+}
+
+Program *GetValidProgram(ValidationContext *context, GLuint id)
+{
+    // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
+    // generate the error INVALID_VALUE if the provided name is not the name of either a shader
+    // or program object and INVALID_OPERATION if the provided name identifies an object
+    // that is not the expected type."
+
+    Program *validProgram = context->getProgram(id);
+
+    if (!validProgram)
+    {
+        if (context->getShader(id))
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
+        }
+        else
+        {
+            context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
+        }
+    }
+
+    return validProgram;
+}
+
+Shader *GetValidShader(ValidationContext *context, GLuint id)
+{
+    // See ValidProgram for spec details.
+
+    Shader *validShader = context->getShader(id);
+
+    if (!validShader)
+    {
+        if (context->getProgram(id))
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
+        }
+        else
+        {
+            context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
+        }
+    }
+
+    return validShader;
+}
+
+bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
+{
+    if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+    {
+        const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
+
+        if (colorAttachment >= context->getCaps().maxColorAttachments)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+    }
+    else
+    {
+        switch (attachment)
+        {
+            case GL_DEPTH_ATTACHMENT:
+            case GL_STENCIL_ATTACHMENT:
+                break;
+
+            case GL_DEPTH_STENCIL_ATTACHMENT:
+                if (!context->getExtensions().webglCompatibility &&
+                    context->getClientMajorVersion() < 3)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+
+            default:
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
+                                               GLenum target,
+                                               GLsizei samples,
+                                               GLenum internalformat,
+                                               GLsizei width,
+                                               GLsizei height)
+{
+    switch (target)
+    {
+        case GL_RENDERBUFFER:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    if (width < 0 || height < 0 || samples < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+    GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
+
+    const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
+    if (!formatCaps.renderable)
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
+    // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
+    // only sized internal formats.
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
+    if (formatInfo.internalFormat == GL_NONE)
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    GLuint handle = context->getGLState().getRenderbufferId();
+    if (handle == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
+                                               GLenum target,
+                                               GLenum attachment,
+                                               GLenum renderbuffertarget,
+                                               GLuint renderbuffer)
+{
+    if (!ValidFramebufferTarget(target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+
+    ASSERT(framebuffer);
+    if (framebuffer->id() == 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
+        return false;
+    }
+
+    if (!ValidateAttachmentTarget(context, attachment))
+    {
+        return false;
+    }
+
+    // [OpenGL ES 2.0.25] Section 4.4.3 page 112
+    // [OpenGL ES 3.0.2] Section 4.4.2 page 201
+    // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
+    // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
+    if (renderbuffer != 0)
+    {
+        if (!context->getRenderbuffer(renderbuffer))
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateBlitFramebufferParameters(ValidationContext *context,
+                                       GLint srcX0,
+                                       GLint srcY0,
+                                       GLint srcX1,
+                                       GLint srcY1,
+                                       GLint dstX0,
+                                       GLint dstY0,
+                                       GLint dstX1,
+                                       GLint dstY1,
+                                       GLbitfield mask,
+                                       GLenum filter)
+{
+    switch (filter)
+    {
+        case GL_NEAREST:
+            break;
+        case GL_LINEAR:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (mask == 0)
+    {
+        // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
+        // buffers are copied.
+        return false;
+    }
+
+    // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
+    // color buffer, leaving only nearest being unfiltered from above
+    if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const auto &glState              = context->getGLState();
+    gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
+    gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+
+    if (!readFramebuffer || !drawFramebuffer)
+    {
+        context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    if (readFramebuffer->id() == drawFramebuffer->id())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    if (drawFramebuffer->getSamples(context) != 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
+
+    if (mask & GL_COLOR_BUFFER_BIT)
+    {
+        const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
+        const Extensions &extensions                     = context->getExtensions();
+
+        if (readColorBuffer)
+        {
+            const Format &readFormat = readColorBuffer->getFormat();
+
+            for (size_t drawbufferIdx = 0;
+                 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
+            {
+                const FramebufferAttachment *attachment =
+                    drawFramebuffer->getDrawBuffer(drawbufferIdx);
+                if (attachment)
+                {
+                    const Format &drawFormat = attachment->getFormat();
+
+                    // The GL ES 3.0.2 spec (pg 193) states that:
+                    // 1) If the read buffer is fixed point format, the draw buffer must be as well
+                    // 2) If the read buffer is an unsigned integer format, the draw buffer must be
+                    // as well
+                    // 3) If the read buffer is a signed integer format, the draw buffer must be as
+                    // well
+                    // Changes with EXT_color_buffer_float:
+                    // Case 1) is changed to fixed point OR floating point
+                    GLenum readComponentType = readFormat.info->componentType;
+                    GLenum drawComponentType = drawFormat.info->componentType;
+                    bool readFixedPoint      = (readComponentType == GL_UNSIGNED_NORMALIZED ||
+                                           readComponentType == GL_SIGNED_NORMALIZED);
+                    bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
+                                           drawComponentType == GL_SIGNED_NORMALIZED);
+
+                    if (extensions.colorBufferFloat)
+                    {
+                        bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
+                        bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
+
+                        if (readFixedOrFloat != drawFixedOrFloat)
+                        {
+                            context->handleError(Error(GL_INVALID_OPERATION,
+                                                       "If the read buffer contains fixed-point or "
+                                                       "floating-point values, the draw buffer "
+                                                       "must as well."));
+                            return false;
+                        }
+                    }
+                    else if (readFixedPoint != drawFixedPoint)
+                    {
+                        context->handleError(Error(GL_INVALID_OPERATION,
+                                                   "If the read buffer contains fixed-point "
+                                                   "values, the draw buffer must as well."));
+                        return false;
+                    }
+
+                    if (readComponentType == GL_UNSIGNED_INT &&
+                        drawComponentType != GL_UNSIGNED_INT)
+                    {
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                    }
+
+                    if (readComponentType == GL_INT && drawComponentType != GL_INT)
+                    {
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                    }
+
+                    if (readColorBuffer->getSamples() > 0 &&
+                        (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
+                    {
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                    }
+
+                    if (context->getExtensions().webglCompatibility &&
+                        *readColorBuffer == *attachment)
+                    {
+                        context->handleError(
+                            Error(GL_INVALID_OPERATION,
+                                  "Read and write color attachments cannot be the same image."));
+                        return false;
+                    }
+                }
+            }
+
+            if ((readFormat.info->componentType == GL_INT ||
+                 readFormat.info->componentType == GL_UNSIGNED_INT) &&
+                filter == GL_LINEAR)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+        }
+        // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
+        // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
+        // attachment and WebGL defines it to be an error. We do the check unconditionally as the
+        // situation is an application error that would lead to a crash in ANGLE.
+        else if (drawFramebuffer->hasEnabledDrawBuffer())
+        {
+            context->handleError(Error(
+                GL_INVALID_OPERATION,
+                "Attempt to read from a missing color attachment of a complete framebuffer."));
+            return false;
+        }
+    }
+
+    GLenum masks[]       = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
+    GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
+    for (size_t i = 0; i < 2; i++)
+    {
+        if (mask & masks[i])
+        {
+            const gl::FramebufferAttachment *readBuffer =
+                readFramebuffer->getAttachment(attachments[i]);
+            const gl::FramebufferAttachment *drawBuffer =
+                drawFramebuffer->getAttachment(attachments[i]);
+
+            if (readBuffer && drawBuffer)
+            {
+                if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+
+                if (readBuffer->getSamples() > 0 && !sameBounds)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+
+                if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
+                {
+                    context->handleError(Error(
+                        GL_INVALID_OPERATION,
+                        "Read and write depth stencil attachments cannot be the same image."));
+                    return false;
+                }
+            }
+            // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
+            else if (drawBuffer)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION,
+                                           "Attempt to read from a missing depth/stencil "
+                                           "attachment of a complete framebuffer."));
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
+                                   GLint x,
+                                   GLint y,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   GLenum format,
+                                   GLenum type,
+                                   GLsizei bufSize,
+                                   GLsizei *length,
+                                   GLsizei *columns,
+                                   GLsizei *rows,
+                                   void *pixels)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
+                                columns, rows, pixels))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateReadnPixelsEXT(Context *context,
+                            GLint x,
+                            GLint y,
+                            GLsizei width,
+                            GLsizei height,
+                            GLenum format,
+                            GLenum type,
+                            GLsizei bufSize,
+                            void *pixels)
+{
+    if (bufSize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
+        return false;
+    }
+
+    return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
+                                  nullptr, nullptr, pixels);
+}
+
+bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
+                                    GLint x,
+                                    GLint y,
+                                    GLsizei width,
+                                    GLsizei height,
+                                    GLenum format,
+                                    GLenum type,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLsizei *columns,
+                                    GLsizei *rows,
+                                    void *data)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
+                                columns, rows, data))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
+{
+    if (!context->getExtensions().occlusionQueryBoolean &&
+        !context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+        return false;
+    }
+
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
+{
+    if (!context->getExtensions().occlusionQueryBoolean &&
+        !context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+        return false;
+    }
+
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
+{
+    if (!ValidQueryType(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
+        return false;
+    }
+
+    if (id == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
+        return false;
+    }
+
+    // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
+    // of zero, if the active query object name for <target> is non-zero (for the
+    // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
+    // the active query for either target is non-zero), if <id> is the name of an
+    // existing query object whose type does not match <target>, or if <id> is the
+    // active query object name for any query type, the error INVALID_OPERATION is
+    // generated.
+
+    // Ensure no other queries are active
+    // NOTE: If other queries than occlusion are supported, we will need to check
+    // separately that:
+    //    a) The query ID passed is not the current active query for any target/type
+    //    b) There are no active queries for the requested target (and in the case
+    //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
+    //       no query may be active for either if glBeginQuery targets either.
+
+    if (context->getGLState().isQueryActive(target))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
+        return false;
+    }
+
+    Query *queryObject = context->getQuery(id, true, target);
+
+    // check that name was obtained with glGenQueries
+    if (!queryObject)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
+        return false;
+    }
+
+    // check for type mismatch
+    if (queryObject->getType() != target)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
+{
+    if (!context->getExtensions().occlusionQueryBoolean &&
+        !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+        return false;
+    }
+
+    return ValidateBeginQueryBase(context, target, id);
+}
+
+bool ValidateEndQueryBase(gl::Context *context, GLenum target)
+{
+    if (!ValidQueryType(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
+        return false;
+    }
+
+    const Query *queryObject = context->getGLState().getActiveQuery(target);
+
+    if (queryObject == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
+{
+    if (!context->getExtensions().occlusionQueryBoolean &&
+        !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+        return false;
+    }
+
+    return ValidateEndQueryBase(context, target);
+}
+
+bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
+        return false;
+    }
+
+    if (target != GL_TIMESTAMP_EXT)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
+        return false;
+    }
+
+    Query *queryObject = context->getQuery(id, true, target);
+    if (queryObject == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
+        return false;
+    }
+
+    if (context->getGLState().isQueryActive(queryObject))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
+{
+    if (numParams)
+    {
+        *numParams = 0;
+    }
+
+    if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_CURRENT_QUERY_EXT:
+            if (target == GL_TIMESTAMP_EXT)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
+                return false;
+            }
+            break;
+        case GL_QUERY_COUNTER_BITS_EXT:
+            if (!context->getExtensions().disjointTimerQuery ||
+                (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
+                return false;
+            }
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
+            return false;
+    }
+
+    if (numParams)
+    {
+        // All queries return only one value
+        *numParams = 1;
+    }
+
+    return true;
+}
+
+bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
+{
+    if (!context->getExtensions().occlusionQueryBoolean &&
+        !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+        return false;
+    }
+
+    return ValidateGetQueryivBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetQueryivRobustANGLE(Context *context,
+                                   GLenum target,
+                                   GLenum pname,
+                                   GLsizei bufSize,
+                                   GLsizei *length,
+                                   GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryivBase(context, target, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
+{
+    if (numParams)
+    {
+        *numParams = 0;
+    }
+
+    Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+    if (!queryObject)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
+        return false;
+    }
+
+    if (context->getGLState().isQueryActive(queryObject))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_QUERY_RESULT_EXT:
+        case GL_QUERY_RESULT_AVAILABLE_EXT:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
+            return false;
+    }
+
+    if (numParams)
+    {
+        *numParams = 1;
+    }
+
+    return true;
+}
+
+bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+        return false;
+    }
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectivRobustANGLE(Context *context,
+                                         GLuint id,
+                                         GLenum pname,
+                                         GLsizei bufSize,
+                                         GLsizei *length,
+                                         GLint *params)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
+{
+    if (!context->getExtensions().disjointTimerQuery &&
+        !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+        return false;
+    }
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
+                                          GLuint id,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLuint *params)
+{
+    if (!context->getExtensions().disjointTimerQuery &&
+        !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+        return false;
+    }
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
+                                           GLuint id,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           GLsizei *length,
+                                           GLint64 *params)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+        return false;
+    }
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
+                                            GLuint id,
+                                            GLenum pname,
+                                            GLsizei bufSize,
+                                            GLsizei *length,
+                                            GLuint64 *params)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateProgramUniform(gl::Context *context,
+                            GLenum valueType,
+                            GLuint program,
+                            GLint location,
+                            GLsizei count)
+{
+    // Check for ES31 program uniform entry points
+    if (context->getClientVersion() < Version(3, 1))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const LinkedUniform *uniform = nullptr;
+    gl::Program *programObject   = GetValidProgram(context, program);
+    return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+           ValidateUniformValue(context, valueType, uniform->type);
+}
+
+bool ValidateProgramUniform1iv(gl::Context *context,
+                               GLuint program,
+                               GLint location,
+                               GLsizei count,
+                               const GLint *value)
+{
+    // Check for ES31 program uniform entry points
+    if (context->getClientVersion() < Version(3, 1))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const LinkedUniform *uniform = nullptr;
+    gl::Program *programObject   = GetValidProgram(context, program);
+    return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+           ValidateUniform1ivValue(context, uniform->type, count, value);
+}
+
+bool ValidateProgramUniformMatrix(gl::Context *context,
+                                  GLenum valueType,
+                                  GLuint program,
+                                  GLint location,
+                                  GLsizei count,
+                                  GLboolean transpose)
+{
+    // Check for ES31 program uniform entry points
+    if (context->getClientVersion() < Version(3, 1))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const LinkedUniform *uniform = nullptr;
+    gl::Program *programObject   = GetValidProgram(context, program);
+    return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+           ValidateUniformMatrixValue(context, valueType, uniform->type);
+}
+
+bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
+{
+    // Check for ES3 uniform entry points
+    if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const LinkedUniform *uniform = nullptr;
+    gl::Program *programObject   = context->getGLState().getProgram();
+    return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+           ValidateUniformValue(context, valueType, uniform->type);
+}
+
+bool ValidateUniform1iv(ValidationContext *context,
+                        GLint location,
+                        GLsizei count,
+                        const GLint *value)
+{
+    const LinkedUniform *uniform = nullptr;
+    gl::Program *programObject   = context->getGLState().getProgram();
+    return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+           ValidateUniform1ivValue(context, uniform->type, count, value);
+}
+
+bool ValidateUniformMatrix(ValidationContext *context,
+                           GLenum valueType,
+                           GLint location,
+                           GLsizei count,
+                           GLboolean transpose)
+{
+    // Check for ES3 uniform entry points
+    int rows = VariableRowCount(valueType);
+    int cols = VariableColumnCount(valueType);
+    if (rows != cols && context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    const LinkedUniform *uniform = nullptr;
+    gl::Program *programObject   = context->getGLState().getProgram();
+    return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+           ValidateUniformMatrixValue(context, valueType, uniform->type);
+}
+
+bool ValidateStateQuery(ValidationContext *context,
+                        GLenum pname,
+                        GLenum *nativeType,
+                        unsigned int *numParams)
+{
+    if (!context->getQueryParameterInfo(pname, nativeType, numParams))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+
+    if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
+    {
+        unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
+
+        if (colorAttachment >= caps.maxDrawBuffers)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+
+    switch (pname)
+    {
+        case GL_TEXTURE_BINDING_2D:
+        case GL_TEXTURE_BINDING_CUBE_MAP:
+        case GL_TEXTURE_BINDING_3D:
+        case GL_TEXTURE_BINDING_2D_ARRAY:
+            break;
+        case GL_TEXTURE_BINDING_EXTERNAL_OES:
+            if (!context->getExtensions().eglStreamConsumerExternal &&
+                !context->getExtensions().eglImageExternal)
+            {
+                context->handleError(Error(GL_INVALID_ENUM,
+                                           "Neither NV_EGL_stream_consumer_external nor "
+                                           "GL_OES_EGL_image_external extensions enabled"));
+                return false;
+            }
+            break;
+
+        case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+        case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+        {
+            if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
+                GL_FRAMEBUFFER_COMPLETE)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+
+            const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
+            ASSERT(framebuffer);
+
+            if (framebuffer->getReadBufferState() == GL_NONE)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
+                return false;
+            }
+
+            const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
+            if (!attachment)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+        }
+        break;
+
+        default:
+            break;
+    }
+
+    // pname is valid, but there are no parameters to return
+    if (*numParams == 0)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateRobustStateQuery(ValidationContext *context,
+                              GLenum pname,
+                              GLsizei bufSize,
+                              GLenum *nativeType,
+                              unsigned int *numParams)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateStateQuery(context, pname, nativeType, numParams))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *numParams))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateCopyTexImageParametersBase(ValidationContext *context,
+                                        GLenum target,
+                                        GLint level,
+                                        GLenum internalformat,
+                                        bool isSubImage,
+                                        GLint xoffset,
+                                        GLint yoffset,
+                                        GLint zoffset,
+                                        GLint x,
+                                        GLint y,
+                                        GLsizei width,
+                                        GLsizei height,
+                                        GLint border,
+                                        Format *textureFormatOut)
+{
+    if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
+        std::numeric_limits<GLsizei>::max() - yoffset < height)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (border != 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (!ValidMipLevel(context, target, level))
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    const auto &state    = context->getGLState();
+    auto readFramebuffer = state.getReadFramebuffer();
+    if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (readFramebuffer->getReadBufferState() == GL_NONE)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
+        return false;
+    }
+
+    // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
+    // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
+    // attachment and WebGL defines it to be an error. We do the check unconditionally as the
+    // situation is an application error that would lead to a crash in ANGLE.
+    if (readFramebuffer->getReadColorbuffer() == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
+        return false;
+    }
+
+    const gl::Caps &caps = context->getCaps();
+
+    GLuint maxDimension = 0;
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+            maxDimension = caps.max2DTextureSize;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+            maxDimension = caps.maxCubeMapTextureSize;
+            break;
+
+        case GL_TEXTURE_2D_ARRAY:
+            maxDimension = caps.max2DTextureSize;
+            break;
+
+        case GL_TEXTURE_3D:
+            maxDimension = caps.max3DTextureSize;
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    gl::Texture *texture =
+        state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    if (!texture)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (texture->getImmutableFormat() && !isSubImage)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const gl::InternalFormat &formatInfo =
+        gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
+
+    if (formatInfo.depthBits > 0 || formatInfo.compressed)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (isSubImage)
+    {
+        if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+            static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
+            static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+    }
+    else
+    {
+        if (IsCubeMapTextureTarget(target) && width != height)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+
+        if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+        {
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+        }
+
+        int maxLevelDimension = (maxDimension >> level);
+        if (static_cast<int>(width) > maxLevelDimension ||
+            static_cast<int>(height) > maxLevelDimension)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+    }
+
+    if (textureFormatOut)
+    {
+        *textureFormatOut = texture->getFormat(target, level);
+    }
+
+    // Detect texture copying feedback loops for WebGL.
+    if (context->getExtensions().webglCompatibility)
+    {
+        if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
+        {
+            context->handleError(Error(GL_INVALID_OPERATION,
+                                       "Texture copying feedback loop formed between Framebuffer "
+                                       "and specified Texture level."));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
+{
+    switch (mode)
+    {
+        case GL_POINTS:
+        case GL_LINES:
+        case GL_LINE_LOOP:
+        case GL_LINE_STRIP:
+        case GL_TRIANGLES:
+        case GL_TRIANGLE_STRIP:
+        case GL_TRIANGLE_FAN:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    if (count < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    const State &state = context->getGLState();
+
+    // Check for mapped buffers
+    if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
+    // Section 6.10 of the WebGL 1.0 spec.
+    Framebuffer *framebuffer = state.getDrawFramebuffer();
+    if (context->getLimitations().noSeparateStencilRefsAndMasks ||
+        context->getExtensions().webglCompatibility)
+    {
+        const FramebufferAttachment *dsAttachment =
+            framebuffer->getStencilOrDepthStencilAttachment();
+        GLuint stencilBits                = dsAttachment ? dsAttachment->getStencilSize() : 0;
+        GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
+        const DepthStencilState &depthStencilState = state.getDepthStencilState();
+
+        bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
+        bool differentWritemasks =
+            (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
+            (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
+        bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
+                              (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
+
+        if (differentRefs || differentWritemasks || differentMasks)
+        {
+            if (!context->getExtensions().webglCompatibility)
+            {
+                ERR() << "This ANGLE implementation does not support separate front/back stencil "
+                         "writemasks, reference values, or stencil mask values.";
+            }
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+
+    if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    gl::Program *program = state.getProgram();
+    if (!program)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (!program->validateSamplers(nullptr, context->getCaps()))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    // Uniform buffer validation
+    for (unsigned int uniformBlockIndex = 0;
+         uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
+    {
+        const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
+        GLuint blockBinding                  = program->getUniformBlockBinding(uniformBlockIndex);
+        const OffsetBindingPointer<Buffer> &uniformBuffer =
+            state.getIndexedUniformBuffer(blockBinding);
+
+        if (uniformBuffer.get() == nullptr)
+        {
+            // undefined behaviour
+            context->handleError(
+                Error(GL_INVALID_OPERATION,
+                      "It is undefined behaviour to have a used but unbound uniform buffer."));
+            return false;
+        }
+
+        size_t uniformBufferSize = uniformBuffer.getSize();
+        if (uniformBufferSize == 0)
+        {
+            // Bind the whole buffer.
+            uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
+        }
+
+        if (uniformBufferSize < uniformBlock.dataSize)
+        {
+            // undefined behaviour
+            context->handleError(
+                Error(GL_INVALID_OPERATION,
+                      "It is undefined behaviour to use a uniform buffer that is too small."));
+            return false;
+        }
+    }
+
+    // Detect rendering feedback loops for WebGL.
+    if (context->getExtensions().webglCompatibility)
+    {
+        if (framebuffer->formsRenderingFeedbackLoopWith(state))
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION,
+                      "Rendering feedback loop formed between Framebuffer and active Texture."));
+            return false;
+        }
+    }
+
+    // No-op if zero count
+    return (count > 0);
+}
+
+bool ValidateDrawArraysCommon(ValidationContext *context,
+                              GLenum mode,
+                              GLint first,
+                              GLsizei count,
+                              GLsizei primcount)
+{
+    if (first < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    const State &state                          = context->getGLState();
+    gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+    if (curTransformFeedback && curTransformFeedback->isActive() &&
+        !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
+    {
+        // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
+        // that does not match the current transform feedback object's draw mode (if transform
+        // feedback
+        // is active), (3.0.2, section 2.14, pg 86)
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (!ValidateDrawBase(context, mode, count))
+    {
+        return false;
+    }
+
+    // Check the computation of maxVertex doesn't overflow.
+    // - first < 0 or count < 0 have been checked as an error condition
+    // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
+    // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
+    ASSERT(count > 0 && first >= 0);
+    int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
+    if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
+        return false;
+    }
+
+    if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDrawArraysInstanced(Context *context,
+                                 GLenum mode,
+                                 GLint first,
+                                 GLsizei count,
+                                 GLsizei primcount)
+{
+    if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
+    {
+        return false;
+    }
+
+    return !context->getExtensions().webglCompatibility ||
+           ValidateDrawInstancedANGLEAndWebGL(context);
+}
+
+bool ValidateDrawArraysInstancedANGLE(Context *context,
+                                      GLenum mode,
+                                      GLint first,
+                                      GLsizei count,
+                                      GLsizei primcount)
+{
+    if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
+    {
+        return false;
+    }
+
+    return ValidateDrawInstancedANGLEAndWebGL(context);
+}
+
+bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+        case GL_UNSIGNED_SHORT:
+            break;
+        case GL_UNSIGNED_INT:
+            if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    const State &state = context->getGLState();
+
+    gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+    if (curTransformFeedback && curTransformFeedback->isActive() &&
+        !curTransformFeedback->isPaused())
+    {
+        // It is an invalid operation to call DrawElements, DrawRangeElements or
+        // DrawElementsInstanced
+        // while transform feedback is active, (3.0.2, section 2.14, pg 86)
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDrawElementsCommon(ValidationContext *context,
+                                GLenum mode,
+                                GLsizei count,
+                                GLenum type,
+                                const void *indices,
+                                GLsizei primcount)
+{
+    if (!ValidateDrawElementsBase(context, type))
+        return false;
+
+    const State &state = context->getGLState();
+
+    if (!ValidateDrawBase(context, mode, count))
+    {
+        return false;
+    }
+
+    // Check for mapped buffers
+    if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
+        return false;
+    }
+
+    const gl::VertexArray *vao     = state.getVertexArray();
+    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+    GLuint typeBytes = gl::GetTypeInfo(type).bytes;
+
+    if (context->getExtensions().webglCompatibility)
+    {
+        ASSERT(isPow2(typeBytes) && typeBytes > 0);
+        if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
+        {
+            // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
+            // The offset arguments to drawElements and [...], must be a multiple of the size of the
+            // data type passed to the call, or an INVALID_OPERATION error is generated.
+            context->handleError(Error(GL_INVALID_OPERATION,
+                                       "indices must be a multiple of the element type size."));
+            return false;
+        }
+
+        // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
+        // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
+        // error is generated.
+        if (reinterpret_cast<intptr_t>(indices) < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
+            return false;
+        }
+    }
+
+    if (context->getExtensions().webglCompatibility ||
+        !context->getGLState().areClientArraysEnabled())
+    {
+        if (!elementArrayBuffer && count > 0)
+        {
+            // [WebGL 1.0] Section 6.2 No Client Side Arrays
+            // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
+            // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
+            context->handleError(Error(GL_INVALID_OPERATION,
+                                       "There is no element array buffer bound and count > 0."));
+            return false;
+        }
+    }
+
+    if (count > 0)
+    {
+        if (elementArrayBuffer)
+        {
+            // The max possible type size is 8 and count is on 32 bits so doing the multiplication
+            // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
+            static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
+            constexpr uint64_t kMaxTypeSize = 8;
+            constexpr uint64_t kIntMax      = std::numeric_limits<int>::max();
+            constexpr uint64_t kUint64Max   = std::numeric_limits<uint64_t>::max();
+            static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
+
+            uint64_t typeSize     = typeBytes;
+            uint64_t elementCount = static_cast<uint64_t>(count);
+            ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
+
+            // Doing the multiplication here is overflow-safe
+            uint64_t elementDataSizeNoOffset = typeSize * elementCount;
+
+            // The offset can be any value, check for overflows
+            uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
+            if (elementDataSizeNoOffset > kUint64Max - offset)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
+                return false;
+            }
+
+            uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
+            if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
+                return false;
+            }
+        }
+        else if (!indices)
+        {
+            // This is an application error that would normally result in a crash,
+            // but we catch it and return an error
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
+            return false;
+        }
+    }
+
+    // Use the parameter buffer to retrieve and cache the index range.
+    // TODO: offer fast path, with disabled index validation.
+    // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
+    const auto &params        = context->getParams<HasIndexRange>();
+    const auto &indexRangeOpt = params.getIndexRange();
+    if (!indexRangeOpt.valid())
+    {
+        // Unexpected error.
+        return false;
+    }
+
+    // If we use an index greater than our maximum supported index range, return an error.
+    // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
+    // return an error if possible here.
+    if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
+        return false;
+    }
+
+    if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
+                             static_cast<GLint>(indexRangeOpt.value().vertexCount())))
+    {
+        return false;
+    }
+
+    // No op if there are no real indices in the index data (all are primitive restart).
+    return (indexRangeOpt.value().vertexIndexCount > 0);
+}
+
+bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
+                                         GLenum mode,
+                                         GLsizei count,
+                                         GLenum type,
+                                         const void *indices,
+                                         GLsizei primcount)
+{
+    if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
+    {
+        return false;
+    }
+
+    return !context->getExtensions().webglCompatibility ||
+           ValidateDrawInstancedANGLEAndWebGL(context);
+}
+
+bool ValidateDrawElementsInstancedANGLE(Context *context,
+                                        GLenum mode,
+                                        GLsizei count,
+                                        GLenum type,
+                                        const void *indices,
+                                        GLsizei primcount)
+{
+    if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
+    {
+        return false;
+    }
+
+    return ValidateDrawInstancedANGLEAndWebGL(context);
+}
+
+bool ValidateFramebufferTextureBase(Context *context,
+                                    GLenum target,
+                                    GLenum attachment,
+                                    GLuint texture,
+                                    GLint level)
+{
+    if (!ValidFramebufferTarget(target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    if (!ValidateAttachmentTarget(context, attachment))
+    {
+        return false;
+    }
+
+    if (texture != 0)
+    {
+        gl::Texture *tex = context->getTexture(texture);
+
+        if (tex == NULL)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+
+        if (level < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+    }
+
+    const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (framebuffer->id() == 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
+{
+    if (program == 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    gl::Program *programObject = GetValidProgram(context, program);
+    if (!programObject)
+    {
+        return false;
+    }
+
+    if (!programObject || !programObject->isLinked())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (!programObject->isValidUniformLocation(location))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return true;
+}
+
+static bool ValidateSizedGetUniform(Context *context,
+                                    GLuint program,
+                                    GLint location,
+                                    GLsizei bufSize,
+                                    GLsizei *length)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (!ValidateGetUniformBase(context, program, location))
+    {
+        return false;
+    }
+
+    if (bufSize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+        return false;
+    }
+
+    gl::Program *programObject = context->getProgram(program);
+    ASSERT(programObject);
+
+    // sized queries -- ensure the provided buffer is large enough
+    const LinkedUniform &uniform = programObject->getUniformByLocation(location);
+    size_t requiredBytes         = VariableExternalSize(uniform.type);
+    if (static_cast<size_t>(bufSize) < requiredBytes)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
+        return false;
+    }
+
+    if (length)
+    {
+        *length = VariableComponentCount(uniform.type);
+    }
+
+    return true;
+}
+
+bool ValidateGetnUniformfvEXT(Context *context,
+                              GLuint program,
+                              GLint location,
+                              GLsizei bufSize,
+                              GLfloat *params)
+{
+    return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
+}
+
+bool ValidateGetnUniformivEXT(Context *context,
+                              GLuint program,
+                              GLint location,
+                              GLsizei bufSize,
+                              GLint *params)
+{
+    return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
+}
+
+bool ValidateGetUniformfvRobustANGLE(Context *context,
+                                     GLuint program,
+                                     GLint location,
+                                     GLsizei bufSize,
+                                     GLsizei *length,
+                                     GLfloat *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    // bufSize is validated in ValidateSizedGetUniform
+    return ValidateSizedGetUniform(context, program, location, bufSize, length);
+}
+
+bool ValidateGetUniformivRobustANGLE(Context *context,
+                                     GLuint program,
+                                     GLint location,
+                                     GLsizei bufSize,
+                                     GLsizei *length,
+                                     GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    // bufSize is validated in ValidateSizedGetUniform
+    return ValidateSizedGetUniform(context, program, location, bufSize, length);
+}
+
+bool ValidateGetUniformuivRobustANGLE(Context *context,
+                                      GLuint program,
+                                      GLint location,
+                                      GLsizei bufSize,
+                                      GLsizei *length,
+                                      GLuint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
+        return false;
+    }
+
+    // bufSize is validated in ValidateSizedGetUniform
+    return ValidateSizedGetUniform(context, program, location, bufSize, length);
+}
+
+bool ValidateDiscardFramebufferBase(Context *context,
+                                    GLenum target,
+                                    GLsizei numAttachments,
+                                    const GLenum *attachments,
+                                    bool defaultFramebuffer)
+{
+    if (numAttachments < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
+        return false;
+    }
+
+    for (GLsizei i = 0; i < numAttachments; ++i)
+    {
+        if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
+        {
+            if (defaultFramebuffer)
+            {
+                context->handleError(Error(
+                    GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
+                return false;
+            }
+
+            if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION,
+                                           "Requested color attachment is greater than the maximum "
+                                           "supported color attachments"));
+                return false;
+            }
+        }
+        else
+        {
+            switch (attachments[i])
+            {
+                case GL_DEPTH_ATTACHMENT:
+                case GL_STENCIL_ATTACHMENT:
+                case GL_DEPTH_STENCIL_ATTACHMENT:
+                    if (defaultFramebuffer)
+                    {
+                        context->handleError(
+                            Error(GL_INVALID_ENUM,
+                                  "Invalid attachment when the default framebuffer is bound"));
+                        return false;
+                    }
+                    break;
+                case GL_COLOR:
+                case GL_DEPTH:
+                case GL_STENCIL:
+                    if (!defaultFramebuffer)
+                    {
+                        context->handleError(
+                            Error(GL_INVALID_ENUM,
+                                  "Invalid attachment when the default framebuffer is not bound"));
+                        return false;
+                    }
+                    break;
+                default:
+                    context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
+                    return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
+{
+    // Note that debug marker calls must not set error state
+
+    if (length < 0)
+    {
+        return false;
+    }
+
+    if (marker == nullptr)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
+{
+    // Note that debug marker calls must not set error state
+
+    if (length < 0)
+    {
+        return false;
+    }
+
+    if (length > 0 && marker == nullptr)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateEGLImageTargetTexture2DOES(Context *context,
+                                        egl::Display *display,
+                                        GLenum target,
+                                        egl::Image *image)
+{
+    if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+            if (!context->getExtensions().eglImage)
+            {
+                context->handleError(Error(
+                    GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
+            }
+            break;
+
+        case GL_TEXTURE_EXTERNAL_OES:
+            if (!context->getExtensions().eglImageExternal)
+            {
+                context->handleError(Error(
+                    GL_INVALID_ENUM,
+                    "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
+            return false;
+    }
+
+    if (!display->isValidImage(image))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
+        return false;
+    }
+
+    if (image->getSamples() > 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION,
+                                   "cannot create a 2D texture from a multisampled EGL image."));
+        return false;
+    }
+
+    const TextureCaps &textureCaps =
+        context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
+    if (!textureCaps.texturable)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION,
+                                   "EGL image internal format is not supported as a texture."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
+                                                  egl::Display *display,
+                                                  GLenum target,
+                                                  egl::Image *image)
+{
+    if (!context->getExtensions().eglImage)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    switch (target)
+    {
+        case GL_RENDERBUFFER:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
+            return false;
+    }
+
+    if (!display->isValidImage(image))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
+        return false;
+    }
+
+    const TextureCaps &textureCaps =
+        context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
+    if (!textureCaps.renderable)
+    {
+        context->handleError(Error(
+            GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateBindVertexArrayBase(Context *context, GLuint array)
+{
+    if (!context->isVertexArrayGenerated(array))
+    {
+        // The default VAO should always exist
+        ASSERT(array != 0);
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateProgramBinaryBase(Context *context,
+                               GLuint program,
+                               GLenum binaryFormat,
+                               const void *binary,
+                               GLint length)
+{
+    Program *programObject = GetValidProgram(context, program);
+    if (programObject == nullptr)
+    {
+        return false;
+    }
+
+    const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
+    if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
+        programBinaryFormats.end())
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
+        return false;
+    }
+
+    if (context->hasActiveTransformFeedback(program))
+    {
+        // ES 3.0.4 section 2.15 page 91
+        context->handleError(Error(GL_INVALID_OPERATION,
+                                   "Cannot change program binary while program is associated with "
+                                   "an active transform feedback object."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetProgramBinaryBase(Context *context,
+                                  GLuint program,
+                                  GLsizei bufSize,
+                                  GLsizei *length,
+                                  GLenum *binaryFormat,
+                                  void *binary)
+{
+    Program *programObject = GetValidProgram(context, program);
+    if (programObject == nullptr)
+    {
+        return false;
+    }
+
+    if (!programObject->isLinked())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
+        return false;
+    }
+
+    if (context->getCaps().programBinaryFormats.empty())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
+{
+    // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
+    if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
+        return false;
+    }
+
+    ASSERT(context->getGLState().getDrawFramebuffer());
+    GLuint frameBufferId      = context->getGLState().getDrawFramebuffer()->id();
+    GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
+
+    // This should come first before the check for the default frame buffer
+    // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
+    // rather than INVALID_OPERATION
+    for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
+    {
+        const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
+
+        if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
+            (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
+             bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
+        {
+            // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
+            // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
+            // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
+            // 3.1 is still a bit ambiguous about the error, but future specs are
+            // expected to clarify that GL_INVALID_ENUM is the correct error.
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
+            return false;
+        }
+        else if (bufs[colorAttachment] >= maxColorAttachment)
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
+            return false;
+        }
+        else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
+                 frameBufferId != 0)
+        {
+            // INVALID_OPERATION-GL is bound to buffer and ith argument
+            // is not COLOR_ATTACHMENTi or NONE
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
+            return false;
+        }
+    }
+
+    // INVALID_OPERATION is generated if GL is bound to the default framebuffer
+    // and n is not 1 or bufs is bound to value other than BACK and NONE
+    if (frameBufferId == 0)
+    {
+        if (n != 1)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION,
+                                       "n must be 1 when GL is bound to the default framebuffer"));
+            return false;
+        }
+
+        if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
+        {
+            context->handleError(Error(
+                GL_INVALID_OPERATION,
+                "Only NONE or BACK are valid values when drawing to the default framebuffer"));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateGetBufferPointervBase(Context *context,
+                                   GLenum target,
+                                   GLenum pname,
+                                   GLsizei *length,
+                                   void **params)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
+        return false;
+    }
+
+    if (!ValidBufferTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_BUFFER_MAP_POINTER:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
+    // target bound to zero generate an INVALID_OPERATION error."
+    // GLES 3.1 section 6.6 explicitly specifies this error.
+    if (context->getGLState().getTargetBuffer(target) == nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
+        return false;
+    }
+
+    if (length)
+    {
+        *length = 1;
+    }
+
+    return true;
+}
+
+bool ValidateUnmapBufferBase(Context *context, GLenum target)
+{
+    if (!ValidBufferTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+        return false;
+    }
+
+    Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+    if (buffer == nullptr || !buffer->isMapped())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateMapBufferRangeBase(Context *context,
+                                GLenum target,
+                                GLintptr offset,
+                                GLsizeiptr length,
+                                GLbitfield access)
+{
+    if (!ValidBufferTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+        return false;
+    }
+
+    if (offset < 0 || length < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
+        return false;
+    }
+
+    Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+    if (!buffer)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
+        return false;
+    }
+
+    // Check for buffer overflow
+    CheckedNumeric<size_t> checkedOffset(offset);
+    auto checkedSize = checkedOffset + length;
+
+    if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
+        return false;
+    }
+
+    // Check for invalid bits in the mask
+    GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
+                               GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
+                               GL_MAP_UNSYNCHRONIZED_BIT;
+
+    if (access & ~(allAccessBits))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
+        return false;
+    }
+
+    if (length == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
+        return false;
+    }
+
+    if (buffer->isMapped())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
+        return false;
+    }
+
+    // Check for invalid bit combinations
+    if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
+        return false;
+    }
+
+    GLbitfield writeOnlyBits =
+        GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
+
+    if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION,
+                                   "Invalid access bits when mapping buffer for reading: 0x%X.",
+                                   access));
+        return false;
+    }
+
+    if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
+    {
+        context->handleError(Error(
+            GL_INVALID_OPERATION,
+            "The explicit flushing bit may only be set if the buffer is mapped for writing."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateFlushMappedBufferRangeBase(Context *context,
+                                        GLenum target,
+                                        GLintptr offset,
+                                        GLsizeiptr length)
+{
+    if (offset < 0 || length < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
+        return false;
+    }
+
+    if (!ValidBufferTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+        return false;
+    }
+
+    Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+    if (buffer == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
+        return false;
+    }
+
+    if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
+    {
+        context->handleError(Error(
+            GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
+        return false;
+    }
+
+    // Check for buffer overflow
+    CheckedNumeric<size_t> checkedOffset(offset);
+    auto checkedSize = checkedOffset + length;
+
+    if (!checkedSize.IsValid() ||
+        checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGenOrDelete(Context *context, GLint n)
+{
+    if (n < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
+{
+    if (!context->getExtensions().robustClientMemory)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
+        return false;
+    }
+
+    if (bufSize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
+{
+    if (bufSize < numParams)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION,
+                                   "%u parameters are required but %i were provided.", numParams,
+                                   bufSize));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
+                                                     GLenum target,
+                                                     GLenum attachment,
+                                                     GLenum pname,
+                                                     GLsizei *numParams)
+{
+    // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
+    if (numParams)
+    {
+        *numParams = 1;
+    }
+
+    if (!ValidFramebufferTarget(target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    int clientVersion = context->getClientMajorVersion();
+
+    switch (pname)
+    {
+        case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+        case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+            if (clientVersion < 3 && !context->getExtensions().sRGB)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+
+        case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+        case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+        case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+        case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+        case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+        case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+        case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+            if (clientVersion < 3)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    // Determine if the attachment is a valid enum
+    switch (attachment)
+    {
+        case GL_BACK:
+        case GL_FRONT:
+        case GL_DEPTH:
+        case GL_STENCIL:
+        case GL_DEPTH_STENCIL_ATTACHMENT:
+            if (clientVersion < 3)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+
+        case GL_DEPTH_ATTACHMENT:
+        case GL_STENCIL_ATTACHMENT:
+            break;
+
+        default:
+            if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
+                (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+    }
+
+    const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (framebuffer->id() == 0)
+    {
+        if (clientVersion < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+
+        switch (attachment)
+        {
+            case GL_BACK:
+            case GL_DEPTH:
+            case GL_STENCIL:
+                break;
+
+            default:
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+        }
+    }
+    else
+    {
+        if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+        {
+            // Valid attachment query
+        }
+        else
+        {
+            switch (attachment)
+            {
+                case GL_DEPTH_ATTACHMENT:
+                case GL_STENCIL_ATTACHMENT:
+                    break;
+
+                case GL_DEPTH_STENCIL_ATTACHMENT:
+                    if (!framebuffer->hasValidDepthStencil())
+                    {
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                    }
+                    break;
+
+                default:
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+            }
+        }
+    }
+
+    const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
+    if (attachmentObject)
+    {
+        ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
+               attachmentObject->type() == GL_TEXTURE ||
+               attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
+
+        switch (pname)
+        {
+            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+                if (attachmentObject->type() != GL_RENDERBUFFER &&
+                    attachmentObject->type() != GL_TEXTURE)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+
+            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+                if (attachmentObject->type() != GL_TEXTURE)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+
+            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+                if (attachmentObject->type() != GL_TEXTURE)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+
+            case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+                if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+
+            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+                if (attachmentObject->type() != GL_TEXTURE)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+
+            default:
+                break;
+        }
+    }
+    else
+    {
+        // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
+        // is NONE, then querying any other pname will generate INVALID_ENUM.
+
+        // ES 3.0.2 spec pg 235 states that if the attachment type is none,
+        // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
+        // INVALID_OPERATION for all other pnames
+
+        switch (pname)
+        {
+            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+                break;
+
+            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+                if (clientVersion < 3)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+
+            default:
+                if (clientVersion < 3)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+        }
+    }
+
+    return true;
+}
+
+bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
+                                                            GLenum target,
+                                                            GLenum attachment,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *numParams)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
+                                                         numParams))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *numParams))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
+                                             GLenum target,
+                                             GLenum pname,
+                                             GLsizei bufSize,
+                                             GLsizei *length,
+                                             GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetBufferParameteri64v(ValidationContext *context,
+                                    GLenum target,
+                                    GLenum pname,
+                                    GLint64 *params)
+{
+    return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
+}
+
+bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
+                                               GLenum target,
+                                               GLenum pname,
+                                               GLsizei bufSize,
+                                               GLsizei *length,
+                                               GLint64 *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetProgramivBase(ValidationContext *context,
+                              GLuint program,
+                              GLenum pname,
+                              GLsizei *numParams)
+{
+    // Currently, all GetProgramiv queries return 1 parameter
+    if (numParams)
+    {
+        *numParams = 1;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+    if (!programObject)
+    {
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_DELETE_STATUS:
+        case GL_LINK_STATUS:
+        case GL_VALIDATE_STATUS:
+        case GL_INFO_LOG_LENGTH:
+        case GL_ATTACHED_SHADERS:
+        case GL_ACTIVE_ATTRIBUTES:
+        case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+        case GL_ACTIVE_UNIFORMS:
+        case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+            break;
+
+        case GL_PROGRAM_BINARY_LENGTH:
+            if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
+            {
+                context->handleError(Error(GL_INVALID_ENUM,
+                                           "Querying GL_PROGRAM_BINARY_LENGTH requires "
+                                           "GL_OES_get_program_binary or ES 3.0."));
+                return false;
+            }
+            break;
+
+        case GL_ACTIVE_UNIFORM_BLOCKS:
+        case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+        case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+        case GL_TRANSFORM_FEEDBACK_VARYINGS:
+        case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+        case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+            if (context->getClientMajorVersion() < 3)
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
+                return false;
+            }
+            break;
+
+        case GL_PROGRAM_SEPARABLE:
+            if (context->getClientVersion() < Version(3, 1))
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.1."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetProgramivRobustANGLE(Context *context,
+                                     GLuint program,
+                                     GLenum pname,
+                                     GLsizei bufSize,
+                                     GLsizei *numParams)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetProgramivBase(context, program, pname, numParams))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *numParams))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
+                                                   GLenum target,
+                                                   GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetShaderivRobustANGLE(Context *context,
+                                    GLuint shader,
+                                    GLenum pname,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetShaderivBase(context, shader, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetTexParameterfvRobustANGLE(Context *context,
+                                          GLenum target,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLfloat *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetTexParameterBase(context, target, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetTexParameterivRobustANGLE(Context *context,
+                                          GLenum target,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetTexParameterBase(context, target, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateTexParameterfvRobustANGLE(Context *context,
+                                       GLenum target,
+                                       GLenum pname,
+                                       GLsizei bufSize,
+                                       const GLfloat *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    return ValidateTexParameterBase(context, target, pname, bufSize, params);
+}
+
+bool ValidateTexParameterivRobustANGLE(Context *context,
+                                       GLenum target,
+                                       GLenum pname,
+                                       GLsizei bufSize,
+                                       const GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    return ValidateTexParameterBase(context, target, pname, bufSize, params);
+}
+
+bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
+{
+    return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
+}
+
+bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
+                                              GLuint sampler,
+                                              GLenum pname,
+                                              GLuint bufSize,
+                                              GLsizei *length,
+                                              GLfloat *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
+{
+    return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
+}
+
+bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
+                                              GLuint sampler,
+                                              GLenum pname,
+                                              GLuint bufSize,
+                                              GLsizei *length,
+                                              GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
+{
+    return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
+}
+
+bool ValidateSamplerParameterfv(Context *context,
+                                GLuint sampler,
+                                GLenum pname,
+                                const GLfloat *params)
+{
+    return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
+}
+
+bool ValidateSamplerParameterfvRobustANGLE(Context *context,
+                                           GLuint sampler,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           const GLfloat *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
+}
+
+bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
+{
+    return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
+}
+
+bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
+{
+    return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
+}
+
+bool ValidateSamplerParameterivRobustANGLE(Context *context,
+                                           GLuint sampler,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           const GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
+}
+
+bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
+                                          GLuint index,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLfloat *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetVertexAttribivRobustANGLE(Context *context,
+                                          GLuint index,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
+                                                GLuint index,
+                                                GLenum pname,
+                                                GLsizei bufSize,
+                                                GLsizei *length,
+                                                void **pointer)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
+{
+    return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
+}
+
+bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
+                                           GLuint index,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           GLsizei *length,
+                                           GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
+{
+    return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
+}
+
+bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
+                                            GLuint index,
+                                            GLenum pname,
+                                            GLsizei bufSize,
+                                            GLsizei *length,
+                                            GLuint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetActiveUniformBlockiv(Context *context,
+                                     GLuint program,
+                                     GLuint uniformBlockIndex,
+                                     GLenum pname,
+                                     GLint *params)
+{
+    return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
+}
+
+bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
+                                                GLuint program,
+                                                GLuint uniformBlockIndex,
+                                                GLenum pname,
+                                                GLsizei bufSize,
+                                                GLsizei *length,
+                                                GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetInternalFormativ(Context *context,
+                                 GLenum target,
+                                 GLenum internalformat,
+                                 GLenum pname,
+                                 GLsizei bufSize,
+                                 GLint *params)
+{
+    return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
+                                           nullptr);
+}
+
+bool ValidateGetInternalFormativRobustANGLE(Context *context,
+                                            GLenum target,
+                                            GLenum internalformat,
+                                            GLenum pname,
+                                            GLsizei bufSize,
+                                            GLsizei *length,
+                                            GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateVertexFormatBase(ValidationContext *context,
+                              GLuint attribIndex,
+                              GLint size,
+                              GLenum type,
+                              GLboolean pureInteger)
+{
+    const Caps &caps = context->getCaps();
+    if (attribIndex >= caps.maxVertexAttributes)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
+        return false;
+    }
+
+    if (size < 1 || size > 4)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "size must be between one and four."));
+    }
+
+    switch (type)
+    {
+        case GL_BYTE:
+        case GL_UNSIGNED_BYTE:
+        case GL_SHORT:
+        case GL_UNSIGNED_SHORT:
+            break;
+
+        case GL_INT:
+        case GL_UNSIGNED_INT:
+            if (context->getClientMajorVersion() < 3)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
+                return false;
+            }
+            break;
+
+        case GL_FIXED:
+        case GL_FLOAT:
+            if (pureInteger)
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
+                return false;
+            }
+            break;
+
+        case GL_HALF_FLOAT:
+            if (context->getClientMajorVersion() < 3)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
+                return false;
+            }
+            if (pureInteger)
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
+                return false;
+            }
+            break;
+
+        case GL_INT_2_10_10_10_REV:
+        case GL_UNSIGNED_INT_2_10_10_10_REV:
+            if (context->getClientMajorVersion() < 3)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
+                return false;
+            }
+            if (pureInteger)
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
+                return false;
+            }
+            if (size != 4)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION,
+                                           "Type is INT_2_10_10_10_REV or "
+                                           "UNSIGNED_INT_2_10_10_10_REV and size is not 4."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
+            return false;
+    }
+
+    return true;
+}
+
+// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
+// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
+// specified clear value and the type of a buffer that is being cleared generates an
+// INVALID_OPERATION error instead of producing undefined results
+bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
+                                                 GLint drawbuffer,
+                                                 const GLenum *validComponentTypes,
+                                                 size_t validComponentTypeCount)
+{
+    const FramebufferAttachment *attachment =
+        context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
+    if (attachment)
+    {
+        GLenum componentType = attachment->getFormat().info->componentType;
+        const GLenum *end    = validComponentTypes + validComponentTypeCount;
+        if (std::find(validComponentTypes, end, componentType) == end)
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION,
+                      "No defined conversion between clear value and attachment format."));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
+                                          GLsizei imageSize,
+                                          GLsizei dataSize)
+{
+    if (!ValidateRobustEntryPoint(context, dataSize))
+    {
+        return false;
+    }
+
+    gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
+    if (pixelUnpackBuffer == nullptr)
+    {
+        if (dataSize < imageSize)
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "dataSize must be at least %i.", imageSize));
+        }
+    }
+    return true;
+}
+
+bool ValidateGetBufferParameterBase(ValidationContext *context,
+                                    GLenum target,
+                                    GLenum pname,
+                                    bool pointerVersion,
+                                    GLsizei *numParams)
+{
+    if (numParams)
+    {
+        *numParams = 0;
+    }
+
+    if (!ValidBufferTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+        return false;
+    }
+
+    const Buffer *buffer = context->getGLState().getTargetBuffer(target);
+    if (!buffer)
+    {
+        // A null buffer means that "0" is bound to the requested buffer target
+        context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
+        return false;
+    }
+
+    const Extensions &extensions = context->getExtensions();
+
+    switch (pname)
+    {
+        case GL_BUFFER_USAGE:
+        case GL_BUFFER_SIZE:
+            break;
+
+        case GL_BUFFER_ACCESS_OES:
+            if (!extensions.mapBuffer)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
+                return false;
+            }
+            break;
+
+        case GL_BUFFER_MAPPED:
+            static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
+            if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
+                !extensions.mapBufferRange)
+            {
+                context->handleError(Error(
+                    GL_INVALID_ENUM,
+                    "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
+                return false;
+            }
+            break;
+
+        case GL_BUFFER_MAP_POINTER:
+            if (!pointerVersion)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM,
+                          "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
+                return false;
+            }
+            break;
+
+        case GL_BUFFER_ACCESS_FLAGS:
+        case GL_BUFFER_MAP_OFFSET:
+        case GL_BUFFER_MAP_LENGTH:
+            if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
+            {
+                context->handleError(Error(
+                    GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    // All buffer parameter queries return one value.
+    if (numParams)
+    {
+        *numParams = 1;
+    }
+
+    return true;
+}
+
+bool ValidateGetRenderbufferParameterivBase(Context *context,
+                                            GLenum target,
+                                            GLenum pname,
+                                            GLsizei *length)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (target != GL_RENDERBUFFER)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
+        return false;
+    }
+
+    Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
+    if (renderbuffer == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_RENDERBUFFER_WIDTH:
+        case GL_RENDERBUFFER_HEIGHT:
+        case GL_RENDERBUFFER_INTERNAL_FORMAT:
+        case GL_RENDERBUFFER_RED_SIZE:
+        case GL_RENDERBUFFER_GREEN_SIZE:
+        case GL_RENDERBUFFER_BLUE_SIZE:
+        case GL_RENDERBUFFER_ALPHA_SIZE:
+        case GL_RENDERBUFFER_DEPTH_SIZE:
+        case GL_RENDERBUFFER_STENCIL_SIZE:
+            break;
+
+        case GL_RENDERBUFFER_SAMPLES_ANGLE:
+            if (!context->getExtensions().framebufferMultisample)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    if (length)
+    {
+        *length = 1;
+    }
+    return true;
+}
+
+bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (GetValidShader(context, shader) == nullptr)
+    {
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_SHADER_TYPE:
+        case GL_DELETE_STATUS:
+        case GL_COMPILE_STATUS:
+        case GL_INFO_LOG_LENGTH:
+        case GL_SHADER_SOURCE_LENGTH:
+            break;
+
+        case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+            if (!context->getExtensions().translatedShaderSource)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    if (length)
+    {
+        *length = 1;
+    }
+    return true;
+}
+
+bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
+        return false;
+    }
+
+    if (context->getTargetTexture(target) == nullptr)
+    {
+        // Should only be possible for external textures
+        context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_TEXTURE_MAG_FILTER:
+        case GL_TEXTURE_MIN_FILTER:
+        case GL_TEXTURE_WRAP_S:
+        case GL_TEXTURE_WRAP_T:
+            break;
+
+        case GL_TEXTURE_USAGE_ANGLE:
+            if (!context->getExtensions().textureUsage)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+            if (!context->getExtensions().textureFilterAnisotropic)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_IMMUTABLE_FORMAT:
+            if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_WRAP_R:
+        case GL_TEXTURE_IMMUTABLE_LEVELS:
+        case GL_TEXTURE_SWIZZLE_R:
+        case GL_TEXTURE_SWIZZLE_G:
+        case GL_TEXTURE_SWIZZLE_B:
+        case GL_TEXTURE_SWIZZLE_A:
+        case GL_TEXTURE_BASE_LEVEL:
+        case GL_TEXTURE_MAX_LEVEL:
+        case GL_TEXTURE_MIN_LOD:
+        case GL_TEXTURE_MAX_LOD:
+        case GL_TEXTURE_COMPARE_MODE:
+        case GL_TEXTURE_COMPARE_FUNC:
+            if (context->getClientMajorVersion() < 3)
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_SRGB_DECODE_EXT:
+            if (!context->getExtensions().textureSRGBDecode)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    if (length)
+    {
+        *length = 1;
+    }
+    return true;
+}
+
+bool ValidateGetVertexAttribBase(Context *context,
+                                 GLuint index,
+                                 GLenum pname,
+                                 GLsizei *length,
+                                 bool pointer,
+                                 bool pureIntegerEntryPoint)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+        return false;
+    }
+
+    if (index >= context->getCaps().maxVertexAttributes)
+    {
+        context->handleError(Error(
+            GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
+        return false;
+    }
+
+    if (pointer)
+    {
+        if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
+        {
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+        }
+    }
+    else
+    {
+        switch (pname)
+        {
+            case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+            case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+            case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+            case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+            case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+            case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+            case GL_CURRENT_VERTEX_ATTRIB:
+                break;
+
+            case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
+                static_assert(
+                    GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
+                    "ANGLE extension enums not equal to GL enums.");
+                if (context->getClientMajorVersion() < 3 &&
+                    !context->getExtensions().instancedArrays)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM,
+                                               "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
+                                               "3.0 or GL_ANGLE_instanced_arrays."));
+                    return false;
+                }
+                break;
+
+            case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+                if (context->getClientMajorVersion() < 3)
+                {
+                    context->handleError(Error(
+                        GL_INVALID_ENUM, "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0."));
+                    return false;
+                }
+                break;
+
+            case GL_VERTEX_ATTRIB_BINDING:
+            case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
+                if (context->getClientVersion() < ES_3_1)
+                {
+                    context->handleError(
+                        Error(GL_INVALID_ENUM, "Vertex Attrib Bindings require OpenGL ES 3.1."));
+                    return false;
+                }
+                break;
+
+            default:
+                context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+                return false;
+        }
+    }
+
+    if (length)
+    {
+        if (pname == GL_CURRENT_VERTEX_ATTRIB)
+        {
+            *length = 4;
+        }
+        else
+        {
+            *length = 1;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateReadPixelsBase(ValidationContext *context,
+                            GLint x,
+                            GLint y,
+                            GLsizei width,
+                            GLsizei height,
+                            GLenum format,
+                            GLenum type,
+                            GLsizei bufSize,
+                            GLsizei *length,
+                            GLsizei *columns,
+                            GLsizei *rows,
+                            void *pixels)
+{
+    if (length != nullptr)
+    {
+        *length = 0;
+    }
+    if (rows != nullptr)
+    {
+        *rows = 0;
+    }
+    if (columns != nullptr)
+    {
+        *columns = 0;
+    }
+
+    if (width < 0 || height < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
+        return false;
+    }
+
+    auto readFramebuffer = context->getGLState().getReadFramebuffer();
+
+    if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
+    ASSERT(framebuffer);
+
+    if (framebuffer->getReadBufferState() == GL_NONE)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
+        return false;
+    }
+
+    const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
+    // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
+    // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
+    // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
+    // situation is an application error that would lead to a crash in ANGLE.
+    if (readBuffer == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
+        return false;
+    }
+
+    GLenum currentFormat        = framebuffer->getImplementationColorReadFormat();
+    GLenum currentType          = framebuffer->getImplementationColorReadType();
+    GLenum currentComponentType = readBuffer->getFormat().info->componentType;
+
+    bool validFormatTypeCombination =
+        ValidReadPixelsFormatType(context, currentComponentType, format, type);
+
+    if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    // Check for pixel pack buffer related API errors
+    gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
+    if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
+    {
+        // ...the buffer object's data store is currently mapped.
+        context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
+        return false;
+    }
+
+    // ..  the data would be packed to the buffer object such that the memory writes required
+    // would exceed the data store size.
+    const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
+    const gl::Extents size(width, height, 1);
+    const auto &pack = context->getGLState().getPackState();
+
+    auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
+    if (endByteOrErr.isError())
+    {
+        context->handleError(endByteOrErr.getError());
+        return false;
+    }
+
+    size_t endByte = endByteOrErr.getResult();
+    if (bufSize >= 0)
+    {
+        if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
+            return false;
+        }
+    }
+
+    if (pixelPackBuffer != nullptr)
+    {
+        CheckedNumeric<size_t> checkedEndByte(endByte);
+        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
+        checkedEndByte += checkedOffset;
+
+        if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
+        {
+            // Overflow past the end of the buffer
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
+            return false;
+        }
+    }
+
+    if (pixelPackBuffer == nullptr && length != nullptr)
+    {
+        if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
+            return false;
+        }
+
+        *length = static_cast<GLsizei>(endByte);
+    }
+
+    auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
+        angle::CheckedNumeric<int> clippedExtent(length);
+        if (start < 0)
+        {
+            // "subtract" the area that is less than 0
+            clippedExtent += start;
+        }
+
+        const int readExtent = start + length;
+        if (readExtent > bufferSize)
+        {
+            // Subtract the region to the right of the read buffer
+            clippedExtent -= (readExtent - bufferSize);
+        }
+
+        if (!clippedExtent.IsValid())
+        {
+            return 0;
+        }
+
+        return std::max(clippedExtent.ValueOrDie(), 0);
+    };
+
+    if (columns != nullptr)
+    {
+        *columns = getClippedExtent(x, width, readBuffer->getSize().width);
+    }
+
+    if (rows != nullptr)
+    {
+        *rows = getClippedExtent(y, height, readBuffer->getSize().height);
+    }
+
+    return true;
+}
+
+template <typename ParamType>
+bool ValidateTexParameterBase(Context *context,
+                              GLenum target,
+                              GLenum pname,
+                              GLsizei bufSize,
+                              const ParamType *params)
+{
+    if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
+        return false;
+    }
+
+    if (context->getTargetTexture(target) == nullptr)
+    {
+        // Should only be possible for external textures
+        context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
+        return false;
+    }
+
+    const GLsizei minBufSize = 1;
+    if (bufSize >= 0 && bufSize < minBufSize)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_TEXTURE_WRAP_R:
+        case GL_TEXTURE_SWIZZLE_R:
+        case GL_TEXTURE_SWIZZLE_G:
+        case GL_TEXTURE_SWIZZLE_B:
+        case GL_TEXTURE_SWIZZLE_A:
+        case GL_TEXTURE_BASE_LEVEL:
+        case GL_TEXTURE_MAX_LEVEL:
+        case GL_TEXTURE_COMPARE_MODE:
+        case GL_TEXTURE_COMPARE_FUNC:
+        case GL_TEXTURE_MIN_LOD:
+        case GL_TEXTURE_MAX_LOD:
+            if (context->getClientMajorVersion() < 3)
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
+                return false;
+            }
+            if (target == GL_TEXTURE_EXTERNAL_OES &&
+                !context->getExtensions().eglImageExternalEssl3)
+            {
+                context->handleError(Error(GL_INVALID_ENUM,
+                                           "ES3 texture parameters are not available without "
+                                           "GL_OES_EGL_image_external_essl3."));
+                return false;
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    switch (pname)
+    {
+        case GL_TEXTURE_WRAP_S:
+        case GL_TEXTURE_WRAP_T:
+        case GL_TEXTURE_WRAP_R:
+            if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_MIN_FILTER:
+            if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_MAG_FILTER:
+            if (!ValidateTextureMagFilterValue(context, params))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_USAGE_ANGLE:
+            switch (ConvertToGLenum(params[0]))
+            {
+                case GL_NONE:
+                case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
+                    break;
+
+                default:
+                    context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+                    return false;
+            }
+            break;
+
+        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+            if (!context->getExtensions().textureFilterAnisotropic)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
+                return false;
+            }
+
+            // we assume the parameter passed to this validation method is truncated, not rounded
+            if (params[0] < 1)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_MIN_LOD:
+        case GL_TEXTURE_MAX_LOD:
+            // any value is permissible
+            break;
+
+        case GL_TEXTURE_COMPARE_MODE:
+            if (!ValidateTextureCompareModeValue(context, params))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_COMPARE_FUNC:
+            if (!ValidateTextureCompareFuncValue(context, params))
+            {
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_SWIZZLE_R:
+        case GL_TEXTURE_SWIZZLE_G:
+        case GL_TEXTURE_SWIZZLE_B:
+        case GL_TEXTURE_SWIZZLE_A:
+            switch (ConvertToGLenum(params[0]))
+            {
+                case GL_RED:
+                case GL_GREEN:
+                case GL_BLUE:
+                case GL_ALPHA:
+                case GL_ZERO:
+                case GL_ONE:
+                    break;
+
+                default:
+                    context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+                    return false;
+            }
+            break;
+
+        case GL_TEXTURE_BASE_LEVEL:
+            if (params[0] < 0)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
+                return false;
+            }
+            if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_MAX_LEVEL:
+            if (params[0] < 0)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
+                return false;
+            }
+            break;
+
+        case GL_DEPTH_STENCIL_TEXTURE_MODE:
+            if (context->getClientVersion() < Version(3, 1))
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
+                return false;
+            }
+            switch (ConvertToGLenum(params[0]))
+            {
+                case GL_DEPTH_COMPONENT:
+                case GL_STENCIL_INDEX:
+                    break;
+
+                default:
+                    context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+                    return false;
+            }
+            break;
+
+        case GL_TEXTURE_SRGB_DECODE_EXT:
+            if (!ValidateTextureSRGBDecodeValue(context, params))
+            {
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    return true;
+}
+
+template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
+template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/validationES.h b/src/third_party/angle/src/libANGLE/validationES.h
new file mode 100644
index 0000000..6f831af
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationES.h
@@ -0,0 +1,611 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES.h: Validation functions for generic OpenGL ES entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES_H_
+#define LIBANGLE_VALIDATION_ES_H_
+
+#include "common/mathutil.h"
+
+#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl31.h>
+
+namespace egl
+{
+class Display;
+class Image;
+}
+
+namespace gl
+{
+class Context;
+struct Format;
+class Program;
+class Shader;
+class ValidationContext;
+
+bool ValidTextureTarget(const ValidationContext *context, GLenum target);
+bool ValidTexture2DTarget(const ValidationContext *context, GLenum target);
+bool ValidTexture3DTarget(const ValidationContext *context, GLenum target);
+bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target);
+bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target);
+bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target);
+bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target);
+bool ValidFramebufferTarget(GLenum target);
+bool ValidBufferTarget(const ValidationContext *context, GLenum target);
+bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams);
+bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level);
+bool ValidImageSizeParameters(const ValidationContext *context,
+                              GLenum target,
+                              GLint level,
+                              GLsizei width,
+                              GLsizei height,
+                              GLsizei depth,
+                              bool isSubImage);
+bool ValidCompressedImageSize(const ValidationContext *context,
+                              GLenum internalFormat,
+                              GLint level,
+                              GLsizei width,
+                              GLsizei height);
+bool ValidCompressedSubImageSize(const ValidationContext *context,
+                                 GLenum internalFormat,
+                                 GLint xoffset,
+                                 GLint yoffset,
+                                 GLsizei width,
+                                 GLsizei height,
+                                 size_t textureWidth,
+                                 size_t textureHeight);
+bool ValidImageDataSize(ValidationContext *context,
+                        GLenum textureTarget,
+                        GLsizei width,
+                        GLsizei height,
+                        GLsizei depth,
+                        GLenum internalFormat,
+                        GLenum type,
+                        const void *pixels,
+                        GLsizei imageSize);
+
+bool ValidQueryType(const Context *context, GLenum queryType);
+
+bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
+                                      GLenum type,
+                                      GLboolean normalized,
+                                      GLsizei stride,
+                                      const void *ptr,
+                                      bool pureInteger);
+
+// Returns valid program if id is a valid program name
+// Errors INVALID_OPERATION if valid shader is given and returns NULL
+// Errors INVALID_VALUE otherwise and returns NULL
+Program *GetValidProgram(ValidationContext *context, GLuint id);
+
+// Returns valid shader if id is a valid shader name
+// Errors INVALID_OPERATION if valid program is given and returns NULL
+// Errors INVALID_VALUE otherwise and returns NULL
+Shader *GetValidShader(ValidationContext *context, GLuint id);
+
+bool ValidateAttachmentTarget(Context *context, GLenum attachment);
+bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
+                                               GLenum target,
+                                               GLsizei samples,
+                                               GLenum internalformat,
+                                               GLsizei width,
+                                               GLsizei height);
+bool ValidateFramebufferRenderbufferParameters(Context *context,
+                                               GLenum target,
+                                               GLenum attachment,
+                                               GLenum renderbuffertarget,
+                                               GLuint renderbuffer);
+
+bool ValidateBlitFramebufferParameters(ValidationContext *context,
+                                       GLint srcX0,
+                                       GLint srcY0,
+                                       GLint srcX1,
+                                       GLint srcY1,
+                                       GLint dstX0,
+                                       GLint dstY0,
+                                       GLint dstX1,
+                                       GLint dstY1,
+                                       GLbitfield mask,
+                                       GLenum filter);
+
+bool ValidateReadPixelsBase(ValidationContext *context,
+                            GLint x,
+                            GLint y,
+                            GLsizei width,
+                            GLsizei height,
+                            GLenum format,
+                            GLenum type,
+                            GLsizei bufSize,
+                            GLsizei *length,
+                            GLsizei *columns,
+                            GLsizei *rows,
+                            void *pixels);
+bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
+                                   GLint x,
+                                   GLint y,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   GLenum format,
+                                   GLenum type,
+                                   GLsizei bufSize,
+                                   GLsizei *length,
+                                   GLsizei *columns,
+                                   GLsizei *rows,
+                                   void *pixels);
+bool ValidateReadnPixelsEXT(Context *context,
+                            GLint x,
+                            GLint y,
+                            GLsizei width,
+                            GLsizei height,
+                            GLenum format,
+                            GLenum type,
+                            GLsizei bufSize,
+                            void *pixels);
+bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
+                                    GLint x,
+                                    GLint y,
+                                    GLsizei width,
+                                    GLsizei height,
+                                    GLenum format,
+                                    GLenum type,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLsizei *columns,
+                                    GLsizei *rows,
+                                    void *data);
+
+bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n);
+bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n);
+bool ValidateBeginQueryBase(Context *context, GLenum target, GLuint id);
+bool ValidateBeginQueryEXT(Context *context, GLenum target, GLuint id);
+bool ValidateEndQueryBase(Context *context, GLenum target);
+bool ValidateEndQueryEXT(Context *context, GLenum target);
+bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target);
+bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams);
+bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params);
+bool ValidateGetQueryivRobustANGLE(Context *context,
+                                   GLenum target,
+                                   GLenum pname,
+                                   GLsizei bufSize,
+                                   GLsizei *length,
+                                   GLint *params);
+bool ValidateGetQueryObjectValueBase(Context *context,
+                                     GLenum target,
+                                     GLenum pname,
+                                     GLsizei *numParams);
+bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params);
+bool ValidateGetQueryObjectivRobustANGLE(Context *context,
+                                         GLuint id,
+                                         GLenum pname,
+                                         GLsizei bufSize,
+                                         GLsizei *length,
+                                         GLint *params);
+bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params);
+bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
+                                          GLuint id,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLuint *params);
+bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params);
+bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
+                                           GLuint id,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           GLsizei *length,
+                                           GLint64 *params);
+bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params);
+bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
+                                            GLuint id,
+                                            GLenum pname,
+                                            GLsizei bufSize,
+                                            GLsizei *length,
+                                            GLuint64 *params);
+
+bool ValidateProgramUniform(Context *context,
+                            GLenum uniformType,
+                            GLuint program,
+                            GLint location,
+                            GLsizei count);
+bool ValidateProgramUniform1iv(Context *context,
+                               GLuint program,
+                               GLint location,
+                               GLsizei count,
+                               const GLint *value);
+bool ValidateProgramUniformMatrix(Context *context,
+                                  GLenum matrixType,
+                                  GLuint program,
+                                  GLint location,
+                                  GLsizei count,
+                                  GLboolean transpose);
+
+bool ValidateUniform(ValidationContext *context, GLenum uniformType, GLint location, GLsizei count);
+bool ValidateUniformMatrix(ValidationContext *context,
+                           GLenum matrixType,
+                           GLint location,
+                           GLsizei count,
+                           GLboolean transpose);
+
+bool ValidateStateQuery(ValidationContext *context,
+                        GLenum pname,
+                        GLenum *nativeType,
+                        unsigned int *numParams);
+
+bool ValidateRobustStateQuery(ValidationContext *context,
+                              GLenum pname,
+                              GLsizei bufSize,
+                              GLenum *nativeType,
+                              unsigned int *numParams);
+
+bool ValidateCopyTexImageParametersBase(ValidationContext *context,
+                                        GLenum target,
+                                        GLint level,
+                                        GLenum internalformat,
+                                        bool isSubImage,
+                                        GLint xoffset,
+                                        GLint yoffset,
+                                        GLint zoffset,
+                                        GLint x,
+                                        GLint y,
+                                        GLsizei width,
+                                        GLsizei height,
+                                        GLint border,
+                                        Format *textureFormatOut);
+
+bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count);
+bool ValidateDrawArraysCommon(ValidationContext *context,
+                              GLenum mode,
+                              GLint first,
+                              GLsizei count,
+                              GLsizei primcount);
+bool ValidateDrawArraysInstanced(Context *context,
+                                 GLenum mode,
+                                 GLint first,
+                                 GLsizei count,
+                                 GLsizei primcount);
+bool ValidateDrawArraysInstancedANGLE(Context *context,
+                                      GLenum mode,
+                                      GLint first,
+                                      GLsizei count,
+                                      GLsizei primcount);
+
+bool ValidateDrawElementsBase(ValidationContext *context, GLenum type);
+bool ValidateDrawElementsCommon(ValidationContext *context,
+                                GLenum mode,
+                                GLsizei count,
+                                GLenum type,
+                                const void *indices,
+                                GLsizei primcount);
+
+bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
+                                         GLenum mode,
+                                         GLsizei count,
+                                         GLenum type,
+                                         const void *indices,
+                                         GLsizei primcount);
+bool ValidateDrawElementsInstancedANGLE(Context *context,
+                                        GLenum mode,
+                                        GLsizei count,
+                                        GLenum type,
+                                        const void *indices,
+                                        GLsizei primcount);
+
+bool ValidateFramebufferTextureBase(Context *context,
+                                    GLenum target,
+                                    GLenum attachment,
+                                    GLuint texture,
+                                    GLint level);
+
+bool ValidateGetUniformBase(Context *context, GLuint program, GLint location);
+bool ValidateGetnUniformfvEXT(Context *context,
+                              GLuint program,
+                              GLint location,
+                              GLsizei bufSize,
+                              GLfloat *params);
+bool ValidateGetnUniformivEXT(Context *context,
+                              GLuint program,
+                              GLint location,
+                              GLsizei bufSize,
+                              GLint *params);
+bool ValidateGetUniformfvRobustANGLE(Context *context,
+                                     GLuint program,
+                                     GLint location,
+                                     GLsizei bufSize,
+                                     GLsizei *length,
+                                     GLfloat *params);
+bool ValidateGetUniformivRobustANGLE(Context *context,
+                                     GLuint program,
+                                     GLint location,
+                                     GLsizei bufSize,
+                                     GLsizei *length,
+                                     GLint *params);
+bool ValidateGetUniformuivRobustANGLE(Context *context,
+                                      GLuint program,
+                                      GLint location,
+                                      GLsizei bufSize,
+                                      GLsizei *length,
+                                      GLuint *params);
+
+bool ValidateDiscardFramebufferBase(Context *context,
+                                    GLenum target,
+                                    GLsizei numAttachments,
+                                    const GLenum *attachments,
+                                    bool defaultFramebuffer);
+
+bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker);
+bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker);
+
+bool ValidateEGLImageTargetTexture2DOES(Context *context,
+                                        egl::Display *display,
+                                        GLenum target,
+                                        egl::Image *image);
+bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
+                                                  egl::Display *display,
+                                                  GLenum target,
+                                                  egl::Image *image);
+
+bool ValidateBindVertexArrayBase(Context *context, GLuint array);
+
+bool ValidateProgramBinaryBase(Context *context,
+                               GLuint program,
+                               GLenum binaryFormat,
+                               const void *binary,
+                               GLint length);
+bool ValidateGetProgramBinaryBase(Context *context,
+                                  GLuint program,
+                                  GLsizei bufSize,
+                                  GLsizei *length,
+                                  GLenum *binaryFormat,
+                                  void *binary);
+
+bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs);
+
+bool ValidateGetBufferPointervBase(Context *context,
+                                   GLenum target,
+                                   GLenum pname,
+                                   GLsizei *length,
+                                   void **params);
+bool ValidateUnmapBufferBase(Context *context, GLenum target);
+bool ValidateMapBufferRangeBase(Context *context,
+                                GLenum target,
+                                GLintptr offset,
+                                GLsizeiptr length,
+                                GLbitfield access);
+bool ValidateFlushMappedBufferRangeBase(Context *context,
+                                        GLenum target,
+                                        GLintptr offset,
+                                        GLsizeiptr length);
+
+bool ValidateGenOrDelete(Context *context, GLint n);
+
+bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize);
+bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams);
+
+bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
+                                                     GLenum target,
+                                                     GLenum attachment,
+                                                     GLenum pname,
+                                                     GLsizei *numParams);
+bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
+                                                            GLenum target,
+                                                            GLenum attachment,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *numParams);
+
+bool ValidateGetBufferParameterBase(ValidationContext *context,
+                                    GLenum target,
+                                    GLenum pname,
+                                    bool pointerVersion,
+                                    GLsizei *numParams);
+bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
+                                             GLenum target,
+                                             GLenum pname,
+                                             GLsizei bufSize,
+                                             GLsizei *length,
+                                             GLint *params);
+
+bool ValidateGetBufferParameteri64v(ValidationContext *context,
+                                    GLenum target,
+                                    GLenum pname,
+                                    GLint64 *params);
+bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
+                                               GLenum target,
+                                               GLenum pname,
+                                               GLsizei bufSize,
+                                               GLsizei *length,
+                                               GLint64 *params);
+
+bool ValidateGetProgramivBase(ValidationContext *context,
+                              GLuint program,
+                              GLenum pname,
+                              GLsizei *numParams);
+bool ValidateGetProgramivRobustANGLE(Context *context,
+                                     GLuint program,
+                                     GLenum pname,
+                                     GLsizei bufSize,
+                                     GLsizei *numParams);
+
+bool ValidateGetRenderbufferParameterivBase(Context *context,
+                                            GLenum target,
+                                            GLenum pname,
+                                            GLsizei *length);
+bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
+                                                   GLenum target,
+                                                   GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLint *params);
+
+bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length);
+bool ValidateGetShaderivRobustANGLE(Context *context,
+                                    GLuint shader,
+                                    GLenum pname,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLint *params);
+
+bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length);
+bool ValidateGetTexParameterfvRobustANGLE(Context *context,
+                                          GLenum target,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLfloat *params);
+bool ValidateGetTexParameterivRobustANGLE(Context *context,
+                                          GLenum target,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLint *params);
+
+template <typename ParamType>
+bool ValidateTexParameterBase(Context *context,
+                              GLenum target,
+                              GLenum pname,
+                              GLsizei bufSize,
+                              const ParamType *params);
+bool ValidateTexParameterfvRobustANGLE(Context *context,
+                                       GLenum target,
+                                       GLenum pname,
+                                       GLsizei bufSize,
+                                       const GLfloat *params);
+bool ValidateTexParameterivRobustANGLE(Context *context,
+                                       GLenum target,
+                                       GLenum pname,
+                                       GLsizei bufSize,
+                                       const GLint *params);
+
+bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params);
+bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
+                                              GLuint sampler,
+                                              GLenum pname,
+                                              GLuint bufSize,
+                                              GLsizei *length,
+                                              GLfloat *params);
+bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params);
+bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
+                                              GLuint sampler,
+                                              GLenum pname,
+                                              GLuint bufSize,
+                                              GLsizei *length,
+                                              GLint *params);
+
+bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param);
+bool ValidateSamplerParameterfv(Context *context,
+                                GLuint sampler,
+                                GLenum pname,
+                                const GLfloat *params);
+bool ValidateSamplerParameterfvRobustANGLE(Context *context,
+                                           GLuint sampler,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           const GLfloat *params);
+bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param);
+bool ValidateSamplerParameteriv(Context *context,
+                                GLuint sampler,
+                                GLenum pname,
+                                const GLint *params);
+bool ValidateSamplerParameterivRobustANGLE(Context *context,
+                                           GLuint sampler,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           const GLint *params);
+
+bool ValidateGetVertexAttribBase(Context *context,
+                                 GLuint index,
+                                 GLenum pname,
+                                 GLsizei *length,
+                                 bool pointer,
+                                 bool pureIntegerEntryPoint);
+bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
+                                          GLuint index,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLfloat *params);
+
+bool ValidateGetVertexAttribivRobustANGLE(Context *context,
+                                          GLuint index,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLint *params);
+
+bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
+                                                GLuint index,
+                                                GLenum pname,
+                                                GLsizei bufSize,
+                                                GLsizei *length,
+                                                void **pointer);
+
+bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params);
+bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
+                                           GLuint index,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           GLsizei *length,
+                                           GLint *params);
+
+bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params);
+bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
+                                            GLuint index,
+                                            GLenum pname,
+                                            GLsizei bufSize,
+                                            GLsizei *length,
+                                            GLuint *params);
+
+bool ValidateGetActiveUniformBlockiv(Context *context,
+                                     GLuint program,
+                                     GLuint uniformBlockIndex,
+                                     GLenum pname,
+                                     GLint *params);
+bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
+                                                GLuint program,
+                                                GLuint uniformBlockIndex,
+                                                GLenum pname,
+                                                GLsizei bufSize,
+                                                GLsizei *length,
+                                                GLint *params);
+
+bool ValidateGetInternalFormativ(Context *context,
+                                 GLenum target,
+                                 GLenum internalformat,
+                                 GLenum pname,
+                                 GLsizei bufSize,
+                                 GLint *params);
+
+bool ValidateGetInternalFormativRobustANGLE(Context *context,
+                                            GLenum target,
+                                            GLenum internalformat,
+                                            GLenum pname,
+                                            GLsizei bufSize,
+                                            GLsizei *length,
+                                            GLint *params);
+
+bool ValidateVertexFormatBase(ValidationContext *context,
+                              GLuint attribIndex,
+                              GLint size,
+                              GLenum type,
+                              GLboolean pureInteger);
+
+bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
+                                                 GLint drawbuffer,
+                                                 const GLenum *validComponentTypes,
+                                                 size_t validComponentTypeCount);
+
+bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
+                                          GLsizei imageSize,
+                                          GLsizei dataSize);
+
+// Error messages shared here for use in testing.
+extern const char *g_ExceedsMaxElementErrorMessage;
+}  // namespace gl
+
+#endif  // LIBANGLE_VALIDATION_ES_H_
diff --git a/src/third_party/angle/src/libANGLE/validationES2.cpp b/src/third_party/angle/src/libANGLE/validationES2.cpp
new file mode 100644
index 0000000..6ce5dd3
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationES2.cpp
@@ -0,0 +1,5752 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
+
+#include "libANGLE/validationES2.h"
+
+#include <cstdint>
+
+#include "common/mathutil.h"
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES3.h"
+
+namespace gl
+{
+
+namespace
+{
+
+bool IsPartialBlit(gl::Context *context,
+                   const FramebufferAttachment *readBuffer,
+                   const FramebufferAttachment *writeBuffer,
+                   GLint srcX0,
+                   GLint srcY0,
+                   GLint srcX1,
+                   GLint srcY1,
+                   GLint dstX0,
+                   GLint dstY0,
+                   GLint dstX1,
+                   GLint dstY1)
+{
+    const Extents &writeSize = writeBuffer->getSize();
+    const Extents &readSize  = readBuffer->getSize();
+
+    if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
+        dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
+    {
+        return true;
+    }
+
+    if (context->getGLState().isScissorTestEnabled())
+    {
+        const Rectangle &scissor = context->getGLState().getScissor();
+        return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
+               scissor.height < writeSize.height;
+    }
+
+    return false;
+}
+
+template <typename T>
+bool ValidatePathInstances(gl::Context *context,
+                           GLsizei numPaths,
+                           const void *paths,
+                           GLuint pathBase)
+{
+    const auto *array = static_cast<const T *>(paths);
+
+    for (GLsizei i = 0; i < numPaths; ++i)
+    {
+        const GLuint pathName = array[i] + pathBase;
+        if (context->hasPath(pathName) && !context->hasPathData(pathName))
+        {
+            context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ValidateInstancedPathParameters(gl::Context *context,
+                                     GLsizei numPaths,
+                                     GLenum pathNameType,
+                                     const void *paths,
+                                     GLuint pathBase,
+                                     GLenum transformType,
+                                     const GLfloat *transformValues)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+
+    if (paths == nullptr)
+    {
+        context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
+        return false;
+    }
+
+    if (numPaths < 0)
+    {
+        context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
+        return false;
+    }
+
+    if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
+    {
+        context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
+        return false;
+    }
+
+    std::uint32_t pathNameTypeSize = 0;
+    std::uint32_t componentCount   = 0;
+
+    switch (pathNameType)
+    {
+        case GL_UNSIGNED_BYTE:
+            pathNameTypeSize = sizeof(GLubyte);
+            if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
+                return false;
+            break;
+
+        case GL_BYTE:
+            pathNameTypeSize = sizeof(GLbyte);
+            if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
+                return false;
+            break;
+
+        case GL_UNSIGNED_SHORT:
+            pathNameTypeSize = sizeof(GLushort);
+            if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
+                return false;
+            break;
+
+        case GL_SHORT:
+            pathNameTypeSize = sizeof(GLshort);
+            if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
+                return false;
+            break;
+
+        case GL_UNSIGNED_INT:
+            pathNameTypeSize = sizeof(GLuint);
+            if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
+                return false;
+            break;
+
+        case GL_INT:
+            pathNameTypeSize = sizeof(GLint);
+            if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
+                return false;
+            break;
+
+        default:
+            context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
+            return false;
+    }
+
+    switch (transformType)
+    {
+        case GL_NONE:
+            componentCount = 0;
+            break;
+        case GL_TRANSLATE_X_CHROMIUM:
+        case GL_TRANSLATE_Y_CHROMIUM:
+            componentCount = 1;
+            break;
+        case GL_TRANSLATE_2D_CHROMIUM:
+            componentCount = 2;
+            break;
+        case GL_TRANSLATE_3D_CHROMIUM:
+            componentCount = 3;
+            break;
+        case GL_AFFINE_2D_CHROMIUM:
+        case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
+            componentCount = 6;
+            break;
+        case GL_AFFINE_3D_CHROMIUM:
+        case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
+            componentCount = 12;
+            break;
+        default:
+            context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
+            return false;
+    }
+    if (componentCount != 0 && transformValues == nullptr)
+    {
+        context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
+        return false;
+    }
+
+    angle::CheckedNumeric<std::uint32_t> checkedSize(0);
+    checkedSize += (numPaths * pathNameTypeSize);
+    checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
+    if (!checkedSize.IsValid())
+    {
+        context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
+        return false;
+    }
+
+    return true;
+}
+
+bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
+{
+    switch (GetUnsizedFormat(internalFormat))
+    {
+        case GL_ALPHA:
+        case GL_LUMINANCE:
+        case GL_LUMINANCE_ALPHA:
+        case GL_RGB:
+        case GL_RGBA:
+            return true;
+
+        case GL_RED:
+            return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
+
+        case GL_BGRA_EXT:
+            return context->getExtensions().textureFormatBGRA8888;
+
+        default:
+            return false;
+    }
+}
+
+bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
+{
+    switch (internalFormat)
+    {
+        case GL_RGB:
+        case GL_RGBA:
+            break;
+
+        case GL_BGRA_EXT:
+            return context->getExtensions().textureFormatBGRA8888;
+
+        default:
+            return false;
+    }
+
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            break;
+
+        default:
+            return false;
+    }
+
+    return true;
+}
+
+bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
+{
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+            return true;
+
+        // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
+        // supported
+
+        default:
+            return false;
+    }
+}
+
+bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
+{
+    if (IsValidCopyTextureDestinationTarget(context, target))
+    {
+        return true;
+    }
+
+    // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
+    // supported
+
+    return false;
+}
+
+bool IsValidStencilFunc(GLenum func)
+{
+    switch (func)
+    {
+        case GL_NEVER:
+        case GL_ALWAYS:
+        case GL_LESS:
+        case GL_LEQUAL:
+        case GL_EQUAL:
+        case GL_GEQUAL:
+        case GL_GREATER:
+        case GL_NOTEQUAL:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool IsValidStencilFace(GLenum face)
+{
+    switch (face)
+    {
+        case GL_FRONT:
+        case GL_BACK:
+        case GL_FRONT_AND_BACK:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool IsValidStencilOp(GLenum op)
+{
+    switch (op)
+    {
+        case GL_ZERO:
+        case GL_KEEP:
+        case GL_REPLACE:
+        case GL_INCR:
+        case GL_DECR:
+        case GL_INVERT:
+        case GL_INCR_WRAP:
+        case GL_DECR_WRAP:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool ValidateES2CopyTexImageParameters(ValidationContext *context,
+                                       GLenum target,
+                                       GLint level,
+                                       GLenum internalformat,
+                                       bool isSubImage,
+                                       GLint xoffset,
+                                       GLint yoffset,
+                                       GLint x,
+                                       GLint y,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLint border)
+{
+    if (!ValidTexture2DDestinationTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
+        return false;
+    }
+
+    if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
+        return false;
+    }
+
+    Format textureFormat = Format::Invalid();
+    if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+                                            xoffset, yoffset, 0, x, y, width, height, border,
+                                            &textureFormat))
+    {
+        return false;
+    }
+
+    const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
+    GLenum colorbufferFormat =
+        framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
+    const auto &formatInfo = *textureFormat.info;
+
+    // [OpenGL ES 2.0.24] table 3.9
+    if (isSubImage)
+    {
+        switch (formatInfo.format)
+        {
+            case GL_ALPHA:
+                if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
+                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_LUMINANCE:
+                if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+                    colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
+                    colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_RED_EXT:
+                if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+                    colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
+                    colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
+                    colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
+                    colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_RG_EXT:
+                if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
+                    colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
+                    colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
+                    colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
+                    colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_RGB:
+                if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
+                    colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
+                    colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_LUMINANCE_ALPHA:
+            case GL_RGBA:
+                if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
+                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+            case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+            case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+            case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+            case GL_ETC1_RGB8_OES:
+            case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+            case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            case GL_DEPTH_COMPONENT:
+            case GL_DEPTH_STENCIL_OES:
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            default:
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+        }
+
+        if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+    else
+    {
+        switch (internalformat)
+        {
+            case GL_ALPHA:
+                if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
+                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_LUMINANCE:
+                if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+                    colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+                    colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_RED_EXT:
+                if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+                    colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+                    colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_RG_EXT:
+                if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
+                    colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
+                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_RGB:
+                if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+                    colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_LUMINANCE_ALPHA:
+            case GL_RGBA:
+                if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+                    colorbufferFormat != GL_BGR5_A1_ANGLEX)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+            case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                if (context->getExtensions().textureCompressionDXT1)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+                if (context->getExtensions().textureCompressionDXT3)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                if (context->getExtensions().textureCompressionDXT5)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_ETC1_RGB8_OES:
+                if (context->getExtensions().compressedETC1RGB8Texture)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+            case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+                if (context->getExtensions().lossyETCDecode)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION,
+                                               "ETC lossy decode formats can't be copied to."));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(
+                        GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
+                    return false;
+                }
+                break;
+            case GL_DEPTH_COMPONENT:
+            case GL_DEPTH_COMPONENT16:
+            case GL_DEPTH_COMPONENT32_OES:
+            case GL_DEPTH_STENCIL_OES:
+            case GL_DEPTH24_STENCIL8_OES:
+                if (context->getExtensions().depthTextures)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+            default:
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+        }
+    }
+
+    // If width or height is zero, it is a no-op.  Return false without setting an error.
+    return (width > 0 && height > 0);
+}
+
+bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
+{
+    switch (cap)
+    {
+        // EXT_multisample_compatibility
+        case GL_MULTISAMPLE_EXT:
+        case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+            return context->getExtensions().multisampleCompatibility;
+
+        case GL_CULL_FACE:
+        case GL_POLYGON_OFFSET_FILL:
+        case GL_SAMPLE_ALPHA_TO_COVERAGE:
+        case GL_SAMPLE_COVERAGE:
+        case GL_SCISSOR_TEST:
+        case GL_STENCIL_TEST:
+        case GL_DEPTH_TEST:
+        case GL_BLEND:
+        case GL_DITHER:
+            return true;
+
+        case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+        case GL_RASTERIZER_DISCARD:
+            return (context->getClientMajorVersion() >= 3);
+
+        case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+        case GL_DEBUG_OUTPUT:
+            return context->getExtensions().debug;
+
+        case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+            return queryOnly && context->getExtensions().bindGeneratesResource;
+
+        case GL_CLIENT_ARRAYS_ANGLE:
+            return queryOnly && context->getExtensions().clientArrays;
+
+        case GL_FRAMEBUFFER_SRGB_EXT:
+            return context->getExtensions().sRGBWriteControl;
+
+        case GL_SAMPLE_MASK:
+            return context->getClientVersion() >= Version(3, 1);
+
+        case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+            return queryOnly && context->getExtensions().robustResourceInitialization;
+
+        default:
+            return false;
+    }
+}
+
+}  // anonymous namespace
+
+bool ValidateES2TexImageParameters(Context *context,
+                                   GLenum target,
+                                   GLint level,
+                                   GLenum internalformat,
+                                   bool isCompressed,
+                                   bool isSubImage,
+                                   GLint xoffset,
+                                   GLint yoffset,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   GLint border,
+                                   GLenum format,
+                                   GLenum type,
+                                   GLsizei imageSize,
+                                   const void *pixels)
+{
+    if (!ValidTexture2DDestinationTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
+        std::numeric_limits<GLsizei>::max() - yoffset < height)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (!isSubImage && !isCompressed && internalformat != format)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const gl::Caps &caps = context->getCaps();
+
+    if (target == GL_TEXTURE_2D)
+    {
+        if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+            static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+    }
+    else if (IsCubeMapTextureTarget(target))
+    {
+        if (!isSubImage && width != height)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+
+        if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
+            static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+    }
+    else
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    gl::Texture *texture =
+        context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    if (!texture)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (isSubImage)
+    {
+        const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
+        if (textureInternalFormat.internalFormat == GL_NONE)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
+            return false;
+        }
+
+        if (format != GL_NONE)
+        {
+            if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
+                textureInternalFormat.sizedInternalFormat)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+        }
+
+        if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+            static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+    }
+    else
+    {
+        if (texture->getImmutableFormat())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+
+    // Verify zero border
+    if (border != 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (isCompressed)
+    {
+        GLenum actualInternalFormat =
+            isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
+                       : internalformat;
+        switch (actualInternalFormat)
+        {
+            case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+            case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                if (!context->getExtensions().textureCompressionDXT1)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+                if (!context->getExtensions().textureCompressionDXT1)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                if (!context->getExtensions().textureCompressionDXT5)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+            case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+            case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+            case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+                if (!context->getExtensions().textureCompressionS3TCsRGB)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_ETC1_RGB8_OES:
+                if (!context->getExtensions().compressedETC1RGB8Texture)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+            case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+                if (!context->getExtensions().lossyETCDecode)
+                {
+                    context->handleError(Error(
+                        GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
+                    return false;
+                }
+                break;
+            default:
+                context->handleError(
+                    Error(GL_INVALID_ENUM,
+                          "internalformat is not a supported compressed internal format"));
+                return false;
+        }
+
+        if (isSubImage)
+        {
+            if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
+                                             height, texture->getWidth(target, level),
+                                             texture->getHeight(target, level)))
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
+                return false;
+            }
+
+            if (format != actualInternalFormat)
+            {
+                context->handleError(Error(
+                    GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
+                return false;
+            }
+        }
+        else
+        {
+            if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
+                return false;
+            }
+        }
+    }
+    else
+    {
+        // validate <type> by itself (used as secondary key below)
+        switch (type)
+        {
+            case GL_UNSIGNED_BYTE:
+            case GL_UNSIGNED_SHORT_5_6_5:
+            case GL_UNSIGNED_SHORT_4_4_4_4:
+            case GL_UNSIGNED_SHORT_5_5_5_1:
+            case GL_UNSIGNED_SHORT:
+            case GL_UNSIGNED_INT:
+            case GL_UNSIGNED_INT_24_8_OES:
+            case GL_HALF_FLOAT_OES:
+            case GL_FLOAT:
+                break;
+            default:
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+        }
+
+        // validate <format> + <type> combinations
+        // - invalid <format> -> sets INVALID_ENUM
+        // - invalid <format>+<type> combination -> sets INVALID_OPERATION
+        switch (format)
+        {
+            case GL_ALPHA:
+            case GL_LUMINANCE:
+            case GL_LUMINANCE_ALPHA:
+                switch (type)
+                {
+                    case GL_UNSIGNED_BYTE:
+                    case GL_FLOAT:
+                    case GL_HALF_FLOAT_OES:
+                        break;
+                    default:
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                }
+                break;
+            case GL_RED:
+            case GL_RG:
+                if (!context->getExtensions().textureRG)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                switch (type)
+                {
+                    case GL_UNSIGNED_BYTE:
+                    case GL_FLOAT:
+                    case GL_HALF_FLOAT_OES:
+                        break;
+                    default:
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                }
+                break;
+            case GL_RGB:
+                switch (type)
+                {
+                    case GL_UNSIGNED_BYTE:
+                    case GL_UNSIGNED_SHORT_5_6_5:
+                    case GL_FLOAT:
+                    case GL_HALF_FLOAT_OES:
+                        break;
+                    default:
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                }
+                break;
+            case GL_RGBA:
+                switch (type)
+                {
+                    case GL_UNSIGNED_BYTE:
+                    case GL_UNSIGNED_SHORT_4_4_4_4:
+                    case GL_UNSIGNED_SHORT_5_5_5_1:
+                    case GL_FLOAT:
+                    case GL_HALF_FLOAT_OES:
+                        break;
+                    default:
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                }
+                break;
+            case GL_BGRA_EXT:
+                switch (type)
+                {
+                    case GL_UNSIGNED_BYTE:
+                        break;
+                    default:
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                }
+                break;
+            case GL_SRGB_EXT:
+            case GL_SRGB_ALPHA_EXT:
+                if (!context->getExtensions().sRGB)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                switch (type)
+                {
+                    case GL_UNSIGNED_BYTE:
+                        break;
+                    default:
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                }
+                break;
+            case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:  // error cases for compressed textures are
+                                                   // handled below
+            case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+            case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+            case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                break;
+            case GL_DEPTH_COMPONENT:
+                switch (type)
+                {
+                    case GL_UNSIGNED_SHORT:
+                    case GL_UNSIGNED_INT:
+                        break;
+                    default:
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                }
+                break;
+            case GL_DEPTH_STENCIL_OES:
+                switch (type)
+                {
+                    case GL_UNSIGNED_INT_24_8_OES:
+                        break;
+                    default:
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                }
+                break;
+            default:
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+        }
+
+        switch (format)
+        {
+            case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+            case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                if (context->getExtensions().textureCompressionDXT1)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+                if (context->getExtensions().textureCompressionDXT3)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                if (context->getExtensions().textureCompressionDXT5)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_ETC1_RGB8_OES:
+                if (context->getExtensions().compressedETC1RGB8Texture)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+            case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+            case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+            case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+                if (context->getExtensions().lossyETCDecode)
+                {
+                    context->handleError(
+                        Error(GL_INVALID_OPERATION,
+                              "ETC lossy decode formats can't work with this type."));
+                    return false;
+                }
+                else
+                {
+                    context->handleError(Error(
+                        GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
+                    return false;
+                }
+                break;
+            case GL_DEPTH_COMPONENT:
+            case GL_DEPTH_STENCIL_OES:
+                if (!context->getExtensions().depthTextures)
+                {
+                    context->handleError(Error(GL_INVALID_VALUE));
+                    return false;
+                }
+                if (target != GL_TEXTURE_2D)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                // OES_depth_texture supports loading depth data and multiple levels,
+                // but ANGLE_depth_texture does not
+                if (pixels != nullptr || level != 0)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+                break;
+            default:
+                break;
+        }
+
+        if (type == GL_FLOAT)
+        {
+            if (!context->getExtensions().textureFloat)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+        }
+        else if (type == GL_HALF_FLOAT_OES)
+        {
+            if (!context->getExtensions().textureHalfFloat)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+        }
+    }
+
+    if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
+                            imageSize))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateES2TexStorageParameters(Context *context,
+                                     GLenum target,
+                                     GLsizei levels,
+                                     GLenum internalformat,
+                                     GLsizei width,
+                                     GLsizei height)
+{
+    if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    if (width < 1 || height < 1 || levels < 1)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (target == GL_TEXTURE_CUBE_MAP && width != height)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
+    if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    const gl::Caps &caps = context->getCaps();
+
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+            if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+                static_cast<GLuint>(height) > caps.max2DTextureSize)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+        case GL_TEXTURE_CUBE_MAP:
+            if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
+                static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    if (levels != 1 && !context->getExtensions().textureNPOT)
+    {
+        if (!gl::isPow2(width) || !gl::isPow2(height))
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+
+    switch (internalformat)
+    {
+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+            if (!context->getExtensions().textureCompressionDXT1)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+            if (!context->getExtensions().textureCompressionDXT3)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+            if (!context->getExtensions().textureCompressionDXT5)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        case GL_ETC1_RGB8_OES:
+            if (!context->getExtensions().compressedETC1RGB8Texture)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+        case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+        case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+            if (!context->getExtensions().lossyETCDecode)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
+                return false;
+            }
+            break;
+        case GL_RGBA32F_EXT:
+        case GL_RGB32F_EXT:
+        case GL_ALPHA32F_EXT:
+        case GL_LUMINANCE32F_EXT:
+        case GL_LUMINANCE_ALPHA32F_EXT:
+            if (!context->getExtensions().textureFloat)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        case GL_RGBA16F_EXT:
+        case GL_RGB16F_EXT:
+        case GL_ALPHA16F_EXT:
+        case GL_LUMINANCE16F_EXT:
+        case GL_LUMINANCE_ALPHA16F_EXT:
+            if (!context->getExtensions().textureHalfFloat)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        case GL_R8_EXT:
+        case GL_RG8_EXT:
+            if (!context->getExtensions().textureRG)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        case GL_R16F_EXT:
+        case GL_RG16F_EXT:
+            if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        case GL_R32F_EXT:
+        case GL_RG32F_EXT:
+            if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+        case GL_DEPTH_COMPONENT16:
+        case GL_DEPTH_COMPONENT32_OES:
+        case GL_DEPTH24_STENCIL8_OES:
+            if (!context->getExtensions().depthTextures)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            if (target != GL_TEXTURE_2D)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+            // ANGLE_depth_texture only supports 1-level textures
+            if (levels != 1)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+            break;
+        default:
+            break;
+    }
+
+    gl::Texture *texture = context->getTargetTexture(target);
+    if (!texture || texture->id() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (texture->getImmutableFormat())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDiscardFramebufferEXT(Context *context,
+                                   GLenum target,
+                                   GLsizei numAttachments,
+                                   const GLenum *attachments)
+{
+    if (!context->getExtensions().discardFramebuffer)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    bool defaultFramebuffer = false;
+
+    switch (target)
+    {
+        case GL_FRAMEBUFFER:
+            defaultFramebuffer =
+                (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
+            return false;
+    }
+
+    return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
+                                          defaultFramebuffer);
+}
+
+bool ValidateBindVertexArrayOES(Context *context, GLuint array)
+{
+    if (!context->getExtensions().vertexArrayObject)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    return ValidateBindVertexArrayBase(context, array);
+}
+
+bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
+{
+    if (!context->getExtensions().vertexArrayObject)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
+{
+    if (!context->getExtensions().vertexArrayObject)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateIsVertexArrayOES(Context *context)
+{
+    if (!context->getExtensions().vertexArrayObject)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateProgramBinaryOES(Context *context,
+                              GLuint program,
+                              GLenum binaryFormat,
+                              const void *binary,
+                              GLint length)
+{
+    if (!context->getExtensions().getProgramBinary)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
+}
+
+bool ValidateGetProgramBinaryOES(Context *context,
+                                 GLuint program,
+                                 GLsizei bufSize,
+                                 GLsizei *length,
+                                 GLenum *binaryFormat,
+                                 void *binary)
+{
+    if (!context->getExtensions().getProgramBinary)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
+}
+
+static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
+{
+    switch (source)
+    {
+        case GL_DEBUG_SOURCE_API:
+        case GL_DEBUG_SOURCE_SHADER_COMPILER:
+        case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+        case GL_DEBUG_SOURCE_OTHER:
+            // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
+            return !mustBeThirdPartyOrApplication;
+
+        case GL_DEBUG_SOURCE_THIRD_PARTY:
+        case GL_DEBUG_SOURCE_APPLICATION:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+static bool ValidDebugType(GLenum type)
+{
+    switch (type)
+    {
+        case GL_DEBUG_TYPE_ERROR:
+        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+        case GL_DEBUG_TYPE_PERFORMANCE:
+        case GL_DEBUG_TYPE_PORTABILITY:
+        case GL_DEBUG_TYPE_OTHER:
+        case GL_DEBUG_TYPE_MARKER:
+        case GL_DEBUG_TYPE_PUSH_GROUP:
+        case GL_DEBUG_TYPE_POP_GROUP:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+static bool ValidDebugSeverity(GLenum severity)
+{
+    switch (severity)
+    {
+        case GL_DEBUG_SEVERITY_HIGH:
+        case GL_DEBUG_SEVERITY_MEDIUM:
+        case GL_DEBUG_SEVERITY_LOW:
+        case GL_DEBUG_SEVERITY_NOTIFICATION:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool ValidateDebugMessageControlKHR(Context *context,
+                                    GLenum source,
+                                    GLenum type,
+                                    GLenum severity,
+                                    GLsizei count,
+                                    const GLuint *ids,
+                                    GLboolean enabled)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+        return false;
+    }
+
+    if (!ValidDebugType(type) && type != GL_DONT_CARE)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
+        return false;
+    }
+
+    if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
+        return false;
+    }
+
+    if (count > 0)
+    {
+        if (source == GL_DONT_CARE || type == GL_DONT_CARE)
+        {
+            context->handleError(Error(
+                GL_INVALID_OPERATION,
+                "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
+            return false;
+        }
+
+        if (severity != GL_DONT_CARE)
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION,
+                      "If count is greater than zero, severity must be GL_DONT_CARE."));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateDebugMessageInsertKHR(Context *context,
+                                   GLenum source,
+                                   GLenum type,
+                                   GLuint id,
+                                   GLenum severity,
+                                   GLsizei length,
+                                   const GLchar *buf)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    if (!context->getGLState().getDebug().isOutputEnabled())
+    {
+        // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
+        // not generate an error.
+        return false;
+    }
+
+    if (!ValidDebugSeverity(severity))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
+        return false;
+    }
+
+    if (!ValidDebugType(type))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
+        return false;
+    }
+
+    if (!ValidDebugSource(source, true))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+        return false;
+    }
+
+    size_t messageLength = (length < 0) ? strlen(buf) : length;
+    if (messageLength > context->getExtensions().maxDebugMessageLength)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDebugMessageCallbackKHR(Context *context,
+                                     GLDEBUGPROCKHR callback,
+                                     const void *userParam)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetDebugMessageLogKHR(Context *context,
+                                   GLuint count,
+                                   GLsizei bufSize,
+                                   GLenum *sources,
+                                   GLenum *types,
+                                   GLuint *ids,
+                                   GLenum *severities,
+                                   GLsizei *lengths,
+                                   GLchar *messageLog)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    if (bufSize < 0 && messageLog != nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidatePushDebugGroupKHR(Context *context,
+                               GLenum source,
+                               GLuint id,
+                               GLsizei length,
+                               const GLchar *message)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    if (!ValidDebugSource(source, true))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+        return false;
+    }
+
+    size_t messageLength = (length < 0) ? strlen(message) : length;
+    if (messageLength > context->getExtensions().maxDebugMessageLength)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
+        return false;
+    }
+
+    size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
+    if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
+    {
+        context->handleError(
+            Error(GL_STACK_OVERFLOW,
+                  "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidatePopDebugGroupKHR(Context *context)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
+    if (currentStackSize <= 1)
+    {
+        context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
+        return false;
+    }
+
+    return true;
+}
+
+static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
+{
+    switch (identifier)
+    {
+        case GL_BUFFER:
+            if (context->getBuffer(name) == nullptr)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
+                return false;
+            }
+            return true;
+
+        case GL_SHADER:
+            if (context->getShader(name) == nullptr)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
+                return false;
+            }
+            return true;
+
+        case GL_PROGRAM:
+            if (context->getProgram(name) == nullptr)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
+                return false;
+            }
+            return true;
+
+        case GL_VERTEX_ARRAY:
+            if (context->getVertexArray(name) == nullptr)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
+                return false;
+            }
+            return true;
+
+        case GL_QUERY:
+            if (context->getQuery(name) == nullptr)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
+                return false;
+            }
+            return true;
+
+        case GL_TRANSFORM_FEEDBACK:
+            if (context->getTransformFeedback(name) == nullptr)
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
+                return false;
+            }
+            return true;
+
+        case GL_SAMPLER:
+            if (context->getSampler(name) == nullptr)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
+                return false;
+            }
+            return true;
+
+        case GL_TEXTURE:
+            if (context->getTexture(name) == nullptr)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
+                return false;
+            }
+            return true;
+
+        case GL_RENDERBUFFER:
+            if (context->getRenderbuffer(name) == nullptr)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
+                return false;
+            }
+            return true;
+
+        case GL_FRAMEBUFFER:
+            if (context->getFramebuffer(name) == nullptr)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
+                return false;
+            }
+            return true;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
+            return false;
+    }
+}
+
+static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
+{
+    size_t labelLength = 0;
+
+    if (length < 0)
+    {
+        if (label != nullptr)
+        {
+            labelLength = strlen(label);
+        }
+    }
+    else
+    {
+        labelLength = static_cast<size_t>(length);
+    }
+
+    if (labelLength > context->getExtensions().maxLabelLength)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateObjectLabelKHR(Context *context,
+                            GLenum identifier,
+                            GLuint name,
+                            GLsizei length,
+                            const GLchar *label)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateObjectIdentifierAndName(context, identifier, name))
+    {
+        return false;
+    }
+
+    if (!ValidateLabelLength(context, length, label))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetObjectLabelKHR(Context *context,
+                               GLenum identifier,
+                               GLuint name,
+                               GLsizei bufSize,
+                               GLsizei *length,
+                               GLchar *label)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    if (bufSize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+        return false;
+    }
+
+    if (!ValidateObjectIdentifierAndName(context, identifier, name))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+static bool ValidateObjectPtrName(Context *context, const void *ptr)
+{
+    if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateObjectPtrLabelKHR(Context *context,
+                               const void *ptr,
+                               GLsizei length,
+                               const GLchar *label)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateObjectPtrName(context, ptr))
+    {
+        return false;
+    }
+
+    if (!ValidateLabelLength(context, length, label))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetObjectPtrLabelKHR(Context *context,
+                                  const void *ptr,
+                                  GLsizei bufSize,
+                                  GLsizei *length,
+                                  GLchar *label)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    if (bufSize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+        return false;
+    }
+
+    if (!ValidateObjectPtrName(context, ptr))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
+{
+    if (!context->getExtensions().debug)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+        return false;
+    }
+
+    // TODO: represent this in Context::getQueryParameterInfo.
+    switch (pname)
+    {
+        case GL_DEBUG_CALLBACK_FUNCTION:
+        case GL_DEBUG_CALLBACK_USER_PARAM:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateBlitFramebufferANGLE(Context *context,
+                                  GLint srcX0,
+                                  GLint srcY0,
+                                  GLint srcX1,
+                                  GLint srcY1,
+                                  GLint dstX0,
+                                  GLint dstY0,
+                                  GLint dstX1,
+                                  GLint dstY1,
+                                  GLbitfield mask,
+                                  GLenum filter)
+{
+    if (!context->getExtensions().framebufferBlit)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
+        return false;
+    }
+
+    if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
+    {
+        // TODO(jmadill): Determine if this should be available on other implementations.
+        context->handleError(Error(
+            GL_INVALID_OPERATION,
+            "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
+        return false;
+    }
+
+    if (filter == GL_LINEAR)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
+        return false;
+    }
+
+    Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
+    Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
+
+    if (mask & GL_COLOR_BUFFER_BIT)
+    {
+        const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
+        const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
+
+        if (readColorAttachment && drawColorAttachment)
+        {
+            if (!(readColorAttachment->type() == GL_TEXTURE &&
+                  readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
+                readColorAttachment->type() != GL_RENDERBUFFER &&
+                readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+
+            for (size_t drawbufferIdx = 0;
+                 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
+            {
+                const FramebufferAttachment *attachment =
+                    drawFramebuffer->getDrawBuffer(drawbufferIdx);
+                if (attachment)
+                {
+                    if (!(attachment->type() == GL_TEXTURE &&
+                          attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
+                        attachment->type() != GL_RENDERBUFFER &&
+                        attachment->type() != GL_FRAMEBUFFER_DEFAULT)
+                    {
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                    }
+
+                    // Return an error if the destination formats do not match
+                    if (!Format::SameSized(attachment->getFormat(),
+                                           readColorAttachment->getFormat()))
+                    {
+                        context->handleError(Error(GL_INVALID_OPERATION));
+                        return false;
+                    }
+                }
+            }
+
+            if (readFramebuffer->getSamples(context) != 0 &&
+                IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
+                              srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+        }
+    }
+
+    GLenum masks[]       = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
+    GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
+    for (size_t i = 0; i < 2; i++)
+    {
+        if (mask & masks[i])
+        {
+            const FramebufferAttachment *readBuffer =
+                readFramebuffer->getAttachment(attachments[i]);
+            const FramebufferAttachment *drawBuffer =
+                drawFramebuffer->getAttachment(attachments[i]);
+
+            if (readBuffer && drawBuffer)
+            {
+                if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
+                                  dstX0, dstY0, dstX1, dstY1))
+                {
+                    // only whole-buffer copies are permitted
+                    context->handleError(Error(GL_INVALID_OPERATION,
+                                               "Only whole-buffer depth and stencil blits are "
+                                               "supported by this extension."));
+                    return false;
+                }
+
+                if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return false;
+                }
+            }
+        }
+    }
+
+    return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
+                                             dstX1, dstY1, mask, filter);
+}
+
+bool ValidateClear(ValidationContext *context, GLbitfield mask)
+{
+    auto fbo = context->getGLState().getDrawFramebuffer();
+    if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
+    {
+        constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
+                                                  GL_SIGNED_NORMALIZED};
+
+        for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
+             drawBufferIdx++)
+        {
+            if (!ValidateWebGLFramebufferAttachmentClearType(
+                    context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
+{
+    if (!context->getExtensions().drawBuffers)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
+        return false;
+    }
+
+    return ValidateDrawBuffersBase(context, n, bufs);
+}
+
+bool ValidateTexImage2D(Context *context,
+                        GLenum target,
+                        GLint level,
+                        GLint internalformat,
+                        GLsizei width,
+                        GLsizei height,
+                        GLint border,
+                        GLenum format,
+                        GLenum type,
+                        const void *pixels)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
+                                             0, 0, width, height, border, format, type, -1, pixels);
+    }
+
+    ASSERT(context->getClientMajorVersion() >= 3);
+    return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
+                                           0, 0, width, height, 1, border, format, type, -1,
+                                           pixels);
+}
+
+bool ValidateTexImage2DRobust(Context *context,
+                              GLenum target,
+                              GLint level,
+                              GLint internalformat,
+                              GLsizei width,
+                              GLsizei height,
+                              GLint border,
+                              GLenum format,
+                              GLenum type,
+                              GLsizei bufSize,
+                              const void *pixels)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (context->getClientMajorVersion() < 3)
+    {
+        return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
+                                             0, 0, width, height, border, format, type, bufSize,
+                                             pixels);
+    }
+
+    ASSERT(context->getClientMajorVersion() >= 3);
+    return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
+                                           0, 0, width, height, 1, border, format, type, bufSize,
+                                           pixels);
+}
+
+bool ValidateTexSubImage2D(Context *context,
+                           GLenum target,
+                           GLint level,
+                           GLint xoffset,
+                           GLint yoffset,
+                           GLsizei width,
+                           GLsizei height,
+                           GLenum format,
+                           GLenum type,
+                           const void *pixels)
+{
+
+    if (context->getClientMajorVersion() < 3)
+    {
+        return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
+                                             yoffset, width, height, 0, format, type, -1, pixels);
+    }
+
+    ASSERT(context->getClientMajorVersion() >= 3);
+    return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
+                                           yoffset, 0, width, height, 1, 0, format, type, -1,
+                                           pixels);
+}
+
+bool ValidateTexSubImage2DRobustANGLE(Context *context,
+                                      GLenum target,
+                                      GLint level,
+                                      GLint xoffset,
+                                      GLint yoffset,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLenum format,
+                                      GLenum type,
+                                      GLsizei bufSize,
+                                      const void *pixels)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (context->getClientMajorVersion() < 3)
+    {
+        return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
+                                             yoffset, width, height, 0, format, type, bufSize,
+                                             pixels);
+    }
+
+    ASSERT(context->getClientMajorVersion() >= 3);
+    return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
+                                           yoffset, 0, width, height, 1, 0, format, type, bufSize,
+                                           pixels);
+}
+
+bool ValidateCompressedTexImage2D(Context *context,
+                                  GLenum target,
+                                  GLint level,
+                                  GLenum internalformat,
+                                  GLsizei width,
+                                  GLsizei height,
+                                  GLint border,
+                                  GLsizei imageSize,
+                                  const void *data)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
+                                           0, width, height, border, GL_NONE, GL_NONE, -1, data))
+        {
+            return false;
+        }
+    }
+    else
+    {
+        ASSERT(context->getClientMajorVersion() >= 3);
+        if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
+                                             0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
+                                             data))
+        {
+            return false;
+        }
+    }
+
+    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
+    auto blockSizeOrErr =
+        formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
+    if (blockSizeOrErr.isError())
+    {
+        context->handleError(blockSizeOrErr.getError());
+        return false;
+    }
+
+    if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
+                                             GLenum target,
+                                             GLint level,
+                                             GLenum internalformat,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLint border,
+                                             GLsizei imageSize,
+                                             GLsizei dataSize,
+                                             const void *data)
+{
+    if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
+    {
+        return false;
+    }
+
+    return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
+                                        border, imageSize, data);
+}
+bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
+                                                GLenum target,
+                                                GLint level,
+                                                GLint xoffset,
+                                                GLint yoffset,
+                                                GLsizei width,
+                                                GLsizei height,
+                                                GLenum format,
+                                                GLsizei imageSize,
+                                                GLsizei dataSize,
+                                                const void *data)
+{
+    if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
+    {
+        return false;
+    }
+
+    return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
+                                           format, imageSize, data);
+}
+
+bool ValidateCompressedTexSubImage2D(Context *context,
+                                     GLenum target,
+                                     GLint level,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLenum format,
+                                     GLsizei imageSize,
+                                     const void *data)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
+                                           yoffset, width, height, 0, format, GL_NONE, -1, data))
+        {
+            return false;
+        }
+    }
+    else
+    {
+        ASSERT(context->getClientMajorVersion() >= 3);
+        if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
+                                             yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
+                                             data))
+        {
+            return false;
+        }
+    }
+
+    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
+    auto blockSizeOrErr =
+        formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
+    if (blockSizeOrErr.isError())
+    {
+        context->handleError(blockSizeOrErr.getError());
+        return false;
+    }
+
+    if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
+{
+    return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
+}
+
+bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
+{
+    if (!context->getExtensions().mapBuffer)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
+        return false;
+    }
+
+    if (!ValidBufferTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+        return false;
+    }
+
+    Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+    if (buffer == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
+        return false;
+    }
+
+    if (access != GL_WRITE_ONLY_OES)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
+        return false;
+    }
+
+    if (buffer->isMapped())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateUnmapBufferOES(Context *context, GLenum target)
+{
+    if (!context->getExtensions().mapBuffer)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
+        return false;
+    }
+
+    return ValidateUnmapBufferBase(context, target);
+}
+
+bool ValidateMapBufferRangeEXT(Context *context,
+                               GLenum target,
+                               GLintptr offset,
+                               GLsizeiptr length,
+                               GLbitfield access)
+{
+    if (!context->getExtensions().mapBufferRange)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
+        return false;
+    }
+
+    return ValidateMapBufferRangeBase(context, target, offset, length, access);
+}
+
+bool ValidateFlushMappedBufferRangeEXT(Context *context,
+                                       GLenum target,
+                                       GLintptr offset,
+                                       GLsizeiptr length)
+{
+    if (!context->getExtensions().mapBufferRange)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
+        return false;
+    }
+
+    return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
+}
+
+bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
+{
+    Texture *textureObject = context->getTexture(texture);
+    if (textureObject && textureObject->getTarget() != target && texture != 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
+        return false;
+    }
+
+    if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+        !context->isTextureGenerated(texture))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
+        return false;
+    }
+
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+        case GL_TEXTURE_CUBE_MAP:
+            break;
+
+        case GL_TEXTURE_3D:
+        case GL_TEXTURE_2D_ARRAY:
+            if (context->getClientMajorVersion() < 3)
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_2D_MULTISAMPLE:
+            if (context->getClientVersion() < Version(3, 1))
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_EXTERNAL_OES:
+            if (!context->getExtensions().eglImageExternal &&
+                !context->getExtensions().eglStreamConsumerExternal)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "External texture extension not enabled"));
+                return false;
+            }
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateBindUniformLocationCHROMIUM(Context *context,
+                                         GLuint program,
+                                         GLint location,
+                                         const GLchar *name)
+{
+    if (!context->getExtensions().bindUniformLocation)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+    if (!programObject)
+    {
+        return false;
+    }
+
+    if (location < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (static_cast<size_t>(location) >=
+        (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
+    {
+        context->handleError(Error(GL_INVALID_VALUE,
+                                   "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
+                                   "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
+        return false;
+    }
+
+    if (strncmp(name, "gl_", 3) == 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
+{
+    if (!context->getExtensions().framebufferMixedSamples)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
+        return false;
+    }
+    switch (components)
+    {
+        case GL_RGB:
+        case GL_RGBA:
+        case GL_ALPHA:
+        case GL_NONE:
+            break;
+        default:
+            context->handleError(
+                Error(GL_INVALID_ENUM,
+                      "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
+            return false;
+    }
+
+    return true;
+}
+
+// CHROMIUM_path_rendering
+
+bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+    if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
+        return false;
+    }
+    if (matrix == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateMatrixMode(Context *context, GLenum matrixMode)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+    if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateGenPaths(Context *context, GLsizei range)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+
+    // range = 0 is undefined in NV_path_rendering.
+    // we add stricter semantic check here and require a non zero positive range.
+    if (range <= 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
+        return false;
+    }
+
+    if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+
+    // range = 0 is undefined in NV_path_rendering.
+    // we add stricter semantic check here and require a non zero positive range.
+    if (range <= 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
+        return false;
+    }
+
+    angle::CheckedNumeric<std::uint32_t> checkedRange(path);
+    checkedRange += range;
+
+    if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidatePathCommands(Context *context,
+                          GLuint path,
+                          GLsizei numCommands,
+                          const GLubyte *commands,
+                          GLsizei numCoords,
+                          GLenum coordType,
+                          const void *coords)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+    if (!context->hasPath(path))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+        return false;
+    }
+
+    if (numCommands < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
+        return false;
+    }
+    else if (numCommands > 0)
+    {
+        if (!commands)
+        {
+            context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
+            return false;
+        }
+    }
+
+    if (numCoords < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
+        return false;
+    }
+    else if (numCoords > 0)
+    {
+        if (!coords)
+        {
+            context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
+            return false;
+        }
+    }
+
+    std::uint32_t coordTypeSize = 0;
+    switch (coordType)
+    {
+        case GL_BYTE:
+            coordTypeSize = sizeof(GLbyte);
+            break;
+
+        case GL_UNSIGNED_BYTE:
+            coordTypeSize = sizeof(GLubyte);
+            break;
+
+        case GL_SHORT:
+            coordTypeSize = sizeof(GLshort);
+            break;
+
+        case GL_UNSIGNED_SHORT:
+            coordTypeSize = sizeof(GLushort);
+            break;
+
+        case GL_FLOAT:
+            coordTypeSize = sizeof(GLfloat);
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
+            return false;
+    }
+
+    angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
+    checkedSize += (coordTypeSize * numCoords);
+    if (!checkedSize.IsValid())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
+        return false;
+    }
+
+    // early return skips command data validation when it doesn't exist.
+    if (!commands)
+        return true;
+
+    GLsizei expectedNumCoords = 0;
+    for (GLsizei i = 0; i < numCommands; ++i)
+    {
+        switch (commands[i])
+        {
+            case GL_CLOSE_PATH_CHROMIUM:  // no coordinates.
+                break;
+            case GL_MOVE_TO_CHROMIUM:
+            case GL_LINE_TO_CHROMIUM:
+                expectedNumCoords += 2;
+                break;
+            case GL_QUADRATIC_CURVE_TO_CHROMIUM:
+                expectedNumCoords += 4;
+                break;
+            case GL_CUBIC_CURVE_TO_CHROMIUM:
+                expectedNumCoords += 6;
+                break;
+            case GL_CONIC_CURVE_TO_CHROMIUM:
+                expectedNumCoords += 5;
+                break;
+            default:
+                context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
+                return false;
+        }
+    }
+    if (expectedNumCoords != numCoords)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+    if (!context->hasPath(path))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_PATH_STROKE_WIDTH_CHROMIUM:
+            if (value < 0.0f)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
+                return false;
+            }
+            break;
+        case GL_PATH_END_CAPS_CHROMIUM:
+            switch (static_cast<GLenum>(value))
+            {
+                case GL_FLAT_CHROMIUM:
+                case GL_SQUARE_CHROMIUM:
+                case GL_ROUND_CHROMIUM:
+                    break;
+                default:
+                    context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
+                    return false;
+            }
+            break;
+        case GL_PATH_JOIN_STYLE_CHROMIUM:
+            switch (static_cast<GLenum>(value))
+            {
+                case GL_MITER_REVERT_CHROMIUM:
+                case GL_BEVEL_CHROMIUM:
+                case GL_ROUND_CHROMIUM:
+                    break;
+                default:
+                    context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
+                    return false;
+            }
+        case GL_PATH_MITER_LIMIT_CHROMIUM:
+            if (value < 0.0f)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
+                return false;
+            }
+            break;
+
+        case GL_PATH_STROKE_BOUND_CHROMIUM:
+            // no errors, only clamping.
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
+            return false;
+    }
+    return true;
+}
+
+bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+
+    if (!context->hasPath(path))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+        return false;
+    }
+    if (!value)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "No value array."));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_PATH_STROKE_WIDTH_CHROMIUM:
+        case GL_PATH_END_CAPS_CHROMIUM:
+        case GL_PATH_JOIN_STYLE_CHROMIUM:
+        case GL_PATH_MITER_LIMIT_CHROMIUM:
+        case GL_PATH_STROKE_BOUND_CHROMIUM:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+
+    switch (func)
+    {
+        case GL_NEVER:
+        case GL_ALWAYS:
+        case GL_LESS:
+        case GL_LEQUAL:
+        case GL_EQUAL:
+        case GL_GEQUAL:
+        case GL_GREATER:
+        case GL_NOTEQUAL:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
+            return false;
+    }
+
+    return true;
+}
+
+// Note that the spec specifies that for the path drawing commands
+// if the path object is not an existing path object the command
+// does nothing and no error is generated.
+// However if the path object exists but has not been specified any
+// commands then an error is generated.
+
+bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+    if (context->hasPath(path) && !context->hasPathData(path))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+        return false;
+    }
+
+    switch (fillMode)
+    {
+        case GL_COUNT_UP_CHROMIUM:
+        case GL_COUNT_DOWN_CHROMIUM:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
+            return false;
+    }
+
+    if (!isPow2(mask + 1))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+    if (context->hasPath(path) && !context->hasPathData(path))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+    if (context->hasPath(path) && !context->hasPathData(path))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+        return false;
+    }
+
+    switch (coverMode)
+    {
+        case GL_CONVEX_HULL_CHROMIUM:
+        case GL_BOUNDING_BOX_CHROMIUM:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+            return false;
+    }
+    return true;
+}
+
+bool ValidateStencilThenCoverFillPath(Context *context,
+                                      GLuint path,
+                                      GLenum fillMode,
+                                      GLuint mask,
+                                      GLenum coverMode)
+{
+    return ValidateStencilFillPath(context, path, fillMode, mask) &&
+           ValidateCoverPath(context, path, coverMode);
+}
+
+bool ValidateStencilThenCoverStrokePath(Context *context,
+                                        GLuint path,
+                                        GLint reference,
+                                        GLuint mask,
+                                        GLenum coverMode)
+{
+    return ValidateStencilStrokePath(context, path, reference, mask) &&
+           ValidateCoverPath(context, path, coverMode);
+}
+
+bool ValidateIsPath(Context *context)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateCoverFillPathInstanced(Context *context,
+                                    GLsizei numPaths,
+                                    GLenum pathNameType,
+                                    const void *paths,
+                                    GLuint pathBase,
+                                    GLenum coverMode,
+                                    GLenum transformType,
+                                    const GLfloat *transformValues)
+{
+    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+                                         transformType, transformValues))
+        return false;
+
+    switch (coverMode)
+    {
+        case GL_CONVEX_HULL_CHROMIUM:
+        case GL_BOUNDING_BOX_CHROMIUM:
+        case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateCoverStrokePathInstanced(Context *context,
+                                      GLsizei numPaths,
+                                      GLenum pathNameType,
+                                      const void *paths,
+                                      GLuint pathBase,
+                                      GLenum coverMode,
+                                      GLenum transformType,
+                                      const GLfloat *transformValues)
+{
+    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+                                         transformType, transformValues))
+        return false;
+
+    switch (coverMode)
+    {
+        case GL_CONVEX_HULL_CHROMIUM:
+        case GL_BOUNDING_BOX_CHROMIUM:
+        case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateStencilFillPathInstanced(Context *context,
+                                      GLsizei numPaths,
+                                      GLenum pathNameType,
+                                      const void *paths,
+                                      GLuint pathBase,
+                                      GLenum fillMode,
+                                      GLuint mask,
+                                      GLenum transformType,
+                                      const GLfloat *transformValues)
+{
+
+    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+                                         transformType, transformValues))
+        return false;
+
+    switch (fillMode)
+    {
+        case GL_COUNT_UP_CHROMIUM:
+        case GL_COUNT_DOWN_CHROMIUM:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
+            return false;
+    }
+    if (!isPow2(mask + 1))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateStencilStrokePathInstanced(Context *context,
+                                        GLsizei numPaths,
+                                        GLenum pathNameType,
+                                        const void *paths,
+                                        GLuint pathBase,
+                                        GLint reference,
+                                        GLuint mask,
+                                        GLenum transformType,
+                                        const GLfloat *transformValues)
+{
+    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+                                         transformType, transformValues))
+        return false;
+
+    // no more validation here.
+
+    return true;
+}
+
+bool ValidateStencilThenCoverFillPathInstanced(Context *context,
+                                               GLsizei numPaths,
+                                               GLenum pathNameType,
+                                               const void *paths,
+                                               GLuint pathBase,
+                                               GLenum fillMode,
+                                               GLuint mask,
+                                               GLenum coverMode,
+                                               GLenum transformType,
+                                               const GLfloat *transformValues)
+{
+    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+                                         transformType, transformValues))
+        return false;
+
+    switch (coverMode)
+    {
+        case GL_CONVEX_HULL_CHROMIUM:
+        case GL_BOUNDING_BOX_CHROMIUM:
+        case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+            return false;
+    }
+
+    switch (fillMode)
+    {
+        case GL_COUNT_UP_CHROMIUM:
+        case GL_COUNT_DOWN_CHROMIUM:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
+            return false;
+    }
+    if (!isPow2(mask + 1))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
+                                                 GLsizei numPaths,
+                                                 GLenum pathNameType,
+                                                 const void *paths,
+                                                 GLuint pathBase,
+                                                 GLint reference,
+                                                 GLuint mask,
+                                                 GLenum coverMode,
+                                                 GLenum transformType,
+                                                 const GLfloat *transformValues)
+{
+    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+                                         transformType, transformValues))
+        return false;
+
+    switch (coverMode)
+    {
+        case GL_CONVEX_HULL_CHROMIUM:
+        case GL_BOUNDING_BOX_CHROMIUM:
+        case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateBindFragmentInputLocation(Context *context,
+                                       GLuint program,
+                                       GLint location,
+                                       const GLchar *name)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+
+    const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
+    if (location >= MaxLocation)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
+        return false;
+    }
+
+    const auto *programObject = context->getProgram(program);
+    if (!programObject)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
+        return false;
+    }
+
+    if (!name)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "No name given."));
+        return false;
+    }
+
+    if (angle::BeginsWith(name, "gl_"))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateProgramPathFragmentInputGen(Context *context,
+                                         GLuint program,
+                                         GLint location,
+                                         GLenum genMode,
+                                         GLint components,
+                                         const GLfloat *coeffs)
+{
+    if (!context->getExtensions().pathRendering)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+        return false;
+    }
+
+    const auto *programObject = context->getProgram(program);
+    if (!programObject || programObject->isFlaggedForDeletion())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
+        return false;
+    }
+
+    if (!programObject->isLinked())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
+        return false;
+    }
+
+    switch (genMode)
+    {
+        case GL_NONE:
+            if (components != 0)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
+                return false;
+            }
+            break;
+
+        case GL_OBJECT_LINEAR_CHROMIUM:
+        case GL_EYE_LINEAR_CHROMIUM:
+        case GL_CONSTANT_CHROMIUM:
+            if (components < 1 || components > 4)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
+                return false;
+            }
+            if (!coeffs)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
+            return false;
+    }
+
+    // If the location is -1 then the command is silently ignored
+    // and no further validation is needed.
+    if (location == -1)
+        return true;
+
+    const auto &binding = programObject->getFragmentInputBindingInfo(location);
+
+    if (!binding.valid)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
+        return false;
+    }
+
+    if (binding.type != GL_NONE)
+    {
+        GLint expectedComponents = 0;
+        switch (binding.type)
+        {
+            case GL_FLOAT:
+                expectedComponents = 1;
+                break;
+            case GL_FLOAT_VEC2:
+                expectedComponents = 2;
+                break;
+            case GL_FLOAT_VEC3:
+                expectedComponents = 3;
+                break;
+            case GL_FLOAT_VEC4:
+                expectedComponents = 4;
+                break;
+            default:
+                context->handleError(
+                    Error(GL_INVALID_OPERATION,
+                          "Fragment input type is not a floating point scalar or vector."));
+                return false;
+        }
+        if (expectedComponents != components && genMode != GL_NONE)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ValidateCopyTextureCHROMIUM(Context *context,
+                                 GLuint sourceId,
+                                 GLint sourceLevel,
+                                 GLenum destTarget,
+                                 GLuint destId,
+                                 GLint destLevel,
+                                 GLint internalFormat,
+                                 GLenum destType,
+                                 GLboolean unpackFlipY,
+                                 GLboolean unpackPremultiplyAlpha,
+                                 GLboolean unpackUnmultiplyAlpha)
+{
+    if (!context->getExtensions().copyTexture)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
+        return false;
+    }
+
+    const gl::Texture *source = context->getTexture(sourceId);
+    if (source == nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
+        return false;
+    }
+
+    if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
+        return false;
+    }
+
+    GLenum sourceTarget = source->getTarget();
+    ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
+    if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
+        return false;
+    }
+
+    const gl::InternalFormat &sourceFormat = *source->getFormat(sourceTarget, 0).info;
+    if (!IsValidCopyTextureFormat(context, sourceFormat.format))
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
+        return false;
+    }
+
+    const gl::Texture *dest = context->getTexture(destId);
+    if (dest == nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
+        return false;
+    }
+
+    if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
+        return false;
+    }
+
+    if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "Destination internal format and type combination is not valid."));
+        return false;
+    }
+
+    if (dest->getImmutableFormat())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateCopySubTextureCHROMIUM(Context *context,
+                                    GLuint sourceId,
+                                    GLint sourceLevel,
+                                    GLenum destTarget,
+                                    GLuint destId,
+                                    GLint destLevel,
+                                    GLint xoffset,
+                                    GLint yoffset,
+                                    GLint x,
+                                    GLint y,
+                                    GLsizei width,
+                                    GLsizei height,
+                                    GLboolean unpackFlipY,
+                                    GLboolean unpackPremultiplyAlpha,
+                                    GLboolean unpackUnmultiplyAlpha)
+{
+    if (!context->getExtensions().copyTexture)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
+        return false;
+    }
+
+    const gl::Texture *source = context->getTexture(sourceId);
+    if (source == nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
+        return false;
+    }
+
+    if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
+        return false;
+    }
+
+    GLenum sourceTarget = source->getTarget();
+    ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
+    if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
+        return false;
+    }
+
+    if (x < 0 || y < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
+        return false;
+    }
+
+    if (width < 0 || height < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
+        return false;
+    }
+
+    if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
+        static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
+        return false;
+    }
+
+    const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
+    if (!IsValidCopyTextureFormat(context, sourceFormat.info->internalFormat))
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
+        return false;
+    }
+
+    const gl::Texture *dest = context->getTexture(destId);
+    if (dest == nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
+        return false;
+    }
+
+    if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
+        return false;
+    }
+
+    ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
+    if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
+        return false;
+    }
+
+    const gl::InternalFormat &destFormat = *dest->getFormat(destTarget, 0).info;
+    if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "Destination internal format and type combination is not valid."));
+        return false;
+    }
+
+    if (xoffset < 0 || yoffset < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
+        return false;
+    }
+
+    if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
+        static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
+{
+    if (!context->getExtensions().copyCompressedTexture)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION,
+                                   "GL_CHROMIUM_copy_compressed_texture extension not available."));
+        return false;
+    }
+
+    const gl::Texture *source = context->getTexture(sourceId);
+    if (source == nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
+        return false;
+    }
+
+    if (source->getTarget() != GL_TEXTURE_2D)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
+        return false;
+    }
+
+    if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
+        return false;
+    }
+
+    const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
+    if (!sourceFormat.info->compressed)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
+        return false;
+    }
+
+    const gl::Texture *dest = context->getTexture(destId);
+    if (dest == nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
+        return false;
+    }
+
+    if (dest->getTarget() != GL_TEXTURE_2D)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
+        return false;
+    }
+
+    if (dest->getImmutableFormat())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateCreateShader(Context *context, GLenum type)
+{
+    switch (type)
+    {
+        case GL_VERTEX_SHADER:
+        case GL_FRAGMENT_SHADER:
+            break;
+
+        case GL_COMPUTE_SHADER:
+            if (context->getClientVersion() < Version(3, 1))
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateBufferData(ValidationContext *context,
+                        GLenum target,
+                        GLsizeiptr size,
+                        const void *data,
+                        GLenum usage)
+{
+    if (size < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    switch (usage)
+    {
+        case GL_STREAM_DRAW:
+        case GL_STATIC_DRAW:
+        case GL_DYNAMIC_DRAW:
+            break;
+
+        case GL_STREAM_READ:
+        case GL_STREAM_COPY:
+        case GL_STATIC_READ:
+        case GL_STATIC_COPY:
+        case GL_DYNAMIC_READ:
+        case GL_DYNAMIC_COPY:
+            if (context->getClientMajorVersion() < 3)
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    if (!ValidBufferTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+    if (!buffer)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateBufferSubData(ValidationContext *context,
+                           GLenum target,
+                           GLintptr offset,
+                           GLsizeiptr size,
+                           const void *data)
+{
+    if (size < 0 || offset < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (!ValidBufferTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+    if (!buffer)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (buffer->isMapped())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    // Check for possible overflow of size + offset
+    angle::CheckedNumeric<size_t> checkedSize(size);
+    checkedSize += offset;
+    if (!checkedSize.IsValid())
+    {
+        context->handleError(Error(GL_OUT_OF_MEMORY));
+        return false;
+    }
+
+    if (size + offset > buffer->getSize())
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
+{
+    if (!context->getExtensions().requestExtension)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
+        return false;
+    }
+
+    const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+    auto extension                         = extensionInfos.find(name);
+    if (extension == extensionInfos.end() || !extension->second.Requestable)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
+{
+    if (texture < GL_TEXTURE0 ||
+        texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
+{
+    Program *programObject = GetValidProgram(context, program);
+    if (!programObject)
+    {
+        return false;
+    }
+
+    Shader *shaderObject = GetValidShader(context, shader);
+    if (!shaderObject)
+    {
+        return false;
+    }
+
+    switch (shaderObject->getType())
+    {
+        case GL_VERTEX_SHADER:
+        {
+            if (programObject->getAttachedVertexShader())
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+            break;
+        }
+        case GL_FRAGMENT_SHADER:
+        {
+            if (programObject->getAttachedFragmentShader())
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+            break;
+        }
+        case GL_COMPUTE_SHADER:
+        {
+            if (programObject->getAttachedComputeShader())
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+            break;
+        }
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    return true;
+}
+
+bool ValidateBindAttribLocation(ValidationContext *context,
+                                GLuint program,
+                                GLuint index,
+                                const GLchar *name)
+{
+    if (index >= MAX_VERTEX_ATTRIBS)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
+        return false;
+    }
+
+    if (strncmp(name, "gl_", 3) == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
+        return false;
+    }
+
+    return GetValidProgram(context, program) != nullptr;
+}
+
+bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
+{
+    if (!ValidBufferTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
+        return false;
+    }
+
+    if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+        !context->isBufferGenerated(buffer))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
+{
+    if (!ValidFramebufferTarget(target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
+        return false;
+    }
+
+    if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+        !context->isFramebufferGenerated(framebuffer))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
+{
+    if (target != GL_RENDERBUFFER)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
+        return false;
+    }
+
+    if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+        !context->isRenderbufferGenerated(renderbuffer))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
+        return false;
+    }
+
+    return true;
+}
+
+static bool ValidBlendEquationMode(GLenum mode)
+{
+    switch (mode)
+    {
+        case GL_FUNC_ADD:
+        case GL_FUNC_SUBTRACT:
+        case GL_FUNC_REVERSE_SUBTRACT:
+        case GL_MIN:
+        case GL_MAX:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool ValidateBlendColor(ValidationContext *context,
+                        GLfloat red,
+                        GLfloat green,
+                        GLfloat blue,
+                        GLfloat alpha)
+{
+    return true;
+}
+
+bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
+{
+    if (!ValidBlendEquationMode(mode))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
+{
+    if (!ValidBlendEquationMode(modeRGB))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
+        return false;
+    }
+
+    if (!ValidBlendEquationMode(modeAlpha))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
+{
+    return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
+}
+
+static bool ValidSrcBlendFunc(GLenum srcBlend)
+{
+    switch (srcBlend)
+    {
+        case GL_ZERO:
+        case GL_ONE:
+        case GL_SRC_COLOR:
+        case GL_ONE_MINUS_SRC_COLOR:
+        case GL_DST_COLOR:
+        case GL_ONE_MINUS_DST_COLOR:
+        case GL_SRC_ALPHA:
+        case GL_ONE_MINUS_SRC_ALPHA:
+        case GL_DST_ALPHA:
+        case GL_ONE_MINUS_DST_ALPHA:
+        case GL_CONSTANT_COLOR:
+        case GL_ONE_MINUS_CONSTANT_COLOR:
+        case GL_CONSTANT_ALPHA:
+        case GL_ONE_MINUS_CONSTANT_ALPHA:
+        case GL_SRC_ALPHA_SATURATE:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
+{
+    switch (dstBlend)
+    {
+        case GL_ZERO:
+        case GL_ONE:
+        case GL_SRC_COLOR:
+        case GL_ONE_MINUS_SRC_COLOR:
+        case GL_DST_COLOR:
+        case GL_ONE_MINUS_DST_COLOR:
+        case GL_SRC_ALPHA:
+        case GL_ONE_MINUS_SRC_ALPHA:
+        case GL_DST_ALPHA:
+        case GL_ONE_MINUS_DST_ALPHA:
+        case GL_CONSTANT_COLOR:
+        case GL_ONE_MINUS_CONSTANT_COLOR:
+        case GL_CONSTANT_ALPHA:
+        case GL_ONE_MINUS_CONSTANT_ALPHA:
+            return true;
+
+        case GL_SRC_ALPHA_SATURATE:
+            return (contextMajorVersion >= 3);
+
+        default:
+            return false;
+    }
+}
+
+bool ValidateBlendFuncSeparate(ValidationContext *context,
+                               GLenum srcRGB,
+                               GLenum dstRGB,
+                               GLenum srcAlpha,
+                               GLenum dstAlpha)
+{
+    if (!ValidSrcBlendFunc(srcRGB))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
+        return false;
+    }
+
+    if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
+        return false;
+    }
+
+    if (!ValidSrcBlendFunc(srcAlpha))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
+        return false;
+    }
+
+    if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
+        return false;
+    }
+
+    if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
+        context->getExtensions().webglCompatibility)
+    {
+        bool constantColorUsed =
+            (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
+             dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
+
+        bool constantAlphaUsed =
+            (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
+             dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
+
+        if (constantColorUsed && constantAlphaUsed)
+        {
+            const char *msg;
+            if (context->getExtensions().webglCompatibility)
+            {
+                msg =
+                    "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
+                    "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
+            }
+            else
+            {
+                msg =
+                    "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
+                    "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
+                    "implementation.";
+                ERR() << msg;
+            }
+            context->handleError(Error(GL_INVALID_OPERATION, msg));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateGetString(Context *context, GLenum name)
+{
+    switch (name)
+    {
+        case GL_VENDOR:
+        case GL_RENDERER:
+        case GL_VERSION:
+        case GL_SHADING_LANGUAGE_VERSION:
+        case GL_EXTENSIONS:
+            break;
+
+        case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+            if (!context->getExtensions().requestExtension)
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateLineWidth(ValidationContext *context, GLfloat width)
+{
+    if (width <= 0.0f || isNaN(width))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateVertexAttribPointer(ValidationContext *context,
+                                 GLuint index,
+                                 GLint size,
+                                 GLenum type,
+                                 GLboolean normalized,
+                                 GLsizei stride,
+                                 const void *ptr)
+{
+    if (!ValidateVertexFormatBase(context, index, size, type, false))
+    {
+        return false;
+    }
+
+    if (stride < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (context->getClientVersion() >= ES_3_1)
+    {
+        if (stride > caps.maxVertexAttribStride)
+        {
+            context->handleError(
+                Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
+            return false;
+        }
+
+        if (index >= caps.maxVertexAttribBindings)
+        {
+            context->handleError(
+                Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
+            return false;
+        }
+    }
+
+    // [OpenGL ES 3.0.2] Section 2.8 page 24:
+    // An INVALID_OPERATION error is generated when a non-zero vertex array object
+    // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+    // and the pointer argument is not NULL.
+    bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
+                             context->getGLState().getVertexArray()->id() == 0;
+    if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "Client data cannot be used with a non-default vertex array object."));
+        return false;
+    }
+
+    if (context->getExtensions().webglCompatibility)
+    {
+        // WebGL 1.0 [Section 6.14] Fixed point support
+        // The WebGL API does not support the GL_FIXED data type.
+        if (type == GL_FIXED)
+        {
+            context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
+            return false;
+        }
+
+        if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
+{
+    if (context->getExtensions().webglCompatibility && zNear > zFar)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateRenderbufferStorage(ValidationContext *context,
+                                 GLenum target,
+                                 GLenum internalformat,
+                                 GLsizei width,
+                                 GLsizei height)
+{
+    return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
+                                                     height);
+}
+
+bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
+                                                 GLenum target,
+                                                 GLsizei samples,
+                                                 GLenum internalformat,
+                                                 GLsizei width,
+                                                 GLsizei height)
+{
+    if (!context->getExtensions().framebufferMultisample)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
+        return false;
+    }
+
+    // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
+    // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
+    // generated.
+    if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
+    // the specified storage. This is different than ES 3.0 in which a sample number higher
+    // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
+    // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
+    if (context->getClientMajorVersion() >= 3)
+    {
+        const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+        if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+        {
+            context->handleError(Error(GL_OUT_OF_MEMORY));
+            return false;
+        }
+    }
+
+    return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
+                                                     width, height);
+}
+
+bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
+{
+    if (!ValidFramebufferTarget(target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateClearColor(ValidationContext *context,
+                        GLfloat red,
+                        GLfloat green,
+                        GLfloat blue,
+                        GLfloat alpha)
+{
+    return true;
+}
+
+bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
+{
+    return true;
+}
+
+bool ValidateClearStencil(ValidationContext *context, GLint s)
+{
+    return true;
+}
+
+bool ValidateColorMask(ValidationContext *context,
+                       GLboolean red,
+                       GLboolean green,
+                       GLboolean blue,
+                       GLboolean alpha)
+{
+    return true;
+}
+
+bool ValidateCompileShader(ValidationContext *context, GLuint shader)
+{
+    return true;
+}
+
+bool ValidateCreateProgram(ValidationContext *context)
+{
+    return true;
+}
+
+bool ValidateCullFace(ValidationContext *context, GLenum mode)
+{
+    switch (mode)
+    {
+        case GL_FRONT:
+        case GL_BACK:
+        case GL_FRONT_AND_BACK:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
+{
+    if (program == 0)
+    {
+        return false;
+    }
+
+    if (!context->getProgram(program))
+    {
+        if (context->getShader(program))
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
+            return false;
+        }
+        else
+        {
+            context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
+{
+    if (shader == 0)
+    {
+        return false;
+    }
+
+    if (!context->getShader(shader))
+    {
+        if (context->getProgram(shader))
+        {
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
+            return false;
+        }
+        else
+        {
+            context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateDepthFunc(ValidationContext *context, GLenum func)
+{
+    switch (func)
+    {
+        case GL_NEVER:
+        case GL_ALWAYS:
+        case GL_LESS:
+        case GL_LEQUAL:
+        case GL_EQUAL:
+        case GL_GREATER:
+        case GL_GEQUAL:
+        case GL_NOTEQUAL:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
+{
+    return true;
+}
+
+bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
+{
+    Program *programObject = GetValidProgram(context, program);
+    if (!programObject)
+    {
+        return false;
+    }
+
+    Shader *shaderObject = GetValidShader(context, shader);
+    if (!shaderObject)
+    {
+        return false;
+    }
+
+    const Shader *attachedShader = nullptr;
+
+    switch (shaderObject->getType())
+    {
+        case GL_VERTEX_SHADER:
+        {
+            attachedShader = programObject->getAttachedVertexShader();
+            break;
+        }
+        case GL_FRAGMENT_SHADER:
+        {
+            attachedShader = programObject->getAttachedFragmentShader();
+            break;
+        }
+        case GL_COMPUTE_SHADER:
+        {
+            attachedShader = programObject->getAttachedComputeShader();
+            break;
+        }
+        default:
+            UNREACHABLE();
+            return false;
+    }
+
+    if (attachedShader != shaderObject)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
+{
+    if (index >= MAX_VERTEX_ATTRIBS)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
+{
+    if (index >= MAX_VERTEX_ATTRIBS)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateFinish(ValidationContext *context)
+{
+    return true;
+}
+
+bool ValidateFlush(ValidationContext *context)
+{
+    return true;
+}
+
+bool ValidateFrontFace(ValidationContext *context, GLenum mode)
+{
+    switch (mode)
+    {
+        case GL_CW:
+        case GL_CCW:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetActiveAttrib(ValidationContext *context,
+                             GLuint program,
+                             GLuint index,
+                             GLsizei bufsize,
+                             GLsizei *length,
+                             GLint *size,
+                             GLenum *type,
+                             GLchar *name)
+{
+    if (bufsize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+
+    if (!programObject)
+    {
+        return false;
+    }
+
+    if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetActiveUniform(ValidationContext *context,
+                              GLuint program,
+                              GLuint index,
+                              GLsizei bufsize,
+                              GLsizei *length,
+                              GLint *size,
+                              GLenum *type,
+                              GLchar *name)
+{
+    if (bufsize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+
+    if (!programObject)
+    {
+        return false;
+    }
+
+    if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetAttachedShaders(ValidationContext *context,
+                                GLuint program,
+                                GLsizei maxcount,
+                                GLsizei *count,
+                                GLuint *shaders)
+{
+    if (maxcount < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+
+    if (!programObject)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
+{
+    Program *programObject = GetValidProgram(context, program);
+
+    if (!programObject)
+    {
+        return false;
+    }
+
+    if (!programObject->isLinked())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
+{
+    GLenum nativeType;
+    unsigned int numParams = 0;
+    return ValidateStateQuery(context, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetError(ValidationContext *context)
+{
+    return true;
+}
+
+bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
+{
+    GLenum nativeType;
+    unsigned int numParams = 0;
+    return ValidateStateQuery(context, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
+{
+    GLenum nativeType;
+    unsigned int numParams = 0;
+    return ValidateStateQuery(context, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetProgramInfoLog(ValidationContext *context,
+                               GLuint program,
+                               GLsizei bufsize,
+                               GLsizei *length,
+                               GLchar *infolog)
+{
+    if (bufsize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+    if (!programObject)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetShaderInfoLog(ValidationContext *context,
+                              GLuint shader,
+                              GLsizei bufsize,
+                              GLsizei *length,
+                              GLchar *infolog)
+{
+    if (bufsize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+        return false;
+    }
+
+    Shader *shaderObject = GetValidShader(context, shader);
+    if (!shaderObject)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
+                                      GLenum shadertype,
+                                      GLenum precisiontype,
+                                      GLint *range,
+                                      GLint *precision)
+{
+    switch (shadertype)
+    {
+        case GL_VERTEX_SHADER:
+        case GL_FRAGMENT_SHADER:
+            break;
+        case GL_COMPUTE_SHADER:
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
+            return false;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
+            return false;
+    }
+
+    switch (precisiontype)
+    {
+        case GL_LOW_FLOAT:
+        case GL_MEDIUM_FLOAT:
+        case GL_HIGH_FLOAT:
+        case GL_LOW_INT:
+        case GL_MEDIUM_INT:
+        case GL_HIGH_INT:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetShaderSource(ValidationContext *context,
+                             GLuint shader,
+                             GLsizei bufsize,
+                             GLsizei *length,
+                             GLchar *source)
+{
+    if (bufsize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+        return false;
+    }
+
+    Shader *shaderObject = GetValidShader(context, shader);
+    if (!shaderObject)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
+{
+    if (strstr(name, "gl_") == name)
+    {
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+
+    if (!programObject)
+    {
+        return false;
+    }
+
+    if (!programObject->isLinked())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
+{
+    switch (mode)
+    {
+        case GL_FASTEST:
+        case GL_NICEST:
+        case GL_DONT_CARE:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
+            return false;
+    }
+
+    switch (target)
+    {
+        case GL_GENERATE_MIPMAP_HINT:
+            break;
+
+        case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+            if (!context->getExtensions().standardDerivatives)
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
+{
+    return true;
+}
+
+bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
+{
+    return true;
+}
+
+bool ValidateIsProgram(ValidationContext *context, GLuint program)
+{
+    return true;
+}
+
+bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
+{
+    return true;
+}
+
+bool ValidateIsShader(ValidationContext *context, GLuint shader)
+{
+    return true;
+}
+
+bool ValidateIsTexture(ValidationContext *context, GLuint texture)
+{
+    return true;
+}
+
+bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        switch (pname)
+        {
+            case GL_UNPACK_IMAGE_HEIGHT:
+            case GL_UNPACK_SKIP_IMAGES:
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+
+            case GL_UNPACK_ROW_LENGTH:
+            case GL_UNPACK_SKIP_ROWS:
+            case GL_UNPACK_SKIP_PIXELS:
+                if (!context->getExtensions().unpackSubimage)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+
+            case GL_PACK_ROW_LENGTH:
+            case GL_PACK_SKIP_ROWS:
+            case GL_PACK_SKIP_PIXELS:
+                if (!context->getExtensions().packSubimage)
+                {
+                    context->handleError(Error(GL_INVALID_ENUM));
+                    return false;
+                }
+                break;
+        }
+    }
+
+    if (param < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_UNPACK_ALIGNMENT:
+            if (param != 1 && param != 2 && param != 4 && param != 8)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        case GL_PACK_ALIGNMENT:
+            if (param != 1 && param != 2 && param != 4 && param != 8)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+        case GL_UNPACK_ROW_LENGTH:
+        case GL_UNPACK_IMAGE_HEIGHT:
+        case GL_UNPACK_SKIP_IMAGES:
+        case GL_UNPACK_SKIP_ROWS:
+        case GL_UNPACK_SKIP_PIXELS:
+        case GL_PACK_ROW_LENGTH:
+        case GL_PACK_SKIP_ROWS:
+        case GL_PACK_SKIP_PIXELS:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
+{
+    return true;
+}
+
+bool ValidateReleaseShaderCompiler(ValidationContext *context)
+{
+    return true;
+}
+
+bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
+{
+    return true;
+}
+
+bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    if (width < 0 || height < 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateShaderBinary(ValidationContext *context,
+                          GLsizei n,
+                          const GLuint *shaders,
+                          GLenum binaryformat,
+                          const void *binary,
+                          GLsizei length)
+{
+    const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
+    if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
+        shaderBinaryFormats.end())
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateShaderSource(ValidationContext *context,
+                          GLuint shader,
+                          GLsizei count,
+                          const GLchar *const *string,
+                          const GLint *length)
+{
+    if (count < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
+        return false;
+    }
+
+    Shader *shaderObject = GetValidShader(context, shader);
+    if (!shaderObject)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
+{
+    if (!IsValidStencilFunc(func))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateStencilFuncSeparate(ValidationContext *context,
+                                 GLenum face,
+                                 GLenum func,
+                                 GLint ref,
+                                 GLuint mask)
+{
+    if (!IsValidStencilFace(face))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
+        return false;
+    }
+
+    if (!IsValidStencilFunc(func))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateStencilMask(ValidationContext *context, GLuint mask)
+{
+    return true;
+}
+
+bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
+{
+    if (!IsValidStencilFace(face))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
+{
+    if (!IsValidStencilOp(fail))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
+        return false;
+    }
+
+    if (!IsValidStencilOp(zfail))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
+        return false;
+    }
+
+    if (!IsValidStencilOp(zpass))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateStencilOpSeparate(ValidationContext *context,
+                               GLenum face,
+                               GLenum fail,
+                               GLenum zfail,
+                               GLenum zpass)
+{
+    if (!IsValidStencilFace(face))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
+        return false;
+    }
+
+    return ValidateStencilOp(context, fail, zfail, zpass);
+}
+
+bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
+{
+    return ValidateUniform(context, GL_FLOAT, location, 1);
+}
+
+bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+    return ValidateUniform(context, GL_FLOAT, location, count);
+}
+
+bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
+{
+    return ValidateUniform1iv(context, location, 1, &x);
+}
+
+bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
+{
+    return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
+}
+
+bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+    return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
+}
+
+bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
+{
+    return ValidateUniform(context, GL_INT_VEC2, location, 1);
+}
+
+bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
+{
+    return ValidateUniform(context, GL_INT_VEC2, location, count);
+}
+
+bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+    return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
+}
+
+bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+    return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
+}
+
+bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
+{
+    return ValidateUniform(context, GL_INT_VEC3, location, 1);
+}
+
+bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
+{
+    return ValidateUniform(context, GL_INT_VEC3, location, count);
+}
+
+bool ValidateUniform4f(ValidationContext *context,
+                       GLint location,
+                       GLfloat x,
+                       GLfloat y,
+                       GLfloat z,
+                       GLfloat w)
+{
+    return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
+}
+
+bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+    return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
+}
+
+bool ValidateUniform4i(ValidationContext *context,
+                       GLint location,
+                       GLint x,
+                       GLint y,
+                       GLint z,
+                       GLint w)
+{
+    return ValidateUniform(context, GL_INT_VEC4, location, 1);
+}
+
+bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
+{
+    return ValidateUniform(context, GL_INT_VEC4, location, count);
+}
+
+bool ValidateUniformMatrix2fv(ValidationContext *context,
+                              GLint location,
+                              GLsizei count,
+                              GLboolean transpose,
+                              const GLfloat *value)
+{
+    return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
+}
+
+bool ValidateUniformMatrix3fv(ValidationContext *context,
+                              GLint location,
+                              GLsizei count,
+                              GLboolean transpose,
+                              const GLfloat *value)
+{
+    return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
+}
+
+bool ValidateUniformMatrix4fv(ValidationContext *context,
+                              GLint location,
+                              GLsizei count,
+                              GLboolean transpose,
+                              const GLfloat *value)
+{
+    return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
+}
+
+bool ValidateValidateProgram(ValidationContext *context, GLuint program)
+{
+    Program *programObject = GetValidProgram(context, program);
+
+    if (!programObject)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
+{
+    if (index >= MAX_VERTEX_ATTRIBS)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
+{
+    return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+    return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
+{
+    return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+    return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib3f(ValidationContext *context,
+                            GLuint index,
+                            GLfloat x,
+                            GLfloat y,
+                            GLfloat z)
+{
+    return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+    return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib4f(ValidationContext *context,
+                            GLuint index,
+                            GLfloat x,
+                            GLfloat y,
+                            GLfloat z,
+                            GLfloat w)
+{
+    return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+    return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    if (width < 0 || height < 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
+{
+    return ValidateDrawArraysCommon(context, mode, first, count, 1);
+}
+
+bool ValidateDrawElements(ValidationContext *context,
+                          GLenum mode,
+                          GLsizei count,
+                          GLenum type,
+                          const void *indices)
+{
+    return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
+}
+
+bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
+                                                 GLenum target,
+                                                 GLenum attachment,
+                                                 GLenum pname,
+                                                 GLint *params)
+{
+    return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
+                                                           nullptr);
+}
+
+bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
+{
+    return ValidateGetProgramivBase(context, program, pname, nullptr);
+}
+
+bool ValidateCopyTexImage2D(ValidationContext *context,
+                            GLenum target,
+                            GLint level,
+                            GLenum internalformat,
+                            GLint x,
+                            GLint y,
+                            GLsizei width,
+                            GLsizei height,
+                            GLint border)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
+                                                 0, x, y, width, height, border);
+    }
+
+    ASSERT(context->getClientMajorVersion() == 3);
+    return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
+                                               0, x, y, width, height, border);
+}
+
+bool ValidateCopyTexSubImage2D(Context *context,
+                               GLenum target,
+                               GLint level,
+                               GLint xoffset,
+                               GLint yoffset,
+                               GLint x,
+                               GLint y,
+                               GLsizei width,
+                               GLsizei height)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
+                                                 yoffset, x, y, width, height, 0);
+    }
+
+    return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
+                                               yoffset, 0, x, y, width, height, 0);
+}
+
+bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
+{
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
+{
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
+{
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
+{
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDisable(Context *context, GLenum cap)
+{
+    if (!ValidCap(context, cap, false))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateEnable(Context *context, GLenum cap)
+{
+    if (!ValidCap(context, cap, false))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
+        return false;
+    }
+
+    if (context->getLimitations().noSampleAlphaToCoverageSupport &&
+        cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
+    {
+        const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
+        context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
+
+        // We also output an error message to the debugger window if tracing is active, so that
+        // developers can see the error message.
+        ERR() << errorMessage;
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateFramebufferRenderbuffer(Context *context,
+                                     GLenum target,
+                                     GLenum attachment,
+                                     GLenum renderbuffertarget,
+                                     GLuint renderbuffer)
+{
+    if (!ValidFramebufferTarget(target) ||
+        (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return ValidateFramebufferRenderbufferParameters(context, target, attachment,
+                                                     renderbuffertarget, renderbuffer);
+}
+
+bool ValidateFramebufferTexture2D(Context *context,
+                                  GLenum target,
+                                  GLenum attachment,
+                                  GLenum textarget,
+                                  GLuint texture,
+                                  GLint level)
+{
+    // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
+    // extension
+    if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
+        level != 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
+    {
+        return false;
+    }
+
+    if (texture != 0)
+    {
+        gl::Texture *tex = context->getTexture(texture);
+        ASSERT(tex);
+
+        const gl::Caps &caps = context->getCaps();
+
+        switch (textarget)
+        {
+            case GL_TEXTURE_2D:
+            {
+                if (level > gl::log2(caps.max2DTextureSize))
+                {
+                    context->handleError(Error(GL_INVALID_VALUE));
+                    return false;
+                }
+                if (tex->getTarget() != GL_TEXTURE_2D)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION,
+                                               "Textarget must match the texture target type."));
+                    return false;
+                }
+            }
+            break;
+
+            case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+            case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+            case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+            case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+            case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+            case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+            {
+                if (level > gl::log2(caps.maxCubeMapTextureSize))
+                {
+                    context->handleError(Error(GL_INVALID_VALUE));
+                    return false;
+                }
+                if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION,
+                                               "Textarget must match the texture target type."));
+                    return false;
+                }
+            }
+            break;
+
+            case GL_TEXTURE_2D_MULTISAMPLE:
+            {
+                if (context->getClientVersion() < ES_3_1)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION,
+                                               "Texture target requires at least OpenGL ES 3.1."));
+                    return false;
+                }
+
+                if (level != 0)
+                {
+                    context->handleError(
+                        Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
+                    return false;
+                }
+                if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION,
+                                               "Textarget must match the texture target type."));
+                    return false;
+                }
+            }
+            break;
+
+            default:
+                context->handleError(Error(GL_INVALID_ENUM));
+                return false;
+        }
+
+        const Format &format = tex->getFormat(textarget, level);
+        if (format.info->compressed)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
+{
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
+{
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
+{
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenTextures(Context *context, GLint n, GLuint *)
+{
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenerateMipmap(Context *context, GLenum target)
+{
+    if (!ValidTextureTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    Texture *texture = context->getTargetTexture(target);
+
+    if (texture == nullptr)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
+
+    // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
+    // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
+    if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    GLenum baseTarget  = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
+    const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
+    const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
+
+    // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
+    // unsized formats or that are color renderable and filterable.  Since we do not track if
+    // the texture was created with sized or unsized format (only sized formats are stored),
+    // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
+    // be able to) because they aren't color renderable.  Simply do a special case for LUMA
+    // textures since they're the only texture format that can be created with unsized formats
+    // that is not color renderable.  New unsized formats are unlikely to be added, since ES2
+    // was the last version to use add them.
+    if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
+        (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
+    bool supportsSRGBMipmapGeneration =
+        context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
+    if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Mipmap generation of sRGB textures is not allowed."));
+        return false;
+    }
+
+    // Non-power of 2 ES2 check
+    if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
+        (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
+         !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
+    {
+        ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    // Cube completeness check
+    if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetBufferParameteriv(ValidationContext *context,
+                                  GLenum target,
+                                  GLenum pname,
+                                  GLint *params)
+{
+    return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
+}
+
+bool ValidateGetRenderbufferParameteriv(Context *context,
+                                        GLenum target,
+                                        GLenum pname,
+                                        GLint *params)
+{
+    return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
+{
+    return ValidateGetShaderivBase(context, shader, pname, nullptr);
+}
+
+bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
+{
+    return ValidateGetTexParameterBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
+{
+    return ValidateGetTexParameterBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
+{
+    return ValidateGetUniformBase(context, program, location);
+}
+
+bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
+{
+    return ValidateGetUniformBase(context, program, location);
+}
+
+bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
+{
+    return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
+}
+
+bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
+{
+    return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
+}
+
+bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
+{
+    return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
+}
+
+bool ValidateIsEnabled(Context *context, GLenum cap)
+{
+    if (!ValidCap(context, cap, true))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateLinkProgram(Context *context, GLuint program)
+{
+    if (context->hasActiveTransformFeedback(program))
+    {
+        // ES 3.0.4 section 2.15 page 91
+        context->handleError(Error(GL_INVALID_OPERATION,
+                                   "Cannot link program while program is associated with an active "
+                                   "transform feedback object."));
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+    if (!programObject)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateReadPixels(ValidationContext *context,
+                        GLint x,
+                        GLint y,
+                        GLsizei width,
+                        GLsizei height,
+                        GLenum format,
+                        GLenum type,
+                        void *pixels)
+{
+    return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
+                                  nullptr, pixels);
+}
+
+bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
+{
+    return ValidateTexParameterBase(context, target, pname, -1, &param);
+}
+
+bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
+{
+    return ValidateTexParameterBase(context, target, pname, -1, params);
+}
+
+bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
+{
+    return ValidateTexParameterBase(context, target, pname, -1, &param);
+}
+
+bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
+{
+    return ValidateTexParameterBase(context, target, pname, -1, params);
+}
+
+bool ValidateUseProgram(Context *context, GLuint program)
+{
+    if (program != 0)
+    {
+        Program *programObject = context->getProgram(program);
+        if (!programObject)
+        {
+            // ES 3.1.0 section 7.3 page 72
+            if (context->getShader(program))
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION,
+                          "Attempted to use a single shader instead of a shader program."));
+                return false;
+            }
+            else
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
+                return false;
+            }
+        }
+        if (!programObject->isLinked())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
+            return false;
+        }
+    }
+    if (context->getGLState().isTransformFeedbackActiveUnpaused())
+    {
+        // ES 3.0.4 section 2.15 page 91
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "Cannot change active program while transform feedback is unpaused."));
+        return false;
+    }
+
+    return true;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/validationES2.h b/src/third_party/angle/src/libANGLE/validationES2.h
new file mode 100644
index 0000000..e6ae180
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationES2.h
@@ -0,0 +1,681 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES2.h: Validation functions for OpenGL ES 2.0 entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES2_H_
+#define LIBANGLE_VALIDATION_ES2_H_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+namespace gl
+{
+class Context;
+class ValidationContext;
+
+bool ValidateES2TexStorageParameters(Context *context,
+                                     GLenum target,
+                                     GLsizei levels,
+                                     GLenum internalformat,
+                                     GLsizei width,
+                                     GLsizei height);
+
+bool ValidateDiscardFramebufferEXT(Context *context,
+                                   GLenum target,
+                                   GLsizei numAttachments,
+                                   const GLenum *attachments);
+
+bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs);
+
+bool ValidateBindVertexArrayOES(Context *context, GLuint array);
+bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n);
+bool ValidateGenVertexArraysOES(Context *context, GLsizei n);
+bool ValidateIsVertexArrayOES(Context *context);
+
+bool ValidateProgramBinaryOES(Context *context,
+                              GLuint program,
+                              GLenum binaryFormat,
+                              const void *binary,
+                              GLint length);
+bool ValidateGetProgramBinaryOES(Context *context,
+                                 GLuint program,
+                                 GLsizei bufSize,
+                                 GLsizei *length,
+                                 GLenum *binaryFormat,
+                                 void *binary);
+
+// GL_KHR_debug
+bool ValidateDebugMessageControlKHR(Context *context,
+                                    GLenum source,
+                                    GLenum type,
+                                    GLenum severity,
+                                    GLsizei count,
+                                    const GLuint *ids,
+                                    GLboolean enabled);
+bool ValidateDebugMessageInsertKHR(Context *context,
+                                   GLenum source,
+                                   GLenum type,
+                                   GLuint id,
+                                   GLenum severity,
+                                   GLsizei length,
+                                   const GLchar *buf);
+bool ValidateDebugMessageCallbackKHR(Context *context,
+                                     GLDEBUGPROCKHR callback,
+                                     const void *userParam);
+bool ValidateGetDebugMessageLogKHR(Context *context,
+                                   GLuint count,
+                                   GLsizei bufSize,
+                                   GLenum *sources,
+                                   GLenum *types,
+                                   GLuint *ids,
+                                   GLenum *severities,
+                                   GLsizei *lengths,
+                                   GLchar *messageLog);
+bool ValidatePushDebugGroupKHR(Context *context,
+                               GLenum source,
+                               GLuint id,
+                               GLsizei length,
+                               const GLchar *message);
+bool ValidatePopDebugGroupKHR(Context *context);
+bool ValidateObjectLabelKHR(Context *context,
+                            GLenum identifier,
+                            GLuint name,
+                            GLsizei length,
+                            const GLchar *label);
+bool ValidateGetObjectLabelKHR(Context *context,
+                               GLenum identifier,
+                               GLuint name,
+                               GLsizei bufSize,
+                               GLsizei *length,
+                               GLchar *label);
+bool ValidateObjectPtrLabelKHR(Context *context,
+                               const void *ptr,
+                               GLsizei length,
+                               const GLchar *label);
+bool ValidateGetObjectPtrLabelKHR(Context *context,
+                                  const void *ptr,
+                                  GLsizei bufSize,
+                                  GLsizei *length,
+                                  GLchar *label);
+bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params);
+bool ValidateBlitFramebufferANGLE(Context *context,
+                                  GLint srcX0,
+                                  GLint srcY0,
+                                  GLint srcX1,
+                                  GLint srcY1,
+                                  GLint dstX0,
+                                  GLint dstY0,
+                                  GLint dstX1,
+                                  GLint dstY1,
+                                  GLbitfield mask,
+                                  GLenum filter);
+
+bool ValidateClear(ValidationContext *context, GLbitfield mask);
+bool ValidateTexImage2D(Context *context,
+                        GLenum target,
+                        GLint level,
+                        GLint internalformat,
+                        GLsizei width,
+                        GLsizei height,
+                        GLint border,
+                        GLenum format,
+                        GLenum type,
+                        const void *pixels);
+bool ValidateTexImage2DRobust(Context *context,
+                              GLenum target,
+                              GLint level,
+                              GLint internalformat,
+                              GLsizei width,
+                              GLsizei height,
+                              GLint border,
+                              GLenum format,
+                              GLenum type,
+                              GLsizei bufSize,
+                              const void *pixels);
+bool ValidateTexSubImage2D(Context *context,
+                           GLenum target,
+                           GLint level,
+                           GLint xoffset,
+                           GLint yoffset,
+                           GLsizei width,
+                           GLsizei height,
+                           GLenum format,
+                           GLenum type,
+                           const void *pixels);
+bool ValidateTexSubImage2DRobustANGLE(Context *context,
+                                      GLenum target,
+                                      GLint level,
+                                      GLint xoffset,
+                                      GLint yoffset,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLenum format,
+                                      GLenum type,
+                                      GLsizei bufSize,
+                                      const void *pixels);
+bool ValidateCompressedTexImage2D(Context *context,
+                                  GLenum target,
+                                  GLint level,
+                                  GLenum internalformat,
+                                  GLsizei width,
+                                  GLsizei height,
+                                  GLint border,
+                                  GLsizei imageSize,
+                                  const void *data);
+bool ValidateCompressedTexSubImage2D(Context *context,
+                                     GLenum target,
+                                     GLint level,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLenum format,
+                                     GLsizei imageSize,
+                                     const void *data);
+bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
+                                             GLenum target,
+                                             GLint level,
+                                             GLenum internalformat,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLint border,
+                                             GLsizei imageSize,
+                                             GLsizei dataSize,
+                                             const void *data);
+bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
+                                                GLenum target,
+                                                GLint level,
+                                                GLint xoffset,
+                                                GLint yoffset,
+                                                GLsizei width,
+                                                GLsizei height,
+                                                GLenum format,
+                                                GLsizei imageSize,
+                                                GLsizei dataSize,
+                                                const void *data);
+
+bool ValidateBindTexture(Context *context, GLenum target, GLuint texture);
+
+bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params);
+bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access);
+bool ValidateUnmapBufferOES(Context *context, GLenum target);
+bool ValidateMapBufferRangeEXT(Context *context,
+                               GLenum target,
+                               GLintptr offset,
+                               GLsizeiptr length,
+                               GLbitfield access);
+bool ValidateFlushMappedBufferRangeEXT(Context *context,
+                                       GLenum target,
+                                       GLintptr offset,
+                                       GLsizeiptr length);
+
+bool ValidateBindUniformLocationCHROMIUM(Context *context,
+                                         GLuint program,
+                                         GLint location,
+                                         const GLchar *name);
+
+bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components);
+
+// CHROMIUM_path_rendering
+bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix);
+bool ValidateMatrixMode(Context *context, GLenum matrixMode);
+bool ValidateGenPaths(Context *context, GLsizei range);
+bool ValidateDeletePaths(Context *context, GLuint first, GLsizei range);
+bool ValidatePathCommands(Context *context,
+                          GLuint path,
+                          GLsizei numCommands,
+                          const GLubyte *commands,
+                          GLsizei numCoords,
+                          GLenum coordType,
+                          const void *coords);
+bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value);
+bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value);
+bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask);
+bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask);
+bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask);
+bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode);
+bool ValidateStencilThenCoverFillPath(Context *context,
+                                      GLuint path,
+                                      GLenum fillMode,
+                                      GLuint mask,
+                                      GLenum coverMode);
+bool ValidateStencilThenCoverStrokePath(Context *context,
+                                        GLuint path,
+                                        GLint reference,
+                                        GLuint mask,
+                                        GLenum coverMode);
+bool ValidateIsPath(Context *context);
+bool ValidateCoverFillPathInstanced(Context *context,
+                                    GLsizei numPaths,
+                                    GLenum pathNameType,
+                                    const void *paths,
+                                    GLuint pathBase,
+                                    GLenum coverMode,
+                                    GLenum transformType,
+                                    const GLfloat *transformValues);
+bool ValidateCoverStrokePathInstanced(Context *context,
+                                      GLsizei numPaths,
+                                      GLenum pathNameType,
+                                      const void *paths,
+                                      GLuint pathBase,
+                                      GLenum coverMode,
+                                      GLenum transformType,
+                                      const GLfloat *transformValues);
+bool ValidateStencilFillPathInstanced(Context *context,
+                                      GLsizei numPaths,
+                                      GLenum pathNameType,
+                                      const void *paths,
+                                      GLuint pathBAse,
+                                      GLenum fillMode,
+                                      GLuint mask,
+                                      GLenum transformType,
+                                      const GLfloat *transformValues);
+bool ValidateStencilStrokePathInstanced(Context *context,
+                                        GLsizei numPaths,
+                                        GLenum pathNameType,
+                                        const void *paths,
+                                        GLuint pathBase,
+                                        GLint reference,
+                                        GLuint mask,
+                                        GLenum transformType,
+                                        const GLfloat *transformValues);
+bool ValidateStencilThenCoverFillPathInstanced(Context *context,
+                                               GLsizei numPaths,
+                                               GLenum pathNameType,
+                                               const void *paths,
+                                               GLuint pathBase,
+                                               GLenum fillMode,
+                                               GLuint mask,
+                                               GLenum coverMode,
+                                               GLenum transformType,
+                                               const GLfloat *transformValues);
+bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
+                                                 GLsizei numPaths,
+                                                 GLenum pathNameType,
+                                                 const void *paths,
+                                                 GLuint pathBase,
+                                                 GLint reference,
+                                                 GLuint mask,
+                                                 GLenum coverMode,
+                                                 GLenum transformType,
+                                                 const GLfloat *transformValues);
+bool ValidateBindFragmentInputLocation(Context *context,
+                                       GLuint program,
+                                       GLint location,
+                                       const GLchar *name);
+bool ValidateProgramPathFragmentInputGen(Context *context,
+                                         GLuint program,
+                                         GLint location,
+                                         GLenum genMode,
+                                         GLint components,
+                                         const GLfloat *coeffs);
+
+bool ValidateCopyTextureCHROMIUM(Context *context,
+                                 GLuint sourceId,
+                                 GLint sourceLevel,
+                                 GLenum destTarget,
+                                 GLuint destId,
+                                 GLint destLevel,
+                                 GLint internalFormat,
+                                 GLenum destType,
+                                 GLboolean unpackFlipY,
+                                 GLboolean unpackPremultiplyAlpha,
+                                 GLboolean unpackUnmultiplyAlpha);
+bool ValidateCopySubTextureCHROMIUM(Context *context,
+                                    GLuint sourceId,
+                                    GLint sourceLevel,
+                                    GLenum destTarget,
+                                    GLuint destId,
+                                    GLint destLevel,
+                                    GLint xoffset,
+                                    GLint yoffset,
+                                    GLint x,
+                                    GLint y,
+                                    GLsizei width,
+                                    GLsizei height,
+                                    GLboolean unpackFlipY,
+                                    GLboolean unpackPremultiplyAlpha,
+                                    GLboolean unpackUnmultiplyAlpha);
+bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId);
+
+bool ValidateCreateShader(Context *context, GLenum type);
+bool ValidateBufferData(ValidationContext *context,
+                        GLenum target,
+                        GLsizeiptr size,
+                        const void *data,
+                        GLenum usage);
+bool ValidateBufferSubData(ValidationContext *context,
+                           GLenum target,
+                           GLintptr offset,
+                           GLsizeiptr size,
+                           const void *data);
+
+bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name);
+
+bool ValidateActiveTexture(ValidationContext *context, GLenum texture);
+bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader);
+bool ValidateBindAttribLocation(ValidationContext *context,
+                                GLuint program,
+                                GLuint index,
+                                const GLchar *name);
+bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer);
+bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer);
+bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer);
+bool ValidateBlendColor(ValidationContext *context,
+                        GLclampf red,
+                        GLclampf green,
+                        GLclampf blue,
+                        GLclampf alpha);
+bool ValidateBlendEquation(ValidationContext *context, GLenum mode);
+bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha);
+bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor);
+bool ValidateBlendFuncSeparate(ValidationContext *context,
+                               GLenum srcRGB,
+                               GLenum dstRGB,
+                               GLenum srcAlpha,
+                               GLenum dstAlpha);
+
+bool ValidateGetString(Context *context, GLenum name);
+bool ValidateLineWidth(ValidationContext *context, GLfloat width);
+bool ValidateVertexAttribPointer(ValidationContext *context,
+                                 GLuint index,
+                                 GLint size,
+                                 GLenum type,
+                                 GLboolean normalized,
+                                 GLsizei stride,
+                                 const void *ptr);
+
+bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar);
+bool ValidateRenderbufferStorage(ValidationContext *context,
+                                 GLenum target,
+                                 GLenum internalformat,
+                                 GLsizei width,
+                                 GLsizei height);
+bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
+                                                 GLenum target,
+                                                 GLsizei samples,
+                                                 GLenum internalformat,
+                                                 GLsizei width,
+                                                 GLsizei height);
+
+bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target);
+bool ValidateClearColor(ValidationContext *context,
+                        GLclampf red,
+                        GLclampf green,
+                        GLclampf blue,
+                        GLclampf alpha);
+bool ValidateClearDepthf(ValidationContext *context, GLclampf depth);
+bool ValidateClearStencil(ValidationContext *context, GLint s);
+bool ValidateColorMask(ValidationContext *context,
+                       GLboolean red,
+                       GLboolean green,
+                       GLboolean blue,
+                       GLboolean alpha);
+bool ValidateCompileShader(ValidationContext *context, GLuint shader);
+bool ValidateCreateProgram(ValidationContext *context);
+bool ValidateCullFace(ValidationContext *context, GLenum mode);
+bool ValidateDeleteProgram(ValidationContext *context, GLuint program);
+bool ValidateDeleteShader(ValidationContext *context, GLuint shader);
+bool ValidateDepthFunc(ValidationContext *context, GLenum func);
+bool ValidateDepthMask(ValidationContext *context, GLboolean flag);
+bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader);
+bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index);
+bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index);
+bool ValidateFinish(ValidationContext *context);
+bool ValidateFlush(ValidationContext *context);
+bool ValidateFrontFace(ValidationContext *context, GLenum mode);
+bool ValidateGetActiveAttrib(ValidationContext *context,
+                             GLuint program,
+                             GLuint index,
+                             GLsizei bufsize,
+                             GLsizei *length,
+                             GLint *size,
+                             GLenum *type,
+                             GLchar *name);
+bool ValidateGetActiveUniform(ValidationContext *context,
+                              GLuint program,
+                              GLuint index,
+                              GLsizei bufsize,
+                              GLsizei *length,
+                              GLint *size,
+                              GLenum *type,
+                              GLchar *name);
+bool ValidateGetAttachedShaders(ValidationContext *context,
+                                GLuint program,
+                                GLsizei maxcount,
+                                GLsizei *count,
+                                GLuint *shaders);
+bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name);
+bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params);
+bool ValidateGetError(ValidationContext *context);
+bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params);
+bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params);
+bool ValidateGetProgramInfoLog(ValidationContext *context,
+                               GLuint program,
+                               GLsizei bufsize,
+                               GLsizei *length,
+                               GLchar *infolog);
+bool ValidateGetShaderInfoLog(ValidationContext *context,
+                              GLuint shader,
+                              GLsizei bufsize,
+                              GLsizei *length,
+                              GLchar *infolog);
+bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
+                                      GLenum shadertype,
+                                      GLenum precisiontype,
+                                      GLint *range,
+                                      GLint *precision);
+bool ValidateGetShaderSource(ValidationContext *context,
+                             GLuint shader,
+                             GLsizei bufsize,
+                             GLsizei *length,
+                             GLchar *source);
+bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name);
+bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode);
+bool ValidateIsBuffer(ValidationContext *context, GLuint buffer);
+bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer);
+bool ValidateIsProgram(ValidationContext *context, GLuint program);
+bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer);
+bool ValidateIsShader(ValidationContext *context, GLuint shader);
+bool ValidateIsTexture(ValidationContext *context, GLuint texture);
+bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param);
+bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units);
+bool ValidateReleaseShaderCompiler(ValidationContext *context);
+bool ValidateSampleCoverage(ValidationContext *context, GLclampf value, GLboolean invert);
+bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height);
+bool ValidateShaderBinary(ValidationContext *context,
+                          GLsizei n,
+                          const GLuint *shaders,
+                          GLenum binaryformat,
+                          const void *binary,
+                          GLsizei length);
+bool ValidateShaderSource(ValidationContext *context,
+                          GLuint shader,
+                          GLsizei count,
+                          const GLchar *const *string,
+                          const GLint *length);
+bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask);
+bool ValidateStencilFuncSeparate(ValidationContext *context,
+                                 GLenum face,
+                                 GLenum func,
+                                 GLint ref,
+                                 GLuint mask);
+bool ValidateStencilMask(ValidationContext *context, GLuint mask);
+bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask);
+bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass);
+bool ValidateStencilOpSeparate(ValidationContext *context,
+                               GLenum face,
+                               GLenum fail,
+                               GLenum zfail,
+                               GLenum zpass);
+bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x);
+bool ValidateUniform1fv(ValidationContext *context,
+                        GLint location,
+                        GLsizei count,
+                        const GLfloat *v);
+bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x);
+bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y);
+bool ValidateUniform2fv(ValidationContext *context,
+                        GLint location,
+                        GLsizei count,
+                        const GLfloat *v);
+bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y);
+bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v);
+bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z);
+bool ValidateUniform3fv(ValidationContext *context,
+                        GLint location,
+                        GLsizei count,
+                        const GLfloat *v);
+bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z);
+bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v);
+bool ValidateUniform4f(ValidationContext *context,
+                       GLint location,
+                       GLfloat x,
+                       GLfloat y,
+                       GLfloat z,
+                       GLfloat w);
+bool ValidateUniform4fv(ValidationContext *context,
+                        GLint location,
+                        GLsizei count,
+                        const GLfloat *v);
+bool ValidateUniform4i(ValidationContext *context,
+                       GLint location,
+                       GLint x,
+                       GLint y,
+                       GLint z,
+                       GLint w);
+bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v);
+bool ValidateUniformMatrix2fv(ValidationContext *context,
+                              GLint location,
+                              GLsizei count,
+                              GLboolean transpose,
+                              const GLfloat *value);
+bool ValidateUniformMatrix3fv(ValidationContext *context,
+                              GLint location,
+                              GLsizei count,
+                              GLboolean transpose,
+                              const GLfloat *value);
+bool ValidateUniformMatrix4fv(ValidationContext *context,
+                              GLint location,
+                              GLsizei count,
+                              GLboolean transpose,
+                              const GLfloat *value);
+bool ValidateValidateProgram(ValidationContext *context, GLuint program);
+bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x);
+bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values);
+bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y);
+bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values);
+bool ValidateVertexAttrib3f(ValidationContext *context,
+                            GLuint index,
+                            GLfloat x,
+                            GLfloat y,
+                            GLfloat z);
+bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values);
+bool ValidateVertexAttrib4f(ValidationContext *context,
+                            GLuint index,
+                            GLfloat x,
+                            GLfloat y,
+                            GLfloat z,
+                            GLfloat w);
+bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values);
+bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height);
+bool ValidateDrawElements(ValidationContext *context,
+                          GLenum mode,
+                          GLsizei count,
+                          GLenum type,
+                          const void *indices);
+
+bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count);
+
+bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
+                                                 GLenum target,
+                                                 GLenum attachment,
+                                                 GLenum pname,
+                                                 GLint *params);
+bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params);
+
+bool ValidateCopyTexImage2D(ValidationContext *context,
+                            GLenum target,
+                            GLint level,
+                            GLenum internalformat,
+                            GLint x,
+                            GLint y,
+                            GLsizei width,
+                            GLsizei height,
+                            GLint border);
+
+bool ValidateCopyTexSubImage2D(Context *context,
+                               GLenum target,
+                               GLint level,
+                               GLint xoffset,
+                               GLint yoffset,
+                               GLint x,
+                               GLint y,
+                               GLsizei width,
+                               GLsizei height);
+
+bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *buffers);
+bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *framebuffers);
+bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *renderbuffers);
+bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *textures);
+bool ValidateDisable(Context *context, GLenum cap);
+bool ValidateEnable(Context *context, GLenum cap);
+bool ValidateFramebufferRenderbuffer(Context *context,
+                                     GLenum target,
+                                     GLenum attachment,
+                                     GLenum renderbuffertarget,
+                                     GLuint renderbuffer);
+bool ValidateFramebufferTexture2D(Context *context,
+                                  GLenum target,
+                                  GLenum attachment,
+                                  GLenum textarget,
+                                  GLuint texture,
+                                  GLint level);
+bool ValidateGenBuffers(Context *context, GLint n, GLuint *buffers);
+bool ValidateGenerateMipmap(Context *context, GLenum target);
+bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *framebuffers);
+bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *renderbuffers);
+bool ValidateGenTextures(Context *context, GLint n, GLuint *textures);
+bool ValidateGetBufferParameteriv(ValidationContext *context,
+                                  GLenum target,
+                                  GLenum pname,
+                                  GLint *params);
+bool ValidateGetRenderbufferParameteriv(Context *context,
+                                        GLenum target,
+                                        GLenum pname,
+                                        GLint *params);
+bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params);
+bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params);
+bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params);
+bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params);
+bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params);
+bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params);
+bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params);
+bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer);
+bool ValidateIsEnabled(Context *context, GLenum cap);
+bool ValidateLinkProgram(Context *context, GLuint program);
+bool ValidateReadPixels(ValidationContext *context,
+                        GLint x,
+                        GLint y,
+                        GLsizei width,
+                        GLsizei height,
+                        GLenum format,
+                        GLenum type,
+                        void *pixels);
+bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param);
+bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params);
+bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param);
+bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params);
+bool ValidateUniform1iv(ValidationContext *context,
+                        GLint location,
+                        GLsizei count,
+                        const GLint *value);
+bool ValidateUseProgram(Context *context, GLuint program);
+
+}  // namespace gl
+
+#endif  // LIBANGLE_VALIDATION_ES2_H_
diff --git a/src/third_party/angle/src/libANGLE/validationES3.cpp b/src/third_party/angle/src/libANGLE/validationES3.cpp
new file mode 100644
index 0000000..125e839
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationES3.cpp
@@ -0,0 +1,2583 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
+
+#include "libANGLE/validationES3.h"
+
+#include "base/numerics/safe_conversions.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/validationES.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+static bool ValidateTexImageFormatCombination(gl::Context *context,
+                                              GLenum target,
+                                              GLenum internalFormat,
+                                              GLenum format,
+                                              GLenum type)
+{
+
+    // The type and format are valid if any supported internal format has that type and format
+    if (!ValidES3Format(format))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid format."));
+        return false;
+    }
+
+    if (!ValidES3Type(type))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid type."));
+        return false;
+    }
+
+    // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
+    // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
+    // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
+    // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
+    if (!ValidES3InternalFormat(internalFormat))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid internalFormat."));
+        return false;
+    }
+
+    // From the ES 3.0 spec section 3.8.3:
+    // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
+    // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
+    // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
+    // INVALID_OPERATION error.
+    if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
+    {
+        context->handleError(Error(
+            GL_INVALID_OPERATION,
+            "Format cannot be GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL if target is GL_TEXTURE_3D"));
+        return false;
+    }
+
+    // Check if this is a valid format combination to load texture data
+    if (!ValidES3FormatCombination(format, type, internalFormat))
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Invalid combination of format, type and internalFormat."));
+        return false;
+    }
+
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+    if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Unsupported internal format."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateES3TexImageParametersBase(Context *context,
+                                       GLenum target,
+                                       GLint level,
+                                       GLenum internalformat,
+                                       bool isCompressed,
+                                       bool isSubImage,
+                                       GLint xoffset,
+                                       GLint yoffset,
+                                       GLint zoffset,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLsizei depth,
+                                       GLint border,
+                                       GLenum format,
+                                       GLenum type,
+                                       GLsizei imageSize,
+                                       const void *pixels)
+{
+    // Validate image size
+    if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    // Verify zero border
+    if (border != 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
+        std::numeric_limits<GLsizei>::max() - xoffset < width ||
+        std::numeric_limits<GLsizei>::max() - yoffset < height ||
+        std::numeric_limits<GLsizei>::max() - zoffset < depth)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    const gl::Caps &caps = context->getCaps();
+
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+            if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+                static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+            if (!isSubImage && width != height)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+
+            if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_3D:
+            if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
+                static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
+                static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        case GL_TEXTURE_2D_ARRAY:
+            if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+                static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
+                static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    gl::Texture *texture =
+        context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    if (!texture)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (texture->getImmutableFormat() && !isSubImage)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    // Validate texture formats
+    GLenum actualInternalFormat =
+        isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
+    if (isSubImage && actualInternalFormat == GL_NONE)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
+        return false;
+    }
+
+    const gl::InternalFormat &actualFormatInfo = isSubImage
+                                                     ? *texture->getFormat(target, level).info
+                                                     : GetInternalFormatInfo(internalformat, type);
+    if (isCompressed)
+    {
+        if (!actualFormatInfo.compressed)
+        {
+            context->handleError(Error(
+                GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
+            return false;
+        }
+
+        if (isSubImage)
+        {
+            if (!ValidCompressedSubImageSize(
+                    context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
+                    texture->getWidth(target, level), texture->getHeight(target, level)))
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
+                return false;
+            }
+
+            if (format != actualInternalFormat)
+            {
+                context->handleError(Error(
+                    GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
+                return false;
+            }
+        }
+        else
+        {
+            if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
+                return false;
+            }
+        }
+
+        if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+        {
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+        }
+
+        if (target == GL_TEXTURE_3D)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+    else
+    {
+        if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
+        {
+            return false;
+        }
+    }
+
+    // Validate sub image parameters
+    if (isSubImage)
+    {
+        if (isCompressed != actualFormatInfo.compressed)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+
+        if (xoffset < 0 || yoffset < 0 || zoffset < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+
+        if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
+            std::numeric_limits<GLsizei>::max() - yoffset < height ||
+            std::numeric_limits<GLsizei>::max() - zoffset < depth)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+
+        if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+            static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
+            static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+    }
+
+    if (!ValidImageDataSize(context, target, width, height, depth, actualInternalFormat, type,
+                            pixels, imageSize))
+    {
+        return false;
+    }
+
+    // Check for pixel unpack buffer related API errors
+    gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
+    if (pixelUnpackBuffer != nullptr)
+    {
+        // ...data is not evenly divisible into the number of bytes needed to store in memory a
+        // datum
+        // indicated by type.
+        if (!isCompressed)
+        {
+            size_t offset            = reinterpret_cast<size_t>(pixels);
+            size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
+
+            if ((offset % dataBytesPerPixel) != 0)
+            {
+                context->handleError(
+                    Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
+                return false;
+            }
+        }
+
+        // ...the buffer object's data store is currently mapped.
+        if (pixelUnpackBuffer->isMapped())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateES3TexImage2DParameters(Context *context,
+                                     GLenum target,
+                                     GLint level,
+                                     GLenum internalformat,
+                                     bool isCompressed,
+                                     bool isSubImage,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLint zoffset,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLsizei depth,
+                                     GLint border,
+                                     GLenum format,
+                                     GLenum type,
+                                     GLsizei imageSize,
+                                     const void *pixels)
+{
+    if (!ValidTexture2DDestinationTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
+                                             isSubImage, xoffset, yoffset, zoffset, width, height,
+                                             depth, border, format, type, imageSize, pixels);
+}
+
+bool ValidateES3TexImage3DParameters(Context *context,
+                                     GLenum target,
+                                     GLint level,
+                                     GLenum internalformat,
+                                     bool isCompressed,
+                                     bool isSubImage,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLint zoffset,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLsizei depth,
+                                     GLint border,
+                                     GLenum format,
+                                     GLenum type,
+                                     GLsizei bufSize,
+                                     const void *pixels)
+{
+    if (!ValidTexture3DDestinationTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
+                                             isSubImage, xoffset, yoffset, zoffset, width, height,
+                                             depth, border, format, type, bufSize, pixels);
+}
+
+struct EffectiveInternalFormatInfo
+{
+    GLenum effectiveFormat;
+    GLenum destFormat;
+    GLuint minRedBits;
+    GLuint maxRedBits;
+    GLuint minGreenBits;
+    GLuint maxGreenBits;
+    GLuint minBlueBits;
+    GLuint maxBlueBits;
+    GLuint minAlphaBits;
+    GLuint maxAlphaBits;
+};
+
+static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
+                                     GLenum targetFormat,
+                                     const EffectiveInternalFormatInfo *list,
+                                     size_t size,
+                                     GLenum *outEffectiveFormat)
+{
+    for (size_t curFormat = 0; curFormat < size; ++curFormat)
+    {
+        const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
+        if ((formatInfo.destFormat == targetFormat) &&
+            (formatInfo.minRedBits <= srcFormat.redBits &&
+             formatInfo.maxRedBits >= srcFormat.redBits) &&
+            (formatInfo.minGreenBits <= srcFormat.greenBits &&
+             formatInfo.maxGreenBits >= srcFormat.greenBits) &&
+            (formatInfo.minBlueBits <= srcFormat.blueBits &&
+             formatInfo.maxBlueBits >= srcFormat.blueBits) &&
+            (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
+             formatInfo.maxAlphaBits >= srcFormat.alphaBits))
+        {
+            *outEffectiveFormat = formatInfo.effectiveFormat;
+            return true;
+        }
+    }
+
+    *outEffectiveFormat = GL_NONE;
+    return false;
+}
+
+bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
+                                         GLenum *outEffectiveFormat)
+{
+    // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
+    // Effective internal format coresponding to destination internal format and linear source
+    // buffer component sizes.
+    //                                       | Source channel min/max sizes |
+    //   Effective Internal Format   |  N/A  |  R   |  G   |  B   |  A      |
+    // clang-format off
+    constexpr EffectiveInternalFormatInfo list[] = {
+        { GL_ALPHA8_EXT,              GL_NONE, 0,  0, 0,  0, 0,  0, 1, 8 },
+        { GL_R8,                      GL_NONE, 1,  8, 0,  0, 0,  0, 0, 0 },
+        { GL_RG8,                     GL_NONE, 1,  8, 1,  8, 0,  0, 0, 0 },
+        { GL_RGB565,                  GL_NONE, 1,  5, 1,  6, 1,  5, 0, 0 },
+        { GL_RGB8,                    GL_NONE, 6,  8, 7,  8, 6,  8, 0, 0 },
+        { GL_RGBA4,                   GL_NONE, 1,  4, 1,  4, 1,  4, 1, 4 },
+        { GL_RGB5_A1,                 GL_NONE, 5,  5, 5,  5, 5,  5, 1, 1 },
+        { GL_RGBA8,                   GL_NONE, 5,  8, 5,  8, 5,  8, 2, 8 },
+        { GL_RGB10_A2,                GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
+    };
+    // clang-format on
+
+    return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
+}
+
+bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
+                                           const InternalFormat &destFormat,
+                                           GLenum *outEffectiveFormat)
+{
+    constexpr GLuint umax = UINT_MAX;
+
+    // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
+    // Effective internal format coresponding to destination internal format andlinear source buffer
+    // component sizes.
+    //                                                   |   Source channel min/max sizes   |
+    //     Effective Internal Format |   Dest Format     |   R   |    G   |    B   |    A   |
+    // clang-format off
+    constexpr EffectiveInternalFormatInfo list[] = {
+        { GL_ALPHA8_EXT,             GL_ALPHA,           0, umax, 0, umax, 0, umax, 1,    8 },
+        { GL_LUMINANCE8_EXT,         GL_LUMINANCE,       1,    8, 0, umax, 0, umax, 0, umax },
+        { GL_LUMINANCE8_ALPHA8_EXT,  GL_LUMINANCE_ALPHA, 1,    8, 0, umax, 0, umax, 1,    8 },
+        { GL_RGB565,                 GL_RGB,             1,    5, 1,    6, 1,    5, 0, umax },
+        { GL_RGB8,                   GL_RGB,             6,    8, 7,    8, 6,    8, 0, umax },
+        { GL_RGBA4,                  GL_RGBA,            1,    4, 1,    4, 1,    4, 1,    4 },
+        { GL_RGB5_A1,                GL_RGBA,            5,    5, 5,    5, 5,    5, 1,    1 },
+        { GL_RGBA8,                  GL_RGBA,            5,    8, 5,    8, 5,    8, 5,    8 },
+    };
+    // clang-format on
+
+    return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
+                                    outEffectiveFormat);
+}
+
+static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
+                                       const InternalFormat &destFormat,
+                                       GLenum *outEffectiveFormat)
+{
+    if (destFormat.sized)
+    {
+        return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
+    }
+    else
+    {
+        return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
+    }
+}
+
+static bool EqualOrFirstZero(GLuint first, GLuint second)
+{
+    return first == 0 || first == second;
+}
+
+static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
+                                              const InternalFormat &framebufferFormatInfo,
+                                              GLuint readBufferHandle)
+{
+    if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
+    {
+        return false;
+    }
+
+    // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
+    // must both be signed, unsigned, or fixed point and both source and destinations
+    // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
+    // conversion between fixed and floating point.
+
+    if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
+        (framebufferFormatInfo.colorEncoding == GL_SRGB))
+    {
+        return false;
+    }
+
+    if (((textureFormatInfo.componentType == GL_INT) !=
+         (framebufferFormatInfo.componentType == GL_INT)) ||
+        ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
+         (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
+    {
+        return false;
+    }
+
+    if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+         textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
+         textureFormatInfo.componentType == GL_FLOAT) &&
+        !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+          framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
+          framebufferFormatInfo.componentType == GL_FLOAT))
+    {
+        return false;
+    }
+
+    // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
+    // The effective internal format of the source buffer is determined with the following rules
+    // applied in order:
+    //    * If the source buffer is a texture or renderbuffer that was created with a sized internal
+    //      format then the effective internal format is the source buffer's sized internal format.
+    //    * If the source buffer is a texture that was created with an unsized base internal format,
+    //      then the effective internal format is the source image array's effective internal
+    //      format, as specified by table 3.12, which is determined from the <format> and <type>
+    //      that were used when the source image array was specified by TexImage*.
+    //    * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
+    //      where Destination Internal Format matches internalformat and where the [source channel
+    //      sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
+    //      is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
+    //      FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
+    const InternalFormat *sourceEffectiveFormat = nullptr;
+    if (readBufferHandle != 0)
+    {
+        // Not the default framebuffer, therefore the read buffer must be a user-created texture or
+        // renderbuffer
+        if (framebufferFormatInfo.sized)
+        {
+            sourceEffectiveFormat = &framebufferFormatInfo;
+        }
+        else
+        {
+            // Renderbuffers cannot be created with an unsized internal format, so this must be an
+            // unsized-format texture. We can use the same table we use when creating textures to
+            // get its effective sized format.
+            sourceEffectiveFormat =
+                &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
+        }
+    }
+    else
+    {
+        // The effective internal format must be derived from the source framebuffer's channel
+        // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
+        if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
+        {
+            GLenum effectiveFormat;
+            if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
+                                           &effectiveFormat))
+            {
+                sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
+            }
+            else
+            {
+                return false;
+            }
+        }
+        else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
+        {
+            // SRGB buffers can only be copied to sized format destinations according to table 3.18
+            if (textureFormatInfo.sized &&
+                (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
+                (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
+                (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
+                (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
+            {
+                sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
+            }
+            else
+            {
+                return false;
+            }
+        }
+        else
+        {
+            UNREACHABLE();
+            return false;
+        }
+    }
+
+    if (textureFormatInfo.sized)
+    {
+        // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
+        // sized, component sizes of the source and destination formats must exactly match if the
+        // destination format exists.
+        if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
+            !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
+            !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
+            !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
+        {
+            return false;
+        }
+    }
+
+    return true;  // A conversion function exists, and no rule in the specification has precluded
+                  // conversion between these formats.
+}
+
+bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
+                                           GLenum target,
+                                           GLint level,
+                                           GLenum internalformat,
+                                           bool isSubImage,
+                                           GLint xoffset,
+                                           GLint yoffset,
+                                           GLint zoffset,
+                                           GLint x,
+                                           GLint y,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLint border)
+{
+    Format textureFormat = Format::Invalid();
+    if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+                                            xoffset, yoffset, zoffset, x, y, width, height, border,
+                                            &textureFormat))
+    {
+        return false;
+    }
+    ASSERT(textureFormat.valid() || !isSubImage);
+
+    const auto &state            = context->getGLState();
+    gl::Framebuffer *framebuffer = state.getReadFramebuffer();
+    GLuint readFramebufferID     = framebuffer->id();
+
+    if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
+
+    if (isSubImage)
+    {
+        if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
+                                               readFramebufferID))
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+    else
+    {
+        // Use format/type from the source FBO. (Might not be perfect for all cases?)
+        const InternalFormat &framebufferFormat = *source->getFormat().info;
+        const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
+        if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+
+    // If width or height is zero, it is a no-op.  Return false without setting an error.
+    return (width > 0 && height > 0);
+}
+
+bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
+                                         GLenum target,
+                                         GLint level,
+                                         GLenum internalformat,
+                                         bool isSubImage,
+                                         GLint xoffset,
+                                         GLint yoffset,
+                                         GLint zoffset,
+                                         GLint x,
+                                         GLint y,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLint border)
+{
+    if (!ValidTexture2DDestinationTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+                                                 xoffset, yoffset, zoffset, x, y, width, height,
+                                                 border);
+}
+
+bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
+                                         GLenum target,
+                                         GLint level,
+                                         GLenum internalformat,
+                                         bool isSubImage,
+                                         GLint xoffset,
+                                         GLint yoffset,
+                                         GLint zoffset,
+                                         GLint x,
+                                         GLint y,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLint border)
+{
+    if (!ValidTexture3DDestinationTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+                                                 xoffset, yoffset, zoffset, x, y, width, height,
+                                                 border);
+}
+
+bool ValidateES3TexStorageParametersBase(Context *context,
+                                         GLenum target,
+                                         GLsizei levels,
+                                         GLenum internalformat,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLsizei depth)
+{
+    if (width < 1 || height < 1 || depth < 1 || levels < 1)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    GLsizei maxDim = std::max(width, height);
+    if (target != GL_TEXTURE_2D_ARRAY)
+    {
+        maxDim = std::max(maxDim, depth);
+    }
+
+    if (levels > gl::log2(maxDim) + 1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const gl::Caps &caps = context->getCaps();
+
+    switch (target)
+    {
+        case GL_TEXTURE_2D:
+        {
+            if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+                static_cast<GLuint>(height) > caps.max2DTextureSize)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+        }
+        break;
+
+        case GL_TEXTURE_CUBE_MAP:
+        {
+            if (width != height)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+
+            if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+        }
+        break;
+
+        case GL_TEXTURE_3D:
+        {
+            if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
+                static_cast<GLuint>(height) > caps.max3DTextureSize ||
+                static_cast<GLuint>(depth) > caps.max3DTextureSize)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+        }
+        break;
+
+        case GL_TEXTURE_2D_ARRAY:
+        {
+            if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+                static_cast<GLuint>(height) > caps.max2DTextureSize ||
+                static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+        }
+        break;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+
+    gl::Texture *texture = context->getTargetTexture(target);
+    if (!texture || texture->id() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (texture->getImmutableFormat())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
+    if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    if (!formatInfo.sized)
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateES3TexStorage2DParameters(Context *context,
+                                       GLenum target,
+                                       GLsizei levels,
+                                       GLenum internalformat,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLsizei depth)
+{
+    if (!ValidTexture2DTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
+                                               height, depth);
+}
+
+bool ValidateES3TexStorage3DParameters(Context *context,
+                                       GLenum target,
+                                       GLsizei levels,
+                                       GLenum internalformat,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLsizei depth)
+{
+    if (!ValidTexture3DTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
+                                               height, depth);
+}
+
+bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+        return false;
+    }
+
+    return ValidateBeginQueryBase(context, target, id);
+}
+
+bool ValidateEndQuery(gl::Context *context, GLenum target)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+        return false;
+    }
+
+    return ValidateEndQueryBase(context, target);
+}
+
+bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+        return false;
+    }
+
+    return ValidateGetQueryivBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+        return false;
+    }
+
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateFramebufferTextureLayer(Context *context,
+                                     GLenum target,
+                                     GLenum attachment,
+                                     GLuint texture,
+                                     GLint level,
+                                     GLint layer)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (layer < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
+    {
+        return false;
+    }
+
+    const gl::Caps &caps = context->getCaps();
+    if (texture != 0)
+    {
+        gl::Texture *tex = context->getTexture(texture);
+        ASSERT(tex);
+
+        switch (tex->getTarget())
+        {
+            case GL_TEXTURE_2D_ARRAY:
+            {
+                if (level > gl::log2(caps.max2DTextureSize))
+                {
+                    context->handleError(Error(GL_INVALID_VALUE));
+                    return false;
+                }
+
+                if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
+                {
+                    context->handleError(Error(GL_INVALID_VALUE));
+                    return false;
+                }
+            }
+            break;
+
+            case GL_TEXTURE_3D:
+            {
+                if (level > gl::log2(caps.max3DTextureSize))
+                {
+                    context->handleError(Error(GL_INVALID_VALUE));
+                    return false;
+                }
+
+                if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
+                {
+                    context->handleError(Error(GL_INVALID_VALUE));
+                    return false;
+                }
+            }
+            break;
+
+            default:
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+        }
+
+        const auto &format = tex->getFormat(tex->getTarget(), level);
+        if (format.info->compressed)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateInvalidateFramebuffer(Context *context,
+                                   GLenum target,
+                                   GLsizei numAttachments,
+                                   const GLenum *attachments)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
+        return false;
+    }
+
+    bool defaultFramebuffer = false;
+
+    switch (target)
+    {
+        case GL_DRAW_FRAMEBUFFER:
+        case GL_FRAMEBUFFER:
+            defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
+            break;
+        case GL_READ_FRAMEBUFFER:
+            defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
+            return false;
+    }
+
+    return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
+                                          defaultFramebuffer);
+}
+
+bool ValidateClearBuffer(ValidationContext *context)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDrawRangeElements(Context *context,
+                               GLenum mode,
+                               GLuint start,
+                               GLuint end,
+                               GLsizei count,
+                               GLenum type,
+                               const void *indices)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+        return false;
+    }
+
+    if (end < start)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "end < start"));
+        return false;
+    }
+
+    if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
+    {
+        return false;
+    }
+
+    // Use the parameter buffer to retrieve and cache the index range.
+    const auto &params        = context->getParams<HasIndexRange>();
+    const auto &indexRangeOpt = params.getIndexRange();
+    if (!indexRangeOpt.valid())
+    {
+        // Unexpected error.
+        return false;
+    }
+
+    if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
+    {
+        // GL spec says that behavior in this case is undefined - generating an error is fine.
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return ValidateGetUniformBase(context, program, location);
+}
+
+bool ValidateReadBuffer(Context *context, GLenum src)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
+
+    if (readFBO == nullptr)
+    {
+        context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
+        return false;
+    }
+
+    if (src == GL_NONE)
+    {
+        return true;
+    }
+
+    if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
+    {
+        context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
+        return false;
+    }
+
+    if (readFBO->id() == 0)
+    {
+        if (src != GL_BACK)
+        {
+            const char *errorMsg =
+                "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
+            context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
+            return false;
+        }
+    }
+    else
+    {
+        GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
+
+        if (drawBuffer >= context->getCaps().maxDrawBuffers)
+        {
+            const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
+            context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateCompressedTexImage3D(Context *context,
+                                  GLenum target,
+                                  GLint level,
+                                  GLenum internalformat,
+                                  GLsizei width,
+                                  GLsizei height,
+                                  GLsizei depth,
+                                  GLint border,
+                                  GLsizei imageSize,
+                                  const void *data)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (!ValidTextureTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    // Validate image size
+    if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
+    if (!formatInfo.compressed)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
+        return false;
+    }
+
+    auto blockSizeOrErr =
+        formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
+    if (blockSizeOrErr.isError())
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+    if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    // 3D texture target validation
+    if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
+    {
+        context->handleError(
+            Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
+        return false;
+    }
+
+    // validateES3TexImageFormat sets the error code if there is an error
+    if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
+                                         0, width, height, depth, border, GL_NONE, GL_NONE, -1,
+                                         data))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
+                                             GLenum target,
+                                             GLint level,
+                                             GLenum internalformat,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLsizei depth,
+                                             GLint border,
+                                             GLsizei imageSize,
+                                             GLsizei dataSize,
+                                             const void *data)
+{
+    if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
+    {
+        return false;
+    }
+
+    return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
+                                        depth, border, imageSize, data);
+}
+
+bool ValidateBindVertexArray(Context *context, GLuint array)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return ValidateBindVertexArrayBase(context, array);
+}
+
+bool ValidateIsVertexArray(Context *context)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return true;
+}
+
+static bool ValidateBindBufferCommon(Context *context,
+                                     GLenum target,
+                                     GLuint index,
+                                     GLuint buffer,
+                                     GLintptr offset,
+                                     GLsizeiptr size)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (buffer != 0 && offset < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "buffer is non-zero and offset is negative."));
+        return false;
+    }
+
+    if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+        !context->isBufferGenerated(buffer))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    switch (target)
+    {
+        case GL_TRANSFORM_FEEDBACK_BUFFER:
+        {
+            if (index >= caps.maxTransformFeedbackSeparateAttributes)
+            {
+                context->handleError(Error(GL_INVALID_VALUE,
+                                           "index is greater than or equal to the number of "
+                                           "TRANSFORM_FEEDBACK_BUFFER indexed binding points."));
+                return false;
+            }
+            if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE, "offset and size must be multiple of 4."));
+                return false;
+            }
+
+            TransformFeedback *curTransformFeedback =
+                context->getGLState().getCurrentTransformFeedback();
+            if (curTransformFeedback && curTransformFeedback->isActive())
+            {
+                context->handleError(Error(GL_INVALID_OPERATION,
+                                           "target is TRANSFORM_FEEDBACK_BUFFER and transform "
+                                           "feedback is currently active."));
+                return false;
+            }
+            break;
+        }
+        case GL_UNIFORM_BUFFER:
+        {
+            if (index >= caps.maxUniformBufferBindings)
+            {
+                context->handleError(Error(GL_INVALID_VALUE,
+                                           "index is greater than or equal to the number of "
+                                           "UNIFORM_BUFFER indexed binding points."));
+                return false;
+            }
+
+            if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE,
+                          "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT."));
+                return false;
+            }
+            break;
+        }
+        case GL_ATOMIC_COUNTER_BUFFER:
+        {
+            if (context->getClientVersion() < ES_3_1)
+            {
+                context->handleError(Error(
+                    GL_INVALID_ENUM, "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1"));
+                return false;
+            }
+            if (index >= caps.maxAtomicCounterBufferBindings)
+            {
+                context->handleError(Error(GL_INVALID_VALUE,
+                                           "index is greater than or equal to the number of "
+                                           "ATOMIC_COUNTER_BUFFER indexed binding points."));
+                return false;
+            }
+            if (buffer != 0 && (offset % 4) != 0)
+            {
+                context->handleError(Error(GL_INVALID_VALUE, "offset must be a multiple of 4."));
+                return false;
+            }
+            break;
+        }
+        case GL_SHADER_STORAGE_BUFFER:
+        {
+            if (context->getClientVersion() < ES_3_1)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "SHADER_STORAGE_BUFFER is not supported in GLES3."));
+                return false;
+            }
+            if (index >= caps.maxShaderStorageBufferBindings)
+            {
+                context->handleError(Error(GL_INVALID_VALUE,
+                                           "index is greater than or equal to the number of "
+                                           "SHADER_STORAGE_BUFFER indexed binding points."));
+                return false;
+            }
+            if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
+            {
+                context->handleError(Error(
+                    GL_INVALID_VALUE,
+                    "offset must be multiple of value of SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."));
+                return false;
+            }
+            break;
+        }
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "the target is not supported."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
+{
+    return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
+}
+
+bool ValidateBindBufferRange(Context *context,
+                             GLenum target,
+                             GLuint index,
+                             GLuint buffer,
+                             GLintptr offset,
+                             GLsizeiptr size)
+{
+    if (buffer != 0 && size <= 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "buffer is non-zero and size is less than or equal to zero."));
+        return false;
+    }
+    return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
+}
+
+bool ValidateProgramBinary(Context *context,
+                           GLuint program,
+                           GLenum binaryFormat,
+                           const void *binary,
+                           GLint length)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
+}
+
+bool ValidateGetProgramBinary(Context *context,
+                              GLuint program,
+                              GLsizei bufSize,
+                              GLsizei *length,
+                              GLenum *binaryFormat,
+                              void *binary)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
+}
+
+bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+        return false;
+    }
+
+    if (GetValidProgram(context, program) == nullptr)
+    {
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+            if (value != GL_FALSE && value != GL_TRUE)
+            {
+                context->handleError(Error(
+                    GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
+                return false;
+            }
+            break;
+
+        case GL_PROGRAM_SEPARABLE:
+            if (context->getClientVersion() < ES_3_1)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "PROGRAM_SEPARABLE is not supported before GLES 3.1"));
+                return false;
+            }
+
+            if (value != GL_FALSE && value != GL_TRUE)
+            {
+                context->handleError(Error(
+                    GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateBlitFramebuffer(Context *context,
+                             GLint srcX0,
+                             GLint srcY0,
+                             GLint srcX1,
+                             GLint srcY1,
+                             GLint dstX0,
+                             GLint dstY0,
+                             GLint dstX1,
+                             GLint dstY1,
+                             GLbitfield mask,
+                             GLenum filter)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
+                                             dstX1, dstY1, mask, filter);
+}
+
+bool ValidateClearBufferiv(ValidationContext *context,
+                           GLenum buffer,
+                           GLint drawbuffer,
+                           const GLint *value)
+{
+    switch (buffer)
+    {
+        case GL_COLOR:
+            if (drawbuffer < 0 ||
+                static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            if (context->getExtensions().webglCompatibility)
+            {
+                constexpr GLenum validComponentTypes[] = {GL_INT};
+                if (ValidateWebGLFramebufferAttachmentClearType(
+                        context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
+                {
+                    return false;
+                }
+            }
+            break;
+
+        case GL_STENCIL:
+            if (drawbuffer != 0)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    return ValidateClearBuffer(context);
+}
+
+bool ValidateClearBufferuiv(ValidationContext *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLuint *value)
+{
+    switch (buffer)
+    {
+        case GL_COLOR:
+            if (drawbuffer < 0 ||
+                static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            if (context->getExtensions().webglCompatibility)
+            {
+                constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
+                if (ValidateWebGLFramebufferAttachmentClearType(
+                        context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
+                {
+                    return false;
+                }
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    return ValidateClearBuffer(context);
+}
+
+bool ValidateClearBufferfv(ValidationContext *context,
+                           GLenum buffer,
+                           GLint drawbuffer,
+                           const GLfloat *value)
+{
+    switch (buffer)
+    {
+        case GL_COLOR:
+            if (drawbuffer < 0 ||
+                static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            if (context->getExtensions().webglCompatibility)
+            {
+                constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
+                                                          GL_SIGNED_NORMALIZED};
+                if (ValidateWebGLFramebufferAttachmentClearType(
+                        context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
+                {
+                    return false;
+                }
+            }
+            break;
+
+        case GL_DEPTH:
+            if (drawbuffer != 0)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    return ValidateClearBuffer(context);
+}
+
+bool ValidateClearBufferfi(ValidationContext *context,
+                           GLenum buffer,
+                           GLint drawbuffer,
+                           GLfloat depth,
+                           GLint stencil)
+{
+    switch (buffer)
+    {
+        case GL_DEPTH_STENCIL:
+            if (drawbuffer != 0)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    return ValidateClearBuffer(context);
+}
+
+bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+        return false;
+    }
+
+    return ValidateDrawBuffersBase(context, n, bufs);
+}
+
+bool ValidateCopyTexSubImage3D(Context *context,
+                               GLenum target,
+                               GLint level,
+                               GLint xoffset,
+                               GLint yoffset,
+                               GLint zoffset,
+                               GLint x,
+                               GLint y,
+                               GLsizei width,
+                               GLsizei height)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
+                                               yoffset, zoffset, x, y, width, height, 0);
+}
+
+bool ValidateTexImage3D(Context *context,
+                        GLenum target,
+                        GLint level,
+                        GLint internalformat,
+                        GLsizei width,
+                        GLsizei height,
+                        GLsizei depth,
+                        GLint border,
+                        GLenum format,
+                        GLenum type,
+                        const void *pixels)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
+                                           0, 0, width, height, depth, border, format, type, -1,
+                                           pixels);
+}
+
+bool ValidateTexImage3DRobustANGLE(Context *context,
+                                   GLenum target,
+                                   GLint level,
+                                   GLint internalformat,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   GLsizei depth,
+                                   GLint border,
+                                   GLenum format,
+                                   GLenum type,
+                                   GLsizei bufSize,
+                                   const void *pixels)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
+                                           0, 0, width, height, depth, border, format, type,
+                                           bufSize, pixels);
+}
+
+bool ValidateTexSubImage3D(Context *context,
+                           GLenum target,
+                           GLint level,
+                           GLint xoffset,
+                           GLint yoffset,
+                           GLint zoffset,
+                           GLsizei width,
+                           GLsizei height,
+                           GLsizei depth,
+                           GLenum format,
+                           GLenum type,
+                           const void *pixels)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
+                                           yoffset, zoffset, width, height, depth, 0, format, type,
+                                           -1, pixels);
+}
+
+bool ValidateTexSubImage3DRobustANGLE(Context *context,
+                                      GLenum target,
+                                      GLint level,
+                                      GLint xoffset,
+                                      GLint yoffset,
+                                      GLint zoffset,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLsizei depth,
+                                      GLenum format,
+                                      GLenum type,
+                                      GLsizei bufSize,
+                                      const void *pixels)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
+                                           yoffset, zoffset, width, height, depth, 0, format, type,
+                                           bufSize, pixels);
+}
+
+bool ValidateCompressedTexSubImage3D(Context *context,
+                                     GLenum target,
+                                     GLint level,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLint zoffset,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLsizei depth,
+                                     GLenum format,
+                                     GLsizei imageSize,
+                                     const void *data)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
+    if (!formatInfo.compressed)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
+        return false;
+    }
+
+    auto blockSizeOrErr =
+        formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
+    if (blockSizeOrErr.isError())
+    {
+        context->handleError(blockSizeOrErr.getError());
+        return false;
+    }
+    if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    if (!data)
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
+                                           width, height, depth, 0, format, GL_NONE, -1, data);
+}
+bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
+                                                GLenum target,
+                                                GLint level,
+                                                GLint xoffset,
+                                                GLint yoffset,
+                                                GLint zoffset,
+                                                GLsizei width,
+                                                GLsizei height,
+                                                GLsizei depth,
+                                                GLenum format,
+                                                GLsizei imageSize,
+                                                GLsizei dataSize,
+                                                const void *data)
+{
+    if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
+    {
+        return false;
+    }
+
+    return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
+                                           height, depth, format, imageSize, data);
+}
+
+bool ValidateGenQueries(Context *context, GLint n, GLuint *)
+{
+    return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
+{
+    return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
+{
+    return ValidateGenOrDeleteCountES3(context, count);
+}
+
+bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
+{
+    return ValidateGenOrDeleteCountES3(context, count);
+}
+
+bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
+{
+    return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
+{
+    if (!ValidateGenOrDeleteES3(context, n))
+    {
+        return false;
+    }
+    for (GLint i = 0; i < n; ++i)
+    {
+        auto *transformFeedback = context->getTransformFeedback(ids[i]);
+        if (transformFeedback != nullptr && transformFeedback->isActive())
+        {
+            // ES 3.0.4 section 2.15.1 page 86
+            context->handleError(
+                Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
+{
+    return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
+{
+    return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateGenOrDeleteES3(Context *context, GLint n)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+        return false;
+    }
+    return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+        return false;
+    }
+    if (count < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+        return false;
+    }
+    switch (primitiveMode)
+    {
+        case GL_TRIANGLES:
+        case GL_LINES:
+        case GL_POINTS:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
+            return false;
+    }
+
+    TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+    ASSERT(transformFeedback != nullptr);
+
+    if (transformFeedback->isActive())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
+{
+    return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
+}
+
+bool ValidateGetBufferPointervRobustANGLE(Context *context,
+                                          GLenum target,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          void **params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateUnmapBuffer(Context *context, GLenum target)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    return ValidateUnmapBufferBase(context, target);
+}
+
+bool ValidateMapBufferRange(Context *context,
+                            GLenum target,
+                            GLintptr offset,
+                            GLsizeiptr length,
+                            GLbitfield access)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+        return false;
+    }
+
+    return ValidateMapBufferRangeBase(context, target, offset, length, access);
+}
+
+bool ValidateFlushMappedBufferRange(Context *context,
+                                    GLenum target,
+                                    GLintptr offset,
+                                    GLsizeiptr length)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+        return false;
+    }
+
+    return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
+}
+
+bool ValidateIndexedStateQuery(ValidationContext *context,
+                               GLenum pname,
+                               GLuint index,
+                               GLsizei *length)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    GLenum nativeType;
+    unsigned int numParams;
+    if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    switch (pname)
+    {
+        case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+        case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+        case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+            if (index >= caps.maxTransformFeedbackSeparateAttributes)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        case GL_UNIFORM_BUFFER_START:
+        case GL_UNIFORM_BUFFER_SIZE:
+        case GL_UNIFORM_BUFFER_BINDING:
+            if (index >= caps.maxUniformBufferBindings)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+        case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+            if (index >= 3u)
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return false;
+            }
+            break;
+
+        case GL_ATOMIC_COUNTER_BUFFER_START:
+        case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+        case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+            if (context->getClientVersion() < ES_3_1)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM,
+                          "Atomic Counter buffers are not supported in this version of GL"));
+                return false;
+            }
+            if (index >= caps.maxAtomicCounterBufferBindings)
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE,
+                          "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING"));
+                return false;
+            }
+            break;
+
+        case GL_SHADER_STORAGE_BUFFER_START:
+        case GL_SHADER_STORAGE_BUFFER_SIZE:
+        case GL_SHADER_STORAGE_BUFFER_BINDING:
+            if (context->getClientVersion() < ES_3_1)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM,
+                          "Shader storage buffers are not supported in this version of GL"));
+                return false;
+            }
+            if (index >= caps.maxShaderStorageBufferBindings)
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE,
+                          "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING"));
+                return false;
+            }
+            break;
+
+        case GL_VERTEX_BINDING_BUFFER:
+        case GL_VERTEX_BINDING_DIVISOR:
+        case GL_VERTEX_BINDING_OFFSET:
+        case GL_VERTEX_BINDING_STRIDE:
+            if (context->getClientVersion() < ES_3_1)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM,
+                          "Vertex Attrib Bindings are not supported in this version of GL"));
+                return false;
+            }
+            if (index >= caps.maxVertexAttribBindings)
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE,
+                          "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
+                return false;
+            }
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM));
+            return false;
+    }
+
+    if (length)
+    {
+        *length = 1;
+    }
+
+    return true;
+}
+
+bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
+{
+    if (context->getClientVersion() < ES_3_0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
+        return false;
+    }
+    return ValidateIndexedStateQuery(context, target, index, nullptr);
+}
+
+bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
+                                      GLenum target,
+                                      GLuint index,
+                                      GLsizei bufSize,
+                                      GLsizei *length,
+                                      GLint *data)
+{
+    if (context->getClientVersion() < ES_3_0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateIndexedStateQuery(context, target, index, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
+{
+    if (context->getClientVersion() < ES_3_0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
+        return false;
+    }
+    return ValidateIndexedStateQuery(context, target, index, nullptr);
+}
+
+bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
+                                        GLenum target,
+                                        GLuint index,
+                                        GLsizei bufSize,
+                                        GLsizei *length,
+                                        GLint64 *data)
+{
+    if (context->getClientVersion() < ES_3_0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateIndexedStateQuery(context, target, index, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateCopyBufferSubData(ValidationContext *context,
+                               GLenum readTarget,
+                               GLenum writeTarget,
+                               GLintptr readOffset,
+                               GLintptr writeOffset,
+                               GLsizeiptr size)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
+        return false;
+    }
+
+    if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
+        return false;
+    }
+
+    Buffer *readBuffer  = context->getGLState().getTargetBuffer(readTarget);
+    Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
+
+    if (!readBuffer || !writeBuffer)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
+        return false;
+    }
+
+    // Verify that readBuffer and writeBuffer are not currently mapped
+    if (readBuffer->isMapped() || writeBuffer->isMapped())
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
+        return false;
+    }
+
+    CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
+    CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
+    CheckedNumeric<GLintptr> checkedSize(size);
+
+    auto checkedReadSum  = checkedReadOffset + checkedSize;
+    auto checkedWriteSum = checkedWriteOffset + checkedSize;
+
+    if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
+        !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
+        !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
+        return false;
+    }
+
+    if (readOffset < 0 || writeOffset < 0 || size < 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
+        return false;
+    }
+
+    if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
+        checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
+        return false;
+    }
+
+    if (readBuffer == writeBuffer)
+    {
+        auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
+        if (!checkedOffsetDiff.IsValid())
+        {
+            // This shold not be possible.
+            UNREACHABLE();
+            context->handleError(
+                Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
+            return false;
+        }
+
+        if (checkedOffsetDiff.ValueOrDie() < size)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
+        return false;
+    }
+
+    switch (name)
+    {
+        case GL_EXTENSIONS:
+            if (index >= context->getExtensionStringCount())
+            {
+                context->handleError(Error(
+                    GL_INVALID_VALUE, "index must be less than the number of extension strings."));
+                return false;
+            }
+            break;
+
+        case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+            if (!context->getExtensions().requestExtension)
+            {
+                context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
+                return false;
+            }
+            if (index >= context->getRequestableExtensionStringCount())
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE,
+                          "index must be less than the number of requestable extension strings."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
+                                            GLenum target,
+                                            GLsizei samples,
+                                            GLenum internalformat,
+                                            GLsizei width,
+                                            GLsizei height)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
+                                                   height))
+    {
+        return false;
+    }
+
+    // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
+    // format if samples is greater than zero.
+    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
+    if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
+        samples > 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION));
+        return false;
+    }
+
+    // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
+    const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+    if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "Samples must not be greater than maximum supported value for the format."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateVertexAttribIPointer(ValidationContext *context,
+                                  GLuint index,
+                                  GLint size,
+                                  GLenum type,
+                                  GLsizei stride,
+                                  const void *pointer)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "VertexAttribIPointer requires OpenGL ES 3.0 or higher."));
+        return false;
+    }
+
+    if (!ValidateVertexFormatBase(context, index, size, type, true))
+    {
+        return false;
+    }
+
+    if (stride < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (context->getClientVersion() >= ES_3_1)
+    {
+        if (stride > caps.maxVertexAttribStride)
+        {
+            context->handleError(
+                Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
+            return false;
+        }
+
+        // [OpenGL ES 3.1] Section 10.3.1 page 245:
+        // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
+        // validation should be inherited.
+        if (index >= caps.maxVertexAttribBindings)
+        {
+            context->handleError(
+                Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
+            return false;
+        }
+    }
+
+    // [OpenGL ES 3.0.2] Section 2.8 page 24:
+    // An INVALID_OPERATION error is generated when a non-zero vertex array object
+    // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+    // and the pointer argument is not NULL.
+    if (context->getGLState().getVertexArrayId() != 0 &&
+        context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "Client data cannot be used with a non-default vertex array object."));
+        return false;
+    }
+
+    if (context->getExtensions().webglCompatibility)
+    {
+        if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateGetSynciv(Context *context,
+                       GLsync sync,
+                       GLenum pname,
+                       GLsizei bufSize,
+                       GLsizei *length,
+                       GLint *values)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "GetSynciv requires OpenGL ES 3.0 or higher."));
+        return false;
+    }
+
+    if (bufSize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+        return false;
+    }
+
+    FenceSync *fenceSync = context->getFenceSync(sync);
+    if (!fenceSync)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid sync object."));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_OBJECT_TYPE:
+        case GL_SYNC_CONDITION:
+        case GL_SYNC_FLAGS:
+        case GL_SYNC_STATUS:
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
+            return false;
+    }
+
+    return true;
+}
+
+bool ValidateDrawElementsInstanced(ValidationContext *context,
+                                   GLenum mode,
+                                   GLsizei count,
+                                   GLenum type,
+                                   const void *indices,
+                                   GLsizei instanceCount)
+{
+    if (context->getClientMajorVersion() < 3)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Requires a GLES 3.0 or higher context."));
+        return false;
+    }
+
+    return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/validationES3.h b/src/third_party/angle/src/libANGLE/validationES3.h
new file mode 100644
index 0000000..35836b7
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationES3.h
@@ -0,0 +1,432 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES3.h: Validation functions for OpenGL ES 3.0 entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES3_H_
+#define LIBANGLE_VALIDATION_ES3_H_
+
+#include <GLES3/gl3.h>
+
+namespace gl
+{
+class Context;
+struct IndexRange;
+class ValidationContext;
+
+bool ValidateES3TexImageParametersBase(ValidationContext *context,
+                                       GLenum target,
+                                       GLint level,
+                                       GLenum internalformat,
+                                       bool isCompressed,
+                                       bool isSubImage,
+                                       GLint xoffset,
+                                       GLint yoffset,
+                                       GLint zoffset,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLsizei depth,
+                                       GLint border,
+                                       GLenum format,
+                                       GLenum type,
+                                       GLsizei imageSize,
+                                       const void *pixels);
+
+bool ValidateES3TexStorageParameters(Context *context,
+                                     GLenum target,
+                                     GLsizei levels,
+                                     GLenum internalformat,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLsizei depth);
+
+bool ValidateES3TexImage2DParameters(Context *context,
+                                     GLenum target,
+                                     GLint level,
+                                     GLenum internalformat,
+                                     bool isCompressed,
+                                     bool isSubImage,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLint zoffset,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLsizei depth,
+                                     GLint border,
+                                     GLenum format,
+                                     GLenum type,
+                                     GLsizei imageSize,
+                                     const void *pixels);
+
+bool ValidateES3TexImage3DParameters(Context *context,
+                                     GLenum target,
+                                     GLint level,
+                                     GLenum internalformat,
+                                     bool isCompressed,
+                                     bool isSubImage,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLint zoffset,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLsizei depth,
+                                     GLint border,
+                                     GLenum format,
+                                     GLenum type,
+                                     GLsizei bufSize,
+                                     const void *pixels);
+
+bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
+                                           GLenum target,
+                                           GLint level,
+                                           GLenum internalformat,
+                                           bool isSubImage,
+                                           GLint xoffset,
+                                           GLint yoffset,
+                                           GLint zoffset,
+                                           GLint x,
+                                           GLint y,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLint border);
+
+bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
+                                         GLenum target,
+                                         GLint level,
+                                         GLenum internalformat,
+                                         bool isSubImage,
+                                         GLint xoffset,
+                                         GLint yoffset,
+                                         GLint zoffset,
+                                         GLint x,
+                                         GLint y,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLint border);
+
+bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
+                                         GLenum target,
+                                         GLint level,
+                                         GLenum internalformat,
+                                         bool isSubImage,
+                                         GLint xoffset,
+                                         GLint yoffset,
+                                         GLint zoffset,
+                                         GLint x,
+                                         GLint y,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLint border);
+
+bool ValidateES3TexStorageParametersBase(Context *context,
+                                         GLenum target,
+                                         GLsizei levels,
+                                         GLenum internalformat,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLsizei depth);
+
+bool ValidateES3TexStorage2DParameters(Context *context,
+                                       GLenum target,
+                                       GLsizei levels,
+                                       GLenum internalformat,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLsizei depth);
+
+bool ValidateES3TexStorage3DParameters(Context *context,
+                                       GLenum target,
+                                       GLsizei levels,
+                                       GLenum internalformat,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLsizei depth);
+
+bool ValidateBeginQuery(Context *context, GLenum target, GLuint id);
+
+bool ValidateEndQuery(Context *context, GLenum target);
+
+bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params);
+
+bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params);
+
+bool ValidateFramebufferTextureLayer(Context *context,
+                                     GLenum target,
+                                     GLenum attachment,
+                                     GLuint texture,
+                                     GLint level,
+                                     GLint layer);
+
+bool ValidateInvalidateFramebuffer(Context *context,
+                                   GLenum target,
+                                   GLsizei numAttachments,
+                                   const GLenum *attachments);
+
+bool ValidateClearBuffer(ValidationContext *context);
+
+bool ValidateDrawRangeElements(Context *context,
+                               GLenum mode,
+                               GLuint start,
+                               GLuint end,
+                               GLsizei count,
+                               GLenum type,
+                               const void *indices);
+
+bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params);
+
+bool ValidateReadBuffer(Context *context, GLenum mode);
+
+bool ValidateCompressedTexImage3D(Context *context,
+                                  GLenum target,
+                                  GLint level,
+                                  GLenum internalformat,
+                                  GLsizei width,
+                                  GLsizei height,
+                                  GLsizei depth,
+                                  GLint border,
+                                  GLsizei imageSize,
+                                  const void *data);
+bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
+                                             GLenum target,
+                                             GLint level,
+                                             GLenum internalformat,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLsizei depth,
+                                             GLint border,
+                                             GLsizei imageSize,
+                                             GLsizei dataSize,
+                                             const void *data);
+
+bool ValidateBindVertexArray(Context *context, GLuint array);
+bool ValidateIsVertexArray(Context *context);
+
+bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer);
+bool ValidateBindBufferRange(Context *context,
+                             GLenum target,
+                             GLuint index,
+                             GLuint buffer,
+                             GLintptr offset,
+                             GLsizeiptr size);
+
+bool ValidateProgramBinary(Context *context,
+                           GLuint program,
+                           GLenum binaryFormat,
+                           const void *binary,
+                           GLint length);
+bool ValidateGetProgramBinary(Context *context,
+                              GLuint program,
+                              GLsizei bufSize,
+                              GLsizei *length,
+                              GLenum *binaryFormat,
+                              void *binary);
+bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value);
+bool ValidateBlitFramebuffer(Context *context,
+                             GLint srcX0,
+                             GLint srcY0,
+                             GLint srcX1,
+                             GLint srcY1,
+                             GLint dstX0,
+                             GLint dstY0,
+                             GLint dstX1,
+                             GLint dstY1,
+                             GLbitfield mask,
+                             GLenum filter);
+bool ValidateClearBufferiv(ValidationContext *context,
+                           GLenum buffer,
+                           GLint drawbuffer,
+                           const GLint *value);
+bool ValidateClearBufferuiv(ValidationContext *context,
+                            GLenum buffer,
+                            GLint drawbuffer,
+                            const GLuint *value);
+bool ValidateClearBufferfv(ValidationContext *context,
+                           GLenum buffer,
+                           GLint drawbuffer,
+                           const GLfloat *value);
+bool ValidateClearBufferfi(ValidationContext *context,
+                           GLenum buffer,
+                           GLint drawbuffer,
+                           GLfloat depth,
+                           GLint stencil);
+bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs);
+bool ValidateCopyTexSubImage3D(Context *context,
+                               GLenum target,
+                               GLint level,
+                               GLint xoffset,
+                               GLint yoffset,
+                               GLint zoffset,
+                               GLint x,
+                               GLint y,
+                               GLsizei width,
+                               GLsizei height);
+bool ValidateTexImage3D(Context *context,
+                        GLenum target,
+                        GLint level,
+                        GLint internalformat,
+                        GLsizei width,
+                        GLsizei height,
+                        GLsizei depth,
+                        GLint border,
+                        GLenum format,
+                        GLenum type,
+                        const void *pixels);
+bool ValidateTexImage3DRobustANGLE(Context *context,
+                                   GLenum target,
+                                   GLint level,
+                                   GLint internalformat,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   GLsizei depth,
+                                   GLint border,
+                                   GLenum format,
+                                   GLenum type,
+                                   GLsizei bufSize,
+                                   const void *pixels);
+bool ValidateTexSubImage3D(Context *context,
+                           GLenum target,
+                           GLint level,
+                           GLint xoffset,
+                           GLint yoffset,
+                           GLint zoffset,
+                           GLsizei width,
+                           GLsizei height,
+                           GLsizei depth,
+                           GLenum format,
+                           GLenum type,
+                           const void *pixels);
+bool ValidateTexSubImage3DRobustANGLE(Context *context,
+                                      GLenum target,
+                                      GLint level,
+                                      GLint xoffset,
+                                      GLint yoffset,
+                                      GLint zoffset,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLsizei depth,
+                                      GLenum format,
+                                      GLenum type,
+                                      GLsizei bufSize,
+                                      const void *pixels);
+bool ValidateCompressedTexSubImage3D(Context *context,
+                                     GLenum target,
+                                     GLint level,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLint zoffset,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLsizei depth,
+                                     GLenum format,
+                                     GLsizei imageSize,
+                                     const void *data);
+bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
+                                                GLenum target,
+                                                GLint level,
+                                                GLint xoffset,
+                                                GLint yoffset,
+                                                GLint zoffset,
+                                                GLsizei width,
+                                                GLsizei height,
+                                                GLsizei depth,
+                                                GLenum format,
+                                                GLsizei imageSize,
+                                                GLsizei dataSize,
+                                                const void *data);
+
+bool ValidateGenQueries(Context *context, GLint n, GLuint *ids);
+bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *ids);
+bool ValidateGenSamplers(Context *context, GLint count, GLuint *samplers);
+bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *samplers);
+bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *ids);
+bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids);
+bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *arrays);
+bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *arrays);
+
+bool ValidateGenOrDeleteES3(Context *context, GLint n);
+bool ValidateGenOrDeleteCountES3(Context *context, GLint count);
+
+bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode);
+
+bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params);
+bool ValidateGetBufferPointervRobustANGLE(Context *context,
+                                          GLenum target,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          void **params);
+bool ValidateUnmapBuffer(Context *context, GLenum target);
+bool ValidateMapBufferRange(Context *context,
+                            GLenum target,
+                            GLintptr offset,
+                            GLsizeiptr length,
+                            GLbitfield access);
+bool ValidateFlushMappedBufferRange(Context *context,
+                                    GLenum target,
+                                    GLintptr offset,
+                                    GLsizeiptr length);
+
+bool ValidateIndexedStateQuery(ValidationContext *context,
+                               GLenum pname,
+                               GLuint index,
+                               GLsizei *length);
+bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data);
+bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
+                                      GLenum target,
+                                      GLuint index,
+                                      GLsizei bufSize,
+                                      GLsizei *length,
+                                      GLint *data);
+bool ValidateGetInteger64i_v(ValidationContext *context,
+                             GLenum target,
+                             GLuint index,
+                             GLint64 *data);
+bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
+                                        GLenum target,
+                                        GLuint index,
+                                        GLsizei bufSize,
+                                        GLsizei *length,
+                                        GLint64 *data);
+
+bool ValidateCopyBufferSubData(ValidationContext *context,
+                               GLenum readTarget,
+                               GLenum writeTarget,
+                               GLintptr readOffset,
+                               GLintptr writeOffset,
+                               GLsizeiptr size);
+
+bool ValidateGetStringi(Context *context, GLenum name, GLuint index);
+bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
+                                            GLenum target,
+                                            GLsizei samples,
+                                            GLenum internalformat,
+                                            GLsizei width,
+                                            GLsizei height);
+
+bool ValidateVertexAttribIPointer(ValidationContext *context,
+                                  GLuint index,
+                                  GLint size,
+                                  GLenum type,
+                                  GLsizei stride,
+                                  const void *pointer);
+
+bool ValidateGetSynciv(Context *context,
+                       GLsync sync,
+                       GLenum pname,
+                       GLsizei bufSize,
+                       GLsizei *length,
+                       GLint *values);
+
+bool ValidateDrawElementsInstanced(ValidationContext *context,
+                                   GLenum mode,
+                                   GLsizei count,
+                                   GLenum type,
+                                   const void *indices,
+                                   GLsizei instanceCount);
+
+}  // namespace gl
+
+#endif  // LIBANGLE_VALIDATION_ES3_H_
diff --git a/src/third_party/angle/src/libANGLE/validationES31.cpp b/src/third_party/angle/src/libANGLE/validationES31.cpp
new file mode 100644
index 0000000..6debd4f
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationES31.cpp
@@ -0,0 +1,827 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// validationES31.cpp: Validation functions for OpenGL ES 3.1 entry point parameters
+
+#include "libANGLE/validationES31.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES3.h"
+
+#include "common/utilities.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+namespace
+{
+
+bool ValidateNamedProgramInterface(GLenum programInterface)
+{
+    switch (programInterface)
+    {
+        case GL_UNIFORM:
+        case GL_UNIFORM_BLOCK:
+        case GL_PROGRAM_INPUT:
+        case GL_PROGRAM_OUTPUT:
+        case GL_TRANSFORM_FEEDBACK_VARYING:
+        case GL_BUFFER_VARIABLE:
+        case GL_SHADER_STORAGE_BLOCK:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool ValidateProgramResourceIndex(const Program *programObject,
+                                  GLenum programInterface,
+                                  GLuint index)
+{
+    switch (programInterface)
+    {
+        case GL_PROGRAM_INPUT:
+            return (index < static_cast<GLuint>(programObject->getActiveAttributeCount()));
+
+        case GL_PROGRAM_OUTPUT:
+            return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
+
+        // TODO(Jie): more interfaces.
+        case GL_UNIFORM:
+        case GL_UNIFORM_BLOCK:
+        case GL_TRANSFORM_FEEDBACK_VARYING:
+        case GL_BUFFER_VARIABLE:
+        case GL_SHADER_STORAGE_BLOCK:
+            UNIMPLEMENTED();
+            return false;
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+}  // anonymous namespace
+
+bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
+        return false;
+    }
+
+    if (!ValidateIndexedStateQuery(context, target, index, nullptr))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetBooleani_vRobustANGLE(Context *context,
+                                      GLenum target,
+                                      GLuint index,
+                                      GLsizei bufSize,
+                                      GLsizei *length,
+                                      GLboolean *data)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateIndexedStateQuery(context, target, index, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
+        return false;
+    }
+
+    // Here the third parameter 1 is only to pass the count validation.
+    if (!ValidateDrawBase(context, mode, 1))
+    {
+        return false;
+    }
+
+    const State &state = context->getGLState();
+
+    // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
+    // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
+    if (!state.getVertexArrayId())
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to VERTEX_ARRAY_BINDING"));
+        return false;
+    }
+
+    gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
+    if (!drawIndirectBuffer)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to DRAW_INDIRECT_BUFFER"));
+        return false;
+    }
+
+    // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
+    // machine units, of uint.
+    GLint64 offset = reinterpret_cast<GLint64>(indirect);
+    if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE,
+                  "indirect is not a multiple of the size, in basic machine units, of uint"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
+{
+    const State &state                          = context->getGLState();
+    gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+    if (curTransformFeedback && curTransformFeedback->isActive() &&
+        !curTransformFeedback->isPaused())
+    {
+        // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "transform feedback is active and not paused."));
+        return false;
+    }
+
+    if (!ValidateDrawIndirectBase(context, mode, indirect))
+        return false;
+
+    gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
+    CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
+    // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
+    // which's size is 4 * sizeof(uint).
+    auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
+    if (!checkedSum.IsValid() ||
+        checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "the  command  would source data beyond the end of the buffer object."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
+{
+    if (!ValidateDrawElementsBase(context, type))
+        return false;
+
+    const State &state             = context->getGLState();
+    const VertexArray *vao         = state.getVertexArray();
+    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+    if (!elementArrayBuffer)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to ELEMENT_ARRAY_BUFFER"));
+        return false;
+    }
+
+    if (!ValidateDrawIndirectBase(context, mode, indirect))
+        return false;
+
+    gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
+    CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
+    // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
+    // which's size is 5 * sizeof(uint).
+    auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
+    if (!checkedSum.IsValid() ||
+        checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "the  command  would source data beyond the end of the buffer object."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetTexLevelParameterBase(Context *context,
+                                      GLenum target,
+                                      GLint level,
+                                      GLenum pname,
+                                      GLsizei *length)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
+        return false;
+    }
+
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (!ValidTexLevelDestinationTarget(context, target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
+        return false;
+    }
+
+    if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
+        nullptr)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
+        return false;
+    }
+
+    if (!ValidMipLevel(context, target, level))
+    {
+        context->handleError(Error(GL_INVALID_VALUE));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_TEXTURE_RED_TYPE:
+        case GL_TEXTURE_GREEN_TYPE:
+        case GL_TEXTURE_BLUE_TYPE:
+        case GL_TEXTURE_ALPHA_TYPE:
+        case GL_TEXTURE_DEPTH_TYPE:
+            break;
+        case GL_TEXTURE_RED_SIZE:
+        case GL_TEXTURE_GREEN_SIZE:
+        case GL_TEXTURE_BLUE_SIZE:
+        case GL_TEXTURE_ALPHA_SIZE:
+        case GL_TEXTURE_DEPTH_SIZE:
+        case GL_TEXTURE_STENCIL_SIZE:
+        case GL_TEXTURE_SHARED_SIZE:
+            break;
+        case GL_TEXTURE_INTERNAL_FORMAT:
+        case GL_TEXTURE_WIDTH:
+        case GL_TEXTURE_HEIGHT:
+        case GL_TEXTURE_DEPTH:
+            break;
+        case GL_TEXTURE_SAMPLES:
+        case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
+            break;
+        case GL_TEXTURE_COMPRESSED:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    if (length)
+    {
+        *length = 1;
+    }
+    return true;
+}
+
+bool ValidateGetTexLevelParameterfv(Context *context,
+                                    GLenum target,
+                                    GLint level,
+                                    GLenum pname,
+                                    GLfloat *params)
+{
+    return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
+}
+
+bool ValidateGetTexLevelParameteriv(Context *context,
+                                    GLenum target,
+                                    GLint level,
+                                    GLenum pname,
+                                    GLint *params)
+{
+    return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
+}
+
+bool ValidateTexStorage2DMultiSample(Context *context,
+                                     GLenum target,
+                                     GLsizei samples,
+                                     GLint internalFormat,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLboolean fixedSampleLocations)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    if (target != GL_TEXTURE_2D_MULTISAMPLE)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Target must be TEXTURE_2D_MULTISAMPLE."));
+        return false;
+    }
+
+    if (width < 1 || height < 1)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Width and height must be positive."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+        static_cast<GLuint>(height) > caps.max2DTextureSize)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE,
+                  "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE."));
+        return false;
+    }
+
+    if (samples == 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Samples may not be zero."));
+        return false;
+    }
+
+    const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
+    if (!formatCaps.renderable)
+    {
+        context->handleError(
+            Error(GL_INVALID_ENUM,
+                  "SizedInternalformat must be color-renderable, depth-renderable, "
+                  "or stencil-renderable."));
+        return false;
+    }
+
+    // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
+    // is one of the unsized base internalformats listed in table 8.11.
+    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
+    if (formatInfo.internalFormat == GL_NONE)
+    {
+        context->handleError(
+            Error(GL_INVALID_ENUM,
+                  "Internalformat is one of the unsupported unsized base internalformats."));
+        return false;
+    }
+
+    if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "Samples must not be greater than maximum supported value for the format."));
+        return false;
+    }
+
+    Texture *texture = context->getTargetTexture(target);
+    if (!texture || texture->id() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Zero is bound to target."));
+        return false;
+    }
+
+    if (texture->getImmutableFormat())
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION,
+                  "The value of TEXTURE_IMMUTABLE_FORMAT for the texture "
+                  "currently bound to target on the active texture unit is true."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    if (pname != GL_SAMPLE_POSITION)
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Pname must be SAMPLE_POSITION."));
+        return false;
+    }
+
+    GLint maxSamples = context->getCaps().maxSamples;
+    if (index >= static_cast<GLuint>(maxSamples))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "Index must be less than the value of SAMPLES."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidationFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    if (!ValidFramebufferTarget(target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target."));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+        {
+            GLint maxWidth = context->getCaps().maxFramebufferWidth;
+            if (param < 0 || param > maxWidth)
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE,
+                          "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH."));
+                return false;
+            }
+            break;
+        }
+        case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+        {
+            GLint maxHeight = context->getCaps().maxFramebufferHeight;
+            if (param < 0 || param > maxHeight)
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE,
+                          "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT."));
+                return false;
+            }
+            break;
+        }
+        case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+        {
+            GLint maxSamples = context->getCaps().maxFramebufferSamples;
+            if (param < 0 || param > maxSamples)
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE,
+                          "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES."));
+                return false;
+            }
+            break;
+        }
+        case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+        {
+            break;
+        }
+        default:
+        {
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
+            return false;
+        }
+    }
+
+    const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+    if (framebuffer->id() == 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Default framebuffer is bound to target."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidationGetFramebufferParameteri(Context *context,
+                                        GLenum target,
+                                        GLenum pname,
+                                        GLint *params)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    if (!ValidFramebufferTarget(target))
+    {
+        context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target."));
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+        case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+        case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+        case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+            break;
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
+            return false;
+    }
+
+    const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (framebuffer->id() == 0)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "Default framebuffer is bound to target."));
+        return false;
+    }
+    return true;
+}
+
+bool ValidateGetProgramResourceIndex(Context *context,
+                                     GLuint program,
+                                     GLenum programInterface,
+                                     const GLchar *name)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES 3.1."));
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+    if (programObject == nullptr)
+    {
+        return false;
+    }
+
+    if (!ValidateNamedProgramInterface(programInterface))
+    {
+        context->handleError(
+            Error(GL_INVALID_ENUM, "Invalid program interface: 0x%X", programInterface));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateBindVertexBuffer(ValidationContext *context,
+                              GLuint bindingIndex,
+                              GLuint buffer,
+                              GLintptr offset,
+                              GLsizei stride)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    if (!context->isBufferGenerated(buffer))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Buffer is not generated."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (bindingIndex >= caps.maxVertexAttribBindings)
+    {
+        context->handleError(Error(
+            GL_INVALID_VALUE, "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
+        return false;
+    }
+
+    if (offset < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "offset cannot be negative."));
+        return false;
+    }
+
+    if (stride < 0 || stride > caps.maxVertexAttribStride)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE."));
+        return false;
+    }
+
+    // [OpenGL ES 3.1] Section 10.3.1 page 244:
+    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+    if (context->getGLState().getVertexArrayId() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array buffer is bound."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (bindingIndex >= caps.maxVertexAttribBindings)
+    {
+        context->handleError(Error(
+            GL_INVALID_VALUE, "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
+        return false;
+    }
+
+    // [OpenGL ES 3.1] Section 10.3.1 page 243:
+    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+    if (context->getGLState().getVertexArrayId() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array object is bound."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateVertexAttribFormat(ValidationContext *context,
+                                GLuint attribIndex,
+                                GLint size,
+                                GLenum type,
+                                GLuint relativeOffset,
+                                GLboolean pureInteger)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE,
+                  "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET."));
+        return false;
+    }
+
+    // [OpenGL ES 3.1] Section 10.3.1 page 243:
+    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+    if (context->getGLState().getVertexArrayId() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array object is bound."));
+        return false;
+    }
+
+    return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
+}
+
+bool ValidateVertexAttribBinding(ValidationContext *context,
+                                 GLuint attribIndex,
+                                 GLuint bindingIndex)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    // [OpenGL ES 3.1] Section 10.3.1 page 243:
+    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+    if (context->getGLState().getVertexArrayId() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array object is bound."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (attribIndex >= caps.maxVertexAttributes)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
+        return false;
+    }
+
+    if (bindingIndex >= caps.maxVertexAttribBindings)
+    {
+        context->handleError(Error(GL_INVALID_VALUE,
+                                   "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS"));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetProgramResourceName(Context *context,
+                                    GLuint program,
+                                    GLenum programInterface,
+                                    GLuint index,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLchar *name)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    Program *programObject = GetValidProgram(context, program);
+    if (programObject == nullptr)
+    {
+        return false;
+    }
+
+    if (!ValidateNamedProgramInterface(programInterface))
+    {
+        context->handleError(
+            Error(GL_INVALID_ENUM, "Invalid program interface: 0x%X", programInterface));
+        return false;
+    }
+
+    if (!ValidateProgramResourceIndex(programObject, programInterface, index))
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid index: %d", index));
+        return false;
+    }
+
+    if (bufSize < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "Invalid bufSize: %d", bufSize));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateDispatchCompute(Context *context,
+                             GLuint numGroupsX,
+                             GLuint numGroupsY,
+                             GLuint numGroupsZ)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    const State &state = context->getGLState();
+    Program *program   = state.getProgram();
+
+    if (program == nullptr)
+    {
+        context->handleError(
+            Error(GL_INVALID_OPERATION, "No active program object for the compute shader stage."));
+        return false;
+    }
+
+    if (program->isLinked() == false || program->getAttachedComputeShader() == nullptr)
+    {
+        context->handleError(Error(
+            GL_INVALID_OPERATION,
+            "Program has not been successfully linked, or program contains no compute shaders."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (numGroupsX > caps.maxComputeWorkGroupCount[0])
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE,
+                  "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0](%u).",
+                  caps.maxComputeWorkGroupCount[0]));
+        return false;
+    }
+    if (numGroupsY > caps.maxComputeWorkGroupCount[1])
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE,
+                  "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1](%u).",
+                  caps.maxComputeWorkGroupCount[1]));
+        return false;
+    }
+    if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE,
+                  "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2](%u).",
+                  caps.maxComputeWorkGroupCount[2]));
+        return false;
+    }
+
+    return true;
+}
+
+}  // namespace gl
diff --git a/src/third_party/angle/src/libANGLE/validationES31.h b/src/third_party/angle/src/libANGLE/validationES31.h
new file mode 100644
index 0000000..77d6650
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationES31.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// validationES31.h: Validation functions for OpenGL ES 3.1 entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES31_H_
+#define LIBANGLE_VALIDATION_ES31_H_
+
+#include <GLES3/gl31.h>
+
+namespace gl
+{
+class Context;
+class ValidationContext;
+
+bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data);
+bool ValidateGetBooleani_vRobustANGLE(Context *context,
+                                      GLenum target,
+                                      GLuint index,
+                                      GLsizei bufSize,
+                                      GLsizei *length,
+                                      GLboolean *data);
+
+bool ValidateGetTexLevelParameterfv(Context *context,
+                                    GLenum target,
+                                    GLint level,
+                                    GLenum pname,
+                                    GLfloat *params);
+bool ValidateGetTexLevelParameteriv(Context *context,
+                                    GLenum target,
+                                    GLint level,
+                                    GLenum pname,
+                                    GLint *param);
+
+bool ValidateTexStorage2DMultiSample(Context *context,
+                                     GLenum target,
+                                     GLsizei samples,
+                                     GLint internalFormat,
+                                     GLsizei width,
+                                     GLsizei height,
+                                     GLboolean fixedSampleLocations);
+bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val);
+
+bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect);
+bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect);
+bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect);
+
+bool ValidationFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param);
+bool ValidationGetFramebufferParameteri(Context *context,
+                                        GLenum target,
+                                        GLenum pname,
+                                        GLint *params);
+
+bool ValidateGetProgramResourceIndex(Context *context,
+                                     GLuint program,
+                                     GLenum programInterface,
+                                     const GLchar *name);
+bool ValidateGetProgramResourceName(Context *context,
+                                    GLuint program,
+                                    GLenum programInterface,
+                                    GLuint index,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLchar *name);
+
+bool ValidateBindVertexBuffer(ValidationContext *context,
+                              GLuint bindingIndex,
+                              GLuint buffer,
+                              GLintptr offset,
+                              GLsizei stride);
+bool ValidateVertexAttribFormat(ValidationContext *context,
+                                GLuint attribIndex,
+                                GLint size,
+                                GLenum type,
+                                GLuint relativeOffset,
+                                GLboolean pureInteger);
+bool ValidateVertexAttribBinding(ValidationContext *context,
+                                 GLuint attribIndex,
+                                 GLuint bindingIndex);
+bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor);
+
+bool ValidateDispatchCompute(Context *context,
+                             GLuint numGroupsX,
+                             GLuint numGroupsY,
+                             GLuint numGroupsZ);
+
+}  // namespace gl
+
+#endif  // LIBANGLE_VALIDATION_ES31_H_
diff --git a/src/third_party/angle/src/libANGLE/validationES_unittest.cpp b/src/third_party/angle/src/libANGLE/validationES_unittest.cpp
new file mode 100644
index 0000000..0085986
--- /dev/null
+++ b/src/third_party/angle/src/libANGLE/validationES_unittest.cpp
@@ -0,0 +1,130 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES unit tests:
+//   Unit tests for general ES validation functions.
+//
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "libANGLE/ContextState.h"
+#include "libANGLE/VaryingPacking.h"
+#include "libANGLE/renderer/FramebufferImpl_mock.h"
+#include "libANGLE/renderer/ProgramImpl_mock.h"
+#include "libANGLE/renderer/TextureImpl_mock.h"
+#include "libANGLE/validationES.h"
+#include "tests/angle_unittests_utils.h"
+
+using namespace gl;
+using namespace rx;
+using testing::_;
+using testing::NiceMock;
+using testing::Return;
+
+namespace
+{
+
+class MockValidationContext : public ValidationContext
+{
+  public:
+    MockValidationContext(const ValidationContext *shareContext,
+                          TextureManager *shareTextures,
+                          const Version &version,
+                          State *state,
+                          const Caps &caps,
+                          const TextureCapsMap &textureCaps,
+                          const Extensions &extensions,
+                          const Limitations &limitations,
+                          bool skipValidation)
+        : ValidationContext(shareContext,
+                            shareTextures,
+                            version,
+                            state,
+                            caps,
+                            textureCaps,
+                            extensions,
+                            limitations,
+                            skipValidation)
+    {
+    }
+
+    MOCK_METHOD1(handleError, void(const Error &));
+};
+
+// Test that ANGLE generates an INVALID_OPERATION when validating index data that uses a value
+// larger than MAX_ELEMENT_INDEX. Not specified in the GLES 3 spec, it's undefined behaviour,
+// but we want a test to ensure we maintain this behaviour.
+// TODO(jmadill): Re-enable when framebuffer sync state doesn't happen in validation.
+TEST(ValidationESTest, DISABLED_DrawElementsWithMaxIndexGivesError)
+{
+    auto framebufferImpl = MakeFramebufferMock();
+    auto programImpl     = MakeProgramMock();
+
+    // TODO(jmadill): Generalize some of this code so we can re-use it for other tests.
+    NiceMock<MockGLFactory> mockFactory;
+    EXPECT_CALL(mockFactory, createFramebuffer(_)).WillOnce(Return(framebufferImpl));
+    EXPECT_CALL(mockFactory, createProgram(_)).WillOnce(Return(programImpl));
+    EXPECT_CALL(mockFactory, createVertexArray(_)).WillOnce(Return(nullptr));
+
+    State state;
+    Caps caps;
+    TextureCapsMap textureCaps;
+    Extensions extensions;
+    Limitations limitations;
+
+    // Set some basic caps.
+    caps.maxElementIndex     = 100;
+    caps.maxDrawBuffers      = 1;
+    caps.maxColorAttachments = 1;
+    state.initialize(caps, extensions, Version(3, 0), false, true, true, false);
+
+    NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
+    EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
+    EXPECT_CALL(*textureImpl, setStorage(_, _, _, _, _)).WillOnce(Return(NoError()));
+    EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
+
+    Texture *texture = new Texture(&mockFactory, 0, GL_TEXTURE_2D);
+    texture->addRef();
+    texture->setStorage(nullptr, GL_TEXTURE_2D, 1, GL_RGBA8, Extents(1, 1, 0));
+
+    VertexArray *vertexArray = new VertexArray(&mockFactory, 0, 1, 1);
+    Framebuffer *framebuffer = new Framebuffer(caps, &mockFactory, 1);
+    framebuffer->setAttachment(nullptr, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex::Make2D(0),
+                               texture);
+
+    Program *program = new Program(&mockFactory, nullptr, 1);
+
+    state.setVertexArrayBinding(vertexArray);
+    state.setDrawFramebufferBinding(framebuffer);
+    state.setProgram(nullptr, program);
+
+    NiceMock<MockValidationContext> testContext(nullptr, nullptr, Version(3, 0), &state, caps,
+                                                textureCaps, extensions, limitations, false);
+
+    // Set the expectation for the validation error here.
+    Error expectedError(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage);
+    EXPECT_CALL(testContext, handleError(expectedError)).Times(1);
+
+    // Call once with maximum index, and once with an excessive index.
+    GLuint indexData[] = {0, 1, static_cast<GLuint>(caps.maxElementIndex - 1),
+                          3, 4, static_cast<GLuint>(caps.maxElementIndex)};
+    EXPECT_TRUE(
+        ValidateDrawElementsCommon(&testContext, GL_TRIANGLES, 3, GL_UNSIGNED_INT, indexData, 1));
+    EXPECT_FALSE(
+        ValidateDrawElementsCommon(&testContext, GL_TRIANGLES, 6, GL_UNSIGNED_INT, indexData, 2));
+
+    texture->release();
+
+    state.setVertexArrayBinding(nullptr);
+    state.setDrawFramebufferBinding(nullptr);
+    state.setProgram(nullptr, nullptr);
+
+    SafeDelete(vertexArray);
+    SafeDelete(framebuffer);
+    SafeDelete(program);
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/libEGL.gypi b/src/third_party/angle/src/libEGL.gypi
new file mode 100644
index 0000000..fdce4ba
--- /dev/null
+++ b/src/third_party/angle/src/libEGL.gypi
@@ -0,0 +1,90 @@
+# Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    # Everything below this is duplicated in the GN build. If you change
+    # anything also change angle/BUILD.gn
+    'targets':
+    [
+        {
+            'target_name': 'libEGL',
+            'type': '<(angle_gl_library_type)',
+            'dependencies':
+            [
+                'libGLESv2',
+            ],
+            'includes':
+            [
+                '../gyp/common_defines.gypi',
+            ],
+            'include_dirs':
+            [
+                '.',
+                '../include',
+            ],
+            'sources':
+            [
+                '<@(libegl_sources)',
+            ],
+            'conditions':
+            [
+                ['angle_build_winrt==1',
+                {
+                    'msvs_requires_importlibrary' : 'true',
+                }],
+                ['OS=="win"', {
+                    'defines':
+                    [
+                        'EGLAPI=',
+                    ],
+                }, {
+                    'defines':
+                    [
+                        'EGLAPI=__attribute__((visibility("default")))',
+                    ],
+                }],
+                ['OS == "mac"',
+                {
+                    'xcode_settings':
+                    {
+                        'DYLIB_INSTALL_NAME_BASE': '@rpath',
+                    },
+                }],
+            ],
+        },
+
+        {
+            'target_name': 'libEGL_static',
+            'type': 'static_library',
+            'dependencies':
+            [
+                'libGLESv2_static',
+            ],
+            'includes':
+            [
+                '../gyp/common_defines.gypi',
+            ],
+            'include_dirs':
+            [
+                '.',
+                '../include',
+            ],
+            'sources':
+            [
+                '<@(libegl_sources)',
+            ],
+            'defines':
+            [
+                'EGLAPI=',
+            ],
+            'direct_dependent_settings':
+            {
+                'defines':
+                [
+                    'EGLAPI=',
+                ],
+            },
+        },
+    ],
+}
diff --git a/src/third_party/angle/src/libEGL/Config.cpp b/src/third_party/angle/src/libEGL/Config.cpp
deleted file mode 100644
index 5488cb6..0000000
--- a/src/third_party/angle/src/libEGL/Config.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Config.cpp: Implements the egl::Config class, describing the format, type
-// and size for an egl::Surface. Implements EGLConfig and related functionality.
-// [EGL 1.4] section 3.4 page 15.
-
-#include "libEGL/Config.h"
-
-#include <algorithm>
-#include <vector>
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include "common/debug.h"
-
-using namespace std;
-
-namespace egl
-{
-Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight)
-    : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample)
-{
-    mBindToTextureRGB = EGL_FALSE;
-    mBindToTextureRGBA = EGL_FALSE;
-    switch (desc.renderTargetFormat)
-    {
-      case GL_RGB5_A1:
-        mBufferSize = 16;
-        mRedSize = 5;
-        mGreenSize = 5;
-        mBlueSize = 5;
-        mAlphaSize = 1;
-        break;
-      case GL_RGBA8_OES:
-        mBufferSize = 32;
-        mRedSize = 8;
-        mGreenSize = 8;
-        mBlueSize = 8;
-        mAlphaSize = 8;
-        mBindToTextureRGBA = true;
-        break;
-      case GL_RGB565:
-        mBufferSize = 16;
-        mRedSize = 5;
-        mGreenSize = 6;
-        mBlueSize = 5;
-        mAlphaSize = 0;
-        break;
-      case GL_RGB8_OES:
-        mBufferSize = 32;
-        mRedSize = 8;
-        mGreenSize = 8;
-        mBlueSize = 8;
-        mAlphaSize = 0;
-        mBindToTextureRGB = true;
-        break;
-      case GL_BGRA8_EXT:
-        mBufferSize = 32;
-        mRedSize = 8;
-        mGreenSize = 8;
-        mBlueSize = 8;
-        mAlphaSize = 8;
-        mBindToTextureRGBA = true;
-        break;
-      default:
-        UNREACHABLE();   // Other formats should not be valid
-    }
-
-    mLuminanceSize = 0;
-    mAlphaMaskSize = 0;
-    mColorBufferType = EGL_RGB_BUFFER;
-    mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG;
-    mConfigID = 0;
-    mConformant = EGL_OPENGL_ES2_BIT;
-
-    switch (desc.depthStencilFormat)
-    {
-      case GL_NONE:
-        mDepthSize = 0;
-        mStencilSize = 0;
-        break;
-      case GL_DEPTH_COMPONENT32_OES:
-        mDepthSize = 32;
-        mStencilSize = 0;
-        break;
-      case GL_DEPTH24_STENCIL8_OES:
-        mDepthSize = 24;
-        mStencilSize = 8;
-        break;
-      case GL_DEPTH_COMPONENT24_OES:
-        mDepthSize = 24;
-        mStencilSize = 0;
-        break;
-      case GL_DEPTH_COMPONENT16:
-        mDepthSize = 16;
-        mStencilSize = 0;
-        break;
-      default:
-        UNREACHABLE();
-    }
-
-    mLevel = 0;
-    mMatchNativePixmap = EGL_NONE;
-    mMaxPBufferWidth = texWidth;
-    mMaxPBufferHeight = texHeight;
-    mMaxPBufferPixels = texWidth*texHeight;
-    mMaxSwapInterval = maxInterval;
-    mMinSwapInterval = minInterval;
-    mNativeRenderable = EGL_FALSE;
-    mNativeVisualID = 0;
-    mNativeVisualType = 0;
-    mRenderableType = EGL_OPENGL_ES2_BIT;
-    mSampleBuffers = desc.multiSample ? 1 : 0;
-    mSamples = desc.multiSample;
-    mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
-    mTransparentType = EGL_NONE;
-    mTransparentRedValue = 0;
-    mTransparentGreenValue = 0;
-    mTransparentBlueValue = 0;
-}
-
-EGLConfig Config::getHandle() const
-{
-    return (EGLConfig)(size_t)mConfigID;
-}
-
-SortConfig::SortConfig(const EGLint *attribList)
-    : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
-{
-    scanForWantedComponents(attribList);
-}
-
-void SortConfig::scanForWantedComponents(const EGLint *attribList)
-{
-    // [EGL] section 3.4.1 page 24
-    // Sorting rule #3: by larger total number of color bits, not considering
-    // components that are 0 or don't-care.
-    for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
-    {
-        if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
-        {
-            switch (attr[0])
-            {
-              case EGL_RED_SIZE:       mWantRed = true; break;
-              case EGL_GREEN_SIZE:     mWantGreen = true; break;
-              case EGL_BLUE_SIZE:      mWantBlue = true; break;
-              case EGL_ALPHA_SIZE:     mWantAlpha = true; break;
-              case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
-            }
-        }
-    }
-}
-
-EGLint SortConfig::wantedComponentsSize(const Config &config) const
-{
-    EGLint total = 0;
-
-    if (mWantRed)       total += config.mRedSize;
-    if (mWantGreen)     total += config.mGreenSize;
-    if (mWantBlue)      total += config.mBlueSize;
-    if (mWantAlpha)     total += config.mAlphaSize;
-    if (mWantLuminance) total += config.mLuminanceSize;
-
-    return total;
-}
-
-bool SortConfig::operator()(const Config *x, const Config *y) const
-{
-    return (*this)(*x, *y);
-}
-
-bool SortConfig::operator()(const Config &x, const Config &y) const
-{
-    #define SORT(attribute)                        \
-        if (x.attribute != y.attribute)            \
-        {                                          \
-            return x.attribute < y.attribute;      \
-        }
-
-    META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
-    SORT(mConfigCaveat);
-
-    META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
-    SORT(mColorBufferType);
-
-    // By larger total number of color bits, only considering those that are requested to be > 0.
-    EGLint xComponentsSize = wantedComponentsSize(x);
-    EGLint yComponentsSize = wantedComponentsSize(y);
-    if (xComponentsSize != yComponentsSize)
-    {
-        return xComponentsSize > yComponentsSize;
-    }
-
-    SORT(mBufferSize);
-    SORT(mSampleBuffers);
-    SORT(mSamples);
-    SORT(mDepthSize);
-    SORT(mStencilSize);
-    SORT(mAlphaMaskSize);
-    SORT(mNativeVisualType);
-    SORT(mConfigID);
-
-    #undef SORT
-
-    return false;
-}
-
-// We'd like to use SortConfig to also eliminate duplicate configs.
-// This works as long as we never have two configs with different per-RGB-component layouts,
-// but the same total.
-// 5551 and 565 are different because R+G+B is different.
-// 5551 and 555 are different because bufferSize is different.
-const EGLint ConfigSet::mSortAttribs[] =
-{
-    EGL_RED_SIZE, 1,
-    EGL_GREEN_SIZE, 1,
-    EGL_BLUE_SIZE, 1,
-    EGL_LUMINANCE_SIZE, 1,
-    // BUT NOT ALPHA
-    EGL_NONE
-};
-
-ConfigSet::ConfigSet()
-    : mSet(SortConfig(mSortAttribs))
-{
-}
-
-void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight)
-{
-    Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight);
-    mSet.insert(config);
-}
-
-size_t ConfigSet::size() const
-{
-    return mSet.size();
-}
-
-bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
-{
-    vector<const Config*> passed;
-    passed.reserve(mSet.size());
-
-    for (Iterator config = mSet.begin(); config != mSet.end(); config++)
-    {
-        bool match = true;
-        const EGLint *attribute = attribList;
-
-        while (attribute[0] != EGL_NONE)
-        {
-            switch (attribute[0])
-            {
-              case EGL_BUFFER_SIZE:               match = config->mBufferSize >= attribute[1];                      break;
-              case EGL_ALPHA_SIZE:                match = config->mAlphaSize >= attribute[1];                       break;
-              case EGL_BLUE_SIZE:                 match = config->mBlueSize >= attribute[1];                        break;
-              case EGL_GREEN_SIZE:                match = config->mGreenSize >= attribute[1];                       break;
-              case EGL_RED_SIZE:                  match = config->mRedSize >= attribute[1];                         break;
-              case EGL_DEPTH_SIZE:                match = config->mDepthSize >= attribute[1];                       break;
-              case EGL_STENCIL_SIZE:              match = config->mStencilSize >= attribute[1];                     break;
-              case EGL_CONFIG_CAVEAT:             match = config->mConfigCaveat == (EGLenum) attribute[1];          break;
-              case EGL_CONFIG_ID:                 match = config->mConfigID == attribute[1];                        break;
-              case EGL_LEVEL:                     match = config->mLevel >= attribute[1];                           break;
-              case EGL_NATIVE_RENDERABLE:         match = config->mNativeRenderable == (EGLBoolean) attribute[1];   break;
-              case EGL_NATIVE_VISUAL_TYPE:        match = config->mNativeVisualType == attribute[1];                break;
-              case EGL_SAMPLES:                   match = config->mSamples >= attribute[1];                         break;
-              case EGL_SAMPLE_BUFFERS:            match = config->mSampleBuffers >= attribute[1];                   break;
-              case EGL_SURFACE_TYPE:              match = (config->mSurfaceType & attribute[1]) == attribute[1];    break;
-              case EGL_TRANSPARENT_TYPE:          match = config->mTransparentType == (EGLenum) attribute[1];       break;
-              case EGL_TRANSPARENT_BLUE_VALUE:    match = config->mTransparentBlueValue == attribute[1];            break;
-              case EGL_TRANSPARENT_GREEN_VALUE:   match = config->mTransparentGreenValue == attribute[1];           break;
-              case EGL_TRANSPARENT_RED_VALUE:     match = config->mTransparentRedValue == attribute[1];             break;
-              case EGL_BIND_TO_TEXTURE_RGB:       match = config->mBindToTextureRGB == (EGLBoolean) attribute[1];   break;
-              case EGL_BIND_TO_TEXTURE_RGBA:      match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1];  break;
-              case EGL_MIN_SWAP_INTERVAL:         match = config->mMinSwapInterval == attribute[1];                 break;
-              case EGL_MAX_SWAP_INTERVAL:         match = config->mMaxSwapInterval == attribute[1];                 break;
-              case EGL_LUMINANCE_SIZE:            match = config->mLuminanceSize >= attribute[1];                   break;
-              case EGL_ALPHA_MASK_SIZE:           match = config->mAlphaMaskSize >= attribute[1];                   break;
-              case EGL_COLOR_BUFFER_TYPE:         match = config->mColorBufferType == (EGLenum) attribute[1];       break;
-              case EGL_RENDERABLE_TYPE:           match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
-              case EGL_MATCH_NATIVE_PIXMAP:       match = false; UNIMPLEMENTED();                                   break;
-              case EGL_CONFORMANT:                match = (config->mConformant & attribute[1]) == attribute[1];     break;
-              case EGL_MAX_PBUFFER_WIDTH:         match = config->mMaxPBufferWidth >= attribute[1];                 break;
-              case EGL_MAX_PBUFFER_HEIGHT:        match = config->mMaxPBufferHeight >= attribute[1];                break;
-              case EGL_MAX_PBUFFER_PIXELS:        match = config->mMaxPBufferPixels >= attribute[1];                break;
-              default:
-                return false;
-            }
-
-            if (!match)
-            {
-                break;
-            }
-
-            attribute += 2;
-        }
-
-        if (match)
-        {
-            passed.push_back(&*config);
-        }
-    }
-
-    if (configs)
-    {
-        sort(passed.begin(), passed.end(), SortConfig(attribList));
-
-        EGLint index;
-        for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
-        {
-            configs[index] = passed[index]->getHandle();
-        }
-
-        *numConfig = index;
-    }
-    else
-    {
-        *numConfig = passed.size();
-    }
-
-    return true;
-}
-
-const egl::Config *ConfigSet::get(EGLConfig configHandle)
-{
-    for (Iterator config = mSet.begin(); config != mSet.end(); config++)
-    {
-        if (config->getHandle() == configHandle)
-        {
-            return &(*config);
-        }
-    }
-
-    return NULL;
-}
-}
diff --git a/src/third_party/angle/src/libEGL/Config.h b/src/third_party/angle/src/libEGL/Config.h
deleted file mode 100644
index 680337b..0000000
--- a/src/third_party/angle/src/libEGL/Config.h
+++ /dev/null
@@ -1,115 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Config.h: Defines the egl::Config class, describing the format, type
-// and size for an egl::Surface. Implements EGLConfig and related functionality.
-// [EGL 1.4] section 3.4 page 15.
-
-#ifndef INCLUDE_CONFIG_H_
-#define INCLUDE_CONFIG_H_
-
-#define EGLAPI
-#include <EGL/egl.h>
-
-#include <set>
-
-#include "libGLESv2/renderer/Renderer.h"
-#include "common/angleutils.h"
-
-namespace egl
-{
-class Display;
-
-class Config
-{
-  public:
-    Config(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight);
-
-    EGLConfig getHandle() const;
-
-    const GLenum mRenderTargetFormat;
-    const GLenum mDepthStencilFormat;
-    const GLint mMultiSample;
-
-    EGLint mBufferSize;              // Depth of the color buffer
-    EGLint mRedSize;                 // Bits of Red in the color buffer
-    EGLint mGreenSize;               // Bits of Green in the color buffer
-    EGLint mBlueSize;                // Bits of Blue in the color buffer
-    EGLint mLuminanceSize;           // Bits of Luminance in the color buffer
-    EGLint mAlphaSize;               // Bits of Alpha in the color buffer
-    EGLint mAlphaMaskSize;           // Bits of Alpha Mask in the mask buffer
-    EGLBoolean mBindToTextureRGB;    // True if bindable to RGB textures.
-    EGLBoolean mBindToTextureRGBA;   // True if bindable to RGBA textures.
-    EGLenum mColorBufferType;        // Color buffer type
-    EGLenum mConfigCaveat;           // Any caveats for the configuration
-    EGLint mConfigID;                // Unique EGLConfig identifier
-    EGLint mConformant;              // Whether contexts created with this config are conformant
-    EGLint mDepthSize;               // Bits of Z in the depth buffer
-    EGLint mLevel;                   // Frame buffer level
-    EGLBoolean mMatchNativePixmap;   // Match the native pixmap format
-    EGLint mMaxPBufferWidth;         // Maximum width of pbuffer
-    EGLint mMaxPBufferHeight;        // Maximum height of pbuffer
-    EGLint mMaxPBufferPixels;        // Maximum size of pbuffer
-    EGLint mMaxSwapInterval;         // Maximum swap interval
-    EGLint mMinSwapInterval;         // Minimum swap interval
-    EGLBoolean mNativeRenderable;    // EGL_TRUE if native rendering APIs can render to surface
-    EGLint mNativeVisualID;          // Handle of corresponding native visual
-    EGLint mNativeVisualType;        // Native visual type of the associated visual
-    EGLint mRenderableType;          // Which client rendering APIs are supported.
-    EGLint mSampleBuffers;           // Number of multisample buffers
-    EGLint mSamples;                 // Number of samples per pixel
-    EGLint mStencilSize;             // Bits of Stencil in the stencil buffer
-    EGLint mSurfaceType;             // Which types of EGL surfaces are supported.
-    EGLenum mTransparentType;        // Type of transparency supported
-    EGLint mTransparentRedValue;     // Transparent red value
-    EGLint mTransparentGreenValue;   // Transparent green value
-    EGLint mTransparentBlueValue;    // Transparent blue value
-};
-
-// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
-class SortConfig
-{
-  public:
-    explicit SortConfig(const EGLint *attribList);
-
-    bool operator()(const Config *x, const Config *y) const;
-    bool operator()(const Config &x, const Config &y) const;
-
-  private:
-    void scanForWantedComponents(const EGLint *attribList);
-    EGLint wantedComponentsSize(const Config &config) const;
-
-    bool mWantRed;
-    bool mWantGreen;
-    bool mWantBlue;
-    bool mWantAlpha;
-    bool mWantLuminance;
-};
-
-class ConfigSet
-{
-    friend Display;
-
-  public:
-    ConfigSet();
-
-    void add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight);
-    size_t size() const;
-    bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
-    const egl::Config *get(EGLConfig configHandle);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(ConfigSet);
-
-    typedef std::set<Config, SortConfig> Set;
-    typedef Set::iterator Iterator;
-    Set mSet;
-
-    static const EGLint mSortAttribs[];
-};
-}
-
-#endif   // INCLUDE_CONFIG_H_
diff --git a/src/third_party/angle/src/libEGL/Display.cpp b/src/third_party/angle/src/libEGL/Display.cpp
deleted file mode 100644
index e8552bb..0000000
--- a/src/third_party/angle/src/libEGL/Display.cpp
+++ /dev/null
@@ -1,539 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Display.cpp: Implements the egl::Display class, representing the abstract
-// display on which graphics are drawn. Implements EGLDisplay.
-// [EGL 1.4] section 2.1.2 page 3.
-
-#include "libEGL/Display.h"
-
-#include <algorithm>
-#include <map>
-#include <vector>
-
-#include "common/debug.h"
-#include "libGLESv2/mathutil.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/SwapChain.h"
-
-#include "libEGL/main.h"
-#include "libEGL/Surface.h"
-
-namespace egl
-{
-namespace
-{
-    typedef std::map<EGLNativeDisplayType, Display*> DisplayMap; 
-    DisplayMap displays;
-}
-
-egl::Display *Display::getDisplay(EGLNativeDisplayType displayId)
-{
-    if (displays.find(displayId) != displays.end())
-    {
-        return displays[displayId];
-    }
-    
-    // FIXME: Check if displayId is a valid display device context
-
-    egl::Display *display = new egl::Display(displayId, (HDC)displayId);
-
-    displays[displayId] = display;
-    return display;
-}
-
-Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext)
-{
-    mDisplayId = displayId;
-    mRenderer = NULL;
-}
-
-Display::~Display()
-{
-    terminate();
-
-    DisplayMap::iterator thisDisplay = displays.find(mDisplayId);
-
-    if (thisDisplay != displays.end())
-    {
-        displays.erase(thisDisplay);
-    }
-}
-
-bool Display::initialize()
-{
-    if (isInitialized())
-    {
-        return true;
-    }
-
-    mRenderer = glCreateRenderer(this, mDc, mDisplayId);
-    
-    if (!mRenderer)
-    {
-        terminate();
-        return error(EGL_NOT_INITIALIZED, false);
-    }
-
-    EGLint minSwapInterval = mRenderer->getMinSwapInterval();
-    EGLint maxSwapInterval = mRenderer->getMaxSwapInterval();
-    EGLint maxTextureWidth = mRenderer->getMaxTextureWidth();
-    EGLint maxTextureHeight = mRenderer->getMaxTextureHeight();
-
-    rx::ConfigDesc *descList;
-    int numConfigs = mRenderer->generateConfigs(&descList);
-    ConfigSet configSet;
-
-    for (int i = 0; i < numConfigs; ++i)
-        configSet.add(descList[i], minSwapInterval, maxSwapInterval,
-                      maxTextureWidth, maxTextureHeight);
-
-    // Give the sorted configs a unique ID and store them internally
-    EGLint index = 1;
-    for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
-    {
-        Config configuration = *config;
-        configuration.mConfigID = index;
-        index++;
-
-        mConfigSet.mSet.insert(configuration);
-    }
-
-    mRenderer->deleteConfigs(descList);
-    descList = NULL;
-
-    if (!isInitialized())
-    {
-        terminate();
-        return false;
-    }
-
-    initExtensionString();
-    initVendorString();
-
-    return true;
-}
-
-void Display::terminate()
-{
-    while (!mSurfaceSet.empty())
-    {
-        destroySurface(*mSurfaceSet.begin());
-    }
-
-    while (!mContextSet.empty())
-    {
-        destroyContext(*mContextSet.begin());
-    }
-
-    glDestroyRenderer(mRenderer);
-    mRenderer = NULL;
-}
-
-bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
-{
-    return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);
-}
-
-bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
-{
-    const egl::Config *configuration = mConfigSet.get(config);
-
-    switch (attribute)
-    {
-      case EGL_BUFFER_SIZE:               *value = configuration->mBufferSize;             break;
-      case EGL_ALPHA_SIZE:                *value = configuration->mAlphaSize;              break;
-      case EGL_BLUE_SIZE:                 *value = configuration->mBlueSize;               break;
-      case EGL_GREEN_SIZE:                *value = configuration->mGreenSize;              break;
-      case EGL_RED_SIZE:                  *value = configuration->mRedSize;                break;
-      case EGL_DEPTH_SIZE:                *value = configuration->mDepthSize;              break;
-      case EGL_STENCIL_SIZE:              *value = configuration->mStencilSize;            break;
-      case EGL_CONFIG_CAVEAT:             *value = configuration->mConfigCaveat;           break;
-      case EGL_CONFIG_ID:                 *value = configuration->mConfigID;               break;
-      case EGL_LEVEL:                     *value = configuration->mLevel;                  break;
-      case EGL_NATIVE_RENDERABLE:         *value = configuration->mNativeRenderable;       break;
-      case EGL_NATIVE_VISUAL_TYPE:        *value = configuration->mNativeVisualType;       break;
-      case EGL_SAMPLES:                   *value = configuration->mSamples;                break;
-      case EGL_SAMPLE_BUFFERS:            *value = configuration->mSampleBuffers;          break;
-      case EGL_SURFACE_TYPE:              *value = configuration->mSurfaceType;            break;
-      case EGL_TRANSPARENT_TYPE:          *value = configuration->mTransparentType;        break;
-      case EGL_TRANSPARENT_BLUE_VALUE:    *value = configuration->mTransparentBlueValue;   break;
-      case EGL_TRANSPARENT_GREEN_VALUE:   *value = configuration->mTransparentGreenValue;  break;
-      case EGL_TRANSPARENT_RED_VALUE:     *value = configuration->mTransparentRedValue;    break;
-      case EGL_BIND_TO_TEXTURE_RGB:       *value = configuration->mBindToTextureRGB;       break;
-      case EGL_BIND_TO_TEXTURE_RGBA:      *value = configuration->mBindToTextureRGBA;      break;
-      case EGL_MIN_SWAP_INTERVAL:         *value = configuration->mMinSwapInterval;        break;
-      case EGL_MAX_SWAP_INTERVAL:         *value = configuration->mMaxSwapInterval;        break;
-      case EGL_LUMINANCE_SIZE:            *value = configuration->mLuminanceSize;          break;
-      case EGL_ALPHA_MASK_SIZE:           *value = configuration->mAlphaMaskSize;          break;
-      case EGL_COLOR_BUFFER_TYPE:         *value = configuration->mColorBufferType;        break;
-      case EGL_RENDERABLE_TYPE:           *value = configuration->mRenderableType;         break;
-      case EGL_MATCH_NATIVE_PIXMAP:       *value = false; UNIMPLEMENTED();                 break;
-      case EGL_CONFORMANT:                *value = configuration->mConformant;             break;
-      case EGL_MAX_PBUFFER_WIDTH:         *value = configuration->mMaxPBufferWidth;        break;
-      case EGL_MAX_PBUFFER_HEIGHT:        *value = configuration->mMaxPBufferHeight;       break;
-      case EGL_MAX_PBUFFER_PIXELS:        *value = configuration->mMaxPBufferPixels;       break;
-      default:
-        return false;
-    }
-
-    return true;
-}
-
-EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList)
-{
-    const Config *configuration = mConfigSet.get(config);
-    EGLint postSubBufferSupported = EGL_FALSE;
-
-    if (attribList)
-    {
-        while (*attribList != EGL_NONE)
-        {
-            switch (attribList[0])
-            {
-              case EGL_RENDER_BUFFER:
-                switch (attribList[1])
-                {
-                  case EGL_BACK_BUFFER:
-                    break;
-                  case EGL_SINGLE_BUFFER:
-                    return error(EGL_BAD_MATCH, EGL_NO_SURFACE);   // Rendering directly to front buffer not supported
-                  default:
-                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
-                }
-                break;
-              case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
-                postSubBufferSupported = attribList[1];
-                break;
-              case EGL_VG_COLORSPACE:
-                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
-              case EGL_VG_ALPHA_FORMAT:
-                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
-              default:
-                return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
-            }
-
-            attribList += 2;
-        }
-    }
-
-    if (hasExistingWindowSurface(window))
-    {
-        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-    }
-
-    if (mRenderer->testDeviceLost(false))
-    {
-        if (!restoreLostDevice())
-            return EGL_NO_SURFACE;
-    }
-
-    Surface *surface = new Surface(this, configuration, window, postSubBufferSupported);
-
-    if (!surface->initialize())
-    {
-        delete surface;
-        return EGL_NO_SURFACE;
-    }
-
-    mSurfaceSet.insert(surface);
-
-    return success(surface);
-}
-
-EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList)
-{
-    EGLint width = 0, height = 0;
-    EGLenum textureFormat = EGL_NO_TEXTURE;
-    EGLenum textureTarget = EGL_NO_TEXTURE;
-    const Config *configuration = mConfigSet.get(config);
-
-    if (attribList)
-    {
-        while (*attribList != EGL_NONE)
-        {
-            switch (attribList[0])
-            {
-              case EGL_WIDTH:
-                width = attribList[1];
-                break;
-              case EGL_HEIGHT:
-                height = attribList[1];
-                break;
-              case EGL_LARGEST_PBUFFER:
-                if (attribList[1] != EGL_FALSE)
-                  UNIMPLEMENTED(); // FIXME
-                break;
-              case EGL_TEXTURE_FORMAT:
-                switch (attribList[1])
-                {
-                  case EGL_NO_TEXTURE:
-                  case EGL_TEXTURE_RGB:
-                  case EGL_TEXTURE_RGBA:
-                    textureFormat = attribList[1];
-                    break;
-                  default:
-                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
-                }
-                break;
-              case EGL_TEXTURE_TARGET:
-                switch (attribList[1])
-                {
-                  case EGL_NO_TEXTURE:
-                  case EGL_TEXTURE_2D:
-                    textureTarget = attribList[1];
-                    break;
-                  default:
-                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
-                }
-                break;
-              case EGL_MIPMAP_TEXTURE:
-                if (attribList[1] != EGL_FALSE)
-                  return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
-                break;
-              case EGL_VG_COLORSPACE:
-                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
-              case EGL_VG_ALPHA_FORMAT:
-                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
-              default:
-                return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
-            }
-
-            attribList += 2;
-        }
-    }
-
-    if (width < 0 || height < 0)
-    {
-        return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
-    }
-
-    if (width == 0 || height == 0)
-    {
-        return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
-    }
-
-    if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height)))
-    {
-        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
-    }
-
-    if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
-        (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
-    {
-        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
-    }
-
-    if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
-    {
-        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
-    }
-
-    if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
-        (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
-    {
-        return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
-    }
-
-    if (mRenderer->testDeviceLost(false))
-    {
-        if (!restoreLostDevice())
-            return EGL_NO_SURFACE;
-    }
-
-    Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
-
-    if (!surface->initialize())
-    {
-        delete surface;
-        return EGL_NO_SURFACE;
-    }
-
-    mSurfaceSet.insert(surface);
-
-    return success(surface);
-}
-
-EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
-{
-    if (!mRenderer)
-    {
-        return NULL;
-    }
-    else if (mRenderer->testDeviceLost(false))   // Lost device
-    {
-        if (!restoreLostDevice())
-            return NULL;
-    }
-
-    gl::Context *context = glCreateContext(shareContext, mRenderer, notifyResets, robustAccess);
-    mContextSet.insert(context);
-
-    return context;
-}
-
-bool Display::restoreLostDevice()
-{
-    for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
-    {
-        if ((*ctx)->isResetNotificationEnabled())
-            return false;   // If reset notifications have been requested, application must delete all contexts first
-    }
- 
-    // Release surface resources to make the Reset() succeed
-    for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
-    {
-        (*surface)->release();
-    }
-
-    if (!mRenderer->resetDevice())
-    {
-        return error(EGL_BAD_ALLOC, false);
-    }
-
-    // Restore any surfaces that may have been lost
-    for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
-    {
-        (*surface)->resetSwapChain();
-    }
-
-    return true;
-}
-
-
-void Display::destroySurface(egl::Surface *surface)
-{
-    delete surface;
-    mSurfaceSet.erase(surface);
-}
-
-void Display::destroyContext(gl::Context *context)
-{
-    glDestroyContext(context);
-    mContextSet.erase(context);
-}
-
-void Display::notifyDeviceLost()
-{
-    for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
-    {
-        (*context)->markContextLost();
-    }
-    egl::error(EGL_CONTEXT_LOST);
-}
-
-void Display::recreateSwapChains()
-{
-    for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
-    {
-        (*surface)->getSwapChain()->recreate();
-    }
-}
-
-bool Display::isInitialized() const
-{
-    return mRenderer != NULL && mConfigSet.size() > 0;
-}
-
-bool Display::isValidConfig(EGLConfig config)
-{
-    return mConfigSet.get(config) != NULL;
-}
-
-bool Display::isValidContext(gl::Context *context)
-{
-    return mContextSet.find(context) != mContextSet.end();
-}
-
-bool Display::isValidSurface(egl::Surface *surface)
-{
-    return mSurfaceSet.find(surface) != mSurfaceSet.end();
-}
-
-bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
-{
-    for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
-    {
-        if ((*surface)->compareWindow(window))
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-void Display::initExtensionString()
-{
-#if defined(__LB_XB360__)
-    HMODULE swiftShader = NULL;
-#else
-    HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
-#endif
-    bool shareHandleSupported = mRenderer->getShareHandleSupport();
-
-    mExtensionString = "";
-
-    // Multi-vendor (EXT) extensions
-    mExtensionString += "EGL_EXT_create_context_robustness ";
-
-    // ANGLE-specific extensions
-    if (shareHandleSupported)
-    {
-        mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer ";
-    }
-
-    mExtensionString += "EGL_ANGLE_query_surface_pointer ";
-
-    if (swiftShader)
-    {
-        mExtensionString += "EGL_ANGLE_software_display ";
-    }
-
-    if (shareHandleSupported)
-    {
-        mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle ";
-    }
-
-    if (mRenderer->getPostSubBufferSupport())
-    {
-        mExtensionString += "EGL_NV_post_sub_buffer";
-    }
-
-    std::string::size_type end = mExtensionString.find_last_not_of(' ');
-    if (end != std::string::npos)
-    {
-        mExtensionString.resize(end+1);
-    }
-}
-
-const char *Display::getExtensionString() const
-{
-    return mExtensionString.c_str();
-}
-
-void Display::initVendorString()
-{
-    mVendorString = "Google Inc.";
-
-    LUID adapterLuid = {0};
-
-    if (mRenderer && mRenderer->getLUID(&adapterLuid))
-    {
-        char adapterLuidString[64];
-        sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
-
-        mVendorString += adapterLuidString;
-    }
-}
-
-const char *Display::getVendorString() const
-{
-    return mVendorString.c_str();
-}
-
-}
diff --git a/src/third_party/angle/src/libEGL/Display.h b/src/third_party/angle/src/libEGL/Display.h
deleted file mode 100644
index 5d55410..0000000
--- a/src/third_party/angle/src/libEGL/Display.h
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Display.h: Defines the egl::Display class, representing the abstract
-// display on which graphics are drawn. Implements EGLDisplay.
-// [EGL 1.4] section 2.1.2 page 3.
-
-#ifndef LIBEGL_DISPLAY_H_
-#define LIBEGL_DISPLAY_H_
-
-#include "common/system.h"
-
-#include <set>
-#include <vector>
-
-#include "libEGL/Config.h"
-
-namespace gl
-{
-class Context;
-}
-
-namespace egl
-{
-class Surface;
-
-class Display
-{
-  public:
-    ~Display();
-
-    bool initialize();
-    void terminate();
-
-    static egl::Display *getDisplay(EGLNativeDisplayType displayId);
-
-    bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
-    bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
-
-    EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList);
-    EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
-    EGLContext createContext(EGLConfig configHandle, 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(EGLNativeWindowType window);
-
-    rx::Renderer *getRenderer() { return mRenderer; };
-
-    // exported methods must be virtual
-    virtual void notifyDeviceLost();
-    virtual void recreateSwapChains();
-
-    const char *getExtensionString() const;
-    const char *getVendorString() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Display);
-
-    Display(EGLNativeDisplayType displayId, HDC deviceContext);
-
-    bool restoreLostDevice();
-
-    EGLNativeDisplayType mDisplayId;
-    const HDC mDc;
-
-    bool mSoftwareDevice;
-    
-    typedef std::set<Surface*> SurfaceSet;
-    SurfaceSet mSurfaceSet;
-
-    ConfigSet mConfigSet;
-
-    typedef std::set<gl::Context*> ContextSet;
-    ContextSet mContextSet;
-
-    rx::Renderer *mRenderer;
-
-    void initExtensionString();
-    void initVendorString();
-    std::string mExtensionString;
-    std::string mVendorString;
-};
-}
-
-#endif   // LIBEGL_DISPLAY_H_
diff --git a/src/third_party/angle/src/libEGL/Surface.cpp b/src/third_party/angle/src/libEGL/Surface.cpp
deleted file mode 100644
index 1d387d4..0000000
--- a/src/third_party/angle/src/libEGL/Surface.cpp
+++ /dev/null
@@ -1,369 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
-// such as the client area of a window, including any back buffers.
-// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
-
-#include <tchar.h>
-
-#include "libEGL/Surface.h"
-
-#include "common/debug.h"
-#include "common/system.h"
-#include "common/windowutils.h"
-
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/renderer/SwapChain.h"
-#include "libGLESv2/main.h"
-
-#include "libEGL/main.h"
-#include "libEGL/Display.h"
-
-namespace egl
-{
-
-Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint postSubBufferSupported)
-    : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported), mWindowSubclass(NULL)
-{
-    mRenderer = mDisplay->getRenderer();
-    mSwapChain = NULL;
-    mShareHandle = NULL;
-    mTexture = NULL;
-    mTextureFormat = EGL_NO_TEXTURE;
-    mTextureTarget = EGL_NO_TEXTURE;
-
-    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio
-    mRenderBuffer = EGL_BACK_BUFFER;
-    mSwapBehavior = EGL_BUFFER_PRESERVED;
-    mSwapInterval = -1;
-    mWidth = -1;
-    mHeight = -1;
-    setSwapInterval(1);
-}
-
-Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
-  : mDisplay(display), mWindow(ANGLE_NO_WINDOW), mConfig(config), mShareHandle(shareHandle), mWidth(width)
-  , mHeight(height), mPostSubBufferSupported(EGL_FALSE), mWindowSubclass(NULL)
-{
-    mRenderer = mDisplay->getRenderer();
-    mSwapChain = NULL;
-    mTexture = NULL;
-    mTextureFormat = textureFormat;
-    mTextureTarget = textureType;
-
-    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio
-    mRenderBuffer = EGL_BACK_BUFFER;
-    mSwapBehavior = EGL_BUFFER_PRESERVED;
-    mSwapInterval = -1;
-    setSwapInterval(1);
-}
-
-Surface::~Surface()
-{
-    release();
-}
-
-bool Surface::initialize()
-{
-    if (hasWindow())
-        mWindowSubclass = createWindowSubclass(this, mWindow);
-
-    if (!resetSwapChain())
-      return false;
-
-    return true;
-}
-
-void Surface::release()
-{
-    if (mWindowSubclass)
-    {
-        delete mWindowSubclass;
-        mWindowSubclass = NULL;
-    }
-
-    if (mSwapChain)
-    {
-      delete mSwapChain;
-      mSwapChain = NULL;
-    }
-
-    if (mTexture)
-    {
-        mTexture->releaseTexImage();
-        mTexture = NULL;
-    }
-}
-
-bool Surface::resetSwapChain()
-{
-    ASSERT(!mSwapChain);
-
-    EGLint width, height;
-
-    if (hasWindow())
-    {
-        if (!mWindowSubclass || !mWindowSubclass->getWindowSize(&width, &height))
-        {
-            ASSERT(false);
-
-            ERR("Could not retrieve the window dimensions");
-            return error(EGL_BAD_SURFACE, false);
-        }
-    }
-    else
-    {
-        // non-window surface - size is determined at creation
-        width = mWidth;
-        height = mHeight;
-    }
-
-    mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle,
-                                            mConfig->mRenderTargetFormat,
-                                            mConfig->mDepthStencilFormat);
-    if (!mSwapChain)
-    {
-        return error(EGL_BAD_ALLOC, false);
-    }
-
-    if (!resetSwapChain(width, height))
-    {
-        delete mSwapChain;
-        mSwapChain = NULL;
-        return false;
-    }
-
-    return true;
-}
-
-bool Surface::resizeSwapChain(EGLint backbufferWidth, EGLint backbufferHeight)
-{
-    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
-    ASSERT(mSwapChain);
-
-    EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight);
-
-    if (status == EGL_CONTEXT_LOST)
-    {
-        mDisplay->notifyDeviceLost();
-        return false;
-    }
-    else if (status != EGL_SUCCESS)
-    {
-        return error(status, false);
-    }
-
-    mWidth = backbufferWidth;
-    mHeight = backbufferHeight;
-
-    return true;
-}
-
-bool Surface::resetSwapChain(EGLint backbufferWidth, EGLint backbufferHeight)
-{
-    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
-    ASSERT(mSwapChain);
-
-    EGLint status = mSwapChain->reset(backbufferWidth, backbufferHeight, mSwapInterval);
-
-    if (status == EGL_CONTEXT_LOST)
-    {
-        mRenderer->notifyDeviceLost();
-        return false;
-    }
-    else if (status != EGL_SUCCESS)
-    {
-        return error(status, false);
-    }
-
-    mWidth = backbufferWidth;
-    mHeight = backbufferHeight;
-    mSwapIntervalDirty = false;
-
-    return true;
-}
-
-bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
-{
-    if (!mSwapChain)
-    {
-        return true;
-    }
-
-    if (x + width > mWidth)
-    {
-        width = mWidth - x;
-    }
-
-    if (y + height > mHeight)
-    {
-        height = mHeight - y;
-    }
-
-    if (width == 0 || height == 0)
-    {
-        return true;
-    }
-
-    EGLint status = mSwapChain->swapRect(x, y, width, height);
-
-    if (status == EGL_CONTEXT_LOST)
-    {
-        mRenderer->notifyDeviceLost();
-        return false;
-    }
-    else if (status != EGL_SUCCESS)
-    {
-        return error(status, false);
-    }
-
-    checkForOutOfDateSwapChain();
-
-    return true;
-}
-
-#if defined(ANGLE_WIN32)
-WindowSubclass *CreateWindowSubclassWin32(Surface *, EGLNativeWindowType);
-#elif defined(ANGLE_WINRT)
-WindowSubclass *CreateWindowSubclassWinRT(Surface *, EGLNativeWindowType);
-#endif
-
-WindowSubclass *Surface::createWindowSubclass(Surface *surface, EGLNativeWindowType window)
-{
-#if defined(ANGLE_WIN32)
-    return CreateWindowSubclassWin32(surface, window);
-#elif defined(ANGLE_WINRT)
-    return CreateWindowSubclassWinRT(surface, window);
-#endif
-    return NULL;
-}
-
-bool Surface::hasWindow() const
-{
-    return (mWindow != ANGLE_NO_WINDOW);
-}
-
-bool Surface::compareWindow(EGLNativeWindowType window) const
-{
-    return (mWindow == window);
-}
-
-bool Surface::checkForOutOfDateSwapChain()
-{
-    if (!mWindowSubclass)
-    {
-      return false;
-    }
-
-    EGLint clientWidth, clientHeight;
-
-    if (!mWindowSubclass->getWindowSize(&clientWidth, &clientHeight))
-    {
-        ASSERT(false);
-        return false;
-    }
-
-    // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
-    bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
-
-    if (mSwapIntervalDirty)
-    {
-        resetSwapChain(clientWidth, clientHeight);
-    }
-    else if (sizeDirty)
-    {
-        resizeSwapChain(clientWidth, clientHeight);
-    }
-
-    if (mSwapIntervalDirty || sizeDirty)
-    {
-        if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
-        {
-            glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
-bool Surface::swap()
-{
-    return swapRect(0, 0, mWidth, mHeight);
-}
-
-bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
-{
-    if (!mPostSubBufferSupported)
-    {
-        // Spec is not clear about how this should be handled.
-        return true;
-    }
-
-    return swapRect(x, y, width, height);
-}
-
-EGLint Surface::getWidth() const
-{
-    return mWidth;
-}
-
-EGLint Surface::getHeight() const
-{
-    return mHeight;
-}
-
-EGLint Surface::isPostSubBufferSupported() const
-{
-    return mPostSubBufferSupported;
-}
-
-rx::SwapChain *Surface::getSwapChain() const
-{
-    return mSwapChain;
-}
-
-void Surface::setSwapInterval(EGLint interval)
-{
-    if (mSwapInterval == interval)
-    {
-        return;
-    }
-
-    mSwapInterval = interval;
-    mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval());
-    mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval());
-
-    mSwapIntervalDirty = true;
-}
-
-EGLenum Surface::getTextureFormat() const
-{
-    return mTextureFormat;
-}
-
-EGLenum Surface::getTextureTarget() const
-{
-    return mTextureTarget;
-}
-
-void Surface::setBoundTexture(gl::Texture2D *texture)
-{
-    mTexture = texture;
-}
-
-gl::Texture2D *Surface::getBoundTexture() const
-{
-    return mTexture;
-}
-
-EGLenum Surface::getFormat() const
-{
-    return mConfig->mRenderTargetFormat;
-}
-}
diff --git a/src/third_party/angle/src/libEGL/Surface.h b/src/third_party/angle/src/libEGL/Surface.h
deleted file mode 100644
index 1ce5f51..0000000
--- a/src/third_party/angle/src/libEGL/Surface.h
+++ /dev/null
@@ -1,119 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Surface.h: Defines the egl::Surface class, representing a drawing surface
-// such as the client area of a window, including any back buffers.
-// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
-
-#ifndef LIBEGL_SURFACE_H_
-#define LIBEGL_SURFACE_H_
-
-#define EGLAPI
-#include <EGL/egl.h>
-
-#include "common/angleutils.h"
-#include "common/system.h"
-
-namespace gl
-{
-class Texture2D;
-}
-namespace rx
-{
-class Renderer;
-class SwapChain;
-}
-
-namespace egl
-{
-class Display;
-class Config;
-class Surface;
-
-class WindowSubclass
-{
-  public:
-      virtual ~WindowSubclass() {}
-      virtual bool getWindowSize(EGLint *width, EGLint *height) = 0;
-};
-
-class Surface
-{
-  public:
-    Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint postSubBufferSupported);
-    Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);
-
-    ~Surface();
-
-    bool initialize();
-    void release();
-    bool resetSwapChain();
-
-    bool hasWindow() const;
-    bool compareWindow(EGLNativeWindowType window) const;
-
-    bool swap();
-    bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
-
-    virtual EGLint getWidth() const;
-    virtual EGLint getHeight() const;
-
-    virtual EGLint isPostSubBufferSupported() const;
-
-    virtual rx::SwapChain *getSwapChain() const;
-
-    void setSwapInterval(EGLint interval);
-    bool checkForOutOfDateSwapChain();   // Returns true if swapchain changed due to resize or interval update
-
-    virtual EGLenum getTextureFormat() const;
-    virtual EGLenum getTextureTarget() const;
-    virtual EGLenum getFormat() const;
-
-    virtual void setBoundTexture(gl::Texture2D *texture);
-    virtual gl::Texture2D *getBoundTexture() const;
-
-private:
-    DISALLOW_COPY_AND_ASSIGN(Surface);
-
-    bool resizeSwapChain(EGLint backbufferWidth, EGLint backbufferHeight);
-    bool resetSwapChain(EGLint backbufferWidth, EGLint backbufferHeight);
-    bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
-
-    static WindowSubclass *createWindowSubclass(Surface *surface, EGLNativeWindowType window);
-    WindowSubclass *mWindowSubclass;
-
-    Display *const mDisplay;
-    rx::Renderer *mRenderer;
-
-    HANDLE mShareHandle;
-    rx::SwapChain *mSwapChain;
-
-    const EGLNativeWindowType mWindow;   // Window that the surface is created for.
-    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
-//  EGLint mipmapLevel;                  // Mipmap level to render to
-//  EGLenum multisampleResolve;          // Multisample resolve behavior
-    EGLint mPixelAspectRatio;            // Display aspect ratio
-    EGLenum mRenderBuffer;               // Render buffer
-    EGLenum mSwapBehavior;               // Buffer swap behavior
-    EGLenum mTextureFormat;              // Format of texture: RGB, RGBA, or no texture
-    EGLenum mTextureTarget;              // Type of texture: 2D or no texture
-//  EGLenum vgAlphaFormat;               // Alpha format for OpenVG
-//  EGLenum vgColorSpace;                // Color space for OpenVG
-    EGLint mSwapInterval;
-    EGLint mPostSubBufferSupported;
-    
-    bool mSwapIntervalDirty;
-    gl::Texture2D *mTexture;
-};
-}
-
-#endif   // LIBEGL_SURFACE_H_
diff --git a/src/third_party/angle/src/libEGL/libEGL.cpp b/src/third_party/angle/src/libEGL/libEGL.cpp
index f5dd763..30ce081 100644
--- a/src/third_party/angle/src/libEGL/libEGL.cpp
+++ b/src/third_party/angle/src/libEGL/libEGL.cpp
@@ -1,1391 +1,378 @@
 //
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// 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.
 //
 
 // libEGL.cpp: Implements the exported EGL functions.
 
-#include <exception>
-
-#include "common/debug.h"
-#include "common/version.h"
-#include "common/windowutils.h"
-#include "libGLESv2/Context.h"
-#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"
-
-bool validateDisplay(egl::Display *display)
-{
-    if (display == EGL_NO_DISPLAY)
-    {
-        return egl::error(EGL_BAD_DISPLAY, false);
-    }
-
-    if (!display->isInitialized())
-    {
-        return egl::error(EGL_NOT_INITIALIZED, false);
-    }
-
-    return true;
-}
-
-bool validateConfig(egl::Display *display, EGLConfig config)
-{
-    if (!validateDisplay(display))
-    {
-        return false;
-    }
-
-    if (!display->isValidConfig(config))
-    {
-        return egl::error(EGL_BAD_CONFIG, false);
-    }
-
-    return true;
-}
-
-bool validateContext(egl::Display *display, gl::Context *context)
-{
-    if (!validateDisplay(display))
-    {
-        return false;
-    }
-
-    if (!display->isValidContext(context))
-    {
-        return egl::error(EGL_BAD_CONTEXT, false);
-    }
-
-    return true;
-}
-
-bool validateSurface(egl::Display *display, egl::Surface *surface)
-{
-    if (!validateDisplay(display))
-    {
-        return false;
-    }
-
-    if (!display->isValidSurface(surface))
-    {
-        return egl::error(EGL_BAD_SURFACE, false);
-    }
-
-    return true;
-}
+#include "libGLESv2/entry_points_egl.h"
+#include "libGLESv2/entry_points_egl_ext.h"
 
 extern "C"
 {
-EGLint __stdcall eglGetError(void)
+
+EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
 {
-    EVENT("()");
-
-    EGLint error = egl::getCurrentError();
-
-    if (error != EGL_SUCCESS)
-    {
-        egl::setCurrentError(EGL_SUCCESS);
-    }
-
-    return error;
+    return egl::ChooseConfig(dpy, attrib_list, configs, config_size, num_config);
 }
 
-EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
+EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p)", display_id);
-#else
-    EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
-#endif
-
-    try
-    {
-        return egl::Display::getDisplay(display_id);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
-    }
+    return egl::CopyBuffers(dpy, surface, target);
 }
 
-EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, 0x%0.8p)",
-          dpy, major, minor);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",
-          dpy, major, minor);
-#endif
-
-    try
-    {
-        if (dpy == EGL_NO_DISPLAY)
-        {
-            return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
-        }
-
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!display->initialize())
-        {
-            return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE);
-        }
-
-        if (major) *major = 1;
-        if (minor) *minor = 4;
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::CreateContext(dpy, config, share_context, attrib_list);
 }
 
-EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
+EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p)", dpy);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy);
-#endif
-
-    try
-    {
-        if (dpy == EGL_NO_DISPLAY)
-        {
-            return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
-        }
-
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        display->terminate();
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::CreatePbufferSurface(dpy, config, attrib_list);
 }
 
-const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
+EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, %d)", dpy, name);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateDisplay(display))
-        {
-            return NULL;
-        }
-
-        switch (name)
-        {
-          case EGL_CLIENT_APIS:
-            return egl::success("OpenGL_ES");
-          case EGL_EXTENSIONS:
-            return egl::success(display->getExtensionString());
-          case EGL_VENDOR:
-            return egl::success(display->getVendorString());
-          case EGL_VERSION:
-            return egl::success("1.4 (ANGLE " VERSION_STRING ")");
-        }
-
-        return egl::error(EGL_BAD_PARAMETER, (const char*)NULL);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, (const char*)NULL);
-    }
+    return egl::CreatePixmapSurface(dpy, config, pixmap, attrib_list);
 }
 
-EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, %d, 0x%0.8p)",
-          dpy, configs, config_size, num_config);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
-          "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
-          dpy, configs, config_size, num_config);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateDisplay(display))
-        {
-            return EGL_FALSE;
-        }
-
-        if (!num_config)
-        {
-            return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
-        }
-
-        const EGLint attribList[] =    {EGL_NONE};
-
-        if (!display->getConfigs(configs, attribList, config_size, num_config))
-        {
-            return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
-        }
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::CreateWindowSurface(dpy, config, win, attrib_list);
 }
 
-EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, 0x%0.8p, %d, 0x%0.8p)",
-          dpy, attrib_list, configs, config_size, num_config);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
-          "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
-          dpy, attrib_list, configs, config_size, num_config);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateDisplay(display))
-        {
-            return EGL_FALSE;
-        }
-
-        if (!num_config)
-        {
-            return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
-        }
-
-        const EGLint attribList[] =    {EGL_NONE};
-
-        if (!attrib_list)
-        {
-            attrib_list = attribList;
-        }
-
-        display->getConfigs(configs, attrib_list, config_size, num_config);
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::DestroyContext(dpy, ctx);
 }
 
-EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, %d, 0x%0.8p)",
-          dpy, config, attribute, value);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
-          dpy, config, attribute, value);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateConfig(display, config))
-        {
-            return EGL_FALSE;
-        }
-
-        if (!display->getConfigAttrib(config, attribute, value))
-        {
-            return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
-        }
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::DestroySurface(dpy, surface);
 }
 
-EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, 0x%0.8p, 0x%0.8p)", dpy, config, win, attrib_list);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
-          "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateConfig(display, config))
-        {
-            return EGL_NO_SURFACE;
-        }
-
-        if (!egl::verifyWindowAccessible(win))
-        {
-            return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
-        }
-
-        return display->createWindowSurface(win, config, attrib_list);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-    }
+    return egl::GetConfigAttrib(dpy, config, attribute, value);
 }
 
-EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, 0x%0.8p)",
-          dpy, config, attrib_list);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
-          dpy, config, attrib_list);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateConfig(display, config))
-        {
-            return EGL_NO_SURFACE;
-        }
-
-        return display->createOffscreenSurface(config, NULL, attrib_list);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-    }
+    return egl::GetConfigs(dpy, configs, config_size, num_config);
 }
 
-EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
+EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, 0x%0.8p, 0x%0.8p)", dpy, config, pixmap, attrib_list);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "
-          "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateConfig(display, config))
-        {
-            return EGL_NO_SURFACE;
-        }
-
-        UNIMPLEMENTED();   // FIXME
-
-        return egl::success(EGL_NO_SURFACE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-    }
+    return egl::GetCurrentDisplay();
 }
 
-EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p)", dpy, surface);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
-        if (!validateSurface(display, eglSurface))
-        {
-            return EGL_FALSE;
-        }
-
-        if (surface == EGL_NO_SURFACE)
-        {
-            return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
-        }
-
-        display->destroySurface((egl::Surface*)surface);
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::GetCurrentSurface(readdraw);
 }
 
-EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, %d, 0x%0.8p)",
-          dpy, surface, attribute, value);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
-          dpy, surface, attribute, value);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        egl::Surface *eglSurface = (egl::Surface*)surface;
-
-        if (!validateSurface(display, eglSurface))
-        {
-            return EGL_FALSE;
-        }
-
-        if (surface == EGL_NO_SURFACE)
-        {
-            return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
-        }
-
-        switch (attribute)
-        {
-          case EGL_VG_ALPHA_FORMAT:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_VG_COLORSPACE:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_CONFIG_ID:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_HEIGHT:
-            *value = eglSurface->getHeight();
-            break;
-          case EGL_HORIZONTAL_RESOLUTION:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_LARGEST_PBUFFER:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_MIPMAP_TEXTURE:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_MIPMAP_LEVEL:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_MULTISAMPLE_RESOLVE:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_PIXEL_ASPECT_RATIO:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_RENDER_BUFFER:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_SWAP_BEHAVIOR:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_TEXTURE_FORMAT:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_TEXTURE_TARGET:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_VERTICAL_RESOLUTION:
-            UNIMPLEMENTED();   // FIXME
-            break;
-          case EGL_WIDTH:
-            *value = eglSurface->getWidth();
-            break;
-          case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
-            *value = eglSurface->isPostSubBufferSupported();
-            break;
-          default:
-            return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
-        }
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::GetDisplay(display_id);
 }
 
-EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+EGLint EGLAPIENTRY eglGetError(void)
 {
-    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
-          dpy, surface, attribute, value);
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        egl::Surface *eglSurface = (egl::Surface*)surface;
-
-        if (!validateSurface(display, eglSurface))
-        {
-            return EGL_FALSE;
-        }
-
-        if (surface == EGL_NO_SURFACE)
-        {
-            return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
-        }
-
-        switch (attribute)
-        {
-          case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
-            {
-                rx::SwapChain *swapchain = eglSurface->getSwapChain();
-                *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL);
-            }
-            break;
-          default:
-            return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
-        }
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::GetError();
 }
 
-EGLBoolean __stdcall eglQueryD3DDeviceANGLE(EGLDisplay dpy, void **value)
+EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
 {
-    TRACE("(EGLDisplay dpy = 0x%0.8p, void **value = 0x%0.8p)",
-          dpy, value);
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        if (!display)
-        {
-            return EGL_FALSE;
-        }
-
-        *value = display->getRenderer()->getDeviceRaw();
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::Initialize(dpy, major, minor);
 }
 
-EGLBoolean __stdcall eglSetResourceTrackerANGLE(EGLDisplay dpy, EGLResourceTrackerProcAngle proc, void *user_data)
+EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
 {
-    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLResourceTrackerProcAngle proc = 0x%0.8p, void *user_data = 0x%0.8)",
-          dpy, proc, user_data);
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        if (!display)
-        {
-            return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE);
-        }
-
-        if (display->getRenderer()->setResourceTracker(proc, user_data))
-        {
-            return egl::success(EGL_TRUE);
-        }
-        else
-        {
-            return egl::error(EGL_BAD_MATCH, EGL_FALSE);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::MakeCurrent(dpy, draw, read, ctx);
 }
 
-EGLBoolean __stdcall eglBindAPI(EGLenum api)
+EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", api);
-#else
-    EVENT("(EGLenum api = 0x%X)", api);
-#endif
-
-    try
-    {
-        switch (api)
-        {
-          case EGL_OPENGL_API:
-          case EGL_OPENVG_API:
-            return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation
-          case EGL_OPENGL_ES_API:
-            break;
-          default:
-            return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
-        }
-
-        egl::setCurrentAPI(api);
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::QueryContext(dpy, ctx, attribute, value);
 }
 
-EGLenum __stdcall eglQueryAPI(void)
+const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name)
 {
-    EVENT("()");
-
-    try
-    {
-        EGLenum API = egl::getCurrentAPI();
-
-        return egl::success(API);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::QueryString(dpy, name);
 }
 
-EGLBoolean __stdcall eglWaitClient(void)
+EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
 {
-    EVENT("()");
-
-    try
-    {
-        UNIMPLEMENTED();   // FIXME
-
-        return egl::success(0);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::QuerySurface(dpy, surface, attribute, value);
 }
 
-EGLBoolean __stdcall eglReleaseThread(void)
+EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
 {
-    EVENT("()");
-
-    try
-    {
-        eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::SwapBuffers(dpy, surface);
 }
 
-EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%X, 0x%0.8p, 0x%0.8p, 0x%0.8p)",
-          dpy, buftype, buffer, config, attrib_list);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
-          "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
-          dpy, buftype, buffer, config, attrib_list);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateConfig(display, config))
-        {
-            return EGL_NO_SURFACE;
-        }
-
-        if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
-        {
-            return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
-        }
-
-        return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-    }
+    return egl::Terminate(dpy);
 }
 
-EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+EGLBoolean EGLAPIENTRY eglWaitGL(void)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, %d, %d)",
-          dpy, surface, attribute, value);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
-          dpy, surface, attribute, value);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
-        if (!validateSurface(display, eglSurface))
-        {
-            return EGL_FALSE;
-        }
-
-        UNIMPLEMENTED();   // FIXME
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::WaitGL();
 }
 
-EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, %d)", dpy, surface, buffer);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
-        if (!validateSurface(display, eglSurface))
-        {
-            return EGL_FALSE;
-        }
-
-        if (buffer != EGL_BACK_BUFFER)
-        {
-            return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
-        }
-
-        if (surface == EGL_NO_SURFACE || eglSurface->hasWindow())
-        {
-            return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
-        }
-
-        if (eglSurface->getBoundTexture())
-        {
-            return egl::error(EGL_BAD_ACCESS, EGL_FALSE);
-        }
-
-        if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
-        {
-            return egl::error(EGL_BAD_MATCH, EGL_FALSE);
-        }
-
-        if (!glBindTexImage(eglSurface))
-        {
-            return egl::error(EGL_BAD_MATCH, EGL_FALSE);
-        }
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::WaitNative(engine);
 }
 
-EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, %d)", dpy, surface, buffer);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
-        if (!validateSurface(display, eglSurface))
-        {
-            return EGL_FALSE;
-        }
-
-        if (buffer != EGL_BACK_BUFFER)
-        {
-            return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
-        }
-
-        if (surface == EGL_NO_SURFACE || eglSurface->hasWindow())
-        {
-            return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
-        }
-
-        if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
-        {
-            return egl::error(EGL_BAD_MATCH, EGL_FALSE);
-        }
-
-        gl::Texture2D *texture = eglSurface->getBoundTexture();
-
-        if (texture)
-        {
-            texture->releaseTexImage();
-        }
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::BindTexImage(dpy, surface, buffer);
 }
 
-EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
+EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, %d)", dpy, interval);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateDisplay(display))
-        {
-            return EGL_FALSE;
-        }
-
-        egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
-
-        if (draw_surface == NULL)
-        {
-            return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
-        }
-        
-        draw_surface->setSwapInterval(interval);
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::ReleaseTexImage(dpy, surface, buffer);
 }
 
-EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, 0x%0.8p, 0x%0.8p)", dpy, config, share_context, attrib_list);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
-          "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
-#endif
-
-    try
-    {
-        // Get the requested client version (default is 1) and check it is two.
-        EGLint client_version = 1;
-        bool reset_notification = false;
-        bool robust_access = false;
-
-        if (attrib_list)
-        {
-            for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
-            {
-                switch (attribute[0])
-                {
-                  case EGL_CONTEXT_CLIENT_VERSION:
-                    client_version = attribute[1];
-                    break;
-                  case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
-                    if (attribute[1] == EGL_TRUE)
-                    {
-                        return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);   // Unimplemented
-                        // robust_access = true;
-                    }
-                    else if (attribute[1] != EGL_FALSE)
-                        return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
-                    break;
-                  case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
-                    if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
-                        reset_notification = true;
-                    else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
-                        return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
-                    break;
-                  default:
-                    return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
-                }
-            }
-        }
-
-        if (client_version != 2)
-        {
-            return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
-        }
-
-        if (share_context && static_cast<gl::Context*>(share_context)->isResetNotificationEnabled() != reset_notification)
-        {
-            return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
-        }
-
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-
-        if (!validateConfig(display, config))
-        {
-            return EGL_NO_CONTEXT;
-        }
-
-        EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
-
-        if (context)
-            return egl::success(context);
-        else
-            return egl::error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
-    }
+    return egl::SurfaceAttrib(dpy, surface, attribute, value);
 }
 
-EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p)", dpy, ctx);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        gl::Context *context = static_cast<gl::Context*>(ctx);
-
-        if (!validateContext(display, context))
-        {
-            return EGL_FALSE;
-        }
-
-        if (ctx == EGL_NO_CONTEXT)
-        {
-            return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
-        }
-
-        display->destroyContext(context);
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::SwapInterval(dpy, interval);
 }
 
-EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, 0x%0.8p, 0x%0.8p)",
-          dpy, draw, read, ctx);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
-          dpy, draw, read, ctx);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        gl::Context *context = static_cast<gl::Context*>(ctx);
-
-        if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
-        {
-            return EGL_FALSE;
-        }
-
-        rx::Renderer *renderer = display->getRenderer();
-        if (renderer->testDeviceLost(true))
-        {
-            return EGL_FALSE;
-        }
-
-        if (renderer->isDeviceLost())
-        {
-            return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
-        }
-
-        if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
-            (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))
-        {
-            return EGL_FALSE;
-        }
-
-        if (draw != read)
-        {
-            UNIMPLEMENTED();   // FIXME
-        }
-
-        egl::setCurrentDisplay(dpy);
-        egl::setCurrentDrawSurface(draw);
-        egl::setCurrentReadSurface(read);
-
-        glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
-
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::BindAPI(api);
 }
 
-EGLContext __stdcall eglGetCurrentContext(void)
+EGLenum EGLAPIENTRY eglQueryAPI(void)
 {
-    EVENT("()");
-
-    try
-    {
-        EGLContext context = glGetCurrentContext();
-
-        return egl::success(context);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
-    }
+    return egl::QueryAPI();
 }
 
-EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
+EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", readdraw);
-#else
-    EVENT("(EGLint readdraw = %d)", readdraw);
-#endif
-
-    try
-    {
-        if (readdraw == EGL_READ)
-        {
-            EGLSurface read = egl::getCurrentReadSurface();
-            return egl::success(read);
-        }
-        else if (readdraw == EGL_DRAW)
-        {
-            EGLSurface draw = egl::getCurrentDrawSurface();
-            return egl::success(draw);
-        }
-        else
-        {
-            return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-    }
+    return egl::CreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list);
 }
 
-EGLDisplay __stdcall eglGetCurrentDisplay(void)
+EGLBoolean EGLAPIENTRY eglReleaseThread(void)
 {
-    EVENT("()");
-
-    try
-    {
-        EGLDisplay dpy = egl::getCurrentDisplay();
-
-        return egl::success(dpy);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
-    }
+    return egl::ReleaseThread();
 }
 
-EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+EGLBoolean EGLAPIENTRY eglWaitClient(void)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, %d, 0x%0.8p)",
-          dpy, ctx, attribute, value);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
-          dpy, ctx, attribute, value);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        gl::Context *context = static_cast<gl::Context*>(ctx);
-
-        if (!validateContext(display, context))
-        {
-            return EGL_FALSE;
-        }
-
-        UNIMPLEMENTED();   // FIXME
-
-        return egl::success(0);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::WaitClient();
 }
 
-EGLBoolean __stdcall eglWaitGL(void)
+EGLContext EGLAPIENTRY eglGetCurrentContext(void)
 {
-    EVENT("()");
-
-    try
-    {
-        UNIMPLEMENTED();   // FIXME
-
-        return egl::success(0);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::GetCurrentContext();
 }
 
-EGLBoolean __stdcall eglWaitNative(EGLint engine)
+EGLSync EGLAPIENTRY eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", engine);
-#else
-    EVENT("(EGLint engine = %d)", engine);
-#endif
-
-    try
-    {
-        UNIMPLEMENTED();   // FIXME
-
-        return egl::success(0);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::CreateSync(dpy, type, attrib_list);
 }
 
-EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
+EGLBoolean EGLAPIENTRY eglDestroySync(EGLDisplay dpy, EGLSync sync)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p)", dpy, surface);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        egl::Surface *eglSurface = (egl::Surface*)surface;
-
-        if (!validateSurface(display, eglSurface))
-        {
-            return EGL_FALSE;
-        }
-
-        if (display->getRenderer()->isDeviceLost())
-        {
-            return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
-        }
-
-        if (surface == EGL_NO_SURFACE)
-        {
-            return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
-        }
-
-        if (eglSurface->swap())
-        {
-            return egl::success(EGL_TRUE);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
-
-    return EGL_FALSE;
+    return egl::DestroySync(dpy, sync);
 }
 
-EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
+EGLint EGLAPIENTRY eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, 0x%0.8p)", dpy, surface, target);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
-        if (!validateSurface(display, eglSurface))
-        {
-            return EGL_FALSE;
-        }
-
-        if (display->getRenderer()->isDeviceLost())
-        {
-            return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
-        }
-
-        UNIMPLEMENTED();   // FIXME
-
-        return egl::success(0);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::ClientWaitSync(dpy, sync, flags, timeout);
 }
 
-EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
+EGLBoolean EGLAPIENTRY eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p, 0x%0.8p, %d, %d, %d, %d)", dpy, surface, x, y, width, height);
-#else
-    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
-#endif
-
-    try
-    {
-        if (x < 0 || y < 0 || width < 0 || height < 0)
-        {
-            return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
-        }
-
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
-        if (!validateSurface(display, eglSurface))
-        {
-            return EGL_FALSE;
-        }
-
-        if (display->getRenderer()->isDeviceLost())
-        {
-            return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
-        }
-
-        if (surface == EGL_NO_SURFACE)
-        {
-            return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
-        }
-
-        if (eglSurface->postSubBuffer(x, y, width, height))
-        {
-            return egl::success(EGL_TRUE);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
-
-    return EGL_FALSE;
+    return egl::GetSyncAttrib(dpy, sync, attribute, value);
 }
 
-#if defined(__LB_XB360__)
-EGLBoolean __stdcall eglSetPlayerLBSHELL(EGLDisplay dpy, void *value)
+EGLImage EGLAPIENTRY eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
 {
-#if defined(__LB_XB360__)
-    TRACE("(0x%0.8p, 0x%0.8p)", dpy, value);
-#else
-    TRACE("(EGLDisplay dpy = 0x%0.8p, void *value = 0x%0.8p)",
-          dpy, value);
-#endif
-
-    try
-    {
-        egl::Display *display = static_cast<egl::Display*>(dpy);
-        if (!display)
-        {
-            return EGL_FALSE;
-        }
-
-        display->getRenderer()->setPlayerRaw(value);
-        return egl::success(EGL_TRUE);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, EGL_FALSE);
-    }
+    return egl::CreateImage(dpy, ctx, target, buffer, attrib_list);
 }
-#endif
 
-__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
+EGLBoolean EGLAPIENTRY eglDestroyImage(EGLDisplay dpy, EGLImage image)
 {
-#if defined(__LB_XB360__)
-    EVENT("(\"%s\")", procname);
-#else
-    EVENT("(const char *procname = \"%s\")", procname);
-#endif
+    return egl::DestroyImage(dpy, image);
+}
 
-    try
-    {
-        struct Extension
-        {
-            const char *name;
-            __eglMustCastToProperFunctionPointerType address;
-        };
+EGLDisplay EGLAPIENTRY eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
+{
+    return egl::GetPlatformDisplay(platform, native_display, attrib_list);
+}
 
-        static const Extension eglExtensions[] =
-        {
-            {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
-            {"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV},
-#if defined(__LB_SHELL__)
-            {"eglQueryD3DDeviceANGLE", (__eglMustCastToProperFunctionPointerType)eglQueryD3DDeviceANGLE},
-            {"eglSetResourceTrackerANGLE", (__eglMustCastToProperFunctionPointerType)eglSetResourceTrackerANGLE},
-#if defined(__LB_XB360__)
-            {"eglSetPlayerLBSHELL", (__eglMustCastToProperFunctionPointerType)eglSetPlayerLBSHELL},
-#endif
-#endif
-            {"", NULL},
-        };
+EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list)
+{
+    return egl::CreatePlatformWindowSurface(dpy, config, native_window, attrib_list);
+}
 
-        for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++)
-        {
-            if (strcmp(procname, eglExtensions[ext].name) == 0)
-            {
-                return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
-            }
-        }
+EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list)
+{
+    return egl::CreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list);
+}
 
-        return glGetProcAddress(procname);
-    }
-    catch(std::bad_alloc&)
-    {
-        return egl::error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);
-    }
+EGLBoolean EGLAPIENTRY eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
+{
+    return egl::WaitSync(dpy, sync, flags);
+}
+
+EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+{
+    return egl::QuerySurfacePointerANGLE(dpy, surface, attribute, value);
+}
+
+EGLBoolean EGLAPIENTRY eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    return egl::PostSubBufferNV(dpy, surface, x, y, width, height);
+}
+
+EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
+{
+    return egl::GetPlatformDisplayEXT(platform, native_display, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value)
+{
+    return egl::QueryDisplayAttribEXT(dpy, attribute, value);
+}
+
+EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value)
+{
+    return egl::QueryDeviceAttribEXT(device, attribute, value);
+}
+
+const char * EGLAPIENTRY eglQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
+{
+    return egl::QueryDeviceStringEXT(device, name);
+}
+
+EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay dpy,
+                                          EGLContext ctx,
+                                          EGLenum target,
+                                          EGLClientBuffer buffer,
+                                          const EGLint *attrib_list)
+{
+    return egl::CreateImageKHR(dpy, ctx, target, buffer, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
+{
+    return egl::DestroyImageKHR(dpy, image);
+}
+
+EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE(EGLint device_type,
+                                              void *native_device,
+                                              const EGLAttrib *attrib_list)
+{
+    return egl::CreateDeviceANGLE(device_type, native_device, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE(EGLDeviceEXT device)
+{
+    return egl::ReleaseDeviceANGLE(device);
+}
+
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)
+{
+    return egl::GetProcAddress(procname);
+}
+
+EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
+{
+    return egl::CreateStreamKHR(dpy, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+    return egl::DestroyStreamKHR(dpy, stream);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamAttribKHR(EGLDisplay dpy,
+                                          EGLStreamKHR stream,
+                                          EGLenum attribute,
+                                          EGLint value)
+{
+    return egl::StreamAttribKHR(dpy, stream, attribute, value);
+}
+
+EGLBoolean EGLAPIENTRY eglQueryStreamKHR(EGLDisplay dpy,
+                                         EGLStreamKHR stream,
+                                         EGLenum attribute,
+                                         EGLint *value)
+{
+    return egl::QueryStreamKHR(dpy, stream, attribute, value);
+}
+
+EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR(EGLDisplay dpy,
+                                            EGLStreamKHR stream,
+                                            EGLenum attribute,
+                                            EGLuint64KHR *value)
+{
+    return egl::QueryStreamu64KHR(dpy, stream, attribute, value);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+    return egl::StreamConsumerGLTextureExternalKHR(dpy, stream);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+    return egl::StreamConsumerAcquireKHR(dpy, stream);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+    return egl::StreamConsumerReleaseKHR(dpy, stream);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,
+                                                                   EGLStreamKHR stream,
+                                                                   EGLAttrib *attrib_list)
+{
+    return egl::StreamConsumerGLTextureExternalAttribsNV(dpy, stream, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglCreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy,
+                                                                  EGLStreamKHR stream,
+                                                                  const EGLAttrib *attrib_list)
+{
+    return egl::CreateStreamProducerD3DTextureNV12ANGLE(dpy, stream, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy,
+                                                        EGLStreamKHR stream,
+                                                        void *texture,
+                                                        const EGLAttrib *attrib_list)
+{
+    return egl::StreamPostD3DTextureNV12ANGLE(dpy, stream, texture, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglGetSyncValuesCHROMIUM(EGLDisplay dpy,
+                                                EGLSurface surface,
+                                                EGLuint64KHR *ust,
+                                                EGLuint64KHR *msc,
+                                                EGLuint64KHR *sbc)
+{
+    return egl::GetSyncValuesCHROMIUM(dpy, surface, ust, msc, sbc);
+}
+
+EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT(EGLDisplay dpy,
+                                                   EGLSurface surface,
+                                                   EGLint *rects,
+                                                   EGLint n_rects)
+{
+    return egl::SwapBuffersWithDamageEXT(dpy, surface, rects, n_rects);
 }
 }
diff --git a/src/third_party/angle/src/libEGL/libEGL.def b/src/third_party/angle/src/libEGL/libEGL.def
index 71a5e67..1fe3371 100644
--- a/src/third_party/angle/src/libEGL/libEGL.def
+++ b/src/third_party/angle/src/libEGL/libEGL.def
@@ -1,36 +1,73 @@
-LIBRARY	libEGL
+LIBRARY libEGL
 EXPORTS
-	eglBindAPI                      @14
-	eglBindTexImage                 @20
-	eglChooseConfig                 @7
-	eglCopyBuffers                  @33
-	eglCreateContext                @23
-	eglCreatePbufferFromClientBuffer        @18
-	eglCreatePbufferSurface         @10
-	eglCreatePixmapSurface          @11
-	eglCreateWindowSurface          @9
-	eglDestroyContext               @24
-	eglDestroySurface               @12
-	eglGetConfigAttrib              @8
-	eglGetConfigs                   @6
-	eglGetCurrentContext            @26
-	eglGetCurrentDisplay            @28
-	eglGetCurrentSurface            @27
-	eglGetDisplay                   @2
-	eglGetError                     @1
-	eglGetProcAddress               @34
-	eglInitialize                   @3
-	eglMakeCurrent                  @25
-	eglQueryAPI                     @15
-	eglQueryContext                 @29
-	eglQueryString                  @5
-	eglQuerySurface                 @13
-	eglReleaseTexImage              @21
-	eglReleaseThread                @17
-	eglSurfaceAttrib                @19
-	eglSwapBuffers                  @32
-	eglSwapInterval                 @22
-	eglTerminate                    @4
-	eglWaitClient                   @16
-	eglWaitGL                       @30
-	eglWaitNative                   @31
\ No newline at end of file
+    eglBindAPI                                  @14
+    eglBindTexImage                             @20
+    eglChooseConfig                             @7
+    eglCopyBuffers                              @33
+    eglCreateContext                            @23
+    eglCreatePbufferFromClientBuffer            @18
+    eglCreatePbufferSurface                     @10
+    eglCreatePixmapSurface                      @11
+    eglCreateWindowSurface                      @9
+    eglDestroyContext                           @24
+    eglDestroySurface                           @12
+    eglGetConfigAttrib                          @8
+    eglGetConfigs                               @6
+    eglGetCurrentContext                        @26
+    eglGetCurrentDisplay                        @28
+    eglGetCurrentSurface                        @27
+    eglGetDisplay                               @2
+    eglGetError                                 @1
+    eglGetProcAddress                           @34
+    eglInitialize                               @3
+    eglMakeCurrent                              @25
+    eglQueryAPI                                 @15
+    eglQueryContext                             @29
+    eglQueryString                              @5
+    eglQuerySurface                             @13
+    eglReleaseTexImage                          @21
+    eglReleaseThread                            @17
+    eglSurfaceAttrib                            @19
+    eglSwapBuffers                              @32
+    eglSwapInterval                             @22
+    eglTerminate                                @4
+    eglWaitClient                               @16
+    eglWaitGL                                   @30
+    eglWaitNative                               @31
+
+    ; Extensions
+    eglGetPlatformDisplayEXT                    @35
+    eglQuerySurfacePointerANGLE                 @36
+    eglPostSubBufferNV                          @37
+    eglQueryDisplayAttribEXT                    @48
+    eglQueryDeviceAttribEXT                     @49
+    eglQueryDeviceStringEXT                     @50
+    eglCreateImageKHR                           @51
+    eglDestroyImageKHR                          @52
+    eglCreateDeviceANGLE                        @53
+    eglReleaseDeviceANGLE                       @54
+    eglCreateStreamKHR                          @55
+    eglDestroyStreamKHR                         @56
+    eglStreamAttribKHR                          @57
+    eglQueryStreamKHR                           @58
+    eglQueryStreamu64KHR                        @59
+    eglStreamConsumerGLTextureExternalKHR       @60
+    eglStreamConsumerAcquireKHR                 @61
+    eglStreamConsumerReleaseKHR                 @62
+    eglStreamConsumerGLTextureExternalAttribsNV @63
+    eglCreateStreamProducerD3DTextureNV12ANGLE  @64
+    eglStreamPostD3DTextureNV12ANGLE            @65
+    eglGetSyncValuesCHROMIUM                    @66
+    eglSwapBuffersWithDamageEXT                 @67
+
+    ; 1.5 entry points
+    eglCreateSync                               @38
+    eglDestroySync                              @39
+    eglClientWaitSync                           @40
+    eglGetSyncAttrib                            @41
+    eglCreateImage                              @42
+    eglDestroyImage                             @43
+    eglGetPlatformDisplay                       @44
+    eglCreatePlatformWindowSurface              @45
+    eglCreatePlatformPixmapSurface              @46
+    eglWaitSync                                 @47
diff --git a/src/third_party/angle/src/libEGL/libEGL.rc b/src/third_party/angle/src/libEGL/libEGL.rc
index 5d1f32f..acffcef 100644
--- a/src/third_party/angle/src/libEGL/libEGL.rc
+++ b/src/third_party/angle/src/libEGL/libEGL.rc
@@ -1,102 +1,103 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include <windows.h>
-#include "../common/version.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "#include ""../common/version.h""\0"
-END
-
-3 TEXTINCLUDE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
- PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-            VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library"
-            VALUE "FileVersion", VERSION_STRING
-            VALUE "InternalName", "libEGL"
-            VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc."
-            VALUE "OriginalFilename", "libEGL.dll"
-            VALUE "PrivateBuild", VERSION_STRING
-            VALUE "ProductName", "ANGLE libEGL Dynamic Link Library"
-            VALUE "ProductVersion", VERSION_STRING
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
+// Microsoft Visual C++ generated resource script.

+//

+#include "resource.h"

+

+#define APSTUDIO_READONLY_SYMBOLS

+/////////////////////////////////////////////////////////////////////////////

+//

+// Generated from the TEXTINCLUDE 2 resource.

+//

+#include <windows.h>

+#include "../common/version.h"

+

+/////////////////////////////////////////////////////////////////////////////

+#undef APSTUDIO_READONLY_SYMBOLS

+

+/////////////////////////////////////////////////////////////////////////////

+// English (U.S.) resources

+

+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)

+#ifdef _WIN32

+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

+#pragma code_page(1252)

+#endif //_WIN32

+

+#ifdef APSTUDIO_INVOKED

+/////////////////////////////////////////////////////////////////////////////

+//

+// TEXTINCLUDE

+//

+

+1 TEXTINCLUDE 

+BEGIN

+    "resource.h\0"

+END

+

+2 TEXTINCLUDE 

+BEGIN

+    "#include ""afxres.h""\r\n"

+    "#include ""../common/version.h""\0"

+END

+

+3 TEXTINCLUDE 

+BEGIN

+    "\r\n"

+    "\0"

+END

+

+#endif    // APSTUDIO_INVOKED

+

+

+/////////////////////////////////////////////////////////////////////////////

+//

+// Version

+//

+

+VS_VERSION_INFO VERSIONINFO

+ FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,ANGLE_REVISION,0

+ PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,ANGLE_REVISION,0

+ FILEFLAGSMASK 0x17L

+#ifdef _DEBUG

+ FILEFLAGS 0x1L

+#else

+ FILEFLAGS 0x0L

+#endif

+ FILEOS 0x4L

+ FILETYPE 0x2L

+ FILESUBTYPE 0x0L

+BEGIN

+    BLOCK "StringFileInfo"

+    BEGIN

+        BLOCK "040904b0"

+        BEGIN

+            VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library"

+            VALUE "FileVersion", ANGLE_VERSION_STRING

+            VALUE "InternalName", "libEGL"

+            VALUE "LegalCopyright", "Copyright (C) 2015 Google Inc."

+            VALUE "OriginalFilename", "libEGL.dll"

+            VALUE "PrivateBuild", ANGLE_VERSION_STRING

+            VALUE "ProductName", "ANGLE libEGL Dynamic Link Library"

+            VALUE "ProductVersion", ANGLE_VERSION_STRING

+            VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE

+        END

+    END

+    BLOCK "VarFileInfo"

+    BEGIN

+        VALUE "Translation", 0x409, 1200

+    END

+END

+

+#endif    // English (U.S.) resources

+/////////////////////////////////////////////////////////////////////////////

+

+

+

+#ifndef APSTUDIO_INVOKED

+/////////////////////////////////////////////////////////////////////////////

+//

+// Generated from the TEXTINCLUDE 3 resource.

+//

+

+

+/////////////////////////////////////////////////////////////////////////////

+#endif    // not APSTUDIO_INVOKED

diff --git a/src/third_party/angle/src/libEGL/libEGL.vcxproj b/src/third_party/angle/src/libEGL/libEGL.vcxproj
deleted file mode 100644
index b6bc1ef..0000000
--- a/src/third_party/angle/src/libEGL/libEGL.vcxproj
+++ /dev/null
@@ -1,258 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Debug|x64">

-      <Configuration>Debug</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|x64">

-      <Configuration>Release</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}</ProjectGuid>

-    <RootNamespace>libEGL</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>

-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(LibraryPath)</LibraryPath>

-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(DXSDK_DIR)\lib\x86;$(LibraryPath)</LibraryPath>

-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(LibraryPath)</LibraryPath>

-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(LibraryPath)</LibraryPath>

-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(DXSDK_DIR)\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;</IncludePath>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>$(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <ModuleDefinitionFile>libEGL.def</ModuleDefinitionFile>

-      <DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Windows</SubSystem>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>%40echo on

-mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"

-%40echo off

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <AdditionalIncludeDirectories>$(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>ANGLE_DISABLE_TRACE;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <ModuleDefinitionFile>libEGL.def</ModuleDefinitionFile>

-      <DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Windows</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>%40echo on

-mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"

-%40echo off

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>$(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <TreatWarningAsError>true</TreatWarningAsError>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <ModuleDefinitionFile>libEGL.def</ModuleDefinitionFile>

-      <DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Windows</SubSystem>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX64</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>%40echo on

-mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"

-%40echo off

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <AdditionalIncludeDirectories>$(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <TreatWarningAsError>true</TreatWarningAsError>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <ModuleDefinitionFile>libEGL.def</ModuleDefinitionFile>

-      <DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Windows</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX64</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>%40echo on

-mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"

-%40echo off

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="Config.cpp" />

-    <ClCompile Include="..\Common\debug.cpp" />

-    <ClCompile Include="Display.cpp" />

-    <ClCompile Include="libEGL.cpp" />

-    <ClCompile Include="main.cpp" />

-    <ClCompile Include="Surface.cpp" />

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="Config.h" />

-    <ClInclude Include="Display.h" />

-    <ClInclude Include="..\..\include\EGL\egl.h" />

-    <ClInclude Include="..\..\include\EGL\eglext.h" />

-    <ClInclude Include="..\..\include\EGL\eglplatform.h" />

-    <ClInclude Include="main.h" />

-    <ClInclude Include="resource.h" />

-    <ClInclude Include="Surface.h" />

-    <ClInclude Include="..\common\version.h" />

-  </ItemGroup>

-  <ItemGroup>

-    <None Include="libEGL.def" />

-  </ItemGroup>

-  <ItemGroup>

-    <ResourceCompile Include="libEGL.rc" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\libGLESv2\libGLESv2.vcxproj">

-      <Project>{b5871a7a-968c-42e3-a33b-981e6f448e78}</Project>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/src/libEGL/libEGL.vcxproj.filters b/src/third_party/angle/src/libEGL/libEGL.vcxproj.filters
deleted file mode 100644
index 860e169..0000000
--- a/src/third_party/angle/src/libEGL/libEGL.vcxproj.filters
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup>

-    <Filter Include="Source Files">

-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

-    </Filter>

-    <Filter Include="Header Files">

-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

-    </Filter>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="Config.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="..\Common\debug.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Display.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="libEGL.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="main.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Surface.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="Config.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Display.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\..\include\EGL\egl.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\..\include\EGL\eglext.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\..\include\EGL\eglplatform.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="main.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="resource.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Surface.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\common\version.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-  </ItemGroup>

-  <ItemGroup>

-    <ResourceCompile Include="libEGL.rc" />

-  </ItemGroup>

-  <ItemGroup>

-    <None Include="libEGL.def" />

-  </ItemGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/src/libEGL/main.cpp b/src/third_party/angle/src/libEGL/main.cpp
deleted file mode 100644
index 63ec87d..0000000
--- a/src/third_party/angle/src/libEGL/main.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// main.cpp: DLL entry point and management of thread-local data.
-#include "libEGL/main.h"
-
-#include "common/debug.h"
-
-static volatile DWORD currentTLS = TLS_OUT_OF_INDEXES;
-
-static egl::Current* GetCurrent()
-{
-#if !defined(COMPONENT_BUILD)
-    if (currentTLS == TLS_OUT_OF_INDEXES)
-        currentTLS = TlsAlloc();
-#endif
-
-    egl::Current *current = (egl::Current*)TlsGetValue(currentTLS);
-
-#if !defined(COMPONENT_BUILD)
-    if (current == NULL)
-    {
-        current = (egl::Current*)calloc(1, sizeof(egl::Current));
-
-        if (current)
-        {
-            TlsSetValue(currentTLS, current);
-
-            current->error = EGL_SUCCESS;
-            current->API = EGL_OPENGL_ES_API;
-            current->display = EGL_NO_DISPLAY;
-            current->drawSurface = EGL_NO_SURFACE;
-            current->readSurface = EGL_NO_SURFACE;
-        }
-    }
-#endif
-
-    return current;
-}
-
-#if defined(__cplusplus_winrt)
-// Turns off a harmless warning that happens when compiling with /CX flag
-#pragma warning(disable: 4447)
-#endif
-
-#if defined(COMPONENT_BUILD)
-BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
-{
-    switch (reason)
-    {
-      case DLL_PROCESS_ATTACH:
-        {
-#if !defined(ANGLE_DISABLE_TRACE)
-            FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
-
-            if (debug)
-            {
-                fclose(debug);
-                debug = fopen(TRACE_OUTPUT_FILE, "wt");   // Erase
-
-                if (debug)
-                {
-                    fclose(debug);
-                }
-            }
-#endif
-
-            currentTLS = TlsAlloc();
-
-            if (currentTLS == TLS_OUT_OF_INDEXES)
-            {
-                return FALSE;
-            }
-        }
-        // Fall throught to initialize index
-      case DLL_THREAD_ATTACH:
-        {
-            egl::Current *current = (egl::Current*)calloc(1, sizeof(egl::Current));
-
-            if (current)
-            {
-                TlsSetValue(currentTLS, current);
-
-                current->error = EGL_SUCCESS;
-                current->API = EGL_OPENGL_ES_API;
-                current->display = EGL_NO_DISPLAY;
-                current->drawSurface = EGL_NO_SURFACE;
-                current->readSurface = EGL_NO_SURFACE;
-            }
-        }
-        break;
-      case DLL_THREAD_DETACH:
-        {
-            void *current = TlsGetValue(currentTLS);
-
-            if (current)
-            {
-                free(current);
-            }
-        }
-        break;
-      case DLL_PROCESS_DETACH:
-        {
-            void *current = TlsGetValue(currentTLS);
-
-            if (current)
-            {
-                free(current);
-            }
-
-            TlsFree(currentTLS);
-        }
-        break;
-      default:
-        break;
-    }
-
-    return TRUE;
-}
-#endif // defined(COMPONENT_BUILD)
-
-namespace egl
-{
-
-void setCurrentError(EGLint error)
-{
-    egl::Current *current = GetCurrent();
-
-    current->error = error;
-}
-
-EGLint getCurrentError()
-{
-    egl::Current *current = GetCurrent();
-
-    return current->error;
-}
-
-void setCurrentAPI(EGLenum API)
-{
-    egl::Current *current = GetCurrent();
-
-    current->API = API;
-}
-
-EGLenum getCurrentAPI()
-{
-    egl::Current *current = GetCurrent();
-
-    return current->API;
-}
-
-void setCurrentDisplay(EGLDisplay dpy)
-{
-    egl::Current *current = GetCurrent();
-
-    current->display = dpy;
-}
-
-EGLDisplay getCurrentDisplay()
-{
-    egl::Current *current = GetCurrent();
-
-    return current->display;
-}
-
-void setCurrentDrawSurface(EGLSurface surface)
-{
-    egl::Current *current = GetCurrent();
-
-    current->drawSurface = surface;
-}
-
-EGLSurface getCurrentDrawSurface()
-{
-    egl::Current *current = GetCurrent();
-
-    return current->drawSurface;
-}
-
-void setCurrentReadSurface(EGLSurface surface)
-{
-    egl::Current *current = GetCurrent();
-
-    current->readSurface = surface;
-}
-
-EGLSurface getCurrentReadSurface()
-{
-    egl::Current *current = GetCurrent();
-
-    return current->readSurface;
-}
-
-void error(EGLint errorCode)
-{
-    egl::setCurrentError(errorCode);
-}
-
-}
diff --git a/src/third_party/angle/src/libEGL/main.h b/src/third_party/angle/src/libEGL/main.h
deleted file mode 100644
index ae39efb..0000000
--- a/src/third_party/angle/src/libEGL/main.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// main.h: Management of thread-local data.
-
-#ifndef LIBEGL_MAIN_H_
-#define LIBEGL_MAIN_H_
-
-#include "common/system.h"
-
-namespace egl
-{
-struct Current
-{
-    EGLint error;
-    EGLenum API;
-    EGLDisplay display;
-    EGLSurface drawSurface;
-    EGLSurface readSurface;
-};
-
-void setCurrentError(EGLint error);
-EGLint getCurrentError();
-
-void setCurrentAPI(EGLenum API);
-EGLenum getCurrentAPI();
-
-void setCurrentDisplay(EGLDisplay dpy);
-EGLDisplay getCurrentDisplay();
-
-void setCurrentDrawSurface(EGLSurface surface);
-EGLSurface getCurrentDrawSurface();
-
-void setCurrentReadSurface(EGLSurface surface);
-EGLSurface getCurrentReadSurface();
-
-#if !defined(COMPONENT_BUILD)
-void staticInitialize();
-#endif
-
-void error(EGLint errorCode);
-
-template<class T>
-const T &error(EGLint errorCode, const T &returnValue)
-{
-    error(errorCode);
-
-    return returnValue;
-}
-
-template<class T>
-const T &success(const T &returnValue)
-{
-    egl::setCurrentError(EGL_SUCCESS);
-
-    return returnValue;
-}
-
-}
-
-#endif  // LIBEGL_MAIN_H_
diff --git a/src/third_party/angle/src/libEGL/win32/WindowSubclassWin32.cpp b/src/third_party/angle/src/libEGL/win32/WindowSubclassWin32.cpp
deleted file mode 100644
index a733532..0000000
--- a/src/third_party/angle/src/libEGL/win32/WindowSubclassWin32.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// win32/WindowSubclassApi.cpp: Win32 specific implementation for WindowSubclass
-#include "libEGL/Surface.h"
-
-#include <tchar.h>
-
-#include "common/debug.h"
-#include "common/system.h"
-#include "common/windowutils.h"
-
-#include "libEGL/main.h"
-#include "libEGL/Display.h"
-
-#include "libGLESv2/renderer/SwapChain.h"
-#include "libGLESv2/main.h"
-
-namespace egl
-{
-
-#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
-#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
-
-static LRESULT CALLBACK SurfaceWindowProc(
-    HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
-{
-  if (message == WM_SIZE)
-  {
-      Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty));
-      if(surf)
-      {
-          surf->checkForOutOfDateSwapChain();
-      }
-  }
-  WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
-  return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
-}
-
-class WindowSubclassApi : public WindowSubclass
-{
-  public:
-    WindowSubclassApi(Surface *surface, EGLNativeWindowType window);
-    virtual ~WindowSubclassApi();
-
-    virtual bool getWindowSize(EGLint *width, EGLint *height);
-
-    bool initialize();
-
-    bool subclassWindow();
-    void unsubclassWindow();
-
-    Surface *mSurface;
-    EGLNativeWindowType mWindow;
-    bool mWindowSubclassed;
-};
-
-WindowSubclassApi::WindowSubclassApi(Surface *surface, EGLNativeWindowType window)
-  : mSurface(surface), mWindow(window), mWindowSubclassed(false)
-{
-}
-
-WindowSubclassApi::~WindowSubclassApi()
-{
-    unsubclassWindow();
-}
-
-bool WindowSubclassApi::getWindowSize(EGLint *width, EGLint *height)
-{
-    RECT rect = { 0 };
-    if (!::GetClientRect(mWindow, &rect))
-    {
-        return false;
-    }
-
-    *width = rect.right - rect.left;
-    *height = rect.bottom - rect.top;
-
-    return true;
-}
-
-bool WindowSubclassApi::subclassWindow()
-{
-    HWND wnd = (HWND)mWindow;
-    if (!wnd)
-    {
-        return false;
-    }
-
-    DWORD processId;
-    DWORD threadId = GetWindowThreadProcessId(wnd, &processId);
-    if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
-        return false;
-
-    SetLastError(0);
-    LONG_PTR oldWndProc = SetWindowLongPtr(
-        wnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
-    if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
-    {
-        return false;
-    }
-
-    SetProp(wnd, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
-    SetProp(wnd, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
-
-    mWindowSubclassed = true;
-
-    return true;
-}
-
-void WindowSubclassApi::unsubclassWindow()
-{
-    HWND wnd = (HWND)mWindow;
-    if(!mWindowSubclassed)
-    {
-        return;
-    }
-
-    // un-subclass
-    LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(
-        GetProp(wnd, 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(wnd, GWLP_WNDPROC, parentWndFunc);
-        ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
-    }
-
-    RemoveProp(wnd, kSurfaceProperty);
-    RemoveProp(wnd, kParentWndProc);
-    mWindowSubclassed = false;
-}
-
-bool WindowSubclassApi::initialize()
-{
-    if (!egl::verifyWindowAccessible(mWindow))
-        return false;
-
-    return true;
-}
-
-WindowSubclass *CreateWindowSubclassWin32(
-    Surface *surface, EGLNativeWindowType window)
-{
-    WindowSubclassApi *subclass = new WindowSubclassApi(surface, window);
-
-    if (!subclass->initialize())
-    {
-        delete subclass;
-        subclass = NULL;
-    }
-
-    return subclass;
-}
-
-} // namespace egl
diff --git a/src/third_party/angle/src/libEGL/winrt/WindowSubclassWinRT.cpp b/src/third_party/angle/src/libEGL/winrt/WindowSubclassWinRT.cpp
deleted file mode 100644
index 1065884..0000000
--- a/src/third_party/angle/src/libEGL/winrt/WindowSubclassWinRT.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// winrt/WindowSubclassWinRT.cpp: WinRT specific implementation for WindowSubclass
-#include "libEGL/Surface.h"
-
-#include <agile.h>
-#include <dxgi1_2.h>
-#include <math.h>
-#include <mutex>
-#include <Windows.h>
-#include <wrl.h>
-
-#include "common/debug.h"
-#include "common/windowutils.h"
-#include "common/winrt/windowadapter.h"
-
-using namespace Microsoft::WRL;
-using namespace Windows::Foundation;
-using namespace Windows::Graphics::Display;
-using namespace Windows::UI::Core;
-
-namespace egl
-{
-
-EGLint ConvertDipsToPixels(EGLint dips)
-{
-    static const float dipsPerInch = 96.0f;
-
-    float logicalDpi = DisplayProperties::LogicalDpi;
-    // Round to nearest integer.
-    return (EGLint)floor(dips * logicalDpi / dipsPerInch + 0.5f);
-}
-
-class WindowSubclassWinRT;
-
-ref class CoreWindowSizeHandler sealed
-{
-  public:
-    virtual ~CoreWindowSizeHandler();
-
-  internal:
-    CoreWindowSizeHandler(CoreWindow^ coreWindow);
-
-    void OnSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args);
-
-    void setWindowSizeDips(EGLint width, EGLint height);
-    void getWindowSize(EGLint* width, EGLint* height);
-
-    Platform::Agile<CoreWindow> mCoreWindow;
-
-    // We need to synchronize access to our variables since window
-    // size notifications are coming from the UI thread while the variables
-    // can be read from a different thread
-    std::mutex mMutex;
-
-    EGLint mWidth;
-    EGLint mHeight;
-
-    Windows::Foundation::EventRegistrationToken mOnSizeChangedToken;
-};
-
-CoreWindowSizeHandler::CoreWindowSizeHandler(CoreWindow^ coreWindow)
-    : mCoreWindow(coreWindow)
-{
-    setWindowSizeDips(mCoreWindow->Bounds.Width, mCoreWindow->Bounds.Height);
-
-    typedef TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^> SizeChangeHandler;
-    auto eventHandler = ref new SizeChangeHandler(this, &CoreWindowSizeHandler::OnSizeChanged);
-    mOnSizeChangedToken = (mCoreWindow->SizeChanged += eventHandler);
-}
-
-CoreWindowSizeHandler::~CoreWindowSizeHandler()
-{
-    mCoreWindow->SizeChanged -= mOnSizeChangedToken;
-}
-
-void CoreWindowSizeHandler::OnSizeChanged(
-      CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
-{
-    // Window size is reported in DIPs (Device Independent Pixels)
-    setWindowSizeDips(args->Size.Width, args->Size.Height);
-}
-
-void CoreWindowSizeHandler::setWindowSizeDips(EGLint width, EGLint height)
-{
-    width = ConvertDipsToPixels(width);
-    height = ConvertDipsToPixels(height);
-
-    {
-      std::lock_guard<std::mutex> lock(mMutex);
-
-      mWidth = width;
-      mHeight = height;
-    }
-}
-
-void CoreWindowSizeHandler::getWindowSize(EGLint* width, EGLint* height)
-{
-    std::lock_guard<std::mutex> lock(mMutex);
-
-    *width = mWidth;
-    *height = mHeight;
-}
-
-class WindowSubclassWinRT : public WindowSubclass
-{
-  public:
-    WindowSubclassWinRT(IWindowAdapter::Ptr windowAdapter);
-
-    virtual bool getWindowSize(EGLint *width, EGLint *height);
-
-    bool initialize();
-
-    IWindowAdapter::Ptr mWindowAdapter;
-    AngleWindowType mWindowType;
-
-    // Exists only if mWindowType == AWT_COREWINDOW
-    CoreWindowSizeHandler^ mHandler;
-};
-
-WindowSubclassWinRT::WindowSubclassWinRT(IWindowAdapter::Ptr windowAdapter)
-    : mWindowAdapter(windowAdapter)
-{
-    mWindowAdapter->GetType(&mWindowType);
-
-    if (mWindowType == AWT_COREWINDOW)
-    {
-        CoreWindow^ coreWindow;
-        mWindowAdapter->GetWindowAsWinRT(&coreWindow);
-        mHandler = ref new CoreWindowSizeHandler(coreWindow);
-    }
-}
-
-bool WindowSubclassWinRT::getWindowSize(EGLint *width, EGLint *height)
-{
-    if (mWindowType == AWT_COREWINDOW)
-    {
-        if (!mHandler)
-            return false;
-
-        mHandler->getWindowSize(width, height);
-    }
-    else if (mWindowType == AWT_SWAPCHAIN_ADAPTER)
-    {
-        ComPtr<ISwapChainAdapter> swapChainAdapter;
-        if (FAILED(mWindowAdapter->GetWindowAs(swapChainAdapter.GetAddressOf())))
-            return false;
-
-        swapChainAdapter->GetWindowSize(width, height);
-    }
-
-    return true;
-}
-
-bool WindowSubclassWinRT::initialize()
-{
-    if (!egl::verifyWindowAccessible(mWindowAdapter))
-        return false;
-
-    return true;
-}
-
-WindowSubclass *CreateWindowSubclassWinRT(Surface *, EGLNativeWindowType window)
-{
-    WindowSubclassWinRT *subclass = new WindowSubclassWinRT(
-        createWindowAdapter(window));
-
-    if (!subclass->initialize())
-    {
-        delete subclass;
-        subclass = NULL;
-    }
-
-    return subclass;
-}
-
-} // namespace egl
diff --git a/src/third_party/angle/src/libGLESv2.gypi b/src/third_party/angle/src/libGLESv2.gypi
new file mode 100644
index 0000000..f32c83d
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2.gypi
@@ -0,0 +1,1198 @@
+# Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'variables':
+    {
+        # These file lists are shared with the GN build.
+        'libangle_common_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/common/Color.h',
+            '<(DEPTH)/third_party/angle/src/common/Color.inl',
+            '<(DEPTH)/third_party/angle/src/common/Float16ToFloat32.cpp',
+            '<(DEPTH)/third_party/angle/src/common/MemoryBuffer.cpp',
+            '<(DEPTH)/third_party/angle/src/common/MemoryBuffer.h',
+            '<(DEPTH)/third_party/angle/src/common/Optional.h',
+            '<(DEPTH)/third_party/angle/src/common/angleutils.cpp',
+            '<(DEPTH)/third_party/angle/src/common/angleutils.h',
+            '<(DEPTH)/third_party/angle/src/common/bitset_utils.h',
+            '<(DEPTH)/third_party/angle/src/common/debug.cpp',
+            '<(DEPTH)/third_party/angle/src/common/debug.h',
+            '<(DEPTH)/third_party/angle/src/common/mathutil.cpp',
+            '<(DEPTH)/third_party/angle/src/common/mathutil.h',
+            '<(DEPTH)/third_party/angle/src/common/matrix_utils.h',
+            '<(DEPTH)/third_party/angle/src/common/platform.h',
+            '<(DEPTH)/third_party/angle/src/common/string_utils.cpp',
+            '<(DEPTH)/third_party/angle/src/common/string_utils.h',
+            '<(DEPTH)/third_party/angle/src/common/third_party/numerics/base/logging.h',
+            '<(DEPTH)/third_party/angle/src/common/third_party/numerics/base/numerics/safe_conversions.h',
+            '<(DEPTH)/third_party/angle/src/common/third_party/numerics/base/numerics/safe_conversions_impl.h',
+            '<(DEPTH)/third_party/angle/src/common/third_party/numerics/base/numerics/safe_math.h',
+            '<(DEPTH)/third_party/angle/src/common/third_party/numerics/base/numerics/safe_math_impl.h',
+            '<(DEPTH)/third_party/angle/src/common/tls.cpp',
+            '<(DEPTH)/third_party/angle/src/common/tls.h',
+            '<(DEPTH)/third_party/angle/src/common/utilities.cpp',
+            '<(DEPTH)/third_party/angle/src/common/utilities.h',
+            '<(DEPTH)/third_party/angle/src/common/vector_utils.h',
+            '<(DEPTH)/third_party/angle/src/common/version.h',
+        ],
+        'libangle_common_linux_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/common/system_utils_linux.cpp',
+        ],
+        'libangle_common_mac_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/common/system_utils_mac.cpp',
+        ],
+        'libangle_common_win_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/common/system_utils_win.cpp',
+        ],
+        'libangle_image_util_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/image_util/copyimage.cpp',
+            '<(DEPTH)/third_party/angle/src/image_util/copyimage.h',
+            '<(DEPTH)/third_party/angle/src/image_util/copyimage.inl',
+            '<(DEPTH)/third_party/angle/src/image_util/generatemip.h',
+            '<(DEPTH)/third_party/angle/src/image_util/generatemip.inl',
+            '<(DEPTH)/third_party/angle/src/image_util/imageformats.cpp',
+            '<(DEPTH)/third_party/angle/src/image_util/imageformats.h',
+            '<(DEPTH)/third_party/angle/src/image_util/loadimage.cpp',
+            '<(DEPTH)/third_party/angle/src/image_util/loadimage.h',
+            '<(DEPTH)/third_party/angle/src/image_util/loadimage.inl',
+            '<(DEPTH)/third_party/angle/src/image_util/loadimage_etc.cpp',
+        ],
+        'libangle_gpu_info_util_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/gpu_info_util/SystemInfo.cpp',
+            '<(DEPTH)/third_party/angle/src/gpu_info_util/SystemInfo.h',
+            '<(DEPTH)/third_party/angle/src/gpu_info_util/SystemInfo_internal.h',
+        ],
+        'libangle_gpu_info_util_win_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/gpu_info_util/SystemInfo_win.cpp',
+        ],
+        'libangle_gpu_info_util_linux_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/gpu_info_util/SystemInfo_linux.cpp',
+        ],
+        'libangle_gpu_info_util_libpci_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/gpu_info_util/SystemInfo_libpci.cpp',
+        ],
+        'libangle_gpu_info_util_x11_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/gpu_info_util/SystemInfo_x11.cpp',
+        ],
+        'libangle_gpu_info_util_mac_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/gpu_info_util/SystemInfo_mac.mm',
+        ],
+        'libangle_includes':
+        [
+            '<(DEPTH)/third_party/angle/include/angle_gl.h',
+            '<(DEPTH)/third_party/angle/include/export.h',
+            '<(DEPTH)/third_party/angle/include/EGL/egl.h',
+            '<(DEPTH)/third_party/angle/include/EGL/eglext.h',
+            '<(DEPTH)/third_party/angle/include/EGL/eglplatform.h',
+            '<(DEPTH)/third_party/angle/include/GLES2/gl2.h',
+            '<(DEPTH)/third_party/angle/include/GLES2/gl2ext.h',
+            '<(DEPTH)/third_party/angle/include/GLES2/gl2platform.h',
+            '<(DEPTH)/third_party/angle/include/GLES3/gl3.h',
+            '<(DEPTH)/third_party/angle/include/GLES3/gl3platform.h',
+            '<(DEPTH)/third_party/angle/include/GLES3/gl31.h',
+            '<(DEPTH)/third_party/angle/include/GLES3/gl32.h',
+            '<(DEPTH)/third_party/angle/include/GLSLANG/ShaderLang.h',
+            '<(DEPTH)/third_party/angle/include/GLSLANG/ShaderVars.h',
+            '<(DEPTH)/third_party/angle/include/KHR/khrplatform.h',
+            '<(DEPTH)/third_party/angle/include/platform/Platform.h',
+            '<(DEPTH)/third_party/angle/include/platform/WorkaroundsD3D.h',
+        ],
+        'libangle_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/common/event_tracer.cpp',
+            '<(DEPTH)/third_party/angle/src/common/event_tracer.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/AttributeMap.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/AttributeMap.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/BinaryStream.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Buffer.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Buffer.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Caps.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Caps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Compiler.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Compiler.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Config.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Config.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Constants.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Context.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Context.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/ContextState.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/ContextState.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Debug.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Debug.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Device.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Device.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Display.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Display.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Error.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Error.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Error.inl',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Fence.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Fence.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Framebuffer.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Framebuffer.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/FramebufferAttachment.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/FramebufferAttachment.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/HandleAllocator.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/HandleAllocator.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/HandleRangeAllocator.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/HandleRangeAllocator.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Image.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Image.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/ImageIndex.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/ImageIndex.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/IndexRangeCache.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/IndexRangeCache.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/LoggingAnnotator.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/LoggingAnnotator.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Path.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Path.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Platform.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Program.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Program.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Query.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Query.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/RefCountObject.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Renderbuffer.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Renderbuffer.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/ResourceManager.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/ResourceManager.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Sampler.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Sampler.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Shader.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Shader.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/State.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/State.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Stream.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Stream.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Surface.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Surface.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Texture.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Texture.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Thread.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Thread.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/TransformFeedback.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/TransformFeedback.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Uniform.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Uniform.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/UniformLinker.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/UniformLinker.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/VaryingPacking.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/VaryingPacking.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Version.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/Version.inl',
+            '<(DEPTH)/third_party/angle/src/libANGLE/VertexArray.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/VertexArray.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/VertexAttribute.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/VertexAttribute.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/VertexAttribute.inl',
+            '<(DEPTH)/third_party/angle/src/libANGLE/WorkerThread.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/WorkerThread.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/angletypes.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/angletypes.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/angletypes.inl',
+            '<(DEPTH)/third_party/angle/src/libANGLE/entry_points_enum_autogen.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/features.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/format_map_autogen.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/formatutils.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/formatutils.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/histogram_macros.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/params.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/params.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/queryconversions.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/queryconversions.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/queryutils.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/queryutils.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/BufferImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/CompilerImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/ContextImpl.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/ContextImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/driver_utils.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/driver_utils.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/DeviceImpl.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/DeviceImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/DisplayImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/EGLImplFactory.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/FenceNVImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/FenceSyncImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/Format_ID_autogen.inl',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/Format_table_autogen.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/Format.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/GLImplFactory.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/ImageImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/ProgramImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/QueryImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/RenderbufferImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/SamplerImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/ShaderImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/StreamProducerImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/SurfaceImpl.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/TextureImpl.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/TextureImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/TransformFeedbackImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/VertexArrayImpl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/load_functions_table.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/renderer_utils.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/renderer_utils.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/signal_utils.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationEGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationEGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationES.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationES.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationES2.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationES2.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationES3.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationES3.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationES31.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/validationES31.h',
+            '<(DEPTH)/third_party/angle/src/third_party/murmurhash/MurmurHash3.cpp',
+            '<(DEPTH)/third_party/angle/src/third_party/murmurhash/MurmurHash3.h',
+            '<(DEPTH)/third_party/angle/src/third_party/trace_event/trace_event.h',
+        ],
+        'libangle_d3d_shared_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/CompilerD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/IndexBuffer.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/SamplerD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/TextureStorage.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h',
+        ],
+        'libangle_d3d9_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h',
+        ],
+        'libangle_d3d11_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h',
+        ],
+        'libangle_d3d11_win32_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h',
+            '<(DEPTH)/third_party/angle/src/third_party/systeminfo/SystemInfo.cpp',
+            '<(DEPTH)/third_party/angle/src/third_party/systeminfo/SystemInfo.h',
+        ],
+        'libangle_d3d11_winrt_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h',
+        ],
+        'libangle_gl_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/BufferGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/BufferGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/CompilerGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/CompilerGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/ContextGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/ContextGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/FenceNVGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/FenceSyncGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/PathGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/PathGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/RenderbufferGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/SamplerGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/SamplerGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/SurfaceGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/TextureGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/TextureGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/functionsgl_enums.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.h',
+        ],
+        'libangle_gl_wgl_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h',
+            '<(DEPTH)/third_party/angle/src/third_party/khronos/GL/wglext.h',
+        ],
+        'libangle_gl_glx_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h',
+        ],
+        'libangle_gl_egl_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h',
+        ],
+        'libangle_gl_egl_dl_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h',
+        ],
+        'libangle_gl_ozone_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h',
+        ],
+        'libangle_gl_egl_android_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h',
+        ],
+        'libangle_gl_cgl_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h',
+        ],
+        'libangle_vulkan_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/CompilerVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/CompilerVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/DeviceVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/DeviceVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/FenceNVVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/FenceNVVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/SamplerVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/SamplerVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/ShaderVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/ShaderVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/formatutilsvk.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/formatutilsvk.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/renderervk_utils.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/renderervk_utils.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp',
+        ],
+        'libangle_vulkan_win32_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h',
+        ],
+        'libangle_vulkan_xcb_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h',
+        ],
+        'libangle_null_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/BufferNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/BufferNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/CompilerNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/CompilerNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/ContextNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/ContextNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/DeviceNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/DeviceNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/DisplayNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/DisplayNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/FenceNVNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/FenceNVNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/FenceSyncNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/FenceSyncNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/FramebufferNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/FramebufferNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/ImageNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/ImageNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/PathNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/PathNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/QueryNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/QueryNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/RenderbufferNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/RenderbufferNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/SamplerNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/SamplerNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/ShaderNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/ShaderNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/SurfaceNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/SurfaceNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/TextureNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/TextureNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.h',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/VertexArrayNULL.cpp',
+            '<(DEPTH)/third_party/angle/src/libANGLE/renderer/null/VertexArrayNULL.h',
+        ],
+        'libglesv2_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/common/angleutils.h',
+            '<(DEPTH)/third_party/angle/src/common/debug.h',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_egl.cpp',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_egl.h',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_egl_ext.cpp',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_egl_ext.h',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_gles_2_0_autogen.cpp',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_gles_2_0_autogen.h',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_gles_2_0_ext.h',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_gles_3_0.cpp',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_gles_3_0.h',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_gles_3_1.cpp',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/entry_points_gles_3_1.h',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/global_state.cpp',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/global_state.h',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/libGLESv2.cpp',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/libGLESv2.def',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/libGLESv2.rc',
+            '<(DEPTH)/third_party/angle/src/libGLESv2/resource.h',
+        ],
+        'libegl_sources':
+        [
+            '<(DEPTH)/third_party/angle/src/libEGL/libEGL.cpp',
+            '<(DEPTH)/third_party/angle/src/libEGL/libEGL.def',
+            '<(DEPTH)/third_party/angle/src/libEGL/libEGL.rc',
+            '<(DEPTH)/third_party/angle/src/libEGL/resource.h',
+        ],
+    },
+    # Everything below this is duplicated in the GN build. If you change
+    # anything also change angle/BUILD.gn
+    'targets':
+    [
+        {
+            # This target includes the right ANGLE defines for <(DEPTH)/third_party/angle/src/common/platform.h for D3D11.
+            # It also links against the right libs. This is useful for the tests, which
+            # have special D3D11 code for Debug runtime error message handling.
+            'target_name': 'libANGLE_d3d11_config',
+            'type': 'none',
+            'conditions':
+            [
+                ['angle_enable_d3d11==1',
+                {
+                    'link_settings':
+                    {
+                        'msvs_settings':
+                        {
+                            'VCLinkerTool':
+                            {
+                                'conditions':
+                                [
+                                    ['angle_build_winrt==0',
+                                    {
+                                        'AdditionalDependencies':
+                                        [
+                                            'dxguid.lib',
+                                        ],
+                                    }],
+                                    ['angle_build_winrt==1',
+                                    {
+                                        'AdditionalDependencies':
+                                        [
+                                            'dxguid.lib',
+                                            'd3d11.lib',
+                                            'd3dcompiler.lib',
+                                        ],
+                                    }],
+                                ],
+                            }
+                        },
+                    },
+                }],
+            ],
+        },
+
+        {
+            'target_name': 'libANGLE_renderer_config',
+            'type': 'none',
+            'direct_dependent_settings':
+            {
+                'conditions':
+                [
+                    ['angle_enable_d3d11==1',
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_D3D11',
+                        ],
+                    }],
+                    ['angle_enable_d3d9==1',
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_D3D9',
+                        ],
+                    }],
+                    ['angle_enable_gl==1',
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_OPENGL',
+                        ],
+                    }],
+                    ['angle_enable_vulkan==1',
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_VULKAN',
+                        ],
+                    }],
+                    ['angle_enable_null==1',
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_NULL',
+                        ],
+                    }],
+                ],
+            },
+        },
+
+        {
+            'target_name': 'libANGLE',
+            'type': 'static_library',
+            'dependencies':
+            [
+                '<(DEPTH)/base/base.gyp:base',
+                'translator',
+                'angle_common',
+                'angle_image_util',
+                'angle_gpu_info_util',
+                'libANGLE_d3d11_config',
+                'libANGLE_renderer_config',
+            ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'include_dirs':
+            [
+                '<(DEPTH)/third_party/angle/',
+                '<(DEPTH)/third_party/angle/include',
+                '<(DEPTH)/third_party/angle/src/third_party/khronos',
+            ],
+            'sources':
+            [
+                '<@(libangle_sources)',
+                '<@(libangle_includes)',
+            ],
+            'defines':
+            [
+                'LIBANGLE_IMPLEMENTATION',
+            ],
+            'export_dependent_settings':
+            [
+                'angle_common',
+                'libANGLE_d3d11_config',
+                'libANGLE_renderer_config',
+            ],
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(DEPTH)/third_party/angle/src',
+                    '<(DEPTH)/third_party/angle/include',
+                ],
+                'defines':
+                [
+                    'LIBANGLE_IMPLEMENTATION',
+                    'GL_GLEXT_PROTOTYPES',
+                    'ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ "d3dcompiler_47.dll", "d3dcompiler_46.dll", "d3dcompiler_43.dll" }',
+                ],
+                'conditions':
+                [
+                    ['OS=="win"', {
+                        'defines':
+                        [
+                            'GL_APICALL=',
+                        ],
+                    }, {
+                        'defines':
+                        [
+                            'GL_APICALL=__attribute__((visibility("default")))',
+                        ],
+                    }],
+                    ['OS == "mac"',
+                    {
+                        'xcode_settings':
+                        {
+                            'DYLIB_INSTALL_NAME_BASE': '@rpath',
+                        },
+                    }],
+                    ['angle_enable_gl==1',
+                    {
+                        'conditions':
+                        [
+                            ['angle_use_glx==1',
+                            {
+                                'defines':
+                                [
+                                    'ANGLE_USE_X11',
+                                ],
+                            }],
+                        ],
+                    }],
+                ],
+            },
+            'conditions':
+            [
+                ['angle_enable_d3d9==1 or angle_enable_d3d11==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_d3d_shared_sources)',
+                    ],
+                }],
+                ['angle_enable_d3d9==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_d3d9_sources)',
+                    ],
+                    'link_settings':
+                    {
+                        'msvs_settings':
+                        {
+                            'VCLinkerTool':
+                            {
+                                'AdditionalDependencies':
+                                [
+                                    'd3d9.lib',
+                                ]
+                            }
+                        },
+                    },
+                }],
+                ['angle_enable_d3d11==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_d3d11_sources)',
+                    ],
+                    'conditions':
+                    [
+                        ['angle_build_winrt==1',
+                        {
+                            'sources':
+                            [
+                                '<@(libangle_d3d11_winrt_sources)',
+                            ],
+                        },
+                        { # win32
+                            'sources':
+                            [
+                                '<@(libangle_d3d11_win32_sources)',
+                            ],
+                        }],
+                    ],
+                }],
+                ['angle_enable_gl==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_gl_sources)',
+                    ],
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<@(libangle_gl_wgl_sources)',
+                            ],
+                        }],
+                        ['angle_use_glx==1',
+                        {
+                            'defines':
+                            [
+                                'ANGLE_USE_X11',
+                            ],
+                            'sources':
+                            [
+                                '<@(libangle_gl_glx_sources)',
+                            ],
+                            'link_settings': {
+                                'ldflags': [
+                                    '<!@(<(pkg-config) --libs-only-L --libs-only-other x11 xi xext xcb)',
+                                ],
+                                'libraries': [
+                                    '<!@(<(pkg-config) --libs-only-l x11 xi xext xcb) -ldl',
+                                ],
+                            },
+                        }],
+                        ['use_ozone==1',
+                        {
+                            'defines':
+                            [
+                                'ANGLE_USE_OZONE',
+                            ],
+                            'sources':
+                            [
+                                '<@(libangle_gl_egl_sources)',
+                                '<@(libangle_gl_egl_dl_sources)',
+                                '<@(libangle_gl_ozone_sources)',
+                            ],
+                            'cflags':
+                            [
+                                '<!@(<(pkg-config) --cflags libdrm gbm)',
+                            ],
+                            'link_settings': {
+                                'ldflags': [
+                                    '<!@(<(pkg-config) --libs-only-L --libs-only-other libdrm gbm)',
+                                ],
+                                'libraries': [
+                                    '<!@(<(pkg-config) --libs-only-l libdrm gbm) -ldl',
+                                ],
+                            },
+                        }],
+                        ['angle_link_glx==1',
+                        {
+                            'link_settings':
+                            {
+                                'libraries':
+                                [
+                                    '-lGL',
+                                ],
+                            },
+                            'defines':
+                            [
+                                'ANGLE_LINK_GLX',
+                            ],
+                        }],
+                        ['OS=="mac"',
+                        {
+                            'sources':
+                            [
+                                '<@(libangle_gl_cgl_sources)',
+                            ],
+                            'link_settings':
+                            {
+                                'libraries':
+                                [
+                                    '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
+                                    '$(SDKROOT)/System/Library/Frameworks/IOSurface.framework',
+                                    '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework',
+                                    '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
+                                ],
+                            },
+                            'all_dependent_settings':
+                            {
+                                'xcode_settings': {
+                                    'LD_RUNPATH_SEARCH_PATHS': ['@executable_path/.'],
+                                },
+                            }
+                        }],
+                    ],
+                }],
+                ['angle_enable_vulkan==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_vulkan_sources)',
+                    ],
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<@(libangle_vulkan_win32_sources)',
+                            ],
+                        }],
+                        ['OS=="linux"',
+                        {
+                            'sources':
+                            [
+                                '<@(libangle_vulkan_xcb_sources)',
+                            ],
+                        }],
+                    ],
+                    'dependencies':
+                    [
+                        'angle_vulkan',
+                    ],
+                    'export_dependent_settings':
+                    [
+                        'angle_vulkan',
+                    ],
+                }],
+                ['angle_enable_null==1',
+                {
+                    'sources':
+                    [
+                        '<@(libangle_null_sources)',
+                    ],
+                }],
+                ['angle_build_winrt==0 and OS=="win"',
+                {
+                    'dependencies':
+                    [
+                        'copy_compiler_dll'
+                    ],
+                }],
+                ['angle_build_winrt==1',
+                {
+                    'msvs_requires_importlibrary' : 'true',
+                }],
+            ],
+        },
+        {
+            'target_name': 'libGLESv2',
+            'type': '<(angle_gl_library_type)',
+            'dependencies': [ 'libANGLE', 'angle_common' ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources':
+            [
+                '<@(libglesv2_sources)',
+            ],
+            'defines':
+            [
+                'LIBGLESV2_IMPLEMENTATION',
+            ],
+            'conditions':
+            [
+                ['angle_build_winrt==1',
+                {
+                    'msvs_requires_importlibrary' : 'true',
+                }],
+            ],
+        },
+
+        {
+            'target_name': 'libGLESv2_static',
+            'type': 'static_library',
+            'dependencies': [ 'libANGLE', 'angle_common' ],
+            'export_dependent_settings':
+            [
+                'libANGLE',
+            ],
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'sources':
+            [
+                '<@(libglesv2_sources)',
+            ],
+            'conditions':
+            [
+                ['angle_build_winrt==1',
+                {
+                    'msvs_requires_importlibrary' : 'true',
+                }],
+            ],
+        },
+    ],
+}
diff --git a/src/third_party/angle/src/libGLESv2/BinaryStream.h b/src/third_party/angle/src/libGLESv2/BinaryStream.h
deleted file mode 100644
index 21c2f86..0000000
--- a/src/third_party/angle/src/libGLESv2/BinaryStream.h
+++ /dev/null
@@ -1,164 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BinaryStream.h: Provides binary serialization of simple types.
-
-#ifndef LIBGLESV2_BINARYSTREAM_H_
-#define LIBGLESV2_BINARYSTREAM_H_
-
-#include "common/angleutils.h"
-
-namespace gl
-{
-
-class BinaryInputStream
-{
-  public:
-    BinaryInputStream(const void *data, size_t length)
-    {
-        mError = false;
-        mOffset = 0;
-        mData = static_cast<const char*>(data);
-        mLength = length;
-    }
-
-    template <typename T>
-    void read(T *v, size_t num)
-    {
-        union
-        {
-            T dummy;  // Compilation error for non-trivial types
-        } dummy;
-        (void) dummy;
-
-        if (mError)
-        {
-            return;
-        }
-
-        size_t length = num * sizeof(T);
-
-        if (mOffset + length > mLength)
-        {
-            mError = true;
-            return;
-        }
-
-        memcpy(v, mData + mOffset, length);
-        mOffset += length;
-    }
-
-    template <typename T>
-    void read(T * v)
-    {
-        read(v, 1);
-    }
-
-    void read(std::string *v)
-    {
-        size_t length;
-        read(&length);
-
-        if (mError)
-        {
-            return;
-        }
-
-        if (mOffset + length > mLength)
-        {
-            mError = true;
-            return;
-        }
-
-        v->assign(mData + mOffset, length);
-        mOffset += length;
-    }
-
-    void skip(size_t length)
-    {
-        if (mOffset + length > mLength)
-        {
-            mError = true;
-            return;
-        }
-
-        mOffset += length;
-    }
-
-    size_t offset() const
-    {
-        return mOffset;
-    }
-
-    bool error() const
-    {
-        return mError;
-    }
-
-    bool endOfStream() const
-    {
-        return mOffset == mLength;
-    }
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(BinaryInputStream);
-    bool mError;
-    size_t mOffset;
-    const char *mData;
-    size_t mLength;
-};
-
-class BinaryOutputStream
-{
-  public:
-    BinaryOutputStream()
-    {
-    }
-
-    template <typename T>
-    void write(const T *v, size_t num)
-    {
-        union
-        {
-            T dummy;  // Compilation error for non-trivial types
-        } dummy;
-        (void) dummy;
-
-        const char *asBytes = reinterpret_cast<const char*>(v);
-        mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
-    }
-
-    template <typename T>
-    void write(const T &v)
-    {
-        write(&v, 1);
-    }
-
-    void write(const std::string &v)
-    {
-        size_t length = v.length();
-        write(length);
-
-        write(v.c_str(), length);
-    }
-
-    size_t length() const
-    {
-        return mData.size();
-    }
-
-    const void* data() const
-    {
-        return mData.size() ? &mData[0] : NULL;
-    }
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(BinaryOutputStream);
-    std::vector<char> mData;
-};
-}
-
-#endif  // LIBGLESV2_BINARYSTREAM_H_
diff --git a/src/third_party/angle/src/libGLESv2/Buffer.cpp b/src/third_party/angle/src/libGLESv2/Buffer.cpp
deleted file mode 100644
index 8d5b4ef..0000000
--- a/src/third_party/angle/src/libGLESv2/Buffer.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Buffer.cpp: Implements 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.
-
-#include "libGLESv2/Buffer.h"
-
-#include "libGLESv2/renderer/VertexBuffer.h"
-#include "libGLESv2/renderer/IndexBuffer.h"
-#include "libGLESv2/renderer/BufferStorage.h"
-#include "libGLESv2/renderer/Renderer.h"
-
-namespace gl
-{
-
-Buffer::Buffer(rx::Renderer *renderer, GLuint id) : RefCountObject(id)
-{
-    mRenderer = renderer;
-    mUsage = GL_DYNAMIC_DRAW;
-
-    mBufferStorage = renderer->createBufferStorage();
-    mStaticVertexBuffer = NULL;
-    mStaticIndexBuffer = NULL;
-    mUnmodifiedDataUse = 0;
-}
-
-Buffer::~Buffer()
-{
-    delete mBufferStorage;
-    delete mStaticVertexBuffer;
-    delete mStaticIndexBuffer;
-}
-
-void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
-{
-    mBufferStorage->clear();
-    mBufferStorage->setData(data, size, 0);
-
-    mUsage = usage;
-
-    invalidateStaticData();
-
-    if (usage == GL_STATIC_DRAW)
-    {
-        mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer);
-        mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer);
-    }
-}
-
-void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
-{
-    mBufferStorage->setData(data, size, offset);
-
-    if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
-    {
-        invalidateStaticData();
-    }
-
-    mUnmodifiedDataUse = 0;
-}
-
-rx::BufferStorage *Buffer::getStorage() const
-{
-    return mBufferStorage;
-}
-
-unsigned int Buffer::size()
-{
-    return mBufferStorage->getSize();
-}
-
-GLenum Buffer::usage() const
-{
-    return mUsage;
-}
-
-rx::StaticVertexBufferInterface *Buffer::getStaticVertexBuffer()
-{
-    return mStaticVertexBuffer;
-}
-
-rx::StaticIndexBufferInterface *Buffer::getStaticIndexBuffer()
-{
-    return mStaticIndexBuffer;
-}
-
-void Buffer::invalidateStaticData()
-{
-    delete mStaticVertexBuffer;
-    mStaticVertexBuffer = NULL;
-
-    delete mStaticIndexBuffer;
-    mStaticIndexBuffer = NULL;
-
-    mUnmodifiedDataUse = 0;
-}
-
-// Creates static buffers if sufficient used data has been left unmodified
-void Buffer::promoteStaticUsage(int dataSize)
-{
-    if (!mStaticVertexBuffer && !mStaticIndexBuffer)
-    {
-        mUnmodifiedDataUse += dataSize;
-
-        if (mUnmodifiedDataUse > 3 * mBufferStorage->getSize())
-        {
-            mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer);
-            mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer);
-        }
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/Buffer.h b/src/third_party/angle/src/libGLESv2/Buffer.h
deleted file mode 100644
index 4376ada..0000000
--- a/src/third_party/angle/src/libGLESv2/Buffer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// 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 "common/angleutils.h"
-#include "common/RefCountObject.h"
-
-namespace rx
-{
-class Renderer;
-class BufferStorage;
-class StaticIndexBufferInterface;
-class StaticVertexBufferInterface;
-};
-
-namespace gl
-{
-
-class Buffer : public RefCountObject
-{
-  public:
-    Buffer(rx::Renderer *renderer, GLuint id);
-
-    virtual ~Buffer();
-
-    void bufferData(const void *data, GLsizeiptr size, GLenum usage);
-    void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
-
-    GLenum usage() const;
-
-    rx::BufferStorage *getStorage() const;
-    unsigned int size();
-
-    rx::StaticVertexBufferInterface *getStaticVertexBuffer();
-    rx::StaticIndexBufferInterface *getStaticIndexBuffer();
-    void invalidateStaticData();
-    void promoteStaticUsage(int dataSize);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Buffer);
-
-    rx::Renderer *mRenderer;
-    GLenum mUsage;
-
-    rx::BufferStorage *mBufferStorage;
-
-    rx::StaticVertexBufferInterface *mStaticVertexBuffer;
-    rx::StaticIndexBufferInterface *mStaticIndexBuffer;
-    unsigned int mUnmodifiedDataUse;
-};
-
-}
-
-#endif   // LIBGLESV2_BUFFER_H_
diff --git a/src/third_party/angle/src/libGLESv2/Context.cpp b/src/third_party/angle/src/libGLESv2/Context.cpp
deleted file mode 100644
index 52440c9..0000000
--- a/src/third_party/angle/src/libGLESv2/Context.cpp
+++ /dev/null
@@ -1,2985 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Context.cpp: Implements the gl::Context class, managing all GL state and performing
-// rendering operations. It is the GLES2 specific implementation of EGLContext.
-
-#include "libGLESv2/Context.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Fence.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Query.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/ResourceManager.h"
-#include "libGLESv2/renderer/IndexDataManager.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-#include "libGLESv2/renderer/Renderer.h"
-
-#include "libEGL/Surface.h"
-
-#undef near
-#undef far
-
-namespace gl
-{
-static const char* makeStaticString(const std::string& str)
-{
-    static std::set<std::string> strings;
-    std::set<std::string>::iterator it = strings.find(str);
-    if (it != strings.end())
-      return it->c_str();
-
-    return strings.insert(str).first->c_str();
-}
-
-Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer)
-{
-    ASSERT(robustAccess == false);   // Unimplemented
-
-    mFenceHandleAllocator.setBaseHandle(0);
-
-    setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
-    mState.depthClearValue = 1.0f;
-    mState.stencilClearValue = 0;
-
-    mState.rasterizer.cullFace = false;
-    mState.rasterizer.cullMode = GL_BACK;
-    mState.rasterizer.frontFace = GL_CCW;
-    mState.rasterizer.polygonOffsetFill = false;
-    mState.rasterizer.polygonOffsetFactor = 0.0f;
-    mState.rasterizer.polygonOffsetUnits = 0.0f;
-    mState.rasterizer.pointDrawMode = false;
-    mState.rasterizer.multiSample = false;
-    mState.scissorTest = false;
-    mState.scissor.x = 0;
-    mState.scissor.y = 0;
-    mState.scissor.width = 0;
-    mState.scissor.height = 0;
-
-    mState.blend.blend = false;
-    mState.blend.sourceBlendRGB = GL_ONE;
-    mState.blend.sourceBlendAlpha = GL_ONE;
-    mState.blend.destBlendRGB = GL_ZERO;
-    mState.blend.destBlendAlpha = GL_ZERO;
-    mState.blend.blendEquationRGB = GL_FUNC_ADD;
-    mState.blend.blendEquationAlpha = GL_FUNC_ADD;
-    mState.blend.sampleAlphaToCoverage = false;
-    mState.blend.dither = true;
-
-    mState.blendColor.red = 0;
-    mState.blendColor.green = 0;
-    mState.blendColor.blue = 0;
-    mState.blendColor.alpha = 0;
-
-    mState.depthStencil.depthTest = false;
-    mState.depthStencil.depthFunc = GL_LESS;
-    mState.depthStencil.depthMask = true;
-    mState.depthStencil.stencilTest = false;
-    mState.depthStencil.stencilFunc = GL_ALWAYS;
-    mState.depthStencil.stencilMask = -1;
-    mState.depthStencil.stencilWritemask = -1;
-    mState.depthStencil.stencilBackFunc = GL_ALWAYS;
-    mState.depthStencil.stencilBackMask = - 1;
-    mState.depthStencil.stencilBackWritemask = -1;
-    mState.depthStencil.stencilFail = GL_KEEP;
-    mState.depthStencil.stencilPassDepthFail = GL_KEEP;
-    mState.depthStencil.stencilPassDepthPass = GL_KEEP;
-    mState.depthStencil.stencilBackFail = GL_KEEP;
-    mState.depthStencil.stencilBackPassDepthFail = GL_KEEP;
-    mState.depthStencil.stencilBackPassDepthPass = GL_KEEP;
-
-    mState.stencilRef = 0;
-    mState.stencilBackRef = 0;
-
-    mState.sampleCoverage = false;
-    mState.sampleCoverageValue = 1.0f;
-    mState.sampleCoverageInvert = false;
-    mState.generateMipmapHint = GL_DONT_CARE;
-    mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
-
-    mState.lineWidth = 1.0f;
-
-    mState.viewport.x = 0;
-    mState.viewport.y = 0;
-    mState.viewport.width = 0;
-    mState.viewport.height = 0;
-    mState.zNear = 0.0f;
-    mState.zFar = 1.0f;
-
-    mState.blend.colorMaskRed = true;
-    mState.blend.colorMaskGreen = true;
-    mState.blend.colorMaskBlue = true;
-    mState.blend.colorMaskAlpha = true;
-
-    if (shareContext != NULL)
-    {
-        mResourceManager = shareContext->mResourceManager;
-        mResourceManager->addRef();
-    }
-    else
-    {
-        mResourceManager = new ResourceManager(mRenderer);
-    }
-
-    // [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, 0));
-    mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0));
-
-    mState.activeSampler = 0;
-    bindArrayBuffer(0);
-    bindElementArrayBuffer(0);
-    bindTextureCubeMap(0);
-    bindTexture2D(0);
-    bindReadFramebuffer(0);
-    bindDrawFramebuffer(0);
-    bindRenderbuffer(0);
-
-    mState.currentProgram = 0;
-    mCurrentProgramBinary.set(NULL);
-
-    mState.packAlignment = 4;
-    mState.unpackAlignment = 4;
-    mState.packReverseRowOrder = false;
-
-    mExtensionString = NULL;
-    mRendererString = NULL;
-
-    mInvalidEnum = false;
-    mInvalidValue = false;
-    mInvalidOperation = false;
-    mOutOfMemory = false;
-    mInvalidFramebufferOperation = false;
-
-    mHasBeenCurrent = false;
-    mContextLost = false;
-    mResetStatus = GL_NO_ERROR;
-    mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
-    mRobustAccess = robustAccess;
-
-    mSupportsBGRATextures = false;
-    mSupportsDXT1Textures = false;
-    mSupportsDXT3Textures = false;
-    mSupportsDXT5Textures = false;
-    mSupportsEventQueries = false;
-    mSupportsOcclusionQueries = false;
-    mNumCompressedTextureFormats = 0;
-}
-
-Context::~Context()
-{
-    if (mState.currentProgram != 0)
-    {
-        Program *programObject = mResourceManager->getProgram(mState.currentProgram);
-        if (programObject)
-        {
-            programObject->release();
-        }
-        mState.currentProgram = 0;
-    }
-    mCurrentProgramBinary.set(NULL);
-
-    while (!mFramebufferMap.empty())
-    {
-        deleteFramebuffer(mFramebufferMap.begin()->first);
-    }
-
-    while (!mFenceMap.empty())
-    {
-        deleteFence(mFenceMap.begin()->first);
-    }
-
-    while (!mQueryMap.empty())
-    {
-        deleteQuery(mQueryMap.begin()->first);
-    }
-
-    for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
-    {
-        for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
-        {
-            mState.samplerTexture[type][sampler].set(NULL);
-        }
-    }
-
-    for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
-    {
-        mIncompleteTextures[type].set(NULL);
-    }
-
-    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
-    {
-        mState.vertexAttribute[i].mBoundBuffer.set(NULL);
-    }
-
-    for (int i = 0; i < QUERY_TYPE_COUNT; i++)
-    {
-        mState.activeQuery[i].set(NULL);
-    }
-
-    mState.arrayBuffer.set(NULL);
-    mState.elementArrayBuffer.set(NULL);
-    mState.renderbuffer.set(NULL);
-
-    mTexture2DZero.set(NULL);
-    mTextureCubeMapZero.set(NULL);
-
-    mResourceManager->release();
-}
-
-void Context::makeCurrent(egl::Surface *surface)
-{
-    if (!mHasBeenCurrent)
-    {
-        mMajorShaderModel = mRenderer->getMajorShaderModel();
-        mMaximumPointSize = mRenderer->getMaxPointSize();
-        mSupportsVertexTexture = mRenderer->getVertexTextureSupport();
-        mSupportsNonPower2Texture = mRenderer->getNonPower2TextureSupport();
-        mSupportsInstancing = mRenderer->getInstancingSupport();
-
-        mMaxViewportDimension = mRenderer->getMaxViewportDimension();
-        mMaxTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()),
-                                        (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
-        mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
-        mMaxRenderbufferDimension = mMaxTextureDimension;
-        mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
-        mMaxTextureAnisotropy = mRenderer->getTextureMaxAnisotropy();
-        TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d, MaxTextureAnisotropy=%f",
-              mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel, mMaxTextureAnisotropy);
-
-        mSupportsEventQueries = mRenderer->getEventQuerySupport();
-        mSupportsOcclusionQueries = mRenderer->getOcclusionQuerySupport();
-        mSupportsBGRATextures = mRenderer->getBGRATextureSupport();
-        mSupportsDXT1Textures = mRenderer->getDXT1TextureSupport();
-        mSupportsDXT3Textures = mRenderer->getDXT3TextureSupport();
-        mSupportsDXT5Textures = mRenderer->getDXT5TextureSupport();
-        mSupportsFloat32Textures = mRenderer->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures);
-        mSupportsFloat16Textures = mRenderer->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures);
-        mSupportsLuminanceTextures = mRenderer->getLuminanceTextureSupport();
-        mSupportsLuminanceAlphaTextures = mRenderer->getLuminanceAlphaTextureSupport();
-        mSupportsDepthTextures = mRenderer->getDepthTextureSupport();
-        mSupportsTextureFilterAnisotropy = mRenderer->getTextureFilterAnisotropySupport();
-        mSupports32bitIndices = mRenderer->get32BitIndexSupport();
-
-        mNumCompressedTextureFormats = 0;
-        if (supportsDXT1Textures())
-        {
-            mNumCompressedTextureFormats += 2;
-        }
-        if (supportsDXT3Textures())
-        {
-            mNumCompressedTextureFormats += 1;
-        }
-        if (supportsDXT5Textures())
-        {
-            mNumCompressedTextureFormats += 1;
-        }
-
-        initExtensionString();
-        initRendererString();
-
-        mState.viewport.x = 0;
-        mState.viewport.y = 0;
-        mState.viewport.width = surface->getWidth();
-        mState.viewport.height = surface->getHeight();
-
-        mState.scissor.x = 0;
-        mState.scissor.y = 0;
-        mState.scissor.width = surface->getWidth();
-        mState.scissor.height = surface->getHeight();
-
-        mHasBeenCurrent = true;
-    }
-
-    // Wrap the existing swapchain resources into GL objects and assign them to the '0' names
-    rx::SwapChain *swapchain = surface->getSwapChain();
-
-    Colorbuffer *colorbufferZero = new Colorbuffer(mRenderer, swapchain);
-    DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(mRenderer, swapchain);
-    Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero);
-
-    setFramebufferZero(framebufferZero);
-}
-
-// NOTE: this function should not assume that this context is current!
-void Context::markContextLost()
-{
-    if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
-        mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
-    mContextLost = true;
-}
-
-bool Context::isContextLost()
-{
-    return mContextLost;
-}
-
-void Context::setClearColor(float red, float green, float blue, float alpha)
-{
-    mState.colorClearValue.red = red;
-    mState.colorClearValue.green = green;
-    mState.colorClearValue.blue = blue;
-    mState.colorClearValue.alpha = alpha;
-}
-
-void Context::setClearDepth(float depth)
-{
-    mState.depthClearValue = depth;
-}
-
-void Context::setClearStencil(int stencil)
-{
-    mState.stencilClearValue = stencil;
-}
-
-void Context::setCullFace(bool enabled)
-{
-    mState.rasterizer.cullFace = enabled;
-}
-
-bool Context::isCullFaceEnabled() const
-{
-    return mState.rasterizer.cullFace;
-}
-
-void Context::setCullMode(GLenum mode)
-{
-    mState.rasterizer.cullMode = mode;
-}
-
-void Context::setFrontFace(GLenum front)
-{
-    mState.rasterizer.frontFace = front;
-}
-
-void Context::setDepthTest(bool enabled)
-{
-    mState.depthStencil.depthTest = enabled;
-}
-
-bool Context::isDepthTestEnabled() const
-{
-    return mState.depthStencil.depthTest;
-}
-
-void Context::setDepthFunc(GLenum depthFunc)
-{
-     mState.depthStencil.depthFunc = depthFunc;
-}
-
-void Context::setDepthRange(float zNear, float zFar)
-{
-    mState.zNear = zNear;
-    mState.zFar = zFar;
-}
-
-void Context::setBlend(bool enabled)
-{
-    mState.blend.blend = enabled;
-}
-
-bool Context::isBlendEnabled() const
-{
-    return mState.blend.blend;
-}
-
-void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
-{
-    mState.blend.sourceBlendRGB = sourceRGB;
-    mState.blend.destBlendRGB = destRGB;
-    mState.blend.sourceBlendAlpha = sourceAlpha;
-    mState.blend.destBlendAlpha = destAlpha;
-}
-
-void Context::setBlendColor(float red, float green, float blue, float alpha)
-{
-    mState.blendColor.red = red;
-    mState.blendColor.green = green;
-    mState.blendColor.blue = blue;
-    mState.blendColor.alpha = alpha;
-}
-
-void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
-{
-    mState.blend.blendEquationRGB = rgbEquation;
-    mState.blend.blendEquationAlpha = alphaEquation;
-}
-
-void Context::setStencilTest(bool enabled)
-{
-    mState.depthStencil.stencilTest = enabled;
-}
-
-bool Context::isStencilTestEnabled() const
-{
-    return mState.depthStencil.stencilTest;
-}
-
-void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
-{
-    mState.depthStencil.stencilFunc = stencilFunc;
-    mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
-    mState.depthStencil.stencilMask = stencilMask;
-}
-
-void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
-{
-    mState.depthStencil.stencilBackFunc = stencilBackFunc;
-    mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
-    mState.depthStencil.stencilBackMask = stencilBackMask;
-}
-
-void Context::setStencilWritemask(GLuint stencilWritemask)
-{
-    mState.depthStencil.stencilWritemask = stencilWritemask;
-}
-
-void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
-{
-    mState.depthStencil.stencilBackWritemask = stencilBackWritemask;
-}
-
-void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
-{
-    mState.depthStencil.stencilFail = stencilFail;
-    mState.depthStencil.stencilPassDepthFail = stencilPassDepthFail;
-    mState.depthStencil.stencilPassDepthPass = stencilPassDepthPass;
-}
-
-void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
-{
-    mState.depthStencil.stencilBackFail = stencilBackFail;
-    mState.depthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail;
-    mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
-}
-
-void Context::setPolygonOffsetFill(bool enabled)
-{
-     mState.rasterizer.polygonOffsetFill = enabled;
-}
-
-bool Context::isPolygonOffsetFillEnabled() const
-{
-    return mState.rasterizer.polygonOffsetFill;
-}
-
-void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
-{
-    // An application can pass NaN values here, so handle this gracefully
-    mState.rasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor;
-    mState.rasterizer.polygonOffsetUnits = units != units ? 0.0f : units;
-}
-
-void Context::setSampleAlphaToCoverage(bool enabled)
-{
-    mState.blend.sampleAlphaToCoverage = enabled;
-}
-
-bool Context::isSampleAlphaToCoverageEnabled() const
-{
-    return mState.blend.sampleAlphaToCoverage;
-}
-
-void Context::setSampleCoverage(bool enabled)
-{
-    mState.sampleCoverage = enabled;
-}
-
-bool Context::isSampleCoverageEnabled() const
-{
-    return mState.sampleCoverage;
-}
-
-void Context::setSampleCoverageParams(GLclampf value, bool invert)
-{
-    mState.sampleCoverageValue = value;
-    mState.sampleCoverageInvert = invert;
-}
-
-void Context::setScissorTest(bool enabled)
-{
-    mState.scissorTest = enabled;
-}
-
-bool Context::isScissorTestEnabled() const
-{
-    return mState.scissorTest;
-}
-
-void Context::setDither(bool enabled)
-{
-    mState.blend.dither = enabled;
-}
-
-bool Context::isDitherEnabled() const
-{
-    return mState.blend.dither;
-}
-
-void Context::setLineWidth(GLfloat width)
-{
-    mState.lineWidth = width;
-}
-
-void Context::setGenerateMipmapHint(GLenum hint)
-{
-    mState.generateMipmapHint = hint;
-}
-
-void Context::setFragmentShaderDerivativeHint(GLenum hint)
-{
-    mState.fragmentShaderDerivativeHint = hint;
-    // TODO: Propagate the hint to shader translator so we can write
-    // ddx, ddx_coarse, or ddx_fine depending on the hint.
-    // Ignore for now. It is valid for implementations to ignore hint.
-}
-
-void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
-{
-    mState.viewport.x = x;
-    mState.viewport.y = y;
-    mState.viewport.width = width;
-    mState.viewport.height = height;
-}
-
-void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
-{
-    mState.scissor.x = x;
-    mState.scissor.y = y;
-    mState.scissor.width = width;
-    mState.scissor.height = height;
-}
-
-void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
-{
-    mState.blend.colorMaskRed = red;
-    mState.blend.colorMaskGreen = green;
-    mState.blend.colorMaskBlue = blue;
-    mState.blend.colorMaskAlpha = alpha;
-}
-
-void Context::setDepthMask(bool mask)
-{
-    mState.depthStencil.depthMask = mask;
-}
-
-void Context::setActiveSampler(unsigned int active)
-{
-    mState.activeSampler = active;
-}
-
-GLuint Context::getReadFramebufferHandle() const
-{
-    return mState.readFramebuffer;
-}
-
-GLuint Context::getDrawFramebufferHandle() const
-{
-    return mState.drawFramebuffer;
-}
-
-GLuint Context::getRenderbufferHandle() const
-{
-    return mState.renderbuffer.id();
-}
-
-GLuint Context::getArrayBufferHandle() const
-{
-    return mState.arrayBuffer.id();
-}
-
-GLuint Context::getActiveQuery(GLenum target) const
-{
-    Query *queryObject = NULL;
-    
-    switch (target)
-    {
-      case GL_ANY_SAMPLES_PASSED_EXT:
-        queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();
-        break;
-      case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
-        queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();
-        break;
-      default:
-        ASSERT(false);
-    }
-
-    if (queryObject)
-    {
-        return queryObject->id();
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
-{
-    mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
-}
-
-const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
-{
-    return mState.vertexAttribute[attribNum];
-}
-
-void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
-                                   GLsizei stride, const void *pointer)
-{
-    mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
-    mState.vertexAttribute[attribNum].mSize = size;
-    mState.vertexAttribute[attribNum].mType = type;
-    mState.vertexAttribute[attribNum].mNormalized = normalized;
-    mState.vertexAttribute[attribNum].mStride = stride;
-    mState.vertexAttribute[attribNum].mPointer = pointer;
-}
-
-const void *Context::getVertexAttribPointer(unsigned int attribNum) const
-{
-    return mState.vertexAttribute[attribNum].mPointer;
-}
-
-void Context::setPackAlignment(GLint alignment)
-{
-    mState.packAlignment = alignment;
-}
-
-GLint Context::getPackAlignment() const
-{
-    return mState.packAlignment;
-}
-
-void Context::setUnpackAlignment(GLint alignment)
-{
-    mState.unpackAlignment = alignment;
-}
-
-GLint Context::getUnpackAlignment() const
-{
-    return mState.unpackAlignment;
-}
-
-void Context::setPackReverseRowOrder(bool reverseRowOrder)
-{
-    mState.packReverseRowOrder = reverseRowOrder;
-}
-
-bool Context::getPackReverseRowOrder() const
-{
-    return mState.packReverseRowOrder;
-}
-
-GLuint Context::createBuffer()
-{
-    return mResourceManager->createBuffer();
-}
-
-GLuint Context::createProgram()
-{
-    return mResourceManager->createProgram();
-}
-
-GLuint Context::createShader(GLenum type)
-{
-    return mResourceManager->createShader(type);
-}
-
-GLuint Context::createTexture()
-{
-    return mResourceManager->createTexture();
-}
-
-#if defined(__LB_XB360__)
-void Context::setVideoTexture(GLuint texture)
-{
-    mResourceManager->setVideoTextureHandle(texture);
-    mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
-}
-
-GLuint Context::getVideoTexture()
-{
-    return mResourceManager->getVideoTextureHandle();
-}
-#endif
-
-GLuint Context::createRenderbuffer()
-{
-    return mResourceManager->createRenderbuffer();
-}
-
-// Returns an unused framebuffer name
-GLuint Context::createFramebuffer()
-{
-    GLuint handle = mFramebufferHandleAllocator.allocate();
-
-    mFramebufferMap[handle] = NULL;
-
-    return handle;
-}
-
-GLuint Context::createFence()
-{
-    GLuint handle = mFenceHandleAllocator.allocate();
-
-    mFenceMap[handle] = new Fence(mRenderer);
-
-    return handle;
-}
-
-// Returns an unused query name
-GLuint Context::createQuery()
-{
-    GLuint handle = mQueryHandleAllocator.allocate();
-
-    mQueryMap[handle] = NULL;
-
-    return handle;
-}
-
-void Context::deleteBuffer(GLuint buffer)
-{
-    if (mResourceManager->getBuffer(buffer))
-    {
-        detachBuffer(buffer);
-    }
-    
-    mResourceManager->deleteBuffer(buffer);
-}
-
-void Context::deleteShader(GLuint shader)
-{
-    mResourceManager->deleteShader(shader);
-}
-
-void Context::deleteProgram(GLuint program)
-{
-    mResourceManager->deleteProgram(program);
-}
-
-void Context::deleteTexture(GLuint texture)
-{
-    if (mResourceManager->getTexture(texture))
-    {
-        detachTexture(texture);
-    }
-
-    mResourceManager->deleteTexture(texture);
-}
-
-void Context::deleteRenderbuffer(GLuint renderbuffer)
-{
-    if (mResourceManager->getRenderbuffer(renderbuffer))
-    {
-        detachRenderbuffer(renderbuffer);
-    }
-    
-    mResourceManager->deleteRenderbuffer(renderbuffer);
-}
-
-void Context::deleteFramebuffer(GLuint framebuffer)
-{
-    FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
-
-    if (framebufferObject != mFramebufferMap.end())
-    {
-        detachFramebuffer(framebuffer);
-
-        mFramebufferHandleAllocator.release(framebufferObject->first);
-        delete framebufferObject->second;
-        mFramebufferMap.erase(framebufferObject);
-    }
-}
-
-void Context::deleteFence(GLuint fence)
-{
-    FenceMap::iterator fenceObject = mFenceMap.find(fence);
-
-    if (fenceObject != mFenceMap.end())
-    {
-        mFenceHandleAllocator.release(fenceObject->first);
-        delete fenceObject->second;
-        mFenceMap.erase(fenceObject);
-    }
-}
-
-void Context::deleteQuery(GLuint query)
-{
-    QueryMap::iterator queryObject = mQueryMap.find(query);
-    if (queryObject != mQueryMap.end())
-    {
-        mQueryHandleAllocator.release(queryObject->first);
-        if (queryObject->second)
-        {
-            queryObject->second->release();
-        }
-        mQueryMap.erase(queryObject);
-    }
-}
-
-Buffer *Context::getBuffer(GLuint handle)
-{
-    return mResourceManager->getBuffer(handle);
-}
-
-Shader *Context::getShader(GLuint handle)
-{
-    return mResourceManager->getShader(handle);
-}
-
-Program *Context::getProgram(GLuint handle)
-{
-    return mResourceManager->getProgram(handle);
-}
-
-Texture *Context::getTexture(GLuint handle)
-{
-    return mResourceManager->getTexture(handle);
-}
-
-Renderbuffer *Context::getRenderbuffer(GLuint handle)
-{
-    return mResourceManager->getRenderbuffer(handle);
-}
-
-Framebuffer *Context::getReadFramebuffer()
-{
-    return getFramebuffer(mState.readFramebuffer);
-}
-
-Framebuffer *Context::getDrawFramebuffer()
-{
-    return mBoundDrawFramebuffer;
-}
-
-void Context::bindArrayBuffer(unsigned int buffer)
-{
-    mResourceManager->checkBufferAllocation(buffer);
-
-    mState.arrayBuffer.set(getBuffer(buffer));
-}
-
-void Context::bindElementArrayBuffer(unsigned int buffer)
-{
-    mResourceManager->checkBufferAllocation(buffer);
-
-    mState.elementArrayBuffer.set(getBuffer(buffer));
-}
-
-void Context::bindTexture2D(GLuint texture)
-{
-    mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
-
-    mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
-}
-
-void Context::bindTextureCubeMap(GLuint texture)
-{
-    mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
-
-    mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
-}
-
-void Context::bindReadFramebuffer(GLuint framebuffer)
-{
-    if (!getFramebuffer(framebuffer))
-    {
-        mFramebufferMap[framebuffer] = new Framebuffer(mRenderer);
-    }
-
-    mState.readFramebuffer = framebuffer;
-}
-
-void Context::bindDrawFramebuffer(GLuint framebuffer)
-{
-    if (!getFramebuffer(framebuffer))
-    {
-        mFramebufferMap[framebuffer] = new Framebuffer(mRenderer);
-    }
-
-    mState.drawFramebuffer = framebuffer;
-
-    mBoundDrawFramebuffer = getFramebuffer(framebuffer);
-}
-
-void Context::bindRenderbuffer(GLuint renderbuffer)
-{
-    mResourceManager->checkRenderbufferAllocation(renderbuffer);
-
-    mState.renderbuffer.set(getRenderbuffer(renderbuffer));
-}
-
-void Context::useProgram(GLuint program)
-{
-    GLuint priorProgram = mState.currentProgram;
-    mState.currentProgram = program;               // Must switch before trying to delete, otherwise it only gets flagged.
-
-    if (priorProgram != program)
-    {
-        Program *newProgram = mResourceManager->getProgram(program);
-        Program *oldProgram = mResourceManager->getProgram(priorProgram);
-        mCurrentProgramBinary.set(NULL);
-
-        if (newProgram)
-        {
-            newProgram->addRef();
-            mCurrentProgramBinary.set(newProgram->getProgramBinary());
-        }
-        
-        if (oldProgram)
-        {
-            oldProgram->release();
-        }
-    }
-}
-
-void Context::linkProgram(GLuint program)
-{
-    Program *programObject = mResourceManager->getProgram(program);
-
-    bool linked = programObject->link();
-
-    // if the current program was relinked successfully we
-    // need to install the new executables
-    if (linked && program == mState.currentProgram)
-    {
-        mCurrentProgramBinary.set(programObject->getProgramBinary());
-    }
-}
-
-void Context::setProgramBinary(GLuint program, const void *binary, GLint length)
-{
-    Program *programObject = mResourceManager->getProgram(program);
-
-    bool loaded = programObject->setProgramBinary(binary, length);
-
-    // if the current program was reloaded successfully we
-    // need to install the new executables
-    if (loaded && program == mState.currentProgram)
-    {
-        mCurrentProgramBinary.set(programObject->getProgramBinary());
-    }
-
-}
-
-void Context::beginQuery(GLenum target, GLuint query)
-{
-    // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>  
-    // of zero, if the active query object name for <target> is non-zero (for the  
-    // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if  
-    // the active query for either target is non-zero), if <id> is the name of an 
-    // existing query object whose type does not match <target>, or if <id> is the
-    // active query object name for any query type, the error INVALID_OPERATION is
-    // generated.
-
-    // Ensure no other queries are active
-    // NOTE: If other queries than occlusion are supported, we will need to check
-    // separately that:
-    //    a) The query ID passed is not the current active query for any target/type
-    //    b) There are no active queries for the requested target (and in the case
-    //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
-    //       no query may be active for either if glBeginQuery targets either.
-    for (int i = 0; i < QUERY_TYPE_COUNT; i++)
-    {
-        if (mState.activeQuery[i].get() != NULL)
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
-    }
-
-    QueryType qType;
-    switch (target)
-    {
-      case GL_ANY_SAMPLES_PASSED_EXT: 
-        qType = QUERY_ANY_SAMPLES_PASSED; 
-        break;
-      case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: 
-        qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; 
-        break;
-      default: 
-        ASSERT(false);
-        return;
-    }
-
-    Query *queryObject = getQuery(query, true, target);
-
-    // check that name was obtained with glGenQueries
-    if (!queryObject)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    // check for type mismatch
-    if (queryObject->getType() != target)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    // set query as active for specified target
-    mState.activeQuery[qType].set(queryObject);
-
-    // begin query
-    queryObject->begin();
-}
-
-void Context::endQuery(GLenum target)
-{
-    QueryType qType;
-
-    switch (target)
-    {
-      case GL_ANY_SAMPLES_PASSED_EXT: 
-        qType = QUERY_ANY_SAMPLES_PASSED; 
-        break;
-      case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: 
-        qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; 
-        break;
-      default: 
-        ASSERT(false);
-        return;
-    }
-
-    Query *queryObject = mState.activeQuery[qType].get();
-
-    if (queryObject == NULL)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    queryObject->end();
-
-    mState.activeQuery[qType].set(NULL);
-}
-
-void Context::setFramebufferZero(Framebuffer *buffer)
-{
-    delete mFramebufferMap[0];
-    mFramebufferMap[0] = buffer;
-    if (mState.drawFramebuffer == 0)
-    {
-        mBoundDrawFramebuffer = buffer;
-    }
-}
-
-void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
-{
-    RenderbufferStorage *renderbuffer = NULL;
-    switch (internalformat)
-    {
-      case GL_DEPTH_COMPONENT16:
-        renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples);
-        break;
-      case GL_RGBA4:
-      case GL_RGB5_A1:
-      case GL_RGB565:
-      case GL_RGB8_OES:
-      case GL_RGBA8_OES:
-        renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples);
-        break;
-      case GL_STENCIL_INDEX8:
-        renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples);
-        break;
-      case GL_DEPTH24_STENCIL8_OES:
-        renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples);
-        break;
-      default:
-        UNREACHABLE(); return;
-    }
-
-    Renderbuffer *renderbufferObject = mState.renderbuffer.get();
-    renderbufferObject->setStorage(renderbuffer);
-}
-
-Framebuffer *Context::getFramebuffer(unsigned int handle)
-{
-    FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
-
-    if (framebuffer == mFramebufferMap.end())
-    {
-        return NULL;
-    }
-    else
-    {
-        return framebuffer->second;
-    }
-}
-
-Fence *Context::getFence(unsigned int handle)
-{
-    FenceMap::iterator fence = mFenceMap.find(handle);
-
-    if (fence == mFenceMap.end())
-    {
-        return NULL;
-    }
-    else
-    {
-        return fence->second;
-    }
-}
-
-Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
-{
-    QueryMap::iterator query = mQueryMap.find(handle);
-
-    if (query == mQueryMap.end())
-    {
-        return NULL;
-    }
-    else
-    {
-        if (!query->second && create)
-        {
-            query->second = new Query(mRenderer, type, handle);
-            query->second->addRef();
-        }
-        return query->second;
-    }
-}
-
-Buffer *Context::getArrayBuffer()
-{
-    return mState.arrayBuffer.get();
-}
-
-Buffer *Context::getElementArrayBuffer()
-{
-    return mState.elementArrayBuffer.get();
-}
-
-ProgramBinary *Context::getCurrentProgramBinary()
-{
-    return mCurrentProgramBinary.get();
-}
-
-Texture2D *Context::getTexture2D()
-{
-    return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
-}
-
-TextureCubeMap *Context::getTextureCubeMap()
-{
-    return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
-}
-
-Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
-{
-    GLuint texid = mState.samplerTexture[type][sampler].id();
-
-    if (texid == 0)   // Special case: 0 refers to different initial textures based on the target
-    {
-        switch (type)
-        {
-          default: UNREACHABLE();
-          case TEXTURE_2D: return mTexture2DZero.get();
-          case TEXTURE_CUBE: return mTextureCubeMapZero.get();
-        }
-    }
-
-    return mState.samplerTexture[type][sampler].get();
-}
-
-bool Context::getBooleanv(GLenum pname, GLboolean *params)
-{
-    switch (pname)
-    {
-      case GL_SHADER_COMPILER:           *params = GL_TRUE;                             break;
-      case GL_SAMPLE_COVERAGE_INVERT:    *params = mState.sampleCoverageInvert;         break;
-      case GL_DEPTH_WRITEMASK:           *params = mState.depthStencil.depthMask;       break;
-      case GL_COLOR_WRITEMASK:
-        params[0] = mState.blend.colorMaskRed;
-        params[1] = mState.blend.colorMaskGreen;
-        params[2] = mState.blend.colorMaskBlue;
-        params[3] = mState.blend.colorMaskAlpha;
-        break;
-      case GL_CULL_FACE:                 *params = mState.rasterizer.cullFace;          break;
-      case GL_POLYGON_OFFSET_FILL:       *params = mState.rasterizer.polygonOffsetFill; break;
-      case GL_SAMPLE_ALPHA_TO_COVERAGE:  *params = mState.blend.sampleAlphaToCoverage;  break;
-      case GL_SAMPLE_COVERAGE:           *params = mState.sampleCoverage;               break;
-      case GL_SCISSOR_TEST:              *params = mState.scissorTest;                  break;
-      case GL_STENCIL_TEST:              *params = mState.depthStencil.stencilTest;     break;
-      case GL_DEPTH_TEST:                *params = mState.depthStencil.depthTest;       break;
-      case GL_BLEND:                     *params = mState.blend.blend;                  break;
-      case GL_DITHER:                    *params = mState.blend.dither;                 break;
-      case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE;  break;
-      default:
-        return false;
-    }
-
-    return true;
-}
-
-bool Context::getFloatv(GLenum pname, GLfloat *params)
-{
-    // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
-    // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
-    // GetIntegerv as its native query function. As it would require conversion in any
-    // case, this should make no difference to the calling application.
-    switch (pname)
-    {
-      case GL_LINE_WIDTH:               *params = mState.lineWidth;                         break;
-      case GL_SAMPLE_COVERAGE_VALUE:    *params = mState.sampleCoverageValue;               break;
-      case GL_DEPTH_CLEAR_VALUE:        *params = mState.depthClearValue;                   break;
-      case GL_POLYGON_OFFSET_FACTOR:    *params = mState.rasterizer.polygonOffsetFactor;    break;
-      case GL_POLYGON_OFFSET_UNITS:     *params = mState.rasterizer.polygonOffsetUnits;     break;
-      case GL_ALIASED_LINE_WIDTH_RANGE:
-        params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
-        params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
-        break;
-      case GL_ALIASED_POINT_SIZE_RANGE:
-        params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
-        params[1] = getMaximumPointSize();
-        break;
-      case GL_DEPTH_RANGE:
-        params[0] = mState.zNear;
-        params[1] = mState.zFar;
-        break;
-      case GL_COLOR_CLEAR_VALUE:
-        params[0] = mState.colorClearValue.red;
-        params[1] = mState.colorClearValue.green;
-        params[2] = mState.colorClearValue.blue;
-        params[3] = mState.colorClearValue.alpha;
-        break;
-      case GL_BLEND_COLOR:
-        params[0] = mState.blendColor.red;
-        params[1] = mState.blendColor.green;
-        params[2] = mState.blendColor.blue;
-        params[3] = mState.blendColor.alpha;
-        break;
-      case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
-        if (!supportsTextureFilterAnisotropy())
-        {
-            return false;
-        }
-        *params = mMaxTextureAnisotropy;
-        break;
-      default:
-        return false;
-    }
-
-    return true;
-}
-
-bool Context::getIntegerv(GLenum pname, GLint *params)
-{
-    if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
-    {
-        unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
-
-        if (colorAttachment >= mRenderer->getMaxRenderTargets())
-        {
-            // return true to stop further operation in the parent call
-            return gl::error(GL_INVALID_OPERATION, true);
-        }
-
-        Framebuffer *framebuffer = getDrawFramebuffer();
-
-        *params = framebuffer->getDrawBufferState(colorAttachment);
-        return true;
-    }
-
-    // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
-    // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
-    // GetIntegerv as its native query function. As it would require conversion in any
-    // case, this should make no difference to the calling application. You may find it in 
-    // Context::getFloatv.
-    switch (pname)
-    {
-      case GL_MAX_VERTEX_ATTRIBS:               *params = gl::MAX_VERTEX_ATTRIBS;               break;
-      case GL_MAX_VERTEX_UNIFORM_VECTORS:       *params = mRenderer->getMaxVertexUniformVectors(); break;
-      case GL_MAX_VARYING_VECTORS:              *params = mRenderer->getMaxVaryingVectors();    break;
-      case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxCombinedTextureImageUnits(); break;
-      case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:   *params = mRenderer->getMaxVertexTextureImageUnits(); break;
-      case GL_MAX_TEXTURE_IMAGE_UNITS:          *params = gl::MAX_TEXTURE_IMAGE_UNITS;          break;
-      case GL_MAX_FRAGMENT_UNIFORM_VECTORS:     *params = mRenderer->getMaxFragmentUniformVectors(); break;
-      case GL_MAX_RENDERBUFFER_SIZE:            *params = getMaximumRenderbufferDimension();    break;
-      case GL_MAX_COLOR_ATTACHMENTS_EXT:        *params = mRenderer->getMaxRenderTargets();     break;
-      case GL_MAX_DRAW_BUFFERS_EXT:             *params = mRenderer->getMaxRenderTargets();     break;
-      case GL_NUM_SHADER_BINARY_FORMATS:        *params = 0;                                    break;
-      case GL_SHADER_BINARY_FORMATS:      /* no shader binary formats are supported */          break;
-      case GL_ARRAY_BUFFER_BINDING:             *params = mState.arrayBuffer.id();              break;
-      case GL_ELEMENT_ARRAY_BUFFER_BINDING:     *params = mState.elementArrayBuffer.id();       break;
-      //case GL_FRAMEBUFFER_BINDING:            // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
-      case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.drawFramebuffer;               break;
-      case GL_READ_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.readFramebuffer;               break;
-      case GL_RENDERBUFFER_BINDING:             *params = mState.renderbuffer.id();             break;
-      case GL_CURRENT_PROGRAM:                  *params = mState.currentProgram;                break;
-      case GL_PACK_ALIGNMENT:                   *params = mState.packAlignment;                 break;
-      case GL_PACK_REVERSE_ROW_ORDER_ANGLE:     *params = mState.packReverseRowOrder;           break;
-      case GL_UNPACK_ALIGNMENT:                 *params = mState.unpackAlignment;               break;
-      case GL_GENERATE_MIPMAP_HINT:             *params = mState.generateMipmapHint;            break;
-      case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
-      case GL_ACTIVE_TEXTURE:                   *params = (mState.activeSampler + GL_TEXTURE0); break;
-      case GL_STENCIL_FUNC:                     *params = mState.depthStencil.stencilFunc;             break;
-      case GL_STENCIL_REF:                      *params = mState.stencilRef;                           break;
-      case GL_STENCIL_VALUE_MASK:               *params = mState.depthStencil.stencilMask;             break;
-      case GL_STENCIL_BACK_FUNC:                *params = mState.depthStencil.stencilBackFunc;         break;
-      case GL_STENCIL_BACK_REF:                 *params = mState.stencilBackRef;                       break;
-      case GL_STENCIL_BACK_VALUE_MASK:          *params = mState.depthStencil.stencilBackMask;         break;
-      case GL_STENCIL_FAIL:                     *params = mState.depthStencil.stencilFail;             break;
-      case GL_STENCIL_PASS_DEPTH_FAIL:          *params = mState.depthStencil.stencilPassDepthFail;    break;
-      case GL_STENCIL_PASS_DEPTH_PASS:          *params = mState.depthStencil.stencilPassDepthPass;    break;
-      case GL_STENCIL_BACK_FAIL:                *params = mState.depthStencil.stencilBackFail;         break;
-      case GL_STENCIL_BACK_PASS_DEPTH_FAIL:     *params = mState.depthStencil.stencilBackPassDepthFail; break;
-      case GL_STENCIL_BACK_PASS_DEPTH_PASS:     *params = mState.depthStencil.stencilBackPassDepthPass; break;
-      case GL_DEPTH_FUNC:                       *params = mState.depthStencil.depthFunc;               break;
-      case GL_BLEND_SRC_RGB:                    *params = mState.blend.sourceBlendRGB;                 break;
-      case GL_BLEND_SRC_ALPHA:                  *params = mState.blend.sourceBlendAlpha;               break;
-      case GL_BLEND_DST_RGB:                    *params = mState.blend.destBlendRGB;                   break;
-      case GL_BLEND_DST_ALPHA:                  *params = mState.blend.destBlendAlpha;                 break;
-      case GL_BLEND_EQUATION_RGB:               *params = mState.blend.blendEquationRGB;               break;
-      case GL_BLEND_EQUATION_ALPHA:             *params = mState.blend.blendEquationAlpha;             break;
-      case GL_STENCIL_WRITEMASK:                *params = mState.depthStencil.stencilWritemask;        break;
-      case GL_STENCIL_BACK_WRITEMASK:           *params = mState.depthStencil.stencilBackWritemask;    break;
-      case GL_STENCIL_CLEAR_VALUE:              *params = mState.stencilClearValue;             break;
-      case GL_SUBPIXEL_BITS:                    *params = 4;                                    break;
-      case GL_MAX_TEXTURE_SIZE:                 *params = getMaximumTextureDimension();         break;
-      case GL_MAX_CUBE_MAP_TEXTURE_SIZE:        *params = getMaximumCubeTextureDimension();     break;
-      case GL_NUM_COMPRESSED_TEXTURE_FORMATS:   
-        params[0] = mNumCompressedTextureFormats;
-        break;
-      case GL_MAX_SAMPLES_ANGLE:
-        {
-            GLsizei maxSamples = getMaxSupportedSamples();
-            if (maxSamples != 0)
-            {
-                *params = maxSamples;
-            }
-            else
-            {
-                return false;
-            }
-
-            break;
-        }
-      case GL_SAMPLE_BUFFERS:                   
-      case GL_SAMPLES:
-        {
-            gl::Framebuffer *framebuffer = getDrawFramebuffer();
-            if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
-            {
-                switch (pname)
-                {
-                  case GL_SAMPLE_BUFFERS:
-                    if (framebuffer->getSamples() != 0)
-                    {
-                        *params = 1;
-                    }
-                    else
-                    {
-                        *params = 0;
-                    }
-                    break;
-                  case GL_SAMPLES:
-                    *params = framebuffer->getSamples();
-                    break;
-                }
-            }
-            else 
-            {
-                *params = 0;
-            }
-        }
-        break;
-      case GL_IMPLEMENTATION_COLOR_READ_TYPE:
-      case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
-        {
-            GLenum format, type;
-            if (getCurrentReadFormatType(&format, &type))
-            {
-                if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT)
-                    *params = format;
-                else
-                    *params = type;
-            }
-        }
-        break;
-      case GL_MAX_VIEWPORT_DIMS:
-        {
-            params[0] = mMaxViewportDimension;
-            params[1] = mMaxViewportDimension;
-        }
-        break;
-      case GL_COMPRESSED_TEXTURE_FORMATS:
-        {
-            if (supportsDXT1Textures())
-            {
-                *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
-                *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
-            }
-            if (supportsDXT3Textures())
-            {
-                *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
-            }
-            if (supportsDXT5Textures())
-            {
-                *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
-            }
-        }
-        break;
-      case GL_VIEWPORT:
-        params[0] = mState.viewport.x;
-        params[1] = mState.viewport.y;
-        params[2] = mState.viewport.width;
-        params[3] = mState.viewport.height;
-        break;
-      case GL_SCISSOR_BOX:
-        params[0] = mState.scissor.x;
-        params[1] = mState.scissor.y;
-        params[2] = mState.scissor.width;
-        params[3] = mState.scissor.height;
-        break;
-      case GL_CULL_FACE_MODE:                   *params = mState.rasterizer.cullMode;   break;
-      case GL_FRONT_FACE:                       *params = mState.rasterizer.frontFace;  break;
-      case GL_RED_BITS:
-      case GL_GREEN_BITS:
-      case GL_BLUE_BITS:
-      case GL_ALPHA_BITS:
-        {
-            gl::Framebuffer *framebuffer = getDrawFramebuffer();
-            gl::Renderbuffer *colorbuffer = framebuffer->getFirstColorbuffer();
-
-            if (colorbuffer)
-            {
-                switch (pname)
-                {
-                  case GL_RED_BITS:   *params = colorbuffer->getRedSize();      break;
-                  case GL_GREEN_BITS: *params = colorbuffer->getGreenSize();    break;
-                  case GL_BLUE_BITS:  *params = colorbuffer->getBlueSize();     break;
-                  case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize();    break;
-                }
-            }
-            else
-            {
-                *params = 0;
-            }
-        }
-        break;
-      case GL_DEPTH_BITS:
-        {
-            gl::Framebuffer *framebuffer = getDrawFramebuffer();
-            gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
-
-            if (depthbuffer)
-            {
-                *params = depthbuffer->getDepthSize();
-            }
-            else
-            {
-                *params = 0;
-            }
-        }
-        break;
-      case GL_STENCIL_BITS:
-        {
-            gl::Framebuffer *framebuffer = getDrawFramebuffer();
-            gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
-
-            if (stencilbuffer)
-            {
-                *params = stencilbuffer->getStencilSize();
-            }
-            else
-            {
-                *params = 0;
-            }
-        }
-        break;
-      case GL_TEXTURE_BINDING_2D:
-        {
-            if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1)
-            {
-                gl::error(GL_INVALID_OPERATION);
-                return false;
-            }
-
-            *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
-        }
-        break;
-      case GL_TEXTURE_BINDING_CUBE_MAP:
-        {
-            if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1)
-            {
-                gl::error(GL_INVALID_OPERATION);
-                return false;
-            }
-
-            *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
-        }
-        break;
-      case GL_RESET_NOTIFICATION_STRATEGY_EXT:
-        *params = mResetStrategy;
-        break;
-      case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
-        *params = 1;
-        break;
-      case GL_PROGRAM_BINARY_FORMATS_OES:
-        *params = GL_PROGRAM_BINARY_ANGLE;
-        break;
-      default:
-        return false;
-    }
-
-    return true;
-}
-
-bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
-{
-    if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
-    {
-        *type = GL_INT;
-        *numParams = 1;
-        return true;
-    }
-
-    // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
-    // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
-    // to the fact that it is stored internally as a float, and so would require conversion
-    // if returned from Context::getIntegerv. Since this conversion is already implemented 
-    // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
-    // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
-    // application.
-    switch (pname)
-    {
-      case GL_COMPRESSED_TEXTURE_FORMATS:
-        {
-            *type = GL_INT;
-            *numParams = mNumCompressedTextureFormats;
-        }
-        break;
-      case GL_SHADER_BINARY_FORMATS:
-        {
-            *type = GL_INT;
-            *numParams = 0;
-        }
-        break;
-      case GL_MAX_VERTEX_ATTRIBS:
-      case GL_MAX_VERTEX_UNIFORM_VECTORS:
-      case GL_MAX_VARYING_VECTORS:
-      case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
-      case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
-      case GL_MAX_TEXTURE_IMAGE_UNITS:
-      case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
-      case GL_MAX_RENDERBUFFER_SIZE:
-      case GL_MAX_COLOR_ATTACHMENTS_EXT:
-      case GL_MAX_DRAW_BUFFERS_EXT:
-      case GL_NUM_SHADER_BINARY_FORMATS:
-      case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
-      case GL_ARRAY_BUFFER_BINDING:
-      case GL_FRAMEBUFFER_BINDING:
-      case GL_RENDERBUFFER_BINDING:
-      case GL_CURRENT_PROGRAM:
-      case GL_PACK_ALIGNMENT:
-      case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
-      case GL_UNPACK_ALIGNMENT:
-      case GL_GENERATE_MIPMAP_HINT:
-      case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
-      case GL_RED_BITS:
-      case GL_GREEN_BITS:
-      case GL_BLUE_BITS:
-      case GL_ALPHA_BITS:
-      case GL_DEPTH_BITS:
-      case GL_STENCIL_BITS:
-      case GL_ELEMENT_ARRAY_BUFFER_BINDING:
-      case GL_CULL_FACE_MODE:
-      case GL_FRONT_FACE:
-      case GL_ACTIVE_TEXTURE:
-      case GL_STENCIL_FUNC:
-      case GL_STENCIL_VALUE_MASK:
-      case GL_STENCIL_REF:
-      case GL_STENCIL_FAIL:
-      case GL_STENCIL_PASS_DEPTH_FAIL:
-      case GL_STENCIL_PASS_DEPTH_PASS:
-      case GL_STENCIL_BACK_FUNC:
-      case GL_STENCIL_BACK_VALUE_MASK:
-      case GL_STENCIL_BACK_REF:
-      case GL_STENCIL_BACK_FAIL:
-      case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
-      case GL_STENCIL_BACK_PASS_DEPTH_PASS:
-      case GL_DEPTH_FUNC:
-      case GL_BLEND_SRC_RGB:
-      case GL_BLEND_SRC_ALPHA:
-      case GL_BLEND_DST_RGB:
-      case GL_BLEND_DST_ALPHA:
-      case GL_BLEND_EQUATION_RGB:
-      case GL_BLEND_EQUATION_ALPHA:
-      case GL_STENCIL_WRITEMASK:
-      case GL_STENCIL_BACK_WRITEMASK:
-      case GL_STENCIL_CLEAR_VALUE:
-      case GL_SUBPIXEL_BITS:
-      case GL_MAX_TEXTURE_SIZE:
-      case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
-      case GL_SAMPLE_BUFFERS:
-      case GL_SAMPLES:
-      case GL_IMPLEMENTATION_COLOR_READ_TYPE:
-      case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
-      case GL_TEXTURE_BINDING_2D:
-      case GL_TEXTURE_BINDING_CUBE_MAP:
-      case GL_RESET_NOTIFICATION_STRATEGY_EXT:
-      case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
-      case GL_PROGRAM_BINARY_FORMATS_OES:
-        {
-            *type = GL_INT;
-            *numParams = 1;
-        }
-        break;
-      case GL_MAX_SAMPLES_ANGLE:
-        {
-            if (getMaxSupportedSamples() != 0)
-            {
-                *type = GL_INT;
-                *numParams = 1;
-            }
-            else
-            {
-                return false;
-            }
-        }
-        break;
-      case GL_MAX_VIEWPORT_DIMS:
-        {
-            *type = GL_INT;
-            *numParams = 2;
-        }
-        break;
-      case GL_VIEWPORT:
-      case GL_SCISSOR_BOX:
-        {
-            *type = GL_INT;
-            *numParams = 4;
-        }
-        break;
-      case GL_SHADER_COMPILER:
-      case GL_SAMPLE_COVERAGE_INVERT:
-      case GL_DEPTH_WRITEMASK:
-      case GL_CULL_FACE:                // CULL_FACE through DITHER are natural to IsEnabled,
-      case GL_POLYGON_OFFSET_FILL:      // but can be retrieved through the Get{Type}v queries.
-      case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
-      case GL_SAMPLE_COVERAGE:
-      case GL_SCISSOR_TEST:
-      case GL_STENCIL_TEST:
-      case GL_DEPTH_TEST:
-      case GL_BLEND:
-      case GL_DITHER:
-      case GL_CONTEXT_ROBUST_ACCESS_EXT:
-        {
-            *type = GL_BOOL;
-            *numParams = 1;
-        }
-        break;
-      case GL_COLOR_WRITEMASK:
-        {
-            *type = GL_BOOL;
-            *numParams = 4;
-        }
-        break;
-      case GL_POLYGON_OFFSET_FACTOR:
-      case GL_POLYGON_OFFSET_UNITS:
-      case GL_SAMPLE_COVERAGE_VALUE:
-      case GL_DEPTH_CLEAR_VALUE:
-      case GL_LINE_WIDTH:
-        {
-            *type = GL_FLOAT;
-            *numParams = 1;
-        }
-        break;
-      case GL_ALIASED_LINE_WIDTH_RANGE:
-      case GL_ALIASED_POINT_SIZE_RANGE:
-      case GL_DEPTH_RANGE:
-        {
-            *type = GL_FLOAT;
-            *numParams = 2;
-        }
-        break;
-      case GL_COLOR_CLEAR_VALUE:
-      case GL_BLEND_COLOR:
-        {
-            *type = GL_FLOAT;
-            *numParams = 4;
-        }
-        break;
-      case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
-        if (!supportsTextureFilterAnisotropy())
-        {
-            return false;
-        }
-        *type = GL_FLOAT;
-        *numParams = 1;
-        break;
-      default:
-        return false;
-    }
-
-    return true;
-}
-
-// Applies the render target surface, depth stencil surface, viewport rectangle and
-// scissor rectangle to the renderer
-bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
-{
-    Framebuffer *framebufferObject = getDrawFramebuffer();
-
-    if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
-    {
-        return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
-    }
-
-    mRenderer->applyRenderTarget(framebufferObject);
-
-    if (!mRenderer->setViewport(mState.viewport, mState.zNear, mState.zFar, drawMode, mState.rasterizer.frontFace,
-                                ignoreViewport))
-    {
-        return false;
-    }
-
-    mRenderer->setScissorRectangle(mState.scissor, mState.scissorTest);
-
-    return true;
-}
-
-// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
-void Context::applyState(GLenum drawMode)
-{
-    Framebuffer *framebufferObject = getDrawFramebuffer();
-    int samples = framebufferObject->getSamples();
-
-    mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS);
-    mState.rasterizer.multiSample = (samples != 0);
-    mRenderer->setRasterizerState(mState.rasterizer);
-
-    unsigned int mask = 0;
-    if (mState.sampleCoverage)
-    {
-        if (mState.sampleCoverageValue != 0)
-        {
-            
-            float threshold = 0.5f;
-
-            for (int i = 0; i < samples; ++i)
-            {
-                mask <<= 1;
-
-                if ((i + 1) * mState.sampleCoverageValue >= threshold)
-                {
-                    threshold += 1.0f;
-                    mask |= 1;
-                }
-            }
-        }
-
-        if (mState.sampleCoverageInvert)
-        {
-            mask = ~mask;
-        }
-    }
-    else
-    {
-        mask = 0xFFFFFFFF;
-    }
-    mRenderer->setBlendState(mState.blend, mState.blendColor, mask);
-
-    mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef,
-                                    mState.rasterizer.frontFace == GL_CCW);
-}
-
-// Applies the shaders and shader constants to the Direct3D 9 device
-void Context::applyShaders()
-{
-    ProgramBinary *programBinary = getCurrentProgramBinary();
-
-    mRenderer->applyShaders(programBinary);
-    
-    programBinary->applyUniforms();
-}
-
-// Applies the textures and sampler states to the Direct3D 9 device
-void Context::applyTextures()
-{
-    applyTextures(SAMPLER_PIXEL);
-
-    if (mSupportsVertexTexture)
-    {
-        applyTextures(SAMPLER_VERTEX);
-    }
-}
-
-// For each Direct3D 9 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 type)
-{
-    ProgramBinary *programBinary = getCurrentProgramBinary();
-
-    // Range of Direct3D samplers of given sampler type
-    int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits();
-    int samplerRange = programBinary->getUsedSamplerRange(type);
-
-    for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
-    {
-        int textureUnit = programBinary->getSamplerMapping(type, samplerIndex);   // OpenGL texture image unit index
-
-        if (textureUnit != -1)
-        {
-            TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex);
-            Texture *texture = getSamplerTexture(textureUnit, textureType);
-
-            if (texture->isSamplerComplete())
-            {
-                SamplerState samplerState;
-                texture->getSamplerState(&samplerState);
-                mRenderer->setSamplerState(type, samplerIndex, samplerState);
-
-                mRenderer->setTexture(type, samplerIndex, texture);
-
-                texture->resetDirty();
-            }
-            else
-            {
-                mRenderer->setTexture(type, samplerIndex, getIncompleteTexture(textureType));
-            }
-        }
-        else
-        {
-            mRenderer->setTexture(type, samplerIndex, NULL);
-        }
-    }
-
-    for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
-    {
-        mRenderer->setTexture(type, samplerIndex, NULL);
-    }
-}
-
-void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
-                         GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
-{
-    Framebuffer *framebuffer = getReadFramebuffer();
-
-    if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
-    {
-        return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
-    }
-
-    if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), getPackAlignment());
-    // sized query sanity check
-    if (bufSize)
-    {
-        int requiredSize = outputPitch * height;
-        if (requiredSize > *bufSize)
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
-    }
-
-    mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, getPackReverseRowOrder(), getPackAlignment(), pixels);
-}
-
-void Context::clear(GLbitfield mask)
-{
-    Framebuffer *framebufferObject = getDrawFramebuffer();
-
-    if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
-    {
-        return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
-    }
-
-    DWORD flags = 0;
-    GLbitfield finalMask = 0;
-
-    if (mask & GL_COLOR_BUFFER_BIT)
-    {
-        mask &= ~GL_COLOR_BUFFER_BIT;
-
-        if (framebufferObject->hasEnabledColorAttachment())
-        {
-            finalMask |= GL_COLOR_BUFFER_BIT;
-        }
-    }
-
-    if (mask & GL_DEPTH_BUFFER_BIT)
-    {
-        mask &= ~GL_DEPTH_BUFFER_BIT;
-        if (mState.depthStencil.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
-        {
-            finalMask |= GL_DEPTH_BUFFER_BIT;
-        }
-    }
-
-    if (mask & GL_STENCIL_BUFFER_BIT)
-    {
-        mask &= ~GL_STENCIL_BUFFER_BIT;
-        if (framebufferObject->getStencilbufferType() != GL_NONE)
-        {
-            rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
-            if (!depthStencil)
-            {
-                ERR("Depth stencil pointer unexpectedly null.");
-                return;
-            }
-
-            if (GetStencilSize(depthStencil->getActualFormat()) > 0)
-            {
-                finalMask |= GL_STENCIL_BUFFER_BIT;
-            }
-        }
-    }
-
-    if (mask != 0)
-    {
-        return gl::error(GL_INVALID_VALUE);
-    }
-
-    if (!applyRenderTarget(GL_TRIANGLES, true))   // Clips the clear to the scissor rectangle but not the viewport
-    {
-        return;
-    }
-
-    ClearParameters clearParams;
-    clearParams.mask = finalMask;
-    clearParams.colorClearValue = mState.colorClearValue;
-    clearParams.colorMaskRed = mState.blend.colorMaskRed;
-    clearParams.colorMaskGreen = mState.blend.colorMaskGreen;
-    clearParams.colorMaskBlue = mState.blend.colorMaskBlue;
-    clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha;
-    clearParams.depthClearValue = mState.depthClearValue;
-    clearParams.stencilClearValue = mState.stencilClearValue;
-    clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask;
-
-    mRenderer->clear(clearParams, framebufferObject);
-}
-
-void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
-{
-    if (!mState.currentProgram)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    if (!mRenderer->applyPrimitiveType(mode, count))
-    {
-        return;
-    }
-
-    if (!applyRenderTarget(mode, false))
-    {
-        return;
-    }
-
-    applyState(mode);
-
-    ProgramBinary *programBinary = getCurrentProgramBinary();
-
-    GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances);
-    if (err != GL_NO_ERROR)
-    {
-        return gl::error(err);
-    }
-
-    applyShaders();
-    applyTextures();
-
-    if (!programBinary->validateSamplers(NULL))
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    if (!skipDraw(mode))
-    {
-        mRenderer->drawArrays(mode, count, instances);
-    }
-}
-
-void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances)
-{
-    if (!mState.currentProgram)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    if (!indices && !mState.elementArrayBuffer)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-    
-    if (!mRenderer->applyPrimitiveType(mode, count))
-    {
-        return;
-    }
-
-    if (!applyRenderTarget(mode, false))
-    {
-        return;
-    }
-
-    applyState(mode);
-
-    rx::TranslatedIndexData indexInfo;
-    GLenum err = mRenderer->applyIndexBuffer(indices, mState.elementArrayBuffer.get(), count, mode, type, &indexInfo);
-    if (err != GL_NO_ERROR)
-    {
-        return gl::error(err);
-    }
-
-    ProgramBinary *programBinary = getCurrentProgramBinary();
-
-    GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
-    err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances);
-    if (err != GL_NO_ERROR)
-    {
-        return gl::error(err);
-    }
-
-    applyShaders();
-    applyTextures();
-
-    if (!programBinary->validateSamplers(NULL))
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    if (!skipDraw(mode))
-    {
-        mRenderer->drawElements(mode, count, type, indices, mState.elementArrayBuffer.get(), indexInfo, instances);
-    }
-}
-
-// Implements glFlush when block is false, glFinish when block is true
-void Context::sync(bool block)
-{
-    mRenderer->sync(block);
-}
-
-void Context::recordInvalidEnum()
-{
-    mInvalidEnum = true;
-}
-
-void Context::recordInvalidValue()
-{
-    mInvalidValue = true;
-}
-
-void Context::recordInvalidOperation()
-{
-    mInvalidOperation = true;
-}
-
-void Context::recordOutOfMemory()
-{
-    mOutOfMemory = true;
-}
-
-void Context::recordInvalidFramebufferOperation()
-{
-    mInvalidFramebufferOperation = true;
-}
-
-// Get one of the recorded errors and clear its flag, if any.
-// [OpenGL ES 2.0.24] section 2.5 page 13.
-GLenum Context::getError()
-{
-    if (mInvalidEnum)
-    {
-        mInvalidEnum = false;
-
-        return GL_INVALID_ENUM;
-    }
-
-    if (mInvalidValue)
-    {
-        mInvalidValue = false;
-
-        return GL_INVALID_VALUE;
-    }
-
-    if (mInvalidOperation)
-    {
-        mInvalidOperation = false;
-
-        return GL_INVALID_OPERATION;
-    }
-
-    if (mOutOfMemory)
-    {
-        mOutOfMemory = false;
-
-        return GL_OUT_OF_MEMORY;
-    }
-
-    if (mInvalidFramebufferOperation)
-    {
-        mInvalidFramebufferOperation = false;
-
-        return GL_INVALID_FRAMEBUFFER_OPERATION;
-    }
-
-    return GL_NO_ERROR;
-}
-
-GLenum Context::getResetStatus()
-{
-    if (mResetStatus == GL_NO_ERROR && !mContextLost)
-    {
-        // mResetStatus will be set by the markContextLost callback
-        // in the case a notification is sent
-        mRenderer->testDeviceLost(true);
-    }
-
-    GLenum status = mResetStatus;
-
-    if (mResetStatus != GL_NO_ERROR)
-    {
-        ASSERT(mContextLost);
-
-        if (mRenderer->testDeviceResettable())
-        {
-            mResetStatus = GL_NO_ERROR;
-        }
-    }
-    
-    return status;
-}
-
-bool Context::isResetNotificationEnabled()
-{
-    return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
-}
-
-int Context::getMajorShaderModel() const
-{
-    return mMajorShaderModel;
-}
-
-float Context::getMaximumPointSize() const
-{
-    return mMaximumPointSize;
-}
-
-unsigned int Context::getMaximumCombinedTextureImageUnits() const
-{
-    return mRenderer->getMaxCombinedTextureImageUnits();
-}
-
-int Context::getMaxSupportedSamples() const
-{
-    return mRenderer->getMaxSupportedSamples();
-}
-
-unsigned int Context::getMaximumRenderTargets() const
-{
-    return mRenderer->getMaxRenderTargets();
-}
-
-bool Context::supportsEventQueries() const
-{
-    return mSupportsEventQueries;
-}
-
-bool Context::supportsOcclusionQueries() const
-{
-    return mSupportsOcclusionQueries;
-}
-
-bool Context::supportsBGRATextures() const
-{
-    return mSupportsBGRATextures;
-}
-
-bool Context::supportsDXT1Textures() const
-{
-    return mSupportsDXT1Textures;
-}
-
-bool Context::supportsDXT3Textures() const
-{
-    return mSupportsDXT3Textures;
-}
-
-bool Context::supportsDXT5Textures() const
-{
-    return mSupportsDXT5Textures;
-}
-
-bool Context::supportsFloat32Textures() const
-{
-    return mSupportsFloat32Textures;
-}
-
-bool Context::supportsFloat32LinearFilter() const
-{
-    return mSupportsFloat32LinearFilter;
-}
-
-bool Context::supportsFloat32RenderableTextures() const
-{
-    return mSupportsFloat32RenderableTextures;
-}
-
-bool Context::supportsFloat16Textures() const
-{
-    return mSupportsFloat16Textures;
-}
-
-bool Context::supportsFloat16LinearFilter() const
-{
-    return mSupportsFloat16LinearFilter;
-}
-
-bool Context::supportsFloat16RenderableTextures() const
-{
-    return mSupportsFloat16RenderableTextures;
-}
-
-int Context::getMaximumRenderbufferDimension() const
-{
-    return mMaxRenderbufferDimension;
-}
-
-int Context::getMaximumTextureDimension() const
-{
-    return mMaxTextureDimension;
-}
-
-int Context::getMaximumCubeTextureDimension() const
-{
-    return mMaxCubeTextureDimension;
-}
-
-int Context::getMaximumTextureLevel() const
-{
-    return mMaxTextureLevel;
-}
-
-bool Context::supportsLuminanceTextures() const
-{
-    return mSupportsLuminanceTextures;
-}
-
-bool Context::supportsLuminanceAlphaTextures() const
-{
-    return mSupportsLuminanceAlphaTextures;
-}
-
-bool Context::supportsDepthTextures() const
-{
-    return mSupportsDepthTextures;
-}
-
-bool Context::supports32bitIndices() const
-{
-    return mSupports32bitIndices;
-}
-
-bool Context::supportsNonPower2Texture() const
-{
-    return mSupportsNonPower2Texture;
-}
-
-bool Context::supportsInstancing() const
-{
-    return mSupportsInstancing;
-}
-
-bool Context::supportsTextureFilterAnisotropy() const
-{
-    return mSupportsTextureFilterAnisotropy;
-}
-
-float Context::getTextureMaxAnisotropy() const
-{
-    return mMaxTextureAnisotropy;
-}
-
-bool Context::getCurrentReadFormatType(GLenum *format, GLenum *type)
-{
-    Framebuffer *framebuffer = getReadFramebuffer();
-    if (!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
-    {
-        return gl::error(GL_INVALID_OPERATION, false);
-    }
-
-    Renderbuffer *renderbuffer = framebuffer->getReadColorbuffer();
-    if (!renderbuffer)
-    {
-        return gl::error(GL_INVALID_OPERATION, false);
-    }
-
-    *format = gl::ExtractFormat(renderbuffer->getActualFormat()); 
-    *type = gl::ExtractType(renderbuffer->getActualFormat());
-
-    return true;
-}
-
-void Context::detachBuffer(GLuint buffer)
-{
-    // [OpenGL ES 2.0.24] section 2.9 page 22:
-    // If a buffer object is deleted while it is bound, all bindings to that object in the current context
-    // (i.e. in the thread that called Delete-Buffers) are reset to zero.
-
-    if (mState.arrayBuffer.id() == buffer)
-    {
-        mState.arrayBuffer.set(NULL);
-    }
-
-    if (mState.elementArrayBuffer.id() == buffer)
-    {
-        mState.elementArrayBuffer.set(NULL);
-    }
-
-    for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
-    {
-        if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
-        {
-            mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
-        }
-    }
-}
-
-void Context::detachTexture(GLuint texture)
-{
-    // [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 (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
-        {
-            if (mState.samplerTexture[type][sampler].id() == texture)
-            {
-                mState.samplerTexture[type][sampler].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 FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
-    // image was attached in the currently bound framebuffer.
-
-    Framebuffer *readFramebuffer = getReadFramebuffer();
-    Framebuffer *drawFramebuffer = getDrawFramebuffer();
-
-    if (readFramebuffer)
-    {
-        readFramebuffer->detachTexture(texture);
-    }
-
-    if (drawFramebuffer && drawFramebuffer != readFramebuffer)
-    {
-        drawFramebuffer->detachTexture(texture);
-    }
-}
-
-void Context::detachFramebuffer(GLuint framebuffer)
-{
-    // [OpenGL ES 2.0.24] section 4.4 page 107:
-    // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
-    // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
-
-    if (mState.readFramebuffer == framebuffer)
-    {
-        bindReadFramebuffer(0);
-    }
-
-    if (mState.drawFramebuffer == framebuffer)
-    {
-        bindDrawFramebuffer(0);
-    }
-}
-
-void Context::detachRenderbuffer(GLuint renderbuffer)
-{
-    // [OpenGL ES 2.0.24] section 4.4 page 109:
-    // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
-    // had been executed with the target RENDERBUFFER and name of zero.
-
-    if (mState.renderbuffer.id() == renderbuffer)
-    {
-        bindRenderbuffer(0);
-    }
-
-    // [OpenGL ES 2.0.24] section 4.4 page 111:
-    // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
-    // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
-    // point to which this image was attached in the currently bound framebuffer.
-
-    Framebuffer *readFramebuffer = getReadFramebuffer();
-    Framebuffer *drawFramebuffer = getDrawFramebuffer();
-
-    if (readFramebuffer)
-    {
-        readFramebuffer->detachRenderbuffer(renderbuffer);
-    }
-
-    if (drawFramebuffer && drawFramebuffer != readFramebuffer)
-    {
-        drawFramebuffer->detachRenderbuffer(renderbuffer);
-    }
-}
-
-Texture *Context::getIncompleteTexture(TextureType type)
-{
-    Texture *t = mIncompleteTextures[type].get();
-
-    if (t == NULL)
-    {
-        static const GLubyte color[] = { 0, 0, 0, 255 };
-
-        switch (type)
-        {
-          default:
-            UNREACHABLE();
-            // default falls through to TEXTURE_2D
-
-          case TEXTURE_2D:
-            {
-                Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID);
-                incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
-                t = incomplete2d;
-            }
-            break;
-
-          case TEXTURE_CUBE:
-            {
-              TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer, Texture::INCOMPLETE_TEXTURE_ID);
-
-              incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
-              incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
-              incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
-              incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
-              incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
-              incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
-
-              t = incompleteCube;
-            }
-            break;
-        }
-
-        mIncompleteTextures[type].set(t);
-    }
-
-    return t;
-}
-
-bool Context::skipDraw(GLenum drawMode)
-{
-    if (drawMode == GL_POINTS)
-    {
-        // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
-        // which affects varying interpolation. Since the value of gl_PointSize is
-        // undefined when not written, just skip drawing to avoid unexpected results.
-        if (!getCurrentProgramBinary()->usesPointSize())
-        {
-            // This is stictly speaking not an error, but developers should be 
-            // notified of risking undefined behavior.
-            ERR("Point rendering without writing to gl_PointSize.");
-
-            return true;
-        }
-    }
-    else if (IsTriangleMode(drawMode))
-    {
-        if (mState.rasterizer.cullFace && mState.rasterizer.cullMode == GL_FRONT_AND_BACK)
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-void Context::setVertexAttrib(GLuint index, const GLfloat *values)
-{
-    ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
-
-    mState.vertexAttribute[index].mCurrentValue[0] = values[0];
-    mState.vertexAttribute[index].mCurrentValue[1] = values[1];
-    mState.vertexAttribute[index].mCurrentValue[2] = values[2];
-    mState.vertexAttribute[index].mCurrentValue[3] = values[3];
-}
-
-void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
-{
-    ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
-
-    mState.vertexAttribute[index].mDivisor = divisor;
-}
-
-// keep list sorted in following order
-// OES extensions
-// EXT extensions
-// Vendor extensions
-void Context::initExtensionString()
-{
-    std::string extensionString = "";
-
-    // OES extensions
-    if (supports32bitIndices())
-    {
-        extensionString += "GL_OES_element_index_uint ";
-    }
-
-    extensionString += "GL_OES_packed_depth_stencil ";
-    extensionString += "GL_OES_get_program_binary ";
-    extensionString += "GL_OES_rgb8_rgba8 ";
-    if (mRenderer->getDerivativeInstructionSupport())
-    {
-        extensionString += "GL_OES_standard_derivatives ";
-    }
-
-    if (supportsFloat16Textures())
-    {
-        extensionString += "GL_OES_texture_half_float ";
-    }
-    if (supportsFloat16LinearFilter())
-    {
-        extensionString += "GL_OES_texture_half_float_linear ";
-    }
-    if (supportsFloat32Textures())
-    {
-        extensionString += "GL_OES_texture_float ";
-    }
-    if (supportsFloat32LinearFilter())
-    {
-        extensionString += "GL_OES_texture_float_linear ";
-    }
-
-    if (supportsNonPower2Texture())
-    {
-        extensionString += "GL_OES_texture_npot ";
-    }
-
-    // Multi-vendor (EXT) extensions
-    if (supportsOcclusionQueries())
-    {
-        extensionString += "GL_EXT_occlusion_query_boolean ";
-    }
-
-    extensionString += "GL_EXT_read_format_bgra ";
-    extensionString += "GL_EXT_robustness ";
-
-    if (supportsDXT1Textures())
-    {
-        extensionString += "GL_EXT_texture_compression_dxt1 ";
-    }
-
-    if (supportsTextureFilterAnisotropy())
-    {
-        extensionString += "GL_EXT_texture_filter_anisotropic ";
-    }
-
-    if (supportsBGRATextures())
-    {
-        extensionString += "GL_EXT_texture_format_BGRA8888 ";
-    }
-
-    if (mRenderer->getMaxRenderTargets() > 1)
-    {
-        extensionString += "GL_EXT_draw_buffers ";
-    }
-
-    extensionString += "GL_EXT_texture_storage ";
-    extensionString += "GL_EXT_frag_depth ";
-
-    // ANGLE-specific extensions
-    if (supportsDepthTextures())
-    {
-        extensionString += "GL_ANGLE_depth_texture ";
-    }
-
-    extensionString += "GL_ANGLE_framebuffer_blit ";
-    if (getMaxSupportedSamples() != 0)
-    {
-        extensionString += "GL_ANGLE_framebuffer_multisample ";
-    }
-
-    if (supportsInstancing())
-    {
-        extensionString += "GL_ANGLE_instanced_arrays ";
-    }
-
-    extensionString += "GL_ANGLE_pack_reverse_row_order ";
-
-    if (supportsDXT3Textures())
-    {
-        extensionString += "GL_ANGLE_texture_compression_dxt3 ";
-    }
-    if (supportsDXT5Textures())
-    {
-        extensionString += "GL_ANGLE_texture_compression_dxt5 ";
-    }
-
-    extensionString += "GL_ANGLE_texture_usage ";
-    extensionString += "GL_ANGLE_translated_shader_source ";
-
-    // Other vendor-specific extensions
-    if (supportsEventQueries())
-    {
-        extensionString += "GL_NV_fence ";
-    }
-
-    std::string::size_type end = extensionString.find_last_not_of(' ');
-    if (end != std::string::npos)
-    {
-        extensionString.resize(end+1);
-    }
-
-    mExtensionString = makeStaticString(extensionString);
-}
-
-const char *Context::getExtensionString() const
-{
-    return mExtensionString;
-}
-
-void Context::initRendererString()
-{
-    std::ostringstream rendererString;
-    rendererString << "ANGLE (";
-    rendererString << mRenderer->getRendererDescription();
-    rendererString << ")";
-
-    mRendererString = makeStaticString(rendererString.str());
-}
-
-const char *Context::getRendererString() const
-{
-    return mRendererString;
-}
-
-void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 
-                              GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                              GLbitfield mask)
-{
-    Framebuffer *readFramebuffer = getReadFramebuffer();
-    Framebuffer *drawFramebuffer = getDrawFramebuffer();
-
-    if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
-        !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
-    {
-        return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
-    }
-
-    if (drawFramebuffer->getSamples() != 0)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
-    Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
-
-    if (drawColorBuffer == NULL)
-    {
-        ERR("Draw buffers formats don't match, which is not supported in this implementation of BlitFramebufferANGLE");
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    int readBufferWidth = readColorBuffer->getWidth();
-    int readBufferHeight = readColorBuffer->getHeight();
-    int drawBufferWidth = drawColorBuffer->getWidth();
-    int drawBufferHeight = drawColorBuffer->getHeight();
-
-    Rectangle sourceRect;
-    Rectangle destRect;
-
-    if (srcX0 < srcX1)
-    {
-        sourceRect.x = srcX0;
-        destRect.x = dstX0;
-        sourceRect.width = srcX1 - srcX0;
-        destRect.width = dstX1 - dstX0;
-    }
-    else
-    {
-        sourceRect.x = srcX1;
-        destRect.x = dstX1;
-        sourceRect.width = srcX0 - srcX1;
-        destRect.width = dstX0 - dstX1;
-    }
-
-    if (srcY0 < srcY1)
-    {
-        sourceRect.height = srcY1 - srcY0;
-        destRect.height = dstY1 - dstY0;
-        sourceRect.y = srcY0;
-        destRect.y = dstY0;
-    }
-    else
-    {
-        sourceRect.height = srcY0 - srcY1;
-        destRect.height = dstY0 - srcY1;
-        sourceRect.y = srcY1;
-        destRect.y = dstY1;
-    }
-
-    Rectangle sourceScissoredRect = sourceRect;
-    Rectangle destScissoredRect = destRect;
-
-    if (mState.scissorTest)
-    {
-        // Only write to parts of the destination framebuffer which pass the scissor test.
-        if (destRect.x < mState.scissor.x)
-        {
-            int xDiff = mState.scissor.x - destRect.x;
-            destScissoredRect.x = mState.scissor.x;
-            destScissoredRect.width -= xDiff;
-            sourceScissoredRect.x += xDiff;
-            sourceScissoredRect.width -= xDiff;
-
-        }
-
-        if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width)
-        {
-            int xDiff = (destRect.x + destRect.width) - (mState.scissor.x + mState.scissor.width);
-            destScissoredRect.width -= xDiff;
-            sourceScissoredRect.width -= xDiff;
-        }
-
-        if (destRect.y < mState.scissor.y)
-        {
-            int yDiff = mState.scissor.y - destRect.y;
-            destScissoredRect.y = mState.scissor.y;
-            destScissoredRect.height -= yDiff;
-            sourceScissoredRect.y += yDiff;
-            sourceScissoredRect.height -= yDiff;
-        }
-
-        if (destRect.y + destRect.height > mState.scissor.y + mState.scissor.height)
-        {
-            int yDiff = (destRect.y + destRect.height) - (mState.scissor.y + mState.scissor.height);
-            destScissoredRect.height  -= yDiff;
-            sourceScissoredRect.height -= yDiff;
-        }
-    }
-
-    bool blitRenderTarget = false;
-    bool blitDepthStencil = false;
-
-    Rectangle sourceTrimmedRect = sourceScissoredRect;
-    Rectangle destTrimmedRect = destScissoredRect;
-
-    // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of 
-    // the actual draw and read surfaces.
-    if (sourceTrimmedRect.x < 0)
-    {
-        int xDiff = 0 - sourceTrimmedRect.x;
-        sourceTrimmedRect.x = 0;
-        sourceTrimmedRect.width -= xDiff;
-        destTrimmedRect.x += xDiff;
-        destTrimmedRect.width -= xDiff;
-    }
-
-    if (sourceTrimmedRect.x + sourceTrimmedRect.width > readBufferWidth)
-    {
-        int xDiff = (sourceTrimmedRect.x + sourceTrimmedRect.width) - readBufferWidth;
-        sourceTrimmedRect.width -= xDiff;
-        destTrimmedRect.width -= xDiff;
-    }
-
-    if (sourceTrimmedRect.y < 0)
-    {
-        int yDiff = 0 - sourceTrimmedRect.y;
-        sourceTrimmedRect.y = 0;
-        sourceTrimmedRect.height -= yDiff;
-        destTrimmedRect.y += yDiff;
-        destTrimmedRect.height -= yDiff;
-    }
-
-    if (sourceTrimmedRect.y + sourceTrimmedRect.height > readBufferHeight)
-    {
-        int yDiff = (sourceTrimmedRect.y + sourceTrimmedRect.height) - readBufferHeight;
-        sourceTrimmedRect.height -= yDiff;
-        destTrimmedRect.height -= yDiff;
-    }
-
-    if (destTrimmedRect.x < 0)
-    {
-        int xDiff = 0 - destTrimmedRect.x;
-        destTrimmedRect.x = 0;
-        destTrimmedRect.width -= xDiff;
-        sourceTrimmedRect.x += xDiff;
-        sourceTrimmedRect.width -= xDiff;
-    }
-
-    if (destTrimmedRect.x + destTrimmedRect.width > drawBufferWidth)
-    {
-        int xDiff = (destTrimmedRect.x + destTrimmedRect.width) - drawBufferWidth;
-        destTrimmedRect.width -= xDiff;
-        sourceTrimmedRect.width -= xDiff;
-    }
-
-    if (destTrimmedRect.y < 0)
-    {
-        int yDiff = 0 - destTrimmedRect.y;
-        destTrimmedRect.y = 0;
-        destTrimmedRect.height -= yDiff;
-        sourceTrimmedRect.y += yDiff;
-        sourceTrimmedRect.height -= yDiff;
-    }
-
-    if (destTrimmedRect.y + destTrimmedRect.height > drawBufferHeight)
-    {
-        int yDiff = (destTrimmedRect.y + destTrimmedRect.height) - drawBufferHeight;
-        destTrimmedRect.height -= yDiff;
-        sourceTrimmedRect.height -= yDiff;
-    }
-
-    bool partialBufferCopy = false;
-    if (sourceTrimmedRect.height < readBufferHeight ||
-        sourceTrimmedRect.width < readBufferWidth || 
-        destTrimmedRect.height < drawBufferHeight ||
-        destTrimmedRect.width < drawBufferWidth ||
-        sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0 || sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0)
-    {
-        partialBufferCopy = true;
-    }
-
-    if (mask & GL_COLOR_BUFFER_BIT)
-    {
-        const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
-        const bool validReadType = (readColorbufferType == GL_TEXTURE_2D) || (readColorbufferType == GL_RENDERBUFFER);
-        bool validDrawType = true;
-        bool validDrawFormat = true;
-
-        for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-        {
-            if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
-            {
-                if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
-                    drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
-                {
-                    validDrawType = false;
-                }
-
-                if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
-                {
-                    validDrawFormat = false;
-                }
-            }
-        }
-
-        if (!validReadType || !validDrawType || !validDrawFormat)
-        {
-            ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
-            return gl::error(GL_INVALID_OPERATION);
-        }
-        
-        if (partialBufferCopy && readFramebuffer->getSamples() != 0)
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
-
-        blitRenderTarget = true;
-
-    }
-
-    if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
-    {
-        Renderbuffer *readDSBuffer = NULL;
-        Renderbuffer *drawDSBuffer = NULL;
-
-        // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
-        // both a depth and stencil buffer, it will be the same buffer.
-
-        if (mask & GL_DEPTH_BUFFER_BIT)
-        {
-            if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
-            {
-                if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
-                    readFramebuffer->getDepthbuffer()->getActualFormat() != drawFramebuffer->getDepthbuffer()->getActualFormat())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                blitDepthStencil = true;
-                readDSBuffer = readFramebuffer->getDepthbuffer();
-                drawDSBuffer = drawFramebuffer->getDepthbuffer();
-            }
-        }
-
-        if (mask & GL_STENCIL_BUFFER_BIT)
-        {
-            if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
-            {
-                if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
-                    readFramebuffer->getStencilbuffer()->getActualFormat() != drawFramebuffer->getStencilbuffer()->getActualFormat())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                blitDepthStencil = true;
-                readDSBuffer = readFramebuffer->getStencilbuffer();
-                drawDSBuffer = drawFramebuffer->getStencilbuffer();
-            }
-        }
-
-        if (partialBufferCopy)
-        {
-            ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
-            return gl::error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted
-        }
-
-        if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) || 
-            (readDSBuffer && readDSBuffer->getSamples() != 0))
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
-    }
-
-    if (blitRenderTarget || blitDepthStencil)
-    {
-        mRenderer->blitRect(readFramebuffer, sourceTrimmedRect, drawFramebuffer, destTrimmedRect, blitRenderTarget, blitDepthStencil);
-    }
-}
-
-}
-
-extern "C"
-{
-gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
-{
-    return new gl::Context(shareContext, renderer, notifyResets, robustAccess);
-}
-
-void glDestroyContext(gl::Context *context)
-{
-    delete context;
-
-    if (context == gl::getContext())
-    {
-        gl::makeCurrent(NULL, NULL, NULL);
-    }
-}
-
-void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
-{
-    gl::makeCurrent(context, display, surface);
-}
-
-gl::Context *glGetCurrentContext()
-{
-    return gl::getContext();
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/Context.h b/src/third_party/angle/src/libGLESv2/Context.h
deleted file mode 100644
index 1cb32e8..0000000
--- a/src/third_party/angle/src/libGLESv2/Context.h
+++ /dev/null
@@ -1,515 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Context.h: Defines the gl::Context class, managing all GL state and performing
-// rendering operations. It is the GLES2 specific implementation of EGLContext.
-
-#ifndef LIBGLESV2_CONTEXT_H_
-#define LIBGLESV2_CONTEXT_H_
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#define EGLAPI
-#include <EGL/egl.h>
-
-#include <string>
-#include <map>
-#ifdef _MSC_VER
-#include <hash_map>
-#else
-#include <unordered_map>
-#endif
-
-#include "common/angleutils.h"
-#include "common/RefCountObject.h"
-#include "libGLESv2/HandleAllocator.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/Constants.h"
-
-namespace rx
-{
-class Renderer;
-}
-
-namespace egl
-{
-class Display;
-class Surface;
-}
-
-namespace gl
-{
-class Shader;
-class Program;
-class ProgramBinary;
-class Texture;
-class Texture2D;
-class TextureCubeMap;
-class Framebuffer;
-class Renderbuffer;
-class RenderbufferStorage;
-class Colorbuffer;
-class Depthbuffer;
-class Stencilbuffer;
-class DepthStencilbuffer;
-class Fence;
-class Query;
-class ResourceManager;
-class Buffer;
-
-enum QueryType
-{
-    QUERY_ANY_SAMPLES_PASSED,
-    QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE,
-
-    QUERY_TYPE_COUNT
-};
-
-// Helper structure describing a single vertex attribute
-class VertexAttribute
-{
-  public:
-    VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0)
-    {
-        mCurrentValue[0] = 0.0f;
-        mCurrentValue[1] = 0.0f;
-        mCurrentValue[2] = 0.0f;
-        mCurrentValue[3] = 1.0f;
-    }
-
-    int typeSize() const
-    {
-        switch (mType)
-        {
-          case GL_BYTE:           return mSize * sizeof(GLbyte);
-          case GL_UNSIGNED_BYTE:  return mSize * sizeof(GLubyte);
-          case GL_SHORT:          return mSize * sizeof(GLshort);
-          case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort);
-          case GL_FIXED:          return mSize * sizeof(GLfixed);
-          case GL_FLOAT:          return mSize * sizeof(GLfloat);
-          default: UNREACHABLE(); return mSize * sizeof(GLfloat);
-        }
-    }
-
-    GLsizei stride() const
-    {
-        return mStride ? mStride : typeSize();
-    }
-
-    // From glVertexAttribPointer
-    GLenum mType;
-    GLint mSize;
-    bool mNormalized;
-    GLsizei mStride;   // 0 means natural stride
-
-    union
-    {
-        const void *mPointer;
-        intptr_t mOffset;
-    };
-
-    BindingPointer<Buffer> mBoundBuffer;   // Captured when glVertexAttribPointer is called.
-
-    bool mArrayEnabled;   // From glEnable/DisableVertexAttribArray
-    float mCurrentValue[4];   // From glVertexAttrib
-    unsigned int mDivisor;
-};
-
-// Helper structure to store all raw state
-struct State
-{
-    Color colorClearValue;
-    GLclampf depthClearValue;
-    int stencilClearValue;
-
-    RasterizerState rasterizer;
-    bool scissorTest;
-    Rectangle scissor;
-
-    BlendState blend;
-    Color blendColor;
-    bool sampleCoverage;
-    GLclampf sampleCoverageValue;
-    bool sampleCoverageInvert;
-
-    DepthStencilState depthStencil;
-    GLint stencilRef;
-    GLint stencilBackRef;
-
-    GLfloat lineWidth;
-
-    GLenum generateMipmapHint;
-    GLenum fragmentShaderDerivativeHint;
-
-    Rectangle viewport;
-    float zNear;
-    float zFar;
-
-    unsigned int activeSampler;   // Active texture unit selector - GL_TEXTURE0
-    BindingPointer<Buffer> arrayBuffer;
-    BindingPointer<Buffer> elementArrayBuffer;
-    GLuint readFramebuffer;
-    GLuint drawFramebuffer;
-    BindingPointer<Renderbuffer> renderbuffer;
-    GLuint currentProgram;
-
-    VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];
-    BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
-    BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];
-
-    GLint unpackAlignment;
-    GLint packAlignment;
-    bool packReverseRowOrder;
-};
-
-class Context
-{
-  public:
-    Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
-
-    ~Context();
-
-    void makeCurrent(egl::Surface *surface);
-
-    virtual void markContextLost();
-    bool isContextLost();
-
-    // State manipulation
-    void setClearColor(float red, float green, float blue, float alpha);
-
-    void setClearDepth(float depth);
-
-    void setClearStencil(int stencil);
-
-    void setCullFace(bool enabled);
-    bool isCullFaceEnabled() const;
-
-    void setCullMode(GLenum mode);
-
-    void setFrontFace(GLenum front);
-
-    void setDepthTest(bool enabled);
-    bool isDepthTestEnabled() const;
-
-    void setDepthFunc(GLenum depthFunc);
-
-    void setDepthRange(float zNear, float zFar);
-    
-    void setBlend(bool enabled);
-    bool isBlendEnabled() const;
-
-    void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
-    void setBlendColor(float red, float green, float blue, float alpha);
-    void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);
-
-    void setStencilTest(bool enabled);
-    bool isStencilTestEnabled() const;
-
-    void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);
-    void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask);
-    void setStencilWritemask(GLuint stencilWritemask);
-    void setStencilBackWritemask(GLuint stencilBackWritemask);
-    void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);
-    void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass);
-
-    void setPolygonOffsetFill(bool enabled);
-    bool isPolygonOffsetFillEnabled() const;
-
-    void setPolygonOffsetParams(GLfloat factor, GLfloat units);
-
-    void setSampleAlphaToCoverage(bool enabled);
-    bool isSampleAlphaToCoverageEnabled() const;
-
-    void setSampleCoverage(bool enabled);
-    bool isSampleCoverageEnabled() const;
-
-    void setSampleCoverageParams(GLclampf value, bool invert);
-
-    void setScissorTest(bool enabled);
-    bool isScissorTestEnabled() const;
-
-    void setDither(bool enabled);
-    bool isDitherEnabled() const;
-
-    void setLineWidth(GLfloat width);
-
-    void setGenerateMipmapHint(GLenum hint);
-    void setFragmentShaderDerivativeHint(GLenum hint);
-
-    void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
-
-    void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
-
-    void setColorMask(bool red, bool green, bool blue, bool alpha);
-    void setDepthMask(bool mask);
-
-    void setActiveSampler(unsigned int active);
-
-    GLuint getReadFramebufferHandle() const;
-    GLuint getDrawFramebufferHandle() const;
-    GLuint getRenderbufferHandle() const;
-
-    GLuint getArrayBufferHandle() const;
-
-    GLuint getActiveQuery(GLenum target) const;
-
-    void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
-    const VertexAttribute &getVertexAttribState(unsigned int attribNum);
-    void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
-                              bool normalized, GLsizei stride, const void *pointer);
-    const void *getVertexAttribPointer(unsigned int attribNum) const;
-
-    void setUnpackAlignment(GLint alignment);
-    GLint getUnpackAlignment() const;
-
-    void setPackAlignment(GLint alignment);
-    GLint getPackAlignment() const;
-
-    void setPackReverseRowOrder(bool reverseRowOrder);
-    bool getPackReverseRowOrder() const;
-
-    // These create  and destroy methods are merely pass-throughs to 
-    // ResourceManager, which owns these object types
-    GLuint createBuffer();
-    GLuint createShader(GLenum type);
-    GLuint createProgram();
-    GLuint createTexture();
-    GLuint createRenderbuffer();
-
-#if defined(__LB_XB360__)
-    // Binds a texture name to a special video texture that does not have to be
-    // uploaded by the application, but will update itself to be the current
-    // video frame right after the buffers are swapped. Set to 0 to disable.
-    void setVideoTexture(GLuint texture);
-
-    // Returns the set video texture name, returning 0 if not set.
-    GLuint getVideoTexture();
-#endif
-
-    void deleteBuffer(GLuint buffer);
-    void deleteShader(GLuint shader);
-    void deleteProgram(GLuint program);
-    void deleteTexture(GLuint texture);
-    void deleteRenderbuffer(GLuint renderbuffer);
-
-    // Framebuffers are owned by the Context, so these methods do not pass through
-    GLuint createFramebuffer();
-    void deleteFramebuffer(GLuint framebuffer);
-
-    // Fences are owned by the Context.
-    GLuint createFence();
-    void deleteFence(GLuint fence);
-    
-    // Queries are owned by the Context;
-    GLuint createQuery();
-    void deleteQuery(GLuint query);
-
-    void bindArrayBuffer(GLuint buffer);
-    void bindElementArrayBuffer(GLuint buffer);
-    void bindTexture2D(GLuint texture);
-    void bindTextureCubeMap(GLuint texture);
-    void bindReadFramebuffer(GLuint framebuffer);
-    void bindDrawFramebuffer(GLuint framebuffer);
-    void bindRenderbuffer(GLuint renderbuffer);
-    void useProgram(GLuint program);
-    void linkProgram(GLuint program);
-    void setProgramBinary(GLuint program, const void *binary, GLint length);
-
-    void beginQuery(GLenum target, GLuint query);
-    void endQuery(GLenum target);
-
-    void setFramebufferZero(Framebuffer *framebuffer);
-
-    void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
-
-    void setVertexAttrib(GLuint index, const GLfloat *values);
-    void setVertexAttribDivisor(GLuint index, GLuint divisor);
-
-    Buffer *getBuffer(GLuint handle);
-    Fence *getFence(GLuint handle);
-    Shader *getShader(GLuint handle);
-    Program *getProgram(GLuint handle);
-    Texture *getTexture(GLuint handle);
-    Framebuffer *getFramebuffer(GLuint handle);
-    Renderbuffer *getRenderbuffer(GLuint handle);
-    Query *getQuery(GLuint handle, bool create, GLenum type);
-
-    Buffer *getArrayBuffer();
-    Buffer *getElementArrayBuffer();
-    ProgramBinary *getCurrentProgramBinary();
-    Texture2D *getTexture2D();
-    TextureCubeMap *getTextureCubeMap();
-    Texture *getSamplerTexture(unsigned int sampler, TextureType type);
-    Framebuffer *getReadFramebuffer();
-    Framebuffer *getDrawFramebuffer();
-
-    bool getFloatv(GLenum pname, GLfloat *params);
-    bool getIntegerv(GLenum pname, GLint *params);
-    bool getBooleanv(GLenum pname, GLboolean *params);
-
-    bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
-
-    void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
-    void clear(GLbitfield mask);
-    void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
-    void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances);
-    void sync(bool block);   // flush/finish
-
-    void recordInvalidEnum();
-    void recordInvalidValue();
-    void recordInvalidOperation();
-    void recordOutOfMemory();
-    void recordInvalidFramebufferOperation();
-
-    GLenum getError();
-    GLenum getResetStatus();
-    virtual bool isResetNotificationEnabled();
-
-    int getMajorShaderModel() const;
-    float getMaximumPointSize() const;
-    unsigned int getMaximumCombinedTextureImageUnits() const;
-    int getMaximumRenderbufferDimension() const;
-    int getMaximumTextureDimension() const;
-    int getMaximumCubeTextureDimension() const;
-    int getMaximumTextureLevel() const;
-    unsigned int getMaximumRenderTargets() const;
-    GLsizei getMaxSupportedSamples() const;
-    const char *getExtensionString() const;
-    const char *getRendererString() const;
-    bool supportsEventQueries() const;
-    bool supportsOcclusionQueries() const;
-    bool supportsBGRATextures() const;
-    bool supportsDXT1Textures() const;
-    bool supportsDXT3Textures() const;
-    bool supportsDXT5Textures() const;
-    bool supportsFloat32Textures() const;
-    bool supportsFloat32LinearFilter() const;
-    bool supportsFloat32RenderableTextures() const;
-    bool supportsFloat16Textures() const;
-    bool supportsFloat16LinearFilter() const;
-    bool supportsFloat16RenderableTextures() const;
-    bool supportsLuminanceTextures() const;
-    bool supportsLuminanceAlphaTextures() const;
-    bool supportsDepthTextures() const;
-    bool supports32bitIndices() const;
-    bool supportsNonPower2Texture() const;
-    bool supportsInstancing() const;
-    bool supportsTextureFilterAnisotropy() const;
-
-    bool getCurrentReadFormatType(GLenum *format, GLenum *type);
-
-    float getTextureMaxAnisotropy() const;
-
-    void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 
-                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                         GLbitfield mask);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Context);
-
-    bool applyRenderTarget(GLenum drawMode, bool ignoreViewport);
-    void applyState(GLenum drawMode);
-    void applyShaders();
-    void applyTextures();
-    void applyTextures(SamplerType type);
-
-    void detachBuffer(GLuint buffer);
-    void detachTexture(GLuint texture);
-    void detachFramebuffer(GLuint framebuffer);
-    void detachRenderbuffer(GLuint renderbuffer);
-
-    Texture *getIncompleteTexture(TextureType type);
-
-    bool skipDraw(GLenum drawMode);
-
-    void initExtensionString();
-    void initRendererString();
-
-    rx::Renderer *const mRenderer;
-
-    State mState;
-
-    BindingPointer<Texture2D> mTexture2DZero;
-    BindingPointer<TextureCubeMap> mTextureCubeMapZero;
-
-#ifndef HASH_MAP
-# ifdef _MSC_VER
-#  define HASH_MAP stdext::hash_map
-# else
-#  define HASH_MAP std::unordered_map
-# endif
-#endif
-
-    typedef HASH_MAP<GLuint, Framebuffer*> FramebufferMap;
-    FramebufferMap mFramebufferMap;
-    HandleAllocator mFramebufferHandleAllocator;
-
-    typedef HASH_MAP<GLuint, Fence*> FenceMap;
-    FenceMap mFenceMap;
-    HandleAllocator mFenceHandleAllocator;
-
-    typedef HASH_MAP<GLuint, Query*> QueryMap;
-    QueryMap mQueryMap;
-    HandleAllocator mQueryHandleAllocator;
-
-    const char *mExtensionString;
-    const char *mRendererString;
-    
-    BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
-
-    // Recorded errors
-    bool mInvalidEnum;
-    bool mInvalidValue;
-    bool mInvalidOperation;
-    bool mOutOfMemory;
-    bool mInvalidFramebufferOperation;
-
-    // Current/lost context flags
-    bool mHasBeenCurrent;
-    bool mContextLost;
-    GLenum mResetStatus;
-    GLenum mResetStrategy;
-    bool mRobustAccess;
-
-    BindingPointer<ProgramBinary> mCurrentProgramBinary;
-    Framebuffer *mBoundDrawFramebuffer;
-
-    int mMajorShaderModel;
-    float mMaximumPointSize;
-    bool mSupportsVertexTexture;
-    bool mSupportsNonPower2Texture;
-    bool mSupportsInstancing;
-    int  mMaxViewportDimension;
-    int  mMaxRenderbufferDimension;
-    int  mMaxTextureDimension;
-    int  mMaxCubeTextureDimension;
-    int  mMaxTextureLevel;
-    float mMaxTextureAnisotropy;
-    bool mSupportsEventQueries;
-    bool mSupportsOcclusionQueries;
-    bool mSupportsBGRATextures;
-    bool mSupportsDXT1Textures;
-    bool mSupportsDXT3Textures;
-    bool mSupportsDXT5Textures;
-    bool mSupportsFloat32Textures;
-    bool mSupportsFloat32LinearFilter;
-    bool mSupportsFloat32RenderableTextures;
-    bool mSupportsFloat16Textures;
-    bool mSupportsFloat16LinearFilter;
-    bool mSupportsFloat16RenderableTextures;
-    bool mSupportsLuminanceTextures;
-    bool mSupportsLuminanceAlphaTextures;
-    bool mSupportsDepthTextures;
-    bool mSupports32bitIndices;
-    bool mSupportsTextureFilterAnisotropy;
-    int mNumCompressedTextureFormats;
-
-    ResourceManager *mResourceManager;
-};
-}
-
-#endif   // INCLUDE_CONTEXT_H_
diff --git a/src/third_party/angle/src/libGLESv2/Fence.cpp b/src/third_party/angle/src/libGLESv2/Fence.cpp
deleted file mode 100644
index e4218bb..0000000
--- a/src/third_party/angle/src/libGLESv2/Fence.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension.
-
-#include "libGLESv2/Fence.h"
-#include "libGLESv2/renderer/FenceImpl.h"
-#include "libGLESv2/renderer/Renderer.h"
-
-namespace gl
-{
-
-Fence::Fence(rx::Renderer *renderer)
-{
-    mFence = renderer->createFence();
-}
-
-Fence::~Fence()
-{
-    delete mFence;
-}
-
-GLboolean Fence::isFence()
-{
-    return mFence->isFence();
-}
-
-void Fence::setFence(GLenum condition)
-{
-    mFence->setFence(condition);
-}
-
-GLboolean Fence::testFence()
-{
-    return mFence->testFence();
-}
-
-void Fence::finishFence()
-{
-    mFence->finishFence();
-}
-
-void Fence::getFenceiv(GLenum pname, GLint *params)
-{
-    mFence->getFenceiv(pname, params);
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/Fence.h b/src/third_party/angle/src/libGLESv2/Fence.h
deleted file mode 100644
index 1cedebb..0000000
--- a/src/third_party/angle/src/libGLESv2/Fence.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Fence.h: Defines the gl::Fence class, which supports the GL_NV_fence extension.
-
-#ifndef LIBGLESV2_FENCE_H_
-#define LIBGLESV2_FENCE_H_
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-class Renderer;
-class FenceImpl;
-}
-
-namespace gl
-{
-
-class Fence
-{
-  public:
-    explicit Fence(rx::Renderer *renderer);
-    virtual ~Fence();
-
-    GLboolean isFence();
-    void setFence(GLenum condition);
-    GLboolean testFence();
-    void finishFence();
-    void getFenceiv(GLenum pname, GLint *params);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Fence);
-
-    rx::FenceImpl *mFence;
-};
-
-}
-
-#endif   // LIBGLESV2_FENCE_H_
diff --git a/src/third_party/angle/src/libGLESv2/Float16ToFloat32.cpp b/src/third_party/angle/src/libGLESv2/Float16ToFloat32.cpp
deleted file mode 100644
index b90d2f6..0000000
--- a/src/third_party/angle/src/libGLESv2/Float16ToFloat32.cpp
+++ /dev/null
@@ -1,2204 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// This file is automatically generated.
-
-namespace gl
-{
-
-const static unsigned g_mantissa[2048] = {
-    0x00000000,
-    0x33800000,
-    0x34000000,
-    0x34400000,
-    0x34800000,
-    0x34a00000,
-    0x34c00000,
-    0x34e00000,
-    0x35000000,
-    0x35100000,
-    0x35200000,
-    0x35300000,
-    0x35400000,
-    0x35500000,
-    0x35600000,
-    0x35700000,
-    0x35800000,
-    0x35880000,
-    0x35900000,
-    0x35980000,
-    0x35a00000,
-    0x35a80000,
-    0x35b00000,
-    0x35b80000,
-    0x35c00000,
-    0x35c80000,
-    0x35d00000,
-    0x35d80000,
-    0x35e00000,
-    0x35e80000,
-    0x35f00000,
-    0x35f80000,
-    0x36000000,
-    0x36040000,
-    0x36080000,
-    0x360c0000,
-    0x36100000,
-    0x36140000,
-    0x36180000,
-    0x361c0000,
-    0x36200000,
-    0x36240000,
-    0x36280000,
-    0x362c0000,
-    0x36300000,
-    0x36340000,
-    0x36380000,
-    0x363c0000,
-    0x36400000,
-    0x36440000,
-    0x36480000,
-    0x364c0000,
-    0x36500000,
-    0x36540000,
-    0x36580000,
-    0x365c0000,
-    0x36600000,
-    0x36640000,
-    0x36680000,
-    0x366c0000,
-    0x36700000,
-    0x36740000,
-    0x36780000,
-    0x367c0000,
-    0x36800000,
-    0x36820000,
-    0x36840000,
-    0x36860000,
-    0x36880000,
-    0x368a0000,
-    0x368c0000,
-    0x368e0000,
-    0x36900000,
-    0x36920000,
-    0x36940000,
-    0x36960000,
-    0x36980000,
-    0x369a0000,
-    0x369c0000,
-    0x369e0000,
-    0x36a00000,
-    0x36a20000,
-    0x36a40000,
-    0x36a60000,
-    0x36a80000,
-    0x36aa0000,
-    0x36ac0000,
-    0x36ae0000,
-    0x36b00000,
-    0x36b20000,
-    0x36b40000,
-    0x36b60000,
-    0x36b80000,
-    0x36ba0000,
-    0x36bc0000,
-    0x36be0000,
-    0x36c00000,
-    0x36c20000,
-    0x36c40000,
-    0x36c60000,
-    0x36c80000,
-    0x36ca0000,
-    0x36cc0000,
-    0x36ce0000,
-    0x36d00000,
-    0x36d20000,
-    0x36d40000,
-    0x36d60000,
-    0x36d80000,
-    0x36da0000,
-    0x36dc0000,
-    0x36de0000,
-    0x36e00000,
-    0x36e20000,
-    0x36e40000,
-    0x36e60000,
-    0x36e80000,
-    0x36ea0000,
-    0x36ec0000,
-    0x36ee0000,
-    0x36f00000,
-    0x36f20000,
-    0x36f40000,
-    0x36f60000,
-    0x36f80000,
-    0x36fa0000,
-    0x36fc0000,
-    0x36fe0000,
-    0x37000000,
-    0x37010000,
-    0x37020000,
-    0x37030000,
-    0x37040000,
-    0x37050000,
-    0x37060000,
-    0x37070000,
-    0x37080000,
-    0x37090000,
-    0x370a0000,
-    0x370b0000,
-    0x370c0000,
-    0x370d0000,
-    0x370e0000,
-    0x370f0000,
-    0x37100000,
-    0x37110000,
-    0x37120000,
-    0x37130000,
-    0x37140000,
-    0x37150000,
-    0x37160000,
-    0x37170000,
-    0x37180000,
-    0x37190000,
-    0x371a0000,
-    0x371b0000,
-    0x371c0000,
-    0x371d0000,
-    0x371e0000,
-    0x371f0000,
-    0x37200000,
-    0x37210000,
-    0x37220000,
-    0x37230000,
-    0x37240000,
-    0x37250000,
-    0x37260000,
-    0x37270000,
-    0x37280000,
-    0x37290000,
-    0x372a0000,
-    0x372b0000,
-    0x372c0000,
-    0x372d0000,
-    0x372e0000,
-    0x372f0000,
-    0x37300000,
-    0x37310000,
-    0x37320000,
-    0x37330000,
-    0x37340000,
-    0x37350000,
-    0x37360000,
-    0x37370000,
-    0x37380000,
-    0x37390000,
-    0x373a0000,
-    0x373b0000,
-    0x373c0000,
-    0x373d0000,
-    0x373e0000,
-    0x373f0000,
-    0x37400000,
-    0x37410000,
-    0x37420000,
-    0x37430000,
-    0x37440000,
-    0x37450000,
-    0x37460000,
-    0x37470000,
-    0x37480000,
-    0x37490000,
-    0x374a0000,
-    0x374b0000,
-    0x374c0000,
-    0x374d0000,
-    0x374e0000,
-    0x374f0000,
-    0x37500000,
-    0x37510000,
-    0x37520000,
-    0x37530000,
-    0x37540000,
-    0x37550000,
-    0x37560000,
-    0x37570000,
-    0x37580000,
-    0x37590000,
-    0x375a0000,
-    0x375b0000,
-    0x375c0000,
-    0x375d0000,
-    0x375e0000,
-    0x375f0000,
-    0x37600000,
-    0x37610000,
-    0x37620000,
-    0x37630000,
-    0x37640000,
-    0x37650000,
-    0x37660000,
-    0x37670000,
-    0x37680000,
-    0x37690000,
-    0x376a0000,
-    0x376b0000,
-    0x376c0000,
-    0x376d0000,
-    0x376e0000,
-    0x376f0000,
-    0x37700000,
-    0x37710000,
-    0x37720000,
-    0x37730000,
-    0x37740000,
-    0x37750000,
-    0x37760000,
-    0x37770000,
-    0x37780000,
-    0x37790000,
-    0x377a0000,
-    0x377b0000,
-    0x377c0000,
-    0x377d0000,
-    0x377e0000,
-    0x377f0000,
-    0x37800000,
-    0x37808000,
-    0x37810000,
-    0x37818000,
-    0x37820000,
-    0x37828000,
-    0x37830000,
-    0x37838000,
-    0x37840000,
-    0x37848000,
-    0x37850000,
-    0x37858000,
-    0x37860000,
-    0x37868000,
-    0x37870000,
-    0x37878000,
-    0x37880000,
-    0x37888000,
-    0x37890000,
-    0x37898000,
-    0x378a0000,
-    0x378a8000,
-    0x378b0000,
-    0x378b8000,
-    0x378c0000,
-    0x378c8000,
-    0x378d0000,
-    0x378d8000,
-    0x378e0000,
-    0x378e8000,
-    0x378f0000,
-    0x378f8000,
-    0x37900000,
-    0x37908000,
-    0x37910000,
-    0x37918000,
-    0x37920000,
-    0x37928000,
-    0x37930000,
-    0x37938000,
-    0x37940000,
-    0x37948000,
-    0x37950000,
-    0x37958000,
-    0x37960000,
-    0x37968000,
-    0x37970000,
-    0x37978000,
-    0x37980000,
-    0x37988000,
-    0x37990000,
-    0x37998000,
-    0x379a0000,
-    0x379a8000,
-    0x379b0000,
-    0x379b8000,
-    0x379c0000,
-    0x379c8000,
-    0x379d0000,
-    0x379d8000,
-    0x379e0000,
-    0x379e8000,
-    0x379f0000,
-    0x379f8000,
-    0x37a00000,
-    0x37a08000,
-    0x37a10000,
-    0x37a18000,
-    0x37a20000,
-    0x37a28000,
-    0x37a30000,
-    0x37a38000,
-    0x37a40000,
-    0x37a48000,
-    0x37a50000,
-    0x37a58000,
-    0x37a60000,
-    0x37a68000,
-    0x37a70000,
-    0x37a78000,
-    0x37a80000,
-    0x37a88000,
-    0x37a90000,
-    0x37a98000,
-    0x37aa0000,
-    0x37aa8000,
-    0x37ab0000,
-    0x37ab8000,
-    0x37ac0000,
-    0x37ac8000,
-    0x37ad0000,
-    0x37ad8000,
-    0x37ae0000,
-    0x37ae8000,
-    0x37af0000,
-    0x37af8000,
-    0x37b00000,
-    0x37b08000,
-    0x37b10000,
-    0x37b18000,
-    0x37b20000,
-    0x37b28000,
-    0x37b30000,
-    0x37b38000,
-    0x37b40000,
-    0x37b48000,
-    0x37b50000,
-    0x37b58000,
-    0x37b60000,
-    0x37b68000,
-    0x37b70000,
-    0x37b78000,
-    0x37b80000,
-    0x37b88000,
-    0x37b90000,
-    0x37b98000,
-    0x37ba0000,
-    0x37ba8000,
-    0x37bb0000,
-    0x37bb8000,
-    0x37bc0000,
-    0x37bc8000,
-    0x37bd0000,
-    0x37bd8000,
-    0x37be0000,
-    0x37be8000,
-    0x37bf0000,
-    0x37bf8000,
-    0x37c00000,
-    0x37c08000,
-    0x37c10000,
-    0x37c18000,
-    0x37c20000,
-    0x37c28000,
-    0x37c30000,
-    0x37c38000,
-    0x37c40000,
-    0x37c48000,
-    0x37c50000,
-    0x37c58000,
-    0x37c60000,
-    0x37c68000,
-    0x37c70000,
-    0x37c78000,
-    0x37c80000,
-    0x37c88000,
-    0x37c90000,
-    0x37c98000,
-    0x37ca0000,
-    0x37ca8000,
-    0x37cb0000,
-    0x37cb8000,
-    0x37cc0000,
-    0x37cc8000,
-    0x37cd0000,
-    0x37cd8000,
-    0x37ce0000,
-    0x37ce8000,
-    0x37cf0000,
-    0x37cf8000,
-    0x37d00000,
-    0x37d08000,
-    0x37d10000,
-    0x37d18000,
-    0x37d20000,
-    0x37d28000,
-    0x37d30000,
-    0x37d38000,
-    0x37d40000,
-    0x37d48000,
-    0x37d50000,
-    0x37d58000,
-    0x37d60000,
-    0x37d68000,
-    0x37d70000,
-    0x37d78000,
-    0x37d80000,
-    0x37d88000,
-    0x37d90000,
-    0x37d98000,
-    0x37da0000,
-    0x37da8000,
-    0x37db0000,
-    0x37db8000,
-    0x37dc0000,
-    0x37dc8000,
-    0x37dd0000,
-    0x37dd8000,
-    0x37de0000,
-    0x37de8000,
-    0x37df0000,
-    0x37df8000,
-    0x37e00000,
-    0x37e08000,
-    0x37e10000,
-    0x37e18000,
-    0x37e20000,
-    0x37e28000,
-    0x37e30000,
-    0x37e38000,
-    0x37e40000,
-    0x37e48000,
-    0x37e50000,
-    0x37e58000,
-    0x37e60000,
-    0x37e68000,
-    0x37e70000,
-    0x37e78000,
-    0x37e80000,
-    0x37e88000,
-    0x37e90000,
-    0x37e98000,
-    0x37ea0000,
-    0x37ea8000,
-    0x37eb0000,
-    0x37eb8000,
-    0x37ec0000,
-    0x37ec8000,
-    0x37ed0000,
-    0x37ed8000,
-    0x37ee0000,
-    0x37ee8000,
-    0x37ef0000,
-    0x37ef8000,
-    0x37f00000,
-    0x37f08000,
-    0x37f10000,
-    0x37f18000,
-    0x37f20000,
-    0x37f28000,
-    0x37f30000,
-    0x37f38000,
-    0x37f40000,
-    0x37f48000,
-    0x37f50000,
-    0x37f58000,
-    0x37f60000,
-    0x37f68000,
-    0x37f70000,
-    0x37f78000,
-    0x37f80000,
-    0x37f88000,
-    0x37f90000,
-    0x37f98000,
-    0x37fa0000,
-    0x37fa8000,
-    0x37fb0000,
-    0x37fb8000,
-    0x37fc0000,
-    0x37fc8000,
-    0x37fd0000,
-    0x37fd8000,
-    0x37fe0000,
-    0x37fe8000,
-    0x37ff0000,
-    0x37ff8000,
-    0x38000000,
-    0x38004000,
-    0x38008000,
-    0x3800c000,
-    0x38010000,
-    0x38014000,
-    0x38018000,
-    0x3801c000,
-    0x38020000,
-    0x38024000,
-    0x38028000,
-    0x3802c000,
-    0x38030000,
-    0x38034000,
-    0x38038000,
-    0x3803c000,
-    0x38040000,
-    0x38044000,
-    0x38048000,
-    0x3804c000,
-    0x38050000,
-    0x38054000,
-    0x38058000,
-    0x3805c000,
-    0x38060000,
-    0x38064000,
-    0x38068000,
-    0x3806c000,
-    0x38070000,
-    0x38074000,
-    0x38078000,
-    0x3807c000,
-    0x38080000,
-    0x38084000,
-    0x38088000,
-    0x3808c000,
-    0x38090000,
-    0x38094000,
-    0x38098000,
-    0x3809c000,
-    0x380a0000,
-    0x380a4000,
-    0x380a8000,
-    0x380ac000,
-    0x380b0000,
-    0x380b4000,
-    0x380b8000,
-    0x380bc000,
-    0x380c0000,
-    0x380c4000,
-    0x380c8000,
-    0x380cc000,
-    0x380d0000,
-    0x380d4000,
-    0x380d8000,
-    0x380dc000,
-    0x380e0000,
-    0x380e4000,
-    0x380e8000,
-    0x380ec000,
-    0x380f0000,
-    0x380f4000,
-    0x380f8000,
-    0x380fc000,
-    0x38100000,
-    0x38104000,
-    0x38108000,
-    0x3810c000,
-    0x38110000,
-    0x38114000,
-    0x38118000,
-    0x3811c000,
-    0x38120000,
-    0x38124000,
-    0x38128000,
-    0x3812c000,
-    0x38130000,
-    0x38134000,
-    0x38138000,
-    0x3813c000,
-    0x38140000,
-    0x38144000,
-    0x38148000,
-    0x3814c000,
-    0x38150000,
-    0x38154000,
-    0x38158000,
-    0x3815c000,
-    0x38160000,
-    0x38164000,
-    0x38168000,
-    0x3816c000,
-    0x38170000,
-    0x38174000,
-    0x38178000,
-    0x3817c000,
-    0x38180000,
-    0x38184000,
-    0x38188000,
-    0x3818c000,
-    0x38190000,
-    0x38194000,
-    0x38198000,
-    0x3819c000,
-    0x381a0000,
-    0x381a4000,
-    0x381a8000,
-    0x381ac000,
-    0x381b0000,
-    0x381b4000,
-    0x381b8000,
-    0x381bc000,
-    0x381c0000,
-    0x381c4000,
-    0x381c8000,
-    0x381cc000,
-    0x381d0000,
-    0x381d4000,
-    0x381d8000,
-    0x381dc000,
-    0x381e0000,
-    0x381e4000,
-    0x381e8000,
-    0x381ec000,
-    0x381f0000,
-    0x381f4000,
-    0x381f8000,
-    0x381fc000,
-    0x38200000,
-    0x38204000,
-    0x38208000,
-    0x3820c000,
-    0x38210000,
-    0x38214000,
-    0x38218000,
-    0x3821c000,
-    0x38220000,
-    0x38224000,
-    0x38228000,
-    0x3822c000,
-    0x38230000,
-    0x38234000,
-    0x38238000,
-    0x3823c000,
-    0x38240000,
-    0x38244000,
-    0x38248000,
-    0x3824c000,
-    0x38250000,
-    0x38254000,
-    0x38258000,
-    0x3825c000,
-    0x38260000,
-    0x38264000,
-    0x38268000,
-    0x3826c000,
-    0x38270000,
-    0x38274000,
-    0x38278000,
-    0x3827c000,
-    0x38280000,
-    0x38284000,
-    0x38288000,
-    0x3828c000,
-    0x38290000,
-    0x38294000,
-    0x38298000,
-    0x3829c000,
-    0x382a0000,
-    0x382a4000,
-    0x382a8000,
-    0x382ac000,
-    0x382b0000,
-    0x382b4000,
-    0x382b8000,
-    0x382bc000,
-    0x382c0000,
-    0x382c4000,
-    0x382c8000,
-    0x382cc000,
-    0x382d0000,
-    0x382d4000,
-    0x382d8000,
-    0x382dc000,
-    0x382e0000,
-    0x382e4000,
-    0x382e8000,
-    0x382ec000,
-    0x382f0000,
-    0x382f4000,
-    0x382f8000,
-    0x382fc000,
-    0x38300000,
-    0x38304000,
-    0x38308000,
-    0x3830c000,
-    0x38310000,
-    0x38314000,
-    0x38318000,
-    0x3831c000,
-    0x38320000,
-    0x38324000,
-    0x38328000,
-    0x3832c000,
-    0x38330000,
-    0x38334000,
-    0x38338000,
-    0x3833c000,
-    0x38340000,
-    0x38344000,
-    0x38348000,
-    0x3834c000,
-    0x38350000,
-    0x38354000,
-    0x38358000,
-    0x3835c000,
-    0x38360000,
-    0x38364000,
-    0x38368000,
-    0x3836c000,
-    0x38370000,
-    0x38374000,
-    0x38378000,
-    0x3837c000,
-    0x38380000,
-    0x38384000,
-    0x38388000,
-    0x3838c000,
-    0x38390000,
-    0x38394000,
-    0x38398000,
-    0x3839c000,
-    0x383a0000,
-    0x383a4000,
-    0x383a8000,
-    0x383ac000,
-    0x383b0000,
-    0x383b4000,
-    0x383b8000,
-    0x383bc000,
-    0x383c0000,
-    0x383c4000,
-    0x383c8000,
-    0x383cc000,
-    0x383d0000,
-    0x383d4000,
-    0x383d8000,
-    0x383dc000,
-    0x383e0000,
-    0x383e4000,
-    0x383e8000,
-    0x383ec000,
-    0x383f0000,
-    0x383f4000,
-    0x383f8000,
-    0x383fc000,
-    0x38400000,
-    0x38404000,
-    0x38408000,
-    0x3840c000,
-    0x38410000,
-    0x38414000,
-    0x38418000,
-    0x3841c000,
-    0x38420000,
-    0x38424000,
-    0x38428000,
-    0x3842c000,
-    0x38430000,
-    0x38434000,
-    0x38438000,
-    0x3843c000,
-    0x38440000,
-    0x38444000,
-    0x38448000,
-    0x3844c000,
-    0x38450000,
-    0x38454000,
-    0x38458000,
-    0x3845c000,
-    0x38460000,
-    0x38464000,
-    0x38468000,
-    0x3846c000,
-    0x38470000,
-    0x38474000,
-    0x38478000,
-    0x3847c000,
-    0x38480000,
-    0x38484000,
-    0x38488000,
-    0x3848c000,
-    0x38490000,
-    0x38494000,
-    0x38498000,
-    0x3849c000,
-    0x384a0000,
-    0x384a4000,
-    0x384a8000,
-    0x384ac000,
-    0x384b0000,
-    0x384b4000,
-    0x384b8000,
-    0x384bc000,
-    0x384c0000,
-    0x384c4000,
-    0x384c8000,
-    0x384cc000,
-    0x384d0000,
-    0x384d4000,
-    0x384d8000,
-    0x384dc000,
-    0x384e0000,
-    0x384e4000,
-    0x384e8000,
-    0x384ec000,
-    0x384f0000,
-    0x384f4000,
-    0x384f8000,
-    0x384fc000,
-    0x38500000,
-    0x38504000,
-    0x38508000,
-    0x3850c000,
-    0x38510000,
-    0x38514000,
-    0x38518000,
-    0x3851c000,
-    0x38520000,
-    0x38524000,
-    0x38528000,
-    0x3852c000,
-    0x38530000,
-    0x38534000,
-    0x38538000,
-    0x3853c000,
-    0x38540000,
-    0x38544000,
-    0x38548000,
-    0x3854c000,
-    0x38550000,
-    0x38554000,
-    0x38558000,
-    0x3855c000,
-    0x38560000,
-    0x38564000,
-    0x38568000,
-    0x3856c000,
-    0x38570000,
-    0x38574000,
-    0x38578000,
-    0x3857c000,
-    0x38580000,
-    0x38584000,
-    0x38588000,
-    0x3858c000,
-    0x38590000,
-    0x38594000,
-    0x38598000,
-    0x3859c000,
-    0x385a0000,
-    0x385a4000,
-    0x385a8000,
-    0x385ac000,
-    0x385b0000,
-    0x385b4000,
-    0x385b8000,
-    0x385bc000,
-    0x385c0000,
-    0x385c4000,
-    0x385c8000,
-    0x385cc000,
-    0x385d0000,
-    0x385d4000,
-    0x385d8000,
-    0x385dc000,
-    0x385e0000,
-    0x385e4000,
-    0x385e8000,
-    0x385ec000,
-    0x385f0000,
-    0x385f4000,
-    0x385f8000,
-    0x385fc000,
-    0x38600000,
-    0x38604000,
-    0x38608000,
-    0x3860c000,
-    0x38610000,
-    0x38614000,
-    0x38618000,
-    0x3861c000,
-    0x38620000,
-    0x38624000,
-    0x38628000,
-    0x3862c000,
-    0x38630000,
-    0x38634000,
-    0x38638000,
-    0x3863c000,
-    0x38640000,
-    0x38644000,
-    0x38648000,
-    0x3864c000,
-    0x38650000,
-    0x38654000,
-    0x38658000,
-    0x3865c000,
-    0x38660000,
-    0x38664000,
-    0x38668000,
-    0x3866c000,
-    0x38670000,
-    0x38674000,
-    0x38678000,
-    0x3867c000,
-    0x38680000,
-    0x38684000,
-    0x38688000,
-    0x3868c000,
-    0x38690000,
-    0x38694000,
-    0x38698000,
-    0x3869c000,
-    0x386a0000,
-    0x386a4000,
-    0x386a8000,
-    0x386ac000,
-    0x386b0000,
-    0x386b4000,
-    0x386b8000,
-    0x386bc000,
-    0x386c0000,
-    0x386c4000,
-    0x386c8000,
-    0x386cc000,
-    0x386d0000,
-    0x386d4000,
-    0x386d8000,
-    0x386dc000,
-    0x386e0000,
-    0x386e4000,
-    0x386e8000,
-    0x386ec000,
-    0x386f0000,
-    0x386f4000,
-    0x386f8000,
-    0x386fc000,
-    0x38700000,
-    0x38704000,
-    0x38708000,
-    0x3870c000,
-    0x38710000,
-    0x38714000,
-    0x38718000,
-    0x3871c000,
-    0x38720000,
-    0x38724000,
-    0x38728000,
-    0x3872c000,
-    0x38730000,
-    0x38734000,
-    0x38738000,
-    0x3873c000,
-    0x38740000,
-    0x38744000,
-    0x38748000,
-    0x3874c000,
-    0x38750000,
-    0x38754000,
-    0x38758000,
-    0x3875c000,
-    0x38760000,
-    0x38764000,
-    0x38768000,
-    0x3876c000,
-    0x38770000,
-    0x38774000,
-    0x38778000,
-    0x3877c000,
-    0x38780000,
-    0x38784000,
-    0x38788000,
-    0x3878c000,
-    0x38790000,
-    0x38794000,
-    0x38798000,
-    0x3879c000,
-    0x387a0000,
-    0x387a4000,
-    0x387a8000,
-    0x387ac000,
-    0x387b0000,
-    0x387b4000,
-    0x387b8000,
-    0x387bc000,
-    0x387c0000,
-    0x387c4000,
-    0x387c8000,
-    0x387cc000,
-    0x387d0000,
-    0x387d4000,
-    0x387d8000,
-    0x387dc000,
-    0x387e0000,
-    0x387e4000,
-    0x387e8000,
-    0x387ec000,
-    0x387f0000,
-    0x387f4000,
-    0x387f8000,
-    0x387fc000,
-    0x38000000,
-    0x38002000,
-    0x38004000,
-    0x38006000,
-    0x38008000,
-    0x3800a000,
-    0x3800c000,
-    0x3800e000,
-    0x38010000,
-    0x38012000,
-    0x38014000,
-    0x38016000,
-    0x38018000,
-    0x3801a000,
-    0x3801c000,
-    0x3801e000,
-    0x38020000,
-    0x38022000,
-    0x38024000,
-    0x38026000,
-    0x38028000,
-    0x3802a000,
-    0x3802c000,
-    0x3802e000,
-    0x38030000,
-    0x38032000,
-    0x38034000,
-    0x38036000,
-    0x38038000,
-    0x3803a000,
-    0x3803c000,
-    0x3803e000,
-    0x38040000,
-    0x38042000,
-    0x38044000,
-    0x38046000,
-    0x38048000,
-    0x3804a000,
-    0x3804c000,
-    0x3804e000,
-    0x38050000,
-    0x38052000,
-    0x38054000,
-    0x38056000,
-    0x38058000,
-    0x3805a000,
-    0x3805c000,
-    0x3805e000,
-    0x38060000,
-    0x38062000,
-    0x38064000,
-    0x38066000,
-    0x38068000,
-    0x3806a000,
-    0x3806c000,
-    0x3806e000,
-    0x38070000,
-    0x38072000,
-    0x38074000,
-    0x38076000,
-    0x38078000,
-    0x3807a000,
-    0x3807c000,
-    0x3807e000,
-    0x38080000,
-    0x38082000,
-    0x38084000,
-    0x38086000,
-    0x38088000,
-    0x3808a000,
-    0x3808c000,
-    0x3808e000,
-    0x38090000,
-    0x38092000,
-    0x38094000,
-    0x38096000,
-    0x38098000,
-    0x3809a000,
-    0x3809c000,
-    0x3809e000,
-    0x380a0000,
-    0x380a2000,
-    0x380a4000,
-    0x380a6000,
-    0x380a8000,
-    0x380aa000,
-    0x380ac000,
-    0x380ae000,
-    0x380b0000,
-    0x380b2000,
-    0x380b4000,
-    0x380b6000,
-    0x380b8000,
-    0x380ba000,
-    0x380bc000,
-    0x380be000,
-    0x380c0000,
-    0x380c2000,
-    0x380c4000,
-    0x380c6000,
-    0x380c8000,
-    0x380ca000,
-    0x380cc000,
-    0x380ce000,
-    0x380d0000,
-    0x380d2000,
-    0x380d4000,
-    0x380d6000,
-    0x380d8000,
-    0x380da000,
-    0x380dc000,
-    0x380de000,
-    0x380e0000,
-    0x380e2000,
-    0x380e4000,
-    0x380e6000,
-    0x380e8000,
-    0x380ea000,
-    0x380ec000,
-    0x380ee000,
-    0x380f0000,
-    0x380f2000,
-    0x380f4000,
-    0x380f6000,
-    0x380f8000,
-    0x380fa000,
-    0x380fc000,
-    0x380fe000,
-    0x38100000,
-    0x38102000,
-    0x38104000,
-    0x38106000,
-    0x38108000,
-    0x3810a000,
-    0x3810c000,
-    0x3810e000,
-    0x38110000,
-    0x38112000,
-    0x38114000,
-    0x38116000,
-    0x38118000,
-    0x3811a000,
-    0x3811c000,
-    0x3811e000,
-    0x38120000,
-    0x38122000,
-    0x38124000,
-    0x38126000,
-    0x38128000,
-    0x3812a000,
-    0x3812c000,
-    0x3812e000,
-    0x38130000,
-    0x38132000,
-    0x38134000,
-    0x38136000,
-    0x38138000,
-    0x3813a000,
-    0x3813c000,
-    0x3813e000,
-    0x38140000,
-    0x38142000,
-    0x38144000,
-    0x38146000,
-    0x38148000,
-    0x3814a000,
-    0x3814c000,
-    0x3814e000,
-    0x38150000,
-    0x38152000,
-    0x38154000,
-    0x38156000,
-    0x38158000,
-    0x3815a000,
-    0x3815c000,
-    0x3815e000,
-    0x38160000,
-    0x38162000,
-    0x38164000,
-    0x38166000,
-    0x38168000,
-    0x3816a000,
-    0x3816c000,
-    0x3816e000,
-    0x38170000,
-    0x38172000,
-    0x38174000,
-    0x38176000,
-    0x38178000,
-    0x3817a000,
-    0x3817c000,
-    0x3817e000,
-    0x38180000,
-    0x38182000,
-    0x38184000,
-    0x38186000,
-    0x38188000,
-    0x3818a000,
-    0x3818c000,
-    0x3818e000,
-    0x38190000,
-    0x38192000,
-    0x38194000,
-    0x38196000,
-    0x38198000,
-    0x3819a000,
-    0x3819c000,
-    0x3819e000,
-    0x381a0000,
-    0x381a2000,
-    0x381a4000,
-    0x381a6000,
-    0x381a8000,
-    0x381aa000,
-    0x381ac000,
-    0x381ae000,
-    0x381b0000,
-    0x381b2000,
-    0x381b4000,
-    0x381b6000,
-    0x381b8000,
-    0x381ba000,
-    0x381bc000,
-    0x381be000,
-    0x381c0000,
-    0x381c2000,
-    0x381c4000,
-    0x381c6000,
-    0x381c8000,
-    0x381ca000,
-    0x381cc000,
-    0x381ce000,
-    0x381d0000,
-    0x381d2000,
-    0x381d4000,
-    0x381d6000,
-    0x381d8000,
-    0x381da000,
-    0x381dc000,
-    0x381de000,
-    0x381e0000,
-    0x381e2000,
-    0x381e4000,
-    0x381e6000,
-    0x381e8000,
-    0x381ea000,
-    0x381ec000,
-    0x381ee000,
-    0x381f0000,
-    0x381f2000,
-    0x381f4000,
-    0x381f6000,
-    0x381f8000,
-    0x381fa000,
-    0x381fc000,
-    0x381fe000,
-    0x38200000,
-    0x38202000,
-    0x38204000,
-    0x38206000,
-    0x38208000,
-    0x3820a000,
-    0x3820c000,
-    0x3820e000,
-    0x38210000,
-    0x38212000,
-    0x38214000,
-    0x38216000,
-    0x38218000,
-    0x3821a000,
-    0x3821c000,
-    0x3821e000,
-    0x38220000,
-    0x38222000,
-    0x38224000,
-    0x38226000,
-    0x38228000,
-    0x3822a000,
-    0x3822c000,
-    0x3822e000,
-    0x38230000,
-    0x38232000,
-    0x38234000,
-    0x38236000,
-    0x38238000,
-    0x3823a000,
-    0x3823c000,
-    0x3823e000,
-    0x38240000,
-    0x38242000,
-    0x38244000,
-    0x38246000,
-    0x38248000,
-    0x3824a000,
-    0x3824c000,
-    0x3824e000,
-    0x38250000,
-    0x38252000,
-    0x38254000,
-    0x38256000,
-    0x38258000,
-    0x3825a000,
-    0x3825c000,
-    0x3825e000,
-    0x38260000,
-    0x38262000,
-    0x38264000,
-    0x38266000,
-    0x38268000,
-    0x3826a000,
-    0x3826c000,
-    0x3826e000,
-    0x38270000,
-    0x38272000,
-    0x38274000,
-    0x38276000,
-    0x38278000,
-    0x3827a000,
-    0x3827c000,
-    0x3827e000,
-    0x38280000,
-    0x38282000,
-    0x38284000,
-    0x38286000,
-    0x38288000,
-    0x3828a000,
-    0x3828c000,
-    0x3828e000,
-    0x38290000,
-    0x38292000,
-    0x38294000,
-    0x38296000,
-    0x38298000,
-    0x3829a000,
-    0x3829c000,
-    0x3829e000,
-    0x382a0000,
-    0x382a2000,
-    0x382a4000,
-    0x382a6000,
-    0x382a8000,
-    0x382aa000,
-    0x382ac000,
-    0x382ae000,
-    0x382b0000,
-    0x382b2000,
-    0x382b4000,
-    0x382b6000,
-    0x382b8000,
-    0x382ba000,
-    0x382bc000,
-    0x382be000,
-    0x382c0000,
-    0x382c2000,
-    0x382c4000,
-    0x382c6000,
-    0x382c8000,
-    0x382ca000,
-    0x382cc000,
-    0x382ce000,
-    0x382d0000,
-    0x382d2000,
-    0x382d4000,
-    0x382d6000,
-    0x382d8000,
-    0x382da000,
-    0x382dc000,
-    0x382de000,
-    0x382e0000,
-    0x382e2000,
-    0x382e4000,
-    0x382e6000,
-    0x382e8000,
-    0x382ea000,
-    0x382ec000,
-    0x382ee000,
-    0x382f0000,
-    0x382f2000,
-    0x382f4000,
-    0x382f6000,
-    0x382f8000,
-    0x382fa000,
-    0x382fc000,
-    0x382fe000,
-    0x38300000,
-    0x38302000,
-    0x38304000,
-    0x38306000,
-    0x38308000,
-    0x3830a000,
-    0x3830c000,
-    0x3830e000,
-    0x38310000,
-    0x38312000,
-    0x38314000,
-    0x38316000,
-    0x38318000,
-    0x3831a000,
-    0x3831c000,
-    0x3831e000,
-    0x38320000,
-    0x38322000,
-    0x38324000,
-    0x38326000,
-    0x38328000,
-    0x3832a000,
-    0x3832c000,
-    0x3832e000,
-    0x38330000,
-    0x38332000,
-    0x38334000,
-    0x38336000,
-    0x38338000,
-    0x3833a000,
-    0x3833c000,
-    0x3833e000,
-    0x38340000,
-    0x38342000,
-    0x38344000,
-    0x38346000,
-    0x38348000,
-    0x3834a000,
-    0x3834c000,
-    0x3834e000,
-    0x38350000,
-    0x38352000,
-    0x38354000,
-    0x38356000,
-    0x38358000,
-    0x3835a000,
-    0x3835c000,
-    0x3835e000,
-    0x38360000,
-    0x38362000,
-    0x38364000,
-    0x38366000,
-    0x38368000,
-    0x3836a000,
-    0x3836c000,
-    0x3836e000,
-    0x38370000,
-    0x38372000,
-    0x38374000,
-    0x38376000,
-    0x38378000,
-    0x3837a000,
-    0x3837c000,
-    0x3837e000,
-    0x38380000,
-    0x38382000,
-    0x38384000,
-    0x38386000,
-    0x38388000,
-    0x3838a000,
-    0x3838c000,
-    0x3838e000,
-    0x38390000,
-    0x38392000,
-    0x38394000,
-    0x38396000,
-    0x38398000,
-    0x3839a000,
-    0x3839c000,
-    0x3839e000,
-    0x383a0000,
-    0x383a2000,
-    0x383a4000,
-    0x383a6000,
-    0x383a8000,
-    0x383aa000,
-    0x383ac000,
-    0x383ae000,
-    0x383b0000,
-    0x383b2000,
-    0x383b4000,
-    0x383b6000,
-    0x383b8000,
-    0x383ba000,
-    0x383bc000,
-    0x383be000,
-    0x383c0000,
-    0x383c2000,
-    0x383c4000,
-    0x383c6000,
-    0x383c8000,
-    0x383ca000,
-    0x383cc000,
-    0x383ce000,
-    0x383d0000,
-    0x383d2000,
-    0x383d4000,
-    0x383d6000,
-    0x383d8000,
-    0x383da000,
-    0x383dc000,
-    0x383de000,
-    0x383e0000,
-    0x383e2000,
-    0x383e4000,
-    0x383e6000,
-    0x383e8000,
-    0x383ea000,
-    0x383ec000,
-    0x383ee000,
-    0x383f0000,
-    0x383f2000,
-    0x383f4000,
-    0x383f6000,
-    0x383f8000,
-    0x383fa000,
-    0x383fc000,
-    0x383fe000,
-    0x38400000,
-    0x38402000,
-    0x38404000,
-    0x38406000,
-    0x38408000,
-    0x3840a000,
-    0x3840c000,
-    0x3840e000,
-    0x38410000,
-    0x38412000,
-    0x38414000,
-    0x38416000,
-    0x38418000,
-    0x3841a000,
-    0x3841c000,
-    0x3841e000,
-    0x38420000,
-    0x38422000,
-    0x38424000,
-    0x38426000,
-    0x38428000,
-    0x3842a000,
-    0x3842c000,
-    0x3842e000,
-    0x38430000,
-    0x38432000,
-    0x38434000,
-    0x38436000,
-    0x38438000,
-    0x3843a000,
-    0x3843c000,
-    0x3843e000,
-    0x38440000,
-    0x38442000,
-    0x38444000,
-    0x38446000,
-    0x38448000,
-    0x3844a000,
-    0x3844c000,
-    0x3844e000,
-    0x38450000,
-    0x38452000,
-    0x38454000,
-    0x38456000,
-    0x38458000,
-    0x3845a000,
-    0x3845c000,
-    0x3845e000,
-    0x38460000,
-    0x38462000,
-    0x38464000,
-    0x38466000,
-    0x38468000,
-    0x3846a000,
-    0x3846c000,
-    0x3846e000,
-    0x38470000,
-    0x38472000,
-    0x38474000,
-    0x38476000,
-    0x38478000,
-    0x3847a000,
-    0x3847c000,
-    0x3847e000,
-    0x38480000,
-    0x38482000,
-    0x38484000,
-    0x38486000,
-    0x38488000,
-    0x3848a000,
-    0x3848c000,
-    0x3848e000,
-    0x38490000,
-    0x38492000,
-    0x38494000,
-    0x38496000,
-    0x38498000,
-    0x3849a000,
-    0x3849c000,
-    0x3849e000,
-    0x384a0000,
-    0x384a2000,
-    0x384a4000,
-    0x384a6000,
-    0x384a8000,
-    0x384aa000,
-    0x384ac000,
-    0x384ae000,
-    0x384b0000,
-    0x384b2000,
-    0x384b4000,
-    0x384b6000,
-    0x384b8000,
-    0x384ba000,
-    0x384bc000,
-    0x384be000,
-    0x384c0000,
-    0x384c2000,
-    0x384c4000,
-    0x384c6000,
-    0x384c8000,
-    0x384ca000,
-    0x384cc000,
-    0x384ce000,
-    0x384d0000,
-    0x384d2000,
-    0x384d4000,
-    0x384d6000,
-    0x384d8000,
-    0x384da000,
-    0x384dc000,
-    0x384de000,
-    0x384e0000,
-    0x384e2000,
-    0x384e4000,
-    0x384e6000,
-    0x384e8000,
-    0x384ea000,
-    0x384ec000,
-    0x384ee000,
-    0x384f0000,
-    0x384f2000,
-    0x384f4000,
-    0x384f6000,
-    0x384f8000,
-    0x384fa000,
-    0x384fc000,
-    0x384fe000,
-    0x38500000,
-    0x38502000,
-    0x38504000,
-    0x38506000,
-    0x38508000,
-    0x3850a000,
-    0x3850c000,
-    0x3850e000,
-    0x38510000,
-    0x38512000,
-    0x38514000,
-    0x38516000,
-    0x38518000,
-    0x3851a000,
-    0x3851c000,
-    0x3851e000,
-    0x38520000,
-    0x38522000,
-    0x38524000,
-    0x38526000,
-    0x38528000,
-    0x3852a000,
-    0x3852c000,
-    0x3852e000,
-    0x38530000,
-    0x38532000,
-    0x38534000,
-    0x38536000,
-    0x38538000,
-    0x3853a000,
-    0x3853c000,
-    0x3853e000,
-    0x38540000,
-    0x38542000,
-    0x38544000,
-    0x38546000,
-    0x38548000,
-    0x3854a000,
-    0x3854c000,
-    0x3854e000,
-    0x38550000,
-    0x38552000,
-    0x38554000,
-    0x38556000,
-    0x38558000,
-    0x3855a000,
-    0x3855c000,
-    0x3855e000,
-    0x38560000,
-    0x38562000,
-    0x38564000,
-    0x38566000,
-    0x38568000,
-    0x3856a000,
-    0x3856c000,
-    0x3856e000,
-    0x38570000,
-    0x38572000,
-    0x38574000,
-    0x38576000,
-    0x38578000,
-    0x3857a000,
-    0x3857c000,
-    0x3857e000,
-    0x38580000,
-    0x38582000,
-    0x38584000,
-    0x38586000,
-    0x38588000,
-    0x3858a000,
-    0x3858c000,
-    0x3858e000,
-    0x38590000,
-    0x38592000,
-    0x38594000,
-    0x38596000,
-    0x38598000,
-    0x3859a000,
-    0x3859c000,
-    0x3859e000,
-    0x385a0000,
-    0x385a2000,
-    0x385a4000,
-    0x385a6000,
-    0x385a8000,
-    0x385aa000,
-    0x385ac000,
-    0x385ae000,
-    0x385b0000,
-    0x385b2000,
-    0x385b4000,
-    0x385b6000,
-    0x385b8000,
-    0x385ba000,
-    0x385bc000,
-    0x385be000,
-    0x385c0000,
-    0x385c2000,
-    0x385c4000,
-    0x385c6000,
-    0x385c8000,
-    0x385ca000,
-    0x385cc000,
-    0x385ce000,
-    0x385d0000,
-    0x385d2000,
-    0x385d4000,
-    0x385d6000,
-    0x385d8000,
-    0x385da000,
-    0x385dc000,
-    0x385de000,
-    0x385e0000,
-    0x385e2000,
-    0x385e4000,
-    0x385e6000,
-    0x385e8000,
-    0x385ea000,
-    0x385ec000,
-    0x385ee000,
-    0x385f0000,
-    0x385f2000,
-    0x385f4000,
-    0x385f6000,
-    0x385f8000,
-    0x385fa000,
-    0x385fc000,
-    0x385fe000,
-    0x38600000,
-    0x38602000,
-    0x38604000,
-    0x38606000,
-    0x38608000,
-    0x3860a000,
-    0x3860c000,
-    0x3860e000,
-    0x38610000,
-    0x38612000,
-    0x38614000,
-    0x38616000,
-    0x38618000,
-    0x3861a000,
-    0x3861c000,
-    0x3861e000,
-    0x38620000,
-    0x38622000,
-    0x38624000,
-    0x38626000,
-    0x38628000,
-    0x3862a000,
-    0x3862c000,
-    0x3862e000,
-    0x38630000,
-    0x38632000,
-    0x38634000,
-    0x38636000,
-    0x38638000,
-    0x3863a000,
-    0x3863c000,
-    0x3863e000,
-    0x38640000,
-    0x38642000,
-    0x38644000,
-    0x38646000,
-    0x38648000,
-    0x3864a000,
-    0x3864c000,
-    0x3864e000,
-    0x38650000,
-    0x38652000,
-    0x38654000,
-    0x38656000,
-    0x38658000,
-    0x3865a000,
-    0x3865c000,
-    0x3865e000,
-    0x38660000,
-    0x38662000,
-    0x38664000,
-    0x38666000,
-    0x38668000,
-    0x3866a000,
-    0x3866c000,
-    0x3866e000,
-    0x38670000,
-    0x38672000,
-    0x38674000,
-    0x38676000,
-    0x38678000,
-    0x3867a000,
-    0x3867c000,
-    0x3867e000,
-    0x38680000,
-    0x38682000,
-    0x38684000,
-    0x38686000,
-    0x38688000,
-    0x3868a000,
-    0x3868c000,
-    0x3868e000,
-    0x38690000,
-    0x38692000,
-    0x38694000,
-    0x38696000,
-    0x38698000,
-    0x3869a000,
-    0x3869c000,
-    0x3869e000,
-    0x386a0000,
-    0x386a2000,
-    0x386a4000,
-    0x386a6000,
-    0x386a8000,
-    0x386aa000,
-    0x386ac000,
-    0x386ae000,
-    0x386b0000,
-    0x386b2000,
-    0x386b4000,
-    0x386b6000,
-    0x386b8000,
-    0x386ba000,
-    0x386bc000,
-    0x386be000,
-    0x386c0000,
-    0x386c2000,
-    0x386c4000,
-    0x386c6000,
-    0x386c8000,
-    0x386ca000,
-    0x386cc000,
-    0x386ce000,
-    0x386d0000,
-    0x386d2000,
-    0x386d4000,
-    0x386d6000,
-    0x386d8000,
-    0x386da000,
-    0x386dc000,
-    0x386de000,
-    0x386e0000,
-    0x386e2000,
-    0x386e4000,
-    0x386e6000,
-    0x386e8000,
-    0x386ea000,
-    0x386ec000,
-    0x386ee000,
-    0x386f0000,
-    0x386f2000,
-    0x386f4000,
-    0x386f6000,
-    0x386f8000,
-    0x386fa000,
-    0x386fc000,
-    0x386fe000,
-    0x38700000,
-    0x38702000,
-    0x38704000,
-    0x38706000,
-    0x38708000,
-    0x3870a000,
-    0x3870c000,
-    0x3870e000,
-    0x38710000,
-    0x38712000,
-    0x38714000,
-    0x38716000,
-    0x38718000,
-    0x3871a000,
-    0x3871c000,
-    0x3871e000,
-    0x38720000,
-    0x38722000,
-    0x38724000,
-    0x38726000,
-    0x38728000,
-    0x3872a000,
-    0x3872c000,
-    0x3872e000,
-    0x38730000,
-    0x38732000,
-    0x38734000,
-    0x38736000,
-    0x38738000,
-    0x3873a000,
-    0x3873c000,
-    0x3873e000,
-    0x38740000,
-    0x38742000,
-    0x38744000,
-    0x38746000,
-    0x38748000,
-    0x3874a000,
-    0x3874c000,
-    0x3874e000,
-    0x38750000,
-    0x38752000,
-    0x38754000,
-    0x38756000,
-    0x38758000,
-    0x3875a000,
-    0x3875c000,
-    0x3875e000,
-    0x38760000,
-    0x38762000,
-    0x38764000,
-    0x38766000,
-    0x38768000,
-    0x3876a000,
-    0x3876c000,
-    0x3876e000,
-    0x38770000,
-    0x38772000,
-    0x38774000,
-    0x38776000,
-    0x38778000,
-    0x3877a000,
-    0x3877c000,
-    0x3877e000,
-    0x38780000,
-    0x38782000,
-    0x38784000,
-    0x38786000,
-    0x38788000,
-    0x3878a000,
-    0x3878c000,
-    0x3878e000,
-    0x38790000,
-    0x38792000,
-    0x38794000,
-    0x38796000,
-    0x38798000,
-    0x3879a000,
-    0x3879c000,
-    0x3879e000,
-    0x387a0000,
-    0x387a2000,
-    0x387a4000,
-    0x387a6000,
-    0x387a8000,
-    0x387aa000,
-    0x387ac000,
-    0x387ae000,
-    0x387b0000,
-    0x387b2000,
-    0x387b4000,
-    0x387b6000,
-    0x387b8000,
-    0x387ba000,
-    0x387bc000,
-    0x387be000,
-    0x387c0000,
-    0x387c2000,
-    0x387c4000,
-    0x387c6000,
-    0x387c8000,
-    0x387ca000,
-    0x387cc000,
-    0x387ce000,
-    0x387d0000,
-    0x387d2000,
-    0x387d4000,
-    0x387d6000,
-    0x387d8000,
-    0x387da000,
-    0x387dc000,
-    0x387de000,
-    0x387e0000,
-    0x387e2000,
-    0x387e4000,
-    0x387e6000,
-    0x387e8000,
-    0x387ea000,
-    0x387ec000,
-    0x387ee000,
-    0x387f0000,
-    0x387f2000,
-    0x387f4000,
-    0x387f6000,
-    0x387f8000,
-    0x387fa000,
-    0x387fc000,
-    0x387fe000,
-};
-
-const static unsigned g_exponent[64] = {
-    0x00000000,
-    0x00800000,
-    0x01000000,
-    0x01800000,
-    0x02000000,
-    0x02800000,
-    0x03000000,
-    0x03800000,
-    0x04000000,
-    0x04800000,
-    0x05000000,
-    0x05800000,
-    0x06000000,
-    0x06800000,
-    0x07000000,
-    0x07800000,
-    0x08000000,
-    0x08800000,
-    0x09000000,
-    0x09800000,
-    0x0a000000,
-    0x0a800000,
-    0x0b000000,
-    0x0b800000,
-    0x0c000000,
-    0x0c800000,
-    0x0d000000,
-    0x0d800000,
-    0x0e000000,
-    0x0e800000,
-    0x0f000000,
-    0x47800000,
-    0x80000000,
-    0x80800000,
-    0x81000000,
-    0x81800000,
-    0x82000000,
-    0x82800000,
-    0x83000000,
-    0x83800000,
-    0x84000000,
-    0x84800000,
-    0x85000000,
-    0x85800000,
-    0x86000000,
-    0x86800000,
-    0x87000000,
-    0x87800000,
-    0x88000000,
-    0x88800000,
-    0x89000000,
-    0x89800000,
-    0x8a000000,
-    0x8a800000,
-    0x8b000000,
-    0x8b800000,
-    0x8c000000,
-    0x8c800000,
-    0x8d000000,
-    0x8d800000,
-    0x8e000000,
-    0x8e800000,
-    0x8f000000,
-    0xc7800000,
-};
-
-const static unsigned g_offset[64] = {
-    0x00000000,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000000,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-    0x00000400,
-};
-
-float float16ToFloat32(unsigned short h)
-{
-    unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
-    return *(float*) &i32;
-}
-}
-
diff --git a/src/third_party/angle/src/libGLESv2/Float16ToFloat32.py b/src/third_party/angle/src/libGLESv2/Float16ToFloat32.py
deleted file mode 100644
index cf039bf..0000000
--- a/src/third_party/angle/src/libGLESv2/Float16ToFloat32.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-
-# This script generates a function that converts 16-bit precision floating
-# point numbers to 32-bit.
-# It is based on ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf.
-
-def convertMantissa(i):
-    if i == 0:
-        return 0
-    elif i < 1024:
-        m = i << 13
-        e = 0
-        while not (m & 0x00800000):
-            e -= 0x00800000
-            m = m << 1
-        m &= ~0x00800000
-        e += 0x38800000
-        return m | e
-    else:
-        return 0x38000000 + ((i - 1024) << 13)
-
-def convertExponent(i):
-    if i == 0:
-        return 0
-    elif i in range(1, 31):
-        return i << 23
-    elif i == 31:
-        return 0x47800000
-    elif i == 32:
-        return 0x80000000
-    elif i in range(33, 63):
-        return 0x80000000 + ((i - 32) << 23)
-    else:
-        return 0xC7800000
-
-def convertOffset(i):
-    if i == 0 or i == 32:
-        return 0
-    else:
-        return 1024
-
-print """//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// This file is automatically generated.
-
-namespace gl
-{
-"""
-
-print "const static unsigned g_mantissa[2048] = {"
-for i in range(0, 2048):
-    print "    %#010x," % convertMantissa(i)
-print "};\n"
-
-print "const static unsigned g_exponent[64] = {"
-for i in range(0, 64):
-    print "    %#010x," % convertExponent(i)
-print "};\n"
-
-print "const static unsigned g_offset[64] = {"
-for i in range(0, 64):
-    print "    %#010x," % convertOffset(i)
-print "};\n"
-
-print """float float16ToFloat32(unsigned short h)
-{
-    unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
-    return *(float*) &i32;
-}
-}
-"""
diff --git a/src/third_party/angle/src/libGLESv2/Framebuffer.cpp b/src/third_party/angle/src/libGLESv2/Framebuffer.cpp
deleted file mode 100644
index b0abba0..0000000
--- a/src/third_party/angle/src/libGLESv2/Framebuffer.cpp
+++ /dev/null
@@ -1,603 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
-// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
-
-#include "libGLESv2/Framebuffer.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Renderbuffer.h"
-
-namespace gl
-{
-
-Framebuffer::Framebuffer(rx::Renderer *renderer)
-    : mRenderer(renderer)
-{
-    for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-    {
-        mColorbufferTypes[colorAttachment] = GL_NONE;
-        mDrawBufferStates[colorAttachment] = GL_NONE;
-    }
-    mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
-    mReadBufferState = GL_COLOR_ATTACHMENT0_EXT;
-
-    mDepthbufferType = GL_NONE;
-    mStencilbufferType = GL_NONE;
-}
-
-Framebuffer::~Framebuffer()
-{
-    for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-    {
-        mColorbufferPointers[colorAttachment].set(NULL);
-    }
-    mDepthbufferPointer.set(NULL);
-    mStencilbufferPointer.set(NULL);
-}
-
-Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
-{
-    gl::Context *context = gl::getContext();
-    Renderbuffer *buffer = NULL;
-
-    if (type == GL_NONE)
-    {
-        buffer = NULL;
-    }
-    else if (type == GL_RENDERBUFFER)
-    {
-        buffer = context->getRenderbuffer(handle);
-    }
-    else if (IsInternalTextureTarget(type))
-    {
-        buffer = context->getTexture(handle)->getRenderbuffer(type);
-    }
-    else
-    {
-        UNREACHABLE();
-    }
-
-    return buffer;
-}
-
-void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer)
-{
-    ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
-    mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE;
-    mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer));
-}
-
-void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
-{
-    mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
-    mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
-}
-
-void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
-{
-    mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
-    mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
-}
-
-void Framebuffer::detachTexture(GLuint texture)
-{
-    for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-    {
-        if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
-        {
-            mColorbufferTypes[colorAttachment] = GL_NONE;
-            mColorbufferPointers[colorAttachment].set(NULL);
-        }
-    }
-
-    if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
-    {
-        mDepthbufferType = GL_NONE;
-        mDepthbufferPointer.set(NULL);
-    }
-
-    if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
-    {
-        mStencilbufferType = GL_NONE;
-        mStencilbufferPointer.set(NULL);
-    }
-}
-
-void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
-{
-    for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-    {
-        if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
-        {
-            mColorbufferTypes[colorAttachment] = GL_NONE;
-            mColorbufferPointers[colorAttachment].set(NULL);
-        }
-    }
-
-    if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
-    {
-        mDepthbufferType = GL_NONE;
-        mDepthbufferPointer.set(NULL);
-    }
-
-    if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
-    {
-        mStencilbufferType = GL_NONE;
-        mStencilbufferPointer.set(NULL);
-    }
-}
-
-unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const
-{
-    ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
-
-    Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get();
-
-    if (colorbuffer)
-    {
-        return colorbuffer->getSerial();
-    }
-
-    return 0;
-}
-
-unsigned int Framebuffer::getDepthbufferSerial() const
-{
-    Renderbuffer *depthbuffer = mDepthbufferPointer.get();
-
-    if (depthbuffer)
-    {
-        return depthbuffer->getSerial();
-    }
-
-    return 0;
-}
-
-unsigned int Framebuffer::getStencilbufferSerial() const
-{
-    Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
-
-    if (stencilbuffer)
-    {
-        return stencilbuffer->getSerial();
-    }
-
-    return 0;
-}
-
-Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
-{
-    ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
-    return mColorbufferPointers[colorAttachment].get();
-}
-
-Renderbuffer *Framebuffer::getDepthbuffer() const
-{
-    return mDepthbufferPointer.get();
-}
-
-Renderbuffer *Framebuffer::getStencilbuffer() const
-{
-    return mStencilbufferPointer.get();
-}
-
-Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const
-{
-    Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
-    
-    if (!depthstencilbuffer)
-    {
-        depthstencilbuffer = mStencilbufferPointer.get();
-    }
-
-    return depthstencilbuffer;
-}
-
-Renderbuffer *Framebuffer::getReadColorbuffer() const
-{
-    // Will require more logic if glReadBuffers is supported
-    return mColorbufferPointers[0].get();
-}
-
-GLenum Framebuffer::getReadColorbufferType() const
-{
-    // Will require more logic if glReadBuffers is supported
-    return mColorbufferTypes[0];
-}
-
-Renderbuffer *Framebuffer::getFirstColorbuffer() const
-{
-    for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-    {
-        if (mColorbufferTypes[colorAttachment] != GL_NONE)
-        {
-            return mColorbufferPointers[colorAttachment].get();
-        }
-    }
-
-    return NULL;
-}
-
-GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
-{
-    ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
-    return mColorbufferTypes[colorAttachment];
-}
-
-GLenum Framebuffer::getDepthbufferType() const
-{
-    return mDepthbufferType;
-}
-
-GLenum Framebuffer::getStencilbufferType() const
-{
-    return mStencilbufferType;
-}
-
-GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
-{
-    ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
-    return mColorbufferPointers[colorAttachment].id();
-}
-
-GLuint Framebuffer::getDepthbufferHandle() const
-{
-    return mDepthbufferPointer.id();
-}
-
-GLuint Framebuffer::getStencilbufferHandle() const
-{
-    return mStencilbufferPointer.id();
-}
-
-GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
-{
-    return mDrawBufferStates[colorAttachment];
-}
-
-void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
-{
-    mDrawBufferStates[colorAttachment] = drawBuffer;
-}
-
-bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
-{
-    return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE);
-}
-
-bool Framebuffer::hasEnabledColorAttachment() const
-{
-    for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-    {
-        if (isEnabledColorAttachment(colorAttachment))
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-bool Framebuffer::hasStencil() const
-{
-    if (mStencilbufferType != GL_NONE)
-    {
-        const Renderbuffer *stencilbufferObject = getStencilbuffer();
-
-        if (stencilbufferObject)
-        {
-            return stencilbufferObject->getStencilSize() > 0;
-        }
-    }
-
-    return false;
-}
-
-bool Framebuffer::usingExtendedDrawBuffers() const
-{
-    for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-    {
-        if (isEnabledColorAttachment(colorAttachment))
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-GLenum Framebuffer::completeness() const
-{
-    int width = 0;
-    int height = 0;
-    int colorbufferSize = 0;
-    int samples = -1;
-    bool missingAttachment = true;
-
-    for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-    {
-        if (mColorbufferTypes[colorAttachment] != GL_NONE)
-        {
-            const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment);
-
-            if (!colorbuffer)
-            {
-                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-            }
-
-            if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
-            {
-                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-            }
-
-            if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
-            {
-                if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
-                {
-                    return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-                }
-            }
-            else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
-            {
-                GLint internalformat = colorbuffer->getInternalFormat();
-                GLenum format = gl::ExtractFormat(internalformat);
-
-                if (IsCompressed(format) ||
-                    format == GL_ALPHA ||
-                    format == GL_LUMINANCE ||
-                    format == GL_LUMINANCE_ALPHA)
-                {
-                    return GL_FRAMEBUFFER_UNSUPPORTED;
-                }
-
-                bool filtering, renderable;
-
-                if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
-                    (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
-                {
-                    return GL_FRAMEBUFFER_UNSUPPORTED;
-                }
-
-                if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat))
-                {
-                    return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-                }
-            }
-            else
-            {
-                UNREACHABLE();
-                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-            }
-
-            if (!missingAttachment)
-            {
-                // all color attachments must have the same width and height
-                if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
-                {
-                    return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
-                }
-
-                // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
-                // all color attachments have the same number of samples for the FBO to be complete.
-                if (colorbuffer->getSamples() != samples)
-                {
-                    return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
-                }
-
-                // all color attachments attachments must have the same number of bitplanes
-                if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize)
-                {
-                    return GL_FRAMEBUFFER_UNSUPPORTED;
-                }
-
-                // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
-                for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
-                {
-                    if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get())
-                    {
-                        return GL_FRAMEBUFFER_UNSUPPORTED;
-                    }
-                }
-            }
-            else
-            {
-                width = colorbuffer->getWidth();
-                height = colorbuffer->getHeight();
-                samples = colorbuffer->getSamples();
-                colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat());
-                missingAttachment = false;
-            }
-        }
-    }
-
-    const Renderbuffer *depthbuffer = NULL;
-    const Renderbuffer *stencilbuffer = NULL;
-
-    if (mDepthbufferType != GL_NONE)
-    {
-        depthbuffer = getDepthbuffer();
-
-        if (!depthbuffer)
-        {
-            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-        }
-
-        if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
-        {
-            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-        }
-
-        if (mDepthbufferType == GL_RENDERBUFFER)
-        {
-            if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
-            {
-                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-            }
-        }
-        else if (IsInternalTextureTarget(mDepthbufferType))
-        {
-            GLint internalformat = depthbuffer->getInternalFormat();
-
-            // depth texture attachments require OES/ANGLE_depth_texture
-            if (!mRenderer->getDepthTextureSupport())
-            {
-                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-            }
-
-            if (!gl::IsDepthTexture(internalformat))
-            {
-                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-            }
-        }
-        else
-        {
-            UNREACHABLE();
-            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-        }
-
-        if (missingAttachment)
-        {
-            width = depthbuffer->getWidth();
-            height = depthbuffer->getHeight();
-            samples = depthbuffer->getSamples();
-            missingAttachment = false;
-        }
-        else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
-        {
-            return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
-        }
-        else if (samples != depthbuffer->getSamples())
-        {
-            return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
-        }
-    }
-
-    if (mStencilbufferType != GL_NONE)
-    {
-        stencilbuffer = getStencilbuffer();
-
-        if (!stencilbuffer)
-        {
-            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-        }
-
-        if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
-        {
-            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-        }
-
-        if (mStencilbufferType == GL_RENDERBUFFER)
-        {
-            if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
-            {
-                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-            }
-        }
-        else if (IsInternalTextureTarget(mStencilbufferType))
-        {
-            GLint internalformat = stencilbuffer->getInternalFormat();
-
-            // texture stencil attachments come along as part
-            // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
-            if (!mRenderer->getDepthTextureSupport())
-            {
-                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-            }
-
-            if (!gl::IsStencilTexture(internalformat))
-            {
-                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-            }
-        }
-        else
-        {
-            UNREACHABLE();
-            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-        }
-
-        if (missingAttachment)
-        {
-            width = stencilbuffer->getWidth();
-            height = stencilbuffer->getHeight();
-            samples = stencilbuffer->getSamples();
-            missingAttachment = false;
-        }
-        else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
-        {
-            return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
-        }
-        else if (samples != stencilbuffer->getSamples())
-        {
-            return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
-        }
-    }
-
-    // if we have both a depth and stencil buffer, they must refer to the same object
-    // since we only support packed_depth_stencil and not separate depth and stencil
-    if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
-    {
-        return GL_FRAMEBUFFER_UNSUPPORTED;
-    }
-
-    // we need to have at least one attachment to be complete
-    if (missingAttachment)
-    {
-        return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
-    }
-
-    return GL_FRAMEBUFFER_COMPLETE;
-}
-
-DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
-    : Framebuffer(renderer)
-{
-    mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer));
-
-    Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
-    mDepthbufferPointer.set(depthStencilRenderbuffer);
-    mStencilbufferPointer.set(depthStencilRenderbuffer);
-
-    mColorbufferTypes[0] = GL_RENDERBUFFER;
-    mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
-    mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
-
-    mDrawBufferStates[0] = GL_BACK;
-    mReadBufferState = GL_BACK;
-}
-
-int Framebuffer::getSamples() const
-{
-    if (completeness() == GL_FRAMEBUFFER_COMPLETE)
-    {
-        // for a complete framebuffer, all attachments must have the same sample count
-        // in this case return the first nonzero sample size
-        for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-        {
-            if (mColorbufferTypes[colorAttachment] != GL_NONE)
-            {
-                return getColorbuffer(colorAttachment)->getSamples();
-            }
-        }
-    }
-
-    return 0;
-}
-
-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;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/Framebuffer.h b/src/third_party/angle/src/libGLESv2/Framebuffer.h
deleted file mode 100644
index b54e008..0000000
--- a/src/third_party/angle/src/libGLESv2/Framebuffer.h
+++ /dev/null
@@ -1,108 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// 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 "common/angleutils.h"
-#include "common/RefCountObject.h"
-#include "constants.h"
-
-namespace rx
-{
-class Renderer;
-}
-
-namespace gl
-{
-class Renderbuffer;
-class Colorbuffer;
-class Depthbuffer;
-class Stencilbuffer;
-class DepthStencilbuffer;
-
-class Framebuffer
-{
-  public:
-    explicit Framebuffer(rx::Renderer *renderer);
-
-    virtual ~Framebuffer();
-
-    void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer);
-    void setDepthbuffer(GLenum type, GLuint depthbuffer);
-    void setStencilbuffer(GLenum type, GLuint stencilbuffer);
-
-    void detachTexture(GLuint texture);
-    void detachRenderbuffer(GLuint renderbuffer);
-
-    unsigned int getRenderTargetSerial(unsigned int colorAttachment) const;
-    unsigned int getDepthbufferSerial() const;
-    unsigned int getStencilbufferSerial() const;
-
-    Renderbuffer *getColorbuffer(unsigned int colorAttachment) const;
-    Renderbuffer *getDepthbuffer() const;
-    Renderbuffer *getStencilbuffer() const;
-    Renderbuffer *getDepthOrStencilbuffer() const;
-    Renderbuffer *getReadColorbuffer() const;
-    GLenum getReadColorbufferType() const;
-    Renderbuffer *getFirstColorbuffer() const;
-
-    GLenum getColorbufferType(unsigned int colorAttachment) const;
-    GLenum getDepthbufferType() const;
-    GLenum getStencilbufferType() const;
-
-    GLuint getColorbufferHandle(unsigned int colorAttachment) const;
-    GLuint getDepthbufferHandle() const;
-    GLuint getStencilbufferHandle() const;
-
-    GLenum getDrawBufferState(unsigned int colorAttachment) const;
-    void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer);
-
-    bool isEnabledColorAttachment(unsigned int colorAttachment) const;
-    bool hasEnabledColorAttachment() const;
-    bool hasStencil() const;
-    int getSamples() const;
-    bool usingExtendedDrawBuffers() const;
-
-    virtual GLenum completeness() const;
-
-  protected:
-    GLenum mColorbufferTypes[IMPLEMENTATION_MAX_DRAW_BUFFERS];
-    BindingPointer<Renderbuffer> mColorbufferPointers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
-    GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS];
-    GLenum mReadBufferState;
-
-    GLenum mDepthbufferType;
-    BindingPointer<Renderbuffer> mDepthbufferPointer;
-
-    GLenum mStencilbufferType;
-    BindingPointer<Renderbuffer> mStencilbufferPointer;
-
-    rx::Renderer *mRenderer;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Framebuffer);
-
-    Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const;
-};
-
-class DefaultFramebuffer : public Framebuffer
-{
-  public:
-    DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);
-
-    virtual GLenum completeness() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer);
-};
-
-}
-
-#endif   // LIBGLESV2_FRAMEBUFFER_H_
diff --git a/src/third_party/angle/src/libGLESv2/HandleAllocator.cpp b/src/third_party/angle/src/libGLESv2/HandleAllocator.cpp
deleted file mode 100644
index 37da99a..0000000
--- a/src/third_party/angle/src/libGLESv2/HandleAllocator.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2011 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.
-//
-
-// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
-// to allocate GL handles.
-
-#include "libGLESv2/HandleAllocator.h"
-
-#include "libGLESv2/main.h"
-
-namespace gl
-{
-
-HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1)
-{
-}
-
-HandleAllocator::~HandleAllocator()
-{
-}
-
-void HandleAllocator::setBaseHandle(GLuint value)
-{
-    ASSERT(mBaseValue == mNextValue);
-    mBaseValue = value;
-    mNextValue = value;
-}
-
-GLuint HandleAllocator::allocate()
-{
-    if (mFreeValues.size())
-    {
-        GLuint handle = mFreeValues.back();
-        mFreeValues.pop_back();
-        return handle;
-    }
-    return mNextValue++;
-}
-
-void HandleAllocator::release(GLuint handle)
-{
-    if (handle == mNextValue - 1)
-    {
-        // Don't drop below base value
-        if(mNextValue > mBaseValue)
-        {
-            mNextValue--;
-        }
-    }
-    else
-    {
-        // Only free handles that we own - don't drop below the base value
-        if (handle >= mBaseValue)
-        {
-            mFreeValues.push_back(handle);
-        }
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/HandleAllocator.h b/src/third_party/angle/src/libGLESv2/HandleAllocator.h
deleted file mode 100644
index a92e168..0000000
--- a/src/third_party/angle/src/libGLESv2/HandleAllocator.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright (c) 2002-2011 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.
-//
-
-// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to
-// allocate GL handles.
-
-#ifndef LIBGLESV2_HANDLEALLOCATOR_H_
-#define LIBGLESV2_HANDLEALLOCATOR_H_
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
-#include <vector>
-
-#include "common/angleutils.h"
-
-namespace gl
-{
-
-class HandleAllocator
-{
-  public:
-    HandleAllocator();
-    virtual ~HandleAllocator();
-
-    void setBaseHandle(GLuint value);
-
-    GLuint allocate();
-    void release(GLuint handle);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(HandleAllocator);
-
-    GLuint mBaseValue;
-    GLuint mNextValue;
-    typedef std::vector<GLuint> HandleList;
-    HandleList mFreeValues;
-};
-
-}
-
-#endif   // LIBGLESV2_HANDLEALLOCATOR_H_
diff --git a/src/third_party/angle/src/libGLESv2/Program.cpp b/src/third_party/angle/src/libGLESv2/Program.cpp
deleted file mode 100644
index c38aa5a..0000000
--- a/src/third_party/angle/src/libGLESv2/Program.cpp
+++ /dev/null
@@ -1,525 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// 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"
-
-namespace gl
-{
-const char * const g_fakepath = "C:\\fakepath";
-
-AttributeBindings::AttributeBindings()
-{
-}
-
-AttributeBindings::~AttributeBindings()
-{
-}
-
-InfoLog::InfoLog() : mInfoLog(NULL)
-{
-}
-
-InfoLog::~InfoLog()
-{
-    delete[] mInfoLog;
-}
-
-
-int InfoLog::getLength() const
-{
-    if (!mInfoLog)
-    {
-        return 0;
-    }
-    else
-    {
-       return strlen(mInfoLog) + 1;
-    }
-}
-
-void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
-{
-    int index = 0;
-
-    if (bufSize > 0)
-    {
-        if (mInfoLog)
-        {
-            index = std::min(bufSize - 1, (int)strlen(mInfoLog));
-            memcpy(infoLog, mInfoLog, index);
-        }
-
-        infoLog[index] = '\0';
-    }
-
-    if (length)
-    {
-        *length = index;
-    }
-}
-
-// append a santized message to the program info log.
-// The D3D compiler includes a fake file path in some of the warning or error 
-// messages, so lets remove all occurrences of this fake file path from the log.
-void InfoLog::appendSanitized(const char *message)
-{
-    std::string msg(message);
-
-    size_t found;
-    do
-    {
-        found = msg.find(g_fakepath);
-        if (found != std::string::npos)
-        {
-            msg.erase(found, strlen(g_fakepath));
-        }
-    }
-    while (found != std::string::npos);
-
-    append("%s", msg.c_str());
-}
-
-void InfoLog::append(const char *format, ...)
-{
-    if (!format)
-    {
-        return;
-    }
-
-    char info[1024];
-
-    va_list vararg;
-    va_start(vararg, format);
-    vsnprintf(info, sizeof(info), format, vararg);
-    va_end(vararg);
-
-    size_t infoLength = strlen(info);
-
-    if (!mInfoLog)
-    {
-        mInfoLog = new char[infoLength + 2];
-        strcpy(mInfoLog, info);
-        strcpy(mInfoLog + infoLength, "\n");
-    }
-    else
-    {
-        size_t logLength = strlen(mInfoLog);
-        char *newLog = new char[logLength + infoLength + 2];
-        strcpy(newLog, mInfoLog);
-        strcpy(newLog + logLength, info);
-        strcpy(newLog + logLength + infoLength, "\n");
-
-        delete[] mInfoLog;
-        mInfoLog = newLog;
-    }
-}
-
-void InfoLog::reset()
-{
-    if (mInfoLog)
-    {
-        delete [] mInfoLog;
-        mInfoLog = NULL;
-    }
-}
-
-Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
-{
-    mFragmentShader = NULL;
-    mVertexShader = NULL;
-    mProgramBinary.set(NULL);
-    mDeleteStatus = false;
-    mLinked = false;
-    mRefCount = 0;
-    mRenderer = renderer;
-}
-
-Program::~Program()
-{
-    unlink(true);
-
-    if (mVertexShader != NULL)
-    {
-        mVertexShader->release();
-    }
-
-    if (mFragmentShader != NULL)
-    {
-        mFragmentShader->release();
-    }
-}
-
-bool Program::attachShader(Shader *shader)
-{
-    if (shader->getType() == GL_VERTEX_SHADER)
-    {
-        if (mVertexShader)
-        {
-            return false;
-        }
-
-        mVertexShader = (VertexShader*)shader;
-        mVertexShader->addRef();
-    }
-    else if (shader->getType() == GL_FRAGMENT_SHADER)
-    {
-        if (mFragmentShader)
-        {
-            return false;
-        }
-
-        mFragmentShader = (FragmentShader*)shader;
-        mFragmentShader->addRef();
-    }
-    else UNREACHABLE();
-
-    return true;
-}
-
-bool Program::detachShader(Shader *shader)
-{
-    if (shader->getType() == GL_VERTEX_SHADER)
-    {
-        if (mVertexShader != shader)
-        {
-            return false;
-        }
-
-        mVertexShader->release();
-        mVertexShader = NULL;
-    }
-    else if (shader->getType() == GL_FRAGMENT_SHADER)
-    {
-        if (mFragmentShader != shader)
-        {
-            return false;
-        }
-
-        mFragmentShader->release();
-        mFragmentShader = NULL;
-    }
-    else UNREACHABLE();
-
-    return true;
-}
-
-int Program::getAttachedShadersCount() const
-{
-    return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
-}
-
-void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
-{
-    if (index < MAX_VERTEX_ATTRIBS)
-    {
-        for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
-        {
-            mAttributeBinding[i].erase(name);
-        }
-
-        mAttributeBinding[index].insert(name);
-    }
-}
-
-void Program::bindAttributeLocation(GLuint index, const char *name)
-{
-    mAttributeBindings.bindAttributeLocation(index, name);
-}
-
-// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
-// compiling them into binaries, determining the attribute mappings, and collecting
-// a list of uniforms
-bool Program::link()
-{
-    unlink(false);
-
-    mInfoLog.reset();
-
-    mProgramBinary.set(new ProgramBinary(mRenderer));
-    mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader);
-
-    return mLinked;
-}
-
-int AttributeBindings::getAttributeBinding(const std::string &name) const
-{
-    for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
-    {
-        if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
-        {
-            return location;
-        }
-    }
-
-    return -1;
-}
-
-// Returns the program object to an unlinked state, before re-linking, or at destruction
-void Program::unlink(bool destroy)
-{
-    if (destroy)   // Object being destructed
-    {
-        if (mFragmentShader)
-        {
-            mFragmentShader->release();
-            mFragmentShader = NULL;
-        }
-
-        if (mVertexShader)
-        {
-            mVertexShader->release();
-            mVertexShader = NULL;
-        }
-    }
-
-    mProgramBinary.set(NULL);
-    mLinked = false;
-}
-
-bool Program::isLinked()
-{
-    return mLinked;
-}
-
-ProgramBinary* Program::getProgramBinary()
-{
-    return mProgramBinary.get();
-}
-
-bool Program::setProgramBinary(const void *binary, GLsizei length)
-{
-    unlink(false);
-
-    mInfoLog.reset();
-
-    mProgramBinary.set(new ProgramBinary(mRenderer));
-    mLinked = mProgramBinary->load(mInfoLog, binary, length);
-    if (!mLinked)
-    {
-        mProgramBinary.set(NULL);
-    }
-
-    return mLinked;
-}
-
-void Program::release()
-{
-    mRefCount--;
-
-    if (mRefCount == 0 && mDeleteStatus)
-    {
-        mResourceManager->deleteProgram(mHandle);
-    }
-}
-
-void Program::addRef()
-{
-    mRefCount++;
-}
-
-unsigned int Program::getRefCount() const
-{
-    return mRefCount;
-}
-
-GLint Program::getProgramBinaryLength() const
-{
-    ProgramBinary *programBinary = mProgramBinary.get();
-    if (programBinary)
-    {
-        return programBinary->getLength();
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-int Program::getInfoLogLength() const
-{
-    return mInfoLog.getLength();
-}
-
-void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
-{
-    return mInfoLog.getLog(bufSize, length, infoLog);
-}
-
-void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
-{
-    int total = 0;
-
-    if (mVertexShader)
-    {
-        if (total < maxCount)
-        {
-            shaders[total] = mVertexShader->getHandle();
-        }
-
-        total++;
-    }
-
-    if (mFragmentShader)
-    {
-        if (total < maxCount)
-        {
-            shaders[total] = mFragmentShader->getHandle();
-        }
-
-        total++;
-    }
-
-    if (count)
-    {
-        *count = total;
-    }
-}
-
-void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
-{
-    ProgramBinary *programBinary = getProgramBinary();
-    if (programBinary)
-    {
-        programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
-    }
-    else
-    {
-        if (bufsize > 0)
-        {
-            name[0] = '\0';
-        }
-        
-        if (length)
-        {
-            *length = 0;
-        }
-
-        *type = GL_NONE;
-        *size = 1;
-    }
-}
-
-GLint Program::getActiveAttributeCount()
-{
-    ProgramBinary *programBinary = getProgramBinary();
-    if (programBinary)
-    {
-        return programBinary->getActiveAttributeCount();
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-GLint Program::getActiveAttributeMaxLength()
-{
-    ProgramBinary *programBinary = getProgramBinary();
-    if (programBinary)
-    {
-        return programBinary->getActiveAttributeMaxLength();
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
-{
-    ProgramBinary *programBinary = getProgramBinary();
-    if (programBinary)
-    {
-        return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
-    }
-    else
-    {
-        if (bufsize > 0)
-        {
-            name[0] = '\0';
-        }
-
-        if (length)
-        {
-            *length = 0;
-        }
-
-        *size = 0;
-        *type = GL_NONE;
-    }
-}
-
-GLint Program::getActiveUniformCount()
-{
-    ProgramBinary *programBinary = getProgramBinary();
-    if (programBinary)
-    {
-        return programBinary->getActiveUniformCount();
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-GLint Program::getActiveUniformMaxLength()
-{
-    ProgramBinary *programBinary = getProgramBinary();
-    if (programBinary)
-    {
-        return programBinary->getActiveUniformMaxLength();
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-void Program::flagForDeletion()
-{
-    mDeleteStatus = true;
-}
-
-bool Program::isFlaggedForDeletion() const
-{
-    return mDeleteStatus;
-}
-
-void Program::validate()
-{
-    mInfoLog.reset();
-
-    ProgramBinary *programBinary = getProgramBinary();
-    if (isLinked() && programBinary)
-    {
-        programBinary->validate(mInfoLog);
-    }
-    else
-    {
-        mInfoLog.append("Program has not been successfully linked.");
-    }
-}
-
-bool Program::isValidated() const
-{
-    ProgramBinary *programBinary = mProgramBinary.get();
-    if (programBinary)
-    {
-        return programBinary->isValidated();
-    }
-    else
-    {
-        return false;
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/Program.h b/src/third_party/angle/src/libGLESv2/Program.h
deleted file mode 100644
index a9db834..0000000
--- a/src/third_party/angle/src/libGLESv2/Program.h
+++ /dev/null
@@ -1,130 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Program.h: Defines the gl::Program class. Implements GL program objects
-// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
-
-#ifndef LIBGLESV2_PROGRAM_H_
-#define LIBGLESV2_PROGRAM_H_
-
-#include <string>
-#include <set>
-
-#include "common/angleutils.h"
-#include "common/RefCountObject.h"
-#include "libGLESv2/Constants.h"
-
-namespace rx
-{
-class Renderer;
-}
-
-namespace gl
-{
-class ResourceManager;
-class FragmentShader;
-class VertexShader;
-class ProgramBinary;
-class Shader;
-
-extern const char * const g_fakepath;
-
-class AttributeBindings
-{
-  public:
-    AttributeBindings();
-    ~AttributeBindings();
-
-    void bindAttributeLocation(GLuint index, const char *name);
-    int getAttributeBinding(const std::string &name) const;
-
-  private:
-    std::set<std::string> mAttributeBinding[MAX_VERTEX_ATTRIBS];
-};
-
-class InfoLog
-{
-  public:
-    InfoLog();
-    ~InfoLog();
-
-    int getLength() const;
-    void getLog(GLsizei bufSize, GLsizei *length, char *infoLog);
-
-    void appendSanitized(const char *message);
-    void append(const char *info, ...);
-    void reset();
-  private:
-    DISALLOW_COPY_AND_ASSIGN(InfoLog);
-    char *mInfoLog;
-};
-
-class Program
-{
-  public:
-    Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle);
-
-    ~Program();
-
-    bool attachShader(Shader *shader);
-    bool detachShader(Shader *shader);
-    int getAttachedShadersCount() const;
-
-    void bindAttributeLocation(GLuint index, const char *name);
-
-    bool link();
-    bool isLinked();
-    bool setProgramBinary(const void *binary, GLsizei length);
-    ProgramBinary *getProgramBinary();
-
-    int getInfoLogLength() const;
-    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
-    void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
-
-    void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
-    GLint getActiveAttributeCount();
-    GLint getActiveAttributeMaxLength();
-
-    void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
-    GLint getActiveUniformCount();
-    GLint getActiveUniformMaxLength();
-
-    void addRef();
-    void release();
-    unsigned int getRefCount() const;
-    void flagForDeletion();
-    bool isFlaggedForDeletion() const;
-
-    void validate();
-    bool isValidated() const;
-
-    GLint getProgramBinaryLength() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Program);
-
-    void unlink(bool destroy = false);
-
-    FragmentShader *mFragmentShader;
-    VertexShader *mVertexShader;
-
-    AttributeBindings mAttributeBindings;
-
-    BindingPointer<ProgramBinary> mProgramBinary;
-    bool mLinked;
-    bool mDeleteStatus;   // Flag to indicate that the program can be deleted when no longer in use
-
-    unsigned int mRefCount;
-
-    ResourceManager *mResourceManager;
-    rx::Renderer *mRenderer;
-    const GLuint mHandle;
-
-    InfoLog mInfoLog;
-};
-}
-
-#endif   // LIBGLESV2_PROGRAM_H_
diff --git a/src/third_party/angle/src/libGLESv2/ProgramBinary.cpp b/src/third_party/angle/src/libGLESv2/ProgramBinary.cpp
deleted file mode 100644
index 135facd..0000000
--- a/src/third_party/angle/src/libGLESv2/ProgramBinary.cpp
+++ /dev/null
@@ -1,2620 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// 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/renderer/ShaderExecutable.h"
-
-#include "common/debug.h"
-#include "common/version.h"
-#include "utilities.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/VertexDataManager.h"
-
-#undef near
-#undef far
-
-namespace gl
-{
-std::string str(int i)
-{
-    char buffer[20];
-    snprintf(buffer, sizeof(buffer), "%d", i);
-    return buffer;
-}
-
-UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) 
-    : name(name), element(element), index(index)
-{
-}
-
-unsigned int ProgramBinary::mCurrentSerial = 1;
-
-ProgramBinary::ProgramBinary(rx::Renderer *renderer) : mRenderer(renderer), RefCountObject(0), mSerial(issueSerial())
-{
-    mPixelExecutable = NULL;
-    mVertexExecutable = NULL;
-    mGeometryExecutable = NULL;
-
-    mValidated = false;
-
-    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;
-    }
-
-    mUsedVertexSamplerRange = 0;
-    mUsedPixelSamplerRange = 0;
-    mUsesPointSize = false;
-}
-
-ProgramBinary::~ProgramBinary()
-{
-    delete mPixelExecutable;
-    mPixelExecutable = NULL;
-
-    delete mVertexExecutable;
-    mVertexExecutable = NULL;
-
-    delete mGeometryExecutable;
-    mGeometryExecutable = NULL;
-
-    while (!mUniforms.empty())
-    {
-        delete mUniforms.back();
-        mUniforms.pop_back();
-    }
-}
-
-unsigned int ProgramBinary::getSerial() const
-{
-    return mSerial;
-}
-
-unsigned int ProgramBinary::issueSerial()
-{
-    return mCurrentSerial++;
-}
-
-rx::ShaderExecutable *ProgramBinary::getPixelExecutable()
-{
-    return mPixelExecutable;
-}
-
-rx::ShaderExecutable *ProgramBinary::getVertexExecutable()
-{
-    return mVertexExecutable;
-}
-
-rx::ShaderExecutable *ProgramBinary::getGeometryExecutable()
-{
-    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))
-            {
-                return index;
-            }
-        }
-    }
-
-    return -1;
-}
-
-int ProgramBinary::getSemanticIndex(int attributeIndex)
-{
-    ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
-    
-    return mSemanticIndex[attributeIndex];
-}
-
-// Returns one more than the highest sampler index used.
-GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
-{
-    switch (type)
-    {
-      case SAMPLER_PIXEL:
-        return mUsedPixelSamplerRange;
-      case SAMPLER_VERTEX:
-        return mUsedVertexSamplerRange;
-      default:
-        UNREACHABLE();
-        return 0;
-    }
-}
-
-bool ProgramBinary::usesPointSize() const
-{
-    return mUsesPointSize;
-}
-
-bool ProgramBinary::usesPointSpriteEmulation() const
-{
-    return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
-}
-
-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)
-{
-    GLint logicalTextureUnit = -1;
-
-    switch (type)
-    {
-      case SAMPLER_PIXEL:
-        ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
-
-        if (mSamplersPS[samplerIndex].active)
-        {
-            logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
-        }
-        break;
-      case SAMPLER_VERTEX:
-        ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
-
-        if (mSamplersVS[samplerIndex].active)
-        {
-            logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
-        }
-        break;
-      default: UNREACHABLE();
-    }
-
-    if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits())
-    {
-        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)
-{
-    switch (type)
-    {
-      case SAMPLER_PIXEL:
-        ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
-        ASSERT(mSamplersPS[samplerIndex].active);
-        return mSamplersPS[samplerIndex].textureType;
-      case SAMPLER_VERTEX:
-        ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
-        ASSERT(mSamplersVS[samplerIndex].active);
-        return mSamplersVS[samplerIndex].textureType;
-      default: UNREACHABLE();
-    }
-
-    return TEXTURE_2D;
-}
-
-GLint ProgramBinary::getUniformLocation(std::string name)
-{
-    unsigned int subscript = 0;
-
-    // Strip any trailing array operator and retrieve the subscript
-    size_t open = name.find_last_of('[');
-    size_t close = name.find_last_of(']');
-    if (open != std::string::npos && close == name.length() - 1)
-    {
-        subscript = atoi(name.substr(open + 1).c_str());
-        name.erase(open);
-    }
-
-    unsigned int numUniforms = mUniformIndex.size();
-    for (unsigned int location = 0; location < numUniforms; location++)
-    {
-        if (mUniformIndex[location].name == name &&
-            mUniformIndex[location].element == subscript)
-        {
-            return location;
-        }
-    }
-
-    return -1;
-}
-
-bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == GL_FLOAT)
-    {
-        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            target[0] = v[0];
-            target[1] = 0;
-            target[2] = 0;
-            target[3] = 0;
-            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++)
-        {
-            boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams[1] = GL_FALSE;
-            boolParams[2] = GL_FALSE;
-            boolParams[3] = GL_FALSE;
-            boolParams += 4;
-            v += 1;
-        }
-    }
-    else
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == GL_FLOAT_VEC2)
-    {
-        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            target[0] = v[0];
-            target[1] = v[1];
-            target[2] = 0;
-            target[3] = 0;
-            target += 4;
-            v += 2;
-        }
-    }
-    else if (targetUniform->type == GL_BOOL_VEC2)
-    {
-        GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams[2] = GL_FALSE;
-            boolParams[3] = GL_FALSE;
-            boolParams += 4;
-            v += 2;
-        }
-    }
-    else 
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == GL_FLOAT_VEC3)
-    {
-        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            target[0] = v[0];
-            target[1] = v[1];
-            target[2] = v[2];
-            target[3] = 0;
-            target += 4;
-            v += 3;
-        }
-    }
-    else if (targetUniform->type == GL_BOOL_VEC3)
-    {
-        GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams[3] = GL_FALSE;
-            boolParams += 4;
-            v += 3;
-        }
-    }
-    else 
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == GL_FLOAT_VEC4)
-    {
-        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            target[0] = v[0];
-            target[1] = v[1];
-            target[2] = v[2];
-            target[3] = v[3];
-            target += 4;
-            v += 4;
-        }
-    }
-    else if (targetUniform->type == GL_BOOL_VEC4)
-    {
-        GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams[3] = (v[3] == 0.0f) ? GL_FALSE : GL_TRUE;
-            boolParams += 4;
-            v += 4;
-        }
-    }
-    else 
-    {
-        return false;
-    }
-
-    return true;
-}
-
-template<typename T, int targetWidth, int targetHeight, int srcWidth, int srcHeight>
-void transposeMatrix(T *target, const GLfloat *value)
-{
-    int copyWidth = std::min(targetWidth, srcWidth);
-    int copyHeight = std::min(targetHeight, srcHeight);
-
-    for (int x = 0; x < copyWidth; x++)
-    {
-        for (int y = 0; y < copyHeight; y++)
-        {
-            target[x * targetWidth + y] = (T)value[y * srcWidth + x];
-        }
-    }
-    // clear unfilled right side
-    for (int y = 0; y < copyHeight; y++)
-    {
-        for (int x = srcWidth; x < targetWidth; x++)
-        {
-            target[y * targetWidth + x] = (T)0;
-        }
-    }
-    // clear unfilled bottom.
-    for (int y = srcHeight; y < targetHeight; y++)
-    {
-        for (int x = 0; x < targetWidth; x++)
-        {
-            target[y * targetWidth + x] = (T)0;
-        }
-    }
-}
-
-bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    if (targetUniform->type != GL_FLOAT_MAT2)
-    {
-        return false;
-    }
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-    GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8;
-
-    for (int i = 0; i < count; i++)
-    {
-        transposeMatrix<GLfloat,4,2,2,2>(target, value);
-        target += 8;
-        value += 4;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    if (targetUniform->type != GL_FLOAT_MAT3)
-    {
-        return false;
-    }
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-    GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12;
-
-    for (int i = 0; i < count; i++)
-    {
-        transposeMatrix<GLfloat,4,3,3,3>(target, value);
-        target += 12;
-        value += 9;
-    }
-
-    return true;
-}
-
-
-bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    if (targetUniform->type != GL_FLOAT_MAT4)
-    {
-        return false;
-    }
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-    GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16);
-
-    for (int i = 0; i < count; i++)
-    {
-        transposeMatrix<GLfloat,4,4,4,4>(target, value);
-        target += 16;
-        value += 16;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == GL_INT ||
-        targetUniform->type == GL_SAMPLER_2D ||
-        targetUniform->type == GL_SAMPLER_CUBE)
-    {
-        GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            target[0] = v[0];
-            target[1] = 0;
-            target[2] = 0;
-            target[3] = 0;
-            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++)
-        {
-            boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams[1] = GL_FALSE;
-            boolParams[2] = GL_FALSE;
-            boolParams[3] = GL_FALSE;
-            boolParams += 4;
-            v += 1;
-        }
-    }
-    else
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == GL_INT_VEC2)
-    {
-        GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            target[0] = v[0];
-            target[1] = v[1];
-            target[2] = 0;
-            target[3] = 0;
-            target += 4;
-            v += 2;
-        }
-    }
-    else if (targetUniform->type == GL_BOOL_VEC2)
-    {
-        GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams[2] = GL_FALSE;
-            boolParams[3] = GL_FALSE;
-            boolParams += 4;
-            v += 2;
-        }
-    }
-    else
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == GL_INT_VEC3)
-    {
-        GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            target[0] = v[0];
-            target[1] = v[1];
-            target[2] = v[2];
-            target[3] = 0;
-            target += 4;
-            v += 3;
-        }
-    }
-    else if (targetUniform->type == GL_BOOL_VEC3)
-    {
-        GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams[3] = GL_FALSE;
-            boolParams += 4;
-            v += 3;
-        }
-    }
-    else
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-    targetUniform->dirty = true;
-
-    int elementCount = targetUniform->elementCount();
-
-    if (elementCount == 1 && count > 1)
-        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == GL_INT_VEC4)
-    {
-        GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            target[0] = v[0];
-            target[1] = v[1];
-            target[2] = v[2];
-            target[3] = v[3];
-            target += 4;
-            v += 4;
-        }
-    }
-    else if (targetUniform->type == GL_BOOL_VEC4)
-    {
-        GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams[3] = (v[3] == 0) ? GL_FALSE : GL_TRUE;
-            boolParams += 4;
-            v += 4;
-        }
-    }
-    else
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    // sized queries -- ensure the provided buffer is large enough
-    if (bufSize)
-    {
-        int requiredBytes = UniformExternalSize(targetUniform->type);
-        if (*bufSize < requiredBytes)
-        {
-            return false;
-        }
-    }
-
-    switch (targetUniform->type)
-    {
-      case GL_FLOAT_MAT2:
-        transposeMatrix<GLfloat,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
-        break;
-      case GL_FLOAT_MAT3:
-        transposeMatrix<GLfloat,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
-        break;
-      case GL_FLOAT_MAT4:
-        transposeMatrix<GLfloat,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
-        break;
-      default:
-        {
-            unsigned int size = UniformComponentCount(targetUniform->type);
-
-            switch (UniformComponentType(targetUniform->type))
-            {
-              case GL_BOOL:
-                {
-                    GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-                    for (unsigned int i = 0; i < size; i++)
-                    {
-                        params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
-                    }
-                }
-                break;
-              case GL_FLOAT:
-                memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLfloat),
-                       size * sizeof(GLfloat));
-                break;
-              case GL_INT:
-                {
-                    GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-                    for (unsigned int i = 0; i < size; i++)
-                    {
-                        params[i] = (float)intParams[i];
-                    }
-                }
-                break;
-              default: UNREACHABLE();
-            }
-        }
-    }
-
-    return true;
-}
-
-bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
-{
-    if (location < 0 || location >= (int)mUniformIndex.size())
-    {
-        return false;
-    }
-
-    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    // sized queries -- ensure the provided buffer is large enough
-    if (bufSize)
-    {
-        int requiredBytes = UniformExternalSize(targetUniform->type);
-        if (*bufSize < requiredBytes)
-        {
-            return false;
-        }
-    }
-
-    switch (targetUniform->type)
-    {
-      case GL_FLOAT_MAT2:
-        transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
-        break;
-      case GL_FLOAT_MAT3:
-        transposeMatrix<GLint,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
-        break;
-      case GL_FLOAT_MAT4:
-        transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
-        break;
-      default:
-        {
-            unsigned int size = VariableColumnCount(targetUniform->type);
-
-            switch (UniformComponentType(targetUniform->type))
-            {
-              case GL_BOOL:
-                {
-                    GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-                    for (unsigned int i = 0; i < size; i++)
-                    {
-                        params[i] = boolParams[i];
-                    }
-                }
-                break;
-              case GL_FLOAT:
-                {
-                    GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
-
-                    for (unsigned int i = 0; i < size; i++)
-                    {
-                        params[i] = (GLint)floatParams[i];
-                    }
-                }
-                break;
-              case GL_INT:
-                memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLint),
-                    size * sizeof(GLint));
-                break;
-              default: UNREACHABLE();
-            }
-        }
-    }
-
-    return true;
-}
-
-void ProgramBinary::dirtyAllUniforms()
-{
-    unsigned int numUniforms = mUniforms.size();
-    for (unsigned int index = 0; index < numUniforms; index++)
-    {
-        mUniforms[index]->dirty = true;
-    }
-}
-
-// Applies all the uniforms set for this program object to the renderer
-void ProgramBinary::applyUniforms()
-{
-    // Retrieve sampler uniform values
-    for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub)
-    {
-        Uniform *targetUniform = *ub;
-
-        if (targetUniform->dirty)
-        {
-            if (targetUniform->type == GL_SAMPLER_2D || 
-                targetUniform->type == GL_SAMPLER_CUBE)
-            {
-                int count = targetUniform->elementCount();
-                GLint (*v)[4] = (GLint(*)[4])targetUniform->data;
-
-                if (targetUniform->psRegisterIndex >= 0)
-                {
-                    unsigned int firstIndex = targetUniform->psRegisterIndex;
-
-                    for (int i = 0; i < count; i++)
-                    {
-                        unsigned int samplerIndex = firstIndex + i;
-
-                        if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
-                        {
-                            ASSERT(mSamplersPS[samplerIndex].active);
-                            mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
-                        }
-                    }
-                }
-
-                if (targetUniform->vsRegisterIndex >= 0)
-                {
-                    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)
-                        {
-                            ASSERT(mSamplersVS[samplerIndex].active);
-                            mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    mRenderer->applyUniforms(this, &mUniforms);
-}
-
-// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
-// Returns the number of used varying registers, or -1 if unsuccesful
-int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader)
-{
-    const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
-
-    fragmentShader->resetVaryingsRegisterAssignment();
-
-    for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
-    {
-        int n = VariableRowCount(varying->type) * varying->size;
-        int m = VariableColumnCount(varying->type);
-        bool success = false;
-
-        if (m == 2 || m == 3 || m == 4)
-        {
-            for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
-            {
-                bool available = true;
-
-                for (int y = 0; y < n && available; y++)
-                {
-                    for (int x = 0; x < m && available; x++)
-                    {
-                        if (packing[r + y][x])
-                        {
-                            available = false;
-                        }
-                    }
-                }
-
-                if (available)
-                {
-                    varying->reg = r;
-                    varying->col = 0;
-
-                    for (int y = 0; y < n; y++)
-                    {
-                        for (int x = 0; x < m; x++)
-                        {
-                            packing[r + y][x] = &*varying;
-                        }
-                    }
-
-                    success = true;
-                }
-            }
-
-            if (!success && m == 2)
-            {
-                for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
-                {
-                    bool available = true;
-
-                    for (int y = 0; y < n && available; y++)
-                    {
-                        for (int x = 2; x < 4 && available; x++)
-                        {
-                            if (packing[r + y][x])
-                            {
-                                available = false;
-                            }
-                        }
-                    }
-
-                    if (available)
-                    {
-                        varying->reg = r;
-                        varying->col = 2;
-
-                        for (int y = 0; y < n; y++)
-                        {
-                            for (int x = 2; x < 4; x++)
-                            {
-                                packing[r + y][x] = &*varying;
-                            }
-                        }
-
-                        success = true;
-                    }
-                }
-            }
-        }
-        else if (m == 1)
-        {
-            int space[4] = {0};
-
-            for (int y = 0; y < maxVaryingVectors; y++)
-            {
-                for (int x = 0; x < 4; x++)
-                {
-                    space[x] += packing[y][x] ? 0 : 1;
-                }
-            }
-
-            int column = 0;
-
-            for (int x = 0; x < 4; x++)
-            {
-                if (space[x] >= n && space[x] < space[column])
-                {
-                    column = x;
-                }
-            }
-
-            if (space[column] >= n)
-            {
-                for (int r = 0; r < maxVaryingVectors; r++)
-                {
-                    if (!packing[r][column])
-                    {
-                        varying->reg = r;
-
-                        for (int y = r; y < r + n; y++)
-                        {
-                            packing[y][column] = &*varying;
-                        }
-
-                        break;
-                    }
-                }
-
-                varying->col = column;
-
-                success = true;
-            }
-        }
-        else UNREACHABLE();
-
-        if (!success)
-        {
-            infoLog.append("Could not pack varying %s", varying->name.c_str());
-
-            return -1;
-        }
-    }
-
-    // Return the number of used registers
-    int registers = 0;
-
-    for (int r = 0; r < maxVaryingVectors; r++)
-    {
-        if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
-        {
-            registers++;
-        }
-    }
-
-    return registers;
-}
-
-bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4],
-                                 std::string& pixelHLSL, std::string& vertexHLSL,
-                                 FragmentShader *fragmentShader, VertexShader *vertexShader)
-{
-    if (pixelHLSL.empty() || vertexHLSL.empty())
-    {
-        return false;
-    }
-
-    bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
-    bool usesFragColor = fragmentShader->mUsesFragColor;
-    bool usesFragData = fragmentShader->mUsesFragData;
-    if (usesFragColor && usesFragData)
-    {
-        infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
-        return false;
-    }
-
-    // Write the HLSL input/output declarations
-    const int shaderModel = mRenderer->getMajorShaderModel();
-    const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
-
-    const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
-
-    // The output color is broadcast to all enabled draw buffers when writing to gl_FragColor 
-    const bool broadcast = fragmentShader->mUsesFragColor;
-    const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
-
-    if (registersNeeded > maxVaryingVectors)
-    {
-        infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
-
-        return false;
-    }
-
-    vertexShader->resetVaryingsRegisterAssignment();
-
-    for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++)
-    {
-        bool matched = false;
-
-        for (VaryingList::iterator output = vertexShader->mVaryings.begin(); output != vertexShader->mVaryings.end(); output++)
-        {
-            if (output->name == input->name)
-            {
-                if (output->type != input->type || output->size != input->size)
-                {
-                    infoLog.append("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
-
-                    return false;
-                }
-
-                output->reg = input->reg;
-                output->col = input->col;
-
-                matched = true;
-                break;
-            }
-        }
-
-        if (!matched)
-        {
-            infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
-
-            return false;
-        }
-    }
-
-    mUsesPointSize = vertexShader->mUsesPointSize;
-    std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
-    std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
-    std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
-    std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
-
-    // special varyings that use reserved registers
-    int reservedRegisterIndex = registers;
-    std::string fragCoordSemantic;
-    std::string pointCoordSemantic;
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
-    }
-
-    if (fragmentShader->mUsesPointCoord)
-    {
-        // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
-        // In DX11 we compute this in the GS.
-        if (shaderModel == 3)
-        {
-            pointCoordSemantic = "TEXCOORD0";
-        }
-        else if (shaderModel >= 4)
-        {
-            pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); 
-        }
-    }
-
-    vertexHLSL += "struct VS_INPUT\n"
-                  "{\n";
-
-    int semanticIndex = 0;
-    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
-    {
-        switch (attribute->type)
-        {
-          case GL_FLOAT:      vertexHLSL += "    float ";    break;
-          case GL_FLOAT_VEC2: vertexHLSL += "    float2 ";   break;
-          case GL_FLOAT_VEC3: vertexHLSL += "    float3 ";   break;
-          case GL_FLOAT_VEC4: vertexHLSL += "    float4 ";   break;
-          case GL_FLOAT_MAT2: vertexHLSL += "    float2x2 "; break;
-          case GL_FLOAT_MAT3: vertexHLSL += "    float3x3 "; break;
-          case GL_FLOAT_MAT4: vertexHLSL += "    float4x4 "; break;
-          default:  UNREACHABLE();
-        }
-
-        vertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
-
-        semanticIndex += VariableRowCount(attribute->type);
-    }
-
-    vertexHLSL += "};\n"
-                  "\n"
-                  "struct VS_OUTPUT\n"
-                  "{\n";
-
-    if (shaderModel < 4)
-    {
-        vertexHLSL += "    float4 gl_Position : " + positionSemantic + ";\n";
-    }
-
-    for (int r = 0; r < registers; r++)
-    {
-        int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
-
-        vertexHLSL += "    float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
-    }
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        vertexHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
-    }
-
-    if (vertexShader->mUsesPointSize && shaderModel >= 3)
-    {
-        vertexHLSL += "    float gl_PointSize : PSIZE;\n";
-    }
-
-    if (shaderModel >= 4)
-    {
-        vertexHLSL += "    float4 gl_Position : " + positionSemantic + ";\n";
-    }
-
-    vertexHLSL += "};\n"
-                  "\n"
-                  "VS_OUTPUT main(VS_INPUT input)\n"
-                  "{\n";
-
-    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
-    {
-        vertexHLSL += "    " + decorateAttribute(attribute->name) + " = ";
-
-        if (VariableRowCount(attribute->type) > 1)   // Matrix
-        {
-            vertexHLSL += "transpose";
-        }
-
-        vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
-    }
-
-    if (shaderModel >= 4)
-    {
-        vertexHLSL += "\n"
-                      "    gl_main();\n"
-                      "\n"
-                      "    VS_OUTPUT output;\n"
-                      "    output.gl_Position.x = gl_Position.x;\n"
-                      "    output.gl_Position.y = -gl_Position.y;\n"
-                      "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
-                      "    output.gl_Position.w = gl_Position.w;\n";
-    }
-    else
-    {
-        vertexHLSL += "\n"
-                      "    gl_main();\n"
-                      "\n"
-                      "    VS_OUTPUT output;\n"
-                      "    output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
-                      "    output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
-                      "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
-                      "    output.gl_Position.w = gl_Position.w;\n";
-    }
-
-    if (vertexShader->mUsesPointSize && shaderModel >= 3)
-    {
-        vertexHLSL += "    output.gl_PointSize = gl_PointSize;\n";
-    }
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        vertexHLSL += "    output.gl_FragCoord = gl_Position;\n";
-    }
-
-    for (VaryingList::iterator varying = vertexShader->mVaryings.begin(); varying != vertexShader->mVaryings.end(); varying++)
-    {
-        if (varying->reg >= 0)
-        {
-            for (int i = 0; i < varying->size; i++)
-            {
-                int rows = VariableRowCount(varying->type);
-
-                for (int j = 0; j < rows; j++)
-                {
-                    int r = varying->reg + i * rows + j;
-                    vertexHLSL += "    output.v" + str(r);
-
-                    bool sharedRegister = false;   // Register used by multiple varyings
-                    
-                    for (int x = 0; x < 4; x++)
-                    {
-                        if (packing[r][x] && packing[r][x] != packing[r][0])
-                        {
-                            sharedRegister = true;
-                            break;
-                        }
-                    }
-
-                    if(sharedRegister)
-                    {
-                        vertexHLSL += ".";
-
-                        for (int x = 0; x < 4; x++)
-                        {
-                            if (packing[r][x] == &*varying)
-                            {
-                                switch(x)
-                                {
-                                  case 0: vertexHLSL += "x"; break;
-                                  case 1: vertexHLSL += "y"; break;
-                                  case 2: vertexHLSL += "z"; break;
-                                  case 3: vertexHLSL += "w"; break;
-                                }
-                            }
-                        }
-                    }
-
-                    vertexHLSL += " = " + varying->name;
-                    
-                    if (varying->array)
-                    {
-                        vertexHLSL += "[" + str(i) + "]";
-                    }
-
-                    if (rows > 1)
-                    {
-                        vertexHLSL += "[" + str(j) + "]";
-                    }
-                    
-                    vertexHLSL += ";\n";
-                }
-            }
-        }
-    }
-
-    vertexHLSL += "\n"
-                  "    return output;\n"
-                  "}\n";
-
-    pixelHLSL += "struct PS_INPUT\n"
-                 "{\n";
-    
-    for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
-    {
-        if (varying->reg >= 0)
-        {
-            for (int i = 0; i < varying->size; i++)
-            {
-                int rows = VariableRowCount(varying->type);
-                for (int j = 0; j < rows; j++)
-                {
-                    std::string n = str(varying->reg + i * rows + j);
-                    pixelHLSL += "    float" + str(VariableColumnCount(varying->type)) + " v" + n + " : " + varyingSemantic + n + ";\n";
-                }
-            }
-        }
-        else UNREACHABLE();
-    }
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        pixelHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
-    }
-        
-    if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
-    {
-        pixelHLSL += "    float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
-    }
-
-    // Must consume the PSIZE element if the geometry shader is not active
-    // We won't know if we use a GS until we draw
-    if (vertexShader->mUsesPointSize && shaderModel >= 4)
-    {
-        pixelHLSL += "    float gl_PointSize : PSIZE;\n";
-    }
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        if (shaderModel >= 4)
-        {
-            pixelHLSL += "    float4 dx_VPos : SV_Position;\n";
-        }
-        else if (shaderModel >= 3)
-        {
-            pixelHLSL += "    float2 dx_VPos : VPOS;\n";
-        }
-    }
-
-    pixelHLSL += "};\n"
-                 "\n"
-                 "struct PS_OUTPUT\n"
-                 "{\n";
-
-    for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
-    {
-        pixelHLSL += "    float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
-    }
-
-    if (fragmentShader->mUsesFragDepth)
-    {
-        pixelHLSL += "    float gl_Depth : " + depthSemantic + ";\n";
-    }
-
-    pixelHLSL += "};\n"
-                 "\n";
-
-    if (fragmentShader->mUsesFrontFacing)
-    {
-        if (shaderModel >= 4)
-        {
-            pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
-                         "{\n";
-        }
-        else
-        {
-            pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
-                         "{\n";
-        }
-    }
-    else
-    {
-        pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
-                     "{\n";
-    }
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        pixelHLSL += "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
-        
-        if (shaderModel >= 4)
-        {
-            pixelHLSL += "    gl_FragCoord.x = input.dx_VPos.x;\n"
-                         "    gl_FragCoord.y = input.dx_VPos.y;\n";
-        }
-        else if (shaderModel >= 3)
-        {
-            pixelHLSL += "    gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
-                         "    gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
-        }
-        else
-        {
-            // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
-            pixelHLSL += "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n"
-                         "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n";
-        }
-        
-        pixelHLSL += "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
-                     "    gl_FragCoord.w = rhw;\n";
-    }
-
-    if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
-    {
-        pixelHLSL += "    gl_PointCoord.x = input.gl_PointCoord.x;\n";
-        pixelHLSL += "    gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
-    }
-
-    if (fragmentShader->mUsesFrontFacing)
-    {
-        if (shaderModel <= 3)
-        {
-            pixelHLSL += "    gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
-        }
-        else
-        {
-            pixelHLSL += "    gl_FrontFacing = isFrontFace;\n";
-        }
-    }
-
-    for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
-    {
-        if (varying->reg >= 0)
-        {
-            for (int i = 0; i < varying->size; i++)
-            {
-                int rows = VariableRowCount(varying->type);
-                for (int j = 0; j < rows; j++)
-                {
-                    std::string n = str(varying->reg + i * rows + j);
-                    pixelHLSL += "    " + varying->name;
-
-                    if (varying->array)
-                    {
-                        pixelHLSL += "[" + str(i) + "]";
-                    }
-
-                    if (rows > 1)
-                    {
-                        pixelHLSL += "[" + str(j) + "]";
-                    }
-
-                    switch (VariableColumnCount(varying->type))
-                    {
-                      case 1: pixelHLSL += " = input.v" + n + ".x;\n";   break;
-                      case 2: pixelHLSL += " = input.v" + n + ".xy;\n";  break;
-                      case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
-                      case 4: pixelHLSL += " = input.v" + n + ";\n";     break;
-                      default: UNREACHABLE();
-                    }
-                }
-            }
-        }
-        else UNREACHABLE();
-    }
-
-    pixelHLSL += "\n"
-                 "    gl_main();\n"
-                 "\n"
-                 "    PS_OUTPUT output;\n";
-
-    for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
-    {
-        unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
-
-        pixelHLSL += "    output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n";
-    }
-
-    if (fragmentShader->mUsesFragDepth)
-    {
-        pixelHLSL += "    output.gl_Depth = gl_Depth;\n";
-    }
-
-    pixelHLSL += "\n"
-                 "    return output;\n"
-                 "}\n";
-
-    return true;
-}
-
-bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
-{
-    BinaryInputStream stream(binary, length);
-
-    int format = 0;
-    stream.read(&format);
-    if (format != GL_PROGRAM_BINARY_ANGLE)
-    {
-        infoLog.append("Invalid program binary format.");
-        return false;
-    }
-
-    int version = 0;
-    stream.read(&version);
-    if (version != VERSION_DWORD)
-    {
-        infoLog.append("Invalid program binary version.");
-        return false;
-    }
-
-    int compileFlags = 0;
-    stream.read(&compileFlags);
-    if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
-    {
-        infoLog.append("Mismatched compilation flags.");
-        return false;
-    }
-
-    for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
-    {
-        stream.read(&mLinkedAttribute[i].type);
-        std::string name;
-        stream.read(&name);
-        mLinkedAttribute[i].name = name;
-        stream.read(&mSemanticIndex[i]);
-    }
-
-    for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
-    {
-        stream.read(&mSamplersPS[i].active);
-        stream.read(&mSamplersPS[i].logicalTextureUnit);
-        
-        int textureType;
-        stream.read(&textureType);
-        mSamplersPS[i].textureType = (TextureType) textureType;
-    }
-
-    for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
-    {
-        stream.read(&mSamplersVS[i].active);
-        stream.read(&mSamplersVS[i].logicalTextureUnit);
-        
-        int textureType;
-        stream.read(&textureType);
-        mSamplersVS[i].textureType = (TextureType) textureType;
-    }
-
-    stream.read(&mUsedVertexSamplerRange);
-    stream.read(&mUsedPixelSamplerRange);
-    stream.read(&mUsesPointSize);
-
-    size_t size;
-    stream.read(&size);
-    if (stream.error())
-    {
-        infoLog.append("Invalid program binary.");
-        return false;
-    }
-
-    mUniforms.resize(size);
-    for (unsigned int i = 0; i < size; ++i)
-    {
-        GLenum type;
-        GLenum precision;
-        std::string name;
-        unsigned int arraySize;
-
-        stream.read(&type);
-        stream.read(&precision);
-        stream.read(&name);
-        stream.read(&arraySize);
-
-        mUniforms[i] = new Uniform(type, precision, name, arraySize);
-        
-        stream.read(&mUniforms[i]->psRegisterIndex);
-        stream.read(&mUniforms[i]->vsRegisterIndex);
-        stream.read(&mUniforms[i]->registerCount);
-    }
-
-    stream.read(&size);
-    if (stream.error())
-    {
-        infoLog.append("Invalid program binary.");
-        return false;
-    }
-
-    mUniformIndex.resize(size);
-    for (unsigned int i = 0; i < size; ++i)
-    {
-        stream.read(&mUniformIndex[i].name);
-        stream.read(&mUniformIndex[i].element);
-        stream.read(&mUniformIndex[i].index);
-    }
-
-    unsigned int pixelShaderSize;
-    stream.read(&pixelShaderSize);
-
-    unsigned int vertexShaderSize;
-    stream.read(&vertexShaderSize);
-
-    unsigned int geometryShaderSize;
-    stream.read(&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;
-    }
-
-    const char *pixelShaderFunction = ptr;
-    ptr += pixelShaderSize;
-
-    const char *vertexShaderFunction = ptr;
-    ptr += vertexShaderSize;
-
-    const char *geometryShaderFunction = geometryShaderSize > 0 ? ptr : NULL;
-    ptr += geometryShaderSize;
-
-    mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(pixelShaderFunction),
-                                                 pixelShaderSize, rx::SHADER_PIXEL);
-    if (!mPixelExecutable)
-    {
-        infoLog.append("Could not create pixel shader.");
-        return false;
-    }
-
-    mVertexExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
-                                                  vertexShaderSize, rx::SHADER_VERTEX);
-    if (!mVertexExecutable)
-    {
-        infoLog.append("Could not create vertex shader.");
-        delete mPixelExecutable;
-        mPixelExecutable = NULL;
-        return false;
-    }
-
-    if (geometryShaderFunction != NULL && geometryShaderSize > 0)
-    {
-        mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
-                                                        geometryShaderSize, rx::SHADER_GEOMETRY);
-        if (!mGeometryExecutable)
-        {
-            infoLog.append("Could not create geometry shader.");
-            delete mPixelExecutable;
-            mPixelExecutable = NULL;
-            delete mVertexExecutable;
-            mVertexExecutable = NULL;
-            return false;
-        }
-    }
-    else
-    {
-        mGeometryExecutable = NULL;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
-{
-    BinaryOutputStream stream;
-
-    stream.write(GL_PROGRAM_BINARY_ANGLE);
-    stream.write(VERSION_DWORD);
-    stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
-
-    for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
-    {
-        stream.write(mLinkedAttribute[i].type);
-        stream.write(mLinkedAttribute[i].name);
-        stream.write(mSemanticIndex[i]);
-    }
-
-    for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
-    {
-        stream.write(mSamplersPS[i].active);
-        stream.write(mSamplersPS[i].logicalTextureUnit);
-        stream.write((int) mSamplersPS[i].textureType);
-    }
-
-    for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
-    {
-        stream.write(mSamplersVS[i].active);
-        stream.write(mSamplersVS[i].logicalTextureUnit);
-        stream.write((int) mSamplersVS[i].textureType);
-    }
-
-    stream.write(mUsedVertexSamplerRange);
-    stream.write(mUsedPixelSamplerRange);
-    stream.write(mUsesPointSize);
-
-    stream.write(mUniforms.size());
-    for (unsigned int i = 0; i < mUniforms.size(); ++i)
-    {
-        stream.write(mUniforms[i]->type);
-        stream.write(mUniforms[i]->precision);
-        stream.write(mUniforms[i]->name);
-        stream.write(mUniforms[i]->arraySize);
-
-        stream.write(mUniforms[i]->psRegisterIndex);
-        stream.write(mUniforms[i]->vsRegisterIndex);
-        stream.write(mUniforms[i]->registerCount);
-    }
-
-    stream.write(mUniformIndex.size());
-    for (unsigned int i = 0; i < mUniformIndex.size(); ++i)
-    {
-        stream.write(mUniformIndex[i].name);
-        stream.write(mUniformIndex[i].element);
-        stream.write(mUniformIndex[i].index);
-    }
-
-    UINT pixelShaderSize = mPixelExecutable->getLength();
-    stream.write(pixelShaderSize);
-
-    UINT vertexShaderSize = mVertexExecutable->getLength();
-    stream.write(vertexShaderSize);
-
-    UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
-    stream.write(geometryShaderSize);
-
-    GUID identifier = mRenderer->getAdapterIdentifier();
-
-    GLsizei streamLength = stream.length();
-    const void *streamData = stream.data();
-
-    GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize + geometryShaderSize;
-    if (totalLength > 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);
-
-        memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize);
-        ptr += pixelShaderSize;
-
-        memcpy(ptr, mVertexExecutable->getFunction(), vertexShaderSize);
-        ptr += vertexShaderSize;
-
-        if (mGeometryExecutable != NULL && geometryShaderSize > 0)
-        {
-            memcpy(ptr, mGeometryExecutable->getFunction(), geometryShaderSize);
-            ptr += geometryShaderSize;
-        }
-
-        ASSERT(ptr - totalLength == binary);
-    }
-
-    if (length)
-    {
-        *length = totalLength;
-    }
-
-    return true;
-}
-
-GLint ProgramBinary::getLength()
-{
-    GLint length;
-    if (save(NULL, INT_MAX, &length))
-    {
-        return length;
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
-{
-    if (!fragmentShader || !fragmentShader->isCompiled())
-    {
-        return false;
-    }
-
-    if (!vertexShader || !vertexShader->isCompiled())
-    {
-        return false;
-    }
-
-    std::string pixelHLSL = fragmentShader->getHLSL();
-    std::string vertexHLSL = vertexShader->getHLSL();
-
-    // Map the varyings to the register file
-    const Varying *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL};
-    int registers = packVaryings(infoLog, packing, fragmentShader);
-
-    if (registers < 0)
-    {
-        return false;
-    }
-
-    if (!linkVaryings(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader))
-    {
-        return false;
-    }
-
-    bool success = true;
-
-    if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
-    {
-        success = false;
-    }
-
-    if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms()))
-    {
-        success = false;
-    }
-
-    // special case for gl_DepthRange, the only built-in uniform (also a struct)
-    if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange)
-    {
-        mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0));
-        mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0));
-        mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0));
-    }
-
-    if (success)
-    {
-        mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX);
-        mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL);
-
-        if (usesGeometryShader())
-        {
-            std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
-            mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY);
-        }
-
-        if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
-        {
-            infoLog.append("Failed to create D3D shaders.");
-            success = false;
-
-            delete mVertexExecutable;
-            mVertexExecutable = NULL;
-            delete mPixelExecutable;
-            mPixelExecutable = NULL;
-            delete mGeometryExecutable;
-            mGeometryExecutable = NULL;
-        }
-    }
-
-    return success;
-}
-
-// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
-bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
-{
-    unsigned int usedLocations = 0;
-
-    // Link attributes that have a binding location
-    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
-    {
-        int location = attributeBindings.getAttributeBinding(attribute->name);
-
-        if (location != -1)   // Set by glBindAttribLocation
-        {
-            if (!mLinkedAttribute[location].name.empty())
-            {
-                // Multiple active attributes bound to the same location; not an error
-            }
-
-            mLinkedAttribute[location] = *attribute;
-
-            int rows = VariableRowCount(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);
-
-                return false;
-            }
-
-            for (int i = 0; i < rows; i++)
-            {
-                usedLocations |= 1 << (location + i);
-            }
-        }
-    }
-
-    // Link attributes that don't have a binding location
-    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
-    {
-        int location = attributeBindings.getAttributeBinding(attribute->name);
-
-        if (location == -1)   // Not set by glBindAttribLocation
-        {
-            int rows = VariableRowCount(attribute->type);
-            int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
-
-            if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
-            {
-                infoLog.append("Too many active attributes (%s)", attribute->name.c_str());
-
-                return false;   // Fail to link
-            }
-
-            mLinkedAttribute[availableIndex] = *attribute;
-        }
-    }
-
-    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
-    {
-        int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
-        int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
-
-        for (int r = 0; r < rows; r++)
-        {
-            mSemanticIndex[attributeIndex++] = index++;
-        }
-    }
-
-    return true;
-}
-
-bool ProgramBinary::linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms)
-{
-    for (sh::ActiveUniforms::const_iterator uniform = vertexUniforms.begin(); uniform != vertexUniforms.end(); uniform++)
-    {
-        if (!defineUniform(GL_VERTEX_SHADER, *uniform, infoLog))
-        {
-            return false;
-        }
-    }
-
-    for (sh::ActiveUniforms::const_iterator uniform = fragmentUniforms.begin(); uniform != fragmentUniforms.end(); uniform++)
-    {
-        if (!defineUniform(GL_FRAGMENT_SHADER, *uniform, infoLog))
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog)
-{
-    if (constant.type == GL_SAMPLER_2D ||
-        constant.type == GL_SAMPLER_CUBE)
-    {
-        unsigned int samplerIndex = constant.registerIndex;
-            
-        do
-        {
-            if (shader == GL_VERTEX_SHADER)
-            {
-                if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits())
-                {
-                    mSamplersVS[samplerIndex].active = true;
-                    mSamplersVS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
-                    mSamplersVS[samplerIndex].logicalTextureUnit = 0;
-                    mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
-                }
-                else
-                {
-                    infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits());
-                    return false;
-                }
-            }
-            else if (shader == GL_FRAGMENT_SHADER)
-            {
-                if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
-                {
-                    mSamplersPS[samplerIndex].active = true;
-                    mSamplersPS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
-                    mSamplersPS[samplerIndex].logicalTextureUnit = 0;
-                    mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
-                }
-                else
-                {
-                    infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
-                    return false;
-                }
-            }
-            else UNREACHABLE();
-
-            samplerIndex++;
-        }
-        while (samplerIndex < constant.registerIndex + constant.arraySize);
-    }
-
-    Uniform *uniform = NULL;
-    GLint location = getUniformLocation(constant.name);
-
-    if (location >= 0)   // Previously defined, type and precision must match
-    {
-        uniform = mUniforms[mUniformIndex[location].index];
-
-        if (uniform->type != constant.type)
-        {
-            infoLog.append("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
-            return false;
-        }
-
-        if (uniform->precision != constant.precision)
-        {
-            infoLog.append("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
-            return false;
-        }
-    }
-    else
-    {
-        uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize);
-    }
-
-    if (!uniform)
-    {
-        return false;
-    }
-
-    if (shader == GL_FRAGMENT_SHADER)
-    {
-        uniform->psRegisterIndex = constant.registerIndex;
-    }
-    else if (shader == GL_VERTEX_SHADER)
-    {
-        uniform->vsRegisterIndex = constant.registerIndex;
-    }
-    else UNREACHABLE();
-
-    if (location >= 0)
-    {
-        return uniform->type == constant.type;
-    }
-
-    mUniforms.push_back(uniform);
-    unsigned int uniformIndex = mUniforms.size() - 1;
-
-    for (unsigned int i = 0; i < uniform->elementCount(); i++)
-    {
-        mUniformIndex.push_back(UniformLocation(constant.name, i, uniformIndex));
-    }
-
-    if (shader == GL_VERTEX_SHADER)
-    {
-        if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors())
-        {
-            infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors());
-            return false;
-        }
-    }
-    else if (shader == GL_FRAGMENT_SHADER)
-    {
-        if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors())
-        {
-            infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors());
-            return false;
-        }
-    }
-    else UNREACHABLE();
-
-    return true;
-}
-
-std::string ProgramBinary::generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
-{
-    // for now we only handle point sprite emulation
-    ASSERT(usesPointSpriteEmulation());
-    return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader);
-}
-
-std::string ProgramBinary::generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
-{
-    ASSERT(registers >= 0);
-    ASSERT(vertexShader->mUsesPointSize);
-    ASSERT(mRenderer->getMajorShaderModel() >= 4);
-
-    std::string geomHLSL;
-
-    std::string varyingSemantic = "TEXCOORD";
-
-    std::string fragCoordSemantic;
-    std::string pointCoordSemantic;
-
-    int reservedRegisterIndex = registers;
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
-    }
-
-    if (fragmentShader->mUsesPointCoord)
-    {
-        pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
-    }
-
-    geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
-                "\n"
-                "struct GS_INPUT\n"
-                "{\n";
-
-    for (int r = 0; r < registers; r++)
-    {
-        int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
-
-        geomHLSL += "    float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
-    }
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        geomHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
-    }
-
-    geomHLSL += "    float gl_PointSize : PSIZE;\n"
-                "    float4 gl_Position : SV_Position;\n"
-                "};\n"
-                "\n"
-                "struct GS_OUTPUT\n"
-                "{\n";
-
-    for (int r = 0; r < registers; r++)
-    {
-        int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
-
-        geomHLSL += "    float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
-    }
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        geomHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
-    }
-
-    if (fragmentShader->mUsesPointCoord)
-    {
-        geomHLSL += "    float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
-    }
-
-    geomHLSL +=   "    float gl_PointSize : PSIZE;\n"
-                  "    float4 gl_Position : SV_Position;\n"
-                  "};\n"
-                  "\n"
-                  "static float2 pointSpriteCorners[] = \n"
-                  "{\n"
-                  "    float2( 0.5f, -0.5f),\n"
-                  "    float2( 0.5f,  0.5f),\n"
-                  "    float2(-0.5f, -0.5f),\n"
-                  "    float2(-0.5f,  0.5f)\n"
-                  "};\n"
-                  "\n"
-                  "static float2 pointSpriteTexcoords[] = \n"
-                  "{\n"
-                  "    float2(1.0f, 1.0f),\n"
-                  "    float2(1.0f, 0.0f),\n"
-                  "    float2(0.0f, 1.0f),\n"
-                  "    float2(0.0f, 0.0f)\n"
-                  "};\n"
-                  "\n"
-                  "static float minPointSize = " + str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n"
-                  "static float maxPointSize = " + str(mRenderer->getMaxPointSize()) + ".0f;\n"
-                  "\n"
-                  "[maxvertexcount(4)]\n"
-                  "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
-                  "{\n"
-                  "    GS_OUTPUT output = (GS_OUTPUT)0;\n"
-                  "    output.gl_PointSize = input[0].gl_PointSize;\n";
-
-    for (int r = 0; r < registers; r++)
-    {
-        geomHLSL += "    output.v" + str(r) + " = input[0].v" + str(r) + ";\n";
-    }
-
-    if (fragmentShader->mUsesFragCoord)
-    {
-        geomHLSL += "    output.gl_FragCoord = input[0].gl_FragCoord;\n";
-    }
-
-    geomHLSL += "    \n"
-                "    float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
-                "    float4 gl_Position = input[0].gl_Position;\n"
-                "    float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n";
-
-    for (int corner = 0; corner < 4; corner++)
-    {
-        geomHLSL += "    \n"
-                    "    output.gl_Position = gl_Position + float4(pointSpriteCorners[" + str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
-
-        if (fragmentShader->mUsesPointCoord)
-        {
-            geomHLSL += "    output.gl_PointCoord = pointSpriteTexcoords[" + str(corner) + "];\n";
-        }
-
-        geomHLSL += "    outStream.Append(output);\n";
-    }
-
-    geomHLSL += "    \n"
-                "    outStream.RestartStrip();\n"
-                "}\n";
-
-    return geomHLSL;
-}
-
-// This method needs to match OutputHLSL::decorate
-std::string ProgramBinary::decorateAttribute(const std::string &name)
-{
-    if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
-    {
-        return "_" + name;
-    }
-    
-    return name;
-}
-
-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
-    unsigned int activeAttribute = 0;
-    unsigned int attribute;
-    for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
-    {
-        if (mLinkedAttribute[attribute].name.empty())
-        {
-            continue;
-        }
-
-        if (activeAttribute == index)
-        {
-            break;
-        }
-
-        activeAttribute++;
-    }
-
-    if (bufsize > 0)
-    {
-        const char *string = mLinkedAttribute[attribute].name.c_str();
-
-        strncpy(name, string, bufsize);
-        name[bufsize - 1] = '\0';
-
-        if (length)
-        {
-            *length = strlen(name);
-        }
-    }
-
-    *size = 1;   // Always a single 'type' instance
-
-    *type = mLinkedAttribute[attribute].type;
-}
-
-GLint ProgramBinary::getActiveAttributeCount() const
-{
-    int count = 0;
-
-    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
-    {
-        if (!mLinkedAttribute[attributeIndex].name.empty())
-        {
-            count++;
-        }
-    }
-
-    return count;
-}
-
-GLint ProgramBinary::getActiveAttributeMaxLength() const
-{
-    int maxLength = 0;
-
-    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
-    {
-        if (!mLinkedAttribute[attributeIndex].name.empty())
-        {
-            maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
-        }
-    }
-
-    return maxLength;
-}
-
-void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
-{
-    ASSERT(index < mUniforms.size());   // index must be smaller than getActiveUniformCount()
-
-    if (bufsize > 0)
-    {
-        std::string string = mUniforms[index]->name;
-
-        if (mUniforms[index]->isArray())
-        {
-            string += "[0]";
-        }
-
-        strncpy(name, string.c_str(), bufsize);
-        name[bufsize - 1] = '\0';
-
-        if (length)
-        {
-            *length = strlen(name);
-        }
-    }
-
-    *size = mUniforms[index]->elementCount();
-
-    *type = mUniforms[index]->type;
-}
-
-GLint ProgramBinary::getActiveUniformCount() const
-{
-    return mUniforms.size();
-}
-
-GLint ProgramBinary::getActiveUniformMaxLength() const
-{
-    int maxLength = 0;
-
-    unsigned int numUniforms = mUniforms.size();
-    for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
-    {
-        if (!mUniforms[uniformIndex]->name.empty())
-        {
-            int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
-            if (mUniforms[uniformIndex]->isArray())
-            {
-                length += 3;  // Counting in "[0]".
-            }
-            maxLength = std::max(length, maxLength);
-        }
-    }
-
-    return maxLength;
-}
-
-void ProgramBinary::validate(InfoLog &infoLog)
-{
-    applyUniforms();
-    if (!validateSamplers(&infoLog))
-    {
-        mValidated = false;
-    }
-    else
-    {
-        mValidated = true;
-    }
-}
-
-bool ProgramBinary::validateSamplers(InfoLog *infoLog)
-{
-    // 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.
-
-    const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
-    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;
-    }
-
-    for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
-    {
-        if (mSamplersPS[i].active)
-        {
-            unsigned int unit = mSamplersPS[i].logicalTextureUnit;
-            
-            if (unit >= maxCombinedTextureImageUnits)
-            {
-                if (infoLog)
-                {
-                    infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
-                }
-
-                return false;
-            }
-
-            if (textureUnitType[unit] != TEXTURE_UNKNOWN)
-            {
-                if (mSamplersPS[i].textureType != textureUnitType[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;
-            }
-        }
-    }
-
-    for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
-    {
-        if (mSamplersVS[i].active)
-        {
-            unsigned int unit = mSamplersVS[i].logicalTextureUnit;
-            
-            if (unit >= maxCombinedTextureImageUnits)
-            {
-                if (infoLog)
-                {
-                    infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
-                }
-
-                return false;
-            }
-
-            if (textureUnitType[unit] != TEXTURE_UNKNOWN)
-            {
-                if (mSamplersVS[i].textureType != textureUnitType[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;
-            }
-        }
-    }
-
-    return true;
-}
-
-ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D)
-{
-}
-
-struct AttributeSorter
-{
-    AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
-        : originalIndices(semanticIndices)
-    {
-        for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
-        {
-            indices[i] = i;
-        }
-
-        std::sort(&indices[0], &indices[MAX_VERTEX_ATTRIBS], *this);
-    }
-
-    bool operator()(int a, int b)
-    {
-        return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b];
-    }
-
-    int indices[MAX_VERTEX_ATTRIBS];
-    const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
-};
-
-void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
-{
-    AttributeSorter sorter(mSemanticIndex);
-
-    int oldIndices[MAX_VERTEX_ATTRIBS];
-    rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
-
-    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
-    {
-        oldIndices[i] = mSemanticIndex[i];
-        oldTranslatedAttributes[i] = attributes[i];
-    }
-
-    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
-    {
-        int oldIndex = sorter.indices[i];
-        sortedSemanticIndices[i] = oldIndices[oldIndex];
-        attributes[i] = oldTranslatedAttributes[oldIndex];
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/ProgramBinary.h b/src/third_party/angle/src/libGLESv2/ProgramBinary.h
deleted file mode 100644
index 2386c0b..0000000
--- a/src/third_party/angle/src/libGLESv2/ProgramBinary.h
+++ /dev/null
@@ -1,174 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Program.h: Defines the gl::Program class. Implements GL program objects
-// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
-
-#ifndef LIBGLESV2_PROGRAM_BINARY_H_
-#define LIBGLESV2_PROGRAM_BINARY_H_
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <string>
-#include <vector>
-
-#include "common/RefCountObject.h"
-#include "angletypes.h"
-#include "libGLESv2/mathutil.h"
-#include "libGLESv2/Uniform.h"
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/Constants.h"
-
-namespace rx
-{
-class ShaderExecutable;
-class Renderer;
-struct TranslatedAttribute;
-}
-
-namespace gl
-{
-class FragmentShader;
-class VertexShader;
-class InfoLog;
-class AttributeBindings;
-struct Varying;
-
-// Struct used for correlating uniforms/elements of uniform arrays to handles
-struct UniformLocation
-{
-    UniformLocation()
-    {
-    }
-
-    UniformLocation(const std::string &name, unsigned int element, unsigned int index);
-
-    std::string name;
-    unsigned int element;
-    unsigned int index;
-};
-
-// 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);
-    ~ProgramBinary();
-
-    rx::ShaderExecutable *getPixelExecutable();
-    rx::ShaderExecutable *getVertexExecutable();
-    rx::ShaderExecutable *getGeometryExecutable();
-
-    GLuint getAttributeLocation(const char *name);
-    int getSemanticIndex(int attributeIndex);
-
-    GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex);
-    TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
-    GLint getUsedSamplerRange(SamplerType type);
-    bool usesPointSize() const;
-    bool usesPointSpriteEmulation() const;
-    bool usesGeometryShader() const;
-
-    GLint getUniformLocation(std::string name);
-    bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
-    bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
-    bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
-    bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
-    bool setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);
-    bool setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);
-    bool setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);
-    bool setUniform1iv(GLint location, GLsizei count, const GLint *v);
-    bool setUniform2iv(GLint location, GLsizei count, const GLint *v);
-    bool setUniform3iv(GLint location, GLsizei count, const GLint *v);
-    bool setUniform4iv(GLint location, GLsizei count, const GLint *v);
-
-    bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params);
-    bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params);
-
-    void dirtyAllUniforms();
-    void applyUniforms();
-
-    bool load(InfoLog &infoLog, const void *binary, GLsizei length);
-    bool save(void* binary, GLsizei bufSize, GLsizei *length);
-    GLint getLength();
-
-    bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
-    void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
-
-    void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
-    GLint getActiveAttributeCount() const;
-    GLint getActiveAttributeMaxLength() const;
-
-    void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
-    GLint getActiveUniformCount() const;
-    GLint getActiveUniformMaxLength() const;
-
-    void validate(InfoLog &infoLog);
-    bool validateSamplers(InfoLog *infoLog);
-    bool isValidated() const;
-
-    unsigned int getSerial() const;
-
-    void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
-
-    static std::string decorateAttribute(const std::string &name);    // Prepend an underscore
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
-
-    int packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader);
-    bool linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4],
-                      std::string& pixelHLSL, std::string& vertexHLSL,
-                      FragmentShader *fragmentShader, VertexShader *vertexShader);
-
-    bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
-
-    bool linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms);
-    bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog);
-    
-    std::string generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
-    std::string generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
-
-    rx::Renderer *const mRenderer;
-
-    rx::ShaderExecutable *mPixelExecutable;
-    rx::ShaderExecutable *mVertexExecutable;
-    rx::ShaderExecutable *mGeometryExecutable;
-
-    Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
-    int mSemanticIndex[MAX_VERTEX_ATTRIBS];
-
-    struct Sampler
-    {
-        Sampler();
-
-        bool active;
-        GLint logicalTextureUnit;
-        TextureType textureType;
-    };
-
-    Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS];
-    Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    GLuint mUsedVertexSamplerRange;
-    GLuint mUsedPixelSamplerRange;
-    bool mUsesPointSize;
-
-    UniformArray mUniforms;
-    typedef std::vector<UniformLocation> UniformIndex;
-    UniformIndex mUniformIndex;
-
-    bool mValidated;
-
-    const unsigned int mSerial;
-
-    static unsigned int issueSerial();
-    static unsigned int mCurrentSerial;
-};
-}
-
-#endif   // LIBGLESV2_PROGRAM_BINARY_H_
diff --git a/src/third_party/angle/src/libGLESv2/Query.cpp b/src/third_party/angle/src/libGLESv2/Query.cpp
deleted file mode 100644
index bd98795..0000000
--- a/src/third_party/angle/src/libGLESv2/Query.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Query.cpp: Implements the gl::Query class
-
-#include "libGLESv2/Query.h"
-#include "libGLESv2/renderer/QueryImpl.h"
-#include "libGLESv2/renderer/Renderer.h"
-
-namespace gl
-{
-
-Query::Query(rx::Renderer *renderer, GLenum type, GLuint id) : RefCountObject(id)
-{ 
-    mQuery = renderer->createQuery(type);
-}
-
-Query::~Query()
-{
-    delete mQuery;
-}
-
-void Query::begin()
-{
-    mQuery->begin();
-}
-
-void Query::end()
-{
-    mQuery->end();
-}
-
-GLuint Query::getResult()
-{
-    return mQuery->getResult();
-}
-
-GLboolean Query::isResultAvailable()
-{
-    return mQuery->isResultAvailable();
-}
-
-GLenum Query::getType() const
-{
-    return mQuery->getType();
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/Query.h b/src/third_party/angle/src/libGLESv2/Query.h
deleted file mode 100644
index e9b95b7..0000000
--- a/src/third_party/angle/src/libGLESv2/Query.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Query.h: Defines the gl::Query class
-
-#ifndef LIBGLESV2_QUERY_H_
-#define LIBGLESV2_QUERY_H_
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
-#include "common/angleutils.h"
-#include "common/RefCountObject.h"
-
-namespace rx
-{
-class Renderer;
-class QueryImpl;
-}
-
-namespace gl
-{
-
-class Query : public RefCountObject
-{
-  public:
-    Query(rx::Renderer *renderer, GLenum type, GLuint id);
-    virtual ~Query();
-
-    void begin();
-    void end();
-
-    GLuint getResult();
-    GLboolean isResultAvailable();
-
-    GLenum getType() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Query);
-
-    rx::QueryImpl *mQuery;
-};
-
-}
-
-#endif   // LIBGLESV2_QUERY_H_
diff --git a/src/third_party/angle/src/libGLESv2/Renderbuffer.cpp b/src/third_party/angle/src/libGLESv2/Renderbuffer.cpp
deleted file mode 100644
index 1275137..0000000
--- a/src/third_party/angle/src/libGLESv2/Renderbuffer.cpp
+++ /dev/null
@@ -1,485 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderbuffer.cpp: the gl::Renderbuffer class and its derived classes
-// Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
-// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
-
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/utilities.h"
-
-namespace gl
-{
-unsigned int RenderbufferStorage::mCurrentSerial = 1;
-
-RenderbufferInterface::RenderbufferInterface()
-{
-}
-
-// The default case for classes inherited from RenderbufferInterface is not to
-// need to do anything upon the reference count to the parent Renderbuffer incrementing
-// or decrementing. 
-void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy)
-{
-}
-
-void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy)
-{
-}
-
-GLuint RenderbufferInterface::getRedSize() const
-{
-    return gl::GetRedSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getGreenSize() const
-{
-    return gl::GetGreenSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getBlueSize() const
-{
-    return gl::GetBlueSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getAlphaSize() const
-{
-    return gl::GetAlphaSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getDepthSize() const
-{
-    return gl::GetDepthSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getStencilSize() const
-{
-    return gl::GetStencilSize(getActualFormat());
-}
-
-///// RenderbufferTexture2D Implementation ////////
-
-RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLenum target) : mTarget(target)
-{
-    mTexture2D.set(texture);
-}
-
-RenderbufferTexture2D::~RenderbufferTexture2D()
-{
-    mTexture2D.set(NULL);
-}
-
-// Textures need to maintain their own reference count for references via
-// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
-void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy)
-{
-    mTexture2D->addProxyRef(proxy);
-}
-
-void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy)
-{
-    mTexture2D->releaseProxy(proxy);
-}
-
-rx::RenderTarget *RenderbufferTexture2D::getRenderTarget()
-{
-    return mTexture2D->getRenderTarget(mTarget);
-}
-
-rx::RenderTarget *RenderbufferTexture2D::getDepthStencil()
-{
-    return mTexture2D->getDepthStencil(mTarget);
-}
-
-GLsizei RenderbufferTexture2D::getWidth() const
-{
-    return mTexture2D->getWidth(0);
-}
-
-GLsizei RenderbufferTexture2D::getHeight() const
-{
-    return mTexture2D->getHeight(0);
-}
-
-GLenum RenderbufferTexture2D::getInternalFormat() const
-{
-    return mTexture2D->getInternalFormat(0);
-}
-
-GLenum RenderbufferTexture2D::getActualFormat() const
-{
-    return mTexture2D->getActualFormat(0);
-}
-
-GLsizei RenderbufferTexture2D::getSamples() const
-{
-    return 0;
-}
-
-unsigned int RenderbufferTexture2D::getSerial() const
-{
-    return mTexture2D->getRenderTargetSerial(mTarget);
-}
-
-///// RenderbufferTextureCubeMap Implementation ////////
-
-RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target) : mTarget(target)
-{
-    mTextureCubeMap.set(texture);
-}
-
-RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap()
-{
-    mTextureCubeMap.set(NULL);
-}
-
-// Textures need to maintain their own reference count for references via
-// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
-void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy)
-{
-    mTextureCubeMap->addProxyRef(proxy);
-}
-
-void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy)
-{
-    mTextureCubeMap->releaseProxy(proxy);
-}
-
-rx::RenderTarget *RenderbufferTextureCubeMap::getRenderTarget()
-{
-    return mTextureCubeMap->getRenderTarget(mTarget);
-}
-
-rx::RenderTarget *RenderbufferTextureCubeMap::getDepthStencil()
-{
-    return NULL;
-}
-
-GLsizei RenderbufferTextureCubeMap::getWidth() const
-{
-    return mTextureCubeMap->getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-}
-
-GLsizei RenderbufferTextureCubeMap::getHeight() const
-{
-    return mTextureCubeMap->getHeight(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-}
-
-GLenum RenderbufferTextureCubeMap::getInternalFormat() const
-{
-    return mTextureCubeMap->getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-}
-
-GLenum RenderbufferTextureCubeMap::getActualFormat() const
-{
-    return mTextureCubeMap->getActualFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-}
-
-GLsizei RenderbufferTextureCubeMap::getSamples() const
-{
-    return 0;
-}
-
-unsigned int RenderbufferTextureCubeMap::getSerial() const
-{
-    return mTextureCubeMap->getRenderTargetSerial(mTarget);
-}
-
-////// Renderbuffer Implementation //////
-
-Renderbuffer::Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *instance) : RefCountObject(id)
-{
-    ASSERT(instance != NULL);
-    mInstance = instance;
-}
-
-Renderbuffer::~Renderbuffer()
-{
-    delete mInstance;
-}
-
-// The RenderbufferInterface contained in this Renderbuffer may need to maintain
-// its own reference count, so we pass it on here.
-void Renderbuffer::addRef() const
-{
-    mInstance->addProxyRef(this);
-
-    RefCountObject::addRef();
-}
-
-void Renderbuffer::release() const
-{
-    mInstance->releaseProxy(this);
-
-    RefCountObject::release();
-}
-
-rx::RenderTarget *Renderbuffer::getRenderTarget()
-{
-    return mInstance->getRenderTarget();
-}
-
-rx::RenderTarget *Renderbuffer::getDepthStencil()
-{
-    return mInstance->getDepthStencil();
-}
-
-GLsizei Renderbuffer::getWidth() const
-{
-    return mInstance->getWidth();
-}
-
-GLsizei Renderbuffer::getHeight() const
-{
-    return mInstance->getHeight();
-}
-
-GLenum Renderbuffer::getInternalFormat() const
-{
-    return mInstance->getInternalFormat();
-}
-
-GLenum Renderbuffer::getActualFormat() const
-{
-    return mInstance->getActualFormat();
-}
-
-GLuint Renderbuffer::getRedSize() const
-{
-    return mInstance->getRedSize();
-}
-
-GLuint Renderbuffer::getGreenSize() const
-{
-    return mInstance->getGreenSize();
-}
-
-GLuint Renderbuffer::getBlueSize() const
-{
-    return mInstance->getBlueSize();
-}
-
-GLuint Renderbuffer::getAlphaSize() const
-{
-    return mInstance->getAlphaSize();
-}
-
-GLuint Renderbuffer::getDepthSize() const
-{
-    return mInstance->getDepthSize();
-}
-
-GLuint Renderbuffer::getStencilSize() const
-{
-    return mInstance->getStencilSize();
-}
-
-GLsizei Renderbuffer::getSamples() const
-{
-    return mInstance->getSamples();
-}
-
-unsigned int Renderbuffer::getSerial() const
-{
-    return mInstance->getSerial();
-}
-
-void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
-{
-    ASSERT(newStorage != NULL);
-
-    delete mInstance;
-    mInstance = newStorage;
-}
-
-RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial())
-{
-    mWidth = 0;
-    mHeight = 0;
-    mInternalFormat = GL_RGBA4;
-    mActualFormat = GL_RGBA8_OES;
-    mSamples = 0;
-}
-
-RenderbufferStorage::~RenderbufferStorage()
-{
-}
-
-rx::RenderTarget *RenderbufferStorage::getRenderTarget()
-{
-    return NULL;
-}
-
-rx::RenderTarget *RenderbufferStorage::getDepthStencil()
-{
-    return NULL;
-}
-
-GLsizei RenderbufferStorage::getWidth() const
-{
-    return mWidth;
-}
-
-GLsizei RenderbufferStorage::getHeight() const
-{
-    return mHeight;
-}
-
-GLenum RenderbufferStorage::getInternalFormat() const
-{
-    return mInternalFormat;
-}
-
-GLenum RenderbufferStorage::getActualFormat() const
-{
-    return mActualFormat;
-}
-
-GLsizei RenderbufferStorage::getSamples() const
-{
-    return mSamples;
-}
-
-unsigned int RenderbufferStorage::getSerial() const
-{
-    return mSerial;
-}
-
-unsigned int RenderbufferStorage::issueSerial()
-{
-    return mCurrentSerial++;
-}
-
-unsigned int RenderbufferStorage::issueCubeSerials()
-{
-    unsigned int firstSerial = mCurrentSerial;
-    mCurrentSerial += 6;
-    return firstSerial;
-}
-
-Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain)
-{
-    mRenderTarget = renderer->createRenderTarget(swapChain, false); 
-
-    if (mRenderTarget)
-    {
-        mWidth = mRenderTarget->getWidth();
-        mHeight = mRenderTarget->getHeight();
-        mInternalFormat = mRenderTarget->getInternalFormat();
-        mActualFormat = mRenderTarget->getActualFormat();
-        mSamples = mRenderTarget->getSamples();
-    }
-}
-
-Colorbuffer::Colorbuffer(rx::Renderer *renderer, int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
-{
-    mRenderTarget = renderer->createRenderTarget(width, height, format, samples, false);
-
-    if (mRenderTarget)
-    {
-        mWidth = width;
-        mHeight = height;
-        mInternalFormat = format;
-        mActualFormat = mRenderTarget->getActualFormat();
-        mSamples = mRenderTarget->getSamples();
-    }
-}
-
-Colorbuffer::~Colorbuffer()
-{
-    if (mRenderTarget)
-    {
-        delete mRenderTarget;
-    }
-}
-
-rx::RenderTarget *Colorbuffer::getRenderTarget()
-{
-    if (mRenderTarget)
-    {
-        return mRenderTarget;
-    }
-
-    return NULL;
-}
-
-DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain)
-{
-    mDepthStencil = renderer->createRenderTarget(swapChain, true);
-    if (mDepthStencil)
-    {
-        mWidth = mDepthStencil->getWidth();
-        mHeight = mDepthStencil->getHeight();
-        mInternalFormat = mDepthStencil->getInternalFormat();
-        mSamples = mDepthStencil->getSamples();
-        mActualFormat = mDepthStencil->getActualFormat();
-    }
-}
-
-DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples)
-{
-
-    mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples, true);
-
-    mWidth = mDepthStencil->getWidth();
-    mHeight = mDepthStencil->getHeight();
-    mInternalFormat = GL_DEPTH24_STENCIL8_OES;
-    mActualFormat = mDepthStencil->getActualFormat();
-    mSamples = mDepthStencil->getSamples();
-}
-
-DepthStencilbuffer::~DepthStencilbuffer()
-{
-    if (mDepthStencil)
-    {
-        delete mDepthStencil;
-    }
-}
-
-rx::RenderTarget *DepthStencilbuffer::getDepthStencil()
-{
-    if (mDepthStencil)
-    {
-        return mDepthStencil;
-    }
-
-    return NULL;
-}
-
-Depthbuffer::Depthbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples)
-{
-    if (mDepthStencil)
-    {
-        mInternalFormat = GL_DEPTH_COMPONENT16;   // If the renderbuffer parameters are queried, the calling function
-                                                  // will expect one of the valid renderbuffer formats for use in 
-                                                  // glRenderbufferStorage
-    }
-}
-
-Depthbuffer::~Depthbuffer()
-{
-}
-
-Stencilbuffer::Stencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples)
-{
-    if (mDepthStencil)
-    {
-        mInternalFormat = GL_STENCIL_INDEX8;   // If the renderbuffer parameters are queried, the calling function
-                                               // will expect one of the valid renderbuffer formats for use in 
-                                               // glRenderbufferStorage
-    }
-}
-
-Stencilbuffer::~Stencilbuffer()
-{
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/Renderbuffer.h b/src/third_party/angle/src/libGLESv2/Renderbuffer.h
deleted file mode 100644
index eca2f3a..0000000
--- a/src/third_party/angle/src/libGLESv2/Renderbuffer.h
+++ /dev/null
@@ -1,261 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderbuffer.h: Defines the wrapper class gl::Renderbuffer, as well as the
-// class hierarchy used to store its contents: RenderbufferStorage, Colorbuffer,
-// DepthStencilbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
-// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
-
-#ifndef LIBGLESV2_RENDERBUFFER_H_
-#define LIBGLESV2_RENDERBUFFER_H_
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
-#include "common/angleutils.h"
-#include "common/RefCountObject.h"
-
-namespace rx
-{
-class Renderer;
-class SwapChain;
-class RenderTarget;
-}
-
-namespace gl
-{
-class Texture2D;
-class TextureCubeMap;
-class Renderbuffer;
-class Colorbuffer;
-class DepthStencilbuffer;
-
-class RenderbufferInterface
-{
-  public:
-    RenderbufferInterface();
-
-    virtual ~RenderbufferInterface() {};
-
-    virtual void addProxyRef(const Renderbuffer *proxy);
-    virtual void releaseProxy(const Renderbuffer *proxy);
-
-    virtual rx::RenderTarget *getRenderTarget() = 0;
-    virtual rx::RenderTarget *getDepthStencil() = 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;
-
-    GLuint getRedSize() const;
-    GLuint getGreenSize() const;
-    GLuint getBlueSize() const;
-    GLuint getAlphaSize() const;
-    GLuint getDepthSize() const;
-    GLuint getStencilSize() const;
-
-    virtual unsigned int getSerial() const = 0;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface);
-};
-
-class RenderbufferTexture2D : public RenderbufferInterface
-{
-  public:
-    RenderbufferTexture2D(Texture2D *texture, GLenum target);
-
-    virtual ~RenderbufferTexture2D();
-
-    void addProxyRef(const Renderbuffer *proxy);
-    void releaseProxy(const Renderbuffer *proxy);
-
-    rx::RenderTarget *getRenderTarget();
-    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;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture2D);
-
-    BindingPointer <Texture2D> mTexture2D;
-    GLenum mTarget;
-};
-
-class RenderbufferTextureCubeMap : public RenderbufferInterface
-{
-  public:
-    RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target);
-
-    virtual ~RenderbufferTextureCubeMap();
-
-    void addProxyRef(const Renderbuffer *proxy);
-    void releaseProxy(const Renderbuffer *proxy);
-
-    rx::RenderTarget *getRenderTarget();
-    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;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(RenderbufferTextureCubeMap);
-
-    BindingPointer <TextureCubeMap> mTextureCubeMap;
-    GLenum mTarget;
-};
-
-// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
-// is called. The specific concrete type depends on whether the internal format is
-// colour depth, stencil or packed depth/stencil.
-class RenderbufferStorage : public RenderbufferInterface
-{
-  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;
-
-    static unsigned int issueSerial();
-    static unsigned int issueCubeSerials();
-
-  protected:
-    GLsizei mWidth;
-    GLsizei mHeight;
-    GLenum mInternalFormat;
-    GLenum mActualFormat;
-    GLsizei mSamples;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
-
-    const unsigned int mSerial;
-
-    static unsigned int mCurrentSerial;
-};
-
-// Renderbuffer implements the GL renderbuffer object.
-// It's only a proxy for a RenderbufferInterface instance; the internal object
-// can change whenever glRenderbufferStorage is called.
-class Renderbuffer : public RefCountObject
-{
-  public:
-    Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *storage);
-
-    virtual ~Renderbuffer();
-
-    // These functions from RefCountObject are overloaded here because
-    // Textures need to maintain their own count of references to them via
-    // Renderbuffers/RenderbufferTextures. These functions invoke those
-    // reference counting functions on the RenderbufferInterface.
-    void addRef() const;
-    void release() const;
-
-    rx::RenderTarget *getRenderTarget();
-    rx::RenderTarget *getDepthStencil();
-
-    GLsizei getWidth() const;
-    GLsizei getHeight() const;
-    GLenum getInternalFormat() const;
-    GLenum getActualFormat() const;
-    GLuint getRedSize() const;
-    GLuint getGreenSize() const;
-    GLuint getBlueSize() const;
-    GLuint getAlphaSize() const;
-    GLuint getDepthSize() const;
-    GLuint getStencilSize() const;
-    GLsizei getSamples() const;
-
-    unsigned int getSerial() const;
-
-    void setStorage(RenderbufferStorage *newStorage);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
-
-    RenderbufferInterface *mInstance;
-};
-
-class Colorbuffer : public RenderbufferStorage
-{
-  public:
-    Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain);
-    Colorbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples);
-
-    virtual ~Colorbuffer();
-
-    virtual rx::RenderTarget *getRenderTarget();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
-
-    rx::RenderTarget *mRenderTarget;
-};
-
-class DepthStencilbuffer : public RenderbufferStorage
-{
-  public:
-    DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain);
-    DepthStencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples);
-
-    ~DepthStencilbuffer();
-
-    virtual rx::RenderTarget *getDepthStencil();
-
-  protected:
-    rx::RenderTarget  *mDepthStencil;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
-};
-
-class Depthbuffer : public DepthStencilbuffer
-{
-  public:
-    Depthbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples);
-
-    virtual ~Depthbuffer();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
-};
-
-class Stencilbuffer : public DepthStencilbuffer
-{
-  public:
-    Stencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples);
-
-    virtual ~Stencilbuffer();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
-};
-}
-
-#endif   // LIBGLESV2_RENDERBUFFER_H_
diff --git a/src/third_party/angle/src/libGLESv2/ResourceManager.cpp b/src/third_party/angle/src/libGLESv2/ResourceManager.cpp
deleted file mode 100644
index 32a7be9..0000000
--- a/src/third_party/angle/src/libGLESv2/ResourceManager.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and 
-// retrieves objects which may be shared by multiple Contexts.
-
-#include "libGLESv2/ResourceManager.h"
-
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/Texture.h"
-
-namespace gl
-{
-ResourceManager::ResourceManager(rx::Renderer *renderer)
-{
-    mRefCount = 1;
-    mRenderer = renderer;
-#if defined(__LB_XB360__)
-    mVideoTextureHandle = 0;
-#endif
-}
-
-ResourceManager::~ResourceManager()
-{
-    while (!mBufferMap.empty())
-    {
-        deleteBuffer(mBufferMap.begin()->first);
-    }
-
-    while (!mProgramMap.empty())
-    {
-        deleteProgram(mProgramMap.begin()->first);
-    }
-
-    while (!mShaderMap.empty())
-    {
-        deleteShader(mShaderMap.begin()->first);
-    }
-
-    while (!mRenderbufferMap.empty())
-    {
-        deleteRenderbuffer(mRenderbufferMap.begin()->first);
-    }
-
-    while (!mTextureMap.empty())
-    {
-        deleteTexture(mTextureMap.begin()->first);
-    }
-}
-
-void ResourceManager::addRef()
-{
-    mRefCount++;
-}
-
-void ResourceManager::release()
-{
-    if (--mRefCount == 0)
-    {
-        delete this;
-    }
-}
-
-// Returns an unused buffer name
-GLuint ResourceManager::createBuffer()
-{
-    GLuint handle = mBufferHandleAllocator.allocate();
-
-    mBufferMap[handle] = NULL;
-
-    return handle;
-}
-
-// Returns an unused shader/program name
-GLuint ResourceManager::createShader(GLenum type)
-{
-    GLuint handle = mProgramShaderHandleAllocator.allocate();
-
-    if (type == GL_VERTEX_SHADER)
-    {
-        mShaderMap[handle] = new VertexShader(this, mRenderer, handle);
-    }
-    else if (type == GL_FRAGMENT_SHADER)
-    {
-        mShaderMap[handle] = new FragmentShader(this, mRenderer, handle);
-    }
-    else UNREACHABLE();
-
-    return handle;
-}
-
-// Returns an unused program/shader name
-GLuint ResourceManager::createProgram()
-{
-    GLuint handle = mProgramShaderHandleAllocator.allocate();
-
-    mProgramMap[handle] = new Program(mRenderer, this, handle);
-
-    return handle;
-}
-
-// Returns an unused texture name
-GLuint ResourceManager::createTexture()
-{
-    GLuint handle = mTextureHandleAllocator.allocate();
-
-    mTextureMap[handle] = NULL;
-
-    return handle;
-}
-
-// Returns an unused renderbuffer name
-GLuint ResourceManager::createRenderbuffer()
-{
-    GLuint handle = mRenderbufferHandleAllocator.allocate();
-
-    mRenderbufferMap[handle] = NULL;
-
-    return handle;
-}
-
-#if defined(__LB_XB360__)
-void ResourceManager::setVideoTextureHandle(GLuint texture)
-{
-  if (mTextureMap.find(texture) == mTextureMap.end()) {
-    if (mVideoTextureHandle != 0) {
-      mTextureMap[mVideoTextureHandle] = NULL;
-      mVideoTextureHandle = 0;
-    }
-    return;
-  }
-
-  GLuint oldVideoTextureHandle = mVideoTextureHandle;
-  mVideoTextureHandle = texture;
-  if (oldVideoTextureHandle != 0) {
-    mTextureMap[mVideoTextureHandle] = mTextureMap[oldVideoTextureHandle];
-    mTextureMap[oldVideoTextureHandle] = NULL;
-  } else {
-    mTextureMap[mVideoTextureHandle] = NULL;
-  }
-}
-#endif
-
-void ResourceManager::deleteBuffer(GLuint buffer)
-{
-    BufferMap::iterator bufferObject = mBufferMap.find(buffer);
-
-    if (bufferObject != mBufferMap.end())
-    {
-        mBufferHandleAllocator.release(bufferObject->first);
-        if (bufferObject->second) bufferObject->second->release();
-        mBufferMap.erase(bufferObject);
-    }
-}
-
-void ResourceManager::deleteShader(GLuint shader)
-{
-    ShaderMap::iterator shaderObject = mShaderMap.find(shader);
-
-    if (shaderObject != mShaderMap.end())
-    {
-        if (shaderObject->second->getRefCount() == 0)
-        {
-            mProgramShaderHandleAllocator.release(shaderObject->first);
-            delete shaderObject->second;
-            mShaderMap.erase(shaderObject);
-        }
-        else
-        {
-            shaderObject->second->flagForDeletion();
-        }
-    }
-}
-
-void ResourceManager::deleteProgram(GLuint program)
-{
-    ProgramMap::iterator programObject = mProgramMap.find(program);
-
-    if (programObject != mProgramMap.end())
-    {
-        if (programObject->second->getRefCount() == 0)
-        {
-            mProgramShaderHandleAllocator.release(programObject->first);
-            delete programObject->second;
-            mProgramMap.erase(programObject);
-        }
-        else
-        { 
-            programObject->second->flagForDeletion();
-        }
-    }
-}
-
-void ResourceManager::deleteTexture(GLuint texture)
-{
-    TextureMap::iterator textureObject = mTextureMap.find(texture);
-
-    if (textureObject != mTextureMap.end())
-    {
-        mTextureHandleAllocator.release(textureObject->first);
-        if (textureObject->second) textureObject->second->release();
-        mTextureMap.erase(textureObject);
-    }
-
-#if defined(__LB_XB360__)
-    if (texture == mVideoTextureHandle) {
-        mVideoTextureHandle = 0;
-    }
-#endif
-}
-
-void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
-{
-    RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
-
-    if (renderbufferObject != mRenderbufferMap.end())
-    {
-        mRenderbufferHandleAllocator.release(renderbufferObject->first);
-        if (renderbufferObject->second) renderbufferObject->second->release();
-        mRenderbufferMap.erase(renderbufferObject);
-    }
-}
-
-Buffer *ResourceManager::getBuffer(unsigned int handle)
-{
-    BufferMap::iterator buffer = mBufferMap.find(handle);
-
-    if (buffer == mBufferMap.end())
-    {
-        return NULL;
-    }
-    else
-    {
-        return buffer->second;
-    }
-}
-
-Shader *ResourceManager::getShader(unsigned int handle)
-{
-    ShaderMap::iterator shader = mShaderMap.find(handle);
-
-    if (shader == mShaderMap.end())
-    {
-        return NULL;
-    }
-    else
-    {
-        return shader->second;
-    }
-}
-
-Texture *ResourceManager::getTexture(unsigned int handle)
-{
-    if (handle == 0) return NULL;
-
-    TextureMap::iterator texture = mTextureMap.find(handle);
-
-    if (texture == mTextureMap.end())
-    {
-        return NULL;
-    }
-    else
-    {
-        return texture->second;
-    }
-}
-
-Program *ResourceManager::getProgram(unsigned int handle)
-{
-    ProgramMap::iterator program = mProgramMap.find(handle);
-
-    if (program == mProgramMap.end())
-    {
-        return NULL;
-    }
-    else
-    {
-        return program->second;
-    }
-}
-
-Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
-{
-    RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
-
-    if (renderbuffer == mRenderbufferMap.end())
-    {
-        return NULL;
-    }
-    else
-    {
-        return renderbuffer->second;
-    }
-}
-
-void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
-{
-    mRenderbufferMap[handle] = buffer;
-}
-
-void ResourceManager::checkBufferAllocation(unsigned int buffer)
-{
-    if (buffer != 0 && !getBuffer(buffer))
-    {
-        Buffer *bufferObject = new Buffer(mRenderer, buffer);
-        mBufferMap[buffer] = bufferObject;
-        bufferObject->addRef();
-    }
-}
-
-void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
-{
-    if (!getTexture(texture) && texture != 0)
-    {
-        Texture *textureObject;
-
-        if (type == TEXTURE_2D)
-        {
-            textureObject = new Texture2D(mRenderer, texture);
-        }
-        else if (type == TEXTURE_CUBE)
-        {
-            textureObject = new TextureCubeMap(mRenderer, texture);
-        }
-        else
-        {
-            UNREACHABLE();
-            return;
-        }
-
-        mTextureMap[texture] = textureObject;
-        textureObject->addRef();
-    }
-}
-
-void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
-{
-    if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
-    {
-        Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer, renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0));
-        mRenderbufferMap[renderbuffer] = renderbufferObject;
-        renderbufferObject->addRef();
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/ResourceManager.h b/src/third_party/angle/src/libGLESv2/ResourceManager.h
deleted file mode 100644
index b4b0862..0000000
--- a/src/third_party/angle/src/libGLESv2/ResourceManager.h
+++ /dev/null
@@ -1,118 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ResourceManager.h : Defines the ResourceManager class, which tracks objects
-// shared by multiple GL contexts.
-
-#ifndef LIBGLESV2_RESOURCEMANAGER_H_
-#define LIBGLESV2_RESOURCEMANAGER_H_
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
-#ifdef _MSC_VER
-#include <hash_map>
-#else
-#include <unordered_map>
-#endif
-
-#include "common/angleutils.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/HandleAllocator.h"
-
-namespace rx
-{
-class Renderer;
-}
-
-namespace gl
-{
-class Buffer;
-class Shader;
-class Program;
-class Texture;
-class Renderbuffer;
-
-class ResourceManager
-{
-  public:
-    explicit ResourceManager(rx::Renderer *renderer);
-    ~ResourceManager();
-
-    void addRef();
-    void release();
-
-    GLuint createBuffer();
-    GLuint createShader(GLenum type);
-    GLuint createProgram();
-    GLuint createTexture();
-    GLuint createRenderbuffer();
-
-#if defined(__LB_XB360__)
-    void setVideoTextureHandle(GLuint texture);
-    GLuint getVideoTextureHandle() { return mVideoTextureHandle; }
-#endif
-
-    void deleteBuffer(GLuint buffer);
-    void deleteShader(GLuint shader);
-    void deleteProgram(GLuint program);
-    void deleteTexture(GLuint texture);
-    void deleteRenderbuffer(GLuint renderbuffer);
-
-    Buffer *getBuffer(GLuint handle);
-    Shader *getShader(GLuint handle);
-    Program *getProgram(GLuint handle);
-    Texture *getTexture(GLuint handle);
-    Renderbuffer *getRenderbuffer(GLuint handle);
-    
-    void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
-
-    void checkBufferAllocation(unsigned int buffer);
-    void checkTextureAllocation(GLuint texture, TextureType type);
-    void checkRenderbufferAllocation(GLuint renderbuffer);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(ResourceManager);
-
-    std::size_t mRefCount;
-    rx::Renderer *mRenderer;
-
-#ifndef HASH_MAP
-# ifdef _MSC_VER
-#  define HASH_MAP stdext::hash_map
-# else
-#  define HASH_MAP std::unordered_map
-# endif
-#endif
-
-    typedef HASH_MAP<GLuint, Buffer*> BufferMap;
-    BufferMap mBufferMap;
-    HandleAllocator mBufferHandleAllocator;
-
-    typedef HASH_MAP<GLuint, Shader*> ShaderMap;
-    ShaderMap mShaderMap;
-
-    typedef HASH_MAP<GLuint, Program*> ProgramMap;
-    ProgramMap mProgramMap;
-    HandleAllocator mProgramShaderHandleAllocator;
-
-    typedef HASH_MAP<GLuint, Texture*> TextureMap;
-    TextureMap mTextureMap;
-    HandleAllocator mTextureHandleAllocator;
-
-#if defined(__LB_XB360__)
-    // Reserved handle for the video texture.
-    GLuint mVideoTextureHandle;
-#endif
-
-    typedef HASH_MAP<GLuint, Renderbuffer*> RenderbufferMap;
-    RenderbufferMap mRenderbufferMap;
-    HandleAllocator mRenderbufferHandleAllocator;
-};
-
-}
-
-#endif // LIBGLESV2_RESOURCEMANAGER_H_
diff --git a/src/third_party/angle/src/libGLESv2/Shader.cpp b/src/third_party/angle/src/libGLESv2/Shader.cpp
deleted file mode 100644
index d4ea271..0000000
--- a/src/third_party/angle/src/libGLESv2/Shader.cpp
+++ /dev/null
@@ -1,625 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Shader.cpp: Implements the gl::Shader class and its  derived classes
-// VertexShader and FragmentShader. Implements GL shader objects and related
-// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
-
-#include "libGLESv2/Shader.h"
-
-#include "GLSLANG/ShaderLang.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/ResourceManager.h"
-
-#define DONT_SAVE_SHADER_SOURCES
-
-namespace gl
-{
-void *Shader::mFragmentCompiler = NULL;
-void *Shader::mVertexCompiler = NULL;
-
-Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
-    : mHandle(handle), mRenderer(renderer), mResourceManager(manager)
-{
-    mSource = NULL;
-    mHlsl = NULL;
-    mInfoLog = NULL;
-
-    uncompile();
-    initializeCompiler();
-
-    mRefCount = 0;
-    mDeleteStatus = false;
-}
-
-Shader::~Shader()
-{
-    delete[] mSource;
-    delete[] mHlsl;
-    delete[] mInfoLog;
-}
-
-GLuint Shader::getHandle() const
-{
-    return mHandle;
-}
-
-void Shader::setSource(GLsizei count, const char **string, const GLint *length)
-{
-    delete[] mSource;
-    int totalLength = 0;
-
-    for (int i = 0; i < count; i++)
-    {
-        if (length && length[i] >= 0)
-        {
-            totalLength += length[i];
-        }
-        else
-        {
-            totalLength += (int)strlen(string[i]);
-        }
-    }
-
-    mSource = new char[totalLength + 1];
-    char *code = mSource;
-
-    for (int i = 0; i < count; i++)
-    {
-        int stringLength;
-
-        if (length && length[i] >= 0)
-        {
-            stringLength = length[i];
-        }
-        else
-        {
-            stringLength = (int)strlen(string[i]);
-        }
-
-        strncpy(code, string[i], stringLength);
-        code += stringLength;
-    }
-
-    mSource[totalLength] = '\0';
-}
-
-int Shader::getInfoLogLength() const
-{
-    if (!mInfoLog)
-    {
-        return 0;
-    }
-    else
-    {
-       return strlen(mInfoLog) + 1;
-    }
-}
-
-void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
-{
-    int index = 0;
-
-    if (bufSize > 0)
-    {
-        if (mInfoLog)
-        {
-            index = std::min(bufSize - 1, (int)strlen(mInfoLog));
-            memcpy(infoLog, mInfoLog, index);
-        }
-
-        infoLog[index] = '\0';
-    }
-
-    if (length)
-    {
-        *length = index;
-    }
-}
-
-int Shader::getSourceLength() const
-{
-    if (!mSource)
-    {
-        return 0;
-    }
-    else
-    {
-       return strlen(mSource) + 1;
-    }
-}
-
-int Shader::getTranslatedSourceLength() const
-{
-    if (!mHlsl)
-    {
-        return 0;
-    }
-    else
-    {
-       return strlen(mHlsl) + 1;
-    }
-}
-
-void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer)
-{
-    int index = 0;
-
-    if (bufSize > 0)
-    {
-        if (source)
-        {
-            index = std::min(bufSize - 1, (int)strlen(source));
-            memcpy(buffer, source, index);
-        }
-
-        buffer[index] = '\0';
-    }
-
-    if (length)
-    {
-        *length = index;
-    }
-}
-
-void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer)
-{
-    getSourceImpl(mSource, bufSize, length, buffer);
-}
-
-void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
-{
-    getSourceImpl(mHlsl, bufSize, length, buffer);
-}
-
-const sh::ActiveUniforms &Shader::getUniforms()
-{
-    return mActiveUniforms;
-}
-
-bool Shader::isCompiled()
-{
-    return mHlsl != NULL;
-}
-
-const char *Shader::getHLSL()
-{
-    return mHlsl;
-}
-
-void Shader::addRef()
-{
-    mRefCount++;
-}
-
-void Shader::release()
-{
-    mRefCount--;
-
-    if (mRefCount == 0 && mDeleteStatus)
-    {
-        mResourceManager->deleteShader(mHandle);
-    }
-}
-
-unsigned int Shader::getRefCount() const
-{
-    return mRefCount;
-}
-
-bool Shader::isFlaggedForDeletion() const
-{
-    return mDeleteStatus;
-}
-
-void Shader::flagForDeletion()
-{
-    mDeleteStatus = true;
-}
-
-// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
-void Shader::initializeCompiler()
-{
-    if (!mFragmentCompiler)
-    {
-        int result = ShInitialize();
-
-        if (result)
-        {
-            ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
-
-            ShBuiltInResources resources;
-            ShInitBuiltInResources(&resources);
-
-            resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
-            resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
-            resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
-            resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits();
-            resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
-            resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
-            resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
-            resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets();
-            resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport();
-            resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
-            // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
-            resources.FragmentPrecisionHigh = 1;   // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
-            resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
-
-            mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
-            mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
-        }
-    }
-}
-
-void Shader::releaseCompiler()
-{
-    ShDestruct(mFragmentCompiler);
-    ShDestruct(mVertexCompiler);
-
-    mFragmentCompiler = NULL;
-    mVertexCompiler = NULL;
-
-    ShFinalize();
-}
-
-void Shader::parseVaryings()
-{
-    if (mHlsl)
-    {
-        const char *input = strstr(mHlsl, "// Varyings") + 12;
-
-        while(true)
-        {
-            char varyingType[256];
-            char varyingName[256];
-
-            int matches = sscanf(input, "static %255s %255s", varyingType, varyingName);
-
-            if (matches != 2)
-            {
-                break;
-            }
-
-            char *array = strstr(varyingName, "[");
-            int size = 1;
-
-            if (array)
-            {
-                size = atoi(array + 1);
-                *array = '\0';
-            }
-
-            mVaryings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL));
-
-            input = strstr(input, ";") + 2;
-        }
-
-        mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL;
-        mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL;
-        mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL;
-        mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
-        mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
-        mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
-        mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
-        mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL;
-        mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL;
-    }
-}
-
-void Shader::resetVaryingsRegisterAssignment()
-{
-    for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++)
-    {
-        var->reg = -1;
-        var->col = -1;
-    }
-}
-
-// initialize/clean up previous state
-void Shader::uncompile()
-{
-    // set by compileToHLSL
-    delete[] mHlsl;
-    mHlsl = NULL;
-    delete[] mInfoLog;
-    mInfoLog = NULL;
-
-    // set by parseVaryings
-    mVaryings.clear();
-
-    mUsesMultipleRenderTargets = false;
-    mUsesFragColor = false;
-    mUsesFragData = false;
-    mUsesFragCoord = false;
-    mUsesFrontFacing = false;
-    mUsesPointSize = false;
-    mUsesPointCoord = false;
-    mUsesDepthRange = false;
-    mUsesFragDepth = false;
-
-    mActiveUniforms.clear();
-}
-
-void Shader::compileToHLSL(void *compiler)
-{
-    // ensure we don't pass a NULL source to the compiler
-    const char *source = "\0";
-    if (mSource)
-    {
-        source = mSource;
-    }
-
-    // ensure the compiler is loaded
-    initializeCompiler();
-
-    int compileOptions = SH_OBJECT_CODE;
-    std::string sourcePath;
-#ifndef DONT_SAVE_SHADER_SOURCES
-    if (perfActive())
-    {
-        sourcePath = getTempPath();
-        writeFile(sourcePath.c_str(), source, strlen(source));
-        compileOptions |= SH_LINE_DIRECTIVES;
-    }
-#endif
-    int result;
-    if (sourcePath.empty())
-    {
-        result = ShCompile(compiler, &source, 1, compileOptions);
-    }
-    else
-    {
-        const char* sourceStrings[2] =
-        {
-            sourcePath.c_str(),
-            source
-        };
-
-        result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
-    }
-
-    if (result)
-    {
-        size_t objCodeLen = 0;
-        ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
-        mHlsl = new char[objCodeLen];
-        ShGetObjectCode(compiler, mHlsl);
-
-        void *activeUniforms;
-        ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
-        mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms;
-    }
-    else
-    {
-        size_t infoLogLen = 0;
-        ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
-        mInfoLog = new char[infoLogLen];
-        ShGetInfoLog(compiler, mInfoLog);
-
-        TRACE("\n%s", mInfoLog);
-    }
-}
-
-GLenum Shader::parseType(const std::string &type)
-{
-    if (type == "float")
-    {
-        return GL_FLOAT;
-    }
-    else if (type == "float2")
-    {
-        return GL_FLOAT_VEC2;
-    }
-    else if (type == "float3")
-    {
-        return GL_FLOAT_VEC3;
-    }
-    else if (type == "float4")
-    {
-        return GL_FLOAT_VEC4;
-    }
-    else if (type == "float2x2")
-    {
-        return GL_FLOAT_MAT2;
-    }
-    else if (type == "float3x3")
-    {
-        return GL_FLOAT_MAT3;
-    }
-    else if (type == "float4x4")
-    {
-        return GL_FLOAT_MAT4;
-    }
-    else UNREACHABLE();
-
-    return GL_NONE;
-}
-
-// true if varying x has a higher priority in packing than y
-bool Shader::compareVarying(const Varying &x, const Varying &y)
-{
-    if(x.type == y.type)
-    {
-        return x.size > y.size;
-    }
-
-    switch (x.type)
-    {
-      case GL_FLOAT_MAT4: return true;
-      case GL_FLOAT_MAT2:
-        switch(y.type)
-        {
-          case GL_FLOAT_MAT4: return false;
-          case GL_FLOAT_MAT2: return true;
-          case GL_FLOAT_VEC4: return true;
-          case GL_FLOAT_MAT3: return true;
-          case GL_FLOAT_VEC3: return true;
-          case GL_FLOAT_VEC2: return true;
-          case GL_FLOAT:      return true;
-          default: UNREACHABLE();
-        }
-        break;
-      case GL_FLOAT_VEC4:
-        switch(y.type)
-        {
-          case GL_FLOAT_MAT4: return false;
-          case GL_FLOAT_MAT2: return false;
-          case GL_FLOAT_VEC4: return true;
-          case GL_FLOAT_MAT3: return true;
-          case GL_FLOAT_VEC3: return true;
-          case GL_FLOAT_VEC2: return true;
-          case GL_FLOAT:      return true;
-          default: UNREACHABLE();
-        }
-        break;
-      case GL_FLOAT_MAT3:
-        switch(y.type)
-        {
-          case GL_FLOAT_MAT4: return false;
-          case GL_FLOAT_MAT2: return false;
-          case GL_FLOAT_VEC4: return false;
-          case GL_FLOAT_MAT3: return true;
-          case GL_FLOAT_VEC3: return true;
-          case GL_FLOAT_VEC2: return true;
-          case GL_FLOAT:      return true;
-          default: UNREACHABLE();
-        }
-        break;
-      case GL_FLOAT_VEC3:
-        switch(y.type)
-        {
-          case GL_FLOAT_MAT4: return false;
-          case GL_FLOAT_MAT2: return false;
-          case GL_FLOAT_VEC4: return false;
-          case GL_FLOAT_MAT3: return false;
-          case GL_FLOAT_VEC3: return true;
-          case GL_FLOAT_VEC2: return true;
-          case GL_FLOAT:      return true;
-          default: UNREACHABLE();
-        }
-        break;
-      case GL_FLOAT_VEC2:
-        switch(y.type)
-        {
-          case GL_FLOAT_MAT4: return false;
-          case GL_FLOAT_MAT2: return false;
-          case GL_FLOAT_VEC4: return false;
-          case GL_FLOAT_MAT3: return false;
-          case GL_FLOAT_VEC3: return false;
-          case GL_FLOAT_VEC2: return true;
-          case GL_FLOAT:      return true;
-          default: UNREACHABLE();
-        }
-        break;
-      case GL_FLOAT: return false;
-      default: UNREACHABLE();
-    }
-
-    return false;
-}
-
-VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
-    : Shader(manager, renderer, handle)
-{
-}
-
-VertexShader::~VertexShader()
-{
-}
-
-GLenum VertexShader::getType()
-{
-    return GL_VERTEX_SHADER;
-}
-
-void VertexShader::uncompile()
-{
-    Shader::uncompile();
-
-    // set by ParseAttributes
-    mAttributes.clear();
-}
-
-void VertexShader::compile()
-{
-    uncompile();
-
-    compileToHLSL(mVertexCompiler);
-    parseAttributes();
-    parseVaryings();
-}
-
-int VertexShader::getSemanticIndex(const std::string &attributeName)
-{
-    if (!attributeName.empty())
-    {
-        int semanticIndex = 0;
-        for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
-        {
-            if (attribute->name == attributeName)
-            {
-                return semanticIndex;
-            }
-
-            semanticIndex += VariableRowCount(attribute->type);
-        }
-    }
-
-    return -1;
-}
-
-void VertexShader::parseAttributes()
-{
-    const char *hlsl = getHLSL();
-    if (hlsl)
-    {
-        const char *input = strstr(hlsl, "// Attributes") + 14;
-
-        while(true)
-        {
-            char attributeType[256];
-            char attributeName[256];
-
-            int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
-
-            if (matches != 2)
-            {
-                break;
-            }
-
-            mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
-
-            input = strstr(input, ";") + 2;
-        }
-    }
-}
-
-FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
-    : Shader(manager, renderer, handle)
-{
-}
-
-FragmentShader::~FragmentShader()
-{
-}
-
-GLenum FragmentShader::getType()
-{
-    return GL_FRAGMENT_SHADER;
-}
-
-void FragmentShader::compile()
-{
-    uncompile();
-
-    compileToHLSL(mFragmentCompiler);
-    parseVaryings();
-    mVaryings.sort(compareVarying);
-}
-}
diff --git a/src/third_party/angle/src/libGLESv2/Shader.h b/src/third_party/angle/src/libGLESv2/Shader.h
deleted file mode 100644
index 2afe297..0000000
--- a/src/third_party/angle/src/libGLESv2/Shader.h
+++ /dev/null
@@ -1,184 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Shader.h: Defines the abstract gl::Shader class and its concrete derived
-// classes VertexShader and FragmentShader. Implements GL shader objects and
-// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section
-// 3.8 page 84.
-
-#ifndef LIBGLESV2_SHADER_H_
-#define LIBGLESV2_SHADER_H_
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-#include <string>
-#include <list>
-#include <vector>
-
-#include "compiler/Uniform.h"
-#include "common/angleutils.h"
-
-namespace rx
-{
-class Renderer;
-}
-
-namespace gl
-{
-class ResourceManager;
-
-struct Varying
-{
-    Varying(GLenum type, const std::string &name, int size, bool array)
-        : type(type), name(name), size(size), array(array), reg(-1), col(-1)
-    {
-    }
-
-    GLenum type;
-    std::string name;
-    int size;   // Number of 'type' elements
-    bool array;
-
-    int reg;    // First varying register, assigned during link
-    int col;    // First register element, assigned during link
-};
-
-typedef std::list<Varying> VaryingList;
-
-class Shader
-{
-    friend class ProgramBinary;
-
-  public:
-    Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle);
-
-    virtual ~Shader();
-
-    virtual GLenum getType() = 0;
-    GLuint getHandle() const;
-
-    void deleteSource();
-    void setSource(GLsizei count, const char **string, const GLint *length);
-    int getInfoLogLength() const;
-    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
-    int getSourceLength() const;
-    void getSource(GLsizei bufSize, GLsizei *length, char *buffer);
-    int getTranslatedSourceLength() const;
-    void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer);
-    const sh::ActiveUniforms &getUniforms();
-
-    virtual void compile() = 0;
-    virtual void uncompile();
-    bool isCompiled();
-    const char *getHLSL();
-
-    void addRef();
-    void release();
-    unsigned int getRefCount() const;
-    bool isFlaggedForDeletion() const;
-    void flagForDeletion();
-
-    static void releaseCompiler();
-
-  protected:
-    void parseVaryings();
-    void resetVaryingsRegisterAssignment();
-
-    void compileToHLSL(void *compiler);
-
-    void getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer);
-
-    static GLenum parseType(const std::string &type);
-    static bool compareVarying(const Varying &x, const Varying &y);
-
-    const rx::Renderer *const mRenderer;
-
-    VaryingList mVaryings;
-
-    bool mUsesMultipleRenderTargets;
-    bool mUsesFragColor;
-    bool mUsesFragData;
-    bool mUsesFragCoord;
-    bool mUsesFrontFacing;
-    bool mUsesPointSize;
-    bool mUsesPointCoord;
-    bool mUsesDepthRange;
-    bool mUsesFragDepth;
-
-    static void *mFragmentCompiler;
-    static void *mVertexCompiler;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Shader);
-
-    void initializeCompiler();
-
-    const GLuint mHandle;
-    unsigned int mRefCount;     // Number of program objects this shader is attached to
-    bool mDeleteStatus;         // Flag to indicate that the shader can be deleted when no longer in use
-
-    char *mSource;
-    char *mHlsl;
-    char *mInfoLog;
-    sh::ActiveUniforms mActiveUniforms;
-
-    ResourceManager *mResourceManager;
-};
-
-struct Attribute
-{
-    Attribute() : type(GL_NONE), name("")
-    {
-    }
-
-    Attribute(GLenum type, const std::string &name) : type(type), name(name)
-    {
-    }
-
-    GLenum type;
-    std::string name;
-};
-
-typedef std::vector<Attribute> AttributeArray;
-
-class VertexShader : public Shader
-{
-    friend class ProgramBinary;
-
-  public:
-    VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle);
-
-    ~VertexShader();
-
-    virtual GLenum getType();
-    virtual void compile();
-    virtual void uncompile();
-    int getSemanticIndex(const std::string &attributeName);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(VertexShader);
-
-    void parseAttributes();
-
-    AttributeArray mAttributes;
-};
-
-class FragmentShader : public Shader
-{
-  public:
-    FragmentShader(ResourceManager *manager,const rx::Renderer *renderer, GLuint handle);
-
-    ~FragmentShader();
-
-    virtual GLenum getType();
-    virtual void compile();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(FragmentShader);
-};
-}
-
-#endif   // LIBGLESV2_SHADER_H_
diff --git a/src/third_party/angle/src/libGLESv2/Texture.cpp b/src/third_party/angle/src/libGLESv2/Texture.cpp
deleted file mode 100644
index 4108a8f..0000000
--- a/src/third_party/angle/src/libGLESv2/Texture.cpp
+++ /dev/null
@@ -1,1537 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// 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/mathutil.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/renderer/Image.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/TextureStorage.h"
-#include "libEGL/Surface.h"
-
-namespace gl
-{
-
-#if defined(ANGLE_ENABLE_D3D11_STRICT)
-// D3DFMT_UNKNOWN is only available when compiling with D3D9 so we'll
-// define the value ourselves
-#define D3DFMT_UNKNOWN 0
-#endif
-
-Texture::Texture(rx::Renderer *renderer, GLuint id) : RefCountObject(id)
-{
-    mRenderer = renderer;
-
-    mSamplerState.minFilter = GL_NEAREST_MIPMAP_LINEAR;
-    mSamplerState.magFilter = GL_LINEAR;
-    mSamplerState.wrapS = GL_REPEAT;
-    mSamplerState.wrapT = GL_REPEAT;
-    mSamplerState.maxAnisotropy = 1.0f;
-    mSamplerState.lodOffset = 0;
-    mUsage = GL_NONE;
-    
-    mDirtyImages = true;
-
-    mImmutable = false;
-}
-
-Texture::~Texture()
-{
-}
-
-// Returns true on successful filter state update (valid enum parameter)
-bool Texture::setMinFilter(GLenum filter)
-{
-    switch (filter)
-    {
-      case GL_NEAREST:
-      case GL_LINEAR:
-      case GL_NEAREST_MIPMAP_NEAREST:
-      case GL_LINEAR_MIPMAP_NEAREST:
-      case GL_NEAREST_MIPMAP_LINEAR:
-      case GL_LINEAR_MIPMAP_LINEAR:
-        mSamplerState.minFilter = filter;
-        return true;
-      default:
-        return false;
-    }
-}
-
-// Returns true on successful filter state update (valid enum parameter)
-bool Texture::setMagFilter(GLenum filter)
-{
-    switch (filter)
-    {
-      case GL_NEAREST:
-      case GL_LINEAR:
-        mSamplerState.magFilter = filter;
-        return true;
-      default:
-        return false;
-    }
-}
-
-// Returns true on successful wrap state update (valid enum parameter)
-bool Texture::setWrapS(GLenum wrap)
-{
-    switch (wrap)
-    {
-      case GL_REPEAT:
-      case GL_CLAMP_TO_EDGE:
-      case GL_MIRRORED_REPEAT:
-        mSamplerState.wrapS = wrap;
-        return true;
-      default:
-        return false;
-    }
-}
-
-// Returns true on successful wrap state update (valid enum parameter)
-bool Texture::setWrapT(GLenum wrap)
-{
-    switch (wrap)
-    {
-      case GL_REPEAT:
-      case GL_CLAMP_TO_EDGE:
-      case GL_MIRRORED_REPEAT:
-        mSamplerState.wrapT = wrap;
-        return true;
-      default:
-        return false;
-    }
-}
-
-// Returns true on successful max anisotropy update (valid anisotropy value)
-bool Texture::setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy)
-{
-    textureMaxAnisotropy = std::min(textureMaxAnisotropy, contextMaxAnisotropy);
-    if (textureMaxAnisotropy < 1.0f)
-    {
-        return false;
-    }
-
-    mSamplerState.maxAnisotropy = textureMaxAnisotropy;
-
-    return true;
-}
-
-// Returns true on successful usage state update (valid enum parameter)
-bool Texture::setUsage(GLenum usage)
-{
-    switch (usage)
-    {
-      case GL_NONE:
-      case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
-        mUsage = usage;
-        return true;
-      default:
-        return false;
-    }
-}
-
-GLenum Texture::getMinFilter() const
-{
-    return mSamplerState.minFilter;
-}
-
-GLenum Texture::getMagFilter() const
-{
-    return mSamplerState.magFilter;
-}
-
-GLenum Texture::getWrapS() const
-{
-    return mSamplerState.wrapS;
-}
-
-GLenum Texture::getWrapT() const
-{
-    return mSamplerState.wrapT;
-}
-
-float Texture::getMaxAnisotropy() const
-{
-    return mSamplerState.maxAnisotropy;
-}
-
-int Texture::getLodOffset()
-{
-    rx::TextureStorageInterface *texture = getStorage(false);
-    return texture ? texture->getLodOffset() : 0;
-}
-
-void Texture::getSamplerState(SamplerState *sampler)
-{
-    *sampler = mSamplerState;
-    sampler->lodOffset = getLodOffset();
-}
-
-GLenum Texture::getUsage() const
-{
-    return mUsage;
-}
-
-bool Texture::isMipmapFiltered() const
-{
-    switch (mSamplerState.minFilter)
-    {
-      case GL_NEAREST:
-      case GL_LINEAR:
-        return false;
-      case GL_NEAREST_MIPMAP_NEAREST:
-      case GL_LINEAR_MIPMAP_NEAREST:
-      case GL_NEAREST_MIPMAP_LINEAR:
-      case GL_LINEAR_MIPMAP_LINEAR:
-        return true;
-      default: UNREACHABLE();
-        return false;
-    }
-}
-
-void Texture::setImage(GLint unpackAlignment, const void *pixels, rx::Image *image)
-{
-    if (pixels != NULL)
-    {
-        image->loadData(0, 0, image->getWidth(), image->getHeight(), unpackAlignment, pixels);
-        mDirtyImages = true;
-    }
-}
-
-void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image)
-{
-    if (pixels != NULL)
-    {
-        image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), pixels);
-        mDirtyImages = true;
-    }
-}
-
-bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image)
-{
-    if (pixels != NULL)
-    {
-        image->loadData(xoffset, yoffset, width, height, unpackAlignment, pixels);
-        mDirtyImages = true;
-    }
-
-    return true;
-}
-
-bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image)
-{
-    if (pixels != NULL)
-    {
-        image->loadCompressedData(xoffset, yoffset, width, height, pixels);
-        mDirtyImages = true;
-    }
-
-    return true;
-}
-
-rx::TextureStorageInterface *Texture::getNativeTexture()
-{
-    // ensure the underlying texture is created
-
-    rx::TextureStorageInterface *storage = getStorage(false);
-    if (storage)
-    {
-        updateTexture();
-    }
-
-    return storage;
-}
-
-bool Texture::hasDirtyImages() const
-{
-    return mDirtyImages;
-}
-
-void Texture::resetDirty()
-{
-    mDirtyImages = false;
-}
-
-unsigned int Texture::getTextureSerial()
-{
-    rx::TextureStorageInterface *texture = getStorage(false);
-    return texture ? texture->getTextureSerial() : 0;
-}
-
-unsigned int Texture::getRenderTargetSerial(GLenum target)
-{
-    rx::TextureStorageInterface *texture = getStorage(true);
-    return texture ? texture->getRenderTargetSerial(target) : 0;
-}
-
-bool Texture::isImmutable() const
-{
-    return mImmutable;
-}
-
-GLint Texture::creationLevels(GLsizei width, GLsizei height) const
-{
-    if ((isPow2(width) && isPow2(height)) || mRenderer->getNonPower2TextureSupport())
-    {
-        return 0;   // Maximum number of levels
-    }
-    else
-    {
-        // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
-        return 1;
-    }
-}
-
-GLint Texture::creationLevels(GLsizei size) const
-{
-    return creationLevels(size, size);
-}
-
-Texture2D::Texture2D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id)
-{
-    mTexStorage = NULL;
-    mSurface = NULL;
-    mColorbufferProxy = NULL;
-    mProxyRefs = 0;
-
-    for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
-    {
-        mImageArray[i] = renderer->createImage();
-    }
-}
-
-Texture2D::~Texture2D()
-{
-    mColorbufferProxy = NULL;
-
-    delete mTexStorage;
-    mTexStorage = NULL;
-    
-    if (mSurface)
-    {
-        mSurface->setBoundTexture(NULL);
-        mSurface = NULL;
-    }
-
-    for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
-    {
-        delete mImageArray[i];
-    }
-}
-
-// We need to maintain a count of references to renderbuffers acting as 
-// proxies for this texture, so that we do not attempt to use a pointer 
-// to a renderbuffer proxy which has been deleted.
-void Texture2D::addProxyRef(const Renderbuffer *proxy)
-{
-    mProxyRefs++;
-}
-
-void Texture2D::releaseProxy(const Renderbuffer *proxy)
-{
-    if (mProxyRefs > 0)
-        mProxyRefs--;
-
-    if (mProxyRefs == 0)
-        mColorbufferProxy = NULL;
-}
-
-GLenum Texture2D::getTarget() const
-{
-    return GL_TEXTURE_2D;
-}
-
-GLsizei Texture2D::getWidth(GLint level) const
-{
-    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
-        return mImageArray[level]->getWidth();
-    else
-        return 0;
-}
-
-GLsizei Texture2D::getHeight(GLint level) const
-{
-    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
-        return mImageArray[level]->getHeight();
-    else
-        return 0;
-}
-
-GLenum Texture2D::getInternalFormat(GLint level) const
-{
-    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
-        return mImageArray[level]->getInternalFormat();
-    else
-        return GL_NONE;
-}
-
-GLenum Texture2D::getActualFormat(GLint level) const
-{
-    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
-        return mImageArray[level]->getActualFormat();
-    else
-        return D3DFMT_UNKNOWN;
-}
-
-void Texture2D::redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height)
-{
-    releaseTexImage();
-
-    // If there currently is a corresponding storage texture image, it has these parameters
-    const int storageWidth = std::max(1, mImageArray[0]->getWidth() >> level);
-    const int storageHeight = std::max(1, mImageArray[0]->getHeight() >> level);
-    const int storageFormat = mImageArray[0]->getInternalFormat();
-
-    mImageArray[level]->redefine(mRenderer, internalformat, width, height, false);
-
-    if (mTexStorage)
-    {
-        const int storageLevels = mTexStorage->levelCount();
-        
-        if ((level >= storageLevels && storageLevels != 0) ||
-            width != storageWidth ||
-            height != storageHeight ||
-            internalformat != storageFormat)   // Discard mismatched storage
-        {
-            for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-            {
-                mImageArray[i]->markDirty();
-            }
-
-            delete mTexStorage;
-            mTexStorage = NULL;
-            mDirtyImages = true;
-        }
-    }
-}
-
-#if defined(__LB_XB360__)
-void Texture2D::adoptStorage(GLenum internalformat, GLsizei width, GLsizei height, rx::TextureStorage *storage)
-{
-    ASSERT(storage != NULL);
-
-    delete mTexStorage;
-    mTexStorage = new rx::TextureStorageInterface2D(storage);
-    mImmutable = true;
-
-    int levels = mTexStorage->levelCount();
-    ASSERT(levels == 1);
-
-    // TODO: Avoid allocating these images.
-    for (int level = 0; level < levels; level++)
-    {
-        mImageArray[level]->redefine(mRenderer, internalformat, width, height, true);
-        width = std::max(1, width >> 1);
-        height = std::max(1, height >> 1);
-    }
-
-    for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
-    {
-        mImageArray[level]->redefine(mRenderer, GL_NONE, 0, 0, true);
-    }
-
-    if (mTexStorage->isManaged())
-    {
-        int levels = levelCount();
-
-        for (int level = 0; level < levels; level++)
-        {
-            mImageArray[level]->setManagedSurface(mTexStorage, level);
-        }
-    }
-}
-#endif
-
-void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    GLint internalformat = ConvertSizedInternalFormat(format, type);
-    redefineImage(level, internalformat, width, height);
-
-    Texture::setImage(unpackAlignment, pixels, mImageArray[level]);
-}
-
-void Texture2D::bindTexImage(egl::Surface *surface)
-{
-    releaseTexImage();
-
-    GLint internalformat = surface->getFormat();
-
-    mImageArray[0]->redefine(mRenderer, internalformat, surface->getWidth(), surface->getHeight(), true);
-
-    delete mTexStorage;
-    mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain());
-
-    mDirtyImages = true;
-    mSurface = surface;
-    mSurface->setBoundTexture(this);
-}
-
-void Texture2D::releaseTexImage()
-{
-    if (mSurface)
-    {
-        mSurface->setBoundTexture(NULL);
-        mSurface = NULL;
-
-        if (mTexStorage)
-        {
-            delete mTexStorage;
-            mTexStorage = NULL;
-        }
-
-        for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-        {
-            mImageArray[i]->redefine(mRenderer, GL_NONE, 0, 0, true);
-        }
-    }
-}
-
-void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
-{
-    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
-    redefineImage(level, format, width, height);
-
-    Texture::setCompressedImage(imageSize, pixels, mImageArray[level]);
-}
-
-void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
-    if (level < levelCount())
-    {
-        rx::Image *image = mImageArray[level];
-        if (image->updateSurface(mTexStorage, level, xoffset, yoffset, width, height))
-        {
-            image->markClean();
-        }
-    }
-}
-
-void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[level]))
-    {
-        commitRect(level, xoffset, yoffset, width, height);
-    }
-}
-
-void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
-{
-    if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[level]))
-    {
-        commitRect(level, xoffset, yoffset, width, height);
-    }
-}
-
-void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
-{
-    GLint internalformat = ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE);
-    redefineImage(level, internalformat, width, height);
-
-    if (!mImageArray[level]->isRenderableFormat())
-    {
-        mImageArray[level]->copy(0, 0, x, y, width, height, source);
-        mDirtyImages = true;
-    }
-    else
-    {
-        if (!mTexStorage || !mTexStorage->isRenderTarget())
-        {
-            convertToRenderTarget();
-        }
-        
-        mImageArray[level]->markClean();
-
-        if (width != 0 && height != 0 && level < levelCount())
-        {
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
-
-            mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level);
-        }
-    }
-}
-
-void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
-{
-    if (xoffset + width > mImageArray[level]->getWidth() || yoffset + height > mImageArray[level]->getHeight())
-    {
-        return gl::error(GL_INVALID_VALUE);
-    }
-
-    if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
-    {
-        mImageArray[level]->copy(xoffset, yoffset, x, y, width, height, source);
-        mDirtyImages = true;
-    }
-    else
-    {
-        if (!mTexStorage || !mTexStorage->isRenderTarget())
-        {
-            convertToRenderTarget();
-        }
-        
-        updateTexture();
-
-        if (level < levelCount())
-        {
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
-
-            mRenderer->copyImage(source, sourceRect, 
-                                 gl::ExtractFormat(mImageArray[0]->getInternalFormat()),
-                                 xoffset, yoffset, mTexStorage, level);
-        }
-    }
-}
-
-void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
-{
-    delete mTexStorage;
-    mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height);
-    mImmutable = true;
-
-    for (int level = 0; level < levels; level++)
-    {
-        mImageArray[level]->redefine(mRenderer, internalformat, width, height, true);
-        width = std::max(1, width >> 1);
-        height = std::max(1, height >> 1);
-    }
-
-    for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
-    {
-        mImageArray[level]->redefine(mRenderer, GL_NONE, 0, 0, true);
-    }
-
-    if (mTexStorage->isManaged())
-    {
-        int levels = levelCount();
-
-        for (int level = 0; level < levels; level++)
-        {
-            mImageArray[level]->setManagedSurface(mTexStorage, level);
-        }
-    }
-}
-
-// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
-bool Texture2D::isSamplerComplete() const
-{
-    GLsizei width = mImageArray[0]->getWidth();
-    GLsizei height = mImageArray[0]->getHeight();
-
-    if (width <= 0 || height <= 0)
-    {
-        return false;
-    }
-
-    bool mipmapping = isMipmapFiltered();
-    bool filtering, renderable;
-
-    if ((IsFloat32Format(getInternalFormat(0)) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
-        (IsFloat16Format(getInternalFormat(0)) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
-    {
-        if (mSamplerState.magFilter != GL_NEAREST ||
-            (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
-        {
-            return false;
-        }
-    }
-
-    bool npotSupport = mRenderer->getNonPower2TextureSupport();
-
-    if (!npotSupport)
-    {
-        if ((mSamplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
-            (mSamplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(height)))
-        {
-            return false;
-        }
-    }
-
-    if (mipmapping)
-    {
-        if (!npotSupport)
-        {
-            if (!isPow2(width) || !isPow2(height))
-            {
-                return false;
-            }
-        }
-
-        if (!isMipmapComplete())
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool Texture2D::isMipmapComplete() const
-{
-    if (isImmutable())
-    {
-        return true;
-    }
-
-    GLsizei width = mImageArray[0]->getWidth();
-    GLsizei height = mImageArray[0]->getHeight();
-
-    if (width <= 0 || height <= 0)
-    {
-        return false;
-    }
-
-    int q = log2(std::max(width, height));
-
-    for (int level = 1; level <= q; level++)
-    {
-        if (mImageArray[level]->getInternalFormat() != mImageArray[0]->getInternalFormat())
-        {
-            return false;
-        }
-
-        if (mImageArray[level]->getWidth() != std::max(1, width >> level))
-        {
-            return false;
-        }
-
-        if (mImageArray[level]->getHeight() != std::max(1, height >> level))
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-bool Texture2D::isCompressed(GLint level) const
-{
-    return IsCompressed(getInternalFormat(level));
-}
-
-bool Texture2D::isDepth(GLint level) const
-{
-    return IsDepthTexture(getInternalFormat(level));
-}
-
-// Constructs a native texture resource from the texture images
-void Texture2D::createTexture()
-{
-    GLsizei width = mImageArray[0]->getWidth();
-    GLsizei height = mImageArray[0]->getHeight();
-
-    if (!(width > 0 && height > 0))
-        return; // do not attempt to create native textures for nonexistant data
-
-    GLint levels = creationLevels(width, height);
-    GLenum internalformat = mImageArray[0]->getInternalFormat();
-
-    delete mTexStorage;
-    mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height);
-    
-    if (mTexStorage->isManaged())
-    {
-        int levels = levelCount();
-
-        for (int level = 0; level < levels; level++)
-        {
-            mImageArray[level]->setManagedSurface(mTexStorage, level);
-        }
-    }
-
-    mDirtyImages = true;
-}
-
-void Texture2D::updateTexture()
-{
-    bool mipmapping = (isMipmapFiltered() && isMipmapComplete());
-
-    int levels = (mipmapping ? levelCount() : 1);
-
-    for (int level = 0; level < levels; level++)
-    {
-        rx::Image *image = mImageArray[level];
-
-        if (image->isDirty())
-        {
-            commitRect(level, 0, 0, mImageArray[level]->getWidth(), mImageArray[level]->getHeight());
-        }
-    }
-}
-
-void Texture2D::convertToRenderTarget()
-{
-    rx::TextureStorageInterface2D *newTexStorage = NULL;
-
-    if (mImageArray[0]->getWidth() != 0 && mImageArray[0]->getHeight() != 0)
-    {
-        GLsizei width = mImageArray[0]->getWidth();
-        GLsizei height = mImageArray[0]->getHeight();
-        GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(width, height);
-        GLenum internalformat = mImageArray[0]->getInternalFormat();
-
-        newTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, width, height);
-
-        if (mTexStorage != NULL)
-        {
-            if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage))
-            {   
-                delete newTexStorage;
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-        }
-    }
-
-    delete mTexStorage;
-    mTexStorage = newTexStorage;
-
-    mDirtyImages = true;
-}
-
-void Texture2D::generateMipmaps()
-{
-    if (!mRenderer->getNonPower2TextureSupport())
-    {
-        if (!isPow2(mImageArray[0]->getWidth()) || !isPow2(mImageArray[0]->getHeight()))
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
-    }
-
-    // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
-    unsigned int q = log2(std::max(mImageArray[0]->getWidth(), mImageArray[0]->getHeight()));
-    for (unsigned int i = 1; i <= q; i++)
-    {
-        redefineImage(i, mImageArray[0]->getInternalFormat(),
-                      std::max(mImageArray[0]->getWidth() >> i, 1),
-                      std::max(mImageArray[0]->getHeight() >> i, 1));
-    }
-
-    if (mTexStorage && mTexStorage->isRenderTarget())
-    {
-        for (unsigned int i = 1; i <= q; i++)
-        {
-            mTexStorage->generateMipmap(i);
-
-            mImageArray[i]->markClean();
-        }
-    }
-    else
-    {
-        for (unsigned int i = 1; i <= q; i++)
-        {
-            mRenderer->generateMipmap(mImageArray[i], mImageArray[i - 1]);
-        }
-    }
-}
-
-Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
-{
-    if (target != GL_TEXTURE_2D)
-    {
-        return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
-    }
-
-    if (mColorbufferProxy == NULL)
-    {
-        mColorbufferProxy = new Renderbuffer(mRenderer, id(), new RenderbufferTexture2D(this, target));
-    }
-
-    return mColorbufferProxy;
-}
-
-rx::RenderTarget *Texture2D::getRenderTarget(GLenum target)
-{
-    ASSERT(target == GL_TEXTURE_2D);
-
-    // ensure the underlying texture is created
-    if (getStorage(true) == NULL)
-    {
-        return NULL;
-    }
-
-    updateTexture();
-    
-    // ensure this is NOT a depth texture
-    if (isDepth(0))
-    {
-        return NULL;
-    }
-
-    return mTexStorage->getRenderTarget();
-}
-
-rx::RenderTarget *Texture2D::getDepthStencil(GLenum target)
-{
-    ASSERT(target == GL_TEXTURE_2D);
-
-    // ensure the underlying texture is created
-    if (getStorage(true) == NULL)
-    {
-        return NULL;
-    }
-
-    updateTexture();
-
-    // ensure this is actually a depth texture
-    if (!isDepth(0))
-    {
-        return NULL;
-    }
-    return mTexStorage->getRenderTarget();
-}
-
-int Texture2D::levelCount()
-{
-    return mTexStorage ? mTexStorage->levelCount() : 0;
-}
-
-rx::TextureStorageInterface *Texture2D::getStorage(bool renderTarget)
-{
-    if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
-    {
-        if (renderTarget)
-        {
-            convertToRenderTarget();
-        }
-        else
-        {
-            createTexture();
-        }
-    }
-
-    return mTexStorage;
-}
-
-TextureCubeMap::TextureCubeMap(rx::Renderer *renderer, GLuint id) : Texture(renderer, id)
-{
-    mTexStorage = NULL;
-    for (int i = 0; i < 6; i++)
-    {
-        mFaceProxies[i] = NULL;
-        mFaceProxyRefs[i] = 0;
-
-        for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
-        {
-            mImageArray[i][j] = renderer->createImage();
-        }
-    }
-}
-
-TextureCubeMap::~TextureCubeMap()
-{
-    for (int i = 0; i < 6; i++)
-    {
-        mFaceProxies[i] = NULL;
-
-        for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
-        {
-            delete mImageArray[i][j];
-        }
-    }
-
-    delete mTexStorage;
-    mTexStorage = NULL;
-}
-
-// We need to maintain a count of references to renderbuffers acting as 
-// proxies for this texture, so that the texture is not deleted while 
-// proxy references still exist. If the reference count drops to zero,
-// we set our proxy pointer NULL, so that a new attempt at referencing
-// will cause recreation.
-void TextureCubeMap::addProxyRef(const Renderbuffer *proxy)
-{
-    for (int i = 0; i < 6; i++)
-    {
-        if (mFaceProxies[i] == proxy)
-            mFaceProxyRefs[i]++;
-    }
-}
-
-void TextureCubeMap::releaseProxy(const Renderbuffer *proxy)
-{
-    for (int i = 0; i < 6; i++)
-    {
-        if (mFaceProxies[i] == proxy)
-        {
-            if (mFaceProxyRefs[i] > 0)
-                mFaceProxyRefs[i]--;
-
-            if (mFaceProxyRefs[i] == 0)
-                mFaceProxies[i] = NULL;
-        }
-    }
-}
-
-GLenum TextureCubeMap::getTarget() const
-{
-    return GL_TEXTURE_CUBE_MAP;
-}
-
-GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
-{
-    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
-        return mImageArray[faceIndex(target)][level]->getWidth();
-    else
-        return 0;
-}
-
-GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
-{
-    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
-        return mImageArray[faceIndex(target)][level]->getHeight();
-    else
-        return 0;
-}
-
-GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
-{
-    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
-        return mImageArray[faceIndex(target)][level]->getInternalFormat();
-    else
-        return GL_NONE;
-}
-
-GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
-{
-    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
-        return mImageArray[faceIndex(target)][level]->getActualFormat();
-    else
-        return D3DFMT_UNKNOWN;
-}
-
-void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    setImage(0, level, width, height, format, type, unpackAlignment, pixels);
-}
-
-void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    setImage(1, level, width, height, format, type, unpackAlignment, pixels);
-}
-
-void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    setImage(2, level, width, height, format, type, unpackAlignment, pixels);
-}
-
-void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    setImage(3, level, width, height, format, type, unpackAlignment, pixels);
-}
-
-void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    setImage(4, level, width, height, format, type, unpackAlignment, pixels);
-}
-
-void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    setImage(5, level, width, height, format, type, unpackAlignment, pixels);
-}
-
-void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
-{
-    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
-    redefineImage(faceIndex(face), level, format, width, height);
-
-    Texture::setCompressedImage(imageSize, pixels, mImageArray[faceIndex(face)][level]);
-}
-
-void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
-    if (level < levelCount())
-    {
-        rx::Image *image = mImageArray[face][level];
-        if (image->updateSurface(mTexStorage, face, level, xoffset, yoffset, width, height))
-            image->markClean();
-    }
-}
-
-void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[faceIndex(target)][level]))
-    {
-        commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
-    }
-}
-
-void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
-{
-    if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[faceIndex(target)][level]))
-    {
-        commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
-    }
-}
-
-// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.
-bool TextureCubeMap::isSamplerComplete() const
-{
-    int size = mImageArray[0][0]->getWidth();
-
-    bool mipmapping = isMipmapFiltered();
-    bool filtering, renderable;
-
-    if ((gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) == GL_FLOAT && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
-        (gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_HALF_FLOAT_OES) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
-    {
-        if (mSamplerState.magFilter != GL_NEAREST ||
-            (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
-        {
-            return false;
-        }
-    }
-
-    if (!isPow2(size) && !mRenderer->getNonPower2TextureSupport())
-    {
-        if (mSamplerState.wrapS != GL_CLAMP_TO_EDGE || mSamplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
-        {
-            return false;
-        }
-    }
-
-    if (!mipmapping)
-    {
-        if (!isCubeComplete())
-        {
-            return false;
-        }
-    }
-    else
-    {
-        if (!isMipmapCubeComplete())   // Also tests for isCubeComplete()
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool TextureCubeMap::isCubeComplete() const
-{
-    if (mImageArray[0][0]->getWidth() <= 0 || mImageArray[0][0]->getHeight() != mImageArray[0][0]->getWidth())
-    {
-        return false;
-    }
-
-    for (unsigned int face = 1; face < 6; face++)
-    {
-        if (mImageArray[face][0]->getWidth() != mImageArray[0][0]->getWidth() ||
-            mImageArray[face][0]->getWidth() != mImageArray[0][0]->getHeight() ||
-            mImageArray[face][0]->getInternalFormat() != mImageArray[0][0]->getInternalFormat())
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-bool TextureCubeMap::isMipmapCubeComplete() const
-{
-    if (isImmutable())
-    {
-        return true;
-    }
-
-    if (!isCubeComplete())
-    {
-        return false;
-    }
-
-    GLsizei size = mImageArray[0][0]->getWidth();
-
-    int q = log2(size);
-
-    for (int face = 0; face < 6; face++)
-    {
-        for (int level = 1; level <= q; level++)
-        {
-            if (mImageArray[face][level]->getInternalFormat() != mImageArray[0][0]->getInternalFormat())
-            {
-                return false;
-            }
-
-            if (mImageArray[face][level]->getWidth() != std::max(1, size >> level))
-            {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
-{
-    return IsCompressed(getInternalFormat(target, level));
-}
-
-// Constructs a native texture resource from the texture images, or returns an existing one
-void TextureCubeMap::createTexture()
-{
-    GLsizei size = mImageArray[0][0]->getWidth();
-
-    if (!(size > 0))
-        return; // do not attempt to create native textures for nonexistant data
-
-    GLint levels = creationLevels(size);
-    GLenum internalformat = mImageArray[0][0]->getInternalFormat();
-
-    delete mTexStorage;
-    mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size);
-
-    if (mTexStorage->isManaged())
-    {
-        int levels = levelCount();
-
-        for (int face = 0; face < 6; face++)
-        {
-            for (int level = 0; level < levels; level++)
-            {
-                mImageArray[face][level]->setManagedSurface(mTexStorage, face, level);
-            }
-        }
-    }
-
-    mDirtyImages = true;
-}
-
-void TextureCubeMap::updateTexture()
-{
-    bool mipmapping = isMipmapFiltered() && isMipmapCubeComplete();
-
-    for (int face = 0; face < 6; face++)
-    {
-        int levels = (mipmapping ? levelCount() : 1);
-
-        for (int level = 0; level < levels; level++)
-        {
-            rx::Image *image = mImageArray[face][level];
-
-            if (image->isDirty())
-            {
-                commitRect(face, level, 0, 0, image->getWidth(), image->getHeight());
-            }
-        }
-    }
-}
-
-void TextureCubeMap::convertToRenderTarget()
-{
-    rx::TextureStorageInterfaceCube *newTexStorage = NULL;
-
-    if (mImageArray[0][0]->getWidth() != 0)
-    {
-        GLsizei size = mImageArray[0][0]->getWidth();
-        GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(size);
-        GLenum internalformat = mImageArray[0][0]->getInternalFormat();
-
-        newTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, size);
-
-        if (mTexStorage != NULL)
-        {
-            if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage))
-            {
-                delete newTexStorage;
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-        }
-    }
-
-    delete mTexStorage;
-    mTexStorage = newTexStorage;
-
-    mDirtyImages = true;
-}
-
-void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
-    GLint internalformat = ConvertSizedInternalFormat(format, type);
-    redefineImage(faceIndex, level, internalformat, width, height);
-
-    Texture::setImage(unpackAlignment, pixels, mImageArray[faceIndex][level]);
-}
-
-unsigned int TextureCubeMap::faceIndex(GLenum face)
-{
-    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);
-
-    return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
-}
-
-void TextureCubeMap::redefineImage(int face, GLint level, GLint internalformat, GLsizei width, GLsizei height)
-{
-    // If there currently is a corresponding storage texture image, it has these parameters
-    const int storageWidth = std::max(1, mImageArray[0][0]->getWidth() >> level);
-    const int storageHeight = std::max(1, mImageArray[0][0]->getHeight() >> level);
-    const int storageFormat = mImageArray[0][0]->getInternalFormat();
-
-    mImageArray[face][level]->redefine(mRenderer, internalformat, width, height, false);
-
-    if (mTexStorage)
-    {
-        const int storageLevels = mTexStorage->levelCount();
-        
-        if ((level >= storageLevels && storageLevels != 0) ||
-            width != storageWidth ||
-            height != storageHeight ||
-            internalformat != storageFormat)   // Discard mismatched storage
-        {
-            for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-            {
-                for (int f = 0; f < 6; f++)
-                {
-                    mImageArray[f][i]->markDirty();
-                }
-            }
-
-            delete mTexStorage;
-            mTexStorage = NULL;
-
-            mDirtyImages = true;
-        }
-    }
-}
-
-void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
-{
-    unsigned int faceindex = faceIndex(target);
-    GLint internalformat = gl::ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE);
-    redefineImage(faceindex, level, internalformat, width, height);
-
-    if (!mImageArray[faceindex][level]->isRenderableFormat())
-    {
-        mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source);
-        mDirtyImages = true;
-    }
-    else
-    {
-        if (!mTexStorage || !mTexStorage->isRenderTarget())
-        {
-            convertToRenderTarget();
-        }
-        
-        mImageArray[faceindex][level]->markClean();
-
-        ASSERT(width == height);
-
-        if (width > 0 && level < levelCount())
-        {
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
-
-            mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level);
-        }
-    }
-}
-
-void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
-{
-    GLsizei size = mImageArray[faceIndex(target)][level]->getWidth();
-
-    if (xoffset + width > size || yoffset + height > size)
-    {
-        return gl::error(GL_INVALID_VALUE);
-    }
-
-    unsigned int faceindex = faceIndex(target);
-
-    if (!mImageArray[faceindex][level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
-    {
-        mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source);
-        mDirtyImages = true;
-    }
-    else
-    {
-        if (!mTexStorage || !mTexStorage->isRenderTarget())
-        {
-            convertToRenderTarget();
-        }
-        
-        updateTexture();
-
-        if (level < levelCount())
-        {
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
-
-            mRenderer->copyImage(source, sourceRect, gl::ExtractFormat(mImageArray[0][0]->getInternalFormat()), 
-                                 xoffset, yoffset, mTexStorage, target, level);
-        }
-    }
-}
-
-void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
-{
-    delete mTexStorage;
-    mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size);
-    mImmutable = true;
-
-    for (int level = 0; level < levels; level++)
-    {
-        for (int face = 0; face < 6; face++)
-        {
-            mImageArray[face][level]->redefine(mRenderer, internalformat, size, size, true);
-            size = std::max(1, size >> 1);
-        }
-    }
-
-    for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
-    {
-        for (int face = 0; face < 6; face++)
-        {
-            mImageArray[face][level]->redefine(mRenderer, GL_NONE, 0, 0, true);
-        }
-    }
-
-    if (mTexStorage->isManaged())
-    {
-        int levels = levelCount();
-
-        for (int face = 0; face < 6; face++)
-        {
-            for (int level = 0; level < levels; level++)
-            {
-                mImageArray[face][level]->setManagedSurface(mTexStorage, face, level);
-            }
-        }
-    }
-}
-
-void TextureCubeMap::generateMipmaps()
-{
-    if (!isCubeComplete())
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    if (!mRenderer->getNonPower2TextureSupport())
-    {
-        if (!isPow2(mImageArray[0][0]->getWidth()))
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
-    }
-
-    // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
-    unsigned int q = log2(mImageArray[0][0]->getWidth());
-    for (unsigned int f = 0; f < 6; f++)
-    {
-        for (unsigned int i = 1; i <= q; i++)
-        {
-            redefineImage(f, i, mImageArray[f][0]->getInternalFormat(),
-                          std::max(mImageArray[f][0]->getWidth() >> i, 1),
-                          std::max(mImageArray[f][0]->getWidth() >> i, 1));
-        }
-    }
-
-    if (mTexStorage && mTexStorage->isRenderTarget())
-    {
-        for (unsigned int f = 0; f < 6; f++)
-        {
-            for (unsigned int i = 1; i <= q; i++)
-            {
-                mTexStorage->generateMipmap(f, i);
-
-                mImageArray[f][i]->markClean();
-            }
-        }
-    }
-    else
-    {
-        for (unsigned int f = 0; f < 6; f++)
-        {
-            for (unsigned int i = 1; i <= q; i++)
-            {
-                mRenderer->generateMipmap(mImageArray[f][i], mImageArray[f][i - 1]);
-            }
-        }
-    }
-}
-
-Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
-{
-    if (!IsCubemapTextureTarget(target))
-    {
-        return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
-    }
-
-    unsigned int face = faceIndex(target);
-
-    if (mFaceProxies[face] == NULL)
-    {
-        mFaceProxies[face] = new Renderbuffer(mRenderer, id(), new RenderbufferTextureCubeMap(this, target));
-    }
-
-    return mFaceProxies[face];
-}
-
-rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target)
-{
-    ASSERT(IsCubemapTextureTarget(target));
-
-    // ensure the underlying texture is created
-    if (getStorage(true) == NULL)
-    {
-        return NULL;
-    }
-
-    updateTexture();
-    
-    return mTexStorage->getRenderTarget(target);
-}
-
-int TextureCubeMap::levelCount()
-{
-    return mTexStorage ? mTexStorage->levelCount() - getLodOffset() : 0;
-}
-
-rx::TextureStorageInterface *TextureCubeMap::getStorage(bool renderTarget)
-{
-    if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
-    {
-        if (renderTarget)
-        {
-            convertToRenderTarget();
-        }
-        else
-        {
-            createTexture();
-        }
-    }
-
-    return mTexStorage;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/Texture.h b/src/third_party/angle/src/libGLESv2/Texture.h
deleted file mode 100644
index 35b024c..0000000
--- a/src/third_party/angle/src/libGLESv2/Texture.h
+++ /dev/null
@@ -1,283 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Texture.h: Defines the abstract gl::Texture class and its concrete derived
-// classes Texture2D and TextureCubeMap. Implements GL texture objects and
-// related functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
-
-#ifndef LIBGLESV2_TEXTURE_H_
-#define LIBGLESV2_TEXTURE_H_
-
-#include <vector>
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
-#include "common/debug.h"
-#include "common/RefCountObject.h"
-#include "libGLESv2/angletypes.h"
-
-namespace egl
-{
-class Surface;
-}
-
-namespace rx
-{
-class Renderer;
-class TextureStorage;
-class TextureStorageInterface;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
-class RenderTarget;
-class Image;
-}
-
-namespace gl
-{
-class Framebuffer;
-class Renderbuffer;
-
-enum
-{
-    // These are the maximums the implementation can support
-    // The actual GL caps are limited by the device caps
-    // and should be queried from the Context
-    IMPLEMENTATION_MAX_TEXTURE_SIZE = 16384,
-    IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
-
-    IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15   // 1+log2 of MAX_TEXTURE_SIZE
-};
-
-class Texture : public RefCountObject
-{
-  public:
-    Texture(rx::Renderer *renderer, GLuint id);
-
-    virtual ~Texture();
-
-    virtual void addProxyRef(const Renderbuffer *proxy) = 0;
-    virtual void releaseProxy(const Renderbuffer *proxy) = 0;
-
-    virtual GLenum getTarget() const = 0;
-
-    bool setMinFilter(GLenum filter);
-    bool setMagFilter(GLenum filter);
-    bool setWrapS(GLenum wrap);
-    bool setWrapT(GLenum wrap);
-    bool setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy);
-    bool setUsage(GLenum usage);
-
-    GLenum getMinFilter() const;
-    GLenum getMagFilter() const;
-    GLenum getWrapS() const;
-    GLenum getWrapT() const;
-    float getMaxAnisotropy() const;
-    int getLodOffset();
-    void getSamplerState(SamplerState *sampler);
-    GLenum getUsage() const;
-    bool isMipmapFiltered() const;
-
-    virtual bool isSamplerComplete() const = 0;
-
-    rx::TextureStorageInterface *getNativeTexture();
-    virtual Renderbuffer *getRenderbuffer(GLenum target) = 0;
-
-    virtual void generateMipmaps() = 0;
-    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0;
-
-    bool hasDirtyParameters() const;
-    bool hasDirtyImages() const;
-    void resetDirty();
-    unsigned int getTextureSerial();
-    unsigned int getRenderTargetSerial(GLenum target);
-
-    bool isImmutable() const;
-
-    static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1);   // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
-
-  protected:
-    void setImage(GLint unpackAlignment, const void *pixels, rx::Image *image);
-    bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image);
-    void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image);
-    bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image);
-
-    GLint creationLevels(GLsizei width, GLsizei height) const;
-    GLint creationLevels(GLsizei size) const;
-
-    virtual void createTexture() = 0;
-    virtual void updateTexture() = 0;
-    virtual void convertToRenderTarget() = 0;
-    virtual rx::RenderTarget *getRenderTarget(GLenum target) = 0;
-
-    virtual int levelCount() = 0;
-
-    rx::Renderer *mRenderer;
-
-    SamplerState mSamplerState;
-    GLenum mUsage;
-
-    bool mDirtyImages;
-
-    bool mImmutable;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Texture);
-
-    virtual rx::TextureStorageInterface *getStorage(bool renderTarget) = 0;
-};
-
-class Texture2D : public Texture
-{
-  public:
-    Texture2D(rx::Renderer *renderer, GLuint id);
-
-    ~Texture2D();
-
-    void addProxyRef(const Renderbuffer *proxy);
-    void releaseProxy(const Renderbuffer *proxy);
-
-    virtual GLenum getTarget() const;
-
-    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;
-
-#if defined(__LB_XB360__)
-    // Sets the texture storage directly, taking ownership of it. This is used
-    // to expose an internal platform texture as a GL texture to the outside
-    // world.
-    void adoptStorage(GLenum internalformat, GLsizei width, GLsizei height, rx::TextureStorage *storage);
-#endif
-
-    void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, 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, GLint unpackAlignment, const void *pixels);
-    void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
-    void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
-    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
-    void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-
-    virtual bool isSamplerComplete() const;
-    virtual void bindTexImage(egl::Surface *surface);
-    virtual void releaseTexImage();
-
-    virtual void generateMipmaps();
-
-    virtual Renderbuffer *getRenderbuffer(GLenum target);
-
-  protected:
-    friend class RenderbufferTexture2D;
-    virtual rx::RenderTarget *getRenderTarget(GLenum target);
-    virtual rx::RenderTarget *getDepthStencil(GLenum target);
-    virtual int levelCount();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Texture2D);
-
-    virtual void createTexture();
-    virtual void updateTexture();
-    virtual void convertToRenderTarget();
-    virtual rx::TextureStorageInterface *getStorage(bool renderTarget);
-
-    bool isMipmapComplete() const;
-
-    void redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height);
-    void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
-    rx::Image *mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-
-    rx::TextureStorageInterface2D *mTexStorage;
-    egl::Surface *mSurface;
-
-    // A specific internal reference count is kept for colorbuffer proxy references,
-    // because, as the renderbuffer acting as proxy will maintain a binding pointer
-    // back to this texture, there would be a circular reference if we used a binding
-    // pointer here. This reference count will cause the pointer to be set to NULL if
-    // the count drops to zero, but will not cause deletion of the Renderbuffer.
-    Renderbuffer *mColorbufferProxy;
-    unsigned int mProxyRefs;
-};
-
-class TextureCubeMap : public Texture
-{
-  public:
-    TextureCubeMap(rx::Renderer *renderer, GLuint id);
-
-    ~TextureCubeMap();
-
-    void addProxyRef(const Renderbuffer *proxy);
-    void releaseProxy(const Renderbuffer *proxy);
-
-    virtual GLenum getTarget() const;
-    
-    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;
-
-    void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
-    void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
-    void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
-    void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
-    void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
-    void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
-
-    void setCompressedImage(GLenum face, 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, GLint unpackAlignment, const void *pixels);
-    void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
-    void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
-    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
-    void storage(GLsizei levels, GLenum internalformat, GLsizei size);
-
-    virtual bool isSamplerComplete() const;
-
-    virtual void generateMipmaps();
-
-    virtual Renderbuffer *getRenderbuffer(GLenum target);
-
-    static unsigned int faceIndex(GLenum face);
-
-  protected:
-    friend class RenderbufferTextureCubeMap;
-    virtual rx::RenderTarget *getRenderTarget(GLenum target);
-    virtual int levelCount();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
-
-    virtual void createTexture();
-    virtual void updateTexture();
-    virtual void convertToRenderTarget();
-    virtual rx::TextureStorageInterface *getStorage(bool renderTarget);
-
-    bool isCubeComplete() const;
-    bool isMipmapCubeComplete() const;
-
-    void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
-    void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    void redefineImage(int faceIndex, GLint level, GLint internalformat, GLsizei width, GLsizei height);
-
-    rx::Image *mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-
-    rx::TextureStorageInterfaceCube *mTexStorage;
-
-    // A specific internal reference count is kept for colorbuffer proxy references,
-    // because, as the renderbuffer acting as proxy will maintain a binding pointer
-    // back to this texture, there would be a circular reference if we used a binding
-    // pointer here. This reference count will cause the pointer to be set to NULL if
-    // the count drops to zero, but will not cause deletion of the Renderbuffer.
-    Renderbuffer *mFaceProxies[6];
-    unsigned int *mFaceProxyRefs[6];
-};
-}
-
-#endif   // LIBGLESV2_TEXTURE_H_
diff --git a/src/third_party/angle/src/libGLESv2/Uniform.cpp b/src/third_party/angle/src/libGLESv2/Uniform.cpp
deleted file mode 100644
index 0fe3b8c..0000000
--- a/src/third_party/angle/src/libGLESv2/Uniform.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "precompiled.h"
-//

-// Copyright (c) 2010-2013 The ANGLE Project Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-//

-

-#include "libGLESv2/Uniform.h"

-

-#include "libGLESv2/utilities.h"

-

-namespace gl

-{

-

-Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize)

-    : type(type), precision(precision), name(name), arraySize(arraySize)

-{

-    int bytes = gl::UniformInternalSize(type) * elementCount();

-    data = new unsigned char[bytes];

-    memset(data, 0, bytes);

-    dirty = true;

-

-    psRegisterIndex = -1;

-    vsRegisterIndex = -1;

-    registerCount = VariableRowCount(type) * elementCount();

-}

-

-Uniform::~Uniform()

-{

-    delete[] data;

-}

-

-bool Uniform::isArray() const

-{

-    return arraySize > 0;

-}

-

-unsigned int Uniform::elementCount() const

-{

-    return arraySize > 0 ? arraySize : 1;

-}

-

-}

diff --git a/src/third_party/angle/src/libGLESv2/Uniform.h b/src/third_party/angle/src/libGLESv2/Uniform.h
deleted file mode 100644
index 64414ac..0000000
--- a/src/third_party/angle/src/libGLESv2/Uniform.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//

-// Copyright (c) 2010-2013 The ANGLE Project Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-//

-

-#ifndef LIBGLESV2_UNIFORM_H_

-#define LIBGLESV2_UNIFORM_H_

-

-#include <string>

-#include <vector>

-

-#define GL_APICALL

-#include <GLES2/gl2.h>

-

-#include "common/debug.h"

-

-namespace gl

-{

-

-// Helper struct representing a single shader uniform

-struct Uniform

-{

-    Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize);

-

-    ~Uniform();

-

-    bool isArray() const;

-    unsigned int elementCount() const;

-

-    const GLenum type;

-    const GLenum precision;

-    const std::string name;

-    const unsigned int arraySize;

-

-    unsigned char *data;

-    bool dirty;

-

-    int psRegisterIndex;

-    int vsRegisterIndex;

-    unsigned int registerCount;

-};

-

-typedef std::vector<Uniform*> UniformArray;

-

-}

-

-#endif   // LIBGLESV2_UNIFORM_H_

diff --git a/src/third_party/angle/src/libGLESv2/angletypes.h b/src/third_party/angle/src/libGLESv2/angletypes.h
deleted file mode 100644
index b2f0cad..0000000
--- a/src/third_party/angle/src/libGLESv2/angletypes.h
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
-
-#ifndef LIBGLESV2_ANGLETYPES_H_
-#define LIBGLESV2_ANGLETYPES_H_
-
-namespace gl
-{
-
-enum TextureType
-{
-    TEXTURE_2D,
-    TEXTURE_CUBE,
-
-    TEXTURE_TYPE_COUNT,
-    TEXTURE_UNKNOWN
-};
-
-enum SamplerType
-{
-    SAMPLER_PIXEL,
-    SAMPLER_VERTEX
-};
-
-struct Color
-{
-    float red;
-    float green;
-    float blue;
-    float alpha;
-};
-
-struct Rectangle
-{
-    int x;
-    int y;
-    int width;
-    int height;
-};
-
-struct RasterizerState
-{
-    bool cullFace;
-    GLenum cullMode;
-    GLenum frontFace;
-
-    bool polygonOffsetFill;
-    GLfloat polygonOffsetFactor;
-    GLfloat polygonOffsetUnits;
-
-    bool pointDrawMode;
-    bool multiSample;
-};
-
-struct BlendState
-{
-    bool blend;
-    GLenum sourceBlendRGB;
-    GLenum destBlendRGB;
-    GLenum sourceBlendAlpha;
-    GLenum destBlendAlpha;
-    GLenum blendEquationRGB;
-    GLenum blendEquationAlpha;
-
-    bool colorMaskRed;
-    bool colorMaskGreen;
-    bool colorMaskBlue;
-    bool colorMaskAlpha;
-
-    bool sampleAlphaToCoverage;
-
-    bool dither;
-};
-
-struct DepthStencilState
-{
-    bool depthTest;
-    GLenum depthFunc;
-    bool depthMask;
-
-    bool stencilTest;
-    GLenum stencilFunc;
-    GLuint stencilMask;
-    GLenum stencilFail;
-    GLenum stencilPassDepthFail;
-    GLenum stencilPassDepthPass;
-    GLuint stencilWritemask;
-    GLenum stencilBackFunc;
-    GLuint stencilBackMask;
-    GLenum stencilBackFail;
-    GLenum stencilBackPassDepthFail;
-    GLenum stencilBackPassDepthPass;
-    GLuint stencilBackWritemask;
-};
-
-struct SamplerState
-{
-    GLenum minFilter;
-    GLenum magFilter;
-    GLenum wrapS;
-    GLenum wrapT;
-    float maxAnisotropy;
-    int lodOffset;
-};
-
-struct ClearParameters
-{
-    GLbitfield mask;
-
-    Color colorClearValue;
-    bool colorMaskRed;
-    bool colorMaskGreen;
-    bool colorMaskBlue;
-    bool colorMaskAlpha;
-
-    float depthClearValue;
-
-    GLint stencilClearValue;
-    GLuint stencilWriteMask;
-};
-
-}
-
-#endif // LIBGLESV2_ANGLETYPES_H_
diff --git a/src/third_party/angle/src/libGLESv2/constants.h b/src/third_party/angle/src/libGLESv2/constants.h
deleted file mode 100644
index 9f24d66..0000000
--- a/src/third_party/angle/src/libGLESv2/constants.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Contants.h: Defines some implementation specific and gl constants
-
-#ifndef LIBGLESV2_CONSTANTS_H_
-#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
-};
-
-const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f;
-const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f;
-const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f;
-
-}
-
-#endif // LIBGLESV2_CONSTANTS_H_
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_egl.cpp b/src/third_party/angle/src/libGLESv2/entry_points_egl.cpp
new file mode 100644
index 0000000..48009ea
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_egl.cpp
@@ -0,0 +1,1881 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_egl.cpp : Implements the EGL entry points.
+
+#include "libGLESv2/entry_points_egl.h"
+#include "libGLESv2/entry_points_egl_ext.h"
+#include "libGLESv2/entry_points_gles_2_0_autogen.h"
+#include "libGLESv2/entry_points_gles_2_0_ext.h"
+#include "libGLESv2/entry_points_gles_3_0.h"
+#include "libGLESv2/entry_points_gles_3_1.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/queryutils.h"
+#include "libANGLE/validationEGL.h"
+
+#include "common/debug.h"
+#include "common/version.h"
+
+#include "platform/Platform.h"
+
+#include <EGL/eglext.h>
+
+namespace egl
+{
+
+namespace
+{
+
+void ClipConfigs(const std::vector<const Config *> &filteredConfigs,
+                 EGLConfig *output_configs,
+                 EGLint config_size,
+                 EGLint *num_config)
+{
+    EGLint result_size = static_cast<EGLint>(filteredConfigs.size());
+    if (output_configs)
+    {
+        result_size = std::max(std::min(result_size, config_size), 0);
+        for (EGLint i = 0; i < result_size; i++)
+        {
+            output_configs[i] = const_cast<Config *>(filteredConfigs[i]);
+        }
+    }
+    *num_config = result_size;
+}
+
+}  // anonymous namespace
+
+// EGL 1.0
+EGLint EGLAPIENTRY GetError(void)
+{
+    EVENT("()");
+    Thread *thread = GetCurrentThread();
+
+    EGLint error = thread->getError();
+    thread->setError(Error(EGL_SUCCESS));
+    return error;
+}
+
+EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id)
+{
+    EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
+
+    return Display::GetDisplayFromNativeDisplay(display_id, AttributeMap());
+}
+
+EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", dpy,
+          major, minor);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = static_cast<Display *>(dpy);
+    if (dpy == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
+    {
+        thread->setError(Error(EGL_BAD_DISPLAY));
+        return EGL_FALSE;
+    }
+
+    Error error = display->initialize();
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (major)
+        *major = 1;
+    if (minor)
+        *minor = 4;
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = static_cast<Display *>(dpy);
+    if (dpy == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
+    {
+        thread->setError(Error(EGL_BAD_DISPLAY));
+        return EGL_FALSE;
+    }
+
+    if (display->isValidContext(thread->getContext()))
+    {
+        thread->setCurrent(nullptr, nullptr, nullptr, nullptr);
+    }
+
+    display->terminate();
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = static_cast<Display *>(dpy);
+    if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS))
+    {
+        Error error = ValidateDisplay(display);
+        if (error.isError())
+        {
+            thread->setError(error);
+            return nullptr;
+        }
+    }
+
+    const char *result;
+    switch (name)
+    {
+        case EGL_CLIENT_APIS:
+            result = "OpenGL_ES";
+            break;
+        case EGL_EXTENSIONS:
+            if (display == EGL_NO_DISPLAY)
+            {
+                result = Display::getClientExtensionString().c_str();
+            }
+            else
+            {
+                result = display->getExtensionString().c_str();
+            }
+            break;
+        case EGL_VENDOR:
+            result = display->getVendorString().c_str();
+            break;
+        case EGL_VERSION:
+            result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
+            break;
+        default:
+            thread->setError(Error(EGL_BAD_PARAMETER));
+            return nullptr;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return result;
+}
+
+EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy,
+                                  EGLConfig *configs,
+                                  EGLint config_size,
+                                  EGLint *num_config)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
+        "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+        dpy, configs, config_size, num_config);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = static_cast<Display *>(dpy);
+
+    Error error = ValidateGetConfigs(display, config_size, num_config);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    ClipConfigs(display->getConfigs(AttributeMap()), configs, config_size, num_config);
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy,
+                                    const EGLint *attrib_list,
+                                    EGLConfig *configs,
+                                    EGLint config_size,
+                                    EGLint *num_config)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
+        "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+        dpy, attrib_list, configs, config_size, num_config);
+    Thread *thread = GetCurrentThread();
+
+    Display *display       = static_cast<Display *>(dpy);
+    AttributeMap attribMap = AttributeMap::CreateFromIntArray(attrib_list);
+
+    Error error = ValidateChooseConfig(display, attribMap, config_size, num_config);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    ClipConfigs(display->getConfigs(attribMap), configs, config_size, num_config);
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy,
+                                       EGLConfig config,
+                                       EGLint attribute,
+                                       EGLint *value)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint "
+        "*value = 0x%0.8p)",
+        dpy, config, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Display *display      = static_cast<Display *>(dpy);
+    Config *configuration = static_cast<Config *>(config);
+
+    Error error = ValidateGetConfigAttrib(display, configuration, attribute);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    QueryConfigAttrib(configuration, attribute, value);
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy,
+                                           EGLConfig config,
+                                           EGLNativeWindowType win,
+                                           const EGLint *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
+        "const EGLint *attrib_list = 0x%0.8p)",
+        dpy, config, win, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Display *display        = static_cast<Display *>(dpy);
+    Config *configuration   = static_cast<Config *>(config);
+    AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
+
+    Error error = ValidateCreateWindowSurface(display, configuration, win, attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_SURFACE;
+    }
+
+    egl::Surface *surface = nullptr;
+    error                 = display->createWindowSurface(configuration, win, attributes, &surface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_SURFACE;
+    }
+
+    return static_cast<EGLSurface>(surface);
+}
+
+EGLSurface EGLAPIENTRY CreatePbufferSurface(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);
+    Thread *thread = GetCurrentThread();
+
+    Display *display        = static_cast<Display *>(dpy);
+    Config *configuration   = static_cast<Config *>(config);
+    AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
+
+    Error error = ValidateCreatePbufferSurface(display, configuration, attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_SURFACE;
+    }
+
+    egl::Surface *surface = nullptr;
+    error                 = display->createPbufferSurface(configuration, attributes, &surface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_SURFACE;
+    }
+
+    return static_cast<EGLSurface>(surface);
+}
+
+EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy,
+                                           EGLConfig config,
+                                           EGLNativePixmapType pixmap,
+                                           const EGLint *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = "
+        "0x%0.8p, "
+        "const EGLint *attrib_list = 0x%0.8p)",
+        dpy, config, pixmap, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Display *display      = static_cast<Display *>(dpy);
+    Config *configuration = static_cast<Config *>(config);
+
+    Error error = ValidateConfig(display, configuration);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_SURFACE;
+    }
+
+    UNIMPLEMENTED();  // FIXME
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_NO_SURFACE;
+}
+
+EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+    Thread *thread = GetCurrentThread();
+
+    Display *display    = static_cast<Display *>(dpy);
+    Surface *eglSurface = static_cast<Surface *>(surface);
+
+    Error error = ValidateSurface(display, eglSurface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (surface == EGL_NO_SURFACE)
+    {
+        thread->setError(Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
+    }
+
+    display->destroySurface((Surface *)surface);
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy,
+                                    EGLSurface surface,
+                                    EGLint attribute,
+                                    EGLint *value)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint "
+        "*value = 0x%0.8p)",
+        dpy, surface, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Display *display    = static_cast<Display *>(dpy);
+    Surface *eglSurface = (Surface *)surface;
+
+    Error error = ValidateSurface(display, eglSurface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (surface == EGL_NO_SURFACE)
+    {
+        thread->setError(Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
+    }
+
+    switch (attribute)
+    {
+        case EGL_VG_ALPHA_FORMAT:
+            UNIMPLEMENTED();  // FIXME
+            break;
+        case EGL_VG_COLORSPACE:
+            UNIMPLEMENTED();  // FIXME
+            break;
+        case EGL_CONFIG_ID:
+            *value = eglSurface->getConfig()->configID;
+            break;
+        case EGL_HEIGHT:
+            *value = eglSurface->getHeight();
+            break;
+        case EGL_HORIZONTAL_RESOLUTION:
+            UNIMPLEMENTED();  // FIXME
+            break;
+        case EGL_LARGEST_PBUFFER:
+            UNIMPLEMENTED();  // FIXME
+            break;
+        case EGL_MIPMAP_TEXTURE:
+            UNIMPLEMENTED();  // FIXME
+            break;
+        case EGL_MIPMAP_LEVEL:
+            UNIMPLEMENTED();  // FIXME
+            break;
+        case EGL_MULTISAMPLE_RESOLVE:
+            UNIMPLEMENTED();  // FIXME
+            break;
+        case EGL_PIXEL_ASPECT_RATIO:
+            *value = eglSurface->getPixelAspectRatio();
+            break;
+        case EGL_RENDER_BUFFER:
+            *value = eglSurface->getRenderBuffer();
+            break;
+        case EGL_SWAP_BEHAVIOR:
+            *value = eglSurface->getSwapBehavior();
+            break;
+        case EGL_TEXTURE_FORMAT:
+            *value = eglSurface->getTextureFormat();
+            break;
+        case EGL_TEXTURE_TARGET:
+            *value = eglSurface->getTextureTarget();
+            break;
+        case EGL_VERTICAL_RESOLUTION:
+            UNIMPLEMENTED();  // FIXME
+            break;
+        case EGL_WIDTH:
+            *value = eglSurface->getWidth();
+            break;
+        case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+            if (!display->getExtensions().postSubBuffer)
+            {
+                thread->setError(Error(EGL_BAD_ATTRIBUTE));
+                return EGL_FALSE;
+            }
+            *value = eglSurface->isPostSubBufferSupported();
+            break;
+        case EGL_FIXED_SIZE_ANGLE:
+            if (!display->getExtensions().windowFixedSize)
+            {
+                thread->setError(Error(EGL_BAD_ATTRIBUTE));
+                return EGL_FALSE;
+            }
+            *value = eglSurface->isFixedSize();
+            break;
+        case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
+            if (!display->getExtensions().flexibleSurfaceCompatibility)
+            {
+                thread->setError(Error(
+                    EGL_BAD_ATTRIBUTE,
+                    "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without "
+                    "EGL_ANGLE_flexible_surface_compatibility support."));
+                return EGL_FALSE;
+            }
+            *value = eglSurface->flexibleSurfaceCompatibilityRequested();
+            break;
+        case EGL_SURFACE_ORIENTATION_ANGLE:
+            if (!display->getExtensions().surfaceOrientation)
+            {
+                thread->setError(Error(EGL_BAD_ATTRIBUTE,
+                                       "EGL_SURFACE_ORIENTATION_ANGLE cannot be queried without "
+                                       "EGL_ANGLE_surface_orientation support."));
+                return EGL_FALSE;
+            }
+            *value = eglSurface->getOrientation();
+            break;
+        case EGL_DIRECT_COMPOSITION_ANGLE:
+            if (!display->getExtensions().directComposition)
+            {
+                thread->setError(Error(EGL_BAD_ATTRIBUTE,
+                                       "EGL_DIRECT_COMPOSITION_ANGLE cannot be used without "
+                                       "EGL_ANGLE_direct_composition support."));
+                return EGL_FALSE;
+            }
+            *value = eglSurface->directComposition();
+            break;
+        default:
+            thread->setError(Error(EGL_BAD_ATTRIBUTE));
+            return EGL_FALSE;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy,
+                                     EGLConfig config,
+                                     EGLContext share_context,
+                                     const EGLint *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = "
+        "0x%0.8p, "
+        "const EGLint *attrib_list = 0x%0.8p)",
+        dpy, config, share_context, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Display *display             = static_cast<Display *>(dpy);
+    Config *configuration        = static_cast<Config *>(config);
+    gl::Context *sharedGLContext = static_cast<gl::Context *>(share_context);
+    AttributeMap attributes      = AttributeMap::CreateFromIntArray(attrib_list);
+
+    Error error = ValidateCreateContext(display, configuration, sharedGLContext, attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_CONTEXT;
+    }
+
+    gl::Context *context = nullptr;
+    error = display->createContext(configuration, sharedGLContext, attributes, &context);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_CONTEXT;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return static_cast<EGLContext>(context);
+}
+
+EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    gl::Context *context = static_cast<gl::Context *>(ctx);
+
+    Error error = ValidateContext(display, context);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (ctx == EGL_NO_CONTEXT)
+    {
+        thread->setError(Error(EGL_BAD_CONTEXT));
+        return EGL_FALSE;
+    }
+
+    if (context == thread->getContext())
+    {
+        thread->setCurrent(nullptr, thread->getDrawSurface(), thread->getReadSurface(), nullptr);
+    }
+
+    display->destroyContext(context);
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, "
+        "EGLContext ctx = 0x%0.8p)",
+        dpy, draw, read, ctx);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    gl::Context *context = static_cast<gl::Context *>(ctx);
+
+    Error error = ValidateMakeCurrent(display, draw, read, context);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    Surface *readSurface   = static_cast<Surface *>(read);
+    Surface *drawSurface   = static_cast<Surface *>(draw);
+    Error makeCurrentError = display->makeCurrent(drawSurface, readSurface, context);
+    if (makeCurrentError.isError())
+    {
+        thread->setError(makeCurrentError);
+        return EGL_FALSE;
+    }
+
+    gl::Context *previousContext = thread->getContext();
+    thread->setCurrent(display, drawSurface, readSurface, context);
+
+    // Release the surface from the previously-current context, to allow
+    // destroyed surfaces to delete themselves.
+    if (previousContext != nullptr && context != previousContext)
+    {
+        previousContext->releaseSurface(display);
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw)
+{
+    EVENT("(EGLint readdraw = %d)", readdraw);
+    Thread *thread = GetCurrentThread();
+
+    if (readdraw == EGL_READ)
+    {
+        thread->setError(Error(EGL_SUCCESS));
+        return thread->getReadSurface();
+    }
+    else if (readdraw == EGL_DRAW)
+    {
+        thread->setError(Error(EGL_SUCCESS));
+        return thread->getDrawSurface();
+    }
+    else
+    {
+        thread->setError(Error(EGL_BAD_PARAMETER));
+        return EGL_NO_SURFACE;
+    }
+}
+
+EGLDisplay EGLAPIENTRY GetCurrentDisplay(void)
+{
+    EVENT("()");
+    Thread *thread = GetCurrentThread();
+
+    EGLDisplay dpy = thread->getDisplay();
+
+    thread->setError(Error(EGL_SUCCESS));
+    return dpy;
+}
+
+EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value "
+        "= 0x%0.8p)",
+        dpy, ctx, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    gl::Context *context = static_cast<gl::Context *>(ctx);
+
+    Error error = ValidateContext(display, context);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    switch (attribute)
+    {
+        case EGL_CONFIG_ID:
+            *value = context->getConfig()->configID;
+            break;
+        case EGL_CONTEXT_CLIENT_TYPE:
+            *value = context->getClientType();
+            break;
+        case EGL_CONTEXT_CLIENT_VERSION:
+            *value = context->getClientMajorVersion();
+            break;
+        case EGL_RENDER_BUFFER:
+            *value = context->getRenderBuffer();
+            break;
+        default:
+            thread->setError(Error(EGL_BAD_ATTRIBUTE));
+            return EGL_FALSE;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY WaitGL(void)
+{
+    EVENT("()");
+    Thread *thread = GetCurrentThread();
+
+    Display *display = thread->getDisplay();
+
+    Error error = ValidateDisplay(display);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    // eglWaitGL like calling eglWaitClient with the OpenGL ES API bound. Since we only implement
+    // OpenGL ES we can do the call directly.
+    error = display->waitClient();
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY WaitNative(EGLint engine)
+{
+    EVENT("(EGLint engine = %d)", engine);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = thread->getDisplay();
+
+    Error error = ValidateDisplay(display);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (engine != EGL_CORE_NATIVE_ENGINE)
+    {
+        thread->setError(
+            Error(EGL_BAD_PARAMETER, "the 'engine' parameter has an unrecognized value"));
+    }
+
+    error = display->waitNative(engine, thread->getDrawSurface(), thread->getReadSurface());
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+    Thread *thread = GetCurrentThread();
+
+    Display *display    = static_cast<Display *>(dpy);
+    Surface *eglSurface = (Surface *)surface;
+
+    Error error = ValidateSurface(display, eglSurface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (display->testDeviceLost())
+    {
+        thread->setError(Error(EGL_CONTEXT_LOST));
+        return EGL_FALSE;
+    }
+
+    if (surface == EGL_NO_SURFACE)
+    {
+        thread->setError(Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
+    }
+
+    error = eglSurface->swap(*display);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = "
+        "0x%0.8p)",
+        dpy, surface, target);
+    Thread *thread = GetCurrentThread();
+
+    Display *display    = static_cast<Display *>(dpy);
+    Surface *eglSurface = static_cast<Surface *>(surface);
+
+    Error error = ValidateSurface(display, eglSurface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (display->testDeviceLost())
+    {
+        thread->setError(Error(EGL_CONTEXT_LOST));
+        return EGL_FALSE;
+    }
+
+    UNIMPLEMENTED();  // FIXME
+
+    thread->setError(Error(EGL_SUCCESS));
+    return 0;
+}
+
+// EGL 1.1
+EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy,
+          surface, buffer);
+    Thread *thread = GetCurrentThread();
+
+    Display *display    = static_cast<Display *>(dpy);
+    Surface *eglSurface = static_cast<Surface *>(surface);
+
+    Error error = ValidateSurface(display, eglSurface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (buffer != EGL_BACK_BUFFER)
+    {
+        thread->setError(Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;
+    }
+
+    if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT)
+    {
+        thread->setError(Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
+    }
+
+    if (eglSurface->getBoundTexture())
+    {
+        thread->setError(Error(EGL_BAD_ACCESS));
+        return EGL_FALSE;
+    }
+
+    if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+    {
+        thread->setError(Error(EGL_BAD_MATCH));
+        return EGL_FALSE;
+    }
+
+    gl::Context *context = thread->getContext();
+    if (context)
+    {
+        gl::Texture *textureObject = context->getTargetTexture(GL_TEXTURE_2D);
+        ASSERT(textureObject != nullptr);
+
+        if (textureObject->getImmutableFormat())
+        {
+            thread->setError(Error(EGL_BAD_MATCH));
+            return EGL_FALSE;
+        }
+
+        error = eglSurface->bindTexImage(textureObject, buffer);
+        if (error.isError())
+        {
+            thread->setError(error);
+            return EGL_FALSE;
+        }
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy,
+                                     EGLSurface surface,
+                                     EGLint attribute,
+                                     EGLint value)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint "
+        "value = %d)",
+        dpy, surface, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Display *display    = static_cast<Display *>(dpy);
+    Surface *eglSurface = static_cast<Surface *>(surface);
+
+    Error error = ValidateSurface(display, eglSurface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    UNIMPLEMENTED();  // FIXME
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy,
+          surface, buffer);
+    Thread *thread = GetCurrentThread();
+
+    Display *display    = static_cast<Display *>(dpy);
+    Surface *eglSurface = static_cast<Surface *>(surface);
+
+    Error error = ValidateSurface(display, eglSurface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (buffer != EGL_BACK_BUFFER)
+    {
+        thread->setError(Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;
+    }
+
+    if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT)
+    {
+        thread->setError(Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
+    }
+
+    if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+    {
+        thread->setError(Error(EGL_BAD_MATCH));
+        return EGL_FALSE;
+    }
+
+    gl::Texture *texture = eglSurface->getBoundTexture();
+
+    if (texture)
+    {
+        error = eglSurface->releaseTexImage(buffer);
+        if (error.isError())
+        {
+            thread->setError(error);
+            return EGL_FALSE;
+        }
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = static_cast<Display *>(dpy);
+
+    Error error = ValidateDisplay(display);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    Surface *draw_surface = static_cast<Surface *>(thread->getDrawSurface());
+
+    if (draw_surface == nullptr)
+    {
+        thread->setError(Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
+    }
+
+    const egl::Config *surfaceConfig = draw_surface->getConfig();
+    EGLint clampedInterval           = std::min(std::max(interval, surfaceConfig->minSwapInterval),
+                                      surfaceConfig->maxSwapInterval);
+
+    draw_surface->setSwapInterval(clampedInterval);
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+// EGL 1.2
+EGLBoolean EGLAPIENTRY BindAPI(EGLenum api)
+{
+    EVENT("(EGLenum api = 0x%X)", api);
+    Thread *thread = GetCurrentThread();
+
+    switch (api)
+    {
+        case EGL_OPENGL_API:
+        case EGL_OPENVG_API:
+            thread->setError(Error(EGL_BAD_PARAMETER));
+            return EGL_FALSE;  // Not supported by this implementation
+        case EGL_OPENGL_ES_API:
+            break;
+        default:
+            thread->setError(Error(EGL_BAD_PARAMETER));
+            return EGL_FALSE;
+    }
+
+    thread->setAPI(api);
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLenum EGLAPIENTRY QueryAPI(void)
+{
+    EVENT("()");
+    Thread *thread = GetCurrentThread();
+
+    EGLenum API = thread->getAPI();
+
+    thread->setError(Error(EGL_SUCCESS));
+    return API;
+}
+
+EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy,
+                                                     EGLenum buftype,
+                                                     EGLClientBuffer buffer,
+                                                     EGLConfig config,
+                                                     const EGLint *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
+        "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+        dpy, buftype, buffer, config, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Display *display        = static_cast<Display *>(dpy);
+    Config *configuration   = static_cast<Config *>(config);
+    AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
+
+    Error error =
+        ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_SURFACE;
+    }
+
+    egl::Surface *surface = nullptr;
+    error = display->createPbufferFromClientBuffer(configuration, buftype, buffer, attributes,
+                                                   &surface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_SURFACE;
+    }
+
+    return static_cast<EGLSurface>(surface);
+}
+
+EGLBoolean EGLAPIENTRY ReleaseThread(void)
+{
+    EVENT("()");
+    Thread *thread = GetCurrentThread();
+
+    MakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY WaitClient(void)
+{
+    EVENT("()");
+    Thread *thread = GetCurrentThread();
+
+    Display *display = thread->getDisplay();
+
+    Error error = ValidateDisplay(display);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    error = display->waitClient();
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+// EGL 1.4
+EGLContext EGLAPIENTRY GetCurrentContext(void)
+{
+    EVENT("()");
+    Thread *thread = GetCurrentThread();
+
+    gl::Context *context = thread->getContext();
+
+    thread->setError(Error(EGL_SUCCESS));
+    return static_cast<EGLContext>(context);
+}
+
+// EGL 1.5
+EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum type = 0x%X, const EGLint* attrib_list = 0x%0.8p)",
+          dpy, type, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglCreateSync unimplemented."));
+    return EGL_NO_SYNC;
+}
+
+EGLBoolean EGLAPIENTRY DestroySync(EGLDisplay dpy, EGLSync sync)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p)", dpy, sync);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglDestroySync unimplemented."));
+    return EGL_FALSE;
+}
+
+EGLint EGLAPIENTRY ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X, EGLTime timeout = "
+        "%d)",
+        dpy, sync, flags, timeout);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglClientWaitSync unimplemented."));
+    return 0;
+}
+
+EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy,
+                                     EGLSync sync,
+                                     EGLint attribute,
+                                     EGLAttrib *value)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint attribute = 0x%X, EGLAttrib "
+        "*value = 0x%0.8p)",
+        dpy, sync, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglSyncAttrib unimplemented."));
+    return EGL_FALSE;
+}
+
+EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy,
+                                 EGLContext ctx,
+                                 EGLenum target,
+                                 EGLClientBuffer buffer,
+                                 const EGLAttrib *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, "
+        "EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)",
+        dpy, ctx, target, buffer, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglCreateImage unimplemented."));
+    return EGL_NO_IMAGE;
+}
+
+EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLImage image = 0x%0.8p)", dpy, image);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglDestroyImage unimplemented."));
+    return EGL_FALSE;
+}
+
+EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform,
+                                          void *native_display,
+                                          const EGLAttrib *attrib_list)
+{
+    EVENT(
+        "(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = "
+        "0x%0.8p)",
+        platform, native_display, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglGetPlatformDisplay unimplemented."));
+    return EGL_NO_DISPLAY;
+}
+
+EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy,
+                                                   EGLConfig config,
+                                                   void *native_window,
+                                                   const EGLAttrib *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_window = 0x%0.8p, "
+        "const EGLint* attrib_list = 0x%0.8p)",
+        dpy, config, native_window, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglCreatePlatformWindowSurface unimplemented."));
+    return EGL_NO_SURFACE;
+}
+
+EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy,
+                                                   EGLConfig config,
+                                                   void *native_pixmap,
+                                                   const EGLAttrib *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_pixmap = 0x%0.8p, "
+        "const EGLint* attrib_list = 0x%0.8p)",
+        dpy, config, native_pixmap, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglCraetePlatformPixmaSurface unimplemented."));
+    return EGL_NO_SURFACE;
+}
+
+EGLBoolean EGLAPIENTRY WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X)", dpy, sync,
+          flags);
+    Thread *thread = GetCurrentThread();
+
+    UNIMPLEMENTED();
+    thread->setError(Error(EGL_BAD_DISPLAY, "eglWaitSync unimplemented."));
+    return EGL_FALSE;
+}
+
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname)
+{
+    EVENT("(const char *procname = \"%s\")", procname);
+    Thread *thread = GetCurrentThread();
+
+    typedef std::map<std::string, __eglMustCastToProperFunctionPointerType> ProcAddressMap;
+    auto generateProcAddressMap = []() {
+        ProcAddressMap map;
+#define INSERT_PROC_ADDRESS(ns, proc) \
+    map[#ns #proc] = reinterpret_cast<__eglMustCastToProperFunctionPointerType>(ns::proc)
+
+#define INSERT_PROC_ADDRESS_NO_NS(name, proc) \
+    map[name] = reinterpret_cast<__eglMustCastToProperFunctionPointerType>(proc)
+
+        // GLES2 core
+        INSERT_PROC_ADDRESS(gl, ActiveTexture);
+        INSERT_PROC_ADDRESS(gl, AttachShader);
+        INSERT_PROC_ADDRESS(gl, BindAttribLocation);
+        INSERT_PROC_ADDRESS(gl, BindBuffer);
+        INSERT_PROC_ADDRESS(gl, BindFramebuffer);
+        INSERT_PROC_ADDRESS(gl, BindRenderbuffer);
+        INSERT_PROC_ADDRESS(gl, BindTexture);
+        INSERT_PROC_ADDRESS(gl, BlendColor);
+        INSERT_PROC_ADDRESS(gl, BlendEquation);
+        INSERT_PROC_ADDRESS(gl, BlendEquationSeparate);
+        INSERT_PROC_ADDRESS(gl, BlendFunc);
+        INSERT_PROC_ADDRESS(gl, BlendFuncSeparate);
+        INSERT_PROC_ADDRESS(gl, BufferData);
+        INSERT_PROC_ADDRESS(gl, BufferSubData);
+        INSERT_PROC_ADDRESS(gl, CheckFramebufferStatus);
+        INSERT_PROC_ADDRESS(gl, Clear);
+        INSERT_PROC_ADDRESS(gl, ClearColor);
+        INSERT_PROC_ADDRESS(gl, ClearDepthf);
+        INSERT_PROC_ADDRESS(gl, ClearStencil);
+        INSERT_PROC_ADDRESS(gl, ColorMask);
+        INSERT_PROC_ADDRESS(gl, CompileShader);
+        INSERT_PROC_ADDRESS(gl, CompressedTexImage2D);
+        INSERT_PROC_ADDRESS(gl, CompressedTexSubImage2D);
+        INSERT_PROC_ADDRESS(gl, CopyTexImage2D);
+        INSERT_PROC_ADDRESS(gl, CopyTexSubImage2D);
+        INSERT_PROC_ADDRESS(gl, CreateProgram);
+        INSERT_PROC_ADDRESS(gl, CreateShader);
+        INSERT_PROC_ADDRESS(gl, CullFace);
+        INSERT_PROC_ADDRESS(gl, DeleteBuffers);
+        INSERT_PROC_ADDRESS(gl, DeleteFramebuffers);
+        INSERT_PROC_ADDRESS(gl, DeleteProgram);
+        INSERT_PROC_ADDRESS(gl, DeleteRenderbuffers);
+        INSERT_PROC_ADDRESS(gl, DeleteShader);
+        INSERT_PROC_ADDRESS(gl, DeleteTextures);
+        INSERT_PROC_ADDRESS(gl, DepthFunc);
+        INSERT_PROC_ADDRESS(gl, DepthMask);
+        INSERT_PROC_ADDRESS(gl, DepthRangef);
+        INSERT_PROC_ADDRESS(gl, DetachShader);
+        INSERT_PROC_ADDRESS(gl, Disable);
+        INSERT_PROC_ADDRESS(gl, DisableVertexAttribArray);
+        INSERT_PROC_ADDRESS(gl, DrawArrays);
+        INSERT_PROC_ADDRESS(gl, DrawElements);
+        INSERT_PROC_ADDRESS(gl, Enable);
+        INSERT_PROC_ADDRESS(gl, EnableVertexAttribArray);
+        INSERT_PROC_ADDRESS(gl, Finish);
+        INSERT_PROC_ADDRESS(gl, Flush);
+        INSERT_PROC_ADDRESS(gl, FramebufferRenderbuffer);
+        INSERT_PROC_ADDRESS(gl, FramebufferTexture2D);
+        INSERT_PROC_ADDRESS(gl, FrontFace);
+        INSERT_PROC_ADDRESS(gl, GenBuffers);
+        INSERT_PROC_ADDRESS(gl, GenerateMipmap);
+        INSERT_PROC_ADDRESS(gl, GenFramebuffers);
+        INSERT_PROC_ADDRESS(gl, GenRenderbuffers);
+        INSERT_PROC_ADDRESS(gl, GenTextures);
+        INSERT_PROC_ADDRESS(gl, GetActiveAttrib);
+        INSERT_PROC_ADDRESS(gl, GetActiveUniform);
+        INSERT_PROC_ADDRESS(gl, GetAttachedShaders);
+        INSERT_PROC_ADDRESS(gl, GetAttribLocation);
+        INSERT_PROC_ADDRESS(gl, GetBooleanv);
+        INSERT_PROC_ADDRESS(gl, GetBufferParameteriv);
+        INSERT_PROC_ADDRESS(gl, GetError);
+        INSERT_PROC_ADDRESS(gl, GetFloatv);
+        INSERT_PROC_ADDRESS(gl, GetFramebufferAttachmentParameteriv);
+        INSERT_PROC_ADDRESS(gl, GetIntegerv);
+        INSERT_PROC_ADDRESS(gl, GetProgramiv);
+        INSERT_PROC_ADDRESS(gl, GetProgramInfoLog);
+        INSERT_PROC_ADDRESS(gl, GetRenderbufferParameteriv);
+        INSERT_PROC_ADDRESS(gl, GetShaderiv);
+        INSERT_PROC_ADDRESS(gl, GetShaderInfoLog);
+        INSERT_PROC_ADDRESS(gl, GetShaderPrecisionFormat);
+        INSERT_PROC_ADDRESS(gl, GetShaderSource);
+        INSERT_PROC_ADDRESS(gl, GetString);
+        INSERT_PROC_ADDRESS(gl, GetTexParameterfv);
+        INSERT_PROC_ADDRESS(gl, GetTexParameteriv);
+        INSERT_PROC_ADDRESS(gl, GetUniformfv);
+        INSERT_PROC_ADDRESS(gl, GetUniformiv);
+        INSERT_PROC_ADDRESS(gl, GetUniformLocation);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribfv);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribiv);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribPointerv);
+        INSERT_PROC_ADDRESS(gl, Hint);
+        INSERT_PROC_ADDRESS(gl, IsBuffer);
+        INSERT_PROC_ADDRESS(gl, IsEnabled);
+        INSERT_PROC_ADDRESS(gl, IsFramebuffer);
+        INSERT_PROC_ADDRESS(gl, IsProgram);
+        INSERT_PROC_ADDRESS(gl, IsRenderbuffer);
+        INSERT_PROC_ADDRESS(gl, IsShader);
+        INSERT_PROC_ADDRESS(gl, IsTexture);
+        INSERT_PROC_ADDRESS(gl, LineWidth);
+        INSERT_PROC_ADDRESS(gl, LinkProgram);
+        INSERT_PROC_ADDRESS(gl, PixelStorei);
+        INSERT_PROC_ADDRESS(gl, PolygonOffset);
+        INSERT_PROC_ADDRESS(gl, ReadPixels);
+        INSERT_PROC_ADDRESS(gl, ReleaseShaderCompiler);
+        INSERT_PROC_ADDRESS(gl, RenderbufferStorage);
+        INSERT_PROC_ADDRESS(gl, SampleCoverage);
+        INSERT_PROC_ADDRESS(gl, Scissor);
+        INSERT_PROC_ADDRESS(gl, ShaderBinary);
+        INSERT_PROC_ADDRESS(gl, ShaderSource);
+        INSERT_PROC_ADDRESS(gl, StencilFunc);
+        INSERT_PROC_ADDRESS(gl, StencilFuncSeparate);
+        INSERT_PROC_ADDRESS(gl, StencilMask);
+        INSERT_PROC_ADDRESS(gl, StencilMaskSeparate);
+        INSERT_PROC_ADDRESS(gl, StencilOp);
+        INSERT_PROC_ADDRESS(gl, StencilOpSeparate);
+        INSERT_PROC_ADDRESS(gl, TexImage2D);
+        INSERT_PROC_ADDRESS(gl, TexParameterf);
+        INSERT_PROC_ADDRESS(gl, TexParameterfv);
+        INSERT_PROC_ADDRESS(gl, TexParameteri);
+        INSERT_PROC_ADDRESS(gl, TexParameteriv);
+        INSERT_PROC_ADDRESS(gl, TexSubImage2D);
+        INSERT_PROC_ADDRESS(gl, Uniform1f);
+        INSERT_PROC_ADDRESS(gl, Uniform1fv);
+        INSERT_PROC_ADDRESS(gl, Uniform1i);
+        INSERT_PROC_ADDRESS(gl, Uniform1iv);
+        INSERT_PROC_ADDRESS(gl, Uniform2f);
+        INSERT_PROC_ADDRESS(gl, Uniform2fv);
+        INSERT_PROC_ADDRESS(gl, Uniform2i);
+        INSERT_PROC_ADDRESS(gl, Uniform2iv);
+        INSERT_PROC_ADDRESS(gl, Uniform3f);
+        INSERT_PROC_ADDRESS(gl, Uniform3fv);
+        INSERT_PROC_ADDRESS(gl, Uniform3i);
+        INSERT_PROC_ADDRESS(gl, Uniform3iv);
+        INSERT_PROC_ADDRESS(gl, Uniform4f);
+        INSERT_PROC_ADDRESS(gl, Uniform4fv);
+        INSERT_PROC_ADDRESS(gl, Uniform4i);
+        INSERT_PROC_ADDRESS(gl, Uniform4iv);
+        INSERT_PROC_ADDRESS(gl, UniformMatrix2fv);
+        INSERT_PROC_ADDRESS(gl, UniformMatrix3fv);
+        INSERT_PROC_ADDRESS(gl, UniformMatrix4fv);
+        INSERT_PROC_ADDRESS(gl, UseProgram);
+        INSERT_PROC_ADDRESS(gl, ValidateProgram);
+        INSERT_PROC_ADDRESS(gl, VertexAttrib1f);
+        INSERT_PROC_ADDRESS(gl, VertexAttrib1fv);
+        INSERT_PROC_ADDRESS(gl, VertexAttrib2f);
+        INSERT_PROC_ADDRESS(gl, VertexAttrib2fv);
+        INSERT_PROC_ADDRESS(gl, VertexAttrib3f);
+        INSERT_PROC_ADDRESS(gl, VertexAttrib3fv);
+        INSERT_PROC_ADDRESS(gl, VertexAttrib4f);
+        INSERT_PROC_ADDRESS(gl, VertexAttrib4fv);
+        INSERT_PROC_ADDRESS(gl, VertexAttribPointer);
+        INSERT_PROC_ADDRESS(gl, Viewport);
+
+        // GL_ANGLE_framebuffer_blit
+        INSERT_PROC_ADDRESS(gl, BlitFramebufferANGLE);
+
+        // GL_ANGLE_framebuffer_multisample
+        INSERT_PROC_ADDRESS(gl, RenderbufferStorageMultisampleANGLE);
+
+        // GL_EXT_discard_framebuffer
+        INSERT_PROC_ADDRESS(gl, DiscardFramebufferEXT);
+
+        // GL_NV_fence
+        INSERT_PROC_ADDRESS(gl, DeleteFencesNV);
+        INSERT_PROC_ADDRESS(gl, GenFencesNV);
+        INSERT_PROC_ADDRESS(gl, IsFenceNV);
+        INSERT_PROC_ADDRESS(gl, TestFenceNV);
+        INSERT_PROC_ADDRESS(gl, GetFenceivNV);
+        INSERT_PROC_ADDRESS(gl, FinishFenceNV);
+        INSERT_PROC_ADDRESS(gl, SetFenceNV);
+
+        // GL_ANGLE_translated_shader_source
+        INSERT_PROC_ADDRESS(gl, GetTranslatedShaderSourceANGLE);
+
+        // GL_EXT_texture_storage
+        INSERT_PROC_ADDRESS(gl, TexStorage2DEXT);
+
+        // GL_EXT_robustness
+        INSERT_PROC_ADDRESS(gl, GetGraphicsResetStatusEXT);
+        INSERT_PROC_ADDRESS(gl, ReadnPixelsEXT);
+        INSERT_PROC_ADDRESS(gl, GetnUniformfvEXT);
+        INSERT_PROC_ADDRESS(gl, GetnUniformivEXT);
+
+        // GL_EXT_occlusion_query_boolean
+        INSERT_PROC_ADDRESS(gl, GenQueriesEXT);
+        INSERT_PROC_ADDRESS(gl, DeleteQueriesEXT);
+        INSERT_PROC_ADDRESS(gl, IsQueryEXT);
+        INSERT_PROC_ADDRESS(gl, BeginQueryEXT);
+        INSERT_PROC_ADDRESS(gl, EndQueryEXT);
+        INSERT_PROC_ADDRESS(gl, GetQueryivEXT);
+        INSERT_PROC_ADDRESS(gl, GetQueryObjectuivEXT);
+
+        // GL_EXT_disjoint_timer_query
+        // Commented out functions are needed for GL_EXT_disjoint_timer_query
+        // but are pulled in by GL_EXT_occlusion_query_boolean.
+        // INSERT_PROC_ADDRESS(gl, GenQueriesEXT);
+        // INSERT_PROC_ADDRESS(gl, DeleteQueriesEXT);
+        // INSERT_PROC_ADDRESS(gl, IsQueryEXT);
+        // INSERT_PROC_ADDRESS(gl, BeginQueryEXT);
+        // INSERT_PROC_ADDRESS(gl, EndQueryEXT);
+        INSERT_PROC_ADDRESS(gl, QueryCounterEXT);
+        // INSERT_PROC_ADDRESS(gl, GetQueryivEXT);
+        INSERT_PROC_ADDRESS(gl, GetQueryObjectivEXT);
+        // INSERT_PROC_ADDRESS(gl, GetQueryObjectuivEXT);
+        INSERT_PROC_ADDRESS(gl, GetQueryObjecti64vEXT);
+        INSERT_PROC_ADDRESS(gl, GetQueryObjectui64vEXT);
+
+        // GL_EXT_draw_buffers
+        INSERT_PROC_ADDRESS(gl, DrawBuffersEXT);
+
+        // GL_ANGLE_instanced_arrays
+        INSERT_PROC_ADDRESS(gl, DrawArraysInstancedANGLE);
+        INSERT_PROC_ADDRESS(gl, DrawElementsInstancedANGLE);
+        INSERT_PROC_ADDRESS(gl, VertexAttribDivisorANGLE);
+
+        // GL_OES_get_program_binary
+        INSERT_PROC_ADDRESS(gl, GetProgramBinaryOES);
+        INSERT_PROC_ADDRESS(gl, ProgramBinaryOES);
+
+        // GL_OES_mapbuffer
+        INSERT_PROC_ADDRESS(gl, MapBufferOES);
+        INSERT_PROC_ADDRESS(gl, UnmapBufferOES);
+        INSERT_PROC_ADDRESS(gl, GetBufferPointervOES);
+
+        // GL_EXT_map_buffer_range
+        INSERT_PROC_ADDRESS(gl, MapBufferRangeEXT);
+        INSERT_PROC_ADDRESS(gl, FlushMappedBufferRangeEXT);
+
+        // GL_EXT_debug_marker
+        INSERT_PROC_ADDRESS(gl, InsertEventMarkerEXT);
+        INSERT_PROC_ADDRESS(gl, PushGroupMarkerEXT);
+        INSERT_PROC_ADDRESS(gl, PopGroupMarkerEXT);
+
+        // GL_OES_EGL_image
+        INSERT_PROC_ADDRESS(gl, EGLImageTargetTexture2DOES);
+        INSERT_PROC_ADDRESS(gl, EGLImageTargetRenderbufferStorageOES);
+
+        // GL_OES_vertex_array_object
+        INSERT_PROC_ADDRESS(gl, BindVertexArrayOES);
+        INSERT_PROC_ADDRESS(gl, DeleteVertexArraysOES);
+        INSERT_PROC_ADDRESS(gl, GenVertexArraysOES);
+        INSERT_PROC_ADDRESS(gl, IsVertexArrayOES);
+
+        // GL_KHR_debug
+        INSERT_PROC_ADDRESS(gl, DebugMessageControlKHR);
+        INSERT_PROC_ADDRESS(gl, DebugMessageInsertKHR);
+        INSERT_PROC_ADDRESS(gl, DebugMessageCallbackKHR);
+        INSERT_PROC_ADDRESS(gl, GetDebugMessageLogKHR);
+        INSERT_PROC_ADDRESS(gl, PushDebugGroupKHR);
+        INSERT_PROC_ADDRESS(gl, PopDebugGroupKHR);
+        INSERT_PROC_ADDRESS(gl, ObjectLabelKHR);
+        INSERT_PROC_ADDRESS(gl, GetObjectLabelKHR);
+        INSERT_PROC_ADDRESS(gl, ObjectPtrLabelKHR);
+        INSERT_PROC_ADDRESS(gl, GetObjectPtrLabelKHR);
+        INSERT_PROC_ADDRESS(gl, GetPointervKHR);
+
+        // GL_CHROMIUM_bind_uniform_location
+        INSERT_PROC_ADDRESS(gl, BindUniformLocationCHROMIUM);
+
+        // GL_CHROMIUM_copy_texture
+        INSERT_PROC_ADDRESS(gl, CopyTextureCHROMIUM);
+        INSERT_PROC_ADDRESS(gl, CopySubTextureCHROMIUM);
+
+        // GL_CHROMIUM_copy_compressed_texture
+        INSERT_PROC_ADDRESS(gl, CompressedCopyTextureCHROMIUM);
+
+        // GL_ANGLE_request_extension
+        INSERT_PROC_ADDRESS(gl, RequestExtensionANGLE);
+
+        // GL_ANGLE_robust_client_memory
+        INSERT_PROC_ADDRESS(gl, GetBooleanvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetBufferParameterivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetFloatvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetFramebufferAttachmentParameterivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetIntegervRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetProgramivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetRenderbufferParameterivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetShaderivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetTexParameterfvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetTexParameterivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetUniformfvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetUniformivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribfvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribPointervRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, ReadPixelsRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, TexImage2DRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, TexParameterfvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, TexParameterivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, TexSubImage2DRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, TexImage3DRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, TexSubImage3DRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, CompressedTexImage2DRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, CompressedTexSubImage2DRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, CompressedTexImage3DRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, CompressedTexSubImage3DRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetQueryivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetQueryObjectuivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetBufferPointervRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetIntegeri_vRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetInternalformativRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribIivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribIuivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetUniformuivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetActiveUniformBlockivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetInteger64vRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetInteger64i_vRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetBufferParameteri64vRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, SamplerParameterivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, SamplerParameterfvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetSamplerParameterivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetSamplerParameterfvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetFramebufferParameterivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetProgramInterfaceivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetBooleani_vRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetMultisamplefvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetTexLevelParameterivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetTexLevelParameterfvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetPointervRobustANGLERobustANGLE);
+        INSERT_PROC_ADDRESS(gl, ReadnPixelsRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetnUniformfvRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetnUniformivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetnUniformuivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, TexParameterIivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, TexParameterIuivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetTexParameterIivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetTexParameterIuivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, SamplerParameterIivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, SamplerParameterIuivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetSamplerParameterIivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetSamplerParameterIuivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetQueryObjectivRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetQueryObjecti64vRobustANGLE);
+        INSERT_PROC_ADDRESS(gl, GetQueryObjectui64vRobustANGLE);
+
+        // GLES3 core
+        INSERT_PROC_ADDRESS(gl, ReadBuffer);
+        INSERT_PROC_ADDRESS(gl, DrawRangeElements);
+        INSERT_PROC_ADDRESS(gl, TexImage3D);
+        INSERT_PROC_ADDRESS(gl, TexSubImage3D);
+        INSERT_PROC_ADDRESS(gl, CopyTexSubImage3D);
+        INSERT_PROC_ADDRESS(gl, CompressedTexImage3D);
+        INSERT_PROC_ADDRESS(gl, CompressedTexSubImage3D);
+        INSERT_PROC_ADDRESS(gl, GenQueries);
+        INSERT_PROC_ADDRESS(gl, DeleteQueries);
+        INSERT_PROC_ADDRESS(gl, IsQuery);
+        INSERT_PROC_ADDRESS(gl, BeginQuery);
+        INSERT_PROC_ADDRESS(gl, EndQuery);
+        INSERT_PROC_ADDRESS(gl, GetQueryiv);
+        INSERT_PROC_ADDRESS(gl, GetQueryObjectuiv);
+        INSERT_PROC_ADDRESS(gl, UnmapBuffer);
+        INSERT_PROC_ADDRESS(gl, GetBufferPointerv);
+        INSERT_PROC_ADDRESS(gl, DrawBuffers);
+        INSERT_PROC_ADDRESS(gl, UniformMatrix2x3fv);
+        INSERT_PROC_ADDRESS(gl, UniformMatrix3x2fv);
+        INSERT_PROC_ADDRESS(gl, UniformMatrix2x4fv);
+        INSERT_PROC_ADDRESS(gl, UniformMatrix4x2fv);
+        INSERT_PROC_ADDRESS(gl, UniformMatrix3x4fv);
+        INSERT_PROC_ADDRESS(gl, UniformMatrix4x3fv);
+        INSERT_PROC_ADDRESS(gl, BlitFramebuffer);
+        INSERT_PROC_ADDRESS(gl, RenderbufferStorageMultisample);
+        INSERT_PROC_ADDRESS(gl, FramebufferTextureLayer);
+        INSERT_PROC_ADDRESS(gl, MapBufferRange);
+        INSERT_PROC_ADDRESS(gl, FlushMappedBufferRange);
+        INSERT_PROC_ADDRESS(gl, BindVertexArray);
+        INSERT_PROC_ADDRESS(gl, DeleteVertexArrays);
+        INSERT_PROC_ADDRESS(gl, GenVertexArrays);
+        INSERT_PROC_ADDRESS(gl, IsVertexArray);
+        INSERT_PROC_ADDRESS(gl, GetIntegeri_v);
+        INSERT_PROC_ADDRESS(gl, BeginTransformFeedback);
+        INSERT_PROC_ADDRESS(gl, EndTransformFeedback);
+        INSERT_PROC_ADDRESS(gl, BindBufferRange);
+        INSERT_PROC_ADDRESS(gl, BindBufferBase);
+        INSERT_PROC_ADDRESS(gl, TransformFeedbackVaryings);
+        INSERT_PROC_ADDRESS(gl, GetTransformFeedbackVarying);
+        INSERT_PROC_ADDRESS(gl, VertexAttribIPointer);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribIiv);
+        INSERT_PROC_ADDRESS(gl, GetVertexAttribIuiv);
+        INSERT_PROC_ADDRESS(gl, VertexAttribI4i);
+        INSERT_PROC_ADDRESS(gl, VertexAttribI4ui);
+        INSERT_PROC_ADDRESS(gl, VertexAttribI4iv);
+        INSERT_PROC_ADDRESS(gl, VertexAttribI4uiv);
+        INSERT_PROC_ADDRESS(gl, GetUniformuiv);
+        INSERT_PROC_ADDRESS(gl, GetFragDataLocation);
+        INSERT_PROC_ADDRESS(gl, Uniform1ui);
+        INSERT_PROC_ADDRESS(gl, Uniform2ui);
+        INSERT_PROC_ADDRESS(gl, Uniform3ui);
+        INSERT_PROC_ADDRESS(gl, Uniform4ui);
+        INSERT_PROC_ADDRESS(gl, Uniform1uiv);
+        INSERT_PROC_ADDRESS(gl, Uniform2uiv);
+        INSERT_PROC_ADDRESS(gl, Uniform3uiv);
+        INSERT_PROC_ADDRESS(gl, Uniform4uiv);
+        INSERT_PROC_ADDRESS(gl, ClearBufferiv);
+        INSERT_PROC_ADDRESS(gl, ClearBufferuiv);
+        INSERT_PROC_ADDRESS(gl, ClearBufferfv);
+        INSERT_PROC_ADDRESS(gl, ClearBufferfi);
+        INSERT_PROC_ADDRESS(gl, GetStringi);
+        INSERT_PROC_ADDRESS(gl, CopyBufferSubData);
+        INSERT_PROC_ADDRESS(gl, GetUniformIndices);
+        INSERT_PROC_ADDRESS(gl, GetActiveUniformsiv);
+        INSERT_PROC_ADDRESS(gl, GetUniformBlockIndex);
+        INSERT_PROC_ADDRESS(gl, GetActiveUniformBlockiv);
+        INSERT_PROC_ADDRESS(gl, GetActiveUniformBlockName);
+        INSERT_PROC_ADDRESS(gl, UniformBlockBinding);
+        INSERT_PROC_ADDRESS(gl, DrawArraysInstanced);
+        INSERT_PROC_ADDRESS(gl, DrawElementsInstanced);
+        // FenceSync is the name of a class, the function has an added _ to prevent a name conflict.
+        INSERT_PROC_ADDRESS_NO_NS("glFenceSync", gl::FenceSync_);
+        INSERT_PROC_ADDRESS(gl, IsSync);
+        INSERT_PROC_ADDRESS(gl, DeleteSync);
+        INSERT_PROC_ADDRESS(gl, ClientWaitSync);
+        INSERT_PROC_ADDRESS(gl, WaitSync);
+        INSERT_PROC_ADDRESS(gl, GetInteger64v);
+        INSERT_PROC_ADDRESS(gl, GetSynciv);
+        INSERT_PROC_ADDRESS(gl, GetInteger64i_v);
+        INSERT_PROC_ADDRESS(gl, GetBufferParameteri64v);
+        INSERT_PROC_ADDRESS(gl, GenSamplers);
+        INSERT_PROC_ADDRESS(gl, DeleteSamplers);
+        INSERT_PROC_ADDRESS(gl, IsSampler);
+        INSERT_PROC_ADDRESS(gl, BindSampler);
+        INSERT_PROC_ADDRESS(gl, SamplerParameteri);
+        INSERT_PROC_ADDRESS(gl, SamplerParameteriv);
+        INSERT_PROC_ADDRESS(gl, SamplerParameterf);
+        INSERT_PROC_ADDRESS(gl, SamplerParameterfv);
+        INSERT_PROC_ADDRESS(gl, GetSamplerParameteriv);
+        INSERT_PROC_ADDRESS(gl, GetSamplerParameterfv);
+        INSERT_PROC_ADDRESS(gl, VertexAttribDivisor);
+        INSERT_PROC_ADDRESS(gl, BindTransformFeedback);
+        INSERT_PROC_ADDRESS(gl, DeleteTransformFeedbacks);
+        INSERT_PROC_ADDRESS(gl, GenTransformFeedbacks);
+        INSERT_PROC_ADDRESS(gl, IsTransformFeedback);
+        INSERT_PROC_ADDRESS(gl, PauseTransformFeedback);
+        INSERT_PROC_ADDRESS(gl, ResumeTransformFeedback);
+        INSERT_PROC_ADDRESS(gl, GetProgramBinary);
+        INSERT_PROC_ADDRESS(gl, ProgramBinary);
+        INSERT_PROC_ADDRESS(gl, ProgramParameteri);
+        INSERT_PROC_ADDRESS(gl, InvalidateFramebuffer);
+        INSERT_PROC_ADDRESS(gl, InvalidateSubFramebuffer);
+        INSERT_PROC_ADDRESS(gl, TexStorage2D);
+        INSERT_PROC_ADDRESS(gl, TexStorage3D);
+        INSERT_PROC_ADDRESS(gl, GetInternalformativ);
+
+        // GLES31 core
+        INSERT_PROC_ADDRESS(gl, DispatchCompute);
+        INSERT_PROC_ADDRESS(gl, DispatchComputeIndirect);
+        INSERT_PROC_ADDRESS(gl, DrawArraysIndirect);
+        INSERT_PROC_ADDRESS(gl, DrawElementsIndirect);
+        INSERT_PROC_ADDRESS(gl, FramebufferParameteri);
+        INSERT_PROC_ADDRESS(gl, GetFramebufferParameteriv);
+        INSERT_PROC_ADDRESS(gl, GetProgramInterfaceiv);
+        INSERT_PROC_ADDRESS(gl, GetProgramResourceIndex);
+        INSERT_PROC_ADDRESS(gl, GetProgramResourceName);
+        INSERT_PROC_ADDRESS(gl, GetProgramResourceiv);
+        INSERT_PROC_ADDRESS(gl, GetProgramResourceLocation);
+        INSERT_PROC_ADDRESS(gl, UseProgramStages);
+        INSERT_PROC_ADDRESS(gl, ActiveShaderProgram);
+        INSERT_PROC_ADDRESS(gl, CreateShaderProgramv);
+        INSERT_PROC_ADDRESS(gl, BindProgramPipeline);
+        INSERT_PROC_ADDRESS(gl, DeleteProgramPipelines);
+        INSERT_PROC_ADDRESS(gl, GenProgramPipelines);
+        INSERT_PROC_ADDRESS(gl, IsProgramPipeline);
+        INSERT_PROC_ADDRESS(gl, GetProgramPipelineiv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform1i);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform2i);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform3i);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform4i);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform1ui);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform2ui);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform3ui);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform4ui);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform1f);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform2f);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform3f);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform4f);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform1iv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform2iv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform3iv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform4iv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform1uiv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform2uiv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform3uiv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform4uiv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform1fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform2fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform3fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniform4fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniformMatrix2fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniformMatrix3fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniformMatrix4fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniformMatrix2x3fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniformMatrix3x2fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniformMatrix2x4fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniformMatrix4x2fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniformMatrix3x4fv);
+        INSERT_PROC_ADDRESS(gl, ProgramUniformMatrix4x3fv);
+        INSERT_PROC_ADDRESS(gl, ValidateProgramPipeline);
+        INSERT_PROC_ADDRESS(gl, GetProgramPipelineInfoLog);
+        INSERT_PROC_ADDRESS(gl, BindImageTexture);
+        INSERT_PROC_ADDRESS(gl, GetBooleani_v);
+        INSERT_PROC_ADDRESS(gl, MemoryBarrier);
+        INSERT_PROC_ADDRESS(gl, MemoryBarrierByRegion);
+        INSERT_PROC_ADDRESS(gl, TexStorage2DMultisample);
+        INSERT_PROC_ADDRESS(gl, GetMultisamplefv);
+        INSERT_PROC_ADDRESS(gl, SampleMaski);
+        INSERT_PROC_ADDRESS(gl, GetTexLevelParameteriv);
+        INSERT_PROC_ADDRESS(gl, GetTexLevelParameterfv);
+        INSERT_PROC_ADDRESS(gl, BindVertexBuffer);
+        INSERT_PROC_ADDRESS(gl, VertexAttribFormat);
+        INSERT_PROC_ADDRESS(gl, VertexAttribIFormat);
+        INSERT_PROC_ADDRESS(gl, VertexAttribBinding);
+        INSERT_PROC_ADDRESS(gl, VertexBindingDivisor);
+
+        // EGL 1.0
+        INSERT_PROC_ADDRESS(egl, ChooseConfig);
+        INSERT_PROC_ADDRESS(egl, CopyBuffers);
+        INSERT_PROC_ADDRESS(egl, CreateContext);
+        INSERT_PROC_ADDRESS(egl, CreatePbufferSurface);
+        INSERT_PROC_ADDRESS(egl, CreatePixmapSurface);
+        INSERT_PROC_ADDRESS(egl, CreateWindowSurface);
+        INSERT_PROC_ADDRESS(egl, DestroyContext);
+        INSERT_PROC_ADDRESS(egl, DestroySurface);
+        INSERT_PROC_ADDRESS(egl, GetConfigAttrib);
+        INSERT_PROC_ADDRESS(egl, GetConfigs);
+        INSERT_PROC_ADDRESS(egl, GetCurrentDisplay);
+        INSERT_PROC_ADDRESS(egl, GetCurrentSurface);
+        INSERT_PROC_ADDRESS(egl, GetDisplay);
+        INSERT_PROC_ADDRESS(egl, GetError);
+        INSERT_PROC_ADDRESS(egl, GetProcAddress);
+        INSERT_PROC_ADDRESS(egl, Initialize);
+        INSERT_PROC_ADDRESS(egl, MakeCurrent);
+        INSERT_PROC_ADDRESS(egl, QueryContext);
+        INSERT_PROC_ADDRESS(egl, QueryString);
+        INSERT_PROC_ADDRESS(egl, QuerySurface);
+        INSERT_PROC_ADDRESS(egl, SwapBuffers);
+        INSERT_PROC_ADDRESS(egl, Terminate);
+        INSERT_PROC_ADDRESS(egl, WaitGL);
+        INSERT_PROC_ADDRESS(egl, WaitNative);
+
+        // EGL 1.1
+        INSERT_PROC_ADDRESS(egl, BindTexImage);
+        INSERT_PROC_ADDRESS(egl, ReleaseTexImage);
+        INSERT_PROC_ADDRESS(egl, SurfaceAttrib);
+        INSERT_PROC_ADDRESS(egl, SwapInterval);
+
+        // EGL 1.2
+        INSERT_PROC_ADDRESS(egl, BindAPI);
+        INSERT_PROC_ADDRESS(egl, QueryAPI);
+        INSERT_PROC_ADDRESS(egl, CreatePbufferFromClientBuffer);
+        INSERT_PROC_ADDRESS(egl, ReleaseThread);
+        INSERT_PROC_ADDRESS(egl, WaitClient);
+
+        // EGL 1.4
+        INSERT_PROC_ADDRESS(egl, GetCurrentContext);
+
+        // EGL 1.5
+        INSERT_PROC_ADDRESS(egl, CreateSync);
+        INSERT_PROC_ADDRESS(egl, DestroySync);
+        INSERT_PROC_ADDRESS(egl, ClientWaitSync);
+        INSERT_PROC_ADDRESS(egl, GetSyncAttrib);
+        INSERT_PROC_ADDRESS(egl, CreateImage);
+        INSERT_PROC_ADDRESS(egl, DestroyImage);
+        INSERT_PROC_ADDRESS(egl, GetPlatformDisplay);
+        INSERT_PROC_ADDRESS(egl, CreatePlatformWindowSurface);
+        INSERT_PROC_ADDRESS(egl, CreatePlatformPixmapSurface);
+        INSERT_PROC_ADDRESS(egl, WaitSync);
+
+        // EGL_ANGLE_query_surface_pointer
+        INSERT_PROC_ADDRESS(egl, QuerySurfacePointerANGLE);
+
+        // EGL_NV_post_sub_buffer
+        INSERT_PROC_ADDRESS(egl, PostSubBufferNV);
+
+        // EGL_EXT_platform_base
+        INSERT_PROC_ADDRESS(egl, GetPlatformDisplayEXT);
+
+        // EGL_EXT_device_query
+        INSERT_PROC_ADDRESS(egl, QueryDisplayAttribEXT);
+        INSERT_PROC_ADDRESS(egl, QueryDeviceAttribEXT);
+        INSERT_PROC_ADDRESS(egl, QueryDeviceStringEXT);
+
+        // EGL_KHR_image_base/EGL_KHR_image
+        INSERT_PROC_ADDRESS(egl, CreateImageKHR);
+        INSERT_PROC_ADDRESS(egl, DestroyImageKHR);
+
+        // EGL_EXT_device_creation
+        INSERT_PROC_ADDRESS(egl, CreateDeviceANGLE);
+        INSERT_PROC_ADDRESS(egl, ReleaseDeviceANGLE);
+
+        // EGL_KHR_stream
+        INSERT_PROC_ADDRESS(egl, CreateStreamKHR);
+        INSERT_PROC_ADDRESS(egl, DestroyStreamKHR);
+        INSERT_PROC_ADDRESS(egl, StreamAttribKHR);
+        INSERT_PROC_ADDRESS(egl, QueryStreamKHR);
+        INSERT_PROC_ADDRESS(egl, QueryStreamu64KHR);
+
+        // EGL_KHR_stream_consumer_gltexture
+        INSERT_PROC_ADDRESS(egl, StreamConsumerGLTextureExternalKHR);
+        INSERT_PROC_ADDRESS(egl, StreamConsumerAcquireKHR);
+        INSERT_PROC_ADDRESS(egl, StreamConsumerReleaseKHR);
+
+        // EGL_NV_stream_consumer_gltexture_yuv
+        INSERT_PROC_ADDRESS(egl, StreamConsumerGLTextureExternalAttribsNV);
+
+        // EGL_ANGLE_stream_producer_d3d_texture_nv12
+        INSERT_PROC_ADDRESS(egl, CreateStreamProducerD3DTextureNV12ANGLE);
+        INSERT_PROC_ADDRESS(egl, StreamPostD3DTextureNV12ANGLE);
+
+        // EGL_CHROMIUM_get_sync_values
+        INSERT_PROC_ADDRESS(egl, GetSyncValuesCHROMIUM);
+
+        // EGL_EXT_swap_buffers_with_damage
+        INSERT_PROC_ADDRESS(egl, SwapBuffersWithDamageEXT);
+
+        // angle::Platform related entry points
+        INSERT_PROC_ADDRESS_NO_NS("ANGLEGetDisplayPlatform", ANGLEGetDisplayPlatform);
+        INSERT_PROC_ADDRESS_NO_NS("ANGLEResetDisplayPlatform", ANGLEResetDisplayPlatform);
+
+#undef INSERT_PROC_ADDRESS
+#undef INSERT_PROC_ADDRESS_NO_NS
+
+        return map;
+    };
+
+    static const ProcAddressMap procAddressMap = generateProcAddressMap();
+
+    thread->setError(Error(EGL_SUCCESS));
+    auto iter = procAddressMap.find(procname);
+    return iter != procAddressMap.end() ? iter->second : nullptr;
+}
+}
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_egl.h b/src/third_party/angle/src/libGLESv2/entry_points_egl.h
new file mode 100644
index 0000000..259a209
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_egl.h
@@ -0,0 +1,74 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_egl.h : Defines the EGL entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTSEGL_H_
+#define LIBGLESV2_ENTRYPOINTSEGL_H_
+
+#include <EGL/egl.h>
+#include <export.h>
+
+namespace egl
+{
+
+// EGL 1.0
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+ANGLE_EXPORT EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetCurrentDisplay(void);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw);
+ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id);
+ANGLE_EXPORT EGLint EGLAPIENTRY GetError(void);
+ANGLE_EXPORT __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+ANGLE_EXPORT const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitGL(void);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitNative(EGLint engine);
+
+// EGL 1.1
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval);
+
+// EGL 1.2
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY BindAPI(EGLenum api);
+ANGLE_EXPORT EGLenum EGLAPIENTRY QueryAPI(void);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseThread(void);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitClient(void);
+
+// EGL 1.4
+ANGLE_EXPORT EGLContext EGLAPIENTRY GetCurrentContext(void);
+
+// EGL 1.5
+ANGLE_EXPORT EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroySync(EGLDisplay dpy, EGLSync sync);
+ANGLE_EXPORT EGLint EGLAPIENTRY ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+ANGLE_EXPORT EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image);
+ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags);
+
+}
+
+#endif // LIBGLESV2_ENTRYPOINTSEGL_H_
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/third_party/angle/src/libGLESv2/entry_points_egl_ext.cpp
new file mode 100644
index 0000000..09a4a68
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_egl_ext.cpp
@@ -0,0 +1,998 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_ext.cpp : Implements the EGL extension entry points.
+
+#include "libGLESv2/entry_points_egl_ext.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/validationEGL.h"
+
+#include "common/debug.h"
+
+namespace egl
+{
+
+// EGL_ANGLE_query_surface_pointer
+EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
+          dpy, surface, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = static_cast<Display*>(dpy);
+    Surface *eglSurface = static_cast<Surface*>(surface);
+
+    Error error = ValidateSurface(display, eglSurface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (!display->getExtensions().querySurfacePointer)
+    {
+        thread->setError(Error(EGL_SUCCESS));
+        return EGL_FALSE;
+    }
+
+    if (surface == EGL_NO_SURFACE)
+    {
+        thread->setError(Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
+    }
+
+    // validate the attribute parameter
+    switch (attribute)
+    {
+      case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+        if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
+        {
+            thread->setError(Error(EGL_BAD_ATTRIBUTE));
+            return EGL_FALSE;
+        }
+        break;
+      case EGL_DXGI_KEYED_MUTEX_ANGLE:
+        if (!display->getExtensions().keyedMutex)
+        {
+            thread->setError(Error(EGL_BAD_ATTRIBUTE));
+            return EGL_FALSE;
+        }
+        break;
+      default:
+          thread->setError(Error(EGL_BAD_ATTRIBUTE));
+          return EGL_FALSE;
+    }
+
+    error = eglSurface->querySurfacePointerANGLE(attribute, value);
+    thread->setError(error);
+    return (error.isError() ? EGL_FALSE : EGL_TRUE);
+}
+
+
+// EGL_NV_post_sub_buffer
+EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
+    Thread *thread = GetCurrentThread();
+
+    if (x < 0 || y < 0 || width < 0 || height < 0)
+    {
+        thread->setError(Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;
+    }
+
+    Display *display = static_cast<Display*>(dpy);
+    Surface *eglSurface = static_cast<Surface*>(surface);
+
+    Error error = ValidateSurface(display, eglSurface);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (display->testDeviceLost())
+    {
+        thread->setError(Error(EGL_CONTEXT_LOST));
+        return EGL_FALSE;
+    }
+
+    if (surface == EGL_NO_SURFACE)
+    {
+        thread->setError(Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
+    }
+
+    if (!display->getExtensions().postSubBuffer)
+    {
+        // Spec is not clear about how this should be handled.
+        thread->setError(Error(EGL_SUCCESS));
+        return EGL_TRUE;
+    }
+
+    error = eglSurface->postSubBuffer(x, y, width, height);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return EGL_TRUE;
+}
+
+// EGL_EXT_platform_base
+EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
+{
+    EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
+          platform, native_display, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    const ClientExtensions &clientExtensions = Display::getClientExtensions();
+
+    switch (platform)
+    {
+      case EGL_PLATFORM_ANGLE_ANGLE:
+        if (!clientExtensions.platformANGLE)
+        {
+            thread->setError(Error(EGL_BAD_PARAMETER));
+            return EGL_NO_DISPLAY;
+        }
+        break;
+      case EGL_PLATFORM_DEVICE_EXT:
+          if (!clientExtensions.platformDevice)
+          {
+              thread->setError(Error(EGL_BAD_PARAMETER, "Platform Device extension is not active"));
+              return EGL_NO_DISPLAY;
+          }
+          break;
+      default:
+          thread->setError(Error(EGL_BAD_CONFIG));
+          return EGL_NO_DISPLAY;
+    }
+
+    if (platform == EGL_PLATFORM_ANGLE_ANGLE)
+    {
+        EGLint platformType          = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
+        EGLint deviceType            = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
+        bool enableAutoTrimSpecified = false;
+        bool deviceTypeSpecified     = false;
+        bool presentPathSpecified    = false;
+
+        Optional<EGLint> majorVersion;
+        Optional<EGLint> minorVersion;
+
+        if (attrib_list)
+        {
+            for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
+            {
+                switch (curAttrib[0])
+                {
+                    case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
+                    {
+                        egl::Error error = ValidatePlatformType(clientExtensions, curAttrib[1]);
+                        if (error.isError())
+                        {
+                            thread->setError(error);
+                            return EGL_NO_DISPLAY;
+                        }
+                        platformType = curAttrib[1];
+                        break;
+                    }
+
+                    case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
+                        if (curAttrib[1] != EGL_DONT_CARE)
+                        {
+                            majorVersion = curAttrib[1];
+                        }
+                        break;
+
+                    case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
+                        if (curAttrib[1] != EGL_DONT_CARE)
+                        {
+                            minorVersion = curAttrib[1];
+                        }
+                        break;
+
+                    case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
+                        switch (curAttrib[1])
+                    {
+                        case EGL_TRUE:
+                        case EGL_FALSE:
+                            break;
+                        default:
+                            thread->setError(Error(EGL_BAD_ATTRIBUTE));
+                            return EGL_NO_DISPLAY;
+                    }
+                    enableAutoTrimSpecified = true;
+                    break;
+
+                    case EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE:
+                        if (!clientExtensions.experimentalPresentPath)
+                        {
+                            thread->setError(
+                                Error(EGL_BAD_ATTRIBUTE,
+                                      "EGL_ANGLE_experimental_present_path extension not active"));
+                            return EGL_NO_DISPLAY;
+                        }
+
+                        switch (curAttrib[1])
+                        {
+                            case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
+                            case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
+                                break;
+                            default:
+                                thread->setError(
+                                    Error(EGL_BAD_ATTRIBUTE,
+                                          "Invalid value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE"));
+                                return EGL_NO_DISPLAY;
+                        }
+                        presentPathSpecified = true;
+                        break;
+
+                    case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
+                        switch (curAttrib[1])
+                        {
+                            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+                            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
+                            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+                                deviceTypeSpecified = true;
+                                break;
+
+                            case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+                                // This is a hidden option, accepted by the OpenGL back-end.
+                                break;
+
+                            default:
+                                thread->setError(Error(EGL_BAD_ATTRIBUTE,
+                                                       "Invalid value for "
+                                                       "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE "
+                                                       "attrib"));
+                                return EGL_NO_DISPLAY;
+                        }
+                        deviceType = curAttrib[1];
+                    break;
+
+                    case EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE:
+                        if (!clientExtensions.platformANGLEVulkan)
+                        {
+                            thread->setError(
+                                Error(EGL_BAD_ATTRIBUTE,
+                                      "EGL_ANGLE_platform_angle_vulkan extension not active"));
+                            return EGL_NO_DISPLAY;
+                        }
+                        if (platformType != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
+                        {
+                            thread->setError(
+                                Error(EGL_BAD_ATTRIBUTE,
+                                      "Validation can only be enabled for the Vulkan back-end."));
+                            return EGL_NO_DISPLAY;
+                        }
+                        if (curAttrib[1] != EGL_TRUE && curAttrib[1] != EGL_FALSE)
+                        {
+                            thread->setError(
+                                Error(EGL_BAD_ATTRIBUTE,
+                                      "Validation layer attribute must be EGL_TRUE or EGL_FALSE."));
+                            return EGL_NO_DISPLAY;
+                        }
+                        break;
+
+                    default:
+                        break;
+                }
+            }
+        }
+
+        if (!majorVersion.valid() && minorVersion.valid())
+        {
+            thread->setError(Error(EGL_BAD_ATTRIBUTE));
+            return EGL_NO_DISPLAY;
+        }
+
+        if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE &&
+            platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+        {
+            thread->setError(
+                Error(EGL_BAD_ATTRIBUTE,
+                      "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a device type of "
+                      "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE."));
+            return EGL_NO_DISPLAY;
+        }
+
+        if (enableAutoTrimSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+        {
+            thread->setError(
+                Error(EGL_BAD_ATTRIBUTE,
+                      "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE requires a device type of "
+                      "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE."));
+            return EGL_NO_DISPLAY;
+        }
+
+        if (presentPathSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+        {
+            thread->setError(Error(EGL_BAD_ATTRIBUTE,
+                                   "EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE requires a device type of "
+                                   "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE."));
+            return EGL_NO_DISPLAY;
+        }
+
+        if (deviceTypeSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE &&
+            platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+        {
+            thread->setError(
+                Error(EGL_BAD_ATTRIBUTE,
+                      "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE requires a device type of "
+                      "EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE or EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE."));
+            return EGL_NO_DISPLAY;
+        }
+
+        if (platformType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
+        {
+            if ((majorVersion.valid() && majorVersion.value() != 1) ||
+                (minorVersion.valid() && minorVersion.value() != 0))
+            {
+                thread->setError(Error(
+                    EGL_BAD_ATTRIBUTE,
+                    "EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE currently only supports Vulkan 1.0."));
+                return EGL_NO_DISPLAY;
+            }
+        }
+
+        thread->setError(Error(EGL_SUCCESS));
+        return Display::GetDisplayFromNativeDisplay(
+            gl::bitCast<EGLNativeDisplayType>(native_display),
+            AttributeMap::CreateFromIntArray(attrib_list));
+    }
+    else if (platform == EGL_PLATFORM_DEVICE_EXT)
+    {
+        Device *eglDevice = reinterpret_cast<Device *>(native_display);
+        if (eglDevice == nullptr || !Device::IsValidDevice(eglDevice))
+        {
+            thread->setError(Error(EGL_BAD_ATTRIBUTE,
+                                   "native_display should be a valid EGL device if platform equals "
+                                   "EGL_PLATFORM_DEVICE_EXT"));
+            return EGL_NO_DISPLAY;
+        }
+
+        thread->setError(Error(EGL_SUCCESS));
+        return Display::GetDisplayFromDevice(eglDevice);
+    }
+    else
+    {
+        UNREACHABLE();
+        return EGL_NO_DISPLAY;
+    }
+}
+
+// EGL_EXT_device_query
+EGLBoolean EGLAPIENTRY QueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value)
+{
+    EVENT("(EGLDeviceEXT device = 0x%0.8p, EGLint attribute = %d, EGLAttrib *value = 0x%0.8p)",
+          device, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Device *dev = static_cast<Device*>(device);
+    if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
+    {
+        thread->setError(Error(EGL_BAD_ACCESS));
+        return EGL_FALSE;
+    }
+
+    // If the device was created by (and is owned by) a display, and that display doesn't support
+    // device querying, then this call should fail
+    Display *owningDisplay = dev->getOwningDisplay();
+    if (owningDisplay != nullptr && !owningDisplay->getExtensions().deviceQuery)
+    {
+        thread->setError(Error(EGL_BAD_ACCESS,
+                               "Device wasn't created using eglCreateDeviceANGLE, and the Display "
+                               "that created it doesn't support device querying"));
+        return EGL_FALSE;
+    }
+
+    Error error(EGL_SUCCESS);
+
+    // validate the attribute parameter
+    switch (attribute)
+    {
+      case EGL_D3D11_DEVICE_ANGLE:
+      case EGL_D3D9_DEVICE_ANGLE:
+        if (!dev->getExtensions().deviceD3D || dev->getType() != attribute)
+        {
+            thread->setError(Error(EGL_BAD_ATTRIBUTE));
+            return EGL_FALSE;
+        }
+        error = dev->getDevice(value);
+        break;
+      default:
+          thread->setError(Error(EGL_BAD_ATTRIBUTE));
+          return EGL_FALSE;
+    }
+
+    thread->setError(error);
+    return (error.isError() ? EGL_FALSE : EGL_TRUE);
+}
+
+// EGL_EXT_device_query
+const char * EGLAPIENTRY QueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
+{
+    EVENT("(EGLDeviceEXT device = 0x%0.8p, EGLint name = %d)",
+          device, name);
+    Thread *thread = GetCurrentThread();
+
+    Device *dev = static_cast<Device*>(device);
+    if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
+    {
+        thread->setError(Error(EGL_BAD_DEVICE_EXT));
+        return nullptr;
+    }
+
+    const char *result;
+    switch (name)
+    {
+      case EGL_EXTENSIONS:
+        result = dev->getExtensionString().c_str();
+        break;
+      default:
+          thread->setError(Error(EGL_BAD_DEVICE_EXT));
+          return nullptr;
+    }
+
+    thread->setError(Error(EGL_SUCCESS));
+    return result;
+}
+
+// EGL_EXT_device_query
+EGLBoolean EGLAPIENTRY QueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint attribute = %d, EGLAttrib *value = 0x%0.8p)",
+          dpy, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = static_cast<Display*>(dpy);
+
+    Error error = ValidateDisplay(display);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    if (!display->getExtensions().deviceQuery)
+    {
+        thread->setError(Error(EGL_BAD_ACCESS));
+        return EGL_FALSE;
+    }
+
+    // validate the attribute parameter
+    switch (attribute)
+    {
+      case EGL_DEVICE_EXT:
+        *value = reinterpret_cast<EGLAttrib>(display->getDevice());
+        break;
+
+      default:
+          thread->setError(Error(EGL_BAD_ATTRIBUTE));
+          return EGL_FALSE;
+    }
+
+    thread->setError(error);
+    return (error.isError() ? EGL_FALSE : EGL_TRUE);
+}
+
+ANGLE_EXPORT EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy,
+                                                    EGLContext ctx,
+                                                    EGLenum target,
+                                                    EGLClientBuffer buffer,
+                                                    const EGLint *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, "
+        "EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)",
+        dpy, ctx, target, buffer, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    gl::Context *context = static_cast<gl::Context *>(ctx);
+    AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
+
+    Error error = ValidateCreateImageKHR(display, context, target, buffer, attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_IMAGE;
+    }
+
+    Image *image = nullptr;
+    error = display->createImage(context, target, buffer, attributes, &image);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_IMAGE;
+    }
+
+    return static_cast<EGLImage>(image);
+}
+
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLImage image = 0x%0.8p)", dpy, image);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = static_cast<Display *>(dpy);
+    Image *img       = static_cast<Image *>(image);
+
+    Error error = ValidateDestroyImageKHR(display, img);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    display->destroyImage(img);
+
+    return EGL_TRUE;
+}
+
+ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
+                                                        void *native_device,
+                                                        const EGLAttrib *attrib_list)
+{
+    EVENT(
+        "(EGLint device_type = %d, void* native_device = 0x%0.8p, const EGLAttrib* attrib_list = "
+        "0x%0.8p)",
+        device_type, native_device, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Error error = ValidateCreateDeviceANGLE(device_type, native_device, attrib_list);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_DEVICE_EXT;
+    }
+
+    Device *device = nullptr;
+    error = Device::CreateDevice(native_device, device_type, &device);
+    if (error.isError())
+    {
+        ASSERT(device == nullptr);
+        thread->setError(error);
+        return EGL_NO_DEVICE_EXT;
+    }
+
+    return device;
+}
+
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device)
+{
+    EVENT("(EGLDeviceEXT device = 0x%0.8p)", device);
+    Thread *thread = GetCurrentThread();
+
+    Device *dev = static_cast<Device *>(device);
+
+    Error error = ValidateReleaseDeviceANGLE(dev);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    SafeDelete(dev);
+
+    return EGL_TRUE;
+}
+
+// EGL_KHR_stream
+EGLStreamKHR EGLAPIENTRY CreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLAttrib* attrib_list = 0x%0.8p)", dpy, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Display *display = static_cast<Display *>(dpy);
+    AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
+
+    Error error = ValidateCreateStreamKHR(display, attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_STREAM_KHR;
+    }
+
+    Stream *stream;
+    error = display->createStream(attributes, &stream);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_NO_STREAM_KHR;
+    }
+
+    thread->setError(error);
+    return static_cast<EGLStreamKHR>(stream);
+}
+
+EGLBoolean EGLAPIENTRY DestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    Stream *streamObject = static_cast<Stream *>(stream);
+
+    Error error = ValidateDestroyStreamKHR(display, streamObject);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    display->destroyStream(streamObject);
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamAttribKHR(EGLDisplay dpy,
+                                       EGLStreamKHR stream,
+                                       EGLenum attribute,
+                                       EGLint value)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
+        "EGLint value = 0x%X)",
+        dpy, stream, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    Stream *streamObject = static_cast<Stream *>(stream);
+
+    Error error = ValidateStreamAttribKHR(display, streamObject, attribute, value);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    switch (attribute)
+    {
+        case EGL_CONSUMER_LATENCY_USEC_KHR:
+            streamObject->setConsumerLatency(value);
+            break;
+        case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+            streamObject->setConsumerAcquireTimeout(value);
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY QueryStreamKHR(EGLDisplay dpy,
+                                      EGLStreamKHR stream,
+                                      EGLenum attribute,
+                                      EGLint *value)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
+        "EGLint value = 0x%0.8p)",
+        dpy, stream, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    Stream *streamObject = static_cast<Stream *>(stream);
+
+    Error error = ValidateQueryStreamKHR(display, streamObject, attribute, value);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    switch (attribute)
+    {
+        case EGL_STREAM_STATE_KHR:
+            *value = streamObject->getState();
+            break;
+        case EGL_CONSUMER_LATENCY_USEC_KHR:
+            *value = streamObject->getConsumerLatency();
+            break;
+        case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+            *value = streamObject->getConsumerAcquireTimeout();
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY QueryStreamu64KHR(EGLDisplay dpy,
+                                         EGLStreamKHR stream,
+                                         EGLenum attribute,
+                                         EGLuint64KHR *value)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
+        "EGLuint64KHR value = 0x%0.8p)",
+        dpy, stream, attribute, value);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    Stream *streamObject = static_cast<Stream *>(stream);
+
+    Error error = ValidateQueryStreamu64KHR(display, streamObject, attribute, value);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    switch (attribute)
+    {
+        case EGL_PRODUCER_FRAME_KHR:
+            *value = streamObject->getProducerFrame();
+            break;
+        case EGL_CONSUMER_FRAME_KHR:
+            *value = streamObject->getConsumerFrame();
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    Stream *streamObject = static_cast<Stream *>(stream);
+    gl::Context *context = gl::GetValidGlobalContext();
+
+    Error error = ValidateStreamConsumerGLTextureExternalKHR(display, context, streamObject);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    error = streamObject->createConsumerGLTextureExternal(AttributeMap(), context);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    Stream *streamObject = static_cast<Stream *>(stream);
+    gl::Context *context = gl::GetValidGlobalContext();
+
+    Error error = ValidateStreamConsumerAcquireKHR(display, context, streamObject);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    error = streamObject->consumerAcquire();
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
+    Thread *thread = GetCurrentThread();
+
+    Display *display     = static_cast<Display *>(dpy);
+    Stream *streamObject = static_cast<Stream *>(stream);
+    gl::Context *context = gl::GetValidGlobalContext();
+
+    Error error = ValidateStreamConsumerReleaseKHR(display, context, streamObject);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    error = streamObject->consumerRelease();
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,
+                                                                EGLStreamKHR stream,
+                                                                const EGLAttrib *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLAttrib attrib_list = 0x%0.8p",
+        dpy, stream, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Display *display        = static_cast<Display *>(dpy);
+    Stream *streamObject    = static_cast<Stream *>(stream);
+    gl::Context *context    = gl::GetValidGlobalContext();
+    AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
+
+    Error error = ValidateStreamConsumerGLTextureExternalAttribsNV(display, context, streamObject,
+                                                                   attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    error = streamObject->createConsumerGLTextureExternal(attributes, context);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY CreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy,
+                                                               EGLStreamKHR stream,
+                                                               const EGLAttrib *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLAttrib attrib_list = 0x%0.8p",
+        dpy, stream, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Display *display        = static_cast<Display *>(dpy);
+    Stream *streamObject    = static_cast<Stream *>(stream);
+    AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
+
+    Error error =
+        ValidateCreateStreamProducerD3DTextureNV12ANGLE(display, streamObject, attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    error = streamObject->createProducerD3D11TextureNV12(attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamPostD3DTextureNV12ANGLE(EGLDisplay dpy,
+                                                     EGLStreamKHR stream,
+                                                     void *texture,
+                                                     const EGLAttrib *attrib_list)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, void* texture = 0x%0.8p, "
+        "EGLAttrib attrib_list = 0x%0.8p",
+        dpy, stream, texture, attrib_list);
+    Thread *thread = GetCurrentThread();
+
+    Display *display        = static_cast<Display *>(dpy);
+    Stream *streamObject    = static_cast<Stream *>(stream);
+    AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
+
+    Error error = ValidateStreamPostD3DTextureNV12ANGLE(display, streamObject, texture, attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    error = streamObject->postD3D11NV12Texture(texture, attributes);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY GetSyncValuesCHROMIUM(EGLDisplay dpy,
+                                             EGLSurface surface,
+                                             EGLuint64KHR *ust,
+                                             EGLuint64KHR *msc,
+                                             EGLuint64KHR *sbc)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLuint64KHR* ust = 0x%0.8p, "
+        "EGLuint64KHR* msc = 0x%0.8p, EGLuint64KHR* sbc = 0x%0.8p",
+        dpy, surface, ust, msc, sbc);
+    Thread *thread = GetCurrentThread();
+
+    Display *display    = static_cast<Display *>(dpy);
+    Surface *eglSurface = static_cast<Surface *>(surface);
+
+    Error error = ValidateGetSyncValuesCHROMIUM(display, eglSurface, ust, msc, sbc);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    error = eglSurface->getSyncValues(ust, msc, sbc);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    thread->setError(error);
+    return EGL_TRUE;
+}
+
+ANGLE_EXPORT EGLBoolean SwapBuffersWithDamageEXT(EGLDisplay dpy,
+                                                 EGLSurface surface,
+                                                 EGLint *rects,
+                                                 EGLint n_rects)
+{
+    EVENT(
+        "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint *rects = 0x%0.8p, EGLint "
+        "n_rects = %d)",
+        dpy, surface, rects, n_rects);
+    Thread *thread = GetCurrentThread();
+
+    Display *display    = static_cast<Display *>(dpy);
+    Surface *eglSurface = static_cast<Surface *>(surface);
+
+    Error error = ValidateSwapBuffersWithDamageEXT(display, eglSurface, rects, n_rects);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    error = eglSurface->swapWithDamage(rects, n_rects);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
+
+    return EGL_TRUE;
+}
+}
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_egl_ext.h b/src/third_party/angle/src/libGLESv2/entry_points_egl_ext.h
new file mode 100644
index 0000000..d05b12a
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_egl_ext.h
@@ -0,0 +1,98 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_egl_ext.h : Defines the EGL extension entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTSEGLEXT_H_
+#define LIBGLESV2_ENTRYPOINTSEGLEXT_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <export.h>
+
+namespace egl
+{
+
+// EGL_ANGLE_query_surface_pointer
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+
+// EGL_NV_post_sub_buffer
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+
+// EGL_EXT_platform_base
+ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list);
+
+// EGL_EXT_device_query
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+ANGLE_EXPORT const char * EGLAPIENTRY QueryDeviceStringEXT(EGLDeviceEXT device, EGLint name);
+
+// EGL_KHR_image_base/EGL_KHR_image
+ANGLE_EXPORT EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy,
+                                                    EGLContext ctx,
+                                                    EGLenum target,
+                                                    EGLClientBuffer buffer,
+                                                    const EGLint *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image);
+
+// EGL_EXT_device_creation
+ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
+                                                        void *native_device,
+                                                        const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device);
+
+// EGL_KHR_stream
+ANGLE_EXPORT EGLStreamKHR EGLAPIENTRY CreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamAttribKHR(EGLDisplay dpy,
+                                                    EGLStreamKHR stream,
+                                                    EGLenum attribute,
+                                                    EGLint value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryStreamKHR(EGLDisplay dpy,
+                                                   EGLStreamKHR stream,
+                                                   EGLenum attribute,
+                                                   EGLint *value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryStreamu64KHR(EGLDisplay dpy,
+                                                      EGLStreamKHR stream,
+                                                      EGLenum attribute,
+                                                      EGLuint64KHR *value);
+
+// EGL_KHR_stream_consumer_gltexture
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
+                                                                       EGLStreamKHR stream);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY
+StreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,
+                                         EGLStreamKHR stream,
+                                         const EGLAttrib *attrib_list);
+
+// EGL_ANGLE_stream_producer_d3d_texture_nv12
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY
+CreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy,
+                                        EGLStreamKHR stream,
+                                        const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamPostD3DTextureNV12ANGLE(EGLDisplay dpy,
+                                                                  EGLStreamKHR stream,
+                                                                  void *texture,
+                                                                  const EGLAttrib *attrib_list);
+
+// EGL_CHROMIUM_get_sync_values
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetSyncValuesCHROMIUM(EGLDisplay dpy,
+                                                          EGLSurface surface,
+                                                          EGLuint64KHR *ust,
+                                                          EGLuint64KHR *msc,
+                                                          EGLuint64KHR *sbc);
+
+// EGL_EXT_swap_buffers_with_damage
+ANGLE_EXPORT EGLBoolean SwapBuffersWithDamageEXT(EGLDisplay dpy,
+                                                 EGLSurface surface,
+                                                 EGLint *rects,
+                                                 EGLint n_rects);
+
+}  // namespace egl
+
+#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_autogen.cpp b/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_autogen.cpp
new file mode 100644
index 0000000..b3339ac
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_autogen.cpp
@@ -0,0 +1,2607 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 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.
+//
+// entry_points_gles_2_0_autogen.cpp:
+//   Defines the GLES 2.0 entry points.
+
+#include "libGLESv2/entry_points_gles_2_0_autogen.h"
+
+#include "common/debug.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/validationES2.h"
+#include "libGLESv2/global_state.h"
+
+namespace gl
+{
+void GL_APIENTRY ActiveTexture(GLenum texture)
+{
+    EVENT("(GLenum texture = 0x%X)", texture);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ActiveTexture>(texture);
+
+        if (context->skipValidation() || ValidateActiveTexture(context, texture))
+        {
+            context->activeTexture(texture);
+        }
+    }
+}
+
+void GL_APIENTRY AttachShader(GLuint program, GLuint shader)
+{
+    EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::AttachShader>(program, shader);
+
+        if (context->skipValidation() || ValidateAttachShader(context, program, shader))
+        {
+            context->attachShader(program, shader);
+        }
+    }
+}
+
+void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar *name)
+{
+    EVENT("(GLuint program = %d, GLuint index = %d, const GLchar *name = 0x%0.8p)", program, index,
+          name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BindAttribLocation>(program, index, name);
+
+        if (context->skipValidation() || ValidateBindAttribLocation(context, program, index, name))
+        {
+            context->bindAttribLocation(program, index, name);
+        }
+    }
+}
+
+void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
+{
+    EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BindBuffer>(target, buffer);
+
+        if (context->skipValidation() || ValidateBindBuffer(context, target, buffer))
+        {
+            context->bindBuffer(target, buffer);
+        }
+    }
+}
+
+void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
+{
+    EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BindFramebuffer>(target, framebuffer);
+
+        if (context->skipValidation() || ValidateBindFramebuffer(context, target, framebuffer))
+        {
+            context->bindFramebuffer(target, framebuffer);
+        }
+    }
+}
+
+void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+    EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BindRenderbuffer>(target, renderbuffer);
+
+        if (context->skipValidation() || ValidateBindRenderbuffer(context, target, renderbuffer))
+        {
+            context->bindRenderbuffer(target, renderbuffer);
+        }
+    }
+}
+
+void GL_APIENTRY BindTexture(GLenum target, GLuint texture)
+{
+    EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BindTexture>(target, texture);
+
+        if (context->skipValidation() || ValidateBindTexture(context, target, texture))
+        {
+            context->bindTexture(target, texture);
+        }
+    }
+}
+
+void GL_APIENTRY BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+    EVENT("(GLfloat red = %f, GLfloat green = %f, GLfloat blue = %f, GLfloat alpha = %f)", red,
+          green, blue, alpha);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BlendColor>(red, green, blue, alpha);
+
+        if (context->skipValidation() || ValidateBlendColor(context, red, green, blue, alpha))
+        {
+            context->blendColor(red, green, blue, alpha);
+        }
+    }
+}
+
+void GL_APIENTRY BlendEquation(GLenum mode)
+{
+    EVENT("(GLenum mode = 0x%X)", mode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BlendEquation>(mode);
+
+        if (context->skipValidation() || ValidateBlendEquation(context, mode))
+        {
+            context->blendEquation(mode);
+        }
+    }
+}
+
+void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+    EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BlendEquationSeparate>(modeRGB, modeAlpha);
+
+        if (context->skipValidation() || ValidateBlendEquationSeparate(context, modeRGB, modeAlpha))
+        {
+            context->blendEquationSeparate(modeRGB, modeAlpha);
+        }
+    }
+}
+
+void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor)
+{
+    EVENT("(GLenum sfactor = 0x%X, GLenum dfactor = 0x%X)", sfactor, dfactor);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BlendFunc>(sfactor, dfactor);
+
+        if (context->skipValidation() || ValidateBlendFunc(context, sfactor, dfactor))
+        {
+            context->blendFunc(sfactor, dfactor);
+        }
+    }
+}
+
+void GL_APIENTRY BlendFuncSeparate(GLenum sfactorRGB,
+                                   GLenum dfactorRGB,
+                                   GLenum sfactorAlpha,
+                                   GLenum dfactorAlpha)
+{
+    EVENT(
+        "(GLenum sfactorRGB = 0x%X, GLenum dfactorRGB = 0x%X, GLenum sfactorAlpha = 0x%X, GLenum "
+        "dfactorAlpha = 0x%X)",
+        sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BlendFuncSeparate>(sfactorRGB, dfactorRGB, sfactorAlpha,
+                                                             dfactorAlpha);
+
+        if (context->skipValidation() ||
+            ValidateBlendFuncSeparate(context, sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha))
+        {
+            context->blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+        }
+    }
+}
+
+void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLsizeiptr size = %d, const void *data = 0x%0.8p, GLenum usage = "
+        "0x%X)",
+        target, size, data, usage);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BufferData>(target, size, data, usage);
+
+        if (context->skipValidation() || ValidateBufferData(context, target, size, data, usage))
+        {
+            context->bufferData(target, size, data, usage);
+        }
+    }
+}
+
+void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const void *data = "
+        "0x%0.8p)",
+        target, offset, size, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BufferSubData>(target, offset, size, data);
+
+        if (context->skipValidation() || ValidateBufferSubData(context, target, offset, size, data))
+        {
+            context->bufferSubData(target, offset, size, data);
+        }
+    }
+}
+
+GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target)
+{
+    EVENT("(GLenum target = 0x%X)", target);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CheckFramebufferStatus>(target);
+
+        if (context->skipValidation() || ValidateCheckFramebufferStatus(context, target))
+        {
+            return context->checkFramebufferStatus(target);
+        }
+    }
+
+    return 0;
+}
+
+void GL_APIENTRY Clear(GLbitfield mask)
+{
+    EVENT("(GLbitfield mask = 0x%X)", mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Clear>(mask);
+
+        if (context->skipValidation() || ValidateClear(context, mask))
+        {
+            context->clear(mask);
+        }
+    }
+}
+
+void GL_APIENTRY ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+    EVENT("(GLfloat red = %f, GLfloat green = %f, GLfloat blue = %f, GLfloat alpha = %f)", red,
+          green, blue, alpha);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ClearColor>(red, green, blue, alpha);
+
+        if (context->skipValidation() || ValidateClearColor(context, red, green, blue, alpha))
+        {
+            context->clearColor(red, green, blue, alpha);
+        }
+    }
+}
+
+void GL_APIENTRY ClearDepthf(GLfloat d)
+{
+    EVENT("(GLfloat d = %f)", d);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ClearDepthf>(d);
+
+        if (context->skipValidation() || ValidateClearDepthf(context, d))
+        {
+            context->clearDepthf(d);
+        }
+    }
+}
+
+void GL_APIENTRY ClearStencil(GLint s)
+{
+    EVENT("(GLint s = %d)", s);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ClearStencil>(s);
+
+        if (context->skipValidation() || ValidateClearStencil(context, s))
+        {
+            context->clearStencil(s);
+        }
+    }
+}
+
+void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+    EVENT("(GLboolean red = %u, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)",
+          red, green, blue, alpha);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ColorMask>(red, green, blue, alpha);
+
+        if (context->skipValidation() || ValidateColorMask(context, red, green, blue, alpha))
+        {
+            context->colorMask(red, green, blue, alpha);
+        }
+    }
+}
+
+void GL_APIENTRY CompileShader(GLuint shader)
+{
+    EVENT("(GLuint shader = %d)", shader);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CompileShader>(shader);
+
+        if (context->skipValidation() || ValidateCompileShader(context, shader))
+        {
+            context->compileShader(shader);
+        }
+    }
+}
+
+void GL_APIENTRY CompressedTexImage2D(GLenum target,
+                                      GLint level,
+                                      GLenum internalformat,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLint border,
+                                      GLsizei imageSize,
+                                      const void *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+        "%d, GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const void *data = "
+        "0x%0.8p)",
+        target, level, internalformat, width, height, border, imageSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CompressedTexImage2D>(
+            target, level, internalformat, width, height, border, imageSize, data);
+
+        if (context->skipValidation() ||
+            ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
+                                         border, imageSize, data))
+        {
+            context->compressedTexImage2D(target, level, internalformat, width, height, border,
+                                          imageSize, data);
+        }
+    }
+}
+
+void GL_APIENTRY CompressedTexSubImage2D(GLenum target,
+                                         GLint level,
+                                         GLint xoffset,
+                                         GLint yoffset,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLenum format,
+                                         GLsizei imageSize,
+                                         const void *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLsizei "
+        "width = %d, GLsizei height = %d, GLenum format = 0x%X, GLsizei imageSize = %d, const void "
+        "*data = 0x%0.8p)",
+        target, level, xoffset, yoffset, width, height, format, imageSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CompressedTexSubImage2D>(
+            target, level, xoffset, yoffset, width, height, format, imageSize, data);
+
+        if (context->skipValidation() ||
+            ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
+                                            format, imageSize, data))
+        {
+            context->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+                                             imageSize, data);
+        }
+    }
+}
+
+void GL_APIENTRY CopyTexImage2D(GLenum target,
+                                GLint level,
+                                GLenum internalformat,
+                                GLint x,
+                                GLint y,
+                                GLsizei width,
+                                GLsizei height,
+                                GLint border)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLint x = %d, "
+        "GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
+        target, level, internalformat, x, y, width, height, border);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CopyTexImage2D>(target, level, internalformat, x, y,
+                                                          width, height, border);
+
+        if (context->skipValidation() ||
+            ValidateCopyTexImage2D(context, target, level, internalformat, x, y, width, height,
+                                   border))
+        {
+            context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+        }
+    }
+}
+
+void GL_APIENTRY CopyTexSubImage2D(GLenum target,
+                                   GLint level,
+                                   GLint xoffset,
+                                   GLint yoffset,
+                                   GLint x,
+                                   GLint y,
+                                   GLsizei width,
+                                   GLsizei height)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLint x "
+        "= %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+        target, level, xoffset, yoffset, x, y, width, height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CopyTexSubImage2D>(target, level, xoffset, yoffset, x, y,
+                                                             width, height);
+
+        if (context->skipValidation() || ValidateCopyTexSubImage2D(context, target, level, xoffset,
+                                                                   yoffset, x, y, width, height))
+        {
+            context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+        }
+    }
+}
+
+GLuint GL_APIENTRY CreateProgram()
+{
+    EVENT("()");
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CreateProgram>();
+
+        if (context->skipValidation() || ValidateCreateProgram(context))
+        {
+            return context->createProgram();
+        }
+    }
+
+    return 0;
+}
+
+GLuint GL_APIENTRY CreateShader(GLenum type)
+{
+    EVENT("(GLenum type = 0x%X)", type);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CreateShader>(type);
+
+        if (context->skipValidation() || ValidateCreateShader(context, type))
+        {
+            return context->createShader(type);
+        }
+    }
+
+    return 0;
+}
+
+void GL_APIENTRY CullFace(GLenum mode)
+{
+    EVENT("(GLenum mode = 0x%X)", mode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CullFace>(mode);
+
+        if (context->skipValidation() || ValidateCullFace(context, mode))
+        {
+            context->cullFace(mode);
+        }
+    }
+}
+
+void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint *buffers)
+{
+    EVENT("(GLsizei n = %d, const GLuint *buffers = 0x%0.8p)", n, buffers);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DeleteBuffers>(n, buffers);
+
+        if (context->skipValidation() || ValidateDeleteBuffers(context, n, buffers))
+        {
+            context->deleteBuffers(n, buffers);
+        }
+    }
+}
+
+void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
+{
+    EVENT("(GLsizei n = %d, const GLuint *framebuffers = 0x%0.8p)", n, framebuffers);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DeleteFramebuffers>(n, framebuffers);
+
+        if (context->skipValidation() || ValidateDeleteFramebuffers(context, n, framebuffers))
+        {
+            context->deleteFramebuffers(n, framebuffers);
+        }
+    }
+}
+
+void GL_APIENTRY DeleteProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DeleteProgram>(program);
+
+        if (context->skipValidation() || ValidateDeleteProgram(context, program))
+        {
+            context->deleteProgram(program);
+        }
+    }
+}
+
+void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
+{
+    EVENT("(GLsizei n = %d, const GLuint *renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DeleteRenderbuffers>(n, renderbuffers);
+
+        if (context->skipValidation() || ValidateDeleteRenderbuffers(context, n, renderbuffers))
+        {
+            context->deleteRenderbuffers(n, renderbuffers);
+        }
+    }
+}
+
+void GL_APIENTRY DeleteShader(GLuint shader)
+{
+    EVENT("(GLuint shader = %d)", shader);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DeleteShader>(shader);
+
+        if (context->skipValidation() || ValidateDeleteShader(context, shader))
+        {
+            context->deleteShader(shader);
+        }
+    }
+}
+
+void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint *textures)
+{
+    EVENT("(GLsizei n = %d, const GLuint *textures = 0x%0.8p)", n, textures);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DeleteTextures>(n, textures);
+
+        if (context->skipValidation() || ValidateDeleteTextures(context, n, textures))
+        {
+            context->deleteTextures(n, textures);
+        }
+    }
+}
+
+void GL_APIENTRY DepthFunc(GLenum func)
+{
+    EVENT("(GLenum func = 0x%X)", func);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DepthFunc>(func);
+
+        if (context->skipValidation() || ValidateDepthFunc(context, func))
+        {
+            context->depthFunc(func);
+        }
+    }
+}
+
+void GL_APIENTRY DepthMask(GLboolean flag)
+{
+    EVENT("(GLboolean flag = %u)", flag);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DepthMask>(flag);
+
+        if (context->skipValidation() || ValidateDepthMask(context, flag))
+        {
+            context->depthMask(flag);
+        }
+    }
+}
+
+void GL_APIENTRY DepthRangef(GLfloat n, GLfloat f)
+{
+    EVENT("(GLfloat n = %f, GLfloat f = %f)", n, f);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DepthRangef>(n, f);
+
+        if (context->skipValidation() || ValidateDepthRangef(context, n, f))
+        {
+            context->depthRangef(n, f);
+        }
+    }
+}
+
+void GL_APIENTRY DetachShader(GLuint program, GLuint shader)
+{
+    EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DetachShader>(program, shader);
+
+        if (context->skipValidation() || ValidateDetachShader(context, program, shader))
+        {
+            context->detachShader(program, shader);
+        }
+    }
+}
+
+void GL_APIENTRY Disable(GLenum cap)
+{
+    EVENT("(GLenum cap = 0x%X)", cap);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Disable>(cap);
+
+        if (context->skipValidation() || ValidateDisable(context, cap))
+        {
+            context->disable(cap);
+        }
+    }
+}
+
+void GL_APIENTRY DisableVertexAttribArray(GLuint index)
+{
+    EVENT("(GLuint index = %d)", index);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DisableVertexAttribArray>(index);
+
+        if (context->skipValidation() || ValidateDisableVertexAttribArray(context, index))
+        {
+            context->disableVertexAttribArray(index);
+        }
+    }
+}
+
+void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DrawArrays>(mode, first, count);
+
+        if (context->skipValidation() || ValidateDrawArrays(context, mode, first, count))
+        {
+            context->drawArrays(mode, first, count);
+        }
+    }
+}
+
+void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
+{
+    EVENT(
+        "(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = "
+        "0x%0.8p)",
+        mode, count, type, indices);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DrawElements>(mode, count, type, indices);
+
+        if (context->skipValidation() || ValidateDrawElements(context, mode, count, type, indices))
+        {
+            context->drawElements(mode, count, type, indices);
+        }
+    }
+}
+
+void GL_APIENTRY Enable(GLenum cap)
+{
+    EVENT("(GLenum cap = 0x%X)", cap);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Enable>(cap);
+
+        if (context->skipValidation() || ValidateEnable(context, cap))
+        {
+            context->enable(cap);
+        }
+    }
+}
+
+void GL_APIENTRY EnableVertexAttribArray(GLuint index)
+{
+    EVENT("(GLuint index = %d)", index);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::EnableVertexAttribArray>(index);
+
+        if (context->skipValidation() || ValidateEnableVertexAttribArray(context, index))
+        {
+            context->enableVertexAttribArray(index);
+        }
+    }
+}
+
+void GL_APIENTRY Finish()
+{
+    EVENT("()");
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Finish>();
+
+        if (context->skipValidation() || ValidateFinish(context))
+        {
+            context->finish();
+        }
+    }
+}
+
+void GL_APIENTRY Flush()
+{
+    EVENT("()");
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Flush>();
+
+        if (context->skipValidation() || ValidateFlush(context))
+        {
+            context->flush();
+        }
+    }
+}
+
+void GL_APIENTRY FramebufferRenderbuffer(GLenum target,
+                                         GLenum attachment,
+                                         GLenum renderbuffertarget,
+                                         GLuint renderbuffer)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, GLuint "
+        "renderbuffer = %d)",
+        target, attachment, renderbuffertarget, renderbuffer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::FramebufferRenderbuffer>(
+            target, attachment, renderbuffertarget, renderbuffer);
+
+        if (context->skipValidation() ||
+            ValidateFramebufferRenderbuffer(context, target, attachment, renderbuffertarget,
+                                            renderbuffer))
+        {
+            context->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+        }
+    }
+}
+
+void GL_APIENTRY FramebufferTexture2D(GLenum target,
+                                      GLenum attachment,
+                                      GLenum textarget,
+                                      GLuint texture,
+                                      GLint level)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, GLuint texture "
+        "= %d, GLint level = %d)",
+        target, attachment, textarget, texture, level);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::FramebufferTexture2D>(target, attachment, textarget,
+                                                                texture, level);
+
+        if (context->skipValidation() ||
+            ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level))
+        {
+            context->framebufferTexture2D(target, attachment, textarget, texture, level);
+        }
+    }
+}
+
+void GL_APIENTRY FrontFace(GLenum mode)
+{
+    EVENT("(GLenum mode = 0x%X)", mode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::FrontFace>(mode);
+
+        if (context->skipValidation() || ValidateFrontFace(context, mode))
+        {
+            context->frontFace(mode);
+        }
+    }
+}
+
+void GL_APIENTRY GenBuffers(GLsizei n, GLuint *buffers)
+{
+    EVENT("(GLsizei n = %d, GLuint *buffers = 0x%0.8p)", n, buffers);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GenBuffers>(n, buffers);
+
+        if (context->skipValidation() || ValidateGenBuffers(context, n, buffers))
+        {
+            context->genBuffers(n, buffers);
+        }
+    }
+}
+
+void GL_APIENTRY GenerateMipmap(GLenum target)
+{
+    EVENT("(GLenum target = 0x%X)", target);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GenerateMipmap>(target);
+
+        if (context->skipValidation() || ValidateGenerateMipmap(context, target))
+        {
+            context->generateMipmap(target);
+        }
+    }
+}
+
+void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint *framebuffers)
+{
+    EVENT("(GLsizei n = %d, GLuint *framebuffers = 0x%0.8p)", n, framebuffers);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GenFramebuffers>(n, framebuffers);
+
+        if (context->skipValidation() || ValidateGenFramebuffers(context, n, framebuffers))
+        {
+            context->genFramebuffers(n, framebuffers);
+        }
+    }
+}
+
+void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+    EVENT("(GLsizei n = %d, GLuint *renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GenRenderbuffers>(n, renderbuffers);
+
+        if (context->skipValidation() || ValidateGenRenderbuffers(context, n, renderbuffers))
+        {
+            context->genRenderbuffers(n, renderbuffers);
+        }
+    }
+}
+
+void GL_APIENTRY GenTextures(GLsizei n, GLuint *textures)
+{
+    EVENT("(GLsizei n = %d, GLuint *textures = 0x%0.8p)", n, textures);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GenTextures>(n, textures);
+
+        if (context->skipValidation() || ValidateGenTextures(context, n, textures))
+        {
+            context->genTextures(n, textures);
+        }
+    }
+}
+
+void GL_APIENTRY GetActiveAttrib(GLuint program,
+                                 GLuint index,
+                                 GLsizei bufSize,
+                                 GLsizei *length,
+                                 GLint *size,
+                                 GLenum *type,
+                                 GLchar *name)
+{
+    EVENT(
+        "(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, "
+        "GLint *size = 0x%0.8p, GLenum *type = 0x%0.8p, GLchar *name = 0x%0.8p)",
+        program, index, bufSize, length, size, type, name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetActiveAttrib>(program, index, bufSize, length, size,
+                                                           type, name);
+
+        if (context->skipValidation() ||
+            ValidateGetActiveAttrib(context, program, index, bufSize, length, size, type, name))
+        {
+            context->getActiveAttrib(program, index, bufSize, length, size, type, name);
+        }
+    }
+}
+
+void GL_APIENTRY GetActiveUniform(GLuint program,
+                                  GLuint index,
+                                  GLsizei bufSize,
+                                  GLsizei *length,
+                                  GLint *size,
+                                  GLenum *type,
+                                  GLchar *name)
+{
+    EVENT(
+        "(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, "
+        "GLint *size = 0x%0.8p, GLenum *type = 0x%0.8p, GLchar *name = 0x%0.8p)",
+        program, index, bufSize, length, size, type, name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetActiveUniform>(program, index, bufSize, length, size,
+                                                            type, name);
+
+        if (context->skipValidation() ||
+            ValidateGetActiveUniform(context, program, index, bufSize, length, size, type, name))
+        {
+            context->getActiveUniform(program, index, bufSize, length, size, type, name);
+        }
+    }
+}
+
+void GL_APIENTRY GetAttachedShaders(GLuint program,
+                                    GLsizei maxCount,
+                                    GLsizei *count,
+                                    GLuint *shaders)
+{
+    EVENT(
+        "(GLuint program = %d, GLsizei maxCount = %d, GLsizei *count = 0x%0.8p, GLuint *shaders = "
+        "0x%0.8p)",
+        program, maxCount, count, shaders);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetAttachedShaders>(program, maxCount, count, shaders);
+
+        if (context->skipValidation() ||
+            ValidateGetAttachedShaders(context, program, maxCount, count, shaders))
+        {
+            context->getAttachedShaders(program, maxCount, count, shaders);
+        }
+    }
+}
+
+GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar *name)
+{
+    EVENT("(GLuint program = %d, const GLchar *name = 0x%0.8p)", program, name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetAttribLocation>(program, name);
+
+        if (context->skipValidation() || ValidateGetAttribLocation(context, program, name))
+        {
+            return context->getAttribLocation(program, name);
+        }
+    }
+
+    return 0;
+}
+
+void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean *data)
+{
+    EVENT("(GLenum pname = 0x%X, GLboolean *data = 0x%0.8p)", pname, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetBooleanv>(pname, data);
+
+        if (context->skipValidation() || ValidateGetBooleanv(context, pname, data))
+        {
+            context->getBooleanv(pname, data);
+        }
+    }
+}
+
+void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetBufferParameteriv>(target, pname, params);
+
+        if (context->skipValidation() ||
+            ValidateGetBufferParameteriv(context, target, pname, params))
+        {
+            context->getBufferParameteriv(target, pname, params);
+        }
+    }
+}
+
+GLenum GL_APIENTRY GetError()
+{
+    EVENT("()");
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetError>();
+
+        if (context->skipValidation() || ValidateGetError(context))
+        {
+            return context->getError();
+        }
+    }
+
+    return 0;
+}
+
+void GL_APIENTRY GetFloatv(GLenum pname, GLfloat *data)
+{
+    EVENT("(GLenum pname = 0x%X, GLfloat *data = 0x%0.8p)", pname, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetFloatv>(pname, data);
+
+        if (context->skipValidation() || ValidateGetFloatv(context, pname, data))
+        {
+            context->getFloatv(pname, data);
+        }
+    }
+}
+
+void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target,
+                                                     GLenum attachment,
+                                                     GLenum pname,
+                                                     GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint *params = "
+        "0x%0.8p)",
+        target, attachment, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetFramebufferAttachmentParameteriv>(target, attachment,
+                                                                               pname, params);
+
+        if (context->skipValidation() ||
+            ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, params))
+        {
+            context->getFramebufferAttachmentParameteriv(target, attachment, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetIntegerv(GLenum pname, GLint *data)
+{
+    EVENT("(GLenum pname = 0x%X, GLint *data = 0x%0.8p)", pname, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetIntegerv>(pname, data);
+
+        if (context->skipValidation() || ValidateGetIntegerv(context, pname, data))
+        {
+            context->getIntegerv(pname, data);
+        }
+    }
+}
+
+void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint *params)
+{
+    EVENT("(GLuint program = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", program, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetProgramiv>(program, pname, params);
+
+        if (context->skipValidation() || ValidateGetProgramiv(context, program, pname, params))
+        {
+            context->getProgramiv(program, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetProgramInfoLog(GLuint program,
+                                   GLsizei bufSize,
+                                   GLsizei *length,
+                                   GLchar *infoLog)
+{
+    EVENT(
+        "(GLuint program = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLchar *infoLog = "
+        "0x%0.8p)",
+        program, bufSize, length, infoLog);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetProgramInfoLog>(program, bufSize, length, infoLog);
+
+        if (context->skipValidation() ||
+            ValidateGetProgramInfoLog(context, program, bufSize, length, infoLog))
+        {
+            context->getProgramInfoLog(program, bufSize, length, infoLog);
+        }
+    }
+}
+
+void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetRenderbufferParameteriv>(target, pname, params);
+
+        if (context->skipValidation() ||
+            ValidateGetRenderbufferParameteriv(context, target, pname, params))
+        {
+            context->getRenderbufferParameteriv(target, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint *params)
+{
+    EVENT("(GLuint shader = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", shader, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetShaderiv>(shader, pname, params);
+
+        if (context->skipValidation() || ValidateGetShaderiv(context, shader, pname, params))
+        {
+            context->getShaderiv(shader, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+{
+    EVENT(
+        "(GLuint shader = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLchar *infoLog = "
+        "0x%0.8p)",
+        shader, bufSize, length, infoLog);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetShaderInfoLog>(shader, bufSize, length, infoLog);
+
+        if (context->skipValidation() ||
+            ValidateGetShaderInfoLog(context, shader, bufSize, length, infoLog))
+        {
+            context->getShaderInfoLog(shader, bufSize, length, infoLog);
+        }
+    }
+}
+
+void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype,
+                                          GLenum precisiontype,
+                                          GLint *range,
+                                          GLint *precision)
+{
+    EVENT(
+        "(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint *range = 0x%0.8p, GLint "
+        "*precision = 0x%0.8p)",
+        shadertype, precisiontype, range, precision);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetShaderPrecisionFormat>(shadertype, precisiontype,
+                                                                    range, precision);
+
+        if (context->skipValidation() ||
+            ValidateGetShaderPrecisionFormat(context, shadertype, precisiontype, range, precision))
+        {
+            context->getShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+        }
+    }
+}
+
+void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source)
+{
+    EVENT(
+        "(GLuint shader = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLchar *source = "
+        "0x%0.8p)",
+        shader, bufSize, length, source);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetShaderSource>(shader, bufSize, length, source);
+
+        if (context->skipValidation() ||
+            ValidateGetShaderSource(context, shader, bufSize, length, source))
+        {
+            context->getShaderSource(shader, bufSize, length, source);
+        }
+    }
+}
+
+const GLubyte *GL_APIENTRY GetString(GLenum name)
+{
+    EVENT("(GLenum name = 0x%X)", name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetString>(name);
+
+        if (context->skipValidation() || ValidateGetString(context, name))
+        {
+            return context->getString(name);
+        }
+    }
+
+    return nullptr;
+}
+
+void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat *params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetTexParameterfv>(target, pname, params);
+
+        if (context->skipValidation() || ValidateGetTexParameterfv(context, target, pname, params))
+        {
+            context->getTexParameterfv(target, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetTexParameteriv>(target, pname, params);
+
+        if (context->skipValidation() || ValidateGetTexParameteriv(context, target, pname, params))
+        {
+            context->getTexParameteriv(target, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat *params)
+{
+    EVENT("(GLuint program = %d, GLint location = %d, GLfloat *params = 0x%0.8p)", program,
+          location, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetUniformfv>(program, location, params);
+
+        if (context->skipValidation() || ValidateGetUniformfv(context, program, location, params))
+        {
+            context->getUniformfv(program, location, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint *params)
+{
+    EVENT("(GLuint program = %d, GLint location = %d, GLint *params = 0x%0.8p)", program, location,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetUniformiv>(program, location, params);
+
+        if (context->skipValidation() || ValidateGetUniformiv(context, program, location, params))
+        {
+            context->getUniformiv(program, location, params);
+        }
+    }
+}
+
+GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar *name)
+{
+    EVENT("(GLuint program = %d, const GLchar *name = 0x%0.8p)", program, name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetUniformLocation>(program, name);
+
+        if (context->skipValidation() || ValidateGetUniformLocation(context, program, name))
+        {
+            return context->getUniformLocation(program, name);
+        }
+    }
+
+    return 0;
+}
+
+void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
+{
+    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat *params = 0x%0.8p)", index, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetVertexAttribfv>(index, pname, params);
+
+        if (context->skipValidation() || ValidateGetVertexAttribfv(context, index, pname, params))
+        {
+            context->getVertexAttribfv(index, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
+{
+    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", index, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetVertexAttribiv>(index, pname, params);
+
+        if (context->skipValidation() || ValidateGetVertexAttribiv(context, index, pname, params))
+        {
+            context->getVertexAttribiv(index, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer)
+{
+    EVENT("(GLuint index = %d, GLenum pname = 0x%X, void **pointer = 0x%0.8p)", index, pname,
+          pointer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetVertexAttribPointerv>(index, pname, pointer);
+
+        if (context->skipValidation() ||
+            ValidateGetVertexAttribPointerv(context, index, pname, pointer))
+        {
+            context->getVertexAttribPointerv(index, pname, pointer);
+        }
+    }
+}
+
+void GL_APIENTRY Hint(GLenum target, GLenum mode)
+{
+    EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Hint>(target, mode);
+
+        if (context->skipValidation() || ValidateHint(context, target, mode))
+        {
+            context->hint(target, mode);
+        }
+    }
+}
+
+GLboolean GL_APIENTRY IsBuffer(GLuint buffer)
+{
+    EVENT("(GLuint buffer = %d)", buffer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::IsBuffer>(buffer);
+
+        if (context->skipValidation() || ValidateIsBuffer(context, buffer))
+        {
+            return context->isBuffer(buffer);
+        }
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsEnabled(GLenum cap)
+{
+    EVENT("(GLenum cap = 0x%X)", cap);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::IsEnabled>(cap);
+
+        if (context->skipValidation() || ValidateIsEnabled(context, cap))
+        {
+            return context->isEnabled(cap);
+        }
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer)
+{
+    EVENT("(GLuint framebuffer = %d)", framebuffer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::IsFramebuffer>(framebuffer);
+
+        if (context->skipValidation() || ValidateIsFramebuffer(context, framebuffer))
+        {
+            return context->isFramebuffer(framebuffer);
+        }
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::IsProgram>(program);
+
+        if (context->skipValidation() || ValidateIsProgram(context, program))
+        {
+            return context->isProgram(program);
+        }
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer)
+{
+    EVENT("(GLuint renderbuffer = %d)", renderbuffer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::IsRenderbuffer>(renderbuffer);
+
+        if (context->skipValidation() || ValidateIsRenderbuffer(context, renderbuffer))
+        {
+            return context->isRenderbuffer(renderbuffer);
+        }
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsShader(GLuint shader)
+{
+    EVENT("(GLuint shader = %d)", shader);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::IsShader>(shader);
+
+        if (context->skipValidation() || ValidateIsShader(context, shader))
+        {
+            return context->isShader(shader);
+        }
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsTexture(GLuint texture)
+{
+    EVENT("(GLuint texture = %d)", texture);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::IsTexture>(texture);
+
+        if (context->skipValidation() || ValidateIsTexture(context, texture))
+        {
+            return context->isTexture(texture);
+        }
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY LineWidth(GLfloat width)
+{
+    EVENT("(GLfloat width = %f)", width);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::LineWidth>(width);
+
+        if (context->skipValidation() || ValidateLineWidth(context, width))
+        {
+            context->lineWidth(width);
+        }
+    }
+}
+
+void GL_APIENTRY LinkProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::LinkProgram>(program);
+
+        if (context->skipValidation() || ValidateLinkProgram(context, program))
+        {
+            context->linkProgram(program);
+        }
+    }
+}
+
+void GL_APIENTRY PixelStorei(GLenum pname, GLint param)
+{
+    EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::PixelStorei>(pname, param);
+
+        if (context->skipValidation() || ValidatePixelStorei(context, pname, param))
+        {
+            context->pixelStorei(pname, param);
+        }
+    }
+}
+
+void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units)
+{
+    EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::PolygonOffset>(factor, units);
+
+        if (context->skipValidation() || ValidatePolygonOffset(context, factor, units))
+        {
+            context->polygonOffset(factor, units);
+        }
+    }
+}
+
+void GL_APIENTRY ReadPixels(GLint x,
+                            GLint y,
+                            GLsizei width,
+                            GLsizei height,
+                            GLenum format,
+                            GLenum type,
+                            void *pixels)
+{
+    EVENT(
+        "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLenum format = "
+        "0x%X, GLenum type = 0x%X, void *pixels = 0x%0.8p)",
+        x, y, width, height, format, type, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ReadPixels>(x, y, width, height, format, type, pixels);
+
+        if (context->skipValidation() ||
+            ValidateReadPixels(context, x, y, width, height, format, type, pixels))
+        {
+            context->readPixels(x, y, width, height, format, type, pixels);
+        }
+    }
+}
+
+void GL_APIENTRY ReleaseShaderCompiler()
+{
+    EVENT("()");
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ReleaseShaderCompiler>();
+
+        if (context->skipValidation() || ValidateReleaseShaderCompiler(context))
+        {
+            context->releaseShaderCompiler();
+        }
+    }
+}
+
+void GL_APIENTRY RenderbufferStorage(GLenum target,
+                                     GLenum internalformat,
+                                     GLsizei width,
+                                     GLsizei height)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = "
+        "%d)",
+        target, internalformat, width, height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::RenderbufferStorage>(target, internalformat, width,
+                                                               height);
+
+        if (context->skipValidation() ||
+            ValidateRenderbufferStorage(context, target, internalformat, width, height))
+        {
+            context->renderbufferStorage(target, internalformat, width, height);
+        }
+    }
+}
+
+void GL_APIENTRY SampleCoverage(GLfloat value, GLboolean invert)
+{
+    EVENT("(GLfloat value = %f, GLboolean invert = %u)", value, invert);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::SampleCoverage>(value, invert);
+
+        if (context->skipValidation() || ValidateSampleCoverage(context, value, invert))
+        {
+            context->sampleCoverage(value, invert);
+        }
+    }
+}
+
+void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width,
+          height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Scissor>(x, y, width, height);
+
+        if (context->skipValidation() || ValidateScissor(context, x, y, width, height))
+        {
+            context->scissor(x, y, width, height);
+        }
+    }
+}
+
+void GL_APIENTRY ShaderBinary(GLsizei count,
+                              const GLuint *shaders,
+                              GLenum binaryformat,
+                              const void *binary,
+                              GLsizei length)
+{
+    EVENT(
+        "(GLsizei count = %d, const GLuint *shaders = 0x%0.8p, GLenum binaryformat = 0x%X, const "
+        "void *binary = 0x%0.8p, GLsizei length = %d)",
+        count, shaders, binaryformat, binary, length);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ShaderBinary>(count, shaders, binaryformat, binary,
+                                                        length);
+
+        if (context->skipValidation() ||
+            ValidateShaderBinary(context, count, shaders, binaryformat, binary, length))
+        {
+            context->shaderBinary(count, shaders, binaryformat, binary, length);
+        }
+    }
+}
+
+void GL_APIENTRY ShaderSource(GLuint shader,
+                              GLsizei count,
+                              const GLchar *const *string,
+                              const GLint *length)
+{
+    EVENT(
+        "(GLuint shader = %d, GLsizei count = %d, const GLchar *const*string = 0x%0.8p, const "
+        "GLint *length = 0x%0.8p)",
+        shader, count, string, length);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ShaderSource>(shader, count, string, length);
+
+        if (context->skipValidation() ||
+            ValidateShaderSource(context, shader, count, string, length))
+        {
+            context->shaderSource(shader, count, string, length);
+        }
+    }
+}
+
+void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+    EVENT("(GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", func, ref, mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilFunc>(func, ref, mask);
+
+        if (context->skipValidation() || ValidateStencilFunc(context, func, ref, mask))
+        {
+            context->stencilFunc(func, ref, mask);
+        }
+    }
+}
+
+void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+    EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func,
+          ref, mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilFuncSeparate>(face, func, ref, mask);
+
+        if (context->skipValidation() ||
+            ValidateStencilFuncSeparate(context, face, func, ref, mask))
+        {
+            context->stencilFuncSeparate(face, func, ref, mask);
+        }
+    }
+}
+
+void GL_APIENTRY StencilMask(GLuint mask)
+{
+    EVENT("(GLuint mask = %d)", mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilMask>(mask);
+
+        if (context->skipValidation() || ValidateStencilMask(context, mask))
+        {
+            context->stencilMask(mask);
+        }
+    }
+}
+
+void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask)
+{
+    EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilMaskSeparate>(face, mask);
+
+        if (context->skipValidation() || ValidateStencilMaskSeparate(context, face, mask))
+        {
+            context->stencilMaskSeparate(face, mask);
+        }
+    }
+}
+
+void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+    EVENT("(GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpass = 0x%X)", fail, zfail, zpass);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilOp>(fail, zfail, zpass);
+
+        if (context->skipValidation() || ValidateStencilOp(context, fail, zfail, zpass))
+        {
+            context->stencilOp(fail, zfail, zpass);
+        }
+    }
+}
+
+void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
+{
+    EVENT("(GLenum face = 0x%X, GLenum sfail = 0x%X, GLenum dpfail = 0x%X, GLenum dppass = 0x%X)",
+          face, sfail, dpfail, dppass);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilOpSeparate>(face, sfail, dpfail, dppass);
+
+        if (context->skipValidation() ||
+            ValidateStencilOpSeparate(context, face, sfail, dpfail, dppass))
+        {
+            context->stencilOpSeparate(face, sfail, dpfail, dppass);
+        }
+    }
+}
+
+void GL_APIENTRY TexImage2D(GLenum target,
+                            GLint level,
+                            GLint internalformat,
+                            GLsizei width,
+                            GLsizei height,
+                            GLint border,
+                            GLenum format,
+                            GLenum type,
+                            const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+        "GLsizei height = %d, GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const "
+        "void *pixels = 0x%0.8p)",
+        target, level, internalformat, width, height, border, format, type, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::TexImage2D>(target, level, internalformat, width, height,
+                                                      border, format, type, pixels);
+
+        if (context->skipValidation() ||
+            ValidateTexImage2D(context, target, level, internalformat, width, height, border,
+                               format, type, pixels))
+        {
+            context->texImage2D(target, level, internalformat, width, height, border, format, type,
+                                pixels);
+        }
+    }
+}
+
+void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::TexParameterf>(target, pname, param);
+
+        if (context->skipValidation() || ValidateTexParameterf(context, target, pname, param))
+        {
+            context->texParameterf(target, pname, param);
+        }
+    }
+}
+
+void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLfloat *params = 0x%0.8p)", target,
+          pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::TexParameterfv>(target, pname, params);
+
+        if (context->skipValidation() || ValidateTexParameterfv(context, target, pname, params))
+        {
+            context->texParameterfv(target, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::TexParameteri>(target, pname, param);
+
+        if (context->skipValidation() || ValidateTexParameteri(context, target, pname, param))
+        {
+            context->texParameteri(target, pname, param);
+        }
+    }
+}
+
+void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLint *params = 0x%0.8p)", target,
+          pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::TexParameteriv>(target, pname, params);
+
+        if (context->skipValidation() || ValidateTexParameteriv(context, target, pname, params))
+        {
+            context->texParameteriv(target, pname, params);
+        }
+    }
+}
+
+void GL_APIENTRY TexSubImage2D(GLenum target,
+                               GLint level,
+                               GLint xoffset,
+                               GLint yoffset,
+                               GLsizei width,
+                               GLsizei height,
+                               GLenum format,
+                               GLenum type,
+                               const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLsizei "
+        "width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, const void "
+        "*pixels = 0x%0.8p)",
+        target, level, xoffset, yoffset, width, height, format, type, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::TexSubImage2D>(target, level, xoffset, yoffset, width,
+                                                         height, format, type, pixels);
+
+        if (context->skipValidation() ||
+            ValidateTexSubImage2D(context, target, level, xoffset, yoffset, width, height, format,
+                                  type, pixels))
+        {
+            context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
+                                   pixels);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform1f(GLint location, GLfloat v0)
+{
+    EVENT("(GLint location = %d, GLfloat v0 = %f)", location, v0);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform1f>(location, v0);
+
+        if (context->skipValidation() || ValidateUniform1f(context, location, v0))
+        {
+            context->uniform1f(location, v0);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat *value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform1fv>(location, count, value);
+
+        if (context->skipValidation() || ValidateUniform1fv(context, location, count, value))
+        {
+            context->uniform1fv(location, count, value);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform1i(GLint location, GLint v0)
+{
+    EVENT("(GLint location = %d, GLint v0 = %d)", location, v0);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform1i>(location, v0);
+
+        if (context->skipValidation() || ValidateUniform1i(context, location, v0))
+        {
+            context->uniform1i(location, v0);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLint *value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform1iv>(location, count, value);
+
+        if (context->skipValidation() || ValidateUniform1iv(context, location, count, value))
+        {
+            context->uniform1iv(location, count, value);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform2f(GLint location, GLfloat v0, GLfloat v1)
+{
+    EVENT("(GLint location = %d, GLfloat v0 = %f, GLfloat v1 = %f)", location, v0, v1);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform2f>(location, v0, v1);
+
+        if (context->skipValidation() || ValidateUniform2f(context, location, v0, v1))
+        {
+            context->uniform2f(location, v0, v1);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat *value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform2fv>(location, count, value);
+
+        if (context->skipValidation() || ValidateUniform2fv(context, location, count, value))
+        {
+            context->uniform2fv(location, count, value);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform2i(GLint location, GLint v0, GLint v1)
+{
+    EVENT("(GLint location = %d, GLint v0 = %d, GLint v1 = %d)", location, v0, v1);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform2i>(location, v0, v1);
+
+        if (context->skipValidation() || ValidateUniform2i(context, location, v0, v1))
+        {
+            context->uniform2i(location, v0, v1);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLint *value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform2iv>(location, count, value);
+
+        if (context->skipValidation() || ValidateUniform2iv(context, location, count, value))
+        {
+            context->uniform2iv(location, count, value);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+{
+    EVENT("(GLint location = %d, GLfloat v0 = %f, GLfloat v1 = %f, GLfloat v2 = %f)", location, v0,
+          v1, v2);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform3f>(location, v0, v1, v2);
+
+        if (context->skipValidation() || ValidateUniform3f(context, location, v0, v1, v2))
+        {
+            context->uniform3f(location, v0, v1, v2);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat *value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform3fv>(location, count, value);
+
+        if (context->skipValidation() || ValidateUniform3fv(context, location, count, value))
+        {
+            context->uniform3fv(location, count, value);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform3i(GLint location, GLint v0, GLint v1, GLint v2)
+{
+    EVENT("(GLint location = %d, GLint v0 = %d, GLint v1 = %d, GLint v2 = %d)", location, v0, v1,
+          v2);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform3i>(location, v0, v1, v2);
+
+        if (context->skipValidation() || ValidateUniform3i(context, location, v0, v1, v2))
+        {
+            context->uniform3i(location, v0, v1, v2);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLint *value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform3iv>(location, count, value);
+
+        if (context->skipValidation() || ValidateUniform3iv(context, location, count, value))
+        {
+            context->uniform3iv(location, count, value);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+{
+    EVENT(
+        "(GLint location = %d, GLfloat v0 = %f, GLfloat v1 = %f, GLfloat v2 = %f, GLfloat v3 = %f)",
+        location, v0, v1, v2, v3);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform4f>(location, v0, v1, v2, v3);
+
+        if (context->skipValidation() || ValidateUniform4f(context, location, v0, v1, v2, v3))
+        {
+            context->uniform4f(location, v0, v1, v2, v3);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat *value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform4fv>(location, count, value);
+
+        if (context->skipValidation() || ValidateUniform4fv(context, location, count, value))
+        {
+            context->uniform4fv(location, count, value);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+{
+    EVENT("(GLint location = %d, GLint v0 = %d, GLint v1 = %d, GLint v2 = %d, GLint v3 = %d)",
+          location, v0, v1, v2, v3);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform4i>(location, v0, v1, v2, v3);
+
+        if (context->skipValidation() || ValidateUniform4i(context, location, v0, v1, v2, v3))
+        {
+            context->uniform4i(location, v0, v1, v2, v3);
+        }
+    }
+}
+
+void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLint *value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Uniform4iv>(location, count, value);
+
+        if (context->skipValidation() || ValidateUniform4iv(context, location, count, value))
+        {
+            context->uniform4iv(location, count, value);
+        }
+    }
+}
+
+void GL_APIENTRY UniformMatrix2fv(GLint location,
+                                  GLsizei count,
+                                  GLboolean transpose,
+                                  const GLfloat *value)
+{
+    EVENT(
+        "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+        "= 0x%0.8p)",
+        location, count, transpose, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::UniformMatrix2fv>(location, count, transpose, value);
+
+        if (context->skipValidation() ||
+            ValidateUniformMatrix2fv(context, location, count, transpose, value))
+        {
+            context->uniformMatrix2fv(location, count, transpose, value);
+        }
+    }
+}
+
+void GL_APIENTRY UniformMatrix3fv(GLint location,
+                                  GLsizei count,
+                                  GLboolean transpose,
+                                  const GLfloat *value)
+{
+    EVENT(
+        "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+        "= 0x%0.8p)",
+        location, count, transpose, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::UniformMatrix3fv>(location, count, transpose, value);
+
+        if (context->skipValidation() ||
+            ValidateUniformMatrix3fv(context, location, count, transpose, value))
+        {
+            context->uniformMatrix3fv(location, count, transpose, value);
+        }
+    }
+}
+
+void GL_APIENTRY UniformMatrix4fv(GLint location,
+                                  GLsizei count,
+                                  GLboolean transpose,
+                                  const GLfloat *value)
+{
+    EVENT(
+        "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+        "= 0x%0.8p)",
+        location, count, transpose, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::UniformMatrix4fv>(location, count, transpose, value);
+
+        if (context->skipValidation() ||
+            ValidateUniformMatrix4fv(context, location, count, transpose, value))
+        {
+            context->uniformMatrix4fv(location, count, transpose, value);
+        }
+    }
+}
+
+void GL_APIENTRY UseProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::UseProgram>(program);
+
+        if (context->skipValidation() || ValidateUseProgram(context, program))
+        {
+            context->useProgram(program);
+        }
+    }
+}
+
+void GL_APIENTRY ValidateProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ValidateProgram>(program);
+
+        if (context->skipValidation() || ValidateValidateProgram(context, program))
+        {
+            context->validateProgram(program);
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x)
+{
+    EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::VertexAttrib1f>(index, x);
+
+        if (context->skipValidation() || ValidateVertexAttrib1f(context, index, x))
+        {
+            context->vertexAttrib1f(index, x);
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat *v)
+{
+    EVENT("(GLuint index = %d, const GLfloat *v = 0x%0.8p)", index, v);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::VertexAttrib1fv>(index, v);
+
+        if (context->skipValidation() || ValidateVertexAttrib1fv(context, index, v))
+        {
+            context->vertexAttrib1fv(index, v);
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::VertexAttrib2f>(index, x, y);
+
+        if (context->skipValidation() || ValidateVertexAttrib2f(context, index, x, y))
+        {
+            context->vertexAttrib2f(index, x, y);
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat *v)
+{
+    EVENT("(GLuint index = %d, const GLfloat *v = 0x%0.8p)", index, v);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::VertexAttrib2fv>(index, v);
+
+        if (context->skipValidation() || ValidateVertexAttrib2fv(context, index, v))
+        {
+            context->vertexAttrib2fv(index, v);
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::VertexAttrib3f>(index, x, y, z);
+
+        if (context->skipValidation() || ValidateVertexAttrib3f(context, index, x, y, z))
+        {
+            context->vertexAttrib3f(index, x, y, z);
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat *v)
+{
+    EVENT("(GLuint index = %d, const GLfloat *v = 0x%0.8p)", index, v);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::VertexAttrib3fv>(index, v);
+
+        if (context->skipValidation() || ValidateVertexAttrib3fv(context, index, v))
+        {
+            context->vertexAttrib3fv(index, v);
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)",
+          index, x, y, z, w);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::VertexAttrib4f>(index, x, y, z, w);
+
+        if (context->skipValidation() || ValidateVertexAttrib4f(context, index, x, y, z, w))
+        {
+            context->vertexAttrib4f(index, x, y, z, w);
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat *v)
+{
+    EVENT("(GLuint index = %d, const GLfloat *v = 0x%0.8p)", index, v);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::VertexAttrib4fv>(index, v);
+
+        if (context->skipValidation() || ValidateVertexAttrib4fv(context, index, v))
+        {
+            context->vertexAttrib4fv(index, v);
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttribPointer(GLuint index,
+                                     GLint size,
+                                     GLenum type,
+                                     GLboolean normalized,
+                                     GLsizei stride,
+                                     const void *pointer)
+{
+    EVENT(
+        "(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, GLboolean normalized = %u, "
+        "GLsizei stride = %d, const void *pointer = 0x%0.8p)",
+        index, size, type, normalized, stride, pointer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::VertexAttribPointer>(index, size, type, normalized,
+                                                               stride, pointer);
+
+        if (context->skipValidation() ||
+            ValidateVertexAttribPointer(context, index, size, type, normalized, stride, pointer))
+        {
+            context->vertexAttribPointer(index, size, type, normalized, stride, pointer);
+        }
+    }
+}
+
+void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width,
+          height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::Viewport>(x, y, width, height);
+
+        if (context->skipValidation() || ValidateViewport(context, x, y, width, height))
+        {
+            context->viewport(x, y, width, height);
+        }
+    }
+}
+}  // namespace gl
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_autogen.h b/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_autogen.h
new file mode 100644
index 0000000..7735b46
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_autogen.h
@@ -0,0 +1,297 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 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.
+//
+// entry_points_gles_2_0_autogen.h:
+//   Defines the GLES 2.0 entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTSGLES20_AUTOGEN_H_
+#define LIBGLESV2_ENTRYPOINTSGLES20_AUTOGEN_H_
+
+#include <GLES2/gl2.h>
+#include <export.h>
+
+namespace gl
+{
+ANGLE_EXPORT void GL_APIENTRY ActiveTexture(GLenum texture);
+ANGLE_EXPORT void GL_APIENTRY AttachShader(GLuint program, GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer);
+ANGLE_EXPORT void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer);
+ANGLE_EXPORT void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer);
+ANGLE_EXPORT void GL_APIENTRY BindTexture(GLenum target, GLuint texture);
+ANGLE_EXPORT void GL_APIENTRY BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+ANGLE_EXPORT void GL_APIENTRY BlendEquation(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
+ANGLE_EXPORT void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor);
+ANGLE_EXPORT void GL_APIENTRY BlendFuncSeparate(GLenum sfactorRGB,
+                                                GLenum dfactorRGB,
+                                                GLenum sfactorAlpha,
+                                                GLenum dfactorAlpha);
+ANGLE_EXPORT void GL_APIENTRY BufferData(GLenum target,
+                                         GLsizeiptr size,
+                                         const void *data,
+                                         GLenum usage);
+ANGLE_EXPORT void GL_APIENTRY BufferSubData(GLenum target,
+                                            GLintptr offset,
+                                            GLsizeiptr size,
+                                            const void *data);
+ANGLE_EXPORT GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY Clear(GLbitfield mask);
+ANGLE_EXPORT void GL_APIENTRY ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+ANGLE_EXPORT void GL_APIENTRY ClearDepthf(GLfloat d);
+ANGLE_EXPORT void GL_APIENTRY ClearStencil(GLint s);
+ANGLE_EXPORT void GL_APIENTRY ColorMask(GLboolean red,
+                                        GLboolean green,
+                                        GLboolean blue,
+                                        GLboolean alpha);
+ANGLE_EXPORT void GL_APIENTRY CompileShader(GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2D(GLenum target,
+                                                   GLint level,
+                                                   GLenum internalformat,
+                                                   GLsizei width,
+                                                   GLsizei height,
+                                                   GLint border,
+                                                   GLsizei imageSize,
+                                                   const void *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2D(GLenum target,
+                                                      GLint level,
+                                                      GLint xoffset,
+                                                      GLint yoffset,
+                                                      GLsizei width,
+                                                      GLsizei height,
+                                                      GLenum format,
+                                                      GLsizei imageSize,
+                                                      const void *data);
+ANGLE_EXPORT void GL_APIENTRY CopyTexImage2D(GLenum target,
+                                             GLint level,
+                                             GLenum internalformat,
+                                             GLint x,
+                                             GLint y,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLint border);
+ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage2D(GLenum target,
+                                                GLint level,
+                                                GLint xoffset,
+                                                GLint yoffset,
+                                                GLint x,
+                                                GLint y,
+                                                GLsizei width,
+                                                GLsizei height);
+ANGLE_EXPORT GLuint GL_APIENTRY CreateProgram();
+ANGLE_EXPORT GLuint GL_APIENTRY CreateShader(GLenum type);
+ANGLE_EXPORT void GL_APIENTRY CullFace(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint *buffers);
+ANGLE_EXPORT void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint *framebuffers);
+ANGLE_EXPORT void GL_APIENTRY DeleteProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers);
+ANGLE_EXPORT void GL_APIENTRY DeleteShader(GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint *textures);
+ANGLE_EXPORT void GL_APIENTRY DepthFunc(GLenum func);
+ANGLE_EXPORT void GL_APIENTRY DepthMask(GLboolean flag);
+ANGLE_EXPORT void GL_APIENTRY DepthRangef(GLfloat n, GLfloat f);
+ANGLE_EXPORT void GL_APIENTRY DetachShader(GLuint program, GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY Disable(GLenum cap);
+ANGLE_EXPORT void GL_APIENTRY DisableVertexAttribArray(GLuint index);
+ANGLE_EXPORT void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count);
+ANGLE_EXPORT void GL_APIENTRY DrawElements(GLenum mode,
+                                           GLsizei count,
+                                           GLenum type,
+                                           const void *indices);
+ANGLE_EXPORT void GL_APIENTRY Enable(GLenum cap);
+ANGLE_EXPORT void GL_APIENTRY EnableVertexAttribArray(GLuint index);
+ANGLE_EXPORT void GL_APIENTRY Finish();
+ANGLE_EXPORT void GL_APIENTRY Flush();
+ANGLE_EXPORT void GL_APIENTRY FramebufferRenderbuffer(GLenum target,
+                                                      GLenum attachment,
+                                                      GLenum renderbuffertarget,
+                                                      GLuint renderbuffer);
+ANGLE_EXPORT void GL_APIENTRY FramebufferTexture2D(GLenum target,
+                                                   GLenum attachment,
+                                                   GLenum textarget,
+                                                   GLuint texture,
+                                                   GLint level);
+ANGLE_EXPORT void GL_APIENTRY FrontFace(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY GenBuffers(GLsizei n, GLuint *buffers);
+ANGLE_EXPORT void GL_APIENTRY GenerateMipmap(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint *framebuffers);
+ANGLE_EXPORT void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint *renderbuffers);
+ANGLE_EXPORT void GL_APIENTRY GenTextures(GLsizei n, GLuint *textures);
+ANGLE_EXPORT void GL_APIENTRY GetActiveAttrib(GLuint program,
+                                              GLuint index,
+                                              GLsizei bufSize,
+                                              GLsizei *length,
+                                              GLint *size,
+                                              GLenum *type,
+                                              GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniform(GLuint program,
+                                               GLuint index,
+                                               GLsizei bufSize,
+                                               GLsizei *length,
+                                               GLint *size,
+                                               GLenum *type,
+                                               GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetAttachedShaders(GLuint program,
+                                                 GLsizei maxCount,
+                                                 GLsizei *count,
+                                                 GLuint *shaders);
+ANGLE_EXPORT GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean *data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT GLenum GL_APIENTRY GetError();
+ANGLE_EXPORT void GL_APIENTRY GetFloatv(GLenum pname, GLfloat *data);
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target,
+                                                                  GLenum attachment,
+                                                                  GLenum pname,
+                                                                  GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetIntegerv(GLenum pname, GLint *data);
+ANGLE_EXPORT void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetProgramInfoLog(GLuint program,
+                                                GLsizei bufSize,
+                                                GLsizei *length,
+                                                GLchar *infoLog);
+ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameteriv(GLenum target,
+                                                         GLenum pname,
+                                                         GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetShaderInfoLog(GLuint shader,
+                                               GLsizei bufSize,
+                                               GLsizei *length,
+                                               GLchar *infoLog);
+ANGLE_EXPORT void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype,
+                                                       GLenum precisiontype,
+                                                       GLint *range,
+                                                       GLint *precision);
+ANGLE_EXPORT void GL_APIENTRY GetShaderSource(GLuint shader,
+                                              GLsizei bufSize,
+                                              GLsizei *length,
+                                              GLchar *source);
+ANGLE_EXPORT const GLubyte *GL_APIENTRY GetString(GLenum name);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint *params);
+ANGLE_EXPORT GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer);
+ANGLE_EXPORT void GL_APIENTRY Hint(GLenum target, GLenum mode);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsBuffer(GLuint buffer);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsEnabled(GLenum cap);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsProgram(GLuint program);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsShader(GLuint shader);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsTexture(GLuint texture);
+ANGLE_EXPORT void GL_APIENTRY LineWidth(GLfloat width);
+ANGLE_EXPORT void GL_APIENTRY LinkProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY PixelStorei(GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units);
+ANGLE_EXPORT void GL_APIENTRY ReadPixels(GLint x,
+                                         GLint y,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLenum format,
+                                         GLenum type,
+                                         void *pixels);
+ANGLE_EXPORT void GL_APIENTRY ReleaseShaderCompiler();
+ANGLE_EXPORT void GL_APIENTRY RenderbufferStorage(GLenum target,
+                                                  GLenum internalformat,
+                                                  GLsizei width,
+                                                  GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY SampleCoverage(GLfloat value, GLboolean invert);
+ANGLE_EXPORT void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY ShaderBinary(GLsizei count,
+                                           const GLuint *shaders,
+                                           GLenum binaryformat,
+                                           const void *binary,
+                                           GLsizei length);
+ANGLE_EXPORT void GL_APIENTRY ShaderSource(GLuint shader,
+                                           GLsizei count,
+                                           const GLchar *const *string,
+                                           const GLint *length);
+ANGLE_EXPORT void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilMask(GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass);
+ANGLE_EXPORT void GL_APIENTRY StencilOpSeparate(GLenum face,
+                                                GLenum sfail,
+                                                GLenum dpfail,
+                                                GLenum dppass);
+ANGLE_EXPORT void GL_APIENTRY TexImage2D(GLenum target,
+                                         GLint level,
+                                         GLint internalformat,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLint border,
+                                         GLenum format,
+                                         GLenum type,
+                                         const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param);
+ANGLE_EXPORT void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint *params);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage2D(GLenum target,
+                                            GLint level,
+                                            GLint xoffset,
+                                            GLint yoffset,
+                                            GLsizei width,
+                                            GLsizei height,
+                                            GLenum format,
+                                            GLenum type,
+                                            const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY Uniform1f(GLint location, GLfloat v0);
+ANGLE_EXPORT void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform1i(GLint location, GLint v0);
+ANGLE_EXPORT void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform2f(GLint location, GLfloat v0, GLfloat v1);
+ANGLE_EXPORT void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform2i(GLint location, GLint v0, GLint v1);
+ANGLE_EXPORT void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+ANGLE_EXPORT void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform3i(GLint location, GLint v0, GLint v1, GLint v2);
+ANGLE_EXPORT void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY
+Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+ANGLE_EXPORT void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+ANGLE_EXPORT void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix2fv(GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix3fv(GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix4fv(GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UseProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY ValidateProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat *v);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat *v);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat *v);
+ANGLE_EXPORT void GL_APIENTRY
+VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat *v);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribPointer(GLuint index,
+                                                  GLint size,
+                                                  GLenum type,
+                                                  GLboolean normalized,
+                                                  GLsizei stride,
+                                                  const void *pointer);
+ANGLE_EXPORT void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+}  // namespace gl
+
+#endif  // LIBGLESV2_ENTRYPOINTSGLES20_AUTOGEN_H_
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp
new file mode 100644
index 0000000..f9f59f5
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp
@@ -0,0 +1,3542 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_2_0_ext.cpp : Implements the GLES 2.0 extension entry points.
+
+#include "libGLESv2/entry_points_gles_2_0_ext.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
+#include "libANGLE/validationES31.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+namespace
+{
+
+void SetRobustLengthParam(GLsizei *length, GLsizei value)
+{
+    if (length)
+    {
+        *length = value;
+    }
+}
+
+}  // anonymous namespace
+
+void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint *ids)
+{
+    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGenQueriesEXT(context, n))
+        {
+            return;
+        }
+
+        for (GLsizei i = 0; i < n; i++)
+        {
+            ids[i] = context->createQuery();
+        }
+    }
+}
+
+void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids)
+{
+    EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateDeleteQueriesEXT(context, n))
+        {
+            return;
+        }
+
+        for (int i = 0; i < n; i++)
+        {
+            context->deleteQuery(ids[i]);
+        }
+    }
+}
+
+GLboolean GL_APIENTRY IsQueryEXT(GLuint id)
+{
+    EVENT("(GLuint id = %d)", id);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        return (context->getQuery(id, false, GL_NONE) != nullptr) ? GL_TRUE : GL_FALSE;
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint id)
+{
+    EVENT("(GLenum target = 0x%X, GLuint %d)", target, id);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateBeginQueryEXT(context, target, id))
+        {
+            return;
+        }
+
+        Error error = context->beginQuery(target, id);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY EndQueryEXT(GLenum target)
+{
+    EVENT("GLenum target = 0x%X)", target);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateEndQueryEXT(context, target))
+        {
+            return;
+        }
+
+        Error error = context->endQuery(target);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY QueryCounterEXT(GLuint id, GLenum target)
+{
+    EVENT("GLuint id = %d, GLenum target = 0x%X)", id, target);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateQueryCounterEXT(context, id, target))
+        {
+            return;
+        }
+
+        Error error = context->queryCounter(id, target);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
+{
+    EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetQueryivEXT(context, target, pname, params))
+        {
+            return;
+        }
+
+        context->getQueryiv(target, pname, params);
+    }
+}
+
+void GL_APIENTRY GetQueryObjectivEXT(GLuint id, GLenum pname, GLint *params)
+{
+    EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetQueryObjectivEXT(context, id, pname, params))
+        {
+            return;
+        }
+
+        context->getQueryObjectiv(id, pname, params);
+    }
+}
+
+void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
+{
+    EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetQueryObjectuivEXT(context, id, pname, params))
+        {
+            return;
+        }
+
+        context->getQueryObjectuiv(id, pname, params);
+    }
+}
+
+void GL_APIENTRY GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64 *params)
+{
+    EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.16p)", id, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetQueryObjecti64vEXT(context, id, pname, params))
+        {
+            return;
+        }
+
+        context->getQueryObjecti64v(id, pname, params);
+    }
+}
+
+void GL_APIENTRY GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 *params)
+{
+    EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.16p)", id, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetQueryObjectui64vEXT(context, id, pname, params))
+        {
+            return;
+        }
+
+        context->getQueryObjectui64v(id, pname, params);
+    }
+}
+
+void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint *fences)
+{
+    EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (n < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        for (int i = 0; i < n; i++)
+        {
+            context->deleteFenceNV(fences[i]);
+        }
+    }
+}
+
+void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode,
+                                          GLint first,
+                                          GLsizei count,
+                                          GLsizei primcount)
+{
+    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)",
+          mode, first, count, primcount);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount))
+        {
+            return;
+        }
+
+        context->drawArraysInstanced(mode, first, count, primcount);
+    }
+}
+
+void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode,
+                                            GLsizei count,
+                                            GLenum type,
+                                            const void *indices,
+                                            GLsizei primcount)
+{
+    EVENT(
+        "(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void* indices = "
+        "0x%0.8p, GLsizei primcount = %d)",
+        mode, count, type, indices, primcount);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DrawElementsInstancedANGLE>(mode, count, type, indices,
+                                                                      primcount);
+
+        if (!context->skipValidation() &&
+            !ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount))
+        {
+            return;
+        }
+
+        context->drawElementsInstanced(mode, count, type, indices, primcount);
+    }
+}
+
+void GL_APIENTRY FinishFenceNV(GLuint fence)
+{
+    EVENT("(GLuint fence = %d)", fence);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        FenceNV *fenceObject = context->getFenceNV(fence);
+
+        if (fenceObject == nullptr)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (fenceObject->isSet() != GL_TRUE)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        fenceObject->finish();
+    }
+}
+
+void GL_APIENTRY GenFencesNV(GLsizei n, GLuint *fences)
+{
+    EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (n < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        for (int i = 0; i < n; i++)
+        {
+            fences[i] = context->createFenceNV();
+        }
+    }
+}
+
+void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
+{
+    EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        FenceNV *fenceObject = context->getFenceNV(fence);
+
+        if (fenceObject == nullptr)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (fenceObject->isSet() != GL_TRUE)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        switch (pname)
+        {
+            case GL_FENCE_STATUS_NV:
+            {
+                // GL_NV_fence spec:
+                // Once the status of a fence has been finished (via FinishFenceNV) or tested and
+                // the returned status is TRUE (via either TestFenceNV or GetFenceivNV querying the
+                // FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
+                GLboolean status = GL_TRUE;
+                if (fenceObject->getStatus() != GL_TRUE)
+                {
+                    Error error = fenceObject->test(&status);
+                    if (error.isError())
+                    {
+                        context->handleError(error);
+                        return;
+                    }
+                }
+                *params = status;
+                break;
+            }
+
+            case GL_FENCE_CONDITION_NV:
+            {
+                *params = static_cast<GLint>(fenceObject->getCondition());
+                break;
+            }
+
+            default:
+            {
+                context->handleError(Error(GL_INVALID_ENUM));
+                return;
+            }
+        }
+    }
+}
+
+GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void)
+{
+    EVENT("()");
+
+    Context *context = GetGlobalContext();
+
+    if (context)
+    {
+        return context->getResetStatus();
+    }
+
+    return GL_NO_ERROR;
+}
+
+void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader,
+                                                GLsizei bufsize,
+                                                GLsizei *length,
+                                                GLchar *source)
+{
+    EVENT(
+        "(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = "
+        "0x%0.8p)",
+        shader, bufsize, length, source);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (bufsize < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        Shader *shaderObject = context->getShader(shader);
+
+        if (!shaderObject)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source);
+    }
+}
+
+void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
+{
+    EVENT(
+        "(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = "
+        "0x%0.8p)",
+        program, location, bufSize, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+
+        programObject->getUniformfv(location, params);
+    }
+}
+
+void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params)
+{
+    EVENT(
+        "(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
+        program, location, bufSize, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+
+        programObject->getUniformiv(location, params);
+    }
+}
+
+GLboolean GL_APIENTRY IsFenceNV(GLuint fence)
+{
+    EVENT("(GLuint fence = %d)", fence);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        FenceNV *fenceObject = context->getFenceNV(fence);
+
+        if (fenceObject == nullptr)
+        {
+            return GL_FALSE;
+        }
+
+        // GL_NV_fence spec:
+        // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an
+        // existing fence.
+        return fenceObject->isSet();
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY ReadnPixelsEXT(GLint x,
+                                GLint y,
+                                GLsizei width,
+                                GLsizei height,
+                                GLenum format,
+                                GLenum type,
+                                GLsizei bufSize,
+                                void *data)
+{
+    EVENT(
+        "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+        "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, void *data = 0x%0.8p)",
+        x, y, width, height, format, type, bufSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateReadnPixelsEXT(context, x, y, width, height, format, type, bufSize, data))
+        {
+            return;
+        }
+
+        context->readPixels(x, y, width, height, format, type, data);
+    }
+}
+
+void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target,
+                                                     GLsizei samples,
+                                                     GLenum internalformat,
+                                                     GLsizei width,
+                                                     GLsizei height)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width "
+        "= %d, GLsizei height = %d)",
+        target, samples, internalformat, width, height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateRenderbufferStorageMultisampleANGLE(context, target, samples, internalformat,
+                                                         width, height))
+        {
+            return;
+        }
+
+        context->renderbufferStorageMultisample(target, samples, internalformat, width, height);
+    }
+}
+
+void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition)
+{
+    EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (condition != GL_ALL_COMPLETED_NV)
+        {
+            context->handleError(Error(GL_INVALID_ENUM));
+            return;
+        }
+
+        FenceNV *fenceObject = context->getFenceNV(fence);
+
+        if (fenceObject == nullptr)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        Error error = fenceObject->set(condition);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+GLboolean GL_APIENTRY TestFenceNV(GLuint fence)
+{
+    EVENT("(GLuint fence = %d)", fence);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        FenceNV *fenceObject = context->getFenceNV(fence);
+
+        if (fenceObject == nullptr)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return GL_TRUE;
+        }
+
+        if (fenceObject->isSet() != GL_TRUE)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return GL_TRUE;
+        }
+
+        GLboolean result;
+        Error error = fenceObject->test(&result);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return GL_TRUE;
+        }
+
+        return result;
+    }
+
+    return GL_TRUE;
+}
+
+void GL_APIENTRY
+TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = "
+        "%d, GLsizei height = %d)",
+        target, levels, internalformat, width, height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->getExtensions().textureStorage)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (context->getClientMajorVersion() < 3 &&
+            !ValidateES2TexStorageParameters(context, target, levels, internalformat, width,
+                                             height))
+        {
+            return;
+        }
+
+        if (context->getClientMajorVersion() >= 3 &&
+            !ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width,
+                                               height, 1))
+        {
+            return;
+        }
+
+        Extents size(width, height, 1);
+        Texture *texture = context->getTargetTexture(target);
+        Error error      = texture->setStorage(context, target, levels, internalformat, size);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+{
+    EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (index >= MAX_VERTEX_ATTRIBS)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        if (context->getLimitations().attributeZeroRequiresZeroDivisorInEXT)
+        {
+            if (index == 0 && divisor != 0)
+            {
+                const char *errorMessage =
+                    "The current context doesn't support setting a non-zero divisor on the "
+                    "attribute with index zero. "
+                    "Please reorder the attributes in your vertex shader so that attribute zero "
+                    "can have a zero divisor.";
+                context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
+
+                // We also output an error message to the debugger window if tracing is active, so
+                // that developers can see the error message.
+                ERR() << errorMessage;
+
+                return;
+            }
+        }
+
+        context->setVertexAttribDivisor(index, divisor);
+    }
+}
+
+void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0,
+                                      GLint srcY0,
+                                      GLint srcX1,
+                                      GLint srcY1,
+                                      GLint dstX0,
+                                      GLint dstY0,
+                                      GLint dstX1,
+                                      GLint dstY1,
+                                      GLbitfield mask,
+                                      GLenum filter)
+{
+    EVENT(
+        "(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
+        "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
+        "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
+        srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateBlitFramebufferANGLE(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1,
+                                          dstY1, mask, filter))
+        {
+            return;
+        }
+
+        context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
+                                 filter);
+    }
+}
+
+void GL_APIENTRY DiscardFramebufferEXT(GLenum target,
+                                       GLsizei numAttachments,
+                                       const GLenum *attachments)
+{
+    EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, attachments = 0x%0.8p)", target,
+          numAttachments, attachments);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateDiscardFramebufferEXT(context, target, numAttachments, attachments))
+        {
+            return;
+        }
+
+        context->discardFramebuffer(target, numAttachments, attachments);
+    }
+}
+
+void GL_APIENTRY TexImage3DOES(GLenum target,
+                               GLint level,
+                               GLenum internalformat,
+                               GLsizei width,
+                               GLsizei height,
+                               GLsizei depth,
+                               GLint border,
+                               GLenum format,
+                               GLenum type,
+                               const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
+        "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
+        "GLenum format = 0x%X, GLenum type = 0x%x, const void* pixels = 0x%0.8p)",
+        target, level, internalformat, width, height, depth, border, format, type, pixels);
+
+    UNIMPLEMENTED();  // FIXME
+}
+
+void GL_APIENTRY GetProgramBinaryOES(GLuint program,
+                                     GLsizei bufSize,
+                                     GLsizei *length,
+                                     GLenum *binaryFormat,
+                                     void *binary)
+{
+    EVENT(
+        "(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = "
+        "0x%0.8p)",
+        program, bufSize, length, binaryFormat, binary);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetProgramBinaryOES(context, program, bufSize, length, binaryFormat, binary))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject != nullptr);
+
+        Error error = programObject->saveBinary(context, binaryFormat, binary, bufSize, length);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY ProgramBinaryOES(GLuint program,
+                                  GLenum binaryFormat,
+                                  const void *binary,
+                                  GLint length)
+{
+    EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", program,
+          binaryFormat, binary, length);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramBinaryOES(context, program, binaryFormat, binary, length))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject != nullptr);
+
+        Error error = programObject->loadBinary(context, binaryFormat, binary, length);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs)
+{
+    EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateDrawBuffersEXT(context, n, bufs))
+        {
+            return;
+        }
+
+        context->drawBuffers(n, bufs);
+    }
+}
+
+void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void **params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, void** params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetBufferPointervOES(context, target, pname, params))
+        {
+            return;
+        }
+
+        context->getBufferPointerv(target, pname, params);
+    }
+}
+
+void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access)
+{
+    EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateMapBufferOES(context, target, access))
+        {
+            return nullptr;
+        }
+
+        return context->mapBuffer(target, access);
+    }
+
+    return nullptr;
+}
+
+GLboolean GL_APIENTRY UnmapBufferOES(GLenum target)
+{
+    EVENT("(GLenum target = 0x%X)", target);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateUnmapBufferOES(context, target))
+        {
+            return GL_FALSE;
+        }
+
+        return context->unmapBuffer(target);
+    }
+
+    return GL_FALSE;
+}
+
+void *GL_APIENTRY MapBufferRangeEXT(GLenum target,
+                                    GLintptr offset,
+                                    GLsizeiptr length,
+                                    GLbitfield access)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = "
+        "0x%X)",
+        target, offset, length, access);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateMapBufferRangeEXT(context, target, offset, length, access))
+        {
+            return nullptr;
+        }
+
+        return context->mapBufferRange(target, offset, length, access);
+    }
+
+    return nullptr;
+}
+
+void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+    EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset,
+          length);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateFlushMappedBufferRangeEXT(context, target, offset, length))
+        {
+            return;
+        }
+
+        context->flushMappedBufferRange(target, offset, length);
+    }
+}
+
+void GL_APIENTRY InsertEventMarkerEXT(GLsizei length, const char *marker)
+{
+    // Don't run an EVENT() macro on the EXT_debug_marker entry points.
+    // It can interfere with the debug events being set by the caller.
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->getExtensions().debugMarker)
+        {
+            // The debug marker calls should not set error state
+            // However, it seems reasonable to set an error state if the extension is not enabled
+            context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+            return;
+        }
+
+        if (!ValidateInsertEventMarkerEXT(context, length, marker))
+        {
+            return;
+        }
+
+        context->insertEventMarker(length, marker);
+    }
+}
+
+void GL_APIENTRY PushGroupMarkerEXT(GLsizei length, const char *marker)
+{
+    // Don't run an EVENT() macro on the EXT_debug_marker entry points.
+    // It can interfere with the debug events being set by the caller.
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->getExtensions().debugMarker)
+        {
+            // The debug marker calls should not set error state
+            // However, it seems reasonable to set an error state if the extension is not enabled
+            context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+            return;
+        }
+
+        if (!ValidatePushGroupMarkerEXT(context, length, marker))
+        {
+            return;
+        }
+
+        if (marker == nullptr)
+        {
+            // From the EXT_debug_marker spec,
+            // "If <marker> is null then an empty string is pushed on the stack."
+            context->pushGroupMarker(length, "");
+        }
+        else
+        {
+            context->pushGroupMarker(length, marker);
+        }
+    }
+}
+
+void GL_APIENTRY PopGroupMarkerEXT()
+{
+    // Don't run an EVENT() macro on the EXT_debug_marker entry points.
+    // It can interfere with the debug events being set by the caller.
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->getExtensions().debugMarker)
+        {
+            // The debug marker calls should not set error state
+            // However, it seems reasonable to set an error state if the extension is not enabled
+            context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+            return;
+        }
+
+        context->popGroupMarker();
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+    EVENT("(GLenum target = 0x%X, GLeglImageOES image = 0x%0.8p)", target, image);
+
+    egl::Thread *thread = egl::GetCurrentThread();
+    Context *context    = thread->getValidContext();
+    if (context)
+    {
+        egl::Display *display   = thread->getDisplay();
+        egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
+        if (!ValidateEGLImageTargetTexture2DOES(context, display, target, imageObject))
+        {
+            return;
+        }
+
+        Texture *texture = context->getTargetTexture(target);
+        Error error      = texture->setEGLImageTarget(target, imageObject);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY EGLImageTargetRenderbufferStorageOES(GLenum target,
+                                                                   GLeglImageOES image)
+{
+    EVENT("(GLenum target = 0x%X, GLeglImageOES image = 0x%0.8p)", target, image);
+
+    egl::Thread *thread = egl::GetCurrentThread();
+    Context *context    = thread->getValidContext();
+    if (context)
+    {
+        egl::Display *display   = thread->getDisplay();
+        egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
+        if (!ValidateEGLImageTargetRenderbufferStorageOES(context, display, target, imageObject))
+        {
+            return;
+        }
+
+        Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
+        Error error                = renderbuffer->setStorageEGLImageTarget(imageObject);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY BindVertexArrayOES(GLuint array)
+{
+    EVENT("(GLuint array = %u)", array);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateBindVertexArrayOES(context, array))
+        {
+            return;
+        }
+
+        context->bindVertexArray(array);
+    }
+}
+
+void GL_APIENTRY DeleteVertexArraysOES(GLsizei n, const GLuint *arrays)
+{
+    EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateDeleteVertexArraysOES(context, n))
+        {
+            return;
+        }
+
+        for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+        {
+            if (arrays[arrayIndex] != 0)
+            {
+                context->deleteVertexArray(arrays[arrayIndex]);
+            }
+        }
+    }
+}
+
+void GL_APIENTRY GenVertexArraysOES(GLsizei n, GLuint *arrays)
+{
+    EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGenVertexArraysOES(context, n))
+        {
+            return;
+        }
+
+        for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+        {
+            arrays[arrayIndex] = context->createVertexArray();
+        }
+    }
+}
+
+GLboolean GL_APIENTRY IsVertexArrayOES(GLuint array)
+{
+    EVENT("(GLuint array = %u)", array);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateIsVertexArrayOES(context))
+        {
+            return GL_FALSE;
+        }
+
+        if (array == 0)
+        {
+            return GL_FALSE;
+        }
+
+        VertexArray *vao = context->getVertexArray(array);
+
+        return (vao != nullptr ? GL_TRUE : GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY DebugMessageControlKHR(GLenum source,
+                                        GLenum type,
+                                        GLenum severity,
+                                        GLsizei count,
+                                        const GLuint *ids,
+                                        GLboolean enabled)
+{
+    EVENT(
+        "(GLenum source = 0x%X, GLenum type = 0x%X, GLenum severity = 0x%X, GLsizei count = %d, "
+        "GLint *ids = 0x%0.8p, GLboolean enabled = %d)",
+        source, type, severity, count, ids, enabled);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateDebugMessageControlKHR(context, source, type, severity, count, ids, enabled))
+        {
+            return;
+        }
+
+        context->debugMessageControl(source, type, severity, count, ids, enabled);
+    }
+}
+
+void GL_APIENTRY DebugMessageInsertKHR(GLenum source,
+                                       GLenum type,
+                                       GLuint id,
+                                       GLenum severity,
+                                       GLsizei length,
+                                       const GLchar *buf)
+{
+    EVENT(
+        "(GLenum source = 0x%X, GLenum type = 0x%X, GLint id = %d, GLenum severity = 0x%X, GLsizei "
+        "length = %d, const GLchar *buf = 0x%0.8p)",
+        source, type, id, severity, length, buf);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateDebugMessageInsertKHR(context, source, type, id, severity, length, buf))
+        {
+            return;
+        }
+
+        context->debugMessageInsert(source, type, id, severity, length, buf);
+    }
+}
+
+void GL_APIENTRY DebugMessageCallbackKHR(GLDEBUGPROCKHR callback, const void *userParam)
+{
+    EVENT("(GLDEBUGPROCKHR callback = 0x%0.8p, const void *userParam = 0x%0.8p)", callback,
+          userParam);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateDebugMessageCallbackKHR(context, callback, userParam))
+        {
+            return;
+        }
+
+        context->debugMessageCallback(callback, userParam);
+    }
+}
+
+GLuint GL_APIENTRY GetDebugMessageLogKHR(GLuint count,
+                                         GLsizei bufSize,
+                                         GLenum *sources,
+                                         GLenum *types,
+                                         GLuint *ids,
+                                         GLenum *severities,
+                                         GLsizei *lengths,
+                                         GLchar *messageLog)
+{
+    EVENT(
+        "(GLsizei count = %d, GLsizei bufSize = %d, GLenum *sources, GLenum *types = 0x%0.8p, "
+        "GLuint *ids = 0x%0.8p, GLenum *severities = 0x%0.8p, GLsizei *lengths = 0x%0.8p, GLchar "
+        "*messageLog = 0x%0.8p)",
+        count, bufSize, sources, types, ids, severities, lengths, messageLog);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetDebugMessageLogKHR(context, count, bufSize, sources, types, ids, severities,
+                                           lengths, messageLog))
+        {
+            return 0;
+        }
+
+        return context->getDebugMessageLog(count, bufSize, sources, types, ids, severities, lengths,
+                                           messageLog);
+    }
+
+    return 0;
+}
+
+void GL_APIENTRY PushDebugGroupKHR(GLenum source, GLuint id, GLsizei length, const GLchar *message)
+{
+    EVENT(
+        "(GLenum source = 0x%X, GLuint id = 0x%X, GLsizei length = %d, const GLchar *message = "
+        "0x%0.8p)",
+        source, id, length, message);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidatePushDebugGroupKHR(context, source, id, length, message))
+        {
+            return;
+        }
+
+        std::string msg(message, (length > 0) ? static_cast<size_t>(length) : strlen(message));
+        context->pushDebugGroup(source, id, length, message);
+    }
+}
+
+void GL_APIENTRY PopDebugGroupKHR(void)
+{
+    EVENT("()");
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidatePopDebugGroupKHR(context))
+        {
+            return;
+        }
+
+        context->popDebugGroup();
+    }
+}
+
+void GL_APIENTRY ObjectLabelKHR(GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
+{
+    EVENT(
+        "(GLenum identifier = 0x%X, GLuint name = %u, GLsizei length = %d, const GLchar *label = "
+        "0x%0.8p)",
+        identifier, name, length, label);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateObjectLabelKHR(context, identifier, name, length, label))
+        {
+            return;
+        }
+
+        context->objectLabel(identifier, name, length, label);
+    }
+}
+
+void GL_APIENTRY
+GetObjectLabelKHR(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label)
+{
+    EVENT(
+        "(GLenum identifier = 0x%X, GLuint name = %u, GLsizei bufSize = %d, GLsizei *length = "
+        "0x%0.8p, GLchar *label = 0x%0.8p)",
+        identifier, name, bufSize, length, label);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetObjectLabelKHR(context, identifier, name, bufSize, length, label))
+        {
+            return;
+        }
+
+        context->getObjectLabel(identifier, name, bufSize, length, label);
+    }
+}
+
+void GL_APIENTRY ObjectPtrLabelKHR(const void *ptr, GLsizei length, const GLchar *label)
+{
+    EVENT("(const void *ptr = 0x%0.8p, GLsizei length = %d, const GLchar *label = 0x%0.8p)", ptr,
+          length, label);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateObjectPtrLabelKHR(context, ptr, length, label))
+        {
+            return;
+        }
+
+        context->objectPtrLabel(ptr, length, label);
+    }
+}
+
+void GL_APIENTRY GetObjectPtrLabelKHR(const void *ptr,
+                                      GLsizei bufSize,
+                                      GLsizei *length,
+                                      GLchar *label)
+{
+    EVENT(
+        "(const void *ptr = 0x%0.8p, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLchar "
+        "*label = 0x%0.8p)",
+        ptr, bufSize, length, label);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetObjectPtrLabelKHR(context, ptr, bufSize, length, label))
+        {
+            return;
+        }
+
+        context->getObjectPtrLabel(ptr, bufSize, length, label);
+    }
+}
+
+void GL_APIENTRY GetPointervKHR(GLenum pname, void **params)
+{
+    EVENT("(GLenum pname = 0x%X, void **params = 0x%0.8p)", pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetPointervKHR(context, pname, params))
+        {
+            return;
+        }
+
+        context->getPointerv(pname, params);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
+                                                          GLint location,
+                                                          const GLchar *name)
+{
+    EVENT("(GLuint program = %u, GLint location = %d, const GLchar *name = 0x%0.8p)", program,
+          location, name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateBindUniformLocationCHROMIUM(context, program, location, name))
+        {
+            return;
+        }
+
+        context->bindUniformLocation(program, location, name);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components)
+{
+    EVENT("(GLenum components = %u)", components);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateCoverageModulationCHROMIUM(context, components))
+        {
+            return;
+        }
+        context->setCoverageModulation(components);
+    }
+}
+
+// CHROMIUM_path_rendering
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
+{
+    EVENT("(GLenum matrixMode = %u)", matrixMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateMatrix(context, matrixMode, matrix))
+        {
+            return;
+        }
+        context->loadPathRenderingMatrix(matrixMode, matrix);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode)
+{
+    EVENT("(GLenum matrixMode = %u)", matrixMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateMatrixMode(context, matrixMode))
+        {
+            return;
+        }
+        context->loadPathRenderingIdentityMatrix(matrixMode);
+    }
+}
+
+ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei range)
+{
+    EVENT("(GLsizei range = %d)", range);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGenPaths(context, range))
+        {
+            return 0;
+        }
+        return context->createPaths(range);
+    }
+    return 0;
+}
+
+ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range)
+{
+    EVENT("(GLuint first = %u, GLsizei range = %d)", first, range);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateDeletePaths(context, first, range))
+        {
+            return;
+        }
+        context->deletePaths(first, range);
+    }
+}
+
+ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path)
+{
+    EVENT("(GLuint path = %u)", path);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateIsPath(context))
+        {
+            return GL_FALSE;
+        }
+        return context->hasPathData(path);
+    }
+    return GL_FALSE;
+}
+
+ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
+                                                   GLsizei numCommands,
+                                                   const GLubyte *commands,
+                                                   GLsizei numCoords,
+                                                   GLenum coordType,
+                                                   const void *coords)
+{
+    EVENT(
+        "(GLuint path = %u, GLsizei numCommands = %d, commands = %p, "
+        "GLsizei numCoords = %d, GLenum coordType = %u, void* coords = %p)",
+        path, numCommands, commands, numCoords, coordType, coords);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            if (!ValidatePathCommands(context, path, numCommands, commands, numCoords, coordType,
+                                      coords))
+            {
+                return;
+            }
+        }
+        context->setPathCommands(path, numCommands, commands, numCoords, coordType, coords);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
+{
+    EVENT("(GLuint path = %u, GLenum pname = %u, GLfloat value = %f)", path, pname, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateSetPathParameter(context, path, pname, value))
+        {
+            return;
+        }
+        context->setPathParameterf(path, pname, value);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
+{
+    PathParameterfCHROMIUM(path, pname, static_cast<GLfloat>(value));
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
+{
+    EVENT("(GLuint path = %u, GLenum pname = %u)", path, pname);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGetPathParameter(context, path, pname, value))
+        {
+            return;
+        }
+        context->getPathParameterfv(path, pname, value);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint *value)
+{
+    GLfloat val = 0.0f;
+    GetPathParameterfCHROMIUM(path, pname, value != nullptr ? &val : nullptr);
+    if (value)
+        *value = static_cast<GLint>(val);
+}
+
+ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
+{
+    EVENT("(GLenum func = %u, GLint ref = %d, GLuint mask = %u)", func, ref, mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidatePathStencilFunc(context, func, ref, mask))
+        {
+            return;
+        }
+        context->setPathStencilFunc(func, ref, mask);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
+{
+    EVENT("(GLuint path = %u, GLenum fillMode = %u, GLuint mask = %u)", path, fillMode, mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateStencilFillPath(context, path, fillMode, mask))
+        {
+            return;
+        }
+        context->stencilFillPath(path, fillMode, mask);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
+{
+    EVENT("(GLuint path = %u, GLint ference = %d, GLuint mask = %u)", path, reference, mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateStencilStrokePath(context, path, reference, mask))
+        {
+            return;
+        }
+        context->stencilStrokePath(path, reference, mask);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
+{
+    EVENT("(GLuint path = %u, GLenum coverMode = %u)", path, coverMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateCoverPath(context, path, coverMode))
+        {
+            return;
+        }
+        context->coverFillPath(path, coverMode);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
+{
+    EVENT("(GLuint path = %u, GLenum coverMode = %u)", path, coverMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateCoverPath(context, path, coverMode))
+        {
+            return;
+        }
+        context->coverStrokePath(path, coverMode);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
+                                                               GLenum fillMode,
+                                                               GLuint mask,
+                                                               GLenum coverMode)
+{
+    EVENT("(GLuint path = %u, GLenum fillMode = %u, GLuint mask = %u, GLenum coverMode = %u)", path,
+          fillMode, mask, coverMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateStencilThenCoverFillPath(context, path, fillMode, mask, coverMode))
+        {
+            return;
+        }
+        context->stencilThenCoverFillPath(path, fillMode, mask, coverMode);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
+                                                                 GLint reference,
+                                                                 GLuint mask,
+                                                                 GLenum coverMode)
+{
+    EVENT("(GLuint path = %u, GLint reference = %d, GLuint mask = %u, GLenum coverMode = %u)", path,
+          reference, mask, coverMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateStencilThenCoverStrokePath(context, path, reference, mask, coverMode))
+        {
+            return;
+        }
+        context->stencilThenCoverStrokePath(path, reference, mask, coverMode);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                             GLenum pathNameType,
+                                                             const void *paths,
+                                                             GLuint pathBase,
+                                                             GLenum coverMode,
+                                                             GLenum transformType,
+                                                             const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPaths = %d, GLenum pathNameType = %u, const void *paths = %p "
+        "GLuint pathBase = %u, GLenum coverMode = %u, GLenum transformType = %u "
+        "const GLfloat *transformValues = %p)",
+        numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCoverFillPathInstanced(context, numPaths, pathNameType, paths, pathBase,
+                                            coverMode, transformType, transformValues))
+        {
+            return;
+        }
+        context->coverFillPathInstanced(numPaths, pathNameType, paths, pathBase, coverMode,
+                                        transformType, transformValues);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                               GLenum pathNameType,
+                                                               const void *paths,
+                                                               GLuint pathBase,
+                                                               GLenum coverMode,
+                                                               GLenum transformType,
+                                                               const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPaths = %d, GLenum pathNameType = %u, const void *paths = %p "
+        "GLuint pathBase = %u, GLenum coverMode = %u, GLenum transformType = %u "
+        "const GLfloat *transformValues = %p)",
+        numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCoverStrokePathInstanced(context, numPaths, pathNameType, paths, pathBase,
+                                              coverMode, transformType, transformValues))
+        {
+            return;
+        }
+        context->coverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, coverMode,
+                                          transformType, transformValues);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                                 GLenum pathNameType,
+                                                                 const void *paths,
+                                                                 GLuint pathBase,
+                                                                 GLint reference,
+                                                                 GLuint mask,
+                                                                 GLenum transformType,
+                                                                 const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPaths = %u, GLenum pathNameType = %u, const void *paths = %p "
+        "GLuint pathBase = %u, GLint reference = %d GLuint mask = %u GLenum transformType = %u "
+        "const GLfloat *transformValues = %p)",
+        numPaths, pathNameType, paths, pathBase, reference, mask, transformType, transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateStencilStrokePathInstanced(context, numPaths, pathNameType, paths, pathBase,
+                                                reference, mask, transformType, transformValues))
+        {
+            return;
+        }
+        context->stencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase, reference,
+                                            mask, transformType, transformValues);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                               GLenum pathNameType,
+                                                               const void *paths,
+                                                               GLuint pathBase,
+                                                               GLenum fillMode,
+                                                               GLuint mask,
+                                                               GLenum transformType,
+                                                               const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPaths = %u, GLenum pathNameType = %u const void *paths = %p "
+        "GLuint pathBase = %u, GLenum fillMode = %u, GLuint mask = %u, GLenum transformType = %u "
+        "const GLfloat *transformValues = %p)",
+        numPaths, pathNameType, paths, pathBase, fillMode, mask, transformType, transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateStencilFillPathInstanced(context, numPaths, pathNameType, paths, pathBase,
+                                              fillMode, mask, transformType, transformValues))
+        {
+            return;
+        }
+        context->stencilFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode, mask,
+                                          transformType, transformValues);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                          GLenum pathNameType,
+                                          const void *paths,
+                                          GLuint pathBase,
+                                          GLenum fillMode,
+                                          GLuint mask,
+                                          GLenum coverMode,
+                                          GLenum transformType,
+                                          const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPaths = %u, GLenum pathNameType = %u const void *paths = %p "
+        "GLuint pathBase = %u, GLenum coverMode = %u, GLuint mask = %u, GLenum transformType = %u "
+        "const GLfloat *transformValues = %p)",
+        numPaths, pathNameType, paths, pathBase, coverMode, mask, transformType, transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateStencilThenCoverFillPathInstanced(context, numPaths, pathNameType, paths,
+                                                       pathBase, fillMode, mask, coverMode,
+                                                       transformType, transformValues))
+        {
+            return;
+        }
+        context->stencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
+                                                   fillMode, mask, coverMode, transformType,
+                                                   transformValues);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                            GLenum pathNameType,
+                                            const void *paths,
+                                            GLuint pathBase,
+                                            GLint reference,
+                                            GLuint mask,
+                                            GLenum coverMode,
+                                            GLenum transformType,
+                                            const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPaths = %u, GLenum pathNameType = %u, const void *paths = %p "
+        "GLuint pathBase = %u GLenum coverMode = %u GLint reference = %d GLuint mask = %u GLenum "
+        "transformType = %u "
+        "const GLfloat *transformValues = %p)",
+        numPaths, pathNameType, paths, pathBase, coverMode, reference, mask, transformType,
+        transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateStencilThenCoverStrokePathInstanced(context, numPaths, pathNameType, paths,
+                                                         pathBase, reference, mask, coverMode,
+                                                         transformType, transformValues))
+        {
+            return;
+        }
+        context->stencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
+                                                     reference, mask, coverMode, transformType,
+                                                     transformValues);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint program,
+                                                                GLint location,
+                                                                const GLchar *name)
+{
+    EVENT("(GLuint program = %u, GLint location = %d, const GLchar *name = %p)", program, location,
+          name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateBindFragmentInputLocation(context, program, location, name))
+        {
+            return;
+        }
+        context->bindFragmentInputLocation(program, location, name);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+                                                                  GLint location,
+                                                                  GLenum genMode,
+                                                                  GLint components,
+                                                                  const GLfloat *coeffs)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location %d, GLenum genMode = %u, GLint components = %d, "
+        "const GLfloat * coeffs = %p)",
+        program, location, genMode, components, coeffs);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateProgramPathFragmentInputGen(context, program, location, genMode, components,
+                                                 coeffs))
+        {
+            return;
+        }
+        context->programPathFragmentInputGen(program, location, genMode, components, coeffs);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CopyTextureCHROMIUM(GLuint sourceId,
+                                                  GLint sourceLevel,
+                                                  GLenum destTarget,
+                                                  GLuint destId,
+                                                  GLint destLevel,
+                                                  GLint internalFormat,
+                                                  GLenum destType,
+                                                  GLboolean unpackFlipY,
+                                                  GLboolean unpackPremultiplyAlpha,
+                                                  GLboolean unpackUnmultiplyAlpha)
+{
+    EVENT(
+        "(GLuint sourceId = %u, GLint sourceLevel = %d, GLenum destTarget = 0x%X, GLuint destId = "
+        "%u, GLint destLevel = %d, GLint internalFormat = 0x%X, GLenum destType = "
+        "0x%X, GLboolean unpackFlipY = %u, GLboolean unpackPremultiplyAlpha = %u, GLboolean "
+        "unpackUnmultiplyAlpha = %u)",
+        sourceId, sourceLevel, destTarget, destId, destLevel, internalFormat, destType, unpackFlipY,
+        unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCopyTextureCHROMIUM(context, sourceId, sourceLevel, destTarget, destId,
+                                         destLevel, internalFormat, destType, unpackFlipY,
+                                         unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
+        {
+            return;
+        }
+
+        context->copyTextureCHROMIUM(sourceId, sourceLevel, destTarget, destId, destLevel,
+                                     internalFormat, destType, unpackFlipY, unpackPremultiplyAlpha,
+                                     unpackUnmultiplyAlpha);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
+                                                     GLint sourceLevel,
+                                                     GLenum destTarget,
+                                                     GLuint destId,
+                                                     GLint destLevel,
+                                                     GLint xoffset,
+                                                     GLint yoffset,
+                                                     GLint x,
+                                                     GLint y,
+                                                     GLsizei width,
+                                                     GLsizei height,
+                                                     GLboolean unpackFlipY,
+                                                     GLboolean unpackPremultiplyAlpha,
+                                                     GLboolean unpackUnmultiplyAlpha)
+{
+    EVENT(
+        "(GLuint sourceId = %u, GLint sourceLevel = %d, GLenum destTarget = 0x%X, GLuint destId = "
+        "%u, GLint destLevel = %d, GLint xoffset = "
+        "%d, GLint yoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = "
+        "%d, GLboolean unpackPremultiplyAlpha = %u, GLboolean unpackUnmultiplyAlpha = %u)",
+        sourceId, sourceLevel, destTarget, destId, destLevel, xoffset, yoffset, x, y, width, height,
+        unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCopySubTextureCHROMIUM(
+                context, sourceId, sourceLevel, destTarget, destId, destLevel, xoffset, yoffset, x,
+                y, width, height, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
+        {
+            return;
+        }
+
+        context->copySubTextureCHROMIUM(sourceId, sourceLevel, destTarget, destId, destLevel,
+                                        xoffset, yoffset, x, y, width, height, unpackFlipY,
+                                        unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId)
+{
+    EVENT("(GLuint sourceId = %u, GLuint destId = %u)", sourceId, destId);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCompressedCopyTextureCHROMIUM(context, sourceId, destId))
+        {
+            return;
+        }
+
+        context->compressedCopyTextureCHROMIUM(sourceId, destId);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY RequestExtensionANGLE(const GLchar *name)
+{
+    EVENT("(const GLchar *name = %p)", name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateRequestExtensionANGLE(context, name))
+        {
+            return;
+        }
+
+        context->requestExtension(name);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLboolean *params)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLboolean* params "
+        "= 0x%0.8p)",
+        pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLenum nativeType;
+        unsigned int numParams = 0;
+        if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
+        {
+            return;
+        }
+
+        context->getBooleanv(pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameterivRobustANGLE(GLenum target,
+                                                              GLenum pname,
+                                                              GLsizei bufSize,
+                                                              GLsizei *length,
+                                                              GLint *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetBufferParameterivRobustANGLE(context, target, pname, bufSize, &numParams,
+                                                     params))
+        {
+            return;
+        }
+
+        Buffer *buffer = context->getGLState().getTargetBuffer(target);
+        QueryBufferParameteriv(buffer, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetFloatvRobustANGLE(GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLfloat *params)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLfloat* params = "
+        "0x%0.8p)",
+        pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLenum nativeType;
+        unsigned int numParams = 0;
+        if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
+        {
+            return;
+        }
+
+        context->getFloatv(pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameterivRobustANGLE(GLenum target,
+                                                                             GLenum attachment,
+                                                                             GLenum pname,
+                                                                             GLsizei bufSize,
+                                                                             GLsizei *length,
+                                                                             GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X,  GLsizei bufsize = "
+        "%d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+        target, attachment, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetFramebufferAttachmentParameterivRobustANGLE(context, target, attachment,
+                                                                    pname, bufSize, &numParams))
+        {
+            return;
+        }
+
+        const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+        QueryFramebufferAttachmentParameteriv(framebuffer, attachment, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetIntegervRobustANGLE(GLenum pname,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLint *data)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLint* params = "
+        "0x%0.8p)",
+        pname, bufSize, length, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLenum nativeType;
+        unsigned int numParams = 0;
+        if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
+        {
+            return;
+        }
+
+        context->getIntegerv(pname, data);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetProgramivRobustANGLE(GLuint program,
+                                                      GLenum pname,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLint *params)
+{
+    EVENT(
+        "(GLuint program = %d, GLenum pname = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLint* params = 0x%0.8p)",
+        program, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetProgramivRobustANGLE(context, program, pname, bufSize, &numParams))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        QueryProgramiv(programObject, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameterivRobustANGLE(GLenum target,
+                                                                    GLenum pname,
+                                                                    GLsizei bufSize,
+                                                                    GLsizei *length,
+                                                                    GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint* params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetRenderbufferParameterivRobustANGLE(context, target, pname, bufSize,
+                                                           &numParams, params))
+        {
+            return;
+        }
+
+        Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
+        QueryRenderbufferiv(context, renderbuffer, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+GetShaderivRobustANGLE(GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params)
+{
+    EVENT(
+        "(GLuint shader = %d, GLenum pname = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLint* params = 0x%0.8p)",
+        shader, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetShaderivRobustANGLE(context, shader, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        Shader *shaderObject = context->getShader(shader);
+        QueryShaderiv(shaderObject, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterfvRobustANGLE(GLenum target,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLfloat *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLfloat* params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetTexParameterfvRobustANGLE(context, target, pname, bufSize, &numParams,
+                                                  params))
+        {
+            return;
+        }
+
+        Texture *texture = context->getTargetTexture(target);
+        QueryTexParameterfv(texture, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterivRobustANGLE(GLenum target,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLfloat* params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetTexParameterivRobustANGLE(context, target, pname, bufSize, &numParams,
+                                                  params))
+        {
+            return;
+        }
+
+        Texture *texture = context->getTargetTexture(target);
+        QueryTexParameteriv(texture, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetUniformfvRobustANGLE(GLuint program,
+                                                      GLint location,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLfloat *params)
+{
+    EVENT(
+        "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLfloat* params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength = 0;
+        if (!ValidateGetUniformfvRobustANGLE(context, program, location, bufSize, &writeLength,
+                                             params))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+
+        programObject->getUniformfv(location, params);
+        SetRobustLengthParam(length, writeLength);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetUniformivRobustANGLE(GLuint program,
+                                                      GLint location,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLint *params)
+{
+    EVENT(
+        "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint* params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength = 0;
+        if (!ValidateGetUniformivRobustANGLE(context, program, location, bufSize, &writeLength,
+                                             params))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+
+        programObject->getUniformiv(location, params);
+        SetRobustLengthParam(length, writeLength);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfvRobustANGLE(GLuint index,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLfloat *params)
+{
+    EVENT(
+        "(GLuint index = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLfloat* params = 0x%0.8p)",
+        index, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength = 0;
+        if (!ValidateGetVertexAttribfvRobustANGLE(context, index, pname, bufSize, &writeLength,
+                                                  params))
+        {
+            return;
+        }
+
+        context->getVertexAttribfv(index, pname, params);
+        SetRobustLengthParam(length, writeLength);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribivRobustANGLE(GLuint index,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLint *params)
+{
+    EVENT(
+        "(GLuint index = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLint* params = 0x%0.8p)",
+        index, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength = 0;
+        if (!ValidateGetVertexAttribivRobustANGLE(context, index, pname, bufSize, &writeLength,
+                                                  params))
+        {
+            return;
+        }
+
+        context->getVertexAttribiv(index, pname, params);
+        SetRobustLengthParam(length, writeLength);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointervRobustANGLE(GLuint index,
+                                                                 GLenum pname,
+                                                                 GLsizei bufSize,
+                                                                 GLsizei *length,
+                                                                 void **pointer)
+{
+    EVENT(
+        "(GLuint index = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "void** pointer = 0x%0.8p)",
+        index, pname, bufSize, length, pointer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength = 0;
+        if (!ValidateGetVertexAttribPointervRobustANGLE(context, index, pname, bufSize,
+                                                        &writeLength, pointer))
+        {
+            return;
+        }
+
+        context->getVertexAttribPointerv(index, pname, pointer);
+        SetRobustLengthParam(length, writeLength);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY ReadPixelsRobustANGLE(GLint x,
+                                                    GLint y,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    GLsizei bufSize,
+                                                    GLsizei *length,
+                                                    GLsizei *columns,
+                                                    GLsizei *rows,
+                                                    void *pixels)
+{
+    EVENT(
+        "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+        "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLsizei* columns = 0x%0.8p, GLsizei* rows = 0x%0.8p, void* pixels = 0x%0.8p)",
+        x, y, width, height, format, type, bufSize, length, columns, rows, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength  = 0;
+        GLsizei writeColumns = 0;
+        GLsizei writeRows    = 0;
+        if (!ValidateReadPixelsRobustANGLE(context, x, y, width, height, format, type, bufSize,
+                                           &writeLength, &writeColumns, &writeRows, pixels))
+        {
+            return;
+        }
+
+        context->readPixels(x, y, width, height, format, type, pixels);
+
+        SetRobustLengthParam(length, writeLength);
+        SetRobustLengthParam(columns, writeColumns);
+        SetRobustLengthParam(rows, writeRows);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexImage2DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLint internalformat,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLint border,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    GLsizei bufSize,
+                                                    const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+        "GLsizei height = %d, GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, GLsizei "
+        "bufSize = %d, const void* pixels = 0x%0.8p)",
+        target, level, internalformat, width, height, border, format, type, bufSize, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateTexImage2DRobust(context, target, level, internalformat, width, height, border,
+                                      format, type, bufSize, pixels))
+        {
+            return;
+        }
+
+        context->texImage2D(target, level, internalformat, width, height, border, format, type,
+                            pixels);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexParameterfvRobustANGLE(GLenum target,
+                                                        GLenum pname,
+                                                        GLsizei bufSize,
+                                                        const GLfloat *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLfloat* params = "
+        "0x%0.8p)",
+        target, pname, bufSize, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateTexParameterfvRobustANGLE(context, target, pname, bufSize, params))
+        {
+            return;
+        }
+
+        Texture *texture = context->getTargetTexture(target);
+        SetTexParameterfv(texture, pname, params);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexParameterivRobustANGLE(GLenum target,
+                                                        GLenum pname,
+                                                        GLsizei bufSize,
+                                                        const GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLfloat* params = "
+        "0x%0.8p)",
+        target, pname, bufSize, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateTexParameterivRobustANGLE(context, target, pname, bufSize, params))
+        {
+            return;
+        }
+
+        Texture *texture = context->getTargetTexture(target);
+        SetTexParameteriv(texture, pname, params);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexSubImage2DRobustANGLE(GLenum target,
+                                                       GLint level,
+                                                       GLint xoffset,
+                                                       GLint yoffset,
+                                                       GLsizei width,
+                                                       GLsizei height,
+                                                       GLenum format,
+                                                       GLenum type,
+                                                       GLsizei bufSize,
+                                                       const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+        "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
+        "GLsizei bufsize = %d, const void* pixels = 0x%0.8p)",
+        target, level, xoffset, yoffset, width, height, format, type, bufSize, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateTexSubImage2DRobustANGLE(context, target, level, xoffset, yoffset, width,
+                                              height, format, type, bufSize, pixels))
+        {
+            return;
+        }
+
+        context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
+                               pixels);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexImage3DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLint internalformat,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLsizei depth,
+                                                    GLint border,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    GLsizei bufSize,
+                                                    const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+        "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
+        "GLenum type = 0x%X, GLsizei bufsize = %d, const void* pixels = 0x%0.8p)",
+        target, level, internalformat, width, height, depth, border, format, type, bufSize, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateTexImage3DRobustANGLE(context, target, level, internalformat, width, height,
+                                           depth, border, format, type, bufSize, pixels))
+        {
+            return;
+        }
+
+        context->texImage3D(target, level, internalformat, width, height, depth, border, format,
+                            type, pixels);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexSubImage3DRobustANGLE(GLenum target,
+                                                       GLint level,
+                                                       GLint xoffset,
+                                                       GLint yoffset,
+                                                       GLint zoffset,
+                                                       GLsizei width,
+                                                       GLsizei height,
+                                                       GLsizei depth,
+                                                       GLenum format,
+                                                       GLenum type,
+                                                       GLsizei bufSize,
+                                                       const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+        "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+        "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufsize = %d, const void* pixels = "
+        "0x%0.8p)",
+        target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, bufSize,
+        pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateTexSubImage3DRobustANGLE(context, target, level, xoffset, yoffset, zoffset,
+                                              width, height, depth, format, type, bufSize, pixels))
+        {
+            return;
+        }
+
+        context->texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth,
+                               format, type, pixels);
+    }
+}
+
+void GL_APIENTRY CompressedTexImage2DRobustANGLE(GLenum target,
+                                                 GLint level,
+                                                 GLenum internalformat,
+                                                 GLsizei width,
+                                                 GLsizei height,
+                                                 GLint border,
+                                                 GLsizei imageSize,
+                                                 GLsizei dataSize,
+                                                 const GLvoid *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+        "%d, "
+        "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, GLsizei dataSize = %d, "
+        "const GLvoid* data = 0x%0.8p)",
+        target, level, internalformat, width, height, border, imageSize, dataSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCompressedTexImage2DRobustANGLE(context, target, level, internalformat, width,
+                                                     height, border, imageSize, dataSize, data))
+        {
+            return;
+        }
+
+        context->compressedTexImage2D(target, level, internalformat, width, height, border,
+                                      imageSize, data);
+    }
+}
+
+void GL_APIENTRY CompressedTexSubImage2DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLint xoffset,
+                                                    GLint yoffset,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLenum format,
+                                                    GLsizei imageSize,
+                                                    GLsizei dataSize,
+                                                    const GLvoid *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+        "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
+        "GLsizei imageSize = %d, GLsizei dataSize = %d, const GLvoid* data = 0x%0.8p)",
+        target, level, xoffset, yoffset, width, height, format, imageSize, dataSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateCompressedTexSubImage2DRobustANGLE(
+                                              context, target, level, xoffset, yoffset, width,
+                                              height, format, imageSize, dataSize, data))
+        {
+            return;
+        }
+
+        context->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+                                         imageSize, data);
+    }
+}
+
+void GL_APIENTRY CompressedTexImage3DRobustANGLE(GLenum target,
+                                                 GLint level,
+                                                 GLenum internalformat,
+                                                 GLsizei width,
+                                                 GLsizei height,
+                                                 GLsizei depth,
+                                                 GLint border,
+                                                 GLsizei imageSize,
+                                                 GLsizei dataSize,
+                                                 const GLvoid *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+        "%d, "
+        "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
+        "GLsizei dataSize = %d, const GLvoid* data = 0x%0.8p)",
+        target, level, internalformat, width, height, depth, border, imageSize, dataSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateCompressedTexImage3DRobustANGLE(
+                                              context, target, level, internalformat, width, height,
+                                              depth, border, imageSize, dataSize, data))
+        {
+            return;
+        }
+
+        context->compressedTexImage3D(target, level, internalformat, width, height, depth, border,
+                                      imageSize, data);
+    }
+}
+
+void GL_APIENTRY CompressedTexSubImage3DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLint xoffset,
+                                                    GLint yoffset,
+                                                    GLint zoffset,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLsizei depth,
+                                                    GLenum format,
+                                                    GLsizei imageSize,
+                                                    GLsizei dataSize,
+                                                    const GLvoid *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+        "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+        "GLenum format = 0x%X, GLsizei imageSize = %d, GLsizei dataSize = %d, const GLvoid* data = "
+        "0x%0.8p)",
+        target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, dataSize,
+        data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCompressedTexSubImage3DRobustANGLE(context, target, level, xoffset, yoffset,
+                                                        zoffset, width, height, depth, format,
+                                                        imageSize, dataSize, data))
+        {
+            return;
+        }
+
+        context->compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
+                                         depth, format, imageSize, data);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+GetQueryivRobustANGLE(GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint* params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryivRobustANGLE(context, target, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        context->getQueryiv(target, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivRobustANGLE(GLuint id,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLuint *params)
+{
+    EVENT(
+        "(GLuint id = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLint* params = 0x%0.8p)",
+        id, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryObjectuivRobustANGLE(context, id, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        context->getQueryObjectuiv(id, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointervRobustANGLE(GLenum target,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           void **params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X,  GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, void** params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetBufferPointervRobustANGLE(context, target, pname, bufSize, &numParams,
+                                                  params))
+        {
+            return;
+        }
+
+        context->getBufferPointerv(target, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+GetIntegeri_vRobustANGLE(GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint* data = 0x%0.8p)",
+        target, index, bufSize, length, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetIntegeri_vRobustANGLE(context, target, index, bufSize, &numParams, data))
+        {
+            return;
+        }
+
+        context->getIntegeri_v(target, index, data);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetInternalformativRobustANGLE(GLenum target,
+                                                             GLenum internalformat,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize "
+        "= %d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+        target, internalformat, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetInternalFormativRobustANGLE(context, target, internalformat, pname, bufSize,
+                                                    &numParams, params))
+        {
+            return;
+        }
+
+        const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+        QueryInternalFormativ(formatCaps, pname, bufSize, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIivRobustANGLE(GLuint index,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *length,
+                                                            GLint *params)
+{
+    EVENT(
+        "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLint* params = 0x%0.8p)",
+        index, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength = 0;
+        if (!ValidateGetVertexAttribIivRobustANGLE(context, index, pname, bufSize, &writeLength,
+                                                   params))
+        {
+            return;
+        }
+
+        context->getVertexAttribIiv(index, pname, params);
+        SetRobustLengthParam(length, writeLength);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuivRobustANGLE(GLuint index,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLuint *params)
+{
+    EVENT(
+        "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLuint* params = 0x%0.8p)",
+        index, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength = 0;
+        if (!ValidateGetVertexAttribIuivRobustANGLE(context, index, pname, bufSize, &writeLength,
+                                                    params))
+        {
+            return;
+        }
+
+        context->getVertexAttribIuiv(index, pname, params);
+        SetRobustLengthParam(length, writeLength);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetUniformuivRobustANGLE(GLuint program,
+                                                       GLint location,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLuint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLuint* params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength = 0;
+        if (!ValidateGetUniformuivRobustANGLE(context, program, location, bufSize, &writeLength,
+                                              params))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+
+        programObject->getUniformuiv(location, params);
+        SetRobustLengthParam(length, writeLength);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockivRobustANGLE(GLuint program,
+                                                                 GLuint uniformBlockIndex,
+                                                                 GLenum pname,
+                                                                 GLsizei bufSize,
+                                                                 GLsizei *length,
+                                                                 GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLsizei bufsize "
+        "= %d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+        program, uniformBlockIndex, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength = 0;
+        if (!ValidateGetActiveUniformBlockivRobustANGLE(context, program, uniformBlockIndex, pname,
+                                                        bufSize, &writeLength, params))
+        {
+            return;
+        }
+
+        const Program *programObject = context->getProgram(program);
+        QueryActiveUniformBlockiv(programObject, uniformBlockIndex, pname, params);
+        SetRobustLengthParam(length, writeLength);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetInteger64vRobustANGLE(GLenum pname,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLint64 *data)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLint64* params = "
+        "0x%0.8p)",
+        pname, bufSize, length, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLenum nativeType;
+        unsigned int numParams = 0;
+        if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
+        {
+            return;
+        }
+
+        if (nativeType == GL_INT_64_ANGLEX)
+        {
+            context->getInteger64v(pname, data);
+        }
+        else
+        {
+            CastStateValues(context, nativeType, pname, numParams, data);
+        }
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetInteger64i_vRobustANGLE(GLenum target,
+                                                         GLuint index,
+                                                         GLsizei bufSize,
+                                                         GLsizei *length,
+                                                         GLint64 *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint64* data = 0x%0.8p)",
+        target, index, bufSize, length, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetInteger64i_vRobustANGLE(context, target, index, bufSize, &numParams, data))
+        {
+            return;
+        }
+
+        context->getInteger64i_v(target, index, data);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64vRobustANGLE(GLenum target,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint64 *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", target, pname,
+          bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetBufferParameteri64vRobustANGLE(context, target, pname, bufSize, &numParams,
+                                                       params))
+        {
+            return;
+        }
+
+        Buffer *buffer = context->getGLState().getTargetBuffer(target);
+        QueryBufferParameteri64v(buffer, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterivRobustANGLE(GLuint sampler,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            const GLint *param)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLint* params = "
+        "0x%0.8p)",
+        sampler, pname, bufSize, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateSamplerParameterivRobustANGLE(context, sampler, pname, bufSize, param))
+        {
+            return;
+        }
+
+        context->samplerParameteriv(sampler, pname, param);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterfvRobustANGLE(GLuint sampler,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            const GLfloat *param)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLfloat* params = "
+        "0x%0.8p)",
+        sampler, pname, bufSize, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateSamplerParameterfvRobustANGLE(context, sampler, pname, bufSize, param))
+        {
+            return;
+        }
+
+        context->samplerParameterfv(sampler, pname, param);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterivRobustANGLE(GLuint sampler,
+                                                               GLenum pname,
+                                                               GLsizei bufSize,
+                                                               GLsizei *length,
+                                                               GLint *params)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint* params = 0x%0.8p)",
+        sampler, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetSamplerParameterivRobustANGLE(context, sampler, pname, bufSize, &numParams,
+                                                      params))
+        {
+            return;
+        }
+
+        context->getSamplerParameteriv(sampler, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfvRobustANGLE(GLuint sampler,
+                                                               GLenum pname,
+                                                               GLsizei bufSize,
+                                                               GLsizei *length,
+                                                               GLfloat *params)
+{
+    EVENT(
+        "(GLuint sample = %ur, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLfloat* params = 0x%0.8p)",
+        sampler, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetSamplerParameterfvRobustANGLE(context, sampler, pname, bufSize, &numParams,
+                                                      params))
+        {
+            return;
+        }
+
+        context->getSamplerParameterfv(sampler, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferParameterivRobustANGLE(GLenum target,
+                                                                   GLenum pname,
+                                                                   GLsizei bufSize,
+                                                                   GLsizei *length,
+                                                                   GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint* params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetProgramInterfaceivRobustANGLE(GLuint program,
+                                                               GLenum programInterface,
+                                                               GLenum pname,
+                                                               GLsizei bufSize,
+                                                               GLsizei *length,
+                                                               GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLenum programInterface = 0x%X, GLenum pname = 0x%X, GLsizei "
+        "bufsize = %d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+        program, programInterface, pname, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBooleani_vRobustANGLE(GLenum target,
+                                                       GLuint index,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLboolean *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLboolean* data = 0x%0.8p)",
+        target, index, bufSize, length, data);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetBooleani_vRobustANGLE(context, target, index, bufSize, &numParams, data))
+        {
+            return;
+        }
+
+        context->getBooleani_v(target, index, data);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetMultisamplefvRobustANGLE(GLenum pname,
+                                                          GLuint index,
+                                                          GLsizei bufSize,
+                                                          GLsizei *length,
+                                                          GLfloat *val)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLfloat* val = 0x%0.8p)",
+        pname, index, bufSize, length, val);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterivRobustANGLE(GLenum target,
+                                                                GLint level,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, "
+        "GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+        target, level, pname, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfvRobustANGLE(GLenum target,
+                                                                GLint level,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLfloat *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, "
+        "GLsizei* length = 0x%0.8p, GLfloat* params = 0x%0.8p)",
+        target, level, pname, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetPointervRobustANGLERobustANGLE(GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                void **params)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, void **params = "
+        "0x%0.8p)",
+        pname, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY ReadnPixelsRobustANGLE(GLint x,
+                                                     GLint y,
+                                                     GLsizei width,
+                                                     GLsizei height,
+                                                     GLenum format,
+                                                     GLenum type,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLsizei *columns,
+                                                     GLsizei *rows,
+                                                     void *data)
+{
+    EVENT(
+        "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+        "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLsizei* columns = 0x%0.8p, GLsizei* rows = 0x%0.8p, void *data = 0x%0.8p)",
+        x, y, width, height, format, type, bufSize, length, columns, rows, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei writeLength  = 0;
+        GLsizei writeColumns = 0;
+        GLsizei writeRows    = 0;
+        if (!ValidateReadnPixelsRobustANGLE(context, x, y, width, height, format, type, bufSize,
+                                            &writeLength, &writeColumns, &writeRows, data))
+        {
+            return;
+        }
+
+        context->readPixels(x, y, width, height, format, type, data);
+
+        SetRobustLengthParam(length, writeLength);
+        SetRobustLengthParam(columns, writeColumns);
+        SetRobustLengthParam(rows, writeRows);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetnUniformfvRobustANGLE(GLuint program,
+                                                       GLint location,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLfloat *params)
+{
+    EVENT(
+        "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLfloat* params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetnUniformivRobustANGLE(GLuint program,
+                                                       GLint location,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLint *params)
+{
+    EVENT(
+        "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint* params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetnUniformuivRobustANGLE(GLuint program,
+                                                        GLint location,
+                                                        GLsizei bufSize,
+                                                        GLsizei *length,
+                                                        GLuint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLuint* params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexParameterIivRobustANGLE(GLenum target,
+                                                         GLenum pname,
+                                                         GLsizei bufSize,
+                                                         const GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLint *params = "
+        "0x%0.8p)",
+        target, pname, bufSize, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexParameterIuivRobustANGLE(GLenum target,
+                                                          GLenum pname,
+                                                          GLsizei bufSize,
+                                                          const GLuint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLuint *params = "
+        "0x%0.8p)",
+        target, pname, bufSize, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIivRobustANGLE(GLenum target,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *length,
+                                                            GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint *params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIuivRobustANGLE(GLenum target,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLuint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLuint *params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIivRobustANGLE(GLuint sampler,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             const GLint *param)
+{
+    EVENT(
+        "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLint *param = "
+        "0x%0.8p)",
+        sampler, pname, bufSize, param);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIuivRobustANGLE(GLuint sampler,
+                                                              GLenum pname,
+                                                              GLsizei bufSize,
+                                                              const GLuint *param)
+{
+    EVENT(
+        "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLuint *param = "
+        "0x%0.8p)",
+        sampler, pname, bufSize, param);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIivRobustANGLE(GLuint sampler,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint *params)
+{
+    EVENT(
+        "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLint *params = 0x%0.8p)",
+        sampler, pname, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIuivRobustANGLE(GLuint sampler,
+                                                                 GLenum pname,
+                                                                 GLsizei bufSize,
+                                                                 GLsizei *length,
+                                                                 GLuint *params)
+{
+    EVENT(
+        "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+        "0x%0.8p, GLuint *params = 0x%0.8p)",
+        sampler, pname, bufSize, length, params);
+    UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectivRobustANGLE(GLuint id,
+                                                          GLenum pname,
+                                                          GLsizei bufSize,
+                                                          GLsizei *length,
+                                                          GLint *params)
+{
+    EVENT(
+        "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLuint *params = 0x%0.8p)",
+        id, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryObjectivRobustANGLE(context, id, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        context->getQueryObjectiv(id, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjecti64vRobustANGLE(GLuint id,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *length,
+                                                            GLint64 *params)
+{
+    EVENT(
+        "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLint64 *params = 0x%0.8p)",
+        id, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryObjecti64vRobustANGLE(context, id, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        context->getQueryObjecti64v(id, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vRobustANGLE(GLuint id,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLuint64 *params)
+{
+    EVENT(
+        "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+        "GLuint64 *params = 0x%0.8p)",
+        id, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryObjectui64vRobustANGLE(context, id, pname, bufSize, &numParams,
+                                                    params))
+        {
+            return;
+        }
+
+        context->getQueryObjectui64v(id, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
+}
+
+}  // gl
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_ext.h b/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_ext.h
new file mode 100644
index 0000000..f0ca35b
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_gles_2_0_ext.h
@@ -0,0 +1,703 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_2_0_ext.h : Defines the GLES 2.0 extension entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTGLES20EXT_H_
+#define LIBGLESV2_ENTRYPOINTGLES20EXT_H_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <export.h>
+
+namespace gl
+{
+
+// GL_ANGLE_framebuffer_blit
+ANGLE_EXPORT void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0,
+                                                   GLint srcY0,
+                                                   GLint srcX1,
+                                                   GLint srcY1,
+                                                   GLint dstX0,
+                                                   GLint dstY0,
+                                                   GLint dstX1,
+                                                   GLint dstY1,
+                                                   GLbitfield mask,
+                                                   GLenum filter);
+
+// GL_ANGLE_framebuffer_multisample
+ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target,
+                                                                  GLsizei samples,
+                                                                  GLenum internalformat,
+                                                                  GLsizei width,
+                                                                  GLsizei height);
+
+// GL_EXT_discard_framebuffer
+ANGLE_EXPORT void GL_APIENTRY DiscardFramebufferEXT(GLenum target,
+                                                    GLsizei numAttachments,
+                                                    const GLenum *attachments);
+
+// GL_NV_fence
+ANGLE_EXPORT void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint *fences);
+ANGLE_EXPORT void GL_APIENTRY GenFencesNV(GLsizei n, GLuint *fences);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsFenceNV(GLuint fence);
+ANGLE_EXPORT GLboolean GL_APIENTRY TestFenceNV(GLuint fence);
+ANGLE_EXPORT void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY FinishFenceNV(GLuint fence);
+ANGLE_EXPORT void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition);
+
+// GL_ANGLE_translated_shader_source
+ANGLE_EXPORT void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader,
+                                                             GLsizei bufsize,
+                                                             GLsizei *length,
+                                                             GLchar *source);
+
+// GL_EXT_texture_storage
+ANGLE_EXPORT void GL_APIENTRY TexStorage2DEXT(GLenum target,
+                                              GLsizei levels,
+                                              GLenum internalformat,
+                                              GLsizei width,
+                                              GLsizei height);
+
+// GL_EXT_robustness
+ANGLE_EXPORT GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void);
+ANGLE_EXPORT void GL_APIENTRY ReadnPixelsEXT(GLint x,
+                                             GLint y,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLenum format,
+                                             GLenum type,
+                                             GLsizei bufSize,
+                                             void *data);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformfvEXT(GLuint program,
+                                               GLint location,
+                                               GLsizei bufSize,
+                                               float *params);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformivEXT(GLuint program,
+                                               GLint location,
+                                               GLsizei bufSize,
+                                               GLint *params);
+
+// GL_EXT_occlusion_query_boolean
+ANGLE_EXPORT void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint *ids);
+ANGLE_EXPORT void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsQueryEXT(GLuint id);
+ANGLE_EXPORT void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint id);
+ANGLE_EXPORT void GL_APIENTRY EndQueryEXT(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params);
+
+// GL_EXT_disjoint_timer_query
+ANGLE_EXPORT void GL_APIENTRY QueryCounterEXT(GLuint id, GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectivEXT(GLuint id, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 *params);
+
+// GL_EXT_draw_buffers
+ANGLE_EXPORT void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs);
+
+// GL_ANGLE_instanced_arrays
+ANGLE_EXPORT void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode,
+                                                       GLint first,
+                                                       GLsizei count,
+                                                       GLsizei primcount);
+ANGLE_EXPORT void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode,
+                                                         GLsizei count,
+                                                         GLenum type,
+                                                         const void *indices,
+                                                         GLsizei primcount);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor);
+
+// GL_OES_get_program_binary
+ANGLE_EXPORT void GL_APIENTRY GetProgramBinaryOES(GLuint program,
+                                                  GLsizei bufSize,
+                                                  GLsizei *length,
+                                                  GLenum *binaryFormat,
+                                                  void *binary);
+ANGLE_EXPORT void GL_APIENTRY ProgramBinaryOES(GLuint program,
+                                               GLenum binaryFormat,
+                                               const void *binary,
+                                               GLint length);
+
+// GL_OES_mapbuffer
+ANGLE_EXPORT void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access);
+ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBufferOES(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void **params);
+
+// GL_EXT_map_buffer_range
+ANGLE_EXPORT void *GL_APIENTRY MapBufferRangeEXT(GLenum target,
+                                                 GLintptr offset,
+                                                 GLsizeiptr length,
+                                                 GLbitfield access);
+ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target,
+                                                        GLintptr offset,
+                                                        GLsizeiptr length);
+
+// GL_EXT_debug_marker
+ANGLE_EXPORT void GL_APIENTRY InsertEventMarkerEXT(GLsizei length, const char *marker);
+ANGLE_EXPORT void GL_APIENTRY PushGroupMarkerEXT(GLsizei length, const char *marker);
+ANGLE_EXPORT void GL_APIENTRY PopGroupMarkerEXT();
+
+// GL_OES_EGL_image
+ANGLE_EXPORT void GL_APIENTRY EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
+ANGLE_EXPORT void GL_APIENTRY EGLImageTargetRenderbufferStorageOES(GLenum target,
+                                                                   GLeglImageOES image);
+
+// GL_OES_vertex_array_object
+ANGLE_EXPORT void GL_APIENTRY BindVertexArrayOES(GLuint array);
+ANGLE_EXPORT void GL_APIENTRY DeleteVertexArraysOES(GLsizei n, const GLuint *arrays);
+ANGLE_EXPORT void GL_APIENTRY GenVertexArraysOES(GLsizei n, GLuint *arrays);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsVertexArrayOES(GLuint array);
+
+// GL_KHR_debug
+ANGLE_EXPORT void GL_APIENTRY DebugMessageControlKHR(GLenum source,
+                                                     GLenum type,
+                                                     GLenum severity,
+                                                     GLsizei count,
+                                                     const GLuint *ids,
+                                                     GLboolean enabled);
+ANGLE_EXPORT void GL_APIENTRY DebugMessageInsertKHR(GLenum source,
+                                                    GLenum type,
+                                                    GLuint id,
+                                                    GLenum severity,
+                                                    GLsizei length,
+                                                    const GLchar *buf);
+ANGLE_EXPORT void GL_APIENTRY DebugMessageCallbackKHR(GLDEBUGPROCKHR callback,
+                                                      const void *userParam);
+ANGLE_EXPORT GLuint GL_APIENTRY GetDebugMessageLogKHR(GLuint count,
+                                                      GLsizei bufSize,
+                                                      GLenum *sources,
+                                                      GLenum *types,
+                                                      GLuint *ids,
+                                                      GLenum *severities,
+                                                      GLsizei *lengths,
+                                                      GLchar *messageLog);
+ANGLE_EXPORT void GL_APIENTRY PushDebugGroupKHR(GLenum source,
+                                                GLuint id,
+                                                GLsizei length,
+                                                const GLchar *message);
+ANGLE_EXPORT void GL_APIENTRY PopDebugGroupKHR(void);
+ANGLE_EXPORT void GL_APIENTRY ObjectLabelKHR(GLenum identifier,
+                                             GLuint name,
+                                             GLsizei length,
+                                             const GLchar *label);
+ANGLE_EXPORT void GL_APIENTRY
+GetObjectLabelKHR(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+ANGLE_EXPORT void GL_APIENTRY ObjectPtrLabelKHR(const void *ptr,
+                                                GLsizei length,
+                                                const GLchar *label);
+ANGLE_EXPORT void GL_APIENTRY GetObjectPtrLabelKHR(const void *ptr,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLchar *label);
+ANGLE_EXPORT void GL_APIENTRY GetPointervKHR(GLenum pname, void **params);
+
+// GL_CHROMIUM_bind_uniform_location
+ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
+                                                          GLint location,
+                                                          const GLchar *name);
+
+// GL_CHROMIUM_framebuffer_mixed_samples
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix);
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode);
+
+ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components);
+
+// GL_CHROMIUM_path_rendering
+ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei chromium);
+ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path);
+ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
+                                                   GLsizei numCommands,
+                                                   const GLubyte *commands,
+                                                   GLsizei numCoords,
+                                                   GLenum coordType,
+                                                   const void *coords);
+ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
+ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
+ANGLE_EXPORT void GL_APIENTRY GetPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY GetPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint *value);
+ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
+                                                               GLenum fillMode,
+                                                               GLuint mask,
+                                                               GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
+                                                                 GLint reference,
+                                                                 GLuint mask,
+                                                                 GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                             GLenum pathNameType,
+                                                             const void *paths,
+                                                             GLuint pathBase,
+                                                             GLenum coverMode,
+                                                             GLenum transformType,
+                                                             const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                               GLenum pathNameType,
+                                                               const void *paths,
+                                                               GLuint pathBase,
+                                                               GLenum coverMode,
+                                                               GLenum transformType,
+                                                               const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                               GLenum pathNameType,
+                                                               const void *paths,
+                                                               GLuint pathBAse,
+                                                               GLenum fillMode,
+                                                               GLuint mask,
+                                                               GLenum transformType,
+                                                               const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                                 GLenum pathNameType,
+                                                                 const void *paths,
+                                                                 GLuint pathBase,
+                                                                 GLint reference,
+                                                                 GLuint mask,
+                                                                 GLenum transformType,
+                                                                 const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                          GLenum pathNameType,
+                                          const void *paths,
+                                          GLuint pathBase,
+                                          GLenum fillMode,
+                                          GLuint mask,
+                                          GLenum coverMode,
+                                          GLenum transformType,
+                                          const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                            GLenum pathNameType,
+                                            const void *paths,
+                                            GLuint pathBase,
+                                            GLint reference,
+                                            GLuint mask,
+                                            GLenum coverMode,
+                                            GLenum transformType,
+                                            const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint program,
+                                                                GLint location,
+                                                                const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+                                                                  GLint location,
+                                                                  GLenum genMode,
+                                                                  GLint components,
+                                                                  const GLfloat *coeffs);
+
+// GL_CHROMIUM_copy_texture
+ANGLE_EXPORT void GL_APIENTRY CopyTextureCHROMIUM(GLuint sourceId,
+                                                  GLint sourceLevel,
+                                                  GLenum destTarget,
+                                                  GLuint destId,
+                                                  GLint destLevel,
+                                                  GLint internalFormat,
+                                                  GLenum destType,
+                                                  GLboolean unpackFlipY,
+                                                  GLboolean unpackPremultiplyAlpha,
+                                                  GLboolean unpackUnmultiplyAlpha);
+
+ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
+                                                     GLint sourceLevel,
+                                                     GLenum destTarget,
+                                                     GLuint destId,
+                                                     GLint destLevel,
+                                                     GLint xoffset,
+                                                     GLint yoffset,
+                                                     GLint x,
+                                                     GLint y,
+                                                     GLsizei width,
+                                                     GLsizei height,
+                                                     GLboolean unpackFlipY,
+                                                     GLboolean unpackPremultiplyAlpha,
+                                                     GLboolean unpackUnmultiplyAlpha);
+
+// GL_CHROMIUM_copy_compressed_texture
+ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
+
+// GL_ANGLE_request_extension
+ANGLE_EXPORT void GL_APIENTRY RequestExtensionANGLE(const GLchar *name);
+
+// GL_ANGLE_robust_client_memory
+ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLboolean *data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameterivRobustANGLE(GLenum target,
+                                                              GLenum pname,
+                                                              GLsizei bufSize,
+                                                              GLsizei *length,
+                                                              GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetFloatvRobustANGLE(GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLfloat *data);
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameterivRobustANGLE(GLenum target,
+                                                                             GLenum attachment,
+                                                                             GLenum pname,
+                                                                             GLsizei bufSize,
+                                                                             GLsizei *length,
+                                                                             GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetIntegervRobustANGLE(GLenum pname,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLint *data);
+ANGLE_EXPORT void GL_APIENTRY GetProgramivRobustANGLE(GLuint program,
+                                                      GLenum pname,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameterivRobustANGLE(GLenum target,
+                                                                    GLenum pname,
+                                                                    GLsizei bufSize,
+                                                                    GLsizei *length,
+                                                                    GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetShaderivRobustANGLE(GLuint shader,
+                                                     GLenum pname,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterfvRobustANGLE(GLenum target,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterivRobustANGLE(GLenum target,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformfvRobustANGLE(GLuint program,
+                                                      GLint location,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformivRobustANGLE(GLuint program,
+                                                      GLint location,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfvRobustANGLE(GLuint index,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribivRobustANGLE(GLuint index,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointervRobustANGLE(GLuint index,
+                                                                 GLenum pname,
+                                                                 GLsizei bufSize,
+                                                                 GLsizei *length,
+                                                                 void **pointer);
+ANGLE_EXPORT void GL_APIENTRY ReadPixelsRobustANGLE(GLint x,
+                                                    GLint y,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    GLsizei bufSize,
+                                                    GLsizei *length,
+                                                    GLsizei *columns,
+                                                    GLsizei *rows,
+                                                    void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexImage2DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLint internalformat,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLint border,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    GLsizei bufSize,
+                                                    const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexParameterfvRobustANGLE(GLenum target,
+                                                        GLenum pname,
+                                                        GLsizei bufSize,
+                                                        const GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameterivRobustANGLE(GLenum target,
+                                                        GLenum pname,
+                                                        GLsizei bufSize,
+                                                        const GLint *params);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage2DRobustANGLE(GLenum target,
+                                                       GLint level,
+                                                       GLint xoffset,
+                                                       GLint yoffset,
+                                                       GLsizei width,
+                                                       GLsizei height,
+                                                       GLenum format,
+                                                       GLenum type,
+                                                       GLsizei bufSize,
+                                                       const void *pixels);
+
+ANGLE_EXPORT void GL_APIENTRY TexImage3DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLint internalformat,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLsizei depth,
+                                                    GLint border,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    GLsizei bufSize,
+                                                    const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage3DRobustANGLE(GLenum target,
+                                                       GLint level,
+                                                       GLint xoffset,
+                                                       GLint yoffset,
+                                                       GLint zoffset,
+                                                       GLsizei width,
+                                                       GLsizei height,
+                                                       GLsizei depth,
+                                                       GLenum format,
+                                                       GLenum type,
+                                                       GLsizei bufSize,
+                                                       const void *pixels);
+
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2DRobustANGLE(GLenum target,
+                                                              GLint level,
+                                                              GLenum internalformat,
+                                                              GLsizei width,
+                                                              GLsizei height,
+                                                              GLint border,
+                                                              GLsizei imageSize,
+                                                              GLsizei dataSize,
+                                                              const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2DRobustANGLE(GLenum target,
+                                                                 GLint level,
+                                                                 GLint xoffset,
+                                                                 GLint yoffset,
+                                                                 GLsizei width,
+                                                                 GLsizei height,
+                                                                 GLenum format,
+                                                                 GLsizei imageSize,
+                                                                 GLsizei dataSize,
+                                                                 const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3DRobustANGLE(GLenum target,
+                                                              GLint level,
+                                                              GLenum internalformat,
+                                                              GLsizei width,
+                                                              GLsizei height,
+                                                              GLsizei depth,
+                                                              GLint border,
+                                                              GLsizei imageSize,
+                                                              GLsizei dataSize,
+                                                              const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3DRobustANGLE(GLenum target,
+                                                                 GLint level,
+                                                                 GLint xoffset,
+                                                                 GLint yoffset,
+                                                                 GLint zoffset,
+                                                                 GLsizei width,
+                                                                 GLsizei height,
+                                                                 GLsizei depth,
+                                                                 GLenum format,
+                                                                 GLsizei imageSize,
+                                                                 GLsizei dataSize,
+                                                                 const GLvoid *data);
+
+ANGLE_EXPORT void GL_APIENTRY
+GetQueryivRobustANGLE(GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivRobustANGLE(GLuint id,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointervRobustANGLE(GLenum target,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           void **params);
+ANGLE_EXPORT void GL_APIENTRY GetIntegeri_vRobustANGLE(GLenum target,
+                                                       GLuint index,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLint *data);
+ANGLE_EXPORT void GL_APIENTRY GetInternalformativRobustANGLE(GLenum target,
+                                                             GLenum internalformat,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIivRobustANGLE(GLuint index,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *length,
+                                                            GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuivRobustANGLE(GLuint index,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformuivRobustANGLE(GLuint program,
+                                                       GLint location,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockivRobustANGLE(GLuint program,
+                                                                 GLuint uniformBlockIndex,
+                                                                 GLenum pname,
+                                                                 GLsizei bufSize,
+                                                                 GLsizei *length,
+                                                                 GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64vRobustANGLE(GLenum pname,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLint64 *data);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64i_vRobustANGLE(GLenum target,
+                                                         GLuint index,
+                                                         GLsizei bufSize,
+                                                         GLsizei *length,
+                                                         GLint64 *data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64vRobustANGLE(GLenum target,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterivRobustANGLE(GLuint sampler,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            const GLint *param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterfvRobustANGLE(GLuint sampler,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            const GLfloat *param);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterivRobustANGLE(GLuint sampler,
+                                                               GLenum pname,
+                                                               GLsizei bufSize,
+                                                               GLsizei *length,
+                                                               GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfvRobustANGLE(GLuint sampler,
+                                                               GLenum pname,
+                                                               GLsizei bufSize,
+                                                               GLsizei *length,
+                                                               GLfloat *params);
+
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferParameterivRobustANGLE(GLenum target,
+                                                                   GLenum pname,
+                                                                   GLsizei bufSize,
+                                                                   GLsizei *length,
+                                                                   GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetProgramInterfaceivRobustANGLE(GLuint program,
+                                                               GLenum programInterface,
+                                                               GLenum pname,
+                                                               GLsizei bufSize,
+                                                               GLsizei *length,
+                                                               GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetBooleani_vRobustANGLE(GLenum target,
+                                                       GLuint index,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLboolean *data);
+ANGLE_EXPORT void GL_APIENTRY GetMultisamplefvRobustANGLE(GLenum pname,
+                                                          GLuint index,
+                                                          GLsizei bufSize,
+                                                          GLsizei *length,
+                                                          GLfloat *val);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterivRobustANGLE(GLenum target,
+                                                                GLint level,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfvRobustANGLE(GLenum target,
+                                                                GLint level,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLfloat *params);
+
+ANGLE_EXPORT void GL_APIENTRY GetPointervRobustANGLERobustANGLE(GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                void **params);
+ANGLE_EXPORT void GL_APIENTRY ReadnPixelsRobustANGLE(GLint x,
+                                                     GLint y,
+                                                     GLsizei width,
+                                                     GLsizei height,
+                                                     GLenum format,
+                                                     GLenum type,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLsizei *columns,
+                                                     GLsizei *rows,
+                                                     void *data);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformfvRobustANGLE(GLuint program,
+                                                       GLint location,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformivRobustANGLE(GLuint program,
+                                                       GLint location,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformuivRobustANGLE(GLuint program,
+                                                        GLint location,
+                                                        GLsizei bufSize,
+                                                        GLsizei *length,
+                                                        GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameterIivRobustANGLE(GLenum target,
+                                                         GLenum pname,
+                                                         GLsizei bufSize,
+                                                         const GLint *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameterIuivRobustANGLE(GLenum target,
+                                                          GLenum pname,
+                                                          GLsizei bufSize,
+                                                          const GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIivRobustANGLE(GLenum target,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *length,
+                                                            GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIuivRobustANGLE(GLenum target,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIivRobustANGLE(GLuint sampler,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             const GLint *param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIuivRobustANGLE(GLuint sampler,
+                                                              GLenum pname,
+                                                              GLsizei bufSize,
+                                                              const GLuint *param);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIivRobustANGLE(GLuint sampler,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIuivRobustANGLE(GLuint sampler,
+                                                                 GLenum pname,
+                                                                 GLsizei bufSize,
+                                                                 GLsizei *length,
+                                                                 GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectivRobustANGLE(GLuint id,
+                                                          GLenum pname,
+                                                          GLsizei bufSize,
+                                                          GLsizei *length,
+                                                          GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjecti64vRobustANGLE(GLuint id,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *length,
+                                                            GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vRobustANGLE(GLuint id,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLuint64 *params);
+
+}  // namespace gl
+
+#endif  // LIBGLESV2_ENTRYPOINTGLES20EXT_H_
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_gles_3_0.cpp b/src/third_party/angle/src/libGLESv2/entry_points_gles_3_0.cpp
new file mode 100644
index 0000000..8eb2769
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_gles_3_0.cpp
@@ -0,0 +1,2525 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_3_0.cpp : Implements the GLES 3.0 entry points.
+
+#include "libGLESv2/entry_points_gles_3_0.h"
+#include "libGLESv2/entry_points_gles_2_0_ext.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES3.h"
+
+#include "common/debug.h"
+
+namespace gl
+{
+
+void GL_APIENTRY ReadBuffer(GLenum mode)
+{
+    EVENT("(GLenum mode = 0x%X)", mode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateReadBuffer(context, mode))
+        {
+            return;
+        }
+
+        context->readBuffer(mode);
+    }
+}
+
+void GL_APIENTRY DrawRangeElements(GLenum mode,
+                                   GLuint start,
+                                   GLuint end,
+                                   GLsizei count,
+                                   GLenum type,
+                                   const void *indices)
+{
+    EVENT(
+        "(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type "
+        "= 0x%X, "
+        "const void* indices = 0x%0.8p)",
+        mode, start, end, count, type, indices);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DrawRangeElements>(mode, start, end, count, type,
+                                                             indices);
+
+        if (!context->skipValidation() &&
+            !ValidateDrawRangeElements(context, mode, start, end, count, type, indices))
+        {
+            return;
+        }
+
+        context->drawRangeElements(mode, start, end, count, type, indices);
+    }
+}
+
+void GL_APIENTRY TexImage3D(GLenum target,
+                            GLint level,
+                            GLint internalformat,
+                            GLsizei width,
+                            GLsizei height,
+                            GLsizei depth,
+                            GLint border,
+                            GLenum format,
+                            GLenum type,
+                            const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+        "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
+        "GLenum type = 0x%X, const void* pixels = 0x%0.8p)",
+        target, level, internalformat, width, height, depth, border, format, type, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateTexImage3D(context, target, level, internalformat, width, height, depth,
+                                border, format, type, pixels))
+        {
+            return;
+        }
+
+        context->texImage3D(target, level, internalformat, width, height, depth, border, format,
+                            type, pixels);
+    }
+}
+
+void GL_APIENTRY TexSubImage3D(GLenum target,
+                               GLint level,
+                               GLint xoffset,
+                               GLint yoffset,
+                               GLint zoffset,
+                               GLsizei width,
+                               GLsizei height,
+                               GLsizei depth,
+                               GLenum format,
+                               GLenum type,
+                               const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+        "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+        "GLenum format = 0x%X, GLenum type = 0x%X, const void* pixels = 0x%0.8p)",
+        target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width, height,
+                                   depth, format, type, pixels))
+        {
+            return;
+        }
+
+        context->texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth,
+                               format, type, pixels);
+    }
+}
+
+void GL_APIENTRY CopyTexSubImage3D(GLenum target,
+                                   GLint level,
+                                   GLint xoffset,
+                                   GLint yoffset,
+                                   GLint zoffset,
+                                   GLint x,
+                                   GLint y,
+                                   GLsizei width,
+                                   GLsizei height)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+        "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+        target, level, xoffset, yoffset, zoffset, x, y, width, height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCopyTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, x, y,
+                                       width, height))
+        {
+            return;
+        }
+
+        context->copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
+    }
+}
+
+void GL_APIENTRY CompressedTexImage3D(GLenum target,
+                                      GLint level,
+                                      GLenum internalformat,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLsizei depth,
+                                      GLint border,
+                                      GLsizei imageSize,
+                                      const void *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+        "%d, "
+        "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
+        "const void* data = 0x%0.8p)",
+        target, level, internalformat, width, height, depth, border, imageSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
+                                          depth, border, imageSize, data))
+        {
+            return;
+        }
+
+        context->compressedTexImage3D(target, level, internalformat, width, height, depth, border,
+                                      imageSize, data);
+    }
+}
+
+void GL_APIENTRY CompressedTexSubImage3D(GLenum target,
+                                         GLint level,
+                                         GLint xoffset,
+                                         GLint yoffset,
+                                         GLint zoffset,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLsizei depth,
+                                         GLenum format,
+                                         GLsizei imageSize,
+                                         const void *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+        "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+        "GLenum format = 0x%X, GLsizei imageSize = %d, const void* data = 0x%0.8p)",
+        target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset,
+                                             width, height, depth, format, imageSize, data))
+        {
+            return;
+        }
+
+        context->compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
+                                         depth, format, imageSize, data);
+    }
+}
+
+void GL_APIENTRY GenQueries(GLsizei n, GLuint *ids)
+{
+    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGenQueries(context, n, ids))
+        {
+            return;
+        }
+
+        for (GLsizei i = 0; i < n; i++)
+        {
+            ids[i] = context->createQuery();
+        }
+    }
+}
+
+void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint *ids)
+{
+    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateDeleteQueries(context, n, ids))
+        {
+            return;
+        }
+
+        for (int i = 0; i < n; i++)
+        {
+            context->deleteQuery(ids[i]);
+        }
+    }
+}
+
+GLboolean GL_APIENTRY IsQuery(GLuint id)
+{
+    EVENT("(GLuint id = %u)", id);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return GL_FALSE;
+        }
+
+        return (context->getQuery(id, false, GL_NONE) != nullptr) ? GL_TRUE : GL_FALSE;
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY BeginQuery(GLenum target, GLuint id)
+{
+    EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateBeginQuery(context, target, id))
+        {
+            return;
+        }
+
+        Error error = context->beginQuery(target, id);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY EndQuery(GLenum target)
+{
+    EVENT("(GLenum target = 0x%X)", target);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateEndQuery(context, target))
+        {
+            return;
+        }
+
+        Error error = context->endQuery(target);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetQueryiv(context, target, pname, params))
+        {
+            return;
+        }
+
+        context->getQueryiv(target, pname, params);
+    }
+}
+
+void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
+{
+    EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetQueryObjectuiv(context, id, pname, params))
+        {
+            return;
+        }
+
+        context->getQueryObjectuiv(id, pname, params);
+    }
+}
+
+GLboolean GL_APIENTRY UnmapBuffer(GLenum target)
+{
+    EVENT("(GLenum target = 0x%X)", target);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateUnmapBuffer(context, target))
+        {
+            return GL_FALSE;
+        }
+
+        return context->unmapBuffer(target);
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, void **params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, void** params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetBufferPointerv(context, target, pname, params))
+        {
+            return;
+        }
+
+        context->getBufferPointerv(target, pname, params);
+    }
+}
+
+void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum *bufs)
+{
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateDrawBuffers(context, n, bufs))
+        {
+            return;
+        }
+
+        context->drawBuffers(n, bufs);
+    }
+}
+
+void GL_APIENTRY UniformMatrix2x3fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    EVENT(
+        "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value "
+        "= 0x%0.8p)",
+        location, count, transpose, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniformMatrix2x3fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY UniformMatrix3x2fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    EVENT(
+        "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value "
+        "= 0x%0.8p)",
+        location, count, transpose, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniformMatrix3x2fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY UniformMatrix2x4fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    EVENT(
+        "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value "
+        "= 0x%0.8p)",
+        location, count, transpose, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniformMatrix2x4fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY UniformMatrix4x2fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    EVENT(
+        "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value "
+        "= 0x%0.8p)",
+        location, count, transpose, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniformMatrix4x2fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY UniformMatrix3x4fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    EVENT(
+        "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value "
+        "= 0x%0.8p)",
+        location, count, transpose, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniformMatrix3x4fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY UniformMatrix4x3fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    EVENT(
+        "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value "
+        "= 0x%0.8p)",
+        location, count, transpose, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniformMatrix4x3fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY BlitFramebuffer(GLint srcX0,
+                                 GLint srcY0,
+                                 GLint srcX1,
+                                 GLint srcY1,
+                                 GLint dstX0,
+                                 GLint dstY0,
+                                 GLint dstX1,
+                                 GLint dstY1,
+                                 GLbitfield mask,
+                                 GLenum filter)
+{
+    EVENT(
+        "(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = "
+        "%d, "
+        "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum "
+        "filter = 0x%X)",
+        srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateBlitFramebuffer(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1,
+                                     dstY1, mask, filter))
+        {
+            return;
+        }
+
+        context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
+                                 filter);
+    }
+}
+
+void GL_APIENTRY RenderbufferStorageMultisample(GLenum target,
+                                                GLsizei samples,
+                                                GLenum internalformat,
+                                                GLsizei width,
+                                                GLsizei height)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width "
+        "= %d, GLsizei height = %d)",
+        target, samples, internalformat, width, height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateRenderbufferStorageMultisample(context, target, samples, internalformat, width,
+                                                    height))
+        {
+            return;
+        }
+
+        context->renderbufferStorageMultisample(target, samples, internalformat, width, height);
+    }
+}
+
+void GL_APIENTRY
+FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, "
+        "GLint layer = %d)",
+        target, attachment, texture, level, layer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateFramebufferTextureLayer(context, target, attachment, texture, level, layer))
+        {
+            return;
+        }
+
+        context->framebufferTextureLayer(target, attachment, texture, level, layer);
+    }
+}
+
+void *GL_APIENTRY MapBufferRange(GLenum target,
+                                 GLintptr offset,
+                                 GLsizeiptr length,
+                                 GLbitfield access)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = "
+        "0x%X)",
+        target, offset, length, access);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateMapBufferRange(context, target, offset, length, access))
+        {
+            return nullptr;
+        }
+
+        return context->mapBufferRange(target, offset, length, access);
+    }
+
+    return nullptr;
+}
+
+void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+    EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset,
+          length);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateFlushMappedBufferRange(context, target, offset, length))
+        {
+            return;
+        }
+
+        context->flushMappedBufferRange(target, offset, length);
+    }
+}
+
+void GL_APIENTRY BindVertexArray(GLuint array)
+{
+    EVENT("(GLuint array = %u)", array);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateBindVertexArray(context, array))
+        {
+            return;
+        }
+
+        context->bindVertexArray(array);
+    }
+}
+
+void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint *arrays)
+{
+    EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateDeleteVertexArrays(context, n, arrays))
+        {
+            return;
+        }
+
+        for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+        {
+            if (arrays[arrayIndex] != 0)
+            {
+                context->deleteVertexArray(arrays[arrayIndex]);
+            }
+        }
+    }
+}
+
+void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint *arrays)
+{
+    EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGenVertexArrays(context, n, arrays))
+        {
+            return;
+        }
+
+        for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+        {
+            arrays[arrayIndex] = context->createVertexArray();
+        }
+    }
+}
+
+GLboolean GL_APIENTRY IsVertexArray(GLuint array)
+{
+    EVENT("(GLuint array = %u)", array);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateIsVertexArray(context))
+        {
+            return GL_FALSE;
+        }
+
+        if (array == 0)
+        {
+            return GL_FALSE;
+        }
+
+        VertexArray *vao = context->getVertexArray(array);
+
+        return (vao != nullptr ? GL_TRUE : GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint *data)
+{
+    EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)", target, index, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGetIntegeri_v(context, target, index, data))
+        {
+            return;
+        }
+        context->getIntegeri_v(target, index, data);
+    }
+}
+
+void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode)
+{
+    EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateBeginTransformFeedback(context, primitiveMode))
+        {
+            return;
+        }
+
+        context->beginTransformFeedback(primitiveMode);
+    }
+}
+
+void GL_APIENTRY EndTransformFeedback(void)
+{
+    EVENT("(void)");
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+        ASSERT(transformFeedback != nullptr);
+
+        if (!transformFeedback->isActive())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        transformFeedback->end(context);
+    }
+}
+
+void GL_APIENTRY
+BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, "
+        "GLsizeiptr size = %d)",
+        target, index, buffer, offset, size);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateBindBufferRange(context, target, index, buffer, offset, size))
+        {
+            return;
+        }
+        context->bindBufferRange(target, index, buffer, offset, size);
+    }
+}
+
+void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
+{
+    EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", target, index, buffer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateBindBufferBase(context, target, index, buffer))
+        {
+            return;
+        }
+        context->bindBufferBase(target, index, buffer);
+    }
+}
+
+void GL_APIENTRY TransformFeedbackVaryings(GLuint program,
+                                           GLsizei count,
+                                           const GLchar *const *varyings,
+                                           GLenum bufferMode)
+{
+    EVENT(
+        "(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum "
+        "bufferMode = 0x%X)",
+        program, count, varyings, bufferMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (count < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        const Caps &caps = context->getCaps();
+        switch (bufferMode)
+        {
+            case GL_INTERLEAVED_ATTRIBS:
+                break;
+            case GL_SEPARATE_ATTRIBS:
+                if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
+                {
+                    context->handleError(Error(GL_INVALID_VALUE));
+                    return;
+                }
+                break;
+            default:
+                context->handleError(Error(GL_INVALID_ENUM));
+                return;
+        }
+
+        Program *programObject = GetValidProgram(context, program);
+        if (!programObject)
+        {
+            return;
+        }
+
+        programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
+    }
+}
+
+void GL_APIENTRY GetTransformFeedbackVarying(GLuint program,
+                                             GLuint index,
+                                             GLsizei bufSize,
+                                             GLsizei *length,
+                                             GLsizei *size,
+                                             GLenum *type,
+                                             GLchar *name)
+{
+    EVENT(
+        "(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, "
+        "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
+        program, index, bufSize, length, size, type, name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (bufSize < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        Program *programObject = GetValidProgram(context, program);
+        if (!programObject)
+        {
+            return;
+        }
+
+        if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
+    }
+}
+
+void GL_APIENTRY
+VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
+{
+    EVENT(
+        "(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const void* "
+        "pointer = 0x%0.8p)",
+        index, size, type, stride, pointer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateVertexAttribIPointer(context, index, size, type, stride, pointer))
+        {
+            return;
+        }
+
+        context->vertexAttribIPointer(index, size, type, stride, pointer);
+    }
+}
+
+void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
+{
+    EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetVertexAttribIiv(context, index, pname, params))
+        {
+            return;
+        }
+
+        context->getVertexAttribIiv(index, pname, params);
+    }
+}
+
+void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
+{
+    EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)", index, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetVertexAttribIuiv(context, index, pname, params))
+        {
+            return;
+        }
+
+        context->getVertexAttribIuiv(index, pname, params);
+    }
+}
+
+void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+    EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", index, x,
+          y, z, w);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (index >= MAX_VERTEX_ATTRIBS)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        context->vertexAttribI4i(index, x, y, z, w);
+    }
+}
+
+void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+    EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", index,
+          x, y, z, w);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (index >= MAX_VERTEX_ATTRIBS)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        context->vertexAttribI4ui(index, x, y, z, w);
+    }
+}
+
+void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint *v)
+{
+    EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (index >= MAX_VERTEX_ATTRIBS)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        context->vertexAttribI4iv(index, v);
+    }
+}
+
+void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint *v)
+{
+    EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (index >= MAX_VERTEX_ATTRIBS)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        context->vertexAttribI4uiv(index, v);
+    }
+}
+
+void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint *params)
+{
+    EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)", program, location,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetUniformuiv(context, program, location, params))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+
+        programObject->getUniformuiv(location, params);
+    }
+}
+
+GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name)
+{
+    EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", program, name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return -1;
+        }
+
+        if (program == 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return -1;
+        }
+
+        Program *programObject = context->getProgram(program);
+
+        if (!programObject || !programObject->isLinked())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return -1;
+        }
+
+        return programObject->getFragDataLocation(name);
+    }
+
+    return 0;
+}
+
+void GL_APIENTRY Uniform1ui(GLint location, GLuint v0)
+{
+    Uniform1uiv(location, 1, &v0);
+}
+
+void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1)
+{
+    const GLuint xy[] = {v0, v1};
+    Uniform2uiv(location, 1, xy);
+}
+
+void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+    const GLuint xyz[] = {v0, v1, v2};
+    Uniform3uiv(location, 1, xyz);
+}
+
+void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+    const GLuint xyzw[] = {v0, v1, v2, v3};
+    Uniform4uiv(location, 1, xyzw);
+}
+
+void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniform1uiv(location, count, value);
+    }
+}
+
+void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniform2uiv(location, count, value);
+    }
+}
+
+void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)", location, count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniform3uiv(location, count, value);
+    }
+}
+
+void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", location,
+          count, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count))
+        {
+            return;
+        }
+
+        Program *program = context->getGLState().getProgram();
+        program->setUniform4uiv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
+{
+    EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)", buffer,
+          drawbuffer, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateClearBufferiv(context, buffer, drawbuffer, value))
+        {
+            return;
+        }
+
+        context->clearBufferiv(buffer, drawbuffer, value);
+    }
+}
+
+void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
+{
+    EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)", buffer,
+          drawbuffer, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateClearBufferuiv(context, buffer, drawbuffer, value))
+        {
+            return;
+        }
+
+        context->clearBufferuiv(buffer, drawbuffer, value);
+    }
+}
+
+void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
+{
+    EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)", buffer,
+          drawbuffer, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateClearBufferfv(context, buffer, drawbuffer, value))
+        {
+            return;
+        }
+
+        context->clearBufferfv(buffer, drawbuffer, value);
+    }
+}
+
+void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+    EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)",
+          buffer, drawbuffer, depth, stencil);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateClearBufferfi(context, buffer, drawbuffer, depth, stencil))
+        {
+            return;
+        }
+
+        context->clearBufferfi(buffer, drawbuffer, depth, stencil);
+    }
+}
+
+const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index)
+{
+    EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGetStringi(context, name, index))
+        {
+            return nullptr;
+        }
+
+        return context->getStringi(name, index);
+    }
+
+    return nullptr;
+}
+
+void GL_APIENTRY CopyBufferSubData(GLenum readTarget,
+                                   GLenum writeTarget,
+                                   GLintptr readOffset,
+                                   GLintptr writeOffset,
+                                   GLsizeiptr size)
+{
+    EVENT(
+        "(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr "
+        "writeOffset = %d, GLsizeiptr size = %d)",
+        readTarget, writeTarget, readOffset, writeOffset, size);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateCopyBufferSubData(context, readTarget, writeTarget, readOffset, writeOffset,
+                                       size))
+        {
+            return;
+        }
+
+        context->copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
+    }
+}
+
+void GL_APIENTRY GetUniformIndices(GLuint program,
+                                   GLsizei uniformCount,
+                                   const GLchar *const *uniformNames,
+                                   GLuint *uniformIndices)
+{
+    EVENT(
+        "(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = "
+        "0x%0.8p, GLuint* uniformIndices = 0x%0.8p)",
+        program, uniformCount, uniformNames, uniformIndices);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (uniformCount < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        Program *programObject = GetValidProgram(context, program);
+
+        if (!programObject)
+        {
+            return;
+        }
+
+        if (!programObject->isLinked())
+        {
+            for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+            {
+                uniformIndices[uniformId] = GL_INVALID_INDEX;
+            }
+        }
+        else
+        {
+            for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+            {
+                uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
+            }
+        }
+    }
+}
+
+void GL_APIENTRY GetActiveUniformsiv(GLuint program,
+                                     GLsizei uniformCount,
+                                     const GLuint *uniformIndices,
+                                     GLenum pname,
+                                     GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, "
+        "GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+        program, uniformCount, uniformIndices, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (uniformCount < 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        Program *programObject = GetValidProgram(context, program);
+
+        if (!programObject)
+        {
+            return;
+        }
+
+        switch (pname)
+        {
+            case GL_UNIFORM_TYPE:
+            case GL_UNIFORM_SIZE:
+            case GL_UNIFORM_NAME_LENGTH:
+            case GL_UNIFORM_BLOCK_INDEX:
+            case GL_UNIFORM_OFFSET:
+            case GL_UNIFORM_ARRAY_STRIDE:
+            case GL_UNIFORM_MATRIX_STRIDE:
+            case GL_UNIFORM_IS_ROW_MAJOR:
+                break;
+
+            default:
+                context->handleError(Error(GL_INVALID_ENUM));
+                return;
+        }
+
+        if (uniformCount > programObject->getActiveUniformCount())
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+        {
+            const GLuint index = uniformIndices[uniformId];
+
+            if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
+            {
+                context->handleError(Error(GL_INVALID_VALUE));
+                return;
+            }
+        }
+
+        for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+        {
+            const GLuint index = uniformIndices[uniformId];
+            params[uniformId]  = programObject->getActiveUniformi(index, pname);
+        }
+    }
+}
+
+GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
+{
+    EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program,
+          uniformBlockName);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return GL_INVALID_INDEX;
+        }
+
+        Program *programObject = GetValidProgram(context, program);
+        if (!programObject)
+        {
+            return GL_INVALID_INDEX;
+        }
+
+        return programObject->getUniformBlockIndex(uniformBlockName);
+    }
+
+    return 0;
+}
+
+void GL_APIENTRY GetActiveUniformBlockiv(GLuint program,
+                                         GLuint uniformBlockIndex,
+                                         GLenum pname,
+                                         GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = "
+        "0x%0.8p)",
+        program, uniformBlockIndex, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetActiveUniformBlockiv(context, program, uniformBlockIndex, pname, params))
+        {
+            return;
+        }
+
+        const Program *programObject = context->getProgram(program);
+        QueryActiveUniformBlockiv(programObject, uniformBlockIndex, pname, params);
+    }
+}
+
+void GL_APIENTRY GetActiveUniformBlockName(GLuint program,
+                                           GLuint uniformBlockIndex,
+                                           GLsizei bufSize,
+                                           GLsizei *length,
+                                           GLchar *uniformBlockName)
+{
+    EVENT(
+        "(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* "
+        "length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)",
+        program, uniformBlockIndex, bufSize, length, uniformBlockName);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        Program *programObject = GetValidProgram(context, program);
+
+        if (!programObject)
+        {
+            return;
+        }
+
+        if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length,
+                                                 uniformBlockName);
+    }
+}
+
+void GL_APIENTRY UniformBlockBinding(GLuint program,
+                                     GLuint uniformBlockIndex,
+                                     GLuint uniformBlockBinding)
+{
+    EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
+          program, uniformBlockIndex, uniformBlockBinding);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        Program *programObject = GetValidProgram(context, program);
+
+        if (!programObject)
+        {
+            return;
+        }
+
+        // if never linked, there won't be any uniform blocks
+        if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
+    }
+}
+
+void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+{
+    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
+          mode, first, count, instanceCount);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (!ValidateDrawArraysInstanced(context, mode, first, count, instanceCount))
+        {
+            return;
+        }
+
+        context->drawArraysInstanced(mode, first, count, instanceCount);
+    }
+}
+
+void GL_APIENTRY DrawElementsInstanced(GLenum mode,
+                                       GLsizei count,
+                                       GLenum type,
+                                       const void *indices,
+                                       GLsizei instanceCount)
+{
+    EVENT(
+        "(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void* indices = "
+        "0x%0.8p, GLsizei instanceCount = %d)",
+        mode, count, type, indices, instanceCount);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DrawElementsInstanced>(mode, count, type, indices,
+                                                                 instanceCount);
+
+        if (!context->skipValidation() &&
+            !ValidateDrawElementsInstanced(context, mode, count, type, indices, instanceCount))
+        {
+            return;
+        }
+
+        context->drawElementsInstanced(mode, count, type, indices, instanceCount);
+    }
+}
+
+GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags)
+{
+    EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return 0;
+        }
+
+        if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
+        {
+            context->handleError(Error(GL_INVALID_ENUM));
+            return 0;
+        }
+
+        if (flags != 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return 0;
+        }
+
+        GLsync fenceSync = context->createFenceSync();
+
+        FenceSync *fenceSyncObject = context->getFenceSync(fenceSync);
+        Error error                = fenceSyncObject->set(condition, flags);
+        if (error.isError())
+        {
+            context->deleteFenceSync(fenceSync);
+            context->handleError(error);
+            return nullptr;
+        }
+
+        return fenceSync;
+    }
+
+    return nullptr;
+}
+
+GLboolean GL_APIENTRY IsSync(GLsync sync)
+{
+    EVENT("(GLsync sync = 0x%0.8p)", sync);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return GL_FALSE;
+        }
+
+        return (context->getFenceSync(sync) != nullptr);
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY DeleteSync(GLsync sync)
+{
+    EVENT("(GLsync sync = 0x%0.8p)", sync);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        context->deleteFenceSync(sync);
+    }
+}
+
+GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+    EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", sync, flags,
+          timeout);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return GL_WAIT_FAILED;
+        }
+
+        if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return GL_WAIT_FAILED;
+        }
+
+        FenceSync *fenceSync = context->getFenceSync(sync);
+
+        if (!fenceSync)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return GL_WAIT_FAILED;
+        }
+
+        GLenum result = GL_WAIT_FAILED;
+        Error error   = fenceSync->clientWait(flags, timeout, &result);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return GL_WAIT_FAILED;
+        }
+
+        return result;
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+    EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", sync, flags,
+          timeout);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (flags != 0)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        if (timeout != GL_TIMEOUT_IGNORED)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        FenceSync *fenceSync = context->getFenceSync(sync);
+
+        if (!fenceSync)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        Error error = fenceSync->serverWait(flags, timeout);
+        if (error.isError())
+        {
+            context->handleError(error);
+        }
+    }
+}
+
+void GL_APIENTRY GetInteger64v(GLenum pname, GLint64 *params)
+{
+    EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        GLenum nativeType;
+        unsigned int numParams = 0;
+        if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
+        {
+            return;
+        }
+
+        if (nativeType == GL_INT_64_ANGLEX)
+        {
+            context->getInteger64v(pname, params);
+        }
+        else
+        {
+            CastStateValues(context, nativeType, pname, numParams, params);
+        }
+    }
+}
+
+void GL_APIENTRY
+GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+{
+    EVENT(
+        "(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = "
+        "0x%0.8p, GLint* values = 0x%0.8p)",
+        sync, pname, bufSize, length, values);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetSynciv(context, sync, pname, bufSize, length, values))
+        {
+            return;
+        }
+
+        context->getSynciv(sync, pname, bufSize, length, values);
+    }
+}
+
+void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64 *data)
+{
+    EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)", target, index,
+          data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGetInteger64i_v(context, target, index, data))
+        {
+            return;
+        }
+        context->getInteger64i_v(target, index, data);
+    }
+}
+
+void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", target, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetBufferParameteri64v(context, target, pname, params))
+        {
+            return;
+        }
+
+        Buffer *buffer = context->getGLState().getTargetBuffer(target);
+        QueryBufferParameteri64v(buffer, pname, params);
+    }
+}
+
+void GL_APIENTRY GenSamplers(GLsizei count, GLuint *samplers)
+{
+    EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGenSamplers(context, count, samplers))
+        {
+            return;
+        }
+
+        for (int i = 0; i < count; i++)
+        {
+            samplers[i] = context->createSampler();
+        }
+    }
+}
+
+void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint *samplers)
+{
+    EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateDeleteSamplers(context, count, samplers))
+        {
+            return;
+        }
+
+        for (int i = 0; i < count; i++)
+        {
+            context->deleteSampler(samplers[i]);
+        }
+    }
+}
+
+GLboolean GL_APIENTRY IsSampler(GLuint sampler)
+{
+    EVENT("(GLuint sampler = %u)", sampler);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return GL_FALSE;
+        }
+
+        return context->isSampler(sampler);
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler)
+{
+    EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (sampler != 0 && !context->isSampler(sampler))
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (unit >= context->getCaps().maxCombinedTextureImageUnits)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        context->bindSampler(unit, sampler);
+    }
+}
+
+void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+    EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateSamplerParameteri(context, sampler, pname, param))
+        {
+            return;
+        }
+
+        context->samplerParameteri(sampler, pname, param);
+    }
+}
+
+void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
+{
+    EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, const GLint* params = 0x%0.8p)", sampler,
+          pname, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateSamplerParameteriv(context, sampler, pname, param))
+        {
+            return;
+        }
+
+        context->samplerParameteriv(sampler, pname, param);
+    }
+}
+
+void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+{
+    EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateSamplerParameterf(context, sampler, pname, param))
+        {
+            return;
+        }
+
+        context->samplerParameterf(sampler, pname, param);
+    }
+}
+
+void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
+{
+    EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, const GLfloat* params = 0x%0.8p)", sampler,
+          pname, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateSamplerParameterfv(context, sampler, pname, param))
+        {
+            return;
+        }
+
+        context->samplerParameterfv(sampler, pname, param);
+    }
+}
+
+void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
+{
+    EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetSamplerParameteriv(context, sampler, pname, params))
+        {
+            return;
+        }
+
+        context->getSamplerParameteriv(sampler, pname, params);
+    }
+}
+
+void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
+{
+    EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname,
+          params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetSamplerParameterfv(context, sampler, pname, params))
+        {
+            return;
+        }
+
+        context->getSamplerParameterfv(sampler, pname, params);
+    }
+}
+
+void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor)
+{
+    EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (index >= MAX_VERTEX_ATTRIBS)
+        {
+            context->handleError(Error(GL_INVALID_VALUE));
+            return;
+        }
+
+        context->setVertexAttribDivisor(index, divisor);
+    }
+}
+
+void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id)
+{
+    EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        switch (target)
+        {
+            case GL_TRANSFORM_FEEDBACK:
+            {
+                // Cannot bind a transform feedback object if the current one is started and not
+                // paused (3.0.2 pg 85 section 2.14.1)
+                TransformFeedback *curTransformFeedback =
+                    context->getGLState().getCurrentTransformFeedback();
+                if (curTransformFeedback && curTransformFeedback->isActive() &&
+                    !curTransformFeedback->isPaused())
+                {
+                    context->handleError(Error(GL_INVALID_OPERATION));
+                    return;
+                }
+
+                // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
+                // 2.14.1)
+                if (!context->isTransformFeedbackGenerated(id))
+                {
+                    context->handleError(
+                        Error(GL_INVALID_OPERATION,
+                              "Cannot bind a transform feedback object that does not exist."));
+                    return;
+                }
+
+                context->bindTransformFeedback(id);
+            }
+            break;
+
+            default:
+                context->handleError(Error(GL_INVALID_ENUM));
+                return;
+        }
+    }
+}
+
+void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
+{
+    EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateDeleteTransformFeedbacks(context, n, ids))
+        {
+            return;
+        }
+
+        for (int i = 0; i < n; i++)
+        {
+            context->deleteTransformFeedback(ids[i]);
+        }
+    }
+}
+
+void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint *ids)
+{
+    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGenTransformFeedbacks(context, n, ids))
+        {
+            return;
+        }
+
+        for (int i = 0; i < n; i++)
+        {
+            ids[i] = context->createTransformFeedback();
+        }
+    }
+}
+
+GLboolean GL_APIENTRY IsTransformFeedback(GLuint id)
+{
+    EVENT("(GLuint id = %u)", id);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return GL_FALSE;
+        }
+
+        if (id == 0)
+        {
+            // The 3.0.4 spec [section 6.1.11] states that if ID is zero, IsTransformFeedback
+            // returns FALSE
+            return GL_FALSE;
+        }
+
+        const TransformFeedback *transformFeedback = context->getTransformFeedback(id);
+        return ((transformFeedback != nullptr) ? GL_TRUE : GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+void GL_APIENTRY PauseTransformFeedback(void)
+{
+    EVENT("(void)");
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+        ASSERT(transformFeedback != nullptr);
+
+        // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
+        if (!transformFeedback->isActive() || transformFeedback->isPaused())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        transformFeedback->pause();
+    }
+}
+
+void GL_APIENTRY ResumeTransformFeedback(void)
+{
+    EVENT("(void)");
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+        ASSERT(transformFeedback != nullptr);
+
+        // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
+        if (!transformFeedback->isActive() || !transformFeedback->isPaused())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        transformFeedback->resume();
+    }
+}
+
+void GL_APIENTRY GetProgramBinary(GLuint program,
+                                  GLsizei bufSize,
+                                  GLsizei *length,
+                                  GLenum *binaryFormat,
+                                  void *binary)
+{
+    EVENT(
+        "(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* "
+        "binaryFormat = 0x%0.8p, void* binary = 0x%0.8p)",
+        program, bufSize, length, binaryFormat, binary);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateGetProgramBinary(context, program, bufSize, length, binaryFormat, binary))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject != nullptr);
+
+        Error error = programObject->saveBinary(context, binaryFormat, binary, bufSize, length);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY ProgramBinary(GLuint program,
+                               GLenum binaryFormat,
+                               const void *binary,
+                               GLsizei length)
+{
+    EVENT(
+        "(GLuint program = %u, GLenum binaryFormat = 0x%X, const void* binary = 0x%0.8p, GLsizei "
+        "length = %d)",
+        program, binaryFormat, binary, length);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramBinary(context, program, binaryFormat, binary, length))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject != nullptr);
+
+        Error error = programObject->loadBinary(context, binaryFormat, binary, length);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value)
+{
+    EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", program, pname, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateProgramParameteri(context, program, pname, value))
+        {
+            return;
+        }
+
+        context->programParameteri(program, pname, value);
+    }
+}
+
+void GL_APIENTRY InvalidateFramebuffer(GLenum target,
+                                       GLsizei numAttachments,
+                                       const GLenum *attachments)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)",
+        target, numAttachments, attachments);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateInvalidateFramebuffer(context, target, numAttachments, attachments))
+        {
+            return;
+        }
+
+        context->invalidateFramebuffer(target, numAttachments, attachments);
+    }
+}
+
+void GL_APIENTRY InvalidateSubFramebuffer(GLenum target,
+                                          GLsizei numAttachments,
+                                          const GLenum *attachments,
+                                          GLint x,
+                                          GLint y,
+                                          GLsizei width,
+                                          GLsizei height)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, "
+        "GLint x = %d, "
+        "GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+        target, numAttachments, attachments, x, y, width, height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateInvalidateFramebuffer(context, target, numAttachments, attachments))
+        {
+            return;
+        }
+
+        context->invalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
+    }
+}
+
+void GL_APIENTRY
+TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = "
+        "%d, GLsizei height = %d)",
+        target, levels, internalformat, width, height);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width,
+                                               height, 1))
+        {
+            return;
+        }
+
+        Extents size(width, height, 1);
+        Texture *texture = context->getTargetTexture(target);
+        Error error      = texture->setStorage(context, target, levels, internalformat, size);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY TexStorage3D(GLenum target,
+                              GLsizei levels,
+                              GLenum internalformat,
+                              GLsizei width,
+                              GLsizei height,
+                              GLsizei depth)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = "
+        "%d, "
+        "GLsizei height = %d, GLsizei depth = %d)",
+        target, levels, internalformat, width, height, depth);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (context->getClientMajorVersion() < 3)
+        {
+            context->handleError(Error(GL_INVALID_OPERATION));
+            return;
+        }
+
+        if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width,
+                                               height, depth))
+        {
+            return;
+        }
+
+        Extents size(width, height, depth);
+        Texture *texture = context->getTargetTexture(target);
+        Error error      = texture->setStorage(context, target, levels, internalformat, size);
+        if (error.isError())
+        {
+            context->handleError(error);
+            return;
+        }
+    }
+}
+
+void GL_APIENTRY GetInternalformativ(GLenum target,
+                                     GLenum internalformat,
+                                     GLenum pname,
+                                     GLsizei bufSize,
+                                     GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize "
+        "= %d, "
+        "GLint* params = 0x%0.8p)",
+        target, internalformat, pname, bufSize, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetInternalFormativ(context, target, internalformat, pname, bufSize, params))
+        {
+            return;
+        }
+
+        const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+        QueryInternalFormativ(formatCaps, pname, bufSize, params);
+    }
+}
+}
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_gles_3_0.h b/src/third_party/angle/src/libGLESv2/entry_points_gles_3_0.h
new file mode 100644
index 0000000..b93b8aa
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_gles_3_0.h
@@ -0,0 +1,283 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_3_0.h : Defines the GLES 3.0 entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTGLES30_H_
+#define LIBGLESV2_ENTRYPOINTGLES30_H_
+
+#include <GLES3/gl3.h>
+#include <export.h>
+
+namespace gl
+{
+
+ANGLE_EXPORT void GL_APIENTRY ReadBuffer(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY DrawRangeElements(GLenum mode,
+                                                GLuint start,
+                                                GLuint end,
+                                                GLsizei count,
+                                                GLenum type,
+                                                const void *indices);
+ANGLE_EXPORT void GL_APIENTRY TexImage3D(GLenum target,
+                                         GLint level,
+                                         GLint internalformat,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLsizei depth,
+                                         GLint border,
+                                         GLenum format,
+                                         GLenum type,
+                                         const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage3D(GLenum target,
+                                            GLint level,
+                                            GLint xoffset,
+                                            GLint yoffset,
+                                            GLint zoffset,
+                                            GLsizei width,
+                                            GLsizei height,
+                                            GLsizei depth,
+                                            GLenum format,
+                                            GLenum type,
+                                            const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage3D(GLenum target,
+                                                GLint level,
+                                                GLint xoffset,
+                                                GLint yoffset,
+                                                GLint zoffset,
+                                                GLint x,
+                                                GLint y,
+                                                GLsizei width,
+                                                GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3D(GLenum target,
+                                                   GLint level,
+                                                   GLenum internalformat,
+                                                   GLsizei width,
+                                                   GLsizei height,
+                                                   GLsizei depth,
+                                                   GLint border,
+                                                   GLsizei imageSize,
+                                                   const void *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3D(GLenum target,
+                                                      GLint level,
+                                                      GLint xoffset,
+                                                      GLint yoffset,
+                                                      GLint zoffset,
+                                                      GLsizei width,
+                                                      GLsizei height,
+                                                      GLsizei depth,
+                                                      GLenum format,
+                                                      GLsizei imageSize,
+                                                      const void *data);
+ANGLE_EXPORT void GL_APIENTRY GenQueries(GLsizei n, GLuint *ids);
+ANGLE_EXPORT void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint *ids);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsQuery(GLuint id);
+ANGLE_EXPORT void GL_APIENTRY BeginQuery(GLenum target, GLuint id);
+ANGLE_EXPORT void GL_APIENTRY EndQuery(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
+ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBuffer(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, void **params);
+ANGLE_EXPORT void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum *bufs);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x3fv(GLint location,
+                                                 GLsizei count,
+                                                 GLboolean transpose,
+                                                 const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x2fv(GLint location,
+                                                 GLsizei count,
+                                                 GLboolean transpose,
+                                                 const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x4fv(GLint location,
+                                                 GLsizei count,
+                                                 GLboolean transpose,
+                                                 const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x2fv(GLint location,
+                                                 GLsizei count,
+                                                 GLboolean transpose,
+                                                 const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x4fv(GLint location,
+                                                 GLsizei count,
+                                                 GLboolean transpose,
+                                                 const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x3fv(GLint location,
+                                                 GLsizei count,
+                                                 GLboolean transpose,
+                                                 const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY BlitFramebuffer(GLint srcX0,
+                                              GLint srcY0,
+                                              GLint srcX1,
+                                              GLint srcY1,
+                                              GLint dstX0,
+                                              GLint dstY0,
+                                              GLint dstX1,
+                                              GLint dstY1,
+                                              GLbitfield mask,
+                                              GLenum filter);
+ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisample(GLenum target,
+                                                             GLsizei samples,
+                                                             GLenum internalformat,
+                                                             GLsizei width,
+                                                             GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY
+FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+ANGLE_EXPORT void *GL_APIENTRY MapBufferRange(GLenum target,
+                                              GLintptr offset,
+                                              GLsizeiptr length,
+                                              GLbitfield access);
+ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRange(GLenum target,
+                                                     GLintptr offset,
+                                                     GLsizeiptr length);
+ANGLE_EXPORT void GL_APIENTRY BindVertexArray(GLuint array);
+ANGLE_EXPORT void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint *arrays);
+ANGLE_EXPORT void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint *arrays);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsVertexArray(GLuint array);
+ANGLE_EXPORT void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint *data);
+ANGLE_EXPORT void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode);
+ANGLE_EXPORT void GL_APIENTRY EndTransformFeedback(void);
+ANGLE_EXPORT void GL_APIENTRY
+BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+ANGLE_EXPORT void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer);
+ANGLE_EXPORT void GL_APIENTRY TransformFeedbackVaryings(GLuint program,
+                                                        GLsizei count,
+                                                        const GLchar *const *varyings,
+                                                        GLenum bufferMode);
+ANGLE_EXPORT void GL_APIENTRY GetTransformFeedbackVarying(GLuint program,
+                                                          GLuint index,
+                                                          GLsizei bufSize,
+                                                          GLsizei *length,
+                                                          GLsizei *size,
+                                                          GLenum *type,
+                                                          GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY
+VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
+ANGLE_EXPORT void GL_APIENTRY
+VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint *v);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint *v);
+ANGLE_EXPORT void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint *params);
+ANGLE_EXPORT GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY Uniform1ui(GLint location, GLuint v0);
+ANGLE_EXPORT void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1);
+ANGLE_EXPORT void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
+ANGLE_EXPORT void GL_APIENTRY
+Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+ANGLE_EXPORT void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferfi(GLenum buffer,
+                                            GLint drawbuffer,
+                                            GLfloat depth,
+                                            GLint stencil);
+ANGLE_EXPORT const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index);
+ANGLE_EXPORT void GL_APIENTRY CopyBufferSubData(GLenum readTarget,
+                                                GLenum writeTarget,
+                                                GLintptr readOffset,
+                                                GLintptr writeOffset,
+                                                GLsizeiptr size);
+ANGLE_EXPORT void GL_APIENTRY GetUniformIndices(GLuint program,
+                                                GLsizei uniformCount,
+                                                const GLchar *const *uniformNames,
+                                                GLuint *uniformIndices);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformsiv(GLuint program,
+                                                  GLsizei uniformCount,
+                                                  const GLuint *uniformIndices,
+                                                  GLenum pname,
+                                                  GLint *params);
+ANGLE_EXPORT GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program,
+                                                     const GLchar *uniformBlockName);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockiv(GLuint program,
+                                                      GLuint uniformBlockIndex,
+                                                      GLenum pname,
+                                                      GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockName(GLuint program,
+                                                        GLuint uniformBlockIndex,
+                                                        GLsizei bufSize,
+                                                        GLsizei *length,
+                                                        GLchar *uniformBlockName);
+ANGLE_EXPORT void GL_APIENTRY UniformBlockBinding(GLuint program,
+                                                  GLuint uniformBlockIndex,
+                                                  GLuint uniformBlockBinding);
+ANGLE_EXPORT void GL_APIENTRY DrawArraysInstanced(GLenum mode,
+                                                  GLint first,
+                                                  GLsizei count,
+                                                  GLsizei instanceCount);
+ANGLE_EXPORT void GL_APIENTRY DrawElementsInstanced(GLenum mode,
+                                                    GLsizei count,
+                                                    GLenum type,
+                                                    const void *indices,
+                                                    GLsizei instanceCount);
+ANGLE_EXPORT GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsSync(GLsync sync);
+ANGLE_EXPORT void GL_APIENTRY DeleteSync(GLsync sync);
+ANGLE_EXPORT GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+ANGLE_EXPORT void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64v(GLenum pname, GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY
+GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64 *data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY GenSamplers(GLsizei count, GLuint *samplers);
+ANGLE_EXPORT void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint *samplers);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsSampler(GLuint sampler);
+ANGLE_EXPORT void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterfv(GLuint sampler,
+                                                 GLenum pname,
+                                                 const GLfloat *param);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor);
+ANGLE_EXPORT void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id);
+ANGLE_EXPORT void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint *ids);
+ANGLE_EXPORT void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint *ids);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsTransformFeedback(GLuint id);
+ANGLE_EXPORT void GL_APIENTRY PauseTransformFeedback(void);
+ANGLE_EXPORT void GL_APIENTRY ResumeTransformFeedback(void);
+ANGLE_EXPORT void GL_APIENTRY GetProgramBinary(GLuint program,
+                                               GLsizei bufSize,
+                                               GLsizei *length,
+                                               GLenum *binaryFormat,
+                                               void *binary);
+ANGLE_EXPORT void GL_APIENTRY ProgramBinary(GLuint program,
+                                            GLenum binaryFormat,
+                                            const void *binary,
+                                            GLsizei length);
+ANGLE_EXPORT void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value);
+ANGLE_EXPORT void GL_APIENTRY InvalidateFramebuffer(GLenum target,
+                                                    GLsizei numAttachments,
+                                                    const GLenum *attachments);
+ANGLE_EXPORT void GL_APIENTRY InvalidateSubFramebuffer(GLenum target,
+                                                       GLsizei numAttachments,
+                                                       const GLenum *attachments,
+                                                       GLint x,
+                                                       GLint y,
+                                                       GLsizei width,
+                                                       GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY
+TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY TexStorage3D(GLenum target,
+                                           GLsizei levels,
+                                           GLenum internalformat,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLsizei depth);
+ANGLE_EXPORT void GL_APIENTRY GetInternalformativ(GLenum target,
+                                                  GLenum internalformat,
+                                                  GLenum pname,
+                                                  GLsizei bufSize,
+                                                  GLint *params);
+}
+
+#endif  // LIBGLESV2_ENTRYPOINTGLES30_H_
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_gles_3_1.cpp b/src/third_party/angle/src/libGLESv2/entry_points_gles_3_1.cpp
new file mode 100644
index 0000000..1e4100b
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_gles_3_1.cpp
@@ -0,0 +1,1212 @@
+//
+// Copyright(c) 2016 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.
+//
+
+// entry_points_gles_3_1.cpp : Implements the GLES 3.1 Entry point.
+
+#include "libGLESv2/entry_points_gles_3_1.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES31.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+void GL_APIENTRY DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+    EVENT("(GLuint numGroupsX = %u, GLuint numGroupsY = %u, numGroupsZ = %u", numGroupsX,
+          numGroupsY, numGroupsZ);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateDispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ))
+        {
+            return;
+        }
+
+        context->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
+    }
+}
+
+void GL_APIENTRY DispatchComputeIndirect(GLintptr indirect)
+{
+    EVENT("(GLintptr indirect = %d)", indirect);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+void GL_APIENTRY DrawArraysIndirect(GLenum mode, const void *indirect)
+{
+    EVENT("(GLenum mode = 0x%X, const void* indirect)", mode, indirect);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateDrawArraysIndirect(context, mode, indirect))
+        {
+            return;
+        }
+
+        context->drawArraysIndirect(mode, indirect);
+    }
+}
+
+void GL_APIENTRY DrawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+    EVENT("(GLenum mode = 0x%X, GLenum type = 0x%X, const void* indirect)", mode, type, indirect);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateDrawElementsIndirect(context, mode, type, indirect))
+        {
+            return;
+        }
+
+        context->drawElementsIndirect(mode, type, indirect);
+    }
+}
+
+void GL_APIENTRY FramebufferParameteri(GLenum target, GLenum pname, GLint param)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidationFramebufferParameteri(context, target, pname, param))
+        {
+            return;
+        }
+
+        context->setFramebufferParameteri(target, pname, param);
+    }
+}
+
+void GL_APIENTRY GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname,
+          params);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidationGetFramebufferParameteri(context, target, pname, params))
+        {
+            return;
+        }
+
+        context->getFramebufferParameteriv(target, pname, params);
+    }
+}
+
+void GL_APIENTRY GetProgramInterfaceiv(GLuint program,
+                                       GLenum programInterface,
+                                       GLenum pname,
+                                       GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLenum programInterface = 0x%X, GLenum pname = 0x%X, GLint* params "
+        "= 0x%0.8p)",
+        program, programInterface, pname, params);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+GLuint GL_APIENTRY GetProgramResourceIndex(GLuint program,
+                                           GLenum programInterface,
+                                           const GLchar *name)
+{
+    EVENT("(GLuint program = %u, GLenum programInterface = 0x%X, const GLchar* name = 0x%0.8p)",
+          program, programInterface, name);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetProgramResourceIndex(context, program, programInterface, name))
+        {
+            return GL_INVALID_INDEX;
+        }
+        return context->getProgramResourceIndex(program, programInterface, name);
+    }
+    return 0u;
+}
+
+void GL_APIENTRY GetProgramResourceName(GLuint program,
+                                        GLenum programInterface,
+                                        GLuint index,
+                                        GLsizei bufSize,
+                                        GLsizei *length,
+                                        GLchar *name)
+{
+    EVENT(
+        "(GLuint program = %u, GLenum programInterface = 0x%X, GLuint index = %u, GLsizei bufSize "
+        "= %d, GLsizei* length = 0x%0.8p, GLchar* name = 0x%0.8p)",
+        program, programInterface, index, bufSize, length, name);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetProgramResourceName(context, program, programInterface, index, bufSize,
+                                            length, name))
+        {
+            return;
+        }
+        context->getProgramResourceName(program, programInterface, index, bufSize, length, name);
+    }
+}
+
+void GL_APIENTRY GetProgramResourceiv(GLuint program,
+                                      GLenum programInterface,
+                                      GLuint index,
+                                      GLsizei propCount,
+                                      const GLenum *props,
+                                      GLsizei bufSize,
+                                      GLsizei *length,
+                                      GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLenum programInterface = 0x%X, GLuint index = %u, GLsizei "
+        "propCount = %d, const GLenum* props = 0x%0.8p, GLsizei bufSize = %d, GLsizei* length = "
+        "0x%0.8p, GLint* params = 0x%0.8p)",
+        program, programInterface, index, propCount, props, bufSize, length, params);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+GLint GL_APIENTRY GetProgramResourceLocation(GLuint program,
+                                             GLenum programInterface,
+                                             const GLchar *name)
+{
+    EVENT("(GLuint program = %u, GLenum programInterface = 0x%X, const GLchar* name = 0x%0.8p)",
+          program, programInterface, name);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+    return 0;
+}
+
+void GL_APIENTRY UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)
+{
+    EVENT("(GLuint pipeline = %u, GLbitfield stages = 0x%X, GLuint program = %u)", pipeline, stages,
+          program);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+void GL_APIENTRY ActiveShaderProgram(GLuint pipeline, GLuint program)
+{
+    EVENT("(GLuint pipeline = %u, GLuint program = %u)", pipeline, program);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+GLuint GL_APIENTRY CreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const *strings)
+{
+    EVENT("(GLenum type = %0x%X, GLsizei count = %d, const GLchar *const* = 0x%0.8p)", type, count,
+          strings);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+    return 0u;
+}
+
+void GL_APIENTRY BindProgramPipeline(GLuint pipeline)
+{
+    EVENT("(GLuint pipeline = %u)", pipeline);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (pipeline != 0)
+        {
+            // Binding non-zero pipelines is not implemented yet.
+            UNIMPLEMENTED();
+        }
+    }
+}
+
+void GL_APIENTRY DeleteProgramPipelines(GLsizei n, const GLuint *pipelines)
+{
+    EVENT("(GLsizei n = %d, const GLuint* pipelines = 0x%0.8p)", n, pipelines);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+void GL_APIENTRY GenProgramPipelines(GLsizei n, GLuint *pipelines)
+{
+    EVENT("(GLsizei n = %d, GLuint* pipelines = 0x%0.8p)", n, pipelines);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+GLboolean GL_APIENTRY IsProgramPipeline(GLuint pipeline)
+{
+    EVENT("(GLuint pipeline = %u)", pipeline);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+    return false;
+}
+
+void GL_APIENTRY GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params)
+{
+    EVENT("(GLuint pipeline = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pipeline, pname,
+          params);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+void GL_APIENTRY ProgramUniform1i(GLuint program, GLint location, GLint v0)
+{
+    ProgramUniform1iv(program, location, 1, &v0);
+}
+
+void GL_APIENTRY ProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1)
+{
+    GLint xy[2] = {v0, v1};
+    ProgramUniform2iv(program, location, 1, xy);
+}
+
+void GL_APIENTRY ProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
+{
+    GLint xyz[3] = {v0, v1, v2};
+    ProgramUniform3iv(program, location, 1, xyz);
+}
+
+void GL_APIENTRY
+ProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+{
+    GLint xyzw[4] = {v0, v1, v2, v3};
+    ProgramUniform4iv(program, location, 1, xyzw);
+}
+
+void GL_APIENTRY ProgramUniform1ui(GLuint program, GLint location, GLuint v0)
+{
+    ProgramUniform1uiv(program, location, 1, &v0);
+}
+
+void GL_APIENTRY ProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1)
+{
+    GLuint xy[2] = {v0, v1};
+    ProgramUniform2uiv(program, location, 1, xy);
+}
+
+void GL_APIENTRY ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+    GLuint xyz[3] = {v0, v1, v2};
+    ProgramUniform3uiv(program, location, 1, xyz);
+}
+
+void GL_APIENTRY
+ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+    GLuint xyzw[4] = {v0, v1, v2, v3};
+    ProgramUniform4uiv(program, location, 1, xyzw);
+}
+
+void GL_APIENTRY ProgramUniform1f(GLuint program, GLint location, GLfloat v0)
+{
+    ProgramUniform1fv(program, location, 1, &v0);
+}
+
+void GL_APIENTRY ProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1)
+{
+    GLfloat xy[2] = {v0, v1};
+    ProgramUniform2fv(program, location, 1, xy);
+}
+
+void GL_APIENTRY
+ProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+{
+    GLfloat xyz[3] = {v0, v1, v2};
+    ProgramUniform3fv(program, location, 1, xyz);
+}
+
+void GL_APIENTRY
+ProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+{
+    GLfloat xyzw[4] = {v0, v1, v2, v3};
+    ProgramUniform4fv(program, location, 1, xyzw);
+}
+
+void GL_APIENTRY ProgramUniform1iv(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   const GLint *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLint* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform1iv(context, program, location, count, value))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform1iv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform2iv(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   const GLint *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLint* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_INT_VEC2, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform2iv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform3iv(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   const GLint *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLint* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_INT_VEC3, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform3iv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform4iv(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   const GLint *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLint* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_INT_VEC4, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform4iv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform1uiv(GLuint program,
+                                    GLint location,
+                                    GLsizei count,
+                                    const GLuint *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLuint* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_UNSIGNED_INT, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform1uiv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform2uiv(GLuint program,
+                                    GLint location,
+                                    GLsizei count,
+                                    const GLuint *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLuint* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC2, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform2uiv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform3uiv(GLuint program,
+                                    GLint location,
+                                    GLsizei count,
+                                    const GLuint *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLuint* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC3, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform3uiv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform4uiv(GLuint program,
+                                    GLint location,
+                                    GLsizei count,
+                                    const GLuint *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLuint* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC4, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform4uiv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform1fv(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLfloat* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_FLOAT, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform1fv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform2fv(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLfloat* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_FLOAT_VEC2, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform2fv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform3fv(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLfloat* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_FLOAT_VEC3, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform3fv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniform4fv(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLfloat* value = "
+        "0x%0.8p)",
+        program, location, count, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniform(context, GL_FLOAT_VEC4, program, location, count))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniform4fv(location, count, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniformMatrix2fv(GLuint program,
+                                         GLint location,
+                                         GLsizei count,
+                                         GLboolean transpose,
+                                         const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+        "const GLfloat* value = 0x%0.8p)",
+        program, location, count, transpose, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2, program, location, count,
+                                          transpose))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniformMatrix2fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniformMatrix3fv(GLuint program,
+                                         GLint location,
+                                         GLsizei count,
+                                         GLboolean transpose,
+                                         const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+        "const GLfloat* value = 0x%0.8p)",
+        program, location, count, transpose, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3, program, location, count,
+                                          transpose))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniformMatrix3fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniformMatrix4fv(GLuint program,
+                                         GLint location,
+                                         GLsizei count,
+                                         GLboolean transpose,
+                                         const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+        "const GLfloat* value = 0x%0.8p)",
+        program, location, count, transpose, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4, program, location, count,
+                                          transpose))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniformMatrix4fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniformMatrix2x3fv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+        "const GLfloat* value = 0x%0.8p)",
+        program, location, count, transpose, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x3, program, location, count,
+                                          transpose))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniformMatrix2x3fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniformMatrix3x2fv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+        "const GLfloat* value = 0x%0.8p)",
+        program, location, count, transpose, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x2, program, location, count,
+                                          transpose))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniformMatrix3x2fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniformMatrix2x4fv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+        "const GLfloat* value = 0x%0.8p)",
+        program, location, count, transpose, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x4, program, location, count,
+                                          transpose))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniformMatrix2x4fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniformMatrix4x2fv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+        "const GLfloat* value = 0x%0.8p)",
+        program, location, count, transpose, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x2, program, location, count,
+                                          transpose))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniformMatrix4x2fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniformMatrix3x4fv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+        "const GLfloat* value = 0x%0.8p)",
+        program, location, count, transpose, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x4, program, location, count,
+                                          transpose))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniformMatrix3x4fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY ProgramUniformMatrix4x3fv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat *value)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+        "const GLfloat* value = 0x%0.8p)",
+        program, location, count, transpose, value);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x3, program, location, count,
+                                          transpose))
+        {
+            return;
+        }
+
+        Program *programObject = context->getProgram(program);
+        ASSERT(programObject);
+        programObject->setUniformMatrix4x3fv(location, count, transpose, value);
+    }
+}
+
+void GL_APIENTRY ValidateProgramPipeline(GLuint pipeline)
+{
+    EVENT("(GLuint pipeline = %u)", pipeline);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+void GL_APIENTRY GetProgramPipelineInfoLog(GLuint pipeline,
+                                           GLsizei bufSize,
+                                           GLsizei *length,
+                                           GLchar *infoLog)
+{
+    EVENT(
+        "(GLuint pipeline = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* infoLog = "
+        "0x%0.8p)",
+        pipeline, bufSize, length, infoLog);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+void GL_APIENTRY BindImageTexture(GLuint unit,
+                                  GLuint texture,
+                                  GLint level,
+                                  GLboolean layered,
+                                  GLint layer,
+                                  GLenum access,
+                                  GLenum format)
+{
+    EVENT(
+        "(GLuint unit = %u, GLuint texture = %u, GLint level = %d, GLboolean layered = %u, GLint "
+        "layer = %d, GLenum access = 0x%X, GLenum format = 0x%X)",
+        unit, texture, level, layered, layer, access, format);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (texture != 0)
+        {
+            // Binding non-zero image textures is not implemented yet.
+            UNIMPLEMENTED();
+        }
+    }
+}
+
+void GL_APIENTRY GetBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+    EVENT("(GLenum target = 0x%X, GLuint index = %u, GLboolean* data = 0x%0.8p)", target, index,
+          data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGetBooleani_v(context, target, index, data))
+        {
+            return;
+        }
+        context->getBooleani_v(target, index, data);
+    }
+}
+
+void GL_APIENTRY MemoryBarrier(GLbitfield barriers)
+{
+    EVENT("(GLbitfield barriers = 0x%X)", barriers);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+void GL_APIENTRY MemoryBarrierByRegion(GLbitfield barriers)
+{
+    EVENT("(GLbitfield barriers = 0x%X)", barriers);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation())
+        {
+            context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
+        }
+        UNIMPLEMENTED();
+    }
+}
+
+void GL_APIENTRY TexStorage2DMultisample(GLenum target,
+                                         GLsizei samples,
+                                         GLenum internalformat,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLboolean fixedsamplelocations)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width "
+        "= %d, GLsizei height = %d, GLboolean fixedsamplelocations = %u)",
+        target, samples, internalformat, width, height, fixedsamplelocations);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateTexStorage2DMultiSample(context, target, samples, internalformat, width,
+                                             height, fixedsamplelocations))
+        {
+            return;
+        }
+        context->texStorage2DMultisample(target, samples, internalformat, width, height,
+                                         fixedsamplelocations);
+    }
+}
+
+void GL_APIENTRY GetMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
+{
+    EVENT("(GLenum pname = 0x%X, GLuint index = %u, GLfloat* val = 0x%0.8p)", pname, index, val);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() && !ValidateGetMultisamplefv(context, pname, index, val))
+        {
+            return;
+        }
+
+        context->getMultisamplefv(pname, index, val);
+    }
+}
+
+void GL_APIENTRY SampleMaski(GLuint maskNumber, GLbitfield mask)
+{
+    EVENT("(GLuint maskNumber = %u, GLbitfield mask = 0x%X)", maskNumber, mask);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (mask != ~GLbitfield(0))
+        {
+            // Setting a non-default sample mask is not implemented yet.
+            UNIMPLEMENTED();
+        }
+    }
+}
+
+void GL_APIENTRY GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
+{
+    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+          target, level, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetTexLevelParameteriv(context, target, level, pname, params))
+        {
+            return;
+        }
+
+        Texture *texture = context->getTargetTexture(
+            IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+        QueryTexLevelParameteriv(texture, target, level, pname, params);
+    }
+}
+
+void GL_APIENTRY GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)",
+        target, level, pname, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateGetTexLevelParameterfv(context, target, level, pname, params))
+        {
+            return;
+        }
+
+        Texture *texture = context->getTargetTexture(
+            IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+        QueryTexLevelParameterfv(texture, target, level, pname, params);
+    }
+}
+
+void GL_APIENTRY BindVertexBuffer(GLuint bindingindex,
+                                  GLuint buffer,
+                                  GLintptr offset,
+                                  GLsizei stride)
+{
+    EVENT(
+        "(GLuint bindingindex = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizei stride = %d)",
+        bindingindex, buffer, offset, stride);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateBindVertexBuffer(context, bindingindex, buffer, offset, stride))
+        {
+            return;
+        }
+
+        context->bindVertexBuffer(bindingindex, buffer, offset, stride);
+    }
+}
+
+void GL_APIENTRY VertexAttribFormat(GLuint attribindex,
+                                    GLint size,
+                                    GLenum type,
+                                    GLboolean normalized,
+                                    GLuint relativeoffset)
+{
+    EVENT(
+        "(GLuint attribindex = %u, GLint size = %d, GLenum type = 0x%X, GLboolean normalized = %u, "
+        "GLuint relativeoffset = %u)",
+        attribindex, size, type, normalized, relativeoffset);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateVertexAttribFormat(context, attribindex, size, type, relativeoffset, false))
+        {
+            return;
+        }
+
+        context->vertexAttribFormat(attribindex, size, type, normalized, relativeoffset);
+    }
+}
+
+void GL_APIENTRY VertexAttribIFormat(GLuint attribindex,
+                                     GLint size,
+                                     GLenum type,
+                                     GLuint relativeoffset)
+{
+    EVENT(
+        "(GLuint attribindex = %u, GLint size = %d, GLenum type = 0x%X, GLuint relativeoffset = "
+        "%u)",
+        attribindex, size, type, relativeoffset);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateVertexAttribFormat(context, attribindex, size, type, relativeoffset, true))
+        {
+            return;
+        }
+
+        context->vertexAttribIFormat(attribindex, size, type, relativeoffset);
+    }
+}
+
+void GL_APIENTRY VertexAttribBinding(GLuint attribindex, GLuint bindingindex)
+{
+    EVENT("(GLuint attribindex = %u, GLuint bindingindex = %u)", attribindex, bindingindex);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateVertexAttribBinding(context, attribindex, bindingindex))
+        {
+            return;
+        }
+
+        context->vertexAttribBinding(attribindex, bindingindex);
+    }
+}
+
+void GL_APIENTRY VertexBindingDivisor(GLuint bindingindex, GLuint divisor)
+{
+    EVENT("(GLuint bindingindex = %u, GLuint divisor = %u)", bindingindex, divisor);
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        if (!context->skipValidation() &&
+            !ValidateVertexBindingDivisor(context, bindingindex, divisor))
+        {
+            return;
+        }
+
+        context->setVertexBindingDivisor(bindingindex, divisor);
+    }
+}
+}  // namespace gl
diff --git a/src/third_party/angle/src/libGLESv2/entry_points_gles_3_1.h b/src/third_party/angle/src/libGLESv2/entry_points_gles_3_1.h
new file mode 100644
index 0000000..1500fde
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/entry_points_gles_3_1.h
@@ -0,0 +1,229 @@
+//
+// Copyright(c) 2016 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.
+//
+
+// entry_points_gles_3_1.h : Defines the GLES 3.1 entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTGLES31_H_
+#define LIBGLESV2_ENTRYPOINTGLES31_H_
+
+#include <GLES3/gl31.h>
+#include <export.h>
+
+// we include the platform.h header since it undefines the conflicting MemoryBarrier macro
+#include "common/platform.h"
+
+namespace gl
+{
+
+ANGLE_EXPORT void GL_APIENTRY DispatchCompute(GLuint numGroupsX,
+                                              GLuint numGroupsY,
+                                              GLuint numGroupsZ);
+ANGLE_EXPORT void GL_APIENTRY DispatchComputeIndirect(GLintptr indirect);
+ANGLE_EXPORT void GL_APIENTRY DrawArraysIndirect(GLenum mode, const void *indirect);
+ANGLE_EXPORT void GL_APIENTRY DrawElementsIndirect(GLenum mode, GLenum type, const void *indirect);
+ANGLE_EXPORT void GL_APIENTRY FramebufferParameteri(GLenum target, GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetProgramInterfaceiv(GLuint program,
+                                                    GLenum programInterface,
+                                                    GLenum pname,
+                                                    GLint *params);
+ANGLE_EXPORT GLuint GL_APIENTRY GetProgramResourceIndex(GLuint program,
+                                                        GLenum programInterface,
+                                                        const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetProgramResourceName(GLuint program,
+                                                     GLenum programInterface,
+                                                     GLuint index,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetProgramResourceiv(GLuint program,
+                                                   GLenum programInterface,
+                                                   GLuint index,
+                                                   GLsizei propCount,
+                                                   const GLenum *props,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLint *params);
+ANGLE_EXPORT GLint GL_APIENTRY GetProgramResourceLocation(GLuint program,
+                                                          GLenum programInterface,
+                                                          const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program);
+ANGLE_EXPORT void GL_APIENTRY ActiveShaderProgram(GLuint pipeline, GLuint program);
+ANGLE_EXPORT GLuint GL_APIENTRY CreateShaderProgramv(GLenum type,
+                                                     GLsizei count,
+                                                     const GLchar *const *strings);
+ANGLE_EXPORT void GL_APIENTRY BindProgramPipeline(GLuint pipeline);
+ANGLE_EXPORT void GL_APIENTRY DeleteProgramPipelines(GLsizei n, const GLuint *pipelines);
+ANGLE_EXPORT void GL_APIENTRY GenProgramPipelines(GLsizei n, GLuint *pipelines);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsProgramPipeline(GLuint pipeline);
+ANGLE_EXPORT void GL_APIENTRY GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1i(GLuint program, GLint location, GLint v0);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1ui(GLuint program, GLint location, GLuint v0);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2ui(GLuint program,
+                                                GLint location,
+                                                GLuint v0,
+                                                GLuint v1);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1f(GLuint program, GLint location, GLfloat v0);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2f(GLuint program,
+                                               GLint location,
+                                               GLfloat v0,
+                                               GLfloat v1);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1iv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2iv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform3iv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform4iv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1uiv(GLuint program,
+                                                 GLint location,
+                                                 GLsizei count,
+                                                 const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2uiv(GLuint program,
+                                                 GLint location,
+                                                 GLsizei count,
+                                                 const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform3uiv(GLuint program,
+                                                 GLint location,
+                                                 GLsizei count,
+                                                 const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform4uiv(GLuint program,
+                                                 GLint location,
+                                                 GLsizei count,
+                                                 const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1fv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2fv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform3fv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform4fv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix2fv(GLuint program,
+                                                      GLint location,
+                                                      GLsizei count,
+                                                      GLboolean transpose,
+                                                      const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix3fv(GLuint program,
+                                                      GLint location,
+                                                      GLsizei count,
+                                                      GLboolean transpose,
+                                                      const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix4fv(GLuint program,
+                                                      GLint location,
+                                                      GLsizei count,
+                                                      GLboolean transpose,
+                                                      const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix2x3fv(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        GLboolean transpose,
+                                                        const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix3x2fv(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        GLboolean transpose,
+                                                        const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix2x4fv(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        GLboolean transpose,
+                                                        const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix4x2fv(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        GLboolean transpose,
+                                                        const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix3x4fv(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        GLboolean transpose,
+                                                        const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix4x3fv(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        GLboolean transpose,
+                                                        const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ValidateProgramPipeline(GLuint pipeline);
+ANGLE_EXPORT void GL_APIENTRY GetProgramPipelineInfoLog(GLuint pipeline,
+                                                        GLsizei bufSize,
+                                                        GLsizei *length,
+                                                        GLchar *infoLog);
+ANGLE_EXPORT void GL_APIENTRY BindImageTexture(GLuint unit,
+                                               GLuint texture,
+                                               GLint level,
+                                               GLboolean layered,
+                                               GLint layer,
+                                               GLenum access,
+                                               GLenum format);
+ANGLE_EXPORT void GL_APIENTRY GetBooleani_v(GLenum target, GLuint index, GLboolean *data);
+
+ANGLE_EXPORT void GL_APIENTRY MemoryBarrier(GLbitfield barriers);
+ANGLE_EXPORT void GL_APIENTRY MemoryBarrierByRegion(GLbitfield barriers);
+ANGLE_EXPORT void GL_APIENTRY TexStorage2DMultisample(GLenum target,
+                                                      GLsizei samples,
+                                                      GLenum internalformat,
+                                                      GLsizei width,
+                                                      GLsizei height,
+                                                      GLboolean fixedsamplelocations);
+ANGLE_EXPORT void GL_APIENTRY GetMultisamplefv(GLenum pname, GLuint index, GLfloat *val);
+ANGLE_EXPORT void GL_APIENTRY SampleMaski(GLuint maskNumber, GLbitfield mask);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameteriv(GLenum target,
+                                                     GLint level,
+                                                     GLenum pname,
+                                                     GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfv(GLenum target,
+                                                     GLint level,
+                                                     GLenum pname,
+                                                     GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY BindVertexBuffer(GLuint bindingindex,
+                                               GLuint buffer,
+                                               GLintptr offset,
+                                               GLsizei stride);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribFormat(GLuint attribindex,
+                                                 GLint size,
+                                                 GLenum type,
+                                                 GLboolean normalized,
+                                                 GLuint relativeoffset);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribIFormat(GLuint attribindex,
+                                                  GLint size,
+                                                  GLenum type,
+                                                  GLuint relativeoffset);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribBinding(GLuint attribindex, GLuint bindingindex);
+ANGLE_EXPORT void GL_APIENTRY VertexBindingDivisor(GLuint bindingindex, GLuint divisor);
+};
+
+#endif  // LIBGLESV2_ENTRYPOINTGLES31_H_
diff --git a/src/third_party/angle/src/libGLESv2/global_state.cpp b/src/third_party/angle/src/libGLESv2/global_state.cpp
new file mode 100644
index 0000000..c5f3dfe
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/global_state.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// global_state.cpp : Implements functions for querying the thread-local GL and EGL state.
+
+#include "libGLESv2/global_state.h"
+
+#include "common/debug.h"
+#include "common/platform.h"
+#include "common/tls.h"
+
+#include "libANGLE/Thread.h"
+
+namespace gl
+{
+
+Context *GetGlobalContext()
+{
+    egl::Thread *thread = egl::GetCurrentThread();
+    return thread->getContext();
+}
+
+Context *GetValidGlobalContext()
+{
+    egl::Thread *thread = egl::GetCurrentThread();
+    return thread->getValidContext();
+}
+
+}  // namespace gl
+
+namespace egl
+{
+
+namespace
+{
+
+static TLSIndex threadTLS = TLS_INVALID_INDEX;
+
+Thread *AllocateCurrentThread()
+{
+    ASSERT(threadTLS != TLS_INVALID_INDEX);
+    if (threadTLS == TLS_INVALID_INDEX)
+    {
+        return nullptr;
+    }
+
+    Thread *thread = new Thread();
+    if (!SetTLSValue(threadTLS, thread))
+    {
+        ERR() << "Could not set thread local storage.";
+        return nullptr;
+    }
+
+    return thread;
+}
+
+}  // anonymous namespace
+
+Thread *GetCurrentThread()
+{
+    // Create a TLS index if one has not been created for this DLL
+    if (threadTLS == TLS_INVALID_INDEX)
+    {
+        threadTLS = CreateTLSIndex();
+    }
+
+    Thread *current = static_cast<Thread *>(GetTLSValue(threadTLS));
+
+    // ANGLE issue 488: when the dll is loaded after thread initialization,
+    // thread local storage (current) might not exist yet.
+    return (current ? current : AllocateCurrentThread());
+}
+
+}  // namespace egl
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+namespace egl
+{
+
+namespace
+{
+
+bool DeallocateCurrentThread()
+{
+    Thread *thread = static_cast<Thread *>(GetTLSValue(threadTLS));
+    SafeDelete(thread);
+    return SetTLSValue(threadTLS, nullptr);
+}
+
+bool InitializeProcess()
+{
+    threadTLS = CreateTLSIndex();
+    if (threadTLS == TLS_INVALID_INDEX)
+    {
+        return false;
+    }
+
+    return AllocateCurrentThread() != nullptr;
+}
+
+bool TerminateProcess()
+{
+    if (!DeallocateCurrentThread())
+    {
+        return false;
+    }
+
+    if (threadTLS != TLS_INVALID_INDEX)
+    {
+        TLSIndex tlsCopy = threadTLS;
+        threadTLS        = TLS_INVALID_INDEX;
+
+        if (!DestroyTLSIndex(tlsCopy))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+}  // anonymous namespace
+
+}  // namespace egl
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
+{
+    switch (reason)
+    {
+        case DLL_PROCESS_ATTACH:
+            return static_cast<BOOL>(egl::InitializeProcess());
+
+        case DLL_THREAD_ATTACH:
+            return static_cast<BOOL>(egl::AllocateCurrentThread() != nullptr);
+
+        case DLL_THREAD_DETACH:
+            return static_cast<BOOL>(egl::DeallocateCurrentThread());
+
+        case DLL_PROCESS_DETACH:
+            return static_cast<BOOL>(egl::TerminateProcess());
+    }
+
+    return TRUE;
+}
+#endif  // ANGLE_PLATFORM_WINDOWS
diff --git a/src/third_party/angle/src/libGLESv2/global_state.h b/src/third_party/angle/src/libGLESv2/global_state.h
new file mode 100644
index 0000000..3e3740c
--- /dev/null
+++ b/src/third_party/angle/src/libGLESv2/global_state.h
@@ -0,0 +1,29 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// global_state.h : Defines functions for querying the thread-local GL and EGL state.
+
+#ifndef LIBGLESV2_GLOBALSTATE_H_
+#define LIBGLESV2_GLOBALSTATE_H_
+
+namespace gl
+{
+class Context;
+
+Context *GetGlobalContext();
+Context *GetValidGlobalContext();
+
+}  // namespace gl
+
+namespace egl
+{
+class Thread;
+
+Thread *GetCurrentThread();
+
+}  // namespace egl
+
+#endif // LIBGLESV2_GLOBALSTATE_H_
diff --git a/src/third_party/angle/src/libGLESv2/libGLESv2.cpp b/src/third_party/angle/src/libGLESv2/libGLESv2.cpp
index aaade67..e7e78c3 100644
--- a/src/third_party/angle/src/libGLESv2/libGLESv2.cpp
+++ b/src/third_party/angle/src/libGLESv2/libGLESv2.cpp
@@ -1,7781 +1,2547 @@
-#include "precompiled.h"
 //
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// 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.
 //
 
 // libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
 
-#include "common/version.h"
+#include "libGLESv2/entry_points_gles_2_0_autogen.h"
+#include "libGLESv2/entry_points_gles_2_0_ext.h"
+#include "libGLESv2/entry_points_gles_3_0.h"
+#include "libGLESv2/entry_points_gles_3_1.h"
 
-#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Fence.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Query.h"
-#include "libGLESv2/Context.h"
+#include "common/event_tracer.h"
+
+extern "C" {
 
-bool validImageSize(GLint level, GLsizei width, GLsizei height)
+void GL_APIENTRY glActiveTexture(GLenum texture)
 {
-    if (level < 0 || width < 0 || height < 0)
-    {
-        return false;
-    }
+    return gl::ActiveTexture(texture);
+}
 
-    if (gl::getContext() && gl::getContext()->supportsNonPower2Texture())
-    {
-        return true;
-    }
+void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)
+{
+    return gl::AttachShader(program, shader);
+}
 
-    if (level == 0)
-    {
-        return true;
-    }
+void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar *name)
+{
+    return gl::BindAttribLocation(program, index, name);
+}
 
-    if (gl::isPow2(width) && gl::isPow2(height))
-    {
-        return true;
-    }
+void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer)
+{
+    return gl::BindBuffer(target, buffer);
+}
 
-    return false;
+void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer)
+{
+    return gl::BindFramebuffer(target, framebuffer);
 }
 
-// Verify that format/type are one of the combinations from table 3.4.
-bool checkTextureFormatType(GLenum format, GLenum type)
+void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer)
 {
-    // validate <format> by itself (used as secondary key below)
-    switch (format)
-    {
-      case GL_RGBA:
-      case GL_BGRA_EXT:
-      case GL_RGB:
-      case GL_ALPHA:
-      case GL_LUMINANCE:
-      case GL_LUMINANCE_ALPHA:
-      case GL_DEPTH_COMPONENT:
-      case GL_DEPTH_STENCIL_OES:
-        break;
-      default:
-        return gl::error(GL_INVALID_ENUM, false);
-    }
+    return gl::BindRenderbuffer(target, renderbuffer);
+}
 
-    // invalid <type> -> sets INVALID_ENUM
-    // invalid <format>+<type> combination -> sets INVALID_OPERATION
-    switch (type)
-    {
-      case GL_UNSIGNED_BYTE:
-        switch (format)
-        {
-          case GL_RGBA:
-          case GL_BGRA_EXT:
-          case GL_RGB:
-          case GL_ALPHA:
-          case GL_LUMINANCE:
-          case GL_LUMINANCE_ALPHA:
-            return true;
-          default:
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
+void GL_APIENTRY glBindTexture(GLenum target, GLuint texture)
+{
+    return gl::BindTexture(target, texture);
+}
 
-      case GL_FLOAT:
-      case GL_HALF_FLOAT_OES:
-        switch (format)
-        {
-          case GL_RGBA:
-          case GL_RGB:
-          case GL_ALPHA:
-          case GL_LUMINANCE:
-          case GL_LUMINANCE_ALPHA:
-            return true;
-          default:
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
+void GL_APIENTRY glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+    return gl::BlendColor(red, green, blue, alpha);
+}
 
-      case GL_UNSIGNED_SHORT_4_4_4_4:
-      case GL_UNSIGNED_SHORT_5_5_5_1:
-        switch (format)
-        {
-          case GL_RGBA:
-            return true;
-          default:
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
+void GL_APIENTRY glBlendEquation(GLenum mode)
+{
+    return gl::BlendEquation(mode);
+}
 
-      case GL_UNSIGNED_SHORT_5_6_5:
-        switch (format)
-        {
-          case GL_RGB:
-            return true;
-          default:
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
+void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+    return gl::BlendEquationSeparate(modeRGB, modeAlpha);
+}
 
-      case GL_UNSIGNED_SHORT:
-      case GL_UNSIGNED_INT:
-        switch (format)
-        {
-          case GL_DEPTH_COMPONENT:
-            return true;
-          default:
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
+void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+    return gl::BlendFunc(sfactor, dfactor);
+}
 
-      case GL_UNSIGNED_INT_24_8_OES:
-        switch (format)
-        {
-          case GL_DEPTH_STENCIL_OES:
-            return true;
-          default:
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
+void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+    return gl::BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
 
-      default:
-        return gl::error(GL_INVALID_ENUM, false);
-    }
+void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
+{
+    return gl::BufferData(target, size, data, usage);
 }
 
-bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height,
-                              GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
-                              gl::Texture2D *texture)
+void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
 {
-    if (!texture)
-    {
-        return gl::error(GL_INVALID_OPERATION, false);
-    }
+    return gl::BufferSubData(target, offset, size, data);
+}
 
-    if (compressed != texture->isCompressed(level))
-    {
-        return gl::error(GL_INVALID_OPERATION, false);
-    }
+GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target)
+{
+    return gl::CheckFramebufferStatus(target);
+}
 
-    if (format != GL_NONE)
-    {
-        GLenum internalformat = gl::ConvertSizedInternalFormat(format, type);
-        if (internalformat != texture->getInternalFormat(level))
-        {
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
-    }
+void GL_APIENTRY glClear(GLbitfield mask)
+{
+    return gl::Clear(mask);
+}
 
-    if (compressed)
-    {
-        if ((width % 4 != 0 && width != texture->getWidth(0)) ||
-            (height % 4 != 0 && height != texture->getHeight(0)))
-        {
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
-    }
+void GL_APIENTRY glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+    return gl::ClearColor(red, green, blue, alpha);
+}
 
-    if (xoffset + width > texture->getWidth(level) ||
-        yoffset + height > texture->getHeight(level))
-    {
-        return gl::error(GL_INVALID_VALUE, false);
-    }
+void GL_APIENTRY glClearDepthf(GLfloat depth)
+{
+    return gl::ClearDepthf(depth);
+}
 
-    return true;
+void GL_APIENTRY glClearStencil(GLint s)
+{
+    return gl::ClearStencil(s);
 }
 
-bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height,
-                                GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
-                                gl::TextureCubeMap *texture)
+void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
 {
-    if (!texture)
-    {
-        return gl::error(GL_INVALID_OPERATION, false);
-    }
+    return gl::ColorMask(red, green, blue, alpha);
+}
 
-    if (compressed != texture->isCompressed(target, level))
-    {
-        return gl::error(GL_INVALID_OPERATION, false);
-    }
+void GL_APIENTRY glCompileShader(GLuint shader)
+{
+    return gl::CompileShader(shader);
+}
 
-    if (format != GL_NONE)
-    {
-        GLenum internalformat = gl::ConvertSizedInternalFormat(format, type);
-        if (internalformat != texture->getInternalFormat(target, level))
-        {
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
-    }
+void GL_APIENTRY glCompressedTexImage2D(GLenum target,
+                                        GLint level,
+                                        GLenum internalformat,
+                                        GLsizei width,
+                                        GLsizei height,
+                                        GLint border,
+                                        GLsizei imageSize,
+                                        const void *data)
+{
+    return gl::CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize,
+                                    data);
+}
 
-    if (compressed)
-    {
-        if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
-            (height % 4 != 0 && height != texture->getHeight(target, 0)))
-        {
-            return gl::error(GL_INVALID_OPERATION, false);
-        }
-    }
+void GL_APIENTRY glCompressedTexSubImage2D(GLenum target,
+                                           GLint level,
+                                           GLint xoffset,
+                                           GLint yoffset,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLenum format,
+                                           GLsizei imageSize,
+                                           const void *data)
+{
+    return gl::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+                                       imageSize, data);
+}
 
-    if (xoffset + width > texture->getWidth(target, level) ||
-        yoffset + height > texture->getHeight(target, level))
-    {
-        return gl::error(GL_INVALID_VALUE, false);
-    }
+void GL_APIENTRY glCopyTexImage2D(GLenum target,
+                                  GLint level,
+                                  GLenum internalformat,
+                                  GLint x,
+                                  GLint y,
+                                  GLsizei width,
+                                  GLsizei height,
+                                  GLint border)
+{
+    return gl::CopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+}
 
-    return true;
+void GL_APIENTRY glCopyTexSubImage2D(GLenum target,
+                                     GLint level,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLint x,
+                                     GLint y,
+                                     GLsizei width,
+                                     GLsizei height)
+{
+    return gl::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
 }
 
-// check for combinations of format and type that are valid for ReadPixels
-bool validReadFormatType(GLenum format, GLenum type)
+GLuint GL_APIENTRY glCreateProgram(void)
 {
-    switch (format)
-    {
-      case GL_RGBA:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-            break;
-          default:
-            return false;
-        }
-        break;
-      case GL_BGRA_EXT:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
-          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
-            break;
-          default:
-            return false;
-        }
-        break;
-      default:
-        return false;
-    }
-    return true;
+    return gl::CreateProgram();
 }
 
-extern "C"
+GLuint GL_APIENTRY glCreateShader(GLenum type)
 {
+    return gl::CreateShader(type);
+}
 
-void __stdcall glActiveTexture(GLenum texture)
+void GL_APIENTRY glCullFace(GLenum mode)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", texture);
-#else
-    EVENT("(GLenum texture = 0x%X)", texture);
-#endif
+    return gl::CullFace(mode);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint *buffers)
+{
+    return gl::DeleteBuffers(n, buffers);
+}
 
-        if (context)
-        {
-            if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1)
-            {
-                return gl::error(GL_INVALID_ENUM);
-            }
+void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
+{
+    return gl::DeleteFramebuffers(n, framebuffers);
+}
 
-            context->setActiveSampler(texture - GL_TEXTURE0);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glDeleteProgram(GLuint program)
+{
+    return gl::DeleteProgram(program);
 }
 
-void __stdcall glAttachShader(GLuint program, GLuint shader)
+void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d)", program, shader);
-#else
-    EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
-#endif
+    return gl::DeleteRenderbuffers(n, renderbuffers);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glDeleteShader(GLuint shader)
+{
+    return gl::DeleteShader(shader);
+}
 
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-            gl::Shader *shaderObject = context->getShader(shader);
+void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint *textures)
+{
+    return gl::DeleteTextures(n, textures);
+}
 
-            if (!programObject)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
+void GL_APIENTRY glDepthFunc(GLenum func)
+{
+    return gl::DepthFunc(func);
+}
 
-            if (!shaderObject)
-            {
-                if (context->getProgram(shader))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
+void GL_APIENTRY glDepthMask(GLboolean flag)
+{
+    return gl::DepthMask(flag);
+}
 
-            if (!programObject->attachShader(shaderObject))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glDepthRangef(GLfloat n, GLfloat f)
+{
+    return gl::DepthRangef(n, f);
 }
 
-void __stdcall glBeginQueryEXT(GLenum target, GLuint id)
+void GL_APIENTRY glDetachShader(GLuint program, GLuint shader)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d)", target, id);
-#else
-    EVENT("(GLenum target = 0x%X, GLuint %d)", target, id);
-#endif
+    return gl::DetachShader(program, shader);
+}
 
-    try
-    {
-        switch (target)
-        {
-          case GL_ANY_SAMPLES_PASSED_EXT: 
-          case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
-              break;
-          default: 
-              return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glDisable(GLenum cap)
+{
+    return gl::Disable(cap);
+}
 
-        if (id == 0)
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
+void GL_APIENTRY glDisableVertexAttribArray(GLuint index)
+{
+    return gl::DisableVertexAttribArray(index);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    return gl::DrawArrays(mode, first, count);
+}
 
-        if (context)
-        {
-            context->beginQuery(target, id);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
+{
+    return gl::DrawElements(mode, count, type, indices);
 }
 
-void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+void GL_APIENTRY glEnable(GLenum cap)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", program, index, name);
-#else
-    EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
-#endif
+    return gl::Enable(cap);
+}
 
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glEnableVertexAttribArray(GLuint index)
+{
+    return gl::EnableVertexAttribArray(index);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glFinish(void)
+{
+    return gl::Finish();
+}
 
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
+void GL_APIENTRY glFlush(void)
+{
+    return gl::Flush();
+}
 
-            if (!programObject)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
+void GL_APIENTRY glFramebufferRenderbuffer(GLenum target,
+                                           GLenum attachment,
+                                           GLenum renderbuffertarget,
+                                           GLuint renderbuffer)
+{
+    return gl::FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+}
 
-            if (strncmp(name, "gl_", 3) == 0)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
+void GL_APIENTRY glFramebufferTexture2D(GLenum target,
+                                        GLenum attachment,
+                                        GLenum textarget,
+                                        GLuint texture,
+                                        GLint level)
+{
+    return gl::FramebufferTexture2D(target, attachment, textarget, texture, level);
+}
 
-            programObject->bindAttributeLocation(index, name);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glFrontFace(GLenum mode)
+{
+    return gl::FrontFace(mode);
 }
 
-void __stdcall glBindBuffer(GLenum target, GLuint buffer)
+void GL_APIENTRY glGenBuffers(GLsizei n, GLuint *buffers)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d)", target, buffer);
-#else
-    EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
-#endif
+    return gl::GenBuffers(n, buffers);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGenerateMipmap(GLenum target)
+{
+    return gl::GenerateMipmap(target);
+}
 
-        if (context)
-        {
-            switch (target)
-            {
-              case GL_ARRAY_BUFFER:
-                context->bindArrayBuffer(buffer);
-                return;
-              case GL_ELEMENT_ARRAY_BUFFER:
-                context->bindElementArrayBuffer(buffer);
-                return;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint *framebuffers)
+{
+    return gl::GenFramebuffers(n, framebuffers);
 }
 
-void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
+void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint *renderbuffers)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d)", target, framebuffer);
-#else
-    EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
-#endif
+    return gl::GenRenderbuffers(n, renderbuffers);
+}
 
-    try
-    {
-        if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glGenTextures(GLsizei n, GLuint *textures)
+{
+    return gl::GenTextures(n, textures);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetActiveAttrib(GLuint program,
+                                   GLuint index,
+                                   GLsizei bufsize,
+                                   GLsizei *length,
+                                   GLint *size,
+                                   GLenum *type,
+                                   GLchar *name)
+{
+    return gl::GetActiveAttrib(program, index, bufsize, length, size, type, name);
+}
 
-        if (context)
-        {
-            if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
-            {
-                context->bindReadFramebuffer(framebuffer);
-            }
-            
-            if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
-            {
-                context->bindDrawFramebuffer(framebuffer);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetActiveUniform(GLuint program,
+                                    GLuint index,
+                                    GLsizei bufsize,
+                                    GLsizei *length,
+                                    GLint *size,
+                                    GLenum *type,
+                                    GLchar *name)
+{
+    return gl::GetActiveUniform(program, index, bufsize, length, size, type, name);
 }
 
-void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
+void GL_APIENTRY glGetAttachedShaders(GLuint program,
+                                      GLsizei maxcount,
+                                      GLsizei *count,
+                                      GLuint *shaders)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d)", target, renderbuffer);
-#else
-    EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
-#endif
+    return gl::GetAttachedShaders(program, maxcount, count, shaders);
+}
 
-    try
-    {
-        if (target != GL_RENDERBUFFER)
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
+GLint GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar *name)
+{
+    return gl::GetAttribLocation(program, name);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean *params)
+{
+    return gl::GetBooleanv(pname, params);
+}
 
-        if (context)
-        {
-            context->bindRenderbuffer(renderbuffer);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    return gl::GetBufferParameteriv(target, pname, params);
 }
 
-void __stdcall glBindTexture(GLenum target, GLuint texture)
+GLenum GL_APIENTRY glGetError(void)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d)", target, texture);
-#else
-    EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
-#endif
+    return gl::GetError();
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat *params)
+{
+    return gl::GetFloatv(pname, params);
+}
 
-        if (context)
-        {
-            gl::Texture *textureObject = context->getTexture(texture);
+void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target,
+                                                       GLenum attachment,
+                                                       GLenum pname,
+                                                       GLint *params)
+{
+    return gl::GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
+}
 
-            if (textureObject && textureObject->getTarget() != target && texture != 0)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
+void GL_APIENTRY glGetIntegerv(GLenum pname, GLint *params)
+{
+    return gl::GetIntegerv(pname, params);
+}
 
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                context->bindTexture2D(texture);
-                return;
-              case GL_TEXTURE_CUBE_MAP:
-                context->bindTextureCubeMap(texture);
-                return;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint *params)
+{
+    return gl::GetProgramiv(program, pname, params);
 }
 
-void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+void GL_APIENTRY glGetProgramInfoLog(GLuint program,
+                                     GLsizei bufsize,
+                                     GLsizei *length,
+                                     GLchar *infolog)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%f, %f, %f, %f)",
-          red, green, blue, alpha);
-#else
-    EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
-          red, green, blue, alpha);
-#endif
+    return gl::GetProgramInfoLog(program, bufsize, length, infolog);
+}
 
-    try
-    {
-        gl::Context* context = gl::getNonLostContext();
+void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    return gl::GetRenderbufferParameteriv(target, pname, params);
+}
 
-        if (context)
-        {
-            context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
+{
+    return gl::GetShaderiv(shader, pname, params);
 }
 
-void __stdcall glBlendEquation(GLenum mode)
+void GL_APIENTRY glGetShaderInfoLog(GLuint shader,
+                                    GLsizei bufsize,
+                                    GLsizei *length,
+                                    GLchar *infolog)
 {
-    glBlendEquationSeparate(mode, mode);
+    return gl::GetShaderInfoLog(shader, bufsize, length, infolog);
 }
 
-void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype,
+                                            GLenum precisiontype,
+                                            GLint *range,
+                                            GLint *precision)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X)", modeRGB, modeAlpha);
-#else
-    EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
-#endif
+    return gl::GetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+}
 
-    try
-    {
-        switch (modeRGB)
-        {
-          case GL_FUNC_ADD:
-          case GL_FUNC_SUBTRACT:
-          case GL_FUNC_REVERSE_SUBTRACT:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
+{
+    return gl::GetShaderSource(shader, bufsize, length, source);
+}
 
-        switch (modeAlpha)
-        {
-          case GL_FUNC_ADD:
-          case GL_FUNC_SUBTRACT:
-          case GL_FUNC_REVERSE_SUBTRACT:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+const GLubyte *GL_APIENTRY glGetString(GLenum name)
+{
+    return gl::GetString(name);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+    return gl::GetTexParameterfv(target, pname, params);
+}
 
-        if (context)
-        {
-            context->setBlendEquation(modeRGB, modeAlpha);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+    return gl::GetTexParameteriv(target, pname, params);
 }
 
-void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor)
+void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat *params)
 {
-    glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
+    return gl::GetUniformfv(program, location, params);
 }
 
-void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint *params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%X, 0x%X)",
-          srcRGB, dstRGB, srcAlpha, dstAlpha);
-#else
-    EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
-          srcRGB, dstRGB, srcAlpha, dstAlpha);
-#endif
+    return gl::GetUniformiv(program, location, params);
+}
 
-    try
-    {
-        switch (srcRGB)
-        {
-          case GL_ZERO:
-          case GL_ONE:
-          case GL_SRC_COLOR:
-          case GL_ONE_MINUS_SRC_COLOR:
-          case GL_DST_COLOR:
-          case GL_ONE_MINUS_DST_COLOR:
-          case GL_SRC_ALPHA:
-          case GL_ONE_MINUS_SRC_ALPHA:
-          case GL_DST_ALPHA:
-          case GL_ONE_MINUS_DST_ALPHA:
-          case GL_CONSTANT_COLOR:
-          case GL_ONE_MINUS_CONSTANT_COLOR:
-          case GL_CONSTANT_ALPHA:
-          case GL_ONE_MINUS_CONSTANT_ALPHA:
-          case GL_SRC_ALPHA_SATURATE:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar *name)
+{
+    return gl::GetUniformLocation(program, name);
+}
 
-        switch (dstRGB)
-        {
-          case GL_ZERO:
-          case GL_ONE:
-          case GL_SRC_COLOR:
-          case GL_ONE_MINUS_SRC_COLOR:
-          case GL_DST_COLOR:
-          case GL_ONE_MINUS_DST_COLOR:
-          case GL_SRC_ALPHA:
-          case GL_ONE_MINUS_SRC_ALPHA:
-          case GL_DST_ALPHA:
-          case GL_ONE_MINUS_DST_ALPHA:
-          case GL_CONSTANT_COLOR:
-          case GL_ONE_MINUS_CONSTANT_COLOR:
-          case GL_CONSTANT_ALPHA:
-          case GL_ONE_MINUS_CONSTANT_ALPHA:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
+{
+    return gl::GetVertexAttribfv(index, pname, params);
+}
 
-        switch (srcAlpha)
-        {
-          case GL_ZERO:
-          case GL_ONE:
-          case GL_SRC_COLOR:
-          case GL_ONE_MINUS_SRC_COLOR:
-          case GL_DST_COLOR:
-          case GL_ONE_MINUS_DST_COLOR:
-          case GL_SRC_ALPHA:
-          case GL_ONE_MINUS_SRC_ALPHA:
-          case GL_DST_ALPHA:
-          case GL_ONE_MINUS_DST_ALPHA:
-          case GL_CONSTANT_COLOR:
-          case GL_ONE_MINUS_CONSTANT_COLOR:
-          case GL_CONSTANT_ALPHA:
-          case GL_ONE_MINUS_CONSTANT_ALPHA:
-          case GL_SRC_ALPHA_SATURATE:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
+{
+    return gl::GetVertexAttribiv(index, pname, params);
+}
 
-        switch (dstAlpha)
-        {
-          case GL_ZERO:
-          case GL_ONE:
-          case GL_SRC_COLOR:
-          case GL_ONE_MINUS_SRC_COLOR:
-          case GL_DST_COLOR:
-          case GL_ONE_MINUS_DST_COLOR:
-          case GL_SRC_ALPHA:
-          case GL_ONE_MINUS_SRC_ALPHA:
-          case GL_DST_ALPHA:
-          case GL_ONE_MINUS_DST_ALPHA:
-          case GL_CONSTANT_COLOR:
-          case GL_ONE_MINUS_CONSTANT_COLOR:
-          case GL_CONSTANT_ALPHA:
-          case GL_ONE_MINUS_CONSTANT_ALPHA:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer)
+{
+    return gl::GetVertexAttribPointerv(index, pname, pointer);
+}
 
-        bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
-                                  dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
+void GL_APIENTRY glHint(GLenum target, GLenum mode)
+{
+    return gl::Hint(target, mode);
+}
 
-        bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
-                                  dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
+GLboolean GL_APIENTRY glIsBuffer(GLuint buffer)
+{
+    return gl::IsBuffer(buffer);
+}
 
-        if (constantColorUsed && constantAlphaUsed)
-        {
-            ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL");
-            return gl::error(GL_INVALID_OPERATION);
-        }
+GLboolean GL_APIENTRY glIsEnabled(GLenum cap)
+{
+    return gl::IsEnabled(cap);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer)
+{
+    return gl::IsFramebuffer(framebuffer);
+}
 
-        if (context)
-        {
-            context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+GLboolean GL_APIENTRY glIsProgram(GLuint program)
+{
+    return gl::IsProgram(program);
 }
 
-void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, 0x%0.8p, %d)",
-          target, size, data, usage);
-#else
-    EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
-          target, size, data, usage);
-#endif
+    return gl::IsRenderbuffer(renderbuffer);
+}
 
-    try
-    {
-        if (size < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+GLboolean GL_APIENTRY glIsShader(GLuint shader)
+{
+    return gl::IsShader(shader);
+}
 
-        switch (usage)
-        {
-          case GL_STREAM_DRAW:
-          case GL_STATIC_DRAW:
-          case GL_DYNAMIC_DRAW:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+GLboolean GL_APIENTRY glIsTexture(GLuint texture)
+{
+    return gl::IsTexture(texture);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glLineWidth(GLfloat width)
+{
+    return gl::LineWidth(width);
+}
 
-        if (context)
-        {
-            gl::Buffer *buffer;
+void GL_APIENTRY glLinkProgram(GLuint program)
+{
+    return gl::LinkProgram(program);
+}
 
-            switch (target)
-            {
-              case GL_ARRAY_BUFFER:
-                buffer = context->getArrayBuffer();
-                break;
-              case GL_ELEMENT_ARRAY_BUFFER:
-                buffer = context->getElementArrayBuffer();
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
+void GL_APIENTRY glPixelStorei(GLenum pname, GLint param)
+{
+    return gl::PixelStorei(pname, param);
+}
 
-            if (!buffer)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
+void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units)
+{
+    return gl::PolygonOffset(factor, units);
+}
 
-            buffer->bufferData(data, size, usage);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glReadPixels(GLint x,
+                              GLint y,
+                              GLsizei width,
+                              GLsizei height,
+                              GLenum format,
+                              GLenum type,
+                              void *pixels)
+{
+    return gl::ReadPixels(x, y, width, height, format, type, pixels);
 }
 
-void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+void GL_APIENTRY glReleaseShaderCompiler(void)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, %d, 0x%0.8p)",
-          target, offset, size, data);
-#else
-    EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
-          target, offset, size, data);
-#endif
+    return gl::ReleaseShaderCompiler();
+}
 
-    try
-    {
-        if (size < 0 || offset < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glRenderbufferStorage(GLenum target,
+                                       GLenum internalformat,
+                                       GLsizei width,
+                                       GLsizei height)
+{
+    return gl::RenderbufferStorage(target, internalformat, width, height);
+}
 
-        if (data == NULL)
-        {
-            return;
-        }
+void GL_APIENTRY glSampleCoverage(GLfloat value, GLboolean invert)
+{
+    return gl::SampleCoverage(value, invert);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    return gl::Scissor(x, y, width, height);
+}
 
-        if (context)
-        {
-            gl::Buffer *buffer;
+void GL_APIENTRY glShaderBinary(GLsizei n,
+                                const GLuint *shaders,
+                                GLenum binaryformat,
+                                const void *binary,
+                                GLsizei length)
+{
+    return gl::ShaderBinary(n, shaders, binaryformat, binary, length);
+}
 
-            switch (target)
-            {
-              case GL_ARRAY_BUFFER:
-                buffer = context->getArrayBuffer();
-                break;
-              case GL_ELEMENT_ARRAY_BUFFER:
-                buffer = context->getElementArrayBuffer();
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
+void GL_APIENTRY glShaderSource(GLuint shader,
+                                GLsizei count,
+                                const GLchar *const *string,
+                                const GLint *length)
+{
+    return gl::ShaderSource(shader, count, string, length);
+}
 
-            if (!buffer)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
+void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+    return gl::StencilFunc(func, ref, mask);
+}
 
-            if ((size_t)size + offset > buffer->size())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
+void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+    return gl::StencilFuncSeparate(face, func, ref, mask);
+}
 
-            buffer->bufferSubData(data, size, offset);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glStencilMask(GLuint mask)
+{
+    return gl::StencilMask(mask);
 }
 
-GLenum __stdcall glCheckFramebufferStatus(GLenum target)
+void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", target);
-#else
-    EVENT("(GLenum target = 0x%X)", target);
-#endif
+    return gl::StencilMaskSeparate(face, mask);
+}
 
-    try
-    {
-        if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
-        {
-            return gl::error(GL_INVALID_ENUM, 0);
-        }
+void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+    return gl::StencilOp(fail, zfail, zpass);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+    return gl::StencilOpSeparate(face, fail, zfail, zpass);
+}
 
-        if (context)
-        {
-            gl::Framebuffer *framebuffer = NULL;
-            if (target == GL_READ_FRAMEBUFFER_ANGLE)
-            {
-                framebuffer = context->getReadFramebuffer();
-            }
-            else
-            {
-                framebuffer = context->getDrawFramebuffer();
-            }
+void GL_APIENTRY glTexImage2D(GLenum target,
+                              GLint level,
+                              GLint internalformat,
+                              GLsizei width,
+                              GLsizei height,
+                              GLint border,
+                              GLenum format,
+                              GLenum type,
+                              const void *pixels)
+{
+    return gl::TexImage2D(target, level, internalformat, width, height, border, format, type,
+                          pixels);
+}
 
-            return framebuffer->completeness();
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, 0);
-    }
+void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+    return gl::TexParameterf(target, pname, param);
+}
 
-    return 0;
+void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+    return gl::TexParameterfv(target, pname, params);
 }
 
-void __stdcall glClear(GLbitfield mask)
+void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%X)", mask);
-#else
-    EVENT("(GLbitfield mask = %X)", mask);
-#endif
+    return gl::TexParameteri(target, pname, param);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+    return gl::TexParameteriv(target, pname, params);
+}
 
-        if (context)
-        {
-            context->clear(mask);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glTexSubImage2D(GLenum target,
+                                 GLint level,
+                                 GLint xoffset,
+                                 GLint yoffset,
+                                 GLsizei width,
+                                 GLsizei height,
+                                 GLenum format,
+                                 GLenum type,
+                                 const void *pixels)
+{
+    return gl::TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
 }
 
-void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+void GL_APIENTRY glUniform1f(GLint location, GLfloat x)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%f, %f, %f, %f)",
-          red, green, blue, alpha);
-#else
-    EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
-          red, green, blue, alpha);
-#endif
+    return gl::Uniform1f(location, x);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    return gl::Uniform1fv(location, count, v);
+}
 
-        if (context)
-        {
-            context->setClearColor(red, green, blue, alpha);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glUniform1i(GLint location, GLint x)
+{
+    return gl::Uniform1i(location, x);
 }
 
-void __stdcall glClearDepthf(GLclampf depth)
+void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint *v)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%f)", depth);
-#else
-    EVENT("(GLclampf depth = %f)", depth);
-#endif
+    return gl::Uniform1iv(location, count, v);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+    return gl::Uniform2f(location, x, y);
+}
 
-        if (context)
-        {
-            context->setClearDepth(depth);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    return gl::Uniform2fv(location, count, v);
 }
 
-void __stdcall glClearStencil(GLint s)
+void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", s);
-#else
-    EVENT("(GLint s = %d)", s);
-#endif
+    return gl::Uniform2i(location, x, y);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+    return gl::Uniform2iv(location, count, v);
+}
 
-        if (context)
-        {
-            context->setClearStencil(s);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+    return gl::Uniform3f(location, x, y, z);
 }
 
-void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat *v)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, %d)",
-          red, green, blue, alpha);
-#else
-    EVENT("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
-          red, green, blue, alpha);
-#endif
+    return gl::Uniform3fv(location, count, v);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+    return gl::Uniform3i(location, x, y, z);
+}
 
-        if (context)
-        {
-            context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+    return gl::Uniform3iv(location, count, v);
 }
 
-void __stdcall glCompileShader(GLuint shader)
+void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", shader);
-#else
-    EVENT("(GLuint shader = %d)", shader);
-#endif
+    return gl::Uniform4f(location, x, y, z, w);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    return gl::Uniform4fv(location, count, v);
+}
 
-        if (context)
-        {
-            gl::Shader *shaderObject = context->getShader(shader);
+void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+    return gl::Uniform4i(location, x, y, z, w);
+}
 
-            if (!shaderObject)
-            {
-                if (context->getProgram(shader))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
+void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+    return gl::Uniform4iv(location, count, v);
+}
 
-            shaderObject->compile();
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glUniformMatrix2fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    return gl::UniformMatrix2fv(location, count, transpose, value);
 }
 
-void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, 
-                                      GLint border, GLsizei imageSize, const GLvoid* data)
+void GL_APIENTRY glUniformMatrix3fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, 0x%X, %d, %d, %d, %d, 0x%0.8p)",
-          target, level, internalformat, width, height, border, imageSize, data);
-#else
-    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " 
-          "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
-          target, level, internalformat, width, height, border, imageSize, data);
-#endif
+    return gl::UniformMatrix3fv(location, count, transpose, value);
+}
 
-    try
-    {
-        if (!validImageSize(level, width, height) || border != 0 || imageSize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glUniformMatrix4fv(GLint location,
+                                    GLsizei count,
+                                    GLboolean transpose,
+                                    const GLfloat *value)
+{
+    return gl::UniformMatrix4fv(location, count, transpose, value);
+}
 
-        switch (internalformat)
-        {
-          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glUseProgram(GLuint program)
+{
+    return gl::UseProgram(program);
+}
 
-        if (border != 0)
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
+void GL_APIENTRY glValidateProgram(GLuint program)
+{
+    return gl::ValidateProgram(program);
+}
 
-        if (width != 1 && width != 2 && width % 4 != 0)
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
+void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x)
+{
+    return gl::VertexAttrib1f(indx, x);
+}
 
-        if (height != 1 && height != 2 && height % 4 != 0)
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
+void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat *values)
+{
+    return gl::VertexAttrib1fv(indx, values);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+{
+    return gl::VertexAttrib2f(indx, x, y);
+}
 
-        if (context)
-        {
-            if (level > context->getMaximumTextureLevel())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
+void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat *values)
+{
+    return gl::VertexAttrib2fv(indx, values);
+}
 
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                if (width > (context->getMaximumTextureDimension() >> level) ||
-                    height > (context->getMaximumTextureDimension() >> level))
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-                if (width != height)
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
+void GL_APIENTRY glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+{
+    return gl::VertexAttrib3f(indx, x, y, z);
+}
 
-                if (width > (context->getMaximumCubeTextureDimension() >> level) ||
-                    height > (context->getMaximumCubeTextureDimension() >> level))
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
+void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat *values)
+{
+    return gl::VertexAttrib3fv(indx, values);
+}
 
-            switch (internalformat) {
-              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-                if (!context->supportsDXT1Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-                if (!context->supportsDXT3Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-                if (!context->supportsDXT5Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
-                }
-                break;
-              default: UNREACHABLE();
-            }
+void GL_APIENTRY glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    return gl::VertexAttrib4f(indx, x, y, z, w);
+}
 
-            if (imageSize != gl::ComputeCompressedSize(width, height, internalformat))
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
+void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat *values)
+{
+    return gl::VertexAttrib4fv(indx, values);
+}
 
-            if (target == GL_TEXTURE_2D)
-            {
-                gl::Texture2D *texture = context->getTexture2D();
+void GL_APIENTRY glVertexAttribPointer(GLuint indx,
+                                       GLint size,
+                                       GLenum type,
+                                       GLboolean normalized,
+                                       GLsizei stride,
+                                       const void *ptr)
+{
+    return gl::VertexAttribPointer(indx, size, type, normalized, stride, ptr);
+}
 
-                if (!texture)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
+void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    return gl::Viewport(x, y, width, height);
+}
 
-                if (texture->isImmutable())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
+void GL_APIENTRY glReadBuffer(GLenum mode)
+{
+    return gl::ReadBuffer(mode);
+}
 
-                texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
-            }
-            else
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
+void GL_APIENTRY glDrawRangeElements(GLenum mode,
+                                     GLuint start,
+                                     GLuint end,
+                                     GLsizei count,
+                                     GLenum type,
+                                     const void *indices)
+{
+    return gl::DrawRangeElements(mode, start, end, count, type, indices);
+}
 
-                if (!texture)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
+void GL_APIENTRY glTexImage3D(GLenum target,
+                              GLint level,
+                              GLint internalformat,
+                              GLsizei width,
+                              GLsizei height,
+                              GLsizei depth,
+                              GLint border,
+                              GLenum format,
+                              GLenum type,
+                              const void *pixels)
+{
+    return gl::TexImage3D(target, level, internalformat, width, height, depth, border, format, type,
+                          pixels);
+}
 
-                if (texture->isImmutable())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
+void GL_APIENTRY glTexSubImage3D(GLenum target,
+                                 GLint level,
+                                 GLint xoffset,
+                                 GLint yoffset,
+                                 GLint zoffset,
+                                 GLsizei width,
+                                 GLsizei height,
+                                 GLsizei depth,
+                                 GLenum format,
+                                 GLenum type,
+                                 const void *pixels)
+{
+    return gl::TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format,
+                             type, pixels);
+}
 
-                switch (target)
-                {
-                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-                    texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
-                    break;
-                  default: UNREACHABLE();
-                }
-            }
-        }
+void GL_APIENTRY glCopyTexSubImage3D(GLenum target,
+                                     GLint level,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLint zoffset,
+                                     GLint x,
+                                     GLint y,
+                                     GLsizei width,
+                                     GLsizei height)
+{
+    return gl::CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
+}
 
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glCompressedTexImage3D(GLenum target,
+                                        GLint level,
+                                        GLenum internalformat,
+                                        GLsizei width,
+                                        GLsizei height,
+                                        GLsizei depth,
+                                        GLint border,
+                                        GLsizei imageSize,
+                                        const void *data)
+{
+    return gl::CompressedTexImage3D(target, level, internalformat, width, height, depth, border,
+                                    imageSize, data);
 }
 
-void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                         GLenum format, GLsizei imageSize, const GLvoid* data)
+void GL_APIENTRY glCompressedTexSubImage3D(GLenum target,
+                                           GLint level,
+                                           GLint xoffset,
+                                           GLint yoffset,
+                                           GLint zoffset,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLsizei depth,
+                                           GLenum format,
+                                           GLsizei imageSize,
+                                           const void *data)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, %d, %d, %d, %d, 0x%X, %d, 0x%0.8p)",
-          target, level, xoffset, yoffset, width, height, format, imageSize, data);
-#else
-    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
-          "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
-          "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
-          target, level, xoffset, yoffset, width, height, format, imageSize, data);
-#endif
+    return gl::CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
+                                       depth, format, imageSize, data);
+}
 
-    try
-    {
-        if (!gl::IsInternalTextureTarget(target))
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glGenQueries(GLsizei n, GLuint *ids)
+{
+    return gl::GenQueries(n, ids);
+}
 
-        if (xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint *ids)
+{
+    return gl::DeleteQueries(n, ids);
+}
 
-        switch (format)
-        {
-          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+GLboolean GL_APIENTRY glIsQuery(GLuint id)
+{
+    return gl::IsQuery(id);
+}
 
-        if (width == 0 || height == 0 || data == NULL)
-        {
-            return;
-        }
+void GL_APIENTRY glBeginQuery(GLenum target, GLuint id)
+{
+    return gl::BeginQuery(target, id);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glEndQuery(GLenum target)
+{
+    return gl::EndQuery(target);
+}
 
-        if (context)
-        {
-            if (level > context->getMaximumTextureLevel())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
+void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint *params)
+{
+    return gl::GetQueryiv(target, pname, params);
+}
 
-            switch (format) {
-              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-                if (!context->supportsDXT1Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-                if (!context->supportsDXT3Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-                if (!context->supportsDXT5Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
-                }
-                break;
-              default: UNREACHABLE();
-            }
+void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
+{
+    return gl::GetQueryObjectuiv(id, pname, params);
+}
 
-            if (imageSize != gl::ComputeCompressedSize(width, height, format))
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
+GLboolean GL_APIENTRY glUnmapBuffer(GLenum target)
+{
+    return gl::UnmapBuffer(target);
+}
 
-            if (xoffset % 4 != 0 || yoffset % 4 != 0)
-            {
-                return gl::error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction
-                                                    // does not exist unless DXT textures are supported.
-            }
+void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, void **params)
+{
+    return gl::GetBufferPointerv(target, pname, params);
+}
 
-            if (target == GL_TEXTURE_2D)
-            {
-                gl::Texture2D *texture = context->getTexture2D();
-                if (validateSubImageParams2D(true, width, height, xoffset, yoffset, level, format, GL_NONE, texture))
-                {
-                    texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
-                }
-            }
-            else if (gl::IsCubemapTextureTarget(target))
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                if (validateSubImageParamsCube(true, width, height, xoffset, yoffset, target, level, format, GL_NONE, texture))
-                {
-                    texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
-                }
-            }
-            else
-            {
-                UNREACHABLE();
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum *bufs)
+{
+    return gl::DrawBuffers(n, bufs);
 }
 
-void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+void GL_APIENTRY glUniformMatrix2x3fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, 0x%X, %d, %d, %d, %d, %d)",
-          target, level, internalformat, x, y, width, height, border);
-#else
-    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
-          "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
-          target, level, internalformat, x, y, width, height, border);
-#endif
+    return gl::UniformMatrix2x3fv(location, count, transpose, value);
+}
 
-    try
-    {
-        if (!validImageSize(level, width, height))
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glUniformMatrix3x2fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    return gl::UniformMatrix3x2fv(location, count, transpose, value);
+}
 
-        if (border != 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glUniformMatrix2x4fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    return gl::UniformMatrix2x4fv(location, count, transpose, value);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glUniformMatrix4x2fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    return gl::UniformMatrix4x2fv(location, count, transpose, value);
+}
 
-        if (context)
-        {
-            if (level > context->getMaximumTextureLevel())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
+void GL_APIENTRY glUniformMatrix3x4fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    return gl::UniformMatrix3x4fv(location, count, transpose, value);
+}
 
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                if (width > (context->getMaximumTextureDimension() >> level) ||
-                    height > (context->getMaximumTextureDimension() >> level))
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-                if (width != height)
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
+void GL_APIENTRY glUniformMatrix4x3fv(GLint location,
+                                      GLsizei count,
+                                      GLboolean transpose,
+                                      const GLfloat *value)
+{
+    return gl::UniformMatrix4x3fv(location, count, transpose, value);
+}
 
-                if (width > (context->getMaximumCubeTextureDimension() >> level) ||
-                    height > (context->getMaximumCubeTextureDimension() >> level))
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
+void GL_APIENTRY glBlitFramebuffer(GLint srcX0,
+                                   GLint srcY0,
+                                   GLint srcX1,
+                                   GLint srcY1,
+                                   GLint dstX0,
+                                   GLint dstY0,
+                                   GLint dstX1,
+                                   GLint dstY1,
+                                   GLbitfield mask,
+                                   GLenum filter)
+{
+    return gl::BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
+                               filter);
+}
 
-            gl::Framebuffer *framebuffer = context->getReadFramebuffer();
+void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target,
+                                                  GLsizei samples,
+                                                  GLenum internalformat,
+                                                  GLsizei width,
+                                                  GLsizei height)
+{
+    return gl::RenderbufferStorageMultisample(target, samples, internalformat, width, height);
+}
 
-            if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
-            {
-                return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
-            }
+void GL_APIENTRY glFramebufferTextureLayer(GLenum target,
+                                           GLenum attachment,
+                                           GLuint texture,
+                                           GLint level,
+                                           GLint layer)
+{
+    return gl::FramebufferTextureLayer(target, attachment, texture, level, layer);
+}
 
-            if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
+void *GL_APIENTRY glMapBufferRange(GLenum target,
+                                   GLintptr offset,
+                                   GLsizeiptr length,
+                                   GLbitfield access)
+{
+    return gl::MapBufferRange(target, offset, length, access);
+}
 
-            gl::Renderbuffer *source = framebuffer->getReadColorbuffer();
-            GLenum colorbufferFormat = source->getInternalFormat();
+void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+    return gl::FlushMappedBufferRange(target, offset, length);
+}
 
-            // [OpenGL ES 2.0.24] table 3.9
-            switch (internalformat)
-            {
-              case GL_ALPHA:
-                if (colorbufferFormat != GL_ALPHA8_EXT &&
-                    colorbufferFormat != GL_RGBA4 &&
-                    colorbufferFormat != GL_RGB5_A1 &&
-                    colorbufferFormat != GL_BGRA8_EXT &&
-                    colorbufferFormat != GL_RGBA8_OES)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                break;
-              case GL_LUMINANCE:
-              case GL_RGB:
-                if (colorbufferFormat != GL_RGB565 &&
-                    colorbufferFormat != GL_RGB8_OES &&
-                    colorbufferFormat != GL_RGBA4 &&
-                    colorbufferFormat != GL_RGB5_A1 &&
-                    colorbufferFormat != GL_BGRA8_EXT &&
-                    colorbufferFormat != GL_RGBA8_OES)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                break;
-              case GL_LUMINANCE_ALPHA:
-              case GL_RGBA:
-                if (colorbufferFormat != GL_RGBA4 &&
-                    colorbufferFormat != GL_RGB5_A1 &&
-                    colorbufferFormat != GL_BGRA8_EXT &&
-                    colorbufferFormat != GL_RGBA8_OES)
-                 {
-                     return gl::error(GL_INVALID_OPERATION);
-                 }
-                 break;
-              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-                if (context->supportsDXT1Textures())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-                if (context->supportsDXT3Textures())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-                if (context->supportsDXT5Textures())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_DEPTH_COMPONENT:
-              case GL_DEPTH_COMPONENT16:
-              case GL_DEPTH_COMPONENT32_OES:
-              case GL_DEPTH_STENCIL_OES:
-              case GL_DEPTH24_STENCIL8_OES:
-                  if (context->supportsDepthTextures())
-                  {
-                      return gl::error(GL_INVALID_OPERATION);
-                  }
-                  else
-                  {
-                      return gl::error(GL_INVALID_ENUM);
-                  }
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
+void GL_APIENTRY glBindVertexArray(GLuint array)
+{
+    return gl::BindVertexArray(array);
+}
 
-            if (target == GL_TEXTURE_2D)
-            {
-                gl::Texture2D *texture = context->getTexture2D();
+void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint *arrays)
+{
+    return gl::DeleteVertexArrays(n, arrays);
+}
 
-                if (!texture)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
+void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint *arrays)
+{
+    return gl::GenVertexArrays(n, arrays);
+}
 
-                if (texture->isImmutable())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
+GLboolean GL_APIENTRY glIsVertexArray(GLuint array)
+{
+    return gl::IsVertexArray(array);
+}
 
-                texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
-            }
-            else if (gl::IsCubemapTextureTarget(target))
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
+void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint *data)
+{
+    return gl::GetIntegeri_v(target, index, data);
+}
 
-                if (!texture)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
+void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode)
+{
+    return gl::BeginTransformFeedback(primitiveMode);
+}
 
-                if (texture->isImmutable())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
+void GL_APIENTRY glEndTransformFeedback(void)
+{
+    return gl::EndTransformFeedback();
+}
 
-                texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
-            }
-            else UNREACHABLE();
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY
+glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
+{
+    return gl::BindBufferRange(target, index, buffer, offset, size);
 }
 
-void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, %d, %d, %d, %d, %d, %d)",
-          target, level, xoffset, yoffset, x, y, width, height);
-#else
-    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
-          "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
-          target, level, xoffset, yoffset, x, y, width, height);
-#endif
+    return gl::BindBufferBase(target, index, buffer);
+}
 
-    try
-    {
-        if (!gl::IsInternalTextureTarget(target))
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glTransformFeedbackVaryings(GLuint program,
+                                             GLsizei count,
+                                             const GLchar *const *varyings,
+                                             GLenum bufferMode)
+{
+    return gl::TransformFeedbackVaryings(program, count, varyings, bufferMode);
+}
 
-        if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (width == 0 || height == 0)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (level > context->getMaximumTextureLevel())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            gl::Framebuffer *framebuffer = context->getReadFramebuffer();
-
-            if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
-            {
-                return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
-            }
-
-            if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            gl::Renderbuffer *source = framebuffer->getReadColorbuffer();
-            GLenum colorbufferFormat = source->getInternalFormat();
-            gl::Texture *texture = NULL;
-            GLenum textureFormat = GL_RGBA;
-
-            if (target == GL_TEXTURE_2D)
-            {
-                gl::Texture2D *tex2d = context->getTexture2D();
-
-                if (!validateSubImageParams2D(false, width, height, xoffset, yoffset, level, GL_NONE, GL_NONE, tex2d))
-                {
-                    return; // error already registered by validateSubImageParams
-                }
-                textureFormat = gl::ExtractFormat(tex2d->getInternalFormat(level));
-                texture = tex2d;
-            }
-            else if (gl::IsCubemapTextureTarget(target))
-            {
-                gl::TextureCubeMap *texcube = context->getTextureCubeMap();
-
-                if (!validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, GL_NONE, GL_NONE, texcube))
-                {
-                    return; // error already registered by validateSubImageParams
-                }
-                textureFormat = gl::ExtractFormat(texcube->getInternalFormat(target, level));
-                texture = texcube;
-            }
-            else UNREACHABLE();
-
-            // [OpenGL ES 2.0.24] table 3.9
-            switch (textureFormat)
-            {
-              case GL_ALPHA:
-                if (colorbufferFormat != GL_ALPHA8_EXT &&
-                    colorbufferFormat != GL_RGBA4 &&
-                    colorbufferFormat != GL_RGB5_A1 &&
-                    colorbufferFormat != GL_RGBA8_OES)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                break;
-              case GL_LUMINANCE:
-              case GL_RGB:
-                if (colorbufferFormat != GL_RGB565 &&
-                    colorbufferFormat != GL_RGB8_OES &&
-                    colorbufferFormat != GL_RGBA4 &&
-                    colorbufferFormat != GL_RGB5_A1 &&
-                    colorbufferFormat != GL_RGBA8_OES)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                break;
-              case GL_LUMINANCE_ALPHA:
-              case GL_RGBA:
-                if (colorbufferFormat != GL_RGBA4 &&
-                    colorbufferFormat != GL_RGB5_A1 &&
-                    colorbufferFormat != GL_RGBA8_OES)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                break;
-              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-                return gl::error(GL_INVALID_OPERATION);
-              case GL_DEPTH_COMPONENT:
-              case GL_DEPTH_STENCIL_OES:
-                return gl::error(GL_INVALID_OPERATION);
-              default:
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer);
-        }
-    }
+void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program,
+                                               GLuint index,
+                                               GLsizei bufSize,
+                                               GLsizei *length,
+                                               GLsizei *size,
+                                               GLenum *type,
+                                               GLchar *name)
+{
+    return gl::GetTransformFeedbackVarying(program, index, bufSize, length, size, type, name);
+}
 
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY
+glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
+{
+    return gl::VertexAttribIPointer(index, size, type, stride, pointer);
 }
 
-GLuint __stdcall glCreateProgram(void)
+void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
 {
-    EVENT("()");
+    return gl::GetVertexAttribIiv(index, pname, params);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
+{
+    return gl::GetVertexAttribIuiv(index, pname, params);
+}
 
-        if (context)
-        {
-            return context->createProgram();
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, 0);
-    }
+void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+    return gl::VertexAttribI4i(index, x, y, z, w);
+}
 
-    return 0;
+void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+    return gl::VertexAttribI4ui(index, x, y, z, w);
 }
 
-GLuint __stdcall glCreateShader(GLenum type)
+void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint *v)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", type);
-#else
-    EVENT("(GLenum type = 0x%X)", type);
-#endif
+    return gl::VertexAttribI4iv(index, v);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint *v)
+{
+    return gl::VertexAttribI4uiv(index, v);
+}
 
-        if (context)
-        {
-            switch (type)
-            {
-              case GL_FRAGMENT_SHADER:
-              case GL_VERTEX_SHADER:
-                return context->createShader(type);
-              default:
-                return gl::error(GL_INVALID_ENUM, 0);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, 0);
-    }
+void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint *params)
+{
+    return gl::GetUniformuiv(program, location, params);
+}
 
-    return 0;
+GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name)
+{
+    return gl::GetFragDataLocation(program, name);
 }
 
-void __stdcall glCullFace(GLenum mode)
+void GL_APIENTRY glUniform1ui(GLint location, GLuint v0)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", mode);
-#else
-    EVENT("(GLenum mode = 0x%X)", mode);
-#endif
+    return gl::Uniform1ui(location, v0);
+}
 
-    try
-    {
-        switch (mode)
-        {
-          case GL_FRONT:
-          case GL_BACK:
-          case GL_FRONT_AND_BACK:
-            {
-                gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1)
+{
+    return gl::Uniform2ui(location, v0, v1);
+}
 
-                if (context)
-                {
-                    context->setCullMode(mode);
-                }
-            }
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+    return gl::Uniform3ui(location, v0, v1, v2);
 }
 
-void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers)
+void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, buffers);
-#else
-    EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
-#endif
+    return gl::Uniform4ui(location, v0, v1, v2, v3);
+}
 
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint *value)
+{
+    return gl::Uniform1uiv(location, count, value);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint *value)
+{
+    return gl::Uniform2uiv(location, count, value);
+}
 
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                context->deleteBuffer(buffers[i]);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint *value)
+{
+    return gl::Uniform3uiv(location, count, value);
 }
 
-void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences)
+void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, fences);
-#else
-    EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
-#endif
+    return gl::Uniform4uiv(location, count, value);
+}
 
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
+{
+    return gl::ClearBufferiv(buffer, drawbuffer, value);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
+{
+    return gl::ClearBufferuiv(buffer, drawbuffer, value);
+}
 
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                context->deleteFence(fences[i]);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
+{
+    return gl::ClearBufferfv(buffer, drawbuffer, value);
 }
 
-void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, framebuffers);
-#else
-    EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
-#endif
+    return gl::ClearBufferfi(buffer, drawbuffer, depth, stencil);
+}
 
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index)
+{
+    return gl::GetStringi(name, index);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glCopyBufferSubData(GLenum readTarget,
+                                     GLenum writeTarget,
+                                     GLintptr readOffset,
+                                     GLintptr writeOffset,
+                                     GLsizeiptr size)
+{
+    return gl::CopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
+}
 
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                if (framebuffers[i] != 0)
-                {
-                    context->deleteFramebuffer(framebuffers[i]);
-                }
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetUniformIndices(GLuint program,
+                                     GLsizei uniformCount,
+                                     const GLchar *const *uniformNames,
+                                     GLuint *uniformIndices)
+{
+    return gl::GetUniformIndices(program, uniformCount, uniformNames, uniformIndices);
 }
 
-void __stdcall glDeleteProgram(GLuint program)
+void GL_APIENTRY glGetActiveUniformsiv(GLuint program,
+                                       GLsizei uniformCount,
+                                       const GLuint *uniformIndices,
+                                       GLenum pname,
+                                       GLint *params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", program);
-#else
-    EVENT("(GLuint program = %d)", program);
-#endif
+    return gl::GetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params);
+}
 
-    try
-    {
-        if (program == 0)
-        {
-            return;
-        }
+GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
+{
+    return gl::GetUniformBlockIndex(program, uniformBlockName);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program,
+                                           GLuint uniformBlockIndex,
+                                           GLenum pname,
+                                           GLint *params)
+{
+    return gl::GetActiveUniformBlockiv(program, uniformBlockIndex, pname, params);
+}
 
-        if (context)
-        {
-            if (!context->getProgram(program))
-            {
-                if(context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
+void GL_APIENTRY glGetActiveUniformBlockName(GLuint program,
+                                             GLuint uniformBlockIndex,
+                                             GLsizei bufSize,
+                                             GLsizei *length,
+                                             GLchar *uniformBlockName)
+{
+    return gl::GetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length,
+                                         uniformBlockName);
+}
 
-            context->deleteProgram(program);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glUniformBlockBinding(GLuint program,
+                                       GLuint uniformBlockIndex,
+                                       GLuint uniformBlockBinding)
+{
+    return gl::UniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
 }
 
-void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
+void GL_APIENTRY glDrawArraysInstanced(GLenum mode,
+                                       GLint first,
+                                       GLsizei count,
+                                       GLsizei instanceCount)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, ids);
-#else
-    EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
-#endif
+    return gl::DrawArraysInstanced(mode, first, count, instanceCount);
+}
 
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glDrawElementsInstanced(GLenum mode,
+                                         GLsizei count,
+                                         GLenum type,
+                                         const void *indices,
+                                         GLsizei instanceCount)
+{
+    return gl::DrawElementsInstanced(mode, count, type, indices, instanceCount);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags)
+{
+    return gl::FenceSync_(condition, flags);
+}
 
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                context->deleteQuery(ids[i]);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+GLboolean GL_APIENTRY glIsSync(GLsync sync)
+{
+    return gl::IsSync(sync);
 }
 
-void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+void GL_APIENTRY glDeleteSync(GLsync sync)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, renderbuffers);
-#else
-    EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
-#endif
+    return gl::DeleteSync(sync);
+}
 
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+    return gl::ClientWaitSync(sync, flags, timeout);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+    return gl::WaitSync(sync, flags, timeout);
+}
 
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                context->deleteRenderbuffer(renderbuffers[i]);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64 *params)
+{
+    return gl::GetInteger64v(pname, params);
 }
 
-void __stdcall glDeleteShader(GLuint shader)
+void GL_APIENTRY
+glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", shader);
-#else
-    EVENT("(GLuint shader = %d)", shader);
-#endif
+    return gl::GetSynciv(sync, pname, bufSize, length, values);
+}
 
-    try
-    {
-        if (shader == 0)
-        {
-            return;
-        }
+void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data)
+{
+    return gl::GetInteger64i_v(target, index, data);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
+{
+    return gl::GetBufferParameteri64v(target, pname, params);
+}
 
-        if (context)
-        {
-            if (!context->getShader(shader))
-            {
-                if(context->getProgram(shader))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
+void GL_APIENTRY glGenSamplers(GLsizei count, GLuint *samplers)
+{
+    return gl::GenSamplers(count, samplers);
+}
 
-            context->deleteShader(shader);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint *samplers)
+{
+    return gl::DeleteSamplers(count, samplers);
 }
 
-void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
+GLboolean GL_APIENTRY glIsSampler(GLuint sampler)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, textures);
-#else
-    EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
-#endif
+    return gl::IsSampler(sampler);
+}
 
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler)
+{
+    return gl::BindSampler(unit, sampler);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+    return gl::SamplerParameteri(sampler, pname, param);
+}
 
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                if (textures[i] != 0)
-                {
-                    context->deleteTexture(textures[i]);
-                }
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
+{
+    return gl::SamplerParameteriv(sampler, pname, param);
 }
 
-void __stdcall glDepthFunc(GLenum func)
+void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", func);
-#else
-    EVENT("(GLenum func = 0x%X)", func);
-#endif
+    return gl::SamplerParameterf(sampler, pname, param);
+}
 
-    try
-    {
-        switch (func)
-        {
-          case GL_NEVER:
-          case GL_ALWAYS:
-          case GL_LESS:
-          case GL_LEQUAL:
-          case GL_EQUAL:
-          case GL_GREATER:
-          case GL_GEQUAL:
-          case GL_NOTEQUAL:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
+void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
+{
+    return gl::SamplerParameterfv(sampler, pname, param);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
+{
+    return gl::GetSamplerParameteriv(sampler, pname, params);
+}
 
-        if (context)
-        {
-            context->setDepthFunc(func);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
+{
+    return gl::GetSamplerParameterfv(sampler, pname, params);
 }
 
-void __stdcall glDepthMask(GLboolean flag)
+void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", flag);
-#else
-    EVENT("(GLboolean flag = %d)", flag);
-#endif
+    return gl::VertexAttribDivisor(index, divisor);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)
+{
+    return gl::BindTransformFeedback(target, id);
+}
 
-        if (context)
-        {
-            context->setDepthMask(flag != GL_FALSE);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
+{
+    return gl::DeleteTransformFeedbacks(n, ids);
 }
 
-void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
+void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint *ids)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%f, %f)", zNear, zFar);
-#else
-    EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
-#endif
+    return gl::GenTransformFeedbacks(n, ids);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id)
+{
+    return gl::IsTransformFeedback(id);
+}
 
-        if (context)
-        {
-            context->setDepthRange(zNear, zFar);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glPauseTransformFeedback(void)
+{
+    return gl::PauseTransformFeedback();
 }
 
-void __stdcall glDetachShader(GLuint program, GLuint shader)
+void GL_APIENTRY glResumeTransformFeedback(void)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d)", program, shader);
-#else
-    EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
-#endif
+    return gl::ResumeTransformFeedback();
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetProgramBinary(GLuint program,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLenum *binaryFormat,
+                                    void *binary)
+{
+    return gl::GetProgramBinary(program, bufSize, length, binaryFormat, binary);
+}
 
-        if (context)
-        {
+void GL_APIENTRY glProgramBinary(GLuint program,
+                                 GLenum binaryFormat,
+                                 const void *binary,
+                                 GLsizei length)
+{
+    return gl::ProgramBinary(program, binaryFormat, binary, length);
+}
 
-            gl::Program *programObject = context->getProgram(program);
-            gl::Shader *shaderObject = context->getShader(shader);
-            
-            if (!programObject)
-            {
-                gl::Shader *shaderByProgramHandle;
-                shaderByProgramHandle = context->getShader(program);
-                if (!shaderByProgramHandle)
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-            }
+void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value)
+{
+    return gl::ProgramParameteri(program, pname, value);
+}
 
-            if (!shaderObject)
-            {
-                gl::Program *programByShaderHandle = context->getProgram(shader);
-                if (!programByShaderHandle)
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-            }
+void GL_APIENTRY glInvalidateFramebuffer(GLenum target,
+                                         GLsizei numAttachments,
+                                         const GLenum *attachments)
+{
+    return gl::InvalidateFramebuffer(target, numAttachments, attachments);
+}
 
-            if (!programObject->detachShader(shaderObject))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target,
+                                            GLsizei numAttachments,
+                                            const GLenum *attachments,
+                                            GLint x,
+                                            GLint y,
+                                            GLsizei width,
+                                            GLsizei height)
+{
+    return gl::InvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
 }
 
-void __stdcall glDisable(GLenum cap)
+void GL_APIENTRY
+glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", cap);
-#else
-    EVENT("(GLenum cap = 0x%X)", cap);
-#endif
+    return gl::TexStorage2D(target, levels, internalformat, width, height);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glTexStorage3D(GLenum target,
+                                GLsizei levels,
+                                GLenum internalformat,
+                                GLsizei width,
+                                GLsizei height,
+                                GLsizei depth)
+{
+    return gl::TexStorage3D(target, levels, internalformat, width, height, depth);
+}
 
-        if (context)
-        {
-            switch (cap)
-            {
-              case GL_CULL_FACE:                context->setCullFace(false);              break;
-              case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(false);     break;
-              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
-              case GL_SAMPLE_COVERAGE:          context->setSampleCoverage(false);        break;
-              case GL_SCISSOR_TEST:             context->setScissorTest(false);           break;
-              case GL_STENCIL_TEST:             context->setStencilTest(false);           break;
-              case GL_DEPTH_TEST:               context->setDepthTest(false);             break;
-              case GL_BLEND:                    context->setBlend(false);                 break;
-              case GL_DITHER:                   context->setDither(false);                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetInternalformativ(GLenum target,
+                                       GLenum internalformat,
+                                       GLenum pname,
+                                       GLsizei bufSize,
+                                       GLint *params)
+{
+    return gl::GetInternalformativ(target, internalformat, pname, bufSize, params);
 }
 
-void __stdcall glDisableVertexAttribArray(GLuint index)
+void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0,
+                                        GLint srcY0,
+                                        GLint srcX1,
+                                        GLint srcY1,
+                                        GLint dstX0,
+                                        GLint dstY0,
+                                        GLint dstX1,
+                                        GLint dstY1,
+                                        GLbitfield mask,
+                                        GLenum filter)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", index);
-#else
-    EVENT("(GLuint index = %d)", index);
-#endif
+    return gl::BlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
+                                    filter);
+}
 
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target,
+                                                       GLsizei samples,
+                                                       GLenum internalformat,
+                                                       GLsizei width,
+                                                       GLsizei height)
+{
+    return gl::RenderbufferStorageMultisampleANGLE(target, samples, internalformat, width, height);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glDiscardFramebufferEXT(GLenum target,
+                                         GLsizei numAttachments,
+                                         const GLenum *attachments)
+{
+    return gl::DiscardFramebufferEXT(target, numAttachments, attachments);
+}
 
-        if (context)
-        {
-            context->setEnableVertexAttribArray(index, false);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint *fences)
+{
+    return gl::DeleteFencesNV(n, fences);
 }
 
-void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
+void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint *fences)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, %d)", mode, first, count);
-#else
-    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
-#endif
+    return gl::GenFencesNV(n, fences);
+}
 
-    try
-    {
-        if (count < 0 || first < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+GLboolean GL_APIENTRY glIsFenceNV(GLuint fence)
+{
+    return gl::IsFenceNV(fence);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+GLboolean GL_APIENTRY glTestFenceNV(GLuint fence)
+{
+    return gl::TestFenceNV(fence);
+}
 
-        if (context)
-        {
-            context->drawArrays(mode, first, count, 0);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
+{
+    return gl::GetFenceivNV(fence, pname, params);
 }
 
-void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+void GL_APIENTRY glFinishFenceNV(GLuint fence)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, %d, %d)", mode, first, count, primcount);
-#else
-    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount);
-#endif
+    return gl::FinishFenceNV(fence);
+}
 
-    try
-    {
-        if (count < 0 || first < 0 || primcount < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition)
+{
+    return gl::SetFenceNV(fence, condition);
+}
 
-        if (primcount > 0)
-        {
-            gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader,
+                                                  GLsizei bufsize,
+                                                  GLsizei *length,
+                                                  GLchar *source)
+{
+    return gl::GetTranslatedShaderSourceANGLE(shader, bufsize, length, source);
+}
 
-            if (context)
-            {
-                context->drawArrays(mode, first, count, primcount);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glTexStorage2DEXT(GLenum target,
+                                   GLsizei levels,
+                                   GLenum internalformat,
+                                   GLsizei width,
+                                   GLsizei height)
+{
+    return gl::TexStorage2DEXT(target, levels, internalformat, width, height);
 }
 
-void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, 0x%X, 0x%0.8p)",
-          mode, count, type, indices);
-#else
-    EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
-          mode, count, type, indices);
-#endif
+    return gl::GetGraphicsResetStatusEXT();
+}
 
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glReadnPixelsEXT(GLint x,
+                                  GLint y,
+                                  GLsizei width,
+                                  GLsizei height,
+                                  GLenum format,
+                                  GLenum type,
+                                  GLsizei bufSize,
+                                  void *data)
+{
+    return gl::ReadnPixelsEXT(x, y, width, height, format, type, bufSize, data);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, float *params)
+{
+    return gl::GetnUniformfvEXT(program, location, bufSize, params);
+}
 
-        if (context)
-        {
-            switch (type)
-            {
-              case GL_UNSIGNED_BYTE:
-              case GL_UNSIGNED_SHORT:
-                break;
-              case GL_UNSIGNED_INT:
-                if (!context->supports32bitIndices())
-                {
-                    return gl::error(GL_INVALID_ENUM);    
-                }
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        
-            context->drawElements(mode, count, type, indices, 0);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params)
+{
+    return gl::GetnUniformivEXT(program, location, bufSize, params);
 }
 
-void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
+void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint *ids)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, 0x%X, 0x%0.8p, %d)",
-          mode, count, type, indices, primcount);
-#else
-    EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)",
-          mode, count, type, indices, primcount);
-#endif
+    return gl::GenQueriesEXT(n, ids);
+}
 
-    try
-    {
-        if (count < 0 || primcount < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
+{
+    return gl::DeleteQueriesEXT(n, ids);
+}
 
-        if (primcount > 0)
-        {
-            gl::Context *context = gl::getNonLostContext();
+GLboolean GL_APIENTRY glIsQueryEXT(GLuint id)
+{
+    return gl::IsQueryEXT(id);
+}
 
-            if (context)
-            {
-                switch (type)
-                {
-                  case GL_UNSIGNED_BYTE:
-                  case GL_UNSIGNED_SHORT:
-                    break;
-                  case GL_UNSIGNED_INT:
-                    if (!context->supports32bitIndices())
-                    {
-                        return gl::error(GL_INVALID_ENUM);    
-                    }
-                    break;
-                  default:
-                    return gl::error(GL_INVALID_ENUM);
-                }
-            
-                context->drawElements(mode, count, type, indices, primcount);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id)
+{
+    return gl::BeginQueryEXT(target, id);
 }
 
-void __stdcall glEnable(GLenum cap)
+void GL_APIENTRY glEndQueryEXT(GLenum target)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", cap);
-#else
-    EVENT("(GLenum cap = 0x%X)", cap);
-#endif
+    return gl::EndQueryEXT(target);
+}
 
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glQueryCounterEXT(GLuint id, GLenum target)
+{
+    return gl::QueryCounterEXT(id, target);
+}
 
-        if (context)
-        {
-            switch (cap)
-            {
-              case GL_CULL_FACE:                context->setCullFace(true);              break;
-              case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(true);     break;
-              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;
-              case GL_SAMPLE_COVERAGE:          context->setSampleCoverage(true);        break;
-              case GL_SCISSOR_TEST:             context->setScissorTest(true);           break;
-              case GL_STENCIL_TEST:             context->setStencilTest(true);           break;
-              case GL_DEPTH_TEST:               context->setDepthTest(true);             break;
-              case GL_BLEND:                    context->setBlend(true);                 break;
-              case GL_DITHER:                   context->setDither(true);                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
+{
+    return gl::GetQueryivEXT(target, pname, params);
 }
 
-void __stdcall glEnableVertexAttribArray(GLuint index)
+void GL_APIENTRY glGetQueryObjectivEXT(GLuint id, GLenum pname, GLint *params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", index);
-#else
-    EVENT("(GLuint index = %d)", index);
-#endif
+    return gl::GetQueryObjectivEXT(id, pname, params);
+}
 
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
+void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
+{
+    return gl::GetQueryObjectuivEXT(id, pname, params);
+}
 
-        gl::Context *context = gl::getNonLostContext();
+void GL_APIENTRY glGetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64 *params)
+{
+    return gl::GetQueryObjecti64vEXT(id, pname, params);
+}
 
-        if (context)
-        {
-            context->setEnableVertexAttribArray(index, true);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+void GL_APIENTRY glGetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 *params)
+{
+    return gl::GetQueryObjectui64vEXT(id, pname, params);
 }
 
-void __stdcall glEndQueryEXT(GLenum target)
+void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", target);
-#else
-    EVENT("GLenum target = 0x%X)", target);
-#endif
-
-    try
-    {
-        switch (target)
-        {
-          case GL_ANY_SAMPLES_PASSED_EXT: 
-          case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
-              break;
-          default: 
-              return gl::error(GL_INVALID_ENUM);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->endQuery(target);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::DrawBuffersEXT(n, bufs);
 }
 
-void __stdcall glFinishFenceNV(GLuint fence)
+void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode,
+                                            GLint first,
+                                            GLsizei count,
+                                            GLsizei primcount)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", fence);
-#else
-    EVENT("(GLuint fence = %d)", fence);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Fence* fenceObject = context->getFence(fence);
-
-            if (fenceObject == NULL)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            fenceObject->finishFence();
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::DrawArraysInstancedANGLE(mode, first, count, primcount);
 }
 
-void __stdcall glFinish(void)
+void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode,
+                                              GLsizei count,
+                                              GLenum type,
+                                              const void *indices,
+                                              GLsizei primcount)
 {
-    EVENT("()");
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->sync(true);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::DrawElementsInstancedANGLE(mode, count, type, indices, primcount);
 }
 
-void __stdcall glFlush(void)
+void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
 {
-    EVENT("()");
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->sync(false);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::VertexAttribDivisorANGLE(index, divisor);
 }
 
-void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+void GL_APIENTRY glGetProgramBinaryOES(GLuint program,
+                                       GLsizei bufSize,
+                                       GLsizei *length,
+                                       GLenum *binaryFormat,
+                                       void *binary)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%X, %d)",
-          target, attachment, renderbuffertarget, renderbuffer);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
-          "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
-#endif
-
-    try
-    {
-        if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
-            || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Framebuffer *framebuffer = NULL;
-            GLuint framebufferHandle = 0;
-            if (target == GL_READ_FRAMEBUFFER_ANGLE)
-            {
-                framebuffer = context->getReadFramebuffer();
-                framebufferHandle = context->getReadFramebufferHandle();
-            }
-            else
-            {
-                framebuffer = context->getDrawFramebuffer();
-                framebufferHandle = context->getDrawFramebufferHandle();
-            }
-
-            if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
-            {
-                const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
-
-                if (colorAttachment >= context->getMaximumRenderTargets())
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-
-                framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer);
-            }
-            else
-            {
-                switch (attachment)
-                {
-                  case GL_DEPTH_ATTACHMENT:
-                    framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
-                    break;
-                  case GL_STENCIL_ATTACHMENT:
-                    framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
-                    break;
-                  default:
-                    return gl::error(GL_INVALID_ENUM);
-                }
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary);
 }
 
-void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+void GL_APIENTRY glProgramBinaryOES(GLuint program,
+                                    GLenum binaryFormat,
+                                    const void *binary,
+                                    GLint length)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%X, %d, %d)",
-          target, attachment, textarget, texture, level);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
-          "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
-#endif
-
-    try
-    {
-        if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
-            {
-                const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
-
-                if (colorAttachment >= context->getMaximumRenderTargets())
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
-            else
-            {
-                switch (attachment)
-                {
-                  case GL_DEPTH_ATTACHMENT:
-                  case GL_STENCIL_ATTACHMENT:
-                    break;
-                  default:
-                    return gl::error(GL_INVALID_ENUM);
-                }
-            }
-
-            if (texture == 0)
-            {
-                textarget = GL_NONE;
-            }
-            else
-            {
-                gl::Texture *tex = context->getTexture(texture);
-
-                if (tex == NULL)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                switch (textarget)
-                {
-                  case GL_TEXTURE_2D:
-                    {
-                        if (tex->getTarget() != GL_TEXTURE_2D)
-                        {
-                            return gl::error(GL_INVALID_OPERATION);
-                        }
-                        gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
-                        if (tex2d->isCompressed(0))
-                        {
-                            return gl::error(GL_INVALID_OPERATION);
-                        }
-                        break;
-                    }
-
-                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-                    {
-                        if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
-                        {
-                            return gl::error(GL_INVALID_OPERATION);
-                        }
-                        gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
-                        if (texcube->isCompressed(textarget, level))
-                        {
-                            return gl::error(GL_INVALID_OPERATION);
-                        }
-                        break;
-                    }
-
-                  default:
-                    return gl::error(GL_INVALID_ENUM);
-                }
-
-                if (level != 0)
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
-
-            gl::Framebuffer *framebuffer = NULL;
-            GLuint framebufferHandle = 0;
-            if (target == GL_READ_FRAMEBUFFER_ANGLE)
-            {
-                framebuffer = context->getReadFramebuffer();
-                framebufferHandle = context->getReadFramebufferHandle();
-            }
-            else
-            {
-                framebuffer = context->getDrawFramebuffer();
-                framebufferHandle = context->getDrawFramebufferHandle();
-            }
-
-            if (framebufferHandle == 0 || !framebuffer)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
-            {
-                const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
-
-                if (colorAttachment >= context->getMaximumRenderTargets())
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-
-                framebuffer->setColorbuffer(colorAttachment, textarget, texture);
-            }
-            else
-            {
-                switch (attachment)
-                {
-                  case GL_DEPTH_ATTACHMENT:   framebuffer->setDepthbuffer(textarget, texture);   break;
-                  case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
-                }
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::ProgramBinaryOES(program, binaryFormat, binary, length);
 }
 
-void __stdcall glFrontFace(GLenum mode)
+void *GL_APIENTRY glMapBufferOES(GLenum target, GLenum access)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", mode);
-#else
-    EVENT("(GLenum mode = 0x%X)", mode);
-#endif
-
-    try
-    {
-        switch (mode)
-        {
-          case GL_CW:
-          case GL_CCW:
-            {
-                gl::Context *context = gl::getNonLostContext();
-
-                if (context)
-                {
-                    context->setFrontFace(mode);
-                }
-            }
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::MapBufferOES(target, access);
 }
 
-void __stdcall glGenBuffers(GLsizei n, GLuint* buffers)
+GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, buffers);
-#else
-    EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
-#endif
-
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                buffers[i] = context->createBuffer();
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::UnmapBufferOES(target);
 }
 
-void __stdcall glGenerateMipmap(GLenum target)
+void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, void **params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", target);
-#else
-    EVENT("(GLenum target = 0x%X)", target);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                {
-                    gl::Texture2D *tex2d = context->getTexture2D();
-
-                    if (tex2d->isCompressed(0))
-                    {
-                        return gl::error(GL_INVALID_OPERATION);
-                    }
-                    if (tex2d->isDepth(0))
-                    {
-                        return gl::error(GL_INVALID_OPERATION);
-                    }
-
-                    tex2d->generateMipmaps();
-                    break;
-                }
-
-              case GL_TEXTURE_CUBE_MAP:
-                {
-                    gl::TextureCubeMap *texcube = context->getTextureCubeMap();
-
-                    if (texcube->isCompressed(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0))
-                    {
-                        return gl::error(GL_INVALID_OPERATION);
-                    }
-
-                    texcube->generateMipmaps();
-                    break;
-                }
-
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::GetBufferPointervOES(target, pname, params);
 }
 
-void __stdcall glGenFencesNV(GLsizei n, GLuint* fences)
+void *GL_APIENTRY glMapBufferRangeEXT(GLenum target,
+                                      GLintptr offset,
+                                      GLsizeiptr length,
+                                      GLbitfield access)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, fences);
-#else
-    EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
-#endif
-
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                fences[i] = context->createFence();
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::MapBufferRangeEXT(target, offset, length, access);
 }
 
-void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
+void GL_APIENTRY glFlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, framebuffers);
-#else
-    EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
-#endif
-
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                framebuffers[i] = context->createFramebuffer();
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::FlushMappedBufferRangeEXT(target, offset, length);
 }
 
-void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids)
+void GL_APIENTRY glInsertEventMarkerEXT(GLsizei length, const char *marker)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, ids);
-#else
-    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
-#endif
-
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                ids[i] = context->createQuery();
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::InsertEventMarkerEXT(length, marker);
 }
 
-void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+void GL_APIENTRY glPushGroupMarkerEXT(GLsizei length, const char *marker)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, renderbuffers);
-#else
-    EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
-#endif
-
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                renderbuffers[i] = context->createRenderbuffer();
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::PushGroupMarkerEXT(length, marker);
 }
 
-void __stdcall glGenTextures(GLsizei n, GLuint* textures)
+void GL_APIENTRY glPopGroupMarkerEXT()
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, textures);
-#else
-    EVENT("(GLsizei n = %d, GLuint* textures =  0x%0.8p)", n, textures);
-#endif
-
-    try
-    {
-        if (n < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            for (int i = 0; i < n; i++)
-            {
-                textures[i] = context->createTexture();
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::PopGroupMarkerEXT();
 }
 
-void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, 0x%0.8p, 0x%0.8p, %0.8p, %0.8p)",
-          program, index, bufsize, length, size, type, name);
-#else
-    EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
-          "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
-          program, index, bufsize, length, size, type, name);
-#endif
-
-    try
-    {
-        if (bufsize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
-
-            if (index >= (GLuint)programObject->getActiveAttributeCount())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            programObject->getActiveAttribute(index, bufsize, length, size, type, name);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::EGLImageTargetTexture2DOES(target, image);
 }
 
-void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, 0x%0.8p, 0x%0.8p, 0x%0.8p, 0x%0.8p)",
-          program, index, bufsize, length, size, type, name);
-#else
-    EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
-          "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
-          program, index, bufsize, length, size, type, name);
-#endif
-
-    try
-    {
-        if (bufsize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
-
-            if (index >= (GLuint)programObject->getActiveUniformCount())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            programObject->getActiveUniform(index, bufsize, length, size, type, name);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::EGLImageTargetRenderbufferStorageOES(target, image);
 }
 
-void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+void GL_APIENTRY glBindVertexArrayOES(GLuint array)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p, 0x%0.8p)",
-          program, maxcount, count, shaders);
-#else
-    EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
-          program, maxcount, count, shaders);
-#endif
-
-    try
-    {
-        if (maxcount < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
-
-            return programObject->getAttachedShaders(maxcount, count, shaders);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::BindVertexArrayOES(array);
 }
 
-int __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
+void GL_APIENTRY glDeleteVertexArraysOES(GLsizei n, const GLuint *arrays)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %s)", program, name);
-#else
-    EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION, -1);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE, -1);
-                }
-            }
-
-            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-            if (!programObject->isLinked() || !programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION, -1);
-            }
-
-            return programBinary->getAttributeLocation(name);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, -1);
-    }
-
-    return -1;
+    return gl::DeleteVertexArraysOES(n, arrays);
 }
 
-void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
+void GL_APIENTRY glGenVertexArraysOES(GLsizei n, GLuint *arrays)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%0.8p)",  pname, params);
-#else
-    EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)",  pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (!(context->getBooleanv(pname, params)))
-            {
-                GLenum nativeType;
-                unsigned int numParams = 0;
-                if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
-                    return gl::error(GL_INVALID_ENUM);
-
-                if (numParams == 0)
-                    return; // it is known that the pname is valid, but there are no parameters to return
-
-                if (nativeType == GL_FLOAT)
-                {
-                    GLfloat *floatParams = NULL;
-                    floatParams = new GLfloat[numParams];
-
-                    context->getFloatv(pname, floatParams);
-
-                    for (unsigned int i = 0; i < numParams; ++i)
-                    {
-                        if (floatParams[i] == 0.0f)
-                            params[i] = GL_FALSE;
-                        else
-                            params[i] = GL_TRUE;
-                    }
-
-                    delete [] floatParams;
-                }
-                else if (nativeType == GL_INT)
-                {
-                    GLint *intParams = NULL;
-                    intParams = new GLint[numParams];
-
-                    context->getIntegerv(pname, intParams);
-
-                    for (unsigned int i = 0; i < numParams; ++i)
-                    {
-                        if (intParams[i] == 0)
-                            params[i] = GL_FALSE;
-                        else
-                            params[i] = GL_TRUE;
-                    }
-
-                    delete [] intParams;
-                }
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::GenVertexArraysOES(n, arrays);
 }
 
-void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+GLboolean GL_APIENTRY glIsVertexArrayOES(GLuint array)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%0.8p)", target, pname, params);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Buffer *buffer;
-
-            switch (target)
-            {
-              case GL_ARRAY_BUFFER:
-                buffer = context->getArrayBuffer();
-                break;
-              case GL_ELEMENT_ARRAY_BUFFER:
-                buffer = context->getElementArrayBuffer();
-                break;
-              default: return gl::error(GL_INVALID_ENUM);
-            }
-
-            if (!buffer)
-            {
-                // A null buffer means that "0" is bound to the requested buffer target
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            switch (pname)
-            {
-              case GL_BUFFER_USAGE:
-                *params = buffer->usage();
-                break;
-              case GL_BUFFER_SIZE:
-                *params = buffer->size();
-                break;
-              default: return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::IsVertexArrayOES(array);
 }
 
-GLenum __stdcall glGetError(void)
+void GL_APIENTRY glDebugMessageControlKHR(GLenum source,
+                                          GLenum type,
+                                          GLenum severity,
+                                          GLsizei count,
+                                          const GLuint *ids,
+                                          GLboolean enabled)
 {
-    EVENT("()");
-
-    gl::Context *context = gl::getContext();
-
-    if (context)
-    {
-        return context->getError();
-    }
-
-    return GL_NO_ERROR;
+    return gl::DebugMessageControlKHR(source, type, severity, count, ids, enabled);
 }
 
-void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
+void GL_APIENTRY glDebugMessageInsertKHR(GLenum source,
+                                         GLenum type,
+                                         GLuint id,
+                                         GLenum severity,
+                                         GLsizei length,
+                                         const GLchar *buf)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%X, 0x%0.8p)", fence, pname, params);
-#else
-    EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
-#endif
-
-    try
-    {
-    
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Fence *fenceObject = context->getFence(fence);
-
-            if (fenceObject == NULL)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            fenceObject->getFenceiv(pname, params);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::DebugMessageInsertKHR(source, type, id, severity, length, buf);
 }
 
-void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
+void GL_APIENTRY glDebugMessageCallbackKHR(GLDEBUGPROCKHR callback, const void *userParam)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%0.8p)", pname, params);
-#else
-    EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (!(context->getFloatv(pname, params)))
-            {
-                GLenum nativeType;
-                unsigned int numParams = 0;
-                if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
-                    return gl::error(GL_INVALID_ENUM);
-
-                if (numParams == 0)
-                    return; // it is known that the pname is valid, but that there are no parameters to return.
-
-                if (nativeType == GL_BOOL)
-                {
-                    GLboolean *boolParams = NULL;
-                    boolParams = new GLboolean[numParams];
-
-                    context->getBooleanv(pname, boolParams);
-
-                    for (unsigned int i = 0; i < numParams; ++i)
-                    {
-                        if (boolParams[i] == GL_FALSE)
-                            params[i] = 0.0f;
-                        else
-                            params[i] = 1.0f;
-                    }
-
-                    delete [] boolParams;
-                }
-                else if (nativeType == GL_INT)
-                {
-                    GLint *intParams = NULL;
-                    intParams = new GLint[numParams];
-
-                    context->getIntegerv(pname, intParams);
-
-                    for (unsigned int i = 0; i < numParams; ++i)
-                    {
-                        params[i] = (GLfloat)intParams[i];
-                    }
-
-                    delete [] intParams;
-                }
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::DebugMessageCallbackKHR(callback, userParam);
 }
 
-void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GLuint GL_APIENTRY glGetDebugMessageLogKHR(GLuint count,
+                                           GLsizei bufSize,
+                                           GLenum *sources,
+                                           GLenum *types,
+                                           GLuint *ids,
+                                           GLenum *severities,
+                                           GLsizei *lengths,
+                                           GLchar *messageLog)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%X, 0x%0.8p)",
-          target, attachment, pname, params);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
-          target, attachment, pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
-            {
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            gl::Framebuffer *framebuffer = NULL;
-            if (target == GL_READ_FRAMEBUFFER_ANGLE)
-            {
-                if(context->getReadFramebufferHandle() == 0)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                framebuffer = context->getReadFramebuffer();
-            }
-            else 
-            {
-                if (context->getDrawFramebufferHandle() == 0)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                framebuffer = context->getDrawFramebuffer();
-            }
-
-            GLenum attachmentType;
-            GLuint attachmentHandle;
-
-            if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
-            {
-                const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
-
-                if (colorAttachment >= context->getMaximumRenderTargets())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-
-                attachmentType = framebuffer->getColorbufferType(colorAttachment);
-                attachmentHandle = framebuffer->getColorbufferHandle(colorAttachment);
-            }
-            else
-            {
-                switch (attachment)
-                {
-                  case GL_DEPTH_ATTACHMENT:
-                    attachmentType = framebuffer->getDepthbufferType();
-                    attachmentHandle = framebuffer->getDepthbufferHandle();
-                    break;
-                  case GL_STENCIL_ATTACHMENT:
-                    attachmentType = framebuffer->getStencilbufferType();
-                    attachmentHandle = framebuffer->getStencilbufferHandle();
-                    break;
-                  default: return gl::error(GL_INVALID_ENUM);
-                }
-            }
-
-            GLenum attachmentObjectType;   // Type category
-            if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
-            {
-                attachmentObjectType = attachmentType;
-            }
-            else if (gl::IsInternalTextureTarget(attachmentType))
-            {
-                attachmentObjectType = GL_TEXTURE;
-            }
-            else
-            {
-                UNREACHABLE();
-                return;
-            }
-
-            switch (pname)
-            {
-              case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
-                *params = attachmentObjectType;
-                break;
-              case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
-                if (attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
-                {
-                    *params = attachmentHandle;
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
-                if (attachmentObjectType == GL_TEXTURE)
-                {
-                    *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
-                if (attachmentObjectType == GL_TEXTURE)
-                {
-                    if (gl::IsCubemapTextureTarget(attachmentType))
-                    {
-                        *params = attachmentType;
-                    }
-                    else
-                    {
-                        *params = 0;
-                    }
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::GetDebugMessageLogKHR(count, bufSize, sources, types, ids, severities, lengths,
+                                     messageLog);
 }
 
-GLenum __stdcall glGetGraphicsResetStatusEXT(void)
+void GL_APIENTRY glPushDebugGroupKHR(GLenum source,
+                                     GLuint id,
+                                     GLsizei length,
+                                     const GLchar *message)
 {
-    EVENT("()");
-
-    try
-    {
-        gl::Context *context = gl::getContext();
-
-        if (context)
-        {
-            return context->getResetStatus();
-        }
-
-        return GL_NO_ERROR;
-    }
-    catch(std::bad_alloc&)
-    {
-        return GL_OUT_OF_MEMORY;
-    }
+    return gl::PushDebugGroupKHR(source, id, length, message);
 }
 
-void __stdcall glGetIntegerv(GLenum pname, GLint* params)
+void GL_APIENTRY glPopDebugGroupKHR(void)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%0.8p)", pname, params);
-#else
-    EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (!(context->getIntegerv(pname, params)))
-            {
-                GLenum nativeType;
-                unsigned int numParams = 0;
-                if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
-                    return gl::error(GL_INVALID_ENUM);
-
-                if (numParams == 0)
-                    return; // it is known that pname is valid, but there are no parameters to return
-
-                if (nativeType == GL_BOOL)
-                {
-                    GLboolean *boolParams = NULL;
-                    boolParams = new GLboolean[numParams];
-
-                    context->getBooleanv(pname, boolParams);
-
-                    for (unsigned int i = 0; i < numParams; ++i)
-                    {
-                        if (boolParams[i] == GL_FALSE)
-                            params[i] = 0;
-                        else
-                            params[i] = 1;
-                    }
-
-                    delete [] boolParams;
-                }
-                else if (nativeType == GL_FLOAT)
-                {
-                    GLfloat *floatParams = NULL;
-                    floatParams = new GLfloat[numParams];
-
-                    context->getFloatv(pname, floatParams);
-
-                    for (unsigned int i = 0; i < numParams; ++i)
-                    {
-                        if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
-                        {
-                            params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f);
-                        }
-                        else
-                            params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
-                    }
-
-                    delete [] floatParams;
-                }
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::PopDebugGroupKHR();
 }
 
-void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params)
+void GL_APIENTRY glObjectLabelKHR(GLenum identifier,
+                                  GLuint name,
+                                  GLsizei length,
+                                  const GLchar *label)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", program, pname, params);
-#else
-    EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            switch (pname)
-            {
-              case GL_DELETE_STATUS:
-                *params = programObject->isFlaggedForDeletion();
-                return;
-              case GL_LINK_STATUS:
-                *params = programObject->isLinked();
-                return;
-              case GL_VALIDATE_STATUS:
-                *params = programObject->isValidated();
-                return;
-              case GL_INFO_LOG_LENGTH:
-                *params = programObject->getInfoLogLength();
-                return;
-              case GL_ATTACHED_SHADERS:
-                *params = programObject->getAttachedShadersCount();
-                return;
-              case GL_ACTIVE_ATTRIBUTES:
-                *params = programObject->getActiveAttributeCount();
-                return;
-              case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
-                *params = programObject->getActiveAttributeMaxLength();
-                return;
-              case GL_ACTIVE_UNIFORMS:
-                *params = programObject->getActiveUniformCount();
-                return;
-              case GL_ACTIVE_UNIFORM_MAX_LENGTH:
-                *params = programObject->getActiveUniformMaxLength();
-                return;
-              case GL_PROGRAM_BINARY_LENGTH_OES:
-                *params = programObject->getProgramBinaryLength();
-                return;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::ObjectLabelKHR(identifier, name, length, label);
 }
 
-void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+void GL_APIENTRY
+glGetObjectLabelKHR(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p, 0x%0.8p)",
-          program, bufsize, length, infolog);
-#else
-    EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
-          program, bufsize, length, infolog);
-#endif
-
-    try
-    {
-        if (bufsize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            programObject->getInfoLog(bufsize, length, infolog);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::GetObjectLabelKHR(identifier, name, bufSize, length, label);
 }
 
-void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
+void GL_APIENTRY glObjectPtrLabelKHR(const void *ptr, GLsizei length, const GLchar *label)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%0.8p)", target, pname, params);
-#else
-    EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
-#endif
-
-    try
-    {
-        switch (pname)
-        {
-          case GL_CURRENT_QUERY_EXT:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            params[0] = context->getActiveQuery(target);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::ObjectPtrLabelKHR(ptr, length, label);
 }
 
-void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
+void GL_APIENTRY glGetObjectPtrLabelKHR(const void *ptr,
+                                        GLsizei bufSize,
+                                        GLsizei *length,
+                                        GLchar *label)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%X, 0x%0.8p)", id, pname, params);
-#else
-    EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
-#endif
-
-    try
-    {
-        switch (pname)
-        {
-          case GL_QUERY_RESULT_EXT:
-          case GL_QUERY_RESULT_AVAILABLE_EXT:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
-
-            if (!queryObject)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (context->getActiveQuery(queryObject->getType()) == id)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            switch(pname)
-            {
-              case GL_QUERY_RESULT_EXT:
-                params[0] = queryObject->getResult();
-                break;
-              case GL_QUERY_RESULT_AVAILABLE_EXT:
-                params[0] = queryObject->isResultAvailable();
-                break;
-              default:
-                ASSERT(false);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::GetObjectPtrLabelKHR(ptr, bufSize, length, label);
 }
 
-void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glGetPointervKHR(GLenum pname, void **params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%0.8p)", target, pname, params);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (target != GL_RENDERBUFFER)
-            {
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            if (context->getRenderbufferHandle() == 0)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle());
-
-            switch (pname)
-            {
-              case GL_RENDERBUFFER_WIDTH:           *params = renderbuffer->getWidth();          break;
-              case GL_RENDERBUFFER_HEIGHT:          *params = renderbuffer->getHeight();         break;
-              case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break;
-              case GL_RENDERBUFFER_RED_SIZE:        *params = renderbuffer->getRedSize();        break;
-              case GL_RENDERBUFFER_GREEN_SIZE:      *params = renderbuffer->getGreenSize();      break;
-              case GL_RENDERBUFFER_BLUE_SIZE:       *params = renderbuffer->getBlueSize();       break;
-              case GL_RENDERBUFFER_ALPHA_SIZE:      *params = renderbuffer->getAlphaSize();      break;
-              case GL_RENDERBUFFER_DEPTH_SIZE:      *params = renderbuffer->getDepthSize();      break;
-              case GL_RENDERBUFFER_STENCIL_SIZE:    *params = renderbuffer->getStencilSize();    break;
-              case GL_RENDERBUFFER_SAMPLES_ANGLE:
-                if (context->getMaxSupportedSamples() != 0)
-                {
-                    *params = renderbuffer->getSamples();
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::GetPointervKHR(pname, params);
 }
 
-void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+void GL_APIENTRY glBindUniformLocationCHROMIUM(GLuint program, GLint location, const GLchar *name)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", shader, pname, params);
-#else
-    EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Shader *shaderObject = context->getShader(shader);
-
-            if (!shaderObject)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            switch (pname)
-            {
-              case GL_SHADER_TYPE:
-                *params = shaderObject->getType();
-                return;
-              case GL_DELETE_STATUS:
-                *params = shaderObject->isFlaggedForDeletion();
-                return;
-              case GL_COMPILE_STATUS:
-                *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
-                return;
-              case GL_INFO_LOG_LENGTH:
-                *params = shaderObject->getInfoLogLength();
-                return;
-              case GL_SHADER_SOURCE_LENGTH:
-                *params = shaderObject->getSourceLength();
-                return;
-              case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
-                *params = shaderObject->getTranslatedSourceLength();
-                return;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::BindUniformLocationCHROMIUM(program, location, name);
 }
 
-void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p, 0x%0.8p)",
-          shader, bufsize, length, infolog);
-#else
-    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
-          shader, bufsize, length, infolog);
-#endif
-
-    try
-    {
-        if (bufsize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Shader *shaderObject = context->getShader(shader);
-
-            if (!shaderObject)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            shaderObject->getInfoLog(bufsize, length, infolog);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::CoverageModulationCHROMIUM(components);
 }
 
-void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+// CHROMIUM_path_rendendering
+void GL_APIENTRY glMatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%0.8p, 0x%0.8p)",
-          shadertype, precisiontype, range, precision);
-#else
-    EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
-          shadertype, precisiontype, range, precision);
-#endif
-
-    try
-    {
-        switch (shadertype)
-        {
-          case GL_VERTEX_SHADER:
-          case GL_FRAGMENT_SHADER:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        switch (precisiontype)
-        {
-          case GL_LOW_FLOAT:
-          case GL_MEDIUM_FLOAT:
-          case GL_HIGH_FLOAT:
-            // Assume IEEE 754 precision
-            range[0] = 127;
-            range[1] = 127;
-            *precision = 23;
-            break;
-          case GL_LOW_INT:
-          case GL_MEDIUM_INT:
-          case GL_HIGH_INT:
-            // Some (most) hardware only supports single-precision floating-point numbers,
-            // which can accurately represent integers up to +/-16777216
-            range[0] = 24;
-            range[1] = 24;
-            *precision = 0;
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::MatrixLoadfCHROMIUM(matrixMode, matrix);
 }
 
-void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+void GL_APIENTRY glMatrixLoadIdentityCHROMIUM(GLenum matrixMode)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p, 0x%0.8p)",
-          shader, bufsize, length, source);
-#else
-    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
-          shader, bufsize, length, source);
-#endif
-
-    try
-    {
-        if (bufsize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Shader *shaderObject = context->getShader(shader);
-
-            if (!shaderObject)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            shaderObject->getSource(bufsize, length, source);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::MatrixLoadIdentityCHROMIUM(matrixMode);
 }
 
-void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+GLuint GL_APIENTRY glGenPathsCHROMIUM(GLsizei range)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p, 0x%0.8p)",
-          shader, bufsize, length, source);
-#else
-    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
-          shader, bufsize, length, source);
-#endif
-
-    try
-    {
-        if (bufsize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Shader *shaderObject = context->getShader(shader);
-
-            if (!shaderObject)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            shaderObject->getTranslatedSource(bufsize, length, source);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::GenPathsCHROMIUM(range);
 }
 
-const GLubyte* __stdcall glGetString(GLenum name)
+void GL_APIENTRY glDeletePathsCHROMIUM(GLuint first, GLsizei range)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", name);
-#else
-    EVENT("(GLenum name = 0x%X)", name);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        switch (name)
-        {
-          case GL_VENDOR:
-            return (GLubyte*)"Google Inc.";
-          case GL_RENDERER:
-            return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE");
-          case GL_VERSION:
-            return (GLubyte*)"OpenGL ES 2.0 (ANGLE " VERSION_STRING ")";
-          case GL_SHADING_LANGUAGE_VERSION:
-            return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " VERSION_STRING ")";
-          case GL_EXTENSIONS:
-            return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");
-          default:
-            return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, (GLubyte*)NULL);
-    }
+    gl::DeletePathsCHROMIUM(first, range);
 }
 
-void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+GLboolean GL_APIENTRY glIsPathCHROMIUM(GLuint path)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%0.8p)", target, pname, params);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Texture *texture;
-
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                texture = context->getTexture2D();
-                break;
-              case GL_TEXTURE_CUBE_MAP:
-                texture = context->getTextureCubeMap();
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            switch (pname)
-            {
-              case GL_TEXTURE_MAG_FILTER:
-                *params = (GLfloat)texture->getMagFilter();
-                break;
-              case GL_TEXTURE_MIN_FILTER:
-                *params = (GLfloat)texture->getMinFilter();
-                break;
-              case GL_TEXTURE_WRAP_S:
-                *params = (GLfloat)texture->getWrapS();
-                break;
-              case GL_TEXTURE_WRAP_T:
-                *params = (GLfloat)texture->getWrapT();
-                break;
-              case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
-                *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE);
-                break;
-              case GL_TEXTURE_USAGE_ANGLE:
-                *params = (GLfloat)texture->getUsage();
-                break;
-              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
-                if (!context->supportsTextureFilterAnisotropy())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                *params = (GLfloat)texture->getMaxAnisotropy();
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::IsPathCHROMIUM(path);
 }
 
-void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glPathCommandsCHROMIUM(GLuint path,
+                                        GLsizei numCommands,
+                                        const GLubyte *commands,
+                                        GLsizei numCoords,
+                                        GLenum coordType,
+                                        const void *coords)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%0.8p)", target, pname, params);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Texture *texture;
-
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                texture = context->getTexture2D();
-                break;
-              case GL_TEXTURE_CUBE_MAP:
-                texture = context->getTextureCubeMap();
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            switch (pname)
-            {
-              case GL_TEXTURE_MAG_FILTER:
-                *params = texture->getMagFilter();
-                break;
-              case GL_TEXTURE_MIN_FILTER:
-                *params = texture->getMinFilter();
-                break;
-              case GL_TEXTURE_WRAP_S:
-                *params = texture->getWrapS();
-                break;
-              case GL_TEXTURE_WRAP_T:
-                *params = texture->getWrapT();
-                break;
-              case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
-                *params = texture->isImmutable() ? GL_TRUE : GL_FALSE;
-                break;
-              case GL_TEXTURE_USAGE_ANGLE:
-                *params = texture->getUsage();
-                break;
-              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
-                if (!context->supportsTextureFilterAnisotropy())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                *params = (GLint)texture->getMaxAnisotropy();
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::PathCommandsCHROMIUM(path, numCommands, commands, numCoords, coordType, coords);
 }
 
-void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+void GL_APIENTRY glPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, 0x%0.8p)",
-          program, location, bufSize, params);
-#else
-    EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
-          program, location, bufSize, params);
-#endif
-
-    try
-    {
-        if (bufSize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (program == 0)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject || !programObject->isLinked())
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->getUniformfv(location, &bufSize, params))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::PathParameterfCHROMIUM(path, pname, value);
 }
 
-void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
+void GL_APIENTRY glPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", program, location, params);
-#else
-    EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (program == 0)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject || !programObject->isLinked())
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->getUniformfv(location, NULL, params))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::PathParameteriCHROMIUM(path, pname, value);
 }
 
-void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
+void GL_APIENTRY glGetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, 0x%0.8p)",
-          program, location, bufSize, params);
-#else
-    EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", 
-          program, location, bufSize, params);
-#endif
-
-    try
-    {
-        if (bufSize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (program == 0)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject || !programObject->isLinked())
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->getUniformiv(location, &bufSize, params))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetPathParameterfCHROMIUM(path, pname, value);
 }
 
-void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
+void GL_APIENTRY glGetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", program, location, params);
-#else
-    EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (program == 0)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject || !programObject->isLinked())
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->getUniformiv(location, NULL, params))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetPathParameteriCHROMIUM(path, pname, value);
 }
 
-int __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
+void GL_APIENTRY glPathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %0.8p)", program, name);
-#else
-    EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (strstr(name, "gl_") == name)
-        {
-            return -1;
-        }
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION, -1);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE, -1);
-                }
-            }
-
-            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-            if (!programObject->isLinked() || !programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION, -1);
-            }
-
-            return programBinary->getUniformLocation(name);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, -1);
-    }
-
-    return -1;
+    gl::PathStencilFuncCHROMIUM(func, ref, mask);
 }
 
-void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+void GL_APIENTRY glStencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%X, 0x%0.8p)", index, pname, params);
-#else
-    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (index >= gl::MAX_VERTEX_ATTRIBS)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
-
-            switch (pname)
-            {
-              case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
-                *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_SIZE:
-                *params = (GLfloat)attribState.mSize;
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
-                *params = (GLfloat)attribState.mStride;
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_TYPE:
-                *params = (GLfloat)attribState.mType;
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
-                *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
-                *params = (GLfloat)attribState.mBoundBuffer.id();
-                break;
-              case GL_CURRENT_VERTEX_ATTRIB:
-                for (int i = 0; i < 4; ++i)
-                {
-                    params[i] = attribState.mCurrentValue[i];
-                }
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
-                *params = (GLfloat)attribState.mDivisor;
-                break;
-              default: return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::StencilFillPathCHROMIUM(path, fillMode, mask);
 }
 
-void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+void GL_APIENTRY glStencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%X, 0x%0.8p)", index, pname, params);
-#else
-    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (index >= gl::MAX_VERTEX_ATTRIBS)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
-
-            switch (pname)
-            {
-              case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
-                *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_SIZE:
-                *params = attribState.mSize;
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
-                *params = attribState.mStride;
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_TYPE:
-                *params = attribState.mType;
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
-                *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
-                *params = attribState.mBoundBuffer.id();
-                break;
-              case GL_CURRENT_VERTEX_ATTRIB:
-                for (int i = 0; i < 4; ++i)
-                {
-                    float currentValue = attribState.mCurrentValue[i];
-                    params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
-                }
-                break;
-              case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
-                *params = (GLint)attribState.mDivisor;
-                break;
-              default: return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::StencilStrokePathCHROMIUM(path, reference, mask);
 }
 
-void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
+void GL_APIENTRY glCoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%X, 0x%0.8p)", index, pname, pointer);
-#else
-    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (index >= gl::MAX_VERTEX_ATTRIBS)
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
-            {
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::CoverFillPathCHROMIUM(path, coverMode);
 }
 
-void __stdcall glHint(GLenum target, GLenum mode)
+void GL_APIENTRY glCoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X)", target, mode);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
-#endif
-
-    try
-    {
-        switch (mode)
-        {
-          case GL_FASTEST:
-          case GL_NICEST:
-          case GL_DONT_CARE:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM); 
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-        switch (target)
-        {
-          case GL_GENERATE_MIPMAP_HINT:
-            if (context) context->setGenerateMipmapHint(mode);
-            break;
-          case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
-            if (context) context->setFragmentShaderDerivativeHint(mode);
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::CoverStrokePathCHROMIUM(path, coverMode);
 }
 
-GLboolean __stdcall glIsBuffer(GLuint buffer)
+void GL_APIENTRY glStencilThenCoverFillPathCHROMIUM(GLuint path,
+                                                    GLenum fillMode,
+                                                    GLuint mask,
+                                                    GLenum coverMode)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", buffer);
-#else
-    EVENT("(GLuint buffer = %d)", buffer);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context && buffer)
-        {
-            gl::Buffer *bufferObject = context->getBuffer(buffer);
-
-            if (bufferObject)
-            {
-                return GL_TRUE;
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
-    }
-
-    return GL_FALSE;
+    gl::StencilThenCoverFillPathCHROMIUM(path, fillMode, mask, coverMode);
 }
 
-GLboolean __stdcall glIsEnabled(GLenum cap)
+void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUM(GLuint path,
+                                                      GLint reference,
+                                                      GLuint mask,
+                                                      GLenum coverMode)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X)", cap);
-#else
-    EVENT("(GLenum cap = 0x%X)", cap);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            switch (cap)
-            {
-              case GL_CULL_FACE:                return context->isCullFaceEnabled();
-              case GL_POLYGON_OFFSET_FILL:      return context->isPolygonOffsetFillEnabled();
-              case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
-              case GL_SAMPLE_COVERAGE:          return context->isSampleCoverageEnabled();
-              case GL_SCISSOR_TEST:             return context->isScissorTestEnabled();
-              case GL_STENCIL_TEST:             return context->isStencilTestEnabled();
-              case GL_DEPTH_TEST:               return context->isDepthTestEnabled();
-              case GL_BLEND:                    return context->isBlendEnabled();
-              case GL_DITHER:                   return context->isDitherEnabled();
-              default:
-                return gl::error(GL_INVALID_ENUM, false);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    return false;
+    gl::StencilThenCoverStrokePathCHROMIUM(path, reference, mask, coverMode);
 }
 
-GLboolean __stdcall glIsFenceNV(GLuint fence)
+void GL_APIENTRY glCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                  GLenum pathNameType,
+                                                  const void *paths,
+                                                  GLuint pathBase,
+                                                  GLenum coverMode,
+                                                  GLenum transformType,
+                                                  const GLfloat *transformValues)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", fence);
-#else
-    EVENT("(GLuint fence = %d)", fence);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Fence *fenceObject = context->getFence(fence);
-
-            if (fenceObject == NULL)
-            {
-                return GL_FALSE;
-            }
-
-            return fenceObject->isFence();
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
-    }
-
-    return GL_FALSE;
+    gl::CoverFillPathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, coverMode,
+                                       transformType, transformValues);
 }
 
-GLboolean __stdcall glIsFramebuffer(GLuint framebuffer)
+void GL_APIENTRY glCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                    GLenum pathNameType,
+                                                    const void *paths,
+                                                    GLuint pathBase,
+                                                    GLenum coverMode,
+                                                    GLenum transformType,
+                                                    const GLfloat *transformValues)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", framebuffer);
-#else
-    EVENT("(GLuint framebuffer = %d)", framebuffer);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context && framebuffer)
-        {
-            gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
-
-            if (framebufferObject)
-            {
-                return GL_TRUE;
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
-    }
-
-    return GL_FALSE;
+    gl::CoverStrokePathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, coverMode,
+                                         transformType, transformValues);
 }
 
-GLboolean __stdcall glIsProgram(GLuint program)
+void GL_APIENTRY glStencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                    GLenum pathNameType,
+                                                    const void *paths,
+                                                    GLuint pathBase,
+                                                    GLenum fillMode,
+                                                    GLuint mask,
+                                                    GLenum transformType,
+                                                    const GLfloat *transformValues)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", program);
-#else
-    EVENT("(GLuint program = %d)", program);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context && program)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (programObject)
-            {
-                return GL_TRUE;
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
-    }
-
-    return GL_FALSE;
+    gl::StencilFillPathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, fillMode, mask,
+                                         transformType, transformValues);
 }
 
-GLboolean __stdcall glIsQueryEXT(GLuint id)
+void GL_APIENTRY glStencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                      GLenum pathNameType,
+                                                      const void *paths,
+                                                      GLuint pathBase,
+                                                      GLint reference,
+                                                      GLuint mask,
+                                                      GLenum transformType,
+                                                      const GLfloat *transformValues)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", id);
-#else
-    EVENT("(GLuint id = %d)", id);
-#endif
-
-    try
-    {
-        if (id == 0)
-        {
-            return GL_FALSE;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
-
-            if (queryObject)
-            {
-                return GL_TRUE;
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
-    }
-
-    return GL_FALSE;
+    gl::StencilStrokePathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, reference, mask,
+                                           transformType, transformValues);
 }
 
-GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer)
+void GL_APIENTRY glStencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                             GLenum pathNameType,
+                                                             const void *paths,
+                                                             GLuint pathBase,
+                                                             GLenum fillMode,
+                                                             GLuint mask,
+                                                             GLenum coverMode,
+                                                             GLenum transformType,
+                                                             const GLfloat *transformValues)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", renderbuffer);
-#else
-    EVENT("(GLuint renderbuffer = %d)", renderbuffer);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context && renderbuffer)
-        {
-            gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
-
-            if (renderbufferObject)
-            {
-                return GL_TRUE;
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
-    }
-
-    return GL_FALSE;
+    gl::StencilThenCoverFillPathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, fillMode,
+                                                  mask, coverMode, transformType, transformValues);
 }
 
-GLboolean __stdcall glIsShader(GLuint shader)
+void GL_APIENTRY glStencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                               GLenum pathNameType,
+                                                               const void *paths,
+                                                               GLuint pathBase,
+                                                               GLint reference,
+                                                               GLuint mask,
+                                                               GLenum coverMode,
+                                                               GLenum transformType,
+                                                               const GLfloat *transformValues)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", shader);
-#else
-    EVENT("(GLuint shader = %d)", shader);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context && shader)
-        {
-            gl::Shader *shaderObject = context->getShader(shader);
-
-            if (shaderObject)
-            {
-                return GL_TRUE;
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
-    }
-
-    return GL_FALSE;
+    gl::StencilThenCoverStrokePathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase,
+                                                    reference, mask, coverMode, transformType,
+                                                    transformValues);
 }
 
-GLboolean __stdcall glIsTexture(GLuint texture)
+void GL_APIENTRY glBindFragmentInputLocationCHROMIUM(GLuint program,
+                                                     GLint location,
+                                                     const GLchar *name)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", texture);
-#else
-    EVENT("(GLuint texture = %d)", texture);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context && texture)
-        {
-            gl::Texture *textureObject = context->getTexture(texture);
-
-            if (textureObject)
-            {
-                return GL_TRUE;
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
-    }
-
-    return GL_FALSE;
+    gl::BindFragmentInputLocationCHROMIUM(program, location, name);
 }
 
-void __stdcall glLineWidth(GLfloat width)
+void GL_APIENTRY glProgramPathFragmentInputGenCHROMIUM(GLuint program,
+                                                       GLint location,
+                                                       GLenum genMode,
+                                                       GLint components,
+                                                       const GLfloat *coeffs)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%f)", width);
-#else
-    EVENT("(GLfloat width = %f)", width);
-#endif
-
-    try
-    {
-        if (width <= 0.0f)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->setLineWidth(width);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramPathFragmentInputGenCHROMIUM(program, location, genMode, components, coeffs);
 }
 
-void __stdcall glLinkProgram(GLuint program)
+// GLES 3.1
+void GL_APIENTRY glDispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", program);
-#else
-    EVENT("(GLuint program = %d)", program);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
-
-            context->linkProgram(program);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::DispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
 }
 
-void __stdcall glPixelStorei(GLenum pname, GLint param)
+void GL_APIENTRY glDispatchComputeIndirect(GLintptr indirect)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d)", pname, param);
-#else
-    EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            switch (pname)
-            {
-              case GL_UNPACK_ALIGNMENT:
-                if (param != 1 && param != 2 && param != 4 && param != 8)
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-
-                context->setUnpackAlignment(param);
-                break;
-
-              case GL_PACK_ALIGNMENT:
-                if (param != 1 && param != 2 && param != 4 && param != 8)
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-
-                context->setPackAlignment(param);
-                break;
-
-              case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
-                context->setPackReverseRowOrder(param != 0);
-                break;
-
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::DispatchComputeIndirect(indirect);
 }
 
-void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
+void GL_APIENTRY glDrawArraysIndirect(GLenum mode, const void *indirect)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%f, %f)", factor, units);
-#else
-    EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->setPolygonOffsetParams(factor, units);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::DrawArraysIndirect(mode, indirect);
 }
 
-void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
-                                GLenum format, GLenum type, GLsizei bufSize,
-                                GLvoid *data)
+void GL_APIENTRY glDrawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, %d, 0x%X, 0x%X, 0x%d, 0x%0.8p)",
-          x, y, width, height, format, type, bufSize, data);
-#else
-    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
-          "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
-          x, y, width, height, format, type, bufSize, data);
-#endif
-
-    try
-    {
-        if (width < 0 || height < 0 || bufSize < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            GLenum currentFormat, currentType;
-    
-            // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound,
-            // and attempting to read back if that's the case is an error. The error will be registered
-            // by getCurrentReadFormat.
-            if (!context->getCurrentReadFormatType(&currentFormat, &currentType))
-                return;
-
-            if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            context->readPixels(x, y, width, height, format, type, &bufSize, data);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::DrawElementsIndirect(mode, type, indirect);
 }
 
-void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
-                            GLenum format, GLenum type, GLvoid* pixels)
+void GL_APIENTRY glFramebufferParameteri(GLenum target, GLenum pname, GLint param)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, %d, 0x%X, 0x%X, 0x%0.8p)",
-          x, y, width, height, format, type,  pixels);
-#else
-    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
-          "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
-          x, y, width, height, format, type,  pixels);
-#endif
-
-    try
-    {
-        if (width < 0 || height < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            GLenum currentFormat, currentType;
-    
-            // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound,
-            // and attempting to read back if that's the case is an error. The error will be registered
-            // by getCurrentReadFormat.
-            if (!context->getCurrentReadFormatType(&currentFormat, &currentType))
-                return;
-
-            if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            context->readPixels(x, y, width, height, format, type, NULL, pixels);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::FramebufferParameteri(target, pname, param);
 }
 
-void __stdcall glReleaseShaderCompiler(void)
+void GL_APIENTRY glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
 {
-    EVENT("()");
-
-    try
-    {
-        gl::Shader::releaseCompiler();
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetFramebufferParameteriv(target, pname, params);
 }
 
-void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glGetProgramInterfaceiv(GLuint program,
+                                         GLenum programInterface,
+                                         GLenum pname,
+                                         GLint *params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, 0x%X, %d, %d)",
-          target, samples, internalformat, width, height);
-#else
-    EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
-          target, samples, internalformat, width, height);
-#endif
-
-    try
-    {
-        switch (target)
-        {
-          case GL_RENDERBUFFER:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        if (!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat))
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        if (width < 0 || height < 0 || samples < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (width > context->getMaximumRenderbufferDimension() || 
-                height > context->getMaximumRenderbufferDimension() ||
-                samples > context->getMaxSupportedSamples())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            GLuint handle = context->getRenderbufferHandle();
-            if (handle == 0)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            switch (internalformat)
-            {
-              case GL_DEPTH_COMPONENT16:
-              case GL_RGBA4:
-              case GL_RGB5_A1:
-              case GL_RGB565:
-              case GL_RGB8_OES:
-              case GL_RGBA8_OES:
-              case GL_STENCIL_INDEX8:
-              case GL_DEPTH24_STENCIL8_OES:
-                context->setRenderbufferStorage(width, height, internalformat, samples);
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetProgramInterfaceiv(program, programInterface, pname, params);
 }
 
-void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GLuint GL_APIENTRY glGetProgramResourceIndex(GLuint program,
+                                             GLenum programInterface,
+                                             const GLchar *name)
 {
-    glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);
+    return gl::GetProgramResourceIndex(program, programInterface, name);
 }
 
-void __stdcall glSampleCoverage(GLclampf value, GLboolean invert)
+void GL_APIENTRY glGetProgramResourceName(GLuint program,
+                                          GLenum programInterface,
+                                          GLuint index,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLchar *name)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%f, %d)", value, invert);
-#else
-    EVENT("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
-#endif
-
-    try
-    {
-        gl::Context* context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetProgramResourceName(program, programInterface, index, bufSize, length, name);
 }
 
-void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
+void GL_APIENTRY glGetProgramResourceiv(GLuint program,
+                                        GLenum programInterface,
+                                        GLuint index,
+                                        GLsizei propCount,
+                                        const GLenum *props,
+                                        GLsizei bufSize,
+                                        GLsizei *length,
+                                        GLint *params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%X)", fence, condition);
-#else
-    EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
-#endif
-
-    try
-    {
-        if (condition != GL_ALL_COMPLETED_NV)
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Fence *fenceObject = context->getFence(fence);
-
-            if (fenceObject == NULL)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            fenceObject->setFence(condition);    
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetProgramResourceiv(program, programInterface, index, propCount, props, bufSize, length,
+                             params);
 }
 
-void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
+GLint GL_APIENTRY glGetProgramResourceLocation(GLuint program,
+                                               GLenum programInterface,
+                                               const GLchar *name)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, %d)", x, y, width, height);
-#else
-    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
-#endif
-
-    try
-    {
-        if (width < 0 || height < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context* context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->setScissorParams(x, y, width, height);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    return gl::GetProgramResourceLocation(program, programInterface, name);
 }
 
-void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+void GL_APIENTRY glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p, 0x%X, 0x%0.8p, %d)",
-          n, shaders, binaryformat, binary, length);
-#else
-    EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
-          "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
-          n, shaders, binaryformat, binary, length);
-#endif
-
-    try
-    {
-        // No binary shader formats are supported.
-        return gl::error(GL_INVALID_ENUM);
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::UseProgramStages(pipeline, stages, program);
 }
 
-void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+void GL_APIENTRY glActiveShaderProgram(GLuint pipeline, GLuint program)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p, 0x%0.8p)",
-          shader, count, string, length);
-#else
-    EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
-          shader, count, string, length);
-#endif
-
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Shader *shaderObject = context->getShader(shader);
-
-            if (!shaderObject)
-            {
-                if (context->getProgram(shader))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
-
-            shaderObject->setSource(count, string, length);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ActiveShaderProgram(pipeline, program);
 }
 
-void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask)
+GLuint GL_APIENTRY glCreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const *strings)
 {
-    glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
+    return gl::CreateShaderProgramv(type, count, strings);
 }
 
-void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+void GL_APIENTRY glBindProgramPipeline(GLuint pipeline)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, %d, %d)", face, func, ref, mask);
-#else
-    EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
-#endif
-
-    try
-    {
-        switch (face)
-        {
-          case GL_FRONT:
-          case GL_BACK:
-          case GL_FRONT_AND_BACK:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        switch (func)
-        {
-          case GL_NEVER:
-          case GL_ALWAYS:
-          case GL_LESS:
-          case GL_LEQUAL:
-          case GL_EQUAL:
-          case GL_GEQUAL:
-          case GL_GREATER:
-          case GL_NOTEQUAL:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
-            {
-                context->setStencilParams(func, ref, mask);
-            }
-
-            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
-            {
-                context->setStencilBackParams(func, ref, mask);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::BindProgramPipeline(pipeline);
 }
 
-void __stdcall glStencilMask(GLuint mask)
+void GL_APIENTRY glDeleteProgramPipelines(GLsizei n, const GLuint *pipelines)
 {
-    glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
+    gl::DeleteProgramPipelines(n, pipelines);
 }
 
-void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask)
+void GL_APIENTRY glGenProgramPipelines(GLsizei n, GLuint *pipelines)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d)", face, mask);
-#else
-    EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
-#endif
-
-    try
-    {
-        switch (face)
-        {
-          case GL_FRONT:
-          case GL_BACK:
-          case GL_FRONT_AND_BACK:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
-            {
-                context->setStencilWritemask(mask);
-            }
-
-            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
-            {
-                context->setStencilBackWritemask(mask);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GenProgramPipelines(n, pipelines);
 }
 
-void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+GLboolean GL_APIENTRY glIsProgramPipeline(GLuint pipeline)
 {
-    glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
+    return gl::IsProgramPipeline(pipeline);
 }
 
-void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+void GL_APIENTRY glGetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, 0x%X, 0x%Xs)",
-          face, fail, zfail, zpass);
-#else
-    EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
-          face, fail, zfail, zpass);
-#endif
-
-    try
-    {
-        switch (face)
-        {
-          case GL_FRONT:
-          case GL_BACK:
-          case GL_FRONT_AND_BACK:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        switch (fail)
-        {
-          case GL_ZERO:
-          case GL_KEEP:
-          case GL_REPLACE:
-          case GL_INCR:
-          case GL_DECR:
-          case GL_INVERT:
-          case GL_INCR_WRAP:
-          case GL_DECR_WRAP:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        switch (zfail)
-        {
-          case GL_ZERO:
-          case GL_KEEP:
-          case GL_REPLACE:
-          case GL_INCR:
-          case GL_DECR:
-          case GL_INVERT:
-          case GL_INCR_WRAP:
-          case GL_DECR_WRAP:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        switch (zpass)
-        {
-          case GL_ZERO:
-          case GL_KEEP:
-          case GL_REPLACE:
-          case GL_INCR:
-          case GL_DECR:
-          case GL_INVERT:
-          case GL_INCR_WRAP:
-          case GL_DECR_WRAP:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
-            {
-                context->setStencilOperations(fail, zfail, zpass);
-            }
-
-            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
-            {
-                context->setStencilBackOperations(fail, zfail, zpass);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetProgramPipelineiv(pipeline, pname, params);
 }
 
-GLboolean __stdcall glTestFenceNV(GLuint fence)
+void GL_APIENTRY glProgramUniform1i(GLuint program, GLint location, GLint v0)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", fence);
-#else
-    EVENT("(GLuint fence = %d)", fence);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Fence *fenceObject = context->getFence(fence);
-
-            if (fenceObject == NULL)
-            {
-                return gl::error(GL_INVALID_OPERATION, GL_TRUE);
-            }
-
-            return fenceObject->testFence();
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        gl::error(GL_OUT_OF_MEMORY);
-    }
-    
-    return GL_TRUE;
+    gl::ProgramUniform1i(program, location, v0);
 }
 
-void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
-                            GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+void GL_APIENTRY glProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, %d, %d, %d, %d, 0x%X, 0x%X, 0x%0.8p)",
-          target, level, internalformat, width, height, border, format, type, pixels);
-#else
-    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
-          "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels =  0x%0.8p)",
-          target, level, internalformat, width, height, border, format, type, pixels);
-#endif
-
-    try
-    {
-        if (!validImageSize(level, width, height))
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (internalformat != GLint(format))
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
-
-        // validate <type> by itself (used as secondary key below)
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-          case GL_UNSIGNED_SHORT_5_6_5:
-          case GL_UNSIGNED_SHORT_4_4_4_4:
-          case GL_UNSIGNED_SHORT_5_5_5_1:
-          case GL_UNSIGNED_SHORT:
-          case GL_UNSIGNED_INT:
-          case GL_UNSIGNED_INT_24_8_OES:
-          case GL_HALF_FLOAT_OES:
-          case GL_FLOAT:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        // validate <format> + <type> combinations
-        // - invalid <format> -> sets INVALID_ENUM
-        // - invalid <format>+<type> combination -> sets INVALID_OPERATION
-        switch (format)
-        {
-          case GL_ALPHA:
-          case GL_LUMINANCE:
-          case GL_LUMINANCE_ALPHA:
-            switch (type)
-            {
-              case GL_UNSIGNED_BYTE:
-              case GL_FLOAT:
-              case GL_HALF_FLOAT_OES:
-                break;
-              default:
-                return gl::error(GL_INVALID_OPERATION);
-            }
-            break;
-          case GL_RGB:
-            switch (type)
-            {
-              case GL_UNSIGNED_BYTE:
-              case GL_UNSIGNED_SHORT_5_6_5:
-              case GL_FLOAT:
-              case GL_HALF_FLOAT_OES:
-                break;
-              default:
-                return gl::error(GL_INVALID_OPERATION);
-            }
-            break;
-          case GL_RGBA:
-            switch (type)
-            {
-              case GL_UNSIGNED_BYTE:
-              case GL_UNSIGNED_SHORT_4_4_4_4:
-              case GL_UNSIGNED_SHORT_5_5_5_1:
-              case GL_FLOAT:
-              case GL_HALF_FLOAT_OES:
-                break;
-              default:
-                return gl::error(GL_INVALID_OPERATION);
-            }
-            break;
-          case GL_BGRA_EXT:
-            switch (type)
-            {
-              case GL_UNSIGNED_BYTE:
-                break;
-              default:
-                return gl::error(GL_INVALID_OPERATION);
-            }
-            break;
-          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:  // error cases for compressed textures are handled below
-          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-            break; 
-          case GL_DEPTH_COMPONENT:
-            switch (type)
-            {
-              case GL_UNSIGNED_SHORT:
-              case GL_UNSIGNED_INT:
-                break;
-              default:
-                return gl::error(GL_INVALID_OPERATION);
-            }
-            break;
-          case GL_DEPTH_STENCIL_OES:
-            switch (type)
-            {
-              case GL_UNSIGNED_INT_24_8_OES:
-                break;
-              default:
-                return gl::error(GL_INVALID_OPERATION);
-            }
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        if (border != 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (level > context->getMaximumTextureLevel())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                if (width > (context->getMaximumTextureDimension() >> level) ||
-                    height > (context->getMaximumTextureDimension() >> level))
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-                if (width != height)
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-
-                if (width > (context->getMaximumCubeTextureDimension() >> level) ||
-                    height > (context->getMaximumCubeTextureDimension() >> level))
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            switch (format) {
-              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-                if (context->supportsDXT1Textures())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-                if (context->supportsDXT3Textures())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-                if (context->supportsDXT5Textures())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_DEPTH_COMPONENT:
-              case GL_DEPTH_STENCIL_OES:
-                if (!context->supportsDepthTextures())
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                if (target != GL_TEXTURE_2D)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                // OES_depth_texture supports loading depth data and multiple levels,
-                // but ANGLE_depth_texture does not
-                if (pixels != NULL || level != 0)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                break;
-              default:
-                break;
-            }
-
-            if (type == GL_FLOAT)
-            {
-                if (!context->supportsFloat32Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-            }
-            else if (type == GL_HALF_FLOAT_OES)
-            {
-                if (!context->supportsFloat16Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-            }
-
-            if (target == GL_TEXTURE_2D)
-            {
-                gl::Texture2D *texture = context->getTexture2D();
-
-                if (!texture)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                if (texture->isImmutable())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);
-            }
-            else
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
-
-                if (!texture)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                if (texture->isImmutable())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                switch (target)
-                {
-                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-                    texture->setImagePosX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
-                    break;
-                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-                    texture->setImageNegX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
-                    break;
-                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-                    texture->setImagePosY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
-                    break;
-                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-                    texture->setImageNegY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
-                    break;
-                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-                    texture->setImagePosZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
-                    break;
-                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-                    texture->setImageNegZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
-                    break;
-                  default: UNREACHABLE();
-                }
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform2i(program, location, v0, v1);
 }
 
-void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+void GL_APIENTRY glProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, %f)", target, pname, param);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Texture *texture;
-
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                texture = context->getTexture2D();
-                break;
-              case GL_TEXTURE_CUBE_MAP:
-                texture = context->getTextureCubeMap();
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            switch (pname)
-            {
-              case GL_TEXTURE_WRAP_S:
-                if (!texture->setWrapS((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_WRAP_T:
-                if (!texture->setWrapT((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_MIN_FILTER:
-                if (!texture->setMinFilter((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_MAG_FILTER:
-                if (!texture->setMagFilter((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_USAGE_ANGLE:
-                if (!texture->setUsage((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
-                if (!context->supportsTextureFilterAnisotropy())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()))
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform3i(program, location, v0, v1, v2);
 }
 
-void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+void GL_APIENTRY
+glProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
 {
-    glTexParameterf(target, pname, (GLfloat)*params);
+    gl::ProgramUniform4i(program, location, v0, v1, v2, v3);
 }
 
-void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
+void GL_APIENTRY glProgramUniform1ui(GLuint program, GLint location, GLuint v0)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%X, %d)", target, pname, param);
-#else
-    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Texture *texture;
-
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                texture = context->getTexture2D();
-                break;
-              case GL_TEXTURE_CUBE_MAP:
-                texture = context->getTextureCubeMap();
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            switch (pname)
-            {
-              case GL_TEXTURE_WRAP_S:
-                if (!texture->setWrapS((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_WRAP_T:
-                if (!texture->setWrapT((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_MIN_FILTER:
-                if (!texture->setMinFilter((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_MAG_FILTER:
-                if (!texture->setMagFilter((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_USAGE_ANGLE:
-                if (!texture->setUsage((GLenum)param))
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
-                if (!context->supportsTextureFilterAnisotropy())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()))
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform1ui(program, location, v0);
 }
 
-void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+void GL_APIENTRY glProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1)
 {
-    glTexParameteri(target, pname, *params);
+    gl::ProgramUniform2ui(program, location, v0, v1);
 }
 
-void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY
+glProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, 0x%X, %d, %d)",
-           target, levels, internalformat, width, height);
-#else
-    EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
-           target, levels, internalformat, width, height);
-#endif
-
-    try
-    {
-        if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        if (width < 1 || height < 1 || levels < 1)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (target == GL_TEXTURE_CUBE_MAP && width != height)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
-        {
-            return gl::error(GL_INVALID_OPERATION);
-        }
-
-        GLenum format = gl::ExtractFormat(internalformat);
-        GLenum type = gl::ExtractType(internalformat);
-
-        if (format == GL_NONE || type == GL_NONE)
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            switch (target)
-            {
-              case GL_TEXTURE_2D:
-                if (width > context->getMaximumTextureDimension() ||
-                    height > context->getMaximumTextureDimension())
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              case GL_TEXTURE_CUBE_MAP:
-                if (width > context->getMaximumCubeTextureDimension() ||
-                    height > context->getMaximumCubeTextureDimension())
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-                break;
-              default:
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            if (levels != 1 && !context->supportsNonPower2Texture())
-            {
-                if (!gl::isPow2(width) || !gl::isPow2(height))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-            }
-
-            switch (internalformat)
-            {
-              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-                if (!context->supportsDXT1Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-                if (!context->supportsDXT3Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-                if (!context->supportsDXT5Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_RGBA32F_EXT:
-              case GL_RGB32F_EXT:
-              case GL_ALPHA32F_EXT:
-              case GL_LUMINANCE32F_EXT:
-              case GL_LUMINANCE_ALPHA32F_EXT:
-                if (!context->supportsFloat32Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_RGBA16F_EXT:
-              case GL_RGB16F_EXT:
-              case GL_ALPHA16F_EXT:
-              case GL_LUMINANCE16F_EXT:
-              case GL_LUMINANCE_ALPHA16F_EXT:
-                if (!context->supportsFloat16Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                break;
-              case GL_DEPTH_COMPONENT16:
-              case GL_DEPTH_COMPONENT32_OES:
-              case GL_DEPTH24_STENCIL8_OES:
-                if (!context->supportsDepthTextures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                if (target != GL_TEXTURE_2D)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                // ANGLE_depth_texture only supports 1-level textures
-                if (levels != 1)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                break;
-              default:
-                break;
-            }
-
-            if (target == GL_TEXTURE_2D)
-            {
-                gl::Texture2D *texture = context->getTexture2D();
-
-                if (!texture || texture->id() == 0)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                if (texture->isImmutable())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                texture->storage(levels, internalformat, width, height);
-            }
-            else if (target == GL_TEXTURE_CUBE_MAP)
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
-
-                if (!texture || texture->id() == 0)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                if (texture->isImmutable())
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                texture->storage(levels, internalformat, width);
-            }
-            else UNREACHABLE();
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform3ui(program, location, v0, v1, v2);
 }
 
-void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                               GLenum format, GLenum type, const GLvoid* pixels)
+void GL_APIENTRY
+glProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, %d, %d, %d, %d, 0x%X, 0x%X, 0x%0.8p)",
-           target, level, xoffset, yoffset, width, height, format, type, pixels);
-#else
-    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
-          "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
-          "const GLvoid* pixels = 0x%0.8p)",
-           target, level, xoffset, yoffset, width, height, format, type, pixels);
-#endif
-
-    try
-    {
-        if (!gl::IsInternalTextureTarget(target))
-        {
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (!checkTextureFormatType(format, type))
-        {
-            return; // error is set by helper function
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (level > context->getMaximumTextureLevel())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            if (format == GL_FLOAT)
-            {
-                if (!context->supportsFloat32Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-            }
-            else if (format == GL_HALF_FLOAT_OES)
-            {
-                if (!context->supportsFloat16Textures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-            }
-            else if (gl::IsDepthTexture(format))
-            {
-                if (!context->supportsDepthTextures())
-                {
-                    return gl::error(GL_INVALID_ENUM);
-                }
-                if (target != GL_TEXTURE_2D)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                // OES_depth_texture supports loading depth data, but ANGLE_depth_texture does not
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (width == 0 || height == 0 || pixels == NULL)
-            {
-                return;
-            }
-
-            if (target == GL_TEXTURE_2D)
-            {
-                gl::Texture2D *texture = context->getTexture2D();
-                if (validateSubImageParams2D(false, width, height, xoffset, yoffset, level, format, type, texture))
-                {
-                    texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
-                }
-            }
-            else if (gl::IsCubemapTextureTarget(target))
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                if (validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, format, type, texture))
-                {
-                    texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
-                }
-            }
-            else
-            {
-                UNREACHABLE();
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform4ui(program, location, v0, v1, v2, v3);
 }
 
-void __stdcall glUniform1f(GLint location, GLfloat x)
+void GL_APIENTRY glProgramUniform1f(GLuint program, GLint location, GLfloat v0)
 {
-    glUniform1fv(location, 1, &x);
+    gl::ProgramUniform1f(program, location, v0);
 }
 
-void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", location, count, v);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-#endif
-
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniform1fv(location, count, v))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform2f(program, location, v0, v1);
 }
 
-void __stdcall glUniform1i(GLint location, GLint x)
+void GL_APIENTRY
+glProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
 {
-    glUniform1iv(location, 1, &x);
+    gl::ProgramUniform3f(program, location, v0, v1, v2);
 }
 
-void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY
+glProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", location, count, v);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-#endif
-
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniform1iv(location, count, v))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform4f(program, location, v0, v1, v2, v3);
 }
 
-void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y)
+void GL_APIENTRY glProgramUniform1iv(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLint *value)
 {
-    GLfloat xy[2] = {x, y};
-
-    glUniform2fv(location, 1, (GLfloat*)&xy);
+    gl::ProgramUniform1iv(program, location, count, value);
 }
 
-void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glProgramUniform2iv(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLint *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", location, count, v);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-#endif
-
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-        
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniform2fv(location, count, v))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform2iv(program, location, count, value);
 }
 
-void __stdcall glUniform2i(GLint location, GLint x, GLint y)
+void GL_APIENTRY glProgramUniform3iv(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLint *value)
 {
-    GLint xy[4] = {x, y};
-
-    glUniform2iv(location, 1, (GLint*)&xy);
+    gl::ProgramUniform3iv(program, location, count, value);
 }
 
-void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glProgramUniform4iv(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLint *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", location, count, v);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-#endif
-
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniform2iv(location, count, v))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform4iv(program, location, count, value);
 }
 
-void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+void GL_APIENTRY glProgramUniform1uiv(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLuint *value)
 {
-    GLfloat xyz[3] = {x, y, z};
-
-    glUniform3fv(location, 1, (GLfloat*)&xyz);
+    gl::ProgramUniform1uiv(program, location, count, value);
 }
 
-void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glProgramUniform2uiv(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLuint *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", location, count, v);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-#endif
-
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniform3fv(location, count, v))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform2uiv(program, location, count, value);
 }
 
-void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z)
+void GL_APIENTRY glProgramUniform3uiv(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLuint *value)
 {
-    GLint xyz[3] = {x, y, z};
-
-    glUniform3iv(location, 1, (GLint*)&xyz);
+    gl::ProgramUniform3uiv(program, location, count, value);
 }
 
-void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glProgramUniform4uiv(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLuint *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", location, count, v);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-#endif
-
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniform3iv(location, count, v))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform4uiv(program, location, count, value);
 }
 
-void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+void GL_APIENTRY glProgramUniform1fv(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLfloat *value)
 {
-    GLfloat xyzw[4] = {x, y, z, w};
-
-    glUniform4fv(location, 1, (GLfloat*)&xyzw);
+    gl::ProgramUniform1fv(program, location, count, value);
 }
 
-void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glProgramUniform2fv(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", location, count, v);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-#endif
-
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniform4fv(location, count, v))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform2fv(program, location, count, value);
 }
 
-void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+void GL_APIENTRY glProgramUniform3fv(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLfloat *value)
 {
-    GLint xyzw[4] = {x, y, z, w};
-
-    glUniform4iv(location, 1, (GLint*)&xyzw);
+    gl::ProgramUniform3fv(program, location, count, value);
 }
 
-void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glProgramUniform4fv(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%0.8p)", location, count, v);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-#endif
-
-    try
-    {
-        if (count < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniform4iv(location, count, v))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniform4fv(program, location, count, value);
 }
 
-void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glProgramUniformMatrix2fv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, 0x%0.8p)",
-          location, count, transpose, value);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
-          location, count, transpose, value);
-#endif
-
-    try
-    {
-        if (count < 0 || transpose != GL_FALSE)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniformMatrix2fv(location, count, value))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniformMatrix2fv(program, location, count, transpose, value);
 }
 
-void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glProgramUniformMatrix3fv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, 0x%0.8p)",
-          location, count, transpose, value);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
-          location, count, transpose, value);
-#endif
-
-    try
-    {
-        if (count < 0 || transpose != GL_FALSE)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniformMatrix3fv(location, count, value))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniformMatrix3fv(program, location, count, transpose, value);
 }
 
-void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glProgramUniformMatrix4fv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, 0x%0.8p)",
-          location, count, transpose, value);
-#else
-    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
-          location, count, transpose, value);
-#endif
-
-    try
-    {
-        if (count < 0 || transpose != GL_FALSE)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (location == -1)
-        {
-            return;
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->setUniformMatrix4fv(location, count, value))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniformMatrix4fv(program, location, count, transpose, value);
 }
 
-void __stdcall glUseProgram(GLuint program)
+void GL_APIENTRY glProgramUniformMatrix2x3fv(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", program);
-#else
-    EVENT("(GLuint program = %d)", program);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject && program != 0)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
-
-            if (program != 0 && !programObject->isLinked())
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            context->useProgram(program);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniformMatrix2x3fv(program, location, count, transpose, value);
 }
 
-void __stdcall glValidateProgram(GLuint program)
+void GL_APIENTRY glProgramUniformMatrix3x2fv(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d)", program);
-#else
-    EVENT("(GLuint program = %d)", program);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                if (context->getShader(program))
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-                else
-                {
-                    return gl::error(GL_INVALID_VALUE);
-                }
-            }
-
-            programObject->validate();
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniformMatrix3x2fv(program, location, count, transpose, value);
 }
 
-void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
+void GL_APIENTRY glProgramUniformMatrix2x4fv(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %f)", index, x);
-#else
-    EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            GLfloat vals[4] = { x, 0, 0, 1 };
-            context->setVertexAttrib(index, vals);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniformMatrix2x4fv(program, location, count, transpose, value);
 }
 
-void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glProgramUniformMatrix4x2fv(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", index, values);
-#else
-    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            GLfloat vals[4] = { values[0], 0, 0, 1 };
-            context->setVertexAttrib(index, vals);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniformMatrix4x2fv(program, location, count, transpose, value);
 }
 
-void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+void GL_APIENTRY glProgramUniformMatrix3x4fv(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %f, %f)", index, x, y);
-#else
-    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            GLfloat vals[4] = { x, y, 0, 1 };
-            context->setVertexAttrib(index, vals);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniformMatrix3x4fv(program, location, count, transpose, value);
 }
 
-void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glProgramUniformMatrix4x3fv(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat *value)
 {
-#if defined(__LB_XB360__)
-    EVENT("(d, 0x%0.8p)", index, values);
-#else
-    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            GLfloat vals[4] = { values[0], values[1], 0, 1 };
-            context->setVertexAttrib(index, vals);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ProgramUniformMatrix4x3fv(program, location, count, transpose, value);
 }
 
-void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+void GL_APIENTRY glValidateProgramPipeline(GLuint pipeline)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %f, %f, %f)", index, x, y, z);
-#else
-    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            GLfloat vals[4] = { x, y, z, 1 };
-            context->setVertexAttrib(index, vals);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::ValidateProgramPipeline(pipeline);
 }
 
-void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glGetProgramPipelineInfoLog(GLuint pipeline,
+                                             GLsizei bufSize,
+                                             GLsizei *length,
+                                             GLchar *infoLog)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", index, values);
-#else
-    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            GLfloat vals[4] = { values[0], values[1], values[2], 1 };
-            context->setVertexAttrib(index, vals);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetProgramPipelineInfoLog(pipeline, bufSize, length, infoLog);
 }
 
-void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+void GL_APIENTRY glBindImageTexture(GLuint unit,
+                                    GLuint texture,
+                                    GLint level,
+                                    GLboolean layered,
+                                    GLint layer,
+                                    GLenum access,
+                                    GLenum format)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %f, %f, %f, %f)", index, x, y, z, w);
-#else
-    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            GLfloat vals[4] = { x, y, z, w };
-            context->setVertexAttrib(index, vals);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::BindImageTexture(unit, texture, level, layered, layer, access, format);
 }
 
-void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glGetBooleani_v(GLenum target, GLuint index, GLboolean *data)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", index, values);
-#else
-    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->setVertexAttrib(index, values);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetBooleani_v(target, index, data);
 }
 
-void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+void GL_APIENTRY glMemoryBarrier(GLbitfield barriers)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d)", index, divisor);
-#else
-    EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->setVertexAttribDivisor(index, divisor);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::MemoryBarrier(barriers);
 }
 
-void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+void GL_APIENTRY glMemoryBarrierByRegion(GLbitfield barriers)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, 0x%X, %d, %d, 0x%0.8p)",
-          index, size, type, normalized, stride, ptr);
-#else
-    EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
-          "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
-          index, size, type, normalized, stride, ptr);
-#endif
-
-    try
-    {
-        if (index >= gl::MAX_VERTEX_ATTRIBS)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (size < 1 || size > 4)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        switch (type)
-        {
-          case GL_BYTE:
-          case GL_UNSIGNED_BYTE:
-          case GL_SHORT:
-          case GL_UNSIGNED_SHORT:
-          case GL_FIXED:
-          case GL_FLOAT:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        if (stride < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::MemoryBarrierByRegion(barriers);
 }
 
-void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glTexStorage2DMultisample(GLenum target,
+                                           GLsizei samples,
+                                           GLenum internalformat,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLboolean fixedsamplelocations)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, %d)", x, y, width, height);
-#else
-    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
-#endif
-
-    try
-    {
-        if (width < 0 || height < 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            context->setViewportParams(x, y, width, height);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::TexStorage2DMultisample(target, samples, internalformat, width, height,
+                                fixedsamplelocations);
 }
 
-void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                                      GLbitfield mask, GLenum filter)
+void GL_APIENTRY glGetMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, %d, %d, %d, %d, %d, %d, %d, 0x%X, 0x%X)",
-          srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-#else
-    EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
-          "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
-          "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
-          srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-#endif
-
-    try
-    {
-        switch (filter)
-        {
-          case GL_NEAREST:
-            break;
-          default:
-            return gl::error(GL_INVALID_ENUM);
-        }
-
-        if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
-        {
-            ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
-            return gl::error(GL_INVALID_OPERATION);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
-            {
-                ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetMultisamplefv(pname, index, val);
 }
 
-void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
-                               GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+void GL_APIENTRY glSampleMaski(GLuint maskNumber, GLbitfield mask)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, 0x%X, %d, %d, %d, %d, 0x%X, 0x%x, 0x%0.8p)",
-          target, level, internalformat, width, height, depth, border, format, type, pixels);
-#else
-    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
-          "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
-          "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
-          target, level, internalformat, width, height, depth, border, format, type, pixels);
-#endif
-
-    try
-    {
-        UNIMPLEMENTED();   // FIXME
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::SampleMaski(maskNumber, mask);
 }
 
-void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, 
-                                     GLenum *binaryFormat, void *binary)
+void GL_APIENTRY glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, %d, 0x%0.8p, 0x%0.8p, 0x%0.8p)",
-          program, bufSize, length, binaryFormat, binary);
-#else
-    EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)",
-          program, bufSize, length, binaryFormat, binary);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject || !programObject->isLinked())
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-
-            if (!programBinary)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            if (!programBinary->save(binary, bufSize, length))
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetTexLevelParameteriv(target, level, pname, params);
 }
 
-void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
-                                  const void *binary, GLint length)
+void GL_APIENTRY glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%X, 0x%x, 0x%0.8p, %d)",
-          program, binaryFormat, binary, length);
-#else
-    EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)",
-          program, binaryFormat, binary, length);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
-            {
-                return gl::error(GL_INVALID_ENUM);
-            }
-
-            gl::Program *programObject = context->getProgram(program);
-
-            if (!programObject)
-            {
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            context->setProgramBinary(program, binary, length);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::GetTexLevelParameterfv(target, level, pname, params);
 }
 
-void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
+void GL_APIENTRY glBindVertexBuffer(GLuint bindingindex,
+                                    GLuint buffer,
+                                    GLintptr offset,
+                                    GLsizei stride)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%d, 0x%0.8p)", n, bufs);
-#else
-    EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            if (n < 0 || (unsigned int)n > context->getMaximumRenderTargets())
-            {
-                return gl::error(GL_INVALID_VALUE);
-            }
-
-            if (context->getDrawFramebufferHandle() == 0)
-            {
-                if (n != 1)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-
-                if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
-                {
-                    return gl::error(GL_INVALID_OPERATION);
-                }
-            }
-            else
-            {
-                for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
-                {
-                    const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
-                    if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment)
-                    {
-                        return gl::error(GL_INVALID_OPERATION);
-                    }
-                }
-            }
-
-            gl::Framebuffer *framebuffer = context->getDrawFramebuffer();
-
-            for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
-            {
-                framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]);
-            }
-
-            for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++)
-            {
-                framebuffer->setDrawBufferState(colorAttachment, GL_NONE);
-            }
-        }
-    }
-    catch (std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::BindVertexBuffer(bindingindex, buffer, offset, stride);
 }
 
-#if defined(__LB_XB360__)
-void __stdcall glBindTextureToVideoLBSHELL(GLuint texture)
+void GL_APIENTRY glVertexAttribFormat(GLuint attribindex,
+                                      GLint size,
+                                      GLenum type,
+                                      GLboolean normalized,
+                                      GLuint relativeoffset)
 {
-#if defined(__LB_XB360__)
-    EVENT("(%lu)", texture);
-#else
-    EVENT("(GLuint texture = %lu)", texture);
-#endif
-
-    try
-    {
-        if (texture == 0)
-        {
-            return gl::error(GL_INVALID_VALUE);
-        }
-
-        gl::Context *context = gl::getNonLostContext();
-        if (context)
-        {
-            context->setVideoTexture(texture);
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    gl::VertexAttribFormat(attribindex, size, type, normalized, relativeoffset);
 }
-#endif
 
-__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname)
+void GL_APIENTRY glVertexAttribIFormat(GLuint attribindex,
+                                       GLint size,
+                                       GLenum type,
+                                       GLuint relativeoffset)
 {
-    struct Extension
-    {
-        const char *name;
-        __eglMustCastToProperFunctionPointerType address;
-    };
-
-    static const Extension glExtensions[] =
-    {
-        {"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES},
-        {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE},
-        {"glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)glRenderbufferStorageMultisampleANGLE},
-        {"glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)glDeleteFencesNV},
-        {"glGenFencesNV", (__eglMustCastToProperFunctionPointerType)glGenFencesNV},
-        {"glIsFenceNV", (__eglMustCastToProperFunctionPointerType)glIsFenceNV},
-        {"glTestFenceNV", (__eglMustCastToProperFunctionPointerType)glTestFenceNV},
-        {"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV},
-        {"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV},
-        {"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV},
-        {"glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)glGetTranslatedShaderSourceANGLE},
-        {"glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)glTexStorage2DEXT},
-        {"glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)glGetGraphicsResetStatusEXT},
-        {"glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)glReadnPixelsEXT},
-        {"glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformfvEXT},
-        {"glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformivEXT},
-        {"glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)glGenQueriesEXT},
-        {"glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)glDeleteQueriesEXT},
-        {"glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)glIsQueryEXT},
-        {"glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)glBeginQueryEXT},
-        {"glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)glEndQueryEXT},
-        {"glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryivEXT},
-        {"glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryObjectuivEXT},
-        {"glDrawBuffersEXT", (__eglMustCastToProperFunctionPointerType)glDrawBuffersEXT},
-        {"glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)glVertexAttribDivisorANGLE},
-        {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE},
-        {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE},
-        {"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES},
-        {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES},
-#if defined(__LB_XB360__)
-        {"glBindTextureToVideoLBSHELL", (__eglMustCastToProperFunctionPointerType)glBindTextureToVideoLBSHELL},
-#endif
-    };
-
-    for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++)
-    {
-        if (strcmp(procname, glExtensions[ext].name) == 0)
-        {
-            return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
-        }
-    }
-
-    return NULL;
+    gl::VertexAttribIFormat(attribindex, size, type, relativeoffset);
 }
 
-// Non-public functions used by EGL
-
-bool __stdcall glBindTexImage(egl::Surface *surface)
+void GL_APIENTRY glVertexAttribBinding(GLuint attribindex, GLuint bindingindex)
 {
-#if defined(__LB_XB360__)
-    EVENT("(0x%0.8p)", surface);
-#else
-    EVENT("(egl::Surface* surface = 0x%0.8p)",
-          surface);
-#endif
-
-    try
-    {
-        gl::Context *context = gl::getNonLostContext();
-
-        if (context)
-        {
-            gl::Texture2D *textureObject = context->getTexture2D();
-
-            if (textureObject->isImmutable())
-            {
-                return false;
-            }
-
-            if (textureObject)
-            {
-                textureObject->bindTexImage(surface);
-            }
-        }
-    }
-    catch(std::bad_alloc&)
-    {
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    return true;
+    gl::VertexAttribBinding(attribindex, bindingindex);
 }
 
+void GL_APIENTRY glVertexBindingDivisor(GLuint bindingindex, GLuint divisor)
+{
+    gl::VertexBindingDivisor(bindingindex, divisor);
 }
+}  // extern "C"
diff --git a/src/third_party/angle/src/libGLESv2/libGLESv2.def b/src/third_party/angle/src/libGLESv2/libGLESv2.def
index 71398b3..2e73b97 100644
--- a/src/third_party/angle/src/libGLESv2/libGLESv2.def
+++ b/src/third_party/angle/src/libGLESv2/libGLESv2.def
@@ -144,7 +144,6 @@
     glViewport                      @142
 
     ; Extensions
-    glTexImage3DOES                 @143
     glBlitFramebufferANGLE          @149
     glRenderbufferStorageMultisampleANGLE @150
     glDeleteFencesNV                @151
@@ -173,13 +172,241 @@
     glProgramBinaryOES              @175
     glGetProgramBinaryOES           @176
     glDrawBuffersEXT                @179
+    glMapBufferOES                  @285
+    glUnmapBufferOES                @286
+    glGetBufferPointervOES          @287
+    glMapBufferRangeEXT             @288
+    glFlushMappedBufferRangeEXT     @289
+    glDiscardFramebufferEXT         @293
+    glInsertEventMarkerEXT          @294
+    glPushGroupMarkerEXT            @295
+    glPopGroupMarkerEXT             @296
+    glEGLImageTargetTexture2DOES    @297
+    glEGLImageTargetRenderbufferStorageOES @298
+    glBindVertexArrayOES            @299
+    glDeleteVertexArraysOES         @300
+    glGenVertexArraysOES            @301
+    glIsVertexArrayOES              @302
+    glDebugMessageControlKHR        @303
+    glDebugMessageInsertKHR         @304
+    glDebugMessageCallbackKHR       @305
+    glGetDebugMessageLogKHR         @306
+    glPushDebugGroupKHR             @307
+    glPopDebugGroupKHR              @308
+    glObjectLabelKHR                @309
+    glGetObjectLabelKHR             @310
+    glObjectPtrLabelKHR             @311
+    glGetObjectPtrLabelKHR          @312
+    glGetPointervKHR                @313
+    glQueryCounterEXT               @314
+    glGetQueryObjectivEXT           @315
+    glGetQueryObjecti64vEXT         @316
+    glGetQueryObjectui64vEXT        @317
+    glBindUniformLocationCHROMIUM   @318
+    glCoverageModulationCHROMIUM    @319
 
-    ; EGL dependencies
-    glCreateContext                 @144 NONAME
-    glDestroyContext                @145 NONAME
-    glMakeCurrent                   @146 NONAME
-    glGetCurrentContext             @147 NONAME
-    glGetProcAddress                @148 NONAME
-    glBindTexImage                  @158 NONAME
-    glCreateRenderer                @177 NONAME
-    glDestroyRenderer               @178 NONAME
\ No newline at end of file
+    glMatrixLoadfCHROMIUM           @320
+    glMatrixLoadIdentityCHROMIUM    @321
+    glGenPathsCHROMIUM              @322
+    glDeletePathsCHROMIUM           @323
+    glIsPathCHROMIUM                @324
+    glPathCommandsCHROMIUM          @325
+    glPathParameterfCHROMIUM        @326
+    glPathParameteriCHROMIUM        @327
+    glGetPathParameterfvCHROMIUM    @328
+    glGetPathParameterivCHROMIUM    @329
+    glPathStencilFuncCHROMIUM       @330
+    glStencilFillPathCHROMIUM       @331
+    glStencilStrokePathCHROMIUM     @332
+    glCoverFillPathCHROMIUM         @333
+    glCoverStrokePathCHROMIUM       @334
+    glStencilThenCoverFillPathCHROMIUM            @335
+    glStencilThenCoverStrokePathCHROMIUM          @336
+    glCoverFillPathInstancedCHROMIUM              @337
+    glCoverStrokePathInstancedCHROMIUM            @338
+    glStencilStrokePathInstancedCHROMIUM          @339
+    glStencilFillPathInstancedCHROMIUM            @340
+    glStencilThenCoverFillPathInstancedCHROMIUM   @341
+    glStencilThenCoverStrokePathInstancedCHROMIUM @342
+    glBindFragmentInputLocationCHROMIUM           @343
+    glProgramPathFragmentInputGenCHROMIUM         @344
+
+    ; GLES 3.0 Functions
+    glReadBuffer                    @180
+    glDrawRangeElements             @181
+    glTexImage3D                    @182
+    glTexSubImage3D                 @183
+    glCopyTexSubImage3D             @184
+    glCompressedTexImage3D          @185
+    glCompressedTexSubImage3D       @186
+    glGenQueries                    @187
+    glDeleteQueries                 @188
+    glIsQuery                       @189
+    glBeginQuery                    @190
+    glEndQuery                      @191
+    glGetQueryiv                    @192
+    glGetQueryObjectuiv             @193
+    glUnmapBuffer                   @194
+    glGetBufferPointerv             @195
+    glDrawBuffers                   @196
+    glUniformMatrix2x3fv            @197
+    glUniformMatrix3x2fv            @198
+    glUniformMatrix2x4fv            @199
+    glUniformMatrix4x2fv            @200
+    glUniformMatrix3x4fv            @201
+    glUniformMatrix4x3fv            @202
+    glBlitFramebuffer               @203
+    glRenderbufferStorageMultisample @204
+    glFramebufferTextureLayer       @205
+    glMapBufferRange                @206
+    glFlushMappedBufferRange        @207
+    glBindVertexArray               @208
+    glDeleteVertexArrays            @209
+    glGenVertexArrays               @210
+    glIsVertexArray                 @211
+    glGetIntegeri_v                 @212
+    glBeginTransformFeedback        @213
+    glEndTransformFeedback          @214
+    glBindBufferRange               @215
+    glBindBufferBase                @216
+    glTransformFeedbackVaryings     @217
+    glGetTransformFeedbackVarying   @218
+    glVertexAttribIPointer          @219
+    glGetVertexAttribIiv            @220
+    glGetVertexAttribIuiv           @221
+    glVertexAttribI4i               @222
+    glVertexAttribI4ui              @223
+    glVertexAttribI4iv              @224
+    glVertexAttribI4uiv             @225
+    glGetUniformuiv                 @226
+    glGetFragDataLocation           @227
+    glUniform1ui                    @228
+    glUniform2ui                    @229
+    glUniform3ui                    @230
+    glUniform4ui                    @231
+    glUniform1uiv                   @232
+    glUniform2uiv                   @233
+    glUniform3uiv                   @234
+    glUniform4uiv                   @235
+    glClearBufferiv                 @236
+    glClearBufferuiv                @237
+    glClearBufferfv                 @238
+    glClearBufferfi                 @239
+    glGetStringi                    @240
+    glCopyBufferSubData             @241
+    glGetUniformIndices             @242
+    glGetActiveUniformsiv           @243
+    glGetUniformBlockIndex          @244
+    glGetActiveUniformBlockiv       @245
+    glGetActiveUniformBlockName     @246
+    glUniformBlockBinding           @247
+    glDrawArraysInstanced           @248
+    glDrawElementsInstanced         @249
+    glFenceSync                     @250
+    glIsSync                        @251
+    glDeleteSync                    @252
+    glClientWaitSync                @253
+    glWaitSync                      @254
+    glGetInteger64v                 @255
+    glGetSynciv                     @256
+    glGetInteger64i_v               @257
+    glGetBufferParameteri64v        @258
+    glGenSamplers                   @259
+    glDeleteSamplers                @260
+    glIsSampler                     @261
+    glBindSampler                   @262
+    glSamplerParameteri             @263
+    glSamplerParameteriv            @264
+    glSamplerParameterf             @265
+    glSamplerParameterfv            @266
+    glGetSamplerParameteriv         @267
+    glGetSamplerParameterfv         @268
+    glVertexAttribDivisor           @269
+    glBindTransformFeedback         @270
+    glDeleteTransformFeedbacks      @271
+    glGenTransformFeedbacks         @272
+    glIsTransformFeedback           @273
+    glPauseTransformFeedback        @274
+    glResumeTransformFeedback       @275
+    glGetProgramBinary              @276
+    glProgramBinary                 @277
+    glProgramParameteri             @278
+    glInvalidateFramebuffer         @279
+    glInvalidateSubFramebuffer      @280
+    glTexStorage2D                  @281
+    glTexStorage3D                  @282
+    glGetInternalformativ           @283
+
+    ; GLES 3.1 Functions
+    glDispatchCompute               @345
+    glDispatchComputeIndirect       @346
+    glDrawArraysIndirect            @347
+    glDrawElementsIndirect          @348
+    glFramebufferParameteri         @349
+    glGetFramebufferParameteriv     @350
+    glGetProgramInterfaceiv         @351
+    glGetProgramResourceIndex       @352
+    glGetProgramResourceName        @353
+    glGetProgramResourceiv          @354
+    glGetProgramResourceLocation    @355
+    glUseProgramStages              @356
+    glActiveShaderProgram           @357
+    glCreateShaderProgramv          @358
+    glBindProgramPipeline           @359
+    glDeleteProgramPipelines        @360
+    glGenProgramPipelines           @361
+    glIsProgramPipeline             @362
+    glGetProgramPipelineiv          @363
+    glProgramUniform1i              @364
+    glProgramUniform2i              @365
+    glProgramUniform3i              @366
+    glProgramUniform4i              @367
+    glProgramUniform1ui             @368
+    glProgramUniform2ui             @369
+    glProgramUniform3ui             @370
+    glProgramUniform4ui             @371
+    glProgramUniform1f              @372
+    glProgramUniform2f              @373
+    glProgramUniform3f              @374
+    glProgramUniform4f              @375
+    glProgramUniform1iv             @376
+    glProgramUniform2iv             @377
+    glProgramUniform3iv             @378
+    glProgramUniform4iv             @379
+    glProgramUniform1uiv            @380
+    glProgramUniform2uiv            @381
+    glProgramUniform3uiv            @382
+    glProgramUniform4uiv            @383
+    glProgramUniform1fv             @384
+    glProgramUniform2fv             @385
+    glProgramUniform3fv             @386
+    glProgramUniform4fv             @387
+    glProgramUniformMatrix2fv       @388
+    glProgramUniformMatrix3fv       @389
+    glProgramUniformMatrix4fv       @390
+    glProgramUniformMatrix2x3fv     @391
+    glProgramUniformMatrix3x2fv     @392
+    glProgramUniformMatrix2x4fv     @393
+    glProgramUniformMatrix4x2fv     @394
+    glProgramUniformMatrix3x4fv     @395
+    glProgramUniformMatrix4x3fv     @396
+    glValidateProgramPipeline       @397
+    glGetProgramPipelineInfoLog     @398
+    glBindImageTexture              @399
+    glGetBooleani_v                 @400
+    glMemoryBarrier                 @401
+    glMemoryBarrierByRegion         @402
+    glTexStorage2DMultisample       @403
+    glGetMultisamplefv              @404
+    glSampleMaski                   @405
+    glGetTexLevelParameteriv        @406
+    glGetTexLevelParameterfv        @407
+    glBindVertexBuffer              @408
+    glVertexAttribFormat            @409
+    glVertexAttribIFormat           @410
+    glVertexAttribBinding           @411
+    glVertexBindingDivisor          @412
+
+    ; ANGLE Platform Implementation
+    ANGLEGetDisplayPlatform         @290
+    ANGLEResetDisplayPlatform       @291
diff --git a/src/third_party/angle/src/libGLESv2/libGLESv2.rc b/src/third_party/angle/src/libGLESv2/libGLESv2.rc
index 0ad21e4..dfae63e 100644
--- a/src/third_party/angle/src/libGLESv2/libGLESv2.rc
+++ b/src/third_party/angle/src/libGLESv2/libGLESv2.rc
@@ -1,102 +1,103 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include <windows.h>
-#include "../common/version.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "#include ""../common/version.h""\0"
-END
-
-3 TEXTINCLUDE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
- PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-            VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library"
-            VALUE "FileVersion", VERSION_STRING
-            VALUE "InternalName", "libGLESv2"
-            VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc."
-            VALUE "OriginalFilename", "libGLESv2.dll"
-            VALUE "PrivateBuild", VERSION_STRING
-            VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library"
-            VALUE "ProductVersion", VERSION_STRING
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
+// Microsoft Visual C++ generated resource script.

+//

+#include "resource.h"

+

+#define APSTUDIO_READONLY_SYMBOLS

+/////////////////////////////////////////////////////////////////////////////

+//

+// Generated from the TEXTINCLUDE 2 resource.

+//

+#include <windows.h>

+#include "../common/version.h"

+

+/////////////////////////////////////////////////////////////////////////////

+#undef APSTUDIO_READONLY_SYMBOLS

+

+/////////////////////////////////////////////////////////////////////////////

+// English (U.S.) resources

+

+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)

+#ifdef _WIN32

+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

+#pragma code_page(1252)

+#endif //_WIN32

+

+#ifdef APSTUDIO_INVOKED

+/////////////////////////////////////////////////////////////////////////////

+//

+// TEXTINCLUDE

+//

+

+1 TEXTINCLUDE 

+BEGIN

+    "resource.h\0"

+END

+

+2 TEXTINCLUDE 

+BEGIN

+    "#include ""afxres.h""\r\n"

+    "#include ""../common/version.h""\0"

+END

+

+3 TEXTINCLUDE 

+BEGIN

+    "\r\n"

+    "\0"

+END

+

+#endif    // APSTUDIO_INVOKED

+

+

+/////////////////////////////////////////////////////////////////////////////

+//

+// Version

+//

+

+VS_VERSION_INFO VERSIONINFO

+ FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,ANGLE_REVISION,0

+ PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,ANGLE_REVISION,0

+ FILEFLAGSMASK 0x17L

+#ifdef _DEBUG

+ FILEFLAGS 0x1L

+#else

+ FILEFLAGS 0x0L

+#endif

+ FILEOS 0x4L

+ FILETYPE 0x2L

+ FILESUBTYPE 0x0L

+BEGIN

+    BLOCK "StringFileInfo"

+    BEGIN

+        BLOCK "040904b0"

+        BEGIN

+            VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library"

+            VALUE "FileVersion", ANGLE_VERSION_STRING

+            VALUE "InternalName", "libGLESv2"

+            VALUE "LegalCopyright", "Copyright (C) 2015 Google Inc."

+            VALUE "OriginalFilename", "libGLESv2.dll"

+            VALUE "PrivateBuild", ANGLE_VERSION_STRING

+            VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library"

+            VALUE "ProductVersion", ANGLE_VERSION_STRING

+            VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE

+        END

+    END

+    BLOCK "VarFileInfo"

+    BEGIN

+        VALUE "Translation", 0x409, 1200

+    END

+END

+

+#endif    // English (U.S.) resources

+/////////////////////////////////////////////////////////////////////////////

+

+

+

+#ifndef APSTUDIO_INVOKED

+/////////////////////////////////////////////////////////////////////////////

+//

+// Generated from the TEXTINCLUDE 3 resource.

+//

+

+

+/////////////////////////////////////////////////////////////////////////////

+#endif    // not APSTUDIO_INVOKED

diff --git a/src/third_party/angle/src/libGLESv2/libGLESv2.vcxproj b/src/third_party/angle/src/libGLESv2/libGLESv2.vcxproj
deleted file mode 100644
index ca0d6b5..0000000
--- a/src/third_party/angle/src/libGLESv2/libGLESv2.vcxproj
+++ /dev/null
@@ -1,423 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Debug|x64">

-      <Configuration>Debug</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|x64">

-      <Configuration>Release</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{B5871A7A-968C-42E3-A33B-981E6F448E78}</ProjectGuid>

-    <RootNamespace>libGLESv2</RootNamespace>

-    <Keyword>Win32Proj</Keyword>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup>

-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>

-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>

-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>

-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IncludePath)</IncludePath>

-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(LibraryPath)</LibraryPath>

-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IncludePath)</IncludePath>

-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(LibraryPath)</LibraryPath>

-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IncludePath)</IncludePath>

-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IncludePath)</IncludePath>

-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(LibraryPath)</LibraryPath>

-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(LibraryPath)</LibraryPath>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>Use</PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-      <PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>

-      <AdditionalOptions>$(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <ModuleDefinitionFile>libGLESv2.def</ModuleDefinitionFile>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Windows</SubSystem>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>%40echo on

-mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"

-%40echo off

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>ANGLE_DISABLE_TRACE;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>Use</PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-      <PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>

-      <AdditionalOptions>$(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>

-      <ModuleDefinitionFile>libGLESv2.def</ModuleDefinitionFile>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Windows</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX86</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>%40echo on

-mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"

-%40echo off

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>Disabled</Optimization>

-      <AdditionalIncludeDirectories>$(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MinimalRebuild>true</MinimalRebuild>

-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <PrecompiledHeader>Use</PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>

-      <AdditionalOptions>$(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <ModuleDefinitionFile>libGLESv2.def</ModuleDefinitionFile>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Windows</SubSystem>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX64</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>%40echo on

-mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"

-%40echo off

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <Midl>

-      <TargetEnvironment>X64</TargetEnvironment>

-    </Midl>

-    <ClCompile>

-      <Optimization>MaxSpeed</Optimization>

-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

-      <AdditionalIncludeDirectories>$(ProjectDir)/..; $(ProjectDir)/../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

-      <PrecompiledHeader>Use</PrecompiledHeader>

-      <WarningLevel>Level4</WarningLevel>

-      <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>

-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

-      <TreatWarningAsError>true</TreatWarningAsError>

-      <PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>

-      <AdditionalOptions>$(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>

-      <ModuleDefinitionFile>libGLESv2.def</ModuleDefinitionFile>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <SubSystem>Windows</SubSystem>

-      <OptimizeReferences>true</OptimizeReferences>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <DataExecutionPrevention>

-      </DataExecutionPrevention>

-      <TargetMachine>MachineX64</TargetMachine>

-    </Link>

-    <PostBuildEvent>

-      <Command>%40echo on

-mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

-copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"

-%40echo off

-</Command>

-    </PostBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <ClCompile Include="..\third_party\murmurhash\MurmurHash3.cpp">

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>

-    </ClCompile>

-    <ClCompile Include="Buffer.cpp" />

-    <ClCompile Include="Context.cpp" />

-    <ClCompile Include="..\common\debug.cpp">

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>

-    </ClCompile>

-    <ClCompile Include="Fence.cpp" />

-    <ClCompile Include="Float16ToFloat32.cpp" />

-    <ClCompile Include="Framebuffer.cpp" />

-    <ClCompile Include="HandleAllocator.cpp" />

-    <ClCompile Include="libGLESv2.cpp" />

-    <ClCompile Include="main.cpp" />

-    <ClCompile Include="precompiled.cpp">

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>

-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>

-    </ClCompile>

-    <ClCompile Include="Program.cpp" />

-    <ClCompile Include="ProgramBinary.cpp" />

-    <ClCompile Include="Query.cpp" />

-    <ClCompile Include="..\common\RefCountObject.cpp" />

-    <ClCompile Include="Renderbuffer.cpp" />

-    <ClCompile Include="renderer\Blit.cpp" />

-    <ClCompile Include="renderer\Fence11.cpp" />

-    <ClCompile Include="renderer\Fence9.cpp" />

-    <ClCompile Include="renderer\BufferStorage.cpp" />

-    <ClCompile Include="renderer\BufferStorage11.cpp" />

-    <ClCompile Include="renderer\BufferStorage9.cpp" />

-    <ClCompile Include="renderer\Image.cpp" />

-    <ClCompile Include="renderer\Image9.cpp" />

-    <ClCompile Include="renderer\IndexBuffer.cpp" />

-    <ClCompile Include="renderer\IndexBuffer11.cpp" />

-    <ClCompile Include="renderer\IndexBuffer9.cpp" />

-    <ClCompile Include="renderer\IndexDataManager.cpp" />

-    <ClCompile Include="renderer\ImageSSE2.cpp" />

-    <ClCompile Include="renderer\Image11.cpp" />

-    <ClCompile Include="renderer\InputLayoutCache.cpp" />

-    <ClCompile Include="renderer\Query11.cpp" />

-    <ClCompile Include="renderer\Query9.cpp" />

-    <ClCompile Include="renderer\Renderer.cpp" />

-    <ClCompile Include="renderer\Renderer11.cpp" />

-    <ClCompile Include="renderer\renderer11_utils.cpp" />

-    <ClCompile Include="renderer\Renderer9.cpp" />

-    <ClCompile Include="renderer\renderer9_utils.cpp" />

-    <ClCompile Include="renderer\RenderTarget11.cpp" />

-    <ClCompile Include="renderer\RenderTarget9.cpp" />

-    <ClCompile Include="renderer\RenderStateCache.cpp" />

-    <ClCompile Include="renderer\ShaderExecutable11.cpp" />

-    <ClCompile Include="renderer\ShaderExecutable9.cpp" />

-    <ClCompile Include="renderer\SwapChain11.cpp" />

-    <ClCompile Include="renderer\SwapChain9.cpp" />

-    <ClCompile Include="renderer\TextureStorage.cpp" />

-    <ClCompile Include="renderer\TextureStorage11.cpp" />

-    <ClCompile Include="renderer\TextureStorage9.cpp" />

-    <ClCompile Include="renderer\VertexBuffer.cpp" />

-    <ClCompile Include="renderer\VertexBuffer11.cpp" />

-    <ClCompile Include="renderer\VertexBuffer9.cpp" />

-    <ClCompile Include="renderer\VertexDataManager.cpp" />

-    <ClCompile Include="renderer\VertexDeclarationCache.cpp" />

-    <ClCompile Include="ResourceManager.cpp" />

-    <ClCompile Include="Shader.cpp" />

-    <ClCompile Include="Texture.cpp" />

-    <ClCompile Include="Uniform.cpp" />

-    <ClCompile Include="utilities.cpp" />

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="..\common\debug.h" />

-    <ClInclude Include="..\common\system.h" />

-    <ClInclude Include="..\third_party\murmurhash\MurmurHash3.h" />

-    <ClInclude Include="angletypes.h" />

-    <ClInclude Include="BinaryStream.h" />

-    <ClInclude Include="Buffer.h" />

-    <ClInclude Include="constants.h" />

-    <ClInclude Include="Context.h" />

-    <ClInclude Include="Fence.h" />

-    <ClInclude Include="Framebuffer.h" />

-    <ClInclude Include="..\..\include\GLES2\gl2.h" />

-    <ClInclude Include="..\..\include\GLES2\gl2ext.h" />

-    <ClInclude Include="..\..\include\GLES2\gl2platform.h" />

-    <ClInclude Include="HandleAllocator.h" />

-    <ClInclude Include="main.h" />

-    <ClInclude Include="mathutil.h" />

-    <ClInclude Include="precompiled.h" />

-    <ClInclude Include="Program.h" />

-    <ClInclude Include="ProgramBinary.h" />

-    <ClInclude Include="Query.h" />

-    <ClInclude Include="..\common\RefCountObject.h" />

-    <ClInclude Include="Renderbuffer.h" />

-    <ClInclude Include="renderer\Blit.h" />

-    <ClInclude Include="renderer\Fence11.h" />

-    <ClInclude Include="renderer\Fence9.h" />

-    <ClInclude Include="renderer\FenceImpl.h" />

-    <ClInclude Include="renderer\BufferStorage.h" />

-    <ClInclude Include="renderer\BufferStorage11.h" />

-    <ClInclude Include="renderer\BufferStorage9.h" />

-    <ClInclude Include="renderer\generatemip.h" />

-    <ClInclude Include="renderer\Image.h" />

-    <ClInclude Include="renderer\Image11.h" />

-    <ClInclude Include="renderer\Image9.h" />

-    <ClInclude Include="renderer\IndexBuffer.h" />

-    <ClInclude Include="renderer\IndexBuffer11.h" />

-    <ClInclude Include="renderer\IndexBuffer9.h" />

-    <ClInclude Include="renderer\IndexDataManager.h" />

-    <ClInclude Include="renderer\InputLayoutCache.h" />

-    <ClInclude Include="renderer\Query11.h" />

-    <ClInclude Include="renderer\QueryImpl.h" />

-    <ClInclude Include="renderer\Query9.h" />

-    <ClInclude Include="renderer\Renderer.h" />

-    <ClInclude Include="renderer\Renderer11.h" />

-    <ClInclude Include="renderer\renderer11_utils.h" />

-    <ClInclude Include="renderer\Renderer9.h" />

-    <ClInclude Include="renderer\renderer9_utils.h" />

-    <ClInclude Include="renderer\RenderTarget.h" />

-    <ClInclude Include="renderer\RenderTarget11.h" />

-    <ClInclude Include="renderer\RenderTarget9.h" />

-    <ClInclude Include="renderer\RenderStateCache.h" />

-    <ClInclude Include="renderer\ShaderCache.h" />

-    <ClInclude Include="renderer\ShaderExecutable.h" />

-    <ClInclude Include="renderer\ShaderExecutable11.h" />

-    <ClInclude Include="renderer\ShaderExecutable9.h" />

-    <ClInclude Include="renderer\shaders\compiled\clear11vs.h" />

-    <ClInclude Include="renderer\shaders\compiled\clearmultiple11ps.h" />

-    <ClInclude Include="renderer\shaders\compiled\clearsingle11ps.h" />

-    <ClInclude Include="renderer\shaders\compiled\componentmaskps.h" />

-    <ClInclude Include="renderer\shaders\compiled\flipyvs.h" />

-    <ClInclude Include="renderer\shaders\compiled\luminanceps.h" />

-    <ClInclude Include="renderer\shaders\compiled\passthrough11vs.h" />

-    <ClInclude Include="renderer\shaders\compiled\passthroughlum11ps.h" />

-    <ClInclude Include="renderer\shaders\compiled\passthroughlumalpha11ps.h" />

-    <ClInclude Include="renderer\shaders\compiled\passthroughps.h" />

-    <ClInclude Include="renderer\shaders\compiled\passthroughrgb11ps.h" />

-    <ClInclude Include="renderer\shaders\compiled\passthroughrgba11ps.h" />

-    <ClInclude Include="renderer\shaders\compiled\standardvs.h" />

-    <ClInclude Include="renderer\SwapChain.h" />

-    <ClInclude Include="renderer\SwapChain11.h" />

-    <ClInclude Include="renderer\SwapChain9.h" />

-    <ClInclude Include="renderer\TextureStorage.h" />

-    <ClInclude Include="renderer\TextureStorage11.h" />

-    <ClInclude Include="renderer\TextureStorage9.h" />

-    <ClInclude Include="renderer\VertexBuffer.h" />

-    <ClInclude Include="renderer\VertexBuffer11.h" />

-    <ClInclude Include="renderer\VertexBuffer9.h" />

-    <ClInclude Include="renderer\vertexconversion.h" />

-    <ClInclude Include="renderer\VertexDataManager.h" />

-    <ClInclude Include="renderer\VertexDeclarationCache.h" />

-    <ClInclude Include="resource.h" />

-    <ClInclude Include="ResourceManager.h" />

-    <ClInclude Include="Shader.h" />

-    <ClInclude Include="Texture.h" />

-    <ClInclude Include="Uniform.h" />

-    <ClInclude Include="utilities.h" />

-    <ClInclude Include="..\common\version.h" />

-  </ItemGroup>

-  <ItemGroup>

-    <None Include="libGLESv2.def" />

-    <None Include="renderer\shaders\Blit.ps" />

-    <None Include="renderer\shaders\Blit.vs" />

-    <None Include="renderer\shaders\Clear11.hlsl" />

-    <None Include="renderer\shaders\generate_shaders.bat" />

-    <None Include="renderer\shaders\Passthrough11.hlsl" />

-  </ItemGroup>

-  <ItemGroup>

-    <ResourceCompile Include="libGLESv2.rc" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="..\compiler\preprocessor\preprocessor.vcxproj">

-      <Project>{fbe32df3-0fb0-4f2f-a424-2c21bd7bc325}</Project>

-    </ProjectReference>

-    <ProjectReference Include="..\compiler\translator_common.vcxproj">

-      <Project>{5b3a6db8-1e7e-40d7-92b9-da8aae619fad}</Project>

-    </ProjectReference>

-    <ProjectReference Include="..\compiler\translator_hlsl.vcxproj">

-      <Project>{5620f0e4-6c43-49bc-a178-b804e1a0c3a7}</Project>

-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

-      <Private>true</Private>

-      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>

-      <LinkLibraryDependencies>true</LinkLibraryDependencies>

-      <UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>

-    </ProjectReference>

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/libGLESv2.vcxproj.filters b/src/third_party/angle/src/libGLESv2/libGLESv2.vcxproj.filters
deleted file mode 100644
index 34f9704..0000000
--- a/src/third_party/angle/src/libGLESv2/libGLESv2.vcxproj.filters
+++ /dev/null
@@ -1,509 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup>

-    <Filter Include="Source Files">

-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

-    </Filter>

-    <Filter Include="Header Files">

-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

-    </Filter>

-    <Filter Include="Third Party">

-      <UniqueIdentifier>{dc1dac40-3563-41be-9e2d-c2588d8670fb}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Third Party\MurmurHash">

-      <UniqueIdentifier>{b0005d2f-9b4a-4659-a270-138811174f73}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Header Files\Renderer">

-      <UniqueIdentifier>{562e469d-1abb-44bc-b7fa-55eefbf75acc}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Shaders">

-      <UniqueIdentifier>{6dc0306f-6396-4e80-9ef9-09b58aa53c4d}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Shaders\Compiled">

-      <UniqueIdentifier>{6332705b-1999-4292-a38b-dd47329734aa}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Source Files\Renderer">

-      <UniqueIdentifier>{93a76964-77a3-4b20-a6f5-e14e762d4e14}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Header Files\Renderer9">

-      <UniqueIdentifier>{3877f35e-845c-4e95-b9a5-c7d8b9f307c5}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Header Files\Renderer11">

-      <UniqueIdentifier>{2d70fd60-6dea-489f-ac09-16890d325669}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Source Files\Renderer9">

-      <UniqueIdentifier>{60e14f04-2cf2-4a07-b3ef-7c68a82ba2d9}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Source Files\Renderer11">

-      <UniqueIdentifier>{72db61d3-e081-4b58-bc63-a04a8a70585f}</UniqueIdentifier>

-    </Filter>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="Buffer.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Context.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="..\common\debug.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Fence.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Float16ToFloat32.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Framebuffer.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="HandleAllocator.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="libGLESv2.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="main.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Program.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="ProgramBinary.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Query.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="..\common\RefCountObject.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Renderbuffer.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="ResourceManager.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Shader.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="Texture.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="utilities.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Image.cpp">

-      <Filter>Source Files\Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\TextureStorage.cpp">

-      <Filter>Source Files\Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Renderer.cpp">

-      <Filter>Source Files\Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="..\third_party\murmurhash\MurmurHash3.cpp">

-      <Filter>Third Party\MurmurHash</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\IndexDataManager.cpp">

-      <Filter>Source Files\Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\VertexDataManager.cpp">

-      <Filter>Source Files\Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Image.cpp">

-      <Filter>Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\ImageSSE2.cpp">

-      <Filter>Source Files\Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\VertexBuffer.cpp">

-      <Filter>Source Files\Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\IndexBuffer.cpp">

-      <Filter>Source Files\Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="Uniform.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\BufferStorage.cpp">

-      <Filter>Source Files\Renderer</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\BufferStorage11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Fence11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Image11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\IndexBuffer11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Query11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Renderer11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\renderer11_utils.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\RenderTarget11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\ShaderExecutable11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\SwapChain11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\TextureStorage11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\VertexBuffer11.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\BufferStorage9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Fence9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Image9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\IndexBuffer9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Query9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Renderer9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\renderer9_utils.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\RenderTarget9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\ShaderExecutable9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\SwapChain9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\TextureStorage9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\VertexBuffer9.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\Blit.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\InputLayoutCache.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\RenderStateCache.cpp">

-      <Filter>Source Files\Renderer11</Filter>

-    </ClCompile>

-    <ClCompile Include="renderer\VertexDeclarationCache.cpp">

-      <Filter>Source Files\Renderer9</Filter>

-    </ClCompile>

-    <ClCompile Include="precompiled.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-  </ItemGroup>

-  <ItemGroup>

-    <ClInclude Include="BinaryStream.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Buffer.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Context.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Fence.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Framebuffer.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\..\include\GLES2\gl2.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\..\include\GLES2\gl2ext.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\..\include\GLES2\gl2platform.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="HandleAllocator.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="main.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="mathutil.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Program.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="ProgramBinary.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Query.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\common\RefCountObject.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Renderbuffer.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="resource.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="ResourceManager.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Shader.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="Texture.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="utilities.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\common\version.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="angletypes.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\third_party\murmurhash\MurmurHash3.h">

-      <Filter>Third Party\MurmurHash</Filter>

-    </ClInclude>

-    <ClInclude Include="Uniform.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\passthrough11vs.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\passthroughps.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\standardvs.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\componentmaskps.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\flipyvs.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\luminanceps.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\passthroughrgba11ps.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\passthroughrgb11ps.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\passthroughlum11ps.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\passthroughlumalpha11ps.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\clear11vs.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\clearmultiple11ps.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\shaders\compiled\clearsingle11ps.h">

-      <Filter>Shaders\Compiled</Filter>

-    </ClInclude>

-    <ClInclude Include="..\common\system.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="..\common\debug.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\BufferStorage.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\FenceImpl.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\generatemip.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Image.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\IndexBuffer.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\IndexDataManager.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\QueryImpl.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Renderer.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\RenderTarget.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\ShaderExecutable.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\SwapChain.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\TextureStorage.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\VertexBuffer.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\vertexconversion.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\VertexDataManager.h">

-      <Filter>Header Files\Renderer</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\BufferStorage11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\IndexBuffer11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Query11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Renderer11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\RenderTarget11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\ShaderExecutable11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\SwapChain11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\TextureStorage11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\VertexBuffer11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\BufferStorage9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Fence9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Image9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\IndexBuffer9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Query9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Renderer9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\renderer9_utils.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\RenderTarget9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\ShaderExecutable9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\SwapChain9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\TextureStorage9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\VertexBuffer9.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Fence11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Image11.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\renderer11_utils.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Fence9.h">

-      <Filter>Header Files\Renderer\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Query11.h">

-      <Filter>Header Files\Renderer\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\Blit.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\ShaderCache.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\InputLayoutCache.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\RenderStateCache.h">

-      <Filter>Header Files\Renderer11</Filter>

-    </ClInclude>

-    <ClInclude Include="renderer\VertexDeclarationCache.h">

-      <Filter>Header Files\Renderer9</Filter>

-    </ClInclude>

-    <ClInclude Include="constants.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="precompiled.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-  </ItemGroup>

-  <ItemGroup>

-    <None Include="renderer\shaders\Blit.ps">

-      <Filter>Shaders</Filter>

-    </None>

-    <None Include="renderer\shaders\Blit.vs">

-      <Filter>Shaders</Filter>

-    </None>

-    <None Include="renderer\shaders\generate_shaders.bat">

-      <Filter>Shaders</Filter>

-    </None>

-    <None Include="renderer\shaders\Passthrough11.hlsl">

-      <Filter>Shaders</Filter>

-    </None>

-    <None Include="renderer\shaders\Clear11.hlsl">

-      <Filter>Shaders</Filter>

-    </None>

-    <None Include="libGLESv2.def" />

-  </ItemGroup>

-  <ItemGroup>

-    <ResourceCompile Include="libGLESv2.rc" />

-  </ItemGroup>

-</Project>
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/main.cpp b/src/third_party/angle/src/libGLESv2/main.cpp
deleted file mode 100644
index ae69ce5..0000000
--- a/src/third_party/angle/src/libGLESv2/main.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// main.cpp: DLL entry point and management of thread-local data.
-
-#include "libGLESv2/main.h"
-
-#include "libGLESv2/Context.h"
-
-static volatile DWORD currentTLS = TLS_OUT_OF_INDEXES;
-
-static gl::Current* GetCurrent()
-{
-#if !defined(COMPONENT_BUILD)
-    if (currentTLS == TLS_OUT_OF_INDEXES)
-        currentTLS = TlsAlloc();
-#endif
-
-    gl::Current *current = (gl::Current*)TlsGetValue(currentTLS);
-
-#if !defined(COMPONENT_BUILD)
-    if (current == NULL)
-    {
-        current = (gl::Current*)calloc(1, sizeof(gl::Current));
-
-        if (current)
-        {
-            TlsSetValue(currentTLS, current);
-
-            current->context = NULL;
-            current->display = NULL;
-        }
-    }
-#endif
-
-    return current;
-}
-
-#if defined(__cplusplus_winrt)
-// Turns off a harmless warning that happens when compiling with /CX flag
-#pragma warning(disable: 4447)
-#endif
-
-#if defined(COMPONENT_BUILD)
-BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
-{
-    switch (reason)
-    {
-      case DLL_PROCESS_ATTACH:
-        {
-            currentTLS = TlsAlloc();
-
-            if (currentTLS == TLS_OUT_OF_INDEXES)
-            {
-                return FALSE;
-            }
-        }
-        // Fall throught to initialize index
-      case DLL_THREAD_ATTACH:
-        {
-            gl::Current *current = (gl::Current*)calloc(1, sizeof(gl::Current));
-
-            if (current)
-            {
-                TlsSetValue(currentTLS, current);
-
-                current->context = NULL;
-                current->display = NULL;
-            }
-        }
-        break;
-      case DLL_THREAD_DETACH:
-        {
-            void *current = TlsGetValue(currentTLS);
-
-            if (current)
-            {
-                free(current);
-            }
-        }
-        break;
-      case DLL_PROCESS_DETACH:
-        {
-            void *current = TlsGetValue(currentTLS);
-
-            if (current)
-            {
-                free(current);
-            }
-
-            TlsFree(currentTLS);
-        }
-        break;
-      default:
-        break;
-    }
-
-    return TRUE;
-}
-#endif // defined(COMPONENT_BUILD)
-
-namespace gl
-{
-
-void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
-{
-    Current *current = GetCurrent();
-
-    current->context = context;
-    current->display = display;
-
-    if (context && display && surface)
-    {
-        context->makeCurrent(surface);
-    }
-}
-
-Context *getContext()
-{
-    Current *current = GetCurrent();
-
-    return current->context;
-}
-
-Context *getNonLostContext()
-{
-    Context *context = getContext();
-    
-    if (context)
-    {
-        if (context->isContextLost())
-        {
-            gl::error(GL_OUT_OF_MEMORY);
-            return NULL;
-        }
-        else
-        {
-            return context;
-        }
-    }
-    return NULL;
-}
-
-egl::Display *getDisplay()
-{
-    Current *current = GetCurrent();
-
-    return current->display;
-}
-
-// Records an error code
-void error(GLenum errorCode)
-{
-    gl::Context *context = glGetCurrentContext();
-
-    if (context)
-    {
-        switch (errorCode)
-        {
-          case GL_INVALID_ENUM:
-            context->recordInvalidEnum();
-            TRACE("\t! Error generated: invalid enum\n");
-            break;
-          case GL_INVALID_VALUE:
-            context->recordInvalidValue();
-            TRACE("\t! Error generated: invalid value\n");
-            break;
-          case GL_INVALID_OPERATION:
-            context->recordInvalidOperation();
-            TRACE("\t! Error generated: invalid operation\n");
-            break;
-          case GL_OUT_OF_MEMORY:
-            context->recordOutOfMemory();
-            TRACE("\t! Error generated: out of memory\n");
-            break;
-          case GL_INVALID_FRAMEBUFFER_OPERATION:
-            context->recordInvalidFramebufferOperation();
-            TRACE("\t! Error generated: invalid framebuffer operation\n");
-            break;
-          default: UNREACHABLE();
-        }
-    }
-}
-
-}
-
diff --git a/src/third_party/angle/src/libGLESv2/main.h b/src/third_party/angle/src/libGLESv2/main.h
deleted file mode 100644
index 196afae..0000000
--- a/src/third_party/angle/src/libGLESv2/main.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// main.h: Management of thread-local data.
-
-#ifndef LIBGLESV2_MAIN_H_
-#define LIBGLESV2_MAIN_H_
-
-#include "common/debug.h"
-#include "common/system.h"
-
-namespace egl
-{
-class Display;
-class Surface;
-}
-
-namespace gl
-{
-class Context;
-    
-struct Current
-{
-    Context *context;
-    egl::Display *display;
-};
-
-void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface);
-
-Context *getContext();
-Context *getNonLostContext();
-egl::Display *getDisplay();
-
-void error(GLenum errorCode);
-
-template<class T>
-const T &error(GLenum errorCode, const T &returnValue)
-{
-    error(errorCode);
-
-    return returnValue;
-}
-
-}
-
-namespace rx
-{
-class Renderer;
-}
-
-extern "C"
-{
-// Exported functions for use by EGL
-gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
-void glDestroyContext(gl::Context *context);
-void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
-gl::Context *glGetCurrentContext();
-rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId);
-void glDestroyRenderer(rx::Renderer *renderer);
-
-__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
-bool __stdcall glBindTexImage(egl::Surface *surface);
-}
-
-#endif   // LIBGLESV2_MAIN_H_
diff --git a/src/third_party/angle/src/libGLESv2/mathutil.h b/src/third_party/angle/src/libGLESv2/mathutil.h
deleted file mode 100644
index bb48b94..0000000
--- a/src/third_party/angle/src/libGLESv2/mathutil.h
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// mathutil.h: Math and bit manipulation functions.
-
-#ifndef LIBGLESV2_MATHUTIL_H_
-#define LIBGLESV2_MATHUTIL_H_
-
-#include <intrin.h>
-
-#include "common/system.h"
-#include "common/debug.h"
-
-namespace gl
-{
-struct Vector4
-{
-    Vector4() {}
-    Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
-
-    float x;
-    float y;
-    float z;
-    float w;
-};
-
-inline bool isPow2(int x)
-{
-    return (x & (x - 1)) == 0 && (x != 0);
-}
-
-inline int log2(int x)
-{
-    int r = 0;
-    while ((x >> r) > 1) r++;
-    return r;
-}
-
-inline unsigned int ceilPow2(unsigned int x)
-{
-    if (x != 0) x--;
-    x |= x >> 1;
-    x |= x >> 2;
-    x |= x >> 4;
-    x |= x >> 8;
-    x |= x >> 16;
-    x++;
-
-    return x;
-}
-
-template<typename T, typename MIN, typename MAX>
-inline T clamp(T x, MIN min, MAX max)
-{
-    // Since NaNs fail all comparison tests, a NaN value will default to min
-    return x > min ? (x > max ? max : x) : min;
-}
-
-inline float clamp01(float x)
-{
-    return clamp(x, 0.0f, 1.0f);
-}
-
-template<const int n>
-inline unsigned int unorm(float x)
-{
-    const unsigned int max = 0xFFFFFFFF >> (32 - n);
-
-    if (x > 1)
-    {
-        return max;
-    }
-    else if (x < 0)
-    {
-        return 0;
-    }
-    else
-    {
-        return (unsigned int)(max * x + 0.5f);
-    }
-}
-
-inline bool supportsSSE2()
-{
-    static bool checked = false;
-    static bool supports = false;
-
-    if (checked)
-    {
-        return supports;
-    }
-
-    int info[4];
-    __cpuid(info, 0);
-    
-    if (info[0] >= 1)
-    {
-        __cpuid(info, 1);
-
-        supports = (info[3] >> 26) & 1;
-    }
-
-    checked = true;
-
-    return supports;
-}
-
-inline unsigned short float32ToFloat16(float fp32)
-{
-    unsigned int fp32i = (unsigned int&)fp32;
-    unsigned int sign = (fp32i & 0x80000000) >> 16;
-    unsigned int abs = fp32i & 0x7FFFFFFF;
-
-    if(abs > 0x47FFEFFF)   // Infinity
-    {
-        return sign | 0x7FFF;
-    }
-    else if(abs < 0x38800000)   // Denormal
-    {
-        unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;   
-        int e = 113 - (abs >> 23);
-
-        if(e < 24)
-        {
-            abs = mantissa >> e;
-        }
-        else
-        {
-            abs = 0;
-        }
-
-        return sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
-    }
-    else
-    {
-        return sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
-    }
-}
-
-float float16ToFloat32(unsigned short h);
-
-}
-
-namespace rx
-{
-
-struct Range
-{
-    Range() {}
-    Range(int lo, int hi) : start(lo), end(hi) { ASSERT(lo <= hi); }
-
-    int start;
-    int end;
-};
-
-}
-
-#endif   // LIBGLESV2_MATHUTIL_H_
diff --git a/src/third_party/angle/src/libGLESv2/precompiled.cpp b/src/third_party/angle/src/libGLESv2/precompiled.cpp
deleted file mode 100644
index 2621cd6..0000000
--- a/src/third_party/angle/src/libGLESv2/precompiled.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// precompiled.cpp: Precompiled header source file for libGLESv2.
-
-#include "precompiled.h"
diff --git a/src/third_party/angle/src/libGLESv2/precompiled.h b/src/third_party/angle/src/libGLESv2/precompiled.h
deleted file mode 100644
index 2806836..0000000
--- a/src/third_party/angle/src/libGLESv2/precompiled.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// precompiled.h: Precompiled header file for libGLESv2.
-#include <common/system.h>
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <assert.h>
-#include <cstddef>
-#include <float.h>
-#include <intrin.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <algorithm> // for std::min and std::max
-#include <limits>
-#include <map>
-#include <set>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#if ANGLE_ENABLE_D3D11
-#include <D3D11.h>
-#include <dxgi.h>
-#endif
-
-#if !defined(ANGLE_ENABLE_D3D11_STRICT)
-#include <d3d9.h>
-#endif
-
-#if !defined(__LB_XB360__)
-#include <D3Dcompiler.h>
-#endif
-
-#ifdef _MSC_VER
-#include <hash_map>
-#endif
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Blit.cpp b/src/third_party/angle/src/libGLESv2/renderer/Blit.cpp
deleted file mode 100644
index 2a3ce39..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Blit.cpp
+++ /dev/null
@@ -1,595 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Blit.cpp: Surface copy utility class.
-
-#include "libGLESv2/renderer/Blit.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/renderer9_utils.h"
-#include "libGLESv2/renderer/TextureStorage9.h"
-#include "libGLESv2/renderer/RenderTarget9.h"
-#include "libGLESv2/renderer/Renderer9.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-
-namespace
-{
-#include "libGLESv2/renderer/shaders/compiled/standardvs.h"
-#include "libGLESv2/renderer/shaders/compiled/flipyvs.h"
-#include "libGLESv2/renderer/shaders/compiled/passthroughps.h"
-#include "libGLESv2/renderer/shaders/compiled/luminanceps.h"
-#include "libGLESv2/renderer/shaders/compiled/componentmaskps.h"
-
-const BYTE* const g_shaderCode[] =
-{
-    g_vs20_standardvs,
-    g_vs20_flipyvs,
-    g_ps20_passthroughps,
-    g_ps20_luminanceps,
-    g_ps20_componentmaskps
-};
-
-const size_t g_shaderSize[] =
-{
-    sizeof(g_vs20_standardvs),
-    sizeof(g_vs20_flipyvs),
-    sizeof(g_ps20_passthroughps),
-    sizeof(g_ps20_luminanceps),
-    sizeof(g_ps20_componentmaskps)
-};
-}
-
-namespace rx
-{
-Blit::Blit(rx::Renderer9 *renderer)
-  : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL)
-{
-    initGeometry();
-    memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
-}
-
-Blit::~Blit()
-{
-    if (mSavedStateBlock) mSavedStateBlock->Release();
-    if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
-    if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
-
-    for (int i = 0; i < SHADER_COUNT; i++)
-    {
-        if (mCompiledShaders[i])
-        {
-            mCompiledShaders[i]->Release();
-        }
-    }
-}
-
-void Blit::initGeometry()
-{
-    static const float quad[] =
-    {
-        -1, -1,
-        -1,  1,
-         1, -1,
-         1,  1
-    };
-
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
-
-    if (FAILED(result))
-    {
-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    void *lockPtr = NULL;
-    result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
-
-    if (FAILED(result) || lockPtr == NULL)
-    {
-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    memcpy(lockPtr, quad, sizeof(quad));
-    mQuadVertexBuffer->Unlock();
-
-    static const D3DVERTEXELEMENT9 elements[] =
-    {
-        { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
-        D3DDECL_END()
-    };
-
-    result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
-
-    if (FAILED(result))
-    {
-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-}
-
-template <class D3DShaderType>
-bool Blit::setShader(ShaderId source, const char *profile,
-                     D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length),
-                     HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
-{
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    D3DShaderType *shader;
-
-    if (mCompiledShaders[source] != NULL)
-    {
-        shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
-    }
-    else
-    {
-        const BYTE* shaderCode = g_shaderCode[source];
-        size_t shaderSize = g_shaderSize[source];
-
-        shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
-        if (!shader)
-        {
-            ERR("Failed to create shader for blit operation");
-            return false;
-        }
-
-        mCompiledShaders[source] = shader;
-    }
-
-    HRESULT hr = (device->*setShader)(shader);
-
-    if (FAILED(hr))
-    {
-        ERR("Failed to set shader for blit operation");
-        return false;
-    }
-
-    return true;
-}
-
-bool Blit::setVertexShader(ShaderId shader)
-{
-    return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
-}
-
-bool Blit::setPixelShader(ShaderId shader)
-{
-    return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
-}
-
-RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
-{
-    D3DSURFACE_DESC desc;
-    surface->GetDesc(&desc);
-
-    RECT rect;
-    rect.left = 0;
-    rect.top = 0;
-    rect.right = desc.Width;
-    rect.bottom = desc.Height;
-
-    return rect;
-}
-
-bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
-{
-    IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
-    if (!texture)
-    {
-        return false;
-    }
-
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    saveState();
-
-    device->SetTexture(0, texture);
-    device->SetRenderTarget(0, dest);
-
-    setVertexShader(SHADER_VS_STANDARD);
-    setPixelShader(SHADER_PS_PASSTHROUGH);
-
-    setCommonBlitState();
-    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
-    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
-
-    setViewport(getSurfaceRect(dest), 0, 0);
-
-    render();
-
-    texture->Release();
-
-    restoreState();
-
-    return true;
-}
-
-bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
-{
-    RenderTarget9 *renderTarget = NULL;
-    IDirect3DSurface9 *source = NULL;
-    gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
-
-    if (colorbuffer)
-    {
-        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
-    }
-    
-    if (renderTarget)
-    {
-        source = renderTarget->getSurface();
-    }
-
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
-    IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true);
-    bool result = false;
-        
-    if (destSurface)
-    {
-        result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
-        destSurface->Release();
-    }
-
-    source->Release();
-    return result;
-}
-
-bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
-{
-    RenderTarget9 *renderTarget = NULL;
-    IDirect3DSurface9 *source = NULL;
-    gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
-
-    if (colorbuffer)
-    {
-        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
-    }
-    
-    if (renderTarget)
-    {
-        source = renderTarget->getSurface();
-    }
-
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
-    IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true);
-    bool result = false;
-
-    if (destSurface)
-    {
-        result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
-        destSurface->Release();
-    }
-
-    source->Release();
-    return result;
-}
-
-bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
-{
-    if (!dest)
-    {
-        return false;
-    }
-
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    D3DSURFACE_DESC sourceDesc;
-    D3DSURFACE_DESC destDesc;
-    source->GetDesc(&sourceDesc);
-    dest->GetDesc(&destDesc);
-
-    if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
-        d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat))   // Can use StretchRect
-    {
-        RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
-        HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            return gl::error(GL_OUT_OF_MEMORY, false);
-        }
-    }
-    else
-    {
-        return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
-    }
-    return true;
-}
-
-bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
-{
-    IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
-    if (!texture)
-    {
-        return false;
-    }
-
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    saveState();
-
-    device->SetTexture(0, texture);
-    device->SetRenderTarget(0, dest);
-
-    setViewport(sourceRect, xoffset, yoffset);
-
-    setCommonBlitState();
-    if (setFormatConvertShaders(destFormat))
-    {
-        render();
-    }
-
-    texture->Release();
-
-    restoreState();
-
-    return true;
-}
-
-bool Blit::setFormatConvertShaders(GLenum destFormat)
-{
-    bool okay = setVertexShader(SHADER_VS_STANDARD);
-
-    switch (destFormat)
-    {
-      default: UNREACHABLE();
-      case GL_RGBA:
-      case GL_BGRA_EXT:
-      case GL_RGB:
-      case GL_ALPHA:
-        okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
-        break;
-
-      case GL_LUMINANCE:
-      case GL_LUMINANCE_ALPHA:
-        okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
-        break;
-    }
-
-    if (!okay)
-    {
-        return false;
-    }
-
-    enum { X = 0, Y = 1, Z = 2, W = 3 };
-
-    // The meaning of this constant depends on the shader that was selected.
-    // See the shader assembly code above for details.
-    float psConst0[4] = { 0, 0, 0, 0 };
-
-    switch (destFormat)
-    {
-      default: UNREACHABLE();
-      case GL_RGBA:
-      case GL_BGRA_EXT:
-        psConst0[X] = 1;
-        psConst0[Z] = 1;
-        break;
-
-      case GL_RGB:
-        psConst0[X] = 1;
-        psConst0[W] = 1;
-        break;
-
-      case GL_ALPHA:
-        psConst0[Z] = 1;
-        break;
-
-      case GL_LUMINANCE:
-        psConst0[Y] = 1;
-        break;
-
-      case GL_LUMINANCE_ALPHA:
-        psConst0[X] = 1;
-        break;
-    }
-
-    mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1);
-
-    return true;
-}
-
-IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
-{
-    if (!surface)
-    {
-        return NULL;
-    }
-
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    D3DSURFACE_DESC sourceDesc;
-    surface->GetDesc(&sourceDesc);
-
-    // Copy the render target into a texture
-    IDirect3DTexture9 *texture;
-    HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
-
-    if (FAILED(result))
-    {
-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
-    }
-
-    IDirect3DSurface9 *textureSurface;
-    result = texture->GetSurfaceLevel(0, &textureSurface);
-
-    if (FAILED(result))
-    {
-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        texture->Release();
-        return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
-    }
-
-    mRenderer->endScene();
-    result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
-
-    textureSurface->Release();
-
-    if (FAILED(result))
-    {
-        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        texture->Release();
-        return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
-    }
-
-    return texture;
-}
-
-void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
-{
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    D3DVIEWPORT9 vp;
-    vp.X      = xoffset;
-    vp.Y      = yoffset;
-    vp.Width  = sourceRect.right - sourceRect.left;
-    vp.Height = sourceRect.bottom - sourceRect.top;
-    vp.MinZ   = 0.0f;
-    vp.MaxZ   = 1.0f;
-    device->SetViewport(&vp);
-
-    float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
-    device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
-}
-
-void Blit::setCommonBlitState()
-{
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    device->SetDepthStencilSurface(NULL);
-
-    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
-    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
-    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
-    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
-    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
-    device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
-    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
-    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
-
-    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
-    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
-    device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
-    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
-    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
-
-    RECT scissorRect = {0};   // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
-    device->SetScissorRect(&scissorRect);
-
-    for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        device->SetStreamSourceFreq(i, 1);
-    }
-}
-
-void Blit::render()
-{
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
-    hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
-
-    mRenderer->startScene();
-    hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
-}
-
-void Blit::saveState()
-{
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    HRESULT hr;
-
-    device->GetDepthStencilSurface(&mSavedDepthStencil);
-    device->GetRenderTarget(0, &mSavedRenderTarget);
-
-    if (mSavedStateBlock == NULL)
-    {
-        hr = device->BeginStateBlock();
-        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
-
-        setCommonBlitState();
-
-        static const float dummyConst[4] = { 0, 0, 0, 0 };
-
-        device->SetVertexShader(NULL);
-        device->SetVertexShaderConstantF(0, dummyConst, 1);
-        device->SetPixelShader(NULL);
-        device->SetPixelShaderConstantF(0, dummyConst, 1);
-
-        D3DVIEWPORT9 dummyVp;
-        dummyVp.X = 0;
-        dummyVp.Y = 0;
-        dummyVp.Width = 1;
-        dummyVp.Height = 1;
-        dummyVp.MinZ = 0;
-        dummyVp.MaxZ = 1;
-
-        device->SetViewport(&dummyVp);
-
-        device->SetTexture(0, NULL);
-
-        device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
-
-        device->SetVertexDeclaration(mQuadVertexDeclaration);
-
-        hr = device->EndStateBlock(&mSavedStateBlock);
-        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
-    }
-
-    ASSERT(mSavedStateBlock != NULL);
-
-    if (mSavedStateBlock != NULL)
-    {
-        hr = mSavedStateBlock->Capture();
-        ASSERT(SUCCEEDED(hr));
-    }
-}
-
-void Blit::restoreState()
-{
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    device->SetDepthStencilSurface(mSavedDepthStencil);
-    if (mSavedDepthStencil != NULL)
-    {
-        mSavedDepthStencil->Release();
-        mSavedDepthStencil = NULL;
-    }
-
-    device->SetRenderTarget(0, mSavedRenderTarget);
-    if (mSavedRenderTarget != NULL)
-    {
-        mSavedRenderTarget->Release();
-        mSavedRenderTarget = NULL;
-    }
-
-    ASSERT(mSavedStateBlock != NULL);
-
-    if (mSavedStateBlock != NULL)
-    {
-        mSavedStateBlock->Apply();
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Blit.h b/src/third_party/angle/src/libGLESv2/renderer/Blit.h
deleted file mode 100644
index 3718028..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Blit.h
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Blit.cpp: Surface copy utility class.
-
-#ifndef LIBGLESV2_BLIT_H_
-#define LIBGLESV2_BLIT_H_
-
-#include "common/angleutils.h"
-
-namespace gl
-{
-class Framebuffer;
-}
-
-namespace rx
-{
-class Renderer9;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
-
-class Blit
-{
-  public:
-    explicit Blit(Renderer9 *renderer);
-    ~Blit();
-
-    // Copy from source surface to dest surface.
-    // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
-    bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level);
-    bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level);
-
-    // Copy from source surface to dest surface.
-    // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
-    // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
-    bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
-
-    // 2x2 box filter sample from source to dest.
-    // Requires that source is RGB(A) and dest has the same format as source.
-    bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
-
-  private:
-    rx::Renderer9 *mRenderer;
-
-    IDirect3DVertexBuffer9 *mQuadVertexBuffer;
-    IDirect3DVertexDeclaration9 *mQuadVertexDeclaration;
-
-    void initGeometry();
-
-    bool setFormatConvertShaders(GLenum destFormat);
-
-    bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
-    IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect);
-    void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset);
-    void setCommonBlitState();
-    RECT getSurfaceRect(IDirect3DSurface9 *surface) const;
-
-    // This enum is used to index mCompiledShaders and mShaderSource.
-    enum ShaderId
-    {
-        SHADER_VS_STANDARD,
-        SHADER_VS_FLIPY,
-        SHADER_PS_PASSTHROUGH,
-        SHADER_PS_LUMINANCE,
-        SHADER_PS_COMPONENTMASK,
-        SHADER_COUNT
-    };
-
-    // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown.
-    IUnknown *mCompiledShaders[SHADER_COUNT];
-
-    template <class D3DShaderType>
-    bool setShader(ShaderId source, const char *profile,
-                   D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length),
-                   HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*));
-
-    bool setVertexShader(ShaderId shader);
-    bool setPixelShader(ShaderId shader);
-    void render();
-
-    void saveState();
-    void restoreState();
-    IDirect3DStateBlock9 *mSavedStateBlock;
-    IDirect3DSurface9 *mSavedRenderTarget;
-    IDirect3DSurface9 *mSavedDepthStencil;
-
-    DISALLOW_COPY_AND_ASSIGN(Blit);
-};
-}
-
-#endif   // LIBGLESV2_BLIT_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage.cpp b/src/third_party/angle/src/libGLESv2/renderer/BufferStorage.cpp
deleted file mode 100644
index a49b7ba..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BufferStorage.cpp Defines the abstract BufferStorage class.
-
-#include "libGLESv2/renderer/BufferStorage.h"
-
-namespace rx
-{
-
-unsigned int BufferStorage::mNextSerial = 1;
-
-BufferStorage::BufferStorage()
-{
-    updateSerial();
-}
-
-BufferStorage::~BufferStorage()
-{
-}
-
-unsigned int BufferStorage::getSerial() const
-{
-    return mSerial;
-}
-
-void BufferStorage::updateSerial()
-{
-    mSerial = mNextSerial++;
-}
-
-void BufferStorage::markBufferUsage()
-{
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage.h b/src/third_party/angle/src/libGLESv2/renderer/BufferStorage.h
deleted file mode 100644
index ace1a11..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BufferStorage.h Defines the abstract BufferStorage class.
-
-#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE_H_
-#define LIBGLESV2_RENDERER_BUFFERSTORAGE_H_
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-
-class BufferStorage
-{
-  public:
-    BufferStorage();
-    virtual ~BufferStorage();
-
-    // The data returned is only guaranteed valid until next non-const method.
-    virtual void *getData() = 0;
-    virtual void setData(const void* data, unsigned int size, unsigned int offset) = 0;
-    virtual void clear() = 0;
-    virtual unsigned int getSize() const = 0;
-    virtual bool supportsDirectBinding() const = 0;
-    virtual void markBufferUsage();
-    unsigned int getSerial() const;
-
-  protected:
-    void updateSerial();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(BufferStorage);
-
-    unsigned int mSerial;
-    static unsigned int mNextSerial;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/src/third_party/angle/src/libGLESv2/renderer/BufferStorage11.cpp
deleted file mode 100644
index d1f2d4f..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage11.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BufferStorage11.cpp Defines the BufferStorage11 class.
-
-#include "libGLESv2/renderer/BufferStorage11.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/Renderer11.h"
-#include "libGLESv2/renderer/renderer11_utils.h"
-
-namespace rx
-{
-
-BufferStorage11::BufferStorage11(Renderer11 *renderer)
-{
-    mRenderer = renderer;
-
-    mStagingBuffer = NULL;
-    mStagingBufferSize = 0;
-
-    mBuffer = NULL;
-    mBufferSize = 0;
-
-    mSize = 0;
-
-    mResolvedData = NULL;
-    mResolvedDataSize = 0;
-    mResolvedDataValid = false;
-
-    mReadUsageCount = 0;
-    mWriteUsageCount = 0;
-}
-
-BufferStorage11::~BufferStorage11()
-{
-    if (mStagingBuffer)
-    {
-        mStagingBuffer->Release();
-        mStagingBuffer = NULL;
-    }
-
-    if (mBuffer)
-    {
-        mBuffer->Release();
-        mBuffer = NULL;
-    }
-
-    if (mResolvedData)
-    {
-        free(mResolvedData);
-        mResolvedData = NULL;
-    }
-}
-
-BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage));
-    return static_cast<BufferStorage11*>(bufferStorage);
-}
-
-void *BufferStorage11::getData()
-{
-    if (!mResolvedDataValid)
-    {
-        ID3D11Device *device = mRenderer->getDevice();
-        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-        HRESULT result;
-
-        if (!mStagingBuffer || mStagingBufferSize < mBufferSize)
-        {
-            if (mStagingBuffer)
-            {
-                mStagingBuffer->Release();
-                mStagingBuffer = NULL;
-                mStagingBufferSize = 0;
-            }
-
-            D3D11_BUFFER_DESC bufferDesc;
-            bufferDesc.ByteWidth = mSize;
-            bufferDesc.Usage = D3D11_USAGE_STAGING;
-            bufferDesc.BindFlags = 0;
-            bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
-            bufferDesc.MiscFlags = 0;
-            bufferDesc.StructureByteStride = 0;
-
-            result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
-            if (FAILED(result))
-            {
-                return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
-            }
-            d3d11::ResourceTracker::Track(mStagingBuffer);
-            mStagingBufferSize = bufferDesc.ByteWidth;
-        }
-
-        if (!mResolvedData || mResolvedDataSize < mBufferSize)
-        {
-            free(mResolvedData);
-            mResolvedData = malloc(mSize);
-            mResolvedDataSize = mSize;
-        }
-
-        D3D11_BOX srcBox;
-        srcBox.left = 0;
-        srcBox.right = mSize;
-        srcBox.top = 0;
-        srcBox.bottom = 1;
-        srcBox.front = 0;
-        srcBox.back = 1;
-
-        context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);
-
-        D3D11_MAPPED_SUBRESOURCE mappedResource;
-        result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
-        if (FAILED(result))
-        {
-            return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
-        }
-
-        memcpy(mResolvedData, mappedResource.pData, mSize);
-
-        context->Unmap(mStagingBuffer, 0);
-
-        mResolvedDataValid = true;
-    }
-
-    mReadUsageCount = 0;
-
-    return mResolvedData;
-}
-
-void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset)
-{
-    ID3D11Device *device = mRenderer->getDevice();
-    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-    HRESULT result;
-
-    unsigned int requiredBufferSize = size + offset;
-    unsigned int requiredStagingSize = size;
-    bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset);
-
-    if (!directInitialization)
-    {
-        if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize)
-        {
-            if (mStagingBuffer)
-            {
-                mStagingBuffer->Release();
-                mStagingBuffer = NULL;
-                mStagingBufferSize = 0;
-            }
-
-            D3D11_BUFFER_DESC bufferDesc;
-            bufferDesc.ByteWidth = size;
-            bufferDesc.Usage = D3D11_USAGE_STAGING;
-            bufferDesc.BindFlags = 0;
-            bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
-            bufferDesc.MiscFlags = 0;
-            bufferDesc.StructureByteStride = 0;
-
-            if (data)
-            {
-                D3D11_SUBRESOURCE_DATA initialData;
-                initialData.pSysMem = data;
-                initialData.SysMemPitch = size;
-                initialData.SysMemSlicePitch = 0;
-
-                result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
-            }
-            else
-            {
-                result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
-            }
-
-            if (FAILED(result))
-            {
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-            d3d11::ResourceTracker::Track(mStagingBuffer);
-            mStagingBufferSize = size;
-        }
-        else if (data)
-        {
-            D3D11_MAPPED_SUBRESOURCE mappedResource;
-            result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
-            if (FAILED(result))
-            {
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-
-            memcpy(mappedResource.pData, data, size);
-
-            context->Unmap(mStagingBuffer, 0);
-        }
-    }
-
-    if (!mBuffer || mBufferSize < size + offset)
-    {
-        D3D11_BUFFER_DESC bufferDesc;
-        bufferDesc.ByteWidth = requiredBufferSize;
-        bufferDesc.Usage = D3D11_USAGE_DEFAULT;
-        bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER;
-        bufferDesc.CPUAccessFlags = 0;
-        bufferDesc.MiscFlags = 0;
-        bufferDesc.StructureByteStride = 0;
-
-        if (directInitialization)
-        {
-            // Since the data will fill the entire buffer (being larger than the initial size and having
-            // no offset), the buffer can be initialized with the data so no staging buffer is required
-
-            // No longer need the old buffer
-            if (mBuffer)
-            {
-                mBuffer->Release();
-                mBuffer = NULL;
-                mBufferSize = 0;
-            }
-
-            if (data)
-            {
-                D3D11_SUBRESOURCE_DATA initialData;
-                initialData.pSysMem = data;
-                initialData.SysMemPitch = size;
-                initialData.SysMemSlicePitch = 0;
-
-                result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer);
-            }
-            else
-            {
-                result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
-            }
-
-            if (FAILED(result))
-            {
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-            d3d11::ResourceTracker::Track(mBuffer);
-        }
-        else if (mBuffer && offset > 0)
-        {
-            // If offset is greater than zero and the buffer is non-null, need to preserve the data from
-            // the old buffer up to offset
-            ID3D11Buffer *newBuffer = NULL;
-
-            result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
-            if (FAILED(result))
-            {
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-            d3d11::ResourceTracker::Track(newBuffer);
-
-            D3D11_BOX srcBox;
-            srcBox.left = 0;
-            srcBox.right = std::min(offset, mBufferSize);
-            srcBox.top = 0;
-            srcBox.bottom = 1;
-            srcBox.front = 0;
-            srcBox.back = 1;
-
-            context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);
-
-            mBuffer->Release();
-            mBuffer = newBuffer;
-        }
-        else
-        {
-            // Simple case, nothing needs to be copied from the old buffer to the new one, just create
-            // a new buffer
-
-            // No longer need the old buffer
-            if (mBuffer)
-            {
-                mBuffer->Release();
-                mBuffer = NULL;
-                mBufferSize = 0;
-            }
-
-            // Create a new buffer for data storage
-            result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
-            if (FAILED(result))
-            {
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-            d3d11::ResourceTracker::Track(mBuffer);
-        }
-
-        updateSerial();
-        mBufferSize = bufferDesc.ByteWidth;
-    }
-
-    if (!directInitialization)
-    {
-        ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize);
-
-        // Data is already put into the staging buffer, copy it over to the data buffer
-        D3D11_BOX srcBox;
-        srcBox.left = 0;
-        srcBox.right = size;
-        srcBox.top = 0;
-        srcBox.bottom = 1;
-        srcBox.front = 0;
-        srcBox.back = 1;
-
-        context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox);
-    }
-
-    mSize = std::max(mSize, offset + size);
-
-    mWriteUsageCount = 0;
-
-    mResolvedDataValid = false;
-}
-
-void BufferStorage11::clear()
-{
-    mResolvedDataValid = false;
-    mSize = 0;
-}
-
-unsigned int BufferStorage11::getSize() const
-{
-    return mSize;
-}
-
-bool BufferStorage11::supportsDirectBinding() const
-{
-    return true;
-}
-
-void BufferStorage11::markBufferUsage()
-{
-    mReadUsageCount++;
-    mWriteUsageCount++;
-
-    static const unsigned int usageLimit = 5;
-
-    if (mReadUsageCount > usageLimit && mResolvedData)
-    {
-        free(mResolvedData);
-        mResolvedData = NULL;
-        mResolvedDataSize = 0;
-        mResolvedDataValid = false;
-    }
-
-    if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer)
-    {
-        mStagingBuffer->Release();
-        mStagingBuffer = NULL;
-        mStagingBufferSize = 0;
-    }
-}
-
-ID3D11Buffer *BufferStorage11::getBuffer() const
-{
-    return mBuffer;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage11.h b/src/third_party/angle/src/libGLESv2/renderer/BufferStorage11.h
deleted file mode 100644
index b62348b..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage11.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BufferStorage11.h Defines the BufferStorage11 class.
-
-#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_
-#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_
-
-#include "libGLESv2/renderer/BufferStorage.h"
-
-namespace rx
-{
-class Renderer11;
-
-class BufferStorage11 : public BufferStorage
-{
-  public:
-    explicit BufferStorage11(Renderer11 *renderer);
-    virtual ~BufferStorage11();
-
-    static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage);
-
-    virtual void *getData();
-    virtual void setData(const void* data, unsigned int size, unsigned int offset);
-    virtual void clear();
-    virtual unsigned int getSize() const;
-    virtual bool supportsDirectBinding() const;
-    virtual void markBufferUsage();
-
-    ID3D11Buffer *getBuffer() const;
-
-  private:
-    Renderer11 *mRenderer;
-
-    ID3D11Buffer *mStagingBuffer;
-    unsigned int mStagingBufferSize;
-
-    ID3D11Buffer *mBuffer;
-    unsigned int mBufferSize;
-
-    unsigned int mSize;
-
-    void *mResolvedData;
-    unsigned int mResolvedDataSize;
-    bool mResolvedDataValid;
-
-    unsigned int mReadUsageCount;
-    unsigned int mWriteUsageCount;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage9.cpp b/src/third_party/angle/src/libGLESv2/renderer/BufferStorage9.cpp
deleted file mode 100644
index e69e7a8..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage9.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BufferStorage9.cpp Defines the BufferStorage9 class.
-
-#include "libGLESv2/renderer/BufferStorage9.h"
-#include "common/debug.h"
-
-namespace rx
-{
-
-BufferStorage9::BufferStorage9()
-{
-    mMemory = NULL;
-    mAllocatedSize = 0;
-    mSize = 0;
-}
-
-BufferStorage9::~BufferStorage9()
-{
-    delete[] mMemory;
-}
-
-BufferStorage9 *BufferStorage9::makeBufferStorage9(BufferStorage *bufferStorage)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(BufferStorage9*, bufferStorage));
-    return static_cast<BufferStorage9*>(bufferStorage);
-}
-
-void *BufferStorage9::getData()
-{
-    return mMemory;
-}
-
-void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset)
-{
-    if (!mMemory || offset + size > mAllocatedSize)
-    {
-        unsigned int newAllocatedSize = offset + size;
-        void *newMemory = new char[newAllocatedSize];
-
-        if (offset > 0 && mMemory && mAllocatedSize > 0)
-        {
-            memcpy(newMemory, mMemory, std::min(offset, mAllocatedSize));
-        }
-
-        delete[] mMemory;
-        mMemory = newMemory;
-        mAllocatedSize = newAllocatedSize;
-    }
-
-    mSize = std::max(mSize, offset + size);
-    if (data)
-    {
-        memcpy(reinterpret_cast<char*>(mMemory) + offset, data, size);
-    }
-}
-
-void BufferStorage9::clear()
-{
-    mSize = 0;
-}
-
-unsigned int BufferStorage9::getSize() const
-{
-    return mSize;
-}
-
-bool BufferStorage9::supportsDirectBinding() const
-{
-    return false;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage9.h b/src/third_party/angle/src/libGLESv2/renderer/BufferStorage9.h
deleted file mode 100644
index 3e80396..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/BufferStorage9.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BufferStorage9.h Defines the BufferStorage9 class.
-
-#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_
-#define LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_
-
-#include "libGLESv2/renderer/BufferStorage.h"
-
-namespace rx
-{
-
-class BufferStorage9 : public BufferStorage
-{
-  public:
-    BufferStorage9();
-    virtual ~BufferStorage9();
-
-    static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage);
-
-    virtual void *getData();
-    virtual void setData(const void* data, unsigned int size, unsigned int offset);
-    virtual void clear();
-    virtual unsigned int getSize() const;
-    virtual bool supportsDirectBinding() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(BufferStorage9);
-
-    void *mMemory;
-    unsigned int mAllocatedSize;
-
-    unsigned int mSize;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Fence11.cpp b/src/third_party/angle/src/libGLESv2/renderer/Fence11.cpp
deleted file mode 100644
index 9d11c9a..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Fence11.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl.
-
-#include "libGLESv2/renderer/Fence11.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/Renderer11.h"
-
-namespace rx
-{
-
-Fence11::Fence11(rx::Renderer11 *renderer)
-{
-    mRenderer = renderer;
-    mQuery = NULL;
-}
-
-Fence11::~Fence11()
-{
-    if (mQuery)
-    {
-        mQuery->Release();
-        mQuery = NULL;
-    }
-}
-
-GLboolean Fence11::isFence()
-{
-    // GL_NV_fence spec:
-    // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
-    return mQuery != NULL;
-}
-
-void Fence11::setFence(GLenum condition)
-{
-    if (!mQuery)
-    {
-        D3D11_QUERY_DESC queryDesc;
-        queryDesc.Query = D3D11_QUERY_EVENT;
-        queryDesc.MiscFlags = 0;
-
-        if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
-        {
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    mRenderer->getDeviceContext()->End(mQuery);
-
-    setCondition(condition);
-    setStatus(GL_FALSE);
-}
-
-GLboolean Fence11::testFence()
-{
-    if (mQuery == NULL)
-    {
-        return gl::error(GL_INVALID_OPERATION, GL_TRUE);
-    }
-
-    HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0);
-
-    if (mRenderer->isDeviceLost())
-    {
-       return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
-    }
-
-    ASSERT(result == S_OK || result == S_FALSE);
-    setStatus(result == S_OK);
-    return getStatus();
-}
-
-void Fence11::finishFence()
-{
-    if (mQuery == NULL)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    while (!testFence())
-    {
-        Sleep(0);
-    }
-}
-
-void Fence11::getFenceiv(GLenum pname, GLint *params)
-{
-    if (mQuery == NULL)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    switch (pname)
-    {
-      case GL_FENCE_STATUS_NV:
-        {
-            // GL_NV_fence spec:
-            // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
-            // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
-            if (getStatus())
-            {
-                params[0] = GL_TRUE;
-                return;
-            }
-
-            HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
-
-            if (mRenderer->isDeviceLost())
-            {
-                params[0] = GL_TRUE;
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-
-            ASSERT(result == S_OK || result == S_FALSE);
-            setStatus(result == S_OK);
-            params[0] = getStatus();
-
-            break;
-        }
-      case GL_FENCE_CONDITION_NV:
-        params[0] = getCondition();
-        break;
-      default:
-        return gl::error(GL_INVALID_ENUM);
-        break;
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Fence11.h b/src/third_party/angle/src/libGLESv2/renderer/Fence11.h
deleted file mode 100644
index a5398bc..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Fence11.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl.
-
-#ifndef LIBGLESV2_RENDERER_Fence11_H_
-#define LIBGLESV2_RENDERER_Fence11_H_
-
-#include "libGLESv2/renderer/FenceImpl.h"
-
-namespace rx
-{
-class Renderer11;
-
-class Fence11 : public FenceImpl
-{
-  public:
-    explicit Fence11(rx::Renderer11 *renderer);
-    virtual ~Fence11();
-
-    GLboolean isFence();
-    void setFence(GLenum condition);
-    GLboolean testFence();
-    void finishFence();
-    void getFenceiv(GLenum pname, GLint *params);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Fence11);
-
-    rx::Renderer11 *mRenderer;
-    ID3D11Query *mQuery;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_FENCE11_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Fence9.cpp b/src/third_party/angle/src/libGLESv2/renderer/Fence9.cpp
deleted file mode 100644
index 86064d7..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Fence9.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Fence9.cpp: Defines the rx::Fence9 class.
-
-#include "libGLESv2/renderer/Fence9.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/renderer9_utils.h"
-#include "libGLESv2/renderer/Renderer9.h"
-
-namespace rx
-{
-
-Fence9::Fence9(rx::Renderer9 *renderer)
-{
-    mRenderer = renderer;
-    mQuery = NULL;
-}
-
-Fence9::~Fence9()
-{
-    if (mQuery)
-    {
-        mRenderer->freeEventQuery(mQuery);
-        mQuery = NULL;
-    }
-}
-
-GLboolean Fence9::isFence()
-{
-    // GL_NV_fence spec:
-    // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
-    return mQuery != NULL;
-}
-
-void Fence9::setFence(GLenum condition)
-{
-    if (!mQuery)
-    {
-        mQuery = mRenderer->allocateEventQuery();
-        if (!mQuery)
-        {
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    HRESULT result = mQuery->Issue(D3DISSUE_END);
-    ASSERT(SUCCEEDED(result));
-
-    setCondition(condition);
-    setStatus(GL_FALSE);
-}
-
-GLboolean Fence9::testFence()
-{
-    if (mQuery == NULL)
-    {
-        return gl::error(GL_INVALID_OPERATION, GL_TRUE);
-    }
-
-    HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
-
-    if (d3d9::isDeviceLostError(result))
-    {
-        mRenderer->notifyDeviceLost();
-        return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
-    }
-
-    ASSERT(result == S_OK || result == S_FALSE);
-    setStatus(result == S_OK);
-    return getStatus();
-}
-
-void Fence9::finishFence()
-{
-    if (mQuery == NULL)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    while (!testFence())
-    {
-        Sleep(0);
-    }
-}
-
-void Fence9::getFenceiv(GLenum pname, GLint *params)
-{
-    if (mQuery == NULL)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    switch (pname)
-    {
-        case GL_FENCE_STATUS_NV:
-        {
-            // GL_NV_fence spec:
-            // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
-            // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
-            if (getStatus())
-            {
-                params[0] = GL_TRUE;
-                return;
-            }
-            
-            HRESULT result = mQuery->GetData(NULL, 0, 0);
-
-            if (d3d9::isDeviceLostError(result))
-            {
-                params[0] = GL_TRUE;
-                mRenderer->notifyDeviceLost();
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-
-            ASSERT(result == S_OK || result == S_FALSE);
-            setStatus(result == S_OK);
-            params[0] = getStatus();
-
-            break;
-        }
-        case GL_FENCE_CONDITION_NV:
-            params[0] = getCondition();
-            break;
-        default:
-            return gl::error(GL_INVALID_ENUM);
-            break;
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Fence9.h b/src/third_party/angle/src/libGLESv2/renderer/Fence9.h
deleted file mode 100644
index 9f17641..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Fence9.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Fence9.h: Defines the rx::Fence9 class which implements rx::FenceImpl.
-
-#ifndef LIBGLESV2_RENDERER_FENCE9_H_
-#define LIBGLESV2_RENDERER_FENCE9_H_
-
-#include "libGLESv2/renderer/FenceImpl.h"
-
-namespace rx
-{
-class Renderer9;
-
-class Fence9 : public FenceImpl
-{
-  public:
-    explicit Fence9(rx::Renderer9 *renderer);
-    virtual ~Fence9();
-
-    GLboolean isFence();
-    void setFence(GLenum condition);
-    GLboolean testFence();
-    void finishFence();
-    void getFenceiv(GLenum pname, GLint *params);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Fence9);
-
-    rx::Renderer9 *mRenderer;
-    IDirect3DQuery9 *mQuery;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_FENCE9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/FenceImpl.h b/src/third_party/angle/src/libGLESv2/renderer/FenceImpl.h
deleted file mode 100644
index d7f2102..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/FenceImpl.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// FenceImpl.h: Defines the rx::FenceImpl class.
-
-#ifndef LIBGLESV2_RENDERER_FENCEIMPL_H_
-#define LIBGLESV2_RENDERER_FENCEIMPL_H_
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-
-class FenceImpl
-{
-  public:
-    FenceImpl() : mStatus(GL_FALSE), mCondition(GL_NONE) { };
-    virtual ~FenceImpl() { };
-
-    virtual GLboolean isFence() = 0;
-    virtual void setFence(GLenum condition) = 0;
-    virtual GLboolean testFence() = 0;
-    virtual void finishFence() = 0;
-    virtual void getFenceiv(GLenum pname, GLint *params) = 0;
-
-  protected:
-    void setStatus(GLboolean status) { mStatus = status; }
-    GLboolean getStatus() const { return mStatus; }
-
-    void setCondition(GLuint condition) { mCondition = condition; }
-    GLuint getCondition() const { return mCondition; }
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(FenceImpl);
-
-    GLboolean mStatus;
-    GLenum mCondition;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_FENCEIMPL_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Image.cpp b/src/third_party/angle/src/libGLESv2/renderer/Image.cpp
deleted file mode 100644
index 57239ef..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Image.cpp
+++ /dev/null
@@ -1,548 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image.h: Implements the rx::Image class, an abstract base class for the 
-// renderer-specific classes which will define the interface to the underlying
-// surfaces or resources.
-
-#include "libGLESv2/renderer/Image.h"
-
-namespace rx
-{
-
-Image::Image()
-{
-    mWidth = 0; 
-    mHeight = 0;
-    mInternalFormat = GL_NONE;
-    mActualFormat = GL_NONE;
-}
-
-void Image::loadAlphaDataToBGRA(GLsizei width, GLsizei height,
-                                int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-    
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = 0;
-            dest[4 * x + 1] = 0;
-            dest[4 * x + 2] = 0;
-            dest[4 * x + 3] = source[x];
-        }
-    }
-}
-
-void Image::loadAlphaDataToNative(GLsizei width, GLsizei height,
-                                  int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        memcpy(dest, source, width);
-    }
-}
-
-void Image::loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = 0;
-            dest[4 * x + 1] = 0;
-            dest[4 * x + 2] = 0;
-            dest[4 * x + 3] = source[x];
-        }
-    }
-}
-
-void Image::loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned short *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = 0;
-            dest[4 * x + 1] = 0;
-            dest[4 * x + 2] = 0;
-            dest[4 * x + 3] = source[x];
-        }
-    }
-}
-
-void Image::loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height,
-                                            int inputPitch, const void *input, size_t outputPitch, void *output, bool native)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-
-        if (!native)   // BGRA8 destination format
-        {
-            for (int x = 0; x < width; x++)
-            {
-                dest[4 * x + 0] = source[x];
-                dest[4 * x + 1] = source[x];
-                dest[4 * x + 2] = source[x];
-                dest[4 * x + 3] = 0xFF;
-            }
-        }
-        else   // L8 destination format
-        {
-            memcpy(dest, source, width);
-        }
-    }
-}
-
-void Image::loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = source[x];
-            dest[4 * x + 1] = source[x];
-            dest[4 * x + 2] = source[x];
-            dest[4 * x + 3] = 1.0f;
-        }
-    }
-}
-
-void Image::loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[3 * x + 0] = source[x];
-            dest[3 * x + 1] = source[x];
-            dest[3 * x + 2] = source[x];
-        }
-    }
-}
-
-void Image::loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                             int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned short *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = source[x];
-            dest[4 * x + 1] = source[x];
-            dest[4 * x + 2] = source[x];
-            dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
-        }
-    }
-}
-
-void Image::loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height,
-                                                 int inputPitch, const void *input, size_t outputPitch, void *output, bool native)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        
-        if (!native)   // BGRA8 destination format
-        {
-            for (int x = 0; x < width; x++)
-            {
-                dest[4 * x + 0] = source[2*x+0];
-                dest[4 * x + 1] = source[2*x+0];
-                dest[4 * x + 2] = source[2*x+0];
-                dest[4 * x + 3] = source[2*x+1];
-            }
-        }
-        else
-        {
-            memcpy(dest, source, width * 2);
-        }
-    }
-}
-
-void Image::loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
-                                              int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = source[2*x+0];
-            dest[4 * x + 1] = source[2*x+0];
-            dest[4 * x + 2] = source[2*x+0];
-            dest[4 * x + 3] = source[2*x+1];
-        }
-    }
-}
-
-void Image::loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                                  int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned short *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = source[2*x+0];
-            dest[4 * x + 1] = source[2*x+0];
-            dest[4 * x + 2] = source[2*x+0];
-            dest[4 * x + 3] = source[2*x+1];
-        }
-    }
-}
-
-void Image::loadRGBUByteDataToBGRX(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = source[x * 3 + 2];
-            dest[4 * x + 1] = source[x * 3 + 1];
-            dest[4 * x + 2] = source[x * 3 + 0];
-            dest[4 * x + 3] = 0xFF;
-        }
-    }
-}
-
-void Image::loadRGBUByteDataToRGBA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = source[x * 3 + 0];
-            dest[4 * x + 1] = source[x * 3 + 1];
-            dest[4 * x + 2] = source[x * 3 + 2];
-            dest[4 * x + 3] = 0xFF;
-        }
-    }
-}
-
-void Image::loadRGB565DataToBGRA(GLsizei width, GLsizei height,
-                                 int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
-        {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
-            dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
-            dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-            dest[4 * x + 3] = 0xFF;
-        }
-    }
-}
-
-void Image::loadRGB565DataToRGBA(GLsizei width, GLsizei height,
-                                 int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
-        {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-            dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
-            dest[4 * x + 2] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
-            dest[4 * x + 3] = 0xFF;
-        }
-    }
-}
-
-void Image::loadRGBFloatDataToRGBA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = source[x * 3 + 0];
-            dest[4 * x + 1] = source[x * 3 + 1];
-            dest[4 * x + 2] = source[x * 3 + 2];
-            dest[4 * x + 3] = 1.0f;
-        }
-    }
-}
-
-void Image::loadRGBFloatDataToNative(GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        memcpy(dest, source, width * 12);
-    }
-}
-
-void Image::loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned short *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = source[x * 3 + 0];
-            dest[4 * x + 1] = source[x * 3 + 1];
-            dest[4 * x + 2] = source[x * 3 + 2];
-            dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
-        }
-    }
-}
-
-void Image::loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned int *source = NULL;
-    unsigned int *dest = NULL;
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-
-        for (int x = 0; x < width; x++)
-        {
-            unsigned int rgba = source[x];
-            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
-        }
-    }
-}
-
-void Image::loadRGBAUByteDataToNative(GLsizei width, GLsizei height,
-                                      int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned int *source = NULL;
-    unsigned int *dest = NULL;
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-
-        memcpy(dest, source, width * 4);
-    }
-}
-
-void Image::loadRGBA4444DataToBGRA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
-        {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
-            dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
-            dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
-            dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
-        }
-    }
-}
-
-void Image::loadRGBA4444DataToRGBA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
-        {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
-            dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
-            dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
-            dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
-        }
-    }
-}
-
-void Image::loadRGBA5551DataToBGRA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
-        {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
-            dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
-            dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-            dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
-        }
-    }
-}
-
-void Image::loadRGBA5551DataToRGBA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
-        {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-            dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
-            dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
-            dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
-        }
-    }
-}
-
-void Image::loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        memcpy(dest, source, width * 16);
-    }
-}
-
-void Image::loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        memcpy(dest, source, width * 8);
-    }
-}
-
-void Image::loadBGRADataToBGRA(GLsizei width, GLsizei height,
-                               int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        memcpy(dest, source, width*4);
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Image.h b/src/third_party/angle/src/libGLESv2/renderer/Image.h
deleted file mode 100644
index 454e83e..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Image.h
+++ /dev/null
@@ -1,131 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image.h: Defines the rx::Image class, an abstract base class for the 
-// renderer-specific classes which will define the interface to the underlying
-// surfaces or resources.
-
-#ifndef LIBGLESV2_RENDERER_IMAGE_H_
-#define LIBGLESV2_RENDERER_IMAGE_H_
-
-#include "common/debug.h"
-
-namespace gl
-{
-class Framebuffer;
-}
-
-namespace rx
-{
-class Renderer;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
-
-class Image
-{
-  public:
-    Image();
-    virtual ~Image() {};
-
-    GLsizei getWidth() const { return mWidth; }
-    GLsizei getHeight() const { return mHeight; }
-    GLenum getInternalFormat() const { return mInternalFormat; }
-    GLenum getActualFormat() const { return mActualFormat; }
-
-    void markDirty() {mDirty = true;}
-    void markClean() {mDirty = false;}
-    virtual bool isDirty() const = 0;
-
-    virtual void setManagedSurface(TextureStorageInterface2D *storage, int level) {};
-    virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) {};
-    virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
-    virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
-
-    virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) = 0;
-
-    virtual bool isRenderableFormat() const = 0;
-    
-    virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                  GLint unpackAlignment, const void *input) = 0;
-    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                    const void *input) = 0;
-
-    virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
-
-    static void loadAlphaDataToBGRA(GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadAlphaDataToNative(GLsizei width, GLsizei height,
-                                      int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                             int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output, bool native);
-    static void loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height,
-                                             int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height,
-                                            int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                                 int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height,
-                                             int inputPitch, const void *input, size_t outputPitch, void *output, bool native);
-    static void loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
-                                                  int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                                      int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBUByteDataToBGRX(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBUByteDataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGB565DataToBGRA(GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGB565DataToRGBA(GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBFloatDataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBFloatDataToNative(GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                           int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height,
-                                            int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAUByteDataToNative(GLsizei width, GLsizei height,
-                                          int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBA4444DataToBGRA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBA4444DataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBA5551DataToBGRA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBA5551DataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                            int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadBGRADataToBGRA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output);
-
-  protected:
-    GLsizei mWidth;
-    GLsizei mHeight;
-    GLint mInternalFormat;
-    GLenum mActualFormat;
-
-    bool mDirty;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Image);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_IMAGE_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Image11.cpp b/src/third_party/angle/src/libGLESv2/renderer/Image11.cpp
deleted file mode 100644
index a9a335d..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Image11.cpp
+++ /dev/null
@@ -1,459 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image11.h: Implements the rx::Image11 class, which acts as the interface to
-// the actual underlying resources of a Texture
-
-#include "libGLESv2/renderer/Renderer11.h"
-#include "libGLESv2/renderer/Image11.h"
-#include "libGLESv2/renderer/TextureStorage11.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/renderer/renderer11_utils.h"
-#include "libGLESv2/renderer/generatemip.h"
-
-namespace rx
-{
-
-Image11::Image11()
-{
-    mStagingTexture = NULL;
-    mRenderer = NULL;
-    mDXGIFormat = DXGI_FORMAT_UNKNOWN;
-}
-
-Image11::~Image11()
-{
-    if (mStagingTexture)
-    {
-        mStagingTexture->Release();
-    }
-}
-
-Image11 *Image11::makeImage11(Image *img)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img));
-    return static_cast<rx::Image11*>(img);
-}
-
-void Image11::generateMipmap(Image11 *dest, Image11 *src)
-{
-    ASSERT(src->getDXGIFormat() == dest->getDXGIFormat());
-    ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth());
-    ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
-
-    D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped;
-    dest->map(&destMapped);
-    src->map(&srcMapped);
-
-    const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(srcMapped.pData);
-    unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData);
-
-    if (sourceData && destData)
-    {
-        switch (src->getDXGIFormat())
-        {
-          case DXGI_FORMAT_R8G8B8A8_UNORM:
-          case DXGI_FORMAT_B8G8R8A8_UNORM:
-            GenerateMip<R8G8B8A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_A8_UNORM:
-            GenerateMip<A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_R8_UNORM:
-            GenerateMip<R8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_R32G32B32A32_FLOAT:
-            GenerateMip<A32B32G32R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_R32G32B32_FLOAT:
-            GenerateMip<R32G32B32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_R16G16B16A16_FLOAT:
-            GenerateMip<A16B16G16R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_R8G8_UNORM:
-            GenerateMip<R8G8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_R16_FLOAT:
-            GenerateMip<R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_R16G16_FLOAT:
-            GenerateMip<R16G16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_R32_FLOAT:
-            GenerateMip<R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          case DXGI_FORMAT_R32G32_FLOAT:
-            GenerateMip<R32G32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
-            break;
-          default:
-            UNREACHABLE();
-            break;
-        }
-
-        dest->unmap();
-        src->unmap();
-    }
-
-    dest->markDirty();
-}
-
-bool Image11::isDirty() const
-{
-    return (mStagingTexture && mDirty);
-}
-
-bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
-    TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
-    return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height);
-}
-
-bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
-    TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
-    return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height);
-}
-
-bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
-{
-    if (mWidth != width ||
-        mHeight != height ||
-        mInternalFormat != internalformat ||
-        forceRelease)
-    {
-        mRenderer = Renderer11::makeRenderer11(renderer);
-
-        mWidth = width;
-        mHeight = height;
-        mInternalFormat = internalformat;
-        // compute the d3d format that will be used
-        mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat);
-        mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat);
-
-        if (mStagingTexture)
-        {
-            mStagingTexture->Release();
-            mStagingTexture = NULL;
-        }
-        
-        return true;
-    }
-
-    return false;
-}
-
-bool Image11::isRenderableFormat() const
-{
-    return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat);
-}
-
-DXGI_FORMAT Image11::getDXGIFormat() const
-{
-    // this should only happen if the image hasn't been redefined first
-    // which would be a bug by the caller
-    ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN);
-
-    return mDXGIFormat;
-}
-
-// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
-// into the target pixel rectangle.
-void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                       GLint unpackAlignment, const void *input)
-{
-    D3D11_MAPPED_SUBRESOURCE mappedImage;
-    HRESULT result = map(&mappedImage);
-    if (FAILED(result))
-    {
-        ERR("Could not map image for loading.");
-        return;
-    }
-    
-    GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
-    size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8;
-    void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize));
-
-    switch (mInternalFormat)
-    {
-      case GL_ALPHA8_EXT:
-        loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_LUMINANCE8_EXT:
-        loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
-        break;
-      case GL_ALPHA32F_EXT:
-        loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_LUMINANCE32F_EXT:
-        loadLuminanceFloatDataToRGB(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_ALPHA16F_EXT:
-        loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_LUMINANCE16F_EXT:
-        loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_LUMINANCE8_ALPHA8_EXT:
-        loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
-        break;
-      case GL_LUMINANCE_ALPHA32F_EXT:
-        loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_LUMINANCE_ALPHA16F_EXT:
-        loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_RGB8_OES:
-        loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_RGB565:
-        loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_RGBA8_OES:
-        loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_RGBA4:
-        loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_RGB5_A1:
-        loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_BGRA8_EXT:
-        loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_RGB32F_EXT:
-        loadRGBFloatDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_RGB16F_EXT:
-        loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_RGBA32F_EXT:
-        loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      case GL_RGBA16F_EXT:
-        loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
-        break;
-      default: UNREACHABLE(); 
-    }
-
-    unmap();
-}
-
-void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                const void *input)
-{
-    ASSERT(xoffset % 4 == 0);
-    ASSERT(yoffset % 4 == 0);
-
-    D3D11_MAPPED_SUBRESOURCE mappedImage;
-    HRESULT result = map(&mappedImage);
-    if (FAILED(result))
-    {
-        ERR("Could not map image for loading.");
-        return;
-    }
-
-    // Size computation assumes a 4x4 block compressed texture format
-    size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8;
-    void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize));
-
-    GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
-    GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
-    int rows = inputSize / inputPitch;
-    for (int i = 0; i < rows; ++i)
-    {
-        memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
-    }
-
-    unmap();
-}
-
-void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
-{
-    gl::Renderbuffer *colorbuffer = source->getReadColorbuffer();
-
-    if (colorbuffer && colorbuffer->getActualFormat() == (GLuint)mActualFormat)
-    {
-        // No conversion needed-- use copyback fastpath
-        ID3D11Texture2D *colorBufferTexture = NULL;
-        unsigned int subresourceIndex = 0;
-
-        if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
-        {
-            D3D11_TEXTURE2D_DESC textureDesc;
-            colorBufferTexture->GetDesc(&textureDesc);
-
-            ID3D11Device *device = mRenderer->getDevice();
-            ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-
-            ID3D11Texture2D* srcTex = NULL;
-            if (textureDesc.SampleDesc.Count > 1)
-            {
-                D3D11_TEXTURE2D_DESC resolveDesc;
-                resolveDesc.Width = textureDesc.Width;
-                resolveDesc.Height = textureDesc.Height;
-                resolveDesc.MipLevels = 1;
-                resolveDesc.ArraySize = 1;
-                resolveDesc.Format = textureDesc.Format;
-                resolveDesc.SampleDesc.Count = 1;
-                resolveDesc.SampleDesc.Quality = 0;
-                resolveDesc.Usage = D3D11_USAGE_DEFAULT;
-                resolveDesc.BindFlags = 0;
-                resolveDesc.CPUAccessFlags = 0;
-                resolveDesc.MiscFlags = 0;
-
-                HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
-                if (FAILED(result))
-                {
-                    ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
-                    return;
-                }
-                d3d11::ResourceTracker::Track(srcTex);
-
-                deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format);
-                subresourceIndex = 0;
-            }
-            else
-            {
-                srcTex = colorBufferTexture;
-                srcTex->AddRef();
-            }
-
-            D3D11_BOX srcBox;
-            srcBox.left = x;
-            srcBox.right = x + width;
-            srcBox.top = y;
-            srcBox.bottom = y + height;
-            srcBox.front = 0;
-            srcBox.back = 1;
-
-            deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, 0, srcTex, subresourceIndex, &srcBox);
-
-            srcTex->Release();
-            colorBufferTexture->Release();
-        }
-    }
-    else
-    {
-        // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
-        D3D11_MAPPED_SUBRESOURCE mappedImage;
-        HRESULT result = map(&mappedImage);
-            
-        // determine the offset coordinate into the destination buffer
-        GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset;
-        void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset;
-
-        mRenderer->readPixels(source, x, y, width, height, gl::ExtractFormat(mInternalFormat), 
-                              gl::ExtractType(mInternalFormat), mappedImage.RowPitch, false, 4, dataOffset);
-
-        unmap();
-    }
-}
-
-ID3D11Texture2D *Image11::getStagingTexture()
-{
-    createStagingTexture();
-
-    return mStagingTexture;
-}
-
-unsigned int Image11::getStagingSubresource()
-{
-    createStagingTexture();
-
-    return mStagingSubresource;
-}
-
-void Image11::createStagingTexture()
-{
-    if (mStagingTexture)
-    {
-        return;
-    }
-
-    ID3D11Texture2D *newTexture = NULL;
-    int lodOffset = 1;
-    const DXGI_FORMAT dxgiFormat = getDXGIFormat();
-    ASSERT(!d3d11::IsDepthStencilFormat(dxgiFormat)); // We should never get here for depth textures
-
-    if (mWidth != 0 && mHeight != 0)
-    {
-        GLsizei width = mWidth;
-        GLsizei height = mHeight;
-
-        // adjust size if needed for compressed textures
-        gl::MakeValidSize(false, d3d11::IsCompressed(dxgiFormat), &width, &height, &lodOffset);
-        ID3D11Device *device = mRenderer->getDevice();
-
-        D3D11_TEXTURE2D_DESC desc;
-        desc.Width = width;
-        desc.Height = height;
-        desc.MipLevels = lodOffset + 1;
-        desc.ArraySize = 1;
-        desc.Format = dxgiFormat;
-        desc.SampleDesc.Count = 1;
-        desc.SampleDesc.Quality = 0;
-        desc.Usage = D3D11_USAGE_STAGING;
-        desc.BindFlags = 0;
-        desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-        desc.MiscFlags = 0;
-
-        HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == E_OUTOFMEMORY);
-            ERR("Creating image failed.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-        d3d11::ResourceTracker::Track(newTexture);
-    }
-
-    mStagingTexture = newTexture;
-    mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
-    mDirty = false;
-}
-
-HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
-{
-    createStagingTexture();
-
-    HRESULT result = E_FAIL;
-
-    if (mStagingTexture)
-    {
-        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-        result = deviceContext->Map(mStagingTexture, mStagingSubresource, D3D11_MAP_WRITE, 0, map);
-
-        // this can fail if the device is removed (from TDR)
-        if (d3d11::isDeviceLostError(result))
-        {
-            mRenderer->notifyDeviceLost();
-        }
-        else if (SUCCEEDED(result))
-        {
-            mDirty = true;
-        }
-    }
-
-    return result;
-}
-
-void Image11::unmap()
-{
-    if (mStagingTexture)
-    {
-        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-        deviceContext->Unmap(mStagingTexture, mStagingSubresource);
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Image11.h b/src/third_party/angle/src/libGLESv2/renderer/Image11.h
deleted file mode 100644
index 4d5f1c1..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Image11.h
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image11.h: Defines the rx::Image11 class, which acts as the interface to
-// the actual underlying resources of a Texture
-
-#ifndef LIBGLESV2_RENDERER_IMAGE11_H_
-#define LIBGLESV2_RENDERER_IMAGE11_H_
-
-#include "libGLESv2/renderer/Image.h"
-
-#include "common/debug.h"
-
-namespace gl
-{
-class Framebuffer;
-}
-
-namespace rx
-{
-class Renderer;
-class Renderer11;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
-
-class Image11 : public Image
-{
-  public:
-    Image11();
-    virtual ~Image11();
-
-    static Image11 *makeImage11(Image *img);
-
-    static void generateMipmap(Image11 *dest, Image11 *src);
-
-    virtual bool isDirty() const;
-
-    virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
-    virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease);
-
-    virtual bool isRenderableFormat() const;
-    DXGI_FORMAT getDXGIFormat() const;
-    
-    virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                  GLint unpackAlignment, const void *input);
-    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                    const void *input);
-
-    virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-
-  protected:
-    HRESULT map(D3D11_MAPPED_SUBRESOURCE *map);
-    void unmap();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Image11);
-
-    ID3D11Texture2D *getStagingTexture();
-    unsigned int getStagingSubresource();
-    void createStagingTexture();
-
-    Renderer11 *mRenderer;
-
-    DXGI_FORMAT mDXGIFormat;
-    ID3D11Texture2D *mStagingTexture;
-    unsigned int mStagingSubresource;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_IMAGE11_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Image9.cpp b/src/third_party/angle/src/libGLESv2/renderer/Image9.cpp
deleted file mode 100644
index b3dcc59..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Image9.cpp
+++ /dev/null
@@ -1,732 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to
-// the actual underlying surfaces of a Texture.
-
-#include "libGLESv2/renderer/Image9.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/renderer/Renderer9.h"
-#include "libGLESv2/renderer/RenderTarget9.h"
-#include "libGLESv2/renderer/TextureStorage9.h"
-
-#include "libGLESv2/renderer/renderer9_utils.h"
-#include "libGLESv2/renderer/generatemip.h"
-
-namespace rx
-{
-
-Image9::Image9()
-{
-    mSurface = NULL;
-    mRenderer = NULL;
-
-    mD3DPool = D3DPOOL_SYSTEMMEM;
-    mD3DFormat = D3DFMT_UNKNOWN;
-}
-
-Image9::~Image9()
-{
-    if (mSurface)
-    {
-        mSurface->Release();
-    }
-}
-
-void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
-{
-    D3DSURFACE_DESC destDesc;
-    HRESULT result = destSurface->GetDesc(&destDesc);
-    ASSERT(SUCCEEDED(result));
-
-    D3DSURFACE_DESC sourceDesc;
-    result = sourceSurface->GetDesc(&sourceDesc);
-    ASSERT(SUCCEEDED(result));
-
-    ASSERT(sourceDesc.Format == destDesc.Format);
-    ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width);
-    ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height);
-
-    D3DLOCKED_RECT sourceLocked = {0};
-    result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
-    ASSERT(SUCCEEDED(result));
-
-    D3DLOCKED_RECT destLocked = {0};
-    result = destSurface->LockRect(&destLocked, NULL, 0);
-    ASSERT(SUCCEEDED(result));
-
-    const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(sourceLocked.pBits);
-    unsigned char *destData = reinterpret_cast<unsigned char*>(destLocked.pBits);
-
-    if (sourceData && destData)
-    {
-        switch (sourceDesc.Format)
-        {
-          case D3DFMT_L8:
-            GenerateMip<L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
-            break;
-          case D3DFMT_A8L8:
-            GenerateMip<A8L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
-            break;
-          case D3DFMT_A8R8G8B8:
-          case D3DFMT_X8R8G8B8:
-            GenerateMip<A8R8G8B8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
-            break;
-          case D3DFMT_A16B16G16R16F:
-            GenerateMip<A16B16G16R16F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
-            break;
-          case D3DFMT_A32B32G32R32F:
-            GenerateMip<A32B32G32R32F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
-            break;
-          default:
-            UNREACHABLE();
-            break;
-        }
-
-        destSurface->UnlockRect();
-        sourceSurface->UnlockRect();
-    }
-}
-
-Image9 *Image9::makeImage9(Image *img)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img));
-    return static_cast<rx::Image9*>(img);
-}
-
-void Image9::generateMipmap(Image9 *dest, Image9 *source)
-{
-    IDirect3DSurface9 *sourceSurface = source->getSurface();
-    if (sourceSurface == NULL)
-        return gl::error(GL_OUT_OF_MEMORY);
-
-    IDirect3DSurface9 *destSurface = dest->getSurface();
-    generateMip(destSurface, sourceSurface);
-
-    dest->markDirty();
-}
-
-void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
-{
-    D3DLOCKED_RECT sourceLock = {0};
-    D3DLOCKED_RECT destLock = {0};
-    
-    source->LockRect(&sourceLock, NULL, 0);
-    dest->LockRect(&destLock, NULL, 0);
-    
-    if (sourceLock.pBits && destLock.pBits)
-    {
-        D3DSURFACE_DESC desc;
-        source->GetDesc(&desc);
-
-        int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height;
-        int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width);
-        ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch);
-
-        for(int i = 0; i < rows; i++)
-        {
-            memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
-        }
-
-        source->UnlockRect();
-        dest->UnlockRect();
-    }
-    else UNREACHABLE();
-}
-
-bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
-{
-    if (mWidth != width ||
-        mHeight != height ||
-        mInternalFormat != internalformat ||
-        forceRelease)
-    {
-        mRenderer = Renderer9::makeRenderer9(renderer);
-
-        mWidth = width;
-        mHeight = height;
-        mInternalFormat = internalformat;
-        // compute the d3d format that will be used
-        mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat);
-        mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat);
-
-        if (mSurface)
-        {
-            mSurface->Release();
-            mSurface = NULL;
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
-void Image9::createSurface()
-{
-    if(mSurface)
-    {
-        return;
-    }
-
-    IDirect3DTexture9 *newTexture = NULL;
-    IDirect3DSurface9 *newSurface = NULL;
-    const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
-    const D3DFORMAT d3dFormat = getD3DFormat();
-    ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures
-
-    if (mWidth != 0 && mHeight != 0)
-    {
-        int levelToFetch = 0;
-        GLsizei requestWidth = mWidth;
-        GLsizei requestHeight = mHeight;
-        gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch);
-
-        IDirect3DDevice9 *device = mRenderer->getDevice();
-
-        HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat,
-                                                    poolToUse, &newTexture, NULL);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            ERR("Creating image surface failed.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-
-        newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
-        newTexture->Release();
-    }
-
-    mSurface = newSurface;
-    mDirty = false;
-    mD3DPool = poolToUse;
-}
-
-HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
-{
-    createSurface();
-
-    HRESULT result = D3DERR_INVALIDCALL;
-
-    if (mSurface)
-    {
-        result = mSurface->LockRect(lockedRect, rect, 0);
-        ASSERT(SUCCEEDED(result));
-
-        mDirty = true;
-    }
-
-    return result;
-}
-
-void Image9::unlock()
-{
-    if (mSurface)
-    {
-        HRESULT result = mSurface->UnlockRect();
-        ASSERT(SUCCEEDED(result));
-    }
-}
-
-bool Image9::isRenderableFormat() const
-{    
-    return TextureStorage9::IsTextureFormatRenderable(getD3DFormat());
-}
-
-D3DFORMAT Image9::getD3DFormat() const
-{
-    // this should only happen if the image hasn't been redefined first
-    // which would be a bug by the caller
-    ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
-
-    return mD3DFormat;
-}
-
-IDirect3DSurface9 *Image9::getSurface()
-{
-    createSurface();
-
-    return mSurface;
-}
-
-void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level)
-{
-    TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
-    setManagedSurface(storage9->getSurfaceLevel(level, false));
-}
-
-void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level)
-{
-    TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
-    setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false));
-}
-
-void Image9::setManagedSurface(IDirect3DSurface9 *surface)
-{
-    D3DSURFACE_DESC desc;
-    surface->GetDesc(&desc);
-    ASSERT(desc.Pool == D3DPOOL_MANAGED);
-
-    if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
-    {
-        if (mSurface)
-        {
-            copyLockableSurfaces(surface, mSurface);
-            mSurface->Release();
-        }
-
-        mSurface = surface;
-        mD3DPool = desc.Pool;
-    }
-}
-
-bool Image9::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
-    ASSERT(getSurface() != NULL);
-    TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
-    return updateSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height);
-}
-
-bool Image9::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
-    ASSERT(getSurface() != NULL);
-    TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
-    return updateSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height);
-}
-
-bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
-    if (!destSurface)
-        return false;
-
-    IDirect3DSurface9 *sourceSurface = getSurface();
-
-    if (sourceSurface && sourceSurface != destSurface)
-    {
-        RECT rect;
-        rect.left = xoffset;
-        rect.top = yoffset;
-        rect.right = xoffset + width;
-        rect.bottom = yoffset + height;
-
-        POINT point = {rect.left, rect.top};
-
-        IDirect3DDevice9 *device = mRenderer->getDevice();
-
-        if (mD3DPool == D3DPOOL_MANAGED)
-        {
-            D3DSURFACE_DESC desc;
-            sourceSurface->GetDesc(&desc);
-
-            IDirect3DSurface9 *surf = 0;
-            HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
-
-            if (SUCCEEDED(result))
-            {
-                copyLockableSurfaces(surf, sourceSurface);
-                result = device->UpdateSurface(surf, &rect, destSurface, &point);
-                ASSERT(SUCCEEDED(result));
-                surf->Release();
-            }
-        }
-        else
-        {
-            // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools 
-            HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
-            ASSERT(SUCCEEDED(result));
-        }
-    }
-
-    destSurface->Release();
-    return true;
-}
-
-// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
-// into the target pixel rectangle.
-void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                      GLint unpackAlignment, const void *input)
-{
-    RECT lockRect =
-    {
-        xoffset, yoffset,
-        xoffset + width, yoffset + height
-    };
-
-    D3DLOCKED_RECT locked;
-    HRESULT result = lock(&locked, &lockRect);
-    if (FAILED(result))
-    {
-        return;
-    }
-
-
-    GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
-
-    switch (mInternalFormat)
-    {
-      case GL_ALPHA8_EXT:
-        if (gl::supportsSSE2())
-        {
-            loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        }
-        else
-        {
-            loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        }
-        break;
-      case GL_LUMINANCE8_EXT:
-        loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8);
-        break;
-      case GL_ALPHA32F_EXT:
-        loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_LUMINANCE32F_EXT:
-        loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_ALPHA16F_EXT:
-        loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_LUMINANCE16F_EXT:
-        loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_LUMINANCE8_ALPHA8_EXT:
-        loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
-        break;
-      case GL_LUMINANCE_ALPHA32F_EXT:
-        loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_LUMINANCE_ALPHA16F_EXT:
-        loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_RGB8_OES:
-        loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_RGB565:
-        loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_RGBA8_OES:
-        if (gl::supportsSSE2())
-        {
-            loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        }
-        else
-        {
-            loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        }
-        break;
-      case GL_RGBA4:
-        loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_RGB5_A1:
-        loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_BGRA8_EXT:
-        loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
-      case GL_RGB32F_EXT:
-        loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_RGB16F_EXT:
-        loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_RGBA32F_EXT:
-        loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      case GL_RGBA16F_EXT:
-        loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
-        break;
-      default: UNREACHABLE(); 
-    }
-
-    unlock();
-}
-
-void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                const void *input)
-{
-    ASSERT(xoffset % 4 == 0);
-    ASSERT(yoffset % 4 == 0);
-
-    RECT lockRect = {
-        xoffset, yoffset,
-        xoffset + width, yoffset + height
-    };
-
-    D3DLOCKED_RECT locked;
-    HRESULT result = lock(&locked, &lockRect);
-    if (FAILED(result))
-    {
-        return;
-    }
-
-    GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
-    GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
-    int rows = inputSize / inputPitch;
-    for (int i = 0; i < rows; ++i)
-    {
-        memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
-    }
-
-    unlock();
-}
-
-// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
-void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
-{
-    RenderTarget9 *renderTarget = NULL;
-    IDirect3DSurface9 *surface = NULL;
-    gl::Renderbuffer *colorbuffer = source->getColorbuffer(0);
-
-    if (colorbuffer)
-    {
-        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
-    }
-    
-    if (renderTarget)
-    {
-        surface = renderTarget->getSurface();
-    }
-
-    if (!surface)
-    {
-        ERR("Failed to retrieve the render target.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    IDirect3DSurface9 *renderTargetData = NULL;
-    D3DSURFACE_DESC description;
-    surface->GetDesc(&description);
-    
-    HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
-
-    if (FAILED(result))
-    {
-        ERR("Could not create matching destination surface.");
-        surface->Release();
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    result = device->GetRenderTargetData(surface, renderTargetData);
-
-    if (FAILED(result))
-    {
-        ERR("GetRenderTargetData unexpectedly failed.");
-        renderTargetData->Release();
-        surface->Release();
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    RECT sourceRect = {x, y, x + width, y + height};
-    RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
-
-    D3DLOCKED_RECT sourceLock = {0};
-    result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
-
-    if (FAILED(result))
-    {
-        ERR("Failed to lock the source surface (rectangle might be invalid).");
-        renderTargetData->Release();
-        surface->Release();
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    D3DLOCKED_RECT destLock = {0};
-    result = lock(&destLock, &destRect);
-    
-    if (FAILED(result))
-    {
-        ERR("Failed to lock the destination surface (rectangle might be invalid).");
-        renderTargetData->UnlockRect();
-        renderTargetData->Release();
-        surface->Release();
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    if (destLock.pBits && sourceLock.pBits)
-    {
-        unsigned char *source = (unsigned char*)sourceLock.pBits;
-        unsigned char *dest = (unsigned char*)destLock.pBits;
-
-        switch (description.Format)
-        {
-          case D3DFMT_X8R8G8B8:
-          case D3DFMT_A8R8G8B8:
-            switch(getD3DFormat())
-            {
-              case D3DFMT_X8R8G8B8:
-              case D3DFMT_A8R8G8B8:
-                for(int y = 0; y < height; y++)
-                {
-                    memcpy(dest, source, 4 * width);
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              case D3DFMT_L8:
-                for(int y = 0; y < height; y++)
-                {
-                    for(int x = 0; x < width; x++)
-                    {
-                        dest[x] = source[x * 4 + 2];
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              case D3DFMT_A8L8:
-                for(int y = 0; y < height; y++)
-                {
-                    for(int x = 0; x < width; x++)
-                    {
-                        dest[x * 2 + 0] = source[x * 4 + 2];
-                        dest[x * 2 + 1] = source[x * 4 + 3];
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              default:
-                UNREACHABLE();
-            }
-            break;
-          case D3DFMT_R5G6B5:
-            switch(getD3DFormat())
-            {
-              case D3DFMT_X8R8G8B8:
-                for(int y = 0; y < height; y++)
-                {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned short rgb = ((unsigned short*)source)[x];
-                        unsigned char red = (rgb & 0xF800) >> 8;
-                        unsigned char green = (rgb & 0x07E0) >> 3;
-                        unsigned char blue = (rgb & 0x001F) << 3;
-                        dest[x + 0] = blue | (blue >> 5);
-                        dest[x + 1] = green | (green >> 6);
-                        dest[x + 2] = red | (red >> 5);
-                        dest[x + 3] = 0xFF;
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              case D3DFMT_L8:
-                for(int y = 0; y < height; y++)
-                {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned char red = source[x * 2 + 1] & 0xF8;
-                        dest[x] = red | (red >> 5);
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              default:
-                UNREACHABLE();
-            }
-            break;
-          case D3DFMT_A1R5G5B5:
-            switch(getD3DFormat())
-            {
-              case D3DFMT_X8R8G8B8:
-                for(int y = 0; y < height; y++)
-                {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned short argb = ((unsigned short*)source)[x];
-                        unsigned char red = (argb & 0x7C00) >> 7;
-                        unsigned char green = (argb & 0x03E0) >> 2;
-                        unsigned char blue = (argb & 0x001F) << 3;
-                        dest[x + 0] = blue | (blue >> 5);
-                        dest[x + 1] = green | (green >> 5);
-                        dest[x + 2] = red | (red >> 5);
-                        dest[x + 3] = 0xFF;
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              case D3DFMT_A8R8G8B8:
-                for(int y = 0; y < height; y++)
-                {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned short argb = ((unsigned short*)source)[x];
-                        unsigned char red = (argb & 0x7C00) >> 7;
-                        unsigned char green = (argb & 0x03E0) >> 2;
-                        unsigned char blue = (argb & 0x001F) << 3;
-                        unsigned char alpha = (signed short)argb >> 15;
-                        dest[x + 0] = blue | (blue >> 5);
-                        dest[x + 1] = green | (green >> 5);
-                        dest[x + 2] = red | (red >> 5);
-                        dest[x + 3] = alpha;
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              case D3DFMT_L8:
-                for(int y = 0; y < height; y++)
-                {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned char red = source[x * 2 + 1] & 0x7C;
-                        dest[x] = (red << 1) | (red >> 4);
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              case D3DFMT_A8L8:
-                for(int y = 0; y < height; y++)
-                {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned char red = source[x * 2 + 1] & 0x7C;
-                        dest[x * 2 + 0] = (red << 1) | (red >> 4);
-                        dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              default:
-                UNREACHABLE();
-            }
-            break;
-          default:
-            UNREACHABLE();
-        }
-    }
-
-    unlock();
-    renderTargetData->UnlockRect();
-
-    renderTargetData->Release();
-    surface->Release();
-
-    mDirty = true;
-}
-
-}
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Image9.h b/src/third_party/angle/src/libGLESv2/renderer/Image9.h
deleted file mode 100644
index 2fbbca3..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Image9.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image9.h: Defines the rx::Image9 class, which acts as the interface to
-// the actual underlying surfaces of a Texture.
-
-#ifndef LIBGLESV2_RENDERER_IMAGE9_H_
-#define LIBGLESV2_RENDERER_IMAGE9_H_
-
-#include "libGLESv2/renderer/Image.h"
-#include "common/debug.h"
-
-namespace gl
-{
-class Framebuffer;
-}
-
-namespace rx
-{
-class Renderer;
-class Renderer9;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
-
-class Image9 : public Image
-{
-  public:
-    Image9();
-    ~Image9();
-
-    static Image9 *makeImage9(Image *img);
-
-    static void generateMipmap(Image9 *dest, Image9 *source);
-    static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
-    static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
-
-    virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease);
-
-    virtual bool isRenderableFormat() const;
-    D3DFORMAT getD3DFormat() const;
-
-    virtual bool isDirty() const {return mSurface && mDirty;}
-    IDirect3DSurface9 *getSurface();
-
-    virtual void setManagedSurface(TextureStorageInterface2D *storage, int level);
-    virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level);
-    virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
-    virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                  GLint unpackAlignment, const void *input);
-    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                    const void *input);
-
-    virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Image9);
-
-    void createSurface();
-    void setManagedSurface(IDirect3DSurface9 *surface);
-    bool updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
-    HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect);
-    void unlock();
-    
-    Renderer9 *mRenderer;
-
-    D3DPOOL mD3DPool;   // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable.
-    D3DFORMAT mD3DFormat;
-
-    IDirect3DSurface9 *mSurface;
-};
-}
-
-#endif   // LIBGLESV2_RENDERER_IMAGE9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/ImageSSE2.cpp b/src/third_party/angle/src/libGLESv2/renderer/ImageSSE2.cpp
deleted file mode 100644
index b2a90ca..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/ImageSSE2.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ImageSSE2.cpp: Implements SSE2-based functions of rx::Image class. It's
-// in a separated file for GCC, which can enable SSE usage only per-file,
-// not for code blocks that use SSE2 explicitly.
-
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/renderer/Image.h"
-
-namespace rx
-{
-
-void Image::loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned int *source = NULL;
-    unsigned int *dest = NULL;
-    __m128i brMask = _mm_set1_epi32(0x00ff00ff);
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        int x = 0;
-
-        // Make output writes aligned
-        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
-        {
-            unsigned int rgba = source[x];
-            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
-        }
-
-        for (; x + 3 < width; x += 4)
-        {
-            __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
-            // Mask out g and a, which don't change
-            __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
-            // Mask out b and r
-            __m128i brComponents = _mm_and_si128(sourceData, brMask);
-            // Swap b and r
-            __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
-            __m128i result = _mm_or_si128(gaComponents, brSwapped);
-            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
-        }
-
-        // Perform leftover writes
-        for (; x < width; x++)
-        {
-            unsigned int rgba = source[x];
-            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
-        }
-    }
-}
-
-void Image::loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned char *source = NULL;
-    unsigned int *dest = NULL;
-    __m128i zeroWide = _mm_setzero_si128();
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-
-        int x;
-        // Make output writes aligned
-        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
-        {
-            dest[x] = static_cast<unsigned int>(source[x]) << 24;
-        }
-
-        for (; x + 7 < width; x += 8)
-        {
-            __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
-            // Interleave each byte to 16bit, make the lower byte to zero
-            sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
-            // Interleave each 16bit to 32bit, make the lower 16bit to zero
-            __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
-            __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
-
-            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
-            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
-        }
-
-        // Handle the remainder
-        for (; x < width; x++)
-        {
-            dest[x] = static_cast<unsigned int>(source[x]) << 24;
-        }
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer.cpp b/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer.cpp
deleted file mode 100644
index 3d5d7a7..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface
-// class with derivations, classes that perform graphics API agnostic index buffer operations.
-
-#include "libGLESv2/renderer/IndexBuffer.h"
-#include "libGLESv2/renderer/Renderer.h"
-
-namespace rx
-{
-
-unsigned int IndexBuffer::mNextSerial = 1;
-
-IndexBuffer::IndexBuffer()
-{
-    updateSerial();
-}
-
-IndexBuffer::~IndexBuffer()
-{
-}
-
-unsigned int IndexBuffer::getSerial() const
-{
-    return mSerial;
-}
-
-void IndexBuffer::updateSerial()
-{
-    mSerial = mNextSerial++;
-}
-
-
-IndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer)
-{
-    mIndexBuffer = renderer->createIndexBuffer();
-
-    mDynamic = dynamic;
-    mWritePosition = 0;
-}
-
-IndexBufferInterface::~IndexBufferInterface()
-{
-    if (mIndexBuffer)
-    {
-        delete mIndexBuffer;
-    }
-}
-
-GLenum IndexBufferInterface::getIndexType() const
-{
-    return mIndexBuffer->getIndexType();
-}
-
-unsigned int IndexBufferInterface::getBufferSize() const
-{
-    return mIndexBuffer->getBufferSize();
-}
-
-unsigned int IndexBufferInterface::getSerial() const
-{
-    return mIndexBuffer->getSerial();
-}
-
-int IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory)
-{
-    if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
-    {
-        *outMappedMemory = NULL;
-        return -1;
-    }
-
-    int oldWritePos = static_cast<int>(mWritePosition);
-    mWritePosition += size;
-
-    return oldWritePos;
-}
-
-bool IndexBufferInterface::unmapBuffer()
-{
-    return mIndexBuffer->unmapBuffer();
-}
-
-IndexBuffer * IndexBufferInterface::getIndexBuffer() const
-{
-    return mIndexBuffer;
-}
-
-unsigned int IndexBufferInterface::getWritePosition() const
-{
-    return mWritePosition;
-}
-
-void IndexBufferInterface::setWritePosition(unsigned int writePosition)
-{
-    mWritePosition = writePosition;
-}
-
-bool IndexBufferInterface::discard()
-{
-    return mIndexBuffer->discard();
-}
-
-bool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
-{
-    if (mIndexBuffer->getBufferSize() == 0)
-    {
-        return mIndexBuffer->initialize(bufferSize, indexType, mDynamic);
-    }
-    else
-    {
-        return mIndexBuffer->setSize(bufferSize, indexType);
-    }
-}
-
-StreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true)
-{
-}
-
-StreamingIndexBufferInterface::~StreamingIndexBufferInterface()
-{
-}
-
-bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
-{
-    bool result = true;
-    unsigned int curBufferSize = getBufferSize();
-    unsigned int writePos = getWritePosition();
-    if (size > curBufferSize)
-    {
-        result = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
-        setWritePosition(0);
-    }
-    else if (writePos + size > curBufferSize || writePos + size < writePos)
-    {
-        if (!discard())
-        {
-            return false;
-        }
-        setWritePosition(0);
-    }
-
-    return result;
-}
-
-
-StaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false)
-{
-}
-
-StaticIndexBufferInterface::~StaticIndexBufferInterface()
-{
-}
-
-bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
-{
-    unsigned int curSize = getBufferSize();
-    if (curSize == 0)
-    {
-        return setBufferSize(size, indexType);
-    }
-    else if (curSize >= size && indexType == getIndexType())
-    {
-        return true;
-    }
-    else
-    {
-        ERR("Static index buffers can't be resized");
-        UNREACHABLE();
-        return false;
-    }
-}
-
-unsigned int StaticIndexBufferInterface::lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex)
-{
-    IndexRange range = {offset, count};
-
-    std::map<IndexRange, IndexResult>::iterator res = mCache.find(range);
-
-    if (res == mCache.end())
-    {
-        return -1;
-    }
-
-    *minIndex = res->second.minIndex;
-    *maxIndex = res->second.maxIndex;
-    return res->second.streamOffset;
-}
-
-void StaticIndexBufferInterface::addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset)
-{
-    IndexRange indexRange = {offset, count};
-    IndexResult indexResult = {minIndex, maxIndex, streamOffset};
-    mCache[indexRange] = indexResult;
-}
-
-}
-
diff --git a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer.h b/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer.h
deleted file mode 100644
index 1afbd62..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// IndexBuffer.h: Defines the abstract IndexBuffer class and IndexBufferInterface
-// class with derivations, classes that perform graphics API agnostic index buffer operations.
-
-#ifndef LIBGLESV2_RENDERER_INDEXBUFFER_H_
-#define LIBGLESV2_RENDERER_INDEXBUFFER_H_
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-class Renderer;
-
-class IndexBuffer
-{
-  public:
-    IndexBuffer();
-    virtual ~IndexBuffer();
-
-    virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0;
-
-    virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0;
-    virtual bool unmapBuffer() = 0;
-
-    virtual bool discard() = 0;
-
-    virtual GLenum getIndexType() const = 0;
-    virtual unsigned int getBufferSize() const = 0;
-    virtual bool setSize(unsigned int bufferSize, GLenum indexType) = 0;
-
-    unsigned int getSerial() const;
-
-  protected:
-    void updateSerial();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(IndexBuffer);
-
-    unsigned int mSerial;
-    static unsigned int mNextSerial;
-};
-
-class IndexBufferInterface
-{
-  public:
-    IndexBufferInterface(Renderer *renderer, bool dynamic);
-    virtual ~IndexBufferInterface();
-
-    virtual bool reserveBufferSpace(unsigned int size, GLenum indexType) = 0;
-
-    GLenum getIndexType() const;
-    unsigned int getBufferSize() const;
-
-    unsigned int getSerial() const;
-
-    int mapBuffer(unsigned int size, void** outMappedMemory);
-    bool unmapBuffer();
-
-    IndexBuffer *getIndexBuffer() const;
-
-  protected:
-    unsigned int getWritePosition() const;
-    void setWritePosition(unsigned int writePosition);
-
-    bool discard();
-
-    bool setBufferSize(unsigned int bufferSize, GLenum indexType);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface);
-
-    rx::Renderer *const mRenderer;
-
-    IndexBuffer* mIndexBuffer;
-
-    unsigned int mWritePosition;
-    bool mDynamic;
-};
-
-class StreamingIndexBufferInterface : public IndexBufferInterface
-{
-  public:
-    StreamingIndexBufferInterface(Renderer *renderer);
-    ~StreamingIndexBufferInterface();
-
-    virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
-};
-
-class StaticIndexBufferInterface : public IndexBufferInterface
-{
-  public:
-    explicit StaticIndexBufferInterface(Renderer *renderer);
-    ~StaticIndexBufferInterface();
-
-    virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
-
-    unsigned int lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex);   // Returns the offset into the index buffer, or -1 if not found
-    void addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset);
-
-  private:
-    struct IndexRange
-    {
-        intptr_t offset;
-        GLsizei count;
-
-        bool operator<(const IndexRange& rhs) const
-        {
-            if (offset != rhs.offset)
-            {
-                return offset < rhs.offset;
-            }
-            if (count != rhs.count)
-            {
-                return count < rhs.count;
-            }
-            return false;
-        }
-    };
-
-    struct IndexResult
-    {
-        unsigned int minIndex;
-        unsigned int maxIndex;
-        unsigned int streamOffset;
-    };
-
-    std::map<IndexRange, IndexResult> mCache;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer11.cpp b/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer11.cpp
deleted file mode 100644
index 1a63358..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer11.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation.
-
-#include "libGLESv2/renderer/IndexBuffer11.h"
-#include "libGLESv2/renderer/Renderer11.h"
-#include "libGLESv2/renderer/renderer11_utils.h"
-
-namespace rx
-{
-
-IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
-{
-    mBuffer = NULL;
-    mBufferSize = 0;
-    mDynamicUsage = false;
-}
-
-IndexBuffer11::~IndexBuffer11()
-{
-    if (mBuffer)
-    {
-        mBuffer->Release();
-        mBuffer = NULL;
-    }
-}
-
-bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
-{
-    if (mBuffer)
-    {
-        mBuffer->Release();
-        mBuffer = NULL;
-    }
-
-    updateSerial();
-
-    if (bufferSize > 0)
-    {
-        ID3D11Device* dxDevice = mRenderer->getDevice();
-
-        D3D11_BUFFER_DESC bufferDesc;
-        bufferDesc.ByteWidth = bufferSize;
-        bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
-        bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
-        bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-        bufferDesc.MiscFlags = 0;
-        bufferDesc.StructureByteStride = 0;
-
-        HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
-        if (FAILED(result))
-        {
-            return false;
-        }
-        d3d11::ResourceTracker::Track(mBuffer);
-    }
-
-    mBufferSize = bufferSize;
-    mIndexType = indexType;
-    mDynamicUsage = dynamic;
-
-    return true;
-}
-
-IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer));
-    return static_cast<IndexBuffer11*>(indexBuffer);
-}
-
-bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
-{
-    if (mBuffer)
-    {
-        if (offset + size > mBufferSize)
-        {
-            ERR("Index buffer map range is not inside the buffer.");
-            return false;
-        }
-
-        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
-        D3D11_MAPPED_SUBRESOURCE mappedResource;
-        HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
-        if (FAILED(result))
-        {
-            ERR("Index buffer map failed with error 0x%08x", result);
-            return false;
-        }
-
-        *outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset;
-        return true;
-    }
-    else
-    {
-        ERR("Index buffer not initialized.");
-        return false;
-    }
-}
-
-bool IndexBuffer11::unmapBuffer()
-{
-    if (mBuffer)
-    {
-        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-        dxContext->Unmap(mBuffer, 0);
-        return true;
-    }
-    else
-    {
-        ERR("Index buffer not initialized.");
-        return false;
-    }
-}
-
-GLenum IndexBuffer11::getIndexType() const
-{
-    return mIndexType;
-}
-
-unsigned int IndexBuffer11::getBufferSize() const
-{
-    return mBufferSize;
-}
-
-bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType)
-{
-    if (bufferSize > mBufferSize || indexType != mIndexType)
-    {
-        return initialize(bufferSize, indexType, mDynamicUsage);
-    }
-    else
-    {
-        return true;
-    }
-}
-
-bool IndexBuffer11::discard()
-{
-    if (mBuffer)
-    {
-        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
-        D3D11_MAPPED_SUBRESOURCE mappedResource;
-        HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-        if (FAILED(result))
-        {
-            ERR("Index buffer map failed with error 0x%08x", result);
-            return false;
-        }
-
-        dxContext->Unmap(mBuffer, 0);
-
-        return true;
-    }
-    else
-    {
-        ERR("Index buffer not initialized.");
-        return false;
-    }
-}
-
-DXGI_FORMAT IndexBuffer11::getIndexFormat() const
-{
-    switch (mIndexType)
-    {
-      case GL_UNSIGNED_BYTE:    return DXGI_FORMAT_R16_UINT;
-      case GL_UNSIGNED_SHORT:   return DXGI_FORMAT_R16_UINT;
-      case GL_UNSIGNED_INT:     return DXGI_FORMAT_R32_UINT;
-      default: UNREACHABLE();   return DXGI_FORMAT_UNKNOWN;
-    }
-}
-
-ID3D11Buffer *IndexBuffer11::getBuffer() const
-{
-    return mBuffer;
-}
-
-}
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer11.h b/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer11.h
deleted file mode 100644
index 39a6194..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer11.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation.
-
-#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_
-#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_
-
-#include "libGLESv2/renderer/IndexBuffer.h"
-
-namespace rx
-{
-class Renderer11;
-
-class IndexBuffer11 : public IndexBuffer
-{
-  public:
-    explicit IndexBuffer11(Renderer11 *const renderer);
-    virtual ~IndexBuffer11();
-
-    virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
-
-    static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer);
-
-    virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
-    virtual bool unmapBuffer();
-
-    virtual GLenum getIndexType() const;
-    virtual unsigned int getBufferSize() const;
-    virtual bool setSize(unsigned int bufferSize, GLenum indexType);
-
-    virtual bool discard();
-
-    DXGI_FORMAT getIndexFormat() const;
-    ID3D11Buffer *getBuffer() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(IndexBuffer11);
-
-    rx::Renderer11 *const mRenderer;
-
-    ID3D11Buffer *mBuffer;
-    unsigned int mBufferSize;
-    GLenum mIndexType;
-    bool mDynamicUsage;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_INDEXBUFFER11_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer9.cpp b/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer9.cpp
deleted file mode 100644
index c6d83c5..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer9.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.
-
-#include "libGLESv2/renderer/IndexBuffer9.h"
-#include "libGLESv2/renderer/Renderer9.h"
-
-namespace rx
-{
-
-IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
-{
-    mIndexBuffer = NULL;
-    mBufferSize = 0;
-    mIndexType = 0;
-    mDynamic = false;
-}
-
-IndexBuffer9::~IndexBuffer9()
-{
-    if (mIndexBuffer)
-    {
-        mIndexBuffer->Release();
-        mIndexBuffer = NULL;
-    }
-}
-
-bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
-{
-    if (mIndexBuffer)
-    {
-        mIndexBuffer->Release();
-        mIndexBuffer = NULL;
-    }
-
-    updateSerial();
-
-    if (bufferSize > 0)
-    {
-        D3DFORMAT format;
-        if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE)
-        {
-            format = D3DFMT_INDEX16;
-        }
-        else if (indexType == GL_UNSIGNED_INT)
-        {
-            if (mRenderer->get32BitIndexSupport())
-            {
-                format = D3DFMT_INDEX32;
-            }
-            else
-            {
-                ERR("Attempted to create a 32-bit index buffer but renderer does not support 32-bit indices.");
-                return false;
-            }
-        }
-        else
-        {
-            ERR("Invalid index type %u.", indexType);
-            return false;
-        }
-
-        DWORD usageFlags = D3DUSAGE_WRITEONLY;
-        if (dynamic)
-        {
-            usageFlags |= D3DUSAGE_DYNAMIC;
-        }
-
-        HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
-        if (FAILED(result))
-        {
-            ERR("Failed to create an index buffer of size %u, result: 0x%08x.", mBufferSize, result);
-            return false;
-        }
-    }
-
-    mBufferSize = bufferSize;
-    mIndexType = indexType;
-    mDynamic = dynamic;
-
-    return true;
-}
-
-IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer));
-    return static_cast<IndexBuffer9*>(indexBuffer);
-}
-
-bool IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
-{
-    if (mIndexBuffer)
-    {
-        DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
-
-        void *mapPtr = NULL;
-        HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
-        if (FAILED(result))
-        {
-            ERR("Index buffer lock failed with error 0x%08x", result);
-            return false;
-        }
-
-        *outMappedMemory = mapPtr;
-        return true;
-    }
-    else
-    {
-        ERR("Index buffer not initialized.");
-        return false;
-    }
-}
-
-bool IndexBuffer9::unmapBuffer()
-{
-    if (mIndexBuffer)
-    {
-        HRESULT result = mIndexBuffer->Unlock();
-        if (FAILED(result))
-        {
-            ERR("Index buffer unlock failed with error 0x%08x", result);
-            return false;
-        }
-
-        return true;
-    }
-    else
-    {
-        ERR("Index buffer not initialized.");
-        return false;
-    }
-}
-
-GLenum IndexBuffer9::getIndexType() const
-{
-    return mIndexType;
-}
-
-unsigned int IndexBuffer9::getBufferSize() const
-{
-    return mBufferSize;
-}
-
-bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType)
-{
-    if (bufferSize > mBufferSize || indexType != mIndexType)
-    {
-        return initialize(bufferSize, indexType, mDynamic);
-    }
-    else
-    {
-        return true;
-    }
-}
-
-bool IndexBuffer9::discard()
-{
-    if (mIndexBuffer)
-    {
-        void *dummy;
-        HRESULT result;
-
-        result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
-        if (FAILED(result))
-        {
-            ERR("Discard lock failed with error 0x%08x", result);
-            return false;
-        }
-
-        result = mIndexBuffer->Unlock();
-        if (FAILED(result))
-        {
-            ERR("Discard unlock failed with error 0x%08x", result);
-            return false;
-        }
-
-        return true;
-    }
-    else
-    {
-        ERR("Index buffer not initialized.");
-        return false;
-    }
-}
-
-D3DFORMAT IndexBuffer9::getIndexFormat() const
-{
-    switch (mIndexType)
-    {
-      case GL_UNSIGNED_BYTE:    return D3DFMT_INDEX16;
-      case GL_UNSIGNED_SHORT:   return D3DFMT_INDEX16;
-      case GL_UNSIGNED_INT:     return D3DFMT_INDEX32;
-      default: UNREACHABLE();   return D3DFMT_UNKNOWN;
-    }
-}
-
-IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const
-{
-    return mIndexBuffer;
-}
-
-}
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer9.h b/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer9.h
deleted file mode 100644
index 6801867..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/IndexBuffer9.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Indexffer9.h: Defines the D3D9 IndexBuffer implementation.
-
-#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_
-#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_
-
-#include "libGLESv2/renderer/IndexBuffer.h"
-
-namespace rx
-{
-class Renderer9;
-
-class IndexBuffer9 : public IndexBuffer
-{
-  public:
-    explicit IndexBuffer9(Renderer9 *const renderer);
-    virtual ~IndexBuffer9();
-
-    virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
-
-    static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer);
-
-    virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
-    virtual bool unmapBuffer();
-
-    virtual GLenum getIndexType() const;
-    virtual unsigned int getBufferSize() const;
-    virtual bool setSize(unsigned int bufferSize, GLenum indexType);
-
-    virtual bool discard();
-
-    D3DFORMAT getIndexFormat() const;
-    IDirect3DIndexBuffer9 *getBuffer() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(IndexBuffer9);
-
-    rx::Renderer9 *const mRenderer;
-
-    IDirect3DIndexBuffer9 *mIndexBuffer;
-    unsigned int mBufferSize;
-    GLenum mIndexType;
-    bool mDynamic;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_INDEXBUFFER9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/IndexDataManager.cpp b/src/third_party/angle/src/libGLESv2/renderer/IndexDataManager.cpp
deleted file mode 100644
index 84b79b4..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/IndexDataManager.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// IndexDataManager.cpp: Defines the IndexDataManager, a class that
-// runs the Buffer translation process for index buffers.
-
-#include "libGLESv2/renderer/IndexDataManager.h"
-#include "libGLESv2/renderer/BufferStorage.h"
-
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/IndexBuffer.h"
-
-namespace rx
-{
-
-IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer)
-{
-    mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer);
-    if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
-    {
-        delete mStreamingBufferShort;
-        mStreamingBufferShort = NULL;
-    }
-
-    mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer);
-    if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
-    {
-        delete mStreamingBufferInt;
-        mStreamingBufferInt = NULL;
-    }
-
-    if (!mStreamingBufferShort)
-    {
-        // Make sure both buffers are deleted.
-        delete mStreamingBufferInt;
-        mStreamingBufferInt = NULL;
-
-        ERR("Failed to allocate the streaming index buffer(s).");
-    }
-
-    mCountingBuffer = NULL;
-}
-
-IndexDataManager::~IndexDataManager()
-{
-    delete mStreamingBufferShort;
-    delete mStreamingBufferInt;
-    delete mCountingBuffer;
-}
-
-static unsigned int indexTypeSize(GLenum type)
-{
-    switch (type)
-    {
-      case GL_UNSIGNED_INT:   return sizeof(GLuint);
-      case GL_UNSIGNED_SHORT: return sizeof(GLushort);
-      case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);
-      default: UNREACHABLE(); return sizeof(GLushort);
-    }
-}
-
-static void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
-{
-    if (type == GL_UNSIGNED_BYTE)
-    {
-        const GLubyte *in = static_cast<const GLubyte*>(input);
-        GLushort *out = static_cast<GLushort*>(output);
-
-        for (GLsizei i = 0; i < count; i++)
-        {
-            out[i] = in[i];
-        }
-    }
-    else if (type == GL_UNSIGNED_INT)
-    {
-        memcpy(output, input, count * sizeof(GLuint));
-    }
-    else if (type == GL_UNSIGNED_SHORT)
-    {
-        memcpy(output, input, count * sizeof(GLushort));
-    }
-    else UNREACHABLE();
-}
-
-template <class IndexType>
-static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
-{
-    *minIndex = indices[0];
-    *maxIndex = indices[0];
-
-    for (GLsizei i = 0; i < count; i++)
-    {
-        if (*minIndex > indices[i]) *minIndex = indices[i];
-        if (*maxIndex < indices[i]) *maxIndex = indices[i];
-    }
-}
-
-static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
-{
-    if (type == GL_UNSIGNED_BYTE)
-    {
-        computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);
-    }
-    else if (type == GL_UNSIGNED_INT)
-    {
-        computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
-    }
-    else if (type == GL_UNSIGNED_SHORT)
-    {
-        computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
-    }
-    else UNREACHABLE();
-}
-
-GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
-{
-    if (!mStreamingBufferShort)
-    {
-        return GL_OUT_OF_MEMORY;
-    }
-
-    GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
-    intptr_t offset = reinterpret_cast<intptr_t>(indices);
-    bool alignedOffset = false;
-
-    BufferStorage *storage = NULL;
-
-    if (buffer != NULL)
-    {
-        storage = buffer->getStorage();
-
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:  alignedOffset = (offset % sizeof(GLubyte) == 0);  break;
-          case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
-          case GL_UNSIGNED_INT:   alignedOffset = (offset % sizeof(GLuint) == 0);   break;
-          default: UNREACHABLE(); alignedOffset = false;
-        }
-
-        if (indexTypeSize(type) * count + offset > storage->getSize())
-        {
-            return GL_INVALID_OPERATION;
-        }
-
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
-    }
-
-    StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
-
-    StaticIndexBufferInterface *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
-    IndexBufferInterface *indexBuffer = streamingBuffer;
-    bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() &&
-                         destinationIndexType == type;
-    UINT streamOffset = 0;
-
-    if (directStorage)
-    {
-        indexBuffer = streamingBuffer;
-        streamOffset = offset;
-        storage->markBufferUsage();
-        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
-    }
-    else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset)
-    {
-        indexBuffer = staticBuffer;
-        streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
-
-        if (streamOffset == -1)
-        {
-            streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
-            computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
-            staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
-        }
-    }
-    else
-    {
-        int convertCount = count;
-
-        if (staticBuffer)
-        {
-            if (staticBuffer->getBufferSize() == 0 && alignedOffset)
-            {
-                indexBuffer = staticBuffer;
-                convertCount = storage->getSize() / indexTypeSize(type);
-            }
-            else
-            {
-                buffer->invalidateStaticData();
-                staticBuffer = NULL;
-            }
-        }
-
-        if (!indexBuffer)
-        {
-            ERR("No valid index buffer.");
-            return GL_INVALID_OPERATION;
-        }
-
-        unsigned int bufferSizeRequired = convertCount * indexTypeSize(destinationIndexType);
-        indexBuffer->reserveBufferSpace(bufferSizeRequired, type);
-
-        void* output = NULL;
-        streamOffset = indexBuffer->mapBuffer(bufferSizeRequired, &output);
-        if (streamOffset == -1 || output == NULL)
-        {
-            ERR("Failed to map index buffer.");
-            return GL_OUT_OF_MEMORY;
-        }
-
-        convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output);
-
-        if (!indexBuffer->unmapBuffer())
-        {
-            ERR("Failed to unmap index buffer.");
-            return GL_OUT_OF_MEMORY;
-        }
-
-        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
-
-        if (staticBuffer)
-        {
-            streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
-            staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
-        }
-    }
-
-    translated->storage = directStorage ? storage : NULL;
-    translated->indexBuffer = indexBuffer->getIndexBuffer();
-    translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
-    translated->startIndex = streamOffset / indexTypeSize(destinationIndexType);
-    translated->startOffset = streamOffset;
-
-    if (buffer)
-    {
-        buffer->promoteStaticUsage(count * indexTypeSize(type));
-    }
-
-    return GL_NO_ERROR;
-}
-
-StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
-{
-    if (count <= 65536)   // 16-bit indices
-    {
-        const unsigned int spaceNeeded = count * sizeof(unsigned short);
-
-        if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
-        {
-            delete mCountingBuffer;
-            mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
-            mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
-
-            void* mappedMemory = NULL;
-            if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
-            {
-                ERR("Failed to map counting buffer.");
-                return NULL;
-            }
-
-            unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
-            for(int i = 0; i < count; i++)
-            {
-                data[i] = i;
-            }
-
-            if (!mCountingBuffer->unmapBuffer())
-            {
-                ERR("Failed to unmap counting buffer.");
-                return NULL;
-            }
-        }
-    }
-    else if (mStreamingBufferInt)   // 32-bit indices supported
-    {
-        const unsigned int spaceNeeded = count * sizeof(unsigned int);
-
-        if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
-        {
-            delete mCountingBuffer;
-            mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
-            mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
-
-            void* mappedMemory = NULL;
-            if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
-            {
-                ERR("Failed to map counting buffer.");
-                return NULL;
-            }
-
-            unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
-            for(int i = 0; i < count; i++)
-            {
-                data[i] = i;
-            }
-
-            if (!mCountingBuffer->unmapBuffer())
-            {
-                ERR("Failed to unmap counting buffer.");
-                return NULL;
-            }
-        }
-    }
-    else
-    {
-        return NULL;
-    }
-
-    return mCountingBuffer;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/IndexDataManager.h b/src/third_party/angle/src/libGLESv2/renderer/IndexDataManager.h
deleted file mode 100644
index 0e77c81..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/IndexDataManager.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// IndexDataManager.h: Defines the IndexDataManager, a class that
-// runs the Buffer translation process for index buffers.
-
-#ifndef LIBGLESV2_INDEXDATAMANAGER_H_
-#define LIBGLESV2_INDEXDATAMANAGER_H_
-
-#include "common/angleutils.h"
-
-namespace
-{
-    enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
-}
-
-namespace gl
-{
-class Buffer;
-}
-
-namespace rx
-{
-class StaticIndexBufferInterface;
-class StreamingIndexBufferInterface;
-class IndexBuffer;
-class BufferStorage;
-class Renderer;
-
-struct TranslatedIndexData
-{
-    unsigned int minIndex;
-    unsigned int maxIndex;
-    unsigned int startIndex;
-    unsigned int startOffset;   // In bytes
-
-    IndexBuffer *indexBuffer;
-    BufferStorage *storage;
-    unsigned int serial;
-};
-
-class IndexDataManager
-{
-  public:
-    explicit IndexDataManager(Renderer *renderer);
-    virtual ~IndexDataManager();
-
-    GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
-    StaticIndexBufferInterface *getCountingIndices(GLsizei count);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(IndexDataManager);
-
-    Renderer *const mRenderer;
-
-    StreamingIndexBufferInterface *mStreamingBufferShort;
-    StreamingIndexBufferInterface *mStreamingBufferInt;
-    StaticIndexBufferInterface *mCountingBuffer;
-};
-
-}
-
-#endif   // LIBGLESV2_INDEXDATAMANAGER_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/InputLayoutCache.cpp b/src/third_party/angle/src/libGLESv2/renderer/InputLayoutCache.cpp
deleted file mode 100644
index 0402bb3..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/InputLayoutCache.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches
-// D3D11 input layouts.
-
-#include "libGLESv2/renderer/InputLayoutCache.h"
-#include "libGLESv2/renderer/VertexBuffer11.h"
-#include "libGLESv2/renderer/BufferStorage11.h"
-#include "libGLESv2/renderer/ShaderExecutable11.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/VertexDataManager.h"
-
-#include "third_party/murmurhash/MurmurHash3.h"
-
-namespace rx
-{
-
-const unsigned int InputLayoutCache::kMaxInputLayouts = 1024;
-
-InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts)
-{
-    mCounter = 0;
-    mDevice = NULL;
-    mDeviceContext = NULL;
-}
-
-InputLayoutCache::~InputLayoutCache()
-{
-    clear();
-}
-
-void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context)
-{
-    clear();
-    mDevice = device;
-    mDeviceContext = context;
-}
-
-void InputLayoutCache::clear()
-{
-    for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
-    {
-        i->second.inputLayout->Release();
-    }
-    mInputLayoutMap.clear();
-}
-
-GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
-                                            gl::ProgramBinary *programBinary)
-{
-    int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS];
-    programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices);
-
-    if (!mDevice || !mDeviceContext)
-    {
-        ERR("InputLayoutCache is not initialized.");
-        return GL_INVALID_OPERATION;
-    }
-
-    InputLayoutKey ilKey = { 0 };
-
-    ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL };
-    UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 };
-    UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 };
-
-    static const char* semanticName = "TEXCOORD";
-
-    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        if (attributes[i].active)
-        {
-            VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer);
-            BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL;
-
-            D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
-
-            // Record the type of the associated vertex shader vector in our key
-            // This will prevent mismatched vertex shaders from using the same input layout
-            GLint attributeSize;
-            programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.glslElementType[ilKey.elementCount], NULL);
-
-            ilKey.elements[ilKey.elementCount].SemanticName = semanticName;
-            ilKey.elements[ilKey.elementCount].SemanticIndex = sortedSemanticIndices[i];
-            ilKey.elements[ilKey.elementCount].Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
-            ilKey.elements[ilKey.elementCount].InputSlot = i;
-            ilKey.elements[ilKey.elementCount].AlignedByteOffset = 0;
-            ilKey.elements[ilKey.elementCount].InputSlotClass = inputClass;
-            ilKey.elements[ilKey.elementCount].InstanceDataStepRate = attributes[i].divisor;
-            ilKey.elementCount++;
-
-            vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer();
-            vertexStrides[i] = attributes[i].stride;
-            vertexOffsets[i] = attributes[i].offset;
-        }
-    }
-
-    ID3D11InputLayout *inputLayout = NULL;
-
-    InputLayoutMap::iterator i = mInputLayoutMap.find(ilKey);
-    if (i != mInputLayoutMap.end())
-    {
-        inputLayout = i->second.inputLayout;
-        i->second.lastUsedTime = mCounter++;
-    }
-    else
-    {
-        ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
-
-        HRESULT result = mDevice->CreateInputLayout(ilKey.elements, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
-        if (FAILED(result))
-        {
-            ERR("Failed to crate input layout, result: 0x%08x", result);
-            return GL_INVALID_OPERATION;
-        }
-
-        if (mInputLayoutMap.size() >= kMaxInputLayouts)
-        {
-            TRACE("Overflowed the limit of %u input layouts, removing the least recently used "
-                  "to make room.", kMaxInputLayouts);
-
-            InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin();
-            for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
-            {
-                if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime)
-                {
-                    leastRecentlyUsed = i;
-                }
-            }
-            leastRecentlyUsed->second.inputLayout->Release();
-            mInputLayoutMap.erase(leastRecentlyUsed);
-        }
-
-        InputLayoutCounterPair inputCounterPair;
-        inputCounterPair.inputLayout = inputLayout;
-        inputCounterPair.lastUsedTime = mCounter++;
-
-        mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair));
-    }
-
-    mDeviceContext->IASetInputLayout(inputLayout);
-    mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, vertexBuffers, vertexStrides, vertexOffsets);
-
-    return GL_NO_ERROR;
-}
-
-std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout)
-{
-    static const unsigned int seed = 0xDEADBEEF;
-
-    std::size_t hash = 0;
-    MurmurHash3_x86_32(&inputLayout, sizeof(InputLayoutKey), seed, &hash);
-    return hash;
-}
-
-bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b)
-{
-    return memcmp(&a, &b, sizeof(InputLayoutKey)) == 0;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/InputLayoutCache.h b/src/third_party/angle/src/libGLESv2/renderer/InputLayoutCache.h
deleted file mode 100644
index d95f39f..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/InputLayoutCache.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches
-// D3D11 input layouts.
-
-#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
-#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
-
-#include "libGLESv2/Constants.h"
-#include "common/angleutils.h"
-
-namespace gl
-{
-class ProgramBinary;
-}
-
-namespace rx
-{
-struct TranslatedAttribute;
-
-class InputLayoutCache
-{
-  public:
-    InputLayoutCache();
-    virtual ~InputLayoutCache();
-
-    void initialize(ID3D11Device *device, ID3D11DeviceContext *context);
-    void clear();
-
-    GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
-                              gl::ProgramBinary *programBinary);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(InputLayoutCache);
-
-    struct InputLayoutKey
-    {
-        unsigned int elementCount;
-        D3D11_INPUT_ELEMENT_DESC elements[gl::MAX_VERTEX_ATTRIBS];
-        GLenum glslElementType[gl::MAX_VERTEX_ATTRIBS];
-    };
-
-    struct InputLayoutCounterPair
-    {
-        ID3D11InputLayout *inputLayout;
-        unsigned long long lastUsedTime;
-    };
-
-    static std::size_t hashInputLayout(const InputLayoutKey &inputLayout);
-    static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b);
-
-    typedef std::size_t (*InputLayoutHashFunction)(const InputLayoutKey &);
-    typedef bool (*InputLayoutEqualityFunction)(const InputLayoutKey &, const InputLayoutKey &);
-    typedef std::unordered_map<InputLayoutKey,
-                               InputLayoutCounterPair,
-                               InputLayoutHashFunction,
-                               InputLayoutEqualityFunction> InputLayoutMap;
-    InputLayoutMap mInputLayoutMap;
-
-    static const unsigned int kMaxInputLayouts;
-
-    unsigned long long mCounter;
-
-    ID3D11Device *mDevice;
-    ID3D11DeviceContext *mDeviceContext;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Query11.cpp b/src/third_party/angle/src/libGLESv2/renderer/Query11.cpp
deleted file mode 100644
index 13210fc..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Query11.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl.
-
-#include "libGLESv2/renderer/Query11.h"
-#include "libGLESv2/renderer/Renderer11.h"
-#include "libGLESv2/main.h"
-
-namespace rx
-{
-
-Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type)
-{
-    mRenderer = renderer;
-    mQuery = NULL;
-}
-
-Query11::~Query11()
-{
-    if (mQuery)
-    {
-        mQuery->Release();
-        mQuery = NULL;
-    }
-}
-
-void Query11::begin()
-{
-    if (mQuery == NULL)
-    {
-        D3D11_QUERY_DESC queryDesc;
-        queryDesc.Query = D3D11_QUERY_OCCLUSION;
-        queryDesc.MiscFlags = 0;
-
-        if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
-        {
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    mRenderer->getDeviceContext()->Begin(mQuery);
-}
-
-void Query11::end()
-{
-    if (mQuery == NULL)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    mRenderer->getDeviceContext()->End(mQuery);
-
-    mStatus = GL_FALSE;
-    mResult = GL_FALSE;
-}
-
-GLuint Query11::getResult()
-{
-    if (mQuery != NULL)
-    {
-        while (!testQuery())
-        {
-            Sleep(0);
-            // explicitly check for device loss, some drivers seem to return S_FALSE
-            // if the device is lost
-            if (mRenderer->testDeviceLost(true))
-            {
-                return gl::error(GL_OUT_OF_MEMORY, 0);
-            }
-        }
-    }
-
-    return mResult;
-}
-
-GLboolean Query11::isResultAvailable()
-{
-    if (mQuery != NULL)
-    {
-        testQuery();
-    }
-
-    return mStatus;
-}
-
-GLboolean Query11::testQuery()
-{
-    if (mQuery != NULL && mStatus != GL_TRUE)
-    {
-        UINT64 numPixels = 0;
-        HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, &numPixels, sizeof(UINT64), 0);
-        if (result == S_OK)
-        {
-            mStatus = GL_TRUE;
-
-            switch (getType())
-            {
-              case GL_ANY_SAMPLES_PASSED_EXT:
-              case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
-                mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
-                break;
-              default:
-                UNREACHABLE();
-            }
-        }
-        else if (mRenderer->testDeviceLost(true))
-        {
-            return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
-        }
-
-        return mStatus;
-    }
-
-    return GL_TRUE; // prevent blocking when query is null
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Query11.h b/src/third_party/angle/src/libGLESv2/renderer/Query11.h
deleted file mode 100644
index 0a03de7..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Query11.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl.
-
-#ifndef LIBGLESV2_RENDERER_QUERY11_H_
-#define LIBGLESV2_RENDERER_QUERY11_H_
-
-#include "libGLESv2/renderer/QueryImpl.h"
-
-namespace rx
-{
-class Renderer11;
-
-class Query11 : public QueryImpl
-{
-  public:
-    Query11(rx::Renderer11 *renderer, GLenum type);
-    virtual ~Query11();
-
-    void begin();
-    void end();
-    GLuint getResult();
-    GLboolean isResultAvailable();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Query11);
-
-    GLboolean testQuery();
-
-    rx::Renderer11 *mRenderer;
-    ID3D11Query *mQuery;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_QUERY11_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Query9.cpp b/src/third_party/angle/src/libGLESv2/renderer/Query9.cpp
deleted file mode 100644
index ef69426..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Query9.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl.
-
-
-#include "libGLESv2/renderer/Query9.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/renderer9_utils.h"
-#include "libGLESv2/renderer/Renderer9.h"
-
-namespace rx
-{
-
-Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type)
-{
-    mRenderer = renderer;
-    mQuery = NULL;
-}
-
-Query9::~Query9()
-{
-    if (mQuery)
-    {
-        mQuery->Release();
-        mQuery = NULL;
-    }
-}
-
-void Query9::begin()
-{
-    if (mQuery == NULL)
-    {
-        if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery)))
-        {
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
-    ASSERT(SUCCEEDED(result));
-}
-
-void Query9::end()
-{
-    if (mQuery == NULL)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    HRESULT result = mQuery->Issue(D3DISSUE_END);
-    ASSERT(SUCCEEDED(result));
-
-    mStatus = GL_FALSE;
-    mResult = GL_FALSE;
-}
-
-GLuint Query9::getResult()
-{
-    if (mQuery != NULL)
-    {
-        while (!testQuery())
-        {
-            Sleep(0);
-            // explicitly check for device loss
-            // some drivers seem to return S_FALSE even if the device is lost
-            // instead of D3DERR_DEVICELOST like they should
-            if (mRenderer->testDeviceLost(true))
-            {
-                return gl::error(GL_OUT_OF_MEMORY, 0);
-            }
-        }
-    }
-
-    return mResult;
-}
-
-GLboolean Query9::isResultAvailable()
-{
-    if (mQuery != NULL)
-    {
-        testQuery();
-    }
-
-    return mStatus;
-}
-
-GLboolean Query9::testQuery()
-{
-    if (mQuery != NULL && mStatus != GL_TRUE)
-    {
-        DWORD numPixels = 0;
-
-        HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH);
-        if (hres == S_OK)
-        {
-            mStatus =  GL_TRUE;
-
-            switch (getType())
-            {
-              case GL_ANY_SAMPLES_PASSED_EXT:
-              case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
-                mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
-                break;
-              default:
-                ASSERT(false);
-            }
-        }
-        else if (d3d9::isDeviceLostError(hres))
-        {
-            mRenderer->notifyDeviceLost();
-            return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
-        }
-
-        return mStatus;
-    }
-
-    return GL_TRUE; // prevent blocking when query is null
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Query9.h b/src/third_party/angle/src/libGLESv2/renderer/Query9.h
deleted file mode 100644
index 47eef89..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Query9.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl.
-
-#ifndef LIBGLESV2_RENDERER_QUERY9_H_
-#define LIBGLESV2_RENDERER_QUERY9_H_
-
-#include "libGLESv2/renderer/QueryImpl.h"
-
-namespace rx
-{
-class Renderer9;
-
-class Query9 : public QueryImpl
-{
-  public:
-    Query9(rx::Renderer9 *renderer, GLenum type);
-    virtual ~Query9();
-
-    void begin();
-    void end();
-    GLuint getResult();
-    GLboolean isResultAvailable();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Query9);
-
-    GLboolean testQuery();
-
-    rx::Renderer9 *mRenderer;
-    IDirect3DQuery9 *mQuery;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_QUERY9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/QueryImpl.h b/src/third_party/angle/src/libGLESv2/renderer/QueryImpl.h
deleted file mode 100644
index a874047..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/QueryImpl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// QueryImpl.h: Defines the abstract rx::QueryImpl class.
-
-#ifndef LIBGLESV2_RENDERER_QUERYIMPL_H_
-#define LIBGLESV2_RENDERER_QUERYIMPL_H_
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-
-class QueryImpl
-{
-  public:
-    explicit QueryImpl(GLenum type) : mType(type), mStatus(GL_FALSE), mResult(0) { }
-    virtual ~QueryImpl() { }
-
-    virtual void begin() = 0;
-    virtual void end() = 0;
-    virtual GLuint getResult() = 0;
-    virtual GLboolean isResultAvailable() = 0;
-
-    GLenum getType() const { return mType; }
-
-  protected:
-    GLuint mResult;
-    GLboolean mStatus;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(QueryImpl);
-
-    GLenum mType;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_QUERYIMPL_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/RenderStateCache.cpp b/src/third_party/angle/src/libGLESv2/renderer/RenderStateCache.cpp
deleted file mode 100644
index b3111af..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/RenderStateCache.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render
-// state objects.
-
-#include "libGLESv2/renderer/RenderStateCache.h"
-#include "libGLESv2/renderer/renderer11_utils.h"
-
-#include "common/debug.h"
-#include "third_party/murmurhash/MurmurHash3.h"
-
-namespace rx
-{
-
-// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState,
-// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum
-// number of unique states of each type an application can create is 4096
-const unsigned int RenderStateCache::kMaxBlendStates = 4096;
-const unsigned int RenderStateCache::kMaxRasterizerStates = 4096;
-const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096;
-const unsigned int RenderStateCache::kMaxSamplerStates = 4096;
-
-RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0),
-                                       mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
-                                       mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates),
-                                       mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates),
-                                       mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates)
-{
-}
-
-RenderStateCache::~RenderStateCache()
-{
-    clear();
-}
-
-void RenderStateCache::initialize(ID3D11Device *device)
-{
-    clear();
-    mDevice = device;
-}
-
-void RenderStateCache::clear()
-{
-    for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
-    {
-        i->second.first->Release();
-    }
-    mBlendStateCache.clear();
-
-    for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
-    {
-        i->second.first->Release();
-    }
-    mRasterizerStateCache.clear();
-
-    for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
-    {
-        i->second.first->Release();
-    }
-    mDepthStencilStateCache.clear();
-
-    for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
-    {
-        i->second.first->Release();
-    }
-    mSamplerStateCache.clear();
-}
-
-std::size_t RenderStateCache::hashBlendState(const gl::BlendState &blendState)
-{
-    static const unsigned int seed = 0xABCDEF98;
-
-    std::size_t hash = 0;
-    MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash);
-    return hash;
-}
-
-bool RenderStateCache::compareBlendStates(const gl::BlendState &a, const gl::BlendState &b)
-{
-    return memcmp(&a, &b, sizeof(gl::BlendState)) == 0;
-}
-
-ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendState)
-{
-    if (!mDevice)
-    {
-        ERR("RenderStateCache is not initialized.");
-        return NULL;
-    }
-
-    BlendStateMap::iterator i = mBlendStateCache.find(blendState);
-    if (i != mBlendStateCache.end())
-    {
-        BlendStateCounterPair &state = i->second;
-        state.second = mCounter++;
-        return state.first;
-    }
-    else
-    {
-        if (mBlendStateCache.size() >= kMaxBlendStates)
-        {
-            TRACE("Overflowed the limit of %u blend states, removing the least recently used "
-                  "to make room.", kMaxBlendStates);
-
-            BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin();
-            for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
-            {
-                if (i->second.second < leastRecentlyUsed->second.second)
-                {
-                    leastRecentlyUsed = i;
-                }
-            }
-            leastRecentlyUsed->second.first->Release();
-            mBlendStateCache.erase(leastRecentlyUsed);
-        }
-
-        // Create a new blend state and insert it into the cache
-        D3D11_BLEND_DESC blendDesc = { 0 };
-        blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
-        blendDesc.IndependentBlendEnable = FALSE;
-
-        for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
-        {
-            D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i];
-
-            rtBlend.BlendEnable = blendState.blend;
-            if (blendState.blend)
-            {
-                rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
-                rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
-                rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
-
-                rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
-                rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
-                rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
-            }
-
-            rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendState.colorMaskRed,
-                                                                       blendState.colorMaskGreen,
-                                                                       blendState.colorMaskBlue,
-                                                                       blendState.colorMaskAlpha);
-        }
-
-        ID3D11BlendState *dx11BlendState = NULL;
-        HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState);
-        if (FAILED(result) || !dx11BlendState)
-        {
-            ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
-            return NULL;
-        }
-
-        mBlendStateCache.insert(std::make_pair(blendState, std::make_pair(dx11BlendState, mCounter++)));
-
-        return dx11BlendState;
-    }
-}
-
-std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState)
-{
-    static const unsigned int seed = 0xABCDEF98;
-
-    std::size_t hash = 0;
-    MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash);
-    return hash;
-}
-
-bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b)
-{
-    return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
-}
-
-ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState,
-                                                            bool scissorEnabled, unsigned int depthSize)
-{
-    if (!mDevice)
-    {
-        ERR("RenderStateCache is not initialized.");
-        return NULL;
-    }
-
-    RasterizerStateKey key;
-    key.rasterizerState = rasterState;
-    key.scissorEnabled = scissorEnabled;
-    key.depthSize = depthSize;
-
-    RasterizerStateMap::iterator i = mRasterizerStateCache.find(key);
-    if (i != mRasterizerStateCache.end())
-    {
-        RasterizerStateCounterPair &state = i->second;
-        state.second = mCounter++;
-        return state.first;
-    }
-    else
-    {
-        if (mRasterizerStateCache.size() >= kMaxRasterizerStates)
-        {
-            TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used "
-                  "to make room.", kMaxRasterizerStates);
-
-            RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin();
-            for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
-            {
-                if (i->second.second < leastRecentlyUsed->second.second)
-                {
-                    leastRecentlyUsed = i;
-                }
-            }
-            leastRecentlyUsed->second.first->Release();
-            mRasterizerStateCache.erase(leastRecentlyUsed);
-        }
-
-        D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode);
-
-        // Disable culling if drawing points
-        if (rasterState.pointDrawMode)
-        {
-            cullMode = D3D11_CULL_NONE;
-        }
-
-        D3D11_RASTERIZER_DESC rasterDesc;
-        rasterDesc.FillMode = D3D11_FILL_SOLID;
-        rasterDesc.CullMode = cullMode;
-        rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE;
-        rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(depthSize));
-        rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though.
-        rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
-        rasterDesc.DepthClipEnable = TRUE;
-        rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
-        rasterDesc.MultisampleEnable = rasterState.multiSample;
-        rasterDesc.AntialiasedLineEnable = FALSE;
-
-        ID3D11RasterizerState *dx11RasterizerState = NULL;
-        HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState);
-        if (FAILED(result) || !dx11RasterizerState)
-        {
-            ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result);
-            return NULL;
-        }
-
-        mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++)));
-
-        return dx11RasterizerState;
-    }
-}
-
-std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState)
-{
-    static const unsigned int seed = 0xABCDEF98;
-
-    std::size_t hash = 0;
-    MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash);
-    return hash;
-}
-
-bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b)
-{
-    return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
-}
-
-ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState)
-{
-    if (!mDevice)
-    {
-        ERR("RenderStateCache is not initialized.");
-        return NULL;
-    }
-
-    DepthStencilStateMap::iterator i = mDepthStencilStateCache.find(dsState);
-    if (i != mDepthStencilStateCache.end())
-    {
-        DepthStencilStateCounterPair &state = i->second;
-        state.second = mCounter++;
-        return state.first;
-    }
-    else
-    {
-        if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
-        {
-            TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used "
-                  "to make room.", kMaxDepthStencilStates);
-
-            DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin();
-            for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
-            {
-                if (i->second.second < leastRecentlyUsed->second.second)
-                {
-                    leastRecentlyUsed = i;
-                }
-            }
-            leastRecentlyUsed->second.first->Release();
-            mDepthStencilStateCache.erase(leastRecentlyUsed);
-        }
-
-        D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 };
-        dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE;
-        dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask);
-        dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc);
-        dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE;
-        dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask);
-        dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask);
-        dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail);
-        dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail);
-        dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass);
-        dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc);
-        dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail);
-        dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail);
-        dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass);
-        dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc);
-
-        ID3D11DepthStencilState *dx11DepthStencilState = NULL;
-        HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
-        if (FAILED(result) || !dx11DepthStencilState)
-        {
-            ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
-            return NULL;
-        }
-
-        mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++)));
-
-        return dx11DepthStencilState;
-    }
-}
-
-std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState)
-{
-    static const unsigned int seed = 0xABCDEF98;
-
-    std::size_t hash = 0;
-    MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash);
-    return hash;
-}
-
-bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b)
-{
-    return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0;
-}
-
-ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState)
-{
-    if (!mDevice)
-    {
-        ERR("RenderStateCache is not initialized.");
-        return NULL;
-    }
-
-    SamplerStateMap::iterator i = mSamplerStateCache.find(samplerState);
-    if (i != mSamplerStateCache.end())
-    {
-        SamplerStateCounterPair &state = i->second;
-        state.second = mCounter++;
-        return state.first;
-    }
-    else
-    {
-        if (mSamplerStateCache.size() >= kMaxSamplerStates)
-        {
-            TRACE("Overflowed the limit of %u sampler states, removing the least recently used "
-                  "to make room.", kMaxSamplerStates);
-
-            SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin();
-            for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
-            {
-                if (i->second.second < leastRecentlyUsed->second.second)
-                {
-                    leastRecentlyUsed = i;
-                }
-            }
-            leastRecentlyUsed->second.first->Release();
-            mSamplerStateCache.erase(leastRecentlyUsed);
-        }
-
-        D3D11_SAMPLER_DESC samplerDesc;
-        samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, samplerState.maxAnisotropy);
-        samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS);
-        samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT);
-        samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
-        samplerDesc.MipLODBias = static_cast<float>(samplerState.lodOffset);
-        samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy;
-        samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
-        samplerDesc.BorderColor[0] = 0.0f;
-        samplerDesc.BorderColor[1] = 0.0f;
-        samplerDesc.BorderColor[2] = 0.0f;
-        samplerDesc.BorderColor[3] = 0.0f;
-        samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset);
-        samplerDesc.MaxLOD = gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset);
-
-        ID3D11SamplerState *dx11SamplerState = NULL;
-        HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState);
-        if (FAILED(result) || !dx11SamplerState)
-        {
-            ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
-            return NULL;
-        }
-
-        mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++)));
-
-        return dx11SamplerState;
-    }
-}
-
-}
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/RenderStateCache.h b/src/third_party/angle/src/libGLESv2/renderer/RenderStateCache.h
deleted file mode 100644
index f8b5111..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/RenderStateCache.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render
-// state objects.
-
-#ifndef LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
-#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
-
-#include "libGLESv2/angletypes.h"
-#include "common/angleutils.h"
-
-namespace rx
-{
-
-class RenderStateCache
-{
-  public:
-    RenderStateCache();
-    virtual ~RenderStateCache();
-
-    void initialize(ID3D11Device *device);
-    void clear();
-
-    // Increments refcount on the returned blend state, Release() must be called.
-    ID3D11BlendState *getBlendState(const gl::BlendState &blendState);
-    ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState,
-                                              bool scissorEnabled, unsigned int depthSize);
-    ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState);
-    ID3D11SamplerState *getSamplerState(const gl::SamplerState &samplerState);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(RenderStateCache);
-
-    unsigned long long mCounter;
-
-    // Blend state cache
-    static std::size_t hashBlendState(const gl::BlendState &blendState);
-    static bool compareBlendStates(const gl::BlendState &a, const gl::BlendState &b);
-    static const unsigned int kMaxBlendStates;
-
-    typedef std::size_t (*BlendStateHashFunction)(const gl::BlendState &);
-    typedef bool (*BlendStateEqualityFunction)(const gl::BlendState &, const gl::BlendState &);
-    typedef std::pair<ID3D11BlendState*, unsigned long long> BlendStateCounterPair;
-    typedef std::unordered_map<gl::BlendState, BlendStateCounterPair, BlendStateHashFunction, BlendStateEqualityFunction> BlendStateMap;
-    BlendStateMap mBlendStateCache;
-
-    // Rasterizer state cache
-    struct RasterizerStateKey
-    {
-        gl::RasterizerState rasterizerState;
-        bool scissorEnabled;
-        unsigned int depthSize;
-    };
-    static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState);
-    static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
-    static const unsigned int kMaxRasterizerStates;
-
-    typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &);
-    typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &);
-    typedef std::pair<ID3D11RasterizerState*, unsigned long long> RasterizerStateCounterPair;
-    typedef std::unordered_map<RasterizerStateKey, RasterizerStateCounterPair, RasterizerStateHashFunction, RasterizerStateEqualityFunction> RasterizerStateMap;
-    RasterizerStateMap mRasterizerStateCache;
-
-    // Depth stencil state cache
-    static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState);
-    static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b);
-    static const unsigned int kMaxDepthStencilStates;
-
-    typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &);
-    typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &);
-    typedef std::pair<ID3D11DepthStencilState*, unsigned long long> DepthStencilStateCounterPair;
-    typedef std::unordered_map<gl::DepthStencilState,
-                               DepthStencilStateCounterPair,
-                               DepthStencilStateHashFunction,
-                               DepthStencilStateEqualityFunction> DepthStencilStateMap;
-    DepthStencilStateMap mDepthStencilStateCache;
-
-    // Sample state cache
-    static std::size_t hashSamplerState(const gl::SamplerState &samplerState);
-    static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b);
-    static const unsigned int kMaxSamplerStates;
-
-    typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &);
-    typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &);
-    typedef std::pair<ID3D11SamplerState*, unsigned long long> SamplerStateCounterPair;
-    typedef std::unordered_map<gl::SamplerState,
-                               SamplerStateCounterPair,
-                               SamplerStateHashFunction,
-                               SamplerStateEqualityFunction> SamplerStateMap;
-    SamplerStateMap mSamplerStateCache;
-
-    ID3D11Device *mDevice;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget.h b/src/third_party/angle/src/libGLESv2/renderer/RenderTarget.h
deleted file mode 100644
index 80de39f..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderTarget.h: Defines an abstract wrapper class to manage IDirect3DSurface9
-// and ID3D11View objects belonging to renderbuffers.
-
-#ifndef LIBGLESV2_RENDERER_RENDERTARGET_H_
-#define LIBGLESV2_RENDERER_RENDERTARGET_H_
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-class RenderTarget
-{
-  public:
-    RenderTarget()
-    {
-        mWidth = 0;
-        mHeight = 0;
-        mInternalFormat = GL_NONE;
-        mActualFormat = GL_NONE;
-        mSamples = 0;
-    }
-
-    virtual ~RenderTarget() {};
-
-    GLsizei getWidth() { return mWidth; }
-    GLsizei getHeight() { return mHeight; }
-    GLenum getInternalFormat() { return mInternalFormat; }
-    GLenum getActualFormat() { return mActualFormat; }
-    GLsizei getSamples() { return mSamples; }
-    
-    struct Desc {
-        GLsizei width;
-        GLsizei height;
-        GLenum  format;
-    };
-
-  protected:
-    GLsizei mWidth;
-    GLsizei mHeight;
-    GLenum mInternalFormat;
-    GLenum mActualFormat;
-    GLsizei mSamples;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(RenderTarget);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERTARGET_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget11.cpp b/src/third_party/angle/src/libGLESv2/renderer/RenderTarget11.cpp
deleted file mode 100644
index f3b9563..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget11.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers
-// retained by Renderbuffers.
-
-#include "libGLESv2/renderer/RenderTarget11.h"
-#include "libGLESv2/renderer/Renderer11.h"
-
-#include "libGLESv2/renderer/renderer11_utils.h"
-#include "libGLESv2/main.h"
-
-namespace rx
-{
-
-static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view)
-{
-    D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-    view->GetDesc(&rtvDesc);
-
-    D3D11_TEXTURE2D_DESC texDesc;
-    texture->GetDesc(&texDesc);
-
-    unsigned int mipSlice = 0;
-    unsigned int arraySlice = 0;
-    unsigned int mipLevels = texDesc.MipLevels;
-
-    switch (rtvDesc.ViewDimension)
-    {
-      case D3D11_RTV_DIMENSION_TEXTURE1D:
-        mipSlice = rtvDesc.Texture1D.MipSlice;
-        arraySlice = 0;
-        break;
-
-      case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
-        mipSlice = rtvDesc.Texture1DArray.MipSlice;
-        arraySlice = rtvDesc.Texture1DArray.FirstArraySlice;
-        break;
-
-      case D3D11_RTV_DIMENSION_TEXTURE2D:
-        mipSlice = rtvDesc.Texture2D.MipSlice;
-        arraySlice = 0;
-        break;
-
-      case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
-        mipSlice = rtvDesc.Texture2DArray.MipSlice;
-        arraySlice = rtvDesc.Texture2DArray.FirstArraySlice;
-        break;
-
-      case D3D11_RTV_DIMENSION_TEXTURE2DMS:
-        mipSlice = 0;
-        arraySlice = 0;
-        break;
-
-      case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
-        mipSlice = 0;
-        arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice;
-        break;
-
-      case D3D11_RTV_DIMENSION_TEXTURE3D:
-        mipSlice = rtvDesc.Texture3D.MipSlice;
-        arraySlice = 0;
-        break;
-
-      case D3D11_RTV_DIMENSION_UNKNOWN:
-      case D3D11_RTV_DIMENSION_BUFFER:
-        UNIMPLEMENTED();
-        break;
-
-      default:
-        UNREACHABLE();
-        break;
-    }
-
-    return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
-}
-
-static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view)
-{
-    D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
-    view->GetDesc(&dsvDesc);
-
-    D3D11_TEXTURE2D_DESC texDesc;
-    texture->GetDesc(&texDesc);
-
-    unsigned int mipSlice = 0;
-    unsigned int arraySlice = 0;
-    unsigned int mipLevels = texDesc.MipLevels;
-
-    switch (dsvDesc.ViewDimension)
-    {
-      case D3D11_DSV_DIMENSION_TEXTURE1D:
-        mipSlice = dsvDesc.Texture1D.MipSlice;
-        arraySlice = 0;
-        break;
-
-      case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
-        mipSlice = dsvDesc.Texture1DArray.MipSlice;
-        arraySlice = dsvDesc.Texture1DArray.FirstArraySlice;
-        break;
-
-      case D3D11_DSV_DIMENSION_TEXTURE2D:
-        mipSlice = dsvDesc.Texture2D.MipSlice;
-        arraySlice = 0;
-        break;
-
-      case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
-        mipSlice = dsvDesc.Texture2DArray.MipSlice;
-        arraySlice = dsvDesc.Texture2DArray.FirstArraySlice;
-        break;
-
-      case D3D11_DSV_DIMENSION_TEXTURE2DMS:
-        mipSlice = 0;
-        arraySlice = 0;
-        break;
-
-      case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
-        mipSlice = 0;
-        arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice;
-        break;
-
-      case D3D11_RTV_DIMENSION_UNKNOWN:
-        UNIMPLEMENTED();
-        break;
-
-      default:
-        UNREACHABLE();
-        break;
-    }
-
-    return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
-}
-
-RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
-{
-    mRenderer = Renderer11::makeRenderer11(renderer);
-    mTexture = tex;
-    mRenderTarget = rtv;
-    mDepthStencil = NULL;
-    mShaderResource = srv;
-    mSubresourceIndex = 0;
-
-    if (mRenderTarget && mTexture)
-    {
-        D3D11_RENDER_TARGET_VIEW_DESC desc;
-        mRenderTarget->GetDesc(&desc);
-
-        D3D11_TEXTURE2D_DESC texDesc;
-        mTexture->GetDesc(&texDesc);
-
-        mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
-        mWidth = width;
-        mHeight = height;
-        mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0;
-
-        mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
-        mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
-    }
-}
-
-RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
-{
-    mRenderer = Renderer11::makeRenderer11(renderer);
-    mTexture = tex;
-    mRenderTarget = NULL;
-    mDepthStencil = dsv;
-    mShaderResource = srv;
-    mSubresourceIndex = 0;
-
-    if (mDepthStencil && mTexture)
-    {
-        D3D11_DEPTH_STENCIL_VIEW_DESC desc;
-        mDepthStencil->GetDesc(&desc);
-
-        D3D11_TEXTURE2D_DESC texDesc;
-        mTexture->GetDesc(&texDesc);
-
-        mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
-        mWidth = width;
-        mHeight = height;
-        mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0;
-
-        mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
-        mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
-    }
-}
-
-RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth)
-{
-    mRenderer = Renderer11::makeRenderer11(renderer);
-    mTexture = NULL;
-    mRenderTarget = NULL;
-    mDepthStencil = NULL;
-    mShaderResource = NULL;
-
-    DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format);
-
-    int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples);
-    if (supportedSamples < 0)
-    {
-        gl::error(GL_OUT_OF_MEMORY);
-        return;
-    }
-
-    if (width > 0 && height > 0)
-    {
-        // Create texture resource
-        D3D11_TEXTURE2D_DESC desc;
-        desc.Width = width; 
-        desc.Height = height;
-        desc.MipLevels = 1;
-        desc.ArraySize = 1;
-        desc.Format = requestedFormat;
-        desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
-        desc.SampleDesc.Quality = 0;
-        desc.Usage = D3D11_USAGE_DEFAULT;
-        desc.CPUAccessFlags = 0;
-        desc.MiscFlags = 0;
-        desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE));
-
-        ID3D11Device *device = mRenderer->getDevice();
-        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
-
-        if (result == E_OUTOFMEMORY)
-        {
-            gl::error(GL_OUT_OF_MEMORY);
-            return;
-        }
-        ASSERT(SUCCEEDED(result));
-        d3d11::ResourceTracker::Track(mTexture);
-
-        if (depth)
-        {
-            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
-            dsvDesc.Format = requestedFormat;
-            dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
-            dsvDesc.Texture2D.MipSlice = 0;
-            dsvDesc.Flags = 0;
-            result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil);
-
-            if (result == E_OUTOFMEMORY)
-            {
-                mTexture->Release();
-                mTexture = NULL;
-                gl::error(GL_OUT_OF_MEMORY);
-            }
-            ASSERT(SUCCEEDED(result));
-        }
-        else
-        {
-            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-            rtvDesc.Format = requestedFormat;
-            rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
-            rtvDesc.Texture2D.MipSlice = 0;
-            result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget);
-
-            if (result == E_OUTOFMEMORY)
-            {
-                mTexture->Release();
-                mTexture = NULL;
-                gl::error(GL_OUT_OF_MEMORY);
-                return;
-            }
-            ASSERT(SUCCEEDED(result));
-
-            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
-            srvDesc.Format = requestedFormat;
-            srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
-            srvDesc.Texture2D.MostDetailedMip = 0;
-            srvDesc.Texture2D.MipLevels = 1;
-            result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource);
-
-            if (result == E_OUTOFMEMORY)
-            {
-                mTexture->Release();
-                mTexture = NULL;
-                mRenderTarget->Release();
-                mRenderTarget = NULL;
-                gl::error(GL_OUT_OF_MEMORY);
-                return;
-            }
-            ASSERT(SUCCEEDED(result));
-        }
-    }
-
-    mWidth = width;
-    mHeight = height;
-    mInternalFormat = format;
-    mSamples = supportedSamples;
-    mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat);
-    mSubresourceIndex = D3D11CalcSubresource(0, 0, 1);
-}
-
-RenderTarget11::~RenderTarget11()
-{
-    if (mTexture)
-    {
-        mTexture->Release();
-        mTexture = NULL;
-    }
-
-    if (mRenderTarget)
-    {
-        mRenderTarget->Release();
-        mRenderTarget = NULL;
-    }
-
-    if (mDepthStencil)
-    {
-        mDepthStencil->Release();
-        mDepthStencil = NULL;
-    }
-
-    if (mShaderResource)
-    {
-        mShaderResource->Release();
-        mShaderResource = NULL;
-    }
-}
-
-RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target));
-    return static_cast<rx::RenderTarget11*>(target);
-}
-
-ID3D11Texture2D *RenderTarget11::getTexture() const
-{
-    if (mTexture)
-    {
-        mTexture->AddRef();
-    }
-
-    return mTexture;
-}
-
-// Adds reference, caller must call Release
-ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const
-{
-    if (mRenderTarget)
-    {
-        mRenderTarget->AddRef();
-    }
-
-    return mRenderTarget;
-}
-
-// Adds reference, caller must call Release
-ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const
-{
-    if (mDepthStencil)
-    {
-        mDepthStencil->AddRef();
-    }
-
-    return mDepthStencil;
-}
-
-// Adds reference, caller must call Release
-ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const
-{
-    if (mShaderResource)
-    {
-        mShaderResource->AddRef();
-    }
-
-    return mShaderResource;
-}
-
-unsigned int RenderTarget11::getSubresourceIndex() const
-{
-    return mSubresourceIndex;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget11.h b/src/third_party/angle/src/libGLESv2/renderer/RenderTarget11.h
deleted file mode 100644
index dc697cf..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget11.h
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers
-// retained by Renderbuffers.
-
-#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_
-#define LIBGLESV2_RENDERER_RENDERTARGET11_H_
-
-#include "libGLESv2/renderer/RenderTarget.h"
-
-namespace rx
-{
-class Renderer;
-class Renderer11;
-
-class RenderTarget11 : public RenderTarget
-{
-  public:
-    RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height);
-    RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height);
-    RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth);
-    virtual ~RenderTarget11();
-
-    static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget);
-
-    // Adds reference, caller must call Release
-    ID3D11Texture2D *getTexture() const;
-
-    // Adds reference, caller must call Release
-    ID3D11RenderTargetView *getRenderTargetView() const;
-
-    // Adds reference, caller must call Release
-    ID3D11DepthStencilView *getDepthStencilView() const;
-
-    // Adds reference, caller must call Release
-    ID3D11ShaderResourceView *getShaderResourceView() const;
-
-    unsigned int getSubresourceIndex() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(RenderTarget11);
-
-    unsigned int mSubresourceIndex;
-    ID3D11Texture2D *mTexture;
-    ID3D11RenderTargetView *mRenderTarget;
-    ID3D11DepthStencilView *mDepthStencil;
-    ID3D11ShaderResourceView *mShaderResource;
-
-    Renderer11 *mRenderer;
-};
-
-}
-
-#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget9.cpp b/src/third_party/angle/src/libGLESv2/renderer/RenderTarget9.cpp
deleted file mode 100644
index a84c709..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget9.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9
-// pointers retained by renderbuffers.
-
-#include "libGLESv2/renderer/RenderTarget9.h"
-#include "libGLESv2/renderer/Renderer9.h"
-
-#include "libGLESv2/renderer/renderer9_utils.h"
-#include "libGLESv2/main.h"
-
-namespace rx
-{
-
-RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface)
-{
-    mRenderer = Renderer9::makeRenderer9(renderer);
-    mRenderTarget = surface;
-
-    if (mRenderTarget)
-    {
-        D3DSURFACE_DESC description;
-        mRenderTarget->GetDesc(&description);
-
-        mWidth = description.Width;
-        mHeight = description.Height;
-        
-        mInternalFormat = d3d9_gl::GetEquivalentFormat(description.Format);
-        mActualFormat = d3d9_gl::GetEquivalentFormat(description.Format);
-        mSamples = d3d9_gl::GetSamplesFromMultisampleType(description.MultiSampleType);
-    }
-}
-
-RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples)
-{
-    mRenderer = Renderer9::makeRenderer9(renderer);
-    mRenderTarget = NULL;
-
-    D3DFORMAT requestedFormat = gl_d3d9::ConvertRenderbufferFormat(format);
-    int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples);
-
-    if (supportedSamples == -1)
-    {
-        gl::error(GL_OUT_OF_MEMORY);
-
-        return;
-    }
-
-    HRESULT result = D3DERR_INVALIDCALL;
-    
-    if (width > 0 && height > 0)
-    {
-        if (requestedFormat == D3DFMT_D24S8)
-        {
-            result = mRenderer->getDevice()->CreateDepthStencilSurface(width, height, requestedFormat,
-                                                                       gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples),
-                                                                       0, FALSE, &mRenderTarget, NULL);
-        }
-        else
-        {
-            result = mRenderer->getDevice()->CreateRenderTarget(width, height, requestedFormat, 
-                                                                gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples),
-                                                                0, FALSE, &mRenderTarget, NULL);
-        }
-
-        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
-        {
-            gl::error(GL_OUT_OF_MEMORY);
-
-            return;
-        }
-
-        ASSERT(SUCCEEDED(result));
-    }
-
-    mWidth = width;
-    mHeight = height;
-    mInternalFormat = format;
-    mSamples = supportedSamples;
-    mActualFormat = d3d9_gl::GetEquivalentFormat(requestedFormat);
-}
-
-RenderTarget9::~RenderTarget9()
-{
-    if (mRenderTarget)
-    {
-        mRenderTarget->Release();
-    }
-}
-
-RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target));
-    return static_cast<rx::RenderTarget9*>(target);
-}
-
-IDirect3DSurface9 *RenderTarget9::getSurface()
-{
-    // Caller is responsible for releasing the returned surface reference.
-    if (mRenderTarget)
-    {
-        mRenderTarget->AddRef();
-    }
-
-    return mRenderTarget;
-}
-
-}
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget9.h b/src/third_party/angle/src/libGLESv2/renderer/RenderTarget9.h
deleted file mode 100644
index faf8ad1..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/RenderTarget9.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers
-// retained by Renderbuffers.
-
-#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_
-#define LIBGLESV2_RENDERER_RENDERTARGET9_H_
-
-#include "libGLESv2/renderer/RenderTarget.h"
-
-namespace rx
-{
-class Renderer;
-class Renderer9;
-
-class RenderTarget9 : public RenderTarget
-{
-  public:
-    RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface);
-    RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples);
-    virtual ~RenderTarget9();
-
-    static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget);
-    IDirect3DSurface9 *getSurface();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(RenderTarget9);
-
-    IDirect3DSurface9 *mRenderTarget;
-
-    Renderer9 *mRenderer;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Renderer.cpp b/src/third_party/angle/src/libGLESv2/renderer/Renderer.cpp
deleted file mode 100644
index e02ef6a..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Renderer.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances.
-
-#if !defined(ANGLE_ENABLE_D3D11)
-// Enables use of the Direct3D 11 API for a default display, when available
-#define ANGLE_ENABLE_D3D11 0
-#endif
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/renderer/Renderer.h"
-#if !defined(ANGLE_ENABLE_D3D11_STRICT) && !defined(ANGLE_ENABLE_XB360_STRICT)
-#include "libGLESv2/renderer/Renderer9.h"
-#endif
-#if ANGLE_ENABLE_D3D11
-#include "libGLESv2/renderer/Renderer11.h"
-#endif
-#if defined(ANGLE_ENABLE_XB360_STRICT)
-#include "libGLESv2/renderer/xb360/RendererXB360.h"
-#endif
-#include "libGLESv2/utilities.h"
-
-
-namespace rx
-{
-
-Renderer::Renderer(egl::Display *display) : mDisplay(display)
-{
-    mD3dCompilerModule = NULL;
-    mD3DCompileFunc = NULL;
-}
-
-Renderer::~Renderer()
-{
-    if (mD3dCompilerModule)
-    {
-        FreeLibrary(mD3dCompilerModule);
-        mD3dCompilerModule = NULL;
-    }
-}
-
-bool Renderer::initializeCompiler()
-{
-#if defined(__LB_XB360__)
-    UNIMPLEMENTED();
-#else
-
-#if defined(ANGLE_STATIC_D3D_LIB)
-    mD3DCompileFunc = reinterpret_cast<pCompileFunc>(&D3DCompile);
-#else
-#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
-    // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
-    static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
-
-    for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
-    {
-        if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule))
-        {
-            break;
-        }
-    }
-#endif
-    if (!mD3dCompilerModule) {
-        // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
-        mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
-    }
-
-    if (!mD3dCompilerModule)
-    {
-        ERR("No D3D compiler module found - aborting!\n");
-        return false;
-    }
-
-    mD3DCompileFunc = reinterpret_cast<pCompileFunc>(GetProcAddress(mD3dCompilerModule, "D3DCompile"));
-    ASSERT(mD3DCompileFunc);
-#endif // ANGLE_STATIC_D3D_LIB
-
-#endif // defined(__LB_XB360__)
-
-    return mD3DCompileFunc != NULL;
-}
-
-// Compiles HLSL code into executable binaries
-ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags)
-{
-#if defined(__LB_XB360__)
-    UNIMPLEMENTED();
-#else
-    if (!hlsl)
-    {
-        return NULL;
-    }
-
-    HRESULT result = S_OK;
-    UINT flags = 0;
-    std::string sourceText;
-    if (gl::perfActive())
-    {
-        flags |= D3DCOMPILE_DEBUG;
-
-#ifdef NDEBUG
-        flags |= optimizationFlags;
-#else
-        flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
-#endif
-
-        std::string sourcePath = getTempPath();
-        sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
-        writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
-    }
-    else
-    {
-        flags |= optimizationFlags;
-        sourceText = hlsl;
-    }
-
-    // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
-    // Try the default flags first and if compilation fails, try some alternatives.
-    const static UINT extraFlags[] =
-    {
-        0,
-        D3DCOMPILE_AVOID_FLOW_CONTROL,
-        D3DCOMPILE_PREFER_FLOW_CONTROL
-    };
-
-    const static char * const extraFlagNames[] =
-    {
-        "default",
-        "avoid flow control",
-        "prefer flow control"
-    };
-
-    int attempts = alternateFlags ? ArraySize(extraFlags) : 1;
-    pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
-    for (int i = 0; i < attempts; ++i)
-    {
-        ID3DBlob *errorMessage = NULL;
-        ID3DBlob *binary = NULL;
-
-        result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL,
-                             "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage);
-        if (errorMessage)
-        {
-            const char *message = (const char*)errorMessage->GetBufferPointer();
-
-            infoLog.appendSanitized(message);
-            TRACE("\n%s", hlsl);
-            TRACE("\n%s", message);
-
-            errorMessage->Release();
-            errorMessage = NULL;
-        }
-
-        if (SUCCEEDED(result))
-        {
-            return (ShaderBlob*)binary;
-        }
-        else
-        {
-#if defined(ANGLE_ENABLE_D3D11_STRICT)
-            if (result == E_OUTOFMEMORY)
-#else
-            if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
-#endif
-            {
-                return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*) NULL);
-            }
-
-            infoLog.append("Warning: D3D shader compilation failed with ");
-            infoLog.append(extraFlagNames[i]);
-            infoLog.append(" flags.");
-            if (i + 1 < attempts)
-            {
-                infoLog.append(" Retrying with ");
-                infoLog.append(extraFlagNames[i + 1]);
-                infoLog.append(".\n");
-            }
-        }
-    }
-
-#endif // defined(__LB_XB360__)
-
-    return NULL;
-}
-
-}
-
-extern "C"
-{
-
-rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId)
-{
-    rx::Renderer *renderer = NULL;
-    EGLint status = EGL_BAD_ALLOC;
-
-#if defined(ANGLE_ENABLE_XB360_STRICT)
-    renderer = new rx::RendererXB360(display);
-#elif ANGLE_ENABLE_D3D11
-    if (displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
-        displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE)
-    {
-        renderer = new rx::Renderer11(display, hDc);
-
-        if (renderer)
-        {
-            status = renderer->initialize();
-        }
-
-        if (status == EGL_SUCCESS)
-        {
-            return renderer;
-        }
-        else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE)
-        {
-            return NULL;
-        }
-
-        // Failed to create a D3D11 renderer, try creating a D3D9 renderer
-        delete renderer;
-    }
-#endif
-
-#if !defined(ANGLE_ENABLE_D3D11_STRICT)
-    bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE);
-    renderer = new rx::Renderer9(display, hDc, softwareDevice);
-#endif // defined(ANGLE_ENABLE_XB360_STRICT)
-
-    if (renderer)
-    {
-        status = renderer->initialize();
-    }
-
-    if (status == EGL_SUCCESS)
-    {
-        return renderer;
-    }
-
-    return NULL;
-}
-
-void glDestroyRenderer(rx::Renderer *renderer)
-{
-    delete renderer;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Renderer.h b/src/third_party/angle/src/libGLESv2/renderer/Renderer.h
deleted file mode 100644
index 9f2b493..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Renderer.h
+++ /dev/null
@@ -1,263 +0,0 @@
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer.h: Defines a back-end specific class that hides the details of the
-// implementation-specific renderer.
-
-#ifndef LIBGLESV2_RENDERER_RENDERER_H_
-#define LIBGLESV2_RENDERER_RENDERER_H_
-
-#include <EGL/eglext.h>
-
-#include "libGLESv2/Uniform.h"
-#include "libGLESv2/angletypes.h"
-
-#if defined(__LB_XB360__)
-#define ANGLE_COMPILE_OPTIMIZATION_LEVEL 0
-#else
-#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
-#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
-#endif
-#endif
-
-const int versionWindowsVista = MAKEWORD(0x00, 0x06);
-const int versionWindows7 = MAKEWORD(0x01, 0x06);
-
-// Return the version of the operating system in a format suitable for ordering
-// comparison.
-inline int getComparableOSVersion()
-{
-#if defined(__LB_XB360__)
-    return 0;
-#else
-    DWORD version = GetVersion();
-    int majorVersion = LOBYTE(LOWORD(version));
-    int minorVersion = HIBYTE(LOWORD(version));
-    return MAKEWORD(minorVersion, majorVersion);
-#endif
-}
-
-namespace egl
-{
-class Display;
-}
-
-namespace gl
-{
-class InfoLog;
-class ProgramBinary;
-class VertexAttribute;
-class Buffer;
-class Texture;
-class Framebuffer;
-}
-
-namespace rx
-{
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
-class VertexBuffer;
-class IndexBuffer;
-class QueryImpl;
-class FenceImpl;
-class BufferStorage;
-class Blit;
-struct TranslatedIndexData;
-class ShaderExecutable;
-class SwapChain;
-class RenderTarget;
-class Image;
-class TextureStorage;
-
-typedef void * ShaderBlob;
-typedef void (*pCompileFunc)();
-
-struct ConfigDesc
-{
-    GLenum  renderTargetFormat;
-    GLenum  depthStencilFormat;
-    GLint   multiSample;
-    bool    fastConfig;
-};
-
-struct dx_VertexConstants
-{
-    float depthRange[4];
-    float viewAdjust[4];
-};
-
-struct dx_PixelConstants
-{
-    float depthRange[4];
-    float viewCoords[4];
-    float depthFront[4];
-};
-
-enum ShaderType
-{
-    SHADER_VERTEX,
-    SHADER_PIXEL,
-    SHADER_GEOMETRY
-};
-
-class Renderer
-{
-  public:
-    explicit Renderer(egl::Display *display);
-    virtual ~Renderer();
-
-    virtual EGLint initialize() = 0;
-    virtual bool resetDevice() = 0;
-
-    // Increments the reference count
-    virtual void* getDeviceRaw() = 0;
-
-#if defined(__LB_XB360__)
-    virtual void setPlayerRaw(void *player) = 0;
-#endif
-
-    virtual int generateConfigs(ConfigDesc **configDescList) = 0;
-    virtual void deleteConfigs(ConfigDesc *configDescList) = 0;
-
-    virtual void sync(bool block) = 0;
-
-    virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
-
-    virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0;
-    virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
-
-    virtual void setRasterizerState(const gl::RasterizerState &rasterState) = 0;
-    virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor,
-                               unsigned int sampleMask) = 0;
-    virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
-                                      int stencilBackRef, bool frontFaceCCW) = 0;
-
-    virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0;
-    virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
-                             bool ignoreViewport) = 0;
-
-    virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0;
-    virtual void applyShaders(gl::ProgramBinary *programBinary) = 0;
-    virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) = 0;
-    virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) = 0;
-    virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
-
-    virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances) = 0;
-    virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0;
-
-    virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0;
-
-    virtual void markAllStateDirty() = 0;
-
-    // lost device
-    virtual void notifyDeviceLost() = 0;
-    virtual bool isDeviceLost() = 0;
-    virtual bool testDeviceLost(bool notify) = 0;
-    virtual bool testDeviceResettable() = 0;
-
-    // Renderer capabilities
-    virtual DWORD getAdapterVendor() const = 0;
-    virtual std::string getRendererDescription() const = 0;
-    virtual GUID getAdapterIdentifier() const = 0;
-
-    virtual bool getBGRATextureSupport() const = 0;
-    virtual bool getDXT1TextureSupport() = 0;
-    virtual bool getDXT3TextureSupport() = 0;
-    virtual bool getDXT5TextureSupport() = 0;
-    virtual bool getEventQuerySupport() = 0;
-    virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable) = 0;
-    virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable) = 0;
-    virtual bool getLuminanceTextureSupport() = 0;
-    virtual bool getLuminanceAlphaTextureSupport() = 0;
-    bool getVertexTextureSupport() const { return getMaxVertexTextureImageUnits() > 0; }
-    virtual unsigned int getMaxVertexTextureImageUnits() const = 0;
-    virtual unsigned int getMaxCombinedTextureImageUnits() const = 0;
-    virtual unsigned int getReservedVertexUniformVectors() const = 0;
-    virtual unsigned int getReservedFragmentUniformVectors() const = 0;
-    virtual unsigned int getMaxVertexUniformVectors() const = 0;
-    virtual unsigned int getMaxFragmentUniformVectors() const = 0;
-    virtual unsigned int getMaxVaryingVectors() const = 0;
-    virtual bool getNonPower2TextureSupport() const = 0;
-    virtual bool getDepthTextureSupport() const = 0;
-    virtual bool getOcclusionQuerySupport() const = 0;
-    virtual bool getInstancingSupport() const = 0;
-    virtual bool getTextureFilterAnisotropySupport() const = 0;
-    virtual float getTextureMaxAnisotropy() const = 0;
-    virtual bool getShareHandleSupport() const = 0;
-    virtual bool getDerivativeInstructionSupport() const = 0;
-    virtual bool getPostSubBufferSupport() const = 0;
-
-    virtual int getMajorShaderModel() const = 0;
-    virtual float getMaxPointSize() const = 0;
-    virtual int getMaxViewportDimension() const = 0;
-    virtual int getMaxTextureWidth() const = 0;
-    virtual int getMaxTextureHeight() const = 0;
-    virtual bool get32BitIndexSupport() const = 0;
-    virtual int getMinSwapInterval() const = 0;
-    virtual int getMaxSwapInterval() const = 0;
-
-    virtual GLsizei getMaxSupportedSamples() const = 0;
-
-    virtual unsigned int getMaxRenderTargets() const = 0;
-
-    // Pixel operations
-    virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) = 0;
-    virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) = 0;
-
-    virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                           GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) = 0;
-    virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                           GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) = 0;
-
-    virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
-                          bool blitRenderTarget, bool blitDepthStencil) = 0;
-    virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
-                            GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) = 0;
-
-    // RenderTarget creation
-    virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0;
-    virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) = 0;
-
-    // Shader operations
-    virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type) = 0;
-    virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) = 0;
-
-    // Image operations
-    virtual Image *createImage() = 0;
-    virtual void generateMipmap(Image *dest, Image *source) = 0;
-    virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0;
-    virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) = 0;
-    virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) = 0;
-
-    // Buffer creation
-    virtual VertexBuffer *createVertexBuffer() = 0;
-    virtual IndexBuffer *createIndexBuffer() = 0;
-    virtual BufferStorage *createBufferStorage() = 0;
-
-    // Query and Fence creation
-    virtual QueryImpl *createQuery(GLenum type) = 0;
-    virtual FenceImpl *createFence() = 0;
-
-    virtual bool getLUID(LUID *adapterLuid) const = 0;
-
-    virtual bool setResourceTracker(EGLResourceTrackerProcAngle proc, void *userData) = 0;
-
-  protected:
-    bool initializeCompiler();
-    ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags);
-
-    egl::Display *mDisplay;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Renderer);
-
-    HMODULE mD3dCompilerModule;
-    pCompileFunc mD3DCompileFunc;
-};
-
-}
-#endif // LIBGLESV2_RENDERER_RENDERER_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/third_party/angle/src/libGLESv2/renderer/Renderer11.cpp
deleted file mode 100644
index eee20fc..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Renderer11.cpp
+++ /dev/null
@@ -1,3552 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/RenderBuffer.h"
-#include "libGLESv2/renderer/Renderer11.h"
-#include "libGLESv2/renderer/RenderTarget11.h"
-#include "libGLESv2/renderer/renderer11_utils.h"
-#include "libGLESv2/renderer/ShaderExecutable11.h"
-#include "libGLESv2/renderer/SwapChain11.h"
-#include "libGLESv2/renderer/Image11.h"
-#include "libGLESv2/renderer/VertexBuffer11.h"
-#include "libGLESv2/renderer/IndexBuffer11.h"
-#include "libGLESv2/renderer/BufferStorage11.h"
-#include "libGLESv2/renderer/VertexDataManager.h"
-#include "libGLESv2/renderer/IndexDataManager.h"
-#include "libGLESv2/renderer/TextureStorage11.h"
-#include "libGLESv2/renderer/Query11.h"
-#include "libGLESv2/renderer/Fence11.h"
-
-#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h"
-#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h"
-#include "libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h"
-#include "libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h"
-#include "libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h"
-
-#include "libGLESv2/renderer/shaders/compiled/clear11vs.h"
-#include "libGLESv2/renderer/shaders/compiled/clearsingle11ps.h"
-#include "libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h"
-
-#include "libEGL/Display.h"
-
-#ifdef _DEBUG
-// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
-// and conformance tests. to enable all warnings, remove this define.
-#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
-#endif
-
-namespace rx
-{
-static const DXGI_FORMAT RenderTargetFormats[] =
-    {
-        DXGI_FORMAT_B8G8R8A8_UNORM,
-        DXGI_FORMAT_R8G8B8A8_UNORM
-    };
-
-static const DXGI_FORMAT DepthStencilFormats[] =
-    {
-        DXGI_FORMAT_UNKNOWN,
-        DXGI_FORMAT_D24_UNORM_S8_UINT,
-        DXGI_FORMAT_D16_UNORM
-    };
-
-enum
-{
-    MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
-};
-
-Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc)
-{
-    mVertexDataManager = NULL;
-    mIndexDataManager = NULL;
-
-    mLineLoopIB = NULL;
-    mTriangleFanIB = NULL;
-
-    mCopyResourcesInitialized = false;
-    mCopyVB = NULL;
-    mCopySampler = NULL;
-    mCopyIL = NULL;
-    mCopyVS = NULL;
-    mCopyRGBAPS = NULL;
-    mCopyRGBPS = NULL;
-    mCopyLumPS = NULL;
-    mCopyLumAlphaPS = NULL;
-
-    mClearResourcesInitialized = false;
-    mClearVB = NULL;
-    mClearIL = NULL;
-    mClearVS = NULL;
-    mClearSinglePS = NULL;
-    mClearMultiplePS = NULL;
-    mClearScissorRS = NULL;
-    mClearNoScissorRS = NULL;
-
-    mSyncQuery = NULL;
-
-    mD3d11Module = NULL;
-    mDxgiModule = NULL;
-
-    mDeviceLost = false;
-
-    mMaxSupportedSamples = 0;
-
-    mDevice = NULL;
-    mDeviceContext = NULL;
-    mDxgiAdapter = NULL;
-    mDxgiFactory = NULL;
-
-    mDriverConstantBufferVS = NULL;
-    mDriverConstantBufferPS = NULL;
-
-    mBGRATextureSupport = false;
-
-    mIsGeometryShaderActive = false;
-}
-
-Renderer11::~Renderer11()
-{
-    release();
-}
-
-Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer));
-    return static_cast<rx::Renderer11*>(renderer);
-}
-
-#ifndef __d3d11_1_h__
-#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
-#endif
-
-EGLint Renderer11::initialize()
-{
-    if (!initializeCompiler())
-    {
-        return EGL_NOT_INITIALIZED;
-    }
-
-#if !defined(ANGLE_STATIC_D3D_LIB)
-    mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
-    mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
-
-    if (mD3d11Module == NULL || mDxgiModule == NULL)
-    {
-        ERR("Could not load D3D11 or DXGI library - aborting!\n");
-        return EGL_NOT_INITIALIZED;
-    }
-
-    // create the D3D11 device
-    ASSERT(mDevice == NULL);
-    PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
-
-    if (D3D11CreateDevice == NULL)
-    {
-        ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
-        return EGL_NOT_INITIALIZED;
-    }
-
-#endif
-
-    D3D_FEATURE_LEVEL featureLevels[] =
-    {
-        D3D_FEATURE_LEVEL_11_0,
-        D3D_FEATURE_LEVEL_10_1,
-        D3D_FEATURE_LEVEL_10_0,
-    };
-
-    HRESULT result = S_OK;
-
-#ifdef _DEBUG
-    result = D3D11CreateDevice(NULL,
-                               D3D_DRIVER_TYPE_HARDWARE,
-                               NULL,
-                               D3D11_CREATE_DEVICE_DEBUG,
-                               featureLevels,
-                               ArraySize(featureLevels),
-                               D3D11_SDK_VERSION,
-                               &mDevice,
-                               &mFeatureLevel,
-                               &mDeviceContext);
-
-    if (!mDevice || FAILED(result))
-    {
-        ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
-    }
-
-    if (!mDevice || FAILED(result))
-#endif
-    {
-        result = D3D11CreateDevice(NULL,
-                                   D3D_DRIVER_TYPE_HARDWARE,
-                                   NULL,
-                                   0,
-                                   featureLevels,
-                                   ArraySize(featureLevels),
-                                   D3D11_SDK_VERSION,
-                                   &mDevice,
-                                   &mFeatureLevel,
-                                   &mDeviceContext);
-
-        if (!mDevice || FAILED(result))
-        {
-            ERR("Could not create D3D11 device - aborting!\n");
-            return EGL_NOT_INITIALIZED;   // Cleanup done by destructor through glDestroyRenderer
-        }
-    }
-
-    IDXGIDevice *dxgiDevice = NULL;
-    result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
-
-    if (FAILED(result))
-    {
-        ERR("Could not query DXGI device - aborting!\n");
-        return EGL_NOT_INITIALIZED;
-    }
-
-    result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
-
-    if (FAILED(result))
-    {
-        ERR("Could not retrieve DXGI adapter - aborting!\n");
-        return EGL_NOT_INITIALIZED;
-    }
-
-    dxgiDevice->Release();
-
-    mDxgiAdapter->GetDesc(&mAdapterDescription);
-    memset(mDescription, 0, sizeof(mDescription));
-    wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
-
-    result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
-
-    if (!mDxgiFactory || FAILED(result))
-    {
-        ERR("Could not create DXGI factory - aborting!\n");
-        return EGL_NOT_INITIALIZED;
-    }
-
-    // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
-#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
-    ID3D11InfoQueue *infoQueue;
-    result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue),  (void **)&infoQueue);
-
-    if (SUCCEEDED(result))
-    {
-        D3D11_MESSAGE_ID hideMessages[] =
-        {
-            D3D11_MESSAGE_ID_DEVICE_OMSETRENDERTARGETS_HAZARD,
-            D3D11_MESSAGE_ID_DEVICE_PSSETSHADERRESOURCES_HAZARD,
-            D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET
-        };
-
-        D3D11_INFO_QUEUE_FILTER filter = {0};
-        filter.DenyList.NumIDs = ArraySize(hideMessages);
-        filter.DenyList.pIDList = hideMessages;
-
-        infoQueue->AddStorageFilterEntries(&filter);
-
-        infoQueue->Release();
-    }
-#endif
-
-    unsigned int maxSupportedSamples = 0;
-    unsigned int rtFormatCount = ArraySize(RenderTargetFormats);
-    unsigned int dsFormatCount = ArraySize(DepthStencilFormats);
-    for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i)
-    {
-        DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount];
-        if (format != DXGI_FORMAT_UNKNOWN)
-        {
-            UINT formatSupport;
-            result = mDevice->CheckFormatSupport(format, &formatSupport);
-            if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
-            {
-                MultisampleSupportInfo supportInfo;
-
-                for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++)
-                {
-                    result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]);
-                    if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0)
-                    {
-                        maxSupportedSamples = std::max(j, maxSupportedSamples);
-                    }
-                    else
-                    {
-                        supportInfo.qualityLevels[j - 1] = 0;
-                    }
-                }
-
-                mMultisampleSupportMap.insert(std::make_pair(format, supportInfo));
-            }
-        }
-    }
-    mMaxSupportedSamples = maxSupportedSamples;
-
-    initializeDevice();
-
-    // BGRA texture support is optional in feature levels 10 and 10_1
-    UINT formatSupport;
-    result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport);
-    if (FAILED(result))
-    {
-        ERR("Error checking BGRA format support: 0x%08X", result);
-    }
-    else
-    {
-        const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET);
-        mBGRATextureSupport = (formatSupport & flags) == flags;
-    }
-
-    // Check floating point texture support
-    static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE;
-    static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET;
-    static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
-
-    DXGI_FORMAT float16Formats[] =
-    {
-        DXGI_FORMAT_R16_FLOAT,
-        DXGI_FORMAT_R16G16_FLOAT,
-        DXGI_FORMAT_R16G16B16A16_FLOAT,
-    };
-
-    DXGI_FORMAT float32Formats[] =
-    {
-        DXGI_FORMAT_R32_FLOAT,
-        DXGI_FORMAT_R32G32_FLOAT,
-        DXGI_FORMAT_R32G32B32_FLOAT,
-        DXGI_FORMAT_R32G32B32A32_FLOAT,
-    };
-
-    mFloat16TextureSupport = true;
-    mFloat16FilterSupport = true;
-    mFloat16RenderSupport = true;
-    for (unsigned int i = 0; i < ArraySize(float16Formats); i++)
-    {
-        if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport)))
-        {
-            mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
-            mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
-            mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
-        }
-        else
-        {
-            mFloat16TextureSupport = false;
-            mFloat16RenderSupport = false;
-            mFloat16FilterSupport = false;
-        }
-    }
-
-    mFloat32TextureSupport = true;
-    mFloat32FilterSupport = true;
-    mFloat32RenderSupport = true;
-    for (unsigned int i = 0; i < ArraySize(float32Formats); i++)
-    {
-        if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport)))
-        {
-            mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
-            mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
-            mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
-        }
-        else
-        {
-            mFloat32TextureSupport = false;
-            mFloat32FilterSupport = false;
-            mFloat32RenderSupport = false;
-        }
-    }
-
-    // Check compressed texture support
-    const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D;
-
-    if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport)))
-    {
-        mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
-    }
-    else
-    {
-        mDXT1TextureSupport = false;
-    }
-
-    if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport)))
-    {
-        mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
-    }
-    else
-    {
-        mDXT3TextureSupport = false;
-    }
-
-    if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport)))
-    {
-        mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
-    }
-    else
-    {
-        mDXT5TextureSupport = false;
-    }
-
-    // Check depth texture support
-    DXGI_FORMAT depthTextureFormats[] =
-    {
-        DXGI_FORMAT_D16_UNORM,
-        DXGI_FORMAT_D24_UNORM_S8_UINT,
-    };
-
-    static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL |
-                                                          D3D11_FORMAT_SUPPORT_TEXTURE2D;
-
-    mDepthTextureSupport = true;
-    for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++)
-    {
-        if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport)))
-        {
-            mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags);
-        }
-        else
-        {
-            mDepthTextureSupport = false;
-        }
-    }
-
-    return EGL_SUCCESS;
-}
-
-// do any one-time device initialization
-// NOTE: this is also needed after a device lost/reset
-// to reset the scene status and ensure the default states are reset.
-void Renderer11::initializeDevice()
-{
-    mStateCache.initialize(mDevice);
-    mInputLayoutCache.initialize(mDevice, mDeviceContext);
-
-    ASSERT(!mVertexDataManager && !mIndexDataManager);
-    mVertexDataManager = new VertexDataManager(this);
-    mIndexDataManager = new IndexDataManager(this);
-
-    markAllStateDirty();
-}
-
-int Renderer11::generateConfigs(ConfigDesc **configDescList)
-{
-    unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
-    unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
-    (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
-    int numConfigs = 0;
-    
-    for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
-    {
-        for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
-        {
-            DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
-
-            UINT formatSupport = 0;
-            HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport);
-
-            if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET))
-            {
-                DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
-
-                bool depthStencilFormatOK = true;
-
-                if (depthStencilFormat != DXGI_FORMAT_UNKNOWN)
-                {
-                    UINT formatSupport = 0;
-                    result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport);
-                    depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL);
-                }
-
-                if (depthStencilFormatOK)
-                {
-                    ConfigDesc newConfig;
-                    newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat);
-                    newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat);
-                    newConfig.multiSample = 0;     // FIXME: enumerate multi-sampling
-                    newConfig.fastConfig = true;   // Assume all DX11 format conversions to be fast
-
-                    (*configDescList)[numConfigs++] = newConfig;
-                }
-            }
-        }
-    }
-
-    return numConfigs;
-}
-
-void Renderer11::deleteConfigs(ConfigDesc *configDescList)
-{
-    delete [] (configDescList);
-}
-
-void Renderer11::sync(bool block)
-{
-    if (block)
-    {
-        HRESULT result;
-
-        if (!mSyncQuery)
-        {
-            D3D11_QUERY_DESC queryDesc;
-            queryDesc.Query = D3D11_QUERY_EVENT;
-            queryDesc.MiscFlags = 0;
-
-            result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
-            ASSERT(SUCCEEDED(result));
-        }
-
-        mDeviceContext->End(mSyncQuery);
-        mDeviceContext->Flush();
-
-        do
-        {
-            result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
-
-            // Keep polling, but allow other threads to do something useful first
-            Sleep(0);
-
-            if (testDeviceLost(true))
-            {
-                return;
-            }
-        }
-        while (result == S_FALSE);
-    }
-    else
-    {
-        mDeviceContext->Flush();
-    }
-}
-
-SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
-{
-    return rx::SwapChain11::create(this, window, shareHandle, backBufferFormat, depthBufferFormat);
-}
-
-void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
-{
-    if (type == gl::SAMPLER_PIXEL)
-    {
-        if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
-        {
-            ERR("Pixel shader sampler index %i is not valid.", index);
-            return;
-        }
-
-        if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
-        {
-            ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
-
-            if (!dxSamplerState)
-            {
-                ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
-                    "sampler state for pixel shaders at slot %i.", index);
-            }
-
-            mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
-
-            mCurPixelSamplerStates[index] = samplerState;
-        }
-
-        mForceSetPixelSamplerStates[index] = false;
-    }
-    else if (type == gl::SAMPLER_VERTEX)
-    {
-        if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
-        {
-            ERR("Vertex shader sampler index %i is not valid.", index);
-            return;
-        }
-
-        if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
-        {
-            ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
-
-            if (!dxSamplerState)
-            {
-                ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
-                    "sampler state for vertex shaders at slot %i.", index);
-            }
-
-            mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
-
-            mCurVertexSamplerStates[index] = samplerState;
-        }
-
-        mForceSetVertexSamplerStates[index] = false;
-    }
-    else UNREACHABLE();
-}
-
-void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
-{
-    ID3D11ShaderResourceView *textureSRV = NULL;
-    unsigned int serial = 0;
-    bool forceSetTexture = false;
-
-    if (texture)
-    {
-        TextureStorageInterface *texStorage = texture->getNativeTexture();
-        if (texStorage)
-        {
-            TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance());
-            textureSRV = storage11->getSRV();
-        }
-
-        // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly
-        // missing the shader resource view
-        ASSERT(textureSRV != NULL);
-
-        serial = texture->getTextureSerial();
-        forceSetTexture = texture->hasDirtyImages();
-    }
-
-    if (type == gl::SAMPLER_PIXEL)
-    {
-        if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
-        {
-            ERR("Pixel shader sampler index %i is not valid.", index);
-            return;
-        }
-
-        if (forceSetTexture || mCurPixelTextureSerials[index] != serial)
-        {
-            mDeviceContext->PSSetShaderResources(index, 1, &textureSRV);
-        }
-
-        mCurPixelTextureSerials[index] = serial;
-    }
-    else if (type == gl::SAMPLER_VERTEX)
-    {
-        if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
-        {
-            ERR("Vertex shader sampler index %i is not valid.", index);
-            return;
-        }
-
-        if (forceSetTexture || mCurVertexTextureSerials[index] != serial)
-        {
-            mDeviceContext->VSSetShaderResources(index, 1, &textureSRV);
-        }
-
-        mCurVertexTextureSerials[index] = serial;
-    }
-    else UNREACHABLE();
-}
-
-void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
-{
-    if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
-    {
-        ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled,
-                                                                              mCurDepthSize);
-        if (!dxRasterState)
-        {
-            ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default"
-                "rasterizer state.");
-        }
-
-        mDeviceContext->RSSetState(dxRasterState);
-
-        mCurRasterState = rasterState;
-    }
-
-    mForceSetRasterState = false;
-}
-
-void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor,
-                               unsigned int sampleMask)
-{
-    if (mForceSetBlendState ||
-        memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
-        memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 ||
-        sampleMask != mCurSampleMask)
-    {
-        ID3D11BlendState *dxBlendState = mStateCache.getBlendState(blendState);
-        if (!dxBlendState)
-        {
-            ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default "
-                "blend state.");
-        }
-
-        float blendColors[4] = {0.0f};
-        if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
-            blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
-        {
-            blendColors[0] = blendColor.red;
-            blendColors[1] = blendColor.green;
-            blendColors[2] = blendColor.blue;
-            blendColors[3] = blendColor.alpha;
-        }
-        else
-        {
-            blendColors[0] = blendColor.alpha;
-            blendColors[1] = blendColor.alpha;
-            blendColors[2] = blendColor.alpha;
-            blendColors[3] = blendColor.alpha;
-        }
-
-        mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
-
-        mCurBlendState = blendState;
-        mCurBlendColor = blendColor;
-        mCurSampleMask = sampleMask;
-    }
-
-    mForceSetBlendState = false;
-}
-
-void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
-                                      int stencilBackRef, bool frontFaceCCW)
-{
-    if (mForceSetDepthStencilState ||
-        memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
-        stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
-    {
-        if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
-            stencilRef != stencilBackRef ||
-            depthStencilState.stencilMask != depthStencilState.stencilBackMask)
-        {
-            ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are "
-                "invalid under WebGL.");
-            return gl::error(GL_INVALID_OPERATION);
-        }
-
-        ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
-        if (!dxDepthStencilState)
-        {
-            ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, "
-                "setting the default depth stencil state.");
-        }
-
-        mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef));
-
-        mCurDepthStencilState = depthStencilState;
-        mCurStencilRef = stencilRef;
-        mCurStencilBackRef = stencilBackRef;
-    }
-
-    mForceSetDepthStencilState = false;
-}
-
-void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
-{
-    if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
-        enabled != mScissorEnabled)
-    {
-        if (enabled)
-        {
-            D3D11_RECT rect;
-            rect.left = std::max(0, scissor.x);
-            rect.top = std::max(0, scissor.y);
-            rect.right = scissor.x + std::max(0, scissor.width);
-            rect.bottom = scissor.y + std::max(0, scissor.height);
-
-            mDeviceContext->RSSetScissorRects(1, &rect);
-        }
-
-        if (enabled != mScissorEnabled)
-        {
-            mForceSetRasterState = true;
-        }
-
-        mCurScissor = scissor;
-        mScissorEnabled = enabled;
-    }
-
-    mForceSetScissor = false;
-}
-
-bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, 
-                             bool ignoreViewport)
-{
-    gl::Rectangle actualViewport = viewport;
-    float actualZNear = gl::clamp01(zNear);
-    float actualZFar = gl::clamp01(zFar);
-    if (ignoreViewport)
-    {
-        actualViewport.x = 0;
-        actualViewport.y = 0;
-        actualViewport.width = mRenderTargetDesc.width;
-        actualViewport.height = mRenderTargetDesc.height;
-        actualZNear = 0.0f;
-        actualZFar = 1.0f;
-    }
-
-    // Get D3D viewport bounds, which depends on the feature level
-    const Range& viewportBounds = getViewportBounds();
-
-    // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
-    D3D11_VIEWPORT dxViewport;
-    dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end);
-    dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end);
-    dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension());
-    dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension());
-    dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX));
-    dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY));
-    dxViewport.MinDepth = actualZNear;
-    dxViewport.MaxDepth = actualZFar;
-
-    if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
-    {
-        return false;   // Nothing to render
-    }
-
-    bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
-                           actualZNear != mCurNear || actualZFar != mCurFar;
-
-    if (viewportChanged)
-    {
-        mDeviceContext->RSSetViewports(1, &dxViewport);
-
-        mCurViewport = actualViewport;
-        mCurNear = actualZNear;
-        mCurFar = actualZFar;
-
-        mPixelConstants.viewCoords[0] = actualViewport.width  * 0.5f;
-        mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
-        mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width  * 0.5f);
-        mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
-
-        mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
-        mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
-
-        mVertexConstants.depthRange[0] = actualZNear;
-        mVertexConstants.depthRange[1] = actualZFar;
-        mVertexConstants.depthRange[2] = actualZFar - actualZNear;
-
-        mPixelConstants.depthRange[0] = actualZNear;
-        mPixelConstants.depthRange[1] = actualZFar;
-        mPixelConstants.depthRange[2] = actualZFar - actualZNear;
-    }
-
-    mForceSetViewport = false;
-    return true;
-}
-
-bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
-{
-    D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
-
-    switch (mode)
-    {
-      case GL_POINTS:         primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;   break;
-      case GL_LINES:          primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;      break;
-      case GL_LINE_LOOP:      primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;     break;
-      case GL_LINE_STRIP:     primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;     break;
-      case GL_TRIANGLES:      primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;  break;
-      case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break;
-          // emulate fans via rewriting index buffer
-      case GL_TRIANGLE_FAN:   primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;  break;
-      default:
-        return gl::error(GL_INVALID_ENUM, false);
-    }
-
-    mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
-
-    return count > 0;
-}
-
-bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
-{
-    // Get the color render buffer and serial
-    // Also extract the render target dimensions and view
-    unsigned int renderTargetWidth = 0;
-    unsigned int renderTargetHeight = 0;
-    GLenum renderTargetFormat = 0;
-    unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0};
-    ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
-    bool missingColorRenderTarget = true;
-
-    for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-    {
-        const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment);
-
-        if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE)
-        {
-            // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order)
-            ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
-
-            gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment);
-
-            if (!colorbuffer)
-            {
-                ERR("render target pointer unexpectedly null.");
-                return false;
-            }
-
-            // check for zero-sized default framebuffer, which is a special case.
-            // in this case we do not wish to modify any state and just silently return false.
-            // this will not report any gl error but will cause the calling method to return.
-            if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
-            {
-                return false;
-            }
-
-            renderTargetSerials[colorAttachment] = colorbuffer->getSerial();
-
-            // Extract the render target dimensions and view
-            RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
-            if (!renderTarget)
-            {
-                ERR("render target pointer unexpectedly null.");
-                return false;
-            }
-
-            framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
-            if (!framebufferRTVs[colorAttachment])
-            {
-                ERR("render target view pointer unexpectedly null.");
-                return false;
-            }
-
-            if (missingColorRenderTarget)
-            {
-                renderTargetWidth = colorbuffer->getWidth();
-                renderTargetHeight = colorbuffer->getHeight();
-                renderTargetFormat = colorbuffer->getActualFormat();
-                missingColorRenderTarget = false;
-            }
-        }
-    }
-
-    // Get the depth stencil render buffer and serials
-    gl::Renderbuffer *depthStencil = NULL;
-    unsigned int depthbufferSerial = 0;
-    unsigned int stencilbufferSerial = 0;
-    if (framebuffer->getDepthbufferType() != GL_NONE)
-    {
-        depthStencil = framebuffer->getDepthbuffer();
-        if (!depthStencil)
-        {
-            ERR("Depth stencil pointer unexpectedly null.");
-            SafeRelease(framebufferRTVs);
-            return false;
-        }
-
-        depthbufferSerial = depthStencil->getSerial();
-    }
-    else if (framebuffer->getStencilbufferType() != GL_NONE)
-    {
-        depthStencil = framebuffer->getStencilbuffer();
-        if (!depthStencil)
-        {
-            ERR("Depth stencil pointer unexpectedly null.");
-            SafeRelease(framebufferRTVs);
-            return false;
-        }
-
-        stencilbufferSerial = depthStencil->getSerial();
-    }
-
-    // Extract the depth stencil sizes and view
-    unsigned int depthSize = 0;
-    unsigned int stencilSize = 0;
-    ID3D11DepthStencilView* framebufferDSV = NULL;
-    if (depthStencil)
-    {
-        RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil());
-        if (!depthStencilRenderTarget)
-        {
-            ERR("render target pointer unexpectedly null.");
-            SafeRelease(framebufferRTVs);
-            return false;
-        }
-
-        framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
-        if (!framebufferDSV)
-        {
-            ERR("depth stencil view pointer unexpectedly null.");
-            SafeRelease(framebufferRTVs);
-            return false;
-        }
-
-        // If there is no render buffer, the width, height and format values come from
-        // the depth stencil
-        if (missingColorRenderTarget)
-        {
-            renderTargetWidth = depthStencil->getWidth();
-            renderTargetHeight = depthStencil->getHeight();
-            renderTargetFormat = depthStencil->getActualFormat();
-        }
-
-        depthSize = depthStencil->getDepthSize();
-        stencilSize = depthStencil->getStencilSize();
-    }
-
-    // Apply the render target and depth stencil
-    if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
-        memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
-        depthbufferSerial != mAppliedDepthbufferSerial ||
-        stencilbufferSerial != mAppliedStencilbufferSerial)
-    {
-        mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV);
-
-        mRenderTargetDesc.width = renderTargetWidth;
-        mRenderTargetDesc.height = renderTargetHeight;
-        mRenderTargetDesc.format = renderTargetFormat;
-        mForceSetViewport = true;
-        mForceSetScissor = true;
-
-        if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
-        {
-            mCurDepthSize = depthSize;
-            mForceSetRasterState = true;
-        }
-
-        mCurStencilSize = stencilSize;
-
-        for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
-        {
-            mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
-        }
-        mAppliedDepthbufferSerial = depthbufferSerial;
-        mAppliedStencilbufferSerial = stencilbufferSerial;
-        mRenderTargetDescInitialized = true;
-        mDepthStencilInitialized = true;
-    }
-
-    SafeRelease(framebufferRTVs);
-    SafeRelease(framebufferDSV);
-
-    return true;
-}
-
-GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
-{
-    TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
-    GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
-    if (err != GL_NO_ERROR)
-    {
-        return err;
-    }
-
-    return mInputLayoutCache.applyVertexBuffers(attributes, programBinary);
-}
-
-GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
-{
-    GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
-
-    if (err == GL_NO_ERROR)
-    {
-        if (indexInfo->storage)
-        {
-            if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset)
-            {
-                BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage);
-                IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
-
-                mDeviceContext->IASetIndexBuffer(storage->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
-
-                mAppliedIBSerial = 0;
-                mAppliedStorageIBSerial = storage->getSerial();
-                mAppliedIBOffset = indexInfo->startOffset;
-            }
-        }
-        else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset)
-        {
-            IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
-
-            mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
-
-            mAppliedIBSerial = indexInfo->serial;
-            mAppliedStorageIBSerial = 0;
-            mAppliedIBOffset = indexInfo->startOffset;
-        }
-    }
-
-    return err;
-}
-
-void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
-{
-    if (mode == GL_LINE_LOOP)
-    {
-        drawLineLoop(count, GL_NONE, NULL, 0, NULL);
-    }
-    else if (mode == GL_TRIANGLE_FAN)
-    {
-        drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
-    }
-    else if (instances > 0)
-    {
-        mDeviceContext->DrawInstanced(count, instances, 0, 0);
-    }
-    else
-    {
-        mDeviceContext->Draw(count, 0);
-    }
-}
-
-void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances)
-{
-    if (mode == GL_LINE_LOOP)
-    {
-        drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
-    }
-    else if (mode == GL_TRIANGLE_FAN)
-    {
-        drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances);
-    }
-    else if (instances > 0)
-    {
-        mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast<int>(indexInfo.minIndex), 0);
-    }
-    else
-    {
-        mDeviceContext->DrawIndexed(count, 0, -static_cast<int>(indexInfo.minIndex));
-    }
-}
-
-void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
-{
-    // Get the raw indices for an indexed draw
-    if (type != GL_NONE && elementArrayBuffer)
-    {
-        gl::Buffer *indexBuffer = elementArrayBuffer;
-        BufferStorage *storage = indexBuffer->getStorage();
-        intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
-    }
-
-    if (!mLineLoopIB)
-    {
-        mLineLoopIB = new StreamingIndexBufferInterface(this);
-        if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
-        {
-            delete mLineLoopIB;
-            mLineLoopIB = NULL;
-
-            ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    if (static_cast<unsigned int>(count + 1) > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
-    {
-        ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    const unsigned int spaceNeeded = (count + 1) * sizeof(unsigned int);
-    if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
-    {
-        ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    void* mappedMemory = NULL;
-    int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
-    if (offset == -1 || mappedMemory == NULL)
-    {
-        ERR("Could not map index buffer for GL_LINE_LOOP.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
-    unsigned int indexBufferOffset = static_cast<unsigned int>(offset);
-
-    switch (type)
-    {
-      case GL_NONE:   // Non-indexed draw
-        for (int i = 0; i < count; i++)
-        {
-            data[i] = i;
-        }
-        data[count] = 0;
-        break;
-      case GL_UNSIGNED_BYTE:
-        for (int i = 0; i < count; i++)
-        {
-            data[i] = static_cast<const GLubyte*>(indices)[i];
-        }
-        data[count] = static_cast<const GLubyte*>(indices)[0];
-        break;
-      case GL_UNSIGNED_SHORT:
-        for (int i = 0; i < count; i++)
-        {
-            data[i] = static_cast<const GLushort*>(indices)[i];
-        }
-        data[count] = static_cast<const GLushort*>(indices)[0];
-        break;
-      case GL_UNSIGNED_INT:
-        for (int i = 0; i < count; i++)
-        {
-            data[i] = static_cast<const GLuint*>(indices)[i];
-        }
-        data[count] = static_cast<const GLuint*>(indices)[0];
-        break;
-      default: UNREACHABLE();
-    }
-
-    if (!mLineLoopIB->unmapBuffer())
-    {
-        ERR("Could not unmap index buffer for GL_LINE_LOOP.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
-    {
-        IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
-
-        mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
-        mAppliedIBSerial = mLineLoopIB->getSerial();
-        mAppliedStorageIBSerial = 0;
-        mAppliedIBOffset = indexBufferOffset;
-    }
-
-    mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
-}
-
-void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
-{
-    // Get the raw indices for an indexed draw
-    if (type != GL_NONE && elementArrayBuffer)
-    {
-        gl::Buffer *indexBuffer = elementArrayBuffer;
-        BufferStorage *storage = indexBuffer->getStorage();
-        intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
-    }
-
-    if (!mTriangleFanIB)
-    {
-        mTriangleFanIB = new StreamingIndexBufferInterface(this);
-        if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
-        {
-            delete mTriangleFanIB;
-            mTriangleFanIB = NULL;
-
-            ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    const unsigned int numTris = count - 2;
-
-    if (numTris * 3 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
-    {
-        ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
-    if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
-    {
-        ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    void* mappedMemory = NULL;
-    int offset = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory);
-    if (offset == -1 || mappedMemory == NULL)
-    {
-        ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
-    unsigned int indexBufferOffset = static_cast<unsigned int>(offset);
-
-    switch (type)
-    {
-      case GL_NONE:   // Non-indexed draw
-        for (unsigned int i = 0; i < numTris; i++)
-        {
-            data[i*3 + 0] = 0;
-            data[i*3 + 1] = i + 1;
-            data[i*3 + 2] = i + 2;
-        }
-        break;
-      case GL_UNSIGNED_BYTE:
-        for (unsigned int i = 0; i < numTris; i++)
-        {
-            data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
-            data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
-            data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
-        }
-        break;
-      case GL_UNSIGNED_SHORT:
-        for (unsigned int i = 0; i < numTris; i++)
-        {
-            data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
-            data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
-            data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
-        }
-        break;
-      case GL_UNSIGNED_INT:
-        for (unsigned int i = 0; i < numTris; i++)
-        {
-            data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
-            data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
-            data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
-        }
-        break;
-      default: UNREACHABLE();
-    }
-
-    if (!mTriangleFanIB->unmapBuffer())
-    {
-        ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
-    {
-        IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer());
-
-        mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
-        mAppliedIBSerial = mTriangleFanIB->getSerial();
-        mAppliedStorageIBSerial = 0;
-        mAppliedIBOffset = indexBufferOffset;
-    }
-
-    if (instances > 0)
-    {
-        mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0);
-    }
-    else
-    {
-        mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex);
-    }
-}
-
-void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
-{
-    unsigned int programBinarySerial = programBinary->getSerial();
-    const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial);
-
-    if (updateProgramState)
-    {
-        ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
-        ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
-
-        ID3D11VertexShader *vertexShader = NULL;
-        if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader();
-
-        ID3D11PixelShader *pixelShader = NULL;
-        if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader();
-
-        mDeviceContext->PSSetShader(pixelShader, NULL, 0);
-        mDeviceContext->VSSetShader(vertexShader, NULL, 0);
-
-        programBinary->dirtyAllUniforms();
-
-        mAppliedProgramBinarySerial = programBinarySerial;
-    }
-
-    // Only use the geometry shader currently for point sprite drawing
-    const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode);
-
-    if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive)
-    {
-        if (usesGeometryShader)
-        {
-            ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
-            ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader();
-            mDeviceContext->GSSetShader(geometryShader, NULL, 0);
-        }
-        else
-        {
-            mDeviceContext->GSSetShader(NULL, NULL, 0);
-        }
-
-        mIsGeometryShaderActive = usesGeometryShader;
-    }
-}
-
-void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
-{
-    ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
-    ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable());
-
-    unsigned int totalRegisterCountVS = 0;
-    unsigned int totalRegisterCountPS = 0;
-
-    bool vertexUniformsDirty = false;
-    bool pixelUniformsDirty = false;
-
-    for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
-    {
-        const gl::Uniform *uniform = *uniform_iterator;
-
-        if (uniform->vsRegisterIndex >= 0)
-        {
-            totalRegisterCountVS += uniform->registerCount;
-            vertexUniformsDirty = vertexUniformsDirty || uniform->dirty;
-        }
-
-        if (uniform->psRegisterIndex >= 0)
-        {
-            totalRegisterCountPS += uniform->registerCount;
-            pixelUniformsDirty = pixelUniformsDirty || uniform->dirty;
-        }
-    }
-
-    ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS);
-    ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS);
-
-    float (*mapVS)[4] = NULL;
-    float (*mapPS)[4] = NULL;
-
-    if (totalRegisterCountVS > 0 && vertexUniformsDirty)
-    {
-        D3D11_MAPPED_SUBRESOURCE map = {0};
-        HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
-        ASSERT(SUCCEEDED(result));
-        mapVS = (float(*)[4])map.pData;
-    }
-
-    if (totalRegisterCountPS > 0 && pixelUniformsDirty)
-    {
-        D3D11_MAPPED_SUBRESOURCE map = {0};
-        HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
-        ASSERT(SUCCEEDED(result));
-        mapPS = (float(*)[4])map.pData;
-    }
-
-    for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
-    {
-        gl::Uniform *uniform = *uniform_iterator;
-
-        if (uniform->type !=  GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE)
-        {
-            if (uniform->vsRegisterIndex >= 0 && mapVS)
-            {
-                memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
-            }
-
-            if (uniform->psRegisterIndex >= 0 && mapPS)
-            {
-                memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
-            }
-        }
-
-        uniform->dirty = false;
-    }
-
-    if (mapVS)
-    {
-        mDeviceContext->Unmap(vertexConstantBuffer, 0);
-    }
-
-    if (mapPS)
-    {
-        mDeviceContext->Unmap(pixelConstantBuffer, 0);
-    }
-    
-    mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
-    mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
-
-    // Driver uniforms
-    if (!mDriverConstantBufferVS)
-    {
-        D3D11_BUFFER_DESC constantBufferDescription = {0};
-        constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants);
-        constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
-        constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
-        constantBufferDescription.CPUAccessFlags = 0;
-        constantBufferDescription.MiscFlags = 0;
-        constantBufferDescription.StructureByteStride = 0;
-
-        HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::ResourceTracker::Track(mDriverConstantBufferVS);
-
-        mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS);
-    }
-
-    if (!mDriverConstantBufferPS)
-    {
-        D3D11_BUFFER_DESC constantBufferDescription = {0};
-        constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants);
-        constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
-        constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
-        constantBufferDescription.CPUAccessFlags = 0;
-        constantBufferDescription.MiscFlags = 0;
-        constantBufferDescription.StructureByteStride = 0;
-
-        HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::ResourceTracker::Track(mDriverConstantBufferPS);
-
-        mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
-    }
-
-    if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
-    {
-        mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0);
-        memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants));
-    }
-
-    if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
-    {
-        mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0);
-        memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
-    }
-
-    // needed for the point sprite geometry shader
-    mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
-}
-
-void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
-{
-     bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
-     bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
-                                 !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
-                                   clearParams.colorMaskBlue && alphaUnmasked);
-
-     unsigned int stencilUnmasked = 0x0;
-     if (frameBuffer->hasStencil())
-     {
-         unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
-         stencilUnmasked = (0x1 << stencilSize) - 1;
-     }
-     bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
-                                   (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
-
-     bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 ||
-                                                   mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width ||
-                                                   mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height);
-
-     if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear)
-     {
-         maskedClear(clearParams, frameBuffer->usingExtendedDrawBuffers());
-     }
-     else
-     {
-         if (clearParams.mask & GL_COLOR_BUFFER_BIT)
-         {
-             for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-             {
-                 if (frameBuffer->isEnabledColorAttachment(colorAttachment))
-                 {
-                     gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment);
-                     if (renderbufferObject)
-                     {
-                        RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
-                        if (!renderTarget)
-                        {
-                            ERR("render target pointer unexpectedly null.");
-                            return;
-                        }
-
-                        ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
-                        if (!framebufferRTV)
-                        {
-                            ERR("render target view pointer unexpectedly null.");
-                            return;
-                        }
-
-                        const float clearValues[4] = { clearParams.colorClearValue.red,
-                                                       clearParams.colorClearValue.green,
-                                                       clearParams.colorClearValue.blue,
-                                                       clearParams.colorClearValue.alpha };
-                        mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
-
-                        framebufferRTV->Release();
-                    }
-                 }
-             }
-        }
-        if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT)
-        {
-            gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer();
-            if (renderbufferObject)
-            {
-                RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil());
-                if (!renderTarget)
-                {
-                    ERR("render target pointer unexpectedly null.");
-                    return;
-                }
-
-                ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
-                if (!framebufferDSV)
-                {
-                    ERR("depth stencil view pointer unexpectedly null.");
-                    return;
-                }
-
-                UINT clearFlags = 0;
-                if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
-                {
-                    clearFlags |= D3D11_CLEAR_DEPTH;
-                }
-                if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
-                {
-                    clearFlags |= D3D11_CLEAR_STENCIL;
-                }
-
-                float depthClear = gl::clamp01(clearParams.depthClearValue);
-                UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
-
-                mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
-
-                framebufferDSV->Release();
-            }
-        }
-    }
-}
-
-void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers)
-{
-    HRESULT result;
-
-    if (!mClearResourcesInitialized)
-    {
-        ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS);
-
-        D3D11_BUFFER_DESC vbDesc;
-        vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4;
-        vbDesc.Usage = D3D11_USAGE_DYNAMIC;
-        vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
-        vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-        vbDesc.MiscFlags = 0;
-        vbDesc.StructureByteStride = 0;
-
-        result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer");
-        d3d11::ResourceTracker::Track(mClearVB);
-
-        D3D11_INPUT_ELEMENT_DESC quadLayout[] =
-        {
-            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-            { "COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-        };
-
-        result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout");
-
-        result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader");
-
-        result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)");
-
-        result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)");
-
-        D3D11_RASTERIZER_DESC rsScissorDesc;
-        rsScissorDesc.FillMode = D3D11_FILL_SOLID;
-        rsScissorDesc.CullMode = D3D11_CULL_NONE;
-        rsScissorDesc.FrontCounterClockwise = FALSE;
-        rsScissorDesc.DepthBias = 0;
-        rsScissorDesc.DepthBiasClamp = 0.0f;
-        rsScissorDesc.SlopeScaledDepthBias = 0.0f;
-        rsScissorDesc.DepthClipEnable = FALSE;
-        rsScissorDesc.ScissorEnable = TRUE;
-        rsScissorDesc.MultisampleEnable = FALSE;
-        rsScissorDesc.AntialiasedLineEnable = FALSE;
-
-        result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state");
-
-        D3D11_RASTERIZER_DESC rsNoScissorDesc;
-        rsNoScissorDesc.FillMode = D3D11_FILL_SOLID;
-        rsNoScissorDesc.CullMode = D3D11_CULL_NONE;
-        rsNoScissorDesc.FrontCounterClockwise = FALSE;
-        rsNoScissorDesc.DepthBias = 0;
-        rsNoScissorDesc.DepthBiasClamp = 0.0f;
-        rsNoScissorDesc.SlopeScaledDepthBias = 0.0f;
-        rsNoScissorDesc.DepthClipEnable = FALSE;
-        rsNoScissorDesc.ScissorEnable = FALSE;
-        rsNoScissorDesc.MultisampleEnable = FALSE;
-        rsNoScissorDesc.AntialiasedLineEnable = FALSE;
-
-        result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state");
-
-        mClearResourcesInitialized = true;
-    }
-
-    // Prepare the depth stencil state to write depth values if the depth should be cleared
-    // and stencil values if the stencil should be cleared
-    gl::DepthStencilState glDSState;
-    glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
-    glDSState.depthFunc = GL_ALWAYS;
-    glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
-    glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0;
-    glDSState.stencilFunc = GL_ALWAYS;
-    glDSState.stencilMask = 0;
-    glDSState.stencilFail = GL_REPLACE;
-    glDSState.stencilPassDepthFail = GL_REPLACE;
-    glDSState.stencilPassDepthPass = GL_REPLACE;
-    glDSState.stencilWritemask = clearParams.stencilWriteMask;
-    glDSState.stencilBackFunc = GL_ALWAYS;
-    glDSState.stencilBackMask = 0;
-    glDSState.stencilBackFail = GL_REPLACE;
-    glDSState.stencilBackPassDepthFail = GL_REPLACE;
-    glDSState.stencilBackPassDepthPass = GL_REPLACE;
-    glDSState.stencilBackWritemask = clearParams.stencilWriteMask;
-
-    int stencilClear = clearParams.stencilClearValue & 0x000000FF;
-
-    ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState);
-
-    // Prepare the blend state to use a write mask if the color buffer should be cleared
-    gl::BlendState glBlendState;
-    glBlendState.blend = false;
-    glBlendState.sourceBlendRGB = GL_ONE;
-    glBlendState.destBlendRGB = GL_ZERO;
-    glBlendState.sourceBlendAlpha = GL_ONE;
-    glBlendState.destBlendAlpha = GL_ZERO;
-    glBlendState.blendEquationRGB = GL_FUNC_ADD;
-    glBlendState.blendEquationAlpha = GL_FUNC_ADD;
-    glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false;
-    glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false;
-    glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false;
-    glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false;
-    glBlendState.sampleAlphaToCoverage = false;
-    glBlendState.dither = false;
-
-    static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
-    static const UINT sampleMask = 0xFFFFFFFF;
-
-    ID3D11BlendState *blendState = mStateCache.getBlendState(glBlendState);
-
-    // Set the vertices
-    D3D11_MAPPED_SUBRESOURCE mappedResource;
-    result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-    if (FAILED(result))
-    {
-        ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result);
-        return;
-    }
-
-    d3d11::PositionDepthColorVertex *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex*>(mappedResource.pData);
-
-    float depthClear = gl::clamp01(clearParams.depthClearValue);
-    d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f,  1.0f, depthClear, clearParams.colorClearValue);
-    d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue);
-    d3d11::SetPositionDepthColorVertex(&vertices[2],  1.0f,  1.0f, depthClear, clearParams.colorClearValue);
-    d3d11::SetPositionDepthColorVertex(&vertices[3],  1.0f, -1.0f, depthClear, clearParams.colorClearValue);
-
-    mDeviceContext->Unmap(mClearVB, 0);
-
-    // Apply state
-    mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
-    mDeviceContext->OMSetDepthStencilState(dsState, stencilClear);
-    mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS);
-
-    // Apply shaders
-    ID3D11PixelShader *pixelShader = usingExtendedDrawBuffers ? mClearMultiplePS : mClearSinglePS;
-
-    mDeviceContext->IASetInputLayout(mClearIL);
-    mDeviceContext->VSSetShader(mClearVS, NULL, 0);
-    mDeviceContext->PSSetShader(pixelShader, NULL, 0);
-    mDeviceContext->GSSetShader(NULL, NULL, 0);
-
-    // Apply vertex buffer
-    static UINT stride = sizeof(d3d11::PositionDepthColorVertex);
-    static UINT startIdx = 0;
-    mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx);
-    mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-
-    // Draw the clear quad
-    mDeviceContext->Draw(4, 0);
-
-    // Clean up
-    markAllStateDirty();
-}
-
-void Renderer11::markAllStateDirty()
-{
-    for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
-    {
-        mAppliedRenderTargetSerials[rtIndex] = 0;
-    }
-    mAppliedDepthbufferSerial = 0;
-    mAppliedStencilbufferSerial = 0;
-    mDepthStencilInitialized = false;
-    mRenderTargetDescInitialized = false;
-
-    for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
-    {
-        mForceSetVertexSamplerStates[i] = true;
-        mCurVertexTextureSerials[i] = 0;
-    }
-    for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
-    {
-        mForceSetPixelSamplerStates[i] = true;
-        mCurPixelTextureSerials[i] = 0;
-    }
-
-    mForceSetBlendState = true;
-    mForceSetRasterState = true;
-    mForceSetDepthStencilState = true;
-    mForceSetScissor = true;
-    mForceSetViewport = true;
-
-    mAppliedIBSerial = 0;
-    mAppliedStorageIBSerial = 0;
-    mAppliedIBOffset = 0;
-
-    mAppliedProgramBinarySerial = 0;
-    memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants));
-    memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants));
-}
-
-void Renderer11::releaseDeviceResources()
-{
-    mStateCache.clear();
-    mInputLayoutCache.clear();
-
-    delete mVertexDataManager;
-    mVertexDataManager = NULL;
-
-    delete mIndexDataManager;
-    mIndexDataManager = NULL;
-
-    delete mLineLoopIB;
-    mLineLoopIB = NULL;
-
-    delete mTriangleFanIB;
-    mTriangleFanIB = NULL;
-
-    SafeRelease(mCopyVB);
-    SafeRelease(mCopySampler);
-    SafeRelease(mCopyIL);
-    SafeRelease(mCopyIL);
-    SafeRelease(mCopyVS);
-    SafeRelease(mCopyRGBAPS);
-    SafeRelease(mCopyRGBPS);
-    SafeRelease(mCopyLumPS);
-    SafeRelease(mCopyLumAlphaPS);
-
-    mCopyResourcesInitialized = false;
-
-    SafeRelease(mClearVB);
-    SafeRelease(mClearIL);
-    SafeRelease(mClearVS);
-    SafeRelease(mClearSinglePS);
-    SafeRelease(mClearMultiplePS);
-    SafeRelease(mClearScissorRS);
-    SafeRelease(mClearNoScissorRS);
-
-    mClearResourcesInitialized = false;
-
-    SafeRelease(mDriverConstantBufferVS);
-    SafeRelease(mDriverConstantBufferPS);
-    SafeRelease(mSyncQuery);
-}
-
-void Renderer11::notifyDeviceLost()
-{
-    mDeviceLost = true;
-    mDisplay->notifyDeviceLost();
-}
-
-bool Renderer11::isDeviceLost()
-{
-    return mDeviceLost;
-}
-
-// set notify to true to broadcast a message to all contexts of the device loss
-bool Renderer11::testDeviceLost(bool notify)
-{
-    bool isLost = false;
-
-    // GetRemovedReason is used to test if the device is removed
-    HRESULT result = mDevice->GetDeviceRemovedReason();
-    isLost = d3d11::isDeviceLostError(result);
-
-    if (isLost)
-    {
-        // Log error if this is a new device lost event
-        if (mDeviceLost == false)
-        {
-            ERR("The D3D11 device was removed: 0x%08X", result);
-        }
-
-        // ensure we note the device loss --
-        // we'll probably get this done again by notifyDeviceLost
-        // but best to remember it!
-        // Note that we don't want to clear the device loss status here
-        // -- this needs to be done by resetDevice
-        mDeviceLost = true;
-        if (notify)
-        {
-            notifyDeviceLost();
-        }
-    }
-
-    return isLost;
-}
-
-bool Renderer11::testDeviceResettable()
-{
-    // determine if the device is resettable by creating a dummy device
-    PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
-
-    if (D3D11CreateDevice == NULL)
-    {
-        return false;
-    }
-
-    D3D_FEATURE_LEVEL featureLevels[] =
-    {
-        D3D_FEATURE_LEVEL_11_0,
-        D3D_FEATURE_LEVEL_10_1,
-        D3D_FEATURE_LEVEL_10_0,
-    };
-
-    ID3D11Device* dummyDevice;
-    D3D_FEATURE_LEVEL dummyFeatureLevel;
-    ID3D11DeviceContext* dummyContext;
-
-    HRESULT result = D3D11CreateDevice(NULL,
-                                       D3D_DRIVER_TYPE_HARDWARE,
-                                       NULL,
-                                       #if defined(_DEBUG)
-                                       D3D11_CREATE_DEVICE_DEBUG,
-                                       #else
-                                       0,
-                                       #endif
-                                       featureLevels,
-                                       ArraySize(featureLevels),
-                                       D3D11_SDK_VERSION,
-                                       &dummyDevice,
-                                       &dummyFeatureLevel,
-                                       &dummyContext);
-
-    if (!mDevice || FAILED(result))
-    {
-        return false;
-    }
-
-    dummyContext->Release();
-    dummyDevice->Release();
-
-    return true;
-}
-
-void Renderer11::release()
-{
-    releaseDeviceResources();
-
-    if (mDxgiFactory)
-    {
-        mDxgiFactory->Release();
-        mDxgiFactory = NULL;
-    }
-
-    if (mDxgiAdapter)
-    {
-        mDxgiAdapter->Release();
-        mDxgiAdapter = NULL;
-    }
-
-    if (mDeviceContext)
-    {
-        mDeviceContext->ClearState();
-        mDeviceContext->Flush();
-        mDeviceContext->Release();
-        mDeviceContext = NULL;
-    }
-
-    if (mDevice)
-    {
-        mDevice->Release();
-        mDevice = NULL;
-    }
-
-    if (mD3d11Module)
-    {
-        FreeLibrary(mD3d11Module);
-        mD3d11Module = NULL;
-    }
-
-    if (mDxgiModule)
-    {
-        FreeLibrary(mDxgiModule);
-        mDxgiModule = NULL;
-    }
-}
-
-bool Renderer11::resetDevice()
-{
-    // recreate everything
-    release();
-    EGLint result = initialize();
-
-    if (result != EGL_SUCCESS)
-    {
-        ERR("Could not reinitialize D3D11 device: %08X", result);
-        return false;
-    }
-
-    mDeviceLost = false;
-
-    return true;
-}
-
-void *Renderer11::getDeviceRaw()
-{
-    ID3D11Device *device = getDevice();
-    if (device)
-      device->AddRef();
-
-    return reinterpret_cast<void *>(device);
-}
-
-DWORD Renderer11::getAdapterVendor() const
-{
-    return mAdapterDescription.VendorId;
-}
-
-std::string Renderer11::getRendererDescription() const
-{
-    std::ostringstream rendererString;
-
-    rendererString << mDescription;
-    rendererString << " Direct3D11";
-
-    rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel();
-    rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel();
-
-    return rendererString.str();
-}
-
-GUID Renderer11::getAdapterIdentifier() const
-{
-    // Use the adapter LUID as our adapter ID
-    // This number is local to a machine is only guaranteed to be unique between restarts
-    META_ASSERT(sizeof(LUID) <= sizeof(GUID));
-    GUID adapterId = {0};
-    memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID));
-    return adapterId;
-}
-
-bool Renderer11::getBGRATextureSupport() const
-{
-    return mBGRATextureSupport;
-}
-
-bool Renderer11::getDXT1TextureSupport()
-{
-    return mDXT1TextureSupport;
-}
-
-bool Renderer11::getDXT3TextureSupport()
-{
-    return mDXT3TextureSupport;
-}
-
-bool Renderer11::getDXT5TextureSupport()
-{
-    return mDXT5TextureSupport;
-}
-
-bool Renderer11::getDepthTextureSupport() const
-{
-    return mDepthTextureSupport;
-}
-
-bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable)
-{
-    *renderable = mFloat32RenderSupport;
-    *filtering = mFloat32FilterSupport;
-    return mFloat32TextureSupport;
-}
-
-bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable)
-{
-    *renderable = mFloat16RenderSupport;
-    *filtering = mFloat16FilterSupport;
-    return mFloat16TextureSupport;
-}
-
-bool Renderer11::getLuminanceTextureSupport()
-{
-    return false;
-}
-
-bool Renderer11::getLuminanceAlphaTextureSupport()
-{
-    return false;
-}
-
-bool Renderer11::getTextureFilterAnisotropySupport() const
-{
-    return true;
-}
-
-float Renderer11::getTextureMaxAnisotropy() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-        return D3D11_MAX_MAXANISOTROPY;
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return D3D10_MAX_MAXANISOTROPY;
-      default: UNREACHABLE();
-        return 0;
-    }
-}
-
-bool Renderer11::getEventQuerySupport()
-{
-    return true;
-}
-
-Range Renderer11::getViewportBounds() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-        return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX);
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX);
-      default: UNREACHABLE();
-        return Range(0, 0);
-    }
-}
-
-unsigned int Renderer11::getMaxVertexTextureImageUnits() const
-{
-    META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4;
-      default: UNREACHABLE();
-        return 0;
-    }
-}
-
-unsigned int Renderer11::getMaxCombinedTextureImageUnits() const
-{
-    return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
-}
-
-unsigned int Renderer11::getReservedVertexUniformVectors() const
-{
-    return 0;   // Driver uniforms are stored in a separate constant buffer
-}
-
-unsigned int Renderer11::getReservedFragmentUniformVectors() const
-{
-    return 0;   // Driver uniforms are stored in a separate constant buffer
-}
-
-unsigned int Renderer11::getMaxVertexUniformVectors() const
-{
-    META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
-    ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
-    return MAX_VERTEX_UNIFORM_VECTORS_D3D11;
-}
-
-unsigned int Renderer11::getMaxFragmentUniformVectors() const
-{
-    META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
-    ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
-    return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11;
-}
-
-unsigned int Renderer11::getMaxVaryingVectors() const
-{
-    META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT);
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-        return D3D11_VS_OUTPUT_REGISTER_COUNT;
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return D3D10_VS_OUTPUT_REGISTER_COUNT;
-      default: UNREACHABLE();
-        return 0;
-    }
-}
-
-bool Renderer11::getNonPower2TextureSupport() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return true;
-      default: UNREACHABLE();
-        return false;
-    }
-}
-
-bool Renderer11::getOcclusionQuerySupport() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return true;
-      default: UNREACHABLE();
-        return false;
-    }
-}
-
-bool Renderer11::getInstancingSupport() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return true;
-      default: UNREACHABLE();
-        return false;
-    }
-}
-
-bool Renderer11::getShareHandleSupport() const
-{
-    // We only currently support share handles with BGRA surfaces, because
-    // chrome needs BGRA. Once chrome fixes this, we should always support them.
-    // PIX doesn't seem to support using share handles, so disable them.
-    return getBGRATextureSupport() && !gl::perfActive();
-}
-
-bool Renderer11::getDerivativeInstructionSupport() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return true;
-      default: UNREACHABLE();
-        return false;
-    }
-}
-
-bool Renderer11::getPostSubBufferSupport() const
-{
-    // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2.
-    return false;
-}
-
-int Renderer11::getMajorShaderModel() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION;   // 5
-      case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION;   // 4
-      default: UNREACHABLE();      return 0;
-    }
-}
-
-int Renderer11::getMinorShaderModel() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION;   // 0
-      case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION;   // 0
-      default: UNREACHABLE();      return 0;
-    }
-}
-
-float Renderer11::getMaxPointSize() const
-{
-    // choose a reasonable maximum. we enforce this in the shader.
-    // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size)
-    return 1024.0f;
-}
-
-int Renderer11::getMaxViewportDimension() const
-{
-    // Maximum viewport size must be at least as large as the largest render buffer (or larger).
-    // In our case return the maximum texture size, which is the maximum render buffer size.
-    META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX);
-    META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX);
-
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: 
-        return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 16384
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: 
-        return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 8192
-      default: UNREACHABLE();      
-        return 0;
-    }
-}
-
-int Renderer11::getMaxTextureWidth() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 16384
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 8192
-      default: UNREACHABLE();      return 0;
-    }
-}
-
-int Renderer11::getMaxTextureHeight() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 16384
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;   // 8192
-      default: UNREACHABLE();      return 0;
-    }
-}
-
-bool Renderer11::get32BitIndexSupport() const
-{
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0: 
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32;   // true
-      default: UNREACHABLE();      return false;
-    }
-}
-
-int Renderer11::getMinSwapInterval() const
-{
-    return 0;
-}
-
-int Renderer11::getMaxSwapInterval() const
-{
-    return 4;
-}
-
-int Renderer11::getMaxSupportedSamples() const
-{
-    return mMaxSupportedSamples;
-}
-
-int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const
-{
-    if (requested == 0)
-    {
-        return 0;
-    }
-
-    MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format);
-    if (iter != mMultisampleSupportMap.end())
-    {
-        const MultisampleSupportInfo& info = iter->second;
-        for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
-        {
-            if (info.qualityLevels[i] > 0)
-            {
-                return i + 1;
-            }
-        }
-    }
-
-    return -1;
-}
-
-unsigned int Renderer11::getMaxRenderTargets() const
-{
-    META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
-    META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
-
-    switch (mFeatureLevel)
-    {
-      case D3D_FEATURE_LEVEL_11_0:
-        return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;  // 8
-      case D3D_FEATURE_LEVEL_10_1:
-      case D3D_FEATURE_LEVEL_10_0:
-        return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT;  // 8
-      default:
-        UNREACHABLE();
-        return 1;
-    }
-}
-
-bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance());
-        TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance());
-
-        mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance());
-        TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance());
-
-        mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                           GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
-{
-    gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
-    if (!sourceRenderTarget)
-    {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
-    if (!storage11)
-    {
-        source->Release();
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level));
-    if (!destRenderTarget)
-    {
-        source->Release();
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        source->Release();
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    gl::Rectangle destRect;
-    destRect.x = xoffset;
-    destRect.y = yoffset;
-    destRect.width = sourceRect.width;
-    destRect.height = sourceRect.height;
-
-    bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
-                           dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
-
-    source->Release();
-    dest->Release();
-
-    return ret;
-}
-
-bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                           GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
-{
-    gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
-    if (!sourceRenderTarget)
-    {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
-    if (!storage11)
-    {
-        source->Release();
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level));
-    if (!destRenderTarget)
-    {
-        source->Release();
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        source->Release();
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    gl::Rectangle destRect;
-    destRect.x = xoffset;
-    destRect.y = yoffset;
-    destRect.width = sourceRect.width;
-    destRect.height = sourceRect.height;
-
-    bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
-                           dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
-
-    source->Release();
-    dest->Release();
-
-    return ret;
-}
-
-bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight,
-                             ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat)
-{
-    HRESULT result;
-
-    if (!mCopyResourcesInitialized)
-    {
-        ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS);
-
-        D3D11_BUFFER_DESC vbDesc;
-        vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
-        vbDesc.Usage = D3D11_USAGE_DYNAMIC;
-        vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
-        vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-        vbDesc.MiscFlags = 0;
-        vbDesc.StructureByteStride = 0;
-
-        result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer");
-        d3d11::ResourceTracker::Track(mCopyVB);
-
-        D3D11_SAMPLER_DESC samplerDesc;
-        samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
-        samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
-        samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
-        samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
-        samplerDesc.MipLODBias = 0.0f;
-        samplerDesc.MaxAnisotropy = 0;
-        samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
-        samplerDesc.BorderColor[0] = 0.0f;
-        samplerDesc.BorderColor[1] = 0.0f;
-        samplerDesc.BorderColor[2] = 0.0f;
-        samplerDesc.BorderColor[3] = 0.0f;
-        samplerDesc.MinLOD = 0.0f;
-        samplerDesc.MaxLOD = 0.0f;
-
-        result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler");
-
-        D3D11_INPUT_ELEMENT_DESC quadLayout[] =
-        {
-            { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-            { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-        };
-
-        result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout");
-
-        result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader");
-
-        result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader");
-
-        result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader");
-
-        result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader");
-
-        result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader");
-
-        mCopyResourcesInitialized = true;
-    }
-
-    // Verify the source and destination area sizes
-    if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast<int>(sourceWidth) ||
-        sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast<int>(sourceHeight) ||
-        destArea.x < 0 || destArea.x + destArea.width > static_cast<int>(destWidth) ||
-        destArea.y < 0 || destArea.y + destArea.height > static_cast<int>(destHeight))
-    {
-        return gl::error(GL_INVALID_VALUE, false);
-    }
-
-    // Set vertices
-    D3D11_MAPPED_SUBRESOURCE mappedResource;
-    result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-    if (FAILED(result))
-    {
-        ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
-
-    // Create a quad in homogeneous coordinates
-    float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f;
-    float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f;
-    float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f;
-    float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f;
-
-    float u1 = sourceArea.x / float(sourceWidth);
-    float v1 = sourceArea.y / float(sourceHeight);
-    float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth);
-    float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight);
-
-    d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
-    d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
-    d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
-    d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
-
-    mDeviceContext->Unmap(mCopyVB, 0);
-
-    static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
-    static UINT startIdx = 0;
-    mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx);
-
-    // Apply state
-    mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
-    mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
-    mDeviceContext->RSSetState(NULL);
-
-    // Apply shaders
-    mDeviceContext->IASetInputLayout(mCopyIL);
-    mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-    mDeviceContext->VSSetShader(mCopyVS, NULL, 0);
-
-    ID3D11PixelShader *ps = NULL;
-    switch(destFormat)
-    {
-      case GL_RGBA:            ps = mCopyRGBAPS;     break;
-      case GL_RGB:             ps = mCopyRGBPS;      break;
-      case GL_ALPHA:           ps = mCopyRGBAPS;     break;
-      case GL_BGRA_EXT:        ps = mCopyRGBAPS;     break;
-      case GL_LUMINANCE:       ps = mCopyLumPS;      break;
-      case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break;
-      default: UNREACHABLE();  ps = NULL;            break;
-    }
-
-    mDeviceContext->PSSetShader(ps, NULL, 0);
-    mDeviceContext->GSSetShader(NULL, NULL, 0);
-
-    // Unset the currently bound shader resource to avoid conflicts
-    static ID3D11ShaderResourceView *const nullSRV = NULL;
-    mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
-
-    // Apply render target
-    setOneTimeRenderTarget(dest);
-
-    // Set the viewport
-    D3D11_VIEWPORT viewport;
-    viewport.TopLeftX = 0;
-    viewport.TopLeftY = 0;
-    viewport.Width = destWidth;
-    viewport.Height = destHeight;
-    viewport.MinDepth = 0.0f;
-    viewport.MaxDepth = 1.0f;
-    mDeviceContext->RSSetViewports(1, &viewport);
-
-    // Apply textures
-    mDeviceContext->PSSetShaderResources(0, 1, &source);
-    mDeviceContext->PSSetSamplers(0, 1, &mCopySampler);
-
-    // Draw the quad
-    mDeviceContext->Draw(4, 0);
-
-    // Unbind textures and render targets and vertex buffer
-    mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
-
-    unapplyRenderTargets();
-
-    UINT zero = 0;
-    ID3D11Buffer *const nullBuffer = NULL;
-    mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
-
-    markAllStateDirty();
-
-    return true;
-}
-
-void Renderer11::unapplyRenderTargets()
-{
-    setOneTimeRenderTarget(NULL);
-}
-
-void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView)
-{
-    ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
-
-    rtvArray[0] = renderTargetView;
-
-    mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL);
-
-    // Do not preserve the serial for this one-time-use render target
-    for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
-    {
-        mAppliedRenderTargetSerials[rtIndex] = 0;
-    }
-}
-
-RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
-{
-    SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
-    RenderTarget11 *renderTarget = NULL;
-
-    if (depth)
-    {
-        // Note: depth stencil may be NULL for 0 sized surfaces
-        renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(),
-                                          swapChain11->getDepthStencilTexture(), NULL,
-                                          swapChain11->getWidth(), swapChain11->getHeight());
-    }
-    else
-    {
-        // Note: render target may be NULL for 0 sized surfaces
-        renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
-                                          swapChain11->getOffscreenTexture(),
-                                          swapChain11->getRenderTargetShaderResource(),
-                                          swapChain11->getWidth(), swapChain11->getHeight());
-    }
-    return renderTarget;
-}
-
-RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
-{
-    RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth);
-    return renderTarget;
-}
-
-ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type)
-{
-    ShaderExecutable11 *executable = NULL;
-
-    switch (type)
-    {
-      case rx::SHADER_VERTEX:
-        {
-            ID3D11VertexShader *vshader = NULL;
-            HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader);
-            ASSERT(SUCCEEDED(result));
-
-            if (vshader)
-            {
-                executable = new ShaderExecutable11(function, length, vshader);
-            }
-        }
-        break;
-      case rx::SHADER_PIXEL:
-        {
-            ID3D11PixelShader *pshader = NULL;
-            HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader);
-            ASSERT(SUCCEEDED(result));
-
-            if (pshader)
-            {
-                executable = new ShaderExecutable11(function, length, pshader);
-            }
-        }
-        break;
-      case rx::SHADER_GEOMETRY:
-        {
-            ID3D11GeometryShader *gshader = NULL;
-            HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader);
-            ASSERT(SUCCEEDED(result));
-
-            if (gshader)
-            {
-                executable = new ShaderExecutable11(function, length, gshader);
-            }
-        }
-        break;
-      default:
-        UNREACHABLE();
-        break;
-    }
-
-    return executable;
-}
-
-ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type)
-{
-    const char *profile = NULL;
-
-    switch (type)
-    {
-      case rx::SHADER_VERTEX:
-        profile = "vs_4_0";
-        break;
-      case rx::SHADER_PIXEL:
-        profile = "ps_4_0";
-        break;
-      case rx::SHADER_GEOMETRY:
-        profile = "gs_4_0";
-        break;
-      default:
-        UNREACHABLE();
-        return NULL;
-    }
-
-    ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false);
-    if (!binary)
-        return NULL;
-
-    ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type);
-    binary->Release();
-
-    return executable;
-}
-
-VertexBuffer *Renderer11::createVertexBuffer()
-{
-    return new VertexBuffer11(this);
-}
-
-IndexBuffer *Renderer11::createIndexBuffer()
-{
-    return new IndexBuffer11(this);
-}
-
-BufferStorage *Renderer11::createBufferStorage()
-{
-    return new BufferStorage11(this);
-}
-
-QueryImpl *Renderer11::createQuery(GLenum type)
-{
-    return new Query11(this, type);
-}
-
-FenceImpl *Renderer11::createFence()
-{
-    return new Fence11(this);
-}
-
-bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)
-{
-    ASSERT(colorbuffer != NULL);
-
-    RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
-    if (renderTarget)
-    {
-        *subresourceIndex = renderTarget->getSubresourceIndex();
-
-        ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView();
-        if (colorBufferRTV)
-        {
-            ID3D11Resource *textureResource = NULL;
-            colorBufferRTV->GetResource(&textureResource);
-            colorBufferRTV->Release();
-
-            if (textureResource)
-            {
-                HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource);
-                textureResource->Release();
-
-                if (SUCCEEDED(result))
-                {
-                    return true;
-                }
-                else
-                {
-                    ERR("Failed to extract the ID3D11Texture2D from the render target resource, "
-                        "HRESULT: 0x%X.", result);
-                }
-            }
-        }
-    }
-
-    return false;
-}
-
-bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
-                          bool blitRenderTarget, bool blitDepthStencil)
-{
-    if (blitRenderTarget)
-    {
-        gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer();
-
-        if (!readBuffer)
-        {
-            ERR("Failed to retrieve the read buffer from the read framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
-        }
-
-        RenderTarget *readRenderTarget = readBuffer->getRenderTarget();
-
-        for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
-        {
-            if (drawTarget->isEnabledColorAttachment(colorAttachment))
-            {
-                gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
-
-                if (!drawBuffer)
-                {
-                    ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
-                    return gl::error(GL_OUT_OF_MEMORY, false);
-                }
-
-                RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
-
-                if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false))
-                {
-                    return false;
-                }
-            }
-        }
-    }
-
-    if (blitDepthStencil)
-    {
-        gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer();
-        gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer();
-
-        if (!readBuffer)
-        {
-            ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
-        }
-
-        if (!drawBuffer)
-        {
-            ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
-        }
-
-        RenderTarget *readRenderTarget = readBuffer->getDepthStencil();
-        RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil();
-
-        if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true))
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
-                            GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
-{
-    ID3D11Texture2D *colorBufferTexture = NULL;
-    unsigned int subresourceIndex = 0;
-
-    gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
-
-    if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
-    {
-        gl::Rectangle area;
-        area.x = x;
-        area.y = y;
-        area.width = width;
-        area.height = height;
-
-        readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch,
-                        packReverseRowOrder, packAlignment, pixels);
-
-        colorBufferTexture->Release();
-        colorBufferTexture = NULL;
-    }
-}
-
-Image *Renderer11::createImage()
-{
-    return new Image11();
-}
-
-void Renderer11::generateMipmap(Image *dest, Image *src)
-{
-    Image11 *dest11 = Image11::makeImage11(dest);
-    Image11 *src11 = Image11::makeImage11(src);
-    Image11::generateMipmap(dest11, src11);
-}
-
-TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
-{
-    SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
-    return new TextureStorage11_2D(this, swapChain11);
-}
-
-TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
-{
-    return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height);
-}
-
-TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
-{
-    return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size);
-}
-
-static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType)
-{
-    if (sourceFormat == DXGI_FORMAT_A8_UNORM &&
-        destFormat   == GL_ALPHA &&
-        destType     == GL_UNSIGNED_BYTE)
-    {
-        return 1;
-    }
-    else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM &&
-             destFormat   == GL_RGBA &&
-             destType     == GL_UNSIGNED_BYTE)
-    {
-        return 4;
-    }
-    else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM &&
-             destFormat   == GL_BGRA_EXT &&
-             destType     == GL_UNSIGNED_BYTE)
-    {
-        return 4;
-    }
-    else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT &&
-             destFormat   == GL_RGBA &&
-             destType     == GL_HALF_FLOAT_OES)
-    {
-        return 8;
-    }
-    else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT &&
-             destFormat   == GL_RGB &&
-             destType     == GL_FLOAT)
-    {
-        return 12;
-    }
-    else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT &&
-             destFormat   == GL_RGBA &&
-             destType     == GL_FLOAT)
-    {
-        return 16;
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, unsigned int x,
-                                  unsigned int y, int inputPitch, gl::Color *outColor)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_R8G8B8A8_UNORM:
-        {
-            unsigned int rgba = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
-            outColor->red =   (rgba & 0x000000FF) * (1.0f / 0x000000FF);
-            outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00);
-            outColor->blue =  (rgba & 0x00FF0000) * (1.0f / 0x00FF0000);
-            outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000);
-        }
-        break;
-
-      case DXGI_FORMAT_A8_UNORM:
-        {
-            outColor->red =   0.0f;
-            outColor->green = 0.0f;
-            outColor->blue =  0.0f;
-            outColor->alpha = *(data + x + y * inputPitch) / 255.0f;
-        }
-        break;
-
-      case DXGI_FORMAT_R32G32B32A32_FLOAT:
-        {
-            outColor->red =   *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 0);
-            outColor->green = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 1);
-            outColor->blue =  *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 2);
-            outColor->alpha = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 3);
-        }
-        break;
-
-      case DXGI_FORMAT_R32G32B32_FLOAT:
-        {
-            outColor->red =   *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 0);
-            outColor->green = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 1);
-            outColor->blue =  *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 2);
-            outColor->alpha = 1.0f;
-        }
-        break;
-
-      case DXGI_FORMAT_R16G16B16A16_FLOAT:
-        {
-            outColor->red =   gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 0));
-            outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 1));
-            outColor->blue =  gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 2));
-            outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 3));
-        }
-        break;
-
-      case DXGI_FORMAT_B8G8R8A8_UNORM:
-        {
-            unsigned int bgra = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
-            outColor->red =   (bgra & 0x00FF0000) * (1.0f / 0x00FF0000);
-            outColor->blue =  (bgra & 0x000000FF) * (1.0f / 0x000000FF);
-            outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00);
-            outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000);
-        }
-        break;
-
-      case DXGI_FORMAT_R8_UNORM:
-        {
-            outColor->red =   *(data + x + y * inputPitch) / 255.0f;
-            outColor->green = 0.0f;
-            outColor->blue =  0.0f;
-            outColor->alpha = 1.0f;
-        }
-        break;
-
-      case DXGI_FORMAT_R8G8_UNORM:
-        {
-            unsigned short rg = *reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch);
-
-            outColor->red =   (rg & 0xFF00) * (1.0f / 0xFF00);
-            outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF);
-            outColor->blue =  0.0f;
-            outColor->alpha = 1.0f;
-        }
-        break;
-
-      case DXGI_FORMAT_R16_FLOAT:
-        {
-            outColor->red =   gl::float16ToFloat32(*reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch));
-            outColor->green = 0.0f;
-            outColor->blue =  0.0f;
-            outColor->alpha = 1.0f;
-        }
-        break;
-
-      case DXGI_FORMAT_R16G16_FLOAT:
-        {
-            outColor->red =   gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 0));
-            outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 1));
-            outColor->blue =  0.0f;
-            outColor->alpha = 1.0f;
-        }
-        break;
-
-      default:
-        ERR("ReadPixelColor not implemented for DXGI format %u.", format);
-        UNIMPLEMENTED();
-        break;
-    }
-}
-
-static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x,
-                                   unsigned int y, int outputPitch, void *outData)
-{
-    unsigned char* byteData = reinterpret_cast<unsigned char*>(outData);
-    unsigned short* shortData = reinterpret_cast<unsigned short*>(outData);
-
-    switch (format)
-    {
-      case GL_RGBA:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-            byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red   + 0.5f);
-            byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
-            byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue  + 0.5f);
-            byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
-            break;
-
-          default:
-            ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type);
-            UNIMPLEMENTED();
-            break;
-        }
-        break;
-
-      case GL_BGRA_EXT:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-            byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.blue  + 0.5f);
-            byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
-            byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.red   + 0.5f);
-            byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
-            break;
-
-          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
-            // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
-            // this type is packed as follows:
-            //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
-            //  --------------------------------------------------------------------------------
-            // |       4th         |        3rd         |        2nd        |   1st component   |
-            //  --------------------------------------------------------------------------------
-            // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
-            shortData[x + y * outputPitch / sizeof(unsigned short)] =
-                (static_cast<unsigned short>(15 * color.alpha + 0.5f) << 12) |
-                (static_cast<unsigned short>(15 * color.red   + 0.5f) <<  8) |
-                (static_cast<unsigned short>(15 * color.green + 0.5f) <<  4) |
-                (static_cast<unsigned short>(15 * color.blue  + 0.5f) <<  0);
-            break;
-
-          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
-            // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
-            // this type is packed as follows:
-            //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
-            //  --------------------------------------------------------------------------------
-            // | 4th |          3rd           |           2nd          |      1st component     |
-            //  --------------------------------------------------------------------------------
-            // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
-            shortData[x + y * outputPitch / sizeof(unsigned short)] =
-                (static_cast<unsigned short>(     color.alpha + 0.5f) << 15) |
-                (static_cast<unsigned short>(31 * color.red   + 0.5f) << 10) |
-                (static_cast<unsigned short>(31 * color.green + 0.5f) <<  5) |
-                (static_cast<unsigned short>(31 * color.blue  + 0.5f) <<  0);
-            break;
-
-          default:
-            ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type);
-            UNIMPLEMENTED();
-            break;
-        }
-        break;
-
-      case GL_RGB:
-        switch (type)
-        {
-          case GL_UNSIGNED_SHORT_5_6_5:
-            shortData[x + y * outputPitch / sizeof(unsigned short)] =
-                (static_cast<unsigned short>(31 * color.blue  + 0.5f) <<  0) |
-                (static_cast<unsigned short>(63 * color.green + 0.5f) <<  5) |
-                (static_cast<unsigned short>(31 * color.red   + 0.5f) << 11);
-            break;
-
-          case GL_UNSIGNED_BYTE:
-            byteData[3 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red +   0.5f);
-            byteData[3 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
-            byteData[3 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue +  0.5f);
-            break;
-
-          default:
-            ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type);
-            UNIMPLEMENTED();
-            break;
-        }
-        break;
-
-      default:
-        ERR("WritePixelColor not implemented for format 0x%X.", format);
-        UNIMPLEMENTED();
-        break;
-    }
-}
-
-void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area,
-                                 GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
-                                 GLint packAlignment, void *pixels)
-{
-    D3D11_TEXTURE2D_DESC textureDesc;
-    texture->GetDesc(&textureDesc);
-
-    D3D11_TEXTURE2D_DESC stagingDesc;
-    stagingDesc.Width = area.width;
-    stagingDesc.Height = area.height;
-    stagingDesc.MipLevels = 1;
-    stagingDesc.ArraySize = 1;
-    stagingDesc.Format = textureDesc.Format;
-    stagingDesc.SampleDesc.Count = 1;
-    stagingDesc.SampleDesc.Quality = 0;
-    stagingDesc.Usage = D3D11_USAGE_STAGING;
-    stagingDesc.BindFlags = 0;
-    stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
-    stagingDesc.MiscFlags = 0;
-
-    ID3D11Texture2D* stagingTex = NULL;
-    HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex);
-    if (FAILED(result))
-    {
-        ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result);
-        return;
-    }
-    d3d11::ResourceTracker::Track(stagingTex);
-
-    ID3D11Texture2D* srcTex = NULL;
-    if (textureDesc.SampleDesc.Count > 1)
-    {
-        D3D11_TEXTURE2D_DESC resolveDesc;
-        resolveDesc.Width = textureDesc.Width;
-        resolveDesc.Height = textureDesc.Height;
-        resolveDesc.MipLevels = 1;
-        resolveDesc.ArraySize = 1;
-        resolveDesc.Format = textureDesc.Format;
-        resolveDesc.SampleDesc.Count = 1;
-        resolveDesc.SampleDesc.Quality = 0;
-        resolveDesc.Usage = D3D11_USAGE_DEFAULT;
-        resolveDesc.BindFlags = 0;
-        resolveDesc.CPUAccessFlags = 0;
-        resolveDesc.MiscFlags = 0;
-
-        result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex);
-        if (FAILED(result))
-        {
-            ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result);
-            stagingTex->Release();
-            return;
-        }
-        d3d11::ResourceTracker::Track(srcTex);
-
-        mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format);
-        subResource = 0;
-    }
-    else
-    {
-        srcTex = texture;
-        srcTex->AddRef();
-    }
-
-    D3D11_BOX srcBox;
-    srcBox.left = area.x;
-    srcBox.right = area.x + area.width;
-    srcBox.top = area.y;
-    srcBox.bottom = area.y + area.height;
-    srcBox.front = 0;
-    srcBox.back = 1;
-
-    mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox);
-
-    srcTex->Release();
-    srcTex = NULL;
-
-    D3D11_MAPPED_SUBRESOURCE mapping;
-    mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping);
-
-    unsigned char *source;
-    int inputPitch;
-    if (packReverseRowOrder)
-    {
-        source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (area.height - 1);
-        inputPitch = -static_cast<int>(mapping.RowPitch);
-    }
-    else
-    {
-        source = static_cast<unsigned char*>(mapping.pData);
-        inputPitch = static_cast<int>(mapping.RowPitch);
-    }
-
-    unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, format, type);
-    if (fastPixelSize != 0)
-    {
-        unsigned char *dest = static_cast<unsigned char*>(pixels);
-        for (int j = 0; j < area.height; j++)
-        {
-            memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize);
-        }
-    }
-    else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM &&
-             format == GL_RGBA &&
-             type == GL_UNSIGNED_BYTE)
-    {
-        // Fast path for swapping red with blue
-        unsigned char *dest = static_cast<unsigned char*>(pixels);
-
-        for (int j = 0; j < area.height; j++)
-        {
-            for (int i = 0; i < area.width; i++)
-            {
-                unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
-                *(unsigned int*)(dest + 4 * i + j * outputPitch) =
-                    (argb & 0xFF00FF00) |       // Keep alpha and green
-                    (argb & 0x00FF0000) >> 16 | // Move red to blue
-                    (argb & 0x000000FF) << 16;  // Move blue to red
-            }
-        }
-    }
-    else
-    {
-        gl::Color pixelColor;
-        for (int j = 0; j < area.height; j++)
-        {
-            for (int i = 0; i < area.width; i++)
-            {
-                readPixelColor(source, textureDesc.Format, i, j, inputPitch, &pixelColor);
-                writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels);
-            }
-        }
-    }
-
-    mDeviceContext->Unmap(stagingTex, 0);
-
-    stagingTex->Release();
-    stagingTex = NULL;
-}
-
-bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, 
-                                      RenderTarget *drawRenderTarget, bool wholeBufferCopy)
-{
-    ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height);
-
-    RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
-    if (!readRenderTarget)
-    {
-        ERR("Failed to retrieve the read render target from the read framebuffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    ID3D11Texture2D *readTexture = NULL;
-    unsigned int readSubresource = 0;
-    if (readRenderTarget->getSamples() > 0)
-    {
-        ID3D11Texture2D *unresolvedTexture = readRenderTarget11->getTexture();
-
-        readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex());
-        readSubresource = 0;
-
-        unresolvedTexture->Release();
-    }
-    else
-    {
-        readTexture = readRenderTarget11->getTexture();
-        readSubresource = readRenderTarget11->getSubresourceIndex();
-    }
-
-    if (!readTexture)
-    {
-        ERR("Failed to retrieve the read render target view from the read render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
-    if (!drawRenderTarget)
-    {
-        readTexture->Release();
-        ERR("Failed to retrieve the draw render target from the draw framebuffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
-
-    ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture();
-    unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
-
-    D3D11_BOX readBox;
-    readBox.left = readRect.x;
-    readBox.right = readRect.x + readRect.width;
-    readBox.top = readRect.y;
-    readBox.bottom = readRect.y + readRect.height;
-    readBox.front = 0;
-    readBox.back = 1;
-
-    // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
-    // We also require complete framebuffer copies for depth-stencil blit.
-    D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox;
-
-    mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0,
-                                          readTexture, readSubresource, pSrcBox);
-
-    readTexture->Release();
-    drawTexture->Release();
-
-    return true;
-}
-
-ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
-{
-    D3D11_TEXTURE2D_DESC textureDesc;
-    source->GetDesc(&textureDesc);
-
-    if (textureDesc.SampleDesc.Count > 1)
-    {
-        D3D11_TEXTURE2D_DESC resolveDesc;
-        resolveDesc.Width = textureDesc.Width;
-        resolveDesc.Height = textureDesc.Height;
-        resolveDesc.MipLevels = 1;
-        resolveDesc.ArraySize = 1;
-        resolveDesc.Format = textureDesc.Format;
-        resolveDesc.SampleDesc.Count = 1;
-        resolveDesc.SampleDesc.Quality = 0;
-        resolveDesc.Usage = textureDesc.Usage;
-        resolveDesc.BindFlags = textureDesc.BindFlags;
-        resolveDesc.CPUAccessFlags = 0;
-        resolveDesc.MiscFlags = 0;
-
-        ID3D11Texture2D *resolveTexture = NULL;
-        HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture);
-        if (FAILED(result))
-        {
-            ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
-            return NULL;
-        }
-        d3d11::ResourceTracker::Track(resolveTexture);
-
-        mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format);
-        return resolveTexture;
-    }
-    else
-    {
-        source->AddRef();
-        return source;
-    }
-}
-
-bool Renderer11::getLUID(LUID *adapterLuid) const
-{
-    adapterLuid->HighPart = 0;
-    adapterLuid->LowPart = 0;
-
-    if (!mDxgiAdapter)
-    {
-        return false;
-    }
-
-    DXGI_ADAPTER_DESC adapterDesc;
-    if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
-    {
-        return false;
-    }
-
-    *adapterLuid = adapterDesc.AdapterLuid;
-    return true;
-}
-
-bool Renderer11::setResourceTracker(EGLResourceTrackerProcAngle proc, void *userData)
-{
-    d3d11::ResourceTracker::SetTracker(proc, userData);
-    return true;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Renderer11.h b/src/third_party/angle/src/libGLESv2/renderer/Renderer11.h
deleted file mode 100644
index c68b953..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Renderer11.h
+++ /dev/null
@@ -1,355 +0,0 @@
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer11.h: Defines a back-end specific class for the D3D11 renderer.
-
-#ifndef LIBGLESV2_RENDERER_RENDERER11_H_
-#define LIBGLESV2_RENDERER_RENDERER11_H_
-
-#include "common/angleutils.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/mathutil.h"
-
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/RenderStateCache.h"
-#include "libGLESv2/renderer/InputLayoutCache.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-
-namespace gl
-{
-class Renderbuffer;
-}
-
-namespace rx
-{
-
-class VertexDataManager;
-class IndexDataManager;
-class StreamingIndexBufferInterface;
-
-enum
-{
-    MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024,
-    MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024
-};
-
-class Renderer11 : public Renderer
-{
-  public:
-    Renderer11(egl::Display *display, HDC hDc);
-    virtual ~Renderer11();
-
-    static Renderer11 *makeRenderer11(Renderer *renderer);
-
-    virtual EGLint initialize();
-    virtual bool resetDevice();
-
-    virtual void* getDeviceRaw();
-
-    virtual int generateConfigs(ConfigDesc **configDescList);
-    virtual void deleteConfigs(ConfigDesc *configDescList);
-
-    virtual void sync(bool block);
-
-    virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
-
-    virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
-    virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture);
-
-    virtual void setRasterizerState(const gl::RasterizerState &rasterState);
-    virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor,
-                               unsigned int sampleMask);
-    virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
-                                      int stencilBackRef, bool frontFaceCCW);
-
-    virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
-    virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
-                             bool ignoreViewport);
-
-    virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
-    virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
-    virtual void applyShaders(gl::ProgramBinary *programBinary);
-    virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
-    virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
-
-    virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
-    virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
-
-    virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
-
-    virtual void markAllStateDirty();
-
-    // lost device
-    void notifyDeviceLost();
-    virtual bool isDeviceLost();
-    virtual bool testDeviceLost(bool notify);
-    virtual bool testDeviceResettable();
-
-    // Renderer capabilities
-    virtual DWORD getAdapterVendor() const;
-    virtual std::string getRendererDescription() const;
-    virtual GUID getAdapterIdentifier() const;
-
-    virtual bool getBGRATextureSupport() const;
-    virtual bool getDXT1TextureSupport();
-    virtual bool getDXT3TextureSupport();
-    virtual bool getDXT5TextureSupport();
-    virtual bool getEventQuerySupport();
-    virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
-    virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
-    virtual bool getLuminanceTextureSupport();
-    virtual bool getLuminanceAlphaTextureSupport();
-    virtual unsigned int getMaxVertexTextureImageUnits() const;
-    virtual unsigned int getMaxCombinedTextureImageUnits() const;
-    virtual unsigned int getReservedVertexUniformVectors() const;
-    virtual unsigned int getReservedFragmentUniformVectors() const;
-    virtual unsigned int getMaxVertexUniformVectors() const;
-    virtual unsigned int getMaxFragmentUniformVectors() const;
-    virtual unsigned int getMaxVaryingVectors() const;
-    virtual bool getNonPower2TextureSupport() const;
-    virtual bool getDepthTextureSupport() const;
-    virtual bool getOcclusionQuerySupport() const;
-    virtual bool getInstancingSupport() const;
-    virtual bool getTextureFilterAnisotropySupport() const;
-    virtual float getTextureMaxAnisotropy() const;
-    virtual bool getShareHandleSupport() const;
-    virtual bool getDerivativeInstructionSupport() const;
-    virtual bool getPostSubBufferSupport() const;
-
-    virtual int getMajorShaderModel() const;
-    virtual float getMaxPointSize() const;
-    virtual int getMaxViewportDimension() const;
-    virtual int getMaxTextureWidth() const;
-    virtual int getMaxTextureHeight() const;
-    virtual bool get32BitIndexSupport() const;
-    virtual int getMinSwapInterval() const;
-    virtual int getMaxSwapInterval() const;
-
-    virtual GLsizei getMaxSupportedSamples() const;
-    int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const;
-
-    virtual unsigned int getMaxRenderTargets() const;
-
-    // Pixel operations
-    virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source);
-    virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source);
-
-    virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                           GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level);
-    virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                           GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level);
-
-    bool copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight,
-                     ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat);
-
-    virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
-                          bool blitRenderTarget, bool blitDepthStencil);
-    virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
-                            GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
-
-    // RenderTarget creation
-    virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
-    virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth);
-
-    // Shader operations
-    virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type);
-    virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type);
-
-    // Image operations
-    virtual Image *createImage();
-    virtual void generateMipmap(Image *dest, Image *source);
-    virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
-    virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
-    virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
-
-    // Buffer creation
-    virtual VertexBuffer *createVertexBuffer();
-    virtual IndexBuffer *createIndexBuffer();
-    virtual BufferStorage *createBufferStorage();
-
-    // Query and Fence creation
-    virtual QueryImpl *createQuery(GLenum type);
-    virtual FenceImpl *createFence();
-
-    // D3D11-renderer specific methods
-    ID3D11Device *getDevice() { return mDevice; }
-    ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
-    IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
-
-    bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource);
-    void unapplyRenderTargets();
-    void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView);
-
-    virtual bool getLUID(LUID *adapterLuid) const;
-
-    virtual bool setResourceTracker(EGLResourceTrackerProcAngle proc, void *userData);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Renderer11);
-
-    void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
-    void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances);
-
-    void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area,
-                         GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
-                         GLint packAlignment, void *pixels);
-
-    void maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers);
-    rx::Range getViewportBounds() const;
-
-    bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, 
-                              RenderTarget *drawRenderTarget, bool wholeBufferCopy);
-    ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
-
-    HMODULE mD3d11Module;
-    HMODULE mDxgiModule;
-    HDC mDc;
-
-    bool mDeviceLost;
-
-    void initializeDevice();
-    void releaseDeviceResources();
-    int getMinorShaderModel() const;
-    void release();
-
-    RenderStateCache mStateCache;
-
-    // Support flags
-    bool mFloat16TextureSupport;
-    bool mFloat16FilterSupport;
-    bool mFloat16RenderSupport;
-
-    bool mFloat32TextureSupport;
-    bool mFloat32FilterSupport;
-    bool mFloat32RenderSupport;
-
-    bool mDXT1TextureSupport;
-    bool mDXT3TextureSupport;
-    bool mDXT5TextureSupport;
-
-    bool mDepthTextureSupport;
-
-    // Multisample format support
-    struct MultisampleSupportInfo
-    {
-        unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT];
-    };
-
-    typedef std::unordered_map<DXGI_FORMAT, MultisampleSupportInfo> MultisampleSupportMap;
-    MultisampleSupportMap mMultisampleSupportMap;
-
-    unsigned int mMaxSupportedSamples;
-
-    // current render target states
-    unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
-    unsigned int mAppliedDepthbufferSerial;
-    unsigned int mAppliedStencilbufferSerial;
-    bool mDepthStencilInitialized;
-    bool mRenderTargetDescInitialized;
-    rx::RenderTarget::Desc mRenderTargetDesc;
-    unsigned int mCurDepthSize;
-    unsigned int mCurStencilSize;
-
-    // Currently applied sampler states
-    bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-
-    bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
-    gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
-
-    // Currently applied textures
-    unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS];
-
-    // Currently applied blend state
-    bool mForceSetBlendState;
-    gl::BlendState mCurBlendState;
-    gl::Color mCurBlendColor;
-    unsigned int mCurSampleMask;
-
-    // Currently applied rasterizer state
-    bool mForceSetRasterState;
-    gl::RasterizerState mCurRasterState;
-
-    // Currently applied depth stencil state
-    bool mForceSetDepthStencilState;
-    gl::DepthStencilState mCurDepthStencilState;
-    int mCurStencilRef;
-    int mCurStencilBackRef;
-
-    // Currently applied scissor rectangle
-    bool mForceSetScissor;
-    bool mScissorEnabled;
-    gl::Rectangle mCurScissor;
-
-    // Currently applied viewport
-    bool mForceSetViewport;
-    gl::Rectangle mCurViewport;
-    float mCurNear;
-    float mCurFar;
-
-    unsigned int mAppliedIBSerial;
-    unsigned int mAppliedStorageIBSerial;
-    unsigned int mAppliedIBOffset;
-
-    unsigned int mAppliedProgramBinarySerial;
-    bool mIsGeometryShaderActive;
-
-    dx_VertexConstants mVertexConstants;
-    dx_VertexConstants mAppliedVertexConstants;
-    ID3D11Buffer *mDriverConstantBufferVS;
-
-    dx_PixelConstants mPixelConstants;
-    dx_PixelConstants mAppliedPixelConstants;
-    ID3D11Buffer *mDriverConstantBufferPS;
-
-    // Vertex, index and input layouts
-    VertexDataManager *mVertexDataManager;
-    IndexDataManager *mIndexDataManager;
-    InputLayoutCache mInputLayoutCache;
-
-    StreamingIndexBufferInterface *mLineLoopIB;
-    StreamingIndexBufferInterface *mTriangleFanIB;
-
-    // Texture copy resources
-    bool mCopyResourcesInitialized;
-    ID3D11Buffer *mCopyVB;
-    ID3D11SamplerState *mCopySampler;
-    ID3D11InputLayout *mCopyIL;
-    ID3D11VertexShader *mCopyVS;
-    ID3D11PixelShader *mCopyRGBAPS;
-    ID3D11PixelShader *mCopyRGBPS;
-    ID3D11PixelShader *mCopyLumPS;
-    ID3D11PixelShader *mCopyLumAlphaPS;
-
-    // Masked clear resources
-    bool mClearResourcesInitialized;
-    ID3D11Buffer *mClearVB;
-    ID3D11InputLayout *mClearIL;
-    ID3D11VertexShader *mClearVS;
-    ID3D11PixelShader *mClearSinglePS;
-    ID3D11PixelShader *mClearMultiplePS;
-    ID3D11RasterizerState *mClearScissorRS;
-    ID3D11RasterizerState *mClearNoScissorRS;
-
-    // Sync query
-    ID3D11Query *mSyncQuery;
-
-    ID3D11Device *mDevice;
-    D3D_FEATURE_LEVEL mFeatureLevel;
-    ID3D11DeviceContext *mDeviceContext;
-    IDXGIAdapter *mDxgiAdapter;
-    DXGI_ADAPTER_DESC mAdapterDescription;
-    char mDescription[128];
-    IDXGIFactory *mDxgiFactory;
-
-    // Cached device caps
-    bool mBGRATextureSupport;
-};
-
-}
-#endif // LIBGLESV2_RENDERER_RENDERER11_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Renderer9.cpp b/src/third_party/angle/src/libGLESv2/renderer/Renderer9.cpp
deleted file mode 100644
index 7f24589..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Renderer9.cpp
+++ /dev/null
@@ -1,3223 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/renderer/IndexDataManager.h"
-#include "libGLESv2/renderer/Renderer9.h"
-#include "libGLESv2/renderer/renderer9_utils.h"
-#include "libGLESv2/renderer/ShaderExecutable9.h"
-#include "libGLESv2/renderer/SwapChain9.h"
-#include "libGLESv2/renderer/TextureStorage9.h"
-#include "libGLESv2/renderer/Image9.h"
-#include "libGLESv2/renderer/Blit.h"
-#include "libGLESv2/renderer/RenderTarget9.h"
-#include "libGLESv2/renderer/VertexBuffer9.h"
-#include "libGLESv2/renderer/IndexBuffer9.h"
-#include "libGLESv2/renderer/BufferStorage9.h"
-#include "libGLESv2/renderer/Query9.h"
-#include "libGLESv2/renderer/Fence9.h"
-
-#include "libEGL/Display.h"
-
-// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
-#define REF_RAST 0
-
-// The "Debug This Pixel..." feature in PIX often fails when using the
-// D3D9Ex interfaces.  In order to get debug pixel to work on a Vista/Win 7
-// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
-#if !defined(ANGLE_ENABLE_D3D9EX)
-// Enables use of the IDirect3D9Ex interface, when available
-#define ANGLE_ENABLE_D3D9EX 1
-#endif // !defined(ANGLE_ENABLE_D3D9EX)
-
-namespace rx
-{
-static const D3DFORMAT RenderTargetFormats[] =
-    {
-        D3DFMT_A1R5G5B5,
-    //  D3DFMT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
-        D3DFMT_A8R8G8B8,
-        D3DFMT_R5G6B5,
-    //  D3DFMT_X1R5G5B5,      // Has no compatible OpenGL ES renderbuffer format
-        D3DFMT_X8R8G8B8
-    };
-
-static const D3DFORMAT DepthStencilFormats[] =
-    {
-        D3DFMT_UNKNOWN,
-    //  D3DFMT_D16_LOCKABLE,
-        D3DFMT_D32,
-    //  D3DFMT_D15S1,
-        D3DFMT_D24S8,
-        D3DFMT_D24X8,
-    //  D3DFMT_D24X4S4,
-        D3DFMT_D16,
-    //  D3DFMT_D32F_LOCKABLE,
-    //  D3DFMT_D24FS8
-    };
-
-enum
-{
-    MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
-    MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32,
-    MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224,
-    MAX_VARYING_VECTORS_SM2 = 8,
-    MAX_VARYING_VECTORS_SM3 = 10,
-
-    MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
-};
-
-Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice)
-{
-    mD3d9Module = NULL;
-
-    mD3d9 = NULL;
-    mD3d9Ex = NULL;
-    mDevice = NULL;
-    mDeviceEx = NULL;
-    mDeviceWindow = NULL;
-    mBlit = NULL;
-
-    mAdapter = D3DADAPTER_DEFAULT;
-
-    #if REF_RAST == 1 || defined(FORCE_REF_RAST)
-        mDeviceType = D3DDEVTYPE_REF;
-    #else
-        mDeviceType = D3DDEVTYPE_HAL;
-    #endif
-
-    mDeviceLost = false;
-
-    mMaxSupportedSamples = 0;
-
-    mMaskedClearSavedState = NULL;
-
-    mVertexDataManager = NULL;
-    mIndexDataManager = NULL;
-    mLineLoopIB = NULL;
-
-    mMaxNullColorbufferLRU = 0;
-    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
-    {
-        mNullColorbufferCache[i].lruCount = 0;
-        mNullColorbufferCache[i].width = 0;
-        mNullColorbufferCache[i].height = 0;
-        mNullColorbufferCache[i].buffer = NULL;
-    }
-}
-
-Renderer9::~Renderer9()
-{
-    releaseDeviceResources();
-
-    if (mDevice)
-    {
-        // If the device is lost, reset it first to prevent leaving the driver in an unstable state
-        if (testDeviceLost(false))
-        {
-            resetDevice();
-        }
-
-        mDevice->Release();
-        mDevice = NULL;
-    }
-
-    if (mDeviceEx)
-    {
-        mDeviceEx->Release();
-        mDeviceEx = NULL;
-    }
-
-    if (mD3d9)
-    {
-        mD3d9->Release();
-        mD3d9 = NULL;
-    }
-
-    if (mDeviceWindow)
-    {
-        DestroyWindow(mDeviceWindow);
-        mDeviceWindow = NULL;
-    }
-
-    if (mD3d9Ex)
-    {
-        mD3d9Ex->Release();
-        mD3d9Ex = NULL;
-    }
-
-    if (mD3d9Module)
-    {
-        mD3d9Module = NULL;
-    }
-
-    while (!mMultiSampleSupport.empty())
-    {
-        delete [] mMultiSampleSupport.begin()->second;
-        mMultiSampleSupport.erase(mMultiSampleSupport.begin());
-    }
-}
-
-Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer));
-    return static_cast<rx::Renderer9*>(renderer);
-}
-
-EGLint Renderer9::initialize()
-{
-    if (!initializeCompiler())
-    {
-        return EGL_NOT_INITIALIZED;
-    }
-
-    if (mSoftwareDevice)
-    {
-        mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
-    }
-    else
-    {
-        mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
-    }
-
-    if (mD3d9Module == NULL)
-    {
-        ERR("No D3D9 module found - aborting!\n");
-        return EGL_NOT_INITIALIZED;
-    }
-
-    typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
-    Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
-
-    // Use Direct3D9Ex if available. Among other things, this version is less
-    // inclined to report a lost context, for example when the user switches
-    // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
-    if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
-    {
-        ASSERT(mD3d9Ex);
-        mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
-        ASSERT(mD3d9);
-    }
-    else
-    {
-        mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
-    }
-
-    if (!mD3d9)
-    {
-        ERR("Could not create D3D9 device - aborting!\n");
-        return EGL_NOT_INITIALIZED;
-    }
-
-    if (mDc != NULL)
-    {
-    //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context corresponds to
-    }
-
-    HRESULT result;
-
-    // Give up on getting device caps after about one second.
-    for (int i = 0; i < 10; ++i)
-    {
-        result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
-        if (SUCCEEDED(result))
-        {
-            break;
-        }
-        else if (result == D3DERR_NOTAVAILABLE)
-        {
-            Sleep(100);   // Give the driver some time to initialize/recover
-        }
-        else if (FAILED(result))   // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
-        {
-            ERR("failed to get device caps (0x%x)\n", result);
-            return EGL_NOT_INITIALIZED;
-        }
-    }
-
-    if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
-    {
-        ERR("Renderer does not support PS 2.0. aborting!\n");
-        return EGL_NOT_INITIALIZED;
-    }
-
-    // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
-    // This is required by Texture2D::convertToRenderTarget.
-    if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
-    {
-        ERR("Renderer does not support stretctrect from textures!\n");
-        return EGL_NOT_INITIALIZED;
-    }
-
-    mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
-
-    // ATI cards on XP have problems with non-power-of-two textures.
-    mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
-        !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
-        !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
-        !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
-
-    // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
-    mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2));
-
-    mMinSwapInterval = 4;
-    mMaxSwapInterval = 0;
-
-    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
-    {
-        mMinSwapInterval = std::min(mMinSwapInterval, 0);
-        mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
-    }
-    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
-    {
-        mMinSwapInterval = std::min(mMinSwapInterval, 1);
-        mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
-    }
-    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
-    {
-        mMinSwapInterval = std::min(mMinSwapInterval, 2);
-        mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
-    }
-    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
-    {
-        mMinSwapInterval = std::min(mMinSwapInterval, 3);
-        mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
-    }
-    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
-    {
-        mMinSwapInterval = std::min(mMinSwapInterval, 4);
-        mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
-    }
-
-    int max = 0;
-    for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i)
-    {
-        bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
-        getMultiSampleSupport(RenderTargetFormats[i], multisampleArray);
-        mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray;
-
-        for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
-        {
-            if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
-            {
-                max = j;
-            }
-        }
-    }
-
-    for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i)
-    {
-        if (DepthStencilFormats[i] == D3DFMT_UNKNOWN)
-            continue;
-
-        bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
-        getMultiSampleSupport(DepthStencilFormats[i], multisampleArray);
-        mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray;
-
-        for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
-        {
-            if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
-            {
-                max = j;
-            }
-        }
-    }
-
-    mMaxSupportedSamples = max;
-
-    static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
-    static const TCHAR className[] = TEXT("STATIC");
-
-    mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
-
-    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
-    DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
-
-    result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
-    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
-    {
-        return EGL_BAD_ALLOC;
-    }
-
-    if (FAILED(result))
-    {
-        result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
-            return EGL_BAD_ALLOC;
-        }
-    }
-
-    if (mD3d9Ex)
-    {
-        result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
-        ASSERT(SUCCEEDED(result));
-    }
-
-    mVertexShaderCache.initialize(mDevice);
-    mPixelShaderCache.initialize(mDevice);
-
-    // Check occlusion query support
-    IDirect3DQuery9 *occlusionQuery = NULL;
-    if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery)
-    {
-        occlusionQuery->Release();
-        mOcclusionQuerySupport = true;
-    }
-    else
-    {
-        mOcclusionQuerySupport = false;
-    }
-
-    // Check event query support
-    IDirect3DQuery9 *eventQuery = NULL;
-    if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery)
-    {
-        eventQuery->Release();
-        mEventQuerySupport = true;
-    }
-    else
-    {
-        mEventQuerySupport = false;
-    }
-
-    D3DDISPLAYMODE currentDisplayMode;
-    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
-
-    // Check vertex texture support
-    // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
-    // We test this using D3D9 by checking support for the R16F format.
-    mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
-                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
-                                                               D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
-
-    // Check depth texture support
-    // we use INTZ for depth textures in Direct3D9
-    // we also want NULL texture support to ensure the we can make depth-only FBOs
-    // see http://aras-p.info/texts/D3D9GPUHacks.html
-    mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
-                                                              D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) &&
-                           SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
-                                                              D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
-
-    // Check 32 bit floating point texture support
-    mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
-                                                               D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
-                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
-                                                               D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
-
-    mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
-                                                               D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
-                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
-                                                               D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
-
-    if (!mFloat32FilterSupport && !mFloat32RenderSupport)
-    {
-        mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
-                                                                    D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
-                                 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
-                                                                    D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
-    }
-    else
-    {
-        mFloat32TextureSupport = true;
-    }
-
-    // Check 16 bit floating point texture support
-    mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
-                                                               D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
-                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
-                                                               D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
-
-    mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
-                                                               D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
-                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
-                                                               D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
-
-    if (!mFloat16FilterSupport && !mFloat16RenderSupport)
-    {
-        mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
-                                                                    D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
-                                 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
-                                                                    D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
-    }
-    else
-    {
-        mFloat16TextureSupport = true;
-    }
-
-    // Check DXT texture support
-    mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
-    mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
-    mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
-
-    // Check luminance[alpha] texture support
-    mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
-    mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
-
-    initializeDevice();
-
-    return EGL_SUCCESS;
-}
-
-// do any one-time device initialization
-// NOTE: this is also needed after a device lost/reset
-// to reset the scene status and ensure the default states are reset.
-void Renderer9::initializeDevice()
-{
-    // Permanent non-default states
-    mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
-    mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
-
-    if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
-    {
-        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
-    }
-    else
-    {
-        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000);   // 1.0f
-    }
-
-    markAllStateDirty();
-
-    mSceneStarted = false;
-
-    ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager);
-    mBlit = new Blit(this);
-    mVertexDataManager = new rx::VertexDataManager(this);
-    mIndexDataManager = new rx::IndexDataManager(this);
-}
-
-D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
-{
-    D3DPRESENT_PARAMETERS presentParameters = {0};
-
-    // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
-    presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
-    presentParameters.BackBufferCount = 1;
-    presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
-    presentParameters.BackBufferWidth = 1;
-    presentParameters.BackBufferHeight = 1;
-    presentParameters.EnableAutoDepthStencil = FALSE;
-    presentParameters.Flags = 0;
-    presentParameters.hDeviceWindow = mDeviceWindow;
-    presentParameters.MultiSampleQuality = 0;
-    presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
-    presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
-    presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
-    presentParameters.Windowed = TRUE;
-
-    return presentParameters;
-}
-
-int Renderer9::generateConfigs(ConfigDesc **configDescList)
-{
-    D3DDISPLAYMODE currentDisplayMode;
-    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
-
-    unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
-    unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
-    (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
-    int numConfigs = 0;
-
-    for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
-    {
-        D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
-
-        HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
-
-        if (SUCCEEDED(result))
-        {
-            for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
-            {
-                D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
-                HRESULT result = D3D_OK;
-
-                if(depthStencilFormat != D3DFMT_UNKNOWN)
-                {
-                    result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
-                }
-
-                if (SUCCEEDED(result))
-                {
-                    if(depthStencilFormat != D3DFMT_UNKNOWN)
-                    {
-                        result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
-                    }
-
-                    if (SUCCEEDED(result))
-                    {
-                        ConfigDesc newConfig;
-                        newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat);
-                        newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat);
-                        newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
-                        newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat);
-
-                        (*configDescList)[numConfigs++] = newConfig;
-                    }
-                }
-            }
-        }
-    }
-
-    return numConfigs;
-}
-
-void Renderer9::deleteConfigs(ConfigDesc *configDescList)
-{
-    delete [] (configDescList);
-}
-
-void Renderer9::startScene()
-{
-    if (!mSceneStarted)
-    {
-        long result = mDevice->BeginScene();
-        if (SUCCEEDED(result)) {
-            // This is defensive checking against the device being
-            // lost at unexpected times.
-            mSceneStarted = true;
-        }
-    }
-}
-
-void Renderer9::endScene()
-{
-    if (mSceneStarted)
-    {
-        // EndScene can fail if the device was lost, for example due
-        // to a TDR during a draw call.
-        mDevice->EndScene();
-        mSceneStarted = false;
-    }
-}
-
-void Renderer9::sync(bool block)
-{
-    HRESULT result;
-
-    IDirect3DQuery9* query = allocateEventQuery();
-    if (!query)
-    {
-        return;
-    }
-
-    result = query->Issue(D3DISSUE_END);
-    ASSERT(SUCCEEDED(result));
-
-    do
-    {
-        result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
-
-        if(block && result == S_FALSE)
-        {
-            // Keep polling, but allow other threads to do something useful first
-            Sleep(0);
-            // explicitly check for device loss
-            // some drivers seem to return S_FALSE even if the device is lost
-            // instead of D3DERR_DEVICELOST like they should
-            if (testDeviceLost(false))
-            {
-                result = D3DERR_DEVICELOST;
-            }
-        }
-    }
-    while(block && result == S_FALSE);
-
-    freeEventQuery(query);
-
-    if (d3d9::isDeviceLostError(result))
-    {
-        notifyDeviceLost();
-    }
-}
-
-SwapChain *Renderer9::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
-{
-    return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat);
-}
-
-IDirect3DQuery9* Renderer9::allocateEventQuery()
-{
-    IDirect3DQuery9 *query = NULL;
-
-    if (mEventQueryPool.empty())
-    {
-        HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
-        ASSERT(SUCCEEDED(result));
-    }
-    else
-    {
-        query = mEventQueryPool.back();
-        mEventQueryPool.pop_back();
-    }
-
-    return query;
-}
-
-void Renderer9::freeEventQuery(IDirect3DQuery9* query)
-{
-    if (mEventQueryPool.size() > 1000)
-    {
-        query->Release();
-    }
-    else
-    {
-        mEventQueryPool.push_back(query);
-    }
-}
-
-IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length)
-{
-    return mVertexShaderCache.create(function, length);
-}
-
-IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length)
-{
-    return mPixelShaderCache.create(function, length);
-}
-
-HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
-{
-    D3DPOOL Pool = getBufferPool(Usage);
-    return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL);
-}
-
-VertexBuffer *Renderer9::createVertexBuffer()
-{
-    return new VertexBuffer9(this);
-}
-
-HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer)
-{
-    D3DPOOL Pool = getBufferPool(Usage);
-    return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL);
-}
-
-IndexBuffer *Renderer9::createIndexBuffer()
-{
-    return new IndexBuffer9(this);
-}
-
-BufferStorage *Renderer9::createBufferStorage()
-{
-    return new BufferStorage9();
-}
-
-QueryImpl *Renderer9::createQuery(GLenum type)
-{
-    return new Query9(this, type);
-}
-
-FenceImpl *Renderer9::createFence()
-{
-    return new Fence9(this);
-}
-
-void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
-{
-    bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates;
-    gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates;
-
-    if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0)
-    {
-        int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
-        int d3dSampler = index + d3dSamplerOffset;
-
-        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
-        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
-
-        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
-        D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
-        gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy);
-        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
-        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
-        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset);
-        if (mSupportsTextureFilterAnisotropy)
-        {
-            mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
-        }
-    }
-
-    forceSetSamplers[index] = false;
-    appliedSamplers[index] = samplerState;
-}
-
-void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
-{
-    int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
-    int d3dSampler = index + d3dSamplerOffset;
-    IDirect3DBaseTexture9 *d3dTexture = NULL;
-    unsigned int serial = 0;
-    bool forceSetTexture = false;
-
-    unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials;
-
-    if (texture)
-    {
-        TextureStorageInterface *texStorage = texture->getNativeTexture();
-        if (texStorage)
-        {
-            TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance());
-            d3dTexture = storage9->getBaseTexture();
-        }
-        // If we get NULL back from getBaseTexture here, something went wrong
-        // in the texture class and we're unexpectedly missing the d3d texture
-        ASSERT(d3dTexture != NULL);
-
-        serial = texture->getTextureSerial();
-        forceSetTexture = texture->hasDirtyImages();
-    }
-
-    if (forceSetTexture || appliedSerials[index] != serial)
-    {
-        mDevice->SetTexture(d3dSampler, d3dTexture);
-    }
-
-    appliedSerials[index] = serial;
-}
-
-void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
-{
-    bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0;
-
-    if (rasterStateChanged)
-    {
-        // Set the cull mode
-        if (rasterState.cullFace)
-        {
-            mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace));
-        }
-        else
-        {
-            mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
-        }
-
-        if (rasterState.polygonOffsetFill)
-        {
-            if (mCurDepthSize > 0)
-            {
-                mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor);
-
-                float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
-                mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias);
-            }
-        }
-        else
-        {
-            mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
-            mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
-        }
-
-        mCurRasterState = rasterState;
-    }
-
-    mForceSetRasterState = false;
-}
-
-void Renderer9::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask)
-{
-    bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0;
-    bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0;
-    bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask;
-
-    if (blendStateChanged || blendColorChanged)
-    {
-        if (blendState.blend)
-        {
-            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
-
-            if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
-                blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
-            {
-                mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor));
-            }
-            else
-            {
-                mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha),
-                                                                         gl::unorm<8>(blendColor.alpha),
-                                                                         gl::unorm<8>(blendColor.alpha),
-                                                                         gl::unorm<8>(blendColor.alpha)));
-            }
-
-            mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
-            mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
-            mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));
-
-            if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
-                blendState.destBlendRGB != blendState.destBlendAlpha ||
-                blendState.blendEquationRGB != blendState.blendEquationAlpha)
-            {
-                mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
-
-                mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
-                mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
-                mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
-            }
-            else
-            {
-                mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
-            }
-        }
-        else
-        {
-            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
-        }
-
-        if (blendState.sampleAlphaToCoverage)
-        {
-            FIXME("Sample alpha to coverage is unimplemented.");
-        }
-
-        // Set the color mask
-        bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD;
-        // Apparently some ATI cards have a bug where a draw with a zero color
-        // write mask can cause later draws to have incorrect results. Instead,
-        // set a nonzero color write mask but modify the blend state so that no
-        // drawing is done.
-        // http://code.google.com/p/angleproject/issues/detail?id=169
-
-        DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
-                                                    blendState.colorMaskBlue, blendState.colorMaskAlpha);
-        if (colorMask == 0 && !zeroColorMaskAllowed)
-        {
-            // Enable green channel, but set blending so nothing will be drawn.
-            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
-            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
-
-            mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
-            mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
-            mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
-        }
-        else
-        {
-            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
-        }
-
-        mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE);
-
-        mCurBlendState = blendState;
-        mCurBlendColor = blendColor;
-    }
-
-    if (sampleMaskChanged)
-    {
-        // Set the multisample mask
-        mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
-        mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));
-
-        mCurSampleMask = sampleMask;
-    }
-
-    mForceSetBlendState = false;
-}
-
-void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
-                                     int stencilBackRef, bool frontFaceCCW)
-{
-    bool depthStencilStateChanged = mForceSetDepthStencilState ||
-                                    memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0;
-    bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef ||
-                             stencilBackRef != mCurStencilBackRef;
-    bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW;
-
-    if (depthStencilStateChanged)
-    {
-        if (depthStencilState.depthTest)
-        {
-            mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
-            mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc));
-        }
-        else
-        {
-            mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
-        }
-
-        mCurDepthStencilState = depthStencilState;
-    }
-
-    if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged)
-    {
-        if (depthStencilState.stencilTest && mCurStencilSize > 0)
-        {
-            mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
-            mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
-
-            // FIXME: Unsupported by D3D9
-            const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
-            const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
-            const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
-            if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
-                stencilRef != stencilBackRef ||
-                depthStencilState.stencilMask != depthStencilState.stencilBackMask)
-            {
-                ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
-                return gl::error(GL_INVALID_OPERATION);
-            }
-
-            // get the maximum size of the stencil ref
-            unsigned int maxStencil = (1 << mCurStencilSize) - 1;
-
-            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
-                                    depthStencilState.stencilWritemask);
-            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
-                                    gl_d3d9::ConvertComparison(depthStencilState.stencilFunc));
-
-            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
-                                    (stencilRef < (int)maxStencil) ? stencilRef : maxStencil);
-            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
-                                    depthStencilState.stencilMask);
-
-            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
-                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail));
-            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
-                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail));
-            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
-                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass));
-
-            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
-                                    depthStencilState.stencilBackWritemask);
-            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
-                                    gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc));
-
-            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
-                                    (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
-            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
-                                    depthStencilState.stencilBackMask);
-
-            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
-                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail));
-            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
-                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail));
-            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
-                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass));
-        }
-        else
-        {
-            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
-        }
-
-        mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE);
-
-        mCurStencilRef = stencilRef;
-        mCurStencilBackRef = stencilBackRef;
-        mCurFrontFaceCCW = frontFaceCCW;
-    }
-
-    mForceSetDepthStencilState = false;
-}
-
-void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
-{
-    bool scissorChanged = mForceSetScissor ||
-                          memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
-                          enabled != mScissorEnabled;
-
-    if (scissorChanged)
-    {
-        if (enabled)
-        {
-            RECT rect;
-            rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
-            rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
-            rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
-            rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
-            mDevice->SetScissorRect(&rect);
-        }
-
-        mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE);
-
-        mScissorEnabled = enabled;
-        mCurScissor = scissor;
-    }
-
-    mForceSetScissor = false;
-}
-
-bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
-                            bool ignoreViewport)
-{
-    gl::Rectangle actualViewport = viewport;
-    float actualZNear = gl::clamp01(zNear);
-    float actualZFar = gl::clamp01(zFar);
-    if (ignoreViewport)
-    {
-        actualViewport.x = 0;
-        actualViewport.y = 0;
-        actualViewport.width = mRenderTargetDesc.width;
-        actualViewport.height = mRenderTargetDesc.height;
-        actualZNear = 0.0f;
-        actualZFar = 1.0f;
-    }
-
-    D3DVIEWPORT9 dxViewport;
-    dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width));
-    dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height));
-    dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.X));
-    dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.Y));
-    dxViewport.MinZ = actualZNear;
-    dxViewport.MaxZ = actualZFar;
-
-    if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
-    {
-        return false;   // Nothing to render
-    }
-
-    bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
-                           actualZNear != mCurNear || actualZFar != mCurFar;
-    if (viewportChanged)
-    {
-        mDevice->SetViewport(&dxViewport);
-
-        mCurViewport = actualViewport;
-        mCurNear = actualZNear;
-        mCurFar = actualZFar;
-
-        dx_VertexConstants vc = {0};
-        dx_PixelConstants pc = {0};
-
-        vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width;
-        vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height;
-        vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width;
-        vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height;
-
-        pc.viewCoords[0] = actualViewport.width  * 0.5f;
-        pc.viewCoords[1] = actualViewport.height * 0.5f;
-        pc.viewCoords[2] = actualViewport.x + (actualViewport.width  * 0.5f);
-        pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
-
-        pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
-        pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
-        pc.depthFront[2] = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);;
-
-        vc.depthRange[0] = actualZNear;
-        vc.depthRange[1] = actualZFar;
-        vc.depthRange[2] = actualZFar - actualZNear;
-
-        pc.depthRange[0] = actualZNear;
-        pc.depthRange[1] = actualZFar;
-        pc.depthRange[2] = actualZFar - actualZNear;
-
-        if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0)
-        {
-            mVertexConstants = vc;
-            mDxUniformsDirty = true;
-        }
-
-        if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0)
-        {
-            mPixelConstants = pc;
-            mDxUniformsDirty = true;
-        }
-    }
-
-    mForceSetViewport = false;
-    return true;
-}
-
-bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
-{
-    switch (mode)
-    {
-      case GL_POINTS:
-        mPrimitiveType = D3DPT_POINTLIST;
-        mPrimitiveCount = count;
-        break;
-      case GL_LINES:
-        mPrimitiveType = D3DPT_LINELIST;
-        mPrimitiveCount = count / 2;
-        break;
-      case GL_LINE_LOOP:
-        mPrimitiveType = D3DPT_LINESTRIP;
-        mPrimitiveCount = count - 1;   // D3D doesn't support line loops, so we draw the last line separately
-        break;
-      case GL_LINE_STRIP:
-        mPrimitiveType = D3DPT_LINESTRIP;
-        mPrimitiveCount = count - 1;
-        break;
-      case GL_TRIANGLES:
-        mPrimitiveType = D3DPT_TRIANGLELIST;
-        mPrimitiveCount = count / 3;
-        break;
-      case GL_TRIANGLE_STRIP:
-        mPrimitiveType = D3DPT_TRIANGLESTRIP;
-        mPrimitiveCount = count - 2;
-        break;
-      case GL_TRIANGLE_FAN:
-        mPrimitiveType = D3DPT_TRIANGLEFAN;
-        mPrimitiveCount = count - 2;
-        break;
-      default:
-        return gl::error(GL_INVALID_ENUM, false);
-    }
-
-    return mPrimitiveCount > 0;
-}
-
-
-gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer)
-{
-    if (!depthbuffer)
-    {
-        ERR("Unexpected null depthbuffer for depth-only FBO.");
-        return NULL;
-    }
-
-    GLsizei width  = depthbuffer->getWidth();
-    GLsizei height = depthbuffer->getHeight();
-
-    // search cached nullcolorbuffers
-    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
-    {
-        if (mNullColorbufferCache[i].buffer != NULL &&
-            mNullColorbufferCache[i].width == width &&
-            mNullColorbufferCache[i].height == height)
-        {
-            mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
-            return mNullColorbufferCache[i].buffer;
-        }
-    }
-
-    gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
-
-    // add nullbuffer to the cache
-    NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
-    for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
-    {
-        if (mNullColorbufferCache[i].lruCount < oldest->lruCount)
-        {
-            oldest = &mNullColorbufferCache[i];
-        }
-    }
-
-    delete oldest->buffer;
-    oldest->buffer = nullbuffer;
-    oldest->lruCount = ++mMaxNullColorbufferLRU;
-    oldest->width = width;
-    oldest->height = height;
-
-    return nullbuffer;
-}
-
-bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
-{
-    // if there is no color attachment we must synthesize a NULL colorattachment
-    // to keep the D3D runtime happy.  This should only be possible if depth texturing.
-    gl::Renderbuffer *renderbufferObject = NULL;
-    if (framebuffer->getColorbufferType(0) != GL_NONE)
-    {
-        renderbufferObject = framebuffer->getColorbuffer(0);
-    }
-    else
-    {
-        renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer());
-    }
-    if (!renderbufferObject)
-    {
-        ERR("unable to locate renderbuffer for FBO.");
-        return false;
-    }
-
-    bool renderTargetChanged = false;
-    unsigned int renderTargetSerial = renderbufferObject->getSerial();
-    if (renderTargetSerial != mAppliedRenderTargetSerial)
-    {
-        // Apply the render target on the device
-        IDirect3DSurface9 *renderTargetSurface = NULL;
-
-        RenderTarget *renderTarget = renderbufferObject->getRenderTarget();
-        if (renderTarget)
-        {
-            renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface();
-        }
-
-        if (!renderTargetSurface)
-        {
-            ERR("render target pointer unexpectedly null.");
-            return false;   // Context must be lost
-        }
-
-        mDevice->SetRenderTarget(0, renderTargetSurface);
-        renderTargetSurface->Release();
-
-        mAppliedRenderTargetSerial = renderTargetSerial;
-        renderTargetChanged = true;
-    }
-
-    gl::Renderbuffer *depthStencil = NULL;
-    unsigned int depthbufferSerial = 0;
-    unsigned int stencilbufferSerial = 0;
-    if (framebuffer->getDepthbufferType() != GL_NONE)
-    {
-        depthStencil = framebuffer->getDepthbuffer();
-        if (!depthStencil)
-        {
-            ERR("Depth stencil pointer unexpectedly null.");
-            return false;
-        }
-
-        depthbufferSerial = depthStencil->getSerial();
-    }
-    else if (framebuffer->getStencilbufferType() != GL_NONE)
-    {
-        depthStencil = framebuffer->getStencilbuffer();
-        if (!depthStencil)
-        {
-            ERR("Depth stencil pointer unexpectedly null.");
-            return false;
-        }
-
-        stencilbufferSerial = depthStencil->getSerial();
-    }
-
-    if (depthbufferSerial != mAppliedDepthbufferSerial ||
-        stencilbufferSerial != mAppliedStencilbufferSerial ||
-        !mDepthStencilInitialized)
-    {
-        unsigned int depthSize = 0;
-        unsigned int stencilSize = 0;
-
-        // Apply the depth stencil on the device
-        if (depthStencil)
-        {
-            IDirect3DSurface9 *depthStencilSurface = NULL;
-            RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil();
-
-            if (depthStencilRenderTarget)
-            {
-                depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface();
-            }
-
-            if (!depthStencilSurface)
-            {
-                ERR("depth stencil pointer unexpectedly null.");
-                return false;   // Context must be lost
-            }
-
-            mDevice->SetDepthStencilSurface(depthStencilSurface);
-            depthStencilSurface->Release();
-
-            depthSize = depthStencil->getDepthSize();
-            stencilSize = depthStencil->getStencilSize();
-        }
-        else
-        {
-            mDevice->SetDepthStencilSurface(NULL);
-        }
-
-        if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
-        {
-            mCurDepthSize = depthSize;
-            mForceSetRasterState = true;
-        }
-
-        if (!mDepthStencilInitialized || stencilSize != mCurStencilSize)
-        {
-            mCurStencilSize = stencilSize;
-            mForceSetDepthStencilState = true;
-        }
-
-        mAppliedDepthbufferSerial = depthbufferSerial;
-        mAppliedStencilbufferSerial = stencilbufferSerial;
-        mDepthStencilInitialized = true;
-    }
-
-    if (renderTargetChanged || !mRenderTargetDescInitialized)
-    {
-        mForceSetScissor = true;
-        mForceSetViewport = true;
-
-        mRenderTargetDesc.width = renderbufferObject->getWidth();
-        mRenderTargetDesc.height = renderbufferObject->getHeight();
-        mRenderTargetDesc.format = renderbufferObject->getActualFormat();
-        mRenderTargetDescInitialized = true;
-    }
-
-    return true;
-}
-
-GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
-{
-    TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
-    GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
-    if (err != GL_NO_ERROR)
-    {
-        return err;
-    }
-
-    return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw);
-}
-
-// Applies the indices and element array bindings to the Direct3D 9 device
-GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
-{
-    GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
-
-    if (err == GL_NO_ERROR)
-    {
-        // Directly binding the storage buffer is not supported for d3d9
-        ASSERT(indexInfo->storage == NULL);
-
-        if (indexInfo->serial != mAppliedIBSerial)
-        {
-            IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);
-
-            mDevice->SetIndices(indexBuffer->getBuffer());
-            mAppliedIBSerial = indexInfo->serial;
-        }
-    }
-
-    return err;
-}
-
-void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
-{
-    startScene();
-
-    if (mode == GL_LINE_LOOP)
-    {
-        drawLineLoop(count, GL_NONE, NULL, 0, NULL);
-    }
-    else if (instances > 0)
-    {
-        StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count);
-        if (countingIB)
-        {
-            if (mAppliedIBSerial != countingIB->getSerial())
-            {
-                IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer());
-
-                mDevice->SetIndices(indexBuffer->getBuffer());
-                mAppliedIBSerial = countingIB->getSerial();
-            }
-
-            for (int i = 0; i < mRepeatDraw; i++)
-            {
-                mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
-            }
-        }
-        else
-        {
-            ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-    else   // Regular case
-    {
-        mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
-    }
-}
-
-void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/)
-{
-    startScene();
-
-    if (mode == GL_POINTS)
-    {
-        drawIndexedPoints(count, type, indices, elementArrayBuffer);
-    }
-    else if (mode == GL_LINE_LOOP)
-    {
-        drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
-    }
-    else
-    {
-        for (int i = 0; i < mRepeatDraw; i++)
-        {
-            GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
-            mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount);
-        }
-    }
-}
-
-void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
-{
-    // Get the raw indices for an indexed draw
-    if (type != GL_NONE && elementArrayBuffer)
-    {
-        gl::Buffer *indexBuffer = elementArrayBuffer;
-        BufferStorage *storage = indexBuffer->getStorage();
-        intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
-    }
-
-    UINT startIndex = 0;
-
-    if (get32BitIndexSupport())
-    {
-        if (!mLineLoopIB)
-        {
-            mLineLoopIB = new StreamingIndexBufferInterface(this);
-            if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
-            {
-                delete mLineLoopIB;
-                mLineLoopIB = NULL;
-
-                ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-        }
-
-        if (static_cast<unsigned int>(count + 1) > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
-        {
-            ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-
-        const unsigned int spaceNeeded = (count + 1) * sizeof(unsigned int);
-        if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
-        {
-            ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-
-        void* mappedMemory = NULL;
-        int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
-        if (offset == -1 || mappedMemory == NULL)
-        {
-            ERR("Could not map index buffer for GL_LINE_LOOP.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-
-        startIndex = static_cast<UINT>(offset) / 4;
-        unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
-
-        switch (type)
-        {
-          case GL_NONE:   // Non-indexed draw
-            for (int i = 0; i < count; i++)
-            {
-                data[i] = i;
-            }
-            data[count] = 0;
-            break;
-          case GL_UNSIGNED_BYTE:
-            for (int i = 0; i < count; i++)
-            {
-                data[i] = static_cast<const GLubyte*>(indices)[i];
-            }
-            data[count] = static_cast<const GLubyte*>(indices)[0];
-            break;
-          case GL_UNSIGNED_SHORT:
-            for (int i = 0; i < count; i++)
-            {
-                data[i] = static_cast<const GLushort*>(indices)[i];
-            }
-            data[count] = static_cast<const GLushort*>(indices)[0];
-            break;
-          case GL_UNSIGNED_INT:
-            for (int i = 0; i < count; i++)
-            {
-                data[i] = static_cast<const GLuint*>(indices)[i];
-            }
-            data[count] = static_cast<const GLuint*>(indices)[0];
-            break;
-          default: UNREACHABLE();
-        }
-
-        if (!mLineLoopIB->unmapBuffer())
-        {
-            ERR("Could not unmap index buffer for GL_LINE_LOOP.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-    else
-    {
-        if (!mLineLoopIB)
-        {
-            mLineLoopIB = new StreamingIndexBufferInterface(this);
-            if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
-            {
-                delete mLineLoopIB;
-                mLineLoopIB = NULL;
-
-                ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP.");
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-        }
-
-        if (static_cast<unsigned int>(count + 1) > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
-        {
-            ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-
-        const int spaceNeeded = (count + 1) * sizeof(unsigned short);
-        if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT))
-        {
-            ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-
-        void* mappedMemory = NULL;
-        int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
-        if (offset == -1 || mappedMemory == NULL)
-        {
-            ERR("Could not map index buffer for GL_LINE_LOOP.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-
-        startIndex = static_cast<UINT>(offset) / 2;
-        unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
-
-        switch (type)
-        {
-          case GL_NONE:   // Non-indexed draw
-            for (int i = 0; i < count; i++)
-            {
-                data[i] = i;
-            }
-            data[count] = 0;
-            break;
-          case GL_UNSIGNED_BYTE:
-            for (int i = 0; i < count; i++)
-            {
-                data[i] = static_cast<const GLubyte*>(indices)[i];
-            }
-            data[count] = static_cast<const GLubyte*>(indices)[0];
-            break;
-          case GL_UNSIGNED_SHORT:
-            for (int i = 0; i < count; i++)
-            {
-                data[i] = static_cast<const GLushort*>(indices)[i];
-            }
-            data[count] = static_cast<const GLushort*>(indices)[0];
-            break;
-          case GL_UNSIGNED_INT:
-            for (int i = 0; i < count; i++)
-            {
-                data[i] = static_cast<const GLuint*>(indices)[i];
-            }
-            data[count] = static_cast<const GLuint*>(indices)[0];
-            break;
-          default: UNREACHABLE();
-        }
-
-        if (!mLineLoopIB->unmapBuffer())
-        {
-            ERR("Could not unmap index buffer for GL_LINE_LOOP.");
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    if (mAppliedIBSerial != mLineLoopIB->getSerial())
-    {
-        IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer());
-
-        mDevice->SetIndices(indexBuffer->getBuffer());
-        mAppliedIBSerial = mLineLoopIB->getSerial();
-    }
-
-    mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
-}
-
-template <typename T>
-static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices)
-{
-    for (int i = 0; i < count; i++)
-    {
-        unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]);
-        device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
-    }
-}
-
-void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer)
-{
-    // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
-    // for each individual point. This call is not expected to happen often.
-
-    if (elementArrayBuffer)
-    {
-        BufferStorage *storage = elementArrayBuffer->getStorage();
-        intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
-    }
-
-    switch (type)
-    {
-        case GL_UNSIGNED_BYTE:  drawPoints<GLubyte>(mDevice, count, indices);  break;
-        case GL_UNSIGNED_SHORT: drawPoints<GLushort>(mDevice, count, indices); break;
-        case GL_UNSIGNED_INT:   drawPoints<GLuint>(mDevice, count, indices);   break;
-        default: UNREACHABLE();
-    }
-}
-
-void Renderer9::applyShaders(gl::ProgramBinary *programBinary)
-{
-    unsigned int programBinarySerial = programBinary->getSerial();
-    if (programBinarySerial != mAppliedProgramBinarySerial)
-    {
-        ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
-        ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
-
-        IDirect3DVertexShader9 *vertexShader = NULL;
-        if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader();
-
-        IDirect3DPixelShader9 *pixelShader = NULL;
-        if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader();
-
-        mDevice->SetPixelShader(pixelShader);
-        mDevice->SetVertexShader(vertexShader);
-        programBinary->dirtyAllUniforms();
-        mDxUniformsDirty = true;
-
-        mAppliedProgramBinarySerial = programBinarySerial;
-    }
-}
-
-void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
-{
-    for (std::vector<gl::Uniform*>::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub)
-    {
-        gl::Uniform *targetUniform = *ub;
-
-        if (targetUniform->dirty)
-        {
-            GLfloat *f = (GLfloat*)targetUniform->data;
-            GLint *i = (GLint*)targetUniform->data;
-
-            switch (targetUniform->type)
-            {
-              case GL_SAMPLER_2D:
-              case GL_SAMPLER_CUBE:
-                break;
-              case GL_BOOL:
-              case GL_BOOL_VEC2:
-              case GL_BOOL_VEC3:
-              case GL_BOOL_VEC4:
-                applyUniformnbv(targetUniform, i);
-                break;
-              case GL_FLOAT:
-              case GL_FLOAT_VEC2:
-              case GL_FLOAT_VEC3:
-              case GL_FLOAT_VEC4:
-              case GL_FLOAT_MAT2:
-              case GL_FLOAT_MAT3:
-              case GL_FLOAT_MAT4:
-                applyUniformnfv(targetUniform, f);
-                break;
-              case GL_INT:
-              case GL_INT_VEC2:
-              case GL_INT_VEC3:
-              case GL_INT_VEC4:
-                applyUniformniv(targetUniform, i);
-                break;
-              default:
-                UNREACHABLE();
-            }
-
-            targetUniform->dirty = false;
-        }
-    }
-
-    // Driver uniforms
-    if (mDxUniformsDirty)
-    {
-        mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4]));
-        mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4]));
-        mDxUniformsDirty = false;
-    }
-}
-
-void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v)
-{
-    if (targetUniform->psRegisterIndex >= 0)
-    {
-        mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount);
-    }
-
-    if (targetUniform->vsRegisterIndex >= 0)
-    {
-        mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount);
-    }
-}
-
-void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v)
-{
-    ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
-    GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
-
-    for (unsigned int i = 0; i < targetUniform->registerCount; i++)
-    {
-        vector[i][0] = (GLfloat)v[4 * i + 0];
-        vector[i][1] = (GLfloat)v[4 * i + 1];
-        vector[i][2] = (GLfloat)v[4 * i + 2];
-        vector[i][3] = (GLfloat)v[4 * i + 3];
-    }
-
-    applyUniformnfv(targetUniform, (GLfloat*)vector);
-}
-
-void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v)
-{
-    ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
-    GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
-
-    for (unsigned int i = 0; i < targetUniform->registerCount; i++)
-    {
-        vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f;
-        vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f;
-        vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f;
-        vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
-    }
-
-    applyUniformnfv(targetUniform, (GLfloat*)vector);
-}
-
-void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
-{
-    D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha),
-                                   gl::unorm<8>(clearParams.colorClearValue.red),
-                                   gl::unorm<8>(clearParams.colorClearValue.green),
-                                   gl::unorm<8>(clearParams.colorClearValue.blue));
-    float depth = gl::clamp01(clearParams.depthClearValue);
-    int stencil = clearParams.stencilClearValue & 0x000000FF;
-
-    unsigned int stencilUnmasked = 0x0;
-    if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil())
-    {
-        unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
-        stencilUnmasked = (0x1 << stencilSize) - 1;
-    }
-
-    bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
-
-    const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
-                                        (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
-    const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
-                                      !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
-                                        clearParams.colorMaskBlue && alphaUnmasked);
-
-    if (needMaskedColorClear || needMaskedStencilClear)
-    {
-        // State which is altered in all paths from this point to the clear call is saved.
-        // State which is altered in only some paths will be flagged dirty in the case that
-        //  that path is taken.
-        HRESULT hr;
-        if (mMaskedClearSavedState == NULL)
-        {
-            hr = mDevice->BeginStateBlock();
-            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
-
-            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
-            mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
-            mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
-            mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
-            mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
-            mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
-            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
-            mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
-            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
-            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
-            mDevice->SetPixelShader(NULL);
-            mDevice->SetVertexShader(NULL);
-            mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
-            mDevice->SetStreamSource(0, NULL, 0, 0);
-            mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
-            mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
-            mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
-            mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
-            mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
-            mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
-            mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
-
-            for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-            {
-                mDevice->SetStreamSourceFreq(i, 1);
-            }
-
-            hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
-            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
-        }
-
-        ASSERT(mMaskedClearSavedState != NULL);
-
-        if (mMaskedClearSavedState != NULL)
-        {
-            hr = mMaskedClearSavedState->Capture();
-            ASSERT(SUCCEEDED(hr));
-        }
-
-        mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
-        mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
-        mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
-        mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
-        mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
-        mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
-        mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
-        mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
-
-        if (clearParams.mask & GL_COLOR_BUFFER_BIT)
-        {
-            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
-                                    gl_d3d9::ConvertColorMask(clearParams.colorMaskRed,
-                                                              clearParams.colorMaskGreen,
-                                                              clearParams.colorMaskBlue,
-                                                              clearParams.colorMaskAlpha));
-        }
-        else
-        {
-            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
-        }
-
-        if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT))
-        {
-            mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
-            mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
-            mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
-            mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
-            mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask);
-            mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
-            mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
-            mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
-        }
-        else
-        {
-            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
-        }
-
-        mDevice->SetPixelShader(NULL);
-        mDevice->SetVertexShader(NULL);
-        mDevice->SetFVF(D3DFVF_XYZRHW);
-        mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
-        mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
-        mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
-        mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
-        mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
-        mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
-        mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
-
-        for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-        {
-            mDevice->SetStreamSourceFreq(i, 1);
-        }
-
-        float quad[4][4];   // A quadrilateral covering the target, aligned to match the edges
-        quad[0][0] = -0.5f;
-        quad[0][1] = mRenderTargetDesc.height - 0.5f;
-        quad[0][2] = 0.0f;
-        quad[0][3] = 1.0f;
-
-        quad[1][0] = mRenderTargetDesc.width - 0.5f;
-        quad[1][1] = mRenderTargetDesc.height - 0.5f;
-        quad[1][2] = 0.0f;
-        quad[1][3] = 1.0f;
-
-        quad[2][0] = -0.5f;
-        quad[2][1] = -0.5f;
-        quad[2][2] = 0.0f;
-        quad[2][3] = 1.0f;
-
-        quad[3][0] = mRenderTargetDesc.width - 0.5f;
-        quad[3][1] = -0.5f;
-        quad[3][2] = 0.0f;
-        quad[3][3] = 1.0f;
-
-        startScene();
-        mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
-
-        if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
-        {
-            mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
-            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
-            mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
-        }
-
-        if (mMaskedClearSavedState != NULL)
-        {
-            mMaskedClearSavedState->Apply();
-        }
-    }
-    else if (clearParams.mask)
-    {
-        DWORD dxClearFlags = 0;
-        if (clearParams.mask & GL_COLOR_BUFFER_BIT)
-        {
-            dxClearFlags |= D3DCLEAR_TARGET;
-        }
-        if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
-        {
-            dxClearFlags |= D3DCLEAR_ZBUFFER;
-        }
-        if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
-        {
-            dxClearFlags |= D3DCLEAR_STENCIL;
-        }
-
-        mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil);
-    }
-}
-
-void Renderer9::markAllStateDirty()
-{
-    mAppliedRenderTargetSerial = 0;
-    mAppliedDepthbufferSerial = 0;
-    mAppliedStencilbufferSerial = 0;
-    mDepthStencilInitialized = false;
-    mRenderTargetDescInitialized = false;
-
-    mForceSetDepthStencilState = true;
-    mForceSetRasterState = true;
-    mForceSetScissor = true;
-    mForceSetViewport = true;
-    mForceSetBlendState = true;
-
-    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
-    {
-        mForceSetVertexSamplerStates[i] = true;
-        mCurVertexTextureSerials[i] = 0;
-    }
-    for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
-    {
-        mForceSetPixelSamplerStates[i] = true;
-        mCurPixelTextureSerials[i] = 0;
-    }
-
-    mAppliedIBSerial = 0;
-    mAppliedProgramBinarySerial = 0;
-    mDxUniformsDirty = true;
-
-    mVertexDeclarationCache.markStateDirty();
-}
-
-void Renderer9::releaseDeviceResources()
-{
-    while (!mEventQueryPool.empty())
-    {
-        mEventQueryPool.back()->Release();
-        mEventQueryPool.pop_back();
-    }
-
-    if (mMaskedClearSavedState)
-    {
-        mMaskedClearSavedState->Release();
-        mMaskedClearSavedState = NULL;
-    }
-
-    mVertexShaderCache.clear();
-    mPixelShaderCache.clear();
-
-    delete mBlit;
-    mBlit = NULL;
-
-    delete mVertexDataManager;
-    mVertexDataManager = NULL;
-
-    delete mIndexDataManager;
-    mIndexDataManager = NULL;
-
-    delete mLineLoopIB;
-    mLineLoopIB = NULL;
-
-    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
-    {
-        delete mNullColorbufferCache[i].buffer;
-        mNullColorbufferCache[i].buffer = NULL;
-    }
-
-}
-
-
-void Renderer9::notifyDeviceLost()
-{
-    mDeviceLost = true;
-    mDisplay->notifyDeviceLost();
-}
-
-bool Renderer9::isDeviceLost()
-{
-    return mDeviceLost;
-}
-
-// set notify to true to broadcast a message to all contexts of the device loss
-bool Renderer9::testDeviceLost(bool notify)
-{
-    HRESULT status = S_OK;
-
-    if (mDeviceEx)
-    {
-        status = mDeviceEx->CheckDeviceState(NULL);
-    }
-    else if (mDevice)
-    {
-        status = mDevice->TestCooperativeLevel();
-    }
-    else
-    {
-        // No device yet, so no reset required
-    }
-
-    bool isLost = FAILED(status) || d3d9::isDeviceLostError(status);
-
-    if (isLost)
-    {
-        // ensure we note the device loss --
-        // we'll probably get this done again by notifyDeviceLost
-        // but best to remember it!
-        // Note that we don't want to clear the device loss status here
-        // -- this needs to be done by resetDevice
-        mDeviceLost = true;
-        if (notify)
-        {
-            notifyDeviceLost();
-        }
-    }
-
-    return isLost;
-}
-
-bool Renderer9::testDeviceResettable()
-{
-    HRESULT status = D3D_OK;
-
-    if (mDeviceEx)
-    {
-        status = mDeviceEx->CheckDeviceState(NULL);
-    }
-    else if (mDevice)
-    {
-        status = mDevice->TestCooperativeLevel();
-    }
-
-    // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted
-    // DEVICEREMOVED indicates the device has been stopped and must be recreated
-    switch (status)
-    {
-      case D3DERR_DEVICENOTRESET:
-      case D3DERR_DEVICEHUNG:
-        return true;
-      case D3DERR_DEVICELOST:
-        return (mDeviceEx != NULL);
-      case D3DERR_DEVICEREMOVED:
-        UNIMPLEMENTED();
-        return false;
-      default:
-        return false;
-    }
-}
-
-bool Renderer9::resetDevice()
-{
-    releaseDeviceResources();
-
-    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
-
-    HRESULT result = D3D_OK;
-    bool lost = testDeviceLost(false);
-    int attempts = 3;
-
-    while (lost && attempts > 0)
-    {
-        if (mDeviceEx)
-        {
-            Sleep(500);   // Give the graphics driver some CPU time
-            result = mDeviceEx->ResetEx(&presentParameters, NULL);
-        }
-        else
-        {
-            result = mDevice->TestCooperativeLevel();
-            while (result == D3DERR_DEVICELOST)
-            {
-                Sleep(100);   // Give the graphics driver some CPU time
-                result = mDevice->TestCooperativeLevel();
-            }
-
-            if (result == D3DERR_DEVICENOTRESET)
-            {
-                result = mDevice->Reset(&presentParameters);
-            }
-        }
-
-        lost = testDeviceLost(false);
-        attempts --;
-    }
-
-    if (FAILED(result))
-    {
-        ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
-        return false;
-    }
-
-    // reset device defaults
-    initializeDevice();
-    mDeviceLost = false;
-
-    return true;
-}
-
-void *Renderer9::getDeviceRaw()
-{
-    EVENT("()");
-    UNIMPLEMENTED();
-    return NULL;
-}
-
-DWORD Renderer9::getAdapterVendor() const
-{
-    return mAdapterIdentifier.VendorId;
-}
-
-std::string Renderer9::getRendererDescription() const
-{
-    std::ostringstream rendererString;
-
-    rendererString << mAdapterIdentifier.Description;
-    if (getShareHandleSupport())
-    {
-        rendererString << " Direct3D9Ex";
-    }
-    else
-    {
-        rendererString << " Direct3D9";
-    }
-
-    rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
-    rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
-
-    return rendererString.str();
-}
-
-GUID Renderer9::getAdapterIdentifier() const
-{
-    return mAdapterIdentifier.DeviceIdentifier;
-}
-
-void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
-{
-    for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
-    {
-        HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
-                                                           TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
-
-        multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
-    }
-}
-
-bool Renderer9::getBGRATextureSupport() const
-{
-    // DirectX 9 always supports BGRA
-    return true;
-}
-
-bool Renderer9::getDXT1TextureSupport()
-{
-    return mDXT1TextureSupport;
-}
-
-bool Renderer9::getDXT3TextureSupport()
-{
-    return mDXT3TextureSupport;
-}
-
-bool Renderer9::getDXT5TextureSupport()
-{
-    return mDXT5TextureSupport;
-}
-
-bool Renderer9::getDepthTextureSupport() const
-{
-    return mDepthTextureSupport;
-}
-
-bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable)
-{
-    *filtering = mFloat32FilterSupport;
-    *renderable = mFloat32RenderSupport;
-    return mFloat32TextureSupport;
-}
-
-bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable)
-{
-    *filtering = mFloat16FilterSupport;
-    *renderable = mFloat16RenderSupport;
-    return mFloat16TextureSupport;
-}
-
-bool Renderer9::getLuminanceTextureSupport()
-{
-    return mLuminanceTextureSupport;
-}
-
-bool Renderer9::getLuminanceAlphaTextureSupport()
-{
-    return mLuminanceAlphaTextureSupport;
-}
-
-bool Renderer9::getTextureFilterAnisotropySupport() const
-{
-    return mSupportsTextureFilterAnisotropy;
-}
-
-float Renderer9::getTextureMaxAnisotropy() const
-{
-    if (mSupportsTextureFilterAnisotropy)
-    {
-        return static_cast<float>(mDeviceCaps.MaxAnisotropy);
-    }
-    return 1.0f;
-}
-
-bool Renderer9::getEventQuerySupport()
-{
-    return mEventQuerySupport;
-}
-
-unsigned int Renderer9::getMaxVertexTextureImageUnits() const
-{
-    META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
-    return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0;
-}
-
-unsigned int Renderer9::getMaxCombinedTextureImageUnits() const
-{
-    return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
-}
-
-unsigned int Renderer9::getReservedVertexUniformVectors() const
-{
-    return 2;   // dx_ViewAdjust and dx_DepthRange.
-}
-
-unsigned int Renderer9::getReservedFragmentUniformVectors() const
-{
-    return 3;   // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
-}
-
-unsigned int Renderer9::getMaxVertexUniformVectors() const
-{
-    return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors();
-}
-
-unsigned int Renderer9::getMaxFragmentUniformVectors() const
-{
-    const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2;
-
-    return maxPixelConstantVectors - getReservedFragmentUniformVectors();
-}
-
-unsigned int Renderer9::getMaxVaryingVectors() const
-{
-    return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
-}
-
-bool Renderer9::getNonPower2TextureSupport() const
-{
-    return mSupportsNonPower2Textures;
-}
-
-bool Renderer9::getOcclusionQuerySupport() const
-{
-    return mOcclusionQuerySupport;
-}
-
-bool Renderer9::getInstancingSupport() const
-{
-    return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
-}
-
-bool Renderer9::getShareHandleSupport() const
-{
-    // PIX doesn't seem to support using share handles, so disable them.
-    return (mD3d9Ex != NULL) && !gl::perfActive();
-}
-
-bool Renderer9::getDerivativeInstructionSupport() const
-{
-    return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
-}
-
-bool Renderer9::getPostSubBufferSupport() const
-{
-    return true;
-}
-
-int Renderer9::getMajorShaderModel() const
-{
-    return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
-}
-
-float Renderer9::getMaxPointSize() const
-{
-    // Point size clamped at 1.0f for SM2
-    return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f;
-}
-
-int Renderer9::getMaxViewportDimension() const
-{
-    int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()),
-                                       (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
-    return maxTextureDimension;
-}
-
-int Renderer9::getMaxTextureWidth() const
-{
-    return (int)mDeviceCaps.MaxTextureWidth;
-}
-
-int Renderer9::getMaxTextureHeight() const
-{
-    return (int)mDeviceCaps.MaxTextureHeight;
-}
-
-bool Renderer9::get32BitIndexSupport() const
-{
-    return mDeviceCaps.MaxVertexIndex >= (1 << 16);
-}
-
-DWORD Renderer9::getCapsDeclTypes() const
-{
-    return mDeviceCaps.DeclTypes;
-}
-
-int Renderer9::getMinSwapInterval() const
-{
-    return mMinSwapInterval;
-}
-
-int Renderer9::getMaxSwapInterval() const
-{
-    return mMaxSwapInterval;
-}
-
-int Renderer9::getMaxSupportedSamples() const
-{
-    return mMaxSupportedSamples;
-}
-
-int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const
-{
-    if (requested == 0)
-    {
-        return requested;
-    }
-
-    std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
-    if (itr == mMultiSampleSupport.end())
-    {
-        if (format == D3DFMT_UNKNOWN)
-            return 0;
-        return -1;
-    }
-
-    for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
-    {
-        if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
-        {
-            return i;
-        }
-    }
-
-    return -1;
-}
-
-unsigned int Renderer9::getMaxRenderTargets() const
-{
-    // we do not support MRT in d3d9
-    return 1;
-}
-
-D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_DEPTH_COMPONENT16:
-      case GL_DEPTH_COMPONENT32_OES:
-      case GL_DEPTH24_STENCIL8_OES:
-        return D3DFMT_INTZ;
-      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-        return D3DFMT_DXT1;
-      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-        return D3DFMT_DXT3;
-      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-        return D3DFMT_DXT5;
-      case GL_RGBA32F_EXT:
-      case GL_RGB32F_EXT:
-      case GL_ALPHA32F_EXT:
-      case GL_LUMINANCE32F_EXT:
-      case GL_LUMINANCE_ALPHA32F_EXT:
-        return D3DFMT_A32B32G32R32F;
-      case GL_RGBA16F_EXT:
-      case GL_RGB16F_EXT:
-      case GL_ALPHA16F_EXT:
-      case GL_LUMINANCE16F_EXT:
-      case GL_LUMINANCE_ALPHA16F_EXT:
-        return D3DFMT_A16B16G16R16F;
-      case GL_LUMINANCE8_EXT:
-        if (getLuminanceTextureSupport())
-        {
-            return D3DFMT_L8;
-        }
-        break;
-      case GL_LUMINANCE8_ALPHA8_EXT:
-        if (getLuminanceAlphaTextureSupport())
-        {
-            return D3DFMT_A8L8;
-        }
-        break;
-      case GL_RGB8_OES:
-      case GL_RGB565:
-        return D3DFMT_X8R8G8B8;
-    }
-
-    return D3DFMT_A8R8G8B8;
-}
-
-bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
-{
-    bool result = false;
-
-    if (source && dest)
-    {
-        TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance());
-        TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance());
-
-        int levels = source9->levelCount();
-        for (int i = 0; i < levels; ++i)
-        {
-            IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false);
-            IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false);
-
-            result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
-
-            if (srcSurf) srcSurf->Release();
-            if (dstSurf) dstSurf->Release();
-
-            if (!result)
-                return false;
-        }
-    }
-
-    return result;
-}
-
-bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
-{
-    bool result = false;
-
-    if (source && dest)
-    {
-        TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance());
-        TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance());
-        int levels = source9->levelCount();
-        for (int f = 0; f < 6; f++)
-        {
-            for (int i = 0; i < levels; i++)
-            {
-                IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
-                IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
-
-                result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
-
-                if (srcSurf) srcSurf->Release();
-                if (dstSurf) dstSurf->Release();
-
-                if (!result)
-                    return false;
-            }
-        }
-    }
-
-    return result;
-}
-
-D3DPOOL Renderer9::getBufferPool(DWORD usage) const
-{
-    if (mD3d9Ex != NULL)
-    {
-        return D3DPOOL_DEFAULT;
-    }
-    else
-    {
-        if (!(usage & D3DUSAGE_DYNAMIC))
-        {
-            return D3DPOOL_MANAGED;
-        }
-    }
-
-    return D3DPOOL_DEFAULT;
-}
-
-bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                          GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
-{
-    RECT rect;
-    rect.left = sourceRect.x;
-    rect.top = sourceRect.y;
-    rect.right = sourceRect.x + sourceRect.width;
-    rect.bottom = sourceRect.y + sourceRect.height;
-
-    return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level);
-}
-
-bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                          GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
-{
-    RECT rect;
-    rect.left = sourceRect.x;
-    rect.top = sourceRect.y;
-    rect.right = sourceRect.x + sourceRect.width;
-    rect.bottom = sourceRect.y + sourceRect.height;
-
-    return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level);
-}
-
-bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
-                         bool blitRenderTarget, bool blitDepthStencil)
-{
-    endScene();
-
-    if (blitRenderTarget)
-    {
-        gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0);
-        gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0);
-        RenderTarget9 *readRenderTarget = NULL;
-        RenderTarget9 *drawRenderTarget = NULL;
-        IDirect3DSurface9* readSurface = NULL;
-        IDirect3DSurface9* drawSurface = NULL;
-
-        if (readBuffer)
-        {
-            readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget());
-        }
-        if (drawBuffer)
-        {
-            drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget());
-        }
-
-        if (readRenderTarget)
-        {
-            readSurface = readRenderTarget->getSurface();
-        }
-        if (drawRenderTarget)
-        {
-            drawSurface = drawRenderTarget->getSurface();
-        }
-
-        if (!readSurface || !drawSurface)
-        {
-            ERR("Failed to retrieve the render target.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
-        }
-
-        RECT srcRect;
-        srcRect.left = readRect.x;
-        srcRect.right = readRect.x + readRect.width;
-        srcRect.top = readRect.y;
-        srcRect.bottom = readRect.y + readRect.height;
-
-        RECT dstRect;
-        dstRect.left = drawRect.x;
-        dstRect.right = drawRect.x + drawRect.width;
-        dstRect.top = drawRect.y;
-        dstRect.bottom = drawRect.y + drawRect.height;
-
-        HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
-
-        readSurface->Release();
-        drawSurface->Release();
-
-        if (FAILED(result))
-        {
-            ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
-            return false;
-        }
-    }
-
-    if (blitDepthStencil)
-    {
-        gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
-        gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
-        RenderTarget9 *readDepthStencil = NULL;
-        RenderTarget9 *drawDepthStencil = NULL;
-        IDirect3DSurface9* readSurface = NULL;
-        IDirect3DSurface9* drawSurface = NULL;
-
-        if (readBuffer)
-        {
-            readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil());
-        }
-        if (drawBuffer)
-        {
-            drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil());
-        }
-
-        if (readDepthStencil)
-        {
-            readSurface = readDepthStencil->getSurface();
-        }
-        if (drawDepthStencil)
-        {
-            drawSurface = drawDepthStencil->getSurface();
-        }
-
-        if (!readSurface || !drawSurface)
-        {
-            ERR("Failed to retrieve the render target.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
-        }
-
-        HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
-
-        readSurface->Release();
-        drawSurface->Release();
-
-        if (FAILED(result))
-        {
-            ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
-            return false;
-        }
-    }
-
-    return true;
-}
-
-void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
-                           GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
-{
-    RenderTarget9 *renderTarget = NULL;
-    IDirect3DSurface9 *surface = NULL;
-    gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
-
-    if (colorbuffer)
-    {
-        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
-    }
-
-    if (renderTarget)
-    {
-        surface = renderTarget->getSurface();
-    }
-
-    if (!surface)
-    {
-        // context must be lost
-        return;
-    }
-
-    D3DSURFACE_DESC desc;
-    surface->GetDesc(&desc);
-
-    if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
-    {
-        UNIMPLEMENTED();   // FIXME: Requires resolve using StretchRect into non-multisampled render target
-        surface->Release();
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
-
-    HRESULT result;
-    IDirect3DSurface9 *systemSurface = NULL;
-    bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() &&
-                          x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height &&
-                          desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
-    if (directToPixels)
-    {
-        // Use the pixels ptr as a shared handle to write directly into client's memory
-        result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
-                                                      D3DPOOL_SYSTEMMEM, &systemSurface, &pixels);
-        if (FAILED(result))
-        {
-            // Try again without the shared handle
-            directToPixels = false;
-        }
-    }
-
-    if (!directToPixels)
-    {
-        result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
-                                                      D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            surface->Release();
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    result = mDevice->GetRenderTargetData(surface, systemSurface);
-    surface->Release();
-    surface = NULL;
-
-    if (FAILED(result))
-    {
-        systemSurface->Release();
-
-        // It turns out that D3D will sometimes produce more error
-        // codes than those documented.
-        if (d3d9::isDeviceLostError(result))
-        {
-            notifyDeviceLost();
-            return gl::error(GL_OUT_OF_MEMORY);
-        }
-        else
-        {
-            UNREACHABLE();
-            return;
-        }
-
-    }
-
-    if (directToPixels)
-    {
-        systemSurface->Release();
-        return;
-    }
-
-    RECT rect;
-    rect.left = gl::clamp(x, 0L, static_cast<LONG>(desc.Width));
-    rect.top = gl::clamp(y, 0L, static_cast<LONG>(desc.Height));
-    rect.right = gl::clamp(x + width, 0L, static_cast<LONG>(desc.Width));
-    rect.bottom = gl::clamp(y + height, 0L, static_cast<LONG>(desc.Height));
-
-    D3DLOCKED_RECT lock;
-    result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
-
-    if (FAILED(result))
-    {
-        UNREACHABLE();
-        systemSurface->Release();
-
-        return;   // No sensible error to generate
-    }
-
-    unsigned char *dest = (unsigned char*)pixels;
-    unsigned short *dest16 = (unsigned short*)pixels;
-
-    unsigned char *source;
-    int inputPitch;
-    if (packReverseRowOrder)
-    {
-        source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
-        inputPitch = -lock.Pitch;
-    }
-    else
-    {
-        source = (unsigned char*)lock.pBits;
-        inputPitch = lock.Pitch;
-    }
-
-    unsigned int fastPixelSize = 0;
-
-    if (desc.Format == D3DFMT_A8R8G8B8 &&
-        format == GL_BGRA_EXT &&
-        type == GL_UNSIGNED_BYTE)
-    {
-        fastPixelSize = 4;
-    }
-    else if ((desc.Format == D3DFMT_A4R4G4B4 &&
-             format == GL_BGRA_EXT &&
-             type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) ||
-             (desc.Format == D3DFMT_A1R5G5B5 &&
-             format == GL_BGRA_EXT &&
-             type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT))
-    {
-        fastPixelSize = 2;
-    }
-    else if (desc.Format == D3DFMT_A16B16G16R16F &&
-             format == GL_RGBA &&
-             type == GL_HALF_FLOAT_OES)
-    {
-        fastPixelSize = 8;
-    }
-    else if (desc.Format == D3DFMT_A32B32G32R32F &&
-             format == GL_RGBA &&
-             type == GL_FLOAT)
-    {
-        fastPixelSize = 16;
-    }
-
-    for (int j = 0; j < rect.bottom - rect.top; j++)
-    {
-        if (fastPixelSize != 0)
-        {
-            // Fast path for formats which require no translation:
-            // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE
-            // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT
-            // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT
-            // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES
-            // D3DFMT_A32B32G32R32F to RGBA/FLOAT
-            //
-            // Note that buffers with no alpha go through the slow path below.
-            memcpy(dest + j * outputPitch,
-                   source + j * inputPitch,
-                   (rect.right - rect.left) * fastPixelSize);
-            continue;
-        }
-        else if (desc.Format == D3DFMT_A8R8G8B8 &&
-                 format == GL_RGBA &&
-                 type == GL_UNSIGNED_BYTE)
-        {
-            // Fast path for swapping red with blue
-            for (int i = 0; i < rect.right - rect.left; i++)
-            {
-                unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
-                *(unsigned int*)(dest + 4 * i + j * outputPitch) =
-                    (argb & 0xFF00FF00) |       // Keep alpha and green
-                    (argb & 0x00FF0000) >> 16 | // Move red to blue
-                    (argb & 0x000000FF) << 16;  // Move blue to red
-            }
-            continue;
-        }
-
-        for (int i = 0; i < rect.right - rect.left; i++)
-        {
-            float r;
-            float g;
-            float b;
-            float a;
-
-            switch (desc.Format)
-            {
-              case D3DFMT_R5G6B5:
-                {
-                    unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
-
-                    a = 1.0f;
-                    b = (rgb & 0x001F) * (1.0f / 0x001F);
-                    g = (rgb & 0x07E0) * (1.0f / 0x07E0);
-                    r = (rgb & 0xF800) * (1.0f / 0xF800);
-                }
-                break;
-              case D3DFMT_A1R5G5B5:
-                {
-                    unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
-
-                    a = (argb & 0x8000) ? 1.0f : 0.0f;
-                    b = (argb & 0x001F) * (1.0f / 0x001F);
-                    g = (argb & 0x03E0) * (1.0f / 0x03E0);
-                    r = (argb & 0x7C00) * (1.0f / 0x7C00);
-                }
-                break;
-              case D3DFMT_A8R8G8B8:
-                {
-                    unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
-
-                    a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
-                    b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
-                    g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
-                    r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
-                }
-                break;
-              case D3DFMT_X8R8G8B8:
-                {
-                    unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
-
-                    a = 1.0f;
-                    b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
-                    g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
-                    r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
-                }
-                break;
-              case D3DFMT_A2R10G10B10:
-                {
-                    unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
-
-                    a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
-                    b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
-                    g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
-                    r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
-                }
-                break;
-              case D3DFMT_A32B32G32R32F:
-                {
-                    // float formats in D3D are stored rgba, rather than the other way round
-                    r = *((float*)(source + 16 * i + j * inputPitch) + 0);
-                    g = *((float*)(source + 16 * i + j * inputPitch) + 1);
-                    b = *((float*)(source + 16 * i + j * inputPitch) + 2);
-                    a = *((float*)(source + 16 * i + j * inputPitch) + 3);
-                }
-                break;
-              case D3DFMT_A16B16G16R16F:
-                {
-                    // float formats in D3D are stored rgba, rather than the other way round
-                    r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0));
-                    g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1));
-                    b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2));
-                    a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3));
-                }
-                break;
-              default:
-                UNIMPLEMENTED();   // FIXME
-                UNREACHABLE();
-                return;
-            }
-
-            switch (format)
-            {
-              case GL_RGBA:
-                switch (type)
-                {
-                  case GL_UNSIGNED_BYTE:
-                    dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
-                    dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
-                    dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
-                    dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
-                    break;
-                  default: UNREACHABLE();
-                }
-                break;
-              case GL_BGRA_EXT:
-                switch (type)
-                {
-                  case GL_UNSIGNED_BYTE:
-                    dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
-                    dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
-                    dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
-                    dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
-                    break;
-                  case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
-                    // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
-                    // this type is packed as follows:
-                    //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
-                    //  --------------------------------------------------------------------------------
-                    // |       4th         |        3rd         |        2nd        |   1st component   |
-                    //  --------------------------------------------------------------------------------
-                    // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
-                    dest16[i + j * outputPitch / sizeof(unsigned short)] =
-                        ((unsigned short)(15 * a + 0.5f) << 12)|
-                        ((unsigned short)(15 * r + 0.5f) << 8) |
-                        ((unsigned short)(15 * g + 0.5f) << 4) |
-                        ((unsigned short)(15 * b + 0.5f) << 0);
-                    break;
-                  case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
-                    // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
-                    // this type is packed as follows:
-                    //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
-                    //  --------------------------------------------------------------------------------
-                    // | 4th |          3rd           |           2nd          |      1st component     |
-                    //  --------------------------------------------------------------------------------
-                    // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
-                    dest16[i + j * outputPitch / sizeof(unsigned short)] =
-                        ((unsigned short)(     a + 0.5f) << 15) |
-                        ((unsigned short)(31 * r + 0.5f) << 10) |
-                        ((unsigned short)(31 * g + 0.5f) << 5) |
-                        ((unsigned short)(31 * b + 0.5f) << 0);
-                    break;
-                  default: UNREACHABLE();
-                }
-                break;
-              case GL_RGB:
-                switch (type)
-                {
-                  case GL_UNSIGNED_SHORT_5_6_5:
-                    dest16[i + j * outputPitch / sizeof(unsigned short)] =
-                        ((unsigned short)(31 * b + 0.5f) << 0) |
-                        ((unsigned short)(63 * g + 0.5f) << 5) |
-                        ((unsigned short)(31 * r + 0.5f) << 11);
-                    break;
-                  case GL_UNSIGNED_BYTE:
-                    dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
-                    dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
-                    dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
-                    break;
-                  default: UNREACHABLE();
-                }
-                break;
-              default: UNREACHABLE();
-            }
-        }
-    }
-
-    systemSurface->UnlockRect();
-
-    systemSurface->Release();
-}
-
-RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth)
-{
-    SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
-    IDirect3DSurface9 *surface = NULL;
-    if (depth)
-    {
-        surface = swapChain9->getDepthStencil();
-    }
-    else
-    {
-        surface = swapChain9->getRenderTarget();
-    }
-
-    RenderTarget9 *renderTarget = new RenderTarget9(this, surface);
-
-    return renderTarget;
-}
-
-RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
-{
-    RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples);
-    return renderTarget;
-}
-
-ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type)
-{
-    ShaderExecutable9 *executable = NULL;
-
-    switch (type)
-    {
-      case rx::SHADER_VERTEX:
-        {
-            IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length);
-            if (vshader)
-            {
-                executable = new ShaderExecutable9(function, length, vshader);
-            }
-        }
-        break;
-      case rx::SHADER_PIXEL:
-        {
-            IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length);
-            if (pshader)
-            {
-                executable = new ShaderExecutable9(function, length, pshader);
-            }
-        }
-        break;
-      default:
-        UNREACHABLE();
-        break;
-    }
-
-    return executable;
-}
-
-ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type)
-{
-    const char *profile = NULL;
-
-    switch (type)
-    {
-      case rx::SHADER_VERTEX:
-        profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0";
-        break;
-      case rx::SHADER_PIXEL:
-        profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0";
-        break;
-      default:
-        UNREACHABLE();
-        return NULL;
-    }
-
-    ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, ANGLE_COMPILE_OPTIMIZATION_LEVEL, true);
-    if (!binary)
-        return NULL;
-
-    ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type);
-    binary->Release();
-
-    return executable;
-}
-
-bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
-{
-    return mBlit->boxFilter(source, dest);
-}
-
-D3DPOOL Renderer9::getTexturePool(DWORD usage) const
-{
-    if (mD3d9Ex != NULL)
-    {
-        return D3DPOOL_DEFAULT;
-    }
-    else
-    {
-        if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
-        {
-            return D3DPOOL_MANAGED;
-        }
-    }
-
-    return D3DPOOL_DEFAULT;
-}
-
-bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
-{
-    if (source && dest)
-    {
-        HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
-
-        if (fromManaged)
-        {
-            D3DSURFACE_DESC desc;
-            source->GetDesc(&desc);
-
-            IDirect3DSurface9 *surf = 0;
-            result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
-
-            if (SUCCEEDED(result))
-            {
-                Image9::copyLockableSurfaces(surf, source);
-                result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
-                surf->Release();
-            }
-        }
-        else
-        {
-            endScene();
-            result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
-        }
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            return false;
-        }
-    }
-
-    return true;
-}
-
-Image *Renderer9::createImage()
-{
-    return new Image9();
-}
-
-void Renderer9::generateMipmap(Image *dest, Image *src)
-{
-    Image9 *src9 = Image9::makeImage9(src);
-    Image9 *dst9 = Image9::makeImage9(dest);
-    Image9::generateMipmap(dst9, src9);
-}
-
-TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
-{
-    SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
-    return new TextureStorage9_2D(this, swapChain9);
-}
-
-TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
-{
-    return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height);
-}
-
-TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
-{
-    return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size);
-}
-
-bool Renderer9::getLUID(LUID *adapterLuid) const
-{
-    adapterLuid->HighPart = 0;
-    adapterLuid->LowPart = 0;
-
-    if (mD3d9Ex)
-    {
-        mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
-        return true;
-    }
-
-    return false;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/Renderer9.h b/src/third_party/angle/src/libGLESv2/renderer/Renderer9.h
deleted file mode 100644
index 1dc244c..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/Renderer9.h
+++ /dev/null
@@ -1,353 +0,0 @@
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer9.h: Defines a back-end specific class for the D3D9 renderer.
-
-#ifndef LIBGLESV2_RENDERER_RENDERER9_H_
-#define LIBGLESV2_RENDERER_RENDERER9_H_
-
-#include "common/angleutils.h"
-#include "libGLESv2/mathutil.h"
-#include "libGLESv2/renderer/ShaderCache.h"
-#include "libGLESv2/renderer/VertexDeclarationCache.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-
-namespace gl
-{
-class Renderbuffer;
-}
-
-namespace rx
-{
-class VertexDataManager;
-class IndexDataManager;
-class StreamingIndexBufferInterface;
-struct TranslatedAttribute;
-
-class Renderer9 : public Renderer
-{
-  public:
-    Renderer9(egl::Display *display, HDC hDc, bool softwareDevice);
-    virtual ~Renderer9();
-
-    static Renderer9 *makeRenderer9(Renderer *renderer);
-
-    virtual EGLint initialize();
-    virtual bool resetDevice();
-
-    virtual void* getDeviceRaw();
-
-    virtual int generateConfigs(ConfigDesc **configDescList);
-    virtual void deleteConfigs(ConfigDesc *configDescList);
-
-    void startScene();
-    void endScene();
-
-    virtual void sync(bool block);
-
-    virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
-
-    IDirect3DQuery9* allocateEventQuery();
-    void freeEventQuery(IDirect3DQuery9* query);
-
-    // resource creation
-    IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length);
-    IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length);
-    HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
-    HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer);
-#if 0
-    void *createTexture2D();
-    void *createTextureCube();
-    void *createQuery();
-    void *createIndexBuffer();
-    void *createVertexbuffer();
-
-    // state setup
-    void applyShaders();
-    void applyConstants();
-#endif
-    virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
-    virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture);
-
-    virtual void setRasterizerState(const gl::RasterizerState &rasterState);
-    virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor,
-                               unsigned int sampleMask);
-    virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
-                                      int stencilBackRef, bool frontFaceCCW);
-
-    virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
-    virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
-                             bool ignoreViewport);
-
-    virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
-    virtual void applyShaders(gl::ProgramBinary *programBinary);
-    virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
-    virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
-    virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
-
-    virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
-    virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
-
-    virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
-
-    virtual void markAllStateDirty();
-
-    // lost device
-    void notifyDeviceLost();
-    virtual bool isDeviceLost();
-    virtual bool testDeviceLost(bool notify);
-    virtual bool testDeviceResettable();
-
-    // Renderer capabilities
-    IDirect3DDevice9 *getDevice() { return mDevice; }
-    virtual DWORD getAdapterVendor() const;
-    virtual std::string getRendererDescription() const;
-    virtual GUID getAdapterIdentifier() const;
-
-    virtual bool getBGRATextureSupport() const;
-    virtual bool getDXT1TextureSupport();
-    virtual bool getDXT3TextureSupport();
-    virtual bool getDXT5TextureSupport();
-    virtual bool getEventQuerySupport();
-    virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
-    virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
-    virtual bool getLuminanceTextureSupport();
-    virtual bool getLuminanceAlphaTextureSupport();
-    virtual unsigned int getMaxVertexTextureImageUnits() const;
-    virtual unsigned int getMaxCombinedTextureImageUnits() const;
-    virtual unsigned int getReservedVertexUniformVectors() const;
-    virtual unsigned int getReservedFragmentUniformVectors() const;
-    virtual unsigned int getMaxVertexUniformVectors() const;
-    virtual unsigned int getMaxFragmentUniformVectors() const;
-    virtual unsigned int getMaxVaryingVectors() const;
-    virtual bool getNonPower2TextureSupport() const;
-    virtual bool getDepthTextureSupport() const;
-    virtual bool getOcclusionQuerySupport() const;
-    virtual bool getInstancingSupport() const;
-    virtual bool getTextureFilterAnisotropySupport() const;
-    virtual float getTextureMaxAnisotropy() const;
-    virtual bool getShareHandleSupport() const;
-    virtual bool getDerivativeInstructionSupport() const;
-    virtual bool getPostSubBufferSupport() const;
-
-    virtual int getMajorShaderModel() const;
-    virtual float getMaxPointSize() const;
-    virtual int getMaxViewportDimension() const;
-    virtual int getMaxTextureWidth() const;
-    virtual int getMaxTextureHeight() const;
-    virtual bool get32BitIndexSupport() const;
-    DWORD getCapsDeclTypes() const;
-    virtual int getMinSwapInterval() const;
-    virtual int getMaxSwapInterval() const;
-
-    virtual GLsizei getMaxSupportedSamples() const;
-    int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
-
-    virtual unsigned int getMaxRenderTargets() const;
-
-    D3DFORMAT ConvertTextureInternalFormat(GLint internalformat);
-
-    // Pixel operations
-    virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source);
-    virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source);
-
-    virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                           GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level);
-    virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                           GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level);
-
-    virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
-                          bool blitRenderTarget, bool blitDepthStencil);
-    virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
-                            GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
-
-    // RenderTarget creation
-    virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
-    virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth);
-
-    // Shader operations
-    virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type);
-    virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type);
-
-    // Image operations
-    virtual Image *createImage();
-    virtual void generateMipmap(Image *dest, Image *source);
-    virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
-    virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
-    virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
-
-    // Buffer creation
-    virtual VertexBuffer *createVertexBuffer();
-    virtual IndexBuffer *createIndexBuffer();
-    virtual BufferStorage *createBufferStorage();
-
-    // Query and Fence creation
-    virtual QueryImpl *createQuery(GLenum type);
-    virtual FenceImpl *createFence();
-
-    // D3D9-renderer specific methods
-    bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
-
-    D3DPOOL getTexturePool(DWORD usage) const;
-
-    virtual bool getLUID(LUID *adapterLuid) const;
-
-    virtual bool setResourceTracker(EGLResourceTrackerProcAngle proc, void *userData) { return false; }
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Renderer9);
-
-    void applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v);
-    void applyUniformniv(gl::Uniform *targetUniform, const GLint *v);
-    void applyUniformnbv(gl::Uniform *targetUniform, const GLint *v);
-
-    void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
-    void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer);
-
-    void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
-    bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
-    gl::Renderbuffer *getNullColorbuffer(gl::Renderbuffer *depthbuffer);
-
-    D3DPOOL getBufferPool(DWORD usage) const;
-
-    HMODULE mD3d9Module;
-    HDC mDc;
-
-    void initializeDevice();
-    D3DPRESENT_PARAMETERS getDefaultPresentParameters();
-    void releaseDeviceResources();
-
-    UINT mAdapter;
-    D3DDEVTYPE mDeviceType;
-    bool mSoftwareDevice;   // FIXME: Deprecate
-    IDirect3D9 *mD3d9;  // Always valid after successful initialization.
-    IDirect3D9Ex *mD3d9Ex;  // Might be null if D3D9Ex is not supported.
-    IDirect3DDevice9 *mDevice;
-    IDirect3DDevice9Ex *mDeviceEx;  // Might be null if D3D9Ex is not supported.
-
-    Blit *mBlit;
-
-    EGLNativeWindowType mDeviceWindow;
-
-    bool mDeviceLost;
-    D3DCAPS9 mDeviceCaps;
-    D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
-
-    D3DPRIMITIVETYPE mPrimitiveType;
-    int mPrimitiveCount;
-    GLsizei mRepeatDraw;
-
-    bool mSceneStarted;
-    bool mSupportsNonPower2Textures;
-    bool mSupportsTextureFilterAnisotropy;
-    int mMinSwapInterval;
-    int mMaxSwapInterval;
-
-    bool mOcclusionQuerySupport;
-    bool mEventQuerySupport;
-    bool mVertexTextureSupport;
-
-    bool mDepthTextureSupport;
-
-    bool mFloat32TextureSupport;
-    bool mFloat32FilterSupport;
-    bool mFloat32RenderSupport;
-
-    bool mFloat16TextureSupport;
-    bool mFloat16FilterSupport;
-    bool mFloat16RenderSupport;
-
-    bool mDXT1TextureSupport;
-    bool mDXT3TextureSupport;
-    bool mDXT5TextureSupport;
-
-    bool mLuminanceTextureSupport;
-    bool mLuminanceAlphaTextureSupport;
-
-    std::map<D3DFORMAT, bool *> mMultiSampleSupport;
-    GLsizei mMaxSupportedSamples;
-
-    // current render target states
-    unsigned int mAppliedRenderTargetSerial;
-    unsigned int mAppliedDepthbufferSerial;
-    unsigned int mAppliedStencilbufferSerial;
-    bool mDepthStencilInitialized;
-    bool mRenderTargetDescInitialized;
-    rx::RenderTarget::Desc mRenderTargetDesc;
-    unsigned int mCurStencilSize;
-    unsigned int mCurDepthSize;
-
-    IDirect3DStateBlock9 *mMaskedClearSavedState;
-
-    // previously set render states
-    bool mForceSetDepthStencilState;
-    gl::DepthStencilState mCurDepthStencilState;
-    int mCurStencilRef;
-    int mCurStencilBackRef;
-    bool mCurFrontFaceCCW;
-
-    bool mForceSetRasterState;
-    gl::RasterizerState mCurRasterState;
-
-    bool mForceSetScissor;
-    gl::Rectangle mCurScissor;
-    bool mScissorEnabled;
-
-    bool mForceSetViewport;
-    gl::Rectangle mCurViewport;
-    float mCurNear;
-    float mCurFar;
-
-    bool mForceSetBlendState;
-    gl::BlendState mCurBlendState;
-    gl::Color mCurBlendColor;
-    GLuint mCurSampleMask;
-
-    // Currently applied sampler states
-    bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-
-    bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
-    gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
-
-    // Currently applied textures
-    unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS];
-
-    unsigned int mAppliedIBSerial;
-    unsigned int mAppliedProgramBinarySerial;
-
-    rx::dx_VertexConstants mVertexConstants;
-    rx::dx_PixelConstants mPixelConstants;
-    bool mDxUniformsDirty;
-
-    // A pool of event queries that are currently unused.
-    std::vector<IDirect3DQuery9*> mEventQueryPool;
-    VertexShaderCache mVertexShaderCache;
-    PixelShaderCache mPixelShaderCache;
-
-    VertexDataManager *mVertexDataManager;
-    VertexDeclarationCache mVertexDeclarationCache;
-
-    IndexDataManager *mIndexDataManager;
-    StreamingIndexBufferInterface *mLineLoopIB;
-
-    enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 };
-    struct NullColorbufferCacheEntry
-    {
-        UINT lruCount;
-        int width;
-        int height;
-        gl::Renderbuffer *buffer;
-    } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES];
-    UINT mMaxNullColorbufferLRU;
-
-};
-
-}
-#endif // LIBGLESV2_RENDERER_RENDERER9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/ShaderCache.h b/src/third_party/angle/src/libGLESv2/renderer/ShaderCache.h
deleted file mode 100644
index 4391ac2..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/ShaderCache.h
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects
-// keyed by their byte code.
-
-#ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_
-#define LIBGLESV2_RENDERER_SHADER_CACHE_H_
-
-#include "common/debug.h"
-
-namespace rx
-{
-template <typename ShaderObject>
-class ShaderCache
-{
-  public:
-    ShaderCache() : mDevice(NULL)
-    {
-    }
-
-    ~ShaderCache()
-    {
-        // Call clear while the device is still valid.
-        ASSERT(mMap.empty());
-    }
-
-    void initialize(IDirect3DDevice9* device)
-    {
-        mDevice = device;
-    }
-
-    ShaderObject *create(const DWORD *function, size_t length)
-    {
-        std::string key(reinterpret_cast<const char*>(function), length);
-        typename Map::iterator it = mMap.find(key);
-        if (it != mMap.end())
-        {
-            it->second->AddRef();
-            return it->second;
-        }
-
-        ShaderObject *shader;
-        HRESULT result = createShader(function, &shader);
-        if (FAILED(result))
-        {
-            return NULL;
-        }
-
-        // Random eviction policy.
-        if (mMap.size() >= kMaxMapSize)
-        {
-            mMap.begin()->second->Release();
-            mMap.erase(mMap.begin());
-        }
-
-        shader->AddRef();
-        mMap[key] = shader;
-
-        return shader;
-    }
-
-    void clear()
-    {
-        for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it)
-        {
-            it->second->Release();
-        }
-
-        mMap.clear();
-    }
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(ShaderCache);
-
-    const static size_t kMaxMapSize = 100;
-
-    HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader)
-    {
-        return mDevice->CreateVertexShader(function, shader);
-    }
-
-    HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader)
-    {
-        return mDevice->CreatePixelShader(function, shader);
-    }
-
-#ifndef HASH_MAP
-# ifdef _MSC_VER
-#  define HASH_MAP stdext::hash_map
-# else
-#  define HASH_MAP std::unordered_map
-# endif
-#endif
-
-    typedef HASH_MAP<std::string, ShaderObject*> Map;
-    Map mMap;
-
-    IDirect3DDevice9 *mDevice;
-};
-
-typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache;
-typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache;
-
-}
-
-#endif   // LIBGLESV2_RENDERER_SHADER_CACHE_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable.h
deleted file mode 100644
index 293e340..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ShaderExecutable.h: Defines a renderer-agnostic class to contain shader
-// executable implementation details.
-
-#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_
-#define LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-
-class ShaderExecutable
-{
-  public:
-    ShaderExecutable(const void *function, size_t length) : mLength(length)
-    {
-        mFunction = new char[length];
-        memcpy(mFunction, function, length);
-    }
-    
-    virtual ~ShaderExecutable()
-    {
-        delete[] mFunction;
-    }
-
-    void *getFunction() const
-    {
-        return mFunction;
-    }
-
-    size_t getLength() const
-    {
-        return mLength;
-    }
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(ShaderExecutable);
-
-    void *mFunction;
-    const size_t mLength;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp b/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp
deleted file mode 100644
index 759b436..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader
-// executable implementation details.
-
-#include "libGLESv2/renderer/renderer11_utils.h"
-#include "libGLESv2/renderer/ShaderExecutable11.h"
-
-#include "common/debug.h"
-
-namespace rx
-{
-
-ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable)
-    : ShaderExecutable(function, length)
-{
-    mPixelExecutable = executable;
-    mVertexExecutable = NULL;
-    mGeometryExecutable = NULL;
-
-    mConstantBuffer = NULL;
-}
-
-ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable)
-    : ShaderExecutable(function, length)
-{
-    mVertexExecutable = executable;
-    mPixelExecutable = NULL;
-    mGeometryExecutable = NULL;
-
-    mConstantBuffer = NULL;
-}
-
-ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable)
-    : ShaderExecutable(function, length)
-{
-    mGeometryExecutable = executable;
-    mVertexExecutable = NULL;
-    mPixelExecutable = NULL;
-
-    mConstantBuffer = NULL;
-}
-
-ShaderExecutable11::~ShaderExecutable11()
-{
-    if (mVertexExecutable)
-    {
-        mVertexExecutable->Release();
-    }
-    if (mPixelExecutable)
-    {
-        mPixelExecutable->Release();
-    }
-    if (mGeometryExecutable)
-    {
-        mGeometryExecutable->Release();
-    }
-    
-    if (mConstantBuffer)
-    {
-        mConstantBuffer->Release();
-    }
-}
-
-ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable));
-    return static_cast<ShaderExecutable11*>(executable);
-}
-
-ID3D11VertexShader *ShaderExecutable11::getVertexShader() const
-{
-    return mVertexExecutable;
-}
-
-ID3D11PixelShader *ShaderExecutable11::getPixelShader() const
-{
-    return mPixelExecutable;
-}
-
-ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const
-{
-    return mGeometryExecutable;
-}
-
-ID3D11Buffer *ShaderExecutable11::getConstantBuffer(ID3D11Device *device, unsigned int registerCount)
-{
-    if (!mConstantBuffer && registerCount > 0)
-    {
-        D3D11_BUFFER_DESC constantBufferDescription = {0};
-        constantBufferDescription.ByteWidth = registerCount * sizeof(float[4]);
-        constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC;
-        constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
-        constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-        constantBufferDescription.MiscFlags = 0;
-        constantBufferDescription.StructureByteStride = 0;
-
-        HRESULT result = device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer);
-        ASSERT(SUCCEEDED(result));
-        d3d11::ResourceTracker::Track(mConstantBuffer);
-    }
-
-    return mConstantBuffer;
-}
-
-}
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable11.h b/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable11.h
deleted file mode 100644
index c6ec1cf..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable11.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader
-// executable implementation details.
-
-#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_
-#define LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_
-
-#include "libGLESv2/renderer/ShaderExecutable.h"
-
-namespace rx
-{
-
-class ShaderExecutable11 : public ShaderExecutable
-{
-  public:
-    ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable);
-    ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable);
-    ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable);
-
-    virtual ~ShaderExecutable11();
-
-    static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutable *executable);
-
-    ID3D11PixelShader *getPixelShader() const;
-    ID3D11VertexShader *getVertexShader() const;
-    ID3D11GeometryShader *getGeometryShader() const;
-
-    ID3D11Buffer *getConstantBuffer(ID3D11Device *device, unsigned int registerCount);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11);
-
-    ID3D11PixelShader *mPixelExecutable;
-    ID3D11VertexShader *mVertexExecutable;
-    ID3D11GeometryShader *mGeometryExecutable;
-
-    ID3D11Buffer *mConstantBuffer;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp b/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp
deleted file mode 100644
index 98868a3..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader
-// executable implementation details.
-
-#include "libGLESv2/renderer/ShaderExecutable9.h"
-
-#include "common/debug.h"
-
-namespace rx
-{
-
-ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable)
-    : ShaderExecutable(function, length)
-{
-    mPixelExecutable = executable;
-    mVertexExecutable = NULL;
-}
-
-ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable)
-    : ShaderExecutable(function, length)
-{
-    mVertexExecutable = executable;
-    mPixelExecutable = NULL;
-}
-
-ShaderExecutable9::~ShaderExecutable9()
-{
-    if (mVertexExecutable)
-    {
-        mVertexExecutable->Release();
-    }
-    if (mPixelExecutable)
-    {
-        mPixelExecutable->Release();
-    }
-}
-
-ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable));
-    return static_cast<ShaderExecutable9*>(executable);
-}
-
-IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const
-{
-    return mVertexExecutable;
-}
-
-IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const
-{
-    return mPixelExecutable;
-}
-
-}
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable9.h b/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable9.h
deleted file mode 100644
index fa1e6c2..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/ShaderExecutable9.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader
-// executable implementation details.
-
-#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
-#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
-
-#include "libGLESv2/renderer/ShaderExecutable.h"
-
-namespace rx
-{
-
-class ShaderExecutable9 : public ShaderExecutable
-{
-  public:
-    ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable);
-    ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable);
-    virtual ~ShaderExecutable9();
-
-    static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable);
-
-    IDirect3DPixelShader9 *getPixelShader() const;
-    IDirect3DVertexShader9 *getVertexShader() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(ShaderExecutable9);
-
-    IDirect3DPixelShader9 *mPixelExecutable;
-    IDirect3DVertexShader9 *mVertexExecutable;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/SwapChain.h b/src/third_party/angle/src/libGLESv2/renderer/SwapChain.h
deleted file mode 100644
index a6870eb..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/SwapChain.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// SwapChain.h: Defines a back-end specific class that hides the details of the
-// implementation-specific swapchain.
-
-#ifndef LIBGLESV2_RENDERER_SWAPCHAIN_H_
-#define LIBGLESV2_RENDERER_SWAPCHAIN_H_
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-
-class SwapChain
-{
-  public:
-    SwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
-        : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat)
-    {
-    }
-
-    virtual ~SwapChain() {};
-
-    virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0;
-    virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
-    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
-    virtual void recreate() = 0;
-
-    virtual HANDLE getShareHandle() {return mShareHandle;};
-
-  protected:
-    const EGLNativeWindowType mWindow;            // Window that the surface is created for.
-    const GLenum mBackBufferFormat;
-    const GLenum mDepthBufferFormat;
-
-    HANDLE mShareHandle;
-};
-
-}
-#endif // LIBGLESV2_RENDERER_SWAPCHAIN_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/third_party/angle/src/libGLESv2/renderer/SwapChain11.cpp
deleted file mode 100644
index 36de8cb..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/SwapChain11.cpp
+++ /dev/null
@@ -1,754 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
-
-#include "libGLESv2/renderer/SwapChain11.h"
-
-#include "libGLESv2/renderer/renderer11_utils.h"
-#include "libGLESv2/renderer/Renderer11.h"
-#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h"
-#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h"
-
-namespace rx
-{
-
-SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-                         GLenum backBufferFormat, GLenum depthBufferFormat)
-    : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
-{
-    mSwapChain = NULL;
-    mBackBufferTexture = NULL;
-    mBackBufferRTView = NULL;
-    mOffscreenTexture = NULL;
-    mOffscreenRTView = NULL;
-    mOffscreenSRView = NULL;
-    mDepthStencilTexture = NULL;
-    mDepthStencilDSView = NULL;
-    mQuadVB = NULL;
-    mPassThroughSampler = NULL;
-    mPassThroughIL = NULL;
-    mPassThroughVS = NULL;
-    mPassThroughPS = NULL;
-    mWidth = -1;
-    mHeight = -1;
-    mSwapInterval = 0;
-    mAppCreatedShareHandle = mShareHandle != NULL;
-    mPassThroughResourcesInit = false;
-}
-
-SwapChain11::~SwapChain11()
-{
-    release();
-}
-
-void SwapChain11::release()
-{
-    if (mSwapChain)
-    {
-        mSwapChain->Release();
-        mSwapChain = NULL;
-    }
-
-    if (mBackBufferTexture)
-    {
-        mBackBufferTexture->Release();
-        mBackBufferTexture = NULL;
-    }
-
-    if (mBackBufferRTView)
-    {
-        mBackBufferRTView->Release();
-        mBackBufferRTView = NULL;
-    }
-
-    if (mOffscreenTexture)
-    {
-        mOffscreenTexture->Release();
-        mOffscreenTexture = NULL;
-    }
-
-    if (mOffscreenRTView)
-    {
-        mOffscreenRTView->Release();
-        mOffscreenRTView = NULL;
-    }
-
-    if (mOffscreenSRView)
-    {
-        mOffscreenSRView->Release();
-        mOffscreenSRView = NULL;
-    }
-
-    if (mDepthStencilTexture)
-    {
-        mDepthStencilTexture->Release();
-        mDepthStencilTexture = NULL;
-    }
-
-    if (mDepthStencilDSView)
-    {
-        mDepthStencilDSView->Release();
-        mDepthStencilDSView = NULL;
-    }
-
-    if (mQuadVB)
-    {
-        mQuadVB->Release();
-        mQuadVB = NULL;
-    }
-
-    if (mPassThroughSampler)
-    {
-        mPassThroughSampler->Release();
-        mPassThroughSampler = NULL;
-    }
-
-    if (mPassThroughIL)
-    {
-        mPassThroughIL->Release();
-        mPassThroughIL = NULL;
-    }
-
-    if (mPassThroughVS)
-    {
-        mPassThroughVS->Release();
-        mPassThroughVS = NULL;
-    }
-
-    if (mPassThroughPS)
-    {
-        mPassThroughPS->Release();
-        mPassThroughPS = NULL;
-    }
-
-    if (!mAppCreatedShareHandle)
-    {
-        mShareHandle = NULL;
-    }
-}
-
-void SwapChain11::releaseOffscreenTexture()
-{
-    if (mOffscreenTexture)
-    {
-        mOffscreenTexture->Release();
-        mOffscreenTexture = NULL;
-    }
-
-    if (mOffscreenRTView)
-    {
-        mOffscreenRTView->Release();
-        mOffscreenRTView = NULL;
-    }
-
-    if (mOffscreenSRView)
-    {
-        mOffscreenSRView->Release();
-        mOffscreenSRView = NULL;
-    }
-
-    if (mDepthStencilTexture)
-    {
-        mDepthStencilTexture->Release();
-        mDepthStencilTexture = NULL;
-    }
-
-    if (mDepthStencilDSView)
-    {
-        mDepthStencilDSView->Release();
-        mDepthStencilDSView = NULL;
-    }
-}
-
-EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
-{
-    ID3D11Device *device = mRenderer->getDevice();
-
-    ASSERT(device != NULL);
-
-    // D3D11 does not allow zero size textures
-    ASSERT(backbufferWidth >= 1);
-    ASSERT(backbufferHeight >= 1);
-
-    // Preserve the render target content
-    ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
-    if (previousOffscreenTexture)
-    {
-        previousOffscreenTexture->AddRef();
-    }
-    const int previousWidth = mWidth;
-    const int previousHeight = mHeight;
-
-    releaseOffscreenTexture();
-
-    // If the app passed in a share handle, open the resource
-    // See EGL_ANGLE_d3d_share_handle_client_buffer
-    if (mAppCreatedShareHandle)
-    {
-        ID3D11Resource *tempResource11;
-        HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
-
-        if (FAILED(result))
-        {
-            ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
-            release();
-            return EGL_BAD_PARAMETER;
-        }
-
-        result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
-        tempResource11->Release();
-
-        if (FAILED(result))
-        {
-            ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
-            release();
-            return EGL_BAD_PARAMETER;
-        }
-
-        // Validate offscreen texture parameters
-        D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
-        mOffscreenTexture->GetDesc(&offscreenTextureDesc);
-
-        if (offscreenTextureDesc.Width != (UINT)backbufferWidth
-            || offscreenTextureDesc.Height != (UINT)backbufferHeight
-            || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
-            || offscreenTextureDesc.MipLevels != 1
-            || offscreenTextureDesc.ArraySize != 1)
-        {
-            ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
-            release();
-            return EGL_BAD_PARAMETER;
-        }
-    }
-    else
-    {
-        const bool useSharedResource = (mWindow == ANGLE_NO_WINDOW) && mRenderer->getShareHandleSupport();
-
-        D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
-        offscreenTextureDesc.Width = backbufferWidth;
-        offscreenTextureDesc.Height = backbufferHeight;
-        offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
-        offscreenTextureDesc.MipLevels = 1;
-        offscreenTextureDesc.ArraySize = 1;
-        offscreenTextureDesc.SampleDesc.Count = 1;
-        offscreenTextureDesc.SampleDesc.Quality = 0;
-        offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
-        offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
-        offscreenTextureDesc.CPUAccessFlags = 0;
-        offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
-
-        HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
-
-        if (FAILED(result))
-        {
-            ERR("Could not create offscreen texture: %08lX", result);
-            release();
-
-            if (d3d11::isDeviceLostError(result))
-            {
-                return EGL_CONTEXT_LOST;
-            }
-            else
-            {
-                return EGL_BAD_ALLOC;
-            }
-        }
-        d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
-        d3d11::ResourceTracker::Track(mOffscreenTexture);
-
-        // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
-        if (useSharedResource)
-        {
-            IDXGIResource *offscreenTextureResource = NULL;
-            result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
-
-            // Fall back to no share handle on failure
-            if (FAILED(result))
-            {
-                ERR("Could not query offscreen texture resource: %08lX", result);
-            }
-            else
-            {
-                result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
-
-                if (FAILED(result))
-                {
-                    mShareHandle = NULL;
-                    ERR("Could not get offscreen texture shared handle: %08lX", result);
-                }
-            }
-        }
-    }
-
-    HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
-
-    ASSERT(SUCCEEDED(result));
-    d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
-
-    result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
-    ASSERT(SUCCEEDED(result));
-    d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
-
-    if (mDepthBufferFormat != GL_NONE)
-    {
-        D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
-        depthStencilDesc.Width = backbufferWidth;
-        depthStencilDesc.Height = backbufferHeight;
-        depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
-        depthStencilDesc.MipLevels = 1;
-        depthStencilDesc.ArraySize = 1;
-        depthStencilDesc.SampleDesc.Count = 1;
-        depthStencilDesc.SampleDesc.Quality = 0;
-        depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
-        depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
-        depthStencilDesc.CPUAccessFlags = 0;
-        depthStencilDesc.MiscFlags = 0;
-
-        result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
-        if (FAILED(result))
-        {
-            ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
-            release();
-
-            if (d3d11::isDeviceLostError(result))
-            {
-                return EGL_CONTEXT_LOST;
-            }
-            else
-            {
-                return EGL_BAD_ALLOC;
-            }
-        }
-        d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
-        d3d11::ResourceTracker::Track(mDepthStencilTexture);
-
-        result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
-        ASSERT(SUCCEEDED(result));
-        d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
-    }
-
-    mWidth = backbufferWidth;
-    mHeight = backbufferHeight;
-
-    if (previousOffscreenTexture != NULL)
-    {
-        D3D11_BOX sourceBox = {0};
-        sourceBox.left = 0;
-        sourceBox.right = std::min(previousWidth, mWidth);
-        sourceBox.top = std::max(previousHeight - mHeight, 0);
-        sourceBox.bottom = previousHeight;
-        sourceBox.front = 0;
-        sourceBox.back = 1;
-
-        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-        const int yoffset = std::max(mHeight - previousHeight, 0);
-        deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
-
-        previousOffscreenTexture->Release();
-
-        if (mSwapChain)
-        {
-            swapRect(0, 0, mWidth, mHeight);
-        }
-    }
-
-    return EGL_SUCCESS;
-}
-
-EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
-{
-    ID3D11Device *device = mRenderer->getDevice();
-
-    if (device == NULL)
-    {
-        return EGL_BAD_ACCESS;
-    }
-
-    // Can only call resize if we have already created our swap buffer and resources
-    ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
-
-    if (mBackBufferTexture)
-    {
-        mBackBufferTexture->Release();
-        mBackBufferTexture = NULL;
-    }
-
-    if (mBackBufferRTView)
-    {
-        mBackBufferRTView->Release();
-        mBackBufferRTView = NULL;
-    }
-
-    // Resize swap chain
-    DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
-    HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
-
-    if (FAILED(result))
-    {
-        ERR("Error resizing swap chain buffers: 0x%08X", result);
-        release();
-
-        if (d3d11::isDeviceLostError(result))
-        {
-            return EGL_CONTEXT_LOST;
-        }
-        else
-        {
-            return EGL_BAD_ALLOC;
-        }
-    }
-
-    result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
-    ASSERT(SUCCEEDED(result));
-    if (SUCCEEDED(result))
-    {
-        d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
-    }
-
-    result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
-    ASSERT(SUCCEEDED(result));
-    if (SUCCEEDED(result))
-    {
-        d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
-    }
-
-    return resetOffscreenTexture(backbufferWidth, backbufferHeight);
-}
-
-EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
-{
-    ID3D11Device *device = mRenderer->getDevice();
-
-    if (device == NULL)
-    {
-        return EGL_BAD_ACCESS;
-    }
-
-    // Release specific resources to free up memory for the new render target, while the
-    // old render target still exists for the purpose of preserving its contents.
-    if (mSwapChain)
-    {
-        mSwapChain->Release();
-        mSwapChain = NULL;
-    }
-
-    if (mBackBufferTexture)
-    {
-        mBackBufferTexture->Release();
-        mBackBufferTexture = NULL;
-    }
-
-    if (mBackBufferRTView)
-    {
-        mBackBufferRTView->Release();
-        mBackBufferRTView = NULL;
-    }
-
-    mSwapInterval = static_cast<unsigned int>(swapInterval);
-    if (mSwapInterval > 4)
-    {
-        // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
-        return EGL_BAD_PARAMETER;
-    }
-
-    // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
-    if (backbufferWidth < 1 || backbufferHeight < 1)
-    {
-        releaseOffscreenTexture();
-        return EGL_SUCCESS;
-    }
-
-    if (mWindow != ANGLE_NO_WINDOW)
-    {
-        EGLint result = createSwapChain(backbufferWidth, backbufferHeight, &mSwapChain);
-        if (result != EGL_SUCCESS)
-        {
-            ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
-            release();
-
-            return result;
-        }
-
-        HRESULT hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
-        ASSERT(SUCCEEDED(hr));
-        d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
-
-        hr = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
-        ASSERT(SUCCEEDED(hr));
-        d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
-    }
-
-    // If we are resizing the swap chain, we don't wish to recreate all the static resources
-    if (!mPassThroughResourcesInit)
-    {
-        mPassThroughResourcesInit = true;
-        initPassThroughResources();
-    }
-
-    return resetOffscreenTexture(backbufferWidth, backbufferHeight);
-}
-
-void SwapChain11::initPassThroughResources()
-{
-    ID3D11Device *device = mRenderer->getDevice();
-
-    ASSERT(device != NULL);
-
-    // Make sure our resources are all not allocated, when we create
-    ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
-    ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
-
-    D3D11_BUFFER_DESC vbDesc;
-    vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
-    vbDesc.Usage = D3D11_USAGE_DYNAMIC;
-    vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
-    vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-    vbDesc.MiscFlags = 0;
-    vbDesc.StructureByteStride = 0;
-
-    HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
-    ASSERT(SUCCEEDED(result));
-    d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
-    d3d11::ResourceTracker::Track(mQuadVB);
-
-    D3D11_SAMPLER_DESC samplerDesc;
-    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
-    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
-    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
-    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
-    samplerDesc.MipLODBias = 0.0f;
-    samplerDesc.MaxAnisotropy = 0;
-    samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
-    samplerDesc.BorderColor[0] = 0.0f;
-    samplerDesc.BorderColor[1] = 0.0f;
-    samplerDesc.BorderColor[2] = 0.0f;
-    samplerDesc.BorderColor[3] = 0.0f;
-    samplerDesc.MinLOD = 0;
-    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
-
-    result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
-    ASSERT(SUCCEEDED(result));
-    d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
-
-    D3D11_INPUT_ELEMENT_DESC quadLayout[] =
-    {
-        { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-    };
-
-    result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
-    ASSERT(SUCCEEDED(result));
-    d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
-
-    result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
-    ASSERT(SUCCEEDED(result));
-    d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
-
-    result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
-    ASSERT(SUCCEEDED(result));
-    d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
-}
-
-// parameters should be validated/clamped by caller
-EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
-{
-    if (!mSwapChain)
-    {
-        return EGL_SUCCESS;
-    }
-
-    ID3D11Device *device = mRenderer->getDevice();
-    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-
-    // Set vertices
-    D3D11_MAPPED_SUBRESOURCE mappedResource;
-    HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-    if (FAILED(result))
-    {
-        return EGL_BAD_ACCESS;
-    }
-
-    d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
-
-    // Create a quad in homogeneous coordinates
-    float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
-    float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
-    float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
-    float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
-
-    float u1 = x / float(mWidth);
-    float v1 = y / float(mHeight);
-    float u2 = (x + width) / float(mWidth);
-    float v2 = (y + height) / float(mHeight);
-
-    d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
-    d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
-    d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
-    d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
-
-    deviceContext->Unmap(mQuadVB, 0);
-
-    static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
-    static UINT startIdx = 0;
-    deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
-
-    // Apply state
-    deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
-
-    static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
-    deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
-
-    deviceContext->RSSetState(NULL);
-
-    // Apply shaders
-    deviceContext->IASetInputLayout(mPassThroughIL);
-    deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-    deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
-    deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
-    deviceContext->GSSetShader(NULL, NULL, 0);
-
-    // Apply render targets
-    mRenderer->setOneTimeRenderTarget(mBackBufferRTView);
-
-    // Set the viewport
-    D3D11_VIEWPORT viewport;
-    viewport.TopLeftX = 0;
-    viewport.TopLeftY = 0;
-    viewport.Width = mWidth;
-    viewport.Height = mHeight;
-    viewport.MinDepth = 0.0f;
-    viewport.MaxDepth = 1.0f;
-    deviceContext->RSSetViewports(1, &viewport);
-
-    // Apply textures
-    deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
-    deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
-
-    // Draw
-    deviceContext->Draw(4, 0);
-    result = mSwapChain->Present(mSwapInterval, 0);
-
-    if (result == DXGI_ERROR_DEVICE_REMOVED)
-    {
-        HRESULT removedReason = device->GetDeviceRemovedReason();
-        ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
-        return EGL_CONTEXT_LOST;
-    }
-    else if (result == DXGI_ERROR_DEVICE_RESET)
-    {
-        ERR("Present failed: the D3D11 device was reset from a bad command.");
-        return EGL_CONTEXT_LOST;
-    }
-    else if (FAILED(result))
-    {
-        ERR("Present failed with error code 0x%08X", result);
-    }
-
-    // Unbind
-    static ID3D11ShaderResourceView *const nullSRV = NULL;
-    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
-
-    mRenderer->unapplyRenderTargets();
-    mRenderer->markAllStateDirty();
-
-    return EGL_SUCCESS;
-}
-
-// Increments refcount on texture.
-// caller must Release() the returned texture
-ID3D11Texture2D *SwapChain11::getOffscreenTexture()
-{
-    if (mOffscreenTexture)
-    {
-        mOffscreenTexture->AddRef();
-    }
-
-    return mOffscreenTexture;
-}
-
-// Increments refcount on view.
-// caller must Release() the returned view
-ID3D11RenderTargetView *SwapChain11::getRenderTarget()
-{
-    if (mOffscreenRTView)
-    {
-        mOffscreenRTView->AddRef();
-    }
-
-    return mOffscreenRTView;
-}
-
-// Increments refcount on view.
-// caller must Release() the returned view
-ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
-{
-    if (mOffscreenSRView)
-    {
-        mOffscreenSRView->AddRef();
-    }
-
-    return mOffscreenSRView;
-}
-
-// Increments refcount on view.
-// caller must Release() the returned view
-ID3D11DepthStencilView *SwapChain11::getDepthStencil()
-{
-    if (mDepthStencilDSView)
-    {
-        mDepthStencilDSView->AddRef();
-    }
-
-    return mDepthStencilDSView;
-}
-
-ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
-{
-    if (mDepthStencilTexture)
-    {
-        mDepthStencilTexture->AddRef();
-    }
-
-    return mDepthStencilTexture;
-}
-
-SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
-    return static_cast<rx::SwapChain11*>(swapChain);
-}
-
-void SwapChain11::recreate()
-{
-    // possibly should use this method instead of reset
-}
-
-#if defined(ANGLE_WIN32)
-SwapChain11* CreateSwapChainWin32(Renderer11 *, EGLNativeWindowType, HANDLE,
-                                  GLenum, GLenum);
-#elif defined(ANGLE_WINRT)
-SwapChain11* CreateSwapChainWinRT(Renderer11 *, EGLNativeWindowType, HANDLE,
-                                  GLenum, GLenum);
-#endif
-
-SwapChain11 *SwapChain11::create(
-    Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-    GLenum backBufferFormat, GLenum depthBufferFormat)
-{
-#if defined(ANGLE_WIN32)
-    return CreateSwapChainWin32(renderer, window, shareHandle,
-                                backBufferFormat, depthBufferFormat);
-#elif defined(ANGLE_WINRT)
-    return CreateSwapChainWinRT(renderer, window, shareHandle,
-                                backBufferFormat, depthBufferFormat);
-#endif
-
-    return NULL;
-}
-
-} // namespace rx
diff --git a/src/third_party/angle/src/libGLESv2/renderer/SwapChain11.h b/src/third_party/angle/src/libGLESv2/renderer/SwapChain11.h
deleted file mode 100644
index 852dfa4..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/SwapChain11.h
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain.
-
-#ifndef LIBGLESV2_RENDERER_SWAPCHAIN11_H_
-#define LIBGLESV2_RENDERER_SWAPCHAIN11_H_
-
-#include "common/angleutils.h"
-#include "libGLESv2/renderer/SwapChain.h"
-
-namespace rx
-{
-class Renderer11;
-
-class SwapChain11 : public SwapChain
-{
-  public:
-    // Creates an instance of API specific implementation of SwapChain11
-    static SwapChain11 *create(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-                               GLenum backBufferFormat, GLenum depthBufferFormat);
-    virtual ~SwapChain11();
-
-    EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
-    virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
-    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
-    virtual void recreate();
-
-    virtual ID3D11Texture2D *getOffscreenTexture();
-    virtual ID3D11RenderTargetView *getRenderTarget();
-    virtual ID3D11ShaderResourceView *getRenderTargetShaderResource();
-
-    virtual ID3D11Texture2D *getDepthStencilTexture();
-    virtual ID3D11DepthStencilView *getDepthStencil();
-
-    Renderer11 *getRenderer() const { return mRenderer; }
-    EGLint getWidth() const { return mWidth; }
-    EGLint getHeight() const { return mHeight; }
-
-    static SwapChain11 *makeSwapChain11(SwapChain *swapChain);
-
-  protected:
-    SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-                GLenum backBufferFormat, GLenum depthBufferFormat);
-
-    // Api specific swap chain creation
-    virtual EGLint createSwapChain(int backbufferWidth, int backbufferHeight, IDXGISwapChain **outSwapChain) = 0;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(SwapChain11);
-
-    void release();
-    void initPassThroughResources();
-    void releaseOffscreenTexture();
-    EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight);
-
-    Renderer11 *mRenderer;
-    EGLint mHeight;
-    EGLint mWidth;
-    bool mAppCreatedShareHandle;
-    unsigned int mSwapInterval;
-    bool mPassThroughResourcesInit;
-
-    IDXGISwapChain *mSwapChain;
-
-    ID3D11Texture2D *mBackBufferTexture;
-    ID3D11RenderTargetView *mBackBufferRTView;
-
-    ID3D11Texture2D *mOffscreenTexture;
-    ID3D11RenderTargetView *mOffscreenRTView;
-    ID3D11ShaderResourceView *mOffscreenSRView;
-
-    ID3D11Texture2D *mDepthStencilTexture;
-    ID3D11DepthStencilView *mDepthStencilDSView;
-
-    ID3D11Buffer *mQuadVB;
-    ID3D11SamplerState *mPassThroughSampler;
-    ID3D11InputLayout *mPassThroughIL;
-    ID3D11VertexShader *mPassThroughVS;
-    ID3D11PixelShader *mPassThroughPS;
-};
-
-}
-#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/SwapChain9.cpp b/src/third_party/angle/src/libGLESv2/renderer/SwapChain9.cpp
deleted file mode 100644
index 8dfbb3b..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/SwapChain9.cpp
+++ /dev/null
@@ -1,434 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.
-
-#include "libGLESv2/renderer/SwapChain9.h"
-#include "libGLESv2/renderer/renderer9_utils.h"
-#include "libGLESv2/renderer/Renderer9.h"
-
-namespace rx
-{
-
-SwapChain9::SwapChain9(Renderer9 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-                       GLenum backBufferFormat, GLenum depthBufferFormat)
-    : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
-{
-    mSwapChain = NULL;
-    mBackBuffer = NULL;
-    mDepthStencil = NULL;
-    mRenderTarget = NULL;
-    mOffscreenTexture = NULL;
-    mWidth = -1;
-    mHeight = -1;
-    mSwapInterval = -1;
-}
-
-SwapChain9::~SwapChain9()
-{
-    release();
-}
-
-void SwapChain9::release()
-{
-    if (mSwapChain)
-    {
-        mSwapChain->Release();
-        mSwapChain = NULL;
-    }
-
-    if (mBackBuffer)
-    {
-        mBackBuffer->Release();
-        mBackBuffer = NULL;
-    }
-
-    if (mDepthStencil)
-    {
-        mDepthStencil->Release();
-        mDepthStencil = NULL;
-    }
-
-    if (mRenderTarget)
-    {
-        mRenderTarget->Release();
-        mRenderTarget = NULL;
-    }
-
-    if (mOffscreenTexture)
-    {
-        mOffscreenTexture->Release();
-        mOffscreenTexture = NULL;
-    }
-
-    if (mWindow)
-        mShareHandle = NULL;
-}
-
-static DWORD convertInterval(EGLint interval)
-{
-    switch(interval)
-    {
-      case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
-      case 1: return D3DPRESENT_INTERVAL_ONE;
-      case 2: return D3DPRESENT_INTERVAL_TWO;
-      case 3: return D3DPRESENT_INTERVAL_THREE;
-      case 4: return D3DPRESENT_INTERVAL_FOUR;
-      default: UNREACHABLE();
-    }
-
-    return D3DPRESENT_INTERVAL_DEFAULT;
-}
-
-EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight)
-{
-    // D3D9 does not support resizing swap chains without recreating them
-    return reset(backbufferWidth, backbufferHeight, mSwapInterval);
-}
-
-EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
-{
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    if (device == NULL)
-    {
-        return EGL_BAD_ACCESS;
-    }
-
-    // Evict all non-render target textures to system memory and release all resources
-    // before reallocating them to free up as much video memory as possible.
-    device->EvictManagedResources();
-
-    HRESULT result;
-
-    // Release specific resources to free up memory for the new render target, while the
-    // old render target still exists for the purpose of preserving its contents.
-    if (mSwapChain)
-    {
-        mSwapChain->Release();
-        mSwapChain = NULL;
-    }
-
-    if (mBackBuffer)
-    {
-        mBackBuffer->Release();
-        mBackBuffer = NULL;
-    }
-
-    if (mOffscreenTexture)
-    {
-        mOffscreenTexture->Release();
-        mOffscreenTexture = NULL;
-    }
-
-    if (mDepthStencil)
-    {
-        mDepthStencil->Release();
-        mDepthStencil = NULL;
-    }
-
-    HANDLE *pShareHandle = NULL;
-    if (!mWindow && mRenderer->getShareHandleSupport())
-    {
-        pShareHandle = &mShareHandle;
-    }
-
-    result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
-                                   gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT,
-                                   &mOffscreenTexture, pShareHandle);
-    if (FAILED(result))
-    {
-        ERR("Could not create offscreen texture: %08lX", result);
-        release();
-
-        if (d3d9::isDeviceLostError(result))
-        {
-            return EGL_CONTEXT_LOST;
-        }
-        else
-        {
-            return EGL_BAD_ALLOC;
-        }
-    }
-
-    IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
-
-    result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
-    ASSERT(SUCCEEDED(result));
-
-    if (oldRenderTarget)
-    {
-        RECT rect =
-        {
-            0, 0,
-            mWidth, mHeight
-        };
-
-        if (rect.right > static_cast<LONG>(backbufferWidth))
-        {
-            rect.right = backbufferWidth;
-        }
-
-        if (rect.bottom > static_cast<LONG>(backbufferHeight))
-        {
-            rect.bottom = backbufferHeight;
-        }
-
-        mRenderer->endScene();
-
-        result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
-        ASSERT(SUCCEEDED(result));
-
-        oldRenderTarget->Release();
-    }
-
-    if (mWindow)
-    {
-        D3DPRESENT_PARAMETERS presentParameters = {0};
-        presentParameters.AutoDepthStencilFormat = gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat);
-        presentParameters.BackBufferCount = 1;
-        presentParameters.BackBufferFormat = gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat);
-        presentParameters.EnableAutoDepthStencil = FALSE;
-        presentParameters.Flags = 0;
-        presentParameters.hDeviceWindow = mWindow;
-        presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
-        presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
-        presentParameters.PresentationInterval = convertInterval(swapInterval);
-        presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
-        presentParameters.Windowed = TRUE;
-        presentParameters.BackBufferWidth = backbufferWidth;
-        presentParameters.BackBufferHeight = backbufferHeight;
-
-        // http://crbug.com/140239
-        // http://crbug.com/143434
-        //
-        // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width
-        // when using the integrated Intel. This rounds the width up rather than down.
-        //
-        // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
-        // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
-        if (mRenderer->getAdapterVendor() == VENDOR_ID_INTEL)
-        {
-            presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
-        }
-
-        result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
-
-            ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
-            release();
-
-            if (d3d9::isDeviceLostError(result))
-            {
-                return EGL_CONTEXT_LOST;
-            }
-            else
-            {
-                return EGL_BAD_ALLOC;
-            }
-        }
-
-        result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
-        ASSERT(SUCCEEDED(result));
-        InvalidateRect(mWindow, NULL, FALSE);
-    }
-
-    if (mDepthBufferFormat != GL_NONE)
-    {
-        result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
-                                                   gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat),
-                                                   D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
-
-            ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
-            release();
-
-            if (d3d9::isDeviceLostError(result))
-            {
-                return EGL_CONTEXT_LOST;
-            }
-            else
-            {
-                return EGL_BAD_ALLOC;
-            }
-        }
-    }
-
-    mWidth = backbufferWidth;
-    mHeight = backbufferHeight;
-    mSwapInterval = swapInterval;
-
-    return EGL_SUCCESS;
-}
-
-// parameters should be validated/clamped by caller
-EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
-{
-    if (!mSwapChain)
-    {
-        return EGL_SUCCESS;
-    }
-
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-
-    // Disable all pipeline operations
-    device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
-    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
-    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
-    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
-    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
-    device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
-    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
-    device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
-    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
-    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
-    device->SetPixelShader(NULL);
-    device->SetVertexShader(NULL);
-
-    device->SetRenderTarget(0, mBackBuffer);
-    device->SetDepthStencilSurface(NULL);
-
-    device->SetTexture(0, mOffscreenTexture);
-    device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
-    device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
-    device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
-    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
-    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
-    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
-    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
-    device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
-
-    D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f};
-    device->SetViewport(&viewport);
-
-    float x1 = x - 0.5f;
-    float y1 = (mHeight - y - height) - 0.5f;
-    float x2 = (x + width) - 0.5f;
-    float y2 = (mHeight - y) - 0.5f;
-
-    float u1 = x / float(mWidth);
-    float v1 = y / float(mHeight);
-    float u2 = (x + width) / float(mWidth);
-    float v2 = (y + height) / float(mHeight);
-
-    float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
-                        {x2, y1, 0.0f, 1.0f, u2, v2},
-                        {x2, y2, 0.0f, 1.0f, u2, v1},
-                        {x1, y2, 0.0f, 1.0f, u1, v1}};   // x, y, z, rhw, u, v
-
-    mRenderer->startScene();
-    device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
-    mRenderer->endScene();
-
-    device->SetTexture(0, NULL);
-
-    RECT rect =
-    {
-        x, mHeight - y - height,
-        x + width, mHeight - y
-    };
-
-    HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
-
-    mRenderer->markAllStateDirty();
-
-    if (d3d9::isDeviceLostError(result))
-    {
-        return EGL_CONTEXT_LOST;
-    }
-
-    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
-    {
-        return EGL_BAD_ALLOC;
-    }
-
-    ASSERT(SUCCEEDED(result));
-
-    return EGL_SUCCESS;
-}
-
-// Increments refcount on surface.
-// caller must Release() the returned surface
-IDirect3DSurface9 *SwapChain9::getRenderTarget()
-{
-    if (mRenderTarget)
-    {
-        mRenderTarget->AddRef();
-    }
-
-    return mRenderTarget;
-}
-
-// Increments refcount on surface.
-// caller must Release() the returned surface
-IDirect3DSurface9 *SwapChain9::getDepthStencil()
-{
-    if (mDepthStencil)
-    {
-        mDepthStencil->AddRef();
-    }
-
-    return mDepthStencil;
-}
-
-// Increments refcount on texture.
-// caller must Release() the returned texture
-IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
-{
-    if (mOffscreenTexture)
-    {
-        mOffscreenTexture->AddRef();
-    }
-
-    return mOffscreenTexture;
-}
-
-SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain));
-    return static_cast<rx::SwapChain9*>(swapChain);
-}
-
-void SwapChain9::recreate()
-{
-    if (!mSwapChain)
-    {
-        return;
-    }
-
-    IDirect3DDevice9 *device = mRenderer->getDevice();
-    if (device == NULL)
-    {
-        return;
-    }
-
-    D3DPRESENT_PARAMETERS presentParameters;
-    HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
-    ASSERT(SUCCEEDED(result));
-
-    IDirect3DSwapChain9* newSwapChain = NULL;
-    result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain);
-    if (FAILED(result))
-    {
-        return;
-    }
-
-    mSwapChain->Release();
-    mSwapChain = newSwapChain;
-
-    mBackBuffer->Release();
-    result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
-    ASSERT(SUCCEEDED(result));
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/SwapChain9.h b/src/third_party/angle/src/libGLESv2/renderer/SwapChain9.h
deleted file mode 100644
index 83ffd09..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/SwapChain9.h
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain.
-
-#ifndef LIBGLESV2_RENDERER_SWAPCHAIN9_H_
-#define LIBGLESV2_RENDERER_SWAPCHAIN9_H_
-
-#include "common/angleutils.h"
-#include "libGLESv2/renderer/SwapChain.h"
-
-namespace rx
-{
-class Renderer9;
-
-class SwapChain9 : public SwapChain
-{
-  public:
-    SwapChain9(Renderer9 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-               GLenum backBufferFormat, GLenum depthBufferFormat);
-    virtual ~SwapChain9();
-
-    EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
-    virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
-    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
-    virtual void recreate();
-
-    virtual IDirect3DSurface9 *getRenderTarget();
-    virtual IDirect3DSurface9 *getDepthStencil();
-    virtual IDirect3DTexture9 *getOffscreenTexture();
-
-    static SwapChain9 *makeSwapChain9(SwapChain *swapChain);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(SwapChain9);
-
-    void release();
-
-    Renderer9 *mRenderer;
-    EGLint mHeight;
-    EGLint mWidth;
-    EGLint mSwapInterval;
-
-    IDirect3DSwapChain9 *mSwapChain;
-    IDirect3DSurface9 *mBackBuffer;
-    IDirect3DSurface9 *mRenderTarget;
-    IDirect3DSurface9 *mDepthStencil;
-    IDirect3DTexture9* mOffscreenTexture;
-};
-
-}
-#endif // LIBGLESV2_RENDERER_SWAPCHAIN9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage.cpp b/src/third_party/angle/src/libGLESv2/renderer/TextureStorage.cpp
deleted file mode 100644
index 5ef4965..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TextureStorage.cpp: Implements the abstract rx::TextureStorageInterface class and its concrete derived
-// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the
-// GPU-side texture.
-
-#include "libGLESv2/renderer/TextureStorage.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Texture.h"
-
-#include "common/debug.h"
-
-namespace rx
-{
-unsigned int TextureStorageInterface::mCurrentTextureSerial = 1;
-
-TextureStorageInterface::TextureStorageInterface()
-    : mTextureSerial(issueTextureSerial()),
-      mInstance(NULL)
-{
-}
-
-TextureStorageInterface::~TextureStorageInterface()
-{
-    delete mInstance;
-}
-
-bool TextureStorageInterface::isRenderTarget() const
-{
-    return mInstance->isRenderTarget();
-}
-
-
-bool TextureStorageInterface::isManaged() const
-{
-    return mInstance->isManaged();
-}
-
-unsigned int TextureStorageInterface::getTextureSerial() const
-{
-    return mTextureSerial;
-}
-
-unsigned int TextureStorageInterface::issueTextureSerial()
-{
-    return mCurrentTextureSerial++;
-}
-
-int TextureStorageInterface::getLodOffset() const
-{
-    return mInstance->getLodOffset();
-}
-
-
-int TextureStorageInterface::levelCount()
-{
-    return mInstance->levelCount();
-}
-
-TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain) 
-    : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial())
-{
-    mInstance = renderer->createTextureStorage2D(swapchain);
-}
-
-TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
-    : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial())
-{
-    mInstance = renderer->createTextureStorage2D(levels, internalformat, usage, forceRenderable, width, height);
-}
-
-#if defined(__LB_XB360__)
-TextureStorageInterface2D::TextureStorageInterface2D(TextureStorage *storage)
-    : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial())
-{
-    mInstance = storage;
-}
-#endif
-
-TextureStorageInterface2D::~TextureStorageInterface2D()
-{
-}
-
-RenderTarget *TextureStorageInterface2D::getRenderTarget() const
-{
-    return mInstance->getRenderTarget();
-}
-
-void TextureStorageInterface2D::generateMipmap(int level)
-{
-    mInstance->generateMipmap(level);
-}
-
-unsigned int TextureStorageInterface2D::getRenderTargetSerial(GLenum target) const
-{
-    return mRenderTargetSerial;
-}
-
-TextureStorageInterfaceCube::TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
-    : mFirstRenderTargetSerial(gl::RenderbufferStorage::issueCubeSerials())
-{
-    mInstance = renderer->createTextureStorageCube(levels, internalformat, usage, forceRenderable, size);
-}
-
-TextureStorageInterfaceCube::~TextureStorageInterfaceCube()
-{
-}
-
-RenderTarget *TextureStorageInterfaceCube::getRenderTarget(GLenum faceTarget) const
-{
-    return mInstance->getRenderTarget(faceTarget);
-}
-
-void TextureStorageInterfaceCube::generateMipmap(int face, int level)
-{
-    mInstance->generateMipmap(face, level);
-}
-
-unsigned int TextureStorageInterfaceCube::getRenderTargetSerial(GLenum target) const
-{
-    return mFirstRenderTargetSerial + gl::TextureCubeMap::faceIndex(target);
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage.h b/src/third_party/angle/src/libGLESv2/renderer/TextureStorage.h
deleted file mode 100644
index 3e468be..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage.h
+++ /dev/null
@@ -1,114 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TextureStorage.h: Defines the abstract rx::TextureStorageInterface class and its concrete derived
-// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the
-// GPU-side texture.
-
-#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
-#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
-
-#include "common/debug.h"
-
-namespace rx
-{
-class Renderer;
-class SwapChain;
-class RenderTarget;
-class Blit;
-
-class TextureStorage
-{
-  public:
-    TextureStorage() {};
-    virtual ~TextureStorage() {};
-
-    virtual int getLodOffset() const = 0;
-    virtual bool isRenderTarget() const = 0;
-    virtual bool isManaged() const = 0;
-    virtual int levelCount() = 0;
-
-    virtual RenderTarget *getRenderTarget() = 0;
-    virtual RenderTarget *getRenderTarget(GLenum faceTarget) = 0;
-    virtual void generateMipmap(int level) = 0;
-    virtual void generateMipmap(int face, int level) = 0;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorage);
-
-};
-
-class TextureStorageInterface
-{
-  public:
-    TextureStorageInterface();
-    virtual ~TextureStorageInterface();
-
-    TextureStorage *getStorageInstance() { return mInstance; }
-
-    unsigned int getTextureSerial() const;
-    virtual unsigned int getRenderTargetSerial(GLenum target) const = 0;
-
-    virtual int getLodOffset() const;
-    virtual bool isRenderTarget() const;
-    virtual bool isManaged() const;
-    virtual int levelCount();
-
-  protected:
-    TextureStorage *mInstance;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface);
-
-    const unsigned int mTextureSerial;
-    static unsigned int issueTextureSerial();
-
-    static unsigned int mCurrentTextureSerial;
-};
-
-class TextureStorageInterface2D : public TextureStorageInterface
-{
-  public:
-    TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain);
-    TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
-#if defined(__LB_XB360__)
-    // Allows a TextureStorageInterface2D to adopt an existing texture storage,
-    // rather than creating its own.
-    TextureStorageInterface2D(TextureStorage *storage);
-#endif
-    virtual ~TextureStorageInterface2D();
-
-    void generateMipmap(int level);
-    RenderTarget *getRenderTarget() const;
-
-    virtual unsigned int getRenderTargetSerial(GLenum target) const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2D);
-
-    const unsigned int mRenderTargetSerial;
-};
-
-class TextureStorageInterfaceCube : public TextureStorageInterface
-{
-  public:
-    TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
-    virtual ~TextureStorageInterfaceCube();
-
-    void generateMipmap(int face, int level);
-    RenderTarget *getRenderTarget(GLenum faceTarget) const;
-
-    virtual unsigned int getRenderTargetSerial(GLenum target) const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorageInterfaceCube);
-
-    const unsigned int mFirstRenderTargetSerial;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage11.cpp b/src/third_party/angle/src/libGLESv2/renderer/TextureStorage11.cpp
deleted file mode 100644
index e68b869..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage11.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
-// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
-
-#include "libGLESv2/renderer/TextureStorage11.h"
-
-#include "libGLESv2/renderer/Renderer11.h"
-#include "libGLESv2/renderer/RenderTarget11.h"
-#include "libGLESv2/renderer/SwapChain11.h"
-#include "libGLESv2/renderer/renderer11_utils.h"
-
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/main.h"
-
-namespace rx
-{
-
-TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
-    : mBindFlags(bindFlags),
-      mLodOffset(0),
-      mMipLevels(0),
-      mTexture(NULL),
-      mTextureFormat(DXGI_FORMAT_UNKNOWN),
-      mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
-      mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
-      mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
-      mSRV(NULL),
-      mTextureWidth(0),
-      mTextureHeight(0)
-{
-    mRenderer = Renderer11::makeRenderer11(renderer);
-}
-
-TextureStorage11::~TextureStorage11()
-{
-}
-
-TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
-    return static_cast<TextureStorage11*>(storage);
-}
-
-DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
-{
-    UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
-    
-    if (d3d11::IsDepthStencilFormat(format))
-    {
-        bindFlags |= D3D11_BIND_DEPTH_STENCIL;
-    }
-    else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
-    {
-        bindFlags |= D3D11_BIND_RENDER_TARGET;
-    }
-    return bindFlags;
-}
-
-bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
-{
-    switch(format)
-    {
-      case DXGI_FORMAT_R8G8B8A8_UNORM:
-      case DXGI_FORMAT_A8_UNORM:
-      case DXGI_FORMAT_R32G32B32A32_FLOAT:
-      case DXGI_FORMAT_R32G32B32_FLOAT:
-      case DXGI_FORMAT_R16G16B16A16_FLOAT:
-      case DXGI_FORMAT_B8G8R8A8_UNORM:
-      case DXGI_FORMAT_R8_UNORM:
-      case DXGI_FORMAT_R8G8_UNORM:
-      case DXGI_FORMAT_R16_FLOAT:
-      case DXGI_FORMAT_R16G16_FLOAT:
-        return true;
-      case DXGI_FORMAT_BC1_UNORM:
-      case DXGI_FORMAT_BC2_UNORM: 
-      case DXGI_FORMAT_BC3_UNORM:
-        return false;
-      default:
-        UNREACHABLE();
-        return false;
-    }
-}
-
-UINT TextureStorage11::getBindFlags() const
-{
-    return mBindFlags;
-}
-
-ID3D11Texture2D *TextureStorage11::getBaseTexture() const
-{
-    return mTexture;
-}
-
-int TextureStorage11::getLodOffset() const
-{
-    return mLodOffset;
-}
-
-bool TextureStorage11::isRenderTarget() const
-{
-    return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
-}
-    
-bool TextureStorage11::isManaged() const
-{
-    return false;
-}
-
-int TextureStorage11::levelCount()
-{
-    int levels = 0;
-    if (getBaseTexture())
-    {
-        levels = mMipLevels - getLodOffset();
-    }
-    return levels;
-}
-
-UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
-{
-    UINT index = 0;
-    if (getBaseTexture())
-    {
-        index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
-    }
-    return index;
-}
-
-bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource,
-                                              int level, int face, GLint xoffset, GLint yoffset,
-                                              GLsizei width, GLsizei height)
-{
-    if (srcTexture)
-    {
-        // Round up the width and height to the nearest multiple of dimension alignment
-        unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
-        width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment;
-        height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment;
-
-        D3D11_BOX srcBox;
-        srcBox.left = xoffset;
-        srcBox.top = yoffset;
-        srcBox.right = xoffset + width;
-        srcBox.bottom = yoffset + height;
-        srcBox.front = 0;
-        srcBox.back = 1;
-
-        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-        
-        ASSERT(getBaseTexture());
-        context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face),
-                                       xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox);
-        return true;
-    }
-
-    return false;
-}
-
-void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
-{
-    if (source && dest)
-    {
-        ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
-        ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
-
-        if (sourceSRV && destRTV)
-        {
-            gl::Rectangle sourceArea;
-            sourceArea.x = 0;
-            sourceArea.y = 0;
-            sourceArea.width = source->getWidth();
-            sourceArea.height = source->getHeight();
-
-            gl::Rectangle destArea;
-            destArea.x = 0;
-            destArea.y = 0;
-            destArea.width = dest->getWidth();
-            destArea.height = dest->getHeight();
-
-            mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
-                                   destRTV, destArea, dest->getWidth(), dest->getHeight(),
-                                   GL_RGBA);
-        }
-
-        if (sourceSRV)
-        {
-            sourceSRV->Release();
-        }
-        if (destRTV)
-        {
-            destRTV->Release();
-        }
-    }
-}
-
-TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
-    : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
-{
-    mTexture = swapchain->getOffscreenTexture();
-    mSRV = swapchain->getRenderTargetShaderResource();
-
-    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-    {
-        mRenderTarget[i] = NULL;
-    }
-
-    D3D11_TEXTURE2D_DESC texDesc;
-    mTexture->GetDesc(&texDesc);
-    mMipLevels = texDesc.MipLevels;
-    mTextureFormat = texDesc.Format;
-    mTextureWidth = texDesc.Width;
-    mTextureHeight = texDesc.Height;
-
-    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
-    mSRV->GetDesc(&srvDesc);
-    mShaderResourceFormat = srvDesc.Format;
-
-    ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
-    D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-    offscreenRTV->GetDesc(&rtvDesc);
-    mRenderTargetFormat = rtvDesc.Format;
-    offscreenRTV->Release();
-
-    mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
-}
-
-TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
-    : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
-{
-    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-    {
-        mRenderTarget[i] = NULL;
-    }
-
-    DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
-    if (d3d11::IsDepthStencilFormat(convertedFormat))
-    {
-        mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
-        mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
-        mDepthStencilFormat = convertedFormat;
-        mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
-    }
-    else
-    {
-        mTextureFormat = convertedFormat;
-        mShaderResourceFormat = convertedFormat;
-        mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
-        mRenderTargetFormat = convertedFormat;
-    }
-
-    // if the width or height is not positive this should be treated as an incomplete texture
-    // we handle that here by skipping the d3d texture creation
-    if (width > 0 && height > 0)
-    {
-        // adjust size if needed for compressed textures
-        gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
-
-        ID3D11Device *device = mRenderer->getDevice();
-
-        D3D11_TEXTURE2D_DESC desc;
-        desc.Width = width;      // Compressed texture size constraints?
-        desc.Height = height;
-        desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
-        desc.ArraySize = 1;
-        desc.Format = mTextureFormat;
-        desc.SampleDesc.Count = 1;
-        desc.SampleDesc.Quality = 0;
-        desc.Usage = D3D11_USAGE_DEFAULT;
-        desc.BindFlags = getBindFlags();
-        desc.CPUAccessFlags = 0;
-        desc.MiscFlags = 0;
-
-        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
-
-        // this can happen from windows TDR
-        if (d3d11::isDeviceLostError(result))
-        {
-            mRenderer->notifyDeviceLost();
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else if (FAILED(result))
-        {
-            ASSERT(result == E_OUTOFMEMORY);
-            ERR("Creating image failed.");
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else
-        {
-            mTexture->GetDesc(&desc);
-            mMipLevels = desc.MipLevels;
-            mTextureWidth = desc.Width;
-            mTextureHeight = desc.Height;
-
-            d3d11::ResourceTracker::Track(mTexture);
-        }
-    }
-}
-
-TextureStorage11_2D::~TextureStorage11_2D()
-{
-    if (mTexture)
-    {
-        mTexture->Release();
-        mTexture = NULL;
-    }
-
-    if (mSRV)
-    {
-        mSRV->Release();
-        mSRV = NULL;
-    }
-
-    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
-    {
-        delete mRenderTarget[i];
-        mRenderTarget[i] = NULL;
-    }
-}
-
-TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
-    return static_cast<TextureStorage11_2D*>(storage);
-}
-
-RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
-{
-    if (level >= 0 && level < static_cast<int>(mMipLevels))
-    {
-        if (!mRenderTarget[level])
-        {
-            ID3D11Device *device = mRenderer->getDevice();
-            HRESULT result;
-
-            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
-            srvDesc.Format = mShaderResourceFormat;
-            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-            srvDesc.Texture2D.MostDetailedMip = level;
-            srvDesc.Texture2D.MipLevels = 1;
-
-            ID3D11ShaderResourceView *srv;
-            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
-
-            if (result == E_OUTOFMEMORY)
-            {
-                return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-            }
-            ASSERT(SUCCEEDED(result));
-
-            if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
-            {
-                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-                rtvDesc.Format = mRenderTargetFormat;
-                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-                rtvDesc.Texture2D.MipSlice = level;
-
-                ID3D11RenderTargetView *rtv;
-                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
-
-                if (result == E_OUTOFMEMORY)
-                {
-                    srv->Release();
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
-
-                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
-                // also needs to keep a reference to the texture.
-                mTexture->AddRef();
-
-                mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
-                                                          std::max(mTextureWidth >> level, 1U),
-                                                          std::max(mTextureHeight >> level, 1U));
-            }
-            else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
-            {
-                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
-                dsvDesc.Format = mDepthStencilFormat;
-                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
-                dsvDesc.Texture2D.MipSlice = level;
-                dsvDesc.Flags = 0;
-
-                ID3D11DepthStencilView *dsv;
-                result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
-
-                if (result == E_OUTOFMEMORY)
-                {
-                    srv->Release();
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
-
-                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
-                // also needs to keep a reference to the texture.
-                mTexture->AddRef();
-
-                mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
-                                                          std::max(mTextureWidth >> level, 1U),
-                                                          std::max(mTextureHeight >> level, 1U));
-            }
-            else
-            {
-                UNREACHABLE();
-            }
-        }
-
-        return mRenderTarget[level];
-    }
-    else
-    {
-        return NULL;
-    }
-}
-
-ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
-{
-    if (!mSRV)
-    {
-        ID3D11Device *device = mRenderer->getDevice();
-
-        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
-        srvDesc.Format = mShaderResourceFormat;
-        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-        srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
-        srvDesc.Texture2D.MostDetailedMip = 0;
-
-        HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
-
-        if (result == E_OUTOFMEMORY)
-        {
-            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
-        }
-        ASSERT(SUCCEEDED(result));
-    }
-
-    return mSRV;
-}
-
-void TextureStorage11_2D::generateMipmap(int level)
-{
-    RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
-    RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
-
-    generateMipmapLayer(source, dest);
-}
-
-TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
-    : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
-{
-    for (unsigned int i = 0; i < 6; i++)
-    {
-        for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
-        {
-            mRenderTarget[i][j] = NULL;
-        }
-    }
-
-    DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
-    if (d3d11::IsDepthStencilFormat(convertedFormat))
-    {
-        mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
-        mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
-        mDepthStencilFormat = convertedFormat;
-        mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
-    }
-    else
-    {
-        mTextureFormat = convertedFormat;
-        mShaderResourceFormat = convertedFormat;
-        mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
-        mRenderTargetFormat = convertedFormat;
-    }
-
-    // if the size is not positive this should be treated as an incomplete texture
-    // we handle that here by skipping the d3d texture creation
-    if (size > 0)
-    {
-        // adjust size if needed for compressed textures
-        int height = size;
-        gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
-
-        ID3D11Device *device = mRenderer->getDevice();
-
-        D3D11_TEXTURE2D_DESC desc;
-        desc.Width = size;
-        desc.Height = size;
-        desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
-        desc.ArraySize = 6;
-        desc.Format = mTextureFormat;
-        desc.SampleDesc.Count = 1;
-        desc.SampleDesc.Quality = 0;
-        desc.Usage = D3D11_USAGE_DEFAULT;
-        desc.BindFlags = getBindFlags();
-        desc.CPUAccessFlags = 0;
-        desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
-
-        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == E_OUTOFMEMORY);
-            ERR("Creating image failed.");
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else
-        {
-            mTexture->GetDesc(&desc);
-            mMipLevels = desc.MipLevels;
-            mTextureWidth = desc.Width;
-            mTextureHeight = desc.Height;
-
-            d3d11::ResourceTracker::Track(mTexture);
-        }
-    }
-}
-
-TextureStorage11_Cube::~TextureStorage11_Cube()
-{
-    if (mTexture)
-    {
-        mTexture->Release();
-        mTexture = NULL;
-    }
-
-    if (mSRV)
-    {
-        mSRV->Release();
-        mSRV = NULL;
-    }
-
-    for (unsigned int i = 0; i < 6; i++)
-    {
-        for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
-        {
-            delete mRenderTarget[i][j];
-            mRenderTarget[i][j] = NULL;
-        }
-    }
-}
-
-TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
-    return static_cast<TextureStorage11_Cube*>(storage);
-}
-
-RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
-{
-    unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
-    if (level >= 0 && level < static_cast<int>(mMipLevels))
-    {
-        if (!mRenderTarget[faceIdx][level])
-        {
-            ID3D11Device *device = mRenderer->getDevice();
-            HRESULT result;
-
-            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
-            srvDesc.Format = mShaderResourceFormat;
-            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
-            srvDesc.Texture2DArray.MostDetailedMip = level;
-            srvDesc.Texture2DArray.MipLevels = 1;
-            srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
-            srvDesc.Texture2DArray.ArraySize = 1;
-
-            ID3D11ShaderResourceView *srv;
-            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
-
-            if (result == E_OUTOFMEMORY)
-            {
-                return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-            }
-            ASSERT(SUCCEEDED(result));
-
-            if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
-            {
-                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-                rtvDesc.Format = mRenderTargetFormat;
-                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
-                rtvDesc.Texture2DArray.MipSlice = level;
-                rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
-                rtvDesc.Texture2DArray.ArraySize = 1;
-
-                ID3D11RenderTargetView *rtv;
-                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
-
-                if (result == E_OUTOFMEMORY)
-                {
-                    srv->Release();
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
-
-                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
-                // also needs to keep a reference to the texture.
-                mTexture->AddRef();
-
-                mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
-                                                                   std::max(mTextureWidth >> level, 1U),
-                                                                   std::max(mTextureHeight >> level, 1U));
-            }
-            else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
-            {
-                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
-                dsvDesc.Format = mRenderTargetFormat;
-                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
-                dsvDesc.Texture2DArray.MipSlice = level;
-                dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
-                dsvDesc.Texture2DArray.ArraySize = 1;
-
-                ID3D11DepthStencilView *dsv;
-                result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
-
-                if (result == E_OUTOFMEMORY)
-                {
-                    srv->Release();
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
-
-                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
-                // also needs to keep a reference to the texture.
-                mTexture->AddRef();
-
-                mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
-                                                                   std::max(mTextureWidth >> level, 1U),
-                                                                   std::max(mTextureHeight >> level, 1U));
-            }
-            else
-            {
-                UNREACHABLE();
-            }
-        }
-
-        return mRenderTarget[faceIdx][level];
-    }
-    else
-    {
-        return NULL;
-    }
-}
-
-ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
-{
-    if (!mSRV)
-    {
-        ID3D11Device *device = mRenderer->getDevice();
-
-        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
-        srvDesc.Format = mShaderResourceFormat;
-        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
-        srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
-        srvDesc.TextureCube.MostDetailedMip = 0;
-
-        HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
-
-        if (result == E_OUTOFMEMORY)
-        {
-            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
-        }
-        ASSERT(SUCCEEDED(result));
-    }
-
-    return mSRV;
-}
-
-void TextureStorage11_Cube::generateMipmap(int face, int level)
-{
-    RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
-    RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
-
-    generateMipmapLayer(source, dest);
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage11.h b/src/third_party/angle/src/libGLESv2/renderer/TextureStorage11.h
deleted file mode 100644
index 3c5ded0..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage11.h
+++ /dev/null
@@ -1,120 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived
-// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
-
-#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
-#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
-
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/renderer/TextureStorage.h"
-
-namespace rx
-{
-class RenderTarget;
-class RenderTarget11;
-class Renderer;
-class Renderer11;
-class SwapChain11;
-
-class TextureStorage11 : public TextureStorage
-{
-  public:
-    TextureStorage11(Renderer *renderer, UINT bindFlags);
-    virtual ~TextureStorage11();
-
-    static TextureStorage11 *makeTextureStorage11(TextureStorage *storage);
-
-    static DWORD GetTextureBindFlags(DXGI_FORMAT d3dfmt, GLenum glusage, bool forceRenderable);
-    static bool IsTextureFormatRenderable(DXGI_FORMAT format);
-
-    UINT getBindFlags() const;
-
-    virtual ID3D11Texture2D *getBaseTexture() const;
-    virtual ID3D11ShaderResourceView *getSRV() = 0;
-    virtual RenderTarget *getRenderTarget() { return getRenderTarget(0); }
-    virtual RenderTarget *getRenderTarget(int level) { return NULL; }
-    virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return getRenderTarget(faceTarget, 0); }
-    virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level) { return NULL; }
-
-    virtual void generateMipmap(int level) {};
-    virtual void generateMipmap(int face, int level) {};
-
-    virtual int getLodOffset() const;
-    virtual bool isRenderTarget() const;
-    virtual bool isManaged() const;
-    virtual int levelCount();
-    UINT getSubresourceIndex(int level, int faceTarget);
-
-    bool updateSubresourceLevel(ID3D11Texture2D *texture, unsigned int sourceSubresource, int level,
-                                int faceTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
-  protected:
-    void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest);
-
-    Renderer11 *mRenderer;
-    int mLodOffset;
-    unsigned int mMipLevels;
-
-    ID3D11Texture2D *mTexture;
-    DXGI_FORMAT mTextureFormat;
-    DXGI_FORMAT mShaderResourceFormat;
-    DXGI_FORMAT mRenderTargetFormat;
-    DXGI_FORMAT mDepthStencilFormat;
-    unsigned int mTextureWidth;
-    unsigned int mTextureHeight;
-
-    ID3D11ShaderResourceView *mSRV;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorage11);
-
-    const UINT mBindFlags;
-};
-
-class TextureStorage11_2D : public TextureStorage11
-{
-  public:
-    TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain);
-    TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
-    virtual ~TextureStorage11_2D();
-
-    static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage);
-
-    virtual ID3D11ShaderResourceView *getSRV();
-    virtual RenderTarget *getRenderTarget(int level);
-
-    virtual void generateMipmap(int level);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D);
-
-    RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-};
-
-class TextureStorage11_Cube : public TextureStorage11
-{
-  public:
-    TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
-    virtual ~TextureStorage11_Cube();
-
-    static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage);
-
-    virtual ID3D11ShaderResourceView *getSRV();
-    virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level);
-
-    virtual void generateMipmap(int face, int level);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube);
-
-    RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage9.cpp b/src/third_party/angle/src/libGLESv2/renderer/TextureStorage9.cpp
deleted file mode 100644
index 8aa74a7..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage9.cpp
+++ /dev/null
@@ -1,328 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived
-// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
-// D3D9 texture.
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/Renderer9.h"
-#include "libGLESv2/renderer/TextureStorage9.h"
-#include "libGLESv2/renderer/SwapChain9.h"
-#include "libGLESv2/renderer/RenderTarget9.h"
-#include "libGLESv2/renderer/renderer9_utils.h"
-#include "libGLESv2/Texture.h"
-
-namespace rx
-{
-TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage)
-    : mLodOffset(0),
-      mRenderer(Renderer9::makeRenderer9(renderer)),
-      mD3DUsage(usage),
-      mD3DPool(mRenderer->getTexturePool(usage))
-{
-}
-
-TextureStorage9::~TextureStorage9()
-{
-}
-
-TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage));
-    return static_cast<TextureStorage9*>(storage);
-}
-
-DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable)
-{
-    DWORD d3dusage = 0;
-
-    if (d3dfmt == D3DFMT_INTZ)
-    {
-        d3dusage |= D3DUSAGE_DEPTHSTENCIL;
-    }
-    else if(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
-    {
-        d3dusage |= D3DUSAGE_RENDERTARGET;
-    }
-    return d3dusage;
-}
-
-bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format)
-{
-    if (format == D3DFMT_INTZ)
-    {
-        return true;
-    }
-    switch(format)
-    {
-      case D3DFMT_L8:
-      case D3DFMT_A8L8:
-      case D3DFMT_DXT1:
-      case D3DFMT_DXT3:
-      case D3DFMT_DXT5:
-        return false;
-      case D3DFMT_A8R8G8B8:
-      case D3DFMT_X8R8G8B8:
-      case D3DFMT_A16B16G16R16F:
-      case D3DFMT_A32B32G32R32F:
-        return true;
-      default:
-        UNREACHABLE();
-    }
-
-    return false;
-}
-
-bool TextureStorage9::isRenderTarget() const
-{
-    return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
-}
-
-bool TextureStorage9::isManaged() const
-{
-    return (mD3DPool == D3DPOOL_MANAGED);
-}
-
-D3DPOOL TextureStorage9::getPool() const
-{
-    return mD3DPool;
-}
-
-DWORD TextureStorage9::getUsage() const
-{
-    return mD3DUsage;
-}
-
-int TextureStorage9::getLodOffset() const
-{
-    return mLodOffset;
-}
-
-int TextureStorage9::levelCount()
-{
-    return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0;
-}
-
-TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
-{
-    IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
-    mTexture = surfaceTexture;
-    mRenderTarget = NULL;
-
-    initializeRenderTarget();
-}
-
-TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
-    : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable))
-{
-    mTexture = NULL;
-    mRenderTarget = NULL;
-    // if the width or height is not positive this should be treated as an incomplete texture
-    // we handle that here by skipping the d3d texture creation
-    if (width > 0 && height > 0)
-    {
-        IDirect3DDevice9 *device = mRenderer->getDevice();
-        gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
-        HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(),
-                                               mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    initializeRenderTarget();
-}
-
-TextureStorage9_2D::~TextureStorage9_2D()
-{
-    if (mTexture)
-    {
-        mTexture->Release();
-    }
-
-    delete mRenderTarget;
-}
-
-TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage));
-    return static_cast<TextureStorage9_2D*>(storage);
-}
-
-// Increments refcount on surface.
-// caller must Release() the returned surface
-IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty)
-{
-    IDirect3DSurface9 *surface = NULL;
-
-    if (mTexture)
-    {
-        HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface);
-        ASSERT(SUCCEEDED(result));
-
-        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
-        if (level + mLodOffset != 0 && isManaged() && dirty)
-        {
-            mTexture->AddDirtyRect(NULL);
-        }
-    }
-
-    return surface;
-}
-
-RenderTarget *TextureStorage9_2D::getRenderTarget()
-{
-    return mRenderTarget;
-}
-
-void TextureStorage9_2D::generateMipmap(int level)
-{
-    IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false);
-    IDirect3DSurface9 *lower = getSurfaceLevel(level, true);
-
-    if (upper != NULL && lower != NULL)
-    {
-        mRenderer->boxFilter(upper, lower);
-    }
-
-    if (upper != NULL) upper->Release();
-    if (lower != NULL) lower->Release();
-}
-
-IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const
-{
-    return mTexture;
-}
-
-void TextureStorage9_2D::initializeRenderTarget()
-{
-    ASSERT(mRenderTarget == NULL);
-
-    if (mTexture != NULL && isRenderTarget())
-    {
-        IDirect3DSurface9 *surface = getSurfaceLevel(0, false);
-
-        mRenderTarget = new RenderTarget9(mRenderer, surface);
-    }
-}
-
-TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
-    : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable))
-{
-    mTexture = NULL;
-    for (int i = 0; i < 6; ++i)
-    {
-        mRenderTarget[i] = NULL;
-    }
-
-    // if the size is not positive this should be treated as an incomplete texture
-    // we handle that here by skipping the d3d texture creation
-    if (size > 0)
-    {
-        IDirect3DDevice9 *device = mRenderer->getDevice();
-        int height = size;
-        gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
-        HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(),
-                                                   mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    initializeRenderTarget();
-}
-
-TextureStorage9_Cube::~TextureStorage9_Cube()
-{
-    if (mTexture)
-    {
-        mTexture->Release();
-    }
-
-    for (int i = 0; i < 6; ++i)
-    {
-        delete mRenderTarget[i];
-    }
-}
-
-TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage));
-    return static_cast<TextureStorage9_Cube*>(storage);
-}
-
-// Increments refcount on surface.
-// caller must Release() the returned surface
-IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty)
-{
-    IDirect3DSurface9 *surface = NULL;
-
-    if (mTexture)
-    {
-        D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
-        HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface);
-        ASSERT(SUCCEEDED(result));
-
-        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
-        if (level != 0 && isManaged() && dirty)
-        {
-            mTexture->AddDirtyRect(face, NULL);
-        }
-    }
-
-    return surface;
-}
-
-RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget)
-{
-    return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)];
-}
-
-void TextureStorage9_Cube::generateMipmap(int face, int level)
-{
-    IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false);
-    IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true);
-
-    if (upper != NULL && lower != NULL)
-    {
-        mRenderer->boxFilter(upper, lower);
-    }
-
-    if (upper != NULL) upper->Release();
-    if (lower != NULL) lower->Release();
-}
-
-IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const
-{
-    return mTexture;
-}
-
-void TextureStorage9_Cube::initializeRenderTarget()
-{
-    if (mTexture != NULL && isRenderTarget())
-    {
-        IDirect3DSurface9 *surface = NULL;
-
-        for (int i = 0; i < 6; ++i)
-        {
-            ASSERT(mRenderTarget[i] == NULL);
-
-            surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false);
-
-            mRenderTarget[i] = new RenderTarget9(mRenderer, surface);
-        }
-    }
-}
-
-}
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage9.h b/src/third_party/angle/src/libGLESv2/renderer/TextureStorage9.h
deleted file mode 100644
index 86f551a..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/TextureStorage9.h
+++ /dev/null
@@ -1,109 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived
-// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
-// D3D9 texture.
-
-#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_
-#define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_
-
-#include "libGLESv2/renderer/TextureStorage.h"
-#include "common/debug.h"
-
-namespace rx
-{
-class Renderer9;
-class SwapChain9;
-class RenderTarget;
-class RenderTarget9;
-class Blit;
-
-class TextureStorage9 : public TextureStorage
-{
-  public:
-    TextureStorage9(Renderer *renderer, DWORD usage);
-    virtual ~TextureStorage9();
-
-    static TextureStorage9 *makeTextureStorage9(TextureStorage *storage);
-
-    static DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable);
-    static bool IsTextureFormatRenderable(D3DFORMAT format);
-
-    D3DPOOL getPool() const;
-    DWORD getUsage() const;
-
-    virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
-    virtual RenderTarget *getRenderTarget() { return NULL; }
-    virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return NULL; }
-    virtual void generateMipmap(int level) {};
-    virtual void generateMipmap(int face, int level) {};
-
-    virtual int getLodOffset() const;
-    virtual bool isRenderTarget() const;
-    virtual bool isManaged() const;
-    virtual int levelCount();
-
-  protected:
-    int mLodOffset;
-    Renderer9 *mRenderer;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorage9);
-
-    const DWORD mD3DUsage;
-    const D3DPOOL mD3DPool;
-};
-
-class TextureStorage9_2D : public TextureStorage9
-{
-  public:
-    TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain);
-    TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
-    virtual ~TextureStorage9_2D();
-
-    static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage);
-
-    IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty);
-    virtual RenderTarget *getRenderTarget();
-    virtual IDirect3DBaseTexture9 *getBaseTexture() const;
-    virtual void generateMipmap(int level);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D);
-
-    void initializeRenderTarget();
-
-    IDirect3DTexture9 *mTexture;
-    RenderTarget9 *mRenderTarget;
-};
-
-class TextureStorage9_Cube : public TextureStorage9
-{
-  public:
-    TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
-    virtual ~TextureStorage9_Cube();
-
-    static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage);
-
-    IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty);
-    virtual RenderTarget *getRenderTarget(GLenum faceTarget);
-    virtual IDirect3DBaseTexture9 *getBaseTexture() const;
-    virtual void generateMipmap(int face, int level);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube);
-
-    void initializeRenderTarget();
-
-    IDirect3DCubeTexture9 *mTexture;
-    RenderTarget9 *mRenderTarget[6];
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_
-
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer.cpp b/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer.cpp
deleted file mode 100644
index a858946..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface
-// class with derivations, classes that perform graphics API agnostic vertex buffer operations.
-
-#include "libGLESv2/renderer/VertexBuffer.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Context.h"
-
-namespace rx
-{
-
-unsigned int VertexBuffer::mNextSerial = 1;
-
-VertexBuffer::VertexBuffer()
-{
-    updateSerial();
-}
-
-VertexBuffer::~VertexBuffer()
-{
-}
-
-void VertexBuffer::updateSerial()
-{
-    mSerial = mNextSerial++;
-}
-
-unsigned int VertexBuffer::getSerial() const
-{
-    return mSerial;
-}
-
-VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer)
-{
-    mDynamic = dynamic;
-    mWritePosition = 0;
-    mReservedSpace = 0;
-
-    mVertexBuffer = renderer->createVertexBuffer();
-}
-
-VertexBufferInterface::~VertexBufferInterface()
-{
-    delete mVertexBuffer;
-}
-
-unsigned int VertexBufferInterface::getSerial() const
-{
-    return mVertexBuffer->getSerial();
-}
-
-unsigned int VertexBufferInterface::getBufferSize() const
-{
-    return mVertexBuffer->getBufferSize();
-}
-
-bool VertexBufferInterface::setBufferSize(unsigned int size)
-{
-    if (mVertexBuffer->getBufferSize() == 0)
-    {
-        return mVertexBuffer->initialize(size, mDynamic);
-    }
-    else
-    {
-        return mVertexBuffer->setBufferSize(size);
-    }
-}
-
-unsigned int VertexBufferInterface::getWritePosition() const
-{
-    return mWritePosition;
-}
-
-void VertexBufferInterface::setWritePosition(unsigned int writePosition)
-{
-    mWritePosition = writePosition;
-}
-
-bool VertexBufferInterface::discard()
-{
-    return mVertexBuffer->discard();
-}
-
-int VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances)
-{
-    if (!reserveSpace(mReservedSpace))
-    {
-        return -1;
-    }
-    mReservedSpace = 0;
-
-    if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition))
-    {
-        return -1;
-    }
-
-    int oldWritePos = static_cast<int>(mWritePosition);
-    mWritePosition += mVertexBuffer->getSpaceRequired(attrib, count, instances);
-
-    return oldWritePos;
-}
-
-int VertexBufferInterface::storeRawData(const void* data, unsigned int size)
-{
-    if (!reserveSpace(mReservedSpace))
-    {
-        return -1;
-    }
-    mReservedSpace = 0;
-
-    if (!mVertexBuffer->storeRawData(data, size, mWritePosition))
-    {
-        return -1;
-    }
-
-    int oldWritePos = static_cast<int>(mWritePosition);
-    mWritePosition += size;
-
-    return oldWritePos;
-}
-
-bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances)
-{
-    unsigned int requiredSpace = mVertexBuffer->getSpaceRequired(attribute, count, instances);
-
-    // Protect against integer overflow
-    if (mReservedSpace + requiredSpace < mReservedSpace)
-    {
-         return false;
-    }
-
-    mReservedSpace += requiredSpace;
-    return true;
-}
-
-bool VertexBufferInterface::reserveRawDataSpace(unsigned int size)
-{
-    // Protect against integer overflow
-    if (mReservedSpace + size < mReservedSpace)
-    {
-         return false;
-    }
-
-    mReservedSpace += size;
-    return true;
-}
-
-VertexBuffer* VertexBufferInterface::getVertexBuffer() const
-{
-    return mVertexBuffer;
-}
-
-
-StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true)
-{
-    setBufferSize(initialSize);
-}
-
-StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
-{
-}
-
-bool StreamingVertexBufferInterface::reserveSpace(unsigned int size)
-{
-    bool result = true;
-    unsigned int curBufferSize = getBufferSize();
-    if (size > curBufferSize)
-    {
-        result = setBufferSize(std::max(size, 3 * curBufferSize / 2));
-        setWritePosition(0);
-    }
-    else if (getWritePosition() + size > curBufferSize)
-    {
-        if (!discard())
-        {
-            return false;
-        }
-        setWritePosition(0);
-    }
-
-    return result;
-}
-
-StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false)
-{
-}
-
-StaticVertexBufferInterface::~StaticVertexBufferInterface()
-{
-}
-
-int StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute)
-{
-    for (unsigned int element = 0; element < mCache.size(); element++)
-    {
-        if (mCache[element].type == attribute.mType &&
-            mCache[element].size == attribute.mSize &&
-            mCache[element].stride == attribute.stride() &&
-            mCache[element].normalized == attribute.mNormalized)
-        {
-            if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
-            {
-                return mCache[element].streamOffset;
-            }
-        }
-    }
-
-    return -1;
-}
-
-bool StaticVertexBufferInterface::reserveSpace(unsigned int size)
-{
-    unsigned int curSize = getBufferSize();
-    if (curSize == 0)
-    {
-        setBufferSize(size);
-        return true;
-    }
-    else if (curSize >= size)
-    {
-        return true;
-    }
-    else
-    {
-        UNREACHABLE();   // Static vertex buffers can't be resized
-        return false;
-    }
-}
-
-int StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances)
-{
-    int attributeOffset = attrib.mOffset % attrib.stride();
-    VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, getWritePosition() };
-    mCache.push_back(element);
-
-    return VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances);
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer.h b/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer.h
deleted file mode 100644
index c474b05..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer.h
+++ /dev/null
@@ -1,138 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexBuffer.h: Defines the abstract VertexBuffer class and VertexBufferInterface
-// class with derivations, classes that perform graphics API agnostic vertex buffer operations.
-
-#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER_H_
-#define LIBGLESV2_RENDERER_VERTEXBUFFER_H_
-
-#include "common/angleutils.h"
-
-namespace gl
-{
-class VertexAttribute;
-}
-
-namespace rx
-{
-class Renderer;
-
-class VertexBuffer
-{
-  public:
-    VertexBuffer();
-    virtual ~VertexBuffer();
-
-    virtual bool initialize(unsigned int size, bool dynamicUsage) = 0;
-
-    virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
-                                       GLsizei instances, unsigned int offset) = 0;
-    virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset) = 0;
-
-    virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
-                                          GLsizei instances) const = 0;
-
-    virtual bool requiresConversion(const gl::VertexAttribute &attrib) const = 0;
-
-    virtual unsigned int getBufferSize() const = 0;
-    virtual bool setBufferSize(unsigned int size) = 0;
-    virtual bool discard() = 0;
-
-    unsigned int getSerial() const;
-
-  protected:
-    void updateSerial();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(VertexBuffer);
-
-    unsigned int mSerial;
-    static unsigned int mNextSerial;
-};
-
-class VertexBufferInterface
-{
-  public:
-    VertexBufferInterface(rx::Renderer *renderer, bool dynamic);
-    virtual ~VertexBufferInterface();
-
-    bool reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances);
-    bool reserveRawDataSpace(unsigned int size);
-
-    unsigned int getBufferSize() const;
-
-    unsigned int getSerial() const;
-
-    virtual int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances);
-    virtual int storeRawData(const void* data, unsigned int size);
-
-    VertexBuffer* getVertexBuffer() const;
-
-  protected:
-    virtual bool reserveSpace(unsigned int size) = 0;
-
-    unsigned int getWritePosition() const;
-    void setWritePosition(unsigned int writePosition);
-
-    bool discard();
-
-    bool setBufferSize(unsigned int size);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface);
-
-    rx::Renderer *const mRenderer;
-
-    VertexBuffer* mVertexBuffer;
-
-    unsigned int mWritePosition;
-    unsigned int mReservedSpace;
-    bool mDynamic;
-};
-
-class StreamingVertexBufferInterface : public VertexBufferInterface
-{
-  public:
-    StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize);
-    ~StreamingVertexBufferInterface();
-
-  protected:
-    bool reserveSpace(unsigned int size);
-};
-
-class StaticVertexBufferInterface : public VertexBufferInterface
-{
-  public:
-    explicit StaticVertexBufferInterface(rx::Renderer *renderer);
-    ~StaticVertexBufferInterface();
-
-    int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances);
-
-    // Returns the offset into the vertex buffer, or -1 if not found
-    int lookupAttribute(const gl::VertexAttribute &attribute);
-
-  protected:
-    bool reserveSpace(unsigned int size);
-
-  private:
-    struct VertexElement
-    {
-        GLenum type;
-        GLint size;
-        GLsizei stride;
-        bool normalized;
-        int attributeOffset;
-
-        unsigned int streamOffset;
-    };
-
-    std::vector<VertexElement> mCache;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_VERTEXBUFFER_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer11.cpp b/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer11.cpp
deleted file mode 100644
index 461dbd9..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer11.cpp
+++ /dev/null
@@ -1,420 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.
-
-#include "libGLESv2/renderer/VertexBuffer11.h"
-#include "libGLESv2/renderer/BufferStorage.h"
-
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/renderer/Renderer11.h"
-#include "libGLESv2/renderer/renderer11_utils.h"
-#include "libGLESv2/Context.h"
-
-namespace rx
-{
-
-VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer)
-{
-    mBuffer = NULL;
-    mBufferSize = 0;
-    mDynamicUsage = false;
-}
-
-VertexBuffer11::~VertexBuffer11()
-{
-    if (mBuffer)
-    {
-        mBuffer->Release();
-        mBuffer = NULL;
-    }
-}
-
-bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
-{
-    if (mBuffer)
-    {
-        mBuffer->Release();
-        mBuffer = NULL;
-    }
-
-    updateSerial();
-
-    if (size > 0)
-    {
-        ID3D11Device* dxDevice = mRenderer->getDevice();
-
-        D3D11_BUFFER_DESC bufferDesc;
-        bufferDesc.ByteWidth = size;
-        bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
-        bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
-        bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-        bufferDesc.MiscFlags = 0;
-        bufferDesc.StructureByteStride = 0;
-
-        HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
-        if (FAILED(result))
-        {
-            return false;
-        }
-        d3d11::ResourceTracker::Track(mBuffer);
-    }
-
-    mBufferSize = size;
-    mDynamicUsage = dynamicUsage;
-    return true;
-}
-
-VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer));
-    return static_cast<VertexBuffer11*>(vetexBuffer);
-}
-
-bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
-                                           GLsizei instances, unsigned int offset)
-{
-    if (mBuffer)
-    {
-        gl::Buffer *buffer = attrib.mBoundBuffer.get();
-
-        int inputStride = attrib.stride();
-        const VertexConverter &converter = getVertexConversion(attrib);
-
-        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
-        D3D11_MAPPED_SUBRESOURCE mappedResource;
-        HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
-        if (FAILED(result))
-        {
-            ERR("Vertex buffer map failed with error 0x%08x", result);
-            return false;
-        }
-
-        char* output = reinterpret_cast<char*>(mappedResource.pData) + offset;
-
-        const char *input = NULL;
-        if (buffer)
-        {
-            BufferStorage *storage = buffer->getStorage();
-            input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
-        }
-        else
-        {
-            input = static_cast<const char*>(attrib.mPointer);
-        }
-
-        if (instances == 0 || attrib.mDivisor == 0)
-        {
-            input += inputStride * start;
-        }
-
-        converter.conversionFunc(input, inputStride, count, output);
-
-        dxContext->Unmap(mBuffer, 0);
-
-        return true;
-    }
-    else
-    {
-        ERR("Vertex buffer not initialized.");
-        return false;
-    }
-}
-
-bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned int offset)
-{
-    if (mBuffer)
-    {
-        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
-        D3D11_MAPPED_SUBRESOURCE mappedResource;
-        HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
-        if (FAILED(result))
-        {
-            ERR("Vertex buffer map failed with error 0x%08x", result);
-            return false;
-        }
-
-        char* bufferData = static_cast<char*>(mappedResource.pData);
-        memcpy(bufferData + offset, data, size);
-
-        dxContext->Unmap(mBuffer, 0);
-
-        return true;
-    }
-    else
-    {
-        ERR("Vertex buffer not initialized.");
-        return false;
-    }
-}
-
-unsigned int VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
-                                              GLsizei instances) const
-{
-    unsigned int elementSize = getVertexConversion(attrib).outputElementSize;
-
-    if (instances == 0 || attrib.mDivisor == 0)
-    {
-        return elementSize * count;
-    }
-    else
-    {
-        return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor);
-    }
-}
-
-bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const
-{
-    return !getVertexConversion(attrib).identity;
-}
-
-unsigned int VertexBuffer11::getBufferSize() const
-{
-    return mBufferSize;
-}
-
-bool VertexBuffer11::setBufferSize(unsigned int size)
-{
-    if (size > mBufferSize)
-    {
-        return initialize(size, mDynamicUsage);
-    }
-    else
-    {
-        return true;
-    }
-}
-
-bool VertexBuffer11::discard()
-{
-    if (mBuffer)
-    {
-        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
-        D3D11_MAPPED_SUBRESOURCE mappedResource;
-        HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-        if (FAILED(result))
-        {
-            ERR("Vertex buffer map failed with error 0x%08x", result);
-            return false;
-        }
-
-        dxContext->Unmap(mBuffer, 0);
-
-        return true;
-    }
-    else
-    {
-        ERR("Vertex buffer not initialized.");
-        return false;
-    }
-}
-
-unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const
-{
-    return getVertexConversion(attrib).outputElementSize;
-}
-
-DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const
-{
-    return getVertexConversion(attrib).dxgiFormat;
-}
-
-ID3D11Buffer *VertexBuffer11::getBuffer() const
-{
-    return mBuffer;
-}
-
-template <typename T, unsigned int componentCount, bool widen, bool normalized>
-static void copyVertexData(const void *input, unsigned int stride, unsigned int count, void *output)
-{
-    unsigned int attribSize = sizeof(T) * componentCount;
-
-    if (attribSize == stride && !widen)
-    {
-        memcpy(output, input, count * attribSize);
-    }
-    else
-    {
-        unsigned int outputStride = widen ? 4 : componentCount;
-        T defaultVal = normalized ? std::numeric_limits<T>::max() : T(1);
-
-        for (unsigned int i = 0; i < count; i++)
-        {
-            const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + i * stride);
-            T *offsetOutput = reinterpret_cast<T*>(output) + i * outputStride;
-
-            for (unsigned int j = 0; j < componentCount; j++)
-            {
-                offsetOutput[j] = offsetInput[j];
-            }
-
-            if (widen)
-            {
-                offsetOutput[3] = defaultVal;
-            }
-        }
-    }
-}
-
-template <unsigned int componentCount>
-static void copyFixedVertexData(const void* input, unsigned int stride, unsigned int count, void* output)
-{
-    static const float divisor = 1.0f / (1 << 16);
-
-    for (unsigned int i = 0; i < count; i++)
-    {
-        const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(reinterpret_cast<const char*>(input) + stride * i);
-        float* offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
-
-        for (unsigned int j = 0; j < componentCount; j++)
-        {
-            offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor;
-        }
-    }
-}
-
-template <typename T, unsigned int componentCount, bool normalized>
-static void copyToFloatVertexData(const void* input, unsigned int stride, unsigned int count, void* output)
-{
-    typedef std::numeric_limits<T> NL;
-
-    for (unsigned int i = 0; i < count; i++)
-    {
-        const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + stride * i);
-        float *offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
-
-        for (unsigned int j = 0; j < componentCount; j++)
-        {
-            if (normalized)
-            {
-                if (NL::is_signed)
-                {
-                    const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1);
-                    offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor;
-                }
-                else
-                {
-                    offsetOutput[j] =  static_cast<float>(offsetInput[j]) / NL::max();
-                }
-            }
-            else
-            {
-                offsetOutput[j] =  static_cast<float>(offsetInput[j]);
-            }
-        }
-    }
-}
-
-const VertexBuffer11::VertexConverter VertexBuffer11::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] =
-{
-    { // GL_BYTE
-        { // unnormalized
-            { &copyToFloatVertexData<GLbyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
-            { &copyToFloatVertexData<GLbyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
-            { &copyToFloatVertexData<GLbyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
-            { &copyToFloatVertexData<GLbyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
-        },
-        { // normalized
-            { &copyVertexData<GLbyte, 1, false, true>, true, DXGI_FORMAT_R8_SNORM, 1 },
-            { &copyVertexData<GLbyte, 2, false, true>, true, DXGI_FORMAT_R8G8_SNORM, 2 },
-            { &copyVertexData<GLbyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
-            { &copyVertexData<GLbyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
-        },
-    },
-    { // GL_UNSIGNED_BYTE
-        { // unnormalized
-            { &copyToFloatVertexData<GLubyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
-            { &copyToFloatVertexData<GLubyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
-            { &copyToFloatVertexData<GLubyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
-            { &copyToFloatVertexData<GLubyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
-        },
-        { // normalized
-            { &copyVertexData<GLubyte, 1, false, true>, true, DXGI_FORMAT_R8_UNORM, 1 },
-            { &copyVertexData<GLubyte, 2, false, true>, true, DXGI_FORMAT_R8G8_UNORM, 2 },
-            { &copyVertexData<GLubyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
-            { &copyVertexData<GLubyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
-        },
-    },
-    { // GL_SHORT
-        { // unnormalized
-            { &copyToFloatVertexData<GLshort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
-            { &copyToFloatVertexData<GLshort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
-            { &copyToFloatVertexData<GLshort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
-            { &copyToFloatVertexData<GLshort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
-        },
-        { // normalized
-            { &copyVertexData<GLshort, 1, false, true>, true, DXGI_FORMAT_R16_SNORM, 2 },
-            { &copyVertexData<GLshort, 2, false, true>, true, DXGI_FORMAT_R16G16_SNORM, 4 },
-            { &copyVertexData<GLshort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
-            { &copyVertexData<GLshort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
-        },
-    },
-    { // GL_UNSIGNED_SHORT
-        { // unnormalized
-            { &copyToFloatVertexData<GLushort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
-            { &copyToFloatVertexData<GLushort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
-            { &copyToFloatVertexData<GLushort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
-            { &copyToFloatVertexData<GLushort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
-        },
-        { // normalized
-            { &copyVertexData<GLushort, 1, false, true>, true, DXGI_FORMAT_R16_UNORM, 2 },
-            { &copyVertexData<GLushort, 2, false, true>, true, DXGI_FORMAT_R16G16_UNORM, 4 },
-            { &copyVertexData<GLushort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
-            { &copyVertexData<GLushort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
-        },
-    },
-    { // GL_FIXED
-        { // unnormalized
-            { &copyFixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
-            { &copyFixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
-            { &copyFixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
-            { &copyFixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
-        },
-        { // normalized
-            { &copyFixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
-            { &copyFixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
-            { &copyFixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
-            { &copyFixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
-        },
-    },
-    { // GL_FLOAT
-        { // unnormalized
-            { &copyVertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
-            { &copyVertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
-            { &copyVertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
-            { &copyVertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
-        },
-        { // normalized
-            { &copyVertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
-            { &copyVertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
-            { &copyVertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
-            { &copyVertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
-        },
-    },
-};
-
-const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute)
-{
-    unsigned int typeIndex = 0;
-    switch (attribute.mType)
-    {
-      case GL_BYTE:             typeIndex = 0; break;
-      case GL_UNSIGNED_BYTE:    typeIndex = 1; break;
-      case GL_SHORT:            typeIndex = 2; break;
-      case GL_UNSIGNED_SHORT:   typeIndex = 3; break;
-      case GL_FIXED:            typeIndex = 4; break;
-      case GL_FLOAT:            typeIndex = 5; break;
-      default:                  UNREACHABLE(); break;
-    }
-
-    return mPossibleTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1];
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer11.h b/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer11.h
deleted file mode 100644
index 75e0250..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer11.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation.
-
-#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
-#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
-
-#include "libGLESv2/renderer/VertexBuffer.h"
-
-namespace rx
-{
-class Renderer11;
-
-class VertexBuffer11 : public VertexBuffer
-{
-  public:
-    explicit VertexBuffer11(rx::Renderer11 *const renderer);
-    virtual ~VertexBuffer11();
-
-    virtual bool initialize(unsigned int size, bool dynamicUsage);
-
-    static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer);
-
-    virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
-                                 unsigned int offset);
-    virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset);
-
-    virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const;
-
-    virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
-
-    virtual unsigned int getBufferSize() const;
-    virtual bool setBufferSize(unsigned int size);
-    virtual bool discard();
-
-    unsigned int getVertexSize(const gl::VertexAttribute &attrib) const;
-    DXGI_FORMAT getDXGIFormat(const gl::VertexAttribute &attrib) const;
-
-    ID3D11Buffer *getBuffer() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(VertexBuffer11);
-
-    rx::Renderer11 *const mRenderer;
-
-    ID3D11Buffer *mBuffer;
-    unsigned int mBufferSize;
-    bool mDynamicUsage;
-
-    typedef void (*VertexConversionFunction)(const void *, unsigned int, unsigned int, void *);
-    struct VertexConverter
-    {
-        VertexConversionFunction conversionFunc;
-        bool identity;
-        DXGI_FORMAT dxgiFormat;
-        unsigned int outputElementSize;
-    };
-
-    enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
-
-    // This table is used to generate mAttributeTypes.
-    static const VertexConverter mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1]
-
-    static const VertexConverter &getVertexConversion(const gl::VertexAttribute &attribute);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
\ No newline at end of file
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer9.cpp b/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer9.cpp
deleted file mode 100644
index 76dc73e..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer9.cpp
+++ /dev/null
@@ -1,486 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
-
-#include "libGLESv2/renderer/VertexBuffer9.h"
-#include "libGLESv2/renderer/vertexconversion.h"
-#include "libGLESv2/renderer/BufferStorage.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/Renderer9.h"
-
-#include "libGLESv2/Buffer.h"
-
-namespace rx
-{
-
-bool VertexBuffer9::mTranslationsInitialized = false;
-VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
-
-VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer)
-{
-    mVertexBuffer = NULL;
-    mBufferSize = 0;
-    mDynamicUsage = false;
-
-    if (!mTranslationsInitialized)
-    {
-        initializeTranslations(renderer->getCapsDeclTypes());
-        mTranslationsInitialized = true;
-    }
-}
-
-VertexBuffer9::~VertexBuffer9()
-{
-    if (mVertexBuffer)
-    {
-        mVertexBuffer->Release();
-        mVertexBuffer = NULL;
-    }
-}
-
-bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
-{
-    if (mVertexBuffer)
-    {
-        mVertexBuffer->Release();
-        mVertexBuffer = NULL;
-    }
-
-    updateSerial();
-
-    if (size > 0)
-    {
-        DWORD flags = D3DUSAGE_WRITEONLY;
-        if (dynamicUsage)
-        {
-            flags |= D3DUSAGE_DYNAMIC;
-        }
-
-        HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
-
-        if (FAILED(result))
-        {
-            ERR("Out of memory allocating a vertex buffer of size %lu.", size);
-            return false;
-        }
-    }
-
-    mBufferSize = size;
-    mDynamicUsage = dynamicUsage;
-    return true;
-}
-
-VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
-{
-    ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
-    return static_cast<VertexBuffer9*>(vertexBuffer);
-}
-
-bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
-                                             GLsizei instances, unsigned int offset)
-{
-    if (mVertexBuffer)
-    {
-        gl::Buffer *buffer = attrib.mBoundBuffer.get();
-
-        int inputStride = attrib.stride();
-        int elementSize = attrib.typeSize();
-        const FormatConverter &converter = formatConverter(attrib);
-
-        DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
-
-        void *mapPtr = NULL;
-        HRESULT result = mVertexBuffer->Lock(offset, spaceRequired(attrib, count, instances), &mapPtr, lockFlags);
-
-        if (FAILED(result))
-        {
-            ERR("Lock failed with error 0x%08x", result);
-            return false;
-        }
-
-        const char *input = NULL;
-        if (buffer)
-        {
-            BufferStorage *storage = buffer->getStorage();
-            input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
-        }
-        else
-        {
-            input = static_cast<const char*>(attrib.mPointer);
-        }
-
-        if (instances == 0 || attrib.mDivisor == 0)
-        {
-            input += inputStride * start;
-        }
-
-        if (converter.identity && inputStride == elementSize)
-        {
-            memcpy(mapPtr, input, count * inputStride);
-        }
-        else
-        {
-            converter.convertArray(input, inputStride, count, mapPtr);
-        }
-
-        mVertexBuffer->Unlock();
-
-        return true;
-    }
-    else
-    {
-        ERR("Vertex buffer not initialized.");
-        return false;
-    }
-}
-
-bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset)
-{
-    if (mVertexBuffer)
-    {
-        DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
-
-        void *mapPtr = NULL;
-        HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags);
-
-        if (FAILED(result))
-        {
-            ERR("Lock failed with error 0x%08x", result);
-            return false;
-        }
-
-        memcpy(mapPtr, data, size);
-
-        mVertexBuffer->Unlock();
-
-        return true;
-    }
-    else
-    {
-        ERR("Vertex buffer not initialized.");
-        return false;
-    }
-}
-
-unsigned int VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const
-{
-    return spaceRequired(attrib, count, instances);
-}
-
-bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const
-{
-    return formatConverter(attrib).identity;
-}
-
-unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const
-{
-    return spaceRequired(attrib, 1, 0);
-}
-
-D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const
-{
-    return formatConverter(attrib).d3dDeclType;
-}
-
-unsigned int VertexBuffer9::getBufferSize() const
-{
-    return mBufferSize;
-}
-
-bool VertexBuffer9::setBufferSize(unsigned int size)
-{
-    if (size > mBufferSize)
-    {
-        return initialize(size, mDynamicUsage);
-    }
-    else
-    {
-        return true;
-    }
-}
-
-bool VertexBuffer9::discard()
-{
-    if (mVertexBuffer)
-    {
-        void *dummy;
-        HRESULT result;
-
-        result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
-        if (FAILED(result))
-        {
-            ERR("Discard lock failed with error 0x%08x", result);
-            return false;
-        }
-
-        result = mVertexBuffer->Unlock();
-        if (FAILED(result))
-        {
-            ERR("Discard unlock failed with error 0x%08x", result);
-            return false;
-        }
-
-        return true;
-    }
-    else
-    {
-        ERR("Vertex buffer not initialized.");
-        return false;
-    }
-}
-
-IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
-{
-    return mVertexBuffer;
-}
-
-// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
-//
-// BYTE                 SHORT (Cast)
-// BYTE-norm            FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
-// UNSIGNED_BYTE        UBYTE4 (Identity) or SHORT (Cast)
-// UNSIGNED_BYTE-norm   UBYTE4N (Identity) or FLOAT (Normalize)
-// SHORT                SHORT (Identity)
-// SHORT-norm           SHORT-norm (Identity) or FLOAT (Normalize)
-// UNSIGNED_SHORT       FLOAT (Cast)
-// UNSIGNED_SHORT-norm  USHORT-norm (Identity) or FLOAT (Normalize)
-// FIXED (not in WebGL) FLOAT (FixedToFloat)
-// FLOAT                FLOAT (Identity)
-
-// GLToCType maps from GL type (as GLenum) to the C typedef.
-template <GLenum GLType> struct GLToCType { };
-
-template <> struct GLToCType<GL_BYTE>           { typedef GLbyte type;      };
-template <> struct GLToCType<GL_UNSIGNED_BYTE>  { typedef GLubyte type;     };
-template <> struct GLToCType<GL_SHORT>          { typedef GLshort type;     };
-template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type;    };
-template <> struct GLToCType<GL_FIXED>          { typedef GLuint type;      };
-template <> struct GLToCType<GL_FLOAT>          { typedef GLfloat type;     };
-
-// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
-enum D3DVertexType
-{
-    D3DVT_FLOAT,
-    D3DVT_SHORT,
-    D3DVT_SHORT_NORM,
-    D3DVT_UBYTE,
-    D3DVT_UBYTE_NORM,
-    D3DVT_USHORT_NORM
-};
-
-// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
-template <unsigned int D3DType> struct D3DToCType { };
-
-template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
-template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
-template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
-template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
-template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
-template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
-
-// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
-template <unsigned int type, int size> struct WidenRule { };
-
-template <int size> struct WidenRule<D3DVT_FLOAT, size>          : NoWiden<size> { };
-template <int size> struct WidenRule<D3DVT_SHORT, size>          : WidenToEven<size> { };
-template <int size> struct WidenRule<D3DVT_SHORT_NORM, size>     : WidenToEven<size> { };
-template <int size> struct WidenRule<D3DVT_UBYTE, size>          : WidenToFour<size> { };
-template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size>     : WidenToFour<size> { };
-template <int size> struct WidenRule<D3DVT_USHORT_NORM, size>    : WidenToEven<size> { };
-
-// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
-template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
-
-template <unsigned int _capflag, unsigned int _declflag>
-struct VertexTypeFlagsHelper
-{
-    enum { capflag = _capflag };
-    enum { declflag = _declflag };
-};
-
-template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
-template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
-template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
-template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
-template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
-template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
-template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
-template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
-template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
-template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
-template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
-template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
-
-
-// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
-template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
-
-template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
-struct VertexTypeMappingBase
-{
-    enum { preferred = Preferred };
-    enum { fallback = Fallback };
-};
-
-template <> struct VertexTypeMapping<GL_BYTE, false>                        : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Cast
-template <> struct VertexTypeMapping<GL_BYTE, true>                         : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Normalize
-template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false>               : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { };          // Identity, Cast
-template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true>                : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { };     // Identity, Normalize
-template <> struct VertexTypeMapping<GL_SHORT, false>                       : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Identity
-template <> struct VertexTypeMapping<GL_SHORT, true>                        : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { };     // Cast, Normalize
-template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false>              : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Cast
-template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true>               : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { };    // Cast, Normalize
-template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // FixedToFloat
-template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Identity
-
-
-// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
-// The conversion rules themselves are defined in vertexconversion.h.
-
-// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
-template <GLenum fromType, bool normalized, unsigned int toType>
-struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
-
-// All conversions from normalized types to float use the Normalize operator.
-template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
-
-// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
-template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT>  : FixedToFloat<GLint, 16> { };
-template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
-
-// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
-// whether it is normalized or not.
-template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
-
-template <class T> struct DefaultVertexValuesStage2<T, true>  : NormalizedDefaultValues<T> { };
-template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
-
-// Work out the default value rule for a D3D type (expressed as the C type) and
-template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
-template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
-
-// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
-// The fallback conversion produces an output that all D3D9 devices must support.
-template <class T> struct UsePreferred { enum { type = T::preferred }; };
-template <class T> struct UseFallback { enum { type = T::fallback }; };
-
-// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
-// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
-// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
-template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
-struct Converter
-    : VertexDataConverter<typename GLToCType<fromType>::type,
-                          WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
-                          ConversionRule<fromType,
-                                         normalized,
-                                         PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
-                          DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
-{
-private:
-    enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
-    enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
-
-public:
-    enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
-    enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
-};
-
-// Initialize a TranslationInfo
-#define TRANSLATION(type, norm, size, preferred)                                    \
-    {                                                                               \
-        Converter<type, norm, size, preferred>::identity,                           \
-        Converter<type, norm, size, preferred>::finalSize,                          \
-        Converter<type, norm, size, preferred>::convertArray,                       \
-        static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag)  \
-    }
-
-#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size)    \
-    {                                                       \
-        Converter<type, norm, size, UsePreferred>::capflag, \
-        TRANSLATION(type, norm, size, UsePreferred),        \
-        TRANSLATION(type, norm, size, UseFallback)          \
-    }
-
-#define TRANSLATIONS_FOR_TYPE(type)                                                                                                                                                                         \
-    {                                                                                                                                                                                                       \
-        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
-        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) },     \
-    }
-
-#define TRANSLATIONS_FOR_TYPE_NO_NORM(type)                                                                                                                                                                 \
-    {                                                                                                                                                                                                       \
-        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
-        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
-    }
-
-const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
-{
-    TRANSLATIONS_FOR_TYPE(GL_BYTE),
-    TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
-    TRANSLATIONS_FOR_TYPE(GL_SHORT),
-    TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
-    TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
-    TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
-};
-
-void VertexBuffer9::initializeTranslations(DWORD declTypes)
-{
-    for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
-    {
-        for (unsigned int j = 0; j < 2; j++)
-        {
-            for (unsigned int k = 0; k < 4; k++)
-            {
-                if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
-                {
-                    mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
-                }
-                else
-                {
-                    mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
-                }
-            }
-        }
-    }
-}
-
-unsigned int VertexBuffer9::typeIndex(GLenum type)
-{
-    switch (type)
-    {
-      case GL_BYTE: return 0;
-      case GL_UNSIGNED_BYTE: return 1;
-      case GL_SHORT: return 2;
-      case GL_UNSIGNED_SHORT: return 3;
-      case GL_FIXED: return 4;
-      case GL_FLOAT: return 5;
-
-      default: UNREACHABLE(); return 5;
-    }
-}
-
-const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute)
-{
-    return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
-}
-
-unsigned int VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances)
-{
-    unsigned int elementSize = formatConverter(attrib).outputElementSize;
-
-    if (instances == 0 || attrib.mDivisor == 0)
-    {
-        return elementSize * count;
-    }
-    else
-    {
-        return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor);
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer9.h b/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer9.h
deleted file mode 100644
index f771635..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexBuffer9.h
+++ /dev/null
@@ -1,90 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation.
-
-#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
-#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
-
-#include "libGLESv2/renderer/VertexBuffer.h"
-
-namespace rx
-{
-class Renderer9;
-
-class VertexBuffer9 : public VertexBuffer
-{
-  public:
-    explicit VertexBuffer9(rx::Renderer9 *const renderer);
-    virtual ~VertexBuffer9();
-
-    virtual bool initialize(unsigned int size, bool dynamicUsage);
-
-    static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer);
-
-    virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
-                                       unsigned int offset);
-    virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset);
-
-    virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const;
-
-    virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
-
-    unsigned int getVertexSize(const gl::VertexAttribute &attrib) const;
-    D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const;
-
-    virtual unsigned int getBufferSize() const;
-    virtual bool setBufferSize(unsigned int size);
-    virtual bool discard();
-
-    IDirect3DVertexBuffer9 *getBuffer() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(VertexBuffer9);
-
-    rx::Renderer9 *const mRenderer;
-
-    IDirect3DVertexBuffer9 *mVertexBuffer;
-    unsigned int mBufferSize;
-    bool mDynamicUsage;
-
-    // Attribute format conversion
-    enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
-
-    struct FormatConverter
-    {
-        bool identity;
-        std::size_t outputElementSize;
-        void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
-        D3DDECLTYPE d3dDeclType;
-    };
-
-    static bool mTranslationsInitialized;
-    static void initializeTranslations(DWORD declTypes);
-
-    // [GL types as enumerated by typeIndex()][normalized][size - 1]
-    static FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
-
-    struct TranslationDescription
-    {
-        DWORD capsFlag;
-        FormatConverter preferredConversion;
-        FormatConverter fallbackConversion;
-    };
-
-    // This table is used to generate mFormatConverters.
-    // [GL types as enumerated by typeIndex()][normalized][size - 1]
-    static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
-
-    static unsigned int typeIndex(GLenum type);
-    static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute);
-
-    static unsigned int spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/third_party/angle/src/libGLESv2/renderer/VertexDataManager.cpp
deleted file mode 100644
index fd869b1..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexDataManager.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexDataManager.h: Defines the VertexDataManager, a class that
-// runs the Buffer translation process.
-
-#include "libGLESv2/renderer/VertexDataManager.h"
-#include "libGLESv2/renderer/BufferStorage.h"
-
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/VertexBuffer.h"
-
-namespace
-{
-    enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
-    // This has to be at least 4k or else it fails on ATI cards.
-    enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 };
-}
-
-namespace rx
-{
-
-static int elementsInBuffer(const gl::VertexAttribute &attribute, int size)
-{
-    int stride = attribute.stride();
-    return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
-}
-
-VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
-{
-    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        mCurrentValue[i][0] = std::numeric_limits<float>::quiet_NaN();
-        mCurrentValue[i][1] = std::numeric_limits<float>::quiet_NaN();
-        mCurrentValue[i][2] = std::numeric_limits<float>::quiet_NaN();
-        mCurrentValue[i][3] = std::numeric_limits<float>::quiet_NaN();
-        mCurrentValueBuffer[i] = NULL;
-        mCurrentValueOffsets[i] = 0;
-    }
-
-    mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE);
-
-    if (!mStreamingBuffer)
-    {
-        ERR("Failed to allocate the streaming vertex buffer.");
-    }
-}
-
-VertexDataManager::~VertexDataManager()
-{
-    delete mStreamingBuffer;
-
-    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        delete mCurrentValueBuffer[i];
-    }
-}
-
-static bool directStoragePossible(VertexBufferInterface* vb, const gl::VertexAttribute& attrib)
-{
-    gl::Buffer *buffer = attrib.mBoundBuffer.get();
-    BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
-
-    const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0);
-
-    return storage && storage->supportsDirectBinding() && !vb->getVertexBuffer()->requiresConversion(attrib) && isAligned;
-}
-
-GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
-{
-    if (!mStreamingBuffer)
-    {
-        return GL_OUT_OF_MEMORY;
-    }
-
-    for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
-    {
-        translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1);
-    }
-
-    // Invalidate static buffers that don't contain matching attributes
-    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        if (translated[i].active && attribs[i].mArrayEnabled)
-        {
-            gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
-            StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
-
-            if (staticBuffer && staticBuffer->getBufferSize() > 0 && staticBuffer->lookupAttribute(attribs[i]) == -1 &&
-                !directStoragePossible(staticBuffer, attribs[i]))
-            {
-                buffer->invalidateStaticData();
-            }
-        }
-    }
-
-    // Reserve the required space in the buffers
-    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        if (translated[i].active && attribs[i].mArrayEnabled)
-        {
-            gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
-            StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
-            VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
-
-            if (!directStoragePossible(vertexBuffer, attribs[i]))
-            {
-                if (staticBuffer)
-                {
-                    if (staticBuffer->getBufferSize() == 0)
-                    {
-                        int totalCount = elementsInBuffer(attribs[i], buffer->size());
-                        if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0))
-                        {
-                            return GL_OUT_OF_MEMORY;
-                        }
-                    }
-                }
-                else
-                {
-                    if (!mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances))
-                    {
-                        return GL_OUT_OF_MEMORY;
-                    }
-                }
-            }
-        }
-    }
-
-    // Perform the vertex data translations
-    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        if (translated[i].active)
-        {
-            if (attribs[i].mArrayEnabled)
-            {
-                gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
-
-                if (!buffer && attribs[i].mPointer == NULL)
-                {
-                    // This is an application error that would normally result in a crash, but we catch it and return an error
-                    ERR("An enabled vertex array has no buffer and no pointer.");
-                    return GL_INVALID_OPERATION;
-                }
-
-                StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
-                VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
-
-                BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
-                bool directStorage = directStoragePossible(vertexBuffer, attribs[i]);
-
-                std::size_t streamOffset = -1;
-                unsigned int outputElementSize = 0;
-
-                if (directStorage)
-                {
-                    outputElementSize = attribs[i].stride();
-                    streamOffset = attribs[i].mOffset + outputElementSize * start;
-                    storage->markBufferUsage();
-                }
-                else if (staticBuffer)
-                {
-                    streamOffset = staticBuffer->lookupAttribute(attribs[i]);
-                    outputElementSize = staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0);
-
-                    if (streamOffset == -1)
-                    {
-                        // Convert the entire buffer
-                        int totalCount = elementsInBuffer(attribs[i], storage->getSize());
-                        int startIndex = attribs[i].mOffset / attribs[i].stride();
-
-                        streamOffset = staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0);
-                    }
-
-                    if (streamOffset != -1)
-                    {
-                        streamOffset += (attribs[i].mOffset / attribs[i].stride()) * outputElementSize;
-
-                        if (instances == 0 || attribs[i].mDivisor == 0)
-                        {
-                            streamOffset += start * outputElementSize;
-                        }
-                    }
-                }
-                else
-                {
-                    outputElementSize = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0);
-                    streamOffset = mStreamingBuffer->storeVertexAttributes(attribs[i], start, count, instances);
-                }
-
-                if (streamOffset == -1)
-                {
-                    return GL_OUT_OF_MEMORY;
-                }
-
-                translated[i].storage = directStorage ? storage : NULL;
-                translated[i].vertexBuffer = vertexBuffer->getVertexBuffer();
-                translated[i].serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial();
-                translated[i].divisor = attribs[i].mDivisor;
-
-                translated[i].attribute = &attribs[i];
-                translated[i].stride = outputElementSize;
-                translated[i].offset = streamOffset;
-            }
-            else
-            {
-                if (!mCurrentValueBuffer[i])
-                {
-                    mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
-                }
-
-                StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i];
-
-                if (mCurrentValue[i][0] != attribs[i].mCurrentValue[0] ||
-                    mCurrentValue[i][1] != attribs[i].mCurrentValue[1] ||
-                    mCurrentValue[i][2] != attribs[i].mCurrentValue[2] ||
-                    mCurrentValue[i][3] != attribs[i].mCurrentValue[3])
-                {
-                    unsigned int requiredSpace = sizeof(float) * 4;
-                    if (!buffer->reserveRawDataSpace(requiredSpace))
-                    {
-                        return GL_OUT_OF_MEMORY;
-                    }
-                    int streamOffset = buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace);
-                    if (streamOffset == -1)
-                    {
-                        return GL_OUT_OF_MEMORY;
-                    }
-
-                    mCurrentValueOffsets[i] = streamOffset;
-                }
-
-                translated[i].storage = NULL;
-                translated[i].vertexBuffer = mCurrentValueBuffer[i]->getVertexBuffer();
-                translated[i].serial = mCurrentValueBuffer[i]->getSerial();
-                translated[i].divisor = 0;
-
-                translated[i].attribute = &attribs[i];
-                translated[i].stride = 0;
-                translated[i].offset = mCurrentValueOffsets[i];
-            }
-        }
-    }
-
-    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        if (translated[i].active && attribs[i].mArrayEnabled)
-        {
-            gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
-
-            if (buffer)
-            {
-                buffer->promoteStaticUsage(count * attribs[i].typeSize());
-            }
-        }
-    }
-
-    return GL_NO_ERROR;
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexDataManager.h b/src/third_party/angle/src/libGLESv2/renderer/VertexDataManager.h
deleted file mode 100644
index 28387e6..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexDataManager.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexDataManager.h: Defines the VertexDataManager, a class that
-// runs the Buffer translation process.
-
-#ifndef LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
-#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
-
-#include "libGLESv2/Constants.h"
-#include "common/angleutils.h"
-
-namespace gl
-{
-class VertexAttribute;
-class ProgramBinary;
-}
-
-namespace rx
-{
-class BufferStorage;
-class StreamingVertexBufferInterface;
-class VertexBuffer;
-class Renderer;
-
-struct TranslatedAttribute
-{
-    bool active;
-
-    const gl::VertexAttribute *attribute;
-    UINT offset;
-    UINT stride;   // 0 means not to advance the read pointer at all
-
-    VertexBuffer *vertexBuffer;
-    BufferStorage *storage;
-    unsigned int serial;
-    unsigned int divisor;
-};
-
-class VertexDataManager
-{
-  public:
-    VertexDataManager(rx::Renderer *renderer);
-    virtual ~VertexDataManager();
-
-    GLenum prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
-
-    rx::Renderer *const mRenderer;
-
-    StreamingVertexBufferInterface *mStreamingBuffer;
-
-    float mCurrentValue[gl::MAX_VERTEX_ATTRIBS][4];
-    StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS];
-    std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS];
-};
-
-}
-
-#endif   // LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp b/src/third_party/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp
deleted file mode 100644
index 9b83a64..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.
-
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/VertexBuffer9.h"
-#include "libGLESv2/renderer/VertexDeclarationCache.h"
-
-namespace rx
-{
-
-VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
-{
-    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
-    {
-        mVertexDeclCache[i].vertexDeclaration = NULL;
-        mVertexDeclCache[i].lruCount = 0;
-    }
-
-    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        mAppliedVBs[i].serial = 0;
-    }
-
-    mLastSetVDecl = NULL;
-    mInstancingEnabled = true;
-}
-
-VertexDeclarationCache::~VertexDeclarationCache()
-{
-    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
-    {
-        if (mVertexDeclCache[i].vertexDeclaration)
-        {
-            mVertexDeclCache[i].vertexDeclaration->Release();
-        }
-    }
-}
-
-GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
-{
-    *repeatDraw = 1;
-
-    int indexedAttribute = gl::MAX_VERTEX_ATTRIBS;
-    int instancedAttribute = gl::MAX_VERTEX_ATTRIBS;
-
-    if (instances > 0)
-    {
-        // Find an indexed attribute to be mapped to D3D stream 0
-        for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-        {
-            if (attributes[i].active)
-            {
-                if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0)
-                {
-                    indexedAttribute = i;
-                }
-                else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0)
-                {
-                    instancedAttribute = i;
-                }
-                if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS)
-                    break;   // Found both an indexed and instanced attribute
-            }
-        }
-
-        if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS)
-        {
-            return GL_INVALID_OPERATION;
-        }
-    }
-
-    D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1];
-    D3DVERTEXELEMENT9 *element = &elements[0];
-
-    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        if (attributes[i].active)
-        {
-            // Directly binding the storage buffer is not supported for d3d9
-            ASSERT(attributes[i].storage == NULL);
-
-            int stream = i;
-
-            if (instances > 0)
-            {
-                // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
-                if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
-                {
-                    *repeatDraw = instances;
-                }
-                else
-                {
-                    if (i == indexedAttribute)
-                    {
-                        stream = 0;
-                    }
-                    else if (i == 0)
-                    {
-                        stream = indexedAttribute;
-                    }
-
-                    UINT frequency = 1;
-                    
-                    if (attributes[i].divisor == 0)
-                    {
-                        frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
-                    }
-                    else
-                    {
-                        frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
-                    }
-                    
-                    device->SetStreamSourceFreq(stream, frequency);
-                    mInstancingEnabled = true;
-                }
-            }
-
-            VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer);
-
-            if (mAppliedVBs[stream].serial != attributes[i].serial ||
-                mAppliedVBs[stream].stride != attributes[i].stride ||
-                mAppliedVBs[stream].offset != attributes[i].offset)
-            {
-                device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride);
-                mAppliedVBs[stream].serial = attributes[i].serial;
-                mAppliedVBs[stream].stride = attributes[i].stride;
-                mAppliedVBs[stream].offset = attributes[i].offset;
-            }
-
-            element->Stream = stream;
-            element->Offset = 0;
-            element->Type = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDeclType(*attributes[i].attribute) : D3DDECLTYPE_FLOAT4;
-            element->Method = D3DDECLMETHOD_DEFAULT;
-            element->Usage = D3DDECLUSAGE_TEXCOORD;
-            element->UsageIndex = programBinary->getSemanticIndex(i);
-            element++;
-        }
-    }
-
-    if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
-    {
-        if (mInstancingEnabled)
-        {
-            for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-            {
-                device->SetStreamSourceFreq(i, 1);
-            }
-
-            mInstancingEnabled = false;
-        }
-    }
-
-    static const D3DVERTEXELEMENT9 end = D3DDECL_END();
-    *(element++) = end;
-
-    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
-    {
-        VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
-        if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
-        {
-            entry->lruCount = ++mMaxLru;
-            if(entry->vertexDeclaration != mLastSetVDecl)
-            {
-                device->SetVertexDeclaration(entry->vertexDeclaration);
-                mLastSetVDecl = entry->vertexDeclaration;
-            }
-
-            return GL_NO_ERROR;
-        }
-    }
-
-    VertexDeclCacheEntry *lastCache = mVertexDeclCache;
-
-    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
-    {
-        if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
-        {
-            lastCache = &mVertexDeclCache[i];
-        }
-    }
-
-    if (lastCache->vertexDeclaration != NULL)
-    {
-        lastCache->vertexDeclaration->Release();
-        lastCache->vertexDeclaration = NULL;
-        // mLastSetVDecl is set to the replacement, so we don't have to worry
-        // about it.
-    }
-
-    memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
-    device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
-    device->SetVertexDeclaration(lastCache->vertexDeclaration);
-    mLastSetVDecl = lastCache->vertexDeclaration;
-    lastCache->lruCount = ++mMaxLru;
-
-    return GL_NO_ERROR;
-}
-
-void VertexDeclarationCache::markStateDirty()
-{
-    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
-    {
-        mAppliedVBs[i].serial = 0;
-    }
-
-    mLastSetVDecl = NULL;
-    mInstancingEnabled = true;   // Forces it to be disabled when not used
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/VertexDeclarationCache.h b/src/third_party/angle/src/libGLESv2/renderer/VertexDeclarationCache.h
deleted file mode 100644
index 3fc024a..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/VertexDeclarationCache.h
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations.
-
-#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
-#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
-
-#include "libGLESv2/renderer/VertexDataManager.h"
-
-namespace gl
-{
-class VertexDataManager;
-}
-
-namespace rx
-{
-
-class VertexDeclarationCache
-{
-  public:
-    VertexDeclarationCache();
-    ~VertexDeclarationCache();
-
-    GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw);
-
-    void markStateDirty();
-
-  private:
-    UINT mMaxLru;
-
-    enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 };
-
-    struct VBData
-    {
-        unsigned int serial;
-        unsigned int stride;
-        unsigned int offset;
-    };
-
-    VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS];
-    IDirect3DVertexDeclaration9 *mLastSetVDecl;
-    bool mInstancingEnabled;
-
-    struct VertexDeclCacheEntry
-    {
-        D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1];
-        UINT lruCount;
-        IDirect3DVertexDeclaration9 *vertexDeclaration;
-    } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/generatemip.h b/src/third_party/angle/src/libGLESv2/renderer/generatemip.h
deleted file mode 100644
index 8e19736..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/generatemip.h
+++ /dev/null
@@ -1,203 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// generatemip.h: Defines the GenerateMip function, templated on the format
-// type of the image for which mip levels are being generated.
-
-#ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_
-#define LIBGLESV2_RENDERER_GENERATEMIP_H_
-
-#include "libGLESv2/mathutil.h"
-
-namespace rx
-{
-struct L8
-{
-    unsigned char L;
-
-    static void average(L8 *dst, const L8 *src1, const L8 *src2)
-    {
-        dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L);
-    }
-};
-
-typedef L8 R8; // R8 type is functionally equivalent for mip purposes
-typedef L8 A8; // A8 type is functionally equivalent for mip purposes
-
-struct A8L8
-{
-    unsigned char L;
-    unsigned char A;
-
-    static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2)
-    {
-        *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
-    }
-};
-
-typedef A8L8 R8G8; // R8G8 type is functionally equivalent for mip purposes
-
-struct A8R8G8B8
-{
-    unsigned char B;
-    unsigned char G;
-    unsigned char R;
-    unsigned char A;
-
-    static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2)
-    {
-        *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
-    }
-};
-
-typedef A8R8G8B8 R8G8B8A8; // R8G8B8A8 type is functionally equivalent for mip purposes
-
-struct A16B16G16R16F
-{
-    unsigned short R;
-    unsigned short G;
-    unsigned short B;
-    unsigned short A;
-
-    static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2)
-    {
-        dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
-        dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f);
-        dst->B = gl::float32ToFloat16((gl::float16ToFloat32(src1->B) + gl::float16ToFloat32(src2->B)) * 0.5f);
-        dst->A = gl::float32ToFloat16((gl::float16ToFloat32(src1->A) + gl::float16ToFloat32(src2->A)) * 0.5f);
-    }
-};
-
-struct R16F
-{
-    unsigned short R;
-
-    static void average(R16F *dst, const R16F *src1, const R16F *src2)
-    {
-        dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
-    }
-};
-
-struct R16G16F
-{
-    unsigned short R;
-    unsigned short G;
-
-    static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2)
-    {
-        dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
-        dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f);
-    }
-};
-
-struct A32B32G32R32F
-{
-    float R;
-    float G;
-    float B;
-    float A;
-
-    static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2)
-    {
-        dst->R = (src1->R + src2->R) * 0.5f;
-        dst->G = (src1->G + src2->G) * 0.5f;
-        dst->B = (src1->B + src2->B) * 0.5f;
-        dst->A = (src1->A + src2->A) * 0.5f;
-    }
-};
-
-struct R32F
-{
-    float R;
-
-    static void average(R32F *dst, const R32F *src1, const R32F *src2)
-    {
-        dst->R = (src1->R + src2->R) * 0.5f;
-    }
-};
-
-struct R32G32F
-{
-    float R;
-    float G;
-
-    static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2)
-    {
-        dst->R = (src1->R + src2->R) * 0.5f;
-        dst->G = (src1->G + src2->G) * 0.5f;
-    }
-};
-
-struct R32G32B32F
-{
-    float R;
-    float G;
-    float B;
-
-    static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2)
-    {
-        dst->R = (src1->R + src2->R) * 0.5f;
-        dst->G = (src1->G + src2->G) * 0.5f;
-        dst->B = (src1->B + src2->B) * 0.5f;
-    }
-};
-
-template <typename T>
-static void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight,
-                        const unsigned char *sourceData, int sourcePitch,
-                        unsigned char *destData, int destPitch)
-{
-    unsigned int mipWidth = std::max(1U, sourceWidth >> 1);
-    unsigned int mipHeight = std::max(1U, sourceHeight >> 1);
-
-    if (sourceHeight == 1)
-    {
-        ASSERT(sourceWidth != 1);
-
-        const T *src = (const T*)sourceData;
-        T *dst = (T*)destData;
-
-        for (unsigned int x = 0; x < mipWidth; x++)
-        {
-            T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]);
-        }
-    }
-    else if (sourceWidth == 1)
-    {
-        ASSERT(sourceHeight != 1);
-
-        for (unsigned int y = 0; y < mipHeight; y++)
-        {
-            const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch);
-            const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch);
-            T *dst = (T*)(destData + y * destPitch);
-
-            T::average(dst, src0, src1);
-        }
-    }
-    else
-    {
-        for (unsigned int y = 0; y < mipHeight; y++)
-        {
-            const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch);
-            const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch);
-            T *dst = (T*)(destData + y * destPitch);
-
-            for (unsigned int x = 0; x < mipWidth; x++)
-            {
-                T tmp0;
-                T tmp1;
-
-                T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]);
-                T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]);
-                T::average(&dst[x], &tmp0, &tmp1);
-            }
-        }
-    }
-}
-}
-
-#endif // LIBGLESV2_RENDERER_GENERATEMIP_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/renderer11_utils.cpp b/src/third_party/angle/src/libGLESv2/renderer/renderer11_utils.cpp
deleted file mode 100644
index 608245e..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/renderer11_utils.cpp
+++ /dev/null
@@ -1,950 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// renderer11_utils.cpp: Conversion functions and other utility routines
-// specific to the D3D11 renderer.
-
-#include "libGLESv2/renderer/renderer11_utils.h"
-
-#include "common/debug.h"
-
-#define MAX(a, b) ((a) > (b)) ? (a) : (b)
-
-namespace gl_d3d11
-{
-
-D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
-{
-    D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
-
-    switch (glBlend)
-    {
-      case GL_ZERO:                     d3dBlend = D3D11_BLEND_ZERO;                break;
-      case GL_ONE:                      d3dBlend = D3D11_BLEND_ONE;                 break;
-      case GL_SRC_COLOR:                d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR);           break;
-      case GL_ONE_MINUS_SRC_COLOR:      d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR);   break;
-      case GL_DST_COLOR:                d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR);         break;
-      case GL_ONE_MINUS_DST_COLOR:      d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break;
-      case GL_SRC_ALPHA:                d3dBlend = D3D11_BLEND_SRC_ALPHA;           break;
-      case GL_ONE_MINUS_SRC_ALPHA:      d3dBlend = D3D11_BLEND_INV_SRC_ALPHA;       break;
-      case GL_DST_ALPHA:                d3dBlend = D3D11_BLEND_DEST_ALPHA;          break;
-      case GL_ONE_MINUS_DST_ALPHA:      d3dBlend = D3D11_BLEND_INV_DEST_ALPHA;      break;
-      case GL_CONSTANT_COLOR:           d3dBlend = D3D11_BLEND_BLEND_FACTOR;        break;
-      case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;    break;
-      case GL_CONSTANT_ALPHA:           d3dBlend = D3D11_BLEND_BLEND_FACTOR;        break;
-      case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;    break;
-      case GL_SRC_ALPHA_SATURATE:       d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;       break;
-      default: UNREACHABLE();
-    }
-
-    return d3dBlend;
-}
-
-D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
-{
-    D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
-
-    switch (glBlendOp)
-    {
-      case GL_FUNC_ADD:              d3dBlendOp = D3D11_BLEND_OP_ADD;           break;
-      case GL_FUNC_SUBTRACT:         d3dBlendOp = D3D11_BLEND_OP_SUBTRACT;      break;
-      case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT;  break;
-      default: UNREACHABLE();
-    }
-
-    return d3dBlendOp;
-}
-
-UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
-{
-    UINT8 mask = 0;
-    if (red)
-    {
-        mask |= D3D11_COLOR_WRITE_ENABLE_RED;
-    }
-    if (green)
-    {
-        mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
-    }
-    if (blue)
-    {
-        mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
-    }
-    if (alpha)
-    {
-        mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
-    }
-    return mask;
-}
-
-D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode)
-{
-    D3D11_CULL_MODE cull = D3D11_CULL_NONE;
-
-    if (cullEnabled)
-    {
-        switch (cullMode)
-        {
-          case GL_FRONT:            cull = D3D11_CULL_FRONT;    break;
-          case GL_BACK:             cull = D3D11_CULL_BACK;     break;
-          case GL_FRONT_AND_BACK:   cull = D3D11_CULL_NONE;     break;
-          default: UNREACHABLE();
-        }
-    }
-    else
-    {
-        cull = D3D11_CULL_NONE;
-    }
-
-    return cull;
-}
-
-D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
-{
-    D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
-    switch (comparison)
-    {
-      case GL_NEVER:    d3dComp = D3D11_COMPARISON_NEVER;           break;
-      case GL_ALWAYS:   d3dComp = D3D11_COMPARISON_ALWAYS;          break;
-      case GL_LESS:     d3dComp = D3D11_COMPARISON_LESS;            break;
-      case GL_LEQUAL:   d3dComp = D3D11_COMPARISON_LESS_EQUAL;      break;
-      case GL_EQUAL:    d3dComp = D3D11_COMPARISON_EQUAL;           break;
-      case GL_GREATER:  d3dComp = D3D11_COMPARISON_GREATER;         break;
-      case GL_GEQUAL:   d3dComp = D3D11_COMPARISON_GREATER_EQUAL;   break;
-      case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL;       break;
-      default: UNREACHABLE();
-    }
-
-    return d3dComp;
-}
-
-D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
-{
-    return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
-}
-
-UINT8 ConvertStencilMask(GLuint stencilmask)
-{
-    return static_cast<UINT8>(stencilmask);
-}
-
-D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
-{
-    D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
-
-    switch (stencilOp)
-    {
-      case GL_ZERO:      d3dStencilOp = D3D11_STENCIL_OP_ZERO;      break;
-      case GL_KEEP:      d3dStencilOp = D3D11_STENCIL_OP_KEEP;      break;
-      case GL_REPLACE:   d3dStencilOp = D3D11_STENCIL_OP_REPLACE;   break;
-      case GL_INCR:      d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT;  break;
-      case GL_DECR:      d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT;  break;
-      case GL_INVERT:    d3dStencilOp = D3D11_STENCIL_OP_INVERT;    break;
-      case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR;      break;
-      case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR;      break;
-      default: UNREACHABLE();
-    }
-
-    return d3dStencilOp;
-}
-
-D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy)
-{
-    if (maxAnisotropy > 1.0f)
-    {
-        return D3D11_ENCODE_ANISOTROPIC_FILTER(false);
-    }
-    else
-    {
-        D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
-        D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
-        switch (minFilter)
-        {
-          case GL_NEAREST:                dxMin = D3D11_FILTER_TYPE_POINT;  dxMip = D3D11_FILTER_TYPE_POINT;  break;
-          case GL_LINEAR:                 dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT;  break;
-          case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT;  dxMip = D3D11_FILTER_TYPE_POINT;  break;
-          case GL_LINEAR_MIPMAP_NEAREST:  dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT;  break;
-          case GL_NEAREST_MIPMAP_LINEAR:  dxMin = D3D11_FILTER_TYPE_POINT;  dxMip = D3D11_FILTER_TYPE_LINEAR; break;
-          case GL_LINEAR_MIPMAP_LINEAR:   dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break;
-          default:                        UNREACHABLE();
-        }
-
-        D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
-        switch (magFilter)
-        {
-          case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT;  break;
-          case GL_LINEAR:  dxMag = D3D11_FILTER_TYPE_LINEAR; break;
-          default:         UNREACHABLE();
-        }
-
-        return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, false);
-    }
-}
-
-D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
-{
-    switch (wrap)
-    {
-      case GL_REPEAT:          return D3D11_TEXTURE_ADDRESS_WRAP;
-      case GL_CLAMP_TO_EDGE:   return D3D11_TEXTURE_ADDRESS_CLAMP;
-      case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR;
-      default:                 UNREACHABLE();
-    }
-
-    return D3D11_TEXTURE_ADDRESS_WRAP;
-}
-
-FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset)
-{
-    return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast<float>(lodOffset) : -FLT_MAX;
-}
-
-FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset)
-{
-    return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast<float>(lodOffset) : FLT_MAX;
-}
-
-}
-
-namespace d3d11_gl
-{
-
-GLenum ConvertBackBufferFormat(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8_OES;
-      case DXGI_FORMAT_B8G8R8A8_UNORM: return GL_BGRA8_EXT;
-      default:
-        UNREACHABLE();
-    }
-
-    return GL_RGBA8_OES;
-}
-
-GLenum ConvertDepthStencilFormat(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_UNKNOWN: return GL_NONE;
-      case DXGI_FORMAT_D16_UNORM: return GL_DEPTH_COMPONENT16;
-      case DXGI_FORMAT_D24_UNORM_S8_UINT: return GL_DEPTH24_STENCIL8_OES;
-      default:
-        UNREACHABLE();
-    }
-
-    return GL_DEPTH24_STENCIL8_OES;
-}
-
-GLenum ConvertRenderbufferFormat(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_B8G8R8A8_UNORM:
-        return GL_BGRA8_EXT;
-      case DXGI_FORMAT_R8G8B8A8_UNORM:
-        return GL_RGBA8_OES;
-      case DXGI_FORMAT_D16_UNORM:
-        return GL_DEPTH_COMPONENT16;
-      case DXGI_FORMAT_D24_UNORM_S8_UINT:
-        return GL_DEPTH24_STENCIL8_OES;
-      default:
-        UNREACHABLE();
-    }
-
-    return GL_RGBA8_OES;
-}
-
-GLenum ConvertTextureInternalFormat(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_R8G8B8A8_UNORM:
-        return GL_RGBA8_OES;
-      case DXGI_FORMAT_A8_UNORM:
-        return GL_ALPHA8_EXT;
-      case DXGI_FORMAT_BC1_UNORM:
-        return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
-      case DXGI_FORMAT_BC2_UNORM:
-        return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
-      case DXGI_FORMAT_BC3_UNORM:
-        return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
-      case DXGI_FORMAT_R32G32B32A32_FLOAT:
-        return GL_RGBA32F_EXT;
-      case DXGI_FORMAT_R32G32B32_FLOAT:
-        return GL_RGB32F_EXT;
-      case DXGI_FORMAT_R16G16B16A16_FLOAT:
-        return GL_RGBA16F_EXT;
-      case DXGI_FORMAT_B8G8R8A8_UNORM:
-        return GL_BGRA8_EXT;
-      case DXGI_FORMAT_R8_UNORM:
-        return GL_R8_EXT;
-      case DXGI_FORMAT_R8G8_UNORM:
-        return GL_RG8_EXT;
-      case DXGI_FORMAT_R16_FLOAT:
-        return GL_R16F_EXT;
-      case DXGI_FORMAT_R16G16_FLOAT:
-        return GL_RG16F_EXT;
-      case DXGI_FORMAT_D16_UNORM:
-        return GL_DEPTH_COMPONENT16;
-      case DXGI_FORMAT_D24_UNORM_S8_UINT:
-        return GL_DEPTH24_STENCIL8_OES;
-      case DXGI_FORMAT_UNKNOWN:
-        return GL_NONE;
-      default:
-        UNREACHABLE();
-    }
-
-    return GL_RGBA8_OES;
-}
-
-}
-
-namespace gl_d3d11
-{
-
-DXGI_FORMAT ConvertRenderbufferFormat(GLenum format)
-{
-    switch (format)
-    {
-      case GL_RGBA4:
-      case GL_RGB5_A1:
-      case GL_RGBA8_OES:
-      case GL_RGB565:
-      case GL_RGB8_OES:
-        return DXGI_FORMAT_R8G8B8A8_UNORM;
-      case GL_BGRA8_EXT:
-        return DXGI_FORMAT_B8G8R8A8_UNORM;
-      case GL_DEPTH_COMPONENT16:
-        return DXGI_FORMAT_D16_UNORM;
-      case GL_STENCIL_INDEX8:
-      case GL_DEPTH24_STENCIL8_OES:
-        return DXGI_FORMAT_D24_UNORM_S8_UINT;
-      default:
-        UNREACHABLE();
-    }
-
-    return DXGI_FORMAT_R8G8B8A8_UNORM;
-}
-
-DXGI_FORMAT ConvertTextureFormat(GLenum internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_RGB565:
-      case GL_RGBA4:
-      case GL_RGB5_A1:
-      case GL_RGB8_OES:
-      case GL_RGBA8_OES:
-      case GL_LUMINANCE8_EXT:
-      case GL_LUMINANCE8_ALPHA8_EXT:
-        return DXGI_FORMAT_R8G8B8A8_UNORM;
-      case GL_ALPHA8_EXT:
-        return DXGI_FORMAT_A8_UNORM;
-      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-        return DXGI_FORMAT_BC1_UNORM;
-      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-        return DXGI_FORMAT_BC2_UNORM;
-      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-        return DXGI_FORMAT_BC3_UNORM;
-      case GL_RGBA32F_EXT:
-      case GL_ALPHA32F_EXT:
-      case GL_LUMINANCE_ALPHA32F_EXT:
-        return DXGI_FORMAT_R32G32B32A32_FLOAT;
-      case GL_RGB32F_EXT:
-      case GL_LUMINANCE32F_EXT:
-        return DXGI_FORMAT_R32G32B32_FLOAT;
-      case GL_RGBA16F_EXT:
-      case GL_ALPHA16F_EXT:
-      case GL_LUMINANCE_ALPHA16F_EXT:
-      case GL_RGB16F_EXT:
-      case GL_LUMINANCE16F_EXT:
-        return DXGI_FORMAT_R16G16B16A16_FLOAT;
-      case GL_BGRA8_EXT:
-        return DXGI_FORMAT_B8G8R8A8_UNORM;
-      case GL_R8_EXT:
-        return DXGI_FORMAT_R8_UNORM;
-      case GL_RG8_EXT:
-        return DXGI_FORMAT_R8G8_UNORM;
-      case GL_R16F_EXT:
-        return DXGI_FORMAT_R16_FLOAT;
-      case GL_RG16F_EXT:
-        return DXGI_FORMAT_R16G16_FLOAT;
-      case GL_DEPTH_COMPONENT16:
-        return DXGI_FORMAT_D16_UNORM;
-      case GL_DEPTH_COMPONENT32_OES:
-      case GL_DEPTH24_STENCIL8_OES:
-        return DXGI_FORMAT_D24_UNORM_S8_UINT;
-      case GL_NONE:
-        return DXGI_FORMAT_UNKNOWN;
-      default:
-        UNREACHABLE();
-    }
-
-    return DXGI_FORMAT_R8G8B8A8_UNORM;
-}
-
-}
-
-namespace d3d11
-{
-
-void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v)
-{
-    vertex->x = x;
-    vertex->y = y;
-    vertex->u = u;
-    vertex->v = v;
-}
-
-void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z,
-                                 const gl::Color &color)
-{
-    vertex->x = x;
-    vertex->y = y;
-    vertex->z = z;
-    vertex->r = color.red;
-    vertex->g = color.green;
-    vertex->b = color.blue;
-    vertex->a = color.alpha;
-}
-
-size_t ComputePixelSizeBits(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_R1_UNORM:
-        return 1;
-
-      case DXGI_FORMAT_A8_UNORM:
-      case DXGI_FORMAT_R8_SINT:
-      case DXGI_FORMAT_R8_SNORM:
-      case DXGI_FORMAT_R8_TYPELESS:
-      case DXGI_FORMAT_R8_UINT:
-      case DXGI_FORMAT_R8_UNORM:
-        return 8;
-
-      case DXGI_FORMAT_B5G5R5A1_UNORM:
-      case DXGI_FORMAT_B5G6R5_UNORM:
-      case DXGI_FORMAT_D16_UNORM:
-      case DXGI_FORMAT_R16_FLOAT:
-      case DXGI_FORMAT_R16_SINT:
-      case DXGI_FORMAT_R16_SNORM:
-      case DXGI_FORMAT_R16_TYPELESS:
-      case DXGI_FORMAT_R16_UINT:
-      case DXGI_FORMAT_R16_UNORM:
-      case DXGI_FORMAT_R8G8_SINT:
-      case DXGI_FORMAT_R8G8_SNORM:
-      case DXGI_FORMAT_R8G8_TYPELESS:
-      case DXGI_FORMAT_R8G8_UINT:
-      case DXGI_FORMAT_R8G8_UNORM:
-        return 16;
-
-      case DXGI_FORMAT_B8G8R8X8_TYPELESS:
-      case DXGI_FORMAT_B8G8R8X8_UNORM:
-      case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
-      case DXGI_FORMAT_D24_UNORM_S8_UINT:
-      case DXGI_FORMAT_D32_FLOAT:
-      case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
-      case DXGI_FORMAT_G8R8_G8B8_UNORM:
-      case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
-      case DXGI_FORMAT_R10G10B10A2_TYPELESS:
-      case DXGI_FORMAT_R10G10B10A2_UINT:
-      case DXGI_FORMAT_R10G10B10A2_UNORM:
-      case DXGI_FORMAT_R11G11B10_FLOAT:
-      case DXGI_FORMAT_R16G16_FLOAT:
-      case DXGI_FORMAT_R16G16_SINT:
-      case DXGI_FORMAT_R16G16_SNORM:
-      case DXGI_FORMAT_R16G16_TYPELESS:
-      case DXGI_FORMAT_R16G16_UINT:
-      case DXGI_FORMAT_R16G16_UNORM:
-      case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
-      case DXGI_FORMAT_R24G8_TYPELESS:
-      case DXGI_FORMAT_R32_FLOAT:
-      case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
-      case DXGI_FORMAT_R32_SINT:
-      case DXGI_FORMAT_R32_TYPELESS:
-      case DXGI_FORMAT_R32_UINT:
-      case DXGI_FORMAT_R8G8_B8G8_UNORM:
-      case DXGI_FORMAT_R8G8B8A8_SINT:
-      case DXGI_FORMAT_R8G8B8A8_SNORM:
-      case DXGI_FORMAT_R8G8B8A8_TYPELESS:
-      case DXGI_FORMAT_R8G8B8A8_UINT:
-      case DXGI_FORMAT_R8G8B8A8_UNORM:
-      case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
-      case DXGI_FORMAT_B8G8R8A8_TYPELESS:
-      case DXGI_FORMAT_B8G8R8A8_UNORM:
-      case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
-      case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
-      case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
-      case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
-        return 32;
-
-      case DXGI_FORMAT_R16G16B16A16_FLOAT:
-      case DXGI_FORMAT_R16G16B16A16_SINT:
-      case DXGI_FORMAT_R16G16B16A16_SNORM:
-      case DXGI_FORMAT_R16G16B16A16_TYPELESS:
-      case DXGI_FORMAT_R16G16B16A16_UINT:
-      case DXGI_FORMAT_R16G16B16A16_UNORM:
-      case DXGI_FORMAT_R32G32_FLOAT:
-      case DXGI_FORMAT_R32G32_SINT:
-      case DXGI_FORMAT_R32G32_TYPELESS:
-      case DXGI_FORMAT_R32G32_UINT:
-      case DXGI_FORMAT_R32G8X24_TYPELESS:
-        return 64;
-
-      case DXGI_FORMAT_R32G32B32_FLOAT:
-      case DXGI_FORMAT_R32G32B32_SINT:
-      case DXGI_FORMAT_R32G32B32_TYPELESS:
-      case DXGI_FORMAT_R32G32B32_UINT:
-        return 96;
-
-      case DXGI_FORMAT_R32G32B32A32_FLOAT:
-      case DXGI_FORMAT_R32G32B32A32_SINT:
-      case DXGI_FORMAT_R32G32B32A32_TYPELESS:
-      case DXGI_FORMAT_R32G32B32A32_UINT:
-        return 128;
-
-      case DXGI_FORMAT_BC1_TYPELESS:
-      case DXGI_FORMAT_BC1_UNORM:
-      case DXGI_FORMAT_BC1_UNORM_SRGB:
-      case DXGI_FORMAT_BC4_SNORM:
-      case DXGI_FORMAT_BC4_TYPELESS:
-      case DXGI_FORMAT_BC4_UNORM:
-        return 4;
-
-      case DXGI_FORMAT_BC2_TYPELESS:
-      case DXGI_FORMAT_BC2_UNORM:
-      case DXGI_FORMAT_BC2_UNORM_SRGB:
-      case DXGI_FORMAT_BC3_TYPELESS:
-      case DXGI_FORMAT_BC3_UNORM:
-      case DXGI_FORMAT_BC3_UNORM_SRGB:
-      case DXGI_FORMAT_BC5_SNORM:
-      case DXGI_FORMAT_BC5_TYPELESS:
-      case DXGI_FORMAT_BC5_UNORM:
-      case DXGI_FORMAT_BC6H_SF16:
-      case DXGI_FORMAT_BC6H_TYPELESS:
-      case DXGI_FORMAT_BC6H_UF16:
-      case DXGI_FORMAT_BC7_TYPELESS:
-      case DXGI_FORMAT_BC7_UNORM:
-      case DXGI_FORMAT_BC7_UNORM_SRGB:
-        return 8;
-
-      default:
-        return 0;
-    }
-}
-
-size_t ComputeBlockSizeBits(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_BC1_TYPELESS:
-      case DXGI_FORMAT_BC1_UNORM:
-      case DXGI_FORMAT_BC1_UNORM_SRGB:
-      case DXGI_FORMAT_BC4_SNORM:
-      case DXGI_FORMAT_BC4_TYPELESS:
-      case DXGI_FORMAT_BC4_UNORM:
-      case DXGI_FORMAT_BC2_TYPELESS:
-      case DXGI_FORMAT_BC2_UNORM:
-      case DXGI_FORMAT_BC2_UNORM_SRGB:
-      case DXGI_FORMAT_BC3_TYPELESS:
-      case DXGI_FORMAT_BC3_UNORM:
-      case DXGI_FORMAT_BC3_UNORM_SRGB:
-      case DXGI_FORMAT_BC5_SNORM:
-      case DXGI_FORMAT_BC5_TYPELESS:
-      case DXGI_FORMAT_BC5_UNORM:
-      case DXGI_FORMAT_BC6H_SF16:
-      case DXGI_FORMAT_BC6H_TYPELESS:
-      case DXGI_FORMAT_BC6H_UF16:
-      case DXGI_FORMAT_BC7_TYPELESS:
-      case DXGI_FORMAT_BC7_UNORM:
-      case DXGI_FORMAT_BC7_UNORM_SRGB:
-        return ComputePixelSizeBits(format) * 16;
-      default:
-        UNREACHABLE();
-        return 0;
-    }
-}
-
-bool IsCompressed(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_BC1_TYPELESS:
-      case DXGI_FORMAT_BC1_UNORM:
-      case DXGI_FORMAT_BC1_UNORM_SRGB:
-      case DXGI_FORMAT_BC4_SNORM:
-      case DXGI_FORMAT_BC4_TYPELESS:
-      case DXGI_FORMAT_BC4_UNORM:
-      case DXGI_FORMAT_BC2_TYPELESS:
-      case DXGI_FORMAT_BC2_UNORM:
-      case DXGI_FORMAT_BC2_UNORM_SRGB:
-      case DXGI_FORMAT_BC3_TYPELESS:
-      case DXGI_FORMAT_BC3_UNORM:
-      case DXGI_FORMAT_BC3_UNORM_SRGB:
-      case DXGI_FORMAT_BC5_SNORM:
-      case DXGI_FORMAT_BC5_TYPELESS:
-      case DXGI_FORMAT_BC5_UNORM:
-      case DXGI_FORMAT_BC6H_SF16:
-      case DXGI_FORMAT_BC6H_TYPELESS:
-      case DXGI_FORMAT_BC6H_UF16:
-      case DXGI_FORMAT_BC7_TYPELESS:
-      case DXGI_FORMAT_BC7_UNORM:
-      case DXGI_FORMAT_BC7_UNORM_SRGB:
-        return true;
-      case DXGI_FORMAT_UNKNOWN:
-        UNREACHABLE();
-        return false;
-      default:
-        return false;
-    }
-}
-
-unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_BC1_TYPELESS:
-      case DXGI_FORMAT_BC1_UNORM:
-      case DXGI_FORMAT_BC1_UNORM_SRGB:
-      case DXGI_FORMAT_BC4_SNORM:
-      case DXGI_FORMAT_BC4_TYPELESS:
-      case DXGI_FORMAT_BC4_UNORM:
-      case DXGI_FORMAT_BC2_TYPELESS:
-      case DXGI_FORMAT_BC2_UNORM:
-      case DXGI_FORMAT_BC2_UNORM_SRGB:
-      case DXGI_FORMAT_BC3_TYPELESS:
-      case DXGI_FORMAT_BC3_UNORM:
-      case DXGI_FORMAT_BC3_UNORM_SRGB:
-      case DXGI_FORMAT_BC5_SNORM:
-      case DXGI_FORMAT_BC5_TYPELESS:
-      case DXGI_FORMAT_BC5_UNORM:
-      case DXGI_FORMAT_BC6H_SF16:
-      case DXGI_FORMAT_BC6H_TYPELESS:
-      case DXGI_FORMAT_BC6H_UF16:
-      case DXGI_FORMAT_BC7_TYPELESS:
-      case DXGI_FORMAT_BC7_UNORM:
-      case DXGI_FORMAT_BC7_UNORM_SRGB:
-        return 4;
-      case DXGI_FORMAT_UNKNOWN:
-        UNREACHABLE();
-        return 1;
-      default:
-        return 1;
-    }
-}
-
-bool IsDepthStencilFormat(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
-      case DXGI_FORMAT_D32_FLOAT:
-      case DXGI_FORMAT_D24_UNORM_S8_UINT:
-      case DXGI_FORMAT_D16_UNORM:
-        return true;
-      default:
-        return false;
-    }
-}
-
-DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS;
-      case DXGI_FORMAT_D32_FLOAT:            return DXGI_FORMAT_R32_TYPELESS;
-      case DXGI_FORMAT_D24_UNORM_S8_UINT:    return DXGI_FORMAT_R24G8_TYPELESS;
-      case DXGI_FORMAT_D16_UNORM:            return DXGI_FORMAT_R16_TYPELESS;
-      default: UNREACHABLE();                return DXGI_FORMAT_UNKNOWN;
-    }
-}
-
-DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format)
-{
-    switch (format)
-    {
-      case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
-      case DXGI_FORMAT_D32_FLOAT:            return DXGI_FORMAT_R32_UINT;
-      case DXGI_FORMAT_D24_UNORM_S8_UINT:    return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
-      case DXGI_FORMAT_D16_UNORM:            return DXGI_FORMAT_R16_UNORM;
-      default: UNREACHABLE();                return DXGI_FORMAT_UNKNOWN;
-    }
-}
-
-HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
-{
-#if defined(_DEBUG)
-    return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name);
-#else
-    return S_OK;
-#endif
-}
-
-namespace
-{
-EGLResourceTrackerProcAngle sResourceTrackerProc;
-void *sResourceTrackerUserData;
-
-size_t ComputeSurfaceSize(size_t width, size_t height, DXGI_FORMAT format)
-{
-  size_t sizeBits = width * height * ComputePixelSizeBits(format);
-
-  // Round up to the closest multiple of 8
-  size_t remainder = sizeBits & 7;
-  if (remainder)
-      sizeBits += (8 - remainder);
-
-  return sizeBits / 8;
-}
-}
-
-enum ResourceWrapperType
-{
-    // ID3D11Resource objects
-    RESOURCE_TEXTURE1D  = EGL_ANGLE_TRACK_TYPE_TEX1D,
-    RESOURCE_TEXTURE2D  = EGL_ANGLE_TRACK_TYPE_TEX2D,
-    RESOURCE_TEXTURE3D  = EGL_ANGLE_TRACK_TYPE_TEX3D,
-    RESOURCE_BUFFER     = EGL_ANGLE_TRACK_TYPE_BUFFER,
-
-    // DXGI objects
-    RESOURCE_SWAPCHAIN  = EGL_ANGLE_TRACK_TYPE_SWAPCHAIN,
-};
-
-MIDL_INTERFACE("404B2EB6-4229-45B2-A784-AF6416720434")
-IResourceWrapper : public IUnknown {
-    virtual EGLint GetResourceType() = 0;
-};
-
-class ResourceWrapper : public IResourceWrapper
-{
-  public:
-    ResourceWrapper(IUnknown *resource, ResourceWrapperType type,
-                    size_t resourceSize)
-    {
-        mCounter = 0;
-        mResource = resource;
-        mResourceSize = static_cast<EGLint>(resourceSize);
-        mResourceType = type;
-    }
-
-    virtual ~ResourceWrapper()
-    {
-        SignalRelease();
-    }
-
-    //////////////////////
-    // IUnknown methods
-
-    virtual ULONG AddRef()
-    {
-      return mCounter++;
-    }
-
-    virtual ULONG Release()
-    {
-      if (mCounter == 0)
-          return 0;
-
-      ULONG counter = --mCounter;
-      if (counter == 0)
-          delete this;
-
-      return counter;
-    }
-
-    virtual HRESULT QueryInterface(REFIID riid, void **ppvObject)
-    {
-        if (ppvObject == NULL)
-            return E_POINTER;
-
-        if (IsEqualGUID(riid, __uuidof(IResourceWrapper)) ||
-            IsEqualGUID(riid, __uuidof(IUnknown)))
-        {
-            *ppvObject = this;
-            return S_OK;
-        }
-        return E_NOINTERFACE;
-    }
-
-    /////////////////////////////
-    // IResourceWrapper methods
-
-    virtual EGLint GetResourceType()
-    {
-        return static_cast<EGLint>(mResourceType);
-    }
-
-    /////////////////////////////
-    // ResourceWrapper methods
-    void SignalCreate()
-    {
-        EGLResourceTrackerDataAngle data =
-        {
-            mResource,
-            EGL_ANGLE_TRACK_OPTYPE_CREATE,
-            mResourceType,
-            mResourceSize,
-        };
-        if (sResourceTrackerProc)
-            sResourceTrackerProc(&data, sResourceTrackerUserData);
-    }
-
-    void SignalRelease()
-    {
-        EGLResourceTrackerDataAngle data =
-        {
-            mResource,
-            EGL_ANGLE_TRACK_OPTYPE_DESTROY,
-            mResourceType,
-            mResourceSize,
-        };
-        if (sResourceTrackerProc)
-            sResourceTrackerProc(&data, sResourceTrackerUserData);
-    }
-
-  private:
-    ULONG mCounter;
-
-    IUnknown *mResource;
-    EGLint mResourceSize;
-    ResourceWrapperType mResourceType;
-};
-
-template <typename Resource_>
-void RegisterWrapper(Resource_ *resource, ResourceWrapperType type,
-                     size_t resourceSize) {
-    ResourceWrapper *wrapper = new ResourceWrapper(resource, type,
-                                                   resourceSize);
-    resource->SetPrivateDataInterface(__uuidof(IResourceWrapper), wrapper);
-    wrapper->SignalCreate();
-}
-
-bool ShouldTrackResource(ID3D11Resource *resource)
-{
-    if (resource == NULL || sResourceTrackerProc == NULL)
-        return false;
-
-    return true;
-}
-
-bool ShouldTrackDxgiObj(IDXGIObject *dxgiObj)
-{
-    if (dxgiObj == NULL || sResourceTrackerProc == NULL)
-        return false;
-
-    return true;
-}
-
-void ResourceTracker::SetTracker(EGLResourceTrackerProcAngle proc, void *userData)
-{
-    sResourceTrackerProc = proc;
-    sResourceTrackerUserData = userData;
-}
-
-void ResourceTracker::Track(ID3D11Texture1D *tex1d)
-{
-    if (!ShouldTrackResource(tex1d))
-        return;
-
-    D3D11_TEXTURE1D_DESC desc;
-    tex1d->GetDesc(&desc);
-
-    size_t numMips = MAX(1, desc.MipLevels);
-    size_t width = desc.Width;
-
-    size_t resourceSize = 0;
-    for (size_t i = 0; i < numMips; ++i)
-    {
-        resourceSize += ComputeSurfaceSize(width, 1, desc.Format);
-        width = MAX(1, width / 2);
-    }
-
-    resourceSize = desc.ArraySize * resourceSize;
-    RegisterWrapper(tex1d, RESOURCE_TEXTURE1D, resourceSize);
-}
-
-void ResourceTracker::Track(ID3D11Texture2D *tex2d)
-{
-    if (!ShouldTrackResource(tex2d))
-        return;
-
-    D3D11_TEXTURE2D_DESC desc;
-    tex2d->GetDesc(&desc);
-
-    size_t numMips = MAX(1, desc.MipLevels);
-    size_t width = desc.Width;
-    size_t height = desc.Height;
-
-    size_t resourceSize = 0;
-    for (size_t i = 0; i < numMips; ++i)
-    {
-        resourceSize += ComputeSurfaceSize(width, height, desc.Format);
-        width = MAX(1, width / 2);
-        height = MAX(1, height / 2);
-    }
-
-    resourceSize = desc.ArraySize * resourceSize;
-    RegisterWrapper(tex2d, RESOURCE_TEXTURE2D, resourceSize);
-}
-
-void ResourceTracker::Track(ID3D11Texture3D *tex3d)
-{
-    if (!ShouldTrackResource(tex3d))
-        return;
-
-    D3D11_TEXTURE3D_DESC desc;
-    tex3d->GetDesc(&desc);
-
-    size_t numMips = MAX(1, desc.MipLevels);
-    size_t width = desc.Width;
-    size_t height = desc.Height;
-    size_t depth = desc.Depth;
-
-    size_t resourceSize = 0;
-    for (size_t i = 0; i < numMips; ++i)
-    {
-        resourceSize += ComputeSurfaceSize(width, height, desc.Format) * depth;
-        width = MAX(1, width / 2);
-        height = MAX(1, height / 2);
-        depth = MAX(1, depth / 2);
-    }
-
-    RegisterWrapper(tex3d, RESOURCE_TEXTURE3D, resourceSize);
-}
-
-void ResourceTracker::Track(ID3D11Buffer *buf)
-{
-    if (!ShouldTrackResource(buf))
-        return;
-
-    D3D11_BUFFER_DESC desc;
-    buf->GetDesc(&desc);
-
-    size_t resourceSize = desc.ByteWidth;
-    RegisterWrapper(buf, RESOURCE_BUFFER, resourceSize);
-}
-
-void ResourceTracker::Track(IDXGISwapChain *swapChain)
-{
-    if (!ShouldTrackDxgiObj(swapChain))
-        return;
-
-    DXGI_SWAP_CHAIN_DESC desc;
-    swapChain->GetDesc(&desc);
-
-    size_t resourceSize = ComputeSurfaceSize(desc.BufferDesc.Width,
-                                             desc.BufferDesc.Height,
-                                             desc.BufferDesc.Format);
-
-    resourceSize = desc.BufferCount * resourceSize;
-    RegisterWrapper(swapChain, RESOURCE_SWAPCHAIN, resourceSize);
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/renderer11_utils.h b/src/third_party/angle/src/libGLESv2/renderer/renderer11_utils.h
deleted file mode 100644
index c939c9b..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/renderer11_utils.h
+++ /dev/null
@@ -1,107 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// renderer11_utils.h: Conversion functions and other utility routines
-// specific to the D3D11 renderer.
-
-#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H
-#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H
-
-#include "libGLESv2/angletypes.h"
-
-namespace gl_d3d11
-{
-
-D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha);
-D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp);
-UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha);
-
-D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode);
-
-D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison);
-D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled);
-UINT8 ConvertStencilMask(GLuint stencilmask);
-D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp);
-
-D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy);
-D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap);
-FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset);
-FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset);
-
-DXGI_FORMAT ConvertRenderbufferFormat(GLenum format);
-DXGI_FORMAT ConvertTextureFormat(GLenum format);
-}
-
-namespace d3d11_gl
-{
-
-GLenum ConvertBackBufferFormat(DXGI_FORMAT format);
-GLenum ConvertDepthStencilFormat(DXGI_FORMAT format);
-GLenum ConvertRenderbufferFormat(DXGI_FORMAT format);
-GLenum ConvertTextureInternalFormat(DXGI_FORMAT format);
-
-}
-
-namespace d3d11
-{
-
-struct PositionTexCoordVertex
-{
-    float x, y;
-    float u, v;
-};
-void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v);
-
-struct PositionDepthColorVertex
-{
-    float x, y, z;
-    float r, g, b, a;
-};
-void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z,
-                                 const gl::Color &color);
-
-size_t ComputePixelSizeBits(DXGI_FORMAT format);
-size_t ComputeBlockSizeBits(DXGI_FORMAT format);
-
-bool IsCompressed(DXGI_FORMAT format);
-unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format);
-
-bool IsDepthStencilFormat(DXGI_FORMAT format);
-DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format);
-DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format);
-
-HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name);
-
-struct ResourceTracker
-{
-    static void SetTracker(EGLResourceTrackerProcAngle proc, void *userData);
-
-    static void Track(ID3D11Texture1D *tex1d);
-    static void Track(ID3D11Texture2D *tex2d);
-    static void Track(ID3D11Texture3D *tex3d);
-    static void Track(ID3D11Buffer *buf);
-
-    static void Track(IDXGISwapChain *swapChain);
-};
-
-inline bool isDeviceLostError(HRESULT errorCode)
-{
-    switch (errorCode)
-    {
-      case DXGI_ERROR_DEVICE_HUNG:
-      case DXGI_ERROR_DEVICE_REMOVED:
-      case DXGI_ERROR_DEVICE_RESET:
-      case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
-      case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
-        return true;
-      default:
-        return false;
-    }
-}
-
-}
-
-#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H
diff --git a/src/third_party/angle/src/libGLESv2/renderer/renderer9_utils.cpp b/src/third_party/angle/src/libGLESv2/renderer/renderer9_utils.cpp
deleted file mode 100644
index da75d46..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/renderer9_utils.cpp
+++ /dev/null
@@ -1,500 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// renderer9_utils.cpp: Conversion functions and other utility routines
-// specific to the D3D9 renderer.
-
-#include "libGLESv2/renderer/renderer9_utils.h"
-#include "libGLESv2/mathutil.h"
-#include "libGLESv2/Context.h"
-
-#include "common/debug.h"
-
-namespace gl_d3d9
-{
-
-D3DCMPFUNC ConvertComparison(GLenum comparison)
-{
-    D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
-    switch (comparison)
-    {
-      case GL_NEVER:    d3dComp = D3DCMP_NEVER;        break;
-      case GL_ALWAYS:   d3dComp = D3DCMP_ALWAYS;       break;
-      case GL_LESS:     d3dComp = D3DCMP_LESS;         break;
-      case GL_LEQUAL:   d3dComp = D3DCMP_LESSEQUAL;    break;
-      case GL_EQUAL:    d3dComp = D3DCMP_EQUAL;        break;
-      case GL_GREATER:  d3dComp = D3DCMP_GREATER;      break;
-      case GL_GEQUAL:   d3dComp = D3DCMP_GREATEREQUAL; break;
-      case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL;     break;
-      default: UNREACHABLE();
-    }
-
-    return d3dComp;
-}
-
-D3DCOLOR ConvertColor(gl::Color color)
-{
-    return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
-                         gl::unorm<8>(color.green),
-                         gl::unorm<8>(color.blue),
-                         gl::unorm<8>(color.alpha));
-}
-
-D3DBLEND ConvertBlendFunc(GLenum blend)
-{
-    D3DBLEND d3dBlend = D3DBLEND_ZERO;
-
-    switch (blend)
-    {
-      case GL_ZERO:                     d3dBlend = D3DBLEND_ZERO;           break;
-      case GL_ONE:                      d3dBlend = D3DBLEND_ONE;            break;
-      case GL_SRC_COLOR:                d3dBlend = D3DBLEND_SRCCOLOR;       break;
-      case GL_ONE_MINUS_SRC_COLOR:      d3dBlend = D3DBLEND_INVSRCCOLOR;    break;
-      case GL_DST_COLOR:                d3dBlend = D3DBLEND_DESTCOLOR;      break;
-      case GL_ONE_MINUS_DST_COLOR:      d3dBlend = D3DBLEND_INVDESTCOLOR;   break;
-      case GL_SRC_ALPHA:                d3dBlend = D3DBLEND_SRCALPHA;       break;
-      case GL_ONE_MINUS_SRC_ALPHA:      d3dBlend = D3DBLEND_INVSRCALPHA;    break;
-      case GL_DST_ALPHA:                d3dBlend = D3DBLEND_DESTALPHA;      break;
-      case GL_ONE_MINUS_DST_ALPHA:      d3dBlend = D3DBLEND_INVDESTALPHA;   break;
-      case GL_CONSTANT_COLOR:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
-      case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
-      case GL_CONSTANT_ALPHA:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
-      case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
-      case GL_SRC_ALPHA_SATURATE:       d3dBlend = D3DBLEND_SRCALPHASAT;    break;
-      default: UNREACHABLE();
-    }
-
-    return d3dBlend;
-}
-
-D3DBLENDOP ConvertBlendOp(GLenum blendOp)
-{
-    D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
-
-    switch (blendOp)
-    {
-      case GL_FUNC_ADD:              d3dBlendOp = D3DBLENDOP_ADD;         break;
-      case GL_FUNC_SUBTRACT:         d3dBlendOp = D3DBLENDOP_SUBTRACT;    break;
-      case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
-      default: UNREACHABLE();
-    }
-
-    return d3dBlendOp;
-}
-
-D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
-{
-    D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
-
-    switch (stencilOp)
-    {
-      case GL_ZERO:      d3dStencilOp = D3DSTENCILOP_ZERO;    break;
-      case GL_KEEP:      d3dStencilOp = D3DSTENCILOP_KEEP;    break;
-      case GL_REPLACE:   d3dStencilOp = D3DSTENCILOP_REPLACE; break;
-      case GL_INCR:      d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
-      case GL_DECR:      d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
-      case GL_INVERT:    d3dStencilOp = D3DSTENCILOP_INVERT;  break;
-      case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR;    break;
-      case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR;    break;
-      default: UNREACHABLE();
-    }
-
-    return d3dStencilOp;
-}
-
-D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
-{
-    D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
-
-    switch (wrap)
-    {
-      case GL_REPEAT:            d3dWrap = D3DTADDRESS_WRAP;   break;
-      case GL_CLAMP_TO_EDGE:     d3dWrap = D3DTADDRESS_CLAMP;  break;
-      case GL_MIRRORED_REPEAT:   d3dWrap = D3DTADDRESS_MIRROR; break;
-      default: UNREACHABLE();
-    }
-
-    return d3dWrap;
-}
-
-D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
-{
-    D3DCULL cull = D3DCULL_CCW;
-    switch (cullFace)
-    {
-      case GL_FRONT:
-        cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
-        break;
-      case GL_BACK:
-        cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
-        break;
-      case GL_FRONT_AND_BACK:
-        cull = D3DCULL_NONE; // culling will be handled during draw
-        break;
-      default: UNREACHABLE();
-    }
-
-    return cull;
-}
-
-D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
-{
-    D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
-
-    switch (cubeFace)
-    {
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-        face = D3DCUBEMAP_FACE_POSITIVE_X;
-        break;
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-        face = D3DCUBEMAP_FACE_NEGATIVE_X;
-        break;
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-        face = D3DCUBEMAP_FACE_POSITIVE_Y;
-        break;
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-        face = D3DCUBEMAP_FACE_NEGATIVE_Y;
-        break;
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-        face = D3DCUBEMAP_FACE_POSITIVE_Z;
-        break;
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-        face = D3DCUBEMAP_FACE_NEGATIVE_Z;
-        break;
-      default: UNREACHABLE();
-    }
-
-    return face;
-}
-
-DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
-{
-    return (red   ? D3DCOLORWRITEENABLE_RED   : 0) |
-           (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
-           (blue  ? D3DCOLORWRITEENABLE_BLUE  : 0) |
-           (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
-}
-
-D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
-{
-    if (maxAnisotropy > 1.0f)
-    {
-        return D3DTEXF_ANISOTROPIC;
-    }
-
-    D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
-    switch (magFilter)
-    {
-      case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT;  break;
-      case GL_LINEAR:  d3dMagFilter = D3DTEXF_LINEAR; break;
-      default: UNREACHABLE();
-    }
-
-    return d3dMagFilter;
-}
-
-void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy)
-{
-    switch (minFilter)
-    {
-      case GL_NEAREST:
-        *d3dMinFilter = D3DTEXF_POINT;
-        *d3dMipFilter = D3DTEXF_NONE;
-        break;
-      case GL_LINEAR:
-        *d3dMinFilter = D3DTEXF_LINEAR;
-        *d3dMipFilter = D3DTEXF_NONE;
-        break;
-      case GL_NEAREST_MIPMAP_NEAREST:
-        *d3dMinFilter = D3DTEXF_POINT;
-        *d3dMipFilter = D3DTEXF_POINT;
-        break;
-      case GL_LINEAR_MIPMAP_NEAREST:
-        *d3dMinFilter = D3DTEXF_LINEAR;
-        *d3dMipFilter = D3DTEXF_POINT;
-        break;
-      case GL_NEAREST_MIPMAP_LINEAR:
-        *d3dMinFilter = D3DTEXF_POINT;
-        *d3dMipFilter = D3DTEXF_LINEAR;
-        break;
-      case GL_LINEAR_MIPMAP_LINEAR:
-        *d3dMinFilter = D3DTEXF_LINEAR;
-        *d3dMipFilter = D3DTEXF_LINEAR;
-        break;
-      default:
-        *d3dMinFilter = D3DTEXF_POINT;
-        *d3dMipFilter = D3DTEXF_NONE;
-        UNREACHABLE();
-    }
-
-    if (maxAnisotropy > 1.0f)
-    {
-        *d3dMinFilter = D3DTEXF_ANISOTROPIC;
-    }
-}
-
-D3DFORMAT ConvertRenderbufferFormat(GLenum format)
-{
-    switch (format)
-    {
-      case GL_NONE:                 return D3DFMT_NULL;
-      case GL_RGBA4:
-      case GL_RGB5_A1:
-      case GL_RGBA8_OES:            return D3DFMT_A8R8G8B8;
-      case GL_RGB565:               return D3DFMT_R5G6B5;
-      case GL_RGB8_OES:             return D3DFMT_X8R8G8B8;
-      case GL_DEPTH_COMPONENT16:
-      case GL_STENCIL_INDEX8:       
-      case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
-      default: UNREACHABLE();       return D3DFMT_A8R8G8B8;
-    }
-}
-
-D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
-{
-    if (samples <= 1)
-        return D3DMULTISAMPLE_NONE;
-    else
-        return (D3DMULTISAMPLE_TYPE)samples;
-}
-
-}
-
-namespace d3d9_gl
-{
-
-unsigned int GetStencilSize(D3DFORMAT stencilFormat)
-{
-    if (stencilFormat == D3DFMT_INTZ)
-    {
-        return 8;
-    }
-    switch(stencilFormat)
-    {
-      case D3DFMT_D24FS8:
-      case D3DFMT_D24S8:
-        return 8;
-      case D3DFMT_D24X4S4:
-        return 4;
-      case D3DFMT_D15S1:
-        return 1;
-      case D3DFMT_D16_LOCKABLE:
-      case D3DFMT_D32:
-      case D3DFMT_D24X8:
-      case D3DFMT_D32F_LOCKABLE:
-      case D3DFMT_D16:
-        return 0;
-    //case D3DFMT_D32_LOCKABLE:  return 0;   // DirectX 9Ex only
-    //case D3DFMT_S8_LOCKABLE:   return 8;   // DirectX 9Ex only
-      default:
-        return 0;
-    }
-}
-
-unsigned int GetAlphaSize(D3DFORMAT colorFormat)
-{
-    switch (colorFormat)
-    {
-      case D3DFMT_A16B16G16R16F:
-        return 16;
-      case D3DFMT_A32B32G32R32F:
-        return 32;
-      case D3DFMT_A2R10G10B10:
-        return 2;
-      case D3DFMT_A8R8G8B8:
-        return 8;
-      case D3DFMT_A1R5G5B5:
-        return 1;
-      case D3DFMT_X8R8G8B8:
-      case D3DFMT_R5G6B5:
-        return 0;
-      default:
-        return 0;
-    }
-}
-
-GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
-{
-    if (type == D3DMULTISAMPLE_NONMASKABLE)
-        return 0;
-    else
-        return type;
-}
-
-bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
-{
-    switch (d3dformat)
-    {
-      case D3DFMT_L8:
-        return (format == GL_LUMINANCE);
-      case D3DFMT_A8L8:
-        return (format == GL_LUMINANCE_ALPHA);
-      case D3DFMT_DXT1:
-        return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
-      case D3DFMT_DXT3:
-        return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
-      case D3DFMT_DXT5:
-        return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
-      case D3DFMT_A8R8G8B8:
-      case D3DFMT_A16B16G16R16F:
-      case D3DFMT_A32B32G32R32F:
-        return (format == GL_RGBA || format == GL_BGRA_EXT);
-      case D3DFMT_X8R8G8B8:
-        return (format == GL_RGB);
-      default:
-        if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format))
-            return true;
-        return false;
-    }
-}
-
-GLenum ConvertBackBufferFormat(D3DFORMAT format)
-{
-    switch (format)
-    {
-      case D3DFMT_A4R4G4B4: return GL_RGBA4;
-      case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
-      case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
-      case D3DFMT_R5G6B5:   return GL_RGB565;
-      case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
-      default:
-        UNREACHABLE();
-    }
-
-    return GL_RGBA4;
-}
-
-GLenum ConvertDepthStencilFormat(D3DFORMAT format)
-{
-    if (format == D3DFMT_INTZ)
-    {
-        return GL_DEPTH24_STENCIL8_OES;
-    }
-    switch (format)
-    {
-      case D3DFMT_D16:
-      case D3DFMT_D24X8:
-        return GL_DEPTH_COMPONENT16;
-      case D3DFMT_D24S8:
-        return GL_DEPTH24_STENCIL8_OES;
-      case D3DFMT_UNKNOWN:
-        return GL_NONE;
-      default:
-        UNREACHABLE();
-    }
-
-    return GL_DEPTH24_STENCIL8_OES;
-}
-
-GLenum ConvertRenderTargetFormat(D3DFORMAT format)
-{
-    if (format == D3DFMT_INTZ)
-    {
-        return GL_DEPTH24_STENCIL8_OES;
-    }
-    
-    switch (format)
-    {
-      case D3DFMT_A4R4G4B4: return GL_RGBA4;
-      case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
-      case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
-      case D3DFMT_R5G6B5:   return GL_RGB565;
-      case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
-      case D3DFMT_D16:
-      case D3DFMT_D24X8:
-        return GL_DEPTH_COMPONENT16;
-      case D3DFMT_D24S8:
-        return GL_DEPTH24_STENCIL8_OES;
-      case D3DFMT_UNKNOWN:
-        return GL_NONE;
-      default:
-        UNREACHABLE();
-    }
-
-    return GL_RGBA4;
-}
-
-GLenum GetEquivalentFormat(D3DFORMAT format)
-{
-    if (format == D3DFMT_INTZ)
-        return GL_DEPTH24_STENCIL8_OES;
-    if (format == D3DFMT_NULL)
-        return GL_NONE;
-
-    switch (format)
-    {
-      case D3DFMT_A4R4G4B4:             return GL_RGBA4;
-      case D3DFMT_A8R8G8B8:             return GL_RGBA8_OES;
-      case D3DFMT_A1R5G5B5:             return GL_RGB5_A1;
-      case D3DFMT_R5G6B5:               return GL_RGB565;
-      case D3DFMT_X8R8G8B8:             return GL_RGB8_OES;
-      case D3DFMT_D16:                  return GL_DEPTH_COMPONENT16;
-      case D3DFMT_D24S8:                return GL_DEPTH24_STENCIL8_OES;
-      case D3DFMT_UNKNOWN:              return GL_NONE;
-      case D3DFMT_DXT1:                 return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
-      case D3DFMT_DXT3:                 return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
-      case D3DFMT_DXT5:                 return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
-      case D3DFMT_A32B32G32R32F:        return GL_RGBA32F_EXT;
-      case D3DFMT_A16B16G16R16F:        return GL_RGBA16F_EXT;
-      case D3DFMT_L8:                   return GL_LUMINANCE8_EXT;
-      case D3DFMT_A8L8:                 return GL_LUMINANCE8_ALPHA8_EXT;
-      default:              UNREACHABLE();
-        return GL_NONE;
-    }
-}
-
-}
-
-namespace d3d9
-{
-
-bool IsCompressedFormat(D3DFORMAT surfaceFormat)
-{
-    switch(surfaceFormat)
-    {
-      case D3DFMT_DXT1:
-      case D3DFMT_DXT2:
-      case D3DFMT_DXT3:
-      case D3DFMT_DXT4:
-      case D3DFMT_DXT5:
-        return true;
-      default:
-        return false;
-    }
-}
-
-size_t ComputeRowSize(D3DFORMAT format, unsigned int width)
-{
-    if (format == D3DFMT_INTZ)
-    {
-        return 4 * width;
-    }
-    switch (format)
-    {
-      case D3DFMT_L8:
-          return 1 * width;
-      case D3DFMT_A8L8:
-          return 2 * width;
-      case D3DFMT_X8R8G8B8:
-      case D3DFMT_A8R8G8B8:
-        return 4 * width;
-      case D3DFMT_A16B16G16R16F:
-        return 8 * width;
-      case D3DFMT_A32B32G32R32F:
-        return 16 * width;
-      case D3DFMT_DXT1:
-        return 8 * ((width + 3) / 4);
-      case D3DFMT_DXT3:
-      case D3DFMT_DXT5:
-        return 16 * ((width + 3) / 4);
-      default:
-        UNREACHABLE();
-        return 0;
-    }
-}
-
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/renderer9_utils.h b/src/third_party/angle/src/libGLESv2/renderer/renderer9_utils.h
deleted file mode 100644
index bf6cdf1..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/renderer9_utils.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// renderer9_utils.h: Conversion functions and other utility routines 
-// specific to the D3D9 renderer
-
-#ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H
-#define LIBGLESV2_RENDERER_RENDERER9_UTILS_H
-
-#include "libGLESv2/utilities.h"
-
-const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')));
-const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')));
-
-namespace gl_d3d9
-{
-
-D3DCMPFUNC ConvertComparison(GLenum comparison);
-D3DCOLOR ConvertColor(gl::Color color);
-D3DBLEND ConvertBlendFunc(GLenum blend);
-D3DBLENDOP ConvertBlendOp(GLenum blendOp);
-D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
-D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
-D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace);
-D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace);
-DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
-D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy);
-void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy);
-D3DFORMAT ConvertRenderbufferFormat(GLenum format);
-D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples);
-
-}
-
-namespace d3d9_gl
-{
-
-GLuint GetAlphaSize(D3DFORMAT colorFormat);
-GLuint GetStencilSize(D3DFORMAT stencilFormat);
-
-GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
-
-bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format);
-GLenum ConvertBackBufferFormat(D3DFORMAT format);
-GLenum ConvertDepthStencilFormat(D3DFORMAT format);
-GLenum ConvertRenderTargetFormat(D3DFORMAT format);
-GLenum GetEquivalentFormat(D3DFORMAT format);
-
-}
-
-namespace d3d9
-{
-bool IsCompressedFormat(D3DFORMAT format);
-size_t ComputeRowSize(D3DFORMAT format, unsigned int width);
-
-inline bool isDeviceLostError(HRESULT errorCode)
-{
-    switch (errorCode)
-    {
-      case D3DERR_DRIVERINTERNALERROR:
-      case D3DERR_DEVICELOST:
-      case D3DERR_DEVICEHUNG:
-      case D3DERR_DEVICEREMOVED:
-        return true;
-      default:
-        return false;
-    }
-}
-
-}
-
-#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H
diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/Blit.ps b/src/third_party/angle/src/libGLESv2/renderer/shaders/Blit.ps
deleted file mode 100644
index dcb3bd0..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/Blit.ps
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-sampler2D tex : s0;
-
-uniform float4 mode : c0;
-
-// Passthrough Pixel Shader
-// Outputs texture 0 sampled at texcoord 0.
-float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR
-{
-	return tex2D(tex, texcoord.xy);
-};
-
-// Luminance Conversion Pixel Shader
-// Outputs sample(tex0, tc0).rrra.
-// For LA output (pass A) set C0.X = 1, C0.Y = 0.
-// For L output (A = 1) set C0.X = 0, C0.Y = 1.
-float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
-{
-	float4 tmp = tex2D(tex, texcoord.xy);
-	tmp.w = tmp.w * mode.x + mode.y;
-	return tmp.xxxw;
-};
-
-// RGB/A Component Mask Pixel Shader
-// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1.
-// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1.
-// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0.
-float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR
-{
-	float4 tmp = tex2D(tex, texcoord.xy);
-	tmp.xyz = tmp.xyz * mode.x;
-	tmp.w = tmp.w * mode.z + mode.w;
-	return tmp;
-};
diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/Blit.vs b/src/third_party/angle/src/libGLESv2/renderer/shaders/Blit.vs
deleted file mode 100644
index 3a36980..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/Blit.vs
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-struct VS_OUTPUT
-{
-    float4 position : POSITION;
-    float4 texcoord : TEXCOORD0;
-};
-
-uniform float4 halfPixelSize : c0;
-
-// Standard Vertex Shader
-// Input 0 is the homogenous position.
-// Outputs the homogenous position as-is.
-// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right.
-// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0.
-VS_OUTPUT standardvs(in float4 position : POSITION)
-{
-    VS_OUTPUT Out;
-
-    Out.position = position + halfPixelSize;
-    Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
-
-    return Out;
-};
-
-// Flip Y Vertex Shader
-// Input 0 is the homogenous position.
-// Outputs the homogenous position as-is.
-// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right.
-// C0.XY must be the half-pixel width and height. C0.ZW must be 0.
-VS_OUTPUT flipyvs(in float4 position : POSITION)
-{
-    VS_OUTPUT Out;
-
-    Out.position = position + halfPixelSize;
-    Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
-
-    return Out;
-};
diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl b/src/third_party/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl
deleted file mode 100644
index 042ac69..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl
+++ /dev/null
@@ -1,38 +0,0 @@
-void VS_Clear( in float3  inPosition :    POSITION,  in float4  inColor : COLOR,
-              out float4 outPosition : SV_POSITION, out float4 outColor : COLOR)
-{
-    outPosition = float4(inPosition, 1.0f);
-    outColor = inColor;
-}
-
-// Assume we are in SM4+, which has 8 color outputs
-struct PS_OutputMultiple
-{
-	float4 color0 : SV_TARGET0;
-	float4 color1 : SV_TARGET1;
-	float4 color2 : SV_TARGET2;
-	float4 color3 : SV_TARGET3;
-	float4 color4 : SV_TARGET4;
-	float4 color5 : SV_TARGET5;
-	float4 color6 : SV_TARGET6;
-	float4 color7 : SV_TARGET7;
-};
-
-PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
-{
-	PS_OutputMultiple outColor;
-	outColor.color0 = inColor;
-	outColor.color1 = inColor;
-	outColor.color2 = inColor;
-	outColor.color3 = inColor;
-	outColor.color4 = inColor;
-	outColor.color5 = inColor;
-	outColor.color6 = inColor;
-	outColor.color7 = inColor;
-	return outColor;
-}
-
-float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0
-{
-	return inColor;
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl b/src/third_party/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl
deleted file mode 100644
index 43b7801..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl
+++ /dev/null
@@ -1,29 +0,0 @@
-Texture2D Texture : register(t0);
-SamplerState Sampler : register(s0);
-
-void VS_Passthrough( in float2  inPosition :    POSITION,  in float2  inTexCoord : TEXCOORD0,
-                    out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0)
-{
-    outPosition = float4(inPosition, 0.0f, 1.0f);
-    outTexCoord = inTexCoord;
-}
-
-float4 PS_PassthroughRGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
-{
-    return Texture.Sample(Sampler, inTexCoord).rgba;
-}
-
-float4 PS_PassthroughRGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
-{
-    return float4(Texture.Sample(Sampler, inTexCoord).rgb, 1.0f);
-}
-
-float4 PS_PassthroughLum(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
-{
-    return float4(Texture.Sample(Sampler, inTexCoord).rrr, 1.0f);
-}
-
-float4 PS_PassthroughLumAlpha(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
-{
-    return Texture.Sample(Sampler, inTexCoord).rrra;
-}
diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/clear11vs.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/clear11vs.h
deleted file mode 100644
index 9f9c701..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/clear11vs.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//

-//   fxc /E VS_Clear /T vs_4_0 /Fh compiled/clear11vs.h Clear11.hlsl

-//

-//

-//

-// Input signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// POSITION                 0   xyz         0     NONE  float   xyz 

-// COLOR                    0   xyzw        1     NONE  float   xyzw

-//

-//

-// Output signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_POSITION              0   xyzw        0      POS  float   xyzw

-// COLOR                    0   xyzw        1     NONE  float   xyzw

-//

-vs_4_0

-dcl_input v0.xyz

-dcl_input v1.xyzw

-dcl_output_siv o0.xyzw, position

-dcl_output o1.xyzw

-mov o0.xyz, v0.xyzx

-mov o0.w, l(1.000000)

-mov o1.xyzw, v1.xyzw

-ret 

-// Approximately 4 instruction slots used

-#endif

-

-const BYTE g_VS_Clear[] =

-{

-     68,  88,  66,  67, 109, 138, 

-    105,  83,  86, 190,  83, 125, 

-     72, 102, 194, 136,  46,  69, 

-     17, 121,   1,   0,   0,   0, 

-     48,   2,   0,   0,   5,   0, 

-      0,   0,  52,   0,   0,   0, 

-    140,   0,   0,   0, 220,   0, 

-      0,   0,  48,   1,   0,   0, 

-    180,   1,   0,   0,  82,  68, 

-     69,  70,  80,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-     28,   0,   0,   0,   0,   4, 

-    254, 255,   0,   1,   0,   0, 

-     28,   0,   0,   0,  77, 105, 

-     99, 114, 111, 115, 111, 102, 

-    116,  32,  40,  82,  41,  32, 

-     72,  76,  83,  76,  32,  83, 

-    104,  97, 100, 101, 114,  32, 

-     67, 111, 109, 112, 105, 108, 

-    101, 114,  32,  57,  46,  50, 

-     57,  46,  57,  53,  50,  46, 

-     51,  49,  49,  49,   0, 171, 

-    171, 171,  73,  83,  71,  78, 

-     72,   0,   0,   0,   2,   0, 

-      0,   0,   8,   0,   0,   0, 

-     56,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,   7,   7,   0,   0, 

-     65,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   1,   0, 

-      0,   0,  15,  15,   0,   0, 

-     80,  79,  83,  73,  84,  73, 

-     79,  78,   0,  67,  79,  76, 

-     79,  82,   0, 171,  79,  83, 

-     71,  78,  76,   0,   0,   0, 

-      2,   0,   0,   0,   8,   0, 

-      0,   0,  56,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   3,   0,   0,   0, 

-      0,   0,   0,   0,  15,   0, 

-      0,   0,  68,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   3,   0,   0,   0, 

-      1,   0,   0,   0,  15,   0, 

-      0,   0,  83,  86,  95,  80, 

-     79,  83,  73,  84,  73,  79, 

-     78,   0,  67,  79,  76,  79, 

-     82,   0, 171, 171,  83,  72, 

-     68,  82, 124,   0,   0,   0, 

-     64,   0,   1,   0,  31,   0, 

-      0,   0,  95,   0,   0,   3, 

-    114,  16,  16,   0,   0,   0, 

-      0,   0,  95,   0,   0,   3, 

-    242,  16,  16,   0,   1,   0, 

-      0,   0, 103,   0,   0,   4, 

-    242,  32,  16,   0,   0,   0, 

-      0,   0,   1,   0,   0,   0, 

-    101,   0,   0,   3, 242,  32, 

-     16,   0,   1,   0,   0,   0, 

-     54,   0,   0,   5, 114,  32, 

-     16,   0,   0,   0,   0,   0, 

-     70,  18,  16,   0,   0,   0, 

-      0,   0,  54,   0,   0,   5, 

-    130,  32,  16,   0,   0,   0, 

-      0,   0,   1,  64,   0,   0, 

-      0,   0, 128,  63,  54,   0, 

-      0,   5, 242,  32,  16,   0, 

-      1,   0,   0,   0,  70,  30, 

-     16,   0,   1,   0,   0,   0, 

-     62,   0,   0,   1,  83,  84, 

-     65,  84, 116,   0,   0,   0, 

-      4,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      4,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   3,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h
deleted file mode 100644
index c70eebb..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h
+++ /dev/null
@@ -1,199 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//

-//   fxc /E PS_ClearMultiple /T ps_4_0 /Fh compiled/clearmultiple11ps.h

-//    Clear11.hlsl

-//

-//

-//

-// Input signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_POSITION              0   xyzw        0      POS  float       

-// COLOR                    0   xyzw        1     NONE  float   xyzw

-//

-//

-// Output signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_TARGET                0   xyzw        0   TARGET  float   xyzw

-// SV_TARGET                1   xyzw        1   TARGET  float   xyzw

-// SV_TARGET                2   xyzw        2   TARGET  float   xyzw

-// SV_TARGET                3   xyzw        3   TARGET  float   xyzw

-// SV_TARGET                4   xyzw        4   TARGET  float   xyzw

-// SV_TARGET                5   xyzw        5   TARGET  float   xyzw

-// SV_TARGET                6   xyzw        6   TARGET  float   xyzw

-// SV_TARGET                7   xyzw        7   TARGET  float   xyzw

-//

-ps_4_0

-dcl_input_ps linear v1.xyzw

-dcl_output o0.xyzw

-dcl_output o1.xyzw

-dcl_output o2.xyzw

-dcl_output o3.xyzw

-dcl_output o4.xyzw

-dcl_output o5.xyzw

-dcl_output o6.xyzw

-dcl_output o7.xyzw

-mov o0.xyzw, v1.xyzw

-mov o1.xyzw, v1.xyzw

-mov o2.xyzw, v1.xyzw

-mov o3.xyzw, v1.xyzw

-mov o4.xyzw, v1.xyzw

-mov o5.xyzw, v1.xyzw

-mov o6.xyzw, v1.xyzw

-mov o7.xyzw, v1.xyzw

-ret 

-// Approximately 9 instruction slots used

-#endif

-

-const BYTE g_PS_ClearMultiple[] =

-{

-     68,  88,  66,  67, 146, 246, 

-    236, 240,  50,  40,  87,  55, 

-     73, 140, 251, 200,   8,  22, 

-    173, 117,   1,   0,   0,   0, 

-     88,   3,   0,   0,   5,   0, 

-      0,   0,  52,   0,   0,   0, 

-    140,   0,   0,   0, 224,   0, 

-      0,   0, 188,   1,   0,   0, 

-    220,   2,   0,   0,  82,  68, 

-     69,  70,  80,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-     28,   0,   0,   0,   0,   4, 

-    255, 255,   0,   1,   0,   0, 

-     28,   0,   0,   0,  77, 105, 

-     99, 114, 111, 115, 111, 102, 

-    116,  32,  40,  82,  41,  32, 

-     72,  76,  83,  76,  32,  83, 

-    104,  97, 100, 101, 114,  32, 

-     67, 111, 109, 112, 105, 108, 

-    101, 114,  32,  57,  46,  50, 

-     57,  46,  57,  53,  50,  46, 

-     51,  49,  49,  49,   0, 171, 

-    171, 171,  73,  83,  71,  78, 

-     76,   0,   0,   0,   2,   0, 

-      0,   0,   8,   0,   0,   0, 

-     56,   0,   0,   0,   0,   0, 

-      0,   0,   1,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,  15,   0,   0,   0, 

-     68,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   1,   0, 

-      0,   0,  15,  15,   0,   0, 

-     83,  86,  95,  80,  79,  83, 

-     73,  84,  73,  79,  78,   0, 

-     67,  79,  76,  79,  82,   0, 

-    171, 171,  79,  83,  71,  78, 

-    212,   0,   0,   0,   8,   0, 

-      0,   0,   8,   0,   0,   0, 

-    200,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,  15,   0,   0,   0, 

-    200,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   1,   0, 

-      0,   0,  15,   0,   0,   0, 

-    200,   0,   0,   0,   2,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   2,   0, 

-      0,   0,  15,   0,   0,   0, 

-    200,   0,   0,   0,   3,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   3,   0, 

-      0,   0,  15,   0,   0,   0, 

-    200,   0,   0,   0,   4,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   4,   0, 

-      0,   0,  15,   0,   0,   0, 

-    200,   0,   0,   0,   5,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   5,   0, 

-      0,   0,  15,   0,   0,   0, 

-    200,   0,   0,   0,   6,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   6,   0, 

-      0,   0,  15,   0,   0,   0, 

-    200,   0,   0,   0,   7,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   7,   0, 

-      0,   0,  15,   0,   0,   0, 

-     83,  86,  95,  84,  65,  82, 

-     71,  69,  84,   0, 171, 171, 

-     83,  72,  68,  82,  24,   1, 

-      0,   0,  64,   0,   0,   0, 

-     70,   0,   0,   0,  98,  16, 

-      0,   3, 242,  16,  16,   0, 

-      1,   0,   0,   0, 101,   0, 

-      0,   3, 242,  32,  16,   0, 

-      0,   0,   0,   0, 101,   0, 

-      0,   3, 242,  32,  16,   0, 

-      1,   0,   0,   0, 101,   0, 

-      0,   3, 242,  32,  16,   0, 

-      2,   0,   0,   0, 101,   0, 

-      0,   3, 242,  32,  16,   0, 

-      3,   0,   0,   0, 101,   0, 

-      0,   3, 242,  32,  16,   0, 

-      4,   0,   0,   0, 101,   0, 

-      0,   3, 242,  32,  16,   0, 

-      5,   0,   0,   0, 101,   0, 

-      0,   3, 242,  32,  16,   0, 

-      6,   0,   0,   0, 101,   0, 

-      0,   3, 242,  32,  16,   0, 

-      7,   0,   0,   0,  54,   0, 

-      0,   5, 242,  32,  16,   0, 

-      0,   0,   0,   0,  70,  30, 

-     16,   0,   1,   0,   0,   0, 

-     54,   0,   0,   5, 242,  32, 

-     16,   0,   1,   0,   0,   0, 

-     70,  30,  16,   0,   1,   0, 

-      0,   0,  54,   0,   0,   5, 

-    242,  32,  16,   0,   2,   0, 

-      0,   0,  70,  30,  16,   0, 

-      1,   0,   0,   0,  54,   0, 

-      0,   5, 242,  32,  16,   0, 

-      3,   0,   0,   0,  70,  30, 

-     16,   0,   1,   0,   0,   0, 

-     54,   0,   0,   5, 242,  32, 

-     16,   0,   4,   0,   0,   0, 

-     70,  30,  16,   0,   1,   0, 

-      0,   0,  54,   0,   0,   5, 

-    242,  32,  16,   0,   5,   0, 

-      0,   0,  70,  30,  16,   0, 

-      1,   0,   0,   0,  54,   0, 

-      0,   5, 242,  32,  16,   0, 

-      6,   0,   0,   0,  70,  30, 

-     16,   0,   1,   0,   0,   0, 

-     54,   0,   0,   5, 242,  32, 

-     16,   0,   7,   0,   0,   0, 

-     70,  30,  16,   0,   1,   0, 

-      0,   0,  62,   0,   0,   1, 

-     83,  84,  65,  84, 116,   0, 

-      0,   0,   9,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   9,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      8,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h
deleted file mode 100644
index 20395e2..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h
+++ /dev/null
@@ -1,113 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//

-//   fxc /E PS_ClearSingle /T ps_4_0 /Fh compiled/clearsingle11ps.h

-//    Clear11.hlsl

-//

-//

-//

-// Input signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_Position              0   xyzw        0      POS  float       

-// COLOR                    0   xyzw        1     NONE  float   xyzw

-//

-//

-// Output signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_Target                0   xyzw        0   TARGET  float   xyzw

-//

-ps_4_0

-dcl_input_ps linear v1.xyzw

-dcl_output o0.xyzw

-mov o0.xyzw, v1.xyzw

-ret 

-// Approximately 2 instruction slots used

-#endif

-

-const BYTE g_PS_ClearSingle[] =

-{

-     68,  88,  66,  67,  11,  49, 

-    220, 157,  35, 106, 175, 161, 

-    180, 178, 147, 150, 134, 162, 

-    222,  79,   1,   0,   0,   0, 

-    208,   1,   0,   0,   5,   0, 

-      0,   0,  52,   0,   0,   0, 

-    140,   0,   0,   0, 224,   0, 

-      0,   0,  20,   1,   0,   0, 

-     84,   1,   0,   0,  82,  68, 

-     69,  70,  80,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-     28,   0,   0,   0,   0,   4, 

-    255, 255,   0,   1,   0,   0, 

-     28,   0,   0,   0,  77, 105, 

-     99, 114, 111, 115, 111, 102, 

-    116,  32,  40,  82,  41,  32, 

-     72,  76,  83,  76,  32,  83, 

-    104,  97, 100, 101, 114,  32, 

-     67, 111, 109, 112, 105, 108, 

-    101, 114,  32,  57,  46,  50, 

-     57,  46,  57,  53,  50,  46, 

-     51,  49,  49,  49,   0, 171, 

-    171, 171,  73,  83,  71,  78, 

-     76,   0,   0,   0,   2,   0, 

-      0,   0,   8,   0,   0,   0, 

-     56,   0,   0,   0,   0,   0, 

-      0,   0,   1,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,  15,   0,   0,   0, 

-     68,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   1,   0, 

-      0,   0,  15,  15,   0,   0, 

-     83,  86,  95,  80, 111, 115, 

-    105, 116, 105, 111, 110,   0, 

-     67,  79,  76,  79,  82,   0, 

-    171, 171,  79,  83,  71,  78, 

-     44,   0,   0,   0,   1,   0, 

-      0,   0,   8,   0,   0,   0, 

-     32,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,  15,   0,   0,   0, 

-     83,  86,  95,  84,  97, 114, 

-    103, 101, 116,   0, 171, 171, 

-     83,  72,  68,  82,  56,   0, 

-      0,   0,  64,   0,   0,   0, 

-     14,   0,   0,   0,  98,  16, 

-      0,   3, 242,  16,  16,   0, 

-      1,   0,   0,   0, 101,   0, 

-      0,   3, 242,  32,  16,   0, 

-      0,   0,   0,   0,  54,   0, 

-      0,   5, 242,  32,  16,   0, 

-      0,   0,   0,   0,  70,  30, 

-     16,   0,   1,   0,   0,   0, 

-     62,   0,   0,   1,  83,  84, 

-     65,  84, 116,   0,   0,   0, 

-      2,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      2,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/componentmaskps.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/componentmaskps.h
deleted file mode 100644
index 2b8f04b..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/componentmaskps.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//   fxc /E componentmaskps /T ps_2_0 /Fh compiled/componentmaskps.h Blit.ps

-//

-//

-// Parameters:

-//

-//   float4 mode;

-//   sampler2D tex;

-//

-//

-// Registers:

-//

-//   Name         Reg   Size

-//   ------------ ----- ----

-//   mode         c0       1

-//   tex          s0       1

-//

-

-    ps_2_0

-    dcl t0.xy

-    dcl_2d s0

-    texld r0, t0, s0

-    mul r1.xyz, r0, c0.x

-    mad r1.w, r0.w, c0.z, c0.w

-    mov oC0, r1

-

-// approximately 4 instruction slots used (1 texture, 3 arithmetic)

-#endif

-

-const BYTE g_ps20_componentmaskps[] =

-{

-      0,   2, 255, 255, 254, 255, 

-     43,   0,  67,  84,  65,  66, 

-     28,   0,   0,   0, 119,   0, 

-      0,   0,   0,   2, 255, 255, 

-      2,   0,   0,   0,  28,   0, 

-      0,   0,   0,   1,   0,   0, 

-    112,   0,   0,   0,  68,   0, 

-      0,   0,   2,   0,   0,   0, 

-      1,   0,   0,   0,  76,   0, 

-      0,   0,   0,   0,   0,   0, 

-     92,   0,   0,   0,   3,   0, 

-      0,   0,   1,   0,   0,   0, 

-     96,   0,   0,   0,   0,   0, 

-      0,   0, 109, 111, 100, 101, 

-      0, 171, 171, 171,   1,   0, 

-      3,   0,   1,   0,   4,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0, 116, 101, 120,   0, 

-      4,   0,  12,   0,   1,   0, 

-      1,   0,   1,   0,   0,   0, 

-      0,   0,   0,   0, 112, 115, 

-     95,  50,  95,  48,   0,  77, 

-    105,  99, 114, 111, 115, 111, 

-    102, 116,  32,  40,  82,  41, 

-     32,  72,  76,  83,  76,  32, 

-     83, 104,  97, 100, 101, 114, 

-     32,  67, 111, 109, 112, 105, 

-    108, 101, 114,  32,  57,  46, 

-     50,  57,  46,  57,  53,  50, 

-     46,  51,  49,  49,  49,   0, 

-     31,   0,   0,   2,   0,   0, 

-      0, 128,   0,   0,   3, 176, 

-     31,   0,   0,   2,   0,   0, 

-      0, 144,   0,   8,  15, 160, 

-     66,   0,   0,   3,   0,   0, 

-     15, 128,   0,   0, 228, 176, 

-      0,   8, 228, 160,   5,   0, 

-      0,   3,   1,   0,   7, 128, 

-      0,   0, 228, 128,   0,   0, 

-      0, 160,   4,   0,   0,   4, 

-      1,   0,   8, 128,   0,   0, 

-    255, 128,   0,   0, 170, 160, 

-      0,   0, 255, 160,   1,   0, 

-      0,   2,   0,   8,  15, 128, 

-      1,   0, 228, 128, 255, 255, 

-      0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/flipyvs.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/flipyvs.h
deleted file mode 100644
index ef12101..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/flipyvs.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//   fxc /E flipyvs /T vs_2_0 /Fh compiled/flipyvs.h Blit.vs

-//

-//

-// Parameters:

-//

-//   float4 halfPixelSize;

-//

-//

-// Registers:

-//

-//   Name          Reg   Size

-//   ------------- ----- ----

-//   halfPixelSize c0       1

-//

-

-    vs_2_0

-    def c1, 0.5, 1, 0, 0

-    dcl_position v0

-    add oPos, v0, c0

-    mad oT0, v0, c1.xxyy, c1.xxzz

-

-// approximately 2 instruction slots used

-#endif

-

-const BYTE g_vs20_flipyvs[] =

-{

-      0,   2, 254, 255, 254, 255, 

-     35,   0,  67,  84,  65,  66, 

-     28,   0,   0,   0,  87,   0, 

-      0,   0,   0,   2, 254, 255, 

-      1,   0,   0,   0,  28,   0, 

-      0,   0,   0,   1,   0,   0, 

-     80,   0,   0,   0,  48,   0, 

-      0,   0,   2,   0,   0,   0, 

-      1,   0,   0,   0,  64,   0, 

-      0,   0,   0,   0,   0,   0, 

-    104,  97, 108, 102,  80, 105, 

-    120, 101, 108,  83, 105, 122, 

-    101,   0, 171, 171,   1,   0, 

-      3,   0,   1,   0,   4,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0, 118, 115,  95,  50, 

-     95,  48,   0,  77, 105,  99, 

-    114, 111, 115, 111, 102, 116, 

-     32,  40,  82,  41,  32,  72, 

-     76,  83,  76,  32,  83, 104, 

-     97, 100, 101, 114,  32,  67, 

-    111, 109, 112, 105, 108, 101, 

-    114,  32,  57,  46,  50,  57, 

-     46,  57,  53,  50,  46,  51, 

-     49,  49,  49,   0,  81,   0, 

-      0,   5,   1,   0,  15, 160, 

-      0,   0,   0,  63,   0,   0, 

-    128,  63,   0,   0,   0,   0, 

-      0,   0,   0,   0,  31,   0, 

-      0,   2,   0,   0,   0, 128, 

-      0,   0,  15, 144,   2,   0, 

-      0,   3,   0,   0,  15, 192, 

-      0,   0, 228, 144,   0,   0, 

-    228, 160,   4,   0,   0,   4, 

-      0,   0,  15, 224,   0,   0, 

-    228, 144,   1,   0,  80, 160, 

-      1,   0, 160, 160, 255, 255, 

-      0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/luminanceps.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/luminanceps.h
deleted file mode 100644
index 44dc749..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/luminanceps.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//   fxc /E luminanceps /T ps_2_0 /Fh compiled/luminanceps.h Blit.ps

-//

-//

-// Parameters:

-//

-//   float4 mode;

-//   sampler2D tex;

-//

-//

-// Registers:

-//

-//   Name         Reg   Size

-//   ------------ ----- ----

-//   mode         c0       1

-//   tex          s0       1

-//

-

-    ps_2_0

-    dcl t0.xy

-    dcl_2d s0

-    texld r0, t0, s0

-    mad r1.w, r0.w, c0.x, c0.y

-    mov r1.xyz, r0.x

-    mov oC0, r1

-

-// approximately 4 instruction slots used (1 texture, 3 arithmetic)

-#endif

-

-const BYTE g_ps20_luminanceps[] =

-{

-      0,   2, 255, 255, 254, 255, 

-     43,   0,  67,  84,  65,  66, 

-     28,   0,   0,   0, 119,   0, 

-      0,   0,   0,   2, 255, 255, 

-      2,   0,   0,   0,  28,   0, 

-      0,   0,   0,   1,   0,   0, 

-    112,   0,   0,   0,  68,   0, 

-      0,   0,   2,   0,   0,   0, 

-      1,   0,   0,   0,  76,   0, 

-      0,   0,   0,   0,   0,   0, 

-     92,   0,   0,   0,   3,   0, 

-      0,   0,   1,   0,   0,   0, 

-     96,   0,   0,   0,   0,   0, 

-      0,   0, 109, 111, 100, 101, 

-      0, 171, 171, 171,   1,   0, 

-      3,   0,   1,   0,   4,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0, 116, 101, 120,   0, 

-      4,   0,  12,   0,   1,   0, 

-      1,   0,   1,   0,   0,   0, 

-      0,   0,   0,   0, 112, 115, 

-     95,  50,  95,  48,   0,  77, 

-    105,  99, 114, 111, 115, 111, 

-    102, 116,  32,  40,  82,  41, 

-     32,  72,  76,  83,  76,  32, 

-     83, 104,  97, 100, 101, 114, 

-     32,  67, 111, 109, 112, 105, 

-    108, 101, 114,  32,  57,  46, 

-     50,  57,  46,  57,  53,  50, 

-     46,  51,  49,  49,  49,   0, 

-     31,   0,   0,   2,   0,   0, 

-      0, 128,   0,   0,   3, 176, 

-     31,   0,   0,   2,   0,   0, 

-      0, 144,   0,   8,  15, 160, 

-     66,   0,   0,   3,   0,   0, 

-     15, 128,   0,   0, 228, 176, 

-      0,   8, 228, 160,   4,   0, 

-      0,   4,   1,   0,   8, 128, 

-      0,   0, 255, 128,   0,   0, 

-      0, 160,   0,   0,  85, 160, 

-      1,   0,   0,   2,   1,   0, 

-      7, 128,   0,   0,   0, 128, 

-      1,   0,   0,   2,   0,   8, 

-     15, 128,   1,   0, 228, 128, 

-    255, 255,   0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthrough11vs.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthrough11vs.h
deleted file mode 100644
index b12fff9..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthrough11vs.h
+++ /dev/null
@@ -1,137 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//

-//   fxc /E VS_Passthrough /T vs_4_0 /Fh compiled/passthrough11vs.h

-//    Passthrough11.hlsl

-//

-//

-//

-// Input signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// POSITION                 0   xy          0     NONE  float   xy  

-// TEXCOORD                 0   xy          1     NONE  float   xy  

-//

-//

-// Output signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_POSITION              0   xyzw        0      POS  float   xyzw

-// TEXCOORD                 0   xy          1     NONE  float   xy  

-//

-vs_4_0

-dcl_input v0.xy

-dcl_input v1.xy

-dcl_output_siv o0.xyzw, position

-dcl_output o1.xy

-mov o0.xy, v0.xyxx

-mov o0.zw, l(0,0,0,1.000000)

-mov o1.xy, v1.xyxx

-ret 

-// Approximately 4 instruction slots used

-#endif

-

-const BYTE g_VS_Passthrough[] =

-{

-     68,  88,  66,  67, 117,  74, 

-     34,  79, 174, 226, 170,  74, 

-    110,  16, 237,  14,  67, 185, 

-    119, 167,   1,   0,   0,   0, 

-     68,   2,   0,   0,   5,   0, 

-      0,   0,  52,   0,   0,   0, 

-    140,   0,   0,   0, 224,   0, 

-      0,   0,  56,   1,   0,   0, 

-    200,   1,   0,   0,  82,  68, 

-     69,  70,  80,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-     28,   0,   0,   0,   0,   4, 

-    254, 255,   0,   1,   0,   0, 

-     28,   0,   0,   0,  77, 105, 

-     99, 114, 111, 115, 111, 102, 

-    116,  32,  40,  82,  41,  32, 

-     72,  76,  83,  76,  32,  83, 

-    104,  97, 100, 101, 114,  32, 

-     67, 111, 109, 112, 105, 108, 

-    101, 114,  32,  57,  46,  50, 

-     57,  46,  57,  53,  50,  46, 

-     51,  49,  49,  49,   0, 171, 

-    171, 171,  73,  83,  71,  78, 

-     76,   0,   0,   0,   2,   0, 

-      0,   0,   8,   0,   0,   0, 

-     56,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,   3,   3,   0,   0, 

-     65,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   1,   0, 

-      0,   0,   3,   3,   0,   0, 

-     80,  79,  83,  73,  84,  73, 

-     79,  78,   0,  84,  69,  88, 

-     67,  79,  79,  82,  68,   0, 

-    171, 171,  79,  83,  71,  78, 

-     80,   0,   0,   0,   2,   0, 

-      0,   0,   8,   0,   0,   0, 

-     56,   0,   0,   0,   0,   0, 

-      0,   0,   1,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,  15,   0,   0,   0, 

-     68,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   1,   0, 

-      0,   0,   3,  12,   0,   0, 

-     83,  86,  95,  80,  79,  83, 

-     73,  84,  73,  79,  78,   0, 

-     84,  69,  88,  67,  79,  79, 

-     82,  68,   0, 171, 171, 171, 

-     83,  72,  68,  82, 136,   0, 

-      0,   0,  64,   0,   1,   0, 

-     34,   0,   0,   0,  95,   0, 

-      0,   3,  50,  16,  16,   0, 

-      0,   0,   0,   0,  95,   0, 

-      0,   3,  50,  16,  16,   0, 

-      1,   0,   0,   0, 103,   0, 

-      0,   4, 242,  32,  16,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0, 101,   0,   0,   3, 

-     50,  32,  16,   0,   1,   0, 

-      0,   0,  54,   0,   0,   5, 

-     50,  32,  16,   0,   0,   0, 

-      0,   0,  70,  16,  16,   0, 

-      0,   0,   0,   0,  54,   0, 

-      0,   8, 194,  32,  16,   0, 

-      0,   0,   0,   0,   2,  64, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0, 128,  63, 

-     54,   0,   0,   5,  50,  32, 

-     16,   0,   1,   0,   0,   0, 

-     70,  16,  16,   0,   1,   0, 

-      0,   0,  62,   0,   0,   1, 

-     83,  84,  65,  84, 116,   0, 

-      0,   0,   4,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   4,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h
deleted file mode 100644
index 0d5c8eb..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//

-//   fxc /E PS_PassthroughLum /T ps_4_0 /Fh compiled/passthroughlum11ps.h

-//    Passthrough11.hlsl

-//

-//

-// Resource Bindings:

-//

-// Name                                 Type  Format         Dim Slot Elements

-// ------------------------------ ---------- ------- ----------- ---- --------

-// Sampler                           sampler      NA          NA    0        1

-// Texture                           texture  float4          2d    0        1

-//

-//

-//

-// Input signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_POSITION              0   xyzw        0      POS  float       

-// TEXCOORD                 0   xy          1     NONE  float   xy  

-//

-//

-// Output signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_TARGET                0   xyzw        0   TARGET  float   xyzw

-//

-ps_4_0

-dcl_sampler s0, mode_default

-dcl_resource_texture2d (float,float,float,float) t0

-dcl_input_ps linear v1.xy

-dcl_output o0.xyzw

-dcl_temps 1

-sample r0.xyzw, v1.xyxx, t0.xyzw, s0

-mov o0.xyz, r0.xxxx

-mov o0.w, l(1.000000)

-ret 

-// Approximately 4 instruction slots used

-#endif

-

-const BYTE g_PS_PassthroughLum[] =

-{

-     68,  88,  66,  67,  97,  41, 

-     37, 154,   0, 174, 137, 157, 

-     76, 219, 230,  26, 227, 174, 

-    187,  66,   1,   0,   0,   0, 

-    128,   2,   0,   0,   5,   0, 

-      0,   0,  52,   0,   0,   0, 

-    220,   0,   0,   0,  52,   1, 

-      0,   0, 104,   1,   0,   0, 

-      4,   2,   0,   0,  82,  68, 

-     69,  70, 160,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   2,   0,   0,   0, 

-     28,   0,   0,   0,   0,   4, 

-    255, 255,   0,   1,   0,   0, 

-    108,   0,   0,   0,  92,   0, 

-      0,   0,   3,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   1,   0,   0,   0, 

-    100,   0,   0,   0,   2,   0, 

-      0,   0,   5,   0,   0,   0, 

-      4,   0,   0,   0, 255, 255, 

-    255, 255,   0,   0,   0,   0, 

-      1,   0,   0,   0,  13,   0, 

-      0,   0,  83,  97, 109, 112, 

-    108, 101, 114,   0,  84, 101, 

-    120, 116, 117, 114, 101,   0, 

-     77, 105,  99, 114, 111, 115, 

-    111, 102, 116,  32,  40,  82, 

-     41,  32,  72,  76,  83,  76, 

-     32,  83, 104,  97, 100, 101, 

-    114,  32,  67, 111, 109, 112, 

-    105, 108, 101, 114,  32,  57, 

-     46,  50,  57,  46,  57,  53, 

-     50,  46,  51,  49,  49,  49, 

-      0, 171, 171, 171,  73,  83, 

-     71,  78,  80,   0,   0,   0, 

-      2,   0,   0,   0,   8,   0, 

-      0,   0,  56,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   3,   0,   0,   0, 

-      0,   0,   0,   0,  15,   0, 

-      0,   0,  68,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   3,   0,   0,   0, 

-      1,   0,   0,   0,   3,   3, 

-      0,   0,  83,  86,  95,  80, 

-     79,  83,  73,  84,  73,  79, 

-     78,   0,  84,  69,  88,  67, 

-     79,  79,  82,  68,   0, 171, 

-    171, 171,  79,  83,  71,  78, 

-     44,   0,   0,   0,   1,   0, 

-      0,   0,   8,   0,   0,   0, 

-     32,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,  15,   0,   0,   0, 

-     83,  86,  95,  84,  65,  82, 

-     71,  69,  84,   0, 171, 171, 

-     83,  72,  68,  82, 148,   0, 

-      0,   0,  64,   0,   0,   0, 

-     37,   0,   0,   0,  90,   0, 

-      0,   3,   0,  96,  16,   0, 

-      0,   0,   0,   0,  88,  24, 

-      0,   4,   0, 112,  16,   0, 

-      0,   0,   0,   0,  85,  85, 

-      0,   0,  98,  16,   0,   3, 

-     50,  16,  16,   0,   1,   0, 

-      0,   0, 101,   0,   0,   3, 

-    242,  32,  16,   0,   0,   0, 

-      0,   0, 104,   0,   0,   2, 

-      1,   0,   0,   0,  69,   0, 

-      0,   9, 242,   0,  16,   0, 

-      0,   0,   0,   0,  70,  16, 

-     16,   0,   1,   0,   0,   0, 

-     70, 126,  16,   0,   0,   0, 

-      0,   0,   0,  96,  16,   0, 

-      0,   0,   0,   0,  54,   0, 

-      0,   5, 114,  32,  16,   0, 

-      0,   0,   0,   0,   6,   0, 

-     16,   0,   0,   0,   0,   0, 

-     54,   0,   0,   5, 130,  32, 

-     16,   0,   0,   0,   0,   0, 

-      1,  64,   0,   0,   0,   0, 

-    128,  63,  62,   0,   0,   1, 

-     83,  84,  65,  84, 116,   0, 

-      0,   0,   4,   0,   0,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0,   2,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      2,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h
deleted file mode 100644
index 6f9c14d..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h
+++ /dev/null
@@ -1,151 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//

-//   fxc /E PS_PassthroughLumAlpha /T ps_4_0 /Fh

-//    compiled/passthroughlumalpha11ps.h Passthrough11.hlsl

-//

-//

-// Resource Bindings:

-//

-// Name                                 Type  Format         Dim Slot Elements

-// ------------------------------ ---------- ------- ----------- ---- --------

-// Sampler                           sampler      NA          NA    0        1

-// Texture                           texture  float4          2d    0        1

-//

-//

-//

-// Input signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_POSITION              0   xyzw        0      POS  float       

-// TEXCOORD                 0   xy          1     NONE  float   xy  

-//

-//

-// Output signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_TARGET                0   xyzw        0   TARGET  float   xyzw

-//

-ps_4_0

-dcl_sampler s0, mode_default

-dcl_resource_texture2d (float,float,float,float) t0

-dcl_input_ps linear v1.xy

-dcl_output o0.xyzw

-dcl_temps 1

-sample r0.xyzw, v1.xyxx, t0.xyzw, s0

-mov o0.xyzw, r0.xxxw

-ret 

-// Approximately 3 instruction slots used

-#endif

-

-const BYTE g_PS_PassthroughLumAlpha[] =

-{

-     68,  88,  66,  67, 197,  72, 

-    251, 236,  53, 107, 182, 146, 

-    196, 219, 130, 187, 140, 159, 

-    211, 123,   1,   0,   0,   0, 

-    108,   2,   0,   0,   5,   0, 

-      0,   0,  52,   0,   0,   0, 

-    220,   0,   0,   0,  52,   1, 

-      0,   0, 104,   1,   0,   0, 

-    240,   1,   0,   0,  82,  68, 

-     69,  70, 160,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   2,   0,   0,   0, 

-     28,   0,   0,   0,   0,   4, 

-    255, 255,   0,   1,   0,   0, 

-    108,   0,   0,   0,  92,   0, 

-      0,   0,   3,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   1,   0,   0,   0, 

-    100,   0,   0,   0,   2,   0, 

-      0,   0,   5,   0,   0,   0, 

-      4,   0,   0,   0, 255, 255, 

-    255, 255,   0,   0,   0,   0, 

-      1,   0,   0,   0,  13,   0, 

-      0,   0,  83,  97, 109, 112, 

-    108, 101, 114,   0,  84, 101, 

-    120, 116, 117, 114, 101,   0, 

-     77, 105,  99, 114, 111, 115, 

-    111, 102, 116,  32,  40,  82, 

-     41,  32,  72,  76,  83,  76, 

-     32,  83, 104,  97, 100, 101, 

-    114,  32,  67, 111, 109, 112, 

-    105, 108, 101, 114,  32,  57, 

-     46,  50,  57,  46,  57,  53, 

-     50,  46,  51,  49,  49,  49, 

-      0, 171, 171, 171,  73,  83, 

-     71,  78,  80,   0,   0,   0, 

-      2,   0,   0,   0,   8,   0, 

-      0,   0,  56,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   3,   0,   0,   0, 

-      0,   0,   0,   0,  15,   0, 

-      0,   0,  68,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   3,   0,   0,   0, 

-      1,   0,   0,   0,   3,   3, 

-      0,   0,  83,  86,  95,  80, 

-     79,  83,  73,  84,  73,  79, 

-     78,   0,  84,  69,  88,  67, 

-     79,  79,  82,  68,   0, 171, 

-    171, 171,  79,  83,  71,  78, 

-     44,   0,   0,   0,   1,   0, 

-      0,   0,   8,   0,   0,   0, 

-     32,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,  15,   0,   0,   0, 

-     83,  86,  95,  84,  65,  82, 

-     71,  69,  84,   0, 171, 171, 

-     83,  72,  68,  82, 128,   0, 

-      0,   0,  64,   0,   0,   0, 

-     32,   0,   0,   0,  90,   0, 

-      0,   3,   0,  96,  16,   0, 

-      0,   0,   0,   0,  88,  24, 

-      0,   4,   0, 112,  16,   0, 

-      0,   0,   0,   0,  85,  85, 

-      0,   0,  98,  16,   0,   3, 

-     50,  16,  16,   0,   1,   0, 

-      0,   0, 101,   0,   0,   3, 

-    242,  32,  16,   0,   0,   0, 

-      0,   0, 104,   0,   0,   2, 

-      1,   0,   0,   0,  69,   0, 

-      0,   9, 242,   0,  16,   0, 

-      0,   0,   0,   0,  70,  16, 

-     16,   0,   1,   0,   0,   0, 

-     70, 126,  16,   0,   0,   0, 

-      0,   0,   0,  96,  16,   0, 

-      0,   0,   0,   0,  54,   0, 

-      0,   5, 242,  32,  16,   0, 

-      0,   0,   0,   0,   6,  12, 

-     16,   0,   0,   0,   0,   0, 

-     62,   0,   0,   1,  83,  84, 

-     65,  84, 116,   0,   0,   0, 

-      3,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      2,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   1,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughps.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughps.h
deleted file mode 100644
index f231d44..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughps.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//   fxc /E passthroughps /T ps_2_0 /Fh compiled/passthroughps.h Blit.ps

-//

-//

-// Parameters:

-//

-//   sampler2D tex;

-//

-//

-// Registers:

-//

-//   Name         Reg   Size

-//   ------------ ----- ----

-//   tex          s0       1

-//

-

-    ps_2_0

-    dcl t0.xy

-    dcl_2d s0

-    texld r0, t0, s0

-    mov oC0, r0

-

-// approximately 2 instruction slots used (1 texture, 1 arithmetic)

-#endif

-

-const BYTE g_ps20_passthroughps[] =

-{

-      0,   2, 255, 255, 254, 255, 

-     32,   0,  67,  84,  65,  66, 

-     28,   0,   0,   0,  75,   0, 

-      0,   0,   0,   2, 255, 255, 

-      1,   0,   0,   0,  28,   0, 

-      0,   0,   0,   1,   0,   0, 

-     68,   0,   0,   0,  48,   0, 

-      0,   0,   3,   0,   0,   0, 

-      1,   0,   0,   0,  52,   0, 

-      0,   0,   0,   0,   0,   0, 

-    116, 101, 120,   0,   4,   0, 

-     12,   0,   1,   0,   1,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0, 112, 115,  95,  50, 

-     95,  48,   0,  77, 105,  99, 

-    114, 111, 115, 111, 102, 116, 

-     32,  40,  82,  41,  32,  72, 

-     76,  83,  76,  32,  83, 104, 

-     97, 100, 101, 114,  32,  67, 

-    111, 109, 112, 105, 108, 101, 

-    114,  32,  57,  46,  50,  57, 

-     46,  57,  53,  50,  46,  51, 

-     49,  49,  49,   0,  31,   0, 

-      0,   2,   0,   0,   0, 128, 

-      0,   0,   3, 176,  31,   0, 

-      0,   2,   0,   0,   0, 144, 

-      0,   8,  15, 160,  66,   0, 

-      0,   3,   0,   0,  15, 128, 

-      0,   0, 228, 176,   0,   8, 

-    228, 160,   1,   0,   0,   2, 

-      0,   8,  15, 128,   0,   0, 

-    228, 128, 255, 255,   0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h
deleted file mode 100644
index da9ff63..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//

-//   fxc /E PS_PassthroughRGB /T ps_4_0 /Fh compiled/passthroughrgb11ps.h

-//    Passthrough11.hlsl

-//

-//

-// Resource Bindings:

-//

-// Name                                 Type  Format         Dim Slot Elements

-// ------------------------------ ---------- ------- ----------- ---- --------

-// Sampler                           sampler      NA          NA    0        1

-// Texture                           texture  float4          2d    0        1

-//

-//

-//

-// Input signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_POSITION              0   xyzw        0      POS  float       

-// TEXCOORD                 0   xy          1     NONE  float   xy  

-//

-//

-// Output signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_TARGET                0   xyzw        0   TARGET  float   xyzw

-//

-ps_4_0

-dcl_sampler s0, mode_default

-dcl_resource_texture2d (float,float,float,float) t0

-dcl_input_ps linear v1.xy

-dcl_output o0.xyzw

-dcl_temps 1

-sample r0.xyzw, v1.xyxx, t0.xyzw, s0

-mov o0.xyz, r0.xyzx

-mov o0.w, l(1.000000)

-ret 

-// Approximately 4 instruction slots used

-#endif

-

-const BYTE g_PS_PassthroughRGB[] =

-{

-     68,  88,  66,  67, 253,  45, 

-     13,  34, 125, 194,  95, 149, 

-      1,  95, 194, 252, 118, 228, 

-    178, 200,   1,   0,   0,   0, 

-    128,   2,   0,   0,   5,   0, 

-      0,   0,  52,   0,   0,   0, 

-    220,   0,   0,   0,  52,   1, 

-      0,   0, 104,   1,   0,   0, 

-      4,   2,   0,   0,  82,  68, 

-     69,  70, 160,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   2,   0,   0,   0, 

-     28,   0,   0,   0,   0,   4, 

-    255, 255,   0,   1,   0,   0, 

-    108,   0,   0,   0,  92,   0, 

-      0,   0,   3,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   1,   0,   0,   0, 

-    100,   0,   0,   0,   2,   0, 

-      0,   0,   5,   0,   0,   0, 

-      4,   0,   0,   0, 255, 255, 

-    255, 255,   0,   0,   0,   0, 

-      1,   0,   0,   0,  13,   0, 

-      0,   0,  83,  97, 109, 112, 

-    108, 101, 114,   0,  84, 101, 

-    120, 116, 117, 114, 101,   0, 

-     77, 105,  99, 114, 111, 115, 

-    111, 102, 116,  32,  40,  82, 

-     41,  32,  72,  76,  83,  76, 

-     32,  83, 104,  97, 100, 101, 

-    114,  32,  67, 111, 109, 112, 

-    105, 108, 101, 114,  32,  57, 

-     46,  50,  57,  46,  57,  53, 

-     50,  46,  51,  49,  49,  49, 

-      0, 171, 171, 171,  73,  83, 

-     71,  78,  80,   0,   0,   0, 

-      2,   0,   0,   0,   8,   0, 

-      0,   0,  56,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   3,   0,   0,   0, 

-      0,   0,   0,   0,  15,   0, 

-      0,   0,  68,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   3,   0,   0,   0, 

-      1,   0,   0,   0,   3,   3, 

-      0,   0,  83,  86,  95,  80, 

-     79,  83,  73,  84,  73,  79, 

-     78,   0,  84,  69,  88,  67, 

-     79,  79,  82,  68,   0, 171, 

-    171, 171,  79,  83,  71,  78, 

-     44,   0,   0,   0,   1,   0, 

-      0,   0,   8,   0,   0,   0, 

-     32,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,  15,   0,   0,   0, 

-     83,  86,  95,  84,  65,  82, 

-     71,  69,  84,   0, 171, 171, 

-     83,  72,  68,  82, 148,   0, 

-      0,   0,  64,   0,   0,   0, 

-     37,   0,   0,   0,  90,   0, 

-      0,   3,   0,  96,  16,   0, 

-      0,   0,   0,   0,  88,  24, 

-      0,   4,   0, 112,  16,   0, 

-      0,   0,   0,   0,  85,  85, 

-      0,   0,  98,  16,   0,   3, 

-     50,  16,  16,   0,   1,   0, 

-      0,   0, 101,   0,   0,   3, 

-    242,  32,  16,   0,   0,   0, 

-      0,   0, 104,   0,   0,   2, 

-      1,   0,   0,   0,  69,   0, 

-      0,   9, 242,   0,  16,   0, 

-      0,   0,   0,   0,  70,  16, 

-     16,   0,   1,   0,   0,   0, 

-     70, 126,  16,   0,   0,   0, 

-      0,   0,   0,  96,  16,   0, 

-      0,   0,   0,   0,  54,   0, 

-      0,   5, 114,  32,  16,   0, 

-      0,   0,   0,   0,  70,   2, 

-     16,   0,   0,   0,   0,   0, 

-     54,   0,   0,   5, 130,  32, 

-     16,   0,   0,   0,   0,   0, 

-      1,  64,   0,   0,   0,   0, 

-    128,  63,  62,   0,   0,   1, 

-     83,  84,  65,  84, 116,   0, 

-      0,   0,   4,   0,   0,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0,   2,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      2,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h
deleted file mode 100644
index 55f2fef..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h
+++ /dev/null
@@ -1,144 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//

-//   fxc /E PS_PassthroughRGBA /T ps_4_0 /Fh compiled/passthroughrgba11ps.h

-//    Passthrough11.hlsl

-//

-//

-// Resource Bindings:

-//

-// Name                                 Type  Format         Dim Slot Elements

-// ------------------------------ ---------- ------- ----------- ---- --------

-// Sampler                           sampler      NA          NA    0        1

-// Texture                           texture  float4          2d    0        1

-//

-//

-//

-// Input signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_POSITION              0   xyzw        0      POS  float       

-// TEXCOORD                 0   xy          1     NONE  float   xy  

-//

-//

-// Output signature:

-//

-// Name                 Index   Mask Register SysValue Format   Used

-// -------------------- ----- ------ -------- -------- ------ ------

-// SV_TARGET                0   xyzw        0   TARGET  float   xyzw

-//

-ps_4_0

-dcl_sampler s0, mode_default

-dcl_resource_texture2d (float,float,float,float) t0

-dcl_input_ps linear v1.xy

-dcl_output o0.xyzw

-sample o0.xyzw, v1.xyxx, t0.xyzw, s0

-ret 

-// Approximately 2 instruction slots used

-#endif

-

-const BYTE g_PS_PassthroughRGBA[] =

-{

-     68,  88,  66,  67, 152,  86, 

-    225, 107, 155,  83, 216,  13, 

-    154, 212, 144,   5,  82,  74, 

-     90,  98,   1,   0,   0,   0, 

-     80,   2,   0,   0,   5,   0, 

-      0,   0,  52,   0,   0,   0, 

-    220,   0,   0,   0,  52,   1, 

-      0,   0, 104,   1,   0,   0, 

-    212,   1,   0,   0,  82,  68, 

-     69,  70, 160,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   2,   0,   0,   0, 

-     28,   0,   0,   0,   0,   4, 

-    255, 255,   0,   1,   0,   0, 

-    108,   0,   0,   0,  92,   0, 

-      0,   0,   3,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   1,   0,   0,   0, 

-    100,   0,   0,   0,   2,   0, 

-      0,   0,   5,   0,   0,   0, 

-      4,   0,   0,   0, 255, 255, 

-    255, 255,   0,   0,   0,   0, 

-      1,   0,   0,   0,  13,   0, 

-      0,   0,  83,  97, 109, 112, 

-    108, 101, 114,   0,  84, 101, 

-    120, 116, 117, 114, 101,   0, 

-     77, 105,  99, 114, 111, 115, 

-    111, 102, 116,  32,  40,  82, 

-     41,  32,  72,  76,  83,  76, 

-     32,  83, 104,  97, 100, 101, 

-    114,  32,  67, 111, 109, 112, 

-    105, 108, 101, 114,  32,  57, 

-     46,  50,  57,  46,  57,  53, 

-     50,  46,  51,  49,  49,  49, 

-      0, 171, 171, 171,  73,  83, 

-     71,  78,  80,   0,   0,   0, 

-      2,   0,   0,   0,   8,   0, 

-      0,   0,  56,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   3,   0,   0,   0, 

-      0,   0,   0,   0,  15,   0, 

-      0,   0,  68,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   3,   0,   0,   0, 

-      1,   0,   0,   0,   3,   3, 

-      0,   0,  83,  86,  95,  80, 

-     79,  83,  73,  84,  73,  79, 

-     78,   0,  84,  69,  88,  67, 

-     79,  79,  82,  68,   0, 171, 

-    171, 171,  79,  83,  71,  78, 

-     44,   0,   0,   0,   1,   0, 

-      0,   0,   8,   0,   0,   0, 

-     32,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      3,   0,   0,   0,   0,   0, 

-      0,   0,  15,   0,   0,   0, 

-     83,  86,  95,  84,  65,  82, 

-     71,  69,  84,   0, 171, 171, 

-     83,  72,  68,  82, 100,   0, 

-      0,   0,  64,   0,   0,   0, 

-     25,   0,   0,   0,  90,   0, 

-      0,   3,   0,  96,  16,   0, 

-      0,   0,   0,   0,  88,  24, 

-      0,   4,   0, 112,  16,   0, 

-      0,   0,   0,   0,  85,  85, 

-      0,   0,  98,  16,   0,   3, 

-     50,  16,  16,   0,   1,   0, 

-      0,   0, 101,   0,   0,   3, 

-    242,  32,  16,   0,   0,   0, 

-      0,   0,  69,   0,   0,   9, 

-    242,  32,  16,   0,   0,   0, 

-      0,   0,  70,  16,  16,   0, 

-      1,   0,   0,   0,  70, 126, 

-     16,   0,   0,   0,   0,   0, 

-      0,  96,  16,   0,   0,   0, 

-      0,   0,  62,   0,   0,   1, 

-     83,  84,  65,  84, 116,   0, 

-      0,   0,   2,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   2,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   1,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0,   0,   0, 

-      0,   0,   0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/standardvs.h b/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/standardvs.h
deleted file mode 100644
index 8ea892e..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/compiled/standardvs.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#if 0

-//

-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

-//

-//   fxc /E standardvs /T vs_2_0 /Fh compiled/standardvs.h Blit.vs

-//

-//

-// Parameters:

-//

-//   float4 halfPixelSize;

-//

-//

-// Registers:

-//

-//   Name          Reg   Size

-//   ------------- ----- ----

-//   halfPixelSize c0       1

-//

-

-    vs_2_0

-    def c1, 0.5, -0.5, 1, 0

-    dcl_position v0

-    add oPos, v0, c0

-    mad oT0, v0, c1.xyzz, c1.xxww

-

-// approximately 2 instruction slots used

-#endif

-

-const BYTE g_vs20_standardvs[] =

-{

-      0,   2, 254, 255, 254, 255, 

-     35,   0,  67,  84,  65,  66, 

-     28,   0,   0,   0,  87,   0, 

-      0,   0,   0,   2, 254, 255, 

-      1,   0,   0,   0,  28,   0, 

-      0,   0,   0,   1,   0,   0, 

-     80,   0,   0,   0,  48,   0, 

-      0,   0,   2,   0,   0,   0, 

-      1,   0,   0,   0,  64,   0, 

-      0,   0,   0,   0,   0,   0, 

-    104,  97, 108, 102,  80, 105, 

-    120, 101, 108,  83, 105, 122, 

-    101,   0, 171, 171,   1,   0, 

-      3,   0,   1,   0,   4,   0, 

-      1,   0,   0,   0,   0,   0, 

-      0,   0, 118, 115,  95,  50, 

-     95,  48,   0,  77, 105,  99, 

-    114, 111, 115, 111, 102, 116, 

-     32,  40,  82,  41,  32,  72, 

-     76,  83,  76,  32,  83, 104, 

-     97, 100, 101, 114,  32,  67, 

-    111, 109, 112, 105, 108, 101, 

-    114,  32,  57,  46,  50,  57, 

-     46,  57,  53,  50,  46,  51, 

-     49,  49,  49,   0,  81,   0, 

-      0,   5,   1,   0,  15, 160, 

-      0,   0,   0,  63,   0,   0, 

-      0, 191,   0,   0, 128,  63, 

-      0,   0,   0,   0,  31,   0, 

-      0,   2,   0,   0,   0, 128, 

-      0,   0,  15, 144,   2,   0, 

-      0,   3,   0,   0,  15, 192, 

-      0,   0, 228, 144,   0,   0, 

-    228, 160,   4,   0,   0,   4, 

-      0,   0,  15, 224,   0,   0, 

-    228, 144,   1,   0, 164, 160, 

-      1,   0, 240, 160, 255, 255, 

-      0,   0

-};

diff --git a/src/third_party/angle/src/libGLESv2/renderer/shaders/generate_shaders.bat b/src/third_party/angle/src/libGLESv2/renderer/shaders/generate_shaders.bat
deleted file mode 100644
index 04ef136..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/shaders/generate_shaders.bat
+++ /dev/null
@@ -1,24 +0,0 @@
-@ECHO OFF

-REM

-REM Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

-REM Use of this source code is governed by a BSD-style license that can be

-REM found in the LICENSE file.

-REM

-

-PATH %PATH%;%DXSDK_DIR%\Utilities\bin\x86

-

-fxc /E standardvs /T vs_2_0 /Fh compiled/standardvs.h Blit.vs

-fxc /E flipyvs /T vs_2_0 /Fh compiled/flipyvs.h Blit.vs

-fxc /E passthroughps /T ps_2_0 /Fh compiled/passthroughps.h Blit.ps

-fxc /E luminanceps /T ps_2_0 /Fh compiled/luminanceps.h Blit.ps

-fxc /E componentmaskps /T ps_2_0 /Fh compiled/componentmaskps.h Blit.ps

-

-fxc /E VS_Passthrough /T vs_4_0 /Fh compiled/passthrough11vs.h Passthrough11.hlsl

-fxc /E PS_PassthroughRGBA /T ps_4_0 /Fh compiled/passthroughrgba11ps.h Passthrough11.hlsl

-fxc /E PS_PassthroughRGB /T ps_4_0 /Fh compiled/passthroughrgb11ps.h Passthrough11.hlsl

-fxc /E PS_PassthroughLum /T ps_4_0 /Fh compiled/passthroughlum11ps.h Passthrough11.hlsl

-fxc /E PS_PassthroughLumAlpha /T ps_4_0 /Fh compiled/passthroughlumalpha11ps.h Passthrough11.hlsl

-

-fxc /E VS_Clear /T vs_4_0 /Fh compiled/clear11vs.h Clear11.hlsl

-fxc /E PS_ClearSingle /T ps_4_0 /Fh compiled/clearsingle11ps.h Clear11.hlsl

-fxc /E PS_ClearMultiple /T ps_4_0 /Fh compiled/clearmultiple11ps.h Clear11.hlsl

diff --git a/src/third_party/angle/src/libGLESv2/renderer/vertexconversion.h b/src/third_party/angle/src/libGLESv2/renderer/vertexconversion.h
deleted file mode 100644
index 590b9d4..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/vertexconversion.h
+++ /dev/null
@@ -1,203 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// vertexconversion.h: A library of vertex conversion classes that can be used to build
-// the FormatConverter objects used by the buffer conversion system.
-
-#ifndef LIBGLESV2_VERTEXCONVERSION_H_
-#define LIBGLESV2_VERTEXCONVERSION_H_
-
-namespace rx
-{
-
-// Conversion types:
-// static const bool identity: true if this is an identity transform, false otherwise
-// static U convert(T): convert a single element from the input type to the output type
-// typedef ... OutputType: the type produced by this conversion
-
-template <class T>
-struct Identity
-{
-    static const bool identity = true;
-
-    typedef T OutputType;
-
-    static T convert(T x)
-    {
-        return x;
-    }
-};
-
-template <class FromT, class ToT>
-struct Cast
-{
-    static const bool identity = false;
-
-    typedef ToT OutputType;
-
-    static ToT convert(FromT x)
-    {
-        return static_cast<ToT>(x);
-    }
-};
-
-template <class T>
-struct Cast<T, T>
-{
-    static const bool identity = true;
-
-    typedef T OutputType;
-
-    static T convert(T x)
-    {
-        return static_cast<T>(x);
-    }
-};
-
-template <class T>
-struct Normalize
-{
-    static const bool identity = false;
-
-    typedef float OutputType;
-
-    static float convert(T x)
-    {
-        typedef std::numeric_limits<T> NL;
-        float f = static_cast<float>(x);
-
-        if (NL::is_signed)
-        {
-            // const float => VC2008 computes it at compile time
-            // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
-            const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
-            return (2*f+1)*divisor;
-        }
-        else
-        {
-            return f/NL::max();
-        }
-    }
-};
-
-template <class FromType, std::size_t ScaleBits>
-struct FixedToFloat
-{
-    static const bool identity = false;
-
-    typedef float OutputType;
-
-    static float convert(FromType x)
-    {
-        const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
-        return static_cast<float>(x) * divisor;
-    }
-};
-
-// Widen types:
-// static const unsigned int initialWidth: number of components before conversion
-// static const unsigned int finalWidth: number of components after conversion
-
-// Float is supported at any size.
-template <std::size_t N>
-struct NoWiden
-{
-    static const std::size_t initialWidth = N;
-    static const std::size_t finalWidth = N;
-};
-
-// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
-template <std::size_t N>
-struct WidenToEven
-{
-    static const std::size_t initialWidth = N;
-    static const std::size_t finalWidth = N+(N&1);
-};
-
-template <std::size_t N>
-struct WidenToFour
-{
-    static const std::size_t initialWidth = N;
-    static const std::size_t finalWidth = 4;
-};
-
-// Most types have 0 and 1 that are just that.
-template <class T>
-struct SimpleDefaultValues
-{
-    static T zero() { return static_cast<T>(0); }
-    static T one() { return static_cast<T>(1); }
-};
-
-// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
-template <class T>
-struct NormalizedDefaultValues
-{
-    static T zero() { return static_cast<T>(0); }
-    static T one() { return std::numeric_limits<T>::max(); }
-};
-
-// Converter:
-// static const bool identity: true if this is an identity transform (with no widening)
-// static const std::size_t finalSize: number of bytes per output vertex
-// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided.
-
-template <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> >
-struct VertexDataConverter
-{
-    typedef typename Converter::OutputType OutputType;
-    typedef InT InputType;
-
-    static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
-    static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
-
-    static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out)
-    {
-        for (std::size_t i = 0; i < n; i++)
-        {
-            const InputType *ein = pointerAddBytes(in, i * stride);
-
-            copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
-            copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
-            copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
-            copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
-
-            out += WidenRule::finalWidth;
-        }
-    }
-
-    static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out)
-    {
-        return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
-    }
-
-  private:
-    // Advance the given pointer by a number of bytes (not pointed-to elements).
-    template <class T>
-    static T *pointerAddBytes(T *basePtr, std::size_t numBytes)
-    {
-        return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes);
-    }
-
-    static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
-    {
-        if (WidenRule::finalWidth > elementindex)
-        {
-            if (WidenRule::initialWidth > elementindex)
-            {
-                out[elementindex] = Converter::convert(in[elementindex]);
-            }
-            else
-            {
-                out[elementindex] = defaultvalue;
-            }
-        }
-    }
-};
-
-}
-
-#endif   // LIBGLESV2_VERTEXCONVERSION_H_
diff --git a/src/third_party/angle/src/libGLESv2/renderer/win32/SwapChain11Win32.cpp b/src/third_party/angle/src/libGLESv2/renderer/win32/SwapChain11Win32.cpp
deleted file mode 100644
index febb8ae..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/win32/SwapChain11Win32.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// SwapChain11Api.cpp: Win32 specific implementation for the D3D11 swap chain.
-
-#include "libGLESv2/renderer/SwapChain11.h"
-
-#include "libGLESv2/renderer/renderer11_utils.h"
-#include "libGLESv2/renderer/Renderer11.h"
-
-namespace rx
-{
-
-class SwapChain11Api : public SwapChain11
-{
-  public:
-    SwapChain11Api(Renderer11 *renderer, EGLNativeWindowType window,
-                   HANDLE shareHandle, GLenum backBufferFormat,
-                   GLenum depthBufferFormat);
-
-  protected:
-    virtual EGLint createSwapChain(int backbufferWidth, int backbufferHeight,
-                                   IDXGISwapChain **outSwapChain);
-};
-
-SwapChain11Api::SwapChain11Api(
-    Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-    GLenum backBufferFormat, GLenum depthBufferFormat)
-  : SwapChain11(renderer, window, shareHandle, backBufferFormat,
-                depthBufferFormat) {}
-
-SwapChain11* CreateSwapChainWin32(
-    Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-    GLenum backBufferFormat, GLenum depthBufferFormat)
-{
-    return new SwapChain11Api(renderer, window, shareHandle,
-                              backBufferFormat, depthBufferFormat);
-}
-
-EGLint SwapChain11Api::createSwapChain(
-    int backbufferWidth, int backbufferHeight, IDXGISwapChain **outSwapChain)
-{
-    // We cannot create a swap chain for an HWND that is owned by a
-    // different process
-    DWORD currentProcessId = GetCurrentProcessId();
-    DWORD wndProcessId;
-    GetWindowThreadProcessId((HWND)mWindow, &wndProcessId);
-
-    if (currentProcessId != wndProcessId)
-    {
-        ERR("Could not create swap chain, window owned by different process");
-        return EGL_BAD_NATIVE_WINDOW;
-    }
-
-    ID3D11Device *device = getRenderer()->getDevice();
-    IDXGIFactory *factory = getRenderer()->getDxgiFactory();
-    DXGI_FORMAT format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
-
-    DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
-    swapChainDesc.BufferCount = 2;
-    swapChainDesc.BufferDesc.Format = format;
-    swapChainDesc.BufferDesc.Width = backbufferWidth;
-    swapChainDesc.BufferDesc.Height = backbufferHeight;
-    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;
-    swapChainDesc.Flags = 0;
-    swapChainDesc.OutputWindow = mWindow;
-    swapChainDesc.SampleDesc.Count = 1;
-    swapChainDesc.SampleDesc.Quality = 0;
-    swapChainDesc.Windowed = TRUE;
-
-    IDXGISwapChain *swapChain;
-    HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &swapChain);
-
-    if (SUCCEEDED(result))
-    {
-        *outSwapChain = swapChain;
-        d3d11::ResourceTracker::Track(swapChain);
-        return EGL_SUCCESS;
-    }
-    else
-    {
-        if (d3d11::isDeviceLostError(result))
-            return EGL_CONTEXT_LOST;
-        else
-            return EGL_BAD_ALLOC;
-    }
-}
-
-} // namespace rx
diff --git a/src/third_party/angle/src/libGLESv2/renderer/winrt/SwapChain11WinRT.cpp b/src/third_party/angle/src/libGLESv2/renderer/winrt/SwapChain11WinRT.cpp
deleted file mode 100644
index 175cfaa..0000000
--- a/src/third_party/angle/src/libGLESv2/renderer/winrt/SwapChain11WinRT.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-#include "libGLESv2/precompiled.h"
-//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// SwapChain11WinRT.cpp: WinRT specific implementation for the D3D11 swap chain.
-#include "libGLESv2/renderer/SwapChain11.h"
-
-#include <dxgi1_2.h>
-#include <wrl.h>
-
-#include "common/debug.h"
-#include "common/windowutils.h"
-#include "common/winrt/windowadapter.h"
-#include "libGLESv2/renderer/renderer11_utils.h"
-#include "libGLESv2/renderer/Renderer11.h"
-
-using namespace Microsoft::WRL;
-using namespace Windows::UI::Core;
-
-namespace rx
-{
-class SwapChain11WinRT : public SwapChain11
-{
-  public:
-    SwapChain11WinRT(Renderer11 *renderer, EGLNativeWindowType window,
-                     HANDLE shareHandle, GLenum backBufferFormat,
-                     GLenum depthBufferFormat);
-
-  protected:
-    virtual EGLint createSwapChain(int backbufferWidth, int backbufferHeight,
-                                   IDXGISwapChain **outSwapChain);
-
-    // Keep a reference to the window pointer
-    ComPtr<egl::IWindowAdapter> mWindowAdapter;
-};
-
-SwapChain11WinRT::SwapChain11WinRT(
-    Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-    GLenum backBufferFormat, GLenum depthBufferFormat)
-  : SwapChain11(renderer, window, shareHandle, backBufferFormat,
-                depthBufferFormat)
-{
-    mWindowAdapter = egl::createWindowAdapter(window);
-}
-
-EGLint SwapChain11WinRT::createSwapChain(
-      int backbufferWidth, int backbufferHeight, IDXGISwapChain **outSwapChain)
-{
-    if (!egl::verifyWindowAccessible(mWindowAdapter))
-        return EGL_BAD_NATIVE_WINDOW;
-
-    egl::AngleWindowType windowType;
-    mWindowAdapter->GetType(&windowType);
-
-    ID3D11Device *device = getRenderer()->getDevice();
-    DXGI_FORMAT format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
-
-    ComPtr<IDXGIFactory2> factory;
-    getRenderer()->getDxgiFactory()->QueryInterface(factory.GetAddressOf());
-
-    if (windowType == egl::AWT_COREWINDOW)
-    {
-        ComPtr<IUnknown> windowUnk;
-        if (FAILED(mWindowAdapter->GetWindow(&windowUnk)))
-            return EGL_BAD_NATIVE_WINDOW;
-
-        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
-        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-        swapChainDesc.BufferCount = 2;
-        swapChainDesc.Flags = 0;
-        swapChainDesc.SampleDesc.Count = 1;
-        swapChainDesc.SampleDesc.Quality = 0;
-        swapChainDesc.Format = format;
-        swapChainDesc.Width = backbufferWidth;
-        swapChainDesc.Height = backbufferHeight;
-        swapChainDesc.Stereo = false;
-        swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
-        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
-
-        IDXGISwapChain1* swapChain1 = NULL;
-        HRESULT result = factory->CreateSwapChainForCoreWindow(
-            device, windowUnk.Get(), &swapChainDesc, NULL, &swapChain1);
-
-        if (SUCCEEDED(result))
-        {
-            *outSwapChain = swapChain1;
-            d3d11::ResourceTracker::Track(swapChain1);
-            return EGL_SUCCESS;
-        }
-        else
-        {
-            if (d3d11::isDeviceLostError(result))
-                return EGL_CONTEXT_LOST;
-            else
-                return EGL_BAD_ALLOC;
-        }
-    }
-    else if (windowType == egl::AWT_SWAPCHAIN_ADAPTER)
-    {
-        // A swap chain was already created externally
-        ComPtr<egl::ISwapChainAdapter> swapChainAdapter;
-        if (FAILED(mWindowAdapter->GetWindowAs(swapChainAdapter.GetAddressOf())))
-        {
-            ERR("The supplied window type is not a DXGI swap chain");
-            return EGL_BAD_NATIVE_WINDOW;
-        }
-
-        ComPtr<IDXGISwapChain> swapChain;
-        swapChainAdapter->GetSwapChain(&swapChain);
-
-        *outSwapChain = swapChain.Get();
-        // Note that we are incrementing the reference count here to take
-        // ownership of the resource
-        (*outSwapChain)->AddRef();
-
-        d3d11::ResourceTracker::Track(*outSwapChain);
-        return EGL_SUCCESS;
-    }
-    else
-    {
-        ERR("Unsupported EGL_EXT_WINDOW_TYPE: %d", windowType);
-        return EGL_BAD_NATIVE_WINDOW;
-    }
-}
-
-SwapChain11* CreateSwapChainWinRT(
-    Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-    GLenum backBufferFormat, GLenum depthBufferFormat)
-{
-    return new SwapChain11WinRT(
-        renderer, window, shareHandle, backBufferFormat, depthBufferFormat);
-}
-
-} // namespace rx
diff --git a/src/third_party/angle/src/libGLESv2/utilities.cpp b/src/third_party/angle/src/libGLESv2/utilities.cpp
deleted file mode 100644
index 5953f36..0000000
--- a/src/third_party/angle/src/libGLESv2/utilities.cpp
+++ /dev/null
@@ -1,798 +0,0 @@
-#include "precompiled.h"
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// utilities.cpp: Conversion functions and other utility routines.
-
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/mathutil.h"
-
-namespace gl
-{
-
-int UniformComponentCount(GLenum type)
-{
-    switch (type)
-    {
-      case GL_BOOL:
-      case GL_FLOAT:
-      case GL_INT:
-      case GL_SAMPLER_2D:
-      case GL_SAMPLER_CUBE:
-          return 1;
-      case GL_BOOL_VEC2:
-      case GL_FLOAT_VEC2:
-      case GL_INT_VEC2:
-          return 2;
-      case GL_INT_VEC3:
-      case GL_FLOAT_VEC3:
-      case GL_BOOL_VEC3:
-          return 3;
-      case GL_BOOL_VEC4:
-      case GL_FLOAT_VEC4:
-      case GL_INT_VEC4:
-      case GL_FLOAT_MAT2:
-          return 4;
-      case GL_FLOAT_MAT3:
-          return 9;
-      case GL_FLOAT_MAT4:
-          return 16;
-      default:
-          UNREACHABLE();
-    }
-
-    return 0;
-}
-
-GLenum UniformComponentType(GLenum type)
-{
-    switch(type)
-    {
-      case GL_BOOL:
-      case GL_BOOL_VEC2:
-      case GL_BOOL_VEC3:
-      case GL_BOOL_VEC4:
-          return GL_BOOL;
-      case GL_FLOAT:
-      case GL_FLOAT_VEC2:
-      case GL_FLOAT_VEC3:
-      case GL_FLOAT_VEC4:
-      case GL_FLOAT_MAT2:
-      case GL_FLOAT_MAT3:
-      case GL_FLOAT_MAT4:
-          return GL_FLOAT;
-      case GL_INT:
-      case GL_SAMPLER_2D:
-      case GL_SAMPLER_CUBE:
-      case GL_INT_VEC2:
-      case GL_INT_VEC3:
-      case GL_INT_VEC4:
-          return GL_INT;
-      default:
-          UNREACHABLE();
-    }
-
-    return GL_NONE;
-}
-
-size_t UniformComponentSize(GLenum type)
-{
-    switch(type)
-    {
-      case GL_BOOL:  return sizeof(GLint);
-      case GL_FLOAT: return sizeof(GLfloat);
-      case GL_INT:   return sizeof(GLint);
-      default:       UNREACHABLE();
-    }
-
-    return 0;
-}
-
-size_t UniformInternalSize(GLenum type)
-{
-    // Expanded to 4-element vectors
-    return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4;
-}
-
-size_t UniformExternalSize(GLenum type)
-{
-    return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type);
-}
-
-int VariableRowCount(GLenum type)
-{
-    switch (type)
-    {
-      case GL_NONE:
-        return 0;
-      case GL_BOOL:
-      case GL_FLOAT:
-      case GL_INT:
-      case GL_BOOL_VEC2:
-      case GL_FLOAT_VEC2:
-      case GL_INT_VEC2:
-      case GL_INT_VEC3:
-      case GL_FLOAT_VEC3:
-      case GL_BOOL_VEC3:
-      case GL_BOOL_VEC4:
-      case GL_FLOAT_VEC4:
-      case GL_INT_VEC4:
-      case GL_SAMPLER_2D:
-      case GL_SAMPLER_CUBE:
-        return 1;
-      case GL_FLOAT_MAT2:
-        return 2;
-      case GL_FLOAT_MAT3:
-        return 3;
-      case GL_FLOAT_MAT4:
-        return 4;
-      default:
-        UNREACHABLE();
-    }
-
-    return 0;
-}
-
-int VariableColumnCount(GLenum type)
-{
-    switch (type)
-    {
-      case GL_NONE:
-        return 0;
-      case GL_BOOL:
-      case GL_FLOAT:
-      case GL_INT:
-      case GL_SAMPLER_2D:
-      case GL_SAMPLER_CUBE:
-        return 1;
-      case GL_BOOL_VEC2:
-      case GL_FLOAT_VEC2:
-      case GL_INT_VEC2:
-      case GL_FLOAT_MAT2:
-        return 2;
-      case GL_INT_VEC3:
-      case GL_FLOAT_VEC3:
-      case GL_BOOL_VEC3:
-      case GL_FLOAT_MAT3:
-        return 3;
-      case GL_BOOL_VEC4:
-      case GL_FLOAT_VEC4:
-      case GL_INT_VEC4:
-      case GL_FLOAT_MAT4:
-        return 4;
-      default:
-        UNREACHABLE();
-    }
-
-    return 0;
-}
-
-int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
-{
-    ASSERT(allocationSize <= bitsSize);
-
-    unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
-
-    for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
-    {
-        if ((*bits & mask) == 0)
-        {
-            *bits |= mask;
-            return i;
-        }
-
-        mask <<= 1;
-    }
-
-    return -1;
-}
-
-GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment)
-{
-    ASSERT(alignment > 0 && isPow2(alignment));
-
-    GLsizei rawPitch = ComputePixelSize(internalformat) * width;
-    return (rawPitch + alignment - 1) & ~(alignment - 1);
-}
-
-GLsizei ComputeCompressedPitch(GLsizei width, GLenum internalformat)
-{
-    return ComputeCompressedSize(width, 1, internalformat);
-}
-
-GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-        return 8 * ((width + 3) / 4) * ((height + 3) / 4);
-      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-        return 16 * ((width + 3) / 4) * ((height + 3) / 4);
-      default:
-        return 0;
-    }
-}
-
-bool IsCompressed(GLenum format)
-{
-    if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
-       format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
-       format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
-       format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
-    {
-        return true;
-    }
-    else
-    {
-        return false;
-    }
-}
-
-bool IsDepthTexture(GLenum format)
-{
-    if (format == GL_DEPTH_COMPONENT ||
-        format == GL_DEPTH_STENCIL_OES ||
-        format == GL_DEPTH_COMPONENT16 ||
-        format == GL_DEPTH_COMPONENT32_OES ||
-        format == GL_DEPTH24_STENCIL8_OES)
-    {
-        return true;
-    }
-
-    return false;
-}
-
-bool IsStencilTexture(GLenum format)
-{
-    if (format == GL_DEPTH_STENCIL_OES ||
-        format == GL_DEPTH24_STENCIL8_OES)
-    {
-        return true;
-    }
-
-    return false;
-}
-
-void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
-{
-    int upsampleCount = 0;
-
-    if (isCompressed)
-    {
-        // Don't expand the size of full textures that are at least 4x4
-        // already.
-        if (isImage || *requestWidth < 4 || *requestHeight < 4)
-        {
-            while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0)
-            {
-                *requestWidth <<= 1;
-                *requestHeight <<= 1;
-                upsampleCount++;
-            }
-        }
-    }
-    *levelOffset = upsampleCount;
-}
-
-// Returns the size, in bytes, of a single texel in an Image
-int ComputePixelSize(GLint internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_ALPHA8_EXT:                       return sizeof(unsigned char);
-      case GL_LUMINANCE8_EXT:                   return sizeof(unsigned char);
-      case GL_ALPHA32F_EXT:                     return sizeof(float);
-      case GL_LUMINANCE32F_EXT:                 return sizeof(float);
-      case GL_ALPHA16F_EXT:                     return sizeof(unsigned short);
-      case GL_LUMINANCE16F_EXT:                 return sizeof(unsigned short);
-      case GL_LUMINANCE8_ALPHA8_EXT:            return sizeof(unsigned char) * 2;
-      case GL_LUMINANCE_ALPHA32F_EXT:           return sizeof(float) * 2;
-      case GL_LUMINANCE_ALPHA16F_EXT:           return sizeof(unsigned short) * 2;
-      case GL_RGB8_OES:                         return sizeof(unsigned char) * 3;
-      case GL_RGB565:                           return sizeof(unsigned short);
-      case GL_RGB32F_EXT:                       return sizeof(float) * 3;
-      case GL_RGB16F_EXT:                       return sizeof(unsigned short) * 3;
-      case GL_RGBA8_OES:                        return sizeof(unsigned char) * 4;
-      case GL_RGBA4:                            return sizeof(unsigned short);
-      case GL_RGB5_A1:                          return sizeof(unsigned short);
-      case GL_RGBA32F_EXT:                      return sizeof(float) * 4;
-      case GL_RGBA16F_EXT:                      return sizeof(unsigned short) * 4;
-      case GL_BGRA8_EXT:                        return sizeof(unsigned char) * 4;
-      case GL_BGRA4_ANGLEX:                     return sizeof(unsigned short);
-      case GL_BGR5_A1_ANGLEX:                   return sizeof(unsigned short);
-      default: UNREACHABLE();
-    }
-
-    return 0;
-}
-
-bool IsCubemapTextureTarget(GLenum target)
-{
-    return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
-}
-
-bool IsInternalTextureTarget(GLenum target)
-{
-    return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
-}
-
-GLint ConvertSizedInternalFormat(GLenum format, GLenum type)
-{
-    switch (format)
-    {
-      case GL_ALPHA:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:    return GL_ALPHA8_EXT;
-          case GL_FLOAT:            return GL_ALPHA32F_EXT;
-          case GL_HALF_FLOAT_OES:   return GL_ALPHA16F_EXT;
-          default:                  UNIMPLEMENTED();
-        }
-        break;
-      case GL_LUMINANCE:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:    return GL_LUMINANCE8_EXT;
-          case GL_FLOAT:            return GL_LUMINANCE32F_EXT;
-          case GL_HALF_FLOAT_OES:   return GL_LUMINANCE16F_EXT;
-          default:                  UNIMPLEMENTED();
-        }
-        break;
-      case GL_LUMINANCE_ALPHA:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:    return GL_LUMINANCE8_ALPHA8_EXT;
-          case GL_FLOAT:            return GL_LUMINANCE_ALPHA32F_EXT;
-          case GL_HALF_FLOAT_OES:   return GL_LUMINANCE_ALPHA16F_EXT;
-          default:                  UNIMPLEMENTED();
-        }
-        break;
-      case GL_RGB:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:            return GL_RGB8_OES;
-          case GL_UNSIGNED_SHORT_5_6_5:     return GL_RGB565;
-          case GL_FLOAT:                    return GL_RGB32F_EXT;
-          case GL_HALF_FLOAT_OES:           return GL_RGB16F_EXT;
-          default:                          UNIMPLEMENTED();
-        }
-        break;
-      case GL_RGBA:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:            return GL_RGBA8_OES;
-          case GL_UNSIGNED_SHORT_4_4_4_4:   return GL_RGBA4;
-          case GL_UNSIGNED_SHORT_5_5_5_1:   return GL_RGB5_A1;
-          case GL_FLOAT:                    return GL_RGBA32F_EXT;
-          case GL_HALF_FLOAT_OES:           return GL_RGBA16F_EXT;
-            break;
-          default:                          UNIMPLEMENTED();
-        }
-        break;
-      case GL_BGRA_EXT:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:                    return GL_BGRA8_EXT;
-          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:   return GL_BGRA4_ANGLEX;
-          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:   return GL_BGR5_A1_ANGLEX;
-          default:                                  UNIMPLEMENTED();
-        }
-        break;
-      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
-      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
-        return format;
-      case GL_DEPTH_COMPONENT:
-        switch (type)
-        {
-          case GL_UNSIGNED_SHORT:           return GL_DEPTH_COMPONENT16;
-          case GL_UNSIGNED_INT:             return GL_DEPTH_COMPONENT32_OES;
-          default:                          UNIMPLEMENTED();
-        }
-        break;
-      case GL_DEPTH_STENCIL_OES:
-        switch (type)
-        {
-          case GL_UNSIGNED_INT_24_8_OES:    return GL_DEPTH24_STENCIL8_OES;
-          default:                          UNIMPLEMENTED();
-        }
-        break;
-      default:
-        UNIMPLEMENTED();
-    }
-
-    return GL_NONE;
-}
-
-GLenum ExtractFormat(GLenum internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_RGB565:                          return GL_RGB;
-      case GL_RGBA4:                           return GL_RGBA;
-      case GL_RGB5_A1:                         return GL_RGBA;
-      case GL_RGB8_OES:                        return GL_RGB;
-      case GL_RGBA8_OES:                       return GL_RGBA;
-      case GL_LUMINANCE8_ALPHA8_EXT:           return GL_LUMINANCE_ALPHA;
-      case GL_LUMINANCE8_EXT:                  return GL_LUMINANCE;
-      case GL_ALPHA8_EXT:                      return GL_ALPHA;
-      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:    return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
-      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:   return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
-      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
-      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
-      case GL_RGBA32F_EXT:                     return GL_RGBA;
-      case GL_RGB32F_EXT:                      return GL_RGB;
-      case GL_ALPHA32F_EXT:                    return GL_ALPHA;
-      case GL_LUMINANCE32F_EXT:                return GL_LUMINANCE;
-      case GL_LUMINANCE_ALPHA32F_EXT:          return GL_LUMINANCE_ALPHA;
-      case GL_RGBA16F_EXT:                     return GL_RGBA;
-      case GL_RGB16F_EXT:                      return GL_RGB;
-      case GL_ALPHA16F_EXT:                    return GL_ALPHA;
-      case GL_LUMINANCE16F_EXT:                return GL_LUMINANCE;
-      case GL_LUMINANCE_ALPHA16F_EXT:          return GL_LUMINANCE_ALPHA;
-      case GL_BGRA8_EXT:                       return GL_BGRA_EXT;
-      case GL_DEPTH_COMPONENT16:               return GL_DEPTH_COMPONENT;
-      case GL_DEPTH_COMPONENT32_OES:           return GL_DEPTH_COMPONENT;
-      case GL_DEPTH24_STENCIL8_OES:            return GL_DEPTH_STENCIL_OES;
-      default:                                 return GL_NONE;   // Unsupported
-    }
-}
-
-GLenum ExtractType(GLenum internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_RGB565:                          return GL_UNSIGNED_SHORT_5_6_5;
-      case GL_RGBA4:                           return GL_UNSIGNED_SHORT_4_4_4_4;
-      case GL_RGB5_A1:                         return GL_UNSIGNED_SHORT_5_5_5_1;
-      case GL_RGB8_OES:                        return GL_UNSIGNED_BYTE;
-      case GL_RGBA8_OES:                       return GL_UNSIGNED_BYTE;
-      case GL_LUMINANCE8_ALPHA8_EXT:           return GL_UNSIGNED_BYTE;
-      case GL_LUMINANCE8_EXT:                  return GL_UNSIGNED_BYTE;
-      case GL_ALPHA8_EXT:                      return GL_UNSIGNED_BYTE;
-      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:    return GL_UNSIGNED_BYTE;
-      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:   return GL_UNSIGNED_BYTE;
-      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE;
-      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE;
-      case GL_RGBA32F_EXT:                     return GL_FLOAT;
-      case GL_RGB32F_EXT:                      return GL_FLOAT;
-      case GL_ALPHA32F_EXT:                    return GL_FLOAT;
-      case GL_LUMINANCE32F_EXT:                return GL_FLOAT;
-      case GL_LUMINANCE_ALPHA32F_EXT:          return GL_FLOAT;
-      case GL_RGBA16F_EXT:                     return GL_HALF_FLOAT_OES;
-      case GL_RGB16F_EXT:                      return GL_HALF_FLOAT_OES;
-      case GL_ALPHA16F_EXT:                    return GL_HALF_FLOAT_OES;
-      case GL_LUMINANCE16F_EXT:                return GL_HALF_FLOAT_OES;
-      case GL_LUMINANCE_ALPHA16F_EXT:          return GL_HALF_FLOAT_OES;
-      case GL_BGRA8_EXT:                       return GL_UNSIGNED_BYTE;
-      case GL_DEPTH_COMPONENT16:               return GL_UNSIGNED_SHORT;
-      case GL_DEPTH_COMPONENT32_OES:           return GL_UNSIGNED_INT;
-      case GL_DEPTH24_STENCIL8_OES:            return GL_UNSIGNED_INT_24_8_OES;
-      default:                                 return GL_NONE;   // Unsupported
-    }
-}
-
-bool IsColorRenderable(GLenum internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_RGBA4:
-      case GL_RGB5_A1:
-      case GL_RGB565:
-      case GL_RGB8_OES:
-      case GL_RGBA8_OES:
-        return true;
-      case GL_DEPTH_COMPONENT16:
-      case GL_STENCIL_INDEX8:
-      case GL_DEPTH24_STENCIL8_OES:
-        return false;
-      case GL_BGRA8_EXT:
-          return true;
-      default:
-        UNIMPLEMENTED();
-    }
-
-    return false;
-}
-
-bool IsDepthRenderable(GLenum internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_DEPTH_COMPONENT16:
-      case GL_DEPTH24_STENCIL8_OES:
-        return true;
-      case GL_STENCIL_INDEX8:
-      case GL_RGBA4:
-      case GL_RGB5_A1:
-      case GL_RGB565:
-      case GL_RGB8_OES:
-      case GL_RGBA8_OES:
-        return false;
-      default:
-        UNIMPLEMENTED();
-    }
-
-    return false;
-}
-
-bool IsStencilRenderable(GLenum internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_STENCIL_INDEX8:
-      case GL_DEPTH24_STENCIL8_OES:
-        return true;
-      case GL_RGBA4:
-      case GL_RGB5_A1:
-      case GL_RGB565:
-      case GL_RGB8_OES:
-      case GL_RGBA8_OES:
-      case GL_DEPTH_COMPONENT16:
-        return false;
-      default:
-        UNIMPLEMENTED();
-    }
-
-    return false;
-}
-
-bool IsFloat32Format(GLint internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_RGBA32F_EXT:
-      case GL_RGB32F_EXT:
-      case GL_ALPHA32F_EXT:
-      case GL_LUMINANCE32F_EXT:
-      case GL_LUMINANCE_ALPHA32F_EXT:
-        return true;
-      default:
-        return false;
-    }
-}
-
-bool IsFloat16Format(GLint internalformat)
-{
-    switch (internalformat)
-    {
-      case GL_RGBA16F_EXT:
-      case GL_RGB16F_EXT:
-      case GL_ALPHA16F_EXT:
-      case GL_LUMINANCE16F_EXT:
-      case GL_LUMINANCE_ALPHA16F_EXT:
-        return true;
-      default:
-        return false;
-    }
-}
-
-unsigned int GetAlphaSize(GLenum colorFormat)
-{
-    switch (colorFormat)
-    {
-      case GL_RGBA16F_EXT:
-        return 16;
-      case GL_RGBA32F_EXT:
-        return 32;
-      case GL_RGBA4:
-        return 4;
-      case GL_RGBA8_OES:
-      case GL_BGRA8_EXT:
-        return 8;
-      case GL_RGB5_A1:
-        return 1;
-      case GL_RGB8_OES:
-      case GL_RGB565:
-      case GL_RGB32F_EXT:
-      case GL_RGB16F_EXT:
-        return 0;
-      default:
-        return 0;
-    }
-}
-
-unsigned int GetRedSize(GLenum colorFormat)
-{
-    switch (colorFormat)
-    {
-      case GL_RGBA16F_EXT:
-      case GL_RGB16F_EXT:
-        return 16;
-      case GL_RGBA32F_EXT:
-      case GL_RGB32F_EXT:
-        return 32;
-      case GL_RGBA4:
-        return 4;
-      case GL_RGBA8_OES:
-      case GL_BGRA8_EXT:
-      case GL_RGB8_OES:
-        return 8;
-      case GL_RGB5_A1:
-      case GL_RGB565:
-        return 5;
-      default:
-        return 0;
-    }
-}
-
-unsigned int GetGreenSize(GLenum colorFormat)
-{
-    switch (colorFormat)
-    {
-      case GL_RGBA16F_EXT:
-      case GL_RGB16F_EXT:
-        return 16;
-      case GL_RGBA32F_EXT:
-      case GL_RGB32F_EXT:
-        return 32;
-      case GL_RGBA4:
-        return 4;
-      case GL_RGBA8_OES:
-      case GL_BGRA8_EXT:
-      case GL_RGB8_OES:
-        return 8;
-      case GL_RGB5_A1:
-        return 5;
-      case GL_RGB565:
-        return 6;
-      default:
-        return 0;
-    }
-}
-
-unsigned int GetBlueSize(GLenum colorFormat)
-{
-    switch (colorFormat)
-    {
-      case GL_RGBA16F_EXT:
-      case GL_RGB16F_EXT:
-        return 16;
-      case GL_RGBA32F_EXT:
-      case GL_RGB32F_EXT:
-        return 32;
-      case GL_RGBA4:
-        return 4;
-      case GL_RGBA8_OES:
-      case GL_BGRA8_EXT:
-      case GL_RGB8_OES:
-        return 8;
-      case GL_RGB5_A1:
-      case GL_RGB565:
-        return 5;
-      default:
-        return 0;
-    }
-}
-
-unsigned int GetDepthSize(GLenum depthFormat)
-{
-    switch (depthFormat)
-    {
-      case GL_DEPTH_COMPONENT16:        return 16;
-      case GL_DEPTH_COMPONENT32_OES:    return 32;
-      case GL_DEPTH24_STENCIL8_OES:     return 24;
-      default:                          return 0;
-    }
-}
-
-unsigned int GetStencilSize(GLenum stencilFormat)
-{
-    switch (stencilFormat)
-    {
-      case GL_DEPTH24_STENCIL8_OES:     return 8;
-      default:                          return 0;
-    }
-}
-
-bool IsTriangleMode(GLenum drawMode)
-{
-    switch (drawMode)
-    {
-      case GL_TRIANGLES:
-      case GL_TRIANGLE_FAN:
-      case GL_TRIANGLE_STRIP:
-        return true;
-      case GL_POINTS:
-      case GL_LINES:
-      case GL_LINE_LOOP:
-      case GL_LINE_STRIP:
-        return false;
-      default: UNREACHABLE();
-    }
-
-    return false;
-}
-
-}
-
-#if defined(__LB_XB360__)
-
-#include <stdio.h>
-
-static DWORD GetTempPathW(DWORD nBufferLength, LPTSTR lpBuffer)
-{
-  return !wcsncpy_s(lpBuffer, nBufferLength, _wP_tmpdir, nBufferLength);
-}
-
-static UINT GetTempFileNameW(LPCTSTR lpPathName, LPCTSTR lpPrefixString,
-                             UINT uUnique, LPTSTR lpTempFileName)
-{
-  LPCTSTR tempname = _wtempnam(lpPathName, lpPrefixString);
-  if (!tempname) return 0;
-
-  return !wcsncpy_s(lpTempFileName, MAX_PATH, tempname, MAX_PATH);
-}
-
-static DWORD GetShortPathNameW(LPCTSTR lpszLongPath, LPTSTR lpszShortPath,
-                               DWORD cchBuffer)
-{
-  return !wcsncpy_s(lpszShortPath, cchBuffer, lpszLongPath, cchBuffer);
-}
-
-#endif // defined(__LB_XB360__)
-
-std::string getTempPath()
-{
-#ifdef __LB_SHELL__FOR_RELEASE__
-  return std::string();
-#else
-    wchar_t widePath[MAX_PATH];
-    if (GetTempPathW(MAX_PATH, widePath) == 0)
-    {
-        UNREACHABLE();
-        return std::string();
-    }
-
-    wchar_t wideFileName[MAX_PATH];
-    if (GetTempFileNameW(widePath, L"sh", 0, wideFileName) == 0)
-    {
-        UNREACHABLE();
-        return std::string();
-    }
-
-    wchar_t shortPath[MAX_PATH];
-    if (GetShortPathNameW(wideFileName, shortPath, MAX_PATH) == 0)
-    {
-        UNREACHABLE();
-        return std::string();
-    }
-
-    // Short paths should not contain any non-ASCII characters which means
-    // that the resulting UTF-8 should be pure ASCII, even if the original
-    // name had special UNICODE characters
-    int bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, shortPath, -1,
-                                          NULL, 0, NULL, NULL);
-
-    std::string result(bytesNeeded, 0);
-    if (WideCharToMultiByte(CP_UTF8, 0, shortPath, -1,
-                            &result[0], bytesNeeded, NULL, NULL) == 0)
-    {
-        UNREACHABLE();
-        return std::string();
-    }
-
-    return result;
-#endif
-}
-
-void writeFile(const char* path, const void* content, size_t size)
-{
-#ifndef __LB_SHELL__FOR_RELEASE__
-    FILE* file = fopen(path, "w");
-    if (!file)
-    {
-        UNREACHABLE();
-        return;
-    }
-
-    fwrite(content, sizeof(char), size, file);
-    fclose(file);
-#endif
-}
diff --git a/src/third_party/angle/src/libGLESv2/utilities.h b/src/third_party/angle/src/libGLESv2/utilities.h
deleted file mode 100644
index 7a10767..0000000
--- a/src/third_party/angle/src/libGLESv2/utilities.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// utilities.h: Conversion functions and other utility routines.
-
-#ifndef LIBGLESV2_UTILITIES_H
-#define LIBGLESV2_UTILITIES_H
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <string>
-
-namespace gl
-{
-
-struct Color;
-
-int UniformComponentCount(GLenum type);
-GLenum UniformComponentType(GLenum type);
-size_t UniformInternalSize(GLenum type);
-size_t UniformExternalSize(GLenum type);
-int VariableRowCount(GLenum type);
-int VariableColumnCount(GLenum type);
-
-int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
-
-void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset);
-int ComputePixelSize(GLint internalformat);
-GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment);
-GLsizei ComputeCompressedPitch(GLsizei width, GLenum format);
-GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format);
-bool IsCompressed(GLenum format);
-bool IsDepthTexture(GLenum format);
-bool IsStencilTexture(GLenum format);
-bool IsCubemapTextureTarget(GLenum target);
-bool IsInternalTextureTarget(GLenum target);
-GLint ConvertSizedInternalFormat(GLenum format, GLenum type);
-GLenum ExtractFormat(GLenum internalformat);
-GLenum ExtractType(GLenum internalformat);
-
-bool IsColorRenderable(GLenum internalformat);
-bool IsDepthRenderable(GLenum internalformat);
-bool IsStencilRenderable(GLenum internalformat);
-
-bool IsFloat32Format(GLint internalformat);
-bool IsFloat16Format(GLint internalformat);
-
-GLuint GetAlphaSize(GLenum colorFormat);
-GLuint GetRedSize(GLenum colorFormat);
-GLuint GetGreenSize(GLenum colorFormat);
-GLuint GetBlueSize(GLenum colorFormat);
-GLuint GetDepthSize(GLenum depthFormat);
-GLuint GetStencilSize(GLenum stencilFormat);
-bool IsTriangleMode(GLenum drawMode);
-
-}
-
-std::string getTempPath();
-void writeFile(const char* path, const void* data, size_t size);
-
-#endif  // LIBGLESV2_UTILITIES_H
diff --git a/src/third_party/angle/src/tests/BUILD.gn b/src/third_party/angle/src/tests/BUILD.gn
new file mode 100644
index 0000000..76a913c
--- /dev/null
+++ b/src/third_party/angle/src/tests/BUILD.gn
@@ -0,0 +1,409 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//testing/test.gni")
+import("//build/config/chromecast_build.gni")
+import("//third_party/angle/gni/angle.gni")
+
+unittests_gypi = exec_script("//build/gypi_to_gn.py",
+                             [
+                               rebase_path("angle_unittests.gypi"),
+                               "--replace=<(angle_path)=.",
+                             ],
+                             "scope",
+                             [ "angle_unittests.gypi" ])
+
+test("angle_unittests") {
+  include_dirs = [
+    "testing/gtest/include",
+    "../../src",
+  ]
+
+  sources = rebase_path(unittests_gypi.angle_unittests_sources, ".", "../..")
+
+  if (angle_enable_hlsl) {
+    sources +=
+        rebase_path(unittests_gypi.angle_unittests_hlsl_sources, ".", "../..")
+    defines = [ "ANGLE_ENABLE_HLSL" ]
+  }
+
+  sources += [ "//gpu/angle_unittest_main.cc" ]
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/angle:libANGLE",
+    "//third_party/angle:preprocessor",
+    "//third_party/angle:translator",
+  ]
+}
+
+if (is_win || is_linux || is_mac || is_android) {
+  end2end_gypi = exec_script("//build/gypi_to_gn.py",
+                             [
+                               rebase_path("angle_end2end_tests.gypi"),
+                               "--replace=<(angle_path)=.",
+                             ],
+                             "scope",
+                             [ "angle_end2end_tests.gypi" ])
+
+  test("angle_end2end_tests") {
+    include_dirs = [
+      "testing/gtest/include",
+      "../../src/tests",
+      "../../util",
+    ]
+
+    if (is_android) {
+      use_native_activity = true
+    }
+
+    sources =
+        rebase_path(end2end_gypi.angle_end2end_tests_sources, ".", "../..")
+
+    if (is_win) {
+      sources += rebase_path(end2end_gypi.angle_end2end_tests_win_sources,
+                             ".",
+                             "../..")
+    }
+    if (use_x11) {
+      sources += rebase_path(end2end_gypi.angle_end2end_tests_x11_sources,
+                             ".",
+                             "../..")
+    }
+
+    sources += [ "//gpu/angle_end2end_tests_main.cc" ]
+
+    configs += [
+      "//third_party/angle:internal_config",
+      "//third_party/angle:libANGLE_config",
+    ]
+
+    if (is_linux && !is_component_build) {
+      # Set rpath to find libEGL.so and libGLESv2.so even in a non-component build.
+      configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
+    }
+
+    deps = [
+      "//base",
+      "//base/test:test_support",
+      "//testing/gmock",
+      "//testing/gtest",
+      "//third_party/angle:angle_image_util",
+      "//third_party/angle:angle_util",
+      "//third_party/angle:libEGL",
+      "//third_party/angle:libGLESv2",
+      "//third_party/angle:preprocessor",
+      "//third_party/angle:translator",
+    ]
+  }
+
+  white_box_gypi = exec_script("//build/gypi_to_gn.py",
+                               [
+                                 rebase_path("angle_white_box_tests.gypi"),
+                                 "--replace=<(angle_path)=.",
+                               ],
+                               "scope",
+                               [ "angle_white_box_tests.gypi" ])
+
+  test("angle_white_box_tests") {
+    include_dirs = [
+      "testing/gtest/include",
+      "../../src/tests",
+      "../../util",
+    ]
+
+    if (is_android) {
+      use_native_activity = true
+    }
+
+    sources =
+        rebase_path(white_box_gypi.angle_white_box_tests_sources, ".", "../..")
+
+    if (is_win) {
+      sources += rebase_path(white_box_gypi.angle_white_box_tests_win_sources,
+                             ".",
+                             "../..")
+    }
+
+    # Share the same main file as end2end_tests.
+    # TODO(jmadill): Probably should rename this if we're sharing.
+    sources += [ "//gpu/angle_end2end_tests_main.cc" ]
+
+    configs += [
+      "//third_party/angle:internal_config",
+      "//third_party/angle:libANGLE_config",
+    ]
+
+    deps = [
+      "//base",
+      "//base/test:test_support",
+      "//testing/gmock",
+      "//testing/gtest",
+      "//third_party/angle:angle_util_static",
+      "//third_party/angle:libANGLE",
+      "//third_party/angle:libEGL_static",
+      "//third_party/angle:libGLESv2_static",
+      "//third_party/angle:preprocessor",
+      "//third_party/angle:translator",
+    ]
+  }
+}
+
+if (is_win || is_linux) {
+  perftests_gypi = exec_script("//build/gypi_to_gn.py",
+                               [
+                                 rebase_path("angle_perftests.gypi"),
+                                 "--replace=<(angle_path)=.",
+                               ],
+                               "scope",
+                               [ "angle_perftests.gypi" ])
+
+  test("angle_perftests") {
+    include_dirs = [
+      "testing/gtest/include",
+      "../../src/tests",
+      "../../util",
+    ]
+
+    sources = rebase_path(perftests_gypi.angle_perf_tests_sources, ".", "../..")
+
+    if (is_win) {
+      sources +=
+          rebase_path(perftests_gypi.angle_perf_tests_win_sources, ".", "../..")
+    }
+
+    sources += [ "//gpu/angle_perftests_main.cc" ]
+
+    configs += [
+      "//third_party/angle:internal_config",
+      "//third_party/angle:libANGLE_config",
+    ]
+
+    deps = [
+      "//base",
+      "//base/test:test_support",
+      "//testing/gmock",
+      "//testing/gtest",
+      "//third_party/angle:angle_util_static",
+      "//third_party/angle:libEGL_static",
+      "//third_party/angle:libGLESv2_static",
+    ]
+  }
+}
+
+###-----------------------------------------------------
+### dEQP tests
+###-----------------------------------------------------
+
+declare_args() {
+  # Don't build dEQP by default.
+  build_angle_deqp_tests = false
+}
+
+# TODO(jmadill): Other platforms.
+if (build_angle_deqp_tests) {
+  deqp_gypi = exec_script("//build/gypi_to_gn.py",
+                          [
+                            rebase_path("deqp.gypi"),
+                            "--replace=<(angle_path)=.",
+                            "--replace=<(deqp_path)=../deqp/src",
+                          ],
+                          "scope",
+                          [ "deqp.gypi" ])
+
+  config("angle_deqp_support") {
+    include_dirs = rebase_path(deqp_gypi.deqp_include_dirs, ".", "../..")
+    if (is_win) {
+      include_dirs += [ "../deqp/src/framework/platform/win32" ]
+      cflags = deqp_gypi.deqp_win_cflags
+    }
+    if (is_android) {
+      include_dirs += [ "../../../deqp/src/framework/platform/android" ]
+    }
+    defines = deqp_gypi.deqp_defines
+    defines += [ "_MBCS" ]
+
+    # Ask the system headers to expose all the regular function otherwise
+    # dEQP doesn't compile and produces warnings about implicitly defined
+    # functions.
+    if (is_linux) {
+      # This has to be GNU_SOURCE as on Linux dEQP uses syscall()
+      defines += [ "_GNU_SOURCE" ]
+    }
+    if (is_android) {
+      # _XOPEN_SOURCE=600 is what is used in deqp/src/Android.mk
+      defines += [ "_XOPEN_SOURCE=600" ]
+    }
+  }
+
+  deqp_undefine_configs = [
+    "//build/config/compiler:chromium_code",
+    "//build/config/compiler:no_rtti",
+  ]
+
+  if (is_win) {
+    deqp_undefine_configs += [
+      "//build/config/win:lean_and_mean",
+      "//build/config/win:nominmax",
+      "//build/config/win:unicode",
+    ]
+  }
+
+  if (is_linux || is_android) {
+    deqp_undefine_configs += [ "//build/config/gcc:no_exceptions" ]
+  }
+
+  static_library("angle_deqp_decpp") {
+    configs -= deqp_undefine_configs
+    public_configs = [
+      ":angle_deqp_support",
+      "//build/config/compiler:no_chromium_code",
+      "//third_party/angle:internal_config",
+    ]
+    sources = rebase_path(deqp_gypi.deqp_libtester_decpp_sources, ".", "../..")
+  }
+
+  config("angle_deqp_libtester_config") {
+    defines = [ "ANGLE_DEQP_LIBTESTER_IMPLEMENTATION" ]
+
+    if (is_clang) {
+      # TODO(jmadill): Remove this once we fix dEQP.
+      cflags_cc = [ "-Wno-delete-non-virtual-dtor" ]
+    }
+  }
+
+  static_library("angle_deqp_libtester") {
+    public_deps = [
+      ":angle_deqp_decpp",
+      "//third_party/angle:angle_common",
+      "//third_party/angle:angle_util",
+      "//third_party/angle:libEGL",
+      "//third_party/libpng:libpng",
+    ]
+    configs -= deqp_undefine_configs
+    public_configs = [ ":angle_deqp_libtester_config" ]
+    sources = rebase_path(deqp_gypi.deqp_libtester_sources, ".", "../..")
+    if (is_win) {
+      sources += rebase_path(deqp_gypi.deqp_libtester_sources_win, ".", "../..")
+    }
+    if (is_linux || is_android) {
+      sources +=
+          rebase_path(deqp_gypi.deqp_libtester_sources_unix, ".", "../..")
+    }
+    if (is_android) {
+      sources +=
+          rebase_path(deqp_gypi.deqp_libtester_sources_android, ".", "../..")
+      libs = [ "log" ]
+    }
+  }
+
+  config("angle_deqp_gtest_support_config") {
+    include_dirs = [ "third_party/gpu_test_expectations" ]
+  }
+
+  source_set("angle_deqp_gtest_support") {
+    testonly = true
+    public_deps = [
+      "//base",
+      "//base/test:test_support",
+      "//testing/gtest",
+      "//third_party/angle:angle_common",
+      "//third_party/angle:angle_util",
+    ]
+    public_configs = [ ":angle_deqp_gtest_support_config" ]
+    sources = deqp_gypi.deqp_gpu_test_expectations_sources
+    sources += [ "//gpu/angle_deqp_tests_main.cc" ]
+
+    # Taken from gpu/BUILD.gn
+    # TODO(jmadill): this should be in a shared location
+    if (is_linux && !is_chromecast) {
+      libs = [ "pci" ]
+    }
+  }
+
+  api_names = [
+    "gles2",
+    "gles3",
+    "gles31",
+    "egl",
+  ]
+  target_defines = [
+    "ANGLE_DEQP_GLES2_TESTS",
+    "ANGLE_DEQP_GLES3_TESTS",
+    "ANGLE_DEQP_GLES31_TESTS",
+    "ANGLE_DEQP_EGL_TESTS",
+  ]
+  target_sources = [
+    deqp_gypi.deqp_gles2_sources,
+    deqp_gypi.deqp_gles3_sources,
+    deqp_gypi.deqp_gles31_sources,
+    deqp_gypi.deqp_egl_sources,
+  ]
+
+  foreach(index,
+          [
+            0,
+            1,
+            2,
+            3,
+          ]) {
+    api_name = api_names[index]
+    config_name = "angle_deqp_lib${api_name}_config"
+    config(config_name) {
+      defines = [ target_defines[index] ]
+    }
+
+    shared_library_name = "angle_deqp_lib${api_name}"
+    shared_library(shared_library_name) {
+      deps = [
+        ":angle_deqp_libtester",
+        "//third_party/angle:angle_util",
+      ]
+
+      configs -= deqp_undefine_configs
+      if (is_android) {
+        configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
+      }
+      public_configs = [ ":${config_name}" ]
+
+      sources = rebase_path(target_sources[index], ".", "../..")
+      sources += [
+        "deqp_support/angle_deqp_libtester_main.cpp",
+        "deqp_support/tcuANGLEPlatform.cpp",
+        "deqp_support/tcuANGLEPlatform.h",
+      ]
+    }
+
+    test_name = "angle_deqp_${api_name}_tests"
+    test(test_name) {
+      deps = [
+        ":${shared_library_name}",
+        ":angle_deqp_gtest_support",
+      ]
+
+      # Must be included outside of the source set for the define
+      sources = [
+        "deqp_support/angle_deqp_gtest.cpp",
+      ]
+
+      data = [
+        "deqp_support/deqp_${api_name}_test_expectations.txt",
+        "../../../deqp/src/android/cts/master/${api_name}-master.txt",
+        "../../../deqp/src/data/",
+      ]
+
+      if (is_linux && !is_component_build) {
+        # Set rpath to find *.so files even in a non-component build.
+        configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
+      }
+
+      if (is_android) {
+        use_native_activity = true
+      }
+    }
+  }
+}
diff --git a/src/third_party/angle/src/tests/angle_end2end_tests.gypi b/src/third_party/angle/src/tests/angle_end2end_tests.gypi
new file mode 100644
index 0000000..fe0a604
--- /dev/null
+++ b/src/third_party/angle/src/tests/angle_end2end_tests.gypi
@@ -0,0 +1,162 @@
+# Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This .gypi describes all of the sources and dependencies to build a
+# unified "angle_end2end_tests" target, which contains all of the
+# tests that exercise the ANGLE implementation. It requires a parent
+# target to include this gypi in an executable target containing a
+# gtest harness in a main.cpp.
+
+{
+    # Everything below this is duplicated in the GN build.
+    # If you change anything also change angle/src/tests/BUILD.gn
+    'variables':
+    {
+        'angle_end2end_tests_sources':
+        [
+            '<(angle_path)/src/tests/gl_tests/AtomicCounterBufferTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/BindGeneratesResourceTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/BindUniformLocationTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/BlendMinMaxTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/BlitFramebufferANGLETest.cpp',
+            '<(angle_path)/src/tests/gl_tests/BufferDataTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/BuiltinVariableTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ClearTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ClientArraysTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ColorMaskTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ComputeShaderTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/CopyCompressedTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/CopyTexImageTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/CopyTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/CubeMapTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/DebugMarkerTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/DebugTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/DepthStencilFormatsTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/DiscardFramebufferEXTTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/DrawBuffersTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/DrawElementsTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/DXT1CompressedTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/DXTSRGBCompressedTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ETCTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/FenceSyncTests.cpp',
+            '<(angle_path)/src/tests/gl_tests/FloatingPointSurfaceTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/FramebufferTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/GLSLTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ImageTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/IncompleteTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/IndexBufferOffsetTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/IndexedPointsTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/InstancingTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/LineLoopTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/MaxTextureSizeTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/MipmapTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/MultisampleCompatibilityTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/media/pixel.inl',
+            '<(angle_path)/src/tests/gl_tests/PackUnpackTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/PathRenderingTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/PbufferTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/PBOExtensionTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/PointSpritesTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ProvokingVertexTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ObjectAllocationTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/OcclusionQueriesTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ProgramBinaryTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ProgramInterfaceTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ProgramParameterTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ReadPixelsTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/RendererTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/RobustClientMemoryTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/RobustResourceInitTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/SimpleOperationTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/SixteenBppTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/SRGBFramebufferTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/SRGBTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/StateChangeTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/SwizzleTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/SyncQueriesTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/TextureMultisampleTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/TextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/TimerQueriesTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/TransformFeedbackTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/UniformBufferTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/UniformTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/UnpackAlignmentTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/UnpackRowLength.cpp',
+            '<(angle_path)/src/tests/gl_tests/VertexAttributeTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/ViewportTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/WebGLCompatibilityTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/WebGLFramebufferTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLContextCompatibilityTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLContextSharingTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLQueryContextTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLRobustnessTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLSanityCheckTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLSurfacelessContextTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLSurfaceTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLVulkanEXTTest.cpp',
+            '<(angle_path)/src/tests/test_utils/ANGLETest.cpp',
+            '<(angle_path)/src/tests/test_utils/ANGLETest.h',
+            '<(angle_path)/src/tests/test_utils/angle_test_configs.cpp',
+            '<(angle_path)/src/tests/test_utils/angle_test_configs.h',
+            '<(angle_path)/src/tests/test_utils/angle_test_instantiate.cpp',
+            '<(angle_path)/src/tests/test_utils/angle_test_instantiate.h',
+            '<(angle_path)/src/tests/test_utils/gl_raii.h',
+        ],
+        'angle_end2end_tests_win_sources':
+        [
+            '<(angle_path)/src/tests/gl_tests/D3DImageFormatConversionTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLDeviceTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLStreamTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/EGLSyncControlTest.cpp',
+            # TODO(cwallez) for Linux, requires a portable implementation of threads
+            '<(angle_path)/src/tests/egl_tests/EGLThreadTest.cpp',
+            '<(angle_path)/src/tests/egl_tests/media/yuvtest.inl',
+        ],
+        'angle_end2end_tests_x11_sources':
+        [
+            '<(angle_path)/src/tests/egl_tests/EGLX11VisualTest.cpp',
+        ],
+    },
+    'dependencies':
+    [
+        '<(angle_path)/src/angle.gyp:angle_image_util',
+        # We use the D3D11 config for enabling Debug runtime error logging.
+        '<(angle_path)/src/angle.gyp:libANGLE_d3d11_config',
+        # This lets us filter test configs more intelligently.
+        '<(angle_path)/src/angle.gyp:libANGLE_renderer_config',
+        '<(angle_path)/src/angle.gyp:libEGL',
+        '<(angle_path)/src/angle.gyp:libGLESv2',
+        '<(angle_path)/src/tests/tests.gyp:angle_test_support',
+        '<(angle_path)/util/util.gyp:angle_util',
+    ],
+    'include_dirs':
+    [
+        '<(angle_path)/include',
+        '<(angle_path)/src/tests'
+    ],
+    'sources':
+    [
+        '<@(angle_end2end_tests_sources)',
+    ],
+    'conditions':
+    [
+        ['OS=="win"',
+        {
+            'sources':
+            [
+                '<@(angle_end2end_tests_win_sources)',
+            ],
+        }],
+        ['use_x11==1',
+        {
+            'sources':
+            [
+                '<@(angle_end2end_tests_x11_sources)',
+            ],
+        }],
+    ]
+}
diff --git a/src/third_party/angle/src/tests/angle_end2end_tests_main.cpp b/src/third_party/angle/src/tests/angle_end2end_tests_main.cpp
new file mode 100644
index 0000000..b4b9f02
--- /dev/null
+++ b/src/third_party/angle/src/tests/angle_end2end_tests_main.cpp
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gtest/gtest.h"
+#include "test_utils/ANGLETest.h"
+
+int main(int argc, char** argv)
+{
+    testing::InitGoogleTest(&argc, argv);
+    testing::AddGlobalTestEnvironment(new ANGLETestEnvironment());
+    int rt = RUN_ALL_TESTS();
+    return rt;
+}
diff --git a/src/third_party/angle/src/tests/angle_perftests.gypi b/src/third_party/angle/src/tests/angle_perftests.gypi
new file mode 100644
index 0000000..760f7c8
--- /dev/null
+++ b/src/third_party/angle/src/tests/angle_perftests.gypi
@@ -0,0 +1,81 @@
+# Copyright 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# angle_perftests.gypi:
+#
+# This .gypi describes all of the sources and dependencies to build a
+# unified "angle_perftests" target, which contains all of ANGLE's
+# performance tests (buffer updates, texture updates, draw calls, etc)
+# It requires a parent target to include this gypi in an executable
+# target containing a gtest harness in a main.cpp.
+
+{
+    'variables':
+    {
+        'angle_perf_tests_sources':
+        [
+            '<(angle_path)/src/tests/perf_tests/ANGLEPerfTest.cpp',
+            '<(angle_path)/src/tests/perf_tests/ANGLEPerfTest.h',
+            '<(angle_path)/src/tests/perf_tests/BlitFramebufferPerf.cpp',
+            '<(angle_path)/src/tests/perf_tests/BindingPerf.cpp',
+            '<(angle_path)/src/tests/perf_tests/BitSetIteratorPerf.cpp',
+            '<(angle_path)/src/tests/perf_tests/BufferSubData.cpp',
+            '<(angle_path)/src/tests/perf_tests/DrawCallPerf.cpp',
+            '<(angle_path)/src/tests/perf_tests/DrawCallPerfParams.cpp',
+            '<(angle_path)/src/tests/perf_tests/DrawCallPerfParams.h',
+            '<(angle_path)/src/tests/perf_tests/DynamicPromotionPerfTest.cpp',
+            '<(angle_path)/src/tests/perf_tests/EGLInitializePerf.cpp',
+            '<(angle_path)/src/tests/perf_tests/IndexConversionPerf.cpp',
+            '<(angle_path)/src/tests/perf_tests/InstancingPerf.cpp',
+            '<(angle_path)/src/tests/perf_tests/InterleavedAttributeData.cpp',
+            '<(angle_path)/src/tests/perf_tests/LinkProgramPerfTest.cpp',
+            '<(angle_path)/src/tests/perf_tests/PointSprites.cpp',
+            '<(angle_path)/src/tests/perf_tests/TexSubImage.cpp',
+            '<(angle_path)/src/tests/perf_tests/TextureSampling.cpp',
+            '<(angle_path)/src/tests/perf_tests/TexturesPerf.cpp',
+            '<(angle_path)/src/tests/perf_tests/UniformsPerf.cpp',
+            '<(angle_path)/src/tests/perf_tests/third_party/perf/perf_test.cc',
+            '<(angle_path)/src/tests/perf_tests/third_party/perf/perf_test.h',
+            '<(angle_path)/src/tests/test_utils/angle_test_configs.cpp',
+            '<(angle_path)/src/tests/test_utils/angle_test_configs.h',
+            '<(angle_path)/src/tests/test_utils/angle_test_instantiate.cpp',
+            '<(angle_path)/src/tests/test_utils/angle_test_instantiate.h',
+            '<(angle_path)/src/tests/test_utils/draw_call_perf_utils.cpp',
+            '<(angle_path)/src/tests/test_utils/draw_call_perf_utils.h',
+        ],
+        'angle_perf_tests_win_sources':
+        [
+            '<(angle_path)/src/tests/perf_tests/IndexDataManagerTest.cpp',
+        ]
+    },
+    # Everything below (except WinRT-related config) must be also maintained for GN.
+    # If you change anything below, also update angle/src/tests/BUILD.gn.
+    'dependencies':
+    [
+        '<(angle_path)/src/angle.gyp:angle_common',
+        '<(angle_path)/src/angle.gyp:libGLESv2_static',
+        '<(angle_path)/src/angle.gyp:libEGL_static',
+        '<(angle_path)/src/tests/tests.gyp:angle_test_support',
+        '<(angle_path)/util/util.gyp:angle_util_static',
+    ],
+    'include_dirs':
+    [
+        '<(angle_path)/include',
+        '<(angle_path)/src/tests'
+    ],
+    'sources':
+    [
+        '<@(angle_perf_tests_sources)',
+    ],
+    'conditions':
+    [
+        ['OS=="win"',
+        {
+            'sources':
+            [
+                '<@(angle_perf_tests_win_sources)',
+            ],
+        }],
+    ]
+}
diff --git a/src/third_party/angle/src/tests/angle_perftests_main.cpp b/src/third_party/angle/src/tests/angle_perftests_main.cpp
new file mode 100644
index 0000000..20f8dac
--- /dev/null
+++ b/src/third_party/angle/src/tests/angle_perftests_main.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_perftests_main.cpp
+//   Entry point for the gtest-based performance tests.
+//
+
+#include <gtest/gtest.h>
+
+int main(int argc, char **argv)
+{
+    testing::InitGoogleTest(&argc, argv);
+    testing::AddGlobalTestEnvironment(new testing::Environment());
+    int rt = RUN_ALL_TESTS();
+    return rt;
+}
diff --git a/src/third_party/angle/src/tests/angle_unittests.gypi b/src/third_party/angle/src/tests/angle_unittests.gypi
new file mode 100644
index 0000000..0c0199c
--- /dev/null
+++ b/src/third_party/angle/src/tests/angle_unittests.gypi
@@ -0,0 +1,171 @@
+# Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This .gypi describes all of the sources and dependencies to build a
+# unified "angle_unittests" target, which contains all of ANGLE's
+# tests that don't require a fully functional ANGLE in order to run
+# (compiler tests, preprocessor tests, etc.). It requires a parent
+# target to include this gypi in an executable target containing a
+# gtest harness in a main.cpp.
+
+{
+    'variables':
+    {
+        'angle_unittests_sources':
+        [
+            '<(angle_path)/src/common/Optional_unittest.cpp',
+            '<(angle_path)/src/common/bitset_utils_unittest.cpp',
+            '<(angle_path)/src/common/mathutil_unittest.cpp',
+            '<(angle_path)/src/common/matrix_utils_unittest.cpp',
+            '<(angle_path)/src/common/string_utils_unittest.cpp',
+            '<(angle_path)/src/common/utilities_unittest.cpp',
+            '<(angle_path)/src/common/vector_utils_unittest.cpp',
+            '<(angle_path)/src/gpu_info_util/SystemInfo_unittest.cpp',
+            '<(angle_path)/src/libANGLE/BinaryStream_unittest.cpp',
+            '<(angle_path)/src/libANGLE/Config_unittest.cpp',
+            '<(angle_path)/src/libANGLE/Fence_unittest.cpp',
+            '<(angle_path)/src/libANGLE/HandleAllocator_unittest.cpp',
+            '<(angle_path)/src/libANGLE/HandleRangeAllocator_unittest.cpp',
+            '<(angle_path)/src/libANGLE/Image_unittest.cpp',
+            '<(angle_path)/src/libANGLE/ImageIndexIterator_unittest.cpp',
+            '<(angle_path)/src/libANGLE/Program_unittest.cpp',
+            '<(angle_path)/src/libANGLE/ResourceManager_unittest.cpp',
+            '<(angle_path)/src/libANGLE/Surface_unittest.cpp',
+            '<(angle_path)/src/libANGLE/TransformFeedback_unittest.cpp',
+            '<(angle_path)/src/libANGLE/VaryingPacking_unittest.cpp',
+            '<(angle_path)/src/libANGLE/VertexArray_unittest.cpp',
+            '<(angle_path)/src/libANGLE/WorkerThread_unittest.cpp',
+            '<(angle_path)/src/libANGLE/renderer/BufferImpl_mock.h',
+            '<(angle_path)/src/libANGLE/renderer/FramebufferImpl_mock.h',
+            '<(angle_path)/src/libANGLE/renderer/ProgramImpl_mock.h',
+            '<(angle_path)/src/libANGLE/renderer/RenderbufferImpl_mock.h',
+            '<(angle_path)/src/libANGLE/renderer/ImageImpl_mock.h',
+            '<(angle_path)/src/libANGLE/renderer/TextureImpl_mock.h',
+            '<(angle_path)/src/libANGLE/renderer/TransformFeedbackImpl_mock.h',
+            '<(angle_path)/src/libANGLE/signal_utils_unittest.cpp',
+            '<(angle_path)/src/libANGLE/validationES_unittest.cpp',
+            '<(angle_path)/src/tests/angle_unittests_utils.h',
+            '<(angle_path)/src/tests/compiler_tests/API_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/AppendixALimitations_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/CollectVariables_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ConstantFolding_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ConstantFoldingOverflow_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ConstructCompiler_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/DebugShaderPrecision_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/EmulateGLFragColorBroadcast_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ExpressionLimit_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/EXT_YUV_target_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/FloatLex_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/FragDepth_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/GLSLCompatibilityOutput_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/IntermNode_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/NV_draw_buffers_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/Pack_Unpack_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/PruneEmptyDeclarations_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/PrunePureLiteralStatements_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/PruneUnusedFunctions_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/QualificationOrderESSL31_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/QualificationOrder_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/RecordConstantPrecision_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/RemovePow_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/SamplerMultisample_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ShaderExtension_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ShaderImage_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ShaderValidation_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ShaderVariable_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/ShCompile_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/TypeTracking_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/VariablePacker_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/WEBGL_multiview_test.cpp',
+            '<(angle_path)/src/tests/compiler_tests/WorkGroupSize_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/char_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/comment_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/define_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/error_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/extension_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/identifier_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/if_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/input_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/location_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/MockDiagnostics.h',
+            '<(angle_path)/src/tests/preprocessor_tests/MockDirectiveHandler.h',
+            '<(angle_path)/src/tests/preprocessor_tests/number_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/operator_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/pragma_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/PreprocessorTest.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/PreprocessorTest.h',
+            '<(angle_path)/src/tests/preprocessor_tests/space_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/token_test.cpp',
+            '<(angle_path)/src/tests/preprocessor_tests/version_test.cpp',
+            '<(angle_path)/src/tests/test_utils/compiler_test.cpp',
+            '<(angle_path)/src/tests/test_utils/compiler_test.h',
+            '<(angle_path)/src/tests/test_utils/ConstantFoldingTest.h',
+            '<(angle_path)/src/tests/test_utils/ConstantFoldingTest.cpp',
+            '<(angle_path)/src/tests/test_utils/ShaderCompileTreeTest.h',
+            '<(angle_path)/src/tests/test_utils/ShaderCompileTreeTest.cpp',
+        ],
+        # TODO(jmadill): should probably call this windows sources
+        'angle_unittests_hlsl_sources':
+        [
+            '<(angle_path)/src/tests/compiler_tests/UnrollFlatten_test.cpp',
+        ],
+    },
+    # Everything below this but the WinRT configuration is duplicated in the GN build.
+    # If you change anything also change angle/src/tests/BUILD.gn
+    'dependencies':
+    [
+        '<(angle_path)/src/angle.gyp:libANGLE',
+        '<(angle_path)/src/angle.gyp:preprocessor',
+        '<(angle_path)/src/angle.gyp:translator',
+        '<(angle_path)/src/tests/tests.gyp:angle_test_support',
+    ],
+    'include_dirs':
+    [
+        '<(angle_path)/include',
+        '<(angle_path)/src',
+    ],
+    'sources':
+    [
+        '<@(angle_unittests_sources)',
+    ],
+    'conditions':
+    [
+        ['angle_build_winrt==1',
+        {
+            'sources':
+            [
+                '<(angle_path)/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp',
+                '<(angle_path)/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp',
+            ],
+            'defines':
+            [
+                'ANGLE_ENABLE_D3D11',
+            ],
+            'msvs_settings':
+            {
+                'VCLinkerTool':
+                {
+                    'AdditionalDependencies':
+                    [
+                        'runtimeobject.lib',
+                    ],
+                },
+            },
+        }],
+        ['OS=="win"',
+        {
+            # TODO(cwallez): make this angle_enable_hlsl instead (requires gyp file refactoring)
+            'defines':
+            [
+                'ANGLE_ENABLE_HLSL',
+            ],
+            'sources':
+            [
+                '<@(angle_unittests_hlsl_sources)',
+            ],
+        }],
+    ],
+}
diff --git a/src/third_party/angle/src/tests/angle_unittests_main.cpp b/src/third_party/angle/src/tests/angle_unittests_main.cpp
new file mode 100644
index 0000000..1b44dbb
--- /dev/null
+++ b/src/third_party/angle/src/tests/angle_unittests_main.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+class CompilerTestEnvironment : public testing::Environment
+{
+  public:
+    void SetUp() override
+    {
+        if (!sh::Initialize())
+        {
+            FAIL() << "Failed to initialize the compiler.";
+        }
+    }
+
+    void TearDown() override
+    {
+        if (!sh::Finalize())
+        {
+            FAIL() << "Failed to finalize the compiler.";
+        }
+    }
+};
+
+int main(int argc, char** argv)
+{
+    testing::InitGoogleTest(&argc, argv);
+    testing::AddGlobalTestEnvironment(new CompilerTestEnvironment());
+    int rt = RUN_ALL_TESTS();
+    return rt;
+}
diff --git a/src/third_party/angle/src/tests/angle_unittests_utils.h b/src/third_party/angle/src/tests/angle_unittests_utils.h
new file mode 100644
index 0000000..c86ee39
--- /dev/null
+++ b/src/third_party/angle/src/tests/angle_unittests_utils.h
@@ -0,0 +1,121 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_unittests_utils.h:
+//   Helpers for mocking and unit testing.
+
+#ifndef TESTS_ANGLE_UNITTESTS_UTILS_H_
+#define TESTS_ANGLE_UNITTESTS_UTILS_H_
+
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace rx
+{
+
+// Useful when mocking a part of the GLImplFactory class
+class NullFactory : public GLImplFactory
+{
+  public:
+    NullFactory() {}
+
+    // Shader creation
+    CompilerImpl *createCompiler() override { return nullptr; }
+    ShaderImpl *createShader(const gl::ShaderState &data) override { return nullptr; }
+    ProgramImpl *createProgram(const gl::ProgramState &data) override { return nullptr; }
+
+    // Framebuffer creation
+    FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override
+    {
+        return nullptr;
+    }
+
+    // Texture creation
+    TextureImpl *createTexture(const gl::TextureState &data) override { return nullptr; }
+
+    // Renderbuffer creation
+    RenderbufferImpl *createRenderbuffer() override { return nullptr; }
+
+    // Buffer creation
+    BufferImpl *createBuffer(const gl::BufferState &state) override { return nullptr; }
+
+    // Vertex Array creation
+    VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override
+    {
+        return nullptr;
+    }
+
+    // Query and Fence creation
+    QueryImpl *createQuery(GLenum type) override { return nullptr; }
+    FenceNVImpl *createFenceNV() override { return nullptr; }
+    FenceSyncImpl *createFenceSync() override { return nullptr; }
+
+    // Transform Feedback creation
+    TransformFeedbackImpl *createTransformFeedback(const gl::TransformFeedbackState &state) override
+    {
+        return nullptr;
+    }
+
+    // Sampler object creation
+    SamplerImpl *createSampler() override { return nullptr; }
+
+    std::vector<PathImpl *> createPaths(GLsizei range) override
+    {
+        return std::vector<PathImpl *>();
+    }
+};
+
+// A class with all the factory methods mocked.
+class MockGLFactory : public GLImplFactory
+{
+  public:
+    MOCK_METHOD1(createContext, ContextImpl *(const gl::ContextState &));
+    MOCK_METHOD0(createCompiler, CompilerImpl *());
+    MOCK_METHOD1(createShader, ShaderImpl *(const gl::ShaderState &));
+    MOCK_METHOD1(createProgram, ProgramImpl *(const gl::ProgramState &));
+    MOCK_METHOD1(createFramebuffer, FramebufferImpl *(const gl::FramebufferState &));
+    MOCK_METHOD1(createTexture, TextureImpl *(const gl::TextureState &));
+    MOCK_METHOD0(createRenderbuffer, RenderbufferImpl *());
+    MOCK_METHOD1(createBuffer, BufferImpl *(const gl::BufferState &));
+    MOCK_METHOD1(createVertexArray, VertexArrayImpl *(const gl::VertexArrayState &));
+    MOCK_METHOD1(createQuery, QueryImpl *(GLenum type));
+    MOCK_METHOD0(createFenceNV, FenceNVImpl *());
+    MOCK_METHOD0(createFenceSync, FenceSyncImpl *());
+    MOCK_METHOD1(createTransformFeedback,
+                 TransformFeedbackImpl *(const gl::TransformFeedbackState &));
+    MOCK_METHOD0(createSampler, SamplerImpl *());
+    MOCK_METHOD1(createPaths, std::vector<PathImpl *>(GLsizei));
+};
+
+class MockEGLFactory : public EGLImplFactory
+{
+  public:
+    MOCK_METHOD3(createWindowSurface,
+                 SurfaceImpl *(const egl::SurfaceState &,
+                               EGLNativeWindowType,
+                               const egl::AttributeMap &));
+    MOCK_METHOD2(createPbufferSurface,
+                 SurfaceImpl *(const egl::SurfaceState &, const egl::AttributeMap &));
+    MOCK_METHOD4(createPbufferFromClientBuffer,
+                 SurfaceImpl *(const egl::SurfaceState &,
+                               EGLenum,
+                               EGLClientBuffer,
+                               const egl::AttributeMap &));
+    MOCK_METHOD3(createPixmapSurface,
+                 SurfaceImpl *(const egl::SurfaceState &,
+                               NativePixmapType,
+                               const egl::AttributeMap &));
+    MOCK_METHOD3(createImage,
+                 ImageImpl *(const egl::ImageState &, EGLenum, const egl::AttributeMap &));
+    MOCK_METHOD1(createContext, ContextImpl *(const gl::ContextState &));
+    MOCK_METHOD2(createStreamProducerD3DTextureNV12,
+                 StreamProducerImpl *(egl::Stream::ConsumerType, const egl::AttributeMap &));
+};
+
+}  // namespace rx
+
+#endif // TESTS_ANGLE_UNITTESTS_UTILS_H_
diff --git a/src/third_party/angle/src/tests/angle_white_box_tests.gypi b/src/third_party/angle/src/tests/angle_white_box_tests.gypi
new file mode 100644
index 0000000..28c7a45
--- /dev/null
+++ b/src/third_party/angle/src/tests/angle_white_box_tests.gypi
@@ -0,0 +1,61 @@
+# Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This .gypi describes all of the sources and dependencies to build a
+# unified "angle_white_box_tests" target, which contains all of the
+# tests that exercise the ANGLE implementation. It requires a parent
+# target to include this gypi in an executable target containing a
+# gtest harness in a main.cpp.
+
+{
+    # Everything below this is duplicated in the GN build.
+    # If you change anything also change angle/src/tests/BUILD.gn
+    'variables':
+    {
+        'angle_white_box_tests_sources':
+        [
+            '<(angle_path)/src/tests/util_tests/PrintSystemInfoTest.cpp',
+            '<(angle_path)/src/tests/test_utils/angle_test_configs.cpp',
+            '<(angle_path)/src/tests/test_utils/angle_test_configs.h',
+            '<(angle_path)/src/tests/test_utils/angle_test_instantiate.cpp',
+            '<(angle_path)/src/tests/test_utils/angle_test_instantiate.h',
+            '<(angle_path)/src/tests/test_utils/ANGLETest.cpp',
+            '<(angle_path)/src/tests/test_utils/ANGLETest.h',
+            '<(angle_path)/src/tests/test_utils/gl_raii.h',
+        ],
+        'angle_white_box_tests_win_sources':
+        [
+            '<(angle_path)/src/tests/gl_tests/D3D11EmulatedIndexedBufferTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/D3D11FormatTablesTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/D3DTextureTest.cpp',
+        ],
+    },
+    'dependencies':
+    [
+        '<(angle_path)/src/angle.gyp:libGLESv2_static',
+        '<(angle_path)/src/angle.gyp:libEGL_static',
+        '<(angle_path)/src/tests/tests.gyp:angle_test_support',
+        '<(angle_path)/util/util.gyp:angle_util_static',
+    ],
+    'include_dirs':
+    [
+        '<(angle_path)/include',
+        '<(angle_path)/src/tests'
+    ],
+    'sources':
+    [
+        '<@(angle_white_box_tests_sources)',
+    ],
+    'conditions':
+    [
+        ['OS=="win"',
+        {
+            'sources':
+            [
+                '<@(angle_white_box_tests_win_sources)',
+            ],
+        }],
+    ]
+}
diff --git a/src/third_party/angle/src/tests/angle_white_box_tests_main.cpp b/src/third_party/angle/src/tests/angle_white_box_tests_main.cpp
new file mode 100644
index 0000000..f503627
--- /dev/null
+++ b/src/third_party/angle/src/tests/angle_white_box_tests_main.cpp
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gtest/gtest.h"
+#include "test_utils/ANGLETest.h"
+
+int main(int argc, char **argv)
+{
+    testing::InitGoogleTest(&argc, argv);
+    testing::AddGlobalTestEnvironment(new ANGLETestEnvironment());
+    int rt = RUN_ALL_TESTS();
+    return rt;
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/API_test.cpp b/src/third_party/angle/src/tests/compiler_tests/API_test.cpp
new file mode 100644
index 0000000..090e31e
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/API_test.cpp
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// API_test.cpp:
+//   Some tests for the compiler API.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+TEST(APITest, CompareShBuiltInResources)
+{
+    ShBuiltInResources a_resources;
+    memset(&a_resources, 88, sizeof(a_resources));
+    sh::InitBuiltInResources(&a_resources);
+
+    ShBuiltInResources b_resources;
+    memset(&b_resources, 77, sizeof(b_resources));
+    sh::InitBuiltInResources(&b_resources);
+
+    EXPECT_TRUE(memcmp(&a_resources, &b_resources, sizeof(a_resources)) == 0);
+}
+
diff --git a/src/third_party/angle/src/tests/compiler_tests/AppendixALimitations_test.cpp b/src/third_party/angle/src/tests/compiler_tests/AppendixALimitations_test.cpp
new file mode 100644
index 0000000..a14b249
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/AppendixALimitations_test.cpp
@@ -0,0 +1,135 @@
+//
+// Copyright (c) 2017 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.
+//
+// AppendixALimitations_test.cpp:
+//   Tests for validating ESSL 1.00 Appendix A limitations.
+//
+
+#include "gtest/gtest.h"
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+
+using namespace sh;
+
+class AppendixALimitationsTest : public ShaderCompileTreeTest
+{
+  public:
+    AppendixALimitationsTest() {}
+  protected:
+    ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_WEBGL_SPEC; }
+};
+
+// Test an invalid shader where a for loop index is used as an out parameter.
+TEST_F(AppendixALimitationsTest, IndexAsFunctionOutParameter)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void fun(out int a)\n"
+        "{\n"
+        "   a = 2;\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "    for (int i = 0; i < 2; ++i)\n"
+        "    {\n"
+        "        fun(i);\n"
+        "    }\n"
+        "    gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test an invalid shader where a for loop index is used as an inout parameter.
+TEST_F(AppendixALimitationsTest, IndexAsFunctionInOutParameter)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void fun(int b, inout int a)\n"
+        "{\n"
+        "   a += b;\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "    for (int i = 0; i < 2; ++i)\n"
+        "    {\n"
+        "        fun(2, i);\n"
+        "    }\n"
+        "    gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test a valid shader where a for loop index is used as an in parameter in a function that also has
+// an out parameter.
+TEST_F(AppendixALimitationsTest, IndexAsFunctionInParameter)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void fun(int b, inout int a)\n"
+        "{\n"
+        "   a += b;\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "    for (int i = 0; i < 2; ++i)\n"
+        "    {\n"
+        "        int a = 1;"
+        "        fun(i, a);\n"
+        "    }\n"
+        "    gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test an invalid shader where a for loop index is used as a target of assignment.
+TEST_F(AppendixALimitationsTest, IndexAsTargetOfAssignment)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    for (int i = 0; i < 2; ++i)\n"
+        "    {\n"
+        "        i = 2;\n"
+        "    }\n"
+        "    gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test an invalid shader where a for loop index is incremented inside the loop.
+TEST_F(AppendixALimitationsTest, IndexIncrementedInLoopBody)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    for (int i = 0; i < 2; ++i)\n"
+        "    {\n"
+        "        ++i;\n"
+        "    }\n"
+        "    gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/CollectVariables_test.cpp b/src/third_party/angle/src/tests/compiler_tests/CollectVariables_test.cpp
new file mode 100644
index 0000000..228223b
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/CollectVariables_test.cpp
@@ -0,0 +1,802 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CollectVariables_test.cpp:
+//   Some tests for shader inspection
+//
+
+#include <memory>
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/TranslatorGLSL.h"
+
+using namespace sh;
+
+#define EXPECT_GLENUM_EQ(expected, actual) \
+    EXPECT_EQ(static_cast<::GLenum>(expected), static_cast<::GLenum>(actual))
+
+class CollectVariablesTest : public testing::Test
+{
+  public:
+    CollectVariablesTest(::GLenum shaderType) : mShaderType(shaderType) {}
+
+  protected:
+    void SetUp() override
+    {
+        ShBuiltInResources resources;
+        InitBuiltInResources(&resources);
+        resources.MaxDrawBuffers = 8;
+
+        initTranslator(resources);
+    }
+
+    void initTranslator(const ShBuiltInResources &resources)
+    {
+        mTranslator.reset(
+            new TranslatorGLSL(mShaderType, SH_GLES3_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT));
+        ASSERT_TRUE(mTranslator->Init(resources));
+    }
+
+    // For use in the gl_DepthRange tests.
+    void validateDepthRangeShader(const std::string &shaderString)
+    {
+        const char *shaderStrings[] = { shaderString.c_str() };
+        ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
+
+        const std::vector<Uniform> &uniforms = mTranslator->getUniforms();
+        ASSERT_EQ(1u, uniforms.size());
+
+        const Uniform &uniform = uniforms[0];
+        EXPECT_EQ("gl_DepthRange", uniform.name);
+        ASSERT_TRUE(uniform.isStruct());
+        ASSERT_EQ(3u, uniform.fields.size());
+
+        bool foundNear = false;
+        bool foundFar = false;
+        bool foundDiff = false;
+
+        for (const auto &field : uniform.fields)
+        {
+            if (field.name == "near")
+            {
+                EXPECT_FALSE(foundNear);
+                foundNear = true;
+            }
+            else if (field.name == "far")
+            {
+                EXPECT_FALSE(foundFar);
+                foundFar = true;
+            }
+            else
+            {
+                ASSERT_EQ("diff", field.name);
+                EXPECT_FALSE(foundDiff);
+                foundDiff = true;
+            }
+
+            EXPECT_EQ(0u, field.arraySize);
+            EXPECT_FALSE(field.isStruct());
+            EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
+            EXPECT_TRUE(field.staticUse);
+            EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
+        }
+
+        EXPECT_TRUE(foundNear && foundFar && foundDiff);
+    }
+
+    // For use in tests for output varibles.
+    void validateOutputVariableForShader(const std::string &shaderString,
+                                         unsigned int varIndex,
+                                         const char *varName,
+                                         const OutputVariable **outResult)
+    {
+        const char *shaderStrings[] = {shaderString.c_str()};
+        ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES))
+            << mTranslator->getInfoSink().info.str();
+
+        const auto &outputVariables = mTranslator->getOutputVariables();
+        ASSERT_LT(varIndex, outputVariables.size());
+        const OutputVariable &outputVariable = outputVariables[varIndex];
+        EXPECT_EQ(-1, outputVariable.location);
+        EXPECT_TRUE(outputVariable.staticUse);
+        EXPECT_EQ(varName, outputVariable.name);
+        *outResult = &outputVariable;
+    }
+
+    void compile(const std::string &shaderString)
+    {
+        const char *shaderStrings[] = {shaderString.c_str()};
+        ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
+    }
+
+    ::GLenum mShaderType;
+    std::unique_ptr<TranslatorGLSL> mTranslator;
+};
+
+class CollectVertexVariablesTest : public CollectVariablesTest
+{
+  public:
+    CollectVertexVariablesTest() : CollectVariablesTest(GL_VERTEX_SHADER) {}
+};
+
+class CollectFragmentVariablesTest : public CollectVariablesTest
+{
+  public:
+      CollectFragmentVariablesTest() : CollectVariablesTest(GL_FRAGMENT_SHADER) {}
+};
+
+TEST_F(CollectFragmentVariablesTest, SimpleOutputVar)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 out_fragColor;\n"
+        "void main() {\n"
+        "   out_fragColor = vec4(1.0);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const auto &outputVariables = mTranslator->getOutputVariables();
+    ASSERT_EQ(1u, outputVariables.size());
+
+    const OutputVariable &outputVariable = outputVariables[0];
+
+    EXPECT_EQ(0u, outputVariable.arraySize);
+    EXPECT_EQ(-1, outputVariable.location);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable.precision);
+    EXPECT_TRUE(outputVariable.staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable.type);
+    EXPECT_EQ("out_fragColor", outputVariable.name);
+}
+
+TEST_F(CollectFragmentVariablesTest, LocationOutputVar)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(location=5) out vec4 out_fragColor;\n"
+        "void main() {\n"
+        "   out_fragColor = vec4(1.0);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const auto &outputVariables = mTranslator->getOutputVariables();
+    ASSERT_EQ(1u, outputVariables.size());
+
+    const OutputVariable &outputVariable = outputVariables[0];
+
+    EXPECT_EQ(0u, outputVariable.arraySize);
+    EXPECT_EQ(5, outputVariable.location);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable.precision);
+    EXPECT_TRUE(outputVariable.staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable.type);
+    EXPECT_EQ("out_fragColor", outputVariable.name);
+}
+
+TEST_F(CollectVertexVariablesTest, LocationAttribute)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "layout(location=5) in vec4 in_Position;\n"
+        "void main() {\n"
+        "   gl_Position = in_Position;\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const std::vector<Attribute> &attributes = mTranslator->getAttributes();
+    ASSERT_EQ(1u, attributes.size());
+
+    const Attribute &attribute = attributes[0];
+
+    EXPECT_EQ(0u, attribute.arraySize);
+    EXPECT_EQ(5, attribute.location);
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, attribute.precision);
+    EXPECT_TRUE(attribute.staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, attribute.type);
+    EXPECT_EQ("in_Position", attribute.name);
+}
+
+TEST_F(CollectVertexVariablesTest, SimpleInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "uniform b {\n"
+        "  float f;\n"
+        "};"
+        "void main() {\n"
+        "   gl_Position = vec4(f, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
+    ASSERT_EQ(1u, interfaceBlocks.size());
+
+    const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
+
+    EXPECT_EQ(0u, interfaceBlock.arraySize);
+    EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
+    EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
+    EXPECT_EQ("b", interfaceBlock.name);
+    EXPECT_TRUE(interfaceBlock.staticUse);
+
+    ASSERT_EQ(1u, interfaceBlock.fields.size());
+
+    const InterfaceBlockField &field = interfaceBlock.fields[0];
+
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
+    EXPECT_TRUE(field.staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
+    EXPECT_EQ("f", field.name);
+    EXPECT_FALSE(field.isRowMajorLayout);
+    EXPECT_TRUE(field.fields.empty());
+}
+
+TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "uniform b {\n"
+        "  float f;\n"
+        "} blockInstance;"
+        "void main() {\n"
+        "   gl_Position = vec4(blockInstance.f, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
+    ASSERT_EQ(1u, interfaceBlocks.size());
+
+    const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
+
+    EXPECT_EQ(0u, interfaceBlock.arraySize);
+    EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
+    EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
+    EXPECT_EQ("b", interfaceBlock.name);
+    EXPECT_EQ("blockInstance", interfaceBlock.instanceName);
+    EXPECT_TRUE(interfaceBlock.staticUse);
+
+    ASSERT_EQ(1u, interfaceBlock.fields.size());
+
+    const InterfaceBlockField &field = interfaceBlock.fields[0];
+
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
+    EXPECT_TRUE(field.staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
+    EXPECT_EQ("f", field.name);
+    EXPECT_FALSE(field.isRowMajorLayout);
+    EXPECT_TRUE(field.fields.empty());
+}
+
+TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "struct st { float f; };"
+        "uniform b {\n"
+        "  st s;\n"
+        "};"
+        "void main() {\n"
+        "   gl_Position = vec4(s.f, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
+    ASSERT_EQ(1u, interfaceBlocks.size());
+
+    const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
+
+    EXPECT_EQ(0u, interfaceBlock.arraySize);
+    EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
+    EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
+    EXPECT_EQ("b", interfaceBlock.name);
+    EXPECT_TRUE(interfaceBlock.staticUse);
+
+    ASSERT_EQ(1u, interfaceBlock.fields.size());
+
+    const InterfaceBlockField &field = interfaceBlock.fields[0];
+
+    EXPECT_TRUE(field.isStruct());
+    EXPECT_TRUE(field.staticUse);
+    EXPECT_EQ("s", field.name);
+    EXPECT_FALSE(field.isRowMajorLayout);
+
+    const ShaderVariable &member = field.fields[0];
+
+    // NOTE: we don't currently mark struct members as statically used or not
+    EXPECT_FALSE(member.isStruct());
+    EXPECT_EQ("f", member.name);
+    EXPECT_GLENUM_EQ(GL_FLOAT, member.type);
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
+}
+
+TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "struct st { float f; };"
+        "uniform b {\n"
+        "  st s;\n"
+        "} instanceName;"
+        "void main() {\n"
+        "   gl_Position = vec4(instanceName.s.f, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
+    ASSERT_EQ(1u, interfaceBlocks.size());
+
+    const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
+
+    EXPECT_EQ(0u, interfaceBlock.arraySize);
+    EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
+    EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
+    EXPECT_EQ("b", interfaceBlock.name);
+    EXPECT_EQ("instanceName", interfaceBlock.instanceName);
+    EXPECT_TRUE(interfaceBlock.staticUse);
+
+    ASSERT_EQ(1u, interfaceBlock.fields.size());
+
+    const InterfaceBlockField &field = interfaceBlock.fields[0];
+
+    EXPECT_TRUE(field.isStruct());
+    EXPECT_TRUE(field.staticUse);
+    EXPECT_EQ("s", field.name);
+    EXPECT_FALSE(field.isRowMajorLayout);
+
+    const ShaderVariable &member = field.fields[0];
+
+    // NOTE: we don't currently mark struct members as statically used or not
+    EXPECT_FALSE(member.isStruct());
+    EXPECT_EQ("f", member.name);
+    EXPECT_GLENUM_EQ(GL_FLOAT, member.type);
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
+}
+
+TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "struct st { mat2 m; };"
+        "layout(row_major) uniform b {\n"
+        "  st s;\n"
+        "};"
+        "void main() {\n"
+        "   gl_Position = vec4(s.m);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
+    ASSERT_EQ(1u, interfaceBlocks.size());
+
+    const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
+
+    EXPECT_EQ(0u, interfaceBlock.arraySize);
+    EXPECT_TRUE(interfaceBlock.isRowMajorLayout);
+    EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
+    EXPECT_EQ("b", interfaceBlock.name);
+    EXPECT_TRUE(interfaceBlock.staticUse);
+
+    ASSERT_EQ(1u, interfaceBlock.fields.size());
+
+    const InterfaceBlockField &field = interfaceBlock.fields[0];
+
+    EXPECT_TRUE(field.isStruct());
+    EXPECT_TRUE(field.staticUse);
+    EXPECT_EQ("s", field.name);
+    EXPECT_TRUE(field.isRowMajorLayout);
+
+    const ShaderVariable &member = field.fields[0];
+
+    // NOTE: we don't currently mark struct members as statically used or not
+    EXPECT_FALSE(member.isStruct());
+    EXPECT_EQ("m", member.name);
+    EXPECT_GLENUM_EQ(GL_FLOAT_MAT2, member.type);
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
+}
+
+TEST_F(CollectVertexVariablesTest, VaryingInterpolation)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "centroid out float vary;\n"
+        "void main() {\n"
+        "   gl_Position = vec4(1.0);\n"
+        "   vary = 1.0;\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const std::vector<Varying> &varyings = mTranslator->getVaryings();
+    ASSERT_EQ(2u, varyings.size());
+
+    const Varying *varying = &varyings[0];
+
+    if (varying->name == "gl_Position")
+    {
+        varying = &varyings[1];
+    }
+
+    EXPECT_EQ(0u, varying->arraySize);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, varying->precision);
+    EXPECT_TRUE(varying->staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT, varying->type);
+    EXPECT_EQ("vary", varying->name);
+    EXPECT_EQ(INTERPOLATION_CENTROID, varying->interpolation);
+}
+
+// Test for builtin uniform "gl_DepthRange" (Vertex shader)
+TEST_F(CollectVertexVariablesTest, DepthRange)
+{
+    const std::string &shaderString =
+        "attribute vec4 position;\n"
+        "void main() {\n"
+        "   gl_Position = position + vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1.0);\n"
+        "}\n";
+
+    validateDepthRangeShader(shaderString);
+}
+
+// Test for builtin uniform "gl_DepthRange" (Fragment shader)
+TEST_F(CollectFragmentVariablesTest, DepthRange)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1.0);\n"
+        "}\n";
+
+    validateDepthRangeShader(shaderString);
+}
+
+// Test that gl_FragColor built-in usage in ESSL1 fragment shader is reflected in the output
+// variables list.
+TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragColor)
+{
+    const std::string &fragColorShader =
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    const OutputVariable *outputVariable = nullptr;
+    validateOutputVariableForShader(fragColorShader, 0u, "gl_FragColor", &outputVariable);
+    ASSERT_NE(outputVariable, nullptr);
+    EXPECT_EQ(0u, outputVariable->arraySize);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
+}
+
+// Test that gl_FragData built-in usage in ESSL1 fragment shader is reflected in the output
+// variables list.
+TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragData)
+{
+    const std::string &fragDataShader =
+        "#extension GL_EXT_draw_buffers : require\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   gl_FragData[0] = vec4(1.0);\n"
+        "   gl_FragData[1] = vec4(0.5);\n"
+        "}\n";
+
+    ShBuiltInResources resources       = mTranslator->getResources();
+    resources.EXT_draw_buffers         = 1;
+    const unsigned int kMaxDrawBuffers = 3u;
+    resources.MaxDrawBuffers = kMaxDrawBuffers;
+    initTranslator(resources);
+
+    const OutputVariable *outputVariable = nullptr;
+    validateOutputVariableForShader(fragDataShader, 0u, "gl_FragData", &outputVariable);
+    ASSERT_NE(outputVariable, nullptr);
+    EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySize);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
+}
+
+// Test that gl_FragDataEXT built-in usage in ESSL1 fragment shader is reflected in the output
+// variables list. Also test that the precision is mediump.
+TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthMediump)
+{
+    const std::string &fragDepthShader =
+        "#extension GL_EXT_frag_depth : require\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   gl_FragDepthEXT = 0.7;"
+        "}\n";
+
+    ShBuiltInResources resources = mTranslator->getResources();
+    resources.EXT_frag_depth = 1;
+    initTranslator(resources);
+
+    const OutputVariable *outputVariable = nullptr;
+    validateOutputVariableForShader(fragDepthShader, 0u, "gl_FragDepthEXT", &outputVariable);
+    ASSERT_NE(outputVariable, nullptr);
+    EXPECT_EQ(0u, outputVariable->arraySize);
+    EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
+}
+
+// Test that gl_FragDataEXT built-in usage in ESSL1 fragment shader is reflected in the output
+// variables list. Also test that the precision is highp if user requests it.
+TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthHighp)
+{
+    const std::string &fragDepthHighShader =
+        "#extension GL_EXT_frag_depth : require\n"
+        "void main() {\n"
+        "   gl_FragDepthEXT = 0.7;"
+        "}\n";
+
+    ShBuiltInResources resources    = mTranslator->getResources();
+    resources.EXT_frag_depth        = 1;
+    resources.FragmentPrecisionHigh = 1;
+    initTranslator(resources);
+
+    const OutputVariable *outputVariable = nullptr;
+    validateOutputVariableForShader(fragDepthHighShader, 0u, "gl_FragDepthEXT", &outputVariable);
+    ASSERT_NE(outputVariable, nullptr);
+    EXPECT_EQ(0u, outputVariable->arraySize);
+    EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type);
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, outputVariable->precision);
+}
+
+// Test that gl_FragData built-in usage in ESSL3 fragment shader is reflected in the output
+// variables list. Also test that the precision is highp.
+TEST_F(CollectFragmentVariablesTest, OutputVarESSL3FragDepthHighp)
+{
+    const std::string &fragDepthHighShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   gl_FragDepth = 0.7;"
+        "}\n";
+
+    ShBuiltInResources resources = mTranslator->getResources();
+    resources.EXT_frag_depth = 1;
+    initTranslator(resources);
+
+    const OutputVariable *outputVariable = nullptr;
+    validateOutputVariableForShader(fragDepthHighShader, 0u, "gl_FragDepth", &outputVariable);
+    ASSERT_NE(outputVariable, nullptr);
+    EXPECT_EQ(0u, outputVariable->arraySize);
+    EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type);
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, outputVariable->precision);
+}
+
+// Test that gl_SecondaryFragColorEXT built-in usage in ESSL1 fragment shader is reflected in the
+// output variables list.
+TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondaryFragColor)
+{
+    const char *secondaryFragColorShader =
+        "#extension GL_EXT_blend_func_extended : require\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(1.0);\n"
+        "   gl_SecondaryFragColorEXT = vec4(1.0);\n"
+        "}\n";
+
+    const unsigned int kMaxDrawBuffers = 3u;
+    ShBuiltInResources resources       = mTranslator->getResources();
+    resources.EXT_blend_func_extended  = 1;
+    resources.EXT_draw_buffers         = 1;
+    resources.MaxDrawBuffers           = kMaxDrawBuffers;
+    resources.MaxDualSourceDrawBuffers = resources.MaxDrawBuffers;
+    initTranslator(resources);
+
+    const OutputVariable *outputVariable = nullptr;
+    validateOutputVariableForShader(secondaryFragColorShader, 0u, "gl_FragColor", &outputVariable);
+    ASSERT_NE(outputVariable, nullptr);
+    EXPECT_EQ(0u, outputVariable->arraySize);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
+
+    outputVariable = nullptr;
+    validateOutputVariableForShader(secondaryFragColorShader, 1u, "gl_SecondaryFragColorEXT",
+                                    &outputVariable);
+    ASSERT_NE(outputVariable, nullptr);
+    EXPECT_EQ(0u, outputVariable->arraySize);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
+}
+
+// Test that gl_SecondaryFragDataEXT built-in usage in ESSL1 fragment shader is reflected in the
+// output variables list.
+TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondaryFragData)
+{
+    const char *secondaryFragDataShader =
+        "#extension GL_EXT_blend_func_extended : require\n"
+        "#extension GL_EXT_draw_buffers : require\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   gl_FragData[0] = vec4(1.0);\n"
+        "   gl_FragData[1] = vec4(0.5);\n"
+        "   gl_SecondaryFragDataEXT[0] = vec4(1.0);\n"
+        "   gl_SecondaryFragDataEXT[1] = vec4(0.8);\n"
+        "}\n";
+    const unsigned int kMaxDrawBuffers = 3u;
+    ShBuiltInResources resources       = mTranslator->getResources();
+    resources.EXT_blend_func_extended  = 1;
+    resources.EXT_draw_buffers         = 1;
+    resources.MaxDrawBuffers           = kMaxDrawBuffers;
+    resources.MaxDualSourceDrawBuffers = resources.MaxDrawBuffers;
+    initTranslator(resources);
+
+    const OutputVariable *outputVariable = nullptr;
+    validateOutputVariableForShader(secondaryFragDataShader, 0u, "gl_FragData", &outputVariable);
+    ASSERT_NE(outputVariable, nullptr);
+    EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySize);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
+
+    outputVariable = nullptr;
+    validateOutputVariableForShader(secondaryFragDataShader, 1u, "gl_SecondaryFragDataEXT",
+                                    &outputVariable);
+    ASSERT_NE(outputVariable, nullptr);
+    EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySize);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
+}
+
+static khronos_uint64_t SimpleTestHash(const char *str, size_t len)
+{
+    return static_cast<uint64_t>(len);
+}
+
+class CollectHashedVertexVariablesTest : public CollectVertexVariablesTest
+{
+  protected:
+    void SetUp() override
+    {
+        // Initialize the translate with a hash function
+        ShBuiltInResources resources;
+        sh::InitBuiltInResources(&resources);
+        resources.HashFunction = SimpleTestHash;
+        initTranslator(resources);
+    }
+};
+
+TEST_F(CollectHashedVertexVariablesTest, InstancedInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "uniform blockName {\n"
+        "  float field;\n"
+        "} blockInstance;"
+        "void main() {\n"
+        "   gl_Position = vec4(blockInstance.field, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
+    ASSERT_EQ(1u, interfaceBlocks.size());
+
+    const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
+
+    EXPECT_EQ(0u, interfaceBlock.arraySize);
+    EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
+    EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
+    EXPECT_EQ("blockName", interfaceBlock.name);
+    EXPECT_EQ("blockInstance", interfaceBlock.instanceName);
+    EXPECT_EQ("webgl_9", interfaceBlock.mappedName);
+    EXPECT_TRUE(interfaceBlock.staticUse);
+
+    ASSERT_EQ(1u, interfaceBlock.fields.size());
+
+    const InterfaceBlockField &field = interfaceBlock.fields[0];
+
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
+    EXPECT_TRUE(field.staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
+    EXPECT_EQ("field", field.name);
+    EXPECT_EQ("webgl_5", field.mappedName);
+    EXPECT_FALSE(field.isRowMajorLayout);
+    EXPECT_TRUE(field.fields.empty());
+}
+
+TEST_F(CollectHashedVertexVariablesTest, StructUniform)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "struct sType {\n"
+        "  float field;\n"
+        "};"
+        "uniform sType u;"
+        "void main() {\n"
+        "   gl_Position = vec4(u.field, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const auto &uniforms = mTranslator->getUniforms();
+    ASSERT_EQ(1u, uniforms.size());
+
+    const Uniform &uniform = uniforms[0];
+
+    EXPECT_EQ(0u, uniform.arraySize);
+    EXPECT_EQ("u", uniform.name);
+    EXPECT_EQ("webgl_1", uniform.mappedName);
+    EXPECT_TRUE(uniform.staticUse);
+
+    ASSERT_EQ(1u, uniform.fields.size());
+
+    const ShaderVariable &field = uniform.fields[0];
+
+    EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
+    // EXPECT_TRUE(field.staticUse); // we don't yet support struct static use
+    EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
+    EXPECT_EQ("field", field.name);
+    EXPECT_EQ("webgl_5", field.mappedName);
+    EXPECT_TRUE(field.fields.empty());
+}
+
+// Test a uniform declaration with multiple declarators.
+TEST_F(CollectFragmentVariablesTest, MultiDeclaration)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 out_fragColor;\n"
+        "uniform float uA, uB;\n"
+        "void main()\n"
+        "{\n"
+        "    vec4 color = vec4(uA, uA, uA, uB);\n"
+        "    out_fragColor = color;\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const auto &uniforms = mTranslator->getUniforms();
+    ASSERT_EQ(2u, uniforms.size());
+
+    const Uniform &uniform = uniforms[0];
+    EXPECT_EQ(0u, uniform.arraySize);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, uniform.precision);
+    EXPECT_TRUE(uniform.staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT, uniform.type);
+    EXPECT_EQ("uA", uniform.name);
+
+    const Uniform &uniformB = uniforms[1];
+    EXPECT_EQ(0u, uniformB.arraySize);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, uniformB.precision);
+    EXPECT_TRUE(uniformB.staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT, uniformB.type);
+    EXPECT_EQ("uB", uniformB.name);
+}
+
+// Test a uniform declaration starting with an empty declarator.
+TEST_F(CollectFragmentVariablesTest, EmptyDeclarator)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 out_fragColor;\n"
+        "uniform float /* empty declarator */, uB;\n"
+        "void main()\n"
+        "{\n"
+        "    out_fragColor = vec4(uB, uB, uB, uB);\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const auto &uniforms = mTranslator->getUniforms();
+    ASSERT_EQ(1u, uniforms.size());
+
+    const Uniform &uniformB = uniforms[0];
+    EXPECT_EQ(0u, uniformB.arraySize);
+    EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, uniformB.precision);
+    EXPECT_TRUE(uniformB.staticUse);
+    EXPECT_GLENUM_EQ(GL_FLOAT, uniformB.type);
+    EXPECT_EQ("uB", uniformB.name);
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp
new file mode 100644
index 0000000..33bdb69
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp
@@ -0,0 +1,67 @@
+//
+// Copyright (c) 2016 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.
+//
+// ConstantFoldingNaN_test.cpp:
+//   Tests for constant folding that results in NaN according to IEEE and should also generate a
+//   warning. The ESSL spec does not mandate generating NaNs, but this is reasonable behavior in
+//   this case.
+//
+
+#include "tests/test_utils/ConstantFoldingTest.h"
+
+using namespace sh;
+
+namespace
+{
+
+class ConstantFoldingNaNExpressionTest : public ConstantFoldingExpressionTest
+{
+  public:
+    ConstantFoldingNaNExpressionTest() {}
+
+    void evaluateFloatNaN(const std::string &floatString)
+    {
+        evaluateFloat(floatString);
+        ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::quiet_NaN()));
+        ASSERT_TRUE(hasWarning());
+    }
+};
+
+}  // anonymous namespace
+
+// Test that infinity - infinity evaluates to NaN.
+TEST_F(ConstantFoldingNaNExpressionTest, FoldInfinityMinusInfinity)
+{
+    const std::string &floatString = "1.0e2048 - 1.0e2048";
+    evaluateFloatNaN(floatString);
+}
+
+// Test that infinity + negative infinity evaluates to NaN.
+TEST_F(ConstantFoldingNaNExpressionTest, FoldInfinityPlusNegativeInfinity)
+{
+    const std::string &floatString = "1.0e2048 + (-1.0e2048)";
+    evaluateFloatNaN(floatString);
+}
+
+// Test that infinity multiplied by zero evaluates to NaN.
+TEST_F(ConstantFoldingNaNExpressionTest, FoldInfinityMultipliedByZero)
+{
+    const std::string &floatString = "1.0e2048 * 0.0";
+    evaluateFloatNaN(floatString);
+}
+
+// Test that infinity divided by infinity evaluates to NaN.
+TEST_F(ConstantFoldingNaNExpressionTest, FoldInfinityDividedByInfinity)
+{
+    const std::string &floatString = "1.0e2048 / 1.0e2048";
+    evaluateFloatNaN(floatString);
+}
+
+// Test that zero divided by zero evaluates to NaN.
+TEST_F(ConstantFoldingNaNExpressionTest, FoldZeroDividedByZero)
+{
+    const std::string &floatString = "0.0 / 0.0";
+    evaluateFloatNaN(floatString);
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/ConstantFoldingOverflow_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ConstantFoldingOverflow_test.cpp
new file mode 100644
index 0000000..e14b8b7
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ConstantFoldingOverflow_test.cpp
@@ -0,0 +1,65 @@
+//
+// Copyright (c) 2016 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.
+//
+// ConstantFoldingOverflow_test.cpp:
+//   Tests for constant folding that results in floating point overflow.
+//   In IEEE floating point, the overflow result depends on which of the various rounding modes is
+//   chosen - it's either the maximum representable value or infinity.
+//   ESSL 3.00.6 section 4.5.1 says that the rounding mode cannot be set and is undefined, so the
+//   result in this case is not defined by the spec.
+//   We decide to overflow to infinity and issue a warning.
+//
+
+#include "tests/test_utils/ConstantFoldingTest.h"
+
+using namespace sh;
+
+namespace
+{
+
+class ConstantFoldingOverflowExpressionTest : public ConstantFoldingExpressionTest
+{
+  public:
+    ConstantFoldingOverflowExpressionTest() {}
+
+    void evaluateFloatOverflow(const std::string &floatString, bool positive)
+    {
+        evaluateFloat(floatString);
+        float expected = positive ? std::numeric_limits<float>::infinity()
+                                  : -std::numeric_limits<float>::infinity();
+        ASSERT_TRUE(constantFoundInAST(expected));
+        ASSERT_TRUE(hasWarning());
+    }
+};
+
+}  // anonymous namespace
+
+// Test that addition that overflows is evaluated correctly.
+TEST_F(ConstantFoldingOverflowExpressionTest, Add)
+{
+    const std::string &floatString = "2.0e38 + 2.0e38";
+    evaluateFloatOverflow(floatString, true);
+}
+
+// Test that subtraction that overflows is evaluated correctly.
+TEST_F(ConstantFoldingOverflowExpressionTest, Subtract)
+{
+    const std::string &floatString = "2.0e38 - (-2.0e38)";
+    evaluateFloatOverflow(floatString, true);
+}
+
+// Test that multiplication that overflows is evaluated correctly.
+TEST_F(ConstantFoldingOverflowExpressionTest, Multiply)
+{
+    const std::string &floatString = "1.0e30 * 1.0e10";
+    evaluateFloatOverflow(floatString, true);
+}
+
+// Test that division that overflows is evaluated correctly.
+TEST_F(ConstantFoldingOverflowExpressionTest, Divide)
+{
+    const std::string &floatString = "1.0e30 / 1.0e-10";
+    evaluateFloatOverflow(floatString, true);
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/ConstantFolding_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ConstantFolding_test.cpp
new file mode 100644
index 0000000..0f67362
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ConstantFolding_test.cpp
@@ -0,0 +1,1419 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ConstantFolding_test.cpp:
+//   Tests for constant folding
+//
+
+#include "tests/test_utils/ConstantFoldingTest.h"
+
+using namespace sh;
+
+// Test that zero, true or false are not found in AST when they are not expected. This is to make
+// sure that the subsequent tests run correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldFloatTestSanityCheck)
+{
+    const std::string &floatString = "1.0";
+    evaluateFloat(floatString);
+    ASSERT_FALSE(constantFoundInAST(0.0f));
+    ASSERT_FALSE(constantFoundInAST(true));
+    ASSERT_FALSE(constantFoundInAST(false));
+}
+
+TEST_F(ConstantFoldingTest, FoldIntegerAdd)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out int my_Int;\n"
+        "void main() {\n"
+        "   const int i = 1124 + 5;\n"
+        "   my_Int = i;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_FALSE(constantFoundInAST(1124));
+    ASSERT_FALSE(constantFoundInAST(5));
+    ASSERT_TRUE(constantFoundInAST(1129));
+}
+
+TEST_F(ConstantFoldingTest, FoldIntegerSub)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out int my_Int;\n"
+        "void main() {\n"
+        "   const int i = 1124 - 5;\n"
+        "   my_Int = i;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_FALSE(constantFoundInAST(1124));
+    ASSERT_FALSE(constantFoundInAST(5));
+    ASSERT_TRUE(constantFoundInAST(1119));
+}
+
+TEST_F(ConstantFoldingTest, FoldIntegerMul)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out int my_Int;\n"
+        "void main() {\n"
+        "   const int i = 1124 * 5;\n"
+        "   my_Int = i;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_FALSE(constantFoundInAST(1124));
+    ASSERT_FALSE(constantFoundInAST(5));
+    ASSERT_TRUE(constantFoundInAST(5620));
+}
+
+TEST_F(ConstantFoldingTest, FoldIntegerDiv)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out int my_Int;\n"
+        "void main() {\n"
+        "   const int i = 1124 / 5;\n"
+        "   my_Int = i;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_FALSE(constantFoundInAST(1124));
+    ASSERT_FALSE(constantFoundInAST(5));
+    // Rounding mode of division is undefined in the spec but ANGLE can be expected to round down.
+    ASSERT_TRUE(constantFoundInAST(224));
+}
+
+TEST_F(ConstantFoldingTest, FoldIntegerModulus)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out int my_Int;\n"
+        "void main() {\n"
+        "   const int i = 1124 % 5;\n"
+        "   my_Int = i;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_FALSE(constantFoundInAST(1124));
+    ASSERT_FALSE(constantFoundInAST(5));
+    ASSERT_TRUE(constantFoundInAST(4));
+}
+
+TEST_F(ConstantFoldingTest, FoldVectorCrossProduct)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec3 my_Vec3;"
+        "void main() {\n"
+        "   const vec3 v3 = cross(vec3(1.0f, 1.0f, 1.0f), vec3(1.0f, -1.0f, 1.0f));\n"
+        "   my_Vec3 = v3;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    std::vector<float> input1(3, 1.0f);
+    ASSERT_FALSE(constantVectorFoundInAST(input1));
+    std::vector<float> input2;
+    input2.push_back(1.0f);
+    input2.push_back(-1.0f);
+    input2.push_back(1.0f);
+    ASSERT_FALSE(constantVectorFoundInAST(input2));
+    std::vector<float> result;
+    result.push_back(2.0f);
+    result.push_back(0.0f);
+    result.push_back(-2.0f);
+    ASSERT_TRUE(constantVectorFoundInAST(result));
+}
+
+// FoldMxNMatrixInverse tests check if the matrix 'inverse' operation
+// on MxN matrix is constant folded when argument is constant expression and also
+// checks the correctness of the result returned by the constant folding operation.
+// All the matrices including matrices in the shader code are in column-major order.
+TEST_F(ConstantFoldingTest, Fold2x2MatrixInverse)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in float i;\n"
+        "out vec2 my_Vec;\n"
+        "void main() {\n"
+        "   const mat2 m2 = inverse(mat2(2.0f, 3.0f,\n"
+        "                                5.0f, 7.0f));\n"
+        "   mat2 m = m2 * mat2(i);\n"
+        "   my_Vec = m[0];\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float inputElements[] =
+    {
+        2.0f, 3.0f,
+        5.0f, 7.0f
+    };
+    std::vector<float> input(inputElements, inputElements + 4);
+    ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
+    float outputElements[] =
+    {
+        -7.0f, 3.0f,
+        5.0f, -2.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 4);
+    ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
+}
+
+// Check if the matrix 'inverse' operation on 3x3 matrix is constant folded.
+TEST_F(ConstantFoldingTest, Fold3x3MatrixInverse)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in float i;\n"
+        "out vec3 my_Vec;\n"
+        "void main() {\n"
+        "   const mat3 m3 = inverse(mat3(11.0f, 13.0f, 19.0f,\n"
+        "                                23.0f, 29.0f, 31.0f,\n"
+        "                                37.0f, 41.0f, 43.0f));\n"
+        "   mat3 m = m3 * mat3(i);\n"
+        "   my_Vec = m3[0];\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float inputElements[] =
+    {
+        11.0f, 13.0f, 19.0f,
+        23.0f, 29.0f, 31.0f,
+        37.0f, 41.0f, 43.0f
+    };
+    std::vector<float> input(inputElements, inputElements + 9);
+    ASSERT_FALSE(constantVectorFoundInAST(input));
+    float outputElements[] =
+    {
+        3.0f / 85.0f, -11.0f / 34.0f, 37.0f / 170.0f,
+        -79.0f / 340.0f, 23.0f / 68.0f, -12.0f / 85.0f,
+        13.0f / 68.0f, -3.0f / 68.0f, -1.0f / 34.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 9);
+    const float floatFaultTolerance = 0.000001f;
+    ASSERT_TRUE(constantVectorNearFoundInAST(result, floatFaultTolerance));
+}
+
+// Check if the matrix 'inverse' operation on 4x4 matrix is constant folded.
+TEST_F(ConstantFoldingTest, Fold4x4MatrixInverse)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in float i;\n"
+        "out vec4 my_Vec;\n"
+        "void main() {\n"
+        "   const mat4 m4 = inverse(mat4(29.0f, 31.0f, 37.0f, 41.0f,\n"
+        "                                43.0f, 47.0f, 53.0f, 59.0f,\n"
+        "                                61.0f, 67.0f, 71.0f, 73.0f,\n"
+        "                                79.0f, 83.0f, 89.0f, 97.0f));\n"
+        "   mat4 m = m4 * mat4(i);\n"
+        "   my_Vec = m[0];\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float inputElements[] =
+    {
+        29.0f, 31.0f, 37.0f, 41.0f,
+        43.0f, 47.0f, 53.0f, 59.0f,
+        61.0f, 67.0f, 71.0f, 73.0f,
+        79.0f, 83.0f, 89.0f, 97.0f
+    };
+    std::vector<float> input(inputElements, inputElements + 16);
+    ASSERT_FALSE(constantVectorFoundInAST(input));
+    float outputElements[] =
+    {
+        43.0f / 126.0f, -11.0f / 21.0f, -2.0f / 21.0f, 31.0f / 126.0f,
+        -5.0f / 7.0f, 9.0f / 14.0f, 1.0f / 14.0f, -1.0f / 7.0f,
+        85.0f / 126.0f, -11.0f / 21.0f, 43.0f / 210.0f, -38.0f / 315.0f,
+        -2.0f / 7.0f, 5.0f / 14.0f, -6.0f / 35.0f, 3.0f / 70.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 16);
+    const float floatFaultTolerance = 0.00001f;
+    ASSERT_TRUE(constantVectorNearFoundInAST(result, floatFaultTolerance));
+}
+
+// FoldMxNMatrixDeterminant tests check if the matrix 'determinant' operation
+// on MxN matrix is constant folded when argument is constant expression and also
+// checks the correctness of the result returned by the constant folding operation.
+// All the matrices including matrices in the shader code are in column-major order.
+TEST_F(ConstantFoldingTest, Fold2x2MatrixDeterminant)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out float my_Float;"
+        "void main() {\n"
+        "   const float f = determinant(mat2(2.0f, 3.0f,\n"
+        "                                    5.0f, 7.0f));\n"
+        "   my_Float = f;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float inputElements[] =
+    {
+        2.0f, 3.0f,
+        5.0f, 7.0f
+    };
+    std::vector<float> input(inputElements, inputElements + 4);
+    ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
+    ASSERT_TRUE(constantFoundInAST(-1.0f));
+}
+
+// Check if the matrix 'determinant' operation on 3x3 matrix is constant folded.
+TEST_F(ConstantFoldingTest, Fold3x3MatrixDeterminant)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out float my_Float;"
+        "void main() {\n"
+        "   const float f = determinant(mat3(11.0f, 13.0f, 19.0f,\n"
+             "                               23.0f, 29.0f, 31.0f,\n"
+        "                                    37.0f, 41.0f, 43.0f));\n"
+        "   my_Float = f;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float inputElements[] =
+    {
+        11.0f, 13.0f, 19.0f,
+        23.0f, 29.0f, 31.0f,
+        37.0f, 41.0f, 43.0f
+    };
+    std::vector<float> input(inputElements, inputElements + 9);
+    ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
+    ASSERT_TRUE(constantFoundInAST(-680.0f));
+}
+
+// Check if the matrix 'determinant' operation on 4x4 matrix is constant folded.
+TEST_F(ConstantFoldingTest, Fold4x4MatrixDeterminant)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out float my_Float;"
+        "void main() {\n"
+        "   const float f = determinant(mat4(29.0f, 31.0f, 37.0f, 41.0f,\n"
+        "                                    43.0f, 47.0f, 53.0f, 59.0f,\n"
+        "                                    61.0f, 67.0f, 71.0f, 73.0f,\n"
+        "                                    79.0f, 83.0f, 89.0f, 97.0f));\n"
+        "   my_Float = f;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float inputElements[] =
+    {
+        29.0f, 31.0f, 37.0f, 41.0f,
+        43.0f, 47.0f, 53.0f, 59.0f,
+        61.0f, 67.0f, 71.0f, 73.0f,
+        79.0f, 83.0f, 89.0f, 97.0f
+    };
+    std::vector<float> input(inputElements, inputElements + 16);
+    ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
+    ASSERT_TRUE(constantFoundInAST(-2520.0f));
+}
+
+// Check if the matrix 'transpose' operation on 3x3 matrix is constant folded.
+// All the matrices including matrices in the shader code are in column-major order.
+TEST_F(ConstantFoldingTest, Fold3x3MatrixTranspose)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in float i;\n"
+        "out vec3 my_Vec;\n"
+        "void main() {\n"
+        "   const mat3 m3 = transpose(mat3(11.0f, 13.0f, 19.0f,\n"
+        "                                  23.0f, 29.0f, 31.0f,\n"
+        "                                  37.0f, 41.0f, 43.0f));\n"
+        "   mat3 m = m3 * mat3(i);\n"
+        "   my_Vec = m[0];\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float inputElements[] =
+    {
+        11.0f, 13.0f, 19.0f,
+        23.0f, 29.0f, 31.0f,
+        37.0f, 41.0f, 43.0f
+    };
+    std::vector<float> input(inputElements, inputElements + 9);
+    ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
+    float outputElements[] =
+    {
+        11.0f, 23.0f, 37.0f,
+        13.0f, 29.0f, 41.0f,
+        19.0f, 31.0f, 43.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 9);
+    ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
+}
+
+// Test that 0xFFFFFFFF wraps to -1 when parsed as integer.
+// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42
+// means that any 32-bit unsigned integer value is a valid literal.
+TEST_F(ConstantFoldingTest, ParseWrappedHexIntLiteral)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision highp int;\n"
+        "uniform int inInt;\n"
+        "out vec4 my_Vec;\n"
+        "void main() {\n"
+        "   const int i = 0xFFFFFFFF;\n"
+        "   my_Vec = vec4(i * inInt);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(-1));
+}
+
+// Test that 3000000000 wraps to -1294967296 when parsed as integer.
+// This is featured in the examples of GLSL 4.5, and ESSL behavior should match
+// desktop GLSL when it comes to integer parsing.
+TEST_F(ConstantFoldingTest, ParseWrappedDecimalIntLiteral)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision highp int;\n"
+        "uniform int inInt;\n"
+        "out vec4 my_Vec;\n"
+        "void main() {\n"
+        "   const int i = 3000000000;\n"
+        "   my_Vec = vec4(i * inInt);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(-1294967296));
+}
+
+// Test that 0xFFFFFFFFu is parsed correctly as an unsigned integer literal.
+// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42
+// means that any 32-bit unsigned integer value is a valid literal.
+TEST_F(ConstantFoldingTest, ParseMaxUintLiteral)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision highp int;\n"
+        "uniform uint inInt;\n"
+        "out vec4 my_Vec;\n"
+        "void main() {\n"
+        "   const uint i = 0xFFFFFFFFu;\n"
+        "   my_Vec = vec4(i * inInt);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0xFFFFFFFFu));
+}
+
+// Test that unary minus applied to unsigned int is constant folded correctly.
+// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42
+// means that any 32-bit unsigned integer value is a valid literal.
+TEST_F(ConstantFoldingTest, FoldUnaryMinusOnUintLiteral)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision highp int;\n"
+        "uniform uint inInt;\n"
+        "out vec4 my_Vec;\n"
+        "void main() {\n"
+        "   const uint i = -1u;\n"
+        "   my_Vec = vec4(i * inInt);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0xFFFFFFFFu));
+}
+
+// Test that constant mat2 initialization with a mat2 parameter works correctly.
+TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMat2)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float mult;\n"
+        "void main() {\n"
+        "   const mat2 cm = mat2(mat2(0.0, 1.0, 2.0, 3.0));\n"
+        "   mat2 m = cm * mult;\n"
+        "   gl_FragColor = vec4(m[0], m[1]);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float outputElements[] =
+    {
+        0.0f, 1.0f,
+        2.0f, 3.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 4);
+    ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
+}
+
+// Test that constant mat2 initialization with an int parameter works correctly.
+TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingScalar)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float mult;\n"
+        "void main() {\n"
+        "   const mat2 cm = mat2(3);\n"
+        "   mat2 m = cm * mult;\n"
+        "   gl_FragColor = vec4(m[0], m[1]);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float outputElements[] =
+    {
+        3.0f, 0.0f,
+        0.0f, 3.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 4);
+    ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
+}
+
+// Test that constant mat2 initialization with a mix of parameters works correctly.
+TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMix)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float mult;\n"
+        "void main() {\n"
+        "   const mat2 cm = mat2(-1, vec2(0.0, 1.0), vec4(2.0));\n"
+        "   mat2 m = cm * mult;\n"
+        "   gl_FragColor = vec4(m[0], m[1]);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float outputElements[] =
+    {
+        -1.0, 0.0f,
+        1.0f, 2.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 4);
+    ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
+}
+
+// Test that constant mat2 initialization with a mat3 parameter works correctly.
+TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMat3)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float mult;\n"
+        "void main() {\n"
+        "   const mat2 cm = mat2(mat3(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0));\n"
+        "   mat2 m = cm * mult;\n"
+        "   gl_FragColor = vec4(m[0], m[1]);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float outputElements[] =
+    {
+        0.0f, 1.0f,
+        3.0f, 4.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 4);
+    ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
+}
+
+// Test that constant mat4x3 initialization with a mat3x2 parameter works correctly.
+TEST_F(ConstantFoldingTest, FoldMat4x3ConstructorTakingMat3x2)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform float mult;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   const mat4x3 cm = mat4x3(mat3x2(1.0, 2.0,\n"
+        "                                   3.0, 4.0,\n"
+        "                                   5.0, 6.0));\n"
+        "   mat4x3 m = cm * mult;\n"
+        "   my_FragColor = vec4(m[0], m[1][0]);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float outputElements[] =
+    {
+        1.0f, 2.0f, 0.0f,
+        3.0f, 4.0f, 0.0f,
+        5.0f, 6.0f, 1.0f,
+        0.0f, 0.0f, 0.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 12);
+    ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
+}
+
+
+// Test that constant mat2 initialization with a vec4 parameter works correctly.
+TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingVec4)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float mult;\n"
+        "void main() {\n"
+        "   const mat2 cm = mat2(vec4(0.0, 1.0, 2.0, 3.0));\n"
+        "   mat2 m = cm * mult;\n"
+        "   gl_FragColor = vec4(m[0], m[1]);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float outputElements[] =
+    {
+        0.0f, 1.0f,
+        2.0f, 3.0f
+    };
+    std::vector<float> result(outputElements, outputElements + 4);
+    ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
+}
+
+// Test that equality comparison of two different structs with a nested struct inside returns false.
+TEST_F(ConstantFoldingTest, FoldNestedDifferentStructEqualityComparison)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "struct nested {\n"
+        "    float f\n;"
+        "};\n"
+        "struct S {\n"
+        "    nested a;\n"
+        "    float f;\n"
+        "};\n"
+        "uniform vec4 mult;\n"
+        "void main()\n"
+        "{\n"
+        "    const S s1 = S(nested(0.0), 2.0);\n"
+        "    const S s2 = S(nested(0.0), 3.0);\n"
+        "    gl_FragColor = (s1 == s2 ? 1.0 : 0.5) * mult;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0.5f));
+}
+
+// Test that equality comparison of two identical structs with a nested struct inside returns true.
+TEST_F(ConstantFoldingTest, FoldNestedIdenticalStructEqualityComparison)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "struct nested {\n"
+        "    float f\n;"
+        "};\n"
+        "struct S {\n"
+        "    nested a;\n"
+        "    float f;\n"
+        "    int i;\n"
+        "};\n"
+        "uniform vec4 mult;\n"
+        "void main()\n"
+        "{\n"
+        "    const S s1 = S(nested(0.0), 2.0, 3);\n"
+        "    const S s2 = S(nested(0.0), 2.0, 3);\n"
+        "    gl_FragColor = (s1 == s2 ? 1.0 : 0.5) * mult;\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(1.0f));
+}
+
+// Test that right elements are chosen from non-square matrix
+TEST_F(ConstantFoldingTest, FoldNonSquareMatrixIndexing)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = mat3x4(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)[1];\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    float outputElements[] = {4.0f, 5.0f, 6.0f, 7.0f};
+    std::vector<float> result(outputElements, outputElements + 4);
+    ASSERT_TRUE(constantVectorFoundInAST(result));
+}
+
+// Test that folding outer product of vectors with non-matching lengths works.
+TEST_F(ConstantFoldingTest, FoldNonSquareOuterProduct)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    mat3x2 prod = outerProduct(vec2(2.0, 3.0), vec3(5.0, 7.0, 11.0));\n"
+        "    my_FragColor = vec4(prod[0].x);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    // clang-format off
+    float outputElements[] =
+    {
+        10.0f, 15.0f,
+        14.0f, 21.0f,
+        22.0f, 33.0f
+    };
+    // clang-format on
+    std::vector<float> result(outputElements, outputElements + 6);
+    ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
+}
+
+// Test that folding bit shift left with non-matching signedness works.
+TEST_F(ConstantFoldingTest, FoldBitShiftLeftDifferentSignedness)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    uint u = 0xffffffffu << 31;\n"
+        "    my_FragColor = vec4(u);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0x80000000u));
+}
+
+// Test that folding bit shift right with non-matching signedness works.
+TEST_F(ConstantFoldingTest, FoldBitShiftRightDifferentSignedness)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    uint u = 0xffffffffu >> 30;\n"
+        "    my_FragColor = vec4(u);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0x3u));
+}
+
+// Test that folding signed bit shift right extends the sign bit.
+// ESSL 3.00.6 section 5.9 Expressions.
+TEST_F(ConstantFoldingTest, FoldBitShiftRightExtendSignBit)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    const int i = 0x8fffe000 >> 6;\n"
+        "    uint u = uint(i);"
+        "    my_FragColor = vec4(u);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    // The bits of the operand are 0x8fffe000 = 1000 1111 1111 1111 1110 0000 0000 0000
+    // After shifting, they become              1111 1110 0011 1111 1111 1111 1000 0000 = 0xfe3fff80
+    ASSERT_TRUE(constantFoundInAST(0xfe3fff80u));
+}
+
+// Signed bit shift left should interpret its operand as a bit pattern. As a consequence a number
+// may turn from positive to negative when shifted left.
+// ESSL 3.00.6 section 5.9 Expressions.
+TEST_F(ConstantFoldingTest, FoldBitShiftLeftInterpretedAsBitPattern)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    const int i = 0x1fffffff << 3;\n"
+        "    uint u = uint(i);"
+        "    my_FragColor = vec4(u);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0xfffffff8u));
+}
+
+// Test that dividing the minimum signed integer by -1 works.
+// ESSL 3.00.6 section 4.1.3 Integers:
+// "However, for the case where the minimum representable value is divided by -1, it is allowed to
+// return either the minimum representable value or the maximum representable value."
+TEST_F(ConstantFoldingTest, FoldDivideMinimumIntegerByMinusOne)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    int i = 0x80000000 / (-1);\n"
+        "    my_FragColor = vec4(i);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0x7fffffff) || constantFoundInAST(-0x7fffffff - 1));
+}
+
+// Test that folding an unsigned integer addition that overflows works.
+// ESSL 3.00.6 section 4.1.3 Integers:
+// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
+// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
+// n is the size in bits of the integer."
+TEST_F(ConstantFoldingTest, FoldUnsignedIntegerAddOverflow)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    uint u = 0xffffffffu + 43u;\n"
+        "    my_FragColor = vec4(u);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(42u));
+}
+
+// Test that folding a signed integer addition that overflows works.
+// ESSL 3.00.6 section 4.1.3 Integers:
+// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
+// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
+// n is the size in bits of the integer."
+TEST_F(ConstantFoldingTest, FoldSignedIntegerAddOverflow)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    int i = 0x7fffffff + 4;\n"
+        "    my_FragColor = vec4(i);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(-0x7ffffffd));
+}
+
+// Test that folding an unsigned integer subtraction that overflows works.
+// ESSL 3.00.6 section 4.1.3 Integers:
+// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
+// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
+// n is the size in bits of the integer."
+TEST_F(ConstantFoldingTest, FoldUnsignedIntegerDiffOverflow)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    uint u = 0u - 5u;\n"
+        "    my_FragColor = vec4(u);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0xfffffffbu));
+}
+
+// Test that folding a signed integer subtraction that overflows works.
+// ESSL 3.00.6 section 4.1.3 Integers:
+// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
+// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
+// n is the size in bits of the integer."
+TEST_F(ConstantFoldingTest, FoldSignedIntegerDiffOverflow)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    int i = -0x7fffffff - 7;\n"
+        "    my_FragColor = vec4(i);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0x7ffffffa));
+}
+
+// Test that folding an unsigned integer multiplication that overflows works.
+// ESSL 3.00.6 section 4.1.3 Integers:
+// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
+// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
+// n is the size in bits of the integer."
+TEST_F(ConstantFoldingTest, FoldUnsignedIntegerMultiplyOverflow)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    uint u = 0xffffffffu * 10u;\n"
+        "    my_FragColor = vec4(u);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(0xfffffff6u));
+}
+
+// Test that folding a signed integer multiplication that overflows works.
+// ESSL 3.00.6 section 4.1.3 Integers:
+// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
+// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
+// n is the size in bits of the integer."
+TEST_F(ConstantFoldingTest, FoldSignedIntegerMultiplyOverflow)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    int i = 0x7fffffff * 42;\n"
+        "    my_FragColor = vec4(i);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(-42));
+}
+
+// Test that folding of negating the minimum representable integer works. Note that in the test
+// "0x80000000" is a negative literal, and the minus sign before it is the negation operator.
+// ESSL 3.00.6 section 4.1.3 Integers:
+// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
+// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
+// n is the size in bits of the integer."
+TEST_F(ConstantFoldingTest, FoldMinimumSignedIntegerNegation)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    int i = -0x80000000;\n"
+        "    my_FragColor = vec4(i);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    // Negating the minimum signed integer overflows the positive range, so it wraps back to itself.
+    ASSERT_TRUE(constantFoundInAST(-0x7fffffff - 1));
+}
+
+// Test that folding of shifting the minimum representable integer works.
+TEST_F(ConstantFoldingTest, FoldMinimumSignedIntegerRightShift)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    int i = (0x80000000 >> 1);\n"
+        "    int j = (0x80000000 >> 7);\n"
+        "    my_FragColor = vec4(i, j, i, j);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(-0x40000000));
+    ASSERT_TRUE(constantFoundInAST(-0x01000000));
+}
+
+// Test that folding of shifting by 0 works.
+TEST_F(ConstantFoldingTest, FoldShiftByZero)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    int i = (3 >> 0);\n"
+        "    int j = (73 << 0);\n"
+        "    my_FragColor = vec4(i, j, i, j);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(3));
+    ASSERT_TRUE(constantFoundInAST(73));
+}
+
+// Test that folding IsInf results in true when the parameter is an out-of-range float literal.
+// ESSL 3.00.6 section 4.1.4 Floats:
+// "If the value of the floating point number is too large (small) to be stored as a single
+// precision value, it is converted to positive (negative) infinity."
+// ESSL 3.00.6 section 12.4:
+// "Mandate support for signed infinities."
+TEST_F(ConstantFoldingTest, FoldIsInfOutOfRangeFloatLiteral)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    bool b = isinf(1.0e2048);\n"
+        "    my_FragColor = vec4(b);\n"
+        "}\n";
+    compileAssumeSuccess(shaderString);
+    ASSERT_TRUE(constantFoundInAST(true));
+}
+
+// Test that floats that are too small to be represented get flushed to zero.
+// ESSL 3.00.6 section 4.1.4 Floats:
+// "A value with a magnitude too small to be represented as a mantissa and exponent is converted to
+// zero."
+TEST_F(ConstantFoldingExpressionTest, FoldTooSmallFloat)
+{
+    const std::string &floatString = "1.0e-2048";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim radians(x) x -> inf = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldRadiansInfinity)
+{
+    const std::string &floatString = "radians(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim degrees(x) x -> inf = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldDegreesInfinity)
+{
+    const std::string &floatString = "degrees(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that sinh(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldSinhInfinity)
+{
+    const std::string &floatString = "sinh(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that sinh(-inf) = -inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldSinhNegativeInfinity)
+{
+    const std::string &floatString = "sinh(-1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that cosh(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldCoshInfinity)
+{
+    const std::string &floatString = "cosh(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that cosh(-inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldCoshNegativeInfinity)
+{
+    const std::string &floatString = "cosh(-1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that asinh(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldAsinhInfinity)
+{
+    const std::string &floatString = "asinh(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that asinh(-inf) = -inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldAsinhNegativeInfinity)
+{
+    const std::string &floatString = "asinh(-1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that acosh(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldAcoshInfinity)
+{
+    const std::string &floatString = "acosh(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that pow or powr(0, inf) = 0.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldPowInfinity)
+{
+    const std::string &floatString = "pow(0.0, 1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that exp(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldExpInfinity)
+{
+    const std::string &floatString = "exp(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that exp(-inf) = 0.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldExpNegativeInfinity)
+{
+    const std::string &floatString = "exp(-1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that log(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldLogInfinity)
+{
+    const std::string &floatString = "log(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that exp2(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldExp2Infinity)
+{
+    const std::string &floatString = "exp2(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that exp2(-inf) = 0.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldExp2NegativeInfinity)
+{
+    const std::string &floatString = "exp2(-1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that log2(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldLog2Infinity)
+{
+    const std::string &floatString = "log2(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim sqrt(x) x -> inf = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldSqrtInfinity)
+{
+    const std::string &floatString = "sqrt(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that rSqrt(inf) = 0
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldInversesqrtInfinity)
+{
+    const std::string &floatString = "inversesqrt(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim length(x) x -> inf = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldLengthInfinity)
+{
+    const std::string &floatString = "length(1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim dot(x, y) x -> inf, y > 0 = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity)
+{
+    const std::string &floatString = "dot(1.0e2048, 1.0)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim dot(vec2(x, y), vec2(z)) x -> inf, finite y, z > 0 = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity2)
+{
+    const std::string &floatString = "dot(vec2(1.0e2048, -1.0), vec2(1.0))";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// Faceforward behavior with infinity as a parameter can be derived from dot().
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity)
+{
+    const std::string &floatString = "faceforward(4.0, 1.0e2048, 1.0)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(-4.0f));
+}
+
+// Faceforward behavior with infinity as a parameter can be derived from dot().
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity2)
+{
+    const std::string &floatString = "faceforward(vec2(4.0), vec2(1.0e2048, -1.0), vec2(1.0)).x";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(-4.0f));
+}
+
+// Test that infinity - finite value evaluates to infinity.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldInfinityMinusFinite)
+{
+    const std::string &floatString = "1.0e2048 - 1.0e20";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// Test that -infinity + finite value evaluates to -infinity.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldMinusInfinityPlusFinite)
+{
+    const std::string &floatString = "(-1.0e2048) + 1.0e20";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
+}
+
+// Test that infinity * finite value evaluates to infinity.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByFinite)
+{
+    const std::string &floatString = "1.0e2048 * 1.0e-20";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// Test that infinity * infinity evaluates to infinity.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByInfinity)
+{
+    const std::string &floatString = "1.0e2048 * 1.0e2048";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// Test that infinity * negative infinity evaluates to negative infinity.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByNegativeInfinity)
+{
+    const std::string &floatString = "1.0e2048 * (-1.0e2048)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
+}
+
+// Test that dividing by minus zero results in the appropriately signed infinity.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+// "If both positive and negative zeros are implemented, the correctly signed Inf will be
+// generated".
+TEST_F(ConstantFoldingExpressionTest, FoldDivideByNegativeZero)
+{
+    const std::string &floatString = "1.0 / (-0.0)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
+    ASSERT_TRUE(hasWarning());
+}
+
+// Test that infinity divided by zero evaluates to infinity.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldInfinityDividedByZero)
+{
+    const std::string &floatString = "1.0e2048 / 0.0";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+    ASSERT_TRUE(hasWarning());
+}
+
+// Test that negative infinity divided by zero evaluates to negative infinity.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldMinusInfinityDividedByZero)
+{
+    const std::string &floatString = "(-1.0e2048) / 0.0";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
+    ASSERT_TRUE(hasWarning());
+}
+
+// Test that dividing a finite number by infinity results in zero.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldDivideByInfinity)
+{
+    const std::string &floatString = "1.0e30 / 1.0e2048";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// Test that unsigned bitfieldExtract is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract)
+{
+    const std::string &uintString = "bitfieldExtract(0x00110000u, 16, 5)";
+    evaluateUint(uintString);
+    ASSERT_TRUE(constantFoundInAST(0x11u));
+}
+
+// Test that unsigned bitfieldExtract to extract 32 bits is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract32Bits)
+{
+    const std::string &uintString = "bitfieldExtract(0xff0000ffu, 0, 32)";
+    evaluateUint(uintString);
+    ASSERT_TRUE(constantFoundInAST(0xff0000ffu));
+}
+
+// Test that signed bitfieldExtract is folded correctly. The higher bits should be set to 1 if the
+// most significant bit of the extracted value is 1.
+TEST_F(ConstantFoldingExpressionTest, FoldSignedBitfieldExtract)
+{
+    const std::string &intString = "bitfieldExtract(0x00110000, 16, 5)";
+    evaluateInt(intString);
+    // 0xfffffff1 == -15
+    ASSERT_TRUE(constantFoundInAST(-15));
+}
+
+// Test that bitfieldInsert is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert)
+{
+    const std::string &uintString = "bitfieldInsert(0x04501701u, 0x11u, 8, 5)";
+    evaluateUint(uintString);
+    ASSERT_TRUE(constantFoundInAST(0x04501101u));
+}
+
+// Test that bitfieldInsert to insert 32 bits is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert32Bits)
+{
+    const std::string &uintString = "bitfieldInsert(0xff0000ffu, 0x11u, 0, 32)";
+    evaluateUint(uintString);
+    ASSERT_TRUE(constantFoundInAST(0x11u));
+}
+
+// Test that bitfieldReverse is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldBitfieldReverse)
+{
+    const std::string &uintString = "bitfieldReverse((1u << 4u) | (1u << 7u))";
+    evaluateUint(uintString);
+    uint32_t flag1 = 1u << (31u - 4u);
+    uint32_t flag2 = 1u << (31u - 7u);
+    ASSERT_TRUE(constantFoundInAST(flag1 | flag2));
+}
+
+// Test that bitCount is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldBitCount)
+{
+    const std::string &intString = "bitCount(0x17103121u)";
+    evaluateInt(intString);
+    ASSERT_TRUE(constantFoundInAST(10));
+}
+
+// Test that findLSB is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldFindLSB)
+{
+    const std::string &intString = "findLSB(0x80010000u)";
+    evaluateInt(intString);
+    ASSERT_TRUE(constantFoundInAST(16));
+}
+
+// Test that findLSB is folded correctly when the operand is zero.
+TEST_F(ConstantFoldingExpressionTest, FoldFindLSBZero)
+{
+    const std::string &intString = "findLSB(0u)";
+    evaluateInt(intString);
+    ASSERT_TRUE(constantFoundInAST(-1));
+}
+
+// Test that findMSB is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldFindMSB)
+{
+    const std::string &intString = "findMSB(0x01000008u)";
+    evaluateInt(intString);
+    ASSERT_TRUE(constantFoundInAST(24));
+}
+
+// Test that findMSB is folded correctly when the operand is zero.
+TEST_F(ConstantFoldingExpressionTest, FoldFindMSBZero)
+{
+    const std::string &intString = "findMSB(0u)";
+    evaluateInt(intString);
+    ASSERT_TRUE(constantFoundInAST(-1));
+}
+
+// Test that findMSB is folded correctly for a negative integer.
+// It is supposed to return the index of the most significant bit set to 0.
+TEST_F(ConstantFoldingExpressionTest, FoldFindMSBNegativeInt)
+{
+    const std::string &intString = "findMSB(-8)";
+    evaluateInt(intString);
+    ASSERT_TRUE(constantFoundInAST(2));
+}
+
+// Test that findMSB is folded correctly for -1.
+TEST_F(ConstantFoldingExpressionTest, FoldFindMSBMinusOne)
+{
+    const std::string &intString = "findMSB(-1)";
+    evaluateInt(intString);
+    ASSERT_TRUE(constantFoundInAST(-1));
+}
+
+// Test that packUnorm4x8 is folded correctly for a vector of zeroes.
+TEST_F(ConstantFoldingExpressionTest, FoldPackUnorm4x8Zero)
+{
+    const std::string &intString = "packUnorm4x8(vec4(0.0))";
+    evaluateUint(intString);
+    ASSERT_TRUE(constantFoundInAST(0u));
+}
+
+// Test that packUnorm4x8 is folded correctly for a vector of ones.
+TEST_F(ConstantFoldingExpressionTest, FoldPackUnorm4x8One)
+{
+    const std::string &intString = "packUnorm4x8(vec4(1.0))";
+    evaluateUint(intString);
+    ASSERT_TRUE(constantFoundInAST(0xffffffffu));
+}
+
+// Test that packSnorm4x8 is folded correctly for a vector of zeroes.
+TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8Zero)
+{
+    const std::string &intString = "packSnorm4x8(vec4(0.0))";
+    evaluateUint(intString);
+    ASSERT_TRUE(constantFoundInAST(0u));
+}
+
+// Test that packSnorm4x8 is folded correctly for a vector of ones.
+TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8One)
+{
+    const std::string &intString = "packSnorm4x8(vec4(1.0))";
+    evaluateUint(intString);
+    ASSERT_TRUE(constantFoundInAST(0x7f7f7f7fu));
+}
+
+// Test that packSnorm4x8 is folded correctly for a vector of minus ones.
+TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8MinusOne)
+{
+    const std::string &intString = "packSnorm4x8(vec4(-1.0))";
+    evaluateUint(intString);
+    ASSERT_TRUE(constantFoundInAST(0x81818181u));
+}
+
+// Test that unpackSnorm4x8 is folded correctly when it needs to clamp the result.
+TEST_F(ConstantFoldingExpressionTest, FoldUnpackSnorm4x8Clamp)
+{
+    const std::string &floatString = "unpackSnorm4x8(0x00000080u).x";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(-1.0f));
+}
+
+// Test that unpackUnorm4x8 is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldUnpackUnorm4x8)
+{
+    const std::string &floatString = "unpackUnorm4x8(0x007bbeefu).z";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(123.0f / 255.0f));
+}
+
+// Test that ldexp is folded correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldLdexp)
+{
+    const std::string &floatString = "ldexp(0.625, 1)";
+    evaluateFloat(floatString);
+    ASSERT_TRUE(constantFoundInAST(1.25f));
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/ConstructCompiler_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ConstructCompiler_test.cpp
new file mode 100644
index 0000000..30829d3
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ConstructCompiler_test.cpp
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 2016 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.
+//
+// ConstructCompiler_test.cpp
+//   Test the sh::ConstructCompiler interface with different parameters.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+// Test default parameters.
+TEST(ConstructCompilerTest, DefaultParameters)
+{
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+    ShHandle compiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL_SPEC,
+                                              SH_GLSL_COMPATIBILITY_OUTPUT, &resources);
+    ASSERT_NE(nullptr, compiler);
+}
+
+// Test invalid MaxDrawBuffers zero.
+TEST(ConstructCompilerTest, InvalidMaxDrawBuffers)
+{
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+    resources.MaxDrawBuffers = 0;
+    ShHandle compiler        = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL_SPEC,
+                                              SH_GLSL_COMPATIBILITY_OUTPUT, &resources);
+    ASSERT_EQ(nullptr, compiler);
+}
+
+// Test invalid MaxDualSourceDrawBuffers zero.
+TEST(ConstructCompilerTest, InvalidMaxDualSourceDrawBuffers)
+{
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+    resources.EXT_blend_func_extended  = 1;
+    resources.MaxDualSourceDrawBuffers = 0;
+    ShHandle compiler                  = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL_SPEC,
+                                              SH_GLSL_COMPATIBILITY_OUTPUT, &resources);
+    ASSERT_EQ(nullptr, compiler);
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/DebugShaderPrecision_test.cpp b/src/third_party/angle/src/tests/compiler_tests/DebugShaderPrecision_test.cpp
new file mode 100644
index 0000000..52f77c7
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/DebugShaderPrecision_test.cpp
@@ -0,0 +1,1044 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugShaderPrecision_test.cpp:
+//   Tests for writing the code for shader precision emulation.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+class DebugShaderPrecisionTest : public MatchOutputCodeTest
+{
+  public:
+    DebugShaderPrecisionTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT)
+    {
+        addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
+#if defined(ANGLE_ENABLE_HLSL)
+        addOutputType(SH_HLSL_4_1_OUTPUT);
+#endif
+        getResources()->WEBGL_debug_shader_precision = 1;
+    }
+
+  protected:
+    bool foundInAllGLSLCode(const char *str)
+    {
+        return foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, str) && foundInCode(SH_ESSL_OUTPUT, str);
+    }
+
+    bool foundInHLSLCode(const char *stringToFind) const
+    {
+#if defined(ANGLE_ENABLE_HLSL)
+        return foundInCode(SH_HLSL_4_1_OUTPUT, stringToFind);
+#else
+        return true;
+#endif
+    }
+};
+
+class NoDebugShaderPrecisionTest : public MatchOutputCodeTest
+{
+  public:
+    NoDebugShaderPrecisionTest()
+        : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_GLSL_COMPATIBILITY_OUTPUT)
+    {
+    }
+};
+
+TEST_F(DebugShaderPrecisionTest, RoundingFunctionsDefined)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(u);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode("highp float angle_frm(in highp float"));
+    ASSERT_TRUE(foundInESSLCode("highp vec2 angle_frm(in highp vec2"));
+    ASSERT_TRUE(foundInESSLCode("highp vec3 angle_frm(in highp vec3"));
+    ASSERT_TRUE(foundInESSLCode("highp vec4 angle_frm(in highp vec4"));
+    ASSERT_TRUE(foundInESSLCode("highp mat2 angle_frm(in highp mat2"));
+    ASSERT_TRUE(foundInESSLCode("highp mat3 angle_frm(in highp mat3"));
+    ASSERT_TRUE(foundInESSLCode("highp mat4 angle_frm(in highp mat4"));
+
+    ASSERT_TRUE(foundInESSLCode("highp float angle_frl(in highp float"));
+    ASSERT_TRUE(foundInESSLCode("highp vec2 angle_frl(in highp vec2"));
+    ASSERT_TRUE(foundInESSLCode("highp vec3 angle_frl(in highp vec3"));
+    ASSERT_TRUE(foundInESSLCode("highp vec4 angle_frl(in highp vec4"));
+    ASSERT_TRUE(foundInESSLCode("highp mat2 angle_frl(in highp mat2"));
+    ASSERT_TRUE(foundInESSLCode("highp mat3 angle_frl(in highp mat3"));
+    ASSERT_TRUE(foundInESSLCode("highp mat4 angle_frl(in highp mat4"));
+
+    ASSERT_TRUE(foundInGLSLCode("float angle_frm(in float"));
+    ASSERT_TRUE(foundInGLSLCode("vec2 angle_frm(in vec2"));
+    ASSERT_TRUE(foundInGLSLCode("vec3 angle_frm(in vec3"));
+    ASSERT_TRUE(foundInGLSLCode("vec4 angle_frm(in vec4"));
+    ASSERT_TRUE(foundInGLSLCode("mat2 angle_frm(in mat2"));
+    ASSERT_TRUE(foundInGLSLCode("mat3 angle_frm(in mat3"));
+    ASSERT_TRUE(foundInGLSLCode("mat4 angle_frm(in mat4"));
+
+    ASSERT_TRUE(foundInGLSLCode("float angle_frl(in float"));
+    ASSERT_TRUE(foundInGLSLCode("vec2 angle_frl(in vec2"));
+    ASSERT_TRUE(foundInGLSLCode("vec3 angle_frl(in vec3"));
+    ASSERT_TRUE(foundInGLSLCode("vec4 angle_frl(in vec4"));
+    ASSERT_TRUE(foundInGLSLCode("mat2 angle_frl(in mat2"));
+    ASSERT_TRUE(foundInGLSLCode("mat3 angle_frl(in mat3"));
+    ASSERT_TRUE(foundInGLSLCode("mat4 angle_frl(in mat4"));
+
+    ASSERT_TRUE(foundInHLSLCode("float1 angle_frm(float1"));
+    ASSERT_TRUE(foundInHLSLCode("float2 angle_frm(float2"));
+    ASSERT_TRUE(foundInHLSLCode("float3 angle_frm(float3"));
+    ASSERT_TRUE(foundInHLSLCode("float4 angle_frm(float4"));
+    ASSERT_TRUE(foundInHLSLCode("float2x2 angle_frm(float2x2"));
+    ASSERT_TRUE(foundInHLSLCode("float3x3 angle_frm(float3x3"));
+    ASSERT_TRUE(foundInHLSLCode("float4x4 angle_frm(float4x4"));
+
+    ASSERT_TRUE(foundInHLSLCode("float1 angle_frl(float1"));
+    ASSERT_TRUE(foundInHLSLCode("float2 angle_frl(float2"));
+    ASSERT_TRUE(foundInHLSLCode("float3 angle_frl(float3"));
+    ASSERT_TRUE(foundInHLSLCode("float4 angle_frl(float4"));
+    ASSERT_TRUE(foundInHLSLCode("float2x2 angle_frl(float2x2"));
+    ASSERT_TRUE(foundInHLSLCode("float3x3 angle_frl(float3x3"));
+    ASSERT_TRUE(foundInHLSLCode("float4x4 angle_frl(float4x4"));
+
+    // Check that ESSL 3.00 rounding functions for non-square matrices are not defined.
+    ASSERT_TRUE(notFoundInCode("mat2x"));
+    ASSERT_TRUE(notFoundInCode("mat3x"));
+    ASSERT_TRUE(notFoundInCode("mat4x"));
+}
+
+// Test that all ESSL 3.00 shaders get rounding function definitions for non-square matrices.
+TEST_F(DebugShaderPrecisionTest, NonSquareMatrixRoundingFunctionsDefinedES3)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   my_FragColor = vec4(u);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode("highp mat2x3 angle_frm(in highp mat2x3"));
+    ASSERT_TRUE(foundInESSLCode("highp mat2x4 angle_frm(in highp mat2x4"));
+    ASSERT_TRUE(foundInESSLCode("highp mat3x2 angle_frm(in highp mat3x2"));
+    ASSERT_TRUE(foundInESSLCode("highp mat3x4 angle_frm(in highp mat3x4"));
+    ASSERT_TRUE(foundInESSLCode("highp mat4x2 angle_frm(in highp mat4x2"));
+    ASSERT_TRUE(foundInESSLCode("highp mat4x3 angle_frm(in highp mat4x3"));
+
+    ASSERT_TRUE(foundInESSLCode("highp mat2x3 angle_frl(in highp mat2x3"));
+    ASSERT_TRUE(foundInESSLCode("highp mat2x4 angle_frl(in highp mat2x4"));
+    ASSERT_TRUE(foundInESSLCode("highp mat3x2 angle_frl(in highp mat3x2"));
+    ASSERT_TRUE(foundInESSLCode("highp mat3x4 angle_frl(in highp mat3x4"));
+    ASSERT_TRUE(foundInESSLCode("highp mat4x2 angle_frl(in highp mat4x2"));
+    ASSERT_TRUE(foundInESSLCode("highp mat4x3 angle_frl(in highp mat4x3"));
+
+    ASSERT_TRUE(foundInGLSLCode("mat2x3 angle_frm(in mat2x3"));
+    ASSERT_TRUE(foundInGLSLCode("mat2x4 angle_frm(in mat2x4"));
+    ASSERT_TRUE(foundInGLSLCode("mat3x2 angle_frm(in mat3x2"));
+    ASSERT_TRUE(foundInGLSLCode("mat3x4 angle_frm(in mat3x4"));
+    ASSERT_TRUE(foundInGLSLCode("mat4x2 angle_frm(in mat4x2"));
+    ASSERT_TRUE(foundInGLSLCode("mat4x3 angle_frm(in mat4x3"));
+
+    ASSERT_TRUE(foundInGLSLCode("mat2x3 angle_frl(in mat2x3"));
+    ASSERT_TRUE(foundInGLSLCode("mat2x4 angle_frl(in mat2x4"));
+    ASSERT_TRUE(foundInGLSLCode("mat3x2 angle_frl(in mat3x2"));
+    ASSERT_TRUE(foundInGLSLCode("mat3x4 angle_frl(in mat3x4"));
+    ASSERT_TRUE(foundInGLSLCode("mat4x2 angle_frl(in mat4x2"));
+    ASSERT_TRUE(foundInGLSLCode("mat4x3 angle_frl(in mat4x3"));
+
+    ASSERT_TRUE(foundInHLSLCode("float2x3 angle_frm(float2x3"));
+    ASSERT_TRUE(foundInHLSLCode("float2x4 angle_frm(float2x4"));
+    ASSERT_TRUE(foundInHLSLCode("float3x2 angle_frm(float3x2"));
+    ASSERT_TRUE(foundInHLSLCode("float3x4 angle_frm(float3x4"));
+    ASSERT_TRUE(foundInHLSLCode("float4x2 angle_frm(float4x2"));
+    ASSERT_TRUE(foundInHLSLCode("float4x3 angle_frm(float4x3"));
+
+    ASSERT_TRUE(foundInHLSLCode("float2x3 angle_frl(float2x3"));
+    ASSERT_TRUE(foundInHLSLCode("float2x4 angle_frl(float2x4"));
+    ASSERT_TRUE(foundInHLSLCode("float3x2 angle_frl(float3x2"));
+    ASSERT_TRUE(foundInHLSLCode("float3x4 angle_frl(float3x4"));
+    ASSERT_TRUE(foundInHLSLCode("float4x2 angle_frl(float4x2"));
+    ASSERT_TRUE(foundInHLSLCode("float4x3 angle_frl(float4x3"));
+}
+
+TEST_F(DebugShaderPrecisionTest, PragmaDisablesEmulation)
+{
+    const std::string &shaderString =
+        "#pragma webgl_debug_shader_precision(off)\n"
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(u);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(notFoundInCode("angle_frm"));
+    const std::string &shaderStringPragmaOn =
+        "#pragma webgl_debug_shader_precision(on)\n"
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(u);\n"
+        "}\n";
+    compile(shaderStringPragmaOn);
+    ASSERT_TRUE(foundInCode("angle_frm"));
+}
+
+// Emulation can't be toggled on for only a part of a shader.
+// Only the last pragma in the shader has an effect.
+TEST_F(DebugShaderPrecisionTest, MultiplePragmas)
+{
+    const std::string &shaderString =
+        "#pragma webgl_debug_shader_precision(off)\n"
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(u);\n"
+        "}\n"
+        "#pragma webgl_debug_shader_precision(on)\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("angle_frm"));
+}
+
+TEST_F(NoDebugShaderPrecisionTest, HelpersWrittenOnlyWithExtension)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(u);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundInCode("angle_frm"));
+}
+
+TEST_F(NoDebugShaderPrecisionTest, PragmaHasEffectsOnlyWithExtension)
+{
+    const std::string &shaderString =
+        "#pragma webgl_debug_shader_precision(on)\n"
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(u);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundInCode("angle_frm"));
+}
+
+TEST_F(DebugShaderPrecisionTest, DeclarationsAndConstants)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 f;\n"
+        "uniform float uu, uu2;\n"
+        "varying float vv, vv2;\n"
+        "float gg = 0.0, gg2;\n"
+        "void main() {\n"
+        "   float aa = 0.0, aa2;\n"
+        "   gl_FragColor = f;\n"
+        "}\n";
+    compile(shaderString);
+    // Declarations or constants should not have rounding inserted around them
+    ASSERT_TRUE(notFoundInCode("angle_frm(0"));
+    ASSERT_TRUE(notFoundInCode("angle_frm(uu"));
+    ASSERT_TRUE(notFoundInCode("angle_frm(vv"));
+    ASSERT_TRUE(notFoundInCode("angle_frm(gg"));
+    ASSERT_TRUE(notFoundInCode("angle_frm(aa"));
+}
+
+// Test that expressions that are part of initialization have rounding.
+TEST_F(DebugShaderPrecisionTest, InitializerRounding)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   float a = u;\n"
+        "   gl_FragColor = vec4(a);\n"
+        "}\n";
+    compile(shaderString);
+    // An expression that's part of initialization should have rounding
+    ASSERT_TRUE(foundInAllGLSLCode("angle_frm(u)"));
+    ASSERT_TRUE(foundInHLSLCode("angle_frm(_u)"));
+}
+
+// Test that compound additions have rounding in the GLSL translations.
+TEST_F(DebugShaderPrecisionTest, CompoundAddFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "uniform vec4 u2;\n"
+        "void main() {\n"
+        "   vec4 v = u;\n"
+        "   v += u2;\n"
+        "   gl_FragColor = v;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp vec4 angle_compound_add_frm(inout highp vec4 x, in highp vec4 y) {\n"
+        "    x = angle_frm(angle_frm(x) + y);"
+    ));
+    ASSERT_TRUE(foundInGLSLCode(
+        "vec4 angle_compound_add_frm(inout vec4 x, in vec4 y) {\n"
+        "    x = angle_frm(angle_frm(x) + y);"
+    ));
+    ASSERT_TRUE(
+        foundInHLSLCode("float4 angle_compound_add_frm(inout float4 x, in float4 y) {\n"
+                        "    x = angle_frm(angle_frm(x) + y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_add_frm(v, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_add_frm(_v, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("+="));
+}
+
+TEST_F(DebugShaderPrecisionTest, CompoundSubFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "uniform vec4 u2;\n"
+        "void main() {\n"
+        "   vec4 v = u;\n"
+        "   v -= u2;\n"
+        "   gl_FragColor = v;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp vec4 angle_compound_sub_frm(inout highp vec4 x, in highp vec4 y) {\n"
+        "    x = angle_frm(angle_frm(x) - y);"
+    ));
+    ASSERT_TRUE(foundInGLSLCode(
+        "vec4 angle_compound_sub_frm(inout vec4 x, in vec4 y) {\n"
+        "    x = angle_frm(angle_frm(x) - y);"
+    ));
+    ASSERT_TRUE(
+        foundInHLSLCode("float4 angle_compound_sub_frm(inout float4 x, in float4 y) {\n"
+                        "    x = angle_frm(angle_frm(x) - y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_sub_frm(v, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_sub_frm(_v, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("-="));
+}
+
+TEST_F(DebugShaderPrecisionTest, CompoundDivFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "uniform vec4 u2;\n"
+        "void main() {\n"
+        "   vec4 v = u;\n"
+        "   v /= u2;\n"
+        "   gl_FragColor = v;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp vec4 angle_compound_div_frm(inout highp vec4 x, in highp vec4 y) {\n"
+        "    x = angle_frm(angle_frm(x) / y);"
+    ));
+    ASSERT_TRUE(foundInGLSLCode(
+        "vec4 angle_compound_div_frm(inout vec4 x, in vec4 y) {\n"
+        "    x = angle_frm(angle_frm(x) / y);"
+    ));
+    ASSERT_TRUE(
+        foundInHLSLCode("float4 angle_compound_div_frm(inout float4 x, in float4 y) {\n"
+                        "    x = angle_frm(angle_frm(x) / y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_div_frm(v, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_div_frm(_v, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("/="));
+}
+
+TEST_F(DebugShaderPrecisionTest, CompoundMulFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "uniform vec4 u2;\n"
+        "void main() {\n"
+        "   vec4 v = u;\n"
+        "   v *= u2;\n"
+        "   gl_FragColor = v;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp vec4 angle_compound_mul_frm(inout highp vec4 x, in highp vec4 y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(foundInGLSLCode(
+        "vec4 angle_compound_mul_frm(inout vec4 x, in vec4 y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(
+        foundInHLSLCode("float4 angle_compound_mul_frm(inout float4 x, in float4 y) {\n"
+                        "    x = angle_frm(angle_frm(x) * y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(v, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_v, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("*="));
+}
+
+TEST_F(DebugShaderPrecisionTest, CompoundAddVectorPlusScalarFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "uniform float u2;\n"
+        "void main() {\n"
+        "   vec4 v = u;\n"
+        "   v += u2;\n"
+        "   gl_FragColor = v;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp vec4 angle_compound_add_frm(inout highp vec4 x, in highp float y) {\n"
+        "    x = angle_frm(angle_frm(x) + y);"
+    ));
+    ASSERT_TRUE(foundInGLSLCode(
+        "vec4 angle_compound_add_frm(inout vec4 x, in float y) {\n"
+        "    x = angle_frm(angle_frm(x) + y);"
+    ));
+    ASSERT_TRUE(
+        foundInHLSLCode("float4 angle_compound_add_frm(inout float4 x, in float y) {\n"
+                        "    x = angle_frm(angle_frm(x) + y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_add_frm(v, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_add_frm(_v, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("+="));
+}
+
+TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesMatrixFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform mat4 u;\n"
+        "uniform mat4 u2;\n"
+        "void main() {\n"
+        "   mat4 m = u;\n"
+        "   m *= u2;\n"
+        "   gl_FragColor = m[0];\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp mat4 angle_compound_mul_frm(inout highp mat4 x, in highp mat4 y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(foundInGLSLCode(
+        "mat4 angle_compound_mul_frm(inout mat4 x, in mat4 y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(
+        foundInHLSLCode("float4x4 angle_compound_mul_frm(inout float4x4 x, in float4x4 y) {\n"
+                        "    x = angle_frm(angle_frm(x) * y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(m, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_m, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("*="));
+}
+
+// Test that compound multiplying a non-square matrix with another matrix gets translated into an
+// angle_compound_mul function call.
+TEST_F(DebugShaderPrecisionTest, CompoundNonSquareMatrixTimesMatrixFunction)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform mat2x4 u;\n"
+        "uniform mat2 u2;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   mat2x4 m = u;\n"
+        "   m *= u2;\n"
+        "   my_FragColor = m[0];\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp mat2x4 angle_compound_mul_frm(inout highp mat2x4 x, in highp mat2 y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"));
+    ASSERT_TRUE(
+        foundInGLSLCode("mat2x4 angle_compound_mul_frm(inout mat2x4 x, in mat2 y) {\n"
+                        "    x = angle_frm(angle_frm(x) * y);"));
+    ASSERT_TRUE(
+        foundInHLSLCode("float2x4 angle_compound_mul_frm(inout float2x4 x, in float2x2 y) {\n"
+                        "    x = angle_frm(angle_frm(x) * y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(m, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_m, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("*="));
+}
+
+TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesScalarFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform mat4 u;\n"
+        "uniform float u2;\n"
+        "void main() {\n"
+        "   mat4 m = u;\n"
+        "   m *= u2;\n"
+        "   gl_FragColor = m[0];\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp mat4 angle_compound_mul_frm(inout highp mat4 x, in highp float y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(foundInGLSLCode(
+        "mat4 angle_compound_mul_frm(inout mat4 x, in float y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(
+        foundInHLSLCode("float4x4 angle_compound_mul_frm(inout float4x4 x, in float y) {\n"
+                        "    x = angle_frm(angle_frm(x) * y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(m, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_m, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("*="));
+}
+
+TEST_F(DebugShaderPrecisionTest, CompoundVectorTimesMatrixFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "uniform mat4 u2;\n"
+        "void main() {\n"
+        "   vec4 v = u;\n"
+        "   v *= u2;\n"
+        "   gl_FragColor = v;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp vec4 angle_compound_mul_frm(inout highp vec4 x, in highp mat4 y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(foundInGLSLCode("vec4 angle_compound_mul_frm(inout vec4 x, in mat4 y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(
+        foundInHLSLCode("float4 angle_compound_mul_frm(inout float4 x, in float4x4 y) {\n"
+                        "    x = angle_frm(angle_frm(x) * y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(v, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_v, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("*="));
+}
+
+TEST_F(DebugShaderPrecisionTest, CompoundVectorTimesScalarFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "uniform float u2;\n"
+        "void main() {\n"
+        "   vec4 v = u;\n"
+        "   v *= u2;\n"
+        "   gl_FragColor = v;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInESSLCode(
+        "highp vec4 angle_compound_mul_frm(inout highp vec4 x, in highp float y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(foundInGLSLCode(
+        "vec4 angle_compound_mul_frm(inout vec4 x, in float y) {\n"
+        "    x = angle_frm(angle_frm(x) * y);"
+    ));
+    ASSERT_TRUE(
+        foundInHLSLCode("float4 angle_compound_mul_frm(inout float4 x, in float y) {\n"
+                        "    x = angle_frm(angle_frm(x) * y);"));
+    ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(v, angle_frm(u2));"));
+    ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_v, angle_frm(_u2));"));
+    ASSERT_TRUE(notFoundInCode("*="));
+}
+
+TEST_F(DebugShaderPrecisionTest, BinaryMathRounding)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u1;\n"
+        "uniform vec4 u2;\n"
+        "uniform vec4 u3;\n"
+        "uniform vec4 u4;\n"
+        "uniform vec4 u5;\n"
+        "void main() {\n"
+        "   vec4 v1 = u1 + u2;\n"
+        "   vec4 v2 = u2 - u3;\n"
+        "   vec4 v3 = u3 * u4;\n"
+        "   vec4 v4 = u4 / u5;\n"
+        "   vec4 v5;\n"
+        "   vec4 v6 = (v5 = u5);\n"
+        "   gl_FragColor = v1 + v2 + v3 + v4;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("v1 = angle_frm((angle_frm(u1) + angle_frm(u2)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm((angle_frm(u2) - angle_frm(u3)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v3 = angle_frm((angle_frm(u3) * angle_frm(u4)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v4 = angle_frm((angle_frm(u4) / angle_frm(u5)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v6 = angle_frm((v5 = angle_frm(u5)))"));
+
+    ASSERT_TRUE(foundInHLSLCode("v1 = angle_frm((angle_frm(_u1) + angle_frm(_u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("v2 = angle_frm((angle_frm(_u2) - angle_frm(_u3)))"));
+    ASSERT_TRUE(foundInHLSLCode("v3 = angle_frm((angle_frm(_u3) * angle_frm(_u4)))"));
+    ASSERT_TRUE(foundInHLSLCode("v4 = angle_frm((angle_frm(_u4) / angle_frm(_u5)))"));
+    ASSERT_TRUE(foundInHLSLCode("v6 = angle_frm((_v5 = angle_frm(_u5)))"));
+}
+
+TEST_F(DebugShaderPrecisionTest, BuiltInMathFunctionRounding)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u1;\n"
+        "uniform vec4 u2;\n"
+        "uniform vec4 u3;\n"
+        "uniform float uf;\n"
+        "uniform float uf2;\n"
+        "uniform vec3 uf31;\n"
+        "uniform vec3 uf32;\n"
+        "uniform mat4 um1;\n"
+        "uniform mat4 um2;\n"
+        "void main() {\n"
+        "   vec4 v1 = radians(u1);\n"
+        "   vec4 v2 = degrees(u1);\n"
+        "   vec4 v3 = sin(u1);\n"
+        "   vec4 v4 = cos(u1);\n"
+        "   vec4 v5 = tan(u1);\n"
+        "   vec4 v6 = asin(u1);\n"
+        "   vec4 v7 = acos(u1);\n"
+        "   vec4 v8 = atan(u1);\n"
+        "   vec4 v9 = atan(u1, u2);\n"
+        "   vec4 v10 = pow(u1, u2);\n"
+        "   vec4 v11 = exp(u1);\n"
+        "   vec4 v12 = log(u1);\n"
+        "   vec4 v13 = exp2(u1);\n"
+        "   vec4 v14 = log2(u1);\n"
+        "   vec4 v15 = sqrt(u1);\n"
+        "   vec4 v16 = inversesqrt(u1);\n"
+        "   vec4 v17 = abs(u1);\n"
+        "   vec4 v18 = sign(u1);\n"
+        "   vec4 v19 = floor(u1);\n"
+        "   vec4 v20 = ceil(u1);\n"
+        "   vec4 v21 = fract(u1);\n"
+        "   vec4 v22 = mod(u1, uf);\n"
+        "   vec4 v23 = mod(u1, u2);\n"
+        "   vec4 v24 = min(u1, uf);\n"
+        "   vec4 v25 = min(u1, u2);\n"
+        "   vec4 v26 = max(u1, uf);\n"
+        "   vec4 v27 = max(u1, u2);\n"
+        "   vec4 v28 = clamp(u1, u2, u3);\n"
+        "   vec4 v29 = clamp(u1, uf, uf2);\n"
+        "   vec4 v30 = mix(u1, u2, u3);\n"
+        "   vec4 v31 = mix(u1, u2, uf);\n"
+        "   vec4 v32 = step(u1, u2);\n"
+        "   vec4 v33 = step(uf, u1);\n"
+        "   vec4 v34 = smoothstep(u1, u2, u3);\n"
+        "   vec4 v35 = smoothstep(uf, uf2, u1);\n"
+        "   vec4 v36 = normalize(u1);\n"
+        "   vec4 v37 = faceforward(u1, u2, u3);\n"
+        "   vec4 v38 = reflect(u1, u2);\n"
+        "   vec4 v39 = refract(u1, u2, uf);\n"
+
+        "   float f1 = length(u1);\n"
+        "   float f2 = distance(u1, u2);\n"
+        "   float f3 = dot(u1, u2);\n"
+        "   vec3 vf31 = cross(uf31, uf32);\n"
+        "   mat4 m1 = matrixCompMult(um1, um2);\n"
+
+        "   gl_FragColor = v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10 +"
+            "v11 + v12 + v13 + v14 + v15 + v16 + v17 + v18 + v19 + v20 +"
+            "v21 + v22 + v23 + v24 + v25 + v26 + v27 + v28 + v29 + v30 +"
+            "v31 + v32 + v33 + v34 + v35 + v36 + v37 + v38 + v39 +"
+            "vec4(f1, f2, f3, 0.0) + vec4(vf31, 0.0) + m1[0];\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("v1 = angle_frm(radians(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm(degrees(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v3 = angle_frm(sin(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v4 = angle_frm(cos(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v5 = angle_frm(tan(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v6 = angle_frm(asin(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v7 = angle_frm(acos(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v8 = angle_frm(atan(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v9 = angle_frm(atan(angle_frm(u1), angle_frm(u2)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v10 = angle_frm(pow(angle_frm(u1), angle_frm(u2)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v11 = angle_frm(exp(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v12 = angle_frm(log(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v13 = angle_frm(exp2(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v14 = angle_frm(log2(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v15 = angle_frm(sqrt(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v16 = angle_frm(inversesqrt(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v17 = angle_frm(abs(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v18 = angle_frm(sign(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v19 = angle_frm(floor(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v20 = angle_frm(ceil(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v21 = angle_frm(fract(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v22 = angle_frm(mod(angle_frm(u1), angle_frm(uf)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v23 = angle_frm(mod(angle_frm(u1), angle_frm(u2)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v24 = angle_frm(min(angle_frm(u1), angle_frm(uf)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v25 = angle_frm(min(angle_frm(u1), angle_frm(u2)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v26 = angle_frm(max(angle_frm(u1), angle_frm(uf)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v27 = angle_frm(max(angle_frm(u1), angle_frm(u2)))"));
+    ASSERT_TRUE(
+        foundInAllGLSLCode("v28 = angle_frm(clamp(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
+    ASSERT_TRUE(
+        foundInAllGLSLCode("v29 = angle_frm(clamp(angle_frm(u1), angle_frm(uf), angle_frm(uf2)))"));
+    ASSERT_TRUE(
+        foundInAllGLSLCode("v30 = angle_frm(mix(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
+    ASSERT_TRUE(
+        foundInAllGLSLCode("v31 = angle_frm(mix(angle_frm(u1), angle_frm(u2), angle_frm(uf)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v32 = angle_frm(step(angle_frm(u1), angle_frm(u2)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v33 = angle_frm(step(angle_frm(uf), angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode(
+        "v34 = angle_frm(smoothstep(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
+    ASSERT_TRUE(foundInAllGLSLCode(
+        "v35 = angle_frm(smoothstep(angle_frm(uf), angle_frm(uf2), angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v36 = angle_frm(normalize(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode(
+        "v37 = angle_frm(faceforward(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v38 = angle_frm(reflect(angle_frm(u1), angle_frm(u2)))"));
+    ASSERT_TRUE(foundInAllGLSLCode(
+        "v39 = angle_frm(refract(angle_frm(u1), angle_frm(u2), angle_frm(uf)))"));
+
+    ASSERT_TRUE(foundInAllGLSLCode("f1 = angle_frm(length(angle_frm(u1)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("f2 = angle_frm(distance(angle_frm(u1), angle_frm(u2)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("f3 = angle_frm(dot(angle_frm(u1), angle_frm(u2)))"));
+    ASSERT_TRUE(foundInAllGLSLCode("vf31 = angle_frm(cross(angle_frm(uf31), angle_frm(uf32)))"));
+    ASSERT_TRUE(
+        foundInAllGLSLCode("m1 = angle_frm(matrixCompMult(angle_frm(um1), angle_frm(um2)))"));
+
+    ASSERT_TRUE(foundInHLSLCode("v1 = angle_frm(radians(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v2 = angle_frm(degrees(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v3 = angle_frm(sin(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v4 = angle_frm(cos(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v5 = angle_frm(tan(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v6 = angle_frm(asin(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v7 = angle_frm(acos(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v8 = angle_frm(atan(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v9 = angle_frm(webgl_atan_emu(angle_frm(_u1), angle_frm(_u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("v10 = angle_frm(pow(angle_frm(_u1), angle_frm(_u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("v11 = angle_frm(exp(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v12 = angle_frm(log(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v13 = angle_frm(exp2(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v14 = angle_frm(log2(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v15 = angle_frm(sqrt(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v16 = angle_frm(rsqrt(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v17 = angle_frm(abs(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v18 = angle_frm(sign(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v19 = angle_frm(floor(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v20 = angle_frm(ceil(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v21 = angle_frm(frac(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v22 = angle_frm(webgl_mod_emu(angle_frm(_u1), angle_frm(_uf)))"));
+    ASSERT_TRUE(foundInHLSLCode("v23 = angle_frm(webgl_mod_emu(angle_frm(_u1), angle_frm(_u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("v24 = angle_frm(min(angle_frm(_u1), angle_frm(_uf)))"));
+    ASSERT_TRUE(foundInHLSLCode("v25 = angle_frm(min(angle_frm(_u1), angle_frm(_u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("v26 = angle_frm(max(angle_frm(_u1), angle_frm(_uf)))"));
+    ASSERT_TRUE(foundInHLSLCode("v27 = angle_frm(max(angle_frm(_u1), angle_frm(_u2)))"));
+    ASSERT_TRUE(
+        foundInHLSLCode("v28 = angle_frm(clamp(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3)))"));
+    ASSERT_TRUE(
+        foundInHLSLCode("v29 = angle_frm(clamp(angle_frm(_u1), angle_frm(_uf), angle_frm(_uf2)))"));
+    ASSERT_TRUE(
+        foundInHLSLCode("v30 = angle_frm(lerp(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3)))"));
+    ASSERT_TRUE(
+        foundInHLSLCode("v31 = angle_frm(lerp(angle_frm(_u1), angle_frm(_u2), angle_frm(_uf)))"));
+    ASSERT_TRUE(foundInHLSLCode("v32 = angle_frm(step(angle_frm(_u1), angle_frm(_u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("v33 = angle_frm(step(angle_frm(_uf), angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode(
+        "v34 = angle_frm(smoothstep(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3)))"));
+    ASSERT_TRUE(foundInHLSLCode(
+        "v35 = angle_frm(smoothstep(angle_frm(_uf), angle_frm(_uf2), angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("v36 = angle_frm(normalize(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode(
+        "v37 = angle_frm(webgl_faceforward_emu(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3)))"));
+    ASSERT_TRUE(foundInHLSLCode("v38 = angle_frm(reflect(angle_frm(_u1), angle_frm(_u2)))"));
+    ASSERT_TRUE(foundInHLSLCode(
+        "v39 = angle_frm(refract(angle_frm(_u1), angle_frm(_u2), angle_frm(_uf)))"));
+
+    ASSERT_TRUE(foundInHLSLCode("f1 = angle_frm(length(angle_frm(_u1)))"));
+    ASSERT_TRUE(foundInHLSLCode("f2 = angle_frm(distance(angle_frm(_u1), angle_frm(_u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("f3 = angle_frm(dot(angle_frm(_u1), angle_frm(_u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("vf31 = angle_frm(cross(angle_frm(_uf31), angle_frm(_uf32)))"));
+    ASSERT_TRUE(foundInHLSLCode("m1 = angle_frm((angle_frm(_um1) * angle_frm(_um2)))"));
+}
+
+TEST_F(DebugShaderPrecisionTest, BuiltInRelationalFunctionRounding)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u1;\n"
+        "uniform vec4 u2;\n"
+        "void main() {\n"
+        "   bvec4 bv1 = lessThan(u1, u2);\n"
+        "   bvec4 bv2 = lessThanEqual(u1, u2);\n"
+        "   bvec4 bv3 = greaterThan(u1, u2);\n"
+        "   bvec4 bv4 = greaterThanEqual(u1, u2);\n"
+        "   bvec4 bv5 = equal(u1, u2);\n"
+        "   bvec4 bv6 = notEqual(u1, u2);\n"
+        "   gl_FragColor = vec4(bv1) + vec4(bv2) + vec4(bv3) + vec4(bv4) + vec4(bv5) + vec4(bv6);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("bv1 = lessThan(angle_frm(u1), angle_frm(u2))"));
+    ASSERT_TRUE(foundInAllGLSLCode("bv2 = lessThanEqual(angle_frm(u1), angle_frm(u2))"));
+    ASSERT_TRUE(foundInAllGLSLCode("bv3 = greaterThan(angle_frm(u1), angle_frm(u2))"));
+    ASSERT_TRUE(foundInAllGLSLCode("bv4 = greaterThanEqual(angle_frm(u1), angle_frm(u2))"));
+    ASSERT_TRUE(foundInAllGLSLCode("bv5 = equal(angle_frm(u1), angle_frm(u2))"));
+    ASSERT_TRUE(foundInAllGLSLCode("bv6 = notEqual(angle_frm(u1), angle_frm(u2))"));
+
+    ASSERT_TRUE(foundInHLSLCode("bv1 = (angle_frm(_u1) < angle_frm(_u2))"));
+    ASSERT_TRUE(foundInHLSLCode("bv2 = (angle_frm(_u1) <= angle_frm(_u2))"));
+    ASSERT_TRUE(foundInHLSLCode("bv3 = (angle_frm(_u1) > angle_frm(_u2))"));
+    ASSERT_TRUE(foundInHLSLCode("bv4 = (angle_frm(_u1) >= angle_frm(_u2))"));
+    ASSERT_TRUE(foundInHLSLCode("bv5 = (angle_frm(_u1) == angle_frm(_u2))"));
+    ASSERT_TRUE(foundInHLSLCode("bv6 = (angle_frm(_u1) != angle_frm(_u2))"));
+}
+
+TEST_F(DebugShaderPrecisionTest, ConstructorRounding)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "precision mediump int;\n"
+        "uniform float u1;\n"
+        "uniform float u2;\n"
+        "uniform lowp float u3;\n"
+        "uniform float u4;\n"
+        "uniform ivec4 uiv;\n"
+        "void main() {\n"
+        "   vec4 v1 = vec4(u1, u2, u3, u4);\n"
+        "   vec4 v2 = vec4(uiv);\n"
+        "   gl_FragColor = v1 + v2;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("v1 = angle_frm(vec4(u1, u2, angle_frl(u3), u4))"));
+    ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm(vec4(uiv))"));
+
+    ASSERT_TRUE(foundInHLSLCode("v1 = angle_frm(vec4(_u1, _u2, angle_frl(_u3), _u4))"));
+    ASSERT_TRUE(foundInHLSLCode("v2 = angle_frm(vec4(_uiv))"));
+}
+
+TEST_F(DebugShaderPrecisionTest, StructConstructorNoRounding)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "struct S { mediump vec4 a; };\n"
+        "uniform vec4 u;\n"
+        "void main() {\n"
+        "   S s = S(u);\n"
+        "   gl_FragColor = s.a;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("s = S(angle_frm(u))"));
+    ASSERT_TRUE(foundInHLSLCode("s = _S_ctor(angle_frm(_u))"));
+    ASSERT_TRUE(notFoundInCode("angle_frm(S"));
+}
+
+TEST_F(DebugShaderPrecisionTest, SwizzleRounding)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "void main() {\n"
+        "   vec4 v = u.xyxy;"
+        "   gl_FragColor = v;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("v = angle_frm(u).xyxy"));
+    ASSERT_TRUE(foundInHLSLCode("v = angle_frm(_u).xyxy"));
+}
+
+TEST_F(DebugShaderPrecisionTest, BuiltInTexFunctionRounding)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "precision lowp sampler2D;\n"
+        "uniform vec2 u;\n"
+        "uniform sampler2D s;\n"
+        "void main() {\n"
+        "   lowp vec4 v = texture2D(s, u);\n"
+        "   gl_FragColor = v;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("v = angle_frl(texture2D(s, angle_frm(u)))"));
+    ASSERT_TRUE(foundInHLSLCode("v = angle_frl(gl_texture2D(_s, angle_frm(_u)))"));
+}
+
+TEST_F(DebugShaderPrecisionTest, FunctionCallParameterQualifiersFromDefinition)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u1;\n"
+        "uniform vec4 u2;\n"
+        "uniform vec4 u3;\n"
+        "uniform vec4 u4;\n"
+        "uniform vec4 u5;\n"
+        "vec4 add(in vec4 x, in vec4 y) {\n"
+        "   return x + y;\n"
+        "}\n"
+        "void compound_add(inout vec4 x, in vec4 y) {\n"
+        "   x = x + y;\n"
+        "}\n"
+        "void add_to_last(in vec4 x, in vec4 y, out vec4 z) {\n"
+        "   z = x + y;\n"
+        "}\n"
+        "void main() {\n"
+        "   vec4 v = add(u1, u2);\n"
+        "   compound_add(v, u3);\n"
+        "   vec4 v2;\n"
+        "   add_to_last(u4, u5, v2);\n"
+        "   gl_FragColor = v + v2;\n"
+        "}\n";
+    compile(shaderString);
+    // Note that this is not optimal code, there are redundant frm calls.
+    // However, getting the implementation working when other operations
+    // are nested within function calls would be tricky if to get right
+    // otherwise.
+    // Test in parameters
+    ASSERT_TRUE(foundInAllGLSLCode("v = add(angle_frm(u1), angle_frm(u2))"));
+    ASSERT_TRUE(foundInHLSLCode("v = _add_float4_float4(angle_frm(_u1), angle_frm(_u2))"));
+    // Test inout parameter
+    ASSERT_TRUE(foundInAllGLSLCode("compound_add(v, angle_frm(u3))"));
+    ASSERT_TRUE(foundInHLSLCode("compound_add_float4_float4(_v, angle_frm(_u3))"));
+    // Test out parameter
+    ASSERT_TRUE(foundInAllGLSLCode("add_to_last(angle_frm(u4), angle_frm(u5), v2)"));
+    ASSERT_TRUE(
+        foundInHLSLCode("add_to_last_float4_float4_float4(angle_frm(_u4), angle_frm(_u5), _v2)"));
+}
+
+TEST_F(DebugShaderPrecisionTest, FunctionCallParameterQualifiersFromPrototype)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u1;\n"
+        "uniform vec4 u2;\n"
+        "uniform vec4 u3;\n"
+        "uniform vec4 u4;\n"
+        "uniform vec4 u5;\n"
+        "vec4 add(in vec4 x, in vec4 y);\n"
+        "void compound_add(inout vec4 x, in vec4 y);\n"
+        "void add_to_last(in vec4 x, in vec4 y, out vec4 z);\n"
+        "void main() {\n"
+        "   vec4 v = add(u1, u2);\n"
+        "   compound_add(v, u3);\n"
+        "   vec4 v2;\n"
+        "   add_to_last(u4, u5, v2);\n"
+        "   gl_FragColor = v + v2;\n"
+        "}\n"
+        "vec4 add(in vec4 x, in vec4 y) {\n"
+        "   return x + y;\n"
+        "}\n"
+        "void compound_add(inout vec4 x, in vec4 y) {\n"
+        "   x = x + y;\n"
+        "}\n"
+        "void add_to_last(in vec4 x, in vec4 y, out vec4 z) {\n"
+        "   z = x + y;\n"
+        "}\n";
+    compile(shaderString);
+    // Test in parameters
+    ASSERT_TRUE(foundInAllGLSLCode("v = add(angle_frm(u1), angle_frm(u2))"));
+    ASSERT_TRUE(foundInHLSLCode("v = _add_float4_float4(angle_frm(_u1), angle_frm(_u2))"));
+    // Test inout parameter
+    ASSERT_TRUE(foundInAllGLSLCode("compound_add(v, angle_frm(u3))"));
+    ASSERT_TRUE(foundInHLSLCode("compound_add_float4_float4(_v, angle_frm(_u3))"));
+    // Test out parameter
+    ASSERT_TRUE(foundInAllGLSLCode("add_to_last(angle_frm(u4), angle_frm(u5), v2)"));
+    ASSERT_TRUE(
+        foundInHLSLCode("add_to_last_float4_float4_float4(angle_frm(_u4), angle_frm(_u5), _v2)"));
+}
+
+TEST_F(DebugShaderPrecisionTest, NestedFunctionCalls)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u1;\n"
+        "uniform vec4 u2;\n"
+        "uniform vec4 u3;\n"
+        "vec4 add(in vec4 x, in vec4 y) {\n"
+        "   return x + y;\n"
+        "}\n"
+        "vec4 compound_add(inout vec4 x, in vec4 y) {\n"
+        "   x = x + y;\n"
+        "   return x;\n"
+        "}\n"
+        "void main() {\n"
+        "   vec4 v = u1;\n"
+        "   vec4 v2 = add(compound_add(v, u2), fract(u3));\n"
+        "   gl_FragColor = v + v2;\n"
+        "}\n";
+    compile(shaderString);
+    // Test nested calls
+    ASSERT_TRUE(foundInAllGLSLCode(
+        "v2 = add(compound_add(v, angle_frm(u2)), angle_frm(fract(angle_frm(u3))))"));
+    ASSERT_TRUE(
+        foundInHLSLCode("v2 = _add_float4_float4(_compound_add_float4_float4(_v, angle_frm(_u2)), "
+                        "angle_frm(frac(angle_frm(_u3))))"));
+}
+
+// Test that code inside an index of a function out parameter gets processed.
+TEST_F(DebugShaderPrecisionTest, OpInIndexOfFunctionOutParameter)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void foo(out vec4 f) { f.x = 0.0; }\n"
+        "uniform float u2;\n"
+        "void main() {\n"
+        "   vec4 v[2];\n"
+        "   foo(v[int(exp2(u2))]);\n"
+        "   gl_FragColor = v[0];\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("angle_frm(exp2(angle_frm(u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("angle_frm(exp2(angle_frm(_u2)))"));
+}
+
+// Test that code inside an index of an l-value gets processed.
+TEST_F(DebugShaderPrecisionTest, OpInIndexOfLValue)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u1;\n"
+        "uniform float u2;\n"
+        "void main() {\n"
+        "   vec4 v[2];\n"
+        "   v[int(exp2(u2))] = u1;\n"
+        "   gl_FragColor = v[0];\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("angle_frm(exp2(angle_frm(u2)))"));
+    ASSERT_TRUE(foundInHLSLCode("angle_frm(exp2(angle_frm(_u2)))"));
+}
+
+// Test that the out parameter of modf doesn't get rounded
+TEST_F(DebugShaderPrecisionTest, ModfOutParameter)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   float o;\n"
+        "   float f = modf(u, o);\n"
+        "   my_FragColor = vec4(f, o, 0, 1);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInAllGLSLCode("modf(angle_frm(u), o)"));
+    ASSERT_TRUE(foundInHLSLCode("modf(angle_frm(_u), _o)"));
+}
+
+#if defined(ANGLE_ENABLE_HLSL)
+// Tests precision emulation with HLSL 3.0 output -- should error gracefully.
+TEST(DebugShaderPrecisionNegativeTest, HLSL3Unsupported)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(u);\n"
+        "}\n";
+    std::string infoLog;
+    std::string translatedCode;
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+    resources.WEBGL_debug_shader_precision = 1;
+    ASSERT_FALSE(compileTestShader(GL_FRAGMENT_SHADER, SH_GLES3_SPEC, SH_HLSL_3_0_OUTPUT,
+                                   shaderString, &resources, 0, &translatedCode, &infoLog));
+}
+#endif  // defined(ANGLE_ENABLE_HLSL)
diff --git a/src/third_party/angle/src/tests/compiler_tests/EXT_YUV_target_test.cpp b/src/third_party/angle/src/tests/compiler_tests/EXT_YUV_target_test.cpp
new file mode 100644
index 0000000..35557fd
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/EXT_YUV_target_test.cpp
@@ -0,0 +1,340 @@
+//
+// Copyright (c) 2017 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.
+//
+// EXT_YUV_target.cpp:
+//   Test for EXT_YUV_target implementation.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+using testing::Combine;
+using testing::Values;
+
+namespace
+{
+const char ESSLVersion300[] = "#version 300 es\n";
+const char EXTYTPragma[]    = "#extension GL_EXT_YUV_target : require\n";
+
+const char ESSL300_SimpleShader[] =
+    "precision mediump float;\n"
+    "uniform __samplerExternal2DY2YEXT uSampler;\n"
+    "out vec4 fragColor;\n"
+    "void main() { \n"
+    "    fragColor = vec4(1.0);\n"
+    "}\n";
+
+// Shader that samples the texture and writes to FragColor.
+const char ESSL300_FragColorShader[] =
+    "precision mediump float;\n"
+    "uniform __samplerExternal2DY2YEXT uSampler;\n"
+    "layout(yuv) out vec4 fragColor;\n"
+    "void main() { \n"
+    "    fragColor = texture(uSampler, vec2(0.0));\n"
+    "}\n";
+
+// Shader that specifies yuv layout qualifier multiple times.
+const char ESSL300_YUVQualifierMultipleTimesShader[] =
+    "precision mediump float;\n"
+    "layout(yuv, yuv, yuv) out vec4 fragColor;\n"
+    "void main() { \n"
+    "}\n";
+
+// Shader that specifies yuv layout qualifier for not output fails to compile.
+const char ESSL300_YUVQualifierFailureShader1[] =
+    "precision mediump float;\n"
+    "layout(yuv) in vec4 fragColor;\n"
+    "void main() { \n"
+    "}\n";
+
+const char ESSL300_YUVQualifierFailureShader2[] =
+    "precision mediump float;\n"
+    "layout(yuv) uniform;\n"
+    "layout(yuv) uniform Transform {\n"
+    "     mat4 M1;\n"
+    "}\n"
+    "void main() { \n"
+    "}\n";
+
+// Shader that specifies yuv layout qualifier with location fails to compile.
+const char ESSL300_LocationAndYUVFailureShader[] =
+    "precision mediump float;\n"
+    "layout(location = 0, yuv) out vec4 fragColor;\n"
+    "void main() { \n"
+    "}\n";
+
+// Shader that specifies yuv layout qualifier with multiple color outputs fails to compile.
+const char ESSL300_MultipleColorAndYUVOutputsFailureShader1[] =
+    "precision mediump float;\n"
+    "layout(yuv) out vec4 fragColor;\n"
+    "layout out vec4 fragColor1;\n"
+    "void main() { \n"
+    "}\n";
+
+const char ESSL300_MultipleColorAndYUVOutputsFailureShader2[] =
+    "precision mediump float;\n"
+    "layout(yuv) out vec4 fragColor;\n"
+    "layout(location = 1) out vec4 fragColor1;\n"
+    "void main() { \n"
+    "}\n";
+
+// Shader that specifies yuv layout qualifier with depth output fails to compile.
+const char ESSL300_DepthAndYUVOutputsFailureShader[] =
+    "precision mediump float;\n"
+    "layout(yuv) out vec4 fragColor;\n"
+    "void main() { \n"
+    "    gl_FragDepth = 1.0f;\n"
+    "}\n";
+
+// Shader that specifies yuv layout qualifier with multiple outputs fails to compile.
+const char ESSL300_MultipleYUVOutputsFailureShader[] =
+    "precision mediump float;\n"
+    "layout(yuv) out vec4 fragColor;\n"
+    "layout(yuv) out vec4 fragColor1;\n"
+    "void main() { \n"
+    "}\n";
+
+// Shader that specifies yuvCscStandartEXT type and associated values.
+const char ESSL300_YuvCscStandardEXTShader[] =
+    "precision mediump float;\n"
+    "yuvCscStandardEXT;\n"
+    "yuvCscStandardEXT conv;\n"
+    "yuvCscStandardEXT conv1 = itu_601;\n"
+    "yuvCscStandardEXT conv2 = itu_601_full_range;\n"
+    "yuvCscStandardEXT conv3 = itu_709;\n"
+    "const yuvCscStandardEXT conv4 = itu_709;\n"
+    "yuvCscStandardEXT conv_standard() {\n"
+    "    return itu_601;\n"
+    "}\n"
+    "bool is_itu_601(inout yuvCscStandardEXT csc) {\n"
+    "    csc = itu_601;\n"
+    "    return csc == itu_601;\n"
+    "}\n"
+    "bool is_itu_709(yuvCscStandardEXT csc) {\n"
+    "    return csc == itu_709;\n"
+    "}\n"
+    "void main() { \n"
+    "    yuvCscStandardEXT conv = conv_standard();\n"
+    "    bool csc_check1 = is_itu_601(conv);\n"
+    "    bool csc_check2 = is_itu_709(itu_709);\n"
+    "}\n";
+
+// Shader that specifies yuvCscStandartEXT type constructor fails to compile.
+const char ESSL300_YuvCscStandartdEXTConstructFailureShader1[] =
+    "precision mediump float;\n"
+    "yuvCscStandardEXT conv = yuvCscStandardEXT();\n"
+    "void main() { \n"
+    "}\n";
+
+const char ESSL300_YuvCscStandartdEXTConstructFailureShader2[] =
+    "precision mediump float;\n"
+    "yuvCscStandardEXT conv = yuvCscStandardEXT(itu_601);\n"
+    "void main() { \n"
+    "}\n";
+
+// Shader that specifies yuvCscStandartEXT type conversion fails to compile.
+const char ESSL300_YuvCscStandartdEXTConversionFailureShader1[] =
+    "precision mediump float;\n"
+    "yuvCscStandardEXT conv = false;\n"
+    "void main() { \n"
+    "}\n";
+
+const char ESSL300_YuvCscStandartdEXTConversionFailureShader2[] =
+    "precision mediump float;\n"
+    "yuvCscStandardEXT conv = 0;\n"
+    "void main() { \n"
+    "}\n";
+
+const char ESSL300_YuvCscStandartdEXTConversionFailureShader3[] =
+    "precision mediump float;\n"
+    "yuvCscStandardEXT conv = 2.0f;\n"
+    "void main() { \n"
+    "}\n";
+
+const char ESSL300_YuvCscStandartdEXTConversionFailureShader4[] =
+    "precision mediump float;\n"
+    "yuvCscStandardEXT conv = itu_601 | itu_709;\n"
+    "void main() { \n"
+    "}\n";
+
+const char ESSL300_YuvCscStandartdEXTConversionFailureShader5[] =
+    "precision mediump float;\n"
+    "yuvCscStandardEXT conv = itu_601 & 3.0f;\n"
+    "void main() { \n"
+    "}\n";
+
+// Shader that specifies yuvCscStandartEXT type qualifiers fails to compile.
+const char ESSL300_YuvCscStandartdEXTQualifiersFailureShader1[] =
+    "precision mediump float;\n"
+    "in yuvCscStandardEXT conv = itu_601;\n"
+    "void main() { \n"
+    "}\n";
+
+const char ESSL300_YuvCscStandartdEXTQualifiersFailureShader2[] =
+    "precision mediump float;\n"
+    "out yuvCscStandardEXT conv = itu_601;\n"
+    "void main() { \n"
+    "}\n";
+
+const char ESSL300_YuvCscStandartdEXTQualifiersFailureShader3[] =
+    "precision mediump float;\n"
+    "uniform yuvCscStandardEXT conv = itu_601;\n"
+    "void main() { \n"
+    "}\n";
+
+// Shader that specifies yuv_to_rgb() and rgb_to_yuv() built-in functions.
+const char ESSL300_BuiltInFunctionsShader[] =
+    "precision mediump float;\n"
+    "yuvCscStandardEXT conv = itu_601;\n"
+    "void main() { \n"
+    "    vec3 yuv = rgb_2_yuv(vec3(0.0f), conv);\n"
+    "    vec3 rgb = yuv_2_rgb(yuv, itu_601);\n"
+    "}\n";
+
+class EXTYUVTargetTest : public testing::TestWithParam<testing::tuple<const char *, const char *>>
+{
+  protected:
+    virtual void SetUp()
+    {
+        sh::InitBuiltInResources(&mResources);
+        mResources.EXT_YUV_target = 1;
+
+        mCompiler = nullptr;
+    }
+
+    virtual void TearDown() { DestroyCompiler(); }
+    void DestroyCompiler()
+    {
+        if (mCompiler)
+        {
+            sh::Destruct(mCompiler);
+            mCompiler = nullptr;
+        }
+    }
+
+    void InitializeCompiler()
+    {
+        DestroyCompiler();
+        mCompiler =
+            sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES3_SPEC, SH_ESSL_OUTPUT, &mResources);
+        ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
+    }
+
+    testing::AssertionResult TestShaderCompile(const char *pragma)
+    {
+        return TestShaderCompile(testing::get<0>(GetParam()),  // Version.
+                                 pragma,
+                                 testing::get<1>(GetParam())  // Shader.
+                                 );
+    }
+
+    testing::AssertionResult TestShaderCompile(const char *version,
+                                               const char *pragma,
+                                               const char *shader)
+    {
+        const char *shaderStrings[] = {version, pragma, shader};
+        bool success                = sh::Compile(mCompiler, shaderStrings, 3, 0);
+        if (success)
+        {
+            return ::testing::AssertionSuccess() << "Compilation success";
+        }
+        return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
+    }
+
+  protected:
+    ShBuiltInResources mResources;
+    ShHandle mCompiler;
+};
+
+// Extension flag is required to compile properly. Expect failure when it is
+// not present.
+TEST_P(EXTYUVTargetTest, CompileFailsWithoutExtension)
+{
+    mResources.EXT_YUV_target = 0;
+    InitializeCompiler();
+    EXPECT_FALSE(TestShaderCompile(EXTYTPragma));
+}
+
+// Extension directive is required to compile properly. Expect failure when
+// it is not present.
+TEST_P(EXTYUVTargetTest, CompileFailsWithExtensionWithoutPragma)
+{
+    mResources.EXT_YUV_target = 1;
+    InitializeCompiler();
+    EXPECT_FALSE(TestShaderCompile(""));
+}
+
+// With extension flag and extension directive, compiling succeeds.
+// Also test that the extension directive state is reset correctly.
+TEST_P(EXTYUVTargetTest, CompileSucceedsWithExtensionAndPragma)
+{
+    mResources.EXT_YUV_target = 1;
+    InitializeCompiler();
+    EXPECT_TRUE(TestShaderCompile(EXTYTPragma));
+    // Test reset functionality.
+    EXPECT_FALSE(TestShaderCompile(""));
+    EXPECT_TRUE(TestShaderCompile(EXTYTPragma));
+}
+
+INSTANTIATE_TEST_CASE_P(CorrectVariantsWithExtensionAndPragma,
+                        EXTYUVTargetTest,
+                        Combine(Values(ESSLVersion300),
+                                Values(ESSL300_SimpleShader, ESSL300_FragColorShader)));
+
+class EXTYUVTargetCompileSuccessTest : public EXTYUVTargetTest
+{
+};
+
+TEST_P(EXTYUVTargetCompileSuccessTest, CompileSucceeds)
+{
+    // Expect compile success.
+    mResources.EXT_YUV_target = 1;
+    InitializeCompiler();
+    EXPECT_TRUE(TestShaderCompile(EXTYTPragma));
+}
+
+INSTANTIATE_TEST_CASE_P(CorrectESSL300Shaders,
+                        EXTYUVTargetCompileSuccessTest,
+                        Combine(Values(ESSLVersion300),
+                                Values(ESSL300_FragColorShader,
+                                       ESSL300_YUVQualifierMultipleTimesShader,
+                                       ESSL300_YuvCscStandardEXTShader,
+                                       ESSL300_BuiltInFunctionsShader)));
+
+class EXTYUVTargetCompileFailureTest : public EXTYUVTargetTest
+{
+};
+
+TEST_P(EXTYUVTargetCompileFailureTest, CompileFails)
+{
+    // Expect compile failure due to shader error, with shader having correct pragma.
+    mResources.EXT_YUV_target = 1;
+    InitializeCompiler();
+    EXPECT_FALSE(TestShaderCompile(EXTYTPragma));
+}
+
+INSTANTIATE_TEST_CASE_P(IncorrectESSL300Shaders,
+                        EXTYUVTargetCompileFailureTest,
+                        Combine(Values(ESSLVersion300),
+                                Values(ESSL300_YUVQualifierFailureShader1,
+                                       ESSL300_YUVQualifierFailureShader2,
+                                       ESSL300_LocationAndYUVFailureShader,
+                                       ESSL300_MultipleColorAndYUVOutputsFailureShader1,
+                                       ESSL300_MultipleColorAndYUVOutputsFailureShader2,
+                                       ESSL300_DepthAndYUVOutputsFailureShader,
+                                       ESSL300_MultipleYUVOutputsFailureShader,
+                                       ESSL300_YuvCscStandartdEXTConstructFailureShader1,
+                                       ESSL300_YuvCscStandartdEXTConstructFailureShader2,
+                                       ESSL300_YuvCscStandartdEXTConversionFailureShader1,
+                                       ESSL300_YuvCscStandartdEXTConversionFailureShader2,
+                                       ESSL300_YuvCscStandartdEXTConversionFailureShader3,
+                                       ESSL300_YuvCscStandartdEXTConversionFailureShader4,
+                                       ESSL300_YuvCscStandartdEXTConversionFailureShader5,
+                                       ESSL300_YuvCscStandartdEXTQualifiersFailureShader1,
+                                       ESSL300_YuvCscStandartdEXTQualifiersFailureShader2,
+                                       ESSL300_YuvCscStandartdEXTQualifiersFailureShader3)));
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp b/src/third_party/angle/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp
new file mode 100644
index 0000000..7d965d7
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp
@@ -0,0 +1,285 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// EXT_blend_func_extended.cpp:
+//   Test for EXT_blend_func_extended_test
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+using testing::Combine;
+using testing::Values;
+using testing::make_tuple;
+
+namespace
+{
+const char ESSLVersion100[] = "#version 100\n";
+const char ESSLVersion300[] = "#version 300 es\n";
+const char ESSLVersion310[] = "#version 310 es\n";
+const char EXTBFEPragma[]   = "#extension GL_EXT_blend_func_extended : require\n";
+
+const char ESSL100_SimpleShader1[] =
+    "precision mediump float;\n"
+    "void main() { \n"
+    "    gl_FragColor = vec4(1.0);\n"
+    "    gl_SecondaryFragColorEXT = vec4(gl_MaxDualSourceDrawBuffersEXT / 10);\n"
+    "}\n";
+
+// Shader that tests only the access to gl_MaxDualSourceDrawBuffersEXT.
+const char ESSL100_MaxDualSourceAccessShader[] =
+    "precision mediump float;\n"
+    "void main() { gl_FragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10); }\n";
+
+// Shader that writes to SecondaryFragData.
+const char ESSL100_FragDataShader[] =
+    "#extension GL_EXT_draw_buffers : require\n"
+    "precision mediump float;\n"
+    "void main() {\n"
+    "    gl_FragData[gl_MaxDrawBuffers - 1] = vec4(1.0);\n"
+    "    gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT - 1] = vec4(0.1);\n"
+    "}\n";
+
+// Shader that writes to SecondaryFragColor and SecondaryFragData does not compile.
+const char ESSL100_ColorAndDataWriteFailureShader1[] =
+    "precision mediump float;\n"
+    "void main() {\n"
+    "    gl_SecondaryFragColorEXT = vec4(1.0);\n"
+    "    gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT] = vec4(0.1);\n"
+    "}\n";
+
+// Shader that writes to FragColor and SecondaryFragData does not compile.
+const char ESSL100_ColorAndDataWriteFailureShader2[] =
+    "precision mediump float;\n"
+    "void main() {\n"
+    "    gl_FragColor = vec4(1.0);\n"
+    "    gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT] = vec4(0.1);\n"
+    "}\n";
+
+// Shader that writes to FragData and SecondaryFragColor.
+const char ESSL100_ColorAndDataWriteFailureShader3[] =
+    "#extension GL_EXT_draw_buffers : require\n"
+    "precision mediump float;\n"
+    "void main() {\n"
+    "    gl_SecondaryFragColorEXT = vec4(1.0);\n"
+    "    gl_FragData[gl_MaxDrawBuffers] = vec4(0.1);\n"
+    "}\n";
+
+// In GLSL version 300 es, the gl_MaxDualSourceDrawBuffersEXT is available.
+const char ESSL300_MaxDualSourceAccessShader[] =
+    "precision mediump float;\n"
+    "layout(location = 0) out mediump vec4 fragColor;"
+    "void main() {\n"
+    "    fragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10);\n"
+    "}\n";
+
+// In GLSL version 300 es, the only way to write a correct shader is to require the extension and
+// then leave the locations unspecified. The caller will then bind the variables with the extension
+// binding functions.
+const char ESSL300_LocationAndUnspecifiedOutputShader[] =
+    "precision mediump float;\n"
+    "layout(location = 0) out mediump vec4 fragColor;"
+    "out mediump vec4 secondaryFragColor;"
+    "void main() {\n"
+    "    fragColor = vec4(1.0);\n"
+    "    secondaryFragColor = vec4(1.0);\n"
+    "}\n";
+
+const char ESSL300_TwoUnspecifiedLocationOutputsShader[] =
+    "precision mediump float;\n"
+    "out mediump vec4 fragColor;"
+    "out mediump vec4 secondaryFragColor;"
+    "void main() {\n"
+    "    fragColor = vec4(1.0);\n"
+    "    secondaryFragColor = vec4(1.0);\n"
+    "}\n";
+
+// Shader that is correct in GLSL ES 3.10 fails when used in version 300 es.
+const char ESSL310_LocationIndexShader[] =
+    "precision mediump float;\n"
+    "layout(location = 0) out mediump vec4 fragColor;"
+    "layout(location = 0, index = 1) out mediump vec4 secondaryFragColor;"
+    "void main() {\n"
+    "   fragColor = vec4(1);\n"
+    "   secondaryFragColor = vec4(1);\n"
+    "}\n";
+
+// Shader that specifies index layout qualifier but not location fails to compile. Currently fails
+// to compile due to version 310 es not being supported.
+const char ESSL310_LocationIndexFailureShader[] =
+    "precision mediump float;\n"
+    "layout(location = 0) out mediump vec4 fragColor;"
+    "layout(index = 1) out mediump vec4 secondaryFragColor;"
+    "void main() {\n"
+    "   fragColor = vec4(1.0);\n"
+    "   secondaryFragColor = vec4(1.0);\n"
+    "}\n";
+
+class EXTBlendFuncExtendedTest
+    : public testing::TestWithParam<testing::tuple<ShShaderSpec, const char *, const char *>>
+{
+  protected:
+    virtual void SetUp()
+    {
+        sh::InitBuiltInResources(&mResources);
+        // EXT_draw_buffers is used in some of the shaders for test purposes.
+        mResources.EXT_draw_buffers = 1;
+        mResources.NV_draw_buffers  = 2;
+
+        mCompiler = nullptr;
+    }
+
+    virtual void TearDown() { DestroyCompiler(); }
+    void DestroyCompiler()
+    {
+        if (mCompiler)
+        {
+            sh::Destruct(mCompiler);
+            mCompiler = nullptr;
+        }
+    }
+
+    void InitializeCompiler()
+    {
+        DestroyCompiler();
+        mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()),
+                                          SH_GLSL_COMPATIBILITY_OUTPUT, &mResources);
+        ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
+    }
+
+    testing::AssertionResult TestShaderCompile(const char *pragma)
+    {
+        return TestShaderCompile(testing::get<1>(GetParam()),  // Version.
+                                 pragma,
+                                 testing::get<2>(GetParam())  // Shader.
+                                 );
+    }
+
+    testing::AssertionResult TestShaderCompile(const char *version,
+                                               const char *pragma,
+                                               const char *shader)
+    {
+        const char *shaderStrings[] = {version, pragma, shader};
+        bool success                = sh::Compile(mCompiler, shaderStrings, 3, 0);
+        if (success)
+        {
+            return ::testing::AssertionSuccess() << "Compilation success";
+        }
+        return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
+    }
+
+  protected:
+    ShBuiltInResources mResources;
+    ShHandle mCompiler;
+};
+
+// Extension flag is required to compile properly. Expect failure when it is
+// not present.
+TEST_P(EXTBlendFuncExtendedTest, CompileFailsWithoutExtension)
+{
+    mResources.EXT_blend_func_extended = 0;
+    InitializeCompiler();
+    EXPECT_FALSE(TestShaderCompile(EXTBFEPragma));
+}
+
+// Extension directive is required to compile properly. Expect failure when
+// it is not present.
+TEST_P(EXTBlendFuncExtendedTest, CompileFailsWithExtensionWithoutPragma)
+{
+    mResources.EXT_blend_func_extended  = 1;
+    mResources.MaxDualSourceDrawBuffers = 1;
+    InitializeCompiler();
+    EXPECT_FALSE(TestShaderCompile(""));
+}
+
+// With extension flag and extension directive, compiling succeeds.
+// Also test that the extension directive state is reset correctly.
+TEST_P(EXTBlendFuncExtendedTest, CompileSucceedsWithExtensionAndPragma)
+{
+    mResources.EXT_blend_func_extended  = 1;
+    mResources.MaxDualSourceDrawBuffers = 1;
+    InitializeCompiler();
+    EXPECT_TRUE(TestShaderCompile(EXTBFEPragma));
+    // Test reset functionality.
+    EXPECT_FALSE(TestShaderCompile(""));
+    EXPECT_TRUE(TestShaderCompile(EXTBFEPragma));
+}
+
+// The SL #version 100 shaders that are correct work similarly
+// in both GL2 and GL3, with and without the version string.
+INSTANTIATE_TEST_CASE_P(CorrectESSL100Shaders,
+                        EXTBlendFuncExtendedTest,
+                        Combine(Values(SH_GLES2_SPEC, SH_GLES3_SPEC),
+                                Values("", ESSLVersion100),
+                                Values(ESSL100_SimpleShader1,
+                                       ESSL100_MaxDualSourceAccessShader,
+                                       ESSL100_FragDataShader)));
+
+INSTANTIATE_TEST_CASE_P(CorrectESSL300Shaders,
+                        EXTBlendFuncExtendedTest,
+                        Combine(Values(SH_GLES3_SPEC),
+                                Values(ESSLVersion300),
+                                Values(ESSL300_MaxDualSourceAccessShader,
+                                       ESSL300_LocationAndUnspecifiedOutputShader,
+                                       ESSL300_TwoUnspecifiedLocationOutputsShader)));
+
+class EXTBlendFuncExtendedCompileFailureTest : public EXTBlendFuncExtendedTest
+{
+};
+
+TEST_P(EXTBlendFuncExtendedCompileFailureTest, CompileFails)
+{
+    // Expect compile failure due to shader error, with shader having correct pragma.
+    mResources.EXT_blend_func_extended  = 1;
+    mResources.MaxDualSourceDrawBuffers = 1;
+    InitializeCompiler();
+    EXPECT_FALSE(TestShaderCompile(EXTBFEPragma));
+}
+
+// Incorrect #version 100 shaders fail.
+INSTANTIATE_TEST_CASE_P(IncorrectESSL100Shaders,
+                        EXTBlendFuncExtendedCompileFailureTest,
+                        Combine(Values(SH_GLES2_SPEC),
+                                Values(ESSLVersion100),
+                                Values(ESSL100_ColorAndDataWriteFailureShader1,
+                                       ESSL100_ColorAndDataWriteFailureShader2,
+                                       ESSL100_ColorAndDataWriteFailureShader3)));
+
+// Correct #version 300 es shaders fail in GLES2 context, regardless of version string.
+INSTANTIATE_TEST_CASE_P(CorrectESSL300Shaders,
+                        EXTBlendFuncExtendedCompileFailureTest,
+                        Combine(Values(SH_GLES2_SPEC),
+                                Values("", ESSLVersion100, ESSLVersion300),
+                                Values(ESSL300_LocationAndUnspecifiedOutputShader,
+                                       ESSL300_TwoUnspecifiedLocationOutputsShader)));
+
+// Correct #version 100 shaders fail when used with #version 300 es.
+INSTANTIATE_TEST_CASE_P(CorrectESSL100Shaders,
+                        EXTBlendFuncExtendedCompileFailureTest,
+                        Combine(Values(SH_GLES3_SPEC),
+                                Values(ESSLVersion300),
+                                Values(ESSL100_SimpleShader1, ESSL100_FragDataShader)));
+
+// Incorrect #version 310 es always fails.
+INSTANTIATE_TEST_CASE_P(IncorrectESSL310Shaders,
+                        EXTBlendFuncExtendedCompileFailureTest,
+                        Combine(Values(SH_GLES3_SPEC),
+                                Values(ESSLVersion300, ESSLVersion310),
+                                Values(ESSL310_LocationIndexFailureShader)));
+
+// Correct #version 310 es fails in #version 300 es.
+INSTANTIATE_TEST_CASE_P(
+    CorrectESSL310ShadersInESSL300,
+    EXTBlendFuncExtendedCompileFailureTest,
+    Values(make_tuple(SH_GLES3_SPEC, &ESSLVersion300[0], &ESSL310_LocationIndexShader[0])));
+
+// Correct #version 310 es fails in #version 310 es, due to 3.1 not being supported.
+INSTANTIATE_TEST_CASE_P(
+    CorrectESSL310Shaders,
+    EXTBlendFuncExtendedCompileFailureTest,
+    Values(make_tuple(SH_GLES3_SPEC, &ESSLVersion310[0], &ESSL310_LocationIndexShader[0])));
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/compiler_tests/EmulateGLFragColorBroadcast_test.cpp b/src/third_party/angle/src/tests/compiler_tests/EmulateGLFragColorBroadcast_test.cpp
new file mode 100644
index 0000000..07cf3fd
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/EmulateGLFragColorBroadcast_test.cpp
@@ -0,0 +1,81 @@
+//
+// Copyright (c) 2016 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.
+//
+// EmulateGLFragColorBroadcast_test.cpp:
+//   Tests for gl_FragColor broadcast behavior emulation.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+namespace
+{
+
+const int kMaxDrawBuffers = 2;
+
+class EmulateGLFragColorBroadcastTest : public MatchOutputCodeTest
+{
+  public:
+    EmulateGLFragColorBroadcastTest()
+        : MatchOutputCodeTest(GL_FRAGMENT_SHADER,
+                              0,  // compile options
+                              SH_GLSL_COMPATIBILITY_OUTPUT)
+    {
+        getResources()->MaxDrawBuffers   = kMaxDrawBuffers;
+        getResources()->EXT_draw_buffers = 1;
+    }
+};
+
+// Verifies that without explicitly enabling GL_EXT_draw_buffers extension
+// in the shader, no broadcast emulation.
+TEST_F(EmulateGLFragColorBroadcastTest, FragColorNoBroadcast)
+{
+    const std::string shaderString =
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1, 0, 0, 0);\n"
+        "}\n";
+    compile(shaderString);
+    EXPECT_TRUE(foundInCode("gl_FragColor"));
+    EXPECT_FALSE(foundInCode("gl_FragData[0]"));
+    EXPECT_FALSE(foundInCode("gl_FragData[1]"));
+}
+
+// Verifies that with explicitly enabling GL_EXT_draw_buffers extension
+// in the shader, broadcast is emualted by replacing gl_FragColor with gl_FragData.
+TEST_F(EmulateGLFragColorBroadcastTest, FragColorBroadcast)
+{
+    const std::string shaderString =
+        "#extension GL_EXT_draw_buffers : require\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1, 0, 0, 0);\n"
+        "}\n";
+    compile(shaderString);
+    EXPECT_FALSE(foundInCode("gl_FragColor"));
+    EXPECT_TRUE(foundInCode("gl_FragData[0]"));
+    EXPECT_TRUE(foundInCode("gl_FragData[1]"));
+}
+
+// Verifies that with explicitly enabling GL_EXT_draw_buffers extension
+// in the shader with an empty main(), anothing happens.
+TEST_F(EmulateGLFragColorBroadcastTest, EmptyMain)
+{
+    const std::string shaderString =
+        "#extension GL_EXT_draw_buffers : require\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    compile(shaderString);
+    EXPECT_FALSE(foundInCode("gl_FragColor"));
+    EXPECT_FALSE(foundInCode("gl_FragData[0]"));
+    EXPECT_FALSE(foundInCode("gl_FragData[1]"));
+}
+
+}  // namespace anonymous
diff --git a/src/third_party/angle/src/tests/compiler_tests/ExpressionLimit_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ExpressionLimit_test.cpp
new file mode 100644
index 0000000..8aefe23
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ExpressionLimit_test.cpp
@@ -0,0 +1,541 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#include <sstream>
+#include <string>
+#include <vector>
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define SHADER(Src) #Src
+
+class ExpressionLimitTest : public testing::Test {
+protected:
+    static const int kMaxExpressionComplexity = 16;
+    static const int kMaxCallStackDepth       = 16;
+    static const int kMaxFunctionParameters   = 16;
+    static const char* kExpressionTooComplex;
+    static const char* kCallStackTooDeep;
+    static const char* kHasRecursion;
+    static const char *kTooManyParameters;
+
+    virtual void SetUp()
+    {
+        memset(&resources, 0, sizeof(resources));
+
+        GenerateResources(&resources);
+    }
+
+    // Set up the per compile resources
+    static void GenerateResources(ShBuiltInResources *res)
+    {
+        sh::InitBuiltInResources(res);
+
+        res->MaxVertexAttribs             = 8;
+        res->MaxVertexUniformVectors      = 128;
+        res->MaxVaryingVectors            = 8;
+        res->MaxVertexTextureImageUnits   = 0;
+        res->MaxCombinedTextureImageUnits = 8;
+        res->MaxTextureImageUnits         = 8;
+        res->MaxFragmentUniformVectors    = 16;
+        res->MaxDrawBuffers               = 1;
+
+        res->OES_standard_derivatives = 0;
+        res->OES_EGL_image_external   = 0;
+
+        res->MaxExpressionComplexity = kMaxExpressionComplexity;
+        res->MaxCallStackDepth       = kMaxCallStackDepth;
+        res->MaxFunctionParameters   = kMaxFunctionParameters;
+    }
+
+    void GenerateLongExpression(int length, std::stringstream* ss)
+    {
+        for (int ii = 0; ii < length; ++ii) {
+          *ss << "+ vec4(" << ii << ")";
+        }
+    }
+
+    std::string GenerateShaderWithLongExpression(int length)
+    {
+        static const char* shaderStart = SHADER(
+            precision mediump float;
+            uniform vec4 u_color;
+            void main()
+            {
+               gl_FragColor = u_color
+        );
+
+        std::stringstream ss;
+        ss << shaderStart;
+        GenerateLongExpression(length, &ss);
+        ss << "; }";
+
+        return ss.str();
+    }
+
+    std::string GenerateShaderWithUnusedLongExpression(int length)
+    {
+        static const char* shaderStart = SHADER(
+            precision mediump float;
+            uniform vec4 u_color;
+            void main()
+            {
+               gl_FragColor = u_color;
+            }
+            vec4 someFunction() {
+              return u_color
+        );
+
+        std::stringstream ss;
+
+        ss << shaderStart;
+        GenerateLongExpression(length, &ss);
+        ss << "; }";
+
+        return ss.str();
+    }
+
+    void GenerateDeepFunctionStack(int length, std::stringstream* ss)
+    {
+        static const char* shaderStart = SHADER(
+            precision mediump float;
+            uniform vec4 u_color;
+            vec4 function0()  {
+              return u_color;
+            }
+        );
+
+        *ss << shaderStart;
+        for (int ii = 0; ii < length; ++ii) {
+          *ss << "vec4 function" << (ii + 1) << "() {\n"
+              << "  return function" << ii << "();\n"
+              << "}\n";
+        }
+    }
+
+    std::string GenerateShaderWithDeepFunctionStack(int length)
+    {
+        std::stringstream ss;
+
+        GenerateDeepFunctionStack(length, &ss);
+
+        ss << "void main() {\n"
+           << "  gl_FragColor = function" << length << "();\n"
+           << "}";
+
+        return ss.str();
+    }
+
+    std::string GenerateShaderWithUnusedDeepFunctionStack(int length)
+    {
+        std::stringstream ss;
+
+        GenerateDeepFunctionStack(length, &ss);
+
+        ss << "void main() {\n"
+           << "  gl_FragColor = vec4(0,0,0,0);\n"
+           << "}";
+
+
+        return ss.str();
+    }
+
+    std::string GenerateShaderWithFunctionParameters(int parameters)
+    {
+        std::stringstream ss;
+
+        ss << "precision mediump float;\n"
+           << "\n"
+           << "float foo(";
+        for (int i = 0; i < parameters; ++i)
+        {
+            ss << "float f" << i;
+            if (i + 1 < parameters)
+            {
+                ss << ", ";
+            }
+        }
+        ss << ")\n"
+           << "{\n"
+           << "    return f0;\n"
+           << "}\n"
+           << "\n"
+           << "void main()\n"
+           << "{\n"
+           << "    gl_FragColor = vec4(0,0,0,0);\n"
+           << "}";
+
+        return ss.str();
+    }
+
+    // Compiles a shader and if there's an error checks for a specific
+    // substring in the error log. This way we know the error is specific
+    // to the issue we are testing.
+    bool CheckShaderCompilation(ShHandle compiler,
+                                const char *source,
+                                ShCompileOptions compileOptions,
+                                const char *expected_error)
+    {
+                bool success = sh::Compile(compiler, &source, 1, compileOptions) != 0;
+                if (success)
+                {
+                    success = !expected_error;
+        }
+        else
+        {
+            std::string log = sh::GetInfoLog(compiler);
+            if (expected_error)
+                success = log.find(expected_error) != std::string::npos;
+
+            EXPECT_TRUE(success) << log << "\n----shader----\n" << source;
+        }
+        return success;
+    }
+
+    ShBuiltInResources resources;
+};
+
+const char* ExpressionLimitTest::kExpressionTooComplex =
+    "Expression too complex";
+const char* ExpressionLimitTest::kCallStackTooDeep =
+    "Call stack too deep";
+const char* ExpressionLimitTest::kHasRecursion =
+    "Recursive function call in the following call chain";
+const char* ExpressionLimitTest::kTooManyParameters =
+    "Function has too many parameters";
+
+TEST_F(ExpressionLimitTest, ExpressionComplexity)
+{
+    ShShaderSpec spec = SH_WEBGL_SPEC;
+    ShShaderOutput output = SH_ESSL_OUTPUT;
+    ShHandle vertexCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &resources);
+    ShCompileOptions compileOptions = SH_LIMIT_EXPRESSION_COMPLEXITY;
+
+    // Test expression under the limit passes.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, GenerateShaderWithLongExpression(kMaxExpressionComplexity - 10).c_str(),
+        compileOptions, nullptr));
+    // Test expression over the limit fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler,
+        GenerateShaderWithLongExpression(
+            kMaxExpressionComplexity + 10).c_str(),
+        compileOptions, kExpressionTooComplex));
+    // Test expression over the limit without a limit does not fail.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, GenerateShaderWithLongExpression(kMaxExpressionComplexity + 10).c_str(),
+        compileOptions & ~SH_LIMIT_EXPRESSION_COMPLEXITY, nullptr));
+    sh::Destruct(vertexCompiler);
+}
+
+TEST_F(ExpressionLimitTest, UnusedExpressionComplexity)
+{
+    ShShaderSpec spec = SH_WEBGL_SPEC;
+    ShShaderOutput output = SH_ESSL_OUTPUT;
+    ShHandle vertexCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &resources);
+    ShCompileOptions compileOptions = SH_LIMIT_EXPRESSION_COMPLEXITY;
+
+    // Test expression under the limit passes.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler,
+        GenerateShaderWithUnusedLongExpression(kMaxExpressionComplexity - 10).c_str(),
+        compileOptions, nullptr));
+    // Test expression over the limit fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler,
+        GenerateShaderWithUnusedLongExpression(
+            kMaxExpressionComplexity + 10).c_str(),
+        compileOptions, kExpressionTooComplex));
+    // Test expression over the limit without a limit does not fail.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler,
+        GenerateShaderWithUnusedLongExpression(kMaxExpressionComplexity + 10).c_str(),
+        compileOptions & ~SH_LIMIT_EXPRESSION_COMPLEXITY, nullptr));
+    sh::Destruct(vertexCompiler);
+}
+
+TEST_F(ExpressionLimitTest, CallStackDepth)
+{
+    ShShaderSpec spec = SH_WEBGL_SPEC;
+    ShShaderOutput output = SH_ESSL_OUTPUT;
+    ShHandle vertexCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &resources);
+    ShCompileOptions compileOptions = SH_LIMIT_CALL_STACK_DEPTH;
+
+    // Test call stack under the limit passes.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, GenerateShaderWithDeepFunctionStack(kMaxCallStackDepth - 10).c_str(),
+        compileOptions, nullptr));
+    // Test call stack over the limit fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler,
+        GenerateShaderWithDeepFunctionStack(
+            kMaxCallStackDepth + 10).c_str(),
+        compileOptions, kCallStackTooDeep));
+    // Test call stack over the limit without limit does not fail.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, GenerateShaderWithDeepFunctionStack(kMaxCallStackDepth + 10).c_str(),
+        compileOptions & ~SH_LIMIT_CALL_STACK_DEPTH, nullptr));
+    sh::Destruct(vertexCompiler);
+}
+
+TEST_F(ExpressionLimitTest, UnusedCallStackDepth)
+{
+    ShShaderSpec spec = SH_WEBGL_SPEC;
+    ShShaderOutput output = SH_ESSL_OUTPUT;
+    ShHandle vertexCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &resources);
+    ShCompileOptions compileOptions = SH_LIMIT_CALL_STACK_DEPTH;
+
+    // Test call stack under the limit passes.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, GenerateShaderWithUnusedDeepFunctionStack(kMaxCallStackDepth - 10).c_str(),
+        compileOptions, nullptr));
+    // Test call stack over the limit fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler,
+        GenerateShaderWithUnusedDeepFunctionStack(
+            kMaxCallStackDepth + 10).c_str(),
+        compileOptions, kCallStackTooDeep));
+    // Test call stack over the limit without limit does not fail.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, GenerateShaderWithUnusedDeepFunctionStack(kMaxCallStackDepth + 10).c_str(),
+        compileOptions & ~SH_LIMIT_CALL_STACK_DEPTH, nullptr));
+    sh::Destruct(vertexCompiler);
+}
+
+TEST_F(ExpressionLimitTest, Recursion)
+{
+    ShShaderSpec spec = SH_WEBGL_SPEC;
+    ShShaderOutput output = SH_ESSL_OUTPUT;
+    ShHandle vertexCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &resources);
+    ShCompileOptions compileOptions = 0;
+
+    static const char* shaderWithRecursion0 = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+        vec4 someFunc()  {
+            return someFunc();
+        }
+
+        void main() {
+            gl_FragColor = u_color * someFunc();
+        }
+    );
+
+    static const char* shaderWithRecursion1 = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+
+        vec4 someFunc();
+
+        vec4 someFunc1()  {
+            return someFunc();
+        }
+
+        vec4 someFunc()  {
+            return someFunc1();
+        }
+
+        void main() {
+            gl_FragColor = u_color * someFunc();
+        }
+    );
+
+    static const char* shaderWithRecursion2 = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+        vec4 someFunc()  {
+            if (u_color.x > 0.5) {
+                return someFunc();
+            } else {
+                return vec4(1);
+            }
+        }
+
+        void main() {
+            gl_FragColor = someFunc();
+        }
+    );
+
+    static const char* shaderWithRecursion3 = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+        vec4 someFunc()  {
+            if (u_color.x > 0.5) {
+                return vec4(1);
+            } else {
+                return someFunc();
+            }
+        }
+
+        void main() {
+            gl_FragColor = someFunc();
+        }
+    );
+
+    static const char* shaderWithRecursion4 = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+        vec4 someFunc()  {
+            return (u_color.x > 0.5) ? vec4(1) : someFunc();
+        }
+
+        void main() {
+            gl_FragColor = someFunc();
+        }
+    );
+
+    static const char* shaderWithRecursion5 = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+        vec4 someFunc()  {
+            return (u_color.x > 0.5) ? someFunc() : vec4(1);
+        }
+
+        void main() {
+            gl_FragColor = someFunc();
+        }
+    );
+
+    static const char* shaderWithRecursion6 = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+        vec4 someFunc()  {
+            return someFunc();
+        }
+
+        void main() {
+            gl_FragColor = u_color;
+        }
+    );
+
+    static const char* shaderWithNoRecursion = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+
+        vec3 rgb(int r, int g, int b) {
+            return vec3(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0);
+        }
+
+        void main() {
+            vec3 hairColor0 = rgb(151, 200, 234);
+            vec3 faceColor2 = rgb(183, 148, 133);
+            gl_FragColor = u_color + vec4(hairColor0 + faceColor2, 0);
+        }
+    );
+
+    static const char* shaderWithRecursion7 = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+
+        vec4 function2() {
+            return u_color;
+        }
+
+        vec4 function1() {
+            vec4 a = function2();
+            vec4 b = function1();
+            return a + b;
+        }
+
+        void main() {
+            gl_FragColor = function1();
+        }
+    );
+
+    static const char* shaderWithRecursion8 = SHADER(
+        precision mediump float;
+        uniform vec4 u_color;
+
+        vec4 function1();
+
+        vec4 function3() {
+            return function1();
+        }
+
+        vec4 function2() {
+            return function3();
+        }
+
+        vec4 function1() {
+            return function2();
+        }
+
+        void main() {
+            gl_FragColor = function1();
+        }
+    );
+
+    // Check simple recursions fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion0,
+        compileOptions, kHasRecursion));
+    // Check simple recursions fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion1,
+        compileOptions, kHasRecursion));
+    // Check if recursions fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion2,
+        compileOptions, kHasRecursion));
+    // Check if recursions fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion3,
+        compileOptions, kHasRecursion));
+    // Check ternary recursions fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion4,
+        compileOptions, kHasRecursion));
+    // Check ternary recursions fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion5,
+        compileOptions, kHasRecursion));
+
+    // Check some more forms of recursion
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion6,
+        compileOptions, kHasRecursion));
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion7,
+        compileOptions, kHasRecursion));
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion8,
+        compileOptions, kHasRecursion));
+    // Check unused recursions fails if limiting call stack
+    // since we check all paths.
+    EXPECT_TRUE(CheckShaderCompilation(
+        vertexCompiler, shaderWithRecursion6,
+        compileOptions | SH_LIMIT_CALL_STACK_DEPTH, kHasRecursion));
+
+    // Check unused recursions passes.
+    EXPECT_TRUE(
+        CheckShaderCompilation(vertexCompiler, shaderWithNoRecursion, compileOptions, nullptr));
+    // Check unused recursions passes if limiting call stack.
+    EXPECT_TRUE(CheckShaderCompilation(vertexCompiler, shaderWithNoRecursion,
+                                       compileOptions | SH_LIMIT_CALL_STACK_DEPTH, nullptr));
+    sh::Destruct(vertexCompiler);
+}
+
+TEST_F(ExpressionLimitTest, FunctionParameterCount)
+{
+    ShShaderSpec spec     = SH_WEBGL_SPEC;
+    ShShaderOutput output = SH_ESSL_OUTPUT;
+    ShHandle compiler     = sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &resources);
+    ShCompileOptions compileOptions = SH_LIMIT_EXPRESSION_COMPLEXITY;
+
+    // Test parameters under the limit succeeds.
+    EXPECT_TRUE(CheckShaderCompilation(
+        compiler, GenerateShaderWithFunctionParameters(kMaxFunctionParameters).c_str(),
+        compileOptions, nullptr));
+    // Test parameters over the limit fails.
+    EXPECT_TRUE(CheckShaderCompilation(
+        compiler, GenerateShaderWithFunctionParameters(kMaxFunctionParameters + 1).c_str(),
+        compileOptions, kTooManyParameters));
+    // Test parameters over the limit without limit does not fail.
+    EXPECT_TRUE(CheckShaderCompilation(
+        compiler, GenerateShaderWithFunctionParameters(kMaxFunctionParameters + 1).c_str(),
+        compileOptions & ~SH_LIMIT_EXPRESSION_COMPLEXITY, nullptr));
+    sh::Destruct(compiler);
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/FloatLex_test.cpp b/src/third_party/angle/src/tests/compiler_tests/FloatLex_test.cpp
new file mode 100644
index 0000000..013d7ca
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/FloatLex_test.cpp
@@ -0,0 +1,195 @@
+//
+// Copyright (c) 2016 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.
+//
+// FloatLex_test.cpp:
+// Tests for parsing floats in GLSL source.
+//
+
+#include <sstream>
+#include <string>
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "compiler/translator/util.h"
+#include "gtest/gtest.h"
+
+namespace
+{
+
+class StrtofClampParser
+{
+  public:
+    static float Parse(std::string str)
+    {
+        float value;
+        sh::strtof_clamp(str, &value);
+        return value;
+    }
+};
+
+// NumericLexFloat32OutOfRangeToInfinity usually only comes to play in corner cases of parsing, but
+// it's useful to test that it works as expected across the whole range of floats.
+class NumericLexFloatParser
+{
+  public:
+    static float Parse(std::string str) { return sh::NumericLexFloat32OutOfRangeToInfinity(str); }
+};
+
+}  // anonymous namespace
+
+template <typename T>
+class FloatLexTest : public ::testing::Test
+{
+  public:
+    FloatLexTest() {}
+
+  protected:
+    void SetUp() override {}
+
+    void TearDown() override {}
+
+    static bool ParsedMatches(std::string str, float expected)
+    {
+        return (T::Parse(str) == expected);
+    }
+
+    static bool IsInfinity(std::string str)
+    {
+        float f = T::Parse(str);
+        return gl::isInf(f);
+    }
+
+    static std::string Zeros(size_t count) { return std::string(count, '0'); }
+};
+
+typedef ::testing::Types<StrtofClampParser, NumericLexFloatParser> FloatParserTypes;
+TYPED_TEST_CASE(FloatLexTest, FloatParserTypes);
+
+TYPED_TEST(FloatLexTest, One)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("1.0", 1.0f));
+}
+
+TYPED_TEST(FloatLexTest, Ten)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("10.0", 10.0f));
+}
+
+TYPED_TEST(FloatLexTest, TenScientific)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("1.0e1", 10.0f));
+}
+
+TYPED_TEST(FloatLexTest, ScientificWithSmallMantissa)
+{
+    std::stringstream ss;
+    ss << "0." << TestFixture::Zeros(100) << "125e102";
+    ASSERT_TRUE(TestFixture::ParsedMatches(ss.str(), 12.5f));
+}
+
+TYPED_TEST(FloatLexTest, ScientificWithLargeMantissa)
+{
+    std::stringstream ss;
+    ss << "9" << TestFixture::Zeros(100) << ".0e-100";
+    ASSERT_TRUE(TestFixture::ParsedMatches(ss.str(), 9.0f));
+}
+
+TYPED_TEST(FloatLexTest, ScientificWithVerySmallMantissa)
+{
+    std::stringstream ss;
+    ss << "0." << TestFixture::Zeros(5000) << "125e5002";
+    ASSERT_TRUE(TestFixture::ParsedMatches(ss.str(), 12.5f));
+}
+
+TYPED_TEST(FloatLexTest, ScientificWithVeryLargeMantissa)
+{
+    std::stringstream ss;
+    ss << "9" << TestFixture::Zeros(5000) << ".0e-5000";
+    ASSERT_TRUE(TestFixture::ParsedMatches(ss.str(), 9.0f));
+}
+
+TYPED_TEST(FloatLexTest, StartWithDecimalDot)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches(".125", 0.125f));
+}
+
+TYPED_TEST(FloatLexTest, EndWithDecimalDot)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("123.", 123.0f));
+}
+
+TYPED_TEST(FloatLexTest, NoDecimalDot)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("125e-2", 1.25f));
+}
+
+TYPED_TEST(FloatLexTest, EndStartWithDecimalDotScientific)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches(".625e-1", 0.0625f));
+}
+
+TYPED_TEST(FloatLexTest, EndWithDecimalDotScientific)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("102400.e-2", 1024.0f));
+}
+
+TYPED_TEST(FloatLexTest, UppercaseE)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("125E-2", 1.25f));
+}
+
+TYPED_TEST(FloatLexTest, PlusInExponent)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("1E+2", 100.0f));
+}
+
+TYPED_TEST(FloatLexTest, SlightlyAboveMaxFloat)
+{
+    ASSERT_TRUE(TestFixture::IsInfinity("3.4029e38"));
+}
+
+TYPED_TEST(FloatLexTest, SlightlyBelowMaxFloat)
+{
+    ASSERT_FALSE(TestFixture::IsInfinity("3.4028e38"));
+}
+
+TYPED_TEST(FloatLexTest, SlightlyBelowMinSubnormalFloat)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("1.0e-48", 0.0f));
+}
+
+TYPED_TEST(FloatLexTest, SlightlyAboveMinNormalFloat)
+{
+    ASSERT_FALSE(TestFixture::ParsedMatches("1.0e-37", 0.0f));
+}
+
+TYPED_TEST(FloatLexTest, ManySignificantDigits)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("1.23456789", 1.23456789f));
+}
+
+TYPED_TEST(FloatLexTest, MantissaBitAboveMaxUint)
+{
+    ASSERT_TRUE(TestFixture::ParsedMatches("4294967299.", 4294967299.0f));
+}
+
+TYPED_TEST(FloatLexTest, ExponentBitAboveMaxInt)
+{
+    ASSERT_TRUE(TestFixture::IsInfinity("1.0e2147483649"));
+}
+
+TYPED_TEST(FloatLexTest, ExponentBitBelowMaxIntAndLargeMantissa)
+{
+    std::stringstream ss;
+    ss << "1" << TestFixture::Zeros(32) << ".0e2147483640";
+    ASSERT_TRUE(TestFixture::IsInfinity(ss.str()));
+}
+
+TYPED_TEST(FloatLexTest, ExponentBitAboveMinIntAndSmallMantissa)
+{
+    std::stringstream ss;
+    ss << "0." << TestFixture::Zeros(32) << "1e-2147483640";
+    ASSERT_TRUE(TestFixture::ParsedMatches(ss.str(), 0.0f));
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/FragDepth_test.cpp b/src/third_party/angle/src/tests/compiler_tests/FragDepth_test.cpp
new file mode 100644
index 0000000..1d3e358
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/FragDepth_test.cpp
@@ -0,0 +1,119 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FragDepth_test.cpp:
+//   Test for GLES SL 3.0 gl_FragDepth variable implementation.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace
+{
+const char ESSLVersion100[] = "#version 100\n";
+const char ESSLVersion300[] = "#version 300 es\n";
+const char EXTFDPragma[]    = "#extension GL_EXT_frag_depth : require\n";
+}  // namespace
+
+class FragDepthTest : public testing::TestWithParam<bool>
+{
+  protected:
+    void SetUp() override
+    {
+        sh::InitBuiltInResources(&mResources);
+        mCompiler                 = nullptr;
+        mResources.EXT_frag_depth = GetParam();
+    }
+
+    void TearDown() override { DestroyCompiler(); }
+    void DestroyCompiler()
+    {
+        if (mCompiler)
+        {
+            sh::Destruct(mCompiler);
+            mCompiler = nullptr;
+        }
+    }
+
+    void InitializeCompiler()
+    {
+        DestroyCompiler();
+        mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES3_SPEC,
+                                          SH_GLSL_COMPATIBILITY_OUTPUT, &mResources);
+        ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
+    }
+
+    testing::AssertionResult TestShaderCompile(const char *version,
+                                               const char *pragma,
+                                               const char *shader)
+    {
+        const char *shaderStrings[] = {version, pragma, shader};
+        bool success                = sh::Compile(mCompiler, shaderStrings, 3, 0);
+        if (success)
+        {
+            return ::testing::AssertionSuccess() << "Compilation success";
+        }
+        return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
+    }
+
+  protected:
+    ShBuiltInResources mResources;
+    ShHandle mCompiler;
+};
+
+// The GLES SL 3.0 built-in variable gl_FragDepth fails to compile with GLES SL 1.0.
+TEST_P(FragDepthTest, CompileFailsESSL100)
+{
+    static const char shaderString[] =
+        "precision mediump float;\n"
+        "void main() { \n"
+        "    gl_FragDepth = 1.0;\n"
+        "}\n";
+
+    InitializeCompiler();
+    EXPECT_FALSE(TestShaderCompile(ESSLVersion100, "", shaderString));
+    EXPECT_FALSE(TestShaderCompile("", "", shaderString));
+    EXPECT_FALSE(TestShaderCompile("", EXTFDPragma, shaderString));
+}
+
+// The GLES SL 3.0 built-in variable gl_FragDepth compiles with GLES SL 3.0.
+TEST_P(FragDepthTest, CompileSucceedsESSL300)
+{
+    static const char shaderString[] =
+        "precision mediump float;\n"
+        "void main() { \n"
+        "    gl_FragDepth = 1.0;\n"
+        "}\n";
+    InitializeCompiler();
+    EXPECT_TRUE(TestShaderCompile(ESSLVersion300, "", shaderString));
+}
+
+// Using #extension GL_EXT_frag_depth in GLSL ES 3.0 shader fails to compile.
+TEST_P(FragDepthTest, ExtensionFDFailsESSL300)
+{
+    static const char shaderString[] =
+        "precision mediump float;\n"
+        "out vec4 fragColor;\n"
+        "void main() { \n"
+        "    fragColor = vec4(1.0);\n"
+        "}\n";
+    InitializeCompiler();
+    if (mResources.EXT_frag_depth == 1)
+    {
+        // TODO(kkinnunen, geofflang): this should fail. Extensions need to have similar level
+        // system to SymbolTable.  The biggest task is to implement version-aware preprocessor, so
+        // that the extension defines can be defined depending on the version that the preprocessor
+        // saw or did not see.
+        EXPECT_TRUE(TestShaderCompile(ESSLVersion300, EXTFDPragma, shaderString));
+    }
+    else
+    {
+        EXPECT_FALSE(TestShaderCompile(ESSLVersion300, EXTFDPragma, shaderString));
+    }
+}
+
+// The tests should pass regardless whether the EXT_frag_depth is on or not.
+INSTANTIATE_TEST_CASE_P(FragDepthTests, FragDepthTest, testing::Values(false, true));
diff --git a/src/third_party/angle/src/tests/compiler_tests/GLSLCompatibilityOutput_test.cpp b/src/third_party/angle/src/tests/compiler_tests/GLSLCompatibilityOutput_test.cpp
new file mode 100644
index 0000000..8adec77
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/GLSLCompatibilityOutput_test.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2016 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.
+//
+// GLSLCompatibilityOutputTest.cpp
+//   Test compiler output for glsl compatibility mode
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+class GLSLCompatibilityOutputTest : public MatchOutputCodeTest
+{
+  public:
+    GLSLCompatibilityOutputTest()
+        : MatchOutputCodeTest(GL_VERTEX_SHADER, SH_VARIABLES, SH_GLSL_COMPATIBILITY_OUTPUT)
+    {
+    }
+};
+
+// Verify gl_Position is written when compiling in compatibility mode
+TEST_F(GLSLCompatibilityOutputTest, GLPositionWrittenTest)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void main() {\n"
+        "}";
+    compile(shaderString);
+    EXPECT_TRUE(foundInCode("gl_Position"));
+}
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/compiler_tests/IntermNode_test.cpp b/src/third_party/angle/src/tests/compiler_tests/IntermNode_test.cpp
new file mode 100644
index 0000000..67ef370
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/IntermNode_test.cpp
@@ -0,0 +1,232 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IntermNode_test.cpp:
+//   Unit tests for the AST node classes.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/PoolAlloc.h"
+
+using namespace sh;
+
+class IntermNodeTest : public testing::Test
+{
+  public:
+    IntermNodeTest() : mUniqueIndex(0) {}
+
+  protected:
+    void SetUp() override
+    {
+        allocator.push();
+        SetGlobalPoolAllocator(&allocator);
+    }
+
+    void TearDown() override
+    {
+        SetGlobalPoolAllocator(nullptr);
+        allocator.pop();
+    }
+
+    TIntermSymbol *createTestSymbol(const TType &type)
+    {
+        TInfoSinkBase symbolNameOut;
+        symbolNameOut << "test" << mUniqueIndex;
+        TString symbolName = symbolNameOut.c_str();
+        ++mUniqueIndex;
+
+        TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
+        node->setLine(createUniqueSourceLoc());
+        node->setInternal(true);
+        node->getTypePointer()->setQualifier(EvqTemporary);
+        return node;
+    }
+
+    TIntermSymbol *createTestSymbol()
+    {
+        TType type(EbtFloat, EbpHigh);
+        return createTestSymbol(type);
+    }
+
+    void checkTypeEqualWithQualifiers(const TType &original, const TType &copy)
+    {
+        ASSERT_EQ(original, copy);
+        ASSERT_EQ(original.getPrecision(), copy.getPrecision());
+        ASSERT_EQ(original.getQualifier(), copy.getQualifier());
+    }
+
+    void checkSymbolCopy(TIntermNode *aOriginal, TIntermNode *aCopy)
+    {
+        ASSERT_NE(aOriginal, aCopy);
+        TIntermSymbol *copy     = aCopy->getAsSymbolNode();
+        TIntermSymbol *original = aOriginal->getAsSymbolNode();
+        ASSERT_NE(nullptr, copy);
+        ASSERT_NE(nullptr, original);
+        ASSERT_NE(original, copy);
+        ASSERT_EQ(original->getId(), copy->getId());
+        ASSERT_EQ(original->getName().getString(), copy->getName().getString());
+        ASSERT_EQ(original->getName().isInternal(), copy->getName().isInternal());
+        checkTypeEqualWithQualifiers(original->getType(), copy->getType());
+        ASSERT_EQ(original->getLine().first_file, copy->getLine().first_file);
+        ASSERT_EQ(original->getLine().first_line, copy->getLine().first_line);
+        ASSERT_EQ(original->getLine().last_file, copy->getLine().last_file);
+        ASSERT_EQ(original->getLine().last_line, copy->getLine().last_line);
+    }
+
+    TSourceLoc createUniqueSourceLoc()
+    {
+        TSourceLoc loc;
+        loc.first_file = mUniqueIndex;
+        loc.first_line = mUniqueIndex + 1;
+        loc.last_file  = mUniqueIndex + 2;
+        loc.last_line  = mUniqueIndex + 3;
+        ++mUniqueIndex;
+        return loc;
+    }
+
+    static TSourceLoc getTestSourceLoc()
+    {
+        TSourceLoc loc;
+        loc.first_file = 1;
+        loc.first_line = 2;
+        loc.last_file  = 3;
+        loc.last_line  = 4;
+        return loc;
+    }
+
+    static void checkTestSourceLoc(const TSourceLoc &loc)
+    {
+        ASSERT_EQ(1, loc.first_file);
+        ASSERT_EQ(2, loc.first_line);
+        ASSERT_EQ(3, loc.last_file);
+        ASSERT_EQ(4, loc.last_line);
+    }
+
+  private:
+    TPoolAllocator allocator;
+    int mUniqueIndex;
+};
+
+// Check that the deep copy of a symbol node is an actual copy with the same attributes as the
+// original.
+TEST_F(IntermNodeTest, DeepCopySymbolNode)
+{
+    TType type(EbtInt, EbpHigh);
+    TIntermSymbol *original = new TIntermSymbol(0, TString("name"), type);
+    original->setLine(getTestSourceLoc());
+    original->setInternal(true);
+    TIntermTyped *copy = original->deepCopy();
+    checkSymbolCopy(original, copy);
+    checkTestSourceLoc(copy->getLine());
+}
+
+// Check that the deep copy of a constant union node is an actual copy with the same attributes as
+// the original.
+TEST_F(IntermNodeTest, DeepCopyConstantUnionNode)
+{
+    TType type(EbtInt, EbpHigh);
+    TConstantUnion *constValue = new TConstantUnion[1];
+    constValue[0].setIConst(101);
+    TIntermConstantUnion *original = new TIntermConstantUnion(constValue, type);
+    original->setLine(getTestSourceLoc());
+    TIntermTyped *copyTyped    = original->deepCopy();
+    TIntermConstantUnion *copy = copyTyped->getAsConstantUnion();
+    ASSERT_NE(nullptr, copy);
+    ASSERT_NE(original, copy);
+    checkTestSourceLoc(copy->getLine());
+    checkTypeEqualWithQualifiers(original->getType(), copy->getType());
+    ASSERT_EQ(101, copy->getIConst(0));
+}
+
+// Check that the deep copy of a binary node is an actual copy with the same attributes as the
+// original. Child nodes also need to be copies with the same attributes as the original children.
+TEST_F(IntermNodeTest, DeepCopyBinaryNode)
+{
+    TType type(EbtFloat, EbpHigh);
+
+    TIntermBinary *original = new TIntermBinary(EOpAdd, createTestSymbol(), createTestSymbol());
+    original->setLine(getTestSourceLoc());
+    TIntermTyped *copyTyped = original->deepCopy();
+    TIntermBinary *copy = copyTyped->getAsBinaryNode();
+    ASSERT_NE(nullptr, copy);
+    ASSERT_NE(original, copy);
+    checkTestSourceLoc(copy->getLine());
+    checkTypeEqualWithQualifiers(original->getType(), copy->getType());
+
+    checkSymbolCopy(original->getLeft(), copy->getLeft());
+    checkSymbolCopy(original->getRight(), copy->getRight());
+}
+
+// Check that the deep copy of a unary node is an actual copy with the same attributes as the
+// original. The child node also needs to be a copy with the same attributes as the original child.
+TEST_F(IntermNodeTest, DeepCopyUnaryNode)
+{
+    TType type(EbtFloat, EbpHigh);
+
+    TIntermUnary *original = new TIntermUnary(EOpPreIncrement, createTestSymbol());
+    original->setLine(getTestSourceLoc());
+    TIntermTyped *copyTyped = original->deepCopy();
+    TIntermUnary *copy = copyTyped->getAsUnaryNode();
+    ASSERT_NE(nullptr, copy);
+    ASSERT_NE(original, copy);
+    checkTestSourceLoc(copy->getLine());
+    checkTypeEqualWithQualifiers(original->getType(), copy->getType());
+
+    checkSymbolCopy(original->getOperand(), copy->getOperand());
+}
+
+// Check that the deep copy of an aggregate node is an actual copy with the same attributes as the
+// original. Child nodes also need to be copies with the same attributes as the original children.
+TEST_F(IntermNodeTest, DeepCopyAggregateNode)
+{
+    TIntermSequence *originalSeq = new TIntermSequence();
+    originalSeq->push_back(createTestSymbol());
+    originalSeq->push_back(createTestSymbol());
+    originalSeq->push_back(createTestSymbol());
+    TIntermAggregate *original =
+        TIntermAggregate::Create(originalSeq->at(0)->getAsTyped()->getType(), EOpMix, originalSeq);
+    original->setLine(getTestSourceLoc());
+
+    TIntermTyped *copyTyped = original->deepCopy();
+    TIntermAggregate *copy = copyTyped->getAsAggregate();
+    ASSERT_NE(nullptr, copy);
+    ASSERT_NE(original, copy);
+    checkTestSourceLoc(copy->getLine());
+    checkTypeEqualWithQualifiers(original->getType(), copy->getType());
+
+    ASSERT_EQ(original->getSequence()->size(), copy->getSequence()->size());
+    TIntermSequence::size_type i = 0;
+    for (auto *copyChild : *copy->getSequence())
+    {
+        TIntermNode *originalChild = original->getSequence()->at(i);
+        checkSymbolCopy(originalChild, copyChild);
+        ++i;
+    }
+}
+
+// Check that the deep copy of a ternary node is an actual copy with the same attributes as the
+// original. Child nodes also need to be copies with the same attributes as the original children.
+TEST_F(IntermNodeTest, DeepCopyTernaryNode)
+{
+    TType type(EbtFloat, EbpHigh);
+
+    TIntermTernary *original = new TIntermTernary(createTestSymbol(TType(EbtBool, EbpUndefined)),
+                                                  createTestSymbol(), createTestSymbol());
+    original->setLine(getTestSourceLoc());
+    TIntermTyped *copyTyped = original->deepCopy();
+    TIntermTernary *copy    = copyTyped->getAsTernaryNode();
+    ASSERT_NE(nullptr, copy);
+    ASSERT_NE(original, copy);
+    checkTestSourceLoc(copy->getLine());
+    checkTypeEqualWithQualifiers(original->getType(), copy->getType());
+
+    checkSymbolCopy(original->getCondition(), copy->getCondition());
+    checkSymbolCopy(original->getTrueExpression(), copy->getTrueExpression());
+    checkSymbolCopy(original->getFalseExpression(), copy->getFalseExpression());
+}
+
diff --git a/src/third_party/angle/src/tests/compiler_tests/NV_draw_buffers_test.cpp b/src/third_party/angle/src/tests/compiler_tests/NV_draw_buffers_test.cpp
new file mode 100644
index 0000000..13a44fd
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/NV_draw_buffers_test.cpp
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// NV_draw_buffers_test.cpp:
+//   Test for NV_draw_buffers setting
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+class NVDrawBuffersTest : public MatchOutputCodeTest
+{
+  public:
+    NVDrawBuffersTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT)
+    {
+        ShBuiltInResources *resources = getResources();
+        resources->MaxDrawBuffers     = 8;
+        resources->EXT_draw_buffers   = 1;
+        resources->NV_draw_buffers    = 1;
+    }
+};
+
+TEST_F(NVDrawBuffersTest, NVDrawBuffers)
+{
+    const std::string &shaderString =
+        "#extension GL_EXT_draw_buffers : require\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   gl_FragData[0] = vec4(1.0);\n"
+        "   gl_FragData[1] = vec4(0.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("GL_NV_draw_buffers"));
+    ASSERT_FALSE(foundInCode("GL_EXT_draw_buffers"));
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/Pack_Unpack_test.cpp b/src/third_party/angle/src/tests/compiler_tests/Pack_Unpack_test.cpp
new file mode 100644
index 0000000..a6333e7
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/Pack_Unpack_test.cpp
@@ -0,0 +1,122 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Pack_Unpack_test.cpp:
+//   Tests for the emulating pack_unpack functions for GLSL.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+namespace
+{
+
+class PackUnpackTest : public MatchOutputCodeTest
+{
+  public:
+    PackUnpackTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_GLSL_400_CORE_OUTPUT) {}
+};
+
+// Check if PackSnorm2x16 Emulation for GLSL < 4.2 compile correctly.
+TEST_F(PackUnpackTest, PackSnorm2x16Emulation)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(location = 0) out mediump vec4 fragColor;"
+        "void main() {\n"
+        "   vec2 v;\n"
+        "   uint u = packSnorm2x16(v);\n"
+        "   fragColor = vec4(0.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("uint webgl_packSnorm2x16_emu(vec2 v)"));
+}
+
+// Check if UnpackSnorm2x16 Emulation for GLSL < 4.2 compile correctly.
+TEST_F(PackUnpackTest, UnpackSnorm2x16Emulation)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(location = 0) out mediump vec4 fragColor;"
+        "void main() {\n"
+        "   uint u;\n"
+        "   vec2 v=unpackSnorm2x16(u);\n"
+        "   fragColor = vec4(0.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("vec2 webgl_unpackSnorm2x16_emu(uint u)"));
+}
+
+// Check if PackUnorm2x16 Emulation for GLSL < 4.1 compiles correctly.
+TEST_F(PackUnpackTest, PackUnorm2x16Emulation)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(location = 0) out mediump vec4 fragColor;"
+        "void main() {\n"
+        "   vec2 v;\n"
+        "   uint u = packUnorm2x16(v);\n"
+        "   fragColor = vec4(0.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("uint webgl_packUnorm2x16_emu(vec2 v)"));
+}
+
+// Check if UnpackSnorm2x16 Emulation for GLSL < 4.1 compiles correctly.
+TEST_F(PackUnpackTest, UnpackUnorm2x16Emulation)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(location = 0) out mediump vec4 fragColor;"
+        "void main() {\n"
+        "   uint u;\n"
+        "   vec2 v=unpackUnorm2x16(u);\n"
+        "   fragColor = vec4(0.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("vec2 webgl_unpackUnorm2x16_emu(uint u)"));
+}
+
+// Check if PackHalf2x16 Emulation for GLSL < 4.2 compiles correctly.
+TEST_F(PackUnpackTest, PackHalf2x16Emulation)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(location = 0) out mediump vec4 fragColor;"
+        "void main() {\n"
+        "   vec2 v;\n"
+        "   uint u=packHalf2x16(v);\n"
+        "   fragColor = vec4(0.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("uint webgl_packHalf2x16_emu(vec2 v)"));
+}
+
+// Check if UnpackHalf2x16 Emulation for GLSL < 4.2 compiles correctly.
+TEST_F(PackUnpackTest, UnpackHalf2x16Emulation)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(location = 0) out mediump vec4 fragColor;"
+        "void main() {\n"
+        "   uint u;\n"
+        "   vec2 v=unpackHalf2x16(u);\n"
+        "   fragColor = vec4(0.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("vec2 webgl_unpackHalf2x16_emu(uint u)"));
+}
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/compiler_tests/PruneEmptyDeclarations_test.cpp b/src/third_party/angle/src/tests/compiler_tests/PruneEmptyDeclarations_test.cpp
new file mode 100644
index 0000000..6b59e0c
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/PruneEmptyDeclarations_test.cpp
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2016 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.
+//
+// PruneEmptyDeclarations_test.cpp:
+//   Tests for pruning empty declarations.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+namespace
+{
+
+class PruneEmptyDeclarationsTest : public MatchOutputCodeTest
+{
+  public:
+    PruneEmptyDeclarationsTest()
+        : MatchOutputCodeTest(GL_VERTEX_SHADER, 0, SH_GLSL_COMPATIBILITY_OUTPUT)
+    {
+    }
+};
+
+TEST_F(PruneEmptyDeclarationsTest, EmptyDeclarationStartsDeclaratorList)
+{
+    const std::string shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main()\n"
+        "{\n"
+        "   float, f;\n"
+        "   gl_Position = vec4(u * f);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("float f"));
+    ASSERT_TRUE(notFoundInCode("float, f"));
+}
+
+TEST_F(PruneEmptyDeclarationsTest, EmptyStructDeclarationWithQualifiers)
+{
+    const std::string shaderString =
+        "precision mediump float;\n"
+        "const struct S { float f; };\n"
+        "uniform S s;"
+        "void main()\n"
+        "{\n"
+        "   gl_Position = vec4(s.f);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("struct S"));
+    ASSERT_TRUE(foundInCode("uniform S"));
+    ASSERT_TRUE(notFoundInCode("const struct S"));
+}
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/compiler_tests/PrunePureLiteralStatements_test.cpp b/src/third_party/angle/src/tests/compiler_tests/PrunePureLiteralStatements_test.cpp
new file mode 100644
index 0000000..d1a61cc
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/PrunePureLiteralStatements_test.cpp
@@ -0,0 +1,171 @@
+//
+// Copyright (c) 2017 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.
+//
+// PrunePureLiteralStatements_test.cpp:
+//   Tests for pruning literal statements.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+namespace
+{
+
+class PrunePureLiteralStatementsTest : public MatchOutputCodeTest
+{
+  public:
+    // The PrunePureLiteralStatements pass is used when outputting ESSL
+    PrunePureLiteralStatementsTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT) {}
+};
+
+// Most basic test for the pruning
+TEST_F(PrunePureLiteralStatementsTest, FloatLiteralStatement)
+{
+    const std::string shaderString =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "   float f = 41.0;\n"
+        "   42.0;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("41"));
+    ASSERT_TRUE(notFoundInCode("42"));
+}
+
+// Test the pruning works for constructed types too
+TEST_F(PrunePureLiteralStatementsTest, ConstructorLiteralStatement)
+{
+    const std::string shaderString =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "   vec2 f = vec2(41.0, 41.0);\n"
+        "   vec2(42.0, 42.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("41"));
+    ASSERT_TRUE(notFoundInCode("42"));
+}
+
+// Test the pruning works when the literal is a (non-trivial) expression
+TEST_F(PrunePureLiteralStatementsTest, ExpressionLiteralStatement)
+{
+    const std::string shaderString =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "   vec2(21.0, 21.0) + vec2(21.0, 21.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(notFoundInCode("21"));
+    ASSERT_TRUE(notFoundInCode("42"));
+}
+
+// Test that the pruning happens in the for-loop expression too
+TEST_F(PrunePureLiteralStatementsTest, ForLoopLiteralExpression)
+{
+    const std::string shaderString =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    for (;; vec2(42.0, 42.0)) {}\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(notFoundInCode("42"));
+}
+
+// Test that the pruning correctly handles the pruning inside switch statements - for a switch with
+// one empty case.
+TEST_F(PrunePureLiteralStatementsTest, SwitchLiteralExpressionEmptyCase)
+{
+    const std::string shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    switch(1)\n"
+        "    {\n"
+        "      default:\n"
+        "        42;\n"
+        "    }\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(notFoundInCode("default"));
+    ASSERT_TRUE(notFoundInCode("42"));
+}
+
+// Test that the pruning correctly handles the pruning inside switch statements - for a switch with
+// multiple cases.
+TEST_F(PrunePureLiteralStatementsTest, SwitchLiteralExpressionEmptyCases)
+{
+    const std::string shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    switch(1)\n"
+        "    {\n"
+        "      case 1:\n"
+        "      case 2:\n"
+        "      default:\n"
+        "        42;\n"
+        "    }\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(notFoundInCode("default"));
+    ASSERT_TRUE(notFoundInCode("case"));
+    ASSERT_TRUE(notFoundInCode("42"));
+}
+
+// Test that the pruning correctly handles the pruning inside switch statements - only cases at the
+// end are deleted
+TEST_F(PrunePureLiteralStatementsTest, SwitchLiteralExpressionOnlyLastCase)
+{
+    const std::string shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    switch(1)\n"
+        "    {\n"
+        "      case 1:\n"
+        "      default:\n"
+        "        42;\n"
+        "        break;\n"
+        "    }\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("default"));
+    ASSERT_TRUE(foundInCode("case"));
+    ASSERT_TRUE(notFoundInCode("42"));
+}
+
+// Test that the pruning correctly handles the pruning inside switch statements - pruning isn't stopped by literal statements
+TEST_F(PrunePureLiteralStatementsTest, SwitchLiteralExpressionLiteralDoesntStop)
+{
+    const std::string shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    switch(1)\n"
+        "    {\n"
+        "      case 1:\n"
+        "        42;\n"
+        "      case 2:\n"
+        "        43;\n"
+        "    }\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(notFoundInCode("case"));
+    ASSERT_TRUE(notFoundInCode("42"));
+    ASSERT_TRUE(notFoundInCode("43"));
+}
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/compiler_tests/PruneUnusedFunctions_test.cpp b/src/third_party/angle/src/tests/compiler_tests/PruneUnusedFunctions_test.cpp
new file mode 100644
index 0000000..d9ccedc
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/PruneUnusedFunctions_test.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PruneUnusedFunctions_test.cpp:
+//   Test for the pruning of unused function with the SH_PRUNE_UNUSED_FUNCTIONS compile flag
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+namespace
+{
+
+class PruneUnusedFunctionsTest : public MatchOutputCodeTest
+{
+  public:
+    PruneUnusedFunctionsTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT) {}
+
+  protected:
+    void compile(const std::string &shaderString, bool prune)
+    {
+        int compilationFlags = SH_VARIABLES | (prune ? 0 : SH_DONT_PRUNE_UNUSED_FUNCTIONS);
+        MatchOutputCodeTest::compile(shaderString, compilationFlags);
+    }
+};
+
+// Check that unused function and prototypes are removed iff the options is set
+TEST_F(PruneUnusedFunctionsTest, UnusedFunctionAndProto)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float unused(float a);\n"
+        "void main() {\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n"
+        "float unused(float a) {\n"
+        "    return a;\n"
+        "}\n";
+    compile(shaderString, true);
+    EXPECT_TRUE(notFoundInCode("unused("));
+    EXPECT_TRUE(foundInCode("main(", 1));
+
+    compile(shaderString, false);
+    EXPECT_TRUE(foundInCode("unused(", 2));
+    EXPECT_TRUE(foundInCode("main(", 1));
+}
+
+// Check that unimplemented prototypes are removed iff the options is set
+TEST_F(PruneUnusedFunctionsTest, UnimplementedPrototype)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float unused(float a);\n"
+        "void main() {\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+    compile(shaderString, true);
+    EXPECT_TRUE(notFoundInCode("unused("));
+    EXPECT_TRUE(foundInCode("main(", 1));
+
+    compile(shaderString, false);
+    EXPECT_TRUE(foundInCode("unused(", 1));
+    EXPECT_TRUE(foundInCode("main(", 1));
+}
+
+// Check that used functions are not pruned (duh)
+TEST_F(PruneUnusedFunctionsTest, UsedFunction)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float used(float a);\n"
+        "void main() {\n"
+        "    gl_FragColor = vec4(used(1.0));\n"
+        "}\n"
+        "float used(float a) {\n"
+        "    return a;\n"
+        "}\n";
+    compile(shaderString, true);
+    EXPECT_TRUE(foundInCode("used(", 3));
+    EXPECT_TRUE(foundInCode("main(", 1));
+
+    compile(shaderString, false);
+    EXPECT_TRUE(foundInCode("used(", 3));
+    EXPECT_TRUE(foundInCode("main(", 1));
+}
+
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/QualificationOrderESSL31_test.cpp b/src/third_party/angle/src/tests/compiler_tests/QualificationOrderESSL31_test.cpp
new file mode 100644
index 0000000..8dfff08
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/QualificationOrderESSL31_test.cpp
@@ -0,0 +1,161 @@
+//
+// Copyright (c) 2016 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.
+//
+// QualificationOrderESSL31_test.cpp:
+//   OpenGL ES 3.1 removes the strict order of qualifiers imposed by the grammar.
+//   This file contains tests for invalid order and usage of qualifiers in GLSL ES 3.10.
+
+#include "gtest/gtest.h"
+
+#include "angle_gl.h"
+#include "compiler/translator/TranslatorESSL.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+
+using namespace sh;
+
+class QualificationVertexShaderTestESSL31 : public ShaderCompileTreeTest
+{
+  public:
+    QualificationVertexShaderTestESSL31() {}
+  protected:
+    ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
+
+    const TIntermSymbol *findSymbolInAST(const TString &symbolName, TBasicType basicType)
+    {
+        return FindSymbolNode(mASTRoot, symbolName, basicType);
+    }
+};
+
+// GLSL ES 3.10 has relaxed checks on qualifier order. Any order is correct.
+TEST_F(QualificationVertexShaderTestESSL31, CentroidOut)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision lowp float;\n"
+        "out centroid float something;\n"
+        "void main(){\n"
+        "   something = 1.0;\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success" << mInfoLog;
+    }
+    else
+    {
+        const TIntermSymbol *node = findSymbolInAST("something", EbtFloat);
+        ASSERT_NE(nullptr, node);
+
+        const TType &type = node->getType();
+        EXPECT_EQ(EvqCentroidOut, type.getQualifier());
+    }
+}
+
+// GLSL ES 3.10 has relaxed checks on qualifier order. Any order is correct.
+TEST_F(QualificationVertexShaderTestESSL31, AllQualifiersMixed)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision lowp float;\n"
+        "highp out invariant centroid flat vec4 something;\n"
+        "void main(){\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success" << mInfoLog;
+    }
+    else
+    {
+        const TIntermSymbol *node = findSymbolInAST("something", EbtFloat);
+        ASSERT_NE(nullptr, node);
+
+        const TType &type = node->getType();
+        EXPECT_TRUE(type.isInvariant());
+        EXPECT_EQ(EvqFlatOut, type.getQualifier());
+        EXPECT_EQ(EbpHigh, type.getPrecision());
+    }
+}
+
+// GLSL ES 3.10 allows multiple layout qualifiers to be specified.
+TEST_F(QualificationVertexShaderTestESSL31, MultipleLayouts)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision lowp float;\n"
+        "in layout(location=1) layout(location=2) vec4 something;\n"
+        "void main(){\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success" << mInfoLog;
+    }
+    else
+    {
+        const TIntermSymbol *node = findSymbolInAST("something", EbtFloat);
+        ASSERT_NE(nullptr, node);
+
+        const TType &type = node->getType();
+        EXPECT_EQ(EvqVertexIn, type.getQualifier());
+        EXPECT_EQ(2, type.getLayoutQualifier().location);
+    }
+}
+
+// The test checks layout qualifier overriding when multiple layouts are specified.
+TEST_F(QualificationVertexShaderTestESSL31, MultipleLayoutsInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision lowp float;\n"
+        "out float someValue;\n"
+        "layout(shared) layout(std140) layout(column_major) uniform MyInterface\n"
+        "{ vec4 something; } MyInterfaceName;\n"
+        "void main(){\n"
+        "   someValue = MyInterfaceName.something.r;\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success" << mInfoLog;
+    }
+    else
+    {
+        const TIntermSymbol *node = findSymbolInAST("MyInterfaceName", EbtInterfaceBlock);
+        ASSERT_NE(nullptr, node);
+
+        const TType &type                = node->getType();
+        TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
+        EXPECT_EQ(EbsStd140, layoutQualifier.blockStorage);
+        EXPECT_EQ(EmpColumnMajor, layoutQualifier.matrixPacking);
+    }
+}
+
+// The test checks layout qualifier overriding when multiple layouts are specified.
+TEST_F(QualificationVertexShaderTestESSL31, MultipleLayoutsInterfaceBlock2)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision lowp float;\n"
+        "out float someValue;\n"
+        "layout(row_major) layout(std140) layout(shared) uniform MyInterface\n"
+        "{ vec4 something; } MyInterfaceName;\n"
+        "void main(){\n"
+        "   someValue = MyInterfaceName.something.r;\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success" << mInfoLog;
+    }
+    else
+    {
+        const TIntermSymbol *node = findSymbolInAST("MyInterfaceName", EbtInterfaceBlock);
+        ASSERT_NE(nullptr, node);
+
+        const TType &type                = node->getType();
+        TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
+        EXPECT_EQ(EbsShared, layoutQualifier.blockStorage);
+        EXPECT_EQ(EmpRowMajor, layoutQualifier.matrixPacking);
+    }
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/QualificationOrder_test.cpp b/src/third_party/angle/src/tests/compiler_tests/QualificationOrder_test.cpp
new file mode 100644
index 0000000..c0249db
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/QualificationOrder_test.cpp
@@ -0,0 +1,562 @@
+//
+// Copyright (c) 2016 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.
+//
+// QualificationOrder_test.cpp:
+//   OpenGL ES 3.1 removes the strict order of qualifiers imposed by the grammar.
+//   This file contains tests for invalid order and usage of qualifiers.
+
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+
+using namespace sh;
+
+class QualificationOrderFragmentShaderTest : public ShaderCompileTreeTest
+{
+  public:
+    QualificationOrderFragmentShaderTest() {}
+
+  protected:
+    void initResources(ShBuiltInResources *resources) override
+    {
+        resources->MaxDrawBuffers = (getShaderSpec() == SH_GLES2_SPEC) ? 1 : 8;
+    }
+
+    ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
+
+    ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
+};
+
+class QualificationOrderVertexShaderTest : public QualificationOrderFragmentShaderTest
+{
+  public:
+    QualificationOrderVertexShaderTest() {}
+
+  protected:
+    ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
+};
+
+// Repeating centroid qualifier is invalid.
+TEST_F(QualificationOrderFragmentShaderTest, RepeatingCentroid)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "flat centroid centroid in float myValue;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Repeating uniform storage qualifiers is invalid.
+TEST_F(QualificationOrderFragmentShaderTest, RepeatingUniforms)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform uniform float myValue;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Repeating varying storage qualifiers is invalid.
+TEST_F(QualificationOrderFragmentShaderTest, RepeatingVaryings)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "varying varying vec4 myColor;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Layout qualifier should be before the storage qualifiers.
+TEST_F(QualificationOrderFragmentShaderTest, WrongOrderQualifiers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out layout(location=1) vec4 myColor;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Centroid out is the correct order. Out centroid is incorrect.
+TEST_F(QualificationOrderVertexShaderTest, WrongOrderCentroidOut)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 uv;\n"
+        "out centroid vec4 position;\n"
+        "void main() {\n"
+        "position = uv;\n"
+        "gl_Position = uv;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Centroid in is the correct order. In centroid is incorrect.
+TEST_F(QualificationOrderFragmentShaderTest, WrongOrderCentroidIn)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in centroid vec4 colorIN;\n"
+        "out vec4 colorOUT;\n"
+        "void main() {\n"
+        "colorOUT = colorIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Type cannot be before the storage qualifier.
+TEST_F(QualificationOrderFragmentShaderTest, WrongOrderTypeStorage)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "centroid in vec4 colorIN;\n"
+        "vec4 out colorOUT;\n"
+        "void main() {\n"
+        "colorOUT = colorIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// A variable cannot have two conflicting storage qualifiers.
+TEST_F(QualificationOrderFragmentShaderTest, RepeatingDifferentStorageQualifiers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "centroid in vec4 colorIN;\n"
+        "uniform out vec4 colorOUT;\n"
+        "void main() {\n"
+        "colorOUT = colorIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// A variable cannot have two different layout qualifiers.
+TEST_F(QualificationOrderFragmentShaderTest, RepeatingLayoutQualifiers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 colorIN;\n"
+        "layout(location=0) layout(location=0) out vec4 colorOUT;\n"
+        "void main() {\n"
+        "colorOUT = colorIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// A variable cannot have repeating invariant qualifiers.
+TEST_F(QualificationOrderFragmentShaderTest, RepeatingInvariantQualifiers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 colorIN;\n"
+        "invariant invariant out vec4 colorOUT;\n"
+        "void main() {\n"
+        "colorOUT = colorIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// A variable cannot have repeating storage qualifiers.
+TEST_F(QualificationOrderVertexShaderTest, RepeatingAttributes)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "attribute attribute vec4 positionIN;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Wrong order for invariant varying. It should be 'invariant varying', not 'varying invariant'.
+TEST_F(QualificationOrderVertexShaderTest, VaryingInvariantWrongOrder)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "attribute vec4 positionIN;\n"
+        "varying invariant vec4 dataOUT;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// A variable cannot have repeating storage qualifiers.
+TEST_F(QualificationOrderVertexShaderTest, AttributeVaryingMix)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "attribute varying vec4 positionIN;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// A variable cannot have repeating storage qualifiers.
+TEST_F(QualificationOrderVertexShaderTest, VaryingAttributeMix)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "varying attribute vec4 positionIN;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// A variable cannot have repeating interpolation qualifiers.
+TEST_F(QualificationOrderVertexShaderTest, RepeatingInterpolationQualifiers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 positionIN;\n"
+        "flat flat out vec4 dataOUT;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Wrong order for the interpolation and storage qualifier. The correct order is interpolation
+// qualifier and then storage qualifier.
+TEST_F(QualificationOrderVertexShaderTest, WrongOrderInterpolationStorageQualifiers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 positionIN;\n"
+        "out flat vec4 dataOUT;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// The correct order is invariant, interpolation, storage.
+TEST_F(QualificationOrderVertexShaderTest, WrongOrderInvariantInterpolationStorageQualifiers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 positionIN;\n"
+        "flat invariant out vec4 dataOUT;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// The invariant qualifer has to be before the storage qualifiers.
+TEST_F(QualificationOrderVertexShaderTest, WrongOrderInvariantNotFirst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 positionIN;\n"
+        "centroid out invariant vec4 dataOUT;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// The precision qualifier is after the storage qualifiers.
+TEST_F(QualificationOrderVertexShaderTest, WrongOrderPrecision)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 positionIN;\n"
+        "highp centroid out vec4 dataOUT;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// A variable cannot have multiple declarations of the 'in' storage qualifier.
+TEST_F(QualificationOrderVertexShaderTest, RepeatingInQualifier)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in in vec4 positionIN;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// A variable cannot have multiple declarations of the 'attribute' storage qualifier.
+TEST_F(QualificationOrderVertexShaderTest, RepeatingAttributeQualifier)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "attribute attribute vec4 positionIN;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Vertex input cannot be qualified with invariant.
+TEST_F(QualificationOrderVertexShaderTest, InvariantVertexInput)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "invariant attribute vec4 positionIN;\n"
+        "void main() {\n"
+        "gl_Position = positionIN;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Cannot have a function parameter with the invariant qualifier.
+TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersInvariant)
+{
+    const std::string &shaderString =
+        "precision lowp float;\n"
+        "varying float value;\n"
+        "float foo0 (invariant in float x) {\n"
+        "   return 2.0*x;\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "	gl_FragColor = vec4(foo0(value));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
+    }
+}
+
+// Cannot have a function parameter with the attribute qualifier.
+TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersAttribute)
+{
+    const std::string &shaderString =
+        "precision lowp float;\n"
+        "varying float value;\n"
+        "float foo0 (attribute float x) {\n"
+        "   return 2.0*x;\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "	gl_FragColor = vec4(foo0(value));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
+    }
+}
+
+// Cannot have a function parameter with the varying qualifier.
+TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersVarying)
+{
+    const std::string &shaderString =
+        "precision lowp float;\n"
+        "varying float value;\n"
+        "float foo0 (varying float x) {\n"
+        "   return 2.0*x;\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "	gl_FragColor = vec4(foo0(value));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
+    }
+}
+
+// Cannot have a function parameter with the layout qualifier
+TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersLayout)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision lowp float;\n"
+        "in float value;\n"
+        "float foo0 (layout(location = 3) in float x) {\n"
+        "   return 2.0*x;\n"
+        "}\n"
+        "out vec4 colorOUT;\n"
+        "void main()\n"
+        "{\n"
+        "	colorOUT = vec4(foo0(value));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
+    }
+}
+
+// Cannot have a function parameter with the centroid qualifier
+TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersCentroidIn)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision lowp float;\n"
+        "in float value;\n"
+        "float foo0 (centroid in float x) {\n"
+        "   return 2.0*x;\n"
+        "}\n"
+        "out vec4 colorOUT;\n"
+        "void main()\n"
+        "{\n"
+        "	colorOUT = vec4(foo0(value));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
+    }
+}
+
+// Cannot have a function parameter with the flat qualifier
+TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersFlatIn)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision lowp float;\n"
+        "in float value;\n"
+        "float foo0 (flat in float x) {\n"
+        "   return 2.0*x;\n"
+        "}\n"
+        "out vec4 colorOUT;\n"
+        "void main()\n"
+        "{\n"
+        "	colorOUT = vec4(foo0(value));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
+    }
+}
+
+// Output layout location qualifier can't appear more than once within a declaration.
+// GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers.
+TEST_F(QualificationOrderFragmentShaderTest, TwoOutputLocations)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(location=1, location=2) out vec4 myColor;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/RecordConstantPrecision_test.cpp b/src/third_party/angle/src/tests/compiler_tests/RecordConstantPrecision_test.cpp
new file mode 100644
index 0000000..2cd2bfd
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/RecordConstantPrecision_test.cpp
@@ -0,0 +1,95 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RecordConstantPrecision_test.cpp:
+//   Test for recording constant variable precision when it affects consuming expression.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+class RecordConstantPrecisionTest : public MatchOutputCodeTest
+{
+  public:
+    RecordConstantPrecisionTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT) {}
+};
+
+// The constant cannot be folded if its precision is higher than the other operands, since it
+// increases the precision of the consuming expression.
+TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantAsParameter)
+{
+    const std::string &shaderString =
+        "uniform mediump float u;"
+        "void main()\n"
+        "{\n"
+        "    const highp float a = 4096.5;\n"
+        "    mediump float b = fract(a + u);\n"
+        "    gl_FragColor = vec4(b);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("const highp float webgl_angle_s"));
+    ASSERT_FALSE(foundInCode("fract(4096.5"));
+    ASSERT_FALSE(foundInCode("fract((4096.5"));
+}
+
+// The constant can be folded if its precision is equal to the other operands, as it does not
+// increase the precision of the consuming expression.
+TEST_F(RecordConstantPrecisionTest, EqualPrecisionConstantAsParameter)
+{
+    const std::string &shaderString =
+        "uniform mediump float u;"
+        "void main()\n"
+        "{\n"
+        "    const mediump float a = 4096.5;\n"
+        "    mediump float b = fract(a + u);\n"
+        "    gl_FragColor = vec4(b);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundInCode("const mediump float webgl_angle_s"));
+    ASSERT_TRUE(foundInCode("fract((4096.5"));
+}
+
+// The constant cannot be folded if its precision is higher than the other operands, since it
+// increases the precision of the consuming expression. This applies also when the constant is
+// part of a constant expression that can be folded.
+TEST_F(RecordConstantPrecisionTest, FoldedBinaryConstantPrecisionIsHigher)
+{
+    const std::string &shaderString =
+        "uniform mediump float u;"
+        "void main()\n"
+        "{\n"
+        "    const highp float a = 4095.5;\n"
+        "    mediump float b = fract((a + 1.0) + u);\n"
+        "    gl_FragColor = vec4(b);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("const highp float webgl_angle_s"));
+    ASSERT_FALSE(foundInCode("fract(4096.5"));
+    ASSERT_FALSE(foundInCode("fract((4096.5"));
+}
+
+
+// The constant cannot be folded if its precision is higher than the other operands, since it
+// increases the precision of the consuming expression. This applies also when the constant is
+// part of a constant expression that can be folded.
+TEST_F(RecordConstantPrecisionTest, FoldedUnaryConstantPrecisionIsHigher)
+{
+    const std::string &shaderString =
+        "uniform mediump float u;"
+        "void main()\n"
+        "{\n"
+        "    const highp float a = 0.5;\n"
+        "    mediump float b = sin(fract(a) + u);\n"
+        "    gl_FragColor = vec4(b);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_TRUE(foundInCode("const highp float webgl_angle_s"));
+    ASSERT_FALSE(foundInCode("sin(0.5"));
+    ASSERT_FALSE(foundInCode("sin((0.5"));
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/RemovePow_test.cpp b/src/third_party/angle/src/tests/compiler_tests/RemovePow_test.cpp
new file mode 100644
index 0000000..8367ac7
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/RemovePow_test.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemovePow_test.cpp:
+//   Tests for removing pow() function calls from the AST.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/NodeSearch.h"
+#include "compiler/translator/TranslatorGLSL.h"
+
+using namespace sh;
+
+class RemovePowTest : public testing::Test
+{
+  public:
+    RemovePowTest() {}
+
+  protected:
+    void SetUp() override
+    {
+        allocator.push();
+        SetGlobalPoolAllocator(&allocator);
+        ShBuiltInResources resources;
+        sh::InitBuiltInResources(&resources);
+        mTranslatorGLSL =
+            new sh::TranslatorGLSL(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT);
+        ASSERT_TRUE(mTranslatorGLSL->Init(resources));
+    }
+
+    void TearDown() override
+    {
+        SafeDelete(mTranslatorGLSL);
+        SetGlobalPoolAllocator(nullptr);
+        allocator.pop();
+    }
+
+    void compile(const std::string& shaderString)
+    {
+        const char *shaderStrings[] = { shaderString.c_str() };
+        mASTRoot = mTranslatorGLSL->compileTreeForTesting(shaderStrings, 1,
+                                                          SH_OBJECT_CODE | SH_REMOVE_POW_WITH_CONSTANT_EXPONENT);
+        if (!mASTRoot)
+        {
+            TInfoSink &infoSink = mTranslatorGLSL->getInfoSink();
+            FAIL() << "Shader compilation into ESSL failed " << infoSink.info.c_str();
+        }
+    }
+
+    template <class T>
+    bool foundInAST()
+    {
+        return T::search(mASTRoot);
+    }
+
+  private:
+    sh::TranslatorGLSL *mTranslatorGLSL;
+    TIntermNode *mASTRoot;
+
+    TPoolAllocator allocator;
+};
+
+// Check if there's a pow() node anywhere in the tree.
+class FindPow : public sh::NodeSearchTraverser<FindPow>
+{
+  public:
+    bool visitBinary(Visit visit, TIntermBinary *node) override
+    {
+        if (node->getOp() == EOpPow)
+        {
+            mFound = true;
+        }
+        return !mFound;
+    }
+};
+
+// Check if the tree starting at node corresponds to exp2(y * log2(x))
+// If the tree matches, set base to the node corresponding to x.
+bool IsPowWorkaround(TIntermNode *node, TIntermNode **base)
+{
+    TIntermUnary *exp = node->getAsUnaryNode();
+    if (exp != nullptr && exp->getOp() == EOpExp2)
+    {
+        TIntermBinary *mul = exp->getOperand()->getAsBinaryNode();
+        if (mul != nullptr && mul->isMultiplication())
+        {
+            TIntermUnary *log = mul->getRight()->getAsUnaryNode();
+            if (mul->getLeft()->getAsConstantUnion() && log != nullptr)
+            {
+                if (log->getOp() == EOpLog2)
+                {
+                    if (base)
+                        *base = log->getOperand();
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+// Check if there's a node with the correct workaround to pow anywhere in the tree.
+class FindPowWorkaround : public sh::NodeSearchTraverser<FindPowWorkaround>
+{
+  public:
+    bool visitUnary(Visit visit, TIntermUnary *node) override
+    {
+        mFound = IsPowWorkaround(node, nullptr);
+        return !mFound;
+    }
+};
+
+// Check if there's a node with the correct workaround to pow with another workaround to pow
+// nested within it anywhere in the tree.
+class FindNestedPowWorkaround : public sh::NodeSearchTraverser<FindNestedPowWorkaround>
+{
+  public:
+    bool visitUnary(Visit visit, TIntermUnary *node) override
+    {
+        TIntermNode *base = nullptr;
+        bool oneFound = IsPowWorkaround(node, &base);
+        if (oneFound && base)
+            mFound = IsPowWorkaround(base, nullptr);
+        return !mFound;
+    }
+};
+
+TEST_F(RemovePowTest, PowWithConstantExponent)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   gl_FragColor = pow(vec4(u), vec4(0.5));\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundInAST<FindPow>());
+    ASSERT_TRUE(foundInAST<FindPowWorkaround>());
+    ASSERT_FALSE(foundInAST<FindNestedPowWorkaround>());
+}
+
+TEST_F(RemovePowTest, NestedPowWithConstantExponent)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main() {\n"
+        "   gl_FragColor = pow(pow(vec4(u), vec4(2.0)), vec4(0.5));\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundInAST<FindPow>());
+    ASSERT_TRUE(foundInAST<FindNestedPowWorkaround>());
+}
+
diff --git a/src/third_party/angle/src/tests/compiler_tests/SamplerMultisample_test.cpp b/src/third_party/angle/src/tests/compiler_tests/SamplerMultisample_test.cpp
new file mode 100644
index 0000000..e1baa3a
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/SamplerMultisample_test.cpp
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2016 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.
+//
+// SamplerMultisample_test.cpp:
+// Tests compiling shaders that use gsampler2DMS types
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+
+using namespace sh;
+
+class SamplerMultisampleTest : public ShaderCompileTreeTest
+{
+  public:
+    SamplerMultisampleTest() {}
+
+  protected:
+    ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
+};
+
+// checks whether compiler has parsed the gsampler2DMS, texelfetch qualifiers correctly
+TEST_F(SamplerMultisampleTest, TexelFetchSampler2DMSQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision highp float;\n"
+        "uniform highp sampler2DMS s;\n"
+        "uniform highp isampler2DMS is;\n"
+        "uniform highp usampler2DMS us;\n"
+        ""
+        "void main() {\n"
+        "    vec4 tex1 = texelFetch(s, ivec2(0, 0), 0);\n"
+        "    ivec4 tex2 = texelFetch(is, ivec2(0, 0), 0);\n"
+        "    uvec4 tex3 = texelFetch(us, ivec2(0, 0), 0);\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// checks whether compiler has parsed the gsampler2DMS, texturesize qualifiers correctly
+TEST_F(SamplerMultisampleTest, TextureSizeSampler2DMSQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision highp float;\n"
+        "uniform highp sampler2DMS s;\n"
+        "uniform highp isampler2DMS is;\n"
+        "uniform highp usampler2DMS us;\n"
+        ""
+        "void main() {\n"
+        "    ivec2 size = textureSize(s);\n"
+        "    size = textureSize(is);\n"
+        "    size = textureSize(us);\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// checks gsampler2DMS has no default precision
+TEST_F(SamplerMultisampleTest, NoPrecisionSampler2DMS)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision highp float;\n"
+        "uniform sampler2DMS s;\n"
+        "uniform isampler2DMS is;\n"
+        "uniform usampler2DMS us;\n"
+        ""
+        "void main() {}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/ShCompile_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ShCompile_test.cpp
new file mode 100644
index 0000000..21e4a3c
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ShCompile_test.cpp
@@ -0,0 +1,83 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ShCompile_test.cpp
+//   Test the sh::Compile interface with different parameters.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+class ShCompileTest : public testing::Test
+{
+  public:
+    ShCompileTest() {}
+
+  protected:
+    void SetUp() override
+    {
+        sh::InitBuiltInResources(&mResources);
+        mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL_SPEC,
+                                          SH_GLSL_COMPATIBILITY_OUTPUT, &mResources);
+        ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
+    }
+
+    void TearDown() override
+    {
+        if (mCompiler)
+        {
+            sh::Destruct(mCompiler);
+            mCompiler = nullptr;
+        }
+    }
+
+    void testCompile(const char **shaderStrings, int stringCount, bool expectation)
+    {
+        bool success                  = sh::Compile(mCompiler, shaderStrings, stringCount, 0);
+        const std::string &compileLog = sh::GetInfoLog(mCompiler);
+        EXPECT_EQ(expectation, success) << compileLog;
+    }
+
+  private:
+    ShBuiltInResources mResources;
+    ShHandle mCompiler;
+};
+
+// Test calling sh::Compile with more than one shader source string.
+TEST_F(ShCompileTest, MultipleShaderStrings)
+{
+    const std::string &shaderString1 =
+        "precision mediump float;\n"
+        "void main() {\n";
+    const std::string &shaderString2 =
+        "    gl_FragColor = vec4(0.0);\n"
+        "}";
+
+    const char *shaderStrings[] = {shaderString1.c_str(), shaderString2.c_str()};
+
+    testCompile(shaderStrings, 2, true);
+}
+
+// Test calling sh::Compile with a tokens split into different shader source strings.
+TEST_F(ShCompileTest, TokensSplitInShaderStrings)
+{
+    const std::string &shaderString1 =
+        "precision mediump float;\n"
+        "void ma";
+    const std::string &shaderString2 =
+        "in() {\n"
+        "#i";
+    const std::string &shaderString3 =
+        "f 1\n"
+        "    gl_FragColor = vec4(0.0);\n"
+        "#endif\n"
+        "}";
+
+    const char *shaderStrings[] = {shaderString1.c_str(), shaderString2.c_str(),
+                                   shaderString3.c_str()};
+
+    testCompile(shaderStrings, 3, true);
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/ShaderExtension_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ShaderExtension_test.cpp
new file mode 100644
index 0000000..576fa75
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ShaderExtension_test.cpp
@@ -0,0 +1,218 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Extension_test.cpp
+//   Test that shaders need various extensions to be compiled.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+static const char *FragDepthExtShdr[] =
+{
+    // First string of the shader. The required pragma declaration.
+    "#extension GL_EXT_frag_depth : enable\n",
+
+    // Second string of the shader. The rest of the shader body.
+    "void main() { gl_FragDepthEXT = 1.0; }\n"
+};
+
+static const char *StandDerivExtShdr[] =
+{
+    // First string of the shader. The required pragma declaration.
+    "#extension GL_OES_standard_derivatives : enable\n",
+
+    // Second string of the shader. The rest of the shader body.
+    "precision mediump float;\n"
+    "varying vec2 texCoord;\n"
+    "void main() { gl_FragColor = vec4(dFdx(texCoord.x), dFdy(texCoord.y), fwidth(texCoord.x), 1.0); }\n"
+};
+
+static const char *TextureLODShdr[] =
+{
+    // First string of the shader. The required pragma declaration.
+    "#extension GL_EXT_shader_texture_lod : enable\n",
+
+    // Second string of the shader. The rest of the shader body.
+    "precision mediump float;\n"
+    "varying vec2 texCoord0v;\n"
+    "uniform float lod;\n"
+    "uniform sampler2D tex;\n"
+    "void main() { vec4 color = texture2DLodEXT(tex, texCoord0v, lod); }\n"
+};
+
+class ShaderExtensionTest : public testing::Test
+{
+  public:
+    ShaderExtensionTest() {}
+
+  protected:
+    virtual void SetUp()
+    {
+        sh::InitBuiltInResources(&mResources);
+        mCompiler = nullptr;
+    }
+
+    virtual void TearDown()
+    {
+        DestroyCompiler();
+    }
+
+    void DestroyCompiler()
+    {
+        if (mCompiler)
+        {
+            sh::Destruct(mCompiler);
+            mCompiler = nullptr;
+        }
+    }
+
+    void InitializeCompiler()
+    {
+        DestroyCompiler();
+        mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL_SPEC,
+                                          SH_GLSL_COMPATIBILITY_OUTPUT, &mResources);
+        ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
+    }
+
+    void TestShaderExtension(const char **shaderStrings, int stringCount, bool expectation)
+    {
+        bool success                  = sh::Compile(mCompiler, shaderStrings, stringCount, 0);
+        const std::string &compileLog = sh::GetInfoLog(mCompiler);
+        EXPECT_EQ(expectation, success) << compileLog;
+    }
+
+  protected:
+    ShBuiltInResources mResources;
+    ShHandle mCompiler;
+};
+
+TEST_F(ShaderExtensionTest, FragDepthExtRequiresExt)
+{
+    // Extension is required to compile properly.
+    mResources.EXT_frag_depth = 0;
+    InitializeCompiler();
+    TestShaderExtension(FragDepthExtShdr, 2, false);
+}
+
+TEST_F(ShaderExtensionTest, FragDepthExtRequiresPragma)
+{
+    // Pragma is required to compile properly.
+    mResources.EXT_frag_depth = 1;
+    InitializeCompiler();
+    TestShaderExtension(&FragDepthExtShdr[1], 1, false);
+}
+
+TEST_F(ShaderExtensionTest, FragDepthExtCompiles)
+{
+    // Test that it compiles properly with extension enabled.
+    mResources.EXT_frag_depth = 1;
+    InitializeCompiler();
+    TestShaderExtension(FragDepthExtShdr, 2, true);
+}
+
+TEST_F(ShaderExtensionTest, FragDepthExtResetsInternalStates)
+{
+    // Test that extension internal states are reset properly between compiles.
+    mResources.EXT_frag_depth = 1;
+    InitializeCompiler();
+
+    TestShaderExtension(FragDepthExtShdr, 2, true);
+    TestShaderExtension(&FragDepthExtShdr[1], 1, false);
+    TestShaderExtension(FragDepthExtShdr, 2, true);
+}
+
+TEST_F(ShaderExtensionTest, StandDerivExtRequiresExt)
+{
+    // Extension is required to compile properly.
+    mResources.OES_standard_derivatives = 0;
+    InitializeCompiler();
+    TestShaderExtension(StandDerivExtShdr, 2, false);
+}
+
+TEST_F(ShaderExtensionTest, StandDerivExtRequiresPragma)
+{
+    // Pragma is required to compile properly.
+    mResources.OES_standard_derivatives = 1;
+    InitializeCompiler();
+    TestShaderExtension(&StandDerivExtShdr[1], 1, false);
+}
+
+TEST_F(ShaderExtensionTest, StandDerivExtCompiles)
+{
+    // Test that it compiles properly with extension enabled.
+    mResources.OES_standard_derivatives = 1;
+    InitializeCompiler();
+    TestShaderExtension(StandDerivExtShdr, 2, true);
+}
+
+TEST_F(ShaderExtensionTest, StandDerivExtResetsInternalStates)
+{
+    // Test that extension internal states are reset properly between compiles.
+    mResources.OES_standard_derivatives = 1;
+    InitializeCompiler();
+
+    TestShaderExtension(StandDerivExtShdr, 2, true);
+    TestShaderExtension(&StandDerivExtShdr[1], 1, false);
+    TestShaderExtension(StandDerivExtShdr, 2, true);
+    TestShaderExtension(&StandDerivExtShdr[1], 1, false);
+}
+
+TEST_F(ShaderExtensionTest, TextureLODExtRequiresExt)
+{
+    // Extension is required to compile properly.
+    mResources.EXT_shader_texture_lod = 0;
+    InitializeCompiler();
+    TestShaderExtension(TextureLODShdr, 2, false);
+}
+
+TEST_F(ShaderExtensionTest, TextureLODExtRequiresPragma)
+{
+    // Pragma is required to compile properly.
+    mResources.EXT_shader_texture_lod = 1;
+    InitializeCompiler();
+    TestShaderExtension(&TextureLODShdr[1], 1, false);
+}
+
+TEST_F(ShaderExtensionTest, TextureLODExtCompiles)
+{
+    // Test that it compiles properly with extension enabled.
+    mResources.EXT_shader_texture_lod = 1;
+    InitializeCompiler();
+    TestShaderExtension(TextureLODShdr, 2, true);
+}
+
+TEST_F(ShaderExtensionTest, TextureLODExtResetsInternalStates)
+{
+    // Test that extension internal states are reset properly between compiles.
+    mResources.EXT_shader_texture_lod = 1;
+    InitializeCompiler();
+
+    TestShaderExtension(&TextureLODShdr[1], 1, false);
+    TestShaderExtension(TextureLODShdr, 2, true);
+    TestShaderExtension(&TextureLODShdr[1], 1, false);
+    TestShaderExtension(TextureLODShdr, 2, true);
+}
+
+// Test a bug where we could modify the value of a builtin variable.
+TEST_F(ShaderExtensionTest, BuiltinRewritingBug)
+{
+    mResources.MaxDrawBuffers = 4;
+    mResources.EXT_draw_buffers = 1;
+    InitializeCompiler();
+
+    const std::string &shaderString =
+        "#extension GL_EXT_draw_buffers : require\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "    gl_FragData[gl_MaxDrawBuffers] = vec4(0.0);\n"
+        "}";
+
+    const char *shaderStrings[] = { shaderString.c_str() };
+
+    TestShaderExtension(shaderStrings, 1, false);
+    TestShaderExtension(shaderStrings, 1, false);
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/ShaderImage_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ShaderImage_test.cpp
new file mode 100644
index 0000000..49e8ceb
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ShaderImage_test.cpp
@@ -0,0 +1,242 @@
+//
+// Copyright (c) 2016 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.
+//
+// ShaderImage_test.cpp:
+// Tests for images
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+
+using namespace sh;
+
+namespace
+{
+
+// Checks that the imageStore call with mangled name imageStoreMangledName exists in the AST.
+// Further each argument is checked whether it matches the expected properties given the compiled
+// shader.
+void CheckImageStoreCall(TIntermNode *astRoot,
+                         const TString &imageStoreMangledName,
+                         TBasicType imageType,
+                         int storeLocationNominalSize,
+                         TBasicType storeValueType,
+                         int storeValueNominalSize)
+{
+    const TIntermAggregate *imageStoreFunctionCall =
+        FindFunctionCallNode(astRoot, imageStoreMangledName);
+    ASSERT_NE(nullptr, imageStoreFunctionCall);
+
+    const TIntermSequence *storeArguments = imageStoreFunctionCall->getSequence();
+    ASSERT_EQ(3u, storeArguments->size());
+
+    const TIntermTyped *storeArgument1Typed = (*storeArguments)[0]->getAsTyped();
+    ASSERT_EQ(imageType, storeArgument1Typed->getBasicType());
+
+    const TIntermTyped *storeArgument2Typed = (*storeArguments)[1]->getAsTyped();
+    ASSERT_EQ(EbtInt, storeArgument2Typed->getBasicType());
+    ASSERT_EQ(storeLocationNominalSize, storeArgument2Typed->getNominalSize());
+
+    const TIntermTyped *storeArgument3Typed = (*storeArguments)[2]->getAsTyped();
+    ASSERT_EQ(storeValueType, storeArgument3Typed->getBasicType());
+    ASSERT_EQ(storeValueNominalSize, storeArgument3Typed->getNominalSize());
+}
+
+// Checks that the imageLoad call with mangled name imageLoadMangledName exists in the AST.
+// Further each argument is checked whether it matches the expected properties given the compiled
+// shader.
+void CheckImageLoadCall(TIntermNode *astRoot,
+                        const TString &imageLoadMangledName,
+                        TBasicType imageType,
+                        int loadLocationNominalSize)
+{
+    const TIntermAggregate *imageLoadFunctionCall =
+        FindFunctionCallNode(astRoot, imageLoadMangledName);
+    ASSERT_NE(nullptr, imageLoadFunctionCall);
+
+    const TIntermSequence *loadArguments = imageLoadFunctionCall->getSequence();
+    ASSERT_EQ(2u, loadArguments->size());
+
+    const TIntermTyped *loadArgument1Typed = (*loadArguments)[0]->getAsTyped();
+    ASSERT_EQ(imageType, loadArgument1Typed->getBasicType());
+
+    const TIntermTyped *loadArgument2Typed = (*loadArguments)[1]->getAsTyped();
+    ASSERT_EQ(EbtInt, loadArgument2Typed->getBasicType());
+    ASSERT_EQ(loadLocationNominalSize, loadArgument2Typed->getNominalSize());
+}
+
+// Checks whether the image is properly exported as a uniform by the compiler.
+void CheckExportedImageUniform(const std::vector<sh::Uniform> &uniforms,
+                               size_t uniformIndex,
+                               ::GLenum imageTypeGL,
+                               const TString &imageName)
+{
+    ASSERT_EQ(1u, uniforms.size());
+
+    const auto &imageUniform = uniforms[uniformIndex];
+    ASSERT_EQ(imageTypeGL, imageUniform.type);
+    ASSERT_STREQ(imageUniform.name.c_str(), imageName.c_str());
+}
+
+// Checks whether the image is saved in the AST as a node with the correct properties given the
+// shader.
+void CheckImageDeclaration(TIntermNode *astRoot,
+                           const TString &imageName,
+                           TBasicType imageType,
+                           TLayoutImageInternalFormat internalFormat,
+                           bool readonly,
+                           bool writeonly,
+                           bool coherent,
+                           bool restrictQualifier,
+                           bool volatileQualifier,
+                           int binding)
+{
+    const TIntermSymbol *myImageNode = FindSymbolNode(astRoot, imageName, imageType);
+    ASSERT_NE(nullptr, myImageNode);
+
+    const TType &myImageType                = myImageNode->getType();
+    TLayoutQualifier myImageLayoutQualifier = myImageType.getLayoutQualifier();
+    ASSERT_EQ(internalFormat, myImageLayoutQualifier.imageInternalFormat);
+    TMemoryQualifier myImageMemoryQualifier = myImageType.getMemoryQualifier();
+    ASSERT_EQ(readonly, myImageMemoryQualifier.readonly);
+    ASSERT_EQ(writeonly, myImageMemoryQualifier.writeonly);
+    ASSERT_EQ(coherent, myImageMemoryQualifier.coherent);
+    ASSERT_EQ(restrictQualifier, myImageMemoryQualifier.restrictQualifier);
+    ASSERT_EQ(volatileQualifier, myImageMemoryQualifier.volatileQualifier);
+    ASSERT_EQ(binding, myImageType.getLayoutQualifier().binding);
+}
+
+}  // namespace
+
+class ShaderImageTest : public ShaderCompileTreeTest
+{
+  public:
+    ShaderImageTest() {}
+
+  protected:
+    void SetUp() override
+    {
+        ShaderCompileTreeTest::SetUp();
+        mExtraCompileOptions |= SH_VARIABLES;
+    }
+
+    ::GLenum getShaderType() const override { return GL_COMPUTE_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
+};
+
+// Test that an image2D is properly parsed and exported as a uniform.
+TEST_F(ShaderImageTest, Image2DDeclaration)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 4) in;\n"
+        "layout(rgba32f, binding = 1) uniform highp readonly image2D myImage;\n"
+        "void main() {\n"
+        "   ivec2 sz = imageSize(myImage);\n"
+        "}";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed" << mInfoLog;
+    }
+
+    CheckExportedImageUniform(getUniforms(), 0, GL_IMAGE_2D, "myImage");
+    CheckImageDeclaration(mASTRoot, "myImage", EbtImage2D, EiifRGBA32F, true, false, false, false,
+                          false, 1);
+}
+
+// Test that an image3D is properly parsed and exported as a uniform.
+TEST_F(ShaderImageTest, Image3DDeclaration)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 4) in;\n"
+        "layout(rgba32ui, binding = 3) uniform highp writeonly readonly uimage3D myImage;\n"
+        "void main() {\n"
+        "   ivec3 sz = imageSize(myImage);\n"
+        "}";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed" << mInfoLog;
+    }
+
+    CheckExportedImageUniform(getUniforms(), 0, GL_UNSIGNED_INT_IMAGE_3D, "myImage");
+    CheckImageDeclaration(mASTRoot, "myImage", EbtUImage3D, EiifRGBA32UI, true, true, false, false,
+                          false, 3);
+}
+
+// Check that imageLoad calls get correctly parsed.
+TEST_F(ShaderImageTest, ImageLoad)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 4) in;\n"
+        "layout(rgba32f) uniform highp readonly image2D my2DImageInput;\n"
+        "layout(rgba32i) uniform highp readonly iimage3D my3DImageInput;\n"
+        "void main() {\n"
+        "   vec4 result = imageLoad(my2DImageInput, ivec2(gl_LocalInvocationID.xy));\n"
+        "   ivec4 result2 = imageLoad(my3DImageInput, ivec3(gl_LocalInvocationID.xyz));\n"
+        "}";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed" << mInfoLog;
+    }
+
+    // imageLoad call with image2D passed
+    CheckImageLoadCall(mASTRoot, "imageLoad(im21;vi2;", EbtImage2D, 2);
+
+    // imageLoad call with image3D passed
+    CheckImageLoadCall(mASTRoot, "imageLoad(iim31;vi3;", EbtIImage3D, 3);
+}
+
+// Check that imageStore calls get correctly parsed.
+TEST_F(ShaderImageTest, ImageStore)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 4) in;\n"
+        "layout(rgba32f) uniform highp writeonly image2D my2DImageOutput;\n"
+        "layout(rgba32ui) uniform highp writeonly uimage2DArray my2DImageArrayOutput;\n"
+        "void main() {\n"
+        "   imageStore(my2DImageOutput, ivec2(gl_LocalInvocationID.xy), vec4(0.0));\n"
+        "   imageStore(my2DImageArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));\n"
+        "}";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed" << mInfoLog;
+    }
+
+    // imageStore call with image2D
+    CheckImageStoreCall(mASTRoot, "imageStore(im21;vi2;vf4;", EbtImage2D, 2, EbtFloat, 4);
+
+    // imageStore call with image2DArray
+    CheckImageStoreCall(mASTRoot, "imageStore(uim2a1;vi3;vu4;", EbtUImage2DArray, 3, EbtUInt, 4);
+}
+
+// Check that memory qualifiers are correctly parsed.
+TEST_F(ShaderImageTest, ImageMemoryQualifiers)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 4) in;"
+        "layout(rgba32f) uniform highp coherent readonly image2D image1;\n"
+        "layout(rgba32f) uniform highp volatile writeonly image2D image2;\n"
+        "layout(rgba32f) uniform highp volatile restrict readonly writeonly image2D image3;\n"
+        "void main() {\n"
+        "}";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed" << mInfoLog;
+    }
+
+    CheckImageDeclaration(mASTRoot, "image1", EbtImage2D, EiifRGBA32F, true, false, true, false,
+                          false, -1);
+    CheckImageDeclaration(mASTRoot, "image2", EbtImage2D, EiifRGBA32F, false, true, true, false,
+                          true, -1);
+    CheckImageDeclaration(mASTRoot, "image3", EbtImage2D, EiifRGBA32F, true, true, true, true, true,
+                          -1);
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/ShaderValidation_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ShaderValidation_test.cpp
new file mode 100644
index 0000000..4ce9458
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ShaderValidation_test.cpp
@@ -0,0 +1,3860 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ShaderValidation_test.cpp:
+//   Tests that malformed shaders fail compilation, and that correct shaders pass compilation.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+
+using namespace sh;
+
+// Tests that don't target a specific version of the API spec (sometimes there are minor
+// differences). They choose the shader spec version with version directives.
+class FragmentShaderValidationTest : public ShaderCompileTreeTest
+{
+  public:
+    FragmentShaderValidationTest() {}
+  protected:
+    ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
+};
+
+// Tests that don't target a specific version of the API spec (sometimes there are minor
+// differences). They choose the shader spec version with version directives.
+class VertexShaderValidationTest : public ShaderCompileTreeTest
+{
+  public:
+    VertexShaderValidationTest() {}
+
+  protected:
+    ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
+};
+
+class WebGL2FragmentShaderValidationTest : public ShaderCompileTreeTest
+{
+  public:
+    WebGL2FragmentShaderValidationTest() {}
+
+  protected:
+    ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_WEBGL2_SPEC; }
+};
+
+class WebGL1FragmentShaderValidationTest : public ShaderCompileTreeTest
+{
+  public:
+    WebGL1FragmentShaderValidationTest() {}
+
+  protected:
+    ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_WEBGL_SPEC; }
+};
+
+class ComputeShaderValidationTest : public ShaderCompileTreeTest
+{
+  public:
+    ComputeShaderValidationTest() {}
+
+  private:
+    ::GLenum getShaderType() const override { return GL_COMPUTE_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
+};
+
+// This is a test for a bug that used to exist in ANGLE:
+// Calling a function with all parameters missing should not succeed.
+TEST_F(FragmentShaderValidationTest, FunctionParameterMismatch)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float fun(float a) {\n"
+        "   return a * 2.0;\n"
+        "}\n"
+        "void main() {\n"
+        "   float ff = fun();\n"
+        "   gl_FragColor = vec4(ff);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Functions can't be redeclared as variables in the same scope (ESSL 1.00 section 4.2.7)
+TEST_F(FragmentShaderValidationTest, RedeclaringFunctionAsVariable)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float fun(float a) {\n"
+        "   return a * 2.0;\n"
+        "}\n"
+        "float fun;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Functions can't be redeclared as structs in the same scope (ESSL 1.00 section 4.2.7)
+TEST_F(FragmentShaderValidationTest, RedeclaringFunctionAsStruct)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float fun(float a) {\n"
+        "   return a * 2.0;\n"
+        "}\n"
+        "struct fun { float a; };\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Functions can't be redeclared with different qualifiers (ESSL 1.00 section 6.1.0)
+TEST_F(FragmentShaderValidationTest, RedeclaringFunctionWithDifferentQualifiers)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float fun(out float a);\n"
+        "float fun(float a) {\n"
+        "   return a * 2.0;\n"
+        "}\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7)
+TEST_F(FragmentShaderValidationTest, CompareStructsContainingArrays)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "struct s { float a[3]; };\n"
+        "void main() {\n"
+        "   s a;\n"
+        "   s b;\n"
+        "   bool c = (a == b);\n"
+        "   gl_FragColor = vec4(c ? 1.0 : 0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7)
+TEST_F(FragmentShaderValidationTest, AssignStructsContainingArrays)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "struct s { float a[3]; };\n"
+        "void main() {\n"
+        "   s a;\n"
+        "   s b;\n"
+        "   b.a[0] = 0.0;\n"
+        "   a = b;\n"
+        "   gl_FragColor = vec4(a.a[0]);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Assignment and equality are undefined for structures containing samplers (ESSL 1.00 sections 5.7
+// and 5.9)
+TEST_F(FragmentShaderValidationTest, CompareStructsContainingSamplers)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "struct s { sampler2D foo; };\n"
+        "uniform s a;\n"
+        "uniform s b;\n"
+        "void main() {\n"
+        "   bool c = (a == b);\n"
+        "   gl_FragColor = vec4(c ? 1.0 : 0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Samplers are not allowed as l-values (ESSL 3.00 section 4.1.7), our interpretation is that this
+// extends to structs containing samplers. ESSL 1.00 spec is clearer about this.
+TEST_F(FragmentShaderValidationTest, AssignStructsContainingSamplers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "struct s { sampler2D foo; };\n"
+        "uniform s a;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   s b;\n"
+        "   b = a;\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// This is a regression test for a particular bug that was in ANGLE.
+// It also verifies that ESSL3 functionality doesn't leak to ESSL1.
+TEST_F(FragmentShaderValidationTest, ArrayWithNoSizeInInitializerList)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   float a[2], b[];\n"
+        "   gl_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Const variables need an initializer.
+TEST_F(FragmentShaderValidationTest, ConstVarNotInitialized)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   const float a;\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Const variables need an initializer. In ESSL1 const structs containing
+// arrays are not allowed at all since it's impossible to initialize them.
+// Even though this test is for ESSL3 the only thing that's critical for
+// ESSL1 is the non-initialization check that's used for both language versions.
+// Whether ESSL1 compilation generates the most helpful error messages is a
+// secondary concern.
+TEST_F(FragmentShaderValidationTest, ConstStructNotInitialized)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "struct S {\n"
+        "   float a[3];\n"
+        "};\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   const S b;\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Const variables need an initializer. In ESSL1 const arrays are not allowed
+// at all since it's impossible to initialize them.
+// Even though this test is for ESSL3 the only thing that's critical for
+// ESSL1 is the non-initialization check that's used for both language versions.
+// Whether ESSL1 compilation generates the most helpful error messages is a
+// secondary concern.
+TEST_F(FragmentShaderValidationTest, ConstArrayNotInitialized)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   const float a[3];\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3)
+TEST_F(FragmentShaderValidationTest, BlockLayoutQualifierOnRegularUniform)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(packed) uniform mat2 x;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3)
+TEST_F(FragmentShaderValidationTest, BlockLayoutQualifierOnUniformWithEmptyDecl)
+{
+    // Yes, the comma in the declaration below is not a typo.
+    // Empty declarations are allowed in GLSL.
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(packed) uniform mat2, x;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9)
+TEST_F(FragmentShaderValidationTest, ArraysOfArrays1)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   float[5] a[3];\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9)
+TEST_F(FragmentShaderValidationTest, ArraysOfArrays2)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   float[2] a, b[3];\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Implicitly sized arrays need to be initialized (ESSL 3.00 section 4.1.9)
+TEST_F(FragmentShaderValidationTest, UninitializedImplicitArraySize)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   float[] a;\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// An operator can only form a constant expression if all the operands are constant expressions
+// - even operands of ternary operator that are never evaluated. (ESSL 3.00 section 4.3.3)
+TEST_F(FragmentShaderValidationTest, TernaryOperatorNotConstantExpression)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform bool u;\n"
+        "void main() {\n"
+        "   const bool a = true ? true : u;\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Ternary operator can't operate on arrays (ESSL 3.00 section 5.7)
+TEST_F(FragmentShaderValidationTest, TernaryOperatorOnArrays)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   float[1] a = float[1](0.0);\n"
+        "   float[1] b = float[1](1.0);\n"
+        "   float[1] c = true ? a : b;\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Ternary operator can't operate on structs (ESSL 3.00 section 5.7)
+TEST_F(FragmentShaderValidationTest, TernaryOperatorOnStructs)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "struct S { float foo; };\n"
+        "void main() {\n"
+        "   S a = S(0.0);\n"
+        "   S b = S(1.0);\n"
+        "   S c = true ? a : b;\n"
+        "   my_FragColor = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Array length() returns a constant signed integral expression (ESSL 3.00 section 4.1.9)
+// Assigning it to unsigned should result in an error.
+TEST_F(FragmentShaderValidationTest, AssignArrayLengthToUnsigned)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   int[1] arr;\n"
+        "   uint l = arr.length();\n"
+        "   my_FragColor = vec4(float(l));\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
+// Initializing with a varying should be an error.
+TEST_F(FragmentShaderValidationTest, AssignVaryingToGlobal)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "varying float a;\n"
+        "float b = a * 2.0;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(b);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3)
+// Initializing with an uniform should be an error.
+TEST_F(FragmentShaderValidationTest, AssignUniformToGlobalESSL3)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform float a;\n"
+        "float b = a * 2.0;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   my_FragColor = vec4(b);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
+// Initializing with an uniform should generate a warning
+// (we don't generate an error on ESSL 1.00 because of legacy compatibility)
+TEST_F(FragmentShaderValidationTest, AssignUniformToGlobalESSL1)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float a;\n"
+        "float b = a * 2.0;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(b);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        if (!hasWarning())
+        {
+            FAIL() << "Shader compilation succeeded without warnings, expecting warning:\n"
+                   << mInfoLog;
+        }
+    }
+    else
+    {
+        FAIL() << "Shader compilation failed, expecting success with warning:\n" << mInfoLog;
+    }
+}
+
+// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
+// Initializing with an user-defined function call should be an error.
+TEST_F(FragmentShaderValidationTest, AssignFunctionCallToGlobal)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float foo() { return 1.0; }\n"
+        "float b = foo();\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(b);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
+// Initializing with an assignment to another global should be an error.
+TEST_F(FragmentShaderValidationTest, AssignAssignmentToGlobal)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float c = 1.0;\n"
+        "float b = (c = 0.0);\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(b);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
+// Initializing with incrementing another global should be an error.
+TEST_F(FragmentShaderValidationTest, AssignIncrementToGlobal)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float c = 1.0;\n"
+        "float b = (c++);\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(b);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
+// Initializing with a texture lookup function call should be an error.
+TEST_F(FragmentShaderValidationTest, AssignTexture2DToGlobal)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform mediump sampler2D s;\n"
+        "float b = texture2D(s, vec2(0.5, 0.5)).x;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(b);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3)
+// Initializing with a non-constant global should be an error.
+TEST_F(FragmentShaderValidationTest, AssignNonConstGlobalToGlobal)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "float a = 1.0;\n"
+        "float b = a * 2.0;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   my_FragColor = vec4(b);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3)
+// Initializing with a constant global should be fine.
+TEST_F(FragmentShaderValidationTest, AssignConstGlobalToGlobal)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "const float a = 1.0;\n"
+        "float b = a * 2.0;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   my_FragColor = vec4(b);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Statically assigning to both gl_FragData and gl_FragColor is forbidden (ESSL 1.00 section 7.2)
+TEST_F(FragmentShaderValidationTest, WriteBothFragDataAndFragColor)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void foo() {\n"
+        "   gl_FragData[0].a++;\n"
+        "}\n"
+        "void main() {\n"
+        "   gl_FragColor.x += 0.0;\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Version directive must be on the first line (ESSL 3.00 section 3.3)
+TEST_F(FragmentShaderValidationTest, VersionOnSecondLine)
+{
+    const std::string &shaderString =
+        "\n"
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Layout qualifier can only appear in global scope (ESSL 3.00 section 4.3.8)
+TEST_F(FragmentShaderValidationTest, LayoutQualifierInCondition)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "    int i = 0;\n"
+        "    for (int j = 0; layout(location = 0) bool b = false; ++j) {\n"
+        "        ++i;\n"
+        "    }\n"
+        "    my_FragColor = u;\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Layout qualifier can only appear where specified (ESSL 3.00 section 4.3.8)
+TEST_F(FragmentShaderValidationTest, LayoutQualifierInFunctionReturnType)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "out vec4 my_FragColor;\n"
+        "layout(location = 0) vec4 foo() {\n"
+        "    return u;\n"
+        "}\n"
+        "void main() {\n"
+        "    my_FragColor = foo();\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// If there is more than one output, the location must be specified for all outputs.
+// (ESSL 3.00.04 section 4.3.8.2)
+TEST_F(FragmentShaderValidationTest, TwoOutputsNoLayoutQualifiers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "out vec4 my_FragColor;\n"
+        "out vec4 my_SecondaryFragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = vec4(1.0);\n"
+        "    my_SecondaryFragColor = vec4(0.5);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// (ESSL 3.00.04 section 4.3.8.2)
+TEST_F(FragmentShaderValidationTest, TwoOutputsFirstLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "layout(location = 0) out vec4 my_FragColor;\n"
+        "out vec4 my_SecondaryFragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = vec4(1.0);\n"
+        "    my_SecondaryFragColor = vec4(0.5);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// (ESSL 3.00.04 section 4.3.8.2)
+TEST_F(FragmentShaderValidationTest, TwoOutputsSecondLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "out vec4 my_FragColor;\n"
+        "layout(location = 0) out vec4 my_SecondaryFragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = vec4(1.0);\n"
+        "    my_SecondaryFragColor = vec4(0.5);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Uniforms can be arrays (ESSL 3.00 section 4.3.5)
+TEST_F(FragmentShaderValidationTest, UniformArray)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform vec4[2] u;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = u[0];\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Fragment shader input variables cannot be arrays of structs (ESSL 3.00 section 4.3.4)
+TEST_F(FragmentShaderValidationTest, FragmentInputArrayOfStructs)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "struct S {\n"
+        "    vec4 foo;\n"
+        "};\n"
+        "in S i[2];\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = i[0].foo;\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4)
+// This test is testing the case where the array brackets are after the variable name, so
+// the arrayness isn't known when the type and qualifiers are initially parsed.
+TEST_F(VertexShaderValidationTest, VertexShaderInputArray)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 i[2];\n"
+        "void main() {\n"
+        "    gl_Position = i[0];\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4)
+// This test is testing the case where the array brackets are after the type.
+TEST_F(VertexShaderValidationTest, VertexShaderInputArrayType)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4[2] i;\n"
+        "void main() {\n"
+        "    gl_Position = i[0];\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Fragment shader inputs can't contain booleans (ESSL 3.00 section 4.3.4)
+TEST_F(FragmentShaderValidationTest, FragmentShaderInputStructWithBool)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "struct S {\n"
+        "    bool foo;\n"
+        "};\n"
+        "in S s;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Fragment shader inputs without a flat qualifier can't contain integers (ESSL 3.00 section 4.3.4)
+TEST_F(FragmentShaderValidationTest, FragmentShaderInputStructWithInt)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "struct S {\n"
+        "    int foo;\n"
+        "};\n"
+        "in S s;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Selecting a field of a vector that's the result of dynamic indexing a constant array should work.
+TEST_F(FragmentShaderValidationTest, ShaderSelectingFieldOfVectorIndexedFromArray)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform int i;\n"
+        "void main() {\n"
+        "    float f = vec2[1](vec2(0.0, 0.1))[i].x;\n"
+        "    my_FragColor = vec4(f);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Passing an array into a function and then passing a value from that array into another function
+// should work. This is a regression test for a bug where the mangled name of a TType was not
+// properly updated when determining the type resulting from array indexing.
+TEST_F(FragmentShaderValidationTest, ArrayValueFromFunctionParameterAsParameter)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "float foo(float f) {\n"
+        "   return f * 2.0;\n"
+        "}\n"
+        "float bar(float[2] f) {\n"
+        "    return foo(f[0]);\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "    float arr[2];\n"
+        "    arr[0] = u;\n"
+        "    gl_FragColor = vec4(bar(arr));\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that out-of-range integer literal generates an error in ESSL 3.00.
+TEST_F(FragmentShaderValidationTest, OutOfRangeIntegerLiteral)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision highp int;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = vec4(0x100000000);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that vector field selection from a value taken from an array constructor is accepted as a
+// constant expression.
+TEST_F(FragmentShaderValidationTest, FieldSelectionFromVectorArrayConstructorIsConst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    const float f = vec2[1](vec2(0.0, 1.0))[0].x;\n"
+        "    my_FragColor = vec4(f);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that structure field selection from a value taken from an array constructor is accepted as a
+// constant expression.
+TEST_F(FragmentShaderValidationTest, FieldSelectionFromStructArrayConstructorIsConst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "struct S { float member; };\n"
+        "void main()\n"
+        "{\n"
+        "    const float f = S[1](S(0.0))[0].member;\n"
+        "    my_FragColor = vec4(f);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that a reference to a const array is accepted as a constant expression.
+TEST_F(FragmentShaderValidationTest, ArraySymbolIsConst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    const float[2] arr = float[2](0.0, 1.0);\n"
+        "    const float f = arr[0];\n"
+        "    my_FragColor = vec4(f);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that using an array constructor in a parameter to a built-in function is accepted as a
+// constant expression.
+TEST_F(FragmentShaderValidationTest, BuiltInFunctionAppliedToArrayConstructorIsConst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    const float f = sin(float[2](0.0, 1.0)[0]);\n"
+        "    my_FragColor = vec4(f);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that using an array constructor in a parameter to a built-in function is accepted as a
+// constant expression.
+TEST_F(FragmentShaderValidationTest,
+       BuiltInFunctionWithMultipleParametersAppliedToArrayConstructorIsConst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    const float f = pow(1.0, float[2](0.0, 1.0)[0]);\n"
+        "    my_FragColor = vec4(f);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that using an array constructor in a parameter to a constructor is accepted as a constant
+// expression.
+TEST_F(FragmentShaderValidationTest,
+       ConstructorWithMultipleParametersAppliedToArrayConstructorIsConst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    const vec2 f = vec2(1.0, float[2](0.0, 1.0)[0]);\n"
+        "    my_FragColor = vec4(f.x);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that using an array constructor in an operand of the ternary selection operator is accepted
+// as a constant expression.
+TEST_F(FragmentShaderValidationTest, TernaryOperatorAppliedToArrayConstructorIsConst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    const float f = true ? float[2](0.0, 1.0)[0] : 1.0;\n"
+        "    my_FragColor = vec4(f);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that a ternary operator with one unevaluated non-constant operand is not a constant
+// expression.
+TEST_F(FragmentShaderValidationTest, TernaryOperatorNonConstantOperand)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "void main()\n"
+        "{\n"
+        "    const float f = true ? 1.0 : u;\n"
+        "    gl_FragColor = vec4(f);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that a sampler can't be used in constructor argument list
+TEST_F(FragmentShaderValidationTest, SamplerInConstructorArguments)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform sampler2D s;\n"
+        "void main()\n"
+        "{\n"
+        "    vec2 v = vec2(0.0, s);\n"
+        "    gl_FragColor = vec4(v, 0.0, 0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that void can't be used in constructor argument list
+TEST_F(FragmentShaderValidationTest, VoidInConstructorArguments)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void foo() {}\n"
+        "void main()\n"
+        "{\n"
+        "    vec2 v = vec2(0.0, foo());\n"
+        "    gl_FragColor = vec4(v, 0.0, 0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that a shader passing a struct into a constructor of array of structs with 1 element works.
+TEST_F(FragmentShaderValidationTest, SingleStructArrayConstructor)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform float u;\n"
+        "struct S { float member; };\n"
+        "void main()\n"
+        "{\n"
+        "    S[1] sarr = S[1](S(u));\n"
+        "    my_FragColor = vec4(sarr[0].member);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that a shader with empty constructor parameter list is not accepted.
+TEST_F(FragmentShaderValidationTest, EmptyArrayConstructor)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform float u;\n"
+        "const float[] f = f[]();\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that indexing fragment outputs with a non-constant expression is forbidden, even if ANGLE
+// is able to constant fold the index expression. ESSL 3.00 section 4.3.6.
+TEST_F(FragmentShaderValidationTest, DynamicallyIndexedFragmentOutput)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform int a;\n"
+        "out vec4[2] my_FragData;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragData[true ? 0 : a] = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that indexing an interface block array with a non-constant expression is forbidden, even if
+// ANGLE is able to constant fold the index expression. ESSL 3.00 section 4.3.7.
+TEST_F(FragmentShaderValidationTest, DynamicallyIndexedInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform int a;\n"
+        "uniform B\n"
+        "{\n"
+        "    vec4 f;\n"
+        "}\n"
+        "blocks[2];\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = blocks[true ? 0 : a].f;\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that a shader that uses a struct definition in place of a struct constructor does not
+// compile. See GLSL ES 1.00 section 5.4.3.
+TEST_F(FragmentShaderValidationTest, StructConstructorWithStructDefinition)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    struct s { float f; } (0.0);\n"
+        "    gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that indexing gl_FragData with a non-constant expression is forbidden in WebGL 2.0, even
+// when ANGLE is able to constant fold the index.
+// WebGL 2.0 spec section 'GLSL ES 1.00 Fragment Shader Output'
+TEST_F(WebGL2FragmentShaderValidationTest, IndexFragDataWithNonConstant)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    for (int i = 0; i < 2; ++i) {\n"
+        "        gl_FragData[true ? 0 : i] = vec4(0.0);\n"
+        "    }\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that a non-constant texture offset is not accepted for textureOffset.
+// ESSL 3.00 section 8.8
+TEST_F(FragmentShaderValidationTest, TextureOffsetNonConst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform vec3 u_texCoord;\n"
+        "uniform mediump sampler3D u_sampler;\n"
+        "uniform int x;\n"
+        "void main()\n"
+        "{\n"
+        "   my_FragColor = textureOffset(u_sampler, u_texCoord, ivec3(x, 3, -8));\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that a non-constant texture offset is not accepted for textureProjOffset with bias.
+// ESSL 3.00 section 8.8
+TEST_F(FragmentShaderValidationTest, TextureProjOffsetNonConst)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform vec4 u_texCoord;\n"
+        "uniform mediump sampler3D u_sampler;\n"
+        "uniform int x;\n"
+        "void main()\n"
+        "{\n"
+        "   my_FragColor = textureProjOffset(u_sampler, u_texCoord, ivec3(x, 3, -8), 0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that an out-of-range texture offset is not accepted.
+// GLES 3.0.4 section 3.8.10 specifies that out-of-range offset has undefined behavior.
+TEST_F(FragmentShaderValidationTest, TextureLodOffsetOutOfRange)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform vec3 u_texCoord;\n"
+        "uniform mediump sampler3D u_sampler;\n"
+        "void main()\n"
+        "{\n"
+        "   my_FragColor = textureLodOffset(u_sampler, u_texCoord, 0.0, ivec3(0, 0, 8));\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that default precision qualifier for uint is not accepted.
+// ESSL 3.00.4 section 4.5.4: Only allowed for float, int and sampler types.
+TEST_F(FragmentShaderValidationTest, DefaultPrecisionUint)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision mediump uint;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "   my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that sampler3D needs to be precision qualified.
+// ESSL 3.00.4 section 4.5.4: New ESSL 3.00 sampler types don't have predefined precision.
+TEST_F(FragmentShaderValidationTest, NoPrecisionSampler3D)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform sampler3D s;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "   my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that using a non-constant expression in a for loop initializer is forbidden in WebGL 1.0,
+// even when ANGLE is able to constant fold the initializer.
+// ESSL 1.00 Appendix A.
+TEST_F(WebGL1FragmentShaderValidationTest, NonConstantLoopIndex)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform int u;\n"
+        "void main()\n"
+        "{\n"
+        "    for (int i = (true ? 1 : u); i < 5; ++i) {\n"
+        "        gl_FragColor = vec4(0.0);\n"
+        "    }\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Check that indices that are not integers are rejected.
+// The check should be done even if ESSL 1.00 Appendix A limitations are not applied.
+TEST_F(FragmentShaderValidationTest, NonIntegerIndex)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    float f[3];\n"
+        "    const float i = 2.0;\n"
+        "    gl_FragColor = vec4(f[i]);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// ESSL1 shaders with a duplicate function prototype should be rejected.
+// ESSL 1.00.17 section 4.2.7.
+TEST_F(FragmentShaderValidationTest, DuplicatePrototypeESSL1)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "void foo();\n"
+        "void foo();\n"
+        "void foo() {}\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// ESSL3 shaders with a duplicate function prototype should be allowed.
+// ESSL 3.00.4 section 4.2.3.
+TEST_F(FragmentShaderValidationTest, DuplicatePrototypeESSL3)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void foo();\n"
+        "void foo();\n"
+        "void foo() {}\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Shaders with a local function prototype should be rejected.
+// ESSL 3.00.4 section 4.2.4.
+TEST_F(FragmentShaderValidationTest, LocalFunctionPrototype)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    void foo();\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// ESSL 3.00 fragment shaders can not use #pragma STDGL invariant(all).
+// ESSL 3.00.4 section 4.6.1. Does not apply to other versions of ESSL.
+TEST_F(FragmentShaderValidationTest, ESSL300FragmentInvariantAll)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#pragma STDGL invariant(all)\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Built-in functions can be overloaded in ESSL 1.00.
+TEST_F(FragmentShaderValidationTest, ESSL100BuiltInFunctionOverload)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "int sin(int x)\n"
+        "{\n"
+        "    return int(sin(float(x)));\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "   gl_FragColor = vec4(sin(1));"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Built-in functions can not be overloaded in ESSL 3.00.
+TEST_F(FragmentShaderValidationTest, ESSL300BuiltInFunctionOverload)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "int sin(int x)\n"
+        "{\n"
+        "    return int(sin(float(x)));\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "   my_FragColor = vec4(sin(1));"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Multiplying a 4x2 matrix with a 4x2 matrix should not work.
+TEST_F(FragmentShaderValidationTest, CompoundMultiplyMatrixIdenticalNonSquareDimensions)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "   mat4x2 foo;\n"
+        "   foo *= mat4x2(4.0);\n"
+        "   my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Multiplying a matrix with 2 columns and 4 rows with a 2x2 matrix should work.
+TEST_F(FragmentShaderValidationTest, CompoundMultiplyMatrixValidNonSquareDimensions)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "   mat2x4 foo;\n"
+        "   foo *= mat2x2(4.0);\n"
+        "   my_FragColor = vec4(0.0);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Covers a bug where we would set the incorrect result size on an out-of-bounds vector swizzle.
+TEST_F(FragmentShaderValidationTest, OutOfBoundsVectorSwizzle)
+{
+    const std::string &shaderString =
+        "void main() {\n"
+        "   vec2(0).qq;\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Covers a bug where strange preprocessor defines could trigger asserts.
+TEST_F(FragmentShaderValidationTest, DefineWithSemicolon)
+{
+    const std::string &shaderString =
+        "#define Def; highp\n"
+        "uniform Def vec2 a;\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Covers a bug in our parsing of malformed shift preprocessor expressions.
+TEST_F(FragmentShaderValidationTest, LineDirectiveUndefinedShift)
+{
+    const std::string &shaderString = "#line x << y";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Covers a bug in our parsing of malformed shift preprocessor expressions.
+TEST_F(FragmentShaderValidationTest, LineDirectiveNegativeShift)
+{
+    const std::string &shaderString = "#line x << -1";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// gl_MaxImageUnits is only available in ES 3.1 shaders.
+TEST_F(FragmentShaderValidationTest, MaxImageUnitsInES3Shader)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 myOutput;"
+        "void main() {\n"
+        "   float ff = float(gl_MaxImageUnits);\n"
+        "   myOutput = vec4(ff);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// struct += struct is an invalid operation.
+TEST_F(FragmentShaderValidationTest, StructCompoundAssignStruct)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 myOutput;\n"
+        "struct S { float foo; };\n"
+        "void main() {\n"
+        "   S a, b;\n"
+        "   a += b;\n"
+        "   myOutput = vec4(0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// struct == different struct is an invalid operation.
+TEST_F(FragmentShaderValidationTest, StructEqDifferentStruct)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 myOutput;\n"
+        "struct S { float foo; };\n"
+        "struct S2 { float foobar; };\n"
+        "void main() {\n"
+        "   S a;\n"
+        "   S2 b;\n"
+        "   a == b;\n"
+        "   myOutput = vec4(0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Compute shaders are not supported in versions lower than 310.
+TEST_F(ComputeShaderValidationTest, Version100)
+{
+    const std::string &shaderString =
+        "void main()\n"
+        "layout(local_size_x=1) in;\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Compute shaders are not supported in versions lower than 310.
+TEST_F(ComputeShaderValidationTest, Version300)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "void main()\n"
+        "layout(local_size_x=1) in;\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Compute shaders should have work group size specified. However, it is not a compile time error
+// to not have the size specified, but rather a link time one.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, NoWorkGroupSizeSpecified)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Work group size is less than 1. It should be at least 1.
+// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables
+// The spec is not clear whether having a local size qualifier equal zero
+// is correct.
+// TODO (mradev): Ask people from Khronos to clarify the spec.
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooSmallXdimension)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 0) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Work group size is correct for the x and y dimensions, but not for the z dimension.
+// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooSmallZDimension)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 4, local_size_y = 6, local_size_z = 0) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Work group size is bigger than the minimum in the x dimension.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooBigXDimension)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 9989899) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Work group size is bigger than the minimum in the y dimension.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooBigYDimension)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5, local_size_y = 9989899) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Work group size is definitely bigger than the minimum in the z dimension.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooBigZDimension)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5, local_size_y = 5, local_size_z = 9989899) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Work group size specified through macro expansion.
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeMacro)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "#define MYDEF(x) x"
+        "layout(local_size_x = MYDEF(127)) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Work group size specified as an unsigned integer.
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeUnsignedInteger)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 123u) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Work group size specified in hexadecimal.
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeHexadecimal)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 0x3A) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// local_size_x is -1 in hexadecimal format.
+// -1 is used as unspecified value in the TLayoutQualifier structure.
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeMinusOneHexadecimal)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 0xFFFFFFFF) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Work group size specified in octal.
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeOctal)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 013) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Work group size is negative. It is specified in hexadecimal.
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeNegativeHexadecimal)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 0xFFFFFFEC) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Multiple work group layout qualifiers with differing values.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, DifferingLayoutQualifiers)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5, local_size_x = 6) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Multiple work group input variables with differing local size values.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, MultipleInputVariablesDifferingLocalSize)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5, local_size_y = 6) in;\n"
+        "layout(local_size_x = 5, local_size_y = 7) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Multiple work group input variables with differing local size values.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, MultipleInputVariablesDifferingLocalSize2)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5) in;\n"
+        "layout(local_size_x = 5, local_size_y = 7) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Multiple work group input variables with the same local size values. It should compile.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, MultipleInputVariablesSameLocalSize)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5, local_size_y = 6) in;\n"
+        "layout(local_size_x = 5, local_size_y = 6) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Multiple work group input variables with the same local size values. It should compile.
+// Since the default value is 1, it should compile.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, MultipleInputVariablesSameLocalSize2)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5) in;\n"
+        "layout(local_size_x = 5, local_size_y = 1) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Multiple work group input variables with the same local size values. It should compile.
+// Since the default value is 1, it should compile.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, MultipleInputVariablesSameLocalSize3)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5, local_size_y = 1) in;\n"
+        "layout(local_size_x = 5) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Specifying row_major qualifier in a work group size layout.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, RowMajorInComputeInputLayout)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5, row_major) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// local size layout can be used only with compute input variables
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, UniformComputeInputLayout)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5) uniform;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// local size layout can be used only with compute input variables
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, UniformBufferComputeInputLayout)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5) uniform SomeBuffer { vec4 something; };\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// local size layout can be used only with compute input variables
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, StructComputeInputLayout)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5) struct SomeBuffer { vec4 something; };\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// local size layout can be used only with compute input variables
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, StructBodyComputeInputLayout)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "struct S {\n"
+        "   layout(local_size_x = 12) vec4 foo;\n"
+        "};\n"
+        "void main()"
+        "{"
+        "}";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// local size layout can be used only with compute input variables
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, TypeComputeInputLayout)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5) vec4;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid use of the out storage qualifier in a compute shader.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, InvalidOutStorageQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 15) in;\n"
+        "out vec4 myOutput;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid use of the out storage qualifier in a compute shader.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, InvalidOutStorageQualifier2)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 15) in;\n"
+        "out myOutput;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid use of the in storage qualifier. Can be only used to describe the local block size.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, InvalidInStorageQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 15) in;\n"
+        "in vec4 myInput;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid use of the in storage qualifier. Can be only used to describe the local block size.
+// The test checks a different part of the GLSL grammar than what InvalidInStorageQualifier checks.
+// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
+TEST_F(ComputeShaderValidationTest, InvalidInStorageQualifier2)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 15) in;\n"
+        "in myInput;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// The local_size layout qualifier is only available in compute shaders.
+TEST_F(VertexShaderValidationTest, InvalidUseOfLocalSizeX)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 15) in vec4 myInput;\n"
+        "out vec4 myOutput;\n"
+        "void main() {\n"
+        "   myOutput = myInput;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// The local_size layout qualifier is only available in compute shaders.
+TEST_F(FragmentShaderValidationTest, InvalidUseOfLocalSizeX)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 15) in vec4 myInput;\n"
+        "out vec4 myOutput;\n"
+        "void main() {\n"
+        "   myOutput = myInput;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is a compile time error to use the gl_WorkGroupSize constant if
+// the local size has not been declared yet.
+// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables
+TEST_F(ComputeShaderValidationTest, InvalidUsageOfWorkGroupSize)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "   uvec3 WorkGroupSize = gl_WorkGroupSize;\n"
+        "}\n"
+        "layout(local_size_x = 12) in;\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// The test covers the compute shader built-in variables and constants.
+TEST_F(ComputeShaderValidationTest, CorrectUsageOfComputeBuiltins)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 12) in;\n"
+        "void main()\n"
+        "{\n"
+        "   uvec3 NumWorkGroups = gl_NumWorkGroups;\n"
+        "   uvec3 WorkGroupSize = gl_WorkGroupSize;\n"
+        "   uvec3 WorkGroupID = gl_WorkGroupID;\n"
+        "   uvec3 GlobalInvocationID = gl_GlobalInvocationID;\n"
+        "   uvec3 LocalInvocationID = gl_LocalInvocationID;\n"
+        "   uint LocalInvocationIndex = gl_LocalInvocationIndex;\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// It is illegal to write to a special variable.
+TEST_F(ComputeShaderValidationTest, SpecialVariableNumWorkGroups)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 12) in;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_NumWorkGroups = uvec3(1); \n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is illegal to write to a special variable.
+TEST_F(ComputeShaderValidationTest, SpecialVariableWorkGroupID)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 12) in;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_WorkGroupID = uvec3(1); \n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is illegal to write to a special variable.
+TEST_F(ComputeShaderValidationTest, SpecialVariableLocalInvocationID)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 12) in;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_LocalInvocationID = uvec3(1); \n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is illegal to write to a special variable.
+TEST_F(ComputeShaderValidationTest, SpecialVariableGlobalInvocationID)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 12) in;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_GlobalInvocationID = uvec3(1); \n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is illegal to write to a special variable.
+TEST_F(ComputeShaderValidationTest, SpecialVariableLocalInvocationIndex)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 12) in;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_LocalInvocationIndex = 1; \n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is illegal to write to a special variable.
+TEST_F(ComputeShaderValidationTest, SpecialVariableWorkGroupSize)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 12) in;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_WorkGroupSize = uvec3(1); \n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is illegal to apply an unary operator to a sampler.
+TEST_F(FragmentShaderValidationTest, SamplerUnaryOperator)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform sampler2D s;\n"
+        "void main()\n"
+        "{\n"
+        "   -s;\n"
+        "   gl_FragColor = vec4(0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invariant cannot be used with a work group size declaration.
+TEST_F(ComputeShaderValidationTest, InvariantBlockSize)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "invariant layout(local_size_x = 15) in;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invariant cannot be used with a non-output variable in ESSL3.
+TEST_F(FragmentShaderValidationTest, InvariantNonOuput)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "invariant int value;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invariant cannot be used with a non-output variable in ESSL3.
+// ESSL 3.00.6 section 4.8: This applies even if the declaration is empty.
+TEST_F(FragmentShaderValidationTest, InvariantNonOuputEmptyDeclaration)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "invariant in float;\n"
+        "void main() {}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invariant declaration should follow the following format "invariant <out variable name>".
+// Test having an incorrect qualifier in the invariant declaration.
+TEST_F(FragmentShaderValidationTest, InvariantDeclarationWithStorageQualifier)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 foo;\n"
+        "invariant centroid foo;\n"
+        "void main() {\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invariant declaration should follow the following format "invariant <out variable name>".
+// Test having an incorrect precision qualifier in the invariant declaration.
+TEST_F(FragmentShaderValidationTest, InvariantDeclarationWithPrecisionQualifier)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 foo;\n"
+        "invariant highp foo;\n"
+        "void main() {\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invariant declaration should follow the following format "invariant <out variable name>".
+// Test having an incorrect layout qualifier in the invariant declaration.
+TEST_F(FragmentShaderValidationTest, InvariantDeclarationWithLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 foo;\n"
+        "invariant layout(location=0) foo;\n"
+        "void main() {\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Variable declaration with both invariant and layout qualifiers is not valid in the formal grammar
+// provided in the ESSL 3.00 spec. ESSL 3.10 starts allowing this combination, but ESSL 3.00 should
+// still disallow it.
+TEST_F(FragmentShaderValidationTest, VariableDeclarationWithInvariantAndLayoutQualifierESSL300)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "invariant layout(location = 0) out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Bit shift with a rhs value > 31 has an undefined result in the GLSL spec. Detecting an undefined
+// result at compile time should not generate an error either way.
+// ESSL 3.00.6 section 5.9.
+TEST_F(FragmentShaderValidationTest, ShiftBy32)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   uint u = 1u << 32u;\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        if (!hasWarning())
+        {
+            FAIL() << "Shader compilation succeeded without warnings, expecting warning:\n"
+                   << mInfoLog;
+        }
+    }
+    else
+    {
+        FAIL() << "Shader compilation failed, expecting success with warning:\n" << mInfoLog;
+    }
+}
+
+// Bit shift with a rhs value < 0 has an undefined result in the GLSL spec. Detecting an undefined
+// result at compile time should not generate an error either way.
+// ESSL 3.00.6 section 5.9.
+TEST_F(FragmentShaderValidationTest, ShiftByNegative)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "   uint u = 1u << (-1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        if (!hasWarning())
+        {
+            FAIL() << "Shader compilation succeeded without warnings, expecting warning:\n"
+                   << mInfoLog;
+        }
+    }
+    else
+    {
+        FAIL() << "Shader compilation failed, expecting success with warning:\n" << mInfoLog;
+    }
+}
+
+// Test that deferring global variable init works with an empty main().
+TEST_F(FragmentShaderValidationTest, DeferGlobalVariableInitWithEmptyMain)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u;\n"
+        "float foo = u;\n"
+        "void main() {}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that pruning empty declarations from loop init expression works.
+TEST_F(FragmentShaderValidationTest, EmptyDeclarationAsLoopInit)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    int i = 0;\n"
+        "    for (int; i < 3; i++)\n"
+        "    {\n"
+        "        my_FragColor = vec4(i);\n"
+        "    }\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+// r32f, r32i, r32ui do not require either the writeonly or readonly memory qualifiers.
+// GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, ImageR32FNoMemoryQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "in vec4 myInput;\n"
+        "layout(r32f) uniform image2D myImage;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Images which do not have r32f, r32i or r32ui as internal format, must have readonly or writeonly
+// specified.
+// GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, ImageRGBA32FWithIncorrectMemoryQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "in vec4 myInput;\n"
+        "layout(rgba32f) uniform image2D myImage;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is a compile-time error to call imageStore when the image is qualified as readonly.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, StoreInReadOnlyImage)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "in vec4 myInput;\n"
+        "layout(r32f) uniform readonly image2D myImage;\n"
+        "void main() {\n"
+        "   imageStore(myImage, ivec2(0), vec4(1.0));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is a compile-time error to call imageLoad when the image is qualified as writeonly.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, LoadFromWriteOnlyImage)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "in vec4 myInput;\n"
+        "layout(r32f) uniform writeonly image2D myImage;\n"
+        "void main() {\n"
+        "   imageLoad(myImage, ivec2(0));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is a compile-time error to call imageStore when the image is qualified as readonly.
+// Test to make sure this is validated correctly for images in arrays.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, StoreInReadOnlyImageArray)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "in vec4 myInput;\n"
+        "layout(r32f) uniform readonly image2D myImage[2];\n"
+        "void main() {\n"
+        "   imageStore(myImage[0], ivec2(0), vec4(1.0));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It is a compile-time error to call imageStore when the image is qualified as readonly.
+// Test to make sure that checking this doesn't crash when validating an image in a struct.
+// Image in a struct in itself isn't accepted by the parser, but error recovery still results in
+// an image in the struct.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, StoreInReadOnlyImageInStruct)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "in vec4 myInput;\n"
+        "uniform struct S {\n"
+        "    layout(r32f) readonly image2D myImage;\n"
+        "} s;\n"
+        "void main() {\n"
+        "   imageStore(s.myImage, ivec2(0), vec4(1.0));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// A valid declaration and usage of an image3D.
+TEST_F(FragmentShaderValidationTest, ValidImage3D)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image3D;\n"
+        "in vec4 myInput;\n"
+        "layout(rgba32f) uniform readonly image3D myImage;\n"
+        "void main() {\n"
+        "   imageLoad(myImage, ivec3(0));\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// A valid declaration and usage of an imageCube.
+TEST_F(FragmentShaderValidationTest, ValidImageCube)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump imageCube;\n"
+        "in vec4 myInput;\n"
+        "layout(rgba32f) uniform readonly imageCube myImage;\n"
+        "void main() {\n"
+        "   imageLoad(myImage, ivec3(0));\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// A valid declaration and usage of an image2DArray.
+TEST_F(FragmentShaderValidationTest, ValidImage2DArray)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2DArray;\n"
+        "in vec4 myInput;\n"
+        "layout(rgba32f) uniform readonly image2DArray myImage;\n"
+        "void main() {\n"
+        "   imageLoad(myImage, ivec3(0));\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Images cannot be l-values.
+// GLSL ES 3.10 Revision 4, 4.1.7 Opaque Types
+TEST_F(FragmentShaderValidationTest, ImageLValueFunctionDefinitionInOut)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "void myFunc(inout image2D someImage) {}\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Cannot assign to images.
+// GLSL ES 3.10 Revision 4, 4.1.7 Opaque Types
+TEST_F(FragmentShaderValidationTest, ImageAssignment)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(rgba32f) uniform readonly image2D myImage;\n"
+        "layout(rgba32f) uniform readonly image2D myImage2;\n"
+        "void main() {\n"
+        "   myImage = myImage2;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Passing an image qualifier to a function should not be able to discard the readonly qualifier.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, ReadOnlyQualifierMissingInFunctionArgument)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(rgba32f) uniform readonly image2D myImage;\n"
+        "void myFunc(in image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(myImage);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Passing an image qualifier to a function should not be able to discard the readonly qualifier.
+// Test with an image from an array.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, ReadOnlyQualifierMissingInFunctionArgumentArray)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(rgba32f) uniform readonly image2D myImage[2];\n"
+        "void myFunc(in image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(myImage[0]);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Passing an image qualifier to a function should not be able to discard the readonly qualifier.
+// Test that validation doesn't crash on this for an image in a struct.
+// Image in a struct in itself isn't accepted by the parser, but error recovery still results in
+// an image in the struct.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, ReadOnlyQualifierMissingInFunctionArgumentStruct)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "uniform struct S {\n"
+        "    layout(r32f) readonly image2D myImage;\n"
+        "} s;\n"
+        "void myFunc(in image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(s.myImage);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Passing an image qualifier to a function should not be able to discard the writeonly qualifier.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, WriteOnlyQualifierMissingInFunctionArgument)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(rgba32f) uniform writeonly image2D myImage;\n"
+        "void myFunc(in image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(myImage);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Passing an image parameter as an argument to another function should not be able to discard the
+// writeonly qualifier.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, DiscardWriteonlyInFunctionBody)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(rgba32f) uniform writeonly image2D myImage;\n"
+        "void myFunc1(in image2D someImage) {}\n"
+        "void myFunc2(in writeonly image2D someImage) { myFunc1(someImage); }\n"
+        "void main() {\n"
+        "   myFunc2(myImage);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// The memory qualifiers for the image declaration and function argument match and the test should
+// pass.
+TEST_F(FragmentShaderValidationTest, CorrectImageMemoryQualifierSpecified)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(r32f) uniform image2D myImage;\n"
+        "void myFunc(in image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(myImage);\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// The test adds additional qualifiers to the argument in the function header.
+// This is correct since no memory qualifiers are discarded upon the function call.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, CorrectImageMemoryQualifierSpecified2)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(r32f) uniform image2D myImage;\n"
+        "void myFunc(in readonly writeonly image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(myImage);\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Images are not allowed in structs.
+// GLSL ES 3.10 Revision 4, 4.1.8 Structures
+TEST_F(FragmentShaderValidationTest, ImageInStruct)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "struct myStruct { layout(r32f) image2D myImage; };\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Images are not allowed in interface blocks.
+// GLSL ES 3.10 Revision 4, 4.3.9 Interface Blocks
+TEST_F(FragmentShaderValidationTest, ImageInInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "uniform myBlock { layout(r32f) image2D myImage; };\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Readonly used with an interface block.
+TEST_F(FragmentShaderValidationTest, ReadonlyWithInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform readonly myBlock { float something; };\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Readonly used with an invariant.
+TEST_F(FragmentShaderValidationTest, ReadonlyWithInvariant)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "out vec4 something;\n"
+        "invariant readonly something;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Readonly used with a member of a structure.
+TEST_F(FragmentShaderValidationTest, ReadonlyWithStructMember)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "out vec4 something;\n"
+        "struct MyStruct { readonly float myMember; };\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It should not be possible to use an internal format layout qualifier with an interface block.
+TEST_F(FragmentShaderValidationTest, ImageInternalFormatWithInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "out vec4 something;\n"
+        "layout(rgba32f) uniform MyStruct { float myMember; };\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// It should not be possible to use an internal format layout qualifier with a uniform without a
+// type.
+TEST_F(FragmentShaderValidationTest, ImageInternalFormatInGlobalLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "out vec4 something;\n"
+        "layout(rgba32f) uniform;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// ESSL 1.00 section 4.1.7.
+// Samplers are not allowed as operands for most operations. Test this for ternary operator.
+TEST_F(FragmentShaderValidationTest, SamplerAsTernaryOperand)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform bool u;\n"
+        "uniform sampler2D s1;\n"
+        "uniform sampler2D s2;\n"
+        "void main() {\n"
+        "    gl_FragColor = texture2D(u ? s1 : s2, vec2(0, 0));\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// ESSL 1.00.17 section 4.5.2.
+// ESSL 3.00.6 section 4.5.3.
+// Precision must be specified for floats. Test this with a declaration with no qualifiers.
+TEST_F(FragmentShaderValidationTest, FloatDeclarationNoQualifiersNoPrecision)
+{
+    const std::string &shaderString =
+        "vec4 foo = vec4(0.0);\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = foo;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Check compiler doesn't crash on incorrect unsized array declarations.
+TEST_F(FragmentShaderValidationTest, IncorrectUnsizedArray)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "float foo[] = 0.0;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    foo[0] = 1.0;\n"
+        "    my_FragColor = vec4(foo[0]);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Check compiler doesn't crash when a bvec is on the right hand side of a logical operator.
+// ESSL 3.00.6 section 5.9.
+TEST_F(FragmentShaderValidationTest, LogicalOpRHSIsBVec)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "void main()\n"
+        "{\n"
+        "    bool b;\n"
+        "    bvec3 b3;\n"
+        "    b && b3;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Check compiler doesn't crash when there's an unsized array constructor with no parameters.
+// ESSL 3.00.6 section 4.1.9: Array size must be greater than zero.
+TEST_F(FragmentShaderValidationTest, UnsizedArrayConstructorNoParameters)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "void main()\n"
+        "{\n"
+        "    int[]();\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Passing an image parameter as an argument to another function should not be able to discard the
+// coherent qualifier.
+TEST_F(FragmentShaderValidationTest, CoherentQualifierMissingInFunctionArgument)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(r32f) uniform coherent image2D myImage;\n"
+        "void myFunc(in image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(myImage);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Passing an image parameter as an argument to another function should not be able to discard the
+// volatile qualifier.
+TEST_F(FragmentShaderValidationTest, VolatileQualifierMissingInFunctionArgument)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(r32f) uniform volatile image2D myImage;\n"
+        "void myFunc(in image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(myImage);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// The restrict qualifier can be discarded from a function argument.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, RestrictQualifierDiscardedInFunctionArgument)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(r32f) uniform restrict image2D myImage;\n"
+        "void myFunc(in image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(myImage);\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Function image arguments can be overqualified.
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+TEST_F(FragmentShaderValidationTest, OverqualifyingImageParameter)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(r32f) uniform image2D myImage;\n"
+        "void myFunc(in coherent volatile image2D someImage) {}\n"
+        "void main() {\n"
+        "   myFunc(myImage);\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that work group size can be used to size arrays.
+// GLSL ES 3.10.4 section 7.1.3 Compute Shader Special Variables
+TEST_F(ComputeShaderValidationTest, WorkGroupSizeAsArraySize)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5, local_size_y = 3, local_size_z = 1) in;\n"
+        "void main()\n"
+        "{\n"
+        "    int[gl_WorkGroupSize.x] a = int[5](0, 0, 0, 0, 0);\n"
+        "    int[gl_WorkGroupSize.y] b = int[3](0, 0, 0);\n"
+        "    int[gl_WorkGroupSize.z] c = int[1](0);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Shared memory variables cannot be used inside a vertex shader.
+// GLSL ES 3.10 Revision 4, 4.3.8 Shared Variables
+TEST_F(VertexShaderValidationTest, VertexShaderSharedMemory)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "in vec4 i;\n"
+        "shared float myShared[10];\n"
+        "void main() {\n"
+        "    gl_Position = i;\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Shared memory variables cannot be used inside a fragment shader.
+// GLSL ES 3.10 Revision 4, 4.3.8 Shared Variables
+TEST_F(FragmentShaderValidationTest, FragmentShaderSharedMemory)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "shared float myShared[10];\n"
+        "out vec4 color;\n"
+        "void main() {\n"
+        "   color = vec4(1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Shared memory cannot be combined with any other storage qualifier.
+TEST_F(ComputeShaderValidationTest, UniformSharedMemory)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 5) in;\n"
+        "uniform shared float myShared[100];\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Correct usage of shared memory variables.
+TEST_F(ComputeShaderValidationTest, CorrectUsageOfSharedMemory)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 5) in;\n"
+        "shared float myShared[100];\n"
+        "void main() {\n"
+        "   myShared[gl_LocalInvocationID.x] = 1.0;\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Shared memory variables cannot be initialized.
+// GLSL ES 3.10 Revision 4, 4.3.8 Shared Variables
+TEST_F(ComputeShaderValidationTest, SharedVariableInitialization)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 5) in;\n"
+        "shared int myShared = 0;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Local variables cannot be qualified as shared.
+// GLSL ES 3.10 Revision 4, 4.3 Storage Qualifiers
+TEST_F(ComputeShaderValidationTest, SharedMemoryInFunctionBody)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 5) in;\n"
+        "void func() {\n"
+        "   shared int myShared;\n"
+        "}\n"
+        "void main() {\n"
+        "   func();\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Struct members cannot be qualified as shared.
+TEST_F(ComputeShaderValidationTest, SharedMemoryInStruct)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 5) in;\n"
+        "struct MyStruct {\n"
+        "   shared int myShared;\n"
+        "};\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Interface block members cannot be qualified as shared.
+TEST_F(ComputeShaderValidationTest, SharedMemoryInInterfaceBlock)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 5) in;\n"
+        "uniform Myblock {\n"
+        "   shared int myShared;\n"
+        "};\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// The shared qualifier cannot be used with any other qualifier.
+TEST_F(ComputeShaderValidationTest, SharedWithInvariant)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 5) in;\n"
+        "invariant shared int myShared;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// The shared qualifier cannot be used with any other qualifier.
+TEST_F(ComputeShaderValidationTest, SharedWithMemoryQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 5) in;\n"
+        "readonly shared int myShared;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// The shared qualifier cannot be used with any other qualifier.
+TEST_F(ComputeShaderValidationTest, SharedGlobalLayoutDeclaration)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 5) in;\n"
+        "layout(row_major) shared mat4;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Declaring a function with the same name as a built-in from a higher ESSL version should not cause
+// a redeclaration error.
+TEST_F(FragmentShaderValidationTest, BuiltinESSL31FunctionDeclaredInESSL30Shader)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "void imageSize() {}\n"
+        "void main() {\n"
+        "   imageSize();\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Attempting to declare num_views without enabling OVR_multiview.
+TEST_F(VertexShaderValidationTest, InvalidNumViews)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout (num_views = 2) in;\n"
+        "void main() {\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// memoryBarrierShared is only available in a compute shader.
+// GLSL ES 3.10 Revision 4, 8.15 Shader Memory Control Functions
+TEST_F(FragmentShaderValidationTest, InvalidUseOfMemoryBarrierShared)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "    memoryBarrierShared();\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// groupMemoryBarrier is only available in a compute shader.
+// GLSL ES 3.10 Revision 4, 8.15 Shader Memory Control Functions
+TEST_F(FragmentShaderValidationTest, InvalidUseOfGroupMemoryBarrier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "void main() {\n"
+        "    groupMemoryBarrier();\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// barrier can be used in a compute shader.
+// GLSL ES 3.10 Revision 4, 8.14 Shader Invocation Control Functions
+TEST_F(ComputeShaderValidationTest, ValidUseOfBarrier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 15) in;\n"
+        "void main() {\n"
+        "   barrier();\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
+    }
+}
+
+// memoryBarrierImage() can be used in all GLSL ES 3.10 shaders.
+// GLSL ES 3.10 Revision 4, 8.15 Shader Memory Control Functions
+TEST_F(FragmentShaderValidationTest, ValidUseOfMemoryBarrierImageInFragmentShader)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision highp image2D;\n"
+        "layout(r32f) uniform image2D myImage;\n"
+        "void main() {\n"
+        "    imageStore(myImage, ivec2(0), vec4(1.0));\n"
+        "    memoryBarrierImage();\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
+    }
+}
+
+// checks that gsampler2DMS is not supported in version lower than 310
+TEST_F(FragmentShaderValidationTest, Sampler2DMSInESSL300Shader)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "uniform highp sampler2DMS s;\n"
+        "void main() {}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Declare main() with incorrect parameters.
+// ESSL 3.00.6 section 6.1 Function Definitions.
+TEST_F(FragmentShaderValidationTest, InvalidMainPrototypeParameters)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "void main(int a);\n"
+        "void main() {}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Regression test for a crash in the empty constructor of unsized array
+// of a structure with non-basic fields fields. Test with "void".
+TEST_F(FragmentShaderValidationTest, VoidFieldStructUnsizedArrayEmptyConstructor)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "struct S {void a;};"
+        "void main() {S s[] = S[]();}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Regression test for a crash in the empty constructor of unsized array
+// of a structure with non-basic fields fields. Test with something other than "void".
+TEST_F(FragmentShaderValidationTest, SamplerFieldStructUnsizedArrayEmptyConstructor)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "struct S {sampler2D a;};"
+        "void main() {S s[] = S[]();}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Checks that odd array initialization syntax is an error, and does not produce
+// an ASSERT failure.
+TEST_F(VertexShaderValidationTest, InvalidArrayConstruction)
+{
+    const std::string &shaderString =
+        "struct S { mediump float i; mediump int ggb; };\n"
+        "void main() {\n"
+        "  S s[2];\n"
+        "  s = S[](s.x, 0.0);\n"
+        "  gl_Position = vec4(1, 0, 0, 1);\n"
+        "}";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Correct usage of image binding layout qualifier.
+TEST_F(ComputeShaderValidationTest, CorrectImageBindingLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "precision mediump image2D;\n"
+        "layout(local_size_x = 5) in;\n"
+        "layout(binding = 1, rgba32f) writeonly uniform image2D myImage;\n"
+        "void main()\n"
+        "{\n"
+        "   imageStore(myImage, ivec2(gl_LocalInvocationID.xy), vec4(1.0));\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
+    }
+}
+
+// Incorrect use of "binding" on a global layout qualifier.
+TEST_F(ComputeShaderValidationTest, IncorrectGlobalBindingLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x = 5, binding = 0) in;\n"
+        "void main() {}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Incorrect use of "binding" on a struct field layout qualifier.
+TEST_F(ComputeShaderValidationTest, IncorrectStructFieldBindingLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(local_size_x = 1) in;\n"
+        "struct S\n"
+        "{\n"
+        "  layout(binding = 0) float f;\n"
+        "};\n"
+        "void main() {}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Variable binding layout qualifier is set to a negative value. 0xffffffff wraps around to -1
+// according to the integer parsing rules.
+TEST_F(FragmentShaderValidationTest, ImageBindingUnitNegative)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(rgba32f, binding = 0xffffffff) writeonly uniform mediump image2D myImage;\n"
+        "out vec4 outFrag;\n"
+        "void main()\n"
+        "{\n"
+        "   outFrag = vec4(0.0);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Image binding layout qualifier value is greater than the maximum image binding.
+TEST_F(FragmentShaderValidationTest, ImageBindingUnitTooBig)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(rgba32f, binding = 9999) writeonly uniform mediump image2D myImage;\n"
+        "out vec4 outFrag;\n"
+        "void main()\n"
+        "{\n"
+        "   outFrag = vec4(0.0);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Uniform variable binding is set on a non-opaque type.
+TEST_F(FragmentShaderValidationTest, NonOpaqueUniformBinding)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(binding = 0) uniform float myFloat;\n"
+        "out vec4 outFrag;\n"
+        "void main()\n"
+        "{\n"
+        "   outFrag = vec4(myFloat);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Uniform variable binding is set on a sampler type.
+// ESSL 3.10 section 4.4.5 Opaque Uniform Layout Qualifiers.
+TEST_F(FragmentShaderValidationTest, SamplerUniformBinding)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "layout(binding = 0) uniform mediump sampler2D mySampler;\n"
+        "out vec4 outFrag;\n"
+        "void main()\n"
+        "{\n"
+        "   outFrag = vec4(0.0);\n"
+        "}\n";
+
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
+    }
+}
+
+// Uniform variable binding is set on a sampler type in an ESSL 3.00 shader.
+// The binding layout qualifier was added in ESSL 3.10, so this is incorrect.
+TEST_F(FragmentShaderValidationTest, SamplerUniformBindingESSL300)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(binding = 0) uniform mediump sampler2D mySampler;\n"
+        "out vec4 outFrag;\n"
+        "void main()\n"
+        "{\n"
+        "   outFrag = vec4(0.0);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Attempting to construct a struct containing a void array should fail without asserting.
+TEST_F(FragmentShaderValidationTest, ConstructStructContainingVoidArray)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 outFrag;\n"
+        "struct S\n"
+        "{\n"
+        "    void A[1];\n"
+        "} s = S();\n"
+        "void main()\n"
+        "{\n"
+        "    outFrag = vec4(0.0);\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// Uniforms can't have location in ESSL 3.00.
+// Test this with an empty declaration (ESSL 3.00.6 section 4.8: The combinations of qualifiers that
+// cause compile-time or link-time errors are the same whether or not the declaration is empty).
+TEST_F(FragmentShaderValidationTest, UniformLocationEmptyDeclaration)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "layout(location=0) uniform float;\n"
+        "void main() {}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test function parameters of opaque type can't be l-value too.
+TEST_F(FragmentShaderValidationTest, OpaqueParameterCanNotBeLValue)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "uniform sampler2D s;\n"
+        "void foo(sampler2D as) {\n"
+        "    as = s;\n"
+        "}\n"
+        "void main() {}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test samplers must not be operands in expressions, except for array indexing, structure field
+// selection and parentheses(ESSL 3.00 Secion 4.1.7).
+TEST_F(FragmentShaderValidationTest, InvalidExpressionForSamplerOperands)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "uniform sampler2D s;\n"
+        "uniform sampler2D s2;\n"
+        "void main() {\n"
+        "    s + s2;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test interface blocks as invalid operands to a binary expression.
+TEST_F(FragmentShaderValidationTest, InvalidInterfaceBlockBinaryExpression)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "uniform U\n"
+        "{\n"
+        "    int foo; \n"
+        "} u;\n"
+        "void main()\n"
+        "{\n"
+        "    u + u;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test interface block as an invalid operand to an unary expression.
+TEST_F(FragmentShaderValidationTest, InvalidInterfaceBlockUnaryExpression)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "uniform U\n"
+        "{\n"
+        "    int foo; \n"
+        "} u;\n"
+        "void main()\n"
+        "{\n"
+        "    +u;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test interface block as an invalid operand to a ternary expression.
+// Note that the spec is not very explicit on this, but it makes sense to forbid this.
+TEST_F(FragmentShaderValidationTest, InvalidInterfaceBlockTernaryExpression)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "uniform U\n"
+        "{\n"
+        "    int foo; \n"
+        "} u;\n"
+        "void main()\n"
+        "{\n"
+        "    true ? u : u;\n"
+        "}\n";
+
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/ShaderVariable_test.cpp b/src/third_party/angle/src/tests/compiler_tests/ShaderVariable_test.cpp
new file mode 100644
index 0000000..53dd93f
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/ShaderVariable_test.cpp
@@ -0,0 +1,421 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CollectVariables_test.cpp:
+//   Some tests for shader inspection
+//
+
+#include "angle_gl.h"
+#include "compiler/translator/Compiler.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+
+TEST(ShaderVariableTest, FindInfoByMappedName)
+{
+    // struct A {
+    //   float x[2];
+    //   vec3 y;
+    // };
+    // struct B {
+    //   A a[3];
+    // };
+    // B uni[2];
+    ShaderVariable uni;
+    uni.arraySize = 2;
+    uni.name = "uni";
+    uni.mappedName = "m_uni";
+    uni.structName = "B";
+    {
+        ShaderVariable a;
+        a.arraySize = 3;
+        a.name = "a";
+        a.mappedName = "m_a";
+        a.structName = "A";
+        {
+            ShaderVariable x(GL_FLOAT, 2);
+            x.name = "x";
+            x.mappedName = "m_x";
+            a.fields.push_back(x);
+
+            ShaderVariable y(GL_FLOAT_VEC3, 0);
+            y.name = "y";
+            y.mappedName = "m_y";
+            a.fields.push_back(y);
+        }
+        uni.fields.push_back(a);
+    }
+
+    const ShaderVariable *leafVar = nullptr;
+    std::string originalFullName;
+
+    std::string mappedFullName = "wrongName";
+    EXPECT_FALSE(uni.findInfoByMappedName(
+        mappedFullName, &leafVar, &originalFullName));
+
+    mappedFullName = "m_uni";
+    EXPECT_TRUE(uni.findInfoByMappedName(
+        mappedFullName, &leafVar, &originalFullName));
+    EXPECT_EQ(&uni, leafVar);
+    EXPECT_STREQ("uni", originalFullName.c_str());
+
+    mappedFullName = "m_uni[0].m_a[1].wrongName";
+    EXPECT_FALSE(uni.findInfoByMappedName(
+        mappedFullName, &leafVar, &originalFullName));
+
+    mappedFullName = "m_uni[0].m_a[1].m_x";
+    EXPECT_TRUE(uni.findInfoByMappedName(
+        mappedFullName, &leafVar, &originalFullName));
+    EXPECT_EQ(&(uni.fields[0].fields[0]), leafVar);
+    EXPECT_STREQ("uni[0].a[1].x", originalFullName.c_str());
+
+    mappedFullName = "m_uni[0].m_a[1].m_x[0]";
+    EXPECT_TRUE(uni.findInfoByMappedName(
+        mappedFullName, &leafVar, &originalFullName));
+    EXPECT_EQ(&(uni.fields[0].fields[0]), leafVar);
+    EXPECT_STREQ("uni[0].a[1].x[0]", originalFullName.c_str());
+
+    mappedFullName = "m_uni[0].m_a[1].m_y";
+    EXPECT_TRUE(uni.findInfoByMappedName(
+        mappedFullName, &leafVar, &originalFullName));
+    EXPECT_EQ(&(uni.fields[0].fields[1]), leafVar);
+    EXPECT_STREQ("uni[0].a[1].y", originalFullName.c_str());
+}
+
+TEST(ShaderVariableTest, IsSameUniformWithDifferentFieldOrder)
+{
+    // struct A {
+    //   float x;
+    //   float y;
+    // };
+    // uniform A uni;
+    Uniform vx_a;
+    vx_a.arraySize = 0;
+    vx_a.name = "uni";
+    vx_a.mappedName = "m_uni";
+    vx_a.structName = "A";
+    {
+        ShaderVariable x(GL_FLOAT, 0);
+        x.name = "x";
+        x.mappedName = "m_x";
+        vx_a.fields.push_back(x);
+
+        ShaderVariable y(GL_FLOAT, 0);
+        y.name = "y";
+        y.mappedName = "m_y";
+        vx_a.fields.push_back(y);
+    }
+
+    // struct A {
+    //   float y;
+    //   float x;
+    // };
+    // uniform A uni;
+    Uniform fx_a;
+    fx_a.arraySize = 0;
+    fx_a.name = "uni";
+    fx_a.mappedName = "m_uni";
+    fx_a.structName = "A";
+    {
+        ShaderVariable y(GL_FLOAT, 0);
+        y.name = "y";
+        y.mappedName = "m_y";
+        fx_a.fields.push_back(y);
+
+        ShaderVariable x(GL_FLOAT, 0);
+        x.name = "x";
+        x.mappedName = "m_x";
+        fx_a.fields.push_back(x);
+    }
+
+    EXPECT_FALSE(vx_a.isSameUniformAtLinkTime(fx_a));
+}
+
+TEST(ShaderVariableTest, IsSameUniformWithDifferentStructNames)
+{
+    // struct A {
+    //   float x;
+    //   float y;
+    // };
+    // uniform A uni;
+    Uniform vx_a;
+    vx_a.arraySize = 0;
+    vx_a.name = "uni";
+    vx_a.mappedName = "m_uni";
+    vx_a.structName = "A";
+    {
+        ShaderVariable x(GL_FLOAT, 0);
+        x.name = "x";
+        x.mappedName = "m_x";
+        vx_a.fields.push_back(x);
+
+        ShaderVariable y(GL_FLOAT, 0);
+        y.name = "y";
+        y.mappedName = "m_y";
+        vx_a.fields.push_back(y);
+    }
+
+    // struct B {
+    //   float x;
+    //   float y;
+    // };
+    // uniform B uni;
+    Uniform fx_a;
+    fx_a.arraySize = 0;
+    fx_a.name = "uni";
+    fx_a.mappedName = "m_uni";
+    {
+        ShaderVariable x(GL_FLOAT, 0);
+        x.name = "x";
+        x.mappedName = "m_x";
+        fx_a.fields.push_back(x);
+
+        ShaderVariable y(GL_FLOAT, 0);
+        y.name = "y";
+        y.mappedName = "m_y";
+        fx_a.fields.push_back(y);
+    }
+
+    fx_a.structName = "B";
+    EXPECT_FALSE(vx_a.isSameUniformAtLinkTime(fx_a));
+
+    fx_a.structName = "A";
+    EXPECT_TRUE(vx_a.isSameUniformAtLinkTime(fx_a));
+
+    fx_a.structName = "";
+    EXPECT_FALSE(vx_a.isSameUniformAtLinkTime(fx_a));
+}
+
+TEST(ShaderVariableTest, IsSameVaryingWithDifferentInvariance)
+{
+    // invariant varying float vary;
+    Varying vx;
+    vx.type = GL_FLOAT;
+    vx.arraySize = 0;
+    vx.precision = GL_MEDIUM_FLOAT;
+    vx.name = "vary";
+    vx.mappedName = "m_vary";
+    vx.staticUse = true;
+    vx.isInvariant = true;
+
+    // varying float vary;
+    Varying fx;
+    fx.type = GL_FLOAT;
+    fx.arraySize = 0;
+    fx.precision = GL_MEDIUM_FLOAT;
+    fx.name = "vary";
+    fx.mappedName = "m_vary";
+    fx.staticUse = true;
+    fx.isInvariant = false;
+
+    // Default to ESSL1 behavior: invariance must match
+    EXPECT_FALSE(vx.isSameVaryingAtLinkTime(fx));
+    EXPECT_FALSE(vx.isSameVaryingAtLinkTime(fx, 100));
+    // ESSL3 behavior: invariance doesn't need to match
+    EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx, 300));
+
+    // invariant varying float vary;
+    fx.isInvariant = true;
+    EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx));
+    EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx, 100));
+    EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx, 300));
+}
+
+// Test that using invariant varyings doesn't trigger a double delete.
+TEST(ShaderVariableTest, InvariantDoubleDeleteBug)
+{
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+
+    ShHandle compiler = sh::ConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC,
+                                              SH_GLSL_COMPATIBILITY_OUTPUT, &resources);
+    EXPECT_NE(static_cast<ShHandle>(0), compiler);
+
+    const char *program[] =
+    {
+        "attribute vec4 position;\n"
+        "varying float v;\n"
+        "invariant v;\n"
+        "void main() {\n"
+        "  v = 1.0;\n"
+        "  gl_Position = position;\n"
+        "}"
+    };
+
+    EXPECT_TRUE(sh::Compile(compiler, program, 1, SH_OBJECT_CODE));
+    EXPECT_TRUE(sh::Compile(compiler, program, 1, SH_OBJECT_CODE));
+    sh::Destruct(compiler);
+}
+
+TEST(ShaderVariableTest, IllegalInvariantVarying)
+{
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+
+    ShHandle compiler = sh::ConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC,
+                                              SH_GLSL_COMPATIBILITY_OUTPUT, &resources);
+    EXPECT_NE(static_cast<ShHandle>(0), compiler);
+
+    const char *program1[] =
+    {
+        "void foo() {\n"
+        "  vec4 v;\n"
+        "}\n"
+        "varying vec4 v_varying;\n"
+        "invariant v_varying;\n"
+        "void main() {\n"
+        "  foo();\n"
+        "  gl_Position = v_varying;\n"
+        "}"
+    };
+    const char *program2[] =
+    {
+        "varying vec4 v_varying;\n"
+        "void foo() {\n"
+        "  invariant v_varying;\n"
+        "}\n"
+        "void main() {\n"
+        "  foo();\n"
+        "  gl_Position = v_varying;\n"
+        "}"
+    };
+
+    EXPECT_TRUE(sh::Compile(compiler, program1, 1, SH_VARIABLES));
+    EXPECT_FALSE(sh::Compile(compiler, program2, 1, SH_VARIABLES));
+}
+
+TEST(ShaderVariableTest, InvariantLeakAcrossShaders)
+{
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+
+    ShHandle compiler = sh::ConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC,
+                                              SH_GLSL_COMPATIBILITY_OUTPUT, &resources);
+    EXPECT_NE(static_cast<ShHandle>(0), compiler);
+
+    const char *program1[] =
+    {
+        "varying vec4 v_varying;\n"
+        "invariant v_varying;\n"
+        "void main() {\n"
+        "  gl_Position = v_varying;\n"
+        "}"
+    };
+    const char *program2[] =
+    {
+        "varying vec4 v_varying;\n"
+        "void main() {\n"
+        "  gl_Position = v_varying;\n"
+        "}"
+    };
+
+    EXPECT_TRUE(sh::Compile(compiler, program1, 1, SH_VARIABLES));
+    const std::vector<sh::Varying> *varyings = sh::GetVaryings(compiler);
+    for (const sh::Varying &varying : *varyings)
+    {
+        if (varying.name == "v_varying")
+            EXPECT_TRUE(varying.isInvariant);
+    }
+    EXPECT_TRUE(sh::Compile(compiler, program2, 1, SH_VARIABLES));
+    varyings = sh::GetVaryings(compiler);
+    for (const sh::Varying &varying : *varyings)
+    {
+        if (varying.name == "v_varying")
+            EXPECT_FALSE(varying.isInvariant);
+    }
+}
+
+TEST(ShaderVariableTest, GlobalInvariantLeakAcrossShaders)
+{
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+
+    ShHandle compiler = sh::ConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC,
+                                              SH_GLSL_COMPATIBILITY_OUTPUT, &resources);
+    EXPECT_NE(static_cast<ShHandle>(0), compiler);
+
+    const char *program1[] =
+    {
+        "#pragma STDGL invariant(all)\n"
+        "varying vec4 v_varying;\n"
+        "void main() {\n"
+        "  gl_Position = v_varying;\n"
+        "}"
+    };
+    const char *program2[] =
+    {
+        "varying vec4 v_varying;\n"
+        "void main() {\n"
+        "  gl_Position = v_varying;\n"
+        "}"
+    };
+
+    EXPECT_TRUE(sh::Compile(compiler, program1, 1, SH_VARIABLES));
+    const std::vector<sh::Varying> *varyings = sh::GetVaryings(compiler);
+    for (const sh::Varying &varying : *varyings)
+    {
+        if (varying.name == "v_varying")
+            EXPECT_TRUE(varying.isInvariant);
+    }
+    EXPECT_TRUE(sh::Compile(compiler, program2, 1, SH_VARIABLES));
+    varyings = sh::GetVaryings(compiler);
+    for (const sh::Varying &varying : *varyings)
+    {
+        if (varying.name == "v_varying")
+            EXPECT_FALSE(varying.isInvariant);
+    }
+}
+
+TEST(ShaderVariableTest, BuiltinInvariantVarying)
+{
+
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+
+    ShHandle compiler = sh::ConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC,
+                                              SH_GLSL_COMPATIBILITY_OUTPUT, &resources);
+    EXPECT_NE(static_cast<ShHandle>(0), compiler);
+
+    const char *program1[] =
+    {
+        "invariant gl_Position;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(0, 0, 0, 0);\n"
+        "}"
+    };
+    const char *program2[] =
+    {
+        "void main() {\n"
+        "  gl_Position = vec4(0, 0, 0, 0);\n"
+        "}"
+    };
+    const char *program3[] =
+    {
+        "void main() {\n"
+        "  invariant gl_Position;\n"
+        "  gl_Position = vec4(0, 0, 0, 0);\n"
+        "}"
+    };
+
+    EXPECT_TRUE(sh::Compile(compiler, program1, 1, SH_VARIABLES));
+    const std::vector<sh::Varying> *varyings = sh::GetVaryings(compiler);
+    for (const sh::Varying &varying : *varyings)
+    {
+        if (varying.name == "gl_Position")
+            EXPECT_TRUE(varying.isInvariant);
+    }
+    EXPECT_TRUE(sh::Compile(compiler, program2, 1, SH_VARIABLES));
+    varyings = sh::GetVaryings(compiler);
+    for (const sh::Varying &varying : *varyings)
+    {
+        if (varying.name == "gl_Position")
+            EXPECT_FALSE(varying.isInvariant);
+    }
+    EXPECT_FALSE(sh::Compile(compiler, program3, 1, SH_VARIABLES));
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/tests/compiler_tests/TypeTracking_test.cpp b/src/third_party/angle/src/tests/compiler_tests/TypeTracking_test.cpp
new file mode 100644
index 0000000..8e3f95f
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/TypeTracking_test.cpp
@@ -0,0 +1,645 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TypeTracking_test.cpp:
+//   Test for tracking types resulting from math operations, including their
+//   precision.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/TranslatorESSL.h"
+
+using namespace sh;
+
+class TypeTrackingTest : public testing::Test
+{
+  public:
+    TypeTrackingTest() {}
+
+  protected:
+    void SetUp() override
+    {
+        ShBuiltInResources resources;
+        InitBuiltInResources(&resources);
+        resources.FragmentPrecisionHigh = 1;
+
+        mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_GLES3_1_SPEC);
+        ASSERT_TRUE(mTranslator->Init(resources));
+    }
+
+    void TearDown() override { delete mTranslator; }
+
+    void compile(const std::string& shaderString)
+    {
+        const char *shaderStrings[] = { shaderString.c_str() };
+        bool compilationSuccess = mTranslator->compile(shaderStrings, 1, SH_INTERMEDIATE_TREE);
+        TInfoSink &infoSink = mTranslator->getInfoSink();
+        mInfoLog                    = RemoveSymbolIdsFromInfoLog(infoSink.info.c_str());
+        if (!compilationSuccess)
+            FAIL() << "Shader compilation failed " << mInfoLog;
+    }
+
+    bool foundErrorInIntermediateTree() const
+    {
+        return foundInIntermediateTree("ERROR:");
+    }
+
+    bool foundInIntermediateTree(const char* stringToFind) const
+    {
+        return mInfoLog.find(stringToFind) != std::string::npos;
+    }
+
+  private:
+    // Remove symbol ids from info log - the tests don't care about them.
+    static std::string RemoveSymbolIdsFromInfoLog(const char *infoLog)
+    {
+        std::string filteredLog(infoLog);
+        size_t idPrefixPos = 0u;
+        do
+        {
+            idPrefixPos = filteredLog.find(" (symbol id");
+            if (idPrefixPos != std::string::npos)
+            {
+                size_t idSuffixPos = filteredLog.find(")", idPrefixPos);
+                filteredLog.erase(idPrefixPos, idSuffixPos - idPrefixPos + 1u);
+            }
+        } while (idPrefixPos != std::string::npos);
+        return filteredLog;
+    }
+
+    TranslatorESSL *mTranslator;
+    std::string mInfoLog;
+};
+
+TEST_F(TypeTrackingTest, FunctionPrototype)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "float fun(float a);\n"
+        "uniform float f;\n"
+        "void main() {\n"
+        "   float ff = fun(f);\n"
+        "   gl_FragColor = vec4(ff);\n"
+        "}\n"
+        "float fun(float a) {\n"
+        "   return a * 2.0;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("Function Prototype: fun"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInFunctionResultPrecision)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float f;\n"
+        "void main() {\n"
+        "   float ff = sin(f);\n"
+        "   gl_FragColor = vec4(ff);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("sin (mediump float)"));
+}
+
+TEST_F(TypeTrackingTest, BinaryMathResultPrecision)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float f;\n"
+        "void main() {\n"
+        "   float ff = f * 0.5;\n"
+        "   gl_FragColor = vec4(ff);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("multiply (mediump float)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInVecFunctionResultTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec2 a;\n"
+        "void main() {\n"
+        "   float b = length(a);\n"
+        "   float c = dot(a, vec2(0.5));\n"
+        "   float d = distance(vec2(0.5), a);\n"
+        "   gl_FragColor = vec4(b, c, d, 1.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("length (mediump float)"));
+    ASSERT_TRUE(foundInIntermediateTree("dot product (mediump float)"));
+    ASSERT_TRUE(foundInIntermediateTree("distance (mediump float)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInMatFunctionResultTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform mat4 m;\n"
+        "void main() {\n"
+        "   mat3x2 tmp32 = mat3x2(m);\n"
+        "   mat2x3 tmp23 = mat2x3(m);\n"
+        "   mat4x2 tmp42 = mat4x2(m);\n"
+        "   mat2x4 tmp24 = mat2x4(m);\n"
+        "   mat4x3 tmp43 = mat4x3(m);\n"
+        "   mat3x4 tmp34 = mat3x4(m);\n"
+        "   my_FragColor = vec4(tmp32[2][1] * tmp23[1][2], tmp42[3][1] * tmp24[1][3], tmp43[3][2] * tmp34[2][3], 1.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 2X3 matrix of float)"));
+    ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 3X2 matrix of float)"));
+    ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 2X4 matrix of float)"));
+    ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 4X2 matrix of float)"));
+    ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 3X4 matrix of float)"));
+    ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 4X3 matrix of float)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInFunctionChoosesHigherPrecision)
+{
+    const std::string &shaderString =
+        "precision lowp float;\n"
+        "uniform mediump vec2 a;\n"
+        "uniform lowp vec2 b;\n"
+        "void main() {\n"
+        "   float c = dot(a, b);\n"
+        "   float d = distance(b, a);\n"
+        "   gl_FragColor = vec4(c, d, 0.0, 1.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("dot product (mediump float)"));
+    ASSERT_TRUE(foundInIntermediateTree("distance (mediump float)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInBoolFunctionResultType)
+{
+    const std::string &shaderString =
+        "uniform bvec4 bees;\n"
+        "void main() {\n"
+        "   bool b = any(bees);\n"
+        "   bool c = all(bees);\n"
+        "   bvec4 d = not(bees);\n"
+        "   gl_FragColor = vec4(b ? 1.0 : 0.0, c ? 1.0 : 0.0, d.x ? 1.0 : 0.0, 1.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("any (bool)"));
+    ASSERT_TRUE(foundInIntermediateTree("all (bool)"));
+    ASSERT_TRUE(foundInIntermediateTree("component-wise not (4-component vector of bool)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInVecToBoolFunctionResultType)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec2 apples;\n"
+        "uniform vec2 oranges;\n"
+        "uniform ivec2 foo;\n"
+        "uniform ivec2 bar;\n"
+        "void main() {\n"
+        "   bvec2 a = lessThan(apples, oranges);\n"
+        "   bvec2 b = greaterThan(foo, bar);\n"
+        "   gl_FragColor = vec4(any(a) ? 1.0 : 0.0, any(b) ? 1.0 : 0.0, 0.0, 1.0);\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("component-wise less than (2-component vector of bool)"));
+    ASSERT_TRUE(
+        foundInIntermediateTree("component-wise greater than (2-component vector of bool)"));
+}
+
+TEST_F(TypeTrackingTest, Texture2DResultTypeAndPrecision)
+{
+    // ESSL spec section 4.5.3: sampler2D and samplerCube are lowp by default
+    // ESSL spec section 8: For the texture functions, the precision of the return type matches the precision of the sampler type.
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform sampler2D s;\n"
+        "uniform vec2 a;\n"
+        "void main() {\n"
+        "   vec4 c = texture2D(s, a);\n"
+        "   gl_FragColor = c;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("texture2D (lowp 4-component vector of float)"));
+}
+
+TEST_F(TypeTrackingTest, TextureCubeResultTypeAndPrecision)
+{
+    // ESSL spec section 4.5.3: sampler2D and samplerCube are lowp by default
+    // ESSL spec section 8: For the texture functions, the precision of the return type matches the precision of the sampler type.
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform samplerCube sc;\n"
+        "uniform vec3 a;\n"
+        "void main() {\n"
+        "   vec4 c = textureCube(sc, a);\n"
+        "   gl_FragColor = c;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("textureCube (lowp 4-component vector of float)"));
+}
+
+TEST_F(TypeTrackingTest, TextureSizeResultTypeAndPrecision)
+{
+    // ESSL 3.0 spec section 8: textureSize has predefined precision highp
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform sampler2D s;\n"
+        "void main() {\n"
+        "   ivec2 size = textureSize(s, 0);\n"
+        "   if (size.x > 100) {\n"
+        "       my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+        "   } else {\n"
+        "       my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "   }\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("textureSize (highp 2-component vector of int)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInConstructorResultTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float u1;\n"
+        "uniform float u2;\n"
+        "uniform float u3;\n"
+        "uniform float u4;\n"
+        "void main() {\n"
+        "   vec4 a = vec4(u1, u2, u3, u4);\n"
+        "   gl_FragColor = a;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 4-component vector of float)"));
+}
+
+TEST_F(TypeTrackingTest, StructConstructorResultNoPrecision)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u1;\n"
+        "uniform vec4 u2;\n"
+        "struct S { highp vec4 a; highp vec4 b; };\n"
+        "void main() {\n"
+        "   S s = S(u1, u2);\n"
+        "   gl_FragColor = s.a;\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("Construct (structure)"));
+}
+
+TEST_F(TypeTrackingTest, PackResultTypeAndPrecision)
+{
+    // ESSL 3.0 spec section 8.4: pack functions have predefined precision highp
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision mediump int;\n"
+        "uniform vec2 uv;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   uint u0 = packSnorm2x16(uv);\n"
+        "   uint u1 = packUnorm2x16(uv);\n"
+        "   uint u2 = packHalf2x16(uv);\n"
+        "   if (u0 + u1 + u2 > 100u) {\n"
+        "       my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+        "   } else {\n"
+        "       my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "   }\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("packSnorm2x16 (highp uint)"));
+    ASSERT_TRUE(foundInIntermediateTree("packUnorm2x16 (highp uint)"));
+    ASSERT_TRUE(foundInIntermediateTree("packHalf2x16 (highp uint)"));
+}
+
+TEST_F(TypeTrackingTest, UnpackNormResultTypeAndPrecision)
+{
+    // ESSL 3.0 spec section 8.4: unpack(S/U)norm2x16 has predefined precision highp
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision mediump int;\n"
+        "uniform uint uu;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   vec2 v0 = unpackSnorm2x16(uu);\n"
+        "   vec2 v1 = unpackUnorm2x16(uu);\n"
+        "   if (v0.x * v1.x > 1.0) {\n"
+        "       my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+        "   } else {\n"
+        "       my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "   }\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("unpackSnorm2x16 (highp 2-component vector of float)"));
+    ASSERT_TRUE(foundInIntermediateTree("unpackUnorm2x16 (highp 2-component vector of float)"));
+}
+
+TEST_F(TypeTrackingTest, UnpackHalfResultTypeAndPrecision)
+{
+    // ESSL 3.0 spec section 8.4: unpackHalf2x16 has predefined precision mediump
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "precision highp int;\n"
+        "uniform uint uu;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   vec2 v = unpackHalf2x16(uu);\n"
+        "   if (v.x > 1.0) {\n"
+        "       my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+        "   } else {\n"
+        "       my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "   }\n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("unpackHalf2x16 (mediump 2-component vector of float)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInAbsSignFunctionFloatResultTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float fval1;\n"
+        "void main() {\n"
+        "   float fval2 = abs(fval1);\n"
+        "   float fval3 = sign(fval1);\n"
+        "   gl_FragColor = vec4(fval1, 0.0, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("abs (mediump float)"));
+    ASSERT_TRUE(foundInIntermediateTree("sign (mediump float)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInAbsSignFunctionIntResultTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision mediump int;\n"
+        "uniform int ival1;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   int ival2 = abs(ival1);\n"
+        "   int ival3 = sign(ival1);\n"
+        "   my_FragColor = vec4(0.0, 0.0, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("abs (mediump int)"));
+    ASSERT_TRUE(foundInIntermediateTree("sign (mediump int)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInFloatBitsToIntResultTypeAndPrecision)
+{
+    // ESSL 3.00 section 8.3: floatBitsTo(U)int returns a highp value.
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision mediump int;\n"
+        "uniform float f;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   int i = floatBitsToInt(f);\n"
+        "   uint u = floatBitsToUint(f);\n"
+        "   my_FragColor = vec4(0.0, 0.0, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("floatBitsToInt (highp int)"));
+    ASSERT_TRUE(foundInIntermediateTree("floatBitsToUint (highp uint)"));
+}
+
+TEST_F(TypeTrackingTest, BuiltInIntBitsToFloatResultTypeAndPrecision)
+{
+    // ESSL 3.00 section 8.3: (u)intBitsToFloat returns a highp value.
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "precision mediump int;\n"
+        "uniform int i;\n"
+        "uniform uint u;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   float f1 = intBitsToFloat(i);\n"
+        "   float f2 = uintBitsToFloat(u);\n"
+        "   my_FragColor = vec4(f1, f2, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("intBitsToFloat (highp float)"));
+    ASSERT_TRUE(foundInIntermediateTree("uintBitsToFloat (highp float)"));
+}
+
+// Test that bitfieldExtract returns a precision consistent with its "value" parameter.
+TEST_F(TypeTrackingTest, BuiltInBitfieldExtractResultTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform mediump int i;\n"
+        "uniform highp uint u;\n"
+        "uniform lowp int offset;\n"
+        "uniform highp int bits;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   lowp int i2 = bitfieldExtract(i, offset, bits);\n"
+        "   lowp uint u2 = bitfieldExtract(u, offset, bits);\n"
+        "   my_FragColor = vec4(i2, u2, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("bitfieldExtract (mediump int)"));
+    ASSERT_TRUE(foundInIntermediateTree("bitfieldExtract (highp uint)"));
+}
+
+// Test that signed bitfieldInsert returns a precision consistent with its "base/insert" parameters.
+TEST_F(TypeTrackingTest, BuiltInBitfieldInsertResultTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform lowp int iBase;\n"
+        "uniform mediump int iInsert;\n"
+        "uniform highp uint uBase;\n"
+        "uniform mediump uint uInsert;\n"
+        "uniform highp int offset;\n"
+        "uniform highp int bits;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   lowp int i = bitfieldInsert(iBase, iInsert, offset, bits);\n"
+        "   lowp uint u = bitfieldInsert(uBase, uInsert, offset, bits);\n"
+        "   my_FragColor = vec4(i, u, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (mediump int)"));
+    ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (highp uint)"));
+}
+
+// Test that signed bitfieldInsert returns a precision consistent with its "base/insert" parameters.
+// Another variation on parameter precisions.
+TEST_F(TypeTrackingTest, BuiltInBitfieldInsertResultTypeAndPrecision2)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform highp int iBase;\n"
+        "uniform mediump int iInsert;\n"
+        "uniform lowp uint uBase;\n"
+        "uniform mediump uint uInsert;\n"
+        "uniform lowp int offset;\n"
+        "uniform lowp int bits;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   lowp int i = bitfieldInsert(iBase, iInsert, offset, bits);\n"
+        "   lowp uint u = bitfieldInsert(uBase, uInsert, offset, bits);\n"
+        "   my_FragColor = vec4(i, u, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (highp int)"));
+    ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (mediump uint)"));
+}
+
+// Test that bitfieldReverse always results in highp precision.
+TEST_F(TypeTrackingTest, BuiltInBitfieldReversePrecision)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform lowp uint u;\n"
+        "uniform mediump int i;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   lowp uint u2 = bitfieldReverse(u);\n"
+        "   lowp int i2 = bitfieldReverse(i);\n"
+        "   my_FragColor = vec4(u2, i2, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("bitfieldReverse (highp uint)"));
+    ASSERT_TRUE(foundInIntermediateTree("bitfieldReverse (highp int)"));
+}
+
+// Test that bitCount always results in lowp precision integer.
+TEST_F(TypeTrackingTest, BuiltInBitCountTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform highp uint u;\n"
+        "uniform mediump int i;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   highp int count1 = bitCount(u);\n"
+        "   highp int count2 = bitCount(i);\n"
+        "   my_FragColor = vec4(count1, count2, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("bitCount (lowp int)"));
+    ASSERT_FALSE(foundInIntermediateTree("bitCount (lowp uint)"));
+}
+
+// Test that findLSB always results in a lowp precision integer.
+TEST_F(TypeTrackingTest, BuiltInFindLSBTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform highp uint u;\n"
+        "uniform mediump int i;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   highp int index1 = findLSB(u);\n"
+        "   highp int index2 = findLSB(i);\n"
+        "   my_FragColor = vec4(index1, index2, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("findLSB (lowp int)"));
+    ASSERT_FALSE(foundInIntermediateTree("findLSB (lowp uint)"));
+}
+
+// Test that findMSB always results in a lowp precision integer.
+TEST_F(TypeTrackingTest, BuiltInFindMSBTypeAndPrecision)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform highp uint u;\n"
+        "uniform mediump int i;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   highp int index1 = findMSB(u);\n"
+        "   highp int index2 = findMSB(i);\n"
+        "   my_FragColor = vec4(index1, index2, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("findMSB (lowp int)"));
+    ASSERT_FALSE(foundInIntermediateTree("findMSB (lowp uint)"));
+}
+
+// Test that uaddCarry always results in highp precision.
+TEST_F(TypeTrackingTest, BuiltInUaddCarryPrecision)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform mediump uvec2 x;\n"
+        "uniform mediump uvec2 y;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   lowp uvec2 carry;\n"
+        "   mediump uvec2 result = uaddCarry(x, y, carry);\n"
+        "   my_FragColor = vec4(result.x, carry.y, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("uaddCarry (highp 2-component vector of uint)"));
+}
+
+// Test that usubBorrow always results in highp precision.
+TEST_F(TypeTrackingTest, BuiltInUsubBorrowPrecision)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "uniform mediump uvec2 x;\n"
+        "uniform mediump uvec2 y;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "   lowp uvec2 borrow;\n"
+        "   mediump uvec2 result = usubBorrow(x, y, borrow);\n"
+        "   my_FragColor = vec4(result.x, borrow.y, 0.0, 1.0); \n"
+        "}\n";
+    compile(shaderString);
+    ASSERT_FALSE(foundErrorInIntermediateTree());
+    ASSERT_TRUE(foundInIntermediateTree("usubBorrow (highp 2-component vector of uint)"));
+}
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/compiler_tests/UnrollFlatten_test.cpp b/src/third_party/angle/src/tests/compiler_tests/UnrollFlatten_test.cpp
new file mode 100644
index 0000000..82ed75a
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/UnrollFlatten_test.cpp
@@ -0,0 +1,238 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// UnrollFlatten_test.cpp:
+//   Test for the outputting of [[unroll]] and [[flatten]] for the D3D compiler.
+//   This test can only be enabled when HLSL support is enabled.
+//
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+namespace
+{
+
+class UnrollFlattenTest : public testing::Test
+{
+  public:
+    UnrollFlattenTest() : mInputSpec(SH_GLES2_SPEC) {}
+    UnrollFlattenTest(ShShaderSpec inputSpec) : mInputSpec(inputSpec) {}
+
+  protected:
+    void compile(const std::string &shaderString)
+    {
+        std::string infoLog;
+        bool compilationSuccess =
+            compileTestShader(GL_FRAGMENT_SHADER, mInputSpec, SH_HLSL_4_1_OUTPUT, shaderString,
+                              SH_VARIABLES, &mTranslatedSource, &infoLog);
+        if (!compilationSuccess)
+        {
+            FAIL() << "Shader compilation failed " << infoLog;
+        }
+        // Ignore the beginning of the shader to avoid the definitions of LOOP and FLATTEN
+        mCurrentPosition = static_cast<int>(mTranslatedSource.find("cbuffer DriverConstants"));
+    }
+
+    void expect(const char *patterns[], size_t count)
+    {
+        const char *badPatterns[] = { UNROLL, FLATTEN };
+        for (size_t i = 0; i < count; i++)
+        {
+            const char *pattern = patterns[i];
+            auto position = mTranslatedSource.find(pattern, mCurrentPosition);
+            if (position == std::string::npos)
+            {
+                FAIL() << "Couldn't find '" << pattern << "' after expectations '"
+                       << mExpectationList << "' in translated source:\n" << mTranslatedSource;
+            }
+
+            for (size_t j = 0; j < ArraySize(badPatterns); j++)
+            {
+                const char *badPattern = badPatterns[j];
+                if (pattern != badPattern &&
+                    mTranslatedSource.find(badPattern, mCurrentPosition) < position)
+                {
+                    FAIL() << "Found '" << badPattern << "' before '" << pattern << "' after expectations '"
+                           << mExpectationList << "' in translated source:\n" << mTranslatedSource;
+                }
+            }
+            mExpectationList += " - " + std::string(pattern);
+            mCurrentPosition = static_cast<int>(position) + 1;
+        }
+    }
+
+    static const char *UNROLL;
+    static const char *FLATTEN;
+
+  private:
+    ShShaderSpec mInputSpec;
+    std::string mTranslatedSource;
+
+    int mCurrentPosition;
+    std::string mExpectationList;
+};
+
+const char *UnrollFlattenTest::UNROLL = "LOOP";
+const char *UnrollFlattenTest::FLATTEN = "FLATTEN";
+
+// Check that the nothing is added if there is no gradient operation
+// even when there is ifs and discontinuous loops
+TEST_F(UnrollFlattenTest, NoGradient)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float f;\n"
+        "float fun(float a){\n" // 1
+        "    if (a > 1.0) {return f;}\n" // 2
+        "    else {return a + 1.0;}\n"
+        "}\n"
+        "float fun2(float a){\n" // 3
+        "    for (int i = 0; i < 10; i++) {\n" // 4
+        "        if (a > 1.0) {break;}\n" // 5
+        "        a = fun(a);\n" // 6
+        "    }\n"
+        "    return a;\n"
+        "}\n"
+        "void main() {\n"
+        "    float accum = 0.0;\n"
+        "    if (f < 5.0) {accum = fun2(accum);}\n" // 7
+        "    gl_FragColor = vec4(accum);\n"
+        "}\n";
+    compile(shaderString);
+    // 1 - shouldn't get a Lod0 version generated
+    // 2 - no FLATTEN because does not contain discont loop
+    // 3 - shouldn't get a Lod0 version generated
+    // 4 - no LOOP because discont, and also no gradient
+    // 5 - no FLATTEN because does not contain loop with a gradient
+    // 6 - call non-Lod0 version
+    // 7 - no FLATTEN
+    const char *expectations[] =
+    {
+        "fun(", "if",
+        "fun2(", "for", "if", "break", "fun(",
+        "main(", "if", "fun2("
+    };
+    expect(expectations, ArraySize(expectations));
+}
+
+// Check that when we have a gradient in a non-discontinuous loop
+// we use the regular version of the functions. Also checks that
+// LOOP is generated for the loop containing the gradient.
+TEST_F(UnrollFlattenTest, GradientNotInDiscont)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float f;\n"
+        "uniform sampler2D tex;"
+        "float fun(float a){\n" // 1
+        "    return texture2D(tex, vec2(0.5, f)).x;\n" // 2
+        "}\n"
+        "float fun2(float a){\n" // 3
+        "    for (int i = 0; i < 10; i++) {\n" // 4
+        "        if (a > 1.0) {}\n" // 5
+        "        a = fun(a);\n" // 6
+        "        a += texture2D(tex, vec2(a, 0.0)).x;" // 7
+        "    }\n"
+        "    return a;\n"
+        "}\n"
+        "void main() {\n"
+        "    float accum = 0.0;\n"
+        "    if (f < 5.0) {accum = fun2(accum);}\n" // 8
+        "    gl_FragColor = vec4(accum);\n"
+        "}\n";
+    // 1 - shouldn't get a Lod0 version generated
+    // 2 - no Lod0 version generated
+    // 3 - shouldn't get a Lod0 version generated (not in discont loop)
+    // 4 - should have LOOP because it contains a gradient operation (even if Lod0)
+    // 5 - no FLATTEN because doesn't contain loop with a gradient
+    // 6 - call non-Lod0 version
+    // 7 - call non-Lod0 version
+    // 8 - FLATTEN because it contains a loop with a gradient
+    compile(shaderString);
+    const char *expectations[] =
+    {
+        "fun(", "texture2D(",
+        "fun2(", "LOOP", "for", "if", "fun(", "texture2D(",
+        "main(", "FLATTEN", "if", "fun2("
+    };
+    expect(expectations, ArraySize(expectations));
+}
+
+// Check that when we have a gradient in a discontinuous loop
+// we use the Lod0 version of the functions.
+TEST_F(UnrollFlattenTest, GradientInDiscont)
+{
+    const std::string &shaderString =
+        "precision mediump float;\n"
+        "uniform float f;\n"
+        "uniform sampler2D tex;"
+        "float fun(float a){\n" // 1
+        "    return texture2D(tex, vec2(0.5, f)).x;\n" // 2
+        "}\n"
+        "float fun2(float a){\n" // 3
+        "    for (int i = 0; i < 10; i++) {\n" // 4
+        "        if (a > 1.0) {break;}\n" // 5
+        "        a = fun(a);\n" // 6
+        "        a += texture2D(tex, vec2(a, 0.0)).x;" // 7
+        "    }\n"
+        "    return a;\n"
+        "}\n"
+        "void main() {\n"
+        "    float accum = 0.0;\n"
+        "    if (f < 5.0) {accum = fun2(accum);}\n" // 8
+        "    gl_FragColor = vec4(accum);\n"
+        "}\n";
+    // 1 - should get a Lod0 version generated (gradient + discont loop)
+    // 2 - will get the Lod0 if in funLod0
+    // 3 - shouldn't get a Lod0 version generated (not in discont loop)
+    // 4 - should have LOOP because it contains a gradient operation (even if Lod0)
+    // 5 - no FLATTEN because doesn't contain a loop with a gradient
+    // 6 - call Lod0 version
+    // 7 - call Lod0 version
+    // 8 - FLATTEN because it contains a loop with a gradient
+    compile(shaderString);
+    const char *expectations[] =
+    {
+        "fun(", "texture2D(",
+        "funLod0(", "texture2DLod0(",
+        "fun2(", "LOOP", "for", "if", "break", "funLod0(", "texture2DLod0",
+        "main(", "FLATTEN", "if", "fun2("
+    };
+    expect(expectations, ArraySize(expectations));
+}
+
+class UnrollFlattenTest_ES3 : public UnrollFlattenTest
+{
+  public:
+    UnrollFlattenTest_ES3() : UnrollFlattenTest(SH_GLES3_SPEC) {}
+};
+
+// Check that we correctly detect the ES3 builtin "texture" function as a gradient operation.
+TEST_F(UnrollFlattenTest_ES3, TextureBuiltin)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform sampler2D tex;"
+        "out float fragColor;\n"
+        "void main() {\n"
+        "    float a = 0.0;"
+        "    for (int i = 0; i < 10; i++) {\n"
+        "        if (a > 1.0) {break;}\n"
+        "        a += texture(tex, vec2(a, 0.0)).x;"
+        "    }\n"
+        "    fragColor = a;\n"
+        "}\n";
+
+    compile(shaderString);
+    const char *expectations[] = {"main(", "LOOP", "Lod0("};
+    expect(expectations, ArraySize(expectations));
+}
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/VariablePacker_test.cpp b/src/third_party/angle/src/tests/compiler_tests/VariablePacker_test.cpp
new file mode 100644
index 0000000..dd9b0b5
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/VariablePacker_test.cpp
@@ -0,0 +1,237 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#include "gtest/gtest.h"
+#include "angle_gl.h"
+#include "common/utilities.h"
+#include "common/angleutils.h"
+#include "compiler/translator/VariablePacker.h"
+
+static sh::GLenum types[] = {
+  GL_FLOAT_MAT4,            // 0
+  GL_FLOAT_MAT2,            // 1
+  GL_FLOAT_VEC4,            // 2
+  GL_INT_VEC4,              // 3
+  GL_BOOL_VEC4,             // 4
+  GL_FLOAT_MAT3,            // 5
+  GL_FLOAT_VEC3,            // 6
+  GL_INT_VEC3,              // 7
+  GL_BOOL_VEC3,             // 8
+  GL_FLOAT_VEC2,            // 9
+  GL_INT_VEC2,              // 10
+  GL_BOOL_VEC2,             // 11
+  GL_FLOAT,                 // 12
+  GL_INT,                   // 13
+  GL_BOOL,                  // 14
+  GL_SAMPLER_2D,            // 15
+  GL_SAMPLER_CUBE,          // 16
+  GL_SAMPLER_EXTERNAL_OES,  // 17
+  GL_SAMPLER_2D_RECT_ARB,   // 18
+  GL_UNSIGNED_INT,          // 19
+  GL_UNSIGNED_INT_VEC2,     // 20
+  GL_UNSIGNED_INT_VEC3,     // 21
+  GL_UNSIGNED_INT_VEC4,     // 22
+  GL_FLOAT_MAT2x3,          // 23
+  GL_FLOAT_MAT2x4,          // 24
+  GL_FLOAT_MAT3x2,          // 25
+  GL_FLOAT_MAT3x4,          // 26
+  GL_FLOAT_MAT4x2,          // 27
+  GL_FLOAT_MAT4x3,          // 28
+  GL_SAMPLER_3D,            // 29
+  GL_SAMPLER_2D_ARRAY,      // 30
+  GL_SAMPLER_2D_SHADOW,     // 31
+  GL_SAMPLER_CUBE_SHADOW,   // 32
+  GL_SAMPLER_2D_ARRAY_SHADOW, // 33
+  GL_INT_SAMPLER_2D,        // 34
+  GL_INT_SAMPLER_CUBE,      // 35
+  GL_INT_SAMPLER_3D,        // 36
+  GL_INT_SAMPLER_2D_ARRAY,  // 37
+  GL_UNSIGNED_INT_SAMPLER_2D, // 38
+  GL_UNSIGNED_INT_SAMPLER_CUBE, // 39
+  GL_UNSIGNED_INT_SAMPLER_3D, // 40
+  GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, // 41
+};
+
+static sh::GLenum nonSqMatTypes[] = {
+  GL_FLOAT_MAT2x3,
+  GL_FLOAT_MAT2x4,
+  GL_FLOAT_MAT3x2,
+  GL_FLOAT_MAT3x4,
+  GL_FLOAT_MAT4x2,
+  GL_FLOAT_MAT4x3
+};
+
+TEST(VariablePacking, Pack) {
+    VariablePacker packer;
+    std::vector<sh::ShaderVariable> vars;
+    const int kMaxRows = 16;
+    // test no vars.
+    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+    for (size_t tt = 0; tt < ArraySize(types); ++tt)
+    {
+        sh::GLenum type            = types[tt];
+        int num_rows               = VariablePacker::GetNumRows(type);
+        int num_components_per_row = VariablePacker::GetNumComponentsPerRow(type);
+        // Check 1 of the type.
+        vars.clear();
+        vars.push_back(sh::ShaderVariable(type, 0));
+        EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+        // Check exactly the right amount of 1 type as an array.
+        int num_vars = kMaxRows / num_rows;
+        vars.clear();
+        vars.push_back(sh::ShaderVariable(type, num_vars == 1 ? 0 : num_vars));
+        EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+        // test too many
+        vars.clear();
+        vars.push_back(sh::ShaderVariable(type, num_vars == 0 ? 0 : (num_vars + 1)));
+        EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+        // Check exactly the right amount of 1 type as individual vars.
+        num_vars =
+            kMaxRows / num_rows * ((num_components_per_row > 2) ? 1 : (4 / num_components_per_row));
+        vars.clear();
+        for (int ii = 0; ii < num_vars; ++ii)
+        {
+            vars.push_back(sh::ShaderVariable(type, 0));
+        }
+        EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+        // Check 1 too many.
+        vars.push_back(sh::ShaderVariable(type, 0));
+        EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+    }
+
+    // Test example from GLSL ES 3.0 spec chapter 11.
+    vars.clear();
+    vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC4, 0));
+    vars.push_back(sh::ShaderVariable(GL_FLOAT_MAT3, 0));
+    vars.push_back(sh::ShaderVariable(GL_FLOAT_MAT3, 0));
+    vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 6));
+    vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 4));
+    vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 0));
+    vars.push_back(sh::ShaderVariable(GL_FLOAT, 3));
+    vars.push_back(sh::ShaderVariable(GL_FLOAT, 2));
+    vars.push_back(sh::ShaderVariable(GL_FLOAT, 0));
+    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+}
+
+TEST(VariablePacking, PackSizes) {
+  for (size_t tt = 0; tt < ArraySize(types); ++tt) {
+    GLenum type = types[tt];
+
+    int expectedComponents = gl::VariableComponentCount(type);
+    int expectedRows = gl::VariableRowCount(type);
+
+    if (type == GL_FLOAT_MAT2) {
+      expectedComponents = 4;
+    } else if (gl::IsMatrixType(type)) {
+      int squareSize = std::max(gl::VariableRowCount(type),
+          gl::VariableColumnCount(type));
+      expectedComponents = squareSize;
+      expectedRows = squareSize;
+    }
+
+    EXPECT_EQ(expectedComponents,
+      VariablePacker::GetNumComponentsPerRow(type));
+    EXPECT_EQ(expectedRows, VariablePacker::GetNumRows(type));
+  }
+}
+
+// Check special assumptions about packing non-square mats
+TEST(VariablePacking, NonSquareMats) {
+
+  for (size_t mt = 0; mt < ArraySize(nonSqMatTypes); ++mt) {
+    
+    GLenum type = nonSqMatTypes[mt];
+
+    int rows = gl::VariableRowCount(type);
+    int cols = gl::VariableColumnCount(type);
+    int squareSize = std::max(rows, cols);
+
+    std::vector<sh::ShaderVariable> vars;
+    vars.push_back(sh::ShaderVariable(type, 0));
+
+    // Fill columns
+    for (int row = 0; row < squareSize; row++) {
+      for (int col = squareSize; col < 4; ++col) {
+        vars.push_back(sh::ShaderVariable(GL_FLOAT, 0));
+      }
+    }
+
+    VariablePacker packer;
+
+    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(squareSize, vars));
+
+    // and one scalar and packing should fail
+    vars.push_back(sh::ShaderVariable(GL_FLOAT, 0));
+    EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(squareSize, vars));
+  }
+}
+
+// Scalar type variables can be packed sharing rows with other variables.
+TEST(VariablePacking, ReuseRows)
+{
+    VariablePacker packer;
+    std::vector<sh::ShaderVariable> vars;
+    const int kMaxRows = 512;
+
+    // uniform bool u0[129];
+    // uniform bool u1[129];
+    // uniform bool u2[129];
+    // uniform bool u3[129];
+    {
+        int num_arrays = 4;
+        int num_elements_per_array = kMaxRows / num_arrays + 1;
+        for (int ii = 0; ii < num_arrays; ++ii)
+        {
+            vars.push_back(sh::ShaderVariable(GL_BOOL, num_elements_per_array));
+        }
+        EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+    }
+
+    vars.clear();
+    // uniform vec2 u0[257];
+    // uniform float u1[257];
+    // uniform int u1[257];
+    {
+        int num_elements_per_array = kMaxRows / 2 + 1;
+        vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, num_elements_per_array));
+        vars.push_back(sh::ShaderVariable(GL_FLOAT, num_elements_per_array));
+        vars.push_back(sh::ShaderVariable(GL_INT, num_elements_per_array));
+        EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+    }
+}
+
+// Check the packer supports and flattens structures.
+TEST(VariablePacking, Struct)
+{
+    VariablePacker packer;
+    std::vector<sh::ShaderVariable> fields;
+    const int kMaxRows = 16;
+
+    // Test example from GLSL ES 3.0 spec chapter 11, but with structs
+    std::vector<sh::ShaderVariable> vars;
+    vars.push_back(sh::ShaderVariable(GL_STRUCT_ANGLEX, 0));
+
+    sh::ShaderVariable &parentStruct = vars[0];
+    parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC4, 0));
+    parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_MAT3, 0));
+
+    parentStruct.fields.push_back(sh::ShaderVariable(GL_STRUCT_ANGLEX, 0));
+    sh::ShaderVariable &innerStruct = parentStruct.fields.back();
+    innerStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_MAT3, 0));
+    innerStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 6));
+    innerStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 4));
+
+    parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 0));
+    parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 3));
+    parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 2));
+    parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 0));
+
+    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/WEBGL_multiview_test.cpp b/src/third_party/angle/src/tests/compiler_tests/WEBGL_multiview_test.cpp
new file mode 100644
index 0000000..363f1ef
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/WEBGL_multiview_test.cpp
@@ -0,0 +1,420 @@
+//
+// Copyright (c) 2016 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.
+//
+// WEBGL_multiview_test.cpp:
+//   Test that shaders with gl_ViewID_OVR are validated correctly.
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+
+using namespace sh;
+
+class WEBGLMultiviewVertexShaderTest : public ShaderCompileTreeTest
+{
+  public:
+    WEBGLMultiviewVertexShaderTest() {}
+  protected:
+    ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_WEBGL3_SPEC; }
+    void initResources(ShBuiltInResources *resources) override
+    {
+        resources->OVR_multiview = 1;
+        resources->MaxViewsOVR   = 4;
+    }
+};
+
+class WEBGLMultiviewFragmentShaderTest : public ShaderCompileTreeTest
+{
+  public:
+    WEBGLMultiviewFragmentShaderTest() {}
+  protected:
+    ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_WEBGL3_SPEC; }
+    void initResources(ShBuiltInResources *resources) override
+    {
+        resources->OVR_multiview = 1;
+        resources->MaxViewsOVR   = 4;
+    }
+};
+
+// Invalid combination of extensions (restricted in the WEBGL_multiview spec).
+TEST_F(WEBGLMultiviewVertexShaderTest, InvalidBothMultiviewAndMultiview2)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "#extension GL_OVR_multiview2 : enable\n"
+        "layout(num_views = 2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid combination of non-matching num_views declarations.
+TEST_F(WEBGLMultiviewVertexShaderTest, InvalidNumViewsMismatch)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview2 : require\n"
+        "layout(num_views = 2) in;\n"
+        "layout(num_views = 1) in;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid value zero for num_views.
+TEST_F(WEBGLMultiviewVertexShaderTest, InvalidNumViewsZero)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview2 : require\n"
+        "layout(num_views = 0) in;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Too large value for num_views.
+TEST_F(WEBGLMultiviewVertexShaderTest, InvalidNumViewsGreaterThanMax)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview2 : require\n"
+        "layout(num_views = 5) in;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Valid use of gl_ViewID_OVR in a ternary operator.
+TEST_F(WEBGLMultiviewVertexShaderTest, ValidViewIDInTernary)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "layout(num_views = 2) in;  // Duplicated on purpose\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Valid use of gl_ViewID_OVR in an if statement.
+TEST_F(WEBGLMultiviewVertexShaderTest, ValidViewIDInIf)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0u)\n"
+        "    {\n"
+        "        gl_Position.x = 1.0;\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_Position.x = 1.0;\n"
+        "    }\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Valid normal write of gl_Position in addition to the write that's dependent on gl_ViewID_OVR.
+TEST_F(WEBGLMultiviewVertexShaderTest, ValidWriteOfGlPosition)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    if (0u == gl_ViewID_OVR)\n"
+        "    {\n"
+        "        gl_Position.x = 1.0;\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_Position.x = 1.0;\n"
+        "    }\n"
+        "    gl_Position = vec4(1, 1, 1, 1);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Invalid assignment to gl_Position.y inside if dependent on gl_ViewID_OVR.
+TEST_F(WEBGLMultiviewVertexShaderTest, InvalidGlPositionAssignmentInIf)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0u)\n"
+        "    {\n"
+        "        gl_Position.y = 1.0;\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_Position.y = 1.0;\n"
+        "    }\n"
+        "    gl_Position.xzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid multiple assignments inside if dependent on gl_ViewID_OVR.
+TEST_F(WEBGLMultiviewVertexShaderTest, InvalidMultipleGlPositionXAssignmentsInIf)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0u)\n"
+        "    {\n"
+        "        gl_Position.x = 1.0;\n"
+        "        gl_Position.x = 2.0;\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_Position.x = 1.0;\n"
+        "    }\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid read of gl_Position
+TEST_F(WEBGLMultiviewVertexShaderTest, InvalidReadOfGlPosition)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0u) {\n"
+        "        gl_Position.x = 1.0;\n"
+        "    } else {\n"
+        "        gl_Position.x = 1.0;\n"
+        "    }\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "    float f = gl_Position.y;\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Read gl_Position when the shader does not refer to gl_ViewID_OVR.
+TEST_F(WEBGLMultiviewVertexShaderTest, ValidReadOfGlPosition)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "uniform float u;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0, 0, 0, 1);\n"
+        "    gl_Position.y = gl_Position.x * u;\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Read gl_FragCoord in a OVR_multiview fragment shader.
+TEST_F(WEBGLMultiviewFragmentShaderTest, InvalidReadOfFragCoord)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "precision highp float;\n"
+        "out vec4 outColor;\n"
+        "void main()\n"
+        "{\n"
+        "    outColor = vec4(gl_FragCoord.xy, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Read gl_ViewID_OVR in an OVR_multiview fragment shader.
+TEST_F(WEBGLMultiviewFragmentShaderTest, InvalidReadOfViewID)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "precision highp float;\n"
+        "out vec4 outColor;\n"
+        "void main()\n"
+        "{\n"
+        "    outColor = vec4(gl_ViewID_OVR, 0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Tricky invalid read of view ID.
+TEST_F(WEBGLMultiviewVertexShaderTest, InvalidConsumingExpressionForAssignGLPositionX)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    float f = (gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0);\n"
+        "    gl_Position.yzw = vec3(f, f, f);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Using the OVR_multiview2 extension directive lifts restrictions of OVR_multiview.
+TEST_F(WEBGLMultiviewVertexShaderTest, RestrictionsLiftedMultiview2)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview2 : require\n"
+        "layout(num_views = 2) in;\n"
+        "out float out_f;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0u)\n"
+        "    {\n"
+        "        gl_Position.x = 1.0;\n"
+        "        gl_Position.x = 2.0;\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_Position.x = 1.0;\n"
+        "    }\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "    gl_Position += vec4(1, 0, 0, 1);\n"
+        "    out_f = float(gl_ViewID_OVR * 2u);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Correct use of GL_OVR_multiview macros.
+TEST_F(WEBGLMultiviewVertexShaderTest, ValidUseOfExtensionMacros)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#ifdef GL_OVR_multiview\n"
+        "#ifdef GL_OVR_multiview2\n"
+        "#if (GL_OVR_multiview == 1) && (GL_OVR_multiview2 == 1)\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+        "}\n"
+        "#endif\n"
+        "#endif\n"
+        "#endif\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that the parent node is tracked correctly when validating assignment to gl_Position.
+TEST_F(WEBGLMultiviewVertexShaderTest, AssignmentWithViewIDInsideAssignment)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.y = (gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that gl_ViewID_OVR can't be used as an l-value.
+TEST_F(WEBGLMultiviewVertexShaderTest, ViewIdAsLValue)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview2 : require\n"
+        "void foo(out uint u)\n"
+        "{\n"
+        "    u = 3u;\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "    foo(gl_ViewID_OVR);\n"
+        "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
diff --git a/src/third_party/angle/src/tests/compiler_tests/WorkGroupSize_test.cpp b/src/third_party/angle/src/tests/compiler_tests/WorkGroupSize_test.cpp
new file mode 100644
index 0000000..980617f
--- /dev/null
+++ b/src/third_party/angle/src/tests/compiler_tests/WorkGroupSize_test.cpp
@@ -0,0 +1,99 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// WorkGroupSize_test.cpp:
+// tests for local group size in a compute shader
+//
+
+#include "angle_gl.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/TranslatorESSL.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+class WorkGroupSizeTest : public testing::Test
+{
+  public:
+    WorkGroupSizeTest() {}
+
+  protected:
+    void SetUp() override
+    {
+        ShBuiltInResources resources;
+        InitBuiltInResources(&resources);
+
+        mTranslator = new TranslatorESSL(GL_COMPUTE_SHADER, SH_GLES3_1_SPEC);
+        ASSERT_TRUE(mTranslator->Init(resources));
+    }
+
+    void TearDown() override { SafeDelete(mTranslator); }
+
+    // Return true when compilation succeeds
+    bool compile(const std::string &shaderString)
+    {
+        const char *shaderStrings[] = {shaderString.c_str()};
+        bool status = mTranslator->compile(shaderStrings, 1, SH_INTERMEDIATE_TREE | SH_VARIABLES);
+        TInfoSink &infoSink = mTranslator->getInfoSink();
+        mInfoLog            = infoSink.info.c_str();
+        return status;
+    }
+
+  protected:
+    std::string mInfoLog;
+    TranslatorESSL *mTranslator = nullptr;
+};
+
+// checks whether compiler has parsed the local size layout qualifiers qcorrectly
+TEST_F(WorkGroupSizeTest, OnlyLocalSizeXSpecified)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x=5) in;\n"
+        "void main() {\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const WorkGroupSize &localSize = mTranslator->getComputeShaderLocalSize();
+    ASSERT_EQ(5, localSize[0]);
+    ASSERT_EQ(1, localSize[1]);
+    ASSERT_EQ(1, localSize[2]);
+}
+
+// checks whether compiler has parsed the local size layout qualifiers qcorrectly
+TEST_F(WorkGroupSizeTest, LocalSizeXandZ)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x=5, local_size_z=10) in;\n"
+        "void main() {\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const WorkGroupSize &localSize = mTranslator->getComputeShaderLocalSize();
+    ASSERT_EQ(5, localSize[0]);
+    ASSERT_EQ(1, localSize[1]);
+    ASSERT_EQ(10, localSize[2]);
+}
+
+// checks whether compiler has parsed the local size layout qualifiers qcorrectly
+TEST_F(WorkGroupSizeTest, LocalSizeAll)
+{
+    const std::string &shaderString =
+        "#version 310 es\n"
+        "layout(local_size_x=5, local_size_z=10, local_size_y=15) in;\n"
+        "void main() {\n"
+        "}\n";
+
+    compile(shaderString);
+
+    const WorkGroupSize &localSize = mTranslator->getComputeShaderLocalSize();
+    ASSERT_EQ(5, localSize[0]);
+    ASSERT_EQ(15, localSize[1]);
+    ASSERT_EQ(10, localSize[2]);
+}
diff --git a/src/third_party/angle/src/tests/deqp.gypi b/src/third_party/angle/src/tests/deqp.gypi
new file mode 100644
index 0000000..fcfb004
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp.gypi
@@ -0,0 +1,1939 @@
+# Copyright 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'variables':
+    {
+        # Define these variables within an inner variables dict.
+        # This is necessary to get these variables defined for the conditions
+        # within the outer variables dict which operate on these variables.
+        'variables':
+        {
+            'angle_build_winrt%': 0,
+        },
+
+        # Copy conditionally-set variables to the outer variables dict.
+        'angle_build_winrt%': '<(angle_build_winrt)',
+
+        'deqp_path': '<(DEPTH)/third_party/deqp/src',
+        'libpng_path': '<(DEPTH)/third_party/libpng',
+        'zlib_path': '<(DEPTH)/third_party/zlib',
+
+        'angle_build_deqp_libraries%' : 0,
+        'angle_build_deqp_gtest_support%' : 0,
+        'angle_build_deqp_executables%' : 0,
+        'angle_build_deqp_gtest_executables%' :0,
+
+        'clang_warning_flags':
+        [
+             # tcu::CommandLine has virtual functions but no virtual destructor
+            '-Wno-no-delete-non-virtual-dtor',
+        ],
+
+        'deqp_win_cflags':
+        [
+            '/EHsc',   # dEQP requires exceptions
+            '/wd4091', # typedef ignored when no variable is declared
+            '/wd4100',
+            '/wd4125', # decimal digit terminates octal escape sequence
+            '/wd4127', # conditional expression constant
+            '/wd4244', # possible loss of data
+            '/wd4245', # argument signed/unsigned mismatch
+            '/wd4297', # function assumed not to throw an exception but does
+            '/wd4389', # signed/unsigned mismatch
+            '/wd4510', # default constructor could not be generated
+            '/wd4512',
+            '/wd4610', # cannot be instantiated
+            '/wd4611', # setjmp interaction non-portable
+            '/wd4701', # potentially uninit used
+            '/wd4702', # unreachable code
+            '/wd4706', # assignment within conditional expression
+            '/wd4838', # conversion requires a narrowing conversion
+            '/wd4996', # deprecated
+        ],
+        'deqp_defines':
+        [
+            'DEQP_SUPPORT_GLES31=1',
+            'DEQP_SUPPORT_GLES3=1',
+            'DEQP_SUPPORT_GLES2=1',
+            'DEQP_SUPPORT_EGL=1',
+            'DEQP_TARGET_NAME="angle"',
+            'DEQP_GLES31_RUNTIME_LOAD=1',
+            'DEQP_GLES3_RUNTIME_LOAD=1',
+            'DEQP_GLES2_RUNTIME_LOAD=1',
+            'QP_SUPPORT_PNG=1',
+            '_HAS_EXCEPTIONS=1',
+        ],
+        'deqp_undefines':
+        [
+            'WIN32_LEAN_AND_MEAN',
+            'NOMINMAX',
+            '_HAS_EXCEPTIONS=0',
+        ],
+        'deqp_include_dirs':
+        [
+            '<(deqp_path)/executor',
+            '<(deqp_path)/execserver',
+            '<(deqp_path)/framework/common',
+            '<(deqp_path)/framework/delibs/debase',
+            '<(deqp_path)/framework/delibs/decpp',
+            '<(deqp_path)/framework/delibs/depool',
+            '<(deqp_path)/framework/delibs/dethread',
+            '<(deqp_path)/framework/delibs/deutil',
+            '<(deqp_path)/framework/delibs/destream',
+            '<(deqp_path)/framework/egl',
+            '<(deqp_path)/framework/egl/wrapper',
+            '<(deqp_path)/framework/opengl',
+            '<(deqp_path)/framework/opengl/simplereference',
+            '<(deqp_path)/framework/opengl/wrapper',
+            '<(deqp_path)/framework/platform/null',
+            '<(deqp_path)/framework/qphelper',
+            '<(deqp_path)/framework/randomshaders',
+            '<(deqp_path)/framework/referencerenderer',
+            '<(deqp_path)/modules/gles2',
+            '<(deqp_path)/modules/gles2/functional',
+            '<(deqp_path)/modules/gles2/accuracy',
+            '<(deqp_path)/modules/gles2/performance',
+            '<(deqp_path)/modules/gles2/stress',
+            '<(deqp_path)/modules/gles2/usecases',
+            '<(deqp_path)/modules/gles3',
+            '<(deqp_path)/modules/gles3/functional',
+            '<(deqp_path)/modules/gles3/accuracy',
+            '<(deqp_path)/modules/gles3/performance',
+            '<(deqp_path)/modules/gles3/stress',
+            '<(deqp_path)/modules/gles3/usecases',
+            '<(deqp_path)/modules/gles31',
+            '<(deqp_path)/modules/gles31/functional',
+            '<(deqp_path)/modules/gles31/stress',
+            '<(deqp_path)/modules/glshared',
+            '<(deqp_path)/modules/glusecases',
+            '<(libpng_path)',
+            '<(zlib_path)',
+        ],
+        'deqp_gles2_sources':
+        [
+            '<(deqp_path)/modules/gles2/accuracy/es2aAccuracyTests.cpp',
+            '<(deqp_path)/modules/gles2/accuracy/es2aAccuracyTests.hpp',
+            '<(deqp_path)/modules/gles2/accuracy/es2aTextureFilteringTests.cpp',
+            '<(deqp_path)/modules/gles2/accuracy/es2aTextureFilteringTests.hpp',
+            '<(deqp_path)/modules/gles2/accuracy/es2aTextureMipmapTests.cpp',
+            '<(deqp_path)/modules/gles2/accuracy/es2aTextureMipmapTests.hpp',
+            '<(deqp_path)/modules/gles2/accuracy/es2aVaryingInterpolationTests.cpp',
+            '<(deqp_path)/modules/gles2/accuracy/es2aVaryingInterpolationTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fApiCase.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fApiCase.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fAttribLocationTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fAttribLocationTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBlendTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBlendTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBooleanStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBooleanStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBufferObjectQueryTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBufferObjectQueryTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBufferTestUtil.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBufferTestUtil.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBufferWriteTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fBufferWriteTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fClippingTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fClippingTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fColorClearTest.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fColorClearTest.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDebugMarkerTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDebugMarkerTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDefaultVertexAttributeTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDefaultVertexAttributeTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDepthRangeTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDepthRangeTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDepthStencilClearTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDepthStencilClearTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDepthStencilTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDepthStencilTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDepthTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDepthTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDitheringTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDitheringTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDrawTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fDrawTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFboApiTest.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFboApiTest.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFboCompletenessTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFboCompletenessTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFboRenderTest.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFboRenderTest.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFboStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFboStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFloatStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFloatStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFlushFinishTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFlushFinishTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFragOpInteractionTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFragOpInteractionTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFunctionalTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fFunctionalTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fImplementationLimitTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fImplementationLimitTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fIntegerStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fIntegerStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fLifetimeTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fLifetimeTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fLightAmountTest.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fLightAmountTest.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fMultisampleTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fMultisampleTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeBufferApiTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeBufferApiTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeFragmentApiTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeFragmentApiTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeShaderApiTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeShaderApiTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeStateApiTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeStateApiTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeTextureApiTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeTextureApiTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeVertexArrayApiTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fNegativeVertexArrayApiTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fPolygonOffsetTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fPolygonOffsetTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fPrerequisiteTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fPrerequisiteTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fRandomFragmentOpTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fRandomFragmentOpTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fRandomShaderTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fRandomShaderTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fRasterizationTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fRasterizationTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fRboStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fRboStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fReadPixelsTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fReadPixelsTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fScissorTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fScissorTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderAlgorithmTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderAlgorithmTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderApiTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderApiTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderBuiltinVarTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderBuiltinVarTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderConstExprTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderConstExprTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderDiscardTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderDiscardTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderExecuteTest.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderExecuteTest.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderFragDataTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderFragDataTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderIndexingTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderIndexingTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderInvarianceTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderInvarianceTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderLoopTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderLoopTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderMatrixTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderMatrixTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderOperatorTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderOperatorTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderReturnTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderReturnTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderStructTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderStructTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderTextureFunctionTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fShaderTextureFunctionTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fStencilTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fStencilTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fStringQueryTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fStringQueryTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureCompletenessTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureCompletenessTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureFilteringTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureFilteringTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureFormatTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureFormatTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureMipmapTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureMipmapTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureSizeTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureSizeTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureSpecificationTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureSpecificationTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureUnitTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureUnitTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureWrapTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fTextureWrapTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fUniformApiTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fUniformApiTests.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fVertexArrayTest.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fVertexArrayTest.hpp',
+            '<(deqp_path)/modules/gles2/functional/es2fVertexTextureTests.cpp',
+            '<(deqp_path)/modules/gles2/functional/es2fVertexTextureTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pBlendTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pBlendTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pDrawCallBatchingTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pDrawCallBatchingTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pPerformanceTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pPerformanceTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pRedundantStateChangeTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pRedundantStateChangeTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderCompilationCases.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderCompilationCases.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderCompilerTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderCompilerTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderControlStatementTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderControlStatementTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderOperatorTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderOperatorTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderOptimizationTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pShaderOptimizationTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pStateChangeCallTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pStateChangeCallTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pStateChangeTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pStateChangeTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureCases.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureCases.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureCountTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureCountTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureFilteringTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureFilteringTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureFormatTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureFormatTests.hpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureUploadTests.cpp',
+            '<(deqp_path)/modules/gles2/performance/es2pTextureUploadTests.hpp',
+            '<(deqp_path)/modules/gles2/stress/es2sDrawTests.cpp',
+            '<(deqp_path)/modules/gles2/stress/es2sDrawTests.hpp',
+            '<(deqp_path)/modules/gles2/stress/es2sLongRunningTests.cpp',
+            '<(deqp_path)/modules/gles2/stress/es2sLongRunningTests.hpp',
+            '<(deqp_path)/modules/gles2/stress/es2sMemoryTests.cpp',
+            '<(deqp_path)/modules/gles2/stress/es2sMemoryTests.hpp',
+            '<(deqp_path)/modules/gles2/stress/es2sSpecialFloatTests.cpp',
+            '<(deqp_path)/modules/gles2/stress/es2sSpecialFloatTests.hpp',
+            '<(deqp_path)/modules/gles2/stress/es2sStressTests.cpp',
+            '<(deqp_path)/modules/gles2/stress/es2sStressTests.hpp',
+            '<(deqp_path)/modules/gles2/stress/es2sVertexArrayTests.cpp',
+            '<(deqp_path)/modules/gles2/stress/es2sVertexArrayTests.hpp',
+            '<(deqp_path)/modules/gles2/tes2CapabilityTests.cpp',
+            '<(deqp_path)/modules/gles2/tes2CapabilityTests.hpp',
+            '<(deqp_path)/modules/gles2/tes2Context.cpp',
+            '<(deqp_path)/modules/gles2/tes2Context.hpp',
+            '<(deqp_path)/modules/gles2/tes2InfoTests.cpp',
+            '<(deqp_path)/modules/gles2/tes2InfoTests.hpp',
+            '<(deqp_path)/modules/gles2/tes2TestCase.cpp',
+            '<(deqp_path)/modules/gles2/tes2TestCase.hpp',
+            '<(deqp_path)/modules/gles2/tes2TestPackage.cpp',
+            '<(deqp_path)/modules/gles2/tes2TestPackage.hpp',
+            '<(deqp_path)/modules/gles2/tes2TestPackageEntry.cpp',
+        ],
+        'deqp_gles3_sources':
+        [
+            '<(deqp_path)/modules/gles3/accuracy/es3aAccuracyTests.cpp',
+            '<(deqp_path)/modules/gles3/accuracy/es3aAccuracyTests.hpp',
+            '<(deqp_path)/modules/gles3/accuracy/es3aTextureFilteringTests.cpp',
+            '<(deqp_path)/modules/gles3/accuracy/es3aTextureFilteringTests.hpp',
+            '<(deqp_path)/modules/gles3/accuracy/es3aTextureMipmapTests.cpp',
+            '<(deqp_path)/modules/gles3/accuracy/es3aTextureMipmapTests.hpp',
+            '<(deqp_path)/modules/gles3/accuracy/es3aVaryingInterpolationTests.cpp',
+            '<(deqp_path)/modules/gles3/accuracy/es3aVaryingInterpolationTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fApiCase.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fApiCase.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fASTCDecompressionCases.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fASTCDecompressionCases.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fAttribLocationTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fAttribLocationTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBlendTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBlendTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBooleanStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBooleanStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBufferCopyTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBufferCopyTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBufferMapTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBufferMapTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBufferObjectQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBufferObjectQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBufferWriteTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBufferWriteTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBuiltinPrecisionTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fBuiltinPrecisionTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fClippingTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fClippingTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fColorClearTest.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fColorClearTest.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fCompressedTextureTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fCompressedTextureTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDefaultVertexArrayObjectTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDefaultVertexArrayObjectTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDefaultVertexAttributeTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDefaultVertexAttributeTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDepthStencilClearTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDepthStencilClearTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDepthStencilTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDepthStencilTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDepthTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDepthTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDitheringTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDitheringTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDrawTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fDrawTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboApiTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboApiTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboColorbufferTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboColorbufferTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboCompletenessTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboCompletenessTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboDepthbufferTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboDepthbufferTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboInvalidateTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboInvalidateTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboMultisampleTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboMultisampleTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboRenderTest.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboRenderTest.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboStencilbufferTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboStencilbufferTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboTestCase.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboTestCase.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboTestUtil.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFboTestUtil.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFloatStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFloatStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFlushFinishTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFlushFinishTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFragDepthTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFragDepthTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFragmentOutputTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFragmentOutputTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFragOpInteractionTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFragOpInteractionTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFramebufferBlitTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFramebufferBlitTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFunctionalTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fFunctionalTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fImplementationLimitTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fImplementationLimitTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fIndexedStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fIndexedStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fInstancedRenderingTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fInstancedRenderingTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fInteger64StateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fInteger64StateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fIntegerStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fIntegerStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fInternalFormatQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fInternalFormatQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fLifetimeTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fLifetimeTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fMultisampleTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fMultisampleTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeBufferApiTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeBufferApiTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeFragmentApiTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeFragmentApiTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeShaderApiTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeShaderApiTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeStateApiTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeStateApiTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeTextureApiTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeTextureApiTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeVertexArrayApiTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fNegativeVertexArrayApiTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fOcclusionQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fOcclusionQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fPixelBufferObjectTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fPixelBufferObjectTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fPolygonOffsetTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fPolygonOffsetTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fPrerequisiteTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fPrerequisiteTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fPrimitiveRestartTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fPrimitiveRestartTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRandomFragmentOpTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRandomFragmentOpTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRandomShaderTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRandomShaderTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRasterizationTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRasterizationTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRasterizerDiscardTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRasterizerDiscardTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRboStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fRboStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fReadPixelsTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fReadPixelsTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fSamplerObjectTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fSamplerObjectTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fSamplerStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fSamplerStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fScissorTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fScissorTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderApiTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderApiTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderBuiltinVarTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderBuiltinVarTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderCommonFunctionTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderCommonFunctionTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderConstExprTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderConstExprTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderDerivateTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderDerivateTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderDiscardTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderDiscardTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderFragDataTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderFragDataTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderIndexingTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderIndexingTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderInvarianceTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderInvarianceTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderLoopTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderLoopTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderMatrixTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderMatrixTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderOperatorTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderOperatorTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderPackingFunctionTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderPackingFunctionTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderPrecisionTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderPrecisionTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderReturnTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderReturnTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderStructTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderStructTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderSwitchTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderSwitchTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderTextureFunctionTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fShaderTextureFunctionTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fStencilTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fStencilTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fStringQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fStringQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fSyncTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fSyncTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureFilteringTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureFilteringTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureFormatTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureFormatTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureMipmapTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureMipmapTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureShadowTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureShadowTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureSizeTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureSizeTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureSpecificationTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureSpecificationTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureSwizzleTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureSwizzleTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureUnitTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureUnitTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureWrapTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTextureWrapTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTransformFeedbackTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fTransformFeedbackTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fUniformApiTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fUniformApiTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fUniformBlockTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fUniformBlockTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fVertexArrayObjectTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fVertexArrayObjectTests.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fVertexArrayTest.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fVertexArrayTest.hpp',
+            '<(deqp_path)/modules/gles3/functional/es3fVertexTextureTests.cpp',
+            '<(deqp_path)/modules/gles3/functional/es3fVertexTextureTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pBlendTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pBlendTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pBufferDataUploadTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pBufferDataUploadTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pDepthTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pDepthTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pPerformanceTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pPerformanceTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pRedundantStateChangeTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pRedundantStateChangeTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderCompilationCases.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderCompilationCases.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderCompilerTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderCompilerTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderControlStatementTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderControlStatementTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderOperatorTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderOperatorTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderOptimizationTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pShaderOptimizationTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pStateChangeCallTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pStateChangeCallTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pStateChangeTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pStateChangeTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pTextureCases.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pTextureCases.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pTextureCountTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pTextureCountTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pTextureFilteringTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pTextureFilteringTests.hpp',
+            '<(deqp_path)/modules/gles3/performance/es3pTextureFormatTests.cpp',
+            '<(deqp_path)/modules/gles3/performance/es3pTextureFormatTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sDrawTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sDrawTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sLongRunningShaderTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sLongRunningShaderTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sLongRunningTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sLongRunningTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sLongShaderTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sLongShaderTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sMemoryTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sMemoryTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sOcclusionQueryTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sOcclusionQueryTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sSpecialFloatTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sSpecialFloatTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sStressTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sStressTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sSyncTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sSyncTests.hpp',
+            '<(deqp_path)/modules/gles3/stress/es3sVertexArrayTests.cpp',
+            '<(deqp_path)/modules/gles3/stress/es3sVertexArrayTests.hpp',
+            '<(deqp_path)/modules/gles3/tes3Context.cpp',
+            '<(deqp_path)/modules/gles3/tes3Context.hpp',
+            '<(deqp_path)/modules/gles3/tes3InfoTests.cpp',
+            '<(deqp_path)/modules/gles3/tes3InfoTests.hpp',
+            '<(deqp_path)/modules/gles3/tes3TestCase.cpp',
+            '<(deqp_path)/modules/gles3/tes3TestCase.hpp',
+            '<(deqp_path)/modules/gles3/tes3TestPackage.cpp',
+            '<(deqp_path)/modules/gles3/tes3TestPackage.hpp',
+            '<(deqp_path)/modules/gles3/tes3TestPackageEntry.cpp',
+        ],
+        'deqp_gles31_sources':
+        [
+            '<(deqp_path)/modules/gles31/functional/es31fAdvancedBlendTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fAdvancedBlendTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fAndroidExtensionPackES31ATests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fAndroidExtensionPackES31ATests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fAtomicCounterTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fAtomicCounterTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fBasicComputeShaderTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fBasicComputeShaderTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fBooleanStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fBooleanStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fBuiltinPrecisionTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fBuiltinPrecisionTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fComputeShaderBuiltinVarTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fComputeShaderBuiltinVarTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fCopyImageTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fCopyImageTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fDebugTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fDebugTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fDefaultVertexArrayObjectTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fDefaultVertexArrayObjectTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fDrawBuffersIndexedTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fDrawBuffersIndexedTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fDrawTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fDrawTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFboColorbufferTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFboColorbufferTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFboNoAttachmentTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFboNoAttachmentTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFboTestCase.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFboTestCase.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFboTestUtil.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFboTestUtil.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFramebufferDefaultStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFramebufferDefaultStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFunctionalTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fFunctionalTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fGeometryShaderTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fGeometryShaderTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fIndexedStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fIndexedStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fIndirectComputeDispatchTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fIndirectComputeDispatchTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fInfoLogQueryShared.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fInfoLogQueryShared.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fIntegerStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fIntegerStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fInternalFormatQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fInternalFormatQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fLayoutBindingTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fLayoutBindingTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fMultisampleShaderRenderCase.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fMultisampleShaderRenderCase.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fMultisampleTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fMultisampleTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeAdvancedBlendEquationTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeAdvancedBlendEquationTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeAtomicCounterTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeAtomicCounterTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeBufferApiTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeBufferApiTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeFragmentApiTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeFragmentApiTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativePreciseTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativePreciseTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeShaderApiTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeShaderApiTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeShaderDirectiveTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeShaderDirectiveTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeShaderFunctionTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeShaderFunctionTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeShaderImageLoadStoreTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeShaderImageLoadStoreTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeStateApiTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeStateApiTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeTestShared.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeTestShared.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeTextureApiTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeTextureApiTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeVertexArrayApiTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fNegativeVertexArrayApiTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fOpaqueTypeIndexingTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fOpaqueTypeIndexingTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fPrimitiveBoundingBoxTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fPrimitiveBoundingBoxTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramInterfaceDefinition.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramInterfaceQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramPipelineStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramPipelineStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramUniformTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fProgramUniformTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSSBOArrayLengthTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSSBOArrayLengthTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSSBOLayoutCase.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSSBOLayoutCase.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSSBOLayoutTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSSBOLayoutTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSampleShadingTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSampleShadingTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSampleVariableTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSampleVariableTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSamplerStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSamplerStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSeparateShaderTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSeparateShaderTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderAtomicOpTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderAtomicOpTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderBuiltinConstantTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderBuiltinConstantTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderCommonFunctionTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderCommonFunctionTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderHelperInvocationTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderHelperInvocationTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderImageLoadStoreTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderImageLoadStoreTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderIntegerFunctionTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderIntegerFunctionTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderMultisampleInterpolationStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderMultisampleInterpolationStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderMultisampleInterpolationTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderMultisampleInterpolationTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderPackingFunctionTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderPackingFunctionTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderSharedVarTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderSharedVarTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderTextureSizeTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fShaderTextureSizeTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fStencilTexturingTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fStencilTexturingTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSynchronizationTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fSynchronizationTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTessellationGeometryInteractionTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTessellationGeometryInteractionTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTessellationTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTessellationTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureBorderClampTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureBorderClampTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureBufferTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureBufferTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureFilteringTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureFilteringTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureFormatTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureFormatTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureGatherTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureGatherTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureLevelStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureLevelStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureMultisampleTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureMultisampleTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureSpecificationTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureSpecificationTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fTextureStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fUniformBlockTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fUniformBlockTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fUniformLocationTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fUniformLocationTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fVertexAttributeBindingStateQueryTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fVertexAttributeBindingStateQueryTests.hpp',
+            '<(deqp_path)/modules/gles31/functional/es31fVertexAttributeBindingTests.cpp',
+            '<(deqp_path)/modules/gles31/functional/es31fVertexAttributeBindingTests.hpp',
+            '<(deqp_path)/modules/gles31/stress/es31sDrawTests.cpp',
+            '<(deqp_path)/modules/gles31/stress/es31sDrawTests.hpp',
+            '<(deqp_path)/modules/gles31/stress/es31sStressTests.cpp',
+            '<(deqp_path)/modules/gles31/stress/es31sStressTests.hpp',
+            '<(deqp_path)/modules/gles31/stress/es31sTessellationGeometryInteractionTests.cpp',
+            '<(deqp_path)/modules/gles31/stress/es31sTessellationGeometryInteractionTests.hpp',
+            '<(deqp_path)/modules/gles31/stress/es31sVertexAttributeBindingTests.cpp',
+            '<(deqp_path)/modules/gles31/stress/es31sVertexAttributeBindingTests.hpp',
+            '<(deqp_path)/modules/gles31/tes31Context.cpp',
+            '<(deqp_path)/modules/gles31/tes31Context.hpp',
+            '<(deqp_path)/modules/gles31/tes31InfoTests.cpp',
+            '<(deqp_path)/modules/gles31/tes31InfoTests.hpp',
+            '<(deqp_path)/modules/gles31/tes31TestCase.cpp',
+            '<(deqp_path)/modules/gles31/tes31TestCase.hpp',
+            '<(deqp_path)/modules/gles31/tes31TestPackage.cpp',
+            '<(deqp_path)/modules/gles31/tes31TestPackage.hpp',
+            '<(deqp_path)/modules/gles31/tes31TestPackageEntry.cpp'
+        ],
+        'deqp_egl_sources':
+        [
+            '<(deqp_path)/modules/egl/teglAndroidUtil.cpp',
+            '<(deqp_path)/modules/egl/teglAndroidUtil.hpp',
+            '<(deqp_path)/modules/egl/teglApiCase.cpp',
+            '<(deqp_path)/modules/egl/teglApiCase.hpp',
+            '<(deqp_path)/modules/egl/teglBufferAgeTests.cpp',
+            '<(deqp_path)/modules/egl/teglBufferAgeTests.hpp',
+            '<(deqp_path)/modules/egl/teglChooseConfigReference.cpp',
+            '<(deqp_path)/modules/egl/teglChooseConfigReference.hpp',
+            '<(deqp_path)/modules/egl/teglChooseConfigTests.cpp',
+            '<(deqp_path)/modules/egl/teglChooseConfigTests.hpp',
+            '<(deqp_path)/modules/egl/teglClientExtensionTests.cpp',
+            '<(deqp_path)/modules/egl/teglClientExtensionTests.hpp',
+            '<(deqp_path)/modules/egl/teglColorClearCase.cpp',
+            '<(deqp_path)/modules/egl/teglColorClearCase.hpp',
+            '<(deqp_path)/modules/egl/teglColorClearTests.cpp',
+            '<(deqp_path)/modules/egl/teglColorClearTests.hpp',
+            '<(deqp_path)/modules/egl/teglConfigList.cpp',
+            '<(deqp_path)/modules/egl/teglConfigList.hpp',
+            '<(deqp_path)/modules/egl/teglCreateContextExtTests.cpp',
+            '<(deqp_path)/modules/egl/teglCreateContextExtTests.hpp',
+            '<(deqp_path)/modules/egl/teglCreateContextTests.cpp',
+            '<(deqp_path)/modules/egl/teglCreateContextTests.hpp',
+            '<(deqp_path)/modules/egl/teglCreateSurfaceTests.cpp',
+            '<(deqp_path)/modules/egl/teglCreateSurfaceTests.hpp',
+            '<(deqp_path)/modules/egl/teglGetProcAddressTests.cpp',
+            '<(deqp_path)/modules/egl/teglGetProcAddressTests.hpp',
+            '<(deqp_path)/modules/egl/teglGLES1RenderUtil.cpp',
+            '<(deqp_path)/modules/egl/teglGLES1RenderUtil.hpp',
+            '<(deqp_path)/modules/egl/teglGLES2RenderUtil.cpp',
+            '<(deqp_path)/modules/egl/teglGLES2RenderUtil.hpp',
+            '<(deqp_path)/modules/egl/teglGLES2SharedRenderingPerfTests.cpp',
+            '<(deqp_path)/modules/egl/teglGLES2SharedRenderingPerfTests.hpp',
+            '<(deqp_path)/modules/egl/teglGLES2SharingTests.cpp',
+            '<(deqp_path)/modules/egl/teglGLES2SharingTests.hpp',
+            '<(deqp_path)/modules/egl/teglGLES2SharingThreadedTests.cpp',
+            '<(deqp_path)/modules/egl/teglGLES2SharingThreadedTests.hpp',
+            '<(deqp_path)/modules/egl/teglImageFormatTests.cpp',
+            '<(deqp_path)/modules/egl/teglImageFormatTests.hpp',
+            '<(deqp_path)/modules/egl/teglImageTests.cpp',
+            '<(deqp_path)/modules/egl/teglImageTests.hpp',
+            '<(deqp_path)/modules/egl/teglImageUtil.cpp',
+            '<(deqp_path)/modules/egl/teglImageUtil.hpp',
+            '<(deqp_path)/modules/egl/teglInfoTests.cpp',
+            '<(deqp_path)/modules/egl/teglInfoTests.hpp',
+            '<(deqp_path)/modules/egl/teglMakeCurrentPerfTests.cpp',
+            '<(deqp_path)/modules/egl/teglMakeCurrentPerfTests.hpp',
+            '<(deqp_path)/modules/egl/teglMemoryStressTests.cpp',
+            '<(deqp_path)/modules/egl/teglMemoryStressTests.hpp',
+            '<(deqp_path)/modules/egl/teglMultiContextTests.cpp',
+            '<(deqp_path)/modules/egl/teglMultiContextTests.hpp',
+            '<(deqp_path)/modules/egl/teglMultiThreadTests.cpp',
+            '<(deqp_path)/modules/egl/teglMultiThreadTests.hpp',
+            '<(deqp_path)/modules/egl/teglMutableRenderBufferTests.cpp',
+            '<(deqp_path)/modules/egl/teglMutableRenderBufferTests.hpp',
+            '<(deqp_path)/modules/egl/teglNativeColorMappingTests.cpp',
+            '<(deqp_path)/modules/egl/teglNativeColorMappingTests.hpp',
+            '<(deqp_path)/modules/egl/teglNativeCoordMappingTests.cpp',
+            '<(deqp_path)/modules/egl/teglNativeCoordMappingTests.hpp',
+            '<(deqp_path)/modules/egl/teglNegativeApiTests.cpp',
+            '<(deqp_path)/modules/egl/teglNegativeApiTests.hpp',
+            '<(deqp_path)/modules/egl/teglNegativePartialUpdateTests.cpp',
+            '<(deqp_path)/modules/egl/teglNegativePartialUpdateTests.hpp',
+            '<(deqp_path)/modules/egl/teglPreservingSwapTests.cpp',
+            '<(deqp_path)/modules/egl/teglPreservingSwapTests.hpp',
+            '<(deqp_path)/modules/egl/teglPartialUpdateTests.cpp',
+            '<(deqp_path)/modules/egl/teglPartialUpdateTests.hpp',
+            '<(deqp_path)/modules/egl/teglQueryConfigTests.cpp',
+            '<(deqp_path)/modules/egl/teglQueryConfigTests.hpp',
+            '<(deqp_path)/modules/egl/teglQueryContextTests.cpp',
+            '<(deqp_path)/modules/egl/teglQueryContextTests.hpp',
+            '<(deqp_path)/modules/egl/teglQuerySurfaceTests.cpp',
+            '<(deqp_path)/modules/egl/teglQuerySurfaceTests.hpp',
+            '<(deqp_path)/modules/egl/teglRenderCase.cpp',
+            '<(deqp_path)/modules/egl/teglRenderCase.hpp',
+            '<(deqp_path)/modules/egl/teglRenderTests.cpp',
+            '<(deqp_path)/modules/egl/teglRenderTests.hpp',
+            '<(deqp_path)/modules/egl/teglResizeTests.cpp',
+            '<(deqp_path)/modules/egl/teglResizeTests.hpp',
+            '<(deqp_path)/modules/egl/teglSimpleConfigCase.cpp',
+            '<(deqp_path)/modules/egl/teglSimpleConfigCase.hpp',
+            '<(deqp_path)/modules/egl/teglSurfacelessContextTests.cpp',
+            '<(deqp_path)/modules/egl/teglSurfacelessContextTests.hpp',
+            '<(deqp_path)/modules/egl/teglSwapBuffersTests.cpp',
+            '<(deqp_path)/modules/egl/teglSwapBuffersTests.hpp',
+            '<(deqp_path)/modules/egl/teglSwapBuffersWithDamageTests.cpp',
+            '<(deqp_path)/modules/egl/teglSwapBuffersWithDamageTests.hpp',
+            '<(deqp_path)/modules/egl/teglSyncTests.cpp',
+            '<(deqp_path)/modules/egl/teglSyncTests.hpp',
+            '<(deqp_path)/modules/egl/teglTestCase.cpp',
+            '<(deqp_path)/modules/egl/teglTestCase.hpp',
+            '<(deqp_path)/modules/egl/teglTestPackage.cpp',
+            '<(deqp_path)/modules/egl/teglTestPackage.hpp',
+            '<(deqp_path)/modules/egl/teglTestPackageEntry.cpp',
+            '<(deqp_path)/modules/egl/teglThreadCleanUpTests.cpp',
+            '<(deqp_path)/modules/egl/teglThreadCleanUpTests.hpp',
+            '<(deqp_path)/modules/egl/teglVGRenderUtil.cpp',
+            '<(deqp_path)/modules/egl/teglVGRenderUtil.hpp',
+        ],
+        'deqp_libtester_decpp_sources':
+        [
+            '<(deqp_path)/framework/delibs/decpp/deArrayBuffer.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deBlockBuffer.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deCommandLine.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deDefs.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deDirectoryIterator.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deDynamicLibrary.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deFilePath.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deMemPool.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deMutex.cpp',
+            '<(deqp_path)/framework/delibs/decpp/dePoolArray.cpp',
+            '<(deqp_path)/framework/delibs/decpp/dePoolString.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deProcess.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deRandom.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deRingBuffer.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deSemaphore.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deSharedPtr.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deSha1.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deSocket.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deSTLUtil.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deStringUtil.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deThread.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deThreadLocal.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deThreadSafeRingBuffer.cpp',
+            '<(deqp_path)/framework/delibs/decpp/deUniquePtr.cpp',
+        ],
+        'deqp_libtester_sources':
+        [
+            '<(deqp_path)/execserver/xsDefs.cpp',
+            '<(deqp_path)/execserver/xsExecutionServer.cpp',
+            '<(deqp_path)/execserver/xsPosixFileReader.cpp',
+            '<(deqp_path)/execserver/xsPosixTestProcess.cpp',
+            '<(deqp_path)/execserver/xsProtocol.cpp',
+            '<(deqp_path)/execserver/xsTcpServer.cpp',
+            '<(deqp_path)/execserver/xsTestDriver.cpp',
+            '<(deqp_path)/execserver/xsTestProcess.cpp',
+            '<(deqp_path)/executor/xeBatchExecutor.cpp',
+            '<(deqp_path)/executor/xeBatchResult.cpp',
+            '<(deqp_path)/executor/xeCallQueue.cpp',
+            '<(deqp_path)/executor/xeCommLink.cpp',
+            '<(deqp_path)/executor/xeContainerFormatParser.cpp',
+            '<(deqp_path)/executor/xeDefs.cpp',
+            '<(deqp_path)/executor/xeLocalTcpIpLink.cpp',
+            '<(deqp_path)/executor/xeTcpIpLink.cpp',
+            '<(deqp_path)/executor/xeTestCase.cpp',
+            '<(deqp_path)/executor/xeTestCaseListParser.cpp',
+            '<(deqp_path)/executor/xeTestCaseResult.cpp',
+            '<(deqp_path)/executor/xeTestLogParser.cpp',
+            '<(deqp_path)/executor/xeTestLogWriter.cpp',
+            '<(deqp_path)/executor/xeTestResultParser.cpp',
+            '<(deqp_path)/executor/xeXMLParser.cpp',
+            '<(deqp_path)/executor/xeXMLWriter.cpp',
+            '<(deqp_path)/framework/common/tcuApp.cpp',
+            '<(deqp_path)/framework/common/tcuAstcUtil.cpp',
+            '<(deqp_path)/framework/common/tcuBilinearImageCompare.cpp',
+            '<(deqp_path)/framework/common/tcuCommandLine.cpp',
+            '<(deqp_path)/framework/common/tcuCompressedTexture.cpp',
+            '<(deqp_path)/framework/common/tcuCPUWarmup.cpp',
+            '<(deqp_path)/framework/common/tcuDefs.cpp',
+            '<(deqp_path)/framework/common/tcuEither.cpp',
+            '<(deqp_path)/framework/common/tcuFactoryRegistry.cpp',
+            '<(deqp_path)/framework/common/tcuFloatFormat.cpp',
+            '<(deqp_path)/framework/common/tcuFunctionLibrary.cpp',
+            '<(deqp_path)/framework/common/tcuFuzzyImageCompare.cpp',
+            '<(deqp_path)/framework/common/tcuImageCompare.cpp',
+            '<(deqp_path)/framework/common/tcuImageIO.cpp',
+            '<(deqp_path)/framework/common/tcuInterval.cpp',
+            '<(deqp_path)/framework/common/tcuPlatform.cpp',
+            '<(deqp_path)/framework/common/tcuRandomValueIterator.cpp',
+            '<(deqp_path)/framework/common/tcuRasterizationVerifier.cpp',
+            '<(deqp_path)/framework/common/tcuRasterizationVerifier.hpp',
+            '<(deqp_path)/framework/common/tcuRenderTarget.cpp',
+            '<(deqp_path)/framework/common/tcuResource.cpp',
+            '<(deqp_path)/framework/common/tcuResultCollector.cpp',
+            '<(deqp_path)/framework/common/tcuRGBA.cpp',
+            '<(deqp_path)/framework/common/tcuStringTemplate.cpp',
+            '<(deqp_path)/framework/common/tcuSurface.cpp',
+            '<(deqp_path)/framework/common/tcuSurfaceAccess.cpp',
+            '<(deqp_path)/framework/common/tcuSurfaceAccess.hpp',
+            '<(deqp_path)/framework/common/tcuTestCase.cpp',
+            '<(deqp_path)/framework/common/tcuTestContext.cpp',
+            '<(deqp_path)/framework/common/tcuTestHierarchyIterator.cpp',
+            '<(deqp_path)/framework/common/tcuTestHierarchyUtil.cpp',
+            '<(deqp_path)/framework/common/tcuTestLog.cpp',
+            '<(deqp_path)/framework/common/tcuTestPackage.cpp',
+            '<(deqp_path)/framework/common/tcuTestSessionExecutor.cpp',
+            '<(deqp_path)/framework/common/tcuTexCompareVerifier.cpp',
+            '<(deqp_path)/framework/common/tcuTexLookupVerifier.cpp',
+            '<(deqp_path)/framework/common/tcuTexture.cpp',
+            '<(deqp_path)/framework/common/tcuTextureUtil.cpp',
+            '<(deqp_path)/framework/common/tcuTexVerifierUtil.cpp',
+            '<(deqp_path)/framework/common/tcuThreadUtil.cpp',
+            '<(deqp_path)/framework/common/tcuSeedBuilder.cpp',
+            '<(deqp_path)/framework/delibs/debase/deDefs.c',
+            '<(deqp_path)/framework/delibs/debase/deFloat16.c',
+            '<(deqp_path)/framework/delibs/debase/deInt32.c',
+            '<(deqp_path)/framework/delibs/debase/deInt32Test.c',
+            '<(deqp_path)/framework/delibs/debase/deMath.c',
+            '<(deqp_path)/framework/delibs/debase/deMemory.c',
+            '<(deqp_path)/framework/delibs/debase/deRandom.c',
+            '<(deqp_path)/framework/delibs/debase/deString.c',
+            '<(deqp_path)/framework/delibs/debase/deSha1.c',
+            '<(deqp_path)/framework/delibs/deimage/deImage.c',
+            '<(deqp_path)/framework/delibs/deimage/deTarga.c',
+            '<(deqp_path)/framework/delibs/depool/deMemPool.c',
+            '<(deqp_path)/framework/delibs/depool/dePoolArray.c',
+            '<(deqp_path)/framework/delibs/depool/dePoolHashArray.c',
+            '<(deqp_path)/framework/delibs/depool/dePoolHash.c',
+            '<(deqp_path)/framework/delibs/depool/dePoolHashSet.c',
+            '<(deqp_path)/framework/delibs/depool/dePoolHeap.c',
+            '<(deqp_path)/framework/delibs/depool/dePoolMultiSet.c',
+            '<(deqp_path)/framework/delibs/depool/dePoolSet.c',
+            '<(deqp_path)/framework/delibs/depool/dePoolStringBuilder.c',
+            '<(deqp_path)/framework/delibs/depool/dePoolTest.c',
+            '<(deqp_path)/framework/delibs/destream/deFileStream.c',
+            '<(deqp_path)/framework/delibs/destream/deRingbuffer.c',
+            '<(deqp_path)/framework/delibs/destream/deStreamCpyThread.c',
+            '<(deqp_path)/framework/delibs/destream/deThreadStream.c',
+            '<(deqp_path)/framework/delibs/dethread/deAtomic.c',
+            '<(deqp_path)/framework/delibs/dethread/deSingleton.c',
+            '<(deqp_path)/framework/delibs/dethread/deThreadTest.c',
+            '<(deqp_path)/framework/delibs/deutil/deClock.c',
+            '<(deqp_path)/framework/delibs/deutil/deCommandLine.c',
+            '<(deqp_path)/framework/delibs/deutil/deDynamicLibrary.c',
+            '<(deqp_path)/framework/delibs/deutil/deFile.c',
+            '<(deqp_path)/framework/delibs/deutil/deProcess.c',
+            '<(deqp_path)/framework/delibs/deutil/deSocket.c',
+            '<(deqp_path)/framework/delibs/deutil/deTimer.c',
+            '<(deqp_path)/framework/delibs/deutil/deTimerTest.c',
+            '<(deqp_path)/framework/egl/egluCallLogWrapper.cpp',
+            '<(deqp_path)/framework/egl/egluConfigFilter.cpp',
+            '<(deqp_path)/framework/egl/egluConfigInfo.cpp',
+            '<(deqp_path)/framework/egl/egluDefs.cpp',
+            '<(deqp_path)/framework/egl/egluGLContextFactory.cpp',
+            '<(deqp_path)/framework/egl/egluGLFunctionLoader.cpp',
+            '<(deqp_path)/framework/egl/egluGLUtil.cpp',
+            '<(deqp_path)/framework/egl/egluNativeDisplay.cpp',
+            '<(deqp_path)/framework/egl/egluNativePixmap.cpp',
+            '<(deqp_path)/framework/egl/egluNativeWindow.cpp',
+            '<(deqp_path)/framework/egl/egluPlatform.cpp',
+            '<(deqp_path)/framework/egl/egluStaticESLibrary.cpp',
+            '<(deqp_path)/framework/egl/egluStrUtil.cpp',
+            '<(deqp_path)/framework/egl/egluUnique.cpp',
+            '<(deqp_path)/framework/egl/egluUtil.cpp',
+            '<(deqp_path)/framework/egl/wrapper/eglwDefs.cpp',
+            '<(deqp_path)/framework/egl/wrapper/eglwFunctions.cpp',
+            '<(deqp_path)/framework/egl/wrapper/eglwLibrary.cpp',
+            '<(deqp_path)/framework/opengl/gluCallLogWrapper.cpp',
+            '<(deqp_path)/framework/opengl/gluContextFactory.cpp',
+            '<(deqp_path)/framework/opengl/gluContextInfo.cpp',
+            '<(deqp_path)/framework/opengl/gluDefs.cpp',
+            '<(deqp_path)/framework/opengl/gluDrawUtil.cpp',
+            '<(deqp_path)/framework/opengl/gluDummyRenderContext.cpp',
+            '<(deqp_path)/framework/opengl/gluES3PlusWrapperContext.cpp',
+            '<(deqp_path)/framework/opengl/gluFboRenderContext.cpp',
+            '<(deqp_path)/framework/opengl/gluObjectWrapper.cpp',
+            '<(deqp_path)/framework/opengl/gluPixelTransfer.cpp',
+            '<(deqp_path)/framework/opengl/gluPlatform.cpp',
+            '<(deqp_path)/framework/opengl/gluProgramInterfaceQuery.cpp',
+            '<(deqp_path)/framework/opengl/gluRenderConfig.cpp',
+            '<(deqp_path)/framework/opengl/gluRenderContext.cpp',
+            '<(deqp_path)/framework/opengl/gluShaderLibrary.cpp',
+            '<(deqp_path)/framework/opengl/gluShaderProgram.cpp',
+            '<(deqp_path)/framework/opengl/gluShaderUtil.cpp',
+            '<(deqp_path)/framework/opengl/gluStateReset.cpp',
+            '<(deqp_path)/framework/opengl/gluStrUtil.cpp',
+            '<(deqp_path)/framework/opengl/gluTexture.cpp',
+            '<(deqp_path)/framework/opengl/gluTextureUtil.cpp',
+            '<(deqp_path)/framework/opengl/gluTextureTestUtil.cpp',
+            '<(deqp_path)/framework/opengl/gluTextureTestUtil.hpp',
+            '<(deqp_path)/framework/opengl/gluVarType.cpp',
+            '<(deqp_path)/framework/opengl/gluVarTypeUtil.cpp',
+            '<(deqp_path)/framework/opengl/simplereference/sglrContext.cpp',
+            '<(deqp_path)/framework/opengl/simplereference/sglrContextUtil.cpp',
+            '<(deqp_path)/framework/opengl/simplereference/sglrContextWrapper.cpp',
+            '<(deqp_path)/framework/opengl/simplereference/sglrGLContext.cpp',
+            '<(deqp_path)/framework/opengl/simplereference/sglrReferenceContext.cpp',
+            '<(deqp_path)/framework/opengl/simplereference/sglrReferenceUtils.cpp',
+            '<(deqp_path)/framework/opengl/simplereference/sglrShaderProgram.cpp',
+            '<(deqp_path)/framework/opengl/wrapper/glwDefs.cpp',
+            '<(deqp_path)/framework/opengl/wrapper/glwFunctions.cpp',
+            '<(deqp_path)/framework/opengl/wrapper/glwInitES20Direct.cpp',
+            '<(deqp_path)/framework/opengl/wrapper/glwInitES30Direct.cpp',
+            '<(deqp_path)/framework/opengl/wrapper/glwInitFunctions.cpp',
+            '<(deqp_path)/framework/opengl/wrapper/glwWrapper.cpp',
+            '<(deqp_path)/framework/platform/null/tcuNullContextFactory.cpp',
+            '<(deqp_path)/framework/platform/null/tcuNullContextFactory.hpp',
+            '<(deqp_path)/framework/platform/null/tcuNullRenderContext.cpp',
+            '<(deqp_path)/framework/qphelper/qpCrashHandler.c',
+            '<(deqp_path)/framework/qphelper/qpDebugOut.c',
+            '<(deqp_path)/framework/qphelper/qpInfo.c',
+            # TODO(jmadill): Restore this when we upstream the change.
+            #'<(deqp_path)/framework/qphelper/qpTestLog.c',
+            '<(deqp_path)/framework/qphelper/qpWatchDog.c',
+            '<(deqp_path)/framework/qphelper/qpXmlWriter.c',
+            '<(deqp_path)/framework/randomshaders/rsgBinaryOps.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgBuiltinFunctions.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgDefs.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgExecutionContext.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgExpression.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgExpressionGenerator.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgFunctionGenerator.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgGeneratorState.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgNameAllocator.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgParameters.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgPrettyPrinter.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgProgramExecutor.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgProgramGenerator.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgSamplers.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgShader.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgShaderGenerator.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgStatement.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgToken.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgUtils.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgVariable.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgVariableManager.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgVariableType.cpp',
+            '<(deqp_path)/framework/randomshaders/rsgVariableValue.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrDefs.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrFragmentOperations.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrMultisamplePixelBufferAccess.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrPrimitivePacket.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrRasterizer.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrRenderer.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrShaders.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrShadingContext.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrVertexAttrib.cpp',
+            '<(deqp_path)/framework/referencerenderer/rrVertexPacket.cpp',
+            '<(deqp_path)/modules/glshared/glsAttributeLocationTests.cpp',
+            '<(deqp_path)/modules/glshared/glsBufferTestUtil.cpp',
+            '<(deqp_path)/modules/glshared/glsBuiltinPrecisionTests.cpp',
+            '<(deqp_path)/modules/glshared/glsCalibration.cpp',
+            '<(deqp_path)/modules/glshared/glsDrawTest.cpp',
+            '<(deqp_path)/modules/glshared/glsFboCompletenessTests.cpp',
+            '<(deqp_path)/modules/glshared/glsFboUtil.cpp',
+            '<(deqp_path)/modules/glshared/glsFragmentOpUtil.cpp',
+            '<(deqp_path)/modules/glshared/glsFragOpInteractionCase.cpp',
+            '<(deqp_path)/modules/glshared/glsInteractionTestUtil.cpp',
+            '<(deqp_path)/modules/glshared/glsLifetimeTests.cpp',
+            '<(deqp_path)/modules/glshared/glsLongStressCase.cpp',
+            '<(deqp_path)/modules/glshared/glsLongStressTestUtil.cpp',
+            '<(deqp_path)/modules/glshared/glsMemoryStressCase.cpp',
+            '<(deqp_path)/modules/glshared/glsRandomShaderCase.cpp',
+            '<(deqp_path)/modules/glshared/glsRandomShaderProgram.cpp',
+            '<(deqp_path)/modules/glshared/glsRandomUniformBlockCase.cpp',
+            '<(deqp_path)/modules/glshared/glsSamplerObjectTest.cpp',
+            '<(deqp_path)/modules/glshared/glsScissorTests.cpp',
+            '<(deqp_path)/modules/glshared/glsShaderConstExprTests.cpp',
+            '<(deqp_path)/modules/glshared/glsShaderExecUtil.cpp',
+            '<(deqp_path)/modules/glshared/glsShaderLibraryCase.cpp',
+            '<(deqp_path)/modules/glshared/glsShaderLibrary.cpp',
+            '<(deqp_path)/modules/glshared/glsShaderPerformanceCase.cpp',
+            '<(deqp_path)/modules/glshared/glsShaderPerformanceMeasurer.cpp',
+            '<(deqp_path)/modules/glshared/glsShaderRenderCase.cpp',
+            '<(deqp_path)/modules/glshared/glsStateQueryUtil.cpp',
+            '<(deqp_path)/modules/glshared/glsStateChangePerfTestCases.cpp',
+            '<(deqp_path)/modules/glshared/glsTextureBufferCase.cpp',
+            '<(deqp_path)/modules/glshared/glsTextureStateQueryTests.cpp',
+            '<(deqp_path)/modules/glshared/glsTextureTestUtil.cpp',
+            '<(deqp_path)/modules/glshared/glsUniformBlockCase.cpp',
+            '<(deqp_path)/modules/glshared/glsVertexArrayTests.cpp',
+            # TODO(jmadill): Remove this when we upstream the change.
+            '<(angle_path)/src/tests/deqp_support/qpTestLog.c',
+            '<(angle_path)/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp',
+            '<(angle_path)/src/tests/deqp_support/tcuANGLENativeDisplayFactory.h',
+            # TODO(jmadill): integrate with dEQP
+            '<(angle_path)/src/tests/deqp_support/tcuRandomOrderExecutor.cpp',
+            '<(angle_path)/src/tests/deqp_support/tcuRandomOrderExecutor.h',
+        ],
+        'deqp_libtester_sources_win':
+        [
+            '<(deqp_path)/framework/delibs/dethread/win32/deMutexWin32.c',
+            '<(deqp_path)/framework/delibs/dethread/win32/deSemaphoreWin32.c',
+            '<(deqp_path)/framework/delibs/dethread/win32/deThreadLocalWin32.c',
+            '<(deqp_path)/framework/delibs/dethread/win32/deThreadWin32.c',
+        ],
+        'deqp_libtester_sources_unix':
+        [
+            '<(deqp_path)/framework/delibs/dethread/unix/deMutexUnix.c',
+            '<(deqp_path)/framework/delibs/dethread/unix/deNamedSemaphoreUnix.c',
+            '<(deqp_path)/framework/delibs/dethread/unix/deSemaphoreUnix.c',
+            '<(deqp_path)/framework/delibs/dethread/unix/deThreadLocalUnix.c',
+            '<(deqp_path)/framework/delibs/dethread/unix/deThreadUnix.c',
+        ],
+        'deqp_libtester_sources_android':
+        [
+            '<(deqp_path)/framework/platform/android/tcuAndroidInternals.cpp',
+            '<(deqp_path)/framework/platform/android/tcuAndroidInternals.hpp',
+        ],
+        'deqp_gpu_test_expectations_sources':
+        [
+            'third_party/gpu_test_expectations/gpu_info.cc',
+            'third_party/gpu_test_expectations/gpu_info.h',
+            'third_party/gpu_test_expectations/gpu_test_config.cc',
+            'third_party/gpu_test_expectations/gpu_test_config.h',
+            'third_party/gpu_test_expectations/gpu_test_expectations_parser.cc',
+            'third_party/gpu_test_expectations/gpu_test_expectations_parser.h',
+        ],
+        'conditions':
+        [
+            ['(OS=="win" or OS=="linux" or OS=="mac")',
+            {
+                # Build the dEQP libraries for all Windows/Linux builds
+                'angle_build_deqp_libraries%': 1,
+            }],
+            ['((OS=="win" or OS=="linux" or OS=="mac") and angle_build_winrt==0)',
+            {
+                # Build the dEQP GoogleTest support helpers for all Windows/Linux builds except WinRT
+                # GoogleTest doesn't support WinRT
+                'angle_build_deqp_gtest_support%': 1,
+            }],
+            ['((OS=="win" or OS=="linux" or OS=="mac") and angle_build_winrt==0)',
+            {
+                # Build the dEQP executables for all standalone Windows/Linux builds except WinRT
+                # GYP doesn't support generating standalone WinRT executables
+                'angle_build_deqp_executables%': 1,
+
+                # Build the GoogleTest versions of dEQP for all standalone Windows/Linux builds except WinRT
+                # GoogleTest doesn't support WinRT
+                'angle_build_deqp_gtest_executables%': 1,
+            }],
+            ['OS=="linux" and use_x11==1',
+            {
+                'deqp_include_dirs':
+                [
+                    '<(deqp_path)/framework/platform/x11',
+                ],
+            }],
+            ['OS=="linux"',
+            {
+                'deqp_defines':
+                [
+                    # Ask the system headers to expose all the regular function otherwise
+                    # dEQP doesn't compile and produces warnings about implicitly defined
+                    # functions.
+                    # This has to be GNU_SOURCE as on Linux dEQP uses syscall()
+                    '_GNU_SOURCE',
+                ],
+            }],
+            ['OS=="mac"',
+            {
+                'deqp_include_dirs':
+                [
+                    '<(deqp_path)/framework/platform/osx',
+                ],
+                'deqp_defines':
+                [
+                    # Ask the system headers to expose all the regular function otherwise
+                    # dEQP doesn't compile and produces warnings about implicitly defined
+                    # functions.
+                    '_XOPEN_SOURCE=600',
+                ],
+            }],
+            ['use_ozone==1',
+            {
+                'deqp_defines':
+                [
+                    'ANGLE_USE_OZONE',
+                ],
+            }],
+        ],
+    },
+    'conditions':
+    [
+        ['angle_build_deqp_libraries==1',
+        {
+            'targets':
+            [
+                {
+                    'target_name': 'angle_zlib',
+                    'type': 'static_library',
+                    'includes': [ '../../gyp/common_defines.gypi', ],
+                    'include_dirs':
+                    [
+                        '<(zlib_path)',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'include_dirs':
+                        [
+                            '<(zlib_path)',
+                        ],
+                    },
+                    'msvs_settings':
+                    {
+                        'VCCLCompilerTool':
+                        {
+                            'AdditionalOptions':
+                            [
+                                '/wd4131', # old-style declarator
+                                '/wd4244', # Conversion from 'type1' to 'type2', possible loss of data
+                                '/wd4245', # argument signed/unsigned mismatch
+                                '/wd4267', # size_t to 'type', possible loss of data
+                                '/wd4324', # structure was padded
+                                '/wd4701', # potentially uninit used
+                                '/wd4996', # deprecated
+                            ],
+                        },
+                    },
+                    'conditions':
+                    [
+                        ['angle_build_winrt==1',
+                        {
+                            # In zlib, deflate.c/insert_string_sse assumes _MSC_VER is only used for x86 or x64
+                            # To compile this function for ARM using MSC, we trick it by defining __clang__
+                            # __clang__ isn't used elsewhere zlib, so this workaround shouldn't impact anything else
+                            'defines':
+                            [
+                                '__clang__',
+                            ],
+                        }],
+                    ],
+                    'sources':
+                    [
+                        '<(zlib_path)/adler32.c',
+                        '<(zlib_path)/compress.c',
+                        '<(zlib_path)/crc32.c',
+                        '<(zlib_path)/crc32.h',
+                        '<(zlib_path)/deflate.c',
+                        '<(zlib_path)/deflate.h',
+                        '<(zlib_path)/gzclose.c',
+                        '<(zlib_path)/gzguts.h',
+                        '<(zlib_path)/gzlib.c',
+                        '<(zlib_path)/gzread.c',
+                        '<(zlib_path)/gzwrite.c',
+                        '<(zlib_path)/infback.c',
+                        '<(zlib_path)/inffast.c',
+                        '<(zlib_path)/inffast.h',
+                        '<(zlib_path)/inffixed.h',
+                        '<(zlib_path)/inflate.c',
+                        '<(zlib_path)/inflate.h',
+                        '<(zlib_path)/inftrees.c',
+                        '<(zlib_path)/inftrees.h',
+                        '<(zlib_path)/trees.c',
+                        '<(zlib_path)/trees.h',
+                        '<(zlib_path)/uncompr.c',
+                        '<(zlib_path)/x86.h',
+                        '<(zlib_path)/zconf.h',
+                        '<(zlib_path)/zlib.h',
+                        '<(zlib_path)/zutil.c',
+                        '<(zlib_path)/zutil.h',
+                        '<(zlib_path)/simd_stub.c',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_libpng',
+                    'type': 'static_library',
+                    'includes': [ '../../gyp/common_defines.gypi', ],
+                    'dependencies':
+                    [
+                        'angle_zlib'
+                    ],
+                    'msvs_settings':
+                    {
+                        'VCCLCompilerTool':
+                        {
+                            'AdditionalOptions':
+                            [
+                                '/wd4018', # signed/unsigned mismatch
+                                '/wd4028', # parameter differs from decl
+                                '/wd4101', # unreferenced local
+                                '/wd4189', # unreferenced but initted
+                                '/wd4244', # Conversion from 'type1' to 'type2', possible loss of data
+                                '/wd4267', # Conversion from 'size_t' to 'type', possible loss of data
+                            ],
+                        },
+                    },
+                    'sources':
+                    [
+                        '<(libpng_path)/png.c',
+                        '<(libpng_path)/pngerror.c',
+                        '<(libpng_path)/pngget.c',
+                        '<(libpng_path)/pngmem.c',
+                        '<(libpng_path)/pngpread.c',
+                        '<(libpng_path)/pngread.c',
+                        '<(libpng_path)/pngrio.c',
+                        '<(libpng_path)/pngrtran.c',
+                        '<(libpng_path)/pngrutil.c',
+                        '<(libpng_path)/pngset.c',
+                        '<(libpng_path)/pngtrans.c',
+                        '<(libpng_path)/pngwio.c',
+                        '<(libpng_path)/pngwrite.c',
+                        '<(libpng_path)/pngwtran.c',
+                        '<(libpng_path)/pngwutil.c',
+                    ],
+                },
+            ], # targets
+        }], # angle_build_deqp_libraries==1
+        ['angle_build_deqp_libraries==1',
+        {
+            'targets':
+            [
+                {
+                    'target_name': 'angle_deqp_support',
+                    'type': 'none',
+                    'direct_dependent_settings':
+                    {
+                        'configurations':
+                        {
+                            'Common_Base':
+                            {
+                                'msvs_configuration_attributes':
+                                {
+                                    # dEQP requires ASCII
+                                    'CharacterSet': '0',
+                                },
+                                'msvs_settings':
+                                {
+                                    'VCLinkerTool':
+                                    {
+                                        'conditions':
+                                        [
+                                            ['angle_build_winrt==0',
+                                            {
+                                                'AdditionalDependencies':
+                                                [
+                                                    'dbghelp.lib',
+                                                    'gdi32.lib',
+                                                    'user32.lib',
+                                                    'ws2_32.lib',
+                                                ],
+                                            }],
+                                            ['angle_build_winrt==1',
+                                            {
+                                                # Disable COMDAT optimizations, disabled by default for non-WinRT
+                                                'AdditionalOptions': ['/OPT:NOREF', '/OPT:NOICF'],
+                                                # AdditionalDependencies automatically configures the required .libs
+                                                'AdditionalDependencies':
+                                                [
+                                                    '%(AdditionalDependencies)'
+                                                ],
+                                            }],
+                                        ],
+                                    },
+                                },
+                            },
+
+                            'Debug_Base':
+                            {
+                                'msvs_settings':
+                                {
+                                    'VCCLCompilerTool':
+                                    {
+                                        'RuntimeTypeInfo': 'true', # dEQP needs RTTI
+                                    },
+                                },
+                            },
+
+                            'Release_Base':
+                            {
+                                'msvs_settings':
+                                {
+                                    'VCCLCompilerTool':
+                                    {
+                                        'RuntimeTypeInfo': 'true', # dEQP needs RTTI
+                                    },
+                                },
+                            },
+                        },
+                        # Re-enable RTTI and exceptions, dEQP needs them.
+                        'cflags_cc!':
+                        [
+                            '-fno-exceptions',
+                            '-fno-rtti',
+                        ],
+                        'include_dirs': ['<@(deqp_include_dirs)'],
+                        'defines': ['<@(deqp_defines)'],
+                        'defines!': [ '<@(deqp_undefines)' ],
+                        'msvs_settings':
+                        {
+                            'VCCLCompilerTool':
+                            {
+                                'AdditionalOptions': ['<@(deqp_win_cflags)'],
+                            },
+                        },
+                        'conditions':
+                        [
+                            ['clang==1',
+                            {
+                                # TODO(jmadill): Remove this once we fix dEQP.
+                                'cflags_cc':
+                                [
+                                    '-Wno-delete-non-virtual-dtor',
+                                ],
+                            }],
+                            ['OS=="win"',
+                            {
+                                'cflags': ['<@(deqp_win_cflags)'],
+                                'cflags_cc': ['<@(deqp_win_cflags)'],
+                                'include_dirs':
+                                [
+                                    '<(deqp_path)/framework/platform/win32',
+                                ],
+                            }],
+                        ],
+                    },
+                    'conditions':
+                    [
+                        ['angle_build_winrt==1',
+                        {
+                            'type' : 'shared_library',
+                        }],
+                    ],
+                },
+
+                # Compile decpp separately because MSVC ignores the extension of the files when
+                # outputting the obj file, and later thinks that a decpp obj and another obj are the
+                # same, ignoring one and eventually producing a link error. The problem occurs for
+                # example between decpp/deRandom.cpp and debase/deRandom.c
+                {
+                    'target_name': 'angle_deqp_decpp',
+                    'type': 'static_library',
+                    'dependencies': [ 'angle_deqp_support' ],
+                    'sources':
+                    [
+                        '<@(deqp_libtester_decpp_sources)',
+                    ],
+                    # In a chromium build dl is required for deDynamicLibrary
+                    'conditions':
+                    [
+                        ['OS=="linux"',
+                        {
+                            'link_settings':
+                            {
+                                'libraries': ['-ldl']
+                            },
+                        }],
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_libtester',
+                    'type': 'static_library',
+                    'dependencies':
+                    [
+                        '<(angle_path)/src/angle.gyp:angle_common',
+                        'angle_deqp_decpp',
+                        'angle_deqp_support',
+                        'angle_libpng',
+                        '<(angle_path)/src/angle.gyp:libEGL',
+                        '<(angle_path)/util/util.gyp:angle_util',
+                    ],
+                    'export_dependent_settings':
+                    [
+                        'angle_deqp_support',
+                        '<(angle_path)/util/util.gyp:angle_util',
+                    ],
+                    'include_dirs':
+                    [
+                        '<(angle_path)/include',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'include_dirs':
+                        [
+                            '<(angle_path)/include',
+                        ],
+                        'defines':
+                        [
+                            'ANGLE_DEQP_LIBTESTER_IMPLEMENTATION',
+                        ],
+                    },
+                    'msvs_settings':
+                    {
+                        'VCCLCompilerTool':
+                        {
+                            'AdditionalOptions':
+                            [
+                                '/bigobj', # needed for glsBuiltinPrecisionTests.cpp
+                                '/wd4251', # needed for angle_util STL objects not having DLL interface
+                            ],
+                        },
+                    },
+                    'sources':
+                    [
+                        '<@(deqp_libtester_sources)',
+                    ],
+                    'conditions':
+                    [
+                        ['OS=="mac"',
+                        {
+                            'direct_dependent_settings':
+                            {
+                                'xcode_settings':
+                                {
+                                    'DYLIB_INSTALL_NAME_BASE': '@rpath',
+                                },
+                            },
+                        }],
+                        ['OS=="win"',
+                        {
+                            'sources': [ '<@(deqp_libtester_sources_win)', ],
+                        }],
+                        ['OS=="linux" or OS=="mac"',
+                        {
+                            'sources': [ '<@(deqp_libtester_sources_unix)', ],
+                        }],
+                        ['OS=="linux"',
+                        {
+                            'link_settings':
+                            {
+                                'libraries': ['-lrt']
+                            },
+                        }],
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_libgles2',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'angle_deqp_libtester',
+                    ],
+                    'defines':
+                    [
+                        'ANGLE_DEQP_GLES2_TESTS',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_DEQP_GLES2_TESTS',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(deqp_gles2_sources)',
+                        'deqp_support/angle_deqp_libtester_main.cpp',
+                        'deqp_support/tcuANGLEPlatform.cpp',
+                        'deqp_support/tcuANGLEPlatform.h',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_libgles3',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'angle_deqp_libtester',
+                    ],
+                    'defines':
+                    [
+                        'ANGLE_DEQP_GLES3_TESTS',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_DEQP_GLES3_TESTS',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(deqp_gles3_sources)',
+                        'deqp_support/angle_deqp_libtester_main.cpp',
+                        'deqp_support/tcuANGLEPlatform.cpp',
+                        'deqp_support/tcuANGLEPlatform.h',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_libgles31',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'angle_deqp_libtester',
+                    ],
+                    'defines':
+                    [
+                        'ANGLE_DEQP_GLES31_TESTS',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_DEQP_GLES31_TESTS',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(deqp_gles31_sources)',
+                        'deqp_support/angle_deqp_libtester_main.cpp',
+                        'deqp_support/tcuANGLEPlatform.cpp',
+                        'deqp_support/tcuANGLEPlatform.h',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_libegl',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'angle_deqp_libtester',
+                    ],
+                    'defines':
+                    [
+                        'ANGLE_DEQP_EGL_TESTS',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_DEQP_EGL_TESTS',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(deqp_egl_sources)',
+                        'deqp_support/angle_deqp_libtester_main.cpp',
+                        'deqp_support/tcuANGLEPlatform.cpp',
+                        'deqp_support/tcuANGLEPlatform.h',
+                    ],
+                },
+            ], # targets
+        }], # angle_build_deqp_libraries
+        ['angle_build_deqp_executables==1',
+        {
+            "targets":
+            [
+                {
+                    'target_name': 'angle_deqp_gles2_tests',
+                    'type': 'executable',
+                    'dependencies':
+                    [
+                        'angle_deqp_libgles2',
+                        # Real dependency is in angle_deqp_libtester, however, not propagated here by GYP
+                        '<(angle_path)/src/angle.gyp:libEGL',
+                    ],
+                    'sources':
+                    [
+                        'deqp_support/angle_deqp_tests_main.cpp',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_gles3_tests',
+                    'type': 'executable',
+                    'dependencies':
+                    [
+                        'angle_deqp_libgles3',
+                        # Real dependency is in angle_deqp_libtester, however, not propagated here by GYP
+                        '<(angle_path)/src/angle.gyp:libEGL',
+                    ],
+                    'sources':
+                    [
+                        'deqp_support/angle_deqp_tests_main.cpp',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_gles31_tests',
+                    'type': 'executable',
+                    'dependencies':
+                    [
+                        'angle_deqp_libgles31',
+                        # Real dependency is in angle_deqp_libtester, however, not propagated here by GYP
+                        '<(angle_path)/src/angle.gyp:libEGL',
+                    ],
+                    'sources':
+                    [
+                        'deqp_support/angle_deqp_tests_main.cpp',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_egl_tests',
+                    'type': 'executable',
+                    'dependencies':
+                    [
+                        'angle_deqp_libegl',
+                        # Real dependency is in angle_deqp_libtester, however, not propagated here by GYP
+                        '<(angle_path)/src/angle.gyp:libEGL',
+                    ],
+                    'sources':
+                    [
+                        'deqp_support/angle_deqp_tests_main.cpp',
+                    ],
+                },
+            ], # targets
+        }], # angle_build_deqp_executables
+        ['angle_build_deqp_gtest_support==1',
+        {
+            'targets':
+            [
+                # Helper target for synching our implementation with chrome's
+                {
+                    'target_name': 'angle_deqp_gtest_support',
+                    'type': 'none',
+                    'dependencies':
+                    [
+                        'angle_test_support',
+                        '<(angle_path)/util/util.gyp:angle_util',
+                        '<(angle_path)/src/angle.gyp:angle_common',
+                    ],
+                    'export_dependent_settings':
+                    [
+                        'angle_test_support',
+                        '<(angle_path)/util/util.gyp:angle_util',
+                    ],
+
+                    'direct_dependent_settings':
+                    {
+                        'include_dirs':
+                        [
+                            'deqp_support',
+                            'third_party/gpu_test_expectations',
+                        ],
+                        'sources':
+                        [
+                            '<@(deqp_gpu_test_expectations_sources)',
+                            'deqp_support/angle_deqp_gtest.cpp',
+                        ],
+
+                        'defines':
+                        [
+                            # Re-define the missing Windows macros
+                            '<@(deqp_undefines)',
+                        ],
+
+                        'msvs_settings':
+                        {
+                            'VCLinkerTool':
+                            {
+                                'AdditionalDependencies':
+                                [
+                                    'user32.lib',
+                                ],
+                            },
+                        },
+
+                        'conditions':
+                        [
+                            # NOTE(smcgruer): Guarding with use_libpci allows gyp to run successfully
+                            # on systems without libpci, but the test targets will not compile or link.
+                            ['OS=="linux" and use_libpci==1',
+                            {
+                                'ldflags':
+                                [
+                                    '<!@(<(pkg-config) --libs-only-L --libs-only-other libpci)',
+                                ],
+                                'libraries':
+                                [
+                                    '<!@(<(pkg-config) --libs-only-l libpci)',
+                                ],
+                            }],
+                            ['OS=="mac"',
+                            {
+                                'sources':
+                                [
+                                    'third_party/gpu_test_expectations/gpu_test_config_mac.mm',
+                                ],
+                                'link_settings':
+                                {
+                                    'libraries':
+                                    [
+                                        '$(SDKROOT)/System/Library/Frameworks/IOKit.framework',
+                                    ],
+                                },
+                            }],
+                        ],
+                    },
+                },
+            ], # targets
+        }], # angle_build_deqp_gtest_support
+        ['angle_build_deqp_gtest_executables==1',
+        {
+            "targets":
+            [
+                {
+                    'target_name': 'angle_deqp_gtest_gles2_tests',
+                    'type': 'executable',
+                    'includes': [ '../../gyp/common_defines.gypi', ],
+                    'dependencies':
+                    [
+                        'angle_deqp_gtest_support',
+                        'angle_deqp_libgles2',
+                        # Real dependency is in angle_deqp_libtester, however, not propagated here by GYP
+                        '<(angle_path)/src/angle.gyp:libEGL',
+                    ],
+                    'sources':
+                    [
+                        'deqp_support/angle_deqp_gtest_main.cpp',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_gtest_gles3_tests',
+                    'type': 'executable',
+                    'includes': [ '../../gyp/common_defines.gypi', ],
+                    'dependencies':
+                    [
+                        'angle_deqp_gtest_support',
+                        'angle_deqp_libgles3',
+                        # Real dependency is in angle_deqp_libtester, however, not propagated here by GYP
+                        '<(angle_path)/src/angle.gyp:libEGL',
+                    ],
+                    'sources':
+                    [
+                        'deqp_support/angle_deqp_gtest_main.cpp',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_gtest_gles31_tests',
+                    'type': 'executable',
+                    'includes': [ '../../gyp/common_defines.gypi', ],
+                    'dependencies':
+                    [
+                        'angle_deqp_gtest_support',
+                        'angle_deqp_libgles31',
+                        # Real dependency is in angle_deqp_libtester, however, not propagated here by GYP
+                        '<(angle_path)/src/angle.gyp:libEGL',
+                    ],
+                    'sources':
+                    [
+                        'deqp_support/angle_deqp_gtest_main.cpp',
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_deqp_gtest_egl_tests',
+                    'type': 'executable',
+                    'includes': [ '../../gyp/common_defines.gypi', ],
+                    'dependencies':
+                    [
+                        'angle_deqp_gtest_support',
+                        'angle_deqp_libegl',
+                        # Real dependency is in angle_deqp_libtester, however, not propagated here by GYP
+                        '<(angle_path)/src/angle.gyp:libEGL',
+                    ],
+                    'sources':
+                    [
+                        'deqp_support/angle_deqp_gtest_main.cpp',
+                    ],
+                },
+            ], # targets
+        }], # angle_build_deqp_gtest_executables
+    ], # conditions
+}
diff --git a/src/third_party/angle/src/tests/deqp_support/angle_deqp_gtest.cpp b/src/third_party/angle/src/tests/deqp_support/angle_deqp_gtest.cpp
new file mode 100644
index 0000000..a4bec13
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/angle_deqp_gtest.cpp
@@ -0,0 +1,453 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_deqp_gtest:
+//   dEQP and GoogleTest integration logic. Calls through to the random
+//   order executor.
+
+#include <fstream>
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include "angle_deqp_libtester.h"
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/Optional.h"
+#include "common/platform.h"
+#include "common/string_utils.h"
+#include "gpu_test_expectations_parser.h"
+#include "system_utils.h"
+
+namespace
+{
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+const char *g_CaseListRelativePath =
+    "/../../sdcard/chromium_tests_root/third_party/deqp/src/android/cts/master/";
+#else
+const char *g_CaseListRelativePath = "/../../third_party/deqp/src/android/cts/master/";
+#endif
+
+const char *g_TestExpectationsSearchPaths[] = {
+    "/../../src/tests/deqp_support/", "/../../third_party/angle/src/tests/deqp_support/",
+    "/deqp_support/", "/../../sdcard/chromium_tests_root/third_party/angle/src/tests/deqp_support/",
+};
+
+const char *g_CaseListFiles[] = {
+    "gles2-master.txt", "gles3-master.txt", "gles31-master.txt", "egl-master.txt",
+};
+
+const char *g_TestExpectationsFiles[] = {
+    "deqp_gles2_test_expectations.txt", "deqp_gles3_test_expectations.txt",
+    "deqp_gles31_test_expectations.txt", "deqp_egl_test_expectations.txt",
+};
+
+using APIInfo = std::pair<const char *, gpu::GPUTestConfig::API>;
+
+const APIInfo g_eglDisplayAPIs[] = {
+    {"angle-d3d9", gpu::GPUTestConfig::kAPID3D9},
+    {"angle-d3d11", gpu::GPUTestConfig::kAPID3D11},
+    {"angle-gl", gpu::GPUTestConfig::kAPIGLDesktop},
+    {"angle-gles", gpu::GPUTestConfig::kAPIGLES},
+    {"angle-null", gpu::GPUTestConfig::kAPIUnknown },
+};
+
+const char *g_deqpEGLString = "--deqp-egl-display-type=";
+const char *g_angleEGLString = "--use-angle=";
+
+const APIInfo *g_initAPI = nullptr;
+
+// Returns the default API for a platform.
+const char *GetDefaultAPIName()
+{
+#if defined(ANGLE_PLATFORM_WINDOWS)
+    return "angle-d3d11";
+#elif defined(ANGLE_PLATFORM_APPLE) || defined(ANGLE_PLATFORM_LINUX)
+    return "angle-gl";
+#elif defined(ANGLE_PLATFORM_ANDROID)
+    return "angle-gles";
+#else
+#error Unknown platform.
+#endif
+}
+
+const APIInfo *FindAPIInfo(const std::string &arg)
+{
+    for (auto &displayAPI : g_eglDisplayAPIs)
+    {
+        if (arg == displayAPI.first)
+        {
+            return &displayAPI;
+        }
+    }
+    return nullptr;
+}
+
+const APIInfo *GetDefaultAPIInfo()
+{
+    const APIInfo *defaultInfo = FindAPIInfo(GetDefaultAPIName());
+    ASSERT(defaultInfo);
+    return defaultInfo;
+}
+
+// During the CaseList initialization we cannot use the GTEST FAIL macro to quit the program because
+// the initialization is called outside of tests the first time.
+void Die()
+{
+    exit(EXIT_FAILURE);
+}
+
+Optional<std::string> FindTestExpectationsPath(const std::string &exeDir,
+                                                      size_t testModuleIndex)
+{
+    for (const char *testPath : g_TestExpectationsSearchPaths)
+    {
+        std::stringstream testExpectationsPathStr;
+        testExpectationsPathStr << exeDir << testPath << g_TestExpectationsFiles[testModuleIndex];
+
+        std::string path = testExpectationsPathStr.str();
+        std::ifstream inFile(path.c_str());
+        if (!inFile.fail())
+        {
+            inFile.close();
+            return Optional<std::string>(path);
+        }
+    }
+
+    return Optional<std::string>::Invalid();
+}
+
+class dEQPCaseList
+{
+  public:
+    dEQPCaseList(size_t testModuleIndex);
+
+    struct CaseInfo
+    {
+        CaseInfo(const std::string &dEQPName,
+                 const std::string &gTestName,
+                 int expectation)
+            : mDEQPName(dEQPName),
+              mGTestName(gTestName),
+              mExpectation(expectation)
+        {
+        }
+
+        std::string mDEQPName;
+        std::string mGTestName;
+        int mExpectation;
+    };
+
+    void initialize();
+
+    const CaseInfo &getCaseInfo(size_t caseIndex) const
+    {
+        ASSERT(mInitialized);
+        ASSERT(caseIndex < mCaseInfoList.size());
+        return mCaseInfoList[caseIndex];
+    }
+
+    size_t numCases() const
+    {
+        ASSERT(mInitialized);
+        return mCaseInfoList.size();
+    }
+
+  private:
+    std::vector<CaseInfo> mCaseInfoList;
+    gpu::GPUTestExpectationsParser mTestExpectationsParser;
+    gpu::GPUTestBotConfig mTestConfig;
+    size_t mTestModuleIndex;
+    bool mInitialized;
+};
+
+dEQPCaseList::dEQPCaseList(size_t testModuleIndex)
+    : mTestModuleIndex(testModuleIndex),
+      mInitialized(false)
+{
+}
+
+void dEQPCaseList::initialize()
+{
+    if (mInitialized)
+    {
+        return;
+    }
+
+    mInitialized = true;
+
+    std::string exeDir = angle::GetExecutableDirectory();
+
+    std::stringstream caseListPathStr;
+    caseListPathStr << exeDir << g_CaseListRelativePath << g_CaseListFiles[mTestModuleIndex];
+    std::string caseListPath = caseListPathStr.str();
+
+    Optional<std::string> testExpectationsPath = FindTestExpectationsPath(exeDir, mTestModuleIndex);
+    if (!testExpectationsPath.valid())
+    {
+        std::cerr << "Failed to find test expectations file." << std::endl;
+        Die();
+    }
+
+    if (!mTestExpectationsParser.LoadTestExpectationsFromFile(testExpectationsPath.value()))
+    {
+        std::stringstream errorMsgStream;
+        for (const auto &message : mTestExpectationsParser.GetErrorMessages())
+        {
+            errorMsgStream << std::endl << " " << message;
+        }
+
+        std::cerr << "Failed to load test expectations." << errorMsgStream.str() << std::endl;
+        Die();
+    }
+
+    if (!mTestConfig.LoadCurrentConfig(nullptr))
+    {
+        std::cerr << "Failed to load test configuration." << std::endl;
+        Die();
+    }
+
+    // Set the API from the command line, or using the default platform API.
+    if (g_initAPI)
+    {
+        mTestConfig.set_api(g_initAPI->second);
+    }
+    else
+    {
+        mTestConfig.set_api(GetDefaultAPIInfo()->second);
+    }
+
+    std::ifstream caseListStream(caseListPath);
+    if (caseListStream.fail())
+    {
+        std::cerr << "Failed to load the case list." << std::endl;
+        Die();
+    }
+
+    while (!caseListStream.eof())
+    {
+        std::string inString;
+        std::getline(caseListStream, inString);
+
+        std::string dEQPName = angle::TrimString(inString, angle::kWhitespaceASCII);
+        if (dEQPName.empty())
+            continue;
+        std::string gTestName = dEQPName.substr(dEQPName.find('.') + 1);
+        if (gTestName.empty())
+            continue;
+        std::replace(gTestName.begin(), gTestName.end(), '.', '_');
+
+        // Occurs in some luminance tests
+        gTestName.erase(std::remove(gTestName.begin(), gTestName.end(), '-'), gTestName.end());
+
+        int expectation = mTestExpectationsParser.GetTestExpectation(dEQPName, mTestConfig);
+        if (expectation != gpu::GPUTestExpectationsParser::kGpuTestSkip)
+        {
+            mCaseInfoList.push_back(CaseInfo(dEQPName, gTestName, expectation));
+        }
+    }
+}
+
+template <size_t TestModuleIndex>
+class dEQPTest : public testing::TestWithParam<size_t>
+{
+  public:
+    static testing::internal::ParamGenerator<size_t> GetTestingRange()
+    {
+        return testing::Range<size_t>(0, GetCaseList().numCases());
+    }
+
+    static std::string GetCaseGTestName(size_t caseIndex)
+    {
+        const auto &caseInfo = GetCaseList().getCaseInfo(caseIndex);
+        return caseInfo.mGTestName;
+    }
+
+    static const dEQPCaseList &GetCaseList()
+    {
+        static dEQPCaseList sCaseList(TestModuleIndex);
+        sCaseList.initialize();
+        return sCaseList;
+    }
+
+    static void SetUpTestCase();
+    static void TearDownTestCase();
+
+  protected:
+    void runTest()
+    {
+        const auto &caseInfo = GetCaseList().getCaseInfo(GetParam());
+        std::cout << caseInfo.mDEQPName << std::endl;
+
+        bool result = deqp_libtester_run(caseInfo.mDEQPName.c_str());
+
+        if (caseInfo.mExpectation == gpu::GPUTestExpectationsParser::kGpuTestPass)
+        {
+            EXPECT_TRUE(result);
+            sPasses += (result ? 1u : 0u);
+            sFails += (!result ? 1u : 0u);
+        }
+        else if (result)
+        {
+            std::cout << "Test expected to fail but passed!" << std::endl;
+            sUnexpectedPasses++;
+        }
+        else
+        {
+            sFails++;
+        }
+    }
+
+    static unsigned int sPasses;
+    static unsigned int sFails;
+    static unsigned int sUnexpectedPasses;
+};
+
+template <size_t TestModuleIndex>
+unsigned int dEQPTest<TestModuleIndex>::sPasses           = 0;
+template <size_t TestModuleIndex>
+unsigned int dEQPTest<TestModuleIndex>::sFails            = 0;
+template <size_t TestModuleIndex>
+unsigned int dEQPTest<TestModuleIndex>::sUnexpectedPasses = 0;
+
+// static
+template <size_t TestModuleIndex>
+void dEQPTest<TestModuleIndex>::SetUpTestCase()
+{
+    sPasses           = 0;
+    sFails            = 0;
+    sUnexpectedPasses = 0;
+
+    std::vector<const char *> argv;
+
+    // Reserve one argument for the binary name.
+    argv.push_back("");
+
+    // Add init api.
+    const char *targetApi    = g_initAPI ? g_initAPI->first : GetDefaultAPIName();
+    std::string apiArgString = std::string(g_deqpEGLString) + targetApi;
+    argv.push_back(apiArgString.c_str());
+
+    // Init the platform.
+    if (!deqp_libtester_init_platform(static_cast<int>(argv.size()), argv.data()))
+    {
+        std::cout << "Aborting test due to dEQP initialization error." << std::endl;
+        exit(1);
+    }
+}
+
+// static
+template <size_t TestModuleIndex>
+void dEQPTest<TestModuleIndex>::TearDownTestCase()
+{
+    unsigned int total = sPasses + sFails;
+    float passFrac     = static_cast<float>(sPasses) / static_cast<float>(total) * 100.0f;
+    float failFrac     = static_cast<float>(sFails) / static_cast<float>(total) * 100.0f;
+    std::cout << "Passed: " << sPasses << "/" << total << " tests. (" << passFrac << "%)"
+              << std::endl;
+    if (sFails > 0)
+    {
+        std::cout << "Failed: " << sFails << "/" << total << " tests. (" << failFrac << "%)"
+                  << std::endl;
+    }
+    if (sUnexpectedPasses > 0)
+    {
+        std::cout << sUnexpectedPasses << " tests unexpectedly passed." << std::endl;
+    }
+
+    deqp_libtester_shutdown_platform();
+}
+
+#define ANGLE_INSTANTIATE_DEQP_TEST_CASE(DEQP_TEST, N)                          \
+    class DEQP_TEST : public dEQPTest<N>                                        \
+    {                                                                           \
+    };                                                                          \
+    TEST_P(DEQP_TEST, Default) { runTest(); }                                   \
+                                                                                \
+    INSTANTIATE_TEST_CASE_P(, DEQP_TEST, DEQP_TEST::GetTestingRange(),          \
+                            [](const testing::TestParamInfo<size_t> &info) {    \
+                                return DEQP_TEST::GetCaseGTestName(info.param); \
+                            })
+
+#ifdef ANGLE_DEQP_GLES2_TESTS
+ANGLE_INSTANTIATE_DEQP_TEST_CASE(dEQP_GLES2, 0);
+#endif
+
+#ifdef ANGLE_DEQP_GLES3_TESTS
+ANGLE_INSTANTIATE_DEQP_TEST_CASE(dEQP_GLES3, 1);
+#endif
+
+#ifdef ANGLE_DEQP_GLES31_TESTS
+ANGLE_INSTANTIATE_DEQP_TEST_CASE(dEQP_GLES31, 2);
+#endif
+
+#ifdef ANGLE_DEQP_EGL_TESTS
+ANGLE_INSTANTIATE_DEQP_TEST_CASE(dEQP_EGL, 3);
+#endif
+
+void HandleDisplayType(const char *displayTypeString)
+{
+    std::stringstream argStream;
+
+    if (g_initAPI)
+    {
+        std::cout << "Cannot specify two EGL displays!" << std::endl;
+        exit(1);
+    }
+
+    if (strncmp(displayTypeString, "angle-", strlen("angle-")) != 0)
+    {
+        argStream << "angle-";
+    }
+
+    argStream << displayTypeString;
+    std::string arg = argStream.str();
+
+    g_initAPI = FindAPIInfo(arg);
+
+    if (!g_initAPI)
+    {
+        std::cout << "Unknown ANGLE back-end API: " << displayTypeString << std::endl;
+        exit(1);
+    }
+}
+
+void DeleteArg(int *argc, int argIndex, char **argv)
+{
+    (*argc)--;
+    for (int moveIndex = argIndex; moveIndex < *argc; ++moveIndex)
+    {
+        argv[moveIndex] = argv[moveIndex + 1];
+    }
+}
+
+} // anonymous namespace
+
+// Called from main() to process command-line arguments.
+namespace angle
+{
+void InitTestHarness(int *argc, char **argv)
+{
+    int argIndex = 0;
+    while (argIndex < *argc)
+    {
+        if (strncmp(argv[argIndex], g_deqpEGLString, strlen(g_deqpEGLString)) == 0)
+        {
+            HandleDisplayType(argv[argIndex] + strlen(g_deqpEGLString));
+            DeleteArg(argc, argIndex, argv);
+        }
+        else if (strncmp(argv[argIndex], g_angleEGLString, strlen(g_angleEGLString)) == 0)
+        {
+            HandleDisplayType(argv[argIndex] + strlen(g_angleEGLString));
+            DeleteArg(argc, argIndex, argv);
+        }
+        else
+        {
+            argIndex++;
+        }
+    }
+}
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/deqp_support/angle_deqp_gtest_main.cpp b/src/third_party/angle/src/tests/deqp_support/angle_deqp_gtest_main.cpp
new file mode 100644
index 0000000..e72417f
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/angle_deqp_gtest_main.cpp
@@ -0,0 +1,24 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_deqp_gtest_main:
+//   Entry point for standalone dEQP tests.
+
+#include <gtest/gtest.h>
+
+// Defined in angle_deqp_gtest.cpp. Declared here so we don't need to make a header that we import
+// in Chromium.
+namespace angle
+{
+void InitTestHarness(int *argc, char **argv);
+}  // namespace angle
+
+int main(int argc, char **argv)
+{
+    angle::InitTestHarness(&argc, argv);
+    testing::InitGoogleTest(&argc, argv);
+    int rt = RUN_ALL_TESTS();
+    return rt;
+}
diff --git a/src/third_party/angle/src/tests/deqp_support/angle_deqp_libtester.h b/src/third_party/angle/src/tests/deqp_support/angle_deqp_libtester.h
new file mode 100644
index 0000000..7f35ddb
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/angle_deqp_libtester.h
@@ -0,0 +1,35 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angle_deqp_libtester.h:
+//   Exports for the ANGLE dEQP libtester module.
+
+#ifndef ANGLE_DEQP_LIBTESTER_H_
+#define ANGLE_DEQP_LIBTESTER_H_
+
+#if defined(_WIN32)
+#   if defined(ANGLE_DEQP_LIBTESTER_IMPLEMENTATION)
+#       define ANGLE_LIBTESTER_EXPORT __declspec(dllexport)
+#   else
+#       define ANGLE_LIBTESTER_EXPORT __declspec(dllimport)
+#   endif
+#elif defined(__GNUC__)
+#   if defined(ANGLE_DEQP_LIBTESTER_IMPLEMENTATION)
+#       define ANGLE_LIBTESTER_EXPORT __attribute__((visibility ("default")))
+#   else
+#       define ANGLE_LIBTESTER_EXPORT
+#   endif
+#else
+#   define ANGLE_LIBTESTER_EXPORT
+#endif
+
+// Exported to the tester app.
+ANGLE_LIBTESTER_EXPORT int deqp_libtester_main(int argc, const char *argv[]);
+ANGLE_LIBTESTER_EXPORT bool deqp_libtester_init_platform(int argc, const char *argv[]);
+ANGLE_LIBTESTER_EXPORT void deqp_libtester_shutdown_platform();
+ANGLE_LIBTESTER_EXPORT bool deqp_libtester_run(const char *caseName);
+
+#endif // ANGLE_DEQP_LIBTESTER_H_
diff --git a/src/third_party/angle/src/tests/deqp_support/angle_deqp_libtester_main.cpp b/src/third_party/angle/src/tests/deqp_support/angle_deqp_libtester_main.cpp
new file mode 100644
index 0000000..90727f3
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/angle_deqp_libtester_main.cpp
@@ -0,0 +1,250 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// deqp_libtester_main.cpp: Entry point for tester DLL.
+
+#include <cstdio>
+#include <iostream>
+
+#include "angle_deqp_libtester.h"
+#include "common/angleutils.h"
+#include "deMath.h"
+#include "deUniquePtr.hpp"
+#include "tcuApp.hpp"
+#include "tcuCommandLine.hpp"
+#include "tcuDefs.hpp"
+#include "tcuPlatform.hpp"
+#include "tcuRandomOrderExecutor.h"
+#include "tcuResource.hpp"
+#include "tcuTestLog.hpp"
+#include "system_utils.h"
+
+#if (DE_OS == DE_OS_WIN32)
+#include <Windows.h>
+#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX)
+#include <sys/unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#elif (DE_OS == DE_OS_ANDROID)
+#include <sys/stat.h>
+#endif
+
+tcu::Platform *createPlatform();
+
+namespace
+{
+
+tcu::Platform *g_platform = nullptr;
+tcu::CommandLine *g_cmdLine = nullptr;
+tcu::DirArchive *g_archive = nullptr;
+tcu::TestLog *g_log = nullptr;
+tcu::TestContext *g_testCtx = nullptr;
+tcu::TestPackageRoot *g_root = nullptr;
+tcu::RandomOrderExecutor *g_executor = nullptr;
+
+const char *g_dEQPDataSearchDirs[] = {
+    "data",
+    "third_party/deqp/data",
+    "../third_party/deqp/src/data",
+    "deqp_support/data",
+    "third_party/deqp/src/data",
+    "../../third_party/deqp/src/data",
+    "../../../third_party/deqp/src/data",
+    "../../sdcard/chromium_tests_root/third_party/deqp/src/data",
+};
+
+// TODO(jmadill): upstream to dEQP?
+#if (DE_OS == DE_OS_WIN32)
+deBool deIsDir(const char *filename)
+{
+    WIN32_FILE_ATTRIBUTE_DATA fileInformation;
+
+    BOOL result = GetFileAttributesExA(filename, GetFileExInfoStandard, &fileInformation);
+    if (result)
+    {
+        DWORD attribs = fileInformation.dwFileAttributes;
+        return (attribs != INVALID_FILE_ATTRIBUTES) && ((attribs & FILE_ATTRIBUTE_DIRECTORY) > 0);
+    }
+
+    return false;
+}
+#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_ANDROID)
+deBool deIsDir(const char *filename)
+{
+    struct stat st;
+    int result = stat(filename, &st);
+    return result == 0 && ((st.st_mode & S_IFDIR) == S_IFDIR);
+}
+#else
+#error TODO(jmadill): support other platforms
+#endif
+
+bool FindDataDir(std::string *dataDirOut)
+{
+    for (auto searchDir : g_dEQPDataSearchDirs)
+    {
+        if (deIsDir((std::string(searchDir) + "/gles2").c_str()))
+        {
+            *dataDirOut = searchDir;
+            return true;
+        }
+
+        std::stringstream dirStream;
+        dirStream << angle::GetExecutableDirectory() << "/" << searchDir;
+        std::string dataDir = dirStream.str();
+        dirStream << "/gles2";
+        std::string searchPath = dirStream.str();
+
+        if (deIsDir(searchPath.c_str()))
+        {
+            *dataDirOut = dataDir;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+std::string GetLogFileName(std::string deqpDataDir)
+{
+#if (DE_OS == DE_OS_ANDROID)
+    // On Android executable dir is not writable, so use data dir instead
+    return deqpDataDir + "/" + g_cmdLine->getLogFileName();
+#else
+    return g_cmdLine->getLogFileName();
+#endif
+}
+
+}  // anonymous namespace
+
+ANGLE_LIBTESTER_EXPORT bool deqp_libtester_init_platform(int argc, const char *argv[])
+{
+    try
+    {
+#if (DE_OS != DE_OS_WIN32)
+        // Set stdout to line-buffered mode (will be fully buffered by default if stdout is pipe).
+        setvbuf(stdout, DE_NULL, _IOLBF, 4 * 1024);
+#endif
+        g_platform = createPlatform();
+
+        if (!deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST))
+        {
+            std::cout << "Failed to set floating point rounding mode." << std::endl;
+            return false;
+        }
+
+        std::string deqpDataDir;
+        if (!FindDataDir(&deqpDataDir))
+        {
+            std::cout << "Failed to find dEQP data directory." << std::endl;
+            return false;
+        }
+
+        g_cmdLine = new tcu::CommandLine(argc, argv);
+        g_archive = new tcu::DirArchive(deqpDataDir.c_str());
+        g_log     = new tcu::TestLog(GetLogFileName(deqpDataDir).c_str(), g_cmdLine->getLogFlags());
+        g_testCtx = new tcu::TestContext(*g_platform, *g_archive, *g_log, *g_cmdLine, DE_NULL);
+        g_root = new tcu::TestPackageRoot(*g_testCtx, tcu::TestPackageRegistry::getSingleton());
+        g_executor = new tcu::RandomOrderExecutor(*g_root, *g_testCtx);
+    }
+    catch (const std::exception& e)
+    {
+        tcu::die("%s", e.what());
+        return false;
+    }
+
+    return true;
+}
+
+// Exported to the tester app.
+ANGLE_LIBTESTER_EXPORT int deqp_libtester_main(int argc, const char *argv[])
+{
+    if (!deqp_libtester_init_platform(argc, argv))
+    {
+        tcu::die("Could not initialize the dEQP platform");
+    }
+
+    try
+    {
+        de::UniquePtr<tcu::App> app(new tcu::App(*g_platform, *g_archive, *g_log, *g_cmdLine));
+
+        // Main loop.
+        for (;;)
+        {
+            if (!app->iterate())
+                break;
+        }
+    }
+    catch (const std::exception &e)
+    {
+        deqp_libtester_shutdown_platform();
+        tcu::die("%s", e.what());
+    }
+
+    deqp_libtester_shutdown_platform();
+    return 0;
+}
+
+ANGLE_LIBTESTER_EXPORT void deqp_libtester_shutdown_platform()
+{
+    delete g_executor;
+    g_executor = nullptr;
+    delete g_root;
+    g_root = nullptr;
+    delete g_testCtx;
+    g_testCtx = nullptr;
+    delete g_log;
+    g_log = nullptr;
+    delete g_archive;
+    g_archive = nullptr;
+    delete g_cmdLine;
+    g_cmdLine = nullptr;
+    delete g_platform;
+    g_platform = nullptr;
+}
+
+ANGLE_LIBTESTER_EXPORT bool deqp_libtester_run(const char *caseName)
+{
+    const char *emptyString = "";
+    if (g_platform == nullptr && !deqp_libtester_init_platform(1, &emptyString))
+    {
+        tcu::die("Failed to initialize platform.");
+    }
+
+    try
+    {
+        // Poll platform events
+        const bool platformOk = g_platform->processEvents();
+
+        if (platformOk)
+        {
+            const tcu::TestStatus &result = g_executor->execute(caseName);
+            switch (result.getCode())
+            {
+                case QP_TEST_RESULT_PASS:
+                case QP_TEST_RESULT_NOT_SUPPORTED:
+                    return true;
+                case QP_TEST_RESULT_QUALITY_WARNING:
+                    std::cout << "Quality warning! " << result.getDescription() << std::endl;
+                    return true;
+                case QP_TEST_RESULT_COMPATIBILITY_WARNING:
+                    std::cout << "Compatiblity warning! " << result.getDescription() << std::endl;
+                    return true;
+                default:
+                    return false;
+            }
+        }
+        else
+        {
+            std::cout << "Aborted test!" << std::endl;
+        }
+    }
+    catch (const std::exception &e)
+    {
+        std::cout << "Exception running test: " << e.what() << std::endl;
+    }
+
+    return false;
+}
diff --git a/src/third_party/angle/src/tests/deqp_support/angle_deqp_tests_main.cpp b/src/third_party/angle/src/tests/deqp_support/angle_deqp_tests_main.cpp
new file mode 100644
index 0000000..468f1c1
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/angle_deqp_tests_main.cpp
@@ -0,0 +1,14 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angle_deqp_tests_main.cpp: Entry point for ANGLE's dEQP tests.
+
+#include "angle_deqp_libtester.h"
+
+int main(int argc, const char *argv[])
+{
+    return deqp_libtester_main(argc, argv);
+}
diff --git a/src/third_party/angle/src/tests/deqp_support/deqp_egl_test_expectations.txt b/src/third_party/angle/src/tests/deqp_support/deqp_egl_test_expectations.txt
new file mode 100644
index 0000000..b354022
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/deqp_egl_test_expectations.txt
@@ -0,0 +1,288 @@
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains a list of defective dEQP conformance tests. The expected
+// format is:
+//  {BUG#} {MODIFIERS} : {TEST_NAME} = {PASS,FAIL,FLAKY,TIMEOUT,SKIP}
+//
+// MODIFIERS can be a combination of the below list:
+//  WIN XP VISTA WIN7 MAC LEOPARD SNOWLEOPARD LION LINUX CHROMEOS MOUNTAINLION
+//  MAVERICKS
+//  NVIDIA AMD INTEL
+//  0xabcd - GPU PCI device ID. Specifying a PCI id requires a vendor.
+//  DEBUG RELEASE
+// TODO(jmadill): Add ANGLE Renderer selection modifiers
+//
+// TEST_NAME can be a specific test name, or have a '*' in the end, which
+// indicates a prefix matching.
+//
+// Examples:
+//  91530 MAC WIN LINUX : context_lost_restored = TIMEOUT
+//  91533 WIN : gl_min_uniforms = FAIL
+//  91531 MAC WIN LINUX : conformance_more_* = SKIP
+//  91532 MAC NVIDIA 0x0640 : tex_image_and_sub_image_2d_with_video = PASS FAIL
+
+// ANGLE does not yet support multithreading
+1340 WIN MAC LINUX : dEQP-EGL.functional.sharing.gles2.multithread.* = SKIP
+1340 WIN MAC LINUX : dEQP-EGL.functional.multithread.* = SKIP
+1340 WIN MAC LINUX : dEQP-EGL.functional.render.multi_thread.* = SKIP
+
+// dEQP doesn't handle configs created for extensions
+1662 WIN : dEQP-EGL.functional.color_clears.single_context.gles2.other = FAIL
+1662 WIN : dEQP-EGL.functional.color_clears.single_context.gles3.other = FAIL
+1662 WIN : dEQP-EGL.functional.color_clears.multi_context.gles2.other = FAIL
+1662 WIN : dEQP-EGL.functional.color_clears.multi_context.gles3.other = FAIL
+1662 WIN : dEQP-EGL.functional.color_clears.multi_thread.gles2.other = FAIL
+1662 WIN : dEQP-EGL.functional.color_clears.multi_thread.gles3.other = FAIL
+1662 WIN : dEQP-EGL.functional.render.single_context.gles2.other = FAIL
+1662 WIN : dEQP-EGL.functional.render.single_context.gles3.other = FAIL
+1662 WIN : dEQP-EGL.functional.render.multi_context.gles2.other = FAIL
+1662 WIN : dEQP-EGL.functional.render.multi_context.gles3.other = FAIL
+1662 WIN : dEQP-EGL.functional.render.multi_context.gles2_gles3.other = FAIL
+1662 WIN : dEQP-EGL.functional.render.multi_thread.gles2.other = FAIL
+1662 WIN : dEQP-EGL.functional.render.multi_thread.gles3.other = FAIL
+1662 WIN : dEQP-EGL.functional.swap_buffers.other = FAIL
+1662 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.other_clear = FAIL
+1662 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.other_render = FAIL
+1662 WIN : dEQP-EGL.functional.query_context.get_current_context.other = FAIL
+1662 WIN : dEQP-EGL.functional.query_context.get_current_surface.other = FAIL
+1662 WIN : dEQP-EGL.functional.query_context.get_current_display.other = FAIL
+1662 WIN : dEQP-EGL.functional.query_context.query_context.other = FAIL
+1662 WIN : dEQP-EGL.functional.query_surface.simple.window.other = FAIL
+1662 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.other = FAIL
+1662 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.other = FAIL
+1662 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.other = FAIL
+1662 WIN : dEQP-EGL.functional.native_color_mapping.native_window.other_clear = SKIP
+1662 WIN : dEQP-EGL.functional.native_color_mapping.native_window.other_render = SKIP
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Temprory entries: they should be removed once the bugs are fixed.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// TODO(jmadill): Triage these into permananent and temporary failures.
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgb565_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgb565_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgb565_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgb888_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgb888_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgb888_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgba4444_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgba4444_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgba4444_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgba5551_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgba5551_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgba5551_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgba8888_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgba8888_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.window.rgba8888_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgb565_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgb565_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgb565_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgb888_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgb888_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgb888_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba4444_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba4444_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba4444_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba5551_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba5551_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba5551_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba8888_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba8888_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba8888_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgb565_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgb565_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgb565_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgb888_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgb888_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgb888_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgba4444_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgba4444_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgba4444_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgba5551_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgba5551_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgba5551_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgba8888_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgba8888_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.window.rgba8888_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgb565_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgb565_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgb565_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgb888_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgb888_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgb888_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgba4444_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgba4444_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgba4444_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgba5551_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgba5551_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgba5551_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgba8888_no_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgba8888_depth_no_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_surface.set_attribute.pbuffer.rgba8888_depth_stencil = SKIP
+1340 WIN : dEQP-EGL.functional.query_config.get_configs.get_configs_bounds = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.buffer_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.red_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.green_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.blue_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.luminance_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.alpha_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.alpha_mask_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.bind_to_texture_rgb = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.bind_to_texture_rgba = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.color_buffer_type = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.config_caveat = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.config_id = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.depth_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.level = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.max_swap_interval = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.min_swap_interval = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.native_renderable = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.native_visual_type = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.sample_buffers = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.samples = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.stencil_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.surface_type = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.transparent_red_value = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.transparent_green_value = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_only.transparent_blue_value = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.buffer_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.red_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.green_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.blue_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.luminance_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.alpha_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.alpha_mask_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.bind_to_texture_rgb = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.bind_to_texture_rgba = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.color_buffer_type = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.config_caveat = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.config_id = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.depth_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.level = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.max_swap_interval = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.min_swap_interval = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.native_renderable = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.native_visual_type = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.sample_buffers = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.samples = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.stencil_size = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.surface_type = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.transparent_red_value = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.transparent_green_value = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.simple.selection_and_sort.transparent_blue_value = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.random.color_sizes = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.random.color_depth_stencil_sizes = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.random.buffer_sizes = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.random.surface_type = FAIL
+1340 WIN : dEQP-EGL.functional.choose_config.random.sample_buffers = FAIL
+1340 WIN : dEQP-EGL.functional.render.single_context.gles2.rgba5551_window = FAIL
+1340 WIN : dEQP-EGL.functional.render.single_context.gles2.rgba5551_pbuffer = FAIL
+1340 WIN : dEQP-EGL.functional.render.single_context.gles3.rgba5551_window = FAIL
+1340 WIN : dEQP-EGL.functional.render.single_context.gles3.rgba5551_pbuffer = FAIL
+1340 WIN : dEQP-EGL.functional.render.multi_context.gles2.rgba5551_window = FAIL
+1340 WIN : dEQP-EGL.functional.render.multi_context.gles2.rgba5551_pbuffer = FAIL
+1340 WIN : dEQP-EGL.functional.render.multi_context.gles3.rgba5551_window = FAIL
+1340 WIN : dEQP-EGL.functional.render.multi_context.gles3.rgba5551_pbuffer = FAIL
+1340 WIN : dEQP-EGL.functional.render.multi_context.gles2_gles3.rgba5551_window = FAIL
+1340 WIN : dEQP-EGL.functional.render.multi_context.gles2_gles3.rgba5551_pbuffer = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.tex_rgb8_tex_subimage_rgb565 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.tex_rgb565_tex_subimage_rgb8 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.tex_rgba8_tex_subimage_rgba5_a1 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.tex_rgba8_tex_subimage_rgba4 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.tex_rgba5_a1_tex_subimage_rgba8 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.tex_rgba5_a1_tex_subimage_rgba4 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.tex_rgba4_tex_subimage_rgba8 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.tex_rgba4_tex_subimage_rgba5_a1 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.renderbuffer_rgba4_tex_subimage_rgba8 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.renderbuffer_rgba4_tex_subimage_rgba5_a1 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.renderbuffer_rgb5_a1_tex_subimage_rgba8 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.renderbuffer_rgb5_a1_tex_subimage_rgba4 = FAIL
+1340 WIN : dEQP-EGL.functional.image.modify.renderbuffer_rgb565_tex_subimage_rgb8 = FAIL
+1340 WIN : dEQP-EGL.functional.negative_api.choose_config = SKIP
+1340 WIN : dEQP-EGL.functional.negative_api.get_display = FAIL
+1340 WIN : dEQP-EGL.functional.negative_api.surface_attrib = SKIP
+1340 WIN : dEQP-EGL.functional.negative_api.swap_interval = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgb565_no_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgb565_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgb565_depth_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgb888_no_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgb888_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgb888_depth_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgba4444_no_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgba4444_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgba4444_depth_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgba5551_no_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgba5551_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgba5551_depth_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgba8888_no_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgba8888_depth_no_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.swap_buffers.rgba8888_depth_stencil = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb565_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb565_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb565_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb565_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb565_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb565_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb888_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb888_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb888_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb888_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb888_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgb888_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba4444_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba4444_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba4444_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba4444_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba4444_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba4444_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba5551_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba5551_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba5551_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba5551_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba5551_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba5551_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba8888_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba8888_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba8888_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba8888_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba8888_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_color_mapping.native_window.rgba8888_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb565_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb565_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb565_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb565_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb565_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb565_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb888_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb888_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb888_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb888_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb888_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgb888_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba4444_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba4444_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba4444_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba4444_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba4444_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba4444_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba5551_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba5551_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba5551_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba5551_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba5551_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba5551_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba8888_no_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba8888_no_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba8888_depth_no_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba8888_depth_no_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba8888_depth_stencil_clear = FAIL
+1340 WIN : dEQP-EGL.functional.native_coord_mapping.native_window.rgba8888_depth_stencil_render = FAIL
+1340 WIN : dEQP-EGL.functional.get_proc_address.extension.egl_ext_platform_base = FAIL
+1340 WIN : dEQP-EGL.functional.preserve_swap.preserve.no_read_before_swap.* = SKIP
+1340 WIN : dEQP-EGL.functional.preserve_swap.preserve.read_before_swap.* = SKIP
+1340 WIN : dEQP-EGL.functional.resize.back_buffer.* = SKIP
+1340 WIN : dEQP-EGL.functional.resize.pixel_density.* = SKIP
diff --git a/src/third_party/angle/src/tests/deqp_support/deqp_gles2_test_expectations.txt b/src/third_party/angle/src/tests/deqp_support/deqp_gles2_test_expectations.txt
new file mode 100644
index 0000000..b94e05b
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/deqp_gles2_test_expectations.txt
@@ -0,0 +1,158 @@
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains a list of defective dEQP conformance tests. The expected
+// format is:
+//  {BUG#} {MODIFIERS} : {TEST_NAME} = {PASS,FAIL,FLAKY,TIMEOUT,SKIP}
+//
+// MODIFIERS can be a combination of the below list:
+//  WIN XP VISTA WIN7 MAC LEOPARD SNOWLEOPARD LION LINUX CHROMEOS MOUNTAINLION
+//  MAVERICKS
+//  NVIDIA AMD INTEL
+//  0xabcd - GPU PCI device ID. Specifying a PCI id requires a vendor.
+//  DEBUG RELEASE
+// TODO(jmadill): Add ANGLE Renderer selection modifiers
+//
+// TEST_NAME can be a specific test name, or have a '*' in the end, which
+// indicates a prefix matching.
+//
+// Examples:
+//  91530 MAC WIN LINUX : context_lost_restored = TIMEOUT
+//  91533 WIN : gl_min_uniforms = FAIL
+//  91531 MAC WIN LINUX : conformance_more_* = SKIP
+//  91532 MAC NVIDIA 0x0640 : tex_image_and_sub_image_2d_with_video = PASS FAIL
+
+// Skip these tests due to timeouts
+1034 DEBUG RELEASE : dEQP-GLES2.functional.flush_finish.* = SKIP
+
+// Don't run these tests for faster turnover
+998 DEBUG RELEASE : dEQP-GLES2.performance.* = SKIP
+998 DEBUG RELEASE : dEQP-GLES2.stress.* = SKIP
+
+// Tests that we fail because they're not in line with the WebGL spec
+1335 DEBUG RELEASE : dEQP-GLES2.functional.shaders.preprocessor.conditional_inclusion.basic_2* = FAIL
+
+// Failures related to not supporting separate depth/stencil masks on D3D11.
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.depth_stencil.stencil_depth_funcs.stencil_* = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.depth_stencil.stencil_ops.* = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.depth_stencil.write_mask.* = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.add_constant_color_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.add_constant_color_one_minus_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.add_one_minus_constant_color_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.add_one_minus_constant_color_one_minus_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.add_constant_alpha_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.add_constant_alpha_one_minus_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.add_one_minus_constant_alpha_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.add_one_minus_constant_alpha_one_minus_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.subtract_constant_color_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.subtract_constant_color_one_minus_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.subtract_one_minus_constant_color_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.subtract_one_minus_constant_color_one_minus_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.subtract_constant_alpha_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.subtract_constant_alpha_one_minus_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.subtract_one_minus_constant_alpha_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.subtract_one_minus_constant_alpha_one_minus_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.reverse_subtract_constant_color_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.reverse_subtract_constant_color_one_minus_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.reverse_subtract_one_minus_constant_color_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.reverse_subtract_one_minus_constant_color_one_minus_constant_alpha = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.reverse_subtract_constant_alpha_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.reverse_subtract_constant_alpha_one_minus_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.reverse_subtract_one_minus_constant_alpha_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.blend.equation_src_func_dst_func.reverse_subtract_one_minus_constant_alpha_one_minus_constant_color = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.random.* = FAIL
+1655 D3D11 : dEQP-GLES2.functional.fragment_ops.interaction.basic_shader.* = FAIL
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Temporary entries: they should be removed once the bugs are fixed.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// A Clang roll causes a crash in the dEQP rsgExpression file on Linux NVIDIA. Bug ID is a Chromium bug ID.
+// Failure expectations did not work, so skipping these tests.
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.conditionals.combined.7 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.conditionals.vertex.94 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.basic_expression.vertex.78 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.conditionals.vertex.2 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.conditionals.vertex.33 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.comparison_ops.fragment.11 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.scalar_conversion.fragment.11 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.scalar_conversion.combined.11 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.basic_expression.vertex.98 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.scalar_conversion.combined.48 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.swizzle.vertex.38 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.scalar_conversion.combined.79 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.conditionals.fragment.32 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.conditionals.combined.32 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.all_features.fragment.29 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES2.functional.shaders.random.trigonometric.fragment.77 = SKIP
+
+
+// Only fails in D3D11 32-bit.
+1418 D3D11 : dEQP-GLES2.functional.clipping.triangle_vertex.clip_three.clip_pos_x_pos_y_pos_z_and_neg_x_pos_y_pos_z_and_neg_x_neg_y_neg_z = FAIL
+
+// Failures on the D3D11 bots that do not reproduce locally
+// TODO(jmadill): Figure out why these fail on the bots, but not locally.
+1108 D3D11 : dEQP-GLES2.functional.shaders.struct.local.dynamic_loop_struct_array_fragment = FAIL
+1108 D3D11 : dEQP-GLES2.functional.shaders.invariance.highp.loop_2 = FAIL
+1108 D3D11 : dEQP-GLES2.functional.shaders.invariance.mediump.loop_2 = FAIL
+
+// OpenGL desktop back-end failures
+1656 OPENGL : dEQP-GLES2.functional.fbo.completeness.renderable.texture.stencil.srgb8_alpha8 = FAIL
+1656 OPENGL : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8_alpha8 = FAIL
+
+// Mac specific failures
+1143 MAC : dEQP-GLES2.functional.shaders.scoping.valid.local_int_variable_hides_struct_type_* = FAIL
+1143 MAC : dEQP-GLES2.functional.shaders.scoping.valid.local_struct_variable_hides_struct_type_* = FAIL
+1143 MAC : dEQP-GLES2.functional.shaders.scoping.valid.function_parameter_hides_struct_type_* = FAIL
+1143 MAC : dEQP-GLES2.functional.shaders.random.trigonometric.vertex.65 = FAIL
+
+// Android only failures
+1484 ANDROID : dEQP-GLES2.functional.vertex_arrays.* = SKIP
+1485 ANDROID : dEQP-GLES2.functional.clipping.triangle_vertex.clip_three.clip_neg_x_neg_z_and_pos_x_pos_z_and_neg_x_neg_y_pos_z = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.none_none_none_tex = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.none_none_rbo_tex = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.none_none_tex_none = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.none_none_tex_rbo = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.none_none_tex_tex = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.rbo_none_none_tex = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.rbo_none_rbo_tex = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.rbo_none_tex_none = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.rbo_none_tex_rbo = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.rbo_none_tex_tex = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.tex_none_none_tex = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.tex_none_rbo_tex = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.tex_none_tex_none = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.tex_none_tex_rbo = FAIL
+1486 ANDROID : dEQP-GLES2.functional.fbo.completeness.attachment_combinations.tex_none_tex_tex = FAIL
+1487 ANDROID : dEQP-GLES2.functional.fbo.completeness.renderable.texture.color0.depth_stencil_unsigned_int_24_8 = FAIL
+1487 ANDROID : dEQP-GLES2.functional.fbo.completeness.renderable.texture.color0.srgb8 = FAIL
+1487 ANDROID : dEQP-GLES2.functional.fbo.completeness.renderable.texture.stencil.depth_stencil_unsigned_int_24_8 = FAIL
+1487 ANDROID : dEQP-GLES2.functional.fbo.completeness.renderable.texture.stencil.srgb8 = FAIL
+1487 ANDROID : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.depth_stencil_unsigned_int_24_8 = FAIL
+1487 ANDROID : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL
+1488 ANDROID : dEQP-GLES2.functional.shaders.return.conditional_return_always_vertex = FAIL
+1488 ANDROID : dEQP-GLES2.functional.shaders.return.conditional_return_always_fragment = FAIL
+1488 ANDROID : dEQP-GLES2.functional.shaders.return.output_write_always_vertex = FAIL
+1488 ANDROID : dEQP-GLES2.functional.shaders.return.output_write_always_fragment = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.2d.generate.a8_fastest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.2d.generate.a8_nicest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.2d.generate.l8_fastest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.2d.generate.l8_nicest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.2d.generate.la88_fastest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.2d.generate.la88_nicest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.cube.generate.a8_fastest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.cube.generate.a8_nicest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.cube.generate.l8_fastest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.cube.generate.l8_nicest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.cube.generate.la88_fastest = FAIL
+1489 ANDROID : dEQP-GLES2.functional.texture.mipmap.cube.generate.la88_nicest = FAIL
+
+// Windows Linux and Mac failures
+1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.color0.srgb8 = FAIL
+1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.stencil.srgb8 = FAIL
+1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.depth_component_unsigned_short = FAIL
+1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.depth_component_unsigned_int = FAIL
+1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL
diff --git a/src/third_party/angle/src/tests/deqp_support/deqp_gles31_test_expectations.txt b/src/third_party/angle/src/tests/deqp_support/deqp_gles31_test_expectations.txt
new file mode 100644
index 0000000..116e8a0
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/deqp_gles31_test_expectations.txt
@@ -0,0 +1,1366 @@
+// Copyright 2016 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.
+
+// This file contains a list of defective dEQP conformance tests. The expected
+// format is:
+//  {BUG#} {MODIFIERS} : {TEST_NAME} = {PASS,FAIL,FLAKY,TIMEOUT,SKIP}
+//
+// MODIFIERS can be a combination of the below list:
+//  WIN XP VISTA WIN7 MAC LEOPARD SNOWLEOPARD LION LINUX CHROMEOS MOUNTAINLION
+//  MAVERICKS
+//  NVIDIA AMD INTEL
+//  0xabcd - GPU PCI device ID. Specifying a PCI id requires a vendor.
+//  DEBUG RELEASE
+// TODO(jmadill): Add ANGLE Renderer selection modifiers
+//
+// TEST_NAME can be a specific test name, or have a '*' in the end, which
+// indicates a prefix matching.
+//
+// Examples:
+//  91530 MAC WIN LINUX : context_lost_restored = TIMEOUT
+//  91533 WIN : gl_min_uniforms = FAIL
+//  91531 MAC WIN LINUX : conformance_more_* = SKIP
+//  91532 MAC NVIDIA 0x0640 : tex_image_and_sub_image_2d_with_video = PASS FAIL
+
+// Crashing Tests
+1659 NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.random.0 = SKIP
+1659 NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.random.10 = SKIP
+1659 NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.random.15 = SKIP
+1659 NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.random.18 = SKIP
+1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.resource_list.vertex_fragment.builtin_gl_position = SKIP
+1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.resource_list.vertex_fragment.default_block_struct_member = SKIP
+1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.array_size.vertex_fragment.default_block_struct_member = SKIP
+1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.name_length.vertex_fragment.default_block_struct_member = SKIP
+1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.type.vertex_fragment.struct.* = SKIP
+1442 OPENGL D3D11 : dEQP-GLES31.functional.vertex_attribute_binding.* = SKIP
+1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP
+1442 D3D11 : dEQP-GLES31.functional.state_query.shader.sampler_type = SKIP
+
+// OpenGL Failing Tests
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.samples_* = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_min_filter = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_mag_filter = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_wrap_s = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_wrap_t = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_wrap_r = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_min_lod = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_max_lod = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_compare_mode = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_compare_func = FAIL
+1442 OPENGL : dEQP-GLES31.functional.texture.multisample.negative.texture_base_level = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_1_texture_2d_array = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_4_texture_2d_array = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_1_texture_int_2d = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_4_texture_int_2d = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_1_texture_int_2d_array = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_4_texture_int_2d_array = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_1_texture_uint_2d = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_4_texture_uint_2d = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_1_texture_uint_2d_array = FAIL
+1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_4_texture_uint_2d_array = FAIL
+
+// D3D11 Failing Tests
+1442 D3D11 : dEQP-GLES31.functional.fbo.completeness.no_attachments = FAIL
+1442 D3D11 : dEQP-GLES31.functional.fbo.no_attachments.* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_color_texture_samples_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_depth_texture_samples_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_integer_samples_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_sample_mask_words_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_framebuffer_width_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_framebuffer_height_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_framebuffer_samples_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_shared_memory_size_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_atomic_counter_buffers_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_atomic_counters_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_image_uniforms_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_shader_storage_blocks_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_atomic_counter_buffer_bindings_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_atomic_counter_buffer_size_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_combined_atomic_counter_buffers_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_combined_atomic_counters* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_image_units_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_combined_image_uniforms_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_shader_storage_buffer_bindings_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_shader_storage_block_size_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_combined_shader_storage_blocks_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_combined_shader_output_resources_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_uniform_buffer_bindings_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_combined_texture_image_units_* = FAIL
+1729 D3D11 : dEQP-GLES31.functional.state_query.indexed.atomic_counter_buffer_* = FAIL
+1951 D3D11 : dEQP-GLES31.functional.state_query.indexed.shader_storage_buffer_* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.* = FAIL
+1679 D3D11 : dEQP-GLES31.functional.state_query.texture_level.texture_2d_multisample.* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.texture.multisample.* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.framebuffer_default.framebuffer_default_width_get_framebuffer_parameteriv = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.framebuffer_default.framebuffer_default_height_get_framebuffer_parameteriv = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.framebuffer_default.framebuffer_default_samples_get_framebuffer_parameteriv = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.framebuffer_default.framebuffer_default_fixed_sample_locations_get_framebuffer_parameteriv = FAIL
+1442 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.texture.texparameter* = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texparameter* = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.texture.texparameter* = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.async.case_4_log = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.async.case_5_callback = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_2 = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_3 = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_9 = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_10 = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_27 = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_filters.case_28 = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_2 = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_3 = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_9 = SKIP
+1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_10 = SKIP
+
+// OPENGL Failing Tests
+1665 WIN NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.negative.command_offset_not_in_buffer_unsigned32_wrap = FAIL
+1442 NVIDIA OPENGL : dEQP-GLES31.functional.fbo.no_attachments.maximums.all = FAIL
+
+// OpenGL and D3D11 Failing Tests
+1663 OPENGL D3D11 : dEQP-GLES31.functional.draw_indirect.compute_interop.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.num_work_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.work_group_size = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.work_group_id = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.local_invocation_id = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.global_invocation_id = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.local_invocation_index = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.int_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.int_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.ivec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.ivec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.ivec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.ivec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.ivec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.ivec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.abs.ivec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.int_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.int_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.ivec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.ivec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.ivec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.ivec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.ivec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.ivec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.sign.ivec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floor.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.trunc.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.round.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.roundeven.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ceil.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.fract.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.modf.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isnan.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.isinf.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstoint.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.intbitstofloat.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.intbitstofloat.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.intbitstofloat.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.uintbitstofloat.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.uintbitstofloat.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.uintbitstofloat.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packsnorm4x8_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packsnorm4x8_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packsnorm4x8_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.unpacksnorm4x8_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packunorm4x8_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packunorm4x8_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packunorm4x8_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.unpackunorm4x8_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packsnorm2x16_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packsnorm2x16_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packsnorm2x16_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.unpacksnorm2x16_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packunorm2x16_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packunorm2x16_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packunorm2x16_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.unpackunorm2x16_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packhalf2x16_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.unpackhalf2x16_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uint_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uint_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uint_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uint_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.umulextended.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.umulextended.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.umulextended.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.umulextended.uvec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.imulextended.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.imulextended.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.imulextended.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.imulextended.ivec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.int_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.int_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uint_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uint_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.int_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.int_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uint_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uint_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.int_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.int_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uint_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uint_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.int_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.int_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uint_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uint_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.int_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.int_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uint_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uint_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.int_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.int_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.int_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uint_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uint_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uint_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec2_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec2_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec2_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec3_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec3_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec3_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec4_lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec4_mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec4_highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sub.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mul.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.div.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.div.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.div.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.div.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.div.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.div.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.div.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.div.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.radians.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.degrees.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sin.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sin.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sin.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sin.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sin.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sin.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sin.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sin.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asin.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acos.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acos.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acos.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acos.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acos.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acos.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acos.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acos.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan2.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan2.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan2.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan2.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atan.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sinh.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cosh.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.tanh.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.asinh.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acosh.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acosh.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acosh.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acosh.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acosh.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acosh.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acosh.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.acosh.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atanh.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atanh.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atanh.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atanh.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atanh.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atanh.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atanh.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.atanh.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.pow.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.exp2.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.log2.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sqrt.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inversesqrt.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.abs.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.sign.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.floor.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.trunc.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.round.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.roundeven.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ceil.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.fract.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mod.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mod.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mod.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mod.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mod.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mod.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mod.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mod.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.modf.lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.modf.mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.modf.highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.min.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.min.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.min.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.min.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.min.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.min.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.min.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.min.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.max.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.max.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.max.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.max.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.max.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.max.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.max.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.max.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.clamp.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.clamp.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.clamp.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.clamp.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.clamp.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.clamp.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.clamp.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.clamp.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.mix.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.step.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.smoothstep.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.smoothstep.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.smoothstep.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.smoothstep.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.length.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.distance.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.dot.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cross.lowp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cross.mediump_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.cross.highp_compute = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.normalize.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.faceforward.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.reflect.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.reflect.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.reflect.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.reflect.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.reflect.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.reflect.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.reflect.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.reflect.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.reflect.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.lowp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.lowp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.lowp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.lowp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.mediump_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.mediump_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.mediump_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.mediump_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.highp_compute.scalar = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.highp_compute.vec2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.highp_compute.vec3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.refract.highp_compute.vec4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.lowp_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.lowp_compute.mat2x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.lowp_compute.mat2x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.lowp_compute.mat3x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.lowp_compute.mat3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.lowp_compute.mat3x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.lowp_compute.mat4x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.lowp_compute.mat4x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.lowp_compute.mat4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.mediump_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.mediump_compute.mat2x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.mediump_compute.mat2x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.mediump_compute.mat3x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.mediump_compute.mat3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.mediump_compute.mat3x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.mediump_compute.mat4x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.mediump_compute.mat4x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.mediump_compute.mat4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.highp_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.highp_compute.mat2x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.highp_compute.mat2x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.highp_compute.mat3x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.highp_compute.mat3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.highp_compute.mat3x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.highp_compute.mat4x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.highp_compute.mat4x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.matrixcompmult.highp_compute.mat4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.lowp_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.lowp_compute.mat2x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.lowp_compute.mat2x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.lowp_compute.mat3x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.lowp_compute.mat3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.lowp_compute.mat3x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.lowp_compute.mat4x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.lowp_compute.mat4x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.lowp_compute.mat4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.mediump_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.mediump_compute.mat2x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.mediump_compute.mat2x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.mediump_compute.mat3x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.mediump_compute.mat3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.mediump_compute.mat3x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.mediump_compute.mat4x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.mediump_compute.mat4x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.mediump_compute.mat4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.highp_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.highp_compute.mat2x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.highp_compute.mat2x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.highp_compute.mat3x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.highp_compute.mat3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.highp_compute.mat3x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.highp_compute.mat4x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.highp_compute.mat4x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.outerproduct.highp_compute.mat4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.lowp_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.lowp_compute.mat2x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.lowp_compute.mat2x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.lowp_compute.mat3x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.lowp_compute.mat3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.lowp_compute.mat3x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.lowp_compute.mat4x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.lowp_compute.mat4x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.lowp_compute.mat4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.mediump_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.mediump_compute.mat2x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.mediump_compute.mat2x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.mediump_compute.mat3x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.mediump_compute.mat3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.mediump_compute.mat3x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.mediump_compute.mat4x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.mediump_compute.mat4x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.mediump_compute.mat4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.highp_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.highp_compute.mat2x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.highp_compute.mat2x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.highp_compute.mat3x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.highp_compute.mat3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.highp_compute.mat3x4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.highp_compute.mat4x2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.highp_compute.mat4x3 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.transpose.highp_compute.mat4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.determinant.lowp_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.determinant.mediump_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.determinant.highp_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inverse.lowp_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.inverse.mediump_compute.mat2 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.frexp.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.ldexp.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.opaque_type_indexing.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.functions.overloading.arrays_of_arrays_size_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.functions.overloading.arrays_of_arrays_size_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.float_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.float_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.int_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.int_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.bool_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.bool_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.struct_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.struct_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.mat3_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.mat3_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.constant_expression_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.length.constant_expression_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.array_access.constant_expression_access_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.array_access.constant_expression_access_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.array_access.dynamic_expression_access_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.array_access.dynamic_expression_access_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.single_statement_multiple_declarations.explicit_constructor.float_2_dimensions_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.single_statement_multiple_declarations.explicit_constructor.float_2_dimensions_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.single_statement_multiple_declarations.explicit_constructor.int_3_dimensions_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.single_statement_multiple_declarations.explicit_constructor.int_3_dimensions_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.single_statement_multiple_declarations.implicit_constructor.float_2_dimensions_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.single_statement_multiple_declarations.implicit_constructor.float_2_dimensions_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.single_statement_multiple_declarations.implicit_constructor.int_3_dimensions_vertex = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.arrays_of_arrays.single_statement_multiple_declarations.implicit_constructor.int_3_dimensions_fragment = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.linkage.shader_storage_block.mismatch_number_of_declarations = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.linkage.shader_storage_block.mismatch_order = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.linkage.shader_storage_block.mismatch_type = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.linkage.shader_storage_block.mismatch_member_name = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.linkage.shader_storage_block.mismatch_member_unsized_sized_array = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.linkage.shader_storage_block.mismatch_member_array_size = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.linkage.shader_storage_block.mismatch_with_and_without_instance_name = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.linkage.shader_storage_block.mismatch_block_array_size = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_vertex_attribs = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_vertex_uniform_vectors = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_vertex_output_vectors = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_fragment_input_vectors = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_fragment_uniform_vectors = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_draw_buffers = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_vertex_texture_image_units = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_combined_texture_image_units = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_texture_image_units = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.min_program_texel_offset = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_program_texel_offset = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_image_units = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_vertex_image_uniforms = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_fragment_image_uniforms = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_compute_image_uniforms = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_combined_image_uniforms = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_combined_shader_output_resources = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_compute_uniform_components = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_compute_texture_image_units = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_compute_atomic_counters = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_compute_atomic_counter_buffers = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_vertex_atomic_counters = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_fragment_atomic_counters = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_combined_atomic_counters = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_atomic_counter_bindings = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_vertex_atomic_counter_buffers = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_fragment_atomic_counter_buffers = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_combined_atomic_counter_buffers = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_atomic_counter_buffer_size = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_compute_work_group_count = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_constants.core.max_compute_work_group_size = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.helper_invocation.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.empty = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ubo_to_ssbo_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ubo_to_ssbo_single_group = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ubo_to_ssbo_multiple_invocations = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ubo_to_ssbo_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.copy_ssbo_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.copy_ssbo_multiple_invocations = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.copy_ssbo_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_rw_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_rw_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_unsized_arr_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_unsized_arr_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.write_multiple_arr_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.write_multiple_arr_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.write_multiple_unsized_arr_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.write_multiple_unsized_arr_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_local_barrier_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_local_barrier_single_group = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_local_barrier_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_cmd_barrier_single = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_cmd_barrier_multiple = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.shared_var_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.shared_var_single_group = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.shared_var_multiple_invocations = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.shared_var_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.shared_atomic_op_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.shared_atomic_op_single_group = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.shared_atomic_op_multiple_invocations = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.shared_atomic_op_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.copy_image_to_ssbo_small = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.copy_image_to_ssbo_large = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.copy_ssbo_to_image_small = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.copy_ssbo_to_image_large = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.image_barrier_single = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.image_barrier_multiple = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_single_invocation = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_single_group = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_multiple_invocations = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_multiple_groups = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.shared_var.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.indirect_dispatch.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ssbo.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.2_level_array.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.3_level_array.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.2_level_struct_array.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.basic_type_arrays.4 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.basic_type_arrays.10 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.1 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.7 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.10 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.13 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.18 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.20 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.29 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.41 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.1 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.8 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.22 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.37 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.38 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.image_load_store.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.atomic_counter.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth32f_stencil8_2d = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth32f_stencil8_2d_array = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth32f_stencil8_cube = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth24_stencil8_2d = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth24_stencil8_2d_array = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth24_stencil8_cube = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.render.depth32f_stencil8_clear = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.render.depth32f_stencil8_draw = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.render.depth24_stencil8_clear = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.render.depth24_stencil8_draw = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.misc.compare_mode_effect = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.misc.base_level = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.texture.gather.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.boolean.sample_mask_* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.integer.texture_binding_2d_multisample_* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.integer.dispatch_indirect_buffer_binding_* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.integer.program_pipeline_binding_* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.indexed.sample_mask_value_* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.indexed.image_binding* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.texture.texture_2d.depth_stencil_mode_* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.texture.texture_cube_map.depth_stencil_mode_* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.texture.texture_2d_array.depth_stencil_mode_* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.texture.texture_3d.depth_stencil_mode_* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.texture.texture_2d_multisample.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rgb10_a2ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.r8i_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.r8ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.r16i_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.r16ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.r32i_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.r32ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rg8i_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rg8ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rg16i_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rg16ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rg32i_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rg32ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rgba8i_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rgba8ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rgba16i_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rgba16ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rgba32i_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.rgba32ui_samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.texture_2d_multisample.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.partial_query.num_sample_counts = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.internal_format.partial_query.samples = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.program.program_separable_get_programiv = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.program.compute_work_group_size_get_programiv = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.program.active_atomic_counter_buffers_get_programiv = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.state_query.program_pipeline.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.synchronization.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.geometry_shading.query.geometry_linked_vertices_out = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.geometry_shading.query.geometry_linked_input_type = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.geometry_shading.query.geometry_linked_output_type = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.geometry_shading.query.geometry_shader_invocations = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.separate_shader.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.uniform_location.nested_array.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.error_filters.case_11 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.error_groups.case_11 = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.buffer.bind_buffer_range = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader.compile_compute_shader = SKIP
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.primitive_bounding_box = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.geometry_shader = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.tessellation_shader = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.buffer.bind_buffer_range = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.shader.compile_compute_shader = SKIP
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.primitive_bounding_box = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.geometry_shader = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.tessellation_shader = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.bind_buffer_range = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.read_pixels_format_mismatch = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.framebuffer_texture2d = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.blit_framebuffer = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.invalidate_sub_framebuffer = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.renderbuffer_storage_multisample = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.copyteximage2d_invalid_format = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.copyteximage2d_inequal_width_height_cube = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.copyteximage2d_max_width_height = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.copytexsubimage2d_invalid_offset = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.copytexsubimage2d_texture_internalformat = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texparameteri = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texparameterf = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texparameteriv = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texparameterfv = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.compressedtexsubimage2d = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.compressedtexsubimage2d_invalid_size = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texsubimage3d_neg_level = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texsubimage3d_neg_offset = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.copytexsubimage3d_invalid_offset = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.compressedtexsubimage3d = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.compressedtexsubimage3d_invalid_buffer_target = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.shader.compile_compute_shader = SKIP
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.vertex_array.draw_range_elements = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.vertex_array.draw_range_elements_incomplete_primitive = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.primitive_bounding_box = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.geometry_shader = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.tessellation_shader = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.debug.object_labels.program_pipeline = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.ubo.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.ssbo.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.image.image2d.* = FAIL
+1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.image.image3d.* = FAIL
diff --git a/src/third_party/angle/src/tests/deqp_support/deqp_gles3_test_expectations.txt b/src/third_party/angle/src/tests/deqp_support/deqp_gles3_test_expectations.txt
new file mode 100644
index 0000000..5dba77b
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/deqp_gles3_test_expectations.txt
@@ -0,0 +1,393 @@
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains a list of defective dEQP conformance tests. The expected
+// format is:
+//  {BUG#} {MODIFIERS} : {TEST_NAME} = {PASS,FAIL,FLAKY,TIMEOUT,SKIP}
+//
+// MODIFIERS can be a combination of the below list:
+//  WIN XP VISTA WIN7 MAC LEOPARD SNOWLEOPARD LION LINUX CHROMEOS MOUNTAINLION
+//  MAVERICKS
+//  NVIDIA AMD INTEL
+//  0xabcd - GPU PCI device ID. Specifying a PCI id requires a vendor.
+//  DEBUG RELEASE
+// TODO(jmadill): Add ANGLE Renderer selection modifiers
+//
+// TEST_NAME can be a specific test name, or have a '*' in the end, which
+// indicates a prefix matching.
+//
+// Examples:
+//  91530 MAC WIN LINUX : context_lost_restored = TIMEOUT
+//  91533 WIN : gl_min_uniforms = FAIL
+//  91531 MAC WIN LINUX : conformance_more_* = SKIP
+//  91532 MAC NVIDIA 0x0640 : tex_image_and_sub_image_2d_with_video = PASS FAIL
+
+// Don't run these tests for faster turnover
+998 WIN LINUX : dEQP-GLES3.performance.* = SKIP
+998 WIN LINUX : dEQP-GLES3.stress.* = SKIP
+1101 WIN LINUX : dEQP-GLES3.functional.flush_finish.* = SKIP
+
+// TODO(jmadill): Figure out why these fail on the bots, but not locally.
+1108 WIN : dEQP-GLES3.functional.shaders.struct.local.dynamic_loop_struct_array_fragment = FAIL
+1094 WIN : dEQP-GLES3.functional.shaders.invariance.highp.loop_2 = FAIL
+1094 WIN : dEQP-GLES3.functional.shaders.invariance.mediump.loop_2 = FAIL
+
+// We can't support distinct texture sizes in D3D11.
+1097 WIN : dEQP-GLES3.functional.fbo.completeness.size.distinct = FAIL
+
+// Fail because we support these formats through the ANGLE_depth_texture extension instead of OES_depth_texture
+605754 MAC WIN LINUX ANDROID : dEQP-GLES3.functional.fbo.completeness.renderable.texture.depth.depth_component_unsigned_short = FAIL
+605754 MAC WIN LINUX ANDROID : dEQP-GLES3.functional.fbo.completeness.renderable.texture.depth.depth_component_unsigned_int = FAIL
+
+// Tests that we fail because they're not in line with the WebGL spec
+1335 MAC WIN LINUX : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.basic_2* = FAIL
+1335 MAC WIN LINUX : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.defined_macro_defined_test* = FAIL
+1335 MAC WIN LINUX : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.defined_macro_undef* = FAIL
+1335 MAC WIN LINUX : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.define_defined* = FAIL
+1335 MAC WIN LINUX : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.define_defined_outside_if* = FAIL
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Temporary entries: they should be removed once the bugs are fixed.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// TODO(jmadill): Find why this fails when run in a certain sequence, but not singly.
+1098 WIN : dEQP-GLES3.functional.uniform_api.random.50 = FAIL
+
+// Missing the SampleCmp instruction in vertex shaders.
+1435 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturelod.sampler2dshadow_vertex = FAIL
+1435 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturelodoffset.sampler2dshadow_vertex = FAIL
+1435 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojlod.sampler2dshadow_vertex = FAIL
+1435 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojlodoffset.sampler2dshadow_vertex = FAIL
+
+// SampleCmp is missing gradient/offset parameters in HLSL.
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturelod.sampler2dshadow_fragment = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturelodoffset.sampler2dshadow_fragment = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojlod.sampler2dshadow_fragment = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojlodoffset.sampler2dshadow_fragment = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturegrad.sampler2dshadow_vertex = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturegrad.sampler2dshadow_fragment = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturegrad.sampler2darrayshadow_vertex = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturegrad.sampler2darrayshadow_fragment = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturegradoffset.sampler2dshadow_vertex = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturegradoffset.sampler2dshadow_fragment = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturegradoffset.sampler2darrayshadow_vertex = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.texturegradoffset.sampler2darrayshadow_fragment = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojgrad.sampler2dshadow_vertex = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojgrad.sampler2dshadow_fragment = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojgradoffset.sampler2dshadow_vertex = FAIL
+1436 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojgradoffset.sampler2dshadow_fragment = FAIL
+
+// TODO(jmadill, cwallez): triage the failures below into permanent and temporary failures
+
+// Windows and Linux failures
+
+1101 WIN LINUX : dEQP-GLES3.functional.negative_api.texture.compressedtexsubimage2d = FAIL
+1101 WIN LINUX : dEQP-GLES3.functional.negative_api.texture.compressedtexsubimage2d_invalid_size = FAIL
+1101 WIN LINUX : dEQP-GLES3.functional.negative_api.texture.compressedtexsubimage3d = FAIL
+1101 WIN LINUX : dEQP-GLES3.functional.negative_api.texture.compressedtexsubimage3d_invalid_buffer_target = FAIL
+1095 WIN LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.nearest_nearest_clamp = FAIL
+1095 WIN LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.nearest_nearest_repeat = FAIL
+1095 WIN LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.nearest_nearest_mirror = FAIL
+1095 WIN LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_nearest_clamp = FAIL
+1095 WIN LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_nearest_repeat = FAIL
+1095 WIN LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_nearest_mirror = FAIL
+
+// Windows only failure
+
+1093 WIN : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.scalar = FAIL
+1093 WIN : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.vec2 = FAIL
+1093 WIN : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.vec3 = FAIL
+1093 WIN : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.vec4 = FAIL
+1093 WIN : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_fragment.scalar = FAIL
+1093 WIN : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_fragment.vec2 = FAIL
+1093 WIN : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_fragment.vec3 = FAIL
+1093 WIN : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_fragment.vec4 = FAIL
+1092 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureoffset.sampler3d_fixed_fragment = FAIL
+1092 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureoffset.sampler3d_float_fragment = FAIL
+1092 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojoffset.sampler3d_fixed_fragment = FAIL
+1092 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojoffset.sampler3d_float_fragment = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.depth_stencil.stencil_depth_funcs.stencil_* = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.depth_stencil.stencil_ops.* = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.depth_stencil.write_mask.* = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.depth_stencil.random.* = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.add_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.add_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.add_one_minus_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.add_one_minus_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.add_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.add_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.add_one_minus_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.add_one_minus_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.subtract_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.subtract_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.subtract_one_minus_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.subtract_one_minus_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.subtract_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.subtract_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.subtract_one_minus_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.subtract_one_minus_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.reverse_subtract_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.reverse_subtract_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.reverse_subtract_one_minus_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.reverse_subtract_one_minus_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.reverse_subtract_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.reverse_subtract_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.reverse_subtract_one_minus_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.default_framebuffer.equation_src_func_dst_func.reverse_subtract_one_minus_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.add_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.add_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.add_one_minus_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.add_one_minus_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.add_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.add_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.add_one_minus_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.add_one_minus_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.subtract_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.subtract_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.subtract_one_minus_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.subtract_one_minus_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.subtract_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.subtract_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.subtract_one_minus_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.subtract_one_minus_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.reverse_subtract_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.reverse_subtract_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.reverse_subtract_one_minus_constant_color_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.reverse_subtract_one_minus_constant_color_one_minus_constant_alpha = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.reverse_subtract_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.reverse_subtract_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.reverse_subtract_one_minus_constant_alpha_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.equation_src_func_dst_func.reverse_subtract_one_minus_constant_alpha_one_minus_constant_color = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.random.* = FAIL
+1096 WIN : dEQP-GLES3.functional.fragment_ops.interaction.basic_shader.* = FAIL
+1098 WIN : dEQP-GLES3.functional.uniform_api.random.8 = FAIL
+1098 WIN : dEQP-GLES3.functional.uniform_api.random.81 = FAIL
+1101 WIN : dEQP-GLES3.functional.polygon_offset.fixed16_render_with_units = FAIL
+1101 WIN : dEQP-GLES3.functional.polygon_offset.fixed24_render_with_units = FAIL
+1101 WIN : dEQP-GLES3.functional.lifetime.attach.deleted_input.buffer_vertex_array = FAIL
+
+// Windows AMD specific failures
+1633 WIN AMD : dEQP-GLES3.functional.fbo.blit.depth_stencil.depth24_stencil8_scale = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.blit.depth_stencil.depth24_stencil8_stencil_only = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.r11f_g11f_b10f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.rg32f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.rg16f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.r32f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.r16f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.rgb16f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.rg8 = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.rgb10_a2 = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.rgba16f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.blit.tex2d.r8 = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.rgba32f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.rgba16f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.r11f_g11f_b10f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.rg32f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.rg16f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.r32f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.r16f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.rgb16f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.rg8 = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.r8 = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.rgb10_a2 = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.fbo.render.shared_colorbuffer_clear.tex2d_rgb16f = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.rasterization.fbo.rbo_multisample_max.interpolation.lines = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.rasterization.fbo.rbo_multisample_max.primitives.lines = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.filtering.cube.formats.rgb10_a2_nearest_mipmap_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.filtering.cube.formats.rgb565_nearest_mipmap_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.filtering.cube.formats.rgba16f_nearest_mipmap_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.mipmap.2d.min_lod.nearest_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.mipmap.2d.min_lod.linear_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.mipmap.2d.max_lod.nearest_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.mipmap.2d.max_lod.linear_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.mipmap.3d.min_lod.nearest_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.mipmap.3d.min_lod.linear_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.mipmap.3d.max_lod.nearest_nearest = FAIL
+1633 WIN AMD : dEQP-GLES3.functional.texture.mipmap.3d.max_lod.linear_nearest = FAIL
+
+// Windows Intel-specific failures
+
+1349 WIN INTEL : dEQP-GLES3.functional.shaders.texture_functions.texturelod.isamplercube_* = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.shaders.texture_functions.texturelod.usamplercube_* = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.shaders.texture_functions.texturegrad.isamplercube_vertex = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.shaders.texture_functions.texturegrad.usamplercube_vertex = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.shaders.texture_functions.texturegrad.usamplercube_fragment = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.2_units.only_cube.0 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.2_units.only_cube.2 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.2_units.only_cube.4 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.2_units.only_cube.7 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.2_units.only_cube.8 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.2_units.mixed.4 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.only_cube.0 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.only_cube.1 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.only_cube.2 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.only_cube.6 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.only_cube.7 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.only_cube.8 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.only_cube.9 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.mixed.4 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.mixed.6 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.4_units.mixed.7 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.8_units.only_cube.* = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.8_units.mixed.2 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.8_units.mixed.3 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.8_units.mixed.4 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.8_units.mixed.6 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.8_units.mixed.7 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.all_units.only_cube.* = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.all_units.mixed.2 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.all_units.mixed.3 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.all_units.mixed.4 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.all_units.mixed.6 = FAIL
+1349 WIN INTEL : dEQP-GLES3.functional.texture.units.all_units.mixed.7 = FAIL
+
+// Linux only failures
+
+// A Clang roll causes a crash in the dEQP rsgExpression file on Linux NVIDIA. Bug ID is a Chromium bug ID.
+// Failure expectations did not work, so skipping these tests.
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.trigonometric.fragment.77 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.texture.vertex.44 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.conditionals.vertex.2 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.conditionals.vertex.33 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.conditionals.fragment.32 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.comparison_ops.fragment.11 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.basic_expression.vertex.98 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.scalar_conversion.fragment.11 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.conditionals.vertex.94 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.scalar_conversion.combined.79 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.swizzle.vertex.38 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.conditionals.combined.7 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.scalar_conversion.combined.48 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.texture.vertex.3 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.scalar_conversion.combined.11 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.conditionals.combined.32 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.all_features.fragment.29 = SKIP
+722345 LINUX NVIDIA : dEQP-GLES3.functional.shaders.random.basic_expression.vertex.78 = SKIP
+
+// UBO tests trigger crashes when getting the program info log, skip them until this is fixed.
+1323 LINUX : dEQP-GLES3.functional.ubo.* = SKIP
+
+1323 LINUX : dEQP-GLES3.functional.fbo.blit.default_framebuffer.srgb8_alpha8 = FAIL
+1323 LINUX : dEQP-GLES3.functional.fbo.blit.default_framebuffer.srgb8_alpha8_linear_out_of_bounds_blit_to_default = FAIL
+1323 LINUX : dEQP-GLES3.functional.fbo.blit.default_framebuffer.srgb8_alpha8_linear_scale_blit_to_default = FAIL
+1323 LINUX : dEQP-GLES3.functional.fbo.blit.default_framebuffer.srgb8_alpha8_nearest_scale_blit_to_default = FAIL
+1323 LINUX : dEQP-GLES3.functional.fbo.depth.depth_test_clamp.depth_component32f = FAIL
+1323 LINUX : dEQP-GLES3.functional.fbo.depth.depth_test_clamp.depth32f_stencil8 = FAIL
+1323 LINUX : dEQP-GLES3.functional.fbo.depth.depth_write_clamp.depth_component32f = FAIL
+1323 LINUX : dEQP-GLES3.functional.fbo.depth.depth_write_clamp.depth32f_stencil8 = FAIL
+1323 LINUX : dEQP-GLES3.functional.rasterization.fbo.rbo_multisample_max.primitives.points = FAIL
+1323 LINUX : dEQP-GLES3.functional.state_query.integers64.max_server_wait_timeout_getfloat = FAIL
+1323 LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_linear_clamp = FAIL
+1323 LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_linear_mirror = FAIL
+1323 LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.linear_linear_repeat = FAIL
+1323 LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.nearest_linear_clamp = FAIL
+1323 LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.nearest_linear_mirror = FAIL
+1323 LINUX : dEQP-GLES3.functional.texture.mipmap.2d.projected.nearest_linear_repeat = FAIL
+1098 LINUX : dEQP-GLES3.functional.uniform_api.random.6 = FAIL
+
+// While loops with 'continue' seem flaky on Linux. (Possibly all GL renderers)
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.conditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.conditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.unconditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.unconditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.only_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.only_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.double_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.double_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.mixed_break_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_constant_iterations.mixed_break_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.conditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.conditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.unconditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.unconditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.only_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.only_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.double_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.double_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.mixed_break_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_uniform_iterations.mixed_break_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.conditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.conditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.unconditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.unconditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.only_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.only_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.double_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.double_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.mixed_break_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.mixed_break_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.conditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.conditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.unconditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.unconditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.only_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.only_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.double_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.double_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.mixed_break_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_constant_iterations.mixed_break_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.conditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.conditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.unconditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.unconditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.only_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.only_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.double_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.double_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.mixed_break_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_uniform_iterations.mixed_break_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.conditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.conditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.unconditional_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.unconditional_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.only_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.only_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.double_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.double_continue_fragment = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.mixed_break_continue_vertex = FAIL
+1324 LINUX : dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.mixed_break_continue_fragment = FAIL
+
+// Android only failures
+1487 ANDROID : dEQP-GLES3.functional.fbo.completeness.renderable.texture.color0.red_half_float_oes = FAIL
+1487 ANDROID : dEQP-GLES3.functional.fbo.completeness.renderable.texture.color0.rg_half_float_oes = FAIL
+1527 ANDROID : dEQP-GLES3.functional.flush_finish.* = SKIP
+1530 ANDROID : dEQP-GLES3.functional.negative_api.texture.compressedtexsubimage2d = FAIL
+1530 ANDROID : dEQP-GLES3.functional.negative_api.texture.compressedtexsubimage2d_invalid_size = FAIL
+1530 ANDROID : dEQP-GLES3.functional.negative_api.texture.compressedtexsubimage3d = FAIL
+1530 ANDROID : dEQP-GLES3.functional.negative_api.texture.compressedtexsubimage3d_invalid_buffer_target = FAIL
+1964 ANDROID : dEQP-GLES3.functional.occlusion_query.* = FAIL
+1962 ANDROID : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.basic_2_fragment = FAIL
+1962 ANDROID : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.basic_2_vertex = FAIL
+1962 ANDROID : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.defined_macro_undef_fragment = FAIL
+1962 ANDROID : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.defined_macro_undef_vertex = FAIL
+1963 ANDROID : dEQP-GLES3.functional.shaders.return.conditional_return_always_fragment = FAIL
+1963 ANDROID : dEQP-GLES3.functional.shaders.return.conditional_return_always_vertex = FAIL
+1963 ANDROID : dEQP-GLES3.functional.shaders.return.output_write_always_fragment = FAIL
+1963 ANDROID : dEQP-GLES3.functional.shaders.return.output_write_always_vertex = FAIL
+1963 ANDROID : dEQP-GLES3.functional.shaders.return.output_write_in_func_always_fragment = FAIL
+1963 ANDROID : dEQP-GLES3.functional.shaders.return.output_write_in_func_always_vertex = FAIL
+1529 ANDROID : dEQP-GLES3.functional.texture.mipmap.2d.generate.a8_* = FAIL
+1529 ANDROID : dEQP-GLES3.functional.texture.mipmap.2d.generate.l8_* = FAIL
+1529 ANDROID : dEQP-GLES3.functional.texture.mipmap.2d.generate.la88_* = FAIL
+1529 ANDROID : dEQP-GLES3.functional.texture.mipmap.cube.generate.a8_* = FAIL
+1529 ANDROID : dEQP-GLES3.functional.texture.mipmap.cube.generate.l8_* = FAIL
+1529 ANDROID : dEQP-GLES3.functional.texture.mipmap.cube.generate.la88_* = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.basic_types.interleaved.* = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.basic_types.separate.* = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.interpolation.* = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.point_size.* = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.position.* = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.interleaved.lines.5 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.interleaved.lines.8 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.interleaved.lines.10 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.interleaved.points.6 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.interleaved.points.7 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.interleaved.triangles.2 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.separate.lines.4 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.separate.lines.6 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.separate.lines.8 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.separate.points.4 = FAIL
+1531 ANDROID : dEQP-GLES3.functional.transform_feedback.random.separate.triangles.4 = FAIL
diff --git a/src/third_party/angle/src/tests/deqp_support/qpTestLog.c b/src/third_party/angle/src/tests/deqp_support/qpTestLog.c
new file mode 100644
index 0000000..7252ae0
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/qpTestLog.c
@@ -0,0 +1,1481 @@
+/*-------------------------------------------------------------------------
+ * drawElements TestLog Library
+ * ----------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Test case result logging
+ *//*--------------------------------------------------------------------*/
+
+#include "qpTestLog.h"
+#include "qpXmlWriter.h"
+#include "qpInfo.h"
+#include "qpDebugOut.h"
+
+#include "deMemory.h"
+#include "deInt32.h"
+#include "deString.h"
+
+#include "deMutex.h"
+
+#if defined(QP_SUPPORT_PNG)
+#	include <png.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#if (DE_OS == DE_OS_WIN32)
+#	include <windows.h>
+#	include <io.h>
+#endif
+
+#if defined(DE_DEBUG)
+
+/* Utils for verifying container (Section, ImageSet, EglConfigSet) usage in debug builds. */
+
+typedef enum ContainerType_e
+{
+	CONTAINERTYPE_SECTION = 0,
+	CONTAINERTYPE_IMAGESET,
+	CONTAINERTYPE_EGLCONFIGSET,
+	CONTAINERTYPE_SHADERPROGRAM,
+	CONTAINERTYPE_SAMPLELIST,
+	CONTAINERTYPE_SAMPLEINFO,
+	CONTAINERTYPE_SAMPLE,
+
+	CONTAINERTYPE_LAST
+} ContainerType;
+
+DE_INLINE deBool childContainersOk (ContainerType type)
+{
+	return type == CONTAINERTYPE_SECTION || type == CONTAINERTYPE_SAMPLELIST;
+}
+
+enum
+{
+	MAX_CONTAINER_STACK_DEPTH		= 32
+};
+
+typedef struct ContainerStack_s
+{
+	int				numElements;
+	ContainerType	elements[MAX_CONTAINER_STACK_DEPTH];
+} ContainerStack;
+
+DE_INLINE void ContainerStack_reset (ContainerStack* stack)
+{
+	deMemset(stack, 0, sizeof(ContainerStack));
+}
+
+DE_INLINE deBool ContainerStack_isEmpty (const ContainerStack* stack)
+{
+	return stack->numElements == 0;
+}
+
+DE_INLINE deBool ContainerStack_push (ContainerStack* stack, ContainerType type)
+{
+	if (stack->numElements == MAX_CONTAINER_STACK_DEPTH)
+		return DE_FALSE;
+
+	if (stack->numElements > 0 && !childContainersOk(stack->elements[stack->numElements-1]))
+		return DE_FALSE;
+
+	stack->elements[stack->numElements]  = type;
+	stack->numElements					+= 1;
+
+	return DE_TRUE;
+}
+
+DE_INLINE ContainerType ContainerStack_pop (ContainerStack* stack)
+{
+	DE_ASSERT(stack->numElements > 0);
+	stack->numElements -= 1;
+	return stack->elements[stack->numElements];
+}
+
+DE_INLINE ContainerType ContainerStack_getTop (const ContainerStack* stack)
+{
+	if (stack->numElements > 0)
+		return stack->elements[stack->numElements-1];
+	else
+		return CONTAINERTYPE_LAST;
+}
+
+#endif
+
+/* qpTestLog instance */
+struct qpTestLog_s
+{
+	deUint32				flags;				/*!< Logging flags.						*/
+
+	deMutex					lock;				/*!< Lock for mutable state below.		*/
+
+	/* State protected by lock. */
+	FILE*					outputFile;
+	qpXmlWriter*			writer;
+	deBool					isSessionOpen;
+	deBool					isCaseOpen;
+
+#if defined(DE_DEBUG)
+	ContainerStack			containerStack;		/*!< For container usage verification.	*/
+#endif
+};
+
+/* Maps integer to string. */
+typedef struct qpKeyStringMap_s
+{
+	int		key;
+	char*	string;
+} qpKeyStringMap;
+
+static const char* LOG_FORMAT_VERSION = "0.3.4";
+
+/* Mapping enum to above strings... */
+static const qpKeyStringMap s_qpTestTypeMap[] =
+{
+	{ QP_TEST_CASE_TYPE_SELF_VALIDATE,		"SelfValidate"	},
+	{ QP_TEST_CASE_TYPE_PERFORMANCE,		"Performance"	},
+	{ QP_TEST_CASE_TYPE_CAPABILITY,			"Capability"	},
+	{ QP_TEST_CASE_TYPE_ACCURACY,			"Accuracy"		},
+
+	{ QP_TEST_CASE_TYPE_LAST,				DE_NULL			}
+};
+
+DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpTestTypeMap) == QP_TEST_CASE_TYPE_LAST + 1);
+
+static const qpKeyStringMap s_qpTestResultMap[] =
+{
+	{ QP_TEST_RESULT_PASS,						"Pass"					},
+	{ QP_TEST_RESULT_FAIL,						"Fail"					},
+	{ QP_TEST_RESULT_QUALITY_WARNING,			"QualityWarning"		},
+	{ QP_TEST_RESULT_COMPATIBILITY_WARNING,		"CompatibilityWarning"	},
+	{ QP_TEST_RESULT_PENDING,					"Pending"				},	/* should not be needed here */
+	{ QP_TEST_RESULT_NOT_SUPPORTED,				"NotSupported"			},
+	{ QP_TEST_RESULT_RESOURCE_ERROR,			"ResourceError"			},
+	{ QP_TEST_RESULT_INTERNAL_ERROR,			"InternalError"			},
+	{ QP_TEST_RESULT_CRASH,						"Crash"					},
+	{ QP_TEST_RESULT_TIMEOUT,					"Timeout"				},
+
+	/* Add new values here if needed, remember to update qpTestResult enumeration. */
+
+	{ QP_TEST_RESULT_LAST,						DE_NULL					}
+};
+
+DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpTestResultMap) == QP_TEST_RESULT_LAST + 1);
+
+/* Key tag to string mapping. */
+
+static const qpKeyStringMap s_qpTagMap[] =
+{
+	{ QP_KEY_TAG_NONE,			DE_NULL			},
+	{ QP_KEY_TAG_PERFORMANCE,	"Performance"	},
+	{ QP_KEY_TAG_QUALITY,		"Quality"		},
+	{ QP_KEY_TAG_PRECISION,		"Precision"		},
+	{ QP_KEY_TAG_TIME,			"Time"			},
+
+	{ QP_KEY_TAG_LAST,			DE_NULL			}
+};
+
+DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpTagMap) == QP_KEY_TAG_LAST + 1);
+
+/* Sample value tag to string mapping. */
+
+static const qpKeyStringMap s_qpSampleValueTagMap[] =
+{
+	{ QP_SAMPLE_VALUE_TAG_PREDICTOR,	"Predictor"	},
+	{ QP_SAMPLE_VALUE_TAG_RESPONSE,		"Response"	},
+
+	{ QP_SAMPLE_VALUE_TAG_LAST,			DE_NULL		}
+};
+
+DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpSampleValueTagMap) == QP_SAMPLE_VALUE_TAG_LAST + 1);
+
+/* Image compression mode to string mapping. */
+
+static const qpKeyStringMap s_qpImageCompressionModeMap[] =
+{
+	{ QP_IMAGE_COMPRESSION_MODE_NONE,	"None"	},
+	{ QP_IMAGE_COMPRESSION_MODE_PNG,	"PNG"	},
+
+	{ QP_IMAGE_COMPRESSION_MODE_BEST,	DE_NULL	},	/* not allowed to be written! */
+
+	{ QP_IMAGE_COMPRESSION_MODE_LAST,	DE_NULL	}
+};
+
+DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpImageCompressionModeMap) == QP_IMAGE_COMPRESSION_MODE_LAST + 1);
+
+/* Image format to string mapping. */
+
+static const qpKeyStringMap s_qpImageFormatMap[] =
+{
+	{ QP_IMAGE_FORMAT_RGB888,	"RGB888"	},
+	{ QP_IMAGE_FORMAT_RGBA8888,	"RGBA8888"	},
+
+	{ QP_IMAGE_FORMAT_LAST,		DE_NULL		}
+};
+
+DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpImageFormatMap) == QP_IMAGE_FORMAT_LAST + 1);
+
+/* Shader type to string mapping. */
+
+static const qpKeyStringMap s_qpShaderTypeMap[] =
+{
+	{ QP_SHADER_TYPE_VERTEX,			"VertexShader"			},
+	{ QP_SHADER_TYPE_FRAGMENT,			"FragmentShader"		},
+	{ QP_SHADER_TYPE_GEOMETRY,			"GeometryShader"		},
+	{ QP_SHADER_TYPE_TESS_CONTROL,		"TessControlShader"		},
+	{ QP_SHADER_TYPE_TESS_EVALUATION,	"TessEvaluationShader"	},
+	{ QP_SHADER_TYPE_COMPUTE,			"ComputeShader"			},
+
+	{ QP_SHADER_TYPE_LAST,				DE_NULL					}
+};
+
+DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpShaderTypeMap) == QP_SHADER_TYPE_LAST + 1);
+
+static void qpTestLog_flushFile (qpTestLog* log)
+{
+	DE_ASSERT(log && log->outputFile);
+	fflush(log->outputFile);
+#if (DE_OS == DE_OS_WIN32) && (DE_COMPILER == DE_COMPILER_MSC)
+	/* \todo [petri] Is this really necessary? */
+	FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(log->outputFile)));
+#endif
+}
+
+#define QP_LOOKUP_STRING(KEYMAP, KEY)	qpLookupString(KEYMAP, DE_LENGTH_OF_ARRAY(KEYMAP), (int)(KEY))
+
+static const char* qpLookupString (const qpKeyStringMap* keyMap, int keyMapSize, int key)
+{
+	DE_ASSERT(keyMap);
+	DE_ASSERT(deInBounds32(key, 0, keyMapSize));
+	DE_ASSERT(keyMap[key].key == key);
+	DE_UNREF(keyMapSize); /* for asserting only */
+	return keyMap[key].string;
+}
+
+DE_INLINE void int32ToString (int val, char buf[32])
+{
+	deSprintf(&buf[0], 32, "%d", val);
+}
+
+DE_INLINE void int64ToString (deInt64 val, char buf[32])
+{
+	deSprintf(&buf[0], 32, "%lld", (long long int)val);
+}
+
+DE_INLINE void floatToString (float value, char* buf, size_t bufSize)
+{
+	deSprintf(buf, bufSize, "%f", value);
+}
+
+DE_INLINE void doubleToString (double value, char* buf, size_t bufSize)
+{
+	deSprintf(buf, bufSize, "%f", value);
+}
+
+static deBool beginSession (qpTestLog* log)
+{
+	DE_ASSERT(log && !log->isSessionOpen);
+
+	/* Write session info. */
+	fprintf(log->outputFile, "#sessionInfo releaseName %s\n", qpGetReleaseName());
+	fprintf(log->outputFile, "#sessionInfo releaseId 0x%08x\n", qpGetReleaseId());
+	fprintf(log->outputFile, "#sessionInfo targetName \"%s\"\n", qpGetTargetName());
+
+    /* Write out #beginSession. */
+	fprintf(log->outputFile, "#beginSession\n");
+	qpTestLog_flushFile(log);
+
+	log->isSessionOpen = DE_TRUE;
+
+	return DE_TRUE;
+}
+
+static deBool endSession (qpTestLog* log)
+{
+	DE_ASSERT(log && log->isSessionOpen);
+
+    /* Make sure xml is flushed. */
+    qpXmlWriter_flush(log->writer);
+
+    /* Write out #endSession. */
+	fprintf(log->outputFile, "\n#endSession\n");
+	qpTestLog_flushFile(log);
+
+	log->isSessionOpen = DE_FALSE;
+
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Create a file based logger instance
+ * \param fileName Name of the file where to put logs
+ * \return qpTestLog instance, or DE_NULL if cannot create file
+ *//*--------------------------------------------------------------------*/
+qpTestLog* qpTestLog_createFileLog (const char* fileName, deUint32 flags)
+{
+	qpTestLog* log = (qpTestLog*)deCalloc(sizeof(qpTestLog));
+	if (!log)
+		return DE_NULL;
+
+	DE_ASSERT(fileName && fileName[0]); /* must have filename. */
+
+#if defined(DE_DEBUG)
+	ContainerStack_reset(&log->containerStack);
+#endif
+
+	qpPrintf("Writing test log into %s\n", fileName);
+
+	/* Create output file. */
+	log->outputFile = fopen(fileName, "wb");
+	if (!log->outputFile)
+	{
+		qpPrintf("ERROR: Unable to open test log output file '%s'.\n", fileName);
+		qpTestLog_destroy(log);
+		return DE_NULL;
+	}
+
+	log->flags			= flags;
+	log->writer			= qpXmlWriter_createFileWriter(log->outputFile, 0, !(flags & QP_TEST_LOG_NO_FLUSH));
+	log->lock			= deMutex_create(DE_NULL);
+	log->isSessionOpen	= DE_FALSE;
+	log->isCaseOpen		= DE_FALSE;
+
+	if (!log->writer)
+	{
+		qpPrintf("ERROR: Unable to create output XML writer to file '%s'.\n", fileName);
+		qpTestLog_destroy(log);
+		return DE_NULL;
+	}
+
+	if (!log->lock)
+	{
+		qpPrintf("ERROR: Unable to create mutex.\n");
+		qpTestLog_destroy(log);
+		return DE_NULL;
+	}
+
+	beginSession(log);
+
+	return log;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Destroy a logger instance
+ * \param a	qpTestLog instance
+ *//*--------------------------------------------------------------------*/
+void qpTestLog_destroy (qpTestLog* log)
+{
+	DE_ASSERT(log);
+
+	if (log->isSessionOpen)
+		endSession(log);
+
+	if (log->writer)
+		qpXmlWriter_destroy(log->writer);
+
+	if (log->outputFile)
+		fclose(log->outputFile);
+
+	if (log->lock)
+		deMutex_destroy(log->lock);
+
+	deFree(log);
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Log start of test case
+ * \param log qpTestLog instance
+ * \param testCasePath	Full test case path (as seen in Candy).
+ * \param testCaseType	Test case type
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_startCase (qpTestLog* log, const char* testCasePath, qpTestCaseType testCaseType)
+{
+	const char*		typeStr				= QP_LOOKUP_STRING(s_qpTestTypeMap, testCaseType);
+	int				numResultAttribs	= 0;
+	qpXmlAttribute	resultAttribs[8];
+
+	DE_ASSERT(log && testCasePath && (testCasePath[0] != 0));
+	deMutex_lock(log->lock);
+
+	DE_ASSERT(!log->isCaseOpen);
+	DE_ASSERT(ContainerStack_isEmpty(&log->containerStack));
+
+	/* Flush XML and write out #beginTestCaseResult. */
+	qpXmlWriter_flush(log->writer);
+	fprintf(log->outputFile, "\n#beginTestCaseResult %s\n", testCasePath);
+	if (!(log->flags & QP_TEST_LOG_NO_FLUSH))
+		qpTestLog_flushFile(log);
+
+	log->isCaseOpen = DE_TRUE;
+
+	/* Fill in attributes. */
+	resultAttribs[numResultAttribs++] = qpSetStringAttrib("Version", LOG_FORMAT_VERSION);
+	resultAttribs[numResultAttribs++] = qpSetStringAttrib("CasePath", testCasePath);
+	resultAttribs[numResultAttribs++] = qpSetStringAttrib("CaseType", typeStr);
+
+	if (!qpXmlWriter_startDocument(log->writer) ||
+		!qpXmlWriter_startElement(log->writer, "TestCaseResult", numResultAttribs, resultAttribs))
+	{
+		qpPrintf("qpTestLog_startCase(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Log end of test case
+ * \param log qpTestLog instance
+ * \param result Test result
+ * \param description Description of a problem in case of error
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_endCase (qpTestLog* log, qpTestResult result, const char* resultDetails)
+{
+	const char*		statusStr		= QP_LOOKUP_STRING(s_qpTestResultMap, result);
+	qpXmlAttribute	statusAttrib	= qpSetStringAttrib("StatusCode", statusStr);
+
+	deMutex_lock(log->lock);
+
+	DE_ASSERT(log->isCaseOpen);
+	DE_ASSERT(ContainerStack_isEmpty(&log->containerStack));
+
+	/* <Result StatusCode="Pass">Result details</Result>
+	 * </TestCaseResult>
+	 */
+	if (!qpXmlWriter_startElement(log->writer, "Result", 1, &statusAttrib) ||
+		(resultDetails && !qpXmlWriter_writeString(log->writer, resultDetails)) ||
+		!qpXmlWriter_endElement(log->writer, "Result") ||
+		!qpXmlWriter_endElement(log->writer, "TestCaseResult") ||
+		!qpXmlWriter_endDocument(log->writer))		/* Close any XML elements still open */
+	{
+		qpPrintf("qpTestLog_endCase(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	/* Flush XML and write #endTestCaseResult. */
+	qpXmlWriter_flush(log->writer);
+	fprintf(log->outputFile, "\n#endTestCaseResult\n");
+	if (!(log->flags & QP_TEST_LOG_NO_FLUSH))
+		qpTestLog_flushFile(log);
+
+	log->isCaseOpen = DE_FALSE;
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Abrupt termination of logging.
+ * \param log		qpTestLog instance
+ * \param result	Result code, only Crash and Timeout are allowed.
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_terminateCase (qpTestLog* log, qpTestResult result)
+{
+	const char* resultStr = QP_LOOKUP_STRING(s_qpTestResultMap, result);
+
+	DE_ASSERT(log);
+	DE_ASSERT(result == QP_TEST_RESULT_CRASH || result == QP_TEST_RESULT_TIMEOUT);
+
+	deMutex_lock(log->lock);
+
+	if (!log->isCaseOpen)
+	{
+		deMutex_unlock(log->lock);
+		return DE_FALSE; /* Soft error. This is called from error handler. */
+	}
+
+	/* Flush XML and write #terminateTestCaseResult. */
+	qpXmlWriter_flush(log->writer);
+	fprintf(log->outputFile, "\n#terminateTestCaseResult %s\n", resultStr);
+	qpTestLog_flushFile(log);
+
+	log->isCaseOpen = DE_FALSE;
+
+#if defined(DE_DEBUG)
+	ContainerStack_reset(&log->containerStack);
+#endif
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+static deBool qpTestLog_writeKeyValuePair (qpTestLog* log, const char* elementName, const char* name, const char* description, const char* unit, qpKeyValueTag tag, const char* text)
+{
+	const char*		tagString = QP_LOOKUP_STRING(s_qpTagMap, tag);
+	qpXmlAttribute	attribs[8];
+	int				numAttribs = 0;
+
+	DE_ASSERT(log && elementName && text);
+	deMutex_lock(log->lock);
+
+	/* Fill in attributes. */
+	if (name)			attribs[numAttribs++] = qpSetStringAttrib("Name", name);
+	if (description)	attribs[numAttribs++] = qpSetStringAttrib("Description", description);
+	if (tagString)		attribs[numAttribs++] = qpSetStringAttrib("Tag", tagString);
+	if (unit)			attribs[numAttribs++] = qpSetStringAttrib("Unit", unit);
+
+	if (!qpXmlWriter_startElement(log->writer, elementName, numAttribs, attribs) ||
+		!qpXmlWriter_writeString(log->writer, text) ||
+		!qpXmlWriter_endElement(log->writer, elementName))
+	{
+		qpPrintf("qpTestLog_writeKeyValuePair(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write a message to output log
+ * \param log		qpTestLog instance
+ * \param format	Format string of message
+ * \param ...		Parameters for message
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeMessage (qpTestLog* log, const char* format, ...)
+{
+	char	buffer[1024];
+	va_list	args;
+
+	/* \todo [petri] Handle buffer overflows! */
+
+	va_start(args, format);
+	buffer[DE_LENGTH_OF_ARRAY(buffer) - 1] = 0;
+	vsnprintf(buffer, sizeof(buffer), format, args);
+	va_end(args);
+
+	/* <Text>text</Text> */
+	return qpTestLog_writeKeyValuePair(log, "Text", DE_NULL, DE_NULL, DE_NULL, QP_KEY_TAG_LAST, buffer);
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write key-value-pair into log
+ * \param log			qpTestLog instance
+ * \param name			Unique identifier for entry
+ * \param description	Human readable description
+ * \param tag			Optional tag
+ * \param value			Value of the key-value-pair
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeText (qpTestLog* log, const char* name, const char* description, qpKeyValueTag tag, const char* text)
+{
+	/* <Text Name="name" Description="description" Tag="tag">text</Text> */
+	return qpTestLog_writeKeyValuePair(log, "Text", name, description, DE_NULL, tag, text);
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write key-value-pair into log
+ * \param log			qpTestLog instance
+ * \param name			Unique identifier for entry
+ * \param description	Human readable description
+ * \param tag			Optional tag
+ * \param value			Value of the key-value-pair
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeInteger (qpTestLog* log, const char* name, const char* description, const char* unit, qpKeyValueTag tag, deInt64 value)
+{
+	char tmpString[64];
+	int64ToString(value, tmpString);
+
+	/* <Number Name="name" Description="description" Tag="Performance">15</Number> */
+	return qpTestLog_writeKeyValuePair(log, "Number", name, description, unit, tag, tmpString);
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write key-value-pair into log
+ * \param log			qpTestLog instance
+ * \param name			Unique identifier for entry
+ * \param description	Human readable description
+ * \param tag			Optional tag
+ * \param value			Value of the key-value-pair
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeFloat (qpTestLog* log, const char* name, const char* description, const char* unit, qpKeyValueTag tag, float value)
+{
+	char tmpString[64];
+	floatToString(value, tmpString, sizeof(tmpString));
+
+	/* <Number Name="name" Description="description" Tag="Performance">15</Number> */
+	return qpTestLog_writeKeyValuePair(log, "Number", name, description, unit, tag, tmpString);
+}
+
+typedef struct Buffer_s
+{
+	size_t		capacity;
+	size_t		size;
+	deUint8*	data;
+} Buffer;
+
+void Buffer_init (Buffer* buffer)
+{
+	buffer->capacity	= 0;
+	buffer->size		= 0;
+	buffer->data		= DE_NULL;
+}
+
+void Buffer_deinit (Buffer* buffer)
+{
+	deFree(buffer->data);
+	Buffer_init(buffer);
+}
+
+deBool Buffer_resize (Buffer* buffer, size_t newSize)
+{
+	/* Grow buffer if necessary. */
+	if (newSize > buffer->capacity)
+	{
+		size_t		newCapacity	= (size_t)deAlign32(deMax32(2*(int)buffer->capacity, (int)newSize), 512);
+		deUint8*	newData		= (deUint8*)deMalloc(newCapacity);
+		if (!newData)
+			return DE_FALSE;
+
+		memcpy(newData, buffer->data, buffer->size);
+		deFree(buffer->data);
+		buffer->data		= newData;
+		buffer->capacity	= newCapacity;
+	}
+
+	buffer->size = newSize;
+	return DE_TRUE;
+}
+
+deBool Buffer_append (Buffer* buffer, const deUint8* data, size_t numBytes)
+{
+	size_t offset = buffer->size;
+
+	if (!Buffer_resize(buffer, buffer->size + numBytes))
+		return DE_FALSE;
+
+	/* Append bytes. */
+	memcpy(&buffer->data[offset], data, numBytes);
+	return DE_TRUE;
+}
+
+#if defined(QP_SUPPORT_PNG)
+void pngWriteData (png_structp png, png_bytep dataPtr, png_size_t numBytes)
+{
+	Buffer* buffer = (Buffer*)png_get_io_ptr(png);
+	if (!Buffer_append(buffer, (const deUint8*)dataPtr, numBytes))
+		png_error(png, "unable to resize PNG write buffer!");
+}
+
+void pngFlushData (png_structp png)
+{
+	DE_UNREF(png);
+	/* nada */
+}
+
+static deBool writeCompressedPNG (png_structp png, png_infop info, png_byte** rowPointers, int width, int height, int colorFormat)
+{
+	if (setjmp(png_jmpbuf(png)) == 0)
+	{
+		/* Write data. */
+		png_set_IHDR(png, info, (png_uint_32)width, (png_uint_32)height,
+			8,
+			colorFormat,
+			PNG_INTERLACE_NONE,
+			PNG_COMPRESSION_TYPE_BASE,
+			PNG_FILTER_TYPE_BASE);
+		png_write_info(png, info);
+		png_write_image(png, rowPointers);
+		png_write_end(png, NULL);
+
+		return DE_TRUE;
+	}
+	else
+		return DE_FALSE;
+}
+
+static deBool compressImagePNG (Buffer* buffer, qpImageFormat imageFormat, int width, int height, int rowStride, const void* data)
+{
+	deBool			compressOk		= DE_FALSE;
+	png_structp		png				= DE_NULL;
+	png_infop		info			= DE_NULL;
+	png_byte**		rowPointers		= DE_NULL;
+	deBool			hasAlpha		= imageFormat == QP_IMAGE_FORMAT_RGBA8888;
+	int				ndx;
+
+	/* Handle format. */
+	DE_ASSERT(imageFormat == QP_IMAGE_FORMAT_RGB888 || imageFormat == QP_IMAGE_FORMAT_RGBA8888);
+
+	/* Allocate & set row pointers. */
+	rowPointers = (png_byte**)deMalloc((size_t)height * sizeof(png_byte*));
+	if (!rowPointers)
+		return DE_FALSE;
+
+	for (ndx = 0; ndx < height; ndx++)
+		rowPointers[ndx] = (png_byte*)((const deUint8*)data + ndx*rowStride);
+
+	/* Initialize PNG compressor. */
+	png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+	info = png ? png_create_info_struct(png) : DE_NULL;
+	if (png && info)
+	{
+		/* Set our own write function. */
+		png_set_write_fn(png, buffer, pngWriteData, pngFlushData);
+
+		compressOk = writeCompressedPNG(png, info, rowPointers, width, height,
+										hasAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB);
+	}
+
+	/* Cleanup & return. */
+	if (png && info)
+	{
+		png_destroy_info_struct(png, &info);
+		png_destroy_write_struct(&png, DE_NULL);
+	}
+	else if (png)
+		png_destroy_write_struct(&png, &info);
+
+	deFree(rowPointers);
+	return compressOk;
+}
+#endif /* QP_SUPPORT_PNG */
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Start image set
+ * \param log			qpTestLog instance
+ * \param name			Unique identifier for the set
+ * \param description	Human readable description
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_startImageSet (qpTestLog* log, const char* name, const char* description)
+{
+	qpXmlAttribute	attribs[4];
+	int				numAttribs = 0;
+
+	DE_ASSERT(log && name);
+	deMutex_lock(log->lock);
+
+	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
+	if (description)
+		attribs[numAttribs++] = qpSetStringAttrib("Description", description);
+
+	/* <ImageSet Name="<name>"> */
+	if (!qpXmlWriter_startElement(log->writer, "ImageSet", numAttribs, attribs))
+	{
+		qpPrintf("qpTestLog_startImageSet(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_IMAGESET));
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief End image set
+ * \param log			qpTestLog instance
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_endImageSet (qpTestLog* log)
+{
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	/* <ImageSet Name="<name>"> */
+	if (!qpXmlWriter_endElement(log->writer, "ImageSet"))
+	{
+		qpPrintf("qpTestLog_endImageSet(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_IMAGESET);
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write base64 encoded raw image data into log
+ * \param log				qpTestLog instance
+ * \param name				Unique name (matching names can be compared across BatchResults).
+ * \param description		Textual description (shown in Candy).
+ * \param compressionMode	Compression mode
+ * \param imageFormat		Color format
+ * \param width				Width in pixels
+ * \param height			Height in pixels
+ * \param stride			Data stride (offset between rows)
+ * \param data				Pointer to pixel data
+ * \return 0 if OK, otherwise <0
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeImage	(
+	qpTestLog*				log,
+	const char*				name,
+	const char*				description,
+	qpImageCompressionMode	compressionMode,
+	qpImageFormat			imageFormat,
+	int						width,
+	int						height,
+	int						stride,
+	const void*				data)
+{
+	char			widthStr[32];
+	char			heightStr[32];
+	qpXmlAttribute	attribs[8];
+	int				numAttribs			= 0;
+	Buffer			compressedBuffer;
+	const void*		writeDataPtr		= DE_NULL;
+	size_t			writeDataBytes		= ~(size_t)0;
+
+	DE_ASSERT(log && name);
+	DE_ASSERT(deInRange32(width, 1, 16384));
+	DE_ASSERT(deInRange32(height, 1, 16384));
+	DE_ASSERT(data);
+
+	if (log->flags & QP_TEST_LOG_EXCLUDE_IMAGES)
+		return DE_TRUE; /* Image not logged. */
+
+	Buffer_init(&compressedBuffer);
+
+	/* BEST compression mode defaults to PNG. */
+	if (compressionMode == QP_IMAGE_COMPRESSION_MODE_BEST)
+	{
+#if defined(QP_SUPPORT_PNG)
+		compressionMode = QP_IMAGE_COMPRESSION_MODE_PNG;
+#else
+		compressionMode = QP_IMAGE_COMPRESSION_MODE_NONE;
+#endif
+	}
+
+#if defined(QP_SUPPORT_PNG)
+	/* Try storing with PNG compression. */
+	if (compressionMode == QP_IMAGE_COMPRESSION_MODE_PNG)
+	{
+		deBool compressOk = compressImagePNG(&compressedBuffer, imageFormat, width, height, stride, data);
+		if (compressOk)
+		{
+			writeDataPtr	= compressedBuffer.data;
+			writeDataBytes	= compressedBuffer.size;
+		}
+		else
+		{
+			/* Fall-back to default compression. */
+			qpPrintf("WARNING: PNG compression failed -- storing image uncompressed.\n");
+			compressionMode	= QP_IMAGE_COMPRESSION_MODE_NONE;
+		}
+	}
+#endif
+
+	/* Handle image compression. */
+	switch (compressionMode)
+	{
+		case QP_IMAGE_COMPRESSION_MODE_NONE:
+		{
+			int pixelSize		= imageFormat == QP_IMAGE_FORMAT_RGB888 ? 3 : 4;
+			int packedStride	= pixelSize*width;
+
+			if (packedStride == stride)
+				writeDataPtr = data;
+			else
+			{
+				/* Need to re-pack pixels. */
+				if (Buffer_resize(&compressedBuffer, (size_t)(packedStride*height)))
+				{
+					int row;
+					for (row = 0; row < height; row++)
+						memcpy(&compressedBuffer.data[packedStride*row], &((const deUint8*)data)[row*stride], (size_t)(pixelSize*width));
+				}
+				else
+				{
+					qpPrintf("ERROR: Failed to pack pixels for writing.\n");
+					Buffer_deinit(&compressedBuffer);
+					return DE_FALSE;
+				}
+			}
+
+			writeDataBytes = (size_t)(packedStride*height);
+			break;
+		}
+
+#if defined(QP_SUPPORT_PNG)
+		case QP_IMAGE_COMPRESSION_MODE_PNG:
+			DE_ASSERT(writeDataPtr); /* Already handled. */
+			break;
+#endif
+
+		default:
+			qpPrintf("qpTestLog_writeImage(): Unknown compression mode: %s\n", QP_LOOKUP_STRING(s_qpImageCompressionModeMap, compressionMode));
+			Buffer_deinit(&compressedBuffer);
+			return DE_FALSE;
+	}
+
+	/* Fill in attributes. */
+	int32ToString(width, widthStr);
+	int32ToString(height, heightStr);
+	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
+	attribs[numAttribs++] = qpSetStringAttrib("Width", widthStr);
+	attribs[numAttribs++] = qpSetStringAttrib("Height", heightStr);
+	attribs[numAttribs++] = qpSetStringAttrib("Format", QP_LOOKUP_STRING(s_qpImageFormatMap, imageFormat));
+	attribs[numAttribs++] = qpSetStringAttrib("CompressionMode", QP_LOOKUP_STRING(s_qpImageCompressionModeMap, compressionMode));
+	if (description) attribs[numAttribs++] = qpSetStringAttrib("Description", description);
+
+	/* \note Log lock is acquired after compression! */
+	deMutex_lock(log->lock);
+
+	/* <Image ID="result" Name="Foobar" Width="640" Height="480" Format="RGB888" CompressionMode="None">base64 data</Image> */
+	if (!qpXmlWriter_startElement(log->writer, "Image", numAttribs, attribs) ||
+		!qpXmlWriter_writeBase64(log->writer, (const deUint8*)writeDataPtr, writeDataBytes) ||
+		!qpXmlWriter_endElement(log->writer, "Image"))
+	{
+		qpPrintf("qpTestLog_writeImage(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		Buffer_deinit(&compressedBuffer);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+
+	/* Free compressed data if allocated. */
+	Buffer_deinit(&compressedBuffer);
+
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write a OpenGL ES shader program into the log.
+ * \param linkOk			Shader program link result, false on failure
+ * \param linkInfoLog		Implementation provided linkage log
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_startShaderProgram (qpTestLog* log, deBool linkOk, const char* linkInfoLog)
+{
+	qpXmlAttribute	programAttribs[4];
+	int				numProgramAttribs = 0;
+
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	programAttribs[numProgramAttribs++] = qpSetStringAttrib("LinkStatus", linkOk ? "OK" : "Fail");
+
+	if (!qpXmlWriter_startElement(log->writer, "ShaderProgram", numProgramAttribs, programAttribs) ||
+		!qpXmlWriter_writeStringElement(log->writer, "InfoLog", linkInfoLog))
+	{
+		qpPrintf("qpTestLog_startShaderProgram(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SHADERPROGRAM));
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief End shader program
+ * \param log			qpTestLog instance
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_endShaderProgram (qpTestLog* log)
+{
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	/* </ShaderProgram> */
+	if (!qpXmlWriter_endElement(log->writer, "ShaderProgram"))
+	{
+		qpPrintf("qpTestLog_endShaderProgram(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM);
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write a OpenGL ES shader into the log.
+ * \param type				Shader type
+ * \param source			Shader source
+ * \param compileOk			Shader compilation result, false on failure
+ * \param infoLog			Implementation provided shader compilation log
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeShader (qpTestLog* log, qpShaderType type, const char* source, deBool compileOk, const char* infoLog)
+{
+	const char*		tagName				= QP_LOOKUP_STRING(s_qpShaderTypeMap, type);
+	const char*		sourceStr			= ((log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) == 0 || !compileOk) ? source : "";
+	int				numShaderAttribs	= 0;
+	qpXmlAttribute	shaderAttribs[4];
+
+	deMutex_lock(log->lock);
+
+	DE_ASSERT(source);
+	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM);
+
+	shaderAttribs[numShaderAttribs++]	= qpSetStringAttrib("CompileStatus", compileOk ? "OK" : "Fail");
+
+	if (!qpXmlWriter_startElement(log->writer, tagName, numShaderAttribs, shaderAttribs) ||
+		!qpXmlWriter_writeStringElement(log->writer, "ShaderSource", sourceStr) ||
+		!qpXmlWriter_writeStringElement(log->writer, "InfoLog", infoLog) ||
+		!qpXmlWriter_endElement(log->writer, tagName))
+	{
+		qpPrintf("qpTestLog_writeShader(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Start writing a set of EGL configurations into the log.
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_startEglConfigSet (qpTestLog* log, const char* name, const char* description)
+{
+	qpXmlAttribute	attribs[4];
+	int				numAttribs = 0;
+
+	DE_ASSERT(log && name);
+	deMutex_lock(log->lock);
+
+	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
+	if (description)
+		attribs[numAttribs++] = qpSetStringAttrib("Description", description);
+
+	/* <EglConfigSet Name="<name>"> */
+	if (!qpXmlWriter_startElement(log->writer, "EglConfigSet", numAttribs, attribs))
+	{
+		qpPrintf("qpTestLog_startEglImageSet(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_EGLCONFIGSET));
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief End an EGL config set
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_endEglConfigSet (qpTestLog* log)
+{
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	/* <EglConfigSet Name="<name>"> */
+	if (!qpXmlWriter_endElement(log->writer, "EglConfigSet"))
+	{
+		qpPrintf("qpTestLog_endEglImageSet(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_EGLCONFIGSET);
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write an EGL config inside an EGL config set
+ * \see   qpElgConfigInfo for details
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeEglConfig (qpTestLog* log, const qpEglConfigInfo* config)
+{
+	qpXmlAttribute	attribs[64];
+	int				numAttribs = 0;
+
+	DE_ASSERT(log && config);
+	deMutex_lock(log->lock);
+
+	attribs[numAttribs++] = qpSetIntAttrib		("BufferSize", config->bufferSize);
+	attribs[numAttribs++] = qpSetIntAttrib		("RedSize", config->redSize);
+	attribs[numAttribs++] = qpSetIntAttrib		("GreenSize", config->greenSize);
+	attribs[numAttribs++] = qpSetIntAttrib		("BlueSize", config->blueSize);
+	attribs[numAttribs++] = qpSetIntAttrib		("LuminanceSize", config->luminanceSize);
+	attribs[numAttribs++] = qpSetIntAttrib		("AlphaSize", config->alphaSize);
+	attribs[numAttribs++] = qpSetIntAttrib		("AlphaMaskSize", config->alphaMaskSize);
+	attribs[numAttribs++] = qpSetBoolAttrib		("BindToTextureRGB", config->bindToTextureRGB);
+	attribs[numAttribs++] = qpSetBoolAttrib		("BindToTextureRGBA", config->bindToTextureRGBA);
+	attribs[numAttribs++] = qpSetStringAttrib	("ColorBufferType", config->colorBufferType);
+	attribs[numAttribs++] = qpSetStringAttrib	("ConfigCaveat", config->configCaveat);
+	attribs[numAttribs++] = qpSetIntAttrib		("ConfigID", config->configID);
+	attribs[numAttribs++] = qpSetStringAttrib	("Conformant", config->conformant);
+	attribs[numAttribs++] = qpSetIntAttrib		("DepthSize", config->depthSize);
+	attribs[numAttribs++] = qpSetIntAttrib		("Level", config->level);
+	attribs[numAttribs++] = qpSetIntAttrib		("MaxPBufferWidth", config->maxPBufferWidth);
+	attribs[numAttribs++] = qpSetIntAttrib		("MaxPBufferHeight", config->maxPBufferHeight);
+	attribs[numAttribs++] = qpSetIntAttrib		("MaxPBufferPixels", config->maxPBufferPixels);
+	attribs[numAttribs++] = qpSetIntAttrib		("MaxSwapInterval", config->maxSwapInterval);
+	attribs[numAttribs++] = qpSetIntAttrib		("MinSwapInterval", config->minSwapInterval);
+	attribs[numAttribs++] = qpSetBoolAttrib		("NativeRenderable", config->nativeRenderable);
+	attribs[numAttribs++] = qpSetStringAttrib	("RenderableType", config->renderableType);
+	attribs[numAttribs++] = qpSetIntAttrib		("SampleBuffers", config->sampleBuffers);
+	attribs[numAttribs++] = qpSetIntAttrib		("Samples", config->samples);
+	attribs[numAttribs++] = qpSetIntAttrib		("StencilSize", config->stencilSize);
+	attribs[numAttribs++] = qpSetStringAttrib	("SurfaceTypes", config->surfaceTypes);
+	attribs[numAttribs++] = qpSetStringAttrib	("TransparentType", config->transparentType);
+	attribs[numAttribs++] = qpSetIntAttrib		("TransparentRedValue", config->transparentRedValue);
+	attribs[numAttribs++] = qpSetIntAttrib		("TransparentGreenValue", config->transparentGreenValue);
+	attribs[numAttribs++] = qpSetIntAttrib		("TransparentBlueValue", config->transparentBlueValue);
+	DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs));
+
+	if (!qpXmlWriter_startElement(log->writer, "EglConfig", numAttribs, attribs) ||
+		!qpXmlWriter_endElement(log->writer, "EglConfig"))
+	{
+		qpPrintf("qpTestLog_writeEglConfig(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Start section in log.
+ * \param log			qpTestLog instance
+ * \param name			Section name
+ * \param description	Human readable description
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_startSection (qpTestLog* log, const char* name, const char* description)
+{
+	qpXmlAttribute	attribs[2];
+	int				numAttribs = 0;
+
+	DE_ASSERT(log && name);
+	deMutex_lock(log->lock);
+
+	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
+	if (description)
+		attribs[numAttribs++] = qpSetStringAttrib("Description", description);
+
+	/* <Section Name="<name>" Description="<description>"> */
+	if (!qpXmlWriter_startElement(log->writer, "Section", numAttribs, attribs))
+	{
+		qpPrintf("qpTestLog_startSection(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SECTION));
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief End section in log.
+ * \param log			qpTestLog instance
+ * \return true if ok, false otherwise
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_endSection (qpTestLog* log)
+{
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	/* </Section> */
+	if (!qpXmlWriter_endElement(log->writer, "Section"))
+	{
+		qpPrintf("qpTestLog_endSection(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SECTION);
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write OpenCL compute kernel source into the log.
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeKernelSource (qpTestLog* log, const char* source)
+{
+	const char*		sourceStr	= (log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) != 0 ? "" : source;
+
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	if (!qpXmlWriter_writeStringElement(log->writer, "KernelSource", sourceStr))
+	{
+		qpPrintf("qpTestLog_writeKernelSource(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write a SPIR-V module assembly source into the log.
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeSpirVAssemblySource (qpTestLog* log, const char* source)
+{
+	const char* const	sourceStr	= (log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) != 0 ? "" : source;
+
+	deMutex_lock(log->lock);
+
+	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM);
+
+	if (!qpXmlWriter_writeStringElement(log->writer, "SpirVAssemblySource", sourceStr))
+	{
+		qpPrintf("qpTestLog_writeSpirVAssemblySource(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Write OpenCL kernel compilation results into the log
+ *//*--------------------------------------------------------------------*/
+deBool qpTestLog_writeCompileInfo (qpTestLog* log, const char* name, const char* description, deBool compileOk, const char* infoLog)
+{
+	int				numAttribs = 0;
+	qpXmlAttribute	attribs[3];
+
+	DE_ASSERT(log && name && description && infoLog);
+	deMutex_lock(log->lock);
+
+	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
+	attribs[numAttribs++] = qpSetStringAttrib("Description", description);
+	attribs[numAttribs++] = qpSetStringAttrib("CompileStatus", compileOk ? "OK" : "Fail");
+
+	if (!qpXmlWriter_startElement(log->writer, "CompileInfo", numAttribs, attribs) ||
+		!qpXmlWriter_writeStringElement(log->writer, "InfoLog", infoLog) ||
+		!qpXmlWriter_endElement(log->writer, "CompileInfo"))
+	{
+		qpPrintf("qpTestLog_writeCompileInfo(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deBool qpTestLog_startSampleList (qpTestLog* log, const char* name, const char* description)
+{
+	int				numAttribs = 0;
+	qpXmlAttribute	attribs[2];
+
+	DE_ASSERT(log && name && description);
+	deMutex_lock(log->lock);
+
+	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
+	attribs[numAttribs++] = qpSetStringAttrib("Description", description);
+
+	if (!qpXmlWriter_startElement(log->writer, "SampleList", numAttribs, attribs))
+	{
+		qpPrintf("qpTestLog_startSampleList(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLELIST));
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deBool qpTestLog_startSampleInfo (qpTestLog* log)
+{
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	if (!qpXmlWriter_startElement(log->writer, "SampleInfo", 0, DE_NULL))
+	{
+		qpPrintf("qpTestLog_startSampleInfo(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLEINFO));
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deBool qpTestLog_writeValueInfo (qpTestLog* log, const char* name, const char* description, const char* unit, qpSampleValueTag tag)
+{
+	const char*		tagName		= QP_LOOKUP_STRING(s_qpSampleValueTagMap, tag);
+	int				numAttribs	= 0;
+	qpXmlAttribute	attribs[4];
+
+	DE_ASSERT(log && name && description && tagName);
+	deMutex_lock(log->lock);
+
+	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLEINFO);
+
+	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
+	attribs[numAttribs++] = qpSetStringAttrib("Description", description);
+	attribs[numAttribs++] = qpSetStringAttrib("Tag", tagName);
+
+	if (unit)
+		attribs[numAttribs++] = qpSetStringAttrib("Unit", unit);
+
+	if (!qpXmlWriter_startElement(log->writer, "ValueInfo", numAttribs, attribs) ||
+		!qpXmlWriter_endElement(log->writer, "ValueInfo"))
+	{
+		qpPrintf("qpTestLog_writeValueInfo(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deBool qpTestLog_endSampleInfo (qpTestLog* log)
+{
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	if (!qpXmlWriter_endElement(log->writer, "SampleInfo"))
+	{
+		qpPrintf("qpTestLog_endSampleInfo(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SAMPLEINFO);
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deBool qpTestLog_startSample (qpTestLog* log)
+{
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLELIST);
+
+	if (!qpXmlWriter_startElement(log->writer, "Sample", 0, DE_NULL))
+	{
+		qpPrintf("qpTestLog_startSample(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLE));
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deBool qpTestLog_writeValueFloat (qpTestLog* log, double value)
+{
+	char tmpString[512];
+	doubleToString(value, tmpString, (int)sizeof(tmpString));
+
+	deMutex_lock(log->lock);
+
+	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLE);
+
+	if (!qpXmlWriter_writeStringElement(log->writer, "Value", &tmpString[0]))
+	{
+		qpPrintf("qpTestLog_writeSampleValue(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deBool qpTestLog_writeValueInteger (qpTestLog* log, deInt64 value)
+{
+	char tmpString[64];
+	int64ToString(value, tmpString);
+
+	deMutex_lock(log->lock);
+
+	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLE);
+
+	if (!qpXmlWriter_writeStringElement(log->writer, "Value", &tmpString[0]))
+	{
+		qpPrintf("qpTestLog_writeSampleValue(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deBool qpTestLog_endSample (qpTestLog* log)
+{
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	if (!qpXmlWriter_endElement(log->writer, "Sample"))
+	{
+		qpPrintf("qpTestLog_endSample(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SAMPLE);
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deBool qpTestLog_endSampleList (qpTestLog* log)
+{
+	DE_ASSERT(log);
+	deMutex_lock(log->lock);
+
+	if (!qpXmlWriter_endElement(log->writer, "SampleList"))
+	{
+		qpPrintf("qpTestLog_endSampleList(): Writing XML failed\n");
+		deMutex_unlock(log->lock);
+		return DE_FALSE;
+	}
+
+	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SAMPLELIST);
+
+	deMutex_unlock(log->lock);
+	return DE_TRUE;
+}
+
+deUint32 qpTestLog_getLogFlags (const qpTestLog* log)
+{
+	DE_ASSERT(log);
+	return log->flags;
+}
+
+const char* qpGetTestResultName (qpTestResult result)
+{
+	return QP_LOOKUP_STRING(s_qpTestResultMap, result);
+}
diff --git a/src/third_party/angle/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp b/src/third_party/angle/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp
new file mode 100644
index 0000000..46a77a6
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp
@@ -0,0 +1,333 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "tcuANGLENativeDisplayFactory.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "deClock.h"
+#include "deMemory.h"
+#include "deThread.h"
+#include "egluDefs.hpp"
+#include "eglwLibrary.hpp"
+#include "OSPixmap.h"
+#include "OSWindow.h"
+#include "tcuTexture.hpp"
+
+// clang-format off
+#if (DE_OS == DE_OS_WIN32)
+    #define ANGLE_EGL_LIBRARY_NAME "libEGL.dll"
+#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID)
+    #define ANGLE_EGL_LIBRARY_NAME "libEGL.so"
+#elif (DE_OS == DE_OS_OSX)
+    #define ANGLE_EGL_LIBRARY_NAME "libEGL.dylib"
+#else
+    #error "Unsupported platform"
+#endif
+// clang-format on
+
+namespace tcu
+{
+namespace
+{
+
+enum
+{
+    DEFAULT_SURFACE_WIDTH       = 400,
+    DEFAULT_SURFACE_HEIGHT      = 300,
+    WAIT_WINDOW_VISIBLE_MS      = 500   //!< Time to wait before issuing screenshot after changing window visibility (hack for DWM)
+};
+
+static const eglu::NativeDisplay::Capability DISPLAY_CAPABILITIES = eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM;
+static const eglu::NativePixmap::Capability  BITMAP_CAPABILITIES  = eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY;
+static const eglu::NativeWindow::Capability  WINDOW_CAPABILITIES  = (eglu::NativeWindow::Capability)
+                                                                     (eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY    |
+                                                                      eglu::NativeWindow::CAPABILITY_GET_SURFACE_SIZE         |
+                                                                      eglu::NativeWindow::CAPABILITY_GET_SCREEN_SIZE          |
+                                                                      eglu::NativeWindow::CAPABILITY_READ_SCREEN_PIXELS       |
+                                                                      eglu::NativeWindow::CAPABILITY_SET_SURFACE_SIZE         |
+                                                                      eglu::NativeWindow::CAPABILITY_CHANGE_VISIBILITY);
+
+class ANGLENativeDisplay : public eglu::NativeDisplay
+{
+  public:
+    ANGLENativeDisplay(const std::vector<eglw::EGLAttrib> &attribs);
+    virtual ~ANGLENativeDisplay() {}
+
+    void *getPlatformNative() override
+    {
+        // On OSX 64bits mDeviceContext is a 32 bit integer, so we can't simply
+        // use reinterpret_cast<void*>.
+        void *result = nullptr;
+        memcpy(&result, &mDeviceContext, sizeof(mDeviceContext));
+        return result;
+    }
+    const eglw::EGLAttrib *getPlatformAttributes() const override { return &mPlatformAttributes[0]; }
+    const eglw::Library &getLibrary() const override { return mLibrary; }
+
+    EGLNativeDisplayType getDeviceContext() { return mDeviceContext; }
+
+  private:
+    EGLNativeDisplayType mDeviceContext;
+    eglw::DefaultLibrary mLibrary;
+    std::vector<eglw::EGLAttrib> mPlatformAttributes;
+};
+
+class NativePixmapFactory : public eglu::NativePixmapFactory
+{
+  public:
+    NativePixmapFactory();
+    ~NativePixmapFactory() {}
+
+    eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay, int width, int height) const override;
+    eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay, eglw::EGLDisplay display, eglw::EGLConfig config, const eglw::EGLAttrib* attribList, int width, int height) const override;
+};
+
+class NativePixmap : public eglu::NativePixmap
+{
+  public:
+    NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth);
+    virtual ~NativePixmap();
+
+    eglw::EGLNativePixmapType getLegacyNative() override;
+
+  private:
+    OSPixmap *mPixmap;
+};
+
+class NativeWindowFactory : public eglu::NativeWindowFactory
+{
+  public:
+    NativeWindowFactory(EventState *eventState);
+    ~NativeWindowFactory() override {}
+
+    eglu::NativeWindow *createWindow(eglu::NativeDisplay *nativeDisplay, const eglu::WindowParams &params) const override;
+
+  private:
+    EventState *mEvents;
+};
+
+class NativeWindow : public eglu::NativeWindow
+{
+  public:
+    NativeWindow(ANGLENativeDisplay *nativeDisplay, const eglu::WindowParams &params, EventState *eventState);
+    ~NativeWindow() override;
+
+    eglw::EGLNativeWindowType getLegacyNative() override;
+    IVec2 getSurfaceSize() const override;
+    IVec2 getScreenSize() const override { return getSurfaceSize(); }
+    void processEvents() override;
+    void setSurfaceSize(IVec2 size) override;
+    void setVisibility(eglu::WindowParams::Visibility visibility) override;
+    void readScreenPixels(tcu::TextureLevel* dst) const override;
+
+  private:
+    OSWindow *mWindow;
+    EventState *mEvents;
+};
+
+// ANGLE NativeDisplay
+
+ANGLENativeDisplay::ANGLENativeDisplay(const std::vector<EGLAttrib> &attribs)
+    : eglu::NativeDisplay(DISPLAY_CAPABILITIES, EGL_PLATFORM_ANGLE_ANGLE, "EGL_EXT_platform_base"),
+      mDeviceContext(EGL_DEFAULT_DISPLAY),
+      mLibrary(ANGLE_EGL_LIBRARY_NAME),
+      mPlatformAttributes(attribs)
+{
+}
+
+// NativePixmap
+
+NativePixmap::NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth)
+    : eglu::NativePixmap(BITMAP_CAPABILITIES),
+      mPixmap(CreateOSPixmap())
+{
+    if (!mPixmap)
+    {
+        throw ResourceError("Failed to create pixmap", DE_NULL, __FILE__, __LINE__);
+    }
+
+    if (!mPixmap->initialize(display, width, height, bitDepth))
+    {
+        throw ResourceError("Failed to initialize pixmap", DE_NULL, __FILE__, __LINE__);
+    }
+}
+
+NativePixmap::~NativePixmap()
+{
+    delete mPixmap;
+}
+
+eglw::EGLNativePixmapType NativePixmap::getLegacyNative()
+{
+    return reinterpret_cast<eglw::EGLNativePixmapType>(mPixmap->getNativePixmap());
+}
+
+// NativePixmapFactory
+
+NativePixmapFactory::NativePixmapFactory()
+    : eglu::NativePixmapFactory("bitmap", "ANGLE Bitmap", BITMAP_CAPABILITIES)
+{
+}
+
+eglu::NativePixmap *NativePixmapFactory::createPixmap (eglu::NativeDisplay* nativeDisplay, eglw::EGLDisplay display, eglw::EGLConfig config, const eglw::EGLAttrib* attribList, int width, int height) const
+{
+    const eglw::Library&    egl         = nativeDisplay->getLibrary();
+    int             redBits     = 0;
+    int             greenBits   = 0;
+    int             blueBits    = 0;
+    int             alphaBits   = 0;
+    int             bitSum      = 0;
+
+    DE_ASSERT(display != EGL_NO_DISPLAY);
+
+    egl.getConfigAttrib(display, config, EGL_RED_SIZE,      &redBits);
+    egl.getConfigAttrib(display, config, EGL_GREEN_SIZE,    &greenBits);
+    egl.getConfigAttrib(display, config, EGL_BLUE_SIZE,     &blueBits);
+    egl.getConfigAttrib(display, config, EGL_ALPHA_SIZE,    &alphaBits);
+    EGLU_CHECK_MSG(egl, "eglGetConfigAttrib()");
+
+    bitSum = redBits+greenBits+blueBits+alphaBits;
+
+    return new NativePixmap(dynamic_cast<ANGLENativeDisplay*>(nativeDisplay)->getDeviceContext(), width, height, bitSum);
+}
+
+eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay* nativeDisplay, int width, int height) const
+{
+    const int defaultDepth = 32;
+    return new NativePixmap(dynamic_cast<ANGLENativeDisplay*>(nativeDisplay)->getDeviceContext(), width, height, defaultDepth);
+}
+
+// NativeWindowFactory
+
+NativeWindowFactory::NativeWindowFactory(EventState *eventState)
+    : eglu::NativeWindowFactory("window", "ANGLE Window", WINDOW_CAPABILITIES),
+      mEvents(eventState)
+{
+}
+
+eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay* nativeDisplay, const eglu::WindowParams& params) const
+{
+    return new NativeWindow(dynamic_cast<ANGLENativeDisplay*>(nativeDisplay), params, mEvents);
+}
+
+// NativeWindow
+
+NativeWindow::NativeWindow(ANGLENativeDisplay *nativeDisplay, const eglu::WindowParams& params, EventState *eventState)
+    : eglu::NativeWindow(WINDOW_CAPABILITIES),
+      mWindow(CreateOSWindow()),
+      mEvents(eventState)
+{
+    bool initialized = mWindow->initialize("dEQP ANGLE Tests",
+                                           params.width == eglu::WindowParams::SIZE_DONT_CARE ? DEFAULT_SURFACE_WIDTH : params.width,
+                                           params.height == eglu::WindowParams::SIZE_DONT_CARE ? DEFAULT_SURFACE_HEIGHT : params.height);
+    TCU_CHECK(initialized);
+
+    if (params.visibility != eglu::WindowParams::VISIBILITY_DONT_CARE)
+        setVisibility(params.visibility);
+}
+
+void NativeWindow::setVisibility(eglu::WindowParams::Visibility visibility)
+{
+    switch (visibility)
+    {
+      case eglu::WindowParams::VISIBILITY_HIDDEN:
+        mWindow->setVisible(false);
+        break;
+
+      case eglu::WindowParams::VISIBILITY_VISIBLE:
+      case eglu::WindowParams::VISIBILITY_FULLSCREEN:
+        // \todo [2014-03-12 pyry] Implement FULLSCREEN, or at least SW_MAXIMIZE.
+        mWindow->setVisible(true);
+        break;
+
+      default:
+        DE_ASSERT(DE_FALSE);
+    }
+}
+
+NativeWindow::~NativeWindow()
+{
+    delete mWindow;
+}
+
+eglw::EGLNativeWindowType NativeWindow::getLegacyNative()
+{
+    return reinterpret_cast<eglw::EGLNativeWindowType>(mWindow->getNativeWindow());
+}
+
+IVec2 NativeWindow::getSurfaceSize() const
+{
+    return IVec2(mWindow->getWidth(), mWindow->getHeight());
+}
+
+void NativeWindow::processEvents()
+{
+    mWindow->messageLoop();
+
+    // Look for a quit event to forward to the EventState
+    Event event;
+    while (mWindow->popEvent(&event))
+    {
+        if (event.Type == Event::EVENT_CLOSED)
+        {
+            mEvents->signalQuitEvent();
+        }
+    }
+}
+
+void NativeWindow::setSurfaceSize(IVec2 size)
+{
+    mWindow->resize(size.x(), size.y());
+}
+
+void NativeWindow::readScreenPixels(tcu::TextureLevel *dst) const
+{
+    dst->setStorage(TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT8), mWindow->getWidth(), mWindow->getHeight());
+    bool success = mWindow->takeScreenshot(reinterpret_cast<uint8_t*>(dst->getAccess().getDataPtr()));
+    DE_ASSERT(success);
+    DE_UNREF(success);
+}
+
+} // anonymous
+
+ANGLENativeDisplayFactory::ANGLENativeDisplayFactory(const std::string &name,
+                                                     const std::string &description,
+                                                     const std::vector<eglw::EGLAttrib> &platformAttributes,
+                                                     EventState *eventState)
+    : eglu::NativeDisplayFactory(name, description, DISPLAY_CAPABILITIES, EGL_PLATFORM_ANGLE_ANGLE, "EGL_EXT_platform_base"),
+      mPlatformAttributes(platformAttributes)
+{
+    m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(eventState));
+    m_nativePixmapRegistry.registerFactory(new NativePixmapFactory());
+}
+
+ANGLENativeDisplayFactory::~ANGLENativeDisplayFactory()
+{
+}
+
+eglu::NativeDisplay *ANGLENativeDisplayFactory::createDisplay(const eglw::EGLAttrib *attribList) const
+{
+    DE_UNREF(attribList);
+    return new ANGLENativeDisplay(mPlatformAttributes);
+}
+
+} // tcu
diff --git a/src/third_party/angle/src/tests/deqp_support/tcuANGLENativeDisplayFactory.h b/src/third_party/angle/src/tests/deqp_support/tcuANGLENativeDisplayFactory.h
new file mode 100644
index 0000000..8eecf75
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/tcuANGLENativeDisplayFactory.h
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef TCU_ANGLE_WIN32_NATIVE_DISPLAY_FACTORY_H_
+#define TCU_ANGLE_WIN32_NATIVE_DISPLAY_FACTORY_H_
+
+#include "tcuDefs.hpp"
+#include "egluNativeDisplay.hpp"
+#include "eglwDefs.hpp"
+
+namespace tcu
+{
+
+class EventState
+{
+  public:
+    EventState()
+        : mQuit(false)
+    {
+    }
+    bool quitSignaled() const { return mQuit; };
+    void signalQuitEvent() { mQuit = true; };
+
+  private:
+    bool mQuit;
+};
+
+class ANGLENativeDisplayFactory : public eglu::NativeDisplayFactory
+{
+  public:
+    ANGLENativeDisplayFactory(const std::string &name,
+                              const std::string &description,
+                              const std::vector<eglw::EGLAttrib> &platformAttributes,
+                              EventState *eventState);
+    ~ANGLENativeDisplayFactory() override;
+
+    eglu::NativeDisplay *createDisplay(const eglw::EGLAttrib* attribList) const override;
+
+  private:
+    std::vector<eglw::EGLAttrib> mPlatformAttributes;
+};
+
+} // tcu
+
+#endif // TCU_ANGLE_WIN32_NATIVE_DISPLAY_FACTORY_H_
diff --git a/src/third_party/angle/src/tests/deqp_support/tcuANGLEPlatform.cpp b/src/third_party/angle/src/tests/deqp_support/tcuANGLEPlatform.cpp
new file mode 100644
index 0000000..a45d904
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/tcuANGLEPlatform.cpp
@@ -0,0 +1,139 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "tcuANGLEPlatform.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "egluGLContextFactory.hpp"
+#include "system_utils.h"
+#include "tcuANGLENativeDisplayFactory.h"
+#include "tcuNullContextFactory.hpp"
+
+namespace tcu
+{
+
+ANGLEPlatform::ANGLEPlatform()
+{
+    angle::SetLowPriorityProcess();
+
+#if (DE_OS == DE_OS_WIN32)
+    {
+        std::vector<eglw::EGLAttrib> d3d11Attribs;
+        d3d11Attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+        d3d11Attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+        d3d11Attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+        d3d11Attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+        d3d11Attribs.push_back(EGL_NONE);
+
+        auto *d3d11Factory = new ANGLENativeDisplayFactory(
+            "angle-d3d11", "ANGLE D3D11 Display", d3d11Attribs, &mEvents);
+        m_nativeDisplayFactoryRegistry.registerFactory(d3d11Factory);
+    }
+
+    {
+        std::vector<eglw::EGLAttrib> d3d9Attribs;
+        d3d9Attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+        d3d9Attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE);
+        d3d9Attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+        d3d9Attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+        d3d9Attribs.push_back(EGL_NONE);
+
+        auto *d3d9Factory = new ANGLENativeDisplayFactory(
+            "angle-d3d9", "ANGLE D3D9 Display", d3d9Attribs, &mEvents);
+        m_nativeDisplayFactoryRegistry.registerFactory(d3d9Factory);
+    }
+
+    {
+        std::vector<eglw::EGLAttrib> d3d1193Attribs;
+        d3d1193Attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+        d3d1193Attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+        d3d1193Attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+        d3d1193Attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+        d3d1193Attribs.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
+        d3d1193Attribs.push_back(9);
+        d3d1193Attribs.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
+        d3d1193Attribs.push_back(3);
+        d3d1193Attribs.push_back(EGL_NONE);
+
+        auto *d3d1193Factory = new ANGLENativeDisplayFactory(
+            "angle-d3d11-fl93", "ANGLE D3D11 FL9_3 Display", d3d1193Attribs, &mEvents);
+        m_nativeDisplayFactoryRegistry.registerFactory(d3d1193Factory);
+    }
+#endif // (DE_OS == DE_OS_WIN32)
+
+#if defined(ANGLE_USE_OZONE) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_WIN32)
+    {
+        std::vector<eglw::EGLAttrib> glesAttribs;
+        glesAttribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+        glesAttribs.push_back(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE);
+        glesAttribs.push_back(EGL_NONE);
+
+        auto *glesFactory = new ANGLENativeDisplayFactory(
+            "angle-gles", "ANGLE OpenGL ES Display", glesAttribs, &mEvents);
+        m_nativeDisplayFactoryRegistry.registerFactory(glesFactory);
+    }
+#endif
+
+    {
+        std::vector<eglw::EGLAttrib> glAttribs;
+        glAttribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+        glAttribs.push_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE);
+        glAttribs.push_back(EGL_NONE);
+
+        auto *glFactory = new ANGLENativeDisplayFactory(
+            "angle-gl", "ANGLE OpenGL Display", glAttribs, &mEvents);
+        m_nativeDisplayFactoryRegistry.registerFactory(glFactory);
+    }
+
+    {
+        std::vector<eglw::EGLAttrib> nullAttribs;
+        nullAttribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+        nullAttribs.push_back(EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE);
+        nullAttribs.push_back(EGL_NONE);
+
+        auto *nullFactory = new ANGLENativeDisplayFactory(
+            "angle-null", "ANGLE NULL Display", nullAttribs, &mEvents);
+        m_nativeDisplayFactoryRegistry.registerFactory(nullFactory);
+    }
+
+    m_contextFactoryRegistry.registerFactory(new eglu::GLContextFactory(m_nativeDisplayFactoryRegistry));
+
+    // Add Null context type for use in generating case lists
+    m_contextFactoryRegistry.registerFactory(new null::NullGLContextFactory());
+}
+
+ANGLEPlatform::~ANGLEPlatform()
+{
+}
+
+bool ANGLEPlatform::processEvents()
+{
+    return !mEvents.quitSignaled();
+}
+
+} // tcu
+
+// Create platform
+tcu::Platform *createPlatform()
+{
+    return new tcu::ANGLEPlatform();
+}
diff --git a/src/third_party/angle/src/tests/deqp_support/tcuANGLEPlatform.h b/src/third_party/angle/src/tests/deqp_support/tcuANGLEPlatform.h
new file mode 100644
index 0000000..d62c1c6
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/tcuANGLEPlatform.h
@@ -0,0 +1,56 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef TCU_ANGLE_WIN32_PLATFORM_H_
+#define TCU_ANGLE_WIN32_PLATFORM_H_
+
+#include "tcuDefs.hpp"
+#include "tcuPlatform.hpp"
+#include "gluPlatform.hpp"
+
+#ifndef _EGLUPLATFORM_HPP
+#   include "egluPlatform.hpp"
+#endif
+
+#include "tcuANGLENativeDisplayFactory.h"
+
+namespace tcu
+{
+
+class ANGLEPlatform : public tcu::Platform,
+                      private glu::Platform,
+                      private eglu::Platform
+{
+  public:
+    ANGLEPlatform();
+    ~ANGLEPlatform();
+
+    bool processEvents() override;
+
+    const glu::Platform &getGLPlatform() const override { return static_cast<const glu::Platform&>(*this); }
+    const eglu::Platform &getEGLPlatform() const override { return static_cast<const eglu::Platform&>(*this); }
+
+  private:
+    EventState mEvents;
+};
+
+} // tcu
+
+#endif // TCU_ANGLE_WIN32_PLATFORM_H_
diff --git a/src/third_party/angle/src/tests/deqp_support/tcuRandomOrderExecutor.cpp b/src/third_party/angle/src/tests/deqp_support/tcuRandomOrderExecutor.cpp
new file mode 100644
index 0000000..3745bc3
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/tcuRandomOrderExecutor.cpp
@@ -0,0 +1,282 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Executor which can run randomly accessed tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuRandomOrderExecutor.h"
+
+#include "tcuCommandLine.hpp"
+#include "tcuTestLog.hpp"
+#include "deStringUtil.hpp"
+#include "deClock.h"
+
+#include <cstdio>
+#include <algorithm>
+#include <fstream>
+
+using std::vector;
+using std::string;
+
+namespace tcu
+{
+
+RandomOrderExecutor::RandomOrderExecutor(TestPackageRoot &root, TestContext &testCtx)
+    : m_testCtx(testCtx), m_inflater(testCtx)
+{
+    m_nodeStack.push_back(NodeStackEntry(&root));
+    root.getChildren(m_nodeStack[0].children);
+}
+
+RandomOrderExecutor::~RandomOrderExecutor(void)
+{
+    pruneStack(1);
+}
+
+void RandomOrderExecutor::pruneStack(size_t newStackSize)
+{
+    // \note Root is not managed by us
+    DE_ASSERT(de::inRange(newStackSize, size_t(1), m_nodeStack.size()));
+
+    while (m_nodeStack.size() > newStackSize)
+    {
+        NodeStackEntry &curEntry = m_nodeStack.back();
+        const bool isPkg = curEntry.node->getNodeType() == NODETYPE_PACKAGE;
+
+        DE_ASSERT((m_nodeStack.size() == 2) == isPkg);
+
+        if (curEntry.node)  // Just in case we are in
+                            // cleanup path after partial
+                            // prune
+        {
+            if (curEntry.node->getNodeType() == NODETYPE_GROUP)
+                m_inflater.leaveGroupNode(static_cast<TestCaseGroup *>(curEntry.node));
+            else if (curEntry.node->getNodeType() == NODETYPE_PACKAGE)
+                m_inflater.leaveTestPackage(static_cast<TestPackage *>(curEntry.node));
+            else
+                DE_ASSERT(curEntry.children.empty());
+
+            curEntry.node = DE_NULL;
+            curEntry.children.clear();
+        }
+
+        if (isPkg)
+            m_caseExecutor.clear();
+
+        m_nodeStack.pop_back();
+    }
+}
+
+static TestNode *findNodeByName(vector<TestNode *> &nodes, const std::string &name)
+{
+    for (vector<TestNode *>::const_iterator node = nodes.begin(); node != nodes.end(); ++node)
+    {
+        if (name == (*node)->getName())
+            return *node;
+    }
+
+    return DE_NULL;
+}
+
+TestCase *RandomOrderExecutor::seekToCase(const string &path)
+{
+    const vector<string> components = de::splitString(path, '.');
+    size_t compNdx;
+
+    DE_ASSERT(!m_nodeStack.empty() && m_nodeStack.front().node->getNodeType() == NODETYPE_ROOT);
+
+    for (compNdx = 0; compNdx < components.size(); compNdx++)
+    {
+        const size_t stackPos = compNdx + 1;
+
+        if (stackPos >= m_nodeStack.size())
+            break;  // Stack end
+        else if (components[compNdx] != m_nodeStack[stackPos].node->getName())
+        {
+            // Current stack doesn't match any more, prune.
+            pruneStack(stackPos);
+            break;
+        }
+    }
+
+    DE_ASSERT(m_nodeStack.size() == compNdx + 1);
+
+    for (; compNdx < components.size(); compNdx++)
+    {
+        const size_t parentStackPos = compNdx;
+        TestNode *const curNode =
+            findNodeByName(m_nodeStack[parentStackPos].children, components[compNdx]);
+
+        if (!curNode)
+            throw Exception(string("Test hierarchy node not found: ") + path);
+
+        m_nodeStack.push_back(NodeStackEntry(curNode));
+
+        if (curNode->getNodeType() == NODETYPE_PACKAGE)
+        {
+            TestPackage *const testPackage = static_cast<TestPackage *>(curNode);
+
+            m_inflater.enterTestPackage(testPackage, m_nodeStack.back().children);
+            DE_ASSERT(!m_caseExecutor);
+            m_caseExecutor = de::MovePtr<TestCaseExecutor>(testPackage->createExecutor());
+        }
+        else if (curNode->getNodeType() == NODETYPE_GROUP)
+            m_inflater.enterGroupNode(static_cast<TestCaseGroup *>(curNode),
+                                      m_nodeStack.back().children);
+        else if (compNdx + 1 != components.size())
+            throw Exception(string("Invalid test hierarchy path: ") + path);
+    }
+
+    DE_ASSERT(m_nodeStack.size() == components.size() + 1);
+
+    if (isTestNodeTypeExecutable(m_nodeStack.back().node->getNodeType()))
+        return dynamic_cast<TestCase *>(m_nodeStack.back().node);
+    else
+        throw Exception(string("Not a test case: ") + path);
+}
+
+static qpTestCaseType nodeTypeToTestCaseType(TestNodeType nodeType)
+{
+    switch (nodeType)
+    {
+        case NODETYPE_SELF_VALIDATE:
+            return QP_TEST_CASE_TYPE_SELF_VALIDATE;
+        case NODETYPE_PERFORMANCE:
+            return QP_TEST_CASE_TYPE_PERFORMANCE;
+        case NODETYPE_CAPABILITY:
+            return QP_TEST_CASE_TYPE_CAPABILITY;
+        case NODETYPE_ACCURACY:
+            return QP_TEST_CASE_TYPE_ACCURACY;
+        default:
+            DE_ASSERT(false);
+            return QP_TEST_CASE_TYPE_LAST;
+    }
+}
+
+TestStatus RandomOrderExecutor::execute(const std::string &casePath)
+{
+    TestCase *const testCase = seekToCase(casePath);
+    TestLog &log = m_testCtx.getLog();
+    const qpTestCaseType caseType = nodeTypeToTestCaseType(testCase->getNodeType());
+
+    m_testCtx.setTerminateAfter(false);
+    log.startCase(casePath.c_str(), caseType);
+
+    {
+        const TestStatus result = executeInner(testCase, casePath);
+        log.endCase(result.getCode(), result.getDescription().c_str());
+        return result;
+    }
+}
+
+tcu::TestStatus RandomOrderExecutor::executeInner(TestCase *testCase, const std::string &casePath)
+{
+    TestLog &log = m_testCtx.getLog();
+    const deUint64 testStartTime = deGetMicroseconds();
+
+    m_testCtx.setTestResult(QP_TEST_RESULT_LAST, "");
+
+    // Initialize, will return immediately if fails
+    try
+    {
+        m_caseExecutor->init(testCase, casePath);
+    }
+    catch (const std::bad_alloc &)
+    {
+        m_testCtx.setTerminateAfter(true);
+        return TestStatus(QP_TEST_RESULT_RESOURCE_ERROR,
+                          "Failed to allocate memory in test case init");
+    }
+    catch (const TestException &e)
+    {
+        DE_ASSERT(e.getTestResult() != QP_TEST_RESULT_LAST);
+        m_testCtx.setTerminateAfter(e.isFatal());
+        log << e;
+        return TestStatus(e.getTestResult(), e.getMessage());
+    }
+    catch (const Exception &e)
+    {
+        log << e;
+        return TestStatus(QP_TEST_RESULT_FAIL, e.getMessage());
+    }
+
+    // Execute
+    for (;;)
+    {
+        TestCase::IterateResult iterateResult = TestCase::STOP;
+
+        m_testCtx.touchWatchdog();
+
+        try
+        {
+            iterateResult = m_caseExecutor->iterate(testCase);
+        }
+        catch (const std::bad_alloc &)
+        {
+            m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR,
+                                    "Failed to allocate memory during test "
+                                    "execution");
+        }
+        catch (const TestException &e)
+        {
+            log << e;
+            m_testCtx.setTestResult(e.getTestResult(), e.getMessage());
+            m_testCtx.setTerminateAfter(e.isFatal());
+        }
+        catch (const Exception &e)
+        {
+            log << e;
+            m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
+        }
+
+        if (iterateResult == TestCase::STOP)
+            break;
+    }
+
+    DE_ASSERT(m_testCtx.getTestResult() != QP_TEST_RESULT_LAST);
+
+    if (m_testCtx.getTestResult() == QP_TEST_RESULT_RESOURCE_ERROR)
+        m_testCtx.setTerminateAfter(true);
+
+    // De-initialize
+    try
+    {
+        m_caseExecutor->deinit(testCase);
+    }
+    catch (const tcu::Exception &e)
+    {
+        log << e << TestLog::Message << "Error in test case deinit, test program "
+                                        "will terminate."
+            << TestLog::EndMessage;
+        m_testCtx.setTerminateAfter(true);
+    }
+
+    if (m_testCtx.getWatchDog())
+        qpWatchDog_reset(m_testCtx.getWatchDog());
+
+    {
+        const TestStatus result =
+            TestStatus(m_testCtx.getTestResult(), m_testCtx.getTestResultDesc());
+        m_testCtx.setTestResult(QP_TEST_RESULT_LAST, "");
+        return result;
+    }
+}
+
+}  // tcu
diff --git a/src/third_party/angle/src/tests/deqp_support/tcuRandomOrderExecutor.h b/src/third_party/angle/src/tests/deqp_support/tcuRandomOrderExecutor.h
new file mode 100644
index 0000000..f8c7085
--- /dev/null
+++ b/src/third_party/angle/src/tests/deqp_support/tcuRandomOrderExecutor.h
@@ -0,0 +1,66 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */ /*!
+ * \file
+ * \brief Generic main().
+ */ /*--------------------------------------------------------------------*/
+
+#ifndef TCU_RANDOM_ORDER_EXECUTOR_H_
+#define TCU_RANDOM_ORDER_EXECUTOR_H_
+
+#include "tcuTestHierarchyIterator.hpp"
+#include "deUniquePtr.hpp"
+
+namespace tcu
+{
+
+class RandomOrderExecutor
+{
+   public:
+    RandomOrderExecutor(TestPackageRoot &root, TestContext &testCtx);
+    ~RandomOrderExecutor(void);
+
+    TestStatus execute(const std::string &path);
+
+   private:
+    void pruneStack(size_t newStackSize);
+    TestCase *seekToCase(const std::string &path);
+
+    TestStatus executeInner(TestCase *testCase, const std::string &casePath);
+
+    struct NodeStackEntry
+    {
+        TestNode *node;
+        std::vector<TestNode *> children;
+
+        NodeStackEntry(void) : node(DE_NULL) {}
+        NodeStackEntry(TestNode *node_) : node(node_) {}
+    };
+
+    TestContext &m_testCtx;
+
+    DefaultHierarchyInflater m_inflater;
+    std::vector<NodeStackEntry> m_nodeStack;
+
+    de::MovePtr<TestCaseExecutor> m_caseExecutor;
+};
+
+}  // tcu
+
+#endif  // TCU_RANDOM_ORDER_EXECUTOR_H_
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLContextCompatibilityTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLContextCompatibilityTest.cpp
new file mode 100644
index 0000000..a9c5780
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLContextCompatibilityTest.cpp
@@ -0,0 +1,355 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLContextCompatibilityTest.cpp:
+//   This test will try to use all combinations of context configs and
+//   surface configs. If the configs are compatible, it checks that simple
+//   rendering works, otherwise it checks an error is generated one MakeCurrent.
+#include <gtest/gtest.h>
+
+#include <vector>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "OSWindow.h"
+#include "test_utils/ANGLETest.h"
+#include "test_utils/angle_test_configs.h"
+
+using namespace angle;
+
+namespace
+{
+
+const EGLint contextAttribs[] =
+{
+    EGL_CONTEXT_CLIENT_VERSION, 2,
+    EGL_NONE
+};
+
+}
+
+class EGLContextCompatibilityTest : public ANGLETest
+{
+  public:
+    EGLContextCompatibilityTest()
+      : mDisplay(0)
+    {
+    }
+
+    void SetUp() override
+    {
+        PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+        ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr);
+
+        EGLint dispattrs[] =
+        {
+            EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(),
+            EGL_NONE
+        };
+        mDisplay = eglGetPlatformDisplayEXT(
+            EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
+        ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
+
+        ASSERT_TRUE(eglInitialize(mDisplay, nullptr, nullptr) == EGL_TRUE);
+
+        int nConfigs = 0;
+        ASSERT_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &nConfigs) == EGL_TRUE);
+        ASSERT_TRUE(nConfigs != 0);
+
+        int nReturnedConfigs = 0;
+        mConfigs.resize(nConfigs);
+        ASSERT_TRUE(eglGetConfigs(mDisplay, mConfigs.data(), nConfigs, &nReturnedConfigs) == EGL_TRUE);
+        ASSERT_TRUE(nConfigs == nReturnedConfigs);
+    }
+
+    void TearDown() override
+    {
+        eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        eglTerminate(mDisplay);
+    };
+
+  protected:
+    // Queries EGL config to determine if multisampled or not
+    bool isMultisampledConfig(EGLConfig config)
+    {
+        EGLint samples = 0;
+        eglGetConfigAttrib(mDisplay, config, EGL_SAMPLES, &samples);
+        return (samples > 1);
+    }
+
+    bool areConfigsCompatible(EGLConfig c1, EGLConfig c2, EGLint surfaceBit)
+    {
+        EGLint colorBufferType1, colorBufferType2;
+        EGLint red1, red2, green1, green2, blue1, blue2, alpha1, alpha2;
+        EGLint depth1, depth2, stencil1, stencil2;
+        EGLint surfaceType1, surfaceType2;
+
+        eglGetConfigAttrib(mDisplay, c1, EGL_COLOR_BUFFER_TYPE, &colorBufferType1);
+        eglGetConfigAttrib(mDisplay, c2, EGL_COLOR_BUFFER_TYPE, &colorBufferType2);
+
+        eglGetConfigAttrib(mDisplay, c1, EGL_RED_SIZE, &red1);
+        eglGetConfigAttrib(mDisplay, c2, EGL_RED_SIZE, &red2);
+        eglGetConfigAttrib(mDisplay, c1, EGL_GREEN_SIZE, &green1);
+        eglGetConfigAttrib(mDisplay, c2, EGL_GREEN_SIZE, &green2);
+        eglGetConfigAttrib(mDisplay, c1, EGL_BLUE_SIZE, &blue1);
+        eglGetConfigAttrib(mDisplay, c2, EGL_BLUE_SIZE, &blue2);
+        eglGetConfigAttrib(mDisplay, c1, EGL_ALPHA_SIZE, &alpha1);
+        eglGetConfigAttrib(mDisplay, c2, EGL_ALPHA_SIZE, &alpha2);
+
+        eglGetConfigAttrib(mDisplay, c1, EGL_DEPTH_SIZE, &depth1);
+        eglGetConfigAttrib(mDisplay, c2, EGL_DEPTH_SIZE, &depth2);
+        eglGetConfigAttrib(mDisplay, c1, EGL_STENCIL_SIZE, &stencil1);
+        eglGetConfigAttrib(mDisplay, c2, EGL_STENCIL_SIZE, &stencil2);
+
+        eglGetConfigAttrib(mDisplay, c1, EGL_SURFACE_TYPE, &surfaceType1);
+        eglGetConfigAttrib(mDisplay, c2, EGL_SURFACE_TYPE, &surfaceType2);
+
+        EGLint colorComponentType1 = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+        EGLint colorComponentType2 = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+        if (eglDisplayExtensionEnabled(mDisplay, "EGL_EXT_pixel_format_float"))
+        {
+            eglGetConfigAttrib(mDisplay, c1, EGL_COLOR_COMPONENT_TYPE_EXT, &colorComponentType1);
+            eglGetConfigAttrib(mDisplay, c2, EGL_COLOR_COMPONENT_TYPE_EXT, &colorComponentType2);
+        }
+
+        EXPECT_EGL_SUCCESS();
+
+        return colorBufferType1 == colorBufferType2 && red1 == red2 && green1 == green2 &&
+               blue1 == blue2 && alpha1 == alpha2 && colorComponentType1 == colorComponentType2 &&
+               depth1 == depth2 && stencil1 == stencil2 && (surfaceType1 & surfaceBit) != 0 &&
+               (surfaceType2 & surfaceBit) != 0;
+    }
+
+    void testWindowCompatibility(EGLConfig windowConfig, EGLConfig contextConfig, bool compatible) const
+    {
+        OSWindow *osWindow = CreateOSWindow();
+        ASSERT_TRUE(osWindow != nullptr);
+        osWindow->initialize("EGLContextCompatibilityTest", 500, 500);
+        osWindow->setVisible(true);
+
+        EGLContext context = eglCreateContext(mDisplay, contextConfig, EGL_NO_CONTEXT, contextAttribs);
+        ASSERT_TRUE(context != EGL_NO_CONTEXT);
+
+        EGLSurface window = eglCreateWindowSurface(mDisplay, windowConfig, osWindow->getNativeWindow(), nullptr);
+        ASSERT_EGL_SUCCESS();
+
+        if (compatible)
+        {
+            testClearSurface(window, windowConfig, context);
+        }
+        else
+        {
+            testMakeCurrentFails(window, context);
+        }
+
+        eglDestroySurface(mDisplay, window);
+        ASSERT_EGL_SUCCESS();
+
+        eglDestroyContext(mDisplay, context);
+        ASSERT_EGL_SUCCESS();
+
+        SafeDelete(osWindow);
+    }
+
+    void testPbufferCompatibility(EGLConfig pbufferConfig, EGLConfig contextConfig, bool compatible) const
+    {
+        EGLContext context = eglCreateContext(mDisplay, contextConfig, EGL_NO_CONTEXT, contextAttribs);
+        ASSERT_TRUE(context != EGL_NO_CONTEXT);
+
+        const EGLint pBufferAttribs[] =
+        {
+            EGL_WIDTH, 500,
+            EGL_HEIGHT, 500,
+            EGL_NONE,
+        };
+        EGLSurface pbuffer = eglCreatePbufferSurface(mDisplay, pbufferConfig, pBufferAttribs);
+        ASSERT_TRUE(pbuffer != EGL_NO_SURFACE);
+
+        if (compatible)
+        {
+            testClearSurface(pbuffer, pbufferConfig, context);
+        }
+        else
+        {
+            testMakeCurrentFails(pbuffer, context);
+        }
+
+        eglDestroySurface(mDisplay, pbuffer);
+        ASSERT_EGL_SUCCESS();
+
+        eglDestroyContext(mDisplay, context);
+        ASSERT_EGL_SUCCESS();
+    }
+
+    std::vector<EGLConfig> mConfigs;
+    EGLDisplay mDisplay;
+
+  private:
+    void testClearSurface(EGLSurface surface, EGLConfig surfaceConfig, EGLContext context) const
+    {
+        eglMakeCurrent(mDisplay, surface, surface, context);
+        ASSERT_EGL_SUCCESS();
+
+        glViewport(0, 0, 500, 500);
+        glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        ASSERT_GL_NO_ERROR();
+
+        EGLint surfaceCompontentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+        if (eglDisplayExtensionEnabled(mDisplay, "EGL_EXT_pixel_format_float"))
+        {
+            eglGetConfigAttrib(mDisplay, surfaceConfig, EGL_COLOR_COMPONENT_TYPE_EXT,
+                               &surfaceCompontentType);
+        }
+
+        if (surfaceCompontentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)
+        {
+            EXPECT_PIXEL_EQ(250, 250, 0, 0, 255, 255);
+        }
+        else
+        {
+            EXPECT_PIXEL_32F_EQ(250, 250, 0, 0, 1.0f, 1.0f);
+        }
+
+        eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        ASSERT_EGL_SUCCESS();
+    }
+
+    void testMakeCurrentFails(EGLSurface surface, EGLContext context) const
+    {
+        eglMakeCurrent(mDisplay, surface, surface, context);
+        EXPECT_EGL_ERROR(EGL_BAD_MATCH);
+    }
+};
+
+// The test is split in several subtest so that simple cases
+// are tested separately. Also each surface types are not tested
+// together.
+
+// Basic test checking contexts and windows created with the
+// same config can render.
+TEST_P(EGLContextCompatibilityTest, WindowSameConfig)
+{
+    for (size_t i = 0; i < mConfigs.size(); i++)
+    {
+        EGLConfig config = mConfigs[i];
+
+        EGLint surfaceType;
+        eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType);
+        ASSERT_EGL_SUCCESS();
+
+        if ((surfaceType & EGL_WINDOW_BIT) != 0)
+        {
+            // Disabling multisampled configurations due to test instability with various graphics
+            // cards
+            if (isMultisampledConfig(config))
+            {
+                continue;
+            }
+            testWindowCompatibility(config, config, true);
+        }
+    }
+}
+
+// Basic test checking contexts and pbuffers created with the
+// same config can render.
+TEST_P(EGLContextCompatibilityTest, PbufferSameConfig)
+{
+    for (size_t i = 0; i < mConfigs.size(); i++)
+    {
+        EGLConfig config = mConfigs[i];
+
+        EGLint surfaceType;
+        eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType);
+        ASSERT_EGL_SUCCESS();
+
+        if ((surfaceType & EGL_PBUFFER_BIT) != 0)
+        {
+            // Disabling multisampled configurations due to test instability with various graphics
+            // cards
+            if (isMultisampledConfig(config))
+            {
+                continue;
+            }
+            testPbufferCompatibility(config, config, true);
+        }
+    }
+}
+
+// Check that a context rendering to a window with a different
+// config works or errors according to the EGL compatibility rules
+TEST_P(EGLContextCompatibilityTest, WindowDifferentConfig)
+{
+    for (size_t i = 0; i < mConfigs.size(); i++)
+    {
+        EGLConfig config1 = mConfigs[i];
+        // Disabling multisampled configurations due to test instability with various graphics cards
+        if (isMultisampledConfig(config1))
+        {
+            continue;
+        }
+
+        EGLint surfaceType;
+        eglGetConfigAttrib(mDisplay, config1, EGL_SURFACE_TYPE, &surfaceType);
+        ASSERT_EGL_SUCCESS();
+
+        if ((surfaceType & EGL_WINDOW_BIT) == 0)
+        {
+            continue;
+        }
+
+        for (size_t j = 0; j < mConfigs.size(); j++)
+        {
+            EGLConfig config2 = mConfigs[j];
+            // Disabling multisampled configurations due to test instability with various graphics
+            // cards
+            if (isMultisampledConfig(config2))
+            {
+                continue;
+            }
+            testWindowCompatibility(config1, config2,
+                                    areConfigsCompatible(config1, config2, EGL_WINDOW_BIT));
+        }
+    }
+}
+
+// Check that a context rendering to a pbuffer with a different
+// config works or errors according to the EGL compatibility rules
+TEST_P(EGLContextCompatibilityTest, PbufferDifferentConfig)
+{
+    for (size_t i = 0; i < mConfigs.size(); i++)
+    {
+        EGLConfig config1 = mConfigs[i];
+        // Disabling multisampled configurations due to test instability with various graphics cards
+        if (isMultisampledConfig(config1))
+        {
+            continue;
+        }
+
+        EGLint surfaceType;
+        eglGetConfigAttrib(mDisplay, config1, EGL_SURFACE_TYPE, &surfaceType);
+        ASSERT_EGL_SUCCESS();
+
+        if ((surfaceType & EGL_PBUFFER_BIT) == 0)
+        {
+            continue;
+        }
+
+        for (size_t j = 0; j < mConfigs.size(); j++)
+        {
+            EGLConfig config2 = mConfigs[j];
+            // Disabling multisampled configurations due to test instability with various graphics
+            // cards
+            if (isMultisampledConfig(config2))
+            {
+                continue;
+            }
+            testPbufferCompatibility(config1, config2, areConfigsCompatible(config1, config2, EGL_PBUFFER_BIT));
+        }
+    }
+}
+
+ANGLE_INSTANTIATE_TEST(EGLContextCompatibilityTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLContextSharingTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLContextSharingTest.cpp
new file mode 100644
index 0000000..818cadd
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLContextSharingTest.cpp
@@ -0,0 +1,254 @@
+//
+// Copyright (c) 2016 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.
+//
+// EGLContextSharingTest.cpp:
+//   Tests relating to shared Contexts.
+
+#include <gtest/gtest.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/angle_test_configs.h"
+
+using namespace angle;
+
+namespace
+{
+
+EGLBoolean SafeDestroyContext(EGLDisplay display, EGLContext &context)
+{
+    EGLBoolean result = EGL_TRUE;
+    if (context != EGL_NO_CONTEXT)
+    {
+        result  = eglDestroyContext(display, context);
+        context = EGL_NO_CONTEXT;
+    }
+    return result;
+}
+
+class EGLContextSharingTest : public ANGLETest
+{
+  public:
+    EGLContextSharingTest() : mContexts{EGL_NO_CONTEXT, EGL_NO_CONTEXT}, mTexture(0) {}
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTexture);
+
+        EGLDisplay display = getEGLWindow()->getDisplay();
+
+        if (display != EGL_NO_DISPLAY)
+        {
+            for (auto &context : mContexts)
+            {
+                SafeDestroyContext(display, context);
+            }
+        }
+
+        ANGLETest::TearDown();
+    }
+
+    EGLContext mContexts[2];
+    GLuint mTexture;
+};
+
+// Tests that creating resources works after freeing the share context.
+TEST_P(EGLContextSharingTest, BindTextureAfterShareContextFree)
+{
+    EGLDisplay display = getEGLWindow()->getDisplay();
+    EGLConfig config   = getEGLWindow()->getConfig();
+    EGLSurface surface = getEGLWindow()->getSurface();
+
+    const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION,
+                                     getEGLWindow()->getClientMajorVersion(), EGL_NONE};
+
+    mContexts[0] = eglCreateContext(display, config, nullptr, contextAttribs);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_TRUE(mContexts[0] != EGL_NO_CONTEXT);
+    mContexts[1] = eglCreateContext(display, config, mContexts[1], contextAttribs);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_TRUE(mContexts[1] != EGL_NO_CONTEXT);
+
+    ASSERT_EGL_TRUE(SafeDestroyContext(display, mContexts[0]));
+    ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[1]));
+    ASSERT_EGL_SUCCESS();
+
+    glGenTextures(1, &mTexture);
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Tests the creation of contexts using EGL_ANGLE_display_texture_share_group
+TEST_P(EGLContextSharingTest, DisplayShareGroupContextCreation)
+{
+    EGLDisplay display = getEGLWindow()->getDisplay();
+    EGLConfig config   = getEGLWindow()->getConfig();
+
+    const EGLint inShareGroupContextAttribs[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 2, EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_TRUE, EGL_NONE};
+
+    // Test creating two contexts in the global share group
+    mContexts[0] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
+    mContexts[1] = eglCreateContext(display, config, mContexts[1], inShareGroupContextAttribs);
+
+    if (!ANGLETest::eglDisplayExtensionEnabled(display, "EGL_ANGLE_display_texture_share_group"))
+    {
+        // Make sure an error is generated and early-exit
+        ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
+        ASSERT_EQ(EGL_NO_CONTEXT, mContexts[0]);
+        return;
+    }
+
+    ASSERT_EGL_SUCCESS();
+
+    ASSERT_NE(EGL_NO_CONTEXT, mContexts[0]);
+    ASSERT_NE(EGL_NO_CONTEXT, mContexts[1]);
+    eglDestroyContext(display, mContexts[0]);
+
+    // Try creating a context that is not in the global share group but tries to share with a
+    // context that is
+    const EGLint notInShareGroupContextAttribs[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 2, EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE, EGL_NONE};
+    mContexts[1] = eglCreateContext(display, config, mContexts[1], notInShareGroupContextAttribs);
+    ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
+    ASSERT_TRUE(mContexts[1] == EGL_NO_CONTEXT);
+}
+
+// Tests the sharing of textures using EGL_ANGLE_display_texture_share_group
+TEST_P(EGLContextSharingTest, DisplayShareGroupObjectSharing)
+{
+    EGLDisplay display = getEGLWindow()->getDisplay();
+    if (!ANGLETest::eglDisplayExtensionEnabled(display, "EGL_ANGLE_display_texture_share_group"))
+    {
+        std::cout << "Test skipped because EGL_ANGLE_display_texture_share_group is not present."
+                  << std::endl;
+        return;
+    }
+
+    EGLConfig config   = getEGLWindow()->getConfig();
+    EGLSurface surface = getEGLWindow()->getSurface();
+
+    const EGLint inShareGroupContextAttribs[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 2, EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_TRUE, EGL_NONE};
+
+    // Create two contexts in the global share group but not in the same context share group
+    mContexts[0] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
+    mContexts[1] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
+
+    ASSERT_EGL_SUCCESS();
+
+    ASSERT_NE(EGL_NO_CONTEXT, mContexts[0]);
+    ASSERT_NE(EGL_NO_CONTEXT, mContexts[1]);
+
+    ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[0]));
+    ASSERT_EGL_SUCCESS();
+
+    // Create a texture and buffer in ctx 0
+    GLuint textureFromCtx0 = 0;
+    glGenTextures(1, &textureFromCtx0);
+    glBindTexture(GL_TEXTURE_2D, textureFromCtx0);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    ASSERT_GL_TRUE(glIsTexture(textureFromCtx0));
+
+    GLuint bufferFromCtx0 = 0;
+    glGenBuffers(1, &bufferFromCtx0);
+    glBindBuffer(GL_ARRAY_BUFFER, bufferFromCtx0);
+    glBufferData(GL_ARRAY_BUFFER, 1, nullptr, GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    ASSERT_GL_TRUE(glIsBuffer(bufferFromCtx0));
+
+    ASSERT_GL_NO_ERROR();
+
+    // Switch to context 1 and verify that the texture is accessible but the buffer is not
+    ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[1]));
+    ASSERT_EGL_SUCCESS();
+
+    ASSERT_GL_TRUE(glIsTexture(textureFromCtx0));
+
+    ASSERT_GL_FALSE(glIsBuffer(bufferFromCtx0));
+    glDeleteBuffers(1, &bufferFromCtx0);
+    ASSERT_GL_NO_ERROR();
+
+    // Call readpixels on the texture to verify that the backend has proper support
+    GLuint fbo = 0;
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureFromCtx0, 0);
+
+    GLubyte pixel[4];
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteFramebuffers(1, &fbo);
+
+    glDeleteTextures(1, &textureFromCtx0);
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GL_FALSE(glIsTexture(textureFromCtx0));
+
+    // Switch back to context 0 and delete the buffer
+    ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[0]));
+    ASSERT_EGL_SUCCESS();
+
+    ASSERT_GL_TRUE(glIsBuffer(bufferFromCtx0));
+    glDeleteBuffers(1, &bufferFromCtx0);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Tests that shared textures using EGL_ANGLE_display_texture_share_group are released when the last
+// context is destroyed
+TEST_P(EGLContextSharingTest, DisplayShareGroupReleasedWithLastContext)
+{
+    EGLDisplay display = getEGLWindow()->getDisplay();
+    if (!ANGLETest::eglDisplayExtensionEnabled(display, "EGL_ANGLE_display_texture_share_group"))
+    {
+        std::cout << "Test skipped because EGL_ANGLE_display_texture_share_group is not present."
+                  << std::endl;
+        return;
+    }
+
+    EGLConfig config   = getEGLWindow()->getConfig();
+    EGLSurface surface = getEGLWindow()->getSurface();
+
+    const EGLint inShareGroupContextAttribs[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 2, EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_TRUE, EGL_NONE};
+
+    // Create two contexts in the global share group but not in the same context share group
+    mContexts[0] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
+    mContexts[1] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
+
+    // Create a texture and buffer in ctx 0
+    ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[0]));
+    GLuint textureFromCtx0 = 0;
+    glGenTextures(1, &textureFromCtx0);
+    glBindTexture(GL_TEXTURE_2D, textureFromCtx0);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    ASSERT_GL_TRUE(glIsTexture(textureFromCtx0));
+
+    // Switch to context 1 and verify that the texture is accessible
+    ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[1]));
+    ASSERT_GL_TRUE(glIsTexture(textureFromCtx0));
+
+    // Destroy both contexts, the texture should be cleaned up automatically
+    ASSERT_EGL_TRUE(eglDestroyContext(display, mContexts[0]));
+    ASSERT_EGL_TRUE(eglDestroyContext(display, mContexts[1]));
+
+    // Create a new context and verify it cannot access the texture previously created
+    mContexts[0] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
+
+    ASSERT_GL_FALSE(glIsTexture(textureFromCtx0));
+}
+
+}  // anonymous namespace
+
+ANGLE_INSTANTIATE_TEST(EGLContextSharingTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL());
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLDeviceTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLDeviceTest.cpp
new file mode 100644
index 0000000..9cd96d1
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLDeviceTest.cpp
@@ -0,0 +1,587 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef ANGLE_ENABLE_D3D9
+#define ANGLE_ENABLE_D3D9
+#endif
+
+#ifndef ANGLE_ENABLE_D3D11
+#define ANGLE_ENABLE_D3D11
+#endif
+
+#include <d3d11.h>
+
+#include "com_utils.h"
+#include "OSWindow.h"
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class EGLDeviceCreationTest : public testing::Test
+{
+  protected:
+    EGLDeviceCreationTest()
+        : mD3D11Available(false),
+          mD3D11Module(nullptr),
+          mD3D11CreateDevice(nullptr),
+          mDevice(nullptr),
+          mDeviceContext(nullptr),
+          mDeviceCreationD3D11ExtAvailable(false),
+          mOSWindow(nullptr),
+          mDisplay(EGL_NO_DISPLAY),
+          mSurface(EGL_NO_SURFACE),
+          mContext(EGL_NO_CONTEXT),
+          mConfig(0)
+    {
+    }
+
+    void SetUp() override
+    {
+        mD3D11Module = LoadLibrary(TEXT("d3d11.dll"));
+        if (mD3D11Module == nullptr)
+        {
+            std::cout << "Unable to LoadLibrary D3D11" << std::endl;
+            return;
+        }
+
+        mD3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+            GetProcAddress(mD3D11Module, "D3D11CreateDevice"));
+        if (mD3D11CreateDevice == nullptr)
+        {
+            std::cout << "Could not retrieve D3D11CreateDevice from d3d11.dll" << std::endl;
+            return;
+        }
+
+        mD3D11Available = true;
+
+        const char *extensionString =
+            static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
+        if (strstr(extensionString, "EGL_ANGLE_device_creation"))
+        {
+            if (strstr(extensionString, "EGL_ANGLE_device_creation_d3d11"))
+            {
+                mDeviceCreationD3D11ExtAvailable = true;
+            }
+        }
+    }
+
+    void TearDown() override
+    {
+        SafeRelease(mDevice);
+        SafeRelease(mDeviceContext);
+
+        SafeDelete(mOSWindow);
+
+        if (mSurface != EGL_NO_SURFACE)
+        {
+            eglDestroySurface(mDisplay, mSurface);
+            mSurface = EGL_NO_SURFACE;
+        }
+
+        if (mContext != EGL_NO_CONTEXT)
+        {
+            eglDestroyContext(mDisplay, mContext);
+            mContext = EGL_NO_CONTEXT;
+        }
+
+        if (mDisplay != EGL_NO_DISPLAY)
+        {
+            eglTerminate(mDisplay);
+            mDisplay = EGL_NO_DISPLAY;
+        }
+    }
+
+    void CreateD3D11Device()
+    {
+        ASSERT_TRUE(mD3D11Available);
+        ASSERT_EQ(nullptr, mDevice);  // The device shouldn't be created twice
+
+        HRESULT hr =
+            mD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, 0, nullptr, 0,
+                               D3D11_SDK_VERSION, &mDevice, &mFeatureLevel, &mDeviceContext);
+
+        ASSERT_TRUE(SUCCEEDED(hr));
+        ASSERT_GE(mFeatureLevel, D3D_FEATURE_LEVEL_9_3);
+    }
+
+    void CreateD3D11FL9_3Device()
+    {
+        ASSERT_TRUE(mD3D11Available);
+        ASSERT_EQ(nullptr, mDevice);
+
+        D3D_FEATURE_LEVEL fl93 = D3D_FEATURE_LEVEL_9_3;
+
+        HRESULT hr =
+            mD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, 0, &fl93, 1, D3D11_SDK_VERSION,
+                               &mDevice, &mFeatureLevel, &mDeviceContext);
+
+        ASSERT_TRUE(SUCCEEDED(hr));
+    }
+
+    void CreateWindowSurface()
+    {
+        EGLint majorVersion, minorVersion;
+        ASSERT_EGL_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion));
+
+        eglBindAPI(EGL_OPENGL_ES_API);
+        ASSERT_EGL_SUCCESS();
+
+        // Choose a config
+        const EGLint configAttributes[] = {EGL_NONE};
+        EGLint configCount = 0;
+        ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, configAttributes, &mConfig, 1, &configCount));
+
+        // Create an OS Window
+        mOSWindow = CreateOSWindow();
+        mOSWindow->initialize("EGLSurfaceTest", 64, 64);
+
+        // Create window surface
+        mSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), nullptr);
+        ASSERT_EGL_SUCCESS();
+
+        // Create EGL context
+        EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+        mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
+        ASSERT_EGL_SUCCESS();
+
+        // Make the surface current
+        eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
+        ASSERT_EGL_SUCCESS();
+    }
+
+    // This triggers a D3D device lost on current Windows systems
+    // This behavior could potentially change in the future
+    void trigger9_3DeviceLost()
+    {
+        ID3D11Buffer *gsBuffer       = nullptr;
+        D3D11_BUFFER_DESC bufferDesc = {0};
+        bufferDesc.ByteWidth         = 64;
+        bufferDesc.Usage             = D3D11_USAGE_DEFAULT;
+        bufferDesc.BindFlags         = D3D11_BIND_CONSTANT_BUFFER;
+
+        HRESULT result = mDevice->CreateBuffer(&bufferDesc, nullptr, &gsBuffer);
+        ASSERT_TRUE(SUCCEEDED(result));
+
+        mDeviceContext->GSSetConstantBuffers(0, 1, &gsBuffer);
+        SafeRelease(gsBuffer);
+        gsBuffer = nullptr;
+
+        result = mDevice->GetDeviceRemovedReason();
+        ASSERT_TRUE(FAILED(result));
+    }
+
+    bool mD3D11Available;
+    HMODULE mD3D11Module;
+    PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice;
+
+    ID3D11Device *mDevice;
+    ID3D11DeviceContext *mDeviceContext;
+    D3D_FEATURE_LEVEL mFeatureLevel;
+
+    bool mDeviceCreationD3D11ExtAvailable;
+
+    OSWindow *mOSWindow;
+
+    EGLDisplay mDisplay;
+    EGLSurface mSurface;
+    EGLContext mContext;
+    EGLConfig mConfig;
+};
+
+// Test that creating a EGLDeviceEXT from D3D11 device works, and it can be queried to retrieve
+// D3D11 device
+TEST_F(EGLDeviceCreationTest, BasicD3D11Device)
+{
+    if (!mDeviceCreationD3D11ExtAvailable || !mD3D11Available)
+    {
+        std::cout << "EGLDevice creation and/or D3D11 not available, skipping test" << std::endl;
+        return;
+    }
+
+    CreateD3D11Device();
+
+    EGLDeviceEXT eglDevice =
+        eglCreateDeviceANGLE(EGL_D3D11_DEVICE_ANGLE, reinterpret_cast<void *>(mDevice), nullptr);
+    ASSERT_NE(EGL_NO_DEVICE_EXT, eglDevice);
+    ASSERT_EGL_SUCCESS();
+
+    EGLAttrib deviceAttrib;
+    eglQueryDeviceAttribEXT(eglDevice, EGL_D3D11_DEVICE_ANGLE, &deviceAttrib);
+    ASSERT_EGL_SUCCESS();
+
+    ID3D11Device *queriedDevice = reinterpret_cast<ID3D11Device *>(deviceAttrib);
+    ASSERT_EQ(mFeatureLevel, queriedDevice->GetFeatureLevel());
+
+    eglReleaseDeviceANGLE(eglDevice);
+}
+
+// Test that creating a EGLDeviceEXT from D3D11 device works, and it can be queried to retrieve
+// D3D11 device
+TEST_F(EGLDeviceCreationTest, BasicD3D11DeviceViaFuncPointer)
+{
+    if (!mDeviceCreationD3D11ExtAvailable || !mD3D11Available)
+    {
+        std::cout << "EGLDevice creation and/or D3D11 not available, skipping test" << std::endl;
+        return;
+    }
+
+    CreateD3D11Device();
+
+    PFNEGLCREATEDEVICEANGLEPROC createDeviceANGLE =
+        (PFNEGLCREATEDEVICEANGLEPROC)eglGetProcAddress("eglCreateDeviceANGLE");
+    PFNEGLRELEASEDEVICEANGLEPROC releaseDeviceANGLE =
+        (PFNEGLRELEASEDEVICEANGLEPROC)eglGetProcAddress("eglReleaseDeviceANGLE");
+
+    EGLDeviceEXT eglDevice =
+        createDeviceANGLE(EGL_D3D11_DEVICE_ANGLE, reinterpret_cast<void *>(mDevice), nullptr);
+    ASSERT_NE(EGL_NO_DEVICE_EXT, eglDevice);
+    ASSERT_EGL_SUCCESS();
+
+    EGLAttrib deviceAttrib;
+    eglQueryDeviceAttribEXT(eglDevice, EGL_D3D11_DEVICE_ANGLE, &deviceAttrib);
+    ASSERT_EGL_SUCCESS();
+
+    ID3D11Device *queriedDevice = reinterpret_cast<ID3D11Device *>(deviceAttrib);
+    ASSERT_EQ(mFeatureLevel, queriedDevice->GetFeatureLevel());
+
+    releaseDeviceANGLE(eglDevice);
+}
+
+// Test that creating a EGLDeviceEXT from D3D11 device works, and can be used for rendering
+TEST_F(EGLDeviceCreationTest, RenderingUsingD3D11Device)
+{
+    if (!mD3D11Available)
+    {
+        std::cout << "D3D11 not available, skipping test" << std::endl;
+        return;
+    }
+
+    CreateD3D11Device();
+
+    EGLDeviceEXT eglDevice =
+        eglCreateDeviceANGLE(EGL_D3D11_DEVICE_ANGLE, reinterpret_cast<void *>(mDevice), nullptr);
+    ASSERT_EGL_SUCCESS();
+
+    // Create an EGLDisplay using the EGLDevice
+    mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr);
+    ASSERT_NE(EGL_NO_DISPLAY, mDisplay);
+
+    // Create a surface using the display
+    CreateWindowSurface();
+
+    // Perform some very basic rendering
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(32, 32, 255, 0, 255, 255);
+
+    // Note that we must call TearDown() before we release the EGL device, since the display
+    // depends on the device
+    TearDown();
+
+    eglReleaseDeviceANGLE(eglDevice);
+}
+
+// Test that ANGLE doesn't try to recreate a D3D11 device if the inputted one is lost
+TEST_F(EGLDeviceCreationTest, D3D11DeviceRecovery)
+{
+    if (!mD3D11Available)
+    {
+        std::cout << "D3D11 not available, skipping test" << std::endl;
+        return;
+    }
+
+    // Force Feature Level 9_3 so we can easily trigger a device lost later
+    CreateD3D11FL9_3Device();
+
+    EGLDeviceEXT eglDevice =
+        eglCreateDeviceANGLE(EGL_D3D11_DEVICE_ANGLE, reinterpret_cast<void *>(mDevice), nullptr);
+    ASSERT_EGL_SUCCESS();
+
+    // Create an EGLDisplay using the EGLDevice
+    mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr);
+    ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
+
+    // Create a surface using the display
+    CreateWindowSurface();
+
+    // Perform some very basic rendering
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(32, 32, 255, 0, 255, 255);
+    ASSERT_GL_NO_ERROR();
+
+    // ANGLE's SwapChain11::initPassThroughResources doesn't handle device lost before
+    // eglSwapBuffers, so we must call eglSwapBuffers before we lose the device.
+    ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mSurface));
+
+    // Trigger a lost device
+    trigger9_3DeviceLost();
+
+    // Destroy the old EGL Window Surface
+    if (mSurface != EGL_NO_SURFACE)
+    {
+        eglDestroySurface(mDisplay, mSurface);
+        mSurface = EGL_NO_SURFACE;
+    }
+
+    // Try to create a new window surface. In certain configurations this will recreate the D3D11
+    // device. We want to test that it doesn't recreate the D3D11 device when EGLDeviceEXT is
+    // used. The window surface creation should fail if a new D3D11 device isn't created.
+    mSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), nullptr);
+    ASSERT_EQ(EGL_NO_SURFACE, mSurface);
+    ASSERT_EGL_ERROR(EGL_BAD_ALLOC);
+
+    // Get the D3D11 device out of the EGLDisplay again. It should be the same one as above.
+    EGLAttrib device       = 0;
+    EGLAttrib newEglDevice = 0;
+    ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice));
+    ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(newEglDevice),
+                                                EGL_D3D11_DEVICE_ANGLE, &device));
+    ID3D11Device *newDevice = reinterpret_cast<ID3D11Device *>(device);
+
+    ASSERT_EQ(reinterpret_cast<EGLDeviceEXT>(newEglDevice), eglDevice);
+    ASSERT_EQ(newDevice, mDevice);
+
+    // Note that we must call TearDown() before we release the EGL device, since the display
+    // depends on the device
+    TearDown();
+
+    eglReleaseDeviceANGLE(eglDevice);
+}
+
+// Test that calling eglGetPlatformDisplayEXT with the same device returns the same display
+TEST_F(EGLDeviceCreationTest, getPlatformDisplayTwice)
+{
+    if (!mD3D11Available)
+    {
+        std::cout << "D3D11 not available, skipping test" << std::endl;
+        return;
+    }
+
+    CreateD3D11Device();
+
+    EGLDeviceEXT eglDevice =
+        eglCreateDeviceANGLE(EGL_D3D11_DEVICE_ANGLE, reinterpret_cast<void *>(mDevice), nullptr);
+    ASSERT_EGL_SUCCESS();
+
+    // Create an EGLDisplay using the EGLDevice
+    EGLDisplay display1 = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr);
+    ASSERT_NE(EGL_NO_DISPLAY, display1);
+
+    EGLDisplay display2 = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr);
+    ASSERT_NE(EGL_NO_DISPLAY, display2);
+
+    ASSERT_EQ(display1, display2);
+
+    eglTerminate(display1);
+    eglReleaseDeviceANGLE(eglDevice);
+}
+
+// Test that creating a EGLDeviceEXT from an invalid D3D11 device fails
+TEST_F(EGLDeviceCreationTest, InvalidD3D11Device)
+{
+    if (!mDeviceCreationD3D11ExtAvailable || !mD3D11Available)
+    {
+        std::cout << "EGLDevice creation and/or D3D11 not available, skipping test" << std::endl;
+        return;
+    }
+
+    CreateD3D11Device();
+
+    // Use mDeviceContext instead of mDevice
+    EGLDeviceEXT eglDevice = eglCreateDeviceANGLE(
+        EGL_D3D11_DEVICE_ANGLE, reinterpret_cast<void *>(mDeviceContext), nullptr);
+    EXPECT_EQ(EGL_NO_DEVICE_EXT, eglDevice);
+    EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
+}
+
+// Test that EGLDeviceEXT holds a ref to the D3D11 device
+TEST_F(EGLDeviceCreationTest, D3D11DeviceReferenceCounting)
+{
+    if (!mDeviceCreationD3D11ExtAvailable || !mD3D11Available)
+    {
+        std::cout << "EGLDevice creation and/or D3D11 not available, skipping test" << std::endl;
+        return;
+    }
+
+    CreateD3D11Device();
+
+    EGLDeviceEXT eglDevice =
+        eglCreateDeviceANGLE(EGL_D3D11_DEVICE_ANGLE, reinterpret_cast<void *>(mDevice), nullptr);
+    ASSERT_NE(EGL_NO_DEVICE_EXT, eglDevice);
+    ASSERT_EGL_SUCCESS();
+
+    // Now release our D3D11 device/context
+    SafeRelease(mDevice);
+    SafeRelease(mDeviceContext);
+
+    EGLAttrib deviceAttrib;
+    eglQueryDeviceAttribEXT(eglDevice, EGL_D3D11_DEVICE_ANGLE, &deviceAttrib);
+    ASSERT_EGL_SUCCESS();
+
+    ID3D11Device *queriedDevice = reinterpret_cast<ID3D11Device *>(deviceAttrib);
+    ASSERT_EQ(mFeatureLevel, queriedDevice->GetFeatureLevel());
+
+    eglReleaseDeviceANGLE(eglDevice);
+}
+
+// Test that creating a EGLDeviceEXT from a D3D9 device fails
+TEST_F(EGLDeviceCreationTest, AnyD3D9Device)
+{
+    if (!mDeviceCreationD3D11ExtAvailable)
+    {
+        std::cout << "EGLDevice creation not available, skipping test" << std::endl;
+        return;
+    }
+
+    std::string fakeD3DDevice = "This is a string, not a D3D device";
+
+    EGLDeviceEXT eglDevice = eglCreateDeviceANGLE(
+        EGL_D3D9_DEVICE_ANGLE, reinterpret_cast<void *>(&fakeD3DDevice), nullptr);
+    EXPECT_EQ(EGL_NO_DEVICE_EXT, eglDevice);
+    EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
+}
+
+class EGLDeviceQueryTest : public ANGLETest
+{
+  protected:
+    EGLDeviceQueryTest()
+    {
+        mQueryDisplayAttribEXT = nullptr;
+        mQueryDeviceAttribEXT  = nullptr;
+        mQueryDeviceStringEXT  = nullptr;
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const char *extensionString =
+            static_cast<const char *>(eglQueryString(getEGLWindow()->getDisplay(), EGL_EXTENSIONS));
+        if (strstr(extensionString, "EGL_EXT_device_query"))
+        {
+            mQueryDisplayAttribEXT =
+                (PFNEGLQUERYDISPLAYATTRIBEXTPROC)eglGetProcAddress("eglQueryDisplayAttribEXT");
+            mQueryDeviceAttribEXT =
+                (PFNEGLQUERYDEVICEATTRIBEXTPROC)eglGetProcAddress("eglQueryDeviceAttribEXT");
+            mQueryDeviceStringEXT =
+                (PFNEGLQUERYDEVICESTRINGEXTPROC)eglGetProcAddress("eglQueryDeviceStringEXT");
+        }
+
+        if (!mQueryDeviceStringEXT)
+        {
+            FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDeviceStringEXT was not "
+                      "found";
+        }
+
+        if (!mQueryDisplayAttribEXT)
+        {
+            FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDisplayAttribEXT was "
+                      "not found";
+        }
+
+        if (!mQueryDeviceAttribEXT)
+        {
+            FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDeviceAttribEXT was not "
+                      "found";
+        }
+
+        EGLAttrib angleDevice = 0;
+        EXPECT_EGL_TRUE(
+            mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
+        extensionString = static_cast<const char *>(
+            mQueryDeviceStringEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_EXTENSIONS));
+        if (strstr(extensionString, "EGL_ANGLE_device_d3d") == nullptr)
+        {
+            FAIL() << "ANGLE extension EGL_ANGLE_device_d3d was not found";
+        }
+    }
+
+    void TearDown() override { ANGLETest::TearDown(); }
+
+    PFNEGLQUERYDISPLAYATTRIBEXTPROC mQueryDisplayAttribEXT;
+    PFNEGLQUERYDEVICEATTRIBEXTPROC mQueryDeviceAttribEXT;
+    PFNEGLQUERYDEVICESTRINGEXTPROC mQueryDeviceStringEXT;
+};
+
+// This test attempts to obtain a D3D11 device and a D3D9 device using the eglQueryDeviceAttribEXT
+// function.
+// If the test is configured to use D3D11 then it should succeed to obtain a D3D11 device.
+// If the test is confitured to use D3D9, then it should succeed to obtain a D3D9 device.
+TEST_P(EGLDeviceQueryTest, QueryDevice)
+{
+    EGLAttrib device      = 0;
+    EGLAttrib angleDevice = 0;
+    if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        EXPECT_EGL_TRUE(
+            mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
+        EXPECT_EGL_TRUE(mQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
+                                              EGL_D3D11_DEVICE_ANGLE, &device));
+        ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);
+        IDXGIDevice *dxgiDevice = DynamicCastComObject<IDXGIDevice>(d3d11Device);
+        EXPECT_TRUE(dxgiDevice != nullptr);
+        SafeRelease(dxgiDevice);
+    }
+
+    if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
+    {
+        EXPECT_EGL_TRUE(
+            mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
+        EXPECT_EGL_TRUE(mQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
+                                              EGL_D3D9_DEVICE_ANGLE, &device));
+        IDirect3DDevice9 *d3d9Device = reinterpret_cast<IDirect3DDevice9 *>(device);
+        IDirect3D9 *d3d9 = nullptr;
+        EXPECT_EQ(S_OK, d3d9Device->GetDirect3D(&d3d9));
+        EXPECT_TRUE(d3d9 != nullptr);
+        SafeRelease(d3d9);
+    }
+}
+
+// This test attempts to obtain a D3D11 device from a D3D9 configured system and a D3D9 device from
+// a D3D11 configured system using the eglQueryDeviceAttribEXT function.
+// If the test is configured to use D3D11 then it should fail to obtain a D3D11 device.
+// If the test is confitured to use D3D9, then it should fail to obtain a D3D9 device.
+TEST_P(EGLDeviceQueryTest, QueryDeviceBadAttribute)
+{
+    EGLAttrib device      = 0;
+    EGLAttrib angleDevice = 0;
+    if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        EXPECT_EGL_TRUE(
+            mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
+        EXPECT_EGL_FALSE(mQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
+                                               EGL_D3D9_DEVICE_ANGLE, &device));
+    }
+
+    if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
+    {
+        EXPECT_EGL_TRUE(
+            mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
+        EXPECT_EGL_FALSE(mQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
+                                               EGL_D3D11_DEVICE_ANGLE, &device));
+    }
+}
+
+// Ensure that:
+//    - calling getPlatformDisplayEXT using ANGLE_Platform with some parameters
+//    - extracting the EGLDeviceEXT from the EGLDisplay
+//    - calling getPlatformDisplayEXT with this EGLDeviceEXT
+// results in the same EGLDisplay being returned from getPlatformDisplayEXT both times
+TEST_P(EGLDeviceQueryTest, getPlatformDisplayDeviceReuse)
+{
+    EGLAttrib eglDevice = 0;
+    EXPECT_EGL_TRUE(
+              eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &eglDevice));
+
+    EGLDisplay display2 = eglGetPlatformDisplayEXT(
+        EGL_PLATFORM_DEVICE_EXT, reinterpret_cast<EGLDeviceEXT>(eglDevice), nullptr);
+    EXPECT_EQ(getEGLWindow()->getDisplay(), display2);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(EGLDeviceQueryTest, ES2_D3D9(), ES2_D3D11());
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp b/src/third_party/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp
new file mode 100644
index 0000000..1b8383b
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp
@@ -0,0 +1,378 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include <cstdint>
+#include "com_utils.h"
+#include "OSWindow.h"
+#include <d3d11.h>
+
+using namespace angle;
+
+class EGLPresentPathD3D11 : public testing::TestWithParam<PlatformParameters>
+{
+  protected:
+    EGLPresentPathD3D11()
+        : mDisplay(EGL_NO_DISPLAY),
+          mContext(EGL_NO_CONTEXT),
+          mSurface(EGL_NO_SURFACE),
+          mOffscreenSurfaceD3D11Texture(nullptr),
+          mConfig(0),
+          mOSWindow(nullptr),
+          mWindowWidth(0)
+    {
+    }
+
+    void SetUp() override
+    {
+        mOSWindow    = CreateOSWindow();
+        mWindowWidth = 64;
+        mOSWindow->initialize("EGLPresentPathD3D11", mWindowWidth, mWindowWidth);
+    }
+
+    void initializeEGL(bool usePresentPathFast)
+    {
+        int clientVersion = GetParam().majorVersion;
+
+        const char *extensionString =
+            static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
+        ASSERT_NE(nullptr, strstr(extensionString, "EGL_ANGLE_experimental_present_path"));
+
+        PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
+            reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
+                eglGetProcAddress("eglGetPlatformDisplayEXT"));
+        ASSERT_NE(nullptr, eglGetPlatformDisplayEXT);
+
+        // Set up EGL Display
+        EGLint displayAttribs[] = {
+            EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(),
+            EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, GetParam().eglParameters.majorVersion,
+            EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, GetParam().eglParameters.majorVersion,
+            EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
+            usePresentPathFast ? EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE
+                               : EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE,
+            EGL_NONE};
+        mDisplay =
+            eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttribs);
+        ASSERT_TRUE(EGL_NO_DISPLAY != mDisplay);
+        ASSERT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));
+
+        // Choose the EGL config
+        EGLint numConfigs;
+        EGLint configAttribs[] = {EGL_RED_SIZE,
+                                  8,
+                                  EGL_GREEN_SIZE,
+                                  8,
+                                  EGL_BLUE_SIZE,
+                                  8,
+                                  EGL_ALPHA_SIZE,
+                                  8,
+                                  EGL_RENDERABLE_TYPE,
+                                  clientVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT,
+                                  EGL_SURFACE_TYPE,
+                                  EGL_PBUFFER_BIT,
+                                  EGL_NONE};
+        ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, configAttribs, &mConfig, 1, &numConfigs));
+        ASSERT_EQ(1, numConfigs);
+
+        // Set up the EGL context
+        EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, clientVersion, EGL_NONE};
+        mContext                = eglCreateContext(mDisplay, mConfig, nullptr, contextAttribs);
+        ASSERT_TRUE(EGL_NO_CONTEXT != mContext);
+    }
+
+    void createWindowSurface()
+    {
+        mSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), nullptr);
+    }
+
+    void createPbufferFromClientBufferSurface()
+    {
+        EGLAttrib device      = 0;
+        EGLAttrib angleDevice = 0;
+
+        PFNEGLQUERYDISPLAYATTRIBEXTPROC queryDisplayAttribEXT;
+        PFNEGLQUERYDEVICEATTRIBEXTPROC queryDeviceAttribEXT;
+
+        const char *extensionString =
+            static_cast<const char *>(eglQueryString(mDisplay, EGL_EXTENSIONS));
+        EXPECT_TRUE(strstr(extensionString, "EGL_EXT_device_query"));
+
+        queryDisplayAttribEXT =
+            (PFNEGLQUERYDISPLAYATTRIBEXTPROC)eglGetProcAddress("eglQueryDisplayAttribEXT");
+        queryDeviceAttribEXT =
+            (PFNEGLQUERYDEVICEATTRIBEXTPROC)eglGetProcAddress("eglQueryDeviceAttribEXT");
+        ASSERT_NE(nullptr, queryDisplayAttribEXT);
+        ASSERT_NE(nullptr, queryDeviceAttribEXT);
+
+        ASSERT_EGL_TRUE(queryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &angleDevice));
+        ASSERT_EGL_TRUE(queryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
+                                             EGL_D3D11_DEVICE_ANGLE, &device));
+        ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);
+
+        D3D11_TEXTURE2D_DESC textureDesc = {0};
+        textureDesc.Width                = mWindowWidth;
+        textureDesc.Height               = mWindowWidth;
+        textureDesc.Format               = DXGI_FORMAT_B8G8R8A8_UNORM;
+        textureDesc.MipLevels            = 1;
+        textureDesc.ArraySize            = 1;
+        textureDesc.SampleDesc.Count     = 1;
+        textureDesc.SampleDesc.Quality   = 0;
+        textureDesc.Usage                = D3D11_USAGE_DEFAULT;
+        textureDesc.BindFlags            = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+        textureDesc.CPUAccessFlags       = 0;
+        textureDesc.MiscFlags            = D3D11_RESOURCE_MISC_SHARED;
+
+        ASSERT_TRUE(SUCCEEDED(
+            d3d11Device->CreateTexture2D(&textureDesc, nullptr, &mOffscreenSurfaceD3D11Texture)));
+
+        IDXGIResource *dxgiResource =
+            DynamicCastComObject<IDXGIResource>(mOffscreenSurfaceD3D11Texture);
+        ASSERT_NE(nullptr, dxgiResource);
+
+        HANDLE sharedHandle = 0;
+        ASSERT_TRUE(SUCCEEDED(dxgiResource->GetSharedHandle(&sharedHandle)));
+        SafeRelease(dxgiResource);
+
+        EGLint pBufferAttributes[] = {EGL_WIDTH,          mWindowWidth,       EGL_HEIGHT,
+                                      mWindowWidth,       EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
+                                      EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,   EGL_NONE};
+
+        mSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
+                                                    sharedHandle, mConfig, pBufferAttributes);
+        ASSERT_TRUE(EGL_NO_SURFACE != mSurface);
+    }
+
+    void makeCurrent() { ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, mSurface, mSurface, mContext)); }
+
+    void TearDown() override
+    {
+        SafeRelease(mOffscreenSurfaceD3D11Texture);
+
+        if (mDisplay != EGL_NO_DISPLAY)
+        {
+            eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+            if (mSurface != EGL_NO_SURFACE)
+            {
+                eglDestroySurface(mDisplay, mSurface);
+                mSurface = EGL_NO_SURFACE;
+            }
+
+            if (mContext != EGL_NO_CONTEXT)
+            {
+                eglDestroyContext(mDisplay, mContext);
+                mContext = EGL_NO_CONTEXT;
+            }
+
+            eglTerminate(mDisplay);
+            mDisplay = EGL_NO_DISPLAY;
+        }
+
+        mOSWindow->destroy();
+        SafeDelete(mOSWindow);
+    }
+
+    void drawQuadUsingGL()
+    {
+        GLuint m2DProgram;
+        GLint mTexture2DUniformLocation;
+
+        const std::string vertexShaderSource =
+            SHADER_SOURCE(precision highp float; attribute vec4 position; varying vec2 texcoord;
+
+                          void main()
+                          {
+                              gl_Position = vec4(position.xy, 0.0, 1.0);
+                              texcoord = (position.xy * 0.5) + 0.5;
+                          });
+
+        const std::string fragmentShaderSource2D =
+            SHADER_SOURCE(precision highp float; uniform sampler2D tex; varying vec2 texcoord;
+
+                          void main()
+                          {
+                              gl_FragColor = texture2D(tex, texcoord);
+                          });
+
+        m2DProgram                = CompileProgram(vertexShaderSource, fragmentShaderSource2D);
+        mTexture2DUniformLocation = glGetUniformLocation(m2DProgram, "tex");
+
+        uint8_t textureInitData[16] = {
+            255, 0,   0,   255,  // Red
+            0,   255, 0,   255,  // Green
+            0,   0,   255, 255,  // Blue
+            255, 255, 0,   255   // Red + Green
+        };
+
+        // Create a simple RGBA texture
+        GLuint tex = 0;
+        glGenTextures(1, &tex);
+        glBindTexture(GL_TEXTURE_2D, tex);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     textureInitData);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        ASSERT_GL_NO_ERROR();
+
+        // Draw a quad using the texture
+        glClear(GL_COLOR_BUFFER_BIT);
+        glUseProgram(m2DProgram);
+        glUniform1i(mTexture2DUniformLocation, 0);
+
+        GLint positionLocation = glGetAttribLocation(m2DProgram, "position");
+        glUseProgram(m2DProgram);
+        const GLfloat vertices[] =
+        {
+            -1.0f,  1.0f, 0.5f,
+            -1.0f, -1.0f, 0.5f,
+             1.0f, -1.0f, 0.5f,
+            -1.0f,  1.0f, 0.5f,
+             1.0f, -1.0f, 0.5f,
+             1.0f,  1.0f, 0.5f,
+        };
+
+        glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
+        glEnableVertexAttribArray(positionLocation);
+
+        glDrawArrays(GL_TRIANGLES, 0, 6);
+        ASSERT_GL_NO_ERROR();
+
+        glDeleteProgram(m2DProgram);
+    }
+
+    void checkPixelsUsingGL()
+    {
+        // Note that the texture is in BGRA format
+        EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);                                  // Red
+        EXPECT_PIXEL_EQ(mWindowWidth - 1, 0, 0, 255, 0, 255);                   // Green
+        EXPECT_PIXEL_EQ(0, mWindowWidth - 1, 0, 0, 255, 255);                   // Blue
+        EXPECT_PIXEL_EQ(mWindowWidth - 1, mWindowWidth - 1, 255, 255, 0, 255);  // Red + green
+    }
+
+    void checkPixelsUsingD3D(bool usingPresentPathFast)
+    {
+        ASSERT_NE(nullptr, mOffscreenSurfaceD3D11Texture);
+
+        D3D11_TEXTURE2D_DESC textureDesc = {0};
+        ID3D11Device *device;
+        ID3D11DeviceContext *context;
+        mOffscreenSurfaceD3D11Texture->GetDesc(&textureDesc);
+        mOffscreenSurfaceD3D11Texture->GetDevice(&device);
+        device->GetImmediateContext(&context);
+        ASSERT_NE(nullptr, device);
+        ASSERT_NE(nullptr, context);
+
+        textureDesc.CPUAccessFlags  = D3D11_CPU_ACCESS_READ;
+        textureDesc.Usage           = D3D11_USAGE_STAGING;
+        textureDesc.BindFlags       = 0;
+        textureDesc.MiscFlags       = 0;
+        ID3D11Texture2D *cpuTexture = nullptr;
+        ASSERT_TRUE(SUCCEEDED(device->CreateTexture2D(&textureDesc, nullptr, &cpuTexture)));
+
+        context->CopyResource(cpuTexture, mOffscreenSurfaceD3D11Texture);
+
+        D3D11_MAPPED_SUBRESOURCE mappedSubresource;
+        context->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mappedSubresource);
+        ASSERT_EQ(static_cast<UINT>(mWindowWidth * 4), mappedSubresource.RowPitch);
+        ASSERT_EQ(static_cast<UINT>(mWindowWidth * mWindowWidth * 4), mappedSubresource.DepthPitch);
+
+        angle::GLColor *byteData = reinterpret_cast<angle::GLColor *>(mappedSubresource.pData);
+
+        // Note that the texture is in BGRA format, although the GLColor struct is RGBA
+        GLColor expectedTopLeftPixel     = GLColor(0,   0, 255, 255);  // Red
+        GLColor expectedTopRightPixel    = GLColor(0, 255,   0, 255);  // Green
+        GLColor expectedBottomLeftPixel  = GLColor(255, 0,   0, 255);  // Blue
+        GLColor expectedBottomRightPixel = GLColor(0, 255, 255, 255);  // Red + Green
+
+        if (usingPresentPathFast)
+        {
+            // Invert the expected values
+            GLColor tempTopLeft      = expectedTopLeftPixel;
+            GLColor tempTopRight     = expectedTopRightPixel;
+            expectedTopLeftPixel     = expectedBottomLeftPixel;
+            expectedTopRightPixel    = expectedBottomRightPixel;
+            expectedBottomLeftPixel  = tempTopLeft;
+            expectedBottomRightPixel = tempTopRight;
+        }
+
+        EXPECT_EQ(expectedTopLeftPixel, byteData[0]);
+        EXPECT_EQ(expectedTopRightPixel, byteData[(mWindowWidth - 1)]);
+        EXPECT_EQ(expectedBottomLeftPixel, byteData[(mWindowWidth - 1) * mWindowWidth]);
+        EXPECT_EQ(expectedBottomRightPixel,
+                  byteData[(mWindowWidth - 1) * mWindowWidth + (mWindowWidth - 1)]);
+
+        context->Unmap(cpuTexture, 0);
+        SafeRelease(cpuTexture);
+        SafeRelease(device);
+        SafeRelease(context);
+    }
+
+    EGLDisplay mDisplay;
+    EGLContext mContext;
+    EGLSurface mSurface;
+    ID3D11Texture2D *mOffscreenSurfaceD3D11Texture;
+    EGLConfig mConfig;
+    OSWindow *mOSWindow;
+    GLint mWindowWidth;
+};
+
+// Test that rendering basic content onto a window surface when present path fast
+// is enabled works as expected
+TEST_P(EGLPresentPathD3D11, WindowPresentPathFast)
+{
+    initializeEGL(true);
+    createWindowSurface();
+    makeCurrent();
+
+    drawQuadUsingGL();
+
+    checkPixelsUsingGL();
+}
+
+// Test that rendering basic content onto a client buffer surface when present path fast
+// works as expected, and is also oriented the correct way around
+TEST_P(EGLPresentPathD3D11, ClientBufferPresentPathFast)
+{
+    initializeEGL(true);
+    createPbufferFromClientBufferSurface();
+    makeCurrent();
+
+    drawQuadUsingGL();
+
+    checkPixelsUsingGL();
+    checkPixelsUsingD3D(true);
+}
+
+// Test that rendering basic content onto a window surface when present path fast
+// is disabled works as expected
+TEST_P(EGLPresentPathD3D11, WindowPresentPathCopy)
+{
+    initializeEGL(false);
+    createWindowSurface();
+    makeCurrent();
+
+    drawQuadUsingGL();
+
+    checkPixelsUsingGL();
+}
+
+// Test that rendering basic content onto a client buffer surface when present path
+// fast is disabled works as expected, and is also oriented the correct way around
+TEST_P(EGLPresentPathD3D11, ClientBufferPresentPathCopy)
+{
+    initializeEGL(false);
+    createPbufferFromClientBufferSurface();
+    makeCurrent();
+
+    drawQuadUsingGL();
+
+    checkPixelsUsingGL();
+    checkPixelsUsingD3D(false);
+}
+
+ANGLE_INSTANTIATE_TEST(EGLPresentPathD3D11, ES2_D3D11(), ES2_D3D11_FL9_3());
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLQueryContextTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLQueryContextTest.cpp
new file mode 100644
index 0000000..6b6bf0a
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLQueryContextTest.cpp
@@ -0,0 +1,153 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include <gtest/gtest.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "test_utils/angle_test_configs.h"
+
+using namespace angle;
+
+class EGLQueryContextTest : public testing::TestWithParam<PlatformParameters>
+{
+  public:
+    void SetUp() override
+    {
+        int clientVersion = GetParam().majorVersion;
+
+        PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+        EXPECT_TRUE(eglGetPlatformDisplayEXT != nullptr);
+
+        EGLint dispattrs[] =
+        {
+            EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(),
+            EGL_NONE
+        };
+        mDisplay = eglGetPlatformDisplayEXT(
+            EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
+        EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY);
+        EXPECT_TRUE(eglInitialize(mDisplay, nullptr, nullptr) != EGL_FALSE);
+
+        EGLint ncfg;
+        EGLint cfgattrs[] =
+        {
+            EGL_RED_SIZE, 8,
+            EGL_GREEN_SIZE, 8,
+            EGL_BLUE_SIZE, 8,
+            EGL_RENDERABLE_TYPE, clientVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT,
+            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+            EGL_NONE
+        };
+        EXPECT_TRUE(eglChooseConfig(mDisplay, cfgattrs, &mConfig, 1, &ncfg) != EGL_FALSE);
+        EXPECT_TRUE(ncfg == 1);
+
+        EGLint ctxattrs[] =
+        {
+            EGL_CONTEXT_CLIENT_VERSION, clientVersion,
+            EGL_NONE
+        };
+        mContext = eglCreateContext(mDisplay, mConfig, nullptr, ctxattrs);
+        EXPECT_TRUE(mContext != EGL_NO_CONTEXT);
+
+        EGLint surfattrs[] =
+        {
+            EGL_WIDTH, 16,
+            EGL_HEIGHT, 16,
+            EGL_NONE
+        };
+        mSurface = eglCreatePbufferSurface(mDisplay, mConfig, surfattrs);
+        EXPECT_TRUE(mSurface != EGL_NO_SURFACE);
+    }
+
+    void TearDown() override
+    {
+        eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        eglDestroyContext(mDisplay, mContext);
+        eglDestroySurface(mDisplay, mSurface);
+        eglTerminate(mDisplay);
+    }
+
+    EGLDisplay mDisplay;
+    EGLConfig mConfig;
+    EGLContext mContext;
+    EGLSurface mSurface;
+};
+
+TEST_P(EGLQueryContextTest, GetConfigID)
+{
+    EGLint configId, contextConfigId;
+    EXPECT_TRUE(eglGetConfigAttrib(mDisplay, mConfig, EGL_CONFIG_ID, &configId) != EGL_FALSE);
+    EXPECT_TRUE(eglQueryContext(mDisplay, mContext, EGL_CONFIG_ID, &contextConfigId) != EGL_FALSE);
+    EXPECT_TRUE(configId == contextConfigId);
+}
+
+TEST_P(EGLQueryContextTest, GetClientType)
+{
+    EGLint clientType;
+    EXPECT_TRUE(eglQueryContext(mDisplay, mContext, EGL_CONTEXT_CLIENT_TYPE, &clientType) != EGL_FALSE);
+    EXPECT_TRUE(clientType == EGL_OPENGL_ES_API);
+}
+
+TEST_P(EGLQueryContextTest, GetClientVersion)
+{
+    EGLint clientVersion;
+    EXPECT_TRUE(eglQueryContext(mDisplay, mContext, EGL_CONTEXT_CLIENT_VERSION, &clientVersion) != EGL_FALSE);
+    EXPECT_TRUE(clientVersion == GetParam().majorVersion);
+}
+
+TEST_P(EGLQueryContextTest, GetRenderBufferNoSurface)
+{
+    EGLint renderBuffer;
+    EXPECT_TRUE(eglQueryContext(mDisplay, mContext, EGL_RENDER_BUFFER, &renderBuffer) != EGL_FALSE);
+    EXPECT_TRUE(renderBuffer == EGL_NONE);
+}
+
+TEST_P(EGLQueryContextTest, GetRenderBufferBoundSurface)
+{
+    EGLint renderBuffer, contextRenderBuffer;
+    EXPECT_TRUE(eglQuerySurface(mDisplay, mSurface, EGL_RENDER_BUFFER, &renderBuffer) != EGL_FALSE);
+    EXPECT_TRUE(eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) != EGL_FALSE);
+    EXPECT_TRUE(eglQueryContext(mDisplay, mContext, EGL_RENDER_BUFFER, &contextRenderBuffer) != EGL_FALSE);
+    EXPECT_TRUE(renderBuffer == contextRenderBuffer);
+}
+
+TEST_P(EGLQueryContextTest, BadDisplay)
+{
+    EGLint val;
+    EXPECT_TRUE(eglQueryContext(EGL_NO_DISPLAY, mContext, EGL_CONTEXT_CLIENT_TYPE, &val) == EGL_FALSE);
+    EXPECT_TRUE(eglGetError() == EGL_BAD_DISPLAY);
+}
+
+TEST_P(EGLQueryContextTest, NotInitialized)
+{
+    EGLint val;
+    TearDown();
+    EXPECT_TRUE(eglQueryContext(mDisplay, mContext, EGL_CONTEXT_CLIENT_TYPE, &val) == EGL_FALSE);
+    EXPECT_TRUE(eglGetError() == EGL_NOT_INITIALIZED);
+
+    mDisplay = EGL_NO_DISPLAY;
+    mSurface = EGL_NO_SURFACE;
+    mContext = EGL_NO_CONTEXT;
+}
+
+TEST_P(EGLQueryContextTest, BadContext)
+{
+    EGLint val;
+    EXPECT_TRUE(eglQueryContext(mDisplay, EGL_NO_CONTEXT, EGL_CONTEXT_CLIENT_TYPE, &val) == EGL_FALSE);
+    EXPECT_TRUE(eglGetError() == EGL_BAD_CONTEXT);
+}
+
+TEST_P(EGLQueryContextTest, BadAttribute)
+{
+    EGLint val;
+    EXPECT_TRUE(eglQueryContext(mDisplay, mContext, EGL_HEIGHT, &val) == EGL_FALSE);
+    EXPECT_TRUE(eglGetError() == EGL_BAD_ATTRIBUTE);
+}
+
+ANGLE_INSTANTIATE_TEST(EGLQueryContextTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3(), ES2_OPENGL(),
+                       ES3_D3D11(), ES3_OPENGL());
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLRobustnessTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLRobustnessTest.cpp
new file mode 100644
index 0000000..0482a7f
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLRobustnessTest.cpp
@@ -0,0 +1,234 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// EGLRobustnessTest.cpp: tests for EGL_EXT_create_context_robustness
+
+#include <gtest/gtest.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "OSWindow.h"
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class EGLRobustnessTest : public ::testing::TestWithParam<angle::PlatformParameters>
+{
+  public:
+    void SetUp() override
+    {
+        mOSWindow = CreateOSWindow();
+        mOSWindow->initialize("EGLRobustnessTest", 500, 500);
+        mOSWindow->setVisible(true);
+
+        auto eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
+            eglGetProcAddress("eglGetPlatformDisplayEXT"));
+
+        const auto &platform = GetParam().eglParameters;
+
+        std::vector<EGLint> displayAttributes;
+        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+        displayAttributes.push_back(platform.renderer);
+        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
+        displayAttributes.push_back(platform.majorVersion);
+        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
+        displayAttributes.push_back(platform.minorVersion);
+
+        if (platform.deviceType != EGL_DONT_CARE)
+        {
+            displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+            displayAttributes.push_back(platform.deviceType);
+        }
+
+        displayAttributes.push_back(EGL_NONE);
+
+        mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
+                                            reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
+                                            &displayAttributes[0]);
+        ASSERT_NE(EGL_NO_DISPLAY, mDisplay);
+
+        ASSERT_TRUE(eglInitialize(mDisplay, nullptr, nullptr) == EGL_TRUE);
+
+        const char *extensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
+        if (strstr(extensions, "EGL_EXT_create_context_robustness") == nullptr)
+        {
+            std::cout << "Test skipped due to missing EGL_EXT_create_context_robustness"
+                      << std::endl;
+            return;
+        }
+
+        int nConfigs = 0;
+        ASSERT_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &nConfigs) == EGL_TRUE);
+        ASSERT_LE(1, nConfigs);
+
+        int nReturnedConfigs = 0;
+        ASSERT_TRUE(eglGetConfigs(mDisplay, &mConfig, 1, &nReturnedConfigs) == EGL_TRUE);
+        ASSERT_EQ(1, nReturnedConfigs);
+
+        mWindow = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), nullptr);
+        ASSERT_EGL_SUCCESS();
+
+        mInitialized = true;
+    }
+
+    void TearDown() override
+    {
+        eglDestroySurface(mDisplay, mWindow);
+        eglDestroyContext(mDisplay, mContext);
+        eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        eglTerminate(mDisplay);
+        EXPECT_EGL_SUCCESS();
+
+        SafeDelete(mOSWindow);
+    }
+
+    void createContext(EGLint resetStrategy)
+    {
+        const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2,
+                                         EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
+                                         resetStrategy, EGL_NONE};
+        mContext = eglCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT, contextAttribs);
+        ASSERT_NE(EGL_NO_CONTEXT, mContext);
+
+        eglMakeCurrent(mDisplay, mWindow, mWindow, mContext);
+        ASSERT_EGL_SUCCESS();
+
+        const char *extensionString = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
+        ASSERT_NE(nullptr, strstr(extensionString, "GL_ANGLE_instanced_arrays"));
+
+        mDrawElementsInstancedANGLE =
+            (PFNGLDRAWELEMENTSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawElementsInstancedANGLE");
+        ASSERT_NE(nullptr, mDrawElementsInstancedANGLE);
+    }
+
+    void forceContextReset()
+    {
+        // Cause a GPU reset by drawing 100,000,000 fullscreen quads
+        GLuint program = CompileProgram(
+            "attribute vec4 pos;\n"
+            "void main() {gl_Position = pos;}\n",
+            "precision mediump float;\n"
+            "void main() {gl_FragColor = vec4(1.0);}\n");
+        ASSERT_NE(0u, program);
+        glUseProgram(program);
+
+        GLfloat vertices[] = {
+            -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
+            1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f,
+        };
+
+        const int kNumQuads = 10000;
+        std::vector<GLushort> indices(6 * kNumQuads);
+
+        for (size_t i = 0; i < kNumQuads; i++)
+        {
+            indices[i * 6 + 0] = 0;
+            indices[i * 6 + 1] = 1;
+            indices[i * 6 + 2] = 2;
+            indices[i * 6 + 3] = 1;
+            indices[i * 6 + 4] = 2;
+            indices[i * 6 + 5] = 3;
+        }
+
+        glBindAttribLocation(program, 0, "pos");
+        glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, vertices);
+        glEnableVertexAttribArray(0);
+
+        glViewport(0, 0, mOSWindow->getWidth(), mOSWindow->getHeight());
+        glClearColor(1.0, 0.0, 0.0, 1.0);
+        glClear(GL_COLOR_BUFFER_BIT);
+        mDrawElementsInstancedANGLE(GL_TRIANGLES, kNumQuads * 6, GL_UNSIGNED_SHORT, indices.data(),
+                                    10000);
+
+        glFinish();
+    }
+
+  protected:
+    EGLDisplay mDisplay                                             = EGL_NO_DISPLAY;
+    EGLSurface mWindow                                              = EGL_NO_SURFACE;
+    bool mInitialized                                               = false;
+    PFNGLDRAWELEMENTSINSTANCEDANGLEPROC mDrawElementsInstancedANGLE = nullptr;
+
+  private:
+    EGLContext mContext = EGL_NO_CONTEXT;
+    EGLConfig mConfig   = 0;
+    OSWindow *mOSWindow = nullptr;
+};
+
+// Check glGetGraphicsResetStatusEXT returns GL_NO_ERROR if we did nothing
+TEST_P(EGLRobustnessTest, NoErrorByDefault)
+{
+    if (!mInitialized)
+    {
+        return;
+    }
+    ASSERT_TRUE(glGetGraphicsResetStatusEXT() == GL_NO_ERROR);
+}
+
+// Checks that the application gets no loss with NO_RESET_NOTIFICATION
+TEST_P(EGLRobustnessTest, DISABLED_NoResetNotification)
+{
+    if (!mInitialized)
+    {
+        return;
+    }
+
+    createContext(EGL_NO_RESET_NOTIFICATION_EXT);
+
+    if (!IsWindows())
+    {
+        std::cout << "Test disabled on non Windows platforms because drivers can't recover. "
+                  << "See " << __FILE__ << ":" << __LINE__ << std::endl;
+        return;
+    }
+    std::cout << "Causing a GPU reset, brace for impact." << std::endl;
+
+    forceContextReset();
+    ASSERT_TRUE(glGetGraphicsResetStatusEXT() == GL_NO_ERROR);
+}
+
+// Checks that resetting the ANGLE display allows to get rid of the context loss.
+// Also checks that the application gets notified of the loss of the display.
+// We coalesce both tests to reduce the number of TDRs done on Windows: by default
+// having more than 5 TDRs in a minute will cause Windows to disable the GPU until
+// the computer is rebooted.
+TEST_P(EGLRobustnessTest, DISABLED_ResettingDisplayWorks)
+{
+    if (!mInitialized)
+    {
+        return;
+    }
+
+    createContext(EGL_LOSE_CONTEXT_ON_RESET_EXT);
+
+    if (!IsWindows())
+    {
+        std::cout << "Test disabled on non Windows platforms because drivers can't recover. "
+                  << "See " << __FILE__ << ":" << __LINE__ << std::endl;
+        return;
+    }
+    std::cout << "Causing a GPU reset, brace for impact." << std::endl;
+
+    forceContextReset();
+    ASSERT_TRUE(glGetGraphicsResetStatusEXT() != GL_NO_ERROR);
+
+    TearDown();
+    SetUp();
+    ASSERT_TRUE(glGetGraphicsResetStatusEXT() == GL_NO_ERROR);
+}
+
+// Tests causing GPU resets are disabled, use the following args to run them:
+// --gtest_also_run_disabled_tests --gtest_filter=EGLRobustnessTest\*
+
+// Note that on Windows the OpenGL driver fails hard (popup that closes the application)
+// if there was a TDR caused by D3D so we don't run D3D tests at the same time as the OpenGL tests.
+#define D3D_HAS_PRIORITY 1
+#if D3D_HAS_PRIORITY && (defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11))
+ANGLE_INSTANTIATE_TEST(EGLRobustnessTest, ES2_D3D9(), ES2_D3D11());
+#else
+ANGLE_INSTANTIATE_TEST(EGLRobustnessTest, ES2_OPENGL());
+#endif
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLSanityCheckTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLSanityCheckTest.cpp
new file mode 100644
index 0000000..897b5ac
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLSanityCheckTest.cpp
@@ -0,0 +1,30 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLSanityCheckTest.cpp:
+//      Tests used to check environment in which other tests are run.
+
+#include <gtest/gtest.h>
+
+#include "test_utils/ANGLETest.h"
+
+// Checks the tests are running against ANGLE
+TEST(EGLSanityCheckTest, IsRunningOnANGLE)
+{
+    const char *extensionString =
+        static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
+    ASSERT_NE(strstr(extensionString, "EGL_ANGLE_platform_angle"), nullptr);
+}
+
+// Checks that getting function pointer works
+TEST(EGLSanityCheckTest, HasGetPlatformDisplayEXT)
+{
+    PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
+        reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
+            eglGetProcAddress("eglGetPlatformDisplayEXT"));
+
+    ASSERT_NE(eglGetPlatformDisplayEXT, nullptr);
+}
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLStreamTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLStreamTest.cpp
new file mode 100644
index 0000000..b667cf7
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLStreamTest.cpp
@@ -0,0 +1,547 @@
+//
+// Copyright 2016 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.
+//
+// EGLStreamTest:
+//   Tests pertaining to egl::Stream.
+//
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include "media/yuvtest.inl"
+#include "OSWindow.h"
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class EGLStreamTest : public ANGLETest
+{
+  protected:
+    EGLStreamTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+};
+
+// Tests validation of the stream API
+TEST_P(EGLStreamTest, StreamValidationTest)
+{
+    EGLWindow *window            = getEGLWindow();
+    EGLDisplay display           = window->getDisplay();
+    const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);
+    if (strstr(extensionsString, "EGL_KHR_stream") == nullptr)
+    {
+        std::cout << "Stream extension not supported" << std::endl;
+        return;
+    }
+
+    const EGLint streamAttributesBad[] = {
+        EGL_STREAM_STATE_KHR,
+        0,
+        EGL_NONE,
+        EGL_PRODUCER_FRAME_KHR,
+        0,
+        EGL_NONE,
+        EGL_CONSUMER_FRAME_KHR,
+        0,
+        EGL_NONE,
+        EGL_CONSUMER_LATENCY_USEC_KHR,
+        -1,
+        EGL_NONE,
+        EGL_RED_SIZE,
+        EGL_DONT_CARE,
+        EGL_NONE,
+    };
+
+    // Validate create stream attributes
+    EGLStreamKHR stream = eglCreateStreamKHR(display, &streamAttributesBad[0]);
+    ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
+    ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
+
+    stream = eglCreateStreamKHR(display, &streamAttributesBad[3]);
+    ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
+    ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
+
+    stream = eglCreateStreamKHR(display, &streamAttributesBad[6]);
+    ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
+    ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
+
+    stream = eglCreateStreamKHR(display, &streamAttributesBad[9]);
+    ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
+    ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
+
+    stream = eglCreateStreamKHR(display, &streamAttributesBad[12]);
+    ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
+    ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
+
+    const EGLint streamAttributes[] = {
+        EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_NONE,
+    };
+
+    stream = eglCreateStreamKHR(EGL_NO_DISPLAY, streamAttributes);
+    ASSERT_EGL_ERROR(EGL_BAD_DISPLAY);
+    ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
+
+    // Create an actual stream
+    stream = eglCreateStreamKHR(display, streamAttributes);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_NE(EGL_NO_STREAM_KHR, stream);
+
+    // Assert it is in the created state
+    EGLint state;
+    eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(EGL_STREAM_STATE_CREATED_KHR, state);
+
+    // Test getting and setting the latency
+    EGLint latency = 10;
+    eglStreamAttribKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, latency);
+    ASSERT_EGL_SUCCESS();
+    eglQueryStreamKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, &latency);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(10, latency);
+    eglStreamAttribKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, -1);
+    ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
+    ASSERT_EQ(10, latency);
+
+    // Test the 64-bit queries
+    EGLuint64KHR value;
+    eglQueryStreamu64KHR(display, stream, EGL_CONSUMER_FRAME_KHR, &value);
+    ASSERT_EGL_SUCCESS();
+    eglQueryStreamu64KHR(display, stream, EGL_PRODUCER_FRAME_KHR, &value);
+    ASSERT_EGL_SUCCESS();
+
+    // Destroy the stream
+    eglDestroyStreamKHR(display, stream);
+    ASSERT_EGL_SUCCESS();
+}
+
+// Tests validation of stream consumer gltexture API
+TEST_P(EGLStreamTest, StreamConsumerGLTextureValidationTest)
+{
+    EGLWindow *window            = getEGLWindow();
+    EGLDisplay display           = window->getDisplay();
+    const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);
+    if (strstr(extensionsString, "EGL_KHR_stream_consumer_gltexture") == nullptr)
+    {
+        std::cout << "Stream consumer gltexture extension not supported" << std::endl;
+        return;
+    }
+
+    const EGLint streamAttributes[] = {
+        EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,
+    };
+
+    EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);
+    ASSERT_EGL_SUCCESS();
+
+    EGLBoolean result = eglStreamConsumerGLTextureExternalKHR(display, stream);
+    ASSERT_EGL_FALSE(result);
+    ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
+
+    GLuint tex;
+    glGenTextures(1, &tex);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
+    result = eglStreamConsumerGLTextureExternalKHR(display, stream);
+    ASSERT_EGL_TRUE(result);
+    ASSERT_EGL_SUCCESS();
+
+    EGLint state;
+    eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(EGL_STREAM_STATE_CONNECTING_KHR, state);
+
+    eglDestroyStreamKHR(display, stream);
+    ASSERT_EGL_SUCCESS();
+}
+
+// Tests validation of stream consumer gltexture yuv API
+TEST_P(EGLStreamTest, StreamConsumerGLTextureYUVValidationTest)
+{
+    EGLWindow *window            = getEGLWindow();
+    EGLDisplay display           = window->getDisplay();
+    const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);
+    if (strstr(extensionsString, "EGL_NV_stream_consumer_gltexture_yuv") == nullptr)
+    {
+        std::cout << "Stream consumer gltexture yuv extension not supported" << std::endl;
+        return;
+    }
+
+    const EGLint streamAttributes[] = {
+        EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,
+    };
+
+    EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);
+    ASSERT_EGL_SUCCESS();
+
+    EGLAttrib consumerAttributesBad[] = {
+        EGL_COLOR_BUFFER_TYPE,
+        EGL_YUV_BUFFER_EXT,  // 0
+        EGL_YUV_NUMBER_OF_PLANES_EXT,
+        0,
+        EGL_NONE,
+        EGL_COLOR_BUFFER_TYPE,
+        EGL_YUV_BUFFER_EXT,  // 5
+        EGL_YUV_NUMBER_OF_PLANES_EXT,
+        1,
+        EGL_NONE,
+        EGL_COLOR_BUFFER_TYPE,
+        EGL_YUV_BUFFER_EXT,  // 10
+        EGL_YUV_NUMBER_OF_PLANES_EXT,
+        1,
+        EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
+        9999,
+        EGL_NONE,
+        EGL_COLOR_BUFFER_TYPE,
+        EGL_YUV_BUFFER_EXT,  // 17
+        EGL_YUV_NUMBER_OF_PLANES_EXT,
+        1,
+        EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
+        0,
+        EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
+        1,
+        EGL_NONE,
+        EGL_COLOR_BUFFER_TYPE,
+        EGL_YUV_BUFFER_EXT,  // 26
+        EGL_YUV_NUMBER_OF_PLANES_EXT,
+        2,
+        EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
+        0,
+        EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
+        0,
+        EGL_NONE,
+    };
+
+    EGLAttrib consumerAttributes[] = {
+        EGL_COLOR_BUFFER_TYPE,
+        EGL_YUV_BUFFER_EXT,
+        EGL_YUV_NUMBER_OF_PLANES_EXT,
+        2,
+        EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
+        0,
+        EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
+        1,
+        EGL_NONE,
+    };
+
+    EGLBoolean result =
+        eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[0]);
+    ASSERT_EGL_FALSE(result);
+    ASSERT_EGL_ERROR(EGL_BAD_MATCH);
+
+    result =
+        eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[5]);
+    ASSERT_EGL_FALSE(result);
+    ASSERT_EGL_ERROR(EGL_BAD_MATCH);
+
+    result =
+        eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[10]);
+    ASSERT_EGL_FALSE(result);
+    ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
+
+    result =
+        eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[17]);
+    ASSERT_EGL_FALSE(result);
+    ASSERT_EGL_ERROR(EGL_BAD_MATCH);
+
+    result = eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);
+    ASSERT_EGL_FALSE(result);
+    ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
+
+    GLuint tex[2];
+    glGenTextures(2, tex);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);
+
+    result =
+        eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[26]);
+    ASSERT_EGL_FALSE(result);
+    ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
+
+    result = eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);
+    ASSERT_EGL_TRUE(result);
+    ASSERT_EGL_SUCCESS();
+
+    EGLint state;
+    eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(EGL_STREAM_STATE_CONNECTING_KHR, state);
+
+    eglDestroyStreamKHR(display, stream);
+    ASSERT_EGL_SUCCESS();
+}
+
+// Tests that deleting a texture invalidates the associated stream
+TEST_P(EGLStreamTest, StreamConsumerGLTextureYUVDeletionTest)
+{
+    EGLWindow *window            = getEGLWindow();
+    EGLDisplay display           = window->getDisplay();
+    const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);
+    if (strstr(extensionsString, "EGL_ANGLE_stream_producer_d3d_texture_nv12") == nullptr)
+    {
+        std::cout << "Stream producer d3d nv12 texture not supported" << std::endl;
+        return;
+    }
+
+    const EGLint streamAttributes[] = {
+        EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,
+    };
+
+    EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);
+    ASSERT_EGL_SUCCESS();
+
+    EGLAttrib consumerAttributes[] = {
+        EGL_COLOR_BUFFER_TYPE,
+        EGL_YUV_BUFFER_EXT,
+        EGL_YUV_NUMBER_OF_PLANES_EXT,
+        2,
+        EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
+        0,
+        EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
+        1,
+        EGL_NONE,
+    };
+
+    GLuint tex[2];
+    glGenTextures(2, tex);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);
+
+    EGLBoolean result =
+        eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);
+    ASSERT_EGL_TRUE(result);
+    ASSERT_EGL_SUCCESS();
+
+    EGLAttrib producerAttributes[] = {
+        EGL_NONE,
+    };
+
+    result = eglCreateStreamProducerD3DTextureNV12ANGLE(display, stream, producerAttributes);
+    ASSERT_EGL_TRUE(result);
+    ASSERT_EGL_SUCCESS();
+
+    EGLint state;
+    eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(EGL_STREAM_STATE_EMPTY_KHR, state);
+
+    // Delete the first texture, which should be enough to invalidate the stream
+    glDeleteTextures(1, tex);
+
+    eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(EGL_STREAM_STATE_DISCONNECTED_KHR, state);
+
+    eglDestroyStreamKHR(display, stream);
+    ASSERT_EGL_SUCCESS();
+}
+
+// End2end test for rendering an NV12 texture. Renders a YUV quad, reads back the RGB values, and
+// ensures they are correct
+TEST_P(EGLStreamTest, StreamProducerTextureNV12End2End)
+{
+    EGLWindow *window            = getEGLWindow();
+    EGLDisplay display           = window->getDisplay();
+    if (!eglDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture_nv12"))
+    {
+        std::cout << "Stream producer d3d nv12 texture not supported" << std::endl;
+        return;
+    }
+
+    bool useESSL3Shaders =
+        getClientMajorVersion() >= 3 && extensionEnabled("GL_OES_EGL_image_external_essl3");
+
+    // yuv to rgb conversion shader using Microsoft's given conversion formulas
+    std::string yuvVS, yuvPS;
+    if (useESSL3Shaders)
+    {
+        yuvVS =
+            "#version 300 es\n"
+            "in highp vec4 position;\n"
+            "out vec2 texcoord;\n"
+            "void main(void)\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "    texcoord.y = 1.0 - texcoord.y;\n"
+            "}\n";
+        yuvPS =
+            "#version 300 es\n"
+            "#extension GL_OES_EGL_image_external_essl3 : require\n"
+            "#extension GL_NV_EGL_stream_consumer_external : require\n"
+            "precision highp float;\n"
+            "in vec2 texcoord;\n"
+            "out vec4 color;\n"
+            "uniform samplerExternalOES y;\n"
+            "uniform samplerExternalOES uv\n;"
+            "void main(void)\n"
+            "{\n"
+            "    float c = texture(y, texcoord).r - (16.0 / 256.0);\n"
+            "    float d = texture(uv, texcoord).r - 0.5;\n"
+            "    float e = texture(uv, texcoord).g - 0.5;\n"
+            "    float r = 1.164383 * c + 1.596027 * e;\n"
+            "    float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n"
+            "    float b = 1.164383 * c + 2.017232 * d;\n"
+            "    color = vec4(r, g, b, 1.0);\n"
+            "}\n";
+    }
+    else
+    {
+        yuvVS =
+            "attribute highp vec4 position;\n"
+            "varying vec2 texcoord;\n"
+            "void main(void)\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "    texcoord.y = 1.0 - texcoord.y;\n"
+            "}\n";
+
+        yuvPS =
+            "#extension GL_NV_EGL_stream_consumer_external : require\n"
+            "precision highp float;\n"
+            "varying vec2 texcoord;\n"
+            "uniform samplerExternalOES y;\n"
+            "uniform samplerExternalOES uv\n;"
+            "void main(void)\n"
+            "{\n"
+            "    float c = texture2D(y, texcoord).r - (16.0 / 256.0);\n"
+            "    float d = texture2D(uv, texcoord).r - 0.5;\n"
+            "    float e = texture2D(uv, texcoord).g - 0.5;\n"
+            "    float r = 1.164383 * c + 1.596027 * e;\n"
+            "    float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n"
+            "    float b = 1.164383 * c + 2.017232 * d;\n"
+            "    gl_FragColor = vec4(r, g, b, 1.0);\n"
+            "}\n";
+    }
+
+    GLuint program = CompileProgram(yuvVS, yuvPS);
+    ASSERT_NE(0u, program);
+    GLuint yUniform  = glGetUniformLocation(program, "y");
+    GLuint uvUniform = glGetUniformLocation(program, "uv");
+
+    // Fetch the D3D11 device
+    EGLDeviceEXT eglDevice;
+    eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, (EGLAttrib *)&eglDevice);
+    ID3D11Device *device;
+    eglQueryDeviceAttribEXT(eglDevice, EGL_D3D11_DEVICE_ANGLE, (EGLAttrib *)&device);
+
+    // Create the NV12 D3D11 texture
+    HRESULT res;
+    D3D11_TEXTURE2D_DESC desc;
+    desc.Width              = yuvtest_width;
+    desc.Height             = yuvtest_height;
+    desc.Format             = DXGI_FORMAT_NV12;
+    desc.MipLevels          = 1;
+    desc.ArraySize          = 1;
+    desc.SampleDesc.Count   = 1;
+    desc.SampleDesc.Quality = 0;
+    desc.Usage              = D3D11_USAGE_DEFAULT;
+    desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE;
+    desc.CPUAccessFlags     = 0;
+    desc.MiscFlags          = 0;
+
+    D3D11_SUBRESOURCE_DATA subres;
+    subres.pSysMem          = yuvtest_data;
+    subres.SysMemPitch      = yuvtest_width;
+    subres.SysMemSlicePitch = yuvtest_width * yuvtest_height * 3 / 2;
+
+    ID3D11Texture2D *texture = nullptr;
+    res                      = device->CreateTexture2D(&desc, &subres, &texture);
+
+    // Create the stream
+    const EGLint streamAttributes[] = {
+        EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,
+    };
+
+    EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);
+    ASSERT_EGL_SUCCESS();
+
+    EGLAttrib consumerAttributes[] = {
+        EGL_COLOR_BUFFER_TYPE,
+        EGL_YUV_BUFFER_EXT,
+        EGL_YUV_NUMBER_OF_PLANES_EXT,
+        2,
+        EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
+        0,
+        EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
+        1,
+        EGL_NONE,
+    };
+
+    GLuint tex[2];
+    glGenTextures(2, tex);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);
+    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    ASSERT_GL_NO_ERROR();
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);
+    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    ASSERT_GL_NO_ERROR();
+
+    EGLBoolean result =
+        eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);
+    ASSERT_EGL_TRUE(result);
+    ASSERT_EGL_SUCCESS();
+
+    EGLAttrib producerAttributes[] = {
+        EGL_NONE,
+    };
+
+    result = eglCreateStreamProducerD3DTextureNV12ANGLE(display, stream, producerAttributes);
+    ASSERT_EGL_TRUE(result);
+    ASSERT_EGL_SUCCESS();
+
+    // Insert the frame
+    EGLAttrib frameAttributes[] = {
+        EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0, EGL_NONE,
+    };
+    result = eglStreamPostD3DTextureNV12ANGLE(display, stream, (void *)texture, frameAttributes);
+    ASSERT_EGL_TRUE(result);
+    ASSERT_EGL_SUCCESS();
+
+    EGLint state;
+    eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR, state);
+
+    eglStreamConsumerAcquireKHR(display, stream);
+    ASSERT_EGL_SUCCESS();
+
+    glUseProgram(program);
+    glUniform1i(yUniform, 0);
+    glUniform1i(uvUniform, 1);
+    drawQuad(program, "position", 0.0f);
+    ASSERT_GL_NO_ERROR();
+
+    eglStreamConsumerReleaseKHR(display, stream);
+    ASSERT_EGL_SUCCESS();
+
+    eglSwapBuffers(display, window->getSurface());
+    SafeRelease(texture);
+}
+
+ANGLE_INSTANTIATE_TEST(EGLStreamTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL());
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLSurfaceTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLSurfaceTest.cpp
new file mode 100644
index 0000000..26390b0
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLSurfaceTest.cpp
@@ -0,0 +1,604 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// EGLSurfaceTest:
+//   Tests pertaining to egl::Surface.
+//
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include "OSWindow.h"
+#include "test_utils/ANGLETest.h"
+
+#if defined(ANGLE_ENABLE_D3D11)
+#define INITGUID
+#include <guiddef.h>
+
+#include <d3d11.h>
+#include <dcomp.h>
+#endif
+
+namespace
+{
+
+class EGLSurfaceTest : public testing::Test
+{
+  protected:
+    EGLSurfaceTest()
+        : mDisplay(EGL_NO_DISPLAY),
+          mWindowSurface(EGL_NO_SURFACE),
+          mPbufferSurface(EGL_NO_SURFACE),
+          mContext(EGL_NO_CONTEXT),
+          mSecondContext(EGL_NO_CONTEXT),
+          mOSWindow(nullptr)
+    {
+    }
+
+    void SetUp() override
+    {
+        mOSWindow = CreateOSWindow();
+        mOSWindow->initialize("EGLSurfaceTest", 64, 64);
+    }
+
+    // Release any resources created in the test body
+    void TearDown() override
+    {
+        if (mDisplay != EGL_NO_DISPLAY)
+        {
+            eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+            if (mWindowSurface != EGL_NO_SURFACE)
+            {
+                eglDestroySurface(mDisplay, mWindowSurface);
+                mWindowSurface = EGL_NO_SURFACE;
+            }
+
+            if (mPbufferSurface != EGL_NO_SURFACE)
+            {
+                eglDestroySurface(mDisplay, mPbufferSurface);
+                mPbufferSurface = EGL_NO_SURFACE;
+            }
+
+            if (mContext != EGL_NO_CONTEXT)
+            {
+                eglDestroyContext(mDisplay, mContext);
+                mContext = EGL_NO_CONTEXT;
+            }
+
+            if (mSecondContext != EGL_NO_CONTEXT)
+            {
+                eglDestroyContext(mDisplay, mSecondContext);
+                mSecondContext = EGL_NO_CONTEXT;
+            }
+
+            eglTerminate(mDisplay);
+            mDisplay = EGL_NO_DISPLAY;
+        }
+
+        mOSWindow->destroy();
+        SafeDelete(mOSWindow);
+
+        ASSERT_TRUE(mWindowSurface == EGL_NO_SURFACE && mContext == EGL_NO_CONTEXT);
+    }
+
+    void initializeDisplay(EGLenum platformType)
+    {
+        PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+        ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr);
+
+        std::vector<EGLint> displayAttributes;
+        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+        displayAttributes.push_back(platformType);
+        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
+        displayAttributes.push_back(EGL_DONT_CARE);
+        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
+        displayAttributes.push_back(EGL_DONT_CARE);
+
+        if (platformType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE || platformType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+        {
+            displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+            displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+        }
+        displayAttributes.push_back(EGL_NONE);
+
+        mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
+                                            reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
+                                            displayAttributes.data());
+        ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
+
+        EGLint majorVersion, minorVersion;
+        ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE);
+
+        eglBindAPI(EGL_OPENGL_ES_API);
+        ASSERT_TRUE(eglGetError() == EGL_SUCCESS);
+    }
+
+    void initializeContext()
+    {
+        EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+
+        mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
+        ASSERT_TRUE(eglGetError() == EGL_SUCCESS);
+
+        mSecondContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
+        ASSERT_TRUE(eglGetError() == EGL_SUCCESS);
+    }
+
+    void initializeSurface(EGLConfig config)
+    {
+        mConfig = config;
+
+        std::vector<EGLint> surfaceAttributes;
+        surfaceAttributes.push_back(EGL_NONE);
+        surfaceAttributes.push_back(EGL_NONE);
+
+        // Create first window surface
+        mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), &surfaceAttributes[0]);
+        ASSERT_TRUE(eglGetError() == EGL_SUCCESS);
+
+        mPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, &surfaceAttributes[0]);
+        initializeContext();
+    }
+
+    void initializeSurfaceWithDefaultConfig()
+    {
+        const EGLint configAttributes[] =
+        {
+            EGL_RED_SIZE, EGL_DONT_CARE,
+            EGL_GREEN_SIZE, EGL_DONT_CARE,
+            EGL_BLUE_SIZE, EGL_DONT_CARE,
+            EGL_ALPHA_SIZE, EGL_DONT_CARE,
+            EGL_DEPTH_SIZE, EGL_DONT_CARE,
+            EGL_STENCIL_SIZE, EGL_DONT_CARE,
+            EGL_SAMPLE_BUFFERS, 0,
+            EGL_NONE
+        };
+
+        EGLint configCount;
+        EGLConfig config;
+        ASSERT_TRUE(eglChooseConfig(mDisplay, configAttributes, &config, 1, &configCount) || (configCount != 1) == EGL_TRUE);
+
+        initializeSurface(config);
+    }
+
+    GLuint createProgram()
+    {
+        const std::string testVertexShaderSource = SHADER_SOURCE
+        (
+            attribute highp vec4 position;
+
+            void main(void)
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string testFragmentShaderSource = SHADER_SOURCE
+        (
+            void main(void)
+            {
+                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+            }
+        );
+
+        return CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+    }
+
+    void drawWithProgram(GLuint program)
+    {
+        glClearColor(0, 0, 0, 1);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        GLint positionLocation = glGetAttribLocation(program, "position");
+
+        glUseProgram(program);
+
+        const GLfloat vertices[] =
+        {
+            -1.0f,  1.0f, 0.5f,
+            -1.0f, -1.0f, 0.5f,
+             1.0f, -1.0f, 0.5f,
+
+            -1.0f,  1.0f, 0.5f,
+             1.0f, -1.0f, 0.5f,
+             1.0f,  1.0f, 0.5f,
+        };
+
+        glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
+        glEnableVertexAttribArray(positionLocation);
+
+        glDrawArrays(GL_TRIANGLES, 0, 6);
+
+        glDisableVertexAttribArray(positionLocation);
+        glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+        EXPECT_PIXEL_EQ(mOSWindow->getWidth() / 2, mOSWindow->getHeight() / 2, 255, 0, 0, 255);
+    }
+
+    void runMessageLoopTest(EGLSurface secondSurface, EGLContext secondContext)
+    {
+        eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
+        ASSERT_TRUE(eglGetError() == EGL_SUCCESS);
+
+        // Make a second context current
+        eglMakeCurrent(mDisplay, secondSurface, secondSurface, secondContext);
+        eglDestroySurface(mDisplay, mWindowSurface);
+
+        // Create second window surface
+        std::vector<EGLint> surfaceAttributes;
+        surfaceAttributes.push_back(EGL_NONE);
+        surfaceAttributes.push_back(EGL_NONE);
+
+        mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), &surfaceAttributes[0]);
+        ASSERT_TRUE(eglGetError() == EGL_SUCCESS);
+
+        eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
+        ASSERT_TRUE(eglGetError() == EGL_SUCCESS);
+
+        mOSWindow->signalTestEvent();
+        mOSWindow->messageLoop();
+        ASSERT_TRUE(mOSWindow->didTestEventFire());
+
+        // Simple operation to test the FBO is set appropriately
+        glClear(GL_COLOR_BUFFER_BIT);
+    }
+
+    EGLDisplay mDisplay;
+    EGLSurface mWindowSurface;
+    EGLSurface mPbufferSurface;
+    EGLContext mContext;
+    EGLContext mSecondContext;
+    EGLConfig mConfig;
+    OSWindow *mOSWindow;
+};
+
+// Test a surface bug where we could have two Window surfaces active
+// at one time, blocking message loops. See http://crbug.com/475085
+TEST_F(EGLSurfaceTest, MessageLoopBug)
+{
+    const char *extensionsString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+    if (strstr(extensionsString, "EGL_ANGLE_platform_angle_d3d") == nullptr)
+    {
+        std::cout << "D3D Platform not supported in ANGLE" << std::endl;
+        return;
+    }
+
+    initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+    initializeSurfaceWithDefaultConfig();
+
+    runMessageLoopTest(EGL_NO_SURFACE, EGL_NO_CONTEXT);
+}
+
+// Tests the message loop bug, but with setting a second context
+// instead of null.
+TEST_F(EGLSurfaceTest, MessageLoopBugContext)
+{
+    const char *extensionsString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+    if (strstr(extensionsString, "EGL_ANGLE_platform_angle_d3d") == nullptr)
+    {
+        std::cout << "D3D Platform not supported in ANGLE" << std::endl;
+        return;
+    }
+
+    initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+    initializeSurfaceWithDefaultConfig();
+
+    runMessageLoopTest(mPbufferSurface, mSecondContext);
+}
+
+// Test a bug where calling makeCurrent twice would release the surface
+TEST_F(EGLSurfaceTest, MakeCurrentTwice)
+{
+#if defined(ANGLE_PLATFORM_APPLE) && !defined(ANGLE_STANDALONE_BUILD)
+    // TODO(cwallez) Make context creation return at least an OpenGL ES 2 context on
+    // the Mac trybots.
+    std::cout << "Test skipped temporarily skipped on the Mac trybots" << std::endl;
+    return;
+#endif
+
+    initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+    initializeSurfaceWithDefaultConfig();
+
+    eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
+    ASSERT_TRUE(eglGetError() == EGL_SUCCESS);
+
+    eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
+    ASSERT_TRUE(eglGetError() == EGL_SUCCESS);
+
+    // Simple operation to test the FBO is set appropriately
+    glClear(GL_COLOR_BUFFER_BIT);
+}
+
+// Test that the D3D window surface is correctly resized after calling swapBuffers
+TEST_F(EGLSurfaceTest, ResizeD3DWindow)
+{
+    const char *extensionsString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+    if (strstr(extensionsString, "EGL_ANGLE_platform_angle_d3d") == nullptr)
+    {
+        std::cout << "D3D Platform not supported in ANGLE" << std::endl;
+        return;
+    }
+
+    initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+    initializeSurfaceWithDefaultConfig();
+
+    eglSwapBuffers(mDisplay, mWindowSurface);
+    ASSERT_EGL_SUCCESS();
+
+    EGLint height;
+    eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(64, height);  // initial size
+
+    // set window's height to 0
+    mOSWindow->resize(64, 0);
+
+    eglSwapBuffers(mDisplay, mWindowSurface);
+    ASSERT_EGL_SUCCESS();
+
+    eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(0, height);
+
+    // restore window's height
+    mOSWindow->resize(64, 64);
+
+    eglSwapBuffers(mDisplay, mWindowSurface);
+    ASSERT_EGL_SUCCESS();
+
+    eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_EQ(64, height);
+}
+
+// Test creating a surface that supports a EGLConfig with 16bit
+// support GL_RGB565
+TEST_F(EGLSurfaceTest, CreateWithEGLConfig5650Support)
+{
+    if (!ANGLETest::eglDisplayExtensionEnabled(EGL_NO_DISPLAY, "EGL_ANGLE_platform_angle_d3d"))
+    {
+        std::cout << "D3D Platform not supported in ANGLE" << std::endl;
+        return;
+    }
+
+    const EGLint configAttributes[] =
+    {
+        EGL_RED_SIZE, 5,
+        EGL_GREEN_SIZE, 6,
+        EGL_BLUE_SIZE, 5,
+        EGL_ALPHA_SIZE, 0,
+        EGL_DEPTH_SIZE, 0,
+        EGL_STENCIL_SIZE, 0,
+        EGL_SAMPLE_BUFFERS, 0,
+        EGL_NONE
+    };
+
+    initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+    EGLConfig config;
+    if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
+    {
+        std::cout << "EGLConfig for a GL_RGB565 surface is not supported, skipping test" << std::endl;
+        return;
+    }
+
+    initializeSurface(config);
+
+    eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
+    ASSERT_EGL_SUCCESS();
+
+    GLuint program = createProgram();
+    ASSERT_NE(0u, program);
+    drawWithProgram(program);
+    EXPECT_GL_NO_ERROR();
+    glDeleteProgram(program);
+}
+
+// Test creating a surface that supports a EGLConfig with 16bit
+// support GL_RGBA4
+TEST_F(EGLSurfaceTest, CreateWithEGLConfig4444Support)
+{
+    if (!ANGLETest::eglDisplayExtensionEnabled(EGL_NO_DISPLAY, "EGL_ANGLE_platform_angle_d3d"))
+    {
+        std::cout << "D3D Platform not supported in ANGLE" << std::endl;
+        return;
+    }
+
+    const EGLint configAttributes[] =
+    {
+        EGL_RED_SIZE, 4,
+        EGL_GREEN_SIZE, 4,
+        EGL_BLUE_SIZE, 4,
+        EGL_ALPHA_SIZE, 4,
+        EGL_DEPTH_SIZE, 0,
+        EGL_STENCIL_SIZE, 0,
+        EGL_SAMPLE_BUFFERS, 0,
+        EGL_NONE
+    };
+
+    initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+    EGLConfig config;
+    if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
+    {
+        std::cout << "EGLConfig for a GL_RGBA4 surface is not supported, skipping test" << std::endl;
+        return;
+    }
+
+    initializeSurface(config);
+
+    eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
+    ASSERT_EGL_SUCCESS();
+
+    GLuint program = createProgram();
+    ASSERT_NE(0u, program);
+    drawWithProgram(program);
+    EXPECT_GL_NO_ERROR();
+    glDeleteProgram(program);
+}
+
+// Test creating a surface that supports a EGLConfig with 16bit
+// support GL_RGB5_A1
+TEST_F(EGLSurfaceTest, CreateWithEGLConfig5551Support)
+{
+    if (!ANGLETest::eglDisplayExtensionEnabled(EGL_NO_DISPLAY, "EGL_ANGLE_platform_angle_d3d"))
+    {
+        std::cout << "D3D Platform not supported in ANGLE" << std::endl;
+        return;
+    }
+
+    const EGLint configAttributes[] =
+    {
+        EGL_RED_SIZE, 5,
+        EGL_GREEN_SIZE, 5,
+        EGL_BLUE_SIZE, 5,
+        EGL_ALPHA_SIZE, 1,
+        EGL_DEPTH_SIZE, 0,
+        EGL_STENCIL_SIZE, 0,
+        EGL_SAMPLE_BUFFERS, 0,
+        EGL_NONE
+    };
+
+    initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+    EGLConfig config;
+    if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
+    {
+        std::cout << "EGLConfig for a GL_RGB5_A1 surface is not supported, skipping test" << std::endl;
+        return;
+    }
+
+    initializeSurface(config);
+
+    eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
+    ASSERT_EGL_SUCCESS();
+
+    GLuint program = createProgram();
+    ASSERT_NE(0u, program);
+    drawWithProgram(program);
+    EXPECT_GL_NO_ERROR();
+    glDeleteProgram(program);
+}
+
+// Test creating a surface that supports a EGLConfig without alpha support
+TEST_F(EGLSurfaceTest, CreateWithEGLConfig8880Support)
+{
+    if (!ANGLETest::eglDisplayExtensionEnabled(EGL_NO_DISPLAY, "EGL_ANGLE_platform_angle_d3d"))
+    {
+        std::cout << "D3D Platform not supported in ANGLE" << std::endl;
+        return;
+    }
+
+    const EGLint configAttributes[] =
+    {
+        EGL_RED_SIZE, 8,
+        EGL_GREEN_SIZE, 8,
+        EGL_BLUE_SIZE, 8,
+        EGL_ALPHA_SIZE, 0,
+        EGL_DEPTH_SIZE, 0,
+        EGL_STENCIL_SIZE, 0,
+        EGL_SAMPLE_BUFFERS, 0,
+        EGL_NONE
+    };
+
+    initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+    EGLConfig config;
+    if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
+    {
+        std::cout << "EGLConfig for a GL_RGB8_OES surface is not supported, skipping test"
+                  << std::endl;
+        return;
+    }
+
+    initializeSurface(config);
+
+    eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
+    ASSERT_EGL_SUCCESS();
+
+    GLuint program = createProgram();
+    ASSERT_NE(0u, program);
+    drawWithProgram(program);
+    EXPECT_GL_NO_ERROR();
+    glDeleteProgram(program);
+}
+
+#if defined(ANGLE_ENABLE_D3D11)
+// Test that rendering to an IDCompositionSurface using a pbuffer works.
+TEST_F(EGLSurfaceTest, CreateDirectCompositionSurface)
+{
+    if (!ANGLETest::eglDisplayExtensionEnabled(EGL_NO_DISPLAY, "EGL_ANGLE_platform_angle_d3d"))
+    {
+        std::cout << "D3D Platform not supported in ANGLE" << std::endl;
+        return;
+    }
+    initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+
+    EGLAttrib device       = 0;
+    EGLAttrib newEglDevice = 0;
+    ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice));
+    ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(newEglDevice),
+                                            EGL_D3D11_DEVICE_ANGLE, &device));
+    angle::ComPtr<ID3D11Device> d3d11Device(reinterpret_cast<ID3D11Device *>(device));
+    ASSERT_TRUE(!!d3d11Device);
+
+    HMODULE dcompLibrary = LoadLibraryA("dcomp.dll");
+    if (!dcompLibrary)
+    {
+        std::cout << "DirectComposition not supported" << std::endl;
+        return;
+    }
+    typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE2)(IUnknown * dxgiDevice, REFIID iid,
+                                                              void **dcompositionDevice);
+    PFN_DCOMPOSITION_CREATE_DEVICE2 createDComp = reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE2>(
+        GetProcAddress(dcompLibrary, "DCompositionCreateDevice2"));
+    if (!createDComp)
+    {
+        std::cout << "DirectComposition2 not supported" << std::endl;
+        FreeLibrary(dcompLibrary);
+        return;
+    }
+
+    angle::ComPtr<IDCompositionDevice> dcompDevice;
+    HRESULT hr = createDComp(d3d11Device.Get(), IID_PPV_ARGS(dcompDevice.GetAddressOf()));
+    ASSERT_TRUE(SUCCEEDED(hr));
+
+    angle::ComPtr<IDCompositionSurface> dcompSurface;
+    hr = dcompDevice->CreateSurface(100, 100, DXGI_FORMAT_B8G8R8A8_UNORM,
+                                    DXGI_ALPHA_MODE_PREMULTIPLIED, dcompSurface.GetAddressOf());
+    ASSERT_TRUE(SUCCEEDED(hr));
+
+    angle::ComPtr<ID3D11Texture2D> texture;
+    POINT updateOffset;
+    hr = dcompSurface->BeginDraw(nullptr, IID_PPV_ARGS(texture.GetAddressOf()), &updateOffset);
+    ASSERT_TRUE(SUCCEEDED(hr));
+
+    const EGLint configAttributes[] = {
+        EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8, EGL_BLUE_SIZE,      8, EGL_ALPHA_SIZE, 8,
+        EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
+
+    EGLConfig config;
+    ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config));
+
+    const EGLint surfaceAttributes[] = {EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE};
+
+    EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture.Get());
+    mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer,
+                                                       config, surfaceAttributes);
+    ASSERT_EGL_SUCCESS();
+
+    mConfig = config;
+    initializeContext();
+
+    eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);
+    ASSERT_EGL_SUCCESS();
+
+    GLuint program = createProgram();
+    ASSERT_NE(0u, program);
+    drawWithProgram(program);
+    EXPECT_GL_NO_ERROR();
+    glDeleteProgram(program);
+}
+
+#endif
+}
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLSurfacelessContextTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLSurfacelessContextTest.cpp
new file mode 100644
index 0000000..a95a005
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLSurfacelessContextTest.cpp
@@ -0,0 +1,268 @@
+//
+// Copyright (c) 2017 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.
+//
+
+// EGLSurfacelessContextTest.cpp:
+//   Tests for the EGL_KHR_surfaceless_context and GL_OES_surfaceless_context
+
+#include <gtest/gtest.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/angle_test_configs.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+class EGLSurfacelessContextTest : public ANGLETest
+{
+  public:
+    EGLSurfacelessContextTest() : mDisplay(0) {}
+
+    void SetUp() override
+    {
+        PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
+            reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
+                eglGetProcAddress("eglGetPlatformDisplayEXT"));
+        ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr);
+
+        EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
+        mDisplay           = eglGetPlatformDisplayEXT(
+            EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
+        ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
+
+        ASSERT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));
+
+        int nConfigs = 0;
+        ASSERT_EGL_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &nConfigs));
+        ASSERT_TRUE(nConfigs != 0);
+
+        int nReturnedConfigs = 0;
+        std::vector<EGLConfig> configs(nConfigs);
+        ASSERT_EGL_TRUE(eglGetConfigs(mDisplay, configs.data(), nConfigs, &nReturnedConfigs));
+        ASSERT_TRUE(nConfigs == nReturnedConfigs);
+
+        for (auto config : configs)
+        {
+            EGLint surfaceType;
+            eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType);
+            if (surfaceType & EGL_PBUFFER_BIT)
+            {
+                mConfig = config;
+                break;
+            }
+        }
+        ASSERT_NE(nullptr, mConfig);
+    }
+
+    void TearDown() override
+    {
+        eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+        if (mContext != EGL_NO_CONTEXT)
+        {
+            eglDestroyContext(mDisplay, mContext);
+        }
+
+        if (mContext != EGL_NO_SURFACE)
+        {
+            eglDestroySurface(mDisplay, mPbuffer);
+        }
+
+        eglTerminate(mDisplay);
+    }
+
+  protected:
+    EGLContext createContext()
+    {
+        const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+
+        mContext = eglCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT, contextAttribs);
+        EXPECT_TRUE(mContext != EGL_NO_CONTEXT);
+        return mContext;
+    }
+
+    EGLSurface createPbuffer(int width, int height)
+    {
+        const EGLint pbufferAttribs[] = {
+            EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE,
+        };
+        mPbuffer = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttribs);
+        EXPECT_TRUE(mPbuffer != EGL_NO_SURFACE);
+        return mPbuffer;
+    }
+
+    void createFramebuffer(GLFramebuffer *fbo, GLTexture *tex) const
+    {
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo->get());
+
+        glBindTexture(GL_TEXTURE_2D, tex->get());
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 500, 500, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->get(), 0);
+        EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    }
+
+    bool checkExtension(bool verbose = true) const
+    {
+        if (!ANGLETest::eglDisplayExtensionEnabled(mDisplay, "EGL_KHR_surfaceless_context"))
+        {
+            if (verbose)
+            {
+                std::cout << "Test skipped because EGL_KHR_surfaceless_context is not available."
+                          << std::endl;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    EGLContext mContext = EGL_NO_CONTEXT;
+    EGLSurface mPbuffer = EGL_NO_SURFACE;
+    EGLConfig mConfig   = 0;
+    EGLDisplay mDisplay = EGL_NO_DISPLAY;
+};
+
+// Test surfaceless MakeCurrent returns the correct value.
+TEST_P(EGLSurfacelessContextTest, MakeCurrentSurfaceless)
+{
+    EGLContext context = createContext();
+
+    if (eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context))
+    {
+        ASSERT_TRUE(checkExtension(false));
+    }
+    else
+    {
+        // The extension allows EGL_BAD_MATCH with the extension too, but ANGLE
+        // shouldn't do that.
+        ASSERT_FALSE(checkExtension(false));
+    }
+}
+
+// Test that the scissor and viewport are set correctly
+TEST_P(EGLSurfacelessContextTest, DefaultScissorAndViewport)
+{
+    if (!checkExtension())
+    {
+        return;
+    }
+
+    EGLContext context = createContext();
+    ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
+
+    GLint scissor[4] = {1, 2, 3, 4};
+    glGetIntegerv(GL_SCISSOR_BOX, scissor);
+    ASSERT_GL_NO_ERROR();
+    ASSERT_EQ(0, scissor[0]);
+    ASSERT_EQ(0, scissor[1]);
+    ASSERT_EQ(0, scissor[2]);
+    ASSERT_EQ(0, scissor[3]);
+
+    GLint viewport[4] = {1, 2, 3, 4};
+    glGetIntegerv(GL_VIEWPORT, viewport);
+    ASSERT_GL_NO_ERROR();
+    ASSERT_EQ(0, viewport[0]);
+    ASSERT_EQ(0, viewport[1]);
+    ASSERT_EQ(0, viewport[2]);
+    ASSERT_EQ(0, viewport[3]);
+}
+
+// Test the CheckFramebufferStatus returns the correct value.
+TEST_P(EGLSurfacelessContextTest, CheckFramebufferStatus)
+{
+    if (!checkExtension())
+    {
+        return;
+    }
+
+    EGLContext context = createContext();
+    ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
+
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_UNDEFINED_OES, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    GLFramebuffer fbo;
+    GLTexture tex;
+    createFramebuffer(&fbo, &tex);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+}
+
+// Test that clearing and readpixels work when done in an FBO.
+TEST_P(EGLSurfacelessContextTest, ClearReadPixelsInFBO)
+{
+    if (!checkExtension())
+    {
+        return;
+    }
+
+    EGLContext context = createContext();
+    ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
+
+    GLFramebuffer fbo;
+    GLTexture tex;
+    createFramebuffer(&fbo, &tex);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR_EQ(250, 250, GLColor::red);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test clear+readpixels in an FBO in surfaceless and in the default FBO in a pbuffer
+TEST_P(EGLSurfacelessContextTest, Switcheroo)
+{
+    if (!checkExtension())
+    {
+        return;
+    }
+
+    EGLContext context = createContext();
+    EGLSurface pbuffer = createPbuffer(500, 500);
+
+    // We need to make the context current to do the one time setup of the FBO
+    ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
+    GLFramebuffer fbo;
+    GLTexture tex;
+    createFramebuffer(&fbo, &tex);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+
+    for (int i = 0; i < 4; ++i)
+    {
+        // Clear to red in the FBO in surfaceless mode
+        ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
+
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        ASSERT_GL_NO_ERROR();
+
+        EXPECT_PIXEL_COLOR_EQ(250, 250, GLColor::red);
+        ASSERT_GL_NO_ERROR();
+
+        // Clear to green in the pbuffer
+        ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, pbuffer, pbuffer, context));
+
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        ASSERT_GL_NO_ERROR();
+
+        EXPECT_PIXEL_COLOR_EQ(250, 250, GLColor::green);
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+}  // anonymous namespace
+
+ANGLE_INSTANTIATE_TEST(EGLSurfacelessContextTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLSyncControlTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLSyncControlTest.cpp
new file mode 100644
index 0000000..8fb65f1
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLSyncControlTest.cpp
@@ -0,0 +1,265 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// EGLSyncControlTest.cpp:
+//   Tests pertaining to eglGetSyncValuesCHROMIUM.
+
+#include <d3d11.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "com_utils.h"
+#include "OSWindow.h"
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLGETSYNCVALUESCHROMIUMPROC)(EGLDisplay dpy,
+                                                                 EGLSurface surface,
+                                                                 EGLuint64KHR *ust,
+                                                                 EGLuint64KHR *msc,
+                                                                 EGLuint64KHR *sbc);
+
+class EGLSyncControlTest : public testing::Test
+{
+  protected:
+    EGLSyncControlTest() {}
+
+    void SetUp() override
+    {
+        mD3D11Module = LoadLibrary(TEXT("d3d11.dll"));
+        if (mD3D11Module == nullptr)
+        {
+            std::cout << "Unable to LoadLibrary D3D11" << std::endl;
+            return;
+        }
+
+        mD3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+            GetProcAddress(mD3D11Module, "D3D11CreateDevice"));
+        if (mD3D11CreateDevice == nullptr)
+        {
+            std::cout << "Could not retrieve D3D11CreateDevice from d3d11.dll" << std::endl;
+            return;
+        }
+
+        mD3D11Available = true;
+
+        const char *extensionString =
+            static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
+        if (strstr(extensionString, "EGL_ANGLE_device_creation"))
+        {
+            if (strstr(extensionString, "EGL_ANGLE_device_creation_d3d11"))
+            {
+                mDeviceCreationD3D11ExtAvailable = true;
+            }
+        }
+
+        eglGetSyncValuesCHROMIUM = reinterpret_cast<PFNEGLGETSYNCVALUESCHROMIUMPROC>(
+            eglGetProcAddress("eglGetSyncValuesCHROMIUM"));
+    }
+
+    void TearDown() override
+    {
+        SafeRelease(mDevice);
+        SafeRelease(mDeviceContext);
+
+        SafeDelete(mOSWindow);
+
+        if (mSurface != EGL_NO_SURFACE)
+        {
+            eglDestroySurface(mDisplay, mSurface);
+            mSurface = EGL_NO_SURFACE;
+        }
+
+        if (mContext != EGL_NO_CONTEXT)
+        {
+            eglDestroyContext(mDisplay, mContext);
+            mContext = EGL_NO_CONTEXT;
+        }
+
+        if (mDisplay != EGL_NO_DISPLAY)
+        {
+            eglTerminate(mDisplay);
+            mDisplay = EGL_NO_DISPLAY;
+        }
+    }
+
+    void CreateD3D11Device()
+    {
+        ASSERT_TRUE(mD3D11Available);
+        ASSERT_EQ(nullptr, mDevice);  // The device shouldn't be created twice
+
+        HRESULT hr =
+            mD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, 0, nullptr, 0,
+                               D3D11_SDK_VERSION, &mDevice, &mFeatureLevel, &mDeviceContext);
+
+        ASSERT_TRUE(SUCCEEDED(hr));
+    }
+
+    void InitializeDisplay()
+    {
+        EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE,
+                                   EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+                                   EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
+                                   EGL_DONT_CARE,
+                                   EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,
+                                   EGL_DONT_CARE,
+                                   EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
+                                   EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
+                                   EGL_NONE};
+
+        // Create an OS Window
+        mOSWindow = CreateOSWindow();
+        mOSWindow->initialize("EGLSyncControlTest", 64, 64);
+        mOSWindow->setVisible(true);
+
+        // Create an EGLDisplay using the EGLDevice
+        mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
+                                            reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
+                                            displayAttribs);
+        ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
+
+        EGLint majorVersion, minorVersion;
+        ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE);
+    }
+
+    void CreateWindowSurface()
+    {
+        eglBindAPI(EGL_OPENGL_ES_API);
+        ASSERT_EGL_SUCCESS();
+
+        // Choose a config
+        const EGLint configAttributes[] = {EGL_NONE};
+
+        EGLint configCount = 0;
+        ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, configAttributes, &mConfig, 1, &configCount));
+
+        const EGLint surfaceAttributes[] = {EGL_DIRECT_COMPOSITION_ANGLE, EGL_TRUE, EGL_NONE};
+
+        // Create window surface
+        mSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),
+                                          surfaceAttributes);
+        if (mSurface == nullptr)
+        {
+            std::cout << "Unable to create window surface with Direct Composition" << std::endl;
+            return;
+        }
+
+        mDirectCompositionSurfaceAvailable = true;
+
+        // Create EGL context
+        EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+
+        mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
+        ASSERT_EGL_SUCCESS();
+
+        // Make the surface current
+        eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
+        ASSERT_EGL_SUCCESS();
+    }
+
+    bool mD3D11Available                       = false;
+    HMODULE mD3D11Module                       = nullptr;
+    PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice = nullptr;
+
+    ID3D11Device *mDevice               = nullptr;
+    ID3D11DeviceContext *mDeviceContext = nullptr;
+    D3D_FEATURE_LEVEL mFeatureLevel;
+
+    bool mDeviceCreationD3D11ExtAvailable = false;
+
+    bool mDirectCompositionSurfaceAvailable = false;
+
+    OSWindow *mOSWindow = nullptr;
+
+    EGLDisplay mDisplay                                      = EGL_NO_DISPLAY;
+    EGLSurface mSurface                                      = EGL_NO_SURFACE;
+    EGLContext mContext                                      = EGL_NO_CONTEXT;
+    EGLConfig mConfig                                        = 0;
+    PFNEGLGETSYNCVALUESCHROMIUMPROC eglGetSyncValuesCHROMIUM = nullptr;
+};
+
+// Basic test for eglGetSyncValuesCHROMIUM extension. Verifies that eglGetSyncValuesCHROMIUM
+// can be called on DX11 with direct composition and that it returns reasonable enough values.
+TEST_F(EGLSyncControlTest, DISABLED_SyncValuesTest)
+{
+    static const DWORD kPollInterval    = 10;
+    static const int kNumPollIterations = 100;
+
+    if (!mD3D11Available)
+    {
+        std::cout << "D3D11 not available, skipping test" << std::endl;
+        return;
+    }
+
+    CreateD3D11Device();
+    InitializeDisplay();
+    CreateWindowSurface();
+
+    if (!mDirectCompositionSurfaceAvailable)
+    {
+        std::cout << "Direct Composition surface not available, skipping test" << std::endl;
+        return;
+    }
+
+    const char *extensionString =
+        static_cast<const char *>(eglQueryString(mDisplay, EGL_EXTENSIONS));
+    ASSERT_TRUE(strstr(extensionString, "EGL_CHROMIUM_sync_control"));
+
+    EGLuint64KHR ust = 0, msc = 0, sbc = 0;
+    // It appears there is a race condition so the very first call to eglGetSyncValuesCHROMIUM
+    // can fail within D3D with DXGI_ERROR_FRAME_STATISTICS_DISJOINT.
+    // Should that be handled inside eglGetSyncValuesCHROMIUM?
+    eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust, &msc, &sbc);
+
+    ASSERT_EGL_TRUE(eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust, &msc, &sbc));
+    // Initial msc and sbc value should be true. Initial ust value is unspecified.
+    ASSERT_EQ(0ull, msc);
+    ASSERT_EQ(0ull, sbc);
+
+    // Perform some very basic rendering.
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mSurface));
+
+    // Poll until sbc value increases. Normally it should change within 16-17 ms.
+    for (int i = 0; i < kNumPollIterations; i++)
+    {
+        ::Sleep(kPollInterval);
+        ASSERT_EGL_TRUE(eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust, &msc, &sbc));
+        if (sbc > 0)
+            break;
+    }
+
+    // sbc should change to 1. msc and ust to some non-zero values.
+    ASSERT_EQ(1ull, sbc);
+    ASSERT_GT(ust, 0ull);
+    ASSERT_GT(msc, 0ull);
+
+    // Perform more rendering.
+    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mSurface));
+
+    // Poll until sbc value increases. Normally it should change within 16-17 ms.
+    EGLuint64KHR ust2 = 0, msc2 = 0, sbc2 = 0;
+    for (int i = 0; i < kNumPollIterations; i++)
+    {
+        ::Sleep(kPollInterval);
+        ASSERT_EGL_TRUE(eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust2, &msc2, &sbc2));
+        if (sbc2 > sbc)
+            break;
+    }
+
+    // sbc2 should be 2. msc2 and ust2 should be greater than previous msc and ust values.
+    ASSERT_EQ(2ull, sbc2);
+    ASSERT_GT(ust2, ust);
+    ASSERT_GT(msc2, msc);
+}
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLThreadTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLThreadTest.cpp
new file mode 100644
index 0000000..8280931
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLThreadTest.cpp
@@ -0,0 +1,84 @@
+#include "gtest/gtest.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+typedef EGLDisplay EGLAPIENTRY EGLGetDisplay(EGLNativeDisplayType display_id);
+typedef EGLBoolean EGLAPIENTRY EGLInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
+typedef EGLContext EGLAPIENTRY EGLGetCurrentContext(void);
+typedef EGLSurface EGLAPIENTRY EGLGetCurrentSurface(EGLint readdraw);
+typedef EGLBoolean EGLAPIENTRY EGLTerminate(EGLDisplay dpy);
+
+class EGLThreadTest : public testing::Test
+{
+  public:
+    virtual void SetUp() {}
+    virtual void TearDown() {}
+
+    EGLGetDisplay *mGetDisplay;
+    EGLInitialize *mInitialize;
+    EGLGetCurrentContext *mGetCurrentContext;
+    EGLGetCurrentSurface *mGetCurrentSurface;
+
+    EGLDisplay mDisplay;
+
+    HMODULE mEGL;
+    HMODULE mGLESv2;
+
+    static DWORD WINAPI ThreadingTestEntryPoint(LPVOID thisPointer);
+
+  private:
+    void ThreadingTest();
+};
+
+DWORD WINAPI EGLThreadTest::ThreadingTestEntryPoint(LPVOID lpParameter)
+{
+    EGLThreadTest *test = (EGLThreadTest *)lpParameter;
+    test->ThreadingTest();
+    return 0;
+}
+
+void EGLThreadTest::ThreadingTest()
+{
+    mEGL = LoadLibrary(TEXT("libEGL.dll"));
+    mGLESv2 = LoadLibrary(TEXT("libGLESv2.dll"));
+
+    EXPECT_TRUE(mEGL != nullptr);
+    EXPECT_TRUE(mGLESv2 != nullptr);
+
+    mGetDisplay = (EGLGetDisplay *)GetProcAddress(mEGL, "eglGetDisplay");
+    mInitialize = (EGLInitialize *)GetProcAddress(mEGL, "eglInitialize");
+    mGetCurrentContext = (EGLGetCurrentContext *)GetProcAddress(mEGL, "eglGetCurrentContext");
+    mGetCurrentSurface = (EGLGetCurrentSurface *)GetProcAddress(mEGL, "eglGetCurrentSurface");
+
+    EXPECT_TRUE(mGetDisplay != nullptr);
+    EXPECT_TRUE(mInitialize != nullptr);
+    EXPECT_TRUE(mGetCurrentContext != nullptr);
+    EXPECT_TRUE(mGetCurrentSurface != nullptr);
+
+    mDisplay = mGetDisplay(EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE);
+
+    EXPECT_TRUE(mDisplay!= EGL_NO_DISPLAY);
+
+    mInitialize(mDisplay, nullptr, nullptr);
+    mGetCurrentContext();
+}
+
+TEST_F(EGLThreadTest, thread_init_crash)
+{
+    DWORD threadId;
+    HANDLE threadHandle =
+        CreateThread(nullptr, 0, EGLThreadTest::ThreadingTestEntryPoint, this, 0, &threadId);
+    EXPECT_TRUE(threadHandle != nullptr);
+
+    // wait for signal from thread
+    DWORD waitResult = WaitForSingleObject(threadHandle, 1000);
+    EXPECT_EQ(waitResult, WAIT_OBJECT_0);
+
+    // crash, because the TLS value is NULL on main thread
+    mGetCurrentSurface(EGL_DRAW);
+    mGetCurrentContext();
+
+    auto terminate = (EGLTerminate *)GetProcAddress(mEGL, "eglTerminate");
+    terminate(mDisplay);
+}
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLVulkanEXTTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLVulkanEXTTest.cpp
new file mode 100644
index 0000000..b18da6a
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLVulkanEXTTest.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 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.
+//
+// VulkanEXTTest:
+//   Tests specific to the ANGLE Vulkan extension.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class VulkanEXTTest : public ANGLETest
+{
+  public:
+    VulkanEXTTest() {}
+
+    // Intentionally do not call base class so we can run EGL in the tests.
+    void SetUp() override {}
+};
+
+// ANGLE requires that the vulkan validation layers are available.
+TEST_P(VulkanEXTTest, ValidationLayersAvailable)
+{
+    setVulkanLayersEnabled(true);
+    ASSERT_TRUE(getEGLWindow()->initializeGL(GetOSWindow()));
+}
+
+ANGLE_INSTANTIATE_TEST(VulkanEXTTest, ES2_VULKAN());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/egl_tests/EGLX11VisualTest.cpp b/src/third_party/angle/src/tests/egl_tests/EGLX11VisualTest.cpp
new file mode 100644
index 0000000..5464bd3
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/EGLX11VisualTest.cpp
@@ -0,0 +1,213 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLX11VisualTest.cpp: tests for EGL_ANGLE_x11_visual extension
+
+#include <gtest/gtest.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <X11/Xlib.h>
+
+#include "OSWindow.h"
+#include "test_utils/ANGLETest.h"
+#include "x11/X11Window.h"
+
+using namespace angle;
+
+namespace
+{
+
+const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+}
+
+class EGLX11VisualHintTest : public ::testing::TestWithParam<angle::PlatformParameters>
+{
+  public:
+    void SetUp() override
+    {
+        mEglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
+            eglGetProcAddress("eglGetPlatformDisplayEXT"));
+
+        mDisplay = XOpenDisplay(nullptr);
+    }
+
+    std::vector<EGLint> getDisplayAttributes(int visualId) const
+    {
+        std::vector<EGLint> attribs;
+
+        attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+        attribs.push_back(GetParam().getRenderer());
+        attribs.push_back(EGL_X11_VISUAL_ID_ANGLE);
+        attribs.push_back(visualId);
+        attribs.push_back(EGL_NONE);
+
+        return attribs;
+    }
+
+    unsigned int chooseDifferentVisual(unsigned int visualId)
+    {
+        int numVisuals;
+        XVisualInfo visualTemplate;
+        visualTemplate.screen = DefaultScreen(mDisplay);
+
+        XVisualInfo *visuals =
+            XGetVisualInfo(mDisplay, VisualScreenMask, &visualTemplate, &numVisuals);
+        EXPECT_TRUE(numVisuals >= 2);
+
+        for (int i = 0; i < numVisuals; ++i)
+        {
+            if (visuals[i].visualid != visualId)
+            {
+                int result = visuals[i].visualid;
+                XFree(visuals);
+                return result;
+            }
+        }
+
+        UNREACHABLE();
+        return -1;
+    }
+
+  protected:
+    PFNEGLGETPLATFORMDISPLAYEXTPROC mEglGetPlatformDisplayEXT;
+    Display *mDisplay;
+};
+
+// Test that display creation fails if the visual ID passed in invalid.
+TEST_P(EGLX11VisualHintTest, InvalidVisualID)
+{
+    static const int gInvalidVisualId = -1;
+    auto attributes                   = getDisplayAttributes(gInvalidVisualId);
+
+    EGLDisplay display =
+        mEglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, attributes.data());
+    ASSERT_TRUE(display != EGL_NO_DISPLAY);
+
+    ASSERT_TRUE(EGL_FALSE == eglInitialize(display, nullptr, nullptr));
+    ASSERT_EGL_ERROR(EGL_NOT_INITIALIZED);
+}
+
+// Test that context creation with a visual ID succeeds, that the context exposes
+// only one config, and that a clear on a surface with this config works.
+TEST_P(EGLX11VisualHintTest, ValidVisualIDAndClear)
+{
+    // We'll test the extension with one visual ID but we don't care which one. This means we
+    // can use OSWindow to create a window and just grab its visual.
+    OSWindow *osWindow = CreateOSWindow();
+    osWindow->initialize("EGLX11VisualHintTest", 500, 500);
+    osWindow->setVisible(true);
+
+    Window xWindow = osWindow->getNativeWindow();
+
+    XWindowAttributes windowAttributes;
+    ASSERT_NE(0, XGetWindowAttributes(mDisplay, xWindow, &windowAttributes));
+    int visualId = windowAttributes.visual->visualid;
+
+    auto attributes = getDisplayAttributes(visualId);
+    EGLDisplay display =
+        mEglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, attributes.data());
+    ASSERT_NE(EGL_NO_DISPLAY, display);
+
+    ASSERT_TRUE(EGL_TRUE == eglInitialize(display, nullptr, nullptr));
+
+    // While this is not required by the extension, test that our implementation returns only one
+    // config, with the same native visual Id that we provided.
+    int nConfigs = 0;
+    ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, nullptr, 0, &nConfigs));
+    ASSERT_EQ(1, nConfigs);
+
+    int nReturnedConfigs = 0;
+    EGLConfig config;
+    ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, &config, 1, &nReturnedConfigs));
+    ASSERT_EQ(nConfigs, nReturnedConfigs);
+
+    EGLint eglNativeId;
+    ASSERT_TRUE(EGL_TRUE == eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &eglNativeId));
+    ASSERT_EQ(visualId, eglNativeId);
+
+    // Finally, try to do a clear on the window.
+    EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
+    ASSERT_NE(EGL_NO_CONTEXT, context);
+
+    EGLSurface window = eglCreateWindowSurface(display, config, xWindow, nullptr);
+    ASSERT_EGL_SUCCESS();
+
+    eglMakeCurrent(display, window, window, context);
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, 500, 500);
+    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(250, 250, 0, 0, 255, 255);
+
+    // Teardown
+    eglDestroySurface(display, window);
+    ASSERT_EGL_SUCCESS();
+
+    eglDestroyContext(display, context);
+    ASSERT_EGL_SUCCESS();
+
+    SafeDelete(osWindow);
+
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(display);
+}
+
+// Test that EGL_BAD_MATCH is generated when trying to create an EGL window from
+// an X11 window whose visual ID doesn't match the visual ID passed at display creation.
+TEST_P(EGLX11VisualHintTest, InvalidWindowVisualID)
+{
+    // Get the default visual ID, as a good guess of a visual id for which display
+    // creation will succeed.
+    int visualId;
+    {
+        OSWindow *osWindow = CreateOSWindow();
+        osWindow->initialize("EGLX11VisualHintTest", 500, 500);
+        osWindow->setVisible(true);
+
+        Window xWindow = osWindow->getNativeWindow();
+
+        XWindowAttributes windowAttributes;
+        ASSERT_NE(0, XGetWindowAttributes(mDisplay, xWindow, &windowAttributes));
+        visualId = windowAttributes.visual->visualid;
+
+        SafeDelete(osWindow);
+    }
+
+    auto attributes = getDisplayAttributes(visualId);
+    EGLDisplay display =
+        mEglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, attributes.data());
+    ASSERT_NE(EGL_NO_DISPLAY, display);
+
+    ASSERT_TRUE(EGL_TRUE == eglInitialize(display, nullptr, nullptr));
+
+
+    // Initialize the window with a visual id different from the display's visual id
+    int otherVisualId = chooseDifferentVisual(visualId);
+    ASSERT_NE(visualId, otherVisualId);
+
+    OSWindow *osWindow = new X11Window(otherVisualId);
+    osWindow->initialize("EGLX11VisualHintTest", 500, 500);
+    osWindow->setVisible(true);
+
+    Window xWindow = osWindow->getNativeWindow();
+
+    // Creating the EGL window should fail with EGL_BAD_MATCH
+    int nReturnedConfigs = 0;
+    EGLConfig config;
+    ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, &config, 1, &nReturnedConfigs));
+    ASSERT_EQ(1, nReturnedConfigs);
+
+    EGLSurface window = eglCreateWindowSurface(display, config, xWindow, nullptr);
+    ASSERT_EQ(EGL_NO_SURFACE, window);
+    ASSERT_EGL_ERROR(EGL_BAD_MATCH);
+
+    SafeDelete(osWindow);
+}
+
+ANGLE_INSTANTIATE_TEST(EGLX11VisualHintTest, ES2_OPENGL());
diff --git a/src/third_party/angle/src/tests/egl_tests/media/yuvtest.inl b/src/third_party/angle/src/tests/egl_tests/media/yuvtest.inl
new file mode 100644
index 0000000..7271cf8
--- /dev/null
+++ b/src/third_party/angle/src/tests/egl_tests/media/yuvtest.inl
@@ -0,0 +1,1548 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by scripts/bmp_to_yuv.py using data from yuvtest.bmp
+//
+// Copyright 2016 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.
+
+static const size_t yuvtest_width = 128;
+static const size_t yuvtest_height = 128;
+static const unsigned char yuvtest_data[] =
+{
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,132,16,16,16,16,105,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,23,16,16,16,16,16,16,44,153,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,16,16,16,16,16,16,16,16,16,78,228,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,16,16,16,173,44,16,16,16,16,16,16,44,153,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,16,16,16,228,235,235,221,112,16,16,16,16,16,78,228,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,37,16,16,92,235,235,235,235,153,44,16,16,16,16,16,
+    92,228,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,212,186,186,186,186,186,186,186,186,186,203,234,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,146,16,16,16,235,235,235,235,235,235,221,112,16,16,16,
+    16,16,16,92,228,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,219,187,160,150,150,150,140,127,121,121,121,
+    152,186,186,186,186,186,186,186,186,186,186,186,186,186,203,234,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,16,16,16,105,235,235,235,235,235,235,235,153,44,16,
+    16,16,16,16,78,228,235,235,235,235,235,235,235,235,235,219,
+    187,160,150,150,150,150,150,149,132,121,121,121,121,121,121,152,
+    186,186,186,186,186,186,186,185,154,134,134,134,134,134,134,134,
+    134,134,134,169,232,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,213,171,135,120,120,120,120,120,120,120,
+    120,120,120,120,120,167,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,232,
+    172,134,27,16,16,16,130,134,134,134,134,134,134,134,169,151,
+    44,16,16,16,16,44,153,235,235,235,235,235,219,187,160,150,
+    150,150,150,150,150,150,149,129,121,121,121,121,121,121,121,185,
+    186,186,185,146,121,121,122,131,134,134,134,134,134,134,134,134,
+    134,134,134,134,134,134,134,134,169,232,235,235,235,235,235,235,
+    235,235,235,235,231,156,120,120,120,120,120,120,120,120,120,120,
+    120,120,120,120,120,124,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,187,134,
+    134,134,101,24,16,16,57,134,134,134,134,134,134,134,134,134,
+    134,134,75,16,16,16,16,78,228,219,187,160,150,150,150,150,
+    150,150,150,150,150,148,134,121,121,121,121,136,172,225,212,186,
+    186,186,163,150,150,149,138,134,134,134,134,134,134,134,134,134,
+    134,134,134,134,134,134,134,134,134,134,134,169,232,235,235,235,
+    235,235,213,171,135,120,120,120,120,120,120,120,120,120,120,120,
+    120,120,120,120,135,192,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,137,134,
+    134,134,134,86,16,16,16,134,134,134,134,134,134,134,134,134,
+    134,134,134,86,24,16,16,16,45,129,150,150,150,150,150,158,
+    184,214,235,235,172,121,121,121,121,178,235,235,235,235,188,186,
+    186,188,200,158,149,139,134,134,134,143,158,136,121,121,121,121,
+    146,178,166,140,134,134,134,134,134,134,134,134,147,197,199,142,
+    120,120,120,120,120,120,120,164,206,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,134,134,
+    134,194,235,235,37,16,16,166,235,235,235,235,235,197,147,134,
+    134,134,134,134,126,68,16,16,16,20,87,150,158,184,214,235,
+    235,235,235,199,125,121,121,125,181,235,235,235,235,226,186,186,
+    186,217,235,232,155,134,134,134,141,150,150,174,225,178,136,121,
+    121,121,154,186,186,186,200,196,147,134,134,134,130,123,120,120,
+    120,120,120,120,120,131,185,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,134,134,
+    134,235,235,235,112,16,16,57,235,235,235,235,235,235,235,235,
+    235,235,206,147,134,134,82,20,16,16,16,72,228,235,235,235,
+    235,232,157,121,121,121,125,225,235,235,235,235,235,203,186,186,
+    202,235,232,163,134,134,134,161,155,150,150,150,174,232,235,235,
+    228,172,121,151,186,186,186,165,113,111,120,122,120,120,120,120,
+    120,120,135,167,206,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,134,134,
+    134,235,235,235,215,16,16,16,235,235,235,235,235,235,235,235,
+    235,235,235,235,145,136,134,115,42,16,16,16,78,228,235,235,
+    235,172,121,121,121,125,181,235,235,235,235,235,235,188,186,186,
+    226,232,163,134,134,134,184,235,230,187,150,150,150,160,203,235,
+    231,158,111,111,149,186,186,186,151,119,120,120,120,120,121,126,
+    133,142,231,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,233,169,189,
+    189,189,189,189,189,16,16,16,87,189,189,189,195,217,235,235,
+    235,235,235,235,150,150,150,167,134,71,16,16,16,71,228,235,
+    235,125,121,121,168,225,235,235,235,235,235,235,235,186,186,186,
+    232,163,134,134,134,184,235,235,235,235,192,150,150,150,148,130,
+    111,111,111,111,111,149,166,133,120,120,120,120,120,121,133,134,
+    134,134,134,152,232,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,233,202,189,189,
+    189,189,189,189,189,32,16,16,16,87,189,189,189,189,195,217,
+    235,235,235,235,150,150,150,235,184,134,75,16,16,16,20,77,
+    121,98,121,121,235,235,235,235,235,235,235,235,212,186,186,185,
+    163,134,134,134,184,235,235,235,235,235,235,200,153,126,111,111,
+    111,111,111,125,148,134,120,120,120,120,121,152,224,200,129,132,
+    134,134,134,134,137,232,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,233,202,189,189,189,
+    189,189,189,189,189,140,27,16,16,16,189,189,189,189,189,189,
+    195,217,235,235,150,150,150,235,235,194,147,75,16,16,16,16,
+    16,16,52,157,235,235,235,235,235,235,235,235,188,186,185,149,
+    134,134,134,184,235,235,235,235,235,235,235,235,163,111,111,111,
+    112,118,127,120,120,120,120,120,122,150,139,121,153,235,235,206,
+    140,134,134,134,134,134,175,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,233,202,189,189,189,161,
+    134,134,134,235,235,235,173,16,16,16,235,232,212,192,189,189,
+    189,189,189,189,189,189,176,233,235,235,235,216,109,31,16,16,
+    16,16,16,152,235,235,235,235,235,235,235,235,186,185,149,134,
+    134,134,184,235,235,235,235,235,235,235,231,158,111,111,115,120,
+    120,120,120,120,120,120,131,159,180,186,174,121,121,199,235,235,
+    235,227,144,134,134,134,134,146,231,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,220,198,189,189,189,212,197,
+    134,134,134,163,235,235,235,37,16,16,166,235,235,232,212,192,
+    189,189,189,189,189,189,189,189,189,189,205,233,235,184,119,89,
+    49,16,16,37,153,235,235,235,235,235,235,234,170,144,134,134,
+    134,184,235,235,235,235,235,235,235,231,146,112,116,120,120,120,
+    120,120,120,128,167,206,235,231,186,186,186,123,121,143,235,235,
+    235,235,223,122,132,134,134,134,137,228,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,210,189,189,189,189,212,235,235,
+    144,134,134,134,203,235,235,112,16,16,57,235,235,235,235,232,
+    212,195,189,189,189,189,189,189,189,189,189,189,194,208,165,133,
+    123,20,16,16,16,59,225,235,235,235,232,157,134,134,134,134,
+    184,235,235,235,235,235,235,235,235,153,117,120,120,120,120,120,
+    123,132,142,150,174,235,235,235,191,186,186,165,121,121,199,235,
+    235,235,235,196,129,132,134,134,134,139,232,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,213,189,189,189,191,213,235,235,235,
+    206,147,134,134,134,175,235,215,23,16,16,166,235,235,235,235,
+    235,235,235,179,150,164,187,189,189,189,189,189,189,189,189,183,
+    165,111,24,16,16,16,57,225,235,235,166,135,169,189,189,189,
+    189,189,189,189,189,189,185,171,127,120,120,120,120,120,135,188,
+    208,155,150,150,150,208,235,235,215,186,186,186,121,121,143,232,
+    235,235,235,235,235,229,151,134,134,134,163,232,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,191,189,189,191,231,235,235,235,235,
+    235,225,137,134,134,134,235,235,112,16,16,57,228,235,235,235,
+    235,235,235,152,150,150,219,235,235,217,195,189,189,189,189,189,
+    189,189,178,92,16,16,16,16,57,140,135,173,189,189,189,189,
+    189,189,189,189,180,148,125,120,120,120,120,120,149,199,235,235,
+    235,230,179,150,150,166,235,235,235,186,186,186,125,121,121,161,
+    235,235,235,235,235,235,235,122,134,134,134,169,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,189,189,189,217,235,235,235,235,235,
+    235,235,203,134,134,134,170,217,215,23,16,16,92,235,235,235,
+    235,235,235,150,150,150,235,235,235,235,235,235,227,177,180,189,
+    189,189,189,189,102,16,16,16,16,57,169,189,189,189,189,189,
+    189,189,170,140,120,120,120,120,120,122,146,178,233,235,235,235,
+    235,235,227,152,150,150,195,235,235,186,186,186,189,121,121,121,
+    235,235,235,235,235,235,235,111,122,134,134,134,160,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,189,189,189,235,235,235,235,235,235,
+    235,235,235,144,134,134,134,149,185,127,16,16,16,105,235,235,
+    235,235,235,150,150,150,235,235,235,235,235,235,235,125,121,135,
+    200,191,189,189,189,124,38,16,16,16,124,178,172,143,156,149,
+    139,120,120,120,120,120,120,128,156,185,189,189,195,176,95,95,
+    152,235,235,195,150,150,152,222,235,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,111,111,132,134,134,134,213,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,233,189,189,189,235,235,235,235,235,235,
+    235,235,235,203,139,134,134,134,152,186,33,16,16,16,235,235,
+    235,235,235,150,150,150,235,235,235,235,235,235,228,121,121,121,
+    208,189,189,189,189,189,189,32,23,58,107,120,120,120,120,120,
+    120,120,120,120,120,149,150,111,111,152,189,189,189,189,163,97,
+    95,95,95,152,168,150,150,168,235,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,111,111,117,147,134,134,182,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,210,189,189,191,235,235,235,235,235,235,
+    235,235,235,235,229,177,134,134,134,149,138,16,16,16,78,235,
+    235,235,235,150,150,150,235,235,235,235,235,235,192,121,121,158,
+    189,189,189,189,189,189,180,126,115,120,120,120,120,120,120,120,
+    120,120,123,134,203,235,115,111,111,176,216,192,189,189,189,163,
+    97,95,95,95,224,152,150,150,208,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,111,111,111,210,134,134,140,197,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,191,189,189,213,235,235,235,235,235,235,
+    235,235,235,235,235,235,144,134,134,134,170,32,16,16,16,144,
+    234,235,235,150,150,150,235,235,235,235,235,235,153,121,127,189,
+    189,189,201,213,162,128,120,120,120,120,120,117,101,140,156,172,
+    173,166,148,134,137,187,111,111,111,235,235,232,210,189,189,189,
+    163,97,95,95,235,187,150,150,166,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,111,111,111,235,144,134,134,134,163,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,233,189,189,189,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,206,147,134,134,146,138,37,16,16,48,
+    194,234,235,150,150,150,235,235,235,235,235,235,125,146,185,189,
+    185,165,139,121,120,120,120,120,120,127,68,23,16,21,108,189,
+    189,189,189,189,189,189,182,154,132,175,210,235,235,212,189,189,
+    189,157,95,95,235,227,152,150,150,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,111,111,111,235,210,140,134,134,134,
+    203,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,210,189,189,191,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,225,137,134,134,157,174,21,16,16,
+    64,187,217,150,150,150,235,235,235,235,235,233,168,174,156,136,
+    120,120,120,120,120,120,120,138,165,212,160,21,16,16,16,65,
+    184,189,189,189,189,189,189,189,188,173,160,146,134,147,193,189,
+    189,189,95,95,235,235,192,150,150,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,123,111,115,235,235,229,169,134,134,
+    153,232,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,191,189,189,213,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,194,134,134,134,147,123,16,16,
+    16,64,186,182,163,150,235,235,235,235,235,178,134,120,120,120,
+    120,120,120,120,124,154,178,189,189,235,235,163,53,16,16,16,
+    70,184,189,189,189,189,189,189,189,189,189,189,182,154,134,184,
+    189,189,142,96,235,235,232,166,150,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,200,142,188,235,235,235,225,137,134,
+    134,163,232,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,184,134,134,134,134,89,16,
+    16,16,133,186,186,178,227,235,235,199,139,120,120,120,120,120,
+    120,123,127,170,235,227,189,189,189,235,235,215,186,96,16,16,
+    16,69,189,189,191,128,150,179,189,189,189,189,189,189,182,181,
+    189,189,179,123,232,235,235,219,150,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,194,134,
+    134,134,169,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,194,140,134,134,134,90,
+    16,16,49,181,186,186,188,183,142,120,120,120,120,122,124,128,
+    133,134,184,235,233,201,189,189,204,235,235,235,191,186,101,16,
+    16,16,139,189,189,172,113,111,229,217,207,192,189,189,189,189,
+    189,189,189,151,134,169,232,235,150,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,184,
+    134,134,134,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,229,144,134,134,123,
+    20,16,16,59,168,150,129,120,120,120,120,122,148,133,134,134,
+    134,184,235,235,210,189,189,189,227,235,235,235,215,186,186,86,
+    16,16,36,125,189,189,167,113,235,235,235,232,212,192,189,189,
+    189,189,189,184,166,148,162,181,150,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    134,134,134,197,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,203,140,134,134,
+    86,35,75,107,120,120,120,120,120,122,150,183,148,134,134,137,
+    187,235,235,235,191,189,189,212,235,235,235,235,235,211,186,170,
+    21,16,16,16,65,189,189,167,233,235,235,235,235,232,210,184,
+    189,189,189,189,189,189,182,156,148,186,186,186,235,121,121,121,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    144,134,134,134,163,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,227,189,189,189,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,229,179,133,
+    124,120,120,120,120,120,120,127,150,183,189,168,134,134,131,225,
+    235,235,235,235,189,189,189,235,235,235,235,235,235,235,217,192,
+    143,28,16,16,16,135,189,189,202,235,235,235,235,152,95,105,
+    137,176,189,189,189,189,189,189,189,189,189,184,165,121,121,121,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    203,140,134,134,134,232,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,205,189,189,204,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,192,122,
+    120,120,120,120,111,93,182,189,189,189,169,134,134,134,176,189,
+    227,235,235,235,189,189,189,235,235,235,235,235,235,235,235,235,
+    235,209,84,16,16,41,189,189,189,167,150,150,150,150,150,150,
+    150,153,189,189,189,186,189,189,189,189,189,189,173,131,122,125,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,229,144,134,134,169,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,191,189,189,227,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,213,171,135,120,120,
+    120,120,106,42,16,16,76,189,189,175,134,134,134,160,186,186,
+    186,212,235,235,189,189,189,187,160,150,150,150,150,150,150,150,
+    150,150,137,20,16,16,88,189,189,186,153,150,150,150,150,150,
+    150,150,189,189,189,126,157,185,189,189,189,189,189,182,155,191,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,194,134,134,134,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,231,156,120,120,120,120,120,
+    139,202,137,75,16,16,16,184,189,134,134,134,163,186,186,186,
+    186,186,194,217,189,189,189,150,150,150,150,150,150,150,150,150,
+    150,150,150,95,16,16,19,151,189,189,175,149,132,121,121,121,
+    121,121,189,189,189,162,186,186,186,182,164,189,189,189,189,185,
+    225,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,134,134,134,232,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,231,153,120,120,120,120,131,174,
+    231,235,203,147,27,16,16,65,184,134,134,184,235,199,137,172,
+    186,186,186,186,189,189,189,150,150,150,150,150,150,150,150,150,
+    150,160,174,192,58,16,16,42,189,189,189,132,121,121,121,121,
+    121,121,189,189,189,186,186,186,186,152,136,179,188,189,189,189,
+    188,176,232,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,144,134,134,169,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,231,164,120,120,120,120,164,206,235,235,
+    235,235,235,235,125,16,16,16,65,134,160,235,235,235,199,129,
+    152,182,186,186,189,189,189,182,214,235,235,235,235,235,235,235,
+    235,235,235,235,198,19,16,16,99,189,189,179,134,134,134,134,
+    134,134,189,189,189,134,134,134,134,134,134,134,137,161,188,189,
+    189,189,173,197,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,194,134,134,134,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,231,164,120,120,120,120,120,177,235,235,235,235,
+    235,235,235,235,175,76,16,16,16,97,134,147,197,235,235,225,
+    149,127,158,186,189,189,189,188,212,225,235,235,235,235,235,232,
+    172,134,134,134,134,75,16,16,20,161,189,189,146,134,134,134,
+    134,134,189,189,189,134,134,134,134,134,134,134,134,134,146,182,
+    189,189,189,184,178,222,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,134,134,134,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,235,
+    235,235,235,199,142,120,120,120,120,135,188,235,235,235,235,235,
+    235,235,235,216,134,154,87,16,16,38,130,134,134,163,229,174,
+    150,146,128,154,189,189,189,186,186,186,205,235,235,232,172,134,
+    134,134,134,134,134,130,38,16,16,49,184,189,163,134,134,134,
+    134,134,189,189,189,134,134,134,134,134,134,134,134,134,134,137,
+    172,189,189,189,189,189,190,208,224,235,235,235,235,235,235,235,
+    235,235,235,235,134,134,134,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,235,
+    235,231,156,120,120,120,120,135,188,235,235,235,235,235,235,235,
+    235,235,175,134,134,173,173,21,16,16,49,134,134,134,136,143,
+    150,150,184,177,189,189,189,186,186,186,186,170,229,163,134,134,
+    134,134,134,134,134,131,100,19,16,16,65,189,190,186,186,186,
+    186,175,189,189,189,235,235,235,235,235,235,235,229,184,147,134,
+    134,156,182,189,189,189,189,189,189,202,233,235,235,235,235,235,
+    235,235,235,235,134,134,134,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,189,189,189,235,235,235,235,235,235,235,235,235,
+    231,153,120,120,120,120,115,111,111,111,111,111,111,111,154,231,
+    235,216,134,134,134,188,189,118,16,16,16,102,134,134,134,134,
+    136,170,235,235,189,189,189,146,180,186,185,154,134,134,134,134,
+    147,194,199,142,111,111,111,83,16,16,16,135,189,188,186,192,
+    173,95,189,189,189,231,235,235,235,235,235,235,235,235,235,235,
+    229,179,134,144,165,182,189,189,189,189,173,169,232,235,235,235,
+    235,235,235,235,134,134,134,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,189,189,189,233,235,235,235,235,235,235,235,231,
+    153,120,120,120,117,112,111,111,111,111,111,111,111,111,111,111,
+    111,140,134,134,147,189,189,189,71,16,16,41,139,134,134,134,
+    134,134,134,169,189,189,189,192,152,182,157,134,134,134,134,149,
+    121,121,121,114,111,111,113,234,92,16,16,49,184,189,207,235,
+    235,165,189,189,189,134,235,235,235,235,235,235,235,235,235,235,
+    235,235,197,147,134,134,144,169,189,189,189,189,189,170,135,147,
+    197,235,235,235,134,134,134,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,194,189,189,202,233,235,235,235,235,235,199,142,
+    120,120,120,115,111,111,111,111,111,111,111,111,111,111,111,111,
+    115,134,134,134,115,189,189,189,102,19,16,16,16,51,147,138,
+    134,134,134,134,189,189,189,235,235,186,134,134,134,140,165,168,
+    121,121,114,111,111,111,176,208,170,21,16,16,65,184,199,235,
+    235,235,189,189,189,95,169,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,197,147,161,189,189,189,189,189,184,166,
+    148,163,235,235,134,134,134,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,216,189,189,189,202,233,235,235,231,156,120,120,
+    120,120,117,111,111,176,235,235,235,235,235,235,235,188,127,124,
+    134,134,134,127,111,189,189,189,111,72,16,16,16,16,92,185,
+    184,147,134,134,189,189,189,156,179,134,134,134,135,186,186,186,
+    146,115,111,111,111,173,212,186,186,117,16,16,16,65,184,227,
+    235,235,189,189,189,95,99,213,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,229,182,182,189,189,189,189,189,
+    189,182,154,134,134,134,134,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,212,189,189,189,202,233,231,153,120,120,120,
+    124,156,111,111,142,235,235,235,235,235,235,235,235,235,216,134,
+    134,134,134,115,111,189,189,189,111,111,75,28,16,16,34,108,
+    111,111,122,134,189,189,189,134,134,134,134,133,129,180,186,186,
+    186,165,111,111,173,212,186,186,186,188,125,16,16,16,65,208,
+    235,235,189,189,189,95,95,130,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,197,147,156,182,189,189,
+    189,189,189,173,134,134,137,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,212,189,189,189,202,170,120,120,120,167,
+    224,146,111,111,184,235,235,235,235,235,235,235,235,235,166,134,
+    134,147,187,235,235,189,189,189,150,150,150,148,21,16,16,43,
+    108,111,111,120,189,189,189,134,134,134,134,122,116,140,183,186,
+    186,186,140,137,234,188,186,186,188,217,235,125,16,16,16,69,
+    235,235,189,189,189,95,95,95,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,197,155,165,
+    186,189,189,189,134,134,137,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,212,189,189,187,123,120,120,177,235,
+    235,115,111,111,223,235,235,235,235,235,235,235,235,216,134,134,
+    134,216,235,235,227,189,189,189,192,150,150,150,102,16,16,16,
+    43,108,111,111,182,189,189,151,134,134,134,128,112,111,126,180,
+    186,186,186,168,175,186,186,188,217,235,235,235,121,16,16,16,
+    132,232,189,189,189,95,95,95,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    232,194,189,188,134,147,197,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,209,146,120,120,120,124,235,235,
+    235,111,111,111,235,235,235,235,235,235,235,235,187,134,134,134,
+    166,235,235,235,205,189,189,204,235,192,150,150,150,82,16,16,
+    16,78,228,235,192,189,189,179,135,134,134,134,131,120,111,135,
+    182,186,186,186,186,186,186,212,235,235,235,235,235,100,16,16,
+    22,186,189,189,201,95,95,95,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,199,142,120,
+    156,222,201,217,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,171,120,120,120,120,163,233,235,
+    235,111,111,111,235,235,235,235,235,235,235,235,137,134,134,134,
+    216,235,235,235,191,189,189,227,235,235,200,155,150,150,82,16,
+    16,16,92,232,146,188,189,189,173,172,134,134,134,134,131,120,
+    116,170,186,186,186,186,149,137,232,235,235,235,235,206,49,16,
+    16,39,124,189,216,95,95,95,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,181,120,120,120,120,120,
+    120,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,231,124,120,120,129,161,189,202,233,
+    235,111,111,111,235,235,235,235,235,235,235,232,134,134,134,187,
+    235,235,235,235,189,189,189,235,235,235,235,230,192,155,150,82,
+    16,16,16,167,133,156,189,189,189,202,191,134,134,134,134,134,
+    137,166,186,186,186,186,135,111,118,188,235,235,235,233,163,21,
+    16,16,16,65,224,95,95,95,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,181,120,120,120,120,120,120,120,124,
+    192,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,171,120,120,124,212,189,189,189,189,
+    189,172,123,111,235,235,235,235,235,235,232,163,134,134,137,235,
+    235,235,235,235,189,189,189,235,235,235,235,235,235,230,187,150,
+    29,16,16,48,130,134,161,189,189,189,166,112,122,132,134,134,
+    134,134,149,185,186,186,173,113,111,111,123,162,204,235,227,130,
+    27,16,16,16,78,92,95,95,235,235,235,235,235,235,235,235,
+    235,235,199,142,120,120,120,120,120,120,120,120,120,135,171,224,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,124,120,120,181,235,212,189,189,189,
+    189,189,187,148,235,235,235,235,235,235,179,134,134,134,113,95,
+    95,95,95,95,189,189,189,113,182,235,235,235,235,235,235,176,
+    95,16,16,16,57,134,137,211,189,189,187,123,111,164,177,137,
+    134,134,134,157,187,186,186,165,113,111,111,111,111,111,138,178,
+    178,92,16,16,16,38,95,95,235,235,235,235,235,213,171,135,
+    120,120,120,120,120,120,120,120,120,120,120,135,192,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,231,120,120,120,235,235,235,217,195,189,
+    189,189,189,189,189,189,208,235,235,235,137,134,134,116,95,95,
+    95,95,95,95,189,189,189,95,95,113,182,235,235,235,235,230,
+    160,75,16,16,16,136,197,214,178,189,189,172,173,208,186,183,
+    157,134,134,134,134,134,149,186,167,114,111,111,111,111,111,131,
+    189,187,114,120,120,120,120,120,120,120,120,120,120,120,120,120,
+    120,120,120,120,120,120,120,120,135,192,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,164,120,120,124,235,235,235,235,235,235,
+    228,172,189,189,189,189,189,217,235,216,134,134,134,95,95,95,
+    95,95,95,95,189,189,189,95,95,95,95,113,182,235,235,235,
+    216,129,27,16,16,60,185,119,125,187,189,189,194,186,186,186,
+    188,175,134,134,134,134,134,170,186,178,165,166,131,111,111,122,
+    120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+    120,120,135,171,224,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,213,120,120,120,181,235,235,235,235,235,235,
+    235,111,148,179,189,189,189,189,189,189,189,184,179,119,95,95,
+    235,235,235,235,189,189,189,165,103,95,95,95,95,126,231,235,
+    216,134,86,16,16,16,43,111,111,149,189,189,189,188,186,188,
+    231,235,197,147,134,134,134,139,166,186,166,135,120,120,120,120,
+    120,120,120,120,120,120,120,120,120,120,120,120,120,135,167,206,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,160,120,120,156,235,235,235,235,235,235,235,
+    235,111,111,111,220,192,189,189,189,189,189,189,189,189,178,130,
+    235,235,235,235,189,189,189,235,226,165,103,95,95,95,148,187,
+    134,134,134,74,16,16,16,81,120,199,212,189,189,189,190,216,
+    235,235,235,235,225,137,134,134,130,126,120,120,120,120,120,120,
+    120,120,129,147,93,19,16,16,16,43,119,162,204,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,124,120,120,213,235,235,235,235,235,235,235,
+    235,111,111,111,235,232,212,194,189,189,189,189,189,189,189,189,
+    189,189,195,217,189,189,189,235,235,235,226,157,95,95,118,134,
+    134,134,134,117,55,16,16,16,70,150,190,188,189,189,189,195,
+    217,235,235,235,235,206,134,123,120,120,120,120,120,120,120,129,
+    161,189,189,183,103,77,22,16,16,16,37,96,111,146,231,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,
+    235,111,111,111,235,235,235,197,134,134,160,227,210,187,189,189,
+    189,189,189,189,189,189,189,217,235,235,235,235,139,102,134,134,
+    134,133,122,111,102,19,16,16,16,150,151,186,188,189,189,189,
+    189,195,187,142,120,120,120,120,120,120,121,129,152,186,189,189,
+    189,189,189,189,95,165,206,93,16,16,16,19,66,111,123,162,
+    204,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,231,120,120,120,235,235,235,235,235,235,235,235,
+    235,111,111,111,235,235,232,156,134,134,194,235,235,220,144,178,
+    189,189,189,189,189,189,189,189,194,208,224,235,223,129,134,134,
+    132,120,111,111,113,138,16,16,16,145,171,186,186,185,147,120,
+    120,120,120,120,120,120,120,120,122,126,133,134,151,188,189,189,
+    189,189,189,189,139,235,235,235,139,23,16,16,16,58,111,111,
+    111,146,231,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,171,120,120,124,235,235,235,235,235,235,235,235,
+    235,111,111,111,231,235,179,134,134,134,225,235,235,235,157,95,
+    95,126,210,195,189,189,189,189,189,189,189,189,189,189,189,189,
+    189,189,189,189,189,189,32,16,16,91,120,120,120,120,120,120,
+    120,120,120,120,120,120,129,150,183,189,189,189,189,189,189,187,
+    133,189,189,189,208,235,235,235,235,201,64,16,16,16,55,111,
+    111,111,146,231,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,124,120,120,181,235,235,235,235,235,235,235,235,
+    235,123,111,111,154,235,137,134,134,187,235,235,235,235,222,99,
+    95,95,134,231,235,189,189,189,189,189,189,189,189,189,189,189,
+    189,189,189,189,189,189,118,81,120,120,120,120,120,120,120,120,
+    120,120,129,150,183,189,189,189,189,189,189,189,189,189,188,162,
+    106,189,189,189,235,235,235,235,235,235,235,37,16,16,16,16,
+    49,108,111,123,162,204,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,184,111,111,111,229,134,134,134,235,235,235,235,235,235,178,
+    95,95,95,134,235,194,189,189,189,189,189,189,189,189,189,189,
+    189,189,189,176,150,129,120,120,120,120,120,120,120,120,129,161,
+    189,189,189,189,189,189,189,189,189,189,189,189,188,165,139,134,
+    134,189,189,189,235,235,235,235,235,235,235,173,30,16,16,16,
+    16,28,75,111,111,111,111,154,231,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,235,111,111,111,194,134,134,160,235,235,235,235,235,235,235,
+    165,95,95,95,191,222,194,189,189,189,189,188,173,159,135,118,
+    102,109,121,120,120,120,120,120,120,120,107,55,166,227,179,150,
+    150,150,150,167,203,189,189,189,189,189,189,184,164,170,137,134,
+    134,189,189,189,235,235,235,235,235,235,235,235,173,44,16,16,
+    16,16,16,16,16,49,108,111,146,231,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,235,123,111,112,136,134,134,194,235,235,235,235,235,235,235,
+    235,152,95,95,95,96,132,139,188,189,189,189,178,161,142,125,
+    120,120,120,120,120,120,120,128,159,86,16,16,57,235,235,214,
+    163,150,150,150,174,216,195,189,189,189,189,189,189,189,188,165,
+    134,189,189,189,134,158,210,235,235,235,235,235,235,235,235,146,
+    30,16,16,16,16,16,28,75,111,127,188,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,235,184,111,124,134,134,134,225,235,235,235,235,235,235,235,
+    235,222,99,113,134,134,134,134,151,170,150,129,120,120,120,120,
+    120,120,120,128,167,200,179,186,186,169,21,16,16,132,235,235,
+    235,192,150,150,150,175,173,146,135,154,178,189,189,189,189,189,
+    184,189,189,189,134,134,134,138,216,235,235,235,235,235,235,235,
+    221,125,44,16,16,16,16,16,16,16,55,123,162,204,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,235,235,173,133,134,134,144,231,235,235,235,235,235,235,235,
+    235,235,164,131,126,122,120,120,120,120,120,120,120,120,120,120,
+    127,146,162,208,223,200,186,186,186,152,68,16,16,23,201,235,
+    235,235,187,150,150,150,119,95,95,95,95,131,196,192,189,189,
+    189,189,189,187,134,134,134,134,133,150,232,235,235,235,235,235,
+    235,235,235,235,146,30,16,16,16,16,16,16,49,108,127,188,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,235,235,216,134,134,134,111,154,235,235,235,235,235,235,235,
+    235,197,124,120,120,120,120,120,120,120,120,120,118,112,114,164,
+    189,189,189,189,189,189,188,187,158,121,118,36,16,16,44,153,
+    235,191,121,132,150,150,150,110,95,108,161,231,235,232,210,189,
+    189,189,189,194,170,135,133,134,134,134,144,232,235,235,235,235,
+    235,235,235,235,235,221,125,44,16,16,16,16,16,43,108,111,
+    146,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,235,235,169,134,134,127,111,111,111,111,111,111,111,112,116,
+    119,120,120,120,120,120,120,120,120,117,110,101,95,95,95,95,
+    139,178,189,189,189,189,189,189,189,170,160,124,20,16,16,16,
+    38,95,95,96,139,150,150,150,201,235,235,235,235,235,235,217,
+    192,189,187,186,200,235,179,134,134,134,134,146,197,235,235,235,
+    235,235,235,235,235,235,235,235,173,44,16,16,16,16,16,49,
+    108,111,162,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,235,235,137,134,134,125,111,111,112,116,119,120,120,120,120,
+    120,120,120,121,121,114,111,173,235,231,200,169,143,121,95,95,
+    95,95,113,148,189,189,189,189,189,189,189,189,129,27,16,16,
+    16,142,121,116,156,158,150,150,160,224,235,235,235,235,235,235,
+    235,211,186,186,186,220,235,229,152,134,134,134,134,163,232,235,
+    235,235,235,235,235,235,235,235,235,235,235,125,16,16,16,16,
+    28,75,115,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,235,235,134,134,134,200,125,119,120,120,120,120,120,120,120,
+    120,121,126,132,111,127,184,235,235,235,235,235,235,235,235,208,
+    95,95,95,113,186,187,188,171,189,189,189,189,189,178,16,16,
+    16,76,184,189,189,194,179,169,162,168,222,235,235,235,235,235,
+    235,235,206,186,186,196,235,235,235,190,140,134,134,134,163,232,
+    235,235,235,235,235,235,235,235,235,235,235,235,153,44,16,16,
+    16,16,65,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,235,235,235,235,235,235,235,235,235,
+    235,235,235,134,131,126,135,120,120,120,120,120,120,120,134,137,
+    130,134,147,197,235,235,235,235,235,235,235,235,235,235,235,235,
+    95,95,95,235,186,186,186,235,235,224,213,204,180,189,32,16,
+    16,16,65,189,189,189,189,189,189,189,189,189,189,189,189,195,
+    217,235,231,188,186,186,220,235,235,235,229,179,134,134,134,163,
+    232,235,235,235,235,235,235,235,235,235,235,235,235,235,146,30,
+    16,16,16,92,228,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,120,120,120,167,235,235,235,235,199,142,120,120,
+    120,120,120,120,120,120,120,120,120,124,167,206,235,235,179,134,
+    134,134,216,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    95,95,95,235,186,186,186,235,235,235,235,235,213,125,98,31,
+    16,16,16,141,189,189,189,189,189,189,189,189,189,189,189,189,
+    189,189,189,189,188,186,186,203,234,235,235,235,184,134,134,134,
+    147,197,235,235,235,235,235,235,235,235,235,235,235,235,235,221,
+    37,16,16,16,92,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,131,120,120,120,120,120,120,120,120,120,120,120,
+    120,120,120,120,120,120,120,131,171,224,235,235,235,235,137,134,
+    134,184,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    95,95,95,235,186,186,186,235,235,235,235,235,235,192,125,121,
+    59,16,16,57,228,227,220,212,198,185,189,189,189,189,189,189,
+    189,189,189,189,189,186,186,186,200,235,235,235,235,184,134,134,
+    134,134,156,219,235,235,235,235,235,235,235,235,235,235,235,235,
+    173,44,16,16,16,16,105,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,203,128,120,120,120,120,120,120,120,120,120,120,
+    120,120,120,120,122,126,206,235,235,235,235,235,235,232,134,134,
+    134,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    95,95,95,235,186,186,186,235,235,235,235,235,235,235,210,136,
+    111,19,16,16,78,228,235,235,235,230,176,150,150,150,195,212,
+    195,189,189,195,208,192,186,186,186,220,235,235,235,235,194,140,
+    134,134,134,137,187,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,37,16,16,16,16,105,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,203,135,120,120,120,120,120,135,171,224,235,
+    235,235,235,134,134,134,235,235,235,235,235,235,235,179,134,134,
+    137,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    95,95,95,235,186,186,186,235,235,235,235,235,235,235,235,228,
+    157,78,16,16,16,78,235,235,235,235,235,190,150,150,152,222,
+    235,235,235,235,235,235,206,186,186,196,235,235,235,235,235,229,
+    184,137,134,134,134,163,232,235,235,235,235,235,235,235,235,235,
+    235,235,173,44,16,16,16,16,78,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,134,134,134,235,235,235,235,235,235,232,137,134,134,
+    187,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    95,95,95,235,186,186,186,235,235,235,235,235,235,235,235,235,
+    235,175,68,16,16,16,166,235,235,235,235,232,166,150,150,168,
+    232,235,235,235,235,235,231,188,186,186,220,235,235,235,235,235,
+    235,219,156,134,134,134,163,232,235,235,235,235,235,235,235,235,
+    235,235,235,235,173,30,16,16,16,166,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,134,134,134,235,235,235,235,235,235,175,134,134,137,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    95,95,95,235,186,186,186,235,235,235,235,235,235,235,235,235,
+    235,232,143,59,16,16,44,201,235,235,235,235,219,152,150,150,
+    174,232,235,235,235,235,235,208,186,186,186,200,235,235,235,235,
+    235,235,235,182,134,134,134,163,232,235,235,235,235,235,235,235,
+    235,235,235,235,235,173,44,16,16,16,105,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,134,134,134,235,235,235,235,235,229,137,134,134,187,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    95,95,95,235,186,186,186,235,235,235,235,235,235,235,235,235,
+    235,235,213,114,19,16,16,46,153,235,235,235,235,198,150,150,
+    150,174,232,235,235,235,235,231,188,186,186,186,220,235,235,235,
+    235,235,235,235,184,134,134,134,163,232,235,235,235,235,235,235,
+    235,235,235,235,235,235,215,23,16,16,16,105,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,134,134,134,235,235,235,235,235,197,134,134,160,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    95,95,95,235,186,186,186,235,235,235,235,235,235,235,235,235,
+    235,235,235,203,87,16,16,16,46,199,235,235,235,235,192,150,
+    150,150,174,232,235,235,235,235,220,192,186,186,186,200,235,235,
+    235,235,235,235,235,184,134,134,134,163,232,235,235,235,235,235,
+    235,235,235,235,235,235,235,166,30,16,16,16,228,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,134,134,134,235,235,235,235,232,156,134,134,194,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,208,
+    95,95,95,235,186,186,186,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,115,16,16,16,96,192,235,235,235,235,192,
+    150,150,150,174,232,235,235,235,235,231,188,186,186,186,220,235,
+    235,235,235,235,235,235,184,134,134,134,163,232,235,235,235,235,
+    235,235,235,235,235,235,235,235,173,30,16,16,92,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,134,134,134,232,235,235,235,172,134,134,134,225,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,139,
+    95,95,139,235,191,186,186,220,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,101,16,16,36,118,153,232,235,235,235,
+    192,150,150,150,174,235,235,235,235,235,220,192,186,186,196,234,
+    235,235,235,235,235,235,235,184,134,134,134,163,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,146,16,16,23,228,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,144,134,134,163,232,235,216,134,134,134,187,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,208,95,
+    95,95,208,235,208,186,186,196,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,215,22,16,16,46,118,153,232,235,235,
+    235,192,150,150,150,208,235,235,235,235,235,231,188,186,186,200,
+    235,235,235,235,235,235,235,235,184,134,134,134,187,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,153,71,153,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,194,134,134,134,169,235,169,134,134,166,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,139,95,
+    95,139,235,235,231,186,186,186,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,146,16,16,16,46,118,153,232,235,
+    235,235,184,150,150,166,235,235,235,235,235,235,215,186,186,186,
+    220,235,235,235,235,235,235,235,235,182,134,134,137,219,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,184,134,134,134,175,137,134,134,216,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,208,95,95,
+    95,208,235,235,235,186,186,186,234,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,125,16,16,16,39,118,121,168,
+    235,235,227,152,150,150,195,235,235,235,235,235,235,206,186,186,
+    186,203,234,235,235,235,235,235,235,232,153,134,134,144,175,210,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,144,134,134,134,134,134,134,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,139,95,95,
+    139,235,235,235,235,191,186,186,203,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,125,16,16,16,56,121,125,
+    235,235,235,192,150,150,152,222,235,235,235,235,235,231,188,186,
+    186,186,203,235,235,235,235,235,235,235,216,137,134,134,134,134,
+    166,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,206,140,134,134,134,134,137,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,226,99,95,95,
+    208,235,235,235,235,215,186,186,186,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,125,16,16,16,98,192,
+    235,235,235,232,166,150,150,168,235,235,235,235,235,235,220,192,
+    186,186,186,235,235,235,235,235,235,235,235,206,147,134,134,134,
+    134,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,206,147,134,134,147,197,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,182,95,95,130,
+    235,235,235,235,235,235,186,186,186,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,85,16,16,30,208,
+    235,235,235,235,219,152,150,150,216,235,235,235,235,235,235,235,
+    186,186,186,235,235,235,235,235,235,235,235,235,235,216,179,160,
+    197,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,130,95,95,178,
+    235,235,235,235,235,235,186,186,186,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,221,44,16,16,64,
+    235,235,235,235,235,184,150,150,190,235,235,235,235,235,235,235,
+    186,186,186,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,182,95,95,95,222,
+    235,235,235,235,235,235,186,186,186,234,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,187,23,16,16,
+    132,235,235,235,235,214,150,150,150,184,235,235,235,235,235,235,
+    186,186,186,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,169,95,
+    152,235,235,235,235,235,235,235,235,235,222,103,95,95,152,235,
+    235,235,235,235,235,235,191,186,186,203,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,125,16,16,
+    23,201,235,235,235,235,158,150,150,152,235,235,235,235,235,235,
+    186,186,186,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,99,95,
+    95,235,235,235,235,235,235,235,235,235,143,95,95,113,231,235,
+    235,235,235,235,235,235,215,186,186,186,234,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,228,57,16,
+    16,64,228,235,235,235,208,160,160,203,235,235,235,235,235,235,
+    186,186,186,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,95,95,
+    95,95,152,235,235,235,235,235,235,191,99,95,95,200,235,235,
+    235,235,235,235,235,235,235,191,186,186,203,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,194,23,
+    16,16,78,228,235,235,235,235,235,235,235,235,235,235,235,235,
+    186,186,186,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,108,95,
+    95,95,95,95,95,95,95,95,95,95,95,95,99,235,235,235,
+    235,235,235,235,235,235,235,215,186,186,186,234,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,139,
+    16,16,16,78,228,235,235,235,235,235,235,235,235,235,235,235,
+    186,186,186,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,196,113,
+    95,95,95,95,95,95,95,95,95,95,95,99,169,235,235,235,
+    235,235,235,235,235,235,235,235,191,186,186,200,234,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    125,16,16,16,78,235,235,235,235,235,235,235,235,235,235,234,
+    186,186,186,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    196,113,95,95,95,95,95,95,95,113,157,222,235,235,235,235,
+    235,235,235,235,235,235,235,235,215,186,186,186,200,234,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,125,16,16,16,187,235,235,235,235,235,235,235,235,234,200,
+    186,186,188,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,211,186,186,186,200,234,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,99,16,16,119,235,235,235,235,235,235,235,234,200,186,
+    186,186,212,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,211,186,186,186,192,217,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,180,16,16,44,228,235,235,235,235,235,235,208,186,186,
+    186,211,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,211,186,186,186,186,
+    200,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,37,16,16,78,228,234,205,186,186,186,186,186,186,
+    211,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,215,190,186,186,
+    186,220,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,234,128,16,16,16,64,181,186,186,186,186,186,186,188,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,232,203,186,
+    186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
+    186,186,186,186,101,16,16,16,64,181,186,186,186,186,192,217,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,231,188,
+    186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
+    186,186,186,186,186,101,16,16,16,66,209,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,220,
+    192,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
+    186,186,186,192,215,235,125,16,16,16,78,228,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,125,16,16,16,78,228,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,125,16,16,16,78,228,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,125,16,16,16,78,228,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,125,16,16,16,78,228,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,125,16,16,16,78,
+    228,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,125,16,16,16,
+    78,228,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,125,16,16,
+    16,78,228,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,125,16,
+    16,16,16,16,105,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,125,
+    16,16,16,16,23,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    153,44,16,44,153,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,136,128,136,128,136,128,136,128,136,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    112,145,99,159,99,159,83,176,81,153,88,131,101,84,105,73,
+    133,114,144,129,144,129,144,129,131,138,123,143,123,143,121,143,
+    115,143,115,143,127,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,133,121,152,95,155,90,155,90,155,90,
+    155,90,155,90,155,90,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,122,135,
+    107,152,118,140,128,128,111,147,103,158,103,158,103,158,107,153,
+    115,143,122,135,128,128,128,128,128,128,112,145,94,165,74,186,
+    71,190,71,190,71,190,87,138,105,73,105,73,110,85,120,100,
+    144,129,120,147,88,131,100,120,103,158,103,158,103,158,103,158,
+    103,158,103,158,103,158,103,158,107,153,115,143,127,128,128,128,
+    128,128,133,121,153,94,183,52,183,52,183,52,183,52,183,52,
+    183,52,183,52,179,57,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,103,157,
+    103,158,115,143,128,128,128,128,115,143,115,143,115,143,104,156,
+    103,158,103,158,115,143,128,128,122,135,84,175,73,187,92,167,
+    111,146,128,128,110,85,105,73,111,87,128,128,128,128,144,129,
+    144,129,116,140,88,172,103,158,95,166,88,148,115,99,106,76,
+    112,83,127,120,123,143,121,143,104,156,103,158,117,139,164,78,
+    183,52,183,52,183,52,167,73,135,118,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,103,158,
+    103,158,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,124,132,93,167,108,151,125,131,128,128,128,128,128,128,
+    128,128,108,81,105,73,111,88,128,128,128,128,128,128,144,129,
+    135,128,118,139,103,158,109,150,99,159,71,190,79,181,117,139,
+    128,126,130,118,147,137,144,129,156,135,166,89,183,52,181,53,
+    147,100,152,95,135,118,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,123,161,
+    128,162,128,162,128,162,128,128,128,135,128,162,128,159,128,142,
+    128,128,128,128,71,190,71,190,109,150,122,135,128,128,127,128,
+    127,125,105,73,121,111,128,128,128,128,128,128,131,128,144,129,
+    118,139,103,158,109,150,128,128,128,128,113,143,74,187,113,175,
+    154,161,154,161,159,126,170,78,183,52,181,52,157,88,122,152,
+    103,158,103,158,121,142,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,157,128,162,
+    115,160,115,160,128,145,128,129,128,128,128,145,128,153,128,162,
+    128,159,128,145,99,176,89,180,128,128,117,141,123,133,128,128,
+    128,128,124,118,128,128,128,128,128,128,128,128,144,129,129,140,
+    103,158,109,150,128,128,128,128,128,128,128,128,147,155,159,140,
+    171,96,179,58,183,52,180,55,164,88,130,103,108,80,128,128,
+    117,142,114,156,103,158,108,152,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,137,128,158,128,162,128,136,
+    104,156,103,158,124,133,128,128,128,128,128,128,128,128,128,136,
+    128,153,128,162,128,162,128,162,128,162,128,156,128,143,110,142,
+    113,146,128,128,128,128,127,128,128,128,127,128,117,148,103,158,
+    109,150,128,128,128,128,128,128,128,128,160,119,176,78,183,52,
+    179,56,140,104,124,128,128,128,143,129,144,129,105,73,124,119,
+    128,128,129,129,121,157,103,158,109,157,127,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,162,128,161,128,136,128,128,
+    124,132,103,157,103,158,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,71,190,120,151,128,145,128,159,128,162,128,162,
+    123,153,127,144,128,128,125,131,123,133,107,153,123,161,128,162,
+    128,162,128,162,131,155,155,107,180,58,183,52,176,61,152,95,
+    123,133,81,179,71,190,128,128,131,128,144,129,105,73,107,78,
+    128,128,128,128,128,128,124,140,103,158,106,153,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,162,128,134,128,128,128,128,
+    128,128,124,133,103,158,115,149,135,129,128,128,128,128,128,128,
+    128,128,128,128,71,190,128,128,128,128,128,128,128,131,115,111,
+    127,152,128,162,128,153,128,130,128,128,123,154,135,148,140,127,
+    151,113,163,91,183,52,183,52,168,81,145,127,128,143,114,173,
+    119,155,125,131,71,190,86,172,128,128,144,129,123,117,105,73,
+    128,128,128,128,128,128,128,128,141,160,103,158,106,154,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,138,128,162,128,128,128,128,128,128,
+    128,128,128,128,116,143,103,158,110,153,134,128,128,128,128,128,
+    128,128,128,128,71,190,128,128,128,128,128,128,123,115,105,73,
+    128,155,128,162,128,162,131,155,155,90,179,57,183,52,183,52,
+    183,52,176,60,158,86,155,137,154,161,128,152,128,162,124,170,
+    100,218,100,219,102,156,71,190,119,137,144,129,128,128,105,73,
+    128,128,128,128,128,128,128,128,154,161,114,144,103,158,123,133,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,161,128,162,128,128,128,128,128,128,
+    128,128,128,128,128,128,113,146,103,158,121,145,129,128,128,128,
+    134,128,128,128,71,190,128,128,128,128,128,128,109,81,116,118,
+    129,158,142,121,158,85,183,52,183,52,168,72,148,100,140,128,
+    131,153,118,160,116,159,139,161,131,159,125,131,128,137,128,162,
+    124,170,100,219,128,128,71,189,76,184,144,129,128,128,105,73,
+    128,128,128,128,128,128,128,128,154,161,128,128,104,157,103,158,
+    124,133,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,162,128,152,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,111,148,103,158,123,142,128,128,
+    130,128,139,128,84,178,128,128,128,128,128,128,146,102,168,81,
+    183,52,183,52,180,55,159,98,137,143,128,128,130,128,128,128,
+    128,147,128,162,128,162,128,162,127,161,121,161,114,159,113,154,
+    128,162,105,196,128,128,112,144,71,190,144,129,128,128,105,73,
+    128,128,128,128,128,128,128,128,151,157,128,128,127,129,103,157,
+    105,155,127,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,162,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,110,149,103,158,111,148,
+    128,128,135,128,144,129,137,128,150,97,178,60,183,52,169,67,
+    147,100,131,122,128,128,128,162,128,156,128,128,143,129,132,128,
+    128,128,128,155,128,161,147,161,128,147,128,155,128,162,126,161,
+    128,162,125,161,115,143,127,128,71,190,144,129,128,128,105,73,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,123,134,
+    103,158,107,153,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,162,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,113,146,103,158,
+    120,137,143,106,165,85,180,57,183,52,171,76,133,128,103,158,
+    110,150,128,128,128,153,128,162,128,131,128,128,131,128,144,129,
+    128,128,128,128,128,150,131,161,128,128,128,128,128,136,128,154,
+    128,162,128,162,123,161,117,155,81,180,144,129,128,128,105,73,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    104,156,103,158,119,138,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,142,128,162,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,131,122,
+    172,67,183,52,180,55,162,87,143,131,125,159,103,158,120,135,
+    129,128,128,128,128,162,128,162,128,128,128,128,128,128,131,128,
+    133,128,125,131,128,128,128,162,128,157,99,159,99,159,85,204,
+    81,192,128,162,128,162,128,162,128,162,128,162,117,128,105,74,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    124,133,104,156,103,158,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,161,128,162,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,147,102,171,68,183,52,
+    178,58,129,124,128,128,127,134,128,162,103,158,113,150,144,129,
+    143,128,135,128,128,162,128,162,74,186,71,190,71,190,71,190,
+    71,190,73,187,128,128,131,137,128,162,91,180,81,153,88,131,
+    88,131,128,162,128,162,130,125,136,145,124,153,128,162,120,154,
+    127,131,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,123,134,103,158,127,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,162,128,162,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,129,127,156,89,183,52,172,66,152,93,
+    129,127,124,133,120,137,128,128,128,149,106,154,128,128,116,97,
+    133,114,144,129,128,162,128,162,92,167,99,159,99,159,99,159,
+    99,159,107,150,125,131,128,128,126,153,128,162,104,115,104,115,
+    104,115,128,162,128,162,123,143,123,143,105,119,116,159,127,161,
+    127,161,123,144,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,103,158,107,153,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,162,128,162,128,128,128,128,128,128,128,128,
+    128,128,128,128,151,96,183,52,183,52,166,74,128,128,128,128,
+    128,128,128,128,108,152,128,135,128,128,103,157,111,148,126,129,
+    84,155,112,102,128,162,128,162,139,128,133,128,128,128,120,137,
+    107,152,103,158,103,158,125,131,127,128,128,161,113,159,103,158,
+    103,158,128,162,128,162,103,158,103,158,103,158,103,158,106,158,
+    124,161,128,162,124,159,127,143,128,132,128,128,128,128,128,128,
+    128,128,128,128,103,158,103,158,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,162,128,162,128,128,128,128,128,128,128,128,
+    129,127,174,64,183,52,175,81,152,129,141,144,141,144,136,139,
+    128,128,108,152,103,158,128,160,128,128,124,132,103,158,101,160,
+    85,176,111,146,128,162,128,162,142,126,143,129,114,142,103,158,
+    104,156,112,134,128,159,143,157,128,128,128,133,129,160,144,129,
+    135,142,128,162,128,162,128,128,128,128,128,128,127,129,117,141,
+    114,144,114,159,122,161,128,162,128,162,124,145,127,128,128,128,
+    128,128,128,128,103,158,103,158,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,160,128,162,128,128,128,128,128,128,136,116,
+    175,63,183,52,162,128,154,161,154,161,154,161,154,161,154,161,
+    149,160,103,158,125,157,128,162,128,155,128,128,106,151,97,164,
+    103,158,103,158,128,162,128,162,123,112,112,151,103,158,115,149,
+    105,73,123,106,154,161,147,151,137,129,128,128,128,149,131,144,
+    128,128,128,162,128,162,121,149,128,128,128,128,128,128,128,128,
+    128,128,123,133,115,143,113,148,122,161,128,162,128,162,114,159,
+    114,149,128,128,103,158,103,158,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,135,128,162,128,157,128,128,149,100,183,52,
+    182,53,161,133,151,157,128,128,128,128,128,128,128,128,137,145,
+    103,158,103,158,154,161,128,162,154,161,136,138,128,128,138,141,
+    135,152,116,159,128,162,128,162,108,151,103,158,105,132,144,129,
+    132,111,154,161,147,153,139,128,144,129,128,128,128,128,128,149,
+    128,128,128,162,128,162,100,217,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,127,129,122,150,121,161,128,162,
+    128,162,120,160,103,158,103,157,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,136,128,162,128,155,183,52,169,71,
+    130,124,154,161,134,136,128,128,128,128,128,128,128,128,107,153,
+    103,158,122,135,128,131,128,162,85,174,71,190,113,144,128,128,
+    144,148,154,161,129,161,128,162,103,158,103,158,140,137,146,141,
+    144,129,147,139,131,122,144,129,139,128,128,128,128,129,128,128,
+    128,128,128,162,128,162,100,219,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,119,141,
+    127,145,128,162,103,158,111,148,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,144,113,183,52,183,52,128,128,
+    128,128,154,161,128,128,128,128,128,128,128,128,110,149,103,158,
+    117,141,128,128,128,155,128,162,128,128,88,171,71,190,113,143,
+    128,128,128,128,118,135,128,162,112,159,103,158,106,158,132,159,
+    149,145,144,129,144,129,145,134,127,127,128,128,128,128,128,131,
+    128,128,128,155,128,147,100,219,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,141,110,155,90,178,59,
+    174,64,128,140,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,182,53,182,53,139,139,128,157,
+    128,145,152,161,128,128,128,128,128,128,127,128,103,158,103,157,
+    128,128,128,128,128,162,128,162,128,128,128,128,113,143,83,176,
+    125,131,128,128,103,156,122,161,128,162,128,148,116,159,103,158,
+    106,157,129,139,144,129,148,143,151,156,140,143,131,132,128,142,
+    128,129,128,128,128,129,100,219,128,128,128,128,128,128,128,128,
+    128,128,136,116,155,90,155,90,183,52,183,52,183,52,171,68,
+    138,113,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,129,127,183,52,141,110,128,136,128,159,
+    128,162,128,161,128,145,128,138,128,128,109,151,103,158,101,204,
+    100,219,100,219,128,162,128,162,109,190,123,145,128,128,128,128,
+    86,173,128,128,123,133,111,148,130,161,128,161,147,153,131,136,
+    112,151,103,158,123,144,129,139,147,143,154,161,154,161,151,157,
+    128,160,145,107,155,90,141,135,155,90,155,90,155,90,171,68,
+    183,52,183,52,183,52,183,52,179,57,155,90,138,113,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,172,66,183,52,128,128,128,128,128,128,
+    128,130,135,161,128,162,128,162,128,145,115,160,112,157,100,219,
+    114,173,114,173,128,162,128,162,101,216,100,219,109,190,127,129,
+    119,138,120,138,128,128,133,139,152,161,128,162,129,157,144,129,
+    137,128,111,148,103,158,103,158,136,134,143,109,166,104,169,105,
+    183,52,183,52,183,52,183,52,183,52,183,52,183,52,172,67,
+    155,90,152,95,130,124,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,183,52,152,95,128,128,128,128,128,128,
+    128,128,154,161,128,133,128,153,128,162,128,162,128,162,126,165,
+    128,145,128,142,128,162,128,162,127,131,114,173,100,219,107,184,
+    103,158,103,158,133,134,128,128,124,158,113,153,128,162,130,157,
+    128,134,128,128,127,129,116,141,155,88,183,52,183,52,183,52,
+    166,84,152,114,138,172,128,129,128,128,143,146,144,148,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,129,127,183,52,128,128,128,128,128,128,128,128,
+    128,128,154,161,128,128,127,128,103,158,113,145,128,137,121,175,
+    128,162,128,162,128,162,128,162,128,143,128,132,117,163,103,158,
+    105,159,141,159,152,157,128,128,128,128,92,172,140,137,145,127,
+    155,107,164,82,183,52,183,52,181,53,145,101,118,148,128,162,
+    128,162,128,162,104,205,130,130,128,128,128,128,135,136,153,159,
+    144,148,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,170,70,183,52,128,128,128,128,128,128,128,128,
+    128,128,154,161,137,139,109,151,103,158,127,129,128,128,118,157,
+    100,219,118,169,128,145,128,162,128,162,128,162,128,162,128,162,
+    128,162,128,162,128,162,128,138,155,90,183,52,183,52,183,52,
+    183,52,179,59,158,101,152,114,130,156,128,162,128,162,127,161,
+    106,197,128,162,125,136,128,128,128,128,128,128,128,128,133,134,
+    145,150,150,156,136,138,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,183,52,183,52,128,128,128,128,128,128,128,128,
+    128,128,154,161,154,161,103,158,106,154,128,128,128,128,128,128,
+    107,196,100,219,123,142,128,160,128,162,128,162,124,161,130,161,
+    127,169,150,116,171,76,183,52,183,52,179,57,155,90,133,117,
+    99,176,99,176,127,156,128,162,128,162,128,162,126,160,106,157,
+    103,158,128,162,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,136,138,141,144,154,160,138,140,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,183,52,183,52,128,128,128,128,128,128,128,128,
+    128,128,145,149,139,160,103,158,122,135,128,128,128,128,128,128,
+    128,128,100,217,101,188,103,163,119,160,143,131,159,98,174,69,
+    183,52,183,52,172,67,159,85,152,113,128,127,128,128,128,128,
+    104,154,71,190,79,181,122,162,120,178,126,165,128,162,128,160,
+    116,156,128,162,103,154,112,146,126,129,128,128,128,128,128,128,
+    128,128,128,128,128,128,130,130,141,144,138,140,136,138,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,183,52,183,52,128,128,128,128,128,128,128,128,
+    128,128,128,128,104,158,103,158,137,139,128,128,128,128,128,128,
+    128,128,140,114,165,75,183,52,183,52,183,52,179,60,159,99,
+    153,112,135,146,128,149,139,139,134,115,111,87,128,128,128,128,
+    128,128,100,182,71,190,79,198,100,219,106,197,126,141,128,154,
+    128,162,128,162,109,135,103,156,103,156,117,129,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,132,133,152,158,
+    137,140,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,183,52,183,52,128,128,128,128,128,128,128,128,
+    128,128,128,128,103,158,131,158,154,161,162,130,168,106,171,96,
+    181,59,183,52,172,74,168,106,155,90,135,135,105,203,100,219,
+    106,205,117,185,129,159,128,162,128,162,123,142,127,138,128,128,
+    124,141,104,211,92,188,71,190,95,166,128,128,128,128,128,128,
+    128,142,141,135,142,129,122,123,105,150,103,158,111,148,127,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    143,146,149,154,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,183,52,183,52,128,128,128,128,128,128,128,128,
+    128,128,128,128,111,148,155,99,180,62,183,52,183,52,179,57,
+    153,92,127,126,141,144,133,134,128,128,128,128,128,128,128,128,
+    100,219,100,219,144,129,139,138,128,145,128,153,126,154,128,129,
+    128,128,128,149,128,162,119,165,108,171,123,150,128,145,128,145,
+    128,134,134,128,144,129,130,128,128,128,115,143,103,158,106,153,
+    127,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,129,129,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,180,55,183,52,155,90,155,90,164,78,183,52,
+    183,52,183,52,183,52,183,52,171,68,144,105,128,128,109,151,
+    103,158,125,131,128,128,128,128,128,128,128,128,128,128,128,128,
+    100,219,100,219,144,129,144,129,128,128,128,128,126,123,109,85,
+    123,117,128,128,128,145,128,150,126,158,128,162,128,162,128,162,
+    128,162,128,162,131,154,144,129,134,128,128,128,122,135,103,158,
+    104,156,118,140,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,135,117,179,57,183,52,183,52,179,57,158,86,
+    155,90,155,90,138,111,135,118,128,128,128,128,128,128,103,158,
+    103,157,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    100,219,100,219,144,129,144,129,128,128,128,128,128,128,125,122,
+    109,84,128,128,128,128,128,128,128,128,108,149,71,190,87,172,
+    128,142,128,145,129,134,141,129,144,129,128,128,128,128,123,134,
+    109,150,103,158,110,150,127,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,103,158,128,128,128,128,128,128,120,137,103,158,
+    122,135,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    100,219,100,219,144,129,144,129,128,128,128,128,128,128,128,128,
+    128,128,113,91,128,128,127,125,128,128,128,128,99,159,71,190,
+    106,151,128,128,128,128,129,128,144,129,138,128,128,128,128,128,
+    128,128,118,140,103,158,106,153,127,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,103,158,128,128,128,128,128,128,103,157,106,154,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    100,219,100,219,144,129,144,129,128,128,128,128,128,128,128,128,
+    128,128,126,123,121,112,128,128,117,102,128,128,128,128,85,174,
+    71,190,106,151,128,128,128,128,138,128,144,129,138,128,128,128,
+    128,128,128,128,122,135,103,158,106,153,127,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,103,158,127,128,128,128,119,138,103,158,122,135,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    100,219,104,205,143,129,144,129,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,127,127,128,128,113,90,127,127,128,128,
+    85,174,71,190,106,151,128,128,128,128,138,128,144,129,137,128,
+    128,128,128,128,128,128,122,135,103,158,106,153,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,103,158,106,153,128,128,103,158,107,153,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,116,168,
+    100,219,125,136,133,128,144,129,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,124,120,109,81,127,127,
+    128,128,82,177,71,190,128,128,128,128,128,128,139,128,144,129,
+    130,128,128,128,128,128,128,128,122,135,103,158,110,149,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,122,135,103,158,108,152,103,158,125,131,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,100,219,
+    104,205,128,128,128,128,144,129,133,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,125,122,105,73,
+    128,128,125,131,71,190,86,172,128,128,128,128,128,128,144,129,
+    144,129,133,128,128,128,128,128,128,128,115,143,103,158,108,152,
+    119,138,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,113,146,103,158,104,156,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,122,148,100,219,
+    125,136,128,128,128,128,144,129,144,129,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,121,111,
+    128,128,128,128,99,159,71,190,122,135,128,128,128,128,130,128,
+    144,129,144,129,128,128,128,128,128,128,128,128,117,141,108,151,
+    111,148,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,103,207,100,219,
+    128,128,128,128,128,128,144,129,144,129,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,71,190,84,175,128,128,128,128,128,128,
+    144,129,144,129,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,108,193,
+    105,200,128,128,128,128,128,128,128,128,117,162,100,219,119,156,
+    128,128,128,128,128,128,139,128,144,129,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,93,165,74,186,128,128,128,128,128,128,
+    144,129,144,129,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,101,215,
+    100,219,105,200,114,173,114,173,114,173,100,217,100,217,128,128,
+    128,128,128,128,128,128,128,128,144,129,141,129,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    144,129,144,129,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,124,141,
+    110,186,100,219,100,219,100,219,100,219,106,199,121,149,128,128,
+    128,128,128,128,128,128,128,128,139,128,144,129,134,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    144,129,144,129,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,140,128,144,129,135,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,142,129,
+    144,129,131,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,139,128,144,129,
+    142,129,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,136,128,144,129,144,129,144,129,
+    132,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,134,128,
+    144,129,144,129,144,129,144,129,144,129,144,129,144,129,144,129,
+    144,129,144,129,140,129,128,128,130,128,139,128,136,128,135,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    135,128,136,128,136,128,136,128,136,128,136,128,136,128,136,128,
+    136,128,136,128,131,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+};
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/gl_tests/AtomicCounterBufferTest.cpp b/src/third_party/angle/src/tests/gl_tests/AtomicCounterBufferTest.cpp
new file mode 100644
index 0000000..3b2b171
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/AtomicCounterBufferTest.cpp
@@ -0,0 +1,54 @@
+//
+// Copyright 2017 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.
+//
+// AtomicCounterBufferTest:
+//   Various tests related for atomic counter buffers.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+class AtomicCounterBufferTest : public ANGLETest
+{
+  protected:
+    AtomicCounterBufferTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+};
+
+// Test GL_ATOMIC_COUNTER_BUFFER is not supported with version lower than ES31.
+TEST_P(AtomicCounterBufferTest, AtomicCounterBufferBindings)
+{
+    ASSERT_EQ(3, getClientMajorVersion());
+    GLBuffer atomicCounterBuffer;
+    glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 1, atomicCounterBuffer.get());
+    if (getClientMinorVersion() < 1)
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+    else
+    {
+        EXPECT_GL_NO_ERROR();
+    }
+}
+
+ANGLE_INSTANTIATE_TEST(AtomicCounterBufferTest,
+                       ES3_OPENGL(),
+                       ES3_OPENGLES(),
+                       ES31_OPENGL(),
+                       ES31_OPENGLES());
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/BindGeneratesResourceTest.cpp b/src/third_party/angle/src/tests/gl_tests/BindGeneratesResourceTest.cpp
new file mode 100644
index 0000000..e8ae739
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/BindGeneratesResourceTest.cpp
@@ -0,0 +1,123 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BindGeneratesResourceTest.cpp : Tests of the GL_CHROMIUM_bind_generates_resource extension.
+
+#include "test_utils/ANGLETest.h"
+
+namespace angle
+{
+
+class BindGeneratesResourceTest : public ANGLETest
+{
+  protected:
+    BindGeneratesResourceTest() { setBindGeneratesResource(false); }
+};
+
+// Context creation would fail if EGL_CHROMIUM_create_context_bind_generates_resource was not
+// available so the GL extension should always be present
+TEST_P(BindGeneratesResourceTest, ExtensionStringExposed)
+{
+    EXPECT_TRUE(extensionEnabled("GL_CHROMIUM_bind_generates_resource"));
+}
+
+// Verify that GL_BIND_GENERATES_RESOURCE_CHROMIUM can be queried but not changed
+TEST_P(BindGeneratesResourceTest, QueryValidation)
+{
+    GLint intValue = 2;
+    glGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &intValue);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(intValue, GL_FALSE);
+
+    float floatValue = 2.0f;
+    glGetFloatv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &floatValue);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(floatValue, 0.0f);
+
+    GLboolean boolValue = GL_TRUE;
+    glGetBooleanv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &boolValue);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(boolValue, GL_FALSE);
+
+    boolValue = glIsEnabled(GL_BIND_GENERATES_RESOURCE_CHROMIUM);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(boolValue, GL_FALSE);
+
+    glEnable(GL_BIND_GENERATES_RESOURCE_CHROMIUM);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    glDisable(GL_BIND_GENERATES_RESOURCE_CHROMIUM);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+// Test that buffers cannot be generated on bind
+TEST_P(BindGeneratesResourceTest, Buffers)
+{
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 2);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    EXPECT_GL_NO_ERROR();
+
+    if (getClientMajorVersion() >= 3)
+    {
+        glBindBufferBase(GL_UNIFORM_BUFFER, 0, 3);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+        glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
+        EXPECT_GL_NO_ERROR();
+
+        glBindBufferRange(GL_UNIFORM_BUFFER, 0, 4, 1, 2);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+        glBindBufferRange(GL_UNIFORM_BUFFER, 0, 0, 1, 2);
+        EXPECT_GL_NO_ERROR();
+    }
+}
+
+// Test that textures cannot be generated on bind
+TEST_P(BindGeneratesResourceTest, Textures)
+{
+    glBindTexture(GL_TEXTURE_2D, 2);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glBindTexture(GL_TEXTURE_2D, 0);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that framebuffers cannot be generated on bind
+TEST_P(BindGeneratesResourceTest, Framebuffers)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, 2);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that renderbuffer cannot be generated on bind
+TEST_P(BindGeneratesResourceTest, Renderbuffers)
+{
+    glBindRenderbuffer(GL_RENDERBUFFER, 2);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glBindRenderbuffer(GL_RENDERBUFFER, 0);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(BindGeneratesResourceTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/BindUniformLocationTest.cpp b/src/third_party/angle/src/tests/gl_tests/BindUniformLocationTest.cpp
new file mode 100644
index 0000000..75bd886
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/BindUniformLocationTest.cpp
@@ -0,0 +1,702 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BindUniformLocationTest.cpp : Tests of the GL_CHROMIUM_bind_uniform_location extension.
+
+#include "test_utils/ANGLETest.h"
+
+#include <cmath>
+
+using namespace angle;
+
+namespace
+{
+
+class BindUniformLocationTest : public ANGLETest
+{
+  protected:
+    BindUniformLocationTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+        mBindUniformLocation = reinterpret_cast<PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC>(
+            eglGetProcAddress("glBindUniformLocationCHROMIUM"));
+    }
+
+    void TearDown() override
+    {
+        if (mProgram != 0)
+        {
+            glDeleteProgram(mProgram);
+        }
+        ANGLETest::TearDown();
+    }
+
+    typedef void(GL_APIENTRYP PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC)(GLuint mProgram,
+                                                                    GLint location,
+                                                                    const GLchar *name);
+    PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC mBindUniformLocation = nullptr;
+
+    GLuint mProgram = 0;
+};
+
+// Test basic functionality of GL_CHROMIUM_bind_uniform_location
+TEST_P(BindUniformLocationTest, Basic)
+{
+    if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+                  << std::endl;
+        return;
+    }
+
+    ASSERT_NE(mBindUniformLocation, nullptr);
+
+    // clang-format off
+    const std::string vsSource = SHADER_SOURCE
+    (
+        attribute vec4 a_position;
+        void main()
+        {
+            gl_Position = a_position;
+        }
+    );
+
+    const std::string fsSource = SHADER_SOURCE
+    (
+        precision mediump float;
+        uniform vec4 u_colorC;
+        uniform vec4 u_colorB[2];
+        uniform vec4 u_colorA;
+        void main()
+        {
+            gl_FragColor = u_colorA + u_colorB[0] + u_colorB[1] + u_colorC;
+        }
+    );
+    // clang-format on
+
+    GLint colorALocation = 3;
+    GLint colorBLocation = 10;
+    GLint colorCLocation = 5;
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+    mProgram = glCreateProgram();
+
+    mBindUniformLocation(mProgram, colorALocation, "u_colorA");
+    mBindUniformLocation(mProgram, colorBLocation, "u_colorB[0]");
+    mBindUniformLocation(mProgram, colorCLocation, "u_colorC");
+
+    glAttachShader(mProgram, vs);
+    glDeleteShader(vs);
+
+    glAttachShader(mProgram, fs);
+    glDeleteShader(fs);
+
+    // Link the mProgram
+    glLinkProgram(mProgram);
+    // Check the link status
+    GLint linked = 0;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    ASSERT_EQ(1, linked);
+
+    glUseProgram(mProgram);
+
+    static const float colorB[] = {
+        0.0f, 0.50f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.0f,
+    };
+
+    glUniform4f(colorALocation, 0.25f, 0.0f, 0.0f, 0.0f);
+    glUniform4fv(colorBLocation, 2, colorB);
+    glUniform4f(colorCLocation, 0.0f, 0.0f, 0.0f, 1.0f);
+
+    drawQuad(mProgram, "a_position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_NEAR(0, 0, 64, 128, 192, 255, 1.0);
+}
+
+// Test that conflicts are detected when two uniforms are bound to the same location
+TEST_P(BindUniformLocationTest, ConflictsDetection)
+{
+    if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+                  << std::endl;
+        return;
+    }
+
+    ASSERT_NE(nullptr, mBindUniformLocation);
+
+    // clang-format off
+    const std::string vsSource = SHADER_SOURCE
+    (
+        attribute vec4 a_position;
+        void main()
+        {
+            gl_Position = a_position;
+        }
+    );
+
+    const std::string fsSource = SHADER_SOURCE
+    (
+        precision mediump float;
+        uniform vec4 u_colorA;
+        uniform vec4 u_colorB;
+        void main()
+        {
+            gl_FragColor = u_colorA + u_colorB;
+        }
+    );
+    // clang-format on
+
+    GLint colorALocation = 3;
+    GLint colorBLocation = 4;
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+    mProgram = glCreateProgram();
+    glAttachShader(mProgram, vs);
+    glDeleteShader(vs);
+    glAttachShader(mProgram, fs);
+    glDeleteShader(fs);
+
+    mBindUniformLocation(mProgram, colorALocation, "u_colorA");
+    // Bind u_colorB to location a, causing conflicts, link should fail.
+    mBindUniformLocation(mProgram, colorALocation, "u_colorB");
+    glLinkProgram(mProgram);
+    GLint linked = 0;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    ASSERT_EQ(0, linked);
+
+    // Bind u_colorB to location b, no conflicts, link should succeed.
+    mBindUniformLocation(mProgram, colorBLocation, "u_colorB");
+    glLinkProgram(mProgram);
+    linked = 0;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    EXPECT_EQ(1, linked);
+}
+
+// Test a use case of the chromium compositor
+TEST_P(BindUniformLocationTest, Compositor)
+{
+    if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+                  << std::endl;
+        return;
+    }
+
+    ASSERT_NE(nullptr, mBindUniformLocation);
+
+    // clang-format off
+    const std::string vsSource = SHADER_SOURCE
+    (
+        attribute vec4 a_position;
+        attribute vec2 a_texCoord;
+        uniform mat4 matrix;
+        uniform vec2 color_a[4];
+        uniform vec4 color_b;
+        varying vec4 v_color;
+        void main()
+        {
+            v_color.xy = color_a[0] + color_a[1];
+            v_color.zw = color_a[2] + color_a[3];
+            v_color += color_b;
+            gl_Position = matrix * a_position;
+        }
+    );
+
+    const std::string fsSource = SHADER_SOURCE
+    (
+        precision mediump float;
+        varying vec4 v_color;
+        uniform float alpha;
+        uniform vec4 multiplier;
+        uniform vec3 color_c[8];
+        void main()
+        {
+            vec4 color_c_sum = vec4(0.0);
+            color_c_sum.xyz += color_c[0];
+            color_c_sum.xyz += color_c[1];
+            color_c_sum.xyz += color_c[2];
+            color_c_sum.xyz += color_c[3];
+            color_c_sum.xyz += color_c[4];
+            color_c_sum.xyz += color_c[5];
+            color_c_sum.xyz += color_c[6];
+            color_c_sum.xyz += color_c[7];
+            color_c_sum.w = alpha;
+            color_c_sum *= multiplier;
+            gl_FragColor = v_color + color_c_sum;
+        }
+    );
+    // clang-format on
+
+    int counter            = 6;
+    int matrixLocation     = counter++;
+    int colorALocation     = counter++;
+    int colorBLocation     = counter++;
+    int alphaLocation      = counter++;
+    int multiplierLocation = counter++;
+    int colorCLocation     = counter++;
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+    mProgram = glCreateProgram();
+
+    mBindUniformLocation(mProgram, matrixLocation, "matrix");
+    mBindUniformLocation(mProgram, colorALocation, "color_a");
+    mBindUniformLocation(mProgram, colorBLocation, "color_b");
+    mBindUniformLocation(mProgram, alphaLocation, "alpha");
+    mBindUniformLocation(mProgram, multiplierLocation, "multiplier");
+    mBindUniformLocation(mProgram, colorCLocation, "color_c");
+
+    glAttachShader(mProgram, vs);
+    glDeleteShader(vs);
+    glAttachShader(mProgram, fs);
+    glDeleteShader(fs);
+
+    // Link the mProgram
+    glLinkProgram(mProgram);
+    // Check the link status
+    GLint linked = 0;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    ASSERT_EQ(1, linked);
+
+    glUseProgram(mProgram);
+
+    static const float colorA[] = {
+        0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,
+    };
+
+    static const float colorC[] = {
+        0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,
+        0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,
+    };
+
+    static const float identity[] = {
+        1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
+    };
+
+    glUniformMatrix4fv(matrixLocation, 1, false, identity);
+    glUniform2fv(colorALocation, 4, colorA);
+    glUniform4f(colorBLocation, 0.2f, 0.2f, 0.2f, 0.2f);
+    glUniform1f(alphaLocation, 0.8f);
+    glUniform4f(multiplierLocation, 0.5f, 0.5f, 0.5f, 0.5f);
+    glUniform3fv(colorCLocation, 8, colorC);
+
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+
+    drawQuad(mProgram, "a_position", 0.5f);
+
+    EXPECT_PIXEL_EQ(0, 0, 204, 204, 204, 204);
+}
+
+// Test that unused uniforms don't conflict when bound to the same location
+TEST_P(BindUniformLocationTest, UnusedUniformUpdate)
+{
+    if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+                  << std::endl;
+        return;
+    }
+
+    ASSERT_NE(nullptr, mBindUniformLocation);
+
+    // clang-format off
+    const std::string vsSource = SHADER_SOURCE
+    (
+        attribute vec4 a_position;
+        void main()
+        {
+            gl_Position = a_position;
+        }
+    );
+
+    const std::string fsSource = SHADER_SOURCE
+    (
+        precision mediump float;
+        uniform vec4 u_colorA;
+        uniform float u_colorU;
+        uniform vec4 u_colorC;
+        void main()
+        {
+            gl_FragColor = u_colorA + u_colorC;
+        }
+    );
+    // clang-format on
+
+    const GLint colorULocation      = 1;
+    const GLint nonexistingLocation = 5;
+    const GLint unboundLocation     = 6;
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+    mProgram = glCreateProgram();
+    mBindUniformLocation(mProgram, colorULocation, "u_colorU");
+    // The non-existing uniform should behave like existing, but optimized away
+    // uniform.
+    mBindUniformLocation(mProgram, nonexistingLocation, "nonexisting");
+    // Let A and C be assigned automatic locations.
+    glAttachShader(mProgram, vs);
+    glDeleteShader(vs);
+    glAttachShader(mProgram, fs);
+    glDeleteShader(fs);
+    glLinkProgram(mProgram);
+    GLint linked = 0;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    ASSERT_EQ(1, linked);
+    glUseProgram(mProgram);
+
+    // No errors on bound locations, since caller does not know
+    // if the driver optimizes them away or not.
+    glUniform1f(colorULocation, 0.25f);
+    EXPECT_GL_NO_ERROR();
+
+    // No errors on bound locations of names that do not exist
+    // in the shader. Otherwise it would be inconsistent wrt the
+    // optimization case.
+    glUniform1f(nonexistingLocation, 0.25f);
+    EXPECT_GL_NO_ERROR();
+
+    // The above are equal to updating -1.
+    glUniform1f(-1, 0.25f);
+    EXPECT_GL_NO_ERROR();
+
+    // No errors when updating with other type either.
+    // The type can not be known with the non-existing case.
+    glUniform2f(colorULocation, 0.25f, 0.25f);
+    EXPECT_GL_NO_ERROR();
+    glUniform2f(nonexistingLocation, 0.25f, 0.25f);
+    EXPECT_GL_NO_ERROR();
+    glUniform2f(-1, 0.25f, 0.25f);
+    EXPECT_GL_NO_ERROR();
+
+    // Ensure that driver or ANGLE has optimized the variable
+    // away and the test tests what it is supposed to.
+    EXPECT_EQ(-1, glGetUniformLocation(mProgram, "u_colorU"));
+
+    // The bound location gets marked as used and the driver
+    // does not allocate other variables to that location.
+    EXPECT_NE(colorULocation, glGetUniformLocation(mProgram, "u_colorA"));
+    EXPECT_NE(colorULocation, glGetUniformLocation(mProgram, "u_colorC"));
+    EXPECT_NE(nonexistingLocation, glGetUniformLocation(mProgram, "u_colorA"));
+    EXPECT_NE(nonexistingLocation, glGetUniformLocation(mProgram, "u_colorC"));
+
+    // Unintuitive: while specifying value works, getting the value does not.
+    GLfloat getResult = 0.0f;
+    glGetUniformfv(mProgram, colorULocation, &getResult);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glGetUniformfv(mProgram, nonexistingLocation, &getResult);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glGetUniformfv(mProgram, -1, &getResult);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Updating an unbound, non-existing location still causes
+    // an error.
+    glUniform1f(unboundLocation, 0.25f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test for a bug where using a sampler caused GL error if the mProgram had
+// uniforms that were optimized away by the driver. This was only a problem with
+// glBindUniformLocationCHROMIUM implementation. This could be reproed by
+// binding the sampler to a location higher than the amount of active uniforms.
+TEST_P(BindUniformLocationTest, UseSamplerWhenUnusedUniforms)
+{
+    if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+                  << std::endl;
+        return;
+    }
+
+    ASSERT_NE(nullptr, mBindUniformLocation);
+
+    // clang-format off
+    const std::string vsSource = SHADER_SOURCE
+    (
+        void main()
+        {
+            gl_Position = vec4(0);
+        }
+    );
+
+    const std::string fsSource = SHADER_SOURCE
+    (
+        uniform sampler2D tex;
+        void main()
+        {
+            gl_FragColor = texture2D(tex, vec2(1));
+        }
+    );
+    // clang-format on
+
+    const GLuint texLocation = 54;
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+    mProgram = glCreateProgram();
+    mBindUniformLocation(mProgram, texLocation, "tex");
+
+    glAttachShader(mProgram, vs);
+    glDeleteShader(vs);
+    glAttachShader(mProgram, fs);
+    glDeleteShader(fs);
+
+    glLinkProgram(mProgram);
+
+    GLint linked = 0;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    EXPECT_NE(0, linked);
+    glUseProgram(mProgram);
+    glUniform1i(texLocation, 0);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test for binding a statically used uniform to the same location as a non-statically used uniform.
+// This is valid according to the extension spec.
+TEST_P(BindUniformLocationTest, SameLocationForUsedAndUnusedUniform)
+{
+    if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+                  << std::endl;
+        return;
+    }
+
+    ASSERT_NE(nullptr, mBindUniformLocation);
+
+    // clang-format off
+    const std::string vsSource = SHADER_SOURCE
+    (
+        void main()
+        {
+            gl_Position = vec4(0);
+        }
+    );
+
+    const std::string fsSource = SHADER_SOURCE
+    (
+        precision mediump float;
+        uniform vec4 a;
+        uniform vec4 b;
+        void main()
+        {
+            gl_FragColor = a;
+        }
+    );
+    // clang-format on
+
+    const GLuint location = 54;
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+    mProgram = glCreateProgram();
+    mBindUniformLocation(mProgram, location, "a");
+    mBindUniformLocation(mProgram, location, "b");
+
+    glAttachShader(mProgram, vs);
+    glDeleteShader(vs);
+    glAttachShader(mProgram, fs);
+    glDeleteShader(fs);
+
+    glLinkProgram(mProgram);
+
+    GLint linked = GL_FALSE;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    ASSERT_GL_TRUE(linked);
+    glUseProgram(mProgram);
+    glUniform4f(location, 0.0, 1.0, 0.0, 1.0);
+    EXPECT_GL_NO_ERROR();
+}
+
+class BindUniformLocationES31Test : public BindUniformLocationTest
+{
+  protected:
+    BindUniformLocationES31Test() : BindUniformLocationTest() {}
+
+    void linkProgramWithUniformLocation(GLuint vs,
+                                        GLuint fs,
+                                        const char *uniformName,
+                                        GLint uniformLocation)
+    {
+        mProgram = glCreateProgram();
+        mBindUniformLocation(mProgram, uniformLocation, uniformName);
+
+        glAttachShader(mProgram, vs);
+        glDeleteShader(vs);
+        glAttachShader(mProgram, fs);
+        glDeleteShader(fs);
+
+        glLinkProgram(mProgram);
+    }
+};
+
+// Test for when the shader specifies an explicit uniform location with a layout qualifier and the
+// bindUniformLocation API sets a consistent location.
+TEST_P(BindUniformLocationES31Test, ConsistentWithLocationLayoutQualifier)
+{
+    if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+                  << std::endl;
+        return;
+    }
+
+    const std::string vsSource =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0);\n"
+        "}\n";
+
+    const std::string fsSource =
+        "#version 310 es\n"
+        "uniform layout(location=2) highp sampler2D tex;\n"
+        "out highp vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = texture(tex, vec2(1));\n"
+        "}\n";
+
+    const GLuint texLocation = 2;
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    EXPECT_NE(0u, vs);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+    EXPECT_NE(0u, fs);
+    linkProgramWithUniformLocation(vs, fs, "tex", texLocation);
+
+    GLint linked = GL_FALSE;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    ASSERT_GL_TRUE(linked);
+
+    EXPECT_EQ(static_cast<GLint>(texLocation), glGetUniformLocation(mProgram, "tex"));
+    glUseProgram(mProgram);
+    glUniform1i(texLocation, 0);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test for when the shader specifies an explicit uniform location with a layout qualifier and the
+// bindUniformLocation API sets a conflicting location for the same variable. The shader-set
+// location should prevail.
+TEST_P(BindUniformLocationES31Test, LocationLayoutQualifierOverridesAPIBinding)
+{
+    if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+                  << std::endl;
+        return;
+    }
+
+    const std::string vsSource =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0);\n"
+        "}\n";
+
+    const std::string fsSource =
+        "#version 310 es\n"
+        "uniform layout(location=2) highp sampler2D tex;\n"
+        "out highp vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = texture(tex, vec2(1));\n"
+        "}\n";
+
+    const GLuint shaderTexLocation = 2;
+    const GLuint texLocation       = 3;
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    EXPECT_NE(0u, vs);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+    EXPECT_NE(0u, fs);
+    linkProgramWithUniformLocation(vs, fs, "tex", texLocation);
+
+    GLint linked = GL_FALSE;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    ASSERT_GL_TRUE(linked);
+
+    EXPECT_EQ(static_cast<GLint>(shaderTexLocation), glGetUniformLocation(mProgram, "tex"));
+    glUseProgram(mProgram);
+    glUniform1i(shaderTexLocation, 1);
+    EXPECT_GL_NO_ERROR();
+    glUniform1i(texLocation, 2);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test for when the shader specifies an explicit uniform location with a layout qualifier and the
+// bindUniformLocation API sets a conflicting location for a different variable. Linking should
+// fail.
+TEST_P(BindUniformLocationES31Test, LocationLayoutQualifierConflictsWithAPIBinding)
+{
+    if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+                  << std::endl;
+        return;
+    }
+
+    const std::string vsSource =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0);\n"
+        "}\n";
+
+    const std::string fsSource =
+        "#version 310 es\n"
+        "uniform layout(location=2) highp sampler2D tex;\n"
+        "uniform highp sampler2D tex2;\n"
+        "out highp vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = texture(tex2, vec2(1));\n"
+        "}\n";
+
+    const GLuint tex2Location = 2;
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    EXPECT_NE(0u, vs);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+    EXPECT_NE(0u, fs);
+    linkProgramWithUniformLocation(vs, fs, "tex2", tex2Location);
+
+    GLint linked = GL_FALSE;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+    ASSERT_GL_FALSE(linked);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(BindUniformLocationTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(BindUniformLocationES31Test, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES())
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/BlendMinMaxTest.cpp b/src/third_party/angle/src/tests/gl_tests/BlendMinMaxTest.cpp
new file mode 100644
index 0000000..39f5251
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/BlendMinMaxTest.cpp
@@ -0,0 +1,255 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class BlendMinMaxTest : public ANGLETest
+{
+  protected:
+    BlendMinMaxTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+
+        mProgram = 0;
+        mColorLocation = -1;
+        mFramebuffer = 0;
+        mColorRenderbuffer = 0;
+    }
+
+    struct Color
+    {
+        float values[4];
+    };
+
+    static float getExpected(bool blendMin, float curColor, float prevColor)
+    {
+        return blendMin ? std::min(curColor, prevColor) : std::max(curColor, prevColor);
+    }
+
+    void runTest(GLenum colorFormat, GLenum type)
+    {
+        if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_blend_minmax"))
+        {
+            std::cout << "Test skipped because ES3 or GL_EXT_blend_minmax is not available." << std::endl;
+            return;
+        }
+
+        // TODO(geofflang): figure out why this fails
+        if (IsIntel() && GetParam() == ES2_OPENGL())
+        {
+            std::cout << "Test skipped on OpenGL Intel due to flakyness." << std::endl;
+            return;
+        }
+
+        SetUpFramebuffer(colorFormat);
+
+        int minValue = 0;
+        int maxValue = 1;
+        if (type == GL_FLOAT)
+        {
+            minValue = -1024;
+            maxValue = 1024;
+        }
+
+        const size_t colorCount = 128;
+        Color colors[colorCount];
+        for (size_t i = 0; i < colorCount; i++)
+        {
+            for (size_t j = 0; j < 4; j++)
+            {
+                colors[i].values[j] =
+                    static_cast<float>(minValue + (rand() % (maxValue - minValue)));
+            }
+        }
+
+        float prevColor[4];
+        for (size_t i = 0; i < colorCount; i++)
+        {
+            const Color &color = colors[i];
+            glUseProgram(mProgram);
+            glUniform4f(mColorLocation, color.values[0], color.values[1], color.values[2], color.values[3]);
+
+            bool blendMin = (rand() % 2 == 0);
+            glBlendEquation(blendMin ? GL_MIN : GL_MAX);
+
+            drawQuad(mProgram, "aPosition", 0.5f);
+
+            float pixel[4];
+            if (type == GL_UNSIGNED_BYTE)
+            {
+                GLubyte ubytePixel[4];
+                glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, ubytePixel);
+                for (size_t componentIdx = 0; componentIdx < ArraySize(pixel); componentIdx++)
+                {
+                    pixel[componentIdx] = ubytePixel[componentIdx] / 255.0f;
+                }
+            }
+            else if (type == GL_FLOAT)
+            {
+                glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixel);
+            }
+            else
+            {
+                FAIL() << "Unexpected pixel type";
+            }
+
+            if (i > 0)
+            {
+                const float errorRange = 1.0f / 255.0f;
+                for (size_t componentIdx = 0; componentIdx < ArraySize(pixel); componentIdx++)
+                {
+                    EXPECT_NEAR(
+                        getExpected(blendMin, color.values[componentIdx], prevColor[componentIdx]),
+                        pixel[componentIdx], errorRange);
+                }
+            }
+
+            memcpy(prevColor, pixel, sizeof(pixel));
+        }
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string testVertexShaderSource = SHADER_SOURCE
+        (
+            attribute highp vec4 aPosition;
+
+            void main(void)
+            {
+                gl_Position = aPosition;
+            }
+        );
+
+        const std::string testFragmentShaderSource = SHADER_SOURCE
+        (
+            uniform highp vec4 color;
+            void main(void)
+            {
+                gl_FragColor = color;
+            }
+        );
+
+        mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mColorLocation = glGetUniformLocation(mProgram, "color");
+
+        glUseProgram(mProgram);
+
+        glClearColor(0, 0, 0, 0);
+        glClearDepthf(0.0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        glEnable(GL_BLEND);
+        glDisable(GL_DEPTH_TEST);
+    }
+
+    void SetUpFramebuffer(GLenum colorFormat)
+    {
+        glGenFramebuffers(1, &mFramebuffer);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
+
+        glGenRenderbuffers(1, &mColorRenderbuffer);
+        glBindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, getWindowWidth(), getWindowHeight());
+        glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mColorRenderbuffer);
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mProgram);
+        glDeleteFramebuffers(1, &mFramebuffer);
+        glDeleteRenderbuffers(1, &mColorRenderbuffer);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+    GLint mColorLocation;
+
+    GLuint mFramebuffer;
+    GLuint mColorRenderbuffer;
+};
+
+TEST_P(BlendMinMaxTest, RGBA8)
+{
+    runTest(GL_RGBA8, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(BlendMinMaxTest, RGBA32F)
+{
+    if (getClientMajorVersion() < 3 || !extensionEnabled("GL_EXT_color_buffer_float"))
+    {
+        std::cout << "Test skipped because ES3 and GL_EXT_color_buffer_float are not available."
+                  << std::endl;
+        return;
+    }
+
+    // TODO(jmadill): Figure out why this is broken on Intel
+    if (IsIntel() && (GetParam() == ES2_D3D11() || GetParam() == ES2_D3D9()))
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    // TODO (bug 1284): Investigate RGBA32f D3D SDK Layers messages on D3D11_FL9_3
+    if (IsD3D11_FL93())
+    {
+        std::cout << "Test skipped on Feature Level 9_3." << std::endl;
+        return;
+    }
+
+    runTest(GL_RGBA32F, GL_FLOAT);
+}
+
+TEST_P(BlendMinMaxTest, RGBA16F)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_color_buffer_half_float"))
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_color_buffer_half_float is not available."
+                  << std::endl;
+        return;
+    }
+
+    // TODO(jmadill): figure out why this fails
+    if (IsIntel() && (GetParam() == ES2_D3D11() || GetParam() == ES2_D3D9()))
+    {
+        std::cout << "Test skipped on Intel due to failures." << std::endl;
+        return;
+    }
+
+    runTest(GL_RGBA16F, GL_FLOAT);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(BlendMinMaxTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/third_party/angle/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
new file mode 100644
index 0000000..c2d7d44
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
@@ -0,0 +1,1075 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+class BlitFramebufferANGLETest : public ANGLETest
+{
+  protected:
+    BlitFramebufferANGLETest()
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+
+        mCheckerProgram = 0;
+        mBlueProgram = 0;
+
+        mOriginalFBO = 0;
+
+        mUserFBO = 0;
+        mUserColorBuffer = 0;
+        mUserDepthStencilBuffer = 0;
+
+        mSmallFBO = 0;
+        mSmallColorBuffer = 0;
+        mSmallDepthStencilBuffer = 0;
+
+        mColorOnlyFBO = 0;
+        mColorOnlyColorBuffer = 0;
+
+        mDiffFormatFBO = 0;
+        mDiffFormatColorBuffer = 0;
+
+        mDiffSizeFBO = 0;
+        mDiffSizeColorBuffer = 0;
+
+        mMRTFBO = 0;
+        mMRTColorBuffer0 = 0;
+        mMRTColorBuffer1 = 0;
+
+        mRGBAColorbuffer = 0;
+        mRGBAFBO = 0;
+
+        mBGRAMultisampledRenderbuffer = 0;
+        mBGRAMultisampledFBO = 0;
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string passthroughVS = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec4 pos;
+
+            void main()
+            {
+                gl_Position = position;
+                pos = position;
+            }
+        );
+
+        const std::string checkeredFS = SHADER_SOURCE
+        (
+            precision highp float;
+            varying vec4 pos;
+
+            void main()
+            {
+                if (pos.x * pos.y > 0.0)
+                {
+                    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+                }
+                else
+                {
+                    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+                }
+            }
+        );
+
+        const std::string blueFS = SHADER_SOURCE
+        (
+            precision highp float;
+            varying vec4 pos;
+
+            void main()
+            {
+                gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
+            }
+        );
+
+        mCheckerProgram = CompileProgram(passthroughVS, checkeredFS);
+        mBlueProgram = CompileProgram(passthroughVS, blueFS);
+        if (mCheckerProgram == 0 || mBlueProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        EXPECT_GL_NO_ERROR();
+
+        GLint originalFBO;
+        glGetIntegerv(GL_FRAMEBUFFER_BINDING, &originalFBO);
+        if (originalFBO >= 0)
+        {
+            mOriginalFBO = (GLuint)originalFBO;
+        }
+
+        GLenum format = GL_BGRA_EXT;
+
+        glGenFramebuffers(1, &mUserFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+        glGenTextures(1, &mUserColorBuffer);
+        glGenRenderbuffers(1, &mUserDepthStencilBuffer);
+        glBindTexture(GL_TEXTURE_2D, mUserColorBuffer);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mUserColorBuffer, 0);
+        glTexImage2D(GL_TEXTURE_2D, 0, format, getWindowWidth(), getWindowHeight(), 0, format,
+                     GL_UNSIGNED_BYTE, nullptr);
+        glBindRenderbuffer(GL_RENDERBUFFER, mUserDepthStencilBuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, getWindowWidth(), getWindowHeight());
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mUserDepthStencilBuffer);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mUserDepthStencilBuffer);
+
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        ASSERT_GL_NO_ERROR();
+
+        glGenFramebuffers(1, &mSmallFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mSmallFBO);
+        glGenTextures(1, &mSmallColorBuffer);
+        glGenRenderbuffers(1, &mSmallDepthStencilBuffer);
+        glBindTexture(GL_TEXTURE_2D, mSmallColorBuffer);
+        glTexImage2D(GL_TEXTURE_2D, 0, format, getWindowWidth() / 2, getWindowHeight() / 2, 0,
+                     format, GL_UNSIGNED_BYTE, nullptr);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mSmallColorBuffer, 0);
+        glBindRenderbuffer(GL_RENDERBUFFER, mSmallDepthStencilBuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, getWindowWidth() / 2, getWindowHeight() / 2);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mSmallDepthStencilBuffer);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mSmallDepthStencilBuffer);
+
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        ASSERT_GL_NO_ERROR();
+
+        glGenFramebuffers(1, &mColorOnlyFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mColorOnlyFBO);
+        glGenTextures(1, &mColorOnlyColorBuffer);
+        glBindTexture(GL_TEXTURE_2D, mColorOnlyColorBuffer);
+        glTexImage2D(GL_TEXTURE_2D, 0, format, getWindowWidth(), getWindowHeight(), 0, format,
+                     GL_UNSIGNED_BYTE, nullptr);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorOnlyColorBuffer, 0);
+
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        ASSERT_GL_NO_ERROR();
+
+        glGenFramebuffers(1, &mDiffFormatFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mDiffFormatFBO);
+        glGenTextures(1, &mDiffFormatColorBuffer);
+        glBindTexture(GL_TEXTURE_2D, mDiffFormatColorBuffer);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB,
+                     GL_UNSIGNED_SHORT_5_6_5, nullptr);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mDiffFormatColorBuffer, 0);
+
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        ASSERT_GL_NO_ERROR();
+
+        glGenFramebuffers(1, &mDiffSizeFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mDiffSizeFBO);
+        glGenTextures(1, &mDiffSizeColorBuffer);
+        glBindTexture(GL_TEXTURE_2D, mDiffSizeColorBuffer);
+        glTexImage2D(GL_TEXTURE_2D, 0, format, getWindowWidth() * 2, getWindowHeight() * 2, 0,
+                     format, GL_UNSIGNED_BYTE, nullptr);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mDiffSizeColorBuffer, 0);
+
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        ASSERT_GL_NO_ERROR();
+
+        if (extensionEnabled("GL_EXT_draw_buffers"))
+        {
+            glGenFramebuffers(1, &mMRTFBO);
+            glBindFramebuffer(GL_FRAMEBUFFER, mMRTFBO);
+            glGenTextures(1, &mMRTColorBuffer0);
+            glGenTextures(1, &mMRTColorBuffer1);
+            glBindTexture(GL_TEXTURE_2D, mMRTColorBuffer0);
+            glTexImage2D(GL_TEXTURE_2D, 0, format, getWindowWidth(), getWindowHeight(), 0, format,
+                         GL_UNSIGNED_BYTE, nullptr);
+            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, mMRTColorBuffer0, 0);
+            glBindTexture(GL_TEXTURE_2D, mMRTColorBuffer1);
+            glTexImage2D(GL_TEXTURE_2D, 0, format, getWindowWidth(), getWindowHeight(), 0, format,
+                         GL_UNSIGNED_BYTE, nullptr);
+            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, mMRTColorBuffer1, 0);
+
+            ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+            ASSERT_GL_NO_ERROR();
+        }
+
+        if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
+        {
+            // Test blit between RGBA and multisampled BGRA
+            glGenTextures(1, &mRGBAColorbuffer);
+            glBindTexture(GL_TEXTURE_2D, mRGBAColorbuffer);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+                         GL_UNSIGNED_BYTE, nullptr);
+
+            glGenFramebuffers(1, &mRGBAFBO);
+            glBindFramebuffer(GL_FRAMEBUFFER, mRGBAFBO);
+            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mRGBAColorbuffer, 0);
+
+            ASSERT_GL_NO_ERROR();
+            ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+            glGenRenderbuffers(1, &mBGRAMultisampledRenderbuffer);
+            glBindRenderbuffer(GL_RENDERBUFFER, mBGRAMultisampledRenderbuffer);
+            glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_BGRA8_EXT, getWindowWidth(), getWindowHeight());
+
+            glGenFramebuffers(1, &mBGRAMultisampledFBO);
+            glBindFramebuffer(GL_FRAMEBUFFER, mBGRAMultisampledFBO);
+            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mBGRAMultisampledRenderbuffer);
+
+            ASSERT_GL_NO_ERROR();
+            ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        }
+
+        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mCheckerProgram);
+        glDeleteProgram(mBlueProgram);
+
+        glDeleteFramebuffers(1, &mUserFBO);
+        glDeleteTextures(1, &mUserColorBuffer);
+        glDeleteRenderbuffers(1, &mUserDepthStencilBuffer);
+
+        glDeleteFramebuffers(1, &mSmallFBO);
+        glDeleteTextures(1, &mSmallColorBuffer);
+        glDeleteRenderbuffers(1, &mSmallDepthStencilBuffer);
+
+        glDeleteFramebuffers(1, &mColorOnlyFBO);
+        glDeleteTextures(1, &mSmallDepthStencilBuffer);
+
+        glDeleteFramebuffers(1, &mDiffFormatFBO);
+        glDeleteTextures(1, &mDiffFormatColorBuffer);
+
+        glDeleteFramebuffers(1, &mDiffSizeFBO);
+        glDeleteTextures(1, &mDiffSizeColorBuffer);
+
+        if (extensionEnabled("GL_EXT_draw_buffers"))
+        {
+            glDeleteFramebuffers(1, &mMRTFBO);
+            glDeleteTextures(1, &mMRTColorBuffer0);
+            glDeleteTextures(1, &mMRTColorBuffer1);
+        }
+
+        if (mRGBAColorbuffer != 0)
+        {
+            glDeleteTextures(1, &mRGBAColorbuffer);
+        }
+
+        if (mRGBAFBO != 0)
+        {
+            glDeleteFramebuffers(1, &mBGRAMultisampledFBO);
+        }
+
+        if (mBGRAMultisampledRenderbuffer != 0)
+        {
+            glDeleteRenderbuffers(1, &mBGRAMultisampledRenderbuffer);
+        }
+
+        if (mBGRAMultisampledFBO != 0)
+        {
+            glDeleteFramebuffers(1, &mBGRAMultisampledFBO);
+        }
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mCheckerProgram;
+    GLuint mBlueProgram;
+
+    GLuint mOriginalFBO;
+
+    GLuint mUserFBO;
+    GLuint mUserColorBuffer;
+    GLuint mUserDepthStencilBuffer;
+
+    GLuint mSmallFBO;
+    GLuint mSmallColorBuffer;
+    GLuint mSmallDepthStencilBuffer;
+
+    GLuint mColorOnlyFBO;
+    GLuint mColorOnlyColorBuffer;
+
+    GLuint mDiffFormatFBO;
+    GLuint mDiffFormatColorBuffer;
+
+    GLuint mDiffSizeFBO;
+    GLuint mDiffSizeColorBuffer;
+
+    GLuint mMRTFBO;
+    GLuint mMRTColorBuffer0;
+    GLuint mMRTColorBuffer1;
+
+    GLuint mRGBAColorbuffer;
+    GLuint mRGBAFBO;
+
+    GLuint mBGRAMultisampledRenderbuffer;
+    GLuint mBGRAMultisampledFBO;
+};
+
+// Draw to user-created framebuffer, blit whole-buffer color to original framebuffer.
+TEST_P(BlitFramebufferANGLETest, BlitColorToDefault)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.8f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
+}
+
+// Draw to system framebuffer, blit whole-buffer color to user-created framebuffer.
+TEST_P(BlitFramebufferANGLETest, ReverseColorBlit)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.8f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
+}
+
+// blit from user-created FBO to system framebuffer, with the scissor test enabled.
+TEST_P(BlitFramebufferANGLETest, ScissoredBlit)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.8f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    glScissor(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
+    glEnable(GL_SCISSOR_TEST);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDisable(GL_SCISSOR_TEST);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255, 255, 255, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 255, 255, 255);
+}
+
+// blit from system FBO to user-created framebuffer, with the scissor test enabled.
+TEST_P(BlitFramebufferANGLETest, ReverseScissoredBlit)
+{
+    // TODO(jmadill): Triage this driver bug.
+    if (IsAMD() && IsD3D11())
+    {
+        std::cout << "Test skipped on AMD D3D11." << std::endl;
+        return;
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.8f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+    
+    glScissor(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
+    glEnable(GL_SCISSOR_TEST);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDisable(GL_SCISSOR_TEST);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+    
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255, 255, 255, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 255, 255, 255);
+}
+
+// blit from user-created FBO to system framebuffer, using region larger than buffer.
+TEST_P(BlitFramebufferANGLETest, OversizedBlit)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.8f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth() * 2, getWindowHeight() * 2, 0, 0, getWindowWidth() * 2, getWindowHeight() * 2, 
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
+}
+
+// blit from system FBO to user-created framebuffer, using region larger than buffer.
+TEST_P(BlitFramebufferANGLETest, ReverseOversizedBlit)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.8f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth() * 2, getWindowHeight() * 2, 0, 0, getWindowWidth() * 2, getWindowHeight() * 2, 
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
+}
+
+// blit from user-created FBO to system framebuffer, with depth buffer.
+TEST_P(BlitFramebufferANGLETest, BlitWithDepth)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glDepthMask(GL_TRUE);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    glEnable(GL_DEPTH_TEST);
+
+    drawQuad(mCheckerProgram, "position", 0.3f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
+                           GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    // if blit is happening correctly, this quad will not draw, because it is behind the blitted one
+    drawQuad(mBlueProgram, "position", 0.8f);
+
+    glDisable(GL_DEPTH_TEST);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
+}
+
+// blit from system FBO to user-created framebuffer, with depth buffer.
+TEST_P(BlitFramebufferANGLETest, ReverseBlitWithDepth)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    glEnable(GL_DEPTH_TEST);
+
+    drawQuad(mCheckerProgram, "position", 0.3f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
+
+    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
+                           GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    // if blit is happening correctly, this quad will not draw, because it is behind the blitted one
+
+    drawQuad(mBlueProgram, "position", 0.8f);
+
+    glDisable(GL_DEPTH_TEST);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
+}
+
+// blit from one region of the system fbo to another-- this should fail.
+TEST_P(BlitFramebufferANGLETest, BlitSameBufferOriginal)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.3f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight(), getWindowWidth() / 2, 0, getWindowWidth(), getWindowHeight(), 
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// blit from one region of the system fbo to another.
+TEST_P(BlitFramebufferANGLETest, BlitSameBufferUser)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.3f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight(), getWindowWidth() / 2, 0, getWindowWidth(), getWindowHeight(), 
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+TEST_P(BlitFramebufferANGLETest, BlitPartialColor)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, 0, getWindowHeight() / 2, getWindowWidth() / 2, getWindowHeight(),
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255, 255, 255, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4, 255, 255, 255, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 255, 255, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+}
+
+TEST_P(BlitFramebufferANGLETest, BlitDifferentSizes)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mSmallFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mSmallFBO);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(BlitFramebufferANGLETest, BlitWithMissingAttachments)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mColorOnlyFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    drawQuad(mCheckerProgram, "position", 0.3f);
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mColorOnlyFBO);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    // generate INVALID_OPERATION if the read FBO has no depth attachment
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
+                           getWindowHeight(), GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
+                           GL_NEAREST);
+
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // generate INVALID_OPERATION if the read FBO has no stencil attachment
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
+                           getWindowHeight(), GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+                           GL_NEAREST);
+
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // generate INVALID_OPERATION if we read from a missing color attachment
+    glReadBuffer(GL_COLOR_ATTACHMENT1);
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
+                           getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+TEST_P(BlitFramebufferANGLETest, BlitStencil)
+{
+    // TODO(jmadill): Figure out if we can fix this on D3D9.
+    // https://code.google.com/p/angleproject/issues/detail?id=809
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D9." << std::endl;
+        return;
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    // fill the stencil buffer with 0x1
+    glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
+    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+    glEnable(GL_STENCIL_TEST); 
+    drawQuad(mCheckerProgram, "position", 0.3f);
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClearStencil(0x0);
+    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    // depth blit request should be silently ignored, because the read FBO has no depth attachment
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
+                           GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); 
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
+
+    glStencilFunc(GL_EQUAL, 0x1, 0xFF); // only pass if stencil buffer at pixel reads 0x1
+    drawQuad(mBlueProgram, "position", 0.8f); // blue quad will draw if stencil buffer was copied
+    glDisable(GL_STENCIL_TEST);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4,   0,   0, 255, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0,   0, 255, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0,   0, 255, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0,   0, 255, 255);
+}
+
+// make sure that attempting to blit a partial depth buffer issues an error
+TEST_P(BlitFramebufferANGLETest, BlitPartialDepthStencil)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 
+                           getWindowWidth() / 2, getWindowHeight() / 2, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test blit with MRT framebuffers
+TEST_P(BlitFramebufferANGLETest, BlitMRT)
+{
+    if (!extensionEnabled("GL_EXT_draw_buffers"))
+    {
+        return;
+    }
+
+    GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mMRTFBO);
+    glDrawBuffersEXT(2, drawBuffers);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mColorOnlyFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    
+    drawQuad(mCheckerProgram, "position", 0.8f);
+    
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mColorOnlyFBO);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mMRTFBO);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mMRTFBO);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
+
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, 0, 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mMRTColorBuffer0, 0);
+
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
+    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
+    EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
+
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mMRTColorBuffer0, 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, mMRTColorBuffer1, 0);
+}
+
+// Make sure that attempts to stretch in a blit call issue an error
+TEST_P(BlitFramebufferANGLETest, ErrorStretching)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 
+                           getWindowWidth(), getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Make sure that attempts to flip in a blit call issue an error
+TEST_P(BlitFramebufferANGLETest, ErrorFlipping)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, getWindowWidth() / 2, getWindowHeight() / 2, 
+                           0, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+TEST_P(BlitFramebufferANGLETest, Errors)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    drawQuad(mCheckerProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
+                           GL_COLOR_BUFFER_BIT, GL_LINEAR);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
+                           GL_COLOR_BUFFER_BIT | 234, GL_NEAREST);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mDiffFormatFBO);
+
+    glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
+                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
+    {
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, mBGRAMultisampledFBO);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRGBAFBO);
+        EXPECT_GL_NO_ERROR();
+
+        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
+                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+
+}
+
+// TODO(geofflang): Fix the dependence on glBlitFramebufferANGLE without checks and assuming the
+// default framebuffer is BGRA to enable the GL and GLES backends. (http://anglebug.com/1289)
+
+class BlitFramebufferTest : public ANGLETest
+{
+  protected:
+    BlitFramebufferTest()
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+};
+
+// Tests resolving a multisample depth buffer.
+TEST_P(BlitFramebufferTest, MultisampleDepth)
+{
+    // TODO(jmadill): Triage this driver bug.
+    if (IsAMD() && IsD3D11())
+    {
+        std::cout << "Test skipped on AMD D3D11." << std::endl;
+        return;
+    }
+
+    GLRenderbuffer renderbuf;
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
+    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 256, 256);
+
+    const std::string &vertex =
+        "#version 300 es\n"
+        "in vec2 position;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(position, 0.0, 0.5);\n"
+        "}";
+    const std::string &fragment =
+        "#version 300 es\n"
+        "out mediump vec4 red;\n"
+        "void main() {\n"
+        "   red = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "   gl_FragDepth = 0.5;\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(drawRed, vertex, fragment);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuf.get());
+
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    glClearDepthf(0.5f);
+    glClear(GL_DEPTH_BUFFER_BIT);
+
+    GLRenderbuffer destRenderbuf;
+    glBindRenderbuffer(GL_RENDERBUFFER, destRenderbuf.get());
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 256, 256);
+
+    GLFramebuffer resolved;
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolved.get());
+    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+                              destRenderbuf.get());
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer.get());
+    glBlitFramebuffer(0, 0, 256, 256, 0, 0, 256, 256, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, resolved.get());
+
+    GLTexture colorbuf;
+    glBindTexture(GL_TEXTURE_2D, colorbuf.get());
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 256);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuf.get(), 0);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Clear to green
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Draw with 0.5f test and the test should pass.
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_EQUAL);
+    drawQuad(drawRed.get(), "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test resolving a multisampled stencil buffer.
+TEST_P(BlitFramebufferTest, MultisampleStencil)
+{
+    GLRenderbuffer renderbuf;
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
+    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_STENCIL_INDEX8, 256, 256);
+
+    const std::string &vertex =
+        "#version 300 es\n"
+        "in vec2 position;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(position, 0.0, 1.0);\n"
+        "}";
+    const std::string &fragment =
+        "#version 300 es\n"
+        "out mediump vec4 red;\n"
+        "void main() {\n"
+        "   red = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(drawRed, vertex, fragment);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuf.get());
+
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // fill the stencil buffer with 0x1
+    glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
+    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+    glEnable(GL_STENCIL_TEST);
+    drawQuad(drawRed.get(), "position", 0.5f);
+
+    GLTexture destColorbuf;
+    glBindTexture(GL_TEXTURE_2D, destColorbuf.get());
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 256);
+
+    GLRenderbuffer destRenderbuf;
+    glBindRenderbuffer(GL_RENDERBUFFER, destRenderbuf.get());
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 256, 256);
+
+    GLFramebuffer resolved;
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolved.get());
+    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                           destColorbuf.get(), 0);
+    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              destRenderbuf.get());
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer.get());
+    glBlitFramebuffer(0, 0, 256, 256, 0, 0, 256, 256, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, resolved.get());
+
+    ASSERT_GL_NO_ERROR();
+
+    // Clear to green
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Draw red if the stencil is 0x1, which should be true after the blit/resolve.
+    glStencilFunc(GL_EQUAL, 0x1, 0xFF);
+    drawQuad(drawRed.get(), "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(BlitFramebufferANGLETest,
+                       ES2_D3D9(),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE));
+
+ANGLE_INSTANTIATE_TEST(BlitFramebufferTest, ES3_D3D11());
diff --git a/src/third_party/angle/src/tests/gl_tests/BufferDataTest.cpp b/src/third_party/angle/src/tests/gl_tests/BufferDataTest.cpp
new file mode 100644
index 0000000..e63b5b2
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/BufferDataTest.cpp
@@ -0,0 +1,594 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include "random_utils.h"
+
+#include <stdint.h>
+
+using namespace angle;
+
+class BufferDataTest : public ANGLETest
+{
+  protected:
+    BufferDataTest()
+    {
+        setWindowWidth(16);
+        setWindowHeight(16);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+
+        mBuffer = 0;
+        mProgram = 0;
+        mAttribLocation = -1;
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const char * vsSource = SHADER_SOURCE
+        (
+            attribute vec4 position;
+            attribute float in_attrib;
+            varying float v_attrib;
+            void main()
+            {
+                v_attrib = in_attrib;
+                gl_Position = position;
+            }
+        );
+
+        const char * fsSource = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying float v_attrib;
+            void main()
+            {
+                gl_FragColor = vec4(v_attrib, 0, 0, 1);
+            }
+        );
+
+        glGenBuffers(1, &mBuffer);
+        ASSERT_NE(mBuffer, 0U);
+
+        mProgram = CompileProgram(vsSource, fsSource);
+        ASSERT_NE(mProgram, 0U);
+
+        mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
+        ASSERT_NE(mAttribLocation, -1);
+
+        glClearColor(0, 0, 0, 0);
+        glClearDepthf(0.0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        glDisable(GL_DEPTH_TEST);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteBuffers(1, &mBuffer);
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mBuffer;
+    GLuint mProgram;
+    GLint mAttribLocation;
+};
+
+TEST_P(BufferDataTest, NULLData)
+{
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    EXPECT_GL_NO_ERROR();
+
+    const int numIterations = 128;
+    for (int i = 0; i < numIterations; ++i)
+    {
+        GLsizei bufferSize = sizeof(GLfloat) * (i + 1);
+        glBufferData(GL_ARRAY_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
+        EXPECT_GL_NO_ERROR();
+
+        for (int j = 0; j < bufferSize; j++)
+        {
+            for (int k = 0; k < bufferSize - j; k++)
+            {
+                glBufferSubData(GL_ARRAY_BUFFER, k, j, nullptr);
+                ASSERT_GL_NO_ERROR();
+            }
+        }
+    }
+}
+
+TEST_P(BufferDataTest, ZeroNonNULLData)
+{
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    EXPECT_GL_NO_ERROR();
+
+    char *zeroData = new char[0];
+    glBufferData(GL_ARRAY_BUFFER, 0, zeroData, GL_STATIC_DRAW);
+    EXPECT_GL_NO_ERROR();
+
+    glBufferSubData(GL_ARRAY_BUFFER, 0, 0, zeroData);
+    EXPECT_GL_NO_ERROR();
+
+    delete [] zeroData;
+}
+
+TEST_P(BufferDataTest, NULLResolvedData)
+{
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_DYNAMIC_DRAW);
+
+    glUseProgram(mProgram);
+    glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
+    glEnableVertexAttribArray(mAttribLocation);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+    drawQuad(mProgram, "position", 0.5f);
+}
+
+// Tests that a huge allocation returns GL_OUT_OF_MEMORY
+// TODO(jmadill): Figure out how to test this reliably on the Chromium bots
+TEST_P(BufferDataTest, DISABLED_HugeSetDataShouldNotCrash)
+{
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    EXPECT_GL_NO_ERROR();
+
+    GLsizei allocSize = std::numeric_limits<GLsizei>::max() >> 2;
+
+    uint8_t *data = nullptr;
+    while (data == nullptr && allocSize >= 4)
+    {
+        data = new (std::nothrow) uint8_t[allocSize];
+
+        if (data == nullptr)
+        {
+            allocSize >>= 1;
+        }
+    }
+
+    ASSERT_NE(static_cast<uint8_t *>(nullptr), data);
+    memset(data, 0, allocSize);
+
+    float * fValue = reinterpret_cast<float*>(data);
+    for (unsigned int f = 0; f < 6; f++)
+    {
+        fValue[f] = 1.0f;
+    }
+
+    glBufferData(GL_ARRAY_BUFFER, allocSize, data, GL_STATIC_DRAW);
+
+    GLenum error = glGetError();
+    if (error == GL_NO_ERROR)
+    {
+        // If we didn't fail because of an out of memory error, try drawing a quad
+        // using the large buffer
+
+        // DISABLED because it takes a long time, but left for posterity
+
+        //glUseProgram(mProgram);
+        // glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
+        // glEnableVertexAttribArray(mAttribLocation);
+        // glBindBuffer(GL_ARRAY_BUFFER, 0);
+        // drawQuad(mProgram, "position", 0.5f);
+        // swapBuffers();
+
+        //// Draw operations can also generate out-of-memory, which is in-spec
+        //error = glGetError();
+        //if (error == GL_NO_ERROR)
+        //{
+        //    GLint viewportSize[4];
+        //    glGetIntegerv(GL_VIEWPORT, viewportSize);
+
+        //    GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
+        //    GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
+
+        //    EXPECT_PIXEL_EQ(midPixelX, midPixelY, 255, 0, 0, 255);
+        //}
+        //else
+        //{
+        //    EXPECT_EQ(GL_OUT_OF_MEMORY, error);
+        //}
+    }
+    else
+    {
+        EXPECT_GLENUM_EQ(GL_OUT_OF_MEMORY, error);
+    }
+
+    delete[] data;
+}
+
+// Internally in D3D, we promote dynamic data to static after many draw loops. This code tests
+// path.
+TEST_P(BufferDataTest, RepeatedDrawWithDynamic)
+{
+    std::vector<GLfloat> data;
+    for (int i = 0; i < 16; ++i)
+    {
+        data.push_back(static_cast<GLfloat>(i));
+    }
+
+    glUseProgram(mProgram);
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
+    glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glEnableVertexAttribArray(mAttribLocation);
+
+    for (int drawCount = 0; drawCount < 40; ++drawCount)
+    {
+        drawQuad(mProgram, "position", 0.5f);
+    }
+
+    EXPECT_GL_NO_ERROR();
+}
+
+class IndexedBufferCopyTest : public ANGLETest
+{
+  protected:
+    IndexedBufferCopyTest()
+    {
+        setWindowWidth(16);
+        setWindowHeight(16);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const char * vsSource = SHADER_SOURCE
+        (
+            attribute vec3 in_attrib;
+            varying vec3 v_attrib;
+            void main()
+            {
+                v_attrib = in_attrib;
+                gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
+                gl_PointSize = 100.0;
+            }
+        );
+
+        const char * fsSource = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec3 v_attrib;
+            void main()
+            {
+                gl_FragColor = vec4(v_attrib, 1);
+            }
+        );
+
+        glGenBuffers(2, mBuffers);
+        ASSERT_NE(mBuffers[0], 0U);
+        ASSERT_NE(mBuffers[1], 0U);
+
+        glGenBuffers(1, &mElementBuffer);
+        ASSERT_NE(mElementBuffer, 0U);
+
+        mProgram = CompileProgram(vsSource, fsSource);
+        ASSERT_NE(mProgram, 0U);
+
+        mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
+        ASSERT_NE(mAttribLocation, -1);
+
+        glClearColor(0, 0, 0, 0);
+        glDisable(GL_DEPTH_TEST);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteBuffers(2, mBuffers);
+        glDeleteBuffers(1, &mElementBuffer);
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mBuffers[2];
+    GLuint mElementBuffer;
+    GLuint mProgram;
+    GLint mAttribLocation;
+};
+
+// The following test covers an ANGLE bug where our index ranges
+// weren't updated from CopyBufferSubData calls
+// https://code.google.com/p/angleproject/issues/detail?id=709
+TEST_P(IndexedBufferCopyTest, IndexRangeBug)
+{
+    // TODO(geofflang): Figure out why this fails on AMD OpenGL (http://anglebug.com/1291)
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test disabled on AMD OpenGL." << std::endl;
+        return;
+    }
+
+    unsigned char vertexData[] = { 255, 0, 0, 0, 0, 0 };
+    unsigned int indexData[] = { 0, 1 };
+
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[0]);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(char) * 6, vertexData, GL_STATIC_DRAW);
+
+    glUseProgram(mProgram);
+    glVertexAttribPointer(mAttribLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE, 3, nullptr);
+    glEnableVertexAttribArray(mAttribLocation);
+
+    ASSERT_GL_NO_ERROR();
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 1, indexData, GL_STATIC_DRAW);
+
+    glUseProgram(mProgram);
+
+    ASSERT_GL_NO_ERROR();
+
+    glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
+
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    glBindBuffer(GL_COPY_READ_BUFFER, mBuffers[1]);
+    glBufferData(GL_COPY_READ_BUFFER, 4, &indexData[1], GL_STATIC_DRAW);
+
+    glBindBuffer(GL_COPY_WRITE_BUFFER, mElementBuffer);
+
+    glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(int));
+
+    ASSERT_GL_NO_ERROR();
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
+
+    unsigned char newData[] = { 0, 255, 0 };
+    glBufferSubData(GL_ARRAY_BUFFER, 3, 3, newData);
+
+    glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
+
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+}
+
+class BufferDataTestES3 : public BufferDataTest
+{
+};
+
+// The following test covers an ANGLE bug where the buffer storage
+// is not resized by Buffer11::getLatestBufferStorage when needed.
+// https://code.google.com/p/angleproject/issues/detail?id=897
+TEST_P(BufferDataTestES3, BufferResizing)
+{
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    ASSERT_GL_NO_ERROR();
+
+    // Allocate a buffer with one byte
+    uint8_t singleByte[] = { 0xaa };
+    glBufferData(GL_ARRAY_BUFFER, 1, singleByte, GL_STATIC_DRAW);
+
+    // Resize the buffer
+    // To trigger the bug, the buffer need to be big enough because some hardware copy buffers
+    // by chunks of pages instead of the minimum number of bytes neeeded.
+    const size_t numBytes = 4096*4;
+    glBufferData(GL_ARRAY_BUFFER, numBytes, nullptr, GL_STATIC_DRAW);
+
+    // Copy the original data to the buffer
+    uint8_t srcBytes[numBytes];
+    for (size_t i = 0; i < numBytes; ++i)
+    {
+        srcBytes[i] = static_cast<uint8_t>(i);
+    }
+
+    void *dest = glMapBufferRange(GL_ARRAY_BUFFER, 0, numBytes, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
+
+    ASSERT_GL_NO_ERROR();
+
+    memcpy(dest, srcBytes, numBytes);
+    glUnmapBuffer(GL_ARRAY_BUFFER);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Create a new buffer and copy the data to it
+    GLuint readBuffer;
+    glGenBuffers(1, &readBuffer);
+    glBindBuffer(GL_COPY_WRITE_BUFFER, readBuffer);
+    uint8_t zeros[numBytes];
+    for (size_t i = 0; i < numBytes; ++i)
+    {
+        zeros[i] = 0;
+    }
+    glBufferData(GL_COPY_WRITE_BUFFER, numBytes, zeros, GL_STATIC_DRAW);
+    glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numBytes);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Read back the data and compare it to the original
+    uint8_t *data = reinterpret_cast<uint8_t*>(glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numBytes, GL_MAP_READ_BIT));
+
+    ASSERT_GL_NO_ERROR();
+
+    for (size_t i = 0; i < numBytes; ++i)
+    {
+        EXPECT_EQ(srcBytes[i], data[i]);
+    }
+    glUnmapBuffer(GL_COPY_WRITE_BUFFER);
+
+    glDeleteBuffers(1, &readBuffer);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Verify OES_mapbuffer is present if EXT_map_buffer_range is.
+TEST_P(BufferDataTest, ExtensionDependency)
+{
+    if (extensionEnabled("GL_EXT_map_buffer_range"))
+    {
+        ASSERT_TRUE(extensionEnabled("GL_OES_mapbuffer"));
+    }
+}
+
+// Test mapping with the OES extension.
+TEST_P(BufferDataTest, MapBufferOES)
+{
+    if (!extensionEnabled("GL_EXT_map_buffer_range"))
+    {
+        // Needed for test validation.
+        return;
+    }
+
+    std::vector<uint8_t> data(1024);
+    FillVectorWithRandomUBytes(&data);
+
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
+    glBufferData(GL_ARRAY_BUFFER, data.size(), nullptr, GL_STATIC_DRAW);
+
+    // Validate that other map flags don't work.
+    void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
+    EXPECT_EQ(nullptr, badMapPtr);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // Map and write.
+    void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
+    ASSERT_NE(nullptr, mapPtr);
+    ASSERT_GL_NO_ERROR();
+    memcpy(mapPtr, data.data(), data.size());
+    glUnmapBufferOES(GL_ARRAY_BUFFER);
+
+    // Validate data with EXT_map_buffer_range
+    void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
+    ASSERT_NE(nullptr, readMapPtr);
+    ASSERT_GL_NO_ERROR();
+    std::vector<uint8_t> actualData(data.size());
+    memcpy(actualData.data(), readMapPtr, data.size());
+    glUnmapBufferOES(GL_ARRAY_BUFFER);
+
+    EXPECT_EQ(data, actualData);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(BufferDataTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(BufferDataTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(IndexedBufferCopyTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+#ifdef _WIN64
+
+// Test a bug where an integer overflow bug could trigger a crash in D3D.
+// The test uses 8 buffers with a size just under 0x2000000 to overflow max uint
+// (with the internal D3D rounding to 16-byte values) and trigger the bug.
+// Only handle this bug on 64-bit Windows for now. Harder to repro on 32-bit.
+class BufferDataOverflowTest : public ANGLETest
+{
+  protected:
+    BufferDataOverflowTest()
+    {
+    }
+};
+
+// See description above.
+TEST_P(BufferDataOverflowTest, VertexBufferIntegerOverflow)
+{
+    // These values are special, to trigger the rounding bug.
+    unsigned int numItems = 0x7FFFFFE;
+    constexpr GLsizei bufferCnt = 8;
+
+    std::vector<GLBuffer> buffers(bufferCnt);
+
+    std::stringstream vertexShaderStr;
+
+    for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
+    {
+        vertexShaderStr << "attribute float attrib" << bufferIndex << ";\n";
+    }
+
+    vertexShaderStr << "attribute vec2 position;\n"
+                       "varying float v_attrib;\n"
+                       "void main() {\n"
+                       "  gl_Position = vec4(position, 0, 1);\n"
+                       "  v_attrib = 0.0;\n";
+
+    for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
+    {
+        vertexShaderStr << "v_attrib += attrib" << bufferIndex << ";\n";
+    }
+
+    vertexShaderStr << "}";
+
+    const std::string &fragmentShader =
+        "varying highp float v_attrib;\n"
+        "void main() {\n"
+        "  gl_FragColor = vec4(v_attrib, 0, 0, 1);\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(program, vertexShaderStr.str(), fragmentShader);
+    glUseProgram(program.get());
+
+    std::vector<GLfloat> data(numItems, 1.0f);
+
+    for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, buffers[bufferIndex].get());
+        glBufferData(GL_ARRAY_BUFFER, numItems * sizeof(float), &data[0], GL_DYNAMIC_DRAW);
+
+        std::stringstream attribNameStr;
+        attribNameStr << "attrib" << bufferIndex;
+
+        GLint attribLocation = glGetAttribLocation(program.get(), attribNameStr.str().c_str());
+        ASSERT_NE(-1, attribLocation);
+
+        glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
+        glEnableVertexAttribArray(attribLocation);
+    }
+
+    GLint positionLocation = glGetAttribLocation(program.get(), "position");
+    ASSERT_NE(-1, positionLocation);
+    glDisableVertexAttribArray(positionLocation);
+    glVertexAttrib2f(positionLocation, 1.0f, 1.0f);
+
+    EXPECT_GL_NO_ERROR();
+    glDrawArrays(GL_TRIANGLES, 0, numItems);
+    EXPECT_GL_ERROR(GL_OUT_OF_MEMORY);
+}
+
+// Tests a security bug in our CopyBufferSubData validation (integer overflow).
+TEST_P(BufferDataOverflowTest, CopySubDataValidation)
+{
+    GLBuffer readBuffer, writeBuffer;
+
+    glBindBuffer(GL_COPY_READ_BUFFER, readBuffer.get());
+    glBindBuffer(GL_COPY_WRITE_BUFFER, writeBuffer.get());
+
+    constexpr int bufSize = 100;
+
+    glBufferData(GL_COPY_READ_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
+    glBufferData(GL_COPY_WRITE_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
+
+    GLintptr big = std::numeric_limits<GLintptr>::max() - bufSize + 90;
+
+    glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, big, 0, 50);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, big, 50);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+ANGLE_INSTANTIATE_TEST(BufferDataOverflowTest, ES3_D3D11());
+
+#endif  // _WIN64
diff --git a/src/third_party/angle/src/tests/gl_tests/BuiltinVariableTest.cpp b/src/third_party/angle/src/tests/gl_tests/BuiltinVariableTest.cpp
new file mode 100644
index 0000000..cbb399d
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/BuiltinVariableTest.cpp
@@ -0,0 +1,209 @@
+//
+// Copyright 2016 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.
+//
+// BuiltinVariableTest:
+//   Tests the correctness of the builtin GLSL variables.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class BuiltinVariableVertexIdTest : public ANGLETest
+{
+  protected:
+    BuiltinVariableVertexIdTest()
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource =
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "in vec4 position;\n"
+            "in int expectedID;"
+            "out vec4 color;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "    color = vec4(gl_VertexID != expectedID, gl_VertexID == expectedID, 0.0, 1.0);"
+            "}\n";
+
+        const std::string fsSource =
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "in vec4 color;\n"
+            "out vec4 fragColor;\n"
+            "void main()\n"
+            "{\n"
+            "    fragColor = color;\n"
+            "}\n";
+
+        mProgram = CompileProgram(vsSource, fsSource);
+        ASSERT_NE(0u, mProgram);
+
+        mPositionLocation = glGetAttribLocation(mProgram, "position");
+        ASSERT_NE(-1, mPositionLocation);
+        mExpectedIdLocation = glGetAttribLocation(mProgram, "expectedID");
+        ASSERT_NE(-1, mExpectedIdLocation);
+
+        static const float positions[] =
+        {
+             0.5,  0.5,
+            -0.5,  0.5,
+             0.5, -0.5,
+            -0.5, -0.5
+        };
+        glGenBuffers(1, &mPositionBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, mPositionBuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteBuffers(1, &mPositionBuffer);
+        glDeleteBuffers(1, &mExpectedIdBuffer);
+        glDeleteBuffers(1, &mIndexBuffer);
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    // Renders a primitive using the specified mode, each vertex color will
+    // be green if gl_VertexID is correct, red otherwise.
+    void runTest(GLuint drawMode, const std::vector<GLint> &indices, int count)
+    {
+        glClearColor(0.0, 0.0, 0.0, 1.0);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        glGenBuffers(1, &mIndexBuffer);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * indices.size(), indices.data(),
+                     GL_STATIC_DRAW);
+
+        std::vector<GLint> expectedIds = makeRange(count);
+
+        glGenBuffers(1, &mExpectedIdBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, mExpectedIdBuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(GLint) * expectedIds.size(), expectedIds.data(),
+                     GL_STATIC_DRAW);
+
+        glBindBuffer(GL_ARRAY_BUFFER, mPositionBuffer);
+        glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
+        glEnableVertexAttribArray(mPositionLocation);
+
+        glBindBuffer(GL_ARRAY_BUFFER, mExpectedIdBuffer);
+        glVertexAttribIPointer(mExpectedIdLocation, 1, GL_INT, 0, 0);
+        glEnableVertexAttribArray(mExpectedIdLocation);
+
+        glUseProgram(mProgram);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+        glDrawElements(drawMode, count, GL_UNSIGNED_INT, 0);
+
+        std::vector<GLColor> pixels(getWindowWidth() * getWindowHeight());
+        glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
+                     pixels.data());
+
+        ASSERT_GL_NO_ERROR();
+
+        const GLColor green(0, 255, 0, 255);
+        const GLColor black(0, 0, 0, 255);
+
+        for (const auto &pixel : pixels)
+        {
+            EXPECT_TRUE(pixel == green || pixel == black);
+        }
+    }
+
+    std::vector<GLint> makeRange(int n) const
+    {
+        std::vector<GLint> result;
+        for (int i = 0; i < n; i++)
+        {
+            result.push_back(i);
+        }
+
+        return result;
+    }
+
+    GLuint mPositionBuffer   = 0;
+    GLuint mExpectedIdBuffer = 0;
+    GLuint mIndexBuffer      = 0;
+
+    GLuint mProgram           = 0;
+    GLint mPositionLocation   = -1;
+    GLint mExpectedIdLocation = -1;
+};
+
+// Test gl_VertexID when rendering points
+TEST_P(BuiltinVariableVertexIdTest, Points)
+{
+    runTest(GL_POINTS, makeRange(4), 4);
+}
+
+// Test gl_VertexID when rendering line strips
+TEST_P(BuiltinVariableVertexIdTest, LineStrip)
+{
+    runTest(GL_LINE_STRIP, makeRange(4), 4);
+}
+
+// Test gl_VertexID when rendering line loops
+TEST_P(BuiltinVariableVertexIdTest, LineLoop)
+{
+    runTest(GL_LINE_LOOP, makeRange(4), 4);
+}
+
+// Test gl_VertexID when rendering lines
+TEST_P(BuiltinVariableVertexIdTest, Lines)
+{
+    runTest(GL_LINES, makeRange(4), 4);
+}
+
+// Test gl_VertexID when rendering triangle strips
+TEST_P(BuiltinVariableVertexIdTest, TriangleStrip)
+{
+    runTest(GL_TRIANGLE_STRIP, makeRange(4), 4);
+}
+
+// Test gl_VertexID when rendering triangle fans
+TEST_P(BuiltinVariableVertexIdTest, TriangleFan)
+{
+    std::vector<GLint> indices;
+    indices.push_back(0);
+    indices.push_back(1);
+    indices.push_back(3);
+    indices.push_back(2);
+    runTest(GL_TRIANGLE_FAN, indices, 4);
+}
+
+// Test gl_VertexID when rendering triangles
+TEST_P(BuiltinVariableVertexIdTest, Triangles)
+{
+    std::vector<GLint> indices;
+    indices.push_back(0);
+    indices.push_back(1);
+    indices.push_back(2);
+    indices.push_back(1);
+    indices.push_back(2);
+    indices.push_back(3);
+    runTest(GL_TRIANGLES, indices, 6);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(BuiltinVariableVertexIdTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/ClearTest.cpp b/src/third_party/angle/src/tests/gl_tests/ClearTest.cpp
new file mode 100644
index 0000000..1e95ed4
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ClearTest.cpp
@@ -0,0 +1,480 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include "random_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+Vector4 RandomVec4(int seed, float minValue, float maxValue)
+{
+    RNG rng(seed);
+    srand(seed);
+    return Vector4(
+        rng.randomFloatBetween(minValue, maxValue), rng.randomFloatBetween(minValue, maxValue),
+        rng.randomFloatBetween(minValue, maxValue), rng.randomFloatBetween(minValue, maxValue));
+}
+
+GLColor Vec4ToColor(const Vector4 &vec)
+{
+    GLColor color;
+    color.R = static_cast<uint8_t>(vec.x() * 255.0f);
+    color.G = static_cast<uint8_t>(vec.y() * 255.0f);
+    color.B = static_cast<uint8_t>(vec.z() * 255.0f);
+    color.A = static_cast<uint8_t>(vec.w() * 255.0f);
+    return color;
+};
+
+class ClearTestBase : public ANGLETest
+{
+  protected:
+    ClearTestBase() : mProgram(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        mFBOs.resize(2, 0);
+        glGenFramebuffers(2, mFBOs.data());
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        if (!mFBOs.empty())
+        {
+            glDeleteFramebuffers(static_cast<GLsizei>(mFBOs.size()), mFBOs.data());
+        }
+
+        if (!mTextures.empty())
+        {
+            glDeleteTextures(static_cast<GLsizei>(mTextures.size()), mTextures.data());
+        }
+
+        ANGLETest::TearDown();
+    }
+
+    void setupDefaultProgram()
+    {
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+
+            void main()
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+
+            void main()
+            {
+                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+    }
+
+    GLuint mProgram;
+    std::vector<GLuint> mFBOs;
+    std::vector<GLuint> mTextures;
+};
+
+class ClearTest : public ClearTestBase {};
+class ClearTestES3 : public ClearTestBase {};
+
+// Test clearing the default framebuffer
+TEST_P(ClearTest, DefaultFramebuffer)
+{
+    glClearColor(0.25f, 0.5f, 0.5f, 0.5f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_NEAR(0, 0, 64, 128, 128, 128, 1.0);
+}
+
+// Test clearing a RGBA8 Framebuffer
+TEST_P(ClearTest, RGBA8Framebuffer)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+
+    glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    EXPECT_PIXEL_NEAR(0, 0, 128, 128, 128, 128, 1.0);
+}
+
+TEST_P(ClearTest, ClearIssue)
+{
+    // TODO(geofflang): Figure out why this is broken on Intel OpenGL
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_LEQUAL);
+
+    glClearColor(0.0, 1.0, 0.0, 1.0);
+    glClearDepthf(0.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
+
+    GLuint rbo;
+    glGenRenderbuffers(1, &rbo);
+    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, 16, 16);
+
+    EXPECT_GL_NO_ERROR();
+
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
+
+    EXPECT_GL_NO_ERROR();
+
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClearDepthf(1.0f);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+    setupDefaultProgram();
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+}
+
+// Requires ES3
+// This tests a bug where in a masked clear when calling "ClearBuffer", we would
+// mistakenly clear every channel (including the masked-out ones)
+TEST_P(ClearTestES3, MaskedClearBufferBug)
+{
+    unsigned char pixelData[] = { 255, 255, 255, 255 };
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
+
+    GLuint textures[2];
+    glGenTextures(2, &textures[0]);
+
+    glBindTexture(GL_TEXTURE_2D, textures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelData);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
+
+    glBindTexture(GL_TEXTURE_2D, textures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelData);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
+
+    float clearValue[] = { 0, 0.5f, 0.5f, 1.0f };
+    GLenum drawBuffers[] = { GL_NONE, GL_COLOR_ATTACHMENT1 };
+    glDrawBuffers(2, drawBuffers);
+    glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
+    glClearBufferfv(GL_COLOR, 1, clearValue);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
+
+    glReadBuffer(GL_COLOR_ATTACHMENT1);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_NEAR(0, 0, 0, 127, 255, 255, 1);
+
+    glDeleteTextures(2, textures);
+}
+
+TEST_P(ClearTestES3, BadFBOSerialBug)
+{
+    // First make a simple framebuffer, and clear it to green
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
+
+    GLuint textures[2];
+    glGenTextures(2, &textures[0]);
+
+    glBindTexture(GL_TEXTURE_2D, textures[0]);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
+
+    GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
+    glDrawBuffers(1, drawBuffers);
+
+    float clearValues1[] = { 0.0f, 1.0f, 0.0f, 1.0f };
+    glClearBufferfv(GL_COLOR, 0, clearValues1);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    // Next make a second framebuffer, and draw it to red
+    // (Triggers bad applied render target serial)
+    GLuint fbo2;
+    glGenFramebuffers(1, &fbo2);
+    ASSERT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
+
+    glBindTexture(GL_TEXTURE_2D, textures[1]);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1], 0);
+
+    glDrawBuffers(1, drawBuffers);
+
+    setupDefaultProgram();
+    drawQuad(mProgram, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    // Check that the first framebuffer is still green.
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    glDeleteTextures(2, textures);
+    glDeleteFramebuffers(1, &fbo2);
+}
+
+// Test that SRGB framebuffers clear to the linearized clear color
+TEST_P(ClearTestES3, SRGBClear)
+{
+    // TODO(jmadill): figure out why this fails
+    if (IsIntel() && GetParam() == ES3_OPENGL())
+    {
+        std::cout << "Test skipped on Intel due to failures." << std::endl;
+        return;
+    }
+
+    // First make a simple framebuffer, and clear it
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_SRGB8_ALPHA8, getWindowWidth(), getWindowHeight());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+
+    glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    EXPECT_PIXEL_NEAR(0, 0, 188, 188, 188, 128, 1.0);
+}
+
+// Test that framebuffers with mixed SRGB/Linear attachments clear to the correct color for each
+// attachment
+TEST_P(ClearTestES3, MixedSRGBClear)
+{
+    // TODO(cwallez) figure out why it is broken on Intel on Mac
+#if defined(ANGLE_PLATFORM_APPLE)
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel on Mac." << std::endl;
+        return;
+    }
+#endif
+
+    // TODO(jmadill): figure out why this fails
+    if (IsIntel() && GetParam() == ES3_OPENGL())
+    {
+        std::cout << "Test skipped on Intel due to failures." << std::endl;
+        return;
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
+
+    GLuint textures[2];
+    glGenTextures(2, &textures[0]);
+
+    glBindTexture(GL_TEXTURE_2D, textures[0]);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_SRGB8_ALPHA8, getWindowWidth(), getWindowHeight());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
+
+    glBindTexture(GL_TEXTURE_2D, textures[1]);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
+
+    GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
+    glDrawBuffers(2, drawBuffers);
+
+    // Clear both textures
+    glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0);
+
+    // Check value of texture0
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
+    EXPECT_PIXEL_NEAR(0, 0, 188, 188, 188, 128, 1.0);
+
+    // Check value of texture1
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1], 0);
+    EXPECT_PIXEL_NEAR(0, 0, 128, 128, 128, 128, 1.0);
+}
+
+// This test covers a D3D11 bug where calling ClearRenderTargetView sometimes wouldn't sync
+// before a draw call. The test draws small quads to a larger FBO (the default back buffer).
+// Before each blit to the back buffer it clears the quad to a certain color using
+// ClearBufferfv to give a solid color. The sync problem goes away if we insert a call to
+// flush or finish after ClearBufferfv or each draw.
+TEST_P(ClearTestES3, RepeatedClear)
+{
+    if (IsD3D11() && (IsNVIDIA() || IsIntel()))
+    {
+        std::cout << "Test skipped on Nvidia and Intel D3D11." << std::endl;
+        return;
+    }
+
+    const std::string &vertexSource =
+        "#version 300 es\n"
+        "in highp vec2 position;\n"
+        "out highp vec2 v_coord;\n"
+        "void main(void)\n"
+        "{\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "    vec2 texCoord = (position * 0.5) + 0.5;\n"
+        "    v_coord = texCoord;\n"
+        "}\n";
+
+    const std::string &fragmentSource =
+        "#version 300 es\n"
+        "in highp vec2 v_coord;\n"
+        "out highp vec4 color;\n"
+        "uniform sampler2D tex;\n"
+        "void main()\n"
+        "{\n"
+        "    color = texture(tex, v_coord);\n"
+        "}\n";
+
+    mProgram = CompileProgram(vertexSource, fragmentSource);
+    ASSERT_NE(0u, mProgram);
+
+    mTextures.resize(1, 0);
+    glGenTextures(1, mTextures.data());
+
+    GLenum format           = GL_RGBA8;
+    const int numRowsCols   = 3;
+    const int cellSize      = 32;
+    const int fboSize       = cellSize;
+    const int backFBOSize   = cellSize * numRowsCols;
+    const float fmtValueMin = 0.0f;
+    const float fmtValueMax = 1.0f;
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexStorage2D(GL_TEXTURE_2D, 1, format, fboSize, fboSize);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    ASSERT_GL_NO_ERROR();
+
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // larger fbo bound -- clear to transparent black
+    glUseProgram(mProgram);
+    GLint uniLoc = glGetUniformLocation(mProgram, "tex");
+    ASSERT_NE(-1, uniLoc);
+    glUniform1i(uniLoc, 0);
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    ASSERT_NE(-1, positionLocation);
+
+    glUseProgram(mProgram);
+
+    for (int cellY = 0; cellY < numRowsCols; cellY++)
+    {
+        for (int cellX = 0; cellX < numRowsCols; cellX++)
+        {
+            int seed            = cellX + cellY * numRowsCols;
+            const Vector4 color = RandomVec4(seed, fmtValueMin, fmtValueMax);
+
+            glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
+            glClearBufferfv(GL_COLOR, 0, color.data());
+
+            glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+            // Method 1: Set viewport and draw full-viewport quad
+            glViewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
+            drawQuad(mProgram, "position", 0.5f);
+
+            // Uncommenting the glFinish call seems to make the test pass.
+            // glFinish();
+        }
+    }
+
+    std::vector<GLColor> pixelData(backFBOSize * backFBOSize);
+    glReadPixels(0, 0, backFBOSize, backFBOSize, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data());
+
+    for (int cellY = 0; cellY < numRowsCols; cellY++)
+    {
+        for (int cellX = 0; cellX < numRowsCols; cellX++)
+        {
+            int seed              = cellX + cellY * numRowsCols;
+            const Vector4 color   = RandomVec4(seed, fmtValueMin, fmtValueMax);
+            GLColor expectedColor = Vec4ToColor(color);
+
+            int testN           = cellX * cellSize + cellY * backFBOSize * cellSize + backFBOSize + 1;
+            GLColor actualColor = pixelData[testN];
+            EXPECT_NEAR(expectedColor.R, actualColor.R, 1);
+            EXPECT_NEAR(expectedColor.G, actualColor.G, 1);
+            EXPECT_NEAR(expectedColor.B, actualColor.B, 1);
+            EXPECT_NEAR(expectedColor.A, actualColor.A, 1);
+        }
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(ClearTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(ClearTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/ClientArraysTest.cpp b/src/third_party/angle/src/tests/gl_tests/ClientArraysTest.cpp
new file mode 100644
index 0000000..a88821e
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ClientArraysTest.cpp
@@ -0,0 +1,127 @@
+//
+// Copyright 2017 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.
+//
+
+// ClientArraysTest.cpp : Tests of the GL_ANGLE_client_arrays extension.
+
+#include "test_utils/ANGLETest.h"
+
+#include "test_utils/gl_raii.h"
+
+namespace angle
+{
+
+class ClientArraysTest : public ANGLETest
+{
+  protected:
+    ClientArraysTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setClientArraysEnabled(false);
+    }
+};
+
+// Context creation would fail if EGL_ANGLE_create_context_client_arrays was not available so
+// the GL extension should always be present
+TEST_P(ClientArraysTest, ExtensionStringExposed)
+{
+    EXPECT_TRUE(extensionEnabled("GL_ANGLE_client_arrays"));
+}
+
+// Verify that GL_CLIENT_ARRAYS_ANGLE can be queried but not changed
+TEST_P(ClientArraysTest, QueryValidation)
+{
+    GLint intValue = 2;
+    glGetIntegerv(GL_CLIENT_ARRAYS_ANGLE, &intValue);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_GL_FALSE(intValue);
+
+    float floatValue = 2.0f;
+    glGetFloatv(GL_CLIENT_ARRAYS_ANGLE, &floatValue);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(0.0f, floatValue);
+
+    GLboolean boolValue = GL_TRUE;
+    glGetBooleanv(GL_CLIENT_ARRAYS_ANGLE, &boolValue);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_GL_FALSE(GL_FALSE);
+
+    EXPECT_GL_FALSE(glIsEnabled(GL_CLIENT_ARRAYS_ANGLE));
+    EXPECT_GL_NO_ERROR();
+
+    glEnable(GL_CLIENT_ARRAYS_ANGLE);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    glDisable(GL_CLIENT_ARRAYS_ANGLE);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+// Test that client-side array buffers are forbidden when client arrays are disabled
+TEST_P(ClientArraysTest, ForbidsClientSideArrayBuffer)
+{
+    const auto &vertices = GetQuadVertices();
+    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test that client-side element array buffers are forbidden when client arrays are disabled
+TEST_P(ClientArraysTest, ForbidsClientSideElementBuffer)
+{
+    ASSERT_GL_FALSE(glIsEnabled(GL_CLIENT_ARRAYS_ANGLE));
+
+    const std::string &vert =
+        "attribute vec3 a_pos;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_pos, 1.0);\n"
+        "}\n";
+
+    const std::string &frag =
+        "precision highp float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vert, frag);
+
+    GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
+    ASSERT_NE(-1, posLocation);
+    glUseProgram(program.get());
+
+    const auto &vertices = GetQuadVertices();
+
+    GLBuffer vertexBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
+                 GL_STATIC_DRAW);
+
+    glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(posLocation);
+
+    const GLubyte indices[] = {0, 1, 2, 3, 4, 5};
+
+    ASSERT_GL_NO_ERROR();
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(ClientArraysTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/ColorMaskTest.cpp b/src/third_party/angle/src/tests/gl_tests/ColorMaskTest.cpp
new file mode 100644
index 0000000..d2ad638
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ColorMaskTest.cpp
@@ -0,0 +1,110 @@
+//
+// Copyright 2016 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.
+//
+
+// ColorMaskTest.cpp: Test GLES functionality related to color masks, particularly an AMD D3D9
+// driver bug.
+
+#include "test_utils/ANGLETest.h"
+
+namespace angle
+{
+class ColorMaskTest : public ANGLETest
+{
+  protected:
+    ColorMaskTest() : mProgram(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource =
+            "precision highp float;\n"
+            "attribute vec4 position;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "}\n";
+
+        const std::string fsSource =
+            "precision highp float;\n"
+            "uniform vec4 color;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = color;\n"
+            "}\n";
+
+        mProgram = CompileProgram(vsSource, fsSource);
+        ASSERT_NE(0u, mProgram) << "shader compilation failed.";
+
+        mColorUniform = glGetUniformLocation(mProgram, "color");
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram     = 0;
+    GLint mColorUniform = -1;
+};
+
+// Some ATI cards have a bug where a draw with a zero color write mask can cause later draws to have
+// incorrect results. Test to make sure this bug is not exposed.
+TEST_P(ColorMaskTest, AMDZeroColorMaskBug)
+{
+    int x = getWindowWidth() / 2;
+    int y = getWindowHeight() / 2;
+
+    // Clear to blue
+    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(x, y, 0, 0, 255, 255);
+
+    // Draw a quad with all colors masked and blending disabled, should remain blue
+    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+    glDisable(GL_BLEND);
+    glUseProgram(mProgram);
+    glUniform4f(mColorUniform, 1.0f, 0.0f, 0.0f, 0.0f);
+    EXPECT_GL_NO_ERROR();
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_EQ(x, y, 0, 0, 255, 255);
+
+    // Re-enable the color mask, should be red (with blend disabled, the red should overwrite
+    // everything)
+    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    glUseProgram(mProgram);
+    glUniform4f(mColorUniform, 1.0f, 0.0f, 0.0f, 0.0f);
+    EXPECT_GL_NO_ERROR();
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_EQ(x, y, 255, 0, 0, 0);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against. D3D11 Feature Level 9_3 uses different D3D formats for vertex
+// attribs compared to Feature Levels 10_0+, so we should test them separately.
+ANGLE_INSTANTIATE_TEST(ColorMaskTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/gl_tests/ComputeShaderTest.cpp b/src/third_party/angle/src/tests/gl_tests/ComputeShaderTest.cpp
new file mode 100644
index 0000000..3ad97a7
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ComputeShaderTest.cpp
@@ -0,0 +1,258 @@
+//
+// Copyright 2016 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.
+//
+// ComputeShaderTest:
+//   Compute shader specific tests.
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+#include <vector>
+
+using namespace angle;
+
+namespace
+{
+
+class ComputeShaderTest : public ANGLETest
+{
+  protected:
+    ComputeShaderTest() {}
+};
+
+class ComputeShaderTestES3 : public ANGLETest
+{
+  protected:
+    ComputeShaderTestES3() {}
+};
+
+// link a simple compute program. It should be successful.
+TEST_P(ComputeShaderTest, LinkComputeProgram)
+{
+    const std::string csSource =
+        "#version 310 es\n"
+        "layout(local_size_x=1) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+
+    ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// link a simple compute program. There is no local size and linking should fail.
+TEST_P(ComputeShaderTest, LinkComputeProgramNoLocalSizeLinkError)
+{
+    const std::string csSource =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+
+    GLuint program = CompileComputeProgram(csSource, false);
+    EXPECT_EQ(0u, program);
+
+    glDeleteProgram(program);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// link a simple compute program.
+// make sure that uniforms and uniform samplers get recorded
+TEST_P(ComputeShaderTest, LinkComputeProgramWithUniforms)
+{
+    const std::string csSource =
+        "#version 310 es\n"
+        "precision mediump sampler2D;\n"
+        "layout(local_size_x=1) in;\n"
+        "uniform int myUniformInt;\n"
+        "uniform sampler2D myUniformSampler;\n"
+        "void main()\n"
+        "{\n"
+        "int q = myUniformInt;\n"
+        "texture(myUniformSampler, vec2(0.0));\n"
+        "}\n";
+
+    ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
+
+    GLint uniformLoc = glGetUniformLocation(program.get(), "myUniformInt");
+    EXPECT_NE(-1, uniformLoc);
+
+    uniformLoc = glGetUniformLocation(program.get(), "myUniformSampler");
+    EXPECT_NE(-1, uniformLoc);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Attach both compute and non-compute shaders. A link time error should occur.
+// OpenGL ES 3.10, 7.3 Program Objects
+TEST_P(ComputeShaderTest, AttachMultipleShaders)
+{
+    const std::string csSource =
+        "#version 310 es\n"
+        "layout(local_size_x=1) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+
+    const std::string vsSource =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+
+    const std::string fsSource =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+
+    GLuint program = glCreateProgram();
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+    GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
+
+    EXPECT_NE(0u, vs);
+    EXPECT_NE(0u, fs);
+    EXPECT_NE(0u, cs);
+
+    glAttachShader(program, vs);
+    glDeleteShader(vs);
+
+    glAttachShader(program, fs);
+    glDeleteShader(fs);
+
+    glAttachShader(program, cs);
+    glDeleteShader(cs);
+
+    glLinkProgram(program);
+
+    GLint linkStatus;
+    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+    EXPECT_EQ(0, linkStatus);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Attach a vertex, fragment and compute shader.
+// Query for the number of attached shaders and check the count.
+TEST_P(ComputeShaderTest, AttachmentCount)
+{
+    const std::string csSource =
+        "#version 310 es\n"
+        "layout(local_size_x=1) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+
+    const std::string vsSource =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+
+    const std::string fsSource =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+
+    GLuint program = glCreateProgram();
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+    GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
+
+    EXPECT_NE(0u, vs);
+    EXPECT_NE(0u, fs);
+    EXPECT_NE(0u, cs);
+
+    glAttachShader(program, vs);
+    glDeleteShader(vs);
+
+    glAttachShader(program, fs);
+    glDeleteShader(fs);
+
+    glAttachShader(program, cs);
+    glDeleteShader(cs);
+
+    GLint numAttachedShaders;
+    glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
+
+    EXPECT_EQ(3, numAttachedShaders);
+
+    glDeleteProgram(program);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Access all compute shader special variables.
+TEST_P(ComputeShaderTest, AccessAllSpecialVariables)
+{
+    const std::string csSource =
+        "#version 310 es\n"
+        "layout(local_size_x=4, local_size_y=3, local_size_z=2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    uvec3 temp1 = gl_NumWorkGroups;\n"
+        "    uvec3 temp2 = gl_WorkGroupSize;\n"
+        "    uvec3 temp3 = gl_WorkGroupID;\n"
+        "    uvec3 temp4 = gl_LocalInvocationID;\n"
+        "    uvec3 temp5 = gl_GlobalInvocationID;\n"
+        "    uint  temp6 = gl_LocalInvocationIndex;\n"
+        "}\n";
+
+    ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
+}
+
+// Access part compute shader special variables.
+TEST_P(ComputeShaderTest, AccessPartSpecialVariables)
+{
+    const std::string csSource =
+        "#version 310 es\n"
+        "layout(local_size_x=4, local_size_y=3, local_size_z=2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    uvec3 temp1 = gl_WorkGroupSize;\n"
+        "    uvec3 temp2 = gl_WorkGroupID;\n"
+        "    uint  temp3 = gl_LocalInvocationIndex;\n"
+        "}\n";
+
+    ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
+}
+
+// Use glDispatchCompute to define work group count.
+TEST_P(ComputeShaderTest, DispatchCompute)
+{
+    const std::string csSource =
+        "#version 310 es\n"
+        "layout(local_size_x=4, local_size_y=3, local_size_z=2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    uvec3 temp = gl_NumWorkGroups;\n"
+        "}\n";
+
+    ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
+
+    glUseProgram(program.get());
+    glDispatchCompute(8, 4, 2);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Check that it is not possible to create a compute shader when the context does not support ES
+// 3.10
+TEST_P(ComputeShaderTestES3, NotSupported)
+{
+    GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER);
+    EXPECT_EQ(0u, computeShaderHandle);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+ANGLE_INSTANTIATE_TEST(ComputeShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
+ANGLE_INSTANTIATE_TEST(ComputeShaderTestES3, ES3_OPENGL(), ES3_OPENGLES());
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/CopyCompressedTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/CopyCompressedTextureTest.cpp
new file mode 100644
index 0000000..4d41519
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/CopyCompressedTextureTest.cpp
@@ -0,0 +1,369 @@
+//
+// Copyright 2016 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.
+//
+
+// CopyCompressedTextureTest.cpp: Tests of the GL_CHROMIUM_copy_compressed_texture extension
+
+#include "test_utils/ANGLETest.h"
+
+namespace angle
+{
+
+class CopyCompressedTextureTest : public ANGLETest
+{
+  protected:
+    CopyCompressedTextureTest()
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenTextures(2, mTextures);
+
+        mProgram = CompileProgram(
+            "attribute vec2 a_position;\n"
+            "varying vec2 v_texcoord;\n"
+            "void main()\n"
+            "{\n"
+            "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
+            "   v_texcoord = (a_position + 1.0) * 0.5;\n"
+            "}\n",
+            "precision mediump float;\n"
+            "uniform sampler2D u_texture;\n"
+            "varying vec2 v_texcoord;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = texture2D(u_texture, v_texcoord);\n"
+            "}\n");
+        ASSERT_NE(0u, mProgram);
+
+        if (extensionEnabled("GL_CHROMIUM_copy_compressed_texture"))
+        {
+            glCompressedCopyTextureCHROMIUM =
+                reinterpret_cast<PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC>(
+                    eglGetProcAddress("glCompressedCopyTextureCHROMIUM"));
+        }
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(2, mTextures);
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    bool checkExtensions() const
+    {
+        if (!extensionEnabled("GL_CHROMIUM_copy_compressed_texture"))
+        {
+            std::cout
+                << "Test skipped because GL_CHROMIUM_copy_compressed_texture is not available."
+                << std::endl;
+            return false;
+        }
+
+        EXPECT_NE(nullptr, glCompressedCopyTextureCHROMIUM);
+        if (glCompressedCopyTextureCHROMIUM == nullptr)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    GLuint mProgram     = 0;
+    GLuint mTextures[2] = {0, 0};
+
+    PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC glCompressedCopyTextureCHROMIUM = nullptr;
+};
+
+namespace
+{
+
+const GLColor &CompressedImageColor = GLColor::red;
+
+// Single compressed ATC block of source pixels all set to:
+// CompressedImageColor.
+const uint8_t CompressedImageATC[8] = {0x0, 0x7c, 0x0, 0xf8, 0x55, 0x55, 0x55, 0x55};
+
+// Single compressed ATCIA block of source pixels all set to:
+// CompressedImageColor.
+const uint8_t CompressedImageATCIA[16] = {0xff, 0xff, 0x0, 0x0,  0x0,  0x0,  0x0,  0x0,
+                                          0x0,  0x7c, 0x0, 0xf8, 0x55, 0x55, 0x55, 0x55};
+
+// Single compressed DXT1 block of source pixels all set to:
+// CompressedImageColor.
+const uint8_t CompressedImageDXT1[8] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
+
+// Single compressed DXT5 block of source pixels all set to:
+// CompressedImageColor.
+const uint8_t CompressedImageDXT5[16] = {0xff, 0xff, 0x0, 0x0,  0x0,  0x0,  0x0,  0x0,
+                                         0x0,  0xf8, 0x0, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
+
+// Single compressed DXT1 block of source pixels all set to:
+// CompressedImageColor.
+const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0};
+
+}  // anonymous namespace
+
+// Test to ensure that the basic functionality of the extension works.
+TEST_P(CopyCompressedTextureTest, Basic)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
+    {
+        std::cout << "Test skipped because GL_EXT_texture_compression_dxt1 is not available."
+                  << std::endl;
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_NO_ERROR();
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
+    ASSERT_GL_NO_ERROR();
+
+    // Load texture.
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    GLint textureLoc = glGetUniformLocation(mProgram, "u_texture");
+    glUseProgram(mProgram);
+    glUniform1i(textureLoc, 0);
+
+    // Draw.
+    drawQuad(mProgram, "a_position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, CompressedImageColor);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test validation of compressed formats
+TEST_P(CopyCompressedTextureTest, InternalFormat)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    struct Data
+    {
+        GLint format;
+        const uint8_t *data;
+        GLsizei dataSize;
+
+        Data() : Data(GL_NONE, nullptr, 0) {}
+        Data(GLint format, const uint8_t *data, GLsizei dataSize)
+            : format(format), data(data), dataSize(dataSize)
+        {
+        }
+    };
+    std::vector<Data> supportedFormats;
+
+    if (extensionEnabled("GL_AMD_compressed_ATC_texture"))
+    {
+        supportedFormats.push_back(
+            Data(GL_ATC_RGB_AMD, CompressedImageATC, sizeof(CompressedImageATC)));
+        supportedFormats.push_back(Data(GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD, CompressedImageATCIA,
+                                        sizeof(CompressedImageATCIA)));
+    }
+    if (extensionEnabled("GL_EXT_texture_compression_dxt1"))
+    {
+        supportedFormats.push_back(Data(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedImageDXT1,
+                                        sizeof(CompressedImageDXT1)));
+    }
+    if (extensionEnabled("GL_ANGLE_texture_compression_dxt5"))
+    {
+        supportedFormats.push_back(Data(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, CompressedImageDXT5,
+                                        sizeof(CompressedImageDXT5)));
+    }
+    if (extensionEnabled("GL_OES_compressed_ETC1_RGB8_texture"))
+    {
+        supportedFormats.push_back(
+            Data(GL_ETC1_RGB8_OES, CompressedImageETC1, sizeof(CompressedImageETC1)));
+    }
+
+    for (const auto &supportedFormat : supportedFormats)
+    {
+        glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glCompressedTexImage2D(GL_TEXTURE_2D, 0, supportedFormat.format, 4, 4, 0,
+                               supportedFormat.dataSize, supportedFormat.data);
+        ASSERT_GL_NO_ERROR();
+
+        glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+// Test that uncompressed textures generate errors when copying
+TEST_P(CopyCompressedTextureTest, InternalFormatNotSupported)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
+    ASSERT_GL_NO_ERROR();
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+
+    // Check that the GL_RGBA format reports an error.
+    glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test validation of texture IDs
+TEST_P(CopyCompressedTextureTest, InvalidTextureIds)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_NO_ERROR();
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+
+    glCompressedCopyTextureCHROMIUM(mTextures[0], 99993);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCompressedCopyTextureCHROMIUM(99994, mTextures[1]);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCompressedCopyTextureCHROMIUM(99995, 99996);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that only 2D textures are valid
+TEST_P(CopyCompressedTextureTest, BindingPoints)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[0]);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+         face++)
+    {
+        glCompressedTexImage2D(face, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
+                               sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    }
+    ASSERT_GL_NO_ERROR();
+
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[1]);
+    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+
+    glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+// Test the destination texture cannot be immutable
+TEST_P(CopyCompressedTextureTest, Immutable)
+{
+    if (!checkExtensions() || getClientMajorVersion() < 3)
+    {
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_NO_ERROR();
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+
+    glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(CopyCompressedTextureTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/gl_tests/CopyTexImageTest.cpp b/src/third_party/angle/src/tests/gl_tests/CopyTexImageTest.cpp
new file mode 100644
index 0000000..b517515
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/CopyTexImageTest.cpp
@@ -0,0 +1,382 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+namespace angle
+{
+
+class CopyTexImageTest : public ANGLETest
+{
+  protected:
+    CopyTexImageTest()
+    {
+        setWindowWidth(16);
+        setWindowHeight(16);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    GLuint createFramebuffer(GLenum format, GLenum type, GLfloat color[4]) const
+    {
+        GLuint fbo;
+        glGenFramebuffers(1, &fbo);
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+        GLuint texture = createTexture(format, type);
+        glBindTexture(GL_TEXTURE_2D, texture);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+
+        glClearColor(color[0], color[1], color[2], color[3]);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        return fbo;
+    }
+
+    GLuint createTexture(GLenum format, GLenum type) const
+    {
+        GLuint tex;
+        glGenTextures(1, &tex);
+        glBindTexture(GL_TEXTURE_2D, tex);
+        glTexImage2D(GL_TEXTURE_2D, 0, format, 16, 16, 0, format, type, nullptr);
+
+        // Disable mipmapping
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        return tex;
+    }
+
+    GLuint createTextureFromCopyTexImage(GLuint fbo, GLenum format) const
+    {
+        GLuint tex;
+        glGenTextures(1, &tex);
+        glBindTexture(GL_TEXTURE_2D, tex);
+
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, 16, 16, 0);
+
+        // Disable mipmapping
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        return tex;
+    }
+
+    void copyTextureWithCopyTexSubImage(GLuint fbo,
+                                        GLuint texture,
+                                        GLint xoffset,
+                                        GLint yoffset,
+                                        GLint x,
+                                        GLint y,
+                                        GLsizei w,
+                                        GLsizei h) const
+    {
+        glBindTexture(GL_TEXTURE_2D, texture);
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, x, y, w, h);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource =
+            "precision highp float;\n"
+            "attribute vec4 position;\n"
+            "varying vec2 texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "    texcoord.y = 1.0 - texcoord.y;\n"
+            "}\n";
+
+        const std::string textureFSSource =
+            "precision highp float;\n"
+            "uniform sampler2D tex;\n"
+            "varying vec2 texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = texture2D(tex, texcoord);\n"
+            "}\n";
+
+        mTextureProgram = CompileProgram(vsSource, textureFSSource);
+        if (mTextureProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mTextureProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    void verifyResults(GLuint texture, GLubyte data[4], GLint x, GLint y)
+    {
+        glViewport(0, 0, 16, 16);
+
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+        // Draw a quad with the target texture
+        glUseProgram(mTextureProgram);
+        glBindTexture(GL_TEXTURE_2D, texture);
+        glUniform1i(mTextureUniformLocation, 0);
+
+        drawQuad(mTextureProgram, "position", 0.5f);
+
+        // Expect that the rendered quad has the same color as the source texture
+        EXPECT_PIXEL_NEAR(x, y, data[0], data[1], data[2], data[3], 1.0);
+    }
+
+    GLuint mTextureProgram;
+    GLint mTextureUniformLocation;
+};
+
+TEST_P(CopyTexImageTest, RGBAToL)
+{
+    GLfloat color[] = {
+        0.25f, 1.0f, 0.75f, 0.5f,
+    };
+
+    GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
+    GLuint tex = createTextureFromCopyTexImage(fbo, GL_LUMINANCE);
+
+    GLubyte expected[] = {
+        64, 64, 64, 255,
+    };
+    verifyResults(tex, expected, 0, 0);
+}
+
+TEST_P(CopyTexImageTest, RGBToL)
+{
+    // TODO (geofflang): Figure out why CopyTex[Sub]Image doesn't work with
+    // RGB->L on older Intel chips
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    GLfloat color[] = {
+        0.25f, 1.0f, 0.75f, 0.5f,
+    };
+
+    GLuint fbo = createFramebuffer(GL_RGB, GL_UNSIGNED_BYTE, color);
+    GLuint tex = createTextureFromCopyTexImage(fbo, GL_LUMINANCE);
+
+    GLubyte expected[] = {
+        64, 64, 64, 255,
+    };
+    verifyResults(tex, expected, 0, 0);
+}
+
+TEST_P(CopyTexImageTest, RGBAToLA)
+{
+    GLfloat color[] = {
+        0.25f, 1.0f, 0.75f, 0.5f,
+    };
+
+    GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
+    GLuint tex = createTextureFromCopyTexImage(fbo, GL_LUMINANCE_ALPHA);
+
+    GLubyte expected[] = {
+        64, 64, 64, 127,
+    };
+    verifyResults(tex, expected, 0, 0);
+}
+
+TEST_P(CopyTexImageTest, RGBAToA)
+{
+    GLfloat color[] = {
+        0.25f, 1.0f, 0.75f, 0.5f,
+    };
+
+    GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
+    GLuint tex = createTextureFromCopyTexImage(fbo, GL_ALPHA);
+
+    GLubyte expected[] = {
+        0, 0, 0, 127,
+    };
+    verifyResults(tex, expected, 0, 0);
+}
+
+TEST_P(CopyTexImageTest, SubImageRGBAToL)
+{
+    GLfloat color0[] = {
+        0.25f, 1.0f, 0.75f, 0.5f,
+    };
+    GLuint fbo0 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color0);
+    GLuint tex  = createTextureFromCopyTexImage(fbo0, GL_LUMINANCE);
+
+    GLfloat color1[] = {
+        0.5f, 0.25f, 1.0f, 0.75f,
+    };
+    GLuint fbo1 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color1);
+    copyTextureWithCopyTexSubImage(fbo1, tex, 2, 4, 5, 6, 8, 8);
+
+    GLubyte expected0[] = {
+        64, 64, 64, 255,
+    };
+    verifyResults(tex, expected0, 0, 0);
+
+    GLubyte expected1[] = {
+        127, 127, 127, 255,
+    };
+    verifyResults(tex, expected1, 7, 7);
+}
+
+TEST_P(CopyTexImageTest, SubImageRGBAToLA)
+{
+    GLfloat color0[] = {
+        0.25f, 1.0f, 0.75f, 0.5f,
+    };
+    GLuint fbo0 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color0);
+    GLuint tex  = createTextureFromCopyTexImage(fbo0, GL_LUMINANCE_ALPHA);
+
+    GLfloat color1[] = {
+        0.5f, 0.25f, 1.0f, 0.75f,
+    };
+    GLuint fbo1 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color1);
+    copyTextureWithCopyTexSubImage(fbo1, tex, 2, 4, 5, 6, 8, 8);
+
+    GLubyte expected0[] = {
+        64, 64, 64, 127,
+    };
+    verifyResults(tex, expected0, 0, 0);
+
+    GLubyte expected1[] = {
+        127, 127, 127, 192,
+    };
+    verifyResults(tex, expected1, 7, 7);
+}
+
+TEST_P(CopyTexImageTest, SubImageRGBToL)
+{
+    // TODO (geofflang): Figure out why CopyTex[Sub]Image doesn't work with
+    // RGB->L on older Intel chips
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    GLfloat color0[] = {
+        0.25f, 1.0f, 0.75f, 0.5f,
+    };
+    GLuint fbo0 = createFramebuffer(GL_RGB, GL_UNSIGNED_BYTE, color0);
+    GLuint tex  = createTextureFromCopyTexImage(fbo0, GL_LUMINANCE);
+
+    GLfloat color1[] = {
+        0.5f, 0.25f, 1.0f, 0.75f,
+    };
+    GLuint fbo1 = createFramebuffer(GL_RGB, GL_UNSIGNED_BYTE, color1);
+    copyTextureWithCopyTexSubImage(fbo1, tex, 2, 4, 5, 6, 8, 8);
+
+    GLubyte expected0[] = {
+        64, 64, 64, 255,
+    };
+    verifyResults(tex, expected0, 0, 0);
+
+    GLubyte expected1[] = {
+        127, 127, 127, 255,
+    };
+    verifyResults(tex, expected1, 7, 7);
+}
+
+// Read default framebuffer with glCopyTexImage2D().
+TEST_P(CopyTexImageTest, DefaultFramebuffer)
+{
+    // TODO(fjhenigman): Test fails on Linnux Intel with the following in GL Debug Output:
+    //   GL_INVALID_OPERATION in glCopyTexImage2D(missing readbuffer)
+    if (IsLinux() && IsIntel())
+    {
+        std::cout << "Test skipped on Linux Intel." << std::endl;
+        return;
+    }
+
+    const GLint w = getWindowWidth(), h = getWindowHeight();
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, w, h, 0);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Read default framebuffer with glCopyTexSubImage2D().
+TEST_P(CopyTexImageTest, SubDefaultFramebuffer)
+{
+    // TODO(fjhenigman): Test fails on Linnux Intel with the following in GL Debug Output:
+    //   GL_INVALID_OPERATION in glCopyTexImage2D(missing readbuffer)
+    if (IsLinux() && IsIntel())
+    {
+        std::cout << "Test skipped on Linux Intel." << std::endl;
+        return;
+    }
+
+    const GLint w = getWindowWidth(), h = getWindowHeight();
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w, h);
+    EXPECT_GL_NO_ERROR();
+}
+
+// specialization of CopyTexImageTest is added so that some tests can be explicitly run with an ES3
+// context
+class CopyTexImageTestES3 : public CopyTexImageTest
+{
+};
+
+//  The test verifies that glCopyTexSubImage2D generates a GL_INVALID_OPERATION error
+//  when the read buffer is GL_NONE.
+//  Reference: GLES 3.0.4, Section 3.8.5 Alternate Texture Image Specification Commands
+TEST_P(CopyTexImageTestES3, ReadBufferIsNone)
+{
+    GLfloat color[] = {
+        0.25f, 1.0f, 0.75f, 0.5f,
+    };
+
+    GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
+    GLuint tex = createTextureFromCopyTexImage(fbo, GL_RGBA);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    glReadBuffer(GL_NONE);
+
+    EXPECT_GL_NO_ERROR();
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 4, 4);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glDeleteFramebuffers(1, &fbo);
+    glDeleteTextures(1, &tex);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(CopyTexImageTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE),
+                       ES2_OPENGL(),
+                       ES2_OPENGL(3, 3),
+                       ES2_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(CopyTexImageTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+}
diff --git a/src/third_party/angle/src/tests/gl_tests/CopyTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/CopyTextureTest.cpp
new file mode 100644
index 0000000..bd5e72e
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/CopyTextureTest.cpp
@@ -0,0 +1,652 @@
+//
+// Copyright 2016 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.
+//
+
+// CopyTextureTest.cpp: Tests of the GL_CHROMIUM_copy_texture extension
+
+#include "test_utils/ANGLETest.h"
+
+namespace angle
+{
+
+class CopyTextureTest : public ANGLETest
+{
+  protected:
+    CopyTextureTest()
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenTextures(2, mTextures);
+        glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+        glGenFramebuffers(1, &mFramebuffer);
+        glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
+                               0);
+
+        if (extensionEnabled("GL_CHROMIUM_copy_texture"))
+        {
+            glCopyTextureCHROMIUM = reinterpret_cast<PFNGLCOPYTEXTURECHROMIUMPROC>(
+                eglGetProcAddress("glCopyTextureCHROMIUM"));
+            glCopySubTextureCHROMIUM = reinterpret_cast<PFNGLCOPYSUBTEXTURECHROMIUMPROC>(
+                eglGetProcAddress("glCopySubTextureCHROMIUM"));
+        }
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(2, mTextures);
+        glDeleteFramebuffers(1, &mFramebuffer);
+
+        ANGLETest::TearDown();
+    }
+
+    bool checkExtensions() const
+    {
+        if (!extensionEnabled("GL_CHROMIUM_copy_texture"))
+        {
+            std::cout << "Test skipped because GL_CHROMIUM_copy_texture is not available."
+                      << std::endl;
+            return false;
+        }
+
+        EXPECT_NE(nullptr, glCopyTextureCHROMIUM);
+        EXPECT_NE(nullptr, glCopySubTextureCHROMIUM);
+        return true;
+    }
+
+    GLuint mTextures[2] = {
+        0, 0,
+    };
+    GLuint mFramebuffer = 0;
+
+    PFNGLCOPYTEXTURECHROMIUMPROC glCopyTextureCHROMIUM       = nullptr;
+    PFNGLCOPYSUBTEXTURECHROMIUMPROC glCopySubTextureCHROMIUM = nullptr;
+};
+
+// Test to ensure that the basic functionality of the extension works.
+TEST_P(CopyTextureTest, BasicCopyTexture)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    GLColor pixels = GLColor::red;
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, false, false, false);
+
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, pixels);
+}
+
+// Test to ensure that the basic functionality of the extension works.
+TEST_P(CopyTextureTest, BasicCopySubTexture)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    GLColor pixels = GLColor::red;
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 0, 0, 0, 0, 1, 1,
+                             false, false, false);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Check that FB is complete.
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, pixels);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that CopyTexture cannot redefine an immutable texture and CopySubTexture can copy data to
+// immutable textures
+TEST_P(CopyTextureTest, ImmutableTexture)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    if (getClientMajorVersion() < 3 &&
+        (!extensionEnabled("GL_EXT_texture_storage") || !extensionEnabled("GL_OES_rgb8_rgba8")))
+    {
+        std::cout
+            << "Test skipped due to missing ES3 or GL_EXT_texture_storage or GL_OES_rgb8_rgba8"
+            << std::endl;
+        return;
+    }
+
+    GLColor pixels = GLColor::red;
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixels);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
+    EXPECT_GL_NO_ERROR();
+
+    // Should generate an error when the texture is redefined
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, false, false, false);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Should succeed when using CopySubTexture
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 0, 0, 0, 0, 1, 1,
+                             false, false, false);
+    EXPECT_GL_NO_ERROR();
+
+    // Check that FB is complete.
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, pixels);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test validation of internal formats in CopyTexture and CopySubTexture
+TEST_P(CopyTextureTest, InternalFormat)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    std::vector<GLint> sourceFormats;
+    sourceFormats.push_back(GL_ALPHA);
+    sourceFormats.push_back(GL_RGB);
+    sourceFormats.push_back(GL_RGBA);
+    sourceFormats.push_back(GL_LUMINANCE);
+    sourceFormats.push_back(GL_LUMINANCE_ALPHA);
+
+    std::vector<GLint> destFormats;
+    destFormats.push_back(GL_RGB);
+    destFormats.push_back(GL_RGBA);
+
+    if (extensionEnabled("GL_EXT_texture_format_BGRA8888"))
+    {
+        sourceFormats.push_back(GL_BGRA_EXT);
+        destFormats.push_back(GL_BGRA_EXT);
+    }
+
+    // Test with glCopyTexture
+    for (GLint sourceFormat : sourceFormats)
+    {
+        for (GLint destFormat : destFormats)
+        {
+            glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+            glTexImage2D(GL_TEXTURE_2D, 0, sourceFormat, 1, 1, 0, sourceFormat, GL_UNSIGNED_BYTE,
+                         nullptr);
+            EXPECT_GL_NO_ERROR();
+
+            glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, destFormat,
+                                  GL_UNSIGNED_BYTE, false, false, false);
+
+            EXPECT_GL_NO_ERROR();
+        }
+    }
+
+    // Test with glCopySubTexture
+    for (GLint sourceFormat : sourceFormats)
+    {
+        for (GLint destFormat : destFormats)
+        {
+            glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+            glTexImage2D(GL_TEXTURE_2D, 0, sourceFormat, 1, 1, 0, sourceFormat, GL_UNSIGNED_BYTE,
+                         nullptr);
+            EXPECT_GL_NO_ERROR();
+
+            glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+            glTexImage2D(GL_TEXTURE_2D, 0, destFormat, 1, 1, 0, destFormat, GL_UNSIGNED_BYTE,
+                         nullptr);
+            EXPECT_GL_NO_ERROR();
+
+            glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 0, 0, 0, 0, 1,
+                                     1, false, false, false);
+
+            EXPECT_GL_NO_ERROR();
+        }
+    }
+}
+
+// Check that invalid internal formats return errors.
+TEST_P(CopyTextureTest, InternalFormatNotSupported)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    std::vector<GLint> unsupportedDestFormats;
+    unsupportedDestFormats.push_back(GL_ALPHA);
+    unsupportedDestFormats.push_back(GL_LUMINANCE);
+    unsupportedDestFormats.push_back(GL_LUMINANCE_ALPHA);
+
+    if (!extensionEnabled("GL_EXT_texture_format_BGRA8888"))
+    {
+        unsupportedDestFormats.push_back(GL_BGRA_EXT);
+    }
+
+    // Check unsupported format reports an error.
+    for (GLint unsupportedDestFormat : unsupportedDestFormats)
+    {
+        glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0,
+                              unsupportedDestFormat, GL_UNSIGNED_BYTE, false, false, false);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+
+    for (GLint unsupportedDestFormat : unsupportedDestFormats)
+    {
+        glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+        glTexImage2D(GL_TEXTURE_2D, 0, unsupportedDestFormat, 1, 1, 0, unsupportedDestFormat,
+                     GL_UNSIGNED_BYTE, nullptr);
+        glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 0, 0, 0, 0, 1, 1,
+                                 false, false, false);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+}
+
+// Test to ensure that the destination texture is redefined if the properties are different.
+TEST_P(CopyTextureTest, RedefineDestinationTexture)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    GLColor pixels[4] = {GLColor::red, GLColor::red, GLColor::red, GLColor::red};
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, 1, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
+    EXPECT_GL_NO_ERROR();
+
+    // GL_INVALID_OPERATION due to "intrinsic format" != "internal format".
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    // GL_INVALID_VALUE due to bad dimensions.
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // If the dest texture has different properties, glCopyTextureCHROMIUM()
+    // redefines them.
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, false, false, false);
+    EXPECT_GL_NO_ERROR();
+
+    // glTexSubImage2D() succeeds because mTextures[1] is redefined into 2x2
+    // dimension and GL_RGBA format.
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    EXPECT_GL_NO_ERROR();
+
+    // Check that FB is complete.
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    EXPECT_PIXEL_COLOR_EQ(1, 1, pixels[3]);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that invalid dimensions in CopySubTexture are validated
+TEST_P(CopyTextureTest, CopySubTextureDimension)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 1, 1, 0, 0, 1, 1,
+                             false, false, false);
+    EXPECT_GL_NO_ERROR();
+
+    // xoffset < 0
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, -1, 1, 0, 0, 1, 1,
+                             false, false, false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // x < 0
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 1, 1, -1, 0, 1, 1,
+                             false, false, false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // xoffset + width > dest_width
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 2, 2, 0, 0, 2, 2,
+                             false, false, false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // x + width > source_width
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 0, 0, 1, 1, 2, 2,
+                             false, false, false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+// Test that invalid IDs in CopyTexture are validated
+TEST_P(CopyTextureTest, CopyTextureInvalidTextureIds)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, 99993, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                          false, false, false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCopyTextureCHROMIUM(99994, 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                          false, false, false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCopyTextureCHROMIUM(99995, 0, GL_TEXTURE_2D, 99996, 0, GL_RGBA, GL_UNSIGNED_BYTE, false,
+                          false, false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, false, false, false);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that invalid IDs in CopySubTexture are validated
+TEST_P(CopyTextureTest, CopySubTextureInvalidTextureIds)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, 99993, 0, 1, 1, 0, 0, 1, 1, false,
+                             false, false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCopySubTextureCHROMIUM(99994, 0, GL_TEXTURE_2D, mTextures[1], 0, 1, 1, 0, 0, 1, 1, false,
+                             false, false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCopySubTextureCHROMIUM(99995, 0, GL_TEXTURE_2D, 99996, 0, 1, 1, 0, 0, 1, 1, false, false,
+                             false);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 1, 1, 0, 0, 1, 1,
+                             false, false, false);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that using an offset in CopySubTexture works correctly
+TEST_P(CopyTextureTest, CopySubTextureOffset)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    GLColor rgbaPixels[4 * 4] = {GLColor::red, GLColor::green, GLColor::blue, GLColor::black};
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaPixels);
+
+    GLColor transparentPixels[4 * 4] = {GLColor::transparentBlack, GLColor::transparentBlack,
+                                        GLColor::transparentBlack, GLColor::transparentBlack};
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, transparentPixels);
+
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 1, 1, 0, 0, 1, 1,
+                             false, false, false);
+    EXPECT_GL_NO_ERROR();
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 1, 0, 1, 0, 1, 1,
+                             false, false, false);
+    EXPECT_GL_NO_ERROR();
+    glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 0, 1, 0, 1, 1, 1,
+                             false, false, false);
+    EXPECT_GL_NO_ERROR();
+
+    // Check that FB is complete.
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
+    EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
+    EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that flipping the Y component works correctly
+TEST_P(CopyTextureTest, FlipY)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    GLColor rgbaPixels[4] = {GLColor(255u, 255u, 255u, 255u), GLColor(127u, 127u, 127u, 127u),
+                             GLColor(63u, 63u, 63u, 127u), GLColor(255u, 255u, 255u, 0u)};
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaPixels);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, GL_TRUE, GL_FALSE, GL_FALSE);
+    EXPECT_GL_NO_ERROR();
+
+    // Check that FB is complete.
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, rgbaPixels[2]);
+    EXPECT_PIXEL_COLOR_EQ(1, 0, rgbaPixels[3]);
+    EXPECT_PIXEL_COLOR_EQ(0, 1, rgbaPixels[0]);
+    EXPECT_PIXEL_COLOR_EQ(1, 1, rgbaPixels[1]);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that premultipying the alpha on copy works correctly
+TEST_P(CopyTextureTest, PremultiplyAlpha)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    GLColor rgbaPixels[4] = {GLColor(255u, 255u, 255u, 255u), GLColor(255u, 255u, 255u, 127u),
+                             GLColor(127u, 127u, 127u, 127u), GLColor(255u, 255u, 255u, 0u)};
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaPixels);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, GL_FALSE, GL_TRUE, GL_FALSE);
+    EXPECT_GL_NO_ERROR();
+
+    // Check that FB is complete.
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 255, 255, 255), 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(1, 0, GLColor(127, 127, 127, 127), 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(0, 1, GLColor(63, 63, 63, 127), 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(1, 1, GLColor(0, 0, 0, 0), 1.0);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that unmultipying the alpha on copy works correctly
+TEST_P(CopyTextureTest, UnmultiplyAlpha)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    GLColor rgbaPixels[4] = {GLColor(255u, 255u, 255u, 255u), GLColor(127u, 127u, 127u, 127u),
+                             GLColor(63u, 63u, 63u, 127u), GLColor(255u, 255u, 255u, 0u)};
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaPixels);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, GL_FALSE, GL_FALSE, GL_TRUE);
+    EXPECT_GL_NO_ERROR();
+
+    // Check that FB is complete.
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 255, 255, 255), 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(1, 0, GLColor(255, 255, 255, 127), 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(0, 1, GLColor(127, 127, 127, 127), 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(1, 1, GLColor(255, 255, 255, 0), 1.0);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that unmultipying and premultiplying the alpha is the same as doing neither
+TEST_P(CopyTextureTest, UnmultiplyAndPremultiplyAlpha)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    GLColor rgbaPixels[4] = {GLColor(255u, 255u, 255u, 255u), GLColor(127u, 127u, 127u, 127u),
+                             GLColor(63u, 63u, 63u, 127u), GLColor(255u, 255u, 255u, 0u)};
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaPixels);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, GL_FALSE, GL_TRUE, GL_TRUE);
+    EXPECT_GL_NO_ERROR();
+
+    // Check that FB is complete.
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 255, 255, 255), 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(1, 0, GLColor(127, 127, 127, 127), 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(0, 1, GLColor(63, 63, 63, 127), 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(1, 1, GLColor(255, 255, 255, 0), 1.0);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test to ensure that CopyTexture works with LUMINANCE_ALPHA texture
+TEST_P(CopyTextureTest, LuminanceAlpha)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    uint8_t originalPixels[] = {163u, 67u};
+    GLColor expectedPixels(163u, 163u, 163u, 67u);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 1, 1, 0, GL_LUMINANCE_ALPHA,
+                 GL_UNSIGNED_BYTE, &originalPixels);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, false, false, false);
+
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, expectedPixels);
+}
+
+// Test to ensure that CopyTexture works with LUMINANCE texture
+TEST_P(CopyTextureTest, Luminance)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    uint8_t originalPixels[] = {57u};
+    GLColor expectedPixels(57u, 57u, 57u, 255u);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+                 &originalPixels);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, false, false, false);
+
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, expectedPixels);
+}
+
+// Test to ensure that CopyTexture works with ALPHA texture
+TEST_P(CopyTextureTest, Alpha)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    uint8_t originalPixels[] = {77u};
+    GLColor expectedPixels(0u, 0u, 0u, 77u);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 1, 1, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &originalPixels);
+
+    glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, GL_RGBA,
+                          GL_UNSIGNED_BYTE, false, false, false);
+
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, expectedPixels);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(CopyTextureTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/gl_tests/CubeMapTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/CubeMapTextureTest.cpp
new file mode 100644
index 0000000..68a91da
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/CubeMapTextureTest.cpp
@@ -0,0 +1,142 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class CubeMapTextureTest : public ANGLETest
+{
+  protected:
+    CubeMapTextureTest()
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource = SHADER_SOURCE
+        (
+            attribute highp vec4 position;
+            void main(void)
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string fsSource = SHADER_SOURCE
+        (
+            uniform highp vec4 color;
+            void main(void)
+            {
+                gl_FragColor = color;
+            }
+        );
+
+        mProgram = CompileProgram(vsSource, fsSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mColorLocation = glGetUniformLocation(mProgram, "color");
+
+        glUseProgram(mProgram);
+
+        glClearColor(0, 0, 0, 0);
+        glClearDepthf(0.0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        glEnable(GL_BLEND);
+        glDisable(GL_DEPTH_TEST);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+    GLint mColorLocation;
+};
+
+// Verify that rendering to the faces of a cube map consecutively will correctly render to each face.
+TEST_P(CubeMapTextureTest, RenderToFacesConsecutively)
+{
+    const GLfloat faceColors[] =
+    {
+        1.0f, 0.0f, 0.0f, 1.0f,
+        0.0f, 1.0f, 0.0f, 1.0f,
+        0.0f, 0.0f, 1.0f, 1.0f,
+        1.0f, 1.0f, 0.0f, 1.0f,
+        1.0f, 0.0f, 1.0f, 1.0f,
+        0.0f, 1.0f, 1.0f, 1.0f,
+    };
+
+    GLuint tex = 0;
+    glGenTextures(1, &tex);
+    glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
+    for (GLenum face = 0; face < 6; face++)
+    {
+        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
+                     GL_UNSIGNED_BYTE, nullptr);
+    }
+    EXPECT_GL_NO_ERROR();
+
+    GLuint fbo = 0;
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    EXPECT_GL_NO_ERROR();
+
+    for (GLenum face = 0; face < 6; face++)
+    {
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, tex, 0);
+        EXPECT_GL_NO_ERROR();
+
+        glUseProgram(mProgram);
+
+        const GLfloat *faceColor = faceColors + (face * 4);
+        glUniform4f(mColorLocation, faceColor[0], faceColor[1], faceColor[2], faceColor[3]);
+
+        drawQuad(mProgram, "position", 0.5f);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    for (GLenum face = 0; face < 6; face++)
+    {
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, tex, 0);
+        EXPECT_GL_NO_ERROR();
+
+        const GLfloat *faceColor = faceColors + (face * 4);
+        EXPECT_PIXEL_EQ(0, 0, faceColor[0] * 255, faceColor[1] * 255, faceColor[2] * 255, faceColor[3] * 255);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    glDeleteFramebuffers(1, &fbo);
+    glDeleteTextures(1, &tex);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(CubeMapTextureTest,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/D3D11EmulatedIndexedBufferTest.cpp b/src/third_party/angle/src/tests/gl_tests/D3D11EmulatedIndexedBufferTest.cpp
new file mode 100644
index 0000000..9485701
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/D3D11EmulatedIndexedBufferTest.cpp
@@ -0,0 +1,195 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// D3D11EmulatedIndexedBufferTest:
+//   Tests to validate our D3D11 support for emulating an indexed
+//   vertex buffer.
+//
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "test_utils/ANGLETest.h"
+#include "test_utils/angle_test_instantiate.h"
+
+using namespace angle;
+
+namespace
+{
+
+class D3D11EmulatedIndexedBufferTest : public ANGLETest
+{
+  protected:
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+        ASSERT_EQ(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, GetParam().getRenderer());
+
+        gl::Context *context = reinterpret_cast<gl::Context *>(getEGLWindow()->getContext());
+        rx::Context11 *context11 = rx::GetImplAs<rx::Context11>(context);
+        mRenderer                = context11->getRenderer();
+
+        mSourceBuffer      = new rx::Buffer11(mBufferState, mRenderer);
+        GLfloat testData[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f };
+        gl::Error error    = mSourceBuffer->setData(nullptr, GL_ARRAY_BUFFER, testData,
+                                                 sizeof(testData), GL_STATIC_DRAW);
+        ASSERT_FALSE(error.isError());
+
+        mTranslatedAttribute.baseOffset            = 0;
+        mTranslatedAttribute.usesFirstVertexOffset = false;
+        mTranslatedAttribute.stride = sizeof(GLfloat);
+
+        GLubyte indices[] = {0, 0, 3, 4, 2, 1, 1};
+
+        for (size_t i = 0; i < ArraySize(indices); i++)
+        {
+            mExpectedExpandedData.push_back(testData[indices[i]]);
+            mubyteIndices.push_back(indices[i]);
+            muintIndices.push_back(indices[i]);
+            mushortIndices.push_back(indices[i]);
+        }
+    }
+
+    void TearDown() override
+    {
+        SafeDelete(mSourceBuffer);
+        ANGLETest::TearDown();
+    }
+
+    void createMappableCompareBufferFromEmulatedBuffer(ID3D11Buffer *sourceBuffer, GLuint size, ID3D11Buffer **mappableBuffer)
+    {
+        *mappableBuffer = nullptr;
+
+        D3D11_BUFFER_DESC bufferDesc;
+        bufferDesc.ByteWidth = size;
+        bufferDesc.MiscFlags = 0;
+        bufferDesc.StructureByteStride = 0;
+        bufferDesc.Usage = D3D11_USAGE_STAGING;
+        bufferDesc.BindFlags = 0;
+        bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+
+        HRESULT hr = mRenderer->getDevice()->CreateBuffer(&bufferDesc, nullptr, mappableBuffer);
+        ASSERT_TRUE(SUCCEEDED(hr));
+
+        D3D11_BOX srcBox;
+        srcBox.left = 0;
+        srcBox.right = size;
+        srcBox.top = 0;
+        srcBox.bottom = 1;
+        srcBox.front = 0;
+        srcBox.back = 1;
+
+        mRenderer->getDeviceContext()->CopySubresourceRegion(*mappableBuffer, 0, 0, 0, 0, sourceBuffer, 0, &srcBox);
+    }
+
+    void compareContents(ID3D11Buffer *actual)
+    {
+        ID3D11Buffer *compareBuffer = nullptr;
+        createMappableCompareBufferFromEmulatedBuffer(
+            actual, sizeof(GLfloat) * static_cast<GLuint>(mExpectedExpandedData.size()),
+            &compareBuffer);
+
+        D3D11_MAPPED_SUBRESOURCE mappedResource;
+        HRESULT hr = mRenderer->getDeviceContext()->Map(compareBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
+        ASSERT_TRUE(SUCCEEDED(hr));
+
+        GLfloat* compareData = static_cast<GLfloat*>(mappedResource.pData);
+        for (size_t i = 0; i < mExpectedExpandedData.size(); i++)
+        {
+            EXPECT_EQ(mExpectedExpandedData[i], compareData[i]);
+        }
+
+        mRenderer->getDeviceContext()->Unmap(compareBuffer, 0);
+        SafeRelease(compareBuffer);
+    }
+
+    void emulateAndCompare(rx::SourceIndexData *srcData)
+    {
+        auto bufferOrError =
+            mSourceBuffer->getEmulatedIndexedBuffer(srcData, mTranslatedAttribute, 0);
+        ASSERT_FALSE(bufferOrError.isError());
+        ID3D11Buffer *emulatedBuffer = bufferOrError.getResult();
+        ASSERT_TRUE(emulatedBuffer != nullptr);
+        compareContents(emulatedBuffer);
+    }
+
+  protected:
+    rx::Buffer11 *mSourceBuffer;
+    rx::Renderer11 *mRenderer;
+    rx::TranslatedAttribute mTranslatedAttribute;
+    std::vector<GLfloat> mExpectedExpandedData;
+    std::vector<GLubyte> mubyteIndices;
+    std::vector<GLuint> muintIndices;
+    std::vector<GLushort> mushortIndices;
+    gl::BufferState mBufferState;
+};
+
+// This tests that a GL_UNSIGNED_BYTE indices list can be successfully expanded
+// into a valid emulated indexed buffer.
+TEST_P(D3D11EmulatedIndexedBufferTest, TestNativeToExpandedUsingGLubyteIndices)
+{
+    rx::SourceIndexData srcData = {nullptr, mubyteIndices.data(),
+                                   static_cast<unsigned int>(mubyteIndices.size()),
+                                   GL_UNSIGNED_BYTE, false};
+    emulateAndCompare(&srcData);
+}
+
+// This tests that a GL_UNSIGNED_SHORT indices list can be successfully expanded
+// into a valid emulated indexed buffer.
+TEST_P(D3D11EmulatedIndexedBufferTest, TestNativeToExpandedUsingGLushortIndices)
+{
+    rx::SourceIndexData srcData = {nullptr, mushortIndices.data(),
+                                   static_cast<unsigned int>(mushortIndices.size()),
+                                   GL_UNSIGNED_SHORT, false};
+    emulateAndCompare(&srcData);
+}
+
+// This tests that a GL_UNSIGNED_INT indices list can be successfully expanded
+// into a valid emulated indexed buffer.
+TEST_P(D3D11EmulatedIndexedBufferTest, TestNativeToExpandedUsingGLuintIndices)
+{
+    rx::SourceIndexData srcData = {nullptr, muintIndices.data(),
+                                   static_cast<unsigned int>(muintIndices.size()), GL_UNSIGNED_INT,
+                                   false};
+    emulateAndCompare(&srcData);
+}
+
+// This tests verifies that a Buffer11 contents remain unchanged after calling getEmulatedIndexedBuffer
+TEST_P(D3D11EmulatedIndexedBufferTest, TestSourceBufferRemainsUntouchedAfterExpandOperation)
+{
+    // Copy the original source buffer before any expand calls have been made
+    gl::BufferState cleanSourceState;
+    rx::Buffer11 *cleanSourceBuffer = new rx::Buffer11(cleanSourceState, mRenderer);
+    cleanSourceBuffer->copySubData(nullptr, mSourceBuffer, 0, 0, mSourceBuffer->getSize());
+
+    // Do a basic exanded and compare test.
+    rx::SourceIndexData srcData = {nullptr, muintIndices.data(),
+                                   static_cast<unsigned int>(muintIndices.size()), GL_UNSIGNED_INT,
+                                   false};
+    emulateAndCompare(&srcData);
+
+    const uint8_t *sourceBufferMem = nullptr;
+    const uint8_t *cleanBufferMem = nullptr;
+
+    gl::Error error = mSourceBuffer->getData(&sourceBufferMem);
+    ASSERT_FALSE(error.isError());
+
+    error = cleanSourceBuffer->getData(&cleanBufferMem);
+    ASSERT_FALSE(error.isError());
+
+    int result = memcmp(sourceBufferMem, cleanBufferMem, cleanSourceBuffer->getSize());
+    ASSERT_EQ(result, 0);
+
+    SafeDelete(cleanSourceBuffer);
+}
+
+ANGLE_INSTANTIATE_TEST(D3D11EmulatedIndexedBufferTest,
+                       ES2_D3D11());
+
+} // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/D3D11FormatTablesTest.cpp b/src/third_party/angle/src/tests/gl_tests/D3D11FormatTablesTest.cpp
new file mode 100644
index 0000000..33df5eb
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/D3D11FormatTablesTest.cpp
@@ -0,0 +1,154 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// D3D11FormatTablesTest:
+//   Tests to validate our D3D11 support tables match hardware support.
+//
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "test_utils/angle_test_instantiate.h"
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class D3D11FormatTablesTest : public ANGLETest
+{
+
+};
+
+// This test enumerates all GL formats - for each, it queries the D3D support for
+// using it as a texture, a render target, and sampling from it in the shader. It
+// checks this against our speed-optimized baked tables, and validates they would
+// give the same result.
+// TODO(jmadill): Find out why in 9_3, some format queries return an error.
+// The error seems to appear for formats that are not supported on 9_3.
+TEST_P(D3D11FormatTablesTest, TestFormatSupport)
+{
+    ASSERT_EQ(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, GetParam().getRenderer());
+
+    // Hack the angle!
+    gl::Context *context = reinterpret_cast<gl::Context *>(getEGLWindow()->getContext());
+    rx::Context11 *context11 = rx::GetImplAs<rx::Context11>(context);
+    rx::Renderer11 *renderer = context11->getRenderer();
+    const auto &textureCaps  = renderer->getNativeTextureCaps();
+
+    ID3D11Device *device = renderer->getDevice();
+
+    const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
+    for (GLenum internalFormat : allFormats)
+    {
+        const rx::d3d11::Format &formatInfo =
+            rx::d3d11::Format::Get(internalFormat, renderer->getRenderer11DeviceCaps());
+        const auto &textureInfo = textureCaps.get(internalFormat);
+
+        // Bits for texturing
+        const gl::InternalFormat &internalFormatInfo =
+            gl::GetSizedInternalFormatInfo(internalFormat);
+
+        UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D;
+        if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0)
+        {
+            texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE;
+            if (GetParam().majorVersion > 2)
+            {
+                texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+            }
+        }
+
+        UINT texSupport  = 0;
+        bool texSuccess  = SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &texSupport));
+        bool textureable = texSuccess && ((texSupport & texSupportMask) == texSupportMask);
+        EXPECT_EQ(textureable, textureInfo.texturable);
+
+        // Bits for mipmap auto-gen.
+        bool expectedMipGen = texSuccess && ((texSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0);
+        auto featureLevel   = renderer->getRenderer11DeviceCaps().featureLevel;
+        const auto &dxgiSupport = rx::d3d11::GetDXGISupport(formatInfo.texFormat, featureLevel);
+        bool actualMipGen =
+            ((dxgiSupport.alwaysSupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0);
+        EXPECT_EQ(0u, dxgiSupport.optionallySupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN);
+        EXPECT_EQ(expectedMipGen, actualMipGen);
+
+        // Bits for filtering
+        UINT filterSupport = 0;
+        bool filterSuccess =
+            SUCCEEDED(device->CheckFormatSupport(formatInfo.srvFormat, &filterSupport));
+        bool filterable = filterSuccess && ((filterSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) != 0);
+        EXPECT_EQ(filterable, textureInfo.filterable);
+
+        // Bits for renderable
+        bool renderable = false;
+        UINT renderSupport       = 0u;
+        DXGI_FORMAT renderFormat = DXGI_FORMAT_UNKNOWN;
+        if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0)
+        {
+            renderFormat = formatInfo.dsvFormat;
+            bool depthSuccess =
+                SUCCEEDED(device->CheckFormatSupport(formatInfo.dsvFormat, &renderSupport));
+            renderable =
+                depthSuccess && ((renderSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0);
+            if (renderable)
+            {
+                EXPECT_NE(DXGI_FORMAT_UNKNOWN, formatInfo.dsvFormat);
+            }
+        }
+        else
+        {
+            renderFormat = formatInfo.rtvFormat;
+            bool rtSuccess =
+                SUCCEEDED(device->CheckFormatSupport(formatInfo.rtvFormat, &renderSupport));
+            renderable = rtSuccess && ((renderSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0);
+            if (renderable)
+            {
+                EXPECT_NE(DXGI_FORMAT_UNKNOWN, formatInfo.rtvFormat);
+            }
+        }
+        EXPECT_EQ(renderable, textureInfo.renderable);
+        if (!textureInfo.sampleCounts.empty())
+        {
+            EXPECT_TRUE(renderable);
+        }
+
+        // Multisample counts
+        if (renderable)
+        {
+            if ((renderSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0)
+            {
+                EXPECT_TRUE(!textureInfo.sampleCounts.empty());
+                for (unsigned int sampleCount = 1;
+                     sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2)
+                {
+                    UINT qualityCount  = 0;
+                    bool sampleSuccess = SUCCEEDED(device->CheckMultisampleQualityLevels(
+                        renderFormat, sampleCount, &qualityCount));
+                    GLuint expectedCount = (!sampleSuccess || qualityCount == 0) ? 0 : 1;
+                    EXPECT_EQ(expectedCount, textureInfo.sampleCounts.count(sampleCount));
+                }
+            }
+            else
+            {
+                EXPECT_TRUE(textureInfo.sampleCounts.empty());
+            }
+        }
+    }
+}
+
+ANGLE_INSTANTIATE_TEST(D3D11FormatTablesTest,
+                       ES2_D3D11_FL9_3(),
+                       ES2_D3D11_FL10_0(),
+                       ES2_D3D11_FL10_1(),
+                       ES2_D3D11_FL11_0());
+
+} // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp b/src/third_party/angle/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp
new file mode 100644
index 0000000..7f182d2
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp
@@ -0,0 +1,126 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// D3D11InputLayoutCacheTest:
+//   Stress to to reproduce a bug where we weren't fluing the case correctly.
+//
+
+#include <sstream>
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "test_utils/ANGLETest.h"
+#include "test_utils/angle_test_instantiate.h"
+
+using namespace angle;
+
+namespace
+{
+
+class D3D11InputLayoutCacheTest : public ANGLETest
+{
+  protected:
+    D3D11InputLayoutCacheTest()
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    GLuint makeProgramWithAttribCount(unsigned int attribCount)
+    {
+        std::stringstream strstr;
+
+        strstr << "attribute vec2 position;" << std::endl;
+        for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+        {
+            strstr << "attribute float a" << attribIndex << ";" << std::endl;
+        }
+        strstr << "varying float v;" << std::endl
+               << "void main() {" << std::endl
+               << "    v = 0.0;" << std::endl;
+        for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+        {
+            strstr << "    v += a" << attribIndex << ";" << std::endl;
+        }
+        strstr << "    gl_Position = vec4(position, 0.0, 1.0);" << std::endl
+               << "}" << std::endl;
+
+        const std::string basicFragmentShader =
+            "varying highp float v;\n"
+            "void main() {"
+            "   gl_FragColor = vec4(v / 255.0, 0.0, 0.0, 1.0);\n"
+            "}\n";
+
+        return CompileProgram(strstr.str(), basicFragmentShader);
+    }
+};
+
+// Stress the cache by setting a small cache size and drawing with a bunch of shaders
+// with different input signatures.
+TEST_P(D3D11InputLayoutCacheTest, StressTest)
+{
+    // Hack the ANGLE!
+    gl::Context *context = reinterpret_cast<gl::Context *>(getEGLWindow()->getContext());
+    rx::Context11 *context11               = rx::GetImplAs<rx::Context11>(context);
+    rx::Renderer11 *renderer11             = context11->getRenderer();
+    rx::InputLayoutCache *inputLayoutCache = renderer11->getInputLayoutCache();
+
+    // Clamp the cache size to something tiny
+    inputLayoutCache->setCacheSize(4);
+
+    GLint maxAttribs = 0;
+    context->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
+
+    // Reserve one attrib for position
+    unsigned int maxInputs = static_cast<unsigned int>(maxAttribs) - 2;
+
+    std::vector<GLuint> programs;
+    for (unsigned int attribCount = 0; attribCount <= maxInputs; ++attribCount)
+    {
+        GLuint program = makeProgramWithAttribCount(attribCount);
+        ASSERT_NE(0u, program);
+        programs.push_back(program);
+    }
+
+    // Iteratively do a simple drop operation, trying every attribute count from 0..MAX_ATTRIBS.
+    // This should thrash the cache.
+    for (unsigned int iterationCount = 0; iterationCount < 10; ++iterationCount)
+    {
+        ASSERT_GL_NO_ERROR();
+
+        for (unsigned int attribCount = 0; attribCount <= maxInputs; ++attribCount)
+        {
+            GLuint program = programs[attribCount];
+            glUseProgram(program);
+
+            for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+            {
+                std::stringstream attribNameStr;
+                attribNameStr << "a" << attribIndex;
+                std::string attribName = attribNameStr.str();
+
+                GLint location = glGetAttribLocation(program, attribName.c_str());
+                ASSERT_NE(-1, location);
+                glVertexAttrib1f(location, 1.0f);
+                glDisableVertexAttribArray(location);
+            }
+
+            drawQuad(program, "position", 0.5f);
+            EXPECT_PIXEL_EQ(0, 0, attribCount, 0, 0, 255u);
+        }
+    }
+
+    for (GLuint program : programs)
+    {
+        glDeleteProgram(program);
+    }
+}
+
+ANGLE_INSTANTIATE_TEST(D3D11InputLayoutCacheTest, ES2_D3D11());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/D3DImageFormatConversionTest.cpp b/src/third_party/angle/src/tests/gl_tests/D3DImageFormatConversionTest.cpp
new file mode 100644
index 0000000..d6319d3
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/D3DImageFormatConversionTest.cpp
@@ -0,0 +1,207 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// D3DImageFormatConversionTest:
+//   Basic tests to validate code relating to D3D Image format conversions.
+
+#include "test_utils/ANGLETest.h"
+
+#include "image_util/imageformats.h"
+
+using namespace angle;
+
+namespace
+{
+
+class D3DImageFormatConversionTest : public ANGLETest
+{
+  protected:
+    D3DImageFormatConversionTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = vec4(position.xy, 0.0, 1.0);
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        );
+
+        const std::string fragmentShaderSource2D = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        m2DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource2D);
+        mTexture2DUniformLocation = glGetUniformLocation(m2DProgram, "tex");
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(m2DProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    // Uses ColorStructType::writeColor to populate initial data for a texture, pass it to glTexImage2D, then render with it.
+    // The resulting colors should match the colors passed into ::writeColor.
+    template <typename ColorStructType>
+    void runTest(GLenum tex2DFormat, GLenum tex2DType)
+    {
+        gl::ColorF srcColorF[4];
+        ColorStructType pixels[4];
+
+        GLuint tex = 0;
+        GLuint fbo = 0;
+        glGenTextures(1, &tex);
+        glGenFramebuffers(1, &fbo);
+        EXPECT_GL_NO_ERROR();
+
+        srcColorF[0].red = 1.0f; srcColorF[0].green = 0.0f; srcColorF[0].blue = 0.0f; srcColorF[0].alpha = 1.0f; // Red
+        srcColorF[1].red = 0.0f; srcColorF[1].green = 1.0f; srcColorF[1].blue = 0.0f; srcColorF[1].alpha = 1.0f; // Green
+        srcColorF[2].red = 0.0f; srcColorF[2].green = 0.0f; srcColorF[2].blue = 1.0f; srcColorF[2].alpha = 1.0f; // Blue
+        srcColorF[3].red = 1.0f; srcColorF[3].green = 1.0f; srcColorF[3].blue = 0.0f; srcColorF[3].alpha = 1.0f; // Red + Green (Yellow)
+
+        // Convert the ColorF into the pixels that will be fed to glTexImage2D
+        for (unsigned int i = 0; i < 4; i++)
+        {
+            ColorStructType::writeColor(&(pixels[i]), &(srcColorF[i]));
+        }
+
+        // Generate the texture
+        glBindTexture(GL_TEXTURE_2D, tex);
+        glTexImage2D(GL_TEXTURE_2D, 0, tex2DFormat, 2, 2, 0, tex2DFormat, tex2DType, pixels);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        EXPECT_GL_NO_ERROR();
+
+        // Draw a quad using the texture
+        glClearColor(0, 0, 0, 0);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glUseProgram(m2DProgram);
+        glUniform1i(mTexture2DUniformLocation, 0);
+        drawQuad(m2DProgram, "position", 0.5f);
+        EXPECT_GL_NO_ERROR();
+
+        // Check that the pixel colors match srcColorF
+        EXPECT_PIXEL_EQ(                    0,                    0, 255,   0,   0, 255);
+        EXPECT_PIXEL_EQ(getWindowHeight() - 1,                    0,   0, 255,   0, 255);
+        EXPECT_PIXEL_EQ(                    0, getWindowWidth() - 1,   0,   0, 255, 255);
+        EXPECT_PIXEL_EQ(getWindowHeight() - 1, getWindowWidth() - 1, 255, 255,   0, 255);
+        swapBuffers();
+
+        glDeleteFramebuffers(1, &fbo);
+        glDeleteTextures(1, &tex);
+    }
+
+    GLuint m2DProgram;
+    GLint mTexture2DUniformLocation;
+};
+
+// Validation test for rx::R4G4B4A4's writeColor functions
+TEST_P(D3DImageFormatConversionTest, WriteColorFunctionR4G4B4A4)
+{
+    // These tests fail on certain Intel machines running an un-updated version of Win7
+    // The tests pass after installing the latest updates from Windows Update.
+    // TODO: reenable these tests once the bots have been updated
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D11." << std::endl;
+        return;
+    }
+
+    runTest<R4G4B4A4>(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
+}
+
+// Validation test for rx::R5G5B5A1's writeColor functions
+TEST_P(D3DImageFormatConversionTest, WriteColorFunctionR5G5B5A1)
+{
+    // These tests fail on certain Intel machines running an un-updated version of Win7
+    // The tests pass after installing the latest updates from Windows Update.
+    // TODO: reenable these tests once the bots have been updated
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D11." << std::endl;
+        return;
+    }
+
+    runTest<R5G5B5A1>(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
+}
+
+// Validation test for rx::R5G6B5's writeColor functions
+TEST_P(D3DImageFormatConversionTest, WriteColorFunctionR5G6B5)
+{
+    // These tests fail on certain Intel machines running an un-updated version of Win7
+    // The tests pass after installing the latest updates from Windows Update.
+    // TODO: reenable these tests once the bots have been updated
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D11." << std::endl;
+        return;
+    }
+
+    runTest<R5G6B5>(GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
+}
+
+// Validation test for rx::R8G8B8A8's writeColor functions
+TEST_P(D3DImageFormatConversionTest, WriteColorFunctionR8G8B8A8)
+{
+    // These tests fail on certain Intel machines running an un-updated version of Win7
+    // The tests pass after installing the latest updates from Windows Update.
+    // TODO: reenable these tests once the bots have been updated
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D11." << std::endl;
+        return;
+    }
+
+    runTest<R8G8B8A8>(GL_RGBA, GL_UNSIGNED_BYTE);
+}
+
+// Validation test for rx::R8G8B8's writeColor functions
+TEST_P(D3DImageFormatConversionTest, WriteColorFunctionR8G8B8)
+{
+    // These tests fail on certain Intel machines running an un-updated version of Win7
+    // The tests pass after installing the latest updates from Windows Update.
+    // TODO: reenable these tests once the bots have been updated
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D11." << std::endl;
+        return;
+    }
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    runTest<R8G8B8>(GL_RGB, GL_UNSIGNED_BYTE);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+// Even though this test is only run on Windows (since it includes imageformats.h from the D3D renderer), we can still run the test
+// against OpenGL. This is valuable, since it provides extra validation using a renderer that doesn't use imageformats.h itself.
+ANGLE_INSTANTIATE_TEST(D3DImageFormatConversionTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3(), ES2_OPENGL());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/D3DTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/D3DTextureTest.cpp
new file mode 100644
index 0000000..71389e5
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/D3DTextureTest.cpp
@@ -0,0 +1,544 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// D3DTextureTest:
+//   Tests of the EGL_ANGLE_d3d_texture_client_buffer extension
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include <d3d11.h>
+#include <windows.h>
+
+#include "com_utils.h"
+
+namespace angle
+{
+
+class D3DTextureTest : public ANGLETest
+{
+  protected:
+    D3DTextureTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        // clang-format off
+        const std::string vsSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = position;
+                texcoord = (position.xy * 0.5) + 0.5;
+                texcoord.y = 1.0 - texcoord.y;
+            }
+        );
+
+        const std::string textureFSSource = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        const std::string textureFSSourceNoSampling = SHADER_SOURCE
+        (
+            precision highp float;
+
+            void main()
+            {
+                gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
+            }
+        );
+        // clang-format on
+
+        mTextureProgram = CompileProgram(vsSource, textureFSSource);
+        ASSERT_NE(0u, mTextureProgram) << "shader compilation failed.";
+
+        mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
+        ASSERT_NE(-1, mTextureUniformLocation);
+
+        mTextureProgramNoSampling = CompileProgram(vsSource, textureFSSourceNoSampling);
+        ASSERT_NE(0u, mTextureProgramNoSampling) << "shader compilation failed.";
+
+        mD3D11Module = LoadLibrary(TEXT("d3d11.dll"));
+        ASSERT_NE(nullptr, mD3D11Module);
+
+        PFN_D3D11_CREATE_DEVICE createDeviceFunc = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+            GetProcAddress(mD3D11Module, "D3D11CreateDevice"));
+
+        EGLWindow *window  = getEGLWindow();
+        EGLDisplay display = window->getDisplay();
+        if (eglDisplayExtensionEnabled(display, "EGL_EXT_device_query"))
+        {
+            PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT =
+                reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
+                    eglGetProcAddress("eglQueryDisplayAttribEXT"));
+            PFNEGLQUERYDEVICEATTRIBEXTPROC eglQueryDeviceAttribEXT =
+                reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(
+                    eglGetProcAddress("eglQueryDeviceAttribEXT"));
+
+            EGLDeviceEXT device = 0;
+            {
+                EGLAttrib result = 0;
+                EXPECT_EGL_TRUE(eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, &result));
+                device = reinterpret_cast<EGLDeviceEXT>(result);
+            }
+
+            if (eglDeviceExtensionEnabled(device, "EGL_ANGLE_device_d3d"))
+            {
+                EGLAttrib result = 0;
+                if (eglQueryDeviceAttribEXT(device, EGL_D3D11_DEVICE_ANGLE, &result))
+                {
+                    mD3D11Device = reinterpret_cast<ID3D11Device *>(result);
+                    mD3D11Device->AddRef();
+                }
+                else if (eglQueryDeviceAttribEXT(device, EGL_D3D9_DEVICE_ANGLE, &result))
+                {
+                    mD3D9Device = reinterpret_cast<IDirect3DDevice9 *>(result);
+                    mD3D9Device->AddRef();
+                }
+            }
+        }
+        else
+        {
+            ASSERT_TRUE(
+                SUCCEEDED(createDeviceFunc(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr,
+                                           0, D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr)));
+        }
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mTextureProgram);
+
+        if (mD3D11Device)
+        {
+            mD3D11Device->Release();
+            mD3D11Device = nullptr;
+        }
+
+        FreeLibrary(mD3D11Module);
+        mD3D11Module = nullptr;
+
+        if (mD3D9Device)
+        {
+            mD3D9Device->Release();
+            mD3D9Device = nullptr;
+        }
+
+        ANGLETest::TearDown();
+    }
+
+    EGLSurface createPBuffer(size_t width,
+                             size_t height,
+                             EGLint eglTextureFormat,
+                             EGLint eglTextureTarget,
+                             UINT sampleCount,
+                             UINT sampleQuality)
+    {
+        EGLWindow *window  = getEGLWindow();
+        EGLDisplay display = window->getDisplay();
+        EGLConfig config   = window->getConfig();
+
+        EGLint attribs[] = {
+            EGL_TEXTURE_FORMAT, eglTextureFormat, EGL_TEXTURE_TARGET,
+            eglTextureTarget,   EGL_NONE,         EGL_NONE,
+        };
+
+        if (mD3D11Device)
+        {
+            ID3D11Texture2D *texture = nullptr;
+            CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, static_cast<UINT>(width),
+                                       static_cast<UINT>(height), 1, 1,
+                                       D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
+            desc.SampleDesc.Count   = sampleCount;
+            desc.SampleDesc.Quality = sampleQuality;
+            EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &texture)));
+
+            EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
+                                                                  texture, config, attribs);
+
+            texture->Release();
+
+            return pbuffer;
+        }
+        else if (mD3D9Device)
+        {
+            // Multisampled textures are not supported on D3D9.
+            ASSERT(sampleCount <= 1);
+            ASSERT(sampleQuality == 0);
+
+            IDirect3DTexture9 *texture = nullptr;
+            EXPECT_TRUE(SUCCEEDED(mD3D9Device->CreateTexture(
+                static_cast<UINT>(width), static_cast<UINT>(height), 1, D3DUSAGE_RENDERTARGET,
+                D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, nullptr)));
+
+            EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
+                                                                  texture, config, attribs);
+
+            texture->Release();
+
+            return pbuffer;
+        }
+        else
+        {
+            return EGL_NO_SURFACE;
+        }
+    }
+
+    bool valid() const
+    {
+        EGLWindow *window  = getEGLWindow();
+        EGLDisplay display = window->getDisplay();
+        if (!eglDisplayExtensionEnabled(display, "EGL_ANGLE_d3d_texture_client_buffer"))
+        {
+            std::cout << "Test skipped due to missing EGL_ANGLE_d3d_texture_client_buffer"
+                      << std::endl;
+            return false;
+        }
+
+        if (!mD3D11Device && !mD3D9Device)
+        {
+            std::cout << "Test skipped due to no D3D devices being available." << std::endl;
+            return false;
+        }
+
+        if (IsWindows() && IsAMD() && IsOpenGL())
+        {
+            std::cout << "Test skipped on Windows AMD OpenGL." << std::endl;
+            return false;
+        }
+
+        if (IsWindows() && IsIntel() && IsOpenGL())
+        {
+            std::cout << "Test skipped on Windows Intel OpenGL." << std::endl;
+            return false;
+        }
+        return true;
+    }
+
+    GLuint mTextureProgram;
+    GLuint mTextureProgramNoSampling;
+    GLint mTextureUniformLocation;
+
+    HMODULE mD3D11Module       = nullptr;
+    ID3D11Device *mD3D11Device = nullptr;
+
+    IDirect3DDevice9 *mD3D9Device = nullptr;
+};
+
+// Test creating a pbuffer from a d3d surface and clearing it
+TEST_P(D3DTextureTest, Clear)
+{
+    if (!valid())
+    {
+        return;
+    }
+
+    EGLWindow *window  = getEGLWindow();
+    EGLDisplay display = window->getDisplay();
+
+    const size_t bufferSize = 32;
+
+    EGLSurface pbuffer =
+        createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 1, 0);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_NE(pbuffer, EGL_NO_SURFACE);
+
+    // Apply the Pbuffer and clear it to purple and verify
+    eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
+                    255, 255);
+
+    // Make current with null to ensure the Surface can be released immediately.
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroySurface(display, pbuffer);
+}
+
+// Test creating a pbuffer with a D3D texture and depth stencil bits in the EGL config creates keeps
+// its depth stencil buffer
+TEST_P(D3DTextureTest, DepthStencil)
+{
+    if (!valid())
+    {
+        return;
+    }
+
+    EGLWindow *window  = getEGLWindow();
+    EGLDisplay display = window->getDisplay();
+
+    const size_t bufferSize = 32;
+
+    EGLSurface pbuffer =
+        createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 1, 0);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_NE(pbuffer, EGL_NO_SURFACE);
+
+    // Apply the Pbuffer and clear it to purple and verify
+    eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
+    glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
+    glClearDepthf(0.5f);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    glEnable(GL_DEPTH_TEST);
+    glDepthMask(GL_FALSE);
+
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
+
+    // Draw a quad that will fail the depth test and verify that the buffer is unchanged
+    drawQuad(mTextureProgram, "position", 1.0f);
+    EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
+                          GLColor::cyan);
+
+    // Draw a quad that will pass the depth test and verify that the buffer is green
+    drawQuad(mTextureProgram, "position", -1.0f);
+    EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
+                          GLColor::green);
+
+    // Make current with null to ensure the Surface can be released immediately.
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroySurface(display, pbuffer);
+}
+
+// Test creating a pbuffer from a d3d surface and binding it to a texture
+TEST_P(D3DTextureTest, BindTexImage)
+{
+    if (!valid())
+    {
+        return;
+    }
+
+    EGLWindow *window = getEGLWindow();
+    EGLDisplay display = window->getDisplay();
+
+    const size_t bufferSize = 32;
+
+    EGLSurface pbuffer =
+        createPBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0);
+    ASSERT_EGL_SUCCESS();
+    ASSERT_NE(pbuffer, EGL_NO_SURFACE);
+
+    // Apply the Pbuffer and clear it to purple
+    eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
+                    255, 255);
+
+    // Apply the window surface
+    eglMakeCurrent(display, window->getSurface(), window->getSurface(), window->getContext());
+
+    // Create a texture and bind the Pbuffer to it
+    GLuint texture = 0;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    EXPECT_GL_NO_ERROR();
+
+    eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
+    glViewport(0, 0, getWindowWidth(), getWindowHeight());
+    ASSERT_EGL_SUCCESS();
+
+    // Draw a quad and verify that it is purple
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    drawQuad(mTextureProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+
+    // Unbind the texture
+    eglReleaseTexImage(display, pbuffer, EGL_BACK_BUFFER);
+    ASSERT_EGL_SUCCESS();
+
+    // Verify that purple was drawn
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
+
+    glDeleteTextures(1, &texture);
+
+    // Make current with null to ensure the Surface can be released immediately.
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroySurface(display, pbuffer);
+}
+
+// Verify that creating a pbuffer with a multisampled texture will fail on a non-multisampled
+// window.
+TEST_P(D3DTextureTest, CheckSampleMismatch)
+{
+    if (!valid())
+    {
+        return;
+    }
+
+    // Multisampling is not supported on D3D9 or OpenGL.
+    if (IsD3D9() || IsOpenGL())
+    {
+        return;
+    }
+
+    constexpr size_t bufferSize = 32;
+
+    EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 2,
+                                       static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
+    EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+    EXPECT_EQ(pbuffer, nullptr);
+}
+
+class D3DTextureTestMS : public D3DTextureTest
+{
+  protected:
+    D3DTextureTestMS() : D3DTextureTest()
+    {
+        setSamples(4);
+        setMultisampleEnabled(true);
+    }
+};
+
+// Test creating a pbuffer from a multisampled d3d surface and clearing it.
+TEST_P(D3DTextureTestMS, Clear)
+{
+    EGLWindow *window  = getEGLWindow();
+    EGLDisplay display = window->getDisplay();
+
+    constexpr size_t bufferSize = 32;
+    constexpr UINT testpoint    = bufferSize / 2;
+
+    EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
+                                       static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
+    ASSERT_EGL_SUCCESS();
+    ASSERT_NE(pbuffer, EGL_NO_SURFACE);
+
+    // Apply the Pbuffer and clear it to magenta and verify
+    eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(testpoint, testpoint, GLColor::magenta);
+
+    // Make current with null to ensure the Surface can be released immediately.
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroySurface(display, pbuffer);
+}
+
+// Test creating a pbuffer from a multisampled d3d surface and drawing with a program.
+TEST_P(D3DTextureTestMS, DrawProgram)
+{
+    EGLWindow *window  = getEGLWindow();
+    EGLDisplay display = window->getDisplay();
+
+    constexpr size_t bufferSize = 32;
+
+    EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
+                                       static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
+    ASSERT_EGL_SUCCESS();
+    ASSERT_NE(pbuffer, EGL_NO_SURFACE);
+
+    // Apply the Pbuffer and clear it to magenta
+    eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    constexpr GLint testPoint = bufferSize / 2;
+    EXPECT_PIXEL_COLOR_EQ(testPoint, testPoint, GLColor::magenta);
+
+    // Apply the window surface
+    eglMakeCurrent(display, window->getSurface(), window->getSurface(), window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, getWindowWidth(), getWindowHeight());
+    ASSERT_EGL_SUCCESS();
+
+    // Draw a quad and verify that it is magenta
+    glUseProgram(mTextureProgramNoSampling);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mTextureProgramNoSampling, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+
+    // Verify that magenta was drawn
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::magenta);
+
+    // Make current with null to ensure the Surface can be released immediately.
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroySurface(display, pbuffer);
+}
+
+// Test for failure when creating a pbuffer from a multisampled d3d surface to bind to a texture.
+TEST_P(D3DTextureTestMS, BindTexture)
+{
+    constexpr size_t bufferSize = 32;
+
+    EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 4,
+                                       static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
+    EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
+    EXPECT_EQ(pbuffer, nullptr);
+}
+
+// Verify that creating a pbuffer from a multisampled texture with a multisampled window will fail
+// when the sample counts do not match.
+TEST_P(D3DTextureTestMS, CheckSampleMismatch)
+{
+    constexpr size_t bufferSize = 32;
+
+    EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 2,
+                                       static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
+
+    EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+    EXPECT_EQ(pbuffer, nullptr);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(D3DTextureTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
+ANGLE_INSTANTIATE_TEST(D3DTextureTestMS, ES2_D3D11());
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/DXT1CompressedTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/DXT1CompressedTextureTest.cpp
new file mode 100644
index 0000000..ce53881
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DXT1CompressedTextureTest.cpp
@@ -0,0 +1,370 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include "media/pixel.inl"
+
+using namespace angle;
+
+class DXT1CompressedTextureTest : public ANGLETest
+{
+  protected:
+    DXT1CompressedTextureTest()
+    {
+        setWindowWidth(512);
+        setWindowHeight(512);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = position;
+                texcoord = (position.xy * 0.5) + 0.5;
+                texcoord.y = 1.0 - texcoord.y;
+            }
+        );
+
+        const std::string textureFSSource = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        mTextureProgram = CompileProgram(vsSource, textureFSSource);
+        if (mTextureProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mTextureProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mTextureProgram;
+    GLint mTextureUniformLocation;
+};
+
+TEST_P(DXT1CompressedTextureTest, CompressedTexImage)
+{
+    if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
+    {
+        std::cout << "Test skipped because GL_EXT_texture_compression_dxt1 is not available." << std::endl;
+        return;
+    }
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height, 0, pixel_0_size, pixel_0_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_width, pixel_1_height, 0, pixel_1_size, pixel_1_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_2_width, pixel_2_height, 0, pixel_2_size, pixel_2_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_3_width, pixel_3_height, 0, pixel_3_size, pixel_3_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_4_width, pixel_4_height, 0, pixel_4_size, pixel_4_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 5, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_5_width, pixel_5_height, 0, pixel_5_size, pixel_5_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 6, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_6_width, pixel_6_height, 0, pixel_6_size, pixel_6_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 7, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_7_width, pixel_7_height, 0, pixel_7_size, pixel_7_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 8, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_8_width, pixel_8_height, 0, pixel_8_size, pixel_8_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 9, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_9_width, pixel_9_height, 0, pixel_9_size, pixel_9_data);
+
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    drawQuad(mTextureProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteTextures(1, &texture);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(DXT1CompressedTextureTest, CompressedTexStorage)
+{
+    if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
+    {
+        std::cout << "Test skipped due to missing GL_EXT_texture_compression_dxt1" << std::endl;
+        return;
+    }
+
+    if (getClientMajorVersion() < 3 &&
+        (!extensionEnabled("GL_EXT_texture_storage") || !extensionEnabled("GL_OES_rgb8_rgba8")))
+    {
+        std::cout << "Test skipped due to missing ES3 or GL_EXT_texture_storage or GL_OES_rgb8_rgba8" << std::endl;
+        return;
+    }
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    if (getClientMajorVersion() < 3)
+    {
+        glTexStorage2DEXT(GL_TEXTURE_2D, pixel_levels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height);
+    }
+    else
+    {
+        glTexStorage2D(GL_TEXTURE_2D, pixel_levels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height);
+    }
+    EXPECT_GL_NO_ERROR();
+
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pixel_0_width, pixel_0_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_size, pixel_0_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, pixel_1_width, pixel_1_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_size, pixel_1_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, pixel_2_width, pixel_2_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_2_size, pixel_2_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 3, 0, 0, pixel_3_width, pixel_3_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_3_size, pixel_3_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 4, 0, 0, pixel_4_width, pixel_4_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_4_size, pixel_4_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 5, 0, 0, pixel_5_width, pixel_5_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_5_size, pixel_5_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 6, 0, 0, pixel_6_width, pixel_6_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_6_size, pixel_6_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 7, 0, 0, pixel_7_width, pixel_7_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_7_size, pixel_7_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 8, 0, 0, pixel_8_width, pixel_8_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_8_size, pixel_8_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 9, 0, 0, pixel_9_width, pixel_9_height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_9_size, pixel_9_data);
+
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    drawQuad(mTextureProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteTextures(1, &texture);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test validation of glCompressedTexSubImage2D with DXT formats
+TEST_P(DXT1CompressedTextureTest, CompressedTexSubImageValidation)
+{
+    if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
+    {
+        std::cout << "Test skipped due to missing GL_EXT_texture_compression_dxt1" << std::endl;
+        return;
+    }
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+
+    // Size mip 0 to a large size
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
+                           pixel_0_height, 0, pixel_0_size, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    // Set a sub image with an offset that isn't a multiple of the block size
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 1, 3, pixel_1_width, pixel_1_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_size, pixel_1_data);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+class DXT1CompressedTextureTestES3 : public DXT1CompressedTextureTest { };
+
+class DXT1CompressedTextureTestD3D11 : public DXT1CompressedTextureTest { };
+
+TEST_P(DXT1CompressedTextureTestES3, PBOCompressedTexImage)
+{
+    if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
+    {
+        std::cout << "Test skipped because GL_EXT_texture_compression_dxt1 is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    GLuint buffer;
+    glGenBuffers(1, &buffer);
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, pixel_0_size, nullptr, GL_STREAM_DRAW);
+    EXPECT_GL_NO_ERROR();
+
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_0_size, pixel_0_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
+                           pixel_0_height, 0, pixel_0_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_1_size, pixel_1_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_width,
+                           pixel_1_height, 0, pixel_1_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_2_size, pixel_2_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_2_width,
+                           pixel_2_height, 0, pixel_2_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_3_size, pixel_3_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_3_width,
+                           pixel_3_height, 0, pixel_3_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_4_size, pixel_4_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_4_width,
+                           pixel_4_height, 0, pixel_4_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_5_size, pixel_5_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 5, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_5_width,
+                           pixel_5_height, 0, pixel_5_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_6_size, pixel_6_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 6, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_6_width,
+                           pixel_6_height, 0, pixel_6_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_7_size, pixel_7_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 7, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_7_width,
+                           pixel_7_height, 0, pixel_7_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_8_size, pixel_8_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 8, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_8_width,
+                           pixel_8_height, 0, pixel_8_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_9_size, pixel_9_data);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 9, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_9_width,
+                           pixel_9_height, 0, pixel_9_size, nullptr);
+
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    drawQuad(mTextureProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteTextures(1, &buffer);
+    glDeleteTextures(1, &texture);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+
+TEST_P(DXT1CompressedTextureTestD3D11, PBOCompressedTexStorage)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_compression_dxt1"))
+    {
+        return;
+    }
+
+    if (getClientMajorVersion() < 3 &&
+        (!extensionEnabled("GL_EXT_texture_storage") || !extensionEnabled("GL_OES_rgb8_rgba8")))
+    {
+        return;
+    }
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    if (getClientMajorVersion() < 3)
+    {
+        glTexStorage2DEXT(GL_TEXTURE_2D, pixel_levels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height);
+    }
+    else
+    {
+        glTexStorage2D(GL_TEXTURE_2D, pixel_levels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height);
+    }
+    EXPECT_GL_NO_ERROR();
+
+    GLuint buffer;
+    glGenBuffers(1, &buffer);
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, pixel_0_size, nullptr, GL_STREAM_DRAW);
+    EXPECT_GL_NO_ERROR();
+
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_0_size, pixel_0_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pixel_0_width, pixel_0_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_1_size, pixel_1_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, pixel_1_width, pixel_1_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_2_size, pixel_2_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, pixel_2_width, pixel_2_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_2_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_3_size, pixel_3_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 3, 0, 0, pixel_3_width, pixel_3_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_3_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_4_size, pixel_4_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 4, 0, 0, pixel_4_width, pixel_4_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_4_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_5_size, pixel_5_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 5, 0, 0, pixel_5_width, pixel_5_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_5_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_6_size, pixel_6_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 6, 0, 0, pixel_6_width, pixel_6_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_6_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_7_size, pixel_7_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 7, 0, 0, pixel_7_width, pixel_7_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_7_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_8_size, pixel_8_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 8, 0, 0, pixel_8_width, pixel_8_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_8_size, nullptr);
+    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_9_size, pixel_9_data);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 9, 0, 0, pixel_9_width, pixel_9_height,
+                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_9_size, nullptr);
+
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    drawQuad(mTextureProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteTextures(1, &texture);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(DXT1CompressedTextureTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(DXT1CompressedTextureTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(DXT1CompressedTextureTestD3D11, ES2_D3D11(), ES3_D3D11(), ES2_D3D11_FL9_3());
diff --git a/src/third_party/angle/src/tests/gl_tests/DXTSRGBCompressedTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/DXTSRGBCompressedTextureTest.cpp
new file mode 100644
index 0000000..0aa9422
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DXTSRGBCompressedTextureTest.cpp
@@ -0,0 +1,170 @@
+//
+// Copyright 2016 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.
+//
+// DXTSRGBCompressedTextureTest.cpp
+//   Tests for sRGB DXT textures (GL_EXT_texture_compression_s3tc_srgb)
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include "media/pixel.inl"
+
+#include "DXTSRGBCompressedTextureTestData.inl"
+
+using namespace angle;
+
+static constexpr int kWindowSize = 64;
+
+class DXTSRGBCompressedTextureTest : public ANGLETest
+{
+  protected:
+    DXTSRGBCompressedTextureTest()
+    {
+        setWindowWidth(kWindowSize);
+        setWindowHeight(kWindowSize);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource = std::string(
+            "precision highp float;\n"
+            "attribute vec4 position;\n"
+            "varying vec2 texcoord;\n"
+            "void main() {\n"
+            "    gl_Position = position;\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "    texcoord.y = 1.0 - texcoord.y;\n"
+            "}");
+
+        const std::string textureFSSource = std::string(
+            "precision highp float;\n"
+            "uniform sampler2D tex;\n"
+            "varying vec2 texcoord;\n"
+            "void main() {\n"
+            "    gl_FragColor = texture2D(tex, texcoord);\n"
+            "}\n");
+
+        mTextureProgram = CompileProgram(vsSource, textureFSSource);
+        ASSERT_NE(0u, mTextureProgram);
+
+        mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
+        ASSERT_NE(-1, mTextureUniformLocation);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mTextureProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    void runTestChecks(const TestCase &test)
+    {
+        GLColor actual[kWindowSize * kWindowSize] = {0};
+        drawQuad(mTextureProgram, "position", 0.5f);
+        ASSERT_GL_NO_ERROR();
+        glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE,
+                     reinterpret_cast<void *>(actual));
+        ASSERT_GL_NO_ERROR();
+        for (GLsizei y = 0; y < test.height; ++y)
+        {
+            for (GLsizei x = 0; x < test.width; ++x)
+            {
+                GLColor exp = reinterpret_cast<const GLColor *>(test.expected)[y * test.width + x];
+                size_t x_actual = (x * kWindowSize + kWindowSize / 2) / test.width;
+                size_t y_actual =
+                    ((test.height - y - 1) * kWindowSize + kWindowSize / 2) / test.height;
+                GLColor act = actual[y_actual * kWindowSize + x_actual];
+                EXPECT_COLOR_NEAR(exp, act, 2.0);
+            }
+        }
+    }
+
+    void runTest(GLenum format)
+    {
+        if (!extensionEnabled("GL_EXT_texture_compression_s3tc_srgb"))
+        {
+            std::cout
+                << "Test skipped because GL_EXT_texture_compression_s3tc_srgb is not available."
+                << std::endl;
+            return;
+        }
+
+        const TestCase &test = kTests.at(format);
+
+        GLTexture texture;
+        glBindTexture(GL_TEXTURE_2D, texture.get());
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+        glUseProgram(mTextureProgram);
+        glUniform1i(mTextureUniformLocation, 0);
+        ASSERT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, test.width, test.height, 0, test.dataSize,
+                               test.data);
+        ASSERT_GL_NO_ERROR() << "glCompressedTexImage2D(format=" << format << ")";
+        runTestChecks(test);
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, test.width, test.height, 0, test.dataSize,
+                               nullptr);
+        ASSERT_GL_NO_ERROR() << "glCompressedTexImage2D(format=" << format << ", data=null)";
+        glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, test.width, test.height, format,
+                                  test.dataSize, test.data);
+        ASSERT_GL_NO_ERROR() << "glCompressedTexSubImage2D(format=" << format << ")";
+        runTestChecks(test);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    GLuint mTextureProgram        = 0;
+    GLint mTextureUniformLocation = -1;
+};
+
+// Test correct decompression of 8x8 textures (four 4x4 blocks) of SRGB_S3TC_DXT1
+TEST_P(DXTSRGBCompressedTextureTest, Decompression8x8RGBDXT1)
+{
+    runTest(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
+}
+
+// Test correct decompression of 8x8 textures (four 4x4 blocks) of SRGB_ALPHA_S3TC_DXT1
+TEST_P(DXTSRGBCompressedTextureTest, Decompression8x8RGBADXT1)
+{
+    runTest(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
+}
+
+// Test correct decompression of 8x8 textures (four 4x4 blocks) of SRGB_ALPHA_S3TC_DXT3
+TEST_P(DXTSRGBCompressedTextureTest, Decompression8x8RGBADXT3)
+{
+    runTest(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
+}
+
+// Test correct decompression of 8x8 textures (four 4x4 blocks) of SRGB_ALPHA_S3TC_DXT5
+TEST_P(DXTSRGBCompressedTextureTest, Decompression8x8RGBADXT5)
+{
+    runTest(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(DXTSRGBCompressedTextureTest,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/DXTSRGBCompressedTextureTestData.inl b/src/third_party/angle/src/tests/gl_tests/DXTSRGBCompressedTextureTestData.inl
new file mode 100644
index 0000000..fa9a308
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DXTSRGBCompressedTextureTestData.inl
@@ -0,0 +1,139 @@
+//
+// Copyright 2016 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.
+//
+// DXTSRGBCompressedTextureTestData.inl
+//   Data for sRGB DXT texture tests (DXTSRGBCompressedTextureTest.cpp)
+//
+
+static constexpr size_t kMaxCompressedSize = 64;
+static constexpr size_t kMaxDecompressedSize = 256;
+
+struct TestCase
+{
+    GLsizei width;
+    GLsizei height;
+    GLsizei dataSize;
+    uint8_t data[kMaxCompressedSize];
+    uint8_t expected[kMaxDecompressedSize];
+};
+
+static const std::map<GLenum, TestCase> kTests = {
+    {
+        GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
+        {
+            8, 8, 32,
+            {
+                0x08, 0xba, 0xe8, 0x45, 0x44, 0x45, 0x40, 0x55, 0xe8, 0xbd, 0x17, 0x42, 0x44, 0x45, 0x40, 0x55,
+                0x17, 0xba, 0xe8, 0x45, 0x11, 0x10, 0x15, 0x00, 0xf7, 0x45, 0x17, 0x42, 0x11, 0x10, 0x15, 0x00,
+            },
+            {
+                0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x82, 0x0d, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x82, 0x83, 0x0d, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 
+            }
+        }
+    },
+    {
+        GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
+        {
+            8, 8, 32,
+            {
+                0xa8, 0x4d, 0x48, 0xb2, 0x13, 0x10, 0x15, 0x00, 0xe8, 0xbd, 0x17, 0x42, 0x44, 0x45, 0x40, 0x55,
+                0x17, 0xba, 0xe8, 0x45, 0x11, 0x10, 0x15, 0x00, 0xf7, 0x45, 0x17, 0x42, 0x11, 0x10, 0x15, 0x00,
+            },
+            {
+                0x00, 0x00, 0x00, 0x00, 0x11, 0x77, 0x0d, 0xff, 0x74, 0x11, 0x0d, 0xff, 0x11, 0x77, 0x0d, 0xff,
+                0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x11, 0x77, 0x0d, 0xff, 0x11, 0x77, 0x0d, 0xff, 0x74, 0x11, 0x0d, 0xff, 0x11, 0x77, 0x0d, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x74, 0x11, 0x0d, 0xff, 0x74, 0x11, 0x0d, 0xff, 0x74, 0x11, 0x0d, 0xff, 0x11, 0x77, 0x0d, 0xff,
+                0x82, 0x83, 0x0d, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x11, 0x77, 0x0d, 0xff, 0x11, 0x77, 0x0d, 0xff, 0x11, 0x77, 0x0d, 0xff, 0x11, 0x77, 0x0d, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+            }
+        }
+    },
+    {
+        GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
+        {
+            8, 8, 64,
+            {
+                0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0xba, 0xe8, 0x45, 0x44, 0x45, 0x40, 0x55,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xbd, 0x17, 0x42, 0x44, 0x45, 0x40, 0x55,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x17, 0xba, 0xe8, 0x45, 0x11, 0x10, 0x15, 0x00,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x45, 0x17, 0x42, 0x11, 0x10, 0x15, 0x00,
+            },
+            {
+                0x82, 0x0d, 0x0d, 0x77, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x82, 0x0d, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x82, 0x83, 0x0d, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 
+            }
+        }
+    },
+    {
+        GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
+        {
+            8, 8, 64,
+            {
+                0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xba, 0xe8, 0x45, 0x44, 0x45, 0x40, 0x55,
+                0xff, 0xff, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0xe8, 0xbd, 0x17, 0x42, 0x44, 0x45, 0x40, 0x55,
+                0xff, 0xff, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x17, 0xba, 0xe8, 0x45, 0x11, 0x10, 0x15, 0x00,
+                0xff, 0xff, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0xf7, 0x45, 0x17, 0x42, 0x11, 0x10, 0x15, 0x00,
+            },
+            {
+                0x82, 0x0d, 0x0d, 0x7f, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x82, 0x0d, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x82, 0x0d, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x82, 0x83, 0x0d, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x82, 0x83, 0x0d, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x0d, 0x83, 0x0d, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x0d, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+                0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff, 0x82, 0x0d, 0x82, 0xff,
+                0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff, 0x0d, 0x83, 0x82, 0xff,
+            }
+        }
+    },
+};
diff --git a/src/third_party/angle/src/tests/gl_tests/DebugMarkerTest.cpp b/src/third_party/angle/src/tests/gl_tests/DebugMarkerTest.cpp
new file mode 100644
index 0000000..bafee8e
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DebugMarkerTest.cpp
@@ -0,0 +1,71 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugMarkerTest:
+//   Basic tests to ensure EXT_debug_marker entry points work.
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class DebugMarkerTest : public ANGLETest
+{
+  protected:
+    DebugMarkerTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+};
+
+// Simple test to ensure the various EXT_debug_marker entry points don't crash.
+// The debug markers can be validated by capturing this test under PIX/Graphics Diagnostics.
+TEST_P(DebugMarkerTest, BasicValidation)
+{
+    if (!extensionEnabled("GL_EXT_debug_marker"))
+    {
+        std::cout << "Test skipped due to missing GL_EXT_debug_marker" << std::endl;
+        return;
+    }
+
+    std::string eventMarkerCaption = "Test event marker caption";
+    std::string groupMarkerCaption = "Test group marker caption";
+
+    glPushGroupMarkerEXT(static_cast<GLsizei>(groupMarkerCaption.length()),
+                         groupMarkerCaption.c_str());
+
+    // Do some basic operations between calls to extension entry points
+    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glInsertEventMarkerEXT(static_cast<GLsizei>(eventMarkerCaption.length()),
+                           eventMarkerCaption.c_str());
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glPushGroupMarkerEXT(0, nullptr);
+    glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glPopGroupMarkerEXT();
+    glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glPopGroupMarkerEXT();
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(DebugMarkerTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/DebugTest.cpp b/src/third_party/angle/src/tests/gl_tests/DebugTest.cpp
new file mode 100644
index 0000000..c07acea
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DebugTest.cpp
@@ -0,0 +1,451 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DebugTest.cpp : Tests of the GL_KHR_debug extension
+
+#include "test_utils/ANGLETest.h"
+
+namespace angle
+{
+
+class DebugTest : public ANGLETest
+{
+  protected:
+    DebugTest() : mDebugExtensionAvailable(false)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setDebugEnabled(true);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        mDebugExtensionAvailable = extensionEnabled("GL_KHR_debug");
+        if (mDebugExtensionAvailable)
+        {
+            glEnable(GL_DEBUG_OUTPUT);
+        }
+    }
+
+    bool mDebugExtensionAvailable;
+};
+
+struct Message
+{
+    GLenum source;
+    GLenum type;
+    GLuint id;
+    GLenum severity;
+    std::string message;
+    const void *userParam;
+};
+
+static void GL_APIENTRY Callback(GLenum source,
+                                 GLenum type,
+                                 GLuint id,
+                                 GLenum severity,
+                                 GLsizei length,
+                                 const GLchar *message,
+                                 const void *userParam)
+{
+    Message m{source, type, id, severity, std::string(message, length), userParam};
+    std::vector<Message> *messages =
+        static_cast<std::vector<Message> *>(const_cast<void *>(userParam));
+    messages->push_back(m);
+}
+
+// Test that all ANGLE back-ends have GL_KHR_debug enabled
+TEST_P(DebugTest, Enabled)
+{
+    ASSERT_TRUE(mDebugExtensionAvailable);
+}
+
+// Test that when debug output is disabled, no message are outputted
+TEST_P(DebugTest, DisabledOutput)
+{
+    if (!mDebugExtensionAvailable)
+    {
+        std::cout << "Test skipped because GL_KHR_debug is not available." << std::endl;
+        return;
+    }
+
+    glDisable(GL_DEBUG_OUTPUT);
+
+    glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 1,
+                            GL_DEBUG_SEVERITY_NOTIFICATION, -1, "discarded");
+
+    GLint numMessages = 0;
+    glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
+    ASSERT_EQ(0, numMessages);
+
+    std::vector<Message> messages;
+    glDebugMessageCallbackKHR(Callback, &messages);
+    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+
+    ASSERT_EQ(0u, messages.size());
+}
+
+// Test a basic flow of inserting a message and reading it back
+TEST_P(DebugTest, InsertMessage)
+{
+    if (!mDebugExtensionAvailable)
+    {
+        std::cout << "Test skipped because GL_KHR_debug is not available." << std::endl;
+        return;
+    }
+
+    const GLenum source       = GL_DEBUG_SOURCE_APPLICATION;
+    const GLenum type         = GL_DEBUG_TYPE_OTHER;
+    const GLuint id           = 1;
+    const GLenum severity     = GL_DEBUG_SEVERITY_NOTIFICATION;
+    const std::string message = "Message";
+
+    glDebugMessageInsertKHR(source, type, id, severity, -1, message.c_str());
+
+    GLint numMessages = 0;
+    glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
+    ASSERT_EQ(1, numMessages);
+
+    GLint messageLength = 0;
+    glGetIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &messageLength);
+    EXPECT_EQ(static_cast<GLint>(message.length()), messageLength);
+
+    GLenum sourceBuf   = 0;
+    GLenum typeBuf     = 0;
+    GLenum idBuf       = 0;
+    GLenum severityBuf = 0;
+    GLsizei lengthBuf = 0;
+    std::vector<char> messageBuf(messageLength + 1);
+    GLuint ret =
+        glGetDebugMessageLogKHR(1, static_cast<GLsizei>(messageBuf.size()), &sourceBuf, &typeBuf,
+                                &idBuf, &severityBuf, &lengthBuf, messageBuf.data());
+    EXPECT_EQ(1u, ret);
+    EXPECT_EQ(source, sourceBuf);
+    EXPECT_EQ(type, typeBuf);
+    EXPECT_EQ(id, idBuf);
+    EXPECT_EQ(severity, severityBuf);
+    EXPECT_EQ(lengthBuf, messageLength);
+    EXPECT_STREQ(message.c_str(), messageBuf.data());
+
+    glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
+    EXPECT_EQ(0, numMessages);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test inserting multiple messages
+TEST_P(DebugTest, InsertMessageMultiple)
+{
+    if (!mDebugExtensionAvailable)
+    {
+        std::cout << "Test skipped because GL_KHR_debug is not available." << std::endl;
+        return;
+    }
+
+    const GLenum source          = GL_DEBUG_SOURCE_APPLICATION;
+    const GLenum type            = GL_DEBUG_TYPE_OTHER;
+    const GLuint startID         = 1;
+    const GLenum severity        = GL_DEBUG_SEVERITY_NOTIFICATION;
+    const char messageRepeatChar = 'm';
+    const size_t messageCount    = 32;
+
+    for (size_t i = 0; i < messageCount; i++)
+    {
+        std::string message(i + 1, messageRepeatChar);
+        glDebugMessageInsertKHR(source, type, startID + static_cast<GLuint>(i), severity, -1,
+                                message.c_str());
+    }
+
+    GLint numMessages = 0;
+    glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
+    ASSERT_EQ(static_cast<GLint>(messageCount), numMessages);
+
+    for (size_t i = 0; i < messageCount; i++)
+    {
+        glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
+        EXPECT_EQ(static_cast<GLint>(messageCount - i), numMessages);
+
+        std::string expectedMessage(i + 1, messageRepeatChar);
+
+        GLint messageLength = 0;
+        glGetIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &messageLength);
+        EXPECT_EQ(static_cast<GLint>(expectedMessage.length()), messageLength);
+
+        GLenum sourceBuf   = 0;
+        GLenum typeBuf     = 0;
+        GLenum idBuf       = 0;
+        GLenum severityBuf = 0;
+        GLsizei lengthBuf = 0;
+        std::vector<char> messageBuf(messageLength + 1);
+        GLuint ret =
+            glGetDebugMessageLogKHR(1, static_cast<GLsizei>(messageBuf.size()), &sourceBuf,
+                                    &typeBuf, &idBuf, &severityBuf, &lengthBuf, messageBuf.data());
+        EXPECT_EQ(1u, ret);
+        EXPECT_EQ(source, sourceBuf);
+        EXPECT_EQ(type, typeBuf);
+        EXPECT_EQ(startID + i, idBuf);
+        EXPECT_EQ(severity, severityBuf);
+        EXPECT_EQ(lengthBuf, messageLength);
+        EXPECT_STREQ(expectedMessage.c_str(), messageBuf.data());
+    }
+
+    glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
+    EXPECT_EQ(0, numMessages);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test using a debug callback
+TEST_P(DebugTest, DebugCallback)
+{
+    if (!mDebugExtensionAvailable)
+    {
+        std::cout << "Test skipped because GL_KHR_debug is not available." << std::endl;
+        return;
+    }
+
+    std::vector<Message> messages;
+
+    glDebugMessageCallbackKHR(Callback, &messages);
+    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+
+    const GLenum source       = GL_DEBUG_SOURCE_APPLICATION;
+    const GLenum type         = GL_DEBUG_TYPE_OTHER;
+    const GLuint id           = 1;
+    const GLenum severity     = GL_DEBUG_SEVERITY_NOTIFICATION;
+    const std::string message = "Message";
+
+    glDebugMessageInsertKHR(source, type, id, severity, -1, message.c_str());
+
+    GLint numMessages = 0;
+    glGetIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
+    EXPECT_EQ(0, numMessages);
+
+    ASSERT_EQ(1u, messages.size());
+
+    const Message &m = messages.front();
+    EXPECT_EQ(source, m.source);
+    EXPECT_EQ(type, m.type);
+    EXPECT_EQ(id, m.id);
+    EXPECT_EQ(severity, m.severity);
+    EXPECT_EQ(message, m.message);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test the glGetPointervKHR entry point
+TEST_P(DebugTest, GetPointer)
+{
+    if (!mDebugExtensionAvailable)
+    {
+        std::cout << "Test skipped because GL_KHR_debug is not available." << std::endl;
+        return;
+    }
+
+    std::vector<Message> messages;
+
+    glDebugMessageCallbackKHR(Callback, &messages);
+
+    void *callback = nullptr;
+    glGetPointervKHR(GL_DEBUG_CALLBACK_FUNCTION, &callback);
+    EXPECT_EQ(reinterpret_cast<void *>(Callback), callback);
+
+    void *userData = nullptr;
+    glGetPointervKHR(GL_DEBUG_CALLBACK_USER_PARAM, &userData);
+    EXPECT_EQ(static_cast<void *>(&messages), userData);
+}
+
+// Test usage of message control.  Example taken from GL_KHR_debug spec.
+TEST_P(DebugTest, MessageControl1)
+{
+    if (!mDebugExtensionAvailable)
+    {
+        std::cout << "Test skipped because GL_KHR_debug is not available." << std::endl;
+        return;
+    }
+
+    std::vector<Message> messages;
+
+    glDebugMessageCallbackKHR(Callback, &messages);
+    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+
+    // Setup of the default active debug group: Filter everything in
+    glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
+
+    // Generate a debug marker debug output message
+    glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
+                            GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Message 1");
+
+    // Push debug group 1
+    glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Message 2");
+
+    // Setup of the debug group 1: Filter everything out
+    glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE);
+
+    // This message won't appear in the debug output log of
+    glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
+                            GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Message 3");
+
+    // Pop debug group 1, restore the volume control of the default debug group.
+    glPopDebugGroupKHR();
+
+    // Generate a debug marker debug output message
+    glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
+                            GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Message 5");
+
+    // Expected debug output from the GL implementation
+    // Message 1
+    // Message 2
+    // Message 2
+    // Message 5
+    EXPECT_EQ(4u, messages.size());
+    EXPECT_STREQ(messages[0].message.c_str(), "Message 1");
+    EXPECT_STREQ(messages[1].message.c_str(), "Message 2");
+    EXPECT_STREQ(messages[2].message.c_str(), "Message 2");
+    EXPECT_STREQ(messages[3].message.c_str(), "Message 5");
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test usage of message control.  Example taken from GL_KHR_debug spec.
+TEST_P(DebugTest, MessageControl2)
+{
+    if (!mDebugExtensionAvailable)
+    {
+        std::cout << "Test skipped because GL_KHR_debug is not available." << std::endl;
+        return;
+    }
+
+    std::vector<Message> messages;
+
+    glDebugMessageCallbackKHR(Callback, &messages);
+    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+
+    // Setup the control of de debug output for the default debug group
+    glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE);
+    glDebugMessageControlKHR(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr,
+                             GL_FALSE);
+    std::vector<GLuint> ids0 = {1234, 2345, 3456, 4567};
+    glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE,
+                             static_cast<GLuint>(ids0.size()), ids0.data(), GL_FALSE);
+    glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, GL_DONT_CARE,
+                             static_cast<GLuint>(ids0.size()), ids0.data(), GL_FALSE);
+
+    // Push debug group 1
+    // Inherit of the default debug group debug output volume control
+    // Filtered out by glDebugMessageControl
+    glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Message 1");
+
+    // In this section of the code, we are interested in performances.
+    glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, GL_DONT_CARE,
+                             0, nullptr, GL_TRUE);
+    // But we already identify that some messages are not really useful for us.
+    std::vector<GLuint> ids1 = {5678, 6789};
+    glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE,
+                             static_cast<GLuint>(ids1.size()), ids1.data(), GL_FALSE);
+
+    glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 1357,
+                            GL_DEBUG_SEVERITY_MEDIUM, -1, "Message 2");
+    glDebugMessageInsertKHR(GL_DEBUG_SOURCE_THIRD_PARTY,  // We still filter out these messages.
+                            GL_DEBUG_TYPE_OTHER, 3579, GL_DEBUG_SEVERITY_MEDIUM, -1, "Message 3");
+
+    glPopDebugGroupKHR();
+
+    // Expected debug output from the GL implementation
+    // Message 2
+    EXPECT_EQ(1u, messages.size());
+    EXPECT_STREQ(messages[0].message.c_str(), "Message 2");
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test basic usage of setting and getting labels
+TEST_P(DebugTest, ObjectLabels)
+{
+    if (!mDebugExtensionAvailable)
+    {
+        std::cout << "Test skipped because GL_KHR_debug is not available." << std::endl;
+        return;
+    }
+
+    GLuint renderbuffer = 0;
+    glGenRenderbuffers(1, &renderbuffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+
+    const std::string &label = "renderbuffer";
+    glObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, -1, label.c_str());
+
+    std::vector<char> labelBuf(label.length() + 1);
+    GLsizei labelLengthBuf = 0;
+    glGetObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, static_cast<GLsizei>(labelBuf.size()),
+                        &labelLengthBuf, labelBuf.data());
+
+    EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
+    EXPECT_STREQ(label.c_str(), labelBuf.data());
+
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteRenderbuffers(1, &renderbuffer);
+
+    glObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, -1, label.c_str());
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glGetObjectLabelKHR(GL_RENDERBUFFER, renderbuffer, static_cast<GLsizei>(labelBuf.size()),
+                        &labelLengthBuf, labelBuf.data());
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+// Test basic usage of setting and getting labels
+TEST_P(DebugTest, ObjectPtrLabels)
+{
+    if (!mDebugExtensionAvailable || getClientMajorVersion() < 3)
+    {
+        std::cout << "Test skipped because GL_KHR_debug or ES3 is not available." << std::endl;
+        return;
+    }
+
+    GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+    const std::string &label = "sync";
+    glObjectPtrLabelKHR(sync, -1, label.c_str());
+
+    std::vector<char> labelBuf(label.length() + 1);
+    GLsizei labelLengthBuf = 0;
+    glGetObjectPtrLabelKHR(sync, static_cast<GLsizei>(labelBuf.size()), &labelLengthBuf,
+                           labelBuf.data());
+
+    EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
+    EXPECT_STREQ(label.c_str(), labelBuf.data());
+
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteSync(sync);
+
+    glObjectPtrLabelKHR(sync, -1, label.c_str());
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glGetObjectPtrLabelKHR(sync, static_cast<GLsizei>(labelBuf.size()), &labelLengthBuf,
+                           labelBuf.data());
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(DebugTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL());
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/gl_tests/DepthStencilFormatsTest.cpp b/src/third_party/angle/src/tests/gl_tests/DepthStencilFormatsTest.cpp
new file mode 100644
index 0000000..2764f56
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DepthStencilFormatsTest.cpp
@@ -0,0 +1,332 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include "common/mathutil.h"
+#include "platform/WorkaroundsD3D.h"
+
+using namespace angle;
+
+class DepthStencilFormatsTestBase : public ANGLETest
+{
+  protected:
+    DepthStencilFormatsTestBase()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    bool checkTexImageFormatSupport(GLenum format, GLenum type)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        GLuint tex = 0;
+        glGenTextures(1, &tex);
+        glBindTexture(GL_TEXTURE_2D, tex);
+        glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, type, nullptr);
+        glDeleteTextures(1, &tex);
+
+        return (glGetError() == GL_NO_ERROR);
+    }
+
+    bool checkTexStorageFormatSupport(GLenum internalFormat)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        GLuint tex = 0;
+        glGenTextures(1, &tex);
+        glBindTexture(GL_TEXTURE_2D, tex);
+        glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
+        glDeleteTextures(1, &tex);
+
+        return (glGetError() == GL_NO_ERROR);
+    }
+
+    bool checkRenderbufferFormatSupport(GLenum internalFormat)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        GLuint rb = 0;
+        glGenRenderbuffers(1, &rb);
+        glBindRenderbuffer(GL_RENDERBUFFER, rb);
+        glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, 1, 1);
+        glDeleteRenderbuffers(1, &rb);
+
+        return (glGetError() == GL_NO_ERROR);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = position;
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
+        EXPECT_NE(-1, mTextureUniformLocation);
+
+        glGenTextures(1, &mTexture);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mProgram);
+        glDeleteTextures(1, &mTexture);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+    GLuint mTexture;
+    GLint mTextureUniformLocation;
+};
+
+class DepthStencilFormatsTest : public DepthStencilFormatsTestBase
+{};
+
+class DepthStencilFormatsTestES3 : public DepthStencilFormatsTestBase
+{};
+
+TEST_P(DepthStencilFormatsTest, DepthTexture)
+{
+    bool shouldHaveTextureSupport = extensionEnabled("GL_ANGLE_depth_texture");
+    EXPECT_EQ(shouldHaveTextureSupport, checkTexImageFormatSupport(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT));
+    EXPECT_EQ(shouldHaveTextureSupport, checkTexImageFormatSupport(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT));
+
+    if (extensionEnabled("GL_EXT_texture_storage"))
+    {
+        EXPECT_EQ(shouldHaveTextureSupport, checkTexStorageFormatSupport(GL_DEPTH_COMPONENT16));
+        EXPECT_EQ(shouldHaveTextureSupport, checkTexStorageFormatSupport(GL_DEPTH_COMPONENT32_OES));
+    }
+}
+
+TEST_P(DepthStencilFormatsTest, PackedDepthStencil)
+{
+    // Expected to fail in D3D9 if GL_OES_packed_depth_stencil is not present.
+    // Expected to fail in D3D11 if GL_OES_packed_depth_stencil or GL_ANGLE_depth_texture is not present.
+
+    bool shouldHaveRenderbufferSupport = extensionEnabled("GL_OES_packed_depth_stencil");
+    EXPECT_EQ(shouldHaveRenderbufferSupport, checkRenderbufferFormatSupport(GL_DEPTH24_STENCIL8_OES));
+
+    bool shouldHaveTextureSupport = extensionEnabled("GL_OES_packed_depth_stencil") &&
+                                    extensionEnabled("GL_ANGLE_depth_texture");
+    EXPECT_EQ(shouldHaveTextureSupport, checkTexImageFormatSupport(GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES));
+
+    if (extensionEnabled("GL_EXT_texture_storage"))
+    {
+        EXPECT_EQ(shouldHaveTextureSupport, checkTexStorageFormatSupport(GL_DEPTH24_STENCIL8_OES));
+    }
+}
+
+TEST_P(DepthStencilFormatsTestES3, DrawWithDepthStencil)
+{
+    GLushort data[16];
+    for (unsigned int i = 0; i < 16; i++)
+    {
+        data[i] = std::numeric_limits<GLushort>::max();
+    }
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, 4, 4);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, data);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glUseProgram(mProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    drawQuad(mProgram, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+
+    GLubyte pixel[4];
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
+
+    // Only require the red and alpha channels have the correct values, the depth texture extensions
+    // leave the green and blue channels undefined
+    ASSERT_NEAR(255, pixel[0], 2.0);
+    ASSERT_EQ(255, pixel[3]);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(DepthStencilFormatsTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(DepthStencilFormatsTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+class TinyDepthStencilWorkaroundTest : public ANGLETest
+{
+  public:
+    TinyDepthStencilWorkaroundTest()
+    {
+        setWindowWidth(512);
+        setWindowHeight(512);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    // Override the workarounds to enable "tiny" depth/stencil textures.
+    void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) override
+    {
+        workarounds->emulateTinyStencilTextures = true;
+    }
+};
+
+// Tests that the tiny depth stencil textures workaround does not "stick" depth textures.
+// http://anglebug.com/1664
+TEST_P(TinyDepthStencilWorkaroundTest, DepthTexturesStick)
+{
+    const std::string &drawVS =
+        "#version 100\n"
+        "attribute vec3 vertex;\n"
+        "void main () {\n"
+        "  gl_Position = vec4(vertex.x, vertex.y, vertex.z * 2.0 - 1.0, 1);\n"
+        "}\n";
+
+    const std::string &drawFS =
+        "#version 100\n"
+        "void main () {\n"
+        "  gl_FragColor = vec4 (1.);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(drawProgram, drawVS, drawFS);
+
+    const std::string &blitVS =
+        "#version 100\n"
+        "attribute vec2 vertex;\n"
+        "varying vec2 position;\n"
+        "void main () {\n"
+        "  position = vertex * .5 + .5;\n"
+        "  gl_Position = vec4(vertex, 0, 1);\n"
+        "}\n";
+
+    const std::string &blitFS =
+        "#version 100\n"
+        "precision mediump float;\n"
+        "uniform sampler2D texture;\n"
+        "varying vec2 position;\n"
+        "void main () {\n"
+        "  gl_FragColor = vec4 (texture2D (texture, position).rrr, 1.);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(blitProgram, blitVS, blitFS);
+
+    GLint blitTextureLocation = glGetUniformLocation(blitProgram.get(), "texture");
+    ASSERT_NE(-1, blitTextureLocation);
+
+    GLTexture colorTex;
+    glBindTexture(GL_TEXTURE_2D, colorTex.get());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, nullptr);
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    GLTexture depthTex;
+    glBindTexture(GL_TEXTURE_2D, depthTex.get());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+    ASSERT_EQ(getWindowWidth(), getWindowHeight());
+    int levels = gl::log2(getWindowWidth());
+    for (int mipLevel = 0; mipLevel <= levels; ++mipLevel)
+    {
+        int size = getWindowWidth() >> mipLevel;
+        glTexImage2D(GL_TEXTURE_2D, mipLevel, GL_DEPTH_STENCIL, size, size, 0, GL_DEPTH_STENCIL,
+                     GL_UNSIGNED_INT_24_8_OES, nullptr);
+    }
+
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    ASSERT_GL_NO_ERROR();
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex.get(), 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex.get(), 0);
+
+    ASSERT_GL_NO_ERROR();
+
+    glDepthRangef(0.0f, 1.0f);
+    glViewport(0, 0, getWindowWidth(), getWindowHeight());
+    glClearColor(0, 0, 0, 1);
+
+    // Draw loop.
+    for (unsigned int frame = 0; frame < 3; ++frame)
+    {
+        // draw into FBO
+        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+        glEnable(GL_DEPTH_TEST);
+
+        float depth = ((frame % 2 == 0) ? 0.0f : 1.0f);
+        drawQuad(drawProgram.get(), "vertex", depth);
+
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+        // blit FBO
+        glDisable(GL_DEPTH_TEST);
+
+        glUseProgram(blitProgram.get());
+        glUniform1i(blitTextureLocation, 0);
+        glBindTexture(GL_TEXTURE_2D, depthTex.get());
+
+        drawQuad(blitProgram.get(), "vertex", 0.5f);
+
+        Vector4 depthVec(depth, depth, depth, 1);
+        GLColor depthColor(depthVec);
+
+        EXPECT_PIXEL_COLOR_NEAR(0, 0, depthColor, 1);
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+ANGLE_INSTANTIATE_TEST(TinyDepthStencilWorkaroundTest, ES3_D3D11());
diff --git a/src/third_party/angle/src/tests/gl_tests/DifferentStencilMasksTest.cpp b/src/third_party/angle/src/tests/gl_tests/DifferentStencilMasksTest.cpp
new file mode 100644
index 0000000..7e1cd8a
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DifferentStencilMasksTest.cpp
@@ -0,0 +1,178 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DifferentStencilMasksTest:
+//   Tests the equality between stencilWriteMask and stencilBackWriteMask.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+class DifferentStencilMasksTest : public ANGLETest
+{
+  protected:
+    DifferentStencilMasksTest() : mProgram(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+
+            void main()
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+
+            void main()
+            {
+                gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+
+        glEnable(GL_STENCIL_TEST);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDisable(GL_STENCIL_TEST);
+        if (mProgram != 0)
+            glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+};
+
+// Tests that effectively same front and back masks are legal.
+TEST_P(DifferentStencilMasksTest, DrawWithSameEffectiveMask)
+{
+    // 0x00ff and 0x01ff are effectively 0x00ff by being masked by the current stencil bits, 8.
+    glStencilMaskSeparate(GL_FRONT, 0x00ff);
+    glStencilMaskSeparate(GL_BACK, 0x01ff);
+
+    glUseProgram(mProgram);
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Tests that effectively different front and back masks are illegal.
+TEST_P(DifferentStencilMasksTest, DrawWithDifferentMask)
+{
+    glStencilMaskSeparate(GL_FRONT, 0x0001);
+    glStencilMaskSeparate(GL_BACK, 0x0002);
+
+    glUseProgram(mProgram);
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+class DifferentStencilMasksWithoutStencilBufferTest : public ANGLETest
+{
+  protected:
+    DifferentStencilMasksWithoutStencilBufferTest() : mProgram(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(0);
+        setConfigStencilBits(0);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+
+            void main()
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+
+            void main()
+            {
+                gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+
+        glEnable(GL_STENCIL_TEST);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDisable(GL_STENCIL_TEST);
+        if (mProgram != 0)
+            glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+};
+
+// Tests that effectively different front and back masks, without stencil bits, are legal.
+TEST_P(DifferentStencilMasksWithoutStencilBufferTest, DrawWithDifferentMask)
+{
+    glStencilMaskSeparate(GL_FRONT, 0x0001);
+    glStencilMaskSeparate(GL_BACK, 0x0002);
+
+    glUseProgram(mProgram);
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(DifferentStencilMasksTest, ES2_D3D9(), ES2_D3D11(), ES3_D3D11(), ES2_OPENGL(), ES3_OPENGL());
+ANGLE_INSTANTIATE_TEST(DifferentStencilMasksWithoutStencilBufferTest, ES2_D3D9(), ES2_D3D11(), ES3_D3D11(), ES2_OPENGL(), ES3_OPENGL());
+} // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/DiscardFramebufferEXTTest.cpp b/src/third_party/angle/src/tests/gl_tests/DiscardFramebufferEXTTest.cpp
new file mode 100644
index 0000000..0e91b0d
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DiscardFramebufferEXTTest.cpp
@@ -0,0 +1,129 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class DiscardFramebufferEXTTest : public ANGLETest
+{
+protected:
+    DiscardFramebufferEXTTest()
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+};
+
+TEST_P(DiscardFramebufferEXTTest, DefaultFramebuffer)
+{
+    if (!extensionEnabled("EXT_discard_framebuffer"))
+    {
+        std::cout << "Test skipped because EXT_discard_framebuffer is not available." << std::endl;
+        return;
+    }
+
+    // These should succeed on the default framebuffer
+    const GLenum discards1[] = { GL_COLOR_EXT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards1);
+    EXPECT_GL_NO_ERROR();
+
+    const GLenum discards2[] = { GL_DEPTH_EXT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards2);
+    EXPECT_GL_NO_ERROR();
+
+    const GLenum discards3[] = { GL_STENCIL_EXT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards3);
+    EXPECT_GL_NO_ERROR();
+
+    const GLenum discards4[] = { GL_STENCIL_EXT, GL_COLOR_EXT, GL_DEPTH_EXT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 3, discards4);
+    EXPECT_GL_NO_ERROR();
+
+    // These should fail on the default framebuffer
+    const GLenum discards5[] = { GL_COLOR_ATTACHMENT0 };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards5);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    const GLenum discards6[] = { GL_DEPTH_ATTACHMENT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards6);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    const GLenum discards7[] = { GL_STENCIL_ATTACHMENT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards7);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+TEST_P(DiscardFramebufferEXTTest, NonDefaultFramebuffer)
+{
+    if (!extensionEnabled("EXT_discard_framebuffer"))
+    {
+        std::cout << "Test skipped because EXT_discard_framebuffer is not available." << std::endl;
+        return;
+    }
+
+    GLuint tex2D;
+    GLuint framebuffer;
+
+    // Create a basic off-screen framebuffer
+    // Don't create a depth/stencil texture, to ensure that also works correctly
+    glGenTextures(1, &tex2D);
+    glGenFramebuffers(1, &framebuffer);
+    glBindTexture(GL_TEXTURE_2D, tex2D);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB,
+                 GL_UNSIGNED_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // These should fail on the non-default framebuffer
+    const GLenum discards1[] = { GL_COLOR_EXT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards1);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    const GLenum discards2[] = { GL_DEPTH_EXT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards2);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    const GLenum discards3[] = { GL_STENCIL_EXT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards3);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    const GLenum discards4[] = { GL_STENCIL_EXT, GL_COLOR_EXT, GL_DEPTH_EXT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 3, discards4);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // These should succeed on the non-default framebuffer
+    const GLenum discards5[] = { GL_COLOR_ATTACHMENT0 };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards5);
+    EXPECT_GL_NO_ERROR();
+
+    const GLenum discards6[] = { GL_DEPTH_ATTACHMENT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards6);
+    EXPECT_GL_NO_ERROR();
+
+    const GLenum discards7[] = { GL_STENCIL_ATTACHMENT };
+    glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards7);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(DiscardFramebufferEXTTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/DrawBuffersTest.cpp b/src/third_party/angle/src/tests/gl_tests/DrawBuffersTest.cpp
new file mode 100644
index 0000000..a34911f
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DrawBuffersTest.cpp
@@ -0,0 +1,535 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+class DrawBuffersTest : public ANGLETest
+{
+  protected:
+    DrawBuffersTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        mMaxDrawBuffers = 0;
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        // This test seems to fail on an nVidia machine when the window is hidden
+        SetWindowVisible(true);
+
+        glGenFramebuffers(1, &mFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+
+        glGenTextures(4, mTextures);
+
+        for (size_t texIndex = 0; texIndex < ArraySize(mTextures); texIndex++)
+        {
+            glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+                         GL_UNSIGNED_BYTE, nullptr);
+        }
+
+        GLfloat data[] =
+        {
+            -1.0f, 1.0f,
+            -1.0f, -2.0f,
+            2.0f, 1.0f
+        };
+
+        glGenBuffers(1, &mBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6, data, GL_STATIC_DRAW);
+
+        if (checkSupport())
+        {
+            glGetIntegerv(GL_MAX_DRAW_BUFFERS, &mMaxDrawBuffers);
+        }
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteFramebuffers(1, &mFBO);
+        glDeleteTextures(4, mTextures);
+        glDeleteBuffers(1, &mBuffer);
+
+        ANGLETest::TearDown();
+    }
+
+    // We must call a different DrawBuffers method depending on extension support. Use this
+    // method instead of calling on directly.
+    void setDrawBuffers(GLsizei n, const GLenum *drawBufs)
+    {
+        if (extensionEnabled("GL_EXT_draw_buffers"))
+        {
+            glDrawBuffersEXT(n, drawBufs);
+        }
+        else
+        {
+            ASSERT_GE(getClientMajorVersion(), 3);
+            glDrawBuffers(n, drawBufs);
+        }
+    }
+
+    // Use this method to filter if we can support these tests.
+    bool checkSupport()
+    {
+        return (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_draw_buffers"));
+    }
+
+    void setupMRTProgramESSL3(bool bufferEnabled[8], GLuint *programOut)
+    {
+        const std::string vertexShaderSource =
+            "#version 300 es\n"
+            "in vec4 position;\n"
+            "void main() {\n"
+            "    gl_Position = position;\n"
+            "}\n";
+
+        std::stringstream strstr;
+
+        strstr << "#version 300 es\n"
+                  "precision highp float;\n";
+
+        for (unsigned int index = 0; index < 8; index++)
+        {
+            if (bufferEnabled[index])
+            {
+                strstr << "layout(location = " << index << ") "
+                          "out vec4 value" << index << ";\n";
+            }
+        }
+
+        strstr << "void main()\n"
+                  "{\n";
+
+        for (unsigned int index = 0; index < 8; index++)
+        {
+            if (bufferEnabled[index])
+            {
+                unsigned int r = (index + 1) & 1;
+                unsigned int g = (index + 1) & 2;
+                unsigned int b = (index + 1) & 4;
+
+                strstr << "    value" << index << " = vec4("
+                       << r << ".0, " << g << ".0, "
+                       << b << ".0, 1.0);\n";
+            }
+        }
+
+        strstr << "}\n";
+
+        *programOut = CompileProgram(vertexShaderSource, strstr.str());
+        if (*programOut == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        glUseProgram(*programOut);
+
+        GLint location = glGetAttribLocation(*programOut, "position");
+        ASSERT_NE(location, -1);
+        glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+        glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 8, nullptr);
+        glEnableVertexAttribArray(location);
+    }
+
+    void setupMRTProgramESSL1(bool bufferEnabled[8], GLuint *programOut)
+    {
+        const std::string vertexShaderSource =
+            "attribute vec4 position;\n"
+            "void main() {\n"
+            "    gl_Position = position;\n"
+            "}\n";
+
+        std::stringstream strstr;
+
+        strstr << "#extension GL_EXT_draw_buffers : enable\n"
+                  "precision highp float;\n"
+                  "void main()\n"
+                  "{\n";
+
+        for (unsigned int index = 0; index < 8; index++)
+        {
+            if (bufferEnabled[index])
+            {
+                unsigned int r = (index + 1) & 1;
+                unsigned int g = (index + 1) & 2;
+                unsigned int b = (index + 1) & 4;
+
+                strstr << "    gl_FragData[" << index << "] = vec4("
+                    << r << ".0, " << g << ".0, "
+                    << b << ".0, 1.0);\n";
+            }
+        }
+
+        strstr << "}\n";
+
+        *programOut = CompileProgram(vertexShaderSource, strstr.str());
+        if (*programOut == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        glUseProgram(*programOut);
+
+        GLint location = glGetAttribLocation(*programOut, "position");
+        ASSERT_NE(location, -1);
+        glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+        glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 8, nullptr);
+        glEnableVertexAttribArray(location);
+    }
+
+    void setupMRTProgram(bool bufferEnabled[8], GLuint *programOut)
+    {
+        if (getClientMajorVersion() == 3)
+        {
+            setupMRTProgramESSL3(bufferEnabled, programOut);
+        }
+        else
+        {
+            ASSERT_EQ(getClientMajorVersion(), 2);
+            setupMRTProgramESSL1(bufferEnabled, programOut);
+        }
+    }
+
+    static GLColor getColorForIndex(unsigned int index)
+    {
+        GLubyte r = (((index + 1) & 1) > 0) ? 255 : 0;
+        GLubyte g = (((index + 1) & 2) > 0) ? 255 : 0;
+        GLubyte b = (((index + 1) & 4) > 0) ? 255 : 0;
+        return GLColor(r, g, b, 255u);
+    }
+
+    void verifyAttachment2D(unsigned int index, GLuint textureName, GLenum target, GLint level)
+    {
+        for (GLint colorAttachment = 0; colorAttachment < mMaxDrawBuffers; colorAttachment++)
+        {
+            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttachment, GL_TEXTURE_2D, 0, 0);
+        }
+
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, textureName, level);
+
+        EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, getColorForIndex(index));
+    }
+
+    void verifyAttachmentLayer(unsigned int index, GLuint texture, GLint level, GLint layer)
+    {
+        for (GLint colorAttachment = 0; colorAttachment < mMaxDrawBuffers; colorAttachment++)
+        {
+            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttachment,
+                                   GL_TEXTURE_2D, 0, 0);
+        }
+
+        glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, level, layer);
+
+        EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, getColorForIndex(index));
+    }
+
+    GLuint mFBO;
+    GLuint mTextures[4];
+    GLuint mBuffer;
+    GLint mMaxDrawBuffers;
+};
+
+// Verify that GL_MAX_DRAW_BUFFERS returns the expected values for D3D11
+TEST_P(DrawBuffersTest, VerifyD3DLimits)
+{
+    EGLPlatformParameters platform = GetParam().eglParameters;
+    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        if (platform.majorVersion == 9 && platform.minorVersion == 3)
+        {
+            // D3D11 Feature Level 9_3 supports 4 draw buffers
+            ASSERT_EQ(mMaxDrawBuffers, 4);
+        }
+        else
+        {
+            // D3D11 Feature Level 10_0+ supports 8 draw buffers
+            ASSERT_EQ(mMaxDrawBuffers, 8);
+        }
+    }
+    else
+    {
+        std::cout << "Test skipped for non-D3D11 renderers." << std::endl;
+        return;
+    }
+}
+
+TEST_P(DrawBuffersTest, Gaps)
+{
+    if (!checkSupport())
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_draw_buffers is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (IsWindows() && IsAMD() && IsDesktopOpenGL())
+    {
+        // TODO(ynovikov): Investigate the failure (http://anglebug.com/1535)
+        std::cout << "Test disabled on Windows AMD OpenGL." << std::endl;
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[0], 0);
+
+    bool flags[8] = { false, true };
+
+    GLuint program;
+    setupMRTProgram(flags, &program);
+
+    const GLenum bufs[] =
+    {
+        GL_NONE,
+        GL_COLOR_ATTACHMENT1
+    };
+    glUseProgram(program);
+    setDrawBuffers(2, bufs);
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    verifyAttachment2D(1, mTextures[0], GL_TEXTURE_2D, 0);
+
+    glDeleteProgram(program);
+}
+
+TEST_P(DrawBuffersTest, FirstAndLast)
+{
+    if (!checkSupport())
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_draw_buffers is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (IsWindows() && IsAMD() && IsDesktopOpenGL())
+    {
+        // TODO(ynovikov): Investigate the failure (https://anglebug.com/1533)
+        std::cout << "Test disabled on Windows AMD OpenGL." << std::endl;
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTextures[1], 0);
+
+    bool flags[8] = { true, false, false, true };
+
+    GLuint program;
+    setupMRTProgram(flags, &program);
+
+    const GLenum bufs[] =
+    {
+        GL_COLOR_ATTACHMENT0,
+        GL_NONE,
+        GL_NONE,
+        GL_COLOR_ATTACHMENT3
+    };
+
+    glUseProgram(program);
+    setDrawBuffers(4, bufs);
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    verifyAttachment2D(0, mTextures[0], GL_TEXTURE_2D, 0);
+    verifyAttachment2D(3, mTextures[1], GL_TEXTURE_2D, 0);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteProgram(program);
+}
+
+TEST_P(DrawBuffersTest, FirstHalfNULL)
+{
+    if (!checkSupport())
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_draw_buffers is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (IsWindows() && IsAMD() && IsDesktopOpenGL())
+    {
+        // TODO(ynovikov): Investigate the failure (https://anglebug.com/1533)
+        std::cout << "Test disabled on Windows AMD OpenGL." << std::endl;
+        return;
+    }
+
+    bool flags[8] = { false };
+    GLenum bufs[8] = { GL_NONE };
+
+    GLuint halfMaxDrawBuffers = static_cast<GLuint>(mMaxDrawBuffers) / 2;
+
+    for (GLuint texIndex = 0; texIndex < halfMaxDrawBuffers; texIndex++)
+    {
+        glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + halfMaxDrawBuffers + texIndex, GL_TEXTURE_2D, mTextures[texIndex], 0);
+        flags[texIndex + halfMaxDrawBuffers] = true;
+        bufs[texIndex + halfMaxDrawBuffers] = GL_COLOR_ATTACHMENT0 + halfMaxDrawBuffers + texIndex;
+    }
+
+    GLuint program;
+    setupMRTProgram(flags, &program);
+
+    glUseProgram(program);
+    setDrawBuffers(mMaxDrawBuffers, bufs);
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    for (GLuint texIndex = 0; texIndex < halfMaxDrawBuffers; texIndex++)
+    {
+        verifyAttachment2D(texIndex + halfMaxDrawBuffers, mTextures[texIndex], GL_TEXTURE_2D, 0);
+    }
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteProgram(program);
+}
+
+TEST_P(DrawBuffersTest, UnwrittenOutputVariablesShouldNotCrash)
+{
+    if (!checkSupport())
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_draw_buffers is not available."
+                  << std::endl;
+        return;
+    }
+
+    // Bind two render targets but use a shader which writes only to the first one.
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
+
+    bool flags[8] = { true, false };
+
+    GLuint program;
+    setupMRTProgram(flags, &program);
+
+    const GLenum bufs[] =
+    {
+        GL_COLOR_ATTACHMENT0,
+        GL_COLOR_ATTACHMENT1,
+        GL_NONE,
+        GL_NONE,
+    };
+
+    glUseProgram(program);
+    setDrawBuffers(4, bufs);
+
+    // This call should not crash when we dynamically generate the HLSL code.
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    verifyAttachment2D(0, mTextures[0], GL_TEXTURE_2D, 0);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteProgram(program);
+}
+
+class DrawBuffersTestES3 : public DrawBuffersTest
+{
+};
+
+// Test that binding multiple layers of a 3D texture works correctly
+TEST_P(DrawBuffersTestES3, 3DTextures)
+{
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_3D, texture.get());
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), getWindowWidth(),
+                 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture.get(), 0, 1);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, texture.get(), 0, 2);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, texture.get(), 0, 3);
+
+    bool flags[8] = {true, true, true, true, false};
+
+    GLuint program;
+    setupMRTProgram(flags, &program);
+
+    const GLenum bufs[] = {
+        GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
+    };
+
+    glUseProgram(program);
+    glDrawBuffers(4, bufs);
+
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    verifyAttachmentLayer(0, texture.get(), 0, 0);
+    verifyAttachmentLayer(1, texture.get(), 0, 1);
+    verifyAttachmentLayer(2, texture.get(), 0, 2);
+    verifyAttachmentLayer(3, texture.get(), 0, 3);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteProgram(program);
+}
+
+// Test that binding multiple layers of a 2D array texture works correctly
+TEST_P(DrawBuffersTestES3, 2DArrayTextures)
+{
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D_ARRAY, texture.get());
+    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, getWindowWidth(), getWindowHeight(),
+                 getWindowWidth(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture.get(), 0, 1);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, texture.get(), 0, 2);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, texture.get(), 0, 3);
+
+    bool flags[8] = {true, true, true, true, false};
+
+    GLuint program;
+    setupMRTProgram(flags, &program);
+
+    const GLenum bufs[] = {
+        GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
+    };
+
+    glUseProgram(program);
+    glDrawBuffers(4, bufs);
+
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    verifyAttachmentLayer(0, texture.get(), 0, 0);
+    verifyAttachmentLayer(1, texture.get(), 0, 1);
+    verifyAttachmentLayer(2, texture.get(), 0, 2);
+    verifyAttachmentLayer(3, texture.get(), 0, 3);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteProgram(program);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(DrawBuffersTest,
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(DrawBuffersTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/DrawElementsTest.cpp b/src/third_party/angle/src/tests/gl_tests/DrawElementsTest.cpp
new file mode 100644
index 0000000..9a65eb2
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/DrawElementsTest.cpp
@@ -0,0 +1,268 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DrawElementsTest:
+//   Tests for indexed draws.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+class DrawElementsTest : public ANGLETest
+{
+  protected:
+    DrawElementsTest() : mProgram(0u)
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+    }
+
+    ~DrawElementsTest()
+    {
+        for (GLuint indexBuffer : mIndexBuffers)
+        {
+            if (indexBuffer != 0)
+            {
+                glDeleteBuffers(1, &indexBuffer);
+            }
+        }
+
+        for (GLuint vertexArray : mVertexArrays)
+        {
+            if (vertexArray != 0)
+            {
+                glDeleteVertexArrays(1, &vertexArray);
+            }
+        }
+
+        for (GLuint vertexBuffer : mVertexBuffers)
+        {
+            if (vertexBuffer != 0)
+            {
+                glDeleteBuffers(1, &vertexBuffer);
+            }
+        }
+
+        if (mProgram != 0u)
+        {
+            glDeleteProgram(mProgram);
+        }
+    }
+
+    std::vector<GLuint> mIndexBuffers;
+    std::vector<GLuint> mVertexArrays;
+    std::vector<GLuint> mVertexBuffers;
+    GLuint mProgram;
+};
+
+// Test no error is generated when using client-side arrays, indices = nullptr and count = 0
+TEST_P(DrawElementsTest, ClientSideNullptrArrayZeroCount)
+{
+    const std::string &vert =
+        "attribute vec3 a_pos;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_pos, 1.0);\n"
+        "}\n";
+
+    const std::string &frag =
+        "precision highp float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vert, frag);
+
+    GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
+    ASSERT_NE(-1, posLocation);
+    glUseProgram(program.get());
+
+    const auto &vertices = GetQuadVertices();
+
+    GLBuffer vertexBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
+                 GL_STATIC_DRAW);
+
+    glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(posLocation);
+    ASSERT_GL_NO_ERROR();
+
+    glDrawElements(GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_BYTE, nullptr);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test a state desync that can occur when using a streaming index buffer in GL in concert with
+// deleting the applied index buffer.
+TEST_P(DrawElementsTest, DeletingAfterStreamingIndexes)
+{
+    // Init program
+    const std::string &vertexShader =
+        "attribute vec2 position;\n"
+        "attribute vec2 testFlag;\n"
+        "varying vec2 v_data;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(position, 0, 1);\n"
+        "  v_data = testFlag;\n"
+        "}";
+
+    const std::string &fragmentShader =
+        "varying highp vec2 v_data;\n"
+        "void main() {\n"
+        "  gl_FragColor = vec4(v_data, 0, 1);\n"
+        "}";
+
+    mProgram = CompileProgram(vertexShader, fragmentShader);
+    ASSERT_NE(0u, mProgram);
+    glUseProgram(mProgram);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    ASSERT_NE(-1, positionLocation);
+
+    GLint testFlagLocation = glGetAttribLocation(mProgram, "testFlag");
+    ASSERT_NE(-1, testFlagLocation);
+
+    mIndexBuffers.resize(3u);
+    glGenBuffers(3, &mIndexBuffers[0]);
+
+    mVertexArrays.resize(2);
+    glGenVertexArrays(2, &mVertexArrays[0]);
+
+    mVertexBuffers.resize(2);
+    glGenBuffers(2, &mVertexBuffers[0]);
+
+    std::vector<GLuint> indexData[2];
+    indexData[0].push_back(0);
+    indexData[0].push_back(1);
+    indexData[0].push_back(2);
+    indexData[0].push_back(2);
+    indexData[0].push_back(3);
+    indexData[0].push_back(0);
+
+    indexData[1] = indexData[0];
+    for (GLuint &item : indexData[1])
+    {
+        item += 4u;
+    }
+
+    std::vector<GLfloat> positionData;
+    // quad verts
+    positionData.push_back(-1.0f);
+    positionData.push_back(1.0f);
+    positionData.push_back(-1.0f);
+    positionData.push_back(-1.0f);
+    positionData.push_back(1.0f);
+    positionData.push_back(-1.0f);
+    positionData.push_back(1.0f);
+    positionData.push_back(1.0f);
+
+    // Repeat position data
+    positionData.push_back(-1.0f);
+    positionData.push_back(1.0f);
+    positionData.push_back(-1.0f);
+    positionData.push_back(-1.0f);
+    positionData.push_back(1.0f);
+    positionData.push_back(-1.0f);
+    positionData.push_back(1.0f);
+    positionData.push_back(1.0f);
+
+    std::vector<GLfloat> testFlagData;
+    // red
+    testFlagData.push_back(1.0f);
+    testFlagData.push_back(0.0f);
+    testFlagData.push_back(1.0f);
+    testFlagData.push_back(0.0f);
+    testFlagData.push_back(1.0f);
+    testFlagData.push_back(0.0f);
+    testFlagData.push_back(1.0f);
+    testFlagData.push_back(0.0f);
+
+    // green
+    testFlagData.push_back(0.0f);
+    testFlagData.push_back(1.0f);
+    testFlagData.push_back(0.0f);
+    testFlagData.push_back(1.0f);
+    testFlagData.push_back(0.0f);
+    testFlagData.push_back(1.0f);
+    testFlagData.push_back(0.0f);
+    testFlagData.push_back(1.0f);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[0]);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indexData[0].size(), &indexData[0][0],
+                 GL_STATIC_DRAW);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[2]);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indexData[0].size(), &indexData[0][0],
+                 GL_STATIC_DRAW);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[1]);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indexData[1].size(), &indexData[1][0],
+                 GL_STATIC_DRAW);
+
+    // Initialize first vertex array with second index buffer
+    glBindVertexArray(mVertexArrays[0]);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[1]);
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[0]);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * positionData.size(), &positionData[0],
+                 GL_STATIC_DRAW);
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[1]);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * testFlagData.size(), &testFlagData[0],
+                 GL_STATIC_DRAW);
+    glVertexAttribPointer(testFlagLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);
+    glEnableVertexAttribArray(testFlagLocation);
+
+    // Initialize second vertex array with first index buffer
+    glBindVertexArray(mVertexArrays[1]);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[0]);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[0]);
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[1]);
+    glVertexAttribPointer(testFlagLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);
+    glEnableVertexAttribArray(testFlagLocation);
+
+    ASSERT_GL_NO_ERROR();
+
+    glBindVertexArray(mVertexArrays[0]);
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    glBindVertexArray(mVertexArrays[1]);
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    glBindVertexArray(mVertexArrays[0]);
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    // Trigger the bug here.
+    glDeleteBuffers(1, &mIndexBuffers[2]);
+
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+ANGLE_INSTANTIATE_TEST(DrawElementsTest, ES3_OPENGL(), ES3_OPENGLES());
+}
diff --git a/src/third_party/angle/src/tests/gl_tests/ETCTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/ETCTextureTest.cpp
new file mode 100644
index 0000000..1d2c55c
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ETCTextureTest.cpp
@@ -0,0 +1,270 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ETCTextureTest:
+//   Tests for ETC lossy decode formats.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class ETCTextureTest : public ANGLETest
+{
+  protected:
+    ETCTextureTest() : mTexture(0u)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenTextures(1, &mTexture);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTexture);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mTexture;
+};
+
+// Tests a texture with ETC1 lossy decode format
+TEST_P(ETCTextureTest, ETC1Validation)
+{
+    bool supported = extensionEnabled("GL_ANGLE_lossy_etc_decode");
+
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    GLubyte pixel[8] = { 0x0, 0x0, 0xf8, 0x2, 0x43, 0xff, 0x4, 0x12 };
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 4, 4, 0,
+                           sizeof(pixel), pixel);
+    if (supported)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE,
+                                  sizeof(pixel), pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 2, 2, 0,
+                               sizeof(pixel), pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 1, 1, 0,
+                               sizeof(pixel), pixel);
+        EXPECT_GL_NO_ERROR();
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+}
+
+// Tests a texture with ETC2 RGB8 lossy decode format
+TEST_P(ETCTextureTest, ETC2RGB8Validation)
+{
+    bool supported = extensionEnabled("GL_ANGLE_lossy_etc_decode");
+
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    GLubyte pixel[] = {
+        0x00, 0x00, 0xf8, 0x02, 0x43, 0xff, 0x04, 0x12,  // Individual/differential block
+        0x1c, 0x65, 0xc6, 0x62, 0xff, 0xf0, 0xff, 0x00,  // T block
+        0x62, 0xf2, 0xe3, 0x32, 0xff, 0x0f, 0xff, 0x00,  // H block
+        0x71, 0x88, 0xfb, 0xee, 0x87, 0x07, 0x11, 0x1f   // Planar block
+    };
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
+                           sizeof(pixel), pixel);
+    if (supported)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
+                                  GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, sizeof(pixel), pixel);
+        EXPECT_GL_NO_ERROR();
+
+        const GLsizei imageSize = 8;
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4,
+                               0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 2, 2,
+                               0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 1, 1,
+                               0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+}
+
+// Tests a texture with ETC2 SRGB8 lossy decode format
+TEST_P(ETCTextureTest, ETC2SRGB8Validation)
+{
+    bool supported = extensionEnabled("GL_ANGLE_lossy_etc_decode");
+
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    GLubyte pixel[] = {
+        0x00, 0x00, 0xf8, 0x02, 0x43, 0xff, 0x04, 0x12,  // Individual/differential block
+        0x1c, 0x65, 0xc6, 0x62, 0xff, 0xf0, 0xff, 0x00,  // T block
+        0x62, 0xf2, 0xe3, 0x32, 0xff, 0x0f, 0xff, 0x00,  // H block
+        0x71, 0x88, 0xfb, 0xee, 0x87, 0x07, 0x11, 0x1f   // Planar block
+    };
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
+                           sizeof(pixel), pixel);
+    if (supported)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
+                                  GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, sizeof(pixel),
+                                  pixel);
+        EXPECT_GL_NO_ERROR();
+
+        const GLsizei imageSize = 8;
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4,
+                               0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 2, 2,
+                               0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 1, 1,
+                               0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+}
+
+// Tests a texture with ETC2 RGB8 punchthrough A1 lossy decode format
+TEST_P(ETCTextureTest, ETC2RGB8A1Validation)
+{
+    bool supported = extensionEnabled("GL_ANGLE_lossy_etc_decode");
+
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    GLubyte pixel[] = {
+        0x80, 0x98, 0x59, 0x02, 0x6e, 0xe7, 0x44, 0x47,  // Individual/differential block
+        0xeb, 0x85, 0x68, 0x30, 0x77, 0x73, 0x44, 0x44,  // T block
+        0xb4, 0x05, 0xab, 0x92, 0xf8, 0x8c, 0x07, 0x73,  // H block
+        0xbb, 0x90, 0x15, 0xba, 0x8a, 0x8c, 0xd5, 0x5f   // Planar block
+    };
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0,
+                           GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
+                           sizeof(pixel), pixel);
+    if (supported)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
+                                  GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
+                                  sizeof(pixel), pixel);
+        EXPECT_GL_NO_ERROR();
+
+        const GLsizei imageSize = 8;
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 1,
+                               GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4, 4,
+                               0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 2,
+                               GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 2, 2,
+                               0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 3,
+                               GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 1, 1,
+                               0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+}
+
+// Tests a texture with ETC2 SRGB8 punchthrough A1 lossy decode format
+TEST_P(ETCTextureTest, ETC2SRGB8A1Validation)
+{
+    bool supported = extensionEnabled("GL_ANGLE_lossy_etc_decode");
+
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    GLubyte pixel[] = {
+        0x80, 0x98, 0x59, 0x02, 0x6e, 0xe7, 0x44, 0x47,  // Individual/differential block
+        0xeb, 0x85, 0x68, 0x30, 0x77, 0x73, 0x44, 0x44,  // T block
+        0xb4, 0x05, 0xab, 0x92, 0xf8, 0x8c, 0x07, 0x73,  // H block
+        0xbb, 0x90, 0x15, 0xba, 0x8a, 0x8c, 0xd5, 0x5f   // Planar block
+    };
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0,
+                           GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
+                           sizeof(pixel), pixel);
+    if (supported)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
+                                  GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
+                                  sizeof(pixel), pixel);
+        EXPECT_GL_NO_ERROR();
+
+        const GLsizei imageSize = 8;
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 1,
+                               GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4,
+                               4, 0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 2,
+                               GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 2,
+                               2, 0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glCompressedTexImage2D(GL_TEXTURE_2D, 3,
+                               GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 1,
+                               1, 0, imageSize, pixel);
+        EXPECT_GL_NO_ERROR();
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+}
+
+ANGLE_INSTANTIATE_TEST(ETCTextureTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL());
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/FenceSyncTests.cpp b/src/third_party/angle/src/tests/gl_tests/FenceSyncTests.cpp
new file mode 100644
index 0000000..1568509
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/FenceSyncTests.cpp
@@ -0,0 +1,282 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class FenceNVTest : public ANGLETest
+{
+  protected:
+    FenceNVTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+};
+
+class FenceSyncTest : public ANGLETest
+{
+  protected:
+    FenceSyncTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+};
+
+// FenceNV objects should respond false to glIsFenceNV until they've been set
+TEST_P(FenceNVTest, IsFence)
+{
+    if (!extensionEnabled("GL_NV_fence"))
+    {
+        std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl;
+        return;
+    }
+
+    GLuint fence = 0;
+    glGenFencesNV(1, &fence);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GL_FALSE, glIsFenceNV(fence));
+    EXPECT_GL_NO_ERROR();
+
+    glSetFenceNV(fence, GL_ALL_COMPLETED_NV);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GL_TRUE, glIsFenceNV(fence));
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test error cases for all FenceNV functions
+TEST_P(FenceNVTest, Errors)
+{
+    if (!extensionEnabled("GL_NV_fence"))
+    {
+        std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl;
+        return;
+    }
+
+    // glTestFenceNV should still return TRUE for an invalid fence and generate an INVALID_OPERATION
+    EXPECT_EQ(GL_TRUE, glTestFenceNV(10));
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    GLuint fence = 20;
+
+    // glGenFencesNV should generate INVALID_VALUE for a negative n and not write anything to the fences pointer
+    glGenFencesNV(-1, &fence);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    EXPECT_EQ(20u, fence);
+
+    // Generate a real fence
+    glGenFencesNV(1, &fence);
+    EXPECT_GL_NO_ERROR();
+
+    // glTestFenceNV should still return TRUE for a fence that is not started and generate an INVALID_OPERATION
+    EXPECT_EQ(GL_TRUE, glTestFenceNV(fence));
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // glGetFenceivNV should generate an INVALID_OPERATION for an invalid or unstarted fence and not modify the params
+    GLint result = 30;
+    glGetFenceivNV(10, GL_FENCE_STATUS_NV, &result);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    EXPECT_EQ(30, result);
+
+    glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &result);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    EXPECT_EQ(30, result);
+
+    // glSetFenceNV should generate an error for any condition that is not ALL_COMPLETED_NV
+    glSetFenceNV(fence, 0);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // glSetFenceNV should generate INVALID_OPERATION for an invalid fence
+    glSetFenceNV(10, GL_ALL_COMPLETED_NV);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test that basic usage works and doesn't generate errors or crash
+TEST_P(FenceNVTest, BasicOperations)
+{
+    if (!extensionEnabled("GL_NV_fence"))
+    {
+        std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl;
+        return;
+    }
+
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+
+    GLuint fences[20] = { 0 };
+    glGenFencesNV(static_cast<GLsizei>(ArraySize(fences)), fences);
+    EXPECT_GL_NO_ERROR();
+
+    for (GLuint fence : fences)
+    {
+        glSetFenceNV(fence, GL_ALL_COMPLETED_NV);
+
+        glClear(GL_COLOR_BUFFER_BIT);
+    }
+
+    glFinish();
+
+    for (GLuint fence : fences)
+    {
+        GLint status = 0;
+        glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &status);
+        EXPECT_GL_NO_ERROR();
+
+        // Fence should be complete now that Finish has been called
+        EXPECT_EQ(GL_TRUE, status);
+    }
+
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 255, 255);
+}
+
+// FenceSync objects should respond true to IsSync after they are created with glFenceSync
+TEST_P(FenceSyncTest, IsSync)
+{
+    GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GL_TRUE, glIsSync(sync));
+    EXPECT_EQ(GL_FALSE, glIsSync(reinterpret_cast<GLsync>(40)));
+}
+
+// Test error cases for all FenceSync function
+TEST_P(FenceSyncTest, Errors)
+{
+    GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+    // DeleteSync generates INVALID_VALUE when the sync is not valid
+    glDeleteSync(reinterpret_cast<GLsync>(20));
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // glFenceSync generates GL_INVALID_ENUM if the condition is not GL_SYNC_GPU_COMMANDS_COMPLETE
+    EXPECT_EQ(0, glFenceSync(0, 0));
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // glFenceSync generates GL_INVALID_ENUM if the flags is not 0
+    EXPECT_EQ(0, glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 10));
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if flags contains more than just GL_SYNC_FLUSH_COMMANDS_BIT
+    EXPECT_GLENUM_EQ(GL_WAIT_FAILED, glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT | 0x2, 0));
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if the sync object is not valid
+    EXPECT_GLENUM_EQ(GL_WAIT_FAILED, glClientWaitSync(reinterpret_cast<GLsync>(30), GL_SYNC_FLUSH_COMMANDS_BIT, 0));
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // glWaitSync generates GL_INVALID_VALUE if flags is non-zero
+    glWaitSync(sync, 1, GL_TIMEOUT_IGNORED);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // glWaitSync generates GL_INVALID_VALUE if GLuint64 is not GL_TIMEOUT_IGNORED
+    glWaitSync(sync, 0, 0);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // glWaitSync generates GL_INVALID_VALUE if the sync object is not valid
+    glWaitSync(reinterpret_cast<GLsync>(30), 0, GL_TIMEOUT_IGNORED);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // glGetSynciv generates GL_INVALID_VALUE if bufSize is less than zero, results should be untouched
+    GLsizei length = 20;
+    GLint value = 30;
+    glGetSynciv(sync, GL_OBJECT_TYPE, -1, &length, &value);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    EXPECT_EQ(20, length);
+    EXPECT_EQ(30, value);
+
+    // glGetSynciv generates GL_INVALID_VALUE if the sync object tis not valid, results should be untouched
+    glGetSynciv(reinterpret_cast<GLsync>(30), GL_OBJECT_TYPE, 1, &length, &value);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    EXPECT_EQ(20, length);
+    EXPECT_EQ(30, value);
+}
+
+// Test usage of glGetSynciv
+TEST_P(FenceSyncTest, BasicQueries)
+{
+    GLsizei length = 0;
+    GLint value = 0;
+    GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+    glGetSynciv(sync, GL_SYNC_CONDITION, 1, &length, &value);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(GL_SYNC_GPU_COMMANDS_COMPLETE, value);
+
+    glGetSynciv(sync, GL_OBJECT_TYPE, 1, &length, &value);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(GL_SYNC_FENCE, value);
+
+    glGetSynciv(sync, GL_SYNC_FLAGS, 1, &length, &value);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(0, value);
+}
+
+// Test that basic usage works and doesn't generate errors or crash
+TEST_P(FenceSyncTest, BasicOperations)
+{
+    // TODO(geofflang): Figure out why this is broken on Intel OpenGL
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+
+    GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+    EXPECT_GL_NO_ERROR();
+
+    GLsizei length = 0;
+    GLint value = 0;
+    unsigned int loopCount = 0;
+
+    glFlush();
+
+    // Use 'loopCount' to make sure the test doesn't get stuck in an infinite loop
+    while (value != GL_SIGNALED && loopCount <= 1000000)
+    {
+        loopCount++;
+
+        glGetSynciv(sync, GL_SYNC_STATUS, 1, &length, &value);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    ASSERT_GLENUM_EQ(GL_SIGNALED, value);
+
+    for (size_t i = 0; i < 20; i++)
+    {
+        glClear(GL_COLOR_BUFFER_BIT);
+        glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+        EXPECT_GL_NO_ERROR();
+    }
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(FenceNVTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(FenceSyncTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/FloatingPointSurfaceTest.cpp b/src/third_party/angle/src/tests/gl_tests/FloatingPointSurfaceTest.cpp
new file mode 100644
index 0000000..8d57984
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/FloatingPointSurfaceTest.cpp
@@ -0,0 +1,87 @@
+//
+// Copyright 2017 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.
+//
+
+// FloatingPointSurfaceTest.cpp : Test functionality of the EGL_EXT_pixel_format_float extension.
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class FloatingPointSurfaceTest : public ANGLETest
+{
+  protected:
+    FloatingPointSurfaceTest()
+    {
+        setWindowWidth(512);
+        setWindowHeight(512);
+        setConfigRedBits(16);
+        setConfigGreenBits(16);
+        setConfigBlueBits(16);
+        setConfigAlphaBits(16);
+        setConfigComponentType(EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource =
+            "precision highp float;\n"
+            "attribute vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "   gl_Position = position;\n"
+            "}\n";
+
+        const std::string fsSource =
+            "precision highp float;\n"
+            "void main()\n"
+            "{\n"
+            "   gl_FragColor = vec4(1.0, 2.0, 3.0, 4.0);\n"
+            "}\n";
+
+        mProgram = CompileProgram(vsSource, fsSource);
+        ASSERT_NE(0u, mProgram) << "shader compilation failed.";
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+};
+
+// Test clearing and checking the color is correct
+TEST_P(FloatingPointSurfaceTest, Clearing)
+{
+    GLColor32F clearColor(0.0f, 1.0f, 2.0f, 3.0f);
+    glClearColor(clearColor.R, clearColor.G, clearColor.B, clearColor.A);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR32F_EQ(0, 0, clearColor);
+}
+
+// Test drawing and checking the color is correct
+TEST_P(FloatingPointSurfaceTest, Drawing)
+{
+    glUseProgram(mProgram);
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_32F_EQ(0, 0, 1.0f, 2.0f, 3.0f, 4.0f);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(FloatingPointSurfaceTest,
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE));
diff --git a/src/third_party/angle/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp b/src/third_party/angle/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp
new file mode 100644
index 0000000..9a16345
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp
@@ -0,0 +1,291 @@
+//
+// Copyright 2016 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.
+//
+// CHROMIUMFramebufferMixedSamplesTest
+//   Test CHROMIUM subset of NV_framebuffer_mixed_samples.
+//   This extension allows rendering to a framebuffer that has different
+//   sample counts for different render buffers (stencil, depth, color)
+
+#include "test_utils/ANGLETest.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+const GLuint kWidth  = 100;
+const GLuint kHeight = 100;
+
+class CHROMIUMFramebufferMixedSamplesTest : public ANGLETest
+{
+  protected:
+    enum SetupFBOType
+    {
+        MixedSampleFBO,   // 1 color sample, N stencil samples.
+        SingleSampleFBO,  // 1 color sample, 1 stencil sample.
+    };
+
+    bool isApplicable() const
+    {
+        return extensionEnabled("GL_CHROMIUM_framebuffer_mixed_samples") &&
+               extensionEnabled("GL_OES_rgb8_rgba8");
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        // clang-format off
+        static const char* kVertexShaderSource =
+            "attribute mediump vec4 position;\n"
+            "void main() {\n"
+            "  gl_Position = position;\n"
+            "}\n";
+
+        static const char* kFragmentShaderSource =
+            "uniform mediump vec4 color;\n"
+            "void main() {\n"
+            "  gl_FragColor = color;\n"
+            "}\n";
+
+        // clang-format on
+        mProgram = CompileProgram(kVertexShaderSource, kFragmentShaderSource);
+
+        GLuint position_loc = glGetAttribLocation(mProgram, "position");
+        mColorLoc           = glGetUniformLocation(mProgram, "color");
+
+        glGenBuffers(1, &mVBO);
+        glBindBuffer(GL_ARRAY_BUFFER, mVBO);
+
+        static float vertices[] = {
+            1.0f,  1.0f, -1.0f, 1.0f,  -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
+            -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f,  -1.0f, 1.0f, 1.0f,
+        };
+        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+        glEnableVertexAttribArray(position_loc);
+        glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteBuffers(1, &mVBO);
+        glDeleteProgram(mProgram);
+
+        ASSERT_GL_NO_ERROR();
+
+        ANGLETest::TearDown();
+    }
+
+    void prepareForDraw(SetupFBOType fbo_type)
+    {
+        glActiveTexture(GL_TEXTURE0);
+        glGenTextures(1, &mTexture);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+        glBindTexture(GL_TEXTURE_2D, 0);
+
+        glGenRenderbuffers(1, &mStencilRB);
+        glBindRenderbuffer(GL_RENDERBUFFER, mStencilRB);
+
+        if (fbo_type == MixedSampleFBO)
+        {
+            // Create a sample buffer.
+            GLsizei num_samples = 8, max_samples = 0;
+            glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+            num_samples = std::min(num_samples, max_samples);
+            glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, num_samples, GL_STENCIL_INDEX8,
+                                                  kWidth, kHeight);
+            GLint param = 0;
+            glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &param);
+            EXPECT_GT(param, 1);
+        }
+        else
+        {
+            glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, kWidth, kHeight);
+        }
+        glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+        glGenFramebuffers(1, &mSampleFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                                  mStencilRB);
+        EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+                  glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+        glUseProgram(mProgram);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        glViewport(0, 0, kWidth, kHeight);
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glClearStencil(1);
+        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+        glEnable(GL_STENCIL_TEST);
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        glStencilMask(0xffffffff);
+        glStencilFunc(GL_EQUAL, 1, 0xffffffff);
+        glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void cleanup()
+    {
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glDeleteFramebuffers(1, &mSampleFBO);
+        glDeleteTextures(1, &mTexture);
+        glDeleteRenderbuffers(1, &mStencilRB);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    GLuint mSampleFBO;
+    GLuint mStencilRB;
+    GLuint mTexture;
+
+    GLuint mProgram;
+    GLuint mVBO;
+    GLint mColorLoc;
+};
+
+}  //
+
+TEST_P(CHROMIUMFramebufferMixedSamplesTest, StateSettingTest)
+{
+    if (!isApplicable())
+    {
+        return;
+    }
+
+    GLint value = -1;
+    glGetIntegerv(GL_COVERAGE_MODULATION_CHROMIUM, &value);
+    EXPECT_EQ(GL_NONE, value);
+    GLenum kValues[] = {GL_NONE, GL_RGB, GL_RGBA, GL_ALPHA};
+    for (auto expect : kValues)
+    {
+        glCoverageModulationCHROMIUM(expect);
+        value = -1;
+        glGetIntegerv(GL_COVERAGE_MODULATION_CHROMIUM, &value);
+        EXPECT_EQ(expect, static_cast<GLenum>(value));
+        EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+    }
+
+    glCoverageModulationCHROMIUM(GL_BYTE);
+    EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+    value = -1;
+    glGetIntegerv(GL_COVERAGE_MODULATION_CHROMIUM, &value);
+    EXPECT_EQ(static_cast<GLenum>(GL_ALPHA), static_cast<GLenum>(value));
+    EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+// The test pattern is as follows:
+// A green triangle (bottom left, top right, top left).
+// A blue triangle (top left, bottom right, bottom left).
+// The triangles will overlap but overlap only contains green pixels,
+// due to each draw erasing its area from stencil.
+// The blue triangle will fill only the area (bottom left, center,
+// bottom right).
+
+// The test tests that CoverageModulation call works.
+// The fractional pixels of both triangles end up being modulated
+// by the coverage of the fragment. Test that drawing with and without
+// CoverageModulation causes the result to be different.
+TEST_P(CHROMIUMFramebufferMixedSamplesTest, CoverageModulation)
+{
+    if (!isApplicable())
+    {
+        return;
+    }
+    static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
+    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+    std::unique_ptr<uint8_t[]> results[3];
+    const GLint kResultSize = kWidth * kHeight * 4;
+
+    for (int pass = 0; pass < 3; ++pass)
+    {
+        prepareForDraw(MixedSampleFBO);
+        if (pass == 1)
+        {
+            glCoverageModulationCHROMIUM(GL_RGBA);
+        }
+        glUniform4fv(mColorLoc, 1, kGreen);
+        glDrawArrays(GL_TRIANGLES, 0, 3);
+
+        glUniform4fv(mColorLoc, 1, kBlue);
+        glDrawArrays(GL_TRIANGLES, 3, 3);
+        if (pass == 1)
+        {
+            glCoverageModulationCHROMIUM(GL_NONE);
+        }
+        results[pass].reset(new uint8_t[kResultSize]);
+        memset(results[pass].get(), 123u, kResultSize);
+        glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, results[pass].get());
+
+        cleanup();
+    }
+
+    EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
+    // Verify that rendering is deterministic, so that the pass above does not
+    // come from non-deterministic rendering.
+    EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
+}
+
+// The test tests that the stencil buffer can be multisampled, even though the
+// color buffer is single-sampled. Draws the same pattern with single-sample
+// stencil buffer and with multisample stencil buffer. The images should differ.
+TEST_P(CHROMIUMFramebufferMixedSamplesTest, MultisampleStencilEffective)
+{
+    if (!isApplicable())
+    {
+        return;
+    }
+
+    static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
+    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+
+    std::unique_ptr<uint8_t[]> results[3];
+    const GLint kResultSize = kWidth * kHeight * 4;
+
+    for (int pass = 0; pass < 3; ++pass)
+    {
+        if (pass == 1)
+        {
+            prepareForDraw(MixedSampleFBO);
+        }
+        else
+        {
+            prepareForDraw(SingleSampleFBO);
+        }
+        glUniform4fv(mColorLoc, 1, kGreen);
+        glDrawArrays(GL_TRIANGLES, 0, 3);
+
+        glUniform4fv(mColorLoc, 1, kBlue);
+        glDrawArrays(GL_TRIANGLES, 3, 3);
+
+        results[pass].reset(new uint8_t[kResultSize]);
+        memset(results[pass].get(), 12u, kResultSize);
+        glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, results[pass].get());
+
+        cleanup();
+    }
+
+    EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
+    // Verify that rendering is deterministic, so that the pass above does not
+    // come from non-deterministic rendering.
+    EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
+}
+
+ANGLE_INSTANTIATE_TEST(CHROMIUMFramebufferMixedSamplesTest,
+                       ES2_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGL());
diff --git a/src/third_party/angle/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp b/src/third_party/angle/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp
new file mode 100644
index 0000000..660b6d6
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp
@@ -0,0 +1,204 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class FramebufferRenderMipmapTest : public ANGLETest
+{
+  protected:
+    FramebufferRenderMipmapTest()
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource = SHADER_SOURCE
+        (
+            attribute highp vec4 position;
+            void main(void)
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string fsSource = SHADER_SOURCE
+        (
+            uniform highp vec4 color;
+            void main(void)
+            {
+                gl_FragColor = color;
+            }
+        );
+
+        mProgram = CompileProgram(vsSource, fsSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mColorLocation = glGetUniformLocation(mProgram, "color");
+
+        glUseProgram(mProgram);
+
+        glClearColor(0, 0, 0, 0);
+        glClearDepthf(0.0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        glEnable(GL_BLEND);
+        glDisable(GL_DEPTH_TEST);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+    GLint mColorLocation;
+};
+
+// Validate that if we are in ES3 or GL_OES_fbo_render_mipmap exists, there are no validation errors
+// when using a non-zero level in glFramebufferTexture2D.
+TEST_P(FramebufferRenderMipmapTest, Validation)
+{
+    bool renderToMipmapSupported =
+        extensionEnabled("GL_OES_fbo_render_mipmap") || getClientMajorVersion() > 2;
+
+    GLuint tex = 0;
+    glGenTextures(1, &tex);
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    const GLint levels = 5;
+    for (GLint i = 0; i < levels; i++)
+    {
+        GLsizei size = 1 << ((levels - 1) - i);
+        glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    }
+
+    EXPECT_GL_NO_ERROR();
+
+    GLuint fbo = 0;
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    EXPECT_GL_NO_ERROR();
+
+    for (GLint i = 0; i < levels; i++)
+    {
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, i);
+
+        if (i > 0 && !renderToMipmapSupported)
+        {
+            EXPECT_GL_ERROR(GL_INVALID_VALUE);
+        }
+        else
+        {
+            EXPECT_GL_NO_ERROR();
+            EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GLenum(GL_FRAMEBUFFER_COMPLETE));
+        }
+    }
+
+    glDeleteFramebuffers(1, &fbo);
+    glDeleteTextures(1, &tex);
+}
+
+// Render to various levels of a texture and check that they have the correct color data via ReadPixels
+TEST_P(FramebufferRenderMipmapTest, RenderToMipmap)
+{
+    // TODO(geofflang): Figure out why this is broken on Intel OpenGL
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    bool renderToMipmapSupported =
+        extensionEnabled("GL_OES_fbo_render_mipmap") || getClientMajorVersion() > 2;
+    if (!renderToMipmapSupported)
+    {
+        std::cout << "Test skipped because GL_OES_fbo_render_mipmap or ES3 is not available." << std::endl;
+        return;
+    }
+
+    const GLfloat levelColors[] =
+    {
+        1.0f, 0.0f, 0.0f, 1.0f,
+        0.0f, 1.0f, 0.0f, 1.0f,
+        0.0f, 0.0f, 1.0f, 1.0f,
+        1.0f, 1.0f, 0.0f, 1.0f,
+        1.0f, 0.0f, 1.0f, 1.0f,
+        0.0f, 1.0f, 1.0f, 1.0f,
+    };
+    const GLint testLevels = static_cast<GLint>(ArraySize(levelColors) / 4);
+
+    GLuint tex = 0;
+    glGenTextures(1, &tex);
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    for (GLint i = 0; i < testLevels; i++)
+    {
+        GLsizei size = 1 << ((testLevels - 1) - i);
+        glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    }
+
+    EXPECT_GL_NO_ERROR();
+
+    GLuint fbo = 0;
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    EXPECT_GL_NO_ERROR();
+
+    // Render to the levels of the texture with different colors
+    for (GLint i = 0; i < testLevels; i++)
+    {
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, i);
+        EXPECT_GL_NO_ERROR();
+
+        glUseProgram(mProgram);
+        glUniform4fv(mColorLocation, 1, levelColors + (i * 4));
+
+        drawQuad(mProgram, "position", 0.5f);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    // Test that the levels of the texture are correct
+    for (GLint i = 0; i < testLevels; i++)
+    {
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, i);
+        EXPECT_GL_NO_ERROR();
+
+        const GLfloat *color = levelColors + (i * 4);
+        EXPECT_PIXEL_EQ(0, 0, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255);
+    }
+
+    glDeleteFramebuffers(1, &fbo);
+    glDeleteTextures(1, &tex);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(FramebufferRenderMipmapTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/FramebufferTest.cpp b/src/third_party/angle/src/tests/gl_tests/FramebufferTest.cpp
new file mode 100644
index 0000000..6ed4f8f
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/FramebufferTest.cpp
@@ -0,0 +1,546 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Framebuffer tests:
+//   Various tests related for Frambuffers.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+class FramebufferFormatsTest : public ANGLETest
+{
+  protected:
+    FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void checkBitCount(GLuint fbo, GLenum channel, GLint minBits)
+    {
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+        GLint bits = 0;
+        glGetIntegerv(channel, &bits);
+
+        if (minBits == 0)
+        {
+            EXPECT_EQ(minBits, bits);
+        }
+        else
+        {
+            EXPECT_GE(bits, minBits);
+        }
+    }
+
+    void testBitCounts(GLuint fbo,
+                       GLint minRedBits,
+                       GLint minGreenBits,
+                       GLint minBlueBits,
+                       GLint minAlphaBits,
+                       GLint minDepthBits,
+                       GLint minStencilBits)
+    {
+        checkBitCount(fbo, GL_RED_BITS, minRedBits);
+        checkBitCount(fbo, GL_GREEN_BITS, minGreenBits);
+        checkBitCount(fbo, GL_BLUE_BITS, minBlueBits);
+        checkBitCount(fbo, GL_ALPHA_BITS, minAlphaBits);
+        checkBitCount(fbo, GL_DEPTH_BITS, minDepthBits);
+        checkBitCount(fbo, GL_STENCIL_BITS, minStencilBits);
+    }
+
+    void testTextureFormat(GLenum internalFormat,
+                           GLint minRedBits,
+                           GLint minGreenBits,
+                           GLint minBlueBits,
+                           GLint minAlphaBits)
+    {
+        glGenTextures(1, &mTexture);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+
+        if (getClientMajorVersion() >= 3)
+        {
+            glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
+        }
+        else
+        {
+            glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
+        }
+
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
+
+        testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
+    }
+
+    void testRenderbufferMultisampleFormat(int minESVersion,
+                                           GLenum attachmentType,
+                                           GLenum internalFormat)
+    {
+        // TODO(geofflang): Figure out why this is broken on Intel OpenGL
+        if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+        {
+            std::cout << "Test skipped on Intel OpenGL." << std::endl;
+            return;
+        }
+
+        int clientVersion = getClientMajorVersion();
+        if (clientVersion < minESVersion)
+        {
+            return;
+        }
+
+        // Check that multisample is supported with at least two samples (minimum required is 1)
+        bool supports2Samples = false;
+
+        if (clientVersion == 2)
+        {
+            if (extensionEnabled("ANGLE_framebuffer_multisample"))
+            {
+                int maxSamples;
+                glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples);
+                supports2Samples = maxSamples >= 2;
+            }
+        }
+        else
+        {
+            assert(clientVersion >= 3);
+            int maxSamples;
+            glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
+            supports2Samples = maxSamples >= 2;
+        }
+
+        if (!supports2Samples)
+        {
+            return;
+        }
+
+        glGenRenderbuffers(1, &mRenderbuffer);
+        glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+
+        EXPECT_GL_NO_ERROR();
+        glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
+        EXPECT_GL_NO_ERROR();
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    void testZeroHeightRenderbuffer()
+    {
+        glGenRenderbuffers(1, &mRenderbuffer);
+        glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 0);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                                  mRenderbuffer);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenFramebuffers(1, &mFramebuffer);
+        glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    }
+
+    void TearDown() override
+    {
+        ANGLETest::TearDown();
+
+        if (mTexture != 0)
+        {
+            glDeleteTextures(1, &mTexture);
+            mTexture = 0;
+        }
+
+        if (mRenderbuffer != 0)
+        {
+            glDeleteRenderbuffers(1, &mRenderbuffer);
+            mRenderbuffer = 0;
+        }
+
+        if (mFramebuffer != 0)
+        {
+            glDeleteFramebuffers(1, &mFramebuffer);
+            mFramebuffer = 0;
+        }
+
+        if (mProgram != 0)
+        {
+            glDeleteProgram(mProgram);
+            mProgram = 0;
+        }
+    }
+
+    GLuint mFramebuffer;
+    GLuint mTexture;
+    GLuint mRenderbuffer;
+    GLuint mProgram;
+};
+
+TEST_P(FramebufferFormatsTest, RGBA4)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage"))
+    {
+        std::cout << "Test skipped due to missing ES3 or GL_EXT_texture_storage." << std::endl;
+        return;
+    }
+
+    testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
+}
+
+TEST_P(FramebufferFormatsTest, RGB565)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage"))
+    {
+        std::cout << "Test skipped due to missing ES3 or GL_EXT_texture_storage." << std::endl;
+        return;
+    }
+
+    testTextureFormat(GL_RGB565, 5, 6, 5, 0);
+}
+
+TEST_P(FramebufferFormatsTest, RGB8)
+{
+    if (getClientMajorVersion() < 3 &&
+        (!extensionEnabled("GL_OES_rgb8_rgba8") || !extensionEnabled("GL_EXT_texture_storage")))
+    {
+        std::cout
+            << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8 and GL_EXT_texture_storage."
+            << std::endl;
+        return;
+    }
+
+    testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
+}
+
+TEST_P(FramebufferFormatsTest, BGRA8)
+{
+    if (!extensionEnabled("GL_EXT_texture_format_BGRA8888") ||
+        (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage")))
+    {
+        std::cout << "Test skipped due to missing GL_EXT_texture_format_BGRA8888 or "
+                     "GL_EXT_texture_storage."
+                  << std::endl;
+        return;
+    }
+
+    testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
+}
+
+TEST_P(FramebufferFormatsTest, RGBA8)
+{
+    if (getClientMajorVersion() < 3 &&
+        (!extensionEnabled("GL_OES_rgb8_rgba8") || !extensionEnabled("GL_EXT_texture_storage")))
+    {
+        std::cout
+            << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8 and GL_EXT_texture_storage."
+            << std::endl;
+        return;
+    }
+
+    testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
+}
+
+TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
+{
+    testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
+}
+
+TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
+{
+    testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
+}
+
+TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
+{
+    if (getClientMajorVersion() < 3)
+    {
+        std::cout << "Test skipped due to missing ES3." << std::endl;
+        return;
+    }
+
+    testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
+}
+
+TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
+{
+    testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
+}
+
+TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
+{
+    if (getClientMajorVersion() < 3)
+    {
+        std::cout << "Test skipped due to missing ES3." << std::endl;
+        return;
+    }
+
+    testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
+}
+
+TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
+{
+    // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
+    if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Desktop OpenGL." << std::endl;
+        return;
+    }
+
+    testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
+}
+
+// Test that binding an incomplete cube map is rejected by ANGLE.
+TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
+{
+    // First make a complete CubeMap.
+    glGenTextures(1, &mTexture);
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+                           mTexture, 0);
+
+    // Verify the framebuffer is complete.
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Make the CubeMap cube-incomplete.
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+
+    // Verify the framebuffer is incomplete.
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Verify drawing with the incomplete framebuffer produces a GL error
+    const std::string &vs = "attribute vec4 position; void main() { gl_Position = position; }";
+    const std::string &ps = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
+    mProgram = CompileProgram(vs, ps);
+    ASSERT_NE(0u, mProgram);
+    drawQuad(mProgram, "position", 0.5f);
+    ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+}
+
+// Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts.
+TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
+{
+    if (getClientMajorVersion() < 3)
+    {
+        std::cout << "Test skipped due to missing ES3" << std::endl;
+        return;
+    }
+
+    testZeroHeightRenderbuffer();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(FramebufferFormatsTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+class FramebufferTest_ES3 : public ANGLETest
+{
+  protected:
+    FramebufferTest_ES3() : mFramebuffer(0), mRenderbuffer(0) {}
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenFramebuffers(1, &mFramebuffer);
+        glGenRenderbuffers(1, &mRenderbuffer);
+    }
+
+    void TearDown() override
+    {
+        glDeleteFramebuffers(1, &mFramebuffer);
+        glDeleteRenderbuffers(1, &mRenderbuffer);
+        ANGLETest::TearDown();
+    }
+
+    GLuint mFramebuffer;
+    GLuint mRenderbuffer;
+};
+
+// Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
+TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    std::vector<GLenum> attachments;
+    attachments.push_back(GL_COLOR_ATTACHMENT0);
+
+    glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that the framebuffer state tracking robustly handles a depth-only attachment being set
+// as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
+TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
+
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              mRenderbuffer);
+    EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+}
+
+ANGLE_INSTANTIATE_TEST(FramebufferTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+class FramebufferTest_ES31 : public ANGLETest
+{
+};
+
+// Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
+// FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
+TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
+{
+    GLFramebuffer mFramebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
+
+    glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
+    glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
+    glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
+    glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
+    glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that the sample count of a mix of texture and renderbuffer should be same.
+TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
+{
+    GLFramebuffer mFramebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
+
+    GLTexture mTexture;
+    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true);
+
+    GLRenderbuffer mRenderbuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
+    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 1, 1);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
+                           mTexture.get(), 0);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
+                              mRenderbuffer.get());
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that the sample count of texture attachments should be same.
+TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
+{
+    GLFramebuffer mFramebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
+
+    GLTexture mTextures[2];
+    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true);
+    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, true);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
+                           mTextures[0].get(), 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
+                           mTextures[1].get(), 0);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that if the attached images are a mix of renderbuffers and textures, the value of
+// TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
+TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
+{
+    GLFramebuffer mFramebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
+
+    GLTexture mTexture;
+    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
+
+    GLRenderbuffer mRenderbuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
+    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
+                           mTexture.get(), 0);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
+                              mRenderbuffer.get());
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
+TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
+{
+    GLFramebuffer mFramebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
+
+    GLTexture mTextures[2];
+    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
+                           mTextures[0].get(), 0);
+    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
+                           mTextures[1].get(), 0);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+ANGLE_INSTANTIATE_TEST(FramebufferTest_ES31, ES31_OPENGL(), ES31_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/GLSLTest.cpp b/src/third_party/angle/src/tests/gl_tests/GLSLTest.cpp
new file mode 100644
index 0000000..050651b
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/GLSLTest.cpp
@@ -0,0 +1,2841 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+class GLSLTest : public ANGLETest
+{
+  protected:
+    GLSLTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        mSimpleVSSource = SHADER_SOURCE
+        (
+            attribute vec4 inputAttribute;
+            void main()
+            {
+                gl_Position = inputAttribute;
+            }
+        );
+    }
+
+    std::string GenerateVaryingType(GLint vectorSize)
+    {
+        char varyingType[10];
+
+        if (vectorSize == 1)
+        {
+            sprintf(varyingType, "float");
+        }
+        else
+        {
+            sprintf(varyingType, "vec%d", vectorSize);
+        }
+
+        return std::string(varyingType);
+    }
+
+    std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
+    {
+        char buff[100];
+
+        if (arraySize == 1)
+        {
+            sprintf(buff, "varying %s v%d;\n", GenerateVaryingType(vectorSize).c_str(), id);
+        }
+        else
+        {
+            sprintf(buff, "varying %s v%d[%d];\n", GenerateVaryingType(vectorSize).c_str(), id, arraySize);
+        }
+
+        return std::string(buff);
+    }
+
+    std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id)
+    {
+        std::string returnString;
+        char buff[100];
+
+        if (arraySize == 1)
+        {
+            sprintf(buff, "\t v%d = %s(1.0);\n", id, GenerateVaryingType(vectorSize).c_str());
+            returnString += buff;
+        }
+        else
+        {
+            for (int i = 0; i < arraySize; i++)
+            {
+                sprintf(buff, "\t v%d[%d] = %s(1.0);\n", id, i, GenerateVaryingType(vectorSize).c_str());
+                returnString += buff;
+            }
+        }
+
+        return returnString;
+    }
+
+    std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
+    {
+        if (arraySize == 1)
+        {
+            char buff[100];
+            sprintf(buff, "v%d + ", id);
+            return std::string(buff);
+        }
+        else
+        {
+            std::string returnString;
+            for (int i = 0; i < arraySize; i++)
+            {
+                char buff[100];
+                sprintf(buff, "v%d[%d] + ", id, i);
+                returnString += buff;
+            }
+            return returnString;
+        }
+    }
+
+    void GenerateGLSLWithVaryings(GLint floatCount, GLint floatArrayCount, GLint vec2Count, GLint vec2ArrayCount, GLint vec3Count, GLint vec3ArrayCount,
+                                  GLint vec4Count, GLint vec4ArrayCount, bool useFragCoord, bool usePointCoord, bool usePointSize,
+                                  std::string* fragmentShader, std::string* vertexShader)
+    {
+        // Generate a string declaring the varyings, to share between the fragment shader and the vertex shader.
+        std::string varyingDeclaration;
+
+        unsigned int varyingCount = 0;
+
+        for (GLint i = 0; i < floatCount; i++)
+        {
+            varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
+            varyingCount += 1;
+        }
+
+        for (GLint i = 0; i < floatArrayCount; i++)
+        {
+            varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
+            varyingCount += 1;
+        }
+
+        for (GLint i = 0; i < vec2Count; i++)
+        {
+            varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
+            varyingCount += 1;
+        }
+
+        for (GLint i = 0; i < vec2ArrayCount; i++)
+        {
+            varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
+            varyingCount += 1;
+        }
+
+        for (GLint i = 0; i < vec3Count; i++)
+        {
+            varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
+            varyingCount += 1;
+        }
+
+        for (GLint i = 0; i < vec3ArrayCount; i++)
+        {
+            varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
+            varyingCount += 1;
+        }
+
+        for (GLint i = 0; i < vec4Count; i++)
+        {
+            varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
+            varyingCount += 1;
+        }
+
+        for (GLint i = 0; i < vec4ArrayCount; i++)
+        {
+            varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
+            varyingCount += 1;
+        }
+
+        // Generate the vertex shader
+        vertexShader->clear();
+        vertexShader->append(varyingDeclaration);
+        vertexShader->append("\nvoid main()\n{\n");
+
+        unsigned int currentVSVarying = 0;
+
+        for (GLint i = 0; i < floatCount; i++)
+        {
+            vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
+            currentVSVarying += 1;
+        }
+
+        for (GLint i = 0; i < floatArrayCount; i++)
+        {
+            vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
+            currentVSVarying += 1;
+        }
+
+        for (GLint i = 0; i < vec2Count; i++)
+        {
+            vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
+            currentVSVarying += 1;
+        }
+
+        for (GLint i = 0; i < vec2ArrayCount; i++)
+        {
+            vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
+            currentVSVarying += 1;
+        }
+
+        for (GLint i = 0; i < vec3Count; i++)
+        {
+            vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
+            currentVSVarying += 1;
+        }
+
+        for (GLint i = 0; i < vec3ArrayCount; i++)
+        {
+            vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
+            currentVSVarying += 1;
+        }
+
+        for (GLint i = 0; i < vec4Count; i++)
+        {
+            vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
+            currentVSVarying += 1;
+        }
+
+        for (GLint i = 0; i < vec4ArrayCount; i++)
+        {
+            vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
+            currentVSVarying += 1;
+        }
+
+        if (usePointSize)
+        {
+            vertexShader->append("gl_PointSize = 1.0;\n");
+        }
+
+        vertexShader->append("}\n");
+
+        // Generate the fragment shader
+        fragmentShader->clear();
+        fragmentShader->append("precision highp float;\n");
+        fragmentShader->append(varyingDeclaration);
+        fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
+
+        unsigned int currentFSVarying = 0;
+
+        // Make use of the float varyings
+        fragmentShader->append("\tretColor += vec4(");
+
+        for (GLint i = 0; i < floatCount; i++)
+        {
+            fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
+            currentFSVarying += 1;
+        }
+
+        for (GLint i = 0; i < floatArrayCount; i++)
+        {
+            fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
+            currentFSVarying += 1;
+        }
+
+        fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
+
+        // Make use of the vec2 varyings
+        fragmentShader->append("\tretColor += vec4(");
+
+        for (GLint i = 0; i < vec2Count; i++)
+        {
+            fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
+            currentFSVarying += 1;
+        }
+
+        for (GLint i = 0; i < vec2ArrayCount; i++)
+        {
+            fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
+            currentFSVarying += 1;
+        }
+
+        fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
+
+        // Make use of the vec3 varyings
+        fragmentShader->append("\tretColor += vec4(");
+
+        for (GLint i = 0; i < vec3Count; i++)
+        {
+            fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
+            currentFSVarying += 1;
+        }
+
+        for (GLint i = 0; i < vec3ArrayCount; i++)
+        {
+            fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
+            currentFSVarying += 1;
+        }
+
+        fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
+
+        // Make use of the vec4 varyings
+        fragmentShader->append("\tretColor += ");
+
+        for (GLint i = 0; i < vec4Count; i++)
+        {
+            fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
+            currentFSVarying += 1;
+        }
+
+        for (GLint i = 0; i < vec4ArrayCount; i++)
+        {
+            fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
+            currentFSVarying += 1;
+        }
+
+        fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
+
+        // Set gl_FragColor, and use special variables if requested
+        fragmentShader->append("\tgl_FragColor = retColor");
+        
+        if (useFragCoord)
+        {
+            fragmentShader->append(" + gl_FragCoord");
+        }
+
+        if (usePointCoord)
+        {
+            fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
+        }
+
+        fragmentShader->append(";\n}");
+    }
+
+    void VaryingTestBase(GLint floatCount, GLint floatArrayCount, GLint vec2Count, GLint vec2ArrayCount, GLint vec3Count, GLint vec3ArrayCount,
+                         GLint vec4Count, GLint vec4ArrayCount, bool useFragCoord, bool usePointCoord, bool usePointSize, bool expectSuccess)
+    {
+        std::string fragmentShaderSource;
+        std::string vertexShaderSource;
+
+        GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count, vec3ArrayCount,
+                                 vec4Count, vec4ArrayCount, useFragCoord, usePointCoord, usePointSize,
+                                 &fragmentShaderSource, &vertexShaderSource);
+
+        GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+
+        if (expectSuccess)
+        {
+            EXPECT_NE(0u, program);
+        }
+        else
+        {
+            EXPECT_EQ(0u, program);
+        }
+    }
+
+    void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
+                                            GLint fragmentUniformCount,
+                                            GLint vertexSamplersCount,
+                                            GLint fragmentSamplersCount,
+                                            bool expectSuccess)
+    {
+        std::stringstream vertexShader;
+        std::stringstream fragmentShader;
+
+        // Generate the vertex shader
+        vertexShader << "precision mediump float;\n";
+
+        for (int i = 0; i < vertexUniformCount; i++)
+        {
+            vertexShader << "uniform vec4 v" << i << ";\n";
+        }
+
+        for (int i = 0; i < vertexSamplersCount; i++)
+        {
+            vertexShader << "uniform sampler2D s" << i << ";\n";
+        }
+
+        vertexShader << "void main()\n{\n";
+
+        for (int i = 0; i < vertexUniformCount; i++)
+        {
+            vertexShader << "    gl_Position +=  v" << i << ";\n";
+        }
+
+        for (int i = 0; i < vertexSamplersCount; i++)
+        {
+            vertexShader << "    gl_Position +=  texture2D(s" << i << ", vec2(0.0, 0.0));\n";
+        }
+
+        if (vertexUniformCount == 0 && vertexSamplersCount == 0)
+        {
+            vertexShader << "   gl_Position = vec4(0.0);\n";
+        }
+
+        vertexShader << "}\n";
+
+        // Generate the fragment shader
+        fragmentShader << "precision mediump float;\n";
+
+        for (int i = 0; i < fragmentUniformCount; i++)
+        {
+            fragmentShader << "uniform vec4 v" << i << ";\n";
+        }
+
+        for (int i = 0; i < fragmentSamplersCount; i++)
+        {
+            fragmentShader << "uniform sampler2D s" << i << ";\n";
+        }
+
+        fragmentShader << "void main()\n{\n";
+
+        for (int i = 0; i < fragmentUniformCount; i++)
+        {
+            fragmentShader << "    gl_FragColor +=  v" << i << ";\n";
+        }
+
+        for (int i = 0; i < fragmentSamplersCount; i++)
+        {
+            fragmentShader << "    gl_FragColor +=  texture2D(s" << i << ", vec2(0.0, 0.0));\n";
+        }
+
+        if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
+        {
+            fragmentShader << "    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
+        }
+
+        fragmentShader << "}\n";
+
+        GLuint program = CompileProgram(vertexShader.str(), fragmentShader.str());
+
+        if (expectSuccess)
+        {
+            EXPECT_NE(0u, program);
+        }
+        else
+        {
+            EXPECT_EQ(0u, program);
+        }
+    }
+
+    std::string mSimpleVSSource;
+};
+
+class GLSLTestNoValidation : public GLSLTest
+{
+  public:
+    GLSLTestNoValidation() { setNoErrorEnabled(true); }
+};
+
+class GLSLTest_ES3 : public GLSLTest
+{
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        mSimpleVSSource =
+            "#version 300 es\n"
+            "in vec4 inputAttribute;"
+            "void main()"
+            "{"
+            "    gl_Position = inputAttribute;"
+            "}";
+    }
+};
+
+class GLSLTest_ES31 : public GLSLTest
+{
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        mSimpleVSSource =
+            "#version 310 es\n"
+            "in vec4 inputAttribute;"
+            "void main()"
+            "{"
+            "    gl_Position = inputAttribute;"
+            "}";
+    }
+};
+
+TEST_P(GLSLTest, NamelessScopedStructs)
+{
+    const std::string fragmentShaderSource = SHADER_SOURCE
+    (
+        precision mediump float;
+
+        void main()
+        {
+            struct
+            {
+                float q;
+            } b;
+
+            gl_FragColor = vec4(1, 0, 0, 1);
+            gl_FragColor.a += b.q;
+        }
+    );
+
+    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+TEST_P(GLSLTest, ScopedStructsOrderBug)
+{
+    // TODO(geofflang): Find out why this doesn't compile on Apple OpenGL drivers
+    // (http://anglebug.com/1292)
+    // TODO(geofflang): Find out why this doesn't compile on AMD OpenGL drivers
+    // (http://anglebug.com/1291)
+    if (IsDesktopOpenGL() && (IsOSX() || !IsNVIDIA()))
+    {
+        std::cout << "Test disabled on this OpenGL configuration." << std::endl;
+        return;
+    }
+
+    const std::string fragmentShaderSource = SHADER_SOURCE
+    (
+        precision mediump float;
+
+        struct T
+        {
+            float f;
+        };
+
+        void main()
+        {
+            T a;
+
+            struct T
+            {
+                float q;
+            };
+
+            T b;
+
+            gl_FragColor = vec4(1, 0, 0, 1);
+            gl_FragColor.a += a.f;
+            gl_FragColor.a += b.q;
+        }
+    );
+
+    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+TEST_P(GLSLTest, ScopedStructsBug)
+{
+    const std::string fragmentShaderSource = SHADER_SOURCE
+    (
+        precision mediump float;
+
+        struct T_0
+        {
+            float f;
+        };
+
+        void main()
+        {
+            gl_FragColor = vec4(1, 0, 0, 1);
+
+            struct T
+            {
+                vec2 v;
+            };
+
+            T_0 a;
+            T b;
+
+            gl_FragColor.a += a.f;
+            gl_FragColor.a += b.v.x;
+        }
+    );
+
+    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+TEST_P(GLSLTest, DxPositionBug)
+{
+    const std::string &vertexShaderSource = SHADER_SOURCE
+    (
+        attribute vec4 inputAttribute;
+        varying float dx_Position;
+        void main()
+        {
+            gl_Position = vec4(inputAttribute);
+            dx_Position = 0.0;
+        }
+    );
+
+    const std::string &fragmentShaderSource = SHADER_SOURCE
+    (
+        precision mediump float;
+
+        varying float dx_Position;
+
+        void main()
+        {
+            gl_FragColor = vec4(dx_Position, 0, 0, 1);
+        }
+    );
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+TEST_P(GLSLTest, ElseIfRewriting)
+{
+    const std::string &vertexShaderSource =
+        "attribute vec4 a_position;\n"
+        "varying float v;\n"
+        "void main() {\n"
+        "  gl_Position = a_position;\n"
+        "  v = 1.0;\n"
+        "  if (a_position.x <= 0.5) {\n"
+        "    v = 0.0;\n"
+        "  } else if (a_position.x >= 0.5) {\n"
+        "    v = 2.0;\n"
+        "  }\n"
+        "}\n";
+
+    const std::string &fragmentShaderSource =
+        "precision highp float;\n"
+        "varying float v;\n"
+        "void main() {\n"
+        "  vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "  if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+        "  if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
+        "  gl_FragColor = color;\n"
+        "}\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    ASSERT_NE(0u, program);
+
+    drawQuad(program, "a_position", 0.5f);
+
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+    EXPECT_PIXEL_EQ(getWindowWidth()-1, 0, 0, 255, 0, 255);
+}
+
+TEST_P(GLSLTest, TwoElseIfRewriting)
+{
+    const std::string &vertexShaderSource =
+        "attribute vec4 a_position;\n"
+        "varying float v;\n"
+        "void main() {\n"
+        "  gl_Position = a_position;\n"
+        "  if (a_position.x == 0.0) {\n"
+        "    v = 1.0;\n"
+        "  } else if (a_position.x > 0.5) {\n"
+        "    v = 0.0;\n"
+        "  } else if (a_position.x > 0.75) {\n"
+        "    v = 0.5;\n"
+        "  }\n"
+        "}\n";
+
+    const std::string &fragmentShaderSource =
+        "precision highp float;\n"
+        "varying float v;\n"
+        "void main() {\n"
+        "  gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+TEST_P(GLSLTest, FrontFacingAndVarying)
+{
+    EGLPlatformParameters platform = GetParam().eglParameters;
+
+    const std::string vertexShaderSource = SHADER_SOURCE
+    (
+        attribute vec4 a_position;
+        varying float v_varying;
+        void main()
+        {
+            v_varying = a_position.x;
+            gl_Position = a_position;
+        }
+    );
+
+    const std::string fragmentShaderSource = SHADER_SOURCE
+    (
+        precision mediump float;
+        varying float v_varying;
+        void main()
+        {
+            vec4 c;
+
+            if (gl_FrontFacing)
+            {
+                c = vec4(v_varying, 0, 0, 1.0);
+            }
+            else
+            {
+                c = vec4(0, v_varying, 0, 1.0);
+            }
+            gl_FragColor = c;
+        }
+    );
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+
+    // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
+    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        if (platform.majorVersion == 9 && platform.minorVersion == 3)
+        {
+            EXPECT_EQ(0u, program);
+            return;
+        }
+    }
+
+    // Otherwise, compilation should succeed
+    EXPECT_NE(0u, program);
+}
+
+// Verify that linking shaders declaring different shading language versions fails.
+TEST_P(GLSLTest_ES3, VersionMismatch)
+{
+    const std::string fragmentShaderSource100 =
+        "precision mediump float;\n"
+        "varying float v_varying;\n"
+        "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource100 =
+        "attribute vec4 a_position;\n"
+        "varying float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    const std::string fragmentShaderSource300 =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in float v_varying;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource300 =
+        "#version 300 es\n"
+        "in vec4 a_position;\n"
+        "out float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource300, fragmentShaderSource100);
+    EXPECT_EQ(0u, program);
+
+    program = CompileProgram(vertexShaderSource100, fragmentShaderSource300);
+    EXPECT_EQ(0u, program);
+}
+
+// Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
+TEST_P(GLSLTest, InvariantVaryingOut)
+{
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "varying float v_varying;\n"
+        "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "attribute vec4 a_position;\n"
+        "invariant varying float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_EQ(0u, program);
+}
+
+// Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
+TEST_P(GLSLTest_ES3, InvariantVaryingOut)
+{
+    // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
+    // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
+    if (IsDesktopOpenGL())
+    {
+        std::cout << "Test disabled on OpenGL." << std::endl;
+        return;
+    }
+
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in float v_varying;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in vec4 a_position;\n"
+        "invariant out float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
+TEST_P(GLSLTest, InvariantVaryingIn)
+{
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "invariant varying float v_varying;\n"
+        "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "attribute vec4 a_position;\n"
+        "varying float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_EQ(0u, program);
+}
+
+// Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
+TEST_P(GLSLTest_ES3, InvariantVaryingIn)
+{
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "invariant in float v_varying;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in vec4 a_position;\n"
+        "out float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_EQ(0u, program);
+}
+
+// Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
+TEST_P(GLSLTest, InvariantVaryingBoth)
+{
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "invariant varying float v_varying;\n"
+        "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "attribute vec4 a_position;\n"
+        "invariant varying float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
+TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
+{
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "invariant in float v_varying;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in vec4 a_position;\n"
+        "invariant out float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_EQ(0u, program);
+}
+
+// Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
+TEST_P(GLSLTest, InvariantGLPosition)
+{
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "varying float v_varying;\n"
+        "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "attribute vec4 a_position;\n"
+        "invariant gl_Position;\n"
+        "varying float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
+TEST_P(GLSLTest_ES3, InvariantGLPosition)
+{
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in float v_varying;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in vec4 a_position;\n"
+        "invariant gl_Position;\n"
+        "out float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that using invariant(all) in both shaders succeeds in ESSL 1.00.
+TEST_P(GLSLTest, InvariantAllBoth)
+{
+    // TODO: ESSL 1.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
+    // for varyings which are invariant in vertex shader individually,
+    // and remove invariant(all) from fragment shader (http://anglebug.com/1293)
+    if (IsDesktopOpenGL())
+    {
+        std::cout << "Test disabled on OpenGL." << std::endl;
+        return;
+    }
+
+    const std::string fragmentShaderSource =
+        "#pragma STDGL invariant(all)\n"
+        "precision mediump float;\n"
+        "varying float v_varying;\n"
+        "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "#pragma STDGL invariant(all)\n"
+        "attribute vec4 a_position;\n"
+        "varying float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnFloat)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "float f() { if (v_varying > 0.0) return 1.0; }\n"
+        "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnVec2)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
+        "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnVec3)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
+        "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnVec4)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
+        "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnIVec4)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
+        "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnMat4)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
+        "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnStruct)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "struct s { float a; int b; vec2 c; };\n"
+        "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
+        "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest_ES3, MissingReturnArray)
+{
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in float v_varying;\n"
+        "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
+        "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
+{
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in float v_varying;\n"
+        "struct s { float a; int b; vec2 c; };\n"
+        "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
+        "vec2(1.0, 1.0))); } }\n"
+        "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
+{
+    // TODO(cwallez) remove the suppression once NVIDIA removes the restriction for
+    // GLSL >= 300. It was defined only in GLSL 2.0, section 6.1.
+    if (IsNVIDIA() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on NVIDIA OpenGL ES because it disallows returning "
+                     "structure of arrays"
+                  << std::endl;
+        return;
+    }
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in float v_varying;\n"
+        "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
+        "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
+        "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
+        "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that using invariant(all) in both shaders fails in ESSL 3.00.
+TEST_P(GLSLTest_ES3, InvariantAllBoth)
+{
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "#pragma STDGL invariant(all)\n"
+        "precision mediump float;\n"
+        "in float v_varying;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "#pragma STDGL invariant(all)\n"
+        "in vec4 a_position;\n"
+        "out float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_EQ(0u, program);
+}
+
+// Verify that using invariant(all) only in fragment shader fails in ESSL 1.00.
+TEST_P(GLSLTest, InvariantAllIn)
+{
+    const std::string fragmentShaderSource =
+        "#pragma STDGL invariant(all)\n"
+        "precision mediump float;\n"
+        "varying float v_varying;\n"
+        "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "attribute vec4 a_position;\n"
+        "varying float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_EQ(0u, program);
+}
+
+// Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
+TEST_P(GLSLTest_ES3, InvariantAllIn)
+{
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "#pragma STDGL invariant(all)\n"
+        "precision mediump float;\n"
+        "in float v_varying;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in vec4 a_position;\n"
+        "out float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_EQ(0u, program);
+}
+
+// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
+TEST_P(GLSLTest, InvariantAllOut)
+{
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "varying float v_varying;\n"
+        "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "#pragma STDGL invariant(all)\n"
+        "attribute vec4 a_position;\n"
+        "varying float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_EQ(0u, program);
+}
+
+// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
+TEST_P(GLSLTest_ES3, InvariantAllOut)
+{
+    // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
+    // for varyings which are invariant in vertex shader,
+    // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
+    if (IsDesktopOpenGL())
+    {
+        std::cout << "Test disabled on OpenGL." << std::endl;
+        return;
+    }
+
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in float v_varying;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "#pragma STDGL invariant(all)\n"
+        "in vec4 a_position;\n"
+        "out float v_varying;\n"
+        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+TEST_P(GLSLTest, MaxVaryingVec4)
+{
+#if defined(__APPLE__)
+    // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
+    // (http://anglebug.com/1291)
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
+        return;
+    }
+#endif
+
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
+}
+
+TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusTwoSpecialVariables)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    // Generate shader code that uses gl_FragCoord and gl_PointCoord, two special fragment shader variables.
+    VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
+}
+
+TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusThreeSpecialVariables)
+{
+    // TODO(geofflang): Figure out why this fails on OpenGL AMD (http://anglebug.com/1291)
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test disabled on OpenGL." << std::endl;
+        return;
+    }
+
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
+    VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, true, true);
+}
+
+TEST_P(GLSLTest, MaxVaryingVec3)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
+}
+
+TEST_P(GLSLTest, MaxVaryingVec3Array)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
+}
+
+// Disabled because of a failure in D3D9
+TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
+{
+    if (IsD3D9())
+    {
+        std::cout << "Test disabled on D3D9." << std::endl;
+        return;
+    }
+
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
+}
+
+// Disabled because of a failure in D3D9
+TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
+{
+    if (IsD3D9())
+    {
+        std::cout << "Test disabled on D3D9." << std::endl;
+        return;
+    }
+
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
+}
+
+// Disabled because of a failure in D3D9
+TEST_P(GLSLTest, TwiceMaxVaryingVec2)
+{
+    if (IsD3D9())
+    {
+        std::cout << "Test disabled on D3D9." << std::endl;
+        return;
+    }
+
+    if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+    {
+        // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
+        std::cout << "Test disabled on OpenGL ES." << std::endl;
+        return;
+    }
+
+#if defined(__APPLE__)
+    // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
+    // (http://anglebug.com/1291)
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
+        return;
+    }
+#endif
+
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, true);
+}
+
+// Disabled because of a failure in D3D9
+TEST_P(GLSLTest, MaxVaryingVec2Arrays)
+{
+    if (IsD3DSM3())
+    {
+        std::cout << "Test disabled on SM3." << std::endl;
+        return;
+    }
+
+    if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+    {
+        // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
+        std::cout << "Test disabled on OpenGL ES." << std::endl;
+        return;
+    }
+
+#if defined(__APPLE__)
+    // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
+    // (http://anglebug.com/1291)
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
+        return;
+    }
+#endif
+
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
+    // we should be aware that when we're packing into an odd number of varying registers the
+    // last row will be empty and can not fit the final vec2 arrary.
+    GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
+
+    VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
+}
+
+// Verify shader source with a fixed length that is less than the null-terminated length will compile.
+TEST_P(GLSLTest, FixedShaderLength)
+{
+    GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
+
+    const std::string appendGarbage = "abcasdfasdfasdfasdfasdf";
+    const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
+    const char *sourceArray[1] = { source.c_str() };
+    GLint lengths[1] = { static_cast<GLint>(source.length() - appendGarbage.length()) };
+    glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+    EXPECT_NE(compileResult, 0);
+}
+
+// Verify that a negative shader source length is treated as a null-terminated length.
+TEST_P(GLSLTest, NegativeShaderLength)
+{
+    GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
+
+    const char *sourceArray[1] = { "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" };
+    GLint lengths[1] = { -10 };
+    glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+    EXPECT_NE(compileResult, 0);
+}
+
+// Check that having an invalid char after the "." doesn't cause an assert.
+TEST_P(GLSLTest, InvalidFieldFirstChar)
+{
+    GLuint shader      = glCreateShader(GL_VERTEX_SHADER);
+    const char *source = "void main() {vec4 x; x.}";
+    glShaderSource(shader, 1, &source, 0);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+    EXPECT_EQ(0, compileResult);
+}
+
+// Verify that a length array with mixed positive and negative values compiles.
+TEST_P(GLSLTest, MixedShaderLengths)
+{
+    GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
+
+    const char *sourceArray[] =
+    {
+        "void main()",
+        "{",
+        "    gl_FragColor = vec4(0, 0, 0, 0);",
+        "}",
+    };
+    GLint lengths[] =
+    {
+        -10,
+        1,
+        static_cast<GLint>(strlen(sourceArray[2])),
+        -1,
+    };
+    ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
+
+    glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+    EXPECT_NE(compileResult, 0);
+}
+
+// Verify that zero-length shader source does not affect shader compilation.
+TEST_P(GLSLTest, ZeroShaderLength)
+{
+    GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
+
+    const char *sourceArray[] =
+    {
+        "adfasdf",
+        "34534",
+        "void main() { gl_FragColor = vec4(0, 0, 0, 0); }",
+        "",
+        "asdfasdfsdsdf",
+    };
+    GLint lengths[] =
+    {
+        0,
+        0,
+        -1,
+        0,
+        0,
+    };
+    ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
+
+    glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+    EXPECT_NE(compileResult, 0);
+}
+
+// Tests that bad index expressions don't crash ANGLE's translator.
+// https://code.google.com/p/angleproject/issues/detail?id=857
+TEST_P(GLSLTest, BadIndexBug)
+{
+    const std::string &fragmentShaderSourceVec =
+        "precision mediump float;\n"
+        "uniform vec4 uniformVec;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(uniformVec[int()]);\n"
+        "}";
+
+    GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceVec);
+    EXPECT_EQ(0u, shader);
+
+    if (shader != 0)
+    {
+        glDeleteShader(shader);
+    }
+
+    const std::string &fragmentShaderSourceMat =
+        "precision mediump float;\n"
+        "uniform mat4 uniformMat;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(uniformMat[int()]);\n"
+        "}";
+
+    shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceMat);
+    EXPECT_EQ(0u, shader);
+
+    if (shader != 0)
+    {
+        glDeleteShader(shader);
+    }
+
+    const std::string &fragmentShaderSourceArray =
+        "precision mediump float;\n"
+        "uniform vec4 uniformArray;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(uniformArray[int()]);\n"
+        "}";
+
+    shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceArray);
+    EXPECT_EQ(0u, shader);
+
+    if (shader != 0)
+    {
+        glDeleteShader(shader);
+    }
+}
+
+// Test that structs defined in uniforms are translated correctly.
+TEST_P(GLSLTest, StructSpecifiersUniforms)
+{
+    const std::string fragmentShaderSource = SHADER_SOURCE
+    (
+        precision mediump float;
+
+        uniform struct S { float field;} s;
+
+        void main()
+        {
+            gl_FragColor = vec4(1, 0, 0, 1);
+            gl_FragColor.a += s.field;
+        }
+    );
+
+    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Test that gl_DepthRange is not stored as a uniform location. Since uniforms
+// beginning with "gl_" are filtered out by our validation logic, we must
+// bypass the validation to test the behaviour of the implementation.
+// (note this test is still Impl-independent)
+TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
+{
+    const std::string fragmentShaderSource = SHADER_SOURCE
+    (
+        precision mediump float;
+
+        void main()
+        {
+            gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
+        }
+    );
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
+
+    // We need to bypass validation for this call.
+    GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
+    EXPECT_EQ(-1, nearIndex);
+
+    // Test drawing does not throw an exception.
+    drawQuad(program.get(), "inputAttribute", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+std::string GenerateSmallPowShader(double base, double exponent)
+{
+    std::stringstream stream;
+
+    stream.precision(8);
+
+    double result = pow(base, exponent);
+
+    stream << "precision highp float;\n"
+           << "float fun(float arg)\n"
+           << "{\n"
+           << "    return pow(arg, " << std::fixed << exponent << ");\n"
+           << "}\n"
+           << "\n"
+           << "void main()\n"
+           << "{\n"
+           << "    const float a = " << std::scientific << base << ";\n"
+           << "    float b = fun(a);\n"
+           << "    if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
+           << "    {\n"
+           << "        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+           << "    }\n"
+           << "    else\n"
+           << "    {\n"
+           << "        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
+           << "    }\n"
+           << "}\n";
+
+    return stream.str();
+}
+
+// Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
+// See http://anglebug.com/851
+TEST_P(GLSLTest, PowOfSmallConstant)
+{
+    std::vector<double> bads;
+    for (int eps = -1; eps <= 1; ++eps)
+    {
+        for (int i = -4; i <= 5; ++i)
+        {
+            if (i >= -1 && i <= 1)
+                continue;
+            const double epsilon = 1.0e-8;
+            double bad           = static_cast<double>(i) + static_cast<double>(eps) * epsilon;
+            bads.push_back(bad);
+        }
+    }
+
+    for (double bad : bads)
+    {
+        const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, bad);
+
+        ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
+
+        drawQuad(program.get(), "inputAttribute", 0.5f);
+
+        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+        EXPECT_GL_NO_ERROR();
+    }
+}
+
+// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
+// below
+// fail with a specific error message.
+// Additionally test that the same fragment shader compiles successfully with feature levels greater
+// than FL9_3.
+TEST_P(GLSLTest, LoopIndexingValidation)
+{
+    const std::string fragmentShaderSource = SHADER_SOURCE
+    (
+        precision mediump float;
+
+        uniform float loopMax;
+
+        void main()
+        {
+            gl_FragColor = vec4(1, 0, 0, 1);
+            for (float l = 0.0; l < loopMax; l++)
+            {
+                if (loopMax > 3.0)
+                {
+                    gl_FragColor.a += 0.1;
+                }
+            }
+        }
+    );
+
+    GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
+
+    const char *sourceArray[1] = {fragmentShaderSource.c_str()};
+    glShaderSource(shader, 1, sourceArray, nullptr);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+
+    // If the test is configured to run limited to Feature Level 9_3, then it is
+    // assumed that shader compilation will fail with an expected error message containing
+    // "Loop index cannot be compared with non-constant expression"
+    if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
+    {
+        if (compileResult != 0)
+        {
+            FAIL() << "Shader compilation succeeded, expected failure";
+        }
+        else
+        {
+            GLint infoLogLength;
+            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+            std::string infoLog;
+            infoLog.resize(infoLogLength);
+            glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
+
+            if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
+                std::string::npos)
+            {
+                FAIL() << "Shader compilation failed with unexpected error message";
+            }
+        }
+    }
+    else
+    {
+        EXPECT_NE(0, compileResult);
+    }
+
+    if (shader != 0)
+    {
+        glDeleteShader(shader);
+    }
+}
+
+// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
+// can actually be used.
+TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
+{
+    if (IsLinux() && IsIntel())
+    {
+        std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
+        return;
+    }
+
+    int maxUniforms = 10000;
+    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
+    EXPECT_GL_NO_ERROR();
+    std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
+
+    CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
+}
+
+// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
+// can actually be used along with the maximum number of texture samplers.
+TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
+{
+    if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
+        GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+    {
+        std::cout << "Test disabled on OpenGL." << std::endl;
+        return;
+    }
+
+    int maxUniforms = 10000;
+    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
+    EXPECT_GL_NO_ERROR();
+    std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
+
+    int maxTextureImageUnits = 0;
+    glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
+
+    CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
+}
+
+// Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
+// fails shader compilation.
+TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
+{
+    int maxUniforms = 10000;
+    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
+    EXPECT_GL_NO_ERROR();
+    std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
+
+    CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
+}
+
+// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
+// can actually be used.
+TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
+{
+    if (IsLinux() && IsIntel())
+    {
+        std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
+        return;
+    }
+
+    int maxUniforms = 10000;
+    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
+    EXPECT_GL_NO_ERROR();
+    std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
+
+    CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
+}
+
+// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
+// can actually be used along with the maximum number of texture samplers.
+TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
+{
+    if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
+        GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+    {
+        std::cout << "Test disabled on OpenGL." << std::endl;
+        return;
+    }
+
+    int maxUniforms = 10000;
+    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
+    EXPECT_GL_NO_ERROR();
+
+    int maxTextureImageUnits = 0;
+    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
+
+    CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
+}
+
+// Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
+// fails shader compilation.
+TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
+{
+    int maxUniforms = 10000;
+    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
+    EXPECT_GL_NO_ERROR();
+    std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
+              << std::endl;
+
+    CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
+}
+
+// Test compiling shaders using the GL_EXT_shader_texture_lod extension
+TEST_P(GLSLTest, TextureLOD)
+{
+    if (!extensionEnabled("GL_EXT_shader_texture_lod"))
+    {
+        std::cout << "Test skipped due to missing GL_EXT_shader_texture_lod." << std::endl;
+        return;
+    }
+
+    const std::string source =
+        "#extension GL_EXT_shader_texture_lod : require\n"
+        "uniform sampler2D u_texture;\n"
+        "void main() {\n"
+        "    gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
+        "0.0));\n"
+        "}\n";
+
+    GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
+    ASSERT_NE(0u, shader);
+    glDeleteShader(shader);
+}
+
+// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
+// HLSL).
+TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
+{
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "in vec4 a_vec;\n"
+        "in mat2 a_mat;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_vec) + vec4(a_mat);\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
+// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
+// the function signatures in this case.
+TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
+{
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "in mat3x2 a_matA;\n"
+        "in mat2x3 a_matB;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_matA) + vec4(a_matB);\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
+TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
+{
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}";
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "in vec4 a_vec;\n"
+        "in mat2 a_mat;\n"
+        "vec4 foo(vec4 a)\n"
+        "{\n"
+        "    return a;\n"
+        "}\n"
+        "vec4 foo(mat2 a)\n"
+        "{\n"
+        "    return vec4(a[0][0]);\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = foo(a_vec) + foo(a_mat);\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Test that an user-defined function with a large number of float4 parameters doesn't fail due to
+// the function name being too long.
+TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
+{
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(0.0);\n"
+        "}";
+
+    std::stringstream vertexShaderStream;
+    const unsigned int paramCount = 1024u;
+
+    vertexShaderStream << "#version 300 es\n"
+                          "precision highp float;\n"
+                          "in vec4 a_vec;\n"
+                          "vec4 lotsOfVec4Parameters(";
+    for (unsigned int i = 0; i < paramCount; ++i)
+    {
+        vertexShaderStream << "vec4 a" << i << ", ";
+    }
+    vertexShaderStream << "vec4 aLast)\n"
+                          "{\n"
+                          "    return ";
+    for (unsigned int i = 0; i < paramCount; ++i)
+    {
+        vertexShaderStream << "a" << i << " + ";
+    }
+    vertexShaderStream << "aLast;\n"
+                          "}\n"
+                          "void main()\n"
+                          "{\n"
+                          "    gl_Position = lotsOfVec4Parameters(";
+    for (unsigned int i = 0; i < paramCount; ++i)
+    {
+        vertexShaderStream << "a_vec, ";
+    }
+    vertexShaderStream << "a_vec);\n"
+                          "}";
+
+    GLuint program = CompileProgram(vertexShaderStream.str(), fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// This test was written specifically to stress DeferGlobalInitializers AST transformation.
+// Test a shader where a global constant array is initialized with an expression containing array
+// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
+// be handled in a way that doesn't generate statements in the global scope in HLSL output.
+// Also includes multiple array initializers in one declaration, where only the second one has
+// array indexing. This makes sure that the qualifier for the declaration is set correctly if
+// transformations are applied to the declaration also in the case of ESSL output.
+TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
+{
+    // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
+    if (IsAndroid() && IsAdreno() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
+        return;
+    }
+
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "in vec4 a_vec;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_vec);\n"
+        "}";
+
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "out vec4 my_FragColor;\n"
+        "const highp float f[2] = float[2](0.1, 0.2);\n"
+        "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(h[1]);\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Test that index-constant sampler array indexing is supported.
+TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
+{
+    if (IsD3D11_FL93()) {
+        std::cout << "Test skipped on D3D11 FL 9.3." << std::endl;
+        return;
+    }
+
+    const std::string vertexShaderSource =
+        "attribute vec4 vPosition;\n"
+        "void main()\n"
+        "{\n"
+        "      gl_Position = vPosition;\n"
+        "}";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "uniform sampler2D uni[2];\n"
+        "\n"
+        "float zero(int x)\n"
+        "{\n"
+        "    return float(x) - float(x);\n"
+        "}\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    vec4 c = vec4(0,0,0,0);\n"
+        "    for (int ii = 1; ii < 3; ++ii) {\n"
+        "        if (c.x > 255.0) {\n"
+        "            c.x = 255.0 + zero(ii);\n"
+        "            break;\n"
+        "        }\n"
+        // Index the sampler array with a predictable loop index (index-constant) as opposed to
+        // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
+        // without an extension.
+        "        c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
+        "    }\n"
+        "    gl_FragColor = c;\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
+// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
+// want to test its behavior, so don't use any varyings.
+TEST_P(GLSLTest, PragmaDirective)
+{
+    const std::string vertexShaderSource =
+        "#pragma STDGL invariant(all)\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
+// The function call that returns the array needs to be evaluated after ++j for the expression to
+// return the correct value (true).
+TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
+{
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor; \n"
+        "int[2] func(int param) {\n"
+        "    return int[2](param, param);\n"
+        "}\n"
+        "void main() {\n"
+        "    int a[2]; \n"
+        "    for (int i = 0; i < 2; ++i) {\n"
+        "        a[i] = 1;\n"
+        "    }\n"
+        "    int j = 0; \n"
+        "    bool result = ((++j), (a == func(j)));\n"
+        "    my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
+        "}\n";
+
+    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    ASSERT_NE(0u, program);
+
+    drawQuad(program, "inputAttribute", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
+// The short-circuiting expression needs to be evaluated after ++j for the expression to return the
+// correct value (true).
+TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
+{
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor; \n"
+        "void main() {\n"
+        "    int j = 0; \n"
+        "    bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
+        "    my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
+        "}\n";
+
+    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    ASSERT_NE(0u, program);
+
+    drawQuad(program, "inputAttribute", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
+// Indexing the vector needs to be evaluated after func() for the right result.
+TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
+{
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform int u_zero;\n"
+        "int sideEffectCount = 0;\n"
+        "float func() {\n"
+        "    ++sideEffectCount;\n"
+        "    return -1.0;\n"
+        "}\n"
+        "void main() {\n"
+        "    vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
+        "    float f = (func(), (++v[u_zero + sideEffectCount]));\n"
+        "    bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
+        "    my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
+        "}\n";
+
+    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    ASSERT_NE(0u, program);
+
+    drawQuad(program, "inputAttribute", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
+// From WebGL test conformance/rendering/point-specific-shader-variables.html
+// See http://anglebug.com/1380
+TEST_P(GLSLTest, RenderTrisWithPointCoord)
+{
+    const std::string &vert =
+        "attribute vec2 aPosition;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(aPosition, 0, 1);\n"
+        "    gl_PointSize = 1.0;\n"
+        "}";
+    const std::string &frag =
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
+        "    gl_FragColor = vec4(0, 1, 0, 1);\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(prog, vert, frag);
+    drawQuad(prog.get(), "aPosition", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Convers a bug with the integer pow statement workaround.
+TEST_P(GLSLTest, NestedPowStatements)
+{
+    const std::string &vert =
+        "attribute vec2 position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "}";
+    const std::string &frag =
+        "precision mediump float;\n"
+        "float func(float v)\n"
+        "{\n"
+        "   float f1 = pow(v, 2.0);\n"
+        "   return pow(f1 + v, 2.0);\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "    float v = func(2.0);\n"
+        "    gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(prog, vert, frag);
+    drawQuad(prog.get(), "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that -float calculation is correct.
+TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
+{
+    const std::string &vert =
+        "#version 300 es\n"
+        "in highp vec4 position;\n"
+        "void main() {\n"
+        "    gl_Position = position;\n"
+        "}\n";
+    const std::string &frag =
+        "#version 300 es\n"
+        "out highp vec4 o_color;\n"
+        "void main() {\n"
+        "    highp float f = -1.0;\n"
+        "    // atan(tan(0.5), -f) should be 0.5.\n"
+        "    highp float v = atan(tan(0.5), -f);\n"
+        "    o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(prog, vert, frag);
+    drawQuad(prog.get(), "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that atan(vec2, vec2) calculation is correct.
+TEST_P(GLSLTest_ES3, AtanVec2)
+{
+    const std::string &vert =
+        "#version 300 es\n"
+        "in highp vec4 position;\n"
+        "void main() {\n"
+        "    gl_Position = position;\n"
+        "}\n";
+    const std::string &frag =
+        "#version 300 es\n"
+        "out highp vec4 o_color;\n"
+        "void main() {\n"
+        "    highp float f = 1.0;\n"
+        "    // atan(tan(0.5), f) should be 0.5.\n"
+        "    highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
+        "    o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
+        "vec4(1, 0, 0, 1);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(prog, vert, frag);
+    drawQuad(prog.get(), "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Convers a bug with the unary minus operator on signed integer workaround.
+TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
+{
+    const std::string &vert =
+        "#version 300 es\n"
+        "in highp vec4 position;\n"
+        "out mediump vec4 v_color;\n"
+        "uniform int ui_one;\n"
+        "uniform int ui_two;\n"
+        "uniform int ui_three;\n"
+        "void main() {\n"
+        "    int s[3];\n"
+        "    s[0] = ui_one;\n"
+        "    s[1] = -(-(-ui_two + 1) + 1);\n"  // s[1] = -ui_two
+        "    s[2] = ui_three;\n"
+        "    int result = 0;\n"
+        "    for (int i = 0; i < ui_three; i++) {\n"
+        "        result += s[i];\n"
+        "    }\n"
+        "    v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
+        "    gl_Position = position;\n"
+        "}\n";
+    const std::string &frag =
+        "#version 300 es\n"
+        "in mediump vec4 v_color;\n"
+        "layout(location=0) out mediump vec4 o_color;\n"
+        "void main() {\n"
+        "    o_color = v_color;\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(prog, vert, frag);
+
+    GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
+    ASSERT_NE(-1, oneIndex);
+    GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
+    ASSERT_NE(-1, twoIndex);
+    GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
+    ASSERT_NE(-1, threeIndex);
+    glUseProgram(prog.get());
+    glUniform1i(oneIndex, 1);
+    glUniform1i(twoIndex, 2);
+    glUniform1i(threeIndex, 3);
+
+    drawQuad(prog.get(), "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Convers a bug with the unary minus operator on unsigned integer workaround.
+TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
+{
+    const std::string &vert =
+        "#version 300 es\n"
+        "in highp vec4 position;\n"
+        "out mediump vec4 v_color;\n"
+        "uniform uint ui_one;\n"
+        "uniform uint ui_two;\n"
+        "uniform uint ui_three;\n"
+        "void main() {\n"
+        "    uint s[3];\n"
+        "    s[0] = ui_one;\n"
+        "    s[1] = -(-(-ui_two + 1u) + 1u);\n"  // s[1] = -ui_two
+        "    s[2] = ui_three;\n"
+        "    uint result = 0u;\n"
+        "    for (uint i = 0u; i < ui_three; i++) {\n"
+        "        result += s[i];\n"
+        "    }\n"
+        "    v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
+        "    gl_Position = position;\n"
+        "}\n";
+    const std::string &frag =
+        "#version 300 es\n"
+        "in mediump vec4 v_color;\n"
+        "layout(location=0) out mediump vec4 o_color;\n"
+        "void main() {\n"
+        "    o_color = v_color;\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(prog, vert, frag);
+
+    GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
+    ASSERT_NE(-1, oneIndex);
+    GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
+    ASSERT_NE(-1, twoIndex);
+    GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
+    ASSERT_NE(-1, threeIndex);
+    glUseProgram(prog.get());
+    glUniform1ui(oneIndex, 1u);
+    glUniform1ui(twoIndex, 2u);
+    glUniform1ui(threeIndex, 3u);
+
+    drawQuad(prog.get(), "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test a nested sequence operator with a ternary operator inside. The ternary operator is
+// intended to be such that it gets converted to an if statement on the HLSL backend.
+TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
+{
+    const std::string &vert =
+        "attribute vec2 position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "}";
+
+    // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
+    // its default value false.
+    const std::string &frag =
+        "precision mediump float;\n"
+        "uniform bool keep_flop_positive;\n"
+        "float flop;\n"
+        "void main() {\n"
+        "    flop = -1.0,\n"
+        "    (flop *= -1.0,\n"
+        "    keep_flop_positive ? 0.0 : flop *= -1.0),\n"
+        "    gl_FragColor = vec4(0, -flop, 0, 1);\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(prog, vert, frag);
+    drawQuad(prog.get(), "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
+TEST_P(GLSLTest, ExternalAnd2DSampler)
+{
+    if (!extensionEnabled("GL_OES_EGL_image_external"))
+    {
+        std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
+                  << std::endl;
+        return;
+    }
+
+    const std::string fragmentShader =
+        "precision mediump float;\n"
+        "uniform samplerExternalOES tex0;\n"
+        "uniform sampler2D tex1;\n"
+        "void main(void)\n"
+        "{\n"
+        " vec2 uv = vec2(0.0, 0.0);"
+        " gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+}
+
+// Test that literal infinity can be written out from the shader translator.
+// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
+TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
+{
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "out vec4 out_color;\n"
+        "uniform float u;\n"
+        "void main()\n"
+        "{\n"
+        "   float infVar = 1.0e40 - u;\n"
+        "   bool correct = isinf(infVar) && infVar > 0.0;\n"
+        "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    drawQuad(program.get(), "inputAttribute", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that literal negative infinity can be written out from the shader translator.
+// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
+TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
+{
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "out vec4 out_color;\n"
+        "uniform float u;\n"
+        "void main()\n"
+        "{\n"
+        "   float infVar = -1.0e40 + u;\n"
+        "   bool correct = isinf(infVar) && infVar < 0.0;\n"
+        "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    drawQuad(program.get(), "inputAttribute", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
+// passes. Because the interaction of multiple passes must be tested, it is difficult to write
+// a unittest for them. Instead we add the tests as end2end so will in particular test
+// TranslatorHLSL when run on Windows.
+
+// Test that passes splitting multiple declarations and comma operators are correctly ordered.
+TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
+{
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 color;\n"
+        "void main(void)\n"
+        "{\n"
+        " float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : 0.0), 1.0);\n"
+        " color = vec4(b);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+}
+
+// Test that passes splitting multiple declarations and comma operators and for loops are
+// correctly ordered.
+TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
+{
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 color;\n"
+        "void main(void)\n"
+        "{\n"
+        " for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : 0.0), 1.0); a < 10.0; a++)\n"
+        " {\n"
+        "  b += 1.0;\n"
+        "  color = vec4(b);\n"
+        " }\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+}
+
+// Test that splitting multiple declaration in for loops works with no loop condition
+TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
+{
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 color;\n"
+        "void main(void)\n"
+        "{\n"
+        " for(float a = 0.0, b = 1.0;; a++)\n"
+        " {\n"
+        "  b += 1.0;\n"
+        "  if (a > 10.0) {break;}\n"
+        "  color = vec4(b);\n"
+        " }\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+}
+
+// Test that splitting multiple declaration in for loops works with no loop expression
+TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
+{
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 color;\n"
+        "void main(void)\n"
+        "{\n"
+        " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
+        " {\n"
+        "  b += 1.0;\n"
+        "  a += 1.0;\n"
+        "  color = vec4(b);\n"
+        " }\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+}
+
+// Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
+// correctly.
+TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
+{
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform int u_zero;\n"
+        "void main() {\n"
+        "    mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
+        "    m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
+        "    float f = m[1][1];\n"
+        "    my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    drawQuad(program.get(), "inputAttribute", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+class WebGLGLSLTest : public GLSLTest
+{
+  protected:
+    WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
+};
+
+TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
+    // This test should fail, since we are really using (maxVaryings + 1) varyings.
+    VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
+}
+
+TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
+    // This test should fail, since we are really using (maxVaryings + 1) varyings.
+    VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
+}
+
+TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
+}
+
+TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
+}
+
+TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
+}
+
+TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
+}
+
+TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
+{
+    GLint maxVaryings = 0;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
+                    false);
+}
+
+}  // anonymous namespace
+
+// Test that FindLSB and FindMSB return correct values in their corner cases.
+TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
+{
+    // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
+    if (IsAMD() && IsOpenGL() && IsLinux())
+    {
+        std::cout << "Test skipped on AMD OpenGL Linux" << std::endl;
+        return;
+    }
+
+    const std::string &fragmentShader =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform int u_zero;\n"
+        "void main() {\n"
+        "    if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
+        "    {\n"
+        "        my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "    }\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    drawQuad(program.get(), "inputAttribute", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that writing into a swizzled vector that is dynamically indexed succeeds.
+TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
+{
+    if (IsOpenGL())
+    {
+        // http://anglebug.com/1924
+        std::cout << "Test skipped on all OpenGL configurations because it has incorrect results"
+                  << std::endl;
+        return;
+    }
+
+    // The shader first assigns v.x to v.z (1.0)
+    // Then v.y to v.y (2.0)
+    // Then v.z to v.x (1.0)
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() {\n"
+        "    vec3 v = vec3(1.0, 2.0, 3.0);\n"
+        "    for (int i = 0; i < 3; i++) {\n"
+        "        v.zyx[i] = v[i];\n"
+        "    }\n"
+        "    my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
+        "0, 0, 1);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    drawQuad(program.get(), "inputAttribute", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
+// compiler DLL.
+TEST_P(GLSLTest_ES3, NestedSamplingOperation)
+{
+    // This seems to be bugged on some version of Android. Might not affect the newest versions.
+    // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
+    if (IsAndroid() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Android because of bug with Nexus 5X." << std::endl;
+        return;
+    }
+
+    const std::string &vertexShader =
+        "#version 300 es\n"
+        "out vec2 texCoord;\n"
+        "in vec2 position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "    texCoord = position * 0.5 + vec2(0.5);\n"
+        "}\n";
+
+    const std::string &simpleFragmentShader =
+        "#version 300 es\n"
+        "in mediump vec2 texCoord;\n"
+        "out mediump vec4 fragColor;\n"
+        "void main()\n"
+        "{\n"
+        "    fragColor = vec4(texCoord, 0, 1);\n"
+        "}\n";
+
+    const std::string &nestedFragmentShader =
+        "#version 300 es\n"
+        "uniform mediump sampler2D samplerA;\n"
+        "uniform mediump sampler2D samplerB;\n"
+        "in mediump vec2 texCoord;\n"
+        "out mediump vec4 fragColor;\n"
+        "void main ()\n"
+        "{\n"
+        "    fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(initProg, vertexShader, simpleFragmentShader);
+    ANGLE_GL_PROGRAM(nestedProg, vertexShader, nestedFragmentShader);
+
+    // Initialize a first texture with default texCoord data.
+    GLTexture texA;
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, texA);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
+
+    drawQuad(initProg, "position", 0.5f);
+    ASSERT_GL_NO_ERROR();
+
+    // Initialize a second texture with a simple color pattern.
+    GLTexture texB;
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, texB);
+
+    std::array<GLColor, 4> simpleColors = {
+        {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 simpleColors.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    // Draw with the nested program, using the first texture to index the second.
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glUseProgram(nestedProg);
+    GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
+    ASSERT_NE(-1, samplerALoc);
+    glUniform1i(samplerALoc, 0);
+    GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
+    ASSERT_NE(-1, samplerBLoc);
+    glUniform1i(samplerBLoc, 1);
+
+    drawQuad(nestedProg, "position", 0.5f);
+    ASSERT_GL_NO_ERROR();
+
+    // Compute four texel centers.
+    Vector2 windowSize(getWindowWidth(), getWindowHeight());
+    Vector2 quarterWindowSize = windowSize / 4;
+    Vector2 ul                = quarterWindowSize;
+    Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
+    Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
+    Vector2 lr = windowSize - quarterWindowSize;
+
+    EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
+    EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
+    EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
+    EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
+}
+
+// Tests that using a constant declaration as the only statement in a for loop without curly braces
+// doesn't crash.
+TEST_P(GLSLTest, ConstantStatementInForLoop)
+{
+    const std::string &vertexShader =
+        "void main()\n"
+        "{\n"
+        "    for (int i = 0; i < 10; ++i)\n"
+        "        const int b = 0;\n"
+        "}\n";
+
+    GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
+    EXPECT_NE(0u, shader);
+    glDeleteShader(shader);
+}
+
+// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
+// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
+TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
+{
+    const std::string &vertexShader =
+        "void main()\n"
+        "{\n"
+        "    for (const int i = 0; i < 0;) {}\n"
+        "}\n";
+
+    GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
+    EXPECT_NE(0u, shader);
+    glDeleteShader(shader);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(GLSLTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/ImageTest.cpp b/src/third_party/angle/src/tests/gl_tests/ImageTest.cpp
new file mode 100644
index 0000000..cb88c48
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ImageTest.cpp
@@ -0,0 +1,1973 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ImageTest:
+//   Tests the correctness of eglImage.
+//
+
+#include "test_utils/ANGLETest.h"
+
+namespace angle
+{
+class ImageTest : public ANGLETest
+{
+  protected:
+    ImageTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource =
+            "precision highp float;\n"
+            "attribute vec4 position;\n"
+            "varying vec2 texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "    texcoord.y = 1.0 - texcoord.y;\n"
+            "}\n";
+        const std::string vsESSL3Source =
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "in vec4 position;\n"
+            "out vec2 texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "    texcoord.y = 1.0 - texcoord.y;\n"
+            "}\n";
+
+        const std::string textureFSSource =
+            "precision highp float;\n"
+            "uniform sampler2D tex;\n"
+            "varying vec2 texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = texture2D(tex, texcoord);\n"
+            "}\n";
+        const std::string textureExternalFSSource =
+            "#extension GL_OES_EGL_image_external : require\n"
+            "precision highp float;\n"
+            "uniform samplerExternalOES tex;\n"
+            "varying vec2 texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = texture2D(tex, texcoord);\n"
+            "}\n";
+        const std::string textureExternalESSL3FSSource =
+            "#version 300 es\n"
+            "#extension GL_OES_EGL_image_external_essl3 : require\n"
+            "precision highp float;\n"
+            "uniform samplerExternalOES tex;\n"
+            "in vec2 texcoord;\n"
+            "out vec4 color;"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    color = texture(tex, texcoord);\n"
+            "}\n";
+
+        mTextureProgram = CompileProgram(vsSource, textureFSSource);
+        if (mTextureProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
+
+        if (extensionEnabled("GL_OES_EGL_image_external"))
+        {
+            mTextureExternalProgram = CompileProgram(vsSource, textureExternalFSSource);
+            ASSERT_NE(0u, mTextureExternalProgram) << "shader compilation failed.";
+
+            mTextureExternalUniformLocation = glGetUniformLocation(mTextureExternalProgram, "tex");
+        }
+
+        if (extensionEnabled("GL_OES_EGL_image_external_essl3"))
+        {
+            mTextureExternalESSL3Program =
+                CompileProgram(vsESSL3Source, textureExternalESSL3FSSource);
+            ASSERT_NE(0u, mTextureExternalESSL3Program) << "shader compilation failed.";
+
+            mTextureExternalESSL3UniformLocation =
+                glGetUniformLocation(mTextureExternalESSL3Program, "tex");
+        }
+
+        eglCreateImageKHR =
+            reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
+        eglDestroyImageKHR =
+            reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mTextureProgram);
+        glDeleteProgram(mTextureExternalProgram);
+        glDeleteProgram(mTextureExternalESSL3Program);
+
+        ANGLETest::TearDown();
+    }
+
+    void createEGLImage2DTextureSource(size_t width,
+                                       size_t height,
+                                       GLenum format,
+                                       GLenum type,
+                                       void *data,
+                                       GLuint *outSourceTexture,
+                                       EGLImageKHR *outSourceImage)
+    {
+        // Create a source 2D texture
+        GLuint source;
+        glGenTextures(1, &source);
+        glBindTexture(GL_TEXTURE_2D, source);
+
+        glTexImage2D(GL_TEXTURE_2D, 0, format, static_cast<GLsizei>(width),
+                     static_cast<GLsizei>(height), 0, format, type, data);
+
+        // Disable mipmapping
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        ASSERT_GL_NO_ERROR();
+
+        // Create an image from the source texture
+        EGLWindow *window = getEGLWindow();
+        EGLImageKHR image =
+            eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
+                              reinterpretHelper<EGLClientBuffer>(source), nullptr);
+
+        ASSERT_EGL_SUCCESS();
+
+        *outSourceTexture = source;
+        *outSourceImage   = image;
+    }
+
+    void createEGLImageCubemapTextureSource(size_t width,
+                                            size_t height,
+                                            GLenum format,
+                                            GLenum type,
+                                            uint8_t *data,
+                                            size_t dataStride,
+                                            EGLenum imageTarget,
+                                            GLuint *outSourceTexture,
+                                            EGLImageKHR *outSourceImage)
+    {
+        // Create a source cube map texture
+        GLuint source;
+        glGenTextures(1, &source);
+        glBindTexture(GL_TEXTURE_CUBE_MAP, source);
+
+        for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++)
+        {
+            glTexImage2D(faceIdx + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format,
+                         static_cast<GLsizei>(width), static_cast<GLsizei>(height), 0, format, type,
+                         data + (faceIdx * dataStride));
+        }
+
+        // Disable mipmapping
+        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        ASSERT_GL_NO_ERROR();
+
+        // Create an image from the source texture
+        EGLWindow *window = getEGLWindow();
+        EGLImageKHR image =
+            eglCreateImageKHR(window->getDisplay(), window->getContext(), imageTarget,
+                              reinterpretHelper<EGLClientBuffer>(source), nullptr);
+
+        ASSERT_EGL_SUCCESS();
+
+        *outSourceTexture = source;
+        *outSourceImage   = image;
+    }
+
+    void createEGLImage3DTextureSource(size_t width,
+                                       size_t height,
+                                       size_t depth,
+                                       GLenum format,
+                                       GLenum type,
+                                       void *data,
+                                       size_t imageLayer,
+                                       GLuint *outSourceTexture,
+                                       EGLImageKHR *outSourceImage)
+    {
+        // Create a source 3D texture
+        GLuint source;
+        glGenTextures(1, &source);
+        glBindTexture(GL_TEXTURE_3D, source);
+
+        glTexImage3D(GL_TEXTURE_3D, 0, format, static_cast<GLsizei>(width),
+                     static_cast<GLsizei>(height), static_cast<GLsizei>(depth), 0, format, type,
+                     data);
+
+        // Disable mipmapping
+        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        ASSERT_GL_NO_ERROR();
+
+        // Create an image from the source texture
+        EGLWindow *window = getEGLWindow();
+
+        EGLint attribs[] = {
+            EGL_GL_TEXTURE_ZOFFSET_KHR, static_cast<EGLint>(imageLayer), EGL_NONE,
+        };
+        EGLImageKHR image =
+            eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_3D_KHR,
+                              reinterpretHelper<EGLClientBuffer>(source), attribs);
+
+        ASSERT_EGL_SUCCESS();
+
+        *outSourceTexture = source;
+        *outSourceImage   = image;
+    }
+
+    void createEGLImageRenderbufferSource(size_t width,
+                                          size_t height,
+                                          GLenum internalFormat,
+                                          GLubyte data[4],
+                                          GLuint *outSourceRenderbuffer,
+                                          EGLImageKHR *outSourceImage)
+    {
+        // Create a source renderbuffer
+        GLuint source;
+        glGenRenderbuffers(1, &source);
+        glBindRenderbuffer(GL_RENDERBUFFER, source);
+        glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, static_cast<GLsizei>(width),
+                              static_cast<GLsizei>(height));
+
+        // Create a framebuffer and clear it to set the data
+        GLuint framebuffer;
+        glGenFramebuffers(1, &framebuffer);
+        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, source);
+
+        glClearColor(data[0] / 255.0f, data[1] / 255.0f, data[2] / 255.0f, data[3] / 255.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        glDeleteFramebuffers(1, &framebuffer);
+
+        ASSERT_GL_NO_ERROR();
+
+        // Create an image from the source renderbuffer
+        EGLWindow *window = getEGLWindow();
+        EGLImageKHR image =
+            eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_RENDERBUFFER_KHR,
+                              reinterpretHelper<EGLClientBuffer>(source), nullptr);
+
+        ASSERT_EGL_SUCCESS();
+
+        *outSourceRenderbuffer = source;
+        *outSourceImage        = image;
+    }
+
+    void createEGLImageTargetTexture2D(EGLImageKHR image, GLuint *outTargetTexture)
+    {
+        // Create a target texture from the image
+        GLuint target;
+        glGenTextures(1, &target);
+        glBindTexture(GL_TEXTURE_2D, target);
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
+
+        // Disable mipmapping
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        ASSERT_GL_NO_ERROR();
+
+        *outTargetTexture = target;
+    }
+
+    void createEGLImageTargetTextureExternal(EGLImageKHR image, GLuint *outTargetTexture)
+    {
+        // Create a target texture from the image
+        GLuint target;
+        glGenTextures(1, &target);
+        glBindTexture(GL_TEXTURE_EXTERNAL_OES, target);
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
+
+        // Disable mipmapping
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        ASSERT_GL_NO_ERROR();
+
+        *outTargetTexture = target;
+    }
+
+    void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint *outTargetRenderbuffer)
+    {
+        // Create a target texture from the image
+        GLuint target;
+        glGenRenderbuffers(1, &target);
+        glBindRenderbuffer(GL_RENDERBUFFER, target);
+        glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
+
+        ASSERT_GL_NO_ERROR();
+
+        *outTargetRenderbuffer = target;
+    }
+
+    void verifyResultsTexture(GLuint texture,
+                              GLubyte data[4],
+                              GLenum textureTarget,
+                              GLuint program,
+                              GLuint textureUniform)
+    {
+        // Draw a quad with the target texture
+        glUseProgram(program);
+        glBindTexture(textureTarget, texture);
+        glUniform1i(textureUniform, 0);
+
+        drawQuad(program, "position", 0.5f);
+
+        // Expect that the rendered quad has the same color as the source texture
+        EXPECT_PIXEL_EQ(0, 0, data[0], data[1], data[2], data[3]);
+    }
+
+    void verifyResults2D(GLuint texture, GLubyte data[4])
+    {
+        verifyResultsTexture(texture, data, GL_TEXTURE_2D, mTextureProgram,
+                             mTextureUniformLocation);
+    }
+
+    void verifyResultsExternal(GLuint texture, GLubyte data[4])
+    {
+        verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalProgram,
+                             mTextureExternalUniformLocation);
+    }
+
+    void verifyResultsExternalESSL3(GLuint texture, GLubyte data[4])
+    {
+        verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalESSL3Program,
+                             mTextureExternalESSL3UniformLocation);
+    }
+
+    void verifyResultsRenderbuffer(GLuint renderbuffer, GLubyte data[4])
+    {
+        // Bind the renderbuffer to a framebuffer
+        GLuint framebuffer;
+        glGenFramebuffers(1, &framebuffer);
+        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                                  renderbuffer);
+
+        // Expect that the rendered quad has the same color as the source texture
+        EXPECT_PIXEL_EQ(0, 0, data[0], data[1], data[2], data[3]);
+
+        glDeleteFramebuffers(1, &framebuffer);
+    }
+
+    template <typename destType, typename sourcetype>
+    destType reinterpretHelper(sourcetype source)
+    {
+        static_assert(sizeof(destType) == sizeof(size_t),
+                      "destType should be the same size as a size_t");
+        size_t sourceSizeT = static_cast<size_t>(source);
+        return reinterpret_cast<destType>(sourceSizeT);
+    }
+
+    GLuint mTextureProgram;
+    GLint mTextureUniformLocation;
+
+    GLuint mTextureExternalProgram        = 0;
+    GLint mTextureExternalUniformLocation = -1;
+
+    GLuint mTextureExternalESSL3Program        = 0;
+    GLint mTextureExternalESSL3UniformLocation = -1;
+
+    PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
+    PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
+};
+
+class ImageTestES3 : public ImageTest
+{
+};
+
+// Check validation from the EGL_KHR_image_base extension
+TEST_P(ImageTest, ValidationImageBase)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLuint glTexture2D;
+    glGenTextures(1, &glTexture2D);
+    glBindTexture(GL_TEXTURE_2D, glTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    EGLDisplay display        = window->getDisplay();
+    EGLContext context        = window->getContext();
+    EGLConfig config          = window->getConfig();
+    EGLImageKHR image         = EGL_NO_IMAGE_KHR;
+    EGLClientBuffer texture2D = reinterpretHelper<EGLClientBuffer>(glTexture2D);
+
+    // Test validation of eglCreateImageKHR
+
+    // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
+    // generated.
+    image = eglCreateImageKHR(reinterpretHelper<EGLDisplay>(0xBAADF00D), context,
+                              EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
+    EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+    EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
+
+    // If <ctx> is neither the handle of a valid EGLContext object on <dpy> nor EGL_NO_CONTEXT, the
+    // error EGL_BAD_CONTEXT is generated.
+    image = eglCreateImageKHR(display, reinterpretHelper<EGLContext>(0xBAADF00D),
+                              EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
+    EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+    EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
+
+    // Test EGL_NO_CONTEXT with a 2D texture target which does require a context.
+    image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
+    EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+    EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
+
+    // If an attribute specified in <attrib_list> is not one of the attributes listed in Table bbb,
+    // the error EGL_BAD_PARAMETER is generated.
+    EGLint badAttributes[] = {
+        static_cast<EGLint>(0xDEADBEEF), 0, EGL_NONE,
+    };
+
+    image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, badAttributes);
+    EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+    EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+
+    // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> has an off -
+    // screen buffer bound to it(e.g., by a
+    // previous call to eglBindTexImage), the error EGL_BAD_ACCESS is generated.
+    EGLint surfaceType = 0;
+    eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
+
+    EGLint bindToTextureRGBA = 0;
+    eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
+    if ((surfaceType & EGL_PBUFFER_BIT) != 0 && bindToTextureRGBA == EGL_TRUE)
+    {
+        EGLint pbufferAttributes[] = {
+            EGL_WIDTH,          1,
+            EGL_HEIGHT,         1,
+            EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+            EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
+            EGL_NONE,           EGL_NONE,
+        };
+        EGLSurface pbuffer = eglCreatePbufferSurface(display, config, pbufferAttributes);
+        ASSERT_NE(pbuffer, EGL_NO_SURFACE);
+        EXPECT_EGL_SUCCESS();
+
+        eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
+        EXPECT_EGL_SUCCESS();
+
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
+
+        eglReleaseTexImage(display, pbuffer, EGL_BACK_BUFFER);
+        eglDestroySurface(display, pbuffer);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        EXPECT_EGL_SUCCESS();
+        EXPECT_GL_NO_ERROR();
+    }
+
+    // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and
+    // <attrib_list> is itself an EGLImage sibling, the error EGL_BAD_ACCESS is generated.
+    image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
+    EXPECT_NE(image, EGL_NO_IMAGE_KHR);
+    EXPECT_EGL_SUCCESS();
+
+    /* TODO(geofflang): Enable this validation when it passes.
+    EGLImageKHR image2 = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
+    reinterpret_cast<EGLClientBuffer>(texture2D), nullptr);
+    EXPECT_EQ(image2, EGL_NO_IMAGE_KHR);
+    EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
+    */
+
+    // Test validation of eglDestroyImageKHR
+    // Note: image is now a valid EGL image
+    EGLBoolean result = EGL_FALSE;
+
+    // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
+    // generated.
+    result = eglDestroyImageKHR(reinterpretHelper<EGLDisplay>(0xBAADF00D), image);
+    EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
+    EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
+
+    // If <image> is not a valid EGLImageKHR object created with respect to <dpy>, the error
+    // EGL_BAD_PARAMETER is generated.
+    result = eglDestroyImageKHR(display, reinterpretHelper<EGLImageKHR>(0xBAADF00D));
+    EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
+    EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+
+    // Clean up and validate image is destroyed
+    result = eglDestroyImageKHR(display, image);
+    EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_TRUE));
+    EXPECT_EGL_SUCCESS();
+
+    glDeleteTextures(1, &glTexture2D);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Check validation from the EGL_KHR_gl_texture_2D_image extension
+TEST_P(ImageTest, ValidationImagePixmap)
+{
+    // This extension is not implemented anywhere yet.  This makes sure that it is tested once it is
+    // added.
+    EGLWindow *window = getEGLWindow();
+    EXPECT_FALSE(eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_pixmap"));
+}
+
+// Check validation from the EGL_KHR_gl_texture_2D_image, EGL_KHR_gl_texture_cubemap_image,
+// EGL_KHR_gl_texture_3D_image and EGL_KHR_gl_renderbuffer_image extensions
+TEST_P(ImageTest, ValidationGLImage)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base"))
+    {
+        std::cout << "Test skipped because OES_EGL_image or EGL_KHR_image_base is not available."
+                  << std::endl;
+        return;
+    }
+
+    EGLDisplay display = window->getDisplay();
+    EGLContext context = window->getContext();
+    EGLImageKHR image  = EGL_NO_IMAGE_KHR;
+
+    if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR or
+        // EGL_GL_TEXTURE_3D_KHR and <buffer> is not the name of a texture object of type <target>,
+        // the error EGL_BAD_PARAMETER is generated.
+        GLuint textureCube;
+        glGenTextures(1, &textureCube);
+        glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
+        for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+             face++)
+        {
+            glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        }
+
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+
+        // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR,
+        // EGL_GL_TEXTURE_CUBE_MAP_*_KHR or EGL_GL_TEXTURE_3D_KHR, <buffer> is the name of an
+        // incomplete GL texture object, and any mipmap levels other than mipmap level 0 are
+        // specified, the error EGL_BAD_PARAMETER is generated.
+        GLuint incompleteTexture;
+        glGenTextures(1, &incompleteTexture);
+        glBindTexture(GL_TEXTURE_2D, incompleteTexture);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+        EGLint level0Attribute[] = {
+            EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE,
+        };
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(incompleteTexture),
+                                  level0Attribute);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+
+        // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR or
+        // EGL_GL_TEXTURE_3D_KHR, <buffer> is not the name of a complete GL texture object, and
+        // mipmap level 0 is not specified, the error EGL_BAD_PARAMETER is generated.
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(incompleteTexture), nullptr);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+
+        // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR,
+        // EGL_GL_RENDERBUFFER_KHR or EGL_GL_TEXTURE_3D_KHR and <buffer> refers to the default GL
+        // texture object(0) for the corresponding GL target, the error EGL_BAD_PARAMETER is
+        // generated.
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, 0, nullptr);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+
+        // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR, or
+        // EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
+        // EGL_GL_TEXTURE_LEVEL_KHR is not a valid mipmap level for the specified GL texture object
+        // <buffer>, the error EGL_BAD_MATCH is generated.
+        EGLint level2Attribute[] = {
+            EGL_GL_TEXTURE_LEVEL_KHR, 2, EGL_NONE,
+        };
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(incompleteTexture),
+                                  level2Attribute);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+    }
+    else
+    {
+        GLuint texture2D;
+        glGenTextures(1, &texture2D);
+        glBindTexture(GL_TEXTURE_2D, texture2D);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+        // From EGL_KHR_image_base:
+        // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
+        // generated.
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(texture2D), nullptr);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+    }
+
+    if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
+    {
+        // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_CUBE_MAP_*_KHR, <buffer> is
+        // not the name of a complete GL texture object, and one or more faces do not have mipmap
+        // level 0 specified, the error EGL_BAD_PARAMETER is generated.
+        GLuint incompleteTextureCube;
+        glGenTextures(1, &incompleteTextureCube);
+        glBindTexture(GL_TEXTURE_CUBE_MAP, incompleteTextureCube);
+        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+        glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+        glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+
+        EGLint level0Attribute[] = {
+            EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE,
+        };
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(incompleteTextureCube),
+                                  level0Attribute);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+    }
+    else
+    {
+        GLuint textureCube;
+        glGenTextures(1, &textureCube);
+        glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
+        for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+             face++)
+        {
+            glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        }
+
+        // From EGL_KHR_image_base:
+        // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
+        // generated.
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+    }
+
+    if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image") &&
+        getClientMajorVersion() >= 3)
+    {
+        // If <target> is EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
+        // EGL_GL_TEXTURE_ZOFFSET_KHR exceeds the depth of the specified mipmap level - of - detail
+        // in <buffer>, the error EGL_BAD_PARAMETER is generated.
+        GLuint texture3D;
+        glGenTextures(1, &texture3D);
+        glBindTexture(GL_TEXTURE_3D, texture3D);
+        glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+        EGLint zOffset3Parameter[] = {
+            EGL_GL_TEXTURE_ZOFFSET_KHR, 3, EGL_NONE,
+        };
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(texture3D), zOffset3Parameter);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+
+        EGLint zOffsetNegative1Parameter[] = {
+            EGL_GL_TEXTURE_ZOFFSET_KHR, -1, EGL_NONE,
+        };
+        image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(texture3D),
+                                  zOffsetNegative1Parameter);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+    }
+    else
+    {
+        if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+        {
+            GLuint texture2D;
+            glGenTextures(1, &texture2D);
+            glBindTexture(GL_TEXTURE_2D, texture2D);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+            // Verify EGL_GL_TEXTURE_ZOFFSET_KHR is not a valid parameter
+            EGLint zOffset0Parameter[] = {
+                EGL_GL_TEXTURE_ZOFFSET_KHR, 0, EGL_NONE,
+            };
+
+            image =
+                eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(texture2D), zOffset0Parameter);
+            EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+            EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+        }
+
+        if (getClientMajorVersion() >= 3)
+        {
+            GLuint texture3D;
+            glGenTextures(1, &texture3D);
+            glBindTexture(GL_TEXTURE_3D, texture3D);
+            glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+            // From EGL_KHR_image_base:
+            // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
+            // generated.
+            image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
+                                      reinterpretHelper<EGLClientBuffer>(texture3D), nullptr);
+            EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+            EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+        }
+    }
+
+    if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
+    {
+        // If <target> is EGL_GL_RENDERBUFFER_KHR and <buffer> is not the name of a renderbuffer
+        // object, or if <buffer> is the name of a multisampled renderbuffer object, the error
+        // EGL_BAD_PARAMETER is generated.
+        image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
+                                  reinterpret_cast<EGLClientBuffer>(0), nullptr);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+
+        if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
+        {
+            GLuint renderbuffer;
+            glGenRenderbuffers(1, &renderbuffer);
+            glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+            glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
+            EXPECT_GL_NO_ERROR();
+
+            image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
+                                      reinterpret_cast<EGLClientBuffer>(0), nullptr);
+            EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+            EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+        }
+    }
+    else
+    {
+        GLuint renderbuffer;
+        glGenRenderbuffers(1, &renderbuffer);
+        glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
+
+        // From EGL_KHR_image_base:
+        // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
+        // generated.
+        image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
+                                  reinterpretHelper<EGLClientBuffer>(renderbuffer), nullptr);
+        EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
+        EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
+    }
+}
+
+// Check validation from the GL_OES_EGL_image extension
+TEST_P(ImageTest, ValidationGLEGLImage)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte data[4] = {255, 0, 255, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+
+    // If <target> is not TEXTURE_2D, the error INVALID_ENUM is generated.
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_CUBE_MAP_POSITIVE_X, image);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // If <image> does not refer to a valid eglImageOES object, the error INVALID_VALUE is
+    // generated.
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, reinterpretHelper<GLeglImageOES>(0xBAADF00D));
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // <target> must be RENDERBUFFER_OES, and <image> must be the handle of a valid EGLImage
+    // resource, cast into the type
+    // eglImageOES.
+    glEGLImageTargetRenderbufferStorageOES(GL_TEXTURE_2D, image);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // If the GL is unable to create a renderbuffer using the specified eglImageOES, the error
+    // INVALID_OPERATION is generated.If <image>
+    // does not refer to a valid eglImageOES object, the error INVALID_VALUE is generated.
+    GLuint renderbuffer;
+    glGenRenderbuffers(1, &renderbuffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+    glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
+                                           reinterpretHelper<GLeglImageOES>(0xBAADF00D));
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // Clean up
+    glDeleteTextures(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteTextures(1, &texture);
+    glDeleteRenderbuffers(1, &renderbuffer);
+}
+
+// Check validation from the GL_OES_EGL_image_external extension
+TEST_P(ImageTest, ValidationGLEGLImageExternal)
+{
+    if (!extensionEnabled("GL_OES_EGL_image_external"))
+    {
+        std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
+
+    // In the initial state of a TEXTURE_EXTERNAL_OES texture object, the value assigned to
+    // TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER is LINEAR, and the s and t wrap modes are both set
+    // to CLAMP_TO_EDGE
+    auto getTexParam = [](GLenum target, GLenum pname)
+    {
+        GLint value = 0;
+        glGetTexParameteriv(target, pname, &value);
+        EXPECT_GL_NO_ERROR();
+        return value;
+    };
+    EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER));
+    EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER));
+    EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S));
+    EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T));
+
+    // "When <target> is TEXTURE_EXTERNAL_OES only NEAREST and LINEAR are accepted as
+    // TEXTURE_MIN_FILTER, only CLAMP_TO_EDGE is accepted as TEXTURE_WRAP_S and TEXTURE_WRAP_T, and
+    // only FALSE is accepted as GENERATE_MIPMAP. Attempting to set other values for
+    // TEXTURE_MIN_FILTER, TEXTURE_WRAP_S, TEXTURE_WRAP_T, or GENERATE_MIPMAP will result in an
+    // INVALID_ENUM error.
+    GLenum validMinFilters[]{
+        GL_NEAREST, GL_LINEAR,
+    };
+    for (auto minFilter : validMinFilters)
+    {
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    GLenum invalidMinFilters[]{
+        GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR,
+        GL_LINEAR_MIPMAP_NEAREST,
+    };
+    for (auto minFilter : invalidMinFilters)
+    {
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+
+    GLenum validWrapModes[]{
+        GL_CLAMP_TO_EDGE,
+    };
+    for (auto minFilter : validWrapModes)
+    {
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, minFilter);
+        EXPECT_GL_NO_ERROR();
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, minFilter);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    GLenum invalidWrapModes[]{
+        GL_REPEAT, GL_MIRRORED_REPEAT,
+    };
+    for (auto minFilter : invalidWrapModes)
+    {
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, minFilter);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, minFilter);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+
+    // When <target> is set to TEXTURE_EXTERNAL_OES, GenerateMipmap always fails and generates an
+    // INVALID_ENUM error.
+    glGenerateMipmap(GL_TEXTURE_EXTERNAL_OES);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    glDeleteTextures(1, &texture);
+}
+
+// Check validation from the GL_OES_EGL_image_external_essl3 extension
+TEST_P(ImageTest, ValidationGLEGLImageExternalESSL3)
+{
+    if (!extensionEnabled("GL_OES_EGL_image_external_essl3"))
+    {
+        std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
+                  << std::endl;
+        return;
+    }
+
+    // Make sure this extension is not exposed without ES3.
+    ASSERT_GE(getClientMajorVersion(), 3);
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
+
+    // It is an INVALID_OPERATION error to set the TEXTURE_BASE_LEVEL to a value other than zero.
+    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 1);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 10);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 0);
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteTextures(1, &texture);
+}
+
+TEST_P(ImageTest, Source2DTarget2D)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte data[4] = {255, 0, 255, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetTexture2D(image, &target);
+
+    // Expect that the target texture has the same color as the source texture
+    verifyResults2D(target, data);
+
+    // Clean up
+    glDeleteTextures(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteTextures(1, &target);
+}
+
+TEST_P(ImageTest, Source2DTargetRenderbuffer)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte data[4] = {255, 0, 255, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetRenderbuffer(image, &target);
+
+    // Expect that the target renderbuffer has the same color as the source texture
+    verifyResultsRenderbuffer(target, data);
+
+    // Clean up
+    glDeleteTextures(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteRenderbuffers(1, &target);
+}
+
+TEST_P(ImageTest, Source2DTargetExternal)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout
+            << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
+               "EGL_KHR_gl_texture_2D_image is not available."
+            << std::endl;
+        return;
+    }
+
+    GLubyte data[4] = {255, 0, 255, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetTextureExternal(image, &target);
+
+    // Expect that the target renderbuffer has the same color as the source texture
+    verifyResultsExternal(target, data);
+
+    // Clean up
+    glDeleteTextures(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteRenderbuffers(1, &target);
+}
+
+TEST_P(ImageTestES3, Source2DTargetExternalESSL3)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, OES_EGL_image_external_essl3, "
+                     "EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte data[4] = {255, 0, 255, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetTextureExternal(image, &target);
+
+    // Expect that the target renderbuffer has the same color as the source texture
+    verifyResultsExternalESSL3(target, data);
+
+    // Clean up
+    glDeleteTextures(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteRenderbuffers(1, &target);
+}
+
+TEST_P(ImageTest, SourceCubeTarget2D)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_cubemap_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte data[24] = {
+        255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
+        0,   0, 255, 255, 0,   255, 0,   255, 0,   0, 0, 255,
+    };
+
+    for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
+    {
+        // Create the Image
+        GLuint source;
+        EGLImageKHR image;
+        createEGLImageCubemapTextureSource(
+            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
+            EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
+
+        // Create the target
+        GLuint target;
+        createEGLImageTargetTexture2D(image, &target);
+
+        // Expect that the target texture has the same color as the source texture
+        verifyResults2D(target, &data[faceIdx * 4]);
+
+        // Clean up
+        glDeleteTextures(1, &source);
+        eglDestroyImageKHR(window->getDisplay(), image);
+        glDeleteTextures(1, &target);
+    }
+}
+
+TEST_P(ImageTest, SourceCubeTargetRenderbuffer)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_cubemap_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte data[24] = {
+        255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
+        0,   0, 255, 255, 0,   255, 0,   255, 0,   0, 0, 255,
+    };
+
+    for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
+    {
+        // Create the Image
+        GLuint source;
+        EGLImageKHR image;
+        createEGLImageCubemapTextureSource(
+            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
+            EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
+
+        // Create the target
+        GLuint target;
+        createEGLImageTargetRenderbuffer(image, &target);
+
+        // Expect that the target texture has the same color as the source texture
+        verifyResultsRenderbuffer(target, &data[faceIdx * 4]);
+
+        // Clean up
+        glDeleteTextures(1, &source);
+        eglDestroyImageKHR(window->getDisplay(), image);
+        glDeleteRenderbuffers(1, &target);
+    }
+}
+
+// Test cubemap -> external texture EGL images.
+TEST_P(ImageTest, SourceCubeTargetExternal)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
+    {
+        std::cout
+            << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
+               "EGL_KHR_gl_texture_cubemap_image is not available."
+            << std::endl;
+        return;
+    }
+
+    GLubyte data[24] = {
+        255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
+        0,   0, 255, 255, 0,   255, 0,   255, 0,   0, 0, 255,
+    };
+
+    for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
+    {
+        // Create the Image
+        GLuint source;
+        EGLImageKHR image;
+        createEGLImageCubemapTextureSource(
+            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
+            EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
+
+        // Create the target
+        GLuint target;
+        createEGLImageTargetTextureExternal(image, &target);
+
+        // Expect that the target texture has the same color as the source texture
+        verifyResultsExternal(target, &data[faceIdx * 4]);
+
+        // Clean up
+        glDeleteTextures(1, &source);
+        eglDestroyImageKHR(window->getDisplay(), image);
+        glDeleteRenderbuffers(1, &target);
+    }
+}
+
+// Test cubemap -> external texture EGL images using ESSL3 shaders.
+TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, OES_EGL_image_external_essl3, "
+                     "EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_cubemap_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte data[24] = {
+        255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
+        0,   0, 255, 255, 0,   255, 0,   255, 0,   0, 0, 255,
+    };
+
+    for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
+    {
+        // Create the Image
+        GLuint source;
+        EGLImageKHR image;
+        createEGLImageCubemapTextureSource(
+            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
+            EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
+
+        // Create the target
+        GLuint target;
+        createEGLImageTargetTextureExternal(image, &target);
+
+        // Expect that the target texture has the same color as the source texture
+        verifyResultsExternalESSL3(target, &data[faceIdx * 4]);
+
+        // Clean up
+        glDeleteTextures(1, &source);
+        eglDestroyImageKHR(window->getDisplay(), image);
+        glDeleteRenderbuffers(1, &target);
+    }
+}
+
+TEST_P(ImageTest, Source3DTargetTexture)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_3D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
+    {
+        std::cout << "Test skipped because 3D textures are not available." << std::endl;
+        return;
+    }
+
+    const size_t depth      = 2;
+    GLubyte data[4 * depth] = {
+        255, 0, 255, 255, 255, 255, 0, 255,
+    };
+
+    for (size_t layer = 0; layer < depth; layer++)
+    {
+        // Create the Image
+        GLuint source;
+        EGLImageKHR image;
+        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
+                                      &image);
+
+        // Create the target
+        GLuint target;
+        createEGLImageTargetTexture2D(image, &target);
+
+        // Expect that the target renderbuffer has the same color as the source texture
+        verifyResults2D(target, &data[layer * 4]);
+
+        // Clean up
+        glDeleteTextures(1, &source);
+        eglDestroyImageKHR(window->getDisplay(), image);
+        glDeleteTextures(1, &target);
+    }
+}
+
+TEST_P(ImageTest, Source3DTargetRenderbuffer)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_3D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
+    {
+        std::cout << "Test skipped because 3D textures are not available." << std::endl;
+        return;
+    }
+
+    const size_t depth      = 2;
+    GLubyte data[4 * depth] = {
+        255, 0, 255, 255, 255, 255, 0, 255,
+    };
+
+    for (size_t layer = 0; layer < depth; layer++)
+    {
+        // Create the Image
+        GLuint source;
+        EGLImageKHR image;
+        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
+                                      &image);
+
+        // Create the target
+        GLuint target;
+        createEGLImageTargetRenderbuffer(image, &target);
+
+        // Expect that the target renderbuffer has the same color as the source texture
+        verifyResultsRenderbuffer(target, &data[layer * 4]);
+
+        // Clean up
+        glDeleteTextures(1, &source);
+        eglDestroyImageKHR(window->getDisplay(), image);
+        glDeleteTextures(1, &target);
+    }
+}
+
+// Test 3D -> external texture EGL images.
+TEST_P(ImageTest, Source3DTargetExternal)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
+    {
+        std::cout
+            << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
+               "EGL_KHR_gl_texture_3D_image is not available."
+            << std::endl;
+        return;
+    }
+
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
+    {
+        std::cout << "Test skipped because 3D textures are not available." << std::endl;
+        return;
+    }
+
+    const size_t depth      = 2;
+    GLubyte data[4 * depth] = {
+        255, 0, 255, 255, 255, 255, 0, 255,
+    };
+
+    for (size_t layer = 0; layer < depth; layer++)
+    {
+        // Create the Image
+        GLuint source;
+        EGLImageKHR image;
+        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
+                                      &image);
+
+        // Create the target
+        GLuint target;
+        createEGLImageTargetTextureExternal(image, &target);
+
+        // Expect that the target renderbuffer has the same color as the source texture
+        verifyResultsExternal(target, &data[layer * 4]);
+
+        // Clean up
+        glDeleteTextures(1, &source);
+        eglDestroyImageKHR(window->getDisplay(), image);
+        glDeleteTextures(1, &target);
+    }
+}
+
+// Test 3D -> external texture EGL images using ESSL3 shaders.
+TEST_P(ImageTestES3, Source3DTargetExternalESSL3)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, OES_EGL_image_external_essl3, "
+                     "EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_3D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
+    {
+        std::cout << "Test skipped because 3D textures are not available." << std::endl;
+        return;
+    }
+
+    const size_t depth      = 2;
+    GLubyte data[4 * depth] = {
+        255, 0, 255, 255, 255, 255, 0, 255,
+    };
+
+    for (size_t layer = 0; layer < depth; layer++)
+    {
+        // Create the Image
+        GLuint source;
+        EGLImageKHR image;
+        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
+                                      &image);
+
+        // Create the target
+        GLuint target;
+        createEGLImageTargetTextureExternal(image, &target);
+
+        // Expect that the target renderbuffer has the same color as the source texture
+        verifyResultsExternalESSL3(target, &data[layer * 4]);
+
+        // Clean up
+        glDeleteTextures(1, &source);
+        eglDestroyImageKHR(window->getDisplay(), image);
+        glDeleteTextures(1, &target);
+    }
+}
+
+TEST_P(ImageTest, SourceRenderbufferTargetTexture)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_renderbuffer_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte data[4] = {255, 0, 255, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetTexture2D(image, &target);
+
+    // Expect that the target texture has the same color as the source texture
+    verifyResults2D(target, data);
+
+    // Clean up
+    glDeleteRenderbuffers(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteTextures(1, &target);
+}
+
+// Test renderbuffer -> external texture EGL images.
+TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
+    {
+        std::cout
+            << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
+               "EGL_KHR_gl_renderbuffer_image is not available."
+            << std::endl;
+        return;
+    }
+
+    GLubyte data[4] = {255, 0, 255, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetTextureExternal(image, &target);
+
+    // Expect that the target texture has the same color as the source texture
+    verifyResultsExternal(target, data);
+
+    // Clean up
+    glDeleteRenderbuffers(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteTextures(1, &target);
+}
+
+// Test renderbuffer -> external texture EGL images using ESSL3 shaders.
+TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
+    {
+        std::cout
+            << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
+               "EGL_KHR_gl_renderbuffer_image is not available."
+            << std::endl;
+        return;
+    }
+
+    GLubyte data[4] = {255, 0, 255, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetTextureExternal(image, &target);
+
+    // Expect that the target texture has the same color as the source texture
+    verifyResultsExternalESSL3(target, data);
+
+    // Clean up
+    glDeleteRenderbuffers(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteTextures(1, &target);
+}
+
+TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_renderbuffer_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte data[4] = {255, 0, 255, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetRenderbuffer(image, &target);
+
+    // Expect that the target renderbuffer has the same color as the source texture
+    verifyResultsRenderbuffer(target, data);
+
+    // Clean up
+    glDeleteRenderbuffers(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteRenderbuffers(1, &target);
+}
+
+// Delete the source texture and EGL image.  The image targets should still have the same data
+// because
+// they hold refs to the image.
+TEST_P(ImageTest, Deletion)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte originalData[4] = {255, 0, 255, 255};
+    GLubyte updateData[4]   = {0, 255, 0, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+
+    // Create multiple targets
+    GLuint targetTexture;
+    createEGLImageTargetTexture2D(image, &targetTexture);
+
+    GLuint targetRenderbuffer;
+    createEGLImageTargetRenderbuffer(image, &targetRenderbuffer);
+
+    // Delete the source texture
+    glDeleteTextures(1, &source);
+    source = 0;
+
+    // Expect that both the targets have the original data
+    verifyResults2D(targetTexture, originalData);
+    verifyResultsRenderbuffer(targetRenderbuffer, originalData);
+
+    // Update the data of the target
+    glBindTexture(GL_TEXTURE_2D, targetTexture);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
+
+    // Expect that both targets have the updated data
+    verifyResults2D(targetTexture, updateData);
+    verifyResultsRenderbuffer(targetRenderbuffer, updateData);
+
+    // Delete the EGL image
+    eglDestroyImageKHR(window->getDisplay(), image);
+    image = EGL_NO_IMAGE_KHR;
+
+    // Update the data of the target back to the original data
+    glBindTexture(GL_TEXTURE_2D, targetTexture);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
+
+    // Expect that both targets have the original data again
+    verifyResults2D(targetTexture, originalData);
+    verifyResultsRenderbuffer(targetRenderbuffer, originalData);
+
+    // Clean up
+    glDeleteTextures(1, &targetTexture);
+    glDeleteRenderbuffers(1, &targetRenderbuffer);
+}
+
+TEST_P(ImageTest, MipLevels)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    const size_t mipLevels   = 3;
+    const size_t textureSize = 4;
+    std::vector<GLuint> mip0Data(textureSize * textureSize, 0xFFFF0000);
+    std::vector<GLuint> mip1Data(mip0Data.size() << 1, 0xFF00FF00);
+    std::vector<GLuint> mip2Data(mip0Data.size() << 2, 0xFF0000FF);
+    GLubyte *data[mipLevels] = {
+        reinterpret_cast<GLubyte *>(&mip0Data[0]), reinterpret_cast<GLubyte *>(&mip1Data[0]),
+        reinterpret_cast<GLubyte *>(&mip2Data[0]),
+    };
+
+    GLuint source;
+    glGenTextures(1, &source);
+    glBindTexture(GL_TEXTURE_2D, source);
+
+    for (size_t level = 0; level < mipLevels; level++)
+    {
+        glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), GL_RGBA, textureSize >> level,
+                     textureSize >> level, 0, GL_RGBA, GL_UNSIGNED_BYTE, data[level]);
+    }
+
+    ASSERT_GL_NO_ERROR();
+
+    for (size_t level = 0; level < mipLevels; level++)
+    {
+        // Create the Image
+        EGLint attribs[] = {
+            EGL_GL_TEXTURE_LEVEL_KHR, static_cast<EGLint>(level), EGL_NONE,
+        };
+        EGLImageKHR image =
+            eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
+                              reinterpretHelper<EGLClientBuffer>(source), attribs);
+        ASSERT_EGL_SUCCESS();
+
+        // Create a texture and renderbuffer target
+        GLuint textureTarget;
+        createEGLImageTargetTexture2D(image, &textureTarget);
+
+        // Disable mipmapping
+        glBindTexture(GL_TEXTURE_2D, textureTarget);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        GLuint renderbufferTarget;
+        createEGLImageTargetRenderbuffer(image, &renderbufferTarget);
+
+        // Expect that the targets have the same color as the source texture
+        verifyResults2D(textureTarget, data[level]);
+        verifyResultsRenderbuffer(renderbufferTarget, data[level]);
+
+        // Clean up
+        eglDestroyImageKHR(window->getDisplay(), image);
+        glDeleteTextures(1, &textureTarget);
+        glDeleteRenderbuffers(1, &renderbufferTarget);
+    }
+
+    // Clean up
+    glDeleteTextures(1, &source);
+}
+
+// Respecify the source texture, orphaning it.  The target texture should not have updated data.
+TEST_P(ImageTest, Respecification)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte originalData[4] = {255, 0, 255, 255};
+    GLubyte updateData[4]   = {0, 255, 0, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetTexture2D(image, &target);
+
+    // Respecify source
+    glBindTexture(GL_TEXTURE_2D, source);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
+
+    // Expect that the target texture has the original data
+    verifyResults2D(target, originalData);
+
+    // Expect that the source texture has the updated data
+    verifyResults2D(source, updateData);
+
+    // Clean up
+    glDeleteTextures(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteTextures(1, &target);
+}
+
+// First render to a target texture, then respecify the source texture, orphaning it.
+// The target texture's FBO should be notified of the target texture's orphaning.
+TEST_P(ImageTest, RespecificationWithFBO)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    // Simple shader
+    const std::string &vertexSource =
+        "attribute vec2 position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "}";
+    const std::string &fragmentSource =
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
+        "}";
+    GLuint program = CompileProgram(vertexSource, fragmentSource);
+    ASSERT_NE(0u, program);
+
+    GLubyte originalData[4] = {255, 0, 255, 255};
+    GLubyte updateData[4]   = {0, 255, 0, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetTexture2D(image, &target);
+
+    // Render to the target texture
+    GLuint fbo;
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
+    drawQuad(program, "position", 0.5f);
+    EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
+
+    // Respecify source with same parameters. This should not change the texture storage in D3D11.
+    glBindTexture(GL_TEXTURE_2D, source);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
+
+    // Expect that the source texture has the updated data
+    verifyResults2D(source, updateData);
+
+    // Render to the target texture again and verify it gets the rendered pixels.
+    drawQuad(program, "position", 0.5f);
+    EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
+
+    // Clean up
+    glDeleteTextures(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteTextures(1, &target);
+    glDeleteProgram(program);
+    glDeleteFramebuffers(1, &fbo);
+}
+
+// Test that respecifying a level of the target texture orphans it and keeps a copy of the EGLimage
+// data
+TEST_P(ImageTest, RespecificationOfOtherLevel)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte originalData[2 * 2 * 4] = {
+        255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+    };
+
+    GLubyte updateData[2 * 2 * 4] = {
+        0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
+    };
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(2, 2, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+
+    // Create the target
+    GLuint target;
+    createEGLImageTargetTexture2D(image, &target);
+
+    // Expect that the target and source textures have the original data
+    verifyResults2D(source, originalData);
+    verifyResults2D(target, originalData);
+
+    // Add a new mipLevel to the target, orphaning it
+    glBindTexture(GL_TEXTURE_2D, target);
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
+    EXPECT_GL_NO_ERROR();
+
+    // Expect that the target and source textures still have the original data
+    verifyResults2D(source, originalData);
+    verifyResults2D(target, originalData);
+
+    // Update the source's data
+    glBindTexture(GL_TEXTURE_2D, source);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
+
+    // Expect that the target still has the original data and source has the updated data
+    verifyResults2D(source, updateData);
+    verifyResults2D(target, originalData);
+
+    // Clean up
+    glDeleteTextures(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteTextures(1, &target);
+}
+
+// Update the data of the source and target textures.  All image siblings should have the new data.
+TEST_P(ImageTest, UpdatedData)
+{
+    EGLWindow *window = getEGLWindow();
+    if (!extensionEnabled("OES_EGL_image") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
+        !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
+    {
+        std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
+                     "EGL_KHR_gl_texture_2D_image is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLubyte originalData[4] = {255, 0, 255, 255};
+    GLubyte updateData[4]   = {0, 255, 0, 255};
+
+    // Create the Image
+    GLuint source;
+    EGLImageKHR image;
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+
+    // Create multiple targets
+    GLuint targetTexture;
+    createEGLImageTargetTexture2D(image, &targetTexture);
+
+    GLuint targetRenderbuffer;
+    createEGLImageTargetRenderbuffer(image, &targetRenderbuffer);
+
+    // Expect that both the source and targets have the original data
+    verifyResults2D(source, originalData);
+    verifyResults2D(targetTexture, originalData);
+    verifyResultsRenderbuffer(targetRenderbuffer, originalData);
+
+    // Update the data of the source
+    glBindTexture(GL_TEXTURE_2D, source);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
+
+    // Expect that both the source and targets have the updated data
+    verifyResults2D(source, updateData);
+    verifyResults2D(targetTexture, updateData);
+    verifyResultsRenderbuffer(targetRenderbuffer, updateData);
+
+    // Update the data of the target back to the original data
+    glBindTexture(GL_TEXTURE_2D, targetTexture);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
+
+    // Expect that both the source and targets have the original data again
+    verifyResults2D(source, originalData);
+    verifyResults2D(targetTexture, originalData);
+    verifyResultsRenderbuffer(targetRenderbuffer, originalData);
+
+    // Clean up
+    glDeleteTextures(1, &source);
+    eglDestroyImageKHR(window->getDisplay(), image);
+    glDeleteTextures(1, &targetTexture);
+    glDeleteRenderbuffers(1, &targetRenderbuffer);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(ImageTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(ImageTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+}
diff --git a/src/third_party/angle/src/tests/gl_tests/IncompleteTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/IncompleteTextureTest.cpp
new file mode 100644
index 0000000..d7a1139
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/IncompleteTextureTest.cpp
@@ -0,0 +1,170 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include <vector>
+
+using namespace angle;
+
+class IncompleteTextureTest : public ANGLETest
+{
+  protected:
+    IncompleteTextureTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = position;
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    void fillTextureData(std::vector<GLubyte> &buffer, GLubyte r, GLubyte g, GLubyte b, GLubyte a)
+    {
+        size_t count = buffer.size() / 4;
+        for (size_t i = 0; i < count; i++)
+        {
+            buffer[i * 4 + 0] = r;
+            buffer[i * 4 + 1] = g;
+            buffer[i * 4 + 2] = b;
+            buffer[i * 4 + 3] = a;
+        }
+    }
+
+    GLuint mProgram;
+    GLint mTextureUniformLocation;
+};
+
+TEST_P(IncompleteTextureTest, IncompleteTexture2D)
+{
+    GLuint tex;
+    glGenTextures(1, &tex);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    glUseProgram(mProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    const GLsizei textureWidth = 2;
+    const GLsizei textureHeight = 2;
+    std::vector<GLubyte> textureData(textureWidth * textureHeight * 4);
+    fillTextureData(textureData, 255, 0, 0, 255);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData[0]);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 255);
+
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, textureWidth >> 1, textureHeight >> 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData[0]);
+
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    glDeleteTextures(1, &tex);
+}
+
+TEST_P(IncompleteTextureTest, UpdateTexture)
+{
+    GLuint tex;
+    glGenTextures(1, &tex);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    glUseProgram(mProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    const GLsizei redTextureWidth = 64;
+    const GLsizei redTextureHeight = 64;
+    std::vector<GLubyte> redTextureData(redTextureWidth * redTextureHeight * 4);
+    fillTextureData(redTextureData, 255, 0, 0, 255);
+    for (size_t i = 0; i < 7; i++)
+    {
+        glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(i), GL_RGBA, redTextureWidth >> i,
+                     redTextureHeight >> i, 0, GL_RGBA, GL_UNSIGNED_BYTE, &redTextureData[0]);
+    }
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    const GLsizei greenTextureWidth = 32;
+    const GLsizei greenTextureHeight = 32;
+    std::vector<GLubyte> greenTextureData(greenTextureWidth * greenTextureHeight * 4);
+    fillTextureData(greenTextureData, 0, 255, 0, 255);
+
+    for (size_t i = 0; i < 6; i++)
+    {
+        glTexSubImage2D(GL_TEXTURE_2D, static_cast<GLint>(i), greenTextureWidth >> i,
+                        greenTextureHeight >> i, greenTextureWidth >> i, greenTextureHeight >> i,
+                        GL_RGBA, GL_UNSIGNED_BYTE, &greenTextureData[0]);
+    }
+
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_EQ(getWindowWidth() - greenTextureWidth, getWindowHeight() - greenTextureWidth, 0, 255, 0, 255);
+
+    glDeleteTextures(1, &tex);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(IncompleteTextureTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/IndexBufferOffsetTest.cpp b/src/third_party/angle/src/tests/gl_tests/IndexBufferOffsetTest.cpp
new file mode 100644
index 0000000..329848a
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/IndexBufferOffsetTest.cpp
@@ -0,0 +1,145 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBufferOffsetTest.cpp: Test glDrawElements with an offset and an index buffer
+
+#include "system_utils.h"
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class IndexBufferOffsetTest : public ANGLETest
+{
+  protected:
+    IndexBufferOffsetTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource =
+            SHADER_SOURCE(precision highp float; attribute vec2 position;
+
+                          void main() { gl_Position = vec4(position, 0.0, 1.0); });
+
+        const std::string fragmentShaderSource =
+            SHADER_SOURCE(precision highp float; uniform vec4 color;
+
+                          void main() { gl_FragColor = color; });
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+
+        mColorUniformLocation      = glGetUniformLocation(mProgram, "color");
+        mPositionAttributeLocation = glGetAttribLocation(mProgram, "position");
+
+        const GLfloat vertices[] = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f};
+        glGenBuffers(1, &mVertexBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
+
+        glGenBuffers(1, &mIndexBuffer);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+    }
+
+    void TearDown() override
+    {
+        glDeleteBuffers(1, &mVertexBuffer);
+        glDeleteBuffers(1, &mIndexBuffer);
+        glDeleteProgram(mProgram);
+        ANGLETest::TearDown();
+    }
+
+    void runTest(GLenum type, int typeWidth, void *indexData)
+    {
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        GLuint nullIndexData[] = {0, 0, 0, 0, 0, 0};
+
+        size_t indexDataWidth = 6 * typeWidth;
+
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * indexDataWidth, nullptr, GL_DYNAMIC_DRAW);
+        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexDataWidth, nullIndexData);
+        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth, indexData);
+        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth, nullIndexData);
+
+        glUseProgram(mProgram);
+
+        glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+        glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
+        glEnableVertexAttribArray(mPositionAttributeLocation);
+
+        glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
+
+        for (int i = 0; i < 16; i++)
+        {
+            glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast<void *>(indexDataWidth));
+            EXPECT_PIXEL_EQ(64, 64, 255, 0, 0, 255);
+        }
+
+        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth, nullIndexData);
+        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth, indexData);
+
+        glUniform4f(mColorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
+        glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast<void *>(indexDataWidth * 2));
+        EXPECT_PIXEL_EQ(64, 64, 0, 255, 0, 255);
+
+        EXPECT_GL_NO_ERROR();
+        swapBuffers();
+    }
+
+    GLuint mProgram;
+    GLint mColorUniformLocation;
+    GLint mPositionAttributeLocation;
+    GLuint mVertexBuffer;
+    GLuint mIndexBuffer;
+};
+
+// Test using an offset for an UInt8 index buffer
+TEST_P(IndexBufferOffsetTest, UInt8Index)
+{
+    GLubyte indexData[] = {0, 1, 2, 1, 2, 3};
+    runTest(GL_UNSIGNED_BYTE, 1, indexData);
+}
+
+// Test using an offset for an UInt16 index buffer
+TEST_P(IndexBufferOffsetTest, UInt16Index)
+{
+    GLushort indexData[] = {0, 1, 2, 1, 2, 3};
+    runTest(GL_UNSIGNED_SHORT, 2, indexData);
+}
+
+// Test using an offset for an UInt32 index buffer
+TEST_P(IndexBufferOffsetTest, UInt32Index)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
+    {
+        std::cout << "Test skipped because ES3 or GL_OES_element_index_uint is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLuint indexData[] = {0, 1, 2, 1, 2, 3};
+    runTest(GL_UNSIGNED_INT, 4, indexData);
+}
+
+ANGLE_INSTANTIATE_TEST(IndexBufferOffsetTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/IndexedPointsTest.cpp b/src/third_party/angle/src/tests/gl_tests/IndexedPointsTest.cpp
new file mode 100644
index 0000000..4858f20
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/IndexedPointsTest.cpp
@@ -0,0 +1,386 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+template <typename IndexType, GLenum IndexTypeName>
+class IndexedPointsTest : public ANGLETest
+{
+  protected:
+    IndexedPointsTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    float getIndexPositionX(size_t idx) { return (idx == 0 || idx == 3) ? -0.5f : 0.5f; }
+
+    float getIndexPositionY(size_t idx) { return (idx == 2 || idx == 3) ? -0.5f : 0.5f; }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource =
+            SHADER_SOURCE(precision highp float; attribute vec2 position;
+
+                          void main() {
+                              gl_PointSize = 5.0;
+                              gl_Position  = vec4(position, 0.0, 1.0);
+                          });
+
+        const std::string fragmentShaderSource =
+            SHADER_SOURCE(precision highp float;
+
+                          void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); });
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+
+        const std::string vertexShaderSource2 =
+            SHADER_SOURCE(precision highp float; attribute vec2 position; attribute vec4 color;
+                          varying vec4 vcolor;
+
+                          void main() {
+                              gl_PointSize = 5.0;
+                              gl_Position  = vec4(position, 0.0, 1.0);
+                              vcolor       = color;
+                          });
+
+        const std::string fragmentShaderSource2 =
+            SHADER_SOURCE(precision highp float; varying vec4 vcolor;
+                          void main() { gl_FragColor = vec4(vcolor.xyz, 1.0); });
+
+        mVertexWithColorBufferProgram = CompileProgram(vertexShaderSource2, fragmentShaderSource2);
+        ASSERT_NE(0u, mVertexWithColorBufferProgram);
+
+        // Construct a vertex buffer of position values and color values
+        // contained in a single structure
+        const float verticesWithColor[] = {
+            getIndexPositionX(0), getIndexPositionY(0), 0.0f, 1.0f, 0.0f,
+            getIndexPositionX(2), getIndexPositionY(2), 0.0f, 1.0f, 0.0f,
+            getIndexPositionX(1), getIndexPositionY(1), 0.0f, 1.0f, 0.0f,
+            getIndexPositionX(3), getIndexPositionY(3), 0.0f, 1.0f, 0.0f,
+        };
+
+        glGenBuffers(1, &mVertexWithColorBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, mVertexWithColorBuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(verticesWithColor), &verticesWithColor[0],
+                     GL_STATIC_DRAW);
+
+        // Construct a vertex buffer of position values only
+        const GLfloat vertices[] = {
+            getIndexPositionX(0), getIndexPositionY(0), getIndexPositionX(2), getIndexPositionY(2),
+            getIndexPositionX(1), getIndexPositionY(1), getIndexPositionX(3), getIndexPositionY(3),
+        };
+        glGenBuffers(1, &mVertexBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
+
+        // The indices buffer is shared between both variations of tests
+        const IndexType indices[] = {0, 2, 1, 3};
+        glGenBuffers(1, &mIndexBuffer);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteBuffers(1, &mVertexBuffer);
+        glDeleteBuffers(1, &mIndexBuffer);
+        glDeleteProgram(mProgram);
+
+        glDeleteBuffers(1, &mVertexWithColorBuffer);
+        glDeleteProgram(mVertexWithColorBufferProgram);
+        ANGLETest::TearDown();
+    }
+
+    void runTest(GLuint firstIndex, bool useVertexBufferWithColor = false)
+    {
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        GLint viewportSize[4];
+        glGetIntegerv(GL_VIEWPORT, viewportSize);
+
+        // Choose appropriate program to apply for the test
+        GLuint program = useVertexBufferWithColor ? mVertexWithColorBufferProgram : mProgram;
+
+        if (useVertexBufferWithColor)
+        {
+            glBindBuffer(GL_ARRAY_BUFFER, mVertexWithColorBuffer);
+            GLint vertexLocation = glGetAttribLocation(program, "position");
+            glVertexAttribPointer(vertexLocation, 2, GL_FLOAT, GL_FALSE,
+                                  static_cast<const GLsizei>(VertexWithColorSize), 0);
+            glEnableVertexAttribArray(vertexLocation);
+
+            GLint vertexColorLocation = glGetAttribLocation(program, "color");
+            glVertexAttribPointer(vertexColorLocation, 3, GL_FLOAT, GL_FALSE,
+                                  static_cast<const GLsizei>(VertexWithColorSize),
+                                  (void *)((sizeof(float) * 2)));
+            glEnableVertexAttribArray(vertexColorLocation);
+        }
+        else
+        {
+            glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+            GLint vertexLocation = glGetAttribLocation(program, "position");
+            glVertexAttribPointer(vertexLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
+            glEnableVertexAttribArray(vertexLocation);
+        }
+
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+        glUseProgram(program);
+
+        glDrawElements(GL_POINTS, mPointCount - firstIndex, IndexTypeName,
+                       reinterpret_cast<void *>(firstIndex * sizeof(IndexType)));
+
+        for (size_t i = 0; i < mPointCount; i++)
+        {
+            GLuint x =
+                static_cast<GLuint>(viewportSize[0] + (getIndexPositionX(i) * 0.5f + 0.5f) *
+                                                          (viewportSize[2] - viewportSize[0]));
+            GLuint y =
+                static_cast<GLuint>(viewportSize[1] + (getIndexPositionY(i) * 0.5f + 0.5f) *
+                                                          (viewportSize[3] - viewportSize[1]));
+
+            if (i < firstIndex)
+            {
+                EXPECT_PIXEL_EQ(x, y, 0, 0, 0, 255);
+            }
+            else
+            {
+                if (useVertexBufferWithColor)
+                {
+                    // Pixel data is assumed to be GREEN
+                    EXPECT_PIXEL_EQ(x, y, 0, 255, 0, 255);
+                }
+                else
+                {
+                    // Pixel data is assumed to be RED
+                    EXPECT_PIXEL_EQ(x, y, 255, 0, 0, 255);
+                }
+            }
+        }
+        swapBuffers();
+    }
+
+    GLuint mProgram;
+    GLuint mVertexBuffer;
+    GLuint mIndexBuffer;
+
+    GLuint mVertexWithColorBufferProgram;
+    GLuint mVertexWithColorBuffer;
+
+    static const GLuint mPointCount = 4;
+
+  private:
+    const size_t VertexWithColorSize = sizeof(float) * 5;
+};
+
+typedef IndexedPointsTest<GLubyte, GL_UNSIGNED_BYTE> IndexedPointsTestUByte;
+
+TEST_P(IndexedPointsTestUByte, UnsignedByteOffset0)
+{
+    runTest(0);
+}
+
+TEST_P(IndexedPointsTestUByte, UnsignedByteOffset1)
+{
+    runTest(1);
+}
+
+TEST_P(IndexedPointsTestUByte, UnsignedByteOffset2)
+{
+    runTest(2);
+}
+
+TEST_P(IndexedPointsTestUByte, UnsignedByteOffset3)
+{
+    runTest(3);
+}
+
+TEST_P(IndexedPointsTestUByte, VertexWithColorUnsignedByteOffset0)
+{
+    runTest(0, true);
+}
+
+TEST_P(IndexedPointsTestUByte, VertexWithColorUnsignedByteOffset1)
+{
+    runTest(1, true);
+}
+
+TEST_P(IndexedPointsTestUByte, VertexWithColorUnsignedByteOffset2)
+{
+    runTest(2, true);
+}
+
+TEST_P(IndexedPointsTestUByte, VertexWithColorUnsignedByteOffset3)
+{
+    runTest(3, true);
+}
+
+typedef IndexedPointsTest<GLushort, GL_UNSIGNED_SHORT> IndexedPointsTestUShort;
+
+TEST_P(IndexedPointsTestUShort, UnsignedShortOffset0)
+{
+    runTest(0);
+}
+
+TEST_P(IndexedPointsTestUShort, UnsignedShortOffset1)
+{
+    runTest(1);
+}
+
+TEST_P(IndexedPointsTestUShort, UnsignedShortOffset2)
+{
+    runTest(2);
+}
+
+TEST_P(IndexedPointsTestUShort, UnsignedShortOffset3)
+{
+    runTest(3);
+}
+
+TEST_P(IndexedPointsTestUShort, VertexWithColorUnsignedShortOffset0)
+{
+    runTest(0, true);
+}
+
+TEST_P(IndexedPointsTestUShort, VertexWithColorUnsignedShortOffset1)
+{
+    runTest(1, true);
+}
+
+TEST_P(IndexedPointsTestUShort, VertexWithColorUnsignedShortOffset2)
+{
+    runTest(2, true);
+}
+
+TEST_P(IndexedPointsTestUShort, VertexWithColorUnsignedShortOffset3)
+{
+    runTest(3, true);
+}
+
+TEST_P(IndexedPointsTestUShort, VertexWithColorUnsignedShortOffsetChangingIndices)
+{
+    // TODO(fjhenigman): Figure out why this fails on Ozone Intel.
+    if (IsOzone() && IsIntel() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Ozone Intel." << std::endl;
+        return;
+    }
+
+    runTest(3, true);
+    runTest(1, true);
+    runTest(0, true);
+    runTest(2, true);
+}
+
+typedef IndexedPointsTest<GLuint, GL_UNSIGNED_INT> IndexedPointsTestUInt;
+
+TEST_P(IndexedPointsTestUInt, UnsignedIntOffset0)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    runTest(0);
+}
+
+TEST_P(IndexedPointsTestUInt, UnsignedIntOffset1)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    runTest(1);
+}
+
+TEST_P(IndexedPointsTestUInt, UnsignedIntOffset2)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    runTest(2);
+}
+
+TEST_P(IndexedPointsTestUInt, UnsignedIntOffset3)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    runTest(3);
+}
+
+TEST_P(IndexedPointsTestUInt, VertexWithColorUnsignedIntOffset0)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    runTest(0, false);
+}
+
+TEST_P(IndexedPointsTestUInt, VertexWithColorUnsignedIntOffset1)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    runTest(1, false);
+}
+
+TEST_P(IndexedPointsTestUInt, VertexWithColorUnsignedIntOffset2)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    runTest(2, false);
+}
+
+TEST_P(IndexedPointsTestUInt, VertexWithColorUnsignedIntOffset3)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    runTest(3, false);
+}
+
+// TODO(geofflang): Figure out why this test fails on Intel OpenGL
+ANGLE_INSTANTIATE_TEST(IndexedPointsTestUByte,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(IndexedPointsTestUShort,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(IndexedPointsTestUInt,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/InstancingTest.cpp b/src/third_party/angle/src/tests/gl_tests/InstancingTest.cpp
new file mode 100644
index 0000000..34f61ef
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/InstancingTest.cpp
@@ -0,0 +1,468 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class InstancingTest : public ANGLETest
+{
+  protected:
+    InstancingTest() : mProgram(0), mVertexBuffer(0)
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    ~InstancingTest() override
+    {
+        glDeleteBuffers(1, &mVertexBuffer);
+        glDeleteProgram(mProgram);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        mVertexAttribDivisorANGLE   = nullptr;
+        mDrawArraysInstancedANGLE   = nullptr;
+        mDrawElementsInstancedANGLE = nullptr;
+
+        char *extensionString = (char*)glGetString(GL_EXTENSIONS);
+        if (strstr(extensionString, "GL_ANGLE_instanced_arrays"))
+        {
+            mVertexAttribDivisorANGLE = (PFNGLVERTEXATTRIBDIVISORANGLEPROC)eglGetProcAddress("glVertexAttribDivisorANGLE");
+            mDrawArraysInstancedANGLE = (PFNGLDRAWARRAYSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawArraysInstancedANGLE");
+            mDrawElementsInstancedANGLE = (PFNGLDRAWELEMENTSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawElementsInstancedANGLE");
+        }
+
+        ASSERT_TRUE(mVertexAttribDivisorANGLE != nullptr);
+        ASSERT_TRUE(mDrawArraysInstancedANGLE != nullptr);
+        ASSERT_TRUE(mDrawElementsInstancedANGLE != nullptr);
+
+        // Initialize the vertex and index vectors
+        GLfloat qvertex1[3] = {-quadRadius,  quadRadius, 0.0f};
+        GLfloat qvertex2[3] = {-quadRadius, -quadRadius, 0.0f};
+        GLfloat qvertex3[3] = { quadRadius, -quadRadius, 0.0f};
+        GLfloat qvertex4[3] = { quadRadius,  quadRadius, 0.0f};
+        mQuadVertices.insert(mQuadVertices.end(), qvertex1, qvertex1 + 3);
+        mQuadVertices.insert(mQuadVertices.end(), qvertex2, qvertex2 + 3);
+        mQuadVertices.insert(mQuadVertices.end(), qvertex3, qvertex3 + 3);
+        mQuadVertices.insert(mQuadVertices.end(), qvertex4, qvertex4 + 3);
+
+        GLfloat coord1[2] = {0.0f, 0.0f};
+        GLfloat coord2[2] = {0.0f, 1.0f};
+        GLfloat coord3[2] = {1.0f, 1.0f};
+        GLfloat coord4[2] = {1.0f, 0.0f};
+        mTexcoords.insert(mTexcoords.end(), coord1, coord1 + 2);
+        mTexcoords.insert(mTexcoords.end(), coord2, coord2 + 2);
+        mTexcoords.insert(mTexcoords.end(), coord3, coord3 + 2);
+        mTexcoords.insert(mTexcoords.end(), coord4, coord4 + 2);
+
+        mIndices.push_back(0);
+        mIndices.push_back(1);
+        mIndices.push_back(2);
+        mIndices.push_back(0);
+        mIndices.push_back(2);
+        mIndices.push_back(3);
+
+        for (size_t vertexIndex = 0; vertexIndex < 6; ++vertexIndex)
+        {
+            mNonIndexedVertices.insert(mNonIndexedVertices.end(),
+                                       mQuadVertices.begin() + mIndices[vertexIndex] * 3,
+                                       mQuadVertices.begin() + mIndices[vertexIndex] * 3 + 3);
+        }
+
+        for (size_t vertexIndex = 0; vertexIndex < 6; ++vertexIndex)
+        {
+            mNonIndexedVertices.insert(mNonIndexedVertices.end(),
+                                       mQuadVertices.begin() + mIndices[vertexIndex] * 3,
+                                       mQuadVertices.begin() + mIndices[vertexIndex] * 3 + 3);
+        }
+
+        // Tile a 2x2 grid of the tiles
+        for (float y = -1.0f + quadRadius; y < 1.0f - quadRadius; y += quadRadius * 3)
+        {
+            for (float x = -1.0f + quadRadius; x < 1.0f - quadRadius; x += quadRadius * 3)
+            {
+                GLfloat instance[3] = {x + quadRadius, y + quadRadius, 0.0f};
+                mInstances.insert(mInstances.end(), instance, instance + 3);
+            }
+        }
+
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+        glGenBuffers(1, &mVertexBuffer);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void setupDrawArraysTest(const std::string &vs)
+    {
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            void main()
+            {
+                gl_FragColor = vec4(1.0, 0, 0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(vs, fs);
+        ASSERT_NE(0u, mProgram);
+
+        // Set the viewport
+        glViewport(0, 0, getWindowWidth(), getWindowHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+    }
+
+    void setupInstancedPointsTest()
+    {
+        mIndices.clear();
+        mIndices.push_back(0);
+        mIndices.push_back(1);
+        mIndices.push_back(2);
+        mIndices.push_back(3);
+
+        // clang-format off
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec3 a_position;
+            attribute vec3 a_instancePos;
+            void main()
+            {
+                gl_Position  = vec4(a_position.xyz, 1.0);
+                gl_Position  = vec4(a_instancePos.xyz, 1.0);
+                gl_PointSize = 6.0;
+            }
+        );
+
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            void main()
+            {
+                gl_FragColor = vec4(1.0, 0, 0, 1.0);
+            }
+        );
+        // clang-format on
+
+        mProgram = CompileProgram(vs, fs);
+        ASSERT_NE(0u, mProgram);
+
+        // Set the viewport
+        glViewport(0, 0, getWindowWidth(), getWindowHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(mProgram);
+    }
+
+    void runDrawArraysTest(GLint first, GLsizei count, GLsizei instanceCount, float *offset)
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+        glBufferData(GL_ARRAY_BUFFER, mInstances.size() * sizeof(mInstances[0]), &mInstances[0], GL_STATIC_DRAW);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+        // Get the attribute locations
+        GLint positionLoc    = glGetAttribLocation(mProgram, "a_position");
+        GLint instancePosLoc = glGetAttribLocation(mProgram, "a_instancePos");
+
+        // Load the vertex position
+        glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, mNonIndexedVertices.data());
+        glEnableVertexAttribArray(positionLoc);
+
+        // Load the instance position
+        glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+        glVertexAttribPointer(instancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        glEnableVertexAttribArray(instancePosLoc);
+
+        // Enable instancing
+        mVertexAttribDivisorANGLE(instancePosLoc, 1);
+
+        // Offset
+        GLint uniformLoc = glGetUniformLocation(mProgram, "u_offset");
+        ASSERT_NE(uniformLoc, -1);
+        glUniform3fv(uniformLoc, 1, offset);
+
+        // Do the instanced draw
+        mDrawArraysInstancedANGLE(GL_TRIANGLES, first, count, instanceCount);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void runDrawElementsTest(std::string vs, bool shouldAttribZeroBeInstanced)
+    {
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+            void main()
+            {
+                gl_FragColor = vec4(1.0, 0, 0, 1.0);
+            }
+        );
+
+        GLuint program = CompileProgram(vs, fs);
+        ASSERT_NE(program, 0u);
+
+        // Get the attribute locations
+        GLint positionLoc = glGetAttribLocation(program, "a_position");
+        GLint instancePosLoc = glGetAttribLocation(program, "a_instancePos");
+
+        // If this ASSERT fails then the vertex shader code should be refactored
+        ASSERT_EQ(shouldAttribZeroBeInstanced, (instancePosLoc == 0));
+
+        // Set the viewport
+        glViewport(0, 0, getWindowWidth(), getWindowHeight());
+
+        // Clear the color buffer
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        glUseProgram(program);
+
+        // Load the vertex position
+        glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, mQuadVertices.data());
+        glEnableVertexAttribArray(positionLoc);
+
+        // Load the instance position
+        glVertexAttribPointer(instancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, mInstances.data());
+        glEnableVertexAttribArray(instancePosLoc);
+
+        // Enable instancing
+        mVertexAttribDivisorANGLE(instancePosLoc, 1);
+
+        // Do the instanced draw
+        mDrawElementsInstancedANGLE(GL_TRIANGLES, static_cast<GLsizei>(mIndices.size()),
+                                    GL_UNSIGNED_SHORT, mIndices.data(),
+                                    static_cast<GLsizei>(mInstances.size()) / 3);
+
+        ASSERT_GL_NO_ERROR();
+
+        checkQuads();
+    }
+
+    void checkQuads()
+    {
+        // Check that various pixels are the expected color.
+        for (unsigned int quadIndex = 0; quadIndex < 4; ++quadIndex)
+        {
+            unsigned int baseOffset = quadIndex * 3;
+
+            int quadx = static_cast<int>(((mInstances[baseOffset + 0]) * 0.5f + 0.5f) * getWindowWidth());
+            int quady = static_cast<int>(((mInstances[baseOffset + 1]) * 0.5f + 0.5f) * getWindowHeight());
+
+            EXPECT_PIXEL_EQ(quadx, quady, 255, 0, 0, 255);
+        }
+    }
+
+    // Loaded entry points
+    PFNGLVERTEXATTRIBDIVISORANGLEPROC mVertexAttribDivisorANGLE;
+    PFNGLDRAWARRAYSINSTANCEDANGLEPROC mDrawArraysInstancedANGLE;
+    PFNGLDRAWELEMENTSINSTANCEDANGLEPROC mDrawElementsInstancedANGLE;
+
+    // Vertex data
+    std::vector<GLfloat> mQuadVertices;
+    std::vector<GLfloat> mNonIndexedVertices;
+    std::vector<GLfloat> mTexcoords;
+    std::vector<GLfloat> mInstances;
+    std::vector<GLushort> mIndices;
+
+    const GLfloat quadRadius = 0.30f;
+
+    GLuint mProgram;
+    GLuint mVertexBuffer;
+};
+
+class InstancingTestAllConfigs : public InstancingTest
+{
+  protected:
+    InstancingTestAllConfigs() {}
+};
+
+class InstancingTestNo9_3 : public InstancingTest
+{
+  protected:
+    InstancingTestNo9_3() {}
+};
+
+class InstancingTestPoints : public InstancingTest
+{
+  protected:
+    InstancingTestPoints() {}
+};
+
+// This test uses a vertex shader with the first attribute (attribute zero) instanced.
+// On D3D9 and D3D11 FL9_3, this triggers a special codepath that rearranges the input layout sent to D3D,
+// to ensure that slot/stream zero of the input layout doesn't contain per-instance data.
+TEST_P(InstancingTestAllConfigs, AttributeZeroInstanced)
+{
+    const std::string vs = SHADER_SOURCE
+    (
+        attribute vec3 a_instancePos;
+        attribute vec3 a_position;
+        void main()
+        {
+            gl_Position = vec4(a_position.xyz + a_instancePos.xyz, 1.0);
+        }
+    );
+
+    runDrawElementsTest(vs, true);
+}
+
+// Same as AttributeZeroInstanced, but attribute zero is not instanced.
+// This ensures the general instancing codepath (i.e. without rearranging the input layout) works as expected.
+TEST_P(InstancingTestAllConfigs, AttributeZeroNotInstanced)
+{
+    const std::string vs = SHADER_SOURCE
+    (
+        attribute vec3 a_position;
+        attribute vec3 a_instancePos;
+        void main()
+        {
+            gl_Position = vec4(a_position.xyz + a_instancePos.xyz, 1.0);
+        }
+    );
+
+    runDrawElementsTest(vs, false);
+}
+
+// Tests that the "first" parameter to glDrawArraysInstancedANGLE is only an offset into
+// the non-instanced vertex attributes.
+TEST_P(InstancingTestNo9_3, DrawArraysWithOffset)
+{
+    const std::string vs = SHADER_SOURCE
+    (
+        attribute vec3 a_position;
+        attribute vec3 a_instancePos;
+        uniform vec3 u_offset;
+        void main()
+        {
+            gl_Position = vec4(a_position.xyz + a_instancePos.xyz + u_offset, 1.0);
+        }
+    );
+
+    setupDrawArraysTest(vs);
+
+    float offset1[3] = { 0, 0, 0 };
+    runDrawArraysTest(0, 6, 2, offset1);
+
+    float offset2[3] = { 0.0f, 1.0f, 0 };
+    runDrawArraysTest(6, 6, 2, offset2);
+
+    checkQuads();
+}
+
+// This test verifies instancing with GL_POINTS with glDrawArraysInstanced works.
+// On D3D11 FL9_3, this triggers a special codepath that emulates instanced points rendering.
+TEST_P(InstancingTestPoints, DrawArrays)
+{
+    // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
+    // On Win7, the D3D SDK Layers emits a false warning for these tests.
+    // This doesn't occur on Windows 10 (Version 1511) though.
+    ignoreD3D11SDKLayersWarnings();
+
+    setupInstancedPointsTest();
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, mInstances.size() * sizeof(mInstances[0]), &mInstances[0],
+                 GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+    // Get the attribute locations
+    GLint positionLoc    = glGetAttribLocation(mProgram, "a_position");
+    GLint instancePosLoc = glGetAttribLocation(mProgram, "a_instancePos");
+
+    // Load the vertex position
+    GLfloat pos[3] = {0, 0, 0};
+    glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, pos);
+    glEnableVertexAttribArray(positionLoc);
+
+    // Load the instance position
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+    glVertexAttribPointer(instancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glEnableVertexAttribArray(instancePosLoc);
+
+    // Enable instancing
+    mVertexAttribDivisorANGLE(instancePosLoc, 1);
+
+    // Do the instanced draw
+    mDrawArraysInstancedANGLE(GL_POINTS, 0, 1, static_cast<GLsizei>(mInstances.size()) / 3);
+
+    ASSERT_GL_NO_ERROR();
+
+    checkQuads();
+}
+
+// This test verifies instancing with GL_POINTS with glDrawElementsInstanced works.
+// On D3D11 FL9_3, this triggers a special codepath that emulates instanced points rendering.
+TEST_P(InstancingTestPoints, DrawElements)
+{
+    // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
+    // On Win7, the D3D SDK Layers emits a false warning for these tests.
+    // This doesn't occur on Windows 10 (Version 1511) though.
+    ignoreD3D11SDKLayersWarnings();
+
+    setupInstancedPointsTest();
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, mInstances.size() * sizeof(mInstances[0]), &mInstances[0],
+                 GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+    // Get the attribute locations
+    GLint positionLoc    = glGetAttribLocation(mProgram, "a_position");
+    GLint instancePosLoc = glGetAttribLocation(mProgram, "a_instancePos");
+
+    // Load the vertex position
+    Vector3 pos[] = {Vector3(0), Vector3(0), Vector3(0), Vector3(0)};
+    glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, pos);
+    glEnableVertexAttribArray(positionLoc);
+
+    // Load the instance position
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+    glVertexAttribPointer(instancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glEnableVertexAttribArray(instancePosLoc);
+
+    // Enable instancing
+    mVertexAttribDivisorANGLE(instancePosLoc, 1);
+
+    // Do the instanced draw
+    mDrawElementsInstancedANGLE(GL_POINTS, static_cast<GLsizei>(mIndices.size()), GL_UNSIGNED_SHORT,
+                                mIndices.data(), static_cast<GLsizei>(mInstances.size()) / 3);
+
+    ASSERT_GL_NO_ERROR();
+
+    checkQuads();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+// We test on D3D9 and D3D11 9_3 because they use special codepaths when attribute zero is instanced, unlike D3D11.
+ANGLE_INSTANTIATE_TEST(InstancingTestAllConfigs,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+
+// TODO(jmadill): Figure out the situation with DrawInstanced on FL 9_3
+ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11());
+
+ANGLE_INSTANTIATE_TEST(InstancingTestPoints, ES2_D3D11(), ES2_D3D11_FL9_3());
diff --git a/src/third_party/angle/src/tests/gl_tests/LineLoopTest.cpp b/src/third_party/angle/src/tests/gl_tests/LineLoopTest.cpp
new file mode 100644
index 0000000..91fe88b
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/LineLoopTest.cpp
@@ -0,0 +1,198 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class LineLoopTest : public ANGLETest
+{
+  protected:
+    LineLoopTest()
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource = SHADER_SOURCE(attribute highp vec4 position;
+
+                                                   void main(void) { gl_Position = position; });
+
+        const std::string fsSource =
+            SHADER_SOURCE(uniform highp vec4 color; void main(void) { gl_FragColor = color; });
+
+        mProgram = CompileProgram(vsSource, fsSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mPositionLocation = glGetAttribLocation(mProgram, "position");
+        mColorLocation    = glGetUniformLocation(mProgram, "color");
+
+        glBlendFunc(GL_ONE, GL_ONE);
+        glEnable(GL_BLEND);
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    void runTest(GLenum indexType, GLuint indexBuffer, const void *indexPtr)
+    {
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        static const GLfloat loopPositions[] = {0.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.0f,
+                                                0.0f,  0.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f,
+                                                -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f};
+
+        static const GLfloat stripPositions[] = {-0.5f, -0.5f, -0.5f, 0.5f,
+                                                 0.5f,  0.5f,  0.5f,  -0.5f};
+        static const GLubyte stripIndices[] = {1, 0, 3, 2, 1};
+
+        glUseProgram(mProgram);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
+        glEnableVertexAttribArray(mPositionLocation);
+        glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, loopPositions);
+        glUniform4f(mColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
+        glDrawElements(GL_LINE_LOOP, 4, indexType, indexPtr);
+
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+        glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, stripPositions);
+        glUniform4f(mColorLocation, 0, 1, 0, 1);
+        glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_BYTE, stripIndices);
+
+        std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
+        glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
+                     &pixels[0]);
+
+        ASSERT_GL_NO_ERROR();
+
+        for (int y = 0; y < getWindowHeight(); y++)
+        {
+            for (int x = 0; x < getWindowWidth(); x++)
+            {
+                const GLubyte *pixel = &pixels[0] + ((y * getWindowWidth() + x) * 4);
+
+                EXPECT_EQ(pixel[0], 0);
+                EXPECT_EQ(pixel[1], pixel[2]);
+                EXPECT_EQ(pixel[3], 255);
+            }
+        }
+    }
+
+    GLuint mProgram;
+    GLint mPositionLocation;
+    GLint mColorLocation;
+};
+
+TEST_P(LineLoopTest, LineLoopUByteIndices)
+{
+    // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
+    // On Win7, the D3D SDK Layers emits a false warning for these tests.
+    // This doesn't occur on Windows 10 (Version 1511) though.
+    ignoreD3D11SDKLayersWarnings();
+
+    static const GLubyte indices[] = {0, 7, 6, 9, 8, 0};
+    runTest(GL_UNSIGNED_BYTE, 0, indices + 1);
+}
+
+TEST_P(LineLoopTest, LineLoopUShortIndices)
+{
+    // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
+    ignoreD3D11SDKLayersWarnings();
+
+    static const GLushort indices[] = {0, 7, 6, 9, 8, 0};
+    runTest(GL_UNSIGNED_SHORT, 0, indices + 1);
+}
+
+TEST_P(LineLoopTest, LineLoopUIntIndices)
+{
+    if (!extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
+    ignoreD3D11SDKLayersWarnings();
+
+    static const GLuint indices[] = {0, 7, 6, 9, 8, 0};
+    runTest(GL_UNSIGNED_INT, 0, indices + 1);
+}
+
+TEST_P(LineLoopTest, LineLoopUByteIndexBuffer)
+{
+    // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
+    ignoreD3D11SDKLayersWarnings();
+
+    static const GLubyte indices[] = {0, 7, 6, 9, 8, 0};
+
+    GLuint buf;
+    glGenBuffers(1, &buf);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+
+    runTest(GL_UNSIGNED_BYTE, buf, reinterpret_cast<const void *>(sizeof(GLubyte)));
+
+    glDeleteBuffers(1, &buf);
+}
+
+TEST_P(LineLoopTest, LineLoopUShortIndexBuffer)
+{
+    // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
+    ignoreD3D11SDKLayersWarnings();
+
+    static const GLushort indices[] = {0, 7, 6, 9, 8, 0};
+
+    GLuint buf;
+    glGenBuffers(1, &buf);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+
+    runTest(GL_UNSIGNED_SHORT, buf, reinterpret_cast<const void *>(sizeof(GLushort)));
+
+    glDeleteBuffers(1, &buf);
+}
+
+TEST_P(LineLoopTest, LineLoopUIntIndexBuffer)
+{
+    if (!extensionEnabled("GL_OES_element_index_uint"))
+    {
+        return;
+    }
+
+    // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
+    ignoreD3D11SDKLayersWarnings();
+
+    static const GLuint indices[] = {0, 7, 6, 9, 8, 0};
+
+    GLuint buf;
+    glGenBuffers(1, &buf);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+
+    runTest(GL_UNSIGNED_INT, buf, reinterpret_cast<const void *>(sizeof(GLuint)));
+
+    glDeleteBuffers(1, &buf);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(LineLoopTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/MaxTextureSizeTest.cpp b/src/third_party/angle/src/tests/gl_tests/MaxTextureSizeTest.cpp
new file mode 100644
index 0000000..bfef701
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/MaxTextureSizeTest.cpp
@@ -0,0 +1,300 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class MaxTextureSizeTest : public ANGLETest
+{
+  protected:
+    MaxTextureSizeTest()
+    {
+        setWindowWidth(512);
+        setWindowHeight(512);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = position;
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        );
+
+        const std::string textureFSSource = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        const std::string blueFSSource = SHADER_SOURCE
+        (
+            precision highp float;
+
+            void main()
+            {
+                gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
+            }
+        );
+
+        mTextureProgram = CompileProgram(vsSource, textureFSSource);
+        mBlueProgram = CompileProgram(vsSource, blueFSSource);
+        if (mTextureProgram == 0 || mBlueProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
+
+        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTexture2DSize);
+        glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxTextureCubeSize);
+        glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mTextureProgram);
+        glDeleteProgram(mBlueProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mTextureProgram;
+    GLint mTextureUniformLocation;
+
+    GLuint mBlueProgram;
+
+    GLint mMaxTexture2DSize;
+    GLint mMaxTextureCubeSize;
+    GLint mMaxRenderbufferSize;
+};
+
+TEST_P(MaxTextureSizeTest, SpecificationTexImage)
+{
+    GLuint tex;
+    glGenTextures(1, &tex);
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    GLsizei textureWidth = mMaxTexture2DSize;
+    GLsizei textureHeight = 64;
+
+    std::vector<GLubyte> data(textureWidth * textureHeight * 4);
+    for (int y = 0; y < textureHeight; y++)
+    {
+        for (int x = 0; x < textureWidth; x++)
+        {
+            GLubyte* pixel = &data[0] + ((y * textureWidth + x) * 4);
+
+            // Draw a gradient, red in direction, green in y direction
+            pixel[0] = static_cast<GLubyte>((float(x) / textureWidth) * 255);
+            pixel[1] = static_cast<GLubyte>((float(y) / textureHeight) * 255);
+            pixel[2] = 0;
+            pixel[3] = 255;
+        }
+    }
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    drawQuad(mTextureProgram, "position", 0.5f);
+
+    std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
+    glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
+
+    for (int y = 1; y < getWindowHeight(); y++)
+    {
+        for (int x = 1; x < getWindowWidth(); x++)
+        {
+            const GLubyte* prevPixel = &pixels[0] + (((y - 1) * getWindowWidth() + (x - 1)) * 4);
+            const GLubyte* curPixel = &pixels[0] + ((y * getWindowWidth() + x) * 4);
+
+            EXPECT_GE(curPixel[0], prevPixel[0]);
+            EXPECT_GE(curPixel[1], prevPixel[1]);
+            EXPECT_EQ(curPixel[2], prevPixel[2]);
+            EXPECT_EQ(curPixel[3], prevPixel[3]);
+        }
+    }
+}
+
+TEST_P(MaxTextureSizeTest, SpecificationTexStorage)
+{
+    if (getClientMajorVersion() < 3 &&
+        (!extensionEnabled("GL_EXT_texture_storage") || !extensionEnabled("GL_OES_rgb8_rgba8")))
+    {
+        return;
+    }
+
+    GLuint tex;
+    glGenTextures(1, &tex);
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    GLsizei textureWidth = 64;
+    GLsizei textureHeight = mMaxTexture2DSize;
+
+    std::vector<GLubyte> data(textureWidth * textureHeight * 4);
+    for (int y = 0; y < textureHeight; y++)
+    {
+        for (int x = 0; x < textureWidth; x++)
+        {
+            GLubyte* pixel = &data[0] + ((y * textureWidth + x) * 4);
+
+            // Draw a gradient, red in direction, green in y direction
+            pixel[0] = static_cast<GLubyte>((float(x) / textureWidth) * 255);
+            pixel[1] = static_cast<GLubyte>((float(y) / textureHeight) * 255);
+            pixel[2] = 0;
+            pixel[3] = 255;
+        }
+    }
+
+    if (getClientMajorVersion() < 3)
+    {
+        glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, textureWidth, textureHeight);
+    }
+    else
+    {
+        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8_OES, textureWidth, textureHeight);
+    }
+    EXPECT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureWidth, textureHeight, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    drawQuad(mTextureProgram, "position", 0.5f);
+
+    std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
+    glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
+
+    for (int y = 1; y < getWindowHeight(); y++)
+    {
+        for (int x = 1; x < getWindowWidth(); x++)
+        {
+            const GLubyte* prevPixel = &pixels[0] + (((y - 1) * getWindowWidth() + (x - 1)) * 4);
+            const GLubyte* curPixel = &pixels[0] + ((y * getWindowWidth() + x) * 4);
+
+            EXPECT_GE(curPixel[0], prevPixel[0]);
+            EXPECT_GE(curPixel[1], prevPixel[1]);
+            EXPECT_EQ(curPixel[2], prevPixel[2]);
+            EXPECT_EQ(curPixel[3], prevPixel[3]);
+        }
+    }
+}
+
+TEST_P(MaxTextureSizeTest, RenderToTexture)
+{
+    if (getClientMajorVersion() < 3 && (!extensionEnabled("GL_ANGLE_framebuffer_blit")))
+    {
+        std::cout << "Test skipped due to missing glBlitFramebuffer[ANGLE] support." << std::endl;
+        return;
+    }
+
+    GLuint fbo = 0;
+    GLuint textureId = 0;
+    // create a 1-level texture at maximum size
+    glGenTextures(1, &textureId);
+    glBindTexture(GL_TEXTURE_2D, textureId);
+
+    GLsizei textureWidth = 64;
+    GLsizei textureHeight = mMaxTexture2DSize;
+
+    // texture setup code
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, textureWidth, textureHeight, 0, GL_BGRA_EXT,
+                 GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    // create an FBO and attach the texture
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
+
+    EXPECT_GL_NO_ERROR();
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    const int frameCount = 64;
+    for (int i = 0; i < frameCount; i++)
+    {
+        // clear the screen
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+        GLubyte clearRed = static_cast<GLubyte>((float(i) / frameCount) * 255);
+        GLubyte clearGreen = 255 - clearRed;
+        GLubyte clearBlue = 0;
+
+        glClearColor(clearRed / 255.0f, clearGreen / 255.0f, clearBlue / 255.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // render blue into the texture
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        drawQuad(mBlueProgram, "position", 0.5f);
+
+        // copy corner of texture to LL corner of window
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, 0);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo);
+        glBlitFramebufferANGLE(0, 0, textureWidth - 1, getWindowHeight() - 1,
+                               0, 0, textureWidth - 1, getWindowHeight() - 1,
+                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, 0);
+        EXPECT_GL_NO_ERROR();
+
+        EXPECT_PIXEL_EQ(textureWidth / 2, getWindowHeight() / 2, 0, 0, 255, 255);
+        EXPECT_PIXEL_EQ(textureWidth + 10, getWindowHeight() / 2, clearRed, clearGreen, clearBlue, 255);
+
+        swapBuffers();
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    glDeleteFramebuffers(1, &fbo);
+    glDeleteTextures(1, &textureId);
+}
+
+// TODO(geofflang): Fix the dependence on glBlitFramebufferANGLE without checks and assuming the
+// default framebuffer is BGRA to enable the GL and GLES backends. (http://anglebug.com/1289)
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(MaxTextureSizeTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3());
diff --git a/src/third_party/angle/src/tests/gl_tests/MipmapTest.cpp b/src/third_party/angle/src/tests/gl_tests/MipmapTest.cpp
new file mode 100644
index 0000000..8487875
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/MipmapTest.cpp
@@ -0,0 +1,1204 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+void TexImageCubeMapFaces(GLint level,
+                          GLenum internalformat,
+                          GLsizei width,
+                          GLenum format,
+                          GLenum type,
+                          void *pixels)
+{
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internalformat, width, width, 0, format,
+                 type, pixels);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internalformat, width, width, 0, format,
+                 type, pixels);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internalformat, width, width, 0, format,
+                 type, pixels);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internalformat, width, width, 0, format,
+                 type, pixels);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internalformat, width, width, 0, format,
+                 type, pixels);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internalformat, width, width, 0, format,
+                 type, pixels);
+}
+
+class BaseMipmapTest : public ANGLETest
+{
+  protected:
+    void clearAndDrawQuad(GLuint program, GLsizei viewportWidth, GLsizei viewportHeight)
+    {
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glViewport(0, 0, viewportWidth, viewportHeight);
+        ASSERT_GL_NO_ERROR();
+
+        drawQuad(program, "position", 0.0f);
+    }
+};
+
+}  // namespace
+
+class MipmapTest : public BaseMipmapTest
+{
+  protected:
+    MipmapTest()
+        : m2DProgram(0),
+          mCubeProgram(0),
+          mTexture2D(0),
+          mTextureCube(0),
+          mLevelZeroBlueInitData(nullptr),
+          mLevelZeroWhiteInitData(nullptr),
+          mLevelOneInitData(nullptr),
+          mLevelTwoInitData(nullptr),
+          mOffscreenFramebuffer(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void setUp2DProgram()
+    {
+        // Vertex Shader source
+        // clang-format off
+        const std::string vs = SHADER_SOURCE
+        (
+            attribute vec4 position;
+            varying vec2 vTexCoord;
+
+            void main()
+            {
+                gl_Position = position;
+                vTexCoord   = (position.xy * 0.5) + 0.5;
+            }
+        );
+
+        // Fragment Shader source
+        const std::string fs = SHADER_SOURCE
+        (
+            precision mediump float;
+
+            uniform sampler2D uTexture;
+            varying vec2 vTexCoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(uTexture, vTexCoord);
+            }
+        );
+        // clang-format on
+
+        m2DProgram = CompileProgram(vs, fs);
+        ASSERT_NE(0u, m2DProgram);
+    }
+
+    void setUpCubeProgram()
+    {
+        // A simple vertex shader for the texture cube
+        // clang-format off
+        const std::string cubeVS = SHADER_SOURCE
+        (
+            attribute vec4 position;
+            varying vec4 vPosition;
+            void main()
+            {
+                gl_Position = position;
+                vPosition = position;
+            }
+        );
+
+        // A very simple fragment shader to sample from the negative-Y face of a texture cube.
+        const std::string cubeFS = SHADER_SOURCE
+        (
+            precision mediump float;
+            uniform samplerCube uTexture;
+            varying vec4 vPosition;
+
+            void main()
+            {
+                gl_FragColor = textureCube(uTexture, vec3(vPosition.x, -1, vPosition.y));
+            }
+        );
+        // clang-format on
+
+        mCubeProgram = CompileProgram(cubeVS, cubeFS);
+        ASSERT_NE(0u, mCubeProgram);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        setUp2DProgram();
+
+        setUpCubeProgram();
+
+        mLevelZeroBlueInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 0, 0, 255); // Blue
+        mLevelZeroWhiteInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 255, 255, 255); // White
+        mLevelOneInitData = createRGBInitData((getWindowWidth() / 2), (getWindowHeight() / 2), 0, 255, 0);   // Green
+        mLevelTwoInitData = createRGBInitData((getWindowWidth() / 4), (getWindowHeight() / 4), 255, 0, 0);   // Red
+
+        glGenFramebuffers(1, &mOffscreenFramebuffer);
+        glGenTextures(1, &mTexture2D);
+
+        // Initialize the texture2D to be empty, and don't use mips.
+        glBindTexture(GL_TEXTURE_2D, mTexture2D);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB,
+                     GL_UNSIGNED_BYTE, nullptr);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+        ASSERT_EQ(getWindowWidth(), getWindowHeight());
+
+        // Create a non-mipped texture cube. Set the negative-Y face to be blue.
+        glGenTextures(1, &mTextureCube);
+        glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
+        TexImageCubeMapFaces(0, GL_RGB, getWindowWidth(), GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+        glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, getWindowWidth(), getWindowWidth(),
+                     0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
+
+        // Complete the texture cube without mipmaps to start with.
+        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(m2DProgram);
+        glDeleteProgram(mCubeProgram);
+        glDeleteFramebuffers(1, &mOffscreenFramebuffer);
+        glDeleteTextures(1, &mTexture2D);
+        glDeleteTextures(1, &mTextureCube);
+
+        SafeDeleteArray(mLevelZeroBlueInitData);
+        SafeDeleteArray(mLevelZeroWhiteInitData);
+        SafeDeleteArray(mLevelOneInitData);
+        SafeDeleteArray(mLevelTwoInitData);
+
+        ANGLETest::TearDown();
+    }
+
+    GLubyte *createRGBInitData(GLint width, GLint height, GLint r, GLint g, GLint b)
+    {
+        GLubyte *data = new GLubyte[3 * width * height];
+
+        for (int i = 0; i < width * height; i+=1)
+        {
+            data[3 * i + 0] = static_cast<GLubyte>(r);
+            data[3 * i + 1] = static_cast<GLubyte>(g);
+            data[3 * i + 2] = static_cast<GLubyte>(b);
+        }
+
+        return data;
+    }
+
+    void clearTextureLevel0(GLenum textarget,
+                            GLuint texture,
+                            GLfloat red,
+                            GLfloat green,
+                            GLfloat blue,
+                            GLfloat alpha)
+    {
+        glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textarget, texture, 0);
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        glClearColor(red, green, blue, alpha);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    }
+
+    GLuint m2DProgram;
+    GLuint mCubeProgram;
+    GLuint mTexture2D;
+    GLuint mTextureCube;
+
+    GLubyte* mLevelZeroBlueInitData;
+    GLubyte* mLevelZeroWhiteInitData;
+    GLubyte* mLevelOneInitData;
+    GLubyte* mLevelTwoInitData;
+
+  private:
+    GLuint mOffscreenFramebuffer;
+};
+
+class MipmapTestES3 : public BaseMipmapTest
+{
+  protected:
+    MipmapTestES3()
+        : mTexture(0),
+          mArrayProgram(0),
+          mTextureArraySliceUniformLocation(-1),
+          m3DProgram(0),
+          mTexture3DSliceUniformLocation(-1),
+          mTexture3DLODUniformLocation(-1),
+          m2DProgram(0)
+
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    std::string vertexShaderSource()
+    {
+        // Don't put "#version ..." on its own line. See [cpp]p1:
+        // "If there are sequences of preprocessing tokens within the list of arguments that
+        //  would otherwise act as preprocessing directives, the behavior is undefined"
+        // clang-format off
+        return SHADER_SOURCE
+        (   #version 300 es\n
+            precision highp float;
+            in vec4 position;
+            out vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = vec4(position.xy, 0.0, 1.0);
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        );
+        // clang-format on
+    }
+
+    void setUpArrayProgram()
+    {
+        const std::string fragmentShaderSourceArray = SHADER_SOURCE
+        (   #version 300 es\n
+            precision highp float;
+            uniform highp sampler2DArray tex;
+            uniform int slice;
+            in vec2 texcoord;
+            out vec4 out_FragColor;
+
+            void main()
+            {
+                out_FragColor = texture(tex, vec3(texcoord, float(slice)));
+            }
+        );
+
+        mArrayProgram = CompileProgram(vertexShaderSource(), fragmentShaderSourceArray);
+        if (mArrayProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTextureArraySliceUniformLocation = glGetUniformLocation(mArrayProgram, "slice");
+        ASSERT_NE(-1, mTextureArraySliceUniformLocation);
+
+        glUseProgram(mArrayProgram);
+        glUseProgram(0);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void setUp3DProgram()
+    {
+        const std::string fragmentShaderSource3D = SHADER_SOURCE
+        (   #version 300 es\n
+            precision highp float;
+            uniform highp sampler3D tex;
+            uniform float slice;
+            uniform float lod;
+            in vec2 texcoord;
+            out vec4 out_FragColor;
+
+            void main()
+            {
+                out_FragColor = textureLod(tex, vec3(texcoord, slice), lod);
+            }
+        );
+
+        m3DProgram = CompileProgram(vertexShaderSource(), fragmentShaderSource3D);
+        if (m3DProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTexture3DSliceUniformLocation = glGetUniformLocation(m3DProgram, "slice");
+        ASSERT_NE(-1, mTexture3DSliceUniformLocation);
+
+        mTexture3DLODUniformLocation = glGetUniformLocation(m3DProgram, "lod");
+        ASSERT_NE(-1, mTexture3DLODUniformLocation);
+
+        glUseProgram(m3DProgram);
+        glUniform1f(mTexture3DLODUniformLocation, 0);
+        glUseProgram(0);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void setUp2DProgram()
+    {
+        // clang-format off
+        const std::string fragmentShaderSource2D = SHADER_SOURCE
+        (   #version 300 es\n
+            precision highp float;
+            uniform highp sampler2D tex;
+            in vec2 texcoord;
+            out vec4 out_FragColor;
+
+            void main()
+            {
+                out_FragColor = texture(tex, texcoord);
+            }
+        );
+        // clang-format on
+
+        m2DProgram = CompileProgram(vertexShaderSource(), fragmentShaderSource2D);
+        ASSERT_NE(0u, m2DProgram);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void setUpCubeProgram()
+    {
+        // A very simple fragment shader to sample from the negative-Y face of a texture cube.
+        // clang-format off
+        const std::string cubeFS = SHADER_SOURCE
+        (   #version 300 es\n
+            precision mediump float;
+            uniform samplerCube uTexture;
+            in vec2 texcoord;
+            out vec4 out_FragColor;
+
+            void main()
+            {
+                out_FragColor = texture(uTexture, vec3(texcoord.x, -1, texcoord.y));
+            }
+        );
+        // clang-format on
+
+        mCubeProgram = CompileProgram(vertexShaderSource(), cubeFS);
+        ASSERT_NE(0u, mCubeProgram);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenTextures(1, &mTexture);
+        ASSERT_GL_NO_ERROR();
+
+        setUpArrayProgram();
+        setUp3DProgram();
+        setUp2DProgram();
+        setUpCubeProgram();
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTexture);
+
+        glDeleteProgram(mArrayProgram);
+        glDeleteProgram(m3DProgram);
+        glDeleteProgram(m2DProgram);
+        glDeleteProgram(mCubeProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mTexture;
+
+    GLuint mArrayProgram;
+    GLint mTextureArraySliceUniformLocation;
+
+    GLuint m3DProgram;
+    GLint mTexture3DSliceUniformLocation;
+    GLint mTexture3DLODUniformLocation;
+
+    GLuint m2DProgram;
+
+    GLuint mCubeProgram;
+};
+
+// This test uses init data for the first three levels of the texture. It passes the level 0 data in, then renders, then level 1, then renders, etc.
+// This ensures that renderers using the zero LOD workaround (e.g. D3D11 FL9_3) correctly pass init data to the mipmapped texture,
+// even if the the zero-LOD texture is currently in use.
+TEST_P(MipmapTest, DISABLED_ThreeLevelsInitData)
+{
+    // Pass in level zero init data.
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
+    ASSERT_GL_NO_ERROR();
+
+    // Disable mips.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+    // Draw a full-sized quad, and check it's blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+
+    // Draw a half-sized quad, and check it's blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
+
+    // Draw a quarter-sized quad, and check it's blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::blue);
+
+    // Complete the texture by initializing the remaining levels.
+    int n = 1;
+    while (getWindowWidth() / (1U << n) >= 1)
+    {
+        glTexImage2D(GL_TEXTURE_2D, n, GL_RGB, getWindowWidth() / (1U << n),
+                     getWindowWidth() / (1U << n), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+        ASSERT_GL_NO_ERROR();
+        n+=1;
+    }
+
+    // Pass in level one init data.
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelOneInitData);
+    ASSERT_GL_NO_ERROR();
+
+    // Draw a full-sized quad, and check it's blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+
+    // Draw a half-sized quad, and check it's blue. We've not enabled mipmaps yet, so our init data for level one shouldn't be used.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
+
+    // Enable mipmaps.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+
+    // Draw a half-sized quad, and check it's green.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::green);
+
+    // Draw a quarter-sized quad, and check it's black, since we've not passed any init data for level two.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::black);
+
+    // Pass in level two init data.
+    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, getWindowWidth() / 4, getWindowHeight() / 4, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelTwoInitData);
+    ASSERT_GL_NO_ERROR();
+
+    // Draw a full-sized quad, and check it's blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+
+    // Draw a half-sized quad, and check it's green.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::green);
+
+    // Draw a quarter-sized quad, and check it's red.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::red);
+
+    // Now disable mipmaps again, and render multiple sized quads. They should all be blue, since level 0 is blue.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::blue);
+
+    // Now reset level 0 to white, keeping mipmaps disabled. Then, render various sized quads. They should be white.
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroWhiteInitData);
+    ASSERT_GL_NO_ERROR();
+
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::white);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::white);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::white);
+
+    // Then enable mipmaps again. The quads should be white, green, red respectively.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::white);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::green);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::red);
+}
+
+// This test generates (and uses) mipmaps on a texture using init data. D3D11 will use a non-renderable TextureStorage for this.
+// The test then disables mips, renders to level zero of the texture, and reenables mips before using the texture again.
+// To do this, D3D11 has to convert the TextureStorage into a renderable one.
+// This test ensures that the conversion works correctly.
+// In particular, on D3D11 Feature Level 9_3 it ensures that both the zero LOD workaround texture AND the 'normal' texture are copied during conversion.
+TEST_P(MipmapTest, GenerateMipmapFromInitDataThenRender)
+{
+    // Pass in initial data so the texture is blue.
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
+
+    // Then generate the mips.
+    glGenerateMipmap(GL_TEXTURE_2D);
+    ASSERT_GL_NO_ERROR();
+
+    // Enable mipmaps.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+
+    // Now draw the texture to various different sized areas.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+
+    // Use mip level 1
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
+
+    // Use mip level 2
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::blue);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Disable mips. Render a quad using the texture and ensure it's blue.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+
+    // Clear level 0 of the texture to red.
+    clearTextureLevel0(GL_TEXTURE_2D, mTexture2D, 1.0f, 0.0f, 0.0f, 1.0f);
+
+    // Reenable mips, and try rendering different-sized quads.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+
+    // Level 0 is now red, so this should render red.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
+
+    // Use mip level 1, blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
+
+    // Use mip level 2, blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::blue);
+}
+
+// This test ensures that mips are correctly generated from a rendered image.
+// In particular, on D3D11 Feature Level 9_3, the clear call will be performed on the zero-level texture, rather than the mipped one.
+// The test ensures that the zero-level texture is correctly copied into the mipped texture before the mipmaps are generated.
+TEST_P(MipmapTest, GenerateMipmapFromRenderedImage)
+{
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    // Clear the texture to blue.
+    clearTextureLevel0(GL_TEXTURE_2D, mTexture2D, 0.0f, 0.0f, 1.0f, 1.0f);
+
+    // Then generate the mips
+    glGenerateMipmap(GL_TEXTURE_2D);
+    ASSERT_GL_NO_ERROR();
+
+    // Enable mips.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+
+    // Now draw the texture to various different sized areas.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+
+    // Use mip level 1
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
+
+    // Use mip level 2
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::blue);
+}
+
+// Test to ensure that rendering to a mipmapped texture works, regardless of whether mipmaps are enabled or not.
+// TODO: This test hits a texture rebind bug in the D3D11 renderer. Fix this.
+TEST_P(MipmapTest, RenderOntoLevelZeroAfterGenerateMipmap)
+{
+    // TODO(geofflang): Figure out why this is broken on AMD OpenGL
+    if ((IsAMD() || IsIntel()) && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel/AMD OpenGL." << std::endl;
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+
+    // Clear the texture to blue.
+    clearTextureLevel0(GL_TEXTURE_2D, mTexture2D, 0.0f, 0.0f, 1.0f, 1.0f);
+
+    // Now, draw the texture to a quad that's the same size as the texture. This draws to the default framebuffer.
+    // The quad should be blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+
+    // Now go back to the texture, and generate mips on it.
+    glGenerateMipmap(GL_TEXTURE_2D);
+    ASSERT_GL_NO_ERROR();
+
+    // Now try rendering the textured quad again. Note: we've not told GL to use the generated mips.
+    // The quad should be blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+
+    // Now tell GL to use the generated mips.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    // Now render the textured quad again. It should be still be blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+
+    // Now render the textured quad to an area smaller than the texture (i.e. to force minification). This should be blue.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::blue);
+
+    // Now clear the texture to green. This just clears the top level. The lower mips should remain blue.
+    clearTextureLevel0(GL_TEXTURE_2D, mTexture2D, 0.0f, 1.0f, 0.0f, 1.0f);
+
+    // Render a textured quad equal in size to the texture. This should be green, since we just cleared level 0.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
+
+    // Render a small textured quad. This forces minification, so should render blue (the color of levels 1+).
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::blue);
+
+    // Disable mipmaps again
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    ASSERT_GL_NO_ERROR();
+
+    // Render a textured quad equal in size to the texture. This should be green, the color of level 0 in the texture.
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
+
+    // Render a small textured quad. This would force minification if mips were enabled, but they're not. Therefore, this should be green.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::green);
+}
+
+// Regression test for a bug that cause mipmaps to only generate using the top left corner as input.
+TEST_P(MipmapTest, MipMapGenerationD3D9Bug)
+{
+    if (!extensionEnabled("GL_EXT_texture_storage") || !extensionEnabled("GL_OES_rgb8_rgba8") ||
+        !extensionEnabled("GL_ANGLE_texture_usage"))
+    {
+        std::cout << "Test skipped due to missing extensions." << std::endl;
+        return;
+    }
+
+    const GLColor mip0Color[4] = {
+        GLColor::red, GLColor::green, GLColor::red, GLColor::green,
+    };
+    const GLColor mip1Color = GLColor(127, 127, 0, 255);
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+    glTexStorage2DEXT(GL_TEXTURE_2D, 2, GL_RGBA8_OES, 2, 2);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color);
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    // Only draw to a 1 pixel viewport so the lower mip is used
+    clearAndDrawQuad(m2DProgram, 1, 1);
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, mip1Color, 1.0);
+}
+
+// This test ensures that the level-zero workaround for TextureCubes (on D3D11 Feature Level 9_3)
+// works as expected. It tests enabling/disabling mipmaps, generating mipmaps, and rendering to level zero.
+TEST_P(MipmapTest, TextureCubeGeneralLevelZero)
+{
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
+
+    // Draw. Since the negative-Y face's is blue, this should be blue.
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+
+    // Generate mipmaps, and render. This should be blue.
+    glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+
+    // Draw using a smaller viewport (to force a lower LOD of the texture). This should still be blue.
+    clearAndDrawQuad(mCubeProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+
+    // Now clear the negative-Y face of the cube to red.
+    clearTextureLevel0(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mTextureCube, 1.0f, 0.0f, 0.0f, 1.0f);
+
+    // Draw using a full-size viewport. This should be red.
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    // Draw using a quarter-size viewport, to force a lower LOD. This should be *BLUE*, since we only cleared level zero
+    // of the negative-Y face to red, and left its mipmaps blue.
+    clearAndDrawQuad(mCubeProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+
+    // Disable mipmaps again, and draw a to a quarter-size viewport.
+    // Since this should use level zero of the texture, this should be *RED*.
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+}
+
+// This test ensures that rendering to level-zero of a TextureCube works as expected.
+TEST_P(MipmapTest, TextureCubeRenderToLevelZero)
+{
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
+
+    // Draw. Since the negative-Y face's is blue, this should be blue.
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+
+    // Now clear the negative-Y face of the cube to red.
+    clearTextureLevel0(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mTextureCube, 1.0f, 0.0f, 0.0f, 1.0f);
+
+    // Draw using a full-size viewport. This should be red.
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    // Draw a to a quarter-size viewport. This should also be red.
+    clearAndDrawQuad(mCubeProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+}
+
+// Creates a mipmapped 2D array texture with three layers, and calls ANGLE's GenerateMipmap.
+// Then tests if the mipmaps are rendered correctly for all three layers.
+TEST_P(MipmapTestES3, MipmapsForTextureArray)
+{
+    int px = getWindowWidth() / 2;
+    int py = getWindowHeight() / 2;
+
+    glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
+
+    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
+
+    // Fill the first layer with red
+    std::vector<GLColor> pixelsRed(16 * 16, GLColor::red);
+    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+                    pixelsRed.data());
+
+    // Fill the second layer with green
+    std::vector<GLColor> pixelsGreen(16 * 16, GLColor::green);
+    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+                    pixelsGreen.data());
+
+    // Fill the third layer with blue
+    std::vector<GLColor> pixelsBlue(16 * 16, GLColor::blue);
+    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+                    pixelsBlue.data());
+
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    EXPECT_GL_NO_ERROR();
+
+    glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mArrayProgram);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Draw the first slice
+    glUniform1i(mTextureArraySliceUniformLocation, 0);
+    drawQuad(mArrayProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
+
+    // Draw the second slice
+    glUniform1i(mTextureArraySliceUniformLocation, 1);
+    drawQuad(mArrayProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+
+    // Draw the third slice
+    glUniform1i(mTextureArraySliceUniformLocation, 2);
+    drawQuad(mArrayProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::blue);
+}
+
+// Create a mipmapped 2D array texture with more layers than width / height, and call
+// GenerateMipmap.
+TEST_P(MipmapTestES3, MipmapForDeepTextureArray)
+{
+    int px = getWindowWidth() / 2;
+    int py = getWindowHeight() / 2;
+
+    glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
+
+    // Fill the whole texture with red.
+    std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
+    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 pixelsRed.data());
+
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    EXPECT_GL_NO_ERROR();
+
+    glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mArrayProgram);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Draw the first slice
+    glUniform1i(mTextureArraySliceUniformLocation, 0);
+    drawQuad(mArrayProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
+
+    // Draw the fourth slice
+    glUniform1i(mTextureArraySliceUniformLocation, 3);
+    drawQuad(mArrayProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
+}
+
+// Creates a mipmapped 3D texture with two layers, and calls ANGLE's GenerateMipmap.
+// Then tests if the mipmaps are rendered correctly for all two layers.
+TEST_P(MipmapTestES3, MipmapsForTexture3D)
+{
+    int px = getWindowWidth() / 2;
+    int py = getWindowHeight() / 2;
+
+    glBindTexture(GL_TEXTURE_3D, mTexture);
+
+    glTexStorage3D(GL_TEXTURE_3D, 5, GL_RGBA8, 16, 16, 2);
+
+    // Fill the first layer with red
+    std::vector<GLColor> pixelsRed(16 * 16, GLColor::red);
+    glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+                    pixelsRed.data());
+
+    // Fill the second layer with green
+    std::vector<GLColor> pixelsGreen(16 * 16, GLColor::green);
+    glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+                    pixelsGreen.data());
+
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    EXPECT_GL_NO_ERROR();
+
+    glGenerateMipmap(GL_TEXTURE_3D);
+
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(m3DProgram);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Mipmap level 0
+    // Draw the first slice
+    glUniform1f(mTexture3DLODUniformLocation, 0.);
+    glUniform1f(mTexture3DSliceUniformLocation, 0.25f);
+    drawQuad(m3DProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
+
+    // Draw the second slice
+    glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
+    drawQuad(m3DProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+
+    // Mipmap level 1
+    // The second mipmap should only have one slice.
+    glUniform1f(mTexture3DLODUniformLocation, 1.);
+    drawQuad(m3DProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_NEAR(px, py, 127, 127, 0, 255, 1.0);
+
+    glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
+    drawQuad(m3DProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_NEAR(px, py, 127, 127, 0, 255, 1.0);
+}
+
+// Create a 2D texture with levels 0-2, call GenerateMipmap with base level 1 so that level 0 stays
+// the same, and then sample levels 0 and 2.
+// GLES 3.0.4 section 3.8.10:
+// "Mipmap generation replaces texel array levels levelbase + 1 through q with arrays derived from
+// the levelbase array, regardless of their previous contents. All other mipmap arrays, including
+// the levelbase array, are left unchanged by this computation."
+TEST_P(MipmapTestES3, GenerateMipmapBaseLevel)
+{
+    if (IsAMD() && IsDesktopOpenGL())
+    {
+        // Observed incorrect rendering on AMD, sampling level 2 returns black.
+        std::cout << "Test skipped on AMD OpenGL." << std::endl;
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    ASSERT_EQ(getWindowWidth(), getWindowHeight());
+
+    // Fill level 0 with blue
+    std::vector<GLColor> pixelsBlue(getWindowWidth() * getWindowHeight(), GLColor::blue);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, pixelsBlue.data());
+
+    // Fill level 1 with red
+    std::vector<GLColor> pixelsRed(getWindowWidth() * getWindowHeight() / 4, GLColor::red);
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth() / 2, getWindowHeight() / 2, 0,
+                 GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
+
+    // Fill level 2 with green
+    std::vector<GLColor> pixelsGreen(getWindowWidth() * getWindowHeight() / 16, GLColor::green);
+    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, getWindowWidth() / 4, getWindowHeight() / 4, 0,
+                 GL_RGBA, GL_UNSIGNED_BYTE, pixelsGreen.data());
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    // The blue level 0 should be untouched by this since base level is 1.
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Draw using level 2. It should be set to red by GenerateMipmap.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::red);
+
+    // Draw using level 0. It should still be blue.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+}
+
+// Create a cube map with levels 0-2, call GenerateMipmap with base level 1 so that level 0 stays
+// the same, and then sample levels 0 and 2.
+// GLES 3.0.4 section 3.8.10:
+// "Mipmap generation replaces texel array levels levelbase + 1 through q with arrays derived from
+// the levelbase array, regardless of their previous contents. All other mipmap arrays, including
+// the levelbase array, are left unchanged by this computation."
+TEST_P(MipmapTestES3, GenerateMipmapCubeBaseLevel)
+{
+    if (IsAMD() && IsDesktopOpenGL())
+    {
+        // Observed incorrect rendering on AMD, sampling level 2 returns black.
+        std::cout << "Test skipped on AMD OpenGL." << std::endl;
+        return;
+    }
+
+    ASSERT_EQ(getWindowWidth(), getWindowHeight());
+
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
+    std::vector<GLColor> pixelsBlue(getWindowWidth() * getWindowWidth(), GLColor::blue);
+    TexImageCubeMapFaces(0, GL_RGBA8, getWindowWidth(), GL_RGBA, GL_UNSIGNED_BYTE,
+                         pixelsBlue.data());
+
+    // Fill level 1 with red
+    std::vector<GLColor> pixelsRed(getWindowWidth() * getWindowWidth() / 4, GLColor::red);
+    TexImageCubeMapFaces(1, GL_RGBA8, getWindowWidth() / 2, GL_RGBA, GL_UNSIGNED_BYTE,
+                         pixelsRed.data());
+
+    // Fill level 2 with green
+    std::vector<GLColor> pixelsGreen(getWindowWidth() * getWindowWidth() / 16, GLColor::green);
+    TexImageCubeMapFaces(2, GL_RGBA8, getWindowWidth() / 4, GL_RGBA, GL_UNSIGNED_BYTE,
+                         pixelsGreen.data());
+
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    // The blue level 0 should be untouched by this since base level is 1.
+    glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Draw using level 2. It should be set to red by GenerateMipmap.
+    clearAndDrawQuad(mCubeProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::red);
+
+    if (IsNVIDIA() && IsOpenGL())
+    {
+        // Observed incorrect rendering on NVIDIA, level zero seems to be incorrectly affected by
+        // GenerateMipmap.
+        std::cout << "Test partially skipped on NVIDIA OpenGL." << std::endl;
+        return;
+    }
+
+    // Draw using level 0. It should still be blue.
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+}
+
+// Create a texture with levels 0-2, call GenerateMipmap with max level 1 so that level 2 stays the
+// same, and then sample levels 1 and 2.
+// GLES 3.0.4 section 3.8.10:
+// "Mipmap generation replaces texel array levels levelbase + 1 through q with arrays derived from
+// the levelbase array, regardless of their previous contents. All other mipmap arrays, including
+// the levelbase array, are left unchanged by this computation."
+TEST_P(MipmapTestES3, GenerateMipmapMaxLevel)
+{
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    // Fill level 0 with blue
+    std::vector<GLColor> pixelsBlue(getWindowWidth() * getWindowHeight(), GLColor::blue);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, pixelsBlue.data());
+
+    // Fill level 1 with red
+    std::vector<GLColor> pixelsRed(getWindowWidth() * getWindowHeight() / 4, GLColor::red);
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth() / 2, getWindowHeight() / 2, 0,
+                 GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
+
+    // Fill level 2 with green
+    std::vector<GLColor> pixelsGreen(getWindowWidth() * getWindowHeight() / 16, GLColor::green);
+    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, getWindowWidth() / 4, getWindowHeight() / 4, 0,
+                 GL_RGBA, GL_UNSIGNED_BYTE, pixelsGreen.data());
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    // The green level 2 should be untouched by this since max level is 1.
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Draw using level 1. It should be set to blue by GenerateMipmap.
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
+
+    // Draw using level 2. It should still be green.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::green);
+}
+
+// Call GenerateMipmap with out-of-range base level. The spec is interpreted so that an out-of-range
+// base level does not have a color-renderable/texture-filterable internal format, so the
+// GenerateMipmap call generates INVALID_OPERATION. GLES 3.0.4 section 3.8.10:
+// "If the levelbase array was not specified with an unsized internal format from table 3.3 or a
+// sized internal format that is both color-renderable and texture-filterable according to table
+// 3.13, an INVALID_OPERATION error is generated."
+TEST_P(MipmapTestES3, GenerateMipmapBaseLevelOutOfRange)
+{
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    // Fill level 0 with blue
+    std::vector<GLColor> pixelsBlue(getWindowWidth() * getWindowHeight(), GLColor::blue);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, pixelsBlue.data());
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1000);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Expecting the out-of-range base level to be treated as not color-renderable and
+    // texture-filterable.
+    glGenerateMipmap(GL_TEXTURE_2D);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Draw using level 0. It should still be blue.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
+}
+
+// Call GenerateMipmap with out-of-range base level on an immutable texture. The base level should
+// be clamped, so the call doesn't generate an error.
+TEST_P(MipmapTestES3, GenerateMipmapBaseLevelOutOfRangeImmutableTexture)
+{
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1000);
+
+    EXPECT_GL_NO_ERROR();
+
+    // This is essentially a no-op, since the texture only has one level.
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    EXPECT_GL_NO_ERROR();
+
+    // The only level of the texture should still be green.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
+}
+
+// A native version of the WebGL2 test tex-base-level-bug.html
+TEST_P(MipmapTestES3, BaseLevelTextureBug)
+{
+    if (IsOpenGL() && IsAMD())
+    {
+        std::cout << "Test skipped on Windows AMD OpenGL." << std::endl;
+        return;
+    }
+
+#if defined(ANGLE_PLATFORM_APPLE)
+    // Regression in 10.12.4 needing workaround -- crbug.com/705865.
+    // Seems to be passing on AMD GPUs. Definitely not NVIDIA.
+    // Probably not Intel.
+    if (IsNVIDIA() || IsIntel())
+    {
+        std::cout << "Test skipped on macOS with NVIDIA and Intel GPUs." << std::endl;
+        return;
+    }
+#endif
+
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+
+    drawQuad(m2DProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    drawQuad(m2DProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+// Note: we run these tests against 9_3 on WARP due to hardware driver issues on Win7
+ANGLE_INSTANTIATE_TEST(MipmapTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE),
+                       ES2_D3D11_FL9_3_WARP(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(MipmapTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/MultisampleCompatibilityTest.cpp b/src/third_party/angle/src/tests/gl_tests/MultisampleCompatibilityTest.cpp
new file mode 100644
index 0000000..e2203be
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/MultisampleCompatibilityTest.cpp
@@ -0,0 +1,444 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MultisampleCompatibilityTest.cpp:
+//   Tests for the EXT_multisample_compatibility extension.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+const GLint kWidth = 64;
+const GLint kHeight = 64;
+
+// test drawing with GL_MULTISAMPLE_EXT enabled/disabled.
+class EXTMultisampleCompatibilityTest : public ANGLETest
+{
+
+protected:
+    EXTMultisampleCompatibilityTest()
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        static const char* v_shader_str =
+            "attribute vec4 a_Position;\n"
+            "void main()\n"
+            "{ gl_Position = a_Position; }";
+
+        static const char* f_shader_str =
+            "precision mediump float;\n"
+            "uniform vec4 color;"
+            "void main() { gl_FragColor = color; }";
+
+        mProgram = CompileProgram(v_shader_str, f_shader_str);
+
+        GLuint position_loc = glGetAttribLocation(mProgram, "a_Position");
+        mColorLoc = glGetUniformLocation(mProgram, "color");
+
+        glGenBuffers(1, &mVBO);
+        glBindBuffer(GL_ARRAY_BUFFER, mVBO);
+        static float vertices[] = {
+            1.0f,  1.0f, -1.0f, 1.0f,  -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
+            -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f,  -1.0f, 1.0f, 1.0f,
+        };
+        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+        glEnableVertexAttribArray(position_loc);
+        glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+    }
+
+    void TearDown() override
+    {
+        glDeleteBuffers(1, &mVBO);
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    void prepareForDraw()
+    {
+        // Create a sample buffer.
+        GLsizei num_samples = 4, max_samples = 0;
+        glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+        num_samples = std::min(num_samples, max_samples);
+
+        glGenRenderbuffers(1, &mSampleRB);
+        glBindRenderbuffer(GL_RENDERBUFFER, mSampleRB);
+        glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, num_samples,
+                                             GL_RGBA8_OES, kWidth, kHeight);
+        GLint param = 0;
+        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
+                                 &param);
+        EXPECT_GE(param, num_samples);
+
+        glGenFramebuffers(1, &mSampleFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                              GL_RENDERBUFFER, mSampleRB);
+        EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+          glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+        // Create another FBO to resolve the multisample buffer into.
+        glGenTextures(1, &mResolveTex);
+        glBindTexture(GL_TEXTURE_2D, mResolveTex);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glGenFramebuffers(1, &mResolveFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mResolveFBO);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                           mResolveTex, 0);
+        EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+          glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+        glUseProgram(mProgram);
+        glViewport(0, 0, kWidth, kHeight);
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        glEnable(GL_BLEND);
+        glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+    }
+
+    void prepareForVerify()
+    {
+        // Resolve.
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleFBO);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFBO);
+        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glBlitFramebufferANGLE(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
+          GL_COLOR_BUFFER_BIT, GL_NEAREST);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, mResolveFBO);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void cleanup()
+    {
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glDeleteFramebuffers(1, &mResolveFBO);
+        glDeleteFramebuffers(1, &mSampleFBO);
+        glDeleteTextures(1, &mResolveTex);
+        glDeleteRenderbuffers(1, &mSampleRB);
+
+        ASSERT_GL_NO_ERROR();
+
+    }
+
+    bool isApplicable() const
+    {
+        return extensionEnabled("GL_EXT_multisample_compatibility") &&
+             extensionEnabled("GL_ANGLE_framebuffer_multisample") &&
+             extensionEnabled("GL_OES_rgb8_rgba8") &&
+             !IsAMD();
+    }
+    GLuint mSampleFBO;
+    GLuint mResolveFBO;
+    GLuint mSampleRB;
+    GLuint mResolveTex;
+
+    GLuint mColorLoc;
+    GLuint mProgram;
+    GLuint mVBO;
+};
+
+} //
+
+// Test simple state tracking
+TEST_P(EXTMultisampleCompatibilityTest, TestStateTracking)
+{
+    if (!isApplicable())
+        return;
+
+    EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
+    glDisable(GL_MULTISAMPLE_EXT);
+    EXPECT_FALSE(glIsEnabled(GL_MULTISAMPLE_EXT));
+    glEnable(GL_MULTISAMPLE_EXT);
+    EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
+
+    EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
+    glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+    EXPECT_TRUE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
+    glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+    EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
+
+    EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+// Test that disabling GL_MULTISAMPLE_EXT is handled correctly.
+TEST_P(EXTMultisampleCompatibilityTest, DrawAndResolve)
+{
+    if (!isApplicable())
+        return;
+
+    static const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
+    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+    static const float kRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
+
+    // Different drivers seem to behave differently with respect to resulting
+    // values. These might be due to different MSAA sample counts causing
+    // different samples to hit.  Other option is driver bugs. Just test that
+    // disabling multisample causes a difference.
+    std::unique_ptr<uint8_t[]> results[3];
+    const GLint kResultSize = kWidth * kHeight * 4;
+    for (int pass = 0; pass < 3; pass++)
+    {
+        prepareForDraw();
+        // Green: from top right to bottom left.
+        glUniform4fv(mColorLoc, 1, kGreen);
+        glDrawArrays(GL_TRIANGLES, 0, 3);
+
+        // Blue: from top left to bottom right.
+        glUniform4fv(mColorLoc, 1, kBlue);
+        glDrawArrays(GL_TRIANGLES, 3, 3);
+
+        // Red, with and without MSAA: from bottom left to top right.
+        if (pass == 1)
+        {
+            glDisable(GL_MULTISAMPLE_EXT);
+        }
+        glUniform4fv(mColorLoc, 1, kRed);
+        glDrawArrays(GL_TRIANGLES, 6, 3);
+        if (pass == 1)
+        {
+            glEnable(GL_MULTISAMPLE_EXT);
+        }
+        prepareForVerify();
+        results[pass].reset(new uint8_t[kResultSize]);
+        memset(results[pass].get(), 123u, kResultSize);
+        glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
+                   results[pass].get());
+
+        cleanup();
+    }
+    EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
+    // Verify that rendering is deterministic, so that the pass above does not
+    // come from non-deterministic rendering.
+    EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
+}
+
+// Test that enabling GL_SAMPLE_ALPHA_TO_ONE_EXT affects rendering.
+TEST_P(EXTMultisampleCompatibilityTest, DrawAlphaOneAndResolve)
+{
+    if (!isApplicable())
+        return;
+
+    // TODO: Figure out why this fails on Android.
+    if (IsAndroid())
+    {
+        std::cout << "Test skipped on Android." << std::endl;
+        return;
+    }
+
+    // SAMPLE_ALPHA_TO_ONE is specified to transform alpha values of
+    // covered samples to 1.0. In order to detect it, we use non-1.0
+    // alpha.
+    static const float kBlue[] = {0.0f, 0.0f, 1.0f, 0.5f};
+    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 0.5f};
+    static const float kRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
+
+    // Different drivers seem to behave differently with respect to resulting
+    // alpha value. These might be due to different MSAA sample counts causing
+    // different samples to hit.  Other option is driver bugs. Testing exact or
+    // even approximate sample values is not that easy.  Thus, just test
+    // representative positions which have fractional pixels, inspecting that
+    // normal rendering is different to SAMPLE_ALPHA_TO_ONE rendering.
+    std::unique_ptr<uint8_t[]> results[3];
+    const GLint kResultSize = kWidth * kHeight * 4;
+
+    for (int pass = 0; pass < 3; ++pass)
+    {
+        prepareForDraw();
+        if (pass == 1)
+        {
+            glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+        }
+        glEnable(GL_MULTISAMPLE_EXT);
+        glUniform4fv(mColorLoc, 1, kGreen);
+        glDrawArrays(GL_TRIANGLES, 0, 3);
+
+        glUniform4fv(mColorLoc, 1, kBlue);
+        glDrawArrays(GL_TRIANGLES, 3, 3);
+
+        glDisable(GL_MULTISAMPLE_EXT);
+        glUniform4fv(mColorLoc, 1, kRed);
+        glDrawArrays(GL_TRIANGLES, 6, 3);
+
+        prepareForVerify();
+        results[pass].reset(new uint8_t[kResultSize]);
+        memset(results[pass].get(), 123u, kResultSize);
+        glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
+            results[pass].get());
+        if (pass == 1)
+        {
+            glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+        }
+
+        cleanup();
+    }
+    EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
+    // Verify that rendering is deterministic, so that the pass above does not
+    // come from non-deterministic rendering.
+    EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
+}
+
+ANGLE_INSTANTIATE_TEST(EXTMultisampleCompatibilityTest, ES2_OPENGL(), ES2_OPENGLES(), ES3_OPENGL());
+
+class MultisampleCompatibilityTest : public ANGLETest
+{
+
+  protected:
+    MultisampleCompatibilityTest()
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void prepareForDraw(GLsizei numSamples)
+    {
+        // Create a sample buffer.
+        glGenRenderbuffers(1, &mSampleRB);
+        glBindRenderbuffer(GL_RENDERBUFFER, mSampleRB);
+        glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, numSamples, GL_RGBA8, kWidth,
+                                              kHeight);
+        GLint param = 0;
+        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &param);
+        EXPECT_GE(param, numSamples);
+        glGenFramebuffers(1, &mSampleFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleRB);
+        EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        // Create another FBO to resolve the multisample buffer into.
+        glGenTextures(1, &mResolveTex);
+        glBindTexture(GL_TEXTURE_2D, mResolveTex);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glGenFramebuffers(1, &mResolveFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mResolveFBO);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mResolveTex, 0);
+        EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        glViewport(0, 0, kWidth, kHeight);
+        glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void prepareForVerify()
+    {
+        // Resolve.
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleFBO);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFBO);
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glBlitFramebufferANGLE(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
+                               GL_NEAREST);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, mResolveFBO);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void cleanup()
+    {
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glDeleteFramebuffers(1, &mResolveFBO);
+        glDeleteFramebuffers(1, &mSampleFBO);
+        glDeleteTextures(1, &mResolveTex);
+        glDeleteRenderbuffers(1, &mSampleRB);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    bool isApplicable() const
+    {
+        return extensionEnabled("GL_ANGLE_framebuffer_multisample") &&
+               extensionEnabled("GL_OES_rgb8_rgba8");
+    }
+
+    GLuint mSampleFBO;
+    GLuint mResolveFBO;
+    GLuint mSampleRB;
+    GLuint mResolveTex;
+};
+
+// Test that enabling GL_SAMPLE_COVERAGE affects rendering.
+TEST_P(MultisampleCompatibilityTest, DrawCoverageAndResolve)
+{
+    if (!isApplicable())
+        return;
+
+    // TODO: Figure out why this fails on Android.
+    if (IsAndroid())
+    {
+        std::cout << "Test skipped on Android." << std::endl;
+        return;
+    }
+
+    const std::string &vertex =
+        "attribute vec4 position;\n"
+        "void main()\n"
+        "{ gl_Position = position; }";
+    const std::string &fragment =
+        "void main()\n"
+        "{ gl_FragColor =  vec4(1.0, 0.0, 0.0, 1.0); }";
+
+    ANGLE_GL_PROGRAM(drawRed, vertex, fragment);
+
+    GLsizei maxSamples = 0;
+    glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
+    int iterationCount = maxSamples + 1;
+    for (int samples = 1; samples < iterationCount; samples++)
+    {
+        prepareForDraw(samples);
+        glEnable(GL_SAMPLE_COVERAGE);
+        glSampleCoverage(1.0, false);
+        drawQuad(drawRed.get(), "position", 0.5f);
+
+        prepareForVerify();
+        GLsizei pixelCount = kWidth * kHeight;
+        std::vector<GLColor> actual(pixelCount, GLColor::black);
+        glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
+        glDisable(GL_SAMPLE_COVERAGE);
+        cleanup();
+
+        std::vector<GLColor> expected(pixelCount, GLColor::red);
+        EXPECT_EQ(expected, actual);
+    }
+}
+
+ANGLE_INSTANTIATE_TEST(MultisampleCompatibilityTest,
+                       ES2_D3D9(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_D3D11(),
+                       ES3_OPENGL(),
+                       ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/ObjectAllocationTest.cpp b/src/third_party/angle/src/tests/gl_tests/ObjectAllocationTest.cpp
new file mode 100644
index 0000000..b0e59f7
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ObjectAllocationTest.cpp
@@ -0,0 +1,54 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ObjectAllocationTest
+//   Tests for object allocations and lifetimes.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class ObjectAllocationTest : public ANGLETest
+{
+  protected:
+    ObjectAllocationTest() {}
+};
+
+// Test that we don't re-allocate a bound framebuffer ID.
+TEST_P(ObjectAllocationTest, BindFramebufferBeforeGen)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, 1);
+    GLuint fbo = 0;
+    glGenFramebuffers(1, &fbo);
+    EXPECT_NE(1u, fbo);
+    glDeleteFramebuffers(1, &fbo);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that we don't re-allocate a bound framebuffer ID, other pattern.
+TEST_P(ObjectAllocationTest, BindFramebufferAfterGen)
+{
+    GLuint firstFBO = 0;
+    glGenFramebuffers(1, &firstFBO);
+    glBindFramebuffer(GL_FRAMEBUFFER, 1);
+    glDeleteFramebuffers(1, &firstFBO);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 2);
+    GLuint secondFBOs[2] = {0};
+    glGenFramebuffers(2, secondFBOs);
+    EXPECT_NE(2u, secondFBOs[0]);
+    EXPECT_NE(2u, secondFBOs[1]);
+    glDeleteFramebuffers(2, secondFBOs);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+}  // anonymous namespace
+
+ANGLE_INSTANTIATE_TEST(ObjectAllocationTest, ES3_OPENGL(), ES3_D3D11());
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/gl_tests/OcclusionQueriesTest.cpp b/src/third_party/angle/src/tests/gl_tests/OcclusionQueriesTest.cpp
new file mode 100644
index 0000000..5c24f8b
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/OcclusionQueriesTest.cpp
@@ -0,0 +1,366 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "system_utils.h"
+#include "test_utils/ANGLETest.h"
+#include "random_utils.h"
+
+using namespace angle;
+
+class OcclusionQueriesTest : public ANGLETest
+{
+  protected:
+    OcclusionQueriesTest() : mProgram(0), mRNG(1)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string passthroughVS = SHADER_SOURCE
+        (
+            attribute highp vec4 position;
+            void main(void)
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string passthroughPS = SHADER_SOURCE
+        (
+            precision highp float;
+            void main(void)
+            {
+               gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(passthroughVS, passthroughPS);
+        ASSERT_NE(0u, mProgram);
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+    RNG mRNG;
+};
+
+TEST_P(OcclusionQueriesTest, IsOccluded)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_occlusion_query_boolean"))
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_occlusion_query_boolean are not available."
+                  << std::endl;
+        return;
+    }
+
+    glDepthMask(GL_TRUE);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    // draw a quad at depth 0.3
+    glEnable(GL_DEPTH_TEST);
+    glUseProgram(mProgram);
+    drawQuad(mProgram, "position", 0.3f);
+    glUseProgram(0);
+
+    EXPECT_GL_NO_ERROR();
+
+    GLuint query = 0;
+    glGenQueriesEXT(1, &query);
+    glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
+    drawQuad(mProgram, "position", 0.8f); // this quad should be occluded by first quad
+    glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
+
+    EXPECT_GL_NO_ERROR();
+
+    swapBuffers();
+
+    GLuint ready = GL_FALSE;
+    while (ready == GL_FALSE)
+    {
+        angle::Sleep(0);
+        glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
+    }
+
+    GLuint result = GL_TRUE;
+    glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteQueriesEXT(1, &query);
+
+    EXPECT_GLENUM_EQ(GL_FALSE, result);
+}
+
+TEST_P(OcclusionQueriesTest, IsNotOccluded)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_occlusion_query_boolean"))
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_occlusion_query_boolean are not available."
+                  << std::endl;
+        return;
+    }
+
+    glDepthMask(GL_TRUE);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    EXPECT_GL_NO_ERROR();
+
+    GLuint query = 0;
+    glGenQueriesEXT(1, &query);
+    glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
+    drawQuad(mProgram, "position", 0.8f); // this quad should not be occluded
+    glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
+
+    EXPECT_GL_NO_ERROR();
+
+    swapBuffers();
+
+    GLuint result = GL_TRUE;
+    glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result); // will block waiting for result
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteQueriesEXT(1, &query);
+
+    EXPECT_GLENUM_EQ(GL_TRUE, result);
+}
+
+TEST_P(OcclusionQueriesTest, Errors)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_occlusion_query_boolean"))
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_occlusion_query_boolean are not available."
+                  << std::endl;
+        return;
+    }
+
+    glDepthMask(GL_TRUE);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    EXPECT_GL_NO_ERROR();
+
+    GLuint query = 0;
+    GLuint query2 = 0;
+    glGenQueriesEXT(1, &query);
+
+    EXPECT_EQ(glIsQueryEXT(query), GL_FALSE);
+    EXPECT_EQ(glIsQueryEXT(query2), GL_FALSE);
+
+    glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, 0); // can't pass 0 as query id
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
+    glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, query2); // can't initiate a query while one's already active
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    EXPECT_EQ(glIsQueryEXT(query), GL_TRUE);
+    EXPECT_EQ(glIsQueryEXT(query2), GL_FALSE); // have not called begin
+
+    drawQuad(mProgram, "position", 0.8f); // this quad should not be occluded
+    glEndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); // no active query for this target
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
+
+    glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, query); // can't begin a query as a different type than previously used
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, query2); // have to call genqueries first
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glGenQueriesEXT(1, &query2);
+    glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, query2); // should be ok now
+    EXPECT_EQ(glIsQueryEXT(query2), GL_TRUE);
+
+    drawQuad(mProgram, "position", 0.3f); // this should draw in front of other quad
+    glDeleteQueriesEXT(1, &query2); // should delete when query becomes inactive
+    glEndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); // should not incur error; should delete query + 1 at end of execution.
+    EXPECT_GL_NO_ERROR();
+
+    swapBuffers();
+
+    EXPECT_GL_NO_ERROR();
+
+    GLuint ready = GL_FALSE;
+    glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT, &ready); // this query is now deleted
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that running multiple simultaneous queries from multiple EGL contexts returns the correct
+// result for each query.  Helps expose bugs in ANGLE's virtual contexts.
+TEST_P(OcclusionQueriesTest, MultiContext)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_occlusion_query_boolean"))
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_occlusion_query_boolean are not available."
+                  << std::endl;
+        return;
+    }
+
+    if (GetParam() == ES2_D3D9() || GetParam() == ES2_D3D11() || GetParam() == ES3_D3D11())
+    {
+        std::cout << "Test skipped because the D3D backends cannot support simultaneous queries on "
+                     "multiple contexts yet."
+                  << std::endl;
+        return;
+    }
+
+    glDepthMask(GL_TRUE);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    // draw a quad at depth 0.5
+    glEnable(GL_DEPTH_TEST);
+    drawQuad(mProgram, "position", 0.5f);
+
+    EGLWindow *window = getEGLWindow();
+
+    EGLDisplay display = window->getDisplay();
+    EGLConfig config   = window->getConfig();
+    EGLSurface surface = window->getSurface();
+
+    EGLint contextAttributes[] = {
+        EGL_CONTEXT_MAJOR_VERSION_KHR,
+        GetParam().majorVersion,
+        EGL_CONTEXT_MINOR_VERSION_KHR,
+        GetParam().minorVersion,
+        EGL_NONE,
+    };
+
+    const size_t passCount = 5;
+    struct ContextInfo
+    {
+        EGLContext context;
+        GLuint program;
+        GLuint query;
+        bool visiblePasses[passCount];
+        bool shouldPass;
+    };
+
+    ContextInfo contexts[] = {
+        {
+            EGL_NO_CONTEXT, 0, 0, {false, false, false, false, false}, false,
+        },
+        {
+            EGL_NO_CONTEXT, 0, 0, {false, true, false, true, false}, true,
+        },
+        {
+            EGL_NO_CONTEXT, 0, 0, {false, false, false, false, false}, false,
+        },
+        {
+            EGL_NO_CONTEXT, 0, 0, {true, true, false, true, true}, true,
+        },
+        {
+            EGL_NO_CONTEXT, 0, 0, {false, true, true, true, true}, true,
+        },
+        {
+            EGL_NO_CONTEXT, 0, 0, {true, false, false, true, false}, true,
+        },
+        {
+            EGL_NO_CONTEXT, 0, 0, {false, false, false, false, false}, false,
+        },
+        {
+            EGL_NO_CONTEXT, 0, 0, {false, false, false, false, false}, false,
+        },
+    };
+
+    for (auto &context : contexts)
+    {
+        context.context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
+        ASSERT_NE(context.context, EGL_NO_CONTEXT);
+
+        eglMakeCurrent(display, surface, surface, context.context);
+
+        const std::string passthroughVS = SHADER_SOURCE
+        (
+            attribute highp vec4 position;
+            void main(void)
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string passthroughPS = SHADER_SOURCE
+        (
+            precision highp float;
+            void main(void)
+            {
+               gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
+            }
+        );
+
+        context.program = CompileProgram(passthroughVS, passthroughPS);
+        ASSERT_NE(context.program, 0u);
+
+        glDepthMask(GL_FALSE);
+        glEnable(GL_DEPTH_TEST);
+
+        glGenQueriesEXT(1, &context.query);
+        glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, context.query);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    for (size_t pass = 0; pass < passCount; pass++)
+    {
+        for (const auto &context : contexts)
+        {
+            eglMakeCurrent(display, surface, surface, context.context);
+
+            float depth = context.visiblePasses[pass] ? mRNG.randomFloatBetween(0.0f, 0.4f)
+                                                      : mRNG.randomFloatBetween(0.6f, 1.0f);
+            drawQuad(context.program, "position", depth);
+
+            EXPECT_GL_NO_ERROR();
+        }
+    }
+
+    for (const auto &context : contexts)
+    {
+        eglMakeCurrent(display, surface, surface, context.context);
+        glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
+
+        GLuint result = GL_TRUE;
+        glGetQueryObjectuivEXT(context.query, GL_QUERY_RESULT_EXT, &result);
+
+        EXPECT_GL_NO_ERROR();
+
+        GLuint expectation = context.shouldPass ? GL_TRUE : GL_FALSE;
+        EXPECT_EQ(expectation, result);
+    }
+
+    eglMakeCurrent(display, surface, surface, window->getContext());
+
+    for (auto &context : contexts)
+    {
+        eglDestroyContext(display, context.context);
+        context.context = EGL_NO_CONTEXT;
+    }
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(OcclusionQueriesTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/PBOExtensionTest.cpp b/src/third_party/angle/src/tests/gl_tests/PBOExtensionTest.cpp
new file mode 100644
index 0000000..bc6179a
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/PBOExtensionTest.cpp
@@ -0,0 +1,144 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class PBOExtensionTest : public ANGLETest
+{
+  protected:
+    PBOExtensionTest()
+    {
+        setWindowWidth(32);
+        setWindowHeight(32);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        if (extensionEnabled("NV_pixel_buffer_object"))
+        {
+            glGenBuffers(1, &mPBO);
+            glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+            glBufferData(GL_PIXEL_PACK_BUFFER, 4 * getWindowWidth() * getWindowHeight(), nullptr,
+                         GL_STATIC_DRAW);
+            glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+
+            const char *vertexShaderSrc =
+                SHADER_SOURCE(attribute vec4 aTest; attribute vec2 aPosition; varying vec4 vTest;
+
+                              void main() {
+                                  vTest        = aTest;
+                                  gl_Position  = vec4(aPosition, 0.0, 1.0);
+                                  gl_PointSize = 1.0;
+                              });
+
+            const char *fragmentShaderSrc =
+                SHADER_SOURCE(precision mediump float; varying vec4 vTest;
+
+                              void main() { gl_FragColor = vTest; });
+
+            mProgram = CompileProgram(vertexShaderSrc, fragmentShaderSrc);
+
+            glGenBuffers(1, &mPositionVBO);
+            glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
+            glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_DYNAMIC_DRAW);
+            glBindBuffer(GL_ARRAY_BUFFER, 0);
+        }
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        ANGLETest::TearDown();
+
+        glDeleteBuffers(1, &mPBO);
+        glDeleteProgram(mProgram);
+    }
+
+    GLuint mPBO;
+    GLuint mProgram;
+    GLuint mPositionVBO;
+};
+
+TEST_P(PBOExtensionTest, PBOWithOtherTarget)
+{
+    if (extensionEnabled("NV_pixel_buffer_object"))
+    {
+        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        EXPECT_GL_NO_ERROR();
+
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+        glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+        glBindBuffer(GL_ARRAY_BUFFER, mPBO);
+
+        void *mappedPtr        = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
+        unsigned char *dataPtr = static_cast<unsigned char *>(mappedPtr);
+        EXPECT_GL_NO_ERROR();
+
+        EXPECT_EQ(255, dataPtr[0]);
+        EXPECT_EQ(0, dataPtr[1]);
+        EXPECT_EQ(0, dataPtr[2]);
+        EXPECT_EQ(255, dataPtr[3]);
+
+        glUnmapBufferOES(GL_ARRAY_BUFFER);
+    }
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(PBOExtensionTest, PBOWithExistingData)
+{
+    if (extensionEnabled("NV_pixel_buffer_object"))
+    {
+        // Clear backbuffer to red
+        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        EXPECT_GL_NO_ERROR();
+
+        // Read 16x16 region from red backbuffer to PBO
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+        glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+        // Clear backbuffer to green
+        glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        EXPECT_GL_NO_ERROR();
+
+        // Read 16x16 region from green backbuffer to PBO at offset 16
+        glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(16));
+        void *mappedPtr        = glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
+        unsigned char *dataPtr = static_cast<unsigned char *>(mappedPtr);
+        EXPECT_GL_NO_ERROR();
+
+        // Test pixel 0 is red (existing data)
+        EXPECT_EQ(255, dataPtr[0]);
+        EXPECT_EQ(0, dataPtr[1]);
+        EXPECT_EQ(0, dataPtr[2]);
+        EXPECT_EQ(255, dataPtr[3]);
+
+        // Test pixel 16 is green (new data)
+        EXPECT_EQ(0, dataPtr[16 * 4 + 0]);
+        EXPECT_EQ(255, dataPtr[16 * 4 + 1]);
+        EXPECT_EQ(0, dataPtr[16 * 4 + 2]);
+        EXPECT_EQ(255, dataPtr[16 * 4 + 3]);
+
+        glUnmapBufferOES(GL_PIXEL_PACK_BUFFER);
+    }
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(PBOExtensionTest, ES2_D3D11(), ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/PackUnpackTest.cpp b/src/third_party/angle/src/tests/gl_tests/PackUnpackTest.cpp
new file mode 100644
index 0000000..032504b
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/PackUnpackTest.cpp
@@ -0,0 +1,268 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PackUnpackTest:
+//   Tests the corrrectness of opengl 4.1 emulation of pack/unpack built-in functions.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class PackUnpackTest : public ANGLETest
+{
+  protected:
+    PackUnpackTest()
+    {
+        setWindowWidth(16);
+        setWindowHeight(16);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        // Vertex Shader source
+        const std::string vs = SHADER_SOURCE
+        (   #version 300 es\n
+            precision mediump float;
+            in vec4 position;
+
+            void main()
+            {
+                gl_Position = position;
+            }
+        );
+
+        // clang-format off
+        // Fragment Shader source
+        const std::string sNormFS = SHADER_SOURCE
+        (   #version 300 es\n
+            precision mediump float;
+            uniform mediump vec2 v;
+            layout(location = 0) out mediump vec4 fragColor;
+
+            void main()
+            {
+                uint u = packSnorm2x16(v);
+                vec2 r = unpackSnorm2x16(u);
+                fragColor = vec4(r, 0.0, 1.0);
+            }
+        );
+
+        // Fragment Shader source
+        const std::string uNormFS = SHADER_SOURCE
+        (   #version 300 es\n
+            precision mediump float;
+            uniform mediump vec2 v;
+            layout(location = 0) out mediump vec4 fragColor;
+
+            void main()
+            {
+                uint u = packUnorm2x16(v);
+                vec2 r = unpackUnorm2x16(u);
+                fragColor = vec4(r, 0.0, 1.0);
+            }
+        );
+
+        // Fragment Shader source
+        const std::string halfFS = SHADER_SOURCE
+        (   #version 300 es\n
+            precision mediump float;
+            uniform mediump vec2 v;
+            layout(location = 0) out mediump vec4 fragColor;
+
+             void main()
+             {
+                 uint u = packHalf2x16(v);
+                 vec2 r = unpackHalf2x16(u);
+                 fragColor = vec4(r, 0.0, 1.0);
+             }
+        );
+        // clang-format on
+
+        mSNormProgram = CompileProgram(vs, sNormFS);
+        mUNormProgram = CompileProgram(vs, uNormFS);
+        mHalfProgram = CompileProgram(vs, halfFS);
+        if (mSNormProgram == 0 || mUNormProgram == 0 || mHalfProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        glGenTextures(1, &mOffscreenTexture2D);
+        glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
+        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, getWindowWidth(), getWindowHeight());
+
+        glGenFramebuffers(1, &mOffscreenFramebuffer);
+        glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOffscreenTexture2D, 0);
+
+        glViewport(0, 0, 16, 16);
+
+        const GLfloat color[] = { 1.0f, 1.0f, 0.0f, 1.0f };
+        glClearBufferfv(GL_COLOR, 0, color);
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mOffscreenTexture2D);
+        glDeleteFramebuffers(1, &mOffscreenFramebuffer);
+        glDeleteProgram(mSNormProgram);
+        glDeleteProgram(mUNormProgram);
+        glDeleteProgram(mHalfProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    void compareBeforeAfter(GLuint program, float input1, float input2)
+    {
+        compareBeforeAfter(program, input1, input2, input1, input2);
+    }
+
+    void compareBeforeAfter(GLuint program, float input1, float input2, float expect1, float expect2)
+    {
+        GLint vec2Location = glGetUniformLocation(program, "v");
+
+        glUseProgram(program);
+        glUniform2f(vec2Location, input1, input2);
+
+        drawQuad(program, "position", 0.5f);
+
+        ASSERT_GL_NO_ERROR();
+
+        GLfloat p[2] = { 0 };
+        glReadPixels(8, 8, 1, 1, GL_RG, GL_FLOAT, p);
+
+        ASSERT_GL_NO_ERROR();
+
+        static const double epsilon = 0.0005;
+        EXPECT_NEAR(p[0], expect1, epsilon);
+        EXPECT_NEAR(p[1], expect2, epsilon);
+    }
+
+    GLuint mSNormProgram;
+    GLuint mUNormProgram;
+    GLuint mHalfProgram;
+    GLuint mOffscreenFramebuffer;
+    GLuint mOffscreenTexture2D;
+};
+
+// Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating normal floating numbers.
+TEST_P(PackUnpackTest, PackUnpackSnormNormal)
+{
+    // Expect the shader to output the same value as the input
+    compareBeforeAfter(mSNormProgram, 0.5f, -0.2f);
+    compareBeforeAfter(mSNormProgram, -0.35f, 0.75f);
+    compareBeforeAfter(mSNormProgram, 0.00392f, -0.99215f);
+    compareBeforeAfter(mSNormProgram, 1.0f, -0.00392f);
+}
+
+// Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating normal floating
+// numbers.
+TEST_P(PackUnpackTest, PackUnpackUnormNormal)
+{
+    // Expect the shader to output the same value as the input
+    compareBeforeAfter(mUNormProgram, 0.5f, 0.2f, 0.5f, 0.2f);
+    compareBeforeAfter(mUNormProgram, 0.35f, 0.75f, 0.35f, 0.75f);
+    compareBeforeAfter(mUNormProgram, 0.00392f, 0.99215f, 0.00392f, 0.99215f);
+    compareBeforeAfter(mUNormProgram, 1.0f, 0.00392f, 1.0f, 0.00392f);
+}
+
+// Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating normal floating numbers.
+TEST_P(PackUnpackTest, PackUnpackHalfNormal)
+{
+    // TODO(cwallez) figure out why it is broken on Intel on Mac
+#if defined(ANGLE_PLATFORM_APPLE)
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel on Mac." << std::endl;
+        return;
+    }
+#endif
+
+    // Expect the shader to output the same value as the input
+    compareBeforeAfter(mHalfProgram, 0.5f, -0.2f);
+    compareBeforeAfter(mHalfProgram, -0.35f, 0.75f);
+    compareBeforeAfter(mHalfProgram, 0.00392f, -0.99215f);
+    compareBeforeAfter(mHalfProgram, 1.0f, -0.00392f);
+}
+
+// Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating subnormal floating numbers.
+TEST_P(PackUnpackTest, PackUnpackSnormSubnormal)
+{
+    // Expect the shader to output the same value as the input
+    compareBeforeAfter(mSNormProgram, 0.00001f, -0.00001f);
+}
+
+// Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating subnormal
+// floating numbers.
+TEST_P(PackUnpackTest, PackUnpackUnormSubnormal)
+{
+    // Expect the shader to output the same value as the input for positive numbers and clamp
+    // to [0, 1]
+    compareBeforeAfter(mUNormProgram, 0.00001f, -0.00001f, 0.00001f, 0.0f);
+}
+
+// Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating subnormal floating numbers.
+TEST_P(PackUnpackTest, PackUnpackHalfSubnormal)
+{
+    // Expect the shader to output the same value as the input
+    compareBeforeAfter(mHalfProgram, 0.00001f, -0.00001f);
+}
+
+// Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating zero floating numbers.
+TEST_P(PackUnpackTest, PackUnpackSnormZero)
+{
+    // Expect the shader to output the same value as the input
+    compareBeforeAfter(mSNormProgram, 0.00000f, -0.00000f);
+}
+
+// Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating zero floating
+// numbers.
+TEST_P(PackUnpackTest, PackUnpackUnormZero)
+{
+    compareBeforeAfter(mUNormProgram, 0.00000f, -0.00000f, 0.00000f, 0.00000f);
+}
+
+// Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating zero floating numbers.
+TEST_P(PackUnpackTest, PackUnpackHalfZero)
+{
+    // Expect the shader to output the same value as the input
+    compareBeforeAfter(mHalfProgram, 0.00000f, -0.00000f);
+}
+
+// Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating overflow floating
+// numbers.
+TEST_P(PackUnpackTest, PackUnpackUnormOverflow)
+{
+    // Expect the shader to clamp the input to [0, 1]
+    compareBeforeAfter(mUNormProgram, 67000.0f, -67000.0f, 1.0f, 0.0f);
+}
+
+// Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating overflow floating numbers.
+TEST_P(PackUnpackTest, PackUnpackSnormOverflow)
+{
+    // Expect the shader to clamp the input to [-1, 1]
+    compareBeforeAfter(mSNormProgram, 67000.0f, -67000.0f, 1.0f, -1.0f);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(PackUnpackTest,
+                       ES3_OPENGL(3, 3),
+                       ES3_OPENGL(4, 0),
+                       ES3_OPENGL(4, 1),
+                       ES3_OPENGL(4, 2),
+                       ES3_OPENGL(4, 3),
+                       ES3_OPENGL(4, 4),
+                       ES3_OPENGL(4, 5),
+                       ES3_OPENGLES());
+}
diff --git a/src/third_party/angle/src/tests/gl_tests/PathRenderingTest.cpp b/src/third_party/angle/src/tests/gl_tests/PathRenderingTest.cpp
new file mode 100644
index 0000000..62f38b3
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/PathRenderingTest.cpp
@@ -0,0 +1,1984 @@
+//
+// Copyright 2016 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.
+//
+// CHROMIUMPathRenderingTest
+//   Test CHROMIUM subset of NV_path_rendering
+//   This extension allows to render geometric paths as first class GL objects.
+
+#include "test_utils/ANGLETest.h"
+#include "shader_utils.h"
+
+#include "common/angleutils.h"
+
+#include <cmath>
+#include <cstring>
+#include <cstddef>
+#include <fstream>
+
+using namespace angle;
+
+namespace
+{
+
+bool CheckPixels(GLint x,
+                 GLint y,
+                 GLsizei width,
+                 GLsizei height,
+                 GLint tolerance,
+                 const angle::GLColor &color)
+{
+    for (GLint yy = 0; yy < height; ++yy)
+    {
+        for (GLint xx = 0; xx < width; ++xx)
+        {
+            const auto px = x + xx;
+            const auto py = y + yy;
+            EXPECT_PIXEL_NEAR(px, py, color.R, color.G, color.B, color.A, tolerance);
+        }
+    }
+
+    return true;
+}
+
+void ExpectEqualMatrix(const GLfloat *expected, const GLfloat *actual)
+{
+    for (size_t i = 0; i < 16; ++i)
+    {
+        EXPECT_EQ(expected[i], actual[i]);
+    }
+}
+
+void ExpectEqualMatrix(const GLfloat *expected, const GLint *actual)
+{
+    for (size_t i = 0; i < 16; ++i)
+    {
+        EXPECT_EQ(static_cast<GLint>(std::roundf(expected[i])), actual[i]);
+    }
+}
+
+const int kResolution = 300;
+
+class CHROMIUMPathRenderingTest : public ANGLETest
+{
+  protected:
+    CHROMIUMPathRenderingTest()
+    {
+        setWindowWidth(kResolution);
+        setWindowHeight(kResolution);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+
+    bool isApplicable() const { return extensionEnabled("GL_CHROMIUM_path_rendering"); }
+
+    void tryAllDrawFunctions(GLuint path, GLenum err)
+    {
+        glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
+        EXPECT_GL_ERROR(err);
+
+        glStencilFillPathCHROMIUM(path, GL_COUNT_DOWN_CHROMIUM, 0x7F);
+        EXPECT_GL_ERROR(err);
+
+        glStencilStrokePathCHROMIUM(path, 0x80, 0x80);
+        EXPECT_GL_ERROR(err);
+
+        glCoverFillPathCHROMIUM(path, GL_BOUNDING_BOX_CHROMIUM);
+        EXPECT_GL_ERROR(err);
+
+        glCoverStrokePathCHROMIUM(path, GL_BOUNDING_BOX_CHROMIUM);
+        EXPECT_GL_ERROR(err);
+
+        glStencilThenCoverStrokePathCHROMIUM(path, 0x80, 0x80, GL_BOUNDING_BOX_CHROMIUM);
+        EXPECT_GL_ERROR(err);
+
+        glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
+                                           GL_BOUNDING_BOX_CHROMIUM);
+        EXPECT_GL_ERROR(err);
+    }
+};
+
+// Test setting and getting of path rendering matrices.
+TEST_P(CHROMIUMPathRenderingTest, TestMatrix)
+{
+    if (!isApplicable())
+        return;
+
+    static const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+                                                0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+
+    static const GLfloat kSeqMatrix[16] = {0.5f,   -0.5f,  -0.1f,  -0.8f, 4.4f,   5.5f,
+                                           6.6f,   7.7f,   8.8f,   9.9f,  10.11f, 11.22f,
+                                           12.33f, 13.44f, 14.55f, 15.66f};
+
+    static const GLenum kMatrixModes[] = {GL_PATH_MODELVIEW_CHROMIUM, GL_PATH_PROJECTION_CHROMIUM};
+
+    static const GLenum kGetMatrixModes[] = {GL_PATH_MODELVIEW_MATRIX_CHROMIUM,
+                                             GL_PATH_PROJECTION_MATRIX_CHROMIUM};
+
+    for (size_t i = 0; i < 2; ++i)
+    {
+        GLfloat mf[16];
+        GLint mi[16];
+        std::memset(mf, 0, sizeof(mf));
+        std::memset(mi, 0, sizeof(mi));
+        glGetFloatv(kGetMatrixModes[i], mf);
+        glGetIntegerv(kGetMatrixModes[i], mi);
+        ExpectEqualMatrix(kIdentityMatrix, mf);
+        ExpectEqualMatrix(kIdentityMatrix, mi);
+
+        glMatrixLoadfCHROMIUM(kMatrixModes[i], kSeqMatrix);
+        std::memset(mf, 0, sizeof(mf));
+        std::memset(mi, 0, sizeof(mi));
+        glGetFloatv(kGetMatrixModes[i], mf);
+        glGetIntegerv(kGetMatrixModes[i], mi);
+        ExpectEqualMatrix(kSeqMatrix, mf);
+        ExpectEqualMatrix(kSeqMatrix, mi);
+
+        glMatrixLoadIdentityCHROMIUM(kMatrixModes[i]);
+        std::memset(mf, 0, sizeof(mf));
+        std::memset(mi, 0, sizeof(mi));
+        glGetFloatv(kGetMatrixModes[i], mf);
+        glGetIntegerv(kGetMatrixModes[i], mi);
+        ExpectEqualMatrix(kIdentityMatrix, mf);
+        ExpectEqualMatrix(kIdentityMatrix, mi);
+
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+// Test that trying to set incorrect matrix target results
+// in a GL error.
+TEST_P(CHROMIUMPathRenderingTest, TestMatrixErrors)
+{
+    if (!isApplicable())
+        return;
+
+    GLfloat mf[16];
+    std::memset(mf, 0, sizeof(mf));
+
+    glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM, mf);
+    ASSERT_GL_NO_ERROR();
+
+    glMatrixLoadIdentityCHROMIUM(GL_PATH_PROJECTION_CHROMIUM);
+    ASSERT_GL_NO_ERROR();
+
+    // Test that invalid matrix targets fail.
+    glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM - 1, mf);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // Test that invalid matrix targets fail.
+    glMatrixLoadIdentityCHROMIUM(GL_PATH_PROJECTION_CHROMIUM + 1);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+// Test basic path create and delete.
+TEST_P(CHROMIUMPathRenderingTest, TestGenDelete)
+{
+    if (!isApplicable())
+        return;
+
+    // This is unspecified in NV_path_rendering.
+    EXPECT_EQ(0u, glGenPathsCHROMIUM(0));
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    GLuint path = glGenPathsCHROMIUM(1);
+    EXPECT_NE(0u, path);
+    glDeletePathsCHROMIUM(path, 1);
+    ASSERT_GL_NO_ERROR();
+
+    GLuint first_path = glGenPathsCHROMIUM(5);
+    EXPECT_NE(0u, first_path);
+    glDeletePathsCHROMIUM(first_path, 5);
+    ASSERT_GL_NO_ERROR();
+
+    // Test deleting paths that are not actually allocated:
+    // "unused names in /paths/ are silently ignored".
+    first_path = glGenPathsCHROMIUM(5);
+    EXPECT_NE(0u, first_path);
+    glDeletePathsCHROMIUM(first_path, 6);
+    ASSERT_GL_NO_ERROR();
+
+    GLsizei big_range = 0xffff;
+    first_path = glGenPathsCHROMIUM(big_range);
+    EXPECT_NE(0u, first_path);
+    glDeletePathsCHROMIUM(first_path, big_range);
+    ASSERT_GL_NO_ERROR();
+
+    // Test glIsPathCHROMIUM(). A path object is not considered a path untill
+    // it has actually been specified with a path data.
+
+    path = glGenPathsCHROMIUM(1);
+    ASSERT_TRUE(glIsPathCHROMIUM(path) == GL_FALSE);
+
+    // specify the data.
+    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+    GLfloat coords[] = {50.0f, 50.0f};
+    glPathCommandsCHROMIUM(path, 2, commands, 2, GL_FLOAT, coords);
+    ASSERT_TRUE(glIsPathCHROMIUM(path) == GL_TRUE);
+    glDeletePathsCHROMIUM(path, 1);
+    ASSERT_TRUE(glIsPathCHROMIUM(path) == GL_FALSE);
+}
+
+// Test incorrect path creation and deletion and expect GL errors.
+TEST_P(CHROMIUMPathRenderingTest, TestGenDeleteErrors)
+{
+    if (!isApplicable())
+        return;
+
+    // GenPaths / DeletePaths tests.
+    // std::numeric_limits<GLuint>::max() is wrong for GLsizei.
+    GLuint first_path = glGenPathsCHROMIUM(std::numeric_limits<GLuint>::max());
+    EXPECT_EQ(first_path, 0u);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    first_path = glGenPathsCHROMIUM(-1);
+    EXPECT_EQ(0u, first_path);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glDeletePathsCHROMIUM(1, -5);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    first_path = glGenPathsCHROMIUM(-1);
+    EXPECT_EQ(0u, first_path);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+// Test setting and getting path parameters.
+TEST_P(CHROMIUMPathRenderingTest, TestPathParameter)
+{
+    if (!isApplicable())
+        return;
+
+    GLuint path = glGenPathsCHROMIUM(1);
+
+    // specify the data.
+    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+    GLfloat coords[] = {50.0f, 50.0f};
+    glPathCommandsCHROMIUM(path, 2, commands, 2, GL_FLOAT, coords);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_TRUE(glIsPathCHROMIUM(path) == GL_TRUE);
+
+    static const GLenum kEndCaps[] = {GL_FLAT_CHROMIUM, GL_SQUARE_CHROMIUM, GL_ROUND_CHROMIUM};
+    for (std::size_t i = 0; i < 3; ++i)
+    {
+        GLint x;
+        glPathParameteriCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, static_cast<GLenum>(kEndCaps[i]));
+        ASSERT_GL_NO_ERROR();
+        glGetPathParameterivCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, &x);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(kEndCaps[i], static_cast<GLenum>(x));
+
+        GLfloat f;
+        glPathParameterfCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM,
+                                 static_cast<GLfloat>(kEndCaps[(i + 1) % 3]));
+        glGetPathParameterfvCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, &f);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(kEndCaps[(i + 1) % 3], static_cast<GLenum>(f));
+    }
+
+    static const GLenum kJoinStyles[] = {GL_MITER_REVERT_CHROMIUM, GL_BEVEL_CHROMIUM,
+                                         GL_ROUND_CHROMIUM};
+    for (std::size_t i = 0; i < 3; ++i)
+    {
+        GLint x;
+        glPathParameteriCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM,
+                                 static_cast<GLenum>(kJoinStyles[i]));
+        ASSERT_GL_NO_ERROR();
+        glGetPathParameterivCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM, &x);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(kJoinStyles[i], static_cast<GLenum>(x));
+
+        GLfloat f;
+        glPathParameterfCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM,
+                                 static_cast<GLfloat>(kJoinStyles[(i + 1) % 3]));
+        ASSERT_GL_NO_ERROR();
+        glGetPathParameterfvCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM, &f);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(kJoinStyles[(i + 1) % 3], static_cast<GLenum>(f));
+    }
+
+    {
+        glPathParameterfCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, 5.0f);
+        ASSERT_GL_NO_ERROR();
+
+        GLfloat f;
+        glGetPathParameterfvCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, &f);
+        EXPECT_EQ(5.0f, f);
+    }
+
+    glDeletePathsCHROMIUM(path, 1);
+}
+
+// Test that setting incorrect path parameter generates GL error.
+TEST_P(CHROMIUMPathRenderingTest, TestPathParameterErrors)
+{
+    if (!isApplicable())
+        return;
+
+    GLuint path = glGenPathsCHROMIUM(1);
+
+    // PathParameter*: Wrong value for the pname should fail.
+    glPathParameteriCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM, GL_FLAT_CHROMIUM);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    glPathParameterfCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, GL_MITER_REVERT_CHROMIUM);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // PathParameter*: Wrong floating-point value should fail.
+    glPathParameterfCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, -0.1f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // PathParameter*: Wrong pname should fail.
+    glPathParameteriCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM - 1, 5);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    glDeletePathsCHROMIUM(path, 1);
+}
+
+// Test expected path object state.
+TEST_P(CHROMIUMPathRenderingTest, TestPathObjectState)
+{
+    if (!isApplicable())
+        return;
+
+    glViewport(0, 0, kResolution, kResolution);
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    glStencilMask(0xffffffff);
+    glClearStencil(0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
+    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+    ASSERT_GL_NO_ERROR();
+
+    // Test that trying to draw non-existing paths does not produce errors or results.
+    GLuint non_existing_paths[] = {0, 55, 74744};
+    for (auto &p : non_existing_paths)
+    {
+        EXPECT_TRUE(glIsPathCHROMIUM(p) == GL_FALSE);
+        ASSERT_GL_NO_ERROR();
+        tryAllDrawFunctions(p, GL_NO_ERROR);
+    }
+
+    // Path name marked as used but without path object state causes
+    // a GL error upon any draw command.
+    GLuint path = glGenPathsCHROMIUM(1);
+    EXPECT_TRUE(glIsPathCHROMIUM(path) == GL_FALSE);
+    tryAllDrawFunctions(path, GL_INVALID_OPERATION);
+    glDeletePathsCHROMIUM(path, 1);
+
+    // Document a bit of an inconsistency: path name marked as used but without
+    // path object state causes a GL error upon any draw command (tested above).
+    // Path name that had path object state, but then was "cleared", still has a
+    // path object state, even though the state is empty.
+    path = glGenPathsCHROMIUM(1);
+    EXPECT_TRUE(glIsPathCHROMIUM(path) == GL_FALSE);
+
+    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+    GLfloat coords[] = {50.0f, 50.0f};
+    glPathCommandsCHROMIUM(path, 2, commands, 2, GL_FLOAT, coords);
+    EXPECT_TRUE(glIsPathCHROMIUM(path) == GL_TRUE);
+
+    glPathCommandsCHROMIUM(path, 0, nullptr, 0, GL_FLOAT, nullptr);
+    EXPECT_TRUE(glIsPathCHROMIUM(path) == GL_TRUE);  // The surprise.
+
+    tryAllDrawFunctions(path, GL_NO_ERROR);
+    glDeletePathsCHROMIUM(path, 1);
+
+    // Make sure nothing got drawn by the drawing commands that should not produce
+    // anything.
+    const angle::GLColor black = {0, 0, 0, 0};
+    EXPECT_TRUE(CheckPixels(0, 0, kResolution, kResolution, 0, black));
+}
+
+// Test that trying to use path object that doesn't exist generates
+// a GL error.
+TEST_P(CHROMIUMPathRenderingTest, TestUnnamedPathsErrors)
+{
+    if (!isApplicable())
+        return;
+
+    // Unnamed paths: Trying to create a path object with non-existing path name
+    // produces error.  (Not a error in real NV_path_rendering).
+    ASSERT_GL_NO_ERROR();
+    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+    GLfloat coords[] = {50.0f, 50.0f};
+    glPathCommandsCHROMIUM(555, 2, commands, 2, GL_FLOAT, coords);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // PathParameter*: Using non-existing path object produces error.
+    ASSERT_GL_NO_ERROR();
+    glPathParameterfCHROMIUM(555, GL_PATH_STROKE_WIDTH_CHROMIUM, 5.0f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    ASSERT_GL_NO_ERROR();
+    glPathParameteriCHROMIUM(555, GL_PATH_JOIN_STYLE_CHROMIUM, GL_ROUND_CHROMIUM);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test that setting incorrect path data generates a GL error.
+TEST_P(CHROMIUMPathRenderingTest, TestPathCommandsErrors)
+{
+    if (!isApplicable())
+        return;
+
+    static const GLenum kInvalidCoordType = GL_NONE;
+
+    GLuint path        = glGenPathsCHROMIUM(1);
+    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+    GLfloat coords[]   = {50.0f, 50.0f};
+
+    glPathCommandsCHROMIUM(path, 2, commands, -4, GL_FLOAT, coords);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glPathCommandsCHROMIUM(path, -1, commands, 2, GL_FLOAT, coords);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glPathCommandsCHROMIUM(path, 2, commands, 2, kInvalidCoordType, coords);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // incorrect number of coordinates
+    glPathCommandsCHROMIUM(path, 2, commands, std::numeric_limits<GLsizei>::max(), GL_FLOAT,
+                           coords);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // This should fail due to cmd count + coord count * short size.
+    glPathCommandsCHROMIUM(path, 2, commands, std::numeric_limits<GLsizei>::max(), GL_SHORT,
+                           coords);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glDeletePathsCHROMIUM(path, 1);
+}
+
+// Test that trying to render a path with invalid arguments
+// generates a GL error.
+TEST_P(CHROMIUMPathRenderingTest, TestPathRenderingInvalidArgs)
+{
+    if (!isApplicable())
+        return;
+
+    GLuint path = glGenPathsCHROMIUM(1);
+    glPathCommandsCHROMIUM(path, 0, nullptr, 0, GL_FLOAT, nullptr);
+
+    // Verify that normal calls work.
+    glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
+    ASSERT_GL_NO_ERROR();
+    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F, GL_BOUNDING_BOX_CHROMIUM);
+    ASSERT_GL_NO_ERROR();
+
+    // Using invalid fill mode causes INVALID_ENUM.
+    glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM - 1, 0x7F);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM - 1, 0x7F,
+                                       GL_BOUNDING_BOX_CHROMIUM);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // Using invalid cover mode causes INVALID_ENUM.
+    glCoverFillPathCHROMIUM(path, GL_CONVEX_HULL_CHROMIUM - 1);
+    EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
+    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
+                                       GL_BOUNDING_BOX_CHROMIUM + 1);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // Using mask+1 not being power of two causes INVALID_VALUE with up/down fill mode
+    glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x40);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_DOWN_CHROMIUM, 12, GL_BOUNDING_BOX_CHROMIUM);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // check incorrect instance parameters.
+
+    // CoverFillPathInstanced
+    {
+        glCoverFillPathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
+                                         GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glCoverFillPathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, GL_CONVEX_HULL_CHROMIUM, GL_NONE,
+                                         nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, GL_CONVEX_HULL_CHROMIUM,
+                                         GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_UNSIGNED_INT, GL_NONE,
+                                         nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
+                                         GL_UNSIGNED_INT, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
+                                         GL_TRANSLATE_X_CHROMIUM, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    }
+
+    // CoverStrokePathInstanced
+    {
+        glCoverStrokePathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
+                                           GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glCoverStrokePathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, GL_CONVEX_HULL_CHROMIUM, GL_NONE,
+                                           nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, GL_CONVEX_HULL_CHROMIUM,
+                                           GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_UNSIGNED_INT, GL_NONE,
+                                           nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
+                                           GL_UNSIGNED_INT, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
+                                           GL_TRANSLATE_X_CHROMIUM, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    }
+
+    // StencilFillPathInstanced
+    {
+        glStencilFillPathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x0,
+                                           GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glStencilFillPathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x0,
+                                           GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, GL_COUNT_UP_CHROMIUM,
+                                           0x0, GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_UNSIGNED_INT, 0x0,
+                                           GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x2,
+                                           GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x0,
+                                           GL_UNSIGNED_INT, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x0,
+                                           GL_TRANSLATE_X_CHROMIUM, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    }
+
+    // StencilStrokePathInstanced
+    {
+        glStencilStrokePathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, 0x00, 0x00, GL_NONE,
+                                             nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glStencilStrokePathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, 0x00, 0x00, GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, 0x00, 0x00, GL_NONE,
+                                             nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glStencilStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x00, 0x00,
+                                             GL_UNSIGNED_INT, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x00, 0x00,
+                                             GL_TRANSLATE_X_CHROMIUM, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    }
+
+    // StencilThenCoverFillPathInstanced
+    {
+        glStencilThenCoverFillPathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0,
+                                                    GL_COUNT_UP_CHROMIUM, 0, GL_COUNT_UP_CHROMIUM,
+                                                    GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
+                                                    0, GL_COUNT_UP_CHROMIUM, GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0,
+                                                    GL_CONVEX_HULL_CHROMIUM, 0,
+                                                    GL_COUNT_UP_CHROMIUM, GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_UNSIGNED_INT,
+                                                    0, GL_COUNT_UP_CHROMIUM, GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0,
+                                                    GL_CONVEX_HULL_CHROMIUM, 0, GL_UNSIGNED_INT,
+                                                    GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0,
+                                                    GL_CONVEX_HULL_CHROMIUM, 0,
+                                                    GL_COUNT_UP_CHROMIUM, GL_FLOAT, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilThenCoverFillPathInstancedCHROMIUM(
+            1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM, 0, GL_COUNT_UP_CHROMIUM,
+            GL_TRANSLATE_X_CHROMIUM, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    }
+
+    // StencilThenCoverStrokePathInstanced
+    {
+        glStencilThenCoverStrokePathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, 0x0, 0x0,
+                                                      GL_CONVEX_HULL_CHROMIUM, GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, 0x0, 0x0,
+                                                      GL_CONVEX_HULL_CHROMIUM, GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, 0x0, 0x0,
+                                                      GL_CONVEX_HULL_CHROMIUM, GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x0, 0x0,
+                                                      GL_FLOAT, GL_NONE, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x0, 0x0,
+                                                      GL_CONVEX_HULL_CHROMIUM, GL_FLOAT, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x0, 0x0,
+                                                      GL_CONVEX_HULL_CHROMIUM,
+                                                      GL_TRANSLATE_X_CHROMIUM, nullptr);
+        EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    }
+
+    glDeletePathsCHROMIUM(path, 1);
+}
+
+const GLfloat kProjectionMatrix[16] = {2.0f / kResolution,
+                                       0.0f,
+                                       0.0f,
+                                       0.0f,
+                                       0.0f,
+                                       2.0f / kResolution,
+                                       0.0f,
+                                       0.0f,
+                                       0.0f,
+                                       0.0f,
+                                       -1.0f,
+                                       0.0f,
+                                       -1.0f,
+                                       -1.0f,
+                                       0.0f,
+                                       1.0f};
+
+class CHROMIUMPathRenderingDrawTest : public ANGLETest
+{
+  protected:
+    CHROMIUMPathRenderingDrawTest()
+    {
+        setWindowWidth(kResolution);
+        setWindowHeight(kResolution);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+
+    bool isApplicable() const { return extensionEnabled("GL_CHROMIUM_path_rendering"); }
+
+    void setupStateForTestPattern()
+    {
+        glViewport(0, 0, kResolution, kResolution);
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glStencilMask(0xffffffff);
+        glClearStencil(0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+        glEnable(GL_STENCIL_TEST);
+
+        static const char *kVertexShaderSource =
+            "void main() {\n"
+            "  gl_Position = vec4(1.0); \n"
+            "}";
+
+        static const char *kFragmentShaderSource =
+            "precision mediump float;\n"
+            "uniform vec4 color;\n"
+            "void main() {\n"
+            "  gl_FragColor = color;\n"
+            "}";
+
+        GLuint program = CompileProgram(kVertexShaderSource, kFragmentShaderSource);
+        glUseProgram(program);
+        mColorLoc = glGetUniformLocation(program, "color");
+        glDeleteProgram(program);
+
+        // Set up orthogonal projection with near/far plane distance of 2.
+        glMatrixLoadfCHROMIUM(GL_PATH_PROJECTION_CHROMIUM, kProjectionMatrix);
+        glMatrixLoadIdentityCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void setupPathStateForTestPattern(GLuint path)
+    {
+        static const GLubyte kCommands[] = {GL_MOVE_TO_CHROMIUM, GL_LINE_TO_CHROMIUM,
+                                            GL_QUADRATIC_CURVE_TO_CHROMIUM,
+                                            GL_CUBIC_CURVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
+
+        static const GLfloat kCoords[] = {50.0f, 50.0f, 75.0f, 75.0f, 100.0f, 62.5f, 50.0f,
+                                          25.5f, 0.0f,  62.5f, 50.0f, 50.0f,  25.0f, 75.0f};
+
+        glPathCommandsCHROMIUM(path, 5, kCommands, 14, GL_FLOAT, kCoords);
+        glPathParameterfCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, 5.0f);
+        glPathParameterfCHROMIUM(path, GL_PATH_MITER_LIMIT_CHROMIUM, 1.0f);
+        glPathParameterfCHROMIUM(path, GL_PATH_STROKE_BOUND_CHROMIUM, .02f);
+        glPathParameteriCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM, GL_ROUND_CHROMIUM);
+        glPathParameteriCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, GL_SQUARE_CHROMIUM);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void verifyTestPatternFill(GLfloat flx, GLfloat fly)
+    {
+        static const GLint kFillCoords[]  = {55, 54, 50, 28, 66, 63};
+        static const angle::GLColor kBlue = {0, 0, 255, 255};
+
+        GLint x = static_cast<GLint>(flx);
+        GLint y = static_cast<GLint>(fly);
+
+        for (size_t i = 0; i < 6; i += 2)
+        {
+            GLint fx = kFillCoords[i];
+            GLint fy = kFillCoords[i + 1];
+            EXPECT_TRUE(CheckPixels(x + fx, y + fy, 1, 1, 0, kBlue));
+        }
+    }
+    void verifyTestPatternBg(GLfloat fx, GLfloat fy)
+    {
+        static const GLint kBackgroundCoords[]     = {80, 80, 20, 20, 90, 1};
+        static const angle::GLColor kExpectedColor = {0, 0, 0, 0};
+
+        GLint x = static_cast<GLint>(fx);
+        GLint y = static_cast<GLint>(fy);
+
+        for (size_t i = 0; i < 6; i += 2)
+        {
+            GLint bx = kBackgroundCoords[i];
+            GLint by = kBackgroundCoords[i + 1];
+            EXPECT_TRUE(CheckPixels(x + bx, y + by, 1, 1, 0, kExpectedColor));
+        }
+    }
+
+    void verifyTestPatternStroke(GLfloat fx, GLfloat fy)
+    {
+        GLint x = static_cast<GLint>(fx);
+        GLint y = static_cast<GLint>(fy);
+
+        // Inside the stroke we should have green.
+        static const angle::GLColor kGreen = {0, 255, 0, 255};
+        EXPECT_TRUE(CheckPixels(x + 50, y + 53, 1, 1, 0, kGreen));
+        EXPECT_TRUE(CheckPixels(x + 26, y + 76, 1, 1, 0, kGreen));
+
+        // Outside the path we should have black.
+        static const angle::GLColor black = {0, 0, 0, 0};
+        EXPECT_TRUE(CheckPixels(x + 10, y + 10, 1, 1, 0, black));
+        EXPECT_TRUE(CheckPixels(x + 80, y + 80, 1, 1, 0, black));
+    }
+
+    GLuint mColorLoc;
+};
+
+// Tests that basic path rendering functions work.
+TEST_P(CHROMIUMPathRenderingDrawTest, TestPathRendering)
+{
+    if (!isApplicable())
+        return;
+
+    static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
+    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+
+    setupStateForTestPattern();
+
+    GLuint path = glGenPathsCHROMIUM(1);
+    setupPathStateForTestPattern(path);
+
+    // Do the stencil fill, cover fill, stencil stroke, cover stroke
+    // in unconventional order:
+    // 1) stencil the stroke in stencil high bit
+    // 2) stencil the fill in low bits
+    // 3) cover the fill
+    // 4) cover the stroke
+    // This is done to check that glPathStencilFunc works, eg the mask
+    // goes through. Stencil func is not tested ATM, for simplicity.
+
+    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
+    glStencilStrokePathCHROMIUM(path, 0x80, 0x80);
+
+    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
+    glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
+
+    glStencilFunc(GL_LESS, 0, 0x7F);
+    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+    glUniform4fv(mColorLoc, 1, kBlue);
+    glCoverFillPathCHROMIUM(path, GL_BOUNDING_BOX_CHROMIUM);
+
+    glStencilFunc(GL_EQUAL, 0x80, 0x80);
+    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+    glUniform4fv(mColorLoc, 1, kGreen);
+    glCoverStrokePathCHROMIUM(path, GL_CONVEX_HULL_CHROMIUM);
+
+    glDeletePathsCHROMIUM(path, 1);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Verify the image.
+    verifyTestPatternFill(0, 0);
+    verifyTestPatternBg(0, 0);
+    verifyTestPatternStroke(0, 0);
+}
+
+// Test that StencilThen{Stroke,Fill} path rendering functions work
+TEST_P(CHROMIUMPathRenderingDrawTest, TestPathRenderingThenFunctions)
+{
+    if (!isApplicable())
+        return;
+
+    static float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
+    static float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+
+    setupStateForTestPattern();
+
+    GLuint path = glGenPathsCHROMIUM(1);
+    setupPathStateForTestPattern(path);
+
+    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
+    glStencilFunc(GL_EQUAL, 0x80, 0x80);
+    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+    glUniform4fv(mColorLoc, 1, kGreen);
+    glStencilThenCoverStrokePathCHROMIUM(path, 0x80, 0x80, GL_BOUNDING_BOX_CHROMIUM);
+
+    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
+    glStencilFunc(GL_LESS, 0, 0x7F);
+    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+    glUniform4fv(mColorLoc, 1, kBlue);
+    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F, GL_CONVEX_HULL_CHROMIUM);
+
+    glDeletePathsCHROMIUM(path, 1);
+
+    // Verify the image.
+    verifyTestPatternFill(0, 0);
+    verifyTestPatternBg(0, 0);
+    verifyTestPatternStroke(0, 0);
+}
+
+// Tests that drawing with *Instanced functions work.
+TEST_P(CHROMIUMPathRenderingDrawTest, TestPathRenderingInstanced)
+{
+    if (!isApplicable())
+        return;
+
+    static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
+    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+
+    setupStateForTestPattern();
+
+    GLuint path = glGenPathsCHROMIUM(1);
+    setupPathStateForTestPattern(path);
+
+    const GLuint kPaths[]                             = {1, 1, 1, 1, 1};
+    const GLsizei kPathCount                          = 5;
+    const GLfloat kShapeSize                          = 80.0f;
+    static const GLfloat kTransforms[kPathCount * 12] = {
+        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,           0.0f,       0.0f,
+        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, kShapeSize,     0.0f,       0.0f,
+        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, kShapeSize * 2, 0.0f,       0.0f,
+        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,           kShapeSize, 0.0f,
+        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, kShapeSize,     kShapeSize, 0.0f};
+
+    // The test pattern is the same as in the simple draw case above,
+    // except that the path is drawn kPathCount times with different offsets.
+    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
+    glStencilStrokePathInstancedCHROMIUM(kPathCount, GL_UNSIGNED_INT, kPaths, path - 1, 0x80, 0x80,
+                                         GL_AFFINE_3D_CHROMIUM, kTransforms);
+
+    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
+    glUniform4fv(mColorLoc, 1, kBlue);
+    glStencilFillPathInstancedCHROMIUM(kPathCount, GL_UNSIGNED_INT, kPaths, path - 1,
+                                       GL_COUNT_UP_CHROMIUM, 0x7F, GL_AFFINE_3D_CHROMIUM,
+                                       kTransforms);
+
+    ASSERT_GL_NO_ERROR();
+
+    glStencilFunc(GL_LESS, 0, 0x7F);
+    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+    glCoverFillPathInstancedCHROMIUM(kPathCount, GL_UNSIGNED_INT, kPaths, path - 1,
+                                     GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
+                                     GL_AFFINE_3D_CHROMIUM, kTransforms);
+
+    ASSERT_GL_NO_ERROR();
+
+    glStencilFunc(GL_EQUAL, 0x80, 0x80);
+    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+    glUniform4fv(mColorLoc, 1, kGreen);
+    glCoverStrokePathInstancedCHROMIUM(kPathCount, GL_UNSIGNED_INT, kPaths, path - 1,
+                                       GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
+                                       GL_AFFINE_3D_CHROMIUM, kTransforms);
+
+    ASSERT_GL_NO_ERROR();
+
+    glDeletePathsCHROMIUM(path, 1);
+
+    // Verify the image.
+    verifyTestPatternFill(0.0f, 0.0f);
+    verifyTestPatternBg(0.0f, 0.0f);
+    verifyTestPatternStroke(0.0f, 0.0f);
+
+    verifyTestPatternFill(kShapeSize, 0.0f);
+    verifyTestPatternBg(kShapeSize, 0.0f);
+    verifyTestPatternStroke(kShapeSize, 0.0f);
+
+    verifyTestPatternFill(kShapeSize * 2, 0.0f);
+    verifyTestPatternBg(kShapeSize * 2, 0.0f);
+    verifyTestPatternStroke(kShapeSize * 2, 0.0f);
+
+    verifyTestPatternFill(0.0f, kShapeSize);
+    verifyTestPatternBg(0.0f, kShapeSize);
+    verifyTestPatternStroke(0.0f, kShapeSize);
+
+    verifyTestPatternFill(kShapeSize, kShapeSize);
+    verifyTestPatternBg(kShapeSize, kShapeSize);
+    verifyTestPatternStroke(kShapeSize, kShapeSize);
+}
+
+// Test that instanced fill/stroke then cover functions work.
+TEST_P(CHROMIUMPathRenderingDrawTest, TestPathRenderingThenFunctionsInstanced)
+{
+    if (!isApplicable())
+        return;
+
+    static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
+    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+
+    setupStateForTestPattern();
+
+    GLuint path = glGenPathsCHROMIUM(1);
+    setupPathStateForTestPattern(path);
+
+    const GLuint kPaths[]              = {1, 1, 1, 1, 1};
+    const GLsizei kPathCount           = 5;
+    const GLfloat kShapeSize           = 80.0f;
+    static const GLfloat kTransforms[] = {
+        0.0f, 0.0f, kShapeSize, 0.0f,       kShapeSize * 2,
+        0.0f, 0.0f, kShapeSize, kShapeSize, kShapeSize,
+    };
+
+    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
+    glStencilFunc(GL_EQUAL, 0x80, 0x80);
+    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+    glUniform4fv(mColorLoc, 1, kGreen);
+    glStencilThenCoverStrokePathInstancedCHROMIUM(
+        kPathCount, GL_UNSIGNED_INT, kPaths, path - 1, 0x80, 0x80,
+        GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_TRANSLATE_2D_CHROMIUM, kTransforms);
+
+    ASSERT_GL_NO_ERROR();
+
+    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
+    glStencilFunc(GL_LESS, 0, 0x7F);
+    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+    glUniform4fv(mColorLoc, 1, kBlue);
+    glStencilThenCoverFillPathInstancedCHROMIUM(
+        kPathCount, GL_UNSIGNED_INT, kPaths, path - 1, GL_COUNT_UP_CHROMIUM, 0x7F,
+        GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_TRANSLATE_2D_CHROMIUM, kTransforms);
+
+    ASSERT_GL_NO_ERROR();
+
+    glDeletePathsCHROMIUM(path, 1);
+
+    // Verify the image.
+    verifyTestPatternFill(0.0f, 0.0f);
+    verifyTestPatternBg(0.0f, 0.0f);
+    verifyTestPatternStroke(0.0f, 0.0f);
+
+    verifyTestPatternFill(kShapeSize, 0.0f);
+    verifyTestPatternBg(kShapeSize, 0.0f);
+    verifyTestPatternStroke(kShapeSize, 0.0f);
+
+    verifyTestPatternFill(kShapeSize * 2, 0.0f);
+    verifyTestPatternBg(kShapeSize * 2, 0.0f);
+    verifyTestPatternStroke(kShapeSize * 2, 0.0f);
+
+    verifyTestPatternFill(0.0f, kShapeSize);
+    verifyTestPatternBg(0.0f, kShapeSize);
+    verifyTestPatternStroke(0.0f, kShapeSize);
+
+    verifyTestPatternFill(kShapeSize, kShapeSize);
+    verifyTestPatternBg(kShapeSize, kShapeSize);
+    verifyTestPatternStroke(kShapeSize, kShapeSize);
+}
+
+
+// This class implements a test that draws a grid of v-shapes. The grid is
+// drawn so that even rows (from the bottom) are drawn with DrawArrays and odd
+// rows are drawn with path rendering.  It can be used to test various texturing
+// modes, comparing how the fill would work in normal GL rendering and how to
+// setup same sort of fill with path rendering.
+// The texturing test is parametrized to run the test with and without
+// ANGLE name hashing.
+class CHROMIUMPathRenderingWithTexturingTest : public ANGLETest
+{
+  protected:
+    CHROMIUMPathRenderingWithTexturingTest() : mProgram(0)
+    {
+        setWindowWidth(kResolution);
+        setWindowHeight(kResolution);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+
+    bool isApplicable() const { return extensionEnabled("GL_CHROMIUM_path_rendering"); }
+
+    void TearDown() override
+    {
+        if (mProgram)
+        {
+            glDeleteProgram(mProgram);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        ANGLETest::TearDown();
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+        mBindUniformLocation = reinterpret_cast<PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC>(
+            eglGetProcAddress("glBindUniformLocationCHROMIUM"));
+    }
+
+    // Sets up the GL program state for the test.
+    // Vertex shader needs at least following variables:
+    //  uniform mat4 view_matrix;
+    //  uniform mat? color_matrix; (accessible with kColorMatrixLocation)
+    //  uniform vec2 model_translate;
+    //  attribute vec2 position;
+    //  varying vec4 color;
+    //
+    // Fragment shader needs at least following variables:
+    //  varying vec4 color;
+    //
+    //  (? can be anything)
+    void compileProgram(const char *vertexShaderSource, const char *fragmentShaderSource)
+    {
+        glViewport(0, 0, kResolution, kResolution);
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glStencilMask(0xffffffff);
+        glClearStencil(0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+        ASSERT_GL_NO_ERROR();
+
+        GLuint vShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
+        GLuint fShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
+        ASSERT_NE(0u, vShader);
+        ASSERT_NE(0u, fShader);
+
+        mProgram = glCreateProgram();
+
+        glAttachShader(mProgram, vShader);
+        glAttachShader(mProgram, fShader);
+        glDeleteShader(vShader);
+        glDeleteShader(fShader);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void bindProgram()
+    {
+        glBindAttribLocation(mProgram, kPositionLocation, "position");
+        mBindUniformLocation(mProgram, kViewMatrixLocation, "view_matrix");
+        mBindUniformLocation(mProgram, kColorMatrixLocation, "color_matrix");
+        mBindUniformLocation(mProgram, kModelTranslateLocation, "model_translate");
+        glBindFragmentInputLocationCHROMIUM(mProgram, kColorFragmentInputLocation, "color");
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    bool linkProgram()
+    {
+        glLinkProgram(mProgram);
+
+        GLint linked = 0;
+        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+        if (linked)
+        {
+            glUseProgram(mProgram);
+        }
+
+        return (linked == 1);
+    }
+
+    void drawTestPattern()
+    {
+        // This v-shape is used both for DrawArrays and path rendering.
+        static const GLfloat kVertices[] = {75.0f, 75.0f, 50.0f, 25.5f, 50.0f, 50.0f, 25.0f, 75.0f};
+
+        GLuint vbo = 0;
+        glGenBuffers(1, &vbo);
+        glBindBuffer(GL_ARRAY_BUFFER, vbo);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW);
+        glEnableVertexAttribArray(kPositionLocation);
+        glVertexAttribPointer(kPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+        // Setup state for drawing the shape with path rendering.
+        glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
+        glStencilFunc(GL_LESS, 0, 0x7F);
+        glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+        glMatrixLoadfCHROMIUM(GL_PATH_PROJECTION_CHROMIUM, kProjectionMatrix);
+        glMatrixLoadIdentityCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM);
+
+        static const GLubyte kCommands[] = {GL_MOVE_TO_CHROMIUM, GL_LINE_TO_CHROMIUM,
+                                            GL_LINE_TO_CHROMIUM, GL_LINE_TO_CHROMIUM,
+                                            GL_CLOSE_PATH_CHROMIUM};
+
+        static const GLfloat kCoords[] = {
+            kVertices[0], kVertices[1], kVertices[2], kVertices[3],
+            kVertices[6], kVertices[7], kVertices[4], kVertices[5],
+        };
+
+        GLuint path = glGenPathsCHROMIUM(1);
+        glPathCommandsCHROMIUM(path, static_cast<GLsizei>(ArraySize(kCommands)), kCommands,
+            static_cast<GLsizei>(ArraySize(kCoords)), GL_FLOAT, kCoords);
+        ASSERT_GL_NO_ERROR();
+
+        GLfloat path_model_translate[16] = {
+            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+        };
+
+        // Draws the shapes. Every even row from the bottom is drawn with
+        // DrawArrays, odd row with path rendering. The shader program is
+        // the same for the both draws.
+        for (int j = 0; j < kTestRows; ++j)
+        {
+            for (int i = 0; i < kTestColumns; ++i)
+            {
+                if (j % 2 == 0)
+                {
+                    glDisable(GL_STENCIL_TEST);
+                    glUniform2f(kModelTranslateLocation, static_cast<GLfloat>(i * kShapeWidth),
+                                static_cast<GLfloat>(j * kShapeHeight));
+                    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+                }
+                else
+                {
+                    glEnable(GL_STENCIL_TEST);
+                    path_model_translate[12] = static_cast<GLfloat>(i * kShapeWidth);
+                    path_model_translate[13] = static_cast<GLfloat>(j * kShapeHeight);
+                    glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM, path_model_translate);
+                    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
+                                                       GL_BOUNDING_BOX_CHROMIUM);
+                }
+            }
+        }
+        ASSERT_GL_NO_ERROR();
+
+        glDisableVertexAttribArray(kPositionLocation);
+        glDeleteBuffers(1, &vbo);
+        glDeletePathsCHROMIUM(path, 1);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    enum
+    {
+        kShapeWidth  = 75,
+        kShapeHeight = 75,
+        kTestRows    = kResolution / kShapeHeight,
+        kTestColumns = kResolution / kShapeWidth,
+    };
+
+    typedef void(GL_APIENTRYP PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC)(GLuint mProgram,
+                                                                    GLint location,
+                                                                    const GLchar *name);
+    PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC mBindUniformLocation = nullptr;
+
+    GLuint mProgram;
+
+    // This uniform be can set by the test. It should be used to set the color for
+    // drawing with DrawArrays.
+    static const GLint kColorMatrixLocation = 4;
+
+    // This fragment input can be set by the test. It should be used to set the
+    // color for drawing with path rendering.
+    static const GLint kColorFragmentInputLocation = 7;
+
+    static const GLint kModelTranslateLocation = 3;
+    static const GLint kPositionLocation       = 0;
+    static const GLint kViewMatrixLocation     = 7;
+};
+
+// Test success and error cases for binding fragment input location.
+TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestBindFragmentInputLocation)
+{
+    if (!isApplicable())
+        return;
+
+    // original NV_path_rendering specification doesn't define whether the
+    // fragment shader input variables should be defined in the vertex shader or
+    // not. In fact it doesn't even require a vertex shader.
+    // However the GLES3.1 spec basically says that fragment inputs are
+    // either built-ins or come from the previous shader stage.
+    // (§ 14.1, Fragment Shader Variables).
+    // Additionally there are many places that are based on the assumption of having
+    // a vertex shader (command buffer, angle) so we're going to stick to the same
+    // semantics and require a vertex shader and to have the vertex shader define the
+    // varying fragment shader input.
+
+    // clang-format off
+    const char* kVertexShaderSource =
+       "varying vec4 color;\n"
+       "void main() {}\n";
+
+    const char* kFragmentShaderSource =
+        "precision mediump float;\n"
+        "varying vec4 color;\n"
+        "void main() {\n"
+        "  gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    // clang-format on
+    compileProgram(kVertexShaderSource, kFragmentShaderSource);
+
+    enum kBindLocations
+    {
+        kColorLocation     = 5,
+        kFragColorLocation = 6
+    };
+
+    // successful bind.
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorLocation, "color");
+    ASSERT_GL_NO_ERROR();
+
+    // any name can be bound and names that do not actually exist in the program after
+    // linking are ignored.
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorLocation, "doesnt_exist");
+    ASSERT_GL_NO_ERROR();
+
+    // illegal program
+    glBindFragmentInputLocationCHROMIUM(mProgram + 1, kColorLocation, "color");
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // illegal bind (built-in)
+    glBindFragmentInputLocationCHROMIUM(mProgram, kFragColorLocation, "gl_FragColor");
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glBindFragmentInputLocationCHROMIUM(mProgram, kFragColorLocation, nullptr);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glBindFragmentInputLocationCHROMIUM(mProgram, 0xffffff, "color");
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    ASSERT_TRUE(linkProgram() == true);
+
+    const GLfloat kCoefficients16[] = {1.0f, 2.0f,  3.0f,  4.0f,  5.0f,  6.0f,  7.0f,  8.0f,
+                                       9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f};
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorLocation, GL_EYE_LINEAR_CHROMIUM, 4,
+                                          kCoefficients16);
+    ASSERT_GL_NO_ERROR();
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, GL_EYE_LINEAR_CHROMIUM, 4, kCoefficients16);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test fragment input interpolation in CHROMIUM_EYE coordinates.
+TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestProgramPathFragmentInputGenCHROMIUM_EYE)
+{
+    if (!isApplicable())
+        return;
+
+    // clang-format off
+    const char *kVertexShaderSource =
+        "uniform mat4 view_matrix;\n"
+        "uniform mat4 color_matrix;\n"
+        "uniform vec2 model_translate;\n"
+        "attribute vec2 position;\n"
+        "varying vec3 color;\n"
+        "void main() {\n"
+        "  vec4 p = vec4(model_translate + position, 1.0, 1.0);\n"
+        "  color = (color_matrix * p).rgb;\n"
+        "  gl_Position = view_matrix * p;\n"
+        "}\n";
+
+    const char *kFragmentShaderSource =
+        "precision mediump float;\n"
+        "varying vec3 color;\n"
+        "void main() {\n"
+        "  gl_FragColor = vec4(color, 1.0);\n"
+        "}\n";
+    // clang-format on
+
+    compileProgram(kVertexShaderSource, kFragmentShaderSource);
+    bindProgram();
+    ASSERT_TRUE(linkProgram() == true);
+
+    glUniformMatrix4fv(kViewMatrixLocation, 1, GL_FALSE, kProjectionMatrix);
+
+    static const GLfloat kColorMatrix[16] = {
+        1.0f / kResolution, 0.0f, 0.0f, 0.0f,
+        0.0f, 1.0f / kResolution, 0.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 0.0f};
+
+    glUniformMatrix4fv(kColorMatrixLocation, 1, GL_FALSE, kColorMatrix);
+
+    // This is the functionality we are testing: ProgramPathFragmentInputGen
+    // does the same work as the color transform in vertex shader.
+    static const GLfloat kColorCoefficients[12] = {
+        1.0f / kResolution, 0.0f, 0.0f,
+        0.0f, 0.0f, 1.0f / kResolution,
+        0.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 0.0f};
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorFragmentInputLocation,
+                                          GL_EYE_LINEAR_CHROMIUM, 3, kColorCoefficients);
+    ASSERT_GL_NO_ERROR();
+
+    drawTestPattern();
+
+    const GLfloat kFillCoords[6] = {59.0f, 50.0f, 50.0f, 28.0f, 66.0f, 63.0f};
+
+    for (int j = 0; j < kTestRows; ++j)
+    {
+        for (int i = 0; i < kTestColumns; ++i)
+        {
+            for (size_t k = 0; k < ArraySize(kFillCoords); k += 2)
+            {
+                const float fx = kFillCoords[k];
+                const float fy = kFillCoords[k + 1];
+                const float px = static_cast<float>(i * kShapeWidth);
+                const float py = static_cast<float>(j * kShapeHeight);
+
+                angle::GLColor color;
+                color.R = static_cast<GLubyte>(std::roundf((px + fx) / kResolution * 255.0f));
+                color.G = static_cast<GLubyte>(std::roundf((py + fy) / kResolution * 255.0f));
+                color.B = 0;
+                color.A = 255;
+                CheckPixels(static_cast<GLint>(px + fx), static_cast<GLint>(py + fy), 1, 1, 2,
+                            color);
+            }
+        }
+    }
+}
+
+// Test fragment input interpolation in CHROMIUM_OBJECT coordinates.
+TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestProgramPathFragmentInputGenCHROMIUM_OBJECT)
+{
+    if (!isApplicable())
+        return;
+
+    // clang-format off
+    const char *kVertexShaderSource =
+        "uniform mat4 view_matrix;\n"
+        "uniform mat4 color_matrix;\n"
+        "uniform vec2 model_translate;\n"
+        "attribute vec2 position;\n"
+        "varying vec3 color;\n"
+        "void main() {\n"
+        "  color = (color_matrix * vec4(position, 1.0, 1.0)).rgb;\n"
+        "  vec4 p = vec4(model_translate + position, 1.0, 1.0);\n"
+        "  gl_Position = view_matrix * p;\n"
+        "}";
+
+    const char *kFragmentShaderSource =
+        "precision mediump float;\n"
+        "varying vec3 color;\n"
+        "void main() {\n"
+        "  gl_FragColor = vec4(color.rgb, 1.0);\n"
+        "}";
+    // clang-format on
+
+    compileProgram(kVertexShaderSource, kFragmentShaderSource);
+    bindProgram();
+    ASSERT_TRUE(linkProgram() == true);
+
+    glUniformMatrix4fv(kViewMatrixLocation, 1, GL_FALSE, kProjectionMatrix);
+
+    static const GLfloat kColorMatrix[16] = {
+        1.0f / kShapeWidth, 0.0f, 0.0f, 0.0f,
+        0.0f, 1.0f / kShapeHeight, 0.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 0.0f };
+    glUniformMatrix4fv(kColorMatrixLocation, 1, GL_FALSE, kColorMatrix);
+
+    // This is the functionality we are testing: ProgramPathFragmentInputGen
+    // does the same work as the color transform in vertex shader.
+    static const GLfloat kColorCoefficients[9] = {
+        1.0f / kShapeWidth, 0.0f, 0.0f, 0.0f, 1.0f / kShapeHeight, 0.0f, 0.0f, 0.0f, 0.0f};
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorFragmentInputLocation,
+                                          GL_OBJECT_LINEAR_CHROMIUM, 3, kColorCoefficients);
+
+    ASSERT_GL_NO_ERROR();
+
+    drawTestPattern();
+
+    const GLfloat kFillCoords[6] = {59.0f, 50.0f, 50.0f, 28.0f, 66.0f, 63.0f};
+
+    for (int j = 0; j < kTestRows; ++j)
+    {
+        for (int i = 0; i < kTestColumns; ++i)
+        {
+            for (size_t k = 0; k < ArraySize(kFillCoords); k += 2)
+            {
+                const float fx = kFillCoords[k];
+                const float fy = kFillCoords[k + 1];
+                const float px = static_cast<float>(i * kShapeWidth);
+                const float py = static_cast<float>(j * kShapeHeight);
+
+                angle::GLColor color;
+                color.R = static_cast<GLubyte>(std::roundf(fx / kShapeWidth * 255.0f));
+                color.G = static_cast<GLubyte>(std::roundf(fy / kShapeHeight * 255.0f));
+                color.B = 0;
+                color.A = 255;
+                CheckPixels(static_cast<GLint>(px + fx), static_cast<GLint>(py + fy), 1, 1, 2,
+                            color);
+            }
+        }
+    }
+}
+
+// Test success and error cases for setting interpolation parameters.
+TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestProgramPathFragmentInputGenArgs)
+{
+    if (!isApplicable())
+        return;
+
+    // clang-format off
+    const char *kVertexShaderSource =
+        "varying vec2 vec2_var;\n"
+        "varying vec3 vec3_var;\n"
+        "varying vec4 vec4_var;\n"
+        "varying float float_var;\n"
+        "varying mat2 mat2_var;\n"
+        "varying mat3 mat3_var;\n"
+        "varying mat4 mat4_var;\n"
+        "attribute float avoid_opt;\n"
+        "void main() {\n"
+        "  vec2_var = vec2(1.0, 2.0 + avoid_opt);\n"
+        "  vec3_var = vec3(1.0, 2.0, 3.0 + avoid_opt);\n"
+        "  vec4_var = vec4(1.0, 2.0, 3.0, 4.0 + avoid_opt);\n"
+        "  float_var = 5.0 + avoid_opt;\n"
+        "  mat2_var = mat2(2.0 + avoid_opt);\n"
+        "  mat3_var = mat3(3.0 + avoid_opt);\n"
+        "  mat4_var = mat4(4.0 + avoid_opt);\n"
+        "  gl_Position = vec4(1.0);\n"
+        "}";
+
+    const char* kFragmentShaderSource =
+        "precision mediump float;\n"
+        "varying vec2 vec2_var;\n"
+        "varying vec3 vec3_var;\n"
+        "varying vec4 vec4_var;\n"
+        "varying float float_var;\n"
+        "varying mat2 mat2_var;\n"
+        "varying mat3 mat3_var;\n"
+        "varying mat4 mat4_var;\n"
+        "void main() {\n"
+        "  gl_FragColor = vec4(vec2_var, 0, 0) + vec4(vec3_var, 0) + vec4_var + "
+        "               vec4(float_var) + "
+        "               vec4(mat2_var[0][0], mat3_var[1][1], mat4_var[2][2], 1);\n"
+        "}";
+    // clang-format on
+
+    enum
+    {
+        kVec2Location = 0,
+        kVec3Location,
+        kVec4Location,
+        kFloatLocation,
+        kMat2Location,
+        kMat3Location,
+        kMat4Location,
+    };
+    struct
+    {
+        GLint location;
+        const char *name;
+        GLint components;
+    } variables[] = {
+        {kVec2Location, "vec2_var", 2},
+        {kVec3Location, "vec3_var", 3},
+        {kVec4Location, "vec4_var", 4},
+        {kFloatLocation, "float_var", 1},
+        // If a varying is not single-precision floating-point scalar or
+        // vector, it always causes an invalid operation.
+        {kMat2Location, "mat2_var", -1},
+        {kMat3Location, "mat3_var", -1},
+        {kMat4Location, "mat4_var", -1},
+    };
+
+    compileProgram(kVertexShaderSource, kFragmentShaderSource);
+
+    for (size_t i = 0; i < ArraySize(variables); ++i)
+    {
+        glBindFragmentInputLocationCHROMIUM(mProgram, variables[i].location, variables[i].name);
+    }
+
+    // test that using invalid (not linked) program is an invalid operation.
+    // See similar calls at the end of the test for discussion about the arguments.
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, GL_NONE, 0, nullptr);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    ASSERT_TRUE(linkProgram() == true);
+
+    const GLfloat kCoefficients16[] = {1.0f, 2.0f,  3.0f,  4.0f,  5.0f,  6.0f,  7.0f,  8.0f,
+                                       9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f};
+    const GLenum kGenModes[] = {GL_NONE, GL_EYE_LINEAR_CHROMIUM, GL_OBJECT_LINEAR_CHROMIUM,
+                                GL_CONSTANT_CHROMIUM};
+
+    for (size_t variable = 0; variable < ArraySize(variables); ++variable)
+    {
+        for (GLint components = 0; components <= 4; ++components)
+        {
+            for (size_t genmode = 0; genmode < ArraySize(kGenModes); ++genmode)
+            {
+                glProgramPathFragmentInputGenCHROMIUM(mProgram, variables[variable].location,
+                                                      kGenModes[genmode], components,
+                                                      kCoefficients16);
+
+                if (components == 0 && kGenModes[genmode] == GL_NONE)
+                {
+                    if (variables[variable].components == -1)
+                    {
+                        // Clearing a fragment input that is not single-precision floating
+                        // point scalar or vector is an invalid operation.
+                        ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+                    }
+                    else
+                    {
+                        // Clearing a valid fragment input is ok.
+                        ASSERT_GL_NO_ERROR();
+                    }
+                }
+                else if (components == 0 || kGenModes[genmode] == GL_NONE)
+                {
+                    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+                }
+                else
+                {
+                    if (components == variables[variable].components)
+                    {
+                        // Setting a generator for a single-precision floating point
+                        // scalar or vector fragment input is ok.
+                        ASSERT_GL_NO_ERROR();
+                    }
+                    else
+                    {
+                        // Setting a generator when components do not match is an invalid operation.
+                        ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+                    }
+                }
+            }
+        }
+    }
+
+    enum
+    {
+        kValidGenMode      = GL_CONSTANT_CHROMIUM,
+        kValidComponents   = 3,
+        kInvalidGenMode    = 0xAB,
+        kInvalidComponents = 5,
+    };
+
+    // The location == -1 would mean fragment input was optimized away. At the
+    // time of writing, -1 can not happen because the only way to obtain the
+    // location numbers is through bind. Test just to be consistent.
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kValidGenMode, kValidComponents,
+                                          kCoefficients16);
+    ASSERT_GL_NO_ERROR();
+
+    // Test that even though the spec says location == -1 causes the operation to
+    // be skipped, the verification of other parameters is still done. This is a
+    // GL policy.
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kInvalidGenMode, kValidComponents,
+                                          kCoefficients16);
+    ASSERT_GL_ERROR(GL_INVALID_ENUM);
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kInvalidGenMode, kInvalidComponents,
+                                          kCoefficients16);
+    ASSERT_GL_ERROR(GL_INVALID_ENUM);
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kValidGenMode, kInvalidComponents,
+                                          kCoefficients16);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    glDeleteProgram(mProgram);
+
+    // Test that using invalid (deleted) program is an invalid operation.
+    EXPECT_FALSE(glIsProgram(mProgram) == GL_FALSE);
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kValidGenMode, kValidComponents,
+                                          kCoefficients16);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kInvalidGenMode, kValidComponents,
+                                          kCoefficients16);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kInvalidGenMode, kInvalidComponents,
+                                          kCoefficients16);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kValidGenMode, kInvalidComponents,
+                                          kCoefficients16);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    mProgram = 0u;
+}
+
+// Test that having input statically aliased fragment inputs the linking fails
+// and then succeeds when the conflict is resolved.
+TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestConflictingBind)
+{
+    if (!isApplicable())
+        return;
+
+    // clang-format off
+    const char* kVertexShaderSource =
+        "attribute vec4 position;\n"
+        "varying vec4 colorA;\n"
+        "varying vec4 colorB;\n"
+        "void main() {\n"
+        "  gl_Position = position;\n"
+        "  colorA = position + vec4(1);\n"
+        "  colorB = position + vec4(2);\n"
+        "}";
+
+    const char* kFragmentShaderSource =
+        "precision mediump float;\n"
+        "varying vec4 colorA;\n"
+        "varying vec4 colorB;\n"
+        "void main() {\n"
+        "  gl_FragColor = colorA + colorB;\n"
+        "}";
+    // clang-format on
+
+    const GLint kColorALocation = 3;
+    const GLint kColorBLocation = 4;
+
+    compileProgram(kVertexShaderSource, kFragmentShaderSource);
+
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorALocation, "colorA");
+    // Bind colorB to location a, causing conflicts. Linking should fail.
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorALocation, "colorB");
+
+    // Should fail now.
+    ASSERT_TRUE(linkProgram() == false);
+    ASSERT_GL_NO_ERROR();
+
+    // Resolve the bind conflict.
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorBLocation, "colorB");
+
+    ASSERT_TRUE(linkProgram() == true);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test binding with array variables, using zero indices. Tests that
+// binding colorA[0] with explicit "colorA[0]" as well as "colorA" produces
+// a correct location that can be used with PathProgramFragmentInputGen.
+// For path rendering, colorA[0] is bound to a location. The input generator for
+// the location is set to produce vec4(0, 0.1, 0, 0.1).
+// The default varying, color, is bound to a location and its generator
+// will produce vec4(10.0).  The shader program produces green pixels.
+// For vertex-based rendering, the vertex shader produces the same effect as
+// the input generator for path rendering.
+TEST_P(CHROMIUMPathRenderingWithTexturingTest, BindFragmentInputArray)
+{
+    if (!isApplicable())
+        return;
+
+    //clang-format off
+    const char* kVertexShaderSource =
+        "uniform mat4 view_matrix;\n"
+        "uniform mat4 color_matrix;\n"
+        "uniform vec2 model_translate;\n"
+        "attribute vec2 position;\n"
+        "varying vec4 color;\n"
+        "varying vec4 colorA[4];\n"
+        "void main() {\n"
+        "  vec4 p = vec4(model_translate + position, 1, 1);\n"
+        "  gl_Position = view_matrix * p;\n"
+        "  colorA[0] = vec4(0.0, 0.1, 0, 0.1);\n"
+        "  colorA[1] = vec4(0.2);\n"
+        "  colorA[2] = vec4(0.3);\n"
+        "  colorA[3] = vec4(0.4);\n"
+        "  color = vec4(10.0);\n"
+        "}";
+
+    const char* kFragmentShaderSource =
+        "precision mediump float;\n"
+        "varying vec4 color;\n"
+        "varying vec4 colorA[4];\n"
+        "void main() {\n"
+        "  gl_FragColor = colorA[0] * color;\n"
+        "}";
+    // clang-format on
+
+    const GLint kColorA0Location = 4;
+    const GLint kUnusedLocation  = 5;
+    const GLfloat kColorA0[]     = {0.0f, 0.1f, 0.0f, 0.1f};
+    const GLfloat kColor[]       = {10.0f, 10.0f, 10.0f, 10.0f};
+    const GLfloat kFillCoords[6] = {59.0f, 50.0f, 50.0f, 28.0f, 66.0f, 63.0f};
+
+    for (int pass = 0; pass < 2; ++pass)
+    {
+        compileProgram(kVertexShaderSource, kFragmentShaderSource);
+        if (pass == 0)
+        {
+            glBindFragmentInputLocationCHROMIUM(mProgram, kUnusedLocation, "colorA[0]");
+            glBindFragmentInputLocationCHROMIUM(mProgram, kColorA0Location, "colorA");
+        }
+        else
+        {
+            glBindFragmentInputLocationCHROMIUM(mProgram, kUnusedLocation, "colorA");
+            glBindFragmentInputLocationCHROMIUM(mProgram, kColorA0Location, "colorA[0]");
+        }
+
+        bindProgram();
+
+        ASSERT_TRUE(linkProgram() == true);
+
+        glUniformMatrix4fv(kViewMatrixLocation, 1, GL_FALSE, kProjectionMatrix);
+        glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA0Location, GL_CONSTANT_CHROMIUM, 4, kColorA0);
+        glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorFragmentInputLocation, GL_CONSTANT_CHROMIUM, 4, kColor);
+        ASSERT_GL_NO_ERROR();
+
+        drawTestPattern();
+
+        for (int j = 0; j < kTestRows; ++j)
+        {
+            for (int i = 0; i < kTestColumns; ++i)
+            {
+                for (size_t k = 0; k < ArraySize(kFillCoords); k += 2)
+                {
+                    const float fx = kFillCoords[k];
+                    const float fy = kFillCoords[k + 1];
+                    const float px = static_cast<float>(i * kShapeWidth);
+                    const float py = static_cast<float>(j * kShapeHeight);
+
+                    angle::GLColor color;
+                    color.R = 0;
+                    color.G = 255;
+                    color.B = 0;
+                    color.A = 255;
+                    CheckPixels(static_cast<GLint>(px + fx), static_cast<GLint>(py + fy), 1, 1, 2,
+                                color);
+                }
+            }
+        }
+    }
+}
+
+// Test binding array variables. This is like BindFragmentInputArray.
+// Currently disabled since it seems there's a driver bug with the
+// older drivers. This should work with driver >= 364.12
+TEST_P(CHROMIUMPathRenderingWithTexturingTest,
+    DISABLED_BindFragmentInputArrayNonZeroIndex)
+{
+    if (!isApplicable())
+        return;
+
+    // clang-format off
+    const char* kVertexShaderSource =
+        "uniform mat4 view_matrix;\n"
+        "uniform mat4 color_matrix;\n"
+        "uniform vec2 model_translate;\n"
+        "attribute vec2 position;\n"
+        "varying vec4 color;\n"
+        "varying vec4 colorA[4];\n"
+        "void main() {\n"
+        "  vec4 p = vec4(model_translate + position, 1, 1);\n"
+        "  gl_Position = view_matrix * p;\n"
+        "  colorA[0] = vec4(0, 0.1, 0, 0.1);\n"
+        "  colorA[1] = vec4(0, 1, 0, 1);\n"
+        "  colorA[2] = vec4(0, 0.8, 0, 0.8);\n"
+        "  colorA[3] = vec4(0, 0.5, 0, 0.5);\n"
+        "  color = vec4(0.2);\n"
+        "}\n";
+
+    const char* kFragmentShaderSource =
+        "precision mediump float;\n"
+        "varying vec4 colorA[4];\n"
+        "varying vec4 color;\n"
+        "void main() {\n"
+        "  gl_FragColor = (colorA[0] * colorA[1]) +\n"
+        "      colorA[2] + (colorA[3] * color);\n"
+        "}\n";
+    // clang-format on
+
+    const GLint kColorA0Location = 4;
+    const GLint kColorA1Location = 1;
+    const GLint kColorA2Location = 2;
+    const GLint kColorA3Location = 3;
+    const GLint kUnusedLocation = 5;
+    const GLfloat kColorA0[] = {0.0f, 0.1f, 0.0f, 0.1f};
+    const GLfloat kColorA1[] = {0.0f, 1.0f, 0.0f, 1.0f};
+    const GLfloat kColorA2[] = {0.0f, 0.8f, 0.0f, 0.8f};
+    const GLfloat kColorA3[] = {0.0f, 0.5f, 0.0f, 0.5f};
+    const GLfloat kColor[] = {0.2f, 0.2f, 0.2f, 0.2f};
+    const GLfloat kFillCoords[6] = {59.0f, 50.0f, 50.0f, 28.0f, 66.0f, 63.0f};
+
+    compileProgram(kVertexShaderSource, kFragmentShaderSource);
+
+    glBindFragmentInputLocationCHROMIUM(mProgram, kUnusedLocation, "colorA[0]");
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorA1Location, "colorA[1]");
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorA2Location, "colorA[2]");
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorA3Location, "colorA[3]");
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorA0Location, "colorA");
+    ASSERT_GL_NO_ERROR();
+
+    bindProgram();
+    ASSERT_TRUE(linkProgram() == true);
+
+    glUniformMatrix4fv(kViewMatrixLocation, 1, GL_FALSE, kProjectionMatrix);
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA0Location, GL_CONSTANT_CHROMIUM, 4, kColorA0);
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA1Location, GL_CONSTANT_CHROMIUM, 4, kColorA1);
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA2Location, GL_CONSTANT_CHROMIUM, 4, kColorA2);
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA3Location, GL_CONSTANT_CHROMIUM, 4, kColorA3);
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorFragmentInputLocation,
+        GL_CONSTANT_CHROMIUM, 4, kColor);
+    ASSERT_GL_NO_ERROR();
+
+    drawTestPattern();
+
+    for (int j = 0; j < kTestRows; ++j)
+    {
+        for (int i = 0; i < kTestColumns; ++i)
+        {
+            for (size_t k = 0; k < ArraySize(kFillCoords); k += 2)
+            {
+                const float fx = kFillCoords[k];
+                const float fy = kFillCoords[k + 1];
+                const float px = static_cast<float>(i * kShapeWidth);
+                const float py = static_cast<float>(j * kShapeHeight);
+
+                angle::GLColor color;
+                color.R = 0;
+                color.G = 255;
+                color.B = 0;
+                color.A = 255;
+                CheckPixels(static_cast<GLint>(px + fx), static_cast<GLint>(py + fy), 1, 1, 2,
+                            color);
+            }
+        }
+    }
+}
+
+TEST_P(CHROMIUMPathRenderingWithTexturingTest, UnusedFragmentInputUpdate)
+{
+    if (!isApplicable())
+        return;
+
+  // clang-format off
+    const char* kVertexShaderString =
+        "attribute vec4 a_position;\n"
+        "void main() {\n"
+        "  gl_Position = a_position;\n"
+        "}";
+
+    const char* kFragmentShaderString =
+        "precision mediump float;\n"
+        "uniform vec4 u_colorA;\n"
+        "uniform float u_colorU;\n"
+        "uniform vec4 u_colorC;\n"
+        "void main() {\n"
+        "  gl_FragColor = u_colorA + u_colorC;\n"
+        "}";
+    // clang-format on
+
+    const GLint kColorULocation = 1;
+    const GLint kNonexistingLocation = 5;
+    const GLint kUnboundLocation = 6;
+
+    compileProgram(kVertexShaderString, kFragmentShaderString);
+
+    glBindFragmentInputLocationCHROMIUM(mProgram, kColorULocation, "u_colorU");
+
+    // The non-existing input should behave like existing but optimized away input.
+    glBindFragmentInputLocationCHROMIUM(mProgram, kNonexistingLocation, "nonexisting");
+
+    // Let A and C be assigned automatic locations.
+    ASSERT_TRUE(linkProgram() == true);
+
+    const GLfloat kColor[16] = {};
+
+    // No errors on bound locations, since caller does not know
+    // if the driver optimizes them away or not.
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorULocation, GL_CONSTANT_CHROMIUM, 1, kColor);
+    ASSERT_GL_NO_ERROR();
+
+    // No errors on bound locations of names that do not exist
+    // in the shader. Otherwise it would be inconsistent wrt the
+    // optimization case.
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kNonexistingLocation, GL_CONSTANT_CHROMIUM, 1, kColor);
+    ASSERT_GL_NO_ERROR();
+
+    // The above are equal to updating -1.
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, GL_CONSTANT_CHROMIUM, 1, kColor);
+    ASSERT_GL_NO_ERROR();
+
+    // No errors when updating with other type either.
+    // The type can not be known with the non-existing case.
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorULocation, GL_CONSTANT_CHROMIUM, 4, kColor);
+    ASSERT_GL_NO_ERROR();
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kNonexistingLocation, GL_CONSTANT_CHROMIUM, 4, kColor);
+    ASSERT_GL_NO_ERROR();
+
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, GL_CONSTANT_CHROMIUM, 4, kColor);
+    ASSERT_GL_NO_ERROR();
+
+    // Updating an unbound, non-existing location still causes an error.
+    glProgramPathFragmentInputGenCHROMIUM(mProgram, kUnboundLocation, GL_CONSTANT_CHROMIUM, 4, kColor);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+
+}  // namespace
+
+ANGLE_INSTANTIATE_TEST(CHROMIUMPathRenderingTest,
+                       ES2_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGL(),
+                       ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(CHROMIUMPathRenderingDrawTest,
+                       ES2_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGL(),
+                       ES3_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(CHROMIUMPathRenderingWithTexturingTest,
+                       ES2_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGL(),
+                       ES3_OPENGLES());
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/gl_tests/PbufferTest.cpp b/src/third_party/angle/src/tests/gl_tests/PbufferTest.cpp
new file mode 100644
index 0000000..fb381e1
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/PbufferTest.cpp
@@ -0,0 +1,343 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+class PbufferTest : public ANGLETest
+{
+  protected:
+    PbufferTest()
+    {
+        setWindowWidth(512);
+        setWindowHeight(512);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string vsSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = position;
+                texcoord = (position.xy * 0.5) + 0.5;
+                texcoord.y = 1.0 - texcoord.y;
+            }
+        );
+
+        const std::string textureFSSource = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        mTextureProgram = CompileProgram(vsSource, textureFSSource);
+        if (mTextureProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
+
+        EGLWindow *window = getEGLWindow();
+
+        EGLint surfaceType = 0;
+        eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_SURFACE_TYPE, &surfaceType);
+        mSupportsPbuffers = (surfaceType & EGL_PBUFFER_BIT) != 0;
+
+        EGLint bindToTextureRGBA = 0;
+        eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
+        mSupportsBindTexImage = (bindToTextureRGBA == EGL_TRUE);
+
+        const EGLint pBufferAttributes[] =
+        {
+            EGL_WIDTH, static_cast<EGLint>(mPbufferSize),
+            EGL_HEIGHT, static_cast<EGLint>(mPbufferSize),
+            EGL_TEXTURE_FORMAT, mSupportsBindTexImage ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,
+            EGL_TEXTURE_TARGET, mSupportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,
+            EGL_NONE, EGL_NONE,
+        };
+
+        mPbuffer = eglCreatePbufferSurface(window->getDisplay(), window->getConfig(), pBufferAttributes);
+        if (mSupportsPbuffers)
+        {
+            ASSERT_NE(mPbuffer, EGL_NO_SURFACE);
+            ASSERT_EGL_SUCCESS();
+        }
+        else
+        {
+            ASSERT_EQ(mPbuffer, EGL_NO_SURFACE);
+            ASSERT_EGL_ERROR(EGL_BAD_MATCH);
+        }
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mTextureProgram);
+
+        EGLWindow *window = getEGLWindow();
+        eglDestroySurface(window->getDisplay(), mPbuffer);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mTextureProgram;
+    GLint mTextureUniformLocation;
+
+    const size_t mPbufferSize = 32;
+    EGLSurface mPbuffer;
+    bool mSupportsPbuffers;
+    bool mSupportsBindTexImage;
+};
+
+// Test clearing a Pbuffer and checking the color is correct
+TEST_P(PbufferTest, Clearing)
+{
+    if (!mSupportsPbuffers)
+    {
+        std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
+        return;
+    }
+
+    EGLWindow *window = getEGLWindow();
+
+    // Clear the window surface to blue and verify
+    eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
+
+    // Apply the Pbuffer and clear it to purple and verify
+    eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
+                    0, 255, 255);
+
+    // Rebind the window surface and verify that it is still blue
+    eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
+    ASSERT_EGL_SUCCESS();
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
+}
+
+// Bind the Pbuffer to a texture and verify it renders correctly
+TEST_P(PbufferTest, BindTexImage)
+{
+    if (!mSupportsPbuffers)
+    {
+        std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
+        return;
+    }
+
+    if (!mSupportsBindTexImage)
+    {
+        std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
+        return;
+    }
+
+    EGLWindow *window = getEGLWindow();
+
+    // Apply the Pbuffer and clear it to purple
+    eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
+                    0, 255, 255);
+
+    // Apply the window surface
+    eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
+
+    // Create a texture and bind the Pbuffer to it
+    GLuint texture = 0;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    EXPECT_GL_NO_ERROR();
+
+    eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
+    glViewport(0, 0, getWindowWidth(), getWindowHeight());
+    ASSERT_EGL_SUCCESS();
+
+    // Draw a quad and verify that it is purple
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    drawQuad(mTextureProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+
+    // Unbind the texture
+    eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
+    ASSERT_EGL_SUCCESS();
+
+    // Verify that purple was drawn
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
+
+    glDeleteTextures(1, &texture);
+}
+
+// Verify that when eglBind/ReleaseTexImage are called, the texture images are freed and their
+// size information is correctly updated.
+TEST_P(PbufferTest, TextureSizeReset)
+{
+    if (!mSupportsPbuffers)
+    {
+        std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
+        return;
+    }
+
+    if (!mSupportsBindTexImage)
+    {
+        std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
+        return;
+    }
+
+    GLuint texture = 0;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    // Fill the texture with white pixels
+    std::vector<GLubyte> whitePixels(mPbufferSize * mPbufferSize * 4, 255);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(mPbufferSize),
+                 static_cast<GLsizei>(mPbufferSize), 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitePixels[0]);
+    EXPECT_GL_NO_ERROR();
+
+    // Draw the white texture and verify that the pixels are correct
+    drawQuad(mTextureProgram, "position", 0.5f);
+    EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
+
+    // Bind the EGL surface and draw with it, results are undefined since nothing has
+    // been written to it
+    EGLWindow *window = getEGLWindow();
+    eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
+    drawQuad(mTextureProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+
+    // Clear the back buffer to a unique color (green)
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    // Unbind the EGL surface and try to draw with the texture again, the texture's size should
+    // now be zero and incomplete so the back buffer should be black
+    eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
+    drawQuad(mTextureProgram, "position", 0.5f);
+    EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 255);
+}
+
+// Bind a Pbuffer, redefine the texture, and verify it renders correctly
+TEST_P(PbufferTest, BindTexImageAndRedefineTexture)
+{
+    if (!mSupportsPbuffers)
+    {
+        std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
+        return;
+    }
+
+    if (!mSupportsBindTexImage)
+    {
+        std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
+        return;
+    }
+
+    EGLWindow *window = getEGLWindow();
+
+    // Apply the Pbuffer and clear it to purple
+    eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
+    ASSERT_EGL_SUCCESS();
+
+    glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
+    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
+                    0, 255, 255);
+
+    // Apply the window surface
+    eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
+
+    // Create a texture and bind the Pbuffer to it
+    GLuint texture = 0;
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    EXPECT_GL_NO_ERROR();
+
+    eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
+    glViewport(0, 0, getWindowWidth(), getWindowHeight());
+    ASSERT_EGL_SUCCESS();
+
+    // Redefine the texture
+    unsigned int pixelValue = 0xFFFF00FF;
+    std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixelData[0]);
+
+    // Draw a quad and verify that it is magenta
+    glUseProgram(mTextureProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    drawQuad(mTextureProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+
+    // Verify that magenta was drawn
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
+
+    glDeleteTextures(1, &texture);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(PbufferTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_OPENGL(),
+                       ES2_D3D11_WARP(),
+                       ES2_D3D11_REFERENCE(),
+                       ES2_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/PointSpritesTest.cpp b/src/third_party/angle/src/tests/gl_tests/PointSpritesTest.cpp
new file mode 100644
index 0000000..f85319c
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/PointSpritesTest.cpp
@@ -0,0 +1,520 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Some of the pointsprite tests below were ported from Khronos WebGL
+// conformance test suite.
+
+#include "test_utils/ANGLETest.h"
+
+#include <cmath>
+
+using namespace angle;
+
+class PointSpritesTest : public ANGLETest
+{
+  protected:
+    const int windowWidth  = 256;
+    const int windowHeight = 256;
+    PointSpritesTest()
+    {
+        setWindowWidth(windowWidth);
+        setWindowHeight(windowHeight);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual void SetUp() { ANGLETest::SetUp(); }
+
+    float s2p(float s) { return (s + 1.0f) * 0.5f * (GLfloat)windowWidth; }
+};
+
+// Checks gl_PointCoord and gl_PointSize
+// https://www.khronos.org/registry/webgl/sdk/tests/conformance/glsl/variables/gl-pointcoord.html
+TEST_P(PointSpritesTest, PointCoordAndPointSizeCompliance)
+{
+    // TODO(jmadill): figure out why this fails
+    if (IsIntel() && GetParam() == ES2_D3D9())
+    {
+        std::cout << "Test skipped on Intel due to failures." << std::endl;
+        return;
+    }
+
+    // TODO(jmadill): Investigate potential AMD driver bug.
+    // http://anglebug.com/1643
+    if (IsAMD() && IsDesktopOpenGL() && IsWindows())
+    {
+        std::cout << "Test skipped on desktop GL AMD Windows." << std::endl;
+        return;
+    }
+
+    const std::string fs = SHADER_SOURCE(precision mediump float; void main() {
+        gl_FragColor = vec4(gl_PointCoord.x, gl_PointCoord.y, 0, 1);
+    });
+
+    const std::string vs =
+        SHADER_SOURCE(attribute vec4 vPosition; uniform float uPointSize; void main() {
+            gl_PointSize = uPointSize;
+            gl_Position  = vPosition;
+        });
+
+    GLuint program = CompileProgram(vs, fs);
+    ASSERT_NE(program, 0u);
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(program);
+
+    GLfloat pointSizeRange[2] = {};
+    glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
+
+    GLfloat maxPointSize = pointSizeRange[1];
+
+    ASSERT_TRUE(maxPointSize >= 1);
+    maxPointSize = floorf(maxPointSize);
+    ASSERT_TRUE((int)maxPointSize % 1 == 0);
+
+    maxPointSize       = std::min(maxPointSize, 64.0f);
+    GLfloat pointWidth = maxPointSize / windowWidth;
+    GLint step         = static_cast<GLint>(floorf(maxPointSize / 4));
+    GLint pointStep    = std::max<GLint>(1, step);
+
+    GLint pointSizeLoc = glGetUniformLocation(program, "uPointSize");
+    ASSERT_GL_NO_ERROR();
+
+    glUniform1f(pointSizeLoc, maxPointSize);
+    ASSERT_GL_NO_ERROR();
+
+    GLfloat pixelOffset = ((int)maxPointSize % 2) ? (1.0f / (GLfloat)windowWidth) : 0;
+    GLuint vertexObject = 0;
+    glGenBuffers(1, &vertexObject);
+    ASSERT_NE(vertexObject, 0U);
+    ASSERT_GL_NO_ERROR();
+
+    glBindBuffer(GL_ARRAY_BUFFER, vertexObject);
+    ASSERT_GL_NO_ERROR();
+
+    GLfloat thePoints[] = {-0.5f + pixelOffset, -0.5f + pixelOffset, 0.5f + pixelOffset,
+                           -0.5f + pixelOffset, -0.5f + pixelOffset, 0.5f + pixelOffset,
+                           0.5f + pixelOffset,  0.5f + pixelOffset};
+
+    glBufferData(GL_ARRAY_BUFFER, sizeof(thePoints), thePoints, GL_STATIC_DRAW);
+    ASSERT_GL_NO_ERROR();
+
+    glEnableVertexAttribArray(0);
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    glDrawArrays(GL_POINTS, 0, 4);
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteBuffers(1, &vertexObject);
+
+    std::string debugText;
+    for (float py = 0; py < 2; ++py)
+    {
+        for (float px = 0; px < 2; ++px)
+        {
+            float pointX = -0.5f + px + pixelOffset;
+            float pointY = -0.5f + py + pixelOffset;
+            for (int yy = 0; yy < maxPointSize; yy += pointStep)
+            {
+                for (int xx = 0; xx < maxPointSize; xx += pointStep)
+                {
+                    // formula for s and t from OpenGL ES 2.0 spec section 3.3
+                    float xw         = s2p(pointX);
+                    float yw         = s2p(pointY);
+                    float u          = xx / maxPointSize * 2 - 1;
+                    float v          = yy / maxPointSize * 2 - 1;
+                    int xf           = static_cast<int>(floorf(s2p(pointX + u * pointWidth)));
+                    int yf           = static_cast<int>(floorf(s2p(pointY + v * pointWidth)));
+                    float s          = 0.5f + (xf + 0.5f - xw) / maxPointSize;
+                    float t          = 0.5f + (yf + 0.5f - yw) / maxPointSize;
+                    GLubyte color[4] = {static_cast<GLubyte>(floorf(s * 255)),
+                                        static_cast<GLubyte>(floorf((1 - t) * 255)), 0, 255};
+                    EXPECT_PIXEL_NEAR(xf, yf, color[0], color[1], color[2], color[3], 4);
+                }
+            }
+        }
+    }
+}
+
+// Verify that drawing a point without enabling any attributes succeeds
+// https://www.khronos.org/registry/webgl/sdk/tests/conformance/rendering/point-no-attributes.html
+TEST_P(PointSpritesTest, PointWithoutAttributesCompliance)
+{
+    // TODO(jmadill): Investigate potential AMD driver bug.
+    // http://anglebug.com/1643
+    if (IsAMD() && IsDesktopOpenGL() && IsWindows())
+    {
+        std::cout << "Test skipped on desktop GL AMD Windows." << std::endl;
+        return;
+    }
+
+    // TODO(jmadill): Figure out why this fails on Intel.
+    // http://anglebug.com/1346
+    if (IsIntel() && IsWindows() && (IsD3D11() || IsD3D9()))
+    {
+        std::cout << "Test skipped on Intel Windows D3D." << std::endl;
+        return;
+    }
+
+    // clang-format off
+    const std::string fs = SHADER_SOURCE
+    (
+        precision mediump float;
+        void main()
+        {
+            gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+        }
+    );
+
+    const std::string vs = SHADER_SOURCE
+    (
+        void main()
+        {
+            gl_PointSize = 2.0;
+            gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+        }
+    );
+    // clang-format on
+
+    GLuint program = CompileProgram(vs, fs);
+    ASSERT_NE(program, 0u);
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(program);
+
+    glDrawArrays(GL_POINTS, 0, 1);
+    ASSERT_GL_NO_ERROR();
+
+    // expect the center pixel to be green
+    EXPECT_PIXEL_EQ((windowWidth - 1) / 2, (windowHeight - 1) / 2, 0, 255, 0, 255);
+}
+
+// This is a regression test for a graphics driver bug affecting end caps on roads in MapsGL
+// https://www.khronos.org/registry/webgl/sdk/tests/conformance/rendering/point-with-gl-pointcoord-in-fragment-shader.html
+TEST_P(PointSpritesTest, PointCoordRegressionTest)
+{
+    // TODO(jmadill): Investigate potential AMD driver bug.
+    // http://anglebug.com/1643
+    if (IsAMD() && IsDesktopOpenGL() && IsWindows())
+    {
+        std::cout << "Test skipped on desktop GL AMD Windows." << std::endl;
+        return;
+    }
+
+    const std::string fs =
+        SHADER_SOURCE(precision mediump float; varying vec4 v_color; void main() {
+            // It seems as long as this mathematical expression references
+            // gl_PointCoord, the fragment's color is incorrect.
+            vec2 diff = gl_PointCoord - vec2(.5, .5);
+            if (length(diff) > 0.5)
+                discard;
+
+            // The point should be a solid color.
+            gl_FragColor = v_color;
+        });
+
+    const std::string vs =
+        SHADER_SOURCE(varying vec4 v_color;
+                      // The X and Y coordinates of the center of the point.
+                      attribute vec2 a_vertex; uniform float u_pointSize; void main() {
+                          gl_PointSize = u_pointSize;
+                          gl_Position  = vec4(a_vertex, 0.0, 1.0);
+                          // The color of the point.
+                          v_color = vec4(0.0, 1.0, 0.0, 1.0);
+                      });
+
+    GLuint program = CompileProgram(vs, fs);
+    ASSERT_NE(program, 0u);
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(program);
+
+    GLfloat pointSizeRange[2] = {};
+    glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
+
+    GLfloat maxPointSize = pointSizeRange[1];
+
+    ASSERT_TRUE(maxPointSize > 2);
+
+    glClearColor(0, 0, 0, 1);
+    glDisable(GL_DEPTH_TEST);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    GLint pointSizeLoc = glGetUniformLocation(program, "u_pointSize");
+    ASSERT_GL_NO_ERROR();
+
+    GLfloat pointSize = std::min<GLfloat>(20.0f, maxPointSize);
+    glUniform1f(pointSizeLoc, pointSize);
+    ASSERT_GL_NO_ERROR();
+
+    GLuint vertexObject = 0;
+    glGenBuffers(1, &vertexObject);
+    ASSERT_NE(vertexObject, 0U);
+    ASSERT_GL_NO_ERROR();
+
+    glBindBuffer(GL_ARRAY_BUFFER, vertexObject);
+    ASSERT_GL_NO_ERROR();
+
+    GLfloat thePoints[] = {0.0f, 0.0f};
+
+    glBufferData(GL_ARRAY_BUFFER, sizeof(thePoints), thePoints, GL_STATIC_DRAW);
+    ASSERT_GL_NO_ERROR();
+
+    glEnableVertexAttribArray(0);
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+    glDrawArrays(GL_POINTS, 0, 1);
+    ASSERT_GL_NO_ERROR();
+
+    // expect the center pixel to be green
+    EXPECT_PIXEL_EQ((windowWidth - 1) / 2, (windowHeight - 1) / 2, 0, 255, 0, 255);
+
+    glDeleteBuffers(1, &vertexObject);
+}
+
+// Verify GL_VERTEX_PROGRAM_POINT_SIZE is enabled
+// https://www.khronos.org/registry/webgl/sdk/tests/conformance/rendering/point-size.html
+TEST_P(PointSpritesTest, PointSizeEnabledCompliance)
+{
+    // TODO(jmadill): Investigate potential AMD driver bug.
+    // http://anglebug.com/1643
+    if (IsAMD() && IsDesktopOpenGL() && IsWindows())
+    {
+        std::cout << "Test skipped on desktop GL AMD Windows." << std::endl;
+        return;
+    }
+
+    const std::string fs = SHADER_SOURCE(precision mediump float; varying vec4 color;
+
+                                         void main() { gl_FragColor = color; });
+
+    const std::string vs = SHADER_SOURCE(attribute vec3 pos; attribute vec4 colorIn;
+                                         uniform float pointSize; varying vec4 color;
+
+                                         void main() {
+                                             gl_PointSize = pointSize;
+                                             color        = colorIn;
+                                             gl_Position  = vec4(pos, 1.0);
+                                         });
+
+    // The WebGL test is drawn on a 2x2 canvas. Emulate this by setting a 2x2 viewport.
+    glViewport(0, 0, 2, 2);
+
+    GLuint program = CompileProgram(vs, fs);
+    ASSERT_NE(program, 0u);
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(program);
+
+    glDisable(GL_BLEND);
+
+    // The choice of (0.4, 0.4) ensures that the centers of the surrounding
+    // pixels are not contained within the point when it is of size 1, but
+    // that they definitely are when it is of size 2.
+    GLfloat vertices[] = {0.4f, 0.4f, 0.0f};
+    GLubyte colors[]   = {255, 0, 0, 255};
+
+    GLuint vertexObject = 0;
+    glGenBuffers(1, &vertexObject);
+    ASSERT_NE(vertexObject, 0U);
+    ASSERT_GL_NO_ERROR();
+
+    glBindBuffer(GL_ARRAY_BUFFER, vertexObject);
+    ASSERT_GL_NO_ERROR();
+
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) + sizeof(colors), nullptr, GL_STATIC_DRAW);
+    ASSERT_GL_NO_ERROR();
+
+    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
+    ASSERT_GL_NO_ERROR();
+
+    glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(colors), colors);
+    ASSERT_GL_NO_ERROR();
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(0);
+
+    glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0,
+                          reinterpret_cast<void *>(sizeof(vertices)));
+    glEnableVertexAttribArray(1);
+
+    GLint pointSizeLoc = glGetUniformLocation(program, "pointSize");
+    ASSERT_GL_NO_ERROR();
+
+    glUniform1f(pointSizeLoc, 1.0f);
+    ASSERT_GL_NO_ERROR();
+
+    glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(ArraySize(vertices)) / 3);
+    ASSERT_GL_NO_ERROR();
+
+    // Test the pixels around the target Red pixel to ensure
+    // they are the expected color values
+    for (GLint y = 0; y < 2; ++y)
+    {
+        for (GLint x = 0; x < 2; ++x)
+        {
+            // 1x1 is expected to be a red pixel
+            // All others are black
+            GLubyte expectedColor[4] = {0, 0, 0, 0};
+            if (x == 1 && y == 1)
+            {
+                expectedColor[0] = 255;
+                expectedColor[3] = 255;
+            }
+            EXPECT_PIXEL_EQ(x, y, expectedColor[0], expectedColor[1], expectedColor[2],
+                            expectedColor[3]);
+        }
+    }
+
+    GLfloat pointSizeRange[2] = {};
+    glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
+
+    if (pointSizeRange[1] >= 2.0)
+    {
+        // Draw a point of size 2 and verify it fills the appropriate region.
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        glUniform1f(pointSizeLoc, 2.0f);
+        ASSERT_GL_NO_ERROR();
+
+        glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(ArraySize(vertices)) / 3);
+        ASSERT_GL_NO_ERROR();
+
+        // Test the pixels to ensure the target is ALL Red pixels
+        for (GLint y = 0; y < 2; ++y)
+        {
+            for (GLint x = 0; x < 2; ++x)
+            {
+                EXPECT_PIXEL_EQ(x, y, 255, 0, 0, 255);
+            }
+        }
+    }
+
+    glDeleteBuffers(1, &vertexObject);
+}
+
+// Verify that rendering works correctly when gl_PointSize is declared in a shader but isn't used
+TEST_P(PointSpritesTest, PointSizeDeclaredButUnused)
+{
+    const std::string vs = SHADER_SOURCE(attribute highp vec4 position;
+
+                                         void main(void) {
+                                             gl_PointSize = 1.0;
+                                             gl_Position  = position;
+                                         });
+
+    const std::string fs =
+        SHADER_SOURCE(void main(void) { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); });
+
+    GLuint program = CompileProgram(vs, fs);
+    ASSERT_NE(program, 0u);
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(program);
+    drawQuad(program, "position", 0.5f, 1.0f);
+    ASSERT_GL_NO_ERROR();
+
+    // expect the center pixel to be red
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
+
+    glDeleteProgram(program);
+}
+
+// Test to cover a bug where the D3D11 rasterizer state would not be update when switching between
+// draw types.  This causes the cull face to potentially be incorrect when drawing emulated point
+// spites.
+TEST_P(PointSpritesTest, PointSpriteAlternatingDrawTypes)
+{
+    // clang-format off
+    const std::string pointFS = SHADER_SOURCE
+    (
+        precision mediump float;
+        void main()
+        {
+            gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+        }
+    );
+
+    const std::string pointVS = SHADER_SOURCE
+    (
+        void main()
+        {
+            gl_PointSize = 16.0;
+            gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+        }
+    );
+
+    const std::string quadFS = SHADER_SOURCE
+    (
+        precision mediump float;
+        void main()
+        {
+            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+        }
+    );
+
+    const std::string quadVS = SHADER_SOURCE
+    (
+        precision mediump float;
+        attribute vec4 pos;
+        void main()
+        {
+            gl_Position = pos;
+        }
+    );
+    // clang-format on
+
+    GLuint pointProgram = CompileProgram(pointVS, pointFS);
+    ASSERT_NE(pointProgram, 0u);
+    ASSERT_GL_NO_ERROR();
+
+    GLuint quadProgram = CompileProgram(quadVS, quadFS);
+    ASSERT_NE(pointProgram, 0u);
+    ASSERT_GL_NO_ERROR();
+
+    glEnable(GL_CULL_FACE);
+    glCullFace(GL_FRONT);
+
+    const GLfloat quadVertices[] = {
+        -1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f, -1.0f, -1.0f, 0.5f,
+
+        -1.0f, 1.0f, 0.5f, 1.0f, 1.0f,  0.5f, 1.0f,  -1.0f, 0.5f,
+    };
+
+    glUseProgram(quadProgram);
+    GLint positionLocation = glGetAttribLocation(quadProgram, "pos");
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices);
+    glEnableVertexAttribArray(positionLocation);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+
+    glUseProgram(pointProgram);
+    glDrawArrays(GL_POINTS, 0, 1);
+    ASSERT_GL_NO_ERROR();
+
+    // expect the center pixel to be green
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
+
+    glDeleteProgram(pointProgram);
+    glDeleteProgram(quadProgram);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES
+// major version) these tests should be run against.
+//
+// We test on D3D11 9_3 because the existing D3D11 PointSprite implementation
+// uses Geometry Shaders which are not supported for 9_3.
+// D3D9 and D3D11 are also tested to ensure no regressions.
+ANGLE_INSTANTIATE_TEST(PointSpritesTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/ProgramBinaryTest.cpp b/src/third_party/angle/src/tests/gl_tests/ProgramBinaryTest.cpp
new file mode 100644
index 0000000..8c69f2c
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ProgramBinaryTest.cpp
@@ -0,0 +1,813 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include <memory>
+#include <stdint.h>
+
+#include "EGLWindow.h"
+#include "OSWindow.h"
+#include "test_utils/angle_test_configs.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+class ProgramBinaryTest : public ANGLETest
+{
+  protected:
+    ProgramBinaryTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            attribute vec4 inputAttribute;
+            void main()
+            {
+                gl_Position = inputAttribute;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            void main()
+            {
+                gl_FragColor = vec4(1,0,0,1);
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        glGenBuffers(1, &mBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+        glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_STATIC_DRAW);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+        glDeleteBuffers(1, &mBuffer);
+
+        ANGLETest::TearDown();
+    }
+
+    GLint getAvailableProgramBinaryFormatCount() const
+    {
+        GLint formatCount;
+        glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &formatCount);
+        return formatCount;
+    }
+
+    GLuint mProgram;
+    GLuint mBuffer;
+};
+
+// This tests the assumption that float attribs of different size
+// should not internally cause a vertex shader recompile (for conversion).
+TEST_P(ProgramBinaryTest, FloatDynamicShaderSize)
+{
+    if (!extensionEnabled("GL_OES_get_program_binary"))
+    {
+        std::cout << "Test skipped because GL_OES_get_program_binary is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (getAvailableProgramBinaryFormatCount() == 0)
+    {
+        std::cout << "Test skipped because no program binary formats are available." << std::endl;
+        return;
+    }
+
+    glUseProgram(mProgram);
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+
+    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8, nullptr);
+    glEnableVertexAttribArray(0);
+    glDrawArrays(GL_POINTS, 0, 1);
+
+    GLint programLength;
+    glGetProgramiv(mProgram, GL_PROGRAM_BINARY_LENGTH_OES, &programLength);
+
+    EXPECT_GL_NO_ERROR();
+
+    for (GLsizei size = 1; size <= 3; size++)
+    {
+        glVertexAttribPointer(0, size, GL_FLOAT, GL_FALSE, 8, nullptr);
+        glEnableVertexAttribArray(0);
+        glDrawArrays(GL_POINTS, 0, 1);
+
+        GLint newProgramLength;
+        glGetProgramiv(mProgram, GL_PROGRAM_BINARY_LENGTH_OES, &newProgramLength);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_EQ(programLength, newProgramLength);
+    }
+}
+
+// Tests that switching between signed and unsigned un-normalized data doesn't trigger a bug
+// in the D3D11 back-end.
+TEST_P(ProgramBinaryTest, DynamicShadersSignatureBug)
+{
+    glUseProgram(mProgram);
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+
+    GLint attribLocation = glGetAttribLocation(mProgram, "inputAttribute");
+    ASSERT_NE(-1, attribLocation);
+    glEnableVertexAttribArray(attribLocation);
+
+    glVertexAttribPointer(attribLocation, 2, GL_BYTE, GL_FALSE, 0, nullptr);
+    glDrawArrays(GL_POINTS, 0, 1);
+
+    glVertexAttribPointer(attribLocation, 2, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
+    glDrawArrays(GL_POINTS, 0, 1);
+}
+
+// This tests the ability to successfully save and load a program binary.
+TEST_P(ProgramBinaryTest, SaveAndLoadBinary)
+{
+    if (!extensionEnabled("GL_OES_get_program_binary"))
+    {
+        std::cout << "Test skipped because GL_OES_get_program_binary is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (getAvailableProgramBinaryFormatCount() == 0)
+    {
+        std::cout << "Test skipped because no program binary formats are available." << std::endl;
+        return;
+    }
+
+    GLint programLength = 0;
+    GLint writtenLength = 0;
+    GLenum binaryFormat = 0;
+
+    glGetProgramiv(mProgram, GL_PROGRAM_BINARY_LENGTH_OES, &programLength);
+    EXPECT_GL_NO_ERROR();
+
+    std::vector<uint8_t> binary(programLength);
+    glGetProgramBinaryOES(mProgram, programLength, &writtenLength, &binaryFormat, binary.data());
+    EXPECT_GL_NO_ERROR();
+
+    // The lengths reported by glGetProgramiv and glGetProgramBinaryOES should match
+    EXPECT_EQ(programLength, writtenLength);
+
+    if (writtenLength)
+    {
+        GLuint program2 = glCreateProgram();
+        glProgramBinaryOES(program2, binaryFormat, binary.data(), writtenLength);
+
+        EXPECT_GL_NO_ERROR();
+
+        GLint linkStatus;
+        glGetProgramiv(program2, GL_LINK_STATUS, &linkStatus);
+        if (linkStatus == 0)
+        {
+            GLint infoLogLength;
+            glGetProgramiv(program2, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+            if (infoLogLength > 0)
+            {
+                std::vector<GLchar> infoLog(infoLogLength);
+                glGetProgramInfoLog(program2, static_cast<GLsizei>(infoLog.size()), nullptr,
+                                    &infoLog[0]);
+                FAIL() << "program link failed: " << &infoLog[0];
+            }
+            else
+            {
+                FAIL() << "program link failed.";
+            }
+        }
+        else
+        {
+            glUseProgram(program2);
+            glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+
+            glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8, nullptr);
+            glEnableVertexAttribArray(0);
+            glDrawArrays(GL_POINTS, 0, 1);
+
+            EXPECT_GL_NO_ERROR();
+        }
+
+        glDeleteProgram(program2);
+    }
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(ProgramBinaryTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL());
+
+class ProgramBinaryES3Test : public ANGLETest
+{
+  protected:
+    void testBinaryAndUBOBlockIndexes(bool drawWithProgramFirst);
+};
+
+void ProgramBinaryES3Test::testBinaryAndUBOBlockIndexes(bool drawWithProgramFirst)
+{
+    // We can't run the test if no program binary formats are supported.
+    GLint binaryFormatCount = 0;
+    glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &binaryFormatCount);
+    if (binaryFormatCount == 0)
+    {
+        std::cout << "Test skipped because no program binary formats available." << std::endl;
+        return;
+    }
+
+    const std::string &vertexShader =
+        "#version 300 es\n"
+        "uniform block {\n"
+        "    float f;\n"
+        "};\n"
+        "in vec4 position;\n"
+        "out vec4 color;\n"
+        "void main() {\n"
+        "    gl_Position = position;\n"
+        "    color = vec4(f, f, f, 1);\n"
+        "}";
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "in vec4 color;\n"
+        "out vec4 colorOut;\n"
+        "void main() {\n"
+        "    colorOut = color;\n"
+        "}";
+
+    // Init and draw with the program.
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+
+    float fData[4]   = {1.0f, 1.0f, 1.0f, 1.0f};
+    GLuint bindIndex = 2;
+
+    GLBuffer ubo;
+    glBindBuffer(GL_UNIFORM_BUFFER, ubo.get());
+    glBufferData(GL_UNIFORM_BUFFER, sizeof(fData), &fData, GL_STATIC_DRAW);
+    glBindBufferRange(GL_UNIFORM_BUFFER, bindIndex, ubo.get(), 0, sizeof(fData));
+
+    GLint blockIndex = glGetUniformBlockIndex(program.get(), "block");
+    ASSERT_NE(-1, blockIndex);
+
+    glUniformBlockBinding(program.get(), blockIndex, bindIndex);
+
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    if (drawWithProgramFirst)
+    {
+        drawQuad(program.get(), "position", 0.5f);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
+    }
+
+    // Read back the binary.
+    GLint programLength = 0;
+    glGetProgramiv(program.get(), GL_PROGRAM_BINARY_LENGTH_OES, &programLength);
+    ASSERT_GL_NO_ERROR();
+
+    GLsizei readLength  = 0;
+    GLenum binaryFormat = GL_NONE;
+    std::vector<uint8_t> binary(programLength);
+    glGetProgramBinary(program.get(), programLength, &readLength, &binaryFormat, binary.data());
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_EQ(static_cast<GLsizei>(programLength), readLength);
+
+    // Load a new program with the binary and draw.
+    ANGLE_GL_BINARY_ES3_PROGRAM(binaryProgram, binary, binaryFormat);
+
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    drawQuad(binaryProgram.get(), "position", 0.5f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
+}
+
+// Tests that saving and loading a program perserves uniform block binding info.
+TEST_P(ProgramBinaryES3Test, UniformBlockBindingWithDraw)
+{
+    testBinaryAndUBOBlockIndexes(true);
+}
+
+// Same as above, but does not do an initial draw with the program. Covers an ANGLE crash.
+// http://anglebug.com/1637
+TEST_P(ProgramBinaryES3Test, UniformBlockBindingNoDraw)
+{
+    // TODO(jmadill): Investigate Intel failure.
+    // http://anglebug.com/1637
+    if (IsWindows() && IsOpenGL() && IsIntel())
+    {
+        std::cout << "Test skipped on Windows Intel OpenGL." << std::endl;
+        return;
+    }
+
+    testBinaryAndUBOBlockIndexes(false);
+}
+
+ANGLE_INSTANTIATE_TEST(ProgramBinaryES3Test, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+class ProgramBinaryES31Test : public ANGLETest
+{
+  protected:
+    ProgramBinaryES31Test()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+};
+
+// Tests that saving and loading a program attached with computer shader.
+TEST_P(ProgramBinaryES31Test, ProgramBinaryWithComputeShader)
+{
+    // We can't run the test if no program binary formats are supported.
+    GLint binaryFormatCount = 0;
+    glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &binaryFormatCount);
+    if (binaryFormatCount == 0)
+    {
+        std::cout << "Test skipped because no program binary formats available." << std::endl;
+        return;
+    }
+
+    const std::string &computeShader =
+        "#version 310 es\n"
+        "layout(local_size_x=4, local_size_y=3, local_size_z=1) in;\n"
+        "uniform block {\n"
+        "    vec2 f;\n"
+        "};\n"
+        "uniform vec2 g;\n"
+        "uniform highp sampler2D tex;\n"
+        "void main() {\n"
+        "    vec4 color = texture(tex, f + g);\n"
+        "}";
+
+    ANGLE_GL_COMPUTE_PROGRAM(program, computeShader);
+
+    // Read back the binary.
+    GLint programLength = 0;
+    glGetProgramiv(program.get(), GL_PROGRAM_BINARY_LENGTH, &programLength);
+    ASSERT_GL_NO_ERROR();
+
+    GLsizei readLength  = 0;
+    GLenum binaryFormat = GL_NONE;
+    std::vector<uint8_t> binary(programLength);
+    glGetProgramBinary(program.get(), programLength, &readLength, &binaryFormat, binary.data());
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_EQ(static_cast<GLsizei>(programLength), readLength);
+
+    // Load a new program with the binary.
+    ANGLE_GL_BINARY_ES3_PROGRAM(binaryProgram, binary, binaryFormat);
+
+    // TODO(Xinghua): add dispatch support when available.
+
+    ASSERT_GL_NO_ERROR();
+}
+
+ANGLE_INSTANTIATE_TEST(ProgramBinaryES31Test, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());
+
+class ProgramBinaryTransformFeedbackTest : public ANGLETest
+{
+  protected:
+    ProgramBinaryTransformFeedbackTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (   #version 300 es\n
+            in vec4 inputAttribute;
+            out vec4 outputVarying;
+            void main()
+            {
+                outputVarying = inputAttribute;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (   #version 300 es\n
+            precision highp float;
+            out vec4 outputColor;
+            void main()
+            {
+                outputColor = vec4(1,0,0,1);
+            }
+        );
+
+        std::vector<std::string> transformFeedbackVaryings;
+        transformFeedbackVaryings.push_back("outputVarying");
+
+        mProgram = CompileProgramWithTransformFeedback(
+            vertexShaderSource, fragmentShaderSource, transformFeedbackVaryings,
+            GL_SEPARATE_ATTRIBS);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLint getAvailableProgramBinaryFormatCount() const
+    {
+        GLint formatCount;
+        glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &formatCount);
+        return formatCount;
+    }
+
+    GLuint mProgram;
+};
+
+// This tests the assumption that float attribs of different size
+// should not internally cause a vertex shader recompile (for conversion).
+TEST_P(ProgramBinaryTransformFeedbackTest, GetTransformFeedbackVarying)
+{
+    if (!extensionEnabled("GL_OES_get_program_binary"))
+    {
+        std::cout << "Test skipped because GL_OES_get_program_binary is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (getAvailableProgramBinaryFormatCount() == 0)
+    {
+        std::cout << "Test skipped because no program binary formats are available." << std::endl;
+        return;
+    }
+
+    std::vector<uint8_t> binary(0);
+    GLint programLength = 0;
+    GLint writtenLength = 0;
+    GLenum binaryFormat = 0;
+
+    // Save the program binary out
+    glGetProgramiv(mProgram, GL_PROGRAM_BINARY_LENGTH_OES, &programLength);
+    ASSERT_GL_NO_ERROR();
+    binary.resize(programLength);
+    glGetProgramBinaryOES(mProgram, programLength, &writtenLength, &binaryFormat, binary.data());
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteProgram(mProgram);
+
+    // Load program binary
+    mProgram = glCreateProgram();
+    glProgramBinaryOES(mProgram, binaryFormat, binary.data(), writtenLength);
+
+    // Ensure the loaded binary is linked
+    GLint linkStatus;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
+    EXPECT_TRUE(linkStatus != 0);
+
+    // Query information about the transform feedback varying
+    char varyingName[64];
+    GLsizei varyingSize = 0;
+    GLenum varyingType = GL_NONE;
+
+    glGetTransformFeedbackVarying(mProgram, 0, 64, &writtenLength, &varyingSize, &varyingType, varyingName);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(13, writtenLength);
+    EXPECT_STREQ("outputVarying", varyingName);
+    EXPECT_EQ(1, varyingSize);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varyingType);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(ProgramBinaryTransformFeedbackTest,
+                       ES3_D3D11(),
+                       ES3_OPENGL());
+
+// For the ProgramBinariesAcrossPlatforms tests, we need two sets of params:
+// - a set to save the program binary
+// - a set to load the program binary
+// We combine these into one struct extending PlatformParameters so we can reuse existing ANGLE test macros
+struct PlatformsWithLinkResult : PlatformParameters
+{
+    PlatformsWithLinkResult(PlatformParameters saveParams, PlatformParameters loadParamsIn, bool expectedLinkResultIn)
+    {
+        majorVersion = saveParams.majorVersion;
+        minorVersion = saveParams.minorVersion;
+        eglParameters = saveParams.eglParameters;
+        loadParams = loadParamsIn;
+        expectedLinkResult = expectedLinkResultIn;
+    }
+
+    PlatformParameters loadParams;
+    bool expectedLinkResult;
+};
+
+// Provide a custom gtest parameter name function for PlatformsWithLinkResult
+// to avoid returning the same parameter name twice. Such a conflict would happen
+// between ES2_D3D11_to_ES2D3D11 and ES2_D3D11_to_ES3D3D11 as they were both
+// named ES2_D3D11
+std::ostream &operator<<(std::ostream& stream, const PlatformsWithLinkResult &platform)
+{
+    const PlatformParameters &platform1 = platform;
+    const PlatformParameters &platform2 = platform.loadParams;
+    stream << platform1 << "_to_" << platform2;
+    return stream;
+}
+
+class ProgramBinariesAcrossPlatforms : public testing::TestWithParam<PlatformsWithLinkResult>
+{
+  public:
+    void SetUp() override
+    {
+        mOSWindow = CreateOSWindow();
+        bool result = mOSWindow->initialize("ProgramBinariesAcrossRenderersTests", 100, 100);
+
+        if (result == false)
+        {
+            FAIL() << "Failed to create OS window";
+        }
+    }
+
+    EGLWindow *createAndInitEGLWindow(angle::PlatformParameters &param)
+    {
+        EGLWindow *eglWindow =
+            new EGLWindow(param.majorVersion, param.minorVersion, param.eglParameters);
+        bool result = eglWindow->initializeGL(mOSWindow);
+        if (result == false)
+        {
+            SafeDelete(eglWindow);
+            eglWindow = nullptr;
+        }
+
+        return eglWindow;
+    }
+
+    void destroyEGLWindow(EGLWindow **eglWindow)
+    {
+        ASSERT_NE(nullptr, *eglWindow);
+        (*eglWindow)->destroyGL();
+        SafeDelete(*eglWindow);
+        *eglWindow = nullptr;
+    }
+
+    GLuint createES2ProgramFromSource()
+    {
+        const std::string testVertexShaderSource = SHADER_SOURCE
+        (
+            attribute highp vec4 position;
+
+            void main(void)
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string testFragmentShaderSource = SHADER_SOURCE
+        (
+            void main(void)
+            {
+                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+            }
+        );
+
+        return CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+    }
+
+    GLuint createES3ProgramFromSource()
+    {
+        const std::string testVertexShaderSource = SHADER_SOURCE
+        (   #version 300 es\n
+            precision highp float;
+            in highp vec4 position;
+
+            void main(void)
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string testFragmentShaderSource = SHADER_SOURCE
+        (   #version 300 es \n
+            precision highp float;
+            out vec4 out_FragColor;
+
+            void main(void)
+            {
+                out_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+            }
+        );
+
+        return CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+    }
+
+    void drawWithProgram(GLuint program)
+    {
+        glClearColor(0, 0, 0, 1);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        GLint positionLocation = glGetAttribLocation(program, "position");
+
+        glUseProgram(program);
+
+        const GLfloat vertices[] =
+        {
+            -1.0f,  1.0f, 0.5f,
+            -1.0f, -1.0f, 0.5f,
+             1.0f, -1.0f, 0.5f,
+
+            -1.0f,  1.0f, 0.5f,
+             1.0f, -1.0f, 0.5f,
+             1.0f,  1.0f, 0.5f,
+        };
+
+        glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
+        glEnableVertexAttribArray(positionLocation);
+
+        glDrawArrays(GL_TRIANGLES, 0, 6);
+
+        glDisableVertexAttribArray(positionLocation);
+        glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+        EXPECT_PIXEL_EQ(mOSWindow->getWidth() / 2, mOSWindow->getHeight() / 2, 255, 0, 0, 255);
+    }
+
+    void TearDown() override
+    {
+        mOSWindow->destroy();
+        SafeDelete(mOSWindow);
+    }
+
+    OSWindow *mOSWindow;
+};
+
+// Tries to create a program binary using one set of platform params, then load it using a different sent of params
+TEST_P(ProgramBinariesAcrossPlatforms, CreateAndReloadBinary)
+{
+    angle::PlatformParameters firstRenderer  = GetParam();
+    angle::PlatformParameters secondRenderer = GetParam().loadParams;
+    bool expectedLinkResult                  = GetParam().expectedLinkResult;
+
+    if (!(IsPlatformAvailable(firstRenderer)))
+    {
+        std::cout << "First renderer not supported, skipping test";
+        return;
+    }
+
+    if (!(IsPlatformAvailable(secondRenderer)))
+    {
+        std::cout << "Second renderer not supported, skipping test";
+        return;
+    }
+
+    EGLWindow *eglWindow = nullptr;
+    std::vector<uint8_t> binary(0);
+    GLuint program = 0;
+
+    GLint programLength = 0;
+    GLint writtenLength = 0;
+    GLenum binaryFormat = 0;
+
+    // Create a EGL window with the first renderer
+    eglWindow = createAndInitEGLWindow(firstRenderer);
+    if (eglWindow == nullptr)
+    {
+        FAIL() << "Failed to create EGL window";
+        return;
+    }
+
+    // If the test is trying to use both the default GPU and WARP, but the default GPU *IS* WARP,
+    // then our expectations for the test results will be invalid.
+    if (firstRenderer.eglParameters.deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE &&
+        secondRenderer.eglParameters.deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE)
+    {
+        std::string rendererString = std::string(reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
+        std::transform(rendererString.begin(), rendererString.end(), rendererString.begin(), ::tolower);
+
+        auto basicRenderPos = rendererString.find(std::string("microsoft basic render"));
+        auto softwareAdapterPos = rendererString.find(std::string("software adapter"));
+
+        if (basicRenderPos != std::string::npos || softwareAdapterPos != std::string::npos)
+        {
+            // The first renderer is using WARP, even though we didn't explictly request it
+            // We should skip this test
+            std::cout << "Test skipped on when default GPU is WARP." << std::endl;
+            return;
+        }
+    }
+
+    // Create a program
+    if (firstRenderer.majorVersion == 3)
+    {
+        program = createES3ProgramFromSource();
+    }
+    else
+    {
+        program = createES2ProgramFromSource();
+    }
+
+    if (program == 0)
+    {
+        destroyEGLWindow(&eglWindow);
+        FAIL() << "Failed to create program from source";
+    }
+
+    // Draw using the program to ensure it works as expected
+    drawWithProgram(program);
+    EXPECT_GL_NO_ERROR();
+
+    // Save the program binary out from this renderer
+    glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH_OES, &programLength);
+    EXPECT_GL_NO_ERROR();
+    binary.resize(programLength);
+    glGetProgramBinaryOES(program, programLength, &writtenLength, &binaryFormat, binary.data());
+    EXPECT_GL_NO_ERROR();
+
+    // Destroy the first renderer
+    glDeleteProgram(program);
+    destroyEGLWindow(&eglWindow);
+
+    // Create an EGL window with the second renderer
+    eglWindow = createAndInitEGLWindow(secondRenderer);
+    if (eglWindow == nullptr)
+    {
+        FAIL() << "Failed to create EGL window";
+        return;
+    }
+
+    program = glCreateProgram();
+    glProgramBinaryOES(program, binaryFormat, binary.data(), writtenLength);
+
+    GLint linkStatus;
+    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+    EXPECT_EQ(expectedLinkResult, (linkStatus != 0));
+
+    if (linkStatus != 0)
+    {
+        // If the link was successful, then we should try to draw using the program to ensure it works as expected
+        drawWithProgram(program);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    // Destroy the second renderer
+    glDeleteProgram(program);
+    destroyEGLWindow(&eglWindow);
+}
+
+// clang-format off
+ANGLE_INSTANTIATE_TEST(ProgramBinariesAcrossPlatforms,
+                       //                     | Save the program   | Load the program      | Expected
+                       //                     | using these params | using these params    | link result
+                       PlatformsWithLinkResult(ES2_D3D11(),         ES2_D3D11(),            true         ), // Loading + reloading binary should work
+                       PlatformsWithLinkResult(ES3_D3D11(),         ES3_D3D11(),            true         ), // Loading + reloading binary should work
+                       PlatformsWithLinkResult(ES2_D3D11_FL11_0(),  ES2_D3D11_FL9_3(),      false        ), // Switching feature level shouldn't work
+                       PlatformsWithLinkResult(ES2_D3D11(),         ES2_D3D11_WARP(),       false        ), // Switching from hardware to software shouldn't work
+                       PlatformsWithLinkResult(ES2_D3D11_FL9_3(),   ES2_D3D11_FL9_3_WARP(), false        ), // Switching from hardware to software shouldn't work for FL9 either
+                       PlatformsWithLinkResult(ES2_D3D11(),         ES2_D3D9(),             false        ), // Switching from D3D11 to D3D9 shouldn't work
+                       PlatformsWithLinkResult(ES2_D3D9(),          ES2_D3D11(),            false        ), // Switching from D3D9 to D3D11 shouldn't work
+                       PlatformsWithLinkResult(ES2_D3D11(),         ES3_D3D11(),            false        ), // Switching to newer client version shouldn't work
+                       );
+// clang-format on
diff --git a/src/third_party/angle/src/tests/gl_tests/ProgramInterfaceTest.cpp b/src/third_party/angle/src/tests/gl_tests/ProgramInterfaceTest.cpp
new file mode 100644
index 0000000..641e49d
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ProgramInterfaceTest.cpp
@@ -0,0 +1,138 @@
+//
+// Copyright 2017 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.
+//
+
+// ProgramInterfaceTest: Tests of program interfaces.
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+class ProgramInterfaceTestES31 : public ANGLETest
+{
+  protected:
+    ProgramInterfaceTestES31()
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+};
+
+// Tests glGetProgramResourceIndex.
+TEST_P(ProgramInterfaceTestES31, GetResourceIndex)
+{
+    const std::string &vertexShaderSource =
+        "#version 310 es\n"
+        "precision highp float;\n"
+        "in highp vec4 position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = position;\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 310 es\n"
+        "precision highp float;\n"
+        "uniform vec4 color;\n"
+        "out vec4 oColor;\n"
+        "void main()\n"
+        "{\n"
+        "    oColor = color;\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
+
+    GLuint index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position");
+    EXPECT_GL_NO_ERROR();
+    EXPECT_NE(GL_INVALID_INDEX, index);
+
+    index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "missing");
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(GL_INVALID_INDEX, index);
+
+    index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor");
+    EXPECT_GL_NO_ERROR();
+    EXPECT_NE(GL_INVALID_INDEX, index);
+
+    index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "missing");
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(GL_INVALID_INDEX, index);
+
+    index = glGetProgramResourceIndex(program, GL_ATOMIC_COUNTER_BUFFER, "missing");
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+// Tests glGetProgramResourceName.
+TEST_P(ProgramInterfaceTestES31, GetResourceName)
+{
+    const std::string &vertexShaderSource =
+        "#version 310 es\n"
+        "precision highp float;\n"
+        "in highp vec4 position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = position;\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 310 es\n"
+        "precision highp float;\n"
+        "uniform vec4 color;\n"
+        "out vec4 oColor[4];\n"
+        "void main()\n"
+        "{\n"
+        "    oColor[0] = color;\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
+
+    GLuint index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position");
+    EXPECT_GL_NO_ERROR();
+    EXPECT_NE(GL_INVALID_INDEX, index);
+
+    GLchar name[64];
+    GLsizei length;
+    glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, sizeof(name), &length, name);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(8, length);
+    EXPECT_EQ("position", std::string(name));
+
+    glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, 4, &length, name);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(3, length);
+    EXPECT_EQ("pos", std::string(name));
+
+    glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, -1, &length, name);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glGetProgramResourceName(program, GL_PROGRAM_INPUT, GL_INVALID_INDEX, sizeof(name), &length,
+                             name);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor");
+    EXPECT_GL_NO_ERROR();
+    EXPECT_NE(GL_INVALID_INDEX, index);
+
+    glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, sizeof(name), &length, name);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(9, length);
+    EXPECT_EQ("oColor[0]", std::string(name));
+
+    glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, 8, &length, name);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(7, length);
+    EXPECT_EQ("oColor[", std::string(name));
+}
+
+ANGLE_INSTANTIATE_TEST(ProgramInterfaceTestES31, ES31_OPENGL(), ES31_D3D11(), ES31_OPENGLES());
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/ProgramParameterTest.cpp b/src/third_party/angle/src/tests/gl_tests/ProgramParameterTest.cpp
new file mode 100644
index 0000000..18a1a6f
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ProgramParameterTest.cpp
@@ -0,0 +1,81 @@
+//
+// Copyright 2017 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.
+//
+
+// ProgramParameterTest: validate parameters of ProgramParameter
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class ProgramParameterTest : public ANGLETest
+{
+  protected:
+    ProgramParameterTest()
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+};
+
+class ProgramParameterTestES31 : public ProgramParameterTest
+{
+  protected:
+    ProgramParameterTestES31() : ProgramParameterTest() {}
+};
+
+// If es version < 3.1, PROGRAM_SEPARABLE is not supported.
+TEST_P(ProgramParameterTest, ValidatePname)
+{
+    GLuint program = glCreateProgram();
+    ASSERT_NE(program, 0u);
+
+    glProgramParameteri(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
+    ASSERT_GL_NO_ERROR();
+
+    glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
+    if (getClientMajorVersion() < 3 || getClientMinorVersion() < 1)
+    {
+        ASSERT_GL_ERROR(GL_INVALID_ENUM);
+    }
+    else
+    {
+        ASSERT_GL_NO_ERROR();
+    }
+
+    glDeleteProgram(program);
+}
+
+// Validate parameters for ProgramParameter when pname is PROGRAM_SEPARABLE.
+TEST_P(ProgramParameterTestES31, ValidateParameters)
+{
+    GLuint program = glCreateProgram();
+    ASSERT_NE(program, 0u);
+
+    glProgramParameteri(0, GL_PROGRAM_SEPARABLE, GL_TRUE);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    glProgramParameteri(program, GL_PROGRAM_SEPARABLE, 2);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    glDeleteProgram(program);
+}
+
+ANGLE_INSTANTIATE_TEST(ProgramParameterTest,
+                       ES3_OPENGL(),
+                       ES3_OPENGLES(),
+                       ES3_D3D11(),
+                       ES31_OPENGL(),
+                       ES31_OPENGLES(),
+                       ES31_D3D11());
+ANGLE_INSTANTIATE_TEST(ProgramParameterTestES31, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
+}
diff --git a/src/third_party/angle/src/tests/gl_tests/ProvokingVertexTest.cpp b/src/third_party/angle/src/tests/gl_tests/ProvokingVertexTest.cpp
new file mode 100644
index 0000000..15c4c9d
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ProvokingVertexTest.cpp
@@ -0,0 +1,316 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProvkingVertexTest:
+//   Tests on the conformance of the provoking vertex, which applies to flat
+//   shading and compatibility with D3D. See the section on 'flatshading'
+//   in the ES 3 specs.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class ProvokingVertexTest : public ANGLETest
+{
+  protected:
+    ProvokingVertexTest()
+        : mProgram(0),
+          mFramebuffer(0),
+          mTexture(0),
+          mTransformFeedback(0),
+          mBuffer(0),
+          mIntAttribLocation(-1)
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string &vertexShader =
+            "#version 300 es\n"
+            "in int intAttrib;\n"
+            "in vec2 position;\n"
+            "flat out int attrib;\n"
+            "void main() {\n"
+            "  gl_Position = vec4(position, 0, 1);\n"
+            "  attrib = intAttrib;\n"
+            "}";
+
+        const std::string &fragmentShader =
+            "#version 300 es\n"
+            "flat in int attrib;\n"
+            "out int fragColor;\n"
+            "void main() {\n"
+            "  fragColor = attrib;\n"
+            "}";
+
+        std::vector<std::string> tfVaryings;
+        tfVaryings.push_back("attrib");
+        mProgram = CompileProgramWithTransformFeedback(vertexShader, fragmentShader, tfVaryings,
+                                                       GL_SEPARATE_ATTRIBS);
+        ASSERT_NE(0u, mProgram);
+
+        glGenTextures(1, &mTexture);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+        glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, getWindowWidth(), getWindowHeight());
+
+        glGenFramebuffers(1, &mFramebuffer);
+        glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
+
+        mIntAttribLocation = glGetAttribLocation(mProgram, "intAttrib");
+        ASSERT_NE(-1, mIntAttribLocation);
+        glEnableVertexAttribArray(mIntAttribLocation);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        if (mProgram != 0)
+        {
+            glDeleteProgram(mProgram);
+            mProgram = 0;
+        }
+
+        if (mFramebuffer != 0)
+        {
+            glDeleteFramebuffers(1, &mFramebuffer);
+            mFramebuffer = 0;
+        }
+
+        if (mTexture != 0)
+        {
+            glDeleteTextures(1, &mTexture);
+            mTexture = 0;
+        }
+
+        if (mTransformFeedback != 0)
+        {
+            glDeleteTransformFeedbacks(1, &mTransformFeedback);
+            mTransformFeedback = 0;
+        }
+
+        if (mBuffer != 0)
+        {
+            glDeleteBuffers(1, &mBuffer);
+            mBuffer = 0;
+        }
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+    GLuint mFramebuffer;
+    GLuint mTexture;
+    GLuint mTransformFeedback;
+    GLuint mBuffer;
+    GLint mIntAttribLocation;
+};
+
+// Test drawing a simple triangle with flat shading, and different valued vertices.
+TEST_P(ProvokingVertexTest, FlatTriangle)
+{
+    GLint vertexData[] = {1, 2, 3, 1, 2, 3};
+    glVertexAttribIPointer(mIntAttribLocation, 1, GL_INT, 0, vertexData);
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    GLint pixelValue = 0;
+    glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_INT, &pixelValue);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(vertexData[2], pixelValue);
+}
+
+// Ensure that any provoking vertex shenanigans still gives correct vertex streams.
+TEST_P(ProvokingVertexTest, FlatTriWithTransformFeedback)
+{
+// TODO(cwallez) figure out why it is broken on AMD on Mac
+#if defined(ANGLE_PLATFORM_APPLE)
+    if (IsAMD())
+    {
+        std::cout << "Test skipped on AMD on Mac." << std::endl;
+        return;
+    }
+#endif
+
+    glGenTransformFeedbacks(1, &mTransformFeedback);
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
+
+    glGenBuffers(1, &mBuffer);
+    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mBuffer);
+    glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 128, nullptr, GL_STREAM_DRAW);
+
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mBuffer);
+
+    GLint vertexData[] = {1, 2, 3, 1, 2, 3};
+    glVertexAttribIPointer(mIntAttribLocation, 1, GL_INT, 0, vertexData);
+
+    glUseProgram(mProgram);
+    glBeginTransformFeedback(GL_TRIANGLES);
+    drawQuad(mProgram, "position", 0.5f);
+    glEndTransformFeedback();
+    glUseProgram(0);
+
+    GLint pixelValue = 0;
+    glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_INT, &pixelValue);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(vertexData[2], pixelValue);
+
+    void *mapPointer =
+        glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(int) * 6, GL_MAP_READ_BIT);
+    ASSERT_NE(nullptr, mapPointer);
+
+    int *mappedInts = static_cast<int *>(mapPointer);
+    for (unsigned int cnt = 0; cnt < 6; ++cnt)
+    {
+        EXPECT_EQ(vertexData[cnt], mappedInts[cnt]);
+    }
+}
+
+// Test drawing a simple line with flat shading, and different valued vertices.
+TEST_P(ProvokingVertexTest, FlatLine)
+{
+    GLfloat halfPixel = 1.0f / static_cast<GLfloat>(getWindowWidth());
+
+    GLint vertexData[]     = {1, 2};
+    GLfloat positionData[] = {-1.0f + halfPixel, -1.0f, -1.0f + halfPixel, 1.0f};
+
+    glVertexAttribIPointer(mIntAttribLocation, 1, GL_INT, 0, vertexData);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    glEnableVertexAttribArray(positionLocation);
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, positionData);
+
+    glUseProgram(mProgram);
+    glDrawArrays(GL_LINES, 0, 2);
+
+    GLint pixelValue = 0;
+    glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_INT, &pixelValue);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(vertexData[1], pixelValue);
+}
+
+// Test drawing a simple triangle strip with flat shading, and different valued vertices.
+TEST_P(ProvokingVertexTest, FlatTriStrip)
+{
+    GLint vertexData[]     = {1, 2, 3, 4, 5, 6};
+    GLfloat positionData[] = {-1.0f, -1.0f, -1.0f, 1.0f,  0.0f, -1.0f,
+                              0.0f,  1.0f,  1.0f,  -1.0f, 1.0f, 1.0f};
+
+    glVertexAttribIPointer(mIntAttribLocation, 1, GL_INT, 0, vertexData);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    glEnableVertexAttribArray(positionLocation);
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, positionData);
+
+    glUseProgram(mProgram);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
+
+    std::vector<GLint> pixelBuffer(getWindowWidth() * getWindowHeight(), 0);
+    glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RED_INTEGER, GL_INT,
+                 &pixelBuffer[0]);
+
+    ASSERT_GL_NO_ERROR();
+
+    for (unsigned int triIndex = 0; triIndex < 4; ++triIndex)
+    {
+        GLfloat sumX = positionData[triIndex * 2 + 0] + positionData[triIndex * 2 + 2] +
+                       positionData[triIndex * 2 + 4];
+        GLfloat sumY = positionData[triIndex * 2 + 1] + positionData[triIndex * 2 + 3] +
+                       positionData[triIndex * 2 + 5];
+
+        float centerX = sumX / 3.0f * 0.5f + 0.5f;
+        float centerY = sumY / 3.0f * 0.5f + 0.5f;
+        unsigned int pixelX =
+            static_cast<unsigned int>(centerX * static_cast<GLfloat>(getWindowWidth()));
+        unsigned int pixelY =
+            static_cast<unsigned int>(centerY * static_cast<GLfloat>(getWindowHeight()));
+        unsigned int pixelIndex = pixelY * getWindowWidth() + pixelX;
+
+        unsigned int provokingVertexIndex = triIndex + 2;
+
+        EXPECT_EQ(vertexData[provokingVertexIndex], pixelBuffer[pixelIndex]);
+    }
+}
+
+// Test drawing an indexed triangle strip with flat shading and primitive restart.
+TEST_P(ProvokingVertexTest, FlatTriStripPrimitiveRestart)
+{
+    // TODO(jmadill): Implement on the D3D back-end.
+    if (IsD3D11())
+    {
+        std::cout << "Test disabled on D3D11." << std::endl;
+        return;
+    }
+
+    GLint indexData[]      = {0, 1, 2, -1, 1, 2, 3, 4, -1, 3, 4, 5};
+    GLint vertexData[]     = {1, 2, 3, 4, 5, 6};
+    GLfloat positionData[] = {-1.0f, -1.0f, -1.0f, 1.0f,  0.0f, -1.0f,
+                              0.0f,  1.0f,  1.0f,  -1.0f, 1.0f, 1.0f};
+
+    glVertexAttribIPointer(mIntAttribLocation, 1, GL_INT, 0, vertexData);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    glEnableVertexAttribArray(positionLocation);
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, positionData);
+
+    glDisable(GL_CULL_FACE);
+    glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
+    glUseProgram(mProgram);
+    glDrawElements(GL_TRIANGLE_STRIP, 12, GL_UNSIGNED_INT, indexData);
+
+    std::vector<GLint> pixelBuffer(getWindowWidth() * getWindowHeight(), 0);
+    glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RED_INTEGER, GL_INT,
+                 &pixelBuffer[0]);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Account for primitive restart when checking the tris.
+    GLint triOffsets[] = {0, 4, 5, 9};
+
+    for (unsigned int triIndex = 0; triIndex < 4; ++triIndex)
+    {
+        GLint vertexA = indexData[triOffsets[triIndex] + 0];
+        GLint vertexB = indexData[triOffsets[triIndex] + 1];
+        GLint vertexC = indexData[triOffsets[triIndex] + 2];
+
+        GLfloat sumX =
+            positionData[vertexA * 2] + positionData[vertexB * 2] + positionData[vertexC * 2];
+        GLfloat sumY = positionData[vertexA * 2 + 1] + positionData[vertexB * 2 + 1] +
+                       positionData[vertexC * 2 + 1];
+
+        float centerX = sumX / 3.0f * 0.5f + 0.5f;
+        float centerY = sumY / 3.0f * 0.5f + 0.5f;
+        unsigned int pixelX =
+            static_cast<unsigned int>(centerX * static_cast<GLfloat>(getWindowWidth()));
+        unsigned int pixelY =
+            static_cast<unsigned int>(centerY * static_cast<GLfloat>(getWindowHeight()));
+        unsigned int pixelIndex = pixelY * getWindowWidth() + pixelX;
+
+        unsigned int provokingVertexIndex = triIndex + 2;
+
+        EXPECT_EQ(vertexData[provokingVertexIndex], pixelBuffer[pixelIndex]);
+    }
+}
+
+ANGLE_INSTANTIATE_TEST(ProvokingVertexTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/ReadPixelsTest.cpp b/src/third_party/angle/src/tests/gl_tests/ReadPixelsTest.cpp
new file mode 100644
index 0000000..1f5f5c0
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ReadPixelsTest.cpp
@@ -0,0 +1,726 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ReadPixelsTest:
+//   Tests calls related to glReadPixels.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include <array>
+
+#include "random_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+class ReadPixelsTest : public ANGLETest
+{
+  protected:
+    ReadPixelsTest()
+    {
+        setWindowWidth(32);
+        setWindowHeight(32);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+};
+
+// Test out of bounds framebuffer reads.
+TEST_P(ReadPixelsTest, OutOfBounds)
+{
+    // TODO: re-enable once root cause of http://anglebug.com/1413 is fixed
+    if (IsAndroid() && IsAdreno() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
+        return;
+    }
+
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    GLsizei pixelsWidth  = 32;
+    GLsizei pixelsHeight = 32;
+    GLint offset         = 16;
+    std::vector<GLColor> pixels((pixelsWidth + offset) * (pixelsHeight + offset));
+
+    glReadPixels(-offset, -offset, pixelsWidth + offset, pixelsHeight + offset, GL_RGBA,
+                 GL_UNSIGNED_BYTE, &pixels[0]);
+    EXPECT_GL_NO_ERROR();
+
+    // Expect that all pixels which fell within the framebuffer are red
+    for (int y = pixelsHeight / 2; y < pixelsHeight; y++)
+    {
+        for (int x = pixelsWidth / 2; x < pixelsWidth; x++)
+        {
+            EXPECT_EQ(GLColor::red, pixels[y * (pixelsWidth + offset) + x]);
+        }
+    }
+}
+
+class ReadPixelsPBOTest : public ReadPixelsTest
+{
+  protected:
+    ReadPixelsPBOTest() : mPBO(0), mTexture(0), mFBO(0) {}
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenBuffers(1, &mPBO);
+        glGenFramebuffers(1, &mFBO);
+
+        Reset(4 * getWindowWidth() * getWindowHeight(), 4, 1);
+    }
+
+    void Reset(GLuint bufferSize, GLuint fboWidth, GLuint fboHeight)
+    {
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+        glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+
+        glDeleteTextures(1, &mTexture);
+        glGenTextures(1, &mTexture);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, fboWidth, fboHeight);
+
+        glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteBuffers(1, &mPBO);
+        glDeleteTextures(1, &mTexture);
+        glDeleteFramebuffers(1, &mFBO);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mPBO     = 0;
+    GLuint mTexture = 0;
+    GLuint mFBO     = 0;
+};
+
+// Test basic usage of PBOs.
+TEST_P(ReadPixelsPBOTest, Basic)
+{
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    void *mappedPtr    = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
+    GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GLColor::red, dataColor[0]);
+
+    glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test an error is generated when the PBO is too small.
+TEST_P(ReadPixelsPBOTest, PBOTooSmall)
+{
+    Reset(4 * 16 * 16 - 1, 16, 16);
+
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test an error is generated when the PBO is mapped.
+TEST_P(ReadPixelsPBOTest, PBOMapped)
+{
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+    glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test that binding a PBO to ARRAY_BUFFER works as expected.
+TEST_P(ReadPixelsPBOTest, ArrayBufferTarget)
+{
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, mPBO);
+
+    void *mappedPtr    = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
+    GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GLColor::red, dataColor[0]);
+
+    glUnmapBuffer(GL_ARRAY_BUFFER);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that using a PBO does not overwrite existing data.
+TEST_P(ReadPixelsPBOTest, ExistingDataPreserved)
+{
+    // TODO(geofflang): Figure out why this fails on AMD OpenGL (http://anglebug.com/1291)
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test disabled on AMD OpenGL." << std::endl;
+        return;
+    }
+
+    // Clear backbuffer to red
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    // Read 16x16 region from red backbuffer to PBO
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    // Clear backbuffer to green
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    // Read 16x16 region from green backbuffer to PBO at offset 16
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(16));
+    void *mappedPtr    = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
+    GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
+    EXPECT_GL_NO_ERROR();
+
+    // Test pixel 0 is red (existing data)
+    EXPECT_EQ(GLColor::red, dataColor[0]);
+
+    // Test pixel 16 is green (new data)
+    EXPECT_EQ(GLColor::green, dataColor[16]);
+
+    glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that calling SubData preserves PBO data.
+TEST_P(ReadPixelsPBOTest, SubDataPreservesContents)
+{
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    unsigned char data[4] = {1, 2, 3, 4};
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, mPBO);
+    glBufferSubData(GL_ARRAY_BUFFER, 0, 4, data);
+
+    void *mappedPtr    = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
+    GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GLColor(1, 2, 3, 4), dataColor[0]);
+
+    glUnmapBuffer(GL_ARRAY_BUFFER);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Same as the prior test, but with an offset.
+TEST_P(ReadPixelsPBOTest, SubDataOffsetPreservesContents)
+{
+    // TODO: re-enable once root cause of http://anglebug.com/1415 is fixed
+    if (IsAndroid() && IsAdreno() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
+        return;
+    }
+
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    unsigned char data[4] = {1, 2, 3, 4};
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, mPBO);
+    glBufferSubData(GL_ARRAY_BUFFER, 16, 4, data);
+
+    void *mappedPtr    = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
+    GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GLColor::red, dataColor[0]);
+    EXPECT_EQ(GLColor(1, 2, 3, 4), dataColor[4]);
+
+    glUnmapBuffer(GL_ARRAY_BUFFER);
+    EXPECT_GL_NO_ERROR();
+}
+
+class ReadPixelsPBODrawTest : public ReadPixelsPBOTest
+{
+  protected:
+    ReadPixelsPBODrawTest() : mProgram(0), mPositionVBO(0) {}
+
+    void SetUp() override
+    {
+        ReadPixelsPBOTest::SetUp();
+
+        const char *vertexShaderSrc =
+            "attribute vec4 aTest; attribute vec2 aPosition; varying vec4 vTest;\n"
+            "void main()\n"
+            "{\n"
+            "    vTest        = aTest;\n"
+            "    gl_Position  = vec4(aPosition, 0.0, 1.0);\n"
+            "    gl_PointSize = 1.0;\n"
+            "}";
+
+        const char *fragmentShaderSrc =
+            "precision mediump float; varying vec4 vTest;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = vTest;\n"
+            "}";
+
+        mProgram = CompileProgram(vertexShaderSrc, fragmentShaderSrc);
+        ASSERT_NE(0u, mProgram);
+
+        glGenBuffers(1, &mPositionVBO);
+        glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
+        glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_DYNAMIC_DRAW);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+        glDeleteBuffers(1, &mPositionVBO);
+        ReadPixelsPBOTest::TearDown();
+    }
+
+    GLuint mProgram;
+    GLuint mPositionVBO;
+};
+
+// Test that we can draw with PBO data.
+TEST_P(ReadPixelsPBODrawTest, DrawWithPBO)
+{
+    GLColor color(1, 2, 3, 4);
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
+    EXPECT_GL_NO_ERROR();
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, mFBO);
+    EXPECT_GL_NO_ERROR();
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+    EXPECT_GL_NO_ERROR();
+
+    float positionData[] = {0.5f, 0.5f};
+
+    glUseProgram(mProgram);
+    glViewport(0, 0, 1, 1);
+    glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
+    glBufferSubData(GL_ARRAY_BUFFER, 0, 1 * 2 * 4, positionData);
+    EXPECT_GL_NO_ERROR();
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");
+    EXPECT_NE(-1, positionLocation);
+
+    GLint testLocation = glGetAttribLocation(mProgram, "aTest");
+    EXPECT_NE(-1, testLocation);
+
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(positionLocation);
+    EXPECT_GL_NO_ERROR();
+
+    glBindBuffer(GL_ARRAY_BUFFER, mPBO);
+    glVertexAttribPointer(testLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(testLocation);
+    EXPECT_GL_NO_ERROR();
+
+    glDrawArrays(GL_POINTS, 0, 1);
+    EXPECT_GL_NO_ERROR();
+
+    color = GLColor(0, 0, 0, 0);
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GLColor(1, 2, 3, 4), color);
+}
+
+class ReadPixelsMultisampleTest : public ReadPixelsTest
+{
+  protected:
+    ReadPixelsMultisampleTest() : mFBO(0), mRBO(0), mPBO(0) {}
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenFramebuffers(1, &mFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+
+        glGenRenderbuffers(1, &mRBO);
+        glBindRenderbuffer(GL_RENDERBUFFER, mRBO);
+
+        glGenBuffers(1, &mPBO);
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+        glBufferData(GL_PIXEL_PACK_BUFFER, 4 * getWindowWidth() * getWindowHeight(), nullptr,
+                     GL_STATIC_DRAW);
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        ANGLETest::TearDown();
+
+        glDeleteFramebuffers(1, &mFBO);
+        glDeleteRenderbuffers(1, &mRBO);
+        glDeleteBuffers(1, &mPBO);
+    }
+
+    GLuint mFBO;
+    GLuint mRBO;
+    GLuint mPBO;
+};
+
+// Test ReadPixels from a multisampled framebuffer.
+TEST_P(ReadPixelsMultisampleTest, BasicClear)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_ANGLE_framebuffer_multisample"))
+    {
+        std::cout
+            << "Test skipped because ES3 or GL_ANGLE_framebuffer_multisample is not available."
+            << std::endl;
+        return;
+    }
+
+    if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
+    {
+        glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, GL_RGBA8, 4, 4);
+    }
+    else
+    {
+        glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 4, 4);
+    }
+
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRBO);
+    ASSERT_GL_NO_ERROR();
+
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
+    EXPECT_GL_NO_ERROR();
+
+    glReadPixels(0, 0, 1, 1, GL_RGBA8, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+class ReadPixelsTextureTest : public ANGLETest
+{
+  public:
+    ReadPixelsTextureTest() : mFBO(0), mTexture(0)
+    {
+        setWindowWidth(32);
+        setWindowHeight(32);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenTextures(1, &mTexture);
+        glGenFramebuffers(1, &mFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+    }
+
+    void TearDown() override
+    {
+        glDeleteFramebuffers(1, &mFBO);
+        glDeleteTextures(1, &mTexture);
+
+        ANGLETest::TearDown();
+    }
+
+    void initTexture(GLenum textureTarget,
+                     GLint levels,
+                     GLint attachmentLevel,
+                     GLint attachmentLayer)
+    {
+        glBindTexture(textureTarget, mTexture);
+        glTexStorage3D(textureTarget, levels, GL_RGBA8, 4, 4, 4);
+        glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, attachmentLevel,
+                                  attachmentLayer);
+        initializeTextureData(textureTarget, levels);
+    }
+
+    void testRead(GLenum textureTarget, GLint levels, GLint attachmentLevel, GLint attachmentLayer)
+    {
+        initTexture(textureTarget, levels, attachmentLevel, attachmentLayer);
+        verifyColor(attachmentLevel, attachmentLayer);
+    }
+
+    void initPBO()
+    {
+        glGenBuffers(1, &mBuffer);
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, mBuffer);
+        glBufferData(GL_PIXEL_PACK_BUFFER, sizeof(angle::GLColor), nullptr, GL_STREAM_COPY);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void testPBORead(GLenum textureTarget,
+                     GLint levels,
+                     GLint attachmentLevel,
+                     GLint attachmentLayer)
+    {
+        initPBO();
+        initTexture(textureTarget, levels, attachmentLevel, attachmentLayer);
+        verifyPBO(attachmentLevel, attachmentLayer);
+    }
+
+    // Give each {level,layer} pair a (probably) unique color via random.
+    GLuint getColorValue(GLint level, GLint layer)
+    {
+        mRNG.reseed(level + layer * 32);
+        return mRNG.randomUInt();
+    }
+
+    void verifyColor(GLint level, GLint layer)
+    {
+        angle::GLColor colorValue(getColorValue(level, layer));
+        EXPECT_PIXEL_COLOR_EQ(0, 0, colorValue);
+    }
+
+    void verifyPBO(GLint level, GLint layer)
+    {
+        glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+        angle::GLColor expectedColor(getColorValue(level, layer));
+        void *mapPointer =
+            glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, sizeof(angle::GLColor), GL_MAP_READ_BIT);
+        ASSERT_NE(nullptr, mapPointer);
+        angle::GLColor actualColor;
+        memcpy(&actualColor, mapPointer, sizeof(angle::GLColor));
+        glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(expectedColor, actualColor);
+    }
+
+    void initializeTextureData(GLenum textureTarget, GLint levels)
+    {
+        for (GLint level = 0; level < levels; ++level)
+        {
+            GLint mipSize = 4 >> level;
+            GLint layers  = (textureTarget == GL_TEXTURE_3D ? mipSize : 4);
+
+            size_t layerSize = mipSize * mipSize;
+            std::vector<GLuint> textureData(layers * layerSize);
+
+            for (GLint layer = 0; layer < layers; ++layer)
+            {
+                GLuint colorValue = getColorValue(level, layer);
+                size_t offset     = (layer * layerSize);
+                std::fill(textureData.begin() + offset, textureData.begin() + offset + layerSize,
+                          colorValue);
+            }
+
+            glTexSubImage3D(textureTarget, level, 0, 0, 0, mipSize, mipSize, layers, GL_RGBA,
+                            GL_UNSIGNED_BYTE, textureData.data());
+        }
+    }
+
+    angle::RNG mRNG;
+    GLuint mFBO;
+    GLuint mTexture;
+    GLuint mBuffer;
+};
+
+// Test 3D attachment readback.
+TEST_P(ReadPixelsTextureTest, BasicAttachment3D)
+{
+    testRead(GL_TEXTURE_3D, 1, 0, 0);
+}
+
+// Test 3D attachment readback, non-zero mip.
+TEST_P(ReadPixelsTextureTest, MipAttachment3D)
+{
+    testRead(GL_TEXTURE_3D, 2, 1, 0);
+}
+
+// Test 3D attachment readback, non-zero layer.
+TEST_P(ReadPixelsTextureTest, LayerAttachment3D)
+{
+    testRead(GL_TEXTURE_3D, 1, 0, 1);
+}
+
+// Test 3D attachment readback, non-zero mip and layer.
+TEST_P(ReadPixelsTextureTest, MipLayerAttachment3D)
+{
+    testRead(GL_TEXTURE_3D, 2, 1, 1);
+}
+
+// Test 2D array attachment readback.
+TEST_P(ReadPixelsTextureTest, BasicAttachment2DArray)
+{
+    testRead(GL_TEXTURE_2D_ARRAY, 1, 0, 0);
+}
+
+// Test 3D attachment readback, non-zero mip.
+TEST_P(ReadPixelsTextureTest, MipAttachment2DArray)
+{
+    testRead(GL_TEXTURE_2D_ARRAY, 2, 1, 0);
+}
+
+// Test 3D attachment readback, non-zero layer.
+TEST_P(ReadPixelsTextureTest, LayerAttachment2DArray)
+{
+    testRead(GL_TEXTURE_2D_ARRAY, 1, 0, 1);
+}
+
+// Test 3D attachment readback, non-zero mip and layer.
+TEST_P(ReadPixelsTextureTest, MipLayerAttachment2DArray)
+{
+    testRead(GL_TEXTURE_2D_ARRAY, 2, 1, 1);
+}
+
+// Test 3D attachment PBO readback.
+TEST_P(ReadPixelsTextureTest, BasicAttachment3DPBO)
+{
+    testPBORead(GL_TEXTURE_3D, 1, 0, 0);
+}
+
+// Test 3D attachment readback, non-zero mip.
+TEST_P(ReadPixelsTextureTest, MipAttachment3DPBO)
+{
+    testPBORead(GL_TEXTURE_3D, 2, 1, 0);
+}
+
+// Test 3D attachment readback, non-zero layer.
+TEST_P(ReadPixelsTextureTest, LayerAttachment3DPBO)
+{
+    testPBORead(GL_TEXTURE_3D, 1, 0, 1);
+}
+
+// Test 3D attachment readback, non-zero mip and layer.
+TEST_P(ReadPixelsTextureTest, MipLayerAttachment3DPBO)
+{
+    testPBORead(GL_TEXTURE_3D, 2, 1, 1);
+}
+
+// Test 2D array attachment readback.
+TEST_P(ReadPixelsTextureTest, BasicAttachment2DArrayPBO)
+{
+    testPBORead(GL_TEXTURE_2D_ARRAY, 1, 0, 0);
+}
+
+// Test 3D attachment readback, non-zero mip.
+TEST_P(ReadPixelsTextureTest, MipAttachment2DArrayPBO)
+{
+    testPBORead(GL_TEXTURE_2D_ARRAY, 2, 1, 0);
+}
+
+// Test 3D attachment readback, non-zero layer.
+TEST_P(ReadPixelsTextureTest, LayerAttachment2DArrayPBO)
+{
+    testPBORead(GL_TEXTURE_2D_ARRAY, 1, 0, 1);
+}
+
+// Test 3D attachment readback, non-zero mip and layer.
+TEST_P(ReadPixelsTextureTest, MipLayerAttachment2DArrayPBO)
+{
+    testPBORead(GL_TEXTURE_2D_ARRAY, 2, 1, 1);
+}
+
+// a test class to be used for error checking of glReadPixels
+class ReadPixelsErrorTest : public ReadPixelsTest
+{
+  protected:
+    ReadPixelsErrorTest() : mTexture(0), mFBO(0) {}
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenTextures(1, &mTexture);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 1);
+
+        glGenFramebuffers(1, &mFBO);
+        glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        ANGLETest::TearDown();
+
+        glDeleteTextures(1, &mTexture);
+        glDeleteFramebuffers(1, &mFBO);
+    }
+
+    GLuint mTexture;
+    GLuint mFBO;
+};
+
+//  The test verifies that glReadPixels generates a GL_INVALID_OPERATION error
+//  when the read buffer is GL_NONE.
+//  Reference: GLES 3.0.4, Section 4.3.2 Reading Pixels
+TEST_P(ReadPixelsErrorTest, ReadBufferIsNone)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+    glReadBuffer(GL_NONE);
+    std::vector<GLubyte> pixels(4);
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+}  // anonymous namespace
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(ReadPixelsTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(ReadPixelsPBOTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(ReadPixelsPBODrawTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(ReadPixelsMultisampleTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(ReadPixelsTextureTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(ReadPixelsErrorTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
diff --git a/src/third_party/angle/src/tests/gl_tests/RendererTest.cpp b/src/third_party/angle/src/tests/gl_tests/RendererTest.cpp
new file mode 100644
index 0000000..20be05f
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/RendererTest.cpp
@@ -0,0 +1,243 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RendererTest:
+//   These tests are designed to ensure that the various configurations of the test fixtures work as expected.
+//   If one of these tests fails, then it is likely that some of the other tests are being configured incorrectly.
+//   For example, they might be using the D3D11 renderer when the test is meant to be using the D3D9 renderer.
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class RendererTest : public ANGLETest
+{
+  protected:
+    RendererTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+    }
+};
+
+TEST_P(RendererTest, RequestedRendererCreated)
+{
+    std::string rendererString = std::string(reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
+    std::transform(rendererString.begin(), rendererString.end(), rendererString.begin(), ::tolower);
+
+    std::string versionString = std::string(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
+    std::transform(versionString.begin(), versionString.end(), versionString.begin(), ::tolower);
+
+    const EGLPlatformParameters &platform = GetParam().eglParameters;
+
+    // Ensure that the renderer string contains D3D11, if we requested a D3D11 renderer.
+    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        ASSERT_NE(rendererString.find(std::string("direct3d11")), std::string::npos);
+    }
+
+    // Ensure that the renderer string contains D3D9, if we requested a D3D9 renderer.
+    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
+    {
+        ASSERT_NE(rendererString.find(std::string("direct3d9")), std::string::npos);
+    }
+
+    // Ensure that the major and minor versions trigger expected behavior in D3D11
+    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        // Ensure that the renderer uses WARP, if we requested it.
+        if (platform.deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE)
+        {
+            auto basicRenderPos = rendererString.find(std::string("microsoft basic render"));
+            auto softwareAdapterPos = rendererString.find(std::string("software adapter"));
+            ASSERT_TRUE(basicRenderPos != std::string::npos || softwareAdapterPos != std::string::npos);
+        }
+
+        std::vector<std::string> acceptableShaderModels;
+
+        // When no specific major/minor version is requested, then ANGLE should return the highest possible feature level by default.
+        // The current hardware driver might not support Feature Level 11_0, but WARP always does.
+        // Therefore if WARP is specified but no major/minor version is specified, then we test to check that ANGLE returns FL11_0.
+        if (platform.majorVersion >= 11 || platform.majorVersion == EGL_DONT_CARE)
+        {
+            // Feature Level 10_0 corresponds to shader model 5_0
+            acceptableShaderModels.push_back("ps_5_0");
+        }
+
+        if (platform.majorVersion >= 10 || platform.majorVersion == EGL_DONT_CARE)
+        {
+            if (platform.minorVersion >= 1 || platform.minorVersion == EGL_DONT_CARE)
+            {
+                // Feature Level 10_1 corresponds to shader model 4_1
+                acceptableShaderModels.push_back("ps_4_1");
+            }
+
+            if (platform.minorVersion >= 0 || platform.minorVersion == EGL_DONT_CARE)
+            {
+                // Feature Level 10_0 corresponds to shader model 4_0
+                acceptableShaderModels.push_back("ps_4_0");
+            }
+        }
+
+        if (platform.majorVersion == 9 && platform.minorVersion == 3)
+        {
+            acceptableShaderModels.push_back("ps_4_0_level_9_3");
+        }
+
+        bool found = false;
+        for (size_t i = 0; i < acceptableShaderModels.size(); i++)
+        {
+            if (rendererString.find(acceptableShaderModels[i]) != std::string::npos)
+            {
+                found = true;
+            }
+        }
+
+        ASSERT_TRUE(found);
+    }
+
+    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE)
+    {
+        ASSERT_TRUE(IsNULL());
+    }
+
+    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
+    {
+        ASSERT_TRUE(IsVulkan());
+    }
+
+    EGLint glesMajorVersion = GetParam().majorVersion;
+    EGLint glesMinorVersion = GetParam().minorVersion;
+
+    // Ensure that the renderer string contains the requested version number
+    if (glesMajorVersion == 3 && glesMinorVersion == 1)
+    {
+        ASSERT_NE(versionString.find(std::string("es 3.1")), std::string::npos);
+    }
+    else if (glesMajorVersion == 3 && glesMinorVersion == 0)
+    {
+        ASSERT_NE(versionString.find(std::string("es 3.0")), std::string::npos);
+    }
+    else if (glesMajorVersion == 2 && glesMinorVersion == 0)
+    {
+        ASSERT_NE(versionString.find(std::string("es 2.0")), std::string::npos);
+    }
+    else
+    {
+        FAIL() << "Unhandled GL ES client version.";
+    }
+
+    ASSERT_GL_NO_ERROR();
+    ASSERT_EGL_SUCCESS();
+}
+
+// Perform a simple operation (clear and read pixels) to verify the device is working
+TEST_P(RendererTest, SimpleOperation)
+{
+    if (IsNULL())
+    {
+        std::cout << "ANGLE NULL backend clears are not functional" << std::endl;
+        return;
+    }
+
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Select configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+
+ANGLE_INSTANTIATE_TEST(RendererTest,
+                       // ES2 on top of D3D9
+                       ES2_D3D9(),
+                       ES2_D3D9_REFERENCE(),
+
+                       // ES2 on top of D3D11 feature level 9.3 to 11.0
+                       ES2_D3D11(),
+                       ES2_D3D11_FL11_0(),
+                       ES2_D3D11_FL10_1(),
+                       ES2_D3D11_FL10_0(),
+                       ES2_D3D11_FL9_3(),
+
+                       // ES2 on top of D3D11 WARP feature level 9.3 to 11.0
+                       ES2_D3D11_WARP(),
+                       ES2_D3D11_FL11_0_WARP(),
+                       ES2_D3D11_FL10_1_WARP(),
+                       ES2_D3D11_FL10_0_WARP(),
+                       ES2_D3D11_FL9_3_WARP(),
+
+                       // ES2 on top of D3D11 reference feature level 9.3 to 11.0
+                       ES2_D3D11_REFERENCE(),
+                       ES2_D3D11_FL11_0_REFERENCE(),
+                       ES2_D3D11_FL10_1_REFERENCE(),
+                       ES2_D3D11_FL10_0_REFERENCE(),
+                       ES2_D3D11_FL9_3_REFERENCE(),
+
+                       // ES3 on top of D3D11.
+                       ES3_D3D11(),
+                       ES3_D3D11_FL11_0(),
+                       ES3_D3D11_FL10_1(),
+
+                       // ES3 on top of D3D11 WARP.
+                       ES3_D3D11_WARP(),
+                       ES3_D3D11_FL11_0_WARP(),
+                       ES3_D3D11_FL10_1_WARP(),
+
+                       // ES3 on top of the D3D11 reference rasterizer.
+                       ES3_D3D11_REFERENCE(),
+                       ES3_D3D11_FL11_0_REFERENCE(),
+                       ES3_D3D11_FL10_1_REFERENCE(),
+
+                       // ES2 on top of desktop OpenGL versions 2.1 to 4.5
+                       ES2_OPENGL(),
+                       ES2_OPENGL(2, 1),
+                       ES2_OPENGL(3, 0),
+                       ES2_OPENGL(3, 1),
+                       ES2_OPENGL(3, 2),
+                       ES2_OPENGL(3, 3),
+                       ES2_OPENGL(4, 0),
+                       ES2_OPENGL(4, 1),
+                       ES2_OPENGL(4, 2),
+                       ES2_OPENGL(4, 3),
+                       ES2_OPENGL(4, 4),
+                       ES2_OPENGL(4, 5),
+
+                       // ES2 on top of desktop OpenGL versions 3.2 to 4.5
+                       ES3_OPENGL(),
+                       ES3_OPENGL(3, 2),
+                       ES3_OPENGL(3, 3),
+                       ES3_OPENGL(4, 0),
+                       ES3_OPENGL(4, 1),
+                       ES3_OPENGL(4, 2),
+                       ES3_OPENGL(4, 3),
+                       ES3_OPENGL(4, 4),
+                       ES3_OPENGL(4, 5),
+
+                       // ES2 on top of OpenGL ES 2.0 to 3.2
+                       ES2_OPENGLES(),
+                       ES2_OPENGLES(2, 0),
+                       ES2_OPENGLES(3, 0),
+                       ES2_OPENGLES(3, 1),
+                       ES2_OPENGLES(3, 2),
+
+                       // ES2 on top of OpenGL ES 3.0 to 3.2
+                       ES3_OPENGLES(),
+                       ES3_OPENGLES(3, 0),
+                       ES3_OPENGLES(3, 1),
+                       ES3_OPENGLES(3, 2),
+
+                       // All ES version on top of the NULL backend
+                       ES2_NULL(),
+                       ES3_NULL(),
+                       ES31_NULL(),
+
+                       // ES on top of Vulkan
+                       ES2_VULKAN());
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/RobustClientMemoryTest.cpp b/src/third_party/angle/src/tests/gl_tests/RobustClientMemoryTest.cpp
new file mode 100644
index 0000000..61b1bfa
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/RobustClientMemoryTest.cpp
@@ -0,0 +1,411 @@
+//
+// Copyright 2016 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.
+//
+
+// RobustClientMemoryTest.cpp : Tests of the GL_ANGLE_robust_client_memory extension.
+
+#include "test_utils/ANGLETest.h"
+
+#include "test_utils/gl_raii.h"
+
+namespace angle
+{
+
+constexpr GLsizei kWindowSize = 128;
+
+class RobustClientMemoryTest : public ANGLETest
+{
+  protected:
+    RobustClientMemoryTest()
+    {
+        setWindowWidth(kWindowSize);
+        setWindowHeight(kWindowSize);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGetBooleanvRobustANGLE = reinterpret_cast<PFNGLGETBOOLEANVROBUSTANGLE>(
+            eglGetProcAddress("glGetBooleanvRobustANGLE"));
+        glGetBufferParameterivRobustANGLE = reinterpret_cast<PFNGLGETBUFFERPARAMETERIVROBUSTANGLE>(
+            eglGetProcAddress("glGetBufferParameterivRobustANGLE"));
+        glGetFloatvRobustANGLE = reinterpret_cast<PFNGLGETFLOATVROBUSTANGLE>(
+            eglGetProcAddress("glGetFloatvRobustANGLE"));
+        glGetFramebufferAttachmentParameterivRobustANGLE =
+            reinterpret_cast<PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVROBUSTANGLE>(
+                eglGetProcAddress("glGetFramebufferAttachmentParameterivRobustANGLE"));
+        glGetIntegervRobustANGLE = reinterpret_cast<PFNGLGETINTEGERVROBUSTANGLE>(
+            eglGetProcAddress("glGetIntegervRobustANGLE"));
+        glGetProgramivRobustANGLE = reinterpret_cast<PFNGLGETPROGRAMIVROBUSTANGLE>(
+            eglGetProcAddress("glGetProgramivRobustANGLE"));
+        glGetRenderbufferParameterivRobustANGLE =
+            reinterpret_cast<PFNGLGETRENDERBUFFERPARAMETERIVROBUSTANGLE>(
+                eglGetProcAddress("glGetRenderbufferParameterivRobustANGLE"));
+        glGetShaderivRobustANGLE = reinterpret_cast<PFNGLGETSHADERIVROBUSTANGLE>(
+            eglGetProcAddress("glGetShaderivRobustANGLE"));
+        glGetTexParameterfvRobustANGLE = reinterpret_cast<PFNGLGETTEXPARAMETERFVROBUSTANGLE>(
+            eglGetProcAddress("glGetTexParameterfvRobustANGLE"));
+        glGetTexParameterivRobustANGLE = reinterpret_cast<PFNGLGETTEXPARAMETERIVROBUSTANGLE>(
+            eglGetProcAddress("glGetTexParameterivRobustANGLE"));
+        glGetUniformfvRobustANGLE = reinterpret_cast<PFNGLGETUNIFORMFVROBUSTANGLE>(
+            eglGetProcAddress("glGetUniformfvRobustANGLE"));
+        glGetUniformivRobustANGLE = reinterpret_cast<PFNGLGETUNIFORMIVROBUSTANGLE>(
+            eglGetProcAddress("glGetUniformivRobustANGLE"));
+        glGetVertexAttribfvRobustANGLE = reinterpret_cast<PFNGLGETVERTEXATTRIBFVROBUSTANGLE>(
+            eglGetProcAddress("glGetVertexAttribfvRobustANGLE"));
+        glGetVertexAttribivRobustANGLE = reinterpret_cast<PFNGLGETVERTEXATTRIBIVROBUSTANGLE>(
+            eglGetProcAddress("glGetVertexAttribivRobustANGLE"));
+        glGetVertexAttribPointervRobustANGLE =
+            reinterpret_cast<PFNGLGETVERTEXATTRIBPOINTERVROBUSTANGLE>(
+                eglGetProcAddress("glGetVertexAttribPointervRobustANGLE"));
+        glReadPixelsRobustANGLE = reinterpret_cast<PFNGLREADPIXELSROBUSTANGLE>(
+            eglGetProcAddress("glReadPixelsRobustANGLE"));
+        glTexImage2DRobustANGLE = reinterpret_cast<PFNGLTEXIMAGE2DROBUSTANGLE>(
+            eglGetProcAddress("glTexImage2DRobustANGLE"));
+        glTexParameterfvRobustANGLE = reinterpret_cast<PFNGLTEXPARAMETERFVROBUSTANGLE>(
+            eglGetProcAddress("glTexParameterfvRobustANGLE"));
+        glTexParameterivRobustANGLE = reinterpret_cast<PFNGLTEXPARAMETERIVROBUSTANGLE>(
+            eglGetProcAddress("glTexParameterivRobustANGLE"));
+        glTexSubImage2DRobustANGLE = reinterpret_cast<PFNGLTEXSUBIMAGE2DROBUSTANGLE>(
+            eglGetProcAddress("glTexSubImage2DRobustANGLE"));
+        glTexImage3DRobustANGLE = reinterpret_cast<PFNGLTEXIMAGE3DROBUSTANGLE>(
+            eglGetProcAddress("glTexImage3DRobustANGLE"));
+        glTexSubImage3DRobustANGLE = reinterpret_cast<PFNGLTEXSUBIMAGE3DROBUSTANGLE>(
+            eglGetProcAddress("glTexSubImage3DRobustANGLE"));
+        glGetQueryivRobustANGLE = reinterpret_cast<PFNGLGETQUERYIVROBUSTANGLE>(
+            eglGetProcAddress("glGetQueryivRobustANGLE"));
+        glGetQueryObjectuivRobustANGLE = reinterpret_cast<PFNGLGETQUERYOBJECTUIVROBUSTANGLE>(
+            eglGetProcAddress("glGetQueryObjectuivRobustANGLE"));
+        glGetBufferPointervRobustANGLE = reinterpret_cast<PFNGLGETBUFFERPOINTERVROBUSTANGLE>(
+            eglGetProcAddress("glGetBufferPointervRobustANGLE"));
+        glGetIntegeri_vRobustANGLE = reinterpret_cast<PFNGLGETINTEGERI_VROBUSTANGLE>(
+            eglGetProcAddress("glGetIntegeri_vRobustANGLE"));
+        glGetInternalformativRobustANGLE = reinterpret_cast<PFNGETINTERNALFORMATIVROBUSTANGLE>(
+            eglGetProcAddress("glGetInternalformativRobustANGLE"));
+        glGetVertexAttribIivRobustANGLE = reinterpret_cast<PFNGLGETVERTEXATTRIBIIVROBUSTANGLE>(
+            eglGetProcAddress("glGetVertexAttribIivRobustANGLE"));
+        glGetVertexAttribIuivRobustANGLE = reinterpret_cast<PFNGLGETVERTEXATTRIBIUIVROBUSTANGLE>(
+            eglGetProcAddress("glGetVertexAttribIuivRobustANGLE"));
+        glGetUniformuivRobustANGLE = reinterpret_cast<PFNGLGETUNIFORMUIVROBUSTANGLE>(
+            eglGetProcAddress("glGetUniformuivRobustANGLE"));
+        glGetActiveUniformBlockivRobustANGLE =
+            reinterpret_cast<PFNGLGETACTIVEUNIFORMBLOCKIVROBUSTANGLE>(
+                eglGetProcAddress("glGetActiveUniformBlockivRobustANGLE"));
+        glGetInteger64vRobustANGLE = reinterpret_cast<PFNGLGETINTEGER64VROBUSTANGLE>(
+            eglGetProcAddress("glGetInteger64vRobustANGLE"));
+        glGetInteger64i_vRobustANGLE = reinterpret_cast<PFNGLGETINTEGER64I_VROBUSTANGLE>(
+            eglGetProcAddress("glGetInteger64i_vRobustANGLE"));
+        glGetBufferParameteri64vRobustANGLE =
+            reinterpret_cast<PFNGLGETBUFFERPARAMETERI64VROBUSTANGLE>(
+                eglGetProcAddress("glGetBufferParameteri64vRobustANGLE"));
+        glSamplerParameterivRobustANGLE = reinterpret_cast<PFNGLSAMPLERPARAMETERIVROBUSTANGLE>(
+            eglGetProcAddress("glSamplerParameterivRobustANGLE"));
+        glSamplerParameterfvRobustANGLE = reinterpret_cast<PFNGLSAMPLERPARAMETERFVROBUSTANGLE>(
+            eglGetProcAddress("glSamplerParameterfvRobustANGLE"));
+        glGetSamplerParameterivRobustANGLE =
+            reinterpret_cast<PFNGLGETSAMPLERPARAMETERIVROBUSTANGLE>(
+                eglGetProcAddress("glGetSamplerParameterivRobustANGLE"));
+        glGetSamplerParameterfvRobustANGLE =
+            reinterpret_cast<PFNGLGETSAMPLERPARAMETERFVROBUSTANGLE>(
+                eglGetProcAddress("glGetSamplerParameterfvRobustANGLE"));
+        glGetFramebufferParameterivRobustANGLE =
+            reinterpret_cast<PFNGLGETFRAMEBUFFERPARAMETERIVROBUSTANGLE>(
+                eglGetProcAddress("glGetFramebufferParameterivRobustANGLE"));
+        glGetProgramInterfaceivRobustANGLE =
+            reinterpret_cast<PFNGLGETPROGRAMINTERFACEIVROBUSTANGLE>(
+                eglGetProcAddress("glGetProgramInterfaceivRobustANGLE"));
+        glGetBooleani_vRobustANGLE = reinterpret_cast<PFNGLGETBOOLEANI_VROBUSTANGLE>(
+            eglGetProcAddress("glGetBooleani_vRobustANGLE"));
+        glGetMultisamplefvRobustANGLE = reinterpret_cast<PFNGLGETMULTISAMPLEFVROBUSTANGLE>(
+            eglGetProcAddress("glGetMultisamplefvRobustANGLE"));
+        glGetTexLevelParameterivRobustANGLE =
+            reinterpret_cast<PFNGLGETTEXLEVELPARAMETERIVROBUSTANGLE>(
+                eglGetProcAddress("glGetTexLevelParameterivRobustANGLE"));
+        glGetTexLevelParameterfvRobustANGLE =
+            reinterpret_cast<PFNGLGETTEXLEVELPARAMETERFVROBUSTANGLE>(
+                eglGetProcAddress("glGetTexLevelParameterfvRobustANGLE"));
+        glGetPointervRobustANGLERobustANGLE =
+            reinterpret_cast<PFNGLGETPOINTERVROBUSTANGLEROBUSTANGLE>(
+                eglGetProcAddress("glGetPointervRobustANGLERobustANGLE"));
+        glReadnPixelsRobustANGLE = reinterpret_cast<PFNGLREADNPIXELSROBUSTANGLE>(
+            eglGetProcAddress("glReadnPixelsRobustANGLE"));
+        glGetnUniformfvRobustANGLE = reinterpret_cast<PFNGLGETNUNIFORMFVROBUSTANGLE>(
+            eglGetProcAddress("glGetnUniformfvRobustANGLE"));
+        glGetnUniformivRobustANGLE = reinterpret_cast<PFNGLGETNUNIFORMIVROBUSTANGLE>(
+            eglGetProcAddress("glGetnUniformivRobustANGLE"));
+        glGetnUniformuivRobustANGLE = reinterpret_cast<PFNGLGETNUNIFORMUIVROBUSTANGLE>(
+            eglGetProcAddress("glGetnUniformuivRobustANGLE"));
+        glTexParameterIivRobustANGLE = reinterpret_cast<PFNGLTEXPARAMETERIIVROBUSTANGLE>(
+            eglGetProcAddress("glTexParameterIivRobustANGLE"));
+        glTexParameterIuivRobustANGLE = reinterpret_cast<PFNGLTEXPARAMETERIUIVROBUSTANGLE>(
+            eglGetProcAddress("glTexParameterIuivRobustANGLE"));
+        glGetTexParameterIivRobustANGLE = reinterpret_cast<PFNGLGETTEXPARAMETERIIVROBUSTANGLE>(
+            eglGetProcAddress("glGetTexParameterIivRobustANGLE"));
+        glGetTexParameterIuivRobustANGLE = reinterpret_cast<PFNGLGETTEXPARAMETERIUIVROBUSTANGLE>(
+            eglGetProcAddress("glGetTexParameterIuivRobustANGLE"));
+        glSamplerParameterIivRobustANGLE = reinterpret_cast<PFNGLSAMPLERPARAMETERIIVROBUSTANGLE>(
+            eglGetProcAddress("glSamplerParameterIivRobustANGLE"));
+        glSamplerParameterIuivRobustANGLE = reinterpret_cast<PFNGLSAMPLERPARAMETERIUIVROBUSTANGLE>(
+            eglGetProcAddress("glSamplerParameterIuivRobustANGLE"));
+        glGetSamplerParameterIivRobustANGLE =
+            reinterpret_cast<PFNGLGETSAMPLERPARAMETERIIVROBUSTANGLE>(
+                eglGetProcAddress("glGetSamplerParameterIivRobustANGLE"));
+        glGetSamplerParameterIuivRobustANGLE =
+            reinterpret_cast<PFNGLGETSAMPLERPARAMETERIUIVROBUSTANGLE>(
+                eglGetProcAddress("glGetSamplerParameterIuivRobustANGLE"));
+        glGetQueryObjectivRobustANGLE = reinterpret_cast<PFNGLGETQUERYOBJECTIVROBUSTANGLE>(
+            eglGetProcAddress("glGetQueryObjectivRobustANGLE"));
+        glGetQueryObjecti64vRobustANGLE = reinterpret_cast<PFNGLGETQUERYOBJECTI64VROBUSTANGLE>(
+            eglGetProcAddress("glGetQueryObjecti64vRobustANGLE"));
+        glGetQueryObjectui64vRobustANGLE = reinterpret_cast<PFNGLGETQUERYOBJECTUI64VROBUSTANGLE>(
+            eglGetProcAddress("glGetQueryObjectui64vRobustANGLE"));
+    }
+
+    void TearDown() override { ANGLETest::TearDown(); }
+
+    bool extensionsPresent() const
+    {
+        if (!extensionEnabled("GL_ANGLE_robust_client_memory"))
+        {
+            std::cout << "Test skipped because GL_ANGLE_robust_client_memory is not available.";
+            return false;
+        }
+
+        return true;
+    }
+
+    PFNGLGETBOOLEANVROBUSTANGLE glGetBooleanvRobustANGLE                   = nullptr;
+    PFNGLGETBUFFERPARAMETERIVROBUSTANGLE glGetBufferParameterivRobustANGLE = nullptr;
+    PFNGLGETFLOATVROBUSTANGLE glGetFloatvRobustANGLE                       = nullptr;
+    PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVROBUSTANGLE
+    glGetFramebufferAttachmentParameterivRobustANGLE                                   = nullptr;
+    PFNGLGETINTEGERVROBUSTANGLE glGetIntegervRobustANGLE                               = nullptr;
+    PFNGLGETPROGRAMIVROBUSTANGLE glGetProgramivRobustANGLE                             = nullptr;
+    PFNGLGETRENDERBUFFERPARAMETERIVROBUSTANGLE glGetRenderbufferParameterivRobustANGLE = nullptr;
+    PFNGLGETSHADERIVROBUSTANGLE glGetShaderivRobustANGLE                               = nullptr;
+    PFNGLGETTEXPARAMETERFVROBUSTANGLE glGetTexParameterfvRobustANGLE                   = nullptr;
+    PFNGLGETTEXPARAMETERIVROBUSTANGLE glGetTexParameterivRobustANGLE                   = nullptr;
+    PFNGLGETUNIFORMFVROBUSTANGLE glGetUniformfvRobustANGLE                             = nullptr;
+    PFNGLGETUNIFORMIVROBUSTANGLE glGetUniformivRobustANGLE                             = nullptr;
+    PFNGLGETVERTEXATTRIBFVROBUSTANGLE glGetVertexAttribfvRobustANGLE                   = nullptr;
+    PFNGLGETVERTEXATTRIBIVROBUSTANGLE glGetVertexAttribivRobustANGLE                   = nullptr;
+    PFNGLGETVERTEXATTRIBPOINTERVROBUSTANGLE glGetVertexAttribPointervRobustANGLE       = nullptr;
+    PFNGLREADPIXELSROBUSTANGLE glReadPixelsRobustANGLE                                 = nullptr;
+    PFNGLTEXIMAGE2DROBUSTANGLE glTexImage2DRobustANGLE                                 = nullptr;
+    PFNGLTEXPARAMETERFVROBUSTANGLE glTexParameterfvRobustANGLE                         = nullptr;
+    PFNGLTEXPARAMETERIVROBUSTANGLE glTexParameterivRobustANGLE                         = nullptr;
+    PFNGLTEXSUBIMAGE2DROBUSTANGLE glTexSubImage2DRobustANGLE                           = nullptr;
+    PFNGLTEXIMAGE3DROBUSTANGLE glTexImage3DRobustANGLE                                 = nullptr;
+    PFNGLTEXSUBIMAGE3DROBUSTANGLE glTexSubImage3DRobustANGLE                           = nullptr;
+    PFNGLGETQUERYIVROBUSTANGLE glGetQueryivRobustANGLE                                 = nullptr;
+    PFNGLGETQUERYOBJECTUIVROBUSTANGLE glGetQueryObjectuivRobustANGLE                   = nullptr;
+    PFNGLGETBUFFERPOINTERVROBUSTANGLE glGetBufferPointervRobustANGLE                   = nullptr;
+    PFNGLGETINTEGERI_VROBUSTANGLE glGetIntegeri_vRobustANGLE                           = nullptr;
+    PFNGETINTERNALFORMATIVROBUSTANGLE glGetInternalformativRobustANGLE                 = nullptr;
+    PFNGLGETVERTEXATTRIBIIVROBUSTANGLE glGetVertexAttribIivRobustANGLE                 = nullptr;
+    PFNGLGETVERTEXATTRIBIUIVROBUSTANGLE glGetVertexAttribIuivRobustANGLE               = nullptr;
+    PFNGLGETUNIFORMUIVROBUSTANGLE glGetUniformuivRobustANGLE                           = nullptr;
+    PFNGLGETACTIVEUNIFORMBLOCKIVROBUSTANGLE glGetActiveUniformBlockivRobustANGLE       = nullptr;
+    PFNGLGETINTEGER64VROBUSTANGLE glGetInteger64vRobustANGLE                           = nullptr;
+    PFNGLGETINTEGER64I_VROBUSTANGLE glGetInteger64i_vRobustANGLE                       = nullptr;
+    PFNGLGETBUFFERPARAMETERI64VROBUSTANGLE glGetBufferParameteri64vRobustANGLE         = nullptr;
+    PFNGLSAMPLERPARAMETERIVROBUSTANGLE glSamplerParameterivRobustANGLE                 = nullptr;
+    PFNGLSAMPLERPARAMETERFVROBUSTANGLE glSamplerParameterfvRobustANGLE                 = nullptr;
+    PFNGLGETSAMPLERPARAMETERIVROBUSTANGLE glGetSamplerParameterivRobustANGLE           = nullptr;
+    PFNGLGETSAMPLERPARAMETERFVROBUSTANGLE glGetSamplerParameterfvRobustANGLE           = nullptr;
+    PFNGLGETFRAMEBUFFERPARAMETERIVROBUSTANGLE glGetFramebufferParameterivRobustANGLE   = nullptr;
+    PFNGLGETPROGRAMINTERFACEIVROBUSTANGLE glGetProgramInterfaceivRobustANGLE           = nullptr;
+    PFNGLGETBOOLEANI_VROBUSTANGLE glGetBooleani_vRobustANGLE                           = nullptr;
+    PFNGLGETMULTISAMPLEFVROBUSTANGLE glGetMultisamplefvRobustANGLE                     = nullptr;
+    PFNGLGETTEXLEVELPARAMETERIVROBUSTANGLE glGetTexLevelParameterivRobustANGLE         = nullptr;
+    PFNGLGETTEXLEVELPARAMETERFVROBUSTANGLE glGetTexLevelParameterfvRobustANGLE         = nullptr;
+    PFNGLGETPOINTERVROBUSTANGLEROBUSTANGLE glGetPointervRobustANGLERobustANGLE         = nullptr;
+    PFNGLREADNPIXELSROBUSTANGLE glReadnPixelsRobustANGLE                               = nullptr;
+    PFNGLGETNUNIFORMFVROBUSTANGLE glGetnUniformfvRobustANGLE                           = nullptr;
+    PFNGLGETNUNIFORMIVROBUSTANGLE glGetnUniformivRobustANGLE                           = nullptr;
+    PFNGLGETNUNIFORMUIVROBUSTANGLE glGetnUniformuivRobustANGLE                         = nullptr;
+    PFNGLTEXPARAMETERIIVROBUSTANGLE glTexParameterIivRobustANGLE                       = nullptr;
+    PFNGLTEXPARAMETERIUIVROBUSTANGLE glTexParameterIuivRobustANGLE                     = nullptr;
+    PFNGLGETTEXPARAMETERIIVROBUSTANGLE glGetTexParameterIivRobustANGLE                 = nullptr;
+    PFNGLGETTEXPARAMETERIUIVROBUSTANGLE glGetTexParameterIuivRobustANGLE               = nullptr;
+    PFNGLSAMPLERPARAMETERIIVROBUSTANGLE glSamplerParameterIivRobustANGLE               = nullptr;
+    PFNGLSAMPLERPARAMETERIUIVROBUSTANGLE glSamplerParameterIuivRobustANGLE             = nullptr;
+    PFNGLGETSAMPLERPARAMETERIIVROBUSTANGLE glGetSamplerParameterIivRobustANGLE         = nullptr;
+    PFNGLGETSAMPLERPARAMETERIUIVROBUSTANGLE glGetSamplerParameterIuivRobustANGLE       = nullptr;
+    PFNGLGETQUERYOBJECTIVROBUSTANGLE glGetQueryObjectivRobustANGLE                     = nullptr;
+    PFNGLGETQUERYOBJECTI64VROBUSTANGLE glGetQueryObjecti64vRobustANGLE                 = nullptr;
+    PFNGLGETQUERYOBJECTUI64VROBUSTANGLE glGetQueryObjectui64vRobustANGLE               = nullptr;
+};
+
+// Test basic usage and validation of glGetIntegervRobustANGLE
+TEST_P(RobustClientMemoryTest, GetInteger)
+{
+    if (!extensionsPresent())
+    {
+        return;
+    }
+
+    // Verify that the robust and regular entry points return the same values
+    GLint resultRobust;
+    GLsizei length;
+    glGetIntegervRobustANGLE(GL_MAX_VERTEX_ATTRIBS, 1, &length, &resultRobust);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(1, length);
+
+    GLint resultRegular;
+    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &resultRegular);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(resultRegular, resultRobust);
+
+    // Query a dynamic value
+    GLint numCompressedFormats;
+    glGetIntegervRobustANGLE(GL_NUM_COMPRESSED_TEXTURE_FORMATS, 1, &length, &numCompressedFormats);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, length);
+
+    if (numCompressedFormats > 0)
+    {
+        std::vector<GLint> resultBuf(numCompressedFormats * 2, 0);
+
+        // Test when the bufSize is too low
+        glGetIntegervRobustANGLE(GL_COMPRESSED_TEXTURE_FORMATS, numCompressedFormats - 1, &length,
+                                 resultBuf.data());
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+        EXPECT_TRUE(std::all_of(resultBuf.begin(), resultBuf.end(),
+                                [](GLint value) { return value == 0; }));
+
+        // Make sure the GL doesn't touch the end of the buffer
+        glGetIntegervRobustANGLE(GL_COMPRESSED_TEXTURE_FORMATS,
+                                 static_cast<GLsizei>(resultBuf.size()), &length, resultBuf.data());
+        EXPECT_GL_NO_ERROR();
+        EXPECT_EQ(numCompressedFormats, length);
+        EXPECT_TRUE(std::none_of(resultBuf.begin(), resultBuf.begin() + length,
+                                 [](GLint value) { return value == 0; }));
+        EXPECT_TRUE(std::all_of(resultBuf.begin() + length, resultBuf.end(),
+                                [](GLint value) { return value == 0; }));
+    }
+
+    // Test with null length
+    glGetIntegervRobustANGLE(GL_MAX_VARYING_VECTORS, 1, nullptr, &resultRobust);
+    EXPECT_GL_NO_ERROR();
+
+    glGetIntegervRobustANGLE(GL_MAX_VIEWPORT_DIMS, 1, nullptr, &resultRobust);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    GLint maxViewportDims[2];
+    glGetIntegervRobustANGLE(GL_MAX_VIEWPORT_DIMS, 2, nullptr, maxViewportDims);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test basic usage and validation of glTexImage2DRobustANGLE
+TEST_P(RobustClientMemoryTest, TexImage2D)
+{
+    if (!extensionsPresent())
+    {
+        return;
+    }
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+
+    GLsizei dataDimension = 1024;
+    std::vector<GLubyte> rgbaData(dataDimension * dataDimension * 4);
+
+    // Test the regular case
+    glTexImage2DRobustANGLE(GL_TEXTURE_2D, 0, GL_RGBA, dataDimension, dataDimension, 0, GL_RGBA,
+                            GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()),
+                            rgbaData.data());
+    EXPECT_GL_NO_ERROR();
+
+    // Test with a data size that is too small
+    glTexImage2DRobustANGLE(GL_TEXTURE_2D, 0, GL_RGBA, dataDimension, dataDimension, 0, GL_RGBA,
+                            GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()) / 2,
+                            rgbaData.data());
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    if (getClientMajorVersion() >= 3)
+    {
+        // Set an unpack parameter that would cause the driver to read past the end of the buffer
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, dataDimension + 1);
+        glTexImage2DRobustANGLE(GL_TEXTURE_2D, 0, GL_RGBA, dataDimension, dataDimension, 0, GL_RGBA,
+                                GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()),
+                                rgbaData.data());
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+}
+
+// Test basic usage and validation of glReadPixelsRobustANGLE
+TEST_P(RobustClientMemoryTest, ReadPixels)
+{
+    if (!extensionsPresent())
+    {
+        return;
+    }
+
+    // TODO(ynovikov): Looks like a driver bug on Intel HD 530 http://anglebug.com/1877
+    if (IsLinux() && IsIntel() && IsDesktopOpenGL())
+    {
+        std::cout << "Test skipped on Intel OpenGL on Linux." << std::endl;
+        return;
+    }
+
+    GLsizei dataDimension = 16;
+    std::vector<GLubyte> rgbaData(dataDimension * dataDimension * 4);
+
+    // Test the regular case
+    GLsizei length = 0;
+    GLsizei width  = 0;
+    GLsizei height = 0;
+    glReadPixelsRobustANGLE(0, 0, dataDimension, dataDimension, GL_RGBA, GL_UNSIGNED_BYTE,
+                            static_cast<GLsizei>(rgbaData.size()), &length, &width, &height,
+                            rgbaData.data());
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(static_cast<GLsizei>(rgbaData.size()), length);
+    EXPECT_EQ(dataDimension, width);
+    EXPECT_EQ(dataDimension, height);
+
+    // Test a case that would be partially clipped
+    glReadPixelsRobustANGLE(-1, kWindowSize - dataDimension + 3, dataDimension, dataDimension,
+                            GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()),
+                            &length, &width, &height, rgbaData.data());
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(static_cast<GLsizei>(rgbaData.size()), length);
+    EXPECT_EQ(dataDimension - 1, width);
+    EXPECT_EQ(dataDimension - 3, height);
+
+    // Test with a data size that is too small
+    glReadPixelsRobustANGLE(0, 0, dataDimension, dataDimension, GL_RGBA, GL_UNSIGNED_BYTE,
+                            static_cast<GLsizei>(rgbaData.size()) - 1, &length, nullptr, nullptr,
+                            rgbaData.data());
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    if (getClientMajorVersion() >= 3)
+    {
+        // Set a pack parameter that would cause the driver to write past the end of the buffer
+        glPixelStorei(GL_PACK_ROW_LENGTH, dataDimension + 1);
+        glReadPixelsRobustANGLE(0, 0, dataDimension, dataDimension, GL_RGBA, GL_UNSIGNED_BYTE,
+                                static_cast<GLsizei>(rgbaData.size()), &length, nullptr, nullptr,
+                                rgbaData.data());
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(RobustClientMemoryTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/RobustResourceInitTest.cpp b/src/third_party/angle/src/tests/gl_tests/RobustResourceInitTest.cpp
new file mode 100644
index 0000000..e38ce7b
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/RobustResourceInitTest.cpp
@@ -0,0 +1,190 @@
+//
+// Copyright 2017 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.
+//
+// RobustResourceInitTest: Tests for GL_ANGLE_robust_resource_initialization.
+
+#include "test_utils/ANGLETest.h"
+
+#include "test_utils/gl_raii.h"
+
+namespace angle
+{
+
+class RobustResourceInitTest : public ANGLETest
+{
+  protected:
+    RobustResourceInitTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+
+        // Defer context init until the test body.
+        setDeferContextInit(true);
+        setRobustResourceInit(true);
+    }
+
+    bool hasEGLExtension()
+    {
+        EGLDisplay display = getEGLWindow()->getDisplay();
+        ASSERT(display != EGL_NO_DISPLAY);
+
+        return (eglDisplayExtensionEnabled(
+            display, "EGL_ANGLE_create_context_robust_resource_initialization"));
+    }
+
+    bool setup()
+    {
+        if (!hasEGLExtension())
+        {
+            return false;
+        }
+
+        if (!getEGLWindow()->initializeContext())
+        {
+            EXPECT_TRUE(false);
+            return false;
+        }
+
+        return true;
+    }
+};
+
+// Context creation should fail if EGL_ANGLE_create_context_robust_resource_initialization
+// is not available, and succeed otherwise.
+TEST_P(RobustResourceInitTest, ExtensionInit)
+{
+    if (hasEGLExtension())
+    {
+        // Context creation shold succeed with robust resource init enabled.
+        EXPECT_TRUE(getEGLWindow()->initializeContext());
+
+        // Robust resource init extension should be available.
+        EXPECT_TRUE(extensionEnabled("GL_ANGLE_robust_resource_initialization"));
+
+        // Querying the state value should return true.
+        GLboolean enabled = 0;
+        glGetBooleanv(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_GL_TRUE(enabled);
+
+        EXPECT_GL_TRUE(glIsEnabled(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE));
+    }
+    else
+    {
+        // Context creation should fail with robust resource init enabled.
+        EXPECT_FALSE(getEGLWindow()->initializeContext());
+
+        // Context creation should succeed with robust resource init disabled.
+        setRobustResourceInit(false);
+        ASSERT_TRUE(getEGLWindow()->initializeGL(GetOSWindow()));
+
+        // If context extension string exposed, check queries.
+        if (extensionEnabled("GL_ANGLE_robust_resource_initialization"))
+        {
+            GLboolean enabled = 0;
+            glGetBooleanv(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
+            EXPECT_GL_FALSE(enabled);
+
+            EXPECT_GL_FALSE(glIsEnabled(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE));
+            EXPECT_GL_NO_ERROR();
+        }
+        else
+        {
+            // Querying robust resource init should return INVALID_ENUM.
+            GLboolean enabled = 0;
+            glGetBooleanv(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
+            EXPECT_GL_ERROR(GL_INVALID_ENUM);
+        }
+    }
+}
+
+// Test queries on a normal, non-robust enabled context.
+TEST_P(RobustResourceInitTest, QueriesOnNonRobustContext)
+{
+    EGLDisplay display = getEGLWindow()->getDisplay();
+    ASSERT_TRUE(display != EGL_NO_DISPLAY);
+
+    if (!hasEGLExtension())
+    {
+        return;
+    }
+
+    setRobustResourceInit(false);
+    EXPECT_TRUE(getEGLWindow()->initializeContext());
+
+    // If context extension string exposed, check queries.
+    ASSERT_TRUE(extensionEnabled("GL_ANGLE_robust_resource_initialization"));
+
+    // Querying robust resource init should return INVALID_ENUM.
+    GLboolean enabled = 0;
+    glGetBooleanv(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
+    EXPECT_GL_FALSE(enabled);
+
+    EXPECT_GL_FALSE(glIsEnabled(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE));
+    EXPECT_GL_NO_ERROR();
+}
+
+// Tests that buffers start zero-filled if the data pointer is null.
+TEST_P(RobustResourceInitTest, BufferData)
+{
+    if (!setup())
+    {
+        return;
+    }
+
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer);
+    glBufferData(GL_ARRAY_BUFFER, getWindowWidth() * getWindowHeight() * sizeof(GLfloat), nullptr,
+                 GL_STATIC_DRAW);
+
+    const std::string &vertexShader =
+        "attribute vec2 position;\n"
+        "attribute float testValue;\n"
+        "varying vec4 colorOut;\n"
+        "void main() {\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "    colorOut = testValue == 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
+        "}";
+    const std::string &fragmentShader =
+        "varying mediump vec4 colorOut;\n"
+        "void main() {\n"
+        "    gl_FragColor = colorOut;\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+
+    GLint testValueLoc = glGetAttribLocation(program.get(), "testValue");
+    ASSERT_NE(-1, testValueLoc);
+
+    glBindBuffer(GL_ARRAY_BUFFER, buffer);
+    glVertexAttribPointer(testValueLoc, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
+    glEnableVertexAttribArray(testValueLoc);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+    drawQuad(program.get(), "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+
+    std::vector<GLColor> expected(getWindowWidth() * getWindowHeight(), GLColor::green);
+    std::vector<GLColor> actual(getWindowWidth() * getWindowHeight());
+    glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
+                 actual.data());
+    EXPECT_EQ(expected, actual);
+}
+
+ANGLE_INSTANTIATE_TEST(RobustResourceInitTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/SRGBFramebufferTest.cpp b/src/third_party/angle/src/tests/gl_tests/SRGBFramebufferTest.cpp
new file mode 100644
index 0000000..47ff2f3
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/SRGBFramebufferTest.cpp
@@ -0,0 +1,141 @@
+//
+// Copyright 2016 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.
+//
+
+// SRGBFramebufferTest.cpp: Tests of sRGB framebuffer functionality.
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+namespace angle
+{
+
+class SRGBFramebufferTest : public ANGLETest
+{
+  protected:
+    SRGBFramebufferTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vs =
+            "precision highp float;\n"
+            "attribute vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "   gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "}\n";
+
+        const std::string fs =
+            "precision highp float;\n"
+            "uniform vec4 color;\n"
+            "void main()\n"
+            "{\n"
+            "   gl_FragColor = color;\n"
+            "}\n";
+
+        mProgram = CompileProgram(vs, fs);
+        ASSERT_NE(0u, mProgram);
+
+        mColorLocation = glGetUniformLocation(mProgram, "color");
+        ASSERT_NE(-1, mColorLocation);
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram      = 0;
+    GLint mColorLocation = -1;
+};
+
+// Test basic validation of GL_EXT_sRGB_write_control
+TEST_P(SRGBFramebufferTest, Validation)
+{
+    GLenum expectedError =
+        extensionEnabled("GL_EXT_sRGB_write_control") ? GL_NO_ERROR : GL_INVALID_ENUM;
+
+    GLboolean value = GL_FALSE;
+    glEnable(GL_FRAMEBUFFER_SRGB_EXT);
+    EXPECT_GL_ERROR(expectedError);
+
+    glGetBooleanv(GL_FRAMEBUFFER_SRGB_EXT, &value);
+    EXPECT_GL_ERROR(expectedError);
+    if (expectedError == GL_NO_ERROR)
+    {
+        EXPECT_EQ(GL_TRUE, value);
+    }
+
+    glDisable(GL_FRAMEBUFFER_SRGB_EXT);
+    EXPECT_GL_ERROR(expectedError);
+
+    glGetBooleanv(GL_FRAMEBUFFER_SRGB_EXT, &value);
+    EXPECT_GL_ERROR(expectedError);
+    if (expectedError == GL_NO_ERROR)
+    {
+        EXPECT_EQ(GL_FALSE, value);
+    }
+}
+
+// Test basic functionality of GL_EXT_sRGB_write_control
+TEST_P(SRGBFramebufferTest, BasicUsage)
+{
+    if (!extensionEnabled("GL_EXT_sRGB_write_control") ||
+        (!extensionEnabled("GL_EXT_sRGB") && getClientMajorVersion() < 3))
+    {
+        std::cout
+            << "Test skipped because GL_EXT_sRGB_write_control and GL_EXT_sRGB are not available."
+            << std::endl;
+        return;
+    }
+
+    GLColor linearColor(64, 127, 191, 255);
+    GLColor srgbColor(13, 54, 133, 255);
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
+                 nullptr);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
+
+    glUseProgram(mProgram);
+    glUniform4fv(mColorLocation, 1, srgbColor.toNormalizedVector().data());
+
+    glEnable(GL_FRAMEBUFFER_SRGB_EXT);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
+
+    glDisable(GL_FRAMEBUFFER_SRGB_EXT);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(SRGBFramebufferTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/gl_tests/SRGBTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/SRGBTextureTest.cpp
new file mode 100644
index 0000000..cbdc492
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/SRGBTextureTest.cpp
@@ -0,0 +1,343 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+namespace angle
+{
+
+class SRGBTextureTest : public ANGLETest
+{
+  protected:
+    SRGBTextureTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vs =
+            "precision highp float;\n"
+            "attribute vec4 position;\n"
+            "varying vec2 texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "   gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "   texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n";
+
+        const std::string fs =
+            "precision highp float;\n"
+            "uniform sampler2D tex;\n"
+            "varying vec2 texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "   gl_FragColor = texture2D(tex, texcoord);\n"
+            "}\n";
+
+        mProgram = CompileProgram(vs, fs);
+        ASSERT_NE(0u, mProgram);
+
+        mTextureLocation = glGetUniformLocation(mProgram, "tex");
+        ASSERT_NE(-1, mTextureLocation);
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram        = 0;
+    GLint mTextureLocation = -1;
+};
+
+TEST_P(SRGBTextureTest, SRGBValidation)
+{
+    bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
+
+    GLuint tex = 0;
+    glGenTextures(1, &tex);
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    GLubyte pixel[3] = { 0 };
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, 1, 1, 0, GL_SRGB, GL_UNSIGNED_BYTE, pixel);
+    if (supported)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_SRGB, GL_UNSIGNED_BYTE, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glGenerateMipmap(GL_TEXTURE_2D);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+
+    glDeleteTextures(1, &tex);
+}
+
+TEST_P(SRGBTextureTest, SRGBAValidation)
+{
+    bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
+
+    GLuint tex = 0;
+    glGenTextures(1, &tex);
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    GLubyte pixel[4] = { 0 };
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel);
+    if (supported)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel);
+        EXPECT_GL_NO_ERROR();
+
+        glGenerateMipmap(GL_TEXTURE_2D);
+        if (getClientMajorVersion() == 2)
+        {
+            EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+        }
+        else
+        {
+            EXPECT_GL_NO_ERROR();
+        }
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+
+    glDeleteTextures(1, &tex);
+}
+
+TEST_P(SRGBTextureTest, SRGBARenderbuffer)
+{
+    bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
+
+    GLuint rbo = 0;
+    glGenRenderbuffers(1, &rbo);
+    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8_EXT, 1, 1);
+    if (supported)
+    {
+        EXPECT_GL_NO_ERROR();
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+        // Make sure the rbo has a size for future tests
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    GLuint fbo = 0;
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
+    EXPECT_GL_NO_ERROR();
+
+    GLint colorEncoding = 0;
+    glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                          GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT, &colorEncoding);
+    if (supported)
+    {
+        EXPECT_GL_NO_ERROR();
+        EXPECT_EQ(GL_SRGB_EXT, colorEncoding);
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+
+    glDeleteFramebuffers(1, &fbo);
+    glDeleteRenderbuffers(1, &rbo);
+}
+
+// Verify that if the srgb decode extension is available, srgb textures are too
+TEST_P(SRGBTextureTest, SRGBDecodeExtensionAvailability)
+{
+    bool hasSRGBDecode = extensionEnabled("GL_EXT_texture_sRGB_decode");
+    if (hasSRGBDecode)
+    {
+        bool hasSRGBTextures = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() >= 3;
+        EXPECT_TRUE(hasSRGBTextures);
+    }
+}
+
+// Test basic functionality of SRGB decode using the texture parameter
+TEST_P(SRGBTextureTest, SRGBDecodeTextureParameter)
+{
+    // TODO(fjhenigman): Figure out why this fails on Ozone Intel.
+    if (IsOzone() && IsIntel() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Ozone Intel." << std::endl;
+        return;
+    }
+
+    if (!extensionEnabled("GL_EXT_texture_sRGB_decode"))
+    {
+        std::cout << "Test skipped because GL_EXT_texture_sRGB_decode is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLColor linearColor(64, 127, 191, 255);
+    GLColor srgbColor(13, 54, 133, 255);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
+                 &linearColor);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(mProgram);
+    glUniform1i(mTextureLocation, 0);
+
+    glDisable(GL_DEPTH_TEST);
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
+}
+
+// Test basic functionality of SRGB decode using the sampler parameter
+TEST_P(SRGBTextureTest, SRGBDecodeSamplerParameter)
+{
+    if (!extensionEnabled("GL_EXT_texture_sRGB_decode") || getClientMajorVersion() < 3)
+    {
+        std::cout << "Test skipped because GL_EXT_texture_sRGB_decode or ES3 is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLColor linearColor(64, 127, 191, 255);
+    GLColor srgbColor(13, 54, 133, 255);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
+                 &linearColor);
+    ASSERT_GL_NO_ERROR();
+
+    GLSampler sampler;
+    glBindSampler(0, sampler.get());
+    glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
+
+    glUseProgram(mProgram);
+    glUniform1i(mTextureLocation, 0);
+
+    glDisable(GL_DEPTH_TEST);
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
+
+    glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
+}
+
+// Test that mipmaps are generated correctly for sRGB textures
+TEST_P(SRGBTextureTest, GenerateMipmaps)
+{
+    if (getClientMajorVersion() < 3)
+    {
+        std::cout << "Test skipped because ES3 is not available." << std::endl;
+        return;
+    }
+
+    if (IsOpenGL() && (IsIntel() || IsAMD()))
+    {
+        std::cout << "Test skipped on Intel and AMD OpenGL drivers." << std::endl;
+        return;
+    }
+
+    auto createAndReadBackTexture = [this](GLenum internalFormat, const GLColor &color) {
+        constexpr GLsizei width  = 128;
+        constexpr GLsizei height = 128;
+
+        std::array<GLColor, width * height> buf;
+        std::fill(buf.begin(), buf.end(), color);
+
+        // Set up-left region of the texture as red color.
+        // In order to make sure bi-linear interpolation operates on different colors, red region
+        // is 1 pixel smaller than a quarter of the full texture on each side.
+        constexpr GLsizei redWidth  = width / 2 - 1;
+        constexpr GLsizei redHeight = height / 2 - 1;
+        std::array<GLColor, redWidth * redHeight> redBuf;
+        std::fill(redBuf.begin(), redBuf.end(), GLColor::red);
+
+        GLTexture tex;
+        glBindTexture(GL_TEXTURE_2D, tex.get());
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     buf.data());
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, redWidth, redHeight, GL_RGBA, GL_UNSIGNED_BYTE,
+                        redBuf.data());
+        glGenerateMipmap(GL_TEXTURE_2D);
+
+        constexpr GLsizei drawWidth  = 32;
+        constexpr GLsizei drawHeight = 32;
+        glViewport(0, 0, drawWidth, drawHeight);
+
+        drawQuad(mProgram, "position", 0.5f);
+
+        std::array<GLColor, drawWidth * drawHeight> result;
+        glReadPixels(0, 0, drawWidth, drawHeight, GL_RGBA, GL_UNSIGNED_BYTE, result.data());
+
+        EXPECT_GL_NO_ERROR();
+
+        return result;
+    };
+
+    GLColor srgbaColor(0, 63, 127, 255);
+    auto srgbaReadback = createAndReadBackTexture(GL_SRGB8_ALPHA8, srgbaColor);
+
+    GLColor linearColor(0, 13, 54, 255);
+    auto rgbaReadback = createAndReadBackTexture(GL_RGBA8, linearColor);
+
+    ASSERT_EQ(srgbaReadback.size(), rgbaReadback.size());
+    for (size_t i = 0; i < srgbaReadback.size(); i++)
+    {
+        constexpr double tolerence = 7.0;
+        EXPECT_COLOR_NEAR(srgbaReadback[i], rgbaReadback[i], tolerence);
+    }
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(SRGBTextureTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/SimpleOperationTest.cpp b/src/third_party/angle/src/tests/gl_tests/SimpleOperationTest.cpp
new file mode 100644
index 0000000..a22b8e1
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/SimpleOperationTest.cpp
@@ -0,0 +1,300 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SimpleOperationTest:
+//   Basic GL commands such as linking a program, initializing a buffer, etc.
+
+#include "test_utils/ANGLETest.h"
+
+#include <vector>
+
+#include "random_utils.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+class SimpleOperationTest : public ANGLETest
+{
+  protected:
+    SimpleOperationTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void verifyBuffer(const std::vector<uint8_t> &data, GLenum binding);
+};
+
+void SimpleOperationTest::verifyBuffer(const std::vector<uint8_t> &data, GLenum binding)
+{
+    if (!extensionEnabled("GL_EXT_map_buffer_range"))
+    {
+        return;
+    }
+
+    uint8_t *mapPointer =
+        static_cast<uint8_t *>(glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, 1024, GL_MAP_READ_BIT));
+    ASSERT_GL_NO_ERROR();
+
+    std::vector<uint8_t> readbackData(data.size());
+    memcpy(readbackData.data(), mapPointer, data.size());
+    glUnmapBufferOES(GL_ARRAY_BUFFER);
+
+    EXPECT_EQ(data, readbackData);
+}
+
+TEST_P(SimpleOperationTest, CompileVertexShader)
+{
+    const std::string source = SHADER_SOURCE
+    (
+        attribute vec4 a_input;
+        void main()
+        {
+            gl_Position = a_input;
+        }
+    );
+
+    GLuint shader = CompileShader(GL_VERTEX_SHADER, source);
+    EXPECT_NE(shader, 0u);
+    glDeleteShader(shader);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(SimpleOperationTest, CompileFragmentShader)
+{
+    const std::string source = SHADER_SOURCE
+    (
+        precision mediump float;
+        varying vec4 v_input;
+        void main()
+        {
+            gl_FragColor = v_input;
+        }
+    );
+
+    GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
+    EXPECT_NE(shader, 0u);
+    glDeleteShader(shader);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(SimpleOperationTest, LinkProgram)
+{
+    const std::string vsSource = SHADER_SOURCE
+    (
+        void main()
+        {
+            gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
+        }
+    );
+
+    const std::string fsSource = SHADER_SOURCE
+    (
+        void main()
+        {
+            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
+        }
+    );
+
+    GLuint program = CompileProgram(vsSource, fsSource);
+    EXPECT_NE(program, 0u);
+    glDeleteProgram(program);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(SimpleOperationTest, LinkProgramWithUniforms)
+{
+    if (IsVulkan())
+    {
+        // TODO(jmadill): Complete Vulkan implementation.
+        std::cout << "Test skipped on Vulkan." << std::endl;
+        return;
+    }
+
+    const std::string vsSource = SHADER_SOURCE
+    (
+        void main()
+        {
+            gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
+        }
+    );
+
+    const std::string fsSource = SHADER_SOURCE
+    (
+        precision mediump float;
+        uniform vec4 u_input;
+        void main()
+        {
+            gl_FragColor = u_input;
+        }
+    );
+
+    GLuint program = CompileProgram(vsSource, fsSource);
+    EXPECT_NE(program, 0u);
+
+    GLint uniformLoc = glGetUniformLocation(program, "u_input");
+    EXPECT_NE(-1, uniformLoc);
+
+    glDeleteProgram(program);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(SimpleOperationTest, LinkProgramWithAttributes)
+{
+    if (IsVulkan())
+    {
+        // TODO(jmadill): Complete Vulkan implementation.
+        std::cout << "Test skipped on Vulkan." << std::endl;
+        return;
+    }
+
+    const std::string vsSource = SHADER_SOURCE
+    (
+        attribute vec4 a_input;
+        void main()
+        {
+            gl_Position = a_input;
+        }
+    );
+
+    const std::string fsSource = SHADER_SOURCE
+    (
+        void main()
+        {
+            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
+        }
+    );
+
+    GLuint program = CompileProgram(vsSource, fsSource);
+    EXPECT_NE(program, 0u);
+
+    GLint attribLoc = glGetAttribLocation(program, "a_input");
+    EXPECT_NE(-1, attribLoc);
+
+    glDeleteProgram(program);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(SimpleOperationTest, BufferDataWithData)
+{
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
+
+    std::vector<uint8_t> data(1024);
+    FillVectorWithRandomUBytes(&data);
+    glBufferData(GL_ARRAY_BUFFER, data.size(), &data[0], GL_STATIC_DRAW);
+
+    verifyBuffer(data, GL_ARRAY_BUFFER);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(SimpleOperationTest, BufferDataWithNoData)
+{
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
+    glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+TEST_P(SimpleOperationTest, BufferSubData)
+{
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
+
+    constexpr size_t bufferSize = 1024;
+    std::vector<uint8_t> data(bufferSize);
+    FillVectorWithRandomUBytes(&data);
+
+    glBufferData(GL_ARRAY_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
+
+    constexpr size_t subDataCount = 16;
+    constexpr size_t sliceSize    = bufferSize / subDataCount;
+    for (size_t i = 0; i < subDataCount; i++)
+    {
+        size_t offset = i * sliceSize;
+        glBufferSubData(GL_ARRAY_BUFFER, offset, sliceSize, &data[offset]);
+    }
+
+    verifyBuffer(data, GL_ARRAY_BUFFER);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Simple quad test.
+TEST_P(SimpleOperationTest, DrawQuad)
+{
+    const std::string &vertexShader =
+        "attribute vec3 position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(position, 1);\n"
+        "}";
+    const std::string &fragmentShader =
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(0, 1, 0, 1);\n"
+        "}";
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+
+    drawQuad(program.get(), "position", 0.5f, 1.0f, true);
+
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Simple repeatd draw and swap test.
+TEST_P(SimpleOperationTest, DrawQuadAndSwap)
+{
+    const std::string &vertexShader =
+        "attribute vec3 position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(position, 1);\n"
+        "}";
+    const std::string &fragmentShader =
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(0, 1, 0, 1);\n"
+        "}";
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+
+    for (int i = 0; i < 8; ++i)
+    {
+        drawQuad(program.get(), "position", 0.5f, 1.0f, true);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+        swapBuffers();
+    }
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(SimpleOperationTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES(),
+                       ES2_VULKAN());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/SixteenBppTextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/SixteenBppTextureTest.cpp
new file mode 100644
index 0000000..ca5274f
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/SixteenBppTextureTest.cpp
@@ -0,0 +1,551 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SixteenBppTextureTest:
+//   Basic tests using 16bpp texture formats (e.g. GL_RGB565).
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include "image_util/imageformats.h"
+
+using namespace angle;
+
+namespace
+{
+
+GLColor Convert565(const R5G6B5 &rgb565)
+{
+    gl::ColorF colorf;
+    R5G6B5::readColor(&colorf, &rgb565);
+    Vector4 vecColor(colorf.red, colorf.green, colorf.blue, colorf.alpha);
+    return GLColor(vecColor);
+}
+
+R5G6B5 Convert565(const GLColor &glColor)
+{
+    const Vector4 &vecColor = glColor.toNormalizedVector();
+    gl::ColorF colorf(vecColor.x(), vecColor.y(), vecColor.z(), vecColor.w());
+    R5G6B5 rgb565;
+    R5G6B5::writeColor(&rgb565, &colorf);
+    return rgb565;
+}
+
+class SixteenBppTextureTest : public ANGLETest
+{
+  protected:
+    SixteenBppTextureTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = vec4(position.xy, 0.0, 1.0);
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        );
+
+        const std::string fragmentShaderSource2D = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        m2DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource2D);
+        mTexture2DUniformLocation = glGetUniformLocation(m2DProgram, "tex");
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(m2DProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    void simpleValidationBase(GLuint tex)
+    {
+        // Draw a quad using the texture
+        glClear(GL_COLOR_BUFFER_BIT);
+        glUseProgram(m2DProgram);
+        glUniform1i(mTexture2DUniformLocation, 0);
+        drawQuad(m2DProgram, "position", 0.5f);
+        ASSERT_GL_NO_ERROR();
+
+        int w = getWindowWidth() - 1;
+        int h = getWindowHeight() - 1;
+
+        // Check that it drew as expected
+        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+        EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
+        EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
+        EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
+
+        // Generate mipmaps
+        glGenerateMipmap(GL_TEXTURE_2D);
+
+        // Draw a quad using the texture
+        glClear(GL_COLOR_BUFFER_BIT);
+        glUseProgram(m2DProgram);
+        glUniform1i(mTexture2DUniformLocation, 0);
+        drawQuad(m2DProgram, "position", 0.5f);
+        ASSERT_GL_NO_ERROR();
+
+        // Check that it drew as expected
+        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+        EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
+        EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
+        EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
+
+        // Bind the texture as a framebuffer, render to it, then check the results
+        GLFramebuffer fbo;
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+        glBindTexture(GL_TEXTURE_2D, 0);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+
+        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_UNSUPPORTED)
+        {
+            glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+            glClear(GL_COLOR_BUFFER_BIT);
+            EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+            EXPECT_PIXEL_EQ(1, 0, 255, 0, 0, 255);
+            EXPECT_PIXEL_EQ(1, 1, 255, 0, 0, 255);
+            EXPECT_PIXEL_EQ(0, 1, 255, 0, 0, 255);
+        }
+        else
+        {
+            std::cout << "Skipping rendering to an unsupported framebuffer format" << std::endl;
+        }
+    }
+
+    GLuint m2DProgram;
+    GLint mTexture2DUniformLocation;
+};
+
+class SixteenBppTextureTestES3 : public SixteenBppTextureTest
+{
+};
+
+// Simple validation test for GL_RGB565 textures.
+// Samples from the texture, renders to it, generates mipmaps etc.
+TEST_P(SixteenBppTextureTest, RGB565Validation)
+{
+    // These tests fail on certain Intel machines running an un-updated version of Win7
+    // The tests pass after installing the latest updates from Windows Update.
+    // TODO: reenable these tests once the bots have been updated
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D11." << std::endl;
+        return;
+    }
+
+    GLuint test;
+    memcpy(&test, &GLColor::black, 4);
+
+    R5G6B5 pixels[4] = {Convert565(GLColor::red), Convert565(GLColor::green),
+                        Convert565(GLColor::blue), Convert565(GLColor::yellow)};
+
+    glClearColor(0, 0, 0, 0);
+
+    // Create a simple RGB565 texture
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    // Supply the data to it
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+    EXPECT_GL_NO_ERROR();
+
+    simpleValidationBase(tex.get());
+}
+
+// Simple validation test for GL_RGBA5551 textures.
+// Samples from the texture, renders to it, generates mipmaps etc.
+TEST_P(SixteenBppTextureTest, RGBA5551Validation)
+{
+    // These tests fail on certain Intel machines running an un-updated version of Win7
+    // The tests pass after installing the latest updates from Windows Update.
+    // TODO: reenable these tests once the bots have been updated
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D11." << std::endl;
+        return;
+    }
+
+    GLushort pixels[4] =
+    {
+        0xF801, // Red
+        0x07C1, // Green
+        0x003F, // Blue
+        0xFFC1  // Red + Green
+    };
+
+    // Create a simple 5551 texture
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixels);
+    EXPECT_GL_NO_ERROR();
+
+    simpleValidationBase(tex.get());
+}
+
+// Test to ensure calling Clear() on an RGBA5551 texture does something reasonable
+// Based on WebGL test conformance/textures/texture-attachment-formats.html
+TEST_P(SixteenBppTextureTest, RGBA5551ClearAlpha)
+{
+    // These tests fail on certain Intel machines running an un-updated version of Win7
+    // The tests pass after installing the latest updates from Windows Update.
+    // TODO: reenable these tests once the bots have been updated
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D11." << std::endl;
+        return;
+    }
+
+    GLTexture tex;
+    GLFramebuffer fbo;
+
+    // Create a simple 5551 texture
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    // Bind the texture as a framebuffer, clear it, then check the results
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.get(), 0);
+
+    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_UNSUPPORTED)
+    {
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
+
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+        EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 255);
+    }
+    else
+    {
+        std::cout << "Skipping rendering to an unsupported framebuffer format" << std::endl;
+    }
+}
+
+// Simple validation test for GL_RGBA4444 textures.
+// Samples from the texture, renders to it, generates mipmaps etc.
+TEST_P(SixteenBppTextureTest, RGBA4444Validation)
+{
+    // These tests fail on certain Intel machines running an un-updated version of Win7
+    // The tests pass after installing the latest updates from Windows Update.
+    // TODO: reenable these tests once the bots have been updated
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel D3D11." << std::endl;
+        return;
+    }
+
+    GLushort pixels[4] =
+    {
+        0xF00F, // Red
+        0x0F0F, // Green
+        0x00FF, // Blue
+        0xFF0F  // Red + Green
+    };
+
+    glClearColor(0, 0, 0, 0);
+
+    // Generate a RGBA4444 texture, no mipmaps
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    // Provide some data for the texture
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels);
+    EXPECT_GL_NO_ERROR();
+
+    simpleValidationBase(tex.get());
+}
+
+// Test uploading RGBA8 data to RGBA4 textures.
+TEST_P(SixteenBppTextureTestES3, RGBA4UploadRGBA8)
+{
+    std::vector<GLColor> fourColors;
+    fourColors.push_back(GLColor::red);
+    fourColors.push_back(GLColor::green);
+    fourColors.push_back(GLColor::blue);
+    fourColors.push_back(GLColor::yellow);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, fourColors.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+    simpleValidationBase(tex.get());
+}
+
+// Test uploading RGB8 data to RGB565 textures.
+TEST_P(SixteenBppTextureTestES3, RGB565UploadRGB8)
+{
+    std::vector<GLColorRGB> fourColors;
+    fourColors.push_back(GLColorRGB::red);
+    fourColors.push_back(GLColorRGB::green);
+    fourColors.push_back(GLColorRGB::blue);
+    fourColors.push_back(GLColorRGB::yellow);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, fourColors.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+
+    simpleValidationBase(tex.get());
+}
+
+// Test uploading RGBA8 data to RGB5A41 textures.
+TEST_P(SixteenBppTextureTestES3, RGB5A1UploadRGBA8)
+{
+    std::vector<GLColor> fourColors;
+    fourColors.push_back(GLColor::red);
+    fourColors.push_back(GLColor::green);
+    fourColors.push_back(GLColor::blue);
+    fourColors.push_back(GLColor::yellow);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 fourColors.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+    simpleValidationBase(tex.get());
+}
+
+// Test uploading RGB10A2 data to RGB5A1 textures.
+TEST_P(SixteenBppTextureTestES3, RGB5A1UploadRGB10A2)
+{
+    struct RGB10A2
+    {
+        RGB10A2(uint32_t r, uint32_t g, uint32_t b, uint32_t a) : R(r), G(g), B(b), A(a) {}
+
+        uint32_t R : 10;
+        uint32_t G : 10;
+        uint32_t B : 10;
+        uint32_t A : 2;
+    };
+
+    uint32_t one10 = (1u << 10u) - 1u;
+
+    RGB10A2 red(one10, 0u, 0u, 0x3u);
+    RGB10A2 green(0u, one10, 0u, 0x3u);
+    RGB10A2 blue(0u, 0u, one10, 0x3u);
+    RGB10A2 yellow(one10, one10, 0u, 0x3u);
+
+    std::vector<RGB10A2> fourColors;
+    fourColors.push_back(red);
+    fourColors.push_back(green);
+    fourColors.push_back(blue);
+    fourColors.push_back(yellow);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 2, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV,
+                 fourColors.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+    simpleValidationBase(tex.get());
+}
+
+// Test reading from RGBA4 textures attached to FBO.
+TEST_P(SixteenBppTextureTestES3, RGBA4FramebufferReadback)
+{
+    // TODO(jmadill): Fix bug with GLES
+    if (IsOpenGLES())
+    {
+        std::cout << "Test skipped on GLES." << std::endl;
+        return;
+    }
+
+    Vector4 rawColor(0.5f, 0.7f, 1.0f, 0.0f);
+    GLColor expectedColor(rawColor);
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.get(), 0);
+
+    glClearColor(rawColor.x(), rawColor.y(), rawColor.z(), rawColor.w());
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    ASSERT_GL_NO_ERROR();
+
+    GLenum colorReadFormat = GL_NONE;
+    GLenum colorReadType   = GL_NONE;
+    glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, reinterpret_cast<GLint *>(&colorReadFormat));
+    glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, reinterpret_cast<GLint *>(&colorReadType));
+
+    if (colorReadFormat == GL_RGBA && colorReadType == GL_UNSIGNED_BYTE)
+    {
+        GLColor actualColor = GLColor::black;
+        glReadPixels(0, 0, 1, 1, colorReadFormat, colorReadType, &actualColor);
+        EXPECT_COLOR_NEAR(expectedColor, actualColor, 20);
+    }
+    else
+    {
+        ASSERT_GLENUM_EQ(GL_RGBA, colorReadFormat);
+        ASSERT_TRUE(colorReadType == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT ||
+                    colorReadType == GL_UNSIGNED_SHORT_4_4_4_4);
+
+        uint16_t rgba = 0;
+        glReadPixels(0, 0, 1, 1, colorReadFormat, colorReadType, &rgba);
+
+        GLubyte r8 = static_cast<GLubyte>((rgba & 0xF000) >> 12);
+        GLubyte g8 = static_cast<GLubyte>((rgba & 0x0F00) >> 8);
+        GLubyte b8 = static_cast<GLubyte>((rgba & 0x00F0) >> 4);
+        GLubyte a8 = static_cast<GLubyte>((rgba & 0x000F));
+
+        GLColor actualColor(r8 << 4, g8 << 4, b8 << 4, a8 << 4);
+        EXPECT_COLOR_NEAR(expectedColor, actualColor, 20);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test reading from RGB565 textures attached to FBO.
+TEST_P(SixteenBppTextureTestES3, RGB565FramebufferReadback)
+{
+    // TODO(jmadill): Fix bug with GLES
+    if (IsOpenGLES())
+    {
+        std::cout << "Test skipped on GLES." << std::endl;
+        return;
+    }
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+
+    std::vector<GLColor> fourColors;
+    fourColors.push_back(GLColor::red);
+    fourColors.push_back(GLColor::green);
+    fourColors.push_back(GLColor::blue);
+    fourColors.push_back(GLColor::white);
+
+    const std::string &vertexShader =
+        "#version 300 es\n"
+        "in vec4 color;\n"
+        "in vec2 position;\n"
+        "out vec4 fcolor;\n"
+        "void main() {\n"
+        "    fcolor = color;\n"
+        "    gl_Position = vec4(position, 0.5, 1.0);\n"
+        "}";
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "in mediump vec4 fcolor;\n"
+        "out mediump vec4 color;\n"
+        "void main() {\n"
+        "    color = fcolor;\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShader, fragmentShader);
+    glUseProgram(program);
+
+    GLint colorLocation = glGetAttribLocation(program, "color");
+    ASSERT_NE(-1, colorLocation);
+    glEnableVertexAttribArray(colorLocation);
+    glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, fourColors.data());
+
+    int w = getWindowWidth();
+    int h = getWindowHeight();
+
+    glViewport(0, 0, w, h);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.get(), 0);
+
+    drawIndexedQuad(program, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+
+    int t = 12;
+    EXPECT_PIXEL_COLOR_NEAR(0, h - 1, GLColor::red, t);
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::green, t);
+    EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, GLColor::blue, t);
+    EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, GLColor::white, t);
+
+    GLenum colorReadFormat = GL_NONE;
+    GLenum colorReadType   = GL_NONE;
+    glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, reinterpret_cast<GLint *>(&colorReadFormat));
+    glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, reinterpret_cast<GLint *>(&colorReadType));
+
+    if (colorReadFormat == GL_RGB && colorReadType == GL_UNSIGNED_SHORT_5_6_5)
+    {
+        std::vector<R5G6B5> readColors(w * h);
+        glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, readColors.data());
+
+        int hoffset = (h - 1) * w;
+        EXPECT_COLOR_NEAR(GLColor::red, Convert565(readColors[hoffset]), t);
+        EXPECT_COLOR_NEAR(GLColor::green, Convert565(readColors[0]), t);
+        EXPECT_COLOR_NEAR(GLColor::blue, Convert565(readColors[w - 1]), t);
+        EXPECT_COLOR_NEAR(GLColor::white, Convert565(readColors[w - 1 + hoffset]), t);
+    }
+
+    glDeleteProgram(program);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(SixteenBppTextureTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(SixteenBppTextureTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/StateChangeTest.cpp b/src/third_party/angle/src/tests/gl_tests/StateChangeTest.cpp
new file mode 100644
index 0000000..0ae1ef7
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/StateChangeTest.cpp
@@ -0,0 +1,610 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// StateChangeTest:
+//   Specifically designed for an ANGLE implementation of GL, these tests validate that
+//   ANGLE's dirty bits systems don't get confused by certain sequences of state changes.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+class StateChangeTest : public ANGLETest
+{
+  protected:
+    StateChangeTest()
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+
+        // Enable the no error extension to avoid syncing the FBO state on validation.
+        setNoErrorEnabled(true);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenFramebuffers(1, &mFramebuffer);
+        glGenTextures(2, mTextures.data());
+        glGenRenderbuffers(1, &mRenderbuffer);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        if (mFramebuffer != 0)
+        {
+            glDeleteFramebuffers(1, &mFramebuffer);
+            mFramebuffer = 0;
+        }
+
+        if (!mTextures.empty())
+        {
+            glDeleteTextures(static_cast<GLsizei>(mTextures.size()), mTextures.data());
+            mTextures.clear();
+        }
+
+        glDeleteRenderbuffers(1, &mRenderbuffer);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mFramebuffer           = 0;
+    GLuint mRenderbuffer          = 0;
+    std::vector<GLuint> mTextures = {0, 0};
+};
+
+class StateChangeTestES3 : public StateChangeTest
+{
+  protected:
+    StateChangeTestES3() {}
+};
+
+}  // anonymous namespace
+
+// Ensure that CopyTexImage2D syncs framebuffer changes.
+TEST_P(StateChangeTest, CopyTexImage2DSync)
+{
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // TODO(geofflang): Fix on Linux AMD drivers (http://anglebug.com/1291)
+        std::cout << "Test disabled on AMD OpenGL." << std::endl;
+        return;
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+    // Init first texture to red
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    // Init second texture to green
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    // Copy in the red texture to the green one.
+    // CopyTexImage should sync the framebuffer attachment change.
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 16, 16, 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Ensure that CopyTexSubImage2D syncs framebuffer changes.
+TEST_P(StateChangeTest, CopyTexSubImage2DSync)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+    // Init first texture to red
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    // Init second texture to green
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    // Copy in the red texture to the green one.
+    // CopyTexImage should sync the framebuffer attachment change.
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that Framebuffer completeness caching works when color attachments change.
+TEST_P(StateChangeTest, FramebufferIncompleteColorAttachment)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Change the texture at color attachment 0 to be non-color-renderable.
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that caching works when color attachments change with TexStorage.
+TEST_P(StateChangeTest, FramebufferIncompleteWithTexStorage)
+{
+    if (!extensionEnabled("GL_EXT_texture_storage"))
+    {
+        std::cout << "Test skipped because TexStorage2DEXT not available." << std::endl;
+        return;
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Change the texture at color attachment 0 to be non-color-renderable.
+    glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ALPHA8_EXT, 16, 16);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that caching works when color attachments change with CompressedTexImage2D.
+TEST_P(StateChangeTestES3, FramebufferIncompleteWithCompressedTex)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Change the texture at color attachment 0 to be non-color-renderable.
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 16, 16, 0, 128, nullptr);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that caching works when color attachments are deleted.
+TEST_P(StateChangeTestES3, FramebufferIncompleteWhenAttachmentDeleted)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Delete the texture at color attachment 0.
+    glDeleteTextures(1, &mTextures[0]);
+    mTextures[0] = 0;
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that Framebuffer completeness caching works when depth attachments change.
+TEST_P(StateChangeTest, FramebufferIncompleteDepthAttachment)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 16, 16);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRenderbuffer);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Change the texture at color attachment 0 to be non-depth-renderable.
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that Framebuffer completeness caching works when stencil attachments change.
+TEST_P(StateChangeTest, FramebufferIncompleteStencilAttachment)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 16, 16);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              mRenderbuffer);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Change the texture at the stencil attachment to be non-stencil-renderable.
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that Framebuffer completeness caching works when depth-stencil attachments change.
+TEST_P(StateChangeTest, FramebufferIncompleteDepthStencilAttachment)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_packed_depth_stencil"))
+    {
+        std::cout << "Test skipped because packed depth+stencil not availble." << std::endl;
+        return;
+    }
+
+    if (IsWindows() && IsIntel() && IsOpenGL())
+    {
+        // TODO(jmadill): Investigate the failure (https://anglebug.com/1388)
+        std::cout << "Test disabled on Windows Intel OpenGL." << std::endl;
+        return;
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              mRenderbuffer);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Change the texture the depth-stencil attachment to be non-depth-stencil-renderable.
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Ensure that CopyTexSubImage3D syncs framebuffer changes.
+TEST_P(StateChangeTestES3, CopyTexSubImage3DSync)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+    // Init first texture to red
+    glBindTexture(GL_TEXTURE_3D, mTextures[0]);
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    // Init second texture to green
+    glBindTexture(GL_TEXTURE_3D, mTextures[1]);
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    // Copy in the red texture to the green one.
+    // CopyTexImage should sync the framebuffer attachment change.
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
+    glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 16, 16);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Ensure that BlitFramebuffer syncs framebuffer changes.
+TEST_P(StateChangeTestES3, BlitFramebufferSync)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+    // Init first texture to red
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    // Init second texture to green
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    // Change to the red textures and blit.
+    // BlitFramebuffer should sync the framebuffer attachment change.
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+    glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
+                           0);
+    glBlitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Ensure that ReadBuffer and DrawBuffers sync framebuffer changes.
+TEST_P(StateChangeTestES3, ReadBufferAndDrawBuffersSync)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+    // Initialize two FBO attachments
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
+
+    // Clear first attachment to red
+    GLenum bufs1[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
+    glDrawBuffers(2, bufs1);
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // Clear second texture to green
+    GLenum bufs2[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
+    glDrawBuffers(2, bufs2);
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // Verify first attachment is red and second is green
+    glReadBuffer(GL_COLOR_ATTACHMENT1);
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+    glReadBuffer(GL_COLOR_ATTACHMENT0);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Tests calling invalidate on incomplete framebuffers after switching attachments.
+// Adapted partially from WebGL 2 test "renderbuffers/invalidate-framebuffer"
+TEST_P(StateChangeTestES3, IncompleteRenderbufferAttachmentInvalidateSync)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+    GLint samples = 0;
+    glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, 1, &samples);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
+    ASSERT_GL_NO_ERROR();
+
+    // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
+    // attached renderbuffer
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
+    glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
+    ASSERT_GL_NO_ERROR();
+
+    glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples), GL_RGBA8,
+                                     getWindowWidth(), getWindowHeight());
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    GLRenderbuffer renderbuf;
+
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuf.get());
+    ASSERT_GL_NO_ERROR();
+
+    // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
+    // attached renderbuffer
+    // Note: the bug will only repro *without* a call to checkStatus before the invalidate.
+    GLenum attachments2[] = {GL_DEPTH_ATTACHMENT};
+    glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments2);
+
+    glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples),
+                                     GL_DEPTH_COMPONENT16, getWindowWidth(), getWindowHeight());
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    glClear(GL_DEPTH_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+}
+
+class StateChangeRenderTest : public StateChangeTest
+{
+  protected:
+    StateChangeRenderTest() : mProgram(0), mRenderbuffer(0) {}
+
+    void SetUp() override
+    {
+        StateChangeTest::SetUp();
+
+        const std::string vertexShaderSource =
+            "attribute vec2 position;\n"
+            "void main() {\n"
+            "    gl_Position = vec4(position, 0, 1);\n"
+            "}";
+        const std::string fragmentShaderSource =
+            "uniform highp vec4 uniformColor;\n"
+            "void main() {\n"
+            "    gl_FragColor = uniformColor;\n"
+            "}";
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+
+        glGenRenderbuffers(1, &mRenderbuffer);
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+        glDeleteRenderbuffers(1, &mRenderbuffer);
+
+        StateChangeTest::TearDown();
+    }
+
+    void setUniformColor(const GLColor &color)
+    {
+        glUseProgram(mProgram);
+        const Vector4 &normalizedColor = color.toNormalizedVector();
+        GLint uniformLocation = glGetUniformLocation(mProgram, "uniformColor");
+        ASSERT_NE(-1, uniformLocation);
+        glUniform4fv(uniformLocation, 1, normalizedColor.data());
+    }
+
+    GLuint mProgram;
+    GLuint mRenderbuffer;
+};
+
+// Test that re-creating a currently attached texture works as expected.
+TEST_P(StateChangeRenderTest, RecreateTexture)
+{
+    if (IsIntel() && IsLinux())
+    {
+        // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/1346)
+        std::cout << "Test disabled on Linux Intel OpenGL." << std::endl;
+        return;
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+
+    // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Draw with red to the FBO.
+    GLColor red(255, 0, 0, 255);
+    setUniformColor(red);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, red);
+
+    // Recreate the texture with green.
+    GLColor green(0, 255, 0, 255);
+    std::vector<GLColor> greenPixels(32 * 32, green);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 greenPixels.data());
+    EXPECT_PIXEL_COLOR_EQ(0, 0, green);
+
+    // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
+    GLColor blue(0, 0, 255, 255);
+    setUniformColor(blue);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that re-creating a currently attached renderbuffer works as expected.
+TEST_P(StateChangeRenderTest, RecreateRenderbuffer)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+    glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
+
+    // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Draw with red to the FBO.
+    GLColor red(255, 0, 0, 255);
+    setUniformColor(red);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, red);
+
+    // Recreate the renderbuffer and clear to green.
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 32, 32);
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    GLColor green(0, 255, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, green);
+
+    // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
+    GLColor blue(0, 0, 255, 255);
+    setUniformColor(blue);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that recreating a texture with GenerateMipmaps signals the FBO is dirty.
+TEST_P(StateChangeRenderTest, GenerateMipmap)
+{
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
+
+    // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Draw once to set the RenderTarget in D3D11
+    GLColor red(255, 0, 0, 255);
+    setUniformColor(red);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, red);
+
+    // This will trigger the texture to be re-created on FL9_3.
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // Now ensure we don't have a stale render target.
+    GLColor blue(0, 0, 255, 255);
+    setUniformColor(blue);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+ANGLE_INSTANTIATE_TEST(StateChangeTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
+ANGLE_INSTANTIATE_TEST(StateChangeRenderTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_OPENGL(),
+                       ES2_D3D11_FL9_3());
+ANGLE_INSTANTIATE_TEST(StateChangeTestES3, ES3_D3D11(), ES3_OPENGL());
diff --git a/src/third_party/angle/src/tests/gl_tests/SwizzleTest.cpp b/src/third_party/angle/src/tests/gl_tests/SwizzleTest.cpp
new file mode 100644
index 0000000..c69074b
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/SwizzleTest.cpp
@@ -0,0 +1,462 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include <vector>
+
+using namespace angle;
+
+namespace
+{
+
+class SwizzleTest : public ANGLETest
+{
+  protected:
+    SwizzleTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+
+        constexpr GLenum swizzles[] = {
+            GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_ZERO, GL_ONE,
+        };
+
+        // Only use every 13th swizzle permutation, use a prime number to make sure the permuations
+        // are somewhat evenly distributed.  Reduces the permuations from 1296 to 100.
+        constexpr size_t swizzleReductionFactor = 13;
+
+        size_t swizzleCount = 0;
+        for (GLenum r : swizzles)
+        {
+            for (GLenum g : swizzles)
+            {
+                for (GLenum b : swizzles)
+                {
+                    for (GLenum a : swizzles)
+                    {
+                        swizzleCount++;
+                        if (swizzleCount % swizzleReductionFactor != 0)
+                        {
+                            continue;
+                        }
+
+                        swizzlePermutation permutation;
+                        permutation.swizzleRed   = r;
+                        permutation.swizzleGreen = g;
+                        permutation.swizzleBlue  = b;
+                        permutation.swizzleAlpha = a;
+                        mPermutations.push_back(permutation);
+                    }
+                }
+            }
+        }
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = position;
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+
+        mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
+        ASSERT_NE(-1, mTextureUniformLocation);
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+        glDeleteTextures(1, &mTexture);
+
+        ANGLETest::TearDown();
+    }
+
+    template <typename T>
+    void init2DTexture(GLenum internalFormat, GLenum dataFormat, GLenum dataType, const T* data)
+    {
+        glGenTextures(1, &mTexture);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, dataFormat, dataType, data);
+
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    }
+
+    void init2DCompressedTexture(GLenum internalFormat, GLsizei width, GLsizei height, GLsizei dataSize, const GLubyte* data)
+    {
+        glGenTextures(1, &mTexture);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+        glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, 0, dataSize, data);
+
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    }
+
+    GLubyte getExpectedValue(GLenum swizzle, GLubyte unswizzled[4])
+    {
+        switch (swizzle)
+        {
+          case GL_RED:   return unswizzled[0];
+          case GL_GREEN: return unswizzled[1];
+          case GL_BLUE:  return unswizzled[2];
+          case GL_ALPHA: return unswizzled[3];
+          case GL_ZERO:  return 0;
+          case GL_ONE:   return 255;
+          default:       return 0;
+        }
+    }
+
+    void runTest2D()
+    {
+        // TODO(jmadill): Figure out why this fails on Intel.
+        if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+        {
+            std::cout << "Test skipped on Intel." << std::endl;
+            return;
+        }
+
+        glUseProgram(mProgram);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+        glUniform1i(mTextureUniformLocation, 0);
+
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
+
+        glClear(GL_COLOR_BUFFER_BIT);
+        drawQuad(mProgram, "position", 0.5f);
+
+        GLubyte unswizzled[4];
+        glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &unswizzled);
+
+        ASSERT_GL_NO_ERROR();
+
+        for (const auto &permutation : mPermutations)
+        {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, permutation.swizzleRed);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, permutation.swizzleGreen);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, permutation.swizzleBlue);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, permutation.swizzleAlpha);
+
+            glClear(GL_COLOR_BUFFER_BIT);
+            drawQuad(mProgram, "position", 0.5f);
+
+            EXPECT_PIXEL_EQ(0, 0,
+                            getExpectedValue(permutation.swizzleRed, unswizzled),
+                            getExpectedValue(permutation.swizzleGreen, unswizzled),
+                            getExpectedValue(permutation.swizzleBlue, unswizzled),
+                            getExpectedValue(permutation.swizzleAlpha, unswizzled));
+
+            ASSERT_GL_NO_ERROR();
+        }
+    }
+
+    GLuint mProgram;
+    GLint mTextureUniformLocation;
+
+    GLuint mTexture;
+
+    struct swizzlePermutation
+    {
+        GLenum swizzleRed;
+        GLenum swizzleGreen;
+        GLenum swizzleBlue;
+        GLenum swizzleAlpha;
+    };
+    std::vector<swizzlePermutation> mPermutations;
+};
+
+class SwizzleIntegerTest : public SwizzleTest
+{
+  protected:
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource =
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "in vec4 position;\n"
+            "out vec2 texcoord;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n";
+
+        const std::string fragmentShaderSource =
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "precision highp usampler2D;\n"
+            "uniform usampler2D tex;\n"
+            "in vec2 texcoord;\n"
+            "out vec4 my_FragColor;\n"
+            "\n"
+            "void main()\n"
+            "{\n"
+            "    uvec4 s = texture(tex, texcoord);\n"
+            "    if (s[0] == 1u) s[0] = 255u;\n"
+            "    if (s[1] == 1u) s[1] = 255u;\n"
+            "    if (s[2] == 1u) s[2] = 255u;\n"
+            "    if (s[3] == 1u) s[3] = 255u;\n"
+            "    my_FragColor = vec4(s) / 255.0;\n"
+            "}\n";
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+
+        mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
+        ASSERT_NE(-1, mTextureUniformLocation);
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        ASSERT_GL_NO_ERROR();
+    }
+};
+
+TEST_P(SwizzleTest, RGBA8_2D)
+{
+    GLubyte data[] = { 1, 64, 128, 200 };
+    init2DTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, RGB8_2D)
+{
+    GLubyte data[] = { 77, 66, 55 };
+    init2DTexture(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, RG8_2D)
+{
+    GLubyte data[] = { 11, 99 };
+    init2DTexture(GL_RG8, GL_RG, GL_UNSIGNED_BYTE, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, R8_2D)
+{
+    GLubyte data[] = { 2 };
+    init2DTexture(GL_R8, GL_RED, GL_UNSIGNED_BYTE, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, RGB10_A2_2D)
+{
+    GLuint data[] = {20u | (40u << 10) | (60u << 20) | (2u << 30)};
+    init2DTexture(GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, RGBA32F_2D)
+{
+    GLfloat data[] = { 0.25f, 0.5f, 0.75f, 0.8f };
+    init2DTexture(GL_RGBA32F, GL_RGBA, GL_FLOAT, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, RGB32F_2D)
+{
+    GLfloat data[] = { 0.1f, 0.2f, 0.3f };
+    init2DTexture(GL_RGB32F, GL_RGB, GL_FLOAT, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, RG32F_2D)
+{
+    GLfloat data[] = { 0.9f, 0.1f  };
+    init2DTexture(GL_RG32F, GL_RG, GL_FLOAT, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, R32F_2D)
+{
+    GLfloat data[] = { 0.5f };
+    init2DTexture(GL_R32F, GL_RED, GL_FLOAT, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, D32F_2D)
+{
+    GLfloat data[] = { 0.5f };
+    init2DTexture(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, D16_2D)
+{
+    GLushort data[] = { 0xFF };
+    init2DTexture(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, D24_2D)
+{
+    GLuint data[] = { 0xFFFF };
+    init2DTexture(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, L8_2D)
+{
+    GLubyte data[] = {0x77};
+    init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, A8_2D)
+{
+    GLubyte data[] = {0x55};
+    init2DTexture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, LA8_2D)
+{
+    GLubyte data[] = {0x77, 0x66};
+    init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, L32F_2D)
+{
+    if (!extensionEnabled("GL_OES_texture_float"))
+    {
+        std::cout << "Test skipped due to missing GL_OES_texture_float." << std::endl;
+        return;
+    }
+
+    GLfloat data[] = {0.7f};
+    init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, A32F_2D)
+{
+    if (!extensionEnabled("GL_OES_texture_float"))
+    {
+        std::cout << "Test skipped due to missing GL_OES_texture_float." << std::endl;
+        return;
+    }
+
+    GLfloat data[] = {
+        0.4f,
+    };
+    init2DTexture(GL_ALPHA, GL_ALPHA, GL_FLOAT, data);
+    runTest2D();
+}
+
+TEST_P(SwizzleTest, LA32F_2D)
+{
+    if (!extensionEnabled("GL_OES_texture_float"))
+    {
+        std::cout << "Test skipped due to missing GL_OES_texture_float." << std::endl;
+        return;
+    }
+
+    GLfloat data[] = {
+        0.5f, 0.6f,
+    };
+    init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, data);
+    runTest2D();
+}
+
+#include "media/pixel.inl"
+
+TEST_P(SwizzleTest, CompressedDXT_2D)
+{
+    if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
+    {
+        std::cout << "Test skipped due to missing GL_EXT_texture_compression_dxt1." << std::endl;
+        return;
+    }
+
+    init2DCompressedTexture(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height, pixel_0_size, pixel_0_data);
+    runTest2D();
+}
+
+TEST_P(SwizzleIntegerTest, RGB8UI_2D)
+{
+    GLubyte data[] = {77, 66, 55};
+    init2DTexture(GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, data);
+    runTest2D();
+}
+
+// Test that updating the texture data still generates the correct swizzles
+TEST_P(SwizzleTest, SubUpdate)
+{
+    GLColor data(1, 64, 128, 200);
+    init2DTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &data);
+
+    glUseProgram(mProgram);
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+    glUniform1i(mTextureUniformLocation, 0);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    drawQuad(mProgram, "position", 0.5f);
+
+    GLColor expectedData(data.R, data.R, data.R, data.R);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, expectedData);
+
+    GLColor updateData(32, 234, 28, 232);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &updateData);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    drawQuad(mProgram, "position", 0.5f);
+
+    GLColor expectedUpdateData(updateData.R, updateData.R, updateData.R, updateData.R);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, expectedUpdateData);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(SwizzleTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGL(3, 3), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(SwizzleIntegerTest,
+                       ES3_D3D11(),
+                       ES3_OPENGL(),
+                       ES3_OPENGL(3, 3),
+                       ES3_OPENGLES());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/SyncQueriesTest.cpp b/src/third_party/angle/src/tests/gl_tests/SyncQueriesTest.cpp
new file mode 100644
index 0000000..b363112
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/SyncQueriesTest.cpp
@@ -0,0 +1,108 @@
+//
+// Copyright 2016 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.
+//
+
+// SyncQueriesTest.cpp: Tests of the GL_CHROMIUM_sync_query extension
+
+#include "test_utils/ANGLETest.h"
+
+namespace angle
+{
+
+class SyncQueriesTest : public ANGLETest
+{
+  protected:
+    SyncQueriesTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    void TearDown() override
+    {
+        if (mQuery != 0)
+        {
+            glDeleteQueriesEXT(1, &mQuery);
+            mQuery = 0;
+        }
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mQuery = 0;
+};
+
+// Test basic usage of sync queries
+TEST_P(SyncQueriesTest, Basic)
+{
+    if (!extensionEnabled("GL_CHROMIUM_sync_query"))
+    {
+        std::cout << "Test skipped because GL_CHROMIUM_sync_query is not available." << std::endl;
+        return;
+    }
+
+    glGenQueriesEXT(1, &mQuery);
+    glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, mQuery);
+    EXPECT_GL_NO_ERROR();
+
+    glClearColor(0.0, 0.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
+
+    glFlush();
+    GLuint result = 0;
+    glGetQueryObjectuivEXT(mQuery, GL_QUERY_RESULT_EXT, &result);
+    EXPECT_EQ(static_cast<GLuint>(GL_TRUE), result);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that the sync query enums are not accepted unless the extension is available
+TEST_P(SyncQueriesTest, Validation)
+{
+    // Need the GL_EXT_occlusion_query_boolean extension for the entry points
+    if (!extensionEnabled("GL_EXT_occlusion_query_boolean"))
+    {
+        std::cout << "Test skipped because GL_EXT_occlusion_query_boolean is not available."
+                  << std::endl;
+        return;
+    }
+
+    bool extensionAvailable = extensionEnabled("GL_CHROMIUM_sync_query");
+
+    glGenQueriesEXT(1, &mQuery);
+
+    glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, mQuery);
+    if (extensionAvailable)
+    {
+        EXPECT_GL_NO_ERROR();
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+
+    glDeleteQueriesEXT(1, &mQuery);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(SyncQueriesTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/gl_tests/TextureMultisampleTest.cpp b/src/third_party/angle/src/tests/gl_tests/TextureMultisampleTest.cpp
new file mode 100644
index 0000000..47eda6f
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/TextureMultisampleTest.cpp
@@ -0,0 +1,149 @@
+//
+// Copyright 2017 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.
+//
+
+// TextureMultisampleTest: Tests of multisampled texture
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+class TextureMultisampleTest : public ANGLETest
+{
+  protected:
+    TextureMultisampleTest()
+    {
+        setWindowWidth(64);
+        setWindowHeight(64);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenFramebuffers(1, &mFramebuffer);
+        glGenTextures(1, &mTexture);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteFramebuffers(1, &mFramebuffer);
+        mFramebuffer = 0;
+        glDeleteTextures(1, &mTexture);
+        mTexture = 0;
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mFramebuffer = 0;
+    GLuint mTexture     = 0;
+};
+
+class TextureMultisampleTestES31 : public TextureMultisampleTest
+{
+  protected:
+    TextureMultisampleTestES31() : TextureMultisampleTest() {}
+};
+
+// Tests that if es version < 3.1, GL_TEXTURE_2D_MULTISAMPLE is not supported in
+// GetInternalformativ.
+TEST_P(TextureMultisampleTest, MultisampleTargetGetInternalFormativBase)
+{
+    GLint maxSamples = 0;
+    glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
+    if (getClientMajorVersion() < 3 || getClientMinorVersion() < 1)
+    {
+        ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+    else
+    {
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+// Tests that if es version < 3.1, GL_TEXTURE_2D_MULTISAMPLE is not supported in
+// FramebufferTexture2D.
+TEST_P(TextureMultisampleTest, MultisampleTargetFramebufferTexture2D)
+{
+    GLint samples = 1;
+    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, 64, 64, GL_FALSE);
+    if (getClientMajorVersion() < 3 || getClientMinorVersion() < 1)
+    {
+        ASSERT_GL_ERROR(GL_INVALID_ENUM);
+    }
+    else
+    {
+        ASSERT_GL_NO_ERROR();
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
+                           mTexture, 0);
+    if (getClientMajorVersion() < 3 || getClientMinorVersion() < 1)
+    {
+        ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+    else
+    {
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+// Tests basic functionality of glTexStorage2DMultisample.
+TEST_P(TextureMultisampleTestES31, ValidateTextureStorageMultisampleParameters)
+{
+    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
+    ASSERT_GL_NO_ERROR();
+
+    GLint params = 0;
+    glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, &params);
+    EXPECT_EQ(1, params);
+
+    glTexStorage2DMultisample(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, GL_FALSE);
+    ASSERT_GL_ERROR(GL_INVALID_ENUM);
+
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 0, 0, GL_FALSE);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    GLint maxSize = 0;
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, maxSize + 1, 1, GL_FALSE);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    GLint maxSamples = 0;
+    glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples + 1, GL_RGBA8, 1, 1, GL_FALSE);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_RGBA8, 1, 1, GL_FALSE);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA, 0, 0, GL_FALSE);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
+    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+ANGLE_INSTANTIATE_TEST(TextureMultisampleTest,
+                       ES3_OPENGL(),
+                       ES3_OPENGLES(),
+                       ES31_OPENGL(),
+                       ES31_OPENGLES());
+ANGLE_INSTANTIATE_TEST(TextureMultisampleTestES31, ES31_OPENGL(), ES31_OPENGLES());
+}
diff --git a/src/third_party/angle/src/tests/gl_tests/TextureTest.cpp b/src/third_party/angle/src/tests/gl_tests/TextureTest.cpp
new file mode 100644
index 0000000..148d68f
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/TextureTest.cpp
@@ -0,0 +1,3865 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "common/mathutil.h"
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+// Take a pixel, and reset the components not covered by the format to default
+// values. In particular, the default value for the alpha component is 255
+// (1.0 as unsigned normalized fixed point value).
+GLColor SliceFormatColor(GLenum format, GLColor full)
+{
+    switch (format)
+    {
+        case GL_RED:
+            return GLColor(full.R, 0, 0, 255u);
+        case GL_RG:
+            return GLColor(full.R, full.G, 0, 255u);
+        case GL_RGB:
+            return GLColor(full.R, full.G, full.B, 255u);
+        case GL_RGBA:
+            return full;
+        default:
+            EXPECT_TRUE(false);
+            return GLColor::white;
+    }
+}
+
+class TexCoordDrawTest : public ANGLETest
+{
+  protected:
+    TexCoordDrawTest() : ANGLETest(), mProgram(0), mFramebuffer(0), mFramebufferColorTexture(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    virtual std::string getVertexShaderSource()
+    {
+        return std::string(SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = vec4(position.xy, 0.0, 1.0);
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        )
+        );
+    }
+
+    virtual std::string getFragmentShaderSource() = 0;
+
+    virtual void setUpProgram()
+    {
+        const std::string vertexShaderSource   = getVertexShaderSource();
+        const std::string fragmentShaderSource = getFragmentShaderSource();
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        setUpFramebuffer();
+    }
+
+    void TearDown() override
+    {
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glDeleteFramebuffers(1, &mFramebuffer);
+        glDeleteTextures(1, &mFramebufferColorTexture);
+        glDeleteProgram(mProgram);
+        ANGLETest::TearDown();
+    }
+
+    void setUpFramebuffer()
+    {
+        // We use an FBO to work around an issue where the default framebuffer applies SRGB
+        // conversion (particularly known to happen incorrectly on Intel GL drivers). It's not
+        // clear whether this issue can even be fixed on all backends. For example GLES 3.0.4 spec
+        // section 4.4 says that the format of the default framebuffer is entirely up to the window
+        // system, so it might be SRGB, and GLES 3.0 doesn't have a "FRAMEBUFFER_SRGB" to turn off
+        // SRGB conversion like desktop GL does.
+        // TODO(oetuaho): Get rid of this if the underlying issue is fixed.
+        glGenFramebuffers(1, &mFramebuffer);
+        glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+        glGenTextures(1, &mFramebufferColorTexture);
+        glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+                     GL_UNSIGNED_BYTE, nullptr);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                               mFramebufferColorTexture, 0);
+        ASSERT_GL_NO_ERROR();
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        glBindTexture(GL_TEXTURE_2D, 0);
+    }
+
+    // Returns the created texture ID.
+    GLuint create2DTexture()
+    {
+        GLuint texture2D;
+        glGenTextures(1, &texture2D);
+        glBindTexture(GL_TEXTURE_2D, texture2D);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        EXPECT_GL_NO_ERROR();
+        return texture2D;
+    }
+
+    GLuint mProgram;
+    GLuint mFramebuffer;
+
+  private:
+    GLuint mFramebufferColorTexture;
+};
+
+class Texture2DTest : public TexCoordDrawTest
+{
+  protected:
+    Texture2DTest() : TexCoordDrawTest(), mTexture2D(0), mTexture2DUniformLocation(-1) {}
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        )
+        );
+    }
+
+    virtual const char *getTextureUniformName() { return "tex"; }
+
+    void setUpProgram() override
+    {
+        TexCoordDrawTest::setUpProgram();
+        mTexture2DUniformLocation = glGetUniformLocation(mProgram, getTextureUniformName());
+        ASSERT_NE(-1, mTexture2DUniformLocation);
+    }
+
+    void SetUp() override
+    {
+        TexCoordDrawTest::SetUp();
+        mTexture2D = create2DTexture();
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTexture2D);
+        TexCoordDrawTest::TearDown();
+    }
+
+    // Tests CopyTexSubImage with floating point textures of various formats.
+    void testFloatCopySubImage(int sourceImageChannels, int destImageChannels)
+    {
+        // TODO(jmadill): Figure out why this is broken on Intel D3D11
+        if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+        {
+            std::cout << "Test skipped on Intel D3D11." << std::endl;
+            return;
+        }
+
+        setUpProgram();
+
+        if (getClientMajorVersion() < 3)
+        {
+            if (!extensionEnabled("GL_EXT_texture_storage"))
+            {
+                std::cout << "Test skipped due to missing GL_EXT_texture_storage." << std::endl;
+                return;
+            }
+
+            if (!extensionEnabled("GL_OES_texture_float"))
+            {
+                std::cout << "Test skipped due to missing GL_OES_texture_float." << std::endl;
+                return;
+            }
+
+            if ((sourceImageChannels < 3 || destImageChannels < 3) && !extensionEnabled("GL_EXT_texture_rg"))
+            {
+                std::cout << "Test skipped due to missing GL_EXT_texture_rg." << std::endl;
+                return;
+            }
+
+            if (destImageChannels == 3 && !extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"))
+            {
+                std::cout << "Test skipped due to missing GL_CHROMIUM_color_buffer_float_rgb."
+                          << std::endl;
+                return;
+            }
+
+            if (destImageChannels == 4 && !extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"))
+            {
+                std::cout << "Test skipped due to missing GL_CHROMIUM_color_buffer_float_rgb."
+                          << std::endl;
+                return;
+            }
+
+            if (destImageChannels <= 2)
+            {
+                std::cout << "Test skipped because no extensions grant renderability to 1 and 2 "
+                             "channel floating point textures."
+                          << std::endl;
+                return;
+            }
+        }
+        else
+        {
+            if (!extensionEnabled("GL_color_buffer_float"))
+            {
+                std::cout << "Test skipped due to missing GL_color_buffer_float." << std::endl;
+                return;
+            }
+
+            if (destImageChannels == 3 && !extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"))
+            {
+                std::cout << "Test skipped due to missing GL_CHROMIUM_color_buffer_float_rgb."
+                          << std::endl;
+                return;
+            }
+        }
+
+        GLfloat sourceImageData[4][16] =
+        {
+            { // R
+                1.0f,
+                0.0f,
+                0.0f,
+                1.0f
+            },
+            { // RG
+                1.0f, 0.0f,
+                0.0f, 1.0f,
+                0.0f, 0.0f,
+                1.0f, 1.0f
+            },
+            { // RGB
+                1.0f, 0.0f, 0.0f,
+                0.0f, 1.0f, 0.0f,
+                0.0f, 0.0f, 1.0f,
+                1.0f, 1.0f, 0.0f
+            },
+            { // RGBA
+                1.0f, 0.0f, 0.0f, 1.0f,
+                0.0f, 1.0f, 0.0f, 1.0f,
+                0.0f, 0.0f, 1.0f, 1.0f,
+                1.0f, 1.0f, 0.0f, 1.0f
+            },
+        };
+
+        GLenum imageFormats[] =
+        {
+            GL_R32F,
+            GL_RG32F,
+            GL_RGB32F,
+            GL_RGBA32F,
+        };
+
+        GLenum sourceUnsizedFormats[] =
+        {
+            GL_RED,
+            GL_RG,
+            GL_RGB,
+            GL_RGBA,
+        };
+
+        GLuint textures[2];
+
+        glGenTextures(2, textures);
+
+        GLfloat *imageData = sourceImageData[sourceImageChannels - 1];
+        GLenum sourceImageFormat = imageFormats[sourceImageChannels - 1];
+        GLenum sourceUnsizedFormat = sourceUnsizedFormats[sourceImageChannels - 1];
+        GLenum destImageFormat = imageFormats[destImageChannels - 1];
+
+        glBindTexture(GL_TEXTURE_2D, textures[0]);
+        if (getClientMajorVersion() >= 3)
+        {
+            glTexStorage2D(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
+        }
+        else
+        {
+            glTexStorage2DEXT(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
+        }
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, sourceUnsizedFormat, GL_FLOAT, imageData);
+
+        if (sourceImageChannels < 3 && !extensionEnabled("GL_EXT_texture_rg"))
+        {
+            // This is not supported
+            ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+        }
+        else
+        {
+            ASSERT_GL_NO_ERROR();
+        }
+
+        GLuint fbo;
+        glGenFramebuffers(1, &fbo);
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
+
+        glBindTexture(GL_TEXTURE_2D, textures[1]);
+        if (getClientMajorVersion() >= 3)
+        {
+            glTexStorage2D(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
+        }
+        else
+        {
+            glTexStorage2DEXT(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
+        }
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2);
+        ASSERT_GL_NO_ERROR();
+
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        drawQuad(mProgram, "position", 0.5f);
+
+        int testImageChannels = std::min(sourceImageChannels, destImageChannels);
+
+        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+        if (testImageChannels > 1)
+        {
+            EXPECT_PIXEL_EQ(getWindowHeight() - 1, 0, 0, 255, 0, 255);
+            EXPECT_PIXEL_EQ(getWindowHeight() - 1, getWindowWidth() - 1, 255, 255, 0, 255);
+            if (testImageChannels > 2)
+            {
+                EXPECT_PIXEL_EQ(0, getWindowWidth() - 1, 0, 0, 255, 255);
+            }
+        }
+
+        glDeleteFramebuffers(1, &fbo);
+        glDeleteTextures(2, textures);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    GLuint mTexture2D;
+    GLint mTexture2DUniformLocation;
+};
+
+class Texture2DTestES3 : public Texture2DTest
+{
+  protected:
+    Texture2DTestES3() : Texture2DTest() {}
+
+    std::string getVertexShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "out vec2 texcoord;\n"
+            "in vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n");
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "uniform highp sampler2D tex;\n"
+            "in vec2 texcoord;\n"
+            "out vec4 fragColor;\n"
+            "void main()\n"
+            "{\n"
+            "    fragColor = texture(tex, texcoord);\n"
+            "}\n");
+    }
+
+    void SetUp() override
+    {
+        Texture2DTest::SetUp();
+        setUpProgram();
+    }
+};
+
+class Texture2DIntegerAlpha1TestES3 : public Texture2DTest
+{
+  protected:
+    Texture2DIntegerAlpha1TestES3() : Texture2DTest() {}
+
+    std::string getVertexShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "out vec2 texcoord;\n"
+            "in vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n");
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "uniform highp isampler2D tex;\n"
+            "in vec2 texcoord;\n"
+            "out vec4 fragColor;\n"
+            "void main()\n"
+            "{\n"
+            "    vec4 green = vec4(0, 1, 0, 1);\n"
+            "    vec4 black = vec4(0, 0, 0, 0);\n"
+            "    fragColor = (texture(tex, texcoord).a == 1) ? green : black;\n"
+            "}\n");
+    }
+
+    void SetUp() override
+    {
+        Texture2DTest::SetUp();
+        setUpProgram();
+    }
+};
+
+class Texture2DUnsignedIntegerAlpha1TestES3 : public Texture2DTest
+{
+  protected:
+    Texture2DUnsignedIntegerAlpha1TestES3() : Texture2DTest() {}
+
+    std::string getVertexShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "out vec2 texcoord;\n"
+            "in vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n");
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "uniform highp usampler2D tex;\n"
+            "in vec2 texcoord;\n"
+            "out vec4 fragColor;\n"
+            "void main()\n"
+            "{\n"
+            "    vec4 green = vec4(0, 1, 0, 1);\n"
+            "    vec4 black = vec4(0, 0, 0, 0);\n"
+            "    fragColor = (texture(tex, texcoord).a == 1u) ? green : black;\n"
+            "}\n");
+    }
+
+    void SetUp() override
+    {
+        Texture2DTest::SetUp();
+        setUpProgram();
+    }
+};
+
+class Texture2DTestWithDrawScale : public Texture2DTest
+{
+  protected:
+    Texture2DTestWithDrawScale() : Texture2DTest(), mDrawScaleUniformLocation(-1) {}
+
+    std::string getVertexShaderSource() override
+    {
+        return std::string(SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            uniform vec2 drawScale;
+
+            void main()
+            {
+                gl_Position = vec4(position.xy * drawScale, 0.0, 1.0);
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        )
+        );
+    }
+
+    void SetUp() override
+    {
+        Texture2DTest::SetUp();
+
+        setUpProgram();
+
+        mDrawScaleUniformLocation = glGetUniformLocation(mProgram, "drawScale");
+        ASSERT_NE(-1, mDrawScaleUniformLocation);
+
+        glUseProgram(mProgram);
+        glUniform2f(mDrawScaleUniformLocation, 1.0f, 1.0f);
+        glUseProgram(0);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    GLint mDrawScaleUniformLocation;
+};
+
+class Sampler2DAsFunctionParameterTest : public Texture2DTest
+{
+  protected:
+    Sampler2DAsFunctionParameterTest() : Texture2DTest() {}
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            vec4 computeFragColor(sampler2D aTex)
+            {
+                return texture2D(aTex, texcoord);
+            }
+
+            void main()
+            {
+                gl_FragColor = computeFragColor(tex);
+            }
+        )
+        );
+    }
+
+    void SetUp() override
+    {
+        Texture2DTest::SetUp();
+        setUpProgram();
+    }
+};
+
+class TextureCubeTest : public TexCoordDrawTest
+{
+  protected:
+    TextureCubeTest()
+        : TexCoordDrawTest(),
+          mTexture2D(0),
+          mTextureCube(0),
+          mTexture2DUniformLocation(-1),
+          mTextureCubeUniformLocation(-1)
+    {
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex2D;
+            uniform samplerCube texCube;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex2D, texcoord);
+                gl_FragColor += textureCube(texCube, vec3(texcoord, 0));
+            }
+        )
+        );
+    }
+
+    void SetUp() override
+    {
+        TexCoordDrawTest::SetUp();
+
+        glGenTextures(1, &mTextureCube);
+        glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
+        for (GLenum face = 0; face < 6; face++)
+        {
+            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
+                         GL_UNSIGNED_BYTE, nullptr);
+        }
+        EXPECT_GL_NO_ERROR();
+
+        mTexture2D = create2DTexture();
+
+        setUpProgram();
+
+        mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
+        ASSERT_NE(-1, mTexture2DUniformLocation);
+        mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
+        ASSERT_NE(-1, mTextureCubeUniformLocation);
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTextureCube);
+        TexCoordDrawTest::TearDown();
+    }
+
+    GLuint mTexture2D;
+    GLuint mTextureCube;
+    GLint mTexture2DUniformLocation;
+    GLint mTextureCubeUniformLocation;
+};
+
+class SamplerArrayTest : public TexCoordDrawTest
+{
+  protected:
+    SamplerArrayTest()
+        : TexCoordDrawTest(),
+          mTexture2DA(0),
+          mTexture2DB(0),
+          mTexture0UniformLocation(-1),
+          mTexture1UniformLocation(-1)
+    {
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(SHADER_SOURCE
+        (
+            precision mediump float;
+            uniform highp sampler2D tex2DArray[2];
+            varying vec2 texcoord;
+            void main()
+            {
+                gl_FragColor = texture2D(tex2DArray[0], texcoord);
+                gl_FragColor += texture2D(tex2DArray[1], texcoord);
+            }
+        )
+        );
+    }
+
+    void SetUp() override
+    {
+        TexCoordDrawTest::SetUp();
+
+        setUpProgram();
+
+        mTexture0UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[0]");
+        ASSERT_NE(-1, mTexture0UniformLocation);
+        mTexture1UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[1]");
+        ASSERT_NE(-1, mTexture1UniformLocation);
+
+        mTexture2DA = create2DTexture();
+        mTexture2DB = create2DTexture();
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTexture2DA);
+        glDeleteTextures(1, &mTexture2DB);
+        TexCoordDrawTest::TearDown();
+    }
+
+    void testSamplerArrayDraw()
+    {
+        GLubyte texData[4];
+        texData[0] = 0;
+        texData[1] = 60;
+        texData[2] = 0;
+        texData[3] = 255;
+
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTexture2DA);
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
+
+        texData[1] = 120;
+        glActiveTexture(GL_TEXTURE1);
+        glBindTexture(GL_TEXTURE_2D, mTexture2DB);
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
+        EXPECT_GL_ERROR(GL_NO_ERROR);
+
+        glUseProgram(mProgram);
+        glUniform1i(mTexture0UniformLocation, 0);
+        glUniform1i(mTexture1UniformLocation, 1);
+        drawQuad(mProgram, "position", 0.5f);
+        EXPECT_GL_NO_ERROR();
+
+        EXPECT_PIXEL_NEAR(0, 0, 0, 180, 0, 255, 2);
+    }
+
+    GLuint mTexture2DA;
+    GLuint mTexture2DB;
+    GLint mTexture0UniformLocation;
+    GLint mTexture1UniformLocation;
+};
+
+
+class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
+{
+  protected:
+    SamplerArrayAsFunctionParameterTest() : SamplerArrayTest() {}
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(SHADER_SOURCE
+        (
+            precision mediump float;
+            uniform highp sampler2D tex2DArray[2];
+            varying vec2 texcoord;
+
+            vec4 computeFragColor(highp sampler2D aTex2DArray[2])
+            {
+                return texture2D(aTex2DArray[0], texcoord) + texture2D(aTex2DArray[1], texcoord);
+            }
+
+            void main()
+            {
+                gl_FragColor = computeFragColor(tex2DArray);
+            }
+        )
+        );
+    }
+};
+
+class Texture2DArrayTestES3 : public TexCoordDrawTest
+{
+  protected:
+    Texture2DArrayTestES3() : TexCoordDrawTest(), m2DArrayTexture(0), mTextureArrayLocation(-1) {}
+
+    std::string getVertexShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "out vec2 texcoord;\n"
+            "in vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n");
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "uniform highp sampler2DArray tex2DArray;\n"
+            "in vec2 texcoord;\n"
+            "out vec4 fragColor;\n"
+            "void main()\n"
+            "{\n"
+            "    fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, 0.0));\n"
+            "}\n");
+    }
+
+    void SetUp() override
+    {
+        TexCoordDrawTest::SetUp();
+
+        setUpProgram();
+
+        mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
+        ASSERT_NE(-1, mTextureArrayLocation);
+
+        glGenTextures(1, &m2DArrayTexture);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &m2DArrayTexture);
+        TexCoordDrawTest::TearDown();
+    }
+
+    GLuint m2DArrayTexture;
+    GLint mTextureArrayLocation;
+};
+
+class TextureSizeTextureArrayTest : public TexCoordDrawTest
+{
+  protected:
+    TextureSizeTextureArrayTest()
+        : TexCoordDrawTest(),
+          mTexture2DA(0),
+          mTexture2DB(0),
+          mTexture0Location(-1),
+          mTexture1Location(-1)
+    {
+    }
+
+    std::string getVertexShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "in vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "}\n");
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "uniform highp sampler2D tex2DArray[2];\n"
+            "out vec4 fragColor;\n"
+            "void main()\n"
+            "{\n"
+            "    float red = float(textureSize(tex2DArray[0], 0).x) / 255.0;\n"
+            "    float green = float(textureSize(tex2DArray[1], 0).x) / 255.0;\n"
+            "    fragColor = vec4(red, green, 0.0, 1.0);\n"
+            "}\n");
+    }
+
+    void SetUp() override
+    {
+        TexCoordDrawTest::SetUp();
+
+        setUpProgram();
+
+        mTexture0Location = glGetUniformLocation(mProgram, "tex2DArray[0]");
+        ASSERT_NE(-1, mTexture0Location);
+        mTexture1Location = glGetUniformLocation(mProgram, "tex2DArray[1]");
+        ASSERT_NE(-1, mTexture1Location);
+
+        mTexture2DA = create2DTexture();
+        mTexture2DB = create2DTexture();
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTexture2DA);
+        glDeleteTextures(1, &mTexture2DB);
+        TexCoordDrawTest::TearDown();
+    }
+
+    GLuint mTexture2DA;
+    GLuint mTexture2DB;
+    GLint mTexture0Location;
+    GLint mTexture1Location;
+};
+
+class Texture3DTestES3 : public TexCoordDrawTest
+{
+  protected:
+    Texture3DTestES3() : TexCoordDrawTest(), mTexture3D(0), mTexture3DUniformLocation(-1) {}
+
+    std::string getVertexShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "out vec2 texcoord;\n"
+            "in vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n");
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "uniform highp sampler3D tex3D;\n"
+            "in vec2 texcoord;\n"
+            "out vec4 fragColor;\n"
+            "void main()\n"
+            "{\n"
+            "    fragColor = texture(tex3D, vec3(texcoord, 0.0));\n"
+            "}\n");
+    }
+
+    void SetUp() override
+    {
+        TexCoordDrawTest::SetUp();
+
+        glGenTextures(1, &mTexture3D);
+
+        setUpProgram();
+
+        mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
+        ASSERT_NE(-1, mTexture3DUniformLocation);
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTexture3D);
+        TexCoordDrawTest::TearDown();
+    }
+
+    GLuint mTexture3D;
+    GLint mTexture3DUniformLocation;
+};
+
+class ShadowSamplerPlusSampler3DTestES3 : public TexCoordDrawTest
+{
+  protected:
+    ShadowSamplerPlusSampler3DTestES3()
+        : TexCoordDrawTest(),
+          mTextureShadow(0),
+          mTexture3D(0),
+          mTextureShadowUniformLocation(-1),
+          mTexture3DUniformLocation(-1),
+          mDepthRefUniformLocation(-1)
+    {
+    }
+
+    std::string getVertexShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "out vec2 texcoord;\n"
+            "in vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n");
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "uniform highp sampler2DShadow tex2DShadow;\n"
+            "uniform highp sampler3D tex3D;\n"
+            "in vec2 texcoord;\n"
+            "uniform float depthRef;\n"
+            "out vec4 fragColor;\n"
+            "void main()\n"
+            "{\n"
+            "    fragColor = vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.5);\n"
+            "    fragColor += texture(tex3D, vec3(texcoord, 0.0));\n"
+            "}\n");
+    }
+
+    void SetUp() override
+    {
+        TexCoordDrawTest::SetUp();
+
+        glGenTextures(1, &mTexture3D);
+
+        glGenTextures(1, &mTextureShadow);
+        glBindTexture(GL_TEXTURE_2D, mTextureShadow);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+
+        setUpProgram();
+
+        mTextureShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
+        ASSERT_NE(-1, mTextureShadowUniformLocation);
+        mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
+        ASSERT_NE(-1, mTexture3DUniformLocation);
+        mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
+        ASSERT_NE(-1, mDepthRefUniformLocation);
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTextureShadow);
+        glDeleteTextures(1, &mTexture3D);
+        TexCoordDrawTest::TearDown();
+    }
+
+    GLuint mTextureShadow;
+    GLuint mTexture3D;
+    GLint mTextureShadowUniformLocation;
+    GLint mTexture3DUniformLocation;
+    GLint mDepthRefUniformLocation;
+};
+
+class SamplerTypeMixTestES3 : public TexCoordDrawTest
+{
+  protected:
+    SamplerTypeMixTestES3()
+        : TexCoordDrawTest(),
+          mTexture2D(0),
+          mTextureCube(0),
+          mTexture2DShadow(0),
+          mTextureCubeShadow(0),
+          mTexture2DUniformLocation(-1),
+          mTextureCubeUniformLocation(-1),
+          mTexture2DShadowUniformLocation(-1),
+          mTextureCubeShadowUniformLocation(-1),
+          mDepthRefUniformLocation(-1)
+    {
+    }
+
+    std::string getVertexShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "out vec2 texcoord;\n"
+            "in vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n");
+    }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "#version 300 es\n"
+            "precision highp float;\n"
+            "uniform highp sampler2D tex2D;\n"
+            "uniform highp samplerCube texCube;\n"
+            "uniform highp sampler2DShadow tex2DShadow;\n"
+            "uniform highp samplerCubeShadow texCubeShadow;\n"
+            "in vec2 texcoord;\n"
+            "uniform float depthRef;\n"
+            "out vec4 fragColor;\n"
+            "void main()\n"
+            "{\n"
+            "    fragColor = texture(tex2D, texcoord);\n"
+            "    fragColor += texture(texCube, vec3(1.0, 0.0, 0.0));\n"
+            "    fragColor += vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.25);\n"
+            "    fragColor += vec4(texture(texCubeShadow, vec4(1.0, 0.0, 0.0, depthRef)) * "
+            "0.125);\n"
+            "}\n");
+    }
+
+    void SetUp() override
+    {
+        TexCoordDrawTest::SetUp();
+
+        glGenTextures(1, &mTexture2D);
+        glGenTextures(1, &mTextureCube);
+
+        glGenTextures(1, &mTexture2DShadow);
+        glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+
+        glGenTextures(1, &mTextureCubeShadow);
+        glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
+        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+
+        setUpProgram();
+
+        mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
+        ASSERT_NE(-1, mTexture2DUniformLocation);
+        mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
+        ASSERT_NE(-1, mTextureCubeUniformLocation);
+        mTexture2DShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
+        ASSERT_NE(-1, mTexture2DShadowUniformLocation);
+        mTextureCubeShadowUniformLocation = glGetUniformLocation(mProgram, "texCubeShadow");
+        ASSERT_NE(-1, mTextureCubeShadowUniformLocation);
+        mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
+        ASSERT_NE(-1, mDepthRefUniformLocation);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(1, &mTexture2D);
+        glDeleteTextures(1, &mTextureCube);
+        glDeleteTextures(1, &mTexture2DShadow);
+        glDeleteTextures(1, &mTextureCubeShadow);
+        TexCoordDrawTest::TearDown();
+    }
+
+    GLuint mTexture2D;
+    GLuint mTextureCube;
+    GLuint mTexture2DShadow;
+    GLuint mTextureCubeShadow;
+    GLint mTexture2DUniformLocation;
+    GLint mTextureCubeUniformLocation;
+    GLint mTexture2DShadowUniformLocation;
+    GLint mTextureCubeShadowUniformLocation;
+    GLint mDepthRefUniformLocation;
+};
+
+class SamplerInStructTest : public Texture2DTest
+{
+  protected:
+    SamplerInStructTest() : Texture2DTest() {}
+
+    const char *getTextureUniformName() override { return "us.tex"; }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "precision highp float;\n"
+            "struct S\n"
+            "{\n"
+            "    vec4 a;\n"
+            "    highp sampler2D tex;\n"
+            "};\n"
+            "uniform S us;\n"
+            "varying vec2 texcoord;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = texture2D(us.tex, texcoord + us.a.x);\n"
+            "}\n");
+    }
+
+    void runSamplerInStructTest()
+    {
+        setUpProgram();
+
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTexture2D);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     &GLColor::green);
+        drawQuad(mProgram, "position", 0.5f);
+        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+    }
+};
+
+class SamplerInStructAsFunctionParameterTest : public SamplerInStructTest
+{
+  protected:
+    SamplerInStructAsFunctionParameterTest() : SamplerInStructTest() {}
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "precision highp float;\n"
+            "struct S\n"
+            "{\n"
+            "    vec4 a;\n"
+            "    highp sampler2D tex;\n"
+            "};\n"
+            "uniform S us;\n"
+            "varying vec2 texcoord;\n"
+            "vec4 sampleFrom(S s) {\n"
+            "    return texture2D(s.tex, texcoord + s.a.x);\n"
+            "}\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = sampleFrom(us);\n"
+            "}\n");
+    }
+};
+
+class SamplerInStructArrayAsFunctionParameterTest : public SamplerInStructTest
+{
+  protected:
+    SamplerInStructArrayAsFunctionParameterTest() : SamplerInStructTest() {}
+
+    const char *getTextureUniformName() override { return "us[0].tex"; }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "precision highp float;\n"
+            "struct S\n"
+            "{\n"
+            "    vec4 a;\n"
+            "    highp sampler2D tex;\n"
+            "};\n"
+            "uniform S us[1];\n"
+            "varying vec2 texcoord;\n"
+            "vec4 sampleFrom(S s) {\n"
+            "    return texture2D(s.tex, texcoord + s.a.x);\n"
+            "}\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = sampleFrom(us[0]);\n"
+            "}\n");
+    }
+};
+
+class SamplerInNestedStructAsFunctionParameterTest : public SamplerInStructTest
+{
+  protected:
+    SamplerInNestedStructAsFunctionParameterTest() : SamplerInStructTest() {}
+
+    const char *getTextureUniformName() override { return "us[0].sub.tex"; }
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "precision highp float;\n"
+            "struct SUB\n"
+            "{\n"
+            "    vec4 a;\n"
+            "    highp sampler2D tex;\n"
+            "};\n"
+            "struct S\n"
+            "{\n"
+            "    SUB sub;\n"
+            "};\n"
+            "uniform S us[1];\n"
+            "varying vec2 texcoord;\n"
+            "vec4 sampleFrom(SUB s) {\n"
+            "    return texture2D(s.tex, texcoord + s.a.x);\n"
+            "}\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = sampleFrom(us[0].sub);\n"
+            "}\n");
+    }
+};
+
+class SamplerInStructAndOtherVariableTest : public SamplerInStructTest
+{
+  protected:
+    SamplerInStructAndOtherVariableTest() : SamplerInStructTest() {}
+
+    std::string getFragmentShaderSource() override
+    {
+        return std::string(
+            "precision highp float;\n"
+            "struct S\n"
+            "{\n"
+            "    vec4 a;\n"
+            "    highp sampler2D tex;\n"
+            "};\n"
+            "uniform S us;\n"
+            "uniform float us_tex;\n"
+            "varying vec2 texcoord;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_FragColor = texture2D(us.tex, texcoord + us.a.x + us_tex);\n"
+            "}\n");
+    }
+};
+
+TEST_P(Texture2DTest, NegativeAPISubImage)
+{
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    EXPECT_GL_ERROR(GL_NO_ERROR);
+
+    setUpProgram();
+
+    const GLubyte *pixels[20] = { 0 };
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    if (extensionEnabled("GL_EXT_texture_storage"))
+    {
+        // Create a 1-level immutable texture.
+        glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
+
+        // Try calling sub image on the second level.
+        glTexSubImage2D(GL_TEXTURE_2D, 1, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+}
+
+// Test that querying GL_TEXTURE_BINDING* doesn't cause an unexpected error.
+TEST_P(Texture2DTest, QueryBinding)
+{
+    glBindTexture(GL_TEXTURE_2D, 0);
+    EXPECT_GL_ERROR(GL_NO_ERROR);
+
+    GLint textureBinding;
+    glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_EQ(0, textureBinding);
+
+    glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &textureBinding);
+    if (extensionEnabled("GL_OES_EGL_image_external") ||
+        extensionEnabled("GL_NV_EGL_stream_consumer_external"))
+    {
+        EXPECT_GL_NO_ERROR();
+        EXPECT_EQ(0, textureBinding);
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+}
+
+TEST_P(Texture2DTest, ZeroSizedUploads)
+{
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    EXPECT_GL_ERROR(GL_NO_ERROR);
+
+    setUpProgram();
+
+    // Use the texture first to make sure it's in video memory
+    glUseProgram(mProgram);
+    glUniform1i(mTexture2DUniformLocation, 0);
+    drawQuad(mProgram, "position", 0.5f);
+
+    const GLubyte *pixel[4] = { 0 };
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    EXPECT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    EXPECT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test drawing with two texture types, to trigger an ANGLE bug in validation
+TEST_P(TextureCubeTest, CubeMapBug)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
+    EXPECT_GL_ERROR(GL_NO_ERROR);
+
+    glUseProgram(mProgram);
+    glUniform1i(mTexture2DUniformLocation, 0);
+    glUniform1i(mTextureCubeUniformLocation, 1);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test drawing with two texture types accessed from the same shader and check that the result of
+// drawing is correct.
+TEST_P(TextureCubeTest, CubeMapDraw)
+{
+    GLubyte texData[4];
+    texData[0] = 0;
+    texData[1] = 60;
+    texData[2] = 0;
+    texData[3] = 255;
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
+
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
+    texData[1] = 120;
+    glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+                    texData);
+    EXPECT_GL_ERROR(GL_NO_ERROR);
+
+    glUseProgram(mProgram);
+    glUniform1i(mTexture2DUniformLocation, 0);
+    glUniform1i(mTextureCubeUniformLocation, 1);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+
+    int px = getWindowWidth() - 1;
+    int py = 0;
+    EXPECT_PIXEL_NEAR(px, py, 0, 180, 0, 255, 2);
+}
+
+TEST_P(Sampler2DAsFunctionParameterTest, Sampler2DAsFunctionParameter)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    GLubyte texData[4];
+    texData[0] = 0;
+    texData[1] = 128;
+    texData[2] = 0;
+    texData[3] = 255;
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
+    glUseProgram(mProgram);
+    glUniform1i(mTexture2DUniformLocation, 0);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_NEAR(0, 0, 0, 128, 0, 255, 2);
+}
+
+// Test drawing with two textures passed to the shader in a sampler array.
+TEST_P(SamplerArrayTest, SamplerArrayDraw)
+{
+    testSamplerArrayDraw();
+}
+
+// Test drawing with two textures passed to the shader in a sampler array which is passed to a
+// user-defined function in the shader.
+TEST_P(SamplerArrayAsFunctionParameterTest, SamplerArrayAsFunctionParameter)
+{
+    testSamplerArrayDraw();
+}
+
+// Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
+TEST_P(Texture2DTestWithDrawScale, MipmapsTwice)
+{
+    int px = getWindowWidth() / 2;
+    int py = getWindowHeight() / 2;
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+
+    std::vector<GLColor> pixelsRed(16u * 16u, GLColor::red);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    glUseProgram(mProgram);
+    glUniform1i(mTexture2DUniformLocation, 0);
+    glUniform2f(mDrawScaleUniformLocation, 0.0625f, 0.0625f);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
+
+    std::vector<GLColor> pixelsBlue(16u * 16u, GLColor::blue);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 pixelsBlue.data());
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    std::vector<GLColor> pixelsGreen(16u * 16u, GLColor::green);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 pixelsGreen.data());
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
+}
+
+// Test creating a FBO with a cube map render target, to test an ANGLE bug
+// https://code.google.com/p/angleproject/issues/detail?id=849
+TEST_P(TextureCubeTest, CubeMapFBO)
+{
+    GLuint fbo;
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mTextureCube, 0);
+
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    glDeleteFramebuffers(1, &fbo);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a default color.
+TEST_P(Texture2DTest, TexStorage)
+{
+    if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage"))
+    {
+        std::cout << "Test skipped because ES3 or GL_EXT_texture_storage not available."
+                  << std::endl;
+        return;
+    }
+
+    int width = getWindowWidth();
+    int height = getWindowHeight();
+
+    GLuint tex2D;
+    glGenTextures(1, &tex2D);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, tex2D);
+
+    // Fill with red
+    std::vector<GLubyte> pixels(3 * 16 * 16);
+    for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
+    {
+        pixels[pixelId * 3 + 0] = 255;
+        pixels[pixelId * 3 + 1] = 0;
+        pixels[pixelId * 3 + 2] = 0;
+    }
+
+    // ANGLE internally uses RGBA as the DirectX format for RGB images
+    // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
+    // The data is kept in a CPU-side image and the image is marked as dirty.
+    if (getClientMajorVersion() >= 3)
+    {
+        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
+    }
+    else
+    {
+        glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
+    }
+
+    // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
+    // glTexSubImage2D should take into account that the image is dirty.
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    setUpProgram();
+
+    glUseProgram(mProgram);
+    glUniform1i(mTexture2DUniformLocation, 0);
+    drawQuad(mProgram, "position", 0.5f);
+    glDeleteTextures(1, &tex2D);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
+
+    // Validate that the region of the texture without data has an alpha of 1.0
+    GLubyte pixel[4];
+    glReadPixels(3 * width / 4, 3 * height / 4, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    EXPECT_EQ(pixel[3], 255);
+}
+
+// Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has initialized the image with a default color.
+TEST_P(Texture2DTest, TexStorageWithPBO)
+{
+    if (extensionEnabled("NV_pixel_buffer_object"))
+    {
+        int width = getWindowWidth();
+        int height = getWindowHeight();
+
+        GLuint tex2D;
+        glGenTextures(1, &tex2D);
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, tex2D);
+
+        // Fill with red
+        std::vector<GLubyte> pixels(3 * 16 * 16);
+        for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
+        {
+            pixels[pixelId * 3 + 0] = 255;
+            pixels[pixelId * 3 + 1] = 0;
+            pixels[pixelId * 3 + 2] = 0;
+        }
+
+        // Read 16x16 region from red backbuffer to PBO
+        GLuint pbo;
+        glGenBuffers(1, &pbo);
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
+        glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
+
+        // ANGLE internally uses RGBA as the DirectX format for RGB images
+        // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
+        // The data is kept in a CPU-side image and the image is marked as dirty.
+        glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
+
+        // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
+        // glTexSubImage2D should take into account that the image is dirty.
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+        setUpProgram();
+
+        glUseProgram(mProgram);
+        glUniform1i(mTexture2DUniformLocation, 0);
+        drawQuad(mProgram, "position", 0.5f);
+        glDeleteTextures(1, &tex2D);
+        glDeleteBuffers(1, &pbo);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
+        EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
+    }
+}
+
+// See description on testFloatCopySubImage
+TEST_P(Texture2DTest, CopySubImageFloat_R_R)
+{
+    testFloatCopySubImage(1, 1);
+}
+
+TEST_P(Texture2DTest, CopySubImageFloat_RG_R)
+{
+    testFloatCopySubImage(2, 1);
+}
+
+TEST_P(Texture2DTest, CopySubImageFloat_RG_RG)
+{
+    testFloatCopySubImage(2, 2);
+}
+
+TEST_P(Texture2DTest, CopySubImageFloat_RGB_R)
+{
+    if (IsIntel() && IsLinux())
+    {
+        // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/1346)
+        std::cout << "Test disabled on Linux Intel OpenGL." << std::endl;
+        return;
+    }
+
+    testFloatCopySubImage(3, 1);
+}
+
+TEST_P(Texture2DTest, CopySubImageFloat_RGB_RG)
+{
+    if (IsIntel() && IsLinux())
+    {
+        // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/1346)
+        std::cout << "Test disabled on Linux Intel OpenGL." << std::endl;
+        return;
+    }
+
+    testFloatCopySubImage(3, 2);
+}
+
+TEST_P(Texture2DTest, CopySubImageFloat_RGB_RGB)
+{
+    if (IsIntel() && IsLinux())
+    {
+        // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/1346)
+        std::cout << "Test disabled on Linux Intel OpenGL." << std::endl;
+        return;
+    }
+
+    // TODO (bug 1284): Investigate RGBA32f D3D SDK Layers messages on D3D11_FL9_3
+    if (IsD3D11_FL93())
+    {
+        std::cout << "Test skipped on Feature Level 9_3." << std::endl;
+        return;
+    }
+
+    testFloatCopySubImage(3, 3);
+}
+
+TEST_P(Texture2DTest, CopySubImageFloat_RGBA_R)
+{
+    testFloatCopySubImage(4, 1);
+}
+
+TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RG)
+{
+    testFloatCopySubImage(4, 2);
+}
+
+TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGB)
+{
+    // TODO (bug 1284): Investigate RGBA32f D3D SDK Layers messages on D3D11_FL9_3
+    if (IsD3D11_FL93())
+    {
+        std::cout << "Test skipped on Feature Level 9_3." << std::endl;
+        return;
+    }
+
+    testFloatCopySubImage(4, 3);
+}
+
+TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGBA)
+{
+    // TODO (bug 1284): Investigate RGBA32f D3D SDK Layers messages on D3D11_FL9_3
+    if (IsD3D11_FL93())
+    {
+        std::cout << "Test skipped on Feature Level 9_3." << std::endl;
+        return;
+    }
+
+    testFloatCopySubImage(4, 4);
+}
+
+// Port of https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html
+// Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly handles GL_ALPHA
+TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE)
+{
+    const int npotTexSize = 5;
+    const int potTexSize = 4; // Should be less than npotTexSize
+    GLuint tex2D;
+
+    if (extensionEnabled("GL_OES_texture_npot"))
+    {
+        // This test isn't applicable if texture_npot is enabled
+        return;
+    }
+
+    setUpProgram();
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    // Default unpack alignment is 4. The values of 'pixels' below needs it to be 1.
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+    glActiveTexture(GL_TEXTURE0);
+    glGenTextures(1, &tex2D);
+    glBindTexture(GL_TEXTURE_2D, tex2D);
+
+    std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize);
+    for (size_t pixelId = 0; pixelId < npotTexSize * npotTexSize; ++pixelId)
+    {
+        pixels[pixelId] = 64;
+    }
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    // Check that an NPOT texture not on level 0 generates INVALID_VALUE
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    // Check that an NPOT texture on level 0 succeeds
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
+    EXPECT_GL_NO_ERROR();
+
+    // Check that generateMipmap fails on NPOT
+    glGenerateMipmap(GL_TEXTURE_2D);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Check that nothing is drawn if filtering is not correct for NPOT
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    glClear(GL_COLOR_BUFFER_BIT);
+    drawQuad(mProgram, "position", 1.0f);
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
+
+    // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
+    glClear(GL_COLOR_BUFFER_BIT);
+    drawQuad(mProgram, "position", 1.0f);
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
+
+    // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glClear(GL_COLOR_BUFFER_BIT);
+    drawQuad(mProgram, "position", 1.0f);
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
+
+    // Check that glTexImage2D for POT texture succeeds
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
+    EXPECT_GL_NO_ERROR();
+
+    // Check that generateMipmap for an POT texture succeeds
+    glGenerateMipmap(GL_TEXTURE_2D);
+    EXPECT_GL_NO_ERROR();
+
+    // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    glClear(GL_COLOR_BUFFER_BIT);
+    drawQuad(mProgram, "position", 1.0f);
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test to ensure that glTexSubImage2D always accepts data for non-power-of-two subregions.
+// ANGLE previously rejected this if GL_OES_texture_npot wasn't active, which is incorrect.
+TEST_P(Texture2DTest, NPOTSubImageParameters)
+{
+    // TODO(geofflang): Allow the GL backend to accept SubImage calls with a null data ptr. (bug
+    // 1278)
+    if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
+        getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+    {
+        std::cout << "Test disabled on OpenGL." << std::endl;
+        return;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+
+    // Create an 8x8 (i.e. power-of-two) texture.
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glGenerateMipmap(GL_TEXTURE_2D);
+
+    // Supply a 3x3 (i.e. non-power-of-two) subimage to the texture.
+    // This should always work, even if GL_OES_texture_npot isn't active.
+    glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test to check that texture completeness is determined correctly when the texture base level is
+// greater than 0, and also that level 0 is not sampled when base level is greater than 0.
+TEST_P(Texture2DTestES3, DrawWithBaseLevel1)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+
+    std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
+    std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
+// have images defined.
+TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeUndefined)
+{
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
+        std::cout << "Test skipped on AMD OpenGL." << std::endl;
+        return;
+    }
+    if (IsOSX())
+    {
+        // Observed incorrect rendering on OSX.
+        std::cout << "Test skipped on OSX." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that drawing works correctly when level 0 is undefined and base level is 1.
+TEST_P(Texture2DTestES3, DrawWithLevelZeroUndefined)
+{
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
+        std::cout << "Test skipped on AMD OpenGL." << std::endl;
+        return;
+    }
+    if (IsOSX())
+    {
+        // Observed incorrect rendering on OSX.
+        std::cout << "Test skipped on OSX." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Texture is incomplete.
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
+
+    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    // Texture is now complete.
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
+// dimensions that don't fit the images inside the range.
+// GLES 3.0.4 section 3.8.13 Texture completeness
+TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
+{
+    if (IsOSX())
+    {
+        // Observed incorrect rendering on OSX.
+        std::cout << "Test skipped on OSX." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    std::vector<GLColor> texDataRed(8u * 8u, GLColor::red);
+    std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
+    std::vector<GLColor> texDataCyan(2u * 2u, GLColor::cyan);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+    // Two levels that are initially unused.
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
+    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataCyan.data());
+
+    // One level that is used - only this level should affect completeness.
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // Intel was observed drawing color 0,0,0,0 instead of the texture color after the base
+        // level was changed.
+        std::cout << "Test partially skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    // Switch the level that is being used to the cyan level 2.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
+}
+
+// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
+// have images defined.
+TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeUndefined)
+{
+    if (IsOSX())
+    {
+        // Observed incorrect rendering on OSX.
+        std::cout << "Test skipped on OSX." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_3D, mTexture3D);
+    std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
+    glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
+// dimensions that don't fit the images inside the range.
+// GLES 3.0.4 section 3.8.13 Texture completeness
+TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
+{
+    if (IsOSX())
+    {
+        // Observed incorrect rendering on OSX.
+        std::cout << "Test skipped on OSX." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_3D, mTexture3D);
+    std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
+    std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
+    std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
+
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+    // Two levels that are initially unused.
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataRed.data());
+    glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataCyan.data());
+
+    // One level that is used - only this level should affect completeness.
+    glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // Intel was observed drawing color 0,0,0,0 instead of the texture color after the base
+        // level was changed.
+        std::cout << "Test partially skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    // Switch the level that is being used to the cyan level 2.
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 2);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 2);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
+}
+
+// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
+// have images defined.
+TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeUndefined)
+{
+    if (IsOSX())
+    {
+        // Observed incorrect rendering on OSX.
+        std::cout << "Test skipped on OSX." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+    std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
+    glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
+// dimensions that don't fit the images inside the range.
+// GLES 3.0.4 section 3.8.13 Texture completeness
+TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
+{
+    if (IsOSX())
+    {
+        // Observed incorrect rendering on OSX.
+        std::cout << "Test skipped on OSX." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_3D, m2DArrayTexture);
+    std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
+    std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
+    std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
+
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+    // Two levels that are initially unused.
+    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataRed.data());
+    glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataCyan.data());
+
+    // One level that is used - only this level should affect completeness.
+    glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // Intel was observed drawing color 0,0,0,0 instead of the texture color after the base
+        // level was changed.
+        std::cout << "Test partially skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+    if (IsNVIDIA() && (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
+                       getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE))
+    {
+        // NVIDIA was observed drawing color 0,0,0,0 instead of the texture color after the base
+        // level was changed.
+        std::cout << "Test partially skipped on NVIDIA OpenGL." << std::endl;
+        return;
+    }
+
+    // Switch the level that is being used to the cyan level 2.
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 2);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 2);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
+}
+
+// Test that texture completeness is updated if texture max level changes.
+// GLES 3.0.4 section 3.8.13 Texture completeness
+TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
+{
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // Intel was observed having wrong behavior after the texture is made incomplete by changing
+        // the base level.
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+    if (IsOSX())
+    {
+        // Observed incorrect rendering on OSX.
+        std::cout << "Test skipped on OSX." << std::endl;
+        return;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+    // A level that is initially unused.
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    // One level that is initially used - only this level should affect completeness.
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Switch the max level to level 1. The levels within the used range now have inconsistent
+    // dimensions and the texture should be incomplete.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
+}
+
+// Test that 3D texture completeness is updated if texture max level changes.
+// GLES 3.0.4 section 3.8.13 Texture completeness
+TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel)
+{
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // Intel was observed having wrong behavior after the texture is made incomplete by changing
+        // the base level.
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+    if (IsOSX())
+    {
+        // Observed incorrect rendering on OSX.
+        std::cout << "Test skipped on OSX." << std::endl;
+        return;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_3D, mTexture3D);
+    std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
+
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+    // A level that is initially unused.
+    glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    // One level that is initially used - only this level should affect completeness.
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Switch the max level to level 1. The levels within the used range now have inconsistent
+    // dimensions and the texture should be incomplete.
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
+}
+
+// Test that texture completeness is updated if texture base level changes.
+// GLES 3.0.4 section 3.8.13 Texture completeness
+TEST_P(Texture2DTestES3, TextureCompletenessChangesWithBaseLevel)
+{
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // Intel was observed having wrong behavior after the texture is made incomplete by changing
+        // the base level.
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+    // Two levels that are initially unused.
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    // One level that is initially used - only this level should affect completeness.
+    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataGreen.data());
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Switch the base level to level 1. The levels within the used range now have inconsistent
+    // dimensions and the texture should be incomplete.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
+}
+
+// Test that texture is not complete if base level is greater than max level.
+// GLES 3.0.4 section 3.8.13 Texture completeness
+TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMaxLevel)
+{
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        // Intel Windows OpenGL driver crashes if the base level of a non-immutable texture is out
+        // of range.
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    // Texture should be incomplete.
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
+}
+
+// Test that immutable texture base level and max level are clamped.
+// GLES 3.0.4 section 3.8.10 subsection Mipmapping
+TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
+
+    // For immutable-format textures, base level should be clamped to [0, levels - 1], and max level
+    // should be clamped to [base_level, levels - 1].
+    // GLES 3.0.4 section 3.8.10 subsection Mipmapping
+    // In the case of this test, those rules make the effective base level and max level 0.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    // Texture should be complete.
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that changing base level works when it affects the format of the texture.
+TEST_P(Texture2DTestES3, TextureFormatChangesWithBaseLevel)
+{
+    if (IsNVIDIA() && IsOpenGL())
+    {
+        // Observed rendering corruption on NVIDIA OpenGL.
+        std::cout << "Test skipped on NVIDIA OpenGL." << std::endl;
+        return;
+    }
+    if (IsIntel() && IsDesktopOpenGL())
+    {
+        // Observed incorrect rendering on Intel OpenGL.
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+    if (IsAMD() && IsDesktopOpenGL())
+    {
+        // Observed incorrect rendering on AMD OpenGL.
+        std::cout << "Test skipped on AMD OpenGL." << std::endl;
+        return;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    std::vector<GLColor> texDataCyan(4u * 4u, GLColor::cyan);
+    std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+    // RGBA8 level that's initially unused.
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 texDataCyan.data());
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
+
+    // RG8 level that's initially used, with consistent dimensions with level 0 but a different
+    // format. It reads green channel data from the green and alpha channels of texDataGreen
+    // (this is a bit hacky but works).
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RG8, 2, 2, 0, GL_RG, GL_UNSIGNED_BYTE, texDataGreen.data());
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Switch the texture to use the cyan level 0 with the RGBA format.
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
+}
+
+// Test that setting a texture image works when base level is out of range.
+TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
+
+    EXPECT_GL_NO_ERROR();
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    // Texture should be complete.
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG RBA->RGBA8, with 1.0
+// in the alpha channel. This test covers a bug where redefining array textures with these formats does not work as
+// expected.
+TEST_P(Texture2DArrayTestES3, RedefineInittableArray)
+{
+    std::vector<GLubyte> pixelData;
+    for (size_t count = 0; count < 5000; count++)
+    {
+        pixelData.push_back(0u);
+        pixelData.push_back(255u);
+        pixelData.push_back(0u);
+    }
+
+    glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
+    glUseProgram(mProgram);
+    glUniform1i(mTextureArrayLocation, 0);
+
+    // The first draw worked correctly.
+    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixelData[0]);
+
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    drawQuad(mProgram, "position", 1.0f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // The dimension of the respecification must match the original exactly to trigger the bug.
+    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixelData[0]);
+    drawQuad(mProgram, "position", 1.0f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test shadow sampler and regular non-shadow sampler coexisting in the same shader.
+// This test is needed especially to confirm that sampler registers get assigned correctly on
+// the HLSL backend even when there's a mix of different HLSL sampler and texture types.
+TEST_P(ShadowSamplerPlusSampler3DTestES3, ShadowSamplerPlusSampler3DDraw)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_3D, mTexture3D);
+    GLubyte texData[4];
+    texData[0] = 0;
+    texData[1] = 60;
+    texData[2] = 0;
+    texData[3] = 255;
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
+
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, mTextureShadow);
+    GLfloat depthTexData[1];
+    depthTexData[0] = 0.5f;
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
+                 depthTexData);
+
+    glUseProgram(mProgram);
+    glUniform1f(mDepthRefUniformLocation, 0.3f);
+    glUniform1i(mTexture3DUniformLocation, 0);
+    glUniform1i(mTextureShadowUniformLocation, 1);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    // The shader writes 0.5 * <comparison result (1.0)> + <texture color>
+    EXPECT_PIXEL_NEAR(0, 0, 128, 188, 128, 255, 2);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    // The shader writes 0.5 * <comparison result (0.0)> + <texture color>
+    EXPECT_PIXEL_NEAR(0, 0, 0, 60, 0, 255, 2);
+}
+
+// Test multiple different sampler types in the same shader.
+// This test makes sure that even if sampler / texture registers get grouped together based on type
+// or otherwise get shuffled around in the HLSL backend of the shader translator, the D3D renderer
+// still has the right register index information for each ESSL sampler.
+// The tested ESSL samplers have the following types in D3D11 HLSL:
+// sampler2D:         Texture2D   + SamplerState
+// samplerCube:       TextureCube + SamplerState
+// sampler2DShadow:   Texture2D   + SamplerComparisonState
+// samplerCubeShadow: TextureCube + SamplerComparisonState
+TEST_P(SamplerTypeMixTestES3, SamplerTypeMixDraw)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    GLubyte texData[4];
+    texData[0] = 0;
+    texData[1] = 0;
+    texData[2] = 120;
+    texData[3] = 255;
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
+
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
+    texData[0] = 0;
+    texData[1] = 90;
+    texData[2] = 0;
+    texData[3] = 255;
+    glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
+    glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+                    texData);
+
+    glActiveTexture(GL_TEXTURE2);
+    glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+    GLfloat depthTexData[1];
+    depthTexData[0] = 0.5f;
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
+                 depthTexData);
+
+    glActiveTexture(GL_TEXTURE3);
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+    depthTexData[0] = 0.2f;
+    glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT32F, 1, 1);
+    glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT,
+                    depthTexData);
+
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mProgram);
+    glUniform1f(mDepthRefUniformLocation, 0.3f);
+    glUniform1i(mTexture2DUniformLocation, 0);
+    glUniform1i(mTextureCubeUniformLocation, 1);
+    glUniform1i(mTexture2DShadowUniformLocation, 2);
+    glUniform1i(mTextureCubeShadowUniformLocation, 3);
+
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    // The shader writes:
+    // <texture 2d color> +
+    // <cube map color> +
+    // 0.25 * <comparison result (1.0)> +
+    // 0.125 * <comparison result (0.0)>
+    EXPECT_PIXEL_NEAR(0, 0, 64, 154, 184, 255, 2);
+}
+
+// Test different base levels on textures accessed through the same sampler array.
+// Calling textureSize() on the samplers hits the D3D sampler metadata workaround.
+TEST_P(TextureSizeTextureArrayTest, BaseLevelVariesInTextureArray)
+{
+    if ((IsAMD() || IsIntel()) && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel and AMD D3D." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2DA);
+    GLsizei size = 64;
+    for (GLint level = 0; level < 7; ++level)
+    {
+        ASSERT_LT(0, size);
+        glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+        size = size / 2;
+    }
+    ASSERT_EQ(0, size);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
+
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, mTexture2DB);
+    size = 128;
+    for (GLint level = 0; level < 8; ++level)
+    {
+        ASSERT_LT(0, size);
+        glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     nullptr);
+        size = size / 2;
+    }
+    ASSERT_EQ(0, size);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 3);
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(mProgram);
+    glUniform1i(mTexture0Location, 0);
+    glUniform1i(mTexture1Location, 1);
+
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    // Red channel: width of level 1 of texture A: 32.
+    // Green channel: width of level 3 of texture B: 16.
+    EXPECT_PIXEL_NEAR(0, 0, 32, 16, 0, 255, 2);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DTestES3, TextureRGBImplicitAlpha1)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DTestES3, TextureLuminanceImplicitAlpha1)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DTestES3, TextureLuminance32ImplicitAlpha1)
+{
+    if (extensionEnabled("GL_OES_texture_float"))
+    {
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTexture2D);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_FLOAT, nullptr);
+        EXPECT_GL_NO_ERROR();
+
+        drawQuad(mProgram, "position", 0.5f);
+
+        EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+    }
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DTestES3, TextureLuminance16ImplicitAlpha1)
+{
+    if (extensionEnabled("GL_OES_texture_half_float"))
+    {
+        if (IsNVIDIA() && IsOpenGLES())
+        {
+            std::cout << "Test skipped on NVIDIA" << std::endl;
+            return;
+        }
+        // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1420 is fixed
+        if (IsAndroid() && IsAdreno() && IsOpenGLES())
+        {
+            std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
+            return;
+        }
+
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, mTexture2D);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES,
+                     nullptr);
+        EXPECT_GL_NO_ERROR();
+
+        drawQuad(mProgram, "position", 0.5f);
+
+        EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+    }
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB8UIImplicitAlpha1)
+{
+    if (IsIntel())
+    {
+        std::cout << "Test disabled on Intel." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB8IImplicitAlpha1)
+{
+    if (IsIntel())
+    {
+        std::cout << "Test disabled on Intel." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8I, 1, 1, 0, GL_RGB_INTEGER, GL_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB16UIImplicitAlpha1)
+{
+    if (IsIntel())
+    {
+        std::cout << "Test disabled on Intel." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB16IImplicitAlpha1)
+{
+    if (IsIntel())
+    {
+        std::cout << "Test disabled on Intel." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16I, 1, 1, 0, GL_RGB_INTEGER, GL_SHORT, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB32UIImplicitAlpha1)
+{
+    if (IsIntel())
+    {
+        std::cout << "Test disabled on Intel." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB32IImplicitAlpha1)
+{
+    if (IsIntel())
+    {
+        std::cout << "Test disabled on Intel." << std::endl;
+        return;
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DTestES3, TextureRGBSNORMImplicitAlpha1)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8_SNORM, 1, 1, 0, GL_RGB, GL_BYTE, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DTestES3, TextureRGB9E5ImplicitAlpha1)
+{
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV,
+                 nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DTestES3, TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)
+{
+    if (IsOSX() && IsIntel() && IsOpenGL())
+    {
+        // Seems to fail on OSX 10.12 Intel.
+        std::cout << "Test skipped on OSX Intel." << std::endl;
+        return;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 1, 1, 0, 8, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// When sampling a texture without an alpha channel, "1" is returned as the alpha value.
+// ES 3.0.4 table 3.24
+TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)
+{
+    if (IsIntel() && IsOpenGL() && (IsLinux() || IsOSX()))
+    {
+        // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/1346)
+        // Also seems to fail on OSX 10.12 Intel.
+        std::cout << "Test disabled on Linux and OSX Intel OpenGL." << std::endl;
+        return;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, 1, 1, 0, 8, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
+}
+
+// Use a sampler in a uniform struct.
+TEST_P(SamplerInStructTest, SamplerInStruct)
+{
+    runSamplerInStructTest();
+}
+
+// Use a sampler in a uniform struct that's passed as a function parameter.
+TEST_P(SamplerInStructAsFunctionParameterTest, SamplerInStructAsFunctionParameter)
+{
+    // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1427 is fixed
+    if (IsAndroid() && IsAdreno() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
+        return;
+    }
+
+    if (IsWindows() && IsIntel() && IsOpenGL())
+    {
+        std::cout << "Test skipped on Windows OpenGL on Intel." << std::endl;
+        return;
+    }
+
+    runSamplerInStructTest();
+}
+
+// Use a sampler in a uniform struct array with a struct from the array passed as a function
+// parameter.
+TEST_P(SamplerInStructArrayAsFunctionParameterTest, SamplerInStructArrayAsFunctionParameter)
+{
+    if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+    // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1427 is fixed
+    if (IsAndroid() && IsAdreno() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
+        return;
+    }
+    runSamplerInStructTest();
+}
+
+// Use a sampler in a struct inside a uniform struct with the nested struct passed as a function
+// parameter.
+TEST_P(SamplerInNestedStructAsFunctionParameterTest, SamplerInNestedStructAsFunctionParameter)
+{
+    if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+    // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1427 is fixed
+    if (IsAndroid() && IsAdreno() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
+        return;
+    }
+    runSamplerInStructTest();
+}
+
+// Make sure that there isn't a name conflict between sampler extracted from a struct and a
+// similarly named uniform.
+TEST_P(SamplerInStructAndOtherVariableTest, SamplerInStructAndOtherVariable)
+{
+    runSamplerInStructTest();
+}
+
+class TextureLimitsTest : public ANGLETest
+{
+  protected:
+    struct RGBA8
+    {
+        uint8_t R, G, B, A;
+    };
+
+    TextureLimitsTest()
+        : mProgram(0), mMaxVertexTextures(0), mMaxFragmentTextures(0), mMaxCombinedTextures(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    ~TextureLimitsTest()
+    {
+        if (mProgram != 0)
+        {
+            glDeleteProgram(mProgram);
+            mProgram = 0;
+
+            if (!mTextures.empty())
+            {
+                glDeleteTextures(static_cast<GLsizei>(mTextures.size()), &mTextures[0]);
+            }
+        }
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mMaxVertexTextures);
+        glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mMaxFragmentTextures);
+        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxCombinedTextures);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void compileProgramWithTextureCounts(const std::string &vertexPrefix,
+                                         GLint vertexTextureCount,
+                                         GLint vertexActiveTextureCount,
+                                         const std::string &fragPrefix,
+                                         GLint fragmentTextureCount,
+                                         GLint fragmentActiveTextureCount)
+    {
+        std::stringstream vertexShaderStr;
+        vertexShaderStr << "attribute vec2 position;\n"
+                        << "varying vec4 color;\n"
+                        << "varying vec2 texCoord;\n";
+
+        for (GLint textureIndex = 0; textureIndex < vertexTextureCount; ++textureIndex)
+        {
+            vertexShaderStr << "uniform sampler2D " << vertexPrefix << textureIndex << ";\n";
+        }
+
+        vertexShaderStr << "void main() {\n"
+                        << "  gl_Position = vec4(position, 0, 1);\n"
+                        << "  texCoord = (position * 0.5) + 0.5;\n"
+                        << "  color = vec4(0);\n";
+
+        for (GLint textureIndex = 0; textureIndex < vertexActiveTextureCount; ++textureIndex)
+        {
+            vertexShaderStr << "  color += texture2D(" << vertexPrefix << textureIndex
+                            << ", texCoord);\n";
+        }
+
+        vertexShaderStr << "}";
+
+        std::stringstream fragmentShaderStr;
+        fragmentShaderStr << "varying mediump vec4 color;\n"
+                          << "varying mediump vec2 texCoord;\n";
+
+        for (GLint textureIndex = 0; textureIndex < fragmentTextureCount; ++textureIndex)
+        {
+            fragmentShaderStr << "uniform sampler2D " << fragPrefix << textureIndex << ";\n";
+        }
+
+        fragmentShaderStr << "void main() {\n"
+                          << "  gl_FragColor = color;\n";
+
+        for (GLint textureIndex = 0; textureIndex < fragmentActiveTextureCount; ++textureIndex)
+        {
+            fragmentShaderStr << "  gl_FragColor += texture2D(" << fragPrefix << textureIndex
+                              << ", texCoord);\n";
+        }
+
+        fragmentShaderStr << "}";
+
+        const std::string &vertexShaderSource   = vertexShaderStr.str();
+        const std::string &fragmentShaderSource = fragmentShaderStr.str();
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    }
+
+    RGBA8 getPixel(GLint texIndex)
+    {
+        RGBA8 pixel = {static_cast<uint8_t>(texIndex & 0x7u), static_cast<uint8_t>(texIndex >> 3),
+                       0, 255u};
+        return pixel;
+    }
+
+    void initTextures(GLint tex2DCount, GLint texCubeCount)
+    {
+        GLint totalCount = tex2DCount + texCubeCount;
+        mTextures.assign(totalCount, 0);
+        glGenTextures(totalCount, &mTextures[0]);
+        ASSERT_GL_NO_ERROR();
+
+        std::vector<RGBA8> texData(16 * 16);
+
+        GLint texIndex = 0;
+        for (; texIndex < tex2DCount; ++texIndex)
+        {
+            texData.assign(texData.size(), getPixel(texIndex));
+            glActiveTexture(GL_TEXTURE0 + texIndex);
+            glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                         &texData[0]);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        }
+
+        ASSERT_GL_NO_ERROR();
+
+        for (; texIndex < texCubeCount; ++texIndex)
+        {
+            texData.assign(texData.size(), getPixel(texIndex));
+            glActiveTexture(GL_TEXTURE0 + texIndex);
+            glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[texIndex]);
+            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
+                         GL_UNSIGNED_BYTE, &texData[0]);
+            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
+                         GL_UNSIGNED_BYTE, &texData[0]);
+            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
+                         GL_UNSIGNED_BYTE, &texData[0]);
+            glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
+                         GL_UNSIGNED_BYTE, &texData[0]);
+            glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
+                         GL_UNSIGNED_BYTE, &texData[0]);
+            glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
+                         GL_UNSIGNED_BYTE, &texData[0]);
+            glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        }
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void testWithTextures(GLint vertexTextureCount,
+                          const std::string &vertexTexturePrefix,
+                          GLint fragmentTextureCount,
+                          const std::string &fragmentTexturePrefix)
+    {
+        // Generate textures
+        initTextures(vertexTextureCount + fragmentTextureCount, 0);
+
+        glUseProgram(mProgram);
+        RGBA8 expectedSum = {0};
+        for (GLint texIndex = 0; texIndex < vertexTextureCount; ++texIndex)
+        {
+            std::stringstream uniformNameStr;
+            uniformNameStr << vertexTexturePrefix << texIndex;
+            const std::string &uniformName = uniformNameStr.str();
+            GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
+            ASSERT_NE(-1, location);
+
+            glUniform1i(location, texIndex);
+            RGBA8 contribution = getPixel(texIndex);
+            expectedSum.R += contribution.R;
+            expectedSum.G += contribution.G;
+        }
+
+        for (GLint texIndex = 0; texIndex < fragmentTextureCount; ++texIndex)
+        {
+            std::stringstream uniformNameStr;
+            uniformNameStr << fragmentTexturePrefix << texIndex;
+            const std::string &uniformName = uniformNameStr.str();
+            GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
+            ASSERT_NE(-1, location);
+
+            glUniform1i(location, texIndex + vertexTextureCount);
+            RGBA8 contribution = getPixel(texIndex + vertexTextureCount);
+            expectedSum.R += contribution.R;
+            expectedSum.G += contribution.G;
+        }
+
+        ASSERT_GE(256u, expectedSum.G);
+
+        drawQuad(mProgram, "position", 0.5f);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_PIXEL_EQ(0, 0, expectedSum.R, expectedSum.G, 0, 255);
+    }
+
+    GLuint mProgram;
+    std::vector<GLuint> mTextures;
+    GLint mMaxVertexTextures;
+    GLint mMaxFragmentTextures;
+    GLint mMaxCombinedTextures;
+};
+
+// Test rendering with the maximum vertex texture units.
+TEST_P(TextureLimitsTest, MaxVertexTextures)
+{
+    // TODO(jmadill): Figure out why this fails on Intel.
+    if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel." << std::endl;
+        return;
+    }
+
+    compileProgramWithTextureCounts("tex", mMaxVertexTextures, mMaxVertexTextures, "tex", 0, 0);
+    ASSERT_NE(0u, mProgram);
+    ASSERT_GL_NO_ERROR();
+
+    testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
+}
+
+// Test rendering with the maximum fragment texture units.
+TEST_P(TextureLimitsTest, MaxFragmentTextures)
+{
+    // TODO(jmadill): Figure out why this fails on Intel.
+    if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel." << std::endl;
+        return;
+    }
+
+    compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures, mMaxFragmentTextures);
+    ASSERT_NE(0u, mProgram);
+    ASSERT_GL_NO_ERROR();
+
+    testWithTextures(mMaxFragmentTextures, "tex", 0, "tex");
+}
+
+// Test rendering with maximum combined texture units.
+TEST_P(TextureLimitsTest, MaxCombinedTextures)
+{
+    // TODO(jmadill): Investigate workaround.
+    if (IsIntel() && GetParam() == ES2_OPENGL())
+    {
+        std::cout << "Test skipped on Intel." << std::endl;
+        return;
+    }
+
+    GLint vertexTextures = mMaxVertexTextures;
+
+    if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
+    {
+        vertexTextures = mMaxCombinedTextures - mMaxFragmentTextures;
+    }
+
+    compileProgramWithTextureCounts("vtex", vertexTextures, vertexTextures, "ftex",
+                                    mMaxFragmentTextures, mMaxFragmentTextures);
+    ASSERT_NE(0u, mProgram);
+    ASSERT_GL_NO_ERROR();
+
+    testWithTextures(vertexTextures, "vtex", mMaxFragmentTextures, "ftex");
+}
+
+// Negative test for exceeding the number of vertex textures
+TEST_P(TextureLimitsTest, ExcessiveVertexTextures)
+{
+    compileProgramWithTextureCounts("tex", mMaxVertexTextures + 1, mMaxVertexTextures + 1, "tex", 0,
+                                    0);
+    ASSERT_EQ(0u, mProgram);
+}
+
+// Negative test for exceeding the number of fragment textures
+TEST_P(TextureLimitsTest, ExcessiveFragmentTextures)
+{
+    compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 1,
+                                    mMaxFragmentTextures + 1);
+    ASSERT_EQ(0u, mProgram);
+}
+
+// Test active vertex textures under the limit, but excessive textures specified.
+TEST_P(TextureLimitsTest, MaxActiveVertexTextures)
+{
+    // TODO(jmadill): Figure out why this fails on Intel.
+    if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel." << std::endl;
+        return;
+    }
+
+    compileProgramWithTextureCounts("tex", mMaxVertexTextures + 4, mMaxVertexTextures, "tex", 0, 0);
+    ASSERT_NE(0u, mProgram);
+    ASSERT_GL_NO_ERROR();
+
+    testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
+}
+
+// Test active fragment textures under the limit, but excessive textures specified.
+TEST_P(TextureLimitsTest, MaxActiveFragmentTextures)
+{
+    // TODO(jmadill): Figure out why this fails on Intel.
+    if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel." << std::endl;
+        return;
+    }
+
+    compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 4,
+                                    mMaxFragmentTextures);
+    ASSERT_NE(0u, mProgram);
+    ASSERT_GL_NO_ERROR();
+
+    testWithTextures(0, "tex", mMaxFragmentTextures, "tex");
+}
+
+// Negative test for pointing two sampler uniforms of different types to the same texture.
+// GLES 2.0.25 section 2.10.4 page 39.
+TEST_P(TextureLimitsTest, TextureTypeConflict)
+{
+    const std::string &vertexShader =
+        "attribute vec2 position;\n"
+        "varying float color;\n"
+        "uniform sampler2D tex2D;\n"
+        "uniform samplerCube texCube;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(position, 0, 1);\n"
+        "  vec2 texCoord = (position * 0.5) + 0.5;\n"
+        "  color = texture2D(tex2D, texCoord).x;\n"
+        "  color += textureCube(texCube, vec3(texCoord, 0)).x;\n"
+        "}";
+    const std::string &fragmentShader =
+        "varying mediump float color;\n"
+        "void main() {\n"
+        "  gl_FragColor = vec4(color, 0, 0, 1);\n"
+        "}";
+
+    mProgram = CompileProgram(vertexShader, fragmentShader);
+    ASSERT_NE(0u, mProgram);
+
+    initTextures(1, 0);
+
+    glUseProgram(mProgram);
+    GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
+    ASSERT_NE(-1, tex2DLocation);
+    GLint texCubeLocation = glGetUniformLocation(mProgram, "texCube");
+    ASSERT_NE(-1, texCubeLocation);
+
+    glUniform1i(tex2DLocation, 0);
+    glUniform1i(texCubeLocation, 0);
+    ASSERT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+class Texture2DNorm16TestES3 : public Texture2DTestES3
+{
+  protected:
+    Texture2DNorm16TestES3() : Texture2DTestES3(), mTextures{0, 0, 0}, mFBO(0), mRenderbuffer(0) {}
+
+    void SetUp() override
+    {
+        Texture2DTestES3::SetUp();
+
+        glActiveTexture(GL_TEXTURE0);
+        glGenTextures(3, mTextures);
+        glGenFramebuffers(1, &mFBO);
+        glGenRenderbuffers(1, &mRenderbuffer);
+
+        for (size_t textureIndex = 0; textureIndex < 3; textureIndex++)
+        {
+            glBindTexture(GL_TEXTURE_2D, mTextures[textureIndex]);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        }
+
+        glBindTexture(GL_TEXTURE_2D, 0);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteTextures(3, mTextures);
+        glDeleteFramebuffers(1, &mFBO);
+        glDeleteRenderbuffers(1, &mRenderbuffer);
+
+        Texture2DTestES3::TearDown();
+    }
+
+    void testNorm16Texture(GLint internalformat, GLenum format, GLenum type)
+    {
+        GLushort pixelValue  = (type == GL_SHORT) ? 0x7FFF : 0x6A35;
+        GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
+
+        setUpProgram();
+
+        glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
+                               0);
+
+        glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16_EXT, 1, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT, nullptr);
+
+        glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+        glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
+
+        EXPECT_GL_NO_ERROR();
+
+        drawQuad(mProgram, "position", 0.5f);
+
+        GLubyte expectedValue = (type == GL_SHORT) ? 0xFF : static_cast<GLubyte>(pixelValue >> 8);
+
+        EXPECT_PIXEL_COLOR_EQ(
+            0, 0, SliceFormatColor(
+                      format, GLColor(expectedValue, expectedValue, expectedValue, expectedValue)));
+
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void testNorm16Render(GLint internalformat, GLenum format, GLenum type)
+    {
+        GLushort pixelValue = 0x6A35;
+        GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
+
+        setUpProgram();
+
+        glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+        glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, nullptr);
+
+        glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
+                               0);
+
+        glBindTexture(GL_TEXTURE_2D, mTextures[2]);
+        glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
+
+        EXPECT_GL_NO_ERROR();
+
+        drawQuad(mProgram, "position", 0.5f);
+
+        GLubyte expectedValue = static_cast<GLubyte>(pixelValue >> 8);
+        EXPECT_PIXEL_COLOR_EQ(
+            0, 0, SliceFormatColor(
+                      format, GLColor(expectedValue, expectedValue, expectedValue, expectedValue)));
+
+        glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                                  mRenderbuffer);
+        glBindRenderbuffer(GL_RENDERBUFFER, 0);
+        EXPECT_GL_NO_ERROR();
+
+        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+
+        EXPECT_PIXEL_COLOR_EQ(0, 0, SliceFormatColor(format, GLColor::white));
+
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    GLuint mTextures[3];
+    GLuint mFBO;
+    GLuint mRenderbuffer;
+};
+
+// Test texture formats enabled by the GL_EXT_texture_norm16 extension.
+TEST_P(Texture2DNorm16TestES3, TextureNorm16Test)
+{
+    if (!extensionEnabled("GL_EXT_texture_norm16"))
+    {
+        std::cout << "Test skipped due to missing GL_EXT_texture_norm16." << std::endl;
+        return;
+    }
+
+    testNorm16Texture(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
+    testNorm16Texture(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
+    testNorm16Texture(GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
+    testNorm16Texture(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
+    testNorm16Texture(GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
+    testNorm16Texture(GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
+    testNorm16Texture(GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
+    testNorm16Texture(GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
+
+    testNorm16Render(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
+    testNorm16Render(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
+    testNorm16Render(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
+}
+
+// Test that UNPACK_SKIP_IMAGES doesn't have an effect on 2D texture uploads.
+// GLES 3.0.4 section 3.8.3.
+TEST_P(Texture2DTestES3, UnpackSkipImages2D)
+{
+    if (IsIntel() && IsDesktopOpenGL())
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+    // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1429 is fixed
+    if (IsAndroid() && IsAdreno() && IsOpenGLES())
+    {
+        std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
+        return;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    ASSERT_GL_NO_ERROR();
+
+    // SKIP_IMAGES should not have an effect on uploading 2D textures
+    glPixelStorei(GL_UNPACK_SKIP_IMAGES, 1000);
+    ASSERT_GL_NO_ERROR();
+
+    std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 pixelsGreen.data());
+    ASSERT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE,
+                    pixelsGreen.data());
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(mProgram);
+    drawQuad(mProgram, "position", 0.5f);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that skip defined in unpack parameters is taken into account when determining whether
+// unpacking source extends outside unpack buffer bounds.
+TEST_P(Texture2DTestES3, UnpackSkipPixelsOutOfBounds)
+{
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    ASSERT_GL_NO_ERROR();
+
+    GLBuffer buf;
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf.get());
+    std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
+                 GL_DYNAMIC_COPY);
+    ASSERT_GL_NO_ERROR();
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+    ASSERT_GL_NO_ERROR();
+
+    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 1);
+    ASSERT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+    glPixelStorei(GL_UNPACK_SKIP_ROWS, 1);
+    ASSERT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test that unpacking rows that overlap in a pixel unpack buffer works as expected.
+TEST_P(Texture2DTestES3, UnpackOverlappingRowsFromUnpackBuffer)
+{
+    if (IsD3D11())
+    {
+        std::cout << "Test skipped on D3D." << std::endl;
+        return;
+    }
+    if (IsOSX() && IsAMD())
+    {
+        // Incorrect rendering results seen on OSX AMD.
+        std::cout << "Test skipped on OSX AMD." << std::endl;
+        return;
+    }
+
+    const GLuint width            = 8u;
+    const GLuint height           = 8u;
+    const GLuint unpackRowLength  = 5u;
+    const GLuint unpackSkipPixels = 1u;
+
+    setWindowWidth(width);
+    setWindowHeight(height);
+
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    ASSERT_GL_NO_ERROR();
+
+    GLBuffer buf;
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf.get());
+    std::vector<GLColor> pixelsGreen((height - 1u) * unpackRowLength + width + unpackSkipPixels,
+                                     GLColor::green);
+
+    for (GLuint skippedPixel = 0u; skippedPixel < unpackSkipPixels; ++skippedPixel)
+    {
+        pixelsGreen[skippedPixel] = GLColor(255, 0, 0, 255);
+    }
+
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
+                 GL_DYNAMIC_COPY);
+    ASSERT_GL_NO_ERROR();
+
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackRowLength);
+    glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels);
+    ASSERT_GL_NO_ERROR();
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(mProgram);
+    drawQuad(mProgram, "position", 0.5f);
+    ASSERT_GL_NO_ERROR();
+
+    GLuint windowPixelCount = getWindowWidth() * getWindowHeight();
+    std::vector<GLColor> actual(windowPixelCount, GLColor::black);
+    glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
+                 actual.data());
+    std::vector<GLColor> expected(windowPixelCount, GLColor::green);
+    EXPECT_EQ(expected, actual);
+}
+
+template <typename T>
+T UNorm(double value)
+{
+    return static_cast<T>(value * static_cast<double>(std::numeric_limits<T>::max()));
+}
+
+// Test rendering a depth texture with mipmaps.
+TEST_P(Texture2DTestES3, DepthTexturesWithMipmaps)
+{
+    // TODO(cwallez) this is failing on Intel Win7 OpenGL.
+    // TODO(zmo) this is faling on Win Intel HD 530 Debug.
+    // http://anglebugs.com/1706
+    if (IsIntel() && IsWindows())
+    {
+        std::cout << "Test skipped on Win Intel." << std::endl;
+        return;
+    }
+
+    const int size = getWindowWidth();
+
+    auto dim   = [size](int level) { return size >> level; };
+    int levels = gl::log2(size);
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexStorage2D(GL_TEXTURE_2D, levels, GL_DEPTH_COMPONENT24, size, size);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(mProgram);
+    glUniform1i(mTexture2DUniformLocation, 0);
+
+    std::vector<unsigned char> expected;
+
+    for (int level = 0; level < levels; ++level)
+    {
+        double value = (static_cast<double>(level) / static_cast<double>(levels - 1));
+        expected.push_back(UNorm<unsigned char>(value));
+
+        int levelDim = dim(level);
+
+        ASSERT_GT(levelDim, 0);
+
+        std::vector<unsigned int> initData(levelDim * levelDim, UNorm<unsigned int>(value));
+        glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, levelDim, levelDim, GL_DEPTH_COMPONENT,
+                        GL_UNSIGNED_INT, initData.data());
+    }
+    ASSERT_GL_NO_ERROR();
+
+    for (int level = 0; level < levels; ++level)
+    {
+        glViewport(0, 0, dim(level), dim(level));
+        drawQuad(mProgram, "position", 0.5f);
+        GLColor actual = ReadColor(0, 0);
+        EXPECT_NEAR(expected[level], actual.R, 10u);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Tests unpacking into the unsized GL_ALPHA format.
+TEST_P(Texture2DTestES3, UnsizedAlphaUnpackBuffer)
+{
+    // TODO(jmadill): Figure out why this fails on OSX.
+    ANGLE_SKIP_TEST_IF(IsOSX());
+
+    // Initialize the texure.
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, getWindowWidth(), getWindowHeight(), 0, GL_ALPHA,
+                 GL_UNSIGNED_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    std::vector<GLubyte> bufferData(getWindowWidth() * getWindowHeight(), 127);
+
+    // Pull in the color data from the unpack buffer.
+    GLBuffer unpackBuffer;
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer.get());
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, getWindowWidth() * getWindowHeight(), bufferData.data(),
+                 GL_STATIC_DRAW);
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_ALPHA,
+                    GL_UNSIGNED_BYTE, nullptr);
+
+    // Clear to a weird color to make sure we're drawing something.
+    glClearColor(0.5f, 0.8f, 1.0f, 0.2f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // Draw with the alpha texture and verify.
+    drawQuad(mProgram, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 127, 1);
+}
+
+// Ensure stale unpack data doesn't propagate in D3D11.
+TEST_P(Texture2DTestES3, StaleUnpackData)
+{
+    // Init unpack buffer.
+    GLsizei pixelCount = getWindowWidth() * getWindowHeight() / 2;
+    std::vector<GLColor> pixels(pixelCount, GLColor::red);
+
+    GLBuffer unpackBuffer;
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer.get());
+    GLsizei bufferSize = pixelCount * sizeof(GLColor);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize, pixels.data(), GL_STATIC_DRAW);
+
+    // Create from unpack buffer.
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth() / 2, getWindowHeight() / 2, 0,
+                 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    // Fill unpack with green, recreating buffer.
+    pixels.assign(getWindowWidth() * getWindowHeight(), GLColor::green);
+    GLsizei size2 = getWindowWidth() * getWindowHeight() * sizeof(GLColor);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, size2, pixels.data(), GL_STATIC_DRAW);
+
+    // Reinit texture with green.
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
+                    GL_UNSIGNED_BYTE, nullptr);
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// This test covers a D3D format redefinition bug for 3D textures. The base level format was not
+// being properly checked, and the texture storage of the previous texture format was persisting.
+// This would result in an ASSERT in debug and incorrect rendering in release.
+// See http://anglebug.com/1609 and WebGL 2 test conformance2/misc/views-with-offsets.html.
+TEST_P(Texture3DTestES3, FormatRedefinitionBug)
+{
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_3D, tex.get());
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex.get(), 0, 0);
+
+    glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+    std::vector<uint8_t> pixelData(100, 0);
+
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB565, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, nullptr);
+    glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+                    pixelData.data());
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test basic pixel unpack buffer OOB checks when uploading to a 2D or 3D texture
+TEST_P(Texture3DTestES3, BasicUnpackBufferOOB)
+{
+    // 2D tests
+    {
+        GLTexture tex;
+        glBindTexture(GL_TEXTURE_2D, tex.get());
+
+        GLBuffer pbo;
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.get());
+
+        // Test OOB
+        glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 - 1, nullptr, GL_STATIC_DRAW);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+        // Test OOB
+        glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2, nullptr, GL_STATIC_DRAW);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        ASSERT_GL_NO_ERROR();
+    }
+
+    // 3D tests
+    {
+        GLTexture tex;
+        glBindTexture(GL_TEXTURE_3D, tex.get());
+
+        GLBuffer pbo;
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.get());
+
+        // Test OOB
+        glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2 - 1, nullptr,
+                     GL_STATIC_DRAW);
+        glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+        // Test OOB
+        glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2, nullptr, GL_STATIC_DRAW);
+        glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+// TODO(oetuaho): Enable all below tests on OpenGL. Requires a fix for ANGLE bug 1278.
+ANGLE_INSTANTIATE_TEST(Texture2DTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(TextureCubeTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(Texture2DTestWithDrawScale,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(Sampler2DAsFunctionParameterTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(SamplerArrayTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(SamplerArrayAsFunctionParameterTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(Texture2DTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(Texture3DTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(Texture2DIntegerAlpha1TestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(Texture2DUnsignedIntegerAlpha1TestES3,
+                       ES3_D3D11(),
+                       ES3_OPENGL(),
+                       ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(ShadowSamplerPlusSampler3DTestES3,
+                       ES3_D3D11(),
+                       ES3_OPENGL(),
+                       ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(SamplerTypeMixTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(Texture2DArrayTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(TextureSizeTextureArrayTest, ES3_D3D11(), ES3_OPENGL());
+ANGLE_INSTANTIATE_TEST(SamplerInStructTest,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_D3D9(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(SamplerInStructAsFunctionParameterTest,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_D3D9(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(SamplerInStructArrayAsFunctionParameterTest,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_D3D9(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(SamplerInNestedStructAsFunctionParameterTest,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_D3D9(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(SamplerInStructAndOtherVariableTest,
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_D3D9(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(TextureLimitsTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(Texture2DNorm16TestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/TimerQueriesTest.cpp b/src/third_party/angle/src/tests/gl_tests/TimerQueriesTest.cpp
new file mode 100644
index 0000000..dc20b09
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/TimerQueriesTest.cpp
@@ -0,0 +1,600 @@
+//
+// Copyright 2016 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.
+//
+// TimerQueriesTest.cpp
+//   Various tests for EXT_disjoint_timer_query functionality and validation
+//
+
+#include "system_utils.h"
+#include "test_utils/ANGLETest.h"
+#include "random_utils.h"
+
+using namespace angle;
+
+class TimerQueriesTest : public ANGLETest
+{
+  protected:
+    TimerQueriesTest() : mProgram(0), mProgramCostly(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const std::string passthroughVS =
+            "attribute highp vec4 position; void main(void)\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "}\n";
+
+        const std::string passthroughPS =
+            "precision highp float; void main(void)\n"
+            "{\n"
+            "    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
+            "}\n";
+
+        const std::string costlyVS =
+            "attribute highp vec4 position; varying highp vec4 testPos; void main(void)\n"
+            "{\n"
+            "    testPos     = position;\n"
+            "    gl_Position = position;\n"
+            "}\n";
+
+        const std::string costlyPS =
+            "precision highp float; varying highp vec4 testPos; void main(void)\n"
+            "{\n"
+            "    vec4 test = testPos;\n"
+            "    for (int i = 0; i < 500; i++)\n"
+            "    {\n"
+            "        test = sqrt(test);\n"
+            "    }\n"
+            "    gl_FragColor = test;\n"
+            "}\n";
+
+        mProgram = CompileProgram(passthroughVS, passthroughPS);
+        ASSERT_NE(0u, mProgram) << "shader compilation failed.";
+
+        mProgramCostly = CompileProgram(costlyVS, costlyPS);
+        ASSERT_NE(0u, mProgramCostly) << "shader compilation failed.";
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mProgram);
+        glDeleteProgram(mProgramCostly);
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+    GLuint mProgramCostly;
+};
+
+// Test that all proc addresses are loadable
+TEST_P(TimerQueriesTest, ProcAddresses)
+{
+    if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
+    {
+        std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
+                  << std::endl;
+        return;
+    }
+
+    ASSERT_NE(nullptr, eglGetProcAddress("glGenQueriesEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glDeleteQueriesEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glIsQueryEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glBeginQueryEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glEndQueryEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glQueryCounterEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryivEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryObjectivEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryObjectuivEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryObjecti64vEXT"));
+    ASSERT_NE(nullptr, eglGetProcAddress("glGetQueryObjectui64vEXT"));
+}
+
+// Tests the time elapsed query
+TEST_P(TimerQueriesTest, TimeElapsed)
+{
+    if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
+    {
+        std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLint queryTimeElapsedBits = 0;
+    glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
+    ASSERT_GL_NO_ERROR();
+
+    std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
+
+    // Skip test if the number of bits is 0
+    if (queryTimeElapsedBits == 0)
+    {
+        std::cout << "Test skipped because of 0 counter bits" << std::endl;
+        return;
+    }
+
+    glDepthMask(GL_TRUE);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    GLuint query1 = 0;
+    GLuint query2 = 0;
+    glGenQueriesEXT(1, &query1);
+    glGenQueriesEXT(1, &query2);
+
+    // Test time elapsed for a single quad
+    glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query1);
+    drawQuad(mProgram, "position", 0.8f);
+    glEndQueryEXT(GL_TIME_ELAPSED_EXT);
+    ASSERT_GL_NO_ERROR();
+
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    // Test time elapsed for costly quad
+    glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query2);
+    drawQuad(mProgramCostly, "position", 0.8f);
+    glEndQueryEXT(GL_TIME_ELAPSED_EXT);
+    ASSERT_GL_NO_ERROR();
+
+    swapBuffers();
+
+    int timeout  = 200000;
+    GLuint ready = GL_FALSE;
+    while (ready == GL_FALSE && timeout > 0)
+    {
+        angle::Sleep(0);
+        glGetQueryObjectuivEXT(query1, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
+        timeout--;
+    }
+    ready = GL_FALSE;
+    while (ready == GL_FALSE && timeout > 0)
+    {
+        angle::Sleep(0);
+        glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
+        timeout--;
+    }
+    ASSERT_LT(0, timeout) << "Query result available timed out" << std::endl;
+
+    GLuint64 result1 = 0;
+    GLuint64 result2 = 0;
+    glGetQueryObjectui64vEXT(query1, GL_QUERY_RESULT_EXT, &result1);
+    glGetQueryObjectui64vEXT(query2, GL_QUERY_RESULT_EXT, &result2);
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteQueriesEXT(1, &query1);
+    glDeleteQueriesEXT(1, &query2);
+    ASSERT_GL_NO_ERROR();
+
+    std::cout << "Elapsed time: " << result1 << " cheap quad" << std::endl;
+    std::cout << "Elapsed time: " << result2 << " costly quad" << std::endl;
+
+    // The time elapsed should be nonzero
+    EXPECT_LT(0ul, result1);
+    EXPECT_LT(0ul, result2);
+
+    // TODO(geofflang): Re-enable this check when it is non-flaky
+    // The costly quad should take longer than the cheap quad
+    // EXPECT_LT(result1, result2);
+}
+
+// Tests time elapsed for a non draw call (texture upload)
+TEST_P(TimerQueriesTest, TimeElapsedTextureTest)
+{
+    // OSX drivers don't seem to properly time non-draw calls so we skip the test on Mac
+    if (IsOSX())
+    {
+        std::cout << "Test skipped on OSX" << std::endl;
+        return;
+    }
+
+    if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
+    {
+        std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLint queryTimeElapsedBits = 0;
+    glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
+    ASSERT_GL_NO_ERROR();
+
+    std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
+
+    // Skip test if the number of bits is 0
+    if (queryTimeElapsedBits == 0)
+    {
+        std::cout << "Test skipped because of 0 counter bits" << std::endl;
+        return;
+    }
+
+    GLubyte pixels[] = {0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 0, 0};
+
+    // Query and texture initialization
+    GLuint texture;
+    GLuint query = 0;
+    glGenQueriesEXT(1, &query);
+    glGenTextures(1, &texture);
+
+    // Upload a texture inside the query
+    glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+    glGenerateMipmap(GL_TEXTURE_2D);
+    glFinish();
+    glEndQueryEXT(GL_TIME_ELAPSED_EXT);
+    ASSERT_GL_NO_ERROR();
+
+    int timeout  = 200000;
+    GLuint ready = GL_FALSE;
+    while (ready == GL_FALSE && timeout > 0)
+    {
+        angle::Sleep(0);
+        glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
+        timeout--;
+    }
+    ASSERT_LT(0, timeout) << "Query result available timed out" << std::endl;
+
+    GLuint64 result = 0;
+    glGetQueryObjectui64vEXT(query, GL_QUERY_RESULT_EXT, &result);
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteTextures(1, &texture);
+    glDeleteQueriesEXT(1, &query);
+
+    std::cout << "Elapsed time: " << result << std::endl;
+    EXPECT_LT(0ul, result);
+}
+
+// Tests validation of query functions with respect to elapsed time query
+TEST_P(TimerQueriesTest, TimeElapsedValidationTest)
+{
+    if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
+    {
+        std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLint queryTimeElapsedBits = 0;
+    glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
+    ASSERT_GL_NO_ERROR();
+
+    std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
+
+    // Skip test if the number of bits is 0
+    if (queryTimeElapsedBits == 0)
+    {
+        std::cout << "Test skipped because of 0 counter bits" << std::endl;
+        return;
+    }
+
+    GLuint query = 0;
+    glGenQueriesEXT(-1, &query);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+
+    glGenQueriesEXT(1, &query);
+    EXPECT_GL_NO_ERROR();
+
+    glBeginQueryEXT(GL_TIMESTAMP_EXT, query);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    glBeginQueryEXT(GL_TIME_ELAPSED_EXT, 0);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glEndQueryEXT(GL_TIME_ELAPSED_EXT);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
+    EXPECT_GL_NO_ERROR();
+
+    glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glEndQueryEXT(GL_TIME_ELAPSED_EXT);
+    EXPECT_GL_NO_ERROR();
+
+    glEndQueryEXT(GL_TIME_ELAPSED_EXT);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Tests timer queries operating under multiple EGL contexts with mid-query switching
+TEST_P(TimerQueriesTest, TimeElapsedMulticontextTest)
+{
+    if (IsAMD() && IsOpenGL() && IsWindows())
+    {
+        // TODO(jmadill): Figure out why this test is flaky on Win/AMD/OpenGL.
+        // http://anglebug.com/1541
+        std::cout << "Test skipped on Windows AMD OpenGL Debug." << std::endl;
+        return;
+    }
+
+    if (IsAMD() && IsOSX())
+    {
+        // TODO(cwallez): Figure out why this test is flaky on OSX/AMD.
+        // http://anglebug.com/1866
+        std::cout << "Test skipped on Mac AMD." << std::endl;
+        return;
+    }
+
+    if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
+    {
+        std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLint queryTimeElapsedBits = 0;
+    glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
+    ASSERT_GL_NO_ERROR();
+
+    std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
+
+    // Skip test if the number of bits is 0
+    if (queryTimeElapsedBits == 0)
+    {
+        std::cout << "Test skipped because of 0 counter bits" << std::endl;
+        return;
+    }
+
+    // Without a glClear, the first draw call on GL takes a huge amount of time when run after the
+    // D3D test on certain NVIDIA drivers
+    glDepthMask(GL_TRUE);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    EGLint contextAttributes[] = {
+        EGL_CONTEXT_MAJOR_VERSION_KHR,
+        GetParam().majorVersion,
+        EGL_CONTEXT_MINOR_VERSION_KHR,
+        GetParam().minorVersion,
+        EGL_NONE,
+    };
+
+    EGLWindow *window = getEGLWindow();
+
+    EGLDisplay display = window->getDisplay();
+    EGLConfig config   = window->getConfig();
+    EGLSurface surface = window->getSurface();
+
+    struct ContextInfo
+    {
+        EGLContext context;
+        GLuint program;
+        GLuint query;
+        EGLDisplay display;
+
+        ContextInfo() : context(EGL_NO_CONTEXT), program(0), query(0), display(EGL_NO_DISPLAY) {}
+
+        ~ContextInfo()
+        {
+            if (context != EGL_NO_CONTEXT && display != EGL_NO_DISPLAY)
+            {
+                eglDestroyContext(display, context);
+            }
+        }
+    };
+    ContextInfo contexts[2];
+
+    // Shaders
+    const std::string cheapVS =
+        "attribute highp vec4 position; void main(void)\n"
+        "{\n"
+        "    gl_Position = position;\n"
+        "}\n";
+
+    const std::string cheapPS =
+        "precision highp float; void main(void)\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
+        "}\n";
+
+    const std::string costlyVS =
+        "attribute highp vec4 position; varying highp vec4 testPos; void main(void)\n"
+        "{\n"
+        "    testPos     = position;\n"
+        "    gl_Position = position;\n"
+        "}\n";
+
+    const std::string costlyPS =
+        "precision highp float; varying highp vec4 testPos; void main(void)\n"
+        "{\n"
+        "    vec4 test = testPos;\n"
+        "    for (int i = 0; i < 500; i++)\n"
+        "    {\n"
+        "        test = sqrt(test);\n"
+        "    }\n"
+        "    gl_FragColor = test;\n"
+        "}\n";
+
+    // Setup the first context with a cheap shader
+    contexts[0].context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
+    contexts[0].display = display;
+    ASSERT_NE(contexts[0].context, EGL_NO_CONTEXT);
+    eglMakeCurrent(display, surface, surface, contexts[0].context);
+    contexts[0].program = CompileProgram(cheapVS, cheapPS);
+    glGenQueriesEXT(1, &contexts[0].query);
+    ASSERT_GL_NO_ERROR();
+
+    // Setup the second context with an expensive shader
+    contexts[1].context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
+    contexts[1].display = display;
+    ASSERT_NE(contexts[1].context, EGL_NO_CONTEXT);
+    eglMakeCurrent(display, surface, surface, contexts[1].context);
+    contexts[1].program = CompileProgram(costlyVS, costlyPS);
+    glGenQueriesEXT(1, &contexts[1].query);
+    ASSERT_GL_NO_ERROR();
+
+    // Start the query and draw a quad on the first context without ending the query
+    eglMakeCurrent(display, surface, surface, contexts[0].context);
+    glBeginQueryEXT(GL_TIME_ELAPSED_EXT, contexts[0].query);
+    drawQuad(contexts[0].program, "position", 0.8f);
+    ASSERT_GL_NO_ERROR();
+
+    // Switch contexts, draw the expensive quad and end its query
+    eglMakeCurrent(display, surface, surface, contexts[1].context);
+    glBeginQueryEXT(GL_TIME_ELAPSED_EXT, contexts[1].query);
+    drawQuad(contexts[1].program, "position", 0.8f);
+    glEndQueryEXT(GL_TIME_ELAPSED_EXT);
+    ASSERT_GL_NO_ERROR();
+
+    // Go back to the first context, end its query, and get the result
+    eglMakeCurrent(display, surface, surface, contexts[0].context);
+    glEndQueryEXT(GL_TIME_ELAPSED_EXT);
+
+    GLuint64 result1 = 0;
+    GLuint64 result2 = 0;
+    glGetQueryObjectui64vEXT(contexts[0].query, GL_QUERY_RESULT_EXT, &result1);
+    glDeleteQueriesEXT(1, &contexts[0].query);
+    glDeleteProgram(contexts[0].program);
+    ASSERT_GL_NO_ERROR();
+
+    // Get the 2nd context's results
+    eglMakeCurrent(display, surface, surface, contexts[1].context);
+    glGetQueryObjectui64vEXT(contexts[1].query, GL_QUERY_RESULT_EXT, &result2);
+    glDeleteQueriesEXT(1, &contexts[1].query);
+    glDeleteProgram(contexts[1].program);
+    ASSERT_GL_NO_ERROR();
+
+    // Switch back to main context
+    eglMakeCurrent(display, surface, surface, window->getContext());
+
+    // Compare the results. The cheap quad should be smaller than the expensive one if
+    // virtualization is working correctly
+    std::cout << "Elapsed time: " << result1 << " cheap quad" << std::endl;
+    std::cout << "Elapsed time: " << result2 << " costly quad" << std::endl;
+    EXPECT_LT(0ul, result1);
+    EXPECT_LT(0ul, result2);
+    EXPECT_LT(result1, result2);
+}
+
+// Tests GPU timestamp functionality
+TEST_P(TimerQueriesTest, Timestamp)
+{
+    if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
+    {
+        std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLint queryTimestampBits = 0;
+    glGetQueryivEXT(GL_TIMESTAMP_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimestampBits);
+    ASSERT_GL_NO_ERROR();
+
+    std::cout << "Timestamp counter bits: " << queryTimestampBits << std::endl;
+
+    // Macs for some reason return 0 bits so skip the test for now if either are 0
+    if (queryTimestampBits == 0)
+    {
+        std::cout << "Test skipped because of 0 counter bits" << std::endl;
+        return;
+    }
+
+    glDepthMask(GL_TRUE);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    GLuint query1 = 0;
+    GLuint query2 = 0;
+    glGenQueriesEXT(1, &query1);
+    glGenQueriesEXT(1, &query2);
+    glQueryCounterEXT(query1, GL_TIMESTAMP_EXT);
+    drawQuad(mProgram, "position", 0.8f);
+    glQueryCounterEXT(query2, GL_TIMESTAMP_EXT);
+
+    ASSERT_GL_NO_ERROR();
+
+    swapBuffers();
+
+    int timeout  = 200000;
+    GLuint ready = GL_FALSE;
+    while (ready == GL_FALSE && timeout > 0)
+    {
+        angle::Sleep(0);
+        glGetQueryObjectuivEXT(query1, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
+        timeout--;
+    }
+    ready = GL_FALSE;
+    while (ready == GL_FALSE && timeout > 0)
+    {
+        angle::Sleep(0);
+        glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
+        timeout--;
+    }
+    ASSERT_LT(0, timeout) << "Query result available timed out" << std::endl;
+
+    GLuint64 result1 = 0;
+    GLuint64 result2 = 0;
+    glGetQueryObjectui64vEXT(query1, GL_QUERY_RESULT_EXT, &result1);
+    glGetQueryObjectui64vEXT(query2, GL_QUERY_RESULT_EXT, &result2);
+
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteQueriesEXT(1, &query1);
+    glDeleteQueriesEXT(1, &query2);
+
+    std::cout << "Timestamps: " << result1 << " " << result2 << std::endl;
+    EXPECT_LT(0ul, result1);
+    EXPECT_LT(0ul, result2);
+    EXPECT_LT(result1, result2);
+}
+
+class TimerQueriesTestES3 : public TimerQueriesTest
+{
+};
+
+// Tests getting timestamps via glGetInteger64v
+TEST_P(TimerQueriesTestES3, TimestampGetInteger64)
+{
+    if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
+    {
+        std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
+                  << std::endl;
+        return;
+    }
+
+    GLint queryTimestampBits = 0;
+    glGetQueryivEXT(GL_TIMESTAMP_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimestampBits);
+    ASSERT_GL_NO_ERROR();
+
+    std::cout << "Timestamp counter bits: " << queryTimestampBits << std::endl;
+
+    if (queryTimestampBits == 0)
+    {
+        std::cout << "Test skipped because of 0 counter bits" << std::endl;
+        return;
+    }
+
+    glDepthMask(GL_TRUE);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+    GLint64 result1 = 0;
+    GLint64 result2 = 0;
+    glGetInteger64v(GL_TIMESTAMP_EXT, &result1);
+    drawQuad(mProgram, "position", 0.8f);
+    glGetInteger64v(GL_TIMESTAMP_EXT, &result2);
+    ASSERT_GL_NO_ERROR();
+    std::cout << "Timestamps (getInteger64v): " << result1 << " " << result2 << std::endl;
+    EXPECT_LT(0l, result1);
+    EXPECT_LT(0l, result2);
+    EXPECT_LT(result1, result2);
+}
+
+ANGLE_INSTANTIATE_TEST(TimerQueriesTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL());
+
+ANGLE_INSTANTIATE_TEST(TimerQueriesTestES3, ES3_D3D11(), ES3_OPENGL());
diff --git a/src/third_party/angle/src/tests/gl_tests/TransformFeedbackTest.cpp b/src/third_party/angle/src/tests/gl_tests/TransformFeedbackTest.cpp
new file mode 100644
index 0000000..88d97f3
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/TransformFeedbackTest.cpp
@@ -0,0 +1,1077 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "random_utils.h"
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class TransformFeedbackTestBase : public ANGLETest
+{
+  protected:
+    TransformFeedbackTestBase() : mProgram(0), mTransformFeedbackBuffer(0), mTransformFeedback(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenBuffers(1, &mTransformFeedbackBuffer);
+        glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
+        glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, nullptr,
+                     GL_STATIC_DRAW);
+
+        glGenTransformFeedbacks(1, &mTransformFeedback);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        if (mProgram != 0)
+        {
+            glDeleteProgram(mProgram);
+            mProgram = 0;
+        }
+
+        if (mTransformFeedbackBuffer != 0)
+        {
+            glDeleteBuffers(1, &mTransformFeedbackBuffer);
+            mTransformFeedbackBuffer = 0;
+        }
+
+        if (mTransformFeedback != 0)
+        {
+            glDeleteTransformFeedbacks(1, &mTransformFeedback);
+            mTransformFeedback = 0;
+        }
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+
+    static const size_t mTransformFeedbackBufferSize = 1 << 24;
+    GLuint mTransformFeedbackBuffer;
+    GLuint mTransformFeedback;
+};
+
+class TransformFeedbackTest : public TransformFeedbackTestBase
+{
+  protected:
+    void compileDefaultProgram(const std::vector<std::string> &tfVaryings, GLenum bufferMode)
+    {
+        ASSERT_EQ(0u, mProgram);
+
+        const std::string vertexShaderSource =
+            SHADER_SOURCE(precision highp float; attribute vec4 position;
+
+                          void main() { gl_Position = position; });
+
+        const std::string fragmentShaderSource =
+            SHADER_SOURCE(precision highp float;
+
+                          void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); });
+
+        mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+                                                       tfVaryings, bufferMode);
+        ASSERT_NE(0u, mProgram);
+    }
+};
+
+TEST_P(TransformFeedbackTest, ZeroSizedViewport)
+{
+    // Set the program's transform feedback varyings (just gl_Position)
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("gl_Position");
+    compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS);
+
+    glUseProgram(mProgram);
+
+    // Bind the buffer for transform feedback output and start transform feedback
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+    glBeginTransformFeedback(GL_TRIANGLES);
+
+    // Create a query to check how many primitives were written
+    GLuint primitivesWrittenQuery = 0;
+    glGenQueries(1, &primitivesWrittenQuery);
+    glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, primitivesWrittenQuery);
+
+    // Set a viewport that would result in no pixels being written to the framebuffer and draw
+    // a quad
+    glViewport(0, 0, 0, 0);
+
+    drawQuad(mProgram, "position", 0.5f);
+
+    // End the query and transform feedkback
+    glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+    glEndTransformFeedback();
+
+    glUseProgram(0);
+
+    // Check how many primitives were written and verify that some were written even if
+    // no pixels were rendered
+    GLuint primitivesWritten = 0;
+    glGetQueryObjectuiv(primitivesWrittenQuery, GL_QUERY_RESULT_EXT, &primitivesWritten);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(2u, primitivesWritten);
+}
+
+// Test that rebinding a buffer with the same offset resets the offset (no longer appending from the
+// old position)
+TEST_P(TransformFeedbackTest, BufferRebinding)
+{
+    glDisable(GL_DEPTH_TEST);
+
+    // Set the program's transform feedback varyings (just gl_Position)
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("gl_Position");
+    compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS);
+
+    glUseProgram(mProgram);
+
+    // Make sure the buffer has zero'd data
+    std::vector<float> data(mTransformFeedbackBufferSize / sizeof(float), 0.0f);
+    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
+    glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, data.data(),
+                 GL_STATIC_DRAW);
+
+    // Create a query to check how many primitives were written
+    GLuint primitivesWrittenQuery = 0;
+    glGenQueries(1, &primitivesWrittenQuery);
+    glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, primitivesWrittenQuery);
+
+    const float finalZ = 0.95f;
+
+    RNG rng;
+
+    const size_t loopCount = 64;
+    for (size_t loopIdx = 0; loopIdx < loopCount; loopIdx++)
+    {
+        // Bind the buffer for transform feedback output and start transform feedback
+        glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+        glBeginTransformFeedback(GL_TRIANGLES);
+
+        float z = (loopIdx + 1 == loopCount) ? finalZ : rng.randomFloatBetween(0.1f, 0.5f);
+        drawQuad(mProgram, "position", z);
+
+        glEndTransformFeedback();
+    }
+
+    // End the query and transform feedback
+    glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+
+    glUseProgram(0);
+
+    // Check how many primitives were written and verify that some were written even if
+    // no pixels were rendered
+    GLuint primitivesWritten = 0;
+    glGetQueryObjectuiv(primitivesWrittenQuery, GL_QUERY_RESULT_EXT, &primitivesWritten);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(loopCount * 2, primitivesWritten);
+
+    // Check the buffer data
+    const float *bufferData = static_cast<float *>(glMapBufferRange(
+        GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBufferSize, GL_MAP_READ_BIT));
+
+    for (size_t vertexIdx = 0; vertexIdx < 6; vertexIdx++)
+    {
+        // Check the third (Z) component of each vertex written and make sure it has the final
+        // value
+        EXPECT_NEAR(finalZ, bufferData[vertexIdx * 4 + 2], 0.0001);
+    }
+
+    for (size_t dataIdx = 24; dataIdx < mTransformFeedbackBufferSize / sizeof(float); dataIdx++)
+    {
+        EXPECT_EQ(data[dataIdx], bufferData[dataIdx]) << "Buffer overrun detected.";
+    }
+
+    glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that XFB can write back vertices to a buffer and that we can draw from this buffer
+// afterward.
+TEST_P(TransformFeedbackTest, RecordAndDraw)
+{
+    // TODO(jmadill): Figure out why this fails on Intel.
+    if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        std::cout << "Test skipped on Intel." << std::endl;
+        return;
+    }
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // Set the program's transform feedback varyings (just gl_Position)
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("gl_Position");
+    compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS);
+
+    glUseProgram(mProgram);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+
+    // First pass: draw 6 points to the XFB buffer
+    glEnable(GL_RASTERIZER_DISCARD);
+
+    const GLfloat vertices[] = {
+        -1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f,
+
+        -1.0f, 1.0f, 0.5f, 1.0f,  -1.0f, 0.5f, 1.0f, 1.0f,  0.5f,
+    };
+
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
+    glEnableVertexAttribArray(positionLocation);
+
+    // Bind the buffer for transform feedback output and start transform feedback
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+    glBeginTransformFeedback(GL_POINTS);
+
+    // Create a query to check how many primitives were written
+    GLuint primitivesWrittenQuery = 0;
+    glGenQueries(1, &primitivesWrittenQuery);
+    glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, primitivesWrittenQuery);
+
+    glDrawArrays(GL_POINTS, 0, 6);
+
+    glDisableVertexAttribArray(positionLocation);
+    glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
+    // End the query and transform feedkback
+    glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+    glEndTransformFeedback();
+
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
+
+    glDisable(GL_RASTERIZER_DISCARD);
+
+    // Check how many primitives were written and verify that some were written even if
+    // no pixels were rendered
+    GLuint primitivesWritten = 0;
+    glGetQueryObjectuiv(primitivesWrittenQuery, GL_QUERY_RESULT_EXT, &primitivesWritten);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(6u, primitivesWritten);
+
+    // Nothing should have been drawn to the framebuffer
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 0);
+
+    // Second pass: draw from the feedback buffer
+
+    glBindBuffer(GL_ARRAY_BUFFER, mTransformFeedbackBuffer);
+    glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(positionLocation);
+
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+
+    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that buffer binding happens only on the current transform feedback object
+TEST_P(TransformFeedbackTest, BufferBinding)
+{
+    // Reset any state
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
+
+    // Generate a new buffer
+    GLuint scratchBuffer = 0;
+    glGenBuffers(1, &scratchBuffer);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Bind TF 0 and a buffer
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Check that the buffer ID matches the one that was just bound
+    GLint currentBufferBinding = 0;
+    glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &currentBufferBinding);
+    EXPECT_EQ(static_cast<GLuint>(currentBufferBinding), mTransformFeedbackBuffer);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Check that the buffer ID for the newly bound transform feedback is zero
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
+
+    glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &currentBufferBinding);
+    EXPECT_EQ(0, currentBufferBinding);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Bind a buffer to this TF
+    glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, scratchBuffer, 0, 32);
+
+    glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, &currentBufferBinding);
+    EXPECT_EQ(static_cast<GLuint>(currentBufferBinding), scratchBuffer);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Rebind the original TF and check it's bindings
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+
+    glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, &currentBufferBinding);
+    EXPECT_EQ(0, currentBufferBinding);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Clean up
+    glDeleteBuffers(1, &scratchBuffer);
+}
+
+// Test that we can capture varyings only used in the vertex shader.
+TEST_P(TransformFeedbackTest, VertexOnly)
+{
+    const std::string &vertexShaderSource =
+        "#version 300 es\n"
+        "in vec2 position;\n"
+        "in float attrib;\n"
+        "out float varyingAttrib;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(position, 0, 1);\n"
+        "  varyingAttrib = attrib;\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "out mediump vec4 color;\n"
+        "void main() {\n"
+        "  color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+        "}";
+
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("varyingAttrib");
+
+    mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+                                                   tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    ASSERT_NE(0u, mProgram);
+
+    glUseProgram(mProgram);
+
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+
+    std::vector<float> attribData;
+    for (unsigned int cnt = 0; cnt < 100; ++cnt)
+    {
+        attribData.push_back(static_cast<float>(cnt));
+    }
+
+    GLint attribLocation = glGetAttribLocation(mProgram, "attrib");
+    ASSERT_NE(-1, attribLocation);
+
+    glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, &attribData[0]);
+    glEnableVertexAttribArray(attribLocation);
+
+    glBeginTransformFeedback(GL_TRIANGLES);
+    drawQuad(mProgram, "position", 0.5f);
+    glEndTransformFeedback();
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(0);
+
+    void *mappedBuffer =
+        glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(float) * 6, GL_MAP_READ_BIT);
+    ASSERT_NE(nullptr, mappedBuffer);
+
+    float *mappedFloats = static_cast<float *>(mappedBuffer);
+    for (unsigned int cnt = 0; cnt < 6; ++cnt)
+    {
+        EXPECT_EQ(attribData[cnt], mappedFloats[cnt]);
+    }
+    glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that multiple paused transform feedbacks do not generate errors or crash
+TEST_P(TransformFeedbackTest, MultiplePaused)
+{
+    const size_t drawSize = 1024;
+    std::vector<float> transformFeedbackData(drawSize);
+    for (size_t i = 0; i < drawSize; i++)
+    {
+        transformFeedbackData[i] = static_cast<float>(i + 1);
+    }
+
+    // Initialize the buffers to zero
+    size_t bufferSize = drawSize;
+    std::vector<float> bufferInitialData(bufferSize, 0);
+
+    const size_t transformFeedbackCount = 8;
+
+    // clang-format off
+    const std::string vertexShaderSource = SHADER_SOURCE
+    (  #version 300 es\n
+       in highp vec4 position;
+       in float transformFeedbackInput;
+       out float transformFeedbackOutput;
+       void main(void)
+       {
+           gl_Position = position;
+           transformFeedbackOutput = transformFeedbackInput;
+       }
+    );
+
+    const std::string fragmentShaderSource = SHADER_SOURCE
+    (  #version 300 es\n
+       out mediump vec4 color;
+       void main(void)
+       {
+           color = vec4(1.0, 1.0, 1.0, 1.0);
+       }
+    );
+    // clang-format on
+
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("transformFeedbackOutput");
+
+    mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+                                                   tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    ASSERT_NE(0u, mProgram);
+    glUseProgram(mProgram);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    glDisableVertexAttribArray(positionLocation);
+    glVertexAttrib4f(positionLocation, 0.0f, 0.0f, 0.0f, 1.0f);
+
+    GLint tfInputLocation = glGetAttribLocation(mProgram, "transformFeedbackInput");
+    glEnableVertexAttribArray(tfInputLocation);
+    glVertexAttribPointer(tfInputLocation, 1, GL_FLOAT, false, 0, &transformFeedbackData[0]);
+
+    glDepthMask(GL_FALSE);
+    glEnable(GL_DEPTH_TEST);
+    ASSERT_GL_NO_ERROR();
+
+    GLuint transformFeedbacks[transformFeedbackCount];
+    glGenTransformFeedbacks(transformFeedbackCount, transformFeedbacks);
+
+    GLuint buffers[transformFeedbackCount];
+    glGenBuffers(transformFeedbackCount, buffers);
+
+    for (size_t i = 0; i < transformFeedbackCount; i++)
+    {
+        glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbacks[i]);
+
+        glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffers[i]);
+        glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferSize * sizeof(GLfloat),
+                     &bufferInitialData[0], GL_DYNAMIC_DRAW);
+        glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffers[i]);
+        ASSERT_GL_NO_ERROR();
+
+        glBeginTransformFeedback(GL_POINTS);
+
+        glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(drawSize));
+
+        glPauseTransformFeedback();
+
+        EXPECT_GL_NO_ERROR();
+    }
+
+    for (size_t i = 0; i < transformFeedbackCount; i++)
+    {
+        glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbacks[i]);
+        glEndTransformFeedback();
+        glDeleteTransformFeedbacks(1, &transformFeedbacks[i]);
+
+        EXPECT_GL_NO_ERROR();
+    }
+}
+// Test that running multiple simultaneous queries and transform feedbacks from multiple EGL
+// contexts returns the correct results.  Helps expose bugs in ANGLE's virtual contexts.
+TEST_P(TransformFeedbackTest, MultiContext)
+{
+#if defined(ANGLE_PLATFORM_APPLE)
+    if ((IsNVIDIA() || IsAMD() || IsIntel()) && GetParam() == ES3_OPENGL())
+    {
+        std::cout << "Test skipped on NVidia, AMD and Intel OpenGL on OSX." << std::endl;
+        return;
+    }
+#endif
+
+#if defined(ANGLE_PLATFORM_LINUX)
+    if (IsAMD() && GetParam() == ES3_OPENGL())
+    {
+        std::cout << "Test skipped on AMD OpenGL on Linux." << std::endl;
+        return;
+    }
+#endif
+
+    EGLint contextAttributes[] = {
+        EGL_CONTEXT_MAJOR_VERSION_KHR,
+        GetParam().majorVersion,
+        EGL_CONTEXT_MINOR_VERSION_KHR,
+        GetParam().minorVersion,
+        EGL_NONE,
+    };
+
+    EGLWindow *window = getEGLWindow();
+
+    EGLDisplay display = window->getDisplay();
+    EGLConfig config   = window->getConfig();
+    EGLSurface surface = window->getSurface();
+
+    const size_t passCount = 5;
+    struct ContextInfo
+    {
+        EGLContext context;
+        GLuint program;
+        GLuint query;
+        GLuint buffer;
+        size_t primitiveCounts[passCount];
+    };
+    ContextInfo contexts[32];
+
+    const size_t maxDrawSize = 1024;
+
+    std::vector<float> transformFeedbackData(maxDrawSize);
+    for (size_t i = 0; i < maxDrawSize; i++)
+    {
+        transformFeedbackData[i] = static_cast<float>(i + 1);
+    }
+
+    // Initialize the buffers to zero
+    size_t bufferSize = maxDrawSize * passCount;
+    std::vector<float> bufferInitialData(bufferSize, 0);
+
+    for (auto &context : contexts)
+    {
+        context.context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
+        ASSERT_NE(context.context, EGL_NO_CONTEXT);
+
+        eglMakeCurrent(display, surface, surface, context.context);
+
+        // clang-format off
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (   #version 300 es\n
+            in highp vec4 position;
+            in float transformFeedbackInput;
+            out float transformFeedbackOutput;
+            void main(void)
+            {
+                gl_Position = position;
+                transformFeedbackOutput = transformFeedbackInput;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (   #version 300 es\n
+            out mediump vec4 color;
+            void main(void)
+            {
+                color = vec4(1.0, 1.0, 1.0, 1.0);
+            }
+        );
+        // clang-format on
+
+        std::vector<std::string> tfVaryings;
+        tfVaryings.push_back("transformFeedbackOutput");
+
+        context.program = CompileProgramWithTransformFeedback(
+            vertexShaderSource, fragmentShaderSource, tfVaryings, GL_INTERLEAVED_ATTRIBS);
+        ASSERT_NE(context.program, 0u);
+        glUseProgram(context.program);
+
+        GLint positionLocation = glGetAttribLocation(context.program, "position");
+        glDisableVertexAttribArray(positionLocation);
+        glVertexAttrib4f(positionLocation, 0.0f, 0.0f, 0.0f, 1.0f);
+
+        GLint tfInputLocation = glGetAttribLocation(context.program, "transformFeedbackInput");
+        glEnableVertexAttribArray(tfInputLocation);
+        glVertexAttribPointer(tfInputLocation, 1, GL_FLOAT, false, 0, &transformFeedbackData[0]);
+
+        glDepthMask(GL_FALSE);
+        glEnable(GL_DEPTH_TEST);
+        glGenQueriesEXT(1, &context.query);
+        glBeginQueryEXT(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, context.query);
+
+        ASSERT_GL_NO_ERROR();
+
+        glGenBuffers(1, &context.buffer);
+        glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, context.buffer);
+        glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferSize * sizeof(GLfloat),
+                     &bufferInitialData[0], GL_DYNAMIC_DRAW);
+        glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, context.buffer);
+
+        ASSERT_GL_NO_ERROR();
+
+        // For each pass, draw between 0 and maxDrawSize primitives
+        for (auto &primCount : context.primitiveCounts)
+        {
+            primCount = rand() % maxDrawSize;
+        }
+
+        glBeginTransformFeedback(GL_POINTS);
+    }
+
+    for (size_t pass = 0; pass < passCount; pass++)
+    {
+        for (const auto &context : contexts)
+        {
+            eglMakeCurrent(display, surface, surface, context.context);
+
+            glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(context.primitiveCounts[pass]));
+        }
+    }
+
+    for (const auto &context : contexts)
+    {
+        eglMakeCurrent(display, surface, surface, context.context);
+
+        glEndTransformFeedback();
+
+        glEndQueryEXT(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+
+        GLuint result = 0;
+        glGetQueryObjectuivEXT(context.query, GL_QUERY_RESULT_EXT, &result);
+
+        EXPECT_GL_NO_ERROR();
+
+        size_t totalPrimCount = 0;
+        for (const auto &primCount : context.primitiveCounts)
+        {
+            totalPrimCount += primCount;
+        }
+        EXPECT_EQ(static_cast<GLuint>(totalPrimCount), result);
+
+        const float *bufferData = reinterpret_cast<float *>(glMapBufferRange(
+            GL_TRANSFORM_FEEDBACK_BUFFER, 0, bufferSize * sizeof(GLfloat), GL_MAP_READ_BIT));
+
+        size_t curBufferIndex = 0;
+        for (const auto &primCount : context.primitiveCounts)
+        {
+            for (size_t prim = 0; prim < primCount; prim++)
+            {
+                EXPECT_EQ(bufferData[curBufferIndex], prim + 1);
+                curBufferIndex++;
+            }
+        }
+
+        while (curBufferIndex < bufferSize)
+        {
+            EXPECT_EQ(bufferData[curBufferIndex], 0.0f);
+            curBufferIndex++;
+        }
+
+        glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+    }
+
+    eglMakeCurrent(display, surface, surface, window->getContext());
+
+    for (auto &context : contexts)
+    {
+        eglDestroyContext(display, context.context);
+        context.context = EGL_NO_CONTEXT;
+    }
+}
+
+// Test that when two vec2s are packed into the same register, we can still capture both of them.
+TEST_P(TransformFeedbackTest, PackingBug)
+{
+    // TODO(jmadill): With points and rasterizer discard?
+    const std::string &vertexShaderSource =
+        "#version 300 es\n"
+        "in vec2 inAttrib1;\n"
+        "in vec2 inAttrib2;\n"
+        "out vec2 outAttrib1;\n"
+        "out vec2 outAttrib2;\n"
+        "in vec2 position;\n"
+        "void main() {"
+        "  outAttrib1 = inAttrib1;\n"
+        "  outAttrib2 = inAttrib2;\n"
+        "  gl_Position = vec4(position, 0, 1);\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 color;\n"
+        "void main() {\n"
+        "  color = vec4(0);\n"
+        "}";
+
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("outAttrib1");
+    tfVaryings.push_back("outAttrib2");
+
+    mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+                                                   tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    ASSERT_NE(0u, mProgram);
+
+    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
+    glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(Vector2) * 2 * 6, nullptr, GL_STREAM_DRAW);
+
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+
+    GLint attrib1Loc = glGetAttribLocation(mProgram, "inAttrib1");
+    GLint attrib2Loc = glGetAttribLocation(mProgram, "inAttrib2");
+
+    std::vector<Vector2> attrib1Data;
+    std::vector<Vector2> attrib2Data;
+    int counter = 0;
+    for (size_t i = 0; i < 6; i++)
+    {
+        attrib1Data.push_back(Vector2(counter + 0.0f, counter + 1.0f));
+        attrib2Data.push_back(Vector2(counter + 2.0f, counter + 3.0f));
+        counter += 4;
+    }
+
+    glEnableVertexAttribArray(attrib1Loc);
+    glEnableVertexAttribArray(attrib2Loc);
+
+    glVertexAttribPointer(attrib1Loc, 2, GL_FLOAT, GL_FALSE, 0, attrib1Data.data());
+    glVertexAttribPointer(attrib2Loc, 2, GL_FLOAT, GL_FALSE, 0, attrib2Data.data());
+
+    glUseProgram(mProgram);
+    glBeginTransformFeedback(GL_TRIANGLES);
+    drawQuad(mProgram, "position", 0.5f);
+    glEndTransformFeedback();
+    glUseProgram(0);
+    ASSERT_GL_NO_ERROR();
+
+    const void *mapPointer =
+        glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(Vector2) * 2 * 6, GL_MAP_READ_BIT);
+    ASSERT_NE(nullptr, mapPointer);
+
+    const Vector2 *vecPointer = static_cast<const Vector2 *>(mapPointer);
+    for (unsigned int vectorIndex = 0; vectorIndex < 3; ++vectorIndex)
+    {
+        unsigned int stream1Index = vectorIndex * 2;
+        unsigned int stream2Index = vectorIndex * 2 + 1;
+        EXPECT_EQ(attrib1Data[vectorIndex], vecPointer[stream1Index]);
+        EXPECT_EQ(attrib2Data[vectorIndex], vecPointer[stream2Index]);
+    }
+    glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that transform feedback varyings that can be optimized out yet do not cause program
+// compilation to fail
+TEST_P(TransformFeedbackTest, OptimizedVaryings)
+{
+    const std::string &vertexShaderSource =
+        "#version 300 es\n"
+        "in vec4 a_vertex;\n"
+        "in vec3 a_normal; \n"
+        "\n"
+        "uniform Transform\n"
+        "{\n"
+        "    mat4 u_modelViewMatrix;\n"
+        "    mat4 u_projectionMatrix;\n"
+        "    mat3 u_normalMatrix;\n"
+        "};\n"
+        "\n"
+        "out vec3 normal;\n"
+        "out vec4 ecPosition;\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    normal = normalize(u_normalMatrix * a_normal);\n"
+        "    ecPosition = u_modelViewMatrix * a_vertex;\n"
+        "    gl_Position = u_projectionMatrix * ecPosition;\n"
+        "}\n";
+
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "\n"
+        "in vec3 normal;\n"
+        "in vec4 ecPosition;\n"
+        "\n"
+        "out vec4 fragColor;\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    fragColor = vec4(normal/2.0+vec3(0.5), 1);\n"
+        "}\n";
+
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("normal");
+    tfVaryings.push_back("ecPosition");
+
+    mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+                                                   tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    ASSERT_NE(0u, mProgram);
+}
+
+// Test an edge case where two varyings are unreferenced in the frag shader.
+TEST_P(TransformFeedbackTest, TwoUnreferencedInFragShader)
+{
+    // TODO(jmadill): With points and rasterizer discard?
+    const std::string &vertexShaderSource =
+        "#version 300 es\n"
+        "in vec3 position;\n"
+        "out vec3 outAttrib1;\n"
+        "out vec3 outAttrib2;\n"
+        "void main() {"
+        "  outAttrib1 = position;\n"
+        "  outAttrib2 = position;\n"
+        "  gl_Position = vec4(position, 1);\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 color;\n"
+        "in vec3 outAttrib1;\n"
+        "in vec3 outAttrib2;\n"
+        "void main() {\n"
+        "  color = vec4(0);\n"
+        "}";
+
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("outAttrib1");
+    tfVaryings.push_back("outAttrib2");
+
+    mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+                                                   tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    ASSERT_NE(0u, mProgram);
+
+    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
+    glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(Vector3) * 2 * 6, nullptr, GL_STREAM_DRAW);
+
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+
+    glUseProgram(mProgram);
+    glBeginTransformFeedback(GL_TRIANGLES);
+    drawQuad(mProgram, "position", 0.5f);
+    glEndTransformFeedback();
+    glUseProgram(0);
+    ASSERT_GL_NO_ERROR();
+
+    const void *mapPointer =
+        glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(Vector3) * 2 * 6, GL_MAP_READ_BIT);
+    ASSERT_NE(nullptr, mapPointer);
+
+    const auto &quadVertices = GetQuadVertices();
+
+    const Vector3 *vecPointer = static_cast<const Vector3 *>(mapPointer);
+    for (unsigned int vectorIndex = 0; vectorIndex < 3; ++vectorIndex)
+    {
+        unsigned int stream1Index = vectorIndex * 2;
+        unsigned int stream2Index = vectorIndex * 2 + 1;
+        EXPECT_EQ(quadVertices[vectorIndex], vecPointer[stream1Index]);
+        EXPECT_EQ(quadVertices[vectorIndex], vecPointer[stream2Index]);
+    }
+    glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+class TransformFeedbackLifetimeTest : public TransformFeedbackTest
+{
+  protected:
+    TransformFeedbackLifetimeTest() : mVertexArray(0) {}
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenVertexArrays(1, &mVertexArray);
+        glBindVertexArray(mVertexArray);
+
+        std::vector<std::string> tfVaryings;
+        tfVaryings.push_back("gl_Position");
+        compileDefaultProgram(tfVaryings, GL_SEPARATE_ATTRIBS);
+
+        glGenBuffers(1, &mTransformFeedbackBuffer);
+        glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
+        glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, nullptr,
+                     GL_DYNAMIC_DRAW);
+        glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
+
+        glGenTransformFeedbacks(1, &mTransformFeedback);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteVertexArrays(1, &mVertexArray);
+        TransformFeedbackTest::TearDown();
+    }
+
+    GLuint mVertexArray;
+};
+
+// Tests a bug with state syncing and deleted transform feedback buffers.
+TEST_P(TransformFeedbackLifetimeTest, DeletedBuffer)
+{
+    // TODO(ynovikov): Obscure driver error on Intel HD 530 http://anglebug.com/1879
+    if (IsWindows() && IsIntel() && IsDesktopOpenGL())
+    {
+        std::cout << "Test skipped on Intel OpenGL on Windows." << std::endl;
+        return;
+    }
+
+    // First stream vertex data to mTransformFeedbackBuffer.
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+
+    glUseProgram(mProgram);
+
+    glBeginTransformFeedback(GL_TRIANGLES);
+    drawQuad(mProgram, "position", 0.5f, 1.0f, true);
+    glEndTransformFeedback();
+
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+
+    // TODO(jmadill): Remove this when http://anglebug.com/1351 is fixed.
+    glBindVertexArray(0);
+    drawQuad(mProgram, "position", 0.5f);
+    glBindVertexArray(1);
+
+    // Next, draw vertices with mTransformFeedbackBuffer. This will link to mVertexArray.
+    glBindBuffer(GL_ARRAY_BUFFER, mTransformFeedbackBuffer);
+    GLint loc = glGetAttribLocation(mProgram, "position");
+    ASSERT_NE(-1, loc);
+    glVertexAttribPointer(loc, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
+    glEnableVertexAttribArray(loc);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    // Delete resources, making a stranded pointer to mVertexArray in mTransformFeedbackBuffer.
+    glDeleteBuffers(1, &mTransformFeedbackBuffer);
+    mTransformFeedbackBuffer = 0;
+    glDeleteVertexArrays(1, &mVertexArray);
+    mVertexArray = 0;
+
+    // Then draw again with transform feedback, dereferencing the stranded pointer.
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
+    glBeginTransformFeedback(GL_TRIANGLES);
+    drawQuad(mProgram, "position", 0.5f, 1.0f, true);
+    glEndTransformFeedback();
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+class TransformFeedbackTestES31 : public TransformFeedbackTestBase
+{
+};
+
+// Test that program link fails in case that transform feedback names including same array element.
+TEST_P(TransformFeedbackTestES31, SameArrayElementVaryings)
+{
+    const std::string &vertexShaderSource =
+        "#version 310 es\n"
+        "in vec3 position;\n"
+        "out vec3 outAttribs[3];\n"
+        "void main() {"
+        "  outAttribs[0] = position;\n"
+        "  outAttribs[1] = vec3(0, 0, 0);\n"
+        "  outAttribs[2] = position;\n"
+        "  gl_Position = vec4(position, 1);\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "out vec4 color;\n"
+        "in vec3 outAttribs[3];\n"
+        "void main() {\n"
+        "  color = vec4(0);\n"
+        "}";
+
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("outAttribs");
+    tfVaryings.push_back("outAttribs[1]");
+
+    mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+                                                   tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    ASSERT_EQ(0u, mProgram);
+}
+
+// Test transform feedback names can be specified using array element.
+TEST_P(TransformFeedbackTestES31, DifferentArrayElementVaryings)
+{
+    const std::string &vertexShaderSource =
+        "#version 310 es\n"
+        "in vec3 position;\n"
+        "out vec3 outAttribs[3];\n"
+        "void main() {"
+        "  outAttribs[0] = position;\n"
+        "  outAttribs[1] = vec3(0, 0, 0);\n"
+        "  outAttribs[2] = position;\n"
+        "  gl_Position = vec4(position, 1);\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "out vec4 color;\n"
+        "in vec3 outAttribs[3];\n"
+        "void main() {\n"
+        "  color = vec4(0);\n"
+        "}";
+
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("outAttribs[0]");
+    tfVaryings.push_back("outAttribs[2]");
+
+    mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+                                                   tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    ASSERT_NE(0u, mProgram);
+
+    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
+    glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(Vector3) * 2 * 6, nullptr, GL_STREAM_DRAW);
+
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+
+    glUseProgram(mProgram);
+    glBeginTransformFeedback(GL_TRIANGLES);
+    drawQuad(mProgram, "position", 0.5f);
+    glEndTransformFeedback();
+    glUseProgram(0);
+    ASSERT_GL_NO_ERROR();
+
+    const GLvoid *mapPointer =
+        glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(Vector3) * 2 * 6, GL_MAP_READ_BIT);
+    ASSERT_NE(nullptr, mapPointer);
+
+    const auto &quadVertices = GetQuadVertices();
+
+    const Vector3 *vecPointer = static_cast<const Vector3 *>(mapPointer);
+    for (unsigned int vectorIndex = 0; vectorIndex < 3; ++vectorIndex)
+    {
+        unsigned int stream1Index = vectorIndex * 2;
+        unsigned int stream2Index = vectorIndex * 2 + 1;
+        EXPECT_EQ(quadVertices[vectorIndex], vecPointer[stream1Index]);
+        EXPECT_EQ(quadVertices[vectorIndex], vecPointer[stream2Index]);
+    }
+    glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(TransformFeedbackTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(TransformFeedbackLifetimeTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(TransformFeedbackTestES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/UniformBufferTest.cpp b/src/third_party/angle/src/tests/gl_tests/UniformBufferTest.cpp
new file mode 100644
index 0000000..f180d17
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/UniformBufferTest.cpp
@@ -0,0 +1,647 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+class UniformBufferTest : public ANGLETest
+{
+  protected:
+    UniformBufferTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (   #version 300 es\n
+            in vec4 position;
+            void main()
+            {
+                gl_Position = position;
+            }
+        );
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (   #version 300 es\n
+            precision highp float;
+            uniform uni {
+                vec4 color;
+            };
+
+            out vec4 fragColor;
+
+            void main()
+            {
+                fragColor = color;
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        ASSERT_NE(mProgram, 0u);
+
+        mUniformBufferIndex = glGetUniformBlockIndex(mProgram, "uni");
+        ASSERT_NE(mUniformBufferIndex, -1);
+
+        glGenBuffers(1, &mUniformBuffer);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteBuffers(1, &mUniformBuffer);
+        glDeleteProgram(mProgram);
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+    GLint mUniformBufferIndex;
+    GLuint mUniformBuffer;
+};
+
+// Basic UBO functionality.
+TEST_P(UniformBufferTest, Simple)
+{
+    glClear(GL_COLOR_BUFFER_BIT);
+    float floatData[4] = {0.5f, 0.75f, 0.25f, 1.0f};
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 4, floatData, GL_STATIC_DRAW);
+
+    glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
+
+    glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
+    drawQuad(mProgram, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
+}
+
+// Test that using a UBO with a non-zero offset and size actually works.
+// The first step of this test renders a color from a UBO with a zero offset.
+// The second step renders a color from a UBO with a non-zero offset.
+TEST_P(UniformBufferTest, UniformBufferRange)
+{
+    int px = getWindowWidth() / 2;
+    int py = getWindowHeight() / 2;
+
+    // Query the uniform buffer alignment requirement
+    GLint alignment;
+    glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
+
+    GLint64 maxUniformBlockSize;
+    glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
+    if (alignment >= maxUniformBlockSize)
+    {
+        // ANGLE doesn't implement UBO offsets for this platform.
+        // Ignore the test case.
+        return;
+    }
+
+    ASSERT_GL_NO_ERROR();
+
+    // Let's create a buffer which contains two vec4.
+    GLuint vec4Size = 4 * sizeof(float);
+    GLuint stride = 0;
+    do
+    {
+        stride += alignment;
+    }
+    while (stride < vec4Size);
+
+    std::vector<char> v(2 * stride);
+    float *first = reinterpret_cast<float*>(v.data());
+    float *second = reinterpret_cast<float*>(v.data() + stride);
+
+    first[0] = 10.f / 255.f;
+    first[1] = 20.f / 255.f;
+    first[2] = 30.f / 255.f;
+    first[3] = 40.f / 255.f;
+
+    second[0] = 110.f / 255.f;
+    second[1] = 120.f / 255.f;
+    second[2] = 130.f / 255.f;
+    second[3] = 140.f / 255.f;
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    // We use on purpose a size which is not a multiple of the alignment.
+    glBufferData(GL_UNIFORM_BUFFER, stride + vec4Size, v.data(), GL_STATIC_DRAW);
+
+    glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Bind the first part of the uniform buffer and draw
+    // Use a size which is smaller than the alignment to check
+    // to check that this case is handle correctly in the conversion to 11.1.
+    glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, vec4Size);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
+
+    // Bind the second part of the uniform buffer and draw
+    // Furthermore the D3D11.1 backend will internally round the vec4Size (16 bytes) to a stride (256 bytes)
+    // hence it will try to map the range [stride, 2 * stride] which is
+    // out-of-bound of the buffer bufferSize = stride + vec4Size < 2 * stride.
+    // Ensure that this behaviour works.
+    glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, stride, vec4Size);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(px, py, 110, 120, 130, 140);
+}
+
+// Test uniform block bindings.
+TEST_P(UniformBufferTest, UniformBufferBindings)
+{
+    int px = getWindowWidth() / 2;
+    int py = getWindowHeight() / 2;
+
+    ASSERT_GL_NO_ERROR();
+
+    // Let's create a buffer which contains one vec4.
+    GLuint vec4Size = 4 * sizeof(float);
+    std::vector<char> v(vec4Size);
+    float *first = reinterpret_cast<float*>(v.data());
+
+    first[0] = 10.f / 255.f;
+    first[1] = 20.f / 255.f;
+    first[2] = 30.f / 255.f;
+    first[3] = 40.f / 255.f;
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    glBufferData(GL_UNIFORM_BUFFER, vec4Size, v.data(), GL_STATIC_DRAW);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Try to bind the buffer to binding point 2
+    glUniformBlockBinding(mProgram, mUniformBufferIndex, 2);
+    glBindBufferBase(GL_UNIFORM_BUFFER, 2, mUniformBuffer);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
+
+    // Clear the framebuffer
+    glClearColor(0.0, 0.0, 0.0, 0.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(px, py, 0, 0, 0, 0);
+
+    // Try to bind the buffer to another binding point
+    glUniformBlockBinding(mProgram, mUniformBufferIndex, 5);
+    glBindBufferBase(GL_UNIFORM_BUFFER, 5, mUniformBuffer);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
+}
+
+// Test that ANGLE handles used but unbound UBO.
+// TODO: A test case shouldn't depend on the error code of an undefined behaviour. Move this to unit tests of the validation layer.
+TEST_P(UniformBufferTest, UnboundUniformBuffer)
+{
+    glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
+    glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
+    EXPECT_GL_NO_ERROR();
+
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Update a UBO many time and verify that ANGLE uses the latest version of the data.
+// https://code.google.com/p/angleproject/issues/detail?id=965
+TEST_P(UniformBufferTest, UniformBufferManyUpdates)
+{
+    // TODO(jmadill): Figure out why this fails on Intel OpenGL.
+    if (IsIntel() && IsOpenGL())
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    int px = getWindowWidth() / 2;
+    int py = getWindowHeight() / 2;
+
+    ASSERT_GL_NO_ERROR();
+
+    float data[4];
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    glBufferData(GL_UNIFORM_BUFFER, sizeof(data), nullptr, GL_DYNAMIC_DRAW);
+    glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
+    glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Repeteadly update the data and draw
+    for (size_t i = 0; i < 10; ++i)
+    {
+        data[0] = (i + 10.f) / 255.f;
+        data[1] = (i + 20.f) / 255.f;
+        data[2] = (i + 30.f) / 255.f;
+        data[3] = (i + 40.f) / 255.f;
+
+        glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(data), data);
+
+        drawQuad(mProgram, "position", 0.5f);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_PIXEL_EQ(px, py, i + 10, i + 20, i + 30, i + 40);
+    }
+}
+
+// Use a large number of buffer ranges (compared to the actual size of the UBO)
+TEST_P(UniformBufferTest, ManyUniformBufferRange)
+{
+    int px = getWindowWidth() / 2;
+    int py = getWindowHeight() / 2;
+
+    // Query the uniform buffer alignment requirement
+    GLint alignment;
+    glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
+
+    GLint64 maxUniformBlockSize;
+    glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
+    if (alignment >= maxUniformBlockSize)
+    {
+        // ANGLE doesn't implement UBO offsets for this platform.
+        // Ignore the test case.
+        return;
+    }
+
+    ASSERT_GL_NO_ERROR();
+
+    // Let's create a buffer which contains eight vec4.
+    GLuint vec4Size = 4 * sizeof(float);
+    GLuint stride = 0;
+    do
+    {
+        stride += alignment;
+    }
+    while (stride < vec4Size);
+
+    std::vector<char> v(8 * stride);
+
+    for (size_t i = 0; i < 8; ++i)
+    {
+        float *data = reinterpret_cast<float*>(v.data() + i * stride);
+
+        data[0] = (i + 10.f) / 255.f;
+        data[1] = (i + 20.f) / 255.f;
+        data[2] = (i + 30.f) / 255.f;
+        data[3] = (i + 40.f) / 255.f;
+    }
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    glBufferData(GL_UNIFORM_BUFFER, v.size(), v.data(), GL_STATIC_DRAW);
+
+    glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
+
+    EXPECT_GL_NO_ERROR();
+
+    // Bind each possible offset
+    for (size_t i = 0; i < 8; ++i)
+    {
+        glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, i * stride, stride);
+        drawQuad(mProgram, "position", 0.5f);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_PIXEL_EQ(px, py, 10 + i, 20 + i, 30 + i, 40 + i);
+    }
+
+    // Try to bind larger range
+    for (size_t i = 0; i < 7; ++i)
+    {
+        glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, i * stride, 2 * stride);
+        drawQuad(mProgram, "position", 0.5f);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_PIXEL_EQ(px, py, 10 + i, 20 + i, 30 + i, 40 + i);
+    }
+
+    // Try to bind even larger range
+    for (size_t i = 0; i < 5; ++i)
+    {
+        glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, i * stride, 4 * stride);
+        drawQuad(mProgram, "position", 0.5f);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_PIXEL_EQ(px, py, 10 + i, 20 + i, 30 + i, 40 + i);
+    }
+}
+
+// Tests that active uniforms have the right names.
+TEST_P(UniformBufferTest, ActiveUniformNames)
+{
+    const std::string &vertexShaderSource =
+        "#version 300 es\n"
+        "in vec2 position;\n"
+        "out vec2 v;\n"
+        "uniform blockName1 {\n"
+        "  float f1;\n"
+        "} instanceName1;\n"
+        "uniform blockName2 {\n"
+        "  float f2;\n"
+        "} instanceName2[1];\n"
+        "void main() {\n"
+        "  v = vec2(instanceName1.f1, instanceName2[0].f2);\n"
+        "  gl_Position = vec4(position, 0, 1);\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "in vec2 v;\n"
+        "out vec4 color;\n"
+        "void main() {\n"
+        "  color = vec4(v, 0, 1);\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    ASSERT_NE(0u, program);
+
+    GLint activeUniformBlocks;
+    glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &activeUniformBlocks);
+    ASSERT_EQ(2, activeUniformBlocks);
+
+    GLuint index = glGetUniformBlockIndex(program, "blockName1");
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+
+    index = glGetUniformBlockIndex(program, "blockName2[0]");
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+
+    GLint activeUniforms;
+    glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
+
+    ASSERT_EQ(2, activeUniforms);
+
+    GLint size;
+    GLenum type;
+    GLint maxLength;
+    GLsizei length;
+
+    glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
+    std::vector<GLchar> strUniformNameBuffer(maxLength + 1, 0);
+    const GLchar *uniformNames[1];
+    uniformNames[0] = "blockName1.f1";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strUniformNameBuffer[0]);
+    EXPECT_EQ(1, size);
+    EXPECT_GLENUM_EQ(GL_FLOAT, type);
+    EXPECT_EQ("blockName1.f1", std::string(&strUniformNameBuffer[0]));
+
+    uniformNames[0] = "blockName2.f2";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strUniformNameBuffer[0]);
+    EXPECT_EQ(1, size);
+    EXPECT_GLENUM_EQ(GL_FLOAT, type);
+    EXPECT_EQ("blockName2.f2", std::string(&strUniformNameBuffer[0]));
+}
+
+// Tests active uniforms and blocks when the layout is std140, shared and packed.
+TEST_P(UniformBufferTest, ActiveUniformNumberAndName)
+{
+    const std::string &vertexShaderSource =
+        "#version 300 es\n"
+        "in vec2 position;\n"
+        "out float v;\n"
+        "struct S {\n"
+        "  highp ivec3 a;\n"
+        "  mediump ivec2 b[4];\n"
+        "};\n"
+        "layout(std140) uniform blockName0 {\n"
+        "  S s0;\n"
+        "  lowp vec2 v0;\n"
+        "  S s1[2];\n"
+        "  highp uint u0;\n"
+        "};\n"
+        "layout(std140) uniform blockName1 {\n"
+        "  float f1;\n"
+        "  bool b1;\n"
+        "} instanceName1;\n"
+        "layout(shared) uniform blockName2 {\n"
+        "  float f2;\n"
+        "};\n"
+        "layout(packed) uniform blockName3 {\n"
+        "  float f3;\n"
+        "};\n"
+        "void main() {\n"
+        "  v = instanceName1.f1;\n"
+        "  gl_Position = vec4(position, 0, 1);\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "in float v;\n"
+        "out vec4 color;\n"
+        "void main() {\n"
+        "  color = vec4(v, 0, 0, 1);\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
+
+    // Note that the packed |blockName3| might (or might not) be optimized out.
+    GLint activeUniforms;
+    glGetProgramiv(program.get(), GL_ACTIVE_UNIFORMS, &activeUniforms);
+    EXPECT_GE(activeUniforms, 11);
+
+    GLint activeUniformBlocks;
+    glGetProgramiv(program.get(), GL_ACTIVE_UNIFORM_BLOCKS, &activeUniformBlocks);
+    EXPECT_GE(activeUniformBlocks, 3);
+
+    GLint maxLength, size;
+    GLenum type;
+    GLsizei length;
+    GLuint index;
+    const GLchar *uniformNames[1];
+    glGetProgramiv(program.get(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
+    std::vector<GLchar> strBuffer(maxLength + 1, 0);
+
+    uniformNames[0] = "s0.a";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    EXPECT_EQ(1, size);
+    EXPECT_EQ("s0.a", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "s0.b[0]";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(4, size);
+    EXPECT_EQ("s0.b[0]", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "v0";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, size);
+    EXPECT_EQ("v0", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "s1[0].a";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, size);
+    EXPECT_EQ("s1[0].a", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "s1[0].b[0]";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(4, size);
+    EXPECT_EQ("s1[0].b[0]", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "s1[1].a";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, size);
+    EXPECT_EQ("s1[1].a", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "s1[1].b[0]";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(4, size);
+    EXPECT_EQ("s1[1].b[0]", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "u0";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, size);
+    EXPECT_EQ("u0", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "blockName1.f1";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, size);
+    EXPECT_EQ("blockName1.f1", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "blockName1.b1";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, size);
+    EXPECT_EQ("blockName1.b1", std::string(&strBuffer[0]));
+
+    uniformNames[0] = "f2";
+    glGetUniformIndices(program, 1, uniformNames, &index);
+    EXPECT_NE(GL_INVALID_INDEX, index);
+    ASSERT_GL_NO_ERROR();
+    glGetActiveUniform(program.get(), index, maxLength, &length, &size, &type, &strBuffer[0]);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, size);
+    EXPECT_EQ("f2", std::string(&strBuffer[0]));
+}
+
+// Test that using a very large buffer to back a small uniform block works OK.
+TEST_P(UniformBufferTest, VeryLarge)
+{
+    glClear(GL_COLOR_BUFFER_BIT);
+    float floatData[4] = {0.5f, 0.75f, 0.25f, 1.0f};
+
+    GLsizei bigSize = 4096 * 64;
+    std::vector<GLubyte> zero(bigSize, 0);
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    glBufferData(GL_UNIFORM_BUFFER, bigSize, zero.data(), GL_STATIC_DRAW);
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(float) * 4, floatData);
+
+    glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
+
+    glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
+    drawQuad(mProgram, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
+}
+
+// Test that readback from a very large uniform buffer works OK.
+TEST_P(UniformBufferTest, VeryLargeReadback)
+{
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // Generate some random data.
+    GLsizei bigSize = 4096 * 64;
+    std::vector<GLubyte> expectedData(bigSize);
+    for (GLsizei index = 0; index < bigSize; ++index)
+    {
+        expectedData[index] = static_cast<GLubyte>(index);
+    }
+
+    // Initialize the GL buffer.
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    glBufferData(GL_UNIFORM_BUFFER, bigSize, expectedData.data(), GL_STATIC_DRAW);
+
+    // Do a small update.
+    GLsizei smallSize = sizeof(float) * 4;
+    std::array<float, 4> floatData = {{0.5f, 0.75f, 0.25f, 1.0f}};
+    memcpy(expectedData.data(), floatData.data(), smallSize);
+
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, smallSize, expectedData.data());
+
+    // Draw with the buffer.
+    glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
+    glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
+    drawQuad(mProgram, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
+
+    // Read back the large buffer data.
+    const void *mapPtr = glMapBufferRange(GL_UNIFORM_BUFFER, 0, bigSize, GL_MAP_READ_BIT);
+    ASSERT_GL_NO_ERROR();
+    const GLubyte *bytePtr = reinterpret_cast<const GLubyte *>(mapPtr);
+    std::vector<GLubyte> actualData(bytePtr, bytePtr + bigSize);
+    EXPECT_EQ(expectedData, actualData);
+
+    glUnmapBuffer(GL_UNIFORM_BUFFER);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(UniformBufferTest,
+                       ES3_D3D11(),
+                       ES3_D3D11_FL11_1(),
+                       ES3_D3D11_FL11_1_REFERENCE(),
+                       ES3_OPENGL(),
+                       ES3_OPENGLES());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/UniformTest.cpp b/src/third_party/angle/src/tests/gl_tests/UniformTest.cpp
new file mode 100644
index 0000000..4ecc3d7
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/UniformTest.cpp
@@ -0,0 +1,938 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include <array>
+#include <cmath>
+
+using namespace angle;
+
+namespace
+{
+
+class UniformTest : public ANGLETest
+{
+  protected:
+    UniformTest() : mProgram(0), mUniformFLocation(-1), mUniformILocation(-1), mUniformBLocation(-1)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string &vertexShader = "void main() { gl_Position = vec4(1); }";
+        const std::string &fragShader =
+            "precision mediump float;\n"
+            "uniform float uniF;\n"
+            "uniform int uniI;\n"
+            "uniform bool uniB;\n"
+            "uniform bool uniBArr[4];\n"
+            "void main() {\n"
+            "  gl_FragColor = vec4(uniF + float(uniI));\n"
+            "  gl_FragColor += vec4(uniB ? 1.0 : 0.0);\n"
+            "  gl_FragColor += vec4(uniBArr[0] ? 1.0 : 0.0);\n"
+            "}";
+
+        mProgram = CompileProgram(vertexShader, fragShader);
+        ASSERT_NE(mProgram, 0u);
+
+        mUniformFLocation = glGetUniformLocation(mProgram, "uniF");
+        ASSERT_NE(mUniformFLocation, -1);
+
+        mUniformILocation = glGetUniformLocation(mProgram, "uniI");
+        ASSERT_NE(mUniformILocation, -1);
+
+        mUniformBLocation = glGetUniformLocation(mProgram, "uniB");
+        ASSERT_NE(mUniformBLocation, -1);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+    GLint mUniformFLocation;
+    GLint mUniformILocation;
+    GLint mUniformBLocation;
+};
+
+TEST_P(UniformTest, GetUniformNoCurrentProgram)
+{
+    glUseProgram(mProgram);
+    glUniform1f(mUniformFLocation, 1.0f);
+    glUniform1i(mUniformILocation, 1);
+    glUseProgram(0);
+
+    GLfloat f;
+    glGetnUniformfvEXT(mProgram, mUniformFLocation, 4, &f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1.0f, f);
+
+    glGetUniformfv(mProgram, mUniformFLocation, &f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1.0f, f);
+
+    GLint i;
+    glGetnUniformivEXT(mProgram, mUniformILocation, 4, &i);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, i);
+
+    glGetUniformiv(mProgram, mUniformILocation, &i);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_EQ(1, i);
+}
+
+TEST_P(UniformTest, UniformArrayLocations)
+{
+    // TODO(geofflang): Figure out why this is broken on Intel OpenGL
+    if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel OpenGL." << std::endl;
+        return;
+    }
+
+    const std::string vertexShader = SHADER_SOURCE
+    (
+        precision mediump float;
+        uniform float uPosition[4];
+        void main(void)
+        {
+            gl_Position = vec4(uPosition[0], uPosition[1], uPosition[2], uPosition[3]);
+        }
+    );
+
+    const std::string fragShader = SHADER_SOURCE
+    (
+        precision mediump float;
+        uniform float uColor[4];
+        void main(void)
+        {
+            gl_FragColor = vec4(uColor[0], uColor[1], uColor[2], uColor[3]);
+        }
+    );
+
+    GLuint program = CompileProgram(vertexShader, fragShader);
+    ASSERT_NE(program, 0u);
+
+    // Array index zero should be equivalent to the un-indexed uniform
+    EXPECT_NE(-1, glGetUniformLocation(program, "uPosition"));
+    EXPECT_EQ(glGetUniformLocation(program, "uPosition"), glGetUniformLocation(program, "uPosition[0]"));
+
+    EXPECT_NE(-1, glGetUniformLocation(program, "uColor"));
+    EXPECT_EQ(glGetUniformLocation(program, "uColor"), glGetUniformLocation(program, "uColor[0]"));
+
+    // All array uniform locations should be unique
+    GLint positionLocations[4] =
+    {
+        glGetUniformLocation(program, "uPosition[0]"),
+        glGetUniformLocation(program, "uPosition[1]"),
+        glGetUniformLocation(program, "uPosition[2]"),
+        glGetUniformLocation(program, "uPosition[3]"),
+    };
+
+    GLint colorLocations[4] =
+    {
+        glGetUniformLocation(program, "uColor[0]"),
+        glGetUniformLocation(program, "uColor[1]"),
+        glGetUniformLocation(program, "uColor[2]"),
+        glGetUniformLocation(program, "uColor[3]"),
+    };
+
+    for (size_t i = 0; i < 4; i++)
+    {
+        EXPECT_NE(-1, positionLocations[i]);
+        EXPECT_NE(-1, colorLocations[i]);
+
+        for (size_t j = i + 1; j < 4; j++)
+        {
+            EXPECT_NE(positionLocations[i], positionLocations[j]);
+            EXPECT_NE(colorLocations[i], colorLocations[j]);
+        }
+    }
+
+    glDeleteProgram(program);
+}
+
+// Test that float to integer GetUniform rounds values correctly.
+TEST_P(UniformTest, FloatUniformStateQuery)
+{
+    std::vector<double> inValues;
+    std::vector<GLfloat> expectedFValues;
+    std::vector<GLint> expectedIValues;
+
+    double intMaxD = static_cast<double>(std::numeric_limits<GLint>::max());
+    double intMinD = static_cast<double>(std::numeric_limits<GLint>::min());
+
+    // TODO(jmadill): Investigate rounding of .5
+    inValues.push_back(-1.0);
+    inValues.push_back(-0.6);
+    // inValues.push_back(-0.5); // undefined behaviour?
+    inValues.push_back(-0.4);
+    inValues.push_back(0.0);
+    inValues.push_back(0.4);
+    // inValues.push_back(0.5); // undefined behaviour?
+    inValues.push_back(0.6);
+    inValues.push_back(1.0);
+    inValues.push_back(999999.2);
+    inValues.push_back(intMaxD * 2.0);
+    inValues.push_back(intMaxD + 1.0);
+    inValues.push_back(intMinD * 2.0);
+    inValues.push_back(intMinD - 1.0);
+
+    for (double value : inValues)
+    {
+        expectedFValues.push_back(static_cast<GLfloat>(value));
+
+        double clampedValue = std::max(intMinD, std::min(intMaxD, value));
+        double rounded = round(clampedValue);
+        expectedIValues.push_back(static_cast<GLint>(rounded));
+    }
+
+    glUseProgram(mProgram);
+    ASSERT_GL_NO_ERROR();
+
+    for (size_t index = 0; index < inValues.size(); ++index)
+    {
+        GLfloat inValue       = static_cast<GLfloat>(inValues[index]);
+        GLfloat expectedValue = expectedFValues[index];
+
+        glUniform1f(mUniformFLocation, inValue);
+        GLfloat testValue;
+        glGetUniformfv(mProgram, mUniformFLocation, &testValue);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(expectedValue, testValue);
+    }
+
+    for (size_t index = 0; index < inValues.size(); ++index)
+    {
+        GLfloat inValue     = static_cast<GLfloat>(inValues[index]);
+        GLint expectedValue = expectedIValues[index];
+
+        glUniform1f(mUniformFLocation, inValue);
+        GLint testValue;
+        glGetUniformiv(mProgram, mUniformFLocation, &testValue);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(expectedValue, testValue);
+    }
+}
+
+// Test that integer to float GetUniform rounds values correctly.
+TEST_P(UniformTest, IntUniformStateQuery)
+{
+    std::vector<GLint> inValues;
+    std::vector<GLint> expectedIValues;
+    std::vector<GLfloat> expectedFValues;
+
+    GLint intMax = std::numeric_limits<GLint>::max();
+    GLint intMin = std::numeric_limits<GLint>::min();
+
+    inValues.push_back(-1);
+    inValues.push_back(0);
+    inValues.push_back(1);
+    inValues.push_back(999999);
+    inValues.push_back(intMax);
+    inValues.push_back(intMax - 1);
+    inValues.push_back(intMin);
+    inValues.push_back(intMin + 1);
+
+    for (GLint value : inValues)
+    {
+        expectedIValues.push_back(value);
+        expectedFValues.push_back(static_cast<GLfloat>(value));
+    }
+
+    glUseProgram(mProgram);
+    ASSERT_GL_NO_ERROR();
+
+    for (size_t index = 0; index < inValues.size(); ++index)
+    {
+        GLint inValue       = inValues[index];
+        GLint expectedValue = expectedIValues[index];
+
+        glUniform1i(mUniformILocation, inValue);
+        GLint testValue;
+        glGetUniformiv(mProgram, mUniformILocation, &testValue);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(expectedValue, testValue);
+    }
+
+    for (size_t index = 0; index < inValues.size(); ++index)
+    {
+        GLint inValue         = inValues[index];
+        GLfloat expectedValue = expectedFValues[index];
+
+        glUniform1i(mUniformILocation, inValue);
+        GLfloat testValue;
+        glGetUniformfv(mProgram, mUniformILocation, &testValue);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(expectedValue, testValue);
+    }
+}
+
+// Test that queries of boolean uniforms round correctly.
+TEST_P(UniformTest, BooleanUniformStateQuery)
+{
+    glUseProgram(mProgram);
+    GLint intValue     = 0;
+    GLfloat floatValue = 0.0f;
+
+    // Calling Uniform1i
+    glUniform1i(mUniformBLocation, GL_FALSE);
+
+    glGetUniformiv(mProgram, mUniformBLocation, &intValue);
+    EXPECT_EQ(0, intValue);
+
+    glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
+    EXPECT_EQ(0.0f, floatValue);
+
+    glUniform1i(mUniformBLocation, GL_TRUE);
+
+    glGetUniformiv(mProgram, mUniformBLocation, &intValue);
+    EXPECT_EQ(1, intValue);
+
+    glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
+    EXPECT_EQ(1.0f, floatValue);
+
+    // Calling Uniform1f
+    glUniform1f(mUniformBLocation, 0.0f);
+
+    glGetUniformiv(mProgram, mUniformBLocation, &intValue);
+    EXPECT_EQ(0, intValue);
+
+    glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
+    EXPECT_EQ(0.0f, floatValue);
+
+    glUniform1f(mUniformBLocation, 1.0f);
+
+    glGetUniformiv(mProgram, mUniformBLocation, &intValue);
+    EXPECT_EQ(1, intValue);
+
+    glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
+    EXPECT_EQ(1.0f, floatValue);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test queries for arrays of boolean uniforms.
+TEST_P(UniformTest, BooleanArrayUniformStateQuery)
+{
+    glUseProgram(mProgram);
+    GLint boolValuesi[4]   = {0, 1, 0, 1};
+    GLfloat boolValuesf[4] = {0, 1, 0, 1};
+
+    GLint locations[4] = {
+        glGetUniformLocation(mProgram, "uniBArr"),
+        glGetUniformLocation(mProgram, "uniBArr[1]"),
+        glGetUniformLocation(mProgram, "uniBArr[2]"),
+        glGetUniformLocation(mProgram, "uniBArr[3]"),
+    };
+
+    // Calling Uniform1iv
+    glUniform1iv(locations[0], 4, boolValuesi);
+
+    for (unsigned int idx = 0; idx < 4; ++idx)
+    {
+        int value = -1;
+        glGetUniformiv(mProgram, locations[idx], &value);
+        EXPECT_EQ(boolValuesi[idx], value);
+    }
+
+    for (unsigned int idx = 0; idx < 4; ++idx)
+    {
+        float value = -1.0f;
+        glGetUniformfv(mProgram, locations[idx], &value);
+        EXPECT_EQ(boolValuesf[idx], value);
+    }
+
+    // Calling Uniform1fv
+    glUniform1fv(locations[0], 4, boolValuesf);
+
+    for (unsigned int idx = 0; idx < 4; ++idx)
+    {
+        int value = -1;
+        glGetUniformiv(mProgram, locations[idx], &value);
+        EXPECT_EQ(boolValuesi[idx], value);
+    }
+
+    for (unsigned int idx = 0; idx < 4; ++idx)
+    {
+        float value = -1.0f;
+        glGetUniformfv(mProgram, locations[idx], &value);
+        EXPECT_EQ(boolValuesf[idx], value);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+class UniformTestES3 : public ANGLETest
+{
+  protected:
+    UniformTestES3() : mProgram(0) {}
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+    }
+
+    void TearDown() override
+    {
+        if (mProgram != 0)
+        {
+            glDeleteProgram(mProgram);
+            mProgram = 0;
+        }
+    }
+
+    GLuint mProgram;
+};
+
+// Test queries for transposed arrays of non-square matrix uniforms.
+TEST_P(UniformTestES3, TranposedMatrixArrayUniformStateQuery)
+{
+    const std::string &vertexShader =
+        "#version 300 es\n"
+        "void main() { gl_Position = vec4(1); }";
+    const std::string &fragShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform mat3x2 uniMat3x2[5];\n"
+        "out vec4 color;\n"
+        "void main() {\n"
+        "  color = vec4(uniMat3x2[0][0][0]);\n"
+        "}";
+
+    mProgram = CompileProgram(vertexShader, fragShader);
+    ASSERT_NE(mProgram, 0u);
+
+    glUseProgram(mProgram);
+
+    std::vector<GLfloat> transposedValues;
+
+    for (size_t arrayElement = 0; arrayElement < 5; ++arrayElement)
+    {
+        transposedValues.push_back(1.0f + arrayElement);
+        transposedValues.push_back(3.0f + arrayElement);
+        transposedValues.push_back(5.0f + arrayElement);
+        transposedValues.push_back(2.0f + arrayElement);
+        transposedValues.push_back(4.0f + arrayElement);
+        transposedValues.push_back(6.0f + arrayElement);
+    }
+
+    // Setting as a clump
+    GLint baseLocation = glGetUniformLocation(mProgram, "uniMat3x2");
+    ASSERT_NE(-1, baseLocation);
+
+    glUniformMatrix3x2fv(baseLocation, 5, GL_TRUE, &transposedValues[0]);
+
+    for (size_t arrayElement = 0; arrayElement < 5; ++arrayElement)
+    {
+        std::stringstream nameStr;
+        nameStr << "uniMat3x2[" << arrayElement << "]";
+        std::string name = nameStr.str();
+        GLint location = glGetUniformLocation(mProgram, name.c_str());
+        ASSERT_NE(-1, location);
+
+        std::vector<GLfloat> sequentialValues(6, 0);
+        glGetUniformfv(mProgram, location, &sequentialValues[0]);
+
+        ASSERT_GL_NO_ERROR();
+
+        for (size_t comp = 0; comp < 6; ++comp)
+        {
+            EXPECT_EQ(static_cast<GLfloat>(comp + 1 + arrayElement), sequentialValues[comp]);
+        }
+    }
+}
+
+// Check that trying setting too many elements of an array doesn't overflow
+TEST_P(UniformTestES3, OverflowArray)
+{
+    const std::string &vertexShader =
+        "#version 300 es\n"
+        "void main() { gl_Position = vec4(1); }";
+    const std::string &fragShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform float uniF[5];\n"
+        "uniform mat3x2 uniMat3x2[5];\n"
+        "out vec4 color;\n"
+        "void main() {\n"
+        "  color = vec4(uniMat3x2[0][0][0] + uniF[0]);\n"
+        "}";
+
+    mProgram = CompileProgram(vertexShader, fragShader);
+    ASSERT_NE(mProgram, 0u);
+
+    glUseProgram(mProgram);
+
+    const size_t kOverflowSize = 10000;
+    std::vector<GLfloat> values(10000 * 6);
+
+    // Setting as a clump
+    GLint floatLocation = glGetUniformLocation(mProgram, "uniF");
+    ASSERT_NE(-1, floatLocation);
+    GLint matLocation = glGetUniformLocation(mProgram, "uniMat3x2");
+    ASSERT_NE(-1, matLocation);
+
+    // Set too many float uniforms
+    glUniform1fv(floatLocation, kOverflowSize, &values[0]);
+
+    // Set too many matrix uniforms, transposed or not
+    glUniformMatrix3x2fv(matLocation, kOverflowSize, GL_FALSE, &values[0]);
+    glUniformMatrix3x2fv(matLocation, kOverflowSize, GL_TRUE, &values[0]);
+
+    // Same checks but with offsets
+    GLint floatLocationOffset = glGetUniformLocation(mProgram, "uniF[3]");
+    ASSERT_NE(-1, floatLocationOffset);
+    GLint matLocationOffset = glGetUniformLocation(mProgram, "uniMat3x2[3]");
+    ASSERT_NE(-1, matLocationOffset);
+
+    glUniform1fv(floatLocationOffset, kOverflowSize, &values[0]);
+    glUniformMatrix3x2fv(matLocationOffset, kOverflowSize, GL_FALSE, &values[0]);
+    glUniformMatrix3x2fv(matLocationOffset, kOverflowSize, GL_TRUE, &values[0]);
+}
+
+// Check setting a sampler uniform
+TEST_P(UniformTest, Sampler)
+{
+    const std::string &vertShader =
+        "uniform sampler2D tex2D;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(0, 0, 0, 1);\n"
+        "}";
+
+    const std::string &fragShader =
+        "precision mediump float;\n"
+        "uniform sampler2D tex2D;\n"
+        "void main() {\n"
+        "  gl_FragColor = texture2D(tex2D, vec2(0, 0));\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(program, vertShader, fragShader);
+
+    GLint location = glGetUniformLocation(program.get(), "tex2D");
+    ASSERT_NE(-1, location);
+
+    const GLint sampler[] = {0, 0, 0, 0};
+
+    // before UseProgram
+    glUniform1i(location, sampler[0]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glUseProgram(program.get());
+
+    // Uniform1i
+    glUniform1i(location, sampler[0]);
+    glUniform1iv(location, 1, sampler);
+    EXPECT_GL_NO_ERROR();
+
+    // Uniform{234}i
+    glUniform2i(location, sampler[0], sampler[0]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform3i(location, sampler[0], sampler[0], sampler[0]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform4i(location, sampler[0], sampler[0], sampler[0], sampler[0]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform2iv(location, 1, sampler);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform3iv(location, 1, sampler);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform4iv(location, 1, sampler);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Uniform{1234}f
+    const GLfloat f[] = {0, 0, 0, 0};
+    glUniform1f(location, f[0]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform2f(location, f[0], f[0]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform3f(location, f[0], f[0], f[0]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform4f(location, f[0], f[0], f[0], f[0]);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform1fv(location, 1, f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform2fv(location, 1, f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform3fv(location, 1, f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glUniform4fv(location, 1, f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // < 0 or >= max
+    GLint tooHigh;
+    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &tooHigh);
+    constexpr GLint tooLow[] = {-1};
+    glUniform1i(location, tooLow[0]);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glUniform1iv(location, 1, tooLow);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glUniform1i(location, tooHigh);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glUniform1iv(location, 1, &tooHigh);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+// Check that sampler uniforms only show up one time in the list
+TEST_P(UniformTest, SamplerUniformsAppearOnce)
+{
+    int maxVertexTextureImageUnits = 0;
+    glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureImageUnits);
+
+    if (maxVertexTextureImageUnits == 0)
+    {
+        std::cout << "Renderer doesn't support vertex texture fetch, skipping test" << std::endl;
+        return;
+    }
+
+    const std::string &vertShader =
+        "attribute vec2 position;\n"
+        "uniform sampler2D tex2D;\n"
+        "varying vec4 color;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(position, 0, 1);\n"
+        "  color = texture2D(tex2D, vec2(0));\n"
+        "}";
+
+    const std::string &fragShader =
+        "precision mediump float;\n"
+        "varying vec4 color;\n"
+        "uniform sampler2D tex2D;\n"
+        "void main() {\n"
+        "  gl_FragColor = texture2D(tex2D, vec2(0)) + color;\n"
+        "}";
+
+    GLuint program = CompileProgram(vertShader, fragShader);
+    ASSERT_NE(0u, program);
+
+    GLint activeUniformsCount = 0;
+    glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniformsCount);
+    ASSERT_EQ(1, activeUniformsCount);
+
+    GLint size       = 0;
+    GLenum type      = GL_NONE;
+    GLchar name[120] = {0};
+    glGetActiveUniform(program, 0, 100, nullptr, &size, &type, name);
+    EXPECT_EQ(1, size);
+    EXPECT_GLENUM_EQ(GL_SAMPLER_2D, type);
+    EXPECT_STREQ("tex2D", name);
+
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteProgram(program);
+}
+
+template <typename T, typename GetUniformV>
+void CheckOneElement(GetUniformV getUniformv,
+                     GLuint program,
+                     const std::string &name,
+                     int components,
+                     T canary)
+{
+    // The buffer getting the results has three chunks
+    //  - A chunk to see underflows
+    //  - A chunk that will hold the result
+    //  - A chunk to see overflows for when components = kChunkSize
+    static const size_t kChunkSize = 4;
+    std::array<T, 3 * kChunkSize> buffer;
+    buffer.fill(canary);
+
+    GLint location = glGetUniformLocation(program, name.c_str());
+    ASSERT_NE(location, -1);
+
+    getUniformv(program, location, &buffer[kChunkSize]);
+    for (size_t i = 0; i < kChunkSize; i++)
+    {
+        ASSERT_EQ(canary, buffer[i]);
+    }
+    for (size_t i = kChunkSize + components; i < buffer.size(); i++)
+    {
+        ASSERT_EQ(canary, buffer[i]);
+    }
+}
+
+// Check that getting an element array doesn't return the whole array.
+TEST_P(UniformTestES3, ReturnsOnlyOneArrayElement)
+{
+    static const size_t kArraySize = 4;
+    struct UniformArrayInfo
+    {
+        UniformArrayInfo(std::string type, std::string name, int components)
+            : type(type), name(name), components(components)
+        {
+        }
+        std::string type;
+        std::string name;
+        int components;
+    };
+
+    // Check for various number of components and types
+    std::vector<UniformArrayInfo> uniformArrays;
+    uniformArrays.emplace_back("bool", "uBool", 1);
+    uniformArrays.emplace_back("vec2", "uFloat", 2);
+    uniformArrays.emplace_back("ivec3", "uInt", 3);
+    uniformArrays.emplace_back("uvec4", "uUint", 4);
+
+    std::ostringstream uniformStream;
+    std::ostringstream additionStream;
+    for (const auto &array : uniformArrays)
+    {
+        uniformStream << "uniform " << array.type << " " << array.name << "["
+                      << ToString(kArraySize) << "];\n";
+
+        // We need to make use of the uniforms or they get compiled out.
+        for (int i = 0; i < 4; i++)
+        {
+            if (array.components == 1)
+            {
+                additionStream << " + float(" << array.name << "[" << i << "])";
+            }
+            else
+            {
+                for (int component = 0; component < array.components; component++)
+                {
+                    additionStream << " + float(" << array.name << "[" << i << "][" << component
+                                   << "])";
+                }
+            }
+        }
+    }
+
+    const std::string &vertexShader =
+        "#version 300 es\n" +
+        uniformStream.str() +
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(1.0" + additionStream.str() + ");\n"
+        "}";
+
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 color;\n"
+        "void main ()\n"
+        "{\n"
+        "    color = vec4(1, 0, 0, 1);\n"
+        "}";
+
+    mProgram = CompileProgram(vertexShader, fragmentShader);
+    ASSERT_NE(0u, mProgram);
+
+    glUseProgram(mProgram);
+
+    for (const auto &uniformArray : uniformArrays)
+    {
+        for (size_t index = 0; index < kArraySize; index++)
+        {
+            std::string strIndex = "[" + ToString(index) + "]";
+            // Check all the different glGetUniformv functions
+            CheckOneElement<float>(glGetUniformfv, mProgram, uniformArray.name + strIndex,
+                                   uniformArray.components, 42.4242f);
+            CheckOneElement<int>(glGetUniformiv, mProgram, uniformArray.name + strIndex,
+                                 uniformArray.components, 0x7BADBED5);
+            CheckOneElement<unsigned int>(glGetUniformuiv, mProgram, uniformArray.name + strIndex,
+                                          uniformArray.components, 0xDEADBEEF);
+        }
+    }
+}
+
+class UniformTestES31 : public ANGLETest
+{
+  protected:
+    UniformTestES31() : mProgram(0) {}
+
+    void SetUp() override { ANGLETest::SetUp(); }
+
+    void TearDown() override
+    {
+        if (mProgram != 0)
+        {
+            glDeleteProgram(mProgram);
+            mProgram = 0;
+        }
+    }
+
+    GLuint mProgram;
+};
+
+// Test that uniform locations get set correctly for structure members.
+// ESSL 3.10.4 section 4.4.3.
+TEST_P(UniformTestES31, StructLocationLayoutQualifier)
+{
+    const std::string &vertShader =
+        "#version 310 es\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0);\n"
+        "}";
+
+    const std::string &fragShader =
+        "#version 310 es\n"
+        "out highp vec4 my_FragColor;\n"
+        "struct S\n"
+        "{\n"
+        "    highp float f;\n"
+        "    highp float f2;\n"
+        "};\n"
+        "uniform layout(location=12) S uS;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(uS.f, uS.f2, 0, 1);\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(program, vertShader, fragShader);
+
+    EXPECT_EQ(12, glGetUniformLocation(program.get(), "uS.f"));
+    EXPECT_EQ(13, glGetUniformLocation(program.get(), "uS.f2"));
+}
+
+// Set uniform location with a layout qualifier in the fragment shader. The same uniform exists in
+// the vertex shader, but doesn't have a location specified there.
+TEST_P(UniformTestES31, UniformLocationInFragmentShader)
+{
+    const std::string &vertShader =
+        "#version 310 es\n"
+        "uniform highp sampler2D tex2D;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = texture(tex2D, vec2(0));\n"
+        "}";
+
+    const std::string &fragShader =
+        "#version 310 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform layout(location=12) highp sampler2D tex2D;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = texture(tex2D, vec2(0));\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(program, vertShader, fragShader);
+
+    EXPECT_EQ(12, glGetUniformLocation(program.get(), "tex2D"));
+}
+
+// Test two unused uniforms that have the same location.
+// ESSL 3.10.4 section 4.4.3: "No two default-block uniform variables in the program can have the
+// same location, even if they are unused, otherwise a compiler or linker error will be generated."
+TEST_P(UniformTestES31, UnusedUniformsConflictingLocation)
+{
+    const std::string &vertShader =
+        "#version 310 es\n"
+        "uniform layout(location=12) highp sampler2D texA;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0);\n"
+        "}";
+
+    const std::string &fragShader =
+        "#version 310 es\n"
+        "out highp vec4 my_FragColor;\n"
+        "uniform layout(location=12) highp sampler2D texB;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(0);\n"
+        "}";
+
+    mProgram = CompileProgram(vertShader, fragShader);
+    EXPECT_EQ(0u, mProgram);
+}
+
+// Test two unused uniforms that have overlapping locations once all array elements are taken into
+// account.
+// ESSL 3.10.4 section 4.4.3: "No two default-block uniform variables in the program can have the
+// same location, even if they are unused, otherwise a compiler or linker error will be generated."
+TEST_P(UniformTestES31, UnusedUniformArraysConflictingLocation)
+{
+    const std::string &vertShader =
+        "#version 310 es\n"
+        "uniform layout(location=11) highp vec4 uA[2];\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0);\n"
+        "}";
+
+    const std::string &fragShader =
+        "#version 310 es\n"
+        "out highp vec4 my_FragColor;\n"
+        "uniform layout(location=12) highp vec4 uB;\n"
+        "void main()\n"
+        "{\n"
+        "    my_FragColor = vec4(0);\n"
+        "}";
+
+    mProgram = CompileProgram(vertShader, fragShader);
+    EXPECT_EQ(0u, mProgram);
+}
+
+// Test a uniform struct containing a non-square matrix and a boolean.
+// Minimal test case for a bug revealed by dEQP tests.
+TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool)
+{
+    const std::string &vertShader =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "in highp vec4 a_position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = a_position;\n"
+        "}\n";
+
+    const std::string &fragShader =
+        "#version 300 es\n"
+        "precision highp float;\n"
+        "out highp vec4 my_color;\n"
+        "struct S\n"
+        "{\n"
+        "    mat2x4 m;\n"
+        "    bool b;\n"
+        "};\n"
+        "uniform S uni;\n"
+        "void main()\n"
+        "{\n"
+        "    my_color = vec4(1.0);\n"
+        "    if (!uni.b) { my_color.g = 0.0; }"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vertShader, fragShader);
+
+    glUseProgram(program.get());
+
+    GLint location = glGetUniformLocation(program.get(), "uni.b");
+    ASSERT_NE(-1, location);
+    glUniform1i(location, 1);
+
+    drawQuad(program.get(), "a_position", 0.0f);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(UniformTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(UniformTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+ANGLE_INSTANTIATE_TEST(UniformTestES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/UnpackAlignmentTest.cpp b/src/third_party/angle/src/tests/gl_tests/UnpackAlignmentTest.cpp
new file mode 100644
index 0000000..2a3f76b
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/UnpackAlignmentTest.cpp
@@ -0,0 +1,325 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class UnpackAlignmentTest : public ANGLETest
+{
+  protected:
+    UnpackAlignmentTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+
+        mProgram = 0;
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+
+            void main()
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            uniform sampler2D tex;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, vec2(0.0, 1.0));
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    void getPixelSize(GLenum format, GLenum type, unsigned int* size)
+    {
+        switch (type)
+        {
+          case GL_UNSIGNED_SHORT_5_5_5_1:
+          case GL_UNSIGNED_SHORT_5_6_5:
+          case GL_UNSIGNED_SHORT_4_4_4_4:
+            *size = sizeof(GLushort);
+            break;
+
+          case GL_UNSIGNED_BYTE:
+            {
+                unsigned int compCount = 0;
+                switch (format)
+                {
+                  case GL_RGBA:            compCount = 4; break;
+                  case GL_RGB:             compCount = 3; break;
+                  case GL_LUMINANCE_ALPHA: compCount = 2; break;
+                  case GL_LUMINANCE:       compCount = 1; break;
+                  case GL_ALPHA:           compCount = 1; break;
+                  default:                 FAIL() << "unknown pixel format.";
+                }
+                *size = sizeof(GLubyte) * compCount;
+            }
+            break;
+          default:
+            FAIL() << "unknown pixel type.";
+        }
+    }
+
+    bool formatHasRGB(GLenum format)
+    {
+        return (format != GL_ALPHA);
+    }
+
+    void testAlignment(int alignment, unsigned int offset, GLenum format, GLenum type)
+    {
+        static const unsigned int width = 7;
+        static const unsigned int height = 2;
+
+        glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+
+        GLint readbackAlignment;
+        glGetIntegerv(GL_UNPACK_ALIGNMENT, &readbackAlignment);
+        EXPECT_EQ(alignment, readbackAlignment);
+
+        GLubyte buf[1024];
+        memset(buf, 0, sizeof(buf));
+
+        unsigned int pixelSize;
+        getPixelSize(format, type, &pixelSize);
+        for (unsigned int i = 0; i < pixelSize; i++)
+        {
+            buf[offset+i] = 0xFF;
+        }
+
+        GLuint tex;
+        glGenTextures(1, &tex);
+        glBindTexture(GL_TEXTURE_2D, tex);
+
+        glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, &buf[0]);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+        drawQuad(mProgram, "position", 0.5f);
+
+        GLubyte expectedRGB = formatHasRGB(format) ? 255 : 0;
+        EXPECT_PIXEL_EQ(0, 0, expectedRGB, expectedRGB, expectedRGB, 255);
+
+        glDeleteTextures(1, &tex);
+    }
+
+    GLuint mProgram;
+};
+
+TEST_P(UnpackAlignmentTest, DefaultAlignment)
+{
+    GLint defaultAlignment;
+    glGetIntegerv(GL_UNPACK_ALIGNMENT, &defaultAlignment);
+    EXPECT_EQ(defaultAlignment, 4);
+}
+
+
+TEST_P(UnpackAlignmentTest, Alignment1RGBAUByte)
+{
+    testAlignment(1, 7 * 4, GL_RGBA, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment1RGBUByte)
+{
+    testAlignment(1, 7 * 3, GL_RGB, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment1RGBAUShort4444)
+{
+    testAlignment(1, 7 * 2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment1RGBAUShort5551)
+{
+    testAlignment(1, 7 * 2, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment1RGBAUShort565)
+{
+    testAlignment(1, 7 * 2, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment1LAUByte)
+{
+    testAlignment(1, 7 * 2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment1LUByte)
+{
+    testAlignment(1, 7, GL_LUMINANCE, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment1AUByte)
+{
+    testAlignment(1, 7, GL_ALPHA, GL_UNSIGNED_BYTE);
+}
+
+
+TEST_P(UnpackAlignmentTest, Alignment2RGBAUByte)
+{
+    testAlignment(2, 7 * 4, GL_RGBA, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment2RGBUByte)
+{
+    testAlignment(2, 7 * 3 + 1, GL_RGB, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment2RGBAUShort4444)
+{
+    testAlignment(2, 7 * 2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment2RGBAUShort5551)
+{
+    testAlignment(2, 7 * 2, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment2RGBAUShort565)
+{
+    testAlignment(2, 7 * 2, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment2LAUByte)
+{
+    testAlignment(2, 7 * 2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment2LAByte)
+{
+    testAlignment(2, 7 + 1, GL_LUMINANCE, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment2AUByte)
+{
+    testAlignment(2, 7 + 1, GL_ALPHA, GL_UNSIGNED_BYTE);
+}
+
+
+TEST_P(UnpackAlignmentTest, Alignment4RGBAUByte)
+{
+    testAlignment(4, 7 * 4, GL_RGBA, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment4RGBUByte)
+{
+    testAlignment(4, 7 * 3 + 3, GL_RGB, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment4RGBAUShort4444)
+{
+    testAlignment(4, 7 * 2 + 2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment4RGBAUShort5551)
+{
+    testAlignment(4, 7 * 2 + 2, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment4RGBAUShort565)
+{
+    testAlignment(4, 7 * 2 + 2, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment4LAUByte)
+{
+    testAlignment(4, 7 * 2 + 2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment4LUByte)
+{
+    testAlignment(4, 7 + 1, GL_LUMINANCE, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment4AUByte)
+{
+    testAlignment(4, 7 + 1, GL_ALPHA, GL_UNSIGNED_BYTE);
+}
+
+
+TEST_P(UnpackAlignmentTest, Alignment8RGBAUByte)
+{
+    testAlignment(8, 7 * 4 + 4, GL_RGBA, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment8RGBUByte)
+{
+    testAlignment(8, 7 * 3 + 3, GL_RGB, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment8RGBAUShort4444)
+{
+    testAlignment(8, 7 * 2 + 2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment8RGBAUShort5551)
+{
+    testAlignment(8, 7 * 2 + 2, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment8RGBAUShort565)
+{
+    testAlignment(8, 7 * 2 + 2, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment8LAUByte)
+{
+    testAlignment(8, 7 * 2 + 2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment8LUByte)
+{
+    testAlignment(8, 7 + 1, GL_LUMINANCE, GL_UNSIGNED_BYTE);
+}
+
+TEST_P(UnpackAlignmentTest, Alignment8AUByte)
+{
+    testAlignment(8, 7 + 1, GL_ALPHA, GL_UNSIGNED_BYTE);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(UnpackAlignmentTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/UnpackRowLength.cpp b/src/third_party/angle/src/tests/gl_tests/UnpackRowLength.cpp
new file mode 100644
index 0000000..05ad595
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/UnpackRowLength.cpp
@@ -0,0 +1,130 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class UnpackRowLengthTest : public ANGLETest
+{
+  protected:
+    UnpackRowLengthTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+
+        mProgram = 0;
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+
+            void main()
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            uniform sampler2D tex;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, vec2(0.0, 1.0));
+            }
+        );
+
+        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    void testRowLength(int texSize, int rowLength)
+    {
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength);
+
+        if ((getClientMajorVersion() == 3) || extensionEnabled("GL_EXT_unpack_subimage"))
+        {
+            // Only texSize * texSize region is filled as WHITE, other parts are BLACK.
+            // If the UNPACK_ROW_LENGTH is implemented correctly, all texels inside this texture are WHITE.
+            std::vector<GLubyte> buf(rowLength * texSize * 4);
+            for (int y = 0; y < texSize; y++)
+            {
+                std::vector<GLubyte>::iterator rowIter = buf.begin() + y * rowLength * 4;
+                std::fill(rowIter, rowIter + texSize * 4, static_cast<GLubyte>(255u));
+                std::fill(rowIter + texSize * 4, rowIter + rowLength * 4, static_cast<GLubyte>(0u));
+            }
+
+            GLuint tex;
+            glGenTextures(1, &tex);
+            glBindTexture(GL_TEXTURE_2D, tex);
+
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texSize, texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, &buf[0]);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+            drawQuad(mProgram, "position", 0.5f);
+
+            EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
+            EXPECT_PIXEL_EQ(1, 0, 255, 255, 255, 255);
+
+            glDeleteTextures(1, &tex);
+        }
+        else
+        {
+            EXPECT_GL_ERROR(GL_INVALID_ENUM);
+        }
+    }
+
+    GLuint mProgram;
+};
+
+TEST_P(UnpackRowLengthTest, RowLength128)
+{
+    testRowLength(128, 128);
+}
+
+TEST_P(UnpackRowLengthTest, RowLength1024)
+{
+    testRowLength(128, 1024);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(UnpackRowLengthTest,
+                       ES3_D3D11(),
+                       ES2_D3D11(),
+                       ES2_D3D9(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/VertexAttributeTest.cpp b/src/third_party/angle/src/tests/gl_tests/VertexAttributeTest.cpp
new file mode 100644
index 0000000..340e15a
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/VertexAttributeTest.cpp
@@ -0,0 +1,1085 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+namespace
+{
+
+GLsizei TypeStride(GLenum attribType)
+{
+    switch (attribType)
+    {
+        case GL_UNSIGNED_BYTE:
+        case GL_BYTE:
+            return 1;
+        case GL_UNSIGNED_SHORT:
+        case GL_SHORT:
+            return 2;
+        case GL_UNSIGNED_INT:
+        case GL_INT:
+        case GL_FLOAT:
+            return 4;
+        default:
+            EXPECT_TRUE(false);
+            return 0;
+    }
+}
+
+template <typename T>
+GLfloat Normalize(T value)
+{
+    static_assert(std::is_integral<T>::value, "Integer required.");
+    if (std::is_signed<T>::value)
+    {
+        typedef typename std::make_unsigned<T>::type unsigned_type;
+        return (2.0f * static_cast<GLfloat>(value) + 1.0f) /
+               static_cast<GLfloat>(std::numeric_limits<unsigned_type>::max());
+    }
+    else
+    {
+        return static_cast<GLfloat>(value) / static_cast<GLfloat>(std::numeric_limits<T>::max());
+    }
+}
+
+class VertexAttributeTest : public ANGLETest
+{
+  protected:
+    VertexAttributeTest()
+        : mProgram(0), mTestAttrib(-1), mExpectedAttrib(-1), mBuffer(0), mQuadBuffer(0)
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    enum class Source
+    {
+        BUFFER,
+        IMMEDIATE,
+    };
+
+    struct TestData final : private angle::NonCopyable
+    {
+        TestData(GLenum typeIn,
+                 GLboolean normalizedIn,
+                 Source sourceIn,
+                 const void *inputDataIn,
+                 const GLfloat *expectedDataIn)
+            : type(typeIn),
+              normalized(normalizedIn),
+              bufferOffset(0),
+              source(sourceIn),
+              inputData(inputDataIn),
+              expectedData(expectedDataIn)
+        {
+        }
+
+        GLenum type;
+        GLboolean normalized;
+        size_t bufferOffset;
+        Source source;
+
+        const void *inputData;
+        const GLfloat *expectedData;
+    };
+
+    void setupTest(const TestData &test, GLint typeSize)
+    {
+        if (mProgram == 0)
+        {
+            initBasicProgram();
+        }
+
+        if (test.source == Source::BUFFER)
+        {
+            GLsizei dataSize = kVertexCount * TypeStride(test.type);
+            glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+            glBufferData(GL_ARRAY_BUFFER, dataSize, test.inputData, GL_STATIC_DRAW);
+            glVertexAttribPointer(mTestAttrib, typeSize, test.type, test.normalized, 0,
+                                  reinterpret_cast<void *>(test.bufferOffset));
+            glBindBuffer(GL_ARRAY_BUFFER, 0);
+        }
+        else
+        {
+            ASSERT_EQ(Source::IMMEDIATE, test.source);
+            glBindBuffer(GL_ARRAY_BUFFER, 0);
+            glVertexAttribPointer(mTestAttrib, typeSize, test.type, test.normalized, 0,
+                                  test.inputData);
+        }
+
+        glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, test.expectedData);
+
+        glEnableVertexAttribArray(mTestAttrib);
+        glEnableVertexAttribArray(mExpectedAttrib);
+    }
+
+    void checkPixels()
+    {
+        GLint viewportSize[4];
+        glGetIntegerv(GL_VIEWPORT, viewportSize);
+
+        GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
+        GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
+
+        // We need to offset our checks from triangle edges to ensure we don't fall on a single tri
+        // Avoid making assumptions of drawQuad with four checks to check the four possible tri
+        // regions
+        EXPECT_PIXEL_EQ((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
+        EXPECT_PIXEL_EQ((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
+        EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
+        EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
+    }
+
+    void runTest(const TestData &test)
+    {
+        // TODO(geofflang): Figure out why this is broken on AMD OpenGL
+        if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+        {
+            std::cout << "Test skipped on AMD OpenGL." << std::endl;
+            return;
+        }
+
+        for (GLint i = 0; i < 4; i++)
+        {
+            GLint typeSize = i + 1;
+            setupTest(test, typeSize);
+
+            drawQuad(mProgram, "position", 0.5f);
+
+            glDisableVertexAttribArray(mTestAttrib);
+            glDisableVertexAttribArray(mExpectedAttrib);
+
+            checkPixels();
+        }
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glClearColor(0, 0, 0, 0);
+        glClearDepthf(0.0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        glDisable(GL_DEPTH_TEST);
+
+        glGenBuffers(1, &mBuffer);
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+        glDeleteBuffers(1, &mBuffer);
+        glDeleteBuffers(1, &mQuadBuffer);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint compileMultiAttribProgram(GLint attribCount)
+    {
+        std::stringstream shaderStream;
+
+        shaderStream << "attribute mediump vec4 position;" << std::endl;
+        for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+        {
+            shaderStream << "attribute float a" << attribIndex << ";" << std::endl;
+        }
+        shaderStream << "varying mediump float color;" << std::endl
+                     << "void main() {" << std::endl
+                     << "  gl_Position = position;" << std::endl
+                     << "  color = 0.0;" << std::endl;
+        for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+        {
+            shaderStream << "  color += a" << attribIndex << ";" << std::endl;
+        }
+        shaderStream << "}" << std::endl;
+
+        const std::string testFragmentShaderSource =
+            "varying mediump float color;\n"
+            "void main(void)\n"
+            "{\n"
+            "    gl_FragColor = vec4(color, 0.0, 0.0, 1.0);\n"
+            "}\n";
+
+        return CompileProgram(shaderStream.str(), testFragmentShaderSource);
+    }
+
+    void setupMultiAttribs(GLuint program, GLint attribCount, GLfloat value)
+    {
+        glUseProgram(program);
+        for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+        {
+            std::stringstream attribStream;
+            attribStream << "a" << attribIndex;
+            GLint location = glGetAttribLocation(program, attribStream.str().c_str());
+            ASSERT_NE(-1, location);
+            glVertexAttrib1f(location, value);
+            glDisableVertexAttribArray(location);
+        }
+    }
+
+    void initBasicProgram()
+    {
+        const std::string testVertexShaderSource =
+            "attribute mediump vec4 position;\n"
+            "attribute mediump vec4 test;\n"
+            "attribute mediump vec4 expected;\n"
+            "varying mediump vec4 color;\n"
+            "void main(void)\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "    vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
+            "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
+            "}\n";
+
+        const std::string testFragmentShaderSource =
+            "varying mediump vec4 color;\n"
+            "void main(void)\n"
+            "{\n"
+            "    gl_FragColor = color;\n"
+            "}\n";
+
+        mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+
+        mTestAttrib = glGetAttribLocation(mProgram, "test");
+        ASSERT_NE(-1, mTestAttrib);
+        mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
+        ASSERT_NE(-1, mExpectedAttrib);
+
+        glUseProgram(mProgram);
+    }
+
+    static constexpr size_t kVertexCount = 24;
+
+    static void InitTestData(std::array<GLfloat, kVertexCount> &inputData,
+                             std::array<GLfloat, kVertexCount> &expectedData)
+    {
+        for (size_t count = 0; count < kVertexCount; ++count)
+        {
+            inputData[count]    = static_cast<GLfloat>(count);
+            expectedData[count] = inputData[count];
+        }
+    }
+
+    GLuint mProgram;
+    GLint mTestAttrib;
+    GLint mExpectedAttrib;
+    GLuint mBuffer;
+    GLuint mQuadBuffer;
+};
+
+TEST_P(VertexAttributeTest, UnsignedByteUnnormalized)
+{
+    std::array<GLubyte, kVertexCount> inputData = {
+        {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = inputData[i];
+    }
+
+    TestData data(GL_UNSIGNED_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(),
+                  expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTest, UnsignedByteNormalized)
+{
+    std::array<GLubyte, kVertexCount> inputData = {
+        {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = Normalize(inputData[i]);
+    }
+
+    TestData data(GL_UNSIGNED_BYTE, GL_TRUE, Source::IMMEDIATE, inputData.data(),
+                  expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTest, ByteUnnormalized)
+{
+    std::array<GLbyte, kVertexCount> inputData = {
+        {0, 1, 2, 3, 4, -1, -2, -3, -4, 125, 126, 127, -128, -127, -126}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = inputData[i];
+    }
+
+    TestData data(GL_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(), expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTest, ByteNormalized)
+{
+    std::array<GLbyte, kVertexCount> inputData = {
+        {0, 1, 2, 3, 4, -1, -2, -3, -4, 125, 126, 127, -128, -127, -126}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = Normalize(inputData[i]);
+    }
+
+    TestData data(GL_BYTE, GL_TRUE, Source::IMMEDIATE, inputData.data(), expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTest, UnsignedShortUnnormalized)
+{
+    std::array<GLushort, kVertexCount> inputData = {
+        {0, 1, 2, 3, 254, 255, 256, 32766, 32767, 32768, 65533, 65534, 65535}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = inputData[i];
+    }
+
+    TestData data(GL_UNSIGNED_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
+                  expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTest, UnsignedShortNormalized)
+{
+    std::array<GLushort, kVertexCount> inputData = {
+        {0, 1, 2, 3, 254, 255, 256, 32766, 32767, 32768, 65533, 65534, 65535}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = Normalize(inputData[i]);
+    }
+
+    TestData data(GL_UNSIGNED_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(),
+                  expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTest, ShortUnnormalized)
+{
+    std::array<GLshort, kVertexCount> inputData = {
+        {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = inputData[i];
+    }
+
+    TestData data(GL_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(), expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTest, ShortNormalized)
+{
+    std::array<GLshort, kVertexCount> inputData = {
+        {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = Normalize(inputData[i]);
+    }
+
+    TestData data(GL_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(), expectedData.data());
+    runTest(data);
+}
+
+class VertexAttributeTestES3 : public VertexAttributeTest
+{
+  protected:
+    VertexAttributeTestES3() {}
+};
+
+TEST_P(VertexAttributeTestES3, IntUnnormalized)
+{
+    GLint lo = std::numeric_limits<GLint>::min();
+    GLint hi = std::numeric_limits<GLint>::max();
+    std::array<GLint, kVertexCount> inputData = {
+        {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = static_cast<GLfloat>(inputData[i]);
+    }
+
+    TestData data(GL_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTestES3, IntNormalized)
+{
+    GLint lo = std::numeric_limits<GLint>::min();
+    GLint hi = std::numeric_limits<GLint>::max();
+    std::array<GLint, kVertexCount> inputData = {
+        {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = Normalize(inputData[i]);
+    }
+
+    TestData data(GL_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTestES3, UnsignedIntUnnormalized)
+{
+    GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
+    GLuint hi  = std::numeric_limits<GLuint>::max();
+    std::array<GLuint, kVertexCount> inputData = {
+        {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = static_cast<GLfloat>(inputData[i]);
+    }
+
+    TestData data(GL_UNSIGNED_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
+    runTest(data);
+}
+
+TEST_P(VertexAttributeTestES3, UnsignedIntNormalized)
+{
+    GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
+    GLuint hi  = std::numeric_limits<GLuint>::max();
+    std::array<GLuint, kVertexCount> inputData = {
+        {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
+    std::array<GLfloat, kVertexCount> expectedData;
+    for (size_t i = 0; i < kVertexCount; i++)
+    {
+        expectedData[i] = Normalize(inputData[i]);
+    }
+
+    TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
+    runTest(data);
+}
+
+// Validate that we can support GL_MAX_ATTRIBS attribs
+TEST_P(VertexAttributeTest, MaxAttribs)
+{
+    // TODO(jmadill): Figure out why we get this error on AMD/OpenGL and Intel.
+    if ((IsIntel() || IsAMD()) && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel and AMD." << std::endl;
+        return;
+    }
+
+    GLint maxAttribs;
+    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
+    ASSERT_GL_NO_ERROR();
+
+    // Reserve one attrib for position
+    GLint drawAttribs = maxAttribs - 1;
+
+    GLuint program = compileMultiAttribProgram(drawAttribs);
+    ASSERT_NE(0u, program);
+
+    setupMultiAttribs(program, drawAttribs, 0.5f / static_cast<float>(drawAttribs));
+    drawQuad(program, "position", 0.5f);
+
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 1);
+}
+
+// Validate that we cannot support GL_MAX_ATTRIBS+1 attribs
+TEST_P(VertexAttributeTest, MaxAttribsPlusOne)
+{
+    // TODO(jmadill): Figure out why we get this error on AMD/ES2/OpenGL
+    if (IsAMD() && GetParam() == ES2_OPENGL())
+    {
+        std::cout << "Test disabled on AMD/ES2/OpenGL" << std::endl;
+        return;
+    }
+
+    GLint maxAttribs;
+    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
+    ASSERT_GL_NO_ERROR();
+
+    // Exceed attrib count by one (counting position)
+    GLint drawAttribs = maxAttribs;
+
+    GLuint program = compileMultiAttribProgram(drawAttribs);
+    ASSERT_EQ(0u, program);
+}
+
+// Simple test for when we use glBindAttribLocation
+TEST_P(VertexAttributeTest, SimpleBindAttribLocation)
+{
+    // TODO(jmadill): Figure out why this fails on Intel.
+    if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on Intel." << std::endl;
+        return;
+    }
+
+    // Re-use the multi-attrib program, binding attribute 0
+    GLuint program = compileMultiAttribProgram(1);
+    glBindAttribLocation(program, 2, "position");
+    glBindAttribLocation(program, 3, "a0");
+    glLinkProgram(program);
+
+    // Setup and draw the quad
+    setupMultiAttribs(program, 1, 0.5f);
+    drawQuad(program, "position", 0.5f);
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 1);
+}
+
+// Verify that drawing with a large out-of-range offset generates INVALID_OPERATION.
+TEST_P(VertexAttributeTest, DrawArraysBufferTooSmall)
+{
+    std::array<GLfloat, kVertexCount> inputData;
+    std::array<GLfloat, kVertexCount> expectedData;
+    InitTestData(inputData, expectedData);
+
+    TestData data(GL_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
+    data.bufferOffset = kVertexCount * TypeStride(GL_FLOAT);
+
+    setupTest(data, 1);
+    drawQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Verify that index draw with an out-of-range offset generates INVALID_OPERATION.
+TEST_P(VertexAttributeTest, DrawElementsBufferTooSmall)
+{
+    std::array<GLfloat, kVertexCount> inputData;
+    std::array<GLfloat, kVertexCount> expectedData;
+    InitTestData(inputData, expectedData);
+
+    TestData data(GL_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
+    data.bufferOffset = (kVertexCount - 3) * TypeStride(GL_FLOAT);
+
+    setupTest(data, 1);
+    drawIndexedQuad(mProgram, "position", 0.5f);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Verify that using a different start vertex doesn't mess up the draw.
+TEST_P(VertexAttributeTest, DrawArraysWithBufferOffset)
+{
+    // TODO(jmadill): Diagnose this failure.
+    if (IsD3D11_FL93())
+    {
+        std::cout << "Test disabled on D3D11 FL 9_3" << std::endl;
+        return;
+    }
+
+    // TODO(geofflang): Figure out why this is broken on AMD OpenGL
+    if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
+    {
+        std::cout << "Test skipped on AMD OpenGL." << std::endl;
+        return;
+    }
+
+    initBasicProgram();
+    glUseProgram(mProgram);
+
+    std::array<GLfloat, kVertexCount> inputData;
+    std::array<GLfloat, kVertexCount> expectedData;
+    InitTestData(inputData, expectedData);
+
+    auto quadVertices        = GetQuadVertices();
+    GLsizei quadVerticesSize = static_cast<GLsizei>(quadVertices.size() * sizeof(quadVertices[0]));
+
+    glGenBuffers(1, &mQuadBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
+    glBufferData(GL_ARRAY_BUFFER, quadVerticesSize + sizeof(Vector3), nullptr, GL_STATIC_DRAW);
+    glBufferSubData(GL_ARRAY_BUFFER, 0, quadVerticesSize, quadVertices.data());
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    ASSERT_NE(-1, positionLocation);
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+
+    GLsizei dataSize = kVertexCount * TypeStride(GL_FLOAT);
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    glBufferData(GL_ARRAY_BUFFER, dataSize + TypeStride(GL_FLOAT), nullptr, GL_STATIC_DRAW);
+    glBufferSubData(GL_ARRAY_BUFFER, 0, dataSize, inputData.data());
+    glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(mTestAttrib);
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
+    glEnableVertexAttribArray(mExpectedAttrib);
+
+    // Vertex draw with no start vertex offset (second argument is zero).
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    checkPixels();
+
+    // Draw offset by one vertex.
+    glDrawArrays(GL_TRIANGLES, 1, 6);
+    checkPixels();
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Verify that when we pass a client memory pointer to a disabled attribute the draw is still
+// correct.
+TEST_P(VertexAttributeTest, DrawArraysWithDisabledAttribute)
+{
+    initBasicProgram();
+
+    std::array<GLfloat, kVertexCount> inputData;
+    std::array<GLfloat, kVertexCount> expectedData;
+    InitTestData(inputData, expectedData);
+
+    auto quadVertices        = GetQuadVertices();
+    GLsizei quadVerticesSize = static_cast<GLsizei>(quadVertices.size() * sizeof(quadVertices[0]));
+
+    glGenBuffers(1, &mQuadBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
+    glBufferData(GL_ARRAY_BUFFER, quadVerticesSize, quadVertices.data(), GL_STATIC_DRAW);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    ASSERT_NE(-1, positionLocation);
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(inputData), inputData.data(), GL_STATIC_DRAW);
+    glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(mTestAttrib);
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
+    glEnableVertexAttribArray(mExpectedAttrib);
+
+    // mProgram2 adds an attribute 'disabled' on the basis of mProgram.
+    const std::string testVertexShaderSource2 =
+        "attribute mediump vec4 position;\n"
+        "attribute mediump vec4 test;\n"
+        "attribute mediump vec4 expected;\n"
+        "attribute mediump vec4 disabled;\n"
+        "varying mediump vec4 color;\n"
+        "void main(void)\n"
+        "{\n"
+        "    gl_Position = position;\n"
+        "    vec4 threshold = max(abs(expected + disabled) * 0.005, 1.0 / 64.0);\n"
+        "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
+        "}\n";
+
+    const std::string testFragmentShaderSource =
+        "varying mediump vec4 color;\n"
+        "void main(void)\n"
+        "{\n"
+        "    gl_FragColor = color;\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, testVertexShaderSource2, testFragmentShaderSource);
+    GLuint mProgram2 = program.get();
+
+    ASSERT_EQ(positionLocation, glGetAttribLocation(mProgram2, "position"));
+    ASSERT_EQ(mTestAttrib, glGetAttribLocation(mProgram2, "test"));
+    ASSERT_EQ(mExpectedAttrib, glGetAttribLocation(mProgram2, "expected"));
+
+    // Pass a client memory pointer to disabledAttribute and disable it.
+    GLint disabledAttribute = glGetAttribLocation(mProgram2, "disabled");
+    ASSERT_EQ(-1, glGetAttribLocation(mProgram, "disabled"));
+    glVertexAttribPointer(disabledAttribute, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
+    glDisableVertexAttribArray(disabledAttribute);
+
+    glUseProgram(mProgram);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    checkPixels();
+
+    // Now enable disabledAttribute which should be used in mProgram2.
+    glEnableVertexAttribArray(disabledAttribute);
+    glUseProgram(mProgram2);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    checkPixels();
+
+    EXPECT_GL_NO_ERROR();
+}
+
+class VertexAttributeTestES31 : public VertexAttributeTestES3
+{
+  protected:
+    VertexAttributeTestES31() {}
+
+    void drawArraysWithStrideAndOffset(GLint stride, GLsizeiptr offset)
+    {
+        GLint floatStride      = stride ? (stride / TypeStride(GL_FLOAT)) : 1;
+        GLsizeiptr floatOffset = offset / TypeStride(GL_FLOAT);
+
+        size_t floatCount    = static_cast<size_t>(floatOffset) + kVertexCount * floatStride;
+        GLsizeiptr inputSize = static_cast<GLsizeiptr>(floatCount) * TypeStride(GL_FLOAT);
+
+        initBasicProgram();
+        glUseProgram(mProgram);
+
+        std::vector<GLfloat> inputData(floatCount);
+        std::array<GLfloat, kVertexCount> expectedData;
+
+        for (size_t count = 0; count < kVertexCount; ++count)
+        {
+            inputData[floatOffset + count * floatStride] = static_cast<GLfloat>(count);
+            expectedData[count]                          = static_cast<GLfloat>(count);
+        }
+
+        auto quadVertices = GetQuadVertices();
+        GLsizeiptr quadVerticesSize =
+            static_cast<GLsizeiptr>(quadVertices.size() * sizeof(quadVertices[0]));
+        glGenBuffers(1, &mQuadBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
+        glBufferData(GL_ARRAY_BUFFER, quadVerticesSize, nullptr, GL_STATIC_DRAW);
+        glBufferSubData(GL_ARRAY_BUFFER, 0, quadVerticesSize, quadVertices.data());
+
+        GLint positionLocation = glGetAttribLocation(mProgram, "position");
+        ASSERT_NE(-1, positionLocation);
+        glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+        glEnableVertexAttribArray(positionLocation);
+
+        // Ensure inputSize, inputStride and inputOffset are multiples of TypeStride(GL_FLOAT).
+        GLsizei inputStride    = stride ? floatStride * TypeStride(GL_FLOAT) : 0;
+        GLsizeiptr inputOffset = floatOffset * TypeStride(GL_FLOAT);
+        glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+        glBufferData(GL_ARRAY_BUFFER, inputSize, nullptr, GL_STATIC_DRAW);
+        glBufferSubData(GL_ARRAY_BUFFER, 0, inputSize, inputData.data());
+        glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, inputStride,
+                              reinterpret_cast<const void *>(inputOffset));
+        glEnableVertexAttribArray(mTestAttrib);
+
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
+        glEnableVertexAttribArray(mExpectedAttrib);
+
+        glDrawArrays(GL_TRIANGLES, 0, 6);
+        checkPixels();
+
+        EXPECT_GL_NO_ERROR();
+    }
+
+    // Set the maximum value for stride if the stride is too large.
+    static constexpr GLint MAX_STRIDE_FOR_TEST = 4095;
+};
+
+// Verify that MAX_VERTEX_ATTRIB_STRIDE is no less than the minimum required value (2048) in ES3.1.
+TEST_P(VertexAttributeTestES31, MaxVertexAttribStride)
+{
+    GLint maxStride;
+    glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_GE(maxStride, 2048);
+}
+
+// Verify that GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET is no less than the minimum required value
+// (2047) in ES3.1.
+TEST_P(VertexAttributeTestES31, MaxVertexAttribRelativeOffset)
+{
+    GLint maxRelativeOffset;
+    glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxRelativeOffset);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_GE(maxRelativeOffset, 2047);
+}
+
+// Verify using MAX_VERTEX_ATTRIB_STRIDE as stride doesn't mess up the draw.
+// Use default value if the value of MAX_VERTEX_ATTRIB_STRIDE is too large for this test.
+TEST_P(VertexAttributeTestES31, DrawArraysWithLargeStride)
+{
+    GLint maxStride;
+    glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
+    ASSERT_GL_NO_ERROR();
+
+    GLint largeStride = (maxStride < MAX_STRIDE_FOR_TEST) ? maxStride : MAX_STRIDE_FOR_TEST;
+    drawArraysWithStrideAndOffset(largeStride, 0);
+}
+
+class VertexAttributeCachingTest : public VertexAttributeTest
+{
+  protected:
+    VertexAttributeCachingTest() {}
+
+    void SetUp() override;
+
+    template <typename DestT>
+    static std::vector<GLfloat> GetExpectedData(const std::vector<GLubyte> &srcData,
+                                                GLenum attribType,
+                                                GLboolean normalized);
+
+    void initDoubleAttribProgram()
+    {
+        const std::string testVertexShaderSource =
+            "attribute mediump vec4 position;\n"
+            "attribute mediump vec4 test;\n"
+            "attribute mediump vec4 expected;\n"
+            "attribute mediump vec4 test2;\n"
+            "attribute mediump vec4 expected2;\n"
+            "varying mediump vec4 color;\n"
+            "void main(void)\n"
+            "{\n"
+            "    gl_Position = position;\n"
+            "    vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
+            "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
+            "    vec4 threshold2 = max(abs(expected2) * 0.01, 1.0 / 64.0);\n"
+            "    color += vec4(lessThanEqual(abs(test2 - expected2), threshold2));\n"
+            "}\n";
+
+        const std::string testFragmentShaderSource =
+            "varying mediump vec4 color;\n"
+            "void main(void)\n"
+            "{\n"
+            "    gl_FragColor = color;\n"
+            "}\n";
+
+        mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+        ASSERT_NE(0u, mProgram);
+
+        mTestAttrib = glGetAttribLocation(mProgram, "test");
+        ASSERT_NE(-1, mTestAttrib);
+        mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
+        ASSERT_NE(-1, mExpectedAttrib);
+
+        glUseProgram(mProgram);
+    }
+
+    struct AttribData
+    {
+        AttribData(GLenum typeIn, GLint sizeIn, GLboolean normalizedIn, GLsizei strideIn);
+
+        GLenum type;
+        GLint size;
+        GLboolean normalized;
+        GLsizei stride;
+    };
+
+    std::vector<AttribData> mTestData;
+    std::map<GLenum, std::vector<GLfloat>> mExpectedData;
+    std::map<GLenum, std::vector<GLfloat>> mNormExpectedData;
+};
+
+VertexAttributeCachingTest::AttribData::AttribData(GLenum typeIn,
+                                                   GLint sizeIn,
+                                                   GLboolean normalizedIn,
+                                                   GLsizei strideIn)
+    : type(typeIn), size(sizeIn), normalized(normalizedIn), stride(strideIn)
+{
+}
+
+// static
+template <typename DestT>
+std::vector<GLfloat> VertexAttributeCachingTest::GetExpectedData(
+    const std::vector<GLubyte> &srcData,
+    GLenum attribType,
+    GLboolean normalized)
+{
+    std::vector<GLfloat> expectedData;
+
+    const DestT *typedSrcPtr = reinterpret_cast<const DestT *>(srcData.data());
+    size_t iterations        = srcData.size() / TypeStride(attribType);
+
+    if (normalized)
+    {
+        for (size_t index = 0; index < iterations; ++index)
+        {
+            expectedData.push_back(Normalize(typedSrcPtr[index]));
+        }
+    }
+    else
+    {
+        for (size_t index = 0; index < iterations; ++index)
+        {
+            expectedData.push_back(static_cast<GLfloat>(typedSrcPtr[index]));
+        }
+    }
+
+    return expectedData;
+}
+
+void VertexAttributeCachingTest::SetUp()
+{
+    VertexAttributeTest::SetUp();
+
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+
+    std::vector<GLubyte> srcData;
+    for (size_t count = 0; count < 4; ++count)
+    {
+        for (GLubyte i = 0; i < std::numeric_limits<GLubyte>::max(); ++i)
+        {
+            srcData.push_back(i);
+        }
+    }
+
+    glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
+
+    GLint viewportSize[4];
+    glGetIntegerv(GL_VIEWPORT, viewportSize);
+
+    std::vector<GLenum> attribTypes;
+    attribTypes.push_back(GL_BYTE);
+    attribTypes.push_back(GL_UNSIGNED_BYTE);
+    attribTypes.push_back(GL_SHORT);
+    attribTypes.push_back(GL_UNSIGNED_SHORT);
+
+    if (getClientMajorVersion() >= 3)
+    {
+        attribTypes.push_back(GL_INT);
+        attribTypes.push_back(GL_UNSIGNED_INT);
+    }
+
+    constexpr GLint kMaxSize     = 4;
+    constexpr GLsizei kMaxStride = 4;
+
+    for (GLenum attribType : attribTypes)
+    {
+        for (GLint attribSize = 1; attribSize <= kMaxSize; ++attribSize)
+        {
+            for (GLsizei stride = 1; stride <= kMaxStride; ++stride)
+            {
+                mTestData.push_back(AttribData(attribType, attribSize, GL_FALSE, stride));
+                if (attribType != GL_FLOAT)
+                {
+                    mTestData.push_back(AttribData(attribType, attribSize, GL_TRUE, stride));
+                }
+            }
+        }
+    }
+
+    mExpectedData[GL_BYTE]          = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_FALSE);
+    mExpectedData[GL_UNSIGNED_BYTE] = GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_FALSE);
+    mExpectedData[GL_SHORT]         = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_FALSE);
+    mExpectedData[GL_UNSIGNED_SHORT] =
+        GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_FALSE);
+    mExpectedData[GL_INT]          = GetExpectedData<GLint>(srcData, GL_INT, GL_FALSE);
+    mExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_FALSE);
+
+    mNormExpectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_TRUE);
+    mNormExpectedData[GL_UNSIGNED_BYTE] =
+        GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_TRUE);
+    mNormExpectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_TRUE);
+    mNormExpectedData[GL_UNSIGNED_SHORT] =
+        GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_TRUE);
+    mNormExpectedData[GL_INT]          = GetExpectedData<GLint>(srcData, GL_INT, GL_TRUE);
+    mNormExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_TRUE);
+}
+
+// In D3D11, we must sometimes translate buffer data into static attribute caches. We also use a
+// cache management scheme which garbage collects old attributes after we start using too much
+// cache data. This test tries to make as many attribute caches from a single buffer as possible
+// to stress-test the caching code.
+TEST_P(VertexAttributeCachingTest, BufferMulticaching)
+{
+    if (IsAMD() && IsDesktopOpenGL())
+    {
+        std::cout << "Test skipped on AMD OpenGL." << std::endl;
+        return;
+    }
+
+    initBasicProgram();
+
+    glEnableVertexAttribArray(mTestAttrib);
+    glEnableVertexAttribArray(mExpectedAttrib);
+
+    ASSERT_GL_NO_ERROR();
+
+    for (const auto &data : mTestData)
+    {
+        const auto &expected =
+            (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
+
+        GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
+        GLsizei stride     = TypeStride(data.type) * baseStride;
+
+        glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+        glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
+                              sizeof(GLfloat) * baseStride, expected.data());
+        drawQuad(mProgram, "position", 0.5f);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
+    }
+}
+
+// With D3D11 dirty bits for VertxArray11, we can leave vertex state unchanged if there aren't any
+// GL calls that affect it. This test targets leaving one vertex attribute unchanged between draw
+// calls while changing another vertex attribute enough that it clears the static buffer cache
+// after enough iterations. It validates the unchanged attributes don't get deleted incidentally.
+TEST_P(VertexAttributeCachingTest, BufferMulticachingWithOneUnchangedAttrib)
+{
+    if (IsAMD() && IsDesktopOpenGL())
+    {
+        std::cout << "Test skipped on AMD OpenGL." << std::endl;
+        return;
+    }
+
+    initDoubleAttribProgram();
+
+    GLint testAttrib2Location = glGetAttribLocation(mProgram, "test2");
+    ASSERT_NE(-1, testAttrib2Location);
+    GLint expectedAttrib2Location = glGetAttribLocation(mProgram, "expected2");
+    ASSERT_NE(-1, expectedAttrib2Location);
+
+    glEnableVertexAttribArray(mTestAttrib);
+    glEnableVertexAttribArray(mExpectedAttrib);
+    glEnableVertexAttribArray(testAttrib2Location);
+    glEnableVertexAttribArray(expectedAttrib2Location);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Use an attribute that we know must be converted. This is a bit sensitive.
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    glVertexAttribPointer(testAttrib2Location, 3, GL_UNSIGNED_SHORT, GL_FALSE, 6, nullptr);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glVertexAttribPointer(expectedAttrib2Location, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3,
+                          mExpectedData[GL_UNSIGNED_SHORT].data());
+
+    for (const auto &data : mTestData)
+    {
+        const auto &expected =
+            (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
+
+        GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
+        GLsizei stride     = TypeStride(data.type) * baseStride;
+
+        glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+        glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
+                              sizeof(GLfloat) * baseStride, expected.data());
+        drawQuad(mProgram, "position", 0.5f);
+
+        ASSERT_GL_NO_ERROR();
+        EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
+    }
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+// D3D11 Feature Level 9_3 uses different D3D formats for vertex attribs compared to Feature Levels
+// 10_0+, so we should test them separately.
+ANGLE_INSTANTIATE_TEST(VertexAttributeTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(VertexAttributeTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(VertexAttributeTestES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(VertexAttributeCachingTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES3_OPENGL());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/ViewportTest.cpp b/src/third_party/angle/src/tests/gl_tests/ViewportTest.cpp
new file mode 100644
index 0000000..8cd9cd3
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/ViewportTest.cpp
@@ -0,0 +1,272 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+namespace
+{
+
+class ViewportTest : public ANGLETest
+{
+  protected:
+    ViewportTest()
+    {
+        setWindowWidth(512);
+        setWindowHeight(512);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+
+        mProgram = 0;
+    }
+
+    void runNonScissoredTest()
+    {
+        glClearColor(0, 0, 0, 1);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        runTest();
+    }
+
+    void runScissoredTest()
+    {
+        glClearColor(0, 0, 0, 1);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        glEnable(GL_SCISSOR_TEST);
+        glScissor(0, getWindowHeight() / 2, getWindowWidth(), getWindowHeight() / 2);
+
+        runTest();
+    }
+
+    void runTest()
+    {
+        // Firstly ensure that no errors have been hit.
+        EXPECT_GL_NO_ERROR();
+
+        GLint viewportSize[4];
+        glGetIntegerv(GL_VIEWPORT, viewportSize);
+
+        // Clear to green. Might be a scissored clear, if scissorSize != window size
+        glClearColor(0, 1, 0, 1);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // Draw a red quad centered in the middle of the viewport, with dimensions 25% of the size of the viewport.
+        drawQuad(mProgram, "position", 0.5f, 0.25f);
+
+        GLint centerViewportX = viewportSize[0] + (viewportSize[2] / 2);
+        GLint centerViewportY = viewportSize[1] + (viewportSize[3] / 2);
+
+        GLint redQuadLeftSideX   = viewportSize[0] + viewportSize[2] * 3 / 8;
+        GLint redQuadRightSideX  = viewportSize[0] + viewportSize[2] * 5 / 8;
+        GLint redQuadTopSideY    = viewportSize[1] + viewportSize[3] * 3 / 8;
+        GLint redQuadBottomSideY = viewportSize[1] + viewportSize[3] * 5 / 8;
+
+        // The midpoint of the viewport should be red.
+        checkPixel(centerViewportX, centerViewportY, true);
+
+        // Pixels just inside the red quad should be red.
+        checkPixel(redQuadLeftSideX,      redQuadTopSideY,        true);
+        checkPixel(redQuadLeftSideX,      redQuadBottomSideY - 1, true);
+        checkPixel(redQuadRightSideX - 1, redQuadTopSideY,        true);
+        checkPixel(redQuadRightSideX - 1, redQuadBottomSideY - 1, true);
+
+        // Pixels just outside the red quad shouldn't be red.
+        checkPixel(redQuadLeftSideX - 1,  redQuadTopSideY - 1, false);
+        checkPixel(redQuadLeftSideX - 1,  redQuadBottomSideY,  false);
+        checkPixel(redQuadRightSideX,     redQuadTopSideY - 1, false);
+        checkPixel(redQuadRightSideX,     redQuadBottomSideY,  false);
+
+        // Pixels just within the viewport shouldn't be red.
+        checkPixel(viewportSize[0],                        viewportSize[1],                       false);
+        checkPixel(viewportSize[0],                        viewportSize[1] + viewportSize[3] - 1, false);
+        checkPixel(viewportSize[0] + viewportSize[2] - 1,  viewportSize[1],                       false);
+        checkPixel(viewportSize[0] + viewportSize[2] - 1,  viewportSize[1] + viewportSize[3] - 1, false);
+    }
+
+    void checkPixel(GLint x, GLint y, GLboolean renderedRed)
+    {
+        // By default, expect the pixel to be black.
+        GLint expectedRedChannel = 0;
+        GLint expectedGreenChannel = 0;
+
+        GLint scissorSize[4];
+        glGetIntegerv(GL_SCISSOR_BOX, scissorSize);
+
+        EXPECT_GL_NO_ERROR();
+
+        if (scissorSize[0] <= x && x < scissorSize[0] + scissorSize[2]
+            && scissorSize[1] <= y && y < scissorSize[1] + scissorSize[3])
+        {
+            // If the pixel lies within the scissor rect, then it should have been cleared to green.
+            // If we rendered a red square on top of it, then the pixel should be red (the green channel will have been reset to 0).
+            expectedRedChannel = renderedRed ? 255 : 0;
+            expectedGreenChannel = renderedRed ? 0 : 255;
+        }
+
+        // If the pixel is within the bounds of the window, then we check it. Otherwise we skip it.
+        if (0 <= x && x < getWindowWidth() && 0 <= y && y < getWindowHeight())
+        {
+            EXPECT_PIXEL_EQ(x, y, expectedRedChannel, expectedGreenChannel, 0, 255);
+        }
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string testVertexShaderSource = SHADER_SOURCE
+        (
+            attribute highp vec4 position;
+
+            void main(void)
+            {
+                gl_Position = position;
+            }
+        );
+
+        const std::string testFragmentShaderSource = SHADER_SOURCE
+        (
+            void main(void)
+            {
+                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+            }
+        );
+
+        mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        glUseProgram(mProgram);
+
+        glClearColor(0, 0, 0, 1);
+        glClearDepthf(0.0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        // Call glViewport and glScissor with default parameters.
+        glScissor(0, 0, getWindowWidth(), getWindowHeight());
+        glViewport(0, 0, getWindowWidth(), getWindowHeight());
+
+        glDisable(GL_DEPTH_TEST);
+    }
+
+    void TearDown() override
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mProgram;
+};
+
+TEST_P(ViewportTest, QuarterWindow)
+{
+    glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+TEST_P(ViewportTest, QuarterWindowCentered)
+{
+    glViewport(getWindowWidth() * 3 / 8, getWindowHeight() * 3 / 8, getWindowWidth() / 4, getWindowHeight() / 4);
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+TEST_P(ViewportTest, FullWindow)
+{
+    glViewport(0, 0, getWindowWidth(), getWindowHeight());
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+TEST_P(ViewportTest, FullWindowOffCenter)
+{
+    glViewport(-getWindowWidth() / 2, getWindowHeight() / 2, getWindowWidth(), getWindowHeight());
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+TEST_P(ViewportTest, DoubleWindow)
+{
+    glViewport(0, 0, getWindowWidth() * 2, getWindowHeight() * 2);
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+TEST_P(ViewportTest, DoubleWindowCentered)
+{
+    glViewport(-getWindowWidth() / 2, -getWindowHeight() / 2, getWindowWidth() * 2, getWindowHeight() * 2);
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+TEST_P(ViewportTest, DoubleWindowOffCenter)
+{
+    glViewport(-getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, getWindowWidth(), getWindowHeight());
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+TEST_P(ViewportTest, TripleWindow)
+{
+    glViewport(0, 0, getWindowWidth() * 3, getWindowHeight() * 3);
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+TEST_P(ViewportTest, TripleWindowCentered)
+{
+    glViewport(-getWindowWidth(), -getWindowHeight(), getWindowWidth() * 3, getWindowHeight() * 3);
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+TEST_P(ViewportTest, TripleWindowOffCenter)
+{
+    glViewport(-getWindowWidth() * 3 / 2, -getWindowHeight() * 3 / 2, getWindowWidth() * 3, getWindowHeight() * 3);
+
+    runNonScissoredTest();
+
+    runScissoredTest();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+// D3D11 Feature Level 9 and D3D9 emulate large and negative viewports in the vertex shader. We should test both of these as well as D3D11 Feature Level 10_0+.
+ANGLE_INSTANTIATE_TEST(ViewportTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE),
+                       ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/third_party/angle/src/tests/gl_tests/WebGLCompatibilityTest.cpp
new file mode 100644
index 0000000..71f91fe
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/WebGLCompatibilityTest.cpp
@@ -0,0 +1,2348 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WebGLCompatibilityTest.cpp : Tests of the GL_ANGLE_webgl_compatibility extension.
+
+#include "test_utils/ANGLETest.h"
+
+#include "common/mathutil.h"
+#include "test_utils/gl_raii.h"
+
+namespace
+{
+
+bool ConstantColorAndAlphaBlendFunctions(GLenum first, GLenum second)
+{
+    return (first == GL_CONSTANT_COLOR || first == GL_ONE_MINUS_CONSTANT_COLOR) &&
+           (second == GL_CONSTANT_ALPHA || second == GL_ONE_MINUS_CONSTANT_ALPHA);
+}
+
+void CheckBlendFunctions(GLenum src, GLenum dst)
+{
+    if (ConstantColorAndAlphaBlendFunctions(src, dst) ||
+        ConstantColorAndAlphaBlendFunctions(dst, src))
+    {
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+    else
+    {
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+// Extensions that affect the ability to use floating point textures
+constexpr const char *FloatingPointTextureExtensions[] = {
+    "",
+    "GL_EXT_texture_storage",
+    "GL_OES_texture_float",
+    "GL_OES_texture_float_linear",
+    "GL_OES_texture_half_float",
+    "GL_OES_texture_half_float_linear",
+    "GL_EXT_color_buffer_half_float",
+    "GL_EXT_color_buffer_float",
+    "GL_CHROMIUM_color_buffer_float_rgba",
+    "GL_CHROMIUM_color_buffer_float_rgb",
+};
+
+}  // namespace
+
+namespace angle
+{
+
+class WebGLCompatibilityTest : public ANGLETest
+{
+  protected:
+    WebGLCompatibilityTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setWebGLCompatibilityEnabled(true);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+        glRequestExtensionANGLE = reinterpret_cast<PFNGLREQUESTEXTENSIONANGLEPROC>(
+            eglGetProcAddress("glRequestExtensionANGLE"));
+    }
+
+    template <typename T>
+    void TestFloatTextureFormat(GLenum internalFormat,
+                                GLenum format,
+                                GLenum type,
+                                bool texturingEnabled,
+                                bool linearSamplingEnabled,
+                                bool renderingEnabled,
+                                const T textureData[4],
+                                const float floatData[4])
+    {
+        ASSERT_GL_NO_ERROR();
+
+        const std::string samplingVs =
+            "attribute vec4 position;\n"
+            "varying vec2 texcoord;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "    texcoord = (position.xy * 0.5) + 0.5;\n"
+            "}\n";
+
+        const std::string samplingFs =
+            "precision mediump float;\n"
+            "uniform sampler2D tex;\n"
+            "uniform vec4 subtractor;\n"
+            "varying vec2 texcoord;\n"
+            "void main()\n"
+            "{\n"
+            "    vec4 color = texture2D(tex, texcoord);\n"
+            "    if (abs(color.r - subtractor.r) +\n"
+            "        abs(color.g - subtractor.g) +\n"
+            "        abs(color.b - subtractor.b) +\n"
+            "        abs(color.a - subtractor.a) < 8.0)\n"
+            "    {\n"
+            "        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+            "    }\n"
+            "    else\n"
+            "    {\n"
+            "        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
+            "    }\n"
+            "}\n";
+
+        ANGLE_GL_PROGRAM(samplingProgram, samplingVs, samplingFs);
+        glUseProgram(samplingProgram.get());
+
+        GLRenderbuffer rbo;
+        glBindRenderbuffer(GL_RENDERBUFFER, rbo.get());
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
+
+        GLFramebuffer fbo;
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo.get());
+
+        GLTexture texture;
+        glBindTexture(GL_TEXTURE_2D, texture.get());
+
+        if (internalFormat == format)
+        {
+            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, textureData);
+        }
+        else
+        {
+            if (getClientMajorVersion() >= 3)
+            {
+                glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
+            }
+            else
+            {
+                ASSERT_TRUE(extensionEnabled("GL_EXT_texture_storage"));
+                glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
+            }
+            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, format, type, textureData);
+        }
+
+        if (!texturingEnabled)
+        {
+            // Depending on the entry point and client version, different errors may be generated
+            ASSERT_GLENUM_NE(GL_NO_ERROR, glGetError());
+
+            // Two errors may be generated in the glTexStorage + glTexSubImage case, clear the
+            // second error
+            glGetError();
+
+            return;
+        }
+        ASSERT_GL_NO_ERROR();
+
+        glUniform1i(glGetUniformLocation(samplingProgram.get(), "tex"), 0);
+        glUniform4fv(glGetUniformLocation(samplingProgram.get(), "subtractor"), 1, floatData);
+
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        drawQuad(samplingProgram.get(), "position", 0.5f, 1.0f, true);
+        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        drawQuad(samplingProgram.get(), "position", 0.5f, 1.0f, true);
+
+        if (linearSamplingEnabled)
+        {
+            EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+        }
+        else
+        {
+            EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+        }
+
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(),
+                               0);
+        glBindTexture(GL_TEXTURE_2D, 0);
+        if (!renderingEnabled)
+        {
+            EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+                             glCheckFramebufferStatus(GL_FRAMEBUFFER));
+            return;
+        }
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+        const std::string renderingVs =
+            "attribute vec4 position;\n"
+            "void main()\n"
+            "{\n"
+            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+            "}\n";
+
+        const std::string renderingFs =
+            "precision mediump float;\n"
+            "uniform vec4 writeValue;\n"
+            "void main()\n"
+            "{\n"
+            "   gl_FragColor = writeValue;\n"
+            "}\n";
+
+        ANGLE_GL_PROGRAM(renderingProgram, renderingVs, renderingFs);
+        glUseProgram(renderingProgram.get());
+
+        glUniform4fv(glGetUniformLocation(renderingProgram.get(), "writeValue"), 1, floatData);
+
+        drawQuad(renderingProgram.get(), "position", 0.5f, 1.0f, true);
+
+        EXPECT_PIXEL_COLOR32F_NEAR(
+            0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f);
+    }
+
+    // Called from RenderingFeedbackLoopWithDrawBuffersEXT.
+    void drawBuffersEXTFeedbackLoop(GLuint program,
+                                    const std::array<GLenum, 2> &drawBuffers,
+                                    GLenum expectedError);
+
+    // Called from RenderingFeedbackLoopWithDrawBuffers.
+    void drawBuffersFeedbackLoop(GLuint program,
+                                 const std::array<GLenum, 2> &drawBuffers,
+                                 GLenum expectedError);
+
+    PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
+};
+
+class WebGL2CompatibilityTest : public WebGLCompatibilityTest
+{
+};
+
+// Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so
+// the GL extension should always be present
+TEST_P(WebGLCompatibilityTest, ExtensionStringExposed)
+{
+    EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
+}
+
+// Verify that all extension entry points are available
+TEST_P(WebGLCompatibilityTest, EntryPoints)
+{
+    if (extensionEnabled("GL_ANGLE_request_extension"))
+    {
+        EXPECT_NE(nullptr, eglGetProcAddress("glRequestExtensionANGLE"));
+    }
+}
+
+// WebGL 1 allows GL_DEPTH_STENCIL_ATTACHMENT as a valid binding point.  Make sure it is usable,
+// even in ES2 contexts.
+TEST_P(WebGLCompatibilityTest, DepthStencilBindingPoint)
+{
+    GLRenderbuffer renderbuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffer.get());
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that attempting to enable an extension that doesn't exist generates GL_INVALID_OPERATION
+TEST_P(WebGLCompatibilityTest, EnableExtensionValidation)
+{
+    glRequestExtensionANGLE("invalid_extension_string");
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test enabling the GL_OES_element_index_uint extension
+TEST_P(WebGLCompatibilityTest, EnableExtensionUintIndices)
+{
+    if (getClientMajorVersion() != 2)
+    {
+        // This test only works on ES2 where uint indices are not available by default
+        return;
+    }
+
+    EXPECT_FALSE(extensionEnabled("GL_OES_element_index_uint"));
+
+    GLBuffer indexBuffer;
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
+
+    GLuint data[] = {0, 1, 2, 1, 3, 2};
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
+
+    ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
+                     "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
+    glUseProgram(program.get());
+
+    glDrawElements(GL_TRIANGLES, 2, GL_UNSIGNED_INT, nullptr);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    if (extensionRequestable("GL_OES_element_index_uint"))
+    {
+        glRequestExtensionANGLE("GL_OES_element_index_uint");
+        EXPECT_GL_NO_ERROR();
+        EXPECT_TRUE(extensionEnabled("GL_OES_element_index_uint"));
+
+        glDrawElements(GL_TRIANGLES, 2, GL_UNSIGNED_INT, nullptr);
+        EXPECT_GL_NO_ERROR();
+    }
+}
+
+// Test enabling the GL_OES_standard_derivatives extension
+TEST_P(WebGLCompatibilityTest, EnableExtensionStandardDerivitives)
+{
+    EXPECT_FALSE(extensionEnabled("GL_OES_standard_derivatives"));
+
+    const std::string source =
+        "#extension GL_OES_standard_derivatives : require\n"
+        "void main() { gl_FragColor = vec4(dFdx(vec2(1.0, 1.0)).x, 1, 0, 1); }\n";
+    ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, source));
+
+    if (extensionRequestable("GL_OES_standard_derivatives"))
+    {
+        glRequestExtensionANGLE("GL_OES_standard_derivatives");
+        EXPECT_GL_NO_ERROR();
+        EXPECT_TRUE(extensionEnabled("GL_OES_standard_derivatives"));
+
+        GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
+        ASSERT_NE(0u, shader);
+        glDeleteShader(shader);
+    }
+}
+
+// Test enabling the GL_EXT_shader_texture_lod extension
+TEST_P(WebGLCompatibilityTest, EnableExtensionTextureLOD)
+{
+    EXPECT_FALSE(extensionEnabled("GL_EXT_shader_texture_lod"));
+
+    const std::string source =
+        "#extension GL_EXT_shader_texture_lod : require\n"
+        "uniform sampler2D u_texture;\n"
+        "void main() {\n"
+        "    gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
+        "0.0));\n"
+        "}\n";
+    ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, source));
+
+    if (extensionRequestable("GL_EXT_shader_texture_lod"))
+    {
+        glRequestExtensionANGLE("GL_EXT_shader_texture_lod");
+        EXPECT_GL_NO_ERROR();
+        EXPECT_TRUE(extensionEnabled("GL_EXT_shader_texture_lod"));
+
+        GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
+        ASSERT_NE(0u, shader);
+        glDeleteShader(shader);
+    }
+}
+
+// Test enabling the GL_EXT_frag_depth extension
+TEST_P(WebGLCompatibilityTest, EnableExtensionFragDepth)
+{
+    EXPECT_FALSE(extensionEnabled("GL_EXT_frag_depth"));
+
+    const std::string source =
+        "#extension GL_EXT_frag_depth : require\n"
+        "void main() {\n"
+        "    gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
+        "    gl_FragDepthEXT = 1.0;\n"
+        "}\n";
+    ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, source));
+
+    if (extensionRequestable("GL_EXT_frag_depth"))
+    {
+        glRequestExtensionANGLE("GL_EXT_frag_depth");
+        EXPECT_GL_NO_ERROR();
+        EXPECT_TRUE(extensionEnabled("GL_EXT_frag_depth"));
+
+        GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
+        ASSERT_NE(0u, shader);
+        glDeleteShader(shader);
+    }
+}
+
+// Test enabling the GL_EXT_texture_filter_anisotropic extension
+TEST_P(WebGLCompatibilityTest, EnableExtensionTextureFilterAnisotropic)
+{
+    EXPECT_FALSE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
+
+    GLfloat maxAnisotropy = 0.0f;
+    glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    ASSERT_GL_NO_ERROR();
+
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    GLfloat currentAnisotropy = 0.0f;
+    glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    if (extensionRequestable("GL_EXT_texture_filter_anisotropic"))
+    {
+        glRequestExtensionANGLE("GL_EXT_texture_filter_anisotropic");
+        EXPECT_GL_NO_ERROR();
+        EXPECT_TRUE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
+
+        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_GE(maxAnisotropy, 2.0f);
+
+        glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
+        ASSERT_GL_NO_ERROR();
+        EXPECT_EQ(1.0f, currentAnisotropy);
+
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+// Verify that shaders are of a compatible spec when the extension is enabled.
+TEST_P(WebGLCompatibilityTest, ExtensionCompilerSpec)
+{
+    EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
+
+    // Use of reserved _webgl prefix should fail when the shader specification is for WebGL.
+    const std::string &vert =
+        "struct Foo {\n"
+        "    int _webgl_bar;\n"
+        "};\n"
+        "void main()\n"
+        "{\n"
+        "    Foo foo = Foo(1);\n"
+        "}";
+
+    // Default fragement shader.
+    const std::string &frag =
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n"
+        "}";
+
+    GLuint program = CompileProgram(vert, frag);
+    EXPECT_EQ(0u, program);
+    glDeleteProgram(program);
+}
+
+// Verify that the context generates the correct error when the framebuffer attachments are
+// different sizes
+TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMissmatch)
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    GLTexture textures[2];
+    glBindTexture(GL_TEXTURE_2D, textures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
+
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    GLRenderbuffer renderbuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 3, 3);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
+
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
+                     glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    if (extensionRequestable("GL_EXT_draw_buffers"))
+    {
+        glRequestExtensionANGLE("GL_EXT_draw_buffers");
+        EXPECT_GL_NO_ERROR();
+        EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
+
+        glBindTexture(GL_TEXTURE_2D, textures[1]);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
+        ASSERT_GL_NO_ERROR();
+
+        ASSERT_GL_NO_ERROR();
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
+                         glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+
+        ASSERT_GL_NO_ERROR();
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+        ASSERT_GL_NO_ERROR();
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
+                         glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    }
+}
+
+// Test that client-side array buffers are forbidden in WebGL mode
+TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBuffer)
+{
+    const std::string &vert =
+        "attribute vec3 a_pos;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_pos, 1.0);\n"
+        "}\n";
+
+    const std::string &frag =
+        "precision highp float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vert, frag);
+
+    GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
+    ASSERT_NE(-1, posLocation);
+    glUseProgram(program.get());
+
+    const auto &vertices = GetQuadVertices();
+    glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
+    glEnableVertexAttribArray(posLocation);
+
+    ASSERT_GL_NO_ERROR();
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test that client-side element array buffers are forbidden in WebGL mode
+TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer)
+{
+    const std::string &vert =
+        "attribute vec3 a_pos;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_pos, 1.0);\n"
+        "}\n";
+
+    const std::string &frag =
+        "precision highp float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vert, frag);
+
+    GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
+    ASSERT_NE(-1, posLocation);
+    glUseProgram(program.get());
+
+    const auto &vertices = GetQuadVertices();
+
+    GLBuffer vertexBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
+                 GL_STATIC_DRAW);
+
+    glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(posLocation);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Use the pointer with value of 1 for indices instead of an actual pointer because WebGL also
+    // enforces that the top bit of indices must be 0 (i.e. offset >= 0) and would generate
+    // GL_INVALID_VALUE in that case. Using a null pointer gets caught by another check.
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void*>(intptr_t(1)));
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Tests the WebGL requirement of having the same stencil mask, writemask and ref for fron and back
+TEST_P(WebGLCompatibilityTest, RequiresSameStencilMaskAndRef)
+{
+    // Run the test in an FBO to make sure we have some stencil bits.
+    GLRenderbuffer renderbuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffer.get());
+
+    ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
+                     "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
+    glUseProgram(program.get());
+    ASSERT_GL_NO_ERROR();
+
+    // Having ref and mask the same for front and back is valid.
+    glStencilMask(255);
+    glStencilFunc(GL_ALWAYS, 0, 255);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    ASSERT_GL_NO_ERROR();
+
+    // Having a different front - back write mask generates an error.
+    glStencilMaskSeparate(GL_FRONT, 1);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Setting both write masks separately to the same value is valid.
+    glStencilMaskSeparate(GL_BACK, 1);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    ASSERT_GL_NO_ERROR();
+
+    // Having a different stencil front - back mask generates an error
+    glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 1);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Setting both masks separately to the same value is valid.
+    glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 1);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    ASSERT_GL_NO_ERROR();
+
+    // Having a different stencil front - back reference generates an error
+    glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 255, 1);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Setting both references separately to the same value is valid.
+    glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 255, 1);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    ASSERT_GL_NO_ERROR();
+
+    // Using different stencil funcs, everything being equal is valid.
+    glStencilFuncSeparate(GL_BACK, GL_NEVER, 255, 1);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that GL_FIXED is forbidden
+TEST_P(WebGLCompatibilityTest, ForbidsGLFixed)
+{
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
+    glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
+
+    glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    glVertexAttribPointer(0, 1, GL_FIXED, GL_FALSE, 0, nullptr);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+// Test the WebGL limit of 255 for the attribute stride
+TEST_P(WebGLCompatibilityTest, MaxStride)
+{
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
+    glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
+
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 255, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 256, nullptr);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+// Test the checks for OOB reads in the vertex buffers, non-instanced version
+TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsNonInstanced)
+{
+    const std::string &vert =
+        "attribute float a_pos;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
+        "}\n";
+
+    const std::string &frag =
+        "precision highp float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vert, frag);
+
+    GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
+    ASSERT_NE(-1, posLocation);
+    glUseProgram(program.get());
+
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
+    glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
+
+    glEnableVertexAttribArray(posLocation);
+
+    const uint8_t* zeroOffset = nullptr;
+
+    // Test touching the last element is valid.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
+    glDrawArrays(GL_POINTS, 0, 4);
+    ASSERT_GL_NO_ERROR();
+
+    // Test touching the last element + 1 is invalid.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
+    glDrawArrays(GL_POINTS, 0, 4);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Test touching the last element is valid, using a stride.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
+    glDrawArrays(GL_POINTS, 0, 4);
+    ASSERT_GL_NO_ERROR();
+
+    // Test touching the last element + 1 is invalid, using a stride.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
+    glDrawArrays(GL_POINTS, 0, 4);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Test any offset is valid if no vertices are drawn.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
+    glDrawArrays(GL_POINTS, 0, 0);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test the checks for OOB reads in the index buffer
+TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInIndexBuffer)
+{
+    const std::string &vert =
+        "attribute float a_pos;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
+        "}\n";
+
+    const std::string &frag =
+        "precision highp float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vert, frag);
+
+    GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
+    ASSERT_NE(-1, posLocation);
+    glUseProgram(program.get());
+
+    GLBuffer vertexBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
+    glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
+
+    glEnableVertexAttribArray(posLocation);
+
+    const uint8_t *zeroOffset   = nullptr;
+    const uint8_t zeroIndices[] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset);
+
+    GLBuffer indexBuffer;
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(zeroIndices), zeroIndices, GL_STATIC_DRAW);
+    ASSERT_GL_NO_ERROR();
+
+    // Test touching the last index is valid
+    glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
+    ASSERT_GL_NO_ERROR();
+
+    // Test touching the last + 1 element is invalid
+    glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 5);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Test any offset if valid if count is zero
+    glDrawElements(GL_POINTS, 0, GL_UNSIGNED_BYTE, zeroOffset + 42);
+    ASSERT_GL_NO_ERROR();
+
+    // Test touching the first index is valid
+    glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
+    ASSERT_GL_NO_ERROR();
+
+    // Test touching the first - 1 index is invalid
+    // The error ha been specified to be INVALID_VALUE instead of INVALID_OPERATION because it was
+    // the historic behavior of WebGL implementations
+    glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset - 1);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+// Test depth range with 'near' more or less than 'far.'
+TEST_P(WebGLCompatibilityTest, DepthRange)
+{
+    glDepthRangef(0, 1);
+    ASSERT_GL_NO_ERROR();
+
+    glDepthRangef(.5, .5);
+    ASSERT_GL_NO_ERROR();
+
+    glDepthRangef(1, 0);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test all blend function combinations.
+// In WebGL it is invalid to combine constant color with constant alpha.
+TEST_P(WebGLCompatibilityTest, BlendWithConstantColor)
+{
+    constexpr GLenum srcFunc[] = {
+        GL_ZERO,
+        GL_ONE,
+        GL_SRC_COLOR,
+        GL_ONE_MINUS_SRC_COLOR,
+        GL_DST_COLOR,
+        GL_ONE_MINUS_DST_COLOR,
+        GL_SRC_ALPHA,
+        GL_ONE_MINUS_SRC_ALPHA,
+        GL_DST_ALPHA,
+        GL_ONE_MINUS_DST_ALPHA,
+        GL_CONSTANT_COLOR,
+        GL_ONE_MINUS_CONSTANT_COLOR,
+        GL_CONSTANT_ALPHA,
+        GL_ONE_MINUS_CONSTANT_ALPHA,
+        GL_SRC_ALPHA_SATURATE,
+    };
+
+    constexpr GLenum dstFunc[] = {
+        GL_ZERO,           GL_ONE,
+        GL_SRC_COLOR,      GL_ONE_MINUS_SRC_COLOR,
+        GL_DST_COLOR,      GL_ONE_MINUS_DST_COLOR,
+        GL_SRC_ALPHA,      GL_ONE_MINUS_SRC_ALPHA,
+        GL_DST_ALPHA,      GL_ONE_MINUS_DST_ALPHA,
+        GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
+        GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA,
+    };
+
+    for (GLenum src : srcFunc)
+    {
+        for (GLenum dst : dstFunc)
+        {
+            glBlendFunc(src, dst);
+            CheckBlendFunctions(src, dst);
+            glBlendFuncSeparate(src, dst, GL_ONE, GL_ONE);
+            CheckBlendFunctions(src, dst);
+        }
+    }
+}
+
+// Test the checks for OOB reads in the vertex buffers, instanced version
+TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
+{
+    const std::string &vert =
+        "attribute float a_pos;\n"
+        "attribute float a_w;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
+        "}\n";
+
+    const std::string &frag =
+        "precision highp float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vert, frag);
+
+    GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
+    ASSERT_NE(-1, posLocation);
+
+    GLint wLocation = glGetAttribLocation(program.get(), "a_w");
+    ASSERT_NE(-1, wLocation);
+
+    glUseProgram(program.get());
+
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
+    glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
+
+    glEnableVertexAttribArray(posLocation);
+    glVertexAttribDivisor(posLocation, 1);
+
+    glEnableVertexAttribArray(wLocation);
+    glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
+    glVertexAttribDivisor(wLocation, 0);
+
+    const uint8_t* zeroOffset = nullptr;
+
+    // Test touching the last element is valid.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
+    glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
+    ASSERT_GL_NO_ERROR();
+
+    // Test touching the last element + 1 is invalid.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
+    glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Test touching the last element is valid, using a stride.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
+    glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
+    ASSERT_GL_NO_ERROR();
+
+    // Test touching the last element + 1 is invalid, using a stride.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
+    glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Test any offset is valid if no vertices are drawn.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
+    glDrawArraysInstanced(GL_POINTS, 0, 1, 0);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test that at least one attribute has a zero divisor for WebGL
+TEST_P(WebGL2CompatibilityTest, InstancedDrawZeroDivisor)
+{
+    const std::string &vert =
+        "attribute float a_pos;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
+        "}\n";
+
+    const std::string &frag =
+        "precision highp float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vert, frag);
+
+    GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
+    ASSERT_NE(-1, posLocation);
+
+    glUseProgram(program.get());
+
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
+    glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
+
+    glEnableVertexAttribArray(posLocation);
+    glVertexAttribDivisor(posLocation, 1);
+
+    // Test touching the last element is valid.
+    glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
+    glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glVertexAttribDivisor(posLocation, 0);
+    ASSERT_GL_NO_ERROR();
+}
+
+// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
+TEST_P(WebGLCompatibilityTest, NPOT)
+{
+    EXPECT_FALSE(extensionEnabled("GL_OES_texture_npot"));
+
+    // Create a texture and set an NPOT mip 0, should always be acceptable.
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    // Try setting an NPOT mip 1 and verify the error if WebGL 1
+    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    if (getClientMajorVersion() < 3)
+    {
+        ASSERT_GL_ERROR(GL_INVALID_VALUE);
+    }
+    else
+    {
+        ASSERT_GL_NO_ERROR();
+    }
+
+    if (extensionRequestable("GL_OES_texture_npot"))
+    {
+        glRequestExtensionANGLE("GL_OES_texture_npot");
+        ASSERT_GL_NO_ERROR();
+
+        // Try again to set NPOT mip 1
+        glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+template <typename T>
+void FillTexture2D(GLuint texture,
+                   GLsizei width,
+                   GLsizei height,
+                   const T &onePixelData,
+                   GLint level,
+                   GLint internalFormat,
+                   GLenum format,
+                   GLenum type)
+{
+    std::vector<T> allPixelsData(width * height, onePixelData);
+
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
+                 allPixelsData.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+// Test that unset gl_Position defaults to (0,0,0,0).
+TEST_P(WebGLCompatibilityTest, DefaultPosition)
+{
+    // Draw a quad where each vertex is red if gl_Position is (0,0,0,0) before it is set,
+    // and green otherwise.  The center of each quadrant will be red if and only if all
+    // four corners are red.
+    const std::string vertexShader =
+        "attribute vec3 pos;\n"
+        "varying vec4 color;\n"
+        "void main() {\n"
+        "    if (gl_Position == vec4(0,0,0,0)) {\n"
+        "        color = vec4(1,0,0,1);\n"
+        "    } else {\n"
+        "        color = vec4(0,1,0,1);\n"
+        "    }\n"
+        "    gl_Position = vec4(pos,1);\n"
+        "}\n";
+
+    const std::string fragmentShader =
+        "precision mediump float;\n"
+        "varying vec4 color;\n"
+        "void main() {\n"
+        "    gl_FragColor = color;\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    drawQuad(program.get(), "pos", 0.0f, 1.0f, true);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 1 / 4, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 3 / 4, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 1 / 4, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, GLColor::red);
+}
+
+// Tests that a rendering feedback loop triggers a GL error under WebGL.
+// Based on WebGL test conformance/renderbuffers/feedback-loop.html.
+TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoop)
+{
+    const std::string vertexShader =
+        "attribute vec4 a_position;\n"
+        "varying vec2 v_texCoord;\n"
+        "void main() {\n"
+        "    gl_Position = a_position;\n"
+        "    v_texCoord = (a_position.xy * 0.5) + 0.5;\n"
+        "}\n";
+
+    const std::string fragmentShader =
+        "precision mediump float;\n"
+        "varying vec2 v_texCoord;\n"
+        "uniform sampler2D u_texture;\n"
+        "void main() {\n"
+        "    // Shader swizzles color channels so we can tell if the draw succeeded.\n"
+        "    gl_FragColor = texture2D(u_texture, v_texCoord).gbra;\n"
+        "}\n";
+
+    GLTexture texture;
+    FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+
+    ASSERT_GL_NO_ERROR();
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
+
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+
+    GLint uniformLoc = glGetUniformLocation(program.get(), "u_texture");
+    ASSERT_NE(-1, uniformLoc);
+
+    glUseProgram(program.get());
+    glUniform1i(uniformLoc, 0);
+    glDisable(GL_BLEND);
+    glDisable(GL_DEPTH_TEST);
+    ASSERT_GL_NO_ERROR();
+
+    // Drawing with a texture that is also bound to the current framebuffer should fail
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Ensure that the texture contents did not change after the previous render
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+
+    // Drawing when texture is bound to an inactive uniform should succeed
+    GLTexture texture2;
+    FillTexture2D(texture2.get(), 1, 1, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+}
+
+// Test for the max draw buffers and color attachments.
+TEST_P(WebGLCompatibilityTest, MaxDrawBuffersAttachmentPoints)
+{
+    // This test only applies to ES2.
+    if (getClientMajorVersion() != 2)
+    {
+        return;
+    }
+
+    GLFramebuffer fbo[2];
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo[0].get());
+
+    // Test that is valid when we bind with a single attachment point.
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
+    ASSERT_GL_NO_ERROR();
+
+    // Test that enabling the draw buffers extension will allow us to bind with a non-zero
+    // attachment point.
+    if (extensionRequestable("GL_EXT_draw_buffers"))
+    {
+        glRequestExtensionANGLE("GL_EXT_draw_buffers");
+        EXPECT_GL_NO_ERROR();
+        EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
+
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo[1].get());
+
+        GLTexture texture2;
+        glBindTexture(GL_TEXTURE_2D, texture2.get());
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2.get(),
+                               0);
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
+// Test that the offset in the index buffer is forced to be a multiple of the element size
+TEST_P(WebGLCompatibilityTest, DrawElementsOffsetRestriction)
+{
+    const std::string &vert =
+        "attribute vec3 a_pos;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(a_pos, 1.0);\n"
+        "}\n";
+
+    const std::string &frag =
+        "precision highp float;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, vert, frag);
+
+    GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
+    ASSERT_NE(-1, posLocation);
+    glUseProgram(program.get());
+
+    const auto &vertices = GetQuadVertices();
+
+    GLBuffer vertexBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
+                 GL_STATIC_DRAW);
+
+    glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(posLocation);
+
+    GLBuffer indexBuffer;
+    const GLubyte indices[] = {0, 0, 0, 0, 0, 0, 0};
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+
+    ASSERT_GL_NO_ERROR();
+
+    const char *zeroIndices = nullptr;
+
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, zeroIndices);
+    ASSERT_GL_NO_ERROR();
+
+    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, zeroIndices);
+    ASSERT_GL_NO_ERROR();
+
+    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, zeroIndices + 1);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test that the offset and stride in the vertex buffer is forced to be a multiple of the element
+// size
+TEST_P(WebGLCompatibilityTest, VertexAttribPointerOffsetRestriction)
+{
+    const char *zeroOffset = nullptr;
+
+    // Base case, vector of two floats
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset);
+    ASSERT_GL_NO_ERROR();
+
+    // Test setting a non-multiple offset
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 1);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 2);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 3);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Test setting a non-multiple stride
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 1, zeroOffset);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2, zeroOffset);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3, zeroOffset);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+void WebGLCompatibilityTest::drawBuffersEXTFeedbackLoop(GLuint program,
+                                                        const std::array<GLenum, 2> &drawBuffers,
+                                                        GLenum expectedError)
+{
+    glDrawBuffersEXT(2, drawBuffers.data());
+
+    // Make sure framebuffer is complete before feedback loop detection
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    drawQuad(program, "aPosition", 0.5f, 1.0f, true);
+
+    // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
+    // it should be NO_ERROR"
+    EXPECT_GL_ERROR(expectedError);
+}
+
+// This tests that rendering feedback loops works as expected with GL_EXT_draw_buffers.
+// Based on WebGL test conformance/extensions/webgl-draw-buffers-feedback-loop.html
+TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoopWithDrawBuffersEXT)
+{
+    const std::string vertexShader =
+        "attribute vec4 aPosition;\n"
+        "varying vec2 texCoord;\n"
+        "void main() {\n"
+        "    gl_Position = aPosition;\n"
+        "    texCoord = (aPosition.xy * 0.5) + 0.5;\n"
+        "}\n";
+
+    const std::string fragmentShader =
+        "#extension GL_EXT_draw_buffers : require\n"
+        "precision mediump float;\n"
+        "uniform sampler2D tex;\n"
+        "varying vec2 texCoord;\n"
+        "void main() {\n"
+        "    gl_FragData[0] = texture2D(tex, texCoord);\n"
+        "    gl_FragData[1] = texture2D(tex, texCoord);\n"
+        "}\n";
+
+    GLsizei width  = 8;
+    GLsizei height = 8;
+
+    // This shader cannot be run in ES3, because WebGL 2 does not expose the draw buffers
+    // extension and gl_FragData semantics are changed to enforce indexing by zero always.
+    // TODO(jmadill): This extension should be disabled in WebGL 2 contexts.
+    if (/*!extensionEnabled("GL_EXT_draw_buffers")*/ getClientMajorVersion() != 2)
+    {
+        // No WEBGL_draw_buffers support -- this is legal.
+        return;
+    }
+
+    GLint maxDrawBuffers = 0;
+    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
+
+    if (maxDrawBuffers < 2)
+    {
+        std::cout << "Test skipped because MAX_DRAW_BUFFERS is too small." << std::endl;
+        return;
+    }
+
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    glUseProgram(program.get());
+    glViewport(0, 0, width, height);
+
+    GLTexture tex0;
+    GLTexture tex1;
+    GLFramebuffer fbo;
+    FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+    FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+    ASSERT_GL_NO_ERROR();
+
+    glBindTexture(GL_TEXTURE_2D, tex1.get());
+    GLint texLoc = glGetUniformLocation(program.get(), "tex");
+    ASSERT_NE(-1, texLoc);
+    glUniform1i(texLoc, 0);
+    ASSERT_GL_NO_ERROR();
+
+    // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
+
+    drawBuffersEXTFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}},
+                               GL_INVALID_OPERATION);
+    drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
+                               GL_INVALID_OPERATION);
+    drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
+}
+
+// Test tests that texture copying feedback loops are properly rejected in WebGL.
+// Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html
+TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops)
+{
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    GLTexture texture2;
+    glBindTexture(GL_TEXTURE_2D, texture2.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
+
+    // framebuffer should be FRAMEBUFFER_COMPLETE.
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    ASSERT_GL_NO_ERROR();
+
+    // testing copyTexImage2D
+
+    // copyTexImage2D to same texture but different level
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0);
+    EXPECT_GL_NO_ERROR();
+
+    // copyTexImage2D to same texture same level, invalid feedback loop
+    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // copyTexImage2D to different texture
+    glBindTexture(GL_TEXTURE_2D, texture2.get());
+    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
+    EXPECT_GL_NO_ERROR();
+
+    // testing copyTexSubImage2D
+
+    // copyTexSubImage2D to same texture but different level
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
+    EXPECT_GL_NO_ERROR();
+
+    // copyTexSubImage2D to same texture same level, invalid feedback loop
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // copyTexSubImage2D to different texture
+    glBindTexture(GL_TEXTURE_2D, texture2.get());
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+    EXPECT_GL_NO_ERROR();
+}
+
+void WebGLCompatibilityTest::drawBuffersFeedbackLoop(GLuint program,
+                                                     const std::array<GLenum, 2> &drawBuffers,
+                                                     GLenum expectedError)
+{
+    glDrawBuffers(2, drawBuffers.data());
+
+    // Make sure framebuffer is complete before feedback loop detection
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    drawQuad(program, "aPosition", 0.5f, 1.0f, true);
+
+    // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
+    // it should be NO_ERROR"
+    EXPECT_GL_ERROR(expectedError);
+}
+
+// Tests invariance matching rules between built in varyings.
+// Based on WebGL test conformance/glsl/misc/shaders-with-invariance.html.
+TEST_P(WebGLCompatibilityTest, BuiltInInvariant)
+{
+    const std::string vertexShaderVariant =
+        "varying vec4 v_varying;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_PointSize = 1.0;\n"
+        "    gl_Position = v_varying;\n"
+        "}";
+    const std::string fragmentShaderInvariantGlFragCoord =
+        "invariant gl_FragCoord;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = gl_FragCoord;\n"
+        "}";
+    const std::string fragmentShaderInvariantGlPointCoord =
+        "invariant gl_PointCoord;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0);\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlFragCoord);
+    EXPECT_EQ(0u, program);
+
+    program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlPointCoord);
+    EXPECT_EQ(0u, program);
+}
+
+// Test dimension and image size validation of compressed textures
+TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC)
+{
+    if (extensionRequestable("GL_EXT_texture_compression_dxt1"))
+    {
+        glRequestExtensionANGLE("GL_EXT_texture_compression_dxt1");
+    }
+
+    if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
+    {
+        std::cout << "Test skipped because GL_EXT_texture_compression_dxt1 is not available."
+                  << std::endl;
+        return;
+    }
+
+    constexpr uint8_t CompressedImageDXT1[] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture);
+
+    // Regular case, verify that it works
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_NO_ERROR();
+
+    // Test various dimensions that are not valid
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3, 4, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 3, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Test various image sizes that are not valid
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
+                           sizeof(CompressedImageDXT1) - 1, CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
+                           sizeof(CompressedImageDXT1) + 1, CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 0,
+                           CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0, 0, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_VALUE);
+
+    // Fill a full mip chain and verify that it works
+    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
+                           sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_NO_ERROR();
+
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+                              sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_NO_ERROR();
+
+    // Test that non-block size sub-uploads are not valid for the 0 mip
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+                              sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Test that non-block size sub-uploads are valid for if they fill the whole mip
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+                              sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, 1, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+                              sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_NO_ERROR();
+
+    // Test that if the format miss-matches the texture, an error is generated
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+                              sizeof(CompressedImageDXT1), CompressedImageDXT1);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+TEST_P(WebGLCompatibilityTest, L32FTextures)
+{
+    constexpr float textureData[]   = {15.1f, 0.0f, 0.0f, 0.0f};
+    constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0], 1.0f};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized L 32F
+        {
+            bool texture = extensionEnabled("GL_OES_texture_float");
+            bool filter  = extensionEnabled("GL_OES_texture_float_linear");
+            bool render  = false;
+            TestFloatTextureFormat(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, texture, filter, render,
+                                   textureData, readPixelData);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized L 32F
+            bool texture = extensionEnabled("GL_OES_texture_float") &&
+                           extensionEnabled("GL_EXT_texture_storage");
+            bool filter = extensionEnabled("GL_OES_texture_float_linear");
+            bool render = false;
+            TestFloatTextureFormat(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT, texture, filter,
+                                   render, textureData, readPixelData);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, A32FTextures)
+{
+    constexpr float textureData[]   = {33.33f, 0.0f, 0.0f, 0.0f};
+    constexpr float readPixelData[] = {0.0f, 0.0f, 0.0f, textureData[0]};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized A 32F
+        {
+            bool texture = extensionEnabled("GL_OES_texture_float");
+            bool filter  = extensionEnabled("GL_OES_texture_float_linear");
+            bool render  = false;
+            TestFloatTextureFormat(GL_ALPHA, GL_ALPHA, GL_FLOAT, texture, filter, render,
+                                   textureData, readPixelData);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized A 32F
+            bool texture = extensionEnabled("GL_OES_texture_float") &&
+                           extensionEnabled("GL_EXT_texture_storage");
+            bool filter = extensionEnabled("GL_OES_texture_float_linear");
+            bool render = false;
+            TestFloatTextureFormat(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT, texture, filter, render,
+                                   textureData, readPixelData);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, LA32FTextures)
+{
+    constexpr float textureData[]   = {-0.21f, 15.1f, 0.0f, 0.0f};
+    constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0],
+                                       textureData[1]};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized LA 32F
+        {
+            bool texture = extensionEnabled("GL_OES_texture_float");
+            bool filter  = extensionEnabled("GL_OES_texture_float_linear");
+            bool render  = false;
+            TestFloatTextureFormat(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
+                                   filter, render, textureData, readPixelData);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized LA 32F
+            bool texture = extensionEnabled("GL_OES_texture_float") &&
+                           extensionEnabled("GL_EXT_texture_storage");
+            bool filter = extensionEnabled("GL_OES_texture_float_linear");
+            bool render = false;
+            TestFloatTextureFormat(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
+                                   filter, render, textureData, readPixelData);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, R32FTextures)
+{
+    constexpr float data[] = {1000.0f, 0.0f, 0.0f, 1.0f};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized R 32F
+        {
+            bool texture =
+                extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg");
+            bool filter = extensionEnabled("GL_OES_texture_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_float");
+            TestFloatTextureFormat(GL_RED, GL_RED, GL_FLOAT, texture, filter, render, data, data);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized R 32F
+            bool texture =
+                (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
+                                                   extensionEnabled("GL_EXT_texture_rg") &&
+                                                   extensionEnabled("GL_EXT_texture_storage"));
+            bool filter = extensionEnabled("GL_OES_texture_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_float");
+            TestFloatTextureFormat(GL_R32F, GL_RED, GL_FLOAT, texture, filter, render, data, data);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, RG32FTextures)
+{
+    constexpr float data[] = {1000.0f, -0.001f, 0.0f, 1.0f};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized RG 32F
+        {
+            bool texture =
+                (extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg"));
+            bool filter = extensionEnabled("GL_OES_texture_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_float");
+            TestFloatTextureFormat(GL_RG, GL_RG, GL_FLOAT, texture, filter, render, data, data);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized RG 32F
+            bool texture =
+                (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
+                                                   extensionEnabled("GL_EXT_texture_rg") &&
+                                                   extensionEnabled("GL_EXT_texture_storage"));
+            bool filter = extensionEnabled("GL_OES_texture_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_float");
+            TestFloatTextureFormat(GL_RG32F, GL_RG, GL_FLOAT, texture, filter, render, data, data);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, RGB32FTextures)
+{
+    if (IsLinux() && IsIntel())
+    {
+        std::cout << "Test skipped on Linux Intel." << std::endl;
+        return;
+    }
+
+    constexpr float data[] = {1000.0f, -500.0f, 10.0f, 1.0f};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized RGB 32F
+        {
+            bool texture = extensionEnabled("GL_OES_texture_float");
+            bool filter  = extensionEnabled("GL_OES_texture_float_linear");
+            bool render  = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
+            TestFloatTextureFormat(GL_RGB, GL_RGB, GL_FLOAT, texture, filter, render, data, data);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized RGBA 32F
+            bool texture =
+                (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
+                                                   extensionEnabled("GL_EXT_texture_storage"));
+            bool filter = extensionEnabled("GL_OES_texture_float_linear");
+            bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
+            TestFloatTextureFormat(GL_RGB32F, GL_RGB, GL_FLOAT, texture, filter, render, data,
+                                   data);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, RGBA32FTextures)
+{
+    constexpr float data[] = {7000.0f, 100.0f, 33.0f, -1.0f};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized RGBA 32F
+        {
+            bool texture = extensionEnabled("GL_OES_texture_float");
+            bool filter  = extensionEnabled("GL_OES_texture_float_linear");
+            bool render  = extensionEnabled("GL_EXT_color_buffer_float") ||
+                          extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
+            TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_FLOAT, texture, filter, render, data, data);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized RGBA 32F
+            bool texture =
+                (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
+                                                   extensionEnabled("GL_EXT_texture_storage"));
+            bool filter = extensionEnabled("GL_OES_texture_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
+                          extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
+            TestFloatTextureFormat(GL_RGBA32F, GL_RGBA, GL_FLOAT, texture, filter, render, data,
+                                   data);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, R16FTextures)
+{
+    constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f};
+    const GLushort textureData[]     = {
+        gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
+        gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized R 16F (OES)
+        {
+            bool texture = extensionEnabled("GL_OES_texture_half_float") &&
+                           extensionEnabled("GL_EXT_texture_rg");
+            bool filter = getClientMajorVersion() >= 3 ||
+                          extensionEnabled("GL_OES_texture_half_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
+            TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT_OES, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+
+        // Unsized R 16F
+        {
+            bool texture = false;
+            bool filter  = false;
+            bool render  = false;
+            TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized R 16F
+            bool texture = getClientMajorVersion() >= 3;
+            bool filter  = getClientMajorVersion() >= 3 ||
+                          extensionEnabled("GL_OES_texture_half_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
+                          extensionEnabled("GL_EXT_color_buffer_float");
+            TestFloatTextureFormat(GL_R16F, GL_RED, GL_HALF_FLOAT, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, RG16FTextures)
+{
+    constexpr float readPixelsData[] = {7108.0f, -10.0f, 0.0f, 1.0f};
+    const GLushort textureData[]     = {
+        gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
+        gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized RG 16F (OES)
+        {
+            bool texture = extensionEnabled("GL_OES_texture_half_float") &&
+                           extensionEnabled("GL_EXT_texture_rg");
+            bool filter = getClientMajorVersion() >= 3 ||
+                          extensionEnabled("GL_OES_texture_half_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_half_float") &&
+                          extensionEnabled("GL_EXT_texture_rg");
+            TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT_OES, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+
+        // Unsized RG 16F
+        {
+            bool texture = false;
+            bool filter  = false;
+            bool render  = false;
+            TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized RG 16F
+            bool texture = getClientMajorVersion() >= 3;
+            bool filter  = getClientMajorVersion() >= 3 ||
+                          extensionEnabled("GL_OES_texture_half_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
+                          extensionEnabled("GL_EXT_color_buffer_float");
+            TestFloatTextureFormat(GL_RG16F, GL_RG, GL_HALF_FLOAT, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, RGB16FTextures)
+{
+    if (IsOzone() && IsIntel())
+    {
+        std::cout << "Test skipped on Intel Ozone." << std::endl;
+        return;
+    }
+
+    constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, 1.0f};
+    const GLushort textureData[]     = {
+        gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
+        gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized RGB 16F (OES)
+        {
+            bool texture = extensionEnabled("GL_OES_texture_half_float");
+            bool filter  = getClientMajorVersion() >= 3 ||
+                          extensionEnabled("GL_OES_texture_half_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
+            TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+
+        // Unsized RGB 16F
+        {
+            bool texture = false;
+            bool filter  = false;
+            bool render  = false;
+            TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized RGB 16F
+            bool texture = getClientMajorVersion() >= 3;
+            bool filter  = getClientMajorVersion() >= 3 ||
+                          extensionEnabled("GL_OES_texture_half_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
+            TestFloatTextureFormat(GL_RGB16F, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+    }
+}
+
+TEST_P(WebGLCompatibilityTest, RGBA16FTextures)
+{
+    if (IsOzone() && IsIntel())
+    {
+        std::cout << "Test skipped on Intel Ozone." << std::endl;
+        return;
+    }
+
+    constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, -1.0f};
+    const GLushort textureData[]     = {
+        gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
+        gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
+
+    for (auto extension : FloatingPointTextureExtensions)
+    {
+        if (strlen(extension) > 0 && extensionRequestable(extension))
+        {
+            glRequestExtensionANGLE(extension);
+            ASSERT_GL_NO_ERROR();
+        }
+
+        // Unsized RGBA 16F (OES)
+        {
+            bool texture = extensionEnabled("GL_OES_texture_half_float");
+            bool filter  = getClientMajorVersion() >= 3 ||
+                          extensionEnabled("GL_OES_texture_half_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
+                          extensionEnabled("GL_EXT_color_buffer_float");
+            TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+
+        // Unsized RGBA 16F
+        {
+            bool texture = false;
+            bool filter  = false;
+            bool render  = false;
+            TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+
+        if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
+        {
+            // Sized RGBA 16F
+            bool texture = getClientMajorVersion() >= 3;
+            bool filter  = getClientMajorVersion() >= 3 ||
+                          extensionEnabled("GL_OES_texture_half_float_linear");
+            bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
+                          extensionEnabled("GL_EXT_color_buffer_float");
+            TestFloatTextureFormat(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
+                                   textureData, readPixelsData);
+        }
+    }
+}
+
+// This tests that rendering feedback loops works as expected with WebGL 2.
+// Based on WebGL test conformance2/rendering/rendering-sampling-feedback-loop.html
+TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDrawBuffers)
+{
+    const std::string vertexShader =
+        "#version 300 es\n"
+        "in vec4 aPosition;\n"
+        "out vec2 texCoord;\n"
+        "void main() {\n"
+        "    gl_Position = aPosition;\n"
+        "    texCoord = (aPosition.xy * 0.5) + 0.5;\n"
+        "}\n";
+
+    const std::string fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform sampler2D tex;\n"
+        "in vec2 texCoord;\n"
+        "out vec4 oColor;\n"
+        "void main() {\n"
+        "    oColor = texture(tex, texCoord);\n"
+        "}\n";
+
+    GLsizei width  = 8;
+    GLsizei height = 8;
+
+    GLint maxDrawBuffers = 0;
+    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
+    // ES3 requires a minimum value of 4 for MAX_DRAW_BUFFERS.
+    ASSERT_GE(maxDrawBuffers, 2);
+
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    glUseProgram(program.get());
+    glViewport(0, 0, width, height);
+
+    GLTexture tex0;
+    GLTexture tex1;
+    GLFramebuffer fbo;
+    FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+    FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+    ASSERT_GL_NO_ERROR();
+
+    glBindTexture(GL_TEXTURE_2D, tex1.get());
+    GLint texLoc = glGetUniformLocation(program.get(), "tex");
+    ASSERT_NE(-1, texLoc);
+    glUniform1i(texLoc, 0);
+
+    // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
+    ASSERT_GL_NO_ERROR();
+
+    drawBuffersFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}}, GL_INVALID_OPERATION);
+    drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
+                            GL_INVALID_OPERATION);
+    drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
+}
+
+// This test covers detection of rendering feedback loops between the FBO and a depth Texture.
+// Based on WebGL test conformance2/rendering/depth-stencil-feedback-loop.html
+TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDepthStencil)
+{
+    const std::string vertexShader =
+        "#version 300 es\n"
+        "in vec4 aPosition;\n"
+        "out vec2 texCoord;\n"
+        "void main() {\n"
+        "    gl_Position = aPosition;\n"
+        "    texCoord = (aPosition.xy * 0.5) + 0.5;\n"
+        "}\n";
+
+    const std::string fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform sampler2D tex;\n"
+        "in vec2 texCoord;\n"
+        "out vec4 oColor;\n"
+        "void main() {\n"
+        "    oColor = texture(tex, texCoord);\n"
+        "}\n";
+
+    GLsizei width  = 8;
+    GLsizei height = 8;
+
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    glUseProgram(program.get());
+
+    glViewport(0, 0, width, height);
+
+    GLint texLoc = glGetUniformLocation(program.get(), "tex");
+    glUniform1i(texLoc, 0);
+
+    // Create textures and allocate storage
+    GLTexture tex0;
+    GLTexture tex1;
+    GLRenderbuffer rb;
+    FillTexture2D(tex0.get(), width, height, GLColor::black, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+    FillTexture2D(tex1.get(), width, height, 0x80, 0, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT,
+                  GL_UNSIGNED_INT);
+    glBindRenderbuffer(GL_RENDERBUFFER, rb.get());
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
+    ASSERT_GL_NO_ERROR();
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
+
+    // Test rendering and sampling feedback loop for depth buffer
+    glBindTexture(GL_TEXTURE_2D, tex1.get());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex1.get(), 0);
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // The same image is used as depth buffer during rendering.
+    glEnable(GL_DEPTH_TEST);
+    drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // The same image is used as depth buffer. But depth mask is false.
+    glDepthMask(GL_FALSE);
+    drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
+    EXPECT_GL_NO_ERROR();
+
+    // The same image is used as depth buffer. But depth test is not enabled during rendering.
+    glDepthMask(GL_TRUE);
+    glDisable(GL_DEPTH_TEST);
+    drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
+    EXPECT_GL_NO_ERROR();
+
+    // Test rendering and sampling feedback loop for stencil buffer
+    glBindTexture(GL_RENDERBUFFER, rb.get());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb.get());
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    constexpr GLint stencilClearValue = 0x40;
+    glClearBufferiv(GL_STENCIL, 0, &stencilClearValue);
+
+    // The same image is used as stencil buffer during rendering.
+    glEnable(GL_STENCIL_TEST);
+    drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // The same image is used as stencil buffer. But stencil mask is zero.
+    glStencilMask(0x0);
+    drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
+    EXPECT_GL_NO_ERROR();
+
+    // The same image is used as stencil buffer. But stencil test is not enabled during rendering.
+    glStencilMask(0xffff);
+    glDisable(GL_STENCIL_TEST);
+    drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
+    EXPECT_GL_NO_ERROR();
+}
+
+// The source and the target for CopyTexSubImage3D are the same 3D texture.
+// But the level of the 3D texture != the level of the read attachment.
+TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLevels)
+{
+    GLTexture texture;
+    GLFramebuffer framebuffer;
+
+    glBindTexture(GL_TEXTURE_3D, texture.get());
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
+    ASSERT_GL_NO_ERROR();
+
+    glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
+    EXPECT_GL_NO_ERROR();
+}
+
+// The source and the target for CopyTexSubImage3D are the same 3D texture.
+// But the zoffset of the 3D texture != the layer of the read attachment.
+TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLayers)
+{
+    GLTexture texture;
+    GLFramebuffer framebuffer;
+
+    glBindTexture(GL_TEXTURE_3D, texture.get());
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 1);
+    ASSERT_GL_NO_ERROR();
+
+    glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 2, 2);
+    EXPECT_GL_NO_ERROR();
+}
+
+// The source and the target for CopyTexSubImage3D are the same 3D texture.
+// And the level / zoffset of the 3D texture is equal to the level / layer of the read attachment.
+TEST_P(WebGL2CompatibilityTest, TextureCopyingFeedbackLoop3D)
+{
+    GLTexture texture;
+    GLFramebuffer framebuffer;
+
+    glBindTexture(GL_TEXTURE_3D, texture.get());
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 1, 0);
+    ASSERT_GL_NO_ERROR();
+
+    glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Verify that errors are generated when there isn not a defined conversion between the clear type
+// and the buffer type.
+TEST_P(WebGL2CompatibilityTest, ClearBufferTypeCompatibity)
+{
+    if (IsD3D11())
+    {
+        std::cout << "Test skipped because it generates D3D11 runtime warnings." << std::endl;
+        return;
+    }
+
+    constexpr float clearFloat[]       = {0.0f, 0.0f, 0.0f, 0.0f};
+    constexpr int clearInt[]           = {0, 0, 0, 0};
+    constexpr unsigned int clearUint[] = {0, 0, 0, 0};
+
+    GLTexture texture;
+    GLFramebuffer framebuffer;
+
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
+    ASSERT_GL_NO_ERROR();
+
+    // Unsigned integer buffer
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    glClearBufferfv(GL_COLOR, 0, clearFloat);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glClearBufferiv(GL_COLOR, 0, clearInt);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glClearBufferuiv(GL_COLOR, 0, clearUint);
+    EXPECT_GL_NO_ERROR();
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Integer buffer
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    glClearBufferfv(GL_COLOR, 0, clearFloat);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glClearBufferiv(GL_COLOR, 0, clearInt);
+    EXPECT_GL_NO_ERROR();
+
+    glClearBufferuiv(GL_COLOR, 0, clearUint);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Float buffer
+    if (extensionRequestable("GL_EXT_color_buffer_float"))
+    {
+        glRequestExtensionANGLE("GL_EXT_color_buffer_float");
+    }
+
+    if (extensionEnabled("GL_EXT_color_buffer_float"))
+    {
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
+        ASSERT_GL_NO_ERROR();
+
+        glClearBufferfv(GL_COLOR, 0, clearFloat);
+        EXPECT_GL_NO_ERROR();
+
+        glClearBufferiv(GL_COLOR, 0, clearInt);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+        glClearBufferuiv(GL_COLOR, 0, clearUint);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+        glClear(GL_COLOR_BUFFER_BIT);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    // Normalized uint buffer
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    glClearBufferfv(GL_COLOR, 0, clearFloat);
+    EXPECT_GL_NO_ERROR();
+
+    glClearBufferiv(GL_COLOR, 0, clearInt);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glClearBufferuiv(GL_COLOR, 0, clearUint);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Verify that errors are generate when trying to blit from an image to itself
+TEST_P(WebGL2CompatibilityTest, BlitFramebufferSameImage)
+{
+    GLTexture textures[2];
+    glBindTexture(GL_TEXTURE_2D, textures[0]);
+    glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
+    glBindTexture(GL_TEXTURE_2D, textures[1]);
+    glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
+
+    GLRenderbuffer renderbuffers[2];
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
+
+    GLFramebuffer framebuffers[2];
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[1]);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Same texture
+    glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
+                           0);
+    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
+                           0);
+    ASSERT_GL_NO_ERROR();
+    glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Same textures but different renderbuffers
+    glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffers[0]);
+    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffers[1]);
+    ASSERT_GL_NO_ERROR();
+    glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+    glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+                      GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+    glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
+                      GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+                      GL_NEAREST);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+
+    // Same renderbuffers but different textures
+    glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
+                           0);
+    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1],
+                           0);
+    glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffers[0]);
+    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffers[0]);
+    ASSERT_GL_NO_ERROR();
+    glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+    glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+                      GL_NEAREST);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+    glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
+                      GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+                      GL_NEAREST);
+    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
+
+ANGLE_INSTANTIATE_TEST(WebGL2CompatibilityTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/WebGLFramebufferTest.cpp b/src/third_party/angle/src/tests/gl_tests/WebGLFramebufferTest.cpp
new file mode 100644
index 0000000..9cc707d
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/WebGLFramebufferTest.cpp
@@ -0,0 +1,835 @@
+//
+// Copyright 2017 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.
+//
+
+// WebGLFramebufferTest.cpp : Framebuffer tests for GL_ANGLE_webgl_compatibility.
+// Based on WebGL 1 test renderbuffers/framebuffer-object-attachment.
+
+#include "test_utils/ANGLETest.h"
+
+#include "test_utils/gl_raii.h"
+
+namespace angle
+{
+
+class WebGLFramebufferTest : public ANGLETest
+{
+  protected:
+    WebGLFramebufferTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setWebGLCompatibilityEnabled(true);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+        glRequestExtensionANGLE = reinterpret_cast<PFNGLREQUESTEXTENSIONANGLEPROC>(
+            eglGetProcAddress("glRequestExtensionANGLE"));
+    }
+
+    void drawUByteColorQuad(GLuint program, GLint uniformLoc, const GLColor &color);
+    void testDepthStencilDepthStencil(GLint width, GLint height);
+    void testDepthStencilRenderbuffer(GLint width,
+                                      GLint height,
+                                      GLRenderbuffer *colorBuffer,
+                                      GLbitfield allowedStatuses);
+    void testRenderingAndReading(GLuint program);
+    void testUsingIncompleteFramebuffer(GLenum depthFormat, GLenum depthAttachment);
+
+    PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
+};
+
+constexpr GLint ALLOW_COMPLETE              = 0x1;
+constexpr GLint ALLOW_UNSUPPORTED           = 0x2;
+constexpr GLint ALLOW_INCOMPLETE_ATTACHMENT = 0x4;
+
+void checkFramebufferForAllowedStatuses(GLbitfield allowedStatuses)
+{
+    // If the framebuffer is in an error state for multiple reasons,
+    // we can't guarantee which one will be reported.
+    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    bool statusAllowed =
+        ((allowedStatuses & ALLOW_COMPLETE) && (status == GL_FRAMEBUFFER_COMPLETE)) ||
+        ((allowedStatuses & ALLOW_UNSUPPORTED) && (status == GL_FRAMEBUFFER_UNSUPPORTED)) ||
+        ((allowedStatuses & ALLOW_INCOMPLETE_ATTACHMENT) &&
+         (status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
+    EXPECT_TRUE(statusAllowed);
+}
+
+void checkBufferBits(GLenum attachment0, GLenum attachment1)
+{
+    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+        return;
+
+    bool haveDepthBuffer =
+        attachment0 == GL_DEPTH_ATTACHMENT || attachment0 == GL_DEPTH_STENCIL_ATTACHMENT ||
+        attachment1 == GL_DEPTH_ATTACHMENT || attachment1 == GL_DEPTH_STENCIL_ATTACHMENT;
+    bool haveStencilBuffer =
+        attachment0 == GL_STENCIL_ATTACHMENT || attachment0 == GL_DEPTH_STENCIL_ATTACHMENT ||
+        attachment1 == GL_STENCIL_ATTACHMENT || attachment1 == GL_DEPTH_STENCIL_ATTACHMENT;
+
+    GLint redBits     = 0;
+    GLint greenBits   = 0;
+    GLint blueBits    = 0;
+    GLint alphaBits   = 0;
+    GLint depthBits   = 0;
+    GLint stencilBits = 0;
+    glGetIntegerv(GL_RED_BITS, &redBits);
+    glGetIntegerv(GL_GREEN_BITS, &greenBits);
+    glGetIntegerv(GL_BLUE_BITS, &blueBits);
+    glGetIntegerv(GL_ALPHA_BITS, &alphaBits);
+    glGetIntegerv(GL_DEPTH_BITS, &depthBits);
+    glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
+
+    EXPECT_GE(redBits + greenBits + blueBits + alphaBits, 16);
+
+    if (haveDepthBuffer)
+        EXPECT_GE(depthBits, 16);
+    else
+        EXPECT_EQ(0, depthBits);
+
+    if (haveStencilBuffer)
+        EXPECT_GE(stencilBits, 8);
+    else
+        EXPECT_EQ(0, stencilBits);
+}
+
+// Tests that certain required combinations work in WebGL compatiblity.
+TEST_P(WebGLFramebufferTest, TestFramebufferRequiredCombinations)
+{
+    // Per discussion with the OpenGL ES working group, the following framebuffer attachment
+    // combinations are required to work in all WebGL implementations:
+    // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
+    // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16
+    // renderbuffer
+    // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL
+    // renderbuffer
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    constexpr int width  = 64;
+    constexpr int height = 64;
+
+    // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+    EXPECT_GL_NO_ERROR();
+    checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
+    checkBufferBits(GL_NONE, GL_NONE);
+
+    // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16
+    // renderbuffer
+    GLRenderbuffer renderbuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
+    EXPECT_GL_NO_ERROR();
+    checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
+    checkBufferBits(GL_DEPTH_ATTACHMENT, GL_NONE);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+
+    // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL
+    // renderbuffer
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuffer);
+    EXPECT_GL_NO_ERROR();
+    checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
+    checkBufferBits(GL_DEPTH_STENCIL_ATTACHMENT, GL_NONE);
+}
+
+void testAttachment(GLint width,
+                    GLint height,
+                    GLRenderbuffer *colorBuffer,
+                    GLenum attachment,
+                    GLRenderbuffer *buffer,
+                    GLbitfield allowedStatuses)
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, *buffer);
+    EXPECT_GL_NO_ERROR();
+    checkFramebufferForAllowedStatuses(allowedStatuses);
+    if ((allowedStatuses & ALLOW_COMPLETE) == 0)
+    {
+        std::vector<uint8_t> tempBuffer(width * height * 4);
+
+        glClear(GL_COLOR_BUFFER_BIT);
+        EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+        glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, tempBuffer.data());
+        EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+    }
+    checkBufferBits(attachment, GL_NONE);
+}
+
+void testAttachments(GLRenderbuffer &colorBuffer,
+                     GLenum attachment0,
+                     GLRenderbuffer &buffer0,
+                     GLenum attachment1,
+                     GLRenderbuffer &buffer1,
+                     GLbitfield allowedStatuses)
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment0, GL_RENDERBUFFER, buffer0);
+    EXPECT_GL_NO_ERROR();
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment1, GL_RENDERBUFFER, buffer1);
+    EXPECT_GL_NO_ERROR();
+    checkFramebufferForAllowedStatuses(allowedStatuses);
+    checkBufferBits(attachment0, attachment1);
+}
+
+void testColorRenderbuffer(GLint width,
+                           GLint height,
+                           GLenum internalformat,
+                           GLbitfield allowedStatuses)
+{
+    GLRenderbuffer colorBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, internalformat, width, height);
+    EXPECT_GL_NO_ERROR();
+    testAttachment(width, height, &colorBuffer, GL_COLOR_ATTACHMENT0, &colorBuffer,
+                   allowedStatuses);
+}
+
+GLint getRenderbufferParameter(GLenum paramName)
+{
+    GLint paramValue = 0;
+    glGetRenderbufferParameteriv(GL_RENDERBUFFER, paramName, &paramValue);
+    return paramValue;
+}
+
+void WebGLFramebufferTest::drawUByteColorQuad(GLuint program,
+                                              GLint uniformLoc,
+                                              const GLColor &color)
+{
+    Vector4 vecColor = color.toNormalizedVector();
+    glUseProgram(program);
+    glUniform4fv(uniformLoc, 1, vecColor.data());
+    drawQuad(program, "position", 0.5f, 1.0f, true);
+}
+
+void WebGLFramebufferTest::testDepthStencilDepthStencil(GLint width, GLint height)
+{
+    const std::string &vertexShader =
+        "attribute vec4 position;\n"
+        "void main() {\n"
+        "    gl_Position = position;\n"
+        "}";
+    const std::string &fragmentShader =
+        "precision mediump float;\n"
+        "uniform vec4 color;\n"
+        "void main() {\n"
+        "    gl_FragColor = color;\n"
+        "}";
+
+    if (width == 0 || height == 0)
+    {
+        return;
+    }
+
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    GLint uniformLoc = glGetUniformLocation(program.get(), "color");
+    ASSERT_NE(-1, uniformLoc);
+
+    struct TestInfo
+    {
+        GLenum firstFormat;
+        GLenum firstAttach;
+        GLenum secondFormat;
+        GLenum secondAttach;
+    };
+
+    TestInfo tests[2] = {
+        {GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL_ATTACHMENT},
+        {GL_DEPTH_STENCIL, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT}};
+
+    for (const TestInfo &test : tests)
+    {
+        for (GLint opIndex = 0; opIndex < 2; ++opIndex)
+        {
+            GLFramebuffer fbo;
+            GLTexture tex;
+            GLRenderbuffer firstRb;
+
+            // test: firstFormat vs secondFormat with unbind or delete.
+
+            glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+            // attach texture as color
+            glBindTexture(GL_TEXTURE_2D, tex);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                         nullptr);
+            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+
+            // attach first
+            glBindRenderbuffer(GL_RENDERBUFFER, firstRb);
+            glRenderbufferStorage(GL_RENDERBUFFER, test.firstFormat, width, height);
+            glFramebufferRenderbuffer(GL_FRAMEBUFFER, test.firstAttach, GL_RENDERBUFFER, firstRb);
+
+            EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+            // TODO(jmadill): Remove clear - this should be implicit in WebGL_
+            glClear(GL_DEPTH_BUFFER_BIT);
+
+            glEnable(GL_DEPTH_TEST);
+            // Test it works
+            drawUByteColorQuad(program.get(), uniformLoc, GLColor::green);
+            // should not draw since DEPTH_FUNC == LESS
+            drawUByteColorQuad(program.get(), uniformLoc, GLColor::red);
+            // should be green
+            EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+            GLuint secondRb = 0;
+            glGenRenderbuffers(1, &secondRb);
+
+            // attach second
+            glBindRenderbuffer(GL_RENDERBUFFER, secondRb);
+            glRenderbufferStorage(GL_RENDERBUFFER, test.secondFormat, width, height);
+            glFramebufferRenderbuffer(GL_FRAMEBUFFER, test.secondAttach, GL_RENDERBUFFER, secondRb);
+
+            if (opIndex == 0)
+            {
+                // now delete it
+                glDeleteRenderbuffers(1, &secondRb);
+                secondRb = 0;
+            }
+            else
+            {
+                // unbind it
+                glFramebufferRenderbuffer(GL_FRAMEBUFFER, test.secondAttach, GL_RENDERBUFFER, 0);
+            }
+
+            // If the first attachment is not restored this may fail
+            EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+            EXPECT_GL_NO_ERROR();
+
+            // If the first attachment is not restored this may fail.
+            glClear(GL_DEPTH_BUFFER_BIT);
+            drawUByteColorQuad(program.get(), uniformLoc, GLColor::green);
+            // should not draw since DEPTH_FUNC == LESS
+            drawUByteColorQuad(program.get(), uniformLoc, GLColor::red);
+            // should be green
+            EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+            glDisable(GL_DEPTH_TEST);
+
+            if (opIndex == 1)
+            {
+                glDeleteRenderbuffers(1, &secondRb);
+                secondRb = 0;
+            }
+        }
+    }
+    EXPECT_GL_NO_ERROR();
+}
+
+void WebGLFramebufferTest::testDepthStencilRenderbuffer(GLint width,
+                                                        GLint height,
+                                                        GLRenderbuffer *colorBuffer,
+                                                        GLbitfield allowedStatuses)
+{
+    GLRenderbuffer depthStencilBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, depthStencilBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
+    EXPECT_GL_NO_ERROR();
+
+    // OpenGL itself doesn't seem to guarantee that e.g. a 2 x 0
+    // renderbuffer will report 2 for its width when queried.
+    if (!(height == 0 && width > 0))
+        EXPECT_EQ(width, getRenderbufferParameter(GL_RENDERBUFFER_WIDTH));
+    if (!(width == 0 && height > 0))
+        EXPECT_EQ(height, getRenderbufferParameter(GL_RENDERBUFFER_HEIGHT));
+    EXPECT_EQ(GL_DEPTH_STENCIL, getRenderbufferParameter(GL_RENDERBUFFER_INTERNAL_FORMAT));
+    EXPECT_EQ(0, getRenderbufferParameter(GL_RENDERBUFFER_RED_SIZE));
+    EXPECT_EQ(0, getRenderbufferParameter(GL_RENDERBUFFER_GREEN_SIZE));
+    EXPECT_EQ(0, getRenderbufferParameter(GL_RENDERBUFFER_BLUE_SIZE));
+    EXPECT_EQ(0, getRenderbufferParameter(GL_RENDERBUFFER_ALPHA_SIZE));
+
+    // Avoid verifying these for zero-sized renderbuffers for the time
+    // being since it appears that even OpenGL doesn't guarantee them.
+    if (width > 0 && height > 0)
+    {
+        EXPECT_GT(getRenderbufferParameter(GL_RENDERBUFFER_DEPTH_SIZE), 0);
+        EXPECT_GT(getRenderbufferParameter(GL_RENDERBUFFER_STENCIL_SIZE), 0);
+    }
+    EXPECT_GL_NO_ERROR();
+    testAttachment(width, height, colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, &depthStencilBuffer,
+                   allowedStatuses);
+    testDepthStencilDepthStencil(width, height);
+}
+
+// Test various attachment combinations with WebGL framebuffers.
+TEST_P(WebGLFramebufferTest, TestAttachments)
+{
+    for (GLint width = 2; width <= 2; width += 2)
+    {
+        for (GLint height = 2; height <= 2; height += 2)
+        {
+            // Dimensions width x height.
+            GLRenderbuffer colorBuffer;
+            glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
+            glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, width, height);
+            EXPECT_GL_NO_ERROR();
+
+            GLRenderbuffer depthBuffer;
+            glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
+            glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
+            EXPECT_GL_NO_ERROR();
+
+            GLRenderbuffer stencilBuffer;
+            glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
+            glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
+            EXPECT_GL_NO_ERROR();
+
+            GLRenderbuffer depthStencilBuffer;
+            glBindRenderbuffer(GL_RENDERBUFFER, depthStencilBuffer);
+            glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
+            EXPECT_GL_NO_ERROR();
+
+            GLbitfield allowedStatusForGoodCase =
+                (width == 0 || height == 0) ? ALLOW_INCOMPLETE_ATTACHMENT : ALLOW_COMPLETE;
+
+            // some cases involving stencil seem to be implementation-dependent
+            GLbitfield allowedStatusForImplDependentCase =
+                allowedStatusForGoodCase | ALLOW_UNSUPPORTED;
+
+            // Attach depth using DEPTH_ATTACHMENT.
+            testAttachment(width, height, &colorBuffer, GL_DEPTH_ATTACHMENT, &depthBuffer,
+                           allowedStatusForGoodCase);
+
+            // Attach depth using STENCIL_ATTACHMENT.
+            testAttachment(width, height, &colorBuffer, GL_STENCIL_ATTACHMENT, &depthBuffer,
+                           ALLOW_INCOMPLETE_ATTACHMENT);
+
+            // Attach depth using DEPTH_STENCIL_ATTACHMENT.
+            testAttachment(width, height, &colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, &depthBuffer,
+                           ALLOW_INCOMPLETE_ATTACHMENT);
+
+            // Attach stencil using STENCIL_ATTACHMENT.
+            testAttachment(width, height, &colorBuffer, GL_STENCIL_ATTACHMENT, &stencilBuffer,
+                           allowedStatusForImplDependentCase);
+
+            // Attach stencil using DEPTH_ATTACHMENT.
+            testAttachment(width, height, &colorBuffer, GL_DEPTH_ATTACHMENT, &stencilBuffer,
+                           ALLOW_INCOMPLETE_ATTACHMENT);
+
+            // Attach stencil using DEPTH_STENCIL_ATTACHMENT.
+            testAttachment(width, height, &colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, &stencilBuffer,
+                           ALLOW_INCOMPLETE_ATTACHMENT);
+
+            // Attach depthStencil using DEPTH_STENCIL_ATTACHMENT.
+            testAttachment(width, height, &colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT,
+                           &depthStencilBuffer, allowedStatusForGoodCase);
+
+            // Attach depthStencil using DEPTH_ATTACHMENT.
+            testAttachment(width, height, &colorBuffer, GL_DEPTH_ATTACHMENT, &depthStencilBuffer,
+                           ALLOW_INCOMPLETE_ATTACHMENT);
+
+            // Attach depthStencil using STENCIL_ATTACHMENT.
+            testAttachment(width, height, &colorBuffer, GL_STENCIL_ATTACHMENT, &depthStencilBuffer,
+                           ALLOW_INCOMPLETE_ATTACHMENT);
+
+            GLbitfield allowedStatusForConflictedAttachment =
+                (width == 0 || height == 0) ? ALLOW_UNSUPPORTED | ALLOW_INCOMPLETE_ATTACHMENT
+                                            : ALLOW_UNSUPPORTED;
+
+            // Attach depth, then stencil, causing conflict.
+            testAttachments(colorBuffer, GL_DEPTH_ATTACHMENT, depthBuffer, GL_STENCIL_ATTACHMENT,
+                            stencilBuffer, allowedStatusForConflictedAttachment);
+
+            // Attach stencil, then depth, causing conflict.
+            testAttachments(colorBuffer, GL_STENCIL_ATTACHMENT, stencilBuffer, GL_DEPTH_ATTACHMENT,
+                            depthBuffer, allowedStatusForConflictedAttachment);
+
+            // Attach depth, then depthStencil, causing conflict.
+            testAttachments(colorBuffer, GL_DEPTH_ATTACHMENT, depthBuffer,
+                            GL_DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer,
+                            allowedStatusForConflictedAttachment);
+
+            // Attach depthStencil, then depth, causing conflict.
+            testAttachments(colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer,
+                            GL_DEPTH_ATTACHMENT, depthBuffer, allowedStatusForConflictedAttachment);
+
+            // Attach stencil, then depthStencil, causing conflict.
+            testAttachments(colorBuffer, GL_DEPTH_ATTACHMENT, depthBuffer,
+                            GL_DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer,
+                            allowedStatusForConflictedAttachment);
+
+            // Attach depthStencil, then stencil, causing conflict.
+            testAttachments(colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer,
+                            GL_STENCIL_ATTACHMENT, stencilBuffer,
+                            allowedStatusForConflictedAttachment);
+
+            // Attach color renderbuffer with internalformat == RGBA4.
+            testColorRenderbuffer(width, height, GL_RGBA4, allowedStatusForGoodCase);
+
+            // Attach color renderbuffer with internalformat == RGB5_A1.
+            // This particular format seems to be bugged on NVIDIA Retina. http://crbug.com/635081
+            // TODO(jmadill): Figure out if we can add a format workaround.
+            if (!(IsNVIDIA() && IsOSX() && IsOpenGL()))
+            {
+                testColorRenderbuffer(width, height, GL_RGB5_A1, allowedStatusForGoodCase);
+            }
+
+            // Attach color renderbuffer with internalformat == RGB565.
+            testColorRenderbuffer(width, height, GL_RGB565, allowedStatusForGoodCase);
+
+            // Create and attach depthStencil renderbuffer.
+            testDepthStencilRenderbuffer(width, height, &colorBuffer, allowedStatusForGoodCase);
+        }
+    }
+}
+
+bool tryDepth(GLRenderbuffer *depthBuffer,
+              GLenum *depthFormat,
+              GLenum *depthAttachment,
+              GLenum try_format,
+              GLenum try_attachment)
+{
+    if (*depthAttachment != GL_NONE)
+    {
+        // If we've tried once unattach the old one.
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, *depthAttachment, GL_RENDERBUFFER, 0);
+    }
+    *depthFormat     = try_format;
+    *depthAttachment = try_attachment;
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, *depthAttachment, GL_RENDERBUFFER, *depthBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, *depthFormat, 16, 16);
+    EXPECT_GL_NO_ERROR();
+    return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
+}
+
+bool checkValidColorDepthCombination(GLenum *depthFormat, GLenum *depthAttachment)
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    GLRenderbuffer colorBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
+
+    GLRenderbuffer depthBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
+
+    return tryDepth(&depthBuffer, depthFormat, depthAttachment, GL_DEPTH_COMPONENT16,
+                    GL_DEPTH_ATTACHMENT) ||
+           tryDepth(&depthBuffer, depthFormat, depthAttachment, GL_DEPTH_STENCIL,
+                    GL_DEPTH_STENCIL_ATTACHMENT);
+}
+
+// glCheckFramebufferStatus(GL_FRAMEBUFFER) should be either complete or (unsupported/expected).
+void checkFramebuffer(GLenum expected)
+{
+    GLenum actual = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    EXPECT_TRUE(actual == expected ||
+                (expected != GL_FRAMEBUFFER_COMPLETE && actual == GL_FRAMEBUFFER_UNSUPPORTED));
+}
+
+void WebGLFramebufferTest::testRenderingAndReading(GLuint program)
+{
+    EXPECT_GL_NO_ERROR();
+
+    // drawArrays with incomplete framebuffer
+    drawQuad(program, "position", 0.5f, 1.0f, true);
+    EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+
+    // readPixels from incomplete framebuffer
+    std::vector<uint8_t> dummyBuffer(4);
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, dummyBuffer.data());
+    EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+
+    // copyTexImage and copyTexSubImage can be either INVALID_FRAMEBUFFER_OPERATION because
+    // the framebuffer is invalid OR INVALID_OPERATION because in the case of no attachments
+    // the framebuffer is not of a compatible type.
+
+    // copyTexSubImage2D from incomplete framebuffer
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+    GLenum error = glGetError();
+    EXPECT_TRUE(error == GL_INVALID_FRAMEBUFFER_OPERATION || error == GL_INVALID_OPERATION);
+
+    // copyTexImage2D from incomplete framebuffer
+    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0);
+    error = glGetError();
+    EXPECT_TRUE(error == GL_INVALID_FRAMEBUFFER_OPERATION || error == GL_INVALID_OPERATION);
+
+    // clear with incomplete framebuffer
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+}
+
+// Test drawing or reading from an incomplete framebuffer
+void WebGLFramebufferTest::testUsingIncompleteFramebuffer(GLenum depthFormat,
+                                                          GLenum depthAttachment)
+{
+    // Simple draw program.
+    const std::string &vertexShader =
+        "attribute vec4 position; void main() { gl_Position = position; }";
+    const std::string &fragmentShader = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
+
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    GLRenderbuffer colorBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
+
+    GLRenderbuffer depthBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, depthAttachment, GL_RENDERBUFFER, depthBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 16, 16);
+    EXPECT_GL_NO_ERROR();
+    checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
+
+    // We pick this combination because it works on desktop OpenGL but should not work on OpenGL ES
+    // 2.0
+    glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 32, 16);
+    checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
+
+    // Drawing or reading from an incomplete framebuffer should generate
+    // INVALID_FRAMEBUFFER_OPERATION.
+    testRenderingAndReading(program.get());
+
+    GLFramebuffer fbo2;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
+    checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+
+    // Drawing or reading from an incomplete framebuffer should generate
+    // INVALID_FRAMEBUFFER_OPERATION.
+    testRenderingAndReading(program.get());
+
+    GLRenderbuffer colorBuffer2;
+    glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer2);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer2);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 0, 0);
+
+    // Drawing or reading from an incomplete framebuffer should generate
+    // INVALID_FRAMEBUFFER_OPERATION.
+    testRenderingAndReading(program.get());
+}
+
+void testFramebufferIncompleteAttachment(GLenum depthFormat)
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    GLRenderbuffer colorBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
+    checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
+
+    // Wrong storage type for type of attachment be FRAMEBUFFER_INCOMPLETE_ATTACHMENT (OpenGL ES 2.0
+    // 4.4.5).
+    glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 16, 16);
+    checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
+
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
+    checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
+
+    // 0 size attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT (OpenGL ES 2.0 4.4.5).
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 0, 0);
+    checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// No attachments should be INCOMPLETE_FRAMEBUFFER_MISSING_ATTACHMENT (OpenGL ES 2.0 4.4.5).
+void testFramebufferIncompleteMissingAttachment()
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+
+    GLRenderbuffer colorBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
+    checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
+
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
+    checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Attachments of different sizes should be FRAMEBUFFER_INCOMPLETE_DIMENSIONS (OpenGL ES 2.0 4.4.5).
+void testFramebufferIncompleteDimensions(GLenum depthFormat, GLenum depthAttachment)
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    GLRenderbuffer colorBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
+
+    GLRenderbuffer depthBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, depthAttachment, GL_RENDERBUFFER, depthBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 16, 16);
+    EXPECT_GL_NO_ERROR();
+    checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
+
+    glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 32, 16);
+    checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
+    glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 16, 16);
+    checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
+    glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 32);
+    checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
+    checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
+    EXPECT_GL_NO_ERROR();
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+    EXPECT_GL_NO_ERROR();
+    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return;
+    }
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test drawing or reading from a missing framebuffer attachment.
+void testReadingFromMissingAttachment()
+{
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    constexpr int size = 16;
+
+    // The only scenario we can verify is an attempt to read or copy
+    // from a missing color attachment while the framebuffer is still
+    // complete.
+    GLRenderbuffer depthBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size);
+
+    // After depth renderbuffer setup
+    EXPECT_GL_NO_ERROR();
+
+    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        // Unable to allocate a framebuffer with just a depth attachment; this is legal.
+        // Try just a depth/stencil renderbuffer
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+        GLRenderbuffer depthStencilBuffer;
+        glBindRenderbuffer(GL_RENDERBUFFER, depthStencilBuffer);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                                  depthStencilBuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, size, size);
+        // After depth+stencil renderbuffer setup
+        EXPECT_GL_NO_ERROR();
+        // Unable to allocate a framebuffer with just a depth+stencil attachment; this is legal.
+        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+        {
+            return;
+        }
+    }
+
+    // The FBO has no color attachment. ReadPixels, CopyTexImage2D,
+    // and CopyTexSubImage2D should all generate INVALID_OPERATION.
+
+    // Before ReadPixels from missing attachment
+    std::vector<uint8_t> dummyBuffer(4);
+    EXPECT_GL_NO_ERROR();
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, dummyBuffer.data());
+    // After ReadPixels from missing attachment
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex);
+    // Before CopyTexImage2D from missing attachment
+    EXPECT_GL_NO_ERROR();
+    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, size, size, 0);
+    // After CopyTexImage2D from missing attachment
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    // Before CopyTexSubImage2D from missing attachment
+    EXPECT_GL_NO_ERROR();
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size, size);
+    // After CopyTexSubImage2D from missing attachment
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Determine if we can attach both color and depth or color and depth_stencil
+TEST_P(WebGLFramebufferTest, CheckValidColorDepthCombination)
+{
+    GLenum depthFormat     = GL_NONE;
+    GLenum depthAttachment = GL_NONE;
+
+    if (checkValidColorDepthCombination(&depthFormat, &depthAttachment))
+    {
+        testFramebufferIncompleteDimensions(depthFormat, depthAttachment);
+        testFramebufferIncompleteAttachment(depthFormat);
+        testFramebufferIncompleteMissingAttachment();
+        testUsingIncompleteFramebuffer(depthFormat, depthAttachment);
+        testReadingFromMissingAttachment();
+    }
+}
+
+// Test to cover a bug in preserving the texture image index for WebGL framebuffer attachments
+TEST_P(WebGLFramebufferTest, TextureAttachmentCommitBug)
+{
+    if (extensionRequestable("GL_ANGLE_depth_texture"))
+    {
+        glRequestExtensionANGLE("GL_ANGLE_depth_texture");
+    }
+
+    if (!extensionEnabled("GL_ANGLE_depth_texture"))
+    {
+        std::cout << "Test skipped because depth textures are not available.\n";
+        return;
+    }
+
+    GLTexture depthTexture;
+    glBindTexture(GL_TEXTURE_2D, depthTexture.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,
+                 nullptr);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture.get(),
+                           0);
+
+    glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Only run against WebGL 1 validation, since much was changed in 2.
+ANGLE_INSTANTIATE_TEST(WebGLFramebufferTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_D3D11_FL9_3(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/gl_tests/media/pixel.inl b/src/third_party/angle/src/tests/gl_tests/media/pixel.inl
new file mode 100644
index 0000000..586e694
--- /dev/null
+++ b/src/third_party/angle/src/tests/gl_tests/media/pixel.inl
@@ -0,0 +1,11000 @@
+// Automatically generated header from pixel.dds, a 512x512 (10 mip levels)
+// DXT1 texture using DDSToHeader.exe.
+static const size_t pixel_width = 512;
+static const size_t pixel_height = 512;
+static const size_t pixel_levels = 10;
+
+static const size_t pixel_0_width = 512;
+static const size_t pixel_0_height = 512;
+static const size_t pixel_0_size = 131072;
+static const unsigned char pixel_0_data[131072] =
+{
+    0x46,0x62,0x63,0x41,0x8B,0x8B,0xFD,0x55,0xE5,0x51,0x22,0x39,0xAA,0xA8,0xFE,0xD5,
+    0xC5,0x51,0x23,0x39,0x60,0x60,0xAE,0xAF,0xA5,0x49,0x02,0x39,0x0B,0x2D,0x97,0xFF,
+    0x47,0x62,0x02,0x39,0x0A,0xAB,0x5F,0x7D,0xE5,0x51,0xC1,0x30,0x80,0xAA,0xDF,0xD5,
+    0xA5,0x49,0x23,0x39,0x60,0xEF,0xE9,0x2D,0xC5,0x51,0xE2,0x30,0xAD,0xFD,0xFF,0x80,
+    0x27,0x5A,0x43,0x39,0x0E,0xF5,0x55,0x7F,0xE5,0x49,0xC1,0x30,0xA8,0xFF,0xD5,0xF7,
+    0xE5,0x49,0x23,0x39,0xEB,0xED,0xAF,0x2B,0xC9,0x6A,0x23,0x39,0x55,0x55,0xF7,0x82,
+    0x06,0x52,0x03,0x31,0xFD,0x7D,0x6B,0xA8,0x84,0x41,0xE2,0x30,0xAE,0xD5,0xDF,0x7C,
+    0xC5,0x49,0x43,0x39,0x5D,0xBF,0x09,0x29,0xA8,0x6A,0x42,0x39,0x55,0x5F,0xE2,0x82,
+    0xE6,0x51,0x23,0x39,0x55,0x5E,0xEA,0xA8,0x84,0x41,0xE2,0x30,0xD5,0xD5,0xDE,0xD8,
+    0xC5,0x49,0x43,0x41,0xFD,0x37,0x2F,0x3D,0xE9,0x72,0x43,0x41,0x55,0xEA,0x82,0xBB,
+    0xC5,0x49,0xE2,0x38,0x7F,0xEA,0xE8,0xAA,0x44,0x41,0xC2,0x30,0x2D,0xB5,0xDE,0xF8,
+    0xE5,0x51,0xE2,0x30,0xAB,0x2B,0xAB,0xB5,0x67,0x62,0x64,0x41,0x5B,0xC0,0x83,0xD7,
+    0xA5,0x49,0x02,0x39,0x7B,0xFA,0x88,0xFE,0xA5,0x51,0x02,0x39,0x2D,0x3F,0xBE,0xAA,
+    0x67,0x62,0x84,0x49,0x2A,0x2A,0xB7,0x7D,0x88,0x6A,0x64,0x49,0xA8,0xFA,0xFE,0x55,
+    0x06,0x5A,0x64,0x49,0x68,0xE8,0xBB,0xFF,0xA5,0x51,0x02,0x39,0x37,0x97,0xDE,0x78,
+    0x47,0x62,0x02,0x39,0x0A,0xAB,0xD7,0x55,0xA9,0x6A,0xC2,0x30,0xE8,0xFA,0xFF,0xD5,
+    0xA5,0x49,0x23,0x39,0xE0,0xB7,0xB7,0xAF,0xA5,0x49,0x02,0x39,0x2D,0xD7,0xDA,0xFA,
+    0x27,0x5A,0x03,0x39,0x0A,0xFF,0x55,0x55,0xA5,0x49,0x23,0x39,0x28,0x6F,0x7D,0xAD,
+    0xC6,0x51,0x03,0x39,0x7E,0xFF,0xBD,0x0B,0xC5,0x51,0xE2,0x38,0xAD,0xD7,0xFE,0xE8,
+    0x85,0x49,0xE2,0x30,0x0A,0xDF,0xD7,0x7E,0xA5,0x49,0x24,0x39,0xF8,0x7D,0xF9,0x0B,
+    0x27,0x5A,0x43,0x39,0x55,0x7D,0xFF,0x82,0x85,0x49,0xC2,0x30,0xEF,0x7F,0xA8,0x02,
+    0x85,0x49,0xC3,0x30,0xAB,0xBD,0x3F,0xFA,0xC6,0x51,0x23,0x39,0xD5,0xBF,0x02,0x02,
+    0xE6,0x51,0x03,0x39,0x7F,0xEA,0xA0,0x80,0xC6,0x51,0x02,0x39,0x55,0x5E,0xEA,0x08,
+    0xC5,0x51,0x23,0x39,0xBD,0x2D,0xA5,0xD5,0x47,0x5A,0x64,0x41,0x7F,0x8A,0x0B,0x8B,
+    0xE6,0x51,0x43,0x41,0x5D,0xEE,0xB8,0xE0,0x85,0x49,0x03,0x39,0x57,0x76,0xF0,0xC0,
+    0xC5,0x51,0xE3,0x30,0x2B,0x0B,0x2B,0xA5,0xC9,0x72,0xA4,0x49,0x5D,0x0A,0x8B,0xD5,
+    0x88,0x6A,0xA5,0x51,0x5F,0x82,0x00,0x5F,0x06,0x5A,0x64,0x41,0x5B,0xB8,0xAE,0xBE,
+    0xC5,0x51,0x63,0x41,0xAE,0x28,0xCA,0x5F,0xC6,0x51,0x43,0x39,0x00,0x80,0xAA,0xF7,
+    0x06,0x52,0x23,0x39,0xFA,0x2A,0x3A,0x95,0x66,0x62,0x63,0x41,0xD5,0xAE,0x22,0x22,
+    0x47,0x62,0xA4,0x49,0xDD,0xAB,0xA0,0x80,0x68,0x62,0xE5,0x51,0xAD,0x0B,0xAA,0x2A,
+    0x67,0x6A,0xE5,0x51,0x56,0x28,0x2E,0x3B,0xC7,0x72,0x24,0x5A,0xD5,0xBF,0x2F,0x6E,
+    0xA7,0x6A,0x05,0x5A,0xAE,0x82,0xA8,0x75,0x66,0x62,0xC4,0x51,0x08,0x2A,0xEA,0xFD,
+    0x67,0x6A,0xE5,0x51,0x2C,0x8A,0x8A,0xA6,0x88,0x6A,0x47,0x62,0x77,0x5F,0xD7,0x99,
+    0x87,0x6A,0x25,0x5A,0x68,0xAA,0xEB,0xFB,0xA7,0x6A,0xC5,0x51,0x7A,0xE8,0x8A,0x2A,
+    0x46,0x5A,0x23,0x39,0x55,0x5E,0xDA,0xA0,0x85,0x49,0x23,0x39,0x0F,0xF5,0x35,0xD7,
+    0x68,0x62,0x44,0x41,0x57,0x75,0x27,0x3D,0x88,0x62,0x64,0x41,0x55,0x55,0xDE,0xF0,
+    0xA5,0x49,0x03,0x31,0xE7,0xFF,0x60,0x58,0xE6,0x51,0x43,0x39,0x55,0x35,0xB9,0xB5,
+    0x0A,0x73,0x43,0x39,0x55,0xFB,0xE2,0x8B,0xC5,0x49,0x03,0x39,0x5F,0x7A,0xC8,0x80,
+    0x64,0x41,0xE2,0x30,0x2A,0x09,0x2F,0xFE,0xA8,0x6A,0x84,0x41,0x7D,0x8B,0x29,0xD5,
+    0x88,0x62,0x63,0x39,0x55,0xFE,0xF0,0xFA,0xA5,0x49,0x02,0x39,0xBD,0xB6,0xFC,0x78,
+    0x68,0x62,0x02,0x39,0xFB,0x0A,0x8B,0xF5,0x88,0x62,0xC5,0x51,0x75,0xC0,0xFE,0x55,
+    0x52,0xC5,0xC5,0x51,0x35,0xD5,0x55,0x55,0x55,0xE6,0x46,0x62,0x00,0x02,0x0D,0xB5,
+    0xB6,0xEE,0x35,0xE6,0x88,0x20,0x22,0x8D,0xB6,0xEE,0x96,0xEE,0xDF,0x7F,0x6F,0x7F,
+    0xB6,0xF6,0x96,0xEE,0xED,0xED,0xF9,0x97,0x96,0xF6,0xB6,0xEE,0xEE,0xFA,0x7F,0xBF,
+    0xB6,0xF6,0x96,0xEE,0xAE,0xB9,0x3D,0x57,0x96,0xF6,0xB6,0xEE,0xFE,0x7E,0xF6,0xF7,
+    0xF7,0xF6,0xB6,0xEE,0x75,0xB5,0xA5,0xAD,0xF7,0xF6,0x96,0xEE,0xAA,0xAA,0xA8,0x7F,
+    0xD7,0xF6,0x96,0xEE,0xFA,0xFA,0xBA,0xDE,0xD6,0xF6,0xB6,0xEE,0xAF,0xAB,0x8F,0x2D,
+    0xD6,0xF6,0x96,0xEE,0xE8,0xF0,0xE8,0x78,0xB6,0xEE,0x75,0xE6,0x57,0xBE,0x2E,0xBA,
+    0xD6,0xF6,0x96,0xEE,0xF7,0xBF,0x2A,0x03,0xF7,0xF6,0x96,0xEE,0xF7,0xAA,0xBA,0xAC,
+    0xD7,0xF6,0xB6,0xEE,0xC0,0x60,0x78,0x08,0xF7,0xF6,0xB7,0xEE,0xF5,0xBD,0xAF,0x8A,
+    0xF7,0xF6,0xD7,0xF6,0xD5,0x35,0x0F,0x0A,0x18,0xFF,0xD7,0xF6,0xBF,0xAF,0xBB,0xAF,
+    0x18,0xFF,0xF8,0xF6,0xAB,0x7A,0x6B,0xEE,0x18,0xFF,0xF8,0xF6,0xAF,0x8B,0x0B,0xAA,
+    0x18,0xFF,0xF7,0xEE,0xA8,0xA8,0x80,0x08,0xF8,0xFE,0x18,0xF7,0x3F,0xAD,0xFD,0xF7,
+    0x18,0xFF,0xD7,0xF6,0xFF,0xFB,0xBE,0xF0,0x18,0xF7,0xD7,0xF6,0xBF,0xEB,0x8E,0xBA,
+    0x18,0xFF,0xF7,0xF6,0xBD,0xFF,0xD5,0xD5,0x37,0xF7,0xD8,0xF6,0xDF,0xBF,0xDF,0xF5,
+    0xF8,0xF6,0xD7,0xF6,0x5F,0x20,0x00,0xB8,0xF7,0xF6,0xB6,0xEE,0xAB,0x7B,0x6C,0x8A,
+    0xD7,0xF6,0x97,0xEE,0x00,0x08,0x9E,0x78,0xF8,0xF6,0xB7,0xEE,0xBF,0xF6,0xEA,0x3D,
+    0xF7,0xF6,0xB7,0xEE,0x83,0xAF,0xE5,0x7B,0xF7,0xF6,0xB7,0xEE,0xAA,0x0A,0xAA,0xB5,
+    0xF7,0xF6,0x96,0xEE,0x7F,0xEA,0x22,0x2A,0xD7,0xF6,0x75,0xE6,0x7E,0xFF,0xDE,0xB8,
+    0x96,0xEE,0x55,0xE6,0x6A,0x6A,0xF8,0xEC,0x35,0xE6,0x10,0xBD,0xFC,0x78,0x78,0x70,
+    0x34,0xE6,0x10,0xC5,0x00,0x03,0x0B,0x29,0x55,0xE6,0xF3,0xDD,0x7E,0xFE,0xFE,0xFC,
+    0x14,0xDE,0xD3,0xDD,0xE2,0x62,0x80,0xA0,0x14,0xDE,0xD3,0xDD,0xB3,0xBA,0xBE,0xDE,
+    0x14,0xDE,0xD2,0xDD,0xA3,0xA0,0x88,0xBB,0x14,0xDE,0xB2,0xD5,0xE8,0xA2,0xA2,0x88,
+    0xF3,0xDD,0xD3,0xD5,0x27,0x0E,0xB6,0x8A,0x14,0xDE,0xD3,0xDD,0xEA,0xC2,0xC8,0xD2,
+    0x87,0x6A,0x63,0x49,0xF5,0x3D,0xB7,0xDD,0x29,0x7B,0x05,0x5A,0x55,0xA0,0x88,0xBD,
+    0x88,0x62,0x64,0x49,0x77,0x7E,0xF8,0xF8,0xC6,0x51,0x63,0x41,0xF5,0x7B,0xA8,0x6B,
+    0xA5,0x49,0x43,0x41,0xE8,0xA8,0x20,0xDE,0xE6,0x51,0x23,0x39,0x55,0x5F,0xEA,0xCB,
+    0xE6,0x51,0xE2,0x30,0x2A,0x0B,0xAB,0x57,0x88,0x6A,0x02,0x31,0x80,0x0A,0xFB,0x55,
+    0xE6,0x51,0x02,0x31,0xA8,0xA0,0xFE,0x57,0xA5,0x49,0x02,0x31,0x5E,0x68,0xCB,0xCB,
+    0xA5,0x49,0x02,0x31,0x02,0x29,0x55,0x57,0xA9,0x6A,0xC1,0x28,0x02,0xAB,0xFF,0xD5,
+    0x27,0x5A,0x02,0x31,0xA8,0xFA,0xF7,0x5F,0xC5,0x49,0xE2,0x30,0x78,0x6E,0xEB,0xE2,
+    0x85,0x49,0xE2,0x30,0x0B,0xBF,0x77,0x6A,0x06,0x5A,0xE2,0x30,0x02,0xB7,0xD5,0x75,
+    0xC5,0x49,0x23,0x39,0xAC,0x5F,0x5D,0xBB,0x05,0x52,0x02,0x31,0x5F,0xB7,0xBD,0x00,
+    0xA5,0x41,0x02,0x39,0xFF,0x55,0x6E,0x88,0x84,0x49,0xE2,0x30,0x30,0xD5,0x97,0xDF,
+    0xC5,0x49,0x23,0x39,0x75,0x55,0xBF,0x23,0x87,0x62,0x22,0x39,0x55,0x55,0xDF,0xC2,
+    0x85,0x49,0xE2,0x30,0x55,0x77,0xEA,0x80,0x23,0x39,0xE2,0x30,0x2D,0x35,0x97,0x58,
+    0xA5,0x51,0xC2,0x30,0xFD,0xBE,0x2A,0x2B,0x27,0x62,0x63,0x41,0x75,0x7D,0xEA,0xA0,
+    0xA5,0x51,0x64,0x49,0xCD,0x95,0xFF,0xA0,0xA5,0x51,0x44,0x49,0xEF,0x9A,0xBA,0x3A,
+    0x07,0x62,0x64,0x49,0xFD,0x2D,0x3F,0xFF,0x48,0x6A,0x64,0x41,0x5F,0xE0,0x80,0xEA,
+    0xC5,0x51,0x23,0x39,0x57,0x7F,0xFA,0xAC,0x85,0x49,0xE3,0x30,0xA5,0x2F,0xBE,0x5F,
+    0xE6,0x59,0x23,0x39,0xAA,0x22,0xAA,0xF5,0x68,0x62,0x44,0x41,0x5F,0xF0,0xEA,0x5D,
+    0x85,0x49,0x23,0x39,0xFF,0xA8,0xA8,0xF5,0x85,0x49,0xE3,0x30,0x0D,0x2D,0xD7,0x7F,
+    0xA9,0x6A,0x44,0x41,0x0F,0x2F,0xF5,0x55,0x89,0x6A,0x03,0x31,0xFA,0xB0,0xFE,0x55,
+    0xC6,0x51,0x23,0x39,0x7A,0x62,0xEA,0xF5,0xE6,0x51,0xC2,0x30,0x0F,0xA7,0xF7,0xFE,
+    0x68,0x62,0x44,0x39,0x82,0xAF,0x55,0x55,0xE6,0x51,0xC2,0x30,0x88,0xA8,0xFF,0xD7,
+    0x85,0x49,0xC2,0x30,0x7C,0xE8,0xAE,0x23,0xC5,0x49,0xE2,0x38,0x2B,0xB5,0xF7,0x20,
+    0xE6,0x59,0x02,0x31,0x00,0xFE,0x7F,0xEE,0xE6,0x51,0xE2,0x30,0xA8,0xFF,0xF5,0xFF,
+    0x26,0x5A,0x43,0x41,0x55,0x5F,0xAF,0x0B,0x88,0x62,0x22,0x39,0xFD,0x55,0xFF,0xA0,
+    0xE5,0x51,0x03,0x39,0xB8,0x7F,0x7F,0xAA,0xA5,0x49,0x02,0x39,0xCE,0xBD,0x25,0xB7,
+    0xA8,0x6A,0x23,0x39,0x55,0x5D,0xAF,0x2F,0xA8,0x6A,0x43,0x41,0x55,0xFF,0xAE,0x00,
+    0x88,0x6A,0x64,0x41,0x55,0x55,0xFE,0xF8,0x06,0x5A,0x43,0x41,0x55,0xFF,0xAA,0xA0,
+    0x06,0x5A,0x43,0x41,0x55,0xF7,0x2E,0x0A,0x27,0x5A,0x44,0x41,0xF5,0xAF,0xAC,0xA8,
+    0xE6,0x51,0x64,0x49,0xF5,0x2E,0xAA,0x82,0x47,0x62,0xC6,0x51,0x03,0xAB,0x75,0xD5,
+    0x89,0x6A,0xE6,0x51,0xFA,0x8A,0xE1,0xED,0x88,0x6A,0x27,0x5A,0xF7,0xDD,0xED,0xAD,
+    0x88,0x6A,0xE6,0x59,0xBA,0x27,0x2C,0xBA,0x87,0x6A,0x05,0x5A,0x60,0xE0,0x42,0xA0,
+    0xE5,0x51,0x23,0x41,0x2E,0xDF,0x56,0x5C,0x87,0x6A,0x63,0x41,0xAF,0x2A,0xBD,0xD5,
+    0x47,0x62,0x84,0x49,0xBA,0xE0,0xB8,0x55,0x47,0x62,0x64,0x49,0x22,0x2A,0x2E,0x95,
+    0x87,0x6A,0x26,0x62,0xA8,0xE2,0x2E,0x59,0x87,0x6A,0x26,0x5A,0x88,0x82,0xAB,0xD5,
+    0x87,0x62,0x26,0x5A,0xE3,0xC0,0xEA,0x75,0x06,0x5A,0x03,0x39,0x7E,0x78,0xE0,0xE0,
+    0xE6,0x51,0x23,0x39,0x2D,0xBD,0x55,0x55,0x68,0x62,0x23,0x39,0xA0,0xEA,0x55,0xDD,
+    0x47,0x62,0x44,0x39,0x7F,0x57,0x5D,0x8B,0x85,0x49,0x02,0x31,0xB7,0xD7,0xDF,0x80,
+    0x06,0x52,0x23,0x39,0x0B,0xF5,0xFF,0xBF,0xC5,0x49,0x23,0x39,0xA8,0xD7,0xFF,0xBA,
+    0xA5,0x49,0x03,0x31,0x5E,0x5F,0xAA,0xA0,0x64,0x41,0x23,0x39,0xBD,0xF5,0xE2,0x40,
+    0x84,0x41,0x23,0x39,0xAA,0xFF,0x3F,0xAD,0xE6,0x51,0x43,0x39,0x55,0x77,0xEB,0x0B,
+    0xE6,0x51,0xE2,0x30,0xBF,0x5F,0x7E,0xE8,0xA5,0x49,0x02,0x39,0x00,0x8B,0xAD,0xB5,
+    0xA5,0x49,0x64,0x49,0xBE,0xB6,0x8A,0x68,0xA8,0x72,0x84,0x49,0x3D,0xF5,0xD5,0x55,
+    0x75,0xEE,0xC5,0x51,0x02,0x2D,0xB5,0xD5,0x96,0xEE,0x8F,0xAC,0x00,0x00,0x00,0x09,
+    0xB6,0xF6,0x96,0xEE,0xB7,0x3F,0xB5,0x7D,0xB6,0xF6,0x96,0xEE,0x62,0xC0,0xCB,0x4A,
+    0xB6,0xEE,0x96,0xEE,0xBD,0xAD,0xAA,0x2B,0xD7,0xF6,0x96,0xEE,0xBF,0x2F,0x0A,0x0A,
+    0xD7,0xF6,0x75,0xEE,0x00,0x88,0xA8,0x78,0xB6,0xEE,0x75,0xE6,0xA8,0xBE,0xBF,0xBF,
+    0xB6,0xEE,0x96,0xEE,0xBB,0xD9,0xEC,0x75,0xD7,0xF6,0x96,0xEE,0x07,0x0F,0xAF,0xAD,
+    0xD6,0xF6,0x96,0xEE,0x7A,0xFA,0xEA,0x6B,0xD7,0xF6,0x54,0xE6,0xA2,0xA8,0xAA,0x97,
+    0xF7,0xF6,0x96,0xEE,0x8A,0x2A,0xFA,0xF7,0xF7,0xF6,0xB6,0xEE,0x8A,0x28,0xEB,0xFF,
+    0xF7,0xF6,0xB7,0xF6,0x08,0x2E,0xBF,0x7E,0xF7,0xF6,0x96,0xEE,0x00,0x00,0x2B,0xDF,
+    0xF7,0xF6,0x96,0xEE,0x00,0x00,0x00,0x3D,0x18,0xFF,0xF7,0xF6,0x55,0x57,0x7F,0x55,
+    0x18,0xFF,0xD7,0xF6,0xEA,0xFE,0xFB,0xFE,0x18,0xF7,0xD7,0xF6,0x2A,0xAE,0xF7,0xFF,
+    0x18,0xF7,0xF7,0xF6,0x2B,0xA7,0x55,0x55,0x18,0xF7,0xD7,0xF6,0x22,0x0A,0x2E,0xFF,
+    0x18,0xF7,0xD8,0xF6,0xA8,0x88,0x2A,0xA9,0x18,0xFF,0xF8,0xF6,0x57,0xF6,0xBF,0xAF,
+    0x18,0xF7,0xF7,0xF6,0x55,0x62,0x88,0x00,0x18,0xF7,0xD7,0xEE,0xDF,0xF7,0xAE,0xA8,
+    0x18,0xF7,0xD7,0xF6,0x77,0xFF,0xAE,0xAA,0x18,0xF7,0xD7,0xF6,0xFF,0x7F,0x6E,0x7A,
+    0xF7,0xF6,0xB7,0xEE,0x78,0xEE,0xBF,0xEB,0xD7,0xF6,0x75,0xE6,0xAE,0x7C,0xE0,0x02,
+    0xD7,0xF6,0x96,0xEE,0x88,0x01,0x0D,0x37,0xD7,0xF6,0xB6,0xEE,0xA5,0xAD,0xAE,0x98,
+    0xD7,0xF6,0x96,0xEE,0x02,0xA6,0xFE,0xFC,0xD7,0xF6,0x96,0xEE,0xE0,0x88,0x02,0xAE,
+    0xD6,0xF6,0x34,0xE6,0x7A,0x7E,0x7E,0xF8,0x34,0xE6,0x71,0xCD,0x70,0x70,0x60,0x60,
+    0xF3,0xDD,0x10,0xC5,0x2F,0x3D,0xB5,0xA5,0x34,0xE6,0xD3,0xD5,0xA0,0xA2,0x8B,0x09,
+    0x14,0xDE,0xB2,0xD5,0xA8,0xAA,0x80,0xC8,0x13,0xDE,0xD2,0xD5,0xDA,0xEC,0xB8,0xBE,
+    0x13,0xDE,0xD3,0xDD,0xBD,0x2F,0xAA,0x0A,0x34,0xE6,0xF3,0xDD,0xF7,0xEA,0x6A,0xFA,
+    0xF3,0xDD,0xD3,0xD5,0x20,0x3A,0xA0,0x00,0x13,0xDE,0xD3,0xD5,0xA8,0xEF,0xFE,0xFA,
+    0x84,0x49,0x03,0x39,0xEF,0xB5,0xA7,0x26,0x67,0x62,0x43,0x41,0x55,0xFD,0x0B,0x0F,
+    0xEA,0x72,0x64,0x41,0x55,0xD5,0xA2,0x02,0xC8,0x72,0x43,0x39,0x75,0x57,0xFA,0x20,
+    0xE6,0x72,0x62,0x41,0x55,0x55,0xFA,0xA0,0x06,0x52,0x64,0x41,0xE5,0xAF,0xFE,0xEC,
+    0xC5,0x49,0xE2,0x30,0x5F,0x7A,0xAA,0x82,0x64,0x41,0xA1,0x28,0xF5,0xBF,0xFA,0xE8,
+    0xE5,0x51,0x43,0x39,0x55,0xED,0x29,0xAD,0xE9,0x6A,0x43,0x39,0xF5,0xF3,0x82,0xEF,
+    0xE5,0x51,0x43,0x39,0x7B,0xBA,0xA8,0xF8,0x85,0x41,0xE2,0x30,0xB5,0xDE,0xE8,0xEA,
+    0xA5,0x49,0x02,0x31,0xA2,0x0A,0x2D,0x95,0xA8,0x6A,0x64,0x41,0xEB,0x03,0xAF,0x55,
+    0xE6,0x51,0x02,0x31,0xEA,0xE8,0xF8,0xD7,0x85,0x41,0xE2,0x30,0x7B,0x70,0x7E,0x6B,
+    0xA5,0x49,0x02,0x31,0x0B,0x09,0xB5,0x55,0xE8,0x6A,0x23,0x39,0x82,0xAB,0xF7,0x55,
+    0x27,0x5A,0x02,0x31,0xBA,0xE8,0xFB,0x57,0x64,0x41,0xC2,0x28,0x5A,0xF8,0xF8,0xBB,
+    0xE6,0x51,0xC1,0x28,0x2B,0xAD,0xD5,0xFF,0x87,0x62,0x23,0x39,0x82,0xFF,0x55,0x55,
+    0x84,0x49,0xE2,0x30,0x00,0x08,0xFF,0xF5,0x64,0x41,0x02,0x39,0x5E,0xF0,0xE0,0x80,
+    0x85,0x49,0xE2,0x30,0x2F,0x2D,0xBF,0x8A,0xE5,0x59,0x44,0x41,0xA8,0xFF,0x5D,0xDF,
+    0xC5,0x51,0x64,0x49,0x7C,0xD5,0x75,0x3F,0xE5,0x59,0x44,0x49,0x7B,0xEB,0xBA,0xAA,
+    0x47,0x6A,0x44,0x49,0x77,0x5F,0xFE,0xA2,0xA5,0x51,0x02,0x39,0xAA,0x6B,0xCB,0xAA,
+    0x64,0x41,0xC1,0x30,0xEE,0x95,0xFF,0xFC,0xC5,0x51,0xE2,0x30,0x7D,0xEF,0x2B,0x0B,
+    0xEA,0x72,0xE2,0x38,0x55,0xFF,0xFE,0x82,0xC6,0x51,0x23,0x39,0x55,0x5E,0xEA,0xA8,
+    0x85,0x41,0xE2,0x30,0x95,0x35,0x1E,0x7A,0xA8,0x6A,0x44,0x41,0x55,0xBF,0x2D,0xB9,
+    0x6A,0x83,0x23,0x39,0x55,0x7F,0xE2,0x82,0xA5,0x49,0x03,0x39,0x5F,0xFA,0xA0,0x80,
+    0xA5,0x49,0xE2,0x30,0x25,0xA5,0xBE,0x7E,0x27,0x5A,0x84,0x41,0x27,0x0F,0x2B,0x75,
+    0x68,0x62,0x84,0x41,0x77,0x7C,0xFA,0x7E,0xA5,0x49,0x03,0x39,0x56,0xE0,0x88,0xAE,
+    0xE6,0x51,0x03,0x39,0xBD,0x37,0xB5,0x57,0x88,0x6A,0x23,0x39,0x8A,0xAA,0xEF,0x75,
+    0x06,0x5A,0x63,0x41,0xFE,0xEC,0xFA,0xD5,0xA4,0x49,0x03,0x39,0x7C,0x7C,0xEA,0xAA,
+    0x06,0x5A,0x02,0x31,0x09,0x0D,0xD5,0x55,0xC9,0x6A,0x22,0x39,0xE2,0x8A,0xDF,0xD5,
+    0xC5,0x51,0x63,0x39,0xB8,0xE0,0x7A,0xBF,0xA5,0x49,0xE2,0x30,0xFC,0x52,0xEA,0x00,
+    0x26,0x5A,0x03,0x31,0x2B,0xBD,0xFD,0xA2,0x88,0x6A,0x43,0x39,0x00,0xFF,0x75,0xFF,
+    0x88,0x6A,0x43,0x41,0xA8,0xFF,0x55,0x7F,0xE6,0x51,0xE3,0x38,0x00,0xFA,0x55,0xF7,
+    0x06,0x5A,0x44,0x41,0x88,0xFF,0xFD,0x2F,0x87,0x62,0xA4,0x49,0x5F,0x55,0xFD,0x00,
+    0x46,0x5A,0x64,0x41,0x6F,0x57,0xFA,0xE0,0xC6,0x51,0x64,0x41,0xFE,0x7D,0xBB,0x82,
+    0x26,0x5A,0x64,0x41,0x0B,0x2D,0xAF,0xBF,0x68,0x62,0xC5,0x51,0x82,0x8A,0xA8,0xE5,
+    0x67,0x62,0x63,0x41,0x08,0xAA,0xFF,0xD5,0x67,0x6A,0xC5,0x51,0xA0,0xDF,0xBD,0x35,
+    0x67,0x6A,0x43,0x41,0x7A,0x7A,0xEA,0xE8,0xC5,0x51,0xE2,0x38,0xB7,0xB7,0xFA,0xF0,
+    0xE5,0x59,0x43,0x41,0xD7,0xF9,0x2B,0xA5,0x88,0x6A,0x64,0x49,0xD5,0xDF,0xC2,0xAA,
+    0x26,0x62,0xA5,0x49,0x8A,0xEB,0xBA,0x5E,0xE5,0x51,0x03,0x39,0x8A,0xAE,0xDE,0xDE,
+    0x26,0x5A,0x43,0x41,0xAF,0x3F,0x2F,0xF5,0x68,0x62,0x84,0x49,0x7F,0xFE,0xF8,0xDD,
+    0xE6,0x51,0x43,0x41,0x5F,0x78,0x40,0x5B,0x64,0x41,0x03,0x39,0x03,0x3D,0x55,0x5E,
+    0x0A,0x7B,0x23,0x39,0x8B,0xAF,0xFD,0x55,0x47,0x5A,0x23,0x39,0xBE,0xA8,0xFE,0x55,
+    0xE5,0x51,0x03,0x39,0x8A,0xAA,0xFA,0x57,0xA5,0x49,0x03,0x39,0x00,0xAC,0xFF,0x55,
+    0xA5,0x49,0x03,0x39,0x88,0xBE,0x76,0x55,0x85,0x49,0x03,0x39,0xE8,0xF8,0x55,0x55,
+    0x43,0x39,0xE3,0x38,0x8E,0xAA,0xEA,0xFD,0xE6,0x51,0xE2,0x38,0x0A,0xBF,0xF5,0x5D,
+    0xE6,0x51,0xE2,0x38,0xA8,0xFE,0x5F,0xF5,0x64,0x41,0x02,0x39,0xFC,0x7A,0x7B,0xFA,
+    0x64,0x49,0x02,0x39,0xA8,0xFD,0x7D,0xFE,0x64,0x49,0x02,0x39,0x08,0xFF,0xAF,0xAD,
+    0xA6,0x51,0x02,0x39,0x28,0xB9,0xBD,0x2F,0x54,0xE6,0x06,0x5A,0x29,0xB5,0xD5,0xD5,
+    0x96,0xEE,0xCE,0xB4,0x00,0x00,0x03,0x09,0xB6,0xF6,0x96,0xEE,0xAA,0xEE,0xAA,0x0E,
+    0xF7,0xF6,0x96,0xEE,0xF7,0xBF,0xBD,0x2B,0xD7,0xF6,0x96,0xEE,0x00,0xE0,0x68,0x70,
+    0xB6,0xF6,0x76,0xEE,0x7A,0x7F,0xD6,0x75,0xB6,0xEE,0x76,0xEE,0xBD,0xAD,0x3D,0xAD,
+    0xB6,0xEE,0x96,0xEE,0xDD,0xB5,0xE7,0x77,0xD7,0xF6,0x96,0xEE,0xEF,0xFB,0x69,0xE9,
+    0x96,0xEE,0xF4,0xDD,0x80,0x80,0xF0,0x70,0x76,0xE6,0xF4,0xDD,0x3E,0xBD,0x3D,0xAD,
+    0xB6,0xEE,0x55,0xE6,0x0A,0x2F,0xA9,0xB7,0xD7,0xF6,0x75,0xE6,0x0E,0x2B,0xFB,0xFF,
+    0xD6,0xF6,0x96,0xEE,0x20,0x22,0xAF,0xFD,0xF8,0xFE,0x75,0xE6,0x5E,0xAA,0x82,0x0A,
+    0xF8,0xF6,0x55,0xE6,0xFF,0x5F,0xE0,0xA0,0xD7,0xF6,0x34,0xDE,0x22,0xEF,0x5F,0xF8,
+    0xD7,0xF6,0x34,0xDE,0x00,0x02,0xE7,0x55,0xF7,0xF6,0x54,0xE6,0x00,0x00,0x2A,0xB5,
+    0x38,0xF7,0xD7,0xF6,0x57,0x7F,0xFF,0xB5,0xF7,0xF6,0xD7,0xF6,0xBF,0xAB,0xB0,0x20,
+    0xF8,0xF6,0xD7,0xF6,0x75,0x4E,0x88,0x80,0x18,0xF7,0xD7,0xF6,0x27,0x5D,0x57,0xEB,
+    0x18,0xF7,0xD7,0xF6,0x82,0xFF,0xD5,0xD7,0x18,0xF7,0xD7,0xEE,0x28,0xA8,0xEF,0xE7,
+    0x18,0xF7,0xD7,0xF6,0x8A,0x02,0xA2,0x7B,0x18,0xF7,0xB7,0xF6,0xE0,0xAA,0xAA,0xA2,
+    0xF8,0xFE,0xD7,0xEE,0x7A,0xEA,0xEA,0x7A,0xF7,0xF6,0xB7,0xEE,0xB7,0x7F,0xBF,0x82,
+    0xD7,0xF6,0x96,0xEE,0x5E,0x62,0x8A,0x00,0xD7,0xF6,0x75,0xE6,0x22,0xA9,0x2F,0x9F,
+    0xD7,0xF6,0xB7,0xEE,0x62,0x0B,0xA7,0xEB,0xD7,0xF6,0x76,0xEE,0xAE,0xBE,0xFE,0x78,
+    0xD7,0xF6,0x75,0xE6,0x70,0x73,0xFF,0xEA,0x96,0xEE,0xD2,0xD5,0x7E,0x5A,0x7A,0x6A,
+    0x92,0xCD,0x30,0xC5,0xA5,0xD6,0xBC,0xAC,0x34,0xE6,0x91,0xCD,0x09,0x2D,0xAD,0x35,
+    0x14,0xE6,0xF3,0xD5,0xF8,0xFC,0x7E,0xFA,0x14,0xDE,0xD2,0xDD,0xAF,0xAB,0x8A,0x0A,
+    0x34,0xE6,0xF3,0xDD,0x27,0x2F,0xAB,0x8A,0x33,0xE6,0xF3,0xDD,0x7A,0x7E,0x7E,0x7C,
+    0x15,0xE6,0xF3,0xD5,0xFF,0xBF,0x9F,0xB7,0x14,0xDE,0xF3,0xDD,0x9F,0x9E,0xB8,0xB4,
+    0x25,0x5A,0x43,0x41,0x55,0x5E,0x5E,0x68,0x27,0x5A,0x23,0x39,0x0B,0xAA,0xDD,0xF5,
+    0xA9,0x6A,0x64,0x41,0x0A,0xEF,0x75,0x55,0x87,0x6A,0x43,0x41,0xA0,0xFB,0x55,0x77,
+    0x45,0x5A,0x22,0x39,0x28,0xFF,0x5F,0x57,0xE5,0x51,0x43,0x39,0xA8,0xDF,0xD5,0xF5,
+    0xA5,0x49,0x03,0x39,0x88,0xFC,0xDE,0xFA,0xA5,0x49,0x02,0x31,0x62,0x8B,0x0B,0x02,
+    0xC5,0x49,0xE2,0x30,0xED,0xF7,0xAA,0xA0,0xA5,0x49,0x02,0x31,0x8F,0x5F,0x6A,0x2A,
+    0x43,0x41,0xC1,0x28,0xAA,0xF5,0xB7,0xBC,0x84,0x41,0x23,0x39,0x05,0xA5,0x7A,0xA2,
+    0xA9,0x6A,0xE2,0x30,0x55,0xFF,0xEA,0x02,0xC6,0x49,0x23,0x39,0x5D,0x7F,0xA9,0x80,
+    0x64,0x41,0xC1,0x28,0x95,0x9F,0xBA,0xE8,0xC5,0x49,0x03,0x31,0xF7,0xAA,0x2B,0x0D,
+    0xEA,0x72,0x43,0x39,0x55,0xFF,0x8B,0xAB,0x27,0x5A,0x43,0x41,0x55,0xF5,0xBE,0xE0,
+    0xC5,0x49,0xE2,0x30,0xD5,0x56,0x7E,0x78,0x85,0x41,0xE2,0x30,0xAA,0x2B,0x09,0x2F,
+    0xA9,0x6A,0x64,0x41,0x57,0x83,0x8B,0xF7,0xE6,0x51,0x23,0x39,0xF5,0xAE,0xA8,0xEE,
+    0xA5,0x49,0xE2,0x30,0xD7,0x7A,0xE0,0xA2,0xA4,0x49,0xE2,0x30,0xAA,0x2B,0x2D,0xD5,
+    0xA9,0x6A,0x44,0x41,0xAB,0x8B,0xEF,0x55,0xC6,0x51,0x43,0x49,0xFA,0xFC,0xFC,0xFF,
+    0xA5,0x51,0x64,0x51,0x2E,0x2A,0x2B,0xC9,0xE6,0x61,0x84,0x51,0xFA,0xED,0xCF,0x82,
+    0x27,0x6A,0xA4,0x59,0xC3,0xFD,0xD5,0xF5,0xA5,0x59,0x23,0x41,0xE8,0xF8,0x7C,0xF8,
+    0x84,0x49,0xE2,0x38,0x7E,0x78,0xEA,0x20,0xA5,0x49,0xE2,0x30,0x01,0xAD,0xD7,0xBA,
+    0x68,0x62,0x44,0x41,0x02,0xFF,0x5D,0xDD,0x48,0x62,0x23,0x39,0xFC,0x57,0x77,0xFF,
+    0xA5,0x49,0xE2,0x30,0x7A,0xEE,0xAA,0x00,0xC6,0x51,0x03,0x31,0x0F,0x55,0xBF,0xAA,
+    0x06,0x52,0x43,0x41,0x80,0xDD,0xBF,0xEE,0xC5,0x49,0x23,0x39,0xFA,0x7E,0xEA,0x0A,
+    0xA5,0x49,0x02,0x31,0x7A,0xA2,0x02,0x00,0xC5,0x49,0x23,0x39,0xF5,0xBD,0x2A,0xAA,
+    0xE6,0x51,0x43,0x39,0xF7,0xDB,0xA0,0xAA,0xC6,0x49,0x44,0x41,0x95,0xAF,0x2A,0xAA,
+    0xC6,0x51,0x02,0x39,0x5E,0x70,0xE0,0xA8,0x84,0x49,0xE1,0x30,0xAD,0x2F,0x3F,0xF6,
+    0x26,0x5A,0x44,0x41,0xBF,0x2B,0xBF,0xB5,0x87,0x62,0xA4,0x49,0x7D,0x82,0xA0,0xD5,
+    0xE5,0x51,0x22,0x31,0x58,0xE8,0xEC,0xBE,0x85,0x41,0x23,0x39,0x2D,0xBD,0xD6,0x7E,
+    0xE5,0x51,0x43,0x39,0x00,0x8A,0xAA,0xDD,0x06,0x52,0x84,0x41,0x00,0x0A,0x9F,0xF5,
+    0x88,0x62,0x43,0x39,0x02,0x82,0xF7,0xD7,0x06,0x52,0x64,0x41,0xC0,0xB0,0xFF,0x55,
+    0xE6,0x51,0x43,0x39,0x80,0xA8,0xBB,0xD7,0xA5,0x49,0x03,0x31,0x5C,0xF8,0x6A,0xFF,
+    0xE5,0x51,0x03,0x31,0x2F,0xBD,0xF5,0x57,0x47,0x62,0x03,0x31,0x02,0xAB,0xFF,0x55,
+    0x66,0x62,0x03,0x31,0xE8,0xFE,0xFF,0x55,0xA5,0x49,0xE2,0x30,0x00,0x88,0xEA,0x7D,
+    0xC5,0x49,0xE2,0x30,0x22,0x8A,0xFF,0x55,0xC5,0x51,0x22,0x39,0x0A,0x2A,0xED,0xD5,
+    0x46,0x5A,0xE2,0x30,0xF7,0x5E,0x7A,0xC2,0xE6,0x51,0xE2,0x30,0x02,0xBF,0xD5,0x57,
+    0x46,0x62,0x02,0x39,0xA0,0xFF,0x55,0x55,0xC5,0x51,0x02,0x39,0x78,0xFA,0x95,0xB5,
+    0xE6,0x59,0x02,0x39,0xF5,0x5F,0x5E,0x60,0xA5,0x51,0x02,0x39,0x00,0x7D,0x55,0xD7,
+    0xA5,0x49,0x03,0x39,0xC8,0xDF,0xDD,0x2B,0x06,0x5A,0x43,0x41,0x75,0xE5,0x0F,0x0A,
+    0x06,0x5A,0x03,0x39,0xF5,0xF7,0xFA,0xA0,0xA4,0x49,0x03,0x39,0xFF,0xFF,0xFD,0xA0,
+    0xC5,0x51,0x02,0x39,0x75,0x75,0xFD,0x02,0xC5,0x51,0xE3,0x38,0x5F,0xDF,0xFF,0x00,
+    0xE5,0x51,0xE2,0x30,0xFD,0xFD,0xB7,0x02,0x07,0x5A,0xE2,0x30,0x57,0x7D,0xEB,0x02,
+    0x27,0x5A,0x23,0x39,0x55,0x55,0xDF,0x08,0x06,0x5A,0x02,0x39,0x55,0xD5,0xBA,0x00,
+    0x06,0x62,0x03,0x39,0x55,0x7E,0xAA,0x00,0x67,0x62,0x03,0x39,0x75,0x7D,0xAA,0x88,
+    0x06,0x5A,0x43,0x41,0x55,0xF5,0x20,0x20,0x47,0x62,0x43,0x41,0x55,0xF7,0xA2,0x80,
+    0x47,0x62,0x23,0x39,0xD5,0xBF,0x00,0x02,0x27,0x62,0x44,0x41,0x55,0x8A,0x00,0x00,
+    0x48,0x6A,0x64,0x49,0x55,0xEA,0xA0,0x2A,0x48,0x6A,0xA5,0x51,0x55,0xAA,0x0A,0x88,
+    0x0A,0x83,0xC6,0x51,0xD5,0xBF,0xAF,0x2B,0x92,0xD5,0x47,0x62,0xD5,0xBF,0x2F,0x2B,
+    0x75,0xEE,0x0F,0xC5,0x09,0x0B,0x02,0x02,0xD7,0xF6,0x96,0xF6,0xED,0xAF,0xBF,0x0B,
+    0xD7,0xF6,0xB6,0xEE,0xC3,0xC2,0xE0,0xC0,0xB6,0xF6,0x76,0xEE,0xE0,0xE8,0xBA,0xB8,
+    0x96,0xF6,0x75,0xE6,0xBE,0xDE,0xDA,0x6A,0x96,0xEE,0x55,0xEE,0x0B,0x0B,0xAB,0x6B,
+    0x96,0xEE,0x34,0xE6,0x88,0xA8,0x7E,0xD7,0xB6,0xEE,0x55,0xE6,0x8B,0xFF,0xD5,0x55,
+    0x76,0xEE,0xB3,0xD5,0xF0,0xF8,0x7E,0xFE,0x55,0xE6,0xF4,0xDD,0x29,0xED,0xB7,0x0F,
+    0x75,0xE6,0xD3,0xD5,0x28,0xAE,0x7A,0xAA,0x75,0xEE,0x71,0xCD,0x00,0x0A,0xFF,0x7B,
+    0x96,0xEE,0x51,0xC5,0x00,0x22,0xAA,0xDD,0x18,0xFF,0xF3,0xDD,0x0A,0x2A,0xBF,0xF5,
+    0x18,0xFF,0x95,0xE6,0xE8,0x80,0xAB,0xFD,0xB7,0xF6,0xD6,0xEE,0xBA,0xAA,0xBB,0xAB,
+    0xD7,0xF6,0x55,0xE6,0x5F,0xE0,0x82,0x8A,0xB6,0xEE,0x35,0xDE,0xD5,0xFF,0xEC,0xA0,
+    0xD7,0xF6,0x35,0xDE,0x2B,0xD5,0x5F,0xEE,0x18,0xF7,0x35,0xE6,0x0A,0x2A,0xAF,0xD5,
+    0x18,0xFF,0x96,0xEE,0x2A,0x20,0x0B,0xAD,0x18,0xFF,0xD7,0xF6,0xA8,0xEE,0x7A,0xE8,
+    0x18,0xF7,0xD7,0xF6,0x8E,0x8A,0x8B,0xDF,0x18,0xFF,0xD7,0xF6,0xFE,0xEA,0xBA,0x7F,
+    0x18,0xF7,0xD7,0xEE,0x5F,0x5E,0xF0,0xE2,0xD7,0xF6,0xF7,0xEE,0xA8,0xA8,0x02,0x22,
+    0xD7,0xF6,0xB7,0xEE,0xC8,0xEC,0x8A,0x80,0xD7,0xF6,0xB7,0xEE,0x00,0x7E,0x6B,0xAA,
+    0xF7,0xF6,0xB7,0xEE,0xEA,0xAF,0xBD,0xA7,0xF7,0xF6,0x55,0xE6,0xDA,0x60,0xE8,0xA2,
+    0xD7,0xF6,0x55,0xE6,0x82,0x0B,0x09,0x35,0xD7,0xF6,0x55,0xE6,0x78,0xFA,0x78,0x68,
+    0xB6,0xEE,0x55,0xE6,0x0B,0x0F,0xBF,0xF5,0x75,0xEE,0xD2,0xD5,0x68,0x68,0x60,0xC0,
+    0xD3,0xDD,0x51,0xCD,0xD6,0xEE,0xBE,0xFC,0xF3,0xDD,0x71,0xCD,0x3F,0xBD,0xBD,0xBF,
+    0x14,0xDE,0xF3,0xDD,0x34,0xF0,0xE2,0x81,0x14,0xDE,0xF3,0xDD,0xAF,0xEF,0xB7,0x03,
+    0x34,0xE6,0xF4,0xDD,0x0B,0x83,0xAB,0xEA,0x34,0xE6,0xF3,0xDD,0x78,0x7A,0xFF,0xFF,
+    0x14,0xDE,0xF3,0xDD,0xCF,0x5F,0xD7,0xF5,0x14,0xDE,0xD3,0xD5,0x8E,0xA7,0xAA,0x8A,
+    0x25,0x5A,0x63,0x41,0x78,0xE2,0x80,0x8A,0xA4,0x49,0x02,0x39,0x3F,0xAF,0x2B,0x9E,
+    0x68,0x62,0x63,0x41,0xBF,0x0F,0x2F,0xFD,0x88,0x62,0x43,0x41,0xBA,0x00,0x88,0x7F,
+    0x27,0x5A,0x64,0x41,0x57,0xF8,0xE8,0x7F,0xC5,0x51,0x63,0x41,0xFF,0x83,0xA8,0x5F,
+    0xC5,0x49,0x64,0x41,0x6A,0x0A,0x0A,0xD5,0xC5,0x49,0x43,0x39,0x2A,0xA8,0xE8,0x57,
+    0xC5,0x49,0x23,0x39,0xA8,0x22,0xAB,0xF5,0xA5,0x49,0x02,0x31,0x2A,0xAA,0xFB,0x57,
+    0xC5,0x49,0x02,0x31,0x7E,0xE3,0xA9,0x2D,0xA5,0x49,0x23,0x39,0x2B,0x35,0xF5,0xAB,
+    0xA8,0x62,0x84,0x41,0xA9,0x55,0x55,0x0D,0xA8,0x62,0x43,0x39,0xFE,0x75,0x57,0xE0,
+    0x84,0x41,0x02,0x31,0x78,0x7D,0x57,0x70,0xA5,0x41,0xE2,0x28,0xAD,0xF5,0xBF,0x2F,
+    0xC5,0x49,0x23,0x39,0xE2,0xFD,0xBF,0xA8,0xA8,0x6A,0x43,0x39,0x7F,0xD5,0xAB,0x82,
+    0xE6,0x51,0x23,0x31,0x76,0xDF,0xBE,0xF8,0xC6,0x51,0xC2,0x30,0xD7,0xD6,0xF8,0x68,
+    0x84,0x49,0x23,0x39,0xDF,0xAF,0x03,0xAD,0x84,0x41,0x43,0x41,0xFB,0xCE,0x08,0x02,
+    0x84,0x49,0x23,0x39,0xB5,0x3F,0x2F,0x8E,0xA5,0x49,0x03,0x39,0xD7,0xBA,0xA8,0xAE,
+    0xA5,0x51,0x23,0x41,0xD5,0xFB,0xFA,0x9F,0x84,0x51,0x44,0x49,0xAD,0x9E,0x3A,0x95,
+    0x06,0x62,0x43,0x49,0xAF,0x29,0x3F,0xBF,0xE5,0x69,0xC5,0x61,0xEF,0x6B,0x39,0x77,
+    0xE5,0x61,0xA4,0x59,0xE8,0x60,0xE0,0xEC,0xC5,0x59,0x64,0x51,0xBB,0xB2,0xE2,0x7A,
+    0xA5,0x51,0x44,0x49,0x22,0xBE,0x97,0x7F,0xA5,0x49,0x24,0x41,0xA8,0xBA,0xFE,0x55,
+    0x85,0x49,0x24,0x41,0x02,0x3E,0x2F,0xF7,0xA5,0x49,0x44,0x41,0x82,0xEB,0xFF,0x95,
+    0xA5,0x49,0x24,0x39,0x20,0xE2,0xCE,0x7F,0xA5,0x49,0x23,0x39,0x02,0xBA,0x2B,0x5F,
+    0x85,0x41,0x03,0x39,0x00,0xA8,0xF8,0x77,0x85,0x49,0x03,0x39,0xA0,0x2A,0xAA,0x55,
+    0xA5,0x49,0x03,0x39,0xA2,0xEF,0xEF,0x75,0x84,0x41,0xC2,0x30,0x00,0xA0,0xBA,0x57,
+    0x84,0x49,0xE2,0x30,0x00,0x2A,0xAF,0x55,0xA5,0x49,0xE2,0x30,0x0A,0xAA,0xFB,0x55,
+    0xA4,0x49,0xE2,0x30,0x0A,0xAA,0xF7,0x55,0x64,0x41,0xC2,0x30,0xF8,0x6B,0xEB,0x0B,
+    0x84,0x41,0xE2,0x30,0x03,0xAD,0x55,0x55,0x63,0x41,0xC2,0x30,0x00,0xA8,0xD7,0xFD,
+    0x64,0x41,0xC1,0x30,0x00,0xBF,0xDF,0xFF,0xC5,0x51,0x22,0x39,0x7F,0xFD,0xB5,0x05,
+    0xA5,0x49,0x02,0x31,0xBF,0x55,0x57,0x5C,0x64,0x41,0x02,0x31,0x28,0x5D,0x55,0xFD,
+    0x84,0x41,0x02,0x31,0x7F,0x55,0x5D,0x8F,0x64,0x41,0xC2,0x28,0xBA,0xF5,0xFF,0x28,
+    0x64,0x41,0xE2,0x30,0xFB,0x5F,0x7F,0x02,0xE5,0x51,0x02,0x31,0xD5,0xB5,0xB5,0x0A,
+    0x06,0x5A,0x02,0x31,0x5F,0x5E,0xF0,0x80,0xC6,0x51,0xC2,0x30,0x75,0xD5,0xBB,0x00,
+    0xE7,0x59,0x03,0x31,0x55,0x55,0xFF,0x80,0xE6,0x59,0xE2,0x30,0x55,0x55,0xAF,0x00,
+    0xE6,0x59,0x03,0x31,0x55,0x55,0x3B,0x00,0x26,0x5A,0x23,0x39,0x55,0xF5,0xAA,0x08,
+    0x67,0x62,0xC5,0x51,0x43,0xE9,0xFD,0xBA,0x06,0x5A,0x03,0x39,0x57,0xFA,0x88,0x00,
+    0x06,0x5A,0x24,0x41,0x55,0xBA,0x08,0x02,0x26,0x62,0x23,0x41,0xFD,0xAA,0x02,0x8A,
+    0x27,0x62,0xC5,0x51,0x43,0x6A,0xA8,0xAA,0x27,0x62,0xA5,0x51,0x55,0xA3,0x28,0xA8,
+    0x26,0x62,0xA4,0x51,0xBD,0xA8,0x22,0x8A,0x47,0x62,0xC5,0x51,0x7F,0xAE,0x2A,0xDF,
+    0x26,0x62,0xA5,0x51,0x22,0x2A,0xA8,0xBD,0x26,0x62,0xC5,0x51,0xDA,0xA2,0xAA,0x6F,
+    0x27,0x62,0xC5,0x51,0x2F,0xBE,0x2A,0xF6,0x27,0x62,0xA5,0x51,0xA8,0x08,0x0A,0x97,
+    0x27,0x62,0xC4,0x51,0xEA,0xA2,0xFC,0xD7,0x47,0x62,0xA4,0x51,0x8B,0x8A,0xDF,0xBF,
+    0xA8,0x72,0xC6,0x51,0xEF,0xEF,0x57,0x3B,0xA8,0x72,0x85,0x51,0xAA,0xFB,0xD7,0x00,
+    0x29,0x83,0xE5,0x59,0x5D,0x55,0x55,0x0B,0x8B,0x8B,0xA4,0x51,0xF7,0x75,0xFD,0x00,
+    0x4D,0xA4,0x05,0x5A,0x55,0x55,0x55,0x02,0xCF,0xB4,0xE5,0x59,0x55,0x55,0xDD,0x00,
+    0x30,0xBD,0xE5,0x59,0x55,0x55,0xFF,0x00,0x71,0xC5,0x05,0x5A,0x55,0x55,0xEF,0x00,
+    0xB3,0xD5,0x07,0x62,0x55,0x55,0xAB,0x00,0x14,0xDE,0x47,0x62,0x55,0x55,0xAA,0x00,
+    0x34,0xE6,0x87,0x6A,0xD5,0xBD,0x22,0x00,0x55,0xE6,0x4D,0xAC,0xBD,0x2B,0x00,0x00,
+    0xD7,0xF6,0x35,0xE6,0xAD,0xAD,0xAB,0x0B,0xF8,0xFE,0xB7,0xF6,0xBD,0xEF,0x6B,0x7A,
+    0xD6,0xF6,0x96,0xEE,0xEC,0xF7,0xBF,0x7B,0xB6,0xF6,0x76,0xEE,0xFA,0xBA,0x7A,0x7E,
+    0x96,0xEE,0x75,0xEE,0x58,0xFF,0xED,0x7F,0x76,0xEE,0xF3,0xDD,0xC2,0xE8,0x78,0x7A,
+    0x34,0xE6,0xD3,0xD5,0x2E,0xBD,0xBD,0xA5,0x75,0xEE,0x14,0xDE,0xAF,0xEF,0xAD,0x2B,
+    0x96,0xEE,0xF3,0xDD,0xF7,0x9F,0xBF,0x22,0x96,0xEE,0x34,0xE6,0x7D,0xFB,0xA2,0x80,
+    0x75,0xEE,0x35,0xE6,0xE9,0x0B,0x02,0x0A,0x96,0xEE,0x14,0xDE,0x7F,0xA8,0x00,0x0A,
+    0x96,0xEE,0x51,0xCD,0x57,0xA0,0x00,0x00,0x96,0xEE,0x10,0xC5,0xBD,0x57,0xE0,0x00,
+    0x96,0xEE,0x71,0xC5,0x0A,0xBD,0xD5,0x5E,0xB6,0xEE,0x92,0xCD,0x00,0x0A,0xAF,0xFD,
+    0xD7,0xF6,0x55,0xE6,0xAA,0xA2,0x0B,0xF5,0xD7,0xF6,0x96,0xEE,0x4B,0x2B,0x2B,0x2B,
+    0xD7,0xF6,0x96,0xEE,0x55,0xBF,0x20,0x00,0xD7,0xF6,0xD3,0xD5,0xFA,0x78,0x60,0xA0,
+    0xB6,0xEE,0x72,0xCD,0x02,0x0B,0xA5,0xD5,0x18,0xF7,0x55,0xE6,0x02,0x0A,0xBB,0xB5,
+    0x18,0xFF,0xD8,0xF6,0xFE,0xEE,0xA2,0x0B,0x18,0xFF,0xD7,0xF6,0xFD,0xEF,0xBA,0xAA,
+    0x18,0xF7,0xF7,0xF6,0xF9,0x77,0xFD,0xF7,0x18,0xF7,0xD7,0xEE,0xFA,0xBA,0xAF,0xBA,
+    0xF7,0xF6,0xB6,0xEE,0xF2,0xFA,0xFC,0xE0,0xB7,0xF6,0xF7,0xEE,0xAF,0xEB,0xAA,0xAB,
+    0xF7,0xF6,0x96,0xEE,0xFF,0xFE,0xFA,0x6A,0xD7,0xF6,0x96,0xEE,0xE0,0x8B,0xEB,0xEF,
+    0xB6,0xEE,0x14,0xDE,0x2F,0x36,0xDE,0x7E,0xD7,0xF6,0x55,0xE6,0x78,0xEA,0xEA,0xEB,
+    0x96,0xEE,0x34,0xE6,0x2D,0x8F,0xBE,0xB7,0x96,0xEE,0x14,0xDE,0x60,0x40,0x62,0xE8,
+    0xF3,0xDD,0x72,0xCD,0xDE,0x7E,0x5C,0x5C,0xB2,0xD5,0x72,0xCD,0x3E,0xBF,0xF7,0xF5,
+    0x14,0xDE,0xD3,0xD5,0x8B,0x0D,0xA9,0x29,0x34,0xE6,0xF4,0xDD,0xA7,0xBF,0xEA,0xAB,
+    0x34,0xE6,0x14,0xDE,0x70,0x80,0x2E,0x2F,0x34,0xE6,0xF4,0xDD,0xDE,0xFA,0xF8,0xFF,
+    0x14,0xDE,0xD3,0xD5,0xFE,0xBA,0x6E,0xF2,0x34,0xE6,0xF4,0xDD,0xF5,0xBD,0x2D,0x3F,
+    0x46,0x62,0xC5,0x51,0x7F,0xF6,0xD6,0xFC,0x05,0x52,0x23,0x39,0xDE,0x7A,0x60,0x60,
+    0xC5,0x49,0x22,0x39,0xEF,0xED,0xE9,0x35,0x27,0x62,0x43,0x41,0x55,0xBD,0x03,0x0B,
+    0x88,0x6A,0x63,0x41,0x55,0xFF,0x80,0xEA,0xC5,0x49,0x43,0x41,0x55,0xAA,0xA8,0xE8,
+    0xC4,0x49,0x42,0x39,0xFD,0x2A,0xAA,0xFB,0xA4,0x49,0x43,0x39,0xDA,0x28,0xAA,0xEF,
+    0xA4,0x49,0x64,0x41,0xAE,0x28,0xFC,0x59,0xA5,0x49,0x43,0x39,0x6B,0xF0,0xFA,0x7B,
+    0x84,0x41,0x23,0x39,0xBD,0xFA,0xCA,0xAA,0xA5,0x49,0x02,0x31,0x22,0x03,0x2D,0xE5,
+    0xCA,0x8B,0xA4,0x49,0x0D,0xB5,0x55,0x55,0xEC,0x8B,0x63,0x41,0xE0,0xEA,0x57,0x55,
+    0xA5,0x49,0x03,0x31,0x60,0xE0,0xC8,0xEE,0x44,0x31,0xA1,0x28,0x2B,0xFE,0xDE,0x5F,
+    0x84,0x41,0xC1,0x28,0x28,0xAA,0xAB,0xAD,0x26,0x5A,0x02,0x31,0x02,0xFF,0xFF,0x75,
+    0xC5,0x49,0x02,0x39,0xB8,0xFE,0xFB,0x55,0xE6,0x51,0x03,0x39,0x72,0xE3,0xEF,0x55,
+    0x44,0x41,0xC1,0x30,0x0B,0x8F,0xF8,0x58,0xA4,0x49,0xE1,0x30,0xA2,0xBA,0xFF,0x55,
+    0x84,0x49,0xE2,0x30,0x28,0xF8,0xFF,0x55,0x64,0x41,0xC1,0x30,0x00,0x82,0xFB,0x55,
+    0x64,0x49,0xC1,0x30,0x00,0x00,0xFF,0x55,0x84,0x51,0x02,0x39,0x3A,0x0E,0x2D,0x05,
+    0x26,0x6A,0x84,0x59,0xFD,0xBF,0x2B,0xAB,0x47,0x72,0xC5,0x61,0xF5,0xBF,0xF8,0xEA,
+    0x26,0x72,0xE5,0x61,0x73,0x5C,0xBE,0xEA,0x05,0x6A,0x64,0x51,0x7E,0x7E,0x58,0x60,
+    0x85,0x59,0x04,0x41,0xFA,0x7E,0x58,0x7A,0x04,0x41,0xA2,0x30,0x00,0xFA,0x5E,0x80,
+    0x24,0x41,0xA2,0x30,0x3E,0x7F,0x7F,0x0B,0x24,0x41,0xA2,0x28,0xAC,0x7F,0x7F,0x02,
+    0x44,0x41,0xA2,0x28,0xEB,0x5D,0xFB,0x20,0x85,0x49,0xC2,0x30,0x55,0x55,0xDD,0x20,
+    0x85,0x49,0xC3,0x30,0x75,0x55,0xFF,0x00,0xA5,0x51,0xE2,0x30,0x55,0x55,0xF7,0x00,
+    0x27,0x5A,0xE3,0x38,0x55,0xD5,0xF7,0xA8,0x07,0x5A,0xA2,0x28,0x55,0x5F,0xAE,0x02,
+    0x07,0x5A,0xC2,0x30,0x55,0x7F,0xAB,0x20,0x06,0x5A,0xC2,0x30,0x55,0xFD,0xBA,0x00,
+    0x27,0x5A,0xE2,0x30,0x55,0xFF,0xAA,0x02,0x06,0x5A,0x03,0x39,0xAD,0xAF,0x20,0x00,
+    0x67,0x62,0x23,0x39,0x57,0xFF,0xAA,0xA2,0x27,0x5A,0x23,0x39,0x55,0xAB,0x08,0x80,
+    0x06,0x5A,0x43,0x41,0xD5,0x2B,0x00,0x00,0x46,0x62,0xA4,0x49,0xD5,0xAF,0xAA,0xEA,
+    0x27,0x62,0x84,0x49,0xD7,0x2A,0x00,0xA2,0x27,0x5A,0x84,0x49,0xF5,0x8A,0xA0,0xEA,
+    0x06,0x5A,0xA5,0x49,0xF5,0x8A,0x00,0xA2,0x46,0x5A,0xA5,0x51,0xD7,0x2A,0xA0,0xBB,
+    0x26,0x5A,0xA4,0x51,0xAB,0x80,0x20,0xD7,0x26,0x5A,0x84,0x49,0x22,0xA8,0xA8,0xF7,
+    0x27,0x62,0x84,0x49,0xA8,0x82,0xAA,0xB5,0x07,0x5A,0xA5,0x51,0xC2,0x2F,0xE9,0xDE,
+    0x28,0x62,0x85,0x51,0xA0,0x8A,0xF5,0xAE,0x48,0x6A,0x65,0x49,0xAA,0xEA,0x5F,0x2B,
+    0x68,0x72,0x85,0x49,0xFB,0xFF,0x7F,0x8A,0x47,0x62,0xA5,0x51,0xBE,0xBF,0xF5,0x02,
+    0x88,0x72,0x06,0x5A,0x7F,0x7F,0xF5,0x3B,0x6B,0x8B,0x84,0x49,0x5F,0x5D,0xFF,0x02,
+    0x4E,0xAC,0xC5,0x51,0x55,0x55,0xD5,0x00,0xB0,0xB4,0xC5,0x51,0x55,0x55,0xFF,0x00,
+    0x52,0xC5,0xC6,0x59,0x55,0x55,0xFF,0x00,0x93,0xCD,0xC5,0x59,0x55,0x55,0xAF,0x00,
+    0xB3,0xD5,0xE6,0x59,0x55,0x55,0xAA,0x00,0xF5,0xDD,0x85,0x51,0x55,0xFF,0xAA,0x00,
+    0x56,0xE6,0xA5,0x51,0x55,0xFF,0xAA,0x00,0x97,0xEE,0x26,0x62,0x55,0xFF,0xAA,0x00,
+    0x15,0xDE,0x27,0x62,0x55,0xAB,0x20,0x00,0x36,0xE6,0x88,0x6A,0x55,0xAA,0x00,0x00,
+    0x75,0xE6,0x29,0x83,0x55,0xAA,0x08,0x00,0x96,0xEE,0xCB,0x93,0x55,0xAA,0x00,0x00,
+    0x96,0xEE,0x0D,0x9C,0xD5,0xAA,0x00,0x00,0x97,0xEE,0x90,0xAC,0xF5,0xA2,0x00,0x00,
+    0x96,0xEE,0x11,0xBD,0xF5,0xAA,0x00,0x00,0xB6,0xEE,0x72,0xCD,0xD5,0xAA,0x00,0x00,
+    0x96,0xEE,0xD3,0xD5,0xD5,0xAA,0x00,0x00,0xB6,0xEE,0xD3,0xD5,0xFD,0xAA,0x00,0x00,
+    0xF6,0xF6,0x34,0xDE,0x55,0xFF,0xEB,0xAA,0xB6,0xEE,0x34,0xDE,0xF7,0xAA,0x82,0x00,
+    0xB6,0xEE,0x55,0xE6,0xDD,0xAA,0x22,0x00,0xB6,0xEE,0x55,0xE6,0xED,0xAA,0x02,0x00,
+    0xD6,0xF6,0x75,0xE6,0xDD,0xEB,0xAA,0x2A,0xF8,0xF6,0x96,0xEE,0x55,0xD7,0xAF,0xAB,
+    0xF7,0xFE,0x96,0xEE,0xBD,0xAB,0xAA,0xB8,0xD6,0xF6,0x96,0xEE,0xF8,0xFE,0xFE,0xFA,
+    0xB6,0xF6,0x96,0xEE,0xE8,0xBA,0xD2,0xF3,0x96,0xEE,0x55,0xEE,0xE0,0xE0,0x80,0x82,
+    0x75,0xEE,0x34,0xE6,0x88,0xEA,0xA8,0x78,0x55,0xE6,0xF3,0xDD,0x7A,0x78,0x7E,0x7E,
+    0x55,0xE6,0x92,0xD5,0xB7,0x97,0xAA,0x00,0xD7,0xF6,0x14,0xDE,0xBD,0xAD,0xAF,0x2B,
+    0xF7,0xF6,0x96,0xEE,0xFD,0xAF,0x0A,0x8A,0xF7,0xF6,0x96,0xF6,0x6B,0x8A,0x80,0xA2,
+    0xD7,0xF6,0x75,0xE6,0x57,0xDA,0xE8,0x28,0x96,0xEE,0x55,0xE6,0xAF,0xFA,0xFA,0xC8,
+    0xB6,0xEE,0x75,0xE6,0xBF,0xD5,0x95,0x7F,0xB6,0xEE,0x55,0xE6,0x88,0xAA,0xBB,0xFF,
+    0x96,0xEE,0xF3,0xD5,0x70,0x00,0x00,0x00,0x96,0xEE,0xB3,0xD5,0xD5,0xDE,0xE0,0x00,
+    0x55,0xE6,0xF4,0xD5,0x2A,0x29,0xAD,0x98,0xB7,0xEE,0x35,0xE6,0x02,0xAF,0xB9,0xFD,
+    0xF8,0xF6,0x75,0xE6,0x2A,0x2F,0xA5,0x75,0xF7,0xF6,0xB7,0xF6,0xFA,0xA0,0x8A,0x2D,
+    0xF7,0xF6,0xD3,0xD5,0x5E,0xEA,0x20,0x00,0xF8,0xF6,0xB3,0xD5,0xBD,0xFF,0xE8,0x00,
+    0xD7,0xF6,0x34,0xDE,0x0A,0x0B,0xB5,0xBA,0x18,0xFF,0x96,0xE6,0xA0,0x82,0x2F,0xAD,
+    0x18,0xFF,0xF8,0xF6,0x95,0xDE,0xDF,0xBA,0x18,0xF7,0xF7,0xF6,0x7A,0xFF,0x5F,0x5D,
+    0x18,0xFF,0xD7,0xF6,0x6F,0xFA,0xA2,0xE2,0xF7,0xF6,0xB6,0xEE,0xEA,0xBB,0xFC,0xF0,
+    0xD7,0xF6,0xB6,0xEE,0xDA,0xFE,0xFC,0x54,0xB6,0xEE,0x96,0xEE,0xB2,0xB2,0x50,0xD0,
+    0xB6,0xEE,0x13,0xDE,0x58,0xF8,0xE0,0xF8,0x96,0xEE,0x34,0xE6,0x83,0x0B,0x89,0xA5,
+    0x75,0xEE,0x14,0xDE,0x36,0xBE,0xDC,0xFC,0x75,0xEE,0x55,0xE6,0x78,0x7B,0xED,0xFD,
+    0x34,0xE6,0x92,0xCD,0x5E,0x5E,0x5C,0x58,0x92,0xCD,0x31,0xCD,0x2A,0x3A,0xA8,0x08,
+    0x34,0xE6,0x92,0xCD,0xAB,0xAB,0x29,0x2B,0x55,0xE6,0xF3,0xDD,0xBD,0xF7,0xF5,0xAB,
+    0x34,0xE6,0xF4,0xDD,0x8A,0xEC,0xCA,0xE2,0x35,0xE6,0xF4,0xDD,0xB7,0xFF,0xAF,0xEF,
+    0x14,0xDE,0xF3,0xDD,0xFA,0x28,0xB0,0x7E,0x34,0xE6,0xF4,0xDD,0xF7,0xDF,0x77,0xEE,
+    0x88,0x6A,0xA5,0x51,0x58,0x78,0xE0,0xF0,0xE6,0x59,0x84,0x41,0x7A,0xF2,0xAE,0xF0,
+    0x84,0x49,0xE1,0x30,0x2F,0xFE,0x5C,0x58,0xC5,0x51,0xC1,0x30,0x0B,0xAB,0xBF,0xD5,
+    0xE5,0x51,0x02,0x31,0xA0,0x8B,0xEA,0x57,0xC4,0x49,0xE1,0x28,0xA2,0x88,0xA8,0x5D,
+    0xA5,0x49,0xC2,0x30,0x8A,0x08,0xEA,0xDF,0xC5,0x49,0xA1,0x28,0xAA,0x02,0xEA,0x7F,
+    0x64,0x41,0xC1,0x28,0x00,0x00,0xBF,0xE9,0x64,0x41,0xE2,0x30,0x00,0x28,0x5F,0xFF,
+    0xA5,0x49,0x02,0x31,0xE8,0xB7,0xB5,0x0D,0x64,0x41,0xC1,0x28,0xB6,0x5C,0xB8,0x80,
+    0x43,0x39,0xC1,0x28,0x2A,0xDF,0xFF,0xEA,0x44,0x39,0xC2,0x28,0x28,0xD7,0x7F,0xEF,
+    0x64,0x41,0xA1,0x28,0xFB,0xFD,0xFD,0x82,0x64,0x41,0xC2,0x28,0x57,0x5D,0xFF,0x2B,
+    0x64,0x41,0xC1,0x28,0x75,0xD5,0xEF,0x02,0x85,0x49,0xC1,0x28,0x55,0xD5,0xFF,0x82,
+    0xA6,0x49,0xE2,0x30,0x5D,0x55,0x5D,0x8A,0xC5,0x51,0xE2,0x30,0xF5,0x95,0x95,0x02,
+    0xE6,0x51,0xE2,0x30,0x5E,0xFA,0xEA,0x00,0x06,0x52,0xC1,0x30,0x55,0xD5,0xEB,0x08,
+    0x06,0x5A,0xC1,0x30,0x55,0x77,0xAA,0x0A,0x06,0x5A,0xC1,0x30,0x55,0xFD,0xAA,0x02,
+    0x06,0x62,0xC1,0x30,0x55,0xFF,0xAA,0x00,0x06,0x62,0x02,0x41,0xB5,0xEF,0x2A,0xA0,
+    0x27,0x72,0xA4,0x59,0x3D,0x2F,0x07,0xAF,0x26,0x72,0xE5,0x69,0x82,0x02,0xE8,0xFE,
+    0x26,0x72,0xE5,0x69,0xFA,0x22,0xAF,0xDD,0x46,0x72,0xE6,0x69,0x5A,0xDC,0xA7,0xFD,
+    0x26,0x6A,0x85,0x59,0x56,0xF8,0xA8,0xA2,0x06,0x62,0x64,0x49,0x7E,0xAA,0x0A,0x8C,
+    0x06,0x62,0x64,0x49,0x75,0xA8,0xB0,0xBA,0x06,0x5A,0x84,0x49,0xF5,0x2A,0xAA,0xAA,
+    0x27,0x5A,0xA5,0x51,0xDF,0x32,0xAB,0x57,0x07,0x5A,0x84,0x49,0xAE,0xA2,0x82,0x7B,
+    0xE6,0x59,0x84,0x49,0x2A,0x02,0xA0,0x77,0x07,0x5A,0x84,0x49,0xA8,0x0A,0xAB,0xDF,
+    0x27,0x62,0x84,0x49,0x8A,0xAB,0xFF,0xF5,0x27,0x62,0xA4,0x51,0x2A,0xEB,0x7E,0x57,
+    0x46,0x62,0x84,0x49,0xBA,0xAB,0x7D,0x3D,0x47,0x62,0x44,0x49,0xAA,0xEA,0xFF,0x08,
+    0xC8,0x72,0x83,0x49,0xFF,0xFF,0xF5,0x2A,0x2A,0x7B,0x84,0x51,0xFF,0x57,0x5D,0x02,
+    0xAC,0x93,0xA5,0x51,0xD7,0x55,0xD5,0x22,0x0D,0xA4,0xC5,0x51,0x55,0x55,0x77,0x02,
+    0x6F,0xAC,0x43,0x41,0xF7,0x55,0xBF,0x00,0xD1,0xBC,0xC5,0x51,0x55,0x55,0xFF,0x00,
+    0x72,0xCD,0xE6,0x59,0x55,0x55,0xFF,0x00,0x93,0xCD,0xE5,0x59,0x55,0x55,0xBB,0x00,
+    0xB3,0xD5,0x63,0x49,0x55,0xFF,0xAA,0x00,0xF4,0xDD,0xA4,0x51,0x55,0xFD,0xAA,0x00,
+    0x56,0xEE,0xA4,0x51,0x55,0xFF,0x2A,0x00,0x76,0xEE,0x06,0x62,0x55,0xFF,0x2A,0x00,
+    0xF4,0xDD,0xE5,0x59,0x55,0xAA,0x20,0x00,0x15,0xE6,0xA8,0x72,0x55,0xAA,0x00,0x00,
+    0x55,0xE6,0x2B,0x83,0x55,0xAA,0x08,0x00,0x55,0xE6,0x8C,0x93,0xD5,0xAA,0x00,0x00,
+    0x35,0xE6,0x2D,0xA4,0x55,0xAA,0xA0,0x80,0x52,0xCD,0xCC,0x9B,0x55,0xE8,0xE0,0x78,
+    0xAC,0x93,0x46,0x6A,0xEA,0x60,0x58,0x56,0xAF,0xB4,0x06,0x62,0x2B,0x2F,0x25,0xB5,
+    0x76,0xEE,0x10,0xBD,0xAF,0x2B,0x09,0x09,0xB7,0xF6,0xF4,0xDD,0x55,0xAA,0x22,0x02,
+    0xB7,0xF6,0x15,0xDE,0xF5,0xEA,0x02,0x00,0xD7,0xF6,0x35,0xE6,0xF5,0xAB,0x2A,0x2A,
+    0xD7,0xF6,0x55,0xE6,0x57,0xAE,0xA2,0x2A,0xD7,0xF6,0x76,0xEE,0x75,0xBE,0x2A,0x82,
+    0xD7,0xF6,0x76,0xEE,0xFD,0xAA,0x28,0x08,0xD7,0xF6,0x96,0xEE,0x75,0xDE,0xAA,0xA8,
+    0xD7,0xF6,0x76,0xEE,0xFD,0xBF,0xAA,0x28,0xD6,0xF6,0xB7,0xEE,0x75,0xFD,0x6A,0xFA,
+    0xD7,0xF6,0x96,0xEE,0xBF,0xEF,0xAA,0xAA,0x96,0xF6,0xD7,0xEE,0xAE,0xBF,0xF7,0xFF,
+    0xD7,0xF6,0x96,0xEE,0xD7,0xFF,0xAA,0x2A,0xD6,0xF6,0xB7,0xEE,0x77,0xFF,0xFA,0x6B,
+    0xB7,0xF6,0xB6,0xEE,0xFF,0xFB,0xEF,0xFF,0xD7,0xF6,0xB6,0xEE,0xFD,0x6F,0xEB,0xEA,
+    0xD6,0xF6,0xB6,0xEE,0xA9,0xB9,0xBF,0xFD,0xD7,0xF6,0xB6,0xEE,0xFF,0xEA,0x68,0xFA,
+    0xD7,0xF6,0xB6,0xEE,0x55,0xBF,0x77,0xFF,0xB6,0xF6,0xD7,0xEE,0x8A,0xC8,0x82,0x22,
+    0xD7,0xF6,0xB6,0xEE,0x7B,0x7B,0xFB,0xBB,0xD7,0xF6,0x96,0xEE,0xBA,0xBA,0xBE,0xFE,
+    0xD7,0xF6,0xB7,0xEE,0x2B,0x32,0x28,0x2A,0xF7,0xF6,0xB6,0xF6,0x8E,0x83,0xA0,0x72,
+    0xD6,0xF6,0x96,0xEE,0xA8,0xB8,0xFF,0xD7,0xB6,0xF6,0x96,0xEE,0xA2,0x60,0x7A,0xB7,
+    0x96,0xEE,0x75,0xEE,0x00,0xBB,0x5F,0x5C,0xB7,0xF6,0x35,0xE6,0xA2,0xEA,0xEE,0x5F,
+    0x55,0xE6,0x14,0xDE,0xA8,0xBA,0xA7,0xAF,0x96,0xEE,0xF3,0xDD,0xD7,0xBF,0xBF,0x2F,
+    0xD7,0xF6,0x34,0xE6,0xF7,0xFF,0x0A,0x22,0xF7,0xF6,0x96,0xEE,0xBD,0x0B,0xA2,0x8A,
+    0xF7,0xF6,0xD7,0xF6,0xA7,0xA7,0xA2,0xEB,0xF7,0xF6,0xD7,0xF6,0xEA,0x6A,0xFB,0xED,
+    0xF7,0xF6,0xB6,0xEE,0xFA,0xFA,0xEA,0xA2,0xD7,0xF6,0x96,0xEE,0x5E,0xEE,0xCA,0x80,
+    0xB6,0xEE,0x76,0xEE,0x7B,0xAB,0xAA,0x00,0xB6,0xEE,0x76,0xE6,0xD5,0xFE,0xFA,0xFC,
+    0x96,0xEE,0x76,0xE6,0xEF,0xDE,0x6F,0xBA,0xB6,0xEE,0x56,0xE6,0x2A,0x2A,0x2B,0x0A,
+    0xF7,0xF6,0x55,0xE6,0x5E,0x7A,0xEA,0xAA,0xD7,0xF6,0x34,0xDE,0xB5,0xFF,0xAA,0x80,
+    0xB6,0xEE,0x75,0xE6,0x5D,0xAF,0xAB,0xA0,0xF7,0xF6,0x96,0xEE,0x2D,0xBD,0xE5,0xBF,
+    0x18,0xFF,0xD7,0xF6,0xAA,0xBB,0xBD,0xB5,0x18,0xF7,0xD7,0xF6,0xFD,0xBA,0xEA,0xA8,
+    0xF8,0xF6,0xD7,0xF6,0x56,0xF8,0x08,0xAC,0xF8,0xF6,0xB7,0xEE,0x55,0x7A,0xC0,0x00,
+    0x18,0xFF,0x96,0xE6,0x82,0x0D,0xB7,0xFE,0x18,0xFF,0xD7,0xEE,0xAE,0xAE,0xAE,0xAD,
+    0x18,0xFF,0xF7,0xF6,0xF7,0xD7,0xAF,0xBD,0x18,0xFF,0xD7,0xF6,0x5A,0x7E,0x7E,0x7A,
+    0xD7,0xF6,0x96,0xEE,0xFE,0x72,0xEF,0xEB,0xB6,0xEE,0x75,0xE6,0xAA,0xBA,0x7E,0x7E,
+    0x96,0xEE,0x14,0xDE,0xE0,0xE0,0xE8,0x7B,0x96,0xEE,0xF3,0xDD,0x2D,0xBD,0xB5,0xD5,
+    0x75,0xEE,0xF3,0xDD,0xFC,0x78,0xF0,0xF8,0x55,0xE6,0x14,0xE6,0x8A,0xA3,0xA9,0xFD,
+    0x34,0xE6,0x92,0xCD,0x78,0x78,0x70,0x68,0x92,0xCD,0x51,0xC5,0x3E,0xB5,0xD5,0x9E,
+    0x14,0xE6,0x92,0xCD,0x0B,0x0B,0x29,0x0F,0x54,0xE6,0x14,0xDE,0xEB,0xDF,0x57,0xD7,
+    0x34,0xE6,0xF4,0xDD,0xC2,0xAA,0xAE,0x6E,0x14,0xDE,0xB3,0xD5,0x0A,0xA8,0xAA,0x2B,
+    0x14,0xDE,0xD3,0xD5,0x37,0x2F,0x2A,0x20,0x34,0xE6,0xF4,0xDD,0xEA,0x7E,0x5F,0x76,
+    0x8B,0x8B,0x06,0x5A,0x7E,0x7E,0x78,0x78,0x06,0x5A,0xA5,0x49,0xDE,0xFA,0x58,0x60,
+    0xA5,0x49,0xC1,0x30,0x68,0xE8,0x82,0x00,0xA5,0x49,0xA1,0x28,0xD5,0xFF,0xAA,0x08,
+    0x47,0x62,0xE1,0x30,0x55,0xD5,0xAB,0x0A,0x88,0x6A,0xE1,0x30,0x55,0xFF,0x2A,0x00,
+    0xE9,0x72,0x23,0x39,0x55,0xAB,0x0A,0x22,0xE9,0x72,0x84,0x41,0x55,0xFA,0xA0,0xA8,
+    0x67,0x62,0x64,0x41,0xF5,0xAA,0x00,0xA0,0x87,0x62,0x64,0x41,0x55,0xFE,0xA8,0xAA,
+    0x68,0x62,0x43,0x39,0xBD,0xAA,0x22,0xAA,0x27,0x5A,0x84,0x49,0x5E,0xA0,0xA8,0xAA,
+    0x07,0x5A,0x84,0x41,0x55,0x20,0x00,0xA0,0x27,0x5A,0x84,0x49,0x55,0x08,0x00,0xFB,
+    0x27,0x5A,0x84,0x49,0xBD,0xA0,0x88,0xEF,0x07,0x5A,0xA5,0x49,0xAD,0x28,0x26,0x77,
+    0x27,0x5A,0x84,0x49,0xAA,0x00,0xAF,0x77,0x47,0x5A,0x85,0x49,0xEB,0xA2,0xFB,0x55,
+    0x07,0x5A,0x64,0x49,0x2A,0x02,0xAA,0x55,0x27,0x62,0x84,0x49,0xAA,0xF0,0x7F,0x55,
+    0x47,0x62,0x64,0x49,0x02,0xEA,0x7F,0x55,0x27,0x5A,0x65,0x49,0x00,0xA8,0x57,0xD5,
+    0x27,0x62,0x85,0x49,0x0A,0x8A,0x55,0x55,0x06,0x5A,0x65,0x49,0x80,0xE3,0xDD,0x3A,
+    0x47,0x6A,0x64,0x49,0xEA,0xFF,0x55,0x82,0x47,0x6A,0x84,0x51,0xFE,0x5F,0xD5,0xE8,
+    0x06,0x6A,0xC5,0x61,0xBB,0x9F,0xA9,0xA5,0x06,0x72,0xE5,0x69,0xD4,0x5F,0x5F,0x5A,
+    0x46,0x7A,0xE5,0x69,0xF5,0xFD,0xAF,0xF9,0x26,0x72,0xE5,0x69,0x6F,0xFF,0xA2,0x2A,
+    0x88,0x82,0xE6,0x69,0x7F,0xAD,0x29,0x2B,0x4E,0xAC,0xA5,0x59,0x55,0x57,0xAF,0x0A,
+    0x73,0xCD,0xE6,0x61,0x55,0x55,0xAB,0x08,0xB3,0xD5,0x84,0x51,0x55,0xDD,0xAA,0x00,
+    0x14,0xDE,0x83,0x49,0x55,0xFF,0xAA,0x00,0x34,0xDE,0xE5,0x59,0x55,0xFF,0x2A,0x00,
+    0x95,0xEE,0x26,0x62,0x55,0xFF,0x2A,0x00,0xF3,0xDD,0x46,0x62,0x55,0xAB,0x08,0x00,
+    0x14,0xDE,0x88,0x6A,0x55,0xAA,0x00,0x00,0x34,0xDE,0x0A,0x7B,0x55,0xAA,0x00,0x00,
+    0x55,0xE6,0x6B,0x8B,0x5D,0xAA,0x00,0x00,0x75,0xE6,0x2D,0x9C,0x55,0xAA,0x00,0x00,
+    0x96,0xEE,0x6E,0xAC,0x55,0x2A,0x00,0x00,0x96,0xEE,0xF0,0xBC,0x55,0xAA,0x00,0x00,
+    0xB6,0xEE,0x52,0xC5,0x75,0xAA,0x22,0x80,0xB6,0xEE,0x93,0xCD,0xD5,0xAA,0x00,0x00,
+    0x96,0xEE,0xF4,0xDD,0x55,0xBB,0x00,0x00,0xB6,0xF6,0x14,0xDE,0x55,0xAE,0xAA,0x00,
+    0xB6,0xF6,0x15,0xDE,0xF7,0xAA,0x28,0x00,0xB6,0xEE,0x35,0xE6,0x5D,0xAA,0x28,0x00,
+    0xB6,0xEE,0x55,0xE6,0x7D,0xEA,0x22,0x00,0xB6,0xEE,0x55,0xE6,0xFD,0x2A,0x00,0x00,
+    0xB6,0xEE,0x76,0xEE,0x57,0xBB,0x22,0x00,0xB6,0xF6,0x56,0xEE,0xF7,0xAF,0x0A,0x00,
+    0xB6,0xF6,0x96,0xEE,0x75,0xED,0xB8,0x00,0xB6,0xF6,0x96,0xEE,0xF5,0xFE,0xFA,0x00,
+    0x96,0xF6,0xB6,0xEE,0xA8,0xEE,0xEE,0xD5,0xB6,0xF6,0x14,0xE6,0xAA,0xE0,0x6A,0x60,
+    0x34,0xE6,0x4E,0xAC,0xA0,0xE8,0x68,0x7A,0xAF,0xBC,0x06,0x62,0xE0,0xF8,0x7E,0x5E,
+    0x66,0x72,0xE6,0x61,0xFC,0x7B,0x7E,0x5E,0xE9,0x82,0xC5,0x61,0x3D,0xBD,0xB7,0xD5,
+    0x75,0xEE,0x8B,0x93,0x0B,0x29,0x0D,0x2D,0x18,0xFF,0x96,0xEE,0xF5,0xFF,0xAB,0x2B,
+    0xF8,0xF6,0xB7,0xF6,0xD5,0xBF,0x2A,0x08,0xF7,0xF6,0xB7,0xEE,0xFD,0xAA,0x00,0x00,
+    0x17,0xFF,0xD7,0xF6,0x7D,0xBF,0xEA,0xAA,0x18,0xF7,0xD7,0xF6,0xD5,0xBA,0x3B,0xAA,
+    0xF7,0xF6,0xB6,0xEE,0xEA,0xE8,0xD0,0xE8,0xF7,0xF6,0xB6,0xEE,0xDB,0xBB,0xAA,0xAB,
+    0xD7,0xF6,0xB6,0xEE,0xBA,0x28,0x0A,0x22,0xD7,0xF6,0xB7,0xEE,0x82,0x82,0x00,0x02,
+    0xD7,0xF6,0xB7,0xEE,0xF0,0x3A,0x82,0x89,0xD7,0xF6,0xB7,0xEE,0x9C,0xBE,0xAB,0x82,
+    0xD7,0xF6,0xB7,0xEE,0x3F,0xFB,0xAE,0x0E,0xD7,0xF6,0xB7,0xEE,0xEA,0xE2,0xAA,0xA8,
+    0xD7,0xF6,0xB6,0xEE,0xEF,0xA2,0xA0,0xA0,0xD7,0xF6,0xB6,0xEE,0xF1,0xEB,0xA8,0xAA,
+    0xD7,0xF6,0xB7,0xEE,0xBF,0xEB,0x4A,0xAA,0xD6,0xF6,0xB7,0xEE,0xD7,0xF5,0xAF,0x8A,
+    0xD7,0xF6,0xB6,0xEE,0x7F,0xFB,0xFA,0xEA,0xD7,0xF6,0xB6,0xEE,0xE3,0x8A,0x7D,0x2F,
+    0xD7,0xF6,0xB6,0xEE,0xEF,0x6A,0x2B,0x29,0xF7,0xF6,0xB6,0xEE,0x5D,0xFF,0xBF,0x2B,
+    0xF7,0xF6,0xB6,0xF6,0x2B,0x8A,0xE2,0xF8,0xD7,0xF6,0x75,0xEE,0xF0,0xF8,0x7E,0xFE,
+    0x96,0xEE,0x75,0xEE,0x26,0xBF,0x64,0x6D,0xB6,0xF6,0x75,0xEE,0xAB,0x7B,0x7F,0x55,
+    0x96,0xEE,0x34,0xE6,0xC0,0xE8,0xEE,0x7A,0x55,0xE6,0xF3,0xDD,0xA0,0xA8,0xFA,0x7E,
+    0x55,0xE6,0xF3,0xDD,0x2A,0x2A,0x2B,0x09,0xB7,0xF6,0x55,0xE6,0x2D,0x2B,0x0B,0x8B,
+    0xD7,0xF6,0x96,0xEE,0x3A,0xE8,0xEA,0xFF,0xD7,0xF6,0x96,0xEE,0x02,0x3B,0xAB,0x2B,
+    0x17,0xF7,0xB7,0xF6,0xFB,0xFF,0xFD,0x55,0xF7,0xF6,0xD7,0xF6,0xAD,0xAD,0x65,0x6D,
+    0xF7,0xF6,0x97,0xEE,0x28,0x88,0xAA,0x8E,0xF7,0xF6,0xD7,0xF6,0xD6,0xF6,0x55,0x77,
+    0xD7,0xF6,0xB7,0xEE,0x7E,0xB8,0xA8,0x08,0xD7,0xF6,0x96,0xEE,0xFB,0xFA,0xEA,0x08,
+    0x96,0xF6,0xB7,0xEE,0xBB,0xDD,0x7D,0x55,0xB7,0xEE,0x96,0xEE,0xF5,0x7E,0x68,0x80,
+    0xB6,0xEE,0x96,0xEE,0x03,0xB5,0xB6,0x2E,0xF7,0xF6,0xB6,0xEE,0x7F,0xAD,0x2D,0xAD,
+    0xF7,0xF6,0xB6,0xEE,0x55,0x5A,0x6A,0x20,0xD7,0xF6,0xB7,0xEE,0xE5,0xED,0xEF,0x98,
+    0x18,0xFF,0xB6,0xF6,0xBF,0xAD,0xBE,0xAB,0x38,0xFF,0xF8,0xF6,0xFF,0xAF,0xA9,0xAF,
+    0x39,0xFF,0xF8,0xF6,0x57,0x5E,0x7A,0xFA,0x18,0xF7,0xD7,0xF6,0xFA,0x7B,0xFA,0xF8,
+    0xF7,0xF6,0x96,0xEE,0x68,0x80,0x02,0x08,0xF7,0xF6,0xB6,0xEE,0x2D,0xB7,0xD6,0x7E,
+    0xF7,0xF6,0xD7,0xF6,0x02,0x0A,0x20,0x29,0x38,0xFF,0xD7,0xF6,0x7F,0x7B,0xFF,0x7D,
+    0xD7,0xF6,0x96,0xEE,0xFE,0xEC,0xFE,0xB8,0xB6,0xEE,0x55,0xE6,0xFA,0x78,0xF8,0x7A,
+    0x75,0xE6,0x14,0xDE,0x6A,0x6A,0x6E,0x68,0x34,0xE6,0x92,0xCD,0xAE,0x3F,0x95,0xD5,
+    0x55,0xE6,0x14,0xE6,0x72,0x62,0x42,0x63,0xF4,0xE5,0x34,0xDE,0x7F,0xFA,0xFA,0xFA,
+    0x55,0xEE,0xB3,0xD5,0x60,0x68,0xE0,0xE2,0xB2,0xD5,0x51,0xC5,0x2F,0xB7,0xF6,0xF6,
+    0x34,0xE6,0x92,0xCD,0x2F,0x0F,0xA9,0x29,0x34,0xE6,0x14,0xDE,0x02,0x88,0x0B,0xFA,
+    0x35,0xE6,0xF4,0xDD,0xFA,0xFE,0x9E,0xB7,0x14,0xDE,0xD3,0xDD,0x3E,0xFC,0xEE,0xBA,
+    0x14,0xDE,0xD3,0xDD,0x28,0xBA,0x9F,0xE7,0x14,0xDE,0x92,0xCD,0xA8,0xA8,0xEA,0x60,
+    0x51,0xC5,0x87,0x6A,0x5E,0x78,0xE0,0x80,0xCB,0x93,0xC5,0x51,0x57,0x57,0x5E,0xE8,
+    0xE5,0x59,0x63,0x49,0xAE,0xAF,0xF7,0xA0,0xE5,0x59,0x42,0x41,0x22,0x0A,0xFF,0xDF,
+    0x47,0x62,0x43,0x41,0x00,0xAE,0xFF,0xE7,0x67,0x62,0x43,0x41,0x00,0xBA,0x7F,0xFA,
+    0x88,0x6A,0x84,0x49,0x20,0xFF,0x55,0xFF,0x67,0x6A,0x84,0x49,0x8A,0x6F,0x75,0x20,
+    0xC9,0x7A,0x84,0x49,0xFF,0x5D,0x55,0x02,0x6B,0x8B,0x84,0x49,0x7F,0x55,0x55,0x02,
+    0xED,0x9B,0x84,0x49,0x55,0x55,0xFF,0x00,0x6E,0xAC,0xA5,0x49,0x55,0x55,0xFF,0x00,
+    0xD0,0xB4,0xA5,0x51,0x55,0x55,0xFF,0x00,0x32,0xBD,0xA5,0x51,0x55,0x55,0xEF,0x00,
+    0x32,0xC5,0xA5,0x51,0x55,0x55,0xAA,0x00,0x92,0xCD,0xA5,0x49,0x55,0xF5,0xAA,0x00,
+    0xF3,0xDD,0x84,0x49,0x55,0xFF,0xAA,0x00,0x34,0xE6,0xA5,0x51,0x55,0xFF,0xAA,0x00,
+    0x14,0xDE,0x06,0x5A,0x55,0xFF,0x8A,0x00,0xB3,0xD5,0xC5,0x51,0x55,0xAA,0x00,0x00,
+    0xF4,0xDD,0x67,0x6A,0x55,0xAA,0x00,0x00,0x14,0xDE,0xE9,0x72,0x55,0xAA,0x00,0x00,
+    0x35,0xDE,0x6B,0x8B,0x55,0xAA,0x08,0x00,0x35,0xE6,0xAD,0x93,0xF5,0xAA,0x00,0x00,
+    0x35,0xE6,0x70,0xAC,0x55,0xAA,0x00,0x00,0x35,0xE6,0xA8,0x7A,0x7E,0xFA,0xE0,0xE0,
+    0x87,0x7A,0x84,0x59,0xF7,0xF6,0x54,0x54,0xE5,0x69,0xA4,0x61,0x20,0x22,0x23,0x3D,
+    0x05,0x72,0xC5,0x69,0xBE,0xBF,0x3E,0x37,0x26,0x72,0xE5,0x69,0xFA,0xBA,0xB8,0xD7,
+    0x88,0x7A,0x06,0x72,0x2D,0xBD,0xB5,0xD5,0x6E,0xB4,0x67,0x72,0x0B,0x2D,0xB5,0xF5,
+    0x35,0xE6,0x0C,0xAC,0x2A,0x0B,0x2F,0xAD,0x96,0xF6,0x35,0xE6,0xB5,0xAA,0xAB,0x09,
+    0xB6,0xF6,0x55,0xE6,0xDD,0xFB,0xAB,0x2A,0xB6,0xF6,0x75,0xEE,0x55,0xFF,0xEA,0xAA,
+    0x96,0xF6,0x75,0xE6,0x5F,0xAE,0x8B,0x08,0xB6,0xF6,0x75,0xE6,0xD7,0xEF,0x2A,0x22,
+    0xB6,0xF6,0x96,0xE6,0x57,0xAB,0xAE,0xA2,0xB6,0xF6,0x75,0xEE,0xFD,0xEE,0xB0,0x3A,
+    0xB7,0xF6,0x75,0xEE,0xBD,0xBB,0xAA,0xAA,0xB6,0xF6,0x96,0xEE,0x7E,0xCA,0x03,0x0F,
+    0x96,0xF6,0xB6,0xEE,0x76,0x5F,0x77,0xFF,0xD7,0xF6,0x96,0xEE,0xD5,0xFF,0xFF,0xBC,
+    0xB6,0xF6,0x95,0xEE,0xEF,0xAA,0x0A,0x0A,0x96,0xFE,0xB6,0xEE,0x7D,0xF7,0xDF,0xFF,
+    0xB7,0xF6,0xB6,0xEE,0xFF,0xBE,0xEB,0xAA,0xD6,0xF6,0x95,0xEE,0xFB,0xAA,0x29,0xAF,
+    0xD7,0xF6,0xB6,0xEE,0x7D,0xAA,0x00,0x02,0xF6,0xF6,0xD7,0xF6,0x55,0x57,0x7F,0xEB,
+    0xF7,0xF6,0xB6,0xEE,0xD7,0xAB,0x82,0x00,0xF7,0xF6,0xB7,0xEE,0xF7,0x2A,0x22,0x80,
+    0xF7,0xF6,0xB6,0xEE,0xFB,0xEA,0x8A,0x22,0xF7,0xF6,0xB6,0xEE,0xBF,0x2A,0x00,0x00,
+    0xF7,0xF6,0xD7,0xF6,0x55,0x58,0xE2,0xA0,0xF8,0xFE,0xB6,0xF6,0xDD,0xAA,0x2B,0xEA,
+    0xD7,0xF6,0x75,0xEE,0x88,0x80,0xE0,0x60,0xB6,0xF6,0xEF,0xBC,0xA0,0xE8,0xEA,0x7A,
+    0x51,0xCD,0x87,0x7A,0xE0,0xE8,0x5A,0x5E,0xC8,0x7A,0x26,0x6A,0x7C,0xFF,0xF5,0xF5,
+    0x46,0x72,0xE5,0x61,0x7C,0xC0,0x88,0x60,0x66,0x72,0xC5,0x61,0x15,0x95,0x9E,0xBF,
+    0x75,0xEE,0x8A,0x93,0x2D,0x2D,0x2D,0x2D,0x18,0xFF,0x96,0xF6,0x29,0x2B,0xAB,0x8B,
+    0xF8,0xFE,0x17,0xF7,0xAA,0xAA,0xAA,0xE2,0x18,0xFF,0xF7,0xF6,0xD7,0xD5,0xAF,0xBE,
+    0x18,0xFF,0xF7,0xF6,0xAF,0xFF,0xEE,0xB9,0x18,0xFF,0xF7,0xF6,0x7E,0xAA,0xAA,0x6E,
+    0xF7,0xF6,0xD7,0xF6,0x70,0xE8,0xE2,0xA8,0xF7,0xF6,0xD7,0xF6,0xDB,0xDA,0x5D,0xD5,
+    0xF7,0xF6,0xD7,0xF6,0x55,0x5D,0x6B,0x7B,0xF6,0xF6,0xD7,0xF6,0x55,0x5F,0x7E,0x7F,
+    0xB7,0xF6,0xD6,0xEE,0xBA,0xEA,0xAA,0xFB,0xD7,0xF6,0xB7,0xEE,0x8A,0x02,0x02,0xC8,
+    0xD7,0xF6,0xB6,0xEE,0xAA,0x22,0x28,0x2F,0xD7,0xF6,0xB7,0xEE,0x82,0x02,0x28,0x2E,
+    0xD7,0xF6,0xB7,0xEE,0x80,0xA8,0x3E,0xA3,0xD7,0xF6,0xF7,0xEE,0x00,0x0A,0x82,0x82,
+    0xF7,0xF6,0xB6,0xEE,0xFF,0xDA,0xFE,0xBA,0xD7,0xF6,0xB6,0xEE,0x8B,0x8A,0xA2,0x28,
+    0xD7,0xF6,0xB6,0xEE,0xE2,0xEA,0xBE,0xBE,0xF7,0xF6,0xB6,0xEE,0xF7,0xFF,0xEA,0xEA,
+    0xF7,0xF6,0xD7,0xF6,0x55,0x5F,0xBD,0x2D,0x18,0xFF,0xD7,0xF6,0xAD,0xE9,0xFB,0x5E,
+    0xF7,0xF6,0x96,0xEE,0xE8,0xFA,0xDE,0x7E,0xB6,0xF6,0x96,0xEE,0xDE,0x7D,0x77,0x7F,
+    0x96,0xEE,0x75,0xEE,0x72,0xFA,0x5E,0x54,0x96,0xEE,0x14,0xE6,0xEA,0xF8,0x7A,0x5A,
+    0x55,0xEE,0xF4,0xDD,0xA0,0xA2,0xEA,0xFF,0x14,0xDE,0x71,0xCD,0x80,0xE8,0x7C,0xD6,
+    0x55,0xE6,0xB2,0xD5,0x03,0xAD,0xBD,0x8B,0x76,0xEE,0x14,0xDE,0x00,0xEB,0x55,0xF2,
+    0x96,0xEE,0xB2,0xD5,0x00,0x2A,0xD7,0x5F,0x96,0xF6,0xD3,0xD5,0x00,0x00,0xAF,0xD5,
+    0xB7,0xF6,0x14,0xDE,0x08,0x02,0xAA,0xF5,0xD7,0xF6,0x55,0xE6,0x00,0x88,0xEB,0xF7,
+    0xD7,0xF6,0x96,0xEE,0x0A,0x0A,0x2D,0xD5,0xF7,0xF6,0xB6,0xF6,0xEE,0x0A,0x2B,0xBD,
+    0xF7,0xF6,0xD7,0xF6,0x75,0xD6,0xB7,0x29,0xF8,0xF6,0xD7,0xF6,0x55,0xFD,0xDF,0xE7,
+    0xD7,0xF6,0xB7,0xEE,0x5E,0x58,0xF8,0x70,0x97,0xF6,0xB6,0xEE,0xDF,0xFF,0xFF,0x5F,
+    0xD7,0xF6,0x96,0xEE,0x2E,0xA3,0xFE,0xFA,0xD7,0xF6,0xB7,0xEE,0x08,0x2A,0xAF,0xF5,
+    0xF7,0xF6,0xB7,0xEE,0x82,0xAA,0xAF,0x0B,0xF7,0xF6,0xD7,0xF6,0xEA,0x08,0x20,0x82,
+    0x18,0xF7,0xD8,0xF6,0x3D,0xAF,0xBF,0xEB,0x38,0xFF,0xF7,0xF6,0xAB,0x2E,0xAB,0xAF,
+    0x39,0xFF,0x18,0xF7,0x7F,0xEA,0xEA,0x22,0x38,0xFF,0xF8,0xF6,0x5F,0xDE,0xFF,0x68,
+    0x18,0xF7,0xD7,0xF6,0xBF,0xFA,0xEA,0xFE,0xF7,0xF6,0xB7,0xEE,0xE8,0xA0,0xA2,0xFA,
+    0xF7,0xF6,0xB6,0xEE,0x0D,0x25,0x17,0xD7,0xF7,0xF6,0x97,0xEE,0xA0,0x88,0xA8,0xEA,
+    0xD7,0xF6,0x96,0xEE,0xEA,0xFA,0x60,0xE2,0x96,0xEE,0x55,0xE6,0xE0,0xE0,0xE0,0xE0,
+    0x55,0xE6,0xD3,0xD5,0x60,0xEA,0xF2,0xF0,0xB3,0xD5,0x0F,0xBD,0x2E,0x2E,0x3E,0x16,
+    0x55,0xE6,0xF3,0xDD,0xA3,0x0B,0x09,0xA9,0x14,0xDE,0xB3,0xDD,0x0A,0x0A,0xA8,0xBA,
+    0x34,0xE6,0xF4,0xDD,0x82,0xEA,0xEB,0x8B,0xD3,0xD5,0x30,0xC5,0xD6,0xDC,0xDC,0x5C,
+    0x14,0xE6,0x71,0xCD,0x2B,0x29,0x2D,0x0F,0x34,0xE6,0x14,0xDE,0xD4,0xF5,0x95,0x55,
+    0x35,0xE6,0xF3,0xDD,0xEF,0xEE,0xDA,0xE0,0x14,0xDE,0xF3,0xDD,0xFA,0x00,0x28,0x54,
+    0x14,0xDE,0xD3,0xDD,0xAA,0xBC,0xFE,0x3A,0xF3,0xDD,0x10,0xC5,0xC0,0x60,0x60,0x60,
+    0xB6,0xEE,0x92,0xCD,0x7F,0xFA,0xA8,0x80,0x55,0xE6,0x2D,0xA4,0x5E,0xAA,0x20,0x00,
+    0x14,0xDE,0x29,0x7B,0x55,0xAA,0x80,0x00,0xF4,0xDD,0xC8,0x72,0x55,0xAA,0x00,0x00,
+    0x14,0xDE,0x09,0x7B,0x55,0xAA,0x02,0x00,0x15,0xDE,0x8B,0x8B,0x55,0xAA,0x00,0x00,
+    0x35,0xE6,0x0D,0x9C,0x55,0xAA,0x00,0x00,0x55,0xE6,0x70,0xAC,0x55,0xAA,0x08,0x00,
+    0x55,0xE6,0xF1,0xBC,0x55,0xAA,0x0A,0x00,0x76,0xE6,0x32,0xC5,0x57,0xAB,0x28,0x00,
+    0x76,0xEE,0x72,0xCD,0xD5,0xBA,0x08,0x00,0x75,0xEE,0xD3,0xD5,0x55,0xBB,0x20,0x00,
+    0x75,0xEE,0xD3,0xD5,0x55,0xEA,0x00,0x00,0x75,0xEE,0xD4,0xD5,0xDD,0xAA,0x82,0x00,
+    0x76,0xEE,0xF4,0xDD,0x75,0x82,0x02,0x00,0x96,0xF6,0x14,0xDE,0x57,0xEE,0xAA,0x0A,
+    0x95,0xEE,0x34,0xE6,0x55,0xBB,0xAA,0x00,0x96,0xEE,0x34,0xE6,0x7F,0xAE,0x8A,0x08,
+    0x96,0xEE,0x34,0xE6,0xD7,0xEA,0xAA,0x88,0x96,0xEE,0x55,0xE6,0xFD,0xAF,0xA8,0xA8,
+    0x96,0xEE,0x34,0xE6,0xFD,0xA8,0xA8,0x08,0xB7,0xF6,0x55,0xE6,0xDD,0xFF,0xBF,0x2B,
+    0x96,0xEE,0x75,0xEE,0xFD,0x8B,0x23,0x00,0x96,0xEE,0x76,0xEE,0x55,0xF0,0x00,0x00,
+    0xB6,0xF6,0x76,0xEE,0xF5,0xFD,0xBB,0xAD,0xB6,0xF6,0x4D,0xAC,0x78,0x6A,0x78,0x68,
+    0xC8,0x82,0x83,0x61,0x54,0xD8,0x7C,0xFC,0xE5,0x69,0x84,0x61,0x3B,0x57,0xFF,0xBF,
+    0x26,0x72,0x84,0x61,0x2F,0x27,0xBF,0xBF,0x26,0x72,0xE5,0x69,0xDF,0xF0,0xA8,0x02,
+    0x27,0x72,0xA4,0x69,0x20,0x2B,0x2E,0x96,0xE8,0x82,0x26,0x72,0x3D,0xD5,0xD5,0x55,
+    0x51,0xCD,0xA8,0x82,0x0B,0x2D,0xBD,0xB5,0x96,0xF6,0x31,0xCD,0x0A,0x0B,0x2F,0x3D,
+    0x96,0xF6,0xB6,0xEE,0xA3,0xA8,0xA0,0x80,0xB6,0xF6,0x96,0xEE,0xEF,0x2B,0xBA,0xA8,
+    0xB6,0xF6,0x96,0xEE,0x2F,0xE8,0x2B,0xA7,0xB6,0xF6,0x96,0xEE,0xBF,0xBF,0xFA,0xA8,
+    0xB6,0xF6,0x96,0xEE,0xB8,0xEA,0xAA,0x2F,0xB6,0xF6,0x96,0xEE,0xF3,0xBB,0xFB,0xBA,
+    0xB6,0xF6,0x96,0xEE,0xEA,0xFA,0xFE,0x9F,0xB7,0xF6,0x96,0xEE,0x07,0xBB,0xE8,0x8A,
+    0xB6,0xF6,0x96,0xEE,0x88,0xAA,0xFF,0xAB,0xB6,0xF6,0x96,0xEE,0x0E,0x0F,0x82,0x82,
+    0xB6,0xF6,0x96,0xEE,0xEA,0xAB,0xBA,0xA8,0xB6,0xF6,0x97,0xEE,0x8B,0xA0,0x0A,0x22,
+    0xB6,0xF6,0xD7,0xEE,0x08,0xA0,0xA8,0xE8,0xD7,0xF6,0xB6,0xEE,0xDD,0x1D,0xAB,0x22,
+    0xF7,0xF6,0xD7,0xF6,0xB5,0x25,0x23,0x0A,0xD7,0xFE,0xF7,0xF6,0xDD,0x77,0x5D,0xF5,
+    0xF7,0xF6,0xD7,0xF6,0x88,0xAA,0xA2,0x08,0x17,0xFF,0xD7,0xF6,0x6E,0x6E,0xFB,0xEF,
+    0x17,0xFF,0xD7,0xF6,0xED,0xAD,0xBF,0xBF,0xF7,0xFE,0xF7,0xF6,0xFF,0xDF,0x77,0xF7,
+    0xD7,0xFE,0xF7,0xF6,0xF7,0xED,0xFF,0xAB,0xF7,0xFE,0xB6,0xF6,0xA8,0xAA,0xEA,0x7A,
+    0xB7,0xF6,0x92,0xD5,0x80,0xE0,0xE8,0x7A,0xD2,0xDD,0xA7,0x82,0xA0,0xE8,0xE8,0x7A,
+    0x8A,0x93,0x26,0x72,0x7C,0x5E,0xFF,0x7D,0xA7,0x82,0x26,0x72,0xF6,0xE7,0xBA,0xAA,
+    0xA7,0x7A,0x05,0x6A,0x7F,0xFE,0xEA,0xCE,0x87,0x7A,0xE4,0x61,0xF7,0x95,0x37,0x37,
+    0x75,0xEE,0xCC,0xA3,0x2D,0x2D,0x2D,0x29,0xF7,0xF6,0x96,0xF6,0x03,0x09,0x0B,0x02,
+    0x18,0xFF,0xF7,0xF6,0xF7,0xE5,0xFF,0xB6,0x17,0xFF,0xF7,0xF6,0xEF,0xBD,0xED,0x9F,
+    0xF8,0xFE,0x17,0xF7,0x7F,0x77,0xFF,0xFF,0x18,0xFF,0xF7,0xF6,0xF8,0x28,0xF0,0x4A,
+    0x17,0xFF,0xD7,0xF6,0xFA,0xEA,0xAA,0x7A,0xF7,0xF6,0xD7,0xF6,0x77,0xDD,0x3D,0x2D,
+    0xF7,0xF6,0xD7,0xF6,0xEF,0xDD,0xFD,0xFA,0xF7,0xF6,0xD7,0xF6,0xD6,0xFF,0xFB,0xBB,
+    0xD7,0xF6,0xB6,0xEE,0x0A,0x00,0x88,0x20,0xD7,0xF6,0xF6,0xEE,0x02,0x20,0x28,0x28,
+    0xF7,0xF6,0xB6,0xEE,0xBD,0xAA,0x2A,0xAE,0xD7,0xF6,0xB6,0xEE,0x08,0xA2,0x80,0x08,
+    0xD7,0xF6,0xB7,0xEE,0x08,0xBE,0x20,0x80,0xD7,0xF6,0xD6,0xEE,0xA8,0xAA,0xAA,0xAA,
+    0xD7,0xF6,0xB6,0xEE,0x20,0xA8,0xA8,0x20,0xD7,0xF6,0xF7,0xEE,0x20,0x20,0xE8,0xA0,
+    0xF7,0xF6,0xB6,0xEE,0xBE,0xFA,0xAE,0xBE,0xF7,0xF6,0xD7,0xF6,0x55,0x55,0xF5,0x2D,
+    0xF7,0xFE,0xD7,0xEE,0xAB,0x8A,0xE0,0x7A,0xF7,0xF6,0xB6,0xF6,0xE0,0x7A,0x5E,0x57,
+    0xD6,0xF6,0x96,0xEE,0x5E,0xDE,0x5E,0x5F,0x75,0xF6,0x96,0xEE,0x55,0xF7,0xFD,0xE7,
+    0x96,0xEE,0x34,0xE6,0xAA,0xBA,0xF0,0x7A,0x55,0xE6,0xF3,0xDD,0x7C,0x7C,0x7A,0x5E,
+    0xF3,0xDD,0x92,0xD5,0xC2,0xFA,0x68,0xF2,0x34,0xE6,0x51,0xCD,0xF7,0x9D,0x27,0x0B,
+    0xB6,0xF6,0x13,0xDE,0xAD,0x2B,0x0A,0x02,0xB6,0xF6,0x76,0xEE,0x7E,0x08,0x08,0x20,
+    0x96,0xEE,0xF4,0xDD,0x7E,0xF8,0x80,0x00,0x55,0xEE,0xD3,0xD5,0x57,0xFA,0x8A,0x00,
+    0x55,0xEE,0xF3,0xDD,0xFD,0xFD,0x2C,0x02,0x75,0xEE,0x14,0xDE,0xAB,0xB5,0xFA,0x0A,
+    0x96,0xEE,0x34,0xE6,0x2B,0xBD,0xF5,0x7A,0xD6,0xF6,0x55,0xE6,0x0A,0xAF,0xED,0xF5,
+    0xF8,0xF6,0x96,0xEE,0x0A,0xAB,0xBF,0xD5,0xF7,0xF6,0xB6,0xF6,0xA2,0xAA,0x2B,0xA7,
+    0xF8,0xF6,0xB6,0xEE,0x7B,0xFA,0xE8,0xAA,0xD7,0xF6,0xB7,0xEE,0xE7,0xAF,0x22,0x02,
+    0xD7,0xF6,0x96,0xEE,0xFE,0x6A,0xF0,0x20,0xD7,0xF6,0x96,0xEE,0x8D,0xAD,0xF7,0xBE,
+    0xF7,0xF6,0xB7,0xEE,0x2F,0xBB,0xAB,0xAB,0x18,0xFF,0xD7,0xF6,0xFF,0xBF,0x2B,0xAE,
+    0x18,0xF7,0xF8,0xF6,0xAD,0xD6,0xD6,0xEE,0x18,0xF7,0xF8,0xF6,0x27,0x95,0xD5,0xF7,
+    0x39,0xFF,0xF7,0xF6,0x02,0x2B,0x0B,0xB7,0x38,0xFF,0xF8,0xF6,0xE0,0xA8,0x20,0x02,
+    0x18,0xFF,0xD7,0xEE,0xFE,0xF8,0xFC,0x78,0xB7,0xF6,0xD7,0xEE,0xFD,0xDB,0xFF,0xBB,
+    0xB6,0xEE,0x76,0xE6,0x28,0xB8,0x58,0x58,0xD7,0xF6,0x96,0xEE,0x80,0x8A,0x09,0x0D,
+    0xD7,0xF6,0x96,0xEE,0xE2,0xE2,0x6A,0x7A,0xB6,0xEE,0x55,0xE6,0x62,0x6E,0xEE,0xEF,
+    0x75,0xEE,0xD3,0xD5,0x6A,0x6A,0x7A,0x78,0x71,0xCD,0xEF,0xBC,0x3C,0x16,0x34,0xD4,
+    0x55,0xEE,0xB2,0xD5,0x83,0x0B,0x09,0x0D,0x55,0xE6,0xF3,0xDD,0x57,0x5E,0x5C,0x5E,
+    0x34,0xE6,0xF4,0xDD,0x89,0xBD,0xAF,0xBD,0x34,0xE6,0x30,0xC5,0x5E,0x5C,0x5A,0x58,
+    0x75,0xEE,0x30,0xC5,0x2D,0x2D,0x2D,0xBD,0xB6,0xF6,0x14,0xDE,0x77,0x80,0x80,0x22,
+    0x96,0xEE,0xF4,0xDD,0x7F,0xFA,0xA0,0x08,0x75,0xEE,0xF3,0xDD,0x57,0xFF,0xA8,0x00,
+    0x55,0xE6,0xF3,0xDD,0x5F,0x77,0xFF,0xF8,0x14,0xDE,0x31,0xC5,0x62,0xC8,0x80,0x00,
+    0x96,0xF6,0xB6,0xEE,0xA5,0xD7,0x75,0x75,0xB6,0xEE,0x76,0xEE,0x5D,0xEE,0xAA,0xA0,
+    0x95,0xEE,0x55,0xE6,0xFE,0xBE,0x08,0x00,0xB6,0xEE,0x55,0xE6,0xDD,0xFF,0xAE,0x8B,
+    0xB6,0xEE,0x55,0xE6,0x57,0xBF,0xAA,0x02,0xB6,0xEE,0x54,0xE6,0xF5,0xBA,0xAA,0xA0,
+    0xB6,0xEE,0x55,0xE6,0x7F,0xBF,0xAA,0x88,0xB6,0xEE,0x55,0xE6,0xD7,0xFF,0xAA,0x00,
+    0xB6,0xEE,0x75,0xE6,0xD5,0xBF,0xAF,0x80,0xB6,0xEE,0x75,0xE6,0x5D,0xFA,0xFA,0x8A,
+    0xB6,0xEE,0x75,0xEE,0x5F,0xBA,0xAA,0x0A,0xB6,0xF6,0x75,0xE6,0xF7,0xAF,0x8A,0x20,
+    0x96,0xEE,0x75,0xEE,0xFF,0x88,0x80,0x80,0x96,0xEE,0x75,0xEE,0xFE,0xC8,0x08,0x20,
+    0x96,0xEE,0x75,0xEE,0xB7,0x8A,0x20,0x28,0xB6,0xEE,0x75,0xEE,0xDD,0xFA,0xFF,0xDE,
+    0x96,0xEE,0x75,0xEE,0xA8,0xAE,0xFE,0x2E,0x76,0xF6,0x96,0xEE,0x7D,0x7F,0x7F,0xF9,
+    0xB6,0xF6,0x96,0xEE,0x7F,0x72,0xC2,0x86,0xB6,0xF6,0x96,0xEE,0x79,0xAA,0x2A,0x02,
+    0xB6,0xF6,0x96,0xEE,0xFF,0x0B,0x3E,0xA0,0xD6,0xF6,0x96,0xEE,0x9D,0xFF,0x08,0x2A,
+    0xD6,0xF6,0x96,0xEE,0xFF,0xAA,0xAA,0x2A,0xD6,0xF6,0x96,0xEE,0xDF,0xF7,0xB3,0xBA,
+    0xD6,0xF6,0x96,0xEE,0xF5,0x5B,0xFE,0xCA,0x34,0xE6,0xAA,0x9B,0x60,0x70,0x60,0x60,
+    0x87,0x7A,0xA4,0x61,0x5C,0xFC,0xFE,0xFE,0xE5,0x69,0x84,0x61,0xFF,0x53,0xF8,0xAA,
+    0xC5,0x69,0x64,0x61,0x0A,0x2D,0x8A,0x0A,0x48,0x7A,0xC5,0x69,0x2B,0x8D,0xDD,0x55,
+    0x06,0x72,0xC6,0x69,0xBC,0xEE,0x88,0x00,0x88,0x82,0x06,0x72,0x15,0x55,0xD5,0xF5,
+    0x4B,0x9B,0x06,0x6A,0x2F,0xBD,0xFD,0xFD,0xD3,0xDD,0xE9,0x82,0x0A,0x0B,0x2D,0xB5,
+    0x96,0xF6,0xF3,0xDD,0x02,0x02,0x03,0x0D,0xB6,0xF6,0x96,0xEE,0xA8,0xA0,0xA2,0xAA,
+    0xD6,0xF6,0x96,0xEE,0xFE,0xFF,0xFF,0x3F,0xD6,0xF6,0x97,0xEE,0xEF,0xAF,0xAB,0xEA,
+    0xB7,0xF6,0xB5,0xEE,0xA8,0xAA,0xAA,0xAA,0xB6,0xF6,0x96,0xEE,0xEE,0xA2,0x20,0x88,
+    0xB6,0xF6,0x96,0xEE,0xEF,0x2A,0xAA,0x2A,0xD7,0xF6,0x96,0xEE,0xEB,0xBB,0xBA,0xAA,
+    0xB6,0xF6,0x96,0xEE,0x3C,0xBB,0xB8,0x08,0xB6,0xF6,0x96,0xEE,0x88,0xE2,0xA8,0x00,
+    0xB6,0xF6,0x96,0xEE,0x80,0x02,0x00,0xC0,0xB6,0xF6,0xD8,0xEE,0x00,0xA2,0x08,0xA0,
+    0xB6,0xF6,0xD6,0xEE,0xAA,0xE8,0xF8,0xB8,0xF7,0xF6,0xB6,0xEE,0x3F,0xBB,0xBF,0x2F,
+    0xD7,0xFE,0xF7,0xF6,0x5D,0x57,0x5F,0xDF,0xF7,0xFE,0xF7,0xF6,0xD7,0xF7,0x5F,0xDF,
+    0x17,0xFF,0xF7,0xF6,0x7D,0xFD,0xF5,0xF9,0xF6,0xFE,0xF7,0xF6,0x7D,0xF7,0xFF,0xDF,
+    0xF7,0xF6,0xD6,0xF6,0x2A,0x2A,0x22,0x88,0xD7,0xFE,0xF7,0xF6,0xF5,0x57,0xF5,0x95,
+    0xF7,0xFE,0xD7,0xF6,0xEB,0x8A,0xEA,0x5A,0xB6,0xF6,0xD3,0xDD,0x00,0x80,0xE0,0x70,
+    0x35,0xEE,0x8B,0x9B,0xA0,0xE8,0x7A,0x7E,0x6F,0xB4,0x87,0x7A,0x78,0x5E,0x57,0x55,
+    0x87,0x7A,0x47,0x7A,0x8A,0x80,0x0E,0xA7,0xA7,0x82,0x46,0x72,0xBD,0x6B,0x6A,0xAA,
+    0x87,0x7A,0x26,0x72,0xC2,0x5A,0x6A,0xE0,0x8B,0x9B,0x26,0x72,0x95,0x95,0x35,0x3D,
+    0xB7,0xF6,0x6E,0xB4,0x2D,0x2D,0x2D,0x2B,0x17,0xFF,0xD7,0xF6,0xAD,0x8F,0xAD,0xFB,
+    0x18,0xFF,0xF7,0xF6,0xBB,0xAB,0xAB,0xAA,0x17,0xFF,0xF8,0xF6,0xAA,0xEF,0x2E,0x2A,
+    0x18,0xFF,0xF7,0xF6,0xAB,0xAA,0xE8,0xA0,0x18,0xFF,0xF7,0xEE,0x82,0x82,0xA0,0x8A,
+    0xF7,0xF6,0xD7,0xF6,0x60,0xA0,0xE0,0xE0,0xF7,0xF6,0xD7,0xF6,0xAB,0xA8,0xA2,0xB8,
+    0xF7,0xF6,0xD7,0xF6,0xF3,0xD5,0xFF,0xFF,0xF7,0xF6,0xD7,0xF6,0x7F,0xBF,0xAD,0xED,
+    0xF7,0xF6,0xB6,0xEE,0xBF,0xAE,0xEA,0xFA,0xF7,0xF6,0xB6,0xEE,0xEA,0xAB,0xAE,0xFF,
+    0xF7,0xF6,0xD7,0xF6,0x7F,0xAF,0xAD,0xAD,0xF7,0xF6,0xD7,0xF6,0xD5,0x75,0x5F,0x7F,
+    0xB7,0xF6,0xF7,0xEE,0xAA,0xAA,0xBA,0xBE,0xD7,0xF6,0xF7,0xEE,0x00,0xB8,0x28,0x82,
+    0xF7,0xF6,0xD7,0xF6,0x69,0xFD,0x55,0x79,0xF7,0xF6,0xB6,0xEE,0xFE,0xAA,0xAF,0xAF,
+    0xF7,0xF6,0xD7,0xF6,0xD5,0xDF,0x1E,0x37,0x17,0xFF,0xD7,0xF6,0xBD,0xE9,0xAA,0xFE,
+    0xF7,0xF6,0x96,0xEE,0xE0,0xF8,0x68,0xFE,0xB6,0xF6,0x96,0xEE,0xAA,0xAA,0xFB,0xFB,
+    0x96,0xEE,0x55,0xEE,0x00,0x80,0xC0,0x80,0x96,0xEE,0x55,0xEE,0xC2,0xA2,0xF0,0x58,
+    0x55,0xE6,0x14,0xDE,0xA0,0xF8,0x5A,0x5F,0x34,0xE6,0xD3,0xD5,0xEC,0xDE,0xFE,0xDF,
+    0x55,0xE6,0xD3,0xD5,0x7F,0xBD,0xBF,0x0F,0xB7,0xF6,0x14,0xDE,0xAD,0x2B,0x23,0x0A,
+    0xF7,0xF6,0xB7,0xF6,0xD5,0x55,0xBB,0xBE,0xD7,0xF6,0xB6,0xF6,0xFF,0x8C,0xBE,0xEE,
+    0xD7,0xF6,0x96,0xEE,0xEF,0xF8,0xFA,0xFA,0xB7,0xF6,0x76,0xEE,0x7A,0xA0,0x20,0x02,
+    0xB6,0xF6,0x35,0xE6,0xDF,0xFA,0x00,0x00,0xD6,0xF6,0x55,0xE6,0xD5,0x75,0xE2,0x88,
+    0xB6,0xEE,0x75,0xEE,0x5F,0xAD,0xFB,0xB8,0xB6,0xEE,0x55,0xE6,0x5D,0xAA,0x00,0x00,
+    0xB6,0xEE,0x75,0xE6,0xBD,0xD7,0xFA,0xAC,0xD7,0xF6,0x76,0xE6,0x0B,0xAB,0xBF,0xDF,
+    0xF7,0xF6,0xB6,0xEE,0xAA,0x8A,0x2F,0x35,0xF7,0xF6,0xD7,0xF6,0xF5,0xBF,0xFB,0xBA,
+    0xF7,0xF6,0xB7,0xEE,0xFA,0xFA,0xA8,0xA2,0xD7,0xF6,0x97,0xEE,0x9E,0xEE,0xAA,0xA2,
+    0xF8,0xF6,0xB7,0xEE,0x2F,0xAD,0x3F,0xAB,0xD7,0xFE,0x18,0xF7,0xFF,0xFA,0xEF,0xAE,
+    0x18,0xFF,0xF8,0xF6,0xAE,0x3B,0xED,0x95,0x18,0xFF,0xF8,0xF6,0xFF,0xAB,0xAE,0xDE,
+    0x18,0xF7,0xF8,0xF6,0x37,0xB6,0x5E,0xF7,0x38,0xFF,0xF7,0xF6,0x82,0x22,0x2B,0xAF,
+    0x38,0xFF,0xF7,0xF6,0x5E,0x62,0x62,0x68,0xF7,0xF6,0x96,0xEE,0xBA,0xFA,0x7C,0x7E,
+    0xB6,0xEE,0x55,0xE6,0x7A,0x78,0xFE,0x7B,0xD7,0xF6,0x54,0xE6,0x0B,0x0B,0x2D,0x2D,
+    0xD7,0xF6,0x34,0xDE,0xA0,0xF8,0xFA,0x78,0x96,0xEE,0x34,0xE6,0x8F,0xBF,0xDD,0xF5,
+    0x55,0xE6,0x31,0xC5,0xE0,0x60,0x68,0x78,0x31,0xC5,0xD0,0xBC,0x9C,0x16,0x3F,0x2F,
+    0x55,0xE6,0x72,0xCD,0x09,0x2D,0x2D,0x2D,0x55,0xE6,0xB2,0xD5,0xFC,0xF8,0x58,0x7A,
+    0x14,0xDE,0xB2,0xD5,0x2A,0xAE,0x35,0x15,0x55,0xE6,0x10,0xBD,0x78,0x78,0x7A,0x78,
+    0x14,0xDE,0xF0,0xBC,0x2D,0x2D,0xBD,0xF5,0xB6,0xF6,0x92,0xCD,0x22,0x0A,0xAF,0xBD,
+    0x96,0xEE,0x55,0xEE,0xF8,0xE2,0xF2,0xFF,0x95,0xEE,0x55,0xE6,0xEB,0xFF,0xF7,0x55,
+    0x95,0xEE,0x55,0xE6,0x57,0x7B,0xFF,0x2F,0x96,0xEE,0x34,0xE6,0x5D,0x8E,0xAE,0xBE,
+    0xD6,0xF6,0xB6,0xEE,0x56,0xDE,0x6A,0x75,0xD6,0xF6,0xB6,0xEE,0x5D,0x75,0x6F,0xE5,
+    0xF6,0xF6,0x96,0xEE,0xDD,0xF5,0x7F,0x7E,0xD6,0xF6,0x96,0xEE,0xEB,0xFB,0xBA,0x7B,
+    0x96,0xF6,0xB6,0xEE,0x7F,0x77,0x9F,0x75,0xD5,0xF6,0x96,0xEE,0x7A,0xBB,0xEE,0xBA,
+    0xD7,0xF6,0x96,0xEE,0x7E,0xFE,0x3A,0x2A,0x96,0xF6,0xD6,0xEE,0xEA,0xBB,0xBB,0xBF,
+    0xB6,0xEE,0x96,0xEE,0xB0,0x80,0x88,0xB8,0xB6,0xEE,0x96,0xEE,0x2A,0x2E,0x2A,0x02,
+    0xD7,0xF6,0x96,0xEE,0xBF,0xFA,0xFA,0xEB,0x95,0xF6,0xD6,0xEE,0xAA,0xEF,0xBF,0xAF,
+    0xB6,0xEE,0x75,0xEE,0xFA,0xF8,0xE0,0xE0,0x96,0xEE,0x75,0xEE,0x00,0x0E,0x0E,0xA2,
+    0x96,0xEE,0x75,0xEE,0xA8,0xAE,0x32,0x28,0x96,0xF6,0x95,0xEE,0xD7,0xFF,0xFF,0xDF,
+    0xB6,0xFE,0x96,0xEE,0x57,0x57,0x5F,0xF7,0xB6,0xF6,0x75,0xEE,0xE6,0x2E,0xAB,0x2A,
+    0xD6,0xF6,0x96,0xEE,0xFF,0xBF,0xAB,0xAB,0xD7,0xF6,0xB6,0xF6,0xFD,0xD7,0xDD,0x2F,
+    0xD7,0xF6,0xB6,0xEE,0x7F,0xAE,0xCB,0xA8,0xB6,0xF6,0xD7,0xEE,0x8A,0xAE,0xEE,0xBE,
+    0xB6,0xF6,0xD6,0xEE,0xAA,0x2E,0xA9,0xFF,0xD7,0xF6,0xB6,0xF6,0x75,0xBD,0x1D,0xAB,
+    0xD7,0xF6,0xB6,0xF6,0x6A,0xE2,0xE8,0xBA,0x76,0xF6,0x8A,0x9B,0x60,0x60,0xE0,0xE0,
+    0xA8,0x82,0xA4,0x61,0xFE,0xFE,0x5C,0x7C,0x26,0x7A,0xC5,0x69,0x7B,0xDA,0xDE,0xE3,
+    0x06,0x72,0xA5,0x69,0xD7,0xF5,0xFE,0x62,0xE6,0x71,0x84,0x61,0x2F,0xAF,0xAD,0xAD,
+    0x27,0x7A,0xC5,0x69,0xBA,0xBB,0xAD,0x3D,0x27,0x72,0xE6,0x69,0x3B,0xBF,0x74,0x5A,
+    0x87,0x7A,0xE6,0x69,0x0A,0xAA,0xAF,0xF7,0x2D,0xAC,0x67,0x7A,0x2F,0xBD,0xFD,0xF5,
+    0x35,0xEE,0x8B,0x9B,0x02,0x03,0x2B,0x2D,0xB6,0xF6,0x76,0xF6,0xAA,0x8A,0xAA,0x83,
+    0xB6,0xF6,0x96,0xEE,0xA8,0xBE,0x23,0xA2,0xB6,0xF6,0x96,0xEE,0x02,0x80,0x82,0xA0,
+    0xD6,0xF6,0xB6,0xF6,0xD5,0xFB,0x5B,0xB5,0xB6,0xF6,0xD6,0xEE,0x28,0x80,0x08,0x02,
+    0xB6,0xF6,0xB7,0xEE,0x8A,0xA8,0x00,0x2A,0x96,0xF6,0xD7,0xEE,0xFA,0xEE,0xAB,0xEF,
+    0xB6,0xF6,0x96,0xEE,0x08,0x02,0x20,0xA8,0xB6,0xF6,0x96,0xEE,0x02,0x00,0x02,0xE8,
+    0xD7,0xF6,0x96,0xEE,0xAE,0xAE,0xAF,0xBB,0xD7,0xF6,0xB6,0xF6,0xDE,0xDE,0xB3,0x2B,
+    0xD6,0xF6,0xB6,0xEE,0xB4,0xA2,0x8B,0xEA,0xD7,0xF6,0xB6,0xEE,0x0A,0x0B,0x2B,0x3F,
+    0x17,0xFF,0xD7,0xF6,0xFF,0xBD,0xBE,0xAB,0x17,0xFF,0xF7,0xF6,0x5D,0x55,0x5F,0x5F,
+    0x18,0xFF,0xF7,0xF6,0xDD,0xF9,0xCF,0x6D,0x17,0xFF,0xF7,0xF6,0x7D,0x77,0xD5,0x75,
+    0xD6,0xFE,0xF7,0xF6,0x5D,0x55,0xD7,0xDF,0x18,0xFF,0xD7,0xF6,0xEA,0xEF,0xFF,0x7F,
+    0xF6,0xFE,0x14,0xE6,0x80,0xE0,0xF8,0x7A,0x34,0xE6,0xAB,0x9B,0x80,0xA0,0xE8,0x7A,
+    0xAF,0xBC,0x46,0x72,0x68,0x7C,0x5E,0x57,0x67,0x82,0x46,0x72,0xBB,0x2B,0x33,0x0A,
+    0x87,0x82,0x46,0x7A,0x3D,0x3F,0x8C,0x3A,0xC7,0x8A,0x87,0x82,0xF5,0xCE,0xAD,0x3D,
+    0xE8,0x8A,0x66,0x7A,0x7E,0xFB,0xF0,0x70,0x8E,0xBC,0x46,0x7A,0xB5,0xB5,0x35,0x25,
+    0xD7,0xFE,0x30,0xCD,0x2D,0x0D,0x09,0x2B,0xF7,0xFE,0x18,0xF7,0xE0,0xA0,0x88,0xA0,
+    0x17,0xFF,0xF7,0xF6,0xBE,0xAA,0x0A,0x0F,0x17,0xFF,0xF7,0xF6,0x2A,0x2A,0xBE,0x3F,
+    0x18,0xFF,0xF7,0xF6,0x8A,0x2A,0xAB,0xAE,0x18,0xFF,0xF7,0xF6,0xE3,0xFA,0xF8,0xB8,
+    0xF7,0xF6,0xD7,0xF6,0xA0,0xBC,0x2A,0x80,0xF7,0xF6,0xD7,0xF6,0xAA,0xAE,0x20,0x88,
+    0xF7,0xF6,0xD7,0xF6,0xBA,0xEA,0xAE,0xFA,0xF7,0xF6,0xD7,0xF6,0xF9,0xFF,0x5D,0x57,
+    0xD7,0xF6,0xB7,0xEE,0xA0,0x2A,0x83,0x88,0xD7,0xF6,0xB7,0xEE,0x2A,0xA2,0x82,0xAA,
+    0xD7,0xF6,0xD7,0xEE,0x00,0x8A,0x20,0x22,0xF7,0xF6,0xD7,0xF6,0x5F,0xF5,0xAD,0xBD,
+    0xF7,0xF6,0xD7,0xF6,0xBD,0x55,0x77,0xE5,0xD7,0xF6,0xF7,0xEE,0x0A,0x82,0x00,0x22,
+    0xF7,0xF6,0xD7,0xF6,0x7F,0x5D,0xFD,0x2B,0x17,0xFF,0xD7,0xF6,0x75,0xD7,0xF7,0x3F,
+    0x17,0xFF,0xD7,0xF6,0x2D,0xAF,0x8A,0x70,0xF7,0xF6,0xB6,0xEE,0xE0,0xF0,0x54,0x5F,
+    0x96,0xF6,0xD6,0xEE,0xBB,0xAF,0xBF,0x2A,0xB6,0xF6,0x76,0xEE,0xA2,0xFA,0xDE,0xDE,
+    0x96,0xEE,0x55,0xEE,0xA8,0x6A,0x78,0x78,0x75,0xEE,0x14,0xDE,0xF8,0x78,0x5A,0x5F,
+    0x35,0xE6,0xB2,0xD5,0xA2,0xFA,0x7E,0x5F,0x75,0xEE,0xB2,0xD5,0xF7,0xD5,0xB5,0x35,
+    0xB6,0xF6,0x14,0xDE,0xBD,0x2D,0x2A,0x02,0xD7,0xF6,0x96,0xEE,0x9D,0xFE,0xAA,0xAA,
+    0xD7,0xF6,0xB6,0xEE,0x0A,0x8B,0x2B,0x80,0xD7,0xF6,0xB7,0xEE,0xE0,0x80,0xA2,0xA0,
+    0xD7,0xF6,0x96,0xEE,0x6A,0xA8,0xA8,0x22,0xD7,0xF6,0x96,0xEE,0xAB,0xF9,0xBA,0xEA,
+    0xD6,0xF6,0x96,0xEE,0xAE,0xAE,0xA7,0xF7,0xD6,0xF6,0xB6,0xEE,0xAA,0xEB,0xE9,0xE5,
+    0xD6,0xF6,0xB6,0xEE,0x7E,0xDE,0xD0,0x5E,0xD7,0xF6,0xB6,0xEE,0x2D,0x0F,0xBF,0x57,
+    0xF7,0xF6,0x96,0xEE,0x7E,0xFA,0x2A,0x2B,0xF7,0xF6,0x96,0xEE,0x55,0x57,0x7A,0x80,
+    0xF7,0xF6,0x96,0xEE,0x27,0xBD,0xE5,0xFF,0xF7,0xF6,0xD7,0xF6,0xF2,0xE2,0x25,0x0D,
+    0x18,0xFF,0xD7,0xF6,0xFB,0xFF,0x7E,0xFA,0xF7,0xF6,0xB7,0xEE,0xB6,0xAF,0xFA,0xAA,
+    0xF8,0xF6,0xD7,0xF6,0xE5,0xCD,0x2B,0xC2,0xF8,0xF6,0xD7,0xEE,0xDA,0xBB,0xBF,0xAE,
+    0xF8,0xF6,0xD7,0xEE,0x3B,0xF2,0xF8,0x58,0x18,0xF7,0xD7,0xF6,0xAA,0xAB,0xAF,0xAD,
+    0x17,0xF7,0xF8,0xF6,0xF6,0x7A,0xFA,0x5D,0x18,0xF7,0xD7,0xF6,0x2A,0xBA,0xEE,0xD5,
+    0x38,0xFF,0xF7,0xF6,0xEA,0xFA,0xF5,0x75,0xF7,0xF6,0x96,0xEE,0x7A,0x78,0x78,0x78,
+    0x96,0xEE,0x55,0xE6,0x62,0xFA,0xFA,0x7A,0xD7,0xF6,0x34,0xDE,0x2F,0xB7,0xB5,0xB5,
+    0xB6,0xEE,0x14,0xE6,0xF0,0xE0,0x60,0x40,0x55,0xE6,0x14,0xDE,0x0D,0xA7,0x35,0xFD,
+    0x55,0xE6,0x51,0xC5,0x78,0x58,0x78,0x7A,0x10,0xC5,0xF0,0xBC,0x25,0x2E,0x36,0x14,
+    0x34,0xE6,0x71,0xCD,0x2D,0x29,0xAD,0x2D,0x34,0xE6,0x92,0xCD,0xE0,0xE8,0xE2,0x60,
+    0xF3,0xDD,0x92,0xCD,0x2F,0x2E,0xB5,0xBD,0xF4,0xDD,0x30,0xC5,0x70,0x60,0x40,0xC0,
+    0x10,0xC5,0x6D,0xAC,0x2E,0x9F,0xDF,0xBE,0x55,0xE6,0x31,0xC5,0x2F,0x0D,0x29,0x0B,
+    0x96,0xEE,0x55,0xE6,0xFF,0x6B,0x7A,0xE0,0x75,0xEE,0x55,0xE6,0x57,0x55,0xB7,0xE6,
+    0x75,0xEE,0x55,0xE6,0x09,0xFD,0x27,0x37,0x96,0xEE,0x75,0xEE,0x5D,0x3F,0xBD,0xF5,
+    0xD7,0xF6,0x96,0xEE,0xEF,0xBE,0xAB,0xEF,0xD6,0xF6,0xB6,0xEE,0xAF,0xBF,0xFD,0xD7,
+    0xD6,0xF6,0xB6,0xEE,0x5F,0x57,0x57,0x7B,0xD6,0xF6,0xB6,0xEE,0xDD,0xF7,0x6D,0xFD,
+    0xD6,0xF6,0xB6,0xEE,0xFD,0x75,0x7D,0xF3,0xD6,0xF6,0xB6,0xEE,0xBF,0xEA,0xBD,0xFF,
+    0xD7,0xF6,0xB6,0xEE,0xD1,0x9F,0x5F,0x7F,0xD7,0xF6,0xB6,0xEE,0xDF,0xF7,0xDD,0xF5,
+    0xD7,0xF6,0xB6,0xEE,0x57,0xED,0xFF,0xE4,0xD7,0xF6,0xB6,0xEE,0x77,0x7F,0xF5,0xFD,
+    0xD7,0xF6,0xB6,0xEE,0x75,0xD5,0xF7,0xFF,0xD6,0xF6,0x96,0xEE,0x7A,0xEA,0xEA,0xEA,
+    0xB6,0xEE,0x96,0xEE,0x68,0x76,0x5E,0x76,0xB6,0xF6,0x75,0xEE,0xFF,0xAF,0xA7,0xBF,
+    0x75,0xF6,0x95,0xEE,0x7D,0x75,0x5D,0x57,0x76,0xF6,0x95,0xEE,0x55,0x75,0x5F,0x7D,
+    0xB6,0xF6,0x95,0xEE,0xAE,0xF6,0x3B,0xFA,0x96,0xF6,0xB6,0xEE,0xFF,0xFF,0xBB,0xBB,
+    0xB6,0xF6,0xD7,0xEE,0xA8,0xAA,0xAA,0xB8,0xD7,0xF6,0xB6,0xEE,0x2B,0x0A,0xAA,0x82,
+    0xD7,0xF6,0xB6,0xEE,0xF8,0xE2,0xEA,0x98,0xF7,0xF6,0xB6,0xEE,0x77,0xAF,0xAB,0xAF,
+    0xD7,0xF6,0xB6,0xEE,0xAF,0xAA,0x88,0x2A,0xD7,0xF6,0xB6,0xF6,0xE7,0xB5,0xDE,0xAE,
+    0xD7,0xF6,0x95,0xF6,0xEA,0xFA,0xFA,0xE8,0x75,0xEE,0x29,0x93,0xE0,0xE0,0x78,0x78,
+    0xC8,0x8A,0xA5,0x61,0x7C,0xDE,0x56,0x57,0x26,0x7A,0xE5,0x69,0xEF,0x8D,0xAD,0x2D,
+    0x26,0x7A,0xC5,0x69,0x7B,0xFC,0x80,0x82,0xC5,0x69,0x64,0x61,0x2A,0xF8,0xFC,0xB0,
+    0x06,0x72,0x84,0x61,0x2B,0x2F,0xBF,0xDF,0x27,0x72,0xC5,0x69,0xE2,0xFA,0xEA,0x75,
+    0x26,0x72,0xC5,0x69,0x2C,0xBA,0xAF,0xB6,0xE8,0x82,0xE5,0x69,0x2F,0x2F,0xBD,0xF5,
+    0xD2,0xDD,0x08,0x8B,0x2D,0xB5,0xF5,0xD5,0x95,0xF6,0xEE,0xBC,0x00,0x02,0x0B,0x29,
+    0xB6,0xF6,0x96,0xEE,0xA0,0x88,0x00,0x00,0xD5,0xF6,0xB6,0xF6,0x5D,0x5D,0xF7,0xBF,
+    0xD6,0xF6,0xB6,0xF6,0xEB,0xE7,0xEF,0xFA,0xD6,0xF6,0xB6,0xF6,0xDD,0xF7,0xDA,0xAA,
+    0xF6,0xF6,0xB6,0xF6,0x55,0x55,0x5F,0x5F,0xB6,0xF6,0xB7,0xEE,0x08,0xA0,0x2A,0xA2,
+    0xD7,0xF6,0x96,0xEE,0xFE,0xFA,0xBE,0xAA,0xB6,0xF6,0xD7,0xEE,0x02,0x82,0x80,0x00,
+    0xD7,0xF6,0xB6,0xF6,0x59,0x57,0xF5,0xDD,0xD7,0xF6,0xB6,0xF6,0xAF,0x8D,0x37,0x9D,
+    0xD7,0xF6,0xB6,0xEE,0x22,0x28,0x60,0xE2,0xF7,0xF6,0xB6,0xEE,0xBF,0x2B,0xBB,0x3F,
+    0x17,0xFF,0xD6,0xF6,0xAB,0xEF,0xFF,0xDE,0xF7,0xF6,0xD6,0xF6,0x80,0x22,0x02,0xAA,
+    0x17,0xFF,0xF7,0xF6,0x75,0x5D,0x5D,0x7F,0x17,0xFF,0xF7,0xF6,0xB5,0xDD,0xF5,0x75,
+    0xF7,0xFE,0xD6,0xF6,0xEB,0xA8,0xAA,0xBC,0xF7,0xFE,0x34,0xE6,0xA0,0xA0,0xE8,0x7A,
+    0x75,0xEE,0x4D,0xB4,0xA0,0xE0,0xF8,0x7E,0xEF,0xC4,0x66,0x7A,0x60,0x78,0x5E,0x57,
+    0x67,0x7A,0x05,0x6A,0xBE,0x86,0x8A,0x02,0x67,0x7A,0x06,0x72,0x28,0x20,0x2A,0xDE,
+    0xA8,0x8A,0x46,0x7A,0xBF,0x8D,0x8A,0x83,0xC8,0x8A,0x67,0x82,0x27,0xA5,0xAE,0x8B,
+    0xC8,0x8A,0x66,0x7A,0x80,0xB0,0x9A,0xF2,0x11,0xCD,0x67,0x7A,0x35,0x35,0x25,0x2D,
+    0xF7,0xFE,0xD3,0xDD,0x09,0x29,0x0B,0x0B,0x17,0xFF,0xF8,0xF6,0xAE,0xAA,0xBA,0x72,
+    0x18,0xFF,0xF7,0xF6,0xAA,0xBA,0xAA,0xAA,0xF7,0xFE,0x18,0xF7,0x7B,0x7E,0x79,0x5F,
+    0x38,0xFF,0x17,0xF7,0x75,0xF7,0xFF,0xDB,0x17,0xFF,0xF7,0xF6,0xA0,0xEB,0xEE,0xEB,
+    0xF7,0xF6,0xF7,0xF6,0x00,0x00,0x00,0x00,0xF7,0xF6,0xD7,0xF6,0xAA,0xAA,0xA2,0x5A,
+    0xF7,0xF6,0xD7,0xF6,0xAB,0x8B,0x7D,0x5F,0xF7,0xF6,0xD7,0xF6,0x57,0x7F,0x7A,0x5B,
+    0xD7,0xF6,0xF6,0xEE,0x00,0xA2,0xA2,0xA8,0xD7,0xF6,0xD6,0xEE,0xAA,0x20,0x0A,0x08,
+    0xF7,0xF6,0xB6,0xEE,0xBA,0x7A,0xBA,0xBE,0xF7,0xF6,0xD7,0xF6,0x65,0x7F,0x79,0xAA,
+    0xD7,0xF6,0xF7,0xEE,0xA0,0x00,0x80,0xA0,0xF6,0xF6,0xD7,0xF6,0xDD,0xF5,0x57,0xAF,
+    0xF7,0xF6,0xB6,0xEE,0x03,0x0F,0x21,0x02,0x18,0xFF,0xF7,0xF6,0xA5,0x89,0x83,0xC0,
+    0x18,0xF7,0xD7,0xF6,0x78,0x5E,0x5F,0x57,0x95,0xF6,0xD6,0xEE,0xFD,0xAB,0xAF,0xBB,
+    0x76,0xF6,0xB6,0xEE,0xFD,0xAD,0xBF,0x2E,0x96,0xF6,0x55,0xE6,0xAA,0xFA,0xAA,0x7B,
+    0x75,0xEE,0x14,0xDE,0xA8,0xF8,0xFE,0x7F,0x34,0xE6,0x92,0xCD,0xE8,0xE8,0xF8,0x7E,
+    0x14,0xDE,0x51,0xC5,0xFE,0xFE,0xB7,0x25,0x96,0xEE,0x92,0xD5,0x2D,0x0B,0x02,0x00,
+    0xD7,0xF6,0xB6,0xEE,0x95,0xBF,0xBF,0x88,0xD7,0xF6,0xB6,0xEE,0x33,0x82,0xA0,0x80,
+    0xD7,0xF6,0xB6,0xEE,0x80,0xB0,0x3E,0xAC,0xD7,0xF6,0xB6,0xEE,0x0B,0x8E,0xA8,0xA2,
+    0xD7,0xF6,0xB7,0xEE,0xA2,0xA2,0x08,0xBA,0xD7,0xF6,0xB6,0xEE,0xEB,0xEA,0xAA,0xEA,
+    0xD7,0xF6,0x96,0xEE,0xFF,0xFA,0xEA,0xBA,0xD7,0xF6,0x96,0xEE,0xA7,0xFF,0xEA,0xAA,
+    0x97,0xFE,0xB6,0xEE,0xD5,0x5F,0x75,0x5F,0x96,0xF6,0xB6,0xEE,0x77,0x57,0xD5,0xF5,
+    0xD7,0xF6,0x96,0xEE,0x2E,0x3F,0xBD,0xBF,0xF7,0xF6,0xB7,0xEE,0x02,0x02,0x2F,0x2D,
+    0x18,0xFF,0xD7,0xF6,0x5F,0xFE,0xAA,0x2A,0x17,0xF7,0xB8,0xF6,0xAB,0xAA,0xAA,0x02,
+    0x18,0xFF,0xF7,0xF6,0x6E,0x6F,0xCB,0x02,0x18,0xF7,0xD7,0xF6,0xFF,0xFB,0xF8,0xF8,
+    0xF7,0xF6,0xD7,0xEE,0xA2,0xFA,0x68,0xA2,0xF8,0xF6,0xD7,0xEE,0x2C,0x2A,0x03,0x2A,
+    0x18,0xF7,0xB7,0xF6,0xDA,0xF8,0xEE,0xEA,0xF8,0xF6,0xD7,0xF6,0x8D,0x88,0xE3,0xDB,
+    0xF8,0xF6,0xD7,0xF6,0x00,0x21,0xAC,0xFE,0xF7,0xF6,0xD7,0xF6,0xFD,0xF8,0x78,0x5A,
+    0xF8,0xF6,0xB7,0xEE,0xAA,0xBE,0xFF,0xF6,0xD7,0xF6,0x96,0xEE,0xE0,0x68,0xE8,0xAA,
+    0x96,0xEE,0x34,0xDE,0xBA,0x6E,0x78,0x78,0x96,0xEE,0x13,0xDE,0x3D,0x27,0xB5,0xB5,
+    0xD7,0xF6,0x54,0xE6,0x62,0xE2,0xE0,0xAA,0x75,0xEE,0x14,0xDE,0x7D,0xFE,0xAA,0xAC,
+    0x55,0xE6,0x71,0xCD,0x7A,0x58,0x78,0x78,0x51,0xC5,0xEF,0xBC,0x96,0xB8,0x20,0x00,
+    0x13,0xDE,0x51,0xC5,0x29,0x29,0xAD,0xBD,0x55,0xE6,0xB2,0xD5,0x7A,0xF2,0x7A,0x6B,
+    0xB2,0xD5,0x72,0xCD,0x2E,0xAF,0xBF,0x2F,0xF3,0xDD,0x71,0xCD,0x62,0x43,0xE2,0x82,
+    0xD3,0xD5,0xAE,0xB4,0xD5,0x37,0x2F,0x2E,0xD6,0xF6,0xB2,0xD5,0xAD,0x2B,0x0B,0x2B,
+    0xB6,0xF6,0x55,0xE6,0xFA,0xF8,0x60,0xE0,0x76,0xE6,0x35,0xE6,0xFE,0xF6,0xD7,0xDE,
+    0x55,0xEE,0x34,0xE6,0x08,0x2C,0x5E,0x55,0x96,0xEE,0x34,0xE6,0xAB,0x2B,0xAF,0xAD,
+    0xD6,0xF6,0xB6,0xEE,0xD5,0xA5,0xFD,0x95,0xD6,0xF6,0xB6,0xEE,0x7D,0x7E,0x5E,0x75,
+    0xD6,0xF6,0xB6,0xEE,0x72,0x5B,0x95,0xA9,0xD6,0xF6,0xB6,0xEE,0xDF,0xB6,0xBE,0x77,
+    0xD6,0xF6,0xB6,0xEE,0x4D,0x8B,0xAB,0xFD,0xD6,0xF6,0x96,0xEE,0xAE,0x8A,0x82,0x8F,
+    0xD6,0xF6,0xB6,0xEE,0xFB,0xE9,0xB5,0x5B,0xD6,0xF6,0xB6,0xEE,0xFD,0xAE,0x39,0x77,
+    0xD6,0xF6,0xB6,0xEE,0xBE,0x3F,0xBA,0xAA,0xD6,0xF6,0xB6,0xEE,0xAF,0xE7,0xFF,0xD6,
+    0xD7,0xF6,0xB6,0xEE,0xEE,0xEB,0x7B,0xEF,0xD6,0xF6,0xB6,0xEE,0xFB,0xFF,0x7A,0xFE,
+    0xD6,0xEE,0x75,0xEE,0xFE,0xDE,0xFF,0xF8,0xB6,0xF6,0x75,0xEE,0xFA,0xBA,0xEA,0xFA,
+    0xB5,0xF6,0x55,0xE6,0xAA,0xA2,0xAA,0xEA,0xB6,0xF6,0x95,0xEE,0xDF,0xFD,0xBB,0x6A,
+    0xB5,0xEE,0x95,0xEE,0xAF,0xFB,0xFF,0xF9,0xB7,0xF6,0x96,0xEE,0xF9,0xDF,0xD7,0xAD,
+    0xD6,0xF6,0xB6,0xEE,0xAF,0x8D,0xBD,0xB5,0xD7,0xF6,0xB6,0xEE,0xA2,0x8E,0x0A,0x02,
+    0xD7,0xF6,0xF7,0xEE,0x00,0x20,0x88,0x88,0xD6,0xF6,0xB7,0xE6,0x0A,0x22,0x20,0x82,
+    0xF7,0xF6,0xB6,0xEE,0xFE,0xBE,0xAA,0xEA,0xD6,0xF6,0xB7,0xF6,0xAE,0xAA,0x00,0xA8,
+    0xD7,0xFE,0x34,0xEE,0xE0,0xC8,0x60,0x6A,0xF2,0xDD,0x46,0x72,0x78,0x7C,0x5E,0x5E,
+    0x47,0x7A,0x85,0x61,0xFA,0xE2,0xE8,0xF0,0x26,0x72,0x43,0x59,0x0A,0xAB,0xAF,0x95,
+    0x26,0x72,0xE6,0x71,0xEA,0x63,0xFB,0xD7,0x06,0x72,0xA5,0x69,0x55,0x7E,0x68,0xEA,
+    0xA5,0x69,0x64,0x61,0xC0,0xF9,0x57,0x5C,0xC5,0x69,0x85,0x61,0x0A,0x8B,0xBB,0xFF,
+    0xE6,0x69,0x64,0x59,0x2A,0x8A,0x2B,0x29,0x46,0x72,0xC5,0x61,0x2F,0x2D,0xBF,0xD7,
+    0x69,0x93,0x26,0x72,0x2F,0xBD,0xBD,0xF5,0x35,0xEE,0x29,0x8B,0x0B,0x0D,0x2D,0xB5,
+    0xD7,0xFE,0x55,0xEE,0xAA,0x2A,0x0B,0x2D,0xD7,0xF6,0xB6,0xF6,0x75,0x5B,0xFA,0xAA,
+    0xD6,0xF6,0xB6,0xF6,0xFD,0xA5,0x87,0x8F,0xD6,0xF6,0xB6,0xF6,0xAD,0xBF,0xA3,0x0A,
+    0xD6,0xF6,0xB6,0xF6,0xA8,0xAA,0xBE,0x97,0xD6,0xF6,0xB6,0xF6,0xD4,0x7C,0x5C,0x77,
+    0xB6,0xF6,0xD7,0xEE,0x0A,0x02,0x08,0x08,0xB6,0xF6,0x96,0xEE,0x08,0x0A,0x88,0x00,
+    0xB6,0xF6,0xD6,0xEE,0xA0,0x00,0x08,0x28,0xD7,0xF6,0xB6,0xF6,0xAF,0xBD,0xB5,0xEF,
+    0xD6,0xF6,0xB6,0xEE,0xA0,0x7A,0x3A,0xAF,0xF7,0xF6,0xD6,0xF6,0x9D,0xDD,0xBF,0xB7,
+    0xD7,0xFE,0xF7,0xF6,0xDF,0x7D,0x57,0x55,0xF6,0xFE,0xF7,0xF6,0xFD,0x7F,0xF7,0xFD,
+    0xD7,0xFE,0xF7,0xF6,0x55,0x55,0x7D,0xFD,0xF7,0xFE,0xD7,0xF6,0xA8,0xAE,0xAB,0x82,
+    0xF7,0xFE,0x55,0xEE,0xA0,0xA8,0xE0,0x7A,0xB6,0xF6,0xAF,0xBC,0xA0,0xE8,0xFA,0x7A,
+    0x30,0xCD,0x66,0x7A,0xE0,0x78,0x5E,0x5F,0x66,0x7A,0x05,0x72,0xA0,0xDA,0xFE,0xAE,
+    0x66,0x7A,0x26,0x7A,0x8A,0x9B,0x9E,0xBA,0x46,0x82,0x26,0x7A,0x7F,0xFF,0xAD,0xB3,
+    0x87,0x8A,0x26,0x7A,0x2B,0xA9,0xAB,0x8A,0xA8,0x8A,0x67,0x82,0xBA,0xF3,0xB3,0xFE,
+    0x87,0x82,0x46,0x7A,0xA0,0xE2,0x7A,0x38,0x14,0xE6,0x09,0x93,0x35,0xAD,0x2D,0x2D,
+    0xF7,0xFE,0x55,0xEE,0x0D,0x01,0x03,0x03,0x17,0xFF,0xF7,0xF6,0xF0,0xAA,0xEA,0xCA,
+    0x17,0xFF,0xF8,0xF6,0xAB,0xB8,0xAE,0xAB,0x38,0xFF,0xF7,0xF6,0xAF,0xAB,0xED,0xAB,
+    0x18,0xFF,0x17,0xF7,0xEF,0xBB,0xFE,0xBE,0x36,0xFF,0x18,0xF7,0x5D,0x77,0xF7,0xFF,
+    0x37,0xF7,0xD7,0xF6,0xDE,0x7F,0xD7,0x5F,0xF7,0xF6,0xD7,0xF6,0xE8,0xA2,0xAF,0xBF,
+    0xF7,0xF6,0xD7,0xF6,0x7A,0xF2,0xBB,0xBD,0xF7,0xF6,0xD7,0xF6,0xFD,0x7D,0xD7,0xFD,
+    0xF7,0xF6,0xD7,0xF6,0xFD,0xFD,0xD6,0x56,0xF7,0xF6,0xD7,0xF6,0xD7,0x75,0xD7,0x7F,
+    0xD7,0xF6,0xB7,0xEE,0x20,0x00,0x68,0x80,0xF7,0xF6,0xB7,0xF6,0x22,0xAA,0xA9,0xAF,
+    0xF7,0xF6,0xD7,0xF6,0x75,0xF5,0x97,0xAF,0x37,0xFF,0xD7,0xF6,0x75,0xF7,0xF5,0xB7,
+    0x18,0xFF,0xD7,0xF6,0x2F,0x8A,0x82,0xC0,0x17,0xFF,0xB6,0xEE,0xA8,0xFA,0x7E,0xD7,
+    0xB6,0xF6,0xD6,0xEE,0x2D,0x2B,0x0A,0x80,0xB6,0xF6,0x75,0xEE,0xE8,0x6A,0xFC,0xFA,
+    0x96,0xEE,0x75,0xEE,0xE0,0x68,0x4C,0xFA,0x75,0xEE,0x14,0xE6,0xA0,0x78,0xF8,0x7E,
+    0x35,0xE6,0xB3,0xD5,0xC8,0xE2,0xFA,0xDE,0x14,0xDE,0x71,0xCD,0x7E,0xDF,0x97,0x2D,
+    0xB6,0xF6,0x92,0xCD,0xA5,0x2F,0x22,0x02,0xD7,0xF6,0x96,0xEE,0x09,0x0A,0x02,0x08,
+    0xD7,0xF6,0xD6,0xEE,0x20,0x22,0x22,0x00,0xF7,0xF6,0xB6,0xEE,0xAB,0xBB,0xAE,0xB3,
+    0xD7,0xF6,0xF7,0xEE,0x00,0x00,0x8A,0x0A,0xD7,0xF6,0xB6,0xEE,0x80,0x00,0xA0,0xC0,
+    0xD7,0xF6,0xB7,0xEE,0x28,0x22,0xE8,0xEA,0xD7,0xF6,0xB7,0xEE,0xFC,0x57,0x76,0xEF,
+    0xD7,0xF6,0xB6,0xEE,0x97,0x8F,0x2F,0x2A,0xD7,0xF6,0xB7,0xEE,0xE3,0xA2,0xA2,0x22,
+    0xD7,0xF6,0xB6,0xEE,0x5F,0xEA,0xF2,0xFE,0xD7,0xF6,0xB6,0xEE,0x5F,0x5E,0x5E,0x7E,
+    0xB6,0xEE,0x96,0xEE,0xA3,0xFE,0x3A,0x00,0xF7,0xF6,0x96,0xEE,0x2F,0xBD,0xBF,0xFD,
+    0x17,0xFF,0xB7,0xEE,0xAA,0x2E,0xAF,0xFD,0x18,0xFF,0xF7,0xF6,0xBB,0x0B,0x0A,0x2B,
+    0x38,0xFF,0x18,0xF7,0xF7,0xEF,0xCB,0xEB,0x39,0xFF,0xF7,0xF6,0x7E,0xFA,0xEA,0x8B,
+    0x18,0xFF,0xD7,0xEE,0xFF,0xBF,0xBE,0xF8,0x18,0xF7,0xF8,0xF6,0x55,0x5F,0xD5,0xFD,
+    0xF8,0xF6,0xD7,0xF6,0xAA,0xA8,0xB0,0x80,0xF8,0xF6,0xD7,0xF6,0x55,0xB7,0xCF,0x6B,
+    0xF7,0xF6,0xD7,0xF6,0xBE,0x0A,0x0A,0x09,0xF7,0xF6,0xB7,0xEE,0x68,0xE0,0x78,0x7A,
+    0xD7,0xF6,0xB7,0xEE,0x8D,0x02,0x82,0xAB,0xD7,0xF6,0xB7,0xEE,0xEA,0x88,0xAA,0xAA,
+    0xB6,0xEE,0x55,0xE6,0x58,0x78,0x68,0xE0,0x55,0xE6,0xF3,0xD5,0x26,0x37,0x1F,0x16,
+    0xD7,0xF6,0x96,0xEE,0x2B,0xA9,0x2B,0x2D,0xB7,0xEE,0x34,0xE6,0x5E,0x7C,0x78,0x58,
+    0x34,0xE6,0x92,0xCD,0x70,0x78,0x70,0x78,0x92,0xD5,0x30,0xC5,0xFB,0x6A,0x68,0xB0,
+    0xD3,0xDD,0x51,0xC5,0x2D,0x2D,0x3D,0xA7,0x14,0xDE,0xB2,0xD5,0x82,0xC2,0x42,0xC2,
+    0xB2,0xD5,0x30,0xC5,0x2A,0xBE,0x9F,0xD6,0xF4,0xDD,0x51,0xCD,0x82,0x8B,0xCB,0x7D,
+    0xF3,0xDD,0x31,0xC5,0x37,0x2E,0xA6,0xAD,0xB6,0xF6,0xF3,0xDD,0x0B,0x29,0x09,0x0B,
+    0xD7,0xF6,0x75,0xEE,0x7A,0xFA,0xFA,0xCA,0x96,0xEE,0x34,0xE6,0xFE,0x56,0x5A,0xFC,
+    0x55,0xE6,0x34,0xE6,0x09,0x25,0x9D,0xFE,0x96,0xEE,0x34,0xE6,0xAD,0xAB,0xAF,0xAF,
+    0xD6,0xF6,0xB6,0xEE,0xAF,0xBB,0x7D,0x7D,0xD5,0xF6,0xB6,0xEE,0x57,0x75,0xF5,0xF7,
+    0xD6,0xF6,0xB6,0xEE,0xD9,0xDF,0xFA,0xEB,0xD6,0xF6,0xB6,0xEE,0xD9,0x7A,0xAE,0xA7,
+    0xD6,0xF6,0xB6,0xEE,0x7F,0x6B,0xAB,0x8D,0xD6,0xF6,0xB6,0xEE,0xAD,0xCF,0xFE,0xFE,
+    0xD6,0xF6,0x96,0xEE,0x6A,0xAA,0x32,0x38,0xD6,0xF6,0xB6,0xEE,0xE3,0xEA,0xDA,0x7E,
+    0xD6,0xF6,0xB6,0xEE,0xDD,0x57,0xD6,0xB7,0xB6,0xF6,0xD7,0xEE,0xEB,0xEB,0xEA,0xFB,
+    0xD7,0xF6,0xB6,0xEE,0xFF,0xFE,0x7E,0x5A,0xD6,0xF6,0xB6,0xEE,0xAF,0x2B,0xAB,0xFE,
+    0xB6,0xEE,0x95,0xEE,0xF8,0xA0,0x78,0x50,0xB6,0xF6,0x95,0xEE,0x77,0xEE,0xEB,0xF7,
+    0xB6,0xF6,0x75,0xEE,0x6F,0x3E,0xAF,0x3A,0xB5,0xF6,0x96,0xEE,0x0B,0xCA,0xBA,0x7E,
+    0x95,0xF6,0xB6,0xEE,0xFF,0xFB,0xFA,0xAE,0x96,0xF6,0xB6,0xEE,0xE5,0xFD,0x7B,0x5E,
+    0xD6,0xF6,0xB6,0xEE,0x95,0xB5,0xAB,0xBA,0xD7,0xF6,0xB6,0xE6,0x80,0x22,0xA2,0x20,
+    0xD7,0xF6,0xF6,0xEE,0x20,0x22,0x28,0x00,0xD7,0xF6,0xB6,0xEE,0x8A,0x5E,0xFE,0xAA,
+    0xF8,0xF6,0xD7,0xF6,0x7D,0x79,0x7D,0xD5,0xD6,0xF6,0xB6,0xF6,0x18,0xBE,0xAA,0x20,
+    0xB6,0xF6,0x52,0xCD,0xC0,0xC0,0x60,0x40,0x2C,0xAC,0x05,0x6A,0x58,0x5C,0x54,0x5E,
+    0x06,0x6A,0x64,0x59,0xB0,0x6A,0x7E,0x77,0x64,0x61,0xE2,0x48,0x2A,0x96,0xDE,0xDE,
+    0x06,0x72,0x23,0x59,0xAA,0x0B,0xA9,0x2D,0x06,0x72,0xA5,0x61,0x78,0xA8,0xA2,0xEA,
+    0xA5,0x69,0x44,0x59,0x28,0xEC,0x7E,0x98,0x85,0x61,0x44,0x59,0xEA,0x4E,0xA6,0x27,
+    0xC5,0x61,0x23,0x51,0x3B,0xB7,0xBF,0xA5,0xE6,0x69,0x85,0x59,0x3F,0xBD,0xBF,0x97,
+    0x88,0x7A,0x06,0x6A,0x0D,0x3D,0x3D,0x35,0x2C,0xAC,0x47,0x72,0x2F,0xAF,0xBF,0xBD,
+    0x96,0xF6,0x0C,0xA4,0x02,0x0B,0x0D,0x25,0xF7,0xFE,0x96,0xF6,0xAA,0xAA,0xAB,0xA9,
+    0xD6,0xFE,0xD7,0xF6,0xFF,0xFF,0xFF,0xFF,0xB6,0xFE,0xD7,0xF6,0x55,0x75,0x67,0x7D,
+    0xF7,0xFE,0xB6,0xF6,0xD7,0x5E,0x76,0x7E,0xD7,0xF6,0xB6,0xF6,0x6E,0xCF,0xBD,0xDF,
+    0xD7,0xF6,0xB6,0xF6,0x55,0x56,0x54,0x57,0xD7,0xF6,0xB6,0xF6,0x75,0xBD,0xB7,0x2F,
+    0xD7,0xF6,0xB6,0xF6,0xDE,0xF8,0xBC,0x53,0xD6,0xF6,0xB6,0xF6,0x6D,0xFF,0xF6,0xA4,
+    0xD6,0xF6,0xB6,0xF6,0x1F,0x0F,0x8B,0xB8,0xF7,0xF6,0xD6,0xF6,0x35,0x15,0x95,0x55,
+    0x17,0xFF,0xD7,0xF6,0xEE,0xEA,0xEF,0xEF,0x17,0xFF,0xF7,0xF6,0xD5,0x75,0xFD,0xFD,
+    0xD7,0xFE,0xF7,0xF6,0xF9,0xB7,0xAD,0x2B,0xF7,0xFE,0x95,0xEE,0x00,0xAA,0xEA,0x78,
+    0xD6,0xF6,0xF0,0xC4,0xA0,0xE8,0x6A,0x5A,0x71,0xD5,0x46,0x7A,0xE0,0xE8,0x5A,0x5E,
+    0xC8,0x82,0xC5,0x69,0xE8,0xBE,0xFB,0xF7,0x46,0x7A,0x05,0x72,0xE8,0x90,0x60,0x8F,
+    0x46,0x82,0xE5,0x71,0xAC,0xBA,0x2D,0xEA,0x87,0x8A,0x26,0x7A,0xBD,0xF3,0x89,0x2B,
+    0xA8,0x8A,0x46,0x82,0x2A,0xBF,0xDF,0xFE,0xA8,0x8A,0x26,0x7A,0xA8,0xA0,0xEF,0xDF,
+    0xA8,0x82,0xE5,0x71,0x2A,0x3E,0x1F,0x37,0x55,0xEE,0x8A,0x9B,0x0D,0x29,0x09,0x0B,
+    0x18,0xFF,0xD7,0xFE,0x39,0xA9,0xAB,0x2B,0x17,0xFF,0x18,0xF7,0xF8,0xA8,0xBA,0xEA,
+    0x17,0xFF,0x18,0xF7,0xFB,0xBE,0xEB,0xEE,0x18,0xFF,0x17,0xF7,0xFF,0xEF,0xFE,0xEB,
+    0x18,0xFF,0x17,0xF7,0xEE,0xFE,0xAF,0xFB,0x18,0xFF,0xF7,0xF6,0x82,0xE0,0x70,0x7A,
+    0xF7,0xF6,0xD7,0xF6,0x78,0xFA,0x5E,0xAA,0xF7,0xF6,0xD7,0xF6,0xAA,0xAA,0x8A,0x83,
+    0xF7,0xF6,0xD7,0xF6,0xFD,0xFA,0xBA,0xA6,0xF7,0xF6,0xD7,0xF6,0xF7,0xBF,0xFF,0xFF,
+    0xF7,0xF6,0xD7,0xF6,0x36,0xBA,0x76,0x5E,0xF7,0xF6,0xD7,0xF6,0x75,0xD7,0x9D,0xD5,
+    0xF7,0xF6,0x97,0xF6,0xB2,0xAA,0xA0,0xA2,0xD7,0xF6,0xF7,0xEE,0x80,0xA0,0x00,0xA0,
+    0xF7,0xF6,0xD7,0xF6,0x8F,0xED,0x35,0x31,0x18,0xFF,0xF7,0xF6,0x35,0x0D,0xBA,0xEA,
+    0x18,0xFF,0xB6,0xEE,0xE0,0x78,0xFE,0xDF,0xB7,0xF6,0xB6,0xEE,0xFF,0x97,0xBF,0xAA,
+    0xB6,0xF6,0x96,0xEE,0xA2,0xAA,0xA0,0xFA,0x96,0xF6,0x75,0xEE,0x70,0x60,0xE8,0x78,
+    0x96,0xEE,0x14,0xDE,0xA8,0xE8,0xE8,0x5A,0x55,0xE6,0xB3,0xD5,0xA8,0xAA,0xE2,0x7A,
+    0x14,0xDE,0x71,0xCD,0x78,0x7A,0xD7,0x25,0xB6,0xF6,0x92,0xD5,0xBD,0x2D,0x0B,0x02,
+    0xF7,0xFE,0x96,0xF6,0xBD,0xAF,0xBB,0x8A,0xF7,0xF6,0xB7,0xEE,0xEA,0xBA,0xEA,0xAE,
+    0xF7,0xF6,0xD7,0xF6,0xFF,0xDD,0x57,0x55,0xF7,0xF6,0xD7,0xF6,0x59,0xD5,0x55,0xB5,
+    0xF8,0xF6,0xB6,0xEE,0xEE,0x7F,0xBE,0x2A,0xF7,0xF6,0xB7,0xEE,0xFF,0xFF,0xEB,0xAA,
+    0xD7,0xF6,0xB7,0xEE,0xEC,0xBF,0xAC,0x38,0xD7,0xF6,0xB7,0xEE,0xAB,0x2E,0x8E,0xAA,
+    0xD7,0xF6,0xB6,0xEE,0x08,0xA2,0xA8,0xEA,0xD7,0xF6,0xB6,0xEE,0x88,0x3E,0xBE,0xB7,
+    0xD7,0xF6,0xB6,0xEE,0xFE,0x6E,0xFE,0x7E,0xD7,0xF6,0xB6,0xEE,0xFF,0x3F,0x3F,0xAF,
+    0xD7,0xF6,0xB6,0xEE,0xDD,0x7E,0x70,0xEA,0xD6,0xF6,0xB7,0xEE,0x5D,0x5F,0x5F,0xFB,
+    0xD7,0xF6,0xB7,0xEE,0xAD,0xFD,0xAD,0xB7,0xF8,0xFE,0xD7,0xEE,0x2B,0x27,0x2D,0xF5,
+    0x38,0xFF,0xF8,0xF6,0x2A,0xAA,0xAF,0xBF,0x38,0xFF,0x19,0xFF,0x2E,0xA6,0xAF,0xAF,
+    0x38,0xFF,0xF7,0xF6,0x7A,0xEA,0xE0,0x80,0x18,0xF7,0xF7,0xF6,0x55,0x55,0x57,0x5E,
+    0xF8,0xF6,0xD7,0xF6,0xE8,0xAA,0xFB,0x2E,0xF7,0xF6,0xD7,0xF6,0x6A,0x2E,0x2B,0xA8,
+    0xF7,0xF6,0xD7,0xF6,0xA5,0xD6,0xFA,0x7A,0xF7,0xF6,0x96,0xEE,0xE0,0xAA,0xD8,0xFA,
+    0xB7,0xF6,0xD7,0xEE,0xBE,0x8A,0xAA,0xA0,0xD7,0xF6,0xB6,0xEE,0x2B,0x2A,0xAA,0x0F,
+    0xD7,0xF6,0x34,0xDE,0xF8,0x78,0xE8,0x78,0x54,0xE6,0xD2,0xD5,0x36,0x36,0x3E,0x2E,
+    0xD7,0xF6,0x75,0xE6,0x0F,0x89,0x01,0x0B,0xD7,0xF6,0x34,0xE6,0x78,0x78,0xE8,0xE2,
+    0x34,0xE6,0x92,0xCD,0x58,0x5A,0x58,0x78,0xB3,0xD5,0x71,0xCD,0x5F,0xEA,0xC3,0xC2,
+    0xD2,0xD5,0x71,0xCD,0x2D,0x17,0xA5,0xA5,0x14,0xDE,0xD3,0xDD,0x63,0xEB,0x8A,0xCD,
+    0x92,0xCD,0xEF,0xBC,0xEA,0xB8,0xF8,0x5C,0x51,0xC5,0x10,0xC5,0x28,0xBE,0xBE,0x55,
+    0x75,0xEE,0x51,0xCD,0xBD,0xA5,0x2D,0x0D,0xD7,0xF6,0x75,0xEE,0xAD,0x29,0x0A,0x02,
+    0xD7,0xF6,0x75,0xEE,0xC2,0xAA,0x68,0xA8,0x96,0xEE,0x34,0xE6,0x7C,0xFA,0x7A,0x6E,
+    0x55,0xE6,0x34,0xE6,0xDE,0xDB,0x77,0x5B,0x75,0xEE,0x55,0xE6,0x07,0x09,0x29,0x75,
+    0xD6,0xF6,0x95,0xEE,0xAF,0xA9,0xAB,0xAB,0xB5,0xF6,0xD6,0xEE,0xAF,0xAA,0xFA,0xE2,
+    0xD6,0xF6,0xB6,0xEE,0x8F,0x78,0x50,0x71,0xD6,0xF6,0xB6,0xEE,0xAD,0xAB,0xFF,0xA7,
+    0xD6,0xF6,0xB6,0xEE,0xAD,0x77,0x77,0xFF,0xD6,0xF6,0xB6,0xEE,0xEA,0xBB,0xAB,0x8A,
+    0xD6,0xF6,0xB6,0xEE,0xBF,0x6F,0x6A,0x72,0xD6,0xF6,0xB6,0xEE,0x5F,0x59,0xFE,0x7E,
+    0xD6,0xF6,0xB6,0xEE,0x2B,0xAF,0xFF,0xF7,0xD6,0xF6,0xB6,0xEE,0xAE,0xBA,0xDE,0xFB,
+    0xD6,0xF6,0xB6,0xEE,0x78,0xBF,0x75,0xFD,0xD6,0xF6,0xB6,0xEE,0xFE,0xFE,0xFF,0x6B,
+    0xD6,0xF6,0x95,0xEE,0x56,0xDA,0x7E,0xFF,0xB6,0xF6,0x96,0xEE,0xDF,0x77,0xBF,0xCD,
+    0xB6,0xF6,0x96,0xEE,0x9A,0x7E,0xF2,0xE2,0xB5,0xF6,0x96,0xEE,0x5E,0xDF,0xFF,0xFE,
+    0xB6,0xF6,0x96,0xEE,0xFB,0xEB,0xFD,0xED,0xD6,0xF6,0x96,0xEE,0xAD,0xAF,0xBD,0xFF,
+    0xD6,0xF6,0xB6,0xEE,0xBA,0x36,0x2F,0x0B,0xF6,0xF6,0xB7,0xEE,0xBE,0xBE,0xAA,0xAB,
+    0xD7,0xF6,0xB6,0xEE,0xEC,0xAC,0xA8,0x28,0xD7,0xF6,0xF6,0xEE,0x00,0xA8,0xA8,0x88,
+    0xD6,0xF6,0xF7,0xEE,0x88,0x0A,0x02,0x00,0xD6,0xF6,0xB7,0xF6,0xE8,0xC2,0xE0,0xFA,
+    0xB6,0xF6,0x72,0xD5,0x60,0x60,0x60,0x40,0x8B,0x9B,0x84,0x59,0x7C,0x5C,0x5C,0x5C,
+    0xA5,0x61,0x43,0x51,0xEC,0x7A,0xFA,0x8F,0x65,0x59,0xE3,0x48,0xEE,0x6A,0x78,0xE0,
+    0xA5,0x61,0xC2,0x48,0x0F,0x2D,0xBD,0xBF,0x06,0x72,0x84,0x59,0x8A,0xAA,0xFF,0xBD,
+    0xC5,0x69,0x64,0x59,0x58,0x7E,0xEE,0x6A,0x64,0x59,0x04,0x51,0x8A,0xAA,0x98,0xAA,
+    0x64,0x59,0x24,0x51,0x2F,0xFB,0xFA,0xAB,0xC5,0x61,0x44,0x51,0x2E,0x3F,0xBD,0xD5,
+    0x27,0x72,0xC5,0x61,0x2F,0x2D,0x5D,0x55,0x09,0x8B,0xE6,0x61,0x2B,0xAF,0xBD,0xB5,
+    0x92,0xD5,0x29,0x8B,0x2D,0xBD,0xF5,0x55,0xB6,0xF6,0x6E,0xB4,0x00,0x02,0x0B,0x0D,
+    0xD7,0xFE,0xD6,0xF6,0xFF,0xFE,0xEA,0xAA,0xB7,0xFE,0xD7,0xF6,0x77,0xFD,0x57,0x55,
+    0xD7,0xF6,0xB6,0xF6,0xF8,0xE2,0xE0,0x80,0xD7,0xF6,0xB6,0xF6,0x7E,0xEB,0xF9,0xA9,
+    0xD7,0xF6,0xB6,0xF6,0xD5,0xB5,0xAF,0xBF,0xD7,0xF6,0xB6,0xF6,0xAE,0xF6,0xAA,0xEB,
+    0xD6,0xF6,0xB7,0xF6,0x60,0xE2,0x20,0xAA,0xD6,0xF6,0xB6,0xF6,0x1A,0xAE,0x9A,0x3A,
+    0xD6,0xF6,0xB7,0xF6,0x78,0xCA,0x80,0xA0,0xF7,0xFE,0xB6,0xF6,0xAB,0xBF,0xA7,0xAD,
+    0xF7,0xFE,0xD7,0xF6,0x8B,0xAA,0x8B,0xAB,0xF7,0xFE,0xD7,0xF6,0x8B,0xAE,0xAA,0xAA,
+    0xF7,0xFE,0xB6,0xF6,0xA8,0xA2,0xEA,0x68,0xB6,0xF6,0x31,0xCD,0x80,0x80,0xE8,0x78,
+    0x72,0xD5,0x25,0x72,0xA0,0xE0,0x78,0x7E,0x09,0x8B,0xE5,0x69,0xDC,0xDE,0xD7,0xFD,
+    0x46,0x7A,0x05,0x72,0xD1,0xAF,0x3F,0x2A,0x67,0x82,0x26,0x7A,0xB5,0x5F,0x1F,0x03,
+    0x67,0x82,0x26,0x7A,0x57,0xDC,0x38,0x80,0x87,0x8A,0x06,0x7A,0x23,0x82,0xCA,0x5E,
+    0x67,0x82,0x26,0x7A,0x28,0xE2,0xCB,0x59,0x67,0x82,0x26,0x7A,0xB2,0xBE,0xBD,0x77,
+    0x0D,0xAC,0x66,0x7A,0xD5,0x95,0xB5,0x35,0xD7,0xFE,0x8E,0xBC,0x2D,0x29,0x09,0x0B,
+    0x18,0xFF,0xF7,0xFE,0xBD,0xB5,0xAD,0x2D,0xF7,0xFE,0x38,0xF7,0xBE,0xEA,0xFA,0x7E,
+    0x18,0xFF,0x37,0xF7,0x82,0xAA,0xAB,0xAB,0x38,0xFF,0x17,0xF7,0x77,0x5F,0xDD,0xFE,
+    0x38,0xFF,0xF7,0xF6,0xAB,0xBA,0xAB,0xAA,0x18,0xFF,0xF7,0xF6,0x7B,0xEA,0xF8,0xD8,
+    0xF7,0xF6,0xD7,0xF6,0xA0,0xB0,0xE8,0xAE,0xF7,0xF6,0xD7,0xF6,0xAA,0xEE,0xAE,0xA8,
+    0xF7,0xF6,0xD7,0xF6,0xBB,0xEA,0xEA,0xC2,0xF7,0xF6,0xB7,0xEE,0xBA,0xF8,0xAA,0x2A,
+    0xF7,0xF6,0xD7,0xF6,0xD5,0x55,0x57,0x28,0xF7,0xF6,0xD7,0xF6,0xF5,0xAD,0xEB,0xC8,
+    0xF7,0xF6,0xD7,0xF6,0x7E,0xDF,0xEF,0x0E,0xF7,0xF6,0xD7,0xF6,0xB5,0x5F,0x9E,0x2E,
+    0x17,0xFF,0xD7,0xF6,0xAF,0x0B,0xAB,0xA2,0x17,0xFF,0xB6,0xF6,0xC8,0xE8,0x5A,0x57,
+    0xD6,0xF6,0x96,0xEE,0x28,0xAA,0xBF,0xAF,0xB6,0xF6,0xD7,0xEE,0x8A,0x0A,0x20,0x82,
+    0xD6,0xF6,0x96,0xEE,0x7F,0x5E,0x5E,0x7E,0x96,0xEE,0x34,0xE6,0xA0,0xE8,0xF8,0xFE,
+    0x75,0xE6,0xF3,0xD5,0xF8,0xFA,0x6A,0x7A,0x35,0xE6,0x92,0xCD,0x7A,0x5E,0xBF,0x2E,
+    0xD7,0xF6,0x92,0xD5,0xB5,0xAF,0x2A,0x02,0xD7,0xF6,0xB6,0xF6,0x21,0x0D,0x0D,0x09,
+    0xF7,0xF6,0xD7,0xF6,0x79,0xFD,0xF5,0x55,0xF7,0xF6,0xD7,0xF6,0xF5,0xFB,0x5F,0x5D,
+    0xF7,0xF6,0xB7,0xEE,0xAB,0xAB,0xAF,0xAF,0xF7,0xF6,0xB7,0xEE,0x2A,0xAA,0xEA,0xFA,
+    0xD7,0xF6,0xF7,0xEE,0x2A,0x00,0x00,0x20,0xD7,0xF6,0xB7,0xEE,0x82,0x80,0xA0,0x80,
+    0xD7,0xF6,0xB7,0xEE,0xA8,0xEB,0x82,0xC8,0xD7,0xF6,0xB7,0xEE,0x28,0x02,0xC2,0xEA,
+    0xD7,0xF6,0xB7,0xEE,0xF8,0x2A,0xAE,0xAF,0xD7,0xF6,0xB6,0xEE,0xA7,0xB5,0xFF,0xDF,
+    0xD7,0xF6,0xB7,0xEE,0x77,0xBE,0xBC,0xA8,0xD7,0xF6,0xB6,0xEE,0x8B,0x8B,0x2F,0xBE,
+    0xD7,0xF6,0xB7,0xEE,0xC8,0x82,0x00,0x80,0xD7,0xF6,0xB7,0xEE,0xE8,0xAE,0xEA,0x2A,
+    0xD7,0xF6,0xB6,0xEE,0xEF,0xFB,0xAA,0xAF,0xD7,0xF6,0xB6,0xEE,0x29,0xEF,0xAA,0x0A,
+    0x18,0xF7,0xD7,0xF6,0x2B,0xAB,0xAF,0xBD,0x38,0xFF,0xF7,0xF6,0xAB,0x2A,0x2B,0xED,
+    0x39,0xFF,0x38,0xFF,0xEB,0xAF,0xAF,0xBF,0x38,0xFF,0xF7,0xF6,0x5E,0x7A,0x78,0x60,
+    0xF7,0xF6,0xD7,0xF6,0xAF,0x09,0xA8,0x83,0xF7,0xF6,0xD7,0xF6,0xC8,0x62,0x7E,0x57,
+    0xF7,0xF6,0x96,0xEE,0xA0,0xAA,0xEA,0xDF,0xD7,0xF6,0x96,0xEE,0x70,0xFE,0x5F,0x57,
+    0xB6,0xEE,0x96,0xEE,0x8A,0xAF,0x3F,0xA5,0xD7,0xF6,0xB6,0xEE,0x0D,0x0D,0x2D,0x25,
+    0xD7,0xF6,0xF4,0xDD,0xE8,0xE0,0x60,0x60,0x14,0xDE,0x51,0xC5,0x00,0x20,0x2E,0x35,
+    0xD6,0xF6,0x55,0xE6,0x09,0x2D,0xAD,0xBD,0xD7,0xF6,0x55,0xEE,0x62,0xE8,0xEA,0xE8,
+    0x35,0xE6,0x92,0xCD,0x5A,0x58,0x58,0x58,0xB2,0xD5,0x71,0xCD,0x63,0xC2,0xC2,0xC2,
+    0xB2,0xD5,0x71,0xCD,0xB5,0xAD,0x2D,0x2D,0x13,0xDE,0xB2,0xD5,0x8B,0x83,0x29,0xA9,
+    0x92,0xD5,0xCF,0xBC,0x7C,0x5C,0x5C,0x5C,0x31,0xC5,0xAE,0xB4,0x0B,0x2B,0xB5,0xD7,
+    0x96,0xEE,0x51,0xCD,0x2D,0xAF,0xBD,0xF5,0xD7,0xF6,0xF3,0xDD,0x00,0x0A,0x0B,0x2D,
+    0xD7,0xF6,0x75,0xEE,0xEA,0xF8,0x58,0xFA,0x75,0xEE,0x34,0xE6,0xE8,0xC0,0x70,0x78,
+    0x35,0xEE,0x54,0xE6,0xE5,0x57,0xDF,0x76,0x76,0xEE,0x35,0xE6,0xFB,0xAF,0xB6,0xFE,
+    0xD6,0xF6,0xB6,0xEE,0xFD,0xFE,0xEE,0x2A,0xD6,0xF6,0xB6,0xEE,0xDB,0xFF,0x7B,0x6A,
+    0xD6,0xF6,0xB6,0xEE,0xAD,0xEF,0xAD,0x3F,0xB6,0xF6,0xD6,0xEE,0xFF,0xFF,0xFF,0xAF,
+    0xD6,0xF6,0xB6,0xEE,0xA6,0xEA,0xEA,0xAA,0xD6,0xF6,0xB6,0xEE,0xF2,0xAF,0xAA,0xA2,
+    0xD6,0xF6,0xB6,0xEE,0xA1,0x8E,0xFE,0xAA,0xD6,0xF6,0xB6,0xEE,0xE2,0xA3,0x82,0xBA,
+    0xD6,0xF6,0x96,0xEE,0xA2,0x8A,0xD8,0x8A,0xD6,0xF6,0xB6,0xEE,0xEB,0xA2,0x68,0xA2,
+    0xD6,0xF6,0xB6,0xEE,0x6E,0xF2,0xE2,0xEB,0xD6,0xF6,0xB6,0xEE,0xF9,0xFF,0x7A,0xAA,
+    0xD6,0xF6,0x96,0xEE,0xFF,0xDF,0xFA,0xFA,0xB6,0xF6,0x96,0xEE,0x9F,0xAA,0x8B,0xBA,
+    0x96,0xF6,0xB6,0xEE,0xBF,0xED,0xBB,0xFF,0xB6,0xF6,0x96,0xEE,0x7E,0xFA,0xCA,0xA8,
+    0x96,0xF6,0xB6,0xEE,0x7E,0x7F,0xF7,0xF7,0xB6,0xEE,0x96,0xEE,0x22,0x2A,0xAA,0xC2,
+    0xD6,0xF6,0xB6,0xEE,0x8F,0x0B,0x03,0x2D,0xF6,0xF6,0xB6,0xEE,0xEE,0xFA,0xFA,0xFE,
+    0xD6,0xF6,0xB7,0xE6,0x20,0xA2,0x0A,0x80,0xD6,0xF6,0xF6,0xEE,0x08,0x28,0x20,0x02,
+    0xF6,0xF6,0xB6,0xEE,0xEB,0xAF,0xAF,0xFE,0xD6,0xF6,0xB6,0xF6,0x72,0xDA,0xBA,0x20,
+    0xD6,0xF6,0xB2,0xD5,0x60,0x60,0x60,0xE0,0x6C,0xAC,0x83,0x51,0x5E,0x5C,0x5C,0x5C,
+    0xA5,0x61,0x23,0x51,0x2F,0xB7,0x7F,0xDA,0x85,0x59,0x23,0x51,0x6A,0xE8,0xAA,0xB7,
+    0x85,0x59,0x23,0x51,0xF5,0x77,0x5C,0xEE,0xC6,0x61,0x24,0x51,0x0B,0xAF,0xEF,0x57,
+    0xA6,0x61,0x44,0x51,0x88,0xEB,0x7E,0x6B,0x64,0x59,0x03,0x49,0x2A,0xFE,0xDE,0xFF,
+    0x44,0x51,0x03,0x49,0x00,0xAE,0x96,0x57,0x85,0x59,0x23,0x49,0xAF,0x2F,0xAF,0xFD,
+    0xE5,0x61,0x65,0x51,0x2A,0x2F,0xAD,0xAD,0x87,0x7A,0xE5,0x61,0x3D,0xED,0x35,0xB5,
+    0x4B,0x93,0x88,0x7A,0x2B,0x2D,0x2D,0x2D,0xD3,0xDD,0x6A,0x93,0x2D,0xBD,0xF5,0xD5,
+    0xB6,0xF6,0x0D,0xA4,0x00,0x02,0x2F,0xB5,0xD7,0xFE,0xF4,0xDD,0x00,0x00,0xAA,0xF5,
+    0xD7,0xF6,0xB2,0xD5,0x00,0x80,0xEA,0x5F,0xB6,0xF6,0x50,0xCD,0x00,0x00,0x0A,0xF5,
+    0xD6,0xF6,0x55,0xEE,0x80,0x22,0x22,0xBD,0xD6,0xF6,0xB6,0xF6,0xED,0x7F,0x7A,0x9D,
+    0xD6,0xF6,0xB6,0xF6,0x2F,0xAB,0xBB,0x55,0xD6,0xF6,0xB6,0xF6,0xA8,0xDE,0xFE,0xBF,
+    0xD6,0xF6,0xB6,0xF6,0xA3,0x2B,0x88,0x6A,0xF7,0xFE,0xB6,0xF6,0xA9,0xA7,0x3D,0x0D,
+    0xF7,0xFE,0xD7,0xF6,0x6F,0xBF,0xE8,0xFC,0xF7,0xFE,0xD7,0xF6,0x2A,0x2B,0xCA,0x60,
+    0xD7,0xFE,0x72,0xD5,0x80,0x80,0xE0,0x7A,0x34,0xE6,0x87,0x7A,0xA0,0xE8,0x6A,0x7E,
+    0x8B,0x9B,0x05,0x72,0x58,0x5E,0x57,0x55,0x46,0x7A,0x05,0x72,0xA7,0xEF,0xE8,0x03,
+    0x67,0x82,0x26,0x7A,0x2F,0x0D,0x05,0x2D,0x87,0x8A,0x46,0x82,0x39,0x2E,0xAF,0xE2,
+    0x88,0x8A,0x26,0x82,0xA8,0xE2,0x53,0x7B,0x67,0x8A,0xE5,0x79,0x76,0xF0,0xFE,0xEF,
+    0x46,0x82,0xE4,0x71,0xEB,0x6F,0xCB,0x03,0xC8,0x92,0x25,0x7A,0xDD,0xF7,0xBF,0x2F,
+    0x52,0xD5,0xA8,0x8A,0x35,0x35,0x3D,0x2D,0xF8,0xFE,0xD3,0xE5,0x2D,0x0B,0x0B,0x03,
+    0x17,0xFF,0xF8,0xFE,0xB9,0xA9,0xEF,0xBB,0x38,0xFF,0xF7,0xF6,0xAB,0xBB,0xAF,0x8F,
+    0x18,0xFF,0x37,0xF7,0xEB,0xAA,0xBA,0xAA,0x38,0xFF,0x18,0xFF,0x5E,0x5A,0xDA,0xBF,
+    0x18,0xFF,0x38,0xF7,0x28,0xA2,0x28,0xAA,0x18,0xFF,0xF7,0xF6,0x78,0x78,0x7C,0x78,
+    0xF7,0xF6,0xD7,0xF6,0xD6,0xAC,0x2A,0x02,0xF7,0xF6,0xD7,0xF6,0xF8,0xE8,0x2A,0xAE,
+    0xF7,0xF6,0xD7,0xF6,0xEA,0x62,0x8A,0xAA,0xF7,0xF6,0xD7,0xF6,0x0E,0x3A,0xEE,0xF6,
+    0xF7,0xF6,0xD7,0xF6,0x80,0x00,0xBA,0xBF,0xF7,0xF6,0xD7,0xF6,0xA8,0xFE,0xB8,0xAA,
+    0xF7,0xF6,0xD7,0xF6,0x2C,0xAC,0xAA,0x28,0x17,0xFF,0xD7,0xF6,0xBF,0x0B,0x0B,0x82,
+    0x18,0xF7,0xB6,0xF6,0xE0,0xF8,0x78,0x5F,0xD6,0xF6,0x96,0xEE,0xFA,0xFA,0xEA,0xFF,
+    0xB6,0xF6,0x96,0xEE,0x2B,0xAF,0xF7,0x5F,0xB6,0xF6,0x96,0xEE,0x38,0xEF,0x5F,0x7D,
+    0xB7,0xF6,0x55,0xE6,0xE8,0xFA,0x6E,0x57,0x75,0xEE,0x14,0xE6,0xE8,0xE2,0xFA,0x7F,
+    0x96,0xEE,0xF3,0xDD,0x5B,0xBF,0xAF,0x0F,0xD7,0xFE,0x34,0xE6,0xB5,0x2F,0x02,0x02,
+    0xF7,0xF6,0xB7,0xF6,0xFF,0xFA,0xEA,0xA8,0xF7,0xF6,0xD7,0xF6,0x55,0xEF,0x9D,0x3D,
+    0xF7,0xF6,0xD7,0xF6,0x5F,0x76,0x5F,0xFF,0xF7,0xF6,0xB6,0xEE,0xDB,0xAB,0xAE,0xAE,
+    0xD7,0xF6,0xF7,0xEE,0x00,0x82,0xA2,0x08,0xB7,0xF6,0xF7,0xEE,0xAB,0x2F,0xAB,0x2A,
+    0xF7,0xF6,0xB7,0xF6,0x2A,0xBB,0xEF,0xFF,0xD7,0xF6,0xB6,0xEE,0x80,0xE0,0xF8,0xFC,
+    0xD7,0xF6,0xB7,0xEE,0x4E,0xAA,0xAA,0x0A,0xD7,0xF6,0xB7,0xEE,0xAA,0xAE,0xFA,0x4A,
+    0xD7,0xF6,0xB6,0xEE,0xEF,0xFF,0xEF,0xA2,0xD7,0xF6,0xB7,0xEE,0xFF,0xAA,0x82,0x00,
+    0xD7,0xF6,0xB7,0xEE,0x2A,0x82,0xA8,0xBA,0xD7,0xF6,0xB7,0xEE,0xA8,0x08,0x00,0x00,
+    0xF7,0xF6,0xB6,0xEE,0xFF,0xEB,0xEA,0xEA,0xD7,0xF6,0xB6,0xEE,0x88,0xAC,0x3E,0xAA,
+    0xB7,0xF6,0xF7,0xEE,0xBA,0xFA,0xAE,0xAE,0xF7,0xF6,0xD7,0xEE,0xF5,0xFD,0xAF,0xA9,
+    0xF7,0xF6,0xD7,0xF6,0xED,0xAD,0xBE,0xAE,0x18,0xFF,0xD7,0xF6,0x0B,0x29,0xAF,0xAF,
+    0x38,0xFF,0x18,0xF7,0x23,0x2B,0xAF,0xB5,0x38,0xFF,0xF8,0xF6,0xE8,0xE8,0xA0,0xA2,
+    0x18,0xF7,0xD7,0xF6,0x7E,0x5E,0x5E,0x50,0xD7,0xF6,0xB7,0xEE,0xE8,0x70,0x72,0x5E,
+    0xD7,0xF6,0x96,0xEE,0xFA,0xFE,0x7F,0xDF,0x96,0xEE,0x97,0xE6,0x00,0x88,0x22,0x80,
+    0x96,0xEE,0x76,0xE6,0x20,0x20,0x0B,0x08,0xD7,0xF6,0x96,0xEE,0x2F,0x1D,0xA7,0x3D,
+    0xD7,0xF6,0xF4,0xDD,0x60,0x60,0x60,0x68,0xF3,0xD5,0xEF,0xBC,0xBF,0x27,0xBF,0x3F,
+    0xB7,0xF6,0x34,0xE6,0x29,0x09,0x2B,0x29,0xB6,0xF6,0x76,0xEE,0xE8,0xA8,0xE2,0x6A,
+    0x55,0xEE,0x92,0xD5,0x58,0x58,0x58,0xF8,0xD3,0xD5,0x92,0xCD,0x55,0x7B,0x6A,0x7E,
+    0xB2,0xD5,0x71,0xCD,0x0D,0x35,0xF5,0x97,0xF3,0xDD,0xB2,0xD5,0x0F,0x0D,0x0F,0x01,
+    0x92,0xD5,0x8E,0xB4,0xD8,0xFC,0x58,0x7C,0xCF,0xBC,0x4D,0xA4,0x2A,0x0A,0x2B,0x27,
+    0xD3,0xDD,0x10,0xC5,0x09,0x29,0xA9,0xAD,0x75,0xEE,0xD3,0xD5,0x2D,0x3D,0xB5,0xF5,
+    0xB6,0xF6,0x55,0xE6,0x8A,0xAA,0xEB,0xB5,0x75,0xEE,0x34,0xE6,0x60,0xF0,0xE0,0x22,
+    0x55,0xE6,0x34,0xE6,0x3B,0x28,0x48,0x5C,0x75,0xEE,0x34,0xE6,0xF7,0xF5,0xB5,0xB5,
+    0xD6,0xF6,0xB6,0xEE,0xAA,0xA8,0xAD,0xED,0xD6,0xF6,0xB6,0xEE,0xFB,0xAF,0xAB,0xA2,
+    0xD6,0xF6,0xB6,0xEE,0xFC,0xB0,0xAA,0xFA,0xD6,0xF6,0xB7,0xEE,0xEA,0xFA,0xF8,0xE8,
+    0xD7,0xF6,0xB6,0xEE,0xAB,0xAA,0xAA,0xAB,0xD6,0xF6,0xD7,0xEE,0xAA,0x8A,0xA8,0x8A,
+    0xD6,0xF6,0xB6,0xEE,0xAA,0xEA,0xE0,0x02,0xD6,0xF6,0xB6,0xEE,0xEA,0x21,0xEE,0xB2,
+    0xD6,0xF6,0xB6,0xEE,0xFF,0xFE,0xBE,0x22,0xD6,0xF6,0xB6,0xEE,0xDA,0x77,0xDE,0x90,
+    0xD6,0xF6,0xB6,0xEE,0xE9,0xAB,0xAB,0x2B,0xD6,0xF6,0xB6,0xEE,0x2A,0x3D,0x07,0x5A,
+    0xD6,0xF6,0x96,0xEE,0xFE,0xFE,0xFE,0xFE,0xB6,0xF6,0x96,0xEE,0xDA,0xBA,0x9E,0x7F,
+    0xB6,0xF6,0x96,0xEE,0xAE,0xAE,0x8A,0x2B,0x96,0xF6,0xB6,0xEE,0xBF,0xAB,0xAF,0xF7,
+    0x95,0xF6,0xB6,0xEE,0xFD,0xD5,0x56,0x57,0xD6,0xF6,0x95,0xEE,0xEB,0xFF,0x9F,0x2F,
+    0xD6,0xF6,0xB6,0xEE,0x2D,0x2B,0x0D,0x2E,0xD6,0xF6,0xF7,0xEE,0x80,0xA0,0x00,0x28,
+    0xF6,0xF6,0xB6,0xEE,0xE2,0xBA,0xEE,0xFF,0xF6,0xF6,0xD6,0xF6,0x56,0xD5,0xFD,0xFF,
+    0xF6,0xF6,0xB6,0xEE,0xBF,0xAE,0xFE,0xEA,0xF5,0xFE,0xD7,0xF6,0x57,0x55,0xF5,0x5D,
+    0xD7,0xF6,0x33,0xEE,0x60,0xE0,0x80,0xA0,0xF2,0xDD,0x83,0x59,0x5E,0x5C,0x78,0x78,
+    0x84,0x51,0x03,0x49,0xA0,0x7E,0xFE,0x7E,0x64,0x51,0x03,0x49,0x3E,0xD7,0xBB,0xBB,
+    0x64,0x59,0x23,0x49,0xB8,0xBC,0xFB,0x7F,0x63,0x51,0x24,0x51,0x5E,0x7E,0xBA,0x5F,
+    0x45,0x51,0x04,0x49,0x02,0xB7,0x58,0x5D,0x24,0x51,0xE3,0x40,0x08,0xAA,0x77,0x77,
+    0x24,0x49,0xC2,0x40,0xA8,0xAE,0x09,0xB7,0x85,0x59,0x03,0x49,0xBB,0x07,0x2D,0xBD,
+    0x06,0x6A,0x64,0x59,0xAB,0xAF,0xAF,0x2D,0xA8,0x7A,0xC5,0x61,0xB5,0xAD,0x2F,0x2B,
+    0x2A,0x8B,0x88,0x72,0x2D,0x2F,0xBD,0xAD,0xAB,0x9B,0x0A,0x8B,0x2B,0xAF,0xA9,0xBD,
+    0x4E,0xAC,0x6A,0x93,0x3F,0xDD,0x55,0x55,0x31,0xC5,0x6B,0x93,0x02,0xFF,0x55,0x55,
+    0x31,0xC5,0x4A,0x8B,0xA0,0xFB,0xF7,0x5D,0x0F,0xC5,0x4A,0x8B,0x2A,0xAF,0xDF,0x55,
+    0x34,0xE6,0x8B,0x93,0x02,0xBB,0xF5,0x55,0x75,0xEE,0x8A,0x93,0x00,0x8A,0xFF,0x55,
+    0x96,0xF6,0x2C,0xA4,0x00,0x02,0xAF,0x55,0x96,0xF6,0xCF,0xBC,0x00,0x00,0xAA,0x55,
+    0xB6,0xF6,0xCF,0xBC,0x00,0x22,0xFE,0x55,0xD7,0xF6,0xF0,0xC4,0x00,0x02,0x2B,0xBD,
+    0xD7,0xFE,0x14,0xE6,0x00,0x00,0x82,0x55,0xB7,0xF6,0xD0,0xC4,0x00,0x80,0xA0,0x7E,
+    0x15,0xE6,0xC9,0x82,0xA0,0xE8,0x7A,0x5F,0xCC,0xA3,0xE5,0x69,0x78,0x5E,0x5F,0x75,
+    0x26,0x72,0xC4,0x69,0xDA,0x8A,0x08,0xEA,0x46,0x82,0x05,0x72,0x8F,0x81,0x8B,0xEB,
+    0x87,0x8A,0x47,0x82,0xBD,0x03,0x29,0x75,0x88,0x8A,0x05,0x7A,0xA0,0x98,0xB8,0xF3,
+    0x67,0x8A,0xE5,0x79,0xEA,0xAA,0xFE,0xF6,0x67,0x8A,0xE5,0x79,0xA7,0xAB,0x27,0x0F,
+    0xA8,0x92,0x05,0x82,0xBD,0xFF,0x2A,0x2A,0x29,0x9B,0x67,0x82,0xB5,0xBF,0xAB,0x2F,
+    0xD3,0xE5,0x29,0x9B,0x25,0x3D,0x2D,0x2D,0xF7,0xFE,0x55,0xEE,0x01,0x09,0x03,0x03,
+    0x18,0xFF,0xF8,0xFE,0xAB,0xAD,0xFB,0xBB,0x38,0xFF,0xF8,0xF6,0xAF,0xEF,0xFF,0xAF,
+    0x18,0xFF,0x38,0xF7,0xA2,0xA0,0x22,0xA8,0x38,0xFF,0x18,0xF7,0xAF,0xFF,0xBE,0xAF,
+    0x38,0xFF,0x18,0xFF,0xFE,0x7A,0x7A,0x6E,0x18,0xFF,0xF7,0xF6,0x78,0x7E,0xDA,0xEA,
+    0x17,0xFF,0xF7,0xF6,0xD7,0x5D,0x55,0x7D,0xF7,0xF6,0xD7,0xF6,0xA8,0x0E,0x2B,0x88,
+    0xF7,0xFE,0xF7,0xF6,0xFD,0xD7,0x7D,0xDF,0xF7,0xF6,0xD7,0xF6,0x60,0xF0,0x80,0x8B,
+    0xF7,0xF6,0xD7,0xF6,0xAB,0x0A,0x2F,0x26,0xD7,0xFE,0xF7,0xF6,0xDD,0xD7,0x57,0xD5,
+    0x18,0xFF,0xF7,0xF6,0x95,0x2D,0x2B,0xCF,0x17,0xFF,0xB6,0xF6,0xA0,0xE0,0x7C,0x7E,
+    0xD6,0xF6,0x96,0xEE,0xFA,0xFA,0xDE,0xFE,0xB6,0xF6,0x96,0xEE,0xFF,0xBF,0x3F,0x77,
+    0xB6,0xF6,0x96,0xEE,0xFF,0xAF,0xA9,0x2B,0xB6,0xF6,0x35,0xE6,0xAA,0xE0,0xFA,0x78,
+    0x55,0xE6,0xD3,0xDD,0x20,0xE2,0xFA,0x5A,0x35,0xE6,0x93,0xCD,0x20,0xAA,0xB7,0x37,
+    0xD7,0xFE,0x55,0xE6,0xB5,0xA5,0xAD,0x2B,0xD7,0xF6,0xB7,0xF6,0x01,0x2D,0x08,0x02,
+    0xF7,0xF6,0xD7,0xF6,0xDF,0xED,0x7D,0xFB,0xF7,0xF6,0xD7,0xF6,0xAF,0xE3,0xED,0x5B,
+    0xF7,0xF6,0xD7,0xF6,0x6A,0xEE,0xFD,0x55,0xF7,0xF6,0xB6,0xEE,0xAA,0xFF,0xA6,0xAF,
+    0xF7,0xF6,0xD7,0xF6,0x75,0x77,0x55,0xFD,0xD7,0xF6,0xB6,0xEE,0xD8,0xE8,0x80,0x80,
+    0xD7,0xF6,0xB6,0xEE,0x3B,0xBB,0x7C,0xE0,0xD7,0xF6,0xB6,0xEE,0x7E,0xEF,0x2B,0x8A,
+    0xF7,0xF6,0xB7,0xEE,0xAB,0xEE,0xE2,0xFA,0xD7,0xF6,0xB7,0xEE,0xA8,0x80,0x02,0x02,
+    0xD7,0xF6,0xB7,0xEE,0x82,0xBA,0x3A,0xFA,0xD7,0xF6,0xB7,0xEE,0x88,0x2A,0xFA,0xEA,
+    0xD7,0xF6,0xB7,0xEE,0xAE,0xAF,0xEB,0x7D,0xD7,0xF6,0xB6,0xEE,0x8A,0x23,0x0A,0x5F,
+    0xF7,0xF6,0xB7,0xEE,0xEA,0xAB,0xFB,0xFF,0xD7,0xF6,0xB7,0xEE,0xAA,0xB2,0xA8,0x0A,
+    0xD7,0xF6,0xD7,0xEE,0xE2,0xA8,0xAA,0xAA,0xD7,0xF6,0xF7,0xE6,0x88,0x20,0x82,0x20,
+    0xD7,0xF6,0xF7,0xEE,0xAA,0xA8,0x80,0x00,0x18,0xFF,0xD7,0xF6,0xBA,0xAF,0xBF,0xFD,
+    0x38,0xFF,0xF7,0xF6,0xAF,0xBD,0xB5,0xD5,0x18,0xFF,0x38,0xF7,0xAC,0xA2,0xA8,0x80,
+    0x38,0xFF,0xD7,0xF6,0x5A,0x7A,0x68,0xE8,0xD7,0xF6,0x96,0xEE,0x7A,0x5A,0x5E,0x5C,
+    0x96,0xEE,0x76,0xE6,0x20,0x38,0xC0,0x80,0x96,0xEE,0x76,0xE6,0xF0,0x38,0x80,0xB9,
+    0x96,0xEE,0x76,0xEE,0x08,0x20,0xA8,0x5E,0xD7,0xF6,0x76,0xEE,0x2E,0xAF,0xBF,0xBD,
+    0xB7,0xF6,0x13,0xDE,0x60,0x40,0x60,0x40,0xD2,0xD5,0x30,0xC5,0x17,0x37,0x37,0x37,
+    0xB6,0xF6,0x14,0xDE,0x09,0x29,0x29,0x2D,0xB6,0xF6,0x76,0xEE,0xE2,0xE2,0xE8,0xA0,
+    0x76,0xEE,0xD3,0xD5,0x5A,0x58,0x58,0x78,0x93,0xD5,0xD2,0xCD,0xAB,0xAA,0xAE,0xBF,
+    0xB2,0xD5,0x72,0xCD,0xBE,0xAE,0xAA,0xAB,0x15,0xDE,0xB3,0xD5,0xAF,0x3D,0xA5,0xA7,
+    0xB3,0xD5,0x4D,0xAC,0x58,0x78,0x78,0x78,0xCE,0xBC,0x2C,0xA4,0xBF,0xBF,0xBF,0x35,
+    0x71,0xCD,0xEF,0xBC,0x09,0x2D,0xAD,0x03,0xF4,0xDD,0x72,0xCD,0x2B,0x2D,0x3F,0x2F,
+    0x95,0xEE,0xF3,0xDD,0x2B,0x8F,0x2F,0x29,0x96,0xEE,0x55,0xE6,0xBE,0x7E,0x7A,0x5E,
+    0x75,0xEE,0x35,0xE6,0x7C,0xF2,0xEB,0xEB,0x75,0xEE,0x34,0xE6,0xAD,0x3F,0xBF,0x56,
+    0xD6,0xF6,0xB6,0xEE,0xAD,0xFA,0xFA,0xEA,0xD6,0xF6,0xB6,0xEE,0xBA,0xAB,0x9B,0x72,
+    0xD6,0xF6,0xB6,0xEE,0xAA,0x2A,0xAE,0xF7,0xD7,0xF6,0xB6,0xEE,0x2A,0xA8,0x38,0x36,
+    0xD7,0xF6,0xB6,0xEE,0xBE,0xB8,0x09,0x2B,0xD6,0xF6,0xB6,0xEE,0x8B,0xAA,0x22,0x00,
+    0xD7,0xF6,0xF6,0xEE,0x80,0xA0,0x88,0x22,0xD6,0xF6,0xD7,0xEE,0x8A,0xAA,0xA2,0xAA,
+    0xD6,0xF6,0xB6,0xEE,0x8A,0x0A,0x22,0x02,0xD6,0xF6,0xF7,0xEE,0x00,0x0A,0x28,0x82,
+    0xF7,0xF6,0xB6,0xEE,0xFF,0xEB,0xEC,0xEA,0xD6,0xF6,0xB6,0xEE,0x76,0x5B,0xFE,0xFE,
+    0x96,0xF6,0xB6,0xEE,0xED,0xBD,0xED,0xE5,0xB6,0xF6,0x96,0xEE,0xAA,0xBA,0x2A,0x82,
+    0xB6,0xF6,0x96,0xEE,0xAE,0xF8,0xAB,0x81,0xB7,0xF6,0xB6,0xEE,0x6B,0xEA,0xEE,0xFF,
+    0x95,0xF6,0xB6,0xEE,0x7D,0x57,0x55,0x55,0xD6,0xF6,0xB6,0xEE,0xB5,0xFF,0xBF,0xF7,
+    0xD6,0xF6,0xF6,0xEE,0x80,0xA8,0xA0,0x80,0xF7,0xF6,0xD6,0xF6,0x75,0x7B,0x5A,0x7A,
+    0xD6,0xF6,0xB6,0xEE,0xA2,0x28,0xA0,0x00,0xD6,0xF6,0xB6,0xEE,0x02,0x00,0x28,0xA0,
+    0xF6,0xF6,0xD6,0xF6,0x5F,0x5F,0xB6,0xB5,0xD6,0xF6,0xD7,0xEE,0x0A,0x28,0x2A,0xA8,
+    0xF7,0xFE,0xB6,0xF6,0x7E,0xEA,0xAB,0xDA,0x95,0xEE,0x26,0x62,0x78,0x60,0xE0,0xE0,
+    0x84,0x51,0x03,0x41,0x7F,0x7C,0xD4,0x5C,0x65,0x51,0xE3,0x40,0x2A,0x83,0xA2,0xA9,
+    0x44,0x51,0xE2,0x40,0xAE,0x26,0xF0,0x8A,0x44,0x51,0x03,0x49,0x4B,0x7A,0x4D,0xAB,
+    0x24,0x49,0x03,0x49,0x49,0xF4,0xFE,0x78,0x24,0x49,0xC2,0x38,0xFA,0xDA,0xF2,0xF8,
+    0x23,0x41,0xE3,0x40,0x75,0x85,0x69,0xF5,0x64,0x51,0xE2,0x40,0x0F,0x0B,0x2F,0x25,
+    0x26,0x6A,0x64,0x51,0x35,0x0F,0x0F,0x29,0xC9,0x7A,0x67,0x72,0x2D,0x29,0x29,0x0D,
+    0x09,0x83,0xA8,0x7A,0xAF,0xB9,0xF7,0x2F,0x6A,0x93,0xE9,0x82,0x2B,0x09,0xAD,0xBF,
+    0x6B,0x93,0x09,0x8B,0x8A,0x0A,0xFB,0x7E,0x4A,0x8B,0xC9,0x82,0x20,0xB2,0xFA,0x77,
+    0x4A,0x8B,0xA8,0x7A,0x88,0xFC,0x5F,0x57,0x29,0x8B,0xA8,0x7A,0x08,0xEA,0xFD,0x55,
+    0x6A,0x93,0xC8,0x7A,0x0F,0xB7,0xD5,0x55,0x8B,0x93,0xE9,0x82,0x08,0xAF,0xFF,0x75,
+    0xCB,0x9B,0x09,0x8B,0x20,0xAB,0xAF,0xB5,0x2C,0xAC,0x6A,0x93,0x2A,0xAF,0xBD,0x7D,
+    0x2D,0xAC,0xCC,0xA3,0x02,0xFE,0xFF,0x7D,0xF0,0xC4,0x8B,0x9B,0x2B,0xBF,0xD5,0x55,
+    0x10,0xCD,0xE8,0x8A,0x00,0xEA,0xFF,0x7F,0x6E,0xB4,0x46,0x7A,0x80,0xFA,0x7F,0x5F,
+    0xE9,0x8A,0xE5,0x69,0xF8,0x7E,0x7F,0x7F,0x67,0x7A,0x05,0x6A,0x7F,0xA5,0xAF,0xEB,
+    0x47,0x7A,0xE5,0x71,0x5A,0x78,0x5A,0x7E,0x26,0x7A,0xC5,0x71,0xB2,0x2F,0xBF,0xFD,
+    0x46,0x82,0xE5,0x71,0x0A,0x0B,0xEA,0xF5,0x47,0x82,0xE5,0x79,0xF8,0xEB,0x6B,0xAB,
+    0x67,0x8A,0xE5,0x79,0x9E,0xBB,0x2D,0x2A,0xC9,0x92,0x46,0x82,0xF5,0xBD,0xBA,0xA2,
+    0xA8,0x92,0x46,0x82,0xDF,0x17,0x2E,0x88,0x4A,0x9B,0xC8,0x92,0xBD,0xBD,0xBD,0x35,
+    0x76,0xF6,0xAB,0xAB,0x2D,0x0D,0x2B,0x09,0xF7,0xFE,0xB6,0xF6,0x03,0x03,0x00,0x00,
+    0x17,0xFF,0xF7,0xF6,0xEF,0xEF,0xAA,0xAB,0x38,0xFF,0xF7,0xF6,0xEF,0xAD,0xAF,0xBF,
+    0x38,0xFF,0x17,0xF7,0xFF,0xBD,0xD7,0xF5,0x37,0xFF,0x18,0xF7,0xBE,0xBF,0xFF,0xFF,
+    0x38,0xFF,0x17,0xF7,0xFA,0x6E,0xFE,0xDF,0xF7,0xFE,0x18,0xF7,0xFD,0x5F,0xFF,0x7F,
+    0x17,0xF7,0xF7,0xF6,0x77,0xF6,0x7E,0xF2,0x17,0xF7,0xF7,0xF6,0x55,0x77,0x56,0x57,
+    0x17,0xFF,0xF7,0xF6,0xD7,0x7F,0xF7,0x55,0x18,0xFF,0xD7,0xF6,0xFB,0xAB,0xEA,0xFE,
+    0x18,0xFF,0xD7,0xF6,0xFF,0xFB,0xAB,0x2A,0x18,0xFF,0xF7,0xF6,0x7D,0xAF,0x0D,0x82,
+    0x18,0xFF,0x95,0xEE,0xA0,0xA8,0x78,0x56,0xD6,0xF6,0x74,0xEE,0xA0,0xAA,0xFA,0xFD,
+    0xB6,0xF6,0x96,0xEE,0x22,0x8F,0x2B,0xAA,0xD6,0xF6,0x97,0xEE,0x7E,0xBA,0xAB,0xBF,
+    0xD7,0xF6,0x76,0xEE,0x8E,0xEA,0xFE,0x7B,0x96,0xEE,0x34,0xE6,0xF8,0x7A,0x5E,0x7E,
+    0x76,0xEE,0x92,0xD5,0x7E,0x5E,0xAF,0x02,0xF7,0xFE,0xB3,0xD5,0xB5,0x2F,0x0A,0x22,
+    0xF7,0xFE,0xB7,0xF6,0xBF,0xAB,0xAA,0xAA,0xF7,0xF6,0xD7,0xF6,0xFD,0xD7,0xDD,0x5F,
+    0xF7,0xF6,0xD7,0xF6,0x8F,0xAD,0xB6,0xF7,0xF7,0xF6,0xD7,0xF6,0x4E,0x7A,0x78,0xF8,
+    0xF7,0xF6,0xD7,0xF6,0x75,0x57,0x5F,0xDF,0xD7,0xF6,0xB7,0xEE,0x02,0xA8,0xA2,0x80,
+    0xD7,0xF6,0xB6,0xEE,0x00,0x0A,0x2B,0xEE,0xD7,0xF6,0xF7,0xEE,0x02,0x20,0xA0,0x00,
+    0xF7,0xF6,0xB6,0xEE,0xFE,0xE8,0xAA,0xBA,0xD7,0xF6,0xB6,0xEE,0x08,0x02,0x00,0xAC,
+    0xF7,0xF6,0xB7,0xEE,0xF2,0xFA,0xEF,0xBB,0xD7,0xF6,0xB7,0xEE,0x8A,0x0A,0xAA,0xFA,
+    0xD7,0xF6,0xB7,0xEE,0xEA,0x68,0xFA,0xB2,0xD7,0xF6,0xB6,0xEE,0x77,0xFD,0x7B,0x7F,
+    0xD7,0xF6,0xB6,0xEE,0x6D,0xED,0xAD,0xEA,0xD7,0xF6,0xB7,0xEE,0x7F,0xE9,0xBF,0xBE,
+    0xB7,0xF6,0xD7,0xEE,0xEE,0xAB,0xFA,0xF9,0xD7,0xF6,0x97,0xEE,0x8A,0xE2,0xAA,0x08,
+    0xD7,0xF6,0xB7,0xEE,0x88,0xA2,0x88,0x00,0xD7,0xF6,0xF7,0xEE,0x88,0xA0,0x88,0x02,
+    0xF8,0xF6,0xD7,0xF6,0x75,0x8F,0xAF,0xAB,0x18,0xFF,0xD7,0xF6,0xE9,0xFB,0xFA,0xAB,
+    0x19,0xF7,0xF8,0xF6,0xD5,0xED,0xB5,0x57,0x38,0xFF,0xF8,0xF6,0xAF,0xAB,0x9F,0x75,
+    0x38,0xFF,0xF8,0xF6,0x72,0x6A,0x7A,0xFB,0xF8,0xF6,0x56,0xE6,0xFE,0xEC,0xFC,0xF8,
+    0xB7,0xEE,0x76,0xEE,0xFF,0xFA,0xFE,0xFA,0x96,0xEE,0x76,0xE6,0xEF,0xAF,0xC0,0xAA,
+    0x96,0xEE,0x55,0xE6,0xEA,0xAA,0xEB,0xF8,0xB7,0xF6,0x76,0xEE,0x3D,0x3D,0x25,0xB5,
+    0xB7,0xF6,0x13,0xDE,0x40,0x60,0x60,0xE0,0x13,0xDE,0x0F,0xC5,0xB5,0x37,0x37,0xB7,
+    0x96,0xEE,0x14,0xDE,0x0D,0x2B,0x29,0x0F,0xB7,0xF6,0x96,0xEE,0xAA,0xAA,0x2A,0xDA,
+    0x76,0xEE,0xD3,0xD5,0x60,0xF8,0x60,0xE0,0xD3,0xDD,0xB3,0xD5,0x6A,0x82,0xE2,0xBF,
+    0xB3,0xD5,0x92,0xCD,0xF6,0x14,0xBC,0x70,0xF3,0xDD,0x92,0xCD,0x2F,0xB7,0xAF,0xFF,
+    0xB2,0xD5,0x0C,0x9C,0xF8,0x70,0x78,0x7A,0x71,0xCD,0x4D,0xAC,0xB5,0x35,0x25,0x2D,
+    0x13,0xDE,0x71,0xCD,0xED,0xAF,0xAA,0xAB,0x35,0xE6,0xB3,0xD5,0xE5,0xFD,0xAB,0x2E,
+    0x96,0xEE,0x14,0xE6,0x2D,0x0D,0x0B,0xA9,0x96,0xEE,0x55,0xE6,0x78,0x5E,0x7E,0x5A,
+    0x55,0xE6,0x34,0xE6,0x04,0x0C,0xB2,0x79,0x55,0xE6,0x34,0xE6,0xA2,0x3F,0xB9,0x37,
+    0xB6,0xF6,0xD6,0xEE,0xFF,0xAB,0xCF,0x6B,0xD6,0xF6,0xB7,0xEE,0x82,0xAA,0x82,0xE8,
+    0xD6,0xF6,0xB7,0xEE,0xAA,0xEA,0x08,0x80,0xD6,0xF6,0xB6,0xEE,0x3F,0xAB,0xAA,0xA2,
+    0xD6,0xF6,0xB6,0xEE,0x82,0x80,0xE0,0x70,0xD7,0xF6,0xB6,0xEE,0x82,0x07,0xAE,0xAA,
+    0xD6,0xF6,0xB6,0xEE,0x02,0x09,0x2B,0xAA,0xD6,0xF6,0xB6,0xE6,0x00,0x88,0x20,0x2A,
+    0xD6,0xF6,0xF8,0xEE,0x88,0x08,0xA2,0x08,0xF7,0xF6,0xB6,0xEE,0xEA,0xCE,0xBB,0x6B,
+    0xD7,0xF6,0xF6,0xEE,0x08,0x20,0x20,0x2A,0xB6,0xF6,0xD7,0xEE,0xED,0xFF,0xB7,0xFD,
+    0xD6,0xF6,0xB6,0xEE,0x57,0x5E,0xDE,0x5E,0x96,0xF6,0xB6,0xEE,0xDD,0xFD,0x55,0xD5,
+    0xD6,0xF6,0x96,0xEE,0xAB,0x29,0xBB,0xAB,0xD6,0xF6,0xB6,0xEE,0x5F,0xFE,0xBD,0xD5,
+    0xD7,0xF6,0xB6,0xEE,0xF5,0xF7,0x7E,0x5D,0xD6,0xF6,0xB6,0xEE,0xDD,0xEB,0xF9,0x5F,
+    0xD6,0xF6,0xB6,0xEE,0x22,0x8A,0x2A,0x02,0xD6,0xF6,0xF6,0xEE,0xAA,0x80,0x88,0x88,
+    0xF7,0xF6,0xD6,0xF6,0x77,0xDD,0x75,0xFF,0xF7,0xF6,0xB5,0xF6,0xEA,0xA8,0x2B,0xAF,
+    0xF7,0xF6,0xD6,0xF6,0xF5,0x7F,0x6E,0x6A,0xF7,0xF6,0xD7,0xF6,0x5F,0xBB,0xBF,0xFD,
+    0xB6,0xFE,0xF7,0xF6,0xAE,0xAD,0xBF,0xEF,0xB6,0xF6,0x8E,0xAC,0x60,0x60,0xC0,0xC0,
+    0xCC,0x9B,0x02,0x41,0x57,0x56,0x5E,0x5C,0x64,0x51,0xE2,0x38,0xAF,0x39,0xAA,0xAD,
+    0x64,0x51,0x23,0x49,0xAF,0xE2,0xFF,0x77,0x23,0x49,0xE2,0x40,0x28,0x88,0x68,0x62,
+    0x24,0x49,0xE2,0x40,0x78,0x6E,0x7A,0xFB,0x03,0x41,0xC2,0x38,0xAF,0xA7,0xDF,0x9A,
+    0x23,0x49,0xC2,0x38,0xF7,0xB7,0xBD,0x2F,0x84,0x51,0x03,0x41,0xA5,0xAF,0xA5,0x27,
+    0x06,0x6A,0x84,0x51,0x0F,0xAD,0xAD,0x2D,0xA8,0x7A,0x06,0x62,0x23,0x0D,0x27,0xBD,
+    0x2A,0x8B,0x87,0x72,0x2B,0x29,0x3D,0xAD,0x4A,0x93,0xE9,0x82,0x2A,0x88,0x7A,0xD2,
+    0x4A,0x93,0xA8,0x7A,0xEC,0xFE,0x5F,0x5F,0xA8,0x7A,0x88,0x72,0xE0,0x52,0xC0,0x23,
+    0xA8,0x7A,0x47,0x6A,0x82,0xEC,0x7A,0xE8,0xC8,0x7A,0x47,0x6A,0x8A,0xEF,0xBD,0xF7,
+    0xC9,0x7A,0x67,0x72,0x3A,0xFE,0xDE,0xB7,0xE9,0x82,0x87,0x72,0x03,0xAD,0xE5,0xDF,
+    0x6A,0x93,0xA8,0x7A,0x2B,0x2F,0x2D,0x2D,0x8A,0x9B,0x4A,0x93,0x2A,0xAB,0xB5,0xBF,
+    0xCC,0xA3,0x6A,0x93,0x83,0x8B,0xEF,0x7D,0x6B,0x9B,0xC8,0x82,0xA8,0x68,0x78,0x7E,
+    0x09,0x93,0x26,0x72,0x80,0xE8,0xFA,0x7E,0x66,0x7A,0xC4,0x69,0xA8,0xFC,0x7E,0x5F,
+    0x47,0x7A,0xA3,0x61,0xAA,0xAF,0xB5,0x27,0x88,0x82,0x27,0x72,0x6D,0xEF,0xEB,0x2F,
+    0x47,0x7A,0xC5,0x69,0xFA,0xFC,0x5A,0x78,0x06,0x7A,0xC5,0x71,0xA9,0xAE,0xDF,0xD5,
+    0x06,0x7A,0xC5,0x71,0x9E,0xAF,0x3F,0xBE,0x47,0x8A,0xE6,0x79,0xAF,0x29,0xAD,0x2B,
+    0x87,0x8A,0x26,0x82,0xAD,0xA5,0xAD,0xAB,0xC8,0x92,0x67,0x8A,0xF0,0x69,0xFC,0x5D,
+    0x2A,0xA3,0x88,0x8A,0xFD,0xBD,0xAD,0x3D,0x4A,0xA3,0xC8,0x92,0x2D,0x8A,0x82,0x2A,
+    0xB6,0xF6,0xAC,0xAB,0x09,0x0D,0x2D,0x2D,0xD7,0xFE,0x18,0xF7,0xAA,0xAE,0xEE,0xBC,
+    0x18,0xFF,0xF7,0xF6,0xAB,0x2B,0xAB,0xA3,0x17,0xFF,0xF8,0xF6,0x2A,0x0A,0x8A,0x2A,
+    0x17,0xFF,0x39,0xF7,0xA2,0x88,0xB0,0xA8,0x37,0xFF,0x18,0xF7,0xFB,0xFD,0xF7,0xFF,
+    0x38,0xFF,0x17,0xF7,0x77,0x57,0xDD,0x7B,0x38,0xFF,0x17,0xF7,0x7F,0xDD,0x7F,0xFF,
+    0x17,0xFF,0x38,0xF7,0x0A,0x08,0xA2,0xAE,0x17,0xFF,0xF7,0xF6,0x76,0x7F,0xAA,0xA8,
+    0x17,0xFF,0xD7,0xF6,0xBF,0xBF,0xB2,0xA0,0x17,0xFF,0xF7,0xF6,0x77,0xA7,0xAE,0x08,
+    0x18,0xFF,0xF7,0xF6,0xAB,0x0B,0x0A,0xA0,0x18,0xFF,0xB6,0xEE,0x60,0x78,0x58,0x5E,
+    0xB6,0xEE,0x75,0xEE,0x7E,0xD7,0xBF,0x8A,0x96,0xF6,0x75,0xE6,0xB5,0xFD,0xFE,0x88,
+    0xB6,0xF6,0x75,0xEE,0xAB,0xAD,0xF5,0x7F,0xB6,0xF6,0x55,0xEE,0x2A,0xAA,0xEF,0xDF,
+    0x96,0xEE,0x75,0xEE,0x40,0x28,0x66,0x5D,0xB6,0xF6,0x54,0xE6,0xBF,0x2F,0xEF,0x75,
+    0xD7,0xF6,0x54,0xE6,0x02,0x02,0xBA,0xD5,0xF7,0xFE,0x76,0xEE,0x02,0x22,0xAF,0xDD,
+    0xF7,0xFE,0xD7,0xF6,0xAA,0xAA,0x3F,0x95,0xF7,0xF6,0xD7,0xF6,0x7A,0xE2,0x8A,0xA8,
+    0xF7,0xF6,0xD7,0xF6,0x8F,0x85,0xB7,0xE7,0xF7,0xF6,0xD7,0xF6,0xFA,0xDE,0xD6,0xFE,
+    0xF7,0xF6,0xD7,0xF6,0x5B,0x5A,0xFA,0x00,0xF7,0xF6,0xD7,0xF6,0x75,0x7B,0x5E,0xE4,
+    0xF7,0xF6,0xB7,0xF6,0xFF,0xEF,0xAB,0x08,0xD7,0xF6,0xB7,0xEE,0x0A,0x02,0x0A,0x00,
+    0xD7,0xF6,0xB6,0xEE,0xA8,0xA0,0x28,0x00,0xD7,0xF6,0xB7,0xEE,0x7C,0xBE,0xEA,0x00,
+    0xD7,0xF6,0xB6,0xEE,0x28,0x3E,0x7A,0x5A,0xD7,0xF6,0xB7,0xEE,0xF8,0xAA,0xEA,0xFE,
+    0xD7,0xF6,0xB7,0xEE,0xAA,0xAB,0xA5,0xEE,0xD7,0xF6,0xB7,0xEE,0xF7,0x2F,0xAE,0xAA,
+    0xD7,0xF6,0xB7,0xEE,0x3A,0xBE,0xAA,0xBE,0xD7,0xF6,0xB7,0xEE,0xA3,0xA6,0xFE,0xAC,
+    0xF7,0xF6,0xB7,0xF6,0xFF,0xFE,0xFF,0xCB,0xF8,0xF6,0x97,0xEE,0xAE,0x2A,0x2A,0x0A,
+    0xF8,0xF6,0xB7,0xF6,0xAF,0xAE,0xBA,0x0A,0xF8,0xF6,0xD7,0xF6,0xDD,0xBD,0x2A,0x28,
+    0xF8,0xF6,0xD7,0xF6,0xEA,0xAE,0xAA,0x3A,0xF8,0xF6,0xD7,0xF6,0x00,0x08,0xAA,0x22,
+    0xF8,0xF6,0xD8,0xF6,0x00,0x28,0xBE,0xAA,0xD7,0xFE,0xF8,0xF6,0x55,0x77,0x5D,0x7F,
+    0x18,0xFF,0xF8,0xF6,0x2A,0x2A,0x2F,0x2D,0x18,0xFF,0x76,0xE6,0x58,0x7A,0xF8,0xF8,
+    0x96,0xEE,0x55,0xE6,0x80,0x2A,0xB6,0xBA,0x96,0xEE,0x76,0xE6,0xB2,0xEF,0x37,0xA3,
+    0x96,0xEE,0x76,0xEE,0x5C,0xD7,0xBE,0xF6,0xB6,0xF6,0x76,0xEE,0xB5,0x3F,0xA9,0xBD,
+    0xB7,0xF6,0xF3,0xDD,0xC8,0x60,0x60,0x60,0xD3,0xD5,0xF0,0xBC,0x3E,0x2F,0x37,0x3F,
+    0x96,0xEE,0xF4,0xDD,0x2B,0x0D,0x0B,0x29,0xB6,0xF6,0x96,0xEE,0x7F,0xF6,0x78,0xFB,
+    0x96,0xEE,0x14,0xDE,0x78,0x78,0x78,0x68,0xB3,0xD5,0x51,0xC5,0x00,0xB8,0x7C,0x7E,
+    0xB3,0xD5,0x71,0xCD,0xA0,0xFA,0x75,0x55,0xB2,0xCD,0x51,0xC5,0xAA,0x8A,0xAA,0xED,
+    0x72,0xCD,0x0C,0xA4,0x78,0x78,0x78,0xF8,0xB3,0xD5,0x8E,0xAC,0x2D,0x2D,0x29,0x09,
+    0x14,0xDE,0xB2,0xD5,0xAD,0x2F,0xB7,0xB5,0x55,0xEE,0xF3,0xDD,0xBF,0xBF,0xAF,0x37,
+    0x96,0xEE,0x34,0xE6,0x2F,0xAD,0xBF,0x2F,0x96,0xEE,0x55,0xE6,0x78,0xFA,0xA8,0x7A,
+    0x55,0xE6,0x14,0xE6,0xE0,0x08,0xA8,0x80,0x55,0xE6,0x35,0xE6,0x3F,0x9E,0xDB,0x23,
+    0xD6,0xF6,0xB6,0xEE,0xAF,0xEA,0xAA,0xAA,0xD7,0xF6,0xB6,0xEE,0xBA,0xE8,0xBE,0xBA,
+    0xB7,0xF6,0xD6,0xEE,0xBF,0xFF,0xB7,0x1F,0xD7,0xF6,0xB6,0xEE,0xA2,0xB3,0x2A,0xBB,
+    0xD7,0xF6,0xB6,0xEE,0xA2,0x0A,0x82,0x02,0xD6,0xF6,0xD7,0xEE,0xAA,0xAA,0xA2,0xAA,
+    0xD6,0xF6,0xB6,0xEE,0x21,0xCB,0x0A,0xAA,0xD6,0xF6,0xB6,0xEE,0xA2,0xA8,0x2A,0x02,
+    0xD7,0xF6,0xD6,0xEE,0xA2,0xAB,0x2A,0xA8,0xF7,0xF6,0xB6,0xEE,0xBF,0xAE,0xAB,0xAF,
+    0xF7,0xF6,0xD7,0xF6,0xFD,0xF5,0xD7,0x5E,0xF7,0xF6,0xB6,0xEE,0xFA,0xEA,0xEE,0xEA,
+    0xD6,0xF6,0xB6,0xEE,0x5E,0x5E,0x5F,0xFF,0xD6,0xF6,0x96,0xEE,0xFE,0xEF,0xAA,0xFA,
+    0xD6,0xF6,0x95,0xEE,0xAF,0xB7,0xFF,0xFF,0xD6,0xF6,0xB6,0xEE,0xFD,0x5F,0xFF,0x7D,
+    0xB7,0xF6,0xB6,0xEE,0xFD,0xFF,0xD7,0xFF,0xD6,0xF6,0xB6,0xEE,0xBD,0xB7,0xD5,0xB5,
+    0xD6,0xF6,0xF8,0xEE,0xA0,0x88,0x20,0x08,0xD7,0xF6,0xF6,0xEE,0x02,0xA8,0x2A,0x80,
+    0xF7,0xF6,0xB6,0xEE,0xBE,0xAF,0xEB,0x8A,0xF7,0xF6,0xB6,0xEE,0xB6,0xAB,0xBA,0xAB,
+    0xD6,0xF6,0xF8,0xEE,0x20,0x88,0x20,0x00,0xF7,0xF6,0xD7,0xF6,0xFD,0xEF,0xF5,0x55,
+    0xF7,0xF6,0xB6,0xF6,0xBA,0xFA,0xF8,0xFE,0xB7,0xF6,0x14,0xDE,0x40,0xC0,0xC0,0x00,
+    0x51,0xC5,0x43,0x49,0x5E,0x5C,0x5C,0x58,0x23,0x41,0xE2,0x40,0x01,0x2D,0xDD,0xEF,
+    0x43,0x49,0x03,0x41,0xB8,0x2A,0x2F,0x0D,0x64,0x51,0x23,0x41,0x5D,0xAB,0x2E,0xBB,
+    0x44,0x49,0x03,0x41,0x57,0xD8,0x70,0x70,0x44,0x49,0xE2,0x38,0xF7,0xF7,0xBF,0x2E,
+    0x64,0x51,0x03,0x41,0xD7,0xB7,0x0F,0x02,0xE5,0x59,0x43,0x49,0xB5,0x2F,0x05,0xAD,
+    0x47,0x6A,0xA4,0x59,0xAD,0x2B,0x2B,0x0A,0x88,0x72,0x26,0x6A,0x29,0x8F,0xAF,0xC3,
+    0xC8,0x7A,0x67,0x72,0x03,0xAA,0x2B,0xC9,0x09,0x83,0xA8,0x7A,0x82,0x83,0xED,0x5D,
+    0xC9,0x82,0x47,0x72,0xF8,0xE2,0xEA,0x7B,0xA8,0x7A,0x47,0x6A,0x2E,0xFA,0xDF,0x9F,
+    0xA8,0x7A,0x47,0x6A,0xE2,0xFA,0x5F,0x57,0x87,0x72,0x26,0x6A,0xA8,0xB6,0x0A,0x8E,
+    0x67,0x72,0x26,0x6A,0x3C,0xF7,0xB0,0x20,0xC8,0x7A,0x26,0x6A,0xAA,0xA3,0xA9,0xFB,
+    0x4A,0x93,0x87,0x72,0x2F,0xAF,0xE5,0x7D,0x6B,0x9B,0xC8,0x82,0x0A,0x8B,0xAF,0xFD,
+    0x8B,0x9B,0x09,0x8B,0xCA,0x8B,0xEA,0xFD,0x29,0x8B,0xC8,0x82,0xD8,0xF8,0x78,0x60,
+    0xC8,0x82,0xE6,0x69,0xF8,0xE8,0xF8,0x5A,0x05,0x6A,0xA4,0x61,0xF8,0xDE,0xDA,0xFA,
+    0x47,0x72,0xC4,0x69,0xB5,0xBF,0xB9,0x25,0x88,0x82,0x27,0x72,0xAB,0xAA,0x2B,0xE5,
+    0x47,0x7A,0x84,0x69,0xF0,0x60,0xE0,0xE8,0xC5,0x71,0x64,0x61,0x28,0x2E,0xB5,0xF5,
+    0x06,0x82,0xA5,0x69,0xAF,0xBF,0xBD,0xBF,0x67,0x8A,0xE6,0x79,0xAD,0xA7,0x2F,0xAE,
+    0x87,0x8A,0x46,0x82,0x4F,0xE7,0x77,0x5D,0x87,0x8A,0x26,0x82,0x28,0xBA,0xB7,0x55,
+    0xE8,0x92,0x46,0x82,0x2D,0xB5,0xBF,0xFF,0x6A,0xA3,0xA8,0x8A,0x2B,0xA9,0xAD,0x25,
+    0x96,0xF6,0x8A,0xA3,0x2D,0x2D,0x2D,0x2D,0xD7,0xFE,0x17,0xF7,0xF8,0xE8,0xF8,0xEA,
+    0x17,0xFF,0xF7,0xF6,0xAA,0xA2,0xAA,0x0B,0x18,0xFF,0xF7,0xF6,0x8A,0x02,0x0A,0x2A,
+    0x18,0xFF,0xF7,0xEE,0x8A,0x8A,0x00,0x80,0x38,0xFF,0x17,0xF7,0xB7,0xED,0xEF,0xFD,
+    0x18,0xFF,0x38,0xF7,0xEE,0xAF,0xAE,0xA8,0x37,0xFF,0x18,0xF7,0xBE,0xAF,0xDB,0xBF,
+    0x38,0xFF,0x18,0xFF,0xAA,0xEA,0x8A,0x8B,0x38,0xFF,0x18,0xF7,0xFF,0xAB,0xA8,0xA8,
+    0x18,0xFF,0x37,0xF7,0x0A,0x2A,0x0A,0x02,0x18,0xFF,0x37,0xF7,0x08,0x20,0xB0,0x20,
+    0x18,0xFF,0xB6,0xEE,0xA0,0xE8,0x78,0x7A,0xD7,0xF6,0x96,0xEE,0xD8,0x5E,0xFF,0xEE,
+    0xB6,0xF6,0x96,0xEE,0xAF,0xFE,0xFE,0xA0,0xB6,0xF6,0x96,0xEE,0xEA,0xEB,0xEA,0xFB,
+    0x96,0xEE,0x54,0xEE,0xE0,0xC0,0xC0,0xC0,0x54,0xE6,0x71,0xCD,0x00,0x80,0xA8,0x78,
+    0x55,0xEE,0x10,0xC5,0x00,0xAA,0xFB,0x57,0x14,0xE6,0x71,0xCD,0x80,0xEA,0xFD,0x09,
+    0xF3,0xDD,0x10,0xC5,0x00,0xFE,0x7E,0xA8,0x55,0xE6,0x31,0xC5,0x00,0x0F,0xBD,0xF7,
+    0xD7,0xFE,0x14,0xDE,0x02,0x2B,0x2F,0xAD,0xF7,0xF6,0x96,0xF6,0x82,0x2A,0xAA,0xAB,
+    0xF7,0xF6,0xD7,0xF6,0xA7,0xBD,0xED,0xA6,0xF7,0xF6,0xD7,0xF6,0xAB,0x21,0x89,0xA2,
+    0x18,0xFF,0xD7,0xF6,0xBE,0xEA,0xFB,0xFB,0xD7,0xFE,0xF7,0xF6,0xFD,0x5D,0xF5,0xF7,
+    0xF7,0xF6,0xD7,0xF6,0xA8,0x5E,0x55,0xFF,0xF7,0xF6,0xD7,0xF6,0x55,0xD5,0xAB,0xAA,
+    0xF7,0xF6,0xD7,0xF6,0x5F,0xFB,0x7F,0xBC,0xD7,0xF6,0xF7,0xEE,0x20,0x08,0x00,0x22,
+    0xD7,0xF6,0xB7,0xEE,0xB8,0xA8,0xC8,0x42,0xD7,0xF6,0xB6,0xEE,0xA4,0x22,0xBF,0xFD,
+    0xD7,0xF6,0xB7,0xEE,0xEE,0x2A,0x8A,0x02,0xB6,0xF6,0xF7,0xEE,0xAA,0xAA,0xBB,0xFA,
+    0xF7,0xF6,0xB6,0xEE,0xDF,0xFF,0xAF,0xAB,0xF7,0xF6,0xB7,0xEE,0xAF,0xA9,0x2F,0xA8,
+    0xF7,0xF6,0xD8,0xF6,0x8F,0x8A,0xA8,0xA0,0xF8,0xF6,0xD7,0xF6,0xA2,0xF8,0xDE,0xEA,
+    0xF8,0xF6,0xD7,0xF6,0xBA,0xAB,0x3E,0x8A,0x18,0xFF,0xD7,0xF6,0xAF,0xAB,0xFE,0xBF,
+    0xF7,0xFE,0xF8,0xF6,0xF7,0xFD,0xD7,0x7F,0x18,0xFF,0xD7,0xF6,0xEE,0xAA,0xEE,0x7F,
+    0xF7,0xF6,0xB8,0xF6,0xA2,0xAE,0xAA,0xEB,0xF8,0xF6,0xD7,0xF6,0xFF,0xDE,0x5D,0x55,
+    0x18,0xFF,0xD7,0xF6,0x2B,0x3F,0xBD,0xBF,0x18,0xFF,0xB6,0xEE,0x58,0x78,0xFA,0xFA,
+    0xB6,0xEE,0x76,0xE6,0x57,0x57,0xFE,0xFC,0x76,0xEE,0x96,0xE6,0x2F,0x8B,0xAA,0x28,
+    0x96,0xEE,0x76,0xEE,0x9B,0xA2,0xFB,0xFD,0x96,0xEE,0x76,0xEE,0x0D,0x2B,0x2D,0x3F,
+    0xB6,0xF6,0xF4,0xDD,0x60,0x60,0x68,0x62,0xD3,0xD5,0xF0,0xBC,0x37,0x3F,0x2F,0x2E,
+    0x96,0xF6,0x14,0xE6,0x2D,0xAD,0xAD,0x25,0xB6,0xF6,0x76,0xEE,0xEA,0xFB,0xFF,0xFF,
+    0x96,0xEE,0x14,0xE6,0x60,0x70,0xEA,0xE8,0xF4,0xDD,0x31,0xC5,0x7E,0x7A,0x7C,0xF8,
+    0x71,0xCD,0x51,0xC5,0x2E,0xB9,0xE7,0xCE,0x71,0xCD,0x51,0xC5,0x20,0x2E,0x25,0x3D,
+    0x72,0xCD,0xCF,0xB4,0x5C,0x5C,0x7C,0xA8,0xB3,0xD5,0x10,0xC5,0x0D,0x0B,0x03,0x0A,
+    0x14,0xDE,0xB3,0xD5,0xBD,0x3F,0x2F,0x23,0x55,0xE6,0xF4,0xDD,0x2D,0x35,0xB7,0xB7,
+    0x76,0xEE,0x55,0xE6,0x23,0x82,0x0B,0x0D,0x96,0xEE,0x35,0xE6,0xA8,0xC8,0xA8,0xAA,
+    0x75,0xEE,0x35,0xE6,0xFF,0xF8,0xFA,0xEA,0x35,0xEE,0x55,0xE6,0x77,0x6D,0x7F,0x5F,
+    0xD6,0xF6,0xB6,0xEE,0xAA,0xAA,0x8A,0x02,0xD7,0xF6,0xB5,0xEE,0x22,0x22,0x28,0x20,
+    0xD7,0xF6,0xB6,0xEE,0x6E,0xC8,0xF8,0xC8,0xD6,0xF6,0xB6,0xEE,0xB9,0x23,0x02,0x02,
+    0xD6,0xF6,0xB7,0xE6,0x08,0x8A,0x08,0xA2,0xF7,0xF6,0xB6,0xEE,0xDB,0x5A,0xFF,0xBF,
+    0xD7,0xF6,0xB6,0xEE,0x1B,0x29,0x2C,0x00,0xD7,0xF6,0xD6,0xEE,0xAA,0x22,0xAA,0xAA,
+    0xD7,0xF6,0xF7,0xEE,0x28,0x08,0x20,0xAA,0xF6,0xF6,0xB7,0xEE,0xA7,0xBE,0xAB,0xAB,
+    0xD6,0xF6,0xF7,0xEE,0x2A,0x2A,0x20,0x82,0xD6,0xF6,0xF8,0xEE,0x08,0x80,0x28,0xA8,
+    0xD6,0xF6,0xB6,0xEE,0xEE,0x68,0xF8,0x6C,0xD6,0xF6,0x96,0xEE,0xBB,0xEF,0xAF,0x0F,
+    0xD6,0xF6,0x96,0xEE,0xFF,0xFE,0xF2,0xC2,0xD6,0xF6,0xB6,0xEE,0xFD,0xF7,0xBD,0xBB,
+    0xD7,0xF6,0xB6,0xEE,0x7D,0xFF,0xAD,0xEE,0xD6,0xF6,0xB6,0xEE,0xB5,0xBD,0xBB,0xB6,
+    0xF7,0xF6,0xD7,0xF6,0xDF,0xFD,0xDD,0xFD,0xF7,0xF6,0xD7,0xF6,0xDD,0xBF,0x3A,0x8D,
+    0xF7,0xF6,0xD7,0xF6,0xEA,0xF8,0xDA,0xFE,0xF6,0xF6,0xD7,0xF6,0xB5,0xFB,0xFF,0xED,
+    0xF7,0xF6,0xD7,0xF6,0x79,0x6B,0xFB,0x9B,0xD7,0xF6,0xF7,0xEE,0x00,0x80,0x0E,0x02,
+    0xF7,0xF6,0x96,0xEE,0xAA,0x2A,0x8A,0xA2,0xF7,0xFE,0x76,0xEE,0x6A,0xE0,0xEA,0xEA,
+    0xF4,0xDD,0x42,0x41,0x58,0x78,0x78,0x78,0x03,0x39,0xC1,0x38,0xAA,0x1D,0x24,0xBA,
+    0x64,0x49,0x02,0x41,0x3F,0xAB,0x2F,0x65,0x84,0x51,0x23,0x49,0xE2,0xA2,0xA9,0xF5,
+    0x64,0x49,0xE2,0x40,0xF8,0x5A,0xFB,0x7E,0x43,0x49,0x03,0x41,0xFF,0xBB,0x2D,0x29,
+    0xC5,0x59,0x44,0x49,0x35,0x2D,0x09,0x0A,0x27,0x6A,0x84,0x51,0xAD,0xAF,0x2A,0x3B,
+    0x27,0x6A,0xA4,0x59,0x08,0x88,0xA8,0x7E,0x67,0x72,0x85,0x59,0x20,0x2A,0xAD,0xAD,
+    0xA8,0x7A,0x46,0x6A,0x83,0xAA,0xA5,0xF5,0xA8,0x7A,0x47,0x6A,0x82,0x8A,0xEF,0x7F,
+    0x88,0x72,0x47,0x72,0xB0,0xBA,0xCD,0xB5,0x88,0x72,0x06,0x6A,0xA0,0xAF,0x97,0xAB,
+    0x67,0x72,0x26,0x6A,0xA6,0x02,0x2B,0xEF,0x67,0x72,0x26,0x6A,0x80,0xF0,0x68,0xD8,
+    0x67,0x72,0x06,0x62,0xB0,0xBF,0xFD,0xFF,0xA7,0x7A,0xE5,0x61,0x0A,0xAD,0xAB,0xFF,
+    0xC8,0x7A,0x67,0x72,0xAB,0xAE,0xAB,0x0D,0xE9,0x82,0x87,0x7A,0x0B,0xBF,0xEF,0xF7,
+    0x2A,0x8B,0x88,0x7A,0x0A,0xBE,0xFF,0xD5,0xE9,0x8A,0x46,0x72,0xA0,0xE0,0x7A,0x5E,
+    0x67,0x7A,0xA4,0x61,0xE0,0xF8,0x7E,0x5F,0xE5,0x69,0x83,0x59,0xBC,0xE7,0xCF,0x2E,
+    0x26,0x72,0xC5,0x69,0xAD,0x3D,0x3D,0x2A,0x68,0x7A,0xE6,0x69,0xEA,0xF8,0x6A,0x7E,
+    0x06,0x72,0x64,0x61,0xE0,0x72,0x72,0x5A,0x84,0x69,0x22,0x59,0x2A,0x27,0x37,0xBF,
+    0x06,0x7A,0x63,0x61,0x0B,0x2F,0xAD,0xBF,0x47,0x82,0x06,0x7A,0xAF,0xA6,0xF5,0x75,
+    0x67,0x8A,0x06,0x82,0xC0,0xCA,0x69,0xCB,0x47,0x82,0x26,0x82,0xB2,0xDD,0x95,0x55,
+    0xE9,0x92,0x47,0x82,0xAD,0xAB,0x2D,0x2F,0x29,0x9B,0xA8,0x8A,0x27,0xB7,0xFB,0xFF,
+    0xB6,0xF6,0x6B,0xA3,0x2D,0x2D,0x2D,0x2D,0x17,0xFF,0xD7,0xFE,0xAD,0xBD,0xAD,0xBF,
+    0xF7,0xFE,0x18,0xF7,0xBE,0xFA,0xFE,0xFE,0x18,0xFF,0xF7,0xF6,0xAF,0x89,0xAB,0xAB,
+    0x17,0xFF,0xF7,0xF6,0x82,0x8A,0x2A,0xB6,0x18,0xFF,0x17,0xF7,0xEA,0xAA,0xA2,0xAA,
+    0x38,0xFF,0xF7,0xF6,0xAE,0xBA,0x2F,0xBF,0x38,0xFF,0x17,0xF7,0xFF,0xAE,0xAA,0xFF,
+    0x38,0xFF,0x18,0xFF,0x2A,0xAA,0xBB,0xEB,0x38,0xFF,0x18,0xFF,0xA2,0xAA,0xFA,0xD5,
+    0x18,0xFF,0x38,0xF7,0x08,0x02,0xC0,0xAA,0x38,0xFF,0xD7,0xF6,0x6A,0xEA,0x78,0x57,
+    0xD7,0xF6,0xB6,0xEE,0xE0,0xA8,0xA8,0xAA,0xD7,0xF6,0xB6,0xEE,0xAF,0x0A,0x08,0x02,
+    0xD7,0xF6,0xB6,0xF6,0xAB,0xEA,0xEA,0x5C,0xB6,0xF6,0x75,0xEE,0xA2,0xA0,0xA8,0xD8,
+    0x96,0xEE,0x55,0xEE,0xE0,0xE0,0xF8,0xF7,0xB6,0xF6,0x30,0xCD,0x7A,0x7E,0xEA,0x00,
+    0x75,0xEE,0xAE,0xBC,0xD7,0xB7,0x2A,0x00,0x76,0xEE,0xD3,0xDD,0x2D,0x0B,0x00,0x08,
+    0x75,0xEE,0xB2,0xD5,0x58,0xE2,0xA0,0x00,0x14,0xE6,0x71,0xCD,0xF5,0xDF,0xF6,0xF8,
+    0x76,0xEE,0xD3,0xD5,0x0B,0x2D,0xB5,0xB5,0xF7,0xF6,0x55,0xE6,0x2A,0x8B,0x2B,0xBD,
+    0xF7,0xF6,0xD7,0xF6,0x8A,0xAB,0xEF,0x95,0xF8,0xF6,0xD7,0xF6,0xAA,0x9D,0x3E,0xFA,
+    0xD8,0xFE,0xF7,0xF6,0xDD,0x5D,0x75,0xFD,0xF7,0xF6,0xD7,0xF6,0xAA,0x88,0x80,0xFC,
+    0xF7,0xF6,0xD7,0xF6,0xEC,0xB2,0xD0,0x5D,0xF7,0xF6,0xD7,0xF6,0x88,0x82,0xFD,0x55,
+    0xF7,0xF6,0xB7,0xF6,0xA0,0xFA,0xD7,0xDB,0xF7,0xF6,0xB7,0xF6,0x7A,0x7F,0xDF,0xBF,
+    0xF7,0xF6,0xB6,0xEE,0x5F,0x55,0x95,0xAA,0xF7,0xF6,0xB6,0xEE,0xF5,0xFB,0xAA,0x2A,
+    0xF7,0xF6,0xD7,0xF6,0x5D,0xF5,0xAA,0xA0,0x18,0xFF,0xD7,0xF6,0x75,0xBF,0xEB,0xEB,
+    0xF7,0xF6,0xD7,0xF6,0xAD,0x02,0x00,0x80,0xF8,0xFE,0xF7,0xF6,0xFF,0xFF,0x5D,0x55,
+    0xF8,0xF6,0xD8,0xF6,0x00,0x20,0xF8,0xAE,0xF8,0xF6,0xD7,0xF6,0x80,0xEE,0xFC,0x8A,
+    0xF8,0xF6,0xD8,0xF6,0x00,0x86,0xAE,0xFE,0xF7,0xF6,0xD8,0xF6,0x2E,0xAF,0xFF,0x5A,
+    0xF8,0xF6,0xD7,0xF6,0xE0,0x80,0xCA,0xAD,0xF8,0xF6,0xD7,0xF6,0x7F,0xFF,0xFD,0xA9,
+    0xF8,0xF6,0xD7,0xF6,0x59,0x7F,0x6E,0x5A,0xD7,0xF6,0xD8,0xEE,0xAA,0xA2,0xAA,0x2A,
+    0xF7,0xF6,0xB7,0xEE,0x0A,0x3B,0x2F,0xBF,0x18,0xFF,0xB7,0xEE,0xFA,0xFA,0x62,0xFA,
+    0xB7,0xEE,0x75,0xEE,0xFA,0xD8,0x78,0xFC,0x76,0xEE,0x96,0xE6,0x08,0x02,0x8A,0x0F,
+    0x96,0xEE,0x55,0xEE,0x8A,0xEE,0xFF,0xDF,0xB7,0xEE,0x56,0xEE,0xEB,0xAF,0x2D,0xAF,
+    0x96,0xEE,0xF4,0xDD,0x60,0x60,0xE0,0xC0,0xD3,0xDD,0x10,0xBD,0x3D,0xA5,0x26,0x27,
+    0x96,0xEE,0xF4,0xDD,0x2B,0x2D,0xAD,0x2F,0xB7,0xF6,0x76,0xEE,0xFE,0xEA,0xFA,0x7A,
+    0x96,0xEE,0x35,0xE6,0xF2,0xEA,0xFC,0x7A,0x14,0xDE,0x72,0xCD,0x5C,0x5C,0x58,0x78,
+    0x92,0xCD,0x51,0xCD,0xFF,0x3E,0xEF,0x55,0x92,0xD5,0x31,0xC5,0xE3,0xFA,0xDE,0x5F,
+    0xB2,0xD5,0x10,0xC5,0xFB,0xAF,0xAF,0x25,0xF3,0xDD,0x92,0xCD,0xB5,0xAD,0x2F,0x2B,
+    0x14,0xDE,0xD3,0xDD,0x0F,0xAF,0xAB,0xC2,0x55,0xE6,0xF4,0xDD,0xBD,0xB7,0x37,0x97,
+    0x96,0xEE,0x55,0xE6,0x2D,0x2D,0x8B,0xAD,0x96,0xEE,0x76,0xEE,0x7C,0x6B,0xFB,0xFF,
+    0x75,0xEE,0x55,0xE6,0x58,0xBA,0xE8,0xFA,0x96,0xEE,0x34,0xE6,0xFD,0xAF,0x3F,0xAB,
+    0xF7,0xF6,0xB6,0xEE,0xAB,0xEB,0xEB,0xFE,0xF7,0xF6,0xB6,0xEE,0xFA,0xFE,0xFF,0xF7,
+    0xD7,0xF6,0xD6,0xEE,0xAA,0x22,0xAA,0xAA,0xD7,0xF6,0xF6,0xEE,0x00,0x22,0xA8,0x2A,
+    0xF7,0xF6,0xB6,0xEE,0xEF,0xFE,0xAA,0xCA,0xD7,0xF6,0xB6,0xEE,0x8A,0x2A,0x08,0x83,
+    0xD7,0xF6,0xF6,0xEE,0x08,0x82,0x08,0x38,0xD7,0xF6,0xF7,0xEE,0x80,0x08,0x22,0x82,
+    0xD7,0xF6,0xF6,0xEE,0xE8,0xA0,0x20,0x08,0xD7,0xF6,0xF7,0xEE,0x88,0x22,0x20,0xA2,
+    0xF7,0xF6,0xD7,0xF6,0xB7,0xFD,0xFF,0x7F,0xF6,0xF6,0xD7,0xF6,0xEF,0xFD,0xD7,0x57,
+    0xD7,0xF6,0xB5,0xEE,0xE0,0xA0,0xA8,0xE8,0xD7,0xF6,0xB6,0xEE,0xAA,0x6A,0xEA,0xEE,
+    0xD6,0xF6,0xB6,0xEE,0xEB,0xB5,0x9F,0xB2,0xD7,0xF6,0xB6,0xEE,0x55,0xF7,0x76,0xDF,
+    0xD6,0xF6,0xB6,0xEE,0xFE,0x57,0xFE,0xA3,0xD6,0xF6,0xB6,0xEE,0x3F,0xAB,0x29,0xAD,
+    0xF7,0xF6,0xB6,0xEE,0xAA,0xAA,0xAF,0xEB,0xF7,0xF6,0xD7,0xF6,0x89,0x97,0x5D,0x5D,
+    0xF7,0xF6,0xD7,0xF6,0xFF,0x6F,0x6C,0x7D,0xF7,0xF6,0xD7,0xF6,0xF5,0x5F,0x75,0xBD,
+    0xF7,0xF6,0xD7,0xF6,0x3E,0xBA,0xAB,0xBB,0xF7,0xF6,0xD7,0xF6,0xFA,0xA2,0x4C,0xEA,
+    0xF7,0xF6,0xD7,0xF6,0x5E,0xFA,0x5E,0x6A,0xF7,0xF6,0xB6,0xEE,0xCA,0xEA,0xEA,0x7A,
+    0x34,0xDE,0xE5,0x59,0x78,0x70,0x60,0x60,0x43,0x41,0xC2,0x38,0x5E,0xFE,0x7C,0x7A,
+    0x23,0x49,0x81,0x30,0x0A,0x2B,0xAD,0xAF,0x64,0x51,0x03,0x41,0xAF,0x8F,0xA5,0x3D,
+    0x85,0x51,0x02,0x41,0x5F,0xFA,0xAE,0x02,0xC5,0x61,0x43,0x49,0xF5,0xB9,0xAA,0x0A,
+    0x06,0x62,0x84,0x59,0xE5,0xBF,0x2F,0x02,0xE6,0x61,0xA5,0x59,0xA2,0xE0,0xE0,0xBC,
+    0xC5,0x59,0x64,0x59,0x80,0x88,0xAA,0x3A,0xE6,0x61,0xA5,0x59,0x0E,0xBD,0x79,0x5A,
+    0x26,0x6A,0xA5,0x59,0x02,0xAA,0xE9,0xA7,0x47,0x72,0xE6,0x61,0x03,0xA2,0xAA,0xED,
+    0x47,0x6A,0x06,0x62,0xEA,0xFF,0xFB,0xFF,0x68,0x72,0xE5,0x61,0x0A,0x2B,0xAB,0xB5,
+    0x88,0x72,0x05,0x62,0xE2,0xF0,0x7A,0xDF,0x47,0x6A,0x06,0x62,0xF0,0x70,0xDD,0x57,
+    0x26,0x6A,0x05,0x62,0xAC,0xBA,0x57,0x7D,0x67,0x72,0xE5,0x61,0xBA,0x2E,0xED,0xF7,
+    0xC9,0x7A,0x26,0x6A,0x2D,0xAF,0xBB,0xF5,0xE9,0x82,0x47,0x72,0x8E,0xAE,0x77,0x55,
+    0x88,0x7A,0xE6,0x61,0x00,0xA8,0xEE,0x5F,0x47,0x72,0xA4,0x59,0xE8,0xEA,0x7A,0x7F,
+    0x05,0x6A,0x83,0x59,0x7F,0xF7,0xBF,0x2F,0x47,0x7A,0xA4,0x61,0xB5,0xBF,0x2A,0x02,
+    0x68,0x7A,0x26,0x72,0x7D,0x7F,0x7B,0x70,0x26,0x72,0xC5,0x69,0x78,0x78,0x78,0x70,
+    0xC5,0x69,0xE3,0x50,0xE8,0xFC,0x7E,0xDE,0x44,0x59,0x03,0x59,0x22,0x03,0x9A,0xAF,
+    0xA5,0x69,0x44,0x61,0x0A,0x2B,0x2F,0xFD,0x06,0x7A,0xA5,0x69,0x02,0xAB,0x1F,0xB9,
+    0x87,0x8A,0x27,0x82,0x7D,0xF5,0xF5,0x27,0x87,0x8A,0x26,0x7A,0x5D,0xDB,0xF3,0xFE,
+    0xC8,0x8A,0x47,0x82,0xBD,0xBF,0xAD,0x29,0x29,0x93,0x87,0x82,0x9F,0x75,0x37,0x37,
+    0x96,0xF6,0xEC,0xAB,0x2D,0x2D,0x29,0x09,0xF7,0xFE,0xD7,0xF6,0x0A,0x08,0x02,0x03,
+    0xF7,0xFE,0x17,0xF7,0xEE,0xEA,0xEE,0xE8,0xF7,0xFE,0x18,0xF7,0xEF,0xAE,0xFF,0xBB,
+    0x17,0xFF,0xF7,0xF6,0x9E,0xB5,0xBD,0xAB,0xF7,0xFE,0x18,0xF7,0x9B,0x5B,0xBF,0xBF,
+    0x17,0xFF,0xF7,0xF6,0x2B,0xAE,0xAE,0xEB,0x17,0xFF,0xF7,0xF6,0xA0,0xBF,0xB7,0xDF,
+    0x17,0xFF,0xF8,0xF6,0x00,0xAA,0xEF,0xAF,0x18,0xFF,0xF7,0xF6,0x22,0x0A,0x02,0x0A,
+    0x38,0xFF,0xD7,0xF6,0xA8,0xF2,0x7A,0x7E,0xF7,0xF6,0xB6,0xEE,0xF0,0xF8,0xFA,0xFF,
+    0xD7,0xF6,0xB6,0xEE,0x29,0xAB,0xFA,0xFE,0xB6,0xF6,0xD7,0xEE,0xFE,0xBE,0xAE,0xEF,
+    0xD6,0xF6,0x96,0xEE,0x7A,0xFE,0x7F,0x5E,0x96,0xEE,0x92,0xD5,0xA0,0xA8,0xEA,0x5A,
+    0xD7,0xF6,0x71,0xCD,0x2A,0xAB,0x0F,0x2D,0x18,0xFF,0xD7,0xFE,0xBD,0xAF,0x2E,0xAA,
+    0x18,0xFF,0x96,0xF6,0x5E,0x7A,0xE8,0xA2,0xD7,0xF6,0x75,0xEE,0x55,0x5E,0x5F,0x5C,
+    0x75,0xEE,0x55,0xEE,0x98,0x38,0xB8,0x78,0x55,0xEE,0xB2,0xD5,0xFC,0x70,0xE0,0x80,
+    0x34,0xE6,0xB2,0xD5,0x2B,0x3D,0x35,0xAF,0xB6,0xF6,0x14,0xDE,0x2F,0x2F,0xBD,0xED,
+    0xF7,0xF6,0x96,0xF6,0x2A,0x2B,0x2F,0x2D,0xF7,0xF6,0xD7,0xF6,0x7E,0xAF,0xEB,0x6B,
+    0xF7,0xF6,0xD7,0xF6,0xAD,0xFE,0xE8,0xA3,0xF7,0xF6,0xD7,0xF6,0xFE,0x5B,0x6B,0xEA,
+    0xF7,0xF6,0xD7,0xF6,0x75,0xFF,0xA9,0x0F,0xF7,0xF6,0xD7,0xF6,0x75,0xFB,0xFE,0xD7,
+    0xF7,0xF6,0xD7,0xF6,0x55,0xF5,0xBD,0xCF,0xF8,0xF6,0xD7,0xF6,0xD5,0x2D,0x01,0x0A,
+    0xF7,0xF6,0xD7,0xF6,0x5C,0x76,0x54,0x5C,0xF7,0xF6,0xD7,0xF6,0x95,0x57,0xB5,0xA5,
+    0xF7,0xF6,0xD7,0xF6,0xB8,0xAE,0xE6,0xE2,0xF7,0xF6,0xB7,0xF6,0x00,0x2C,0x2E,0x82,
+    0xD7,0xF6,0xF7,0xEE,0xAB,0x8B,0xAA,0xAC,0xF7,0xF6,0xD7,0xF6,0xAA,0x2B,0x8E,0xFA,
+    0xF7,0xF6,0xD7,0xF6,0x08,0x22,0x02,0xBA,0xF7,0xF6,0xD8,0xF6,0xAA,0xB8,0xA8,0x88,
+    0xF7,0xF6,0xD7,0xF6,0xFE,0xBA,0xA2,0x20,0xF7,0xF6,0xD7,0xF6,0x78,0xAA,0x80,0x20,
+    0xF7,0xF6,0xD8,0xF6,0x8A,0x8A,0x00,0x80,0xD8,0xFE,0xF8,0xF6,0xD5,0x55,0x7D,0xF5,
+    0xF7,0xF6,0xD7,0xF6,0xE4,0x6A,0x60,0x7A,0xD7,0xF6,0xB7,0xEE,0x8A,0xBA,0xDF,0xD6,
+    0xB7,0xF6,0x18,0xEF,0xA8,0xA8,0xAA,0xA8,0xF8,0xF6,0xB7,0xF6,0xE2,0xC0,0xC0,0xC2,
+    0xB6,0xEE,0x76,0xEE,0x7C,0x5E,0x7E,0x5E,0xB6,0xEE,0x56,0xE6,0xEB,0x7B,0xEB,0x2F,
+    0x96,0xEE,0x55,0xEE,0xDF,0xBA,0x08,0x00,0x96,0xF6,0x76,0xEE,0x2D,0xAB,0xE8,0xA2,
+    0xB7,0xF6,0x14,0xDE,0x60,0x6A,0x6A,0x72,0xF4,0xDD,0x51,0xC5,0x17,0xB7,0x37,0xB7,
+    0x97,0xEE,0x14,0xDE,0xBD,0xAD,0x25,0x2D,0x96,0xEE,0x55,0xEE,0xA0,0xE8,0xE0,0xFA,
+    0x75,0xEE,0x35,0xE6,0xF8,0xBA,0xE8,0xAE,0x35,0xE6,0x72,0xCD,0x7C,0x58,0x58,0x58,
+    0x72,0xCD,0x31,0xC5,0xBE,0x5E,0x58,0xD7,0x52,0xCD,0xD0,0xBC,0xE0,0xFB,0x7E,0x7A,
+    0xB2,0xD5,0xCF,0xBC,0x2B,0xAF,0x25,0x2D,0x34,0xE6,0xD2,0xD5,0xFD,0xB5,0xBD,0x2D,
+    0x14,0xE6,0x34,0xDE,0xA8,0xBF,0xAF,0xAF,0x55,0xE6,0xF3,0xDD,0xBD,0xBE,0xBF,0xAF,
+    0x96,0xEE,0x55,0xE6,0xBD,0xED,0x0D,0xAF,0x96,0xEE,0x76,0xEE,0x79,0x39,0xAF,0x8B,
+    0x75,0xEE,0x55,0xE6,0xF8,0xE8,0x82,0xA0,0x96,0xEE,0x55,0xE6,0xAF,0xAF,0xB7,0xBF,
+    0xD6,0xF6,0xB7,0xEE,0xB0,0x82,0xA8,0x2A,0xD7,0xF6,0xB6,0xEE,0xFA,0xEE,0xAA,0xA2,
+    0xD6,0xF6,0xB7,0xEE,0x8B,0x2E,0x8A,0xA8,0xD6,0xF6,0xB7,0xEE,0x80,0xF0,0x82,0x28,
+    0xD7,0xF6,0xB6,0xEE,0x2B,0xAA,0xAA,0xAC,0xD7,0xF6,0xB6,0xEE,0x02,0x02,0x00,0x8E,
+    0xD7,0xF6,0xF6,0xEE,0xA8,0x28,0x00,0x20,0xF7,0xF6,0xD7,0xF6,0x5F,0xFF,0xFF,0xF5,
+    0xD7,0xF6,0xF7,0xEE,0x22,0x00,0x82,0xA8,0xF7,0xF6,0xD7,0xF6,0xF5,0xBB,0xBE,0xAD,
+    0xF7,0xF6,0xD7,0xF6,0xFF,0xFF,0x2F,0xAD,0xF7,0xF6,0xD7,0xF6,0xBA,0xA9,0xAB,0xE8,
+    0xD7,0xF6,0xF6,0xEE,0x2A,0x02,0x08,0x2A,0xD6,0xF6,0xB7,0xEE,0x2A,0x2A,0xAC,0xAE,
+    0xD6,0xF6,0xB7,0xEE,0xA2,0x2A,0xAA,0x2A,0xD7,0xF6,0xB6,0xEE,0xBF,0xBE,0x88,0x80,
+    0xB6,0xF6,0xD6,0xEE,0xEF,0xAB,0xBB,0xED,0xB6,0xF6,0xD7,0xEE,0x8B,0xAB,0xFE,0xEF,
+    0xF6,0xF6,0xD7,0xF6,0x75,0xF5,0xED,0xAD,0xF7,0xF6,0xD7,0xF6,0xDD,0xF7,0xDD,0x57,
+    0xF7,0xF6,0xD7,0xF6,0x5F,0xE9,0xE3,0x7D,0xF7,0xF6,0xD7,0xF6,0xAD,0xBA,0xEB,0x6E,
+    0xF7,0xF6,0xD7,0xF6,0xFA,0xAF,0xEA,0x0C,0xF7,0xF6,0xD7,0xF6,0xAF,0xA8,0xEE,0xEA,
+    0xF7,0xF6,0xD7,0xF6,0x6A,0x5E,0x5D,0x9D,0xF7,0xF6,0xB6,0xEE,0x7A,0xEA,0xAB,0xAA,
+    0x75,0xEE,0x09,0x7B,0x70,0x70,0x60,0xE0,0xE4,0x59,0xC2,0x38,0x5E,0x5E,0x7A,0xF8,
+    0x64,0x51,0xC2,0x38,0xDD,0xA5,0xBF,0x2A,0xE5,0x61,0xE2,0x40,0xBD,0xBD,0x2B,0x2E,
+    0x06,0x6A,0x84,0x51,0xF5,0xBF,0xAA,0x80,0x26,0x6A,0xC5,0x59,0x9D,0x09,0xAB,0x80,
+    0x27,0x72,0x05,0x62,0xE9,0x8A,0x89,0xCA,0x26,0x6A,0xC6,0x61,0x64,0xC8,0xE8,0xA2,
+    0x06,0x62,0xA4,0x59,0x5B,0x7E,0xBE,0xE8,0xE5,0x61,0xA5,0x59,0xBF,0xFA,0xAF,0x8A,
+    0x27,0x6A,0xE6,0x61,0xE1,0x3F,0x09,0x09,0x47,0x6A,0x06,0x62,0x97,0xD7,0xE2,0x00,
+    0x47,0x6A,0xE5,0x61,0xF7,0x5F,0x7C,0xF8,0x26,0x6A,0xC4,0x59,0x2F,0xCF,0xFF,0x96,
+    0x06,0x6A,0xC5,0x59,0xBC,0xFE,0xBB,0xFA,0x05,0x6A,0xC5,0x59,0x2A,0xE9,0xFA,0xFA,
+    0x26,0x6A,0xC5,0x59,0xA2,0xFD,0xF7,0x5D,0x47,0x6A,0xE5,0x61,0x4B,0xAD,0xF5,0x5D,
+    0x47,0x6A,0xA4,0x59,0x0E,0xFA,0xEE,0x9E,0x26,0x6A,0xC4,0x59,0x88,0xC2,0x7B,0x57,
+    0x06,0x6A,0xA4,0x59,0xE8,0xAE,0xF6,0xFF,0xE5,0x69,0x83,0x59,0xDE,0xBA,0xBE,0x0E,
+    0x67,0x7A,0xC4,0x61,0xB5,0xAD,0x2D,0x0B,0xC8,0x8A,0x47,0x7A,0x5F,0xF7,0xAD,0x8A,
+    0xA8,0x82,0x47,0x7A,0x7B,0x7F,0xE8,0x80,0x68,0x7A,0x64,0x61,0xFA,0x7A,0x78,0xF8,
+    0x65,0x61,0xE2,0x50,0xB4,0xF6,0xFE,0xAC,0x85,0x61,0x23,0x59,0x55,0xE5,0xFD,0x8B,
+    0xA4,0x69,0x43,0x59,0xB5,0x15,0xBF,0x3B,0x67,0x82,0xC5,0x71,0xBD,0xA9,0x29,0x09,
+    0xA8,0x8A,0x47,0x82,0xFD,0x2D,0x8F,0x22,0xC8,0x8A,0x67,0x82,0x77,0xFA,0xAB,0xEA,
+    0xA8,0x8A,0x26,0x7A,0x0A,0x80,0xAA,0x7E,0x2D,0xAC,0x26,0x72,0xBF,0xB7,0xB5,0x25,
+    0xD7,0xFE,0xAF,0xBC,0x2D,0x29,0x09,0x0B,0x17,0xFF,0xD8,0xF6,0xEB,0x8B,0xAA,0x02,
+    0x18,0xFF,0xF7,0xF6,0xFF,0xCF,0xA3,0x82,0x17,0xFF,0xF7,0xF6,0xFE,0xF7,0xBD,0xBF,
+    0x18,0xFF,0xF7,0xF6,0x8B,0x2A,0xAA,0x2A,0xF7,0xFE,0x18,0xF7,0xE5,0xFF,0xEF,0xFF,
+    0x17,0xFF,0xF7,0xF6,0xEB,0xFE,0x7E,0x5E,0xF7,0xFE,0xF7,0xF6,0x5F,0xFF,0xFD,0xDF,
+    0x17,0xFF,0xD7,0xF6,0xAF,0x0B,0x2B,0x0B,0x18,0xFF,0xD7,0xF6,0x00,0x80,0x68,0x58,
+    0xF7,0xF6,0xB6,0xEE,0xB8,0x5E,0x57,0x77,0xB6,0xF6,0xD7,0xEE,0xAA,0xEB,0xEB,0xFA,
+    0x18,0xFF,0xB6,0xEE,0xF7,0xF7,0xFF,0x2B,0x38,0xFF,0xB6,0xEE,0x77,0xFD,0xBF,0x02,
+    0x18,0xFF,0x96,0xEE,0x57,0xFF,0xAA,0x00,0xD7,0xF6,0xB2,0xD5,0x7E,0xF8,0xE0,0xA8,
+    0xD7,0xF6,0xB2,0xD5,0x0D,0x2B,0x0A,0x0B,0xF8,0xFE,0x18,0xF7,0x88,0x20,0x28,0xAA,
+    0x17,0xFF,0xD8,0xF6,0xAB,0xA5,0xFB,0x2A,0x18,0xFF,0x76,0xEE,0x5E,0x7C,0x7A,0x78,
+    0x75,0xEE,0x55,0xE6,0x5E,0xF8,0xE8,0xB8,0x75,0xEE,0x34,0xEE,0xEA,0xEA,0xEA,0xAA,
+    0x35,0xE6,0xD2,0xD5,0xB6,0xBE,0xE0,0xA0,0x75,0xEE,0x14,0xDE,0x29,0xAF,0xAF,0x95,
+    0xF8,0xFE,0x55,0xE6,0x2B,0x2F,0xA9,0xAD,0xF7,0xF6,0xD7,0xF6,0x89,0xBE,0xBF,0xAB,
+    0xF7,0xF6,0xD7,0xF6,0xEA,0xE2,0xE2,0x0A,0xF7,0xF6,0xD7,0xF6,0x6E,0xDD,0x7F,0x80,
+    0xF7,0xF6,0xD7,0xF6,0xAD,0xA5,0xA9,0x05,0xF7,0xF6,0xD7,0xF6,0xB7,0xAF,0x6D,0xD7,
+    0xF7,0xF6,0xD7,0xF6,0xAA,0x57,0x55,0x55,0xF7,0xF6,0xD7,0xF6,0xE8,0x5E,0x5D,0x5F,
+    0xF7,0xF6,0xD7,0xF6,0x5F,0x7D,0xFF,0x7F,0xF7,0xF6,0xD7,0xF6,0xBF,0xFD,0x7F,0xFF,
+    0xD7,0xF6,0xF7,0xEE,0xAE,0x82,0xA8,0xEA,0xF7,0xF6,0xD7,0xF6,0xEB,0xE9,0xE9,0x5E,
+    0xF7,0xF6,0xD7,0xF6,0xAB,0xBA,0xAE,0x2E,0xF7,0xF6,0xD7,0xF6,0x25,0xA3,0xE2,0x7C,
+    0xF7,0xF6,0xD7,0xF6,0xAE,0x0A,0x2A,0x7B,0x18,0xFF,0xD7,0xF6,0xAA,0xAB,0xEF,0x55,
+    0xF7,0xF6,0xD7,0xEE,0x20,0xAC,0xD4,0xDD,0xF7,0xF6,0xD7,0xF6,0xA8,0xAA,0xB9,0x3D,
+    0xF7,0xF6,0xD7,0xF6,0x88,0xEA,0xAE,0x88,0xF7,0xF6,0xD7,0xF6,0xEA,0x78,0x5E,0x7F,
+    0xF7,0xF6,0xB7,0xEE,0xFA,0xFA,0x7E,0x5F,0xD7,0xF6,0x96,0xEE,0xAA,0xBA,0xBF,0xB7,
+    0xD7,0xF6,0xB7,0xEE,0x0A,0x22,0xAF,0x55,0xF7,0xF6,0xB7,0xEE,0xC2,0xEA,0xFB,0xAF,
+    0xD7,0xF6,0x75,0xE6,0x5F,0xFE,0x7A,0xDC,0xB6,0xEE,0x96,0xEE,0x75,0x75,0xFD,0xE5,
+    0x96,0xEE,0x76,0xEE,0x00,0xFC,0xDC,0x9C,0x96,0xEE,0x36,0xEE,0x28,0x2A,0x3A,0x2A,
+    0x97,0xF6,0xF4,0xDD,0x68,0x60,0x48,0x60,0xF4,0xDD,0x51,0xC5,0xB6,0xBE,0x3F,0x36,
+    0x96,0xEE,0x14,0xDE,0xAD,0xAF,0xAD,0xAD,0x96,0xEE,0x55,0xE6,0x7A,0x68,0x7E,0x5A,
+    0x75,0xEE,0x36,0xE6,0xAA,0xAA,0xFA,0xDF,0x55,0xE6,0x52,0xCD,0x78,0x78,0x68,0x78,
+    0x52,0xCD,0xAF,0xBC,0x88,0xA0,0xEA,0x7E,0x11,0xC5,0xAF,0xBC,0xF8,0x76,0xDB,0xF5,
+    0xD3,0xDD,0xCF,0xBC,0xAD,0x2D,0x2D,0x2D,0x34,0xE6,0xD2,0xD5,0x2D,0x29,0x22,0x0B,
+    0x55,0xE6,0x14,0xE6,0xEB,0xAA,0xAA,0xEA,0x54,0xE6,0x14,0xE6,0xB7,0xB7,0xB5,0xA9,
+    0x96,0xEE,0x34,0xE6,0x8A,0xAB,0x2E,0xA9,0xB6,0xF6,0x76,0xEE,0xEF,0xED,0xAB,0xAF,
+    0x95,0xEE,0x55,0xE6,0x5E,0x5E,0xDE,0xDE,0xB7,0xF6,0x55,0xE6,0xBD,0xAD,0x2B,0x0B,
+    0xD6,0xF6,0xB6,0xEE,0xA2,0xFA,0xE8,0x8A,0xB6,0xF6,0xD7,0xEE,0xBF,0xBF,0xBF,0xF7,
+    0xB6,0xF6,0xD7,0xEE,0xFF,0xFB,0xFB,0xBF,0xD7,0xF6,0xB6,0xEE,0x2A,0x8E,0xB8,0xAC,
+    0xB6,0xF6,0xD7,0xEE,0x6D,0xFF,0xFF,0xFF,0xD6,0xF6,0xB6,0xEE,0xE8,0x0A,0x2A,0x02,
+    0xD7,0xF6,0xF6,0xEE,0x80,0x22,0x0A,0x2A,0xD7,0xF6,0xF6,0xEE,0x20,0x02,0xC8,0xA0,
+    0xD7,0xF6,0xB7,0xEE,0x02,0x08,0x28,0x08,0xD7,0xF6,0xF7,0xEE,0xA8,0xA0,0x20,0x80,
+    0xF7,0xF6,0xD7,0xF6,0xA1,0xB5,0xB5,0x55,0xF7,0xF6,0xD7,0xF6,0xDB,0xDA,0xD0,0x5F,
+    0xF7,0xF6,0xD7,0xF6,0x5A,0xDE,0x56,0xD7,0xF7,0xF6,0xD7,0xF6,0x55,0x5F,0xFE,0x95,
+    0xD6,0xF6,0xB7,0xEE,0x20,0x22,0x28,0xA0,0xD7,0xF6,0xF6,0xEE,0x20,0xA2,0x22,0xA2,
+    0xF7,0xF6,0xB6,0xEE,0xDA,0x7E,0xEE,0xEA,0xD7,0xF6,0xB6,0xEE,0xBF,0xBA,0xB2,0xEB,
+    0xF8,0xF6,0xD7,0xF6,0x85,0xB5,0xF5,0xFD,0xF7,0xF6,0xD7,0xF6,0x5B,0xBE,0xB5,0xF9,
+    0xF7,0xF6,0xD7,0xF6,0xFB,0x3A,0xAE,0xAC,0xF7,0xF6,0xD7,0xF6,0xEA,0xE8,0xEA,0xEF,
+    0xF7,0xF6,0xD7,0xF6,0x87,0xED,0xED,0xDF,0xF7,0xF6,0xD7,0xF6,0x8E,0xBB,0xAF,0xEA,
+    0xF7,0xF6,0xD7,0xF6,0xB7,0x94,0xD4,0xF8,0xF7,0xFE,0xD7,0xF6,0x7B,0x6E,0xFE,0x57,
+    0xB6,0xF6,0x4D,0xAC,0x60,0xE0,0x60,0x78,0x29,0x83,0x43,0x49,0x5E,0x7C,0xF8,0xEA,
+    0x25,0x6A,0x43,0x49,0xD5,0xFB,0xAA,0x80,0x46,0x6A,0xA4,0x59,0x7D,0xFF,0x2F,0x0B,
+    0x67,0x72,0xC5,0x61,0xBD,0xEA,0xA8,0x02,0x67,0x72,0x06,0x6A,0x7F,0xD7,0x37,0x22,
+    0x88,0x7A,0xE5,0x61,0xFD,0xFB,0xC8,0x80,0x67,0x72,0x06,0x6A,0x7E,0xEF,0xEB,0xB0,
+    0x26,0x62,0xC5,0x59,0xFF,0xB8,0xFE,0x6E,0x06,0x62,0xA4,0x59,0xEA,0x62,0xBA,0xFF,
+    0x68,0x72,0xC5,0x59,0xAD,0xAF,0x2D,0xA5,0xC8,0x7A,0x67,0x72,0xFD,0xB5,0xBD,0x2D,
+    0xA8,0x7A,0x06,0x6A,0x7A,0xE8,0x40,0xE0,0x26,0x6A,0xC5,0x59,0x37,0xDE,0x5E,0x5E,
+    0xE6,0x61,0xA5,0x59,0x6E,0x94,0x5E,0x1B,0x06,0x62,0xC5,0x59,0xDF,0x3D,0x25,0x80,
+    0x05,0x62,0xC5,0x59,0xFB,0xBA,0xFE,0xBC,0x06,0x62,0xC5,0x59,0xE8,0xA7,0x8B,0xEA,
+    0x06,0x62,0xC5,0x61,0x3B,0x0B,0x82,0x53,0xC4,0x59,0x63,0x51,0x80,0x60,0xE0,0xFA,
+    0xE5,0x69,0x83,0x51,0xFF,0xDD,0xFD,0x3F,0xC9,0x82,0xA4,0x61,0xFD,0xBD,0x0F,0x0B,
+    0x4A,0x93,0x67,0x7A,0x75,0xFF,0xAB,0x22,0x4B,0x9B,0xA8,0x82,0xF5,0xEB,0x0A,0x00,
+    0x2A,0x9B,0xA8,0x82,0xD7,0xFE,0xFA,0xBC,0xC9,0x8A,0xA5,0x69,0x7A,0x7A,0xE0,0x80,
+    0xC8,0x8A,0x85,0x61,0x55,0xFF,0xAB,0x00,0x88,0x82,0x64,0x61,0xF5,0xFF,0xFA,0xF8,
+    0x67,0x7A,0xC5,0x69,0x55,0xD5,0x37,0x3F,0xE9,0x92,0x46,0x7A,0xC5,0x29,0x2B,0x2F,
+    0x09,0x93,0x67,0x82,0xFA,0xF8,0x7A,0x5E,0xA8,0x8A,0x05,0x72,0xA0,0xEA,0xE8,0x7E,
+    0x46,0x7A,0xE5,0x69,0xA0,0xA8,0x3E,0xB5,0xB4,0xDD,0x67,0x7A,0xB5,0x2D,0x2D,0x0B,
+    0xF7,0xFE,0xF4,0xDD,0x2D,0x0F,0x0B,0x02,0xF7,0xFE,0x18,0xF7,0xBE,0xFE,0xBE,0xF8,
+    0x18,0xFF,0xF7,0xF6,0xA2,0xE0,0xF2,0xBF,0x18,0xFF,0xF7,0xF6,0xAA,0x8B,0xAA,0xEF,
+    0x18,0xFF,0xF7,0xF6,0xAA,0x2A,0x2A,0x8B,0x17,0xFF,0xF7,0xF6,0x7A,0xFA,0xFA,0xEA,
+    0x17,0xFF,0xF7,0xF6,0xFE,0xF5,0x5F,0xDF,0x18,0xFF,0xF7,0xF6,0xDD,0x55,0x95,0xBB,
+    0x17,0xFF,0xD7,0xF6,0x8A,0xEA,0x7A,0x7A,0xF7,0xF6,0xB6,0xEE,0xF8,0xFA,0xBF,0xBB,
+    0xD6,0xF6,0xB7,0xEE,0xEB,0x82,0x08,0xAA,0xD6,0xF6,0x96,0xEE,0x08,0x00,0x22,0xEF,
+    0x18,0xFF,0x96,0xEE,0x0A,0x2A,0x3E,0xB5,0x38,0xFF,0x18,0xFF,0x0B,0x09,0x0B,0x01,
+    0x38,0xFF,0xF7,0xF6,0xE0,0x60,0x6A,0xF8,0xF8,0xF6,0x55,0xE6,0x5E,0xFE,0xB8,0xA8,
+    0xF8,0xFE,0x96,0xE6,0x2D,0xAD,0x2F,0x2A,0x18,0xFF,0xF8,0xF6,0xAB,0xED,0xAF,0xFD,
+    0x18,0xFF,0xF8,0xF6,0xFF,0xF9,0xEF,0xEB,0x18,0xFF,0x97,0xF6,0x6A,0xE8,0xA2,0xA0,
+    0xD7,0xF6,0x55,0xE6,0x77,0xDF,0x5E,0x78,0x75,0xEE,0x55,0xE6,0xAF,0xB7,0x7F,0x5F,
+    0x55,0xE6,0x14,0xE6,0x70,0x60,0x00,0x00,0x35,0xE6,0xF4,0xDD,0x0B,0x29,0x2F,0x38,
+    0xB6,0xF6,0x34,0xE6,0x09,0x2F,0x89,0xAD,0xF7,0xF6,0xB7,0xF6,0x8A,0xA2,0x83,0x2D,
+    0x17,0xF7,0xB6,0xEE,0xAB,0xA9,0xAF,0xEE,0xF7,0xFE,0x18,0xF7,0xAA,0xAA,0xAA,0xA0,
+    0x18,0xFF,0xD7,0xF6,0xFD,0xFF,0xFA,0xEA,0xF7,0xF6,0xD7,0xF6,0x75,0x5E,0xD8,0x7E,
+    0xF7,0xF6,0xB7,0xEE,0xFB,0xA3,0xAB,0xFF,0xD7,0xF6,0xF7,0xEE,0x0A,0x80,0x00,0x00,
+    0xF7,0xF6,0xD7,0xF6,0x5F,0xDF,0x7D,0xD5,0xF7,0xF6,0xD7,0xF6,0xEA,0xFB,0xFB,0x59,
+    0xD7,0xF6,0xF7,0xEE,0xEA,0xA8,0x82,0x00,0xD7,0xF6,0xF7,0xEE,0x8A,0x8E,0xA2,0xE8,
+    0xD7,0xF6,0xF7,0xEE,0xAA,0x2A,0x8A,0xBA,0xD7,0xF6,0xF8,0xEE,0x08,0x00,0xF2,0xEA,
+    0x18,0xF7,0xD7,0xF6,0x55,0x97,0xAA,0xAE,0xF8,0xFE,0xD7,0xEE,0xFF,0xAA,0x82,0xAA,
+    0x18,0xF7,0xD7,0xF6,0xFF,0xAB,0xAB,0xEB,0x18,0xF7,0xD7,0xF6,0xAF,0xBE,0xFE,0xFA,
+    0xF7,0xF6,0xD7,0xF6,0x80,0x40,0xF0,0xDF,0xF7,0xF6,0xB7,0xEE,0xEA,0xEE,0x7F,0xFE,
+    0xD7,0xF6,0x76,0xE6,0xA8,0xFA,0xFA,0x68,0xB6,0xEE,0x76,0xE6,0x2A,0xBF,0xBF,0xAB,
+    0xD7,0xF6,0x96,0xEE,0x56,0x9D,0x2D,0x2B,0xD7,0xF6,0xF7,0xEE,0xA0,0x20,0x20,0x08,
+    0xD7,0xF6,0x76,0xE6,0x5C,0xFF,0xDE,0x5E,0x96,0xEE,0x55,0xE6,0x0A,0x28,0xFE,0x7A,
+    0x96,0xEE,0x55,0xE6,0xA8,0x2A,0xAF,0x95,0x96,0xEE,0x76,0xEE,0xFD,0xFB,0x3D,0x25,
+    0x96,0xEE,0xF4,0xDD,0x48,0x60,0xE0,0x60,0xF4,0xDD,0x52,0xC5,0x3F,0x37,0x37,0xBF,
+    0x96,0xEE,0x14,0xDE,0xAD,0x29,0xAD,0x3D,0xB6,0xF6,0x56,0xE6,0x7F,0xFC,0x7B,0x7E,
+    0x35,0xEE,0x56,0xE6,0xFB,0xFB,0xFF,0xF7,0x35,0xE6,0x31,0xCD,0x60,0xE0,0x40,0x60,
+    0x10,0xC5,0xAF,0xBC,0xFC,0x74,0xDC,0x76,0xD0,0xBC,0x6D,0xB4,0xA2,0xEC,0x7A,0xDE,
+    0xF3,0xDD,0xCF,0xBC,0x2D,0x2D,0x0D,0x2D,0x54,0xE6,0xD2,0xDD,0x2F,0x2F,0xB9,0x2B,
+    0x55,0xE6,0xF3,0xDD,0x8A,0x68,0x6A,0xFE,0x55,0xE6,0x14,0xDE,0xBB,0xB5,0x35,0xBD,
+    0x75,0xEE,0x55,0xE6,0x2D,0x37,0xA9,0xC5,0xB6,0xF6,0x35,0xE6,0x8A,0x2A,0xAF,0xED,
+    0x96,0xEE,0x35,0xE6,0xA8,0xAE,0x2E,0x27,0xD7,0xF6,0x75,0xE6,0x2D,0xAF,0x2B,0x2A,
+    0xD7,0xF6,0xB6,0xEE,0xAC,0xAC,0x2F,0x0A,0xD7,0xF6,0xF6,0xEE,0x2A,0x0A,0x00,0xA2,
+    0xD6,0xF6,0xB6,0xEE,0xAE,0x2A,0xA2,0xE0,0xD6,0xF6,0xB7,0xEE,0xE2,0xAE,0xAB,0x2A,
+    0xD6,0xF6,0xB6,0xEE,0xA3,0xA8,0xAA,0x22,0xD6,0xF6,0xD7,0xEE,0x2A,0xAA,0x8A,0xA8,
+    0xD7,0xF6,0xB6,0xEE,0x08,0x26,0x0F,0x00,0xF7,0xF6,0xB6,0xEE,0x6A,0xEE,0xAA,0xBB,
+    0xD7,0xF6,0xF6,0xEE,0xA0,0x82,0x8A,0x0A,0xD7,0xF6,0xF8,0xEE,0x02,0x0A,0xA0,0x80,
+    0xF7,0xF6,0xD7,0xF6,0x7E,0x5B,0x7A,0xFE,0xD7,0xF6,0xD6,0xEE,0xAA,0x8A,0x8C,0x2A,
+    0xD7,0xF6,0xB6,0xEE,0x28,0xA8,0xAA,0xFA,0xF7,0xF6,0xB6,0xEE,0xAA,0xEB,0xFF,0xE7,
+    0xD6,0xF6,0xB7,0xEE,0x20,0x02,0xA8,0xE2,0xF7,0xF6,0xD7,0xF6,0xED,0xAD,0xFD,0x7D,
+    0xF7,0xF6,0xD7,0xF6,0x56,0x77,0xDD,0x7B,0xD7,0xF6,0xB6,0xEE,0xAA,0xB2,0x02,0x00,
+    0xF7,0xF6,0xD7,0xF6,0x83,0xA2,0x8B,0x02,0xF7,0xF6,0xD7,0xF6,0xDF,0xFA,0x2A,0x88,
+    0xF7,0xF6,0xD7,0xF6,0xFE,0x6A,0xE2,0xEE,0xF7,0xF6,0xD7,0xF6,0x6B,0xA6,0xFA,0xAF,
+    0xF7,0xF6,0xD7,0xF6,0xBF,0x8F,0x2B,0xB8,0xF7,0xF6,0xD7,0xF6,0xF0,0xE2,0x6A,0xEA,
+    0xF7,0xFE,0xD7,0xF6,0xFA,0x5F,0x55,0xDF,0xF7,0xFE,0x76,0xEE,0xE2,0xE8,0x6A,0x6A,
+    0x55,0xEE,0x6A,0x93,0x70,0x78,0x5E,0x5E,0xE8,0x82,0x66,0x72,0x54,0xFE,0xEA,0xB8,
+    0xA7,0x7A,0x05,0x62,0xDE,0xEA,0xAA,0xF8,0xA8,0x82,0x45,0x6A,0xF5,0x2F,0x0B,0x22,
+    0xE9,0x8A,0x47,0x72,0xBD,0xAA,0x2A,0x02,0x09,0x8B,0x66,0x72,0x5F,0xFE,0x20,0x00,
+    0x0A,0x8B,0x67,0x72,0xDD,0xBB,0xB8,0xE8,0xE9,0x82,0x47,0x72,0x5E,0x7E,0x28,0x8A,
+    0xA8,0x7A,0x06,0x62,0x55,0x7A,0x88,0x80,0x47,0x6A,0xA4,0x59,0x57,0xDC,0x5C,0x70,
+    0x06,0x6A,0x84,0x51,0x39,0xAB,0xA9,0xA9,0xA8,0x7A,0xE5,0x61,0x0B,0x0B,0x03,0xBD,
+    0xA8,0x7A,0xE5,0x61,0xA0,0xE8,0xEC,0x7E,0x26,0x6A,0xA5,0x59,0xF8,0x9E,0xBE,0xFE,
+    0xE5,0x61,0xA5,0x59,0x1E,0xD9,0xD8,0xFF,0x06,0x62,0xA4,0x59,0x8A,0x0A,0xFB,0xFD,
+    0x47,0x6A,0xC5,0x59,0xA2,0x0A,0xFF,0x7D,0x06,0x62,0xC5,0x61,0x7A,0xCC,0xFE,0xFE,
+    0x26,0x6A,0xC5,0x59,0x5F,0xFD,0xFC,0x5B,0x06,0x6A,0x84,0x59,0x9B,0x2A,0x02,0x00,
+    0x87,0x7A,0xC4,0x61,0xD7,0x2F,0xAA,0x0A,0x09,0x93,0x26,0x72,0xAD,0x2B,0x2A,0xAA,
+    0xAD,0xA3,0x0A,0x93,0xB7,0xBD,0xAD,0x0F,0xED,0xAB,0x4B,0x9B,0x7D,0xFF,0xAA,0x80,
+    0x6B,0xA3,0xC8,0x8A,0x5C,0x5C,0x78,0xE0,0x4A,0x9B,0xA8,0x8A,0xB9,0x09,0x0F,0xAF,
+    0x4A,0x9B,0xE9,0x92,0x6B,0xC2,0xA0,0xFF,0x8C,0xA3,0x26,0x7A,0x5F,0x7A,0xAA,0x0A,
+    0xCC,0xAB,0x26,0x72,0xD5,0xFF,0xEA,0x80,0xC8,0x8A,0x66,0x82,0x0B,0x0B,0xFA,0xF4,
+    0xC9,0x8A,0x26,0x72,0xF8,0xFE,0xFB,0x57,0x67,0x7A,0xC4,0x61,0xE8,0xE8,0x7E,0x77,
+    0x11,0xCD,0xE5,0x69,0xD5,0xB5,0xB5,0x25,0xD7,0xFE,0x6F,0xBC,0x2D,0x2B,0x0B,0x02,
+    0x18,0xFF,0xD7,0xFE,0xAD,0xAB,0xAA,0x2A,0x17,0xFF,0xF8,0xF6,0xAF,0xEA,0xE3,0xEA,
+    0xF8,0xFE,0x17,0xF7,0xEA,0xBA,0xBA,0xBA,0x17,0xFF,0xF7,0xF6,0xBD,0xEF,0xAF,0xAB,
+    0x17,0xFF,0xF7,0xF6,0x8B,0xA6,0xAA,0x7E,0x17,0xFF,0xF7,0xF6,0xFA,0xD6,0x77,0xD5,
+    0x18,0xFF,0xF7,0xF6,0xF7,0xF7,0xAD,0xAB,0x18,0xFF,0xB6,0xEE,0x08,0x80,0xE8,0x7A,
+    0xF7,0xF6,0x96,0xEE,0x80,0xE8,0xFE,0xDF,0xD7,0xF6,0x96,0xEE,0xA0,0xBE,0x5F,0x57,
+    0xB6,0xEE,0x55,0xEE,0x00,0xE8,0x7A,0x5F,0x96,0xEE,0xB2,0xD5,0x20,0xA2,0xFA,0x7A,
+    0x18,0xFF,0xF3,0xD5,0xAF,0x2D,0x2D,0x29,0x38,0xFF,0x18,0xFF,0x2B,0x8B,0x2F,0xAF,
+    0x38,0xFF,0xF8,0xF6,0x6A,0xEA,0xC0,0x80,0x18,0xFF,0xB7,0xEE,0x7E,0xDA,0xFA,0xFC,
+    0xF8,0xFE,0xD7,0xF6,0x9D,0xBF,0xA5,0xB5,0x18,0xFF,0xF8,0xF6,0xFF,0xBE,0xAB,0xAB,
+    0x18,0xFF,0xF8,0xF6,0xEA,0xAE,0xB2,0xAA,0x18,0xFF,0xF8,0xF6,0xFF,0xAF,0xFE,0xF2,
+    0xF8,0xFE,0x75,0xEE,0x58,0x58,0x68,0xE0,0x96,0xEE,0x35,0xE6,0x7E,0xFE,0xBE,0xF8,
+    0x76,0xEE,0x55,0xE6,0x57,0xF7,0xEC,0xFF,0x55,0xEE,0x35,0xE6,0x5E,0xF8,0xDC,0xF8,
+    0x96,0xEE,0x35,0xE6,0x2F,0x3F,0xAD,0xEF,0xF7,0xFE,0x96,0xEE,0xA9,0x2F,0xAD,0xAD,
+    0xF7,0xF6,0xD7,0xF6,0x94,0xBA,0xAA,0x82,0xD7,0xFE,0xF7,0xF6,0x77,0x5F,0xFD,0xF7,
+    0x18,0xFF,0xD7,0xF6,0xEA,0xAA,0xAB,0xAF,0x18,0xF7,0xD7,0xF6,0x7F,0xDE,0xFE,0xA2,
+    0xF7,0xF6,0xB7,0xEE,0xFA,0xAA,0x80,0x00,0xD7,0xF6,0xF7,0xEE,0x00,0x00,0x8A,0xFA,
+    0xF7,0xF6,0xD7,0xEE,0xB7,0xEF,0xF7,0x28,0xF7,0xF6,0xD7,0xF6,0x5F,0x7A,0xE2,0xB2,
+    0x38,0xF7,0xD7,0xF6,0x55,0x7D,0xFF,0xBF,0x18,0xFF,0xD7,0xF6,0xFD,0xBB,0xB2,0xF2,
+    0xD9,0xFE,0xF7,0xF6,0xF5,0x55,0xF5,0xD5,0xD8,0xFE,0xF8,0xF6,0xDD,0x77,0x75,0x57,
+    0x17,0xFF,0xF8,0xF6,0x7D,0xFD,0xFD,0x77,0xF8,0xFE,0xF7,0xF6,0x77,0xDD,0xD7,0x5D,
+    0xF7,0xF6,0xD7,0xF6,0x00,0x20,0x08,0x22,0xF7,0xF6,0xD7,0xF6,0x88,0xC2,0xE8,0xEC,
+    0xF7,0xF6,0xD7,0xF6,0xDF,0xF7,0xDD,0xD5,0xD7,0xF6,0xB6,0xEE,0xF8,0xE8,0xF8,0xFF,
+    0xB7,0xEE,0x76,0xE6,0xE0,0xFA,0x78,0xE0,0xD7,0xF6,0x75,0xE6,0xBF,0xAD,0x3D,0xA9,
+    0xF7,0xF6,0xB6,0xEE,0xF7,0xBF,0xBB,0xAA,0xF7,0xF6,0xB6,0xEE,0xFA,0xFA,0xFA,0xEA,
+    0xB7,0xF6,0x75,0xEE,0x7E,0xF8,0xFC,0x5F,0x96,0xEE,0x35,0xE6,0xE8,0xA8,0x88,0x22,
+    0x76,0xEE,0x55,0xE6,0x2B,0x02,0x00,0x00,0x96,0xEE,0x76,0xEE,0x85,0xB4,0x9F,0xF5,
+    0x76,0xEE,0xF3,0xDD,0x60,0x60,0x40,0xE0,0xF4,0xDD,0x52,0xCD,0x37,0x3E,0x3F,0x2F,
+    0x76,0xEE,0x14,0xDE,0x2D,0xAD,0xAD,0x2D,0x96,0xEE,0x14,0xE6,0xAA,0xEA,0xE0,0xFA,
+    0x55,0xE6,0xF4,0xDD,0xA2,0xEA,0xFE,0xFE,0x14,0xE6,0x52,0xCD,0x60,0xC0,0xE0,0xC0,
+    0x11,0xC5,0x6E,0xB4,0xFE,0xF8,0x78,0x5C,0xCF,0xBC,0x4D,0xAC,0xFE,0xBF,0x3F,0xB7,
+    0x13,0xDE,0x0F,0xC5,0xAD,0x2D,0x2D,0x29,0x54,0xE6,0x14,0xDE,0xB5,0xBD,0xAF,0xAA,
+    0x55,0xE6,0x14,0xE6,0xFF,0xDA,0x7A,0xFA,0x55,0xE6,0x14,0xDE,0xB9,0xEF,0x2B,0x0F,
+    0x55,0xEE,0x35,0xE6,0x3A,0xFF,0xFA,0x28,0x55,0xE6,0x14,0xDE,0x08,0xBF,0xFF,0xA8,
+    0xB6,0xEE,0x35,0xE6,0xB5,0xA5,0x2F,0x2B,0xD6,0xF6,0x96,0xEE,0xA9,0xAB,0x8A,0xBE,
+    0xB6,0xF6,0xF7,0xEE,0xFA,0xFE,0xAA,0xAE,0xD7,0xF6,0xF6,0xEE,0x22,0x0A,0x00,0x08,
+    0xD7,0xF6,0xB6,0xEE,0x28,0xAA,0x8E,0xAB,0xD6,0xF6,0xB6,0xEE,0xA2,0x82,0xA2,0xEA,
+    0xD6,0xF6,0xB5,0xEE,0x02,0xAA,0xAE,0xA5,0xD6,0xF6,0xB6,0xEE,0x00,0x82,0x2C,0xAA,
+    0xD7,0xF6,0xF7,0xEE,0x28,0x20,0x20,0x00,0xD6,0xF6,0xB7,0xEE,0x82,0x2A,0xAA,0x20,
+    0xF6,0xF6,0xD7,0xF6,0x7D,0x7F,0x5A,0x5F,0xD6,0xF6,0xD7,0xEE,0x2A,0xAA,0xAA,0xAA,
+    0xD7,0xF6,0xF6,0xEE,0x22,0x00,0x02,0x08,0xF7,0xF6,0xB6,0xEE,0xBE,0xBF,0xAF,0xAE,
+    0xD7,0xF6,0xB6,0xEE,0xBE,0xAA,0xF8,0xE2,0xD6,0xF6,0xB6,0xEE,0x8F,0xFF,0xAF,0xAF,
+    0xD6,0xF6,0xB6,0xEE,0x88,0x28,0x8B,0x2D,0xF7,0xF6,0xB6,0xEE,0xAA,0xBA,0xEF,0xBF,
+    0xD7,0xF6,0xF7,0xEE,0x88,0x08,0xC0,0x02,0xF7,0xF6,0xD7,0xF6,0x8F,0xBE,0xDE,0xA9,
+    0xF7,0xF6,0xD7,0xF6,0x08,0x2A,0x0A,0x0A,0x17,0xFF,0xD7,0xF6,0xFE,0xAA,0xFA,0xFF,
+    0xD7,0xFE,0xF7,0xF6,0xDD,0xDD,0x55,0x57,0xF7,0xF6,0xD6,0xF6,0xB7,0x3A,0x21,0x00,
+    0xF7,0xF6,0xD7,0xF6,0xA8,0xA8,0x22,0x28,0xF7,0xF6,0xD7,0xF6,0xEA,0xFE,0x60,0x78,
+    0xF7,0xFE,0xD7,0xF6,0xFF,0xBD,0xDF,0xDF,0xF7,0xF6,0x13,0xE6,0x60,0x68,0x68,0x62,
+    0xEF,0xC4,0xA6,0x7A,0xF8,0x78,0x78,0x78,0xC7,0x82,0x46,0x72,0xB8,0xF8,0x56,0x5F,
+    0x87,0x7A,0x26,0x72,0x2A,0xAB,0xFA,0x7D,0xA8,0x7A,0x47,0x72,0x00,0xAB,0x9D,0x5D,
+    0xE9,0x82,0x46,0x72,0x0A,0x2A,0xBF,0xF5,0x4A,0x8B,0x67,0x72,0xA2,0xAB,0x7D,0x55,
+    0xE9,0x8A,0x06,0x6A,0xA8,0xE8,0xFB,0x5F,0xA8,0x7A,0x05,0x62,0x88,0xAA,0xBA,0x7F,
+    0xA8,0x7A,0x06,0x62,0xA8,0xFE,0x5E,0x5F,0x27,0x6A,0x84,0x51,0xE0,0xBA,0xBF,0xDE,
+    0xE5,0x61,0x64,0x51,0x0A,0xAA,0xAC,0xA5,0x05,0x62,0x84,0x59,0x02,0x7B,0xFF,0xD7,
+    0xE5,0x61,0xA4,0x59,0x8A,0xDF,0xB9,0xF5,0xE5,0x61,0x84,0x59,0xA2,0xAA,0xB8,0xBB,
+    0xE5,0x61,0xA4,0x59,0xE5,0xAA,0x82,0xAA,0x06,0x62,0xA5,0x59,0x5F,0xD5,0xBE,0x8E,
+    0xE5,0x61,0xA5,0x59,0x53,0x2B,0x09,0x02,0x26,0x6A,0xC5,0x59,0xEF,0xB9,0xCB,0x0A,
+    0x67,0x72,0xC5,0x59,0x5F,0xED,0xAA,0xA2,0xA8,0x82,0xE5,0x61,0xDD,0xF7,0xBB,0x02,
+    0x09,0x93,0x66,0x72,0xD5,0xBD,0x2A,0x0E,0x2A,0x93,0xC8,0x8A,0x9F,0x83,0x08,0x28,
+    0xAC,0xA3,0x0A,0x93,0x0D,0x2B,0x0D,0x2B,0x4E,0xBC,0xCC,0xAB,0x7D,0x0F,0xAF,0x29,
+    0x6E,0xBC,0x6B,0xA3,0x5F,0xFE,0xA8,0x00,0x2D,0xB4,0x0A,0x93,0x55,0x5F,0x7A,0xB0,
+    0x2A,0x9B,0xC8,0x8A,0xBF,0xFE,0x57,0xF8,0x6B,0xA3,0xC9,0x8A,0x0B,0x2D,0x3F,0xA5,
+    0xED,0xB3,0x4A,0x9B,0x83,0xAA,0xFF,0xD5,0x2A,0x9B,0x67,0x82,0xD4,0x58,0x78,0xF0,
+    0x87,0x82,0x26,0x72,0x7A,0xEA,0x7E,0x2A,0x4A,0x93,0xC5,0x69,0x57,0xDF,0xB5,0x2F,
+    0x56,0xEE,0xC9,0x82,0x35,0x2D,0x0B,0x0B,0xD7,0xFE,0x35,0xEE,0x09,0x03,0x02,0x00,
+    0x18,0xFF,0xF7,0xFE,0xFD,0xBD,0xBD,0xA5,0x18,0xFF,0xF8,0xF6,0xEE,0x7E,0xD8,0xBA,
+    0x17,0xFF,0xF7,0xF6,0xEF,0xEB,0xF7,0xFA,0x18,0xFF,0xF7,0xF6,0xBA,0x8E,0xEB,0x8E,
+    0x17,0xFF,0xD7,0xF6,0xAA,0xBA,0xFA,0xFE,0x17,0xFF,0xD7,0xF6,0xBF,0xB6,0x3A,0xAB,
+    0x18,0xFF,0xB6,0xEE,0x82,0xA0,0xA8,0x72,0xF7,0xF6,0x96,0xEE,0xF8,0xFA,0x5E,0x57,
+    0x75,0xEE,0xB6,0xE6,0xAD,0xAA,0xAE,0xEB,0xB6,0xEE,0x75,0xEE,0xFF,0x7F,0x7F,0x00,
+    0xB6,0xF6,0x54,0xE6,0x7F,0xFF,0xEB,0x80,0x75,0xEE,0xD3,0xD5,0x5A,0x5E,0x9E,0x28,
+    0x18,0xFF,0x34,0xDE,0x0D,0x0F,0x03,0x02,0x39,0xFF,0x18,0xFF,0xBF,0xBF,0xBB,0xAF,
+    0x39,0xFF,0x18,0xFF,0xC2,0x00,0x02,0xC2,0x18,0xF7,0xD7,0xF6,0x56,0x5E,0x78,0xF8,
+    0xF8,0xF6,0xD7,0xF6,0xA5,0x29,0xA3,0x0A,0x18,0xFF,0xF8,0xF6,0xAF,0xED,0xAF,0xA9,
+    0x18,0xFF,0xF8,0xF6,0xBA,0x7F,0xDD,0xEF,0x18,0xFF,0xF8,0xF6,0x6A,0xFF,0x7D,0x7D,
+    0xF8,0xF6,0xB7,0xF6,0x60,0x80,0x20,0x00,0xD7,0xF6,0x55,0xE6,0x57,0x5E,0x7C,0x78,
+    0x76,0xEE,0x55,0xE6,0xEB,0x8F,0x1F,0xEB,0x55,0xEE,0x35,0xE6,0x78,0x70,0xF0,0xE8,
+    0x76,0xEE,0x14,0xDE,0x2A,0x2A,0xAF,0xA9,0xD7,0xF6,0x55,0xEE,0x0B,0x0B,0x2D,0xAF,
+    0x18,0xF7,0xB6,0xEE,0xCA,0xA2,0xFB,0xAD,0xF7,0xF6,0xD7,0xF6,0x2B,0x8D,0xA5,0xBE,
+    0xD7,0xFE,0xF8,0xF6,0x57,0x5D,0x97,0x55,0x18,0xFF,0xF8,0xF6,0xED,0xAD,0xFD,0xED,
+    0xF7,0xF6,0xD8,0xF6,0x2A,0xB8,0x70,0xB0,0x18,0xFF,0xD7,0xF6,0x3D,0xA7,0xB7,0x57,
+    0x18,0xFF,0xF8,0xF6,0x5F,0x7F,0xFF,0xBD,0x18,0xFF,0xD7,0xF6,0xFE,0xFF,0xEA,0xA8,
+    0xF7,0xF6,0xD7,0xF6,0x08,0x2E,0xAA,0x22,0x18,0xFF,0xF7,0xF6,0x75,0x55,0x75,0xD7,
+    0xF7,0xFE,0xF8,0xF6,0x75,0xDD,0x7F,0xF7,0x18,0xFF,0xF8,0xF6,0x75,0x55,0x7F,0x7F,
+    0x18,0xFF,0xD7,0xF6,0xAB,0xEA,0xFB,0xDF,0xF7,0xF6,0xD7,0xF6,0x00,0x00,0x00,0xAC,
+    0xF7,0xF6,0xD7,0xF6,0x28,0x22,0xAC,0xEE,0xF7,0xF6,0xD7,0xF6,0x6C,0x7E,0xD7,0x59,
+    0xD7,0xF6,0xB6,0xEE,0x00,0xC8,0xE0,0xC0,0xD7,0xF6,0x96,0xEE,0xAB,0x8B,0xEE,0x7F,
+    0xB6,0xEE,0x75,0xE6,0xE8,0xAE,0xEC,0xDF,0xD7,0xF6,0x96,0xEE,0x0D,0x2D,0x25,0xAD,
+    0xF7,0xF6,0xB7,0xEE,0xAA,0xE8,0xFA,0xEF,0xF7,0xF6,0xB6,0xEE,0xAA,0xEB,0xFA,0xFB,
+    0xB7,0xF6,0x55,0xE6,0x7E,0xD6,0x76,0x5C,0x96,0xEE,0x76,0xEE,0x89,0xFF,0x7D,0xD5,
+    0x76,0xEE,0x55,0xE6,0x88,0xE0,0xF0,0xFE,0x96,0xEE,0x55,0xE6,0xAB,0xBB,0xEF,0xFF,
+    0x76,0xEE,0xD3,0xDD,0xE0,0xE0,0xE0,0x60,0xF3,0xDD,0x72,0xCD,0xBF,0xAF,0x2F,0x3F,
+    0x76,0xEE,0xF4,0xDD,0x2D,0x2D,0x0B,0x2D,0x76,0xEE,0x14,0xE6,0xF8,0xB8,0x68,0x70,
+    0x34,0xE6,0xF4,0xDD,0xEC,0x68,0xFA,0xB7,0x15,0xE6,0x92,0xD5,0x60,0x48,0x6A,0x62,
+    0x10,0xC5,0xEC,0xA3,0xE8,0xF8,0xFC,0x7C,0xF0,0xC4,0xEC,0x9B,0xAF,0x2F,0x3D,0x25,
+    0x34,0xE6,0x51,0xCD,0xAD,0x2D,0x3D,0x2F,0x55,0xE6,0x14,0xE6,0xAF,0x89,0x23,0x23,
+    0x54,0xE6,0x14,0xDE,0xFA,0x5E,0xDA,0xFC,0xB7,0xF6,0x34,0xE6,0xF5,0xAD,0xA9,0x09,
+    0xB6,0xF6,0x55,0xE6,0xD5,0xFF,0xEA,0x70,0x76,0xEE,0x55,0xE6,0xD7,0x1F,0x2F,0x2B,
+    0xB6,0xEE,0x76,0xEE,0xAD,0x2F,0xAA,0xAA,0xB6,0xF6,0x96,0xEE,0xCA,0xCB,0x7E,0xDE,
+    0xD7,0xF6,0xB6,0xEE,0x0A,0x31,0x22,0xBA,0xD6,0xF6,0xB6,0xEE,0xB8,0xFE,0xA2,0x80,
+    0xD6,0xF6,0xD7,0xEE,0xAA,0xA2,0xAA,0xAA,0xD6,0xF6,0xB7,0xEE,0xEA,0xA8,0x2C,0x28,
+    0xF6,0xF6,0xB7,0xEE,0xBD,0xFE,0xFA,0xEA,0xD7,0xF6,0xB6,0xEE,0xA2,0xE2,0x82,0xA8,
+    0xD6,0xF6,0xB6,0xEE,0x22,0x0A,0x8B,0xA8,0xF7,0xF6,0xB6,0xEE,0xBA,0xFE,0xAB,0xAF,
+    0xF7,0xF6,0xB6,0xEE,0xBA,0xEF,0xAA,0xAA,0xD6,0xF6,0xF8,0xEE,0x88,0x28,0x00,0x22,
+    0xF5,0xF6,0xD7,0xF6,0x57,0xDF,0xF5,0xFD,0xD6,0xF6,0xD7,0xEE,0xAA,0xA2,0xAA,0x28,
+    0xD6,0xF6,0xB6,0xEE,0xFE,0x6E,0x60,0xF0,0xD6,0xF6,0xB6,0xEE,0x6F,0x7F,0xF9,0x9B,
+    0xD6,0xF6,0xB6,0xEE,0x8F,0xEF,0xBE,0xAE,0xD7,0xF6,0xB6,0xEE,0xAA,0xA8,0xBA,0xFF,
+    0xF6,0xF6,0xB6,0xEE,0xEB,0xEB,0xAF,0xAF,0xF7,0xF6,0xB6,0xEE,0xAA,0xBA,0xAD,0xBB,
+    0xF6,0xF6,0xD6,0xF6,0xF6,0xFF,0xDD,0xF5,0xF6,0xF6,0xD6,0xF6,0xAA,0xA2,0xBB,0x79,
+    0xF7,0xF6,0xD7,0xF6,0x20,0xAA,0xAE,0xF5,0xF7,0xF6,0xD7,0xF6,0x80,0x28,0xA0,0xAA,
+    0xF7,0xFE,0xF7,0xF6,0xFD,0xDF,0x7F,0x7D,0xD7,0xFE,0xF7,0xF6,0xF5,0xFD,0xFD,0xBD,
+    0xF7,0xFE,0xD6,0xF6,0xD8,0xEA,0xFF,0x5E,0xB6,0xF6,0x51,0xCD,0xC0,0x60,0x40,0x60,
+    0x4D,0xAC,0xA6,0x7A,0x58,0x5C,0x5C,0x5C,0xE7,0x82,0x45,0x6A,0x55,0x57,0xFD,0x8A,
+    0xA7,0x7A,0x26,0x6A,0x7D,0x77,0x7A,0x78,0x67,0x72,0xC5,0x61,0x0A,0xBA,0x6E,0xEF,
+    0x47,0x72,0xE6,0x61,0x02,0xEA,0xF5,0x85,0x46,0x6A,0xE5,0x61,0xBC,0xDF,0x7B,0xD7,
+    0x46,0x6A,0xE5,0x61,0x9F,0x3F,0xAF,0xAA,0x46,0x6A,0x26,0x6A,0x06,0x68,0x9E,0x76,
+    0x46,0x6A,0xC4,0x59,0xE8,0xF8,0xFA,0x5E,0xE5,0x59,0x43,0x51,0x6E,0xE0,0xE8,0xEA,
+    0x84,0x59,0x03,0x49,0x82,0x6A,0xAA,0xA0,0x84,0x59,0x23,0x49,0x2E,0x3D,0x25,0x8A,
+    0xC6,0x61,0x64,0x51,0xD5,0xBD,0x8B,0x0B,0x06,0x62,0x85,0x59,0xFF,0xFF,0xBA,0x2E,
+    0x06,0x62,0xA5,0x59,0xFB,0xB5,0xFE,0xE8,0x26,0x6A,0xC5,0x61,0xEB,0xFF,0x0F,0x29,
+    0x47,0x72,0xC5,0x59,0x7D,0xD7,0xAB,0x2A,0xC8,0x7A,0x06,0x62,0xF5,0xFF,0xFD,0x8F,
+    0xE9,0x8A,0x46,0x72,0xF5,0xBD,0x2D,0x2A,0x2A,0x93,0xC8,0x82,0xF5,0xFF,0x2E,0x0B,
+    0x2A,0x93,0xE8,0x8A,0x36,0x2B,0xAC,0xAA,0x6B,0x9B,0x09,0x93,0xFF,0xFF,0xEB,0x2B,
+    0x8B,0xA3,0x2A,0x9B,0x29,0x2B,0x0B,0x02,0x6E,0xBC,0xAC,0xAB,0x2D,0xA5,0xAD,0xAD,
+    0xCF,0xCC,0x4E,0xBC,0xF7,0xAD,0xAF,0x0F,0xCF,0xCC,0xCC,0xAB,0x7E,0xEA,0xA8,0xA0,
+    0x0D,0xB4,0x2A,0x93,0x5F,0x7A,0xF8,0xE8,0x4A,0x93,0xE9,0x8A,0xAF,0xEF,0xFA,0xF8,
+    0x2A,0x93,0x87,0x82,0x00,0xEA,0x6E,0x7E,0xE9,0x8A,0xC5,0x69,0xA0,0xEA,0x7E,0x57,
+    0x09,0x8B,0xE5,0x69,0xFF,0xDD,0xB5,0x3D,0x12,0xE6,0xE8,0x82,0xF5,0xB5,0x2D,0x0B,
+    0xD7,0xFE,0x72,0xD5,0x2D,0x0B,0x02,0x00,0x18,0xFF,0xD7,0xFE,0xBF,0xEB,0xAA,0xAA,
+    0x18,0xFF,0xF7,0xFE,0x8D,0xAB,0xA5,0x2D,0x18,0xFF,0xF7,0xF6,0xA2,0x80,0xA8,0xFA,
+    0x17,0xFF,0xF8,0xF6,0xAA,0x7A,0xAE,0xAA,0xF7,0xFE,0x18,0xF7,0xEF,0xFE,0xFF,0xAF,
+    0x17,0xFF,0xD7,0xF6,0x7A,0xFA,0xEA,0xEA,0x17,0xFF,0xB6,0xEE,0x22,0x0A,0xE2,0x6A,
+    0xF7,0xF6,0x96,0xEE,0x60,0x5C,0xDF,0xF7,0xF7,0xF6,0x96,0xEE,0x55,0xF5,0xFD,0x0B,
+    0x17,0xFF,0x96,0xEE,0xFD,0xAF,0x8A,0x00,0x38,0xFF,0xD7,0xF6,0xD5,0xFB,0xAA,0x8A,
+    0x18,0xFF,0xB6,0xF6,0x7E,0xFE,0xE2,0xF0,0xF7,0xF6,0x75,0xEE,0x9D,0xB7,0x37,0x37,
+    0x38,0xFF,0xF8,0xFE,0xAF,0xAB,0xAA,0x8A,0x39,0xFF,0x18,0xFF,0xBF,0xF5,0x2D,0x29,
+    0x39,0xFF,0x18,0xFF,0xC2,0xE8,0xE0,0xB0,0x18,0xFF,0xF8,0xF6,0x56,0x78,0x50,0xD0,
+    0xF8,0xF6,0xD7,0xF6,0x88,0xAA,0xB8,0xA2,0x18,0xFF,0xF8,0xF6,0xFD,0xF5,0xD5,0xDD,
+    0x18,0xFF,0xF8,0xF6,0xED,0xA5,0xAB,0xAF,0x18,0xFF,0xF8,0xF6,0xEB,0xAE,0x2A,0xBA,
+    0x18,0xFF,0xF8,0xF6,0xFA,0xDA,0xB2,0xAA,0x18,0xFF,0x55,0xE6,0x7A,0xFA,0xE0,0xA8,
+    0x75,0xEE,0x55,0xE6,0xBF,0xFD,0xDF,0x70,0x75,0xEE,0x35,0xE6,0xEA,0xFF,0xAF,0x9A,
+    0x76,0xEE,0x35,0xE6,0xAD,0xEF,0x2F,0xAB,0xB6,0xF6,0x55,0xE6,0xAD,0xAD,0xBF,0x0F,
+    0xF7,0xF6,0xB6,0xF6,0x8F,0xA9,0xED,0xAD,0xF7,0xF6,0xD7,0xF6,0xFA,0x7B,0xFF,0xBF,
+    0x18,0xFF,0xD7,0xF6,0xAA,0xAB,0xEB,0xAF,0x18,0xFF,0xF8,0xF6,0xEB,0xED,0xF5,0x55,
+    0x18,0xFF,0xF8,0xF6,0x57,0x56,0x5F,0x5F,0xF8,0xF6,0xD7,0xF6,0xDE,0xFA,0xA2,0x20,
+    0xF8,0xF6,0xD7,0xF6,0x00,0xA2,0xAA,0x2B,0x18,0xFF,0xD7,0xF6,0xAA,0xBF,0xBF,0xBF,
+    0x18,0xFF,0xF7,0xF6,0x5D,0x77,0x7E,0xFD,0xF7,0xF6,0xD7,0xF6,0x00,0xA0,0xF2,0xA0,
+    0x18,0xFF,0xD7,0xF6,0xAE,0xBE,0xEB,0x7F,0x18,0xFF,0xF7,0xF6,0xFF,0xED,0x77,0xD5,
+    0x18,0xF7,0xD7,0xF6,0xDE,0xFA,0x7E,0xFF,0xF7,0xF6,0xD7,0xF6,0xBC,0xEE,0x2E,0x9E,
+    0xF7,0xF6,0xD7,0xF6,0xA8,0xAA,0xAE,0x8A,0xD7,0xF6,0xF7,0xEE,0x2A,0xA2,0x02,0x00,
+    0xD7,0xF6,0xB6,0xEE,0xCA,0xEB,0xE3,0xEB,0xB6,0xEE,0x96,0xEE,0xE0,0xC0,0x78,0x56,
+    0x96,0xEE,0x75,0xEE,0x9E,0xB8,0xC2,0x6A,0xD7,0xF6,0x76,0xEE,0xAB,0x0B,0xEF,0xAD,
+    0xD7,0xF6,0xB6,0xEE,0xEA,0xEB,0xAB,0x3A,0xD7,0xF6,0xB6,0xEE,0x8B,0xFB,0x63,0x74,
+    0x96,0xEE,0x14,0xDE,0xF8,0xFC,0xFC,0x58,0x96,0xEE,0x35,0xE6,0x2B,0xAB,0x8F,0xAD,
+    0x75,0xEE,0x56,0xE6,0xE8,0xA2,0x2B,0x2A,0x96,0xEE,0x55,0xEE,0xB7,0x9D,0x2F,0x8B,
+    0x96,0xEE,0xF4,0xDD,0x60,0x72,0x68,0xE0,0x14,0xDE,0x72,0xCD,0xB7,0x2F,0x35,0xB7,
+    0x76,0xEE,0xF3,0xDD,0x2D,0xAF,0x2B,0x2B,0x75,0xEE,0x35,0xE6,0x72,0x7A,0x5A,0x7A,
+    0x14,0xE6,0xD3,0xDD,0xE8,0xFA,0x7E,0x56,0x14,0xE6,0x93,0xD5,0x62,0x6A,0xEF,0x7B,
+    0xF0,0xC4,0x8B,0x93,0xFC,0xFC,0x7C,0xF8,0x72,0xD5,0xEC,0x9B,0x35,0x25,0x2D,0x2B,
+    0x55,0xEE,0x92,0xD5,0xBD,0xAD,0x2D,0xAD,0x96,0xEE,0x34,0xE6,0xFD,0x2A,0x0A,0x02,
+    0x96,0xEE,0x34,0xE6,0x57,0xF4,0x80,0x00,0xB7,0xF6,0x55,0xE6,0x09,0x29,0xEA,0xFF,
+    0xB6,0xEE,0x14,0xE6,0xB0,0xFA,0xFE,0xD6,0x96,0xEE,0xF4,0xDD,0x2A,0x0A,0xAA,0x75,
+    0x96,0xEE,0x35,0xE6,0x20,0x00,0x82,0x09,0xB6,0xF6,0x55,0xE6,0xAA,0xEA,0x7E,0x7F,
+    0xD6,0xF6,0xB6,0xEE,0xBE,0x2B,0x2A,0xAA,0xF7,0xF6,0xD7,0xF6,0x7C,0x9F,0x55,0x55,
+    0xD7,0xF6,0xD6,0xEE,0xAB,0xAA,0x88,0xAA,0xD6,0xF6,0xD7,0xEE,0xAA,0xAA,0x8A,0x8A,
+    0xD6,0xF6,0xB6,0xEE,0x80,0xA2,0xAB,0x0B,0xF6,0xF6,0xB7,0xEE,0xFA,0xFE,0xBA,0xAB,
+    0xD6,0xF6,0xF8,0xEE,0x00,0xA2,0x02,0x02,0xD6,0xF6,0xB6,0xE6,0x88,0x32,0x02,0x00,
+    0xD6,0xF6,0xF8,0xEE,0x08,0x82,0x20,0x22,0xD7,0xF6,0xD6,0xEE,0xAA,0xA2,0xA8,0xA3,
+    0xB5,0xF6,0xF6,0xEE,0xFA,0xEA,0xBF,0xAA,0xD6,0xF6,0xD6,0xEE,0x38,0xA8,0xAA,0xA8,
+    0xD6,0xF6,0xB6,0xEE,0xF2,0xE2,0x70,0x78,0xD6,0xF6,0xB6,0xEE,0xAA,0xAF,0x9D,0x57,
+    0xD6,0xF6,0xB6,0xEE,0xEF,0x96,0xFE,0xAA,0xD6,0xF6,0xB6,0xEE,0xFE,0xEE,0xEB,0xFE,
+    0xD6,0xF6,0xB6,0xF6,0xA8,0x0B,0x8D,0xAF,0xD6,0xF6,0xB6,0xEE,0x80,0x00,0x80,0xA3,
+    0xF6,0xF6,0xB6,0xEE,0xAA,0x9E,0xBF,0xEF,0xF6,0xF6,0xB6,0xEE,0xAA,0xDA,0xBF,0xEF,
+    0xD6,0xF6,0xF7,0xEE,0x88,0x80,0x20,0xA8,0xF7,0xF6,0xD6,0xF6,0xFA,0xFA,0xED,0xF7,
+    0xF7,0xF6,0xD6,0xF6,0x38,0x96,0xEB,0xFA,0xF7,0xFE,0xD7,0xF6,0xAA,0xAF,0xFF,0x74,
+    0xF7,0xFE,0x75,0xEE,0xA2,0xAA,0xEA,0x7E,0x54,0xEE,0x29,0x83,0x80,0xE0,0xE0,0x78,
+    0xEC,0xA3,0xE5,0x61,0xF8,0xFA,0xFE,0x57,0xC8,0x7A,0x64,0x51,0x00,0xA0,0xFB,0x57,
+    0xA8,0x7A,0x63,0x51,0xA0,0xE8,0xFF,0xD5,0x26,0x6A,0x84,0x51,0xA0,0xA8,0xBB,0xD5,
+    0x06,0x62,0xA5,0x59,0x02,0x22,0xBB,0xDD,0x26,0x6A,0x84,0x51,0xAA,0x82,0x8E,0x6F,
+    0x26,0x6A,0x23,0x41,0xA0,0x8A,0xFA,0x5F,0xE5,0x59,0x43,0x49,0x00,0xFA,0x7E,0x55,
+    0xC5,0x59,0x43,0x49,0x2A,0xAA,0xFE,0xFD,0xA4,0x51,0x64,0x51,0xB0,0xE8,0xAF,0x7D,
+    0xC5,0x61,0x43,0x49,0xDF,0xFF,0x2F,0x0F,0xA8,0x7A,0x84,0x59,0x55,0xFF,0xAB,0x2E,
+    0x47,0x72,0xA5,0x59,0x55,0xFE,0xA8,0x00,0x27,0x6A,0xC5,0x59,0xB7,0xAF,0x98,0x90,
+    0x47,0x6A,0xE5,0x61,0x79,0xF2,0x20,0xAA,0x06,0x6A,0xC5,0x61,0xA7,0x3A,0x9A,0xAC,
+    0xA8,0x7A,0x06,0x6A,0xF7,0xB5,0x8D,0x2F,0x8B,0xA3,0x67,0x72,0xFD,0xAF,0xAB,0x0B,
+    0xCC,0xA3,0xE9,0x8A,0x55,0xFF,0xAA,0x20,0xAB,0xA3,0xC9,0x8A,0xFD,0xAE,0xCA,0x00,
+    0x8B,0xA3,0x09,0x93,0x55,0xEF,0xFB,0x78,0x8B,0xA3,0x2A,0x9B,0x39,0x3F,0x2D,0xA9,
+    0xAB,0xA3,0x6A,0xA3,0xAE,0x9A,0xDC,0x55,0x2D,0xBC,0x8B,0xA3,0x2B,0x25,0xAD,0xF5,
+    0xCF,0xCC,0xCC,0xAB,0x2A,0xAF,0x37,0xFD,0xCF,0xCC,0x2D,0xBC,0x78,0xE8,0x7A,0x77,
+    0x2E,0xBC,0x4A,0x9B,0xF8,0xF8,0x78,0x5E,0x29,0x93,0x46,0x7A,0x80,0xFC,0xFA,0x5E,
+    0xC8,0x8A,0xE5,0x69,0xE0,0xFA,0x56,0x5F,0x46,0x72,0xA4,0x61,0xDE,0x5F,0xAA,0x0A,
+    0xF3,0xE5,0xA7,0x7A,0xD5,0xB5,0x25,0x2D,0xD6,0xF6,0x10,0xCD,0x2D,0x2B,0x02,0x02,
+    0x18,0xFF,0xB6,0xFE,0xAB,0x8A,0x2A,0x22,0x17,0xFF,0xF8,0xFE,0xAF,0xB9,0xAB,0x22,
+    0x17,0xFF,0xF8,0xF6,0xAA,0xA2,0xA8,0x08,0x17,0xFF,0xF8,0xF6,0xEA,0xA0,0x82,0x82,
+    0xF7,0xFE,0x18,0xF7,0xFF,0xEF,0xBF,0xFA,0x17,0xFF,0xF7,0xF6,0x5B,0xFD,0xFF,0xEF,
+    0x17,0xFF,0xD7,0xF6,0xAA,0xE2,0xEA,0x7A,0xF7,0xF6,0x96,0xEE,0xE8,0x78,0xBF,0xAF,
+    0xF7,0xF6,0xB6,0xEE,0x7D,0x2F,0x0A,0x00,0x18,0xFF,0xD7,0xF6,0xBD,0x0B,0x02,0x00,
+    0x38,0xFF,0x18,0xFF,0xB5,0xAD,0xAD,0x8D,0x38,0xFF,0x18,0xFF,0x0A,0x02,0x02,0x00,
+    0x38,0xFF,0xF4,0xDD,0xA0,0xE8,0x78,0x78,0xF7,0xFE,0xD3,0xD5,0x2B,0x27,0x2D,0x2D,
+    0x38,0xFF,0x18,0xFF,0xED,0x7D,0xFD,0xFD,0x39,0xFF,0x18,0xFF,0x2F,0xAE,0xBF,0xBD,
+    0x38,0xFF,0x19,0xFF,0xE8,0xF8,0xFA,0x6A,0x18,0xFF,0xF8,0xF6,0xA8,0xF8,0x72,0xDA,
+    0x18,0xFF,0xD7,0xF6,0xFF,0xAB,0xAF,0xBF,0x18,0xFF,0xF8,0xF6,0xEE,0xBA,0x0A,0x6A,
+    0x18,0xFF,0xF8,0xF6,0xFF,0xFE,0xAA,0xBD,0x18,0xFF,0xF8,0xF6,0xFE,0x9F,0xAF,0x8A,
+    0x18,0xFF,0xF8,0xF6,0xAF,0x2B,0x8E,0x0A,0x18,0xFF,0xD7,0xF6,0x7A,0xE2,0xEA,0xEA,
+    0xF7,0xFE,0x55,0xE6,0x5F,0x5E,0xFA,0xF8,0x75,0xEE,0x55,0xE6,0x55,0x7F,0xFA,0x02,
+    0x55,0xEE,0x75,0xE6,0x80,0x82,0xBE,0xAB,0xB6,0xF6,0x54,0xE6,0x2F,0x29,0x2B,0xAB,
+    0xF7,0xF6,0xB7,0xF6,0xAF,0x0F,0xA5,0x3D,0xF8,0xF6,0xD7,0xF6,0xEB,0x6E,0x60,0x60,
+    0xF7,0xF6,0xD8,0xF6,0x02,0x02,0xAB,0xBD,0xD6,0xFE,0xF8,0xF6,0x55,0x5D,0xDD,0x5F,
+    0xF8,0xF6,0xD8,0xF6,0x00,0xAE,0xBE,0xAA,0xF8,0xF6,0xD7,0xF6,0xAA,0x8B,0xB3,0x82,
+    0xF7,0xF6,0xD7,0xF6,0x88,0xA8,0x82,0x00,0xF7,0xF6,0xD7,0xF6,0x08,0xE0,0xC8,0x00,
+    0xF7,0xF6,0xD7,0xF6,0x00,0x8A,0x8F,0xBF,0xF7,0xF6,0xD7,0xF6,0x20,0x00,0x0A,0x3B,
+    0xF7,0xF6,0xD7,0xF6,0xCA,0xC8,0xE2,0x28,0xF7,0xFE,0xD7,0xF6,0x2D,0x2D,0x2B,0xBA,
+    0xF7,0xF6,0xD7,0xF6,0xA8,0xA8,0xE8,0xFA,0xF7,0xF6,0xD7,0xF6,0xDE,0xDF,0x7E,0x56,
+    0xF7,0xF6,0xD7,0xF6,0xEB,0x4A,0xDD,0x55,0xF7,0xF6,0xB7,0xEE,0x8F,0xBF,0xDE,0xFE,
+    0xD7,0xF6,0x96,0xEE,0xE8,0xEC,0x7E,0x7F,0xB6,0xEE,0x55,0xE6,0xF8,0xFA,0x7A,0x5F,
+    0x96,0xEE,0x55,0xE6,0xBB,0xBD,0xBD,0x35,0xD7,0xF6,0x96,0xEE,0xAD,0x2D,0x0F,0x3B,
+    0xD7,0xF6,0xB6,0xF6,0xB2,0xDF,0xD8,0xEA,0xD7,0xF6,0x96,0xEE,0xA8,0xAA,0xEB,0xE8,
+    0x96,0xEE,0xF4,0xDD,0x78,0x78,0x5C,0x5A,0x76,0xEE,0xF4,0xDD,0x03,0x2B,0x2D,0xAF,
+    0x75,0xEE,0x55,0xE6,0x88,0xA2,0x88,0xA2,0x96,0xEE,0x75,0xEE,0xBF,0xD7,0x7D,0x55,
+    0x76,0xEE,0xD3,0xD5,0x60,0xF8,0x60,0x68,0xF4,0xDD,0x92,0xD5,0xAF,0x27,0x2D,0x3F,
+    0x55,0xEE,0xF4,0xDD,0x0B,0x2B,0x29,0xA7,0x76,0xEE,0x35,0xE6,0x7A,0x7A,0x62,0x6B,
+    0x35,0xE6,0xD3,0xDD,0x56,0x7E,0xE2,0xE8,0x15,0xE6,0xB3,0xD5,0x7B,0x6A,0x62,0x68,
+    0x31,0xC5,0x0D,0xA4,0xDC,0x7C,0xBC,0xAA,0x92,0xD5,0xAF,0xB4,0x2D,0x2D,0x09,0xAF,
+    0x55,0xEE,0x92,0xD5,0x3F,0x35,0x95,0xFD,0x96,0xF6,0xF4,0xDD,0x00,0x22,0xAA,0xF5,
+    0x96,0xEE,0xD3,0xDD,0xA0,0xEA,0xFF,0x5F,0x35,0xE6,0x92,0xD5,0x80,0xBA,0xDF,0x55,
+    0xF4,0xDD,0x52,0xCD,0x00,0xAA,0xFB,0xFD,0xF4,0xDD,0x92,0xD5,0x8F,0xAF,0xAD,0x0D,
+    0x76,0xEE,0xF3,0xDD,0x0D,0xA5,0xAD,0xAD,0x76,0xEE,0x35,0xE6,0xE8,0xFC,0x57,0x55,
+    0xD6,0xF6,0xB6,0xEE,0xAA,0xAA,0x08,0x83,0xF6,0xF6,0xB7,0xEE,0xFB,0xEB,0xAA,0xAF,
+    0xD6,0xF6,0xB6,0xEE,0x2B,0x83,0x02,0x08,0xD6,0xF6,0xD7,0xEE,0x8A,0xAA,0xAA,0x2A,
+    0xD6,0xF6,0xD7,0xEE,0xA2,0x8A,0xA8,0xAA,0xF6,0xF6,0xD6,0xF6,0xBD,0xCB,0x7D,0x55,
+    0xD6,0xF6,0xB6,0xEE,0x38,0x00,0x2A,0x38,0xF6,0xF6,0xD6,0xF6,0xF5,0xF5,0xDD,0xFD,
+    0xD6,0xF6,0xD7,0xEE,0x8A,0xA8,0x2A,0xA8,0xD6,0xF6,0xB6,0xEE,0xAA,0x8A,0x30,0x00,
+    0xF6,0xF6,0xB6,0xEE,0xFF,0xFF,0xEE,0xAA,0xD6,0xF6,0xD6,0xEE,0x2A,0x22,0xAA,0xAA,
+    0xD6,0xF6,0xB6,0xEE,0xB6,0x2E,0xA2,0xFA,0xD6,0xF6,0xB6,0xEE,0x9F,0xDF,0xE7,0xA5,
+    0xB6,0xF6,0xD6,0xEE,0xEB,0xAA,0xBA,0x2A,0xD6,0xF6,0xB6,0xEE,0xFA,0x63,0xAF,0xBD,
+    0xD7,0xF6,0xB6,0xF6,0xFB,0xEB,0xEA,0xF7,0xD6,0xF6,0xB6,0xEE,0x29,0xFB,0xAF,0xAB,
+    0xD6,0xF6,0xB6,0xEE,0x0A,0x0A,0x28,0xBA,0xD6,0xF6,0xB6,0xEE,0x08,0x28,0xA8,0xA3,
+    0xD6,0xF6,0xB6,0xEE,0x00,0xA2,0xA8,0xA2,0xF6,0xF6,0xB5,0xEE,0xAA,0xBA,0xEE,0xFA,
+    0xF6,0xF6,0xB5,0xEE,0x2A,0xAB,0x3F,0xFF,0xF6,0xF6,0xB7,0xF6,0xE8,0xFA,0xFE,0xFE,
+    0xD7,0xF6,0x75,0xEE,0x6A,0x68,0xC0,0xC0,0xF3,0xDD,0xE8,0x82,0x78,0x78,0x78,0x78,
+    0x46,0x6A,0xA4,0x51,0x7E,0x56,0x5C,0x58,0x84,0x51,0x23,0x41,0x77,0xBE,0x7A,0xA0,
+    0x63,0x49,0xE2,0x38,0x02,0xA8,0xDF,0x56,0x84,0x51,0xC2,0x30,0x0A,0x2E,0xEF,0x55,
+    0x84,0x51,0xC2,0x30,0x00,0x02,0xBF,0xFD,0xA4,0x51,0x03,0x39,0xA0,0xFB,0xD7,0x55,
+    0x84,0x51,0xE2,0x38,0xE2,0xDB,0xD5,0x57,0x43,0x49,0xE2,0x38,0x82,0xB6,0xFD,0x75,
+    0x44,0x49,0xC2,0x38,0x22,0xAF,0xAD,0xAB,0x84,0x51,0x23,0x49,0xA9,0xAD,0x3F,0xF9,
+    0x67,0x72,0x84,0x59,0xBD,0x2D,0x2D,0x2F,0xE8,0x82,0x67,0x72,0xBD,0x29,0x8B,0xAB,
+    0xA8,0x7A,0x47,0x72,0xFC,0x7E,0x7C,0xF2,0x47,0x6A,0xC5,0x61,0xBC,0xA8,0xF8,0x5C,
+    0x26,0x6A,0xC5,0x59,0xEC,0x7F,0xFB,0xEB,0x26,0x6A,0xC5,0x61,0xBE,0xAD,0xA9,0xAA,
+    0xC8,0x82,0x26,0x6A,0x3D,0x2D,0x2F,0xB7,0xCC,0xA3,0xC9,0x82,0x0B,0x0B,0xA9,0xA5,
+    0x0D,0xB4,0xAC,0xA3,0xA2,0x2A,0x2F,0x9D,0x4E,0xBC,0xED,0xAB,0x5F,0xFE,0x2F,0x8F,
+    0x4D,0xBC,0x4A,0x9B,0x5F,0xFA,0xC0,0x80,0xCC,0xAB,0x2A,0x9B,0xF7,0x5E,0x7E,0xB0,
+    0x8B,0xA3,0x29,0x9B,0x6F,0x75,0xFB,0x80,0x8B,0xA3,0xE8,0x8A,0x2A,0xAF,0xFF,0x55,
+    0xEC,0xAB,0x09,0x93,0x0A,0xAB,0xAF,0xFD,0x0D,0xB4,0x6A,0x9B,0x0A,0xAF,0xBF,0x75,
+    0xEC,0xAB,0xC8,0x8A,0xE0,0xF8,0x7A,0x5F,0xC8,0x8A,0x26,0x72,0xFC,0xFE,0xDF,0x57,
+    0xC9,0x8A,0xE6,0x69,0x5D,0x7F,0x8A,0x0B,0x4D,0xB4,0x26,0x72,0xD5,0xBD,0x3D,0x2F,
+    0xB6,0xFE,0xAB,0x9B,0xAD,0x2D,0x2A,0x0A,0x18,0xFF,0x96,0xF6,0x29,0x2F,0x8B,0x2A,
+    0x18,0xFF,0xF7,0xFE,0xBD,0xBD,0xA5,0xA7,0x18,0xFF,0x17,0xF7,0xAA,0xA8,0xA0,0x20,
+    0x18,0xFF,0xF6,0xEE,0xA8,0x22,0x08,0xA0,0xF7,0xFE,0x18,0xF7,0xDF,0xFF,0xFF,0xEF,
+    0x17,0xFF,0xF7,0xF6,0x9E,0xBA,0x88,0xAA,0x17,0xFF,0xD7,0xF6,0xAA,0x82,0xE0,0x68,
+    0xF7,0xF6,0xD7,0xF6,0x70,0x58,0x57,0x5F,0xF8,0xFE,0xD6,0xEE,0xB5,0xAB,0xAE,0x8B,
+    0x38,0xFF,0xF7,0xF6,0xF5,0xBF,0xAD,0xAB,0x38,0xFF,0x18,0xFF,0xD5,0xAB,0x0A,0x02,
+    0x59,0xFF,0x18,0xFF,0xAD,0xAA,0xAA,0x2A,0x38,0xFF,0x96,0xEE,0x80,0x80,0x40,0xF0,
+    0xD7,0xF6,0xF4,0xDD,0x78,0x7E,0xFE,0xFE,0x18,0xFF,0x14,0xDE,0x2D,0x2D,0x0F,0x8F,
+    0x38,0xFF,0x18,0xFF,0xFD,0xFD,0x7D,0x55,0x39,0xFF,0x18,0xFF,0xAD,0xAD,0xAF,0x7D,
+    0x39,0xFF,0x18,0xFF,0x6E,0xFE,0xDE,0x5F,0x18,0xFF,0xF8,0xF6,0x5F,0x5A,0xD6,0xDE,
+    0x18,0xFF,0xF8,0xF6,0x95,0xB5,0x9D,0xDD,0x18,0xFF,0xF8,0xF6,0xD6,0xFA,0xFE,0x7F,
+    0x18,0xFF,0xF8,0xF6,0xA9,0xAB,0x77,0xF7,0x18,0xFF,0xF8,0xF6,0x80,0x80,0xAA,0xAB,
+    0x18,0xFF,0xF7,0xF6,0x8E,0x8B,0x82,0x82,0x18,0xFF,0xF7,0xF6,0xFE,0xEA,0xFA,0xFF,
+    0xF7,0xF6,0xB7,0xF6,0x52,0x70,0x78,0x78,0xB6,0xF6,0x76,0xEE,0x57,0x5E,0x7C,0xFA,
+    0x96,0xEE,0x76,0xEE,0x55,0xBD,0x69,0xCA,0xB6,0xF6,0x55,0xE6,0xA9,0xAB,0xAB,0x2E,
+    0xF7,0xF6,0x96,0xEE,0xAF,0xB9,0x2F,0x2B,0x18,0xFF,0xD7,0xF6,0xFF,0xEB,0xBF,0xAF,
+    0xF7,0xF6,0xD7,0xF6,0x3B,0xAF,0x2F,0x28,0x18,0xFF,0xF7,0xF6,0x55,0x55,0xF7,0x7F,
+    0xF8,0xF6,0xD7,0xF6,0x2A,0xA8,0x08,0x00,0xD7,0xFE,0xF7,0xF6,0x57,0xD7,0x55,0x55,
+    0xF7,0xF6,0xD7,0xF6,0x88,0x0A,0x22,0xAA,0x18,0xFF,0xD7,0xF6,0xFA,0xFB,0xFB,0xF9,
+    0xF7,0xF6,0xD7,0xF6,0x96,0xFE,0xAA,0xA2,0xF7,0xF6,0xD7,0xF6,0xD7,0x5D,0x55,0x58,
+    0xF7,0xF6,0xD7,0xF6,0x88,0x2B,0xEF,0x2C,0xF7,0xF6,0xD7,0xF6,0xB4,0xD4,0xFE,0xFA,
+    0xF7,0xF6,0xD7,0xF6,0xAF,0xAF,0xED,0xD7,0xF7,0xF6,0x97,0xEE,0xA8,0xAA,0x80,0xEA,
+    0xD7,0xF6,0xB7,0xEE,0x08,0x02,0x82,0xAC,0xD7,0xF6,0x96,0xEE,0xA8,0xA0,0xE8,0xFA,
+    0xB7,0xF6,0x55,0xEE,0xA0,0xE8,0xE2,0x7E,0x75,0xEE,0x35,0xE6,0xB0,0xA8,0xEE,0xFF,
+    0x96,0xEE,0x55,0xE6,0x3D,0x0D,0x0B,0x0B,0xD7,0xF6,0xB7,0xF6,0x8D,0x35,0xE9,0xFD,
+    0xD7,0xF6,0xB6,0xF6,0x38,0xF8,0xE2,0x77,0xD7,0xF6,0x76,0xEE,0xA8,0xAA,0xE8,0x7A,
+    0x76,0xEE,0xD4,0xD5,0xD8,0x5C,0x7E,0x5A,0x55,0xEE,0xD4,0xDD,0x2F,0xAD,0xAD,0xBD,
+    0x75,0xEE,0x55,0xE6,0x09,0x2F,0x37,0x05,0x96,0xEE,0x75,0xEE,0xFF,0xEE,0x77,0x57,
+    0x76,0xEE,0xD3,0xD5,0x68,0x70,0x60,0xFA,0xF4,0xDD,0x92,0xCD,0x37,0x3D,0x37,0x3F,
+    0x55,0xEE,0xF4,0xDD,0x2F,0x29,0x29,0x2D,0x55,0xEE,0x35,0xE6,0xE2,0x68,0xEA,0x8A,
+    0x55,0xEE,0xB3,0xDD,0xFA,0x7E,0x7E,0xF0,0xF4,0xDD,0x92,0xD5,0x4A,0x7A,0x4A,0xC2,
+    0x72,0xCD,0xCF,0xBC,0x56,0xF6,0xBE,0xF8,0x92,0xD5,0xF0,0xBC,0xAD,0x2F,0x2F,0x2F,
+    0xB3,0xDD,0x72,0xD5,0x2D,0xBD,0xDF,0x7D,0xB3,0xDD,0x51,0xCD,0xA0,0x6C,0xFA,0x5F,
+    0xB2,0xD5,0x31,0xCD,0xA8,0xFF,0x77,0x55,0x72,0xCD,0x31,0xCD,0x80,0x8A,0x2B,0x3D,
+    0xB3,0xDD,0x51,0xCD,0xB5,0xBF,0x2F,0x2B,0xF4,0xE5,0xB3,0xD5,0xBF,0xB7,0xFF,0x35,
+    0x55,0xE6,0xF4,0xDD,0x2D,0xAD,0x2F,0xEB,0x55,0xE6,0x14,0xE6,0xFE,0xAE,0x2F,0x2B,
+    0xD6,0xF6,0xB6,0xF6,0xE2,0xEA,0xBE,0x7E,0xD6,0xF6,0xB6,0xEE,0x22,0xE2,0xA0,0x2A,
+    0xD6,0xF6,0xB6,0xEE,0x02,0x88,0x22,0x08,0xD6,0xF6,0xF8,0xEE,0x88,0x20,0xAA,0x28,
+    0xD6,0xF6,0xB7,0xEE,0xA2,0xA8,0x00,0x02,0xF7,0xF6,0xD6,0xF6,0xF7,0xE7,0x7F,0x5D,
+    0xB6,0xF6,0xF6,0xEE,0xAB,0xEF,0xAB,0xAF,0xF6,0xF6,0xB6,0xEE,0x8A,0xA2,0xAA,0xBF,
+    0xF6,0xF6,0xB6,0xEE,0xFE,0xBE,0xBA,0xAA,0xD6,0xF6,0xB6,0xEE,0x82,0xA0,0x8A,0x28,
+    0xD6,0xF6,0xF7,0xEE,0xA8,0x80,0x02,0x80,0xF6,0xF6,0xB6,0xEE,0xFA,0xBA,0xBF,0xFE,
+    0xD6,0xF6,0xB6,0xEE,0xEE,0xBA,0x2A,0x00,0xD6,0xF6,0xB6,0xEE,0xB7,0x7B,0xEA,0x00,
+    0xD6,0xF6,0xB6,0xEE,0xFF,0xEB,0x8A,0x22,0xD6,0xF6,0xB6,0xF6,0xDD,0xEE,0x68,0xA8,
+    0xB6,0xF6,0xD6,0xEE,0x82,0xAA,0xE8,0xFE,0xB6,0xF6,0xD5,0xEE,0xAA,0xAA,0xF8,0xEA,
+    0xB6,0xF6,0xD6,0xEE,0xEE,0xBA,0xA8,0xF8,0xB6,0xF6,0xD6,0xEE,0xFF,0xEB,0xAA,0x8E,
+    0xD6,0xF6,0xB6,0xEE,0x0A,0x23,0x8B,0x0A,0xD6,0xF6,0xF6,0xEE,0x22,0x02,0xA8,0x80,
+    0xF7,0xF6,0xB6,0xEE,0xBF,0xAE,0xAA,0xEA,0xD6,0xF6,0xB7,0xF6,0xB8,0xBA,0xBE,0xBC,
+    0xD7,0xF6,0x34,0xE6,0xC0,0xE0,0x60,0x68,0x71,0xCD,0x86,0x72,0xF0,0x70,0x78,0x78,
+    0x46,0x6A,0x64,0x49,0xF8,0x78,0x5A,0x5E,0xA4,0x51,0x02,0x39,0xE8,0xFA,0x7A,0x7F,
+    0x02,0x39,0xA1,0x28,0xF8,0xE0,0xEA,0x56,0xC2,0x30,0x81,0x28,0xF8,0xA8,0xA8,0x00,
+    0x03,0x39,0xA2,0x28,0xAB,0x8F,0x6F,0xE7,0xE3,0x38,0xC2,0x30,0x2F,0xEB,0x79,0x7D,
+    0x03,0x39,0xC2,0x30,0xA7,0x2B,0x0B,0x85,0x23,0x41,0xE2,0x38,0x57,0xD6,0xAB,0x0A,
+    0x44,0x49,0x03,0x39,0xE9,0xB9,0xAB,0xA9,0xE5,0x61,0x43,0x49,0xD5,0x35,0xA5,0x35,
+    0x09,0x93,0xA5,0x59,0xBD,0xAF,0xAB,0x2B,0xE9,0x8A,0x87,0x7A,0xFF,0x5B,0x7A,0x60,
+    0xA7,0x82,0xC5,0x61,0xA0,0xFA,0x77,0x5E,0x26,0x6A,0x63,0x49,0xF8,0xFA,0xFF,0x57,
+    0xE5,0x59,0x02,0x41,0x02,0xA2,0xBF,0xF7,0x06,0x6A,0x84,0x51,0x02,0xAB,0xAF,0xB5,
+    0x87,0x7A,0xE6,0x61,0x0F,0x2F,0xA9,0x2D,0x4B,0x93,0x67,0x72,0x0B,0x2B,0xBD,0xF5,
+    0x8B,0x9B,0xA8,0x82,0x08,0xAA,0xAF,0xF5,0x0C,0xAC,0x09,0x93,0x08,0x2F,0xBF,0xF5,
+    0x2D,0xBC,0x8B,0xA3,0x82,0x02,0x2A,0xA9,0x2D,0xB4,0xAB,0xA3,0x7C,0xFA,0xFA,0x7A,
+    0xCC,0xAB,0x6A,0x9B,0x6B,0x6A,0xE8,0xBE,0x6A,0xA3,0xC8,0x8A,0xFA,0x78,0xE0,0xC8,
+    0x49,0x9B,0xA7,0x82,0x0A,0xAB,0xFB,0x5F,0x4A,0x9B,0x87,0x7A,0xA0,0xFA,0x7F,0x56,
+    0x09,0x93,0x46,0x7A,0x60,0xEA,0xAA,0xAB,0x0A,0x93,0x27,0x72,0x7D,0xF7,0xAA,0x02,
+    0x09,0x93,0x68,0x7A,0x35,0xA7,0x2B,0x02,0xEF,0xC4,0x09,0x8B,0x3D,0x25,0x2D,0xAD,
+    0xB6,0xFE,0x51,0xD5,0x0B,0x0B,0x09,0x0D,0x18,0xFF,0xD7,0xFE,0xEB,0xAB,0x29,0xAF,
+    0x18,0xFF,0xF7,0xFE,0xAB,0x7E,0x7A,0x7E,0x18,0xFF,0xF7,0xFE,0x0A,0x09,0xAB,0xAA,
+    0x17,0xFF,0xF8,0xF6,0x22,0x82,0x0A,0x02,0x17,0xFF,0xF8,0xF6,0xB8,0xE8,0x20,0x80,
+    0x18,0xFF,0xD7,0xF6,0x28,0x80,0x80,0x78,0xF7,0xF6,0xD7,0xF6,0xE0,0xE8,0xFE,0x77,
+    0xF7,0xF6,0xD7,0xF6,0xF9,0xAD,0xBD,0xA7,0x18,0xFF,0xD7,0xF6,0xAF,0xAD,0xBF,0xAF,
+    0x38,0xFF,0xF7,0xFE,0xBB,0xAF,0x09,0x02,0x59,0xFF,0x39,0xFF,0xF5,0xF5,0xED,0xFB,
+    0x59,0xFF,0x18,0xFF,0x8A,0xAA,0xEA,0x7E,0x18,0xFF,0x96,0xEE,0x70,0x78,0x58,0x5E,
+    0x96,0xEE,0x55,0xE6,0x5E,0x7A,0xFA,0xFA,0x18,0xFF,0x76,0xEE,0x2D,0x29,0x8F,0x0B,
+    0x18,0xFF,0x19,0xF7,0x22,0x88,0x82,0x22,0x39,0xFF,0x18,0xFF,0xF9,0xED,0xB9,0x9D,
+    0x39,0xFF,0x18,0xFF,0x7F,0x7E,0x5E,0x7E,0x18,0xFF,0xF8,0xF6,0xFE,0xEA,0xA8,0x2A,
+    0x18,0xFF,0xF8,0xF6,0xFF,0xFA,0xBF,0x77,0xF7,0xFE,0xF8,0xF6,0x7F,0xDF,0x7F,0x75,
+    0x18,0xFF,0xF8,0xF6,0xA9,0xC9,0xB9,0xBB,0xF8,0xFE,0x18,0xF7,0x5E,0xFE,0xFE,0xEE,
+    0x18,0xFF,0xF7,0xEE,0x22,0x0A,0x22,0xA8,0x18,0xFF,0xF7,0xF6,0x76,0x7E,0xF8,0x78,
+    0xF7,0xF6,0xB7,0xEE,0xFA,0x7A,0x7C,0xFC,0x96,0xF6,0xB6,0xEE,0x2B,0xAD,0xFE,0xFD,
+    0xB7,0xF6,0x96,0xEE,0x55,0x77,0xF8,0xF8,0xD6,0xF6,0x75,0xEE,0xF5,0xDD,0xF7,0xBF,
+    0xD7,0xF6,0x96,0xEE,0x03,0x0B,0x2F,0x2B,0x18,0xFF,0xD7,0xF6,0xAF,0xAA,0xAB,0xE9,
+    0xF7,0xF6,0xD7,0xF6,0xA8,0xA8,0xA8,0xA8,0x18,0xFF,0xD7,0xF6,0xAA,0x8B,0x2B,0xAD,
+    0x18,0xFF,0xD7,0xF6,0xFE,0xFA,0xB8,0x28,0x18,0xF7,0xD7,0xF6,0xEF,0xFF,0xFE,0xA8,
+    0x18,0xF7,0xD7,0xF6,0xF7,0xFF,0xBB,0xAB,0x18,0xFF,0xD7,0xF6,0xF5,0xFF,0xAE,0xBE,
+    0x18,0xFF,0xD7,0xF6,0xEE,0xAE,0xFE,0xFE,0xD8,0xFE,0xF7,0xF6,0xF5,0xFD,0xF5,0xF5,
+    0xF7,0xF6,0xD7,0xF6,0x28,0xAA,0xAF,0xEA,0xF7,0xF6,0xB6,0xEE,0xA0,0xEA,0x7C,0x7E,
+    0xF7,0xF6,0x96,0xEE,0xAA,0x2B,0xBF,0xD5,0xD7,0xF6,0x96,0xEE,0xA0,0xF8,0x5E,0x5F,
+    0xB6,0xEE,0x76,0xEE,0x28,0xAA,0xDB,0x5D,0xB6,0xF6,0x35,0xE6,0x80,0xAA,0xFA,0x7F,
+    0x96,0xEE,0x35,0xE6,0x68,0xEE,0xFF,0xFF,0x96,0xEE,0x35,0xE6,0xBD,0xAB,0xAB,0x0A,
+    0x76,0xF6,0x96,0xEE,0x7E,0x7F,0x5F,0xDD,0xD7,0xF6,0xB7,0xF6,0xED,0xAB,0xDB,0xC3,
+    0xB6,0xF6,0x96,0xEE,0x6C,0xFE,0xB7,0xF6,0xB6,0xF6,0x76,0xEE,0x7B,0xFF,0xEA,0x82,
+    0x56,0xEE,0xB3,0xD5,0x58,0x78,0x7C,0xD8,0x35,0xE6,0xD3,0xD5,0x35,0x2D,0xAB,0xBF,
+    0x76,0xEE,0x35,0xE6,0x0D,0x2D,0xA5,0xB5,0x76,0xEE,0x55,0xE6,0xE0,0xE0,0xE0,0x73,
+    0x55,0xE6,0xB2,0xD5,0xE0,0x70,0x68,0x70,0xF3,0xDD,0xB2,0xD5,0x35,0xA7,0xB5,0x95,
+    0x55,0xEE,0xF4,0xDD,0xA9,0x29,0xAD,0xBB,0x76,0xEE,0xD3,0xDD,0x8A,0x8A,0xAA,0xDF,
+    0x55,0xEE,0xD3,0xDD,0x68,0xFA,0xE2,0xEB,0x14,0xE6,0xB3,0xD5,0x7F,0x62,0xE2,0xEA,
+    0x72,0xCD,0x8F,0xB4,0xE8,0xF8,0xFC,0xDE,0x72,0xD5,0xD0,0xBC,0x2B,0x2B,0xA9,0x2D,
+    0x92,0xD5,0x52,0xCD,0xB2,0xEF,0xFF,0xDF,0x72,0xCD,0x31,0xCD,0xC8,0xF2,0x42,0x5A,
+    0x71,0xCD,0x31,0xC5,0x55,0xFE,0xBD,0x35,0xB3,0xD5,0x31,0xC5,0xAD,0xAB,0xAF,0x0A,
+    0xB3,0xD5,0x92,0xD5,0xC9,0xC1,0xB9,0xDD,0xF4,0xDD,0x92,0xD5,0x2F,0xAE,0xA7,0x3B,
+    0x14,0xE6,0xD3,0xDD,0x00,0x0A,0xEF,0x5B,0x75,0xEE,0xF4,0xDD,0x2B,0xAF,0xAF,0xBD,
+    0xB6,0xF6,0x50,0xC5,0x00,0x00,0x82,0xB5,0xD6,0xF6,0x55,0xEE,0x08,0x0A,0x8A,0xA9,
+    0xD6,0xF6,0xB6,0xEE,0x28,0xA2,0xAA,0xFE,0xD6,0xF6,0xB6,0xEE,0x02,0x80,0xA3,0xE2,
+    0xD6,0xF6,0xB6,0xEE,0xAA,0xAA,0xA8,0xAA,0xD6,0xF6,0xD7,0xEE,0xAA,0x2A,0x8A,0x20,
+    0xF8,0xF6,0xD6,0xF6,0x77,0x7D,0xE5,0xBD,0xF7,0xF6,0xB6,0xEE,0xBF,0xEE,0xBA,0xEA,
+    0xF6,0xF6,0xB6,0xEE,0xAA,0xAB,0xEB,0xFF,0xD6,0xF6,0xD6,0xEE,0xA8,0x2A,0xAA,0xAA,
+    0xD6,0xF6,0xF6,0xEE,0x00,0xA0,0x8A,0xA0,0xD6,0xF6,0xF7,0xEE,0x08,0x88,0x08,0x02,
+    0xD6,0xF6,0xF6,0xEE,0x88,0x00,0x80,0xA2,0xF7,0xF6,0xD6,0xF6,0xE7,0xA5,0xB5,0xD5,
+    0xF7,0xF6,0xD6,0xF6,0x55,0x75,0xF7,0x5F,0xD6,0xF6,0xD6,0xF6,0x00,0x00,0x00,0x00,
+    0xF7,0xF6,0xD6,0xF6,0x55,0x55,0x75,0xFD,0xD6,0xF6,0xB6,0xEE,0x3B,0x83,0x8B,0x80,
+    0xD6,0xF6,0xB6,0xF6,0x0C,0x8A,0x88,0x00,0xD6,0xF6,0xB6,0xF6,0x9A,0x9A,0x3A,0xBE,
+    0xD6,0xF6,0xB6,0xEE,0x08,0x28,0x2A,0xBA,0xD6,0xF6,0xB6,0xEE,0x00,0x28,0x2A,0x02,
+    0xD6,0xF6,0xB6,0xF6,0x20,0xE0,0x60,0xB8,0xF7,0xF6,0xB6,0xF6,0xFA,0xDF,0x7F,0xDF,
+    0xD6,0xF6,0xB2,0xD5,0xE0,0x60,0x60,0x68,0xCE,0xBC,0x05,0x62,0x78,0x78,0x78,0x58,
+    0xC5,0x59,0x23,0x41,0xE8,0xE8,0x5C,0xEE,0x43,0x41,0xE2,0x30,0xC0,0xE0,0xFE,0x78,
+    0x02,0x31,0xA1,0x28,0x7A,0x78,0xD8,0x5E,0xE2,0x28,0x81,0x28,0xE2,0xFE,0xFA,0xF7,
+    0xC1,0x28,0x80,0x28,0x28,0x28,0xFB,0xBF,0x03,0x31,0xA2,0x28,0x2B,0x2F,0xB9,0xEB,
+    0x02,0x31,0xC2,0x30,0x07,0xAF,0xAD,0xAF,0x23,0x41,0xE2,0x30,0x0A,0x2B,0xA9,0xE9,
+    0x43,0x49,0x03,0x41,0x8B,0x02,0x23,0x29,0x26,0x6A,0x64,0x51,0xB5,0x2D,0x2D,0x2D,
+    0x09,0x8B,0x66,0x7A,0x0D,0x09,0x09,0x29,0x29,0x93,0xA7,0x82,0xDA,0xF8,0xE8,0x70,
+    0x87,0x7A,0xA5,0x59,0x58,0x5C,0x5C,0x7C,0x85,0x59,0x03,0x41,0xF8,0x7E,0x77,0x5F,
+    0x23,0x49,0xE2,0x38,0x2C,0xAF,0xDE,0xFE,0xC6,0x61,0xE2,0x38,0x0A,0xAF,0xFF,0xF5,
+    0x46,0x6A,0x64,0x51,0x0A,0x2B,0xAD,0xBD,0xA8,0x7A,0x06,0x62,0x0B,0xBF,0xF7,0xFD,
+    0xC9,0x82,0x26,0x6A,0x22,0xA2,0xB7,0xF5,0x2A,0x93,0x87,0x7A,0x0A,0x0A,0xAF,0xBD,
+    0xEC,0xAB,0x09,0x93,0x2B,0xAF,0xAD,0xB5,0xEC,0xAB,0xAC,0xAB,0x78,0x72,0x3E,0x3D,
+    0xCC,0xAB,0x6A,0xA3,0xFF,0xED,0xAC,0xFC,0xAB,0xA3,0xE9,0x8A,0xEA,0xE8,0xE0,0x78,
+    0xE8,0x8A,0x67,0x7A,0xF8,0x78,0x7E,0x7F,0x87,0x7A,0x46,0x7A,0xBA,0xF6,0x7F,0xA7,
+    0x29,0x93,0x67,0x7A,0xB9,0x3D,0xB5,0xAD,0xEC,0xAB,0x0A,0x93,0x7D,0xAF,0x0B,0x03,
+    0xAB,0xA3,0x29,0x93,0x75,0x7F,0xEA,0x88,0x6D,0xB4,0x09,0x8B,0x3D,0x35,0x35,0xB7,
+    0xD7,0xFE,0x4D,0xB4,0x0B,0x0B,0xAB,0xD5,0xF7,0xFE,0xD3,0xDD,0x00,0x00,0x0A,0x2D,
+    0x17,0xFF,0xF8,0xFE,0xDB,0xFE,0xB7,0xF5,0x18,0xFF,0xF8,0xFE,0xAB,0xAE,0xFF,0xA7,
+    0x18,0xFF,0xF7,0xFE,0x0A,0x0B,0x2A,0xBE,0x38,0xFF,0xF7,0xF6,0xAA,0xEA,0xFB,0x5F,
+    0x18,0xFF,0xB6,0xEE,0xE8,0xFA,0xFA,0x7F,0xD7,0xF6,0xB6,0xEE,0x00,0xA0,0xE2,0xFA,
+    0xF7,0xF6,0xB6,0xEE,0xAA,0xFB,0x6D,0xDD,0x39,0xFF,0xB6,0xEE,0xBF,0x2D,0x2D,0x0F,
+    0x59,0xFF,0x38,0xFF,0xB5,0xFD,0xAB,0xEE,0x59,0xFF,0x39,0xFF,0xEB,0xEE,0xFA,0x5F,
+    0x38,0xFF,0xD7,0xF6,0xC0,0xE0,0xF0,0x68,0xD6,0xEE,0x76,0xEE,0xFC,0xFE,0xFE,0xF7,
+    0x96,0xEE,0x55,0xE6,0xD8,0x9C,0xB6,0x37,0x18,0xFF,0x96,0xEE,0x01,0x0B,0x29,0x8B,
+    0x18,0xFF,0xF8,0xF6,0x82,0x0A,0x0A,0x22,0x39,0xFF,0x18,0xFF,0x95,0xB5,0xB5,0xFD,
+    0x39,0xFF,0x18,0xFF,0x7A,0x7E,0x7A,0x7E,0x18,0xFF,0xF8,0xF6,0xAE,0xBA,0xAA,0xEA,
+    0x18,0xFF,0xF8,0xF6,0xDF,0x5E,0x58,0x5E,0x18,0xF7,0xD7,0xF6,0xBF,0xAE,0x2B,0xAA,
+    0x18,0xFF,0xF8,0xF6,0xAB,0xEE,0xA9,0xFD,0x18,0xFF,0xF8,0xF6,0xBB,0xDE,0xAE,0xAA,
+    0x18,0xFF,0xF8,0xF6,0xAA,0xBF,0xBE,0xAA,0x18,0xFF,0xF8,0xF6,0x58,0x7A,0xEA,0xFE,
+    0xF7,0xF6,0xB7,0xF6,0xFE,0xE0,0xE0,0xA0,0xD7,0xF6,0xB6,0xEE,0xEF,0xB5,0x35,0x87,
+    0xD7,0xF6,0x96,0xEE,0xFA,0xE0,0xA0,0x20,0xD7,0xF6,0x96,0xEE,0x97,0x9F,0xBE,0xAA,
+    0xD7,0xF6,0x96,0xEE,0xAB,0xBF,0xBB,0xB8,0x18,0xFF,0xB6,0xEE,0xAB,0xAF,0xAD,0x2D,
+    0xF8,0xFE,0xF7,0xF6,0x5F,0x5F,0xDE,0x5F,0x18,0xF7,0xB7,0xF6,0x0A,0x2A,0x2E,0xAA,
+    0x18,0xFF,0xF7,0xF6,0x28,0x28,0x0A,0xAF,0x18,0xFF,0xF8,0xF6,0xA8,0xA0,0xE8,0xB8,
+    0x18,0xFF,0xF7,0xF6,0x7E,0x5D,0x7D,0xEA,0x17,0xFF,0xF8,0xF6,0xFD,0xDD,0xDF,0xB7,
+    0x18,0xFF,0xD7,0xF6,0xFE,0xDE,0xDA,0xEA,0xF8,0xFE,0xF7,0xF6,0xFF,0xFB,0xFF,0xF7,
+    0xF7,0xF6,0xD7,0xF6,0x6F,0xDE,0x5E,0x56,0xD7,0xF6,0x96,0xEE,0xF8,0xEA,0xA8,0xBA,
+    0xB7,0xF6,0x96,0xEE,0x77,0xEB,0x80,0xA0,0x97,0xEE,0x76,0xEE,0xD8,0x5C,0x5C,0xDC,
+    0x96,0xEE,0x76,0xEE,0x55,0xA5,0x9F,0xFE,0x96,0xEE,0x35,0xE6,0x7E,0xF8,0xB2,0xAA,
+    0x96,0xEE,0x55,0xEE,0xD5,0xBD,0x2B,0xAA,0x96,0xEE,0x76,0xEE,0xAD,0x3B,0x00,0xA3,
+    0xB6,0xF6,0x76,0xEE,0xAB,0x89,0xAF,0x3F,0xD7,0xF6,0x96,0xEE,0x22,0xAB,0x6B,0x7F,
+    0xB6,0xF6,0x76,0xEE,0xAE,0x2A,0xBA,0xF7,0xB6,0xF6,0x96,0xEE,0xA2,0x8A,0xE2,0x63,
+    0x76,0xEE,0xD3,0xD5,0x5C,0x58,0x7E,0x5C,0x14,0xE6,0xD3,0xD5,0xAB,0x2D,0x2F,0xA5,
+    0x55,0xEE,0x14,0xE6,0x0B,0x8B,0x8B,0x09,0x75,0xEE,0x35,0xE6,0xF3,0xBF,0xBF,0xAB,
+    0x75,0xEE,0xB2,0xD5,0x78,0x78,0x7E,0x7A,0xF3,0xDD,0x92,0xD5,0x35,0xAD,0xB5,0xBD,
+    0x34,0xE6,0xD3,0xDD,0x8B,0xEB,0x7B,0x7B,0xD4,0xDD,0x30,0xC5,0x28,0xBC,0xFC,0x57,
+    0x14,0xE6,0x71,0xCD,0x00,0x2B,0xAD,0xF5,0x14,0xE6,0x92,0xD5,0xE0,0xCA,0xE2,0x4A,
+    0x51,0xCD,0x2D,0xAC,0xF8,0xFC,0xFC,0xDC,0x72,0xD5,0xD0,0xBC,0x8D,0x2D,0xAD,0x2D,
+    0x72,0xCD,0x10,0xC5,0xE0,0xA0,0x88,0x60,0x51,0xCD,0x11,0xC5,0xB3,0x8F,0xBF,0xF9,
+    0x71,0xCD,0x31,0xC5,0xAD,0x3F,0xED,0xF7,0xB3,0xD5,0x72,0xD5,0x95,0xAD,0xEF,0xA5,
+    0xB3,0xD5,0x51,0xD5,0xBA,0x22,0x22,0x0A,0x14,0xE6,0xB3,0xD5,0x9D,0xAD,0xBF,0xAD,
+    0xF4,0xDD,0xB3,0xDD,0xB8,0x38,0xB2,0xDE,0x35,0xE6,0xD3,0xDD,0x2B,0xAF,0xDB,0x77,
+    0xCE,0xBC,0xE8,0x82,0x2B,0xF5,0x55,0x55,0x14,0xE6,0x29,0x8B,0x02,0xBF,0x75,0x55,
+    0x95,0xEE,0x8A,0x93,0x00,0x02,0xBD,0x55,0x95,0xEE,0x4D,0xAC,0x00,0x00,0x0A,0xB5,
+    0xB6,0xF6,0x13,0xDE,0x00,0x00,0x00,0x0D,0xD6,0xF6,0xB6,0xF6,0x08,0xAA,0x8A,0x75,
+    0x17,0xFF,0xB6,0xF6,0xFF,0xFF,0x9D,0xD7,0xD7,0xF6,0xB6,0xF6,0x00,0x08,0xAA,0xAE,
+    0xD7,0xF6,0xB6,0xF6,0xAC,0x2A,0xAB,0x08,0xF7,0xFE,0xD6,0xF6,0x55,0x55,0xFD,0xB7,
+    0xF7,0xF6,0xD6,0xF6,0xB5,0x9F,0x5B,0x7F,0xF7,0xF6,0xD6,0xF6,0x57,0x57,0x37,0xF5,
+    0xF7,0xF6,0xD6,0xF6,0xFB,0x7A,0x7E,0x7A,0xF7,0xFE,0xD6,0xF6,0x55,0xF5,0xB7,0xFD,
+    0xF6,0xF6,0xD6,0xF6,0x5D,0x7D,0x6A,0x5A,0xF7,0xF6,0xD6,0xF6,0xD5,0xD7,0x57,0x5F,
+    0xF6,0xFE,0xD6,0xF6,0xE7,0xFF,0x57,0x59,0xF6,0xF6,0xB7,0xF6,0xAA,0xEB,0xAF,0xFF,
+    0xF7,0xF6,0xD6,0xF6,0xA5,0xAF,0x3E,0xFF,0xF7,0xFE,0xD6,0xF6,0x55,0x57,0x5F,0xF7,
+    0xD6,0xF6,0xB6,0xF6,0xBC,0xAA,0xA0,0x08,0xD6,0xF6,0xB6,0xF6,0x8E,0xA7,0xAF,0x0A,
+    0xD6,0xF6,0xB6,0xF6,0xEC,0xF8,0x88,0x20,0xD6,0xF6,0xB6,0xF6,0xAB,0xEB,0xCA,0xAA,
+    0xB6,0xF6,0xB3,0xD5,0x60,0x60,0x60,0x60,0x6E,0xB4,0x63,0x49,0xF8,0x78,0x78,0x78,
+    0x84,0x49,0x23,0x41,0xE0,0xF0,0x78,0x7A,0x43,0x41,0xE2,0x30,0x78,0xF8,0x7E,0xF5,
+    0xE2,0x30,0x81,0x28,0xEA,0x6A,0x58,0x78,0xA1,0x28,0x40,0x20,0x08,0x22,0xBC,0xB7,
+    0xC2,0x28,0x81,0x20,0xBF,0x25,0x25,0x0D,0xE2,0x30,0xA1,0x28,0x0A,0x0B,0xAD,0x3F,
+    0x03,0x31,0xC2,0x30,0xEA,0xFA,0xFB,0xE9,0x02,0x39,0xC2,0x30,0x8F,0xAF,0xAB,0x8A,
+    0x44,0x49,0xE2,0x38,0x09,0x0F,0xAF,0x2D,0x26,0x72,0x64,0x51,0x2D,0x3D,0x0D,0x2D,
+    0x29,0x93,0x87,0x7A,0x29,0x0D,0xBF,0xB5,0x2A,0x93,0xA8,0x82,0xE8,0xB2,0x78,0x6A,
+    0x88,0x7A,0x44,0x49,0xF8,0x78,0x78,0x7A,0x44,0x49,0xE2,0x38,0xB8,0x78,0x78,0x5C,
+    0x02,0x39,0xC2,0x38,0xAC,0xB6,0xD7,0xDF,0x44,0x49,0xE3,0x38,0x2D,0x27,0x2D,0x29,
+    0x05,0x62,0x43,0x49,0x8B,0x3D,0xB5,0xFD,0x26,0x6A,0xA5,0x51,0x0A,0xAB,0xA5,0x2D,
+    0x87,0x72,0x06,0x62,0x3B,0xAF,0x0D,0xBF,0x09,0x8B,0x66,0x72,0x3D,0xBD,0xED,0xFF,
+    0x29,0x93,0xC8,0x82,0x0E,0x2E,0xFD,0xB5,0xAB,0xAB,0xE8,0x8A,0x03,0x2B,0xAD,0x95,
+    0xAB,0xA3,0x4A,0x9B,0x2A,0xA0,0xEA,0x75,0x6A,0x9B,0xC8,0x82,0xE0,0xE0,0x78,0x7E,
+    0xA8,0x82,0x47,0x72,0xEA,0xFA,0xFE,0xDE,0xC8,0x8A,0x46,0x7A,0xB7,0xBD,0x0F,0x0B,
+    0x4A,0x93,0xA8,0x82,0xAD,0x2B,0x2B,0x2B,0x0C,0xAC,0x4A,0x9B,0x0F,0x0B,0x2B,0xAD,
+    0x2C,0xB4,0x8B,0x9B,0x5E,0x68,0x68,0x6A,0x2A,0x93,0x66,0x72,0xA0,0x78,0x78,0x78,
+    0x6A,0x93,0x06,0x6A,0x0A,0xEF,0xF5,0xD5,0xF4,0xE5,0x87,0x7A,0x0B,0xBF,0xF5,0x55,
+    0xB6,0xF6,0x86,0x72,0x00,0x0A,0xBF,0xD5,0xD7,0xFE,0xCE,0xBC,0x00,0x02,0x0B,0x2D,
+    0x18,0xFF,0xD7,0xFE,0xA2,0x22,0xA3,0xEF,0xF7,0xFE,0x96,0xF6,0x80,0xF0,0x7A,0xFA,
+    0xB6,0xF6,0xD6,0xE6,0x88,0x88,0x08,0x20,0xD6,0xF6,0xB6,0xEE,0xAA,0xCF,0xE9,0x7F,
+    0x18,0xFF,0xB6,0xEE,0xD5,0x95,0xBD,0x2D,0x59,0xFF,0xF7,0xFE,0xAD,0x2B,0x22,0x8A,
+    0x59,0xFF,0x38,0xFF,0xEA,0xFE,0xFF,0x7B,0x59,0xFF,0x18,0xFF,0xAE,0xFA,0xFA,0xEE,
+    0x38,0xFF,0x56,0xEE,0xE0,0xE8,0xEA,0x78,0x96,0xEE,0x55,0xE6,0xC8,0xAA,0xEB,0xFF,
+    0xB6,0xF6,0x34,0xE6,0x3F,0xAF,0xBF,0x35,0x18,0xFF,0xD7,0xF6,0xBD,0x2D,0xA5,0xAD,
+    0x18,0xFF,0xF8,0xF6,0x0E,0x22,0x0A,0x23,0x38,0xFF,0x19,0xFF,0xBF,0xEB,0xBD,0xAD,
+    0x39,0xFF,0x18,0xFF,0x5E,0xDF,0xDE,0x7E,0x18,0xFF,0xF8,0xF6,0xE2,0xE0,0xAA,0xB8,
+    0x18,0xFF,0xF8,0xF6,0x77,0x57,0x5D,0x5D,0x18,0xFF,0xF8,0xF6,0x5F,0x7F,0xEF,0xEF,
+    0x18,0xFF,0xF8,0xF6,0xED,0xFB,0xBB,0xFD,0x18,0xFF,0xF8,0xF6,0xEA,0xEB,0xE9,0xF7,
+    0x18,0xFF,0xF8,0xF6,0xAA,0xAA,0xEF,0xAA,0x18,0xFF,0xF8,0xF6,0xFE,0xDE,0xFE,0x5E,
+    0xF8,0xF6,0xD7,0xF6,0x60,0x70,0x5C,0x79,0xD7,0xF6,0xB7,0xEE,0x2F,0x0B,0x2A,0x0E,
+    0xF8,0xF6,0xB6,0xEE,0x6E,0xEA,0x8A,0xAA,0xF7,0xF6,0xB6,0xEE,0x9F,0xBB,0xAA,0xB2,
+    0xD7,0xF6,0xB6,0xEE,0x7E,0xE8,0x2A,0x0A,0xF7,0xFE,0xD6,0xEE,0x2D,0x2F,0xBD,0xAF,
+    0x18,0xFF,0xF7,0xF6,0x7F,0x77,0xFF,0x7B,0x18,0xF7,0xD7,0xF6,0xBF,0xFF,0xAF,0xAE,
+    0xF8,0xFE,0x18,0xF7,0xFE,0xFE,0xFF,0xFA,0x18,0xFF,0xF7,0xF6,0xEE,0xBB,0xAE,0xAF,
+    0x18,0xFF,0xF7,0xF6,0xAA,0xAA,0x20,0xA2,0x18,0xFF,0xF7,0xF6,0xE7,0x97,0xD6,0xF7,
+    0x18,0xFF,0xF7,0xF6,0x7D,0x5E,0x76,0x6F,0xD7,0xFE,0xF7,0xF6,0xF7,0xFF,0xDF,0xF7,
+    0xF7,0xF6,0x96,0xEE,0xA8,0xBA,0xFA,0x7E,0xD7,0xF6,0x96,0xEE,0xBA,0xFA,0xFA,0xFF,
+    0xB6,0xF6,0x96,0xEE,0xC0,0xE0,0xDB,0x5F,0x96,0xEE,0x76,0xEE,0x88,0x20,0xA3,0xAD,
+    0x96,0xEE,0x76,0xEE,0xFD,0x6E,0x76,0x5F,0x75,0xEE,0x55,0xE6,0x2A,0xE8,0x7A,0xEE,
+    0x76,0xEE,0x55,0xE6,0xCC,0xE7,0xB5,0xF5,0x76,0xEE,0x55,0xE6,0x00,0x8B,0x22,0x2A,
+    0xB6,0xF6,0x76,0xEE,0xAF,0x89,0xAD,0x2D,0xB6,0xF6,0x76,0xEE,0xAA,0xE2,0xFA,0x6A,
+    0x96,0xF6,0x76,0xEE,0x3E,0x0B,0x09,0x2B,0xB6,0xF6,0x76,0xEE,0x8A,0xC2,0xCA,0x48,
+    0x55,0xE6,0x92,0xCD,0x78,0x5C,0x5C,0x5A,0x15,0xE6,0x92,0xD5,0x2F,0xAB,0xAD,0xB5,
+    0x55,0xEE,0xF4,0xE5,0x2A,0xAF,0x09,0x2B,0x76,0xEE,0x55,0xEE,0xDD,0xF5,0xD9,0x5F,
+    0x55,0xEE,0xB2,0xD5,0x78,0x78,0x6A,0x78,0xD3,0xDD,0x92,0xD5,0x0B,0x29,0x2E,0x2B,
+    0x14,0xE6,0xB2,0xD5,0x63,0x63,0x6A,0x62,0x92,0xD5,0xF0,0xBC,0xFE,0xDE,0x7E,0x5C,
+    0x92,0xD5,0xEF,0xC4,0x2B,0xBD,0xB5,0xFF,0xD4,0xDD,0x71,0xCD,0xCA,0x8F,0xCF,0x85,
+    0x51,0xCD,0x2D,0xAC,0xDC,0x5C,0xDE,0xDC,0x51,0xCD,0xAF,0xB4,0x89,0x21,0xA9,0x2D,
+    0x51,0xCD,0xD0,0xBC,0xE0,0xFA,0xF6,0xDE,0x51,0xCD,0xF0,0xC4,0x9F,0x2D,0x2F,0xA9,
+    0x71,0xD5,0x31,0xC5,0x9B,0xAD,0x3F,0x9F,0x92,0xD5,0x52,0xCD,0x2A,0x8B,0x2B,0xAF,
+    0xB3,0xD5,0x92,0xD5,0xDF,0x35,0x25,0x95,0xF3,0xDD,0xB3,0xD5,0xAD,0xC9,0xFB,0xFF,
+    0xD3,0xDD,0xB2,0xD5,0x3D,0xAD,0x7D,0xFD,0xD3,0xDD,0x71,0xCD,0x08,0xE8,0x78,0x5E,
+    0xE8,0x82,0xA7,0x7A,0x0E,0x80,0x3A,0x98,0x08,0x83,0xC8,0x82,0x28,0xAE,0xCB,0x0F,
+    0x28,0x8B,0xC7,0x7A,0x0A,0xBB,0xEF,0xDF,0xEB,0x9B,0xC7,0x7A,0x2B,0xFF,0x7F,0xD7,
+    0x91,0xD5,0x08,0x83,0x0A,0xFD,0x55,0x55,0x75,0xEE,0x49,0x8B,0x00,0x2B,0xF5,0x55,
+    0x95,0xEE,0xE8,0x82,0x00,0x00,0x2A,0xBD,0xD6,0xF6,0x50,0xCD,0x00,0x02,0x2A,0xBD,
+    0xD6,0xF6,0x54,0xEE,0x00,0x08,0x82,0xAD,0xD6,0xF6,0xB6,0xF6,0x28,0x22,0x0A,0x8D,
+    0xF7,0xF6,0xB6,0xF6,0xAE,0x2F,0xEF,0xBF,0xF7,0xFE,0xB6,0xF6,0xBB,0xBA,0xFE,0x7A,
+    0xD6,0xF6,0xB6,0xF6,0x00,0x80,0xA3,0xAA,0x16,0xF7,0xB6,0xF6,0xEF,0xDD,0xFF,0x55,
+    0xF7,0xFE,0xD6,0xF6,0x7F,0x5D,0xD5,0x5D,0xF6,0xF6,0xD6,0xF6,0x7D,0xD5,0xFD,0x77,
+    0xF7,0xF6,0xD6,0xF6,0x56,0xFE,0x5E,0x57,0xD6,0xF6,0xB6,0xF6,0xE0,0xB0,0x00,0x00,
+    0xF7,0xFE,0xB6,0xF6,0xBB,0xFF,0xFB,0xAA,0xD7,0xF6,0xD6,0xF6,0xFD,0xF5,0xFF,0xEE,
+    0xD7,0xF6,0xD6,0xF6,0xAD,0xBF,0xBD,0xF5,0xB6,0xFE,0xF7,0xF6,0xFA,0xFB,0xEE,0x7A,
+    0xF6,0xF6,0xD6,0xF6,0x57,0xB7,0xEF,0xAB,0xB7,0xFE,0xF6,0xF6,0xBA,0xAF,0xFF,0xEF,
+    0xD6,0xF6,0xB3,0xD5,0x60,0xE8,0xC0,0xC0,0xEF,0xBC,0x43,0x49,0x78,0x78,0x78,0x78,
+    0x64,0x49,0x02,0x39,0xFC,0xFE,0x7B,0xFE,0x23,0x41,0xE2,0x38,0x7D,0x6E,0xF8,0xE0,
+    0x23,0x39,0x80,0x28,0x7E,0xFA,0xAA,0x22,0x03,0x39,0x60,0x20,0xD5,0xFF,0xBA,0x20,
+    0x02,0x31,0x81,0x20,0xAD,0xA1,0xBA,0xA8,0x02,0x39,0xC2,0x30,0xBD,0xAB,0xAF,0xAB,
+    0x23,0x39,0xC2,0x30,0x7D,0xEF,0xEA,0xCB,0x03,0x39,0xC2,0x30,0x2E,0xB7,0xA7,0xFB,
+    0x84,0x59,0xE3,0x38,0xBD,0xAD,0x37,0x25,0x87,0x7A,0x64,0x59,0xAD,0x2D,0x2F,0x2F,
+    0xE9,0x8A,0x87,0x7A,0x09,0xA9,0xA9,0xF5,0xE9,0x8A,0x05,0x6A,0x80,0x80,0xE2,0x7B,
+    0x47,0x72,0xE3,0x38,0xF0,0xE8,0xF8,0x7F,0x24,0x41,0xA1,0x30,0xF0,0xFA,0x7C,0xFE,
+    0xE2,0x38,0xC2,0x30,0xFD,0x2D,0x39,0xBB,0x44,0x49,0xC2,0x38,0x8F,0x2F,0xAF,0x6D,
+    0xA5,0x51,0x81,0x28,0x02,0xAA,0xFE,0x5D,0xA5,0x51,0x61,0x28,0x00,0xAA,0xDF,0x75,
+    0xE5,0x61,0xA2,0x30,0x00,0xAB,0x7D,0x55,0x46,0x6A,0xE3,0x40,0x00,0x0A,0xBD,0xD5,
+    0xE8,0x8A,0x84,0x51,0x02,0x8A,0xAF,0xBD,0x29,0x93,0x87,0x7A,0x2A,0xAB,0xBF,0xB5,
+    0x4A,0x9B,0xC8,0x82,0x02,0xAB,0x7F,0x55,0x2A,0x93,0x67,0x7A,0x60,0x60,0xEE,0xEE,
+    0xA8,0x82,0x46,0x7A,0x93,0xBF,0xB5,0xAA,0x09,0x8B,0x87,0x7A,0x65,0x3F,0x2F,0xAD,
+    0x4A,0x93,0xE9,0x8A,0xAF,0xA3,0xEA,0x7F,0x6A,0x9B,0xC8,0x82,0x2A,0xAF,0x37,0xBD,
+    0xCC,0xA3,0xE9,0x8A,0xA0,0xEE,0x7E,0x5F,0x4B,0x93,0xA8,0x82,0x78,0xE8,0x62,0x6F,
+    0x87,0x7A,0x06,0x6A,0xD7,0xD8,0x78,0xF8,0x67,0x72,0xC5,0x61,0x0A,0xAE,0x5F,0x7A,
+    0x86,0x7A,0xE6,0x61,0x2A,0xA7,0xBD,0xD5,0x54,0xEE,0x29,0x8B,0x0D,0x3D,0x2D,0xB5,
+    0xD7,0xFE,0x54,0xEE,0x82,0xAB,0xAF,0xB5,0xB6,0xF6,0x96,0xEE,0x28,0xFA,0x3C,0x0A,
+    0xD6,0xF6,0x95,0xEE,0xEF,0xBF,0xEA,0xC0,0xF7,0xF6,0x96,0xEE,0x7E,0xFE,0xBF,0x35,
+    0x38,0xFF,0xB6,0xF6,0x2D,0x0B,0x02,0x02,0x59,0xFF,0x39,0xFF,0xAD,0xED,0xFF,0x5D,
+    0x58,0xFF,0x39,0xFF,0x5B,0xD7,0xDF,0x75,0x39,0xFF,0xF7,0xFE,0xC0,0xE8,0xF8,0x68,
+    0xF8,0xFE,0x75,0xEE,0x58,0x5C,0x5E,0x5F,0x75,0xEE,0x35,0xE6,0xE2,0xE0,0xE2,0xEA,
+    0xD7,0xF6,0x34,0xE6,0x35,0xBD,0xBD,0x3D,0x18,0xFF,0xD7,0xF6,0xA9,0xA9,0x2B,0xAB,
+    0x18,0xFF,0xF8,0xF6,0x2B,0x2F,0x2F,0x3F,0x38,0xFF,0x19,0xFF,0xEF,0xEB,0x6B,0xFD,
+    0x39,0xFF,0x18,0xFF,0xFF,0xFD,0xFD,0xDD,0x18,0xFF,0xF8,0xF6,0xF8,0xA0,0xB0,0xF0,
+    0x18,0xFF,0xF8,0xF6,0xDA,0x6A,0xBE,0xF7,0x18,0xFF,0xF8,0xF6,0xFD,0x77,0x57,0x77,
+    0xF7,0xFE,0xF8,0xF6,0xEF,0xAF,0xAD,0xFF,0x18,0xFF,0xF8,0xF6,0xBF,0xDB,0xF5,0xF7,
+    0x18,0xFF,0xF8,0xF6,0xBA,0x77,0x5F,0xDF,0x18,0xFF,0xD7,0xF6,0xE8,0xBA,0x7E,0x6E,
+    0xF8,0xF6,0xD7,0xF6,0x75,0x76,0x5D,0xEF,0xF8,0xF6,0xB6,0xEE,0xA7,0x2F,0x2A,0xAA,
+    0xF7,0xF6,0xD7,0xF6,0xAF,0xBF,0xAB,0xF8,0xF7,0xF6,0xD7,0xF6,0xBA,0xAB,0xAB,0xEA,
+    0xF7,0xF6,0xD7,0xF6,0x57,0xEF,0xAB,0xA3,0xF8,0xF6,0xD7,0xF6,0xA5,0xA7,0x22,0x0A,
+    0x18,0xFF,0xF8,0xF6,0x6A,0xAB,0x8F,0xFF,0x17,0xFF,0xF7,0xF6,0x75,0x57,0x75,0x5F,
+    0x18,0xFF,0xF7,0xF6,0xBB,0xFD,0xBD,0xFF,0x18,0xFF,0xF7,0xF6,0xB7,0xBD,0xAF,0xAB,
+    0x18,0xFF,0xF8,0xF6,0xBA,0xEE,0xFE,0xBA,0x18,0xFF,0xF7,0xF6,0xDF,0x7F,0xEA,0xEA,
+    0xD7,0xFE,0x18,0xF7,0xBF,0xAB,0xAB,0xAF,0xF7,0xF6,0x98,0xEE,0x88,0xA0,0xAA,0xBA,
+    0xD7,0xF6,0x96,0xEE,0xE8,0xAA,0x78,0x7E,0xB6,0xF6,0x76,0xEE,0xA8,0xAA,0xEA,0xFA,
+    0x96,0xEE,0x56,0xEE,0x00,0x80,0x8A,0xFF,0x96,0xEE,0x55,0xE6,0xAB,0xA8,0xFA,0xFF,
+    0x96,0xEE,0x55,0xE6,0xA8,0xBA,0xAF,0xFE,0x75,0xEE,0x35,0xE6,0xA2,0xE0,0xB8,0xFF,
+    0x55,0xEE,0x76,0xE6,0xA0,0xAA,0xA8,0xAA,0x96,0xEE,0x55,0xE6,0xBD,0xBD,0xBF,0xAF,
+    0xB6,0xF6,0x76,0xEE,0x29,0x23,0xAB,0x2B,0xB6,0xF6,0x76,0xEE,0xF8,0xE8,0xEA,0xFA,
+    0xB6,0xF6,0x76,0xEE,0xAD,0xBB,0xAD,0x2F,0xB7,0xF6,0x55,0xE6,0xA0,0xE2,0xC0,0x48,
+    0x35,0xE6,0x52,0xCD,0xF8,0xDC,0xDE,0x5A,0xF4,0xDD,0x51,0xCD,0x2A,0xA9,0x3D,0xAD,
+    0x55,0xEE,0xD3,0xDD,0x0A,0x8B,0x2F,0xA9,0x75,0xEE,0x35,0xE6,0xFA,0xBE,0xFB,0xDB,
+    0x35,0xEE,0xB3,0xD5,0x78,0x58,0x7C,0x7C,0xF4,0xDD,0x92,0xD5,0xAB,0x2F,0x2D,0xAF,
+    0x14,0xE6,0xD3,0xDD,0x62,0xE2,0xA2,0xE2,0xF3,0xDD,0x11,0xC5,0x7E,0x7A,0xF8,0xA0,
+    0x71,0xCD,0x10,0xC5,0xFD,0x7F,0xD6,0xD8,0xB3,0xD5,0x10,0xC5,0x89,0xAB,0xFD,0xAD,
+    0x30,0xC5,0x4D,0xAC,0x5C,0x5C,0x5E,0x54,0x31,0xCD,0x8E,0xB4,0x29,0x8B,0x0D,0x0D,
+    0x31,0xCD,0xD0,0xBC,0xFF,0x9E,0xAA,0xA8,0x31,0xC5,0xF0,0xC4,0x0F,0x2B,0xBB,0xEB,
+    0x51,0xCD,0x11,0xC5,0x28,0xB2,0xBB,0xFE,0x92,0xD5,0x51,0xCD,0xAB,0xEB,0xAD,0xFD,
+    0xB3,0xD5,0x72,0xCD,0x2B,0x27,0xAF,0x35,0xD3,0xDD,0xB3,0xD5,0x8E,0xEB,0xAF,0x09,
+    0xD3,0xDD,0x92,0xD5,0xEE,0x66,0x78,0x68,0x92,0xD5,0x30,0xCD,0xB8,0x5E,0xFF,0xD7,
+    0x08,0x83,0xC7,0x7A,0xBC,0xB6,0x96,0xDF,0x08,0x83,0xC8,0x7A,0x2A,0xFA,0x5C,0xBA,
+    0x29,0x8B,0xC8,0x7A,0xFE,0x7F,0xB6,0x8E,0x08,0x83,0xC8,0x82,0xF6,0xE6,0xF2,0xBE,
+    0x08,0x83,0xC7,0x7A,0xAA,0x85,0xEF,0x18,0x08,0x83,0xC7,0x82,0x02,0xA3,0x2F,0x0E,
+    0x8A,0x93,0xE8,0x82,0x0B,0x77,0x55,0x57,0xCE,0xBC,0x08,0x83,0x2B,0xF5,0x55,0x55,
+    0x14,0xE6,0x28,0x8B,0x02,0xAF,0xD5,0x55,0x96,0xEE,0x29,0x8B,0x00,0x02,0xBF,0xD5,
+    0xB6,0xF6,0x4E,0xAC,0x00,0x00,0x0A,0xBD,0xD6,0xF6,0xF3,0xE5,0x00,0x00,0x0A,0xAD,
+    0xD6,0xF6,0xB5,0xF6,0xA8,0xAA,0xAA,0xF5,0xD6,0xF6,0xB6,0xF6,0xF7,0xFF,0xFD,0x77,
+    0xD6,0xF6,0xB6,0xF6,0xA2,0xEE,0x7B,0xF9,0xD6,0xF6,0xB6,0xF6,0x0C,0x2B,0x8A,0xE8,
+    0xD7,0xFE,0xD6,0xF6,0xD7,0xDF,0x7D,0xD7,0xF7,0xFE,0xD6,0xF6,0xEF,0xED,0xE9,0xFD,
+    0xF7,0xFE,0xD6,0xF6,0xFF,0xDF,0x7F,0xDF,0xF6,0xFE,0xD7,0xF6,0xFD,0xF5,0x57,0x5D,
+    0xF7,0xFE,0xD6,0xF6,0x55,0x5F,0x5F,0x7F,0xF7,0xFE,0xB6,0xF6,0xAF,0xAF,0xBF,0xBF,
+    0xF6,0xFE,0xD6,0xF6,0xAF,0xBB,0x95,0xF7,0xF7,0xFE,0xB6,0xF6,0xBE,0xEE,0xDE,0xFE,
+    0xD6,0xF6,0x54,0xEE,0x60,0xC0,0xA0,0x80,0xF2,0xDD,0xC4,0x59,0x78,0x58,0x78,0xF8,
+    0x84,0x49,0x02,0x39,0xDF,0x5F,0xFF,0xF0,0x43,0x41,0xE2,0x38,0x2A,0x0B,0xA5,0xBF,
+    0x84,0x49,0x23,0x39,0x59,0x8A,0xAB,0xFD,0x64,0x49,0x02,0x39,0x5F,0xBE,0xA8,0x2A,
+    0x85,0x49,0xE2,0x30,0x57,0x57,0x7A,0xE8,0x43,0x41,0xE2,0x30,0x75,0xFD,0xAA,0xA0,
+    0x23,0x41,0xE2,0x38,0xED,0xBB,0x7B,0x5C,0x03,0x39,0xC2,0x38,0xBA,0xBC,0xB8,0x28,
+    0xE5,0x69,0x23,0x41,0xB5,0xB5,0xAD,0xAD,0x47,0x7A,0xC4,0x61,0x09,0x29,0x03,0x83,
+    0x67,0x7A,0x06,0x72,0x00,0xA0,0xA8,0x43,0x46,0x72,0x84,0x59,0x80,0xC8,0xEA,0x7E,
+    0x84,0x59,0xE3,0x38,0x58,0xE8,0x68,0xE8,0x24,0x41,0xC2,0x38,0x55,0x7A,0xA2,0x60,
+    0x03,0x39,0xC2,0x30,0xFF,0xBF,0x7F,0x65,0xE2,0x38,0xA1,0x28,0x5A,0xF8,0xFA,0x78,
+    0xC2,0x30,0x61,0x28,0x7A,0xBE,0xBA,0xA8,0xA2,0x30,0x82,0x28,0xE5,0x0F,0x0B,0x02,
+    0xC2,0x38,0xA2,0x30,0x29,0x28,0x3F,0x25,0x44,0x49,0xE3,0x38,0xBD,0xAF,0xAD,0x95,
+    0xC5,0x61,0x23,0x49,0x09,0xBD,0xD5,0xDD,0xC8,0x82,0x84,0x59,0x0B,0x2F,0xAD,0xB5,
+    0xC8,0x82,0x67,0x7A,0x2C,0xAA,0xBD,0xF5,0x09,0x93,0x87,0x82,0xFF,0xF7,0xAD,0x25,
+    0xE9,0x8A,0x87,0x7A,0xFB,0x0A,0xCB,0x60,0xE8,0x8A,0x88,0x7A,0xAF,0xB1,0xDD,0x7D,
+    0xE9,0x8A,0x87,0x7A,0x00,0x0B,0xF7,0xF6,0x2A,0x93,0xC9,0x82,0x29,0x2D,0xB9,0x15,
+    0x2A,0x93,0x46,0x72,0xE8,0x78,0x78,0x78,0x29,0x8B,0x06,0x6A,0x8A,0xFD,0xD5,0x75,
+    0x87,0x7A,0xE5,0x69,0xE8,0xBA,0x2F,0xBD,0xC8,0x82,0xC5,0x61,0x7F,0xE2,0xA2,0x0A,
+    0x67,0x72,0xC5,0x61,0xD5,0xD7,0xFE,0x80,0x6E,0xB4,0x26,0x72,0x2D,0xB5,0xF5,0xDD,
+    0x96,0xF6,0xCC,0xA3,0x02,0x0B,0x2D,0xB5,0xD7,0xFE,0x96,0xF6,0x2D,0x0A,0x0A,0x2D,
+    0xF7,0xFE,0x96,0xEE,0x6A,0x78,0xFA,0xAA,0x38,0xFF,0x95,0xEE,0xAD,0x29,0x0B,0x02,
+    0x58,0xFF,0x39,0xFF,0x75,0x5D,0x57,0x57,0x39,0xFF,0x18,0xFF,0x00,0x00,0x00,0x3A,
+    0x39,0xFF,0x18,0xFF,0x80,0xA0,0xF8,0xFA,0x59,0xFF,0xB6,0xEE,0x6A,0x6A,0x7A,0x7E,
+    0x96,0xEE,0x55,0xEE,0xD8,0x7E,0x76,0x57,0x76,0xEE,0x35,0xE6,0xE2,0x68,0x5A,0x5E,
+    0xD7,0xF6,0x35,0xE6,0x25,0x2D,0x2D,0x3F,0x18,0xFF,0xF8,0xF6,0x37,0x9B,0xA9,0xED,
+    0x18,0xFF,0xF8,0xF6,0x3F,0x2E,0x2E,0x0E,0x39,0xFF,0x18,0xFF,0x7F,0x79,0xBF,0x9E,
+    0x18,0xFF,0x3A,0xF7,0x80,0x02,0x22,0x2A,0x18,0xFF,0xF8,0xF6,0xE8,0xF2,0xE8,0xFA,
+    0x18,0xFF,0xF8,0xF6,0x76,0x5D,0xF7,0x77,0x18,0xFF,0xF8,0xF6,0x7F,0x66,0x77,0xF5,
+    0x17,0xFF,0xF8,0xF6,0x7F,0x77,0xFD,0xFD,0x17,0xFF,0xF8,0xF6,0xF7,0xED,0xDF,0x7F,
+    0x17,0xFF,0xF8,0xF6,0xFF,0xF7,0x5D,0xF7,0x18,0xFF,0xF7,0xF6,0x57,0x75,0x6F,0x5F,
+    0xF7,0xF6,0xD7,0xF6,0x7A,0x62,0xE0,0xEC,0xF7,0xF6,0xD7,0xF6,0x35,0xAD,0x5D,0xF9,
+    0xF7,0xF6,0xD7,0xF6,0xEA,0xEA,0xF7,0x6F,0xF8,0xF6,0xD7,0xF6,0xAF,0x9D,0x0D,0x0D,
+    0x17,0xFF,0xF8,0xF6,0xD5,0xF5,0xDF,0xDB,0x18,0xFF,0xF8,0xF6,0x57,0x7D,0xBD,0xF7,
+    0x18,0xFF,0xF8,0xF6,0xEF,0xF9,0xFB,0x3D,0x18,0xFF,0xF7,0xF6,0x5D,0x5A,0x7E,0xEA,
+    0x18,0xFF,0xF7,0xF6,0xED,0xB9,0xED,0x97,0x18,0xFF,0xF8,0xF6,0xAA,0xAB,0xFD,0xFF,
+    0x18,0xFF,0xF7,0xF6,0xAE,0x82,0xAE,0xFE,0xF8,0xFE,0x18,0xF7,0xBF,0x2B,0x2F,0x2E,
+    0xF8,0xF6,0xD7,0xF6,0xF0,0x52,0x58,0x5A,0xD7,0xF6,0x97,0xEE,0xE0,0x68,0xE0,0xA8,
+    0xB7,0xF6,0x76,0xEE,0xA0,0xF0,0xFC,0x7A,0x96,0xEE,0x76,0xEE,0xB8,0x68,0xF8,0x5F,
+    0x96,0xEE,0x55,0xE6,0x7E,0x5E,0xFA,0xBA,0x76,0xEE,0x35,0xE6,0xAF,0xFF,0xFF,0xC0,
+    0x76,0xEE,0x35,0xE6,0xFA,0x5F,0x57,0xFF,0x55,0xE6,0x35,0xE6,0x9E,0xD8,0x02,0x83,
+    0x75,0xEE,0x55,0xE6,0xD9,0xDD,0xFF,0x5D,0x96,0xEE,0x55,0xE6,0xBD,0xB7,0x37,0xAD,
+    0x96,0xF6,0xB7,0xEE,0xE8,0xFE,0xEE,0xBA,0xB7,0xF6,0x76,0xEE,0xE8,0xFC,0xFE,0x5F,
+    0xB6,0xF6,0x96,0xEE,0xE5,0xAD,0xCD,0xFD,0xB6,0xF6,0x55,0xE6,0x6A,0x7A,0x72,0x7A,
+    0xF4,0xDD,0x72,0xCD,0x5C,0x5C,0x5C,0x78,0xD3,0xDD,0x72,0xCD,0x25,0x3D,0xAF,0xE9,
+    0x35,0xE6,0xD3,0xDD,0x2B,0x2B,0x2D,0xAD,0x55,0xEE,0x14,0xE6,0xEA,0xEA,0xEB,0xAF,
+    0x35,0xE6,0xB3,0xD5,0x5A,0xDA,0x7A,0x78,0xF4,0xDD,0xB3,0xD5,0xBD,0x2D,0x39,0x2F,
+    0x14,0xE6,0xD3,0xDD,0xF3,0xA8,0xE2,0x60,0xF4,0xDD,0x92,0xD5,0xE2,0xAA,0x80,0x80,
+    0xD3,0xDD,0x31,0xCD,0x5E,0xFE,0xA8,0x00,0x92,0xD5,0xF0,0xBC,0xBF,0xF7,0x78,0x60,
+    0x10,0xC5,0x4E,0xAC,0x5C,0x5E,0x56,0x57,0x32,0xCD,0x8F,0xB4,0x2D,0x2D,0x0D,0x09,
+    0x52,0xCD,0x11,0xC5,0x5A,0xDA,0xDE,0x7C,0x31,0xC5,0xD0,0xC4,0xAA,0x28,0x2B,0x0A,
+    0x51,0xCD,0x10,0xC5,0xEA,0xAA,0xDA,0xEF,0x72,0xD5,0x51,0xCD,0xAD,0x35,0x55,0x55,
+    0xB3,0xD5,0x72,0xCD,0x15,0x2B,0x3D,0xBD,0x34,0xE6,0xD3,0xDD,0xEB,0xA9,0xC9,0xED,
+    0xD3,0xDD,0x10,0xC5,0xA0,0xE0,0xE0,0x78,0x51,0xCD,0x10,0xC5,0xBC,0xBF,0xF5,0xFF,
+    0xE8,0x82,0xC8,0x7A,0xDA,0x9E,0x80,0xC2,0xE8,0x82,0xA7,0x7A,0xDA,0x2F,0x06,0x3F,
+    0x08,0x83,0xC8,0x7A,0xBE,0xEF,0xED,0xA7,0xE8,0x82,0xC8,0x7A,0x28,0x3F,0x65,0x7A,
+    0x08,0x83,0xA7,0x7A,0x68,0xE2,0x8F,0xF5,0x08,0x83,0xC7,0x82,0xEF,0x7A,0xEF,0x77,
+    0x09,0x8B,0xA7,0x7A,0xBB,0xB7,0x3D,0xFF,0x08,0x8B,0xC8,0x82,0xAC,0x7C,0xCF,0xEF,
+    0x29,0x8B,0xC7,0x82,0xA7,0xEB,0xE9,0x75,0x29,0x8B,0xA7,0x7A,0x89,0x6A,0xF9,0x5A,
+    0x2C,0xA4,0xC8,0x82,0x2F,0xFD,0x55,0x55,0x90,0xD5,0x07,0x83,0x0A,0xBD,0x55,0x55,
+    0x54,0xEE,0x49,0x8B,0x00,0x2A,0xB5,0x55,0x96,0xF6,0x8A,0x9B,0x00,0x00,0x2B,0xF5,
+    0xB6,0xF6,0x72,0xD5,0x00,0x00,0x0A,0xBD,0xD6,0xF6,0x76,0xF6,0xA0,0x8A,0x2A,0xB5,
+    0xD6,0xF6,0xB6,0xF6,0x29,0xBD,0xFF,0x55,0xF7,0xF6,0xB6,0xF6,0xEB,0xFF,0xFF,0xD5,
+    0xB7,0xFE,0xD6,0xF6,0xD5,0xD5,0x77,0xDD,0xF7,0xFE,0xB6,0xF6,0xBF,0xAB,0xAF,0xFB,
+    0xF7,0xFE,0xD7,0xF6,0x55,0x57,0x7F,0x55,0xF7,0xFE,0xB6,0xF6,0x9E,0xBF,0xAE,0xBA,
+    0xD6,0xFE,0xF7,0xF6,0xEA,0xFE,0xFB,0xEA,0xF7,0xFE,0xD7,0xF6,0x77,0x5F,0x7D,0x7B,
+    0xB6,0xFE,0xD6,0xF6,0x95,0xB5,0x57,0x55,0xB5,0xF6,0x29,0x83,0x78,0x78,0x78,0xE8,
+    0x46,0x6A,0x44,0x49,0x5F,0xFE,0xDC,0xDC,0xA5,0x51,0x02,0x41,0xDF,0xFC,0xA2,0xC8,
+    0x84,0x51,0x23,0x41,0x55,0x55,0xDF,0x80,0x84,0x51,0x03,0x39,0xF7,0xFD,0xAF,0x02,
+    0x85,0x49,0x03,0x41,0xFA,0x7B,0x6A,0xF8,0x44,0x41,0xE2,0x38,0x8A,0xAB,0xFB,0xDF,
+    0x23,0x41,0xC2,0x38,0xEC,0xAE,0x29,0x29,0x44,0x49,0xE2,0x38,0xFD,0xBF,0xBE,0x3B,
+    0xE5,0x69,0x23,0x49,0x2F,0xBD,0xBF,0x2B,0x67,0x7A,0xE5,0x69,0xAB,0x8B,0x2D,0xAB,
+    0x47,0x72,0xE4,0x69,0x6E,0x7E,0x7E,0xE0,0xE5,0x69,0x44,0x51,0xF8,0xF8,0x78,0x78,
+    0x64,0x51,0x04,0x41,0xF8,0xDE,0xEA,0xE2,0x44,0x49,0xE3,0x38,0x7A,0xDC,0xF2,0x68,
+    0x03,0x39,0xC2,0x30,0xAB,0xA8,0xF8,0x57,0x03,0x39,0xA1,0x30,0x68,0xEA,0xEF,0x83,
+    0xE2,0x30,0x81,0x28,0xEF,0xBE,0xFA,0x78,0xC2,0x30,0x81,0x28,0xB7,0xFA,0x7A,0x75,
+    0xC2,0x30,0x81,0x28,0x2B,0x3E,0xB5,0xE5,0x44,0x49,0xA2,0x30,0xBF,0xAF,0xBF,0x2D,
+    0x84,0x59,0x03,0x41,0xAF,0x27,0x35,0xB7,0xA9,0x82,0x85,0x59,0x3D,0x3F,0x2F,0x29,
+    0xE9,0x82,0x67,0x7A,0x75,0x7F,0xAA,0x02,0x09,0x8B,0x67,0x72,0x0F,0xAF,0x9F,0x57,
+    0x0A,0x93,0x87,0x7A,0xC0,0xEA,0xE3,0xD5,0xC8,0x82,0x67,0x72,0x2B,0x1F,0x2E,0xB3,
+    0xE9,0x82,0x88,0x82,0x9E,0xFE,0x8E,0x8B,0xE9,0x82,0x87,0x7A,0x3A,0xEA,0x68,0x70,
+    0xE9,0x8A,0xC5,0x61,0xA8,0xAA,0xFE,0x5F,0x47,0x72,0xA5,0x59,0x68,0x58,0x5F,0x57,
+    0x67,0x72,0xA5,0x61,0x3D,0x25,0x2D,0x0D,0x08,0x8B,0x86,0x7A,0xBD,0xAD,0x2A,0xA9,
+    0xE8,0x82,0x67,0x7A,0xFE,0xEA,0x6A,0xE8,0xC8,0x82,0x27,0x72,0x2F,0xB7,0xAF,0x2E,
+    0x2E,0xA4,0xC9,0x82,0x3F,0x95,0xD5,0x55,0x76,0xEE,0x0A,0x8B,0x02,0x2F,0xAD,0xF5,
+    0x38,0xFF,0x14,0xE6,0x2A,0x8A,0x0B,0x2D,0x39,0xFF,0x18,0xFF,0x89,0x2B,0x2A,0xA2,
+    0x39,0xFF,0x38,0xFF,0xA2,0xAA,0xA8,0xAA,0x39,0xFF,0x18,0xFF,0xAA,0xAC,0xBA,0xFC,
+    0x38,0xFF,0x18,0xFF,0x7A,0x7A,0xEE,0xFA,0x18,0xFF,0x75,0xEE,0x68,0x78,0x7C,0x5C,
+    0x76,0xEE,0x55,0xE6,0x76,0x5F,0x2E,0xAE,0x76,0xEE,0x14,0xDE,0xF2,0xFA,0xFA,0xDE,
+    0xD7,0xF6,0x55,0xE6,0x2D,0x2D,0x2B,0x09,0xF8,0xFE,0x18,0xF7,0xEC,0xB8,0xAC,0xEA,
+    0x18,0xFF,0xF8,0xF6,0x2F,0x3D,0x05,0x29,0x39,0xFF,0x18,0xFF,0x9F,0xFF,0x5D,0xDD,
+    0x18,0xFF,0x39,0xF7,0x2A,0x82,0x22,0x02,0x18,0xFF,0xF8,0xF6,0xEA,0xAE,0xAA,0xA2,
+    0x18,0xFF,0xF8,0xF6,0xD5,0x7F,0x7A,0xEF,0xF8,0xFE,0x18,0xF7,0xA8,0xA8,0xAA,0x82,
+    0x18,0xFF,0xF8,0xF6,0xF7,0x7D,0x5F,0x7F,0x19,0xFF,0xF7,0xF6,0x7F,0x5F,0x75,0x75,
+    0xF8,0xFE,0x18,0xF7,0xAA,0xEA,0x8A,0x2A,0x18,0xFF,0xD7,0xF6,0xEA,0x7A,0xFB,0x7E,
+    0x38,0xFF,0xD7,0xF6,0x77,0xFD,0xDD,0xFD,0xF7,0xF6,0xD7,0xF6,0x3A,0xBA,0xEA,0xE2,
+    0xF7,0xF6,0xD7,0xF6,0x7E,0xD6,0xD5,0xDD,0x18,0xFF,0xD7,0xF6,0xBD,0xAF,0xAF,0xFF,
+    0x18,0xFF,0xD7,0xF6,0xAA,0xAE,0xAF,0xFF,0xF8,0xFE,0x17,0xEF,0xAA,0x82,0x22,0x2A,
+    0x18,0xFF,0xF8,0xF6,0xBD,0x3D,0xAF,0x2D,0x18,0xFF,0xF7,0xF6,0xE8,0x6A,0x52,0x6A,
+    0xF7,0xF6,0xD7,0xF6,0x28,0x0C,0x0F,0x0E,0xF8,0xFE,0x18,0xF7,0xFF,0x7E,0xEE,0xBA,
+    0x18,0xFF,0xF8,0xF6,0xFE,0xF6,0xD7,0xDF,0x18,0xFF,0xD7,0xF6,0xA2,0x7A,0xAA,0xEA,
+    0xF8,0xF6,0x97,0xEE,0xA8,0x80,0xA8,0xEA,0xD7,0xF6,0x96,0xEE,0xAA,0xE8,0xFE,0x5A,
+    0xB7,0xF6,0x76,0xEE,0xFA,0xFE,0x5F,0xD7,0x96,0xEE,0x55,0xE6,0xFA,0xBC,0xFA,0x82,
+    0x76,0xEE,0x55,0xE6,0x00,0x20,0xBE,0xD7,0x96,0xEE,0x55,0xEE,0x80,0x80,0xB5,0xFD,
+    0x96,0xEE,0x55,0xE6,0x7B,0xC0,0xA2,0xFA,0x96,0xEE,0x55,0xE6,0x55,0x7F,0xCA,0xAB,
+    0x55,0xEE,0x35,0xE6,0xB9,0x7A,0xB8,0x20,0x96,0xEE,0x55,0xE6,0xBD,0x95,0x25,0x2F,
+    0xB7,0xF6,0x76,0xEE,0xFB,0xFB,0x7A,0x78,0x96,0xEE,0x76,0xEE,0xDA,0x7B,0x7F,0xD5,
+    0x96,0xEE,0x75,0xEE,0xA2,0x3D,0x2B,0x03,0xB7,0xF6,0x35,0xE6,0xFA,0xEA,0x72,0x62,
+    0x14,0xDE,0x51,0xCD,0x7C,0x5C,0x5E,0x5E,0xB3,0xD5,0x51,0xCD,0x2F,0xAD,0xB5,0xBB,
+    0x35,0xEE,0xB3,0xD5,0x2D,0x3D,0x3D,0xBD,0x34,0xE6,0x14,0xE6,0xE0,0xC0,0xC2,0xE7,
+    0x14,0xE6,0xB2,0xD5,0x78,0xE8,0x78,0x70,0x34,0xE6,0xB3,0xD5,0xBD,0xA7,0xBD,0x2D,
+    0x35,0xE6,0xD3,0xDD,0x72,0xFE,0x5C,0x5C,0xF4,0xDD,0xD3,0xDD,0xFB,0x3D,0xAD,0xF2,
+    0xF4,0xE5,0xD3,0xDD,0x60,0xFA,0x77,0x55,0xB3,0xDD,0x11,0xC5,0x78,0xE0,0x60,0x70,
+    0xD0,0xBC,0x2D,0xA4,0xDE,0xDC,0x5C,0x5C,0x51,0xCD,0x6E,0xAC,0x29,0x2D,0x05,0xBD,
+    0x31,0xCD,0xD0,0xBC,0xB8,0xF8,0xE8,0x5A,0x31,0xC5,0xAF,0xB4,0x0A,0xAF,0x9F,0xDF,
+    0x51,0xCD,0x10,0xC5,0xFE,0xBB,0x77,0xF9,0x72,0xD5,0x31,0xC5,0x37,0x39,0xAE,0xBF,
+    0x92,0xD5,0x51,0xCD,0xAB,0xFA,0x6A,0x7E,0xD3,0xDD,0xF0,0xC4,0x02,0xEA,0xFF,0x5F,
+    0x72,0xD5,0xF0,0xBC,0xFC,0xD6,0x55,0xD5,0x72,0xCD,0x10,0xC5,0xBF,0xBF,0xA9,0x2A,
+    0xC8,0x7A,0x87,0x7A,0x00,0x88,0x40,0x03,0xE8,0x82,0xA7,0x7A,0xBF,0xB2,0xA9,0x8B,
+    0xE8,0x82,0xA8,0x7A,0x78,0xAC,0xEB,0xBF,0xE8,0x82,0xA7,0x7A,0x24,0x08,0xEF,0xAD,
+    0xE8,0x82,0xC7,0x7A,0x3B,0x6B,0x9E,0x2B,0x09,0x8B,0xC7,0x82,0xA7,0x9E,0xDB,0x5F,
+    0x08,0x8B,0xA7,0x7A,0xFE,0xEF,0xE4,0xB7,0xE8,0x82,0xA7,0x82,0xB8,0x80,0x8A,0xFC,
+    0xE8,0x82,0xA7,0x82,0xEB,0x28,0x0A,0x32,0x08,0x8B,0xC7,0x82,0xDF,0xFF,0xA9,0xBF,
+    0x08,0x8B,0xA7,0x7A,0xBF,0xBE,0x36,0xFC,0x08,0x8B,0xC7,0x82,0x29,0xE8,0xEA,0xA3,
+    0x08,0x8B,0xC7,0x82,0xA0,0x7A,0xAB,0xEB,0x49,0x93,0xA7,0x7A,0x0E,0xAF,0xFE,0xFB,
+    0xF0,0xC4,0x09,0x8B,0x2B,0xD5,0x55,0x55,0x34,0xE6,0x29,0x8B,0x02,0xAF,0xD5,0x55,
+    0x96,0xF6,0x8A,0x93,0x00,0x0A,0xAF,0x55,0x96,0xF6,0x8E,0xB4,0x00,0x00,0x0A,0xB5,
+    0xB6,0xF6,0x14,0xE6,0x00,0x00,0x08,0xAD,0xD6,0xF6,0x95,0xF6,0x23,0x22,0x23,0xA5,
+    0xD7,0xF6,0xB6,0xF6,0xFA,0xFE,0xD8,0x9E,0xB6,0xFE,0xD6,0xF6,0x57,0xFF,0xDF,0xFD,
+    0xF7,0xFE,0xB6,0xF6,0xAA,0xAF,0xFA,0x7F,0xD7,0xF6,0xB6,0xF6,0xC0,0x80,0x0B,0xEB,
+    0xF6,0xFE,0xB7,0xF6,0xBB,0xAB,0xAB,0xEF,0xD6,0xF6,0xAE,0xB4,0x78,0x68,0xE0,0xA0,
+    0x8E,0xB4,0xA4,0x59,0x57,0x56,0x5E,0x58,0xA5,0x51,0x64,0x49,0x82,0x9F,0x9D,0xD7,
+    0xE5,0x59,0x84,0x51,0xED,0xF9,0xD7,0x57,0xE6,0x59,0x84,0x51,0x6F,0x7E,0x68,0x63,
+    0xA5,0x51,0x44,0x41,0x7A,0xF2,0x58,0x7E,0x44,0x41,0x03,0x41,0xDA,0xB8,0x3C,0xBC,
+    0x44,0x49,0x03,0x41,0x7D,0x6E,0xE8,0x8F,0xC5,0x61,0x03,0x41,0xDD,0x95,0xBF,0x2A,
+    0x67,0x7A,0xC5,0x61,0xF5,0x35,0x29,0x0A,0xC8,0x8A,0x26,0x72,0xF5,0x8B,0xAA,0x28,
+    0xC9,0x8A,0x06,0x6A,0x5B,0x6A,0x78,0xB8,0x27,0x72,0x84,0x51,0x5E,0x7A,0x78,0xF0,
+    0x64,0x51,0x24,0x49,0xFA,0xF7,0xD4,0xAC,0x64,0x51,0xE2,0x38,0xFA,0x7C,0x7A,0xEC,
+    0xE3,0x38,0xA2,0x30,0xBE,0xDC,0x5F,0xFA,0x03,0x39,0xC2,0x30,0x8B,0xAB,0x89,0xA9,
+    0x03,0x39,0x82,0x28,0x6A,0xFA,0xE2,0xCA,0xA2,0x30,0x82,0x28,0xD5,0x55,0x57,0x5C,
+    0xE2,0x30,0x82,0x28,0xFF,0xF5,0xB5,0x3D,0x43,0x41,0xA1,0x30,0x29,0xAD,0xAF,0xAF,
+    0xA5,0x59,0x23,0x41,0xB5,0xAD,0x3D,0x0D,0xA9,0x82,0xA5,0x59,0x2D,0x2D,0xAB,0xAB,
+    0xC9,0x82,0x06,0x6A,0x00,0xA8,0xFE,0x7B,0xA8,0x7A,0xE4,0x61,0xF8,0xFA,0x7F,0x55,
+    0x67,0x7A,0xC4,0x61,0x0A,0xBF,0xF5,0xFF,0x88,0x7A,0xE5,0x69,0x00,0x02,0x0B,0xBD,
+    0xC9,0x82,0x46,0x72,0x82,0x2A,0xAF,0x97,0xE9,0x82,0x84,0x51,0x80,0xAA,0xFA,0x7E,
+    0x06,0x6A,0x02,0x49,0xA8,0xE8,0xFF,0x57,0xE6,0x61,0x43,0x51,0xAA,0xFD,0xBD,0x35,
+    0x47,0x72,0xA4,0x59,0x0D,0x2D,0x2F,0x0A,0xA8,0x82,0x46,0x72,0x03,0xB5,0xED,0xAD,
+    0xC9,0x8A,0xA8,0x7A,0xEB,0xEF,0xA9,0x87,0xC9,0x82,0x67,0x7A,0xB7,0xFC,0xFE,0x5E,
+    0xA8,0x82,0x46,0x72,0x02,0xAA,0x2B,0x89,0x8B,0x9B,0x68,0x7A,0x2F,0x2D,0xAD,0xBD,
+    0xD6,0xF6,0x8A,0x93,0x0B,0x0F,0x2D,0x95,0x39,0xFF,0xB6,0xF6,0x00,0x20,0x82,0x89,
+    0x39,0xFF,0x18,0xFF,0x20,0x0A,0x8B,0x8B,0x38,0xFF,0x18,0xFF,0xDE,0x9E,0xBE,0xBE,
+    0x38,0xFF,0xF7,0xF6,0xA0,0xEA,0x6A,0x7A,0xB6,0xF6,0x55,0xE6,0xF0,0xF8,0x78,0xFA,
+    0x55,0xEE,0x75,0xE6,0x0A,0x02,0xA0,0xA0,0x55,0xEE,0x35,0xE6,0xD7,0xDE,0xAC,0xB8,
+    0xF8,0xFE,0x76,0xEE,0x2D,0x2D,0x29,0x0F,0x18,0xFF,0xD7,0xF6,0xFA,0xFA,0xFA,0xE8,
+    0x38,0xFF,0xF8,0xF6,0xB7,0xB5,0xB5,0xAD,0x18,0xFF,0x38,0xF7,0x20,0x0A,0x2A,0x2A,
+    0x18,0xFF,0xF8,0xF6,0x28,0xA8,0xF8,0xBA,0x18,0xFF,0xF8,0xF6,0xEA,0xBA,0xAE,0xAB,
+    0xF8,0xFE,0x18,0xF7,0xAA,0xBA,0xEB,0xBB,0xF8,0xFE,0x18,0xF7,0x82,0xAA,0xA8,0xAC,
+    0x18,0xFF,0xF8,0xF6,0x7F,0x5F,0xDA,0x5F,0xD8,0xFE,0xF7,0xF6,0xF7,0xF7,0x7D,0xDF,
+    0xD7,0xFE,0xF8,0xF6,0xF7,0xFF,0xDD,0x75,0xD8,0xFE,0xF7,0xF6,0xFD,0xFD,0x77,0x55,
+    0x18,0xFF,0xD7,0xF6,0xAF,0xBB,0xFF,0xDF,0xD8,0xFE,0xF7,0xF6,0xBD,0xF5,0x77,0x5F,
+    0x18,0xFF,0xD7,0xF6,0xDD,0x5D,0x7F,0xFA,0xF7,0xF6,0xD7,0xF6,0x2B,0x25,0xB7,0x37,
+    0xF8,0xFE,0xF7,0xF6,0xFF,0xFF,0xFB,0xBF,0x18,0xFF,0xF8,0xF6,0x6D,0xDF,0xF5,0xFF,
+    0x18,0xFF,0xF8,0xF6,0xAD,0x0B,0x8F,0xAF,0x18,0xFF,0xF8,0xF6,0x60,0x7A,0xEE,0xEB,
+    0xD8,0xFE,0xF7,0xF6,0x5D,0x75,0xF5,0xFF,0x18,0xFF,0xD7,0xF6,0xA2,0xAA,0xF7,0xB7,
+    0xF7,0xF6,0xD8,0xF6,0xA0,0xA0,0xE2,0xEA,0xF8,0xF6,0xD7,0xF6,0x82,0x7B,0x5F,0x57,
+    0xF8,0xF6,0xB7,0xF6,0x7A,0xFA,0x77,0x5F,0xB7,0xF6,0x76,0xEE,0xF8,0xB8,0xEC,0xFE,
+    0x96,0xEE,0x76,0xEE,0xD9,0xD7,0x5F,0xD5,0x96,0xEE,0x76,0xEE,0x68,0x7A,0x57,0x55,
+    0x75,0xEE,0x35,0xE6,0xE2,0xBC,0xAE,0xAE,0x75,0xEE,0x35,0xE6,0xAA,0xBB,0xB6,0xFF,
+    0x75,0xEE,0x55,0xE6,0x8A,0xAA,0xFF,0x56,0x76,0xEE,0x35,0xE6,0x2A,0xEE,0x9F,0xD7,
+    0x76,0xEE,0x55,0xE6,0x95,0xBD,0x0D,0xA3,0xB7,0xF6,0x76,0xEE,0xA5,0x2B,0xA9,0xAB,
+    0xB7,0xF6,0x76,0xEE,0xFA,0xF8,0xEA,0x5E,0xB6,0xF6,0x55,0xEE,0xFD,0xAF,0x2B,0x2A,
+    0xB6,0xF6,0x96,0xEE,0xFD,0xFE,0x8A,0xA6,0xB6,0xF6,0x14,0xDE,0xE2,0xE0,0xEA,0x7A,
+    0xF4,0xDD,0x31,0xCD,0xF8,0xF8,0x78,0x5E,0xB3,0xDD,0x31,0xCD,0x2B,0x2B,0xAF,0xF5,
+    0x15,0xE6,0x92,0xD5,0x2F,0xAB,0xAD,0xBD,0x35,0xE6,0xD3,0xDD,0x82,0x8A,0xEE,0x7E,
+    0x14,0xE6,0xB3,0xD5,0x70,0xD8,0xEA,0xEA,0x14,0xE6,0xB3,0xD5,0x2F,0x2D,0x2F,0x0F,
+    0x14,0xE6,0xD3,0xDD,0xF8,0x7C,0xDA,0xDA,0xF4,0xDD,0x92,0xD5,0x80,0x80,0xC2,0x68,
+    0xD3,0xDD,0x31,0xC5,0x00,0x80,0xAA,0x55,0x92,0xD5,0xD0,0xBC,0x60,0xF0,0xFE,0xFF,
+    0xEF,0xBC,0x0D,0xA4,0x5A,0x7E,0xFC,0xF8,0xF0,0xC4,0x4D,0xAC,0x2D,0x2D,0x25,0x35,
+    0x31,0xCD,0xB0,0xB4,0xFA,0xF0,0xF8,0x7A,0xCF,0xBC,0x8F,0xB4,0x36,0x0E,0x2F,0x17,
+    0x31,0xC5,0xF0,0xC4,0x23,0x89,0x09,0x05,0x72,0xCD,0x31,0xCD,0xAD,0x29,0x3D,0x3B,
+    0x71,0xCD,0x31,0xCD,0xAA,0xE8,0xFA,0x56,0x51,0xCD,0xF0,0xBC,0x58,0x56,0xDD,0xF7,
+    0x52,0xCD,0xD0,0xBC,0x35,0x2F,0xBA,0xAA,0x92,0xD5,0x31,0xC5,0xBF,0xAF,0x8B,0xAD,
+    0xE8,0x82,0x86,0x7A,0x89,0x8A,0xE8,0xA2,0x08,0x83,0x87,0x7A,0xC3,0x6E,0x6B,0xEA,
+    0xE8,0x82,0x87,0x7A,0x6E,0xCF,0xEF,0xFE,0xE8,0x82,0x86,0x7A,0x2D,0xBD,0xAB,0xBA,
+    0xE8,0x82,0x87,0x7A,0x02,0x90,0x00,0x8B,0xE7,0x82,0xA7,0x7A,0xBF,0xBC,0xFE,0xFA,
+    0xC8,0x82,0xA8,0x7A,0x0E,0x40,0xD2,0x05,0xE8,0x82,0xA7,0x7A,0xD5,0xAB,0x2A,0x28,
+    0xE8,0x82,0xA6,0x82,0x0F,0xC0,0xE0,0xF0,0x08,0x8B,0xA7,0x7A,0x28,0x5E,0xFA,0xBA,
+    0x09,0x8B,0xC7,0x82,0x5E,0xCB,0x79,0x5A,0x08,0x8B,0xA7,0x7A,0xAB,0x3F,0xFE,0xBD,
+    0x08,0x83,0xA7,0x82,0x2A,0xBE,0xFE,0x9F,0xE8,0x82,0xC8,0x82,0x20,0x22,0x6B,0xDF,
+    0x08,0x8B,0xC8,0x82,0x8B,0xB5,0xA9,0x2D,0x08,0x8B,0xC8,0x82,0x28,0x2A,0x3A,0x5F,
+    0x49,0x8B,0xC8,0x82,0xA8,0xFF,0xDA,0xDF,0x0C,0x9C,0xC7,0x82,0x2B,0xFF,0xF5,0x5D,
+    0xD3,0xDD,0x29,0x8B,0x0A,0xF5,0x55,0x55,0x75,0xEE,0x29,0x8B,0x00,0x0B,0xFD,0x55,
+    0xB6,0xF6,0xCB,0xA3,0x00,0x00,0xAB,0xF5,0xD6,0xF6,0x92,0xD5,0x00,0x08,0x8A,0xBD,
+    0xD6,0xF6,0x75,0xF6,0x08,0x8A,0xAB,0xBD,0xD7,0xFE,0x96,0xF6,0xAA,0xAE,0x9E,0xFB,
+    0xD7,0xFE,0xB6,0xF6,0xEA,0xFF,0xEB,0xEB,0xB7,0xF6,0x34,0xE6,0x60,0xC0,0xA0,0x80,
+    0x55,0xEE,0x87,0x72,0x5E,0x78,0x78,0xE0,0x66,0x6A,0x43,0x49,0xF7,0xD5,0x56,0x5C,
+    0xA5,0x59,0x43,0x49,0xA0,0x80,0xEA,0xD5,0xC5,0x51,0x64,0x49,0x8A,0xAA,0xFE,0x75,
+    0x85,0x51,0x64,0x49,0x7A,0x68,0xD5,0xEF,0x84,0x51,0x23,0x41,0x77,0x7F,0xFE,0x8E,
+    0xC5,0x59,0x23,0x41,0xFD,0x2F,0xAB,0x2A,0xA8,0x82,0x84,0x51,0xF5,0xBD,0xAF,0x2B,
+    0x09,0x93,0x46,0x72,0xBD,0x2D,0x0B,0x0A,0x09,0x93,0xA8,0x8A,0xD7,0x6E,0xE2,0xE0,
+    0xC9,0x8A,0x26,0x72,0xF8,0xFE,0x58,0xD8,0x47,0x7A,0xA4,0x61,0x5C,0x7A,0x7C,0xB0,
+    0xC5,0x69,0x44,0x49,0xDF,0x7F,0xBA,0xA0,0xA5,0x59,0x44,0x49,0x55,0xFF,0xBF,0x2A,
+    0xE6,0x69,0xE2,0x40,0x5F,0xFE,0xAA,0x2A,0xC5,0x59,0x03,0x41,0x55,0x55,0x5E,0xE8,
+    0x03,0x41,0xC2,0x30,0xE8,0x7A,0xFF,0x2E,0x44,0x41,0xA2,0x30,0x55,0xF7,0xAA,0x0A,
+    0x85,0x51,0x81,0x30,0xFD,0xBF,0x2F,0x0A,0x64,0x49,0x03,0x41,0xBD,0x2E,0xAA,0x02,
+    0xC5,0x61,0x44,0x49,0x37,0xAF,0x2A,0xAB,0x27,0x6A,0x84,0x51,0x82,0xEB,0xFF,0x57,
+    0x06,0x6A,0xA4,0x59,0x80,0xEF,0xB5,0xB5,0xE5,0x61,0xA4,0x61,0xDE,0x7B,0xEA,0xA8,
+    0xE5,0x61,0xA4,0x61,0x2E,0x39,0x29,0x09,0x26,0x6A,0xC5,0x61,0x97,0x9F,0x2B,0x2F,
+    0x87,0x7A,0x06,0x62,0xAB,0x7B,0x83,0x8A,0x67,0x72,0x23,0x49,0x78,0x78,0x5E,0x5E,
+    0x63,0x51,0xE2,0x40,0xF7,0xF7,0xBD,0x27,0x26,0x6A,0x02,0x49,0x2D,0x2F,0x2B,0x0B,
+    0x67,0x72,0x26,0x72,0xFF,0x52,0xFA,0xDE,0x88,0x7A,0xE5,0x69,0xA0,0x8B,0xF7,0xFF,
+    0xC9,0x8A,0x05,0x6A,0x0A,0x2B,0x3D,0x25,0x4A,0x9B,0x46,0x72,0x57,0x5E,0xFA,0xE2,
+    0x88,0x7A,0x05,0x6A,0x0F,0xB5,0xFD,0xBA,0x2A,0x8B,0x67,0x7A,0x2D,0x39,0xBD,0x3D,
+    0x8E,0xBC,0x2A,0x8B,0x3D,0xBD,0xD5,0x55,0x18,0xFF,0x6E,0xB4,0x02,0x0B,0x09,0x2D,
+    0x38,0xFF,0x18,0xFF,0xED,0xED,0x7D,0xD5,0x38,0xFF,0x18,0xFF,0x5F,0xDF,0x55,0x55,
+    0x18,0xFF,0x96,0xF6,0xE0,0xE0,0x68,0x78,0x96,0xF6,0x55,0xEE,0x5C,0xDE,0x77,0xD7,
+    0x75,0xEE,0x55,0xEE,0xF5,0xFD,0x7B,0x7D,0x75,0xEE,0x35,0xE6,0xB7,0x97,0x97,0x2F,
+    0xF8,0xFE,0x96,0xEE,0x2D,0x2D,0x0D,0x2D,0xF8,0xFE,0x18,0xF7,0xB8,0xAA,0x2E,0xAE,
+    0x18,0xFF,0xF8,0xF6,0x29,0x0E,0x0D,0xAF,0x18,0xFF,0x38,0xF7,0x28,0x28,0x80,0x02,
+    0x18,0xFF,0xF8,0xF6,0xAA,0xEE,0xBA,0xBE,0x18,0xFF,0xF8,0xF6,0xAA,0xAA,0xE8,0xDE,
+    0x18,0xFF,0xF8,0xF6,0x7A,0x7E,0xDF,0xEF,0xF7,0xFE,0xF8,0xF6,0xBF,0xFF,0x7F,0xFF,
+    0xD7,0xFE,0xF8,0xF6,0xF5,0xF7,0xD7,0x77,0x18,0xFF,0xD7,0xF6,0xBF,0xAB,0xEB,0xAB,
+    0xD7,0xFE,0xF8,0xF6,0x75,0xFD,0xE5,0xE7,0xD7,0xFE,0xF7,0xF6,0x57,0xDD,0xF7,0xFD,
+    0xF7,0xF6,0xB7,0xF6,0x2E,0x28,0x2A,0xA8,0x18,0xFF,0xD7,0xF6,0xAE,0xEB,0xFB,0xEF,
+    0xD7,0xFE,0xF7,0xF6,0x75,0xFD,0xFF,0xFD,0xF7,0xF6,0xD7,0xF6,0x7E,0x3E,0x8A,0x0A,
+    0x18,0xFF,0xF7,0xF6,0x55,0x75,0x7F,0xFF,0x18,0xFF,0xF8,0xF6,0xEF,0x2F,0xB5,0xB7,
+    0x18,0xFF,0xF8,0xF6,0x6B,0x78,0xFA,0xFE,0x17,0xFF,0xF8,0xF6,0x6B,0xFF,0xFD,0x77,
+    0xF8,0xF6,0xD7,0xF6,0xA8,0xBA,0xA8,0xCE,0xF8,0xF6,0xD7,0xF6,0x8A,0xA8,0xAA,0xBE,
+    0xF8,0xF6,0xD7,0xF6,0xC8,0xA2,0x6A,0x7A,0x18,0xF7,0xB7,0xF6,0x7F,0x7F,0xDE,0x7F,
+    0xD7,0xF6,0x96,0xEE,0x7A,0x5F,0x5F,0x7E,0x96,0xEE,0x76,0xEE,0xDA,0x58,0x7F,0xF9,
+    0x96,0xEE,0x55,0xEE,0xFE,0xEA,0xAE,0xEA,0x76,0xEE,0x55,0xE6,0x20,0x80,0x20,0xE8,
+    0x75,0xEE,0x34,0xE6,0xF8,0xFA,0xAA,0xEA,0x75,0xEE,0x35,0xE6,0xBF,0xFE,0xFE,0xEA,
+    0x75,0xEE,0x34,0xE6,0xFE,0xA8,0x02,0x2A,0x75,0xEE,0x34,0xE6,0x9F,0xBA,0xA2,0x80,
+    0x76,0xEE,0x55,0xE6,0xAF,0x0C,0xB7,0x25,0x96,0xEE,0x76,0xEE,0x22,0x26,0x2E,0xBB,
+    0x96,0xEE,0x55,0xE6,0xF8,0xEA,0xEA,0xAA,0x96,0xEE,0x55,0xEE,0x0A,0x02,0x29,0x2F,
+    0xB6,0xF6,0x96,0xEE,0xFB,0x7F,0x7D,0x55,0x96,0xEE,0x14,0xDE,0x60,0x70,0xE0,0xE0,
+    0xD3,0xDD,0x30,0xC5,0x76,0xFC,0xE8,0xF0,0x71,0xCD,0x30,0xCD,0x09,0xE2,0xAA,0xDC,
+    0xF3,0xDD,0x51,0xCD,0x2F,0xA9,0x2D,0xB9,0xF4,0xDD,0xB3,0xD5,0x80,0xE0,0x80,0x02,
+    0xF4,0xDD,0x92,0xD5,0x83,0xAA,0xFA,0x60,0x14,0xE6,0xB3,0xD5,0x2D,0x0F,0xA9,0xB5,
+    0x14,0xE6,0x10,0xC5,0x20,0xA0,0xFA,0x5E,0xB3,0xD5,0xF0,0xC4,0x80,0x78,0x57,0x77,
+    0x30,0xC5,0xF0,0xBC,0x58,0xFF,0x55,0x55,0x30,0xC5,0xD0,0xBC,0xFE,0x36,0x9F,0xDF,
+    0x31,0xCD,0x2D,0xAC,0x7A,0x78,0xE0,0x80,0xCF,0xBC,0xEC,0xA3,0x2B,0x2D,0x3F,0x2F,
+    0x31,0xCD,0xB0,0xBC,0xFA,0x40,0xA2,0xCB,0xCF,0xBC,0x4E,0xAC,0x3E,0x37,0x97,0xBF,
+    0x51,0xCD,0xF0,0xC4,0xA5,0x29,0x89,0x29,0x51,0xCD,0x11,0xC5,0x0A,0x22,0xA9,0xCE,
+    0x52,0xCD,0xD0,0xBC,0xE8,0xE8,0x7C,0xDF,0x52,0xCD,0xCF,0xBC,0xF7,0x9F,0xAD,0x8B,
+    0x72,0xCD,0x11,0xC5,0xB7,0xBD,0x9F,0x3F,0x72,0xCD,0x51,0xCD,0x29,0x3D,0xB5,0xBD,
+    0xC8,0x82,0x25,0x6A,0x20,0xAA,0xAF,0xD7,0xE8,0x82,0x66,0x72,0xA2,0x83,0x8A,0xFD,
+    0xC7,0x82,0x87,0x7A,0xB8,0x2A,0x2A,0x2E,0x07,0x83,0xC8,0x82,0x5F,0x7B,0xFF,0x7E,
+    0xE8,0x82,0xA7,0x7A,0xAB,0x8B,0x89,0x23,0x08,0x8B,0xA7,0x7A,0xF7,0xB7,0xBF,0xBA,
+    0x09,0x8B,0xA7,0x7A,0x8F,0xC6,0xDE,0x5F,0xE8,0x82,0xA7,0x82,0xFB,0x75,0xAB,0xA3,
+    0xE8,0x82,0x87,0x7A,0xE0,0x2A,0x0A,0x28,0x08,0x8B,0xA7,0x7A,0xEF,0xBF,0xFA,0x5C,
+    0xE8,0x82,0x86,0x7A,0x20,0xA8,0x80,0xC1,0xE8,0x82,0xA7,0x7A,0xDE,0xAA,0x3A,0xE8,
+    0x09,0x8B,0xA8,0x7A,0x7F,0xCF,0xAB,0xAF,0x08,0x8B,0xC8,0x82,0xBF,0xB3,0xE3,0x6A,
+    0x08,0x8B,0xA7,0x82,0xAF,0xE2,0xAA,0xDA,0x09,0x8B,0xC8,0x82,0xD5,0xD7,0x2B,0xC5,
+    0xC8,0x8A,0xE8,0x82,0xFD,0x59,0x5F,0xF7,0x08,0x8B,0xC8,0x82,0xBB,0xAA,0xFA,0x7A,
+    0xE8,0x82,0xC8,0x82,0xD8,0xB8,0xAA,0x7B,0x09,0x8B,0xC8,0x82,0x22,0x83,0x0A,0xF9,
+    0x8A,0x93,0xE8,0x82,0x2F,0xFD,0x5D,0x55,0x10,0xCD,0x09,0x8B,0x2B,0xF5,0x55,0x55,
+    0x54,0xEE,0x09,0x8B,0x02,0xAF,0xD5,0x55,0x95,0xF6,0x4A,0x93,0x00,0x02,0xAF,0xD5,
+    0xB6,0xF6,0xAE,0xBC,0x00,0x00,0x0A,0xBD,0xB7,0xF6,0x14,0xE6,0x00,0x00,0x00,0x8D,
+    0x96,0xF6,0xF0,0xBC,0x70,0xE0,0xC0,0x80,0xD0,0xBC,0x44,0x49,0x5E,0x5E,0x58,0x78,
+    0x43,0x49,0x03,0x41,0xA2,0xB8,0xEE,0xFF,0x63,0x49,0x03,0x49,0x0A,0xBA,0xEB,0x09,
+    0xA5,0x51,0x43,0x49,0xCA,0xAE,0xBD,0xEB,0xA5,0x59,0x64,0x51,0x55,0x6D,0xB7,0x35,
+    0x26,0x6A,0x84,0x51,0xA5,0xAF,0x29,0x0F,0x09,0x8B,0x26,0x72,0x3D,0x2D,0x29,0x2F,
+    0x4A,0x9B,0xE8,0x8A,0xA9,0x02,0x0A,0xA3,0x2A,0x9B,0xA8,0x8A,0x78,0x78,0x60,0xF2,
+    0xA8,0x8A,0x47,0x7A,0xD4,0xFA,0x7A,0xF8,0x67,0x82,0xE5,0x69,0xFA,0xF2,0x7E,0x7F,
+    0x06,0x72,0xA5,0x61,0x56,0xA8,0xCA,0x0A,0x27,0x72,0xA5,0x61,0x95,0x2A,0x0A,0x22,
+    0x67,0x7A,0xC5,0x61,0x57,0xFF,0xBE,0x2E,0x27,0x6A,0xA5,0x59,0x76,0x7E,0x78,0x60,
+    0xA5,0x59,0x03,0x41,0xDE,0xA8,0x20,0xF8,0xA5,0x51,0x03,0x41,0xF7,0xA8,0xB8,0x5F,
+    0xA6,0x51,0x24,0x49,0x2F,0xAA,0xAE,0xFD,0xA5,0x51,0x23,0x49,0xAE,0xAC,0xEE,0x7F,
+    0x84,0x51,0x23,0x49,0x20,0xA2,0xEB,0xFD,0xA5,0x59,0x43,0x49,0x3F,0xFF,0xFF,0xAD,
+    0x06,0x62,0x84,0x59,0x2F,0xAD,0x2F,0x8B,0x67,0x72,0xC5,0x61,0x7D,0x7B,0xC2,0x22,
+    0x26,0x6A,0xA4,0x59,0xED,0xF7,0x76,0x68,0x67,0x72,0xC5,0x61,0xAB,0xAB,0x2D,0x29,
+    0x67,0x72,0xA4,0x59,0x80,0xA0,0x70,0x7C,0xC4,0x59,0xE2,0x38,0xF8,0x5C,0x5E,0x57,
+    0xC5,0x61,0xE2,0x38,0xBF,0x35,0x3D,0x2D,0x67,0x7A,0xC5,0x61,0x2D,0x0F,0x8B,0xAB,
+    0x88,0x7A,0x26,0x72,0xBE,0x8E,0xEB,0x5E,0x67,0x7A,0xE6,0x69,0xB8,0xE8,0xFA,0xDF,
+    0xC8,0x8A,0x06,0x72,0x2D,0x25,0x2F,0x2B,0x2A,0x93,0xC8,0x8A,0x4B,0xFB,0x7D,0xC3,
+    0xE9,0x8A,0x67,0x7A,0x56,0xF8,0xBC,0xA8,0xE9,0x8A,0x88,0x82,0x29,0xB7,0xD7,0x5F,
+    0x0A,0x8B,0xA8,0x82,0x3A,0x3F,0x35,0x55,0x76,0xF6,0x8B,0x9B,0x2D,0x2D,0xF5,0xD5,
+    0xF8,0xFE,0x31,0xD5,0x00,0x00,0x02,0x09,0x18,0xFF,0xF8,0xFE,0x7A,0x57,0x7D,0x55,
+    0xF8,0xFE,0x75,0xE6,0xE0,0xF0,0xF0,0x78,0x55,0xEE,0x75,0xE6,0x8A,0xEB,0xAA,0x20,
+    0x75,0xEE,0x55,0xEE,0xD9,0xFF,0xFF,0xE5,0x96,0xEE,0x35,0xE6,0x97,0x2F,0xBB,0x2F,
+    0xF8,0xFE,0x96,0xF6,0x2D,0x2F,0x09,0x0B,0x18,0xFF,0xF8,0xF6,0xDB,0x7B,0x7B,0x7A,
+    0x18,0xFF,0xF8,0xF6,0x2F,0xA9,0x2B,0x0D,0x18,0xFF,0xF8,0xF6,0x00,0x08,0xA0,0xE0,
+    0x18,0xFF,0xF8,0xF6,0xBA,0xAA,0xFA,0xEE,0x18,0xFF,0xF8,0xF6,0xFF,0x7E,0x5E,0x7F,
+    0x18,0xFF,0xF8,0xF6,0xFF,0xDD,0xEF,0xED,0xF7,0xFE,0xF8,0xF6,0xFF,0x7E,0xFF,0xFF,
+    0xD8,0xFE,0xF7,0xF6,0x57,0x5F,0xD7,0x7F,0x18,0xFF,0xF8,0xF6,0x6F,0x55,0x75,0xD5,
+    0xF8,0xF6,0xD7,0xF6,0xBA,0xFC,0xDC,0xBA,0xF7,0xF6,0xD7,0xF6,0xAA,0x2A,0x0B,0xAA,
+    0x18,0xFF,0xF7,0xF6,0x57,0x5D,0xBF,0xBB,0x17,0xFF,0xF8,0xF6,0x55,0xDD,0xFF,0xFD,
+    0x18,0xFF,0xF8,0xF6,0xFF,0xFD,0xFF,0x77,0x18,0xFF,0xF8,0xF6,0xFF,0x7A,0xBD,0xFF,
+    0xF8,0xFE,0xF7,0xF6,0xDB,0xFF,0xFF,0xAE,0x18,0xFF,0xF8,0xF6,0xBB,0xFA,0xFA,0xFF,
+    0x18,0xFF,0xF8,0xF6,0x7F,0x7D,0x7F,0x9B,0xD7,0xFE,0xF8,0xF6,0xDD,0xFD,0xF5,0xD5,
+    0xF8,0xF6,0xD7,0xF6,0x8E,0x9C,0xFE,0x2A,0xF8,0xF6,0xD7,0xF6,0xAA,0xB2,0xF8,0xB2,
+    0xF7,0xF6,0x98,0xF6,0xA0,0xAA,0xE8,0xAA,0xD7,0xF6,0x96,0xEE,0xE0,0xAE,0x6A,0xFE,
+    0x96,0xF6,0x76,0xEE,0x88,0xD8,0x54,0xB2,0x95,0xEE,0x56,0xE6,0xCA,0xFB,0xFF,0xFE,
+    0x76,0xEE,0x55,0xEE,0x00,0xA7,0xD7,0xA5,0x76,0xF6,0x55,0xE6,0xFF,0xFF,0x7C,0x78,
+    0x76,0xEE,0x35,0xE6,0xBA,0xEA,0xB2,0xFA,0x36,0xEE,0x55,0xE6,0x55,0xDF,0xD7,0xBA,
+    0x75,0xEE,0x35,0xE6,0xF6,0xFF,0x3F,0xB5,0x76,0xEE,0x55,0xE6,0xF3,0x23,0xB3,0xFF,
+    0x96,0xEE,0x55,0xE6,0xAD,0xBB,0xAF,0x2F,0x96,0xEE,0x76,0xEE,0x78,0xFE,0x7F,0x6B,
+    0x96,0xEE,0x76,0xEE,0x65,0x7D,0x5F,0x7D,0x95,0xEE,0x76,0xEE,0x55,0x55,0x7B,0x99,
+    0x96,0xEE,0x76,0xEE,0xB5,0x55,0x75,0x7A,0x96,0xEE,0x34,0xE6,0xE2,0x68,0xFE,0x7E,
+    0x14,0xE6,0x71,0xCD,0x5E,0xFA,0xF8,0xE8,0xF4,0xDD,0x51,0xCD,0x57,0x7F,0xAA,0x2A,
+    0xD3,0xDD,0x51,0xCD,0x2D,0x2E,0x2A,0x8A,0x14,0xDE,0xB3,0xD5,0x8A,0xAB,0xEF,0xAF,
+    0x14,0xE6,0x92,0xD5,0x78,0x7A,0xEA,0x6A,0xD3,0xDD,0x92,0xD5,0x01,0x81,0xA3,0x42,
+    0x72,0xD5,0xCF,0xBC,0xF8,0x68,0xFC,0x5E,0x10,0xC5,0xCF,0xBC,0xB8,0xF3,0x72,0x56,
+    0xF0,0xC4,0xCF,0xBC,0x81,0x8D,0x75,0xE6,0x10,0xC5,0xAF,0xBC,0x3B,0xAE,0x9B,0x9E,
+    0x91,0xD5,0xF0,0xC4,0xEB,0xEF,0xAD,0x2B,0x51,0xCD,0x6E,0xB4,0xD7,0x5E,0x5E,0x78,
+    0x31,0xCD,0xAF,0xBC,0xE3,0xCB,0x8B,0xAD,0xAF,0xBC,0x2D,0xAC,0x36,0x9E,0xBC,0x54,
+    0x51,0xCD,0xAF,0xBC,0x29,0x2B,0x0F,0x2D,0x71,0xCD,0x31,0xC5,0xAA,0xEA,0xFF,0x7D,
+    0x31,0xCD,0xCF,0xBC,0xDA,0xFE,0x2E,0x2A,0x72,0xCD,0xF0,0xC4,0xAD,0x2F,0xAA,0x2A,
+    0x72,0xCD,0x51,0xCD,0x5D,0x5E,0x16,0x7C,0x71,0xCD,0x51,0xCD,0x1D,0xF7,0xE4,0xEA,
+    0x87,0x7A,0x25,0x6A,0x7E,0xEE,0xEE,0xAA,0xA7,0x7A,0x25,0x6A,0xBD,0xFD,0xFD,0x2E,
+    0xC7,0x7A,0x45,0x6A,0x2E,0xD7,0xF5,0xDF,0xC7,0x7A,0x25,0x6A,0x02,0x2B,0xF7,0xF5,
+    0xE8,0x82,0x45,0x72,0x2A,0x0B,0xAF,0xFD,0xE8,0x82,0x86,0x7A,0xAA,0xB0,0x2A,0xBD,
+    0xE8,0x82,0xA7,0x7A,0xFA,0x60,0xC8,0xFD,0xE8,0x82,0x87,0x7A,0xA3,0x89,0xCA,0x82,
+    0xE8,0x82,0x87,0x7A,0x08,0x20,0xAA,0x62,0xE8,0x82,0x86,0x7A,0x70,0xF0,0xBA,0xEB,
+    0xE8,0x82,0xA7,0x7A,0x49,0xF9,0xF9,0xEB,0xE8,0x8A,0xA7,0x7A,0x92,0x2A,0xBE,0xAF,
+    0xE8,0x82,0xA7,0x7A,0x2B,0xAF,0x56,0xA6,0xE8,0x82,0xC7,0x82,0x07,0xA1,0x05,0xAD,
+    0xC8,0x8A,0xE8,0x82,0xB5,0xF5,0x95,0xEC,0x08,0x8B,0xC8,0x82,0xEB,0xEA,0xE9,0xDF,
+    0x09,0x8B,0xC8,0x82,0x7B,0xFB,0xFD,0x2E,0x09,0x8B,0xC8,0x82,0x7F,0xFB,0xA9,0x37,
+    0xE8,0x8A,0xC8,0x82,0xEB,0x45,0x86,0x04,0x08,0x8B,0xC8,0x82,0x35,0xA5,0xFE,0xBE,
+    0x09,0x8B,0xC8,0x82,0xEA,0xF2,0xFF,0xA7,0x09,0x8B,0xC8,0x82,0x3E,0x93,0xFB,0x7C,
+    0x29,0x8B,0xE8,0x82,0xA7,0x5D,0x69,0xA9,0x29,0x8B,0xE8,0x82,0x0F,0x8F,0x6F,0x7F,
+    0xEC,0xA3,0x09,0x8B,0x0F,0x75,0x55,0x55,0xB3,0xDD,0x09,0x8B,0x0A,0xBD,0x55,0x55,
+    0x55,0xEE,0x29,0x8B,0x00,0xAA,0xFD,0x55,0x32,0xCD,0x84,0x51,0x78,0x78,0x7A,0x7F,
+    0x43,0x49,0xE2,0x38,0xBF,0xD4,0xBE,0x0A,0x84,0x51,0x03,0x41,0xAD,0xFD,0xEF,0x6A,
+    0xA4,0x51,0x23,0x41,0x8B,0x8B,0xBE,0xF7,0xA5,0x59,0x43,0x49,0x2E,0x3E,0x2F,0x2D,
+    0x26,0x72,0xC5,0x61,0x3D,0xBD,0xBD,0xB5,0xC8,0x8A,0x26,0x72,0x0F,0x0B,0xAD,0xB5,
+    0x2A,0x9B,0xA7,0x82,0x02,0x2B,0xAD,0xAD,0x29,0x9B,0xC9,0x8A,0x6A,0xAA,0x20,0x0A,
+    0x0A,0x9B,0x47,0x7A,0x7E,0xFC,0xF8,0xF8,0x67,0x7A,0x06,0x72,0xDD,0xEF,0xEF,0x2C,
+    0x87,0x82,0xE6,0x69,0x5D,0x7E,0xFA,0xE2,0x47,0x7A,0xE5,0x69,0x1D,0xB5,0xD7,0xF7,
+    0x88,0x7A,0x26,0x72,0x2E,0xA3,0x0F,0xED,0x88,0x82,0x05,0x62,0x78,0xF8,0x7E,0x57,
+    0xE6,0x61,0x43,0x49,0x5E,0x70,0xC0,0x80,0x84,0x51,0xC2,0x38,0xDF,0x5E,0xFA,0xA0,
+    0x44,0x49,0x03,0x41,0xFD,0x75,0xA9,0xA8,0x64,0x49,0x03,0x41,0xE3,0xBF,0xE7,0x9B,
+    0x85,0x51,0x03,0x41,0x95,0xFF,0xAF,0x0A,0xA5,0x59,0x43,0x49,0x2D,0x2D,0x2E,0x2F,
+    0x26,0x6A,0xC5,0x59,0xB9,0xAD,0xAD,0xED,0x87,0x72,0x06,0x6A,0xBB,0xFF,0x9F,0x3B,
+    0xA8,0x7A,0x26,0x6A,0x7F,0xFB,0xAA,0x02,0x67,0x72,0x06,0x62,0x2B,0x2A,0x88,0x78,
+    0x67,0x72,0x63,0x51,0x78,0x58,0x5E,0x5F,0x43,0x49,0xC2,0x38,0xDA,0x5A,0xF8,0xF8,
+    0xE5,0x61,0x23,0x41,0x2D,0xAD,0xAD,0xB5,0x26,0x72,0xA5,0x59,0x02,0x2B,0xA7,0x75,
+    0x27,0x72,0xC5,0x61,0xE8,0xE8,0xFE,0xA9,0x27,0x72,0xA5,0x61,0x9F,0x95,0x1F,0x9E,
+    0xE9,0x8A,0x47,0x7A,0x2D,0xA9,0x2D,0x89,0x4A,0x93,0xA8,0x82,0x8A,0xFA,0x7B,0x5F,
+    0xC9,0x8A,0x47,0x7A,0x68,0xEA,0xAB,0xA5,0xA8,0x82,0x67,0x7A,0xAB,0x0B,0x2F,0xA2,
+    0x29,0x93,0x88,0x7A,0x7D,0xFF,0xFE,0xE2,0x4A,0x93,0x88,0x7A,0x0F,0x3D,0xD5,0xD5,
+    0xB6,0xF6,0x09,0x8B,0x0B,0x2F,0xAD,0xB5,0xD7,0xFE,0xD3,0xDD,0x00,0x00,0x02,0x09,
+    0xD7,0xFE,0x55,0xEE,0x68,0x78,0x58,0xDA,0x76,0xEE,0x55,0xEE,0xFF,0xBB,0xBB,0x69,
+    0x75,0xEE,0x15,0xEE,0x2A,0xA2,0xA8,0xE2,0x96,0xEE,0x55,0xEE,0x37,0x2D,0x05,0x2D,
+    0xF8,0xFE,0xB6,0xF6,0x29,0x2D,0x0D,0x2D,0x18,0xFF,0xF8,0xF6,0x7E,0xFF,0xFF,0xDB,
+    0x39,0xFF,0xF8,0xFE,0xBD,0xBD,0xEF,0x29,0x39,0xFF,0x18,0xFF,0x5F,0x6F,0x7F,0x5F,
+    0x18,0xFF,0xF8,0xF6,0xAA,0xA8,0xA2,0xAA,0x18,0xFF,0xF8,0xF6,0xFB,0xEB,0x92,0x5E,
+    0x18,0xFF,0xF8,0xF6,0xD7,0x77,0xDF,0xFF,0xD7,0xFE,0xF8,0xF6,0x77,0xDD,0xF5,0xF5,
+    0xF8,0xF6,0xD7,0xF6,0xAC,0xEA,0xE8,0xEA,0xF8,0xF6,0xD7,0xF6,0xA2,0x8A,0xAB,0xAE,
+    0xF7,0xF6,0xD7,0xF6,0xAA,0x0E,0xAA,0xAA,0x18,0xFF,0xD7,0xF6,0xBF,0xBB,0xBB,0xAA,
+    0xF7,0xFE,0x18,0xF7,0xAE,0xBE,0xBA,0xAA,0x18,0xFF,0xF7,0xF6,0xFF,0xF7,0xFF,0x7E,
+    0xD8,0xFE,0xF7,0xF6,0x55,0xF5,0xDD,0xFD,0xF7,0xFE,0xF8,0xF6,0xFF,0xFF,0xFF,0xEF,
+    0x19,0xFF,0xF7,0xF6,0xDF,0xFF,0xDD,0xFD,0x18,0xFF,0xF7,0xF6,0xFF,0x7D,0xED,0xFF,
+    0x18,0xFF,0xF8,0xF6,0xFA,0xFE,0x7F,0x7F,0xD7,0xFE,0xF8,0xF6,0x95,0xD5,0x55,0x75,
+    0xF7,0xF6,0xD8,0xF6,0x2A,0xA8,0xA8,0xAA,0xF7,0xF6,0xD7,0xF6,0xB8,0xDB,0xE7,0xF6,
+    0xF7,0xF6,0xB7,0xF6,0x7E,0x7E,0x5E,0x5F,0xB7,0xF6,0x76,0xEE,0xAA,0xEB,0xE2,0xFA,
+    0x96,0xEE,0x55,0xEE,0xA0,0xC8,0xE2,0xEB,0x76,0xEE,0x56,0xE6,0x88,0xAC,0xA0,0x00,
+    0x76,0xEE,0x56,0xEE,0x20,0x02,0xAA,0xA2,0x76,0xEE,0x15,0xE6,0xC8,0x2A,0xA2,0x82,
+    0x76,0xEE,0x35,0xE6,0xFA,0xEA,0xF2,0xFA,0x55,0xEE,0x14,0xDE,0xFA,0xE8,0xF8,0xFA,
+    0x55,0xE6,0x14,0xDE,0x0B,0x0B,0x2F,0x85,0x76,0xEE,0x55,0xE6,0xEF,0x2A,0x29,0xBD,
+    0x96,0xEE,0x76,0xEE,0xBD,0x7F,0xDD,0xF7,0x96,0xEE,0x76,0xEE,0x6D,0xA7,0x25,0x3F,
+    0x96,0xEE,0x76,0xEE,0x7D,0xF5,0xFB,0xF8,0x96,0xEE,0x76,0xEE,0xFB,0xBA,0xFF,0xFF,
+    0x96,0xF6,0x76,0xEE,0xEF,0xEB,0x8B,0xEB,0x96,0xEE,0x14,0xE6,0x6A,0x6A,0xE8,0x68,
+    0x14,0xE6,0xD4,0xDD,0xDA,0x08,0x0A,0x28,0x34,0xE6,0xF4,0xDD,0x5D,0x7F,0xFB,0xCA,
+    0x14,0xE6,0xD3,0xDD,0x55,0x57,0x7B,0xE2,0xF4,0xDD,0xB3,0xDD,0x8B,0x0A,0xAF,0xA8,
+    0x14,0xE6,0x92,0xD5,0x6A,0x7A,0xAA,0xA0,0xF4,0xDD,0xF0,0xC4,0xEA,0xEA,0x78,0x78,
+    0x10,0xC5,0x8E,0xB4,0xA8,0xBC,0xFA,0xDE,0xCF,0xBC,0xAF,0xBC,0x00,0xF2,0xFE,0xAC,
+    0xEF,0xBC,0x8E,0xB4,0xE3,0xF7,0x5F,0x74,0xD0,0xC4,0x4D,0xAC,0xA2,0xEA,0xFE,0xD7,
+    0x51,0xCD,0xCF,0xBC,0x09,0x05,0x8D,0xA5,0x51,0xCD,0x8E,0xB4,0x78,0xE0,0xA0,0x80,
+    0x31,0xCD,0xCF,0xBC,0x25,0xE5,0xF5,0xFF,0xF0,0xBC,0xEC,0xA3,0xDE,0xFC,0x5E,0xF8,
+    0x31,0xCD,0x8F,0xB4,0x09,0x0D,0x09,0x09,0x51,0xCD,0x10,0xC5,0x8B,0xFE,0xAC,0x7A,
+    0x72,0xCD,0xF0,0xC4,0xB7,0xA7,0x2D,0xAA,0x92,0xD5,0x31,0xC5,0xAD,0xEF,0xEC,0x2E,
+    0x93,0xD5,0x51,0xCD,0xD7,0x5F,0x5F,0xFA,0x71,0xCD,0x51,0xCD,0xF3,0xFB,0xF6,0x7E,
+    0x86,0x7A,0x46,0x72,0xA8,0xA6,0xEE,0xA8,0x86,0x7A,0x46,0x72,0x28,0xAB,0x2B,0xAA,
+    0xA7,0x7A,0x45,0x72,0xDF,0x5F,0xEA,0x62,0x86,0x7A,0x45,0x72,0x68,0x60,0x60,0x43,
+    0x86,0x72,0x25,0x72,0xFE,0x9F,0xAA,0xA0,0x87,0x7A,0x46,0x72,0x03,0xBB,0x7E,0x8F,
+    0xC8,0x82,0x25,0x6A,0x2B,0xAB,0xDF,0x57,0xA7,0x82,0x05,0x6A,0x00,0x00,0x0B,0xBD,
+    0xE8,0x82,0x87,0x7A,0xEE,0x2B,0xBB,0x75,0xE8,0x82,0xA7,0x7A,0xEF,0xAB,0xA9,0x29,
+    0xE8,0x82,0x87,0x7A,0xEB,0x7A,0x88,0x0E,0xE8,0x82,0xA8,0x82,0x03,0x82,0xAA,0x28,
+    0xE8,0x82,0x88,0x82,0x2A,0xA2,0x28,0xB8,0x09,0x8B,0xA7,0x7A,0xFF,0xDE,0xBE,0xE8,
+    0xE8,0x82,0xA7,0x7A,0xAB,0xE2,0xC3,0x89,0xE8,0x82,0xA8,0x82,0xA8,0x8A,0xAC,0xEB,
+    0xE8,0x82,0xC8,0x82,0x0A,0xFF,0x2B,0x2A,0x09,0x83,0xA7,0x7A,0x2E,0xBF,0x9E,0xFA,
+    0x09,0x8B,0xC8,0x82,0x3A,0x77,0xE3,0xF0,0x08,0x8B,0xC8,0x82,0x7A,0x6D,0xF5,0x95,
+    0x09,0x8B,0xC8,0x82,0xC1,0xCF,0xAB,0xD4,0x08,0x8B,0xC8,0x82,0x5E,0x7E,0xFA,0x7F,
+    0x08,0x8B,0xC7,0x82,0x82,0x01,0xCB,0xBF,0x29,0x8B,0xC8,0x82,0xF5,0x6F,0xA8,0xEB,
+    0x09,0x8B,0xC9,0x82,0xBF,0x02,0x38,0xFE,0x09,0x8B,0xC8,0x82,0x00,0xB0,0xBE,0x96,
+    0x29,0x8B,0xC8,0x7A,0xFC,0xFA,0xFA,0x7E,0xC9,0x82,0x84,0x51,0x78,0x68,0xF8,0x78,
+    0x63,0x49,0x23,0x49,0xEF,0x2E,0x6C,0xF0,0x84,0x51,0x43,0x49,0xEB,0xBE,0xAF,0xDD,
+    0x84,0x51,0x44,0x49,0xF5,0x5F,0xBE,0x3A,0xC5,0x61,0x64,0x51,0xBD,0x35,0xAF,0xAF,
+    0xE6,0x69,0xA5,0x61,0x38,0xAF,0xB9,0x29,0xA8,0x82,0xE5,0x69,0xAD,0xBF,0x2D,0x29,
+    0xE9,0x92,0xA8,0x82,0x89,0xB9,0xBB,0xAA,0x09,0x93,0xA8,0x8A,0x88,0xFA,0xFD,0x77,
+    0xEA,0x92,0x67,0x82,0xE8,0xFA,0xFE,0x7E,0x67,0x7A,0x26,0x72,0x1E,0x1A,0x58,0x77,
+    0x67,0x7A,0x26,0x72,0xE0,0x00,0x3C,0xD5,0x46,0x72,0x06,0x72,0xE5,0xDE,0x34,0x9C,
+    0x67,0x7A,0x06,0x6A,0xFD,0xEE,0xAE,0x0A,0x46,0x72,0xE5,0x61,0x5E,0xFA,0x7E,0x5C,
+    0x06,0x6A,0xA5,0x59,0xFA,0xF0,0x72,0x55,0xA5,0x59,0x23,0x49,0x7A,0x68,0x5A,0x7A,
+    0x23,0x49,0xE3,0x40,0x28,0xF0,0xE8,0xB2,0x64,0x49,0x03,0x41,0xBD,0x9D,0x2F,0xB9,
+    0x64,0x49,0x23,0x49,0x35,0xAD,0xAF,0xFE,0x84,0x59,0x23,0x49,0x9A,0xAA,0x2A,0x2A,
+    0x05,0x62,0xA5,0x59,0x3F,0xBF,0xB5,0xDD,0x88,0x72,0xC5,0x59,0x2B,0x27,0xAF,0xAD,
+    0x88,0x72,0x46,0x72,0xBE,0xB2,0xE2,0xC2,0x67,0x72,0xA4,0x59,0xE2,0x68,0x7A,0x7A,
+    0xA4,0x59,0x43,0x49,0xE0,0xE8,0xF8,0x7E,0x64,0x51,0x02,0x41,0xDC,0xDC,0xFA,0xEF,
+    0xA5,0x59,0x23,0x49,0xBD,0xAF,0xBD,0x3B,0x47,0x72,0x84,0x59,0xF5,0xD5,0xBD,0x2F,
+    0x27,0x72,0xC6,0x69,0xA5,0xB7,0xAA,0x88,0xA8,0x82,0x06,0x6A,0xD5,0xF5,0xB5,0x0A,
+    0x09,0x93,0x67,0x7A,0xED,0xFF,0xAE,0xA2,0xC9,0x8A,0x26,0x72,0xE0,0x7A,0x78,0xFA,
+    0x88,0x82,0x26,0x72,0x2F,0x9D,0xFF,0xFB,0xE9,0x8A,0x87,0x82,0xAB,0x83,0x09,0x25,
+    0x4A,0x93,0xC8,0x82,0x62,0x6A,0xEB,0x55,0xC9,0x82,0x67,0x7A,0xB7,0xDF,0x7A,0x78,
+    0x0C,0x9C,0xA8,0x82,0x2D,0xFD,0xFD,0xF5,0xB6,0xF6,0x4A,0x93,0x0B,0xAD,0xF5,0x55,
+    0x76,0xF6,0x11,0xC5,0x00,0x80,0x2B,0xAD,0x76,0xEE,0x55,0xEE,0xFE,0xB5,0xB5,0xB5,
+    0x76,0xEE,0x55,0xEE,0xE8,0xAE,0x7E,0x5E,0xD7,0xF6,0x55,0xEE,0xBD,0xA7,0xAF,0xA5,
+    0x18,0xFF,0xB7,0xF6,0xAD,0x2F,0xAF,0x2B,0x18,0xFF,0xD7,0xF6,0xBA,0xF8,0xFA,0xBE,
+    0x39,0xFF,0xF8,0xF6,0x87,0xAD,0xAD,0xAD,0x18,0xFF,0x38,0xF7,0x22,0x88,0x02,0x08,
+    0x18,0xFF,0xF8,0xF6,0xAA,0xA8,0xE2,0xAA,0x18,0xFF,0xF8,0xF6,0xFE,0xFA,0xFF,0xFE,
+    0x18,0xFF,0xF8,0xF6,0xFE,0x79,0xEB,0xDF,0xD7,0xFE,0xF8,0xF6,0xDD,0x57,0xDD,0xFF,
+    0xF8,0xF6,0xD7,0xF6,0xEA,0xB2,0xBE,0xBA,0xF7,0xF6,0xD7,0xF6,0xAE,0x9E,0x3E,0xA7,
+    0xF7,0xF6,0xD7,0xF6,0xE3,0x88,0xAA,0x8A,0xF8,0xFE,0xF7,0xF6,0xFF,0xFF,0xF9,0xFF,
+    0xD7,0xFE,0xF7,0xF6,0x5F,0x57,0x57,0x7F,0xF7,0xFE,0x18,0xF7,0x2E,0x0B,0xAA,0xFF,
+    0xF8,0xFE,0x17,0xEF,0x28,0xA2,0xA2,0xAA,0x17,0xFF,0xF8,0xF6,0xFD,0x57,0x5F,0xFB,
+    0x18,0xFF,0xF8,0xF6,0xAB,0xFE,0xB9,0xDE,0x18,0xFF,0xF8,0xF6,0xFF,0xEE,0xAA,0xAA,
+    0x18,0xFF,0xF8,0xF6,0x7E,0xDA,0x5E,0xD7,0xD8,0xFE,0xF7,0xF6,0xD7,0xF7,0x9D,0xBD,
+    0xF7,0xF6,0xB7,0xEE,0xAA,0xFE,0x5F,0x77,0xD7,0xF6,0x96,0xEE,0x00,0xAA,0xEF,0xDF,
+    0xD7,0xF6,0x76,0xEE,0xA8,0xE2,0xEB,0xFF,0xB7,0xF6,0x55,0xE6,0xE8,0xFC,0xFC,0xFE,
+    0x76,0xEE,0x55,0xE6,0x8E,0xAE,0xA8,0x00,0x96,0xEE,0x76,0xEE,0x7D,0x75,0xD5,0x55,
+    0x76,0xEE,0x56,0xEE,0xBE,0xF4,0x9E,0xFA,0x75,0xEE,0x56,0xEE,0xD5,0xF5,0xAD,0xBB,
+    0x76,0xEE,0x35,0xE6,0xFA,0xFA,0x82,0xA0,0x55,0xEE,0x14,0xE6,0xF2,0xF8,0x20,0x00,
+    0x55,0xEE,0x14,0xDE,0xAF,0xDF,0xBE,0xB0,0x75,0xEE,0x35,0xE6,0xAB,0x2B,0x2B,0xAD,
+    0x96,0xEE,0x76,0xEE,0xBF,0x2F,0x8F,0xEF,0xB6,0xF6,0x75,0xEE,0xAF,0xBF,0xBA,0x2A,
+    0x96,0xEE,0x55,0xE6,0xFC,0x7B,0xB8,0x28,0x96,0xEE,0x55,0xE6,0x2B,0xAF,0x2B,0x00,
+    0x95,0xEE,0x76,0xEE,0x6B,0xFB,0xF2,0xE2,0x96,0xEE,0x14,0xE6,0xE8,0xE0,0x62,0xF8,
+    0x34,0xE6,0xF4,0xDD,0xF0,0xF8,0xFF,0xD7,0x14,0xE6,0xF4,0xDD,0x02,0xBA,0xFB,0x5D,
+    0x14,0xE6,0xD3,0xDD,0xA0,0xBE,0xD7,0xD6,0xD3,0xE5,0xF4,0xDD,0x5D,0xDD,0xEF,0xFF,
+    0x14,0xE6,0xD3,0xD5,0x02,0x02,0xE2,0x68,0xB3,0xD5,0xAF,0xBC,0xF0,0x78,0x58,0x5E,
+    0xCF,0xBC,0x8E,0xB4,0xB8,0xA8,0xDF,0xED,0xAF,0xBC,0x4D,0xAC,0x00,0xA8,0xFA,0x58,
+    0xAF,0xBC,0x0C,0xA4,0xA8,0xEA,0xEE,0x7F,0x8F,0xB4,0x0D,0xA4,0x2E,0xBD,0xB5,0xB5,
+    0x11,0xC5,0x6F,0xB4,0x2A,0x2B,0x2D,0xAF,0x72,0xD5,0x10,0xC5,0xAA,0xAF,0x0D,0x35,
+    0xB3,0xD5,0xF0,0xC4,0x5F,0x7E,0x7A,0xAA,0xF0,0xC4,0x0D,0xA4,0x58,0x58,0xD8,0xD8,
+    0x31,0xCD,0x6E,0xB4,0x09,0x29,0x8D,0x89,0x31,0xCD,0xF0,0xC4,0xD0,0xF2,0x80,0x02,
+    0x72,0xCD,0x31,0xCD,0xB5,0x0D,0x2D,0x2F,0x92,0xD5,0x51,0xCD,0xBF,0xEA,0xFB,0xFF,
+    0x92,0xD5,0x51,0xCD,0xA3,0xDA,0xDE,0xAC,0x71,0xD5,0x51,0xCD,0xF8,0xF8,0xEC,0x30,
+    0xA7,0x7A,0x46,0x7A,0xBB,0x28,0x92,0x82,0xA7,0x7A,0x45,0x72,0xEA,0x10,0xAA,0xAA,
+    0xA7,0x7A,0x45,0x72,0xAA,0x85,0xAA,0xA2,0xA7,0x7A,0x45,0x6A,0xFE,0xDC,0xB2,0xAA,
+    0xA7,0x7A,0x66,0x72,0x69,0xE9,0xA6,0x9A,0xA7,0x7A,0x46,0x72,0xAB,0xBA,0x6B,0x8F,
+    0xA7,0x7A,0x46,0x72,0x57,0x5B,0xF7,0xD7,0x87,0x7A,0x46,0x72,0x55,0x6B,0xFA,0xA2,
+    0x66,0x72,0x25,0x6A,0x9F,0x7E,0x5B,0x28,0xA7,0x7A,0x25,0x6A,0x0A,0xAD,0xFD,0xFF,
+    0xC7,0x82,0x25,0x6A,0x00,0x8A,0xBF,0x57,0xE8,0x8A,0x66,0x72,0x8A,0xA0,0xEE,0xF5,
+    0xE8,0x82,0xA7,0x7A,0xEC,0x1D,0xBD,0x55,0x08,0x8B,0xA7,0x7A,0xFF,0xDF,0xAB,0xBA,
+    0xE8,0x82,0xA7,0x82,0x09,0x0B,0xC2,0x9F,0xE8,0x82,0xA7,0x7A,0xAA,0xBD,0xEB,0xA3,
+    0x09,0x83,0xA7,0x7A,0xE8,0xFA,0xBF,0xBB,0xE9,0x82,0xC8,0x82,0x0F,0xD5,0x5B,0x42,
+    0x09,0x8B,0xA7,0x7A,0xE2,0xEA,0xD8,0xDF,0xE8,0x8A,0xA7,0x7A,0x2B,0xBB,0x3D,0xAF,
+    0xE8,0x8A,0xC8,0x82,0xBC,0x96,0xEE,0xFC,0x08,0x8B,0xC8,0x82,0x77,0xD4,0x5D,0xB7,
+    0x09,0x8B,0xC8,0x82,0x95,0xD8,0xF8,0xFF,0x09,0x8B,0xA7,0x82,0xBE,0xFA,0xF8,0xDE,
+    0xE8,0x8A,0xA8,0x82,0xBA,0xEA,0xAB,0x0A,0x09,0x8B,0xA7,0x82,0xBC,0xBB,0x6B,0xAB,
+    0x08,0x83,0xA7,0x7A,0xFF,0x7F,0xFF,0xF8,0xA7,0x7A,0x84,0x51,0xF8,0x7A,0x78,0x5E,
+    0xA4,0x59,0x23,0x41,0x78,0xFA,0xFF,0x57,0x84,0x49,0x23,0x49,0xAB,0x2D,0x9C,0xFD,
+    0xC5,0x59,0x64,0x51,0xBA,0xBF,0x3B,0xFD,0xC5,0x61,0x84,0x59,0x3E,0xBF,0xAB,0xBB,
+    0x26,0x72,0xC5,0x61,0xA5,0xAB,0x09,0x09,0xE8,0x8A,0x26,0x72,0xBD,0xAF,0x0F,0xAB,
+    0xE9,0x92,0xA8,0x8A,0x2B,0x83,0xAA,0xEC,0xC8,0x92,0x46,0x7A,0xE8,0xF8,0xFE,0x7E,
+    0x88,0x82,0x05,0x72,0xB0,0xDE,0x7F,0xFE,0x46,0x7A,0xE5,0x69,0xEA,0xBA,0x7F,0xEC,
+    0x26,0x72,0xC5,0x69,0x00,0x0A,0x3E,0xDE,0x26,0x72,0xC5,0x61,0x88,0xE8,0xFA,0xBF,
+    0x26,0x72,0x84,0x59,0x00,0xFE,0xFB,0x7E,0x26,0x72,0x84,0x59,0xE8,0xBE,0x5F,0x5D,
+    0xA5,0x59,0x23,0x49,0xAA,0xFC,0x78,0xEA,0x64,0x51,0x02,0x49,0x48,0xEA,0xCF,0x80,
+    0x84,0x51,0x03,0x49,0xDD,0xBB,0xEA,0x2A,0x64,0x49,0x23,0x49,0xFF,0x5C,0xDF,0x97,
+    0x43,0x49,0x02,0x49,0x28,0xE8,0xEA,0x00,0xC5,0x59,0x23,0x49,0xAF,0x2D,0xBF,0x09,
+    0x27,0x6A,0xA4,0x59,0xFD,0xBD,0xA9,0x2E,0x47,0x6A,0xE5,0x61,0x8D,0x02,0xB0,0xFF,
+    0x67,0x72,0xE5,0x61,0x80,0xF2,0x7B,0xDD,0x46,0x72,0xC5,0x61,0x7E,0xE2,0xAA,0xFA,
+    0xA5,0x59,0x43,0x49,0x7E,0xD8,0x50,0x70,0xA5,0x59,0x02,0x41,0xFF,0xB7,0x2F,0x0B,
+    0xC5,0x61,0x44,0x51,0xAD,0xAB,0xA2,0x08,0x67,0x7A,0xA5,0x61,0x2D,0x0D,0xBD,0xB9,
+    0x87,0x82,0x26,0x72,0x5F,0x57,0xAF,0x81,0x2A,0x93,0x26,0x72,0xAD,0x2D,0x2D,0xAF,
+    0x2A,0x93,0xC7,0x8A,0xEA,0x60,0xE8,0x62,0xC8,0x8A,0x27,0x72,0xFE,0xF8,0xF8,0x58,
+    0xE9,0x8A,0x47,0x7A,0xBD,0x35,0x2D,0x3D,0xE9,0x8A,0x46,0x72,0xBF,0xFE,0xF8,0x60,
+    0xA8,0x82,0x06,0x6A,0x20,0x22,0xBA,0x5F,0xA8,0x7A,0xC5,0x61,0x88,0xAA,0xEE,0xD5,
+    0xC8,0x82,0x06,0x6A,0x02,0x02,0x2B,0xB5,0x2A,0x8B,0x87,0x7A,0x2E,0x2E,0x3F,0x95,
+    0xB3,0xDD,0x6B,0x93,0x0B,0x2D,0x35,0xF5,0x56,0xEE,0x93,0xDD,0x00,0x02,0x0B,0x09,
+    0x76,0xEE,0x35,0xE6,0xBA,0xF8,0xB8,0xFE,0xB7,0xF6,0x55,0xEE,0x2D,0x2D,0x2D,0xAD,
+    0xF7,0xFE,0xB7,0xF6,0x02,0x0B,0x03,0x8B,0xD6,0xFE,0xF8,0xF6,0xFD,0xD5,0x7D,0xFD,
+    0x18,0xFF,0xF8,0xF6,0x02,0x0A,0x0D,0x2D,0x18,0xFF,0xF8,0xF6,0x00,0x80,0x80,0xA0,
+    0x18,0xFF,0xF8,0xF6,0x82,0xA0,0xCA,0xAA,0x18,0xFF,0xF8,0xF6,0xFF,0xD7,0xFD,0x7F,
+    0x18,0xFF,0xF8,0xF6,0x5E,0x5B,0xDF,0xD5,0xD7,0xFE,0xF8,0xF6,0x5B,0x5F,0x57,0x75,
+    0xF7,0xF6,0xD8,0xF6,0x9C,0xA0,0x2A,0xAA,0xD7,0xFE,0xF7,0xF6,0xDF,0xDD,0xDF,0xFF,
+    0xD8,0xFE,0xF7,0xF6,0x57,0x5D,0x5F,0xFF,0x18,0xFF,0xF7,0xF6,0x55,0xD5,0xFF,0xFD,
+    0x18,0xFF,0xF7,0xF6,0x57,0xDD,0x36,0xAF,0x18,0xFF,0xF8,0xF6,0xE3,0xAA,0xEC,0xFA,
+    0x18,0xFF,0xF8,0xF6,0xAF,0xAB,0xAB,0xAB,0x18,0xFF,0xF8,0xF6,0xFF,0xDE,0xFF,0xEA,
+    0x18,0xFF,0xF8,0xF6,0xFF,0x7F,0x5F,0xFE,0x18,0xFF,0xD8,0xF6,0xAA,0xBA,0xF2,0xFA,
+    0xF8,0xF6,0xD7,0xF6,0x20,0xB8,0xFB,0x5F,0xF8,0xF6,0xB7,0xEE,0xA0,0xCA,0xEE,0x5E,
+    0xD7,0xF6,0x96,0xEE,0x78,0xFA,0xFE,0xFE,0xB6,0xF6,0x76,0xEE,0xFA,0xEE,0xFA,0xDE,
+    0x96,0xEE,0x55,0xE6,0xE8,0xEA,0x78,0x7E,0x96,0xEE,0x55,0xE6,0xEA,0xFA,0xAF,0x2D,
+    0x96,0xEE,0x76,0xEE,0xFD,0xFD,0xE7,0x7B,0x76,0xEE,0x55,0xEE,0x30,0xA0,0x20,0xAE,
+    0x76,0xEE,0x56,0xEE,0xFB,0xAA,0xF8,0xBC,0x76,0xEE,0x55,0xEE,0xAF,0xB7,0xEA,0xE8,
+    0x76,0xEE,0x55,0xEE,0x82,0x80,0x3B,0x2D,0x76,0xEE,0x55,0xEE,0xD7,0x52,0x68,0x98,
+    0x55,0xEE,0x35,0xE6,0x58,0x72,0xE0,0x20,0x55,0xEE,0x14,0xE6,0x0B,0x15,0x9F,0x9C,
+    0x96,0xEE,0x35,0xEE,0xA2,0xAB,0xFF,0xE7,0xB7,0xF6,0x34,0xE6,0x82,0xAE,0x7F,0x55,
+    0xB7,0xF6,0x35,0xE6,0x2A,0xAE,0xFD,0x55,0x96,0xEE,0x55,0xEE,0x20,0xA0,0xD7,0xD5,
+    0x96,0xEE,0x55,0xEE,0x22,0x2E,0x2F,0x2A,0x96,0xF6,0xF3,0xDD,0x68,0x68,0x68,0xF8,
+    0x14,0xE6,0xD3,0xDD,0xB7,0xEF,0xAB,0xAA,0x14,0xE6,0xD3,0xDD,0xFF,0xDB,0xE6,0xFB,
+    0x14,0xE6,0xD3,0xDD,0xF7,0x75,0xF5,0xAE,0x14,0xE6,0xF4,0xDD,0x79,0xC3,0xE9,0x6B,
+    0xF4,0xE5,0x31,0xCD,0x80,0xE0,0x70,0x70,0x31,0xC5,0xAF,0xBC,0x58,0x5F,0xB7,0xFE,
+    0xF0,0xC4,0x8E,0xB4,0x57,0xFB,0xAE,0x82,0xF0,0xC4,0x4D,0xAC,0xDE,0xFF,0xEA,0xE2,
+    0xAF,0xBC,0x0C,0xA4,0x5F,0xF6,0x88,0x00,0x8E,0xB4,0xAB,0x9B,0xBF,0x2E,0x28,0xA8,
+    0xD0,0xBC,0x8E,0xB4,0xE3,0xAB,0xFB,0xBF,0x31,0xC5,0x8E,0xB4,0x2A,0xAD,0xFD,0xD7,
+    0x71,0xCD,0x6E,0xB4,0x00,0x80,0xFF,0x5F,0x10,0xC5,0x2C,0xAC,0x78,0xDC,0x57,0x95,
+    0x31,0xCD,0x8E,0xB4,0x29,0x89,0x0B,0x0B,0x31,0xCD,0x10,0xC5,0x3C,0x17,0xD7,0xAF,
+    0x92,0xD5,0x31,0xCD,0x8F,0x2D,0xA7,0xA5,0x92,0xD5,0x51,0xCD,0xBB,0x18,0xBA,0xAE,
+    0x92,0xD5,0x51,0xCD,0xAA,0xEF,0x8E,0xF2,0x92,0xD5,0x51,0xCD,0x9E,0xDE,0xFB,0xE2,
+    0xC7,0x7A,0x66,0x72,0x89,0xCB,0xFF,0xFF,0xA7,0x7A,0x86,0x7A,0x92,0xA2,0x9E,0x0B,
+    0xA7,0x7A,0x66,0x72,0xA0,0xF0,0x38,0xF8,0x67,0x7A,0x86,0x72,0x5D,0x5B,0xDB,0x75,
+    0xC7,0x7A,0x86,0x72,0x55,0xF7,0xEB,0xDF,0xA7,0x7A,0x66,0x72,0x2A,0x0A,0x28,0x3E,
+    0xA7,0x7A,0x67,0x72,0x7A,0xFE,0xFF,0x88,0x86,0x7A,0x65,0x6A,0x02,0x08,0xB2,0x82,
+    0xA7,0x7A,0x45,0x72,0xF7,0xD7,0xBB,0x2C,0x87,0x7A,0x46,0x72,0x7E,0x68,0xAA,0x8A,
+    0x87,0x7A,0x46,0x72,0xFF,0xA3,0x08,0x08,0x86,0x7A,0x66,0x72,0xA5,0xFB,0xED,0xFF,
+    0x86,0x7A,0x46,0x72,0x02,0x5F,0x57,0x7E,0xC8,0x82,0x25,0x6A,0x22,0xAF,0xBF,0xDF,
+    0xE8,0x82,0x45,0x72,0x0A,0x80,0xAF,0x7D,0xE8,0x82,0x87,0x7A,0xA0,0x82,0xA2,0x3F,
+    0xE9,0x8A,0xC8,0x82,0x2D,0x37,0xDF,0xDE,0xE8,0x8A,0xC8,0x82,0x62,0xC4,0x6A,0xAE,
+    0x09,0x8B,0xC8,0x82,0x59,0xF3,0xED,0x16,0xE8,0x8A,0xA8,0x82,0xAF,0x2B,0xFE,0xC8,
+    0xE8,0x8A,0xA7,0x82,0x3C,0x28,0x20,0xED,0xE8,0x8A,0xC8,0x82,0xB0,0xC8,0xE2,0xC1,
+    0xE8,0x8A,0xC8,0x82,0x78,0x5E,0x40,0xBA,0x09,0x93,0xA7,0x82,0xDF,0xAE,0x2A,0xE6,
+    0xE8,0x8A,0xA7,0x82,0x29,0x00,0x82,0x0B,0xE8,0x8A,0xC8,0x82,0x0B,0xDE,0xA6,0xE8,
+    0xE8,0x82,0x66,0x72,0xE0,0x70,0x74,0x7A,0x66,0x72,0x84,0x51,0x58,0x5E,0x5A,0x78,
+    0x64,0x51,0xE2,0x40,0xFC,0xF6,0x7E,0xFE,0x44,0x49,0xE2,0x38,0x02,0x3F,0xBF,0x57,
+    0x84,0x51,0xE2,0x38,0x82,0x2F,0xFF,0xD5,0xA4,0x59,0x02,0x41,0x02,0x2B,0x2F,0x0D,
+    0x46,0x72,0xC5,0x61,0x0D,0x0D,0x2F,0xA5,0xC8,0x8A,0x25,0x72,0x0B,0x0D,0xAF,0x25,
+    0x29,0x93,0xA7,0x82,0xFB,0xBB,0x09,0xAF,0x09,0x93,0x67,0x82,0x5E,0xEA,0xA0,0xE8,
+    0x88,0x82,0x06,0x72,0xEA,0xE0,0xFA,0x7C,0x67,0x7A,0x26,0x72,0x72,0xF2,0xCD,0xAD,
+    0x47,0x7A,0xA4,0x61,0x7A,0x7A,0xA0,0xE8,0xE6,0x69,0x44,0x51,0x0A,0xEA,0xD8,0x7E,
+    0xE5,0x69,0x43,0x51,0xA0,0xA3,0x6B,0xD5,0xA5,0x61,0x23,0x49,0xE8,0xEB,0x7B,0x5A,
+    0x85,0x51,0x03,0x49,0x2A,0xBF,0xDD,0x7F,0x85,0x51,0x03,0x49,0xAA,0x0F,0xFF,0xBD,
+    0x64,0x49,0x23,0x49,0xA2,0x88,0x80,0x63,0x84,0x51,0x02,0x41,0xF7,0xDF,0xFF,0x2F,
+    0xA5,0x51,0x43,0x49,0xD5,0xD5,0xA7,0x88,0x06,0x62,0x84,0x51,0x25,0xBD,0xED,0x5D,
+    0x06,0x62,0x64,0x51,0x20,0xB8,0xEB,0xFD,0x06,0x62,0x84,0x51,0x20,0xAB,0xA7,0xD5,
+    0x06,0x62,0xA5,0x51,0xAB,0xAF,0xCF,0xDD,0x06,0x62,0x84,0x51,0x40,0xCA,0xEB,0x5F,
+    0xA5,0x59,0x23,0x49,0xFA,0xFE,0x9F,0x3F,0x06,0x6A,0x64,0x51,0xB5,0xF5,0xBB,0x8B,
+    0xE5,0x69,0xC5,0x61,0x5E,0x7F,0x7D,0xAE,0x67,0x7A,0xC5,0x61,0x5F,0xF5,0xBD,0x0B,
+    0xA8,0x82,0x47,0x7A,0x25,0x25,0xF7,0x7A,0xE9,0x8A,0x47,0x72,0x2A,0x2A,0xBD,0xDD,
+    0xE9,0x8A,0x88,0x82,0xE0,0x5A,0x58,0xCB,0xA8,0x82,0x27,0x72,0x58,0x7E,0xBC,0xFA,
+    0x88,0x7A,0x26,0x72,0x2F,0xDF,0xF5,0xE5,0xA8,0x82,0xC4,0x61,0xA0,0xAA,0xEA,0x7A,
+    0x06,0x6A,0xE2,0x40,0xA0,0xA8,0xFA,0x7E,0xC6,0x61,0x23,0x49,0x2A,0x0F,0x2D,0xB5,
+    0x47,0x72,0xA5,0x59,0x0A,0xAF,0xDF,0xF5,0xC8,0x82,0xE5,0x61,0x0A,0x2F,0x2D,0xAD,
+    0x2E,0xAC,0x88,0x7A,0x2F,0x2F,0xBD,0xF5,0xF4,0xE5,0x6A,0x9B,0x02,0x0B,0x0F,0xB5,
+    0x55,0xEE,0x52,0xD5,0x00,0x00,0xAA,0xBD,0xB7,0xFE,0x14,0xE6,0x2B,0x0B,0x2F,0x2D,
+    0xF8,0xFE,0xB7,0xFE,0x0B,0x2B,0x2A,0x2B,0xF8,0xFE,0xB7,0xF6,0xA8,0xAA,0x3E,0x9E,
+    0x18,0xFF,0xB8,0xF6,0x0A,0x0A,0x2A,0x8B,0x18,0xFF,0xF8,0xF6,0xA2,0x80,0x80,0x80,
+    0x18,0xFF,0xF8,0xF6,0xA2,0x8E,0xFA,0xEA,0x17,0xFF,0xF8,0xF6,0x7E,0xFF,0xFF,0xFF,
+    0xD8,0xFE,0xF7,0xF6,0x56,0x7F,0x77,0x75,0xF7,0xFE,0xF8,0xF6,0xFF,0xFF,0xEF,0xFB,
+    0xF7,0xF6,0xD7,0xF6,0xAB,0x8B,0xE2,0xB0,0xF7,0xF6,0xD8,0xF6,0xA8,0x0E,0x2A,0x8E,
+    0xF8,0xFE,0xF7,0xF6,0xFF,0xFF,0xBF,0xFF,0x18,0xFF,0xD7,0xF6,0xFF,0xEB,0xEA,0xAA,
+    0x18,0xFF,0xF7,0xF6,0xFB,0xFD,0xFF,0x7F,0xF8,0xFE,0x18,0xF7,0xAE,0xAA,0xEA,0xBE,
+    0x18,0xFF,0xF8,0xF6,0xFB,0xFE,0xFE,0xDF,0xF8,0xFE,0x18,0xF7,0xAA,0xB8,0xAA,0xAA,
+    0x18,0xFF,0xF8,0xF6,0xFF,0x7F,0x5E,0x76,0x18,0xFF,0xD7,0xF6,0xFA,0xFA,0xFE,0xEF,
+    0xF7,0xF6,0xD7,0xF6,0x76,0x7E,0xBF,0x77,0xD7,0xF6,0xB7,0xF6,0x7C,0x70,0xA0,0xF8,
+    0xB7,0xF6,0x96,0xEE,0xE8,0xEE,0x78,0xF0,0x96,0xEE,0x76,0xEE,0xD8,0xF0,0x7B,0x56,
+    0x75,0xEE,0x35,0xE6,0xF8,0x7E,0xEA,0xFA,0x75,0xEE,0x35,0xE6,0x0B,0xAB,0xBF,0xFD,
+    0x55,0xEE,0x76,0xE6,0xBD,0x02,0x02,0x22,0x76,0xEE,0x55,0xEE,0xCE,0xDE,0xD5,0xD5,
+    0x76,0xEE,0x55,0xEE,0xFF,0x87,0x3A,0xF2,0x75,0xEE,0x56,0xEE,0xFB,0xEF,0xF7,0x55,
+    0x76,0xEE,0x55,0xEE,0xAD,0xBD,0xF9,0xB0,0x76,0xEE,0x55,0xEE,0x68,0xEB,0x2A,0xBE,
+    0x76,0xEE,0x14,0xE6,0xEA,0xA0,0x2A,0x20,0x55,0xEE,0x14,0xE6,0xE0,0xF0,0xF0,0xF0,
+    0x55,0xEE,0x14,0xE6,0xAB,0xF9,0xD5,0xFF,0x35,0xE6,0x14,0xE6,0xFA,0xD7,0xB4,0xF8,
+    0x55,0xEE,0x14,0xE6,0xBB,0x3F,0xBB,0x3F,0x96,0xF6,0x55,0xE6,0x9D,0xAF,0x0B,0x22,
+    0x96,0xF6,0x75,0xEE,0x89,0xAB,0xC0,0xE0,0x96,0xF6,0xF3,0xDD,0x78,0x5E,0x5C,0x5E,
+    0x14,0xE6,0xD3,0xDD,0xAF,0x3F,0x95,0xAD,0x34,0xE6,0xF4,0xE5,0xDD,0x8B,0x8F,0xB7,
+    0x35,0xE6,0xF3,0xDD,0xFE,0xEE,0xB8,0x7A,0x14,0xE6,0xF4,0xDD,0xB2,0x20,0x20,0xF9,
+    0x14,0xE6,0x31,0xCD,0x78,0x68,0xF8,0x78,0x51,0xCD,0xF0,0xC4,0x5F,0x55,0x5C,0x7A,
+    0xF0,0xC4,0xCF,0xBC,0x0A,0x03,0x69,0x42,0xF0,0xC4,0xAF,0xBC,0xEA,0xEF,0xF4,0x77,
+    0xD0,0xC4,0xAE,0xB4,0xBD,0x2F,0x2A,0x83,0xCF,0xBC,0xEC,0xA3,0xF8,0x58,0x78,0x60,
+    0xCF,0xBC,0xEC,0xA3,0x82,0xAB,0xAF,0xAD,0xAF,0xBC,0x2D,0xAC,0xA8,0xEE,0x7F,0x5F,
+    0x8E,0xB4,0xEC,0xA3,0xA0,0xEB,0xFE,0x77,0xCF,0xBC,0xEC,0x9B,0xBF,0xBD,0x3F,0x3D,
+    0x31,0xCD,0xD0,0xBC,0x2D,0x2B,0x8B,0x8E,0x31,0xCD,0x10,0xC5,0x24,0xF4,0xD7,0x6B,
+    0x72,0xD5,0x10,0xC5,0x2B,0x2B,0xFD,0xFF,0x72,0xD5,0x31,0xCD,0xA8,0xA2,0xA4,0xFF,
+    0x92,0xD5,0x31,0xCD,0xAA,0x83,0xFE,0xDB,0x92,0xD5,0x31,0xCD,0xA2,0xFA,0xAD,0xF9,
+    0xA7,0x7A,0x45,0x6A,0x28,0xAF,0x3F,0xD5,0xC7,0x7A,0x65,0x6A,0x2A,0xBA,0xAE,0xDB,
+    0xA7,0x7A,0x66,0x72,0xA8,0xEA,0xAA,0xED,0xA7,0x7A,0x86,0x72,0x56,0xBF,0xA2,0xC2,
+    0xC7,0x7A,0x86,0x72,0xFF,0x7E,0xFB,0xAB,0xC7,0x7A,0x66,0x72,0xB7,0xB3,0xBB,0xDE,
+    0xA7,0x7A,0x87,0x72,0xAA,0x38,0xBA,0xBE,0xC8,0x82,0x66,0x72,0xE5,0xBF,0x0B,0xAA,
+    0xA7,0x7A,0x66,0x72,0xFF,0xE2,0xF0,0x0A,0xC7,0x82,0x66,0x72,0xFE,0xE2,0xEB,0xB6,
+    0xA7,0x7A,0x46,0x72,0x8E,0xEB,0xAA,0x9A,0xA7,0x7A,0x66,0x72,0xD3,0xD7,0xBB,0xAE,
+    0x87,0x7A,0x45,0x72,0x6A,0xB8,0x28,0x00,0x87,0x7A,0x45,0x72,0x7B,0xE3,0x72,0xC0,
+    0x86,0x7A,0x45,0x72,0xFD,0x25,0xFB,0xDF,0x87,0x7A,0x25,0x6A,0x3F,0xB7,0xA7,0xA2,
+    0xC8,0x82,0x45,0x72,0x03,0x27,0xF5,0xF7,0xE8,0x8A,0x46,0x72,0x88,0xAA,0x3F,0x55,
+    0xE8,0x8A,0x66,0x72,0x2A,0xA0,0xAA,0xBD,0xE8,0x82,0xA7,0x82,0x8A,0x6F,0x89,0xBB,
+    0xE8,0x82,0xA7,0x7A,0x77,0x6D,0x2B,0xAA,0x08,0x8B,0xA7,0x82,0xFD,0xF5,0xBF,0x1E,
+    0xE8,0x8A,0xC8,0x82,0xFB,0x5E,0xEB,0x62,0x08,0x8B,0xA7,0x82,0xA6,0x8B,0xAB,0x6D,
+    0xE8,0x82,0xA8,0x82,0xAC,0xBB,0xFA,0xFA,0xE8,0x82,0x87,0x7A,0x6A,0x68,0x2A,0x02,
+    0xE8,0x82,0x86,0x72,0x7F,0xEA,0xFC,0xE8,0xA7,0x7A,0x83,0x51,0x7E,0x78,0x78,0x78,
+    0x43,0x49,0xE2,0x38,0xFE,0xFC,0x7A,0xFC,0x03,0x41,0xE2,0x38,0xFE,0x9E,0x5D,0x77,
+    0xE2,0x38,0x81,0x30,0xAA,0xDA,0xAA,0xAC,0x64,0x51,0xC2,0x38,0x0F,0x2D,0xF5,0x55,
+    0xE5,0x69,0x03,0x49,0x02,0x0A,0xAF,0xBD,0x87,0x82,0xA4,0x61,0x2B,0xAF,0xF5,0x55,
+    0x09,0x93,0x26,0x72,0x2A,0x2B,0xFF,0xD5,0x09,0x93,0x27,0x7A,0xE8,0x6A,0xDF,0x57,
+    0x88,0x82,0x06,0x72,0xFE,0xDD,0x9E,0x22,0x67,0x7A,0x06,0x6A,0xEF,0xFF,0x7E,0x58,
+    0x06,0x6A,0xC5,0x69,0x68,0x5C,0x7F,0x97,0x26,0x72,0x84,0x59,0x57,0x7F,0xBA,0x0A,
+    0xE5,0x69,0x43,0x51,0xF5,0xBF,0xBA,0xA0,0xC5,0x61,0x23,0x49,0x7E,0xFE,0xF8,0xE8,
+    0x43,0x49,0x03,0x49,0xEA,0xAE,0xEC,0x9E,0x43,0x49,0x02,0x41,0x0D,0x8A,0x0A,0x00,
+    0x64,0x49,0x23,0x49,0xEB,0xAB,0x3A,0x8A,0x85,0x51,0x23,0x41,0x2B,0x0E,0xBE,0x57,
+    0xA5,0x59,0x03,0x41,0x80,0xA2,0xFE,0x75,0x64,0x49,0x23,0x41,0x00,0xF4,0x7F,0x65,
+    0x84,0x51,0x23,0x41,0xF2,0xEF,0xBF,0xDD,0x84,0x51,0x23,0x41,0x0A,0x7E,0xDE,0xFF,
+    0xA5,0x59,0x23,0x41,0x0A,0x2A,0xD7,0x55,0xC5,0x59,0x03,0x41,0xC8,0xFA,0xF5,0x55,
+    0xE6,0x61,0x43,0x49,0xB5,0x3F,0x3D,0x2D,0x67,0x7A,0xE6,0x69,0xAF,0x0D,0xA8,0xB9,
+    0x67,0x7A,0x06,0x6A,0x5F,0xEC,0x8B,0xA0,0xC8,0x82,0x26,0x72,0xBD,0xBD,0x2D,0xEA,
+    0xEA,0x8A,0x47,0x72,0x7A,0xFA,0xE8,0xF8,0x67,0x7A,0xC6,0x69,0x8A,0xBB,0xF8,0x78,
+    0xC9,0x8A,0xE5,0x69,0x8A,0xAB,0xDF,0x75,0x68,0x7A,0xC5,0x61,0x00,0x00,0x8A,0xFD,
+    0x68,0x7A,0xC5,0x59,0x88,0xE0,0xEA,0x7E,0x47,0x72,0x03,0x49,0xA0,0xEA,0xFA,0x5F,
+    0x64,0x51,0x02,0x41,0x58,0x7E,0xEE,0xBF,0xA5,0x59,0x03,0x49,0xAD,0x2D,0x2F,0x2F,
+    0xE5,0x61,0x85,0x51,0xEF,0xA5,0x2B,0xAA,0x47,0x72,0xC4,0x61,0x09,0x8F,0xEE,0xBA,
+    0xA8,0x7A,0x05,0x6A,0x0B,0xFF,0xF5,0xBD,0xAC,0xA3,0x46,0x72,0x2F,0xBD,0xFD,0xFF,
+    0x11,0xCD,0x46,0x72,0x02,0xAF,0xFF,0x5F,0x93,0xDD,0x87,0x7A,0x00,0x2A,0xFF,0x55,
+    0xB7,0xFE,0x6A,0x9B,0x00,0xAA,0xFF,0x55,0x97,0xF6,0x4D,0xB4,0x00,0x00,0xBF,0xD5,
+    0xF8,0xFE,0x92,0xD5,0x00,0x02,0x0B,0x2D,0x18,0xFF,0xF8,0xFE,0xBF,0xBE,0xB7,0xD5,
+    0x18,0xFF,0xF8,0xF6,0xEA,0xEA,0xBE,0xB7,0x18,0xFF,0xF8,0xF6,0xF7,0xFF,0xFA,0xAE,
+    0xF8,0xFE,0xF7,0xF6,0xFF,0xBF,0xFF,0xFF,0x18,0xFF,0xD8,0xF6,0xEA,0xEE,0xFA,0x6E,
+    0xF8,0xF6,0xD7,0xF6,0xA8,0xBE,0xAE,0xAE,0xF7,0xF6,0xD7,0xF6,0x3B,0xAB,0xAC,0x22,
+    0xD8,0xFE,0x17,0xF7,0xEA,0xFA,0xBF,0xFF,0x18,0xFF,0xF7,0xF6,0xD7,0xBD,0xAF,0xAB,
+    0x18,0xFF,0xF8,0xF6,0xFF,0xFA,0xEB,0xEA,0x18,0xFF,0xF8,0xF6,0xFE,0xFE,0xBF,0xF7,
+    0x18,0xFF,0xF8,0xF6,0xFF,0x78,0xEA,0x6A,0xF8,0xFE,0x18,0xF7,0xAB,0xAE,0x8A,0xA8,
+    0x18,0xFF,0xD8,0xF6,0xA9,0xAE,0xAE,0xEA,0xF7,0xF6,0xB7,0xF6,0xA0,0xE8,0x68,0x7A,
+    0xD7,0xF6,0xB7,0xF6,0x00,0xA2,0xA9,0x0D,0xD7,0xF6,0xB7,0xF6,0xDC,0x55,0x76,0x56,
+    0xB6,0xF6,0x96,0xEE,0xF8,0xFC,0x7E,0x56,0x96,0xEE,0x76,0xEE,0x5E,0xBA,0x80,0xA8,
+    0x96,0xEE,0x55,0xE6,0x5F,0xFF,0xAE,0xA2,0x55,0xEE,0x35,0xE6,0xFE,0xFF,0xFE,0x18,
+    0x76,0xEE,0x55,0xEE,0xEF,0xEA,0xAA,0x01,0x76,0xEE,0x55,0xEE,0xAD,0x29,0x00,0xA0,
+    0xB5,0xF6,0x56,0xEE,0x5F,0xFF,0x7D,0xEF,0x76,0xEE,0x55,0xEE,0x95,0x55,0x7D,0xF7,
+    0x76,0xEE,0x55,0xEE,0xFA,0xF8,0x27,0x37,0x76,0xEE,0x55,0xEE,0x9A,0xB2,0xBA,0xAA,
+    0x76,0xEE,0x55,0xEE,0xF8,0x78,0xFB,0xD7,0x75,0xEE,0x15,0xE6,0xEA,0xAA,0xA8,0x08,
+    0x55,0xEE,0x15,0xE6,0xFA,0xFE,0xFC,0xBE,0x55,0xEE,0x35,0xE6,0x5D,0xEB,0x2F,0x3F,
+    0x55,0xEE,0x34,0xE6,0x15,0xE5,0xE0,0x40,0x96,0xF6,0x35,0xE6,0x03,0xAB,0x29,0xE5,
+    0x96,0xF6,0x35,0xE6,0x88,0xF2,0xFA,0x7F,0x75,0xEE,0xD3,0xDD,0x58,0x7A,0x5E,0x56,
+    0x14,0xE6,0xB3,0xD5,0xAB,0x3D,0xAF,0xDF,0x34,0xE6,0xF4,0xE5,0xFF,0xEB,0xAF,0xAD,
+    0x35,0xE6,0xD3,0xDD,0x7A,0x7A,0x7A,0x8A,0x15,0xE6,0xB3,0xD5,0xBB,0xD5,0xF7,0xE8,
+    0xD3,0xDD,0x30,0xCD,0xE0,0x60,0x78,0x60,0x51,0xCD,0xF0,0xC4,0xE8,0x7E,0x7F,0xFE,
+    0x10,0xC5,0xAE,0xBC,0xFB,0xFF,0x5F,0xB8,0xF0,0xBC,0xAF,0xBC,0xD5,0x9E,0xA3,0xAE,
+    0x10,0xC5,0xCF,0xBC,0xFB,0xF9,0xA9,0x92,0x31,0xCD,0x2D,0xAC,0x7A,0xE2,0x82,0x00,
+    0x11,0xC5,0xAB,0x9B,0xB7,0xFF,0x7A,0x60,0x2D,0xAC,0x09,0x8B,0x80,0xAA,0xFF,0xF7,
+    0xEC,0xA3,0x4A,0x8B,0xE8,0xFA,0xDF,0x55,0xD0,0xBC,0x8C,0x9B,0x2D,0x2D,0x0D,0x2D,
+    0x10,0xC5,0xCF,0xBC,0x02,0x0B,0x0B,0x9D,0x10,0xC5,0xF0,0xC4,0x02,0x8C,0x76,0x67,
+    0x51,0xCD,0xF0,0xC4,0xBA,0x2F,0x3F,0xBD,0x51,0xCD,0x31,0xCD,0x83,0xA7,0xD7,0xB7,
+    0x72,0xD5,0x31,0xCD,0xA2,0xEF,0xDF,0x77,0x72,0xD5,0x30,0xCD,0xBB,0xEA,0xFE,0x55,
+    0x46,0x6A,0x05,0x6A,0x2B,0xAB,0xAB,0xFF,0x86,0x72,0xE4,0x61,0x3E,0xB7,0xFF,0xFE,
+    0xA7,0x7A,0x05,0x6A,0x8A,0xCF,0x7F,0x7D,0xA7,0x7A,0x05,0x62,0x82,0x22,0xAB,0xFD,
+    0xA7,0x7A,0x46,0x6A,0x02,0x20,0xB2,0x3D,0xC7,0x7A,0x67,0x72,0xB4,0x9A,0xFC,0xEA,
+    0xA7,0x7A,0x46,0x72,0x02,0x00,0xA2,0x60,0xC8,0x7A,0x66,0x72,0xF8,0xFA,0x7F,0xFB,
+    0xC7,0x82,0x66,0x72,0xBF,0xA7,0x3F,0xBF,0xC7,0x7A,0x86,0x7A,0xD5,0x79,0x77,0xF7,
+    0xA7,0x7A,0x46,0x72,0x9F,0xEE,0x80,0x28,0xA7,0x7A,0x66,0x72,0xBA,0xE7,0x1F,0x23,
+    0xA7,0x7A,0x87,0x7A,0x3E,0x9C,0x9B,0xE9,0xA7,0x7A,0x66,0x72,0x7A,0x57,0xBC,0xB4,
+    0x66,0x7A,0xA7,0x72,0x2E,0xBE,0xBE,0xAE,0xC7,0x82,0x46,0x72,0x5F,0xEF,0xAB,0x2B,
+    0xA7,0x7A,0x66,0x72,0x5F,0xDE,0xDC,0xC2,0x87,0x7A,0x46,0x72,0x7A,0x78,0xFF,0xA3,
+    0xA7,0x82,0x46,0x72,0xBD,0xD7,0xAF,0x8A,0xA7,0x82,0x46,0x72,0x22,0xBB,0x7F,0xF9,
+    0xE8,0x8A,0x46,0x72,0x02,0xAE,0xF7,0x75,0x09,0x8B,0x66,0x72,0x82,0xAA,0xBB,0xD5,
+    0x09,0x8B,0x87,0x7A,0x8A,0xEF,0xAF,0xFD,0xE8,0x82,0xA7,0x7A,0x7E,0x2F,0x0B,0x0B,
+    0x29,0x8B,0xC8,0x82,0xD5,0x9D,0xBF,0xF2,0x08,0x8B,0xA7,0x7A,0xAA,0xA2,0xE0,0xDA,
+    0xE8,0x82,0xA7,0x7A,0xE8,0xBF,0xAE,0xBE,0xC7,0x7A,0xA3,0x59,0x78,0xE0,0xA0,0x80,
+    0x05,0x62,0xE2,0x40,0x5E,0x5E,0x5A,0xF8,0x03,0x41,0xE2,0x38,0x77,0x0E,0xBE,0xFD,
+    0x02,0x41,0xA1,0x30,0xFE,0xFC,0xF6,0xFE,0xE2,0x38,0x81,0x30,0xAA,0xAF,0xFF,0xDB,
+    0x44,0x51,0xA2,0x38,0x0B,0xAF,0xBD,0xF5,0x84,0x61,0xC2,0x40,0x00,0xAB,0xFF,0x55,
+    0xC5,0x69,0x03,0x49,0x02,0xBB,0xDF,0xE5,0x47,0x7A,0x84,0x61,0x3B,0x3F,0x35,0x2D,
+    0x88,0x82,0x26,0x72,0x8E,0xA7,0xAE,0x08,0xA8,0x82,0xC5,0x69,0x7E,0x7A,0xBA,0x00,
+    0x88,0x82,0xE5,0x69,0x55,0x57,0xBF,0x28,0x67,0x7A,0xE5,0x69,0xBD,0x5D,0xB7,0x00,
+    0xA8,0x82,0xE5,0x61,0x57,0xFF,0xAB,0x82,0x87,0x7A,0x63,0x51,0x5F,0x7E,0xFA,0xA8,
+    0xA5,0x59,0x23,0x49,0xD7,0xFF,0xFA,0xE0,0x64,0x51,0x43,0x49,0x65,0xFA,0xF8,0x7D,
+    0x64,0x51,0x03,0x41,0xA0,0xA2,0xF2,0x7E,0x23,0x49,0xC2,0x30,0xB8,0xFA,0x5A,0xFA,
+    0x23,0x41,0xE2,0x38,0x2B,0x2B,0x8B,0xA5,0x64,0x49,0x03,0x41,0x3F,0xED,0xFA,0x7B,
+    0x43,0x49,0xE3,0x38,0x28,0xA2,0xFA,0x7E,0x23,0x41,0xA1,0x30,0x80,0xFA,0x76,0x5F,
+    0x03,0x41,0x81,0x28,0x28,0xAF,0xA5,0x25,0x44,0x49,0xC2,0x38,0xFF,0xF5,0xAF,0x0A,
+    0xE6,0x61,0x03,0x41,0x29,0x3D,0x2F,0x2F,0x67,0x7A,0x06,0x6A,0x9D,0xBF,0xC2,0x63,
+    0x67,0x7A,0x27,0x72,0x20,0x08,0xBF,0x75,0x68,0x7A,0x06,0x6A,0xA0,0xE0,0x6C,0xAA,
+    0x47,0x7A,0xE5,0x69,0xA0,0xFE,0x5F,0x5E,0x06,0x72,0x84,0x59,0xE0,0xE8,0xFE,0x7E,
+    0xE5,0x61,0x84,0x59,0x2D,0x35,0xFF,0xBD,0xE6,0x69,0x84,0x59,0x28,0x0A,0xFB,0x5E,
+    0xE6,0x61,0x84,0x59,0xA0,0x80,0xAD,0x7D,0xA4,0x59,0x03,0x41,0xFE,0x7E,0x7C,0x7E,
+    0x23,0x49,0x03,0x41,0x2B,0xD5,0xDF,0xDB,0x84,0x51,0x23,0x49,0xBD,0x25,0x25,0x25,
+    0x47,0x72,0xA5,0x59,0xBD,0x09,0x2B,0x2B,0x47,0x72,0xA4,0x61,0xAA,0xF8,0x7C,0x5C,
+    0x88,0x7A,0xE5,0x69,0x2B,0x0D,0x2D,0x25,0x0A,0x8B,0xA8,0x82,0xE5,0x8B,0x8B,0x2A,
+    0xE9,0x8A,0x26,0x72,0xF2,0xEA,0x78,0x78,0x87,0x7A,0x05,0x6A,0x08,0x2F,0xBF,0xBD,
+    0x4A,0x93,0x67,0x7A,0x0B,0x2F,0xF5,0xD5,0x2D,0xAC,0xC8,0x82,0x2F,0xBF,0xD5,0xF5,
+    0xB7,0xF6,0xCC,0xA3,0x0B,0x2B,0x2D,0xAD,0xD8,0xFE,0x51,0xD5,0x00,0x00,0xA2,0x5F,
+    0xD7,0xF6,0x72,0xD5,0x00,0x00,0x02,0xAD,0xF8,0xFE,0x96,0xEE,0x00,0x08,0x2A,0xFD,
+    0xF8,0xFE,0xD7,0xF6,0xAA,0xA8,0xBB,0xA5,0xF8,0xFE,0xD7,0xF6,0xAA,0xAA,0xBE,0xAE,
+    0xF8,0xFE,0xD7,0xF6,0xDB,0xFF,0xFA,0xDA,0xF8,0xFE,0xD7,0xF6,0xAA,0xAE,0xAF,0x9B,
+    0xF8,0xFE,0xF7,0xF6,0xBF,0xEB,0xAA,0x82,0xD8,0xFE,0x17,0xF7,0xFF,0xEE,0xAA,0x8A,
+    0x18,0xFF,0xF8,0xF6,0xEA,0xFE,0xBB,0xFF,0xF8,0xFE,0x18,0xF7,0xAA,0xAE,0x0A,0xA2,
+    0xF8,0xFE,0x18,0xF7,0xBE,0xAA,0x00,0x00,0xF8,0xFE,0x18,0xF7,0xAA,0xAA,0x08,0x22,
+    0x18,0xFF,0xD7,0xF6,0xEA,0xBA,0xFD,0xBB,0x18,0xFF,0xB7,0xF6,0x7F,0x7F,0x76,0x7F,
+    0xD8,0xFE,0xB7,0xEE,0xAA,0xEA,0x7A,0x7F,0xB6,0xF6,0x96,0xEE,0xA8,0xEA,0xE0,0xEA,
+    0xB6,0xF6,0x96,0xEE,0x5F,0xDE,0x7E,0x7B,0x96,0xEE,0x76,0xEE,0xA0,0x28,0x5D,0x5F,
+    0x96,0xF6,0x76,0xEE,0x5A,0xF4,0xED,0xEF,0x96,0xF6,0x55,0xEE,0x55,0x7E,0xE2,0x80,
+    0x76,0xEE,0x55,0xEE,0xA9,0xEF,0xE8,0xF0,0x75,0xEE,0x56,0xEE,0xAA,0xDF,0x55,0x97,
+    0x97,0xF6,0x56,0xEE,0xFE,0xEE,0xEB,0xFE,0x76,0xEE,0x35,0xE6,0x8F,0x2E,0x0E,0x02,
+    0x76,0xEE,0x55,0xEE,0x2D,0xF7,0xBE,0x00,0x76,0xEE,0x55,0xEE,0xFE,0xFC,0xFF,0xBE,
+    0x76,0xEE,0x55,0xEE,0xDE,0xDB,0xAB,0xA2,0x76,0xEE,0x55,0xEE,0x0D,0x2E,0xBA,0xB6,
+    0x75,0xEE,0x35,0xE6,0x76,0x5C,0xBC,0xEE,0x75,0xEE,0x34,0xEE,0xB5,0xAF,0xAB,0x22,
+    0x75,0xEE,0x55,0xEE,0x62,0xC5,0x20,0xFA,0x55,0xEE,0x14,0xE6,0xAB,0xBF,0xFC,0x9A,
+    0x75,0xEE,0x34,0xE6,0xE9,0xEB,0x7B,0x7F,0x14,0xE6,0xB3,0xD5,0xF8,0xF8,0x7C,0x78,
+    0xF3,0xDD,0xB3,0xD5,0xD6,0xB7,0xED,0xAB,0x34,0xE6,0xD3,0xDD,0x2B,0x2D,0xAD,0xAD,
+    0x35,0xEE,0x14,0xE6,0x2D,0x2B,0x2A,0x09,0x34,0xE6,0xF3,0xE5,0x78,0xB8,0x20,0x00,
+    0x55,0xEE,0x51,0xCD,0x7F,0x7A,0x7A,0xE0,0x72,0xD5,0xF0,0xC4,0x5F,0xFB,0xFA,0xA8,
+    0x31,0xC5,0xAF,0xBC,0xFE,0xDA,0xFC,0xFA,0x10,0xC5,0xD0,0xBC,0xF5,0xAD,0x8B,0x00,
+    0x31,0xC5,0xF0,0xC4,0xB5,0xA5,0xA2,0x2A,0x52,0xCD,0x10,0xC5,0xE9,0x7F,0xBF,0x0A,
+    0x31,0xCD,0x8F,0xBC,0x60,0x82,0x00,0x00,0xD0,0xBC,0xC8,0x82,0x5F,0x5E,0x7C,0x78,
+    0x6B,0x93,0xA8,0x7A,0x3F,0xBD,0x35,0xB5,0xAF,0xBC,0x8B,0x93,0x09,0x29,0x0B,0x09,
+    0xF0,0xC4,0xAE,0xB4,0x03,0x0B,0xEF,0xE7,0xF0,0xC4,0xCF,0xBC,0x28,0x60,0x8A,0xD8,
+    0x30,0xCD,0xD0,0xBC,0x3B,0xAB,0xFF,0x7F,0x51,0xCD,0xF0,0xC4,0xAA,0x8B,0xEF,0xE5,
+    0x51,0xCD,0xF0,0xC4,0xA8,0xEA,0xDF,0x7F,0x51,0xCD,0xF0,0xC4,0xAB,0xA3,0xFE,0x7E,
+    0x45,0x6A,0xE4,0x69,0xEB,0xFF,0x6E,0xB8,0x45,0x6A,0x05,0x62,0xFF,0x7F,0xDF,0xAA,
+    0x45,0x6A,0x05,0x6A,0x9A,0xFB,0xEA,0xBA,0x46,0x6A,0xE5,0x61,0x52,0x7A,0xBE,0xB8,
+    0x66,0x6A,0x05,0x6A,0x2D,0xEF,0x55,0x76,0xA7,0x7A,0x05,0x62,0x0A,0xBB,0xF5,0xF5,
+    0x87,0x7A,0x25,0x6A,0x02,0x00,0x2E,0x57,0xA7,0x7A,0x26,0x6A,0x80,0x00,0x2A,0xBD,
+    0xC7,0x7A,0x87,0x7A,0xB5,0xFF,0x9D,0x57,0xA7,0x7A,0x87,0x7A,0x09,0xD3,0x14,0x13,
+    0xC7,0x82,0x66,0x7A,0x7E,0xEB,0xEE,0xFA,0xA7,0x7A,0x67,0x7A,0x2A,0xB3,0xAB,0xBE,
+    0xA7,0x7A,0x87,0x7A,0xAF,0xB7,0x27,0xB5,0xA7,0x7A,0x87,0x7A,0x57,0xF4,0xC3,0xAB,
+    0xC7,0x82,0x66,0x72,0xBE,0xAF,0xAD,0xBE,0xA7,0x7A,0x66,0x7A,0x2D,0x88,0x00,0x0C,
+    0xC7,0x82,0x87,0x7A,0x77,0xFC,0xEA,0xAE,0xA7,0x7A,0x46,0x72,0xAB,0x89,0x02,0x08,
+    0xA7,0x7A,0x66,0x72,0x57,0xEE,0x88,0x02,0xA7,0x7A,0x66,0x72,0x77,0xFF,0xFA,0xF2,
+    0xC7,0x82,0x46,0x72,0xDF,0xDF,0xFB,0xB8,0x86,0x7A,0x24,0x6A,0xA6,0x8A,0x8A,0xB0,
+    0x87,0x7A,0x46,0x72,0x8D,0x6B,0x68,0xCB,0xE8,0x82,0x45,0x72,0x2B,0xAF,0xD7,0x5F,
+    0x08,0x8B,0x66,0x72,0x02,0xA2,0xAF,0x57,0xE8,0x82,0xA7,0x7A,0xA0,0x00,0x0E,0x35,
+    0xE8,0x82,0xA7,0x82,0x2F,0x08,0x20,0xE8,0xE8,0x82,0xA6,0x7A,0xEA,0xFA,0x02,0xCE,
+    0xC7,0x7A,0x63,0x51,0x5A,0x58,0xE8,0x80,0xA4,0x59,0xC2,0x38,0xD7,0xD7,0x7E,0xF8,
+    0xE2,0x40,0xC2,0x38,0x57,0x57,0x5E,0x60,0xE2,0x38,0x81,0x38,0x7A,0xFA,0xA8,0xA0,
+    0xE3,0x40,0x81,0x38,0x2D,0x0F,0xAB,0x02,0x44,0x59,0xC2,0x40,0x95,0xB9,0x0B,0x2F,
+    0xA5,0x61,0x23,0x51,0xBD,0xAF,0x2F,0x2B,0x47,0x7A,0xC5,0x69,0xBD,0x2D,0xA9,0x85,
+    0xA8,0x82,0x47,0x7A,0x03,0x5B,0x7D,0xF5,0xC9,0x82,0x47,0x72,0xA2,0x7B,0x7D,0xBF,
+    0x88,0x82,0x06,0x6A,0x08,0xE8,0x5F,0xEC,0xA8,0x82,0xC4,0x69,0x00,0x02,0xBD,0xB7,
+    0xE9,0x8A,0x27,0x72,0x82,0x02,0xAF,0x7F,0x67,0x7A,0xC5,0x59,0xA8,0xDC,0x78,0xFE,
+    0x27,0x6A,0x44,0x49,0x68,0xE0,0xEB,0x57,0x64,0x51,0xC2,0x38,0xA8,0xFC,0xFE,0x7F,
+    0x23,0x41,0xC2,0x38,0xA0,0xAA,0x7D,0x5B,0x03,0x39,0xC2,0x38,0xAA,0xAF,0xAD,0xAD,
+    0x03,0x41,0xE2,0x38,0x37,0xF6,0x32,0xBE,0x24,0x41,0xE3,0x38,0xC0,0xE2,0x7B,0x57,
+    0xE3,0x38,0xA2,0x30,0xE0,0x48,0xAC,0x80,0xC2,0x38,0x81,0x30,0xDE,0xDF,0xCA,0x80,
+    0x44,0x49,0xA1,0x30,0xB5,0xF5,0x3D,0x0B,0xA5,0x59,0x03,0x41,0xAD,0xAD,0x2F,0x0A,
+    0xC6,0x61,0x64,0x51,0x25,0xBF,0xFE,0xFA,0x26,0x72,0x84,0x59,0x22,0x89,0xBD,0xB5,
+    0x67,0x7A,0xE6,0x69,0xA9,0x0B,0x23,0xFD,0x88,0x82,0x26,0x72,0xE0,0xE0,0xFA,0xFD,
+    0x26,0x72,0xA4,0x61,0xA0,0x88,0x80,0x7A,0xE6,0x69,0x84,0x59,0xD8,0xDA,0xD6,0x55,
+    0xC5,0x59,0x84,0x59,0xB7,0xB5,0x2D,0x09,0xE6,0x61,0x85,0x59,0xFA,0xA3,0xEB,0xDE,
+    0xA5,0x59,0x44,0x49,0xE8,0x80,0xE8,0x7E,0x64,0x51,0x03,0x41,0x68,0x7A,0x7A,0x7A,
+    0x24,0x49,0xE3,0x40,0xAF,0xBF,0xFB,0xBF,0xE6,0x61,0x03,0x49,0xAD,0xA5,0xAF,0x2F,
+    0x47,0x72,0xE6,0x61,0xA5,0xA3,0x8F,0xE3,0x68,0x7A,0xC5,0x61,0x5B,0xB7,0x2F,0x2F,
+    0xA8,0x82,0x26,0x72,0xAD,0x8E,0x02,0x8A,0xC9,0x8A,0x26,0x72,0x02,0xA8,0xFE,0x7E,
+    0x88,0x82,0x26,0x72,0x60,0xA2,0xAE,0x27,0xC8,0x8A,0x26,0x72,0x95,0x3E,0x0A,0x08,
+    0x09,0x8B,0x66,0x7A,0xFD,0xAF,0xAE,0x2A,0x0A,0x8B,0xA8,0x82,0x2F,0x2E,0xAA,0x78,
+    0x2E,0xB4,0x88,0x7A,0x0B,0xBF,0x55,0x55,0x4D,0xB4,0xA7,0x82,0x00,0xBE,0x75,0x55,
+    0x31,0xCD,0x09,0x8B,0x2A,0xBF,0xFD,0x55,0x15,0xE6,0x2A,0x93,0x00,0x2A,0xAF,0xF5,
+    0xD7,0xFE,0xD0,0xC4,0x00,0x0A,0x2B,0xFD,0xD7,0xFE,0x11,0xCD,0x00,0x00,0xAA,0xD5,
+    0xD7,0xFE,0x94,0xDD,0x00,0x00,0x02,0xBD,0xF8,0xFE,0x96,0xF6,0xAA,0x2A,0xBB,0xF5,
+    0xF8,0xFE,0xD7,0xF6,0x82,0xA0,0xA0,0x5B,0xF8,0xFE,0xB7,0xF6,0x32,0xA2,0x8A,0xFF,
+    0xF8,0xFE,0xD7,0xF6,0x28,0x2E,0x8A,0xE5,0x18,0xFF,0xD7,0xF6,0xAA,0xBA,0xAB,0xFF,
+    0xF8,0xFE,0xD8,0xF6,0xEA,0xAA,0xAA,0xB8,0xF8,0xFE,0xD7,0xF6,0x0A,0xA8,0x82,0xAA,
+    0xF8,0xFE,0xB7,0xF6,0xA0,0xFA,0xE8,0x7A,0xD7,0xF6,0xB7,0xF6,0x7C,0xFE,0x5F,0x55,
+    0xB7,0xF6,0x96,0xEE,0xE0,0xE8,0xF2,0x7A,0xB7,0xF6,0x76,0xEE,0xAA,0xFA,0x5B,0x7F,
+    0x96,0xEE,0x55,0xEE,0x00,0x8A,0xDD,0xF7,0x76,0xEE,0x55,0xEE,0x20,0x00,0xA2,0xBF,
+    0x55,0xF6,0x76,0xEE,0x55,0x5F,0x77,0xFE,0x96,0xF6,0x76,0xEE,0xE2,0xFF,0x7D,0x5D,
+    0x76,0xEE,0x55,0xEE,0xE8,0xCA,0xB7,0x43,0x96,0xF6,0x56,0xEE,0xF5,0xFD,0xAF,0x2B,
+    0x96,0xF6,0x56,0xEE,0x5E,0x7E,0xEA,0xE8,0x55,0xF6,0x76,0xEE,0x75,0x55,0x76,0xFE,
+    0x96,0xF6,0x76,0xEE,0x7F,0xFE,0xEA,0x6A,0x56,0xF6,0x76,0xEE,0xF7,0xFD,0xDD,0xD5,
+    0x75,0xEE,0x56,0xEE,0xA8,0x9A,0xFA,0xFB,0x76,0xEE,0x55,0xEE,0x26,0xFE,0xEA,0x28,
+    0x76,0xEE,0x55,0xEE,0xFE,0xBE,0x3F,0xD5,0x75,0xEE,0x55,0xEE,0xFE,0x0C,0x80,0xCB,
+    0x76,0xEE,0x34,0xE6,0xAA,0xBA,0x7E,0xFF,0x55,0xEE,0x14,0xE6,0xB2,0xA8,0xEA,0xAE,
+    0x55,0xEE,0x34,0xE6,0x70,0x6B,0x61,0x7F,0x14,0xE6,0x92,0xD5,0xFC,0xF8,0x7E,0xDE,
+    0xF3,0xDD,0xB3,0xD5,0x0B,0x2F,0xBD,0xB5,0x14,0xE6,0xD3,0xDD,0x2B,0x2E,0xBB,0xAD,
+    0x55,0xEE,0xF4,0xDD,0xCB,0xAB,0x2F,0xB9,0x75,0xEE,0x34,0xE6,0x15,0xA5,0x0B,0xA2,
+    0x75,0xEE,0x35,0xE6,0x60,0xEA,0xF6,0xB5,0x55,0xEE,0x93,0xD5,0x5F,0xFE,0xE0,0xA0,
+    0xD3,0xDD,0xF0,0xC4,0x5F,0x7A,0xA8,0x80,0x72,0xCD,0x10,0xC5,0x9D,0xF5,0xBF,0xE0,
+    0x51,0xCD,0x11,0xC5,0xBF,0xBE,0xA2,0x00,0x72,0xCD,0x51,0xCD,0xED,0x6D,0x9D,0x55,
+    0x72,0xCD,0x31,0xCD,0x7F,0x5A,0xEA,0x8F,0x11,0xC5,0x2B,0x8B,0x78,0xE0,0xE0,0x80,
+    0x4A,0x8B,0x67,0x72,0xBF,0xBE,0xBC,0xDC,0x8E,0xB4,0x09,0x83,0x0B,0x2F,0xFD,0xD5,
+    0xAE,0xB4,0x8B,0x93,0x00,0xA8,0xAA,0xFD,0xD0,0xC4,0x6E,0xAC,0x2A,0xBB,0xAF,0x95,
+    0xF0,0xC4,0xAF,0xBC,0xFA,0xDB,0xFD,0x75,0x31,0xCD,0xAF,0xBC,0x0F,0xAF,0xFF,0xF5,
+    0x31,0xCD,0xCF,0xBC,0x2E,0xBE,0x6F,0xFD,0x10,0xC5,0xCF,0xBC,0xE0,0xA8,0xEF,0xD5,
+    0x46,0x6A,0xE5,0x69,0x0A,0xBA,0x88,0xA0,0x46,0x6A,0x25,0x6A,0xF8,0xAA,0x35,0x17,
+    0x46,0x72,0x05,0x62,0xDB,0xEF,0xAA,0x0A,0x66,0x72,0x05,0x6A,0xBA,0xFA,0x5E,0xF3,
+    0x46,0x72,0x05,0x6A,0x7E,0xEF,0x5E,0x2A,0x46,0x72,0x05,0x6A,0xA9,0x2A,0x9A,0xC8,
+    0x46,0x72,0x05,0x6A,0xF5,0x5A,0x73,0xF2,0x45,0x72,0xE4,0x69,0x2A,0xFE,0xFB,0xFA,
+    0x87,0x7A,0x05,0x6A,0x2A,0xF5,0x75,0xFF,0xA7,0x82,0xE5,0x69,0x22,0x0A,0xFB,0xDF,
+    0xA7,0x7A,0x26,0x72,0x20,0x00,0x8A,0xFD,0xC8,0x82,0x87,0x7A,0x57,0x6F,0xF5,0x9D,
+    0xA7,0x7A,0x66,0x7A,0xC2,0x02,0x84,0x88,0xA7,0x7A,0x66,0x72,0x82,0xA8,0x8D,0x0E,
+    0xC7,0x82,0x66,0x72,0x9B,0x1B,0xAB,0xE9,0xC7,0x7A,0x87,0x7A,0xF6,0x76,0x55,0xD7,
+    0xA7,0x7A,0x86,0x7A,0x3E,0x25,0x3B,0xF5,0xC7,0x82,0x87,0x7A,0xDF,0xFB,0xAF,0xEB,
+    0xA7,0x7A,0x45,0x72,0x0A,0xDA,0x8E,0x0B,0xA7,0x7A,0x45,0x72,0xA0,0xDE,0xEC,0x8A,
+    0xA7,0x7A,0x87,0x7A,0xF8,0xBF,0xD5,0x35,0xA7,0x7A,0x87,0x7A,0xB7,0xDA,0xBE,0x2F,
+    0xA7,0x82,0x46,0x72,0x70,0xB2,0x8A,0xB8,0xA7,0x7A,0x66,0x7A,0x56,0xE0,0xFE,0xB4,
+    0xA7,0x7A,0x45,0x72,0x77,0xAF,0xAA,0x28,0xC7,0x82,0x66,0x72,0x25,0x5D,0xEF,0xFD,
+    0xC8,0x82,0x66,0x72,0x03,0xB5,0x55,0xFF,0x08,0x8B,0x66,0x72,0xA8,0x2F,0xFD,0xDD,
+    0xE8,0x82,0x65,0x72,0xE2,0x8A,0x2B,0xAD,0x86,0x72,0x03,0x49,0x7E,0xF8,0xE0,0x80,
+    0xA4,0x59,0xE2,0x40,0x55,0x57,0x5E,0xF8,0x03,0x49,0xC2,0x40,0x7E,0x5A,0xF8,0x80,
+    0x43,0x49,0xE3,0x40,0xDD,0x15,0xBD,0xF5,0x84,0x59,0x03,0x49,0xFD,0xAE,0xAA,0x8B,
+    0x84,0x59,0xE2,0x48,0x0A,0xB7,0x5E,0x7E,0xE6,0x69,0xE3,0x48,0x0A,0xAF,0xFD,0x75,
+    0x27,0x72,0x23,0x51,0x08,0xBF,0xF5,0xD5,0xA9,0x82,0x44,0x59,0x0A,0xAA,0xFF,0x5D,
+    0x88,0x7A,0x85,0x61,0x00,0x08,0x8B,0xF5,0x88,0x82,0xC5,0x61,0xAA,0x00,0xA2,0x55,
+    0x87,0x7A,0xC5,0x61,0xE2,0xE8,0x7A,0x55,0x06,0x6A,0x64,0x51,0x80,0xAE,0x5F,0x77,
+    0xA5,0x59,0x03,0x41,0xFC,0xFE,0x57,0x57,0x23,0x41,0xE3,0x38,0x56,0xFA,0xFA,0xB5,
+    0x03,0x39,0xC2,0x38,0xDE,0x5E,0xF8,0x28,0xE2,0x40,0x03,0x39,0x7A,0x76,0xD7,0xD5,
+    0xE2,0x48,0x03,0x39,0x77,0xD7,0xFD,0x57,0x44,0x41,0xC2,0x38,0xF7,0xBA,0xAA,0xB2,
+    0x03,0x39,0xA2,0x30,0xE8,0x7A,0xF0,0xE2,0xE2,0x38,0xA2,0x30,0xFD,0x37,0xFF,0xB9,
+    0x44,0x49,0xC2,0x38,0x0B,0x29,0x09,0x29,0xC5,0x59,0x64,0x51,0x2B,0xC9,0x8D,0xA9,
+    0xC5,0x69,0x64,0x51,0xFF,0xFF,0xFF,0x2E,0x06,0x72,0x64,0x59,0x89,0x0B,0xA9,0xFA,
+    0xE5,0x69,0x84,0x59,0x00,0x00,0x08,0xDD,0x47,0x72,0xA4,0x61,0x8B,0xB7,0x97,0xD5,
+    0x06,0x6A,0x64,0x59,0xE8,0xFA,0xFA,0x5E,0x85,0x59,0x64,0x51,0x0F,0xB8,0x98,0xEF,
+    0xC5,0x61,0x64,0x51,0xC9,0xA7,0xBF,0xB5,0xE6,0x61,0x84,0x51,0x7F,0xE8,0x82,0xC2,
+    0xA4,0x59,0x24,0x49,0xEA,0xE0,0xE8,0x7E,0x43,0x49,0x02,0x41,0x78,0xAE,0xAA,0xE2,
+    0x64,0x51,0xE2,0x38,0xBD,0xAD,0x3F,0x2A,0xE6,0x61,0x44,0x49,0x2D,0x2B,0xAB,0xAF,
+    0x47,0x72,0xC6,0x61,0xA2,0x8B,0x3F,0xF5,0x88,0x7A,0x26,0x6A,0xBD,0xEF,0xE8,0x01,
+    0x88,0x82,0x26,0x72,0x8B,0xBA,0xDE,0xEA,0x88,0x82,0xE5,0x69,0xF0,0x7E,0xFF,0xD7,
+    0x67,0x7A,0xE5,0x69,0x27,0x0D,0x88,0x02,0xE9,0x8A,0x47,0x72,0x2A,0x0F,0x2D,0xB5,
+    0x2A,0x93,0xC9,0x8A,0x3B,0xAB,0xEF,0x6F,0x09,0x8B,0x67,0x7A,0xE8,0xA8,0xFA,0x5E,
+    0x88,0x7A,0xE5,0x69,0xA8,0x78,0xBA,0xA7,0xC8,0x82,0x26,0x72,0x2B,0xBD,0xBF,0xBD,
+    0xE9,0x8A,0x05,0x72,0x82,0xEA,0x5E,0x5E,0x6B,0x9B,0x47,0x72,0x2B,0x25,0xB5,0xF5,
+    0x2D,0xAC,0x88,0x7A,0x00,0xFB,0x7F,0x5F,0x8B,0x9B,0x68,0x7A,0x08,0xDF,0x55,0x55,
+    0x92,0xD5,0x88,0x7A,0x0B,0xBF,0xFD,0xD5,0x75,0xEE,0x6B,0x93,0x02,0xAB,0xFF,0x55,
+    0xD7,0xFE,0x6B,0x93,0x00,0xAA,0xFF,0x55,0xB6,0xF6,0x6A,0x93,0x00,0xAA,0xFF,0xF5,
+    0xB6,0xF6,0xCF,0xBC,0x00,0x0A,0xAF,0xA5,0xD7,0xF6,0xF4,0xE5,0x00,0x02,0x8A,0xFD,
+    0xF8,0xFE,0x76,0xEE,0x80,0x02,0x2A,0xD5,0xF8,0xFE,0xB7,0xF6,0xE2,0xA8,0xAA,0xF5,
+    0xD7,0xF6,0xB7,0xF6,0x78,0x78,0x58,0x75,0xB7,0xF6,0x96,0xEE,0x80,0x08,0xE8,0x7F,
+    0xB6,0xF6,0x76,0xEE,0xAA,0xFE,0x7F,0x77,0x96,0xEE,0x55,0xEE,0xF0,0xF8,0x7A,0xBE,
+    0x76,0xF6,0x55,0xE6,0xFB,0x2B,0x8A,0xAC,0x96,0xF6,0x55,0xEE,0xFF,0xFB,0xE8,0xFA,
+    0x76,0xEE,0x35,0xEE,0xA8,0xE8,0xFA,0xFE,0x76,0xEE,0x35,0xEE,0x02,0x0F,0xAF,0xAA,
+    0x96,0xF6,0x76,0xEE,0x75,0x5D,0xFD,0xB5,0x57,0xF6,0x75,0xEE,0x5F,0x5F,0xDD,0xFD,
+    0x96,0xF6,0x56,0xEE,0xFA,0xAB,0x8B,0x8B,0x96,0xF6,0x56,0xEE,0xFD,0xEF,0xAA,0xEA,
+    0x96,0xF6,0x76,0xEE,0xEF,0x3B,0x2F,0x8F,0xB6,0xF6,0x76,0xEE,0x7D,0xEF,0xEB,0x7F,
+    0x76,0xEE,0x35,0xEE,0xA8,0xF0,0xB8,0xFA,0x75,0xEE,0x35,0xEE,0xAA,0x8D,0xFB,0xFF,
+    0x76,0xEE,0x55,0xEE,0x55,0x55,0xE5,0x85,0x75,0xEE,0x35,0xEE,0xEE,0x88,0x22,0x23,
+    0x75,0xEE,0x35,0xE6,0xFF,0xE3,0x20,0x80,0x55,0xEE,0x35,0xE6,0xEB,0xEA,0xEC,0xF4,
+    0x55,0xEE,0xF4,0xDD,0xAA,0xC0,0xEA,0x6A,0xF3,0xDD,0x72,0xCD,0xDC,0xFA,0x7A,0x7E,
+    0xD3,0xDD,0x72,0xCD,0x8F,0xB7,0xBF,0xAF,0x14,0xE6,0xB3,0xD5,0x0B,0x2F,0x2D,0xAB,
+    0x34,0xE6,0xF4,0xDD,0x2B,0x8A,0xFF,0x77,0x55,0xEE,0xF4,0xDD,0x82,0xFF,0xFD,0xFD,
+    0x76,0xEE,0x14,0xE6,0xAD,0xAF,0x2D,0x0F,0x96,0xF6,0x34,0xE6,0x7A,0xEA,0xA2,0x20,
+    0x96,0xF6,0xF3,0xDD,0xDD,0xAA,0x82,0x08,0x96,0xF6,0x72,0xD5,0x5F,0xFA,0xE0,0x80,
+    0x14,0xE6,0x51,0xCD,0x55,0x55,0x57,0xF8,0x72,0xD5,0x31,0xC5,0xEB,0xE7,0xEA,0xE8,
+    0x72,0xD5,0x31,0xC5,0x2A,0xA3,0xAF,0xA6,0x72,0xCD,0xD0,0xBC,0x78,0xE8,0x80,0x82,
+    0xD0,0xBC,0x67,0x72,0x5E,0x7C,0x78,0xC0,0xA8,0x7A,0xE6,0x61,0x8A,0x7F,0x5F,0xFE,
+    0xAB,0x9B,0x05,0x62,0x0B,0xB5,0x55,0x55,0x6E,0xAC,0x47,0x72,0x02,0x0A,0xAB,0xF5,
+    0xAF,0xBC,0xEC,0xA3,0x02,0x22,0xBB,0xE5,0xCF,0xBC,0x2E,0xAC,0x80,0x0A,0xBF,0x57,
+    0xD0,0xBC,0x4E,0xAC,0x80,0x28,0xAA,0xA5,0x10,0xC5,0xAF,0xBC,0x9D,0x97,0x3B,0xA5,
+    0x66,0x72,0x25,0x6A,0x6B,0xEA,0x7A,0xBA,0x46,0x72,0x05,0x6A,0x0D,0x82,0x00,0x2C,
+    0x67,0x72,0x25,0x6A,0xE6,0xD3,0x6F,0xE7,0x66,0x72,0x25,0x6A,0x3A,0x1B,0x91,0x8F,
+    0x46,0x72,0x05,0x6A,0xBA,0xFA,0xEE,0x40,0x26,0x6A,0x05,0x6A,0xA2,0x81,0x17,0xBD,
+    0x46,0x72,0xE4,0x61,0xFE,0xFA,0xA2,0x2A,0x67,0x72,0xE5,0x69,0x9D,0xBF,0x2F,0xFE,
+    0x46,0x72,0xE4,0x61,0xA8,0x8A,0x30,0x18,0x46,0x72,0x05,0x6A,0xFF,0xFD,0x6A,0x28,
+    0x46,0x72,0x05,0x6A,0xA0,0x60,0xBE,0x3C,0x87,0x7A,0x05,0x6A,0x0B,0x57,0xD7,0xFF,
+    0xA7,0x7A,0x05,0x6A,0x08,0xAA,0x67,0x57,0xA7,0x7A,0x05,0x6A,0x20,0x82,0xAB,0xBD,
+    0xA7,0x82,0x46,0x72,0xC3,0x23,0x2A,0xB9,0xC7,0x82,0x87,0x7A,0xDD,0xF7,0xDF,0x79,
+    0xC7,0x82,0x66,0x72,0x77,0xAE,0xEA,0xE3,0xC7,0x82,0x66,0x72,0x8B,0xAE,0xBB,0xDF,
+    0xC7,0x82,0x87,0x7A,0x79,0xEA,0xE2,0x62,0xC7,0x82,0x66,0x72,0x29,0xAA,0xFF,0x7F,
+    0xC7,0x82,0x87,0x7A,0xF7,0x6D,0xF9,0x7A,0xC8,0x82,0x66,0x7A,0xF9,0xBE,0xBA,0xA3,
+    0xC7,0x82,0x67,0x7A,0xFF,0xAA,0x6A,0xFA,0xC8,0x82,0x87,0x7A,0xDD,0xDD,0x68,0xF6,
+    0xA7,0x7A,0x86,0x7A,0x6D,0x83,0x0B,0x0E,0xC6,0x82,0x65,0x72,0xDE,0xEE,0xE8,0xB8,
+    0xC7,0x82,0x66,0x72,0x56,0xFF,0xAB,0x8A,0xC7,0x82,0x66,0x72,0x77,0x7F,0xAA,0x2E,
+    0xA7,0x7A,0x66,0x72,0xFD,0xFF,0x78,0xC0,0xA6,0x7A,0x66,0x72,0x5E,0x65,0xEB,0xE9,
+    0x66,0x72,0x44,0x51,0x7E,0x78,0xE8,0xA0,0xA6,0x61,0xE3,0x40,0x7F,0xFA,0xE8,0xA8,
+    0xA5,0x59,0x23,0x49,0x55,0x77,0xFF,0xFE,0x64,0x59,0x23,0x51,0x2E,0xBA,0xDA,0xE2,
+    0x44,0x51,0x03,0x51,0x60,0x00,0xE0,0xA0,0x44,0x51,0xC2,0x40,0xFF,0x76,0xFE,0x2A,
+    0x03,0x49,0xC2,0x40,0x2B,0x87,0xE7,0x0C,0x85,0x61,0x03,0x49,0xE2,0xFD,0xD9,0xFD,
+    0xC6,0x61,0x24,0x49,0x2E,0xA7,0xBF,0xED,0xC6,0x61,0x24,0x49,0xA0,0xAA,0xFF,0x7F,
+    0xA6,0x61,0x44,0x49,0x78,0x5E,0xFF,0xFB,0x85,0x51,0xE2,0x38,0x82,0xF8,0xDA,0x7E,
+    0x03,0x41,0xA1,0x30,0x80,0xEA,0x7A,0x5F,0xE2,0x38,0xA2,0x30,0x0C,0x2B,0x2F,0x29,
+    0x23,0x41,0xE3,0x38,0xF7,0xAA,0xAA,0xBA,0x44,0x41,0x03,0x41,0x55,0xF5,0x8B,0xE8,
+    0x44,0x41,0x03,0x41,0xBF,0x3F,0x27,0x17,0x44,0x41,0xE2,0x38,0x6A,0xF0,0xE0,0xE0,
+    0xC2,0x40,0x03,0x39,0xE7,0xAF,0xAD,0xFB,0x23,0x41,0xC2,0x38,0x65,0xBF,0x8D,0x0A,
+    0x84,0x59,0x03,0x41,0x9D,0xA9,0x0F,0x0B,0xC5,0x61,0x64,0x51,0xBD,0x37,0x2A,0x2A,
+    0x26,0x72,0xC5,0x61,0xE5,0xFF,0xFF,0x2F,0x06,0x72,0xA4,0x61,0x78,0x78,0x78,0xAE,
+    0x06,0x72,0x84,0x59,0xF7,0xDF,0xFB,0x8A,0xE5,0x61,0xA4,0x61,0xF7,0x3D,0x2D,0xD7,
+    0xC5,0x61,0x23,0x49,0xF8,0x78,0x78,0x68,0x85,0x51,0x03,0x49,0x0A,0xBB,0xFF,0xF5,
+    0x64,0x51,0x23,0x49,0x20,0xB0,0xFD,0xB7,0xE6,0x61,0x64,0x51,0x83,0xBA,0xFD,0xD5,
+    0x85,0x51,0x02,0x41,0x7E,0x5E,0x5C,0x78,0x43,0x49,0x03,0x41,0xA9,0xA5,0xAD,0xAD,
+    0xA5,0x59,0x44,0x49,0x2D,0x0B,0x09,0xAD,0xA5,0x59,0x44,0x51,0xAA,0x6E,0x7C,0x58,
+    0xE6,0x69,0x23,0x49,0x0A,0xBF,0xFF,0xFD,0x68,0x7A,0x85,0x59,0x02,0x0B,0x2D,0x2D,
+    0xA9,0x8A,0x47,0x7A,0x7E,0x6A,0xF3,0xAF,0x88,0x82,0xC5,0x69,0xD5,0xFF,0xEA,0x80,
+    0x67,0x7A,0x05,0x72,0x8B,0x2A,0x2B,0xE7,0xA8,0x82,0x26,0x6A,0x27,0x27,0xBA,0x7A,
+    0xC9,0x8A,0x47,0x72,0x0A,0xAF,0xBB,0xA5,0xA8,0x82,0x46,0x72,0x60,0xE8,0x7E,0x57,
+    0x88,0x82,0x06,0x6A,0xB7,0xB7,0xAF,0x0E,0xA8,0x82,0x47,0x7A,0xB5,0xFD,0xEA,0x80,
+    0x88,0x7A,0x26,0x72,0x7C,0xFA,0xB8,0x88,0x88,0x82,0x26,0x72,0x29,0xAA,0xAE,0x82,
+    0xC9,0x8A,0x47,0x7A,0xE2,0xFF,0x5D,0x77,0x88,0x7A,0x47,0x7A,0x3B,0x2B,0x0D,0x5E,
+    0xA8,0x82,0x27,0x72,0x0A,0xB7,0x75,0x57,0xC9,0x82,0x06,0x6A,0x00,0xAA,0xFF,0xD5,
+    0xC9,0x82,0x27,0x6A,0x80,0x2A,0x9F,0xD5,0xCC,0x9B,0x68,0x72,0x0F,0xAF,0xFD,0xD5,
+    0xD0,0xBC,0x46,0x72,0x02,0x2A,0x7F,0x55,0x11,0xC5,0x46,0x72,0x00,0xBE,0xDD,0x55,
+    0xF4,0xE5,0xC8,0x7A,0x02,0x2B,0xAF,0xF5,0x76,0xEE,0x4E,0xAC,0x00,0x00,0x0B,0xBD,
+    0x96,0xF6,0xD3,0xDD,0x00,0x00,0xAA,0xAD,0x96,0xF6,0x55,0xEE,0x80,0x20,0xEF,0xFB,
+    0x96,0xF6,0x56,0xEE,0xEA,0xFE,0x9F,0x5F,0x55,0xF6,0x76,0xEE,0x55,0x55,0xDD,0xFF,
+    0x76,0xF6,0x35,0xE6,0xE0,0x7E,0xDB,0xFF,0x75,0xEE,0x34,0xE6,0xE0,0xD9,0xF7,0x57,
+    0x55,0xEE,0x14,0xE6,0x88,0xAA,0xFE,0xFF,0x75,0xEE,0x34,0xE6,0xAB,0xEF,0xD5,0x55,
+    0x96,0xF6,0x35,0xE6,0x2A,0xEA,0xAD,0xF5,0x75,0xEE,0x34,0xEE,0xA8,0xFA,0xFF,0x7F,
+    0x96,0xF6,0x34,0xE6,0x8B,0xBB,0xF7,0x55,0x96,0xF6,0x34,0xE6,0x8A,0xAA,0xBF,0xF5,
+    0x96,0xF6,0x35,0xE6,0x80,0xEA,0xFE,0x5D,0x75,0xEE,0x35,0xE6,0x88,0xFE,0xFF,0x55,
+    0x75,0xEE,0x35,0xE6,0xBE,0x1A,0xAF,0xB5,0x76,0xEE,0x55,0xEE,0xDB,0xF8,0x8A,0x82,
+    0x56,0xF6,0x96,0xEE,0xBE,0xFE,0xFF,0xFE,0x96,0xF6,0x76,0xEE,0x59,0xFE,0xBA,0x2A,
+    0x96,0xF6,0x55,0xEE,0xFF,0xFE,0xFA,0xF8,0x55,0xEE,0x15,0xE6,0xFC,0xFC,0xB8,0xC0,
+    0x55,0xEE,0xD3,0xDD,0x62,0x72,0xA8,0xA8,0xF3,0xDD,0x72,0xCD,0xFE,0xFE,0xFC,0x78,
+    0xD3,0xDD,0x72,0xD5,0x0B,0x2A,0x2B,0x0D,0x14,0xE6,0xD3,0xDD,0xFD,0xDF,0xAF,0xBD,
+    0x14,0xE6,0xD3,0xDD,0x9F,0x3F,0x2E,0x0A,0x55,0xEE,0x14,0xE6,0x7D,0x7F,0xFB,0xAB,
+    0x75,0xEE,0x34,0xE6,0x2D,0xA9,0xA5,0x2B,0x96,0xEE,0x75,0xEE,0x8A,0xE5,0xAD,0x37,
+    0x96,0xEE,0x76,0xEE,0x75,0xEF,0xFE,0xF6,0x96,0xEE,0x76,0xEE,0x57,0x55,0x5A,0x6C,
+    0x55,0xEE,0x92,0xD5,0x78,0xE0,0x80,0x00,0xF4,0xDD,0x72,0xCD,0x55,0xFE,0xFA,0xE8,
+    0xB3,0xDD,0x31,0xCD,0xF7,0xFE,0xEA,0x80,0x72,0xD5,0x51,0xCD,0x3C,0x2E,0x2F,0x23,
+    0xB3,0xD5,0xED,0xA3,0x6A,0xE8,0xA8,0x00,0xB0,0xBC,0x27,0x6A,0x57,0x5E,0xFE,0xE8,
+    0x89,0x7A,0xE6,0x61,0xDD,0xEE,0xAA,0x00,0x88,0x7A,0x06,0x6A,0x3D,0xFF,0xDE,0xA0,
+    0xEC,0x9B,0x26,0x6A,0x0B,0x95,0xD5,0xD5,0x0E,0xA4,0x68,0x72,0x00,0xAA,0xFF,0x55,
+    0x4E,0xAC,0x89,0x72,0x22,0x0A,0x2F,0x25,0x10,0xC5,0x8E,0xB4,0x2D,0xA9,0x0D,0xA9,
+    0x66,0x72,0x26,0x6A,0x7A,0xA8,0x3A,0xF2,0x66,0x72,0x04,0x6A,0xA6,0xA3,0xFE,0xFA,
+    0x66,0x72,0x25,0x6A,0xAA,0xAE,0xBB,0xFB,0x67,0x72,0x26,0x72,0xAF,0xAF,0x83,0x6E,
+    0x67,0x72,0x05,0x6A,0xEE,0xAB,0x8B,0x89,0x66,0x72,0x05,0x6A,0x7A,0xFB,0xAF,0x28,
+    0x66,0x72,0x05,0x6A,0xBB,0xA7,0xEE,0x32,0x66,0x72,0x05,0x6A,0xFF,0xAA,0xA8,0x9E,
+    0x66,0x72,0x25,0x6A,0xDF,0xA3,0x62,0x7A,0x86,0x72,0x26,0x6A,0x5F,0x5F,0xFB,0xEB,
+    0x46,0x72,0x05,0x6A,0x1E,0x2F,0xAB,0xAE,0x67,0x72,0x26,0x6A,0x9F,0xF7,0xBB,0x8F,
+    0x67,0x72,0x05,0x6A,0x76,0xC7,0xEE,0xF8,0x67,0x72,0x05,0x6A,0xAD,0xFF,0xBB,0xB8,
+    0x87,0x7A,0xE4,0x69,0x2D,0xAF,0xEA,0xEA,0xA7,0x7A,0x05,0x6A,0x02,0xAA,0xAD,0x7F,
+    0xA7,0x7A,0x05,0x6A,0x00,0x00,0xBB,0xF5,0xA7,0x7A,0x66,0x72,0x8E,0x8A,0x0B,0x25,
+    0xE8,0x82,0x86,0x7A,0xFB,0x55,0x5E,0x53,0xA7,0x82,0x87,0x7A,0x55,0x2F,0x2F,0xBB,
+    0xC7,0x82,0x87,0x7A,0xFF,0x5E,0xF8,0xAA,0xA7,0x82,0x67,0x7A,0x8A,0xAE,0x3C,0xB0,
+    0xC7,0x82,0x87,0x7A,0x6B,0xFA,0xFB,0xFA,0xC7,0x82,0x87,0x7A,0xCF,0x7B,0xFE,0x5F,
+    0xC7,0x82,0x86,0x7A,0xBF,0xFB,0xFF,0x2E,0xC7,0x82,0x86,0x7A,0x6F,0xFF,0xB8,0x78,
+    0xC7,0x82,0x86,0x7A,0x4E,0xEE,0xB7,0x35,0xC7,0x82,0xA7,0x7A,0xF5,0xB5,0xBE,0xED,
+    0xA7,0x82,0x87,0x7A,0xB8,0xF3,0x88,0x0A,0xA7,0x82,0x86,0x72,0x7F,0xBC,0x22,0x00,
+    0xA7,0x82,0x06,0x6A,0x7A,0xA2,0xA0,0x80,0x26,0x72,0x64,0x59,0x5E,0x5C,0x78,0xE0,
+    0xC5,0x69,0x64,0x59,0x55,0x75,0xDF,0xAA,0xC5,0x61,0x23,0x51,0x7F,0xDB,0xAA,0x08,
+    0xC5,0x69,0x23,0x51,0x7F,0x7B,0xA8,0xA8,0xC6,0x69,0x44,0x51,0x55,0xF5,0xBF,0x0B,
+    0xA5,0x61,0x03,0x49,0x5F,0xEE,0xA0,0x80,0x85,0x59,0x23,0x49,0xAD,0xA2,0x28,0xE2,
+    0x85,0x51,0x44,0x51,0x8B,0xA2,0xDC,0x56,0x85,0x51,0x23,0x49,0x7A,0xD8,0xFE,0xFF,
+    0x85,0x51,0x03,0x39,0xC2,0xEA,0xFA,0x7F,0x24,0x41,0xA1,0x30,0xF8,0xF8,0xD6,0xD7,
+    0xC2,0x30,0xA2,0x30,0x5F,0x35,0x25,0x08,0xE2,0x38,0xA2,0x30,0x2B,0xAB,0xA2,0xB2,
+    0x44,0x41,0xE3,0x38,0x2F,0x2D,0xAF,0xFA,0x64,0x49,0x03,0x39,0xFC,0xDF,0x7F,0xF5,
+    0x03,0x41,0xE2,0x38,0x28,0x60,0x78,0x6F,0x23,0x41,0xE2,0x38,0x80,0x2B,0xBD,0x0D,
+    0x44,0x49,0xE2,0x38,0x75,0xAF,0xAA,0x22,0x85,0x51,0x03,0x41,0xEF,0x2D,0x8A,0xEA,
+    0x84,0x51,0x23,0x49,0x3D,0xBF,0xF7,0xFD,0xC5,0x61,0x44,0x51,0x0A,0x3E,0x2D,0xFD,
+    0x47,0x72,0xA5,0x61,0x0A,0x0A,0xAB,0xF9,0x68,0x7A,0xE5,0x69,0x55,0xB7,0x8F,0x09,
+    0x68,0x7A,0xE5,0x69,0x5F,0xFE,0xE8,0xE0,0x06,0x6A,0x64,0x51,0xFE,0xFA,0x5C,0x5E,
+    0xC5,0x61,0x03,0x41,0xE8,0xE8,0xFE,0xFF,0x44,0x49,0xE2,0x40,0x0E,0xBC,0x78,0xFE,
+    0xA6,0x59,0x23,0x49,0xEF,0x8B,0xBD,0xA5,0x85,0x51,0x03,0x41,0x2A,0xBE,0x6A,0xF0,
+    0xA5,0x51,0x03,0x41,0x78,0xFA,0xFF,0xD5,0x44,0x49,0x03,0x41,0x2D,0x0D,0x0A,0x2B,
+    0x84,0x51,0x44,0x49,0xBF,0xBD,0x3F,0xCA,0x85,0x51,0x23,0x49,0x92,0xF2,0xE2,0x8A,
+    0xC6,0x61,0x23,0x49,0xED,0xBF,0x3D,0x25,0x68,0x7A,0xC6,0x61,0x05,0x25,0xA5,0x2D,
+    0x4A,0x93,0x68,0x7A,0xBF,0x2D,0xAD,0xAB,0x6B,0x9B,0xC9,0x8A,0x7F,0xEE,0xE0,0xEA,
+    0xE9,0x8A,0x26,0x6A,0x7F,0xFA,0xE8,0xE2,0x26,0x72,0xE5,0x69,0x02,0xAE,0x06,0x94,
+    0x67,0x72,0xE6,0x69,0x2B,0xAF,0xBD,0xBF,0x88,0x7A,0x26,0x72,0x9C,0xA5,0x37,0x3B,
+    0x88,0x82,0x47,0x7A,0xAF,0xDE,0x82,0x00,0xC8,0x8A,0x67,0x7A,0xBA,0x3B,0xAF,0x95,
+    0x09,0x93,0xA8,0x82,0x5D,0xBF,0xAA,0x2B,0x09,0x8B,0x67,0x7A,0xF7,0xFE,0xFA,0xA8,
+    0x88,0x82,0x47,0x7A,0xFF,0x5E,0xFA,0x02,0x68,0x7A,0x27,0x72,0xB8,0xFD,0x7D,0xC3,
+    0x68,0x7A,0x06,0x6A,0x57,0x5E,0xDB,0x2F,0x88,0x7A,0xE6,0x61,0x5F,0x5D,0x6E,0xA2,
+    0x67,0x7A,0xC6,0x61,0xB7,0xBD,0xAB,0x2A,0x88,0x7A,0x26,0x6A,0x8B,0x86,0xAF,0x68,
+    0x87,0x72,0x46,0x72,0xAC,0x82,0x3A,0xD5,0x67,0x72,0x26,0x6A,0x7E,0x7C,0xB0,0xA2,
+    0xA8,0x7A,0xE6,0x61,0x0A,0xAB,0xF7,0x5F,0xF0,0xC4,0x88,0x72,0x2B,0xAD,0x95,0x55,
+    0x35,0xEE,0x4A,0x93,0x02,0x0A,0x2B,0xBD,0x76,0xF6,0xD3,0xDD,0x00,0x22,0xAA,0x55,
+    0x55,0xEE,0xF4,0xE5,0x00,0x00,0x8A,0x95,0x55,0xEE,0x15,0xE6,0x8A,0xE2,0x6C,0x7F,
+    0x55,0xEE,0x14,0xE6,0xA2,0xA2,0x23,0xAF,0x15,0xEE,0x34,0xE6,0x79,0x7F,0x7D,0xBF,
+    0x35,0xE6,0x14,0xE6,0xA0,0xB0,0x68,0x4F,0x34,0xE6,0xD4,0xE5,0xA0,0x2A,0x0A,0xBA,
+    0x34,0xE6,0xF4,0xE5,0x08,0x08,0x96,0xBE,0x15,0xEE,0x34,0xE6,0x75,0xFF,0x7F,0xFF,
+    0x35,0xE6,0xD3,0xDD,0xA2,0xFA,0xDE,0xF8,0x35,0xE6,0xD3,0xDD,0x2A,0xFB,0xFD,0xF7,
+    0x14,0xE6,0xD3,0xDD,0xE8,0xFD,0xB5,0x2B,0x35,0xE6,0xF4,0xE5,0x03,0x2B,0x0B,0x3F,
+    0x76,0xEE,0x35,0xE6,0x95,0xBD,0xAB,0xAF,0x96,0xF6,0x55,0xEE,0xEB,0xFF,0xAF,0xA5,
+    0x76,0xF6,0x96,0xEE,0xE8,0xFE,0xBF,0xFB,0x96,0xF6,0x55,0xEE,0x88,0xEA,0x7A,0x5E,
+    0x76,0xEE,0x35,0xE6,0xC0,0xAE,0xF5,0xDF,0x55,0xEE,0x35,0xE6,0xC0,0x62,0x8A,0x2B,
+    0x55,0xEE,0xF4,0xDD,0x7A,0x7A,0xEA,0xE0,0x14,0xE6,0x72,0xCD,0x7F,0x7E,0xE8,0x00,
+    0xD3,0xDD,0x72,0xCD,0x9D,0xDF,0xBE,0x08,0x14,0xE6,0xB2,0xDD,0xAF,0xA5,0x3D,0x0A,
+    0x34,0xE6,0x14,0xE6,0x75,0xE5,0xF7,0x55,0x55,0xEE,0xF4,0xDD,0x8B,0xBB,0xBF,0xF7,
+    0x75,0xEE,0x35,0xE6,0x0E,0x2F,0xBD,0xBD,0x96,0xEE,0x75,0xEE,0xED,0xFF,0x0A,0x0A,
+    0xB6,0xF6,0x76,0xEE,0x7F,0xFB,0xFE,0xFE,0x96,0xEE,0x76,0xEE,0x7C,0xFE,0xFF,0xFE,
+    0x96,0xEE,0x55,0xE6,0x7B,0xFA,0xA8,0xAA,0x75,0xEE,0xB2,0xD5,0x7F,0xD8,0xE8,0xE0,
+    0xB3,0xDD,0xF3,0xD5,0xAA,0xEB,0xAB,0xAB,0xB3,0xDD,0x71,0xCD,0x7F,0x7C,0x5C,0xE0,
+    0xD3,0xDD,0x71,0xCD,0x0A,0x0B,0x0F,0x25,0xF4,0xDD,0x2E,0xAC,0x78,0xA0,0x00,0x00,
+    0xB3,0xD5,0xC9,0x7A,0x57,0xFA,0x80,0x00,0x10,0xC5,0xA8,0x7A,0x55,0x5D,0xFA,0x80,
+    0x0D,0xA4,0x87,0x72,0x55,0x55,0xFE,0x80,0x8B,0x93,0x26,0x6A,0x5F,0xFD,0xBF,0x80,
+    0xAF,0xB4,0xC9,0x7A,0x35,0x25,0x29,0x0B,0xF0,0xC4,0xAF,0xBC,0x09,0x29,0x0A,0x0E,
+    0x66,0x72,0x25,0x6A,0x60,0xBA,0xD2,0xA0,0x87,0x72,0x46,0x72,0x5A,0x76,0x77,0xBA,
+    0x66,0x72,0x26,0x72,0xBA,0xFF,0xEF,0xEA,0x86,0x72,0x26,0x72,0x7F,0xDF,0xED,0xD5,
+    0x67,0x7A,0x26,0x6A,0xCD,0x8B,0xAC,0xAD,0x87,0x7A,0x25,0x6A,0xA5,0x9D,0xBA,0xBF,
+    0x87,0x7A,0x04,0x6A,0xBB,0xFE,0xDA,0xA2,0x67,0x7A,0x25,0x6A,0x5F,0xC9,0x2F,0xBF,
+    0x66,0x72,0x26,0x72,0x7D,0xFE,0x96,0xDE,0x66,0x72,0x05,0x6A,0x02,0xCA,0x27,0x01,
+    0x66,0x72,0x26,0x6A,0xD6,0xAD,0xBE,0x88,0x66,0x72,0x26,0x6A,0xFF,0x3D,0xBE,0xAE,
+    0x87,0x72,0x26,0x72,0xD7,0xD5,0xFF,0xFB,0x46,0x72,0x25,0x6A,0xA0,0x83,0x8A,0xEA,
+    0x46,0x72,0x05,0x6A,0x82,0x0F,0x2B,0x3A,0x66,0x72,0x05,0x6A,0x6E,0xEC,0xD8,0xFE,
+    0x45,0x72,0x05,0x6A,0x9D,0x90,0xC2,0x38,0x87,0x7A,0x04,0x6A,0x27,0xFF,0xDF,0x7F,
+    0xA7,0x7A,0x04,0x6A,0xB0,0xBD,0xB7,0xED,0xA7,0x82,0x25,0x72,0x02,0xA0,0xFB,0x7E,
+    0xA7,0x82,0x46,0x72,0x00,0xA8,0xA3,0xFD,0xA7,0x82,0x67,0x7A,0xAA,0x2A,0xFA,0x85,
+    0xC8,0x82,0x86,0x7A,0xE5,0xAF,0xEA,0xDB,0xA7,0x82,0x66,0x7A,0x00,0x80,0x18,0x40,
+    0xC7,0x82,0x86,0x7A,0x9E,0xBF,0x8C,0xAC,0xC7,0x82,0x87,0x7A,0xF8,0x0A,0xA2,0xD8,
+    0xE8,0x8A,0x86,0x7A,0xB7,0x2F,0x3B,0xAF,0xE7,0x82,0xA7,0x82,0xDA,0xD6,0x75,0xDF,
+    0xC7,0x82,0x86,0x7A,0xA6,0xF6,0xDC,0xFC,0xC8,0x82,0x87,0x82,0xBE,0x27,0x2F,0xA2,
+    0xE8,0x8A,0x87,0x7A,0x5F,0x5F,0xEF,0xAB,0xA7,0x82,0xE5,0x69,0xF6,0xBE,0x28,0x28,
+    0xE8,0x8A,0x26,0x72,0x55,0xEA,0x80,0xA0,0x87,0x82,0xE5,0x69,0x57,0xF7,0xA8,0x08,
+    0xA7,0x7A,0xA5,0x61,0xD7,0xFE,0xAA,0xA2,0x47,0x72,0xA5,0x59,0xF7,0x7B,0x58,0x58,
+    0xA5,0x59,0x44,0x51,0xE8,0xF0,0x78,0x5A,0x23,0x51,0x44,0x49,0x57,0xE7,0xDE,0x5F,
+    0x44,0x49,0xE3,0x38,0x80,0x80,0x80,0x70,0x64,0x49,0xC2,0x30,0xE8,0xFF,0x7F,0x7F,
+    0x23,0x41,0xA2,0x30,0x8A,0xEF,0xAD,0xAD,0x03,0x39,0xA1,0x30,0x55,0x5E,0xF8,0xFC,
+    0x03,0x39,0xC2,0x30,0x55,0xD5,0x1D,0x29,0x24,0x39,0xC2,0x30,0x9F,0xBF,0xAE,0xB8,
+    0x24,0x41,0x03,0x39,0x73,0xFD,0x85,0x57,0x03,0x39,0xA2,0x30,0xA8,0xD8,0xFC,0xF8,
+    0x03,0x39,0xC2,0x38,0xCB,0xC5,0xB5,0xA7,0x65,0x49,0xE3,0x38,0xB5,0x3F,0x2D,0x25,
+    0x85,0x51,0x44,0x49,0x5D,0x7F,0xDA,0xCF,0x64,0x51,0x23,0x41,0x62,0x63,0xEA,0xFF,
+    0x64,0x51,0x24,0x49,0xA5,0xAF,0x3F,0x2D,0xA5,0x61,0x44,0x49,0xA5,0x35,0xAF,0xFE,
+    0x06,0x6A,0x64,0x59,0x0B,0x0B,0xBF,0xD5,0x68,0x7A,0xC6,0x61,0x0B,0xAA,0xA9,0xAD,
+    0x68,0x7A,0xC6,0x61,0x80,0xC0,0xEA,0xDF,0xE6,0x61,0x44,0x49,0x78,0x7C,0xFC,0x6E,
+    0x44,0x49,0xC2,0x38,0xFF,0x5E,0x54,0xDC,0x03,0x41,0xE3,0x40,0x38,0x3D,0x1F,0xDA,
+    0x85,0x51,0x03,0x41,0x2F,0x09,0x2B,0x2D,0xC6,0x59,0x03,0x41,0x7A,0xEA,0x28,0x22,
+    0xC6,0x59,0x03,0x41,0x55,0x57,0x5A,0xA0,0x64,0x51,0x03,0x41,0x2B,0x2F,0x2D,0x8E,
+    0xA5,0x59,0x23,0x49,0x28,0xE0,0xF6,0xD7,0x85,0x59,0x03,0x41,0xAA,0xE2,0xEF,0x7F,
+    0xA6,0x59,0xE2,0x40,0x2F,0xBF,0xB7,0xF5,0x88,0x7A,0x85,0x59,0x2F,0x2B,0x0B,0xAD,
+    0x29,0x8B,0xA8,0x82,0xAA,0x62,0xAF,0xF5,0x2A,0x93,0x86,0x7A,0x82,0xAA,0xEB,0x75,
+    0xA8,0x82,0x05,0x6A,0xE8,0x78,0x58,0x78,0x26,0x6A,0x63,0x51,0x28,0xBA,0xBF,0xF7,
+    0x47,0x72,0xA5,0x59,0x2A,0x23,0xAB,0xAD,0x47,0x72,0x06,0x6A,0x22,0xEE,0x8F,0x85,
+    0x88,0x7A,0x26,0x72,0xE8,0xEF,0xF9,0x55,0xE9,0x8A,0x26,0x72,0xBF,0x3F,0x29,0xAD,
+    0xE9,0x8A,0x88,0x82,0x22,0x20,0xA8,0x6E,0x2A,0x93,0xA8,0x82,0xAB,0x0B,0xBB,0xF5,
+    0x0A,0x93,0xA8,0x82,0x7E,0x60,0x5E,0xFF,0xA8,0x82,0x68,0x7A,0x64,0xEE,0xF0,0x68,
+    0x68,0x7A,0x26,0x72,0xAB,0xE8,0x50,0xF0,0x67,0x7A,0x06,0x6A,0x80,0x6E,0xF7,0xDF,
+    0x88,0x7A,0x26,0x6A,0x2B,0x2B,0xBF,0xD5,0xA8,0x82,0x46,0x72,0x6A,0xE2,0xFF,0xF7,
+    0x87,0x7A,0x26,0x6A,0x75,0xFF,0xF8,0xA2,0x67,0x6A,0x05,0x6A,0x0F,0xBB,0x97,0xB7,
+    0x67,0x72,0xE6,0x61,0x72,0xA0,0x80,0xA2,0x87,0x72,0xE6,0x61,0x2E,0xBB,0xF7,0xFE,
+    0xCC,0x9B,0x27,0x6A,0x2F,0xF7,0xF5,0x55,0xAF,0xBC,0x67,0x72,0x02,0xBF,0xF5,0x55,
+    0x92,0xD5,0x2A,0x8B,0x02,0x2B,0xFD,0x55,0x14,0xE6,0xEC,0xA3,0x00,0x0A,0xAB,0xB5,
+    0x35,0xEE,0x93,0xD5,0x02,0x08,0x2A,0xAD,0x34,0xEE,0x14,0xE6,0xF7,0x5E,0x78,0xEC,
+    0x34,0xE6,0xD4,0xE5,0xA2,0xA2,0xAA,0xE0,0x14,0xE6,0xF4,0xE5,0x80,0xA2,0xFD,0xD5,
+    0x14,0xE6,0xF4,0xE5,0x08,0x22,0xB6,0xA5,0x35,0xEE,0xD3,0xDD,0x22,0x0E,0xEE,0x9F,
+    0x35,0xE6,0xF4,0xE5,0xAA,0xF8,0xDE,0xFF,0x34,0xE6,0xF4,0xDD,0x75,0xFA,0xFE,0xFE,
+    0x14,0xE6,0xF4,0xDD,0x3F,0x37,0x35,0xD5,0x34,0xE6,0xF4,0xE5,0x3F,0xAF,0xFF,0xFF,
+    0x55,0xEE,0x14,0xE6,0x8A,0xAB,0xAD,0xB9,0x96,0xF6,0x55,0xEE,0xAD,0xAF,0xD5,0xD5,
+    0x97,0xF6,0x35,0xE6,0xA2,0xA8,0x6E,0x5F,0x76,0xEE,0x14,0xE6,0xE8,0xFA,0xF6,0xD5,
+    0x55,0xEE,0x14,0xE6,0xA7,0x3F,0xBF,0xBF,0x55,0xEE,0x35,0xE6,0x2E,0x1C,0xDF,0xFF,
+    0x55,0xEE,0x14,0xE6,0xFA,0xAC,0xFE,0x57,0x55,0xEE,0x14,0xE6,0xFF,0xE2,0xEF,0x55,
+    0x55,0xEE,0xF4,0xDD,0x7F,0xAA,0x82,0xE8,0x35,0xE6,0xD3,0xDD,0xAD,0xAE,0xE8,0xB8,
+    0x14,0xE6,0xF4,0xDD,0xE6,0xFA,0xA2,0x02,0x14,0xE6,0xD4,0xDD,0x0E,0x2B,0xA2,0xB6,
+    0x55,0xE6,0x14,0xE6,0x29,0x2F,0x3D,0xAD,0x96,0xEE,0x55,0xE6,0x02,0x02,0x03,0x0D,
+    0x96,0xEE,0x76,0xEE,0xCA,0xEA,0xA8,0xB8,0x76,0xF6,0x96,0xEE,0x9D,0xD7,0x95,0xF7,
+    0x96,0xEE,0x76,0xEE,0x76,0x5F,0xFD,0x3B,0x96,0xEE,0x35,0xE6,0x7A,0x8A,0x80,0x08,
+    0x96,0xEE,0xD3,0xDD,0x55,0x7E,0xFA,0xA8,0x35,0xE6,0x92,0xD5,0x5F,0x5F,0xFE,0xF0,
+    0xD3,0xD5,0x72,0xD5,0x0D,0xAB,0xED,0x7F,0x14,0xE6,0xB3,0xD5,0xAA,0xAB,0x8D,0xB9,
+    0x14,0xE6,0xB3,0xD5,0x7E,0x6A,0xAA,0xAB,0xF4,0xDD,0x51,0xD5,0x7E,0xAB,0xEA,0x80,
+    0x92,0xD5,0x6F,0xB4,0x5E,0xA0,0x00,0x00,0xB2,0xD5,0x0D,0xA4,0x57,0xFF,0xEA,0xA8,
+    0xAF,0xBC,0x0D,0xA4,0x2D,0x0A,0x2A,0x58,0xF0,0xC4,0x0D,0xA4,0x08,0x02,0x0A,0xBD,
+    0x87,0x7A,0x25,0x6A,0xDF,0x1D,0xFB,0xFA,0x86,0x7A,0x25,0x6A,0x32,0xB9,0xEB,0xE7,
+    0x66,0x72,0x05,0x72,0xA8,0xAE,0xAB,0xA9,0x66,0x72,0x06,0x72,0xAA,0x2A,0x02,0xE0,
+    0x87,0x7A,0x46,0x72,0x55,0x15,0x97,0xEF,0x87,0x7A,0x25,0x6A,0xBD,0xBB,0x2B,0x7A,
+    0x66,0x72,0x05,0x72,0x00,0x8C,0xA8,0x2A,0xA7,0x82,0x25,0x6A,0xEF,0xFB,0xFF,0x6A,
+    0x86,0x72,0x26,0x72,0xFE,0xEE,0xFE,0x92,0x66,0x72,0x26,0x72,0x82,0xEB,0xAE,0xA2,
+    0x66,0x72,0x26,0x72,0xA8,0xE2,0xE0,0x12,0x67,0x72,0x26,0x72,0xEE,0xBF,0x81,0x2B,
+    0x66,0x72,0x25,0x72,0x76,0xBF,0x3F,0x5D,0x87,0x7A,0x25,0x6A,0x5F,0xDF,0xD2,0x38,
+    0x66,0x72,0x05,0x6A,0xBE,0xEE,0xFE,0xB0,0x66,0x72,0xE5,0x69,0xA6,0x28,0xAA,0x82,
+    0x66,0x72,0x05,0x72,0x2A,0x02,0x8E,0xAA,0x66,0x72,0x25,0x72,0xFE,0xD0,0xA8,0x9B,
+    0x66,0x72,0x05,0x6A,0xEF,0xE8,0xFA,0xEE,0x46,0x72,0x05,0x6A,0xE0,0xA8,0x37,0x0A,
+    0x66,0x72,0x25,0x6A,0xFA,0x5F,0x75,0x9F,0x87,0x7A,0x25,0x6A,0x8B,0xBD,0xF7,0x56,
+    0xC7,0x82,0x05,0x6A,0x0A,0x2A,0xBB,0xF5,0xC7,0x82,0x45,0x72,0x02,0xA0,0xBB,0xFD,
+    0xC8,0x82,0x66,0x7A,0xAA,0xAA,0x2B,0x2D,0xC8,0x82,0x86,0x7A,0x7E,0xF7,0xEC,0xB8,
+    0xC7,0x82,0x87,0x7A,0x8B,0xAA,0x8B,0xBE,0xC8,0x82,0xA7,0x82,0x0F,0xCA,0xE8,0x33,
+    0xE7,0x8A,0xA7,0x82,0xF5,0xF5,0xED,0x6A,0xE8,0x8A,0xA7,0x82,0xAB,0xEA,0xFB,0xFB,
+    0xE8,0x8A,0xA7,0x82,0xBF,0xAD,0xEB,0x2B,0xE8,0x8A,0x66,0x7A,0x9F,0x7E,0xF8,0xE8,
+    0xE8,0x8A,0x87,0x7A,0xA3,0x8B,0xED,0xCB,0xC8,0x8A,0x46,0x72,0xD6,0xFC,0xF8,0xA8,
+    0xA7,0x7A,0x26,0x72,0xF2,0x78,0x7E,0x5E,0x26,0x72,0x44,0x51,0xF8,0x7A,0x7C,0x7A,
+    0x64,0x51,0xE3,0x38,0x80,0x2A,0xEA,0x7A,0x64,0x51,0xE3,0x38,0x82,0xA8,0x5E,0x57,
+    0x44,0x49,0xA1,0x28,0xF8,0xF8,0xDF,0x57,0xE3,0x38,0x81,0x28,0x8B,0x8F,0x9F,0xF5,
+    0xE3,0x38,0xC2,0x30,0x39,0x3D,0x9D,0x59,0xE3,0x38,0xC2,0x28,0xA8,0xAA,0xDC,0xA7,
+    0x23,0x39,0xC3,0x30,0x2D,0xAB,0xBE,0xBF,0x24,0x39,0xC2,0x30,0xFC,0xF6,0x7E,0x7E,
+    0x03,0x39,0xC2,0x30,0xA2,0xDE,0x5D,0xF5,0xE2,0x38,0xC2,0x30,0x20,0x0A,0x2A,0x9D,
+    0x03,0x39,0xE2,0x38,0x49,0x59,0xFD,0x97,0x64,0x49,0xE2,0x38,0x2D,0x3D,0xBD,0x2F,
+    0x85,0x51,0x03,0x41,0x82,0xA0,0xA2,0x5E,0x64,0x49,0x23,0x49,0xF6,0x96,0xEB,0xAB,
+    0x64,0x51,0x44,0x51,0xDD,0x9E,0x82,0x22,0xA5,0x59,0x44,0x51,0xFD,0xE9,0x0B,0x02,
+    0xA5,0x59,0x65,0x59,0x95,0xDD,0x36,0x1A,0x27,0x72,0xA5,0x61,0x0D,0x0D,0x09,0x2F,
+    0x07,0x6A,0x65,0x51,0x68,0x60,0xFC,0xF8,0x64,0x51,0x24,0x49,0x7B,0xFD,0xCF,0xF8,
+    0x44,0x49,0xE3,0x40,0x57,0x7E,0xEA,0xF8,0x24,0x41,0xA2,0x30,0xA2,0xE2,0xFA,0xFE,
+    0x85,0x51,0xC2,0x38,0xAF,0xB5,0xB5,0x2D,0xE6,0x59,0x84,0x51,0xA7,0xBD,0xFD,0x2A,
+    0xE6,0x61,0x85,0x51,0xE2,0xF2,0x7B,0x5E,0x85,0x51,0x24,0x49,0xAE,0xC8,0xFE,0xDF,
+    0x65,0x51,0x03,0x41,0x58,0x7A,0x6F,0x5F,0x23,0x49,0xE3,0x38,0xA0,0xFA,0xBB,0xBD,
+    0xE3,0x40,0x02,0x39,0x0A,0x00,0x80,0xE2,0x46,0x72,0x23,0x49,0x29,0xF5,0xF5,0xD5,
+    0x86,0x7A,0xC5,0x59,0x0A,0xAB,0xFD,0x55,0x66,0x72,0x64,0x51,0x80,0xE8,0xFF,0x5F,
+    0x25,0x6A,0x64,0x51,0xA0,0xAB,0xF5,0xD5,0xC5,0x61,0x64,0x51,0x5C,0xFA,0xFD,0xFE,
+    0xC6,0x61,0x64,0x51,0x0B,0xAD,0xFF,0xF7,0x06,0x6A,0x85,0x59,0x2A,0xB7,0xF5,0x55,
+    0x26,0x72,0x84,0x59,0x28,0x2F,0xBD,0x95,0x88,0x7A,0xE5,0x69,0x0A,0x2A,0xAB,0xBD,
+    0xA8,0x82,0x67,0x7A,0xA2,0xCB,0x61,0x6E,0xE9,0x8A,0x46,0x72,0x0A,0x09,0xA7,0x55,
+    0xE9,0x8A,0x67,0x7A,0xA0,0x88,0xEB,0xFD,0xC9,0x8A,0x67,0x7A,0x9E,0xDF,0xAB,0xA2,
+    0xE9,0x92,0x47,0x72,0x5F,0x6F,0xA2,0xA0,0xA8,0x7A,0x06,0x72,0xF7,0xF7,0xFE,0xF8,
+    0x47,0x72,0xE5,0x69,0x3A,0xAE,0xFE,0xF5,0x67,0x7A,0xC5,0x61,0x00,0xBA,0x5F,0x5F,
+    0x67,0x72,0xC5,0x61,0x00,0x0B,0xA5,0x55,0x87,0x72,0x06,0x6A,0xFE,0x82,0xCA,0xFD,
+    0x67,0x72,0xE5,0x61,0xEA,0xE8,0xF2,0xD7,0x46,0x6A,0xC5,0x59,0xBA,0xB8,0x7C,0x5F,
+    0x27,0x6A,0x84,0x59,0x00,0x0A,0xAA,0xDF,0x68,0x72,0xC5,0x61,0x0A,0x2E,0xFB,0x7D,
+    0xC8,0x82,0x26,0x6A,0x00,0x2A,0xAF,0xA5,0xAF,0xBC,0xC8,0x7A,0x2D,0x2D,0xF5,0xF5,
+    0xF4,0xE5,0xEC,0xA3,0x02,0x0A,0x0B,0xBD,0x35,0xEE,0xD3,0xE5,0x02,0x02,0x82,0x29,
+    0x34,0xEE,0xF4,0xE5,0xE2,0xEA,0xFA,0xF2,0x14,0xE6,0xD3,0xDD,0xBE,0xFB,0xF8,0xFA,
+    0xF4,0xE5,0xD3,0xDD,0x28,0x8A,0x2F,0x0B,0xF4,0xDD,0xB3,0xDD,0xE8,0x78,0x7E,0xB0,
+    0x14,0xE6,0xB3,0xDD,0x2A,0x2B,0xAD,0xFE,0x14,0xE6,0xD3,0xDD,0xE8,0x7A,0xFA,0xFF,
+    0xF4,0xE5,0xD3,0xDD,0xFE,0xFB,0x5B,0xDF,0x14,0xE6,0xD3,0xDD,0xCF,0xAD,0xD5,0xB5,
+    0x34,0xE6,0xF3,0xE5,0x0B,0x2B,0x2F,0x2A,0x55,0xEE,0x35,0xE6,0x02,0x82,0x77,0x57,
+    0x56,0xEE,0x14,0xE6,0xAC,0xDE,0xFE,0x55,0x35,0xE6,0x14,0xE6,0xFC,0x38,0x2F,0xBD,
+    0x55,0xEE,0x14,0xE6,0xBE,0xAA,0x3E,0xFF,0x55,0xEE,0x35,0xE6,0xEE,0xBB,0x7E,0xF7,
+    0x35,0xE6,0xD3,0xDD,0xF8,0x78,0x7A,0xA8,0x14,0xE6,0xD3,0xDD,0x2B,0x37,0xBF,0xAF,
+    0xF4,0xE5,0x35,0xDE,0xAB,0x22,0xA0,0xFA,0x34,0xE6,0xF4,0xE5,0xFF,0xA9,0x2B,0x2B,
+    0x35,0xE6,0xF4,0xDD,0xAF,0xEE,0x6E,0xFA,0x34,0xE6,0xF4,0xDD,0xF7,0xBF,0x2D,0xAF,
+    0x76,0xEE,0x15,0xE6,0x3D,0xAF,0xBF,0xFD,0xB6,0xF6,0x56,0xE6,0xB9,0xAF,0xBB,0x0F,
+    0xB6,0xF6,0x76,0xEE,0xF7,0xB5,0xBF,0xF8,0x76,0xF6,0x96,0xEE,0xDD,0xFD,0xFF,0xF5,
+    0x76,0xF6,0x96,0xEE,0x5D,0xF7,0xFF,0x56,0x96,0xEE,0x76,0xEE,0x6A,0xFD,0xFA,0x70,
+    0x96,0xEE,0x35,0xE6,0xEA,0xA8,0x22,0x88,0xB6,0xEE,0x14,0xE6,0x7F,0xFA,0xAA,0xAA,
+    0x55,0xEE,0xB3,0xD5,0x57,0x5A,0xA0,0x00,0x35,0xE6,0x92,0xD5,0xBD,0xF5,0xFF,0xFC,
+    0x14,0xE6,0xB3,0xD5,0x2E,0xAA,0x2F,0xAD,0x14,0xE6,0xD3,0xDD,0xFB,0xCA,0x6A,0xFA,
+    0xF3,0xDD,0xB3,0xD5,0x7F,0xC2,0x08,0x20,0xF4,0xDD,0x51,0xCD,0x5E,0xE8,0x80,0x00,
+    0xD3,0xDD,0x8F,0xB4,0x5E,0xEA,0x20,0x00,0x72,0xCD,0x6A,0x93,0xD7,0x5E,0xF8,0xC0,
+    0x87,0x7A,0x46,0x72,0x7E,0x7A,0x5E,0x75,0x66,0x72,0x25,0x6A,0xE6,0x2A,0x0A,0x32,
+    0x86,0x7A,0x46,0x72,0xF5,0xDB,0xBB,0x7A,0x66,0x72,0x25,0x72,0x3A,0xAA,0x20,0x2F,
+    0x66,0x72,0x25,0x6A,0xE0,0x18,0xD2,0x3A,0x87,0x7A,0x26,0x6A,0x7E,0xEA,0xAF,0xEC,
+    0x87,0x7A,0x46,0x72,0xD1,0x7B,0xEA,0x69,0x66,0x72,0x26,0x72,0x6A,0xAA,0x82,0x23,
+    0x66,0x72,0x25,0x72,0xAE,0x3E,0x3F,0xEA,0x86,0x72,0x25,0x6A,0xEA,0xEF,0xF4,0xB7,
+    0x87,0x7A,0x46,0x72,0xDD,0xFB,0xBF,0x8D,0x66,0x72,0x25,0x72,0xE0,0xCE,0x2C,0xAC,
+    0x66,0x7A,0x25,0x6A,0x69,0xE9,0xB2,0x82,0x87,0x7A,0x46,0x72,0x9F,0xE5,0x45,0xFD,
+    0x87,0x7A,0x25,0x6A,0xDA,0x8B,0xCD,0xAB,0x87,0x7A,0x25,0x6A,0xEF,0xFA,0x9A,0xD8,
+    0x67,0x72,0x26,0x72,0xA3,0x36,0xDE,0x98,0x66,0x72,0x05,0x6A,0xAA,0xC0,0xE8,0xF8,
+    0x66,0x72,0x25,0x72,0x4A,0xCB,0xCA,0xCB,0x46,0x72,0x25,0x6A,0x87,0x2B,0x01,0x03,
+    0x87,0x7A,0x25,0x6A,0x57,0x77,0x6B,0xF2,0x66,0x72,0x05,0x6A,0x7B,0xE2,0xA0,0x0A,
+    0x67,0x7A,0x05,0x6A,0x2D,0x2B,0xAA,0x2A,0x67,0x7A,0x26,0x72,0x7E,0xFE,0xBE,0xC8,
+    0x87,0x7A,0x25,0x72,0x07,0xBF,0xFF,0xFF,0xA8,0x82,0x25,0x72,0x0A,0x2D,0xF7,0x9F,
+    0xC8,0x82,0x26,0x72,0x2A,0x0A,0xEB,0x67,0xC7,0x82,0x66,0x7A,0xAC,0xB8,0xAB,0xAD,
+    0xC8,0x82,0xA7,0x82,0xC0,0xD7,0xD5,0x5F,0xE8,0x8A,0xA7,0x82,0x7B,0xEA,0xB2,0xF5,
+    0x09,0x93,0xA7,0x82,0x8F,0x8B,0xFB,0xDB,0x09,0x93,0xC8,0x8A,0x5F,0xAD,0x3F,0x2F,
+    0x29,0x93,0xC8,0x8A,0x7D,0x7E,0x6E,0x72,0xC9,0x8A,0x06,0x6A,0xA8,0xA8,0xE0,0x78,
+    0x67,0x7A,0xA4,0x59,0xE8,0xFA,0xFA,0x5F,0xE5,0x61,0x23,0x49,0x68,0x78,0x7E,0x5F,
+    0x24,0x49,0xC2,0x30,0xE8,0xF8,0x7C,0x5D,0x03,0x39,0xA2,0x30,0xBF,0xFF,0xFF,0x55,
+    0xC2,0x30,0x82,0x28,0xC0,0x68,0x7E,0xF7,0xC2,0x30,0x81,0x28,0x25,0x25,0x2D,0x2D,
+    0xE2,0x30,0xA2,0x28,0xFE,0xF6,0xF7,0xF7,0x03,0x31,0xA2,0x28,0xBE,0x1F,0xBF,0xB7,
+    0x03,0x39,0xA2,0x28,0xAA,0xA8,0xAA,0x5B,0xE3,0x30,0x82,0x28,0x20,0x2A,0xB6,0xAE,
+    0xE3,0x30,0xA2,0x30,0x80,0xDE,0xFE,0xDF,0xE2,0x30,0xA2,0x30,0x1D,0xFF,0xFF,0xF5,
+    0x23,0x41,0xC2,0x30,0xB5,0x95,0x35,0xB5,0xA6,0x51,0x24,0x41,0xBD,0x8B,0x81,0xEB,
+    0x64,0x49,0xE3,0x40,0x58,0x7A,0x5E,0x57,0x44,0x49,0xE3,0x40,0x03,0x29,0x29,0x2D,
+    0x85,0x59,0x44,0x51,0xEB,0xAA,0xF5,0x83,0xA5,0x59,0x64,0x51,0x0A,0xA6,0x77,0x55,
+    0xC5,0x61,0x44,0x49,0xBC,0x28,0x3A,0xAD,0x27,0x72,0xC5,0x61,0x8D,0xE9,0xA9,0xFD,
+    0xE6,0x61,0x65,0x51,0xFF,0x7E,0x78,0x5A,0x65,0x51,0xE2,0x38,0xA8,0xE8,0xBC,0x5F,
+    0x64,0x49,0xE3,0x38,0x78,0x6A,0xFA,0xEB,0x24,0x41,0xC3,0x38,0x5F,0xFD,0xA7,0x2F,
+    0xA6,0x59,0x03,0x41,0x25,0xAD,0xAB,0x8F,0xE7,0x61,0x44,0x49,0x02,0x0A,0xFF,0x55,
+    0xE7,0x61,0x64,0x49,0xEA,0x20,0xA3,0xF5,0x85,0x51,0x24,0x41,0x7E,0xE8,0x78,0x5C,
+    0x44,0x49,0xE3,0x38,0x7E,0xDC,0xDC,0xFE,0x44,0x49,0xC2,0x30,0xF7,0xFE,0xAA,0x82,
+    0x65,0x49,0xE3,0x38,0xFD,0xFD,0xCB,0x82,0x44,0x49,0x03,0x41,0x2F,0x3F,0xBD,0xEF,
+    0xC6,0x59,0x24,0x49,0x8A,0xA3,0xAB,0xAD,0xA5,0x59,0x43,0x49,0xE2,0x7A,0x5C,0x58,
+    0x85,0x51,0x23,0x49,0xED,0xFF,0xB7,0xD7,0x85,0x51,0x23,0x49,0x00,0xE0,0xDA,0x5F,
+    0x84,0x51,0x43,0x49,0xA8,0xE8,0xEB,0xD7,0xC5,0x61,0x44,0x51,0xAF,0x2F,0x2F,0xAD,
+    0x26,0x6A,0x84,0x59,0x9F,0xAA,0xAA,0x7D,0x88,0x7A,0xA5,0x59,0x0B,0x2A,0x0F,0xAD,
+    0xA8,0x82,0x06,0x72,0xA0,0xA2,0xAA,0x5E,0x68,0x7A,0xE6,0x69,0x8A,0xAA,0xDE,0xDF,
+    0xC9,0x8A,0x46,0x7A,0xB7,0x2D,0x25,0x8D,0xC9,0x8A,0x87,0x82,0x20,0xE0,0xE0,0xFC,
+    0xE9,0x8A,0x67,0x82,0x02,0x02,0xAB,0xDA,0xEA,0x8A,0x47,0x7A,0x5C,0x7C,0xE2,0xAA,
+    0x88,0x82,0x26,0x72,0x55,0xBF,0xF8,0xA8,0x67,0x7A,0xC5,0x61,0x5F,0xB2,0xC0,0xE0,
+    0x07,0x6A,0xA5,0x59,0x7F,0x7E,0xD8,0x6C,0x06,0x6A,0x64,0x51,0x02,0xFE,0x7F,0x57,
+    0xE5,0x61,0x64,0x51,0x00,0xAB,0xBD,0xD5,0xC5,0x61,0x64,0x51,0x80,0xA8,0xFA,0xB7,
+    0xC6,0x59,0x84,0x59,0xDC,0xAA,0xBF,0x2B,0x06,0x6A,0xA5,0x59,0xEB,0x2F,0xAF,0xFD,
+    0x67,0x72,0xE5,0x61,0x3F,0xBF,0xAB,0xDF,0xC9,0x82,0x26,0x6A,0x0A,0xAB,0xB7,0xD7,
+    0x6E,0xB4,0x47,0x72,0x2B,0xBF,0xBD,0xFD,0xD3,0xE5,0x8B,0x9B,0x02,0x0B,0xBF,0xD5,
+    0x14,0xE6,0x6F,0xBC,0x00,0x02,0xAB,0xBD,0x14,0xE6,0xB3,0xE5,0xA2,0xA2,0xAA,0xAD,
+    0x14,0xE6,0xF4,0xE5,0xE5,0xBF,0xFE,0x7A,0x14,0xE6,0xD3,0xDD,0xBF,0xAC,0xA0,0xA3,
+    0x14,0xE6,0xD4,0xDD,0x5E,0xF8,0xE8,0xAA,0xF3,0xE5,0xB3,0xDD,0x8A,0xFF,0xFA,0x7C,
+    0x14,0xE6,0xB3,0xDD,0xFB,0xDF,0x57,0x7F,0xF4,0xE5,0xB3,0xDD,0x2E,0x2F,0xAB,0xBD,
+    0x35,0xE6,0xF4,0xDD,0x2F,0xAB,0x2D,0xBD,0x35,0xE6,0xF3,0xE5,0x80,0xA8,0xEA,0xFA,
+    0x14,0xE6,0xD3,0xDD,0xA2,0x98,0xFE,0x7E,0x35,0xE6,0xD3,0xDD,0x2A,0xAA,0xBB,0xBD,
+    0x56,0xE6,0x14,0xE6,0xB7,0x5F,0xF5,0x95,0x55,0xEE,0x15,0xE6,0xEA,0xA8,0xE0,0xF0,
+    0x34,0xE6,0xF4,0xDD,0xE8,0xAE,0xFF,0x57,0x35,0xE6,0xD3,0xDD,0xFB,0xE8,0xEA,0x7E,
+    0xD4,0xE5,0x14,0xDE,0xBE,0xFA,0xFE,0xFA,0x14,0xE6,0xF4,0xDD,0x23,0x28,0xEE,0xAF,
+    0x55,0xE6,0xF4,0xE5,0xFF,0xF5,0xFF,0xB7,0x34,0xE6,0xF4,0xDD,0xD6,0xBA,0xEA,0xBE,
+    0x55,0xEE,0x14,0xE6,0x35,0xE5,0xF5,0x55,0xB6,0xF6,0x35,0xE6,0x2B,0xAB,0xA9,0xA9,
+    0xB6,0xF6,0x76,0xEE,0xEA,0xFA,0xFE,0xAA,0xB6,0xF6,0x76,0xEE,0xF7,0xEF,0xBA,0xEA,
+    0x76,0xF6,0x96,0xEE,0x6F,0x5F,0xFD,0xD7,0x76,0xF6,0x96,0xEE,0xFD,0xF5,0xFF,0x67,
+    0x96,0xEE,0x76,0xEE,0xFF,0xBF,0xB6,0x57,0x96,0xEE,0x35,0xE6,0xAA,0xA0,0xFA,0x5E,
+    0x75,0xEE,0xF4,0xDD,0x20,0xA0,0xEA,0x7B,0x55,0xEE,0xB2,0xD5,0xF8,0xE8,0xF6,0x57,
+    0xF3,0xDD,0x92,0xD5,0x2A,0xAA,0xEA,0x5F,0x15,0xE6,0xB3,0xD5,0xB2,0xBE,0xBD,0x75,
+    0xF4,0xDD,0xB3,0xD5,0xAA,0xBC,0xAE,0xFF,0xF4,0xE5,0xB3,0xD5,0x28,0xAB,0xB6,0xFF,
+    0xF3,0xDD,0x91,0xD5,0xA8,0xAA,0xAA,0xF6,0xD2,0xDD,0xF0,0xC4,0x68,0xE0,0xA0,0xA0,
+    0x87,0x7A,0x25,0x6A,0xC9,0xAB,0xEA,0xBF,0x86,0x72,0x25,0x72,0xDA,0xBB,0xAA,0x2B,
+    0x86,0x7A,0x26,0x6A,0xAA,0xBB,0x68,0xFB,0x66,0x72,0x46,0x72,0x1F,0x0B,0x3F,0xA1,
+    0x87,0x7A,0x66,0x72,0x97,0xE7,0x6A,0x69,0x87,0x7A,0x46,0x72,0xF4,0xDE,0xEF,0xAE,
+    0x86,0x72,0x26,0x72,0xAF,0xBF,0x1F,0xAF,0x87,0x7A,0x26,0x72,0xFB,0xC1,0xEB,0xAA,
+    0x66,0x72,0x46,0x72,0x6B,0x7B,0xFD,0xFE,0x66,0x72,0x25,0x6A,0x07,0x35,0x27,0x82,
+    0x86,0x7A,0x26,0x6A,0x9F,0xFB,0xEA,0xE8,0x86,0x7A,0x46,0x72,0xED,0xF7,0xDD,0xFE,
+    0x66,0x72,0x25,0x72,0x8A,0x0B,0x3E,0x2E,0x66,0x72,0x25,0x6A,0xBA,0x7A,0x82,0x02,
+    0x66,0x72,0x25,0x6A,0xF1,0x7B,0xAD,0x8C,0x87,0x7A,0x46,0x72,0x5E,0xED,0xAB,0xE3,
+    0x87,0x7A,0x25,0x6A,0xA6,0xEF,0xAA,0xE8,0x66,0x7A,0x46,0x72,0x56,0xDF,0xE9,0x0B,
+    0x87,0x7A,0x25,0x6A,0x6A,0xEA,0xAA,0x62,0x87,0x7A,0x26,0x72,0xFF,0xA2,0xB2,0x7B,
+    0x66,0x72,0x26,0x72,0xBA,0xAB,0x0A,0x00,0x66,0x72,0x25,0x72,0x0B,0x0E,0xAA,0x18,
+    0x66,0x72,0x26,0x72,0xA0,0xA4,0x6B,0xC2,0x86,0x7A,0x25,0x72,0xBE,0xFF,0x63,0x6A,
+    0x66,0x7A,0x26,0x72,0xA8,0x62,0x01,0xB9,0x66,0x82,0x46,0x72,0xDD,0x7F,0xD7,0x59,
+    0x66,0x7A,0x05,0x72,0xB6,0xB6,0xAA,0x8A,0x66,0x7A,0x25,0x72,0x0A,0x9F,0x38,0x02,
+    0xA7,0x82,0x46,0x72,0xA8,0xBB,0xFF,0x97,0xC8,0x82,0x66,0x7A,0x02,0x2B,0xBF,0xD5,
+    0xC8,0x82,0x66,0x7A,0x88,0xA8,0xBF,0xD5,0x09,0x8B,0xA7,0x82,0x2E,0xEA,0x02,0xC9,
+    0x29,0x93,0xC8,0x8A,0xA2,0xE8,0x6A,0x62,0xA7,0x82,0xC5,0x61,0x78,0x7A,0x7C,0x5E,
+    0xA5,0x59,0x03,0x41,0xE0,0xF0,0x5C,0x54,0x23,0x41,0xC2,0x38,0xA0,0xF0,0x7B,0x77,
+    0xE2,0x38,0xA2,0x30,0xFC,0xDC,0xBE,0x7E,0xC2,0x30,0x81,0x28,0x58,0x7E,0xDE,0xBB,
+    0xC2,0x30,0x61,0x20,0xFF,0x7E,0xAE,0xAC,0xA2,0x28,0x61,0x20,0x0B,0x0B,0x23,0xAA,
+    0xC2,0x28,0xA2,0x28,0x9E,0x7D,0x63,0xB5,0xC2,0x30,0xA2,0x28,0xBA,0xF5,0x95,0xD6,
+    0xC2,0x30,0xA2,0x28,0xBA,0xA6,0x06,0x0D,0xE3,0x30,0xA2,0x28,0xEB,0x8B,0x6F,0x7F,
+    0xC2,0x30,0xA2,0x28,0xD8,0xEA,0xEB,0x75,0x03,0x39,0xA2,0x30,0xB5,0xBD,0xBD,0x2B,
+    0x44,0x49,0xC2,0x30,0xBD,0xBD,0xBB,0x0A,0x85,0x51,0xE3,0x38,0xE2,0x7A,0x7F,0x7B,
+    0x03,0x41,0xC2,0x38,0xBE,0xFF,0xDF,0x7F,0x44,0x49,0xE3,0x40,0x25,0x3F,0x2D,0xFD,
+    0x85,0x59,0x23,0x41,0x82,0xBE,0xF5,0xD5,0x64,0x51,0x44,0x49,0x7B,0x7E,0xAB,0x20,
+    0x64,0x51,0x23,0x49,0x0D,0x07,0x2F,0x0A,0xC6,0x61,0x44,0x49,0x0A,0xAB,0xDF,0x77,
+    0xC6,0x59,0x24,0x49,0xF8,0x7E,0x6B,0x7D,0x24,0x49,0xE3,0x38,0x5E,0xF4,0x54,0x57,
+    0x44,0x41,0xC2,0x38,0x8A,0xEA,0xFF,0x7D,0x24,0x41,0xE2,0x38,0x0F,0x26,0xAD,0xFD,
+    0x85,0x49,0x23,0x41,0xCD,0xAD,0x35,0xF5,0x65,0x49,0x24,0x41,0x7F,0x56,0x72,0xFA,
+    0x65,0x49,0xE2,0x38,0x0A,0x2B,0xAA,0x6B,0x44,0x49,0x03,0x41,0xFC,0x5C,0x54,0x55,
+    0x44,0x49,0x03,0x41,0x57,0xDC,0x77,0x56,0x44,0x49,0xE2,0x38,0x0A,0x2A,0xEB,0x5E,
+    0x44,0x49,0xC2,0x38,0xA8,0xB8,0xBF,0xD5,0x44,0x49,0xE3,0x38,0xAB,0x2A,0xBF,0xB7,
+    0x85,0x51,0x23,0x49,0x2F,0x3D,0x3F,0x0F,0xC6,0x59,0x64,0x51,0x5F,0xEB,0xF2,0xFA,
+    0xA5,0x51,0x43,0x49,0x77,0x7F,0xF8,0xBF,0x64,0x49,0x23,0x49,0x7E,0x68,0x56,0xFE,
+    0x43,0x49,0x03,0x41,0x3A,0xB9,0xBB,0xDF,0xA5,0x59,0x03,0x49,0x2B,0x2F,0xAF,0xBD,
+    0xA5,0x59,0x65,0x51,0xFA,0xFF,0x97,0x2E,0x26,0x72,0x84,0x59,0x25,0x95,0xB5,0xBD,
+    0x06,0x72,0xA4,0x61,0x88,0xBF,0xB5,0xEE,0x27,0x72,0xE6,0x69,0xF5,0xAF,0x9A,0x5E,
+    0xC8,0x8A,0x06,0x72,0x2B,0x09,0x2F,0xAF,0xE8,0x8A,0x46,0x7A,0xB8,0xF8,0x7A,0x7F,
+    0xA8,0x82,0x26,0x72,0x20,0xBA,0xAF,0xB5,0xC9,0x8A,0x67,0x7A,0xE2,0xEA,0x6B,0x5F,
+    0xA8,0x82,0x06,0x6A,0xA8,0xFA,0x5F,0x5D,0x47,0x72,0xC6,0x69,0xA0,0xFA,0xDF,0xBF,
+    0x26,0x6A,0x84,0x59,0x5E,0x5E,0xFB,0x80,0xE5,0x61,0x64,0x51,0xD7,0xDD,0xBB,0x00,
+    0xC5,0x59,0x64,0x51,0xF5,0xD7,0xB8,0x28,0xC6,0x59,0x85,0x59,0xBD,0xB5,0xE5,0x88,
+    0xE6,0x61,0xA5,0x59,0xE7,0xEA,0xF9,0x7A,0xE6,0x61,0x85,0x51,0x8B,0xAE,0xEB,0xB7,
+    0x06,0x62,0xA5,0x59,0xE3,0xED,0x55,0xD5,0x47,0x72,0xE5,0x61,0x3D,0xB5,0xDD,0xBD,
+    0xE9,0x82,0x47,0x72,0x3F,0xA5,0xB5,0xFD,0x8B,0x9B,0x88,0x7A,0x0B,0xAB,0x5D,0xDD,
+    0x2D,0xAC,0xA8,0x82,0x02,0xBF,0xF5,0x55,0x93,0xDD,0x29,0x8B,0x02,0x2F,0xAD,0xB5,
+    0xF4,0xE5,0x51,0xD5,0x00,0x03,0x09,0xAD,0xF4,0xE5,0x14,0xDE,0xA8,0x88,0x00,0x00,
+    0x14,0xE6,0xD4,0xDD,0x8B,0x7A,0xAE,0xEA,0xD3,0xDD,0xB3,0xDD,0x98,0xBB,0xFE,0xE5,
+    0xD3,0xDD,0x92,0xD5,0x80,0x00,0xE0,0xE8,0xD3,0xDD,0xB2,0xDD,0x27,0x0F,0x0D,0xA9,
+    0x14,0xE6,0xB3,0xDD,0x0A,0x0A,0xAF,0xED,0x14,0xE6,0xF4,0xDD,0xE8,0xFE,0xED,0xFF,
+    0x14,0xE6,0xB3,0xDD,0xEA,0xBA,0xF8,0x6B,0x14,0xE6,0xD3,0xDD,0xB5,0xA7,0x0F,0x2F,
+    0x55,0xEE,0x14,0xE6,0xB5,0x09,0x20,0x00,0x55,0xEE,0x14,0xE6,0x70,0xF2,0xEA,0xBA,
+    0x35,0xE6,0xD3,0xDD,0xDF,0x57,0xDE,0xE8,0x14,0xE6,0xD3,0xDD,0xDD,0xA7,0x0B,0x02,
+    0x35,0xE6,0xD3,0xDD,0xFD,0xFA,0xEA,0xBA,0x14,0xE6,0xF4,0xDD,0x8F,0x0B,0xA9,0x46,
+    0x14,0xE6,0xF4,0xDD,0x0A,0x20,0x80,0x82,0x14,0xE6,0xD4,0xDD,0xFA,0x7F,0x7F,0xA8,
+    0x35,0xE6,0xD3,0xDD,0x3B,0xAF,0xAD,0x3D,0x96,0xEE,0x35,0xE6,0x0F,0x29,0x29,0x0D,
+    0xB7,0xF6,0x96,0xEE,0xF7,0x5D,0xEF,0x67,0xB6,0xF6,0x96,0xEE,0xDE,0xF7,0x9F,0xD5,
+    0xB6,0xF6,0x76,0xEE,0xEA,0xFA,0xFA,0xFE,0x96,0xEE,0x76,0xEE,0xFE,0xDD,0xEF,0x5E,
+    0x96,0xEE,0xF3,0xDD,0xA8,0xFA,0x7A,0x78,0x35,0xE6,0x93,0xD5,0x20,0xFA,0xFE,0xFF,
+    0xF3,0xDD,0xB3,0xD5,0xEA,0x5F,0x57,0x57,0xD3,0xDD,0x92,0xD5,0xC8,0xEA,0xFF,0x75,
+    0xD3,0xDD,0x92,0xD5,0xD7,0xA5,0xBD,0x6D,0xB3,0xDD,0x71,0xCD,0x80,0xA0,0xFF,0xB7,
+    0xD3,0xDD,0x72,0xCD,0x8A,0x2A,0xEF,0xFB,0xD3,0xDD,0x92,0xD5,0xEA,0xFA,0xFB,0xFD,
+    0xB2,0xD5,0x52,0xD5,0xB8,0xAE,0xEC,0xDA,0xB2,0xD5,0x72,0xD5,0xC2,0xC9,0x7D,0x75,
+    0x66,0x72,0x25,0x72,0x20,0x08,0xA8,0x26,0x87,0x7A,0x46,0x72,0xF3,0x5C,0xE8,0x5F,
+    0x67,0x7A,0x26,0x72,0xE6,0xAE,0x0A,0x00,0x87,0x72,0x26,0x6A,0xBA,0xFF,0xFE,0xE8,
+    0x87,0x7A,0x46,0x72,0xA9,0xEF,0xEE,0x77,0x87,0x72,0x25,0x6A,0xAB,0xB7,0xFB,0xA8,
+    0x87,0x7A,0x46,0x72,0xBF,0xCA,0x0A,0xFF,0x87,0x7A,0x26,0x72,0x2A,0xEA,0xA6,0x8B,
+    0x86,0x7A,0x46,0x72,0x5A,0xF5,0xFD,0xFE,0x86,0x7A,0x26,0x6A,0xEB,0xF3,0xB8,0xF2,
+    0xA7,0x7A,0x46,0x72,0xCF,0xE7,0xFF,0xEB,0x86,0x7A,0x46,0x72,0xA9,0xAF,0xF8,0x7C,
+    0x87,0x7A,0x45,0x72,0xDC,0xE2,0xF8,0xA2,0x86,0x7A,0x46,0x72,0xE3,0xFB,0xB5,0xAD,
+    0x87,0x7A,0x45,0x72,0xFD,0xE3,0xC2,0x82,0x87,0x7A,0x45,0x72,0x69,0x73,0xE3,0xF2,
+    0x66,0x7A,0x45,0x72,0x50,0x6F,0xAE,0x2C,0x66,0x72,0x26,0x72,0xE2,0xE3,0x80,0xB2,
+    0x87,0x7A,0x25,0x72,0x72,0xAA,0xFA,0xF8,0x87,0x7A,0x25,0x72,0xDB,0xBA,0xBA,0x9A,
+    0x66,0x7A,0x46,0x72,0xB9,0xEF,0x78,0x5E,0x66,0x7A,0x46,0x72,0x98,0x80,0x40,0x62,
+    0x87,0x7A,0x46,0x72,0x62,0xEA,0xEA,0x3A,0x87,0x7A,0x46,0x72,0xF1,0x05,0xA3,0x5E,
+    0x87,0x7A,0x25,0x72,0xFD,0xAB,0xB8,0xA2,0xA7,0x82,0x46,0x72,0xFD,0xFB,0xDA,0xF2,
+    0x87,0x7A,0x25,0x72,0xEC,0xBF,0x2B,0xA8,0x87,0x82,0x46,0x72,0xFF,0x5A,0xEA,0xB2,
+    0x87,0x7A,0x25,0x72,0x8D,0xAF,0xAA,0xAF,0x87,0x82,0x25,0x72,0x5F,0xEE,0xF0,0xE2,
+    0xA7,0x82,0x46,0x72,0xFF,0xD7,0xB4,0x7A,0x29,0x93,0x46,0x7A,0xFD,0xBD,0xBD,0x2D,
+    0x2A,0x93,0xA8,0x82,0x6A,0x7F,0x7E,0x78,0x87,0x7A,0xC5,0x61,0x7C,0x7C,0xFE,0xFE,
+    0xC4,0x61,0x02,0x41,0x5E,0xF8,0xE8,0xF0,0x23,0x41,0xC2,0x30,0x7E,0xDA,0x78,0xFA,
+    0xE2,0x30,0xA1,0x30,0x7A,0x7A,0xF3,0xF7,0xC2,0x30,0x81,0x28,0xEA,0xE8,0x62,0xE2,
+    0xC2,0x28,0x61,0x28,0xAA,0xAB,0x8A,0x08,0xE3,0x30,0xA2,0x28,0x57,0xF5,0xA7,0xC9,
+    0xC2,0x30,0xA2,0x28,0x06,0xEA,0xEA,0xCB,0xC2,0x30,0xA2,0x28,0x57,0x55,0xA5,0x8E,
+    0xC2,0x30,0xA2,0x28,0x8D,0x8F,0xAA,0x52,0xC2,0x30,0x81,0x20,0xFA,0x6A,0xEA,0xBE,
+    0xC2,0x30,0x81,0x28,0x2F,0xBB,0xBF,0x2B,0x24,0x39,0xC2,0x30,0x3D,0xAD,0x2F,0xAF,
+    0x64,0x49,0x24,0x41,0x0F,0x2B,0x0B,0x29,0x65,0x49,0xE3,0x38,0x5C,0x56,0x7E,0xD8,
+    0x04,0x41,0xC2,0x38,0x5B,0x5E,0x7F,0x38,0x24,0x49,0xC2,0x38,0xA9,0xAB,0xAB,0x2A,
+    0x64,0x51,0x03,0x41,0xBD,0x2D,0x09,0x0B,0x85,0x51,0x23,0x49,0x8A,0xAA,0xFE,0x7A,
+    0xC6,0x59,0x64,0x51,0xDD,0xFD,0xEF,0xAB,0xA5,0x51,0x03,0x41,0xF8,0x7C,0x7E,0x58,
+    0x44,0x49,0x03,0x41,0xEB,0xE3,0xE2,0x63,0x65,0x49,0xE3,0x38,0x7D,0xEB,0xA3,0xFF,
+    0x24,0x41,0xC2,0x38,0xFD,0xFF,0xC8,0x28,0x24,0x41,0xE2,0x38,0xED,0xEB,0xAD,0x80,
+    0x23,0x41,0xC2,0x38,0x2A,0xAA,0xEE,0x6A,0x44,0x41,0xC2,0x38,0xE8,0xB7,0x7D,0xD5,
+    0x65,0x49,0xE3,0x38,0x5F,0xAF,0xA9,0x2F,0x65,0x49,0xE2,0x38,0xB5,0xAF,0x3E,0x0A,
+    0x64,0x49,0x23,0x41,0xDF,0xBA,0x28,0xA0,0x44,0x49,0xE3,0x38,0x5E,0x5A,0x58,0x7E,
+    0xE3,0x38,0xA2,0x30,0x36,0xFE,0xDE,0x9E,0x24,0x41,0xC2,0x38,0xAF,0xBD,0x2F,0xAB,
+    0xA5,0x51,0x44,0x49,0xAD,0x09,0x09,0xA5,0x06,0x62,0x84,0x51,0x5F,0x7D,0xF3,0xAB,
+    0xC5,0x59,0x23,0x41,0xBF,0xDF,0x5E,0x7C,0x44,0x49,0x03,0x41,0xE0,0x7C,0x7F,0x7E,
+    0x23,0x49,0xE2,0x40,0xAF,0x2D,0x35,0x25,0x84,0x51,0x23,0x49,0x25,0x3D,0x35,0xB7,
+    0x67,0x72,0xA5,0x59,0xF5,0xFD,0xB5,0x2D,0x67,0x7A,0xC5,0x61,0xDD,0xBF,0xAA,0x80,
+    0x26,0x6A,0xE5,0x69,0xD5,0x6E,0x64,0xE8,0x06,0x6A,0xA5,0x61,0xE8,0xF2,0xF2,0x78,
+    0x47,0x72,0xA4,0x61,0x03,0xFD,0xF5,0x55,0x47,0x7A,0xA4,0x61,0x20,0xAB,0xF7,0x5D,
+    0x46,0x7A,0xA4,0x61,0x2A,0xAA,0xAD,0xFD,0x67,0x7A,0x26,0x72,0x00,0x00,0xAB,0x5D,
+    0x67,0x72,0xC5,0x61,0xDA,0xAA,0xA8,0xE2,0x07,0x6A,0xA4,0x59,0x02,0xAA,0xFC,0x7E,
+    0x47,0x72,0xA4,0x59,0x08,0xAB,0x2F,0xB5,0x26,0x6A,0xA5,0x59,0xEE,0xD8,0x5A,0x78,
+    0xE6,0x61,0xA5,0x59,0xFF,0xF0,0x7E,0x75,0xC6,0x59,0x64,0x51,0xA2,0xA2,0xDA,0x5B,
+    0x07,0x62,0x64,0x51,0xA2,0x02,0xBB,0x75,0xE6,0x59,0x64,0x51,0xBE,0xB2,0xF2,0xFD,
+    0xA5,0x59,0x43,0x49,0x80,0x9A,0x38,0x38,0x06,0x62,0xA5,0x59,0x2F,0x25,0xF5,0xF7,
+    0x47,0x72,0xA4,0x59,0x08,0xBF,0xDD,0x5F,0xC9,0x82,0xE6,0x61,0x22,0x2B,0xAD,0xF5,
+    0xC9,0x82,0x67,0x7A,0xFB,0xCE,0x6B,0xF9,0x2D,0xAC,0x67,0x7A,0x2F,0xBD,0xF5,0xFD,
+    0x72,0xD5,0x8B,0x9B,0x02,0x0F,0x2D,0xB5,0xF4,0xE5,0x72,0xD5,0x00,0xA2,0xAB,0xAD,
+    0xF4,0xE5,0xB3,0xDD,0x20,0xA2,0xA3,0xE9,0xD3,0xDD,0xB3,0xDD,0x76,0xF0,0x20,0x80,
+    0xF3,0xDD,0xB3,0xDD,0x6B,0xEF,0x7A,0x5E,0xB3,0xDD,0x72,0xD5,0x02,0x08,0xFE,0x7F,
+    0xD3,0xDD,0x92,0xD5,0x0A,0x2D,0x95,0x55,0xF4,0xDD,0x92,0xD5,0x00,0x08,0x8F,0xAD,
+    0xD3,0xE5,0x14,0xDE,0xAA,0xAA,0xAE,0xFE,0x55,0xEE,0xD3,0xDD,0xB5,0x29,0x2B,0x2A,
+    0x55,0xEE,0xF4,0xDD,0x80,0xB0,0x7C,0x5A,0x35,0xEE,0x92,0xD5,0xA0,0x20,0xFE,0x5F,
+    0x35,0xE6,0xB3,0xD5,0x20,0x00,0x00,0x09,0x55,0xEE,0x14,0xE6,0xD7,0x7E,0xFE,0xE3,
+    0x35,0xEE,0x14,0xDE,0xD7,0xFF,0xB6,0xA2,0x35,0xE6,0xF4,0xDD,0xEB,0xEF,0xEA,0x60,
+    0x35,0xE6,0xF4,0xE5,0xAB,0xAF,0x8A,0x2A,0x35,0xE6,0xF4,0xE5,0xFB,0xEA,0xA8,0x82,
+    0x35,0xE6,0xD4,0xDD,0xBA,0x2A,0x2A,0x0A,0x96,0xEE,0x35,0xE6,0x09,0x0B,0x0B,0x0B,
+    0xB6,0xF6,0x76,0xEE,0xCA,0x6A,0xEA,0xAA,0xB6,0xF6,0x75,0xEE,0x6B,0xEF,0xAB,0xEA,
+    0x76,0xF6,0x96,0xEE,0xD5,0xF5,0xFF,0xDD,0x96,0xEE,0x76,0xEE,0xD8,0xCA,0x3E,0xA8,
+    0x76,0xEE,0x14,0xE6,0x60,0xC0,0xC0,0x00,0x35,0xE6,0xB3,0xD5,0x7F,0xDC,0x5A,0x78,
+    0xD3,0xDD,0x93,0xD5,0xBE,0xFF,0xAA,0xAA,0xD3,0xDD,0x92,0xD5,0x7E,0xBE,0xFE,0x5A,
+    0xB2,0xD5,0x92,0xD5,0x65,0x75,0x75,0xFD,0xB2,0xD5,0x72,0xCD,0xF7,0xBA,0xEA,0xEE,
+    0x92,0xD5,0x72,0xCD,0x80,0xAA,0xE2,0xBE,0x92,0xD5,0x51,0xCD,0x02,0x2B,0x2A,0xEA,
+    0x92,0xD5,0x51,0xCD,0xF8,0xFA,0x9F,0x57,0x92,0xD5,0x51,0xCD,0x7F,0x77,0xEF,0x9D,
+    0x67,0x7A,0x46,0x72,0x3D,0xAA,0xCF,0x9A,0x67,0x7A,0x46,0x72,0xB4,0x50,0xFE,0x0A,
+    0x87,0x7A,0x47,0x72,0xDA,0xBF,0xEF,0xBB,0x67,0x7A,0x46,0x72,0xDB,0x82,0xC2,0x8B,
+    0x67,0x72,0x46,0x72,0x3A,0x7A,0xFA,0x97,0x87,0x7A,0x46,0x72,0x7C,0x6B,0x43,0xF2,
+    0x87,0x7A,0x46,0x72,0x7F,0xA1,0xBE,0xAD,0x87,0x7A,0x25,0x6A,0x2A,0xAA,0xE6,0xF8,
+    0xA7,0x7A,0x26,0x6A,0xEE,0xBE,0xB6,0x2B,0x46,0x7A,0x66,0x72,0x7D,0xD5,0xBD,0x77,
+    0x87,0x7A,0x46,0x72,0x0E,0xAB,0xBB,0xB5,0x86,0x7A,0x45,0x72,0xDE,0xAC,0x2A,0xA2,
+    0x86,0x7A,0x46,0x72,0xA8,0xAA,0xBD,0xAA,0x86,0x7A,0x46,0x72,0xBF,0xEC,0xE2,0xA2,
+    0x86,0x7A,0x46,0x72,0xD7,0x45,0x8F,0xBE,0x86,0x7A,0x46,0x72,0xEF,0xB7,0xAA,0xAA,
+    0x87,0x7A,0x45,0x72,0xAF,0xBF,0xAF,0x8A,0x86,0x7A,0x46,0x72,0xFB,0xEA,0xEA,0x9C,
+    0xA7,0x7A,0x67,0x72,0xFF,0x7D,0xFB,0xB3,0x86,0x7A,0x46,0x72,0xAE,0xFE,0xF6,0xD6,
+    0x87,0x7A,0x46,0x72,0xA5,0xAE,0xFE,0xAA,0x67,0x7A,0x46,0x72,0xB7,0xAB,0x3E,0x22,
+    0x87,0x82,0x46,0x72,0xFF,0xDA,0x98,0x3F,0x87,0x7A,0x46,0x7A,0xAA,0x83,0xEA,0x60,
+    0x87,0x7A,0x46,0x72,0xBA,0xF8,0x1D,0x9B,0x86,0x7A,0x45,0x7A,0x8A,0xE8,0x2C,0xB9,
+    0x87,0x7A,0x46,0x7A,0xBE,0xAF,0xAA,0xA2,0x87,0x7A,0x26,0x7A,0xAC,0xA8,0xA8,0x82,
+    0x87,0x7A,0x25,0x72,0xA9,0xFA,0xBA,0x28,0xA7,0x82,0x66,0x7A,0x57,0xF5,0xAD,0xB9,
+    0xC8,0x8A,0x46,0x72,0x7F,0x7E,0xFF,0x3B,0xCB,0xA3,0xA8,0x82,0xF5,0xA5,0x0D,0x0B,
+    0xCB,0xA3,0xA7,0x82,0x7E,0x5E,0x78,0x7C,0x87,0x82,0xE5,0x61,0x7E,0x7C,0x7C,0x58,
+    0xE5,0x61,0x43,0x49,0x7E,0x5E,0x7C,0x5C,0x03,0x41,0xC2,0x30,0xE4,0x56,0x5E,0x54,
+    0xC2,0x30,0xA1,0x28,0x36,0x8F,0xC6,0x80,0xC2,0x30,0xA2,0x28,0x58,0x5F,0x5F,0x95,
+    0xE3,0x30,0xA2,0x28,0xB7,0xB7,0xAE,0x8F,0x03,0x31,0xA2,0x28,0xAD,0xD7,0xAE,0xB2,
+    0xE3,0x30,0xA2,0x28,0xE9,0xE8,0xC2,0x80,0xC2,0x30,0xA2,0x28,0x0B,0x2F,0x35,0x88,
+    0xE3,0x30,0xA2,0x28,0x7E,0xEE,0x7D,0x57,0xC2,0x30,0x82,0x28,0xFF,0xFF,0xFB,0x23,
+    0x03,0x39,0xA2,0x28,0x95,0xA5,0xB7,0x2A,0x43,0x41,0xE3,0x38,0xE5,0xAD,0xAF,0x8F,
+    0x85,0x49,0x23,0x41,0x2D,0xAD,0xED,0x77,0x64,0x49,0xC2,0x38,0xF8,0x78,0x7A,0x7F,
+    0x23,0x41,0xC2,0x38,0xBE,0x3D,0x0D,0x8F,0xA6,0x51,0x44,0x49,0x7D,0x8D,0x0D,0x89,
+    0xA6,0x51,0x24,0x49,0xF5,0x7E,0x68,0x68,0x64,0x49,0x24,0x41,0xAE,0x0B,0x0F,0xC5,
+    0xA5,0x59,0x03,0x41,0x0A,0x8A,0xEE,0x5F,0xC5,0x59,0xE3,0x38,0xF8,0xF2,0xFF,0x7D,
+    0x24,0x41,0xC2,0x38,0xE8,0x58,0xDA,0xF2,0x03,0x39,0xC2,0x38,0x0E,0xAD,0x17,0xB5,
+    0x24,0x41,0xE3,0x38,0x03,0x23,0x3D,0x5D,0x65,0x49,0x03,0x41,0xEA,0x3A,0x9A,0x5F,
+    0x64,0x49,0xC1,0x38,0x6A,0xF0,0xE8,0xAB,0x03,0x41,0xC2,0x30,0xD5,0xA9,0xAA,0x80,
+    0x23,0x41,0xE3,0x38,0x2B,0x23,0x3F,0x2B,0x85,0x51,0x03,0x41,0x8B,0x2B,0x2D,0xAD,
+    0xA6,0x51,0x23,0x41,0xFC,0xFE,0x7E,0x5F,0x45,0x49,0xC2,0x38,0x7F,0x76,0xFA,0x82,
+    0x03,0x39,0xC2,0x38,0xD5,0xF7,0xA6,0xBE,0x03,0x41,0xC2,0x38,0x2F,0xEF,0xBE,0x82,
+    0x85,0x49,0x03,0x41,0x2D,0xFD,0xFD,0xD5,0xC6,0x59,0x23,0x41,0x22,0x2F,0xB5,0xD5,
+    0xC5,0x51,0x24,0x49,0xF8,0x6E,0xFF,0x7F,0x44,0x49,0x03,0x41,0x7A,0x50,0x72,0xB1,
+    0x64,0x49,0x03,0x41,0xB5,0xBD,0x9D,0x2A,0xE5,0x61,0x64,0x51,0x55,0xDD,0xAF,0x2D,
+    0x26,0x6A,0x84,0x59,0x2D,0xF5,0xFE,0xAB,0x47,0x72,0xA4,0x59,0x80,0x02,0xAB,0xB7,
+    0x26,0x6A,0x84,0x59,0xA8,0xF0,0x60,0x78,0xE5,0x61,0x64,0x51,0xE8,0xBB,0xFF,0x7F,
+    0xC5,0x61,0x43,0x51,0x22,0xAA,0xB7,0xD5,0xC5,0x61,0x84,0x59,0xF2,0xFA,0x6B,0xFB,
+    0xC5,0x61,0x84,0x59,0xB2,0x0D,0x37,0x3D,0x27,0x72,0x84,0x59,0xAB,0xFF,0x7A,0x70,
+    0x27,0x6A,0x84,0x59,0xEA,0x8B,0x2D,0xFF,0x06,0x6A,0x64,0x51,0xFA,0x7A,0x7C,0x7A,
+    0xA4,0x59,0x44,0x51,0x2B,0x37,0x57,0x7D,0xE6,0x61,0x44,0x49,0xA0,0xAF,0x57,0x55,
+    0xA5,0x59,0x44,0x49,0x08,0x8B,0xFA,0xFF,0x85,0x51,0x44,0x49,0xFE,0x70,0x6A,0x7B,
+    0x85,0x51,0x23,0x49,0x2F,0xB7,0xBD,0x5F,0xC6,0x59,0x64,0x49,0xF5,0x8B,0x0D,0x25,
+    0x06,0x62,0x64,0x51,0x7F,0xEA,0xAA,0x0A,0x06,0x62,0x84,0x51,0xBF,0xF7,0x77,0xD8,
+    0x06,0x62,0x84,0x51,0xAA,0x2F,0xBD,0xD7,0xE5,0x61,0x84,0x59,0x22,0xFA,0x62,0xAF,
+    0x67,0x72,0xA5,0x59,0x02,0x09,0xAD,0x55,0xE9,0x8A,0x47,0x72,0x0B,0xA5,0xBD,0xD5,
+    0x4D,0xB4,0xE9,0x8A,0x2B,0x2F,0xBD,0xB5,0x92,0xDD,0xEC,0xA3,0x02,0x2B,0x2B,0x25,
+    0xF4,0xE5,0xB3,0xDD,0xA3,0x8B,0x2B,0x2D,0xF4,0xE5,0x92,0xD5,0xAA,0xBA,0x7A,0xFC,
+    0xB3,0xDD,0x51,0xCD,0xA0,0xF8,0xDA,0xFA,0x92,0xD5,0x72,0xD5,0x6F,0xAF,0xF5,0xF5,
+    0xD3,0xDD,0x72,0xCD,0xAD,0xB7,0x2F,0x0F,0xF4,0xDD,0x92,0xD5,0xA9,0x0B,0xAA,0x2B,
+    0x34,0xE6,0xF4,0xDD,0xFD,0x2D,0xAF,0xF5,0x35,0xE6,0xD3,0xDD,0x02,0xFA,0xFE,0x55,
+    0x14,0xE6,0xD3,0xDD,0xE0,0xB7,0x7F,0xDD,0xD3,0xDD,0x72,0xCD,0xD8,0x78,0x58,0x5E,
+    0x14,0xE6,0x92,0xD5,0x0B,0x0D,0x0D,0x29,0x35,0xE6,0xF4,0xDD,0x80,0x7B,0xFE,0xBE,
+    0x55,0xEE,0x14,0xE6,0x87,0x0D,0x03,0x02,0x76,0xEE,0x14,0xE6,0xDE,0xA2,0x8A,0x8A,
+    0x55,0xEE,0x35,0xE6,0x75,0xF2,0xC0,0x50,0x14,0xEE,0x35,0xE6,0xD5,0xF7,0xB5,0xAD,
+    0x35,0xE6,0x14,0xE6,0x3F,0xB9,0x23,0xBB,0xB7,0xF6,0x55,0xE6,0xFD,0x3D,0x29,0x0B,
+    0xB6,0xF6,0x96,0xEE,0x7A,0xE8,0x7A,0x7E,0x76,0xFE,0x96,0xEE,0xD5,0xDF,0x75,0x77,
+    0x96,0xEE,0x76,0xEE,0x08,0xA0,0xB2,0x66,0x96,0xEE,0x76,0xEE,0xA2,0xEA,0xDE,0x7B,
+    0x76,0xEE,0x56,0xE6,0x08,0x00,0x00,0xA0,0x76,0xEE,0xD3,0xDD,0x5E,0xE0,0xE8,0x88,
+    0x14,0xE6,0xB3,0xD5,0x5F,0x5F,0xFE,0x60,0xD3,0xDD,0x92,0xD5,0xFC,0xFF,0xEE,0xB8,
+    0xB2,0xD5,0x52,0xCD,0xAA,0xAA,0xA8,0xE0,0x92,0xD5,0x72,0xCD,0x08,0x0A,0x98,0x88,
+    0xB2,0xD5,0x72,0xCD,0xF6,0x7A,0xFB,0xFE,0x92,0xD5,0x71,0xCD,0x67,0xFE,0x6F,0x7A,
+    0x71,0xCD,0x51,0xCD,0x77,0x5E,0x5F,0x9A,0x71,0xCD,0x31,0xC5,0xAB,0xFB,0xFB,0xAA,
+    0x67,0x7A,0xA4,0x61,0x02,0x0A,0xAA,0xD5,0x88,0x7A,0xE5,0x69,0x8A,0xAE,0x0E,0x2D,
+    0x67,0x72,0x26,0x72,0xC2,0x8A,0x27,0xAC,0x67,0x7A,0x46,0x72,0x06,0xEA,0x50,0x50,
+    0x67,0x7A,0x46,0x72,0x57,0x70,0x7A,0xE3,0x87,0x72,0x25,0x6A,0x82,0xAB,0xE7,0xAA,
+    0x86,0x7A,0x46,0x72,0x76,0xA5,0xAB,0xF5,0x87,0x7A,0x46,0x72,0xBF,0xAA,0xCF,0xEF,
+    0x87,0x7A,0x46,0x72,0xF9,0x78,0x80,0x00,0x87,0x7A,0x46,0x72,0xB9,0xA3,0x89,0x3E,
+    0xA7,0x7A,0x46,0x72,0x74,0x77,0xDF,0xDE,0x86,0x7A,0x46,0x72,0x8F,0xAB,0xFB,0xFD,
+    0x86,0x7A,0x46,0x72,0x88,0x8B,0x0A,0x89,0xA7,0x7A,0x45,0x72,0xEA,0x78,0xAA,0xBF,
+    0x86,0x7A,0x66,0x72,0xC3,0xBB,0xBE,0x57,0x86,0x7A,0x45,0x72,0xA2,0xB8,0x0D,0x88,
+    0xA7,0x7A,0x66,0x72,0xFA,0xE2,0x56,0xDF,0x86,0x7A,0x66,0x72,0xDE,0xE6,0x8B,0xA6,
+    0xA7,0x7A,0x66,0x72,0xF4,0xD7,0x7D,0x7B,0x86,0x7A,0x46,0x72,0xBE,0xFA,0x6E,0xD5,
+    0xA7,0x82,0x66,0x7A,0xE5,0x75,0x75,0x75,0x87,0x7A,0x46,0x7A,0xB9,0x33,0x0B,0xAB,
+    0x87,0x7A,0x25,0x7A,0xAA,0x62,0xAA,0xAA,0x87,0x7A,0x46,0x72,0xCD,0xA5,0xBF,0x3E,
+    0xA7,0x7A,0x66,0x7A,0x75,0x75,0x6B,0xEB,0xC8,0x82,0x45,0x72,0xF5,0xED,0x2B,0x8B,
+    0xA7,0x82,0x66,0x7A,0xFA,0xB6,0xE4,0x67,0xA7,0x82,0x46,0x72,0x8B,0x2F,0xB7,0xBA,
+    0xA7,0x82,0x66,0x7A,0x9E,0xAB,0xAA,0xAA,0xA7,0x7A,0x46,0x72,0xAC,0xBF,0xE6,0xEB,
+    0x2A,0x93,0x86,0x7A,0x17,0xA5,0x2D,0x2D,0x0D,0xAC,0x29,0x93,0x29,0x2B,0x0B,0x0A,
+    0xEC,0xAB,0xE8,0x8A,0x78,0x78,0xF8,0x78,0xC8,0x82,0xC6,0x61,0x7A,0x7A,0xF8,0x7C,
+    0xC5,0x61,0x03,0x41,0x78,0x60,0xE8,0xEC,0x23,0x41,0xC2,0x38,0xD7,0xAA,0xAA,0x00,
+    0x03,0x39,0xA2,0x28,0xDF,0x6E,0x6A,0xF0,0xA2,0x30,0xC2,0x28,0x4A,0x6E,0xFF,0xBA,
+    0xE3,0x30,0xA2,0x28,0x8A,0xF3,0xF9,0x75,0xE3,0x30,0xA2,0x28,0x3A,0xAB,0xBF,0xFF,
+    0xE3,0x30,0xA2,0x28,0xA0,0xEA,0xF8,0x7A,0xC2,0x30,0xA2,0x28,0xE0,0x42,0xC2,0x61,
+    0xC2,0x28,0x82,0x20,0xB0,0x2A,0xBF,0xBD,0xE3,0x30,0xA2,0x28,0xA5,0x2F,0x2E,0x2B,
+    0x44,0x41,0xE3,0x30,0xF5,0xBD,0xEF,0x2A,0x44,0x41,0x03,0x39,0x29,0x83,0x0B,0x00,
+    0x44,0x49,0xC2,0x30,0xE8,0xB2,0xFE,0x5E,0x03,0x39,0xC2,0x38,0xBE,0xBE,0x3F,0x0B,
+    0x44,0x41,0xE2,0x38,0xB7,0x2F,0x3B,0xAD,0xA5,0x51,0x24,0x41,0x83,0xAB,0xBD,0xF5,
+    0x85,0x51,0x24,0x41,0x62,0xE8,0x68,0x6B,0x23,0x41,0xC2,0x38,0x8A,0xFC,0x78,0x7E,
+    0x03,0x41,0xA2,0x30,0x20,0xBA,0xFB,0x77,0xC2,0x40,0x03,0x39,0xFB,0xEE,0xFA,0xEF,
+    0x24,0x41,0xC2,0x38,0xBE,0xBB,0xEF,0x7B,0x03,0x39,0xA2,0x30,0x0A,0x20,0xBE,0x97,
+    0x24,0x41,0xC3,0x30,0x7F,0xFA,0x8A,0xAF,0x24,0x41,0xC2,0x38,0xF2,0xFD,0xB5,0xF7,
+    0x24,0x41,0xE3,0x38,0x0D,0xBF,0x7B,0xED,0x23,0x41,0xE2,0x38,0xA0,0xAC,0xA7,0x0F,
+    0x44,0x41,0x03,0x41,0xDF,0x83,0xE1,0x2B,0x44,0x41,0x03,0x41,0x37,0x35,0x57,0x56,
+    0x64,0x49,0x23,0x41,0xDA,0x03,0xE1,0x7F,0x85,0x51,0x24,0x41,0x7B,0x8A,0xAA,0xFB,
+    0x65,0x49,0x03,0x41,0x55,0x5E,0xFA,0xF8,0x65,0x49,0x03,0x39,0x57,0x7F,0x6B,0x23,
+    0x85,0x49,0x03,0x41,0xDD,0xE5,0xA9,0xA2,0x85,0x51,0x24,0x41,0xB5,0x37,0xBE,0xFD,
+    0x85,0x51,0x24,0x49,0x6A,0x6A,0xFA,0xAE,0x84,0x51,0x03,0x41,0xBD,0xAF,0xBA,0x82,
+    0x85,0x51,0x23,0x49,0xAB,0xAF,0x2F,0xA4,0xE6,0x61,0x84,0x51,0xA5,0x25,0xAD,0x0B,
+    0x26,0x62,0xC5,0x61,0xAF,0x3F,0xFF,0xB5,0x06,0x6A,0xA4,0x59,0x2E,0x78,0x7E,0x5A,
+    0xE5,0x69,0x64,0x51,0xF8,0xFB,0xD5,0xF7,0xC5,0x61,0x64,0x51,0xFF,0x72,0xA8,0xA3,
+    0xA5,0x59,0x23,0x51,0xD6,0x97,0xE2,0xA0,0xE6,0x69,0x84,0x59,0xFD,0xF9,0xBD,0x25,
+    0x07,0x6A,0xA5,0x61,0xDD,0xDF,0x29,0x0A,0x47,0x72,0xA5,0x61,0x7A,0xCA,0xEB,0xE8,
+    0xA5,0x59,0x44,0x51,0xF0,0xFE,0x9F,0xA8,0xC5,0x61,0x44,0x49,0xE8,0xAB,0xEB,0xF7,
+    0x85,0x51,0x23,0x51,0x6A,0xAB,0x0B,0x02,0x84,0x51,0x44,0x49,0x75,0xFF,0x6F,0xFC,
+    0x64,0x49,0x23,0x49,0x8A,0xEB,0x67,0x88,0x85,0x51,0x23,0x49,0x8B,0x2B,0xBD,0xE5,
+    0x85,0x51,0x23,0x49,0x7E,0xAE,0x02,0x0B,0xC6,0x59,0x64,0x49,0x2D,0x2D,0xBF,0xFF,
+    0x06,0x62,0xA5,0x51,0x8A,0xAA,0xEB,0xEF,0x06,0x62,0x84,0x51,0xA8,0xCA,0xEB,0x6D,
+    0xE6,0x61,0xA5,0x59,0x76,0x7A,0xED,0x05,0xE6,0x61,0x84,0x51,0x2D,0xAF,0xA6,0xFA,
+    0x27,0x72,0xA5,0x59,0xDD,0xBA,0xAA,0x2F,0x88,0x7A,0xE6,0x69,0x2D,0xAD,0x2B,0x2B,
+    0x49,0x93,0xA8,0x7A,0x2D,0x35,0xBD,0xBD,0x4D,0xB4,0xE9,0x8A,0x0B,0xAF,0xFF,0xDD,
+    0x93,0xDD,0xEC,0xA3,0x02,0x0F,0xAD,0xB5,0xF3,0xE5,0x72,0xD5,0xFA,0xAA,0xAB,0xB5,
+    0xD3,0xDD,0x72,0xD5,0x5F,0x5E,0x7C,0xFE,0x92,0xD5,0x71,0xD5,0x0B,0x09,0xA9,0x00,
+    0xD3,0xDD,0x92,0xD5,0xAD,0xAB,0xA5,0x2D,0x14,0xE6,0xB3,0xD5,0xAF,0xED,0xBF,0x8B,
+    0xF4,0xDD,0xB2,0xDD,0x88,0xBE,0x20,0x20,0x14,0xE6,0xD3,0xDD,0xD5,0xD5,0xAE,0x08,
+    0x14,0xE6,0xD3,0xDD,0x7F,0xEB,0x62,0x60,0x92,0xD5,0xF0,0xBC,0x30,0xB8,0xF8,0x5E,
+    0x14,0xE6,0x10,0xC5,0x2B,0xAF,0xF5,0xD5,0x35,0xE6,0x92,0xD5,0x88,0x02,0x0B,0x09,
+    0x76,0xEE,0x14,0xE6,0x2B,0x22,0xAA,0xAA,0x55,0xEE,0x35,0xE6,0x80,0xF4,0x57,0x5E,
+    0x55,0xEE,0x15,0xE6,0xD2,0xBA,0xFB,0xEB,0x35,0xE6,0x14,0xE6,0xF8,0xBE,0xF8,0x5A,
+    0x55,0xE6,0x14,0xE6,0xD7,0x95,0x35,0x0D,0xB7,0xF6,0x55,0xE6,0x2F,0x29,0x2B,0xAB,
+    0xB6,0xF6,0x76,0xEE,0xA2,0xEA,0x7A,0xFE,0x96,0xEE,0x55,0xEE,0x08,0xE8,0xEA,0xFA,
+    0x96,0xEE,0x55,0xE6,0xEA,0xAB,0xAD,0xFD,0x76,0xEE,0x55,0xE6,0x02,0x0E,0x8E,0x4E,
+    0x75,0xEE,0x55,0xE6,0xE8,0xC2,0x2F,0xFB,0x35,0xEE,0x75,0xE6,0xAF,0xAF,0xB7,0xBE,
+    0x55,0xEE,0x14,0xE6,0x6B,0xA8,0x7A,0xFA,0x14,0xE6,0xB3,0xD5,0x5C,0x58,0x78,0x5A,
+    0xB2,0xD5,0x72,0xCD,0xF8,0xFC,0x2A,0x28,0xB2,0xD5,0x73,0xCD,0xBA,0xDA,0xAE,0x2B,
+    0xB2,0xD5,0x71,0xCD,0x6A,0xBA,0xF7,0xED,0x92,0xD5,0x72,0xCD,0x56,0x5E,0x75,0x6F,
+    0xB2,0xD5,0x51,0xCD,0x5B,0xFF,0xEF,0x3B,0x72,0xCD,0x10,0xC5,0xFB,0xFF,0xB4,0xF8,
+    0x83,0x59,0x43,0x59,0x6A,0xAF,0x2F,0x02,0x06,0x6A,0x63,0x59,0x29,0xFD,0xD5,0x55,
+    0x46,0x72,0x63,0x59,0x00,0xAF,0xDD,0x55,0x87,0x7A,0x84,0x61,0x08,0xA2,0xA9,0xF5,
+    0x66,0x72,0x25,0x6A,0x0B,0x0F,0x89,0xED,0x87,0x7A,0x46,0x72,0xFB,0xA7,0xA7,0x25,
+    0xA8,0x7A,0x46,0x72,0x55,0xEF,0x8A,0xFA,0x87,0x7A,0x46,0x72,0xA8,0xAB,0x52,0x62,
+    0x87,0x7A,0x46,0x72,0xAA,0xFA,0xEE,0xBB,0x87,0x7A,0x46,0x72,0x8E,0x0B,0xBF,0xBE,
+    0x87,0x7A,0x46,0x72,0x7A,0xFA,0xAA,0x83,0x87,0x7A,0x46,0x72,0xFF,0xBB,0x1E,0xDE,
+    0xA7,0x7A,0x46,0x72,0x2D,0xA7,0xBD,0xBF,0xA7,0x7A,0x66,0x72,0xBF,0xB9,0xBB,0xAD,
+    0xA7,0x7A,0x66,0x72,0xD5,0x57,0xBE,0xFC,0xA7,0x7A,0x66,0x72,0xEF,0xED,0xEA,0xDE,
+    0xA7,0x7A,0x66,0x72,0xD7,0xB7,0xB4,0x9E,0x86,0x7A,0x46,0x72,0xA8,0x0F,0x0A,0x00,
+    0x86,0x7A,0x66,0x72,0xC2,0xAC,0xCC,0x20,0x87,0x7A,0x45,0x72,0xB5,0x2A,0xF0,0xE2,
+    0xA7,0x82,0x45,0x72,0x6F,0x8F,0xBE,0xAB,0x87,0x7A,0x46,0x72,0xEB,0x72,0xBE,0xA7,
+    0x87,0x82,0x67,0x7A,0xD2,0xC2,0x6C,0x7F,0xA8,0x82,0x46,0x72,0x7F,0x7F,0x9D,0x3B,
+    0xA7,0x7A,0x66,0x7A,0xE9,0xBD,0xDC,0xBE,0xA7,0x82,0x46,0x72,0xAA,0x27,0xAA,0xAA,
+    0xA7,0x82,0x66,0x7A,0x55,0x7E,0x9E,0x58,0xA8,0x82,0x67,0x7A,0xDB,0x7F,0xCB,0xEF,
+    0x87,0x82,0x66,0x7A,0xCC,0xF5,0xDD,0xC5,0xE8,0x8A,0x66,0x7A,0xD7,0xFD,0xBF,0x3F,
+    0xCC,0xA3,0xA7,0x82,0x3D,0x2D,0x2B,0x0B,0x0E,0xB4,0x8B,0x9B,0x0A,0xAE,0xE2,0x70,
+    0xEC,0xAB,0xA7,0x82,0xF8,0x78,0x7A,0x7A,0xC8,0x82,0xC5,0x61,0x58,0x7E,0xDE,0xFE,
+    0x06,0x62,0x64,0x51,0x5F,0xFA,0xE8,0xE8,0x85,0x51,0x03,0x41,0xFE,0xFA,0x7C,0x58,
+    0x23,0x41,0xE2,0x38,0x7C,0xE8,0x6E,0x4B,0xC2,0x30,0xA2,0x28,0xEC,0x20,0xF2,0xF0,
+    0xC2,0x30,0xA2,0x28,0xE9,0xAA,0xEB,0x6B,0xE3,0x30,0xA2,0x28,0xB5,0xF5,0xBF,0x95,
+    0xC2,0x28,0xA2,0x28,0x70,0x62,0x58,0x54,0xA2,0x28,0x81,0x28,0x38,0x22,0xB0,0xB0,
+    0xA2,0x28,0x82,0x28,0x3C,0xE8,0xFE,0x38,0x03,0x39,0xA2,0x28,0x2D,0x85,0xBF,0xFF,
+    0x44,0x41,0xE2,0x30,0xAA,0xAE,0xF3,0xE5,0x44,0x41,0xE3,0x38,0xE8,0xFA,0xFF,0xD7,
+    0x23,0x41,0xA1,0x30,0x7C,0x7F,0xFF,0x3E,0x03,0x39,0xC2,0x38,0x02,0xEB,0xEF,0xC0,
+    0x24,0x41,0xC2,0x30,0x2F,0xAF,0xB7,0xBD,0x44,0x49,0xE3,0x38,0xAA,0xBF,0xDF,0xDF,
+    0x65,0x49,0xE3,0x38,0xC2,0xEA,0x7E,0x55,0x23,0x41,0xC2,0x38,0x78,0xF8,0x7B,0xFF,
+    0xE2,0x38,0xA2,0x30,0xBF,0xFA,0x78,0xFC,0x23,0x39,0xC2,0x30,0xF2,0xAB,0xAB,0xAB,
+    0x24,0x41,0xE3,0x38,0x77,0xFF,0x8B,0x06,0x04,0x41,0xA2,0x30,0x5F,0xFE,0xFA,0xB8,
+    0xE3,0x38,0x81,0x28,0x2B,0x2F,0xFF,0xF7,0xE3,0x38,0x82,0x30,0xAA,0xA8,0xDB,0xFF,
+    0x03,0x39,0xC2,0x30,0x03,0x09,0xAD,0x09,0x23,0x41,0x03,0x39,0x35,0xAF,0x3F,0x2F,
+    0x44,0x41,0x03,0x41,0x2F,0x2D,0x2B,0x0E,0x44,0x41,0xE3,0x38,0xAC,0xE0,0xDA,0xDA,
+    0x44,0x49,0xE3,0x38,0xAA,0x2E,0x0E,0xB7,0x64,0x49,0x24,0x41,0xF2,0xF8,0xFA,0x7F,
+    0x44,0x49,0x03,0x41,0xFC,0xEA,0xFE,0xFE,0x85,0x51,0x24,0x41,0x2B,0x2D,0x3B,0x0B,
+    0xA6,0x51,0x44,0x49,0xEE,0xEA,0xEA,0x50,0x64,0x49,0x03,0x41,0xA8,0x60,0xFE,0xB6,
+    0x64,0x49,0x03,0x41,0x2E,0xA9,0xBB,0x82,0x85,0x51,0x24,0x49,0x20,0x2A,0xFB,0xD8,
+    0x84,0x51,0x23,0x49,0xAA,0x2A,0xEE,0x7D,0x06,0x62,0x65,0x51,0x09,0x27,0xAD,0xA9,
+    0xE6,0x61,0x84,0x51,0xA8,0xB8,0xFE,0xDF,0xA5,0x59,0x63,0x51,0xC0,0xCB,0x8A,0xFC,
+    0xA5,0x59,0x43,0x51,0xAA,0x29,0x8A,0xB0,0xE5,0x61,0x44,0x51,0xAB,0xAF,0x2F,0xF7,
+    0xE6,0x61,0x84,0x59,0x7F,0xDA,0xEA,0x8A,0x06,0x62,0x84,0x59,0x29,0xAF,0xB5,0xFD,
+    0x27,0x6A,0xC6,0x61,0x82,0x00,0x2F,0xB9,0x27,0x6A,0xC6,0x61,0xFA,0x7A,0xE8,0xC0,
+    0xC6,0x59,0x23,0x49,0xFA,0x7A,0x7A,0x68,0x64,0x51,0x03,0x41,0x2A,0xFA,0x5D,0x57,
+    0x85,0x51,0x23,0x49,0x02,0xA2,0x0C,0x3D,0x85,0x51,0x44,0x49,0xB8,0xBA,0x70,0x28,
+    0x64,0x51,0x44,0x49,0xA8,0xAC,0xB6,0x25,0xA6,0x51,0x23,0x49,0xEF,0xEB,0xF9,0xF8,
+    0xE6,0x59,0x44,0x49,0xB7,0xA9,0x22,0x2D,0xC6,0x59,0x43,0x49,0xFB,0xB6,0xF8,0xE0,
+    0xC6,0x59,0x65,0x51,0xB2,0x7A,0xB7,0xF7,0xA5,0x51,0x64,0x51,0x62,0xFA,0x79,0x65,
+    0xE6,0x59,0x43,0x49,0x2A,0xAF,0xB7,0xD5,0xE6,0x59,0x84,0x51,0x40,0xA2,0x3A,0x7D,
+    0x47,0x72,0xC6,0x59,0x25,0xAD,0x2F,0x29,0x87,0x7A,0x27,0x6A,0x0F,0x03,0xAA,0x21,
+    0xE9,0x82,0x87,0x7A,0x0B,0x22,0x89,0x7F,0x6B,0x93,0xC8,0x82,0x0B,0x7F,0x7F,0x7D,
+    0x8F,0xBC,0xE8,0x8A,0x2F,0xBD,0xFD,0x55,0xB3,0xDD,0x8B,0x9B,0x22,0x0B,0x2F,0xAD,
+    0xF4,0xE5,0x92,0xD5,0x7B,0xFB,0xAF,0x29,0xF4,0xDD,0x72,0xD5,0x5F,0x7F,0xB8,0x80,
+    0x14,0xE6,0x92,0xD5,0xBD,0xAD,0x0F,0x0A,0x35,0xEE,0xF4,0xDD,0xEF,0xAF,0xA2,0xAA,
+    0x35,0xE6,0xF4,0xDD,0xDB,0xBE,0xAB,0x2A,0x35,0xE6,0xD3,0xDD,0xAB,0xB7,0x2A,0x82,
+    0x14,0xE6,0x72,0xCD,0xC0,0x78,0x70,0x70,0x31,0xC5,0xCF,0xBC,0xFC,0xF7,0xDE,0x3A,
+    0x72,0xCD,0xF0,0xC4,0xB5,0xBD,0xAB,0x2A,0x55,0xEE,0x92,0xD5,0x2D,0x25,0x2D,0x2D,
+    0x75,0xEE,0x35,0xE6,0xE0,0xA2,0xE8,0xEA,0x55,0xEE,0x14,0xE6,0xFE,0x7E,0xE2,0x78,
+    0x35,0xE6,0x14,0xE6,0xC0,0x3B,0x7F,0x75,0x35,0xE6,0x14,0xE6,0x96,0x9F,0x25,0x05,
+    0x96,0xEE,0x35,0xE6,0xB5,0x2D,0x3F,0x2A,0x76,0xF6,0x96,0xEE,0xD6,0xF5,0xFF,0xF7,
+    0x96,0xEE,0x35,0xE6,0x80,0xA8,0xAA,0xAA,0x95,0xEE,0x55,0xE6,0xF4,0xFF,0x57,0x55,
+    0x75,0xEE,0x55,0xE6,0xBF,0x17,0x97,0xDF,0x75,0xEE,0x55,0xE6,0xFE,0xA8,0xFB,0xBF,
+    0x75,0xEE,0x55,0xE6,0xAF,0xAB,0xB9,0xFF,0x76,0xEE,0x55,0xE6,0xF2,0xEA,0xB2,0xFB,
+    0x55,0xEE,0x35,0xE6,0x7A,0x78,0xFA,0xBA,0x75,0xEE,0xB3,0xD5,0x5E,0x7A,0xAA,0xAA,
+    0x14,0xE6,0x92,0xD5,0x77,0xFF,0x68,0x80,0xB3,0xDD,0x72,0xD5,0xEA,0xEE,0xDB,0xF8,
+    0xB3,0xD5,0x71,0xD5,0x3B,0x2A,0x8B,0x60,0xB3,0xD5,0x72,0xD5,0xB2,0xA0,0xAA,0x7F,
+    0xB2,0xD5,0x51,0xCD,0xFF,0xF8,0xFA,0xEB,0x71,0xCD,0x51,0xCD,0x6F,0xAB,0xE7,0xAF,
+    0x83,0x61,0x43,0x59,0xF8,0xFA,0xAF,0xC9,0xA4,0x61,0x63,0x59,0x5F,0x37,0x5F,0x95,
+    0x84,0x59,0x43,0x59,0xAF,0xB6,0xEB,0xBE,0xC5,0x69,0x44,0x59,0x0F,0xEB,0xFF,0x6F,
+    0xE5,0x69,0x43,0x59,0x0A,0xAF,0xF7,0xF5,0x67,0x7A,0xA4,0x61,0x0A,0xBF,0x55,0x55,
+    0x87,0x7A,0xA4,0x61,0xA0,0xAA,0xBF,0xD5,0x66,0x72,0x05,0x6A,0x02,0x0A,0xFE,0xB5,
+    0x66,0x72,0x25,0x72,0x82,0x02,0x37,0x2B,0xA7,0x7A,0x45,0x72,0xFE,0x77,0x6E,0x3E,
+    0x87,0x7A,0x25,0x72,0x0B,0x8B,0xAF,0xA5,0x87,0x7A,0x66,0x72,0xDF,0xD1,0xF3,0x8B,
+    0xA7,0x7A,0x46,0x72,0xFF,0xAB,0x3B,0x2F,0x86,0x7A,0x46,0x72,0x2E,0xAA,0xF2,0xC8,
+    0xA7,0x7A,0x46,0x72,0xE8,0x6A,0xEB,0xF2,0xA7,0x7A,0x66,0x72,0x5D,0xE9,0x29,0xFB,
+    0xA7,0x7A,0x66,0x72,0x6D,0x8F,0xAE,0x5C,0xA7,0x7A,0x66,0x72,0xEA,0xCF,0xF7,0xBD,
+    0xA7,0x7A,0x66,0x72,0xFA,0xDF,0xD6,0x5A,0x87,0x7A,0x46,0x72,0x8A,0x00,0x89,0xB9,
+    0x87,0x7A,0x45,0x72,0x0D,0x2F,0x0A,0x22,0x87,0x7A,0x46,0x72,0xF0,0x7A,0xAA,0x0A,
+    0x87,0x7A,0x26,0x7A,0xCA,0xA2,0x8A,0x80,0xA7,0x82,0x66,0x7A,0x25,0xF7,0xBA,0x8E,
+    0xA7,0x82,0x46,0x7A,0xA8,0xAA,0xAA,0xAD,0x87,0x82,0x66,0x7A,0x3A,0xA5,0xD5,0x57,
+    0xA7,0x82,0x66,0x7A,0xDE,0xB6,0xF8,0xFF,0xA7,0x82,0x66,0x7A,0xA9,0xA1,0xEA,0x13,
+    0xA7,0x82,0x66,0x7A,0x77,0x7B,0x7A,0xFE,0x6A,0x9B,0x46,0x72,0xBF,0xB5,0x2D,0x0B,
+    0x0D,0xB4,0x6A,0x9B,0x2D,0x0D,0x2A,0x02,0x2D,0xB4,0xCC,0xA3,0x78,0x80,0xC0,0xDE,
+    0xCC,0xA3,0x66,0x7A,0x78,0x78,0x7C,0x7A,0x46,0x72,0xE5,0x69,0xE8,0xBA,0xFC,0x5C,
+    0x06,0x6A,0x63,0x49,0xF8,0x70,0x7A,0x5E,0x64,0x51,0xE2,0x38,0x70,0x68,0xEA,0x7A,
+    0x03,0x41,0xE2,0x38,0x62,0xDA,0x0E,0x35,0x03,0x39,0xA2,0x30,0x5E,0xDE,0x50,0x7C,
+    0xC2,0x38,0xA2,0x28,0x5E,0x57,0xD7,0xD7,0xC1,0x30,0x82,0x20,0x2F,0xFB,0xEE,0xFA,
+    0xA2,0x28,0x81,0x28,0xF0,0x60,0x83,0x02,0xC2,0x28,0x82,0x28,0xFB,0xBF,0xFB,0xAA,
+    0xC2,0x28,0x61,0x28,0x2A,0xAA,0x2B,0xA2,0xE3,0x30,0xA2,0x30,0x6E,0xEB,0x8A,0xEB,
+    0xE3,0x30,0xA2,0x30,0x2B,0xEA,0xD8,0x7A,0xE3,0x38,0xA2,0x30,0x2E,0xA7,0xF7,0xFE,
+    0x44,0x41,0xC2,0x38,0x3D,0xA5,0x2D,0xBD,0x44,0x41,0xE3,0x38,0xF8,0xE0,0x78,0xF8,
+    0x03,0x39,0xC2,0x38,0x6F,0xAA,0xAE,0x2E,0x24,0x41,0xE3,0x38,0x7A,0x7C,0x2A,0x22,
+    0x24,0x41,0xC2,0x30,0x7E,0xFB,0xE0,0xF0,0x44,0x41,0xC2,0x30,0xDD,0xBD,0x2F,0x2B,
+    0x43,0x49,0xA1,0x30,0xDF,0x5F,0xEE,0xA0,0x24,0x41,0xE3,0x38,0xFD,0xA9,0x0B,0x80,
+    0x23,0x41,0xC2,0x38,0x0E,0xBA,0xFC,0x7A,0x24,0x41,0xC3,0x38,0xF0,0xE2,0xFF,0xFF,
+    0xC3,0x30,0x82,0x30,0xF6,0xFA,0xF0,0xB2,0xE3,0x38,0x82,0x30,0xFF,0xB7,0xB7,0x2B,
+    0x24,0x41,0xC2,0x38,0xAD,0x3D,0x23,0xAA,0x44,0x41,0xE3,0x38,0xBF,0xBB,0xFF,0x0D,
+    0x64,0x49,0x24,0x41,0xA5,0xBD,0xD7,0x5E,0x64,0x49,0x24,0x41,0x57,0x72,0xE2,0x7E,
+    0x23,0x41,0xE2,0x38,0xAC,0xB0,0xE3,0xEF,0x24,0x41,0xE3,0x38,0x80,0x8A,0xFB,0x9B,
+    0x44,0x49,0xE3,0x38,0xAB,0xAB,0xAF,0x15,0x85,0x51,0x24,0x41,0x8B,0x22,0xBB,0x5F,
+    0xA6,0x51,0x03,0x39,0xE0,0xFB,0x7B,0xDD,0x44,0x41,0xE3,0x38,0xAE,0xBA,0x3F,0x1E,
+    0x85,0x51,0x24,0x41,0xBB,0x0F,0xFF,0x77,0x65,0x51,0x03,0x41,0xEC,0xE0,0x6A,0x5D,
+    0x24,0x49,0xE3,0x40,0x0A,0x2B,0xBA,0x5A,0xC6,0x59,0x23,0x49,0x8B,0xA9,0xE9,0xF5,
+    0xA5,0x59,0x44,0x49,0xF8,0xFA,0x7B,0x7F,0x64,0x51,0x23,0x49,0x20,0xAA,0xA2,0xFF,
+    0x64,0x51,0x03,0x41,0x80,0xBA,0x9E,0xD7,0x85,0x59,0x23,0x49,0x0E,0xA7,0xA7,0x2D,
+    0xE6,0x61,0x85,0x59,0x8B,0xA1,0xBB,0xFF,0xE6,0x61,0x85,0x51,0xA8,0xAE,0x77,0x7F,
+    0x06,0x62,0x84,0x51,0xA2,0xAB,0xBE,0xFD,0x27,0x6A,0x84,0x51,0x80,0xAE,0xEF,0x77,
+    0xE6,0x61,0x85,0x51,0x6A,0xE0,0xEE,0x9F,0xC6,0x59,0x23,0x49,0x5F,0xEE,0xEA,0x80,
+    0x64,0x51,0x02,0x41,0x3F,0xBF,0xC0,0xA8,0x85,0x51,0x23,0x41,0x0A,0xAD,0xDD,0xBF,
+    0x64,0x49,0x23,0x41,0x03,0x8C,0x86,0xAA,0x64,0x49,0x44,0x49,0x20,0x1C,0x2F,0x29,
+    0xC6,0x59,0x64,0x49,0x2D,0xAD,0xFD,0xFF,0xE6,0x59,0x64,0x49,0xA0,0xAA,0xD5,0x57,
+    0xA5,0x51,0x44,0x49,0xEC,0xA0,0xAA,0x7F,0x85,0x51,0x23,0x41,0x8F,0xAA,0xFB,0x7E,
+    0xA5,0x51,0x23,0x49,0x2E,0x2B,0x2F,0xAF,0xC5,0x51,0x64,0x51,0xFE,0xFE,0xDC,0xB7,
+    0x07,0x6A,0xA5,0x59,0x27,0xA5,0xA5,0x9D,0x87,0x7A,0x06,0x62,0x2A,0xAB,0xAF,0xF5,
+    0xC8,0x82,0x88,0x7A,0xBB,0xC1,0xCD,0xBD,0xE8,0x82,0xA7,0x82,0xAA,0xAF,0xB3,0x7F,
+    0x29,0x8B,0xC7,0x82,0x3F,0xBF,0x75,0xE5,0x31,0xCD,0x09,0x8B,0x2F,0xBD,0xD5,0xD5,
+    0xD4,0xE5,0x0D,0xAC,0x02,0x02,0x0B,0x2D,0x14,0xE6,0xD3,0xE5,0xFE,0xAA,0x22,0x8B,
+    0x55,0xE6,0xF4,0xE5,0xFD,0xBD,0x8F,0xAF,0x55,0xEE,0x14,0xE6,0x57,0xD5,0x3A,0x0E,
+    0x55,0xEE,0x14,0xE6,0xB5,0xAE,0xAA,0x20,0x55,0xEE,0x15,0xE6,0xFA,0xFA,0xFF,0xFC,
+    0xF4,0xE5,0xD0,0xBC,0xE0,0xE0,0xE8,0x78,0x72,0xCD,0x10,0xC5,0xB7,0x27,0xAD,0xF5,
+    0x72,0xCD,0x30,0xCD,0xFB,0xF8,0xAE,0xDD,0x35,0xE6,0x31,0xCD,0x0F,0x2D,0x2F,0xAD,
+    0x76,0xEE,0x34,0xE6,0xFB,0xEB,0xAB,0x81,0x55,0xEE,0x15,0xE6,0x7A,0xEE,0xEA,0xA2,
+    0x76,0xEE,0x14,0xE6,0xDD,0xF7,0xB7,0x2F,0x96,0xEE,0x14,0xE6,0xBD,0x2F,0xAB,0x02,
+    0x96,0xEE,0x76,0xEE,0x3D,0x3F,0xA8,0x82,0xB6,0xF6,0x76,0xEE,0xFA,0xFB,0x5F,0x57,
+    0x76,0xEE,0x55,0xE6,0xA0,0xE0,0x38,0xDE,0x35,0xF6,0x55,0xE6,0x55,0xDD,0x5D,0xDD,
+    0x55,0xEE,0x75,0xE6,0x2E,0xEB,0xEE,0xAE,0x75,0xEE,0x35,0xE6,0x2A,0x3E,0xFE,0xAA,
+    0x75,0xEE,0x35,0xE6,0x8A,0xA8,0xAA,0xB7,0x55,0xEE,0x75,0xE6,0xAA,0xA8,0xA8,0xFE,
+    0x75,0xEE,0x55,0xE6,0xDE,0xDF,0xAF,0xC0,0x75,0xEE,0x35,0xE6,0x7E,0xFE,0x9E,0xBA,
+    0x55,0xE6,0x14,0xE6,0xFA,0x6A,0xA0,0x00,0x55,0xEE,0xB3,0xD5,0x5E,0xEA,0xA8,0x80,
+    0x15,0xE6,0x92,0xD5,0xF7,0x7F,0xFA,0xA0,0xD4,0xDD,0x92,0xD5,0x5D,0x55,0xDE,0xF9,
+    0xB3,0xDD,0x71,0xD5,0x7E,0x6A,0xAB,0xB0,0x92,0xD5,0x51,0xCD,0x97,0xEE,0xAC,0x20,
+    0x84,0x61,0x43,0x59,0xFD,0xEB,0x02,0xCB,0x84,0x61,0x43,0x59,0x3F,0xFE,0xDE,0xBF,
+    0x84,0x61,0x43,0x59,0x8E,0xB4,0xDB,0x72,0xA5,0x61,0x43,0x59,0xF8,0x7C,0x5E,0x5F,
+    0x84,0x61,0x23,0x51,0x2D,0x22,0x80,0xA2,0xA4,0x61,0x63,0x59,0xFA,0x7E,0xF7,0x69,
+    0x84,0x61,0x63,0x59,0x39,0x55,0xAD,0xF9,0xE4,0x69,0x63,0x59,0x2B,0xAD,0xB5,0x79,
+    0x46,0x72,0x63,0x59,0x0A,0xAB,0xFD,0x5D,0x87,0x7A,0x83,0x59,0x02,0xAA,0xBD,0x55,
+    0x66,0x72,0xC4,0x61,0x28,0x80,0x2A,0xB5,0x87,0x7A,0x66,0x72,0x91,0x05,0x7A,0x79,
+    0xA7,0x82,0x66,0x72,0xFA,0xF8,0xFD,0x7D,0x86,0x7A,0x66,0x72,0xE0,0x74,0xD7,0xAE,
+    0xA7,0x7A,0x66,0x72,0xE6,0xAF,0xFB,0x2F,0x87,0x7A,0x46,0x72,0x8E,0xB0,0xA8,0xFE,
+    0xA7,0x7A,0x66,0x72,0xFF,0x56,0xDA,0x7D,0xA7,0x7A,0x66,0x72,0xCD,0x5F,0xEF,0xF7,
+    0x87,0x7A,0x46,0x72,0xC8,0xC2,0x42,0x03,0xA7,0x7A,0x46,0x72,0xBD,0x2F,0xAB,0xEB,
+    0xA8,0x7A,0x66,0x7A,0xF7,0x7F,0xEA,0x57,0x87,0x7A,0x46,0x7A,0x88,0xA2,0x92,0x12,
+    0xA7,0x82,0x67,0x7A,0xAF,0xB7,0xDF,0xFF,0xA7,0x82,0x67,0x7A,0xCB,0x56,0x8E,0xB2,
+    0xA7,0x82,0x46,0x72,0xED,0xAF,0x2B,0xA2,0x87,0x82,0x67,0x7A,0x9F,0xBD,0x34,0x02,
+    0xA7,0x82,0x67,0x7A,0xF4,0xAC,0xBF,0xF9,0xA7,0x82,0x66,0x7A,0xEA,0xAA,0xBF,0x58,
+    0x29,0x93,0x87,0x7A,0x5D,0x5D,0x95,0x3D,0xEC,0xAB,0xA7,0x82,0x2D,0x2F,0x0A,0x0A,
+    0x0D,0xAC,0xAB,0xA3,0x88,0xA8,0xBF,0xFF,0xEC,0xAB,0xAC,0xA3,0x80,0xE8,0xAE,0xB4,
+    0xCB,0xA3,0x86,0x7A,0x58,0x78,0xF8,0xE8,0x46,0x72,0xA5,0x59,0xDC,0x5C,0x5C,0x5C,
+    0xA5,0x59,0x43,0x49,0x70,0xE8,0x62,0xFE,0x64,0x49,0x02,0x41,0x5E,0xFE,0x68,0x50,
+    0x03,0x41,0xE2,0x38,0x7D,0xF8,0xDE,0x55,0xE2,0x30,0xA2,0x28,0xE8,0xF0,0x6A,0x7A,
+    0x82,0x30,0xA2,0x28,0xDF,0x7D,0xFB,0x7F,0xC2,0x30,0xA2,0x28,0xDF,0x7B,0xEA,0x68,
+    0xC2,0x28,0x81,0x28,0xBB,0x6E,0xEB,0x83,0xC2,0x30,0xA2,0x28,0x6B,0x8D,0x2E,0x00,
+    0xC2,0x30,0xA2,0x28,0x82,0x8B,0x23,0xAB,0xE3,0x30,0xA2,0x30,0xA7,0x2F,0xAB,0x02,
+    0xE3,0x38,0xA1,0x28,0x5B,0xFE,0xAE,0x2A,0x03,0x39,0xA2,0x30,0xF7,0xBF,0xFF,0xA2,
+    0x24,0x41,0xC2,0x30,0xED,0xAA,0x82,0x02,0x45,0x41,0x03,0x41,0xDF,0xDF,0xFB,0xAD,
+    0x24,0x41,0xE3,0x38,0x36,0x85,0xBB,0xA0,0x44,0x41,0x03,0x41,0xAE,0xBF,0xFB,0xBA,
+    0x65,0x49,0x03,0x39,0x53,0xE9,0xC3,0xEB,0x44,0x49,0xE3,0x38,0x2F,0xBB,0xFE,0x5A,
+    0x65,0x49,0x03,0x41,0x6A,0xAA,0xAB,0x0B,0x85,0x51,0x03,0x41,0x7F,0xFB,0xEA,0x78,
+    0x24,0x41,0xC3,0x38,0xDA,0xD4,0x5E,0xDF,0xE3,0x38,0xC2,0x30,0xEE,0x63,0xC1,0x00,
+    0xE3,0x38,0xA2,0x30,0x55,0x9B,0xAA,0x80,0x03,0x39,0xC3,0x38,0xA5,0x2D,0x2F,0x3F,
+    0x44,0x41,0x03,0x39,0x75,0xAB,0x2B,0x2B,0x85,0x51,0x03,0x39,0xF5,0xEA,0xC0,0x22,
+    0x44,0x49,0x03,0x41,0xDC,0x5E,0x5E,0x5B,0x24,0x41,0x03,0x39,0xEA,0xEF,0xB9,0xC1,
+    0x03,0x41,0xE3,0x38,0xBE,0xF8,0xEC,0xAA,0x24,0x41,0xE3,0x38,0xFF,0xAF,0x8B,0x0B,
+    0x24,0x49,0xE3,0x38,0x05,0xFF,0xDE,0x56,0x24,0x41,0xE3,0x38,0x80,0xBB,0xF9,0x6F,
+    0x44,0x41,0x04,0x41,0xF5,0xF5,0x9D,0x9F,0x44,0x41,0x03,0x41,0xD5,0x5E,0xFE,0x2A,
+    0x44,0x51,0x03,0x41,0xF7,0xBF,0x2F,0x3F,0x44,0x49,0x03,0x41,0xD5,0xFE,0xE2,0xA0,
+    0x24,0x49,0xE3,0x40,0x56,0x97,0xAE,0xAE,0x44,0x49,0xE3,0x40,0x0B,0xAA,0xEE,0x7E,
+    0x44,0x49,0x03,0x41,0xA8,0xEA,0xAF,0xED,0x23,0x49,0xE2,0x40,0x80,0xA0,0xE8,0x55,
+    0x23,0x49,0xE2,0x38,0xAA,0xFA,0xFB,0xBF,0x85,0x59,0x23,0x41,0x0D,0xBD,0xFD,0xA5,
+    0xA5,0x59,0x64,0x49,0x22,0x2A,0xAB,0xFD,0xC6,0x59,0x64,0x51,0xEA,0xAA,0x3E,0x6F,
+    0xA5,0x59,0x44,0x49,0x0B,0x0B,0xAA,0xBD,0x85,0x51,0x44,0x49,0x98,0xD8,0xDC,0x6F,
+    0xA5,0x51,0x24,0x49,0x28,0xCA,0xFF,0xDF,0xC6,0x59,0x44,0x49,0xA0,0xEB,0xFF,0x5F,
+    0x85,0x51,0x23,0x41,0xFE,0xFE,0x72,0x5E,0x85,0x51,0x23,0x49,0xAF,0xAF,0xBF,0xAD,
+    0x65,0x49,0x23,0x41,0xF4,0xD8,0xD6,0x5F,0x85,0x51,0x23,0x41,0x8F,0xBB,0xAF,0xF5,
+    0xA5,0x51,0x44,0x49,0x3D,0xFF,0xD7,0x57,0xA5,0x51,0x44,0x49,0xB8,0xA8,0xAF,0xD5,
+    0xA6,0x51,0x23,0x41,0xDF,0xFE,0xFC,0xDF,0x64,0x49,0x23,0x41,0x5E,0xFC,0xFA,0x57,
+    0x44,0x49,0x03,0x41,0x2E,0xB7,0x94,0x9A,0xA4,0x51,0x44,0x49,0xA7,0x2F,0xA7,0xEF,
+    0xE5,0x61,0x84,0x51,0x3D,0x29,0xAD,0x3F,0x26,0x6A,0xE5,0x61,0xB9,0xEA,0xA1,0x89,
+    0xA8,0x7A,0xC5,0x61,0x2A,0xBD,0x55,0x55,0xA7,0x82,0x06,0x6A,0x02,0xAB,0xB7,0xF5,
+    0xE8,0x8A,0x87,0x7A,0x8F,0x2A,0x82,0xB5,0x09,0x8B,0xA7,0x7A,0x8E,0xFF,0xFE,0x7A,
+    0x10,0xCD,0x08,0x8B,0x2D,0x2D,0xBD,0xB5,0xF4,0xE5,0x31,0xCD,0x02,0x09,0x0D,0x2D,
+    0x35,0xE6,0xD3,0xDD,0x0B,0xA5,0xBF,0x0A,0x55,0xEE,0x35,0xE6,0x3B,0xBF,0x09,0xAA,
+    0x55,0xEE,0x14,0xE6,0x80,0xE0,0xFA,0x5E,0x35,0xE6,0xD3,0xDD,0x20,0xA8,0x6A,0x5F,
+    0xD4,0xDD,0xF0,0xC4,0x78,0x78,0x5E,0x5E,0x31,0xCD,0xF0,0xC4,0xCF,0xA9,0x23,0x22,
+    0x51,0xCD,0x10,0xC5,0xF7,0xB5,0xB7,0xA7,0xF4,0xDD,0x51,0xCD,0x3D,0x35,0x35,0xBD,
+    0x56,0xEE,0xF4,0xDD,0x02,0x02,0x03,0x09,0x96,0xEE,0x55,0xEE,0xD5,0xFD,0xEF,0xB5,
+    0x96,0xEE,0x56,0xEE,0xB7,0x2B,0x2A,0x02,0xB6,0xF6,0x76,0xEE,0xAF,0xAB,0xAA,0xAB,
+    0x96,0xEE,0x76,0xEE,0x80,0x70,0xC0,0xEA,0x55,0xEE,0x96,0xE6,0xBF,0xAB,0xEA,0xAB,
+    0x75,0xEE,0x55,0xE6,0x6F,0xE0,0x80,0x2E,0x75,0xEE,0x55,0xE6,0xAD,0xC7,0xFF,0x7F,
+    0x75,0xEE,0x55,0xE6,0xAA,0xF0,0x7B,0x7F,0x76,0xEE,0x35,0xE6,0xB2,0xFA,0xBB,0xBB,
+    0x76,0xEE,0x35,0xE6,0xA7,0xD7,0x6E,0xEB,0x76,0xEE,0x55,0xE6,0x20,0x22,0x2F,0x3D,
+    0x76,0xEE,0x55,0xE6,0xE2,0x5F,0xAE,0xCE,0x35,0xEE,0x55,0xE6,0x75,0xF5,0xFF,0x77,
+    0x75,0xEE,0x55,0xE6,0x5F,0x5F,0xEF,0xFD,0x75,0xEE,0x35,0xE6,0x6B,0xFA,0xEA,0xAB,
+    0x55,0xE6,0xF4,0xDD,0x72,0xA2,0x80,0xA0,0x56,0xEE,0xD3,0xD5,0x77,0x2A,0x0A,0x88,
+    0x56,0xEE,0x92,0xD5,0x57,0xFE,0xE2,0x00,0x35,0xE6,0x92,0xD5,0xD5,0x77,0xBB,0x20,
+    0x84,0x61,0x43,0x59,0x7E,0xEA,0xCB,0xAA,0x64,0x59,0x23,0x59,0x03,0x00,0x08,0xFC,
+    0x84,0x59,0x43,0x59,0xDF,0xB5,0x15,0xF5,0xA4,0x61,0x43,0x59,0x7B,0xCA,0xEF,0xFF,
+    0x84,0x61,0x43,0x59,0xE2,0x3B,0xB7,0x77,0xA4,0x61,0x43,0x59,0xF3,0xBF,0xFE,0xE6,
+    0x84,0x61,0x63,0x59,0x55,0x97,0xFD,0xCA,0xA4,0x61,0x63,0x59,0xB2,0xF7,0x7F,0x7A,
+    0x83,0x59,0x23,0x51,0xA8,0xAE,0xFE,0xBD,0x84,0x59,0x43,0x51,0xAE,0xBF,0xFD,0x75,
+    0xC4,0x61,0x22,0x51,0x0A,0xFF,0x5F,0x7F,0x26,0x72,0x43,0x51,0x02,0xA7,0xD5,0x55,
+    0x87,0x7A,0x44,0x51,0x02,0xAA,0xBD,0x75,0x87,0x7A,0xA5,0x61,0x0A,0x20,0xAB,0xFD,
+    0x87,0x7A,0x26,0x72,0x08,0x82,0x0B,0xBD,0xA7,0x7A,0x46,0x7A,0xFC,0xEA,0xBA,0x7E,
+    0x87,0x7A,0x46,0x72,0xCA,0xCC,0x8B,0xE9,0xA7,0x7A,0x66,0x7A,0xFE,0x77,0x6F,0x71,
+    0x87,0x7A,0x46,0x72,0xAB,0x3C,0x1C,0xBA,0xA7,0x82,0x46,0x72,0xEA,0xEA,0xEA,0xDB,
+    0xA7,0x82,0x67,0x7A,0xDD,0x77,0xFA,0x4B,0x66,0x82,0x87,0x7A,0xD5,0x9F,0xDF,0xB6,
+    0xA7,0x82,0x67,0x7A,0xFD,0xB9,0xAF,0xEB,0xA7,0x82,0x67,0x7A,0x43,0xAB,0x2B,0xAB,
+    0xA7,0x82,0x67,0x7A,0xE9,0x0B,0xAF,0xFD,0xA7,0x82,0x66,0x7A,0xFE,0x5E,0x3F,0x3E,
+    0xA7,0x82,0x66,0x7A,0x97,0xF7,0xBA,0xD8,0xA7,0x82,0x67,0x7A,0xB8,0xFA,0xBE,0xBE,
+    0xAB,0xA3,0x87,0x7A,0xB5,0x2D,0x2B,0x0B,0x0C,0xAC,0xAB,0xA3,0x8D,0xAF,0xBA,0xAB,
+    0xEC,0xAB,0xAB,0xA3,0x20,0xB0,0xAA,0xFD,0xEC,0xAB,0xCB,0xA3,0x5E,0x0B,0xED,0x4D,
+    0xCB,0xA3,0x08,0x8B,0x68,0x68,0x60,0xE8,0xA7,0x82,0xA5,0x59,0x5E,0x5C,0x7C,0x68,
+    0x84,0x51,0x44,0x51,0xE4,0x38,0x9E,0x5E,0x64,0x49,0x02,0x41,0x78,0xE8,0xF0,0x68,
+    0x03,0x41,0xC2,0x38,0xE2,0xCA,0xE8,0xC0,0xE2,0x38,0xC2,0x30,0x57,0x56,0x76,0x52,
+    0xC2,0x30,0xA2,0x28,0x27,0x0A,0x2C,0x24,0xC3,0x38,0xA2,0x28,0xBA,0xBA,0xB0,0xAA,
+    0xE3,0x30,0xA2,0x30,0xFF,0xB2,0xA0,0xE2,0xE3,0x30,0xA2,0x30,0xAB,0xEE,0xEE,0xAA,
+    0x65,0x49,0xC3,0x30,0x55,0xD5,0xBD,0x2B,0x65,0x49,0xE3,0x38,0xFD,0xFF,0xEA,0xA0,
+    0x44,0x41,0xE3,0x38,0x77,0xFE,0xFB,0xA2,0x24,0x41,0x03,0x39,0xF7,0xFB,0x2C,0x28,
+    0x44,0x41,0x03,0x41,0xF2,0xFA,0xEF,0x8D,0x44,0x41,0x03,0x39,0x8B,0xEE,0xB7,0xA7,
+    0x44,0x41,0xE3,0x38,0xF6,0xAA,0xAA,0x0A,0x44,0x41,0x03,0x41,0xF3,0x62,0x6D,0x5F,
+    0x24,0x41,0xC2,0x38,0x02,0xEA,0xFA,0x7E,0x03,0x41,0xC3,0x38,0xE8,0xBF,0x2F,0x0B,
+    0x85,0x49,0xE3,0x38,0x29,0xAF,0xAB,0xBF,0x85,0x49,0x03,0x41,0xF8,0x7A,0xFA,0xFA,
+    0x44,0x49,0xE3,0x38,0x55,0xFF,0xEA,0x2A,0x64,0x49,0xE3,0x38,0xDD,0x95,0xF5,0xF8,
+    0x43,0x49,0xE3,0x38,0x75,0x7D,0xFE,0x8A,0x23,0x41,0xE3,0x38,0x7D,0xF7,0xE2,0x80,
+    0x24,0x41,0xC2,0x30,0x83,0xEA,0x7F,0xB7,0x64,0x49,0x03,0x39,0x03,0x29,0xBD,0xB5,
+    0x44,0x41,0x03,0x41,0x56,0x5C,0xF7,0xEF,0x24,0x41,0xC2,0x30,0x82,0xF2,0x78,0xFE,
+    0x24,0x41,0xC3,0x38,0xAC,0xBF,0xBD,0xBF,0x24,0x41,0xE3,0x38,0x0B,0x8E,0x29,0x0F,
+    0x24,0x41,0xE3,0x38,0xE6,0x88,0x80,0x00,0x24,0x41,0xE3,0x38,0x8F,0xAF,0xAF,0xFB,
+    0x64,0x49,0x03,0x41,0xF5,0xFD,0x0D,0x29,0x85,0x51,0x24,0x41,0xF5,0xD5,0xBE,0x2A,
+    0x85,0x51,0x03,0x41,0xF7,0xFF,0xEE,0xA0,0x64,0x49,0x23,0x41,0x7E,0x52,0xDB,0x75,
+    0x24,0x49,0x03,0x41,0x3D,0xFD,0x69,0xC2,0x65,0x51,0x03,0x41,0xFF,0xAD,0xA9,0xAA,
+    0x44,0x49,0x03,0x41,0xEB,0xFE,0x68,0xFE,0x24,0x49,0xC2,0x38,0xF7,0xF6,0xEA,0xEA,
+    0x03,0x41,0xE2,0x40,0xA5,0x05,0x25,0x3A,0x85,0x51,0x03,0x41,0xAD,0x3D,0x2D,0x35,
+    0xA5,0x51,0x64,0x51,0xAF,0xE2,0x43,0xEA,0x85,0x51,0x23,0x49,0x42,0xC8,0x68,0xA8,
+    0x44,0x49,0x03,0x41,0xAA,0x7D,0xD5,0xFA,0x44,0x49,0x03,0x41,0xA6,0x57,0xF7,0x97,
+    0x44,0x49,0x03,0x41,0xA8,0xB9,0x7F,0x5F,0x64,0x49,0x03,0x41,0xA0,0x2F,0xAD,0x55,
+    0x44,0x49,0xE3,0x38,0xF8,0xE8,0xAA,0xDF,0x64,0x49,0x03,0x41,0x0F,0x29,0x27,0xF5,
+    0x64,0x49,0x23,0x41,0xFE,0xBF,0xA0,0xA0,0x64,0x49,0x24,0x41,0xB7,0xFF,0xBE,0xFA,
+    0x64,0x49,0x23,0x41,0xFE,0x97,0xF7,0x5A,0x85,0x49,0x23,0x41,0xED,0xCE,0xFF,0x7D,
+    0x44,0x41,0x03,0x41,0xAA,0x78,0x7A,0x6E,0x23,0x41,0xE3,0x38,0x0A,0xAF,0x8A,0x00,
+    0x64,0x49,0x03,0x41,0xAE,0x89,0x2D,0xAB,0xA4,0x51,0x44,0x49,0xBD,0xF5,0x9F,0x29,
+    0x06,0x6A,0x84,0x51,0x2B,0xAF,0x8D,0xAF,0x47,0x72,0xE5,0x61,0xAD,0xCB,0x2B,0x0B,
+    0x67,0x72,0xE6,0x61,0x57,0x7E,0xF2,0xA2,0x66,0x72,0xE6,0x69,0x3D,0xAD,0xBF,0x2E,
+    0xC8,0x82,0x46,0x72,0x29,0x29,0xAD,0x2D,0xE8,0x82,0xA8,0x82,0x5C,0x7E,0x6B,0x27,
+    0x2C,0xAC,0xC8,0x82,0x3D,0xB5,0xF5,0xD5,0xB3,0xDD,0xAB,0x9B,0x02,0x0B,0x09,0x2D,
+    0x55,0xEE,0xF4,0xE5,0x0A,0x2F,0xEF,0xFD,0x55,0xEE,0xF4,0xE5,0x28,0xA2,0xFB,0x5F,
+    0x35,0xE6,0xB3,0xD5,0xA0,0xEA,0x7E,0x7F,0xF4,0xDD,0x52,0xCD,0xE8,0xE8,0x7A,0x7A,
+    0x52,0xCD,0xF0,0xC4,0xFC,0xFA,0x7E,0xFF,0x31,0xCD,0x10,0xC5,0xB5,0xAF,0x09,0x83,
+    0x51,0xCD,0x31,0xC5,0xB5,0xEB,0xBF,0x69,0xB2,0xD5,0x30,0xCD,0x2F,0xAF,0xA7,0xBD,
+    0x56,0xEE,0xD3,0xDD,0x0B,0x0D,0x2D,0x35,0x96,0xEE,0x56,0xEE,0xB7,0xAB,0xAB,0x2B,
+    0xB6,0xF6,0x76,0xEE,0x77,0xFD,0xFF,0x2F,0xB6,0xF6,0x96,0xEE,0xDD,0xB5,0xB7,0xF9,
+    0x96,0xEE,0x76,0xEE,0x48,0xF8,0x5C,0x8A,0x96,0xEE,0x35,0xE6,0xAA,0xEA,0x2A,0xA0,
+    0x55,0xEE,0x75,0xE6,0xEA,0xEE,0xEA,0xAF,0x55,0xEE,0x75,0xE6,0xAA,0xBA,0xAA,0xA2,
+    0x76,0xEE,0x35,0xE6,0xAD,0xAA,0xBB,0xFE,0x55,0xEE,0x55,0xE6,0xFF,0xEF,0xFF,0xFF,
+    0x56,0xEE,0x55,0xE6,0xFF,0xFF,0xBF,0x9B,0x75,0xEE,0x35,0xE6,0x8E,0xFA,0xFE,0xAA,
+    0x56,0xEE,0x75,0xE6,0x9E,0xAA,0xAA,0xEB,0x76,0xEE,0x55,0xE6,0xDF,0x73,0xFA,0xA0,
+    0x96,0xEE,0x55,0xE6,0x55,0x55,0xFD,0xA8,0x96,0xEE,0x35,0xE6,0xDF,0xFF,0xFA,0x82,
+    0x96,0xEE,0x35,0xE6,0x5F,0xDF,0xBA,0x0B,0x76,0xEE,0x35,0xE6,0xFF,0xBF,0x20,0x00,
+    0x76,0xEE,0x56,0xE6,0x75,0x8F,0x0B,0xAA,0x76,0xEE,0x35,0xE6,0x55,0xFF,0xE8,0x5C,
+    0x63,0x59,0x23,0x51,0x00,0xA3,0xAB,0xBF,0x64,0x59,0x23,0x51,0x9E,0xB3,0x2E,0x0F,
+    0x85,0x61,0x44,0x59,0xF9,0xDA,0xEF,0x8A,0x84,0x59,0x43,0x59,0xAF,0xCD,0xB5,0xF7,
+    0x84,0x61,0x43,0x59,0xDA,0x82,0x6E,0xAB,0x84,0x59,0x43,0x59,0xD4,0xBD,0x9A,0xB8,
+    0x84,0x59,0x43,0x59,0x20,0x8B,0x88,0x68,0x84,0x59,0x22,0x51,0xCA,0x7A,0x7E,0x57,
+    0x43,0x51,0x22,0x51,0x8B,0xDF,0xEA,0x48,0x63,0x51,0x22,0x51,0xDE,0x5F,0xEB,0x6B,
+    0x43,0x51,0x02,0x49,0xBA,0xAB,0x7F,0xD9,0x44,0x59,0x03,0x49,0x97,0x3F,0xA7,0x2F,
+    0x64,0x51,0x02,0x49,0x0B,0xAE,0xEA,0x9A,0x85,0x61,0x23,0x51,0x2A,0x9F,0xBF,0x8D,
+    0x26,0x72,0x43,0x59,0x02,0xEB,0xF5,0xFD,0x66,0x7A,0x84,0x61,0x80,0xAF,0xF5,0x55,
+    0x66,0x7A,0xA4,0x61,0x00,0x0A,0x2B,0xF5,0x87,0x7A,0x26,0x7A,0x22,0xEA,0x0A,0xB9,
+    0xA7,0x82,0x67,0x7A,0xFF,0x7E,0x77,0xD7,0x87,0x7A,0x67,0x7A,0x25,0x00,0x2B,0x59,
+    0xA7,0x82,0x66,0x7A,0xEB,0x9A,0xF8,0xEB,0xA8,0x82,0x67,0x7A,0xA1,0x6F,0xA9,0x0F,
+    0xA8,0x82,0x46,0x7A,0xC2,0x87,0x2E,0xFE,0xA8,0x82,0x66,0x7A,0x7E,0xEC,0xA8,0xAA,
+    0xC8,0x82,0x87,0x7A,0x5D,0xFB,0xAF,0xB5,0xA7,0x82,0x87,0x7A,0xB7,0xDA,0x96,0x16,
+    0xC8,0x82,0x66,0x7A,0xDC,0xFE,0xFE,0xEE,0x8B,0xA3,0x87,0x82,0xD5,0xF5,0x9D,0x3F,
+    0xEC,0xAB,0x4A,0x93,0x2D,0x09,0x8B,0xA2,0xEB,0xAB,0xAB,0xA3,0xAA,0xBE,0x76,0x5F,
+    0xCC,0xA3,0xAB,0xA3,0x95,0x95,0x6E,0xAB,0xEB,0xAB,0xAB,0xA3,0xCA,0xAD,0xD9,0x57,
+    0xCB,0xA3,0x08,0x8B,0xE0,0xC0,0x68,0x60,0xE8,0x82,0x84,0x59,0xF8,0xF8,0x78,0x7E,
+    0x84,0x59,0x23,0x49,0x7C,0xD8,0x7A,0x50,0x43,0x49,0xE2,0x40,0xE0,0xE8,0xBF,0x7F,
+    0x44,0x49,0xE2,0x38,0x7E,0xAA,0x8A,0x0A,0x03,0x41,0xC2,0x30,0x57,0x7F,0x7E,0x78,
+    0xC2,0x30,0xA1,0x30,0x0E,0x0B,0x3F,0x15,0xE3,0x38,0xA2,0x28,0xEF,0xBA,0xF8,0xF0,
+    0xC2,0x30,0xA2,0x28,0x02,0x0A,0x2A,0x03,0x03,0x39,0xC2,0x30,0xA3,0x3B,0xBF,0xBF,
+    0x44,0x41,0x03,0x39,0xAB,0xDD,0xBF,0x2B,0x44,0x49,0x24,0x41,0xC2,0x6D,0xAB,0x02,
+    0x44,0x49,0x24,0x41,0xC9,0xEA,0xE0,0xC0,0x44,0x41,0x03,0x39,0xAA,0xEB,0x7F,0xEE,
+    0x44,0x41,0x03,0x41,0x36,0xBC,0x2D,0x00,0x44,0x49,0xE3,0x38,0xAA,0xBA,0x68,0xAA,
+    0x45,0x41,0xE3,0x38,0x8A,0xBE,0x5F,0x5F,0x24,0x41,0xC2,0x38,0xF8,0xE8,0xFA,0xA7,
+    0x44,0x49,0xE3,0x38,0xF5,0xD5,0xA5,0x0F,0x64,0x49,0xE3,0x38,0xF7,0xBF,0xAA,0xAA,
+    0x44,0x49,0x03,0x41,0x17,0x9A,0x58,0xFA,0x64,0x51,0x03,0x41,0xFA,0xA2,0x0F,0x0D,
+    0x85,0x51,0x24,0x49,0xAD,0xBF,0xBF,0x3B,0x64,0x49,0x24,0x41,0x7E,0xEC,0x78,0x70,
+    0x85,0x51,0x23,0x41,0xFB,0xEA,0x2D,0xA5,0x85,0x51,0x23,0x41,0x57,0x7F,0xEA,0xCA,
+    0x24,0x41,0xC2,0x38,0xF6,0xB7,0xFE,0xE8,0x44,0x41,0xC2,0x38,0x0B,0x8A,0x0B,0xA9,
+    0x44,0x41,0x23,0x41,0x57,0x5F,0xEB,0x55,0x23,0x41,0xE3,0x38,0xDC,0x68,0xFA,0xFE,
+    0x24,0x41,0xE3,0x38,0xBD,0xDF,0x79,0xFA,0x24,0x41,0x03,0x39,0x0A,0x09,0x0D,0x05,
+    0x45,0x49,0xE3,0x38,0xEA,0x6A,0x7B,0xF7,0x03,0x41,0xE3,0x38,0x37,0x09,0x8D,0x2F,
+    0x85,0x49,0x03,0x41,0x25,0x3D,0xBD,0x27,0xC6,0x59,0x64,0x49,0xFD,0xA9,0xCB,0x03,
+    0xA5,0x51,0x23,0x41,0xF0,0x7E,0xDE,0xFA,0x44,0x49,0xE2,0x40,0xDA,0x5E,0x5C,0xD8,
+    0x24,0x49,0xE2,0x40,0x2B,0x37,0x3F,0xBB,0x85,0x51,0x24,0x49,0xFF,0xFD,0xAA,0x81,
+    0x65,0x51,0x03,0x41,0x7A,0xC2,0xE8,0xE0,0x44,0x49,0x03,0x41,0x7E,0xDE,0xAF,0xAA,
+    0x64,0x49,0x03,0x41,0xD5,0x77,0xFA,0xE2,0x85,0x51,0x23,0x49,0x1D,0xAB,0xAD,0xAD,
+    0x85,0x51,0x44,0x49,0xE8,0x7A,0xDC,0xE2,0x64,0x49,0x03,0x41,0xFF,0xFF,0x7B,0xFC,
+    0x64,0x49,0x03,0x41,0xAB,0x23,0x2B,0x9A,0x64,0x49,0x03,0x41,0xD7,0xFE,0x88,0xAB,
+    0x23,0x41,0x03,0x39,0x80,0x82,0xEE,0xC4,0x23,0x41,0xE3,0x38,0xAE,0x9F,0xFB,0x78,
+    0x23,0x41,0xC2,0x38,0xB8,0xBF,0xEF,0xA5,0x65,0x49,0xE3,0x38,0xBF,0x37,0xF5,0xD7,
+    0x85,0x49,0x24,0x41,0xFA,0x2B,0xAF,0xF5,0x64,0x49,0x03,0x41,0x28,0xAA,0xEA,0xFA,
+    0x64,0x49,0x03,0x39,0xB2,0xFA,0x7A,0x7D,0x44,0x41,0xE2,0x38,0x2A,0x88,0xAF,0xB7,
+    0x44,0x41,0x03,0x41,0xFE,0xE2,0xEE,0x65,0x44,0x49,0x03,0x41,0xA9,0x0B,0x07,0xB5,
+    0xA5,0x51,0x23,0x41,0xFD,0xBB,0x2B,0xAB,0xC5,0x59,0x44,0x49,0xA9,0x25,0xB8,0xC8,
+    0x27,0x6A,0x85,0x51,0xAF,0x2B,0xBD,0xFD,0x67,0x72,0xE6,0x61,0xEB,0xAA,0x21,0x25,
+    0xA8,0x7A,0x26,0x6A,0xE5,0xFF,0xAE,0x0A,0xA8,0x82,0x26,0x6A,0xD5,0xFF,0x0E,0x22,
+    0xA8,0x82,0x67,0x72,0xBF,0xDB,0xFB,0x6A,0xE9,0x82,0x67,0x7A,0xAF,0xAB,0xAD,0xAF,
+    0x09,0x8B,0xA8,0x82,0x0B,0x2A,0x16,0x3D,0xEF,0xC4,0x29,0x93,0x2D,0xB5,0xB5,0xF5,
+    0xF4,0xE5,0x6E,0xB4,0x02,0x02,0x0B,0x2D,0x15,0xE6,0xD4,0xDD,0xE8,0xFA,0x7A,0xFB,
+    0x15,0xE6,0xD4,0xDD,0x7F,0xBF,0x83,0x03,0xD4,0xDD,0x31,0xC5,0x70,0x70,0xD0,0x58,
+    0x31,0xCD,0xF0,0xC4,0xAA,0xAA,0xEE,0x7D,0x31,0xCD,0xF0,0xBC,0xAA,0xEA,0x3B,0xAD,
+    0x51,0xCD,0x10,0xCD,0x83,0x29,0x6E,0xAA,0x72,0xCD,0x31,0xCD,0xA7,0xCF,0xBF,0xAD,
+    0x15,0xE6,0x72,0xD5,0x09,0x09,0x2D,0x25,0x96,0xEE,0x35,0xE6,0x0B,0x2A,0x0B,0x09,
+    0xB6,0xF6,0x76,0xEE,0x2E,0xBF,0xB9,0xFF,0xB7,0xF6,0x96,0xEE,0xBF,0xAF,0xD5,0x55,
+    0xB6,0xF6,0x76,0xEE,0xF7,0xFF,0xFF,0xAB,0x96,0xEE,0x55,0xE6,0xB0,0x6A,0x2A,0x00,
+    0xB6,0xF6,0x55,0xE6,0xFF,0xFF,0xAF,0x22,0xB6,0xF6,0x55,0xE6,0xF5,0xFF,0xAA,0xA2,
+    0xB6,0xF6,0x55,0xE6,0x77,0xFF,0xAA,0x20,0xB6,0xF6,0x76,0xEE,0xD5,0xBF,0xA8,0xA2,
+    0xB7,0xF6,0x76,0xEE,0x57,0xBA,0xAA,0xE8,0x96,0xF6,0x76,0xEE,0x39,0xAA,0x28,0xD7,
+    0xB6,0xF6,0x55,0xE6,0xBE,0x8A,0xEA,0x7E,0x96,0xEE,0x35,0xE6,0x20,0x02,0x2A,0x7D,
+    0xB7,0xF6,0x15,0xE6,0x2A,0xA8,0xEA,0x7F,0xB7,0xF6,0x15,0xDE,0xA0,0xA8,0xEE,0x55,
+    0x76,0xEE,0xB3,0xD5,0x00,0x00,0xAA,0x7F,0x56,0xEE,0x72,0xCD,0x00,0x20,0xFA,0x57,
+    0x55,0xEE,0x93,0xCD,0x80,0xFE,0x77,0x55,0xF4,0xDD,0x72,0xCD,0xC0,0x7B,0x55,0x55,
+    0x84,0x59,0x22,0x51,0xFF,0xEA,0x63,0x7B,0x64,0x59,0x22,0x51,0x3F,0x0F,0x25,0x2F,
+    0x84,0x61,0x64,0x59,0xFB,0x2A,0xE9,0x7F,0x84,0x61,0x23,0x51,0xFC,0xAC,0xF8,0xE0,
+    0x84,0x59,0x43,0x59,0xAA,0xAB,0x2B,0x07,0xA4,0x61,0x43,0x51,0xAA,0xAA,0x88,0x7E,
+    0x84,0x59,0x22,0x51,0x6A,0xE8,0xAF,0xB9,0x84,0x59,0x22,0x51,0xD7,0xF7,0x3F,0xEF,
+    0x43,0x51,0x22,0x51,0x58,0x3C,0xD8,0x20,0x43,0x51,0x22,0x49,0x78,0x7A,0x0D,0x2E,
+    0x63,0x59,0x22,0x51,0x5D,0x75,0xA7,0x2A,0x64,0x59,0x23,0x51,0xFD,0xD9,0xFA,0xAA,
+    0x84,0x61,0x23,0x51,0x57,0xF7,0xE7,0xAF,0x84,0x61,0x64,0x59,0x19,0xA9,0xB9,0x81,
+    0xA4,0x61,0x64,0x59,0xB5,0xEF,0xFD,0xFB,0x84,0x61,0x64,0x59,0x7A,0x2E,0xB4,0x1E,
+    0xA4,0x61,0x64,0x59,0xFF,0x7D,0x6E,0xEB,0x06,0x72,0x63,0x59,0x0B,0xEB,0xFD,0x75,
+    0x67,0x7A,0x63,0x59,0x02,0xAB,0xF5,0x57,0x67,0x7A,0x84,0x61,0x00,0x00,0x0B,0xF5,
+    0x88,0x82,0x06,0x72,0x08,0x8A,0xAA,0xA9,0x67,0x82,0x87,0x7A,0x77,0xDC,0xDE,0xFB,
+    0x87,0x82,0x67,0x7A,0x5C,0xFF,0xBF,0x0B,0xA7,0x82,0x67,0x7A,0xAA,0xA5,0xB6,0xA6,
+    0xA7,0x82,0x67,0x7A,0x2E,0x2A,0x6B,0xFF,0xA7,0x82,0x87,0x7A,0x2D,0x05,0xFD,0x7E,
+    0x08,0x8B,0x87,0x7A,0xD5,0xFF,0xBF,0x3D,0xEC,0xAB,0xE8,0x8A,0xA5,0x2D,0x2B,0x0B,
+    0xEB,0xAB,0xAB,0xA3,0x6A,0xFA,0xD0,0xBF,0xCB,0xA3,0x8A,0xA3,0xAA,0xBF,0xEF,0xA8,
+    0xCB,0xA3,0x6C,0xA3,0x8A,0xA8,0x8E,0xAA,0xCB,0xA3,0x8B,0xA3,0x88,0xE9,0xAB,0x8B,
+    0xCB,0xA3,0x49,0x93,0x78,0xA2,0x88,0xAA,0x29,0x8B,0x06,0x6A,0x5E,0x78,0x70,0xE0,
+    0xE6,0x61,0x43,0x51,0x5E,0xEC,0xF8,0xE8,0x64,0x51,0xC2,0x38,0x7E,0x7E,0x78,0xE0,
+    0x23,0x41,0xC2,0x38,0x0B,0xAF,0xAF,0xF7,0x03,0x41,0xC2,0x38,0x70,0x6F,0x7E,0x57,
+    0xE3,0x38,0xA1,0x30,0x95,0xBF,0xFA,0xBA,0xE2,0x38,0xA2,0x30,0x7E,0xFF,0xAB,0x2A,
+    0x03,0x39,0xA2,0x30,0xD5,0xD7,0xFB,0xBC,0x23,0x41,0xE3,0x38,0xF5,0xB5,0xAD,0xBD,
+    0x64,0x49,0x03,0x41,0x2D,0x2D,0x3F,0xBF,0xA6,0x51,0x44,0x49,0x57,0x5F,0x7F,0xE3,
+    0x64,0x49,0x24,0x41,0xEB,0xAA,0xBE,0xBA,0x85,0x49,0x24,0x41,0xB7,0xD7,0x8B,0x0B,
+    0x85,0x51,0x24,0x41,0xFA,0x7E,0xD8,0x58,0x44,0x41,0xE3,0x40,0x8E,0x3B,0x2B,0xA9,
+    0x44,0x49,0xE3,0x38,0x7E,0xD8,0xEE,0xAA,0x23,0x41,0xE2,0x38,0xA5,0x3F,0x9E,0x3F,
+    0xA5,0x51,0x03,0x41,0x2D,0x2F,0x2B,0x2F,0xA5,0x51,0x23,0x49,0x78,0x78,0xE0,0xA0,
+    0x64,0x51,0x03,0x49,0xFF,0xAD,0xF6,0xFC,0x85,0x51,0x24,0x49,0xF5,0x65,0xAF,0x0F,
+    0xA5,0x51,0x64,0x51,0x35,0xB5,0xDF,0x98,0xA5,0x59,0x24,0x49,0x7C,0xF8,0xE2,0x8A,
+    0x64,0x51,0x24,0x49,0x17,0xD7,0xBE,0xE8,0xA5,0x51,0x44,0x49,0xEF,0x2F,0x3D,0x37,
+    0x85,0x51,0x03,0x39,0x5F,0x7E,0x58,0x78,0x24,0x41,0xC2,0x38,0x8A,0xAA,0xEA,0x7F,
+    0x24,0x41,0xE3,0x38,0xBE,0xBD,0xF5,0xD5,0x03,0x39,0xA2,0x30,0xA0,0x08,0x2A,0x28,
+    0x23,0x41,0xE3,0x38,0xDF,0xBF,0xEA,0x72,0x23,0x41,0xE3,0x38,0x6A,0xFC,0xEE,0xFF,
+    0x23,0x41,0xE2,0x38,0xCF,0x03,0x8A,0xDA,0x24,0x41,0xE3,0x38,0x97,0x14,0xBB,0x79,
+    0x85,0x51,0xE3,0x38,0xA7,0xBF,0xEF,0xB5,0xC6,0x59,0x65,0x49,0x2B,0xAF,0xAD,0xFF,
+    0x84,0x51,0x44,0x49,0x7C,0x54,0x54,0x7F,0x44,0x49,0xE2,0x40,0xF2,0x6E,0xFE,0x7E,
+    0x03,0x41,0xE2,0x40,0x02,0x02,0x3B,0xA9,0x44,0x49,0x03,0x41,0x0B,0xF6,0x5F,0x7D,
+    0x64,0x49,0x24,0x49,0x58,0xEF,0xBD,0xAD,0x85,0x51,0x23,0x49,0xB9,0xA9,0x2B,0x02,
+    0x85,0x51,0x23,0x41,0xF2,0xEA,0x78,0x5E,0x64,0x49,0x23,0x49,0x85,0xAD,0x0B,0x2B,
+    0xA5,0x51,0x44,0x41,0xEB,0x2F,0xAD,0xF5,0x85,0x49,0x44,0x49,0x56,0x7A,0x7A,0x57,
+    0x44,0x41,0x03,0x41,0xD6,0x5F,0xFE,0xAC,0x64,0x49,0x03,0x39,0x8F,0xA7,0xAD,0xB5,
+    0x44,0x41,0xE2,0x38,0xE8,0xAC,0xB8,0xB4,0x23,0x41,0xE2,0x38,0x42,0xC0,0xE0,0x7E,
+    0x03,0x39,0xC2,0x38,0x25,0xBF,0x2B,0x82,0x23,0x41,0x03,0x39,0xAD,0x67,0x3D,0x09,
+    0x44,0x41,0x03,0x39,0xBA,0xFF,0xEB,0x22,0x44,0x41,0x03,0x41,0xA2,0xCA,0x7B,0xEA,
+    0xE2,0x48,0x03,0x39,0xF5,0xDD,0x75,0xD7,0x23,0x41,0xC2,0x38,0xA7,0x2F,0xEF,0xAA,
+    0x43,0x41,0x03,0x41,0x65,0xEB,0xFF,0xA9,0x64,0x49,0x23,0x41,0xB7,0x95,0xB5,0x75,
+    0x64,0x49,0x23,0x41,0x02,0x00,0x02,0xAF,0xA5,0x51,0x44,0x49,0x00,0x2F,0x9E,0xB3,
+    0xE7,0x61,0x85,0x51,0xDB,0xEA,0x2B,0x2B,0x27,0x6A,0xA4,0x59,0x25,0x95,0xEF,0xE2,
+    0xA8,0x7A,0xC5,0x59,0x0A,0x03,0xBF,0xBD,0xC9,0x82,0x66,0x72,0x02,0x22,0xAB,0xE9,
+    0xA8,0x7A,0x67,0x7A,0x68,0x6A,0x68,0x78,0xA7,0x7A,0x46,0x72,0x0A,0x2F,0x2F,0x77,
+    0x09,0x8B,0xA7,0x7A,0x3D,0xEF,0xAD,0xBF,0x8B,0x9B,0xE8,0x82,0x2D,0x3D,0xFD,0x55,
+    0xD3,0xDD,0x6A,0x93,0x2B,0x2D,0xAD,0xB5,0x14,0xE6,0x72,0xD5,0x8A,0x0A,0x0B,0x09,
+    0x15,0xE6,0xB3,0xDD,0x02,0x80,0xA0,0x70,0xB3,0xDD,0xF0,0xC4,0x58,0x7C,0x7C,0x5E,
+    0x10,0xC5,0xCF,0xBC,0xEA,0x6A,0xFE,0xB6,0x30,0xCD,0xD0,0xBC,0xAB,0xA9,0xAF,0x2B,
+    0x31,0xCD,0x10,0xC5,0x42,0xC8,0xB3,0x83,0x51,0xCD,0x10,0xC5,0x0B,0x8F,0x0F,0x89,
+    0x14,0xE6,0x51,0xCD,0x35,0x35,0xD5,0xD5,0x96,0xF6,0xF4,0xDD,0x0A,0x0B,0x0B,0x2D,
+    0xD7,0xF6,0x76,0xEE,0xBF,0xAA,0xA8,0x75,0xB7,0xF6,0x55,0xEE,0x08,0x00,0x28,0x7F,
+    0xB7,0xF6,0x35,0xE6,0x00,0x00,0xA0,0x57,0xB7,0xF6,0x35,0xE6,0x02,0xA8,0xEA,0x5D,
+    0xB7,0xF6,0x14,0xDE,0x82,0xA2,0xFF,0x7D,0x96,0xEE,0xF4,0xDD,0x00,0x88,0xFE,0x77,
+    0x96,0xEE,0xB3,0xD5,0x00,0x20,0xAA,0x5F,0x76,0xEE,0xB3,0xD5,0x00,0x00,0xEA,0x57,
+    0x96,0xEE,0x73,0xCD,0x00,0xA8,0xAA,0x57,0x55,0xE6,0x51,0xC5,0x00,0x88,0xFA,0x57,
+    0x55,0xE6,0xF1,0xBC,0x80,0xAA,0xFE,0x77,0x15,0xE6,0xD0,0xBC,0x00,0xAA,0xFF,0x55,
+    0xF4,0xDD,0x8F,0xB4,0x00,0xAA,0xDF,0x55,0xF4,0xDD,0xB0,0xB4,0xA8,0xFE,0x55,0x55,
+    0x72,0xCD,0x4E,0xAC,0x20,0xBA,0xF7,0xF5,0x73,0xC5,0xD0,0xB4,0x2A,0xBF,0x35,0x29,
+    0x93,0xCD,0x52,0xC5,0x82,0x8F,0xB3,0x7A,0xB3,0xD5,0x11,0xC5,0xEA,0xE2,0xFA,0x7E,
+    0x43,0x59,0x23,0x51,0x5A,0xFA,0xE8,0x80,0x64,0x59,0x23,0x51,0x2B,0x0A,0x09,0x00,
+    0x84,0x61,0x44,0x59,0x5E,0x5E,0xBE,0x2A,0x84,0x61,0x43,0x59,0xE7,0xDE,0xF8,0xFE,
+    0x84,0x59,0x43,0x51,0xBA,0xA8,0xA2,0xD0,0x64,0x59,0x23,0x51,0x60,0x7A,0xDA,0x3A,
+    0x84,0x59,0x23,0x51,0x8D,0xA5,0xBD,0xDD,0x84,0x59,0x22,0x51,0x7F,0x8B,0xBE,0xFF,
+    0x63,0x59,0x43,0x51,0x9D,0x6C,0xA6,0xA9,0x63,0x59,0x22,0x51,0x5B,0x5C,0x5E,0xDE,
+    0x63,0x59,0x02,0x49,0x2A,0xBF,0xBD,0xFB,0x64,0x59,0x23,0x51,0x5B,0x5F,0xBF,0xA3,
+    0x84,0x61,0x43,0x51,0xED,0xA9,0xAA,0xEA,0x84,0x61,0x63,0x59,0x8A,0x7A,0xF0,0x64,
+    0xA4,0x61,0x63,0x59,0x5A,0x8E,0x6F,0x83,0x84,0x61,0x63,0x59,0x11,0x9F,0x2A,0x20,
+    0xA4,0x61,0x63,0x59,0xDA,0xFB,0xF0,0x50,0xA5,0x61,0x22,0x51,0xEA,0xE8,0x7E,0xFA,
+    0x63,0x59,0x43,0x59,0x3C,0x7A,0xE0,0xC2,0x84,0x61,0x23,0x51,0x2B,0xFF,0xFF,0x7F,
+    0xE5,0x69,0x03,0x51,0x02,0xAE,0xFF,0x7F,0x67,0x7A,0x43,0x59,0x00,0x2B,0xFD,0xD5,
+    0x67,0x7A,0x84,0x59,0x00,0x00,0x0A,0xFD,0xC7,0x82,0x06,0x72,0xAA,0x2B,0xBB,0xFD,
+    0xA7,0x82,0x66,0x7A,0xFD,0x0B,0x8B,0xBD,0xA7,0x82,0x66,0x7A,0xEA,0xF8,0xF2,0xE0,
+    0x0B,0xAC,0xC8,0x82,0xD5,0xF5,0xB5,0x2D,0xEC,0xAB,0x8A,0x9B,0x0D,0x03,0xA0,0xFA,
+    0xCB,0xA3,0x6A,0x9B,0x08,0xA8,0xFC,0xE7,0xCB,0xA3,0x6A,0x9B,0x8A,0xEF,0x77,0xD7,
+    0xAB,0xA3,0x6A,0x9B,0xA8,0xEB,0xCF,0xE9,0xCC,0xA3,0x6A,0x9B,0x0F,0xAB,0xEB,0x5F,
+    0xAB,0xA3,0x2A,0x93,0x20,0xA8,0xFA,0x7F,0x6A,0x93,0x05,0x6A,0x78,0x78,0x58,0xFE,
+    0x26,0x6A,0xA4,0x59,0x57,0x56,0xFC,0xE8,0xA5,0x59,0x02,0x41,0xDC,0x58,0x78,0xF8,
+    0x03,0x41,0xA2,0x38,0xFC,0x7E,0x78,0xE8,0xE3,0x38,0xA2,0x30,0x3B,0xBD,0xAA,0xE8,
+    0xE3,0x38,0xA2,0x30,0xBE,0x2A,0x0F,0x2B,0x24,0x41,0xE3,0x38,0x57,0xB7,0x2F,0x3F,
+    0x24,0x41,0xC2,0x30,0xB7,0xAB,0xB2,0xA0,0xE3,0x40,0x24,0x39,0xAA,0xA7,0xBA,0xBB,
+    0x44,0x41,0xE3,0x38,0x2F,0xB5,0xDF,0x3F,0x85,0x51,0x23,0x41,0x03,0x29,0xBD,0xAF,
+    0x85,0x51,0x03,0x39,0xAA,0xA0,0x60,0x7A,0x44,0x49,0x03,0x41,0x08,0xBE,0xFD,0x57,
+    0x44,0x49,0x03,0x41,0x78,0x56,0x55,0xFB,0x24,0x41,0xE2,0x38,0x27,0x2E,0xEB,0xE2,
+    0x23,0x41,0xE2,0x38,0x80,0xE2,0xFA,0x02,0x65,0x49,0xE2,0x38,0x95,0x95,0xBD,0xAF,
+    0xC6,0x51,0x44,0x49,0xA5,0x7F,0xEA,0x8B,0xA5,0x51,0x44,0x49,0xC2,0xC9,0xE3,0x6A,
+    0x85,0x51,0x23,0x49,0xDE,0xBA,0x2F,0xB7,0xA5,0x59,0x64,0x49,0x9D,0xFB,0xEA,0xAB,
+    0xA5,0x51,0x44,0x49,0xE8,0xFA,0xBE,0x7F,0xC5,0x61,0x44,0x49,0xAF,0x2D,0x35,0x17,
+    0x06,0x6A,0x64,0x51,0x7F,0x7A,0xE2,0x0A,0xC6,0x59,0x64,0x49,0xF5,0x77,0xFE,0xF0,
+    0xA5,0x51,0x03,0x41,0x58,0x72,0xBF,0xA8,0x23,0x41,0xC2,0x38,0x57,0x57,0x78,0x78,
+    0xE3,0x38,0x81,0x30,0xA2,0xBA,0xBE,0xA7,0x03,0x39,0xC2,0x30,0xAF,0xF5,0xAF,0x3B,
+    0x23,0x41,0xE3,0x38,0x7A,0xFB,0x77,0xFD,0x03,0x41,0xE3,0x38,0xED,0xB5,0x55,0x38,
+    0x23,0x41,0xC2,0x38,0xFA,0x6B,0xAF,0x2E,0x23,0x41,0xE3,0x38,0x7B,0xAF,0x2E,0x2B,
+    0x64,0x49,0xE3,0x38,0x2D,0x8F,0xAE,0xAB,0x64,0x51,0x23,0x49,0x0A,0x0E,0xAB,0x73,
+    0x85,0x51,0x24,0x49,0xE2,0xEB,0x7B,0xFF,0x44,0x49,0x03,0x41,0x74,0xD4,0xAA,0x2A,
+    0x44,0x49,0x03,0x41,0x75,0x6F,0x2A,0x20,0x64,0x51,0x03,0x41,0xB5,0xBD,0x3B,0x2A,
+    0x84,0x51,0x44,0x49,0xBD,0xAF,0xAF,0x2E,0xA5,0x51,0x64,0x49,0xCB,0x6A,0xC2,0xC0,
+    0x64,0x49,0x03,0x41,0xFC,0xF8,0xE8,0x80,0x64,0x49,0x03,0x41,0x2B,0x2B,0x09,0x3F,
+    0x84,0x49,0x03,0x41,0x7F,0x7E,0x7E,0xFC,0x44,0x49,0x03,0x41,0x2E,0xFE,0x7A,0x5F,
+    0x44,0x41,0xE2,0x38,0x88,0x2E,0xA7,0x57,0x44,0x41,0xE3,0x38,0xBA,0xFA,0xDC,0xFF,
+    0x23,0x41,0xE3,0x38,0xFC,0x5F,0xFF,0xAF,0x44,0x41,0xE2,0x38,0xDF,0x77,0x9F,0xE2,
+    0x03,0x39,0xC2,0x38,0x29,0xA6,0xAA,0x02,0x84,0x49,0x03,0x39,0xAD,0x0D,0xAD,0xE7,
+    0x64,0x49,0x03,0x39,0xAE,0xA8,0x80,0xA8,0x65,0x49,0x24,0x41,0x7E,0x72,0xEB,0xFD,
+    0x43,0x41,0xC2,0x38,0xFE,0xB6,0xAA,0xA8,0x65,0x49,0xE2,0x38,0x97,0xB7,0x8B,0x0F,
+    0x44,0x41,0x03,0x41,0x0D,0x09,0xC0,0xA0,0x44,0x49,0x23,0x41,0xEC,0xDE,0xD7,0x96,
+    0x64,0x49,0x23,0x41,0x7D,0xFF,0xEE,0xC0,0x85,0x51,0x02,0x41,0x2B,0xDD,0xF7,0x5E,
+    0xC6,0x59,0x44,0x49,0x2B,0xBF,0xBD,0x95,0xE6,0x61,0x84,0x59,0x02,0xAE,0xDF,0x7A,
+    0x26,0x6A,0xA4,0x59,0x2F,0x8B,0x8B,0x25,0xA8,0x7A,0x05,0x62,0x82,0xA9,0xFD,0xD7,
+    0x67,0x7A,0x26,0x6A,0xA2,0xAB,0xBF,0xFB,0x47,0x72,0x06,0x6A,0xE8,0x6C,0xFC,0x54,
+    0xC8,0x82,0x06,0x6A,0x0A,0x0D,0xB5,0xB5,0xE8,0x82,0x87,0x7A,0x28,0x22,0x8B,0x37,
+    0x6E,0xB4,0xC8,0x82,0x2D,0xBD,0xF5,0xD5,0xD3,0xDD,0x2D,0xAC,0x02,0x0B,0x2D,0xAD,
+    0xF4,0xE5,0x51,0xCD,0xA0,0xE2,0x7A,0xEA,0x52,0xCD,0xD0,0xBC,0xF8,0xFE,0xDA,0x7C,
+    0x10,0xC5,0xD0,0xBC,0xF6,0xAA,0x9A,0xD7,0x10,0xC5,0xF0,0xC4,0x2D,0x0F,0x29,0x05,
+    0x31,0xCD,0x10,0xC5,0x02,0x8E,0x1B,0xAB,0x51,0xCD,0x10,0xC5,0xAF,0x27,0xAF,0xAB,
+    0x51,0xCD,0x31,0xC5,0x28,0x0E,0x2A,0xFC,0x35,0xE6,0x52,0xCD,0x0B,0xAF,0xAD,0xAD,
+    0x35,0xE6,0x10,0xC5,0x00,0xAA,0x7F,0x5E,0x14,0xE6,0xD0,0xBC,0x00,0xAA,0xFF,0x75,
+    0x14,0xE6,0xD0,0xBC,0x20,0xEA,0x7F,0x55,0xF4,0xDD,0xAF,0xBC,0x00,0xAA,0xFF,0x55,
+    0xB3,0xD5,0xB0,0xBC,0x00,0xA2,0xFF,0x55,0xB3,0xD5,0x8F,0xB4,0x00,0xAA,0xDF,0x55,
+    0x92,0xD5,0x6F,0xAC,0x00,0xAA,0xFF,0x55,0x72,0xCD,0x6E,0xAC,0x00,0xAA,0xFF,0x5D,
+    0x52,0xC5,0x4E,0xAC,0x00,0xAA,0xFE,0x57,0x31,0xC5,0x2E,0xA4,0x2A,0xBA,0xF7,0x5D,
+    0xF0,0xBC,0x2D,0xA4,0xE0,0xFA,0xFF,0xD5,0x8F,0xB4,0x2D,0xA4,0xC8,0xE8,0xBA,0xB7,
+    0x52,0xC5,0x2D,0xA4,0xFD,0xBD,0xAF,0x2F,0xD4,0xD5,0xD0,0xB4,0xF5,0xAF,0x0A,0x02,
+    0xD4,0xD5,0xF0,0xB4,0xD5,0xEE,0xA8,0xA0,0x93,0xCD,0x31,0xBD,0xB5,0xAF,0x8A,0xAE,
+    0x73,0xCD,0xF0,0xB4,0xA0,0xE2,0xFA,0x5F,0x52,0xC5,0xB0,0xB4,0xE2,0xFA,0x7E,0x5F,
+    0x84,0x59,0x43,0x59,0xD7,0xE5,0xBF,0xCD,0x84,0x59,0x43,0x51,0x81,0x02,0x8C,0xAA,
+    0x84,0x59,0x64,0x59,0x41,0xE0,0x2B,0x1A,0x84,0x59,0x43,0x51,0x8A,0x8A,0xF8,0xD8,
+    0x64,0x59,0x23,0x51,0x1E,0x2E,0x2A,0xFA,0x84,0x59,0x22,0x51,0xCE,0xEA,0xFA,0x97,
+    0x64,0x59,0x23,0x49,0xFD,0x8A,0xCA,0xAA,0x63,0x59,0x02,0x49,0x9E,0xAB,0x02,0x0A,
+    0x43,0x51,0x22,0x51,0x82,0xFF,0xF8,0xD8,0x43,0x59,0x22,0x49,0xEB,0xAD,0xEB,0xEE,
+    0x63,0x59,0x23,0x51,0xD5,0xF5,0xAF,0x0B,0x84,0x61,0x43,0x59,0x87,0x23,0x8B,0xAF,
+    0x84,0x61,0x43,0x59,0x4A,0x80,0xC0,0x02,0xA4,0x61,0x63,0x59,0xFF,0x5B,0xF1,0x80,
+    0xA4,0x61,0x63,0x59,0xAB,0x9D,0xFF,0xFA,0xA5,0x61,0x43,0x59,0x2A,0x0E,0x28,0x28,
+    0xA4,0x61,0x43,0x59,0xF8,0x7E,0x6E,0xEF,0x63,0x59,0x43,0x59,0x62,0x20,0x28,0x8A,
+    0x63,0x59,0x23,0x51,0xA0,0xA0,0xA8,0x76,0x64,0x59,0x23,0x51,0x5A,0xBA,0xEE,0xE9,
+    0x23,0x59,0x43,0x51,0xAA,0xDE,0xFE,0xAF,0x64,0x59,0x03,0x51,0x0A,0xEA,0xBB,0x5F,
+    0x84,0x59,0x02,0x51,0xAF,0xF7,0xFF,0xFD,0xC5,0x69,0x23,0x51,0x0A,0xFF,0x55,0x57,
+    0x87,0x82,0x23,0x51,0x22,0x3F,0xF5,0x55,0xC8,0x8A,0x64,0x59,0x22,0x8A,0x2F,0x25,
+    0xEB,0xAB,0xE7,0x82,0x2D,0x2B,0x0B,0x0A,0xEC,0xAB,0x8A,0x9B,0xF8,0x68,0x6A,0x7E,
+    0x8A,0x9B,0x6A,0x9B,0xB0,0x0C,0x07,0x7F,0xAB,0x9B,0x4A,0x9B,0xFF,0x7F,0xF6,0xAF,
+    0xAB,0x9B,0x4A,0x93,0xAB,0xAF,0xBE,0x2E,0xAB,0xA3,0x6A,0x9B,0x6B,0x6E,0xDA,0x08,
+    0xCC,0xA3,0x29,0x93,0x57,0xFF,0xFA,0xA8,0x29,0x93,0x66,0x72,0x7E,0x7E,0xF8,0xF8,
+    0x86,0x7A,0xC5,0x61,0x5B,0x7A,0xF8,0xF8,0xE6,0x61,0x44,0x49,0x5E,0xFA,0xFA,0x78,
+    0x44,0x49,0xE2,0x38,0x7A,0x78,0x5A,0x6E,0x03,0x41,0xA2,0x30,0xFE,0xEB,0xCE,0xAE,
+    0x04,0x39,0xC2,0x38,0xDD,0xFD,0xF3,0xAB,0x03,0x39,0xC2,0x38,0x2B,0xBD,0x35,0x95,
+    0x64,0x49,0x03,0x41,0xFF,0xFD,0xBF,0x0F,0x65,0x49,0x03,0x41,0x57,0xFA,0x7A,0xE0,
+    0x23,0x41,0xE3,0x38,0x02,0x6B,0x58,0x5C,0x64,0x49,0xE3,0x38,0x0A,0xBD,0xAF,0xBF,
+    0x44,0x49,0x24,0x41,0x40,0x78,0x56,0x5A,0x23,0x41,0xC2,0x38,0xAA,0x88,0x28,0x1E,
+    0x44,0x49,0x03,0x41,0x7B,0xC3,0x08,0x03,0x65,0x49,0xE3,0x38,0x7F,0xDB,0xEE,0x8A,
+    0x43,0x41,0x04,0x41,0xAA,0xE9,0x8A,0xAB,0x44,0x41,0x03,0x41,0xAA,0xBA,0xBF,0x55,
+    0xA5,0x51,0x23,0x41,0x03,0x0B,0x2D,0xBD,0xA6,0x51,0x24,0x49,0xF8,0xF8,0xEE,0xDF,
+    0xA5,0x59,0x23,0x49,0xB7,0x37,0x2F,0xBF,0x06,0x62,0x43,0x49,0x7F,0x7E,0x7A,0xA2,
+    0xA5,0x59,0x23,0x49,0xD7,0xDF,0x7E,0xBC,0xE5,0x61,0x24,0x49,0x3F,0xBD,0xBD,0xFF,
+    0x47,0x6A,0x64,0x59,0x8A,0x2A,0x2B,0x2D,0x27,0x6A,0xA5,0x59,0x7A,0xFA,0xF0,0x78,
+    0xC6,0x59,0x24,0x49,0xFE,0xFA,0xE8,0x78,0x44,0x49,0xC2,0x38,0x7C,0x70,0x50,0x7A,
+    0xE3,0x38,0xA2,0x30,0xAE,0xAA,0xAE,0x2E,0x23,0x39,0xE3,0x38,0xD5,0xE5,0xAD,0x3B,
+    0x44,0x41,0xE3,0x38,0xF9,0xBF,0x2F,0xAE,0x23,0x41,0x03,0x39,0x7F,0x5A,0xB0,0x80,
+    0x43,0x49,0xE3,0x40,0xF7,0xFD,0xFE,0xE8,0x03,0x41,0x23,0x39,0xE0,0xA0,0xAA,0x2C,
+    0x24,0x49,0xE3,0x40,0xA2,0x78,0xEA,0xAB,0x24,0x49,0xE3,0x40,0x00,0x27,0x2B,0x0A,
+    0x64,0x51,0x23,0x49,0xF9,0xB2,0xB7,0x25,0x64,0x51,0x03,0x41,0xAE,0xFB,0x9E,0xB8,
+    0x65,0x51,0x23,0x41,0x5C,0x7F,0xAA,0xAB,0x64,0x49,0x23,0x49,0xA5,0x05,0x87,0xAD,
+    0xA5,0x59,0x23,0x41,0x2B,0xAA,0xFE,0x56,0xA5,0x51,0x03,0x41,0xA8,0xBF,0xFF,0x5F,
+    0x64,0x49,0x23,0x41,0xAB,0x0A,0x08,0x83,0x85,0x49,0x23,0x41,0xDF,0xEB,0xE0,0xEA,
+    0x64,0x49,0x03,0x41,0xEA,0x4B,0x7A,0x7A,0x23,0x39,0xC1,0x38,0xA8,0x7A,0x7B,0xFA,
+    0x24,0x39,0xC2,0x30,0xFE,0xFE,0xFB,0xAA,0x23,0x41,0x03,0x39,0x95,0x3D,0x29,0x0D,
+    0x64,0x49,0x03,0x41,0x5D,0xFB,0xEE,0x8A,0x85,0x49,0x24,0x41,0xF8,0xAB,0xB9,0xBB,
+    0xA5,0x49,0x03,0x39,0x5F,0xF6,0xEE,0xA8,0x44,0x41,0x03,0x41,0x2F,0xBB,0xB8,0xBE,
+    0x44,0x49,0x03,0x39,0xAA,0xDC,0xF4,0xFE,0x44,0x41,0x03,0x41,0xAF,0x2E,0xB8,0x56,
+    0x44,0x41,0x02,0x41,0xAA,0x0A,0x88,0x2E,0x64,0x49,0x23,0x41,0x2D,0x0F,0x0B,0x0A,
+    0x64,0x49,0x23,0x41,0xD6,0x7E,0xF0,0xB0,0x44,0x49,0x03,0x41,0xAF,0xFF,0xFF,0xAC,
+    0x85,0x51,0x03,0x39,0xAA,0x8A,0xAD,0xB5,0x64,0x49,0x03,0x41,0x78,0xA0,0xA0,0xA2,
+    0x64,0x51,0x23,0x41,0xF9,0x3D,0xAA,0x3B,0xE6,0x61,0x64,0x51,0x8B,0x0F,0xA5,0xD5,
+    0x46,0x72,0xC5,0x61,0xF7,0xBF,0x8B,0x2D,0x67,0x72,0x05,0x62,0xFE,0x67,0x7F,0x2A,
+    0x87,0x72,0x05,0x6A,0xEB,0xAD,0xAD,0x0A,0x67,0x72,0xC5,0x61,0xFE,0xFE,0xBA,0x68,
+    0x87,0x7A,0xE5,0x61,0x3F,0xAF,0xBF,0xAD,0xA8,0x7A,0x46,0x72,0x2A,0x9B,0xED,0xEB,
+    0x09,0x8B,0x87,0x7A,0x26,0x36,0x3D,0xF5,0x72,0xD5,0x2A,0x8B,0x2F,0x0D,0x2D,0xBD,
+    0xD4,0xDD,0x31,0xCD,0xC0,0x78,0x7A,0x7B,0x31,0xCD,0xCF,0xBC,0xFA,0x78,0xF2,0x7E,
+    0xF0,0xC4,0xCF,0xBC,0xDA,0x3F,0x5D,0x7F,0x10,0xC5,0xCF,0xBC,0x2F,0x25,0x17,0x07,
+    0x31,0xCD,0x10,0xC5,0x8F,0x15,0x35,0x35,0x31,0xCD,0x10,0xC5,0x20,0xEE,0x3C,0xA8,
+    0x51,0xCD,0x11,0xC5,0xAA,0xAB,0xAF,0x6E,0xD3,0xDD,0x31,0xC5,0x0D,0x0D,0x25,0xB5,
+    0xD3,0xDD,0xAF,0xBC,0x7C,0xF8,0x58,0x70,0xD0,0xBC,0x8F,0xB4,0xC8,0xF2,0x6F,0x57,
+    0xAF,0xBC,0x6E,0xB4,0x82,0x72,0x7B,0xFF,0xAF,0xB4,0x4D,0xAC,0x80,0x70,0x7A,0xEA,
+    0xAF,0xBC,0x2D,0xAC,0xA8,0xFB,0x7B,0x7F,0x8F,0xB4,0x2D,0xAC,0x22,0x7B,0x77,0x7D,
+    0x6E,0xAC,0x0D,0xA4,0x28,0x0A,0xFB,0x57,0x6E,0xAC,0x0C,0xA4,0x60,0xFA,0x7E,0x5D,
+    0xB0,0xB4,0x0D,0x9C,0xFF,0xD5,0xD5,0x0B,0x72,0xC5,0x0D,0x9C,0x5D,0xDD,0xBD,0x2A,
+    0x93,0xCD,0x2E,0xA4,0x75,0xFD,0xAA,0x88,0x72,0xC5,0x4E,0xAC,0xD5,0xAB,0x2A,0x22,
+    0x93,0xCD,0x11,0xBD,0xA5,0xAF,0x0A,0x80,0xB3,0xD5,0x53,0xC5,0x0A,0xA2,0xA2,0xFF,
+    0xD5,0xD5,0x52,0xC5,0xE2,0xDE,0xFF,0x5F,0x73,0xC5,0xF1,0xBC,0x8A,0xC8,0xF6,0x56,
+    0x32,0xC5,0xB0,0xB4,0xE8,0xEA,0x6A,0x6A,0xF1,0xB4,0x6F,0xAC,0xFC,0xDF,0x57,0x77,
+    0x84,0x61,0x43,0x59,0xFE,0xFC,0x78,0xFD,0xA5,0x61,0x43,0x51,0xB7,0xAE,0x73,0xFA,
+    0x84,0x59,0x23,0x51,0xA2,0xAA,0xAF,0xDE,0x64,0x59,0x23,0x51,0xB8,0xAE,0x7E,0x5F,
+    0x64,0x59,0x23,0x51,0xFA,0xDE,0xFF,0xBE,0x84,0x59,0x22,0x51,0xE7,0xEF,0xE2,0xFE,
+    0x84,0x59,0x43,0x51,0x57,0x5C,0x75,0x55,0x63,0x59,0x23,0x51,0xEE,0xAA,0xCC,0xBB,
+    0x63,0x59,0x23,0x51,0xBB,0xAF,0xFF,0xFD,0x63,0x59,0x23,0x51,0xD7,0xD6,0xBC,0x3A,
+    0x84,0x59,0x43,0x59,0x85,0xB5,0xFD,0xF6,0xA4,0x61,0x43,0x59,0xB5,0xAF,0xB7,0xD5,
+    0xA4,0x61,0x63,0x59,0xBF,0xDE,0xFF,0x77,0xA4,0x61,0x64,0x59,0x8A,0xEF,0xFB,0xED,
+    0xA4,0x61,0x43,0x59,0x82,0xCE,0xE2,0x42,0xA5,0x61,0x43,0x59,0xFC,0x5F,0x5E,0x7F,
+    0x63,0x59,0x22,0x51,0x80,0xC0,0x3B,0xB6,0x84,0x59,0x23,0x51,0xEF,0xCA,0xEB,0x7A,
+    0x43,0x59,0x23,0x51,0xF0,0x3F,0x38,0xEA,0x64,0x59,0x23,0x51,0xEB,0xEA,0xFA,0x6D,
+    0x43,0x59,0x03,0x51,0xBA,0x5A,0x6F,0xFF,0x23,0x51,0xE2,0x48,0xBB,0xFF,0x2B,0x0A,
+    0x44,0x51,0x02,0x49,0x2F,0xAE,0x7A,0xEF,0x23,0x51,0xE2,0x48,0xA0,0x40,0xA0,0xB0,
+    0x63,0x59,0x03,0x51,0xD5,0xD5,0xA7,0x37,0xAB,0xA3,0x63,0x59,0xB5,0x2D,0x2D,0x0B,
+    0xEC,0xAB,0x8A,0x9B,0x8D,0xEB,0xA2,0xFE,0xCC,0xA3,0x4A,0x9B,0xE8,0xE2,0xFE,0x56,
+    0xAB,0xA3,0x6A,0x9B,0x57,0x7B,0xEE,0xA7,0xAB,0xA3,0x6A,0x9B,0x2B,0xFD,0x7F,0xE8,
+    0xAB,0xA3,0x6A,0x9B,0xA6,0x78,0x79,0x6B,0xCC,0xA3,0x8B,0x9B,0x2E,0xAA,0xD5,0x55,
+    0xCC,0xAB,0x6B,0x9B,0xE2,0x62,0xFB,0xFB,0x49,0x93,0x87,0x7A,0xFE,0x78,0xFE,0x76,
+    0x86,0x7A,0xC5,0x61,0x78,0x78,0xE0,0xE0,0xC5,0x61,0x44,0x51,0xFA,0xFC,0x7C,0x7C,
+    0x64,0x51,0x02,0x41,0x7E,0xE0,0xBC,0xAB,0x44,0x49,0xE2,0x38,0x5F,0xFA,0x2A,0x20,
+    0x44,0x49,0xE3,0x38,0x5D,0xDF,0x76,0x78,0x23,0x41,0xA1,0x30,0xFF,0xBE,0x2E,0x2B,
+    0x85,0x49,0x23,0x41,0xA9,0x35,0xBD,0xAB,0xA5,0x49,0x44,0x49,0x7F,0xEC,0xFF,0x6B,
+    0x64,0x49,0xE3,0x38,0x7E,0xFA,0xF8,0xEA,0x23,0x41,0xC2,0x38,0x8B,0xFB,0xDA,0xBE,
+    0x64,0x49,0x03,0x41,0xA9,0x83,0xAD,0xA5,0x44,0x41,0x03,0x41,0x56,0x56,0x9E,0x9E,
+    0x85,0x51,0x23,0x41,0xAD,0xA5,0xED,0x7F,0x44,0x49,0xE2,0x38,0x88,0xFE,0xBF,0xA7,
+    0x44,0x41,0x03,0x41,0xEB,0xAB,0x2B,0x5F,0x23,0x41,0x03,0x39,0x7A,0xF8,0x3C,0x3E,
+    0x44,0x49,0xE2,0x38,0x8B,0xAB,0x5A,0xF7,0x44,0x49,0xE2,0x40,0xFC,0xDD,0x55,0x55,
+    0x64,0x51,0xE2,0x40,0x2B,0x3D,0x3D,0xBF,0xE6,0x61,0x85,0x59,0x02,0x01,0xDB,0x6D,
+    0xA5,0x59,0x24,0x49,0xB8,0xE8,0xB8,0xDA,0x64,0x51,0x23,0x49,0xE0,0xA0,0xA2,0xFE,
+    0xC5,0x59,0x43,0x49,0x0F,0xA5,0xF5,0x57,0x06,0x6A,0x64,0x51,0xC2,0xEA,0xED,0xD5,
+    0xC5,0x59,0x44,0x49,0x5F,0x58,0x68,0xA2,0x44,0x49,0xA2,0x30,0xFA,0x5C,0xDC,0x5C,
+    0xE3,0x38,0xA2,0x30,0x2E,0xBF,0xF7,0x7D,0x24,0x39,0xC2,0x30,0xAA,0xED,0xA1,0xB1,
+    0x23,0x41,0xE3,0x38,0x08,0x82,0xF6,0xBE,0x44,0x41,0x03,0x41,0xDF,0x35,0x35,0xB5,
+    0x65,0x49,0x24,0x41,0xFF,0xBE,0xAE,0xE7,0x44,0x49,0x03,0x41,0xFE,0xAA,0x20,0x00,
+    0x64,0x49,0x23,0x49,0x5D,0x7E,0x5F,0xFB,0x64,0x51,0x03,0x41,0xF7,0xAD,0xA2,0x82,
+    0xA6,0x59,0x44,0x49,0xF5,0xBD,0xAB,0x02,0xC6,0x59,0x64,0x51,0x57,0xDF,0xFA,0x6C,
+    0xA5,0x51,0x23,0x49,0xFF,0x7A,0xF8,0xF2,0x44,0x49,0x03,0x41,0x20,0x6A,0xFA,0x77,
+    0x64,0x49,0x03,0x41,0xF8,0xAE,0xEB,0xF7,0x23,0x41,0x03,0x41,0x62,0xA3,0xC1,0xC2,
+    0x44,0x49,0xE2,0x38,0x02,0x0F,0x2F,0xB7,0x84,0x49,0x44,0x49,0x7D,0x4F,0xDD,0x57,
+    0x44,0x49,0x03,0x41,0x6E,0x36,0xBA,0xFE,0x43,0x41,0x03,0x41,0x5D,0x56,0xDE,0x5F,
+    0x23,0x41,0xE3,0x38,0x37,0xBA,0xA2,0xA2,0x24,0x41,0xE3,0x38,0x0A,0x2B,0xBD,0xFF,
+    0x64,0x49,0x03,0x39,0xCA,0xEB,0xAF,0xBD,0x85,0x49,0x44,0x49,0xD7,0x3D,0xB7,0xBD,
+    0xA5,0x51,0x64,0x49,0xB6,0xAF,0x2B,0x2A,0x85,0x49,0x23,0x41,0x57,0xF7,0x7C,0xE0,
+    0x43,0x41,0x03,0x39,0x78,0x57,0x55,0xF6,0x23,0x41,0x03,0x39,0xDF,0x35,0xA5,0x7D,
+    0x64,0x49,0x03,0x39,0xA7,0x2B,0x2F,0x2D,0xA5,0x49,0x44,0x49,0xAF,0xFF,0xBD,0x3F,
+    0x85,0x51,0x44,0x49,0xA6,0xBF,0xFF,0x6E,0xA5,0x51,0x44,0x49,0xDF,0xEF,0xFF,0x95,
+    0x85,0x51,0x23,0x41,0xD5,0xFB,0xF8,0x00,0x85,0x51,0x23,0x41,0xBF,0xD5,0x5F,0xDC,
+    0x64,0x51,0x44,0x49,0xA2,0x7D,0xD5,0x55,0x64,0x51,0x44,0x49,0x30,0x32,0x3E,0x32,
+    0x06,0x6A,0x44,0x51,0x0B,0xAF,0xFF,0xF5,0x88,0x72,0x85,0x59,0xAA,0x0A,0xBF,0xF5,
+    0xA8,0x7A,0x06,0x6A,0x88,0x80,0xAB,0xA9,0x87,0x72,0x26,0x6A,0x78,0xB8,0x2F,0xAE,
+    0x88,0x7A,0x05,0x62,0xBD,0xAF,0x08,0x02,0xC8,0x82,0x88,0x7A,0xD5,0x1D,0x35,0xFF,
+    0xE9,0x82,0x87,0x7A,0x97,0xBE,0x8A,0xAB,0x4E,0xB4,0xC8,0x82,0x2D,0x3D,0xBD,0x35,
+    0xB3,0xD5,0xAF,0xBC,0xA2,0xE3,0xA9,0x89,0x31,0xCD,0xD0,0xBC,0x7E,0xDE,0x7E,0xF8,
+    0xF0,0xC4,0xAF,0xBC,0xFE,0xEA,0xFB,0xFF,0x10,0xC5,0xB0,0xBC,0xAB,0xAF,0xA9,0x3B,
+    0x31,0xCD,0xF0,0xC4,0xA5,0xE5,0xAF,0xAF,0x51,0xCD,0x10,0xC5,0x7F,0x6D,0xCB,0x8F,
+    0x51,0xCD,0xF0,0xC4,0xA8,0xAE,0xB7,0xAA,0x92,0xCD,0xF0,0xC4,0x27,0xBF,0xFD,0x7E,
+    0xD3,0xDD,0x6F,0xB4,0xF0,0x6A,0x7E,0x7F,0x8F,0xB4,0x2D,0xAC,0x0A,0xC0,0x6E,0xFF,
+    0x8F,0xB4,0x2D,0xAC,0x80,0xAB,0x6F,0x7F,0x6E,0xAC,0x2D,0xAC,0x30,0x7E,0x75,0x7D,
+    0x6F,0xAC,0x0D,0xA4,0xA8,0xDF,0xDD,0x5D,0x6E,0xB4,0xED,0x9B,0xEA,0xEB,0xFD,0x2F,
+    0x73,0xCD,0x0D,0xA4,0x55,0x55,0xF5,0x2B,0x73,0xCD,0x2D,0xA4,0xD5,0x35,0x0B,0x00,
+    0xB3,0xCD,0xF0,0xBC,0xB5,0xAB,0x2A,0xA0,0x93,0xCD,0x52,0xC5,0x23,0xC2,0xF2,0x7D,
+    0x93,0xCD,0x11,0xBD,0xA0,0xE0,0x7B,0xDB,0x73,0xCD,0x11,0xBD,0x2F,0xAF,0x2F,0x0D,
+    0xB4,0xD5,0x52,0xC5,0x6A,0xC3,0x8B,0xA2,0x73,0xCD,0xB0,0xB4,0xA8,0xD8,0x78,0xE8,
+    0x32,0xC5,0x8F,0xAC,0x00,0x8A,0xF9,0x55,0x32,0xBD,0xD0,0xB4,0x74,0xF7,0xBB,0xA9,
+    0x11,0xBD,0x90,0xAC,0xEB,0xFA,0x6C,0xFE,0xB0,0xB4,0x6F,0xAC,0xBA,0xF7,0xAF,0xBB,
+    0x63,0x59,0x02,0x49,0x0A,0x78,0x02,0x08,0x84,0x59,0x43,0x51,0x7B,0x5A,0x72,0x5E,
+    0x43,0x51,0x03,0x51,0x98,0x3A,0x22,0x2A,0x64,0x59,0x02,0x49,0xFC,0xDE,0xBA,0xF7,
+    0x43,0x51,0xE3,0x48,0x00,0x80,0xAA,0xCA,0x43,0x51,0x23,0x51,0xE0,0xC2,0x19,0x2B,
+    0x63,0x51,0x23,0x51,0xFA,0xF8,0xAE,0x73,0x64,0x59,0x23,0x51,0xBF,0xF6,0xFE,0x57,
+    0x63,0x59,0x03,0x51,0xBE,0xDF,0xBF,0x28,0x84,0x61,0x43,0x59,0x0D,0x7B,0xFB,0xFB,
+    0x84,0x61,0x43,0x59,0xFC,0xFE,0xBF,0xFF,0x84,0x61,0x43,0x59,0xEF,0xBD,0xBB,0xEF,
+    0x83,0x61,0x64,0x59,0xFD,0xFF,0x5B,0x7F,0xA4,0x61,0x43,0x59,0xAD,0xAB,0xF2,0xBB,
+    0x84,0x61,0x43,0x59,0xF0,0x5D,0x7F,0x7F,0x63,0x59,0x23,0x51,0x8E,0xAF,0x22,0x22,
+    0x63,0x59,0x22,0x51,0xF2,0x80,0xC0,0xAF,0x43,0x59,0x03,0x51,0x80,0xEA,0xAE,0x00,
+    0x64,0x59,0x03,0x51,0xAA,0xAA,0x6A,0xE8,0x64,0x59,0x03,0x51,0xE3,0xEA,0xFF,0x7F,
+    0x23,0x51,0xE2,0x48,0x88,0xE8,0x7A,0xFA,0x43,0x51,0x02,0x49,0x25,0xD9,0xD3,0xFD,
+    0x23,0x51,0x02,0x49,0x88,0xB2,0x28,0xA4,0x23,0x51,0x03,0x49,0xC2,0xB2,0xE2,0x02,
+    0x29,0x93,0x43,0x59,0xD5,0xD5,0xB5,0x2D,0xEC,0xAB,0xC7,0x8A,0x2D,0x29,0x0A,0x22,
+    0xCC,0xA3,0x6A,0x9B,0xA0,0xB8,0x6C,0x5E,0x6A,0x9B,0x4A,0x93,0x64,0x14,0xE5,0x22,
+    0x8A,0x9B,0x49,0x93,0x35,0xED,0xFF,0x7E,0x8B,0x9B,0x6A,0x9B,0x02,0xBF,0x7D,0x55,
+    0x8B,0x9B,0x4A,0x9B,0x00,0xAA,0xAF,0xBF,0x8B,0x9B,0x6A,0x9B,0x22,0x2A,0xD7,0x27,
+    0xAC,0xA3,0x09,0x8B,0xE0,0xAA,0xF0,0x5C,0xE8,0x8A,0xA7,0x7A,0x7C,0x54,0xE4,0xF4,
+    0xC7,0x82,0x46,0x72,0x6E,0x6C,0x78,0xE8,0x46,0x72,0x44,0x51,0x76,0x5E,0x7A,0xE0,
+    0x64,0x49,0x03,0x49,0xA8,0xDF,0xFF,0xD6,0x43,0x49,0x03,0x41,0x00,0x8A,0x29,0xAF,
+    0x43,0x49,0xE3,0x38,0x7A,0x7E,0xFE,0xE2,0x25,0x41,0xE3,0x40,0x35,0x95,0xB5,0xFF,
+    0x84,0x51,0x24,0x41,0xAB,0xB9,0x2D,0x99,0xA5,0x51,0x44,0x49,0x6A,0x62,0xE3,0xEA,
+    0x64,0x49,0x03,0x41,0xFE,0xFC,0xFE,0x5E,0x44,0x49,0xE3,0x38,0xD6,0xFE,0xBE,0x3F,
+    0x44,0x49,0x24,0x41,0xF5,0x76,0x78,0x68,0x23,0x41,0xE3,0x38,0xA8,0xB8,0x8E,0xB8,
+    0x44,0x49,0x03,0x41,0x7F,0x7D,0xBD,0xEA,0x23,0x41,0xE2,0x38,0xB8,0xBA,0xD8,0x5E,
+    0x44,0x41,0xE3,0x38,0xFA,0xFE,0xEF,0x3F,0x44,0x41,0xE2,0x40,0xEF,0xF7,0xAB,0xA8,
+    0x44,0x41,0xE2,0x38,0xD7,0x7F,0xEA,0xFA,0xE3,0x40,0x03,0x39,0xAA,0x8B,0xAF,0xFB,
+    0x85,0x51,0xE3,0x40,0xBD,0x2D,0x2F,0x2F,0xE6,0x61,0x84,0x51,0x8D,0xAD,0xAF,0xA3,
+    0x85,0x59,0xE3,0x40,0xF8,0xD8,0x78,0xB8,0x44,0x51,0xE3,0x40,0x0A,0x0B,0xBF,0xF7,
+    0x64,0x51,0x03,0x49,0xA2,0xA0,0xA9,0x35,0x64,0x51,0x23,0x49,0x0A,0x0F,0x27,0xE5,
+    0xA5,0x59,0x44,0x49,0x8A,0xA3,0x8F,0xAD,0x65,0x49,0xA2,0x30,0x5C,0x5C,0x78,0xF8,
+    0xC3,0x30,0xA2,0x30,0xEF,0xBA,0xB0,0xC0,0x03,0x39,0xA2,0x28,0x2D,0xAF,0xF7,0xA7,
+    0x23,0x41,0xE3,0x38,0xFA,0x3D,0xDD,0x7D,0x03,0x39,0xA2,0x30,0x00,0x88,0xA8,0xA7,
+    0x65,0x49,0x03,0x39,0xAD,0xAD,0xAD,0x0D,0x64,0x51,0x23,0x49,0xEA,0xA2,0x6B,0x7A,
+    0x64,0x51,0x44,0x49,0x3D,0xA1,0x02,0x01,0x85,0x59,0x64,0x51,0x69,0xB9,0xAB,0x0A,
+    0xA5,0x59,0x44,0x51,0xA8,0x28,0xAA,0xB6,0xC6,0x59,0x85,0x51,0x5A,0x63,0xDF,0xD7,
+    0x85,0x51,0x23,0x49,0xF8,0x5A,0x7C,0x5C,0x24,0x41,0x02,0x41,0xBB,0x3F,0x0B,0x00,
+    0x44,0x49,0x03,0x41,0xFD,0xE2,0xCA,0xE8,0x44,0x41,0xE2,0x38,0xE2,0xEB,0xFB,0x5E,
+    0x23,0x41,0xE2,0x38,0x2B,0xB9,0xBF,0xB9,0x44,0x41,0x03,0x41,0x2A,0xB7,0xAF,0xFB,
+    0x23,0x41,0x03,0x41,0x28,0x08,0xC0,0x7B,0x23,0x41,0x03,0x39,0xFD,0xCB,0xB2,0xE3,
+    0x23,0x41,0xC2,0x30,0xB8,0xFC,0xF8,0xAA,0x03,0x41,0xC2,0x38,0xA0,0xAE,0xFA,0x73,
+    0x24,0x41,0xE3,0x38,0xAB,0xFF,0xB9,0xB5,0x64,0x49,0x03,0x39,0x0B,0xBF,0xBD,0xB5,
+    0x84,0x49,0x23,0x41,0x32,0xBD,0xEA,0xFA,0x85,0x49,0x23,0x41,0x80,0xEA,0xDF,0x55,
+    0x44,0x41,0x03,0x41,0xA8,0xA0,0xE2,0x7C,0x44,0x49,0xE2,0x38,0xEA,0xA2,0xB0,0x9F,
+    0x64,0x49,0x03,0x39,0x35,0xD5,0x57,0x5F,0x64,0x49,0x02,0x39,0x00,0x3B,0xBB,0xBD,
+    0x85,0x49,0x03,0x41,0x68,0x7A,0xBE,0xF7,0x64,0x49,0x03,0x41,0x2F,0x3D,0xAA,0x0A,
+    0xA5,0x51,0x44,0x49,0x8A,0xFF,0xF5,0x5F,0xA5,0x51,0x23,0x49,0xDC,0xA8,0xA2,0x0A,
+    0xA5,0x59,0x23,0x49,0xDF,0xFB,0xFA,0x2C,0x85,0x51,0x44,0x49,0xAB,0xBF,0x9E,0xEC,
+    0xA5,0x59,0x44,0x51,0xB5,0xBF,0xAB,0xFB,0xA5,0x59,0x64,0x51,0xAB,0xFF,0x96,0xF5,
+    0x06,0x6A,0x64,0x59,0x23,0x3F,0xBF,0xBB,0x67,0x72,0xE6,0x61,0x00,0x03,0x8D,0xF5,
+    0xA8,0x7A,0x06,0x6A,0x0A,0xFB,0xFF,0xD5,0xC9,0x82,0x46,0x6A,0xA2,0x82,0xAF,0xB5,
+    0xE9,0x82,0x88,0x7A,0x3F,0xB5,0xAF,0xBA,0x0D,0xAC,0xC8,0x82,0x35,0x35,0xFD,0x95,
+    0xB3,0xDD,0x0C,0xA4,0x8A,0x03,0x09,0x0D,0x72,0xD5,0xCF,0xBC,0x7E,0x5C,0x78,0x78,
+    0xCF,0xBC,0xAF,0xBC,0x98,0xBC,0xBB,0xD7,0xF0,0xC4,0xAF,0xBC,0x2B,0xAB,0xAF,0xA5,
+    0x10,0xC5,0xCF,0xBC,0x2A,0x0B,0x3B,0xFF,0x31,0xCD,0xF0,0xC4,0xA8,0x8A,0xCF,0x75,
+    0x31,0xCD,0xD0,0xBC,0x02,0x80,0xA8,0xAD,0x31,0xCD,0xAF,0xBC,0xE0,0xFA,0x6A,0x6A,
+    0xD0,0xBC,0x2E,0xAC,0x68,0x78,0x5E,0xDF,0x4E,0xAC,0x0D,0xA4,0xAB,0xBF,0x7F,0xEF,
+    0x4E,0xAC,0x0D,0xA4,0xEA,0xCB,0xA9,0xBE,0xF0,0xBC,0x2D,0xA4,0x75,0xA9,0x2F,0x0B,
+    0x93,0xD5,0x4E,0xAC,0x55,0xBF,0x0A,0x0A,0xB3,0xD5,0x6F,0xB4,0xD5,0xAA,0x20,0x00,
+    0xB4,0xD5,0x11,0xC5,0x29,0x0A,0x00,0x00,0xB4,0xD5,0x73,0xCD,0x22,0x0A,0x04,0xD6,
+    0xD4,0xD5,0x32,0xC5,0x78,0x58,0x7C,0x58,0x52,0xC5,0x12,0xBD,0x02,0x6B,0x75,0x5D,
+    0x32,0xBD,0xB0,0xAC,0xA0,0xBA,0xAE,0x77,0x93,0xCD,0x11,0xBD,0x3D,0x2F,0x0D,0x09,
+    0x93,0xCD,0x32,0xC5,0x80,0x80,0x80,0x60,0x93,0xCD,0xB0,0xB4,0xE8,0xEA,0xFE,0x5F,
+    0xF0,0xBC,0x8F,0xAC,0x9A,0xA8,0xFA,0xAF,0x11,0xBD,0xB0,0xAC,0x02,0xC0,0xFA,0x7C,
+    0xD0,0xB4,0x6E,0xAC,0xE2,0xEC,0xFE,0xDF,0xD0,0xB4,0x8F,0xAC,0xD5,0xDF,0xE9,0x3F,
+    0x84,0x59,0x23,0x51,0xA8,0xEE,0x5B,0x56,0x63,0x51,0x23,0x51,0xF8,0x95,0x95,0xA5,
+    0x64,0x59,0x02,0x49,0xEA,0x6A,0x7C,0xFA,0x64,0x59,0x02,0x49,0xBD,0x22,0xEE,0xEA,
+    0x64,0x51,0x03,0x51,0xEF,0x7A,0xE7,0xAF,0x64,0x59,0x23,0x51,0xBF,0xCB,0xBB,0xFA,
+    0x63,0x59,0x23,0x51,0x7F,0xFD,0xAF,0xB3,0x63,0x59,0x23,0x51,0x7F,0xFD,0x8B,0x8B,
+    0x84,0x61,0x43,0x59,0xA9,0x2F,0x2A,0xEA,0x84,0x61,0x43,0x59,0xF8,0x7C,0x78,0xE3,
+    0x84,0x61,0x43,0x59,0xAD,0xB5,0x9F,0xD5,0x84,0x61,0x63,0x59,0xA1,0xAE,0x55,0x85,
+    0x84,0x61,0x43,0x59,0xCA,0xAA,0xEA,0xFF,0x63,0x59,0x23,0x51,0x83,0xAF,0xB4,0x0E,
+    0x63,0x59,0x22,0x59,0x80,0x82,0x3E,0xEE,0x63,0x59,0x23,0x51,0xA2,0xEE,0xEB,0xEF,
+    0x43,0x59,0x02,0x51,0xA0,0x3E,0x3F,0xF8,0x64,0x59,0x23,0x51,0xEA,0xF2,0xF2,0xFB,
+    0x43,0x59,0xE2,0x48,0xB0,0x7A,0xFE,0xAA,0x23,0x51,0xE2,0x48,0x62,0xEB,0xAF,0xAA,
+    0x23,0x51,0xE2,0x48,0x37,0x8A,0x82,0x02,0x23,0x51,0xE2,0x48,0xE8,0xF0,0x6B,0x2E,
+    0x23,0x51,0xE2,0x48,0x3B,0xFD,0xF5,0xBF,0xA5,0x69,0xE2,0x48,0xDF,0xBF,0xBF,0x2F,
+    0x8B,0x9B,0x44,0x59,0x2D,0x2B,0x0B,0x02,0xCC,0xA3,0x8B,0x9B,0x2B,0x62,0xFA,0xDE,
+    0xAC,0xA3,0x6A,0x9B,0xEC,0xA9,0x2A,0xBA,0x8B,0x9B,0x29,0x93,0x2A,0x22,0xC8,0x7C,
+    0x8A,0x9B,0x29,0x93,0xE0,0xE0,0xEE,0xDD,0x49,0x93,0x09,0x93,0x80,0x8A,0xA8,0xFF,
+    0x6A,0x9B,0x29,0x93,0x0A,0x8F,0xF8,0xED,0x8B,0x9B,0x4A,0x93,0xB8,0xBB,0xAF,0xAF,
+    0x6A,0x9B,0xE8,0x8A,0x78,0xE0,0x68,0x60,0xC8,0x82,0x87,0x7A,0xBC,0xA8,0xA0,0x83,
+    0xE8,0x82,0xA7,0x7A,0xDF,0x8F,0x0F,0xA5,0xC8,0x82,0xA5,0x61,0x7A,0xF8,0xE0,0xA8,
+    0xE6,0x61,0x03,0x41,0x57,0x56,0x58,0x78,0x23,0x49,0xE3,0x40,0xAA,0x3E,0xFA,0xE0,
+    0x64,0x51,0x03,0x41,0xFF,0xFF,0x35,0xB5,0x64,0x51,0x03,0x41,0x55,0xFF,0xEA,0xC2,
+    0x44,0x49,0x03,0x41,0x2A,0xFF,0x72,0xEA,0x64,0x49,0x03,0x41,0x03,0xAF,0xEF,0xF5,
+    0x65,0x49,0xE3,0x38,0xFC,0x5E,0x7F,0x6F,0x44,0x49,0xE2,0x38,0x37,0xB5,0x75,0x55,
+    0x65,0x49,0xE2,0x38,0x2A,0x0A,0xA9,0xAD,0x64,0x49,0x23,0x41,0x5C,0xDF,0x27,0xCB,
+    0x64,0x49,0x02,0x41,0xFB,0xFB,0x7A,0xCE,0x23,0x41,0xC2,0x38,0x7C,0xB8,0xBA,0xEF,
+    0x03,0x41,0xC2,0x38,0x0A,0x2B,0xAF,0xBE,0x43,0x49,0xE3,0x38,0xB8,0xFF,0xED,0xFF,
+    0x23,0x41,0xE2,0x38,0xAA,0x38,0xBF,0xDE,0x24,0x41,0xE3,0x38,0xB7,0x37,0x07,0xA8,
+    0x85,0x51,0x24,0x49,0x27,0x0B,0x2B,0xBF,0xE6,0x61,0x85,0x59,0x2A,0x22,0x88,0xBD,
+    0xE6,0x61,0x44,0x51,0x5C,0x78,0xE0,0xFE,0x85,0x51,0x04,0x49,0xDD,0xAB,0xAA,0x08,
+    0x64,0x51,0x24,0x49,0xE7,0xAA,0x28,0xE8,0x85,0x51,0x23,0x49,0xE5,0x2E,0x2A,0x0B,
+    0xA5,0x51,0x23,0x49,0xBF,0xFE,0xDC,0x7A,0x44,0x49,0xC3,0x38,0x78,0x58,0x5E,0x5E,
+    0xC3,0x30,0xA2,0x30,0x8C,0x48,0x7E,0xDD,0xC2,0x30,0xA2,0x28,0x82,0x8A,0x95,0x2E,
+    0xE3,0x38,0xC2,0x30,0x41,0x41,0xDF,0xB6,0x03,0x41,0xA2,0x30,0xAD,0xBE,0x2F,0x2F,
+    0x64,0x51,0x03,0x39,0x2D,0xBD,0x0F,0x2B,0x64,0x51,0x24,0x49,0xEA,0x60,0xFC,0x7A,
+    0x85,0x51,0x23,0x49,0x29,0x09,0xBD,0x3F,0xA5,0x59,0x44,0x51,0xAA,0xA3,0x6E,0x6F,
+    0x85,0x59,0x24,0x49,0x2A,0xAA,0xAA,0x5B,0x85,0x51,0x44,0x49,0xBA,0xF2,0xE0,0x51,
+    0x85,0x51,0x03,0x41,0xF8,0xFA,0x7E,0x5F,0x23,0x41,0x03,0x41,0x2E,0x88,0x00,0x30,
+    0x23,0x41,0xE3,0x38,0xA0,0xE8,0xFA,0x7F,0x44,0x41,0xE2,0x38,0x7A,0x73,0xF5,0xD5,
+    0x23,0x41,0xE2,0x38,0x15,0xD5,0xB7,0xDB,0x23,0x41,0xE2,0x38,0xA2,0x88,0xE3,0xAB,
+    0x44,0x49,0xE2,0x38,0xF7,0x77,0xAE,0x22,0x44,0x49,0x03,0x39,0xD5,0xF5,0xFE,0xD8,
+    0x23,0x41,0x03,0x39,0x76,0x38,0x00,0x0B,0x23,0x41,0xE2,0x38,0xFD,0xE0,0xE0,0x80,
+    0x23,0x41,0xE2,0x38,0x17,0xFE,0xDA,0x3F,0x44,0x41,0x03,0x41,0x27,0x09,0x27,0x9F,
+    0x44,0x41,0x23,0x41,0x72,0xE0,0x08,0xE0,0x44,0x41,0x03,0x39,0xFA,0x7A,0x7E,0x5F,
+    0x44,0x41,0xE2,0x38,0xFE,0xD5,0x55,0xDD,0x23,0x41,0xC2,0x30,0x3A,0xAA,0xDA,0xF8,
+    0x43,0x41,0x03,0x39,0x7A,0xFB,0xF5,0x7D,0x43,0x41,0x03,0x39,0x29,0xEF,0xEB,0xF9,
+    0x23,0x41,0x03,0x41,0x08,0xF7,0xFE,0xFA,0x64,0x49,0x03,0x41,0x02,0x29,0xFD,0x55,
+    0x85,0x51,0x23,0x41,0xFA,0xE2,0xA3,0xA9,0x85,0x51,0x24,0x49,0xAF,0xB5,0xBE,0xBA,
+    0xA5,0x51,0x24,0x49,0x8A,0xAA,0xEB,0xDF,0xA5,0x59,0x44,0x49,0xFA,0xA2,0x2B,0xAD,
+    0xE6,0x61,0x64,0x51,0xD7,0xFE,0x3F,0x2A,0x27,0x6A,0x64,0x51,0xD5,0xFF,0x3F,0x0A,
+    0x26,0x6A,0x84,0x59,0xBD,0xFB,0xEC,0xE8,0x26,0x6A,0xC5,0x61,0xF7,0xEE,0xA5,0x3D,
+    0x27,0x6A,0xC5,0x61,0xFA,0xD6,0x9A,0xC0,0xA8,0x7A,0x06,0x62,0x2D,0x3D,0xD5,0xF5,
+    0xC9,0x82,0x67,0x72,0x0A,0xAA,0x5F,0xDD,0x0A,0x8B,0x67,0x72,0x3B,0xBD,0xBD,0x77,
+    0x52,0xCD,0xE9,0x82,0x0B,0x0D,0x2D,0xB5,0x72,0xD5,0xD0,0xBC,0x78,0x78,0x68,0xEA,
+    0xF0,0xC4,0x8F,0xB4,0xFE,0x7E,0x6A,0x60,0xCF,0xBC,0x6E,0xB4,0x0A,0x2A,0x2F,0xB9,
+    0xF0,0xC4,0x8F,0xB4,0xA8,0xAA,0x2B,0xBD,0xF0,0xC4,0xCF,0xBC,0x09,0x2F,0xF5,0x56,
+    0x10,0xC5,0xAF,0xBC,0x02,0xE8,0xFE,0x5D,0xF0,0xBC,0x4E,0xAC,0xE8,0xFA,0xFE,0x7A,
+    0x8F,0xB4,0x2D,0xAC,0xDF,0x77,0xF5,0x2A,0xD0,0xBC,0x0D,0xA4,0x5D,0xDD,0xFD,0x2A,
+    0x31,0xC5,0x0D,0xA4,0xD5,0xF7,0xAF,0x02,0x52,0xCD,0xAF,0xB4,0xAD,0x0B,0x0A,0x00,
+    0x72,0xCD,0x32,0xC5,0x07,0x08,0x0A,0xFB,0xD4,0xD5,0x52,0xC5,0x0A,0x2B,0xBD,0x75,
+    0xD4,0xD5,0x93,0xCD,0xE2,0x28,0xED,0xFD,0xB4,0xD5,0x52,0xC5,0xAE,0xFA,0x7C,0xE0,
+    0x93,0xCD,0xD0,0xB4,0xE0,0x6A,0xF8,0x78,0x12,0xBD,0x90,0xAC,0xE8,0x7A,0x7E,0x7F,
+    0xAF,0xAC,0x6F,0xAC,0x82,0x9B,0x97,0xBD,0x93,0xCD,0xD0,0xB4,0x0D,0x8F,0x2D,0xAD,
+    0x93,0xCD,0xD1,0xB4,0x80,0xE0,0x7A,0x57,0xF1,0xBC,0x6F,0xA4,0x78,0xD8,0xDE,0xF7,
+    0xD0,0xB4,0x90,0xAC,0x0A,0x03,0x03,0x0A,0xF0,0xB4,0x8F,0xAC,0xEC,0x7A,0xFA,0xFA,
+    0xB0,0xB4,0x4F,0xA4,0xA8,0xAA,0x26,0x80,0xF1,0xB4,0x8F,0xAC,0x37,0x2D,0x0F,0x2B,
+    0x64,0x59,0x03,0x49,0xF8,0xAF,0xEF,0xFD,0x64,0x59,0x23,0x51,0xFB,0xD9,0xFF,0x5F,
+    0x43,0x51,0x03,0x49,0xA0,0x6B,0xA8,0x0A,0x43,0x51,0x02,0x49,0xB8,0x3E,0x2F,0x08,
+    0x64,0x59,0x23,0x51,0x9E,0xD1,0xA9,0xE3,0x84,0x59,0x23,0x51,0xF8,0x7B,0xFF,0xAB,
+    0x63,0x59,0x23,0x51,0xB3,0xBE,0xBE,0xFE,0x64,0x59,0x43,0x59,0x8D,0x0A,0xFE,0xD8,
+    0x84,0x61,0x43,0x59,0xEB,0xB3,0x6D,0x69,0xA4,0x61,0x43,0x59,0xE3,0x7B,0xFD,0xF5,
+    0x84,0x61,0x43,0x59,0x7A,0x7B,0x7B,0x89,0x84,0x59,0x43,0x59,0xAF,0xD9,0x7F,0x7E,
+    0x63,0x59,0x43,0x59,0xE8,0x5A,0x77,0x65,0x63,0x59,0x02,0x51,0x08,0xBA,0x7A,0x6A,
+    0x64,0x59,0x23,0x51,0xAA,0x8B,0x3D,0x35,0x64,0x59,0x23,0x51,0xEA,0xFA,0x7E,0xFE,
+    0x43,0x59,0x23,0x51,0x63,0xAA,0xF7,0x73,0x44,0x59,0x03,0x51,0x02,0xA2,0xBA,0x63,
+    0x23,0x51,0x02,0x49,0xCA,0x6A,0x6F,0x59,0x43,0x51,0x02,0x49,0x7F,0xDA,0xA3,0xBB,
+    0x23,0x51,0x03,0x49,0xBD,0xB5,0x34,0xAD,0x23,0x51,0x03,0x49,0xFF,0xBB,0xFB,0x43,
+    0x42,0x51,0x02,0x49,0xF5,0x7F,0xBF,0xBF,0x4A,0x93,0x43,0x59,0xF5,0xB5,0x2D,0x2B,
+    0xCC,0xA3,0x29,0x93,0x0D,0x03,0x02,0xA2,0xCC,0xA3,0x4A,0x9B,0xE0,0xE8,0xFC,0xDE,
+    0x8B,0x9B,0x29,0x93,0xA8,0xAC,0xFA,0x7A,0x6A,0x9B,0x2A,0x93,0x72,0xAA,0xBF,0x9D,
+    0x6B,0x9B,0x29,0x93,0xFF,0xCB,0xE7,0x57,0x29,0x93,0x09,0x8B,0xFA,0x38,0x38,0x20,
+    0x6B,0x9B,0x29,0x93,0xED,0xF5,0x3D,0xAD,0x8B,0x9B,0x4A,0x9B,0xEF,0xAB,0x0B,0x83,
+    0x6A,0x9B,0xC8,0x82,0x60,0x60,0xF0,0xF8,0xC8,0x82,0x87,0x7A,0xE8,0x74,0x5E,0xD6,
+    0xC8,0x82,0x66,0x72,0x0A,0xBB,0xFF,0xFD,0xA8,0x7A,0x67,0x72,0xF7,0x7F,0xEC,0x36,
+    0x68,0x7A,0x44,0x49,0x7A,0xE8,0x80,0xA0,0xC5,0x61,0x03,0x49,0x55,0x5F,0x56,0x58,
+    0x23,0x49,0xE3,0x40,0x8F,0x97,0x37,0xEB,0x64,0x49,0x23,0x49,0x0D,0x85,0xB5,0xB5,
+    0x64,0x51,0x03,0x41,0x7E,0x5A,0xF8,0xE0,0x23,0x41,0x03,0x41,0xF6,0x21,0x41,0x5F,
+    0x03,0x41,0xE2,0x38,0xF8,0xE8,0x5C,0x56,0x03,0x41,0xC2,0x38,0xEF,0xFA,0x35,0xBE,
+    0x44,0x49,0xE2,0x38,0xAD,0x3F,0xDE,0xAB,0x64,0x49,0x23,0x41,0x8B,0xF9,0xF5,0xAD,
+    0x44,0x41,0x03,0x41,0xC6,0x57,0xF6,0xE8,0x03,0x41,0xC2,0x38,0xFE,0xA0,0x80,0x70,
+    0x03,0x41,0xC2,0x38,0xAA,0xAE,0xEF,0xB7,0x24,0x41,0xE3,0x38,0x5E,0xDF,0x1F,0xED,
+    0x24,0x41,0xE3,0x38,0x9B,0xB6,0xAC,0xAA,0x45,0x41,0x04,0x41,0xEF,0xFA,0x5F,0x77,
+    0x85,0x51,0x24,0x49,0xFF,0xDD,0xDB,0x55,0x85,0x59,0x24,0x49,0x02,0xAB,0x2F,0xDD,
+    0x85,0x59,0x24,0x49,0x2A,0xE8,0xDE,0xFF,0xC6,0x59,0x44,0x51,0x0B,0x2B,0x2D,0xBD,
+    0xC6,0x61,0x23,0x49,0x7E,0x78,0xC8,0xA2,0xA5,0x59,0x24,0x49,0x29,0xB9,0xA9,0xAB,
+    0xA6,0x59,0x23,0x41,0x6A,0x60,0xFA,0x6E,0x23,0x49,0xA3,0x30,0x7A,0x6E,0xFC,0xFE,
+    0xC2,0x30,0x83,0x30,0x2B,0xAA,0xAF,0x2D,0x03,0x39,0xA2,0x30,0xF7,0xA7,0x2B,0x0D,
+    0x24,0x41,0xE3,0x38,0xFD,0xEF,0xAA,0x8E,0x24,0x41,0xE3,0x38,0xBF,0xBB,0xBF,0xB7,
+    0xA5,0x59,0x24,0x41,0xAD,0xEB,0x0D,0x21,0xA6,0x59,0x23,0x49,0xFF,0xF6,0xDE,0x38,
+    0xA5,0x59,0x44,0x51,0xB7,0x3D,0x27,0xBB,0xA5,0x59,0x44,0x51,0xFA,0x6E,0xEA,0x88,
+    0x64,0x51,0x03,0x49,0x5C,0x56,0x5E,0x58,0x24,0x49,0xE3,0x40,0x22,0xFD,0xA3,0x02,
+    0x44,0x49,0x03,0x39,0xE8,0xAA,0x4A,0xEA,0x23,0x41,0xC2,0x38,0xF8,0xEB,0xFB,0x7E,
+    0x03,0x39,0xC2,0x38,0xEE,0x97,0x17,0x27,0x03,0x41,0xE3,0x38,0x2B,0x2F,0xFE,0xFE,
+    0x44,0x41,0x03,0x41,0x57,0xA1,0x0B,0xA9,0x64,0x49,0x23,0x41,0x5D,0x7F,0x62,0xC2,
+    0x64,0x49,0x23,0x41,0x29,0x0D,0xB5,0x95,0x85,0x49,0x23,0x41,0x58,0x52,0x5A,0x5E,
+    0x23,0x41,0xE2,0x38,0xEA,0xFE,0xEF,0xFF,0x24,0x41,0xE2,0x38,0x99,0xB9,0xAF,0xE7,
+    0x44,0x41,0xE2,0x38,0xF7,0x7E,0xFA,0xAF,0x44,0x41,0xE2,0x38,0x3F,0xAD,0xBF,0xBE,
+    0x44,0x41,0x03,0x39,0xA0,0xAB,0x77,0x7A,0x23,0x41,0xE2,0x38,0xE8,0x78,0x6A,0x72,
+    0x03,0x39,0xE3,0x38,0xFB,0xEF,0x3F,0x2D,0x23,0x39,0xE2,0x38,0xAA,0xA8,0x43,0x83,
+    0x23,0x39,0xE2,0x38,0x8B,0xAD,0xE5,0x5D,0x23,0x41,0xE3,0x38,0x8A,0xBE,0xAA,0xA2,
+    0x44,0x49,0xE3,0x38,0xFB,0x6F,0xFA,0x02,0x44,0x49,0xE3,0x40,0xF7,0xEF,0x3F,0xAA,
+    0x64,0x49,0x23,0x41,0xCB,0xA9,0xBB,0x3A,0xA5,0x51,0x44,0x49,0xFB,0xEA,0xAB,0x37,
+    0xA5,0x59,0x44,0x49,0xDF,0x7F,0xD6,0x7C,0xA5,0x59,0x23,0x49,0x2F,0xBF,0xFF,0xD7,
+    0xC5,0x61,0x64,0x49,0xAA,0xAF,0x27,0x25,0x67,0x72,0xC5,0x59,0x29,0x25,0xD5,0x55,
+    0x88,0x72,0xE5,0x61,0x7E,0xC8,0x8B,0xB5,0x67,0x72,0xA4,0x59,0xDD,0xFB,0xF8,0x88,
+    0x47,0x72,0xE6,0x61,0x8A,0xBF,0x3F,0xFF,0xC9,0x82,0x26,0x6A,0xB5,0x2D,0x2B,0x2D,
+    0x0A,0x8B,0x67,0x72,0x57,0x7B,0xEE,0xA8,0xA8,0x7A,0x27,0x72,0xE7,0xA9,0xAA,0xA8,
+    0xED,0xA3,0x88,0x7A,0x3D,0xB5,0xF5,0xFF,0x51,0xCD,0xED,0xAB,0xA2,0x03,0x09,0x09,
+    0x10,0xC5,0xAF,0xBC,0x7E,0x7A,0x6A,0xA0,0xCF,0xBC,0x6E,0xB4,0x77,0x57,0xF7,0x5C,
+    0xCF,0xBC,0x6E,0xB4,0x2D,0xBF,0xFF,0x7D,0xCF,0xBC,0x6E,0xB4,0x80,0xA8,0xF3,0xD7,
+    0xAF,0xB4,0x6F,0xB4,0xA0,0xDC,0xDF,0x7E,0x31,0xCD,0x8F,0xB4,0x77,0xAD,0x2F,0x29,
+    0x52,0xCD,0xAF,0xBC,0xFD,0xAB,0x8A,0x20,0x51,0xC5,0xF0,0xC4,0x55,0xB6,0x8E,0xA2,
+    0x72,0xCD,0xF0,0xBC,0xA7,0x37,0xAF,0x2A,0xB3,0xD5,0x72,0xCD,0x55,0xAB,0x83,0x8B,
+    0xB3,0xD5,0x10,0xBD,0x7F,0xFA,0xFA,0xE0,0x52,0xC5,0x11,0xBD,0x0D,0x2F,0xED,0x7E,
+    0x93,0xCD,0x11,0xBD,0x82,0x3F,0xFF,0xF5,0xB3,0xCD,0x52,0xC5,0x00,0x02,0xAA,0xD7,
+    0x93,0xCD,0xD1,0xB4,0x78,0xA0,0x00,0x00,0x73,0xCD,0xB0,0xB4,0x55,0x5F,0x7C,0x60,
+    0xD1,0xB4,0x2F,0xA4,0xBE,0xBF,0x3F,0x28,0x32,0xC5,0x90,0xAC,0x03,0x82,0x42,0x62,
+    0xD0,0xB4,0xCD,0x93,0xA8,0xFA,0x7F,0x57,0xF1,0xB4,0x0E,0x9C,0xBA,0x2B,0x2D,0xAF,
+    0xF1,0xB4,0xB0,0xB4,0xBD,0xB6,0xF5,0xD5,0xD0,0xB4,0x90,0xAC,0xBA,0xC8,0xEA,0x7A,
+    0xD0,0xB4,0x8F,0xAC,0x2E,0xB6,0x57,0xD7,0x11,0xBD,0x90,0xAC,0x2F,0xAF,0xB9,0x6F,
+    0x43,0x51,0x02,0x49,0xBD,0xFF,0x5A,0x72,0x43,0x51,0xE2,0x48,0xA2,0xF8,0xFF,0xAE,
+    0x64,0x59,0x23,0x51,0x75,0xF5,0xEF,0x8F,0x64,0x59,0x43,0x51,0xFD,0xDD,0x75,0x5E,
+    0x64,0x59,0x02,0x49,0x6B,0x6A,0xAA,0x22,0xA4,0x61,0x02,0x49,0xEF,0xAD,0xAF,0x8A,
+    0xA4,0x61,0x44,0x59,0xD7,0xBD,0xFF,0xD5,0x84,0x61,0x23,0x51,0xF8,0xBA,0x7E,0xFF,
+    0x84,0x61,0x23,0x51,0x2A,0x2E,0x2F,0x0B,0x84,0x59,0x43,0x59,0xAD,0x8A,0xAE,0xEE,
+    0x84,0x61,0x23,0x51,0x88,0xC2,0xAA,0x7E,0x63,0x59,0x03,0x51,0xA0,0x82,0x98,0xAE,
+    0x43,0x59,0x23,0x51,0x08,0x36,0x28,0x20,0x64,0x59,0x23,0x51,0x9B,0xDF,0xBB,0xF8,
+    0x64,0x59,0x02,0x51,0x3F,0x3B,0xDF,0xBA,0x64,0x59,0x23,0x51,0x7E,0xEE,0xBA,0xFB,
+    0x64,0x59,0x23,0x51,0xF9,0x6B,0x6C,0x55,0x44,0x59,0x03,0x49,0xC2,0xD2,0xBC,0xD6,
+    0x43,0x51,0xE2,0x48,0xFF,0xAE,0x7F,0xB2,0x23,0x51,0xE2,0x48,0x82,0xAA,0xED,0xF6,
+    0x43,0x51,0x03,0x49,0xF7,0x75,0x7D,0xFB,0x43,0x51,0x03,0x49,0xFB,0xAB,0x8B,0x2E,
+    0x68,0x7A,0x23,0x51,0xD5,0xD5,0x35,0x2D,0xAB,0xA3,0x27,0x72,0x2D,0x29,0x0B,0x0A,
+    0xCC,0xA3,0x8B,0xA3,0xAB,0x00,0x68,0x58,0x8B,0xA3,0x4A,0x93,0x6C,0x2C,0xFF,0xDF,
+    0x6A,0x9B,0x29,0x93,0xBA,0xBE,0xF8,0x72,0x4A,0x93,0x09,0x93,0xF8,0x72,0xEA,0x20,
+    0x4A,0x93,0x09,0x8B,0x38,0x95,0x27,0xB4,0x6A,0x9B,0x29,0x93,0x6B,0xAB,0xBB,0x27,
+    0x6A,0x93,0x09,0x93,0x8D,0xBE,0xEE,0xEA,0x8B,0x9B,0x4A,0x93,0xB2,0xAF,0xBF,0xFD,
+    0x8B,0x9B,0xA7,0x82,0xFA,0x7A,0x7A,0x7A,0xA7,0x82,0x87,0x7A,0x3F,0xF0,0xC8,0xC8,
+    0xA8,0x82,0x67,0x7A,0xBE,0xE2,0xFF,0x7F,0xA7,0x7A,0x67,0x7A,0xBC,0xDA,0x69,0x5F,
+    0x87,0x7A,0x26,0x6A,0x5C,0x7E,0xFA,0xFA,0x26,0x6A,0x64,0x51,0x5C,0x78,0xE0,0x80,
+    0x85,0x59,0xE3,0x40,0x77,0x5F,0xDE,0xC0,0x44,0x49,0xE3,0x40,0x0A,0x29,0x2B,0xA2,
+    0x64,0x49,0x23,0x49,0x80,0xCA,0xBE,0xDD,0x44,0x49,0xC2,0x38,0xFA,0x7E,0x76,0xE8,
+    0x03,0x39,0xC2,0x38,0xBF,0xBF,0x89,0xAA,0x03,0x39,0xC2,0x38,0x80,0xA8,0xAE,0xD6,
+    0x44,0x49,0xE3,0x38,0x8B,0xAB,0xBF,0xF5,0xA5,0x51,0x23,0x41,0xF5,0xE5,0xA5,0x3D,
+    0x85,0x51,0x23,0x41,0x7A,0x7A,0x72,0xE0,0x23,0x41,0xC3,0x38,0x73,0xEA,0xB8,0xFA,
+    0x03,0x41,0xC2,0x38,0xEF,0xAA,0xF0,0x70,0x23,0x41,0xE3,0x38,0xBB,0xAB,0xAB,0xDD,
+    0x24,0x41,0xE3,0x38,0xCA,0xFA,0xF8,0xEA,0x03,0x41,0x23,0x39,0x2A,0xA0,0x80,0x88,
+    0x44,0x49,0xE3,0x38,0xAA,0xAA,0x2B,0xA7,0x64,0x51,0x24,0x49,0xF5,0xB9,0xCE,0xFF,
+    0x85,0x51,0x44,0x51,0x7B,0xF9,0x89,0x87,0x85,0x59,0x65,0x51,0x25,0x0D,0xAB,0xC9,
+    0xE6,0x61,0x85,0x59,0xE1,0xE3,0x7D,0x55,0xC6,0x59,0x65,0x51,0xB7,0xBA,0xE3,0xCD,
+    0x85,0x51,0x44,0x49,0x6A,0x68,0xE2,0x5C,0x44,0x49,0xC2,0x30,0x7E,0xF4,0x7E,0x5F,
+    0xC2,0x30,0xA2,0x30,0xBF,0x98,0x20,0x22,0x24,0x39,0xC2,0x30,0xA5,0x3D,0xA5,0xFD,
+    0x24,0x41,0xE3,0x38,0xAA,0x9E,0xEE,0xE7,0x03,0x41,0xE3,0x38,0x27,0x2B,0xE0,0xEA,
+    0xA5,0x59,0x03,0x41,0x09,0x2D,0x0F,0x3D,0x07,0x62,0x85,0x59,0xDF,0x7B,0xB3,0xBB,
+    0x07,0x6A,0x85,0x59,0x57,0x7F,0xF2,0xE8,0xC6,0x59,0x44,0x51,0x29,0xAA,0xE2,0xEA,
+    0xA5,0x59,0x03,0x41,0x58,0x78,0x7A,0x7A,0x24,0x49,0x03,0x41,0x8A,0xAA,0xF5,0x55,
+    0x24,0x41,0x03,0x41,0x60,0xE0,0x60,0x63,0x03,0x41,0xC2,0x38,0x7A,0x6A,0xEE,0xBA,
+    0x24,0x41,0xE3,0x38,0xA5,0xA5,0xAF,0xAD,0x23,0x41,0x03,0x39,0xB7,0xAF,0x3F,0x35,
+    0x64,0x49,0x24,0x41,0x6D,0xA9,0xAD,0xBD,0x64,0x49,0x23,0x41,0x09,0xAF,0xA2,0x8A,
+    0x65,0x49,0x03,0x41,0xBF,0xDF,0xBA,0x8A,0x64,0x49,0x03,0x39,0x78,0xEC,0x7F,0x7E,
+    0x23,0x41,0xE3,0x38,0xFF,0x5F,0x7F,0x2A,0x03,0x41,0xC2,0x30,0xAE,0xAF,0x5D,0xFC,
+    0x44,0x41,0xE2,0x38,0x2B,0x8E,0x75,0xD5,0x23,0x41,0xE2,0x30,0x3A,0x3B,0xFF,0xAF,
+    0x24,0x39,0x03,0x39,0x68,0x56,0xFF,0xF5,0x44,0x41,0xE3,0x38,0x7B,0xFF,0xE8,0xAA,
+    0x23,0x39,0xE3,0x30,0xE7,0xD7,0xF7,0xEA,0x23,0x39,0xE3,0x30,0xAC,0x3E,0xFB,0xF2,
+    0x03,0x39,0xE2,0x30,0xDF,0x3E,0xBA,0xF8,0x44,0x41,0xE2,0x38,0xF5,0xF6,0xF7,0x35,
+    0x85,0x49,0x03,0x39,0xAD,0x2D,0xA5,0xF5,0x64,0x49,0x03,0x41,0xF8,0xDE,0xFA,0xAA,
+    0x44,0x49,0x23,0x39,0x02,0x82,0x02,0x20,0x85,0x51,0x23,0x49,0xB7,0xBF,0xE2,0xE2,
+    0x85,0x51,0x23,0x49,0x58,0x7F,0xD7,0x7F,0x64,0x49,0x23,0x49,0xAB,0xB5,0xB5,0x5F,
+    0xA5,0x59,0x23,0x49,0x2F,0xAF,0xFF,0x7D,0xC5,0x59,0x64,0x51,0x03,0x0B,0x2B,0xB5,
+    0x05,0x62,0x84,0x51,0x3A,0xBB,0xAD,0xF5,0x47,0x72,0xC5,0x61,0x02,0x8A,0xEB,0xBD,
+    0x47,0x72,0xE5,0x61,0xFE,0xFE,0x2E,0x2B,0xC9,0x82,0x26,0x6A,0x25,0xB5,0xF5,0xFF,
+    0x2A,0x8B,0x88,0x7A,0xAA,0x0B,0xA9,0xBB,0x29,0x93,0x87,0x7A,0xD7,0x7E,0xEA,0xA0,
+    0x0A,0x8B,0x88,0x7A,0x2B,0xB5,0xFF,0xB6,0x52,0xD5,0x4A,0x93,0x09,0x2D,0x2D,0x2D,
+    0x72,0xD5,0xF0,0xC4,0x7C,0x78,0xF8,0xE0,0x51,0xCD,0x4E,0xAC,0x5E,0x7A,0xA8,0x00,
+    0x72,0xCD,0x4E,0xAC,0x55,0xD5,0xFF,0x02,0xD3,0xDD,0x6E,0xB4,0x55,0x55,0x7F,0xA8,
+    0xF0,0xC4,0x4D,0xAC,0x96,0xD7,0x97,0x00,0x92,0xD5,0xD0,0xBC,0xBD,0xAD,0x2D,0x0B,
+    0xB3,0xD5,0x51,0xCD,0x5D,0xFF,0x0B,0x0A,0xD4,0xDD,0x72,0xCD,0x5D,0xEA,0x60,0x6A,
+    0x93,0xCD,0x52,0xCD,0x57,0xDC,0x37,0x87,0xD4,0xD5,0x72,0xCD,0x8D,0xF9,0xFE,0xDE,
+    0xB4,0xD5,0x73,0xCD,0x70,0x5A,0xF7,0xD7,0x72,0xCD,0x11,0xBD,0x7E,0xE8,0xF8,0xBC,
+    0x32,0xC5,0x11,0xBD,0xBF,0xFE,0x90,0x60,0x52,0xC5,0xF1,0xBC,0x80,0xAE,0xAF,0xF7,
+    0x93,0xCD,0x32,0xC5,0x03,0xAB,0xBF,0xFD,0xB4,0xCD,0x52,0xC5,0x5A,0x0B,0xAF,0xBD,
+    0x93,0xCD,0xF1,0xBC,0x57,0xE0,0xA0,0xE0,0x12,0xBD,0xED,0x9B,0xE0,0xE0,0x68,0x78,
+    0x6E,0xA4,0xCC,0x93,0x57,0xD5,0x95,0x35,0xD0,0xB4,0x4E,0xA4,0x29,0x39,0xAB,0x02,
+    0xD0,0xB4,0x8F,0xB4,0xB0,0x78,0xF8,0xEA,0xD1,0xB4,0x6F,0xAC,0xEA,0xA2,0xDE,0xEF,
+    0xD1,0xB4,0x6F,0xAC,0x3F,0xAF,0xB7,0xAE,0xF1,0xB4,0x90,0xAC,0x4F,0xBE,0xA9,0xEB,
+    0x63,0x59,0x23,0x51,0x7E,0x59,0xE6,0xAE,0x43,0x51,0x02,0x49,0x20,0xAA,0xFB,0x6A,
+    0x43,0x51,0x23,0x51,0x02,0x02,0x29,0x99,0x64,0x59,0x23,0x51,0x28,0xAE,0xDB,0x4F,
+    0x64,0x59,0x23,0x51,0xA2,0xE8,0xA8,0xB7,0x84,0x59,0x43,0x59,0x82,0x6B,0x5F,0x5F,
+    0x84,0x61,0x23,0x51,0xFD,0xBB,0xEA,0xC2,0x84,0x61,0x23,0x51,0xF6,0xFF,0xEF,0x8B,
+    0x84,0x61,0x43,0x59,0x0A,0x03,0x27,0xAA,0xA4,0x61,0x43,0x59,0xFA,0x6A,0xE0,0xF2,
+    0x64,0x59,0x23,0x59,0xFE,0xFB,0xBA,0xE8,0x64,0x59,0x23,0x51,0xC8,0x8A,0xEF,0x6B,
+    0x64,0x59,0x23,0x51,0xBA,0xBF,0x1F,0xEF,0x64,0x59,0x23,0x59,0xA8,0xA8,0x02,0xA9,
+    0x85,0x61,0x24,0x51,0xFE,0xFA,0x63,0xFF,0x64,0x59,0x23,0x51,0xAE,0xDD,0x7D,0x6F,
+    0x44,0x59,0x03,0x51,0x5F,0xBC,0xBD,0x6F,0x23,0x51,0xE2,0x48,0xB8,0xF0,0x28,0xB3,
+    0x43,0x51,0x03,0x49,0xFB,0xFA,0xEA,0xDB,0x23,0x51,0xE2,0x48,0x72,0xC8,0x82,0xA2,
+    0x23,0x51,0x03,0x49,0xC1,0xB5,0xCF,0x0A,0x64,0x59,0x03,0x51,0xBF,0xBF,0x37,0x37,
+    0x4A,0x93,0x64,0x59,0x2D,0x2D,0x0B,0x0B,0xCC,0xA3,0x4A,0x9B,0xAD,0x8B,0x2A,0xEE,
+    0xEC,0xAB,0x8B,0x9B,0x5E,0xAF,0xAD,0x8F,0xCC,0xAB,0x4A,0x93,0x77,0x5A,0xE8,0xA0,
+    0xAB,0xA3,0x4A,0x93,0x77,0xDD,0xEE,0xA8,0x6A,0x9B,0x29,0x93,0xFE,0xE6,0xF7,0x5E,
+    0x6A,0x9B,0x09,0x8B,0x5E,0xFE,0xA3,0xAB,0x4A,0x93,0x09,0x93,0xAF,0xED,0xEF,0x30,
+    0x4A,0x93,0x08,0x93,0x20,0xAA,0xA1,0xE8,0x6A,0x93,0x09,0x93,0x3B,0xAD,0xAF,0xEF,
+    0x6A,0x9B,0xC8,0x82,0x72,0x62,0xFA,0x7A,0xA7,0x7A,0x67,0x72,0xA2,0xB8,0x68,0xAA,
+    0xA8,0x7A,0x47,0x72,0xE2,0xE2,0x7F,0xF7,0x67,0x7A,0x26,0x72,0x80,0xE0,0x52,0x50,
+    0x88,0x7A,0x47,0x72,0x7B,0x7D,0x77,0x49,0x46,0x72,0x06,0x6A,0x5F,0x7A,0x7A,0xFA,
+    0x26,0x6A,0x64,0x51,0x7A,0xE8,0xEA,0x08,0xE5,0x61,0x23,0x49,0x55,0x5F,0x5E,0x68,
+    0x43,0x49,0xE3,0x40,0xAA,0xFB,0x5F,0x54,0x43,0x49,0xE3,0x40,0xE8,0xEB,0xEF,0xF5,
+    0xE3,0x40,0xC2,0x30,0xBE,0xEE,0xEA,0x60,0xE2,0x38,0xA1,0x30,0x0C,0xA8,0xFA,0xFB,
+    0x03,0x41,0xC2,0x38,0x0B,0x0D,0x7D,0xF5,0xA5,0x51,0xE3,0x38,0x0F,0x2F,0xAD,0xFD,
+    0x85,0x51,0x23,0x41,0xC0,0xCA,0xEA,0x7A,0x23,0x41,0xE3,0x38,0xBA,0xDC,0xDF,0x5F,
+    0x24,0x41,0xC2,0x38,0xDA,0x2A,0x02,0x00,0x03,0x41,0xE3,0x38,0x7F,0xEC,0xBA,0x38,
+    0x03,0x41,0xE3,0x38,0x36,0xD5,0xD7,0x5E,0x23,0x41,0xE4,0x38,0xEA,0xBF,0x0B,0x0A,
+    0x44,0x49,0xE3,0x38,0x2B,0xB7,0xAE,0xE8,0x65,0x51,0x23,0x49,0xDC,0xF0,0x70,0xF2,
+    0x85,0x59,0x03,0x41,0x0B,0x2B,0xBF,0x77,0xC6,0x59,0x44,0x51,0x8B,0x3A,0xAA,0xFD,
+    0xA5,0x59,0x65,0x51,0xBC,0xBC,0xFE,0xFE,0xC6,0x59,0x64,0x51,0x5A,0x7A,0x4B,0x4F,
+    0x85,0x51,0xC2,0x30,0xE8,0x6A,0x7E,0x5E,0xE3,0x38,0x82,0x30,0xA0,0xEA,0xDE,0xBF,
+    0xC3,0x30,0xA2,0x30,0xE2,0xFF,0x5F,0x94,0xE3,0x30,0x82,0x28,0xAB,0xFD,0xBA,0xA8,
+    0xE3,0x38,0xA2,0x30,0x21,0x7D,0x5F,0x5E,0x03,0x41,0xA3,0x30,0x2B,0xFB,0xBF,0xBD,
+    0x64,0x51,0x03,0x41,0x2D,0x25,0x15,0xD5,0xE6,0x61,0x85,0x51,0x09,0xAB,0xFD,0x55,
+    0xE6,0x61,0x64,0x51,0x00,0x82,0x8B,0xBF,0xC6,0x61,0x64,0x51,0x6A,0xF8,0xF0,0x80,
+    0x64,0x51,0x03,0x41,0xA8,0xE0,0x60,0xF0,0x24,0x49,0x03,0x41,0x56,0xFE,0x2F,0xAC,
+    0x24,0x41,0xE3,0x38,0xAB,0xA6,0x7E,0x78,0x04,0x41,0xC3,0x38,0x5E,0x72,0xAA,0x22,
+    0x03,0x39,0xA3,0x38,0x0B,0xAA,0x88,0x28,0x03,0x39,0xC2,0x38,0x2A,0x2F,0xBD,0xBF,
+    0x85,0x49,0x03,0x39,0x2B,0x2F,0xAD,0x8D,0x85,0x49,0x24,0x41,0xFF,0xD8,0xE0,0xFC,
+    0x85,0x49,0xE2,0x38,0x8A,0x8A,0xFE,0x5D,0x44,0x41,0x03,0x39,0xA8,0xAE,0xFF,0x2D,
+    0x23,0x41,0xE3,0x38,0x00,0xA0,0xF8,0xE0,0x23,0x41,0xC2,0x30,0xFE,0x66,0xFB,0xA8,
+    0x03,0x39,0xC2,0x30,0x2F,0x2F,0x1F,0xF8,0x24,0x41,0xE2,0x30,0xAD,0x2F,0xAF,0xB5,
+    0x23,0x39,0xE3,0x38,0xAA,0x88,0xA8,0x0F,0x24,0x41,0x03,0x39,0x1E,0xB9,0xAD,0xE2,
+    0x23,0x39,0xE2,0x38,0xE8,0x78,0xB2,0xA0,0x23,0x39,0xE2,0x30,0xFF,0x55,0x5F,0xF0,
+    0x23,0x41,0x03,0x39,0x75,0x25,0xA5,0x55,0x23,0x41,0xC2,0x30,0x27,0xAA,0xAF,0x0A,
+    0x23,0x41,0xE2,0x38,0x17,0x0E,0x82,0x02,0x64,0x49,0x23,0x41,0x0B,0x0B,0x7F,0xFF,
+    0x64,0x49,0x23,0x41,0x37,0xDF,0xBA,0xE7,0x84,0x51,0x44,0x49,0x5E,0x2F,0x65,0x7D,
+    0x85,0x51,0x23,0x41,0xFD,0xD7,0xFB,0xC2,0x65,0x49,0x23,0x49,0xF7,0xB5,0x36,0xF7,
+    0x85,0x51,0x23,0x49,0xFF,0xBF,0x35,0x8F,0xC5,0x61,0x22,0x49,0xDF,0xFE,0xA8,0x2B,
+    0xA4,0x59,0x64,0x51,0x9B,0x7D,0xD8,0xA8,0x06,0x62,0x64,0x51,0x2F,0xAD,0x75,0xFF,
+    0x26,0x6A,0x84,0x59,0x00,0xAE,0xF7,0xDD,0x67,0x7A,0xA5,0x61,0x2A,0x2B,0xAD,0xF5,
+    0x0A,0x8B,0x26,0x72,0x0A,0x2B,0xAB,0xFD,0x2A,0x8B,0xC9,0x82,0xC0,0xA2,0x29,0xF9,
+    0x09,0x8B,0xA8,0x7A,0xFA,0xF0,0xA0,0x28,0x52,0xD5,0x09,0x8B,0x2D,0x2D,0xB5,0xB5,
+    0x35,0xE6,0x52,0xD5,0x5F,0xEB,0x0B,0x09,0x55,0xEE,0x72,0xD5,0x55,0xBF,0xAA,0x00,
+    0x35,0xEE,0x72,0xD5,0xAD,0x8A,0x00,0x00,0x55,0xEE,0xF4,0xDD,0x5F,0xFF,0xEF,0xF2,
+    0x35,0xE6,0xD3,0xDD,0x7D,0xAB,0x8A,0x80,0x14,0xE6,0x92,0xD5,0xF7,0xAA,0x00,0x08,
+    0x34,0xE6,0x92,0xD5,0x7F,0xFE,0x8A,0x20,0x14,0xDE,0x52,0xC5,0x57,0x5F,0x5A,0x58,
+    0xB3,0xD5,0x52,0xC5,0xA5,0x3D,0xAF,0xAD,0xB3,0xD5,0x73,0xCD,0xFE,0xEA,0xAA,0x3B,
+    0x93,0xCD,0x52,0xC5,0xEE,0xAE,0xFE,0xF8,0x72,0xCD,0x32,0xC5,0xF4,0xF8,0x78,0xE0,
+    0x52,0xC5,0x12,0xBD,0x6E,0xF8,0x7A,0xAA,0x32,0xC5,0xF1,0xBC,0x5F,0x76,0x7A,0xD8,
+    0x52,0xC5,0xF1,0xBC,0x2B,0xE5,0x5D,0x5D,0x73,0xCD,0xF1,0xBC,0x22,0x0B,0xAF,0xF7,
+    0x73,0xCD,0xD0,0xB4,0xE0,0xF8,0x7E,0x7F,0xD1,0xB4,0xCD,0x9B,0x78,0xF8,0x7E,0x7E,
+    0xB0,0xB4,0xCC,0x93,0x25,0x2F,0x0B,0x0B,0xD1,0xB4,0x8F,0xAC,0xA2,0xE2,0x40,0xA2,
+    0xD0,0xB4,0x8F,0xAC,0xEA,0xDB,0x7A,0xCC,0xB0,0xB4,0x70,0xAC,0xDA,0x90,0x3C,0x2E,
+    0xB0,0xB4,0x70,0xAC,0xA8,0xEA,0xFE,0x18,0xD1,0xB4,0x90,0xAC,0xEB,0xE9,0xD5,0xBD,
+    0x63,0x59,0x23,0x51,0xAE,0xFA,0xF1,0xA3,0x84,0x59,0x43,0x51,0x75,0xDF,0xEB,0xFE,
+    0x84,0x59,0x23,0x51,0x57,0xFA,0xFA,0xDC,0x83,0x59,0x23,0x51,0x7D,0xF5,0xFD,0xEF,
+    0x63,0x59,0x23,0x51,0xDF,0xB2,0x83,0xCB,0x63,0x59,0x23,0x51,0xF1,0xAA,0xAF,0xAA,
+    0x84,0x61,0x43,0x59,0xDB,0xED,0x0F,0x39,0xA4,0x61,0x44,0x59,0xEB,0x2D,0xE8,0xAA,
+    0xA4,0x61,0x64,0x59,0xFF,0xBD,0xA9,0xFF,0x84,0x59,0x43,0x59,0xF8,0x6C,0xEF,0xBF,
+    0x64,0x59,0x23,0x51,0xAA,0x21,0x2A,0xEE,0x63,0x59,0x23,0x51,0xDA,0x7A,0x6F,0xEE,
+    0x64,0x59,0x23,0x51,0xEA,0x8A,0xE9,0xFF,0x44,0x59,0x23,0x51,0xAB,0x5E,0x77,0xDA,
+    0x44,0x59,0x23,0x51,0x92,0x73,0xB6,0xA7,0x44,0x59,0xE2,0x48,0xA0,0xE8,0x78,0xF8,
+    0x23,0x51,0x03,0x49,0x6B,0xDF,0x69,0x6D,0x23,0x51,0xC2,0x40,0xAA,0x98,0xAA,0xAA,
+    0x23,0x51,0xE2,0x48,0xBA,0x6A,0xDA,0xB2,0x23,0x51,0xE2,0x48,0x92,0x23,0x02,0xAA,
+    0x43,0x51,0x03,0x49,0xCA,0xAF,0x5F,0xF7,0xE9,0x8A,0x23,0x51,0xD5,0x95,0xB5,0x25,
+    0xAB,0xA3,0x88,0x82,0x8D,0x2B,0x8B,0x88,0xAB,0xA3,0x6B,0x9B,0xFE,0x2E,0xA6,0x2F,
+    0xEC,0xAB,0xAB,0xA3,0x85,0xAD,0x21,0x2D,0x0D,0xAC,0xCC,0xA3,0x7F,0x7D,0x7F,0x7A,
+    0xCB,0xA3,0x8B,0x9B,0xFE,0x5C,0x56,0x5E,0x8A,0x9B,0x29,0x93,0x6E,0xF8,0x78,0xD8,
+    0x6A,0x9B,0x29,0x93,0xED,0xA7,0xCA,0x7B,0x6A,0x9B,0x09,0x8B,0x3F,0xDF,0xFE,0xFE,
+    0x6A,0x9B,0x2A,0x93,0x7E,0xF9,0xAF,0xAB,0x6A,0x9B,0x08,0x93,0xAD,0x8B,0x82,0x02,
+    0x4A,0x93,0xC8,0x82,0x7A,0x68,0x60,0x70,0xA8,0x7A,0x46,0x72,0xA8,0x5A,0x78,0xFE,
+    0x88,0x7A,0x46,0x72,0xBA,0x69,0xE9,0xEF,0x67,0x7A,0x06,0x6A,0x90,0xFE,0xEE,0xAA,
+    0x67,0x7A,0x06,0x6A,0x60,0x7E,0xFF,0xDF,0x47,0x72,0x06,0x6A,0x7B,0x8D,0x7F,0xE6,
+    0x26,0x6A,0xE6,0x69,0x80,0xE0,0xA8,0xC0,0x06,0x6A,0x64,0x51,0x78,0xEA,0xC0,0x00,
+    0xE5,0x61,0xC2,0x38,0x7F,0x7E,0x7A,0xF8,0x23,0x49,0xC2,0x38,0xBD,0xAD,0x2B,0x80,
+    0x23,0x41,0xE2,0x38,0x5F,0x57,0x5E,0x58,0xE2,0x38,0x81,0x30,0xA2,0x00,0xAC,0xBE,
+    0x03,0x39,0xC2,0x38,0xAB,0xBB,0xFE,0xE7,0x23,0x41,0xE3,0x38,0x2D,0xFB,0xAD,0xAD,
+    0x44,0x49,0xE3,0x38,0xE2,0xEA,0xFE,0x7B,0x03,0x41,0xE3,0x38,0xAA,0x76,0x4A,0xEB,
+    0x23,0x41,0xE3,0x38,0x0A,0xED,0xF5,0x5F,0x24,0x41,0xE2,0x38,0xE0,0xF2,0xFA,0xE3,
+    0x24,0x41,0xC2,0x38,0xEA,0xBD,0xEA,0xAE,0x24,0x41,0xE2,0x38,0xAC,0x77,0xDE,0x8A,
+    0x44,0x49,0xE2,0x38,0xCA,0xFB,0x57,0xF5,0x44,0x49,0x03,0x41,0x2A,0x5B,0xFD,0x9D,
+    0x44,0x49,0x03,0x41,0xF8,0x7F,0x5E,0xFE,0x85,0x51,0x24,0x49,0xA3,0xBD,0xBF,0x27,
+    0xA5,0x59,0x65,0x51,0xFE,0x8B,0x2F,0x8F,0x85,0x51,0x44,0x49,0xC3,0x6E,0x7C,0x5C,
+    0x44,0x49,0xC3,0x30,0x58,0xF0,0xE0,0xF8,0x04,0x39,0xA2,0x30,0xD5,0x7F,0x7A,0xF8,
+    0xE3,0x30,0xA2,0x30,0x9C,0x9F,0x95,0x95,0x24,0x39,0xC3,0x30,0xFD,0xFF,0xEB,0x82,
+    0x03,0x39,0xA2,0x30,0x7F,0xBF,0xEA,0xEC,0x04,0x39,0xC3,0x38,0x55,0xF5,0xAF,0xBD,
+    0x23,0x41,0xE3,0x38,0x3D,0xFD,0xD5,0xBD,0x85,0x59,0x03,0x41,0x0B,0x0F,0xAD,0xBF,
+    0xA5,0x59,0x65,0x51,0x0F,0x8A,0xDB,0xFF,0x26,0x6A,0x85,0x51,0xEB,0x8B,0xAF,0xF5,
+    0xC6,0x59,0x44,0x49,0x7E,0x5E,0xEC,0xBC,0x44,0x49,0x04,0x41,0x7F,0x28,0xBA,0xF8,
+    0x24,0x41,0xE3,0x38,0xFC,0xEE,0xFE,0xBC,0x04,0x41,0xC3,0x38,0xA2,0xE8,0xB0,0xF8,
+    0xE3,0x38,0xC3,0x38,0x00,0x23,0x00,0x08,0x03,0x39,0xC3,0x30,0xAF,0xBF,0x0F,0x28,
+    0x64,0x49,0x03,0x39,0x2B,0x2F,0xBF,0xB5,0x64,0x41,0x03,0x41,0x68,0x7E,0xFE,0xFB,
+    0x44,0x41,0x03,0x41,0x57,0xD5,0xFF,0xF3,0x85,0x49,0x03,0x41,0xBD,0xAF,0xBD,0xFF,
+    0x85,0x49,0x23,0x41,0x5E,0xFE,0x68,0xDA,0x44,0x41,0xE2,0x38,0xAA,0xA2,0xAB,0x7F,
+    0x03,0x39,0xC2,0x30,0x78,0xA8,0x2A,0x00,0x03,0x39,0xC2,0x30,0x2F,0xCB,0xE8,0x23,
+    0x44,0x39,0xE3,0x38,0xBD,0xFD,0xDD,0x55,0x24,0x39,0x03,0x39,0xD0,0x5C,0x5E,0x5D,
+    0x23,0x39,0xC2,0x30,0xA2,0xA8,0xFE,0x77,0x03,0x39,0xE2,0x30,0xE0,0xDE,0xBB,0xAD,
+    0x23,0x41,0xC2,0x30,0xAF,0x2B,0x0F,0x2F,0x43,0x41,0xE2,0x38,0x6B,0xFE,0x2A,0xAA,
+    0x85,0x49,0x23,0x41,0xF5,0x7D,0x97,0x3D,0xA5,0x51,0x23,0x41,0x7D,0xEF,0x6A,0x80,
+    0x85,0x51,0x23,0x41,0xF7,0xFF,0xEB,0x20,0x84,0x51,0x44,0x49,0x5B,0x6A,0xBA,0xC8,
+    0xA6,0x51,0x44,0x49,0xF5,0xFF,0xFF,0xF8,0xA5,0x59,0x23,0x41,0xD7,0xFF,0xA2,0x02,
+    0xA5,0x59,0x64,0x51,0x75,0xA5,0xE5,0x88,0xC5,0x59,0x84,0x51,0x8D,0x2B,0xAB,0xFB,
+    0xE6,0x61,0x84,0x59,0x6A,0xC7,0x27,0x3F,0xC5,0x61,0x84,0x59,0xE3,0x00,0x8E,0x9C,
+    0x06,0x6A,0x64,0x59,0xFD,0xFB,0xAA,0x03,0x06,0x6A,0x84,0x59,0xB5,0xB7,0x37,0x3E,
+    0x88,0x7A,0x06,0x6A,0x2F,0xAF,0xED,0xAF,0x09,0x8B,0x46,0x72,0x2A,0x8F,0xBD,0xB5,
+    0x09,0x8B,0xA8,0x82,0x2F,0xA7,0xA9,0x2F,0x2E,0xAC,0xE9,0x82,0x2D,0x35,0x3D,0xB5,
+    0x35,0xEE,0xB0,0xBC,0x0B,0x0B,0x0B,0x09,0x76,0xEE,0x35,0xEE,0xFE,0xEA,0x2A,0x28,
+    0x76,0xEE,0x35,0xE6,0xFF,0xFA,0xAA,0xAA,0x76,0xEE,0x35,0xE6,0x7E,0xEA,0xE8,0x6A,
+    0x55,0xEE,0x35,0xE6,0x7F,0xA8,0xE8,0x7A,0x14,0xEE,0x35,0xE6,0xFE,0x75,0xD5,0xF5,
+    0x35,0xE6,0xF4,0xDD,0x88,0x88,0xA8,0x78,0xF4,0xDD,0x11,0xC5,0xF0,0x78,0x7C,0x5A,
+    0xB3,0xCD,0x31,0xC5,0xAF,0x8F,0x2D,0x89,0xB3,0xD5,0x52,0xC5,0x2A,0xAA,0xBA,0xF6,
+    0xD3,0xCD,0x73,0xCD,0x5F,0xDF,0x6F,0x7D,0x93,0xCD,0x52,0xC5,0x7F,0x6A,0xBB,0xBE,
+    0x73,0xCD,0x12,0xBD,0xFF,0x7A,0x7A,0x68,0x32,0xC5,0x11,0xBD,0x60,0xEA,0x09,0x0A,
+    0x32,0xC5,0xD0,0xB4,0xFF,0x6A,0xEA,0xA8,0x11,0xBD,0xB0,0xB4,0x0A,0x8B,0xE8,0x6A,
+    0xF1,0xB4,0x89,0x72,0x80,0xA8,0xFE,0x5E,0x90,0xAC,0xAD,0x93,0xFE,0xBF,0xAD,0x2D,
+    0xB0,0xB4,0x4F,0xA4,0x05,0x0B,0x2A,0x0B,0xD0,0xB4,0x90,0xAC,0x8B,0xDE,0x7E,0xFB,
+    0xD1,0xB4,0x6F,0xAC,0x0A,0x1D,0xAB,0x8A,0xD1,0xB4,0x8F,0xAC,0x9F,0x3E,0xFC,0x08,
+    0xD1,0xB4,0x90,0xAC,0xFA,0xBC,0xFA,0x2A,0xD1,0xB4,0x8F,0xAC,0x88,0xF8,0x7B,0x5F,
+    0x84,0x59,0x43,0x51,0x3F,0x2E,0x6A,0x2B,0x84,0x59,0x22,0x51,0xA8,0xA2,0xE9,0xBF,
+    0x84,0x59,0x23,0x51,0xFF,0xFA,0xFB,0xE2,0x64,0x51,0x23,0x51,0xAF,0xF6,0xAB,0xA9,
+    0x63,0x59,0x22,0x51,0x8A,0x82,0x8D,0x02,0x84,0x59,0x43,0x59,0xEB,0xFF,0xBD,0xB5,
+    0xA4,0x61,0x64,0x59,0xDF,0xFE,0x3B,0x1A,0x84,0x61,0x43,0x59,0xEA,0xFF,0x4E,0x7E,
+    0xA4,0x61,0x23,0x51,0xE8,0xFA,0x7F,0xF5,0x63,0x61,0x43,0x51,0xA9,0xCF,0xED,0xAB,
+    0x63,0x59,0x23,0x51,0xFF,0xAA,0xA3,0xEA,0x64,0x59,0x43,0x59,0xF5,0xE2,0x4B,0x65,
+    0x44,0x59,0x23,0x51,0x2E,0x2C,0x0E,0x4D,0x43,0x59,0x23,0x51,0xD8,0x9E,0x7C,0xB8,
+    0x43,0x59,0x03,0x51,0xFF,0x56,0xFC,0xBE,0x43,0x51,0x03,0x49,0x78,0x69,0xAA,0xB0,
+    0x23,0x51,0x03,0x49,0x77,0x75,0x62,0x5C,0x03,0x49,0xE2,0x48,0xB2,0xDD,0x57,0x0C,
+    0x23,0x51,0xE2,0x48,0xA2,0x22,0xE8,0x6A,0x24,0x51,0xE2,0x48,0xB6,0xEE,0xF5,0xAD,
+    0x63,0x59,0xE2,0x40,0xFF,0xBF,0xAD,0x2D,0x4A,0x93,0x83,0x59,0x25,0x2D,0x29,0x0B,
+    0xAB,0xA3,0x4A,0x9B,0xCF,0xFF,0x2A,0x02,0xEC,0xAB,0x6B,0x9B,0xA5,0x8F,0x2A,0x0B,
+    0xEC,0xAB,0xAB,0xA3,0x3D,0xE6,0x6C,0xF8,0xEC,0xAB,0x8A,0x9B,0x08,0xC8,0xFB,0x57,
+    0xCB,0xA3,0x8A,0x9B,0xFB,0xCE,0xEB,0x55,0xAB,0xA3,0x6A,0x9B,0x57,0xE8,0xEE,0xA9,
+    0x8B,0x9B,0x29,0x93,0x7B,0xFE,0xBA,0xA8,0x8B,0x9B,0x49,0x93,0x55,0xD5,0xEE,0x02,
+    0x8A,0x9B,0x4A,0x93,0x7D,0xDF,0x6B,0xF2,0x6A,0x9B,0x2A,0x93,0xAE,0xAC,0xBF,0xFE,
+    0x6A,0x9B,0x87,0x82,0x68,0x62,0xEA,0xFA,0xA8,0x7A,0x46,0x72,0xFC,0xDE,0x7F,0x7E,
+    0x67,0x72,0x06,0x72,0x8A,0x22,0xEA,0x8A,0x67,0x72,0x26,0x72,0xEA,0xE8,0xFE,0xF9,
+    0x47,0x72,0x05,0x6A,0xBB,0xEE,0x7A,0x20,0x47,0x72,0x06,0x6A,0xCA,0xA2,0x7A,0x78,
+    0x47,0x72,0x06,0x6A,0x69,0xFA,0x7F,0x57,0x26,0x6A,0x06,0x6A,0x6F,0xD7,0x37,0x25,
+    0x06,0x62,0x43,0x51,0x78,0xE0,0x80,0x80,0xA5,0x59,0x03,0x41,0x5F,0x7F,0xFA,0xE8,
+    0x23,0x41,0xE2,0x38,0x70,0x62,0xB8,0xEC,0x03,0x41,0xA1,0x30,0xFF,0x7E,0xFA,0xC8,
+    0x03,0x41,0xC2,0x38,0xAD,0x83,0xA1,0x3F,0x44,0x49,0xE2,0x38,0xAD,0xAD,0x8B,0xAB,
+    0x44,0x49,0xE2,0x38,0x5E,0x7A,0xE8,0xA8,0xE3,0x40,0x03,0x39,0x7E,0xD7,0xFD,0x3F,
+    0x03,0x41,0xC2,0x38,0xA8,0xF8,0xFA,0xFA,0x03,0x41,0xC2,0x38,0x82,0xAE,0xF7,0xF7,
+    0x24,0x41,0xE3,0x38,0xBF,0x3D,0xBD,0xBD,0x44,0x41,0x03,0x41,0xF7,0xFF,0xAF,0xAA,
+    0x44,0x49,0x03,0x41,0xE5,0xBB,0xEA,0x82,0x24,0x49,0x03,0x41,0xBF,0x7A,0x23,0x0B,
+    0x44,0x49,0x03,0x41,0xBB,0xCF,0xBB,0xBF,0xC6,0x61,0x44,0x49,0xFD,0xA5,0x2D,0xAD,
+    0xC6,0x61,0x65,0x51,0xFD,0xFF,0xFA,0xCA,0x86,0x51,0x04,0x41,0xEE,0x7C,0xFE,0xEA,
+    0x24,0x41,0xC3,0x38,0xE0,0xCA,0xEA,0xE6,0x03,0x39,0xC3,0x38,0x5D,0xFB,0x72,0xFE,
+    0xE3,0x38,0xA2,0x30,0x5D,0x5E,0xDE,0x5E,0x45,0x41,0xC3,0x30,0x81,0xFB,0xFD,0xF5,
+    0x03,0x39,0xC3,0x30,0xFE,0xEF,0xFE,0xE0,0x24,0x41,0xC3,0x30,0xBF,0xAB,0xF9,0xCD,
+    0x44,0x41,0xE3,0x40,0xFF,0xAA,0x89,0xBF,0x65,0x49,0x03,0x41,0x3D,0xBF,0x3E,0xAB,
+    0x85,0x51,0x44,0x49,0xAA,0x5A,0xFB,0xEF,0x85,0x51,0x24,0x49,0x2B,0xAB,0xFE,0x7A,
+    0x85,0x59,0x04,0x49,0x88,0xFA,0xFA,0x7D,0x44,0x49,0xE3,0x38,0xC0,0xF8,0xEF,0xFE,
+    0x04,0x41,0xC3,0x38,0xA2,0x0B,0x2F,0x3F,0x04,0x41,0xC3,0x38,0x68,0xEA,0x70,0xB0,
+    0x24,0x41,0xC3,0x38,0xD7,0xFD,0xAB,0x29,0x04,0x41,0xC3,0x38,0xA8,0xEF,0xAF,0xEF,
+    0x44,0x41,0xC2,0x30,0x2F,0x8B,0x2F,0xB7,0x65,0x49,0x04,0x41,0xEB,0xFB,0xEE,0xFE,
+    0x44,0x41,0x23,0x41,0x55,0xD5,0x9D,0x57,0x64,0x49,0xE3,0x38,0xAA,0x2B,0xFA,0xD7,
+    0x44,0x41,0x03,0x39,0xEA,0x7E,0xFA,0xE8,0x23,0x41,0xC2,0x30,0xA8,0xFE,0xFA,0x5A,
+    0x03,0x39,0xC2,0x30,0x80,0xA0,0xAB,0x8D,0xC2,0x38,0xE2,0x30,0x77,0xF7,0xF5,0xDD,
+    0xE3,0x38,0xC2,0x30,0xA2,0xA3,0x3E,0x2A,0x03,0x39,0xC2,0x30,0xE2,0xE8,0x8A,0xAF,
+    0x03,0x39,0xC2,0x30,0xFF,0xFB,0xAA,0xA8,0x24,0x39,0xC3,0x30,0xFD,0xFB,0xBF,0xAB,
+    0x03,0x39,0xC2,0x30,0x2F,0x8A,0x00,0x80,0x23,0x41,0xE3,0x38,0x0A,0x3B,0x3B,0xAD,
+    0x85,0x51,0x23,0x41,0xBD,0xAB,0x37,0xBD,0xC5,0x51,0x64,0x49,0x0B,0xAF,0xFA,0xFB,
+    0xC6,0x59,0x85,0x51,0x7A,0x6E,0xFA,0x55,0x84,0x51,0x64,0x51,0xDF,0xF2,0xEB,0x79,
+    0x85,0x51,0x23,0x49,0x00,0x02,0xBE,0x7E,0xE6,0x61,0x43,0x49,0xAB,0x0A,0x0B,0xAD,
+    0x06,0x62,0xC6,0x61,0x75,0x5A,0xF2,0xA1,0x06,0x6A,0xA5,0x59,0x7D,0xFB,0xBE,0x3F,
+    0x27,0x6A,0xA4,0x59,0xD5,0xDF,0x78,0xF2,0x06,0x6A,0xC5,0x61,0x5A,0x6E,0x21,0x9F,
+    0x47,0x72,0x84,0x59,0x0F,0x27,0xB7,0xBF,0xA8,0x82,0x06,0x6A,0x5D,0xFF,0xA9,0x81,
+    0x67,0x7A,0x06,0x6A,0x0D,0xF5,0xDF,0x7E,0xC9,0x82,0x46,0x72,0x0F,0x2B,0x29,0xA5,
+    0x09,0x8B,0xC8,0x82,0xF5,0xD5,0xBA,0xA9,0x6B,0x93,0xE9,0x82,0x35,0x3D,0x27,0x2D,
+    0x15,0xE6,0xED,0xA3,0x09,0x0D,0x2D,0x2D,0x75,0xEE,0x35,0xEE,0x8A,0x8B,0xED,0xF5,
+    0x75,0xEE,0x35,0xE6,0x8A,0xA8,0xEE,0xFD,0x55,0xEE,0x15,0xE6,0x88,0x88,0xA8,0x42,
+    0x55,0xEE,0x14,0xE6,0x8A,0xEE,0xFF,0x55,0x35,0xE6,0xF4,0xDD,0xA0,0xE8,0xFA,0x7B,
+    0x14,0xDE,0xB4,0xD5,0xC0,0x80,0x68,0x7E,0x93,0xD5,0xF1,0xBC,0xDC,0xA8,0xAC,0xAE,
+    0xB4,0xD5,0x52,0xC5,0xA9,0x8B,0xAA,0xA0,0x93,0xCD,0x32,0xC5,0xBA,0xE8,0x68,0xEA,
+    0x72,0xCD,0x32,0xC5,0x00,0x83,0x2D,0xEF,0x73,0xCD,0x93,0xC5,0x82,0xAA,0x7C,0xAA,
+    0x73,0xC5,0x32,0xC5,0xF8,0xEA,0xEA,0xAA,0x52,0xC5,0x11,0xBD,0xBA,0xFE,0xF7,0x67,
+    0x32,0xC5,0xF1,0xBC,0xAC,0xAB,0x7F,0x5E,0x32,0xC5,0xED,0x9B,0xE8,0xE8,0x6A,0x7A,
+    0xEE,0x9B,0x89,0x72,0x54,0x9E,0xBE,0x2A,0x4F,0xA4,0x6C,0x8B,0x2D,0x2B,0x0B,0x02,
+    0xD1,0xB4,0x6F,0xAC,0x25,0xFD,0xB5,0xF5,0xD0,0xB4,0x90,0xAC,0xF6,0x3B,0xB5,0xB5,
+    0xD1,0xB4,0x8F,0xAC,0xAA,0xEF,0x2B,0xB0,0xD0,0xB4,0x6F,0xAC,0xA0,0xFE,0x7E,0x57,
+    0xB0,0xB4,0x4F,0xA4,0x00,0xAA,0xA6,0xB7,0xB0,0xB4,0x4F,0xA4,0xB0,0xBB,0xAF,0xB5,
+    0x63,0x59,0x22,0x49,0x83,0xFA,0x7A,0x5B,0x84,0x59,0x22,0x51,0xBB,0xED,0x3B,0x3F,
+    0x63,0x59,0x23,0x51,0x00,0x83,0x3C,0x2F,0x84,0x59,0x22,0x49,0xF6,0xA2,0xAC,0xBA,
+    0x84,0x61,0x63,0x59,0x55,0x79,0x4B,0x45,0x84,0x61,0x43,0x59,0x2D,0x2B,0x2B,0x0E,
+    0x84,0x61,0x63,0x59,0x15,0xB6,0xFE,0x7A,0x84,0x59,0x43,0x59,0xEE,0xBE,0xFE,0xFE,
+    0x84,0x61,0x23,0x51,0xFF,0xAA,0xBA,0x68,0x63,0x59,0x02,0x51,0xA2,0x0A,0xB8,0x7F,
+    0x63,0x59,0x23,0x51,0x2A,0x02,0x2B,0x7F,0x84,0x61,0x23,0x51,0xFA,0xE8,0xDB,0xF7,
+    0x64,0x59,0x23,0x51,0xFA,0xFE,0x62,0x6F,0x44,0x51,0x03,0x51,0x8A,0x02,0x0B,0x6B,
+    0x44,0x51,0x03,0x49,0x7E,0x6A,0x73,0x68,0x43,0x51,0xE1,0x48,0xA0,0xEA,0xFB,0xEA,
+    0x23,0x51,0xE2,0x48,0xAA,0xA5,0xD5,0xFB,0x23,0x51,0xE3,0x48,0xEF,0xE8,0xAA,0xAA,
+    0x23,0x51,0xC2,0x48,0xA2,0xAA,0xBA,0x78,0x23,0x51,0xC2,0x48,0xAA,0xEF,0xB7,0x25,
+    0xE6,0x69,0x03,0x51,0xF5,0x35,0x3D,0x2F,0x6A,0x9B,0x25,0x72,0x29,0x01,0x03,0x02,
+    0xCC,0xA3,0x8B,0x9B,0xEF,0xEF,0xED,0x8B,0xAC,0xA3,0x8B,0x9B,0x0A,0xF9,0x79,0x62,
+    0xAB,0xA3,0x29,0x93,0x80,0x7A,0xFE,0xFE,0x69,0x9B,0x28,0x93,0x8A,0xAD,0xAA,0x80,
+    0x8A,0x9B,0x49,0x93,0x8B,0xAB,0x2F,0xBF,0x8A,0x9B,0x49,0x93,0x00,0x82,0xFC,0x7A,
+    0x8B,0x9B,0x29,0x93,0x80,0x32,0xEB,0x7F,0x8B,0x9B,0x09,0x8B,0x88,0x28,0xFB,0x55,
+    0x8B,0xA3,0x09,0x93,0xA2,0xE0,0xEF,0xED,0x4A,0x93,0xE9,0x8A,0x80,0xA8,0xF8,0xFF,
+    0x09,0x8B,0x67,0x7A,0xE0,0xF8,0xE8,0x78,0x87,0x7A,0x26,0x72,0xDC,0xFA,0xFE,0xDE,
+    0x67,0x7A,0x26,0x6A,0x6F,0x5B,0x8A,0xFF,0x46,0x72,0x05,0x6A,0xBB,0xDE,0x80,0x02,
+    0x46,0x72,0x06,0x6A,0x3A,0xFA,0x8B,0xEB,0x47,0x72,0x06,0x6A,0x5C,0xDE,0x7B,0xB5,
+    0x26,0x6A,0xE5,0x69,0xAD,0x36,0xBA,0xA8,0x47,0x72,0x06,0x6A,0xC1,0xAB,0x29,0x0F,
+    0x68,0x72,0x06,0x6A,0x7A,0x7A,0xB0,0x22,0x67,0x72,0x43,0x49,0x7E,0xFA,0xF8,0xE0,
+    0x64,0x49,0xE3,0x40,0x77,0x5E,0xFE,0xF8,0x03,0x41,0xC2,0x38,0xA8,0x0A,0x80,0x78,
+    0x03,0x41,0xC2,0x38,0x02,0xA2,0xEB,0xF9,0x24,0x41,0xC2,0x38,0x0A,0x2E,0xBB,0xA9,
+    0x44,0x49,0x03,0x39,0x02,0xC0,0xEF,0xA5,0x23,0x41,0xE2,0x38,0x5F,0xDA,0xDE,0xC2,
+    0x03,0x41,0xC2,0x38,0xF2,0xCA,0xE8,0xFA,0x03,0x39,0xC2,0x38,0xB7,0xEF,0x3F,0xDF,
+    0x24,0x41,0xC2,0x38,0xAF,0x2F,0x2F,0x9F,0x64,0x49,0x03,0x41,0xBD,0xAF,0x2D,0x0D,
+    0x64,0x49,0x03,0x41,0xFA,0xF8,0xE8,0x58,0x24,0x49,0x03,0x41,0x8A,0x22,0x0A,0x2F,
+    0x44,0x49,0x24,0x49,0x37,0x1A,0xDC,0x94,0xA6,0x59,0x44,0x49,0x2F,0x0F,0x3F,0xBD,
+    0xC6,0x59,0x65,0x51,0xC2,0xE2,0x60,0xFB,0x85,0x51,0x23,0x41,0x6B,0x6A,0xEE,0xE0,
+    0x24,0x41,0xC2,0x38,0xFF,0xD7,0x76,0x78,0x24,0x41,0xC3,0x38,0x7F,0xFF,0x73,0xF3,
+    0xE3,0x30,0xA2,0x30,0x77,0xFD,0xBE,0x2E,0x03,0x39,0xC3,0x30,0xB5,0xD5,0xB7,0x2F,
+    0x45,0x41,0x04,0x39,0x55,0x7A,0xE3,0x7B,0x03,0x39,0xE3,0x38,0xC9,0xBF,0xDF,0x1F,
+    0x24,0x41,0xC2,0x38,0xBA,0x9F,0x2E,0x22,0x44,0x49,0x04,0x41,0x0A,0x2B,0x29,0x0D,
+    0x65,0x51,0x44,0x49,0xF5,0xFD,0xBB,0x75,0x44,0x49,0x03,0x41,0x88,0xEA,0xE8,0xE0,
+    0x24,0x41,0xE3,0x40,0x0A,0x0F,0x27,0x8A,0x24,0x41,0xE3,0x38,0xE8,0x70,0x58,0x6A,
+    0x03,0x41,0xE3,0x38,0xD7,0xD7,0x7F,0xFB,0x24,0x41,0xE3,0x38,0xBF,0xBF,0x57,0x5B,
+    0x24,0x41,0x03,0x39,0x27,0x1E,0xF6,0x7F,0x24,0x41,0xE3,0x38,0x78,0x78,0x6B,0xAF,
+    0x24,0x41,0xE3,0x38,0xBD,0xFD,0x3D,0x37,0x65,0x49,0x03,0x41,0xFA,0xEA,0x62,0xE9,
+    0x44,0x49,0xE3,0x38,0xAF,0x6A,0x0B,0x0A,0x44,0x49,0xC2,0x30,0x7E,0xFA,0xE8,0xE0,
+    0x23,0x41,0xC2,0x30,0x8A,0xDA,0x5E,0x52,0xE2,0x38,0xC2,0x30,0x7C,0xF6,0xC5,0x2B,
+    0x03,0x39,0xC2,0x30,0x2D,0xED,0xAB,0x2A,0x23,0x39,0xC2,0x30,0xF7,0x97,0x8F,0xAE,
+    0x24,0x39,0xC2,0x30,0xFD,0xBF,0xEB,0x2A,0x23,0x39,0xE3,0x30,0xFD,0xFE,0xD4,0x7E,
+    0x24,0x39,0xC3,0x30,0xFE,0xFF,0xFE,0xA3,0x23,0x39,0xE3,0x38,0x2B,0x89,0xB7,0xF5,
+    0x44,0x41,0xE3,0x30,0x7F,0xEF,0xBA,0x8B,0x23,0x41,0xE2,0x38,0xED,0x7D,0xFF,0x8B,
+    0x44,0x41,0xE3,0x38,0x09,0xF5,0xDB,0xD5,0x85,0x51,0x03,0x41,0x82,0xE3,0xFF,0xFD,
+    0x85,0x51,0x02,0x39,0x28,0x8A,0xB5,0x57,0x84,0x51,0x23,0x41,0x20,0xBA,0xEA,0x7F,
+    0x84,0x51,0x03,0x41,0x68,0x6A,0xFE,0xAF,0xA5,0x59,0x03,0x41,0x29,0x2D,0xAF,0x2F,
+    0x06,0x62,0xA5,0x59,0x8B,0xBF,0xAD,0x2B,0x26,0x6A,0xC5,0x61,0xDC,0xAB,0x8B,0xB7,
+    0x27,0x6A,0xC6,0x61,0xEB,0xBF,0x37,0x56,0x67,0x7A,0xE5,0x69,0x5F,0xEA,0xC8,0x03,
+    0x26,0x72,0xC6,0x61,0xB7,0xBF,0xFF,0xFC,0x88,0x7A,0x06,0x6A,0x0D,0xAD,0xF7,0xD5,
+    0x68,0x7A,0x06,0x6A,0x78,0x7A,0x77,0x6B,0xA8,0x7A,0xC4,0x61,0x2B,0xAB,0xBF,0xF5,
+    0x09,0x8B,0x67,0x72,0x0A,0x09,0xAD,0xBD,0x29,0x8B,0xE8,0x82,0x0D,0xFD,0xFF,0x5D,
+    0xD4,0xDD,0x6A,0x93,0x2D,0x2D,0x35,0xB5,0x55,0xEE,0xD3,0xDD,0x0A,0x2B,0xA9,0x2D,
+    0x55,0xEE,0x35,0xE6,0xBF,0x33,0xAF,0xFF,0x55,0xEE,0x15,0xE6,0xEA,0xBA,0xFE,0xFF,
+    0x35,0xE6,0x14,0xE6,0xF7,0x7E,0xFA,0x56,0x14,0xE6,0xB3,0xD5,0xA8,0xE8,0xFE,0x5A,
+    0xD4,0xDD,0x32,0xC5,0xA0,0xE8,0xFA,0x7A,0x93,0xCD,0x11,0xBD,0x2F,0x2E,0x09,0x2D,
+    0xB4,0xD5,0x93,0xCD,0x6A,0x4B,0x7F,0x7B,0x93,0xCD,0x73,0xCD,0x72,0x6A,0xEE,0x68,
+    0x52,0xC5,0x32,0xBD,0x38,0xBA,0x78,0x38,0x72,0xCD,0x32,0xC5,0x08,0x8A,0xEA,0xDA,
+    0x73,0xCD,0x32,0xC5,0x8A,0xEF,0x5D,0x77,0x32,0xC5,0xF1,0xBC,0xFE,0xBC,0xEC,0x68,
+    0x12,0xBD,0xB0,0xB4,0xE0,0xFC,0x5F,0x76,0xB0,0xB4,0x0E,0x9C,0x60,0xF8,0xE8,0x78,
+    0x2E,0xA4,0xAC,0x93,0x17,0x3F,0x3E,0xFA,0x6F,0xAC,0x0F,0x9C,0xAD,0x2A,0x03,0xA9,
+    0xB0,0xB4,0x6F,0xAC,0xD5,0x95,0xB9,0xBD,0xD1,0xB4,0x6F,0xAC,0x27,0x3B,0xEE,0xFE,
+    0xB1,0xB4,0x4F,0xA4,0xF8,0xF8,0xFF,0x5F,0x6F,0xA4,0x2F,0xA4,0xB2,0x2A,0xEB,0xAB,
+    0x8F,0xAC,0x4F,0xA4,0x2F,0xAF,0xEA,0xFB,0xB0,0xAC,0x4F,0xA4,0xF5,0xB7,0x09,0x0F,
+    0x63,0x59,0x02,0x51,0x7E,0xEE,0x2D,0xAF,0x63,0x59,0x22,0x51,0x3D,0x2F,0x02,0xE0,
+    0x84,0x59,0x23,0x51,0x87,0xCA,0xA8,0xE3,0x84,0x59,0x22,0x51,0x7E,0xA3,0x80,0x2B,
+    0xA5,0x61,0x63,0x59,0x25,0xD5,0xF5,0xEB,0xC5,0x61,0x43,0x59,0xAF,0x2F,0xE7,0xFD,
+    0x84,0x61,0x43,0x59,0xE0,0xF8,0xEE,0x7E,0x84,0x61,0x23,0x59,0xFC,0xDB,0xEB,0xDA,
+    0x64,0x59,0x23,0x51,0xA2,0xFB,0x7B,0x5A,0x63,0x59,0x23,0x51,0xFF,0xD8,0xBD,0xA9,
+    0x63,0x59,0x23,0x51,0x7F,0xAA,0x8A,0x6E,0x64,0x51,0x02,0x51,0xAE,0xB4,0xBA,0xAA,
+    0x43,0x59,0x03,0x51,0xE8,0xA8,0xFF,0xFA,0x43,0x51,0x03,0x49,0xAF,0xBE,0xAF,0xBE,
+    0x64,0x59,0x02,0x49,0xF8,0xD2,0x5B,0x7F,0x23,0x51,0x03,0x49,0x88,0x38,0x0B,0x03,
+    0x23,0x51,0x03,0x49,0x7F,0xAC,0xEE,0x63,0x23,0x51,0xE2,0x40,0xAA,0xEA,0xB6,0x0A,
+    0x23,0x51,0xC2,0x48,0x72,0xBA,0xEA,0x00,0x64,0x59,0x03,0x51,0xFD,0x8B,0xAA,0xAA,
+    0xC9,0x8A,0x64,0x59,0x95,0xB5,0x35,0x35,0xAC,0xA3,0x09,0x8B,0x2D,0x2B,0x2B,0xAA,
+    0xCC,0xA3,0x8B,0x9B,0xEB,0xEB,0xAA,0x0F,0xEC,0xAB,0xAB,0xA3,0x75,0x75,0xFB,0x07,
+    0xEC,0xAB,0x4A,0x93,0x5F,0xFE,0xAC,0x88,0xAB,0xA3,0x49,0x93,0xFF,0xDF,0xAA,0xE0,
+    0x6A,0x9B,0x49,0x93,0x8B,0x28,0x2A,0xCC,0x6A,0x9B,0x08,0x93,0xA0,0x72,0xF8,0xB2,
+    0x49,0x93,0xE8,0x8A,0x7E,0x7F,0xD6,0x88,0x29,0x93,0xE8,0x8A,0xFA,0xDE,0xFE,0xEB,
+    0xE9,0x92,0x09,0x8B,0x55,0xFF,0x5F,0x95,0x29,0x93,0xC8,0x82,0x68,0x7A,0x7A,0xFF,
+    0xE9,0x8A,0x87,0x7A,0x7A,0xE8,0x82,0xA0,0xA8,0x82,0x46,0x72,0x77,0x7F,0x7A,0x7C,
+    0x67,0x72,0x26,0x72,0x7D,0x6F,0x3B,0x2A,0x66,0x72,0x05,0x6A,0xEB,0x6A,0xE8,0xB8,
+    0x67,0x72,0xE5,0x69,0x6E,0xEE,0xFE,0x2E,0x47,0x72,0xE5,0x69,0xAF,0x27,0x37,0x9E,
+    0x47,0x72,0x06,0x6A,0x77,0x56,0xFC,0xAF,0x67,0x7A,0x06,0x6A,0xA5,0xBF,0x8E,0xAA,
+    0x87,0x7A,0x47,0x72,0xF5,0xB7,0xFE,0x2F,0x87,0x7A,0xE6,0x61,0x70,0x82,0x00,0x00,
+    0x26,0x6A,0x03,0x41,0x5E,0x7C,0x78,0xF8,0x03,0x41,0xA2,0x38,0x5C,0xE0,0x80,0xA0,
+    0xE2,0x38,0xA2,0x30,0x82,0x2A,0x1E,0xAE,0x03,0x41,0xE3,0x38,0xE9,0xFD,0xC2,0xEB,
+    0x24,0x41,0xE2,0x38,0xF5,0xFA,0xE2,0xAB,0x24,0x41,0xE3,0x38,0xEF,0x5F,0x7B,0x5D,
+    0xE3,0x38,0xC2,0x38,0x80,0xA0,0xC8,0x03,0x23,0x41,0xC2,0x38,0x57,0xDF,0xFF,0xBF,
+    0x03,0x41,0xE3,0x38,0x05,0x01,0x69,0x2B,0x44,0x49,0x03,0x39,0xAA,0x6A,0xAD,0xB5,
+    0x64,0x49,0x03,0x41,0xF8,0x7E,0xDA,0x7A,0x24,0x49,0xE3,0x40,0xB6,0xAE,0xB6,0xFF,
+    0x65,0x51,0x03,0x41,0x3D,0xB5,0xD5,0x55,0x85,0x51,0xC3,0x40,0x0A,0xAA,0xAA,0xFD,
+    0xA6,0x59,0x24,0x49,0xA2,0x22,0xBB,0xFD,0x85,0x51,0x44,0x49,0x42,0xE8,0xFA,0x2F,
+    0x65,0x49,0xC2,0x30,0x7E,0x7A,0x78,0xE0,0x03,0x41,0xC3,0x30,0xA1,0xE3,0xFA,0xFA,
+    0xE3,0x38,0xC3,0x30,0xDC,0x5A,0xFC,0xFF,0x04,0x39,0xC3,0x30,0x8D,0xBD,0xD5,0x7D,
+    0x24,0x39,0xA2,0x30,0x22,0x3E,0xFF,0xD5,0x03,0x39,0xC3,0x30,0x00,0x00,0x0A,0x3D,
+    0x24,0x41,0x03,0x39,0x5B,0xBB,0x83,0xAD,0x44,0x49,0x03,0x41,0x0D,0x0B,0x3D,0x09,
+    0x64,0x49,0x24,0x49,0xAE,0xAF,0xAF,0xBB,0x44,0x49,0x03,0x41,0x80,0xA0,0x72,0xFE,
+    0x24,0x41,0xC2,0x38,0x00,0xAA,0xBA,0x78,0x03,0x41,0xC3,0x38,0x82,0x2A,0xA0,0x3F,
+    0x03,0x41,0xE3,0x38,0xBA,0x9E,0x5A,0xF8,0x24,0x41,0x03,0x39,0x57,0x3A,0x0B,0xEF,
+    0x65,0x41,0xE3,0x30,0xFF,0xDF,0x7C,0x7F,0x44,0x39,0xE3,0x38,0xBF,0xBF,0xF7,0x75,
+    0x23,0x39,0xE3,0x38,0x38,0xFA,0xBD,0x2F,0x44,0x41,0x03,0x39,0x8B,0xA9,0xEA,0xE2,
+    0x64,0x49,0x02,0x39,0xA0,0xEB,0xFF,0x57,0x44,0x41,0xC2,0x30,0xF8,0x6A,0xF2,0xFF,
+    0x02,0x39,0xC2,0x30,0x57,0xDF,0xDE,0x78,0x03,0x39,0xC2,0x30,0xBF,0xA6,0x8B,0xE5,
+    0x23,0x39,0xE2,0x38,0xFD,0xAF,0x0B,0xA9,0x23,0x39,0xE2,0x30,0xFF,0xFA,0xE2,0xE3,
+    0x24,0x39,0x03,0x39,0x2F,0xE5,0x75,0xB5,0x24,0x39,0xE3,0x38,0x7C,0xFC,0xA8,0x08,
+    0x03,0x39,0xC2,0x30,0xA2,0xE0,0xB8,0xB0,0x03,0x39,0xC2,0x30,0x2B,0xAF,0xDD,0x7A,
+    0x23,0x41,0xC2,0x30,0x0B,0xBF,0xDD,0x5D,0x64,0x41,0xC2,0x38,0xEA,0xAA,0xAB,0xAD,
+    0x23,0x41,0xE3,0x38,0xD7,0x5B,0xFC,0xA8,0x43,0x41,0xE3,0x38,0x8D,0xB5,0xF7,0xFF,
+    0x44,0x41,0xE3,0x38,0xFE,0xBA,0x3B,0xB9,0x23,0x41,0xE2,0x38,0x00,0xC7,0xF6,0xBC,
+    0x44,0x49,0xE2,0x38,0x02,0xFA,0x9E,0xEB,0xA5,0x51,0x23,0x49,0x27,0xBF,0xB7,0xBD,
+    0x47,0x6A,0x84,0x51,0x27,0x3F,0xBD,0xFD,0x88,0x7A,0xE6,0x61,0xF5,0xFA,0xAA,0x0B,
+    0x47,0x72,0xA5,0x61,0x55,0x57,0x5C,0xE2,0x47,0x72,0x85,0x59,0x0B,0x2D,0xB7,0xFE,
+    0x47,0x72,0xE5,0x69,0x78,0x60,0xDB,0x79,0x05,0x6A,0xC5,0x61,0x83,0xBF,0x8E,0x0B,
+    0x67,0x72,0xE5,0x61,0x8B,0x09,0x09,0xB5,0x47,0x72,0xE5,0x61,0xF6,0xBE,0xE0,0x00,
+    0xA7,0x7A,0x26,0x72,0x09,0x2B,0x09,0x2B,0x09,0x83,0xA8,0x7A,0xEB,0xA5,0x35,0x7D,
+    0x8F,0xB4,0xE8,0x82,0x2D,0x2D,0x2D,0x2D,0x35,0xE6,0x31,0xCD,0x0B,0x29,0xAD,0x2D,
+    0x35,0xE6,0x14,0xE6,0xA8,0xBF,0xF7,0x55,0x35,0xE6,0xF4,0xDD,0xA8,0xA8,0xFA,0xDF,
+    0x34,0xE6,0xF4,0xDD,0xEA,0x6A,0xFB,0x7B,0x14,0xDE,0x93,0xD5,0xF8,0xFE,0xFE,0x7A,
+    0x93,0xD5,0xF1,0xBC,0x68,0x58,0x58,0x5E,0x93,0xCD,0x11,0xBD,0x2D,0x29,0x29,0x2F,
+    0xB4,0xCD,0x73,0xCD,0xAA,0xEA,0xFE,0x7B,0x93,0xCD,0x32,0xC5,0x82,0xCA,0xFE,0x7F,
+    0x92,0xC5,0x32,0xC5,0x9E,0xFF,0xF7,0xF7,0x52,0xC5,0x32,0xC5,0x80,0xA0,0xC6,0xC8,
+    0x52,0xC5,0x11,0xBD,0xF0,0xEA,0xFA,0x72,0x12,0xC5,0xB0,0xAC,0xA0,0xFA,0xFE,0x60,
+    0xF1,0xBC,0x90,0xAC,0xF8,0xF8,0xF6,0xDF,0xB0,0xAC,0xED,0x9B,0xF8,0x78,0x5E,0x57,
+    0x2E,0xA4,0xCD,0x93,0x8E,0x3D,0xF7,0xF5,0x90,0xAC,0xEE,0x9B,0x2F,0x2F,0x2B,0x29,
+    0xB0,0xB4,0x4F,0xAC,0xAE,0xEF,0xE2,0xFA,0x90,0xAC,0x4F,0xA4,0x88,0xA0,0xFE,0x57,
+    0x6F,0xAC,0x0E,0x9C,0x72,0xE8,0xAA,0x02,0x90,0xAC,0x2E,0xA4,0x29,0x29,0x2F,0x0A,
+    0x90,0xAC,0x6F,0xA4,0x6A,0x00,0x28,0x08,0xB0,0xAC,0x4E,0xA4,0x2A,0xB0,0xF8,0x58,
+    0x84,0x59,0x22,0x51,0xFD,0x9F,0xF7,0xCA,0x84,0x59,0x43,0x51,0xFF,0x8E,0xF7,0x5A,
+    0x83,0x59,0x22,0x51,0xCA,0xAA,0x6A,0xEB,0x84,0x61,0x22,0x51,0x2F,0xAF,0x0D,0xA9,
+    0x84,0x61,0x43,0x51,0x4C,0xCB,0xAE,0xFE,0x63,0x59,0x23,0x51,0x00,0xD8,0x5E,0x69,
+    0x64,0x59,0x22,0x51,0xEA,0x8A,0xFE,0xFF,0x84,0x59,0x22,0x51,0xDA,0x28,0xAA,0xAF,
+    0x63,0x59,0x23,0x51,0xF8,0x68,0xF8,0x30,0x64,0x59,0x22,0x51,0x8B,0x09,0xD7,0x5E,
+    0x64,0x59,0x02,0x49,0xFF,0xFA,0xFC,0xFF,0x43,0x51,0x02,0x49,0xAA,0xAB,0x6F,0xCB,
+    0x43,0x51,0x03,0x49,0xFA,0xFA,0xAB,0x0F,0x64,0x59,0x03,0x49,0xBF,0xFB,0xA1,0xFB,
+    0x44,0x51,0x02,0x49,0xAE,0xAA,0x6A,0x40,0x44,0x51,0xE3,0x48,0xEF,0xAB,0x8F,0xAD,
+    0x23,0x51,0xE2,0x48,0xE2,0xE0,0xE0,0x68,0x24,0x59,0x02,0x49,0xA3,0x89,0x3B,0x39,
+    0x43,0x59,0x03,0x51,0x29,0x03,0xA2,0x20,0x64,0x59,0x44,0x59,0xDB,0x21,0xA5,0x95,
+    0x4A,0x93,0xA5,0x61,0xB5,0x25,0x25,0x2D,0xCB,0xA3,0x4B,0x9B,0x39,0xBD,0xBF,0xBF,
+    0xCC,0xA3,0x8B,0x9B,0x0B,0xBC,0xBB,0xAF,0xEC,0xAB,0xCC,0xA3,0x0C,0x02,0xAE,0xCB,
+    0xEC,0xAB,0xAB,0xA3,0xB8,0xAC,0xF8,0x7E,0xCC,0xA3,0x6A,0x9B,0xE8,0xAA,0x68,0xBA,
+    0xAB,0xA3,0x49,0x93,0xFE,0xFB,0xAE,0xB2,0x8A,0x9B,0x29,0x93,0xAF,0x88,0xBA,0x5E,
+    0x6A,0x9B,0x09,0x8B,0xC8,0x82,0xFC,0x74,0x49,0x93,0xE8,0x8A,0xAA,0xE8,0xEE,0xF7,
+    0x29,0x93,0xC8,0x82,0xC2,0xE2,0x7A,0x5E,0x09,0x8B,0xC8,0x82,0x7F,0x70,0x7F,0x5D,
+    0xE9,0x8A,0x87,0x7A,0xF0,0x78,0xF8,0xF2,0x87,0x7A,0x26,0x6A,0xDA,0xFA,0x78,0xB8,
+    0x67,0x72,0x46,0x72,0x7E,0xB6,0xB5,0xAB,0x67,0x72,0x26,0x72,0xFC,0xBA,0x25,0xAD,
+    0x46,0x72,0x05,0x6A,0x60,0xC2,0xE0,0x80,0x46,0x72,0xE5,0x69,0xDB,0x29,0x29,0x0A,
+    0x46,0x72,0x05,0x6A,0xDA,0xCA,0xAE,0xAA,0x47,0x72,0x06,0x6A,0x00,0x89,0x00,0x08,
+    0xA7,0x7A,0x46,0x72,0xED,0x25,0x2B,0x27,0xE8,0x82,0x87,0x7A,0x77,0xCF,0xFB,0xEB,
+    0xA8,0x7A,0x64,0x51,0x5E,0x6A,0xE0,0xA0,0x84,0x51,0xE3,0x40,0x5F,0x7E,0x5C,0x58,
+    0xE3,0x38,0xA2,0x38,0xC0,0xAA,0xE2,0xEA,0xE3,0x38,0xA1,0x30,0x0F,0x0F,0x2F,0x27,
+    0x24,0x39,0xC2,0x38,0x2B,0xA7,0x9F,0xFE,0x03,0x41,0xA2,0x30,0xE0,0xE0,0x68,0x7B,
+    0xE3,0x38,0xA2,0x30,0x25,0xAB,0xAB,0xB9,0x23,0x41,0xE3,0x38,0xBD,0xAF,0x0B,0xAB,
+    0x23,0x41,0xC2,0x38,0xAE,0xFA,0xF2,0x6A,0x45,0x41,0xE3,0x38,0x3F,0xF5,0xFF,0x57,
+    0x44,0x49,0xE3,0x38,0xE8,0xF8,0xEE,0xED,0x03,0x41,0xE3,0x38,0x88,0x7A,0x82,0xE0,
+    0x03,0x41,0xE3,0x40,0x80,0x03,0xF2,0x61,0x03,0x41,0xC3,0x38,0x8A,0xAA,0x6B,0xDB,
+    0x44,0x49,0xC3,0x38,0xAA,0xAB,0xAD,0xEF,0x86,0x51,0x03,0x41,0x2B,0xB9,0xB5,0xFD,
+    0x65,0x49,0x03,0x41,0xA0,0xF8,0xEA,0x7A,0x24,0x41,0xC3,0x30,0xFE,0x58,0x7A,0xFA,
+    0xE3,0x38,0x82,0x28,0x2E,0xBF,0xDA,0xE8,0xC2,0x30,0x81,0x28,0x80,0xEA,0xFE,0xFF,
+    0xC3,0x30,0x81,0x28,0x2F,0x2F,0x2F,0x2B,0x03,0x39,0xC3,0x30,0x35,0xBB,0xBF,0x9F,
+    0x24,0x41,0xE3,0x38,0x2F,0x27,0xAF,0xAB,0x65,0x49,0x03,0x41,0x2F,0xAF,0xAD,0x0F,
+    0x65,0x49,0x23,0x41,0x6A,0x6A,0xF7,0xAB,0x44,0x49,0x03,0x41,0x2F,0xAF,0xFF,0xDC,
+    0x45,0x49,0xE3,0x38,0x7E,0x6E,0xA0,0xAA,0x24,0x41,0xC3,0x38,0xBD,0xFF,0xFC,0xFC,
+    0x03,0x39,0xE3,0x38,0xBC,0xFC,0xFA,0xBF,0x24,0x39,0xC3,0x30,0xA2,0xC2,0x8A,0xE6,
+    0x03,0x39,0xC2,0x30,0xCA,0x4A,0x52,0x5A,0x03,0x39,0xA2,0x30,0xAA,0xA3,0x9F,0xFD,
+    0x23,0x39,0xE3,0x38,0x02,0x2C,0xBD,0x7D,0x44,0x41,0xE3,0x38,0x80,0xFA,0x5E,0x55,
+    0x24,0x41,0xC2,0x30,0x78,0xDA,0xFF,0xFF,0x03,0x39,0xC2,0x30,0x2B,0xAD,0xAB,0xFA,
+    0x03,0x39,0xC2,0x30,0x80,0x20,0xEF,0xF7,0x03,0x39,0xC2,0x30,0xF6,0xA2,0xEE,0xE8,
+    0x23,0x39,0xE3,0x30,0xAD,0xBD,0xF5,0xE9,0x23,0x39,0xE3,0x30,0x22,0xAA,0xBF,0x77,
+    0x23,0x39,0xE2,0x30,0x8A,0x63,0xAB,0xBE,0x44,0x41,0xE3,0x38,0x3B,0xBD,0x79,0xDF,
+    0x24,0x41,0xE3,0x38,0xDE,0xFA,0xFE,0x7C,0x24,0x39,0xE2,0x30,0x7B,0xFF,0xB0,0xAA,
+    0x03,0x39,0xC2,0x30,0x5D,0xD7,0xF7,0xFC,0x44,0x41,0xE2,0x30,0x3D,0xF5,0xDF,0xB5,
+    0x44,0x41,0x03,0x39,0xFA,0xBA,0xEB,0xFE,0x23,0x41,0xE3,0x38,0xFE,0xBE,0xAA,0xAE,
+    0x03,0x41,0xE2,0x38,0xA0,0x50,0x5F,0x55,0x24,0x41,0xC2,0x38,0xAF,0x7E,0x63,0x8A,
+    0x64,0x49,0x03,0x39,0xAD,0xAD,0xAB,0xAF,0x84,0x51,0x44,0x49,0x95,0x35,0x15,0xED,
+    0xC5,0x59,0x64,0x51,0x3F,0xFE,0xFE,0x5F,0x67,0x72,0xA5,0x59,0x0B,0x25,0xD5,0x55,
+    0x88,0x7A,0xE6,0x61,0xE8,0x08,0x03,0x25,0x87,0x7A,0xE5,0x61,0x57,0x5F,0xE0,0xC0,
+    0x06,0x62,0xA5,0x59,0xAA,0x26,0x1C,0x78,0x67,0x72,0xA5,0x59,0xBF,0xAF,0x2A,0x2D,
+    0x88,0x72,0xE5,0x61,0xDB,0xAA,0x2A,0x28,0xA8,0x7A,0x46,0x72,0xFD,0x75,0xAB,0x2B,
+    0xA8,0x82,0x67,0x72,0xF9,0x4D,0xBF,0x1A,0xA8,0x7A,0x47,0x72,0x02,0x2B,0x2A,0xA6,
+    0xB0,0xBC,0x88,0x7A,0x2D,0x3D,0x3D,0xBD,0xF4,0xDD,0xD1,0xC4,0x0B,0x0B,0x2B,0x2D,
+    0x14,0xE6,0xD4,0xDD,0xA0,0x78,0xD7,0x55,0x14,0xE6,0xB3,0xD5,0x8A,0xAA,0xEF,0x5F,
+    0x14,0xDE,0xB3,0xD5,0x82,0xEC,0x7E,0xDF,0xD4,0xD5,0x52,0xCD,0xE0,0xEA,0x6A,0x6A,
+    0x73,0xC5,0xD1,0xBC,0xDE,0x9C,0xBE,0x3E,0xD3,0xCD,0x73,0xCD,0xF5,0xF5,0xFF,0xED,
+    0x93,0xCD,0x52,0xC5,0x80,0xEA,0xE8,0x78,0x73,0xCD,0x11,0xBD,0xEA,0xE8,0x7E,0x7A,
+    0x52,0xC5,0xF1,0xBC,0x2B,0x3F,0xD5,0xDF,0x73,0xCD,0x11,0xBD,0xA2,0x0A,0x22,0x2D,
+    0x73,0xCD,0xD1,0xB4,0xE2,0xE2,0xE8,0x78,0x11,0xBD,0xB1,0xB4,0xE8,0xFA,0x7C,0xEB,
+    0xD1,0xB4,0x4E,0xA4,0xAA,0x6A,0x78,0x58,0x2E,0xA4,0x4C,0x83,0xA8,0xF8,0xFC,0x5E,
+    0xEE,0x9B,0x6C,0x8B,0x82,0x0A,0xA7,0x25,0x90,0xAC,0xEE,0x9B,0xAD,0x29,0x2F,0xAB,
+    0x90,0xAC,0x2F,0xA4,0xC0,0xF8,0xDE,0x5F,0x4F,0xA4,0xEE,0x9B,0x80,0xAA,0xE6,0xBE,
+    0x6F,0xAC,0x2E,0x9C,0x29,0x29,0x39,0x0E,0x90,0xAC,0x2E,0xA4,0x08,0x80,0x78,0xE8,
+    0x90,0xAC,0x0E,0x9C,0x8A,0xE6,0xFD,0xF7,0x6F,0xAC,0x4E,0xA4,0x78,0x77,0xEA,0x35,
+    0x63,0x59,0x02,0x49,0x00,0x28,0x0F,0x27,0x84,0x59,0x23,0x51,0xE8,0xFB,0x5A,0xFC,
+    0x63,0x59,0x23,0x51,0xAB,0x0B,0x03,0x2F,0x84,0x61,0x23,0x51,0xAC,0xDA,0xBA,0xBC,
+    0x63,0x59,0x01,0x51,0x2C,0xAE,0xAA,0xBF,0x43,0x59,0x23,0x51,0x8A,0x60,0x72,0xB8,
+    0x84,0x59,0x22,0x51,0xFF,0x7F,0x7B,0x5F,0x63,0x59,0x23,0x51,0xCA,0xFF,0xDD,0xB7,
+    0x63,0x59,0x02,0x49,0xA8,0x48,0xFA,0xFE,0x63,0x51,0x22,0x51,0x73,0x63,0xFB,0x5F,
+    0x43,0x51,0x02,0x49,0xAB,0x43,0xE8,0xFE,0x44,0x51,0x02,0x49,0xE5,0x2D,0x2D,0x22,
+    0x64,0x59,0x03,0x49,0x8A,0xEB,0x6F,0x7F,0x43,0x51,0xE2,0x48,0x8A,0xE8,0xEB,0xF7,
+    0x44,0x51,0xE3,0x48,0x7A,0xFF,0xAA,0x8B,0x44,0x51,0xE2,0x48,0xED,0x3F,0xBB,0xFB,
+    0x43,0x51,0x03,0x51,0xF7,0xDA,0xF2,0xB6,0xA5,0x61,0x23,0x51,0xF5,0x75,0xBD,0xDF,
+    0x64,0x59,0x23,0x51,0xBA,0xDA,0xF8,0xF0,0x64,0x59,0x23,0x51,0xA6,0x35,0x1D,0xBD,
+    0x2A,0x93,0x84,0x61,0x2D,0x09,0x0F,0x0B,0xAB,0xA3,0x4A,0x9B,0xAD,0x2D,0x2D,0x27,
+    0xCC,0xA3,0x8B,0xA3,0x2F,0x3D,0xDE,0x08,0x0D,0xAC,0xAB,0xA3,0xAA,0xEE,0xF7,0x3F,
+    0x2D,0xB4,0xCC,0xA3,0x55,0xBF,0xAD,0x0E,0x0D,0xAC,0xAB,0xA3,0x67,0xFA,0xE8,0xEE,
+    0xEC,0xAB,0x8B,0x9B,0xFF,0xDE,0x5A,0xF8,0x8B,0x9B,0x28,0x93,0x7E,0xFE,0xF8,0x6C,
+    0x29,0x93,0xE9,0x8A,0xF8,0xE0,0xEA,0xFA,0x09,0x8B,0xC8,0x8A,0x68,0xFB,0x7A,0x7A,
+    0x09,0x8B,0xA7,0x82,0xDA,0x3E,0xAE,0x9A,0x08,0x8B,0xA8,0x82,0xBD,0xAA,0x2A,0x2A,
+    0x09,0x8B,0x87,0x7A,0x62,0x70,0xF8,0xFA,0x87,0x7A,0x26,0x6A,0xBA,0xF6,0xF6,0xB8,
+    0x67,0x72,0x05,0x72,0xC8,0xA2,0xA8,0xA8,0x67,0x72,0x26,0x72,0xA9,0xFE,0xFE,0xFB,
+    0x46,0x72,0x26,0x6A,0x82,0xA8,0xFA,0x24,0x46,0x72,0x06,0x6A,0x0A,0x2A,0x1E,0xD8,
+    0x46,0x72,0x05,0x6A,0x20,0xA6,0x8B,0x8B,0x87,0x82,0x26,0x72,0xD7,0xBF,0xFF,0x0B,
+    0xA8,0x82,0x46,0x72,0x2D,0xA2,0x20,0x08,0xE8,0x82,0xA8,0x82,0x8D,0xF5,0xD5,0x57,
+    0xC8,0x82,0x26,0x6A,0x6A,0xE8,0x8A,0x88,0x67,0x7A,0xE3,0x40,0x7E,0x7E,0xE8,0xE8,
+    0x03,0x49,0xA2,0x30,0x7F,0xFF,0xEE,0xE0,0xE3,0x38,0xA2,0x30,0xBD,0xFF,0x6E,0x5A,
+    0xE3,0x38,0x81,0x30,0x80,0x2A,0xAB,0xED,0xE3,0x38,0x81,0x28,0xE8,0xAA,0xB2,0xBF,
+    0xE3,0x38,0xA2,0x30,0xAD,0x3E,0x3E,0xAF,0x24,0x41,0xC3,0x30,0x2B,0xBF,0xF6,0xFF,
+    0x24,0x39,0xC2,0x30,0xF8,0xBA,0xEA,0xEF,0x04,0x39,0xC2,0x38,0x7A,0xBE,0xFF,0xFF,
+    0x23,0x41,0xE3,0x38,0x2D,0x6D,0xD5,0x55,0x44,0x49,0xE3,0x38,0xB8,0xAB,0xEB,0xFD,
+    0x24,0x41,0x03,0x41,0x5D,0xF0,0xCA,0x82,0x65,0x49,0xC2,0x38,0xDF,0xF3,0xAA,0x22,
+    0x65,0x49,0xE3,0x40,0x77,0xFD,0x2A,0x8A,0x24,0x41,0xE3,0x38,0x2B,0x2B,0x2A,0x28,
+    0x65,0x49,0x03,0x41,0x6F,0xCE,0xEA,0xEB,0x24,0x41,0xC3,0x30,0xAA,0xFC,0x78,0xFA,
+    0x03,0x39,0xA2,0x30,0x7C,0xE0,0x82,0xAA,0xE3,0x30,0x82,0x28,0xDF,0x7F,0x9F,0x2E,
+    0xE3,0x30,0xA2,0x28,0x95,0xB5,0xA7,0xAC,0x03,0x39,0xC3,0x30,0xDF,0xFA,0x8B,0xAB,
+    0x23,0x41,0xE3,0x38,0x0F,0xBB,0xBD,0x0B,0xC6,0x51,0x23,0x41,0xB5,0xF5,0xBD,0x2B,
+    0xA6,0x51,0x44,0x49,0x7E,0xDF,0xFC,0xE8,0x64,0x49,0x03,0x41,0xF8,0xD7,0xFE,0x80,
+    0x44,0x49,0x03,0x41,0xEA,0xEB,0xEA,0xE6,0x03,0x41,0xC3,0x38,0xA8,0xBC,0x9E,0xFA,
+    0xE3,0x38,0x03,0x31,0x22,0x83,0x82,0x00,0x03,0x39,0xC2,0x30,0x8A,0xFE,0x7F,0x55,
+    0xE3,0x30,0xA2,0x30,0xB8,0xF6,0xFE,0x2A,0xE2,0x30,0xA1,0x30,0x8F,0x8A,0xA8,0x00,
+    0x03,0x39,0xC2,0x30,0x62,0x7F,0xD7,0xFF,0xE2,0x30,0xC2,0x30,0xF6,0xFF,0xBE,0xFE,
+    0x03,0x39,0xC2,0x30,0xFE,0xE2,0xE3,0xAD,0x03,0x39,0xC2,0x30,0xDF,0xFF,0xFA,0xA8,
+    0x03,0x39,0xC2,0x30,0xBF,0x2E,0xAA,0xF2,0x03,0x39,0xC2,0x30,0xDE,0xFC,0xF6,0x3F,
+    0x03,0x39,0xE3,0x30,0x2E,0x0F,0x6B,0xEA,0x24,0x39,0xC2,0x30,0xA2,0xBB,0x7F,0x5D,
+    0x24,0x39,0xC2,0x30,0x23,0x0B,0x2D,0xB7,0x23,0x39,0xE3,0x38,0xDE,0x55,0xFF,0xF2,
+    0x03,0x39,0xE3,0x30,0x60,0xC2,0xCA,0x7D,0x23,0x39,0xE3,0x38,0xBF,0xDD,0xDB,0x57,
+    0x24,0x39,0xC2,0x30,0x7C,0xD8,0xFA,0xBF,0x44,0x49,0xC2,0x30,0xAD,0xAF,0xB5,0xBF,
+    0x44,0x41,0x03,0x39,0x97,0xB5,0xD7,0xD5,0x44,0x41,0x03,0x39,0xD6,0xDF,0xB7,0x2D,
+    0x44,0x41,0xC2,0x30,0xD7,0xBE,0xE8,0xA8,0x43,0x41,0xE3,0x38,0xFF,0xFF,0xCF,0x9B,
+    0x65,0x49,0xE3,0x38,0x35,0xBF,0xF7,0xFF,0x85,0x51,0x03,0x39,0x8A,0x8B,0xBF,0xF5,
+    0x84,0x51,0x44,0x49,0xAA,0xB2,0xDE,0xB7,0xA5,0x59,0x64,0x51,0x22,0x29,0x35,0x95,
+    0x47,0x72,0xA5,0x59,0x09,0xAD,0xD5,0x55,0xA7,0x7A,0xA5,0x59,0x88,0x82,0xAB,0xA5,
+    0x67,0x72,0x85,0x59,0x78,0x78,0xC8,0xA8,0x06,0x6A,0x64,0x51,0x27,0x35,0xFF,0xDE,
+    0x67,0x72,0xA5,0x59,0x02,0x02,0x03,0x0D,0xA8,0x7A,0x46,0x6A,0x2F,0x2F,0xF7,0x5F,
+    0xC9,0x82,0x67,0x7A,0xBA,0xE8,0xA2,0x01,0xC9,0x82,0x67,0x72,0xFF,0xDE,0xFA,0xB8,
+    0x2E,0xAC,0xA8,0x7A,0x35,0x35,0xB5,0xBD,0xB4,0xDD,0x6F,0xB4,0x0B,0x2B,0xAD,0xAD,
+    0xD3,0xDD,0x72,0xCD,0xA8,0x6F,0xF5,0xF5,0xB3,0xD5,0x72,0xCD,0x2A,0x0E,0xB7,0x57,
+    0xD4,0xDD,0x93,0xD5,0xA3,0xEA,0xBD,0xF5,0xB3,0xD5,0x11,0xBD,0xE0,0xE0,0xF8,0x78,
+    0x73,0xCD,0xF1,0xBC,0x27,0x05,0x35,0x3D,0xB3,0xD5,0x53,0xC5,0x8B,0x8A,0xFF,0x5F,
+    0x93,0xCD,0x52,0xC5,0xE0,0xAA,0xEE,0xB5,0x73,0xCD,0xF1,0xB4,0xF2,0xEA,0xE8,0x88,
+    0x52,0xC5,0xB0,0xB4,0xFF,0xD7,0xF6,0xB8,0x52,0xC5,0xF1,0xBC,0x2F,0xA9,0xFF,0x57,
+    0x31,0xC5,0xB0,0xB4,0xE8,0xFC,0xD6,0x57,0xF1,0xBC,0x90,0xAC,0xC8,0xEF,0xFC,0xFB,
+    0xD0,0xB4,0xAD,0x93,0xE0,0x62,0x7C,0x7A,0xAD,0x93,0xEA,0x7A,0xF8,0xFE,0xF7,0xD7,
+    0x4F,0xA4,0x6C,0x8B,0xA5,0x2D,0x2F,0x0B,0x70,0xAC,0x2E,0xA4,0xAE,0x28,0x78,0x5B,
+    0x4F,0xA4,0x0E,0x9C,0xC8,0x92,0xD3,0x5D,0xB0,0xAC,0x0E,0x9C,0xF5,0xFE,0xEF,0x2B,
+    0x90,0xAC,0x2E,0xA4,0xAF,0x99,0xE2,0x20,0x6F,0xAC,0x2E,0x9C,0xC2,0xA2,0xDF,0x00,
+    0x90,0xAC,0x0D,0x9C,0xD7,0xD7,0xBF,0x00,0xD0,0xB4,0x4E,0xA4,0xDD,0xBD,0x0B,0x8A,
+    0x64,0x59,0x22,0x51,0xA5,0xEE,0xBA,0x2F,0x84,0x61,0x22,0x51,0xFF,0xE5,0xEB,0xA0,
+    0x83,0x61,0x23,0x51,0xB7,0xAF,0x3F,0xBF,0x84,0x61,0x22,0x51,0xBE,0xFC,0x5A,0x5A,
+    0x43,0x51,0x02,0x51,0xAA,0xE0,0xEA,0x21,0x63,0x51,0x22,0x51,0xF7,0x95,0xED,0xAF,
+    0x43,0x59,0x22,0x49,0xDA,0xDE,0x0A,0x8A,0x63,0x51,0x23,0x51,0xAF,0xFE,0xEF,0xAF,
+    0x43,0x51,0x02,0x49,0xF2,0xFE,0xE8,0xAE,0x22,0x51,0x02,0x49,0x2A,0x6E,0xDE,0xD7,
+    0x43,0x51,0xE2,0x48,0x2E,0xA9,0xAE,0xAB,0x43,0x51,0x02,0x49,0x00,0xB8,0xBE,0x6E,
+    0x43,0x51,0x03,0x49,0x78,0xEC,0x7E,0x97,0x64,0x59,0x03,0x49,0x55,0xD5,0x3F,0xFF,
+    0x43,0x51,0x02,0x49,0xAB,0xFC,0xEB,0x5A,0x23,0x51,0xE2,0x48,0x6E,0x8B,0x3A,0x2A,
+    0x44,0x59,0x03,0x51,0xB7,0x15,0xA7,0x2B,0x64,0x59,0x23,0x51,0xB3,0x8B,0xBB,0x2D,
+    0x64,0x59,0x23,0x51,0xFA,0x7E,0xEA,0xEE,0xC5,0x69,0x23,0x51,0xF5,0xB5,0xF5,0x37,
+    0x4A,0x9B,0x26,0x72,0x2D,0x0D,0x09,0x0B,0xAB,0xA3,0x6A,0x9B,0x0D,0xA9,0xEE,0xAB,
+    0xEC,0xAB,0x8B,0xA3,0xAB,0x2B,0xA5,0xBD,0x0D,0xAC,0xCC,0xA3,0xBF,0xAF,0x2D,0x2D,
+    0x2D,0xB4,0xEC,0xAB,0x89,0xA2,0x80,0x3F,0x2D,0xB4,0xCC,0xA3,0xFE,0xBA,0xAF,0xE2,
+    0xED,0xAB,0x6B,0x9B,0x68,0xEC,0xF8,0xE8,0x8B,0x9B,0x29,0x93,0x7A,0xEB,0xFB,0x88,
+    0x6B,0x9B,0x09,0x8B,0x5F,0x7F,0xFA,0xE0,0x29,0x93,0xC8,0x82,0x5E,0xDE,0x5E,0xB8,
+    0xE8,0x8A,0xC8,0x82,0x30,0x0A,0x0B,0xFA,0x08,0x8B,0xC8,0x82,0x8A,0x28,0x77,0xF7,
+    0xE8,0x82,0x87,0x7A,0x78,0x7A,0xFE,0x7C,0x87,0x7A,0x26,0x6A,0xBC,0xEC,0xD8,0x58,
+    0x67,0x72,0x26,0x72,0x9A,0xFA,0x6F,0xAF,0x66,0x72,0x05,0x6A,0xD8,0xF6,0xFF,0xBE,
+    0x46,0x72,0x26,0x6A,0x3E,0xA5,0xEE,0xA7,0x46,0x72,0x26,0x6A,0xFA,0xEB,0x8A,0x8A,
+    0x67,0x7A,0x26,0x72,0xF5,0x0D,0x02,0x3B,0xA8,0x82,0x46,0x7A,0xAF,0x36,0xAE,0x02,
+    0xC8,0x82,0x87,0x82,0x1F,0xAD,0xAB,0xAA,0xC8,0x82,0x68,0x7A,0xAA,0xBA,0xF6,0xB8,
+    0xC9,0x82,0x67,0x72,0x6A,0xF2,0xF8,0xFA,0x88,0x7A,0xE5,0x61,0x58,0x72,0xE0,0xE0,
+    0xC5,0x59,0xE2,0x38,0x5E,0x5A,0xFE,0xF8,0x03,0x41,0x81,0x30,0x7A,0xE8,0xA8,0xA0,
+    0xC2,0x30,0x81,0x28,0xAF,0x5E,0x77,0xD4,0xC2,0x30,0x81,0x28,0x3F,0xAB,0x2B,0xAD,
+    0xC2,0x30,0xA2,0x28,0x80,0xA0,0xF8,0xFF,0xE3,0x38,0xA2,0x30,0x08,0x0A,0xFB,0xFE,
+    0x23,0x41,0xA1,0x30,0x83,0xAB,0xAF,0xFD,0xE3,0x38,0xA1,0x30,0xA0,0xE0,0xE8,0xFA,
+    0xE3,0x38,0xC2,0x30,0xA8,0x2B,0x23,0x03,0x24,0x41,0xC2,0x38,0x2B,0xAF,0xFF,0x7F,
+    0x24,0x41,0xC3,0x38,0x00,0x82,0xFD,0xFD,0x65,0x49,0x03,0x41,0x21,0x29,0xAB,0xA5,
+    0x85,0x51,0x24,0x41,0xAA,0xE2,0xCF,0xB7,0x44,0x41,0x03,0x41,0xD6,0x6A,0x60,0xC2,
+    0x44,0x49,0xE3,0x38,0xA2,0xEF,0x7F,0x7F,0x23,0x41,0xE3,0x38,0x70,0xBA,0xEE,0xB7,
+    0xE3,0x30,0xA3,0x30,0x0A,0x00,0x80,0xF0,0xC2,0x30,0xA2,0x28,0x00,0xA0,0x90,0x97,
+    0x04,0x39,0xC3,0x30,0x77,0xA5,0xB5,0xFD,0xC3,0x38,0xE3,0x30,0x7F,0xDF,0xDF,0xD5,
+    0x44,0x49,0xC2,0x30,0xAB,0x2D,0xBD,0x3F,0x85,0x49,0x44,0x49,0x25,0x2D,0x2F,0xB5,
+    0xA5,0x51,0x65,0x49,0x48,0x70,0x5A,0x5D,0x65,0x49,0x23,0x41,0xE0,0xE0,0xF8,0x78,
+    0x44,0x41,0x03,0x41,0xBF,0xBF,0x7F,0x5F,0x03,0x41,0xE3,0x38,0x6A,0xEA,0x58,0xF0,
+    0x03,0x39,0xC3,0x30,0xAF,0x3B,0xFB,0x7F,0xE3,0x38,0xC2,0x30,0x57,0x56,0xD7,0xDE,
+    0xE3,0x38,0xC3,0x30,0xE1,0xB7,0x14,0x0D,0x03,0x39,0xC3,0x30,0xBF,0xBF,0xBE,0xAA,
+    0x03,0x39,0xC2,0x30,0x9A,0xA8,0xBA,0xEE,0xE3,0x30,0xC2,0x30,0x7C,0x5C,0x5B,0x92,
+    0x03,0x39,0xC2,0x30,0xE5,0x7B,0xBF,0xEB,0x03,0x39,0xC2,0x30,0xEB,0xB7,0x7C,0x7A,
+    0x03,0x39,0xC2,0x30,0xE2,0xA3,0x5F,0x75,0xE3,0x38,0xC2,0x30,0x2A,0xFA,0xFA,0x03,
+    0x03,0x39,0xC2,0x30,0xEA,0xBD,0xFB,0xF2,0xC4,0x38,0xE2,0x30,0xB7,0xF5,0x5F,0x7F,
+    0x03,0x39,0xC2,0x30,0x3F,0xDF,0xFB,0xDA,0x24,0x39,0xC2,0x30,0x62,0xFE,0xFB,0xDD,
+    0xE3,0x30,0xA2,0x30,0xCB,0xCA,0xF8,0xE8,0xE3,0x30,0xA1,0x30,0xA0,0xAB,0xAF,0xBF,
+    0x03,0x39,0xC2,0x30,0x2F,0xBD,0xFD,0xDD,0x03,0x39,0xC2,0x38,0x0F,0xBB,0x9B,0x0D,
+    0x23,0x41,0xE2,0x38,0x2A,0x2C,0x0F,0x0D,0x44,0x41,0x03,0x39,0x8F,0xBF,0xD7,0xFC,
+    0x44,0x41,0x23,0x41,0x57,0x65,0xB7,0xF5,0x44,0x41,0xE3,0x38,0xBE,0xFA,0xF8,0x1A,
+    0x44,0x41,0x03,0x39,0xEE,0xAF,0xFB,0x2F,0x23,0x41,0xC2,0x38,0xFA,0xDE,0xF8,0xF8,
+    0x64,0x49,0x03,0x41,0x0D,0x0D,0xAD,0xFD,0x85,0x51,0x23,0x41,0x1F,0xBE,0xAE,0xED,
+    0xA5,0x51,0x44,0x49,0xA2,0x23,0x25,0x3D,0xC5,0x61,0x43,0x49,0x2B,0xFF,0xDF,0xFF,
+    0x26,0x6A,0x64,0x51,0x80,0xAB,0xAF,0xF5,0xE6,0x61,0x63,0x51,0x7E,0xEA,0xC2,0x8B,
+    0x26,0x6A,0x84,0x59,0x2D,0x25,0x9F,0xBF,0xA8,0x7A,0x26,0x6A,0x3F,0xAF,0x2B,0x2D,
+    0xC9,0x82,0x67,0x72,0x8A,0xEA,0xF6,0x7F,0xC9,0x82,0x88,0x7A,0x6B,0xA2,0xBE,0xF7,
+    0xAB,0x93,0xA8,0x7A,0x35,0xB5,0xF5,0xF5,0x52,0xCD,0xEC,0xA3,0x0B,0x2B,0xAD,0xAD,
+    0x93,0xD5,0x11,0xC5,0x0A,0x2B,0xAD,0xB5,0x93,0xD5,0x52,0xCD,0xF4,0x54,0x7B,0xFB,
+    0x93,0xCD,0x31,0xC5,0x8A,0xAE,0xAF,0xFF,0x93,0xD5,0xF0,0xBC,0x78,0x58,0x5F,0x57,
+    0x93,0xCD,0xF1,0xBC,0xAD,0x29,0x8F,0x2A,0x73,0xCD,0x11,0xBD,0xF8,0x78,0xE0,0x60,
+    0x52,0xC5,0xF1,0xBC,0x0E,0xBF,0xF7,0x57,0x73,0xCD,0xD1,0xB4,0xA8,0x28,0xAF,0xFD,
+    0x52,0xC5,0x11,0xBD,0x78,0xAA,0xCF,0x6F,0x11,0xBD,0x6F,0xAC,0xA8,0xF8,0x78,0x5E,
+    0xB0,0xB4,0x4F,0xA4,0xA0,0x92,0xBE,0x17,0xB0,0xB4,0x90,0xAC,0x4A,0x32,0x52,0x76,
+    0x4F,0xA4,0xC9,0x7A,0xE0,0xF8,0x58,0x58,0x2E,0x9C,0xEA,0x7A,0xB5,0xBD,0x25,0x0D,
+    0xD0,0xB4,0xEE,0x9B,0xFD,0xED,0xAB,0x0A,0xF1,0xBC,0x4E,0xA4,0x55,0x55,0xBD,0x0A,
+    0x32,0xBD,0x0E,0x9C,0xFD,0xAE,0xA2,0x80,0xD0,0xB4,0x6F,0xAC,0xBD,0xAA,0xA8,0x20,
+    0xD0,0xB4,0x6F,0xAC,0xA2,0xAF,0xDF,0xFE,0xB0,0xAC,0x6F,0xAC,0x00,0xAE,0xDC,0xDE,
+    0xB0,0xB4,0x4F,0xA4,0xA2,0xE2,0xFB,0xE2,0xB0,0xAC,0x6F,0xAC,0xCB,0xD5,0xD7,0xF7,
+    0x84,0x59,0x43,0x51,0xBF,0xBA,0xE2,0xFE,0x84,0x59,0x43,0x59,0x0A,0x8B,0x0F,0xB7,
+    0x63,0x59,0x23,0x51,0x0F,0x8A,0xEE,0xFC,0x63,0x59,0x02,0x51,0xFA,0xEA,0xEA,0xFB,
+    0x43,0x51,0x02,0x49,0x00,0x7F,0x6F,0x7F,0x64,0x51,0xE2,0x48,0x0A,0xA5,0xBF,0xAE,
+    0x63,0x51,0x22,0x51,0xBF,0xFD,0x7F,0x53,0x43,0x51,0x22,0x51,0xC8,0x70,0x70,0x7A,
+    0x43,0x51,0x02,0x49,0x8E,0xE2,0x62,0xD8,0x43,0x51,0x02,0x49,0x97,0x8F,0xBF,0xEB,
+    0x44,0x51,0x03,0x49,0xEB,0x2A,0x2E,0x01,0x43,0x51,0x02,0x49,0xAE,0x27,0xAD,0xAD,
+    0x64,0x51,0x02,0x49,0xF5,0x37,0xD7,0x5D,0x43,0x51,0x03,0x51,0xEA,0xC2,0xC3,0xFB,
+    0x43,0x51,0xE2,0x48,0x78,0xEB,0xBE,0xFA,0x64,0x59,0x03,0x51,0xF7,0xAF,0xAF,0x8B,
+    0x64,0x59,0x23,0x51,0xAA,0x2A,0xEA,0xEA,0x64,0x59,0x23,0x51,0x2D,0xAE,0xDE,0xFD,
+    0x44,0x59,0x23,0x59,0x08,0x20,0x00,0xC0,0xE5,0x69,0x03,0x51,0xBF,0xBF,0x3D,0x35,
+    0x4A,0x9B,0x67,0x7A,0x09,0x09,0x0B,0x0B,0xAB,0xA3,0x6B,0x9B,0x23,0xAB,0xAF,0x2E,
+    0xEC,0xAB,0x8B,0x9B,0xFF,0xFD,0x2F,0xBB,0xEC,0xAB,0xAC,0xA3,0x2F,0xBF,0xAF,0xAF,
+    0x0D,0xAC,0xCC,0xA3,0x3A,0xAF,0xBB,0xBF,0x0D,0xAC,0xCC,0xAB,0x60,0x82,0xA2,0xEB,
+    0x0D,0xAC,0xAB,0xA3,0x7F,0xAE,0xBF,0x8A,0xEC,0xAB,0x8B,0x9B,0x5F,0xF2,0xE2,0xA0,
+    0xAB,0xA3,0x4A,0x93,0x75,0x7E,0xFE,0xA0,0x6A,0x9B,0xE9,0x8A,0xDE,0x6E,0xA8,0x88,
+    0x29,0x93,0xC8,0x82,0x77,0xFE,0xAA,0xA0,0xE8,0x8A,0xC8,0x82,0xCB,0xBF,0xD4,0xF8,
+    0xE9,0x82,0x67,0x72,0xF0,0x62,0x72,0x7C,0x67,0x72,0x26,0x72,0xD8,0xF8,0xFC,0x7F,
+    0x46,0x72,0x06,0x6A,0x2A,0x0A,0x28,0x6A,0x46,0x72,0x26,0x6A,0xD8,0x28,0x88,0x2B,
+    0x46,0x72,0x05,0x6A,0xAC,0x8A,0x88,0x60,0x66,0x72,0x05,0x6A,0xFB,0xBE,0xEF,0x81,
+    0x87,0x7A,0x26,0x72,0x9B,0x3B,0x2B,0x02,0xE8,0x8A,0x88,0x7A,0x9F,0x95,0xBF,0xAB,
+    0xC8,0x8A,0xA8,0x7A,0x9F,0xFE,0xFC,0x7B,0xE9,0x8A,0x88,0x7A,0xFA,0xA8,0xA2,0xEA,
+    0xA8,0x82,0x68,0x7A,0x78,0xA0,0x80,0xE8,0x87,0x7A,0x26,0x6A,0x62,0x20,0xA0,0x62,
+    0x46,0x6A,0x43,0x49,0x5E,0x58,0x68,0x78,0x23,0x49,0xA2,0x30,0xFA,0x7A,0xFC,0x78,
+    0xA2,0x30,0x61,0x28,0xF0,0xFA,0xDE,0xD8,0xA2,0x28,0x61,0x28,0x2B,0x2F,0x2B,0xA2,
+    0xC2,0x30,0xA2,0x28,0xD7,0xED,0xAF,0x6D,0xC2,0x30,0x82,0x28,0x08,0xAE,0xBB,0xDB,
+    0xC2,0x30,0xA2,0x30,0x0F,0x2A,0x1F,0xD7,0xC2,0x30,0xA2,0x30,0xDC,0x54,0x5A,0xF2,
+    0xE2,0x38,0xA2,0x30,0x0F,0xED,0xBD,0xF7,0xE3,0x38,0xC3,0x38,0xE0,0xE0,0xFF,0x3B,
+    0x03,0x41,0xE3,0x38,0xBD,0xBD,0x05,0xA2,0x44,0x49,0xE3,0x38,0x2B,0x3F,0xDF,0x5F,
+    0x44,0x49,0x03,0x41,0x82,0xEE,0xF5,0x75,0x44,0x49,0x03,0x39,0x2A,0xEB,0xAD,0x35,
+    0x45,0x49,0xE3,0x38,0x5E,0xDF,0xFC,0x7C,0x03,0x39,0xA2,0x38,0x2A,0x28,0x28,0xAB,
+    0x03,0x39,0xA2,0x30,0x7A,0x7C,0xE8,0xA0,0xC3,0x30,0x81,0x28,0x2B,0xA9,0x7F,0xD6,
+    0xE3,0x30,0x82,0x28,0x3A,0x2B,0xAF,0xBD,0x04,0x39,0xC2,0x30,0xE3,0xA3,0x77,0x7F,
+    0x44,0x49,0xC2,0x30,0x35,0xA7,0x35,0xB5,0x85,0x49,0x03,0x41,0x2B,0xAE,0xDF,0x55,
+    0x64,0x49,0x03,0x41,0x88,0xFE,0xF5,0xD7,0x64,0x49,0xE3,0x38,0xE0,0xF0,0xAF,0xDF,
+    0x24,0x41,0xE3,0x38,0xEB,0xEB,0x5E,0x57,0x03,0x39,0xA2,0x30,0xA2,0xF2,0xFA,0xDA,
+    0xE3,0x38,0xA2,0x30,0xEA,0xBA,0x2A,0xB7,0x04,0x39,0xC3,0x30,0xB5,0xBF,0x3E,0x97,
+    0x03,0x39,0xC3,0x30,0xFF,0x7E,0xEA,0xAB,0x03,0x39,0xC3,0x30,0xAB,0xFB,0xBF,0xBD,
+    0x03,0x39,0xC3,0x30,0xA2,0xAA,0xB8,0xDA,0x03,0x39,0xC2,0x30,0x2A,0x0A,0xBA,0xFE,
+    0xE3,0x38,0xC2,0x30,0x2F,0xD7,0x57,0x55,0xE3,0x30,0xA2,0x30,0xA8,0x3F,0x2F,0x2F,
+    0x03,0x39,0xA2,0x28,0xFA,0xFA,0xF0,0x72,0xE3,0x38,0xC2,0x30,0x0D,0xAD,0x95,0x25,
+    0x03,0x41,0xE3,0x30,0x53,0x5D,0xF5,0xF5,0x24,0x41,0xC3,0x30,0xF7,0xBF,0xBA,0xAE,
+    0x03,0x39,0xC2,0x30,0x7E,0x7E,0xBC,0xB8,0x03,0x39,0xC2,0x30,0xBF,0xBB,0xA8,0xC0,
+    0x03,0x39,0xC2,0x30,0x78,0xEA,0xE8,0x82,0x03,0x39,0xA1,0x30,0xF7,0xBB,0xAA,0xA0,
+    0x03,0x39,0xC2,0x30,0xFD,0x5F,0xCB,0x8A,0x03,0x39,0xC2,0x38,0x0B,0x03,0x0B,0xAB,
+    0x44,0x41,0xE3,0x38,0xAD,0x3F,0xAB,0xAB,0x64,0x49,0x23,0x41,0xB8,0xFE,0xBE,0x6F,
+    0x64,0x49,0x23,0x41,0x56,0x78,0x5F,0x5F,0x23,0x41,0x03,0x39,0xFB,0xDF,0xDD,0x36,
+    0x23,0x41,0x03,0x39,0xEE,0x7B,0xBF,0xAE,0x03,0x41,0xE3,0x30,0xA2,0x8A,0x00,0x28,
+    0x24,0x41,0xE2,0x38,0x16,0xF7,0xBE,0xAF,0x44,0x49,0xE2,0x38,0x3E,0x37,0x37,0xFF,
+    0xA5,0x51,0x23,0x49,0xBD,0xBB,0x2B,0x8F,0x84,0x51,0x44,0x49,0xEB,0xEE,0xF8,0xE8,
+    0xA5,0x59,0x44,0x49,0x2F,0xB5,0x5F,0x5F,0xA4,0x59,0x64,0x51,0x2B,0xAE,0x29,0x0B,
+    0x06,0x62,0xA4,0x59,0x2F,0xAD,0xBB,0xEB,0xC8,0x7A,0x06,0x62,0xAD,0x29,0x2D,0x25,
+    0x09,0x83,0x67,0x72,0x7E,0x5A,0x6A,0xA2,0xC8,0x82,0x67,0x72,0xAE,0x8B,0xBD,0xD5,
+    0x2A,0x83,0x87,0x7A,0x3D,0xFF,0xF5,0xF5,0xAF,0xBC,0x4A,0x93,0x0B,0x0B,0x29,0x0D,
+    0x52,0xCD,0xAF,0xB4,0x0B,0x8E,0x2F,0xAD,0x72,0xCD,0x32,0xC5,0x82,0x2B,0x89,0xA5,
+    0x93,0xCD,0x31,0xC5,0xF7,0xFF,0xE7,0x89,0x32,0xC5,0xF1,0xBC,0xF8,0x1F,0x3C,0xBC,
+    0x94,0xCD,0x52,0xC5,0x89,0x2B,0x0B,0x23,0x94,0xCD,0x32,0xC5,0x78,0xE8,0xE0,0x58,
+    0x32,0xC5,0xF1,0xBC,0x7B,0x50,0xFC,0x96,0x11,0xBD,0xD0,0xB4,0xEC,0xEA,0xD0,0xDB,
+    0x32,0xC5,0x90,0xB4,0x22,0xAA,0xBB,0x77,0xF1,0xBC,0x4F,0xA4,0x7C,0x78,0x7A,0xFF,
+    0x8F,0xAC,0x4F,0xA4,0xB7,0xBD,0x2A,0x0A,0xD0,0xB4,0x4F,0xA4,0x7E,0x7B,0x6B,0x8A,
+    0xD0,0xB4,0xEA,0x7A,0x5E,0xFE,0xAA,0x00,0xF0,0xBC,0x8C,0x8B,0x25,0x2B,0x02,0x08,
+    0x11,0xBD,0xB0,0xB4,0xB9,0x8E,0x80,0x7F,0x11,0xBD,0xD0,0xB4,0x22,0x0A,0xBA,0xB5,
+    0x52,0xC5,0x11,0xBD,0x6D,0xBB,0x2D,0x3D,0x51,0xC5,0xD0,0xB4,0x5F,0x5A,0xFA,0xF8,
+    0x11,0xBD,0x8F,0xAC,0x57,0x7E,0xFA,0xB0,0xF1,0xBC,0x8F,0xAC,0x7F,0x7F,0xEF,0xE2,
+    0xB0,0xB4,0x6F,0xAC,0x5D,0x9F,0x23,0xC2,0x90,0xAC,0x6F,0xAC,0x55,0x2B,0x7A,0x7B,
+    0x64,0x59,0x43,0x51,0x8E,0x98,0xF6,0x57,0x64,0x59,0x23,0x51,0xF0,0x7A,0x5F,0xDB,
+    0x64,0x59,0x23,0x51,0xDB,0xE5,0xA3,0xCB,0x43,0x51,0x22,0x51,0xF5,0x74,0x74,0x08,
+    0x43,0x51,0x02,0x49,0xAB,0xDA,0x38,0x2F,0x43,0x51,0x23,0x51,0x8E,0xAF,0x9C,0x58,
+    0x63,0x51,0x02,0x49,0xEF,0x8F,0xAF,0xFE,0x43,0x51,0xE2,0x40,0xA8,0xC2,0xEA,0x7B,
+    0x23,0x49,0xE2,0x48,0xD4,0xBA,0xA7,0x89,0x43,0x51,0x03,0x49,0x0B,0x8F,0x85,0xD5,
+    0x44,0x51,0x03,0x49,0xEA,0xEA,0x5F,0x57,0x23,0x51,0x03,0x49,0x0D,0x8F,0xDC,0x2E,
+    0x43,0x59,0x03,0x51,0xDD,0x3B,0x68,0xFA,0x23,0x51,0xE3,0x48,0x82,0xB2,0xF8,0xFB,
+    0x44,0x59,0x03,0x51,0x55,0x35,0xA9,0x3F,0x64,0x59,0x23,0x59,0xAB,0xE0,0x68,0xCA,
+    0x64,0x59,0x23,0x51,0x78,0xE2,0xFA,0x5E,0x44,0x59,0x23,0x51,0xFD,0xDD,0x74,0x05,
+    0x44,0x59,0x03,0x51,0xEB,0xAF,0x83,0x80,0x87,0x82,0x23,0x51,0xB5,0xB5,0xB5,0x2D,
+    0x8B,0xA3,0xC8,0x8A,0x29,0x09,0x09,0x0B,0xCC,0xAB,0x6A,0x9B,0xBF,0xA7,0xAD,0xAA,
+    0xCC,0xA3,0xAB,0xA3,0x0B,0xB9,0x7B,0xEB,0xEC,0xAB,0x8B,0x9B,0x2A,0x8A,0xAD,0xEE,
+    0x0D,0xAC,0xAB,0xA3,0x28,0x0E,0x37,0xD7,0x2D,0xB4,0xCC,0xA3,0xA8,0xA2,0xCB,0xED,
+    0x0D,0xAC,0xCC,0xAB,0xAA,0xF0,0xE2,0x6D,0x0D,0xAC,0xCC,0xAB,0xE2,0xFB,0xE8,0xDA,
+    0xEC,0xAB,0xAB,0xA3,0x56,0x68,0x00,0x6E,0xCC,0xAB,0x6A,0x9B,0x5F,0xAA,0x80,0xFE,
+    0xAB,0xA3,0x09,0x8B,0x5A,0x7A,0xF0,0x78,0x09,0x93,0x87,0x7A,0xAA,0xF8,0x7C,0x7E,
+    0xA8,0x82,0x46,0x72,0xF0,0xE8,0xFF,0x57,0x67,0x7A,0x26,0x72,0x76,0x87,0x37,0xF7,
+    0x46,0x72,0x26,0x6A,0xA8,0xC0,0x80,0x20,0x46,0x72,0x26,0x6A,0xAD,0x9F,0xBA,0xA3,
+    0x46,0x72,0x05,0x6A,0x32,0x2B,0x0A,0x2F,0x87,0x7A,0x46,0x72,0x79,0xDD,0xFD,0x8B,
+    0xC8,0x82,0x67,0x72,0x3D,0x0F,0x09,0x02,0xC8,0x82,0x87,0x7A,0xA8,0xB0,0xFA,0xF2,
+    0xC8,0x82,0x67,0x7A,0xA8,0xAA,0xAA,0x5A,0xC9,0x82,0x25,0x6A,0x80,0xAB,0xFE,0x56,
+    0x88,0x7A,0x26,0x6A,0x80,0xFA,0x5F,0x5D,0x67,0x7A,0x05,0x6A,0x80,0xFA,0x5B,0xD7,
+    0x26,0x6A,0xA4,0x59,0x70,0x60,0xE0,0xAA,0xA4,0x59,0xC2,0x38,0x5F,0x7E,0xDE,0x78,
+    0xC2,0x38,0x82,0x30,0x56,0x5E,0x7C,0x5C,0xA2,0x30,0x81,0x28,0xAA,0xAF,0x22,0x29,
+    0xC2,0x30,0xA2,0x28,0x6D,0xE8,0xC0,0xE0,0xC2,0x30,0x81,0x28,0x7B,0xEA,0xA2,0xAA,
+    0xC3,0x30,0x81,0x28,0xFA,0xFB,0xBC,0x2A,0xC2,0x30,0xA2,0x30,0xEF,0xAF,0x0B,0x0B,
+    0xE3,0x38,0xA2,0x30,0xF5,0xAF,0x2B,0x02,0x03,0x39,0xC2,0x30,0x3D,0xAF,0xAB,0x0E,
+    0x03,0x39,0xC2,0x38,0x9C,0x5C,0x7E,0x7E,0x03,0x41,0xC3,0x38,0x8A,0xC9,0xED,0xAD,
+    0x44,0x49,0xE3,0x38,0xAD,0xAD,0x0D,0x2B,0x65,0x49,0x03,0x41,0xF5,0xAE,0xAA,0xCA,
+    0x24,0x41,0xE3,0x38,0x54,0x5C,0x8C,0x80,0x24,0x41,0xE3,0x38,0x55,0x7D,0x6A,0x80,
+    0x03,0x39,0xC2,0x30,0xAB,0x9D,0x97,0xBA,0xE3,0x38,0x82,0x28,0x7C,0xF0,0xF8,0xA0,
+    0xC2,0x30,0x82,0x28,0x9F,0xDF,0xD7,0xB6,0xC2,0x30,0xA2,0x28,0x00,0xB3,0x7F,0xD6,
+    0xE3,0x38,0x82,0x28,0x2A,0xAA,0xAD,0xBF,0x23,0x41,0xC3,0x38,0xAF,0x3D,0x9D,0xBD,
+    0x44,0x49,0xE3,0x38,0xDF,0xFF,0xC0,0x8A,0x24,0x41,0xC2,0x38,0xEE,0xF2,0xFA,0xF8,
+    0xE3,0x38,0x82,0x30,0x30,0xFE,0xF6,0xFF,0xC3,0x30,0x82,0x28,0x20,0xAB,0xA7,0xDF,
+    0xC2,0x30,0xA2,0x28,0x0E,0x2E,0x0A,0x83,0xE3,0x30,0xA2,0x28,0x2F,0xB7,0x7F,0xFF,
+    0xE3,0x30,0xA2,0x28,0x0B,0x0A,0x2F,0xA3,0x03,0x31,0xA2,0x28,0x8A,0xAA,0xBE,0xDD,
+    0xE3,0x30,0xA2,0x30,0x20,0x22,0xB6,0xBF,0x03,0x39,0xC2,0x30,0xFF,0x9B,0xFA,0xE8,
+    0x03,0x31,0xA2,0x30,0xDF,0xFC,0xEB,0xEB,0xE3,0x38,0xC2,0x30,0xA5,0xA5,0x2A,0x08,
+    0x03,0x39,0xC2,0x30,0x53,0xEB,0xBF,0xFC,0x03,0x39,0xC2,0x30,0xA5,0x95,0x97,0x55,
+    0x03,0x39,0xA2,0x30,0x2A,0x9A,0x2A,0xA2,0x03,0x39,0xE3,0x38,0xBC,0xD7,0x57,0xDE,
+    0x24,0x41,0xE3,0x38,0xDA,0x7D,0xF2,0x4A,0x03,0x41,0xE2,0x38,0x79,0xAB,0x3A,0xA2,
+    0x24,0x41,0xE2,0x38,0xFF,0x6B,0xE8,0x0F,0x03,0x41,0xE3,0x38,0xBD,0xA7,0xFD,0x7B,
+    0x23,0x41,0xC2,0x30,0xB7,0xBE,0x2A,0xAA,0x24,0x41,0xE2,0x38,0x97,0xF7,0xB9,0x8B,
+    0x64,0x49,0x03,0x41,0xEF,0xB7,0x25,0x0D,0x64,0x49,0x03,0x39,0xEE,0x5A,0xFA,0xF2,
+    0x03,0x41,0x44,0x39,0xAA,0xFA,0x2B,0xFF,0x24,0x41,0xE2,0x38,0x2A,0x8E,0xFB,0xDE,
+    0x23,0x41,0x03,0x39,0x03,0x3F,0x6F,0xD7,0x23,0x41,0xE3,0x38,0x2E,0x08,0xAF,0xBF,
+    0x24,0x41,0xE2,0x38,0x2E,0x2A,0x2F,0xB7,0x44,0x49,0xE2,0x38,0xAA,0x0A,0xF2,0x7E,
+    0x85,0x51,0x03,0x41,0x2B,0x0F,0x3D,0xBD,0xA5,0x51,0x44,0x49,0x7E,0xAE,0x8B,0xAD,
+    0xE6,0x59,0x64,0x51,0x5D,0xF9,0xAA,0x2C,0xC5,0x59,0x64,0x51,0x8D,0xBD,0x9F,0x3F,
+    0x26,0x6A,0xE5,0x61,0x75,0x35,0x9F,0xA2,0xA8,0x72,0x06,0x6A,0x2D,0xBF,0xEF,0xBF,
+    0xE9,0x82,0x87,0x72,0xEB,0xFB,0x3D,0xED,0xC8,0x82,0x67,0x72,0xD6,0x5A,0xF8,0x60,
+    0xA8,0x7A,0x46,0x72,0x0A,0x2D,0x37,0x9E,0x6E,0xAC,0xA8,0x7A,0x0F,0x2B,0x2D,0x2D,
+    0x11,0xC5,0x8E,0xB4,0x29,0xAF,0x2D,0x29,0xB3,0xD5,0x11,0xBD,0xFD,0xB5,0xAF,0x0B,
+    0xB3,0xD5,0x32,0xC5,0xAB,0xEB,0xFA,0x78,0x32,0xC5,0xAF,0xAC,0xA8,0xAA,0xAF,0xB5,
+    0xB4,0xD5,0x32,0xC5,0xA9,0xA9,0xA9,0x8F,0x73,0xCD,0x33,0xC5,0x70,0xE8,0xA8,0xE8,
+    0x53,0xC5,0x11,0xBD,0xF7,0x5A,0x58,0x78,0x11,0xBD,0xB0,0xB4,0x7F,0x7E,0x7E,0x5C,
+    0xB0,0xB4,0x0E,0xA4,0xE0,0xFA,0xFC,0xBE,0xB0,0xB4,0x2E,0xA4,0xAF,0xAD,0xAB,0x8A,
+    0x11,0xBD,0x6F,0xAC,0x9D,0x2F,0x0B,0xAA,0xF1,0xBC,0x6F,0xAC,0xA2,0x88,0x68,0x5E,
+    0xD1,0xB4,0x4E,0xA4,0x80,0xFE,0x55,0x55,0xB0,0xB4,0x2E,0xA4,0x80,0xAF,0xBF,0x55,
+    0xB0,0xB4,0x0E,0x9C,0xA0,0xAA,0x7E,0x57,0xF1,0xB4,0xCD,0x9B,0x2A,0xBA,0xFF,0xD5,
+    0xF1,0xBC,0x4E,0xA4,0x00,0xAB,0xF5,0x55,0x11,0xBD,0x6F,0xAC,0x00,0x8B,0xBF,0xF5,
+    0x32,0xC5,0x8F,0xAC,0xAA,0x02,0xBA,0xDD,0x32,0xC5,0xD0,0xB4,0x7A,0xBC,0xF6,0x9B,
+    0x11,0xBD,0xB0,0xB4,0x5F,0x08,0x20,0x00,0x32,0xC5,0x8F,0xAC,0x55,0xEC,0x88,0x0A,
+    0x64,0x59,0x23,0x51,0xFE,0xDC,0x55,0xD5,0x43,0x51,0x23,0x51,0xCB,0x62,0xBC,0x75,
+    0x63,0x51,0x03,0x49,0x8D,0xFE,0x5A,0xF7,0x43,0x51,0x02,0x49,0x0C,0xBA,0xFE,0x8A,
+    0x43,0x51,0x03,0x51,0x2A,0x8A,0x4A,0xC8,0x64,0x59,0x03,0x49,0xEB,0xB2,0xFB,0x6B,
+    0x43,0x51,0xE2,0x48,0xE2,0x82,0xF8,0x6E,0x43,0x51,0xE2,0x40,0xDB,0xEE,0xFB,0xA3,
+    0x43,0x51,0x03,0x49,0x7F,0x7F,0xFB,0x8B,0x44,0x51,0x02,0x49,0xFD,0xAB,0x8A,0xB8,
+    0x23,0x51,0x02,0x49,0x5E,0x7F,0xA2,0x02,0x43,0x51,0xE3,0x48,0x8A,0xE2,0xA0,0xA8,
+    0x44,0x59,0xE2,0x50,0xEA,0x62,0xFA,0xEA,0x44,0x59,0xE2,0x48,0xBD,0x2D,0xAA,0x02,
+    0x85,0x61,0x23,0x51,0xFD,0x7F,0x5E,0x78,0x64,0x59,0x23,0x51,0xB9,0xB1,0x22,0x83,
+    0x64,0x59,0x23,0x51,0xF4,0xFE,0xFF,0xAD,0x64,0x61,0x23,0x51,0xBD,0xA9,0xCB,0xFB,
+    0x64,0x59,0x23,0x51,0xAC,0xBF,0xF5,0x2F,0xA8,0x82,0x44,0x59,0x3D,0x3D,0x2D,0x2D,
+    0xAB,0xA3,0x09,0x93,0xAF,0xAD,0x0D,0x2B,0xCB,0xA3,0x8B,0x9B,0x1F,0xAD,0xAB,0xAA,
+    0xCC,0xA3,0x8B,0xA3,0x83,0xA2,0xD2,0xEA,0xCB,0xA3,0x6A,0x9B,0xA2,0xAA,0xEB,0x7F,
+    0xAB,0xA3,0x4B,0x9B,0x00,0xE0,0xEB,0x5F,0xAC,0xA3,0x4B,0x9B,0x82,0xAB,0xEB,0xFD,
+    0xCC,0xAB,0x2A,0x93,0x02,0xAA,0xBB,0x5F,0xCC,0xA3,0x29,0x93,0x00,0xAA,0xDF,0x55,
+    0xAB,0xA3,0x09,0x8B,0x80,0xEA,0xFE,0xD5,0x6A,0x9B,0xC8,0x82,0x00,0xEA,0xFE,0x5F,
+    0x29,0x93,0x67,0x7A,0xA0,0xF8,0xFA,0x5F,0xC8,0x82,0x67,0x72,0xDE,0x5F,0xFF,0xFF,
+    0x67,0x7A,0x46,0x72,0x53,0xCC,0x7A,0x74,0x67,0x72,0x26,0x72,0xCE,0x4A,0x6A,0x7F,
+    0x46,0x72,0x25,0x6A,0xA8,0x90,0x7B,0x57,0x46,0x72,0x05,0x6A,0xAE,0xA2,0xAF,0x3F,
+    0x67,0x72,0x06,0x6A,0xBF,0xA6,0xAF,0xAA,0xE9,0x82,0x46,0x72,0x97,0xBD,0xAE,0x23,
+    0xE8,0x82,0x87,0x7A,0xAF,0xFA,0xDA,0x74,0xC8,0x82,0x46,0x72,0x88,0xA8,0xAA,0x7A,
+    0xA8,0x82,0x05,0x6A,0xE8,0xF8,0x7E,0x5F,0x67,0x72,0xC5,0x61,0xE8,0x6A,0x7F,0x5F,
+    0x05,0x6A,0xA4,0x59,0xE0,0x6D,0xFE,0x5F,0x05,0x6A,0x84,0x59,0x02,0xAB,0x9E,0xFF,
+    0x25,0x62,0xC5,0x61,0x6F,0xDF,0xFD,0xED,0xC5,0x61,0xE3,0x40,0x78,0x78,0xE8,0x80,
+    0x04,0x41,0x61,0x28,0x5E,0x5E,0x78,0x78,0xC2,0x30,0x61,0x28,0x3F,0x2D,0x2F,0xAD,
+    0xE3,0x38,0xA2,0x30,0x7F,0xF2,0xAE,0x3F,0xE3,0x38,0xA2,0x30,0x7F,0xFB,0x8A,0xA0,
+    0x04,0x39,0xC3,0x30,0xD5,0xDD,0xF5,0x0A,0xE3,0x38,0xA2,0x30,0xAF,0xAE,0x5E,0xF8,
+    0x03,0x39,0xC2,0x38,0xA9,0x2D,0x09,0x2B,0xE2,0x40,0x23,0x39,0xFC,0xFE,0xFF,0xAF,
+    0x03,0x41,0xA2,0x38,0xE8,0xA8,0x2C,0x2E,0x24,0x41,0xC3,0x38,0xA5,0x2F,0x8A,0xA0,
+    0x65,0x49,0x03,0x41,0xAD,0xB5,0x0D,0xEB,0x65,0x49,0x24,0x41,0xAB,0x9F,0xDE,0x9B,
+    0x44,0x49,0x23,0x41,0x54,0x77,0x5F,0x55,0x44,0x41,0x03,0x41,0xE2,0xF2,0xFF,0xB7,
+    0x44,0x41,0xE3,0x38,0xFB,0xDA,0xE2,0xFA,0x03,0x39,0xC2,0x30,0x7E,0xFA,0xC2,0xE2,
+    0xE3,0x30,0x81,0x28,0xDF,0x5F,0xFC,0xF8,0xE3,0x30,0xA2,0x30,0x5F,0x89,0x29,0xBD,
+    0x03,0x39,0xA2,0x30,0x1D,0xFB,0xEE,0xAE,0x24,0x41,0xC3,0x30,0x2F,0x25,0x2F,0x0B,
+    0x64,0x49,0x04,0x41,0xEF,0xFF,0xEF,0xEF,0x24,0x41,0xA2,0x30,0xE0,0xB0,0xFA,0x5E,
+    0xE3,0x38,0xA2,0x30,0x7F,0x7B,0xEB,0x8B,0xE2,0x30,0x81,0x28,0xFF,0x7B,0xAA,0xA0,
+    0x03,0x39,0x82,0x28,0xEB,0x7B,0xFB,0x0B,0xE3,0x30,0xA2,0x28,0xEF,0xBB,0x8B,0x28,
+    0xE3,0x30,0xA2,0x30,0xE3,0xFB,0xFF,0xD6,0xE3,0x30,0xA2,0x30,0x97,0x1F,0xAB,0x2E,
+    0x03,0x39,0xC2,0x30,0x57,0x7B,0xEB,0xAA,0x44,0x41,0xE3,0x38,0x55,0xDD,0xBD,0x8F,
+    0x03,0x39,0xC2,0x30,0xFE,0xBC,0xA8,0x2A,0x03,0x39,0xC2,0x30,0xAF,0xAF,0xB6,0xFA,
+    0xE2,0x38,0xC2,0x30,0xA2,0x2A,0xBF,0xD5,0xE2,0x38,0xA2,0x30,0xFE,0x2C,0x2E,0xAA,
+    0x04,0x41,0xE3,0x30,0xF9,0x8D,0xAF,0xA9,0x23,0x41,0xE3,0x38,0x1D,0xAF,0xBA,0xA3,
+    0x44,0x41,0x03,0x39,0x7D,0x5D,0x8B,0x2A,0x03,0x41,0xE3,0x38,0xE7,0xBE,0xA4,0x24,
+    0x44,0x49,0x03,0x39,0xBD,0xBB,0x7B,0x02,0x44,0x49,0x03,0x39,0xF7,0xFF,0xFF,0x0F,
+    0x43,0x41,0xE3,0x38,0xF7,0xEF,0xFE,0xA8,0x23,0x41,0x03,0x39,0x9D,0x1B,0x03,0x02,
+    0x85,0x51,0x03,0x39,0x2B,0x2F,0xFD,0xF7,0x85,0x49,0x03,0x41,0xDC,0xFA,0xFB,0xFF,
+    0x44,0x41,0xE2,0x38,0xE2,0xEA,0x7A,0xFA,0x23,0x41,0xE3,0x38,0x56,0x9F,0x3D,0xAE,
+    0x64,0x49,0x03,0x39,0xFD,0xFF,0xBA,0x8A,0x44,0x41,0x03,0x39,0xFE,0xAA,0x9E,0x2A,
+    0x44,0x41,0xE2,0x38,0xFF,0xD7,0xFE,0xEC,0x23,0x41,0x03,0x39,0x77,0x2B,0x01,0xAD,
+    0x44,0x49,0x03,0x41,0xAB,0xAA,0xFE,0xE8,0x85,0x51,0x44,0x49,0x2B,0xBD,0x65,0xD5,
+    0xA5,0x51,0x64,0x51,0xF8,0xFE,0xBD,0x35,0xC6,0x59,0x84,0x51,0xB5,0x1D,0x1A,0x2B,
+    0x67,0x72,0xA5,0x59,0xAB,0x2B,0x2B,0xAD,0x67,0x72,0x06,0x62,0x0A,0x22,0xA8,0xDE,
+    0xA8,0x7A,0x06,0x6A,0x02,0x0A,0xAF,0x75,0xA8,0x7A,0x26,0x6A,0x00,0x02,0xAB,0xB5,
+    0x88,0x7A,0x47,0x72,0x5E,0x5B,0xB0,0xAE,0x4D,0xAC,0xA8,0x7A,0x2D,0x2D,0x25,0x25,
+    0x72,0xCD,0xCF,0xBC,0xA5,0x2D,0x29,0x09,0xB3,0xD5,0x72,0xCD,0xAD,0x8B,0xCB,0x75,
+    0x73,0xCD,0x8F,0xAC,0xE0,0x70,0x78,0x7C,0x73,0xCD,0x4F,0xAC,0xBD,0xBD,0x2D,0x2B,
+    0x94,0xCD,0x53,0xC5,0x09,0x7D,0x7A,0xFB,0x73,0xC5,0xF1,0xBC,0xE0,0xFE,0xDF,0x5F,
+    0x53,0xC5,0xD1,0xB4,0x8A,0x0F,0xA7,0xFF,0x32,0xC5,0x90,0xAC,0xF8,0xEA,0xF8,0x7E,
+    0x90,0xAC,0xEE,0x9B,0x00,0x00,0xA0,0x7A,0x90,0xAC,0xCD,0x93,0x08,0xA8,0xFF,0x75,
+    0xB0,0xAC,0xCD,0x93,0xA0,0xEE,0xF5,0x55,0x6F,0xAC,0xEE,0x9B,0xA0,0xFB,0xBF,0x77,
+    0x0E,0xA4,0x2E,0x9C,0xB5,0xFE,0xBF,0x8A,0x2E,0xA4,0xCC,0x93,0x00,0xEA,0xFA,0x62,
+    0x2F,0xA4,0xCD,0x93,0xA0,0x77,0x7F,0xB7,0x0E,0x9C,0x8C,0x8B,0xBE,0xFF,0xDF,0x20,
+    0x6F,0xAC,0xAD,0x93,0x2F,0xB7,0xF5,0x55,0x6F,0xAC,0xED,0x9B,0x2A,0x0B,0x2B,0x95,
+    0xB0,0xB4,0x2E,0xA4,0x22,0xA2,0xFF,0x77,0x11,0xBD,0x4F,0xA4,0x0A,0x2F,0x9F,0xD5,
+    0x32,0xC5,0xB0,0xAC,0x80,0x02,0x2B,0xB5,0x32,0xC5,0x11,0xBD,0x77,0x2A,0x80,0x23,
+    0x43,0x51,0x23,0x51,0xFD,0xD8,0x00,0xE0,0x43,0x51,0x23,0x51,0x4A,0xC2,0x8D,0x13,
+    0x43,0x51,0xE2,0x48,0xAA,0xFA,0xF8,0xBC,0x63,0x59,0x03,0x49,0xAF,0x29,0x35,0xBF,
+    0x64,0x59,0x23,0x51,0x7E,0x07,0xE5,0x6D,0x43,0x51,0x02,0x49,0x83,0x08,0x02,0x5A,
+    0x23,0x51,0xE2,0x40,0x7C,0xEE,0x6E,0xAF,0x23,0x49,0xE2,0x48,0xAB,0x3F,0xAE,0x00,
+    0x44,0x51,0x02,0x49,0xBE,0x9D,0xA3,0xA2,0x43,0x51,0x03,0x49,0xF2,0xE8,0xBE,0x2F,
+    0x44,0x51,0x02,0x49,0x99,0xFC,0xA2,0x28,0x43,0x51,0x02,0x51,0xAA,0x0A,0xC8,0xEE,
+    0x63,0x51,0x03,0x51,0x6F,0xBE,0xAE,0x2A,0x85,0x61,0x23,0x51,0xE7,0xCE,0xF7,0x57,
+    0x64,0x59,0x23,0x51,0x70,0x58,0xDF,0xDD,0x64,0x59,0x23,0x51,0x8D,0xB7,0xDA,0x7A,
+    0x64,0x59,0x03,0x51,0x2E,0xBB,0xFD,0xAF,0x43,0x59,0x03,0x51,0x32,0xBA,0x28,0x1A,
+    0x64,0x59,0x03,0x51,0x2F,0xA7,0xAF,0xAA,0x4A,0x93,0x64,0x59,0x3D,0x2D,0x2D,0x2F,
+    0xAB,0xA3,0x49,0x9B,0xB5,0xA5,0xFB,0x0F,0xAB,0xA3,0x6A,0x9B,0x02,0x02,0x2B,0xDA,
+    0xCC,0xAB,0x6B,0x9B,0xE2,0xA2,0xEA,0xEA,0x8B,0x9B,0x2A,0x93,0xA2,0xEC,0xFA,0x7E,
+    0x4B,0x9B,0x09,0x93,0x20,0xC0,0xFE,0x7F,0x6B,0x9B,0xE9,0x8A,0x8A,0xEE,0x7F,0x77,
+    0x2A,0x93,0x87,0x7A,0x20,0xBA,0xFE,0x57,0x09,0x8B,0x87,0x7A,0x00,0x80,0xEA,0x5D,
+    0x2A,0x93,0x87,0x7A,0x8A,0xFA,0x7F,0x55,0xA8,0x82,0x66,0x72,0x00,0xBF,0x7E,0x7D,
+    0xA7,0x7A,0x46,0x72,0xF0,0xFA,0xF7,0xFF,0x87,0x7A,0x46,0x72,0xE0,0x7B,0x56,0xD7,
+    0x66,0x72,0x26,0x6A,0xE6,0xAD,0xC8,0x3A,0x87,0x7A,0x26,0x6A,0x57,0xF5,0xF5,0xDA,
+    0x66,0x72,0x25,0x6A,0x7F,0xDA,0xAF,0xBA,0x66,0x72,0x26,0x72,0xBB,0xFB,0xAA,0x0E,
+    0xC8,0x82,0x46,0x72,0xB5,0xFF,0x2D,0x2A,0xE9,0x82,0x88,0x7A,0xEA,0xFB,0x72,0xEA,
+    0xA7,0x7A,0x46,0x72,0xA8,0x8C,0xE8,0x7E,0x87,0x7A,0xE5,0x69,0xA0,0xEA,0x72,0x7E,
+    0x26,0x6A,0xC4,0x61,0x20,0xE0,0x5E,0x7B,0x05,0x6A,0xA4,0x61,0x7C,0xE7,0xEE,0x2B,
+    0x05,0x6A,0xA4,0x61,0x7F,0xF5,0xFE,0xA2,0x06,0x6A,0xA4,0x61,0xDF,0xFB,0xA3,0xAA,
+    0xE5,0x69,0xA4,0x59,0x2B,0xAE,0xAD,0x82,0x06,0x6A,0xA5,0x59,0x5A,0x7B,0x7A,0xE2,
+    0xA5,0x59,0x81,0x30,0x7E,0xFA,0xFA,0xE8,0xE3,0x38,0x81,0x28,0xF5,0xDA,0x7C,0xF0,
+    0xE3,0x38,0x61,0x28,0x2B,0x2B,0xFF,0x5F,0x04,0x39,0xA2,0x30,0x00,0x82,0xBD,0xF5,
+    0x24,0x41,0xA2,0x30,0x8A,0x0E,0xBF,0x27,0x24,0x41,0xC2,0x30,0x7E,0x7A,0xA0,0x80,
+    0xE3,0x38,0xA2,0x30,0x02,0xA8,0xFC,0x58,0xE2,0x38,0xA2,0x30,0xA0,0x3B,0xBF,0x9F,
+    0x24,0x41,0xE2,0x38,0x25,0xFB,0x2B,0xBF,0x64,0x49,0x03,0x41,0xF7,0xBF,0xBF,0xAD,
+    0x64,0x49,0x24,0x41,0xFB,0xE2,0x88,0x00,0x65,0x49,0x24,0x41,0xDB,0x7F,0x77,0x7F,
+    0x44,0x41,0xE2,0x38,0x8F,0xF7,0xFA,0xA0,0x44,0x49,0x03,0x39,0xB7,0xFF,0xAA,0xEA,
+    0x23,0x41,0xE3,0x38,0x70,0xF8,0xDA,0xB8,0x24,0x41,0xE3,0x38,0x69,0x5F,0xBE,0x0A,
+    0x24,0x39,0xA2,0x30,0x7B,0xFE,0xEA,0xF0,0xC3,0x30,0xA2,0x28,0x25,0x3F,0x2C,0x08,
+    0x04,0x39,0xA2,0x30,0xBF,0x3F,0x3E,0xB7,0x44,0x41,0x04,0x39,0xAD,0xEF,0xE1,0x55,
+    0x24,0x41,0xC3,0x30,0x80,0xA8,0xE8,0xDE,0xE3,0x38,0xC3,0x30,0xDC,0xC8,0xEA,0x17,
+    0xC3,0x38,0xE3,0x30,0xBF,0xDF,0x7F,0x55,0x03,0x39,0xC3,0x30,0x77,0x8A,0xE2,0xD6,
+    0x03,0x39,0xC3,0x30,0xAD,0xAF,0x3D,0x7B,0xE3,0x30,0xC2,0x28,0xAC,0x6C,0xFE,0x5C,
+    0xE2,0x30,0xA2,0x28,0x9D,0xF5,0xDF,0x73,0x03,0x39,0xA2,0x28,0xBF,0xBD,0xAF,0x29,
+    0x44,0x41,0xE3,0x38,0xFF,0xAB,0x0D,0x8F,0x44,0x41,0x03,0x39,0xAD,0xEB,0xFB,0x7A,
+    0x24,0x39,0xE3,0x38,0xEF,0x8B,0xFA,0xFF,0xE2,0x30,0xC2,0x30,0x6E,0x57,0x57,0x57,
+    0xE3,0x38,0xC2,0x30,0x55,0x5D,0xA2,0xA2,0x03,0x39,0xC3,0x30,0xFF,0x2F,0x0F,0x8F,
+    0x45,0x41,0xE3,0x38,0xA5,0x2B,0x2E,0xAB,0x65,0x49,0x24,0x41,0x5D,0x55,0xAE,0xEB,
+    0x64,0x49,0x03,0x39,0xFB,0x7E,0x9F,0xA2,0x44,0x49,0xE3,0x38,0xF5,0xF6,0xB8,0xA2,
+    0x64,0x49,0x24,0x41,0xAF,0xBF,0xFC,0xAA,0x65,0x49,0x23,0x41,0xAF,0xFD,0x9F,0x82,
+    0x64,0x49,0x03,0x39,0xF8,0x78,0xFA,0xAA,0x44,0x41,0x03,0x41,0xFA,0xA2,0x98,0xFE,
+    0x44,0x41,0xC2,0x38,0x2A,0x22,0xE8,0x5E,0x44,0x49,0xE3,0x38,0xA8,0xA8,0xEF,0xDD,
+    0x23,0x41,0x03,0x39,0xA2,0x60,0x2A,0x0B,0x23,0x41,0xE2,0x38,0x2E,0x2E,0x28,0xDC,
+    0x64,0x49,0x03,0x39,0x8B,0xBF,0xF7,0xD5,0x44,0x41,0xE2,0x38,0x88,0xBA,0xEF,0x75,
+    0x23,0x41,0xE3,0x30,0x08,0x88,0x83,0x01,0x43,0x41,0x03,0x39,0xB5,0x35,0xBD,0xD5,
+    0x64,0x49,0x24,0x41,0x82,0x82,0x9B,0xFD,0x64,0x49,0x23,0x41,0xB2,0xA2,0xB8,0xDD,
+    0x85,0x51,0x23,0x41,0x27,0xBA,0xFE,0xEE,0xC6,0x59,0x64,0x51,0x82,0xAE,0xFD,0xFD,
+    0x06,0x62,0x84,0x51,0x2D,0xB7,0xF7,0xFF,0x47,0x6A,0xC5,0x61,0xAB,0x0B,0xA9,0xAB,
+    0x47,0x72,0xC5,0x59,0xBE,0x5A,0x58,0xE8,0x47,0x72,0xC4,0x59,0x0A,0x3D,0x2F,0xAF,
+    0x88,0x72,0x26,0x6A,0xE8,0xF5,0xBD,0xB5,0x0D,0xA4,0x87,0x72,0x35,0x25,0x35,0xB5,
+    0x92,0xD5,0x8F,0xB4,0x8B,0x0B,0x29,0x29,0x93,0xD5,0x31,0xC5,0xAA,0xA0,0xEA,0x68,
+    0x52,0xCD,0xB0,0xB4,0x5C,0x58,0x5E,0x57,0x73,0xCD,0xAF,0xB4,0xAD,0x0B,0x2B,0x0B,
+    0x94,0xCD,0x73,0xC5,0x47,0x88,0xFA,0x5E,0x32,0xC5,0x90,0xAC,0xE8,0xE0,0xE0,0x78,
+    0xD1,0xB4,0x2E,0xA4,0x00,0x88,0xFA,0xF7,0xB0,0xB4,0x0E,0x9C,0xC8,0xEA,0x7E,0x5F,
+    0x4F,0xA4,0xAD,0x93,0xE8,0xFE,0xDF,0x77,0xCE,0x9B,0x6C,0x8B,0x08,0xFA,0x7E,0xFB,
+    0xCD,0x93,0x6C,0x8B,0x08,0x2B,0xB7,0xA7,0x0E,0x9C,0xAD,0x93,0xA2,0xEA,0xFF,0xFD,
+    0x0E,0x9C,0x8D,0x93,0x20,0xAA,0xFF,0x7F,0x0E,0xA4,0xAD,0x93,0x8A,0x8B,0xAD,0xF9,
+    0x2E,0xA4,0xCD,0x93,0xFD,0xBF,0x0F,0xE9,0x2E,0x9C,0xEE,0x9B,0x8B,0x68,0x58,0x5E,
+    0xCD,0x93,0x6C,0x8B,0xBC,0xB4,0x5E,0x5E,0x4F,0xA4,0xAC,0x93,0xAF,0x2B,0x2D,0xAD,
+    0x6F,0xAC,0x0E,0xA4,0x3A,0xA2,0x0B,0xAB,0xAF,0xAC,0x4F,0xA4,0xD7,0xDD,0xBF,0xAD,
+    0xF1,0xBC,0x4F,0xA4,0xB7,0xAB,0x02,0x02,0x11,0xBD,0x6F,0xAC,0x2B,0xD6,0xE8,0x00,
+    0x64,0x59,0x02,0x49,0xF2,0xBE,0x78,0xEB,0x64,0x59,0x03,0x49,0xAE,0x3F,0xB9,0xBD,
+    0x65,0x59,0x03,0x49,0xF4,0x7B,0xEF,0xFF,0x44,0x51,0xE3,0x48,0xAF,0x8B,0xEF,0xDB,
+    0x43,0x51,0xE1,0x48,0x02,0x8A,0xAA,0x7E,0x23,0x49,0xE2,0x40,0xEC,0x5E,0xBF,0xFF,
+    0x43,0x51,0xE2,0x40,0xFB,0xB9,0xF7,0x2F,0x43,0x51,0x02,0x49,0xFB,0x8B,0x0F,0xBE,
+    0x43,0x51,0x23,0x49,0xC0,0x44,0xC6,0xE0,0x64,0x51,0x23,0x51,0xAD,0x5D,0xDF,0x57,
+    0x43,0x51,0x03,0x51,0x2E,0xA8,0x8A,0xEB,0x44,0x59,0x22,0x49,0xB7,0xA7,0xA7,0xCF,
+    0x64,0x59,0x23,0x51,0xBA,0xAB,0x8B,0xF9,0x64,0x59,0x03,0x51,0x7E,0xAA,0xA0,0xAE,
+    0x43,0x59,0x23,0x51,0x3B,0xFB,0x75,0xAE,0x64,0x59,0x23,0x51,0xF2,0x5F,0xFF,0xFA,
+    0x43,0x59,0x23,0x51,0x2B,0x1B,0x1E,0x8B,0x44,0x59,0x03,0x51,0xEA,0xF0,0x5A,0x5B,
+    0x84,0x61,0x02,0x51,0xFF,0xBD,0x2F,0xAD,0x4A,0x9B,0xC5,0x61,0x2D,0x0D,0x29,0x09,
+    0xAB,0xA3,0x6A,0x9B,0x0D,0x2D,0x2D,0xA5,0xAB,0xA3,0x6A,0x9B,0xB0,0xFC,0xFC,0x77,
+    0x8B,0x9B,0x09,0x8B,0xA0,0x60,0x7E,0x5F,0x4A,0x9B,0x87,0x82,0xA0,0xAA,0x7B,0x7F,
+    0x29,0x93,0x87,0x7A,0xA0,0x7B,0xDD,0x55,0xE9,0x8A,0x46,0x72,0xE8,0xFA,0xEF,0xFF,
+    0xA8,0x82,0x46,0x72,0xB0,0xAA,0xFF,0xF7,0xA8,0x7A,0x46,0x72,0xE2,0xCA,0xFA,0x7D,
+    0x87,0x7A,0x46,0x72,0xCA,0xEA,0xB8,0x97,0x87,0x7A,0x46,0x72,0xA3,0x88,0xE2,0x7B,
+    0x87,0x7A,0x25,0x72,0xC0,0xEA,0xEA,0x89,0x66,0x72,0x27,0x72,0xAA,0xBE,0xBB,0xEE,
+    0x66,0x72,0x05,0x6A,0xBC,0xFA,0xFE,0xAA,0x66,0x72,0x05,0x72,0xA0,0xE6,0x2F,0xAE,
+    0x66,0x72,0x26,0x72,0x8F,0x22,0x00,0x28,0xA8,0x7A,0x46,0x72,0xD5,0xD5,0x35,0x2E,
+    0xC8,0x82,0x87,0x7A,0x35,0xA7,0xEA,0xA8,0xC8,0x82,0x26,0x72,0xA0,0xAA,0xFA,0x7F,
+    0x87,0x7A,0x05,0x6A,0xAC,0xFF,0x7F,0x75,0x26,0x72,0xE5,0x61,0x78,0xA8,0xF2,0xFA,
+    0x25,0x6A,0xE5,0x69,0xDF,0x3F,0xBD,0x62,0x05,0x6A,0xE5,0x61,0x8E,0x88,0x90,0xB0,
+    0x26,0x6A,0xE5,0x69,0xDD,0xF7,0xF3,0xAE,0x27,0x72,0xC4,0x61,0xF7,0xFF,0xBF,0x2E,
+    0x26,0x72,0xC5,0x61,0x9A,0xDE,0xAA,0x02,0x26,0x72,0xC5,0x59,0x7E,0x7A,0xFE,0xEA,
+    0xC5,0x61,0x24,0x49,0x7C,0x7A,0xF8,0xE8,0x45,0x49,0xA2,0x30,0x5E,0x5E,0xF8,0xF8,
+    0xC3,0x30,0x61,0x28,0xDF,0x9F,0xBC,0x20,0xA2,0x30,0x82,0x28,0x02,0xFE,0x88,0x88,
+    0xE3,0x38,0x81,0x28,0x2B,0x2F,0xBD,0xB9,0x24,0x41,0xC2,0x30,0xE2,0xAF,0x29,0xBD,
+    0x03,0x39,0xC2,0x30,0xF8,0x78,0x7C,0x7A,0xC2,0x30,0x82,0x30,0xBC,0x2E,0x3E,0xFC,
+    0x23,0x41,0xA2,0x30,0x2B,0x2D,0x8D,0x3F,0x44,0x41,0x03,0x41,0x3F,0xB2,0xA2,0x80,
+    0x65,0x49,0x24,0x41,0xC2,0x8A,0xCB,0x5D,0x64,0x49,0x24,0x41,0x5F,0x7B,0xEF,0x8D,
+    0x64,0x49,0x24,0x41,0xDA,0x56,0x5E,0x7E,0x24,0x41,0x03,0x41,0x50,0x7A,0x78,0x0A,
+    0x24,0x41,0xE3,0x38,0xAE,0xAF,0xBE,0xFC,0x65,0x49,0x03,0x39,0xFF,0xFF,0xCF,0xA9,
+    0x24,0x41,0xA2,0x28,0xF8,0xEA,0xF8,0x7A,0xC2,0x30,0x82,0x28,0xA2,0x8A,0xAF,0xED,
+    0xC2,0x30,0x82,0x28,0x3A,0x5E,0x55,0x5F,0x04,0x39,0x82,0x28,0x82,0xFA,0xFD,0x75,
+    0xC3,0x30,0xA2,0x30,0x00,0x02,0xE3,0x85,0x03,0x39,0xC3,0x30,0x15,0xFD,0xBD,0x1D,
+    0x04,0x39,0xC3,0x30,0x20,0xA2,0x7E,0x57,0xE3,0x38,0xA2,0x28,0xE8,0xFE,0xFF,0xF7,
+    0xC2,0x30,0xA2,0x28,0xA0,0x1E,0x36,0xBA,0xE3,0x30,0xA2,0x28,0xEC,0xFF,0xBB,0xBA,
+    0x03,0x39,0xA2,0x28,0xDF,0xF7,0xF5,0x3B,0x03,0x39,0xC3,0x30,0x25,0x25,0xAF,0xBF,
+    0x23,0x39,0xC2,0x30,0x2B,0xAA,0xEA,0x7F,0x24,0x39,0xC2,0x30,0x88,0xE2,0xFF,0x75,
+    0x03,0x39,0xA2,0x30,0xA2,0xEA,0xEA,0xF7,0xE3,0x38,0xC2,0x30,0xF8,0xF0,0x2A,0x07,
+    0x04,0x39,0xC3,0x30,0xDA,0xFE,0xF7,0x5F,0x03,0x39,0xC3,0x38,0xBF,0xFF,0x3F,0x35,
+    0x64,0x49,0xE3,0x38,0xBF,0xF5,0xBD,0x3F,0x85,0x51,0x24,0x41,0xFF,0xB5,0x2F,0x2A,
+    0x85,0x49,0x23,0x41,0xFE,0xF8,0xEC,0x60,0x44,0x49,0x03,0x41,0xAA,0xEE,0x76,0x7B,
+    0x65,0x49,0x03,0x39,0x0A,0x2B,0x2B,0xB5,0x85,0x51,0x23,0x41,0xE8,0x5F,0xDE,0x7F,
+    0x44,0x49,0x03,0x39,0xAA,0x70,0xF8,0xFF,0x23,0x41,0xE3,0x38,0xA0,0xB8,0xF6,0x5F,
+    0x23,0x41,0xC2,0x30,0x78,0xFA,0x7B,0xFB,0x03,0x39,0xC2,0x30,0x2B,0xA5,0xFD,0x5F,
+    0x23,0x41,0xC2,0x30,0x8A,0xAB,0x9F,0xF5,0x02,0x39,0xC2,0x30,0x5C,0xDF,0xFE,0x7E,
+    0x03,0x31,0xA1,0x30,0x22,0xBF,0xBF,0xF9,0x23,0x39,0xC2,0x30,0xA7,0x3E,0x02,0x8F,
+    0x44,0x41,0x03,0x39,0xB7,0x37,0x35,0x9D,0x44,0x41,0x03,0x39,0x5E,0x5C,0x58,0xFE,
+    0x64,0x49,0x03,0x39,0xAD,0x2D,0xAD,0xFD,0x43,0x49,0x23,0x41,0xA5,0xA6,0xE8,0x7D,
+    0x85,0x51,0xE2,0x38,0x2A,0x3F,0xB7,0x95,0xC6,0x51,0x64,0x51,0xFD,0xB2,0xBB,0xB9,
+    0x06,0x62,0xA5,0x51,0xBD,0xAD,0x2F,0x2F,0x47,0x6A,0xC5,0x61,0xBF,0xA7,0x27,0x8F,
+    0xA8,0x7A,0x06,0x6A,0x5E,0x7E,0xEB,0x83,0x47,0x6A,0xE5,0x61,0x3B,0x76,0xD7,0xF8,
+    0x67,0x72,0x26,0x6A,0xFD,0xF5,0x1F,0xF7,0xCC,0x9B,0x47,0x72,0x2D,0x35,0x35,0xB5,
+    0x72,0xCD,0x2E,0xAC,0x0B,0x0B,0x0B,0x29,0x93,0xD5,0xF1,0xBC,0xC0,0xE0,0x60,0x70,
+    0xF1,0xBC,0x4F,0xAC,0xDC,0xBE,0xBF,0xF7,0x53,0xC5,0x90,0xAC,0x0B,0xAB,0xFF,0x5D,
+    0x52,0xC5,0xED,0x9B,0x20,0xB2,0xFE,0x7F,0xD0,0xB4,0x0E,0x9C,0xE8,0xFA,0x7F,0x5D,
+    0x4F,0xA4,0xCD,0x9B,0x88,0xE8,0x7F,0x5F,0x0E,0xA4,0x8D,0x93,0xE8,0xFA,0xD7,0xDF,
+    0xAD,0x93,0x8C,0x8B,0x00,0x82,0xA2,0xD6,0xCD,0x93,0x8C,0x8B,0xFF,0x5F,0x7E,0x78,
+    0xAD,0x93,0x6C,0x8B,0x36,0xAE,0xAE,0xAE,0xEE,0x9B,0x6C,0x8B,0x82,0x8A,0xAF,0xA7,
+    0xEE,0x9B,0x8C,0x8B,0xEF,0xB9,0xAB,0xE0,0x2F,0xA4,0x8C,0x8B,0xAB,0x0A,0xBB,0xDF,
+    0x0E,0x9C,0xCD,0x93,0x72,0x68,0x8A,0x6B,0xED,0x9B,0x6C,0x83,0x82,0xA8,0xFA,0x5E,
+    0xCD,0x93,0x4B,0x83,0xE8,0xEA,0x7B,0x5F,0x4F,0xA4,0x4B,0x83,0x2F,0x2D,0x2D,0xB5,
+    0x90,0xAC,0x2E,0xA4,0x55,0xFA,0xEB,0x8F,0xAF,0xB4,0x4F,0xA4,0xA7,0x3F,0xBF,0xBE,
+    0x32,0xBD,0xB0,0xAC,0xEF,0xFF,0x29,0xA5,0x53,0xC5,0x11,0xBD,0xF5,0x95,0xF5,0x2D,
+    0x43,0x51,0x23,0x51,0x58,0x7F,0x3F,0xD5,0x64,0x59,0x03,0x51,0xAE,0x7F,0xEF,0x83,
+    0x44,0x51,0x02,0x49,0xFC,0xBF,0xFF,0xDA,0x23,0x51,0x03,0x49,0xBA,0x50,0x58,0x73,
+    0x02,0x49,0xC2,0x40,0xA8,0xA4,0x3A,0x02,0x43,0x51,0xE2,0x40,0xDF,0x7B,0xFA,0xCF,
+    0x44,0x51,0x03,0x49,0xB5,0x25,0x35,0xFF,0x44,0x51,0x23,0x49,0xBB,0xFA,0x62,0x77,
+    0x64,0x51,0x23,0x51,0xDA,0xEA,0xE2,0x59,0x44,0x51,0x02,0x51,0xEA,0x80,0x8A,0xFB,
+    0x43,0x51,0x03,0x49,0xFB,0xAE,0x8F,0x06,0x64,0x59,0x23,0x51,0xED,0x85,0xBD,0x3A,
+    0x64,0x59,0x23,0x51,0xEF,0xA8,0x92,0xA6,0x84,0x61,0x23,0x51,0xFF,0xF3,0x6F,0x65,
+    0x84,0x59,0x23,0x51,0xFF,0xEE,0xCB,0xA9,0x64,0x59,0x23,0x51,0xFE,0xAB,0xC5,0xD5,
+    0x44,0x59,0x03,0x51,0xEA,0x62,0x6A,0x94,0x23,0x59,0x02,0x49,0xFF,0xED,0xAA,0xAA,
+    0xA4,0x61,0x02,0x51,0xBD,0x35,0x27,0x3D,0x8B,0x9B,0x26,0x72,0x29,0x09,0x0B,0x2B,
+    0x8A,0x9B,0x4A,0x93,0xC0,0x82,0xA0,0x92,0x6A,0x9B,0x09,0x8B,0x00,0x82,0xE2,0x6A,
+    0x2A,0x93,0x87,0x7A,0x80,0xE8,0x7A,0x76,0x09,0x8B,0x67,0x72,0xF8,0xFF,0x77,0x7D,
+    0xA8,0x7A,0x46,0x72,0xFC,0xD8,0xEA,0xBF,0x87,0x7A,0x26,0x72,0xAE,0xEB,0xDE,0xE4,
+    0x45,0x82,0x67,0x72,0x5F,0xDD,0xD7,0x75,0x87,0x7A,0x46,0x72,0xA6,0x82,0xF8,0x8D,
+    0x87,0x7A,0x46,0x72,0xBC,0x8A,0xB0,0x1A,0x87,0x7A,0x46,0x72,0x6F,0x8F,0xBE,0xFF,
+    0x87,0x7A,0x67,0x72,0x75,0xB7,0x6E,0xF2,0x66,0x72,0x25,0x72,0xA8,0x10,0xAC,0x0F,
+    0x67,0x7A,0x46,0x72,0x65,0x7F,0xA3,0xBA,0x66,0x72,0x26,0x6A,0xDF,0xBA,0x68,0x6A,
+    0x66,0x72,0x25,0x72,0xAE,0x3E,0x32,0x2A,0xC8,0x82,0x67,0x7A,0xA5,0xA7,0x2F,0x6B,
+    0xA8,0x82,0x25,0x6A,0x80,0xA8,0xFE,0x55,0x67,0x7A,0xC4,0x69,0xE0,0xE0,0xFB,0xFF,
+    0x25,0x6A,0xE5,0x69,0xEE,0x62,0x7A,0x5E,0x05,0x6A,0xC5,0x61,0x30,0xBA,0xBF,0xFD,
+    0x26,0x6A,0xC4,0x61,0x2A,0xFF,0xFF,0x7E,0x06,0x6A,0xC5,0x61,0xBE,0xEB,0xAE,0x9F,
+    0x26,0x6A,0xE5,0x69,0xFF,0xBB,0x8B,0xAF,0x46,0x72,0x06,0x6A,0xD5,0xFF,0xEA,0xFD,
+    0x47,0x72,0x06,0x6A,0xF9,0xA9,0xAD,0xAF,0x47,0x72,0xE6,0x69,0x6E,0x7A,0xA8,0x22,
+    0x26,0x6A,0x64,0x51,0x7E,0x7A,0x78,0x68,0x44,0x49,0xC3,0x38,0xD8,0x7B,0x7A,0x78,
+    0xE3,0x38,0x82,0x30,0xC2,0xCA,0x7A,0x7E,0xA2,0x30,0x81,0x28,0xC2,0x63,0xFA,0xAB,
+    0xC1,0x30,0x82,0x28,0xAD,0xBD,0xF7,0xFF,0x03,0x41,0xA2,0x30,0xAB,0x2A,0x0F,0x39,
+    0x03,0x39,0xE3,0x38,0x5F,0x96,0xD4,0x7E,0xE2,0x38,0xA2,0x30,0x56,0x74,0xAA,0xE2,
+    0x64,0x49,0xA2,0x30,0xB5,0x29,0x2B,0x2B,0x44,0x49,0xE3,0x38,0xEA,0xE0,0xE0,0x60,
+    0x03,0x41,0xE3,0x38,0x20,0x96,0x3E,0x76,0x65,0x49,0xE3,0x38,0x2A,0xFE,0xEF,0xF5,
+    0x64,0x49,0xE3,0x38,0xEC,0xFB,0xFF,0xD7,0x24,0x41,0xC2,0x30,0x08,0x80,0xBC,0x57,
+    0x23,0x41,0xC3,0x30,0xBE,0xF6,0xAF,0x2B,0x44,0x41,0xC3,0x30,0x2A,0xAB,0x8E,0x5E,
+    0x04,0x39,0xA2,0x28,0x78,0x5C,0x7E,0x5F,0xE3,0x28,0x82,0x28,0xF5,0xBF,0xFF,0xD7,
+    0xA2,0x28,0x61,0x20,0xE0,0xE0,0xF0,0xE6,0xA2,0x28,0x61,0x20,0x0F,0xBD,0xBD,0x0B,
+    0xE3,0x30,0xA2,0x28,0xD5,0xBD,0xBD,0x8A,0xE3,0x30,0xA2,0x28,0x82,0xEA,0x7A,0x68,
+    0x81,0x30,0xC2,0x28,0xFF,0xFA,0xEB,0x7A,0xC2,0x30,0xA2,0x28,0xBF,0xB5,0x25,0x05,
+    0xE3,0x30,0xA2,0x28,0xA3,0xFB,0xAF,0x27,0xC2,0x30,0xA2,0x28,0xAE,0xCF,0x88,0x08,
+    0xE3,0x30,0xC3,0x30,0x02,0xA9,0x75,0x2D,0x04,0x39,0xC2,0x30,0xDF,0x8B,0xEB,0xDF,
+    0xC3,0x38,0xE3,0x30,0xFD,0xF5,0xFF,0xAD,0x04,0x39,0xC2,0x30,0x5F,0x7D,0xAD,0x2B,
+    0xE3,0x38,0xC2,0x30,0x55,0x61,0x5B,0xF8,0xE3,0x38,0xC2,0x30,0x29,0x81,0xD7,0xF2,
+    0xE3,0x38,0xC2,0x30,0xD6,0x7F,0x89,0x2B,0x03,0x39,0xC3,0x30,0x15,0x15,0xDA,0xF2,
+    0x85,0x51,0xE3,0x38,0xAD,0x2F,0x2D,0xBD,0x85,0x51,0x65,0x49,0x55,0x7F,0xF2,0x7B,
+    0x85,0x51,0x23,0x41,0xE2,0xE2,0xEA,0x62,0x44,0x49,0x03,0x39,0xF2,0x48,0x4A,0x7B,
+    0x23,0x41,0xE2,0x38,0x2F,0x2F,0xE7,0xF7,0x44,0x49,0x24,0x41,0x72,0x6A,0x53,0x95,
+    0x23,0x41,0xC2,0x38,0xFA,0xDF,0xEE,0xBA,0x03,0x41,0xC2,0x30,0x7E,0xEA,0xAA,0xA8,
+    0x03,0x39,0xC2,0x30,0x0F,0xB5,0xD5,0xBB,0x03,0x39,0xC2,0x30,0x7E,0xD7,0xF6,0xCA,
+    0x03,0x39,0xC2,0x30,0x3F,0x3E,0x27,0x2E,0x23,0x39,0xE2,0x30,0x77,0xFF,0xAB,0xBC,
+    0x23,0x39,0xC2,0x30,0xFD,0x7E,0x78,0xF8,0x23,0x39,0xC2,0x30,0x8B,0x0F,0x2D,0x2B,
+    0x23,0x39,0x03,0x39,0xD3,0x2F,0xFD,0x9B,0x23,0x39,0xE2,0x38,0xF8,0xF0,0xE8,0x6A,
+    0x23,0x41,0xC2,0x30,0x02,0x8A,0x0B,0x89,0x43,0x41,0x03,0x39,0x9F,0xB5,0xA5,0x2B,
+    0x44,0x49,0x03,0x39,0x35,0xBB,0xAA,0xA3,0xA5,0x59,0x44,0x49,0x3F,0x3D,0xDD,0x37,
+    0x26,0x62,0x85,0x51,0xB7,0xBF,0x97,0x37,0x67,0x72,0x06,0x62,0xCD,0xED,0xA5,0xBE,
+    0x88,0x72,0x46,0x6A,0xA9,0x29,0xED,0xF5,0x87,0x72,0xE5,0x61,0xFA,0xE8,0xE8,0x5A,
+    0x47,0x6A,0xC5,0x59,0xA0,0xEE,0x7E,0x5E,0x6B,0x93,0xE5,0x61,0x3F,0x3D,0xBD,0xB5,
+    0x73,0xCD,0xED,0xA3,0x2B,0x09,0x29,0x09,0x93,0xD5,0x6F,0xAC,0xE0,0x70,0x78,0x78,
+    0xB0,0xB4,0x4F,0xAC,0xAF,0x37,0x7F,0x7D,0x90,0xAC,0xED,0x9B,0xA0,0xA8,0xFA,0xD7,
+    0x4F,0xA4,0xEE,0x9B,0xC2,0x7F,0x57,0x77,0x0E,0x9C,0xAD,0x93,0xA2,0xEA,0xF2,0x5E,
+    0xEE,0x9B,0xAD,0x93,0x7E,0x6A,0x7A,0x54,0xAD,0x93,0x6D,0x8B,0xB0,0xE8,0xA2,0xA0,
+    0xAD,0x93,0x6C,0x8B,0xEA,0xEA,0x8B,0x0F,0xCD,0x93,0x8C,0x8B,0x7D,0xA9,0x7D,0x5E,
+    0xAD,0x93,0x6C,0x8B,0xB6,0xEF,0xAA,0x22,0xCD,0x93,0x8C,0x8B,0x05,0x0D,0xFF,0xFF,
+    0x0E,0x9C,0x8C,0x8B,0x82,0xBA,0x5B,0x7F,0xAD,0x93,0x0A,0x7B,0x20,0x88,0xA8,0x5E,
+    0xCD,0x93,0x2B,0x7B,0x00,0xAA,0x6F,0x75,0x8C,0x83,0x0A,0x7B,0xBC,0xFE,0x7F,0xD7,
+    0x6C,0x83,0x0B,0x7B,0xBC,0xB7,0xFD,0xB5,0xAD,0x93,0x0B,0x7B,0x2F,0xBF,0xBF,0x55,
+    0x4F,0xAC,0x6C,0x8B,0x0A,0x2F,0xFF,0x55,0x6F,0xAC,0xAD,0x8B,0x20,0x8A,0xAF,0xBD,
+    0x11,0xBD,0x0E,0x9C,0x2B,0x2B,0xBF,0xB5,0x32,0xC5,0x90,0xAC,0x02,0x00,0x0E,0xA5,
+    0x43,0x51,0x02,0x49,0x98,0xE0,0xEC,0xBF,0x64,0x51,0x02,0x49,0x8B,0xF9,0xFF,0xBF,
+    0x43,0x51,0x02,0x49,0x6B,0xF2,0x5A,0x5B,0x23,0x49,0xE1,0x40,0xF8,0xBA,0xAD,0x82,
+    0x23,0x49,0xE2,0x48,0xA3,0x00,0xA2,0x9E,0x44,0x51,0x03,0x49,0x6F,0xD6,0xA7,0x25,
+    0x43,0x51,0x02,0x49,0xF5,0x09,0x36,0xAA,0x64,0x51,0x23,0x49,0xEF,0xBE,0x7A,0x78,
+    0x44,0x51,0x03,0x49,0xBB,0x7E,0x56,0xDA,0x43,0x51,0x03,0x49,0xFF,0xFF,0xBE,0xB7,
+    0x64,0x59,0x02,0x49,0x2F,0x27,0xA3,0xAA,0x64,0x59,0x23,0x51,0xA0,0xF7,0xE5,0x77,
+    0x64,0x59,0x03,0x49,0xBE,0xAF,0xAF,0x8F,0x44,0x59,0x03,0x51,0xAE,0xEE,0xF4,0xAC,
+    0x44,0x59,0x23,0x51,0x01,0xEA,0x0B,0x09,0x44,0x59,0xE2,0x48,0x6E,0xE8,0xE8,0xE8,
+    0x43,0x59,0xE2,0x48,0xEE,0xE2,0xFB,0xDF,0x23,0x51,0x03,0x51,0x21,0xDB,0xFA,0xFD,
+    0x26,0x72,0x23,0x51,0x95,0xB5,0x35,0x35,0x4A,0x9B,0x87,0x82,0x01,0x0B,0x09,0x03,
+    0x6A,0x9B,0x09,0x93,0x2A,0xFA,0xFA,0x7E,0x6A,0x9B,0x87,0x7A,0xA8,0xEE,0x7E,0x7E,
+    0xC8,0x7A,0x67,0x7A,0xF8,0xFE,0xEC,0xD6,0x87,0x7A,0x46,0x72,0xBE,0xBC,0x7E,0x62,
+    0x87,0x7A,0x47,0x72,0xBF,0xB2,0xFA,0xFF,0x87,0x7A,0x26,0x72,0x28,0xEA,0x35,0x0B,
+    0x87,0x7A,0x46,0x72,0x48,0x2A,0xFA,0xFA,0x87,0x7A,0x26,0x72,0x0B,0x8A,0x8A,0xA7,
+    0x87,0x7A,0x25,0x72,0xB8,0xB6,0xB6,0xEA,0x87,0x7A,0x46,0x72,0xFC,0xFF,0xFF,0x1E,
+    0x87,0x7A,0x46,0x72,0xC9,0x63,0x78,0x6B,0x87,0x72,0x25,0x72,0x2F,0xEF,0xFE,0x7F,
+    0x66,0x7A,0x26,0x6A,0xB3,0xEF,0xCB,0x8B,0x67,0x7A,0x46,0x72,0xB7,0xCF,0xAF,0x22,
+    0x87,0x7A,0x46,0x72,0x89,0xAA,0x23,0xAD,0xA7,0x7A,0x46,0x72,0xA3,0xEA,0xFB,0xFD,
+    0x67,0x72,0x05,0x6A,0x5E,0x58,0xFE,0x7A,0x26,0x72,0xE5,0x69,0x77,0x56,0x55,0x89,
+    0x06,0x6A,0xC5,0x61,0xFE,0x8E,0xFB,0x7E,0x05,0x6A,0xC5,0x61,0xEA,0x5C,0x55,0x55,
+    0x05,0x6A,0xC5,0x61,0xE2,0xA2,0xF9,0xFF,0x05,0x6A,0xC4,0x61,0xB7,0xBF,0xBF,0xBF,
+    0x05,0x6A,0xE5,0x61,0x27,0x18,0x08,0x0F,0x66,0x72,0x06,0x6A,0x5F,0xF3,0xFD,0xFD,
+    0x47,0x72,0x06,0x6A,0xBF,0xFE,0x6B,0x2A,0x47,0x72,0x26,0x6A,0xEB,0xAA,0x2E,0xAA,
+    0x26,0x6A,0xA4,0x59,0x70,0xE0,0x00,0x00,0xE5,0x61,0xE2,0x38,0x5F,0x7A,0x78,0xF0,
+    0xE2,0x38,0x82,0x28,0xFA,0xFC,0xFA,0x78,0xA2,0x30,0x81,0x28,0xC3,0x8A,0x0F,0x3F,
+    0xE2,0x30,0x81,0x28,0xBD,0x2D,0x0B,0x2A,0x02,0x39,0xA1,0x30,0x3A,0x3E,0xFA,0xDA,
+    0x03,0x39,0xC2,0x38,0xFA,0xFE,0xBF,0xA1,0x03,0x39,0xC2,0x38,0x5F,0xD4,0xD6,0xFB,
+    0x64,0x49,0xC2,0x38,0xA9,0x2D,0x2D,0x89,0x65,0x49,0xE2,0x38,0x70,0x6A,0xF0,0x7E,
+    0x03,0x39,0xC2,0x30,0x5E,0xEA,0xFA,0x7A,0x03,0x39,0xC2,0x30,0x29,0xEE,0xBB,0xA5,
+    0x24,0x41,0xC2,0x30,0xAE,0xCB,0x57,0x55,0xE3,0x38,0xA2,0x28,0xAA,0xBA,0xFA,0xFF,
+    0x24,0x41,0xC2,0x30,0x2B,0x2D,0xAB,0xAD,0x24,0x39,0xA2,0x28,0x78,0xF8,0xFE,0xFE,
+    0xE3,0x30,0x82,0x28,0xF2,0xF8,0xFC,0x7F,0xA2,0x28,0x62,0x20,0xEC,0xF6,0xFF,0xF7,
+    0x63,0x28,0xA2,0x20,0xBE,0xFA,0xEB,0x6E,0xE3,0x30,0x82,0x28,0xB5,0x2D,0x2F,0x3F,
+    0x04,0x39,0xA2,0x28,0xAA,0xA0,0x72,0x6A,0xC3,0x28,0x82,0x28,0x80,0xAA,0xFB,0xF7,
+    0xA2,0x28,0x82,0x20,0x2B,0x2F,0xBA,0x2C,0xC2,0x28,0xA2,0x28,0xE5,0xD5,0xAD,0xF9,
+    0xE3,0x30,0xA2,0x28,0xFF,0xFB,0x3E,0x29,0xE3,0x30,0xA2,0x28,0x0E,0x2F,0x2C,0xAA,
+    0xE3,0x30,0xC2,0x30,0xBF,0x0B,0xEA,0x6A,0xE3,0x38,0xA2,0x28,0x2E,0xAF,0xFF,0xFF,
+    0xE3,0x30,0xA2,0x30,0x08,0x8A,0xAB,0x2F,0x03,0x39,0xE3,0x30,0xAF,0xFB,0xF7,0xFE,
+    0xE3,0x38,0xC3,0x30,0xF8,0xEC,0xCA,0x70,0x24,0x39,0xC2,0x30,0xFB,0xCB,0x79,0x75,
+    0xE3,0x38,0xC3,0x30,0x37,0xB5,0xD5,0x35,0x03,0x39,0xC3,0x30,0xA2,0xBF,0xBF,0xF7,
+    0x44,0x41,0xE3,0x38,0x0D,0x3D,0x9F,0xDF,0x44,0x49,0xE3,0x38,0x02,0xA3,0xBF,0x7D,
+    0x64,0x49,0x03,0x39,0xE2,0xFF,0xD7,0xDD,0x24,0x41,0xE3,0x38,0xAE,0xFE,0xBA,0xF9,
+    0x03,0x39,0xA2,0x38,0xB8,0xA8,0xA8,0x88,0x23,0x41,0xE3,0x38,0x2A,0xAF,0xAB,0xAB,
+    0x03,0x41,0xE3,0x38,0xA5,0xAA,0xEB,0x62,0x44,0x41,0xE2,0x38,0x77,0xAF,0x0F,0xEE,
+    0x03,0x39,0xA2,0x30,0x9A,0x98,0xA0,0xE2,0x03,0x39,0xC2,0x30,0xE8,0xFA,0xA7,0xD5,
+    0x03,0x39,0xC2,0x30,0xAC,0x7E,0x17,0x95,0x03,0x39,0xE2,0x30,0xE0,0xAD,0x2D,0x2E,
+    0x23,0x39,0xC2,0x30,0xDB,0x7F,0xFE,0xE8,0x23,0x39,0xC2,0x30,0x2F,0x0D,0xBF,0xEF,
+    0x64,0x41,0x03,0x39,0x66,0xEA,0xA3,0x8D,0x43,0x41,0xE2,0x30,0x7F,0xEA,0xAA,0xF8,
+    0x43,0x41,0xE2,0x30,0x2D,0x35,0xFB,0xFF,0x64,0x49,0x02,0x39,0xAE,0x2B,0x01,0x2B,
+    0x84,0x51,0x23,0x41,0xAD,0xBE,0x2E,0x08,0xA5,0x51,0x64,0x49,0x96,0xF2,0xE0,0x82,
+    0x26,0x62,0x84,0x51,0x37,0xED,0xF5,0x57,0x26,0x6A,0x84,0x51,0x80,0xE2,0xFB,0x7E,
+    0x47,0x6A,0x84,0x51,0x82,0xAB,0xF7,0xD5,0x26,0x6A,0xC5,0x59,0xF8,0xFE,0x7F,0xAD,
+    0x06,0x62,0xA4,0x59,0xA8,0xFF,0x9D,0xAD,0xC9,0x7A,0xE6,0x61,0x15,0x35,0x9D,0xF5,
+    0x52,0xCD,0xEA,0x7A,0x0B,0x0B,0x09,0x2D,0x52,0xCD,0x8F,0xAC,0x78,0x78,0x78,0x58,
+    0xB0,0xB4,0x4E,0xA4,0x6B,0x70,0xC2,0xA8,0x4F,0xAC,0xAD,0x8B,0xFE,0xFE,0x5E,0x7C,
+    0xEE,0x9B,0x8C,0x8B,0x0A,0xA7,0xD5,0x57,0xCD,0x93,0x6C,0x8B,0xA8,0xEB,0xED,0xFF,
+    0xCD,0x93,0x6C,0x8B,0xBC,0xBC,0xAE,0xA9,0xCD,0x93,0x8D,0x8B,0xFB,0x7E,0xAB,0x2A,
+    0xCE,0x93,0x8C,0x8B,0xE5,0xFD,0xBF,0x3F,0xEE,0x9B,0x8C,0x8B,0xDF,0x75,0xB5,0xAE,
+    0xCD,0x93,0x8C,0x8B,0xED,0x8B,0x00,0xA0,0xAC,0x8B,0x4C,0x83,0xA2,0x68,0xAA,0x7B,
+    0xAC,0x8B,0x2B,0x7B,0x8A,0x6A,0xEA,0x7F,0x4B,0x83,0xEA,0x72,0xB0,0xD0,0xF8,0xEE,
+    0x2B,0x7B,0xEA,0x72,0x8A,0xF6,0xA6,0x15,0x2B,0x7B,0xEA,0x72,0x28,0xB0,0x92,0xB5,
+    0x4C,0x83,0xEA,0x72,0x2E,0xA9,0x5F,0x5F,0x4B,0x83,0xC9,0x72,0xE8,0xFA,0xFE,0xFB,
+    0x8C,0x8B,0xEA,0x7A,0x2F,0x2D,0x2B,0x2F,0xCD,0x93,0x6C,0x8B,0x3F,0x95,0x77,0xFF,
+    0x2E,0xA4,0x8D,0x8B,0x0A,0x2F,0x35,0xAD,0xD1,0xB4,0x0E,0x9C,0x0B,0xBD,0xFF,0x75,
+    0x43,0x51,0xE3,0x48,0x8E,0xA9,0xAA,0xBA,0x43,0x51,0x23,0x49,0xE5,0x5F,0x5F,0x7E,
+    0x23,0x49,0xE2,0x40,0xAB,0xAA,0x9A,0x8E,0x44,0x51,0xE1,0x40,0x8F,0xEB,0x7F,0xFF,
+    0x43,0x51,0xE1,0x40,0x2F,0x0B,0x2F,0xBD,0x43,0x51,0x02,0x49,0x2E,0xAC,0xAE,0xE6,
+    0x43,0x51,0x02,0x49,0x08,0xAE,0xD6,0x7D,0x43,0x51,0xE2,0x40,0xE0,0x9A,0xFB,0xFB,
+    0x43,0x51,0x02,0x49,0xEA,0xBB,0x7D,0x2D,0x64,0x59,0x02,0x49,0x3B,0xB9,0x89,0xA2,
+    0x64,0x59,0x23,0x51,0xAB,0xEE,0xF7,0x76,0x43,0x51,0x23,0x51,0xD4,0xDB,0xC2,0x03,
+    0x44,0x59,0x23,0x51,0xAD,0xAD,0x31,0x3F,0x44,0x51,0x03,0x51,0xB8,0x9C,0xDA,0xE8,
+    0x43,0x51,0x03,0x51,0xDA,0xD3,0x7A,0xFA,0x44,0x59,0x03,0x51,0xB8,0xEA,0x7B,0xDF,
+    0xE3,0x50,0x02,0x49,0xF7,0xFC,0x57,0x77,0x23,0x51,0xE3,0x48,0x8F,0xFA,0xEE,0xF2,
+    0x67,0x7A,0x03,0x51,0x35,0x3D,0x35,0x35,0x6B,0x9B,0xC9,0x8A,0x29,0x09,0x2B,0xAB,
+    0x4A,0x93,0xC8,0x8A,0x62,0xFA,0xE8,0x6F,0xC8,0x82,0x88,0x7A,0xE0,0xE8,0xFA,0xAC,
+    0xA8,0x7A,0x67,0x7A,0xD8,0xF2,0xEA,0xBA,0xA7,0x7A,0x67,0x7A,0x5F,0xFE,0x68,0xEC,
+    0x87,0x7A,0x46,0x72,0x6A,0x62,0xCA,0xA2,0x87,0x7A,0x47,0x72,0xE9,0xBE,0x3B,0xF9,
+    0x87,0x7A,0x46,0x72,0xEB,0x70,0xE0,0xE8,0x87,0x7A,0x46,0x72,0x3A,0xC0,0xFA,0x3F,
+    0x87,0x7A,0x46,0x72,0xEC,0xEE,0xA6,0xFF,0x87,0x7A,0x46,0x72,0xAE,0xEB,0xAD,0xBF,
+    0x87,0x72,0x25,0x6A,0xF2,0x6E,0xFA,0xFA,0x87,0x72,0x25,0x72,0xFF,0xFC,0xEE,0xFD,
+    0x66,0x72,0x25,0x6A,0xDF,0xAA,0xAA,0xE8,0x86,0x7A,0x25,0x72,0xE6,0xEB,0xAB,0x3F,
+    0xA7,0x7A,0x26,0x6A,0xE9,0xAF,0xAA,0x2A,0x87,0x7A,0x26,0x72,0xA2,0xE8,0x78,0xD2,
+    0x46,0x72,0xE5,0x61,0xE8,0xE8,0xE8,0x7A,0x06,0x6A,0xC5,0x61,0x00,0xFE,0xD7,0x72,
+    0xE5,0x69,0x84,0x61,0xEC,0xFE,0x7E,0xFB,0xE5,0x61,0x84,0x59,0xAB,0xA7,0x2D,0x2E,
+    0x05,0x6A,0xC5,0x61,0xF6,0xE5,0xEF,0x5A,0xE5,0x69,0xC5,0x61,0x96,0x2F,0xAE,0x57,
+    0x26,0x6A,0xC4,0x61,0xAF,0x0F,0x8F,0xB9,0x46,0x72,0x05,0x6A,0xED,0xF5,0x7D,0xC5,
+    0x46,0x72,0x05,0x6A,0xAA,0x82,0x03,0xA3,0x46,0x72,0x26,0x6A,0x0C,0x80,0xFB,0x1F,
+    0x66,0x72,0xE4,0x61,0xBA,0x72,0xFC,0x5E,0x06,0x62,0x03,0x41,0xF8,0x78,0xE8,0x7C,
+    0x03,0x41,0x81,0x28,0x5C,0x5A,0x5C,0x56,0xA2,0x30,0x81,0x28,0x17,0xB7,0xB7,0x1F,
+    0xC2,0x30,0xA2,0x28,0x0B,0x06,0x0A,0x83,0x02,0x39,0xC2,0x30,0x55,0xD5,0xFD,0x2F,
+    0x23,0x41,0xE2,0x38,0xE5,0xBD,0x09,0x0B,0x44,0x41,0xE2,0x38,0x55,0xF5,0xBF,0x02,
+    0x44,0x49,0xE2,0x38,0x29,0xEB,0xAA,0x08,0x23,0x41,0xC2,0x30,0xC0,0xF2,0x78,0x7C,
+    0x03,0x39,0xA2,0x30,0x72,0x7E,0x5F,0x77,0xE3,0x38,0xA2,0x30,0x8B,0xFB,0x55,0x55,
+    0xC2,0x30,0xA2,0x28,0x0A,0x02,0xEF,0x55,0xE3,0x30,0xA2,0x28,0x3F,0xAD,0xBB,0xBD,
+    0x23,0x39,0xC3,0x28,0xEF,0xFF,0xD5,0xD5,0xE3,0x30,0x82,0x28,0xA8,0xE8,0xFE,0xDC,
+    0xC2,0x28,0x62,0x20,0xEA,0xFC,0x77,0xD6,0x82,0x20,0x61,0x20,0x3F,0x2A,0x0A,0xBA,
+    0x61,0x30,0x82,0x20,0x5F,0x55,0x7D,0x55,0xE3,0x30,0x82,0x20,0xAF,0xEF,0xA9,0xAF,
+    0xE3,0x30,0x82,0x28,0xEA,0x62,0xFA,0xFB,0xA2,0x28,0x82,0x20,0xE7,0x55,0xF7,0x08,
+    0xE3,0x30,0x82,0x20,0xFD,0xED,0xBB,0x2B,0xE3,0x30,0x81,0x20,0xDF,0xFF,0xBE,0xA0,
+    0xE3,0x30,0xA2,0x28,0xB5,0xBF,0xAA,0xAA,0xE3,0x30,0xA2,0x28,0xAA,0x7A,0x6E,0xEA,
+    0xE3,0x30,0xA2,0x28,0xE2,0xEF,0x75,0x57,0xC2,0x30,0xA2,0x28,0xF5,0xF9,0x01,0x29,
+    0xE3,0x30,0xA2,0x30,0x0F,0x01,0x0B,0x0F,0x03,0x39,0xC3,0x30,0xBA,0xB3,0xFF,0xFF,
+    0xE3,0x30,0xA2,0x30,0xF0,0xFA,0xFA,0xF6,0xE3,0x38,0xA2,0x30,0x0D,0xBB,0xE2,0xF0,
+    0xE3,0x38,0xA2,0x28,0x0B,0x2E,0xA7,0xB5,0x03,0x39,0xA2,0x30,0xFF,0xF7,0xAE,0x88,
+    0x03,0x39,0xE3,0x38,0x73,0x7B,0xDF,0x98,0x24,0x39,0xE3,0x38,0xA5,0xB5,0xEF,0x7B,
+    0x23,0x41,0xC2,0x30,0xCE,0xFE,0xFF,0x7B,0x03,0x39,0xC2,0x30,0xA3,0xAA,0xEB,0xBF,
+    0xE3,0x48,0x03,0x39,0x5D,0x77,0xF7,0x55,0x23,0x41,0xE3,0x38,0xAA,0x2E,0xA5,0xF5,
+    0x23,0x41,0xC2,0x30,0xA2,0xAA,0xF7,0xFF,0x24,0x41,0xE2,0x38,0xFA,0x3A,0x7B,0x7F,
+    0x44,0x41,0xC2,0x30,0xE2,0xA0,0x7F,0x5F,0x03,0x39,0xC2,0x30,0xBF,0xB6,0xAF,0x2F,
+    0x23,0x41,0xC2,0x30,0xB7,0xAE,0x3B,0x3E,0x44,0x41,0xE2,0x38,0xFF,0x09,0xE5,0xF7,
+    0x43,0x41,0x03,0x39,0x5B,0xFD,0xB5,0xF7,0x23,0x39,0xE2,0x30,0x5F,0xFA,0xFA,0xEB,
+    0x44,0x41,0xE2,0x30,0x29,0xFD,0xFF,0x55,0x44,0x41,0x03,0x39,0x7C,0xBF,0xAF,0xE5,
+    0x23,0x39,0xC2,0x30,0xAA,0xE8,0x7A,0x5C,0x64,0x49,0xC2,0x30,0x0B,0xFF,0xDF,0x7D,
+    0x85,0x51,0xE2,0x38,0x20,0xA3,0xAB,0xF5,0xC5,0x51,0x23,0x41,0xA2,0xE2,0xFF,0x9D,
+    0x84,0x51,0x23,0x41,0x2C,0x3D,0x3D,0x2C,0xC5,0x59,0x64,0x51,0x8A,0x2B,0x9A,0xB5,
+    0xE5,0x59,0x84,0x51,0xB5,0x3D,0x2E,0x2D,0x26,0x62,0xE5,0x59,0xE9,0xB5,0x2B,0x0B,
+    0x46,0x6A,0xC5,0x59,0xF7,0xBE,0xAA,0x2A,0x48,0x6A,0xE5,0x61,0x25,0x2F,0xBA,0xFA,
+    0x90,0xB4,0x89,0x72,0x0D,0x2D,0xB5,0xB5,0xF1,0xBC,0x0E,0xA4,0xE8,0xFE,0xED,0x95,
+    0xB0,0xB4,0x6F,0xAC,0xAA,0xCB,0xFB,0x4A,0x6F,0xAC,0xAC,0x8B,0x58,0x70,0x68,0x68,
+    0x8C,0x8B,0x2B,0x83,0x82,0xEE,0xFE,0x5C,0xAD,0x93,0x4B,0x83,0xCA,0xAB,0xF5,0x2D,
+    0xCD,0x93,0x4B,0x83,0xAD,0xAD,0xAB,0x2A,0xCD,0x93,0x8C,0x8B,0x0B,0x2B,0x2D,0x36,
+    0xEE,0x93,0xAD,0x93,0xF6,0x8A,0xC2,0xFE,0xED,0x93,0x0B,0x7B,0xA8,0xA8,0xEA,0x6A,
+    0xAD,0x8B,0xCA,0x72,0x80,0x8A,0xFB,0x55,0x6C,0x83,0x0A,0x73,0x7A,0xF0,0xFB,0xDD,
+    0x4B,0x83,0xCA,0x6A,0xA2,0x22,0xAE,0xB6,0x4C,0x83,0xCA,0x6A,0xE0,0xAE,0xF0,0x7A,
+    0x0B,0x7B,0xCA,0x72,0xF6,0xDC,0x58,0x7A,0x2A,0x7B,0xCA,0x72,0xF9,0xF7,0x55,0x77,
+    0x4B,0x83,0xEA,0x72,0xDD,0x57,0xBF,0x3B,0x4C,0x83,0xEA,0x72,0xAD,0xAB,0x2A,0xC8,
+    0x6B,0x83,0x0B,0x7B,0x2F,0x97,0xF7,0xBF,0xAD,0x93,0x6C,0x8B,0xFF,0xAB,0x6D,0xF5,
+    0xCE,0x93,0x6C,0x8B,0x0D,0x2F,0xF9,0x7E,0x4F,0xA4,0x6C,0x8B,0x0A,0xAB,0xAF,0xAD,
+    0x43,0x51,0xE1,0x40,0x2A,0xE0,0x4A,0x7A,0x43,0x51,0xE2,0x40,0x8E,0x2B,0xAF,0xE9,
+    0x64,0x51,0x02,0x49,0xFD,0x73,0x5A,0x75,0x23,0x49,0xE1,0x40,0xB2,0x9E,0x6B,0xAB,
+    0x43,0x51,0xE2,0x48,0xE6,0xE7,0xAD,0x3E,0x23,0x49,0x02,0x49,0x80,0x7F,0xA4,0x94,
+    0x43,0x51,0x02,0x49,0xDD,0x9F,0x52,0xE2,0x43,0x51,0xE2,0x40,0x7A,0xF8,0xDA,0xDB,
+    0x64,0x59,0x02,0x49,0xB5,0x2D,0xA9,0xEA,0x64,0x59,0x23,0x51,0xAB,0xA8,0xEB,0xEF,
+    0x64,0x59,0x23,0x51,0xFF,0x7C,0x7D,0x6D,0x43,0x51,0x02,0x49,0x8A,0xF8,0xFF,0x87,
+    0x64,0x51,0x23,0x51,0x7A,0xBF,0xA7,0x7B,0x64,0x59,0x03,0x49,0x2E,0xA8,0xEA,0xDF,
+    0x44,0x51,0x03,0x49,0xB8,0x68,0xEA,0xEA,0x23,0x51,0xE2,0x48,0xAA,0xFF,0xEF,0x0A,
+    0x44,0x51,0x03,0x49,0x7F,0x5E,0x35,0xBF,0x23,0x51,0xE2,0x48,0xFB,0xBF,0x8E,0x8E,
+    0x88,0x7A,0x23,0x51,0x25,0x25,0x3D,0x2D,0x2A,0x93,0xE9,0x8A,0xAB,0xFD,0xA9,0x6B,
+    0x09,0x8B,0xA8,0x82,0xF8,0xF2,0x78,0x5A,0xC8,0x82,0x87,0x7A,0xF2,0xF0,0xDE,0x57,
+    0xA8,0x7A,0x67,0x7A,0xFE,0x5F,0x7C,0xFF,0x87,0x7A,0x46,0x72,0x00,0x0F,0x2E,0xBB,
+    0xA8,0x7A,0x67,0x7A,0xF7,0xEF,0xBF,0xAD,0x87,0x7A,0x67,0x72,0xB7,0x8A,0xC0,0xA0,
+    0x87,0x7A,0x66,0x72,0x7E,0x0A,0x3E,0x12,0xA7,0x7A,0x67,0x72,0x75,0xE5,0xDF,0x37,
+    0x87,0x7A,0x46,0x72,0xF5,0x0F,0x2A,0x08,0x87,0x7A,0x46,0x72,0x5D,0x5F,0x3A,0xFA,
+    0x86,0x72,0x25,0x6A,0xE0,0x9E,0xFE,0xFF,0x67,0x7A,0x26,0x6A,0xBF,0xB6,0xBC,0x8A,
+    0x86,0x7A,0x46,0x72,0x75,0x75,0xFD,0xED,0x87,0x7A,0x46,0x72,0xA5,0x03,0x2A,0xAF,
+    0xA8,0x7A,0x46,0x72,0xEB,0x0E,0xAC,0xED,0x87,0x7A,0x25,0x6A,0x7E,0xEC,0xAE,0x6E,
+    0x26,0x72,0xC5,0x61,0x62,0xBA,0xB8,0xEA,0x06,0x6A,0xA4,0x61,0xE0,0xF2,0xFE,0x77,
+    0xC5,0x61,0x63,0x59,0xA2,0x27,0xAC,0x8A,0x05,0x6A,0xA4,0x61,0xAD,0x29,0xAB,0x5E,
+    0x05,0x6A,0xA4,0x61,0xFA,0xA8,0xFA,0x7A,0x06,0x6A,0xA4,0x59,0xDF,0x7B,0xFF,0x2B,
+    0x05,0x6A,0xA4,0x61,0xBF,0x7F,0xFF,0x80,0x46,0x72,0xC4,0x61,0x8B,0x2D,0xBE,0x2E,
+    0x46,0x72,0x26,0x6A,0x2F,0x2E,0xD0,0xFA,0x87,0x7A,0x26,0x6A,0xFD,0x57,0x6B,0xA2,
+    0x66,0x72,0xE5,0x61,0x7E,0x7B,0xEA,0xE0,0xA4,0x59,0xA2,0x38,0x7C,0x78,0x78,0xF8,
+    0xA1,0x30,0x61,0x28,0x78,0x5F,0x5E,0x5E,0xC2,0x30,0x61,0x28,0xBF,0x3D,0xAD,0xBD,
+    0x23,0x41,0xA1,0x28,0xFD,0xFB,0x2B,0x0B,0x23,0x41,0xE2,0x38,0x8D,0xF7,0xAF,0xAC,
+    0x23,0x41,0xE2,0x38,0x0F,0x2F,0xF7,0xDF,0x64,0x49,0x03,0x41,0x2B,0x89,0x85,0x25,
+    0x64,0x49,0x23,0x41,0xE6,0xFA,0x70,0xE0,0x43,0x41,0xA2,0x30,0xFC,0x5E,0x7A,0xFE,
+    0xC2,0x30,0x81,0x28,0xFC,0xFA,0xE8,0xA8,0xA2,0x28,0x81,0x28,0xBE,0x7E,0xFC,0x68,
+    0xA2,0x28,0x82,0x20,0x80,0xFA,0x5E,0x5D,0xC2,0x28,0x82,0x20,0xAF,0xBD,0x1F,0x7F,
+    0xE3,0x30,0xA2,0x28,0x03,0xFF,0xFF,0x5F,0xC3,0x28,0x61,0x20,0xF8,0xF8,0x7E,0x56,
+    0x83,0x20,0x61,0x20,0xDC,0x96,0xDF,0xD2,0x82,0x20,0x61,0x20,0xF8,0xBE,0xEB,0xFB,
+    0xA2,0x28,0x41,0x18,0xA2,0xA8,0xBE,0xDF,0xC3,0x28,0x61,0x20,0x0B,0xEF,0xBF,0xF5,
+    0xA2,0x28,0x82,0x20,0xBA,0xFE,0x0F,0x2F,0xC3,0x28,0x82,0x20,0x2E,0x89,0x3B,0xAB,
+    0xE3,0x30,0xA2,0x28,0x3F,0xBF,0xFD,0xBD,0x03,0x31,0xA2,0x28,0xDA,0xFA,0xE3,0xFF,
+    0xE3,0x30,0xC2,0x28,0xF2,0x78,0xDE,0x5D,0xE3,0x30,0xA2,0x28,0x2A,0xBF,0xBB,0xF7,
+    0xE3,0x30,0xA2,0x28,0x7F,0xEE,0xAB,0x8A,0xE3,0x38,0xA2,0x28,0xFD,0xF5,0xFE,0x2B,
+    0xE3,0x30,0xA2,0x30,0x8F,0x2B,0x88,0xEA,0xE3,0x30,0xA2,0x30,0xB8,0xF6,0xF7,0x7D,
+    0xC2,0x30,0xA2,0x30,0x0E,0x0B,0x03,0x2A,0xE3,0x38,0xA2,0x28,0xF8,0xFB,0xBF,0xAA,
+    0x03,0x39,0xA2,0x30,0xB5,0xFD,0xBB,0x2A,0x24,0x39,0xE3,0x30,0xB2,0xBB,0x57,0x57,
+    0x03,0x39,0xC2,0x30,0x80,0xA0,0xFA,0xFE,0x03,0x39,0xC2,0x30,0xA2,0xAB,0xBF,0x3F,
+    0x23,0x39,0xE2,0x30,0xEF,0xFE,0xE9,0xE2,0x03,0x39,0xC2,0x30,0xFF,0xAF,0xAB,0x00,
+    0x03,0x39,0xE2,0x38,0x03,0x57,0x27,0x05,0x24,0x39,0xE2,0x38,0x95,0xF5,0x9E,0x5A,
+    0x23,0x41,0xE2,0x38,0x7E,0x6E,0xA0,0x8A,0x03,0x39,0xC2,0x30,0x63,0x62,0x70,0xE8,
+    0x03,0x39,0xA2,0x30,0x7B,0x3F,0x2F,0x2E,0x44,0x41,0xE2,0x30,0xB5,0xFD,0xEE,0x3A,
+    0x44,0x49,0x03,0x39,0x57,0x77,0xFF,0xB0,0x44,0x49,0x03,0x39,0xD5,0x55,0x7D,0xF2,
+    0x24,0x39,0xE3,0x38,0xEA,0xF2,0xB9,0xFF,0x03,0x39,0xC2,0x38,0x02,0x00,0xC0,0xC2,
+    0x03,0x39,0xC2,0x30,0x77,0xAF,0xBB,0x8A,0x23,0x39,0xC2,0x30,0x8B,0xA6,0x3F,0xAB,
+    0x23,0x39,0xE2,0x30,0x56,0xFF,0x6A,0xE8,0x02,0x39,0xC1,0x30,0xEA,0x63,0xA2,0x82,
+    0x03,0x41,0xC2,0x30,0x2F,0xA9,0x2B,0x3F,0xA4,0x51,0x23,0x41,0xAD,0x37,0x29,0x2D,
+    0xC5,0x51,0x64,0x49,0xDF,0x59,0x8A,0x22,0xC5,0x59,0x64,0x49,0xFD,0x95,0xFA,0xF8,
+    0x05,0x62,0x63,0x49,0xAF,0x2F,0xAF,0xF7,0x67,0x6A,0xC5,0x59,0x8A,0xAA,0xBF,0x75,
+    0x06,0x62,0x84,0x51,0x08,0xB8,0xFE,0xDF,0x47,0x6A,0xA4,0x51,0x0A,0x2A,0xBD,0x2D,
+    0x8C,0x93,0x27,0x62,0x2F,0x2D,0x2D,0x2D,0xB0,0xB4,0xED,0x9B,0x3D,0xAD,0x29,0x29,
+    0xD0,0xB4,0x6F,0xAC,0xEE,0x7F,0xE2,0xFA,0x6F,0xAC,0xAD,0x93,0x68,0xE0,0xE8,0xE0,
+    0xAD,0x93,0x0A,0x7B,0xFE,0xAC,0xF8,0x58,0xAC,0x8B,0x2B,0x83,0x2B,0x2B,0x2F,0xBD,
+    0xCD,0x8B,0x8C,0x8B,0xBC,0x68,0x82,0xC9,0xCD,0x93,0x6C,0x7B,0xA8,0xAA,0x2A,0xFF,
+    0xCD,0x93,0x0A,0x73,0xA0,0xA2,0xFA,0x7E,0x8C,0x8B,0xAA,0x6A,0xA0,0xFA,0x7E,0xDF,
+    0x0B,0x73,0xA9,0x6A,0x7B,0xF2,0xFE,0x5E,0x0A,0x73,0x89,0x62,0x02,0x2B,0xF9,0xDD,
+    0x2B,0x73,0xEA,0x72,0xAD,0x7D,0xD5,0x5D,0x2B,0x7B,0xA9,0x6A,0xB8,0xBF,0xF7,0xB7,
+    0x0A,0x73,0xC9,0x72,0x96,0xFB,0x42,0xE0,0x0A,0x7B,0xCA,0x72,0x9E,0x39,0x25,0xD5,
+    0x4C,0x7B,0x0B,0x7B,0xDD,0xDD,0x89,0xB7,0x6C,0x83,0x0B,0x7B,0xDE,0xBF,0x1F,0xEF,
+    0x6C,0x83,0x2B,0x83,0xFF,0xFA,0xEA,0xA8,0xEE,0x9B,0x4B,0x83,0xBD,0x0F,0x29,0x2D,
+    0xEE,0x9B,0x4B,0x83,0x7E,0x7A,0x58,0xF0,0xEE,0x9B,0x4C,0x83,0x2D,0x2D,0xFD,0xF5,
+    0x43,0x51,0xE1,0x48,0xDE,0xEB,0x8A,0x0B,0x22,0x49,0xE2,0x40,0xE0,0xFA,0xFF,0xEF,
+    0x44,0x51,0xC2,0x40,0xFF,0x7F,0xBF,0x2B,0x43,0x51,0xE2,0x40,0xFD,0xEB,0x2F,0x08,
+    0x63,0x51,0x02,0x49,0xF7,0x55,0x6D,0xFE,0x43,0x51,0x02,0x49,0xF7,0xA5,0xB5,0xBF,
+    0x43,0x51,0xE2,0x40,0xE0,0x7A,0x7C,0xFA,0x43,0x51,0xE2,0x40,0xBF,0xAF,0xB9,0xE9,
+    0x43,0x51,0x02,0x49,0x80,0xA8,0xAF,0x4B,0x43,0x51,0x03,0x49,0xA0,0xA3,0xBB,0x0F,
+    0x65,0x59,0x23,0x51,0xED,0xBA,0x5A,0x5F,0x64,0x59,0x02,0x49,0xBB,0x8F,0xCD,0xEA,
+    0x44,0x51,0x23,0x51,0x5C,0xDB,0x8D,0xED,0x43,0x51,0x03,0x49,0xF7,0xFB,0xCB,0xE2,
+    0x23,0x51,0x03,0x49,0xE0,0xFC,0x5A,0x72,0x23,0x51,0xE2,0x48,0xCA,0xFA,0xAA,0xAB,
+    0x23,0x51,0xE2,0x48,0xE2,0xBB,0xFF,0x75,0x23,0x51,0xE2,0x48,0xCF,0xCB,0x2B,0xED,
+    0xE8,0x8A,0x23,0x51,0x2D,0x25,0x29,0x2D,0x29,0x93,0xE8,0x8A,0x72,0xF2,0x62,0x5F,
+    0xC9,0x8A,0xA7,0x7A,0xE8,0xF8,0xBE,0x72,0xA8,0x7A,0x87,0x7A,0x58,0x5C,0xE0,0xFF,
+    0xA7,0x7A,0x67,0x72,0xDB,0x2B,0xBF,0x77,0x87,0x7A,0x46,0x72,0x79,0xCA,0x2A,0x00,
+    0xA7,0x7A,0x67,0x72,0xA9,0xB7,0xE4,0x7C,0xA8,0x82,0x26,0x72,0xA8,0xAF,0x0A,0x22,
+    0xA7,0x7A,0x66,0x72,0xBB,0xDC,0xE0,0x82,0x87,0x7A,0x67,0x72,0x18,0x0C,0x2B,0x0E,
+    0xA7,0x7A,0x67,0x7A,0xFF,0x5F,0xEF,0x1F,0x87,0x7A,0x46,0x72,0x2A,0x2F,0xBA,0x90,
+    0x66,0x72,0x26,0x72,0xEC,0x4C,0xD0,0xC2,0x67,0x7A,0x25,0x6A,0x9A,0xC2,0xCB,0x6F,
+    0x87,0x7A,0x46,0x72,0xFA,0x5E,0x7E,0x7D,0x87,0x7A,0x46,0x72,0xEF,0x8F,0xAD,0x0F,
+    0x87,0x7A,0x67,0x72,0xA3,0x93,0xBD,0x6F,0x67,0x72,0x05,0x6A,0xE8,0xEC,0xFE,0xDF,
+    0x26,0x72,0xC5,0x61,0xF8,0xEF,0x79,0xBE,0xC5,0x61,0x83,0x59,0xEC,0x02,0x20,0xE8,
+    0x05,0x6A,0xA4,0x61,0xF5,0xE5,0x2D,0x0D,0x46,0x72,0xA4,0x61,0xD7,0xBD,0x0A,0xAA,
+    0x46,0x72,0xC5,0x61,0xA5,0x8B,0x80,0x08,0x87,0x7A,0x06,0x6A,0xFD,0x2D,0x8A,0xAA,
+    0xA7,0x7A,0x46,0x72,0x5F,0x2B,0x22,0xAB,0xA8,0x82,0x05,0x6A,0xFD,0xEB,0x88,0x22,
+    0xA8,0x7A,0x26,0x72,0x77,0xAF,0x8A,0xAA,0xA8,0x7A,0x67,0x72,0x7F,0xCB,0x6A,0xDD,
+    0x87,0x72,0x26,0x6A,0x60,0x80,0xE8,0x7F,0x06,0x62,0xE2,0x38,0x5A,0x78,0x78,0x78,
+    0xC2,0x38,0x61,0x28,0x5E,0xBE,0xFA,0xB8,0xE2,0x38,0x81,0x30,0xBD,0x3D,0x2F,0x2D,
+    0x64,0x49,0x03,0x39,0xA9,0x8F,0xA9,0xFD,0x64,0x49,0x03,0x39,0x7A,0x7A,0x7E,0xAF,
+    0x23,0x41,0xE2,0x38,0x45,0xF7,0x7A,0xEA,0x65,0x49,0xE3,0x38,0x2D,0xAD,0xFD,0xDD,
+    0x64,0x49,0x03,0x39,0xA2,0xA2,0xAB,0x87,0x23,0x39,0xA2,0x28,0x68,0x6A,0xF0,0x68,
+    0xC2,0x30,0x82,0x28,0x2F,0xAE,0x20,0x22,0xC2,0x28,0xA2,0x28,0x77,0x5F,0x7F,0xEF,
+    0xA2,0x28,0x82,0x20,0x72,0x62,0xAB,0xEC,0xC3,0x28,0x61,0x20,0xFE,0xFA,0xB8,0x7E,
+    0xC3,0x28,0x61,0x20,0xE3,0xEF,0x7F,0x57,0x82,0x20,0x61,0x20,0x58,0xDF,0xFF,0xBF,
+    0x82,0x20,0x61,0x20,0x60,0x0B,0x3F,0x3B,0xA2,0x28,0x61,0x20,0xFF,0xFA,0x8B,0x02,
+    0xA2,0x20,0x61,0x20,0x57,0x9F,0xFA,0xF8,0xA2,0x28,0x41,0x18,0xBD,0xEA,0xAA,0x2A,
+    0xA2,0x28,0x61,0x20,0x2B,0xAF,0x3B,0x08,0xC2,0x28,0x82,0x20,0xFF,0xFF,0x3F,0xB7,
+    0xC2,0x28,0x81,0x28,0x0B,0x22,0xE8,0xA8,0xC2,0x28,0xA2,0x28,0x78,0x5A,0x5D,0xDB,
+    0xC2,0x30,0xA2,0x28,0x73,0xF5,0x35,0x2B,0xC2,0x30,0xA2,0x28,0x55,0xFA,0xA0,0x80,
+    0x03,0x39,0xA2,0x28,0xAB,0x8B,0xA7,0xFF,0x03,0x39,0xC2,0x30,0xAF,0xF6,0x57,0x57,
+    0xE3,0x38,0xC3,0x30,0x78,0xED,0x3B,0x39,0xE3,0x30,0xA2,0x30,0xFF,0xEE,0xAA,0xAB,
+    0xC2,0x30,0xA3,0x28,0x0A,0xAA,0x80,0x20,0x03,0x31,0xA2,0x30,0xFE,0x5F,0xF5,0x77,
+    0x03,0x39,0xC2,0x30,0x2B,0x2F,0xA5,0x75,0x03,0x39,0xA2,0x30,0xA0,0xA8,0xFE,0xFA,
+    0x03,0x39,0xC3,0x30,0xAA,0x02,0xA7,0xD7,0x23,0x39,0xE3,0x38,0x97,0xBB,0x77,0xD5,
+    0x23,0x39,0xE3,0x38,0xE6,0xAA,0x13,0x3B,0x23,0x39,0xC2,0x30,0x88,0x8A,0xBA,0x9A,
+    0x03,0x39,0xC2,0x30,0x03,0xBE,0x3C,0xBA,0x03,0x39,0xC2,0x30,0x00,0x2A,0xAA,0xFE,
+    0x23,0x39,0xE2,0x30,0x28,0x3B,0xF5,0x57,0x23,0x41,0xE2,0x38,0xFC,0x58,0x50,0x53,
+    0xE2,0x38,0xC2,0x30,0x28,0x0E,0x0E,0x2E,0x44,0x41,0xE3,0x38,0x23,0xAD,0x37,0x1F,
+    0x85,0x49,0x23,0x41,0xFF,0xFB,0x9F,0x1F,0x64,0x49,0x24,0x41,0x52,0x5A,0x78,0x2A,
+    0x44,0x41,0xE2,0x38,0x7F,0xDE,0xFE,0xEC,0x44,0x41,0xE3,0x38,0xED,0xAF,0xEF,0xCA,
+    0x02,0x39,0xC2,0x30,0xF0,0x5A,0xC2,0xAE,0x02,0x39,0xC1,0x30,0x2A,0x25,0xB5,0xEF,
+    0x23,0x39,0xE2,0x38,0xE2,0xAC,0xB7,0xBD,0x43,0x41,0xE2,0x38,0xDF,0xEB,0xA0,0xBC,
+    0x23,0x41,0xE2,0x38,0x55,0xDF,0x14,0xBF,0xA4,0x51,0x02,0x39,0x29,0xAF,0xA5,0xD7,
+    0xA4,0x51,0x02,0x41,0x00,0x82,0xA8,0x6E,0xA4,0x51,0x23,0x41,0xA0,0xFE,0xFF,0xFD,
+    0xA4,0x59,0x22,0x41,0xAF,0xB7,0x2D,0x2F,0xC5,0x59,0x84,0x51,0x83,0xA9,0xFB,0xB3,
+    0xE6,0x59,0x84,0x51,0x57,0x5F,0x7A,0xE2,0x26,0x62,0x84,0x51,0x2F,0xB5,0xAD,0xAF,
+    0x8C,0x93,0x26,0x62,0x2D,0x2D,0x25,0x25,0xB0,0xB4,0x2E,0xA4,0x0D,0x09,0x29,0xAD,
+    0xB0,0xB4,0x6F,0xAC,0x78,0xF8,0x7B,0xE7,0x6F,0xAC,0xCD,0x93,0x68,0x68,0xF8,0x58,
+    0xAD,0x93,0xA9,0x72,0x78,0x78,0x78,0x70,0x2C,0x83,0x48,0x62,0x02,0x8A,0xAF,0xD5,
+    0x8C,0x8B,0x89,0x6A,0x0A,0xFF,0xFF,0x7F,0x8C,0x83,0x69,0x62,0x20,0xAB,0xFF,0x57,
+    0x2B,0x73,0x68,0x62,0xA0,0xE8,0x7F,0x55,0xCA,0x6A,0x68,0x62,0x22,0xED,0xFA,0xF7,
+    0xCA,0x6A,0x68,0x62,0xF8,0x5F,0x75,0x7D,0xCA,0x6A,0x68,0x62,0x3B,0xB3,0x9D,0xE9,
+    0xEA,0x72,0x89,0x62,0x82,0xAA,0x2B,0xAD,0xEA,0x72,0x89,0x62,0x2B,0x2D,0xBE,0xBE,
+    0x0A,0x73,0xC9,0x6A,0xA0,0xFF,0xB5,0x15,0x4B,0x7B,0xCA,0x72,0x57,0xFD,0xAB,0x2D,
+    0xAD,0x8B,0x0B,0x7B,0xF5,0xFD,0x8F,0x0A,0x0E,0x9C,0x2B,0x7B,0xF5,0xFF,0xAB,0x2A,
+    0xED,0x93,0x4B,0x83,0x57,0x77,0xFE,0xFC,0xED,0x93,0x4B,0x83,0x3F,0x27,0x3D,0xBF,
+    0x2E,0xA4,0x8C,0x8B,0x60,0xA2,0x02,0x03,0x0E,0x9C,0x4B,0x83,0xDD,0x5F,0x7E,0x58,
+    0x43,0x51,0x03,0x49,0x8B,0xCE,0x9E,0x96,0x23,0x49,0xE2,0x48,0xFC,0x9E,0x3E,0x0A,
+    0x23,0x49,0x02,0x49,0x5A,0xF8,0x88,0xA8,0x44,0x51,0x02,0x49,0xBF,0xFF,0x6A,0x52,
+    0x44,0x51,0x03,0x49,0xB6,0xBA,0xF5,0xF5,0x22,0x49,0xE2,0x40,0x20,0xA8,0xAD,0xDC,
+    0x43,0x51,0xE2,0x40,0xFA,0xAD,0x2B,0x8A,0x43,0x51,0x02,0x49,0xFB,0xDA,0xA8,0xFA,
+    0x64,0x51,0x03,0x49,0xFE,0xFE,0xEE,0x35,0x44,0x51,0x02,0x49,0xCB,0xEF,0xF9,0xF9,
+    0x64,0x51,0x23,0x51,0xFD,0xD5,0x35,0xA5,0x44,0x59,0x23,0x49,0xEA,0xE3,0x7A,0x7A,
+    0x43,0x51,0x03,0x49,0xAF,0xA3,0x0F,0x6F,0x43,0x51,0x03,0x49,0x83,0x9C,0x5E,0xFD,
+    0x23,0x51,0xE2,0x48,0xE8,0x68,0xFC,0x96,0x23,0x51,0xE2,0x48,0x35,0xA5,0xA9,0xCE,
+    0x02,0x49,0xE2,0x48,0x70,0x02,0xB8,0xF0,0x43,0x51,0xE2,0x48,0xFF,0xF7,0x2F,0xAD,
+    0xE8,0x82,0x83,0x59,0x25,0x0D,0x0D,0x0D,0x29,0x8B,0xC8,0x82,0xEA,0x7A,0xE2,0xFA,
+    0xE9,0x8A,0x87,0x7A,0x62,0xEB,0xFB,0x56,0xA8,0x7A,0x67,0x72,0xE2,0x2E,0xBA,0x7F,
+    0xA7,0x82,0x67,0x72,0xFF,0xEE,0xEB,0xF1,0xA8,0x7A,0x67,0x7A,0xFE,0xDA,0xDA,0xAA,
+    0xC8,0x82,0x67,0x72,0x7F,0x5E,0x58,0xEB,0xA8,0x7A,0x67,0x72,0xBE,0xAB,0x2D,0xBF,
+    0x46,0x82,0xA8,0x7A,0xF6,0xF7,0xFD,0xFF,0xA8,0x7A,0x46,0x72,0x8A,0xAE,0xFF,0xAB,
+    0xA7,0x7A,0x67,0x72,0xFF,0x6B,0x4B,0xFF,0x87,0x7A,0x46,0x72,0xAB,0xFA,0xFA,0x7A,
+    0x66,0x72,0x26,0x72,0x2F,0xAA,0x6B,0xFF,0x66,0x72,0x05,0x72,0xA8,0x8A,0x8B,0x82,
+    0x67,0x7A,0x46,0x72,0xCD,0x37,0xD5,0x17,0x87,0x7A,0x46,0x72,0xB2,0xAF,0xAF,0xEF,
+    0x87,0x7A,0x26,0x72,0xC2,0xDF,0x6F,0xFB,0x46,0x72,0xE5,0x61,0xB8,0xFE,0xDE,0x7C,
+    0x06,0x6A,0xA4,0x61,0xDC,0x5A,0x5A,0x6A,0x25,0x6A,0x83,0x59,0x7F,0xFF,0xDD,0x3B,
+    0x46,0x72,0xA4,0x59,0xFD,0x75,0x3B,0x00,0xA8,0x7A,0x05,0x6A,0xD5,0xB5,0x0F,0xEE,
+    0x87,0x7A,0x05,0x6A,0x2B,0x2A,0xE8,0x56,0x88,0x7A,0x05,0x6A,0xA2,0x2C,0xAF,0xF5,
+    0x87,0x7A,0x05,0x6A,0x22,0x88,0x8B,0xFD,0x87,0x7A,0x26,0x6A,0x8A,0xAA,0xBB,0xFD,
+    0x67,0x72,0x26,0x6A,0xA7,0xB8,0x5A,0x78,0x87,0x7A,0xE6,0x69,0xAB,0xFE,0xBD,0x2E,
+    0x67,0x72,0x06,0x6A,0x6A,0xBE,0xE0,0x80,0xE6,0x61,0x03,0x41,0x78,0x58,0x78,0x78,
+    0xE2,0x38,0x81,0x30,0xD8,0x88,0xA2,0xA8,0x03,0x41,0x81,0x30,0xAD,0xAF,0xAA,0x88,
+    0x23,0x41,0xE3,0x38,0x09,0x09,0xF7,0xF5,0x64,0x49,0xE2,0x38,0x8B,0x2E,0x2D,0xB5,
+    0x44,0x49,0xC2,0x38,0xFE,0xF8,0x58,0xF0,0xE2,0x38,0xC2,0x30,0x00,0xEE,0xEE,0xBF,
+    0x24,0x41,0xC2,0x30,0x0A,0xAB,0xAF,0x7D,0x23,0x39,0xC2,0x28,0x78,0xEA,0x7E,0x7F,
+    0xC2,0x28,0x62,0x20,0xA2,0xAA,0xAA,0xEA,0xC2,0x28,0x82,0x20,0xEA,0x5B,0x5F,0x55,
+    0xA2,0x20,0x61,0x18,0x2C,0xBA,0xBA,0xFF,0xA2,0x20,0x61,0x20,0x7A,0x7A,0x78,0x7F,
+    0x82,0x20,0x61,0x20,0x55,0xD5,0x37,0x0B,0xA1,0x20,0x62,0x20,0xF7,0xF7,0xFE,0xEA,
+    0xA2,0x28,0x61,0x20,0x5F,0xFF,0x8B,0x02,0xC2,0x28,0x82,0x20,0xBD,0x5D,0xBF,0x7E,
+    0xC3,0x28,0x61,0x20,0x7A,0xEA,0xAA,0x8A,0xA2,0x28,0x81,0x20,0x07,0x7C,0x5E,0x7A,
+    0xC2,0x28,0x81,0x20,0xAF,0xAF,0xB5,0xB5,0xC2,0x28,0x61,0x20,0x2A,0x20,0xA8,0xEA,
+    0xE3,0x30,0xA2,0x28,0xBF,0xBB,0xBF,0xD5,0xC2,0x28,0xA2,0x28,0x7A,0xEE,0xD4,0x67,
+    0xC2,0x30,0xA2,0x28,0x7E,0x5F,0x7D,0xA9,0xE3,0x30,0xA2,0x28,0xFB,0x0B,0x03,0x20,
+    0xE3,0x30,0xC2,0x28,0xAB,0x8B,0xAB,0xF6,0xE3,0x30,0x82,0x28,0xEA,0xFA,0xFA,0xDE,
+    0xC2,0x30,0x81,0x28,0xA0,0xB8,0x6F,0xBD,0xE3,0x30,0xA2,0x28,0xA9,0xEB,0xED,0x69,
+    0xE3,0x30,0xA2,0x28,0xE3,0xA3,0xFD,0x7D,0xC2,0x30,0xA2,0x28,0x38,0x30,0x3F,0x0A,
+    0xE3,0x30,0xA2,0x30,0xBE,0xB6,0xAE,0x0A,0xE3,0x38,0xC2,0x30,0xF0,0xE2,0xEA,0xD0,
+    0xC2,0x38,0xE3,0x30,0xFF,0xDF,0xFE,0x2F,0xE3,0x38,0xA2,0x28,0x22,0xE0,0xDA,0xFE,
+    0x03,0x39,0xC2,0x30,0x3E,0x9F,0xFF,0xB7,0x23,0x39,0xE2,0x30,0x5F,0x57,0xB5,0xB5,
+    0x03,0x39,0xC2,0x30,0xDA,0xAA,0x2A,0x08,0x03,0x39,0xC2,0x30,0xFF,0xBE,0xA4,0x00,
+    0x24,0x39,0xE2,0x38,0x77,0xF7,0xBF,0xF8,0x23,0x41,0xE3,0x38,0xFD,0xA9,0xAA,0x4B,
+    0x23,0x41,0xC2,0x30,0xFF,0xDA,0xC2,0xA2,0x44,0x41,0x03,0x41,0xA5,0xA5,0x8D,0xFF,
+    0x85,0x49,0x23,0x41,0xED,0x3D,0x9F,0xBA,0x85,0x51,0x44,0x41,0xAD,0x0D,0xBB,0xBA,
+    0x64,0x49,0x03,0x39,0x76,0xCE,0xC0,0x88,0x84,0x49,0x23,0x41,0xF5,0x5F,0x5B,0x63,
+    0x44,0x49,0xE2,0x38,0x7E,0xAB,0x8A,0x82,0x43,0x49,0xC1,0x38,0x7D,0xFE,0xFA,0xA0,
+    0x23,0x41,0xE2,0x38,0x2F,0x29,0xAF,0xEF,0x23,0x41,0x03,0x39,0x24,0x0A,0x8F,0x2B,
+    0x23,0x41,0xE2,0x38,0xBF,0x38,0x00,0xB0,0x43,0x49,0xE2,0x38,0x2C,0xEA,0xB7,0x2D,
+    0x64,0x49,0x02,0x41,0x2A,0x2D,0xAF,0x0A,0xA5,0x51,0x43,0x41,0xDF,0xE7,0x8A,0x02,
+    0xE5,0x59,0x22,0x41,0xA7,0x2F,0x0B,0x2A,0x27,0x62,0x84,0x51,0x7F,0xEF,0x3A,0x2F,
+    0x27,0x62,0xC5,0x59,0xFD,0xEF,0xA8,0x00,0x27,0x62,0xC5,0x59,0xF7,0x79,0xBE,0xA8,
+    0x2A,0x83,0xE6,0x59,0x2D,0x3D,0x35,0x35,0x32,0xC5,0xED,0x9B,0xBD,0x2D,0x29,0x2D,
+    0x73,0xCD,0xD1,0xB4,0x55,0xFF,0xA2,0x00,0x52,0xC5,0x4F,0xA4,0x5F,0xEA,0xA0,0x80,
+    0xB0,0xB4,0xEA,0x7A,0x7E,0xF8,0xA0,0x20,0x2F,0x9C,0x07,0x5A,0x55,0x57,0xFA,0xA0,
+    0xCA,0x72,0x07,0x5A,0xA0,0xA8,0x6A,0x70,0x49,0x62,0xA6,0x51,0x80,0xAC,0xBE,0xD7,
+    0x48,0x62,0xA6,0x51,0x0A,0xAB,0x7F,0x77,0x68,0x62,0xE6,0x51,0x80,0xEE,0xFF,0xDF,
+    0x68,0x62,0x07,0x52,0x02,0x02,0xFB,0x77,0x89,0x62,0x27,0x5A,0x08,0x2A,0xE8,0xDF,
+    0xA9,0x6A,0x68,0x62,0x2B,0xAA,0xAD,0x25,0xCA,0x6A,0x68,0x62,0x20,0x0B,0x0D,0x0B,
+    0x0A,0x7B,0xA9,0x6A,0xAF,0xE7,0xB3,0x0A,0xAD,0x8B,0x0A,0x73,0x95,0x35,0x2D,0x0B,
+    0x4F,0xA4,0xAD,0x8B,0xF5,0xB5,0x3A,0xAB,0x4E,0xA4,0xCC,0x93,0xD7,0xFA,0xAA,0x02,
+    0x4F,0xA4,0xAC,0x8B,0x7E,0xEA,0xAA,0x82,0xCD,0x93,0x6B,0x8B,0xAA,0xB0,0x98,0x88,
+    0x4E,0xA4,0xCD,0x93,0x0D,0x2F,0xAF,0x3D,0x6F,0xAC,0x8C,0x8B,0x5E,0x78,0x78,0xE8,
+    0x44,0x49,0x02,0x49,0x78,0x55,0xD5,0xF5,0x23,0x49,0x03,0x49,0xEB,0xDA,0xF7,0xC8,
+    0x23,0x49,0xE2,0x40,0x28,0xB7,0xD6,0xAE,0x43,0x51,0x03,0x49,0xFF,0x0B,0xBF,0xF9,
+    0x43,0x51,0xE2,0x40,0xE2,0xA8,0x7A,0x9A,0x43,0x51,0xE2,0x40,0x97,0xA7,0x2F,0x0A,
+    0x64,0x51,0x02,0x49,0xFB,0xFA,0xF6,0xE8,0x43,0x51,0x03,0x49,0x77,0x0A,0x20,0x5B,
+    0x64,0x59,0x02,0x49,0x9F,0xBE,0xB8,0xEF,0x43,0x51,0x03,0x51,0x20,0x00,0x2C,0xEB,
+    0x43,0x51,0x23,0x51,0x26,0xFE,0x56,0xF1,0x43,0x51,0x02,0x49,0x6A,0xEA,0xFA,0x52,
+    0x23,0x51,0x03,0x49,0x0A,0xC7,0x2F,0x09,0xE2,0x50,0x23,0x49,0xFE,0xBB,0xAD,0xED,
+    0x44,0x51,0xE2,0x48,0xFF,0xFD,0xAA,0xA8,0x23,0x51,0xC1,0x40,0x6E,0x7A,0xEA,0xE8,
+    0x02,0x49,0xE2,0x48,0x39,0x0B,0x8B,0xCD,0xE6,0x69,0x02,0x49,0xD5,0xD5,0xB5,0x25,
+    0x49,0x93,0xE5,0x61,0xAD,0x2D,0xAB,0x2A,0x08,0x8B,0xA7,0x7A,0xF0,0xFC,0x78,0x7A,
+    0xC8,0x82,0x66,0x72,0xA8,0xE0,0x6A,0x7A,0xA7,0x7A,0x67,0x7A,0xAE,0xA2,0xFA,0x1F,
+    0xA7,0x7A,0x66,0x72,0xEE,0xA8,0x66,0xAA,0xA7,0x82,0x66,0x72,0xC3,0x71,0x7D,0x75,
+    0x87,0x7A,0x67,0x72,0x02,0xA3,0x21,0x23,0xA7,0x7A,0x66,0x72,0xBA,0xAB,0x29,0xDF,
+    0xA7,0x7A,0x66,0x72,0xBA,0xAA,0xB6,0x77,0xA8,0x7A,0x66,0x7A,0x2F,0xBF,0xEE,0x2D,
+    0xA8,0x82,0x46,0x72,0xBA,0xF2,0x78,0x78,0x67,0x7A,0x46,0x72,0xF2,0xEB,0x7D,0x69,
+    0x66,0x72,0x26,0x6A,0xF7,0xFF,0xF8,0xEB,0x66,0x7A,0x26,0x6A,0x2A,0x89,0x0B,0xBA,
+    0xA7,0x7A,0x26,0x72,0xBF,0xFF,0x7F,0x0A,0x09,0x8B,0x26,0x72,0xF5,0xBD,0xAD,0x2A,
+    0x4A,0x93,0x46,0x72,0x55,0xFF,0xAA,0x2A,0x29,0x8B,0x46,0x72,0x55,0xEE,0xAA,0xA0,
+    0xA8,0x7A,0xE5,0x61,0xDF,0xEA,0xA0,0xB8,0x67,0x7A,0xE5,0x69,0x2B,0x82,0xF0,0x56,
+    0x67,0x72,0xE5,0x69,0xAC,0xFF,0xFF,0xF5,0x25,0x72,0xC5,0x61,0xE8,0xEA,0xAA,0xAA,
+    0x46,0x72,0xC4,0x61,0x7F,0x7F,0xBA,0x8A,0x46,0x72,0xE5,0x61,0xD7,0xDF,0xFB,0x28,
+    0x67,0x72,0x05,0x6A,0xDD,0xFD,0xF9,0x83,0x67,0x7A,0x26,0x6A,0x29,0xF5,0x5D,0xFF,
+    0x87,0x7A,0x26,0x6A,0xBF,0xB5,0xAF,0x0B,0x87,0x72,0x26,0x6A,0xAE,0xFE,0xDF,0x7A,
+    0x87,0x72,0x26,0x6A,0x7E,0x7C,0x57,0x57,0xE5,0x59,0x23,0x41,0x78,0x78,0x78,0x78,
+    0x23,0x41,0xA1,0x30,0xDE,0xFE,0xDE,0xFC,0x04,0x39,0xC2,0x38,0xFB,0xF7,0x6B,0xE9,
+    0x03,0x39,0xC2,0x38,0xAB,0xFF,0xFD,0x77,0x23,0x41,0xC2,0x30,0x3F,0xB7,0xB7,0xFF,
+    0x44,0x41,0x03,0x39,0x6A,0x7A,0x7F,0x55,0x03,0x39,0xE2,0x30,0xBF,0x20,0xF8,0x34,
+    0x03,0x39,0xA2,0x28,0xFA,0xFC,0x78,0x78,0xC2,0x28,0x81,0x20,0xC0,0xE8,0xF7,0x55,
+    0xA2,0x28,0x61,0x20,0xEA,0xE8,0xF8,0xFA,0x82,0x20,0x61,0x18,0xDB,0x5A,0x72,0xC0,
+    0x82,0x20,0x61,0x18,0xD5,0xF5,0xEF,0x8F,0xA2,0x20,0x61,0x18,0xF5,0xE9,0xAB,0xAB,
+    0xA2,0x28,0x61,0x20,0xAB,0xEF,0x27,0xAE,0xC2,0x28,0x81,0x20,0xFB,0x8F,0xAD,0xAF,
+    0x03,0x31,0xA2,0x28,0xF7,0xE7,0x7D,0xFF,0xE3,0x30,0x81,0x20,0x7E,0xFE,0xF2,0xAA,
+    0xC2,0x28,0x82,0x28,0xFD,0x5F,0x5E,0xB6,0xA2,0x28,0x81,0x20,0xFE,0x40,0x78,0x5A,
+    0xA2,0x28,0x61,0x20,0xAA,0xAC,0x7A,0xAE,0xA2,0x28,0x61,0x20,0x28,0xA8,0xFA,0xFA,
+    0xA2,0x28,0x61,0x20,0x00,0x02,0x2F,0xAF,0xC2,0x28,0x81,0x28,0xAB,0x8F,0x2F,0xFF,
+    0xC2,0x28,0x81,0x28,0x02,0xA8,0x7B,0x55,0xE2,0x30,0x81,0x28,0x8A,0xBE,0xE9,0xBF,
+    0xE3,0x30,0xA2,0x28,0x9B,0x3B,0x3E,0xFF,0xC2,0x30,0xA2,0x28,0x5E,0xDC,0x7C,0x5F,
+    0x61,0x30,0xC2,0x28,0xFB,0x77,0xFF,0x5D,0x03,0x31,0xC2,0x28,0x7D,0xF5,0x6D,0x43,
+    0xE3,0x30,0xA2,0x28,0xFD,0x8E,0xA2,0x82,0x04,0x39,0xC3,0x30,0xF5,0xFF,0xDF,0xAF,
+    0x24,0x39,0xE3,0x38,0xF5,0x8D,0x25,0xFF,0x24,0x39,0xC2,0x30,0x5E,0x7E,0x60,0xE8,
+    0xE3,0x30,0xC2,0x30,0x72,0xDD,0xF7,0xB6,0xC3,0x38,0xE3,0x30,0xF6,0xD7,0xFD,0xFF,
+    0x03,0x39,0xC2,0x30,0x2F,0x0B,0xAA,0xA3,0x23,0x39,0xE3,0x38,0xAD,0x82,0xA1,0x2F,
+    0x23,0x39,0xE2,0x30,0xB8,0xEB,0xEC,0xF8,0x23,0x39,0xE2,0x30,0x2A,0x02,0xA3,0xDD,
+    0x44,0x41,0xC2,0x30,0xF8,0xFE,0x7F,0x7F,0x03,0x39,0xE2,0x30,0xAA,0x1F,0x3F,0x7F,
+    0x44,0x41,0xE2,0x38,0x8F,0xAF,0xBF,0xD5,0x44,0x41,0xE2,0x38,0xFE,0x7A,0xF8,0xED,
+    0x44,0x49,0x03,0x39,0x23,0x83,0xA1,0xE9,0x85,0x49,0x03,0x41,0xAB,0x2D,0xBF,0x5D,
+    0x85,0x51,0x44,0x49,0xFA,0xE9,0xAF,0x0A,0x85,0x51,0x23,0x41,0x02,0x2A,0xEA,0xD8,
+    0x44,0x49,0x03,0x41,0x08,0x00,0x80,0xF2,0x64,0x49,0x02,0x39,0xF8,0x52,0xDE,0x9F,
+    0x23,0x41,0xE2,0x38,0xFA,0x7E,0xF8,0xEC,0x23,0x41,0xE2,0x38,0xA2,0xC9,0xF9,0x6B,
+    0x43,0x41,0xE2,0x38,0xDE,0xBF,0xFF,0xA3,0x43,0x41,0x03,0x41,0x0D,0xAA,0x8A,0xBF,
+    0x85,0x51,0x03,0x41,0x23,0x22,0xBA,0xFD,0xA5,0x51,0x22,0x41,0x0A,0xEA,0x77,0x55,
+    0xC5,0x59,0x22,0x41,0x0A,0xAA,0xAD,0xFD,0xE6,0x61,0x63,0x49,0x02,0x0F,0xF5,0xD5,
+    0x27,0x62,0x84,0x51,0x2A,0xBE,0xDF,0x75,0x27,0x62,0x84,0x51,0x00,0x88,0xFB,0x95,
+    0xE9,0x7A,0xE5,0x59,0x35,0x25,0x35,0xBD,0x12,0xC5,0x8C,0x93,0x29,0x29,0x29,0x2D,
+    0x73,0xCD,0x32,0xC5,0x00,0xAE,0xAF,0xBD,0x73,0xCD,0x12,0xBD,0x6C,0xF8,0xFA,0xCA,
+    0x52,0xC5,0x90,0xAC,0x5E,0x5E,0x78,0x7A,0xB0,0xB4,0x0E,0x9C,0x5E,0xBA,0xE8,0xAF,
+    0x6F,0xA4,0x4C,0x83,0x5E,0xEA,0xA8,0xA2,0x0E,0x9C,0x68,0x62,0x57,0xA8,0x00,0x00,
+    0x0E,0x9C,0xE7,0x59,0x55,0x7F,0xE8,0x00,0xCD,0x93,0xC6,0x51,0x55,0x55,0xFF,0xA8,
+    0x4C,0x83,0xE6,0x51,0x55,0x55,0xFF,0x00,0x2B,0x7B,0x07,0x5A,0x75,0xDD,0xFF,0x00,
+    0x6C,0x83,0x06,0x52,0xFD,0xFF,0xBF,0x00,0xAD,0x8B,0x68,0x62,0xF5,0xDF,0xEF,0x00,
+    0x0D,0x94,0xEA,0x72,0x75,0xF5,0xAD,0x2E,0xED,0x93,0x6B,0x83,0x3D,0xAF,0xB7,0x20,
+    0x4E,0xA4,0xCC,0x93,0xBF,0x2F,0x2D,0xAF,0x6F,0xAC,0x0E,0x9C,0x2E,0x8B,0x9A,0xA2,
+    0x6F,0xA4,0x0E,0xA4,0x6A,0xA8,0xFA,0xFE,0x2E,0x9C,0x8B,0x8B,0xFE,0x5C,0xFE,0xF8,
+    0x2E,0xA4,0x8C,0x8B,0x2D,0x29,0xAF,0x2F,0x6F,0xA4,0x2E,0xA4,0x67,0x7B,0xEA,0xAB,
+    0x23,0x49,0xE2,0x40,0x2E,0xAF,0x3E,0x2A,0x03,0x51,0x43,0x49,0xFA,0xBF,0xFF,0xFB,
+    0x43,0x51,0x03,0x49,0xE7,0x7D,0xFF,0xEB,0x43,0x49,0x03,0x49,0x2E,0xF7,0x7D,0xFB,
+    0x43,0x51,0x02,0x49,0xF6,0xBC,0xBF,0xBF,0x43,0x51,0x02,0x49,0xAA,0xEA,0xEB,0xEF,
+    0x63,0x59,0x02,0x49,0xEA,0xAE,0x27,0xBF,0x63,0x59,0x02,0x49,0xFF,0xEB,0xAC,0xAB,
+    0x43,0x51,0x02,0x49,0xFE,0x7C,0xC2,0x08,0x43,0x51,0xE2,0x48,0xBB,0xCD,0xAB,0xAB,
+    0x64,0x59,0xE2,0x48,0xAA,0xAB,0xF9,0x77,0x23,0x51,0x02,0x49,0x52,0xD4,0xD7,0x95,
+    0x43,0x51,0x03,0x49,0xFD,0x3F,0xFF,0x5F,0x43,0x51,0x03,0x49,0xB8,0xE7,0xB7,0x55,
+    0x23,0x49,0xE2,0x40,0xA2,0xBF,0xF3,0xDA,0x23,0x51,0xE2,0x48,0xFC,0x56,0x7F,0xAF,
+    0x43,0x51,0xE2,0x48,0xD5,0xD5,0xB5,0x2F,0x09,0x8B,0x23,0x51,0xB5,0x2D,0x0F,0x03,
+    0x29,0x8B,0xC8,0x82,0xBD,0xE6,0x5C,0x7C,0xE8,0x82,0x87,0x7A,0xF8,0xC8,0x68,0xEA,
+    0xC7,0x82,0x87,0x7A,0x7D,0xFD,0xAD,0xBD,0xA7,0x7A,0x66,0x72,0xB6,0x72,0x80,0xC0,
+    0xA7,0x7A,0x66,0x72,0xEA,0x7B,0xAE,0xEE,0xA7,0x7A,0x46,0x7A,0xAA,0x8A,0xE8,0x20,
+    0xA7,0x82,0x46,0x72,0xAA,0xAE,0x0A,0x0E,0xA7,0x7A,0x66,0x72,0xFB,0xBF,0xAA,0x0A,
+    0xA7,0x7A,0x66,0x72,0xFF,0xAF,0xEA,0xA8,0x87,0x7A,0x67,0x72,0x80,0xC0,0x8A,0xAF,
+    0x87,0x7A,0x46,0x72,0x68,0xE6,0x76,0xAF,0x67,0x7A,0x05,0x6A,0xAA,0x68,0xA8,0x22,
+    0x09,0x8B,0x05,0x6A,0xFD,0xFF,0xFD,0x0F,0x89,0x9B,0x46,0x72,0xDD,0xAD,0x2B,0x02,
+    0x8A,0x9B,0xC8,0x82,0xD5,0x2B,0x80,0x02,0x8A,0x9B,0x08,0x8B,0xF5,0xAE,0x8E,0x78,
+    0x29,0x8B,0x05,0x6A,0x80,0x20,0xE8,0x7E,0xC8,0x82,0xE5,0x69,0xA0,0xEA,0xDF,0x55,
+    0x46,0x6A,0xE6,0x69,0xFC,0xFF,0xDD,0xFF,0x26,0x6A,0xE5,0x61,0xFE,0xDA,0xAA,0x8A,
+    0x26,0x6A,0xC5,0x59,0x0A,0xAA,0xAB,0xDA,0x46,0x6A,0x84,0x51,0x2A,0x20,0xA8,0x5F,
+    0x67,0x72,0xA5,0x59,0x28,0xA8,0xEE,0x55,0x67,0x72,0xA5,0x59,0x20,0x0A,0xFB,0x55,
+    0x67,0x72,0x84,0x51,0x00,0x00,0xBA,0x5D,0x87,0x72,0x84,0x51,0x00,0x00,0xBA,0x55,
+    0xA8,0x7A,0x64,0x51,0x02,0xA8,0xFE,0x55,0x67,0x72,0x43,0x49,0xA0,0xA8,0xFF,0x55,
+    0x06,0x62,0x44,0x49,0x00,0x00,0x2E,0xE5,0xC5,0x59,0x23,0x49,0xF8,0x78,0x78,0x78,
+    0x65,0x49,0xE3,0x38,0x5F,0x7F,0xAA,0xAA,0x43,0x41,0xE3,0x38,0xFD,0xEF,0xFF,0xF8,
+    0x24,0x41,0xC2,0x30,0xF7,0xE7,0xAC,0xAA,0x03,0x39,0xA2,0x30,0xAA,0xA8,0xE8,0xFA,
+    0xE3,0x38,0xA2,0x28,0xA8,0xFC,0x7E,0x5F,0x03,0x39,0x81,0x20,0xA8,0xAE,0xD7,0x7D,
+    0x03,0x31,0x81,0x20,0xFC,0xFE,0xFF,0x55,0xC2,0x28,0x61,0x20,0xFF,0xEA,0x78,0x5E,
+    0x81,0x20,0x61,0x18,0xA8,0x28,0x80,0x76,0xA2,0x20,0x61,0x18,0xEA,0x7A,0x7F,0xFD,
+    0x82,0x20,0x61,0x18,0xCD,0x0B,0x3B,0xBA,0xC2,0x28,0x82,0x20,0xFD,0xFD,0xBB,0x2B,
+    0xE3,0x30,0x81,0x20,0xDD,0xF7,0xAB,0x0A,0xC2,0x28,0xA2,0x28,0xA7,0x35,0x95,0xAC,
+    0xE3,0x30,0xA2,0x28,0xAA,0xAB,0xF9,0x80,0x03,0x31,0xC2,0x28,0x7D,0xEF,0xAE,0x2F,
+    0xE2,0x30,0xA2,0x28,0x57,0x70,0xEC,0xE8,0xE3,0x28,0x82,0x28,0x5F,0xBF,0xBB,0xE2,
+    0xC2,0x28,0x81,0x28,0xF5,0xD6,0xEA,0xA8,0xA2,0x28,0x81,0x20,0xFA,0xAA,0x0A,0x0C,
+    0xC2,0x30,0x61,0x20,0xE9,0x8B,0x02,0x02,0xE3,0x30,0x81,0x28,0x7D,0x7B,0xE8,0xE0,
+    0xC2,0x28,0x61,0x20,0xF7,0xBF,0xAA,0x8A,0xC2,0x30,0xA2,0x28,0xD5,0x75,0x8D,0xC3,
+    0xC2,0x30,0xA2,0x28,0xBB,0x1F,0xDD,0x7F,0xC2,0x30,0xA2,0x28,0xF5,0xE2,0xF7,0xE5,
+    0xE3,0x30,0xA2,0x28,0x2F,0x0F,0xBD,0x85,0x03,0x31,0xC2,0x30,0xAA,0x0A,0x0B,0x3D,
+    0x03,0x31,0xC3,0x30,0xAA,0x08,0x2A,0xB7,0x24,0x39,0xE3,0x30,0x6B,0xFB,0xFF,0xED,
+    0x24,0x39,0xE3,0x38,0xBD,0xBB,0x97,0x55,0x44,0x41,0xE3,0x38,0xF3,0xAA,0xEE,0xFD,
+    0x03,0x39,0xE3,0x30,0xB5,0x0A,0x88,0x8C,0x24,0x41,0xC3,0x30,0xEF,0x2E,0x2F,0xB7,
+    0x24,0x39,0xC2,0x30,0xC9,0xAE,0xB6,0xEA,0x03,0x39,0xC2,0x30,0x1B,0xF2,0x20,0x00,
+    0x23,0x39,0xE2,0x30,0x76,0xBF,0x3F,0xF8,0xE2,0x30,0xC3,0x30,0x20,0x2D,0xB6,0xA8,
+    0x03,0x39,0xC2,0x30,0x7A,0xAB,0xAF,0x6B,0x02,0x39,0xC2,0x30,0xAF,0x2E,0xB7,0xFF,
+    0x03,0x39,0xC2,0x30,0x0F,0xAA,0xAF,0x73,0x24,0x41,0xC2,0x30,0xAA,0x0F,0x0A,0xA7,
+    0x43,0x41,0xE3,0x38,0xFF,0xEF,0xF6,0xF8,0x43,0x41,0x03,0x41,0xFF,0x3D,0x26,0xA7,
+    0x85,0x51,0x44,0x49,0x2F,0x8B,0x1F,0xDF,0x84,0x51,0x23,0x41,0x5C,0xE8,0xE3,0xA2,
+    0x44,0x49,0x03,0x41,0xE2,0xA2,0x2C,0xB4,0x64,0x49,0x23,0x41,0xDD,0xEB,0xAB,0xAB,
+    0x44,0x49,0x02,0x39,0xFE,0xD7,0xFA,0xFC,0x44,0x41,0x02,0x41,0x7F,0xEF,0xAB,0x8B,
+    0x43,0x41,0xE3,0x38,0xB2,0xAA,0x82,0x0A,0x44,0x41,0xE2,0x38,0xDB,0xFE,0xAA,0xE0,
+    0x64,0x49,0x03,0x39,0xD5,0xF5,0xBF,0x2D,0x64,0x49,0x23,0x41,0xF7,0x57,0xFA,0xF0,
+    0x84,0x49,0x22,0x41,0x8D,0xA7,0x29,0xAB,0x64,0x51,0x43,0x41,0x3E,0xDE,0x6F,0x2F,
+    0xA5,0x51,0x44,0x49,0xBB,0xF9,0xAB,0x8A,0xC5,0x59,0x84,0x51,0x2D,0xF5,0x0B,0x0B,
+    0x68,0x72,0xA4,0x51,0x2B,0x2D,0xAD,0x3F,0xD1,0xBC,0x0A,0x83,0x2F,0x2D,0xAD,0xAD,
+    0x73,0xCD,0x90,0xB4,0x2A,0x2B,0xED,0xFD,0x73,0xCD,0x11,0xBD,0xE2,0x8B,0x2B,0xA5,
+    0x73,0xCD,0xB0,0xAC,0x7A,0xB8,0xA0,0x80,0x12,0xBD,0x6F,0xAC,0x77,0x5F,0xDA,0x80,
+    0xF1,0xBC,0x4F,0xA4,0x5D,0xBF,0xAA,0x0A,0xD0,0xB4,0x2E,0xA4,0x9D,0xBF,0xBA,0x80,
+    0xD0,0xB4,0x2E,0x9C,0x7F,0xAA,0xA2,0x08,0xD0,0xB4,0x2E,0x9C,0xD5,0xAA,0x88,0x08,
+    0xD0,0xB4,0x2E,0x9C,0x77,0xFA,0xA8,0x80,0xB0,0xAC,0x0E,0x9C,0x55,0xEA,0xA8,0x0A,
+    0x8F,0xAC,0x0D,0x94,0xD7,0xFA,0xA8,0xAA,0x6F,0xA4,0x2E,0x9C,0xF6,0xAA,0xC0,0xBA,
+    0x6F,0xA4,0x0E,0x9C,0xF5,0xE2,0xEA,0xFA,0x4F,0xA4,0xED,0x93,0x7E,0xFC,0xAE,0xA2,
+    0x6F,0xA4,0x0E,0x9C,0xBD,0xAD,0x8D,0xAF,0x6F,0xA4,0x2E,0xA4,0x68,0x93,0x8E,0x77,
+    0x6F,0xA4,0x0E,0x9C,0xBA,0xFF,0x8F,0x3D,0x2E,0xA4,0xCC,0x93,0x5C,0x6A,0xEA,0x80,
+    0x2E,0xA4,0xCC,0x93,0x25,0x3D,0x95,0x17,0x90,0xAC,0x2E,0xA4,0xEA,0x2A,0x29,0xAB,
+    0x44,0x51,0x02,0x49,0xBC,0xAC,0xE6,0xB5,0x23,0x49,0xE2,0x48,0x28,0x00,0xF0,0xF0,
+    0x43,0x51,0x02,0x49,0x2F,0xB6,0x77,0x75,0x23,0x51,0xE2,0x40,0xA8,0xAF,0x2D,0x2D,
+    0x23,0x51,0x43,0x49,0xA0,0x2A,0x0B,0x78,0x84,0x59,0x23,0x51,0xD5,0x55,0xD5,0xDC,
+    0x63,0x59,0x02,0x49,0xAE,0xE8,0xFA,0xDA,0x43,0x51,0x02,0x49,0x3E,0xB6,0x5A,0xE3,
+    0x64,0x59,0x02,0x49,0x25,0xFB,0xBF,0xEF,0x23,0x51,0x02,0x49,0xA2,0xC2,0xA8,0x2A,
+    0x23,0x51,0x02,0x41,0xF2,0x72,0xFF,0xDF,0x23,0x49,0x03,0x49,0x55,0x16,0x38,0x17,
+    0x23,0x49,0x02,0x49,0x5A,0xF0,0x28,0xA0,0x43,0x49,0x03,0x49,0x55,0x55,0x15,0xFB,
+    0x23,0x49,0xE2,0x48,0xE2,0xA2,0xA8,0xF1,0x23,0x49,0xE2,0x48,0xB9,0xB3,0xBA,0x2A,
+    0xC8,0x82,0x02,0x49,0xF5,0xB5,0x2D,0x2F,0x4A,0x93,0xA7,0x7A,0xA9,0x8B,0xA2,0x8A,
+    0x29,0x8B,0xC7,0x82,0x78,0xD8,0x78,0x5E,0xE8,0x82,0xA7,0x7A,0xFA,0x58,0x6A,0xAA,
+    0xA7,0x7A,0x66,0x72,0x3C,0xE2,0x22,0x00,0xC7,0x82,0x66,0x72,0x7B,0x6F,0xAB,0xAF,
+    0xC7,0x82,0x66,0x7A,0xFB,0xE9,0xEA,0xFE,0xA7,0x82,0x66,0x72,0x3E,0x36,0xDF,0xB6,
+    0xA7,0x7A,0x87,0x7A,0xBD,0x35,0xFF,0xDC,0x87,0x7A,0x66,0x72,0x08,0x28,0x80,0x00,
+    0xA8,0x7A,0x46,0x72,0xEA,0xB2,0xFE,0xD7,0x86,0x7A,0x25,0x6A,0x83,0xFA,0xFA,0x3E,
+    0xE8,0x8A,0x46,0x72,0xDD,0xED,0xAF,0x2A,0x4A,0x93,0x47,0x72,0xD5,0xB7,0x2E,0x02,
+    0xAB,0xA3,0xA8,0x82,0x3D,0xAB,0x8A,0x00,0xAA,0xA3,0x49,0x93,0xAF,0x8A,0xA2,0x72,
+    0x8A,0x9B,0x27,0x72,0x00,0x80,0xE8,0x7E,0x49,0x93,0xC5,0x61,0xA8,0xFA,0x5F,0x55,
+    0x66,0x72,0xC4,0x61,0xF8,0x7F,0xF7,0xDD,0x06,0x6A,0xC5,0x61,0xCE,0xAD,0xB5,0xDF,
+    0x26,0x6A,0xC6,0x61,0xAA,0xA3,0xEA,0xDE,0x26,0x6A,0x23,0x49,0x00,0xA0,0x7A,0x5F,
+    0xE5,0x61,0x23,0x49,0xE8,0x5F,0x55,0x55,0x64,0x51,0x23,0x49,0x7A,0x5A,0x55,0x55,
+    0x64,0x49,0x03,0x41,0xA9,0xBE,0xA8,0xAF,0x43,0x49,0x23,0x41,0x00,0x8E,0xC9,0xCA,
+    0x64,0x49,0x23,0x49,0xF5,0xED,0x5D,0xF3,0x43,0x49,0x03,0x41,0xCA,0x6B,0xEE,0xA2,
+    0x43,0x49,0xE2,0x40,0x7A,0xBB,0xFA,0xE8,0x43,0x49,0xE2,0x40,0x72,0xFA,0x8F,0x2F,
+    0x85,0x51,0x03,0x41,0xAD,0x07,0xAF,0xAA,0x85,0x51,0x23,0x41,0x70,0x6C,0xFB,0xEA,
+    0x65,0x49,0xE3,0x38,0x0B,0xEA,0xBA,0x5E,0x44,0x41,0xE3,0x38,0xD8,0xAE,0xA7,0xDF,
+    0x24,0x41,0xC2,0x30,0x28,0xEA,0x8A,0x5E,0xE3,0x30,0x81,0x20,0xA8,0x48,0x7A,0xDF,
+    0xA2,0x28,0x81,0x20,0x82,0x0B,0x8B,0xC2,0xA2,0x28,0x81,0x20,0x50,0x56,0x76,0xA3,
+    0xA2,0x20,0x81,0x20,0xE5,0xEF,0xBB,0xF0,0xA1,0x20,0x61,0x18,0xDA,0x5A,0x5A,0x7A,
+    0x41,0x20,0x61,0x18,0xFD,0xDD,0x7F,0x77,0x81,0x20,0x41,0x18,0xAB,0x3B,0x2F,0x2B,
+    0xA2,0x28,0x61,0x18,0xBF,0x3F,0xAF,0xAB,0xE3,0x28,0x82,0x20,0xA3,0xAB,0xFF,0xE7,
+    0x03,0x31,0xA2,0x28,0x8F,0xEF,0xD5,0x5F,0x24,0x39,0xC2,0x28,0xBF,0xBF,0x09,0x89,
+    0x03,0x31,0xC2,0x30,0xF8,0x98,0x5A,0x5C,0x03,0x39,0xC2,0x30,0xAF,0xF7,0xEE,0x83,
+    0xE2,0x30,0xA2,0x28,0xFA,0x5A,0x6E,0xE0,0xC2,0x28,0x81,0x28,0x22,0xAA,0x9F,0xDE,
+    0x03,0x31,0xC2,0x28,0x55,0x95,0x9D,0xB5,0x03,0x31,0xC2,0x28,0x55,0xF5,0xB6,0xAC,
+    0x03,0x31,0xC2,0x28,0xFD,0xFA,0xFA,0xBE,0xE3,0x30,0xA2,0x28,0x7A,0x7C,0xEE,0xB6,
+    0xC2,0x30,0x81,0x28,0x0B,0xAA,0xFA,0xF8,0xE3,0x28,0x81,0x28,0xFB,0xFF,0xFD,0x75,
+    0xA2,0x28,0x81,0x28,0x20,0x20,0x2A,0x0B,0xA2,0x28,0x81,0x20,0x00,0xA0,0xA0,0xC2,
+    0xC2,0x28,0x81,0x28,0x0B,0xAB,0xBF,0xAF,0x03,0x31,0xA2,0x28,0x3F,0xFF,0xFF,0x7D,
+    0xE3,0x30,0xA2,0x28,0x34,0xAE,0xEB,0xDF,0x03,0x39,0xA2,0x28,0xAA,0xBF,0xFF,0xDD,
+    0xE3,0x30,0xA2,0x28,0x02,0xA7,0xAD,0xB6,0x24,0x39,0xC2,0x30,0xAF,0x8D,0x8F,0xE5,
+    0x24,0x39,0xE3,0x38,0xEF,0xEB,0xEB,0x7F,0x03,0x39,0xC2,0x30,0xFF,0xDA,0xFA,0xFF,
+    0x24,0x39,0xC2,0x30,0xAB,0x2F,0xBF,0xBF,0x23,0x39,0xE3,0x38,0x2B,0x3A,0x3E,0xFE,
+    0x23,0x39,0xE2,0x30,0xB0,0xA0,0xEA,0xFA,0x23,0x39,0xC2,0x30,0xFE,0xF8,0xFE,0xFB,
+    0x03,0x39,0xC1,0x30,0xB7,0x2B,0xB3,0xAA,0x23,0x41,0xC2,0x30,0xAF,0xAE,0x29,0x8B,
+    0x23,0x41,0xC2,0x30,0x52,0x78,0xAC,0xA8,0x03,0x39,0xA2,0x30,0x2B,0x8F,0xFA,0xF2,
+    0x24,0x41,0xE3,0x38,0xFA,0x7A,0x7F,0xF7,0x64,0x49,0x03,0x41,0xB5,0x25,0x35,0x05,
+    0x85,0x51,0x23,0x41,0xEF,0xFE,0x5C,0x5F,0x84,0x51,0x23,0x41,0xA2,0x2B,0xFF,0x75,
+    0x44,0x49,0x03,0x41,0x2C,0xB4,0xB4,0xF6,0x44,0x41,0x03,0x41,0x20,0x00,0x28,0x2F,
+    0x43,0x41,0xE3,0x38,0xA2,0xAA,0x86,0xFE,0x44,0x41,0x03,0x41,0x8A,0xEF,0x3F,0xD7,
+    0x44,0x41,0x03,0x39,0x2E,0xBE,0xF4,0xF6,0x64,0x49,0x03,0x41,0x42,0x82,0x03,0xED,
+    0xA5,0x51,0x03,0x41,0x2D,0xAF,0xEF,0xF5,0x85,0x51,0x23,0x41,0xAA,0x88,0xE2,0xF9,
+    0xA5,0x51,0x43,0x41,0xBF,0x2E,0x2F,0xA5,0xC5,0x51,0x64,0x49,0xD5,0xEA,0x0A,0x8A,
+    0xE5,0x59,0x84,0x51,0xED,0x3D,0x8B,0x0A,0x26,0x62,0xC5,0x59,0xDD,0xBE,0xFB,0x35,
+    0x47,0x6A,0xC5,0x59,0x3F,0xAF,0xB6,0xB7,0x0E,0xA4,0x67,0x6A,0x0F,0x0F,0x29,0x0D,
+    0xD1,0xBC,0x4F,0xAC,0x0B,0x2D,0xAD,0xFD,0x32,0xBD,0xB0,0xB4,0x2F,0x3F,0xF5,0xD5,
+    0x73,0xC5,0xF1,0xBC,0x8A,0xBA,0xD7,0xD5,0x53,0xC5,0x11,0xBD,0xFE,0x2A,0x2F,0x37,
+    0x73,0xCD,0x11,0xBD,0x75,0xAF,0xAA,0x80,0x73,0xC5,0xF0,0xB4,0x57,0x7E,0xAA,0x22,
+    0x52,0xC5,0xAF,0xAC,0x5D,0x5E,0x5E,0x7C,0xD0,0xB4,0x8F,0xAC,0x2B,0x8B,0x3F,0x15,
+    0xD0,0xB4,0x6F,0xAC,0xB2,0xBA,0xF8,0x7A,0xB0,0xAC,0x4E,0xA4,0xE8,0xE0,0xFA,0x56,
+    0x8F,0xAC,0x2E,0xA4,0xBA,0xAB,0xEA,0x7D,0x6F,0xA4,0x2E,0xA4,0x3F,0xEA,0xA9,0x29,
+    0x90,0xAC,0x2E,0x9C,0x7B,0x7E,0xAA,0x28,0x6F,0xAC,0xED,0x9B,0xFF,0x5F,0xEE,0xB0,
+    0x4F,0xA4,0x0E,0x9C,0x3B,0xEA,0xDE,0x56,0x4F,0xA4,0x0D,0x9C,0x38,0x3C,0x23,0xFB,
+    0x4E,0xA4,0x0E,0x9C,0x0A,0x0A,0xEB,0x7F,0x6F,0xAC,0x0D,0x9C,0x68,0xEA,0xBF,0xFF,
+    0x2E,0xA4,0xCD,0x93,0x36,0xB8,0xAC,0xE0,0x8F,0xAC,0x2E,0x9C,0xAB,0x0D,0x39,0x25,
+    0x23,0x49,0xE2,0x48,0x9C,0xC3,0x6B,0x2F,0x23,0x49,0xE2,0x40,0xB8,0x23,0xFE,0xEA,
+    0x23,0x51,0xE2,0x40,0xFE,0xFF,0x9D,0x3D,0x43,0x51,0xE2,0x48,0xAD,0x2B,0xAB,0x88,
+    0x63,0x51,0x23,0x51,0xFA,0x16,0x4F,0x6D,0x64,0x59,0x23,0x51,0xFE,0x67,0xEF,0xEE,
+    0x63,0x59,0x03,0x49,0xF7,0xFF,0x7A,0xE8,0x43,0x51,0x02,0x49,0xB0,0xE0,0xBA,0xA9,
+    0x43,0x51,0xE1,0x40,0xE2,0xEA,0xA2,0xF8,0x23,0x51,0x02,0x49,0x69,0x0A,0x2D,0x5D,
+    0x43,0x51,0xE2,0x40,0xDE,0xFF,0x2E,0xBE,0x02,0x49,0xE2,0x40,0xBC,0x28,0x38,0xB0,
+    0x23,0x49,0xE2,0x40,0xB0,0x0A,0x0A,0xBE,0x03,0x49,0x22,0x41,0x0A,0x08,0x8A,0xA0,
+    0x23,0x49,0xC2,0x40,0xBE,0xAF,0x3F,0x97,0x47,0x72,0x02,0x49,0xD5,0xF5,0xB5,0x2D,
+    0x29,0x8B,0xA4,0x61,0x2D,0x0B,0x02,0x00,0x4A,0x93,0xC8,0x82,0xAA,0xEA,0x7E,0xDC,
+    0x09,0x8B,0xC8,0x82,0x78,0xAF,0xEF,0x77,0xE8,0x82,0xA7,0x82,0xAA,0x58,0x5B,0xFB,
+    0xE8,0x82,0x87,0x7A,0x7E,0xFB,0xF2,0x80,0xC8,0x82,0x87,0x7A,0xFE,0x6A,0x42,0xAB,
+    0xC8,0x82,0x87,0x7A,0xDF,0x7F,0x5B,0xF8,0xC8,0x82,0x87,0x7A,0x55,0xD5,0xAF,0xBB,
+    0xC7,0x7A,0x66,0x7A,0xBA,0xA2,0x6A,0x7A,0xA7,0x7A,0x46,0x72,0xE2,0xFA,0xFB,0x7A,
+    0x66,0x7A,0x46,0x72,0x75,0x56,0xD8,0x1E,0x6B,0x9B,0x45,0x72,0xD5,0xF5,0xBD,0x2B,
+    0xAB,0xA3,0xC7,0x82,0xB5,0xAF,0x2A,0x00,0xCB,0xA3,0x6A,0x9B,0xA9,0x8B,0x28,0xA8,
+    0xAB,0xA3,0x09,0x8B,0x88,0xA0,0xE8,0x58,0x6A,0x9B,0xE5,0x69,0x80,0xE0,0x78,0x5F,
+    0x87,0x7A,0xA5,0x61,0xF8,0x5E,0xD5,0x57,0xE6,0x69,0xA5,0x61,0x72,0x7E,0xFA,0xEF,
+    0xE6,0x61,0xA4,0x61,0x5E,0x9F,0xA9,0x2A,0x26,0x6A,0x83,0x59,0xF7,0xBF,0xAA,0xCA,
+    0xE5,0x61,0x43,0x51,0xE8,0xF8,0x7A,0xFB,0x64,0x51,0x03,0x41,0xFC,0xF6,0xFA,0x8A,
+    0x64,0x49,0x03,0x41,0x5D,0x57,0xBF,0x2F,0x64,0x49,0x03,0x41,0xED,0x82,0x20,0xB0,
+    0x64,0x49,0x23,0x41,0xEF,0xEB,0x7C,0xFE,0x43,0x49,0x03,0x41,0x8C,0xEA,0xBA,0xC6,
+    0x44,0x49,0x03,0x41,0xAA,0xCA,0x7B,0x5D,0x43,0x41,0x03,0x41,0xFA,0xFA,0x79,0x7F,
+    0x43,0x49,0x03,0x41,0x7A,0xFE,0x5F,0xDD,0x44,0x49,0xE3,0x38,0x27,0xAB,0xEF,0xBE,
+    0x64,0x49,0x03,0x41,0x0A,0xAA,0xA9,0x8B,0x85,0x51,0x23,0x41,0xF0,0xFF,0xF7,0x55,
+    0x23,0x41,0xC3,0x30,0xF8,0xAA,0xA8,0x7C,0x03,0x39,0xA2,0x30,0x2A,0xA8,0xBE,0xD7,
+    0xE3,0x30,0xA2,0x28,0xEC,0xFE,0x7A,0xC0,0xA2,0x28,0x61,0x20,0xA8,0xFA,0xF8,0xFA,
+    0xA1,0x20,0x60,0x20,0x82,0x02,0x29,0xAB,0xC2,0x28,0x81,0x20,0xE2,0x75,0xF7,0x55,
+    0xA2,0x20,0x81,0x20,0xF0,0x7B,0x58,0x57,0x81,0x20,0x61,0x18,0xE8,0xAC,0xAA,0xCF,
+    0xA2,0x20,0x41,0x18,0xFE,0xBE,0xA7,0x2F,0xA2,0x20,0x61,0x20,0xAF,0xBA,0xA0,0x00,
+    0xA2,0x28,0x81,0x20,0x35,0xED,0xCA,0x08,0xE3,0x30,0xA2,0x28,0xF5,0xE5,0x3D,0x2A,
+    0x03,0x31,0xA2,0x28,0x7F,0x7F,0x78,0xE0,0x24,0x39,0xA2,0x28,0x0F,0x09,0x09,0x2F,
+    0x44,0x41,0xC2,0x30,0x5C,0x58,0xFC,0x5C,0x03,0x39,0xC2,0x30,0x81,0x80,0x8A,0xFA,
+    0x03,0x39,0xA2,0x28,0x5A,0xFA,0xFA,0xFE,0xC2,0x30,0x81,0x28,0x5B,0x7E,0xBF,0xAA,
+    0xE2,0x30,0x81,0x20,0x25,0x8B,0xBF,0xFF,0x03,0x31,0xA1,0x28,0xAE,0x2E,0x9D,0xD5,
+    0xE2,0x30,0xA2,0x28,0x22,0xA0,0xFA,0x7E,0xC2,0x30,0xA2,0x28,0x2A,0x2A,0xEE,0xBE,
+    0xE3,0x30,0xA2,0x28,0x5F,0x5F,0x7A,0x5A,0xA2,0x28,0x82,0x20,0xF2,0x60,0xC0,0x00,
+    0xA2,0x28,0x81,0x20,0x2E,0x9E,0x7F,0xCB,0xC2,0x28,0x81,0x20,0xEB,0x8F,0x89,0xA3,
+    0xC2,0x28,0xA2,0x28,0xF7,0x6D,0xC9,0xE9,0xC1,0x28,0x82,0x28,0xAA,0xDA,0xFE,0xFE,
+    0xE3,0x30,0xA2,0x28,0x57,0x7F,0x6B,0x59,0xC2,0x30,0xA2,0x28,0xAB,0xAF,0xC9,0x88,
+    0xC2,0x30,0xA2,0x28,0xAC,0xAC,0xAB,0x8B,0xE2,0x38,0xA2,0x28,0xAB,0x3F,0xBF,0xBF,
+    0x03,0x39,0xC2,0x30,0xAA,0x5F,0x7F,0x55,0xE3,0x38,0xA2,0x30,0x88,0xEA,0xDA,0xFF,
+    0xE3,0x38,0xC2,0x30,0x3E,0x59,0xFF,0x6D,0x03,0x39,0xC2,0x30,0xF2,0xB2,0xB5,0x0D,
+    0x23,0x39,0xE3,0x38,0x8F,0xB7,0xFE,0x8F,0x23,0x39,0xC3,0x30,0xF8,0xAA,0xBE,0xEB,
+    0x02,0x41,0xE3,0x30,0x55,0x7F,0xDF,0xFD,0x23,0x41,0xE2,0x30,0x09,0x2F,0x3F,0xAF,
+    0x24,0x41,0xE2,0x38,0xE8,0xEC,0x77,0x4D,0x03,0x39,0xC2,0x30,0xAC,0xE7,0x6B,0x7F,
+    0x23,0x41,0xC2,0x30,0xAA,0x2F,0x3D,0xD5,0x64,0x49,0xE3,0x38,0x2F,0xAA,0x03,0x0F,
+    0xA5,0x51,0x43,0x41,0x5B,0x60,0xFE,0xAA,0x64,0x49,0x03,0x41,0xFB,0xDA,0xA8,0xBC,
+    0x44,0x49,0xC2,0x38,0xAF,0xFE,0xD4,0xFA,0x44,0x41,0xE2,0x38,0x2B,0x2F,0xEF,0x7F,
+    0x44,0x41,0xC2,0x38,0xFC,0x5E,0xF7,0xEF,0x03,0x39,0xC2,0x38,0xBA,0xFF,0x7A,0xE2,
+    0x24,0x41,0xE3,0x38,0xEA,0x7F,0xDD,0xFF,0x23,0x41,0xE3,0x38,0x89,0x5D,0x5F,0xCD,
+    0x03,0x39,0xC2,0x30,0x8A,0xFF,0xFF,0xAA,0x43,0x41,0xE2,0x38,0x37,0x27,0xED,0xAD,
+    0x64,0x49,0x02,0x41,0xA8,0xEB,0xEF,0xF5,0xA4,0x51,0x23,0x41,0x8B,0x2E,0x7B,0xDF,
+    0xC5,0x51,0x43,0x41,0x2A,0xAF,0xEB,0x5D,0xE6,0x61,0x63,0x49,0x0A,0xAA,0xFF,0xD5,
+    0xE6,0x61,0x43,0x49,0x20,0xBB,0xDF,0xDF,0xED,0x9B,0x06,0x62,0x2F,0x29,0x2D,0x2D,
+    0x8F,0xAC,0xED,0x9B,0x0B,0xAA,0xA9,0xAB,0xD0,0xB4,0x4E,0xAC,0x2E,0xAF,0x37,0xDD,
+    0xF1,0xBC,0x90,0xAC,0x00,0x00,0xAB,0xBD,0x52,0xC5,0xB0,0xB4,0x2E,0x9F,0x57,0xFB,
+    0x73,0xCD,0xF1,0xB4,0x82,0x02,0xAD,0xB5,0x73,0xC5,0x32,0xC5,0xFD,0xD6,0x7E,0xA9,
+    0x52,0xC5,0xB0,0xB4,0x5A,0x7A,0xE8,0xA8,0xF1,0xBC,0x6F,0xAC,0xF7,0xD7,0xFE,0x58,
+    0x90,0xAC,0x4F,0xA4,0x0F,0xFA,0x6A,0xF8,0x8F,0xAC,0x2E,0xA4,0xEA,0x6F,0x6A,0x3A,
+    0x6F,0xAC,0x0E,0x9C,0xFF,0xFD,0xAE,0xA8,0x4E,0xA4,0x0D,0x9C,0x2A,0x72,0xFA,0xA0,
+    0x90,0xAC,0x2E,0xA4,0x2E,0xA3,0xA5,0xBF,0x90,0xAC,0x0D,0x9C,0x9A,0x82,0x0A,0x0A,
+    0x90,0xAC,0x2E,0x9C,0x5F,0xFB,0xA2,0xA8,0x6F,0xAC,0x0D,0x9C,0xEF,0xDE,0xDE,0xBC,
+    0x4E,0xA4,0x0E,0x9C,0xFF,0xEE,0xA8,0x00,0x4F,0xA4,0xED,0x9B,0x2A,0x8A,0xCE,0x60,
+    0x4E,0xA4,0x0E,0x9C,0x7F,0x5F,0xB8,0x3F,0x6F,0xAC,0x0E,0x9C,0x09,0x29,0xA9,0xAD,
+    0x23,0x49,0xE2,0x40,0xA3,0x35,0xFE,0xF6,0x43,0x51,0xC2,0x40,0xFA,0xDE,0xAD,0x2B,
+    0x43,0x51,0xE2,0x40,0xAD,0x3F,0x0B,0x02,0x64,0x59,0x23,0x51,0xBD,0x8A,0x2A,0xAB,
+    0x84,0x59,0x02,0x49,0xFE,0xF6,0xFC,0xEA,0x64,0x51,0x22,0x51,0xBF,0xB7,0x15,0xF7,
+    0x63,0x59,0x23,0x51,0xD0,0xB8,0xDA,0xFF,0x43,0x51,0x23,0x49,0x53,0x63,0x68,0x7E,
+    0x23,0x49,0x03,0x49,0xB8,0xAF,0x31,0xAF,0x23,0x49,0x02,0x49,0xD7,0x97,0x24,0x8C,
+    0x23,0x49,0xE2,0x48,0x90,0xA2,0xA8,0xAA,0x23,0x49,0xE2,0x40,0x76,0xBA,0xA2,0x0A,
+    0x23,0x49,0xE2,0x40,0xF3,0xF2,0xF0,0xB8,0x44,0x51,0xE2,0x40,0xD7,0xFF,0xCF,0xE8,
+    0xA4,0x59,0x03,0x49,0x55,0x55,0xD5,0x15,0xAC,0xA3,0x43,0x51,0xA5,0x2F,0x83,0x0A,
+    0x49,0x93,0x08,0x8B,0x5B,0x5E,0x5E,0x56,0x08,0x8B,0xC8,0x82,0xD8,0xDA,0x02,0x03,
+    0xE8,0x8A,0xC8,0x82,0xFE,0xFE,0x40,0x6B,0xC7,0x82,0xA7,0x82,0xC0,0x88,0xC9,0xEE,
+    0xC7,0x82,0xA7,0x7A,0x00,0xEC,0xF9,0x1A,0xC7,0x82,0x87,0x7A,0x1B,0x88,0xA0,0x00,
+    0xC7,0x82,0x86,0x7A,0xEF,0x9E,0xDA,0xDC,0xE7,0x82,0x86,0x7A,0xF7,0x77,0x54,0x5F,
+    0xA7,0x82,0x45,0x7A,0xE8,0xFB,0x7F,0xFE,0xE8,0x8A,0x45,0x72,0x55,0xF5,0xBF,0x2F,
+    0xAB,0xA3,0x66,0x7A,0xD5,0xB5,0x2B,0x02,0xCB,0xA3,0x29,0x93,0xA5,0xA3,0x00,0x00,
+    0xCB,0xA3,0x6A,0x9B,0x2B,0x0A,0x02,0x78,0xCB,0xA3,0xA7,0x7A,0x80,0xA0,0xE8,0x5E,
+    0x49,0x93,0x06,0x6A,0xE0,0x7E,0x5F,0x57,0x27,0x72,0x84,0x59,0xA8,0xEE,0xFE,0x5E,
+    0xC5,0x61,0x64,0x59,0x28,0xE8,0xAB,0xA7,0x06,0x6A,0xA4,0x59,0xEF,0xBD,0x9D,0x35,
+    0x06,0x6A,0xC5,0x61,0x0B,0x6A,0x7B,0x58,0x06,0x6A,0xA5,0x59,0xC8,0xEA,0x6A,0x5C,
+    0xA5,0x59,0x44,0x49,0x48,0xFC,0xEC,0x7C,0x64,0x51,0x44,0x49,0xAD,0xF2,0xD0,0xF5,
+    0x64,0x49,0x23,0x49,0xFA,0x5C,0xF7,0xAE,0x64,0x49,0xE2,0x40,0xAA,0xAB,0xAE,0xFC,
+    0x43,0x49,0x03,0x41,0xAA,0xAA,0xEA,0x7A,0x43,0x49,0x02,0x41,0x0A,0xCB,0xEB,0xFA,
+    0x43,0x49,0x03,0x41,0x5A,0xEF,0xFF,0x7F,0x24,0x49,0xE3,0x40,0x8E,0xEF,0xAF,0xAF,
+    0x23,0x49,0xE2,0x40,0x9F,0xAE,0x3A,0xFE,0x43,0x41,0xE3,0x40,0x1F,0xB7,0xBF,0xEF,
+    0x64,0x49,0x03,0x41,0xC2,0xE2,0xFB,0xFA,0x44,0x49,0xE2,0x38,0xF8,0xFC,0x5E,0x75,
+    0x03,0x39,0xA2,0x30,0xF8,0xB8,0xDB,0xFD,0xC2,0x30,0xA2,0x30,0x3E,0x3E,0x2C,0x8A,
+    0xE3,0x30,0xC2,0x30,0xEB,0xDF,0x89,0x83,0xC2,0x28,0x61,0x20,0xFE,0xD8,0xD8,0xF8,
+    0x81,0x20,0x61,0x18,0x00,0x28,0x28,0xA0,0x81,0x20,0x61,0x18,0x28,0xA8,0xAA,0xCB,
+    0x81,0x20,0x61,0x18,0x80,0xE8,0xFF,0x55,0x82,0x20,0x61,0x18,0xEB,0x2B,0x89,0x35,
+    0x82,0x20,0x61,0x18,0x0A,0x0F,0x28,0x08,0xA2,0x28,0x82,0x18,0x22,0x01,0x02,0x82,
+    0xA2,0x28,0x82,0x20,0x0A,0x8B,0xAF,0xFA,0xE3,0x30,0x81,0x28,0x28,0xA2,0xFF,0x97,
+    0x03,0x31,0xA2,0x28,0x80,0x8F,0x8D,0xAF,0x24,0x39,0xC2,0x30,0x35,0xB7,0xB5,0x55,
+    0x03,0x39,0xA2,0x28,0xF0,0xF0,0x7E,0xDA,0xE2,0x38,0xA2,0x30,0xF2,0xE2,0xEB,0x60,
+    0x04,0x39,0xA2,0x28,0xFE,0xEA,0x8F,0xB5,0x03,0x39,0xA2,0x28,0xFF,0xEF,0xA2,0xA2,
+    0x02,0x31,0x80,0x28,0x7F,0x7E,0xB8,0xA8,0xC2,0x30,0xA1,0x28,0x9D,0xD5,0x7F,0xE8,
+    0xC2,0x28,0x81,0x20,0xF8,0xEE,0x7A,0xE0,0xE3,0x28,0x81,0x28,0xFF,0xFF,0xB5,0xF5,
+    0xC2,0x28,0x82,0x20,0xE0,0x68,0x6A,0xAE,0xC2,0x30,0xA2,0x28,0xD5,0xB5,0xE5,0xA9,
+    0xC2,0x30,0xA2,0x28,0x75,0x55,0xBD,0xFE,0xE3,0x30,0x81,0x28,0xFF,0xF7,0xBF,0x8B,
+    0xC2,0x30,0xA2,0x28,0x75,0xF4,0xE0,0x5F,0xC2,0x28,0x81,0x20,0xF6,0x8F,0x82,0xEA,
+    0xC2,0x30,0xA2,0x28,0x2B,0xAA,0x81,0xDB,0xE3,0x30,0xA2,0x28,0xFB,0x2F,0x3A,0x56,
+    0xE2,0x30,0xA2,0x28,0xEF,0xF5,0x37,0xAF,0x03,0x39,0xC2,0x30,0x55,0x65,0xCB,0xAF,
+    0xE2,0x30,0xA2,0x28,0xBB,0xF5,0xEF,0xF8,0xE2,0x30,0xA2,0x30,0xFF,0xAA,0xA3,0xA8,
+    0x03,0x39,0xC2,0x30,0xE9,0xF9,0x7F,0xDD,0x44,0x41,0xC2,0x30,0xB5,0x3D,0x2F,0xBF,
+    0x44,0x41,0x03,0x39,0x6F,0xAA,0x8E,0x09,0x44,0x41,0xE3,0x38,0xFB,0x6B,0xEA,0xE2,
+    0x03,0x39,0xC2,0x30,0xAB,0x87,0x3F,0xBB,0x23,0x39,0x02,0x39,0xE9,0x69,0x59,0x42,
+    0x03,0x39,0xC2,0x30,0x68,0xB8,0x0E,0xAC,0x03,0x39,0xC2,0x30,0xDF,0xBE,0x9C,0xCC,
+    0x03,0x39,0xA2,0x30,0x7D,0xF7,0xEB,0xF3,0x64,0x49,0xC2,0x30,0x0D,0x3D,0x2D,0x2F,
+    0xC5,0x59,0x64,0x49,0x73,0xE8,0xEB,0x8E,0x85,0x51,0x03,0x41,0xDA,0x7A,0xD0,0xA8,
+    0x24,0x41,0xC2,0x38,0xA0,0x82,0x60,0xEA,0x03,0x39,0xC2,0x30,0xE0,0xE2,0xA9,0x25,
+    0x03,0x41,0xE2,0x30,0x37,0x8F,0xF9,0xF5,0x44,0x41,0xE3,0x38,0xE5,0xA9,0x29,0x0B,
+    0x23,0x39,0xE2,0x38,0xAA,0xEA,0x78,0xE8,0x23,0x39,0xE2,0x38,0x95,0x97,0xBF,0xFB,
+    0x24,0x41,0xC2,0x30,0xB7,0xBE,0xFF,0x2B,0x64,0x49,0xE3,0x38,0xE5,0xEF,0xAB,0x2A,
+    0x85,0x49,0x23,0x41,0xFF,0xF5,0x2B,0x0A,0x84,0x49,0x44,0x49,0x5F,0x8B,0x01,0x8A,
+    0x64,0x49,0x23,0x41,0xE2,0x68,0xE2,0x08,0xE6,0x59,0x44,0x49,0xFD,0x7F,0xEF,0x0B,
+    0xC5,0x59,0x64,0x49,0x96,0xF5,0xA2,0x0C,0xAC,0x93,0xA4,0x51,0x2D,0x3D,0xAD,0xAD,
+    0x6F,0xAC,0xCD,0x93,0x8A,0x89,0xA9,0x8D,0x6F,0xAC,0x2E,0xA4,0x8A,0x3A,0x27,0xA5,
+    0xB0,0xB4,0x2E,0xA4,0x0A,0xAA,0xBF,0x5F,0x31,0xBD,0x4F,0xA4,0x22,0x2A,0xAD,0xF5,
+    0x52,0xC5,0xD0,0xB4,0xAF,0xAA,0xA2,0x89,0x32,0xC5,0xD0,0xB4,0x0A,0x00,0x6E,0xF8,
+    0x52,0xC5,0xD0,0xB4,0xE8,0xAA,0xFF,0x7F,0xD0,0xB4,0x6F,0xAC,0x78,0xF8,0xE8,0xAE,
+    0xB0,0xAC,0x6F,0xAC,0x7F,0xEB,0xBE,0xAA,0xB0,0xB4,0x4E,0xA4,0xF5,0xFE,0xB2,0xE0,
+    0x8F,0xAC,0x4F,0xA4,0x7A,0x7A,0xBD,0xDD,0x6F,0xAC,0x2E,0xA4,0x9E,0x2E,0x28,0x2A,
+    0x90,0xAC,0x4F,0xA4,0x55,0x0A,0x0E,0xAC,0x8F,0xAC,0x4F,0xA4,0xBF,0xFE,0xE9,0xAF,
+    0x8F,0xAC,0x4F,0xA4,0xDB,0xEE,0xFE,0xAA,0x8F,0xAC,0x2E,0xA4,0xDA,0xF2,0x2A,0xCB,
+    0x90,0xAC,0x4E,0xA4,0xFF,0x5A,0xD2,0xB7,0x6F,0xAC,0x2E,0xA4,0x5C,0xEE,0xC2,0xA3,
+    0x8F,0xB4,0x0E,0xA4,0xF5,0x6B,0xEB,0x8A,0x6F,0xAC,0x2E,0xA4,0xAD,0xF9,0x9A,0x80,
+    0x02,0x49,0xE2,0x40,0xF6,0xDC,0xF5,0x35,0x84,0x59,0x03,0x49,0xAD,0x35,0xB5,0xAD,
+    0x63,0x59,0x43,0x51,0x6F,0xC2,0xE9,0x77,0x64,0x59,0x23,0x51,0xF2,0xE3,0xFF,0xFE,
+    0x84,0x59,0x22,0x51,0x56,0xD7,0xF7,0xF7,0x63,0x59,0x02,0x49,0x7A,0x3E,0xFA,0xF8,
+    0x43,0x51,0x02,0x49,0x8A,0xA8,0x3A,0x7E,0x43,0x49,0x02,0x49,0x7B,0xF8,0xD8,0x95,
+    0x23,0x49,0x02,0x49,0x36,0x0F,0x07,0x1F,0x43,0x51,0x03,0x49,0x6F,0x6A,0x5E,0x55,
+    0x23,0x49,0xE2,0x40,0xFE,0xAB,0x0A,0x2E,0x23,0x49,0xC1,0x40,0x8E,0xB6,0x8E,0xA8,
+    0x43,0x49,0xE2,0x40,0x3E,0xDF,0xDF,0xFF,0x23,0x49,0xE2,0x40,0xE0,0xE0,0xE2,0xF2,
+    0xA7,0x7A,0x02,0x41,0x95,0xB5,0x25,0x25,0x0C,0xAC,0x2A,0x8B,0x89,0x83,0x02,0x02,
+    0xAB,0xA3,0x08,0x8B,0x5F,0xE8,0xF8,0xBA,0x69,0x93,0xE7,0x8A,0x5F,0xFE,0x68,0xA2,
+    0x08,0x8B,0xC8,0x8A,0xEF,0xF8,0xE0,0xB0,0xE8,0x8A,0xA7,0x82,0xBF,0xAE,0xFC,0xDA,
+    0xE7,0x82,0x86,0x7A,0x6B,0xEA,0x2A,0xAF,0xE8,0x82,0xA7,0x7A,0x77,0x57,0xF8,0x6E,
+    0xC7,0x82,0x86,0x7A,0x6E,0x7A,0xF8,0x58,0xA6,0x82,0x66,0x7A,0x92,0xDA,0xE5,0xEB,
+    0x29,0x93,0x86,0x7A,0x55,0x55,0xF5,0x0F,0xAB,0xA3,0x87,0x82,0xA5,0x2F,0x0A,0x02,
+    0xCB,0xA3,0x8A,0x9B,0xA9,0x0F,0x28,0x00,0xEC,0xAB,0x8A,0x9B,0xE8,0xB8,0xFE,0x5E,
+    0x8B,0x9B,0x26,0x72,0x80,0xE0,0x78,0x56,0xC8,0x82,0x26,0x6A,0x78,0x56,0x55,0x55,
+    0x47,0x72,0x05,0x6A,0x7E,0xB7,0x75,0x57,0xE5,0x69,0x84,0x59,0x7A,0x78,0x7C,0xD6,
+    0xC5,0x61,0x84,0x59,0x2F,0x2D,0x2A,0xAF,0x05,0x6A,0xA4,0x59,0x2B,0xAF,0x2F,0x2D,
+    0x26,0x6A,0xC5,0x61,0x5E,0xDC,0x7E,0x5E,0x06,0x6A,0x64,0x51,0x78,0x7B,0x5F,0x5F,
+    0x85,0x59,0x23,0x41,0xF0,0xFA,0x7E,0x5F,0x64,0x49,0x23,0x49,0xA9,0x15,0xB5,0x2E,
+    0x64,0x49,0x23,0x41,0xB7,0xB6,0x3A,0x82,0x64,0x49,0x03,0x41,0xFC,0x60,0xAB,0xAA,
+    0x43,0x49,0x03,0x41,0x5B,0x7D,0x72,0xAA,0xA5,0x51,0x02,0x41,0x7F,0x7F,0xBF,0x0B,
+    0xC5,0x61,0xC2,0x38,0xFF,0xFF,0x8A,0x00,0xE6,0x61,0xE2,0x40,0xD5,0xFF,0xAB,0x00,
+    0xE5,0x59,0x23,0x41,0x55,0xDF,0xAA,0x00,0xC6,0x59,0x03,0x41,0x55,0xFF,0xA0,0x80,
+    0x64,0x49,0x03,0x41,0x7A,0xFE,0xBC,0xFE,0x23,0x41,0xC2,0x38,0xFB,0x9A,0xFE,0xF0,
+    0x03,0x39,0xA2,0x28,0xFF,0x7C,0x74,0x56,0xE3,0x30,0xA2,0x28,0xB9,0x2B,0xB9,0xFD,
+    0xE3,0x30,0xA2,0x28,0xA8,0xFA,0xF0,0x79,0xC2,0x28,0x81,0x20,0x5A,0x7E,0x7A,0x5F,
+    0xA2,0x20,0x61,0x20,0xFF,0xFA,0xEA,0x83,0xA2,0x20,0x61,0x18,0xCB,0xEA,0x7F,0xEE,
+    0x61,0x18,0x41,0x18,0xAB,0x2F,0x0F,0x08,0xA2,0x20,0x41,0x18,0xFF,0xDF,0xFF,0x2E,
+    0xC2,0x28,0x82,0x20,0xF9,0xA9,0xAB,0x8A,0xC2,0x28,0x81,0x20,0xEB,0xBA,0xE8,0xEE,
+    0xA2,0x28,0x82,0x20,0xBC,0x94,0x3D,0x3F,0xA2,0x28,0x81,0x28,0x0E,0x88,0xB8,0x80,
+    0xE3,0x30,0x81,0x28,0x8B,0xAB,0x7F,0xFF,0xC2,0x30,0x82,0x28,0x3A,0xAF,0x8F,0x0F,
+    0xE2,0x30,0xA2,0x28,0xDE,0x9D,0x2D,0x8B,0xE3,0x30,0xA2,0x30,0xF0,0xFA,0xFE,0xDF,
+    0xE3,0x30,0xA2,0x30,0xAD,0xAA,0xBA,0xFE,0x03,0x39,0xC2,0x30,0xAA,0x83,0x03,0xA1,
+    0xE2,0x30,0xC2,0x30,0xF8,0xE0,0x00,0x00,0x03,0x39,0xA1,0x28,0xFF,0xDF,0xD7,0x72,
+    0x03,0x39,0xA2,0x28,0x7B,0xFF,0xAB,0x2B,0x04,0x39,0xA2,0x28,0x55,0x57,0x7E,0xF8,
+    0xC2,0x30,0xA2,0x28,0xFD,0x3D,0x9A,0x9A,0xE3,0x30,0xA2,0x28,0xE9,0x7F,0xFA,0x68,
+    0xC2,0x30,0xA2,0x28,0xAA,0xAF,0x2D,0xAE,0xE2,0x30,0xA2,0x28,0x8B,0xEF,0xEE,0xFF,
+    0xC2,0x30,0xA2,0x28,0xD7,0xA5,0xA6,0xF7,0xE3,0x30,0x81,0x28,0x2B,0x7A,0x7F,0xFF,
+    0xC2,0x28,0x81,0x28,0x3B,0xA9,0xFD,0xAD,0xC3,0x30,0x82,0x28,0xB8,0xAE,0xFA,0xFE,
+    0xC2,0x28,0x81,0x28,0x00,0x22,0xAF,0x0F,0xE2,0x30,0xC2,0x28,0xAF,0x9F,0x27,0x25,
+    0xE2,0x30,0xC2,0x30,0xD4,0xF0,0xA2,0xFD,0xE2,0x30,0xA2,0x30,0xC8,0x80,0x80,0xA2,
+    0x03,0x39,0xA2,0x30,0xEF,0xFD,0xAA,0xE8,0x03,0x39,0xC2,0x30,0xA7,0xD7,0xEF,0xEF,
+    0x24,0x39,0xC3,0x30,0xAB,0x2F,0x3B,0xFF,0x44,0x41,0x03,0x39,0xEA,0xEA,0xEB,0x7D,
+    0x03,0x39,0xC2,0x30,0xBA,0x3E,0xE6,0x54,0x23,0x39,0xE2,0x30,0xA0,0xEA,0xB5,0xF7,
+    0x02,0x39,0xC2,0x30,0xBE,0x9E,0xBB,0xFA,0x03,0x39,0xC2,0x30,0x08,0xA2,0xD8,0xDA,
+    0xE2,0x38,0x03,0x31,0x08,0x80,0x80,0x6A,0x85,0x51,0x03,0x39,0x25,0x25,0xBD,0xBD,
+    0xA5,0x51,0x44,0x41,0x02,0xCA,0x7B,0x5F,0x85,0x49,0x24,0x41,0xE8,0xE2,0xEA,0xDF,
+    0x44,0x49,0xC3,0x38,0xEE,0x7A,0x7A,0xEC,0x03,0x39,0xC2,0x30,0x24,0x0F,0x2F,0xA9,
+    0x03,0x39,0xC2,0x30,0x3C,0xE8,0xEF,0xAF,0x23,0x39,0xE3,0x38,0x02,0x3D,0xFB,0xE6,
+    0x24,0x41,0xE3,0x38,0xC8,0xFA,0xF7,0xF5,0x03,0x39,0xC2,0x30,0xA2,0x2C,0xF7,0xFF,
+    0x24,0x41,0x03,0x39,0xB7,0xA3,0x0B,0xA5,0x64,0x49,0x24,0x41,0xBD,0xF5,0xAD,0x29,
+    0xA5,0x51,0x23,0x41,0xA9,0x0B,0x03,0x00,0xE6,0x59,0x85,0x51,0x55,0xFD,0xAD,0x3F,
+    0xE6,0x59,0x43,0x49,0xD7,0xBA,0xB8,0xA0,0xE6,0x59,0xA5,0x51,0x89,0x0A,0x82,0xAB,
+    0x06,0x62,0xA5,0x49,0xBF,0xB2,0xAF,0xFE,0x4B,0x83,0xE5,0x59,0x2D,0x2D,0x2D,0x2D,
+    0x2E,0xA4,0x8C,0x8B,0x2B,0xAD,0xAF,0xAD,0x4F,0xA4,0xED,0x9B,0x0E,0xA7,0xBD,0xF5,
+    0x6F,0xAC,0x0E,0xA4,0x0B,0xAF,0x7F,0xDF,0x8F,0xAC,0x2E,0xA4,0x27,0xAA,0xAB,0xFD,
+    0xF1,0xBC,0x0E,0xA4,0x0A,0xAF,0xBF,0xD7,0xF1,0xBC,0xB0,0xB4,0xA8,0xBB,0xBB,0x95,
+    0x11,0xBD,0xB0,0xB4,0x02,0x0A,0x2A,0xBD,0x31,0xBD,0xB0,0xB4,0x57,0x7C,0xFA,0xAA,
+    0xF0,0xBC,0x8F,0xAC,0xDF,0xDE,0xBE,0xFA,0xB0,0xB4,0x6F,0xAC,0x7B,0xAA,0xEF,0xBC,
+    0x90,0xAC,0x4F,0xA4,0xD7,0xFA,0x90,0xB8,0x8F,0xAC,0x2E,0xA4,0x8F,0x9A,0x82,0xA2,
+    0xAF,0xB4,0x4F,0xA4,0xBD,0xFF,0xFF,0x73,0x8F,0xAC,0x4F,0xA4,0xAB,0xBF,0xF7,0x75,
+    0x8F,0xAC,0x2E,0xA4,0x0A,0x2A,0x2B,0xE9,0x90,0xAC,0x4E,0xA4,0xE7,0xEE,0xE2,0xAB,
+    0x8F,0xAC,0x4E,0xA4,0xE2,0xAA,0xAB,0xF7,0x6F,0xAC,0x2E,0xA4,0xBB,0x0C,0xA0,0xBA,
+    0x8F,0xAC,0x2E,0xA4,0x2C,0xFF,0x6F,0xFB,0x6F,0xAC,0x0D,0x9C,0x28,0xBB,0x9F,0xFF,
+    0x64,0x59,0xE2,0x40,0xF5,0xAB,0x2A,0xAA,0x64,0x51,0x23,0x51,0xBD,0xB9,0x2F,0xE3,
+    0x84,0x59,0x43,0x51,0x7F,0xDC,0xEE,0xBF,0x84,0x59,0x43,0x51,0x7D,0x79,0xAB,0xEE,
+    0x64,0x59,0x22,0x51,0xF5,0x56,0xBC,0xE8,0x43,0x51,0x02,0x49,0xB8,0xDA,0xE8,0xFA,
+    0x64,0x51,0x02,0x49,0xFF,0xBF,0x7F,0xF2,0x23,0x49,0xE2,0x40,0x29,0x3E,0xDA,0x02,
+    0x43,0x51,0x03,0x49,0xF6,0xFF,0xBA,0xAF,0x23,0x49,0x02,0x41,0x80,0x42,0xA0,0x7A,
+    0x23,0x49,0xE2,0x40,0x3B,0x23,0xAF,0x9F,0x23,0x49,0xE2,0x40,0xA0,0x3E,0xBE,0x2E,
+    0x23,0x49,0x02,0x41,0x1B,0xF6,0xD6,0xFC,0x44,0x49,0x02,0x49,0x5F,0x57,0x95,0x95,
+    0x8A,0x9B,0x43,0x51,0xB5,0x2D,0x2D,0x2D,0x0C,0xAC,0x8A,0x93,0x82,0xAA,0x62,0xE2,
+    0xAB,0x9B,0x49,0x93,0xFC,0xF8,0xFA,0xDD,0x69,0x9B,0x08,0x8B,0xE0,0x78,0xFC,0x78,
+    0x08,0x8B,0xE8,0x8A,0x80,0x77,0xFE,0x9C,0x08,0x8B,0xA7,0x82,0xBF,0x6F,0xEF,0xB2,
+    0xE8,0x82,0xA7,0x82,0xBE,0x7B,0xAE,0xAB,0xC7,0x82,0x86,0x7A,0xEE,0xEA,0x83,0xCA,
+    0xC7,0x82,0x87,0x7A,0xBA,0xEF,0xBF,0xAA,0x8A,0x9B,0x87,0x7A,0x5D,0xB7,0x2F,0x0B,
+    0xCB,0xA3,0x08,0x8B,0x25,0x09,0x02,0x00,0xEA,0xAB,0xAB,0xA3,0x65,0xEF,0xFB,0xFA,
+    0xEC,0xAB,0xC8,0x82,0x20,0xA8,0xF0,0x7E,0x8A,0x9B,0x46,0x72,0xE0,0x78,0x5E,0x55,
+    0x67,0x7A,0x05,0x6A,0xDC,0xFF,0x7F,0x77,0x67,0x72,0x06,0x6A,0xFD,0xAD,0xAD,0x8B,
+    0x26,0x6A,0x84,0x51,0x80,0xE8,0x40,0x60,0xC5,0x59,0x43,0x51,0xDC,0xFF,0xBF,0x2F,
+    0xE5,0x61,0x84,0x51,0xED,0xAB,0xAA,0xAA,0x06,0x62,0xC5,0x59,0xA7,0xFB,0x72,0x7B,
+    0xE5,0x61,0x44,0x51,0xA8,0x68,0x78,0x77,0xA5,0x59,0x23,0x49,0xCA,0xEA,0xED,0xFE,
+    0x64,0x49,0x24,0x49,0xD6,0xD6,0xD2,0xF5,0x84,0x51,0x44,0x49,0x99,0xB5,0xF5,0xB5,
+    0x85,0x51,0x23,0x41,0xFC,0xFF,0xFE,0xFA,0x64,0x51,0x23,0x41,0xFE,0xF6,0xFE,0x33,
+    0x26,0x6A,0x43,0x49,0xD5,0xBD,0x2B,0x0A,0x26,0x6A,0xA5,0x51,0xB5,0xEE,0xE0,0xA0,
+    0xE6,0x61,0x43,0x51,0x00,0x82,0xE0,0xFA,0x06,0x62,0x43,0x49,0x8A,0x2A,0xBF,0x55,
+    0xC5,0x59,0x63,0x49,0x00,0xA8,0xEA,0x5D,0xC5,0x59,0x22,0x41,0xE0,0xFA,0xFE,0x7F,
+    0x23,0x41,0xE2,0x38,0x00,0xAC,0x5E,0x5E,0x03,0x39,0xC2,0x38,0xC0,0xAA,0xFC,0xBC,
+    0xE2,0x30,0x81,0x28,0xFE,0x78,0xFA,0xEA,0xC2,0x30,0x61,0x20,0xAA,0xEA,0xFA,0x7A,
+    0xC2,0x28,0x81,0x20,0xE3,0x8D,0x7D,0x7D,0xA2,0x28,0x61,0x20,0xBA,0x7E,0x56,0x5F,
+    0xA2,0x20,0x61,0x18,0xEA,0xDB,0xD7,0x57,0x81,0x20,0x41,0x18,0x02,0xE0,0xFE,0xE2,
+    0x81,0x20,0x41,0x18,0xFF,0x5F,0xBF,0x2E,0xC2,0x28,0x61,0x18,0xBD,0x3D,0x2F,0x2E,
+    0xC3,0x28,0xA2,0x28,0xCB,0xFE,0xE0,0x80,0xC2,0x28,0x81,0x20,0xFA,0xFA,0xDE,0xA2,
+    0xA2,0x28,0x82,0x20,0x2F,0xAB,0xE3,0x2E,0xC2,0x28,0x81,0x28,0xFB,0xEF,0xAB,0xAA,
+    0xC2,0x28,0x61,0x28,0x2B,0xAA,0x8A,0x02,0x03,0x31,0xA2,0x28,0xF5,0xB5,0x39,0x3A,
+    0x03,0x31,0xC2,0x30,0x57,0x7E,0xBC,0x82,0x03,0x31,0xC2,0x30,0xD7,0x65,0xAF,0xEB,
+    0xC2,0x30,0x82,0x28,0xA8,0xFC,0xF0,0x78,0xE2,0x30,0x81,0x28,0x02,0xAE,0xEB,0xBF,
+    0xE2,0x30,0xA1,0x28,0x88,0xB8,0xBF,0x55,0x03,0x39,0xC2,0x30,0xE2,0xBA,0xBF,0xFD,
+    0x03,0x39,0xC2,0x30,0xEF,0xF8,0xFA,0xA2,0x03,0x39,0xC3,0x30,0x7A,0xFF,0x7F,0xDF,
+    0xE2,0x30,0xA2,0x28,0xDF,0xDF,0xDE,0xF8,0xE3,0x30,0xA2,0x28,0xE3,0xAF,0xA6,0xE5,
+    0x82,0x30,0xC2,0x28,0xBD,0xD5,0x77,0xDD,0xA2,0x28,0x81,0x20,0x62,0xFE,0x0A,0x00,
+    0xC2,0x28,0x81,0x28,0x8F,0xEF,0xEF,0xAE,0xC2,0x28,0x82,0x28,0x20,0x02,0x09,0x02,
+    0xE3,0x30,0xA2,0x28,0xFD,0xAE,0xAE,0xBE,0xC2,0x30,0xA2,0x28,0x58,0x50,0xEA,0xAF,
+    0xC2,0x30,0xA2,0x28,0xD5,0xC3,0xF5,0xF5,0xC2,0x30,0xA2,0x28,0x02,0xBA,0x9B,0xAB,
+    0xE3,0x30,0xC2,0x28,0xEF,0x4D,0x4D,0x3D,0xE2,0x30,0xA1,0x28,0xFA,0xCB,0xA3,0x0A,
+    0x03,0x39,0xC2,0x30,0xF7,0xFF,0x81,0x03,0x03,0x39,0xC2,0x30,0xAB,0xAF,0xBF,0xF6,
+    0xE2,0x30,0xA1,0x30,0x20,0xA0,0xAF,0x2B,0x23,0x39,0xE3,0x38,0xBD,0xDF,0xEF,0xED,
+    0x03,0x39,0xC2,0x30,0xEE,0xAB,0x06,0xB7,0x03,0x39,0xC2,0x30,0x8F,0x88,0xC0,0xD2,
+    0x03,0x39,0xE2,0x30,0xFF,0xE7,0xE3,0xE8,0x03,0x41,0xE2,0x30,0x55,0x7F,0xD7,0xD7,
+    0x43,0x41,0x03,0x39,0x95,0x7D,0xFD,0xED,0x44,0x41,0xE2,0x30,0xA3,0xA9,0xEA,0xEA,
+    0x64,0x49,0xE3,0x38,0xA0,0xBA,0xFE,0xDD,0x44,0x41,0xE3,0x38,0x28,0xFE,0x57,0x55,
+    0x24,0x41,0xC2,0x30,0xE8,0xDE,0xDB,0xDB,0xE3,0x38,0xC2,0x30,0xAE,0x9E,0xB8,0x80,
+    0x03,0x39,0xC2,0x30,0x2F,0x2E,0xAD,0x3F,0x03,0x39,0xE3,0x30,0xAA,0x0A,0x2F,0xE7,
+    0x24,0x39,0xC2,0x30,0xAA,0x3A,0xDE,0xFB,0xE3,0x38,0xC2,0x30,0xFE,0x54,0x76,0x8E,
+    0x03,0x39,0xC2,0x30,0x03,0xA9,0xDD,0x8A,0x23,0x41,0xE3,0x30,0x0F,0x35,0xA3,0x89,
+    0xA5,0x51,0x03,0x39,0x02,0x0A,0xE9,0xBD,0xC5,0x51,0x44,0x49,0x2A,0x8F,0xA5,0xB5,
+    0x06,0x5A,0x64,0x49,0x8E,0xFA,0xFF,0x75,0xA5,0x51,0x64,0x49,0x20,0xB8,0x3B,0x2B,
+    0xE6,0x59,0x85,0x51,0x2B,0x2B,0x3D,0x97,0x4B,0x83,0x06,0x5A,0x35,0xA5,0x35,0x2D,
+    0xED,0x9B,0x8C,0x8B,0x2D,0xBD,0xB5,0x6F,0xED,0x9B,0xAC,0x93,0x22,0x88,0x2A,0xD5,
+    0x0E,0xA4,0xAC,0x93,0x0A,0x2E,0xAE,0xDD,0x2E,0xA4,0xCD,0x93,0x00,0xCE,0xAF,0x7D,
+    0x4E,0xA4,0xED,0x9B,0x08,0x2B,0xB5,0xB5,0xB0,0xAC,0x0D,0x9C,0x0B,0xBB,0xD7,0x57,
+    0xD0,0xB4,0x4E,0xA4,0x0A,0xAB,0x09,0xAD,0x11,0xBD,0xB0,0xB4,0x8B,0x8A,0xFB,0x55,
+    0x11,0xBD,0xB0,0xAC,0x7A,0x7E,0x83,0x8B,0xF1,0xBC,0x8F,0xAC,0xD7,0x9E,0x7F,0xEC,
+    0xB0,0xB4,0x6F,0xAC,0xFE,0xA8,0xAB,0xAA,0xB0,0xB4,0x6F,0xAC,0x7F,0x7E,0xE0,0xAA,
+    0xAF,0xB4,0x4F,0xA4,0x6F,0xFD,0x6E,0xA8,0x8F,0xAC,0x4F,0xA4,0xF7,0xDF,0xFD,0xB0,
+    0x90,0xAC,0x2E,0xA4,0x7B,0x5A,0xFE,0xDC,0x6F,0xA4,0x2E,0xA4,0x33,0xE9,0x6A,0x9E,
+    0x6E,0xAC,0x2E,0xA4,0x2E,0xCB,0xED,0xF9,0x6F,0xAC,0x2E,0xA4,0xA2,0xBB,0xDA,0x42,
+    0x4F,0xA4,0x0E,0x9C,0xF8,0xF8,0x50,0xAF,0x2E,0xA4,0x0E,0x9C,0x7B,0xDD,0xCB,0x82,
+    0x64,0x51,0x23,0x51,0xEB,0xA2,0xBA,0xBF,0x64,0x59,0x43,0x51,0xFD,0xAD,0x50,0xF8,
+    0x64,0x59,0x43,0x51,0xA2,0x88,0x6B,0xFD,0x84,0x59,0x23,0x51,0xEA,0xEA,0xEA,0x4A,
+    0x63,0x51,0x22,0x51,0xFF,0xBF,0x6F,0xA0,0x43,0x51,0x02,0x49,0xE8,0xBA,0xF6,0x7A,
+    0x43,0x51,0x02,0x49,0xBA,0x68,0xF9,0xDD,0x43,0x49,0x02,0x49,0xAA,0xAB,0xED,0xE5,
+    0x43,0x49,0xE2,0x40,0x8A,0xB8,0xFF,0xDF,0x43,0x51,0xE2,0x40,0x3B,0xBE,0xFB,0xF9,
+    0x23,0x49,0xE2,0x40,0xBF,0xBE,0xFE,0xF8,0x23,0x49,0xE2,0x40,0x3A,0xFA,0xF8,0xFA,
+    0x43,0x49,0x02,0x49,0x5E,0x55,0x55,0xD5,0x63,0x59,0xE2,0x40,0xDD,0x3F,0xAF,0x2F,
+    0xCB,0xA3,0xC5,0x61,0x2D,0x2D,0x0D,0xA9,0xEB,0xA3,0x49,0x93,0xE2,0x8A,0xEE,0x7E,
+    0x8A,0x9B,0x49,0x93,0xA2,0xE2,0xFD,0xED,0x69,0x9B,0x08,0x8B,0x48,0xF2,0x7A,0x5E,
+    0x28,0x93,0xC7,0x82,0xBA,0x6E,0x78,0xFA,0xC8,0x8A,0x07,0x83,0xAF,0xEE,0xAE,0xBF,
+    0xE8,0x8A,0xC7,0x82,0xD6,0x96,0x8A,0x1A,0x29,0x93,0xA7,0x82,0x57,0x57,0xBF,0x2B,
+    0xAB,0xA3,0xE8,0x8A,0x55,0x55,0xAD,0x02,0xEB,0xAB,0x4A,0x93,0xAD,0xAB,0xAB,0x88,
+    0x0B,0xAC,0xAB,0xA3,0xFE,0xF3,0x6B,0x5A,0xCB,0xA3,0x66,0x72,0x00,0xA0,0xE8,0x7E,
+    0x4A,0x93,0x26,0x72,0x78,0x7E,0x57,0x55,0x46,0x72,0x05,0x6A,0xEF,0xEB,0x8D,0xAB,
+    0x67,0x72,0x26,0x72,0x5E,0x65,0x7D,0x07,0x67,0x72,0x06,0x62,0x03,0x2A,0xBB,0x7E,
+    0x26,0x6A,0x84,0x51,0x50,0x5E,0xDC,0x7F,0x06,0x62,0x84,0x51,0xB5,0x37,0xAA,0xAB,
+    0xE5,0x61,0xC5,0x59,0xB2,0xD4,0x57,0xFA,0xE6,0x61,0x43,0x49,0xA0,0xF8,0x7F,0x57,
+    0x84,0x59,0x44,0x49,0x7C,0xD7,0x5F,0x7F,0x64,0x51,0x03,0x41,0xEC,0xDA,0xBA,0xA0,
+    0x64,0x49,0x03,0x41,0xBD,0x87,0x8B,0x2A,0x84,0x49,0x44,0x49,0xBD,0xDD,0x56,0x55,
+    0x85,0x51,0x03,0x41,0xEC,0xB8,0xFE,0x7F,0xC5,0x61,0x23,0x41,0xBD,0xB7,0x3D,0x3D,
+    0x27,0x6A,0xE6,0x61,0xE9,0xAB,0xD5,0x57,0x26,0x6A,0x84,0x51,0xAA,0x6F,0x7C,0x7A,
+    0xA4,0x59,0x02,0x41,0xF8,0x7F,0x5E,0x7E,0x63,0x49,0xE2,0x40,0x2B,0xBD,0xF5,0xF5,
+    0x63,0x49,0xE2,0x40,0x22,0xEE,0xFF,0x77,0x63,0x49,0x03,0x41,0xCC,0x6A,0x7D,0x5D,
+    0x03,0x41,0xC2,0x30,0xB8,0x6C,0xF8,0xF8,0xE2,0x38,0xA2,0x30,0xAA,0xE2,0xFB,0x8A,
+    0xE2,0x30,0xA2,0x28,0xFA,0x5E,0x7A,0x7A,0xC2,0x28,0x61,0x20,0xFC,0x7A,0xFF,0xAE,
+    0xC2,0x28,0x61,0x20,0xFB,0xE9,0xBA,0xA8,0xA2,0x28,0x61,0x20,0x57,0xFE,0x6C,0xFA,
+    0x81,0x20,0x41,0x18,0xFB,0xFE,0xFE,0xF8,0x81,0x20,0x41,0x18,0xFB,0x7E,0x7F,0x3F,
+    0xC3,0x28,0x61,0x18,0xB5,0xAD,0xA9,0x0A,0xE3,0x30,0xA2,0x28,0xE5,0xE9,0xAB,0xFB,
+    0xC2,0x28,0xA2,0x28,0x83,0x88,0x08,0xEA,0xC2,0x28,0x81,0x28,0xE8,0xA0,0x00,0x00,
+    0xC2,0x28,0x82,0x28,0xEF,0x2E,0x28,0x02,0xC2,0x30,0x81,0x28,0xEF,0xDE,0xE6,0x2B,
+    0x03,0x39,0xA2,0x28,0xFD,0xBD,0xAF,0x8B,0x03,0x39,0xC2,0x30,0x3F,0xAB,0x68,0x6A,
+    0x23,0x39,0xC2,0x28,0xA2,0x2A,0xFD,0xD5,0xE3,0x30,0xC2,0x28,0x80,0x5C,0x56,0xFE,
+    0xC2,0x30,0x82,0x28,0x70,0xF8,0xA2,0xA2,0xE3,0x30,0x81,0x28,0xF5,0xFF,0xFA,0xA2,
+    0xC2,0x30,0xA2,0x30,0xDB,0xDF,0x29,0x02,0xE3,0x38,0xC2,0x30,0xA2,0xAA,0xA7,0x2D,
+    0x03,0x39,0xC2,0x30,0xEB,0xBD,0xBB,0xAE,0xE3,0x30,0xC2,0x30,0xFC,0xFA,0xFF,0x16,
+    0xE3,0x30,0x82,0x20,0xBA,0xDE,0xFA,0xA0,0xE3,0x30,0xA2,0x28,0x3D,0xAB,0x2B,0x3F,
+    0x03,0x31,0xA2,0x28,0xFB,0xF8,0x77,0x7E,0xC2,0x30,0xA2,0x28,0xF9,0xE5,0x45,0x75,
+    0xA2,0x30,0xC2,0x28,0xFA,0xFF,0xDF,0xFF,0xC2,0x28,0xA2,0x28,0xEF,0xEB,0xA3,0x80,
+    0xE3,0x30,0xA2,0x28,0xF7,0x7D,0xFF,0x3F,0xE3,0x30,0xA2,0x28,0xD5,0xEB,0x72,0x5A,
+    0xC2,0x30,0xA2,0x28,0xBE,0xAE,0x8D,0xEF,0xC2,0x30,0xA2,0x28,0x88,0xB8,0xD8,0x9F,
+    0xE3,0x30,0xA1,0x28,0x2F,0x8B,0xEB,0xA7,0xE3,0x30,0xA2,0x28,0x20,0xBE,0x77,0x55,
+    0x03,0x39,0xA2,0x28,0x0A,0x0F,0x2F,0xAF,0x03,0x39,0xC2,0x30,0xA2,0xDA,0x60,0xCE,
+    0xE3,0x30,0xC2,0x30,0xB7,0xD5,0xD5,0x57,0x02,0x39,0xC3,0x30,0xFE,0xFA,0x3B,0xAF,
+    0xE2,0x30,0xA2,0x30,0xFE,0xDF,0xEC,0xB2,0x03,0x39,0xC2,0x30,0xEB,0x9D,0xAB,0x57,
+    0x03,0x39,0xC2,0x30,0xCA,0x8A,0xAF,0x95,0x23,0x39,0xC2,0x30,0xFF,0xF7,0x3F,0xEF,
+    0x23,0x39,0xE3,0x30,0x23,0x3F,0xBD,0xFD,0x24,0x39,0xE3,0x30,0x7E,0x72,0xC8,0x6B,
+    0x24,0x39,0xC2,0x30,0xF7,0xBD,0xFF,0xAF,0x03,0x39,0xC3,0x30,0xEE,0xF2,0xC0,0xC2,
+    0x03,0x39,0xC3,0x30,0xBD,0x3F,0xED,0xAB,0x03,0x31,0xC3,0x30,0xEA,0x80,0x08,0x68,
+    0x03,0x39,0xE3,0x30,0x3F,0x3D,0x67,0xB5,0x23,0x39,0xE3,0x30,0xDF,0xFD,0xDD,0xC5,
+    0x03,0x39,0xE3,0x30,0x71,0xFD,0xF5,0x59,0x44,0x41,0xE3,0x30,0x7D,0x6F,0xEB,0xA9,
+    0x23,0x39,0xE3,0x30,0xEF,0xFD,0x29,0x8B,0x64,0x41,0xE3,0x38,0xED,0xEF,0x8A,0xAA,
+    0x64,0x49,0x03,0x39,0xAD,0xA9,0x3D,0x1E,0x84,0x49,0x23,0x41,0xBF,0x77,0xB6,0xBE,
+    0x84,0x51,0x44,0x49,0xFE,0xB5,0xBD,0x27,0xE5,0x59,0x85,0x51,0x7D,0xF5,0xB5,0x0E,
+    0xE6,0x59,0xA5,0x51,0x15,0xA5,0x0F,0x20,0x6C,0x8B,0xE5,0x59,0x2D,0x2D,0x2D,0x2F,
+    0xEE,0x9B,0xAC,0x93,0x7D,0xEB,0x23,0x23,0xED,0x9B,0x8C,0x8B,0xFF,0xDF,0x7A,0x5C,
+    0xCD,0x93,0x6B,0x8B,0xA0,0xB8,0xFB,0xFD,0xED,0x9B,0x8C,0x8B,0x8E,0x39,0xB9,0xF7,
+    0x0E,0xA4,0xAC,0x93,0x2A,0x3D,0xAF,0xBF,0x2D,0xA4,0xCC,0x93,0xB8,0x2E,0xAB,0xF7,
+    0x6F,0xAC,0xED,0x9B,0x0B,0xAD,0xFF,0x75,0xAF,0xAC,0x0D,0x9C,0x28,0xAF,0xBD,0xD5,
+    0xF1,0xBC,0x4E,0xA4,0x02,0x2A,0xBD,0x9D,0xF0,0xBC,0x8F,0xAC,0x70,0xEA,0xAE,0xFB,
+    0xD1,0xB4,0x8F,0xAC,0x5F,0x5F,0xA0,0xAC,0xB0,0xB4,0x90,0xAC,0x2E,0x8B,0x04,0x36,
+    0xD0,0xB4,0x6F,0xAC,0xA7,0xBF,0xB7,0xF4,0xB0,0xB4,0x6F,0xAC,0xF8,0xE2,0xA8,0xE8,
+    0xB0,0xB4,0x4F,0xA4,0x5A,0xB8,0xBA,0xEE,0x8F,0xAC,0x4E,0xA4,0x57,0x4F,0xC3,0xCE,
+    0x6F,0xAC,0x0E,0xA4,0x28,0x88,0x88,0x7A,0x6F,0xAC,0x2E,0xA4,0xEA,0x72,0xFE,0x7D,
+    0x4E,0xA4,0x0D,0x9C,0xEF,0xBF,0xBE,0x4B,0x2E,0xA4,0xED,0x9B,0x80,0xCB,0x7F,0x7E,
+    0x64,0x59,0x02,0x49,0xEF,0xEA,0x3C,0x7F,0x84,0x59,0x23,0x51,0xAF,0x3B,0xBE,0xFD,
+    0x84,0x59,0x43,0x51,0x77,0x56,0xF4,0x2F,0x84,0x59,0x43,0x51,0xEB,0xED,0xF8,0x7E,
+    0x84,0x59,0x22,0x49,0x7E,0x5E,0xEE,0x73,0x43,0x51,0x02,0x49,0x5E,0xCE,0x7E,0x5E,
+    0x23,0x49,0x02,0x41,0xFB,0x20,0x02,0x00,0x22,0x49,0x02,0x41,0xCB,0x56,0x8B,0xF6,
+    0x23,0x49,0xE2,0x40,0xAB,0xEB,0xFA,0xA8,0x23,0x49,0xE2,0x40,0xAB,0xBB,0xDE,0x7E,
+    0x23,0x49,0xE2,0x40,0xC8,0x78,0xEF,0x8D,0x02,0x49,0xE2,0x40,0xA0,0xB9,0x25,0x87,
+    0x23,0x49,0xE1,0x40,0xBF,0xA5,0x0A,0x2B,0x05,0x6A,0x43,0x49,0xD5,0xD5,0x15,0x35,
+    0xAB,0x9B,0x66,0x7A,0x29,0x89,0x2F,0x23,0xAB,0xA3,0x49,0x93,0x7B,0xF8,0x6E,0x7A,
+    0x69,0x9B,0x29,0x93,0xA6,0xBE,0x6B,0xFA,0x69,0x9B,0x08,0x8B,0xDA,0xE8,0xE3,0x7E,
+    0x28,0x93,0xC7,0x82,0xEA,0xA8,0x88,0x28,0x28,0x8B,0xE8,0x8A,0x50,0x52,0x7D,0xFB,
+    0x8A,0x9B,0xE8,0x82,0x55,0xBD,0xAD,0x2B,0x0C,0xAC,0xE8,0x8A,0xBD,0xAB,0x2A,0x0A,
+    0x0C,0xAC,0xAA,0xA3,0xDD,0x3E,0xBA,0x28,0x0C,0xAC,0x69,0x9B,0xA2,0xEA,0xA8,0x7A,
+    0xCB,0xA3,0x66,0x72,0xA0,0xE0,0x7A,0x5E,0xC8,0x82,0x25,0x6A,0xF0,0xDE,0x77,0x5E,
+    0x46,0x72,0x05,0x6A,0x2C,0xAF,0x0B,0x02,0x67,0x7A,0x26,0x6A,0xFA,0xAF,0xA7,0x0A,
+    0x67,0x72,0x26,0x72,0x9E,0xDE,0xFC,0x88,0x47,0x72,0xA5,0x59,0xE8,0xF8,0x62,0x7A,
+    0xC5,0x59,0x84,0x59,0x2C,0x2F,0xAE,0x8E,0xC5,0x61,0x43,0x51,0x20,0xA0,0xA8,0xDE,
+    0xC5,0x59,0x23,0x49,0x80,0xFA,0x5E,0x5D,0xA5,0x51,0x02,0x41,0x9F,0x2F,0x2F,0x82,
+    0x84,0x51,0x43,0x49,0x78,0x78,0x7C,0x5A,0x84,0x51,0x44,0x49,0x6F,0xFF,0xBF,0xAD,
+    0x64,0x49,0x23,0x41,0x32,0x2A,0x9E,0x5C,0x64,0x49,0x23,0x41,0xE3,0x8B,0xAF,0xBF,
+    0x64,0x49,0x03,0x41,0x7F,0x7E,0xDC,0x78,0xA5,0x59,0x03,0x41,0x3D,0x2D,0x29,0x2F,
+    0x05,0x62,0xC5,0x61,0x5E,0xD7,0xCA,0xA2,0x06,0x6A,0xA4,0x59,0x5A,0x7C,0xC8,0xAB,
+    0xA4,0x59,0x23,0x49,0x7E,0x7C,0x78,0x5E,0x23,0x49,0xC1,0x38,0x88,0xBB,0xFE,0x6C,
+    0x23,0x41,0xE2,0x40,0xDF,0xBA,0x0B,0x43,0x23,0x41,0xE2,0x38,0x5A,0xDA,0x5F,0x55,
+    0x23,0x41,0xC2,0x30,0xFB,0xA3,0xFF,0x7D,0x03,0x39,0xC2,0x30,0xFA,0xFA,0xFF,0xFD,
+    0xE3,0x30,0xA2,0x28,0x5E,0xFA,0xAE,0xF8,0xA2,0x28,0x81,0x28,0x0E,0x0E,0x08,0x00,
+    0xC2,0x28,0x81,0x20,0xEA,0x82,0xE2,0x5E,0xA2,0x20,0x40,0x18,0xA8,0xAA,0xF8,0x7E,
+    0x82,0x20,0x61,0x18,0x5B,0x5D,0xF9,0x3D,0xC2,0x28,0x61,0x18,0xD5,0xD5,0x9D,0x0F,
+    0xE3,0x30,0xA2,0x20,0xFF,0xEF,0xEB,0xA2,0xE3,0x30,0xC2,0x28,0x57,0x52,0x2B,0xF7,
+    0xA2,0x30,0xC2,0x28,0xDF,0xFD,0x6D,0xF5,0x03,0x31,0xA2,0x28,0xFF,0xDF,0xBE,0x3B,
+    0x23,0x39,0xC2,0x28,0x55,0x7F,0xEF,0x8A,0x03,0x31,0xC2,0x30,0x55,0x7A,0xF8,0xFA,
+    0xE3,0x30,0xA2,0x30,0x0A,0x2A,0xEA,0x7A,0xE3,0x38,0x81,0x28,0xE8,0xEE,0x5B,0x5F,
+    0xC2,0x30,0x81,0x28,0x02,0x8B,0xAF,0xAD,0xA2,0x30,0xE2,0x28,0xBF,0xBE,0xEA,0xEA,
+    0x03,0x31,0xC2,0x30,0x95,0x9D,0xD7,0xB5,0x03,0x39,0xC2,0x30,0xFA,0xEA,0xEF,0xEB,
+    0xE3,0x38,0xC2,0x30,0xF7,0xDF,0x2F,0x0E,0x03,0x39,0xC2,0x30,0x37,0xBB,0x6A,0xAA,
+    0x03,0x39,0xC2,0x30,0xA2,0xEB,0xEB,0x00,0x03,0x39,0xC3,0x30,0x9A,0xBB,0xB3,0xF8,
+    0x24,0x39,0xE3,0x30,0x57,0xE3,0xEA,0xAB,0x03,0x31,0xC3,0x30,0x5E,0xDE,0xBE,0xDE,
+    0xE3,0x30,0xA2,0x28,0x7A,0xB8,0xF8,0xF0,0xC2,0x28,0xA2,0x28,0x75,0x66,0xF7,0x1F,
+    0xE2,0x30,0x81,0x28,0xFF,0x5D,0x75,0xFE,0xE3,0x30,0x81,0x20,0x2B,0xAB,0xFF,0xFD,
+    0xE3,0x30,0xA2,0x28,0xB7,0xEA,0xB3,0xB9,0xE3,0x30,0xA2,0x28,0xFA,0xFA,0x74,0xDF,
+    0xA2,0x28,0x81,0x20,0x28,0xB0,0xA8,0x80,0xE2,0x28,0x82,0x28,0xBF,0xFF,0x75,0xFF,
+    0xC2,0x28,0xA2,0x28,0xEA,0x7A,0x55,0x9D,0xE3,0x30,0x81,0x28,0xFF,0x7F,0xA2,0xA2,
+    0xE3,0x30,0xA2,0x28,0x0B,0x89,0x09,0xBD,0xE3,0x30,0xA2,0x30,0x80,0xAA,0xFF,0xFE,
+    0xE2,0x30,0xA2,0x28,0xFA,0xFA,0xF7,0x56,0xE2,0x30,0xC2,0x30,0x3B,0x9F,0x5F,0xDE,
+    0x03,0x39,0xC2,0x30,0xFA,0x82,0x7A,0x55,0xE3,0x30,0xC2,0x30,0xFF,0xB9,0x4B,0x77,
+    0xE3,0x30,0xA1,0x28,0xB8,0xBC,0xAE,0xB7,0x23,0x39,0xC2,0x28,0xAF,0xBF,0xBF,0xD7,
+    0x03,0x31,0xC2,0x28,0x7A,0x50,0x9C,0xBC,0x03,0x31,0xE3,0x30,0xE9,0xDD,0x56,0x5E,
+    0x24,0x31,0xC2,0x30,0xFF,0xF5,0x6F,0xDF,0x24,0x31,0xC2,0x30,0xFB,0xDF,0xFD,0xE3,
+    0x03,0x31,0xC3,0x30,0xF2,0xFF,0xFA,0x7F,0xE3,0x30,0xC2,0x28,0xC0,0x60,0x60,0x43,
+    0x03,0x31,0xA2,0x28,0xAA,0x2A,0xEB,0xF9,0x03,0x39,0xA2,0x28,0x2E,0xAE,0xF7,0xF7,
+    0xE3,0x30,0xC2,0x28,0x18,0xAA,0x72,0xFB,0x45,0x39,0xE3,0x30,0xCB,0xFD,0xD5,0xD5,
+    0x03,0x31,0xC2,0x30,0xE2,0x9E,0xBC,0xB8,0x23,0x41,0xE2,0x30,0x20,0x3E,0xBF,0x36,
+    0x65,0x41,0x23,0x41,0x9F,0xBF,0xDE,0x9F,0xA5,0x51,0x43,0x41,0x57,0xDD,0xBD,0xFF,
+    0xC5,0x59,0x44,0x49,0xBB,0x39,0xBF,0xFD,0x06,0x62,0xC5,0x51,0xAB,0x8A,0xCD,0xE5,
+    0x26,0x62,0xC5,0x59,0xDE,0xBB,0x2F,0x8F,0x4B,0x83,0x26,0x62,0x2D,0x2D,0x29,0x2F,
+    0xED,0x9B,0x8C,0x8B,0x03,0x81,0x8B,0xAB,0xED,0x9B,0x8C,0x8B,0x7C,0xEF,0xBA,0xAE,
+    0xAC,0x93,0x6B,0x8B,0xAF,0xC4,0x48,0x80,0xCD,0x9B,0x4B,0x8B,0x2A,0x3B,0x9D,0xD7,
+    0xED,0x9B,0x8C,0x8B,0x83,0xAA,0xAF,0xF5,0xED,0x9B,0xAC,0x93,0xAB,0xF3,0x92,0xEA,
+    0x0D,0x9C,0x8C,0x93,0x80,0x0A,0xA9,0x9D,0x2E,0xA4,0xCD,0x93,0xEA,0x2E,0xAD,0xEA,
+    0x6E,0xA4,0xED,0x9B,0x23,0xEF,0xEF,0xDD,0xB0,0xB4,0x0D,0x9C,0x8A,0xAB,0xF5,0xFD,
+    0xB0,0xB4,0x0E,0x9C,0xA0,0xAE,0xBE,0xF7,0x8F,0xAC,0x2E,0xA4,0x0A,0x0E,0xAF,0x7D,
+    0xB0,0xB4,0x0E,0x9C,0x88,0xEA,0xAF,0x7F,0x8F,0xAC,0x2E,0xA4,0x80,0xEF,0xBF,0x55,
+    0x8F,0xAC,0x0D,0x9C,0x88,0xAA,0xEB,0x55,0x8F,0xAC,0xCC,0x93,0x8A,0xEA,0x77,0x7F,
+    0x4E,0xA4,0xCD,0x93,0xA8,0xBB,0xFF,0xFD,0x2E,0xA4,0xED,0x9B,0x23,0xE0,0x59,0x55,
+    0x4E,0xA4,0xED,0x9B,0xFE,0x73,0xDD,0xD5,0x4F,0xA4,0xED,0x9B,0x5E,0xFE,0xEF,0x82,
+    0x64,0x51,0x02,0x51,0x9E,0xEA,0xAA,0xBC,0x63,0x51,0x22,0x51,0xBF,0xBA,0xA2,0xA8,
+    0x84,0x59,0x43,0x51,0xAE,0xCE,0xE9,0xEF,0x64,0x51,0x23,0x51,0xFA,0xC8,0xA2,0xAA,
+    0x64,0x51,0x23,0x49,0xCA,0x55,0x57,0x7F,0x43,0x49,0x02,0x49,0x6A,0x7E,0x55,0x7D,
+    0x23,0x49,0xE1,0x40,0x82,0x2D,0xA9,0xBB,0x23,0x49,0xE2,0x40,0xAA,0xE0,0x78,0xF7,
+    0x23,0x49,0x02,0x41,0xB2,0xFD,0x5D,0x5D,0x23,0x49,0xC2,0x40,0xFA,0xDA,0xBA,0x8A,
+    0x23,0x49,0xC2,0x40,0x0D,0x2F,0xEA,0xBA,0x44,0x49,0xE2,0x40,0x8E,0x9B,0xAF,0xBB,
+    0x23,0x49,0xE3,0x40,0xEF,0xE3,0xEE,0x6A,0x08,0x8B,0x03,0x49,0xB5,0xB5,0xAD,0x2D,
+    0xAB,0x9B,0x08,0x8B,0xA9,0x0D,0x0B,0xAB,0xAB,0x9B,0x49,0x93,0xC8,0x62,0x58,0x7C,
+    0x6A,0x9B,0x29,0x93,0xEB,0xEA,0xBE,0x7E,0x49,0x93,0xE8,0x8A,0x60,0xF0,0xEA,0x80,
+    0x49,0x93,0xE7,0x8A,0xFE,0xDB,0xBF,0x00,0x6A,0x9B,0x08,0x8B,0xDD,0x95,0x9F,0x2E,
+    0xCB,0xA3,0x69,0x93,0x25,0x2F,0xEF,0xB7,0x0C,0xAC,0xAA,0x9B,0xAB,0xF7,0x75,0xF5,
+    0xEC,0xA3,0x49,0x8B,0x00,0x00,0x8A,0x7A,0xCB,0xA3,0x86,0x7A,0xE8,0x78,0x5E,0x57,
+    0x86,0x7A,0x26,0x6A,0xF8,0xAA,0xDC,0xFF,0x66,0x72,0x25,0x6A,0xF0,0xFE,0x5A,0x82,
+    0x66,0x72,0x25,0x72,0x21,0xEB,0xEF,0xCE,0x87,0x7A,0x46,0x72,0x71,0x7B,0xDD,0x72,
+    0x67,0x72,0xC5,0x61,0xC2,0xA8,0xF8,0x72,0xE5,0x61,0x63,0x51,0xC0,0xF8,0xFE,0x5C,
+    0xC4,0x59,0x22,0x41,0xA8,0xEA,0xFF,0x55,0x84,0x51,0x23,0x49,0xF8,0x6A,0x7E,0x55,
+    0xA5,0x51,0x02,0x41,0xBD,0xBF,0x2B,0xAB,0xA5,0x59,0x43,0x49,0xAA,0xEA,0x68,0xEA,
+    0x84,0x49,0x23,0x41,0xAC,0xFE,0xAB,0xAA,0xA5,0x51,0x44,0x49,0x8F,0xEB,0xFA,0x7F,
+    0x64,0x49,0x23,0x41,0xFE,0xFA,0xFA,0x5F,0x64,0x49,0x23,0x41,0xAA,0xA0,0xB5,0xBB,
+    0x44,0x49,0x03,0x39,0xA8,0xB2,0x7C,0x56,0x84,0x51,0xE2,0x38,0x2F,0xBF,0x9D,0x55,
+    0xE5,0x61,0x23,0x49,0x00,0x02,0x03,0x29,0xE5,0x61,0xA4,0x59,0xFA,0x5A,0xBA,0x78,
+    0xC5,0x61,0x23,0x49,0x78,0x7A,0xF0,0xF0,0x23,0x49,0xE2,0x40,0xEA,0x6C,0xA8,0x00,
+    0x23,0x41,0xE2,0x38,0x63,0xE1,0x7E,0x6A,0x03,0x41,0xC2,0x38,0xFF,0x5B,0x7A,0xEE,
+    0xE2,0x38,0xC2,0x30,0xF8,0xEF,0x67,0xDF,0xE3,0x30,0xC2,0x30,0xBF,0xBA,0x7E,0x5A,
+    0x03,0x39,0xA2,0x28,0x6A,0x8A,0xAB,0x3A,0xE3,0x30,0x81,0x20,0xFF,0x7B,0xF8,0x68,
+    0xA2,0x28,0x40,0x18,0x68,0xFA,0xEA,0xFE,0x82,0x18,0x41,0x18,0x7A,0xFF,0xAF,0xAF,
+    0xA1,0x20,0x40,0x18,0xBD,0x2A,0x2B,0x2B,0xC2,0x28,0xA2,0x20,0x0B,0xE2,0x61,0xDB,
+    0x03,0x31,0xA2,0x28,0xBF,0xAF,0xBD,0x2D,0x24,0x39,0xC2,0x28,0xD5,0xDD,0xB7,0x0A,
+    0x65,0x41,0xC2,0x28,0x57,0xDF,0xEF,0x02,0x65,0x41,0xC1,0x28,0xF5,0xEF,0x82,0x80,
+    0x44,0x41,0xE3,0x30,0xFB,0x7E,0xBC,0xBC,0x23,0x39,0xC2,0x30,0x55,0x76,0xFE,0xE8,
+    0x03,0x39,0xA2,0x28,0x5F,0xDF,0xFB,0x60,0xC2,0x30,0x81,0x28,0xD0,0xE0,0xF0,0x0A,
+    0x03,0x39,0xA2,0x30,0xD5,0xDD,0xBD,0x83,0xE3,0x38,0xA2,0x28,0xBE,0xFE,0xF8,0xE8,
+    0x03,0x39,0xC2,0x30,0xA9,0xEB,0x77,0xB5,0x03,0x39,0xE2,0x30,0x7A,0x72,0x61,0x78,
+    0x24,0x39,0xC2,0x30,0xEF,0xA3,0xBB,0xFD,0x23,0x39,0xE2,0x30,0x8F,0xFA,0xEF,0x75,
+    0x23,0x39,0xE3,0x30,0xA2,0xBA,0xAB,0xF9,0x03,0x39,0xA2,0x28,0xE8,0xF8,0xF8,0xDC,
+    0x03,0x39,0xA2,0x28,0x22,0xAF,0xFD,0xF7,0xE2,0x30,0xA3,0x28,0xFE,0xAA,0xEA,0x02,
+    0xE3,0x30,0xA2,0x28,0xEA,0xA7,0xAF,0x2F,0xE3,0x30,0xA2,0x28,0xE7,0xFF,0xEF,0x2E,
+    0xE2,0x30,0xA2,0x28,0xF7,0xDF,0xFF,0xF8,0xC2,0x28,0x61,0x20,0x7F,0xFA,0x08,0x00,
+    0xC2,0x28,0x81,0x20,0xBD,0xFD,0xEB,0x8B,0xC2,0x30,0x81,0x20,0xAA,0xEB,0xFD,0x7A,
+    0xA2,0x28,0x61,0x20,0xB0,0xEF,0xBE,0xFE,0xA2,0x28,0x81,0x20,0x0A,0x8D,0xED,0x7D,
+    0xC2,0x28,0x61,0x20,0x0A,0x2A,0x01,0x0A,0xE2,0x30,0xA2,0x28,0x8E,0xB7,0xCB,0x88,
+    0xE3,0x30,0xA2,0x28,0x6F,0xAC,0x2F,0x2F,0x04,0x31,0xC3,0x30,0x55,0xDA,0x5E,0xFF,
+    0xE3,0x30,0xA2,0x28,0x5F,0x2C,0x9B,0xBB,0x03,0x39,0xC2,0x30,0x7F,0xDA,0xEA,0x6A,
+    0xE2,0x30,0xA2,0x28,0xBA,0xAF,0xA5,0xD7,0xE2,0x30,0xA2,0x28,0xFA,0xFE,0xEE,0xBF,
+    0xC2,0x28,0xA2,0x28,0xD7,0xBD,0xAE,0xA0,0x03,0x31,0xC2,0x28,0xF7,0xBF,0x2A,0xAB,
+    0x03,0x31,0xE3,0x30,0xF5,0xE7,0xFF,0x7B,0x24,0x39,0xE3,0x30,0xEB,0xB2,0xAF,0x29,
+    0x24,0x39,0xC2,0x28,0x7E,0xEA,0xE2,0xC3,0x24,0x39,0xC2,0x28,0xE3,0xAD,0x6B,0x5E,
+    0xE3,0x30,0xC2,0x28,0xBA,0x3C,0x29,0x8D,0x03,0x31,0xC2,0x30,0x6B,0xFA,0xFE,0xFF,
+    0x23,0x31,0xC2,0x30,0xFD,0xFB,0xFF,0x57,0xE3,0x30,0xC2,0x28,0xD7,0xF7,0xFA,0x02,
+    0x03,0x31,0xA3,0x30,0xAB,0x0A,0xAA,0x08,0x03,0x31,0xC3,0x30,0x2C,0xBC,0xFE,0x82,
+    0x03,0x31,0xE2,0x30,0xD8,0x55,0xAF,0xFB,0x44,0x41,0xE2,0x30,0x2F,0xA5,0xBD,0xF7,
+    0x64,0x49,0x03,0x39,0xAA,0x02,0xAE,0xF7,0xA5,0x51,0x23,0x41,0x3E,0x2B,0xDF,0xFD,
+    0xA5,0x51,0x44,0x49,0xFF,0xAA,0xAC,0xD6,0xC5,0x51,0x64,0x49,0xAA,0x3F,0xAD,0x29,
+    0x48,0x6A,0xC5,0x51,0xFD,0xBF,0x3D,0x39,0xAC,0x93,0x88,0x72,0xAD,0x2D,0x29,0x2F,
+    0x0E,0x9C,0xAD,0x93,0xDD,0x5F,0xAB,0xAB,0xED,0x9B,0x8C,0x8B,0x27,0xEF,0x7E,0xA8,
+    0xCD,0x93,0x8C,0x8B,0xFA,0x7A,0x6A,0x76,0xAD,0x93,0x6B,0x8B,0xB6,0xDF,0xFB,0x5E,
+    0x8C,0x93,0x4B,0x83,0xC0,0xBD,0xB7,0x6A,0xCD,0x93,0x4B,0x83,0x02,0x0A,0x3B,0x2D,
+    0xCD,0x93,0xAC,0x93,0x9A,0x30,0x98,0x5C,0x2E,0xA4,0xCD,0x93,0xEB,0xFD,0xDF,0x35,
+    0x2E,0xA4,0xCD,0x93,0xFF,0xFF,0x6F,0xCD,0x2E,0xA4,0xCD,0x93,0x8B,0xEF,0x9B,0xBF,
+    0x2E,0xA4,0xEE,0x9B,0xFA,0x82,0xAE,0x6B,0x2E,0xA4,0xCD,0x93,0x02,0xAB,0x7A,0xF9,
+    0x2E,0xA4,0xCD,0x93,0xA8,0xA8,0x2B,0xAD,0x0D,0x9C,0xCC,0x93,0x00,0x20,0xA8,0x5A,
+    0x2D,0x9C,0xAC,0x93,0xE8,0xE8,0xFA,0x5F,0xCD,0x93,0xAC,0x93,0x83,0xEF,0xAC,0x39,
+    0xED,0x9B,0xAC,0x93,0x3F,0xDF,0xEB,0x7A,0xED,0x9B,0xCC,0x93,0x00,0x2A,0xFF,0x95,
+    0x0D,0x9C,0xCC,0x93,0x8A,0x28,0x2B,0x2B,0x4F,0xA4,0xED,0x9B,0x0F,0xAF,0xDF,0x6D,
+    0x43,0x51,0x23,0x49,0x17,0x95,0xAA,0x39,0x63,0x51,0x23,0x49,0x6A,0xEA,0xEE,0x7D,
+    0x64,0x51,0x23,0x49,0xCB,0x73,0xEE,0x69,0x64,0x51,0x23,0x49,0xAA,0x6A,0x7F,0xED,
+    0x43,0x49,0x02,0x49,0x6C,0x5F,0x57,0x58,0x22,0x49,0xE1,0x40,0xEC,0xDE,0xEB,0xAE,
+    0x02,0x49,0xE2,0x40,0xFE,0x8A,0xF2,0x8A,0x23,0x49,0xE2,0x40,0xE7,0xAF,0x99,0x55,
+    0x23,0x49,0xC1,0x38,0x0A,0x82,0xAA,0xB7,0x22,0x49,0xE3,0x40,0xAA,0x2B,0xAB,0xFF,
+    0x23,0x49,0xE2,0x40,0x77,0xB7,0x17,0xFB,0x23,0x49,0xE3,0x40,0xC3,0x8B,0x8E,0x2F,
+    0x43,0x51,0x03,0x49,0xDD,0x43,0xED,0xBD,0x49,0x93,0x43,0x51,0x25,0x2D,0x2D,0x0D,
+    0xAA,0x9B,0x69,0x93,0xF7,0xAE,0xE3,0x6B,0x8A,0x9B,0x49,0x93,0xBA,0xF8,0xFA,0xEF,
+    0x69,0x9B,0x49,0x93,0xD6,0x55,0xE5,0x55,0x89,0x9B,0x28,0x93,0xD7,0x67,0x17,0x3D,
+    0x8A,0x9B,0x29,0x93,0x7D,0x7F,0x7A,0xC0,0x6A,0x9B,0x29,0x93,0x6B,0x3E,0xBA,0xBE,
+    0x8A,0x9B,0x49,0x93,0x27,0x0F,0xAA,0xBF,0xCB,0xA3,0x29,0x8B,0x8A,0xAA,0xEA,0xFF,
+    0x8A,0x9B,0x66,0x7A,0xA0,0x78,0x7E,0x57,0xA7,0x7A,0x46,0x72,0xF8,0x7B,0xFE,0xFF,
+    0x87,0x7A,0x25,0x6A,0xFF,0x6A,0xAB,0xAB,0x86,0x7A,0x45,0x6A,0xEB,0xAD,0xB6,0xE8,
+    0x87,0x72,0x46,0x72,0xF7,0x87,0x08,0x6A,0x87,0x7A,0x06,0x62,0x82,0x80,0x82,0x72,
+    0x46,0x6A,0x23,0x49,0xE0,0xFA,0x7A,0xD6,0x84,0x59,0x02,0x41,0xA8,0xBE,0x77,0x7F,
+    0x43,0x49,0x23,0x41,0xDC,0xD7,0xA5,0x89,0x63,0x49,0x23,0x49,0x97,0x2F,0x2A,0x0A,
+    0xA5,0x59,0x64,0x51,0xBD,0x2D,0x8F,0xBB,0x84,0x51,0x43,0x49,0xEE,0x68,0xFE,0xFC,
+    0x64,0x49,0x43,0x49,0x1A,0x95,0x37,0x98,0x85,0x49,0x44,0x49,0xFF,0xAE,0xBA,0xEB,
+    0x64,0x49,0x24,0x41,0x7F,0xEC,0x6E,0x7E,0x44,0x49,0x24,0x41,0x2A,0x6F,0xE5,0x2D,
+    0x23,0x41,0x03,0x41,0xEC,0xFA,0x23,0xE0,0x23,0x41,0xC2,0x38,0x2E,0xAE,0xAA,0xF4,
+    0xA5,0x59,0x03,0x41,0x09,0x05,0xF5,0x55,0xC5,0x59,0x23,0x49,0xA8,0xAA,0xAA,0xBD,
+    0xA4,0x51,0x43,0x51,0xE8,0xFA,0xFE,0x7E,0x64,0x51,0x03,0x41,0xFF,0xEA,0xFA,0x6C,
+    0x23,0x41,0xA1,0x30,0xE8,0xEA,0x7A,0x7E,0x03,0x39,0xA1,0x30,0xAB,0x8B,0xAD,0xBE,
+    0xE2,0x38,0xA1,0x28,0x02,0x28,0xEE,0x78,0x03,0x39,0xC2,0x30,0x5E,0xAA,0x82,0x53,
+    0xE3,0x30,0x81,0x28,0x82,0x8A,0xEF,0xDF,0xE3,0x30,0x81,0x20,0xFC,0xFE,0xF7,0x5D,
+    0xA1,0x20,0x40,0x18,0xF8,0xF8,0xF8,0x7A,0x82,0x20,0x40,0x18,0xB9,0x2F,0xAB,0xAF,
+    0xC2,0x28,0x61,0x18,0xB7,0x2F,0x2B,0x03,0x03,0x31,0xA2,0x28,0x9F,0x87,0x2B,0x2A,
+    0x44,0x41,0xC3,0x30,0x2D,0xBB,0x8A,0xBA,0x44,0x41,0xC2,0x28,0x02,0x08,0xBE,0xDE,
+    0x85,0x41,0xA2,0x28,0x0A,0xA8,0xFE,0xF7,0x44,0x41,0xC2,0x30,0x80,0xAA,0xEF,0x5D,
+    0x24,0x39,0xE3,0x30,0x88,0xAB,0x3D,0xD5,0x23,0x41,0x03,0x39,0x5D,0x5F,0x7B,0x55,
+    0x03,0x39,0xC2,0x30,0x72,0x98,0xAA,0xA0,0x03,0x39,0xA2,0x30,0xE5,0x2E,0x8A,0x8A,
+    0x03,0x39,0xC3,0x30,0xE2,0xEA,0xFE,0xF5,0xC2,0x38,0xE3,0x30,0xF5,0xBF,0xFD,0xFF,
+    0xE3,0x38,0xA1,0x28,0x03,0xAA,0xB6,0x9F,0x03,0x39,0xC2,0x30,0xEA,0xAA,0x22,0xF2,
+    0x03,0x39,0xA2,0x30,0xAB,0xAB,0xEE,0x78,0xE2,0x30,0xC2,0x30,0xE1,0xA0,0x23,0xBB,
+    0x03,0x31,0xC2,0x28,0xB9,0xB5,0xA7,0xD5,0xE3,0x30,0x81,0x28,0xB8,0xF8,0x7A,0x7F,
+    0xC2,0x28,0x82,0x28,0x28,0x2F,0xAF,0xF5,0xE3,0x30,0xA2,0x28,0x0A,0xAF,0xBD,0xE9,
+    0x04,0x31,0xC3,0x30,0xBF,0xED,0xFF,0xAD,0xE3,0x30,0xC2,0x28,0xCC,0x98,0xF0,0xC0,
+    0x03,0x39,0xE3,0x30,0x57,0x7B,0xEB,0xA5,0xE3,0x30,0xA2,0x28,0x7F,0xFF,0x2E,0xE2,
+    0xE3,0x30,0x81,0x28,0xAD,0xAB,0xAA,0xEA,0xC2,0x28,0x82,0x28,0x78,0xB0,0xC2,0x80,
+    0xE3,0x30,0x81,0x20,0x55,0x7F,0xEA,0xA0,0xC2,0x28,0x61,0x20,0xFD,0xFB,0xAA,0x00,
+    0xE2,0x30,0x81,0x20,0xAF,0xAD,0xBE,0x28,0x23,0x39,0xC2,0x28,0xFD,0xFF,0xEB,0x8F,
+    0xE3,0x30,0xA2,0x28,0x2A,0xA0,0xA0,0xF8,0x03,0x31,0xC2,0x30,0x15,0xB5,0xA7,0xAF,
+    0x03,0x31,0xA2,0x28,0x9C,0xFE,0xFF,0x56,0xE3,0x30,0xA2,0x28,0x02,0x02,0xEA,0xDF,
+    0xC2,0x30,0xA2,0x28,0xAE,0x0E,0x2E,0xB7,0xE3,0x30,0xC2,0x28,0xDE,0x96,0x2F,0xFF,
+    0x03,0x31,0xA2,0x28,0x6A,0xE2,0xA0,0xAB,0x03,0x31,0xA2,0x30,0xA9,0x22,0x82,0xA8,
+    0x03,0x31,0xE3,0x30,0x22,0x6A,0xF1,0xB2,0x24,0x39,0xA1,0x28,0x0A,0xAA,0xDF,0x5F,
+    0x24,0x39,0xC2,0x30,0xF8,0x7A,0x7F,0x5D,0xE3,0x30,0xA2,0x28,0xF0,0xF8,0xFA,0x7B,
+    0xE3,0x30,0xA2,0x28,0x05,0xED,0x9F,0xAF,0xE3,0x30,0xC2,0x28,0x8E,0x2F,0x0D,0xA5,
+    0xE3,0x30,0xC2,0x28,0x56,0x2A,0x39,0x2F,0xE3,0x30,0xA2,0x28,0x08,0xBE,0x3E,0x2A,
+    0x23,0x31,0xE2,0x30,0x97,0xC7,0x95,0xF5,0x03,0x31,0xE2,0x30,0xE0,0x68,0x40,0xD7,
+    0x03,0x31,0xA1,0x28,0x22,0x82,0xC2,0xFA,0x03,0x39,0xC1,0x28,0x82,0x03,0x09,0x05,
+    0x44,0x41,0x03,0x39,0xFB,0x2B,0xAB,0xED,0x64,0x49,0x23,0x41,0x8F,0xAD,0x9D,0xF5,
+    0x64,0x49,0x23,0x41,0x79,0xEE,0xE2,0xE0,0xE5,0x59,0x43,0x41,0x2F,0xAD,0xAB,0xAA,
+    0xC8,0x7A,0xE4,0x51,0xB7,0xBD,0x2D,0x2F,0xCD,0x9B,0xC9,0x7A,0x2D,0x0D,0x29,0x0B,
+    0x0F,0x9C,0xCD,0x93,0xAF,0xA9,0xC3,0x2F,0xED,0x9B,0xAD,0x93,0xC8,0xA2,0x6A,0x82,
+    0xEE,0x9B,0x8C,0x8B,0x5E,0x5A,0xE8,0xAA,0xAC,0x93,0x4B,0x83,0xDA,0xFB,0xFF,0xF6,
+    0x8B,0x8B,0x4B,0x83,0xBA,0x99,0x77,0xAF,0xAD,0x93,0x2A,0x83,0x37,0x97,0xD5,0xF5,
+    0xCD,0x93,0x6C,0x8B,0x80,0xBA,0x2F,0x2D,0xED,0x9B,0xCD,0x93,0x26,0x2F,0x35,0xF5,
+    0x0D,0x9C,0xAC,0x93,0x80,0x0A,0x39,0x2B,0x0E,0x9C,0xCD,0x9B,0xAA,0xB9,0xE0,0xE2,
+    0xED,0x9B,0xCD,0x93,0x68,0x20,0x0A,0xE2,0x0E,0x9C,0xCD,0x93,0x62,0xDE,0xCB,0xCE,
+    0xED,0x9B,0xCD,0x93,0xE3,0x68,0x57,0x97,0xED,0x9B,0xAD,0x93,0xF6,0xEE,0x3A,0xAC,
+    0xED,0x93,0x8C,0x93,0xDA,0xAA,0x2A,0xA8,0x0D,0x9C,0xAC,0x93,0xFD,0x55,0xD4,0x5F,
+    0xCD,0x93,0x6B,0x8B,0xE0,0x2A,0x22,0xA2,0xCD,0x93,0x8C,0x93,0x2A,0x02,0xAE,0x2D,
+    0xED,0x9B,0x8C,0x8B,0x02,0x0A,0x2A,0xB6,0x2E,0xA4,0xCD,0x93,0x8E,0xFE,0xDF,0xFD,
+    0x44,0x51,0x03,0x49,0xF2,0xE8,0xFB,0x97,0x43,0x51,0x03,0x49,0x3A,0xAB,0x2F,0xA6,
+    0x63,0x51,0x03,0x49,0xEB,0xA0,0xFB,0xD7,0x44,0x51,0x23,0x49,0x6B,0xEF,0x52,0x55,
+    0x22,0x49,0x02,0x41,0x80,0x0F,0xBA,0xB8,0x23,0x49,0x02,0x41,0xD6,0xDC,0x0C,0xBE,
+    0x23,0x49,0xC1,0x38,0xA2,0xE6,0x62,0xAA,0x23,0x49,0xC1,0x38,0xFA,0x6F,0x2F,0x0A,
+    0x23,0x41,0xC1,0x40,0xF6,0x88,0xEA,0xCE,0x02,0x41,0xC2,0x38,0x28,0xCD,0xAB,0x8B,
+    0x23,0x41,0xE3,0x40,0xEE,0x0F,0x27,0x3E,0x23,0x49,0xE2,0x40,0xB2,0xD0,0xEA,0xFB,
+    0x43,0x51,0xE2,0x40,0x2B,0x0F,0x3D,0xBF,0x69,0x93,0xC4,0x59,0x2D,0x09,0x29,0x0D,
+    0xA9,0x9B,0x69,0x93,0x7F,0x53,0x7E,0x54,0x8A,0x9B,0x49,0x93,0xEF,0xEA,0xE8,0x6D,
+    0x69,0x93,0x28,0x8B,0xFE,0xA9,0xFE,0x0E,0x8A,0x9B,0x49,0x93,0xA5,0x2D,0x0D,0xA0,
+    0xAB,0x9B,0x49,0x93,0x42,0xBA,0xFA,0xD5,0x8A,0x9B,0x4A,0x93,0x9F,0xAB,0xFA,0xDF,
+    0x8A,0x9B,0xE9,0x8A,0xBA,0xE8,0xF8,0xFA,0x2A,0x93,0x06,0x6A,0x80,0xE8,0xFA,0x7E,
+    0x87,0x7A,0x25,0x6A,0xBC,0xF8,0xEE,0x7F,0x87,0x72,0x46,0x72,0xAD,0x83,0x8A,0x58,
+    0x87,0x72,0x46,0x72,0xAA,0xBA,0xAB,0xDD,0xA7,0x7A,0x46,0x72,0x5F,0x9A,0xBF,0x0A,
+    0xA7,0x7A,0x46,0x6A,0xEB,0xEE,0xC2,0x68,0x46,0x72,0x64,0x51,0xE0,0xE0,0x78,0x5E,
+    0x84,0x59,0x02,0x41,0xFC,0x5E,0xFF,0xDC,0x43,0x49,0x02,0x41,0xC2,0xAA,0xAD,0xBF,
+    0x64,0x51,0x02,0x41,0xA9,0x8F,0xAF,0x2A,0xA5,0x51,0x43,0x49,0xBF,0xA9,0xBB,0x82,
+    0xA4,0x51,0x43,0x49,0xA8,0xC8,0x6A,0xFE,0xA4,0x51,0x43,0x49,0xDA,0x35,0x25,0xEF,
+    0x84,0x49,0x44,0x49,0x7A,0x78,0xA0,0x80,0x85,0x49,0x44,0x49,0xEB,0x8B,0x37,0x17,
+    0x84,0x49,0x44,0x49,0x77,0xFE,0xF6,0xDB,0x44,0x41,0x03,0x41,0xA8,0xAE,0xAE,0xEA,
+    0x44,0x49,0x03,0x41,0xEE,0x2F,0xAD,0xBA,0x24,0x41,0xE3,0x38,0xD6,0xFB,0xFC,0xAA,
+    0x03,0x41,0xC2,0x38,0xA8,0x5A,0x77,0x5E,0x64,0x51,0xA2,0x38,0x0B,0xAF,0xB5,0xF5,
+    0x84,0x51,0x03,0x41,0xA0,0xA2,0x8A,0xA5,0x64,0x51,0x02,0x41,0xE8,0xEE,0x6A,0xEB,
+    0x23,0x41,0xC2,0x30,0x5F,0x7B,0xEB,0xE8,0x03,0x39,0xC2,0x38,0xFF,0xFF,0xA7,0x8F,
+    0x03,0x39,0xC2,0x30,0x57,0xDF,0xFE,0xFA,0xE3,0x30,0x81,0x28,0xA2,0xEA,0xEA,0x5A,
+    0xA2,0x28,0x61,0x20,0xA0,0xA2,0x7A,0x7F,0x81,0x20,0x41,0x18,0x80,0xE8,0x7E,0x7F,
+    0x61,0x20,0x41,0x18,0xE2,0xEF,0xFD,0x95,0xA2,0x28,0x41,0x18,0xBD,0xAF,0xAF,0x3F,
+    0xE3,0x28,0x81,0x20,0x8B,0xAD,0xFF,0x57,0xE3,0x30,0x81,0x20,0x0A,0xAB,0xED,0xF9,
+    0xE3,0x30,0x81,0x20,0x80,0xEF,0xFD,0x57,0xC2,0x28,0x81,0x20,0x20,0xF2,0xAF,0xAF,
+    0xC3,0x30,0x82,0x20,0xA7,0x97,0xFF,0xBE,0xC3,0x28,0x82,0x28,0xEA,0xEB,0xFE,0x76,
+    0x03,0x39,0x81,0x20,0xAB,0x2F,0xFD,0xF5,0x24,0x39,0xE2,0x30,0xBF,0xBE,0xAE,0xB5,
+    0x24,0x39,0xE3,0x38,0x7A,0xF3,0xDD,0x77,0x03,0x39,0xC2,0x30,0xFF,0xFB,0xF8,0xEE,
+    0xE3,0x30,0xA1,0x28,0x3E,0xF8,0x70,0xA2,0x03,0x39,0xA2,0x28,0x8F,0xEB,0xFB,0x7F,
+    0xC2,0x30,0x81,0x28,0x28,0x28,0xA8,0xBD,0xE2,0x30,0xA2,0x30,0xEA,0xAA,0x8F,0x26,
+    0xE3,0x30,0xA2,0x30,0x40,0x82,0x00,0x02,0xC2,0x30,0xE3,0x28,0xBA,0x2A,0x0E,0xBE,
+    0xC2,0x30,0xA2,0x28,0x5A,0x5E,0xE8,0x58,0xA2,0x28,0x81,0x20,0x7B,0x6B,0x58,0x70,
+    0xA2,0x28,0x61,0x20,0xDF,0xBF,0x1B,0x2B,0xC3,0x30,0xA2,0x28,0x2D,0xDF,0xCA,0x2B,
+    0xE3,0x30,0xA2,0x28,0x2B,0xEA,0xAB,0x3F,0x03,0x31,0xC2,0x30,0xEA,0xFB,0xEA,0x09,
+    0x03,0x31,0xC3,0x30,0x8F,0xBF,0xAF,0xAF,0xE3,0x30,0xA1,0x28,0xB2,0xBC,0xF0,0xFA,
+    0xE3,0x30,0xA2,0x28,0xEB,0xAB,0xB9,0xBB,0xE3,0x30,0xA2,0x28,0xAF,0x26,0x2A,0xAA,
+    0x03,0x39,0xE3,0x30,0x57,0x9F,0x39,0x43,0x24,0x39,0xC2,0x28,0x7E,0xEE,0xFE,0xDC,
+    0x23,0x39,0xE3,0x30,0xC5,0xBD,0xEF,0xF5,0x03,0x39,0xC2,0x30,0xEE,0x7A,0xE8,0xE8,
+    0xE3,0x30,0xC2,0x28,0x52,0x15,0xF7,0xFB,0x02,0x31,0xA2,0x28,0x3F,0xFF,0xBD,0xFF,
+    0xE3,0x30,0xA2,0x28,0xFC,0xFC,0x5F,0x57,0xE3,0x30,0xA2,0x28,0xBD,0xE3,0x7B,0xEA,
+    0xC2,0x28,0xA2,0x28,0xDF,0xD6,0xA5,0x8F,0xC2,0x30,0xA2,0x28,0xD6,0x95,0xA5,0xAD,
+    0x03,0x31,0xC2,0x28,0x35,0xA5,0xAD,0x9D,0x03,0x31,0xC3,0x30,0x08,0x80,0xAA,0xDE,
+    0x24,0x39,0xE3,0x30,0x7E,0xA7,0xED,0x6B,0x03,0x31,0xA2,0x28,0x7E,0xF8,0xFA,0xAA,
+    0xE3,0x30,0xC2,0x28,0x79,0xFF,0x6B,0xC0,0x03,0x31,0xC2,0x28,0x55,0xDD,0xF3,0xB8,
+    0xC2,0x30,0xE3,0x28,0xAE,0xA9,0xAF,0xB7,0xE3,0x30,0xA2,0x28,0xF9,0x3E,0xBA,0x3A,
+    0x03,0x31,0xC2,0x30,0xB7,0x36,0xF8,0xB8,0x03,0x31,0xC2,0x30,0xA7,0xAA,0xBE,0xFE,
+    0x03,0x31,0xC2,0x28,0x2B,0x8E,0x27,0x0F,0x43,0x39,0xE2,0x30,0x55,0x7F,0xEF,0xF2,
+    0x02,0x31,0xC2,0x30,0x72,0x42,0x76,0x7E,0x03,0x39,0xA1,0x28,0x3D,0xAD,0x3D,0xA7,
+    0x64,0x49,0x03,0x39,0xF9,0xBF,0x3D,0x2D,0xA5,0x51,0x43,0x41,0x55,0xD5,0x8B,0x83,
+    0xA5,0x51,0x64,0x49,0x57,0x07,0x2D,0xAE,0x06,0x5A,0x84,0x49,0xB7,0xEF,0xAF,0x2D,
+    0x0A,0x83,0xE5,0x59,0x2F,0xAD,0x29,0x2F,0xED,0x9B,0x4B,0x8B,0x2F,0x0F,0x3D,0x99,
+    0x0E,0x9C,0x8C,0x93,0xAA,0x0A,0xEF,0x5F,0xED,0x9B,0x8C,0x93,0x20,0xAA,0xAA,0xEF,
+    0xCD,0x93,0x8C,0x93,0xC0,0xC4,0x6B,0x5E,0x8C,0x8B,0x4B,0x83,0xE0,0xBE,0xE8,0xF6,
+    0x8C,0x8B,0x4B,0x83,0xEF,0x7E,0xFF,0xD5,0x6B,0x8B,0x0A,0x7B,0xBE,0xD8,0xDE,0x7C,
+    0xCC,0x93,0x29,0x7B,0x2F,0xAF,0xAD,0xFD,0xED,0x9B,0x8B,0x8B,0xAA,0xAA,0x3B,0x3D,
+    0xED,0x9B,0xAC,0x93,0x22,0x38,0xAA,0xF5,0x0E,0x9C,0x8C,0x8B,0xA8,0x2A,0xAB,0x7F,
+    0x2E,0xA4,0xAC,0x93,0xF8,0xBE,0xF7,0x75,0x0E,0x9C,0xAC,0x93,0x3A,0xBE,0xEB,0x9F,
+    0xCD,0x93,0x8C,0x8B,0x00,0x02,0x0A,0x2C,0xCD,0x93,0x8C,0x8B,0x38,0xD0,0x6F,0xEE,
+    0xCD,0x93,0x8C,0x8B,0xA0,0x30,0xFA,0xF7,0xCD,0x93,0x8C,0x8B,0x28,0x0C,0x08,0x88,
+    0xCD,0x93,0x6C,0x8B,0xAA,0xFE,0xA6,0x22,0xCC,0x93,0x6B,0x8B,0x32,0xFA,0xE2,0xE8,
+    0xED,0x9B,0x8C,0x8B,0xEF,0xEB,0xCF,0x5D,0x0E,0x9C,0xAC,0x93,0xBD,0xBC,0xFF,0xF5,
+    0x43,0x51,0x03,0x49,0xEA,0xEA,0xFB,0x6A,0x43,0x51,0x03,0x41,0xEB,0xA2,0xD3,0xFF,
+    0x23,0x49,0xE2,0x40,0x0B,0x0F,0xA2,0x88,0x43,0x49,0xE2,0x40,0xAC,0xFC,0x7F,0xEE,
+    0x23,0x49,0xE2,0x40,0xAB,0x8F,0xBB,0x29,0x23,0x49,0xE2,0x40,0x62,0xDC,0x98,0xF8,
+    0x03,0x49,0xE1,0x38,0xAA,0xF2,0xF2,0xD6,0x23,0x41,0xC1,0x38,0x82,0x8A,0xE3,0xFE,
+    0x02,0x41,0xE2,0x38,0x89,0xE5,0xAF,0x25,0x23,0x49,0xE2,0x38,0xA5,0x8D,0xFF,0xFB,
+    0x03,0x41,0xE2,0x38,0x08,0x02,0x28,0x07,0x23,0x49,0xE2,0x40,0xFB,0xFC,0xFE,0x7F,
+    0x43,0x51,0xE2,0x40,0x3F,0xBF,0x2F,0x2D,0x6A,0x93,0xA5,0x59,0x0B,0x09,0x0B,0x0B,
+    0x8A,0x9B,0x69,0x93,0x68,0xC0,0xA2,0x29,0x8A,0x9B,0x49,0x93,0x87,0x05,0x2A,0xB0,
+    0x8A,0x9B,0x28,0x8B,0x29,0x0A,0xE8,0xFE,0x6A,0x9B,0xE8,0x82,0xC0,0x68,0x7E,0x57,
+    0x29,0x8B,0xC8,0x82,0x0A,0x2F,0xAF,0xDD,0x6A,0x93,0x09,0x8B,0x20,0x03,0xAF,0xF5,
+    0x4A,0x93,0x05,0x6A,0x80,0xA0,0xE0,0x78,0x67,0x7A,0xE5,0x61,0xE2,0xFE,0xDE,0xDF,
+    0x66,0x72,0x05,0x6A,0x8B,0xEF,0xB5,0x7F,0x66,0x72,0xE4,0x61,0xA8,0x2B,0x2B,0xA9,
+    0x87,0x72,0x26,0x72,0x9A,0xEA,0xE2,0xCA,0xC8,0x7A,0x46,0x6A,0x29,0xCF,0xFF,0xD7,
+    0xA7,0x72,0x84,0x59,0xA0,0xEA,0x78,0x5E,0xE5,0x61,0x23,0x49,0xD8,0xDF,0x7F,0xFF,
+    0x63,0x51,0x22,0x41,0x5C,0x76,0x6A,0xEE,0x43,0x49,0x02,0x41,0xFF,0x9F,0x9A,0x58,
+    0x64,0x51,0xE2,0x38,0x0A,0x0B,0x2F,0xAD,0xA5,0x51,0x64,0x49,0xC0,0x8E,0x77,0x75,
+    0x84,0x49,0x44,0x49,0xFA,0xD8,0x2A,0x2F,0xA5,0x51,0x43,0x49,0xA6,0xA8,0x88,0xAA,
+    0x84,0x51,0x64,0x49,0xE2,0x42,0x7E,0x5E,0x85,0x51,0x23,0x41,0xBC,0xF7,0x56,0x77,
+    0x64,0x49,0x23,0x41,0xA0,0x78,0xA3,0xA3,0x64,0x49,0x23,0x41,0x7F,0xCD,0xFF,0xDE,
+    0x64,0x49,0x03,0x39,0xAF,0xB7,0xE6,0xFE,0x64,0x41,0x03,0x41,0x57,0x7E,0x7F,0xDF,
+    0x23,0x41,0xE3,0x38,0x7B,0xA2,0xEB,0xBF,0x03,0x39,0xC2,0x38,0x55,0x5E,0x5A,0xF8,
+    0x03,0x41,0xA1,0x30,0x2E,0x37,0xAF,0x3B,0x43,0x41,0x03,0x41,0x22,0xA8,0xAB,0x0A,
+    0x43,0x41,0xE2,0x38,0xFE,0xFA,0xE2,0xFA,0x03,0x39,0xC2,0x38,0x8A,0x2D,0x2F,0x2B,
+    0x23,0x39,0xC2,0x30,0xFB,0x7C,0xFA,0xEB,0xE3,0x30,0x81,0x28,0x52,0x5A,0x7F,0xDF,
+    0xA1,0x28,0x40,0x20,0xF8,0x6E,0xFA,0xBA,0x61,0x20,0x41,0x18,0xEA,0xAA,0xB0,0x00,
+    0xA2,0x28,0x41,0x18,0x55,0xFF,0xFF,0x2F,0xA2,0x20,0x61,0x20,0xB5,0xA9,0xAB,0x88,
+    0xA1,0x20,0x61,0x20,0xBE,0xAF,0xA7,0x0B,0xA2,0x28,0x81,0x20,0x8D,0xB7,0xBB,0xB8,
+    0xA2,0x28,0x81,0x20,0xBE,0x3E,0xAA,0xE2,0xC2,0x28,0x81,0x20,0x2F,0xA2,0xAF,0xBF,
+    0xA2,0x28,0x82,0x20,0x08,0x8A,0x7E,0xE9,0xA2,0x28,0x81,0x20,0xAC,0x7A,0xFF,0xFB,
+    0xA2,0x28,0x81,0x20,0xBF,0x5E,0x6F,0x9F,0x24,0x39,0xA2,0x28,0xAF,0xBD,0xB5,0xD5,
+    0x03,0x39,0xA2,0x28,0xA0,0x88,0xAA,0xA9,0x03,0x39,0xC2,0x30,0xEF,0xA7,0x7E,0x97,
+    0xA1,0x38,0xE2,0x30,0xF7,0xD5,0xA7,0xF7,0xC2,0x30,0x81,0x28,0x68,0xFA,0xBF,0xF8,
+    0xC2,0x30,0x81,0x28,0x35,0xEC,0xFF,0xBA,0xE2,0x30,0xA2,0x30,0x07,0x21,0x2D,0xBB,
+    0xE2,0x30,0xA2,0x28,0x0C,0x80,0x20,0xBE,0xE3,0x30,0xC2,0x28,0x3B,0xBC,0x2E,0xDF,
+    0x03,0x31,0xA2,0x28,0x56,0xD7,0xE2,0xBF,0xC2,0x30,0xA2,0x28,0x5D,0x7D,0x62,0x58,
+    0xA2,0x28,0x81,0x20,0x2F,0x25,0x2F,0x0A,0xC2,0x28,0xA2,0x28,0xBE,0x53,0x5D,0x55,
+    0xE3,0x30,0xA2,0x28,0xF7,0xFA,0xAB,0x27,0xE3,0x30,0xA2,0x28,0x0B,0x6E,0xAF,0xCA,
+    0x24,0x39,0xC2,0x30,0xEF,0xC9,0xA5,0xD5,0x03,0x31,0xA2,0x28,0x5E,0xFA,0x7E,0xAA,
+    0xE3,0x30,0xA2,0x28,0xBE,0x1F,0x97,0xB5,0xE3,0x30,0xC2,0x30,0x64,0xE0,0xA0,0x3D,
+    0x04,0x39,0xC2,0x30,0xFF,0xE5,0xC3,0xAE,0x03,0x39,0xC2,0x30,0xD4,0xD6,0x77,0xB7,
+    0x03,0x39,0xC2,0x30,0x2D,0xBD,0xFD,0x6B,0x03,0x39,0xC2,0x30,0xCA,0x82,0xC8,0x82,
+    0x03,0x39,0xA2,0x28,0xBA,0xBA,0xE8,0xFC,0x03,0x31,0xC2,0x30,0x77,0xF5,0xA5,0x55,
+    0xE3,0x30,0xA2,0x28,0x7D,0xFF,0xF6,0xBE,0x24,0x39,0xC2,0x28,0x75,0xFD,0xAD,0x25,
+    0x03,0x31,0xA2,0x28,0xFD,0xDF,0xF2,0xE8,0xC2,0x28,0x82,0x28,0x22,0x0A,0xA8,0xBE,
+    0xE3,0x30,0xA2,0x28,0x02,0x82,0x7B,0xDD,0x03,0x31,0xC3,0x28,0x7E,0xEF,0xAF,0xCD,
+    0x03,0x39,0xC3,0x30,0xC2,0x8B,0xFB,0x9A,0x03,0x31,0xC2,0x30,0xEB,0xF7,0x5E,0xD7,
+    0x03,0x31,0xA2,0x28,0xA8,0xBA,0x7B,0xFB,0x03,0x39,0xC2,0x28,0x9A,0xA0,0x5E,0x5D,
+    0xE2,0x30,0xC2,0x28,0xAF,0x3E,0x6D,0xF9,0x03,0x31,0xC2,0x28,0x97,0xD7,0x95,0x15,
+    0x03,0x31,0xC2,0x28,0xFB,0x36,0x2A,0x88,0x23,0x39,0xE3,0x30,0x7D,0xEA,0x6B,0xBF,
+    0x03,0x31,0xE2,0x30,0xB5,0xF3,0xA3,0x35,0x43,0x39,0x03,0x31,0x7F,0xFF,0x8F,0x6D,
+    0x23,0x39,0xC2,0x30,0xDA,0xAC,0x8A,0x2E,0x02,0x39,0xC2,0x30,0x65,0x32,0xA2,0x28,
+    0x64,0x49,0xE2,0x38,0x2D,0x29,0xAF,0xA7,0x85,0x51,0x44,0x49,0x8B,0xAA,0xDF,0xDD,
+    0x84,0x51,0x23,0x41,0x8A,0xFF,0x3D,0x8A,0x68,0x6A,0x64,0x49,0xBD,0xBD,0xBD,0x3F,
+    0x8C,0x93,0x88,0x72,0xA5,0x2D,0x29,0x2D,0xAC,0x93,0x4C,0x8B,0xA1,0xAE,0x2A,0xEE,
+    0xAC,0x93,0x4B,0x8B,0xA0,0xAB,0xEE,0x7F,0xAD,0x93,0x2B,0x83,0xA2,0x88,0xF8,0xDD,
+    0xCC,0x93,0xEA,0x7A,0x22,0xAA,0xFE,0x7F,0x6B,0x8B,0xA9,0x72,0xA8,0xA0,0xA2,0x7E,
+    0x4B,0x83,0x47,0x62,0x00,0x8A,0xAA,0x77,0x4B,0x83,0x07,0x5A,0x20,0x88,0xFE,0x55,
+    0x4B,0x83,0x27,0x62,0x02,0x02,0xAB,0xF5,0xAC,0x8B,0x89,0x6A,0x00,0x8A,0xAB,0xFD,
+    0xAC,0x8B,0x89,0x72,0x00,0xA0,0xFA,0x5F,0x8C,0x8B,0x07,0x5A,0xA0,0xFA,0x5F,0x57,
+    0x6B,0x8B,0x27,0x62,0x00,0xBD,0x75,0x55,0xAD,0x93,0x68,0x62,0x00,0x0A,0xBD,0x55,
+    0xED,0x93,0xEA,0x7A,0x82,0x8A,0xAA,0xBD,0xAD,0x93,0x8C,0x8B,0xA8,0xA8,0xEF,0xFD,
+    0xAC,0x93,0x6C,0x8B,0x2B,0xA1,0xCD,0xA5,0xCC,0x93,0x6C,0x8B,0xAA,0xEA,0xED,0x3F,
+    0xCD,0x93,0x8C,0x8B,0xAC,0x4F,0xA9,0x7B,0xCC,0x93,0x8B,0x8B,0x8C,0xFD,0xEB,0xCA,
+    0xAC,0x93,0x8C,0x8B,0xD2,0xF2,0x9F,0x36,0xED,0x9B,0x8C,0x8B,0x89,0xF9,0x95,0xDE,
+    0x43,0x51,0xE2,0x40,0xCA,0x7F,0xEA,0xFE,0x43,0x49,0xE2,0x40,0xF9,0x61,0xEF,0xAD,
+    0x43,0x49,0xE2,0x40,0xEE,0xEB,0xB7,0xBF,0x23,0x49,0x02,0x41,0xDA,0xDF,0xF2,0xEA,
+    0x43,0x49,0xE2,0x40,0xBB,0x6B,0x78,0x5F,0x22,0x41,0xC1,0x38,0x2A,0xAF,0xBF,0xB5,
+    0x23,0x49,0xE2,0x38,0x5F,0x2B,0x3B,0xD7,0x03,0x41,0xC2,0x38,0xEA,0x7C,0xFC,0xF6,
+    0x02,0x41,0xC2,0x38,0x0B,0x8B,0xED,0xEB,0x02,0x41,0xA1,0x38,0x00,0x01,0x09,0x0B,
+    0x23,0x49,0xE2,0x40,0x37,0x3A,0xBE,0xF6,0x03,0x49,0x22,0x41,0xAA,0xB9,0xF7,0xAE,
+    0x64,0x51,0xE2,0x40,0x35,0x17,0xBF,0xAE,0x6A,0x93,0xA5,0x59,0x0B,0x0B,0x2D,0xF5,
+    0xAA,0x9B,0x87,0x7A,0x8A,0x82,0xEE,0x7D,0x6A,0x93,0xC7,0x82,0x80,0xA0,0xFF,0x5D,
+    0x49,0x93,0xA7,0x7A,0x80,0x2A,0xFE,0x5F,0x29,0x8B,0xA7,0x82,0xF8,0xEA,0xBF,0xD7,
+    0xE8,0x82,0xA7,0x7A,0x7E,0xFE,0xA0,0x50,0x09,0x8B,0x66,0x72,0x22,0xAA,0xDA,0x7F,
+    0x09,0x8B,0xC5,0x61,0xF0,0xFE,0x7F,0x5F,0x06,0x6A,0xE5,0x61,0xBC,0x3E,0x7C,0x57,
+    0x26,0x6A,0xC4,0x61,0x28,0x20,0x0A,0xFD,0x46,0x6A,0xE5,0x61,0x0A,0xAA,0xB6,0xF7,
+    0x67,0x72,0xA4,0x59,0x00,0xA8,0xFA,0x5E,0x25,0x6A,0x63,0x51,0x00,0xF8,0x5E,0x55,
+    0xA5,0x59,0x03,0x49,0xB0,0xFC,0xFF,0xBF,0x84,0x51,0x23,0x49,0xA0,0xAA,0x0D,0x2E,
+    0x84,0x51,0x02,0x41,0x7A,0x72,0x7E,0xFE,0x64,0x49,0x02,0x41,0x7D,0xFF,0x3D,0x0F,
+    0xC5,0x51,0xE2,0x40,0xFD,0xBF,0xAE,0xA0,0x85,0x51,0x23,0x41,0xAA,0x2A,0xA9,0xAB,
+    0xA5,0x51,0x44,0x49,0xBF,0xA7,0x2F,0xFE,0xA5,0x51,0x44,0x49,0xFF,0xD6,0x78,0xFB,
+    0x84,0x49,0x44,0x49,0xEF,0x7F,0x5B,0x6B,0x64,0x49,0x23,0x41,0x6F,0xCA,0xAA,0xE2,
+    0x64,0x49,0x03,0x41,0xAE,0xFF,0xFE,0xDC,0x44,0x49,0xE2,0x38,0xA0,0xAA,0xEE,0xDE,
+    0x44,0x49,0xE3,0x40,0xA2,0xAB,0xEB,0xBF,0x23,0x41,0x03,0x41,0xF0,0xBE,0x57,0xD0,
+    0x44,0x41,0xE2,0x38,0xDF,0xFF,0xFE,0xB8,0x23,0x41,0xE2,0x38,0x7E,0xFF,0xD8,0xBA,
+    0x44,0x49,0xE3,0x38,0x9D,0xB7,0xAB,0x82,0x64,0x49,0x03,0x41,0x2B,0xEA,0xEF,0x55,
+    0x43,0x41,0xE2,0x38,0x70,0x7A,0x7A,0x7F,0x03,0x39,0xA1,0x30,0xAA,0xBB,0x2B,0xF5,
+    0x03,0x39,0xC2,0x30,0xE2,0x6A,0x78,0x7A,0xE3,0x38,0x81,0x28,0x7C,0x5E,0x77,0xEF,
+    0xA2,0x28,0x61,0x20,0xFE,0x7A,0x7B,0x7A,0xA2,0x28,0x61,0x20,0xF7,0xED,0x2D,0x09,
+    0xA2,0x20,0x61,0x20,0x25,0x0C,0x08,0x2A,0xC2,0x28,0x81,0x20,0xBA,0xEA,0x02,0x25,
+    0xC2,0x28,0x81,0x20,0xBD,0xA5,0xBB,0xFF,0xA2,0x28,0x81,0x20,0x1A,0xBA,0xFF,0xCA,
+    0xA2,0x28,0x81,0x20,0xE2,0xCB,0x2B,0xAF,0xA2,0x28,0x81,0x20,0xA8,0xBE,0xFB,0xD7,
+    0xA2,0x28,0x82,0x20,0xAE,0xEF,0xEF,0xBF,0xA2,0x28,0x61,0x20,0xAA,0xFB,0xDF,0xFC,
+    0xA2,0x28,0x61,0x20,0x3E,0xAE,0xBF,0x3F,0xA2,0x30,0x81,0x20,0x3F,0xBE,0x37,0x3E,
+    0x03,0x39,0xA2,0x28,0xBD,0xAF,0xA9,0xAF,0xE3,0x38,0xC2,0x30,0xAD,0xA9,0x08,0x80,
+    0xE2,0x38,0xC2,0x30,0xEA,0x66,0xFE,0xF4,0xE3,0x38,0xA2,0x28,0x5E,0xFB,0xFA,0xF8,
+    0xC2,0x30,0xA2,0x28,0xFA,0xBF,0x3C,0x13,0xE2,0x30,0xA3,0x28,0xEE,0xEB,0xAA,0xEA,
+    0xE3,0x30,0xA2,0x28,0xB7,0xEB,0x25,0xF5,0xC2,0x28,0xA1,0x28,0x30,0xF8,0x57,0x55,
+    0xC2,0x28,0x61,0x28,0x02,0x88,0xAA,0xAE,0xC2,0x28,0x81,0x20,0xA8,0xFA,0x7A,0x7E,
+    0xC2,0x28,0x82,0x28,0xAB,0x0E,0x0D,0x2B,0xE3,0x30,0xA2,0x28,0x5D,0xC3,0xFB,0xBB,
+    0xE3,0x30,0xA2,0x28,0xB5,0xD5,0x55,0x56,0xE3,0x30,0xA2,0x28,0xAE,0xAB,0x01,0x03,
+    0x03,0x31,0xA2,0x28,0x3F,0xFF,0xDE,0xBF,0xE3,0x30,0xC2,0x30,0x82,0x73,0xE3,0x00,
+    0x03,0x39,0xA2,0x28,0xF7,0xA7,0x3F,0x0E,0x03,0x39,0xC3,0x30,0xB5,0xFE,0xCE,0xAA,
+    0x24,0x39,0xE3,0x30,0x59,0x6B,0x59,0x7F,0xE2,0x30,0xA2,0x30,0x0A,0x0A,0x2F,0xB5,
+    0x03,0x39,0xC2,0x30,0xEB,0xAA,0xFF,0xFD,0x44,0x41,0xA2,0x30,0xAF,0x8D,0xAF,0xEF,
+    0x23,0x39,0xC2,0x30,0x5E,0x7A,0xAC,0x28,0x03,0x31,0xC2,0x30,0x75,0x5E,0xBC,0xEA,
+    0xE3,0x30,0xA1,0x28,0xBA,0xE0,0xBA,0xD6,0x03,0x31,0xC2,0x30,0x2B,0xEE,0x2F,0xDF,
+    0x03,0x31,0xC2,0x30,0x7A,0x88,0x2A,0xFB,0xE3,0x30,0xA2,0x28,0x55,0x57,0xDC,0x28,
+    0xC2,0x30,0xA2,0x28,0x79,0x62,0x72,0x52,0xE3,0x30,0x81,0x20,0x0B,0xB7,0xB5,0xEF,
+    0xE3,0x30,0xC2,0x28,0xE0,0xB0,0xEF,0xE5,0xE3,0x30,0xC2,0x28,0xBA,0xEF,0x8E,0xAD,
+    0xE3,0x30,0xC2,0x28,0xA6,0x07,0xFE,0x6F,0x03,0x31,0xC2,0x30,0x55,0xD7,0xBD,0x9B,
+    0xE2,0x30,0xC2,0x28,0xED,0xB3,0x00,0x00,0x23,0x39,0xC2,0x28,0xDD,0xFF,0xFF,0xCA,
+    0x23,0x39,0xE3,0x30,0x8F,0x2F,0x7F,0xFB,0x03,0x31,0xC2,0x30,0x88,0xFE,0xFE,0xBF,
+    0x03,0x39,0xC2,0x28,0x37,0xB7,0xBF,0xFB,0x03,0x39,0xE2,0x30,0x82,0xA2,0xFD,0xB5,
+    0x23,0x39,0xE2,0x30,0x9F,0x9E,0x1F,0x3F,0x23,0x41,0xE2,0x38,0xD5,0xB7,0x9B,0x06,
+    0x85,0x49,0x03,0x39,0xBD,0xBD,0xAF,0x2F,0xC5,0x51,0x64,0x49,0x55,0x9D,0xEB,0x32,
+    0xE5,0x59,0x64,0x49,0xFD,0xB5,0xEB,0x2A,0xC9,0x7A,0xA5,0x51,0xB5,0xBD,0xAF,0x2F,
+    0x8C,0x93,0xA8,0x72,0xAD,0xFD,0xFF,0x8A,0x4A,0x8B,0x87,0x72,0x88,0xDF,0x57,0xA0,
+    0x0A,0x83,0x47,0x6A,0x00,0xFE,0xDF,0xF8,0xE9,0x7A,0x26,0x62,0x08,0xFD,0xDD,0xAA,
+    0xC8,0x72,0x26,0x62,0xE8,0x5F,0xFF,0xBF,0xA8,0x72,0x06,0x5A,0xF8,0x77,0xFE,0x02,
+    0xA9,0x72,0xE6,0x51,0x57,0x75,0xEB,0x02,0xC9,0x72,0xE6,0x51,0x55,0x77,0xBA,0x00,
+    0xA9,0x72,0x07,0x5A,0xF5,0xBF,0xBB,0x00,0xC9,0x72,0x27,0x62,0xF7,0xFF,0xE8,0x2A,
+    0xA9,0x72,0x47,0x62,0xEB,0xE9,0xEF,0x0A,0xA9,0x72,0x07,0x62,0xFF,0x7F,0xF8,0xB8,
+    0x68,0x6A,0x06,0x5A,0xB9,0xEA,0x82,0x88,0x68,0x6A,0x27,0x62,0x56,0xFE,0xB0,0x20,
+    0x0A,0x7B,0x06,0x5A,0x2D,0xF7,0xFF,0x7F,0x8C,0x8B,0x47,0x62,0x00,0x2B,0xAD,0xB5,
+    0xAD,0x93,0x4B,0x83,0x2F,0xAE,0xFF,0x75,0xAD,0x93,0x6B,0x8B,0x0A,0x3F,0xB5,0x7B,
+    0xAC,0x8B,0x6B,0x8B,0x2C,0x2F,0xB5,0x25,0xAC,0x93,0x6C,0x8B,0x00,0xEC,0xAA,0x7E,
+    0xCD,0x93,0x6B,0x8B,0x5C,0x57,0xA5,0xDB,0xAD,0x93,0x6B,0x8B,0x2C,0xAE,0xAE,0x1E,
+    0x23,0x49,0xC2,0x40,0xF6,0x82,0xA8,0xA8,0x23,0x49,0xE2,0x40,0xAB,0xAE,0xBA,0xE2,
+    0x43,0x51,0xE2,0x40,0x8A,0xE3,0xEF,0xE7,0x23,0x49,0xE2,0x40,0xCF,0xB7,0x2B,0xAA,
+    0x23,0x49,0xE2,0x40,0x57,0xD5,0xDC,0xAA,0x23,0x49,0xC1,0x38,0xA7,0xAE,0xEA,0x8A,
+    0x23,0x49,0xE2,0x38,0xBF,0xBD,0xAF,0x2E,0x24,0x41,0xE2,0x40,0xD5,0x47,0xFB,0xEF,
+    0x03,0x41,0xE2,0x38,0x5E,0x5C,0x28,0x80,0x23,0x41,0xC1,0x40,0x2D,0xAF,0xAA,0xAA,
+    0x43,0x49,0xE2,0x40,0xBE,0xBE,0x9B,0x00,0x22,0x49,0x03,0x41,0x62,0x60,0xEA,0xAE,
+    0x23,0x49,0xE2,0x40,0x0A,0x2A,0xF7,0xF7,0xC4,0x59,0x02,0x41,0x2F,0xA5,0x55,0x55,
+    0x46,0x72,0x02,0x49,0x0A,0xBF,0xFD,0x75,0xA7,0x7A,0xA3,0x59,0x02,0x2F,0xAD,0xB5,
+    0xC8,0x82,0x25,0x72,0xA0,0xF2,0xBE,0xD5,0xC7,0x82,0x45,0x72,0xA8,0xAA,0xFD,0x75,
+    0xE7,0x82,0x46,0x72,0xA0,0xAA,0xAB,0xFD,0x86,0x7A,0xC4,0x61,0xC0,0x40,0x78,0x5E,
+    0x06,0x6A,0x64,0x51,0xA2,0xBE,0xDF,0x57,0xE5,0x61,0x43,0x51,0x80,0xAC,0xFE,0x55,
+    0xE5,0x61,0x43,0x51,0x00,0x0A,0xAE,0xA5,0x05,0x6A,0x84,0x51,0xA8,0xEE,0x7F,0xDA,
+    0xC5,0x61,0x43,0x51,0xF2,0x6A,0x78,0xFA,0x83,0x51,0x03,0x49,0xAA,0xFF,0x7A,0xAA,
+    0x64,0x51,0x23,0x49,0xAD,0xE5,0xC5,0x7D,0x64,0x49,0x23,0x49,0x08,0x02,0x03,0x03,
+    0x63,0x49,0x22,0x41,0xE6,0x8C,0x00,0x0E,0xC6,0x59,0x23,0x41,0xBD,0x2D,0x2F,0x8B,
+    0xC5,0x59,0x44,0x41,0xA2,0xA8,0x6A,0xDE,0xA5,0x51,0x64,0x49,0x6A,0xE6,0x3D,0xBB,
+    0x85,0x49,0x44,0x49,0xE2,0xE8,0xF8,0x9E,0x64,0x49,0x44,0x49,0xA2,0x7A,0xF8,0xFB,
+    0x85,0x51,0x24,0x41,0xA3,0xEF,0xFB,0xFD,0x64,0x49,0x23,0x49,0x30,0x83,0xA9,0xED,
+    0x43,0x49,0x03,0x41,0xFC,0xBC,0xAA,0xB2,0xE6,0x61,0x23,0x41,0x55,0x55,0xF7,0x2D,
+    0xE6,0x61,0x03,0x41,0x55,0xDF,0xBF,0x00,0xE6,0x61,0x23,0x41,0x55,0xFA,0x82,0x00,
+    0xC5,0x61,0x03,0x41,0x55,0x77,0xFE,0x80,0x64,0x49,0x03,0x41,0x75,0xFF,0xBF,0xA8,
+    0x85,0x49,0x03,0x41,0x7B,0x5A,0xFB,0xCA,0x23,0x41,0xE2,0x38,0x2F,0x2F,0xBE,0x7A,
+    0x23,0x41,0xC2,0x30,0xEB,0x6B,0xA0,0xE2,0x03,0x39,0xA2,0x30,0xFD,0x2F,0x2A,0xAA,
+    0x03,0x39,0xC2,0x30,0xE2,0xE2,0x80,0x00,0x03,0x39,0xA2,0x28,0x77,0x7F,0x7C,0x78,
+    0xC2,0x28,0x61,0x20,0x7E,0xFE,0xBE,0x3F,0xE3,0x30,0x61,0x20,0xFD,0xAF,0x2A,0x00,
+    0x04,0x31,0x81,0x20,0x5D,0xD7,0xA8,0x80,0xE3,0x30,0x81,0x20,0xD5,0xFE,0xA2,0xE8,
+    0xE2,0x28,0xA2,0x28,0x5F,0x7B,0xFE,0xF2,0xA2,0x28,0x81,0x20,0xC8,0x48,0x40,0xE0,
+    0xA2,0x28,0x81,0x20,0xFD,0x69,0xBF,0xB7,0xA2,0x28,0x61,0x20,0xAE,0xAF,0x0F,0x0A,
+    0xA2,0x28,0x82,0x28,0xB7,0x3F,0x3F,0xF3,0xC2,0x30,0x82,0x28,0x54,0xF6,0x7F,0xF5,
+    0xA1,0x28,0x61,0x20,0xBE,0xCF,0xFD,0xEF,0xC3,0x30,0x82,0x28,0xF7,0xFD,0xDD,0x49,
+    0x03,0x41,0x82,0x28,0xAF,0x0D,0x3F,0x0B,0x23,0x41,0xC3,0x38,0x6F,0xFB,0xE0,0x08,
+    0x23,0x41,0xA1,0x30,0xDD,0xAF,0xE8,0x28,0xE2,0x38,0xA2,0x30,0xF8,0xFA,0xE8,0xE8,
+    0xC2,0x30,0xA2,0x28,0xBF,0xDE,0xD8,0x58,0xC2,0x30,0x81,0x28,0x00,0xAA,0xF8,0xFA,
+    0xC2,0x28,0x81,0x28,0x3A,0xBB,0xBB,0xAB,0xE2,0x30,0x81,0x28,0x7F,0xEB,0xA3,0xAA,
+    0xC3,0x30,0x81,0x28,0xF5,0xFF,0xBE,0x02,0xC2,0x28,0x81,0x28,0xE7,0xF7,0xFF,0xA8,
+    0xA2,0x28,0x81,0x20,0x02,0x05,0x2D,0x80,0xC3,0x30,0x81,0x28,0x0A,0xAB,0x7F,0xD5,
+    0xC2,0x28,0x81,0x20,0x2A,0x2B,0xD7,0xDD,0x03,0x39,0xA2,0x28,0x2B,0x23,0xAD,0x0D,
+    0x03,0x39,0xE3,0x28,0xFF,0x94,0xA6,0x08,0xE2,0x30,0xC2,0x28,0x80,0x88,0x26,0x26,
+    0x03,0x39,0xC2,0x30,0xAA,0xFC,0xF8,0xF6,0x03,0x39,0xC3,0x30,0x5E,0xAB,0xA3,0xF8,
+    0x03,0x39,0xE3,0x30,0x61,0x7A,0x78,0x68,0xE3,0x30,0xA2,0x30,0xDA,0x7A,0xAA,0x02,
+    0xC2,0x30,0xA2,0x30,0x22,0xAB,0xB8,0x2C,0x03,0x39,0xC2,0x30,0xF3,0x25,0x25,0xED,
+    0x23,0x39,0xE2,0x30,0x6A,0xFE,0xFA,0xA3,0x03,0x39,0xE2,0x30,0xAD,0xAD,0xF6,0xB8,
+    0x03,0x31,0xC2,0x30,0xD7,0x6B,0x7A,0x7A,0xE2,0x30,0xA2,0x28,0xA2,0xBE,0xEF,0xFA,
+    0x03,0x39,0xC2,0x28,0x9D,0xFC,0xFA,0x59,0xE2,0x30,0xA2,0x28,0xAC,0xBE,0xCE,0xAF,
+    0xE2,0x30,0xA1,0x28,0x5A,0xFA,0xFB,0xBA,0xC2,0x28,0xA1,0x28,0x27,0x0E,0x00,0x00,
+    0xE3,0x30,0xC2,0x28,0xCD,0x0B,0x25,0x2D,0xE3,0x30,0xC2,0x30,0xE5,0xBE,0xA0,0x20,
+    0x03,0x39,0xC2,0x28,0xF7,0xFB,0x2A,0x6A,0x03,0x31,0xC2,0x28,0xDA,0xFA,0xAB,0xAA,
+    0x03,0x31,0xC2,0x28,0x3F,0xBD,0xAF,0xF7,0x03,0x31,0xE2,0x30,0xC4,0x3E,0xF9,0x63,
+    0x03,0x31,0xC2,0x30,0x08,0x2C,0xC0,0x82,0x03,0x31,0xC2,0x28,0xAC,0x70,0x60,0x80,
+    0x03,0x31,0xC2,0x30,0xB4,0xAB,0xFD,0x7A,0x23,0x39,0xC2,0x30,0xFE,0x97,0xAD,0x27,
+    0x44,0x41,0x03,0x39,0xDD,0xB6,0xE3,0xE3,0x64,0x49,0x23,0x41,0x5F,0x5D,0x4F,0xA3,
+    0x85,0x51,0x03,0x39,0x25,0xBD,0xAF,0xEC,0xC5,0x51,0x43,0x41,0xE2,0xAA,0xBF,0xD5,
+    0x26,0x62,0x43,0x49,0xAF,0x2F,0x2F,0xBD,0x0D,0xA4,0x26,0x62,0xBD,0xAD,0x2F,0x0F,
+    0x6E,0xAC,0x6B,0x8B,0xED,0xAF,0x0A,0x00,0x6E,0xAC,0xED,0x9B,0x57,0x2A,0x82,0x00,
+    0x6E,0xAC,0x2A,0x83,0x7F,0xA8,0x20,0x00,0x6E,0xAC,0x2A,0x83,0x55,0xFE,0xAA,0x00,
+    0x6F,0xAC,0xE9,0x7A,0x55,0xFE,0xA2,0x08,0x2E,0xA4,0xE9,0x7A,0x55,0x7F,0xEC,0x80,
+    0x8B,0x8B,0xA9,0x72,0xFD,0xFA,0xA2,0xA0,0x4B,0x8B,0xC9,0x72,0x77,0xFE,0x72,0xF8,
+    0x09,0x7B,0xC9,0x72,0xBB,0xEB,0x82,0x6A,0xE9,0x7A,0xA8,0x72,0x35,0x17,0xEE,0xFA,
+    0xE9,0x7A,0xA8,0x72,0x69,0xBA,0x02,0xA6,0xE9,0x72,0x67,0x6A,0xD6,0x7F,0xAE,0xE8,
+    0xC9,0x72,0x67,0x6A,0x56,0xDE,0xFE,0xD0,0xA8,0x72,0x67,0x6A,0x4F,0xA3,0xF7,0xBB,
+    0x88,0x6A,0x47,0x62,0x67,0x4B,0x76,0xA8,0xA8,0x72,0x06,0x5A,0x2F,0x5F,0xFA,0xBB,
+    0x6C,0x8B,0x47,0x62,0x0A,0x2D,0xB5,0x55,0x8B,0x8B,0xA8,0x6A,0x80,0x00,0x0B,0xAD,
+    0xAC,0x93,0x6B,0x83,0xFF,0xAB,0xE9,0xBD,0x8B,0x8B,0x4B,0x83,0xEE,0xEA,0xEA,0x26,
+    0x8C,0x8B,0x2A,0x83,0xAE,0xF7,0xAB,0xA2,0xAC,0x93,0x4B,0x83,0xAB,0xAB,0x6A,0xFA,
+    0x23,0x49,0xE2,0x40,0x3A,0xBA,0xAC,0x7A,0x23,0x49,0xE2,0x40,0x2C,0x0A,0xAD,0x41,
+    0x02,0x49,0xE2,0x40,0x28,0xBA,0xBE,0x07,0x23,0x49,0xE2,0x40,0xB0,0xEE,0xE7,0x8B,
+    0x23,0x49,0xE2,0x40,0x8A,0x08,0x28,0xAE,0x23,0x49,0xC2,0x38,0x2B,0x26,0xAA,0xBA,
+    0x23,0x49,0xE2,0x40,0x8B,0xAE,0x2E,0x3C,0x22,0x41,0xE2,0x40,0x6B,0x3E,0x20,0x2A,
+    0x23,0x49,0x02,0x41,0x61,0xEB,0xEC,0x77,0x23,0x41,0xE2,0x38,0x2B,0xBA,0xAF,0xEB,
+    0x43,0x49,0x02,0x41,0x3F,0xFD,0xCF,0x85,0xE2,0x48,0x22,0x41,0xBD,0xA9,0xEB,0xBF,
+    0x23,0x49,0xE2,0x40,0xFD,0xBF,0xEE,0x62,0x03,0x49,0xC2,0x40,0x0A,0xFA,0xFE,0xFF,
+    0x63,0x51,0xC2,0x40,0xBD,0xB5,0x3F,0xBF,0x25,0x6A,0x63,0x51,0x09,0x8D,0x8F,0xAD,
+    0x25,0x6A,0xC4,0x61,0x0F,0xED,0x0F,0x22,0x47,0x72,0xE5,0x61,0xA2,0xED,0xE5,0xD7,
+    0x46,0x72,0xC5,0x59,0x8A,0xAE,0xFB,0x56,0xE5,0x61,0x43,0x51,0x20,0xF8,0xB8,0x5E,
+    0xA4,0x59,0x02,0x49,0xF8,0x5E,0x57,0x57,0x24,0x49,0xA3,0x40,0xE8,0xFE,0xDF,0xB7,
+    0x84,0x59,0xE2,0x40,0x0F,0x2D,0x2D,0x2D,0xC4,0x59,0x84,0x59,0xC2,0xAA,0x8D,0xEB,
+    0xC5,0x59,0x63,0x51,0xDE,0xEA,0x82,0xA2,0xA4,0x59,0x63,0x51,0xD7,0xDC,0x60,0x72,
+    0x84,0x51,0x43,0x49,0xF5,0xCF,0x8A,0x2B,0xA4,0x51,0x64,0x51,0x79,0xED,0x7B,0x5D,
+    0xA4,0x51,0x43,0x49,0xB7,0xB5,0xAF,0x2B,0xA5,0x51,0x44,0x49,0x80,0xA0,0xB8,0xD8,
+    0x84,0x51,0x44,0x49,0xAA,0xE8,0xF7,0xFF,0x84,0x49,0x44,0x49,0x01,0xA1,0xFD,0xDE,
+    0x64,0x49,0x23,0x41,0x08,0xAA,0x7A,0x80,0x64,0x49,0x23,0x41,0x2E,0xE2,0xEF,0xDF,
+    0x64,0x51,0x23,0x49,0xAF,0x0A,0xBE,0x27,0xA4,0x59,0x23,0x49,0xDF,0x7F,0xDE,0x3B,
+    0x06,0x6A,0x02,0x41,0xF5,0xBF,0x2B,0x0E,0x06,0x6A,0x64,0x51,0x0D,0x0B,0x82,0xA0,
+    0x47,0x72,0x43,0x51,0x8A,0xA2,0xA3,0xD7,0xE5,0x61,0x83,0x59,0x88,0xBA,0xE2,0x55,
+    0xE6,0x61,0x84,0x51,0xE0,0xAB,0xED,0x7F,0x85,0x51,0x03,0x41,0xD8,0xF8,0x7A,0x5A,
+    0x64,0x49,0x02,0x41,0x2A,0xFF,0x7D,0x55,0x23,0x41,0xC2,0x38,0x68,0xE0,0xEA,0xBA,
+    0x23,0x41,0xE3,0x38,0x82,0x03,0xEB,0xF9,0x03,0x39,0xC2,0x30,0x8A,0xA8,0xF0,0x7E,
+    0x23,0x39,0xC2,0x30,0xAB,0xAF,0xFF,0xD5,0x03,0x39,0x82,0x20,0x70,0xF0,0xF0,0xFA,
+    0xC2,0x28,0x61,0x20,0x3F,0xB7,0xBD,0x17,0x03,0x31,0xC3,0x28,0x0A,0x03,0x03,0xFD,
+    0x03,0x31,0xC3,0x28,0x20,0x62,0x77,0x55,0xC3,0x28,0x62,0x28,0xA8,0x2A,0xA8,0xE8,
+    0xC2,0x30,0x81,0x28,0x02,0xBC,0xAC,0xB7,0xC2,0x28,0x81,0x28,0xFA,0x7A,0x6F,0xAF,
+    0xA2,0x30,0x81,0x20,0xEF,0xFD,0x5F,0x28,0xC3,0x30,0x81,0x28,0xED,0xF5,0x35,0x3C,
+    0x44,0x41,0x81,0x28,0xD5,0xBF,0xBB,0x82,0x24,0x41,0xA2,0x30,0x57,0x5A,0xA8,0x82,
+    0xE3,0x38,0x61,0x28,0x57,0xFF,0xEA,0xA0,0xA2,0x30,0x82,0x28,0x8D,0xB7,0xBB,0x88,
+    0x24,0x41,0xA2,0x30,0xAD,0x2F,0xAD,0xAD,0x44,0x49,0x03,0x41,0xAF,0xBA,0xAB,0x9F,
+    0x44,0x49,0x03,0x39,0xDE,0x7C,0x7E,0xC0,0x23,0x41,0xA2,0x30,0xFE,0xEA,0xEA,0xFC,
+    0xE2,0x38,0x81,0x28,0x7A,0xEA,0xAA,0x00,0xC2,0x30,0x81,0x28,0xFF,0x7A,0xE8,0xDA,
+    0xE2,0x30,0x81,0x20,0xFF,0xAD,0x0B,0x2A,0x24,0x39,0xC2,0x28,0xFD,0xBF,0xAF,0x0A,
+    0x24,0x39,0xE3,0x30,0x55,0xE7,0x0B,0x02,0x44,0x39,0xC2,0x30,0x5F,0x7A,0xE8,0x0A,
+    0x44,0x39,0xA2,0x28,0x57,0x57,0xFF,0xE8,0x03,0x31,0x82,0x28,0x77,0xFF,0xE2,0xAA,
+    0xE3,0x30,0x81,0x28,0x77,0xFF,0xBE,0x02,0x04,0x39,0xA2,0x28,0x09,0xAD,0x2F,0x3A,
+    0x24,0x39,0xE2,0x30,0xAA,0xEF,0xEF,0xFD,0xE2,0x30,0xA2,0x28,0x00,0x02,0x00,0xF8,
+    0xE3,0x30,0xA2,0x28,0xBE,0xA6,0xFA,0xE3,0xC2,0x30,0xA2,0x28,0x00,0x0E,0x2D,0x2F,
+    0x03,0x39,0xC3,0x30,0xC2,0xEB,0xFF,0xF7,0xE2,0x30,0xA1,0x30,0xC8,0xA9,0xE6,0xAE,
+    0xE2,0x30,0xC2,0x30,0x57,0x57,0xD5,0x8D,0x03,0x39,0xC2,0x30,0xB5,0x3D,0x97,0xD7,
+    0x44,0x39,0xE2,0x30,0xFB,0xDE,0xAE,0xF7,0x03,0x31,0xE2,0x30,0x03,0x82,0xBE,0xB6,
+    0x03,0x31,0xC2,0x30,0x8F,0x8A,0x62,0xF8,0xE2,0x30,0xA2,0x28,0xEA,0x7A,0x6F,0xEC,
+    0xE3,0x30,0xA2,0x28,0xFD,0xA9,0xAD,0x8B,0xE3,0x30,0xA2,0x28,0xAD,0xEB,0x6B,0x7A,
+    0xE2,0x28,0xA1,0x28,0xBF,0x6F,0x55,0xA5,0xC2,0x28,0xA2,0x28,0x80,0x8B,0xF9,0xF8,
+    0xE2,0x28,0xA1,0x28,0xAA,0xDA,0xF7,0x55,0xE3,0x30,0xA1,0x28,0x23,0x0E,0xAB,0x9B,
+    0x03,0x31,0xC2,0x28,0xE3,0xB2,0xEB,0xDF,0x03,0x31,0xE3,0x30,0xCD,0xEF,0xA5,0xF7,
+    0x02,0x31,0xC2,0x30,0x5B,0xCA,0xDE,0xFE,0x03,0x31,0xC2,0x28,0xA8,0xBB,0xFD,0xEB,
+    0x23,0x31,0xC2,0x30,0xFF,0x7E,0xF7,0xD5,0x23,0x31,0xC2,0x30,0xCB,0xFF,0xFB,0x9E,
+    0x02,0x39,0xC2,0x30,0x7A,0xE2,0xFA,0xAC,0x24,0x39,0xC2,0x30,0xB5,0xA5,0x25,0xB5,
+    0x64,0x41,0xE2,0x38,0xF3,0xFF,0xD7,0x57,0x85,0x49,0x24,0x41,0xFB,0xAD,0xAD,0x29,
+    0xA5,0x51,0x43,0x41,0xDD,0xFD,0x6B,0x8A,0xC6,0x59,0x43,0x49,0x75,0xFD,0x97,0x27,
+    0x09,0x83,0x43,0x49,0xFD,0xBD,0x2F,0x2F,0xAF,0xB4,0xA8,0x72,0xAD,0xAF,0x2F,0x2A,
+    0xD0,0xBC,0x6E,0xAC,0x75,0xFF,0xA3,0xA2,0xAF,0xB4,0x4E,0xAC,0xFF,0x7E,0xBA,0xFE,
+    0x8F,0xB4,0x6E,0xAC,0xDD,0xBA,0x0A,0x0F,0xAF,0xB4,0x4E,0xAC,0xDF,0xBA,0x00,0xA2,
+    0xAF,0xB4,0x6E,0xAC,0x57,0xF5,0x2A,0x00,0xAF,0xB4,0x0D,0xA4,0x6A,0xAA,0xE8,0x20,
+    0x4F,0xAC,0x6B,0x8B,0x57,0x58,0x78,0xC0,0x4B,0x8B,0x0A,0x83,0xEE,0xFA,0x5F,0x5A,
+    0x0A,0x7B,0xC9,0x72,0xA2,0xE0,0xE8,0x68,0xE9,0x7A,0xA8,0x72,0xFA,0x62,0x5A,0x7A,
+    0xA8,0x72,0x47,0x62,0x20,0x00,0xEA,0xDA,0xC9,0x72,0x47,0x62,0x02,0x8E,0x8F,0xB5,
+    0xE9,0x7A,0x88,0x6A,0x7F,0x9E,0x83,0xCA,0xC9,0x72,0x67,0x6A,0xFD,0xBF,0x38,0xAA,
+    0xC9,0x72,0x67,0x62,0x5A,0xFA,0x88,0xC0,0xA8,0x72,0x47,0x62,0xDF,0xF8,0xE0,0xE8,
+    0x87,0x6A,0x27,0x62,0x56,0xF7,0x6E,0xCB,0xE9,0x7A,0x06,0x5A,0x2F,0xFF,0xD5,0x57,
+    0x6B,0x83,0x06,0x5A,0x00,0x02,0x2D,0x35,0x8C,0x8B,0x4B,0x83,0xEA,0x3A,0x2C,0x35,
+    0x8C,0x8B,0x4B,0x83,0xB8,0xE8,0x30,0x9A,0x8C,0x8B,0x4B,0x83,0x9E,0xBA,0xAE,0xDC,
+    0x23,0x49,0xE3,0x40,0xFA,0xE8,0xBF,0x2D,0x23,0x49,0xE2,0x40,0xA5,0xAD,0xFA,0x5E,
+    0x23,0x41,0xC2,0x40,0x7F,0xFC,0xBE,0xFA,0x23,0x41,0xC2,0x40,0xAA,0xA9,0x2A,0xAB,
+    0x23,0x49,0xE2,0x40,0xBE,0x9E,0xFE,0xEA,0x23,0x49,0xE2,0x40,0x56,0xDE,0x1E,0xED,
+    0x23,0x49,0xE2,0x40,0xAF,0xFF,0xFE,0x88,0x43,0x49,0xE2,0x40,0xFF,0xEF,0xA7,0xAC,
+    0x43,0x49,0xE2,0x40,0xFB,0x6B,0xE0,0xD0,0x23,0x41,0xE2,0x40,0xAB,0x89,0x8B,0xAA,
+    0x43,0x49,0x03,0x41,0xF5,0xD7,0xB7,0xA4,0x43,0x49,0x03,0x41,0x9F,0x3E,0xA8,0xBF,
+    0x43,0x49,0xE3,0x40,0x78,0xC8,0xAF,0xEF,0x02,0x41,0xC2,0x40,0xBF,0xDF,0x5C,0xA0,
+    0x23,0x49,0xE2,0x40,0x3F,0x3F,0xDD,0xF7,0xE5,0x61,0x03,0x49,0x2F,0x3F,0xB5,0xF5,
+    0x05,0x6A,0xA4,0x59,0x0A,0xAE,0xC2,0x2D,0x26,0x6A,0x84,0x59,0xA8,0xE2,0x7A,0x7A,
+    0xE5,0x61,0x03,0x49,0xA8,0xEA,0xFE,0x7F,0x84,0x59,0xE2,0x40,0xA0,0xE0,0xFF,0xDD,
+    0x03,0x49,0xC2,0x40,0xA8,0xEA,0xFE,0x9A,0x03,0x49,0xC2,0x40,0xBA,0x88,0x78,0x9A,
+    0x85,0x59,0xE2,0x40,0x3D,0x3D,0x35,0x27,0xE6,0x61,0xA5,0x59,0xED,0xD6,0xB6,0x09,
+    0xE6,0x61,0xA5,0x59,0x5D,0x76,0xDA,0xBB,0xC5,0x59,0x64,0x51,0x5A,0x60,0xFC,0xF8,
+    0x84,0x51,0x43,0x51,0xAA,0x8B,0x8B,0x04,0xC5,0x51,0x64,0x51,0xFD,0xFD,0xED,0xBF,
+    0xC5,0x59,0x84,0x51,0xB5,0xBA,0x6D,0xD8,0xA5,0x51,0x64,0x49,0xF8,0xEE,0xD6,0x58,
+    0x85,0x51,0x44,0x49,0xEC,0xBA,0xEF,0xBF,0x84,0x49,0x23,0x41,0xF8,0x5E,0xFA,0x80,
+    0x85,0x51,0x23,0x49,0xFB,0xFB,0x6A,0xFA,0x64,0x49,0x23,0x49,0x97,0x6F,0xDF,0xFA,
+    0x25,0x6A,0x23,0x49,0xF5,0x3D,0x0F,0x23,0x65,0x72,0xC4,0x59,0xB5,0x8E,0x22,0xEA,
+    0x66,0x72,0xA3,0x59,0xAA,0xA8,0xF8,0x7E,0x06,0x6A,0x84,0x51,0xA8,0xA8,0xEA,0x5F,
+    0xC5,0x59,0x64,0x51,0x56,0xD4,0x7E,0x7B,0x64,0x51,0x23,0x49,0x80,0x08,0xFA,0x57,
+    0xC5,0x59,0x43,0x49,0xCA,0xAB,0xEB,0xFD,0x64,0x49,0x03,0x41,0xFA,0x5E,0x7C,0xDC,
+    0x23,0x41,0xA2,0x30,0xAA,0xAA,0xFA,0x7A,0x03,0x39,0xC2,0x38,0xA2,0xAE,0xB7,0x25,
+    0x03,0x39,0xC2,0x30,0x3B,0xBF,0x5F,0xD0,0xE3,0x38,0x61,0x28,0xB0,0xE8,0xA8,0xAA,
+    0xC2,0x30,0x61,0x28,0x2A,0xAB,0xEE,0xFA,0xC2,0x28,0x81,0x28,0xAA,0xFD,0xB5,0xDD,
+    0xA2,0x28,0x61,0x20,0x3F,0xBA,0xB8,0x2A,0xE3,0x30,0xA2,0x28,0x2F,0xAB,0xAB,0xFD,
+    0xE3,0x30,0xA2,0x28,0x7E,0x7A,0xBC,0xB6,0xC3,0x30,0x82,0x28,0xFF,0xEA,0x0A,0x80,
+    0xE3,0x30,0x82,0x20,0xDF,0xD5,0xFB,0xEF,0x44,0x41,0xA2,0x28,0xD5,0xFD,0xAD,0x2F,
+    0x44,0x41,0xA2,0x30,0xBD,0x2F,0x88,0x80,0x65,0x49,0x03,0x39,0xD7,0xFF,0xEF,0x3D,
+    0x65,0x49,0xC3,0x38,0xEA,0xE8,0xFA,0x58,0x24,0x41,0xC2,0x38,0x0A,0x2A,0x3E,0xFD,
+    0x23,0x41,0xE3,0x38,0xDF,0xE6,0xE8,0xA0,0x23,0x41,0xA2,0x30,0xD7,0xEF,0xAA,0x0A,
+    0x03,0x41,0xE2,0x38,0x7D,0x6D,0xD7,0x5C,0x44,0x49,0xE2,0x38,0xFF,0xCD,0xB5,0xB5,
+    0x85,0x51,0x23,0x41,0xFF,0xFD,0x8D,0xC9,0x84,0x51,0x03,0x39,0x57,0xFF,0xAB,0xA2,
+    0x43,0x49,0xE2,0x38,0x5F,0x7E,0x78,0x60,0xE2,0x30,0xA2,0x30,0x7F,0x7F,0xFC,0xD7,
+    0xE2,0x30,0xA1,0x28,0x3D,0xB5,0xBD,0xDF,0x03,0x39,0xA2,0x28,0x02,0x2F,0xBF,0x57,
+    0x24,0x39,0xC2,0x30,0xA0,0x82,0xEF,0xF5,0x44,0x41,0xE3,0x30,0x2D,0x2D,0xAD,0xFD,
+    0x45,0x39,0xC3,0x30,0xEC,0xFA,0x7A,0xDE,0x23,0x39,0xC2,0x30,0xF8,0xFB,0xAB,0xAD,
+    0xE3,0x30,0xA2,0x28,0x28,0xC2,0xB8,0xE0,0xE3,0x30,0xC2,0x28,0x08,0x02,0x20,0x0D,
+    0x24,0x39,0xC2,0x28,0xBF,0xFF,0xFF,0x54,0x03,0x31,0xA2,0x28,0x5A,0x54,0x76,0x7F,
+    0xE3,0x30,0xA2,0x28,0xE9,0xFB,0x7D,0x7E,0xC2,0x30,0x82,0x28,0x3E,0x3F,0xAB,0xC2,
+    0x03,0x39,0xC2,0x30,0xAF,0x8F,0xFB,0xDB,0x03,0x39,0xC2,0x30,0xAF,0x02,0xA2,0xF8,
+    0xE2,0x30,0x81,0x28,0xC2,0xC8,0x60,0xC8,0xE2,0x30,0xA1,0x28,0x2A,0xAD,0xEF,0xBD,
+    0xE2,0x30,0xC2,0x30,0x02,0xDB,0xEB,0x63,0x03,0x31,0xC2,0x30,0x28,0xA8,0xA0,0x8B,
+    0x03,0x31,0xC2,0x30,0x52,0x5E,0xBB,0xF7,0xE3,0x30,0xA2,0x28,0xA8,0xE2,0x80,0x7C,
+    0xE3,0x30,0xA2,0x28,0x62,0xFB,0x97,0xF7,0xE3,0x30,0xC2,0x28,0x5D,0x45,0x8D,0x25,
+    0xE2,0x30,0xC2,0x28,0x89,0xAB,0x7F,0x77,0xE2,0x30,0xA1,0x28,0x5A,0xDA,0xAA,0x20,
+    0xE3,0x30,0x81,0x20,0xDF,0xAE,0x8A,0x8A,0xE2,0x30,0xA2,0x28,0xFB,0xE9,0x8A,0x22,
+    0x03,0x31,0xC2,0x30,0x7F,0xF2,0xCA,0xFE,0x23,0x39,0xE3,0x30,0x7F,0xFE,0xDD,0x3F,
+    0x23,0x39,0xE3,0x30,0x5F,0xFD,0xEF,0x8B,0x23,0x39,0xC2,0x28,0xFB,0xD7,0xEF,0xB8,
+    0x03,0x39,0xC2,0x30,0x57,0x57,0x5C,0x78,0x23,0x39,0xC2,0x30,0xD7,0xD5,0xBF,0xBD,
+    0x03,0x39,0xC2,0x30,0x96,0xFF,0xAB,0xBE,0x03,0x39,0xC2,0x30,0xBF,0xBD,0xB7,0x17,
+    0x03,0x39,0xC2,0x30,0x3E,0xEE,0xB8,0xBA,0xA5,0x49,0x03,0x39,0xAB,0x2D,0x2D,0xBD,
+    0xC5,0x59,0x84,0x49,0xB9,0xFA,0xBB,0xF9,0x06,0x62,0x84,0x51,0xB5,0xAD,0x27,0x2D,
+    0xAD,0x93,0x26,0x62,0xB5,0x2D,0x2D,0x0B,0xF0,0xBC,0x0E,0xA4,0xA9,0x2F,0x0F,0x2A,
+    0xF0,0xC4,0xAF,0xB4,0x7B,0xEE,0xBE,0x78,0xF0,0xC4,0x8F,0xB4,0x7F,0x78,0xFA,0xBF,
+    0xD0,0xBC,0x6E,0xB4,0xF7,0xF7,0xEC,0xFE,0xD0,0xBC,0x8F,0xB4,0xFF,0xBB,0x3D,0xBD,
+    0xD0,0xBC,0x8F,0xB4,0xFB,0xBA,0xA8,0xA8,0xCF,0xBC,0x8F,0xB4,0xB6,0xEB,0xE2,0xAB,
+    0xAF,0xB4,0x2E,0xA4,0x78,0x68,0xA8,0xA0,0x6E,0xAC,0x2B,0x83,0x57,0x5E,0xFA,0xE8,
+    0x6C,0x8B,0xEA,0x7A,0x5F,0x57,0xAF,0xA8,0x2B,0x83,0xA9,0x72,0x5B,0x7A,0x78,0x68,
+    0xC9,0x72,0x47,0x62,0xF6,0x7F,0x3A,0xE0,0x87,0x6A,0x26,0x62,0xBE,0xAE,0xBA,0x48,
+    0xC9,0x72,0x46,0x62,0xAE,0x2E,0xAF,0x2D,0xE9,0x7A,0xA8,0x72,0x7D,0x7C,0x7E,0x7D,
+    0x09,0x7B,0xA8,0x72,0x5B,0x89,0x8B,0x8B,0xE9,0x7A,0x88,0x6A,0x7E,0xFE,0xE2,0x20,
+    0xC9,0x72,0x68,0x6A,0x77,0xEB,0xEE,0x80,0x88,0x6A,0xE6,0x59,0x7E,0x7A,0xEA,0x80,
+    0x27,0x62,0xC5,0x51,0x29,0xAF,0xDE,0xAC,0x4B,0x83,0xE6,0x51,0x0B,0x35,0xD5,0x55,
+    0x6B,0x83,0x06,0x5A,0x00,0x00,0x0A,0xB5,0x8C,0x8B,0x2A,0x7B,0xBA,0xAA,0xB8,0xF5,
+    0x02,0x49,0xE2,0x40,0x8B,0x8E,0x9E,0x37,0x22,0x49,0xC2,0x38,0xB7,0xDF,0xBB,0xFC,
+    0x03,0x49,0xE2,0x38,0xDA,0xFC,0x7A,0xE2,0x03,0x49,0xE2,0x38,0xAA,0xFA,0xBF,0x2E,
+    0x23,0x41,0xE2,0x40,0xCA,0x8A,0x9C,0x3C,0x23,0x49,0xE2,0x40,0x07,0x88,0xBA,0xE8,
+    0x23,0x49,0xE2,0x40,0xA8,0xA8,0xB8,0xD7,0x23,0x49,0x02,0x41,0x75,0x54,0x78,0xD8,
+    0x64,0x49,0x02,0x41,0xDE,0xBB,0xB3,0xEB,0x43,0x49,0xE2,0x40,0x96,0xFA,0xE2,0xA8,
+    0x23,0x49,0xE2,0x40,0x2C,0xDE,0xAE,0x3E,0x23,0x41,0xE2,0x40,0xAE,0xFA,0xF3,0x56,
+    0x23,0x49,0xC2,0x38,0xAA,0xA2,0xB5,0x37,0x23,0x49,0xE2,0x40,0x72,0x40,0xA8,0xEE,
+    0x23,0x49,0xE2,0x40,0x17,0xBB,0xAB,0xB3,0x23,0x49,0xE2,0x40,0xA6,0xAF,0xA1,0x80,
+    0xA5,0x59,0x02,0x41,0x2F,0x2D,0xBD,0xF7,0xC5,0x61,0x23,0x49,0xE0,0xFA,0x7F,0x55,
+    0x44,0x49,0xE3,0x40,0xE6,0xBC,0xFA,0xE6,0x03,0x49,0xC2,0x40,0x2A,0xA8,0xFA,0x5F,
+    0xE2,0x40,0xC2,0x38,0xA8,0x26,0x1F,0x3B,0x03,0x49,0xC2,0x40,0xBF,0xAE,0x7A,0xFA,
+    0xA5,0x59,0x03,0x49,0x35,0x25,0x35,0xA5,0x06,0x62,0xA4,0x59,0xAF,0xEB,0x89,0x8D,
+    0x06,0x62,0xA4,0x59,0xEF,0xFF,0xDF,0x5C,0xE5,0x61,0x84,0x51,0x7A,0x7E,0x6B,0xEA,
+    0xC5,0x59,0x63,0x51,0xD7,0xBB,0x03,0x09,0xC5,0x59,0x84,0x51,0xD7,0xBE,0xBF,0xFC,
+    0xC5,0x59,0x64,0x51,0xE8,0xD8,0xFF,0xFE,0x84,0x51,0x44,0x49,0xF8,0xEE,0xBF,0xBE,
+    0xA5,0x51,0x64,0x49,0x5D,0x7D,0xA3,0x7B,0xA4,0x49,0x44,0x49,0xEF,0x7F,0x5F,0xF9,
+    0x64,0x49,0x23,0x41,0xA0,0x80,0x22,0x0E,0x64,0x51,0x23,0x49,0x1C,0x3F,0x2A,0x0B,
+    0x88,0x7A,0xC5,0x59,0xFD,0xAF,0x29,0x35,0x46,0x72,0xC3,0x61,0xCA,0x6A,0xC0,0xE0,
+    0x05,0x6A,0xA3,0x59,0x7E,0xFA,0xE8,0xE8,0x84,0x59,0xE2,0x38,0x00,0xA0,0xF0,0x70,
+    0x64,0x51,0xA1,0x30,0x80,0xFA,0xFA,0x57,0x44,0x49,0xA2,0x30,0x2A,0xAF,0x35,0xDF,
+    0x64,0x49,0x23,0x41,0x20,0x0A,0x03,0xBD,0x84,0x49,0x03,0x39,0x5B,0x7A,0xF8,0x7A,
+    0x03,0x39,0xA2,0x30,0xE8,0xA8,0x2A,0x00,0x23,0x41,0xC2,0x30,0xF5,0xFB,0x82,0x02,
+    0x03,0x39,0xC2,0x30,0xF2,0xF0,0xF7,0xE6,0xE3,0x30,0xA2,0x30,0xFE,0xFE,0xFC,0xCA,
+    0xC2,0x30,0x82,0x28,0x5C,0xE8,0xA2,0x22,0xC2,0x28,0x81,0x20,0xFB,0xF2,0xEA,0xF8,
+    0xC2,0x28,0x81,0x20,0xB5,0x97,0xA5,0xAD,0xA2,0x30,0xC3,0x28,0xFF,0xD7,0x55,0xD7,
+    0xE3,0x28,0xA2,0x28,0xBF,0x1D,0x97,0xFF,0xE3,0x30,0xA2,0x28,0xFA,0xFE,0x57,0xDD,
+    0xE3,0x30,0xA2,0x28,0x77,0xA7,0xB5,0xBD,0x44,0x41,0xE3,0x30,0x29,0x0B,0x02,0x03,
+    0x85,0x51,0x03,0x39,0x5F,0xBA,0x2A,0x2A,0x64,0x49,0x23,0x41,0x15,0x2F,0x8A,0xA0,
+    0x65,0x49,0xC2,0x38,0x7A,0xFE,0xFE,0x68,0x03,0x39,0xC2,0x38,0xF9,0xE1,0xAA,0xAA,
+    0x23,0x41,0xE3,0x38,0xA3,0xBF,0xBF,0xFF,0x23,0x41,0xE2,0x38,0xEA,0xFC,0x76,0x76,
+    0x03,0x41,0xE2,0x38,0x0A,0x09,0xAB,0x83,0x23,0x49,0xC2,0x40,0x2E,0x3A,0xFE,0x5F,
+    0x65,0x49,0xE2,0x40,0x0B,0xBB,0xAF,0x5D,0x64,0x49,0x03,0x41,0x00,0x02,0x2D,0xB5,
+    0x64,0x49,0x03,0x41,0x48,0x40,0xE0,0x6B,0x23,0x41,0xA1,0x30,0xD5,0x5F,0x7E,0xE8,
+    0xC2,0x30,0x61,0x28,0xE8,0x6A,0xA2,0xA2,0xC2,0x30,0x81,0x28,0xF5,0xFD,0xAA,0x0A,
+    0xE3,0x38,0x61,0x28,0x0B,0x2F,0xAA,0xA2,0x03,0x39,0xA1,0x28,0x80,0x82,0xAA,0xAB,
+    0x03,0x31,0xA2,0x30,0xEA,0x8A,0x0A,0x8A,0x03,0x31,0xA2,0x28,0x8A,0xBE,0xFA,0x7E,
+    0xE3,0x30,0x81,0x20,0xE2,0xEF,0xF7,0x7F,0xC2,0x30,0x81,0x28,0x0A,0x3B,0xAF,0xCD,
+    0xE3,0x30,0xA2,0x28,0xEA,0x8B,0x89,0x5D,0xE3,0x30,0xA2,0x28,0xFB,0xFF,0xFF,0xDA,
+    0xC2,0x30,0xA2,0x28,0xEE,0x7D,0xEA,0xE2,0xE2,0x30,0xA2,0x28,0x6B,0xF9,0x57,0x55,
+    0xE2,0x30,0xA2,0x28,0x02,0xAB,0xC9,0x89,0x03,0x39,0xA2,0x28,0xB8,0xCB,0xBF,0x7D,
+    0xE3,0x30,0xA2,0x28,0xAB,0x2B,0xEF,0xFD,0xE2,0x30,0xA2,0x28,0xEE,0xF4,0xEA,0x2B,
+    0xE2,0x30,0xA2,0x28,0xEB,0xE8,0xBA,0x7A,0xE2,0x30,0xC2,0x28,0x09,0x09,0x87,0x7D,
+    0xE2,0x30,0xC2,0x28,0x28,0x72,0x7F,0xE5,0xE2,0x30,0xA2,0x28,0xBC,0x82,0xA2,0xAE,
+    0xE2,0x30,0xC2,0x28,0xF5,0x77,0xA0,0x3B,0xE3,0x30,0xA1,0x28,0x0D,0xCD,0xFF,0x5B,
+    0xE2,0x30,0xA2,0x28,0xBA,0xBF,0xAF,0xBB,0x03,0x31,0xC2,0x28,0x7E,0x7F,0xF7,0xEB,
+    0x03,0x31,0xA1,0x28,0x2F,0xAF,0xA7,0x1E,0x03,0x39,0xE2,0x30,0xB7,0xB2,0x5E,0xFF,
+    0xE2,0x30,0xA2,0x28,0xB0,0xF0,0xF2,0xF8,0x03,0x31,0xC2,0x28,0x0B,0x3D,0x95,0xD5,
+    0x03,0x31,0xC2,0x30,0x02,0xBB,0xF7,0x7D,0x23,0x39,0xE3,0x30,0xF8,0xFE,0xE5,0xF5,
+    0x23,0x39,0xE3,0x38,0x5E,0xF3,0x7D,0x55,0x03,0x39,0xC2,0x30,0x87,0xAE,0xBE,0x3E,
+    0x03,0x39,0xE3,0x30,0xBF,0x21,0x21,0x31,0x03,0x39,0xA1,0x28,0xFE,0x7C,0xD8,0xB8,
+    0x03,0x39,0xC2,0x30,0xB3,0xAF,0xB9,0xD5,0x44,0x49,0xC2,0x30,0x29,0x07,0x2D,0xBD,
+    0xA4,0x51,0x23,0x41,0x22,0xAF,0xBF,0x3D,0x6B,0x8B,0xA4,0x51,0xF5,0xA5,0x25,0x2D,
+    0xF0,0xC4,0x4B,0x8B,0xBD,0x2F,0x02,0x02,0x31,0xCD,0xB0,0xB4,0xBD,0xAB,0x82,0x02,
+    0x31,0xC5,0xAF,0xBC,0xDF,0xF8,0xA8,0x80,0x10,0xC5,0x8E,0xB4,0x57,0x77,0xFA,0x80,
+    0xD0,0xBC,0x4E,0xAC,0xBA,0xFE,0xFE,0x78,0xCF,0xB4,0x6E,0xB4,0xDF,0xFD,0xED,0x75,
+    0xAF,0xB4,0x6E,0xB4,0x3C,0xBA,0x7A,0x7D,0xCF,0xBC,0x4E,0xAC,0xA2,0xEA,0xBE,0xDF,
+    0xAF,0xB4,0x4E,0xAC,0xF8,0x7E,0x7F,0x57,0x6E,0xAC,0xCC,0x9B,0x58,0xEE,0xAA,0xAA,
+    0x4E,0xA4,0x2B,0x83,0x77,0x7F,0xA8,0x80,0xCC,0x9B,0xA9,0x72,0x7F,0x7E,0x7A,0xE8,
+    0xEA,0x7A,0x68,0x6A,0xFE,0xFF,0xDA,0xF0,0xA8,0x72,0x47,0x62,0x5E,0xFA,0xCA,0x20,
+    0xC8,0x72,0x46,0x62,0xA5,0x2B,0xEA,0xFA,0xE9,0x7A,0x87,0x6A,0xEB,0x8F,0xAD,0x2A,
+    0x09,0x7B,0xC9,0x72,0xA9,0xA9,0x3B,0x09,0x2A,0x83,0xC9,0x72,0x7B,0xFB,0xB3,0xCB,
+    0x0A,0x7B,0x88,0x6A,0xBF,0xEA,0xDA,0xFC,0xC9,0x72,0x68,0x62,0x7C,0xEA,0x8A,0xB8,
+    0xA9,0x6A,0x06,0x5A,0x5F,0xDE,0xF8,0xC8,0x47,0x62,0xC5,0x51,0x7F,0x72,0xF0,0xE0,
+    0x88,0x6A,0xA5,0x49,0x37,0x57,0x57,0x5F,0xEA,0x72,0x64,0x41,0x02,0xAF,0xFD,0x55,
+    0x43,0x49,0xE2,0x38,0xF7,0xAE,0xE8,0xEB,0x23,0x49,0xE2,0x38,0x7E,0xEE,0xEB,0xFA,
+    0x23,0x49,0xE2,0x40,0xAB,0x09,0xC5,0xF7,0x23,0x49,0xC1,0x38,0xA8,0xE8,0xBA,0xBD,
+    0x23,0x49,0x02,0x41,0x1F,0xA9,0xDF,0xDE,0x23,0x49,0x02,0x41,0xE0,0xE0,0xD8,0x57,
+    0x23,0x49,0xE2,0x40,0xD7,0xBD,0x80,0x00,0x43,0x49,0x02,0x41,0x5F,0x69,0xE3,0xFB,
+    0x43,0x49,0x02,0x41,0xA3,0xFE,0xEB,0xEB,0x23,0x49,0x02,0x41,0xAA,0x9A,0x2A,0xB7,
+    0x43,0x49,0xE2,0x40,0xBB,0x2E,0xDB,0x5F,0x23,0x41,0xE2,0x40,0x5A,0xDE,0x57,0x77,
+    0x23,0x49,0xC2,0x40,0xF5,0xAE,0xAB,0xAB,0x23,0x49,0xC2,0x38,0xCA,0x2B,0xE8,0x5A,
+    0x23,0x49,0xE2,0x40,0x3B,0xAB,0xAB,0xED,0x23,0x49,0xE2,0x40,0xAE,0xCA,0xCA,0x4F,
+    0x03,0x49,0xE1,0x38,0x23,0xA9,0xE7,0x6F,0x03,0x41,0xC2,0x40,0x02,0x20,0x32,0x02,
+    0x23,0x49,0xC2,0x38,0xCA,0x6A,0x68,0xE8,0x03,0x41,0xA1,0x38,0xF2,0xA6,0xAD,0x8A,
+    0x03,0x49,0xC2,0x38,0xDF,0xEA,0x82,0xBA,0x23,0x49,0xE3,0x40,0xFA,0xEA,0xBD,0xBD,
+    0xA5,0x59,0x03,0x49,0x2D,0x35,0x35,0x25,0x46,0x6A,0xC5,0x59,0x65,0xAF,0x8F,0x0F,
+    0x26,0x6A,0xC4,0x59,0xDE,0xFB,0x7B,0xFC,0xE5,0x59,0x84,0x51,0x6A,0xEA,0xAB,0xAB,
+    0xE5,0x61,0x84,0x51,0xFD,0xF7,0x32,0x2A,0xA4,0x59,0x64,0x49,0xFE,0xFF,0x08,0x00,
+    0xA4,0x51,0x23,0x49,0x8A,0xEA,0xFE,0x7F,0x64,0x49,0x23,0x41,0xC0,0x60,0xAA,0xBE,
+    0x85,0x51,0x64,0x49,0x4F,0x95,0x99,0x59,0x84,0x49,0x44,0x49,0xC5,0x5E,0x5A,0xF7,
+    0x64,0x49,0x23,0x41,0xAA,0x6B,0x2B,0xA8,0x64,0x51,0x03,0x41,0x8B,0xBE,0xFC,0xDE,
+    0x47,0x72,0x44,0x49,0x0F,0xAD,0xB9,0xB5,0x88,0x7A,0xE5,0x61,0xE8,0xF7,0x77,0xDD,
+    0x05,0x62,0x43,0x49,0xA0,0xE0,0x68,0x5E,0x63,0x51,0x41,0x28,0xE0,0xF8,0x7A,0x7E,
+    0xC2,0x38,0x41,0x20,0x22,0xAA,0xFF,0x7D,0xE2,0x38,0x61,0x28,0xB0,0xF2,0xAB,0xFD,
+    0x44,0x41,0xC2,0x30,0x0B,0xBD,0xFD,0xF5,0x43,0x41,0xC2,0x30,0x62,0x7F,0xFF,0x7F,
+    0x44,0x41,0xE2,0x30,0xE9,0xAF,0x39,0xCF,0x24,0x41,0xE3,0x30,0x8B,0x8B,0xFE,0xFE,
+    0x03,0x39,0xE3,0x30,0xFC,0xA0,0x9E,0x57,0x03,0x31,0xC3,0x30,0xA7,0xF6,0x7C,0xF0,
+    0xC2,0x28,0xA2,0x28,0xBE,0xFE,0xBA,0x5D,0xC2,0x28,0x81,0x20,0xF0,0x0B,0x29,0xBD,
+    0xC2,0x28,0x81,0x20,0xAA,0xAA,0xBE,0xFF,0xC3,0x28,0xA2,0x28,0x0B,0x09,0x03,0xA2,
+    0xC2,0x28,0xA2,0x28,0x90,0x7C,0x68,0xC8,0xC3,0x30,0x82,0x20,0xA2,0xEB,0xAF,0x3F,
+    0xE3,0x30,0xA2,0x28,0x3D,0xBB,0x3A,0x3F,0x65,0x49,0x03,0x39,0xA9,0x29,0xAD,0x2D,
+    0x85,0x51,0x03,0x39,0x8A,0xBA,0xFE,0x5E,0x44,0x49,0xC2,0x30,0x00,0xA0,0xAA,0xFF,
+    0x44,0x49,0xC2,0x30,0x70,0xE8,0xAF,0x55,0x23,0x41,0xC3,0x30,0xB2,0xAA,0x8A,0x6F,
+    0x03,0x41,0xE3,0x38,0xF8,0x5A,0x5B,0x55,0x23,0x41,0xC2,0x38,0xFF,0xF5,0xD7,0x56,
+    0x23,0x41,0xE2,0x38,0xEA,0xE9,0xE9,0xAE,0x03,0x41,0xC2,0x38,0x5F,0xFE,0xEC,0xE0,
+    0xE3,0x40,0xC2,0x38,0x69,0xDA,0xBA,0xBE,0x24,0x49,0xC2,0x38,0x0B,0x27,0xAF,0xAB,
+    0x44,0x49,0xE2,0x38,0xC2,0xEB,0x77,0x7F,0x23,0x41,0xC2,0x38,0xE2,0xE0,0x6A,0xAD,
+    0xE2,0x38,0xA1,0x28,0xFA,0x7C,0xEA,0xC0,0xC2,0x30,0xA2,0x28,0xEE,0x75,0x4F,0xFA,
+    0xE3,0x30,0x81,0x28,0xFA,0x6A,0x70,0xEA,0xE3,0x30,0x82,0x28,0x29,0xAB,0xBB,0xD7,
+    0xE3,0x30,0x81,0x20,0xA0,0xA2,0xD6,0x5D,0xC2,0x28,0x81,0x28,0xA0,0x80,0x3E,0xBD,
+    0xE3,0x30,0xA2,0x28,0x7D,0xF7,0xFF,0x07,0xC2,0x30,0x81,0x28,0xF5,0xDD,0xBF,0x00,
+    0xE3,0x30,0x81,0x28,0x7D,0xAF,0xAB,0x82,0xE3,0x30,0xA2,0x28,0x55,0x57,0xFF,0xAA,
+    0xE3,0x30,0xA2,0x28,0xFF,0xFD,0x5F,0xE0,0xC3,0x30,0x81,0x28,0x6E,0x75,0x57,0x78,
+    0xE2,0x30,0x82,0x28,0x89,0xFD,0x75,0x55,0xC2,0x28,0x81,0x28,0xEA,0x7B,0xBE,0x8B,
+    0xC2,0x28,0xA2,0x28,0x35,0x55,0x55,0x7B,0xC2,0x30,0xA2,0x28,0x2D,0x25,0xED,0xFF,
+    0xE2,0x30,0xC2,0x28,0xEB,0xBF,0xFD,0xA3,0x23,0x31,0xC2,0x28,0x7D,0x7F,0x5B,0xEB,
+    0xE2,0x30,0xA2,0x28,0x2F,0xFF,0xD7,0xEA,0xE3,0x30,0xA2,0x28,0xAE,0xAF,0xAD,0xAA,
+    0xE3,0x30,0xA2,0x28,0xAE,0x97,0xF7,0xEA,0x03,0x31,0xC2,0x28,0xFB,0xAF,0x89,0xAF,
+    0x03,0x31,0xC2,0x30,0xDF,0xEA,0xC8,0xA2,0x03,0x31,0xC2,0x28,0xE3,0xEF,0xBF,0xBF,
+    0x24,0x39,0xC2,0x30,0xB7,0x0D,0xBE,0xBF,0x44,0x41,0xE3,0x30,0xBD,0x27,0xAF,0xAB,
+    0x23,0x39,0xC2,0x30,0x5E,0x7A,0x68,0xFC,0x03,0x39,0xA1,0x28,0xFD,0xFF,0xAD,0x0F,
+    0x03,0x39,0xC2,0x30,0xFB,0xBB,0xEF,0xEE,0x03,0x39,0xC2,0x30,0xFF,0x7A,0x7A,0xBB,
+    0xE3,0x30,0xC2,0x30,0xFB,0xAB,0x2F,0xE7,0xE3,0x38,0x03,0x31,0xC2,0x8A,0xE2,0xEA,
+    0x03,0x39,0xC3,0x30,0xAA,0x7B,0x28,0x2A,0x23,0x39,0xE2,0x38,0x55,0x5D,0x7F,0x7C,
+    0x03,0x39,0xC2,0x30,0xFF,0xFB,0x95,0xAB,0x44,0x49,0xE3,0x38,0xBD,0xBF,0xBB,0x2B,
+    0x26,0x62,0x44,0x49,0xFD,0xBD,0xBD,0x29,0xEC,0x9B,0xC4,0x59,0x2D,0x2D,0x2F,0x2F,
+    0x31,0xC5,0x8E,0xB4,0x2B,0x0B,0x8D,0x05,0x31,0xCD,0x10,0xC5,0xAA,0xBF,0xFC,0xC3,
+    0x31,0xCD,0x10,0xC5,0x40,0xA9,0x82,0x2B,0x31,0xCD,0x10,0xC5,0xDE,0x6A,0xF0,0x60,
+    0x30,0xC5,0xAF,0xB4,0x5E,0xFA,0xAA,0x88,0xEF,0xC4,0x6E,0xAC,0x5D,0x7A,0xE8,0x00,
+    0xEF,0xBC,0x4D,0xAC,0x7F,0x5F,0x7F,0xE8,0x8F,0xB4,0x4D,0xAC,0xBF,0xAD,0x55,0x55,
+    0x8F,0xB4,0x2D,0xAC,0xFF,0x78,0xFF,0xDF,0x8F,0xB4,0x4E,0xAC,0x55,0xF9,0xBA,0xB8,
+    0x8F,0xB4,0xEC,0x9B,0x7E,0x72,0x68,0xFA,0x0D,0x9C,0x0A,0x83,0x78,0xE0,0xE8,0xA0,
+    0x6B,0x8B,0xA9,0x72,0x7F,0x7A,0xEA,0xA0,0xE9,0x7A,0x67,0x6A,0x77,0xDA,0xA8,0xE8,
+    0xC9,0x72,0x66,0x6A,0xBD,0xAF,0xAA,0x22,0xE9,0x72,0xA8,0x72,0xBD,0xAB,0x0F,0x35,
+    0x0A,0x7B,0xC8,0x72,0x2D,0xBF,0x2D,0xAF,0x4B,0x83,0xE9,0x7A,0x3D,0xBF,0xAB,0xAF,
+    0x4B,0x83,0xE9,0x7A,0x5E,0x7E,0xDE,0xFC,0x2A,0x83,0x89,0x6A,0x5A,0xFA,0xA8,0xA0,
+    0xEA,0x7A,0x88,0x6A,0x55,0x76,0xBC,0xB8,0xA9,0x6A,0x06,0x5A,0x5E,0xF2,0xA8,0x88,
+    0x47,0x62,0xA5,0x49,0x5E,0xEF,0xEA,0xE0,0xE6,0x51,0x24,0x39,0xFF,0x6E,0xEA,0x60,
+    0x23,0x49,0xC2,0x38,0xAA,0x20,0xAB,0xAD,0x23,0x49,0xE2,0x40,0x8E,0xAE,0x96,0x57,
+    0x23,0x49,0xC1,0x38,0x68,0x72,0xDA,0xFE,0x44,0x49,0xE2,0x40,0x55,0x75,0xFF,0x37,
+    0x23,0x49,0xE2,0x40,0x2F,0xE1,0xE2,0xF8,0x23,0x49,0xE2,0x40,0xDE,0x55,0x55,0x1D,
+    0x23,0x49,0xE2,0x40,0x23,0x0B,0x2B,0xAD,0x23,0x49,0xE2,0x40,0xCA,0x9A,0xFB,0xFB,
+    0x43,0x49,0x02,0x41,0x2B,0xE5,0xD5,0x7E,0x22,0x41,0xC2,0x38,0xA0,0x28,0xA8,0x7E,
+    0x23,0x49,0xC2,0x38,0xDF,0xD6,0xDC,0xAF,0x02,0x41,0xE2,0x38,0xAD,0x02,0x02,0x02,
+    0x03,0x41,0xE2,0x40,0x43,0x76,0xD7,0xE9,0x03,0x41,0xC1,0x38,0xFB,0xED,0xCF,0x80,
+    0x02,0x49,0xE2,0x38,0x2A,0xAB,0xBD,0x75,0x02,0x41,0xE1,0x40,0x73,0x0A,0x80,0xC0,
+    0x02,0x41,0xC1,0x38,0xCA,0x26,0x2F,0x8B,0x22,0x41,0xE2,0x38,0xFB,0xEB,0xB7,0x95,
+    0x02,0x41,0xC2,0x38,0xE0,0x00,0xAE,0x5E,0x02,0x41,0xC2,0x38,0xEB,0xE8,0xD8,0xFA,
+    0x03,0x49,0xE2,0x40,0x7F,0x55,0x95,0x97,0x03,0x49,0xC2,0x40,0x0A,0xE7,0xA8,0xFE,
+    0xE5,0x61,0x03,0x49,0xA5,0x35,0xB5,0xB5,0x26,0x6A,0xC5,0x59,0x0B,0x29,0x82,0x80,
+    0x26,0x6A,0xC5,0x59,0xE8,0xFA,0x7E,0xFF,0xE5,0x61,0xA4,0x59,0xEE,0x8C,0xC0,0x02,
+    0xE5,0x61,0xA4,0x51,0x2B,0xBF,0xDA,0x60,0xE5,0x59,0x43,0x49,0xFA,0xE8,0x6A,0xEA,
+    0x64,0x49,0x23,0x41,0x78,0xEE,0xF8,0xCA,0x44,0x49,0xE2,0x38,0x2A,0x26,0xAA,0xAA,
+    0x64,0x49,0x02,0x39,0xA8,0xAA,0xFE,0xD7,0x65,0x49,0x24,0x41,0xB5,0xB5,0xE5,0xF7,
+    0x64,0x49,0x03,0x39,0x28,0xBB,0xDF,0xDE,0x64,0x49,0x03,0x41,0x7A,0x7C,0xD2,0xE2,
+    0xA5,0x59,0x03,0x41,0x2D,0x95,0x95,0x55,0x06,0x6A,0x84,0x51,0x2A,0x62,0xEF,0xFD,
+    0xC5,0x59,0xE2,0x40,0xF8,0x7E,0x5A,0xAA,0x64,0x49,0x41,0x28,0x7F,0x5F,0x7F,0xA8,
+    0xE3,0x38,0x41,0x28,0xDD,0x7D,0xFB,0xC8,0xA2,0x30,0x41,0x20,0x2B,0xA9,0x0A,0x22,
+    0x03,0x39,0xA1,0x28,0x2D,0x29,0xFD,0xDD,0x22,0x39,0xC2,0x30,0x57,0xF6,0xDF,0xF5,
+    0x43,0x41,0xE2,0x30,0xAF,0xA9,0x8B,0xFF,0x03,0x39,0xA2,0x28,0x88,0xEE,0xBE,0xF5,
+    0xE3,0x30,0xA2,0x28,0x3A,0xB6,0xD7,0xD5,0xE3,0x30,0x61,0x20,0x80,0xA8,0x6A,0x5A,
+    0xA2,0x28,0x61,0x20,0xBE,0xFE,0xDF,0x57,0xA2,0x28,0x61,0x20,0xA3,0xAB,0xBF,0xE9,
+    0xA2,0x28,0x82,0x20,0xA4,0x35,0xEB,0x09,0xC2,0x28,0x82,0x20,0x02,0x02,0x0B,0x0F,
+    0xE2,0x28,0xA2,0x28,0xF8,0x6A,0x7A,0x7F,0xC2,0x28,0x82,0x28,0x2F,0xAF,0xEA,0x22,
+    0x03,0x39,0xA2,0x28,0xAD,0x27,0x2F,0x3F,0x44,0x41,0x03,0x39,0x25,0xAD,0xF3,0xCB,
+    0x44,0x41,0xA2,0x28,0xE0,0xFE,0x7E,0x7F,0xC2,0x30,0x61,0x20,0x80,0xFE,0x5A,0x5F,
+    0xC2,0x30,0x61,0x20,0xA2,0xBE,0xFF,0xF5,0xE2,0x38,0x81,0x28,0xA3,0x3B,0xBD,0xFF,
+    0xE2,0x38,0x81,0x28,0x2A,0xAA,0xEF,0x75,0xE3,0x38,0x81,0x28,0x08,0xAA,0xBE,0xD7,
+    0x23,0x41,0xA2,0x30,0x22,0xBB,0xAD,0xAD,0x23,0x41,0xE3,0x38,0xF8,0xAA,0x9B,0x5F,
+    0x23,0x41,0xC3,0x38,0x7F,0xFA,0x3E,0xBF,0x23,0x41,0xE3,0x38,0x0D,0xED,0x9E,0xDF,
+    0x23,0x41,0xE2,0x38,0xFA,0x6B,0xEA,0xEA,0x24,0x41,0xE2,0x38,0xED,0x2F,0xBD,0x7D,
+    0x23,0x41,0xC2,0x30,0xFA,0xEA,0xF8,0xFB,0xE2,0x38,0xA2,0x28,0xFE,0x7A,0xF8,0xFE,
+    0xC2,0x30,0xA2,0x28,0xFD,0xFD,0xBA,0x20,0xC3,0x38,0x61,0x20,0x5E,0xFE,0xFE,0xF8,
+    0xA2,0x28,0x61,0x20,0xFA,0xEE,0xBE,0x20,0xC2,0x28,0x81,0x28,0xB5,0xA5,0xE9,0x7C,
+    0xC3,0x28,0x82,0x28,0x0B,0xAF,0xD5,0x75,0xE3,0x30,0x81,0x28,0x0A,0x2B,0xAF,0x75,
+    0xE3,0x30,0xA2,0x28,0x02,0x00,0xAF,0x75,0xE3,0x30,0xA2,0x28,0xA8,0x2A,0x2E,0x3F,
+    0x03,0x31,0xC2,0x30,0x7A,0x7A,0xFE,0x00,0x03,0x39,0xA2,0x28,0x7E,0xEA,0xFA,0xE8,
+    0xC2,0x30,0x82,0x28,0x56,0xBA,0x8A,0x00,0xC1,0x28,0x82,0x28,0xBB,0xFE,0xFA,0x3E,
+    0xE3,0x30,0xA2,0x28,0xBF,0xD7,0x7B,0xBF,0xE3,0x30,0xA2,0x28,0xFA,0x0A,0x3A,0xAA,
+    0x03,0x31,0xC2,0x30,0x8A,0x82,0xBB,0x17,0x03,0x31,0xC2,0x28,0xA2,0xF0,0xFE,0xD6,
+    0xE2,0x30,0xC2,0x28,0xE8,0x8A,0x2A,0x20,0x03,0x31,0xE2,0x30,0x7C,0x40,0x0A,0x0B,
+    0x03,0x31,0xC2,0x30,0xF7,0xA7,0xBF,0x0E,0xE2,0x30,0xC2,0x28,0x3F,0x3F,0xB5,0x95,
+    0x03,0x31,0xC2,0x28,0x3A,0xDA,0xDC,0xAE,0x03,0x31,0xC2,0x28,0xDA,0xD7,0xEE,0xEB,
+    0x03,0x39,0xC2,0x30,0x0A,0x3E,0x9D,0xF5,0x24,0x39,0xE3,0x30,0x83,0xAA,0xFA,0x59,
+    0x03,0x39,0xC2,0x30,0xA8,0x80,0x6C,0x7E,0x23,0x39,0xA2,0x28,0xB7,0xA7,0x8A,0x2A,
+    0x44,0x41,0xC2,0x30,0x77,0xFF,0xFA,0xF3,0x23,0x39,0xE2,0x30,0xB5,0x5D,0x6F,0xAB,
+    0x23,0x39,0xC2,0x30,0xEF,0x7E,0x7A,0xA0,0x03,0x39,0xC3,0x30,0x8A,0xFF,0xFF,0x3E,
+    0x23,0x41,0xC2,0x30,0x8B,0xA1,0xBB,0xD7,0xE2,0x40,0x03,0x39,0xB7,0xD7,0x5F,0xDE,
+    0x43,0x41,0xE3,0x38,0xFD,0x3F,0xED,0xF7,0x85,0x49,0x03,0x39,0xBF,0xBF,0x3D,0x0F,
+    0x47,0x6A,0x65,0x49,0x2D,0xAD,0x2F,0x2F,0x2D,0xA4,0x67,0x6A,0x2D,0x2D,0x2F,0x0B,
+    0x10,0xC5,0x8E,0xB4,0x0D,0x8B,0x89,0xAD,0x31,0xC5,0xF0,0xC4,0x83,0xED,0xF5,0xFF,
+    0x10,0xC5,0xCF,0xBC,0x00,0x08,0x0F,0x97,0x31,0xC5,0xCF,0xBC,0x0A,0xBB,0xFE,0xB6,
+    0x30,0xC5,0xF0,0xBC,0xEE,0x5A,0x5F,0x7F,0x30,0xC5,0xF0,0xBC,0xBF,0x79,0xF2,0xEE,
+    0x10,0xC5,0xAF,0xB4,0x60,0x80,0x82,0x88,0x10,0xC5,0x4D,0xAC,0x7F,0xFA,0xA8,0x22,
+    0xF0,0xC4,0x2D,0xA4,0xD7,0xD7,0xEA,0xE0,0xAF,0xBC,0x4E,0xAC,0xAE,0xFD,0xDD,0x9C,
+    0x8F,0xB4,0x4E,0xAC,0x5E,0xBE,0x83,0xB7,0x6F,0xAC,0xCD,0x9B,0x5A,0x78,0xEA,0xE8,
+    0xCC,0x9B,0x6B,0x8B,0x5E,0x5A,0xFA,0xE0,0xAB,0x93,0xC9,0x72,0x57,0x7E,0xEA,0x80,
+    0x4A,0x83,0xA8,0x72,0x75,0xD5,0xD6,0xF8,0xE9,0x7A,0x88,0x6A,0x36,0x2D,0x32,0x22,
+    0x2A,0x83,0xC9,0x72,0x7E,0xEE,0x3B,0xFF,0x4A,0x83,0xE8,0x7A,0xBD,0x2F,0x2F,0x17,
+    0x6B,0x83,0x0A,0x83,0xEE,0xEE,0x2F,0xB6,0x4B,0x83,0xE9,0x7A,0xBD,0xFA,0xB8,0x08,
+    0x4B,0x83,0xC9,0x72,0x5F,0x6B,0xEA,0x20,0x2B,0x83,0x88,0x6A,0x57,0x7F,0x7F,0xF8,
+    0xC9,0x72,0x27,0x5A,0x5A,0x5E,0xAA,0xE8,0x27,0x5A,0x44,0x41,0x78,0xE0,0xA0,0x80,
+    0x23,0x49,0xE2,0x38,0xB7,0xF7,0xA9,0xC1,0x03,0x49,0xE2,0x38,0xB4,0x27,0x2D,0x3F,
+    0x02,0x49,0xE2,0x40,0x5A,0xC8,0x6C,0xFB,0x23,0x49,0xE2,0x40,0x2B,0x32,0x77,0xBF,
+    0x02,0x49,0xE2,0x40,0x8F,0xAC,0xAD,0x0A,0x23,0x49,0xE2,0x40,0xAD,0xFB,0xE8,0x5A,
+    0x23,0x49,0xE2,0x40,0xBB,0xAA,0x38,0x77,0x43,0x49,0x03,0x41,0x57,0x7E,0x7D,0xD5,
+    0x23,0x49,0xE2,0x40,0xDA,0x7F,0xAF,0x0B,0x02,0x41,0xC1,0x38,0xFA,0x8B,0xAB,0xEA,
+    0x23,0x41,0xC2,0x38,0xB0,0xEE,0xAB,0xA9,0x44,0x41,0xE2,0x40,0xF7,0xBF,0xFD,0xF5,
+    0x23,0x41,0xC2,0x40,0xAF,0xBA,0xFC,0x7E,0x23,0x49,0xE2,0x38,0xEA,0xEA,0xEE,0xED,
+    0x03,0x41,0xE2,0x38,0x99,0x0B,0x01,0x01,0x23,0x41,0xE2,0x40,0xDB,0x57,0xD7,0x97,
+    0x23,0x41,0xC2,0x38,0xDF,0x9E,0xBA,0x2A,0x23,0x41,0xE2,0x40,0xD5,0xFF,0x2F,0xAB,
+    0x03,0x41,0xC2,0x38,0xFF,0xB8,0x20,0xA0,0x23,0x49,0xE2,0x40,0xDF,0xFB,0xFA,0xA9,
+    0x03,0x49,0xE2,0x38,0xA8,0x22,0x8A,0xA2,0x03,0x49,0xE2,0x40,0x7F,0xE8,0xF8,0x5A,
+    0xA4,0x59,0xE2,0x40,0x3D,0xBD,0xA5,0x35,0x46,0x6A,0xE5,0x61,0xBE,0xFB,0xA1,0x09,
+    0x46,0x6A,0xC5,0x59,0x7F,0x6E,0xFF,0xA0,0x06,0x62,0xC5,0x59,0xDF,0xF5,0x3F,0x25,
+    0x05,0x62,0x83,0x51,0xE2,0xFA,0x68,0xE8,0xA5,0x51,0x43,0x49,0x70,0x7E,0xDE,0xD7,
+    0x43,0x49,0x03,0x41,0xE2,0xEA,0xC8,0x9C,0x64,0x49,0x03,0x39,0x2B,0xAA,0xE9,0xF9,
+    0x64,0x49,0x03,0x39,0x7C,0xB7,0xBF,0xFF,0x44,0x41,0x23,0x41,0xAF,0xA7,0x29,0x20,
+    0x44,0x49,0x23,0x39,0xDF,0xB7,0xB6,0x09,0x44,0x41,0x03,0x41,0x7A,0x58,0xFC,0x9C,
+    0x44,0x41,0xE2,0x38,0x77,0xF6,0xE3,0xEB,0x84,0x51,0xE2,0x38,0x02,0x39,0x97,0x55,
+    0xE5,0x59,0x43,0x49,0x0E,0x0A,0x23,0xD5,0xE5,0x59,0x43,0x41,0x78,0xC0,0x80,0xE2,
+    0x23,0x41,0xA2,0x30,0x6C,0xF8,0xFC,0x58,0xE3,0x38,0x81,0x28,0x5F,0x7E,0xF8,0x7B,
+    0xC1,0x30,0x81,0x20,0x6B,0x9F,0xDE,0x3A,0xC2,0x30,0xA1,0x28,0x9B,0x2A,0x2A,0xFC,
+    0x03,0x31,0xA2,0x28,0x88,0xFB,0xBF,0x5F,0xC2,0x28,0x82,0x20,0x26,0xAE,0xE8,0xCA,
+    0xC2,0x28,0x61,0x20,0x0A,0x8A,0x7F,0x57,0x81,0x20,0x41,0x18,0xE0,0xE8,0xFF,0xFF,
+    0x82,0x20,0x61,0x20,0xDD,0xDF,0xAF,0x08,0xC2,0x28,0x81,0x20,0xF5,0xBD,0xB5,0x95,
+    0xC2,0x28,0x81,0x20,0x2F,0x2F,0x0B,0x2F,0xC2,0x28,0xA2,0x28,0x0F,0x2A,0x3B,0x28,
+    0xE3,0x28,0xA1,0x20,0xEE,0x2B,0xEF,0x6F,0xE3,0x30,0xA2,0x28,0xFA,0x83,0xF5,0x95,
+    0x03,0x31,0xA2,0x28,0x35,0x95,0xFF,0x5A,0x44,0x41,0xC2,0x30,0x8A,0xEF,0xFF,0xDD,
+    0x03,0x39,0xA2,0x28,0xFC,0xFA,0x7A,0x7F,0xC2,0x28,0x61,0x28,0x7E,0xE8,0x28,0x82,
+    0xC2,0x30,0x61,0x20,0xF5,0xEF,0x32,0xB2,0xC2,0x28,0x81,0x28,0x7F,0xFA,0xCA,0x80,
+    0xA1,0x28,0x61,0x20,0xFB,0x7C,0x7A,0x7C,0xA2,0x28,0x61,0x28,0xBF,0x57,0xEA,0xCA,
+    0xE3,0x38,0x61,0x20,0x0B,0x0B,0x8F,0xED,0xE2,0x38,0xC2,0x30,0x80,0x00,0x07,0x85,
+    0x24,0x41,0xE2,0x38,0xD5,0x95,0x8D,0xBF,0x23,0x41,0xE3,0x38,0xBF,0xF6,0xBF,0x97,
+    0x23,0x41,0xE3,0x38,0xFA,0xA6,0x2E,0x28,0x23,0x41,0xC2,0x38,0xBE,0xF6,0x3A,0x20,
+    0x03,0x39,0xC2,0x38,0x60,0x68,0xF8,0xC2,0xC2,0x30,0xA2,0x30,0x02,0x00,0xB8,0xFE,
+    0xE3,0x38,0xA2,0x30,0xDE,0x5A,0x7B,0x6D,0xC2,0x30,0x81,0x28,0xA8,0xAF,0xB4,0xAE,
+    0xE3,0x30,0xA2,0x28,0xD3,0xB8,0xAB,0x35,0xE3,0x30,0x61,0x20,0x78,0x7A,0xE8,0xA0,
+    0xA2,0x28,0x61,0x20,0xBB,0xFF,0xFB,0xA0,0xA2,0x28,0x81,0x20,0xBD,0xFF,0x5E,0xFF,
+    0xA2,0x28,0x61,0x20,0x02,0x0A,0x2F,0xA7,0xC2,0x28,0x81,0x28,0x0B,0xA2,0xFA,0xFA,
+    0x03,0x39,0x81,0x28,0x02,0xBF,0xAD,0xFD,0x04,0x39,0xA2,0x28,0xE0,0xF8,0xFB,0xFE,
+    0xC2,0x28,0x82,0x28,0xA8,0xAA,0xF8,0xDA,0xC2,0x28,0x81,0x20,0xAA,0x8B,0xEB,0x7F,
+    0xC2,0x28,0x82,0x28,0x0E,0x28,0xF8,0x65,0xE3,0x30,0x81,0x28,0x8A,0x2F,0xB7,0xED,
+    0xE3,0x30,0xA2,0x28,0x3C,0x7E,0x7F,0x7D,0xE3,0x30,0xA2,0x28,0x3E,0x35,0x2D,0xF5,
+    0x03,0x31,0xA2,0x28,0x2A,0xAB,0x3F,0xB5,0x24,0x39,0xE2,0x30,0x7F,0xFF,0xDF,0xEB,
+    0x03,0x31,0xC2,0x30,0xAA,0xB8,0x76,0xD7,0xE2,0x30,0xC2,0x28,0x78,0xE2,0xCB,0x88,
+    0x03,0x31,0xC2,0x30,0x2D,0xEF,0xCF,0xEF,0x03,0x31,0xA2,0x28,0xC2,0xAA,0xFF,0x5E,
+    0xE2,0x30,0xA2,0x28,0x2A,0xAA,0xAA,0xA9,0x03,0x39,0xC2,0x30,0x52,0x5F,0xB6,0xB5,
+    0x04,0x39,0xC3,0x30,0xEF,0x2D,0xAB,0xBE,0x23,0x39,0xC2,0x30,0xB7,0xFA,0xFA,0x82,
+    0x23,0x39,0xC2,0x30,0xA0,0x82,0x02,0x62,0x23,0x41,0xC2,0x30,0x1E,0xBC,0xA0,0x20,
+    0x23,0x41,0x03,0x39,0x2B,0x19,0x85,0x29,0x44,0x49,0xC2,0x38,0xFE,0xDF,0xFF,0x02,
+    0x23,0x41,0xC2,0x38,0xD6,0xBE,0xA2,0x2A,0x64,0x49,0xE3,0x38,0xD7,0xFF,0xAB,0xAB,
+    0x85,0x51,0x03,0x39,0x75,0xFF,0xAB,0x0A,0xC6,0x59,0x24,0x49,0xBD,0x3B,0x2B,0x2B,
+    0x89,0x72,0xE6,0x59,0x35,0x25,0xBD,0xBF,0x2E,0xAC,0xC9,0x7A,0x09,0x2D,0xBD,0xF5,
+    0x10,0xC5,0xCC,0x9B,0x0A,0x0A,0xAD,0xF5,0x10,0xC5,0x8F,0xB4,0x22,0x22,0x0A,0xFD,
+    0xF0,0xC4,0xCF,0xBC,0x37,0x57,0x7A,0x8B,0x10,0xC5,0xCF,0xBC,0xBF,0xF9,0xE3,0xAA,
+    0x10,0xC5,0xCF,0xBC,0xAA,0xEF,0xFE,0x9A,0x10,0xC5,0xF0,0xBC,0xA2,0x90,0x34,0x32,
+    0x31,0xC5,0xF0,0xBC,0xFE,0x7B,0xEB,0xFE,0x10,0xC5,0xD0,0xBC,0xB1,0x2A,0x28,0xAB,
+    0xF0,0xBC,0xAF,0xBC,0xE8,0x88,0xEA,0x82,0xF0,0xC4,0x6E,0xB4,0x5F,0xEA,0xA0,0x00,
+    0x10,0xC5,0x4E,0xAC,0x57,0xFF,0xEA,0x88,0x8F,0xB4,0x2D,0xA4,0x5F,0xF8,0xF8,0xF0,
+    0x2D,0xA4,0xAC,0x93,0xFB,0xFA,0xA8,0x82,0x0D,0x9C,0x8B,0x93,0x57,0x77,0xFA,0xA8,
+    0xED,0x9B,0x09,0x7B,0x7F,0xA2,0x00,0x00,0xED,0x9B,0xC8,0x72,0xD5,0x5F,0xE8,0xA0,
+    0x8B,0x8B,0xC9,0x7A,0xFF,0xFF,0xBF,0x88,0x4A,0x83,0xE9,0x7A,0x97,0xBB,0xFF,0xE8,
+    0x6B,0x8B,0x0A,0x7B,0xDF,0xBF,0xAF,0x2B,0x6B,0x8B,0x2A,0x83,0xB6,0xEA,0xD3,0xDE,
+    0x6B,0x8B,0x2A,0x83,0x9E,0xFE,0xDB,0xFA,0x6C,0x8B,0xC9,0x72,0x5E,0x7A,0xE0,0xAA,
+    0x0A,0x7B,0xA9,0x6A,0x6D,0x7B,0xBC,0xB0,0xE9,0x72,0x26,0x5A,0x57,0x5A,0x7A,0x78,
+    0x23,0x41,0xE2,0x40,0x6B,0xED,0xF4,0xAE,0x23,0x49,0xE2,0x40,0x96,0x2A,0xAE,0xCB,
+    0x44,0x49,0xE2,0x40,0xF9,0xEC,0xF2,0xFF,0x23,0x49,0x02,0x41,0x7D,0xDD,0x77,0xAE,
+    0x23,0x49,0xE2,0x40,0xB8,0x25,0xBD,0xB8,0x23,0x49,0xE2,0x40,0xF2,0xD8,0xD8,0xF8,
+    0x23,0x49,0xE2,0x40,0xAB,0x0F,0xBA,0xA9,0x43,0x49,0xE2,0x40,0xB7,0xAF,0x82,0xFE,
+    0x03,0x41,0xC2,0x38,0x00,0x80,0xD0,0xDA,0x03,0x41,0xC2,0x38,0x62,0xBF,0xB7,0xBF,
+    0x03,0x41,0xC2,0x38,0x8B,0xD8,0x92,0xAC,0x03,0x41,0xE2,0x40,0xB3,0xC2,0x8A,0xDD,
+    0x02,0x41,0xC2,0x38,0x7E,0xBB,0xB2,0xA2,0x03,0x41,0xE2,0x38,0x0A,0xE5,0x7D,0xED,
+    0x03,0x41,0xE2,0x40,0xBA,0x00,0x09,0xDF,0x23,0x41,0xE2,0x40,0x3F,0xAE,0xD6,0x75,
+    0x03,0x41,0xA2,0x38,0x08,0xA8,0xA8,0xB7,0x03,0x41,0xC1,0x38,0x82,0xBE,0xE2,0x78,
+    0x02,0x41,0xE2,0x40,0x51,0xC3,0x8D,0xD5,0x23,0x41,0xE2,0x40,0xBD,0xAD,0xBD,0x73,
+    0x02,0x41,0xE1,0x40,0xC0,0xC0,0xEA,0xE2,0x22,0x41,0xC1,0x40,0xFD,0x9F,0xD7,0xDF,
+    0xC5,0x59,0xE2,0x40,0x37,0x3D,0xB5,0xB5,0x47,0x6A,0xE5,0x61,0xAF,0xC2,0xC9,0x89,
+    0x47,0x6A,0xE5,0x61,0x63,0x7B,0x7B,0x6E,0x05,0x62,0xA4,0x59,0xAF,0xFA,0xE2,0x82,
+    0x06,0x62,0x64,0x51,0xEC,0xFC,0xFA,0x7A,0x43,0x49,0x03,0x41,0x78,0x78,0xF8,0x5C,
+    0x23,0x41,0xE2,0x38,0xBE,0xB5,0xE5,0xAA,0x23,0x41,0xC2,0x30,0xA2,0xFB,0x7A,0xFA,
+    0x44,0x41,0xE2,0x30,0xBF,0xAB,0xAF,0xA9,0x44,0x41,0x24,0x39,0x02,0x8A,0x02,0xC2,
+    0x44,0x41,0x03,0x39,0x02,0xCB,0x83,0x82,0x44,0x41,0x03,0x41,0xDC,0xFE,0xEB,0xAA,
+    0x43,0x41,0xE3,0x38,0x6B,0xF2,0xFA,0xBA,0xE2,0x38,0xA1,0x30,0x8E,0xBA,0x4A,0x68,
+    0x44,0x49,0xC2,0x30,0xAF,0xAD,0xBD,0xBD,0x84,0x49,0xE3,0x38,0x82,0xB9,0xEF,0x5D,
+    0x23,0x41,0xA2,0x28,0x58,0xF8,0x7E,0xFF,0xC2,0x28,0x81,0x28,0xAA,0xEF,0xF7,0xEA,
+    0xE2,0x28,0x81,0x20,0x3E,0x3F,0xFF,0xED,0xE2,0x30,0xA2,0x28,0x7E,0xF8,0xFE,0xFF,
+    0xC2,0x28,0xA2,0x28,0xDF,0xFF,0xFF,0x22,0xA2,0x28,0x61,0x20,0x80,0xF0,0x70,0x78,
+    0x81,0x20,0x41,0x18,0x78,0xFE,0xFE,0xFB,0x81,0x20,0x41,0x18,0xFB,0xAA,0x8A,0x0A,
+    0xA2,0x28,0x61,0x20,0xEF,0x6F,0xAA,0x2B,0xC2,0x28,0x61,0x20,0xAD,0xAB,0x37,0xAE,
+    0xC2,0x28,0x81,0x20,0x29,0x85,0xAA,0xBA,0xE3,0x30,0xA2,0x28,0xFF,0xCA,0xCE,0xAA,
+    0x03,0x29,0xA2,0x28,0xF7,0x5F,0xFD,0xFE,0xE2,0x30,0xA2,0x28,0xB7,0xB5,0xDD,0x5A,
+    0xE3,0x30,0xA2,0x28,0x6A,0x62,0x72,0xFF,0xC2,0x30,0xA2,0x28,0xE3,0x66,0x75,0x65,
+    0xA2,0x28,0x81,0x20,0x02,0xB8,0x56,0x7C,0xC2,0x28,0x81,0x20,0xA2,0xB3,0xF5,0xFD,
+    0xC2,0x28,0xA2,0x28,0x33,0x01,0x28,0x23,0xE3,0x30,0x81,0x20,0xCA,0xEA,0xFF,0x7E,
+    0xA2,0x28,0x81,0x20,0x57,0x69,0x7D,0xBF,0xA2,0x28,0x61,0x20,0xFB,0xFA,0xAA,0x80,
+    0xA1,0x28,0x61,0x20,0x09,0x3F,0x8B,0x0E,0xE2,0x30,0x81,0x28,0x0F,0x9F,0xAF,0xBB,
+    0x03,0x39,0xA2,0x30,0x20,0x0A,0xBF,0xFD,0x03,0x39,0xC2,0x30,0x0C,0x02,0x0B,0xBF,
+    0x44,0x41,0x03,0x39,0xFA,0xFE,0x6B,0xFD,0x44,0x41,0x03,0x39,0x5E,0x77,0xDD,0x3B,
+    0x44,0x41,0xE2,0x38,0x6F,0x7B,0x6B,0x63,0xE3,0x38,0xA2,0x30,0xDF,0x5F,0x7B,0x78,
+    0xA2,0x28,0x61,0x28,0x00,0x00,0x2A,0x3E,0xE3,0x30,0xA2,0x30,0xDD,0x5F,0xFE,0x2D,
+    0xE2,0x30,0x81,0x28,0x27,0xAF,0xBF,0xEE,0x03,0x31,0xC2,0x28,0xE2,0xED,0xDD,0x7D,
+    0xE3,0x30,0xA2,0x28,0x54,0xAF,0x0F,0x8F,0xC3,0x28,0x81,0x28,0xF7,0xFE,0xFC,0xF0,
+    0xA2,0x30,0x61,0x20,0xF7,0xFB,0xBE,0x2A,0x81,0x30,0xA2,0x28,0xD7,0x5C,0x56,0x5F,
+    0xE3,0x30,0xA2,0x30,0xBD,0x2F,0x0B,0x2B,0xE3,0x30,0xC2,0x28,0x7C,0xF0,0xFA,0xBA,
+    0xE3,0x30,0x81,0x20,0xFF,0xF6,0xDC,0x7E,0xA2,0x28,0x81,0x20,0x78,0x5C,0xA0,0x23,
+    0xC2,0x28,0x61,0x20,0xFF,0xFD,0xAA,0x2A,0xC2,0x30,0x82,0x28,0x0D,0x0D,0x0F,0x00,
+    0xC2,0x30,0x82,0x28,0xE0,0xE8,0xFC,0xF8,0xE3,0x30,0xA2,0x28,0xD5,0xB5,0x3D,0xEF,
+    0xE3,0x30,0xA2,0x28,0xBF,0x9F,0x2F,0xBF,0x03,0x31,0xC3,0x30,0xAA,0xEA,0xBB,0xAF,
+    0x03,0x31,0xA2,0x28,0x9F,0xF5,0x37,0xB7,0x03,0x31,0xA2,0x28,0x22,0xF2,0x7F,0x55,
+    0x03,0x31,0xA2,0x28,0x8B,0xA2,0xBB,0x9D,0xE2,0x30,0xA2,0x28,0x5E,0xE0,0xE0,0xAA,
+    0xE3,0x38,0xC2,0x28,0x57,0x7D,0xDD,0x7D,0x03,0x31,0xA2,0x28,0xA7,0xDD,0x5F,0x2B,
+    0x03,0x39,0xC2,0x30,0x35,0xAF,0xBF,0x3F,0x44,0x41,0xE2,0x30,0xAB,0xA2,0x9A,0xF7,
+    0x23,0x39,0xE2,0x30,0xE0,0xE2,0xE0,0x62,0x44,0x41,0xC1,0x30,0xAA,0xAF,0x2B,0x89,
+    0x24,0x41,0xE2,0x38,0x36,0x26,0xBB,0x7A,0x64,0x49,0xE3,0x38,0xAB,0xBF,0xED,0xFF,
+    0x64,0x49,0x03,0x41,0x95,0x37,0x2D,0x3D,0x44,0x49,0x03,0x41,0x08,0x38,0x27,0x2A,
+    0xC6,0x59,0x24,0x41,0xAD,0xED,0xEB,0x2B,0x07,0x62,0x64,0x49,0xB7,0x3D,0xFF,0x0B,
+    0xCA,0x7A,0x27,0x6A,0xA5,0x2F,0x8D,0x0B,0x2B,0x8B,0xCA,0x7A,0x3D,0x25,0xFD,0xEF,
+    0xAC,0x9B,0x0A,0x83,0x2A,0xBD,0xD5,0x55,0x8F,0xB4,0x2A,0x8B,0x0A,0xBF,0xFF,0x55,
+    0xF0,0xBC,0x8B,0x93,0x02,0x2A,0xBD,0x55,0xF0,0xC4,0x0D,0xAC,0x00,0x00,0x0B,0xBD,
+    0x10,0xC5,0xAF,0xBC,0xAA,0x28,0x2A,0x2D,0x10,0xC5,0xF0,0xBC,0xD6,0x2A,0x86,0xAF,
+    0x10,0xC5,0xCF,0xBC,0x9A,0x62,0xF8,0xFE,0x10,0xC5,0xAF,0xB4,0xAA,0x8E,0x7E,0xFB,
+    0xF0,0xBC,0xAF,0xB4,0x2A,0xB2,0xB3,0xAF,0xF0,0xBC,0xD0,0xBC,0x05,0x2A,0x2E,0xBA,
+    0x11,0xC5,0xAF,0xB4,0xAE,0xA6,0xAA,0xEB,0xF0,0xBC,0x4D,0xA4,0x58,0x78,0x48,0xE0,
+    0x6D,0xAC,0x0D,0xA4,0xDF,0x7F,0x7A,0xF8,0x2D,0xA4,0xCC,0x9B,0x7C,0xAA,0xAA,0x0A,
+    0x2D,0xA4,0xEC,0x9B,0xF5,0xBD,0x97,0x2E,0x2D,0xA4,0x0D,0x9C,0xCF,0x7F,0xFE,0xB3,
+    0x4E,0xA4,0xCC,0x93,0x67,0xAA,0xA2,0x28,0x0D,0x9C,0x2A,0x83,0x7F,0xE8,0x00,0x00,
+    0x0D,0x9C,0x2A,0x83,0x75,0xFF,0xEA,0x80,0xCC,0x93,0x2A,0x83,0x5F,0xFF,0xFA,0x00,
+    0x0D,0x9C,0x2A,0x83,0x77,0xDF,0xEF,0x2A,0xEC,0x9B,0x2A,0x83,0x5D,0x7F,0xFE,0x20,
+    0x8A,0x8B,0xE9,0x7A,0x5F,0xEB,0x58,0xA0,0x4A,0x83,0x68,0x6A,0x5F,0x5B,0xEA,0xA8,
+    0x23,0x49,0xC2,0x38,0xAB,0xA6,0xA4,0x2A,0x44,0x49,0xE2,0x38,0xAD,0xB7,0xEA,0xAA,
+    0x23,0x49,0xE3,0x40,0x38,0xAE,0xEE,0xCE,0x23,0x49,0x03,0x41,0x60,0xCE,0x2C,0x5A,
+    0x23,0x49,0xE2,0x40,0xAA,0x0A,0xE0,0xFA,0x23,0x51,0x03,0x41,0xFA,0x7F,0xDD,0x55,
+    0x43,0x49,0x02,0x41,0xFB,0x3B,0xA3,0xBB,0x23,0x49,0xC2,0x38,0xEA,0xBA,0x58,0xE8,
+    0x23,0x41,0xA1,0x38,0xEA,0xAA,0xFA,0x68,0x03,0x41,0xA2,0x38,0xFF,0xBE,0xAB,0x89,
+    0x03,0x41,0xC2,0x38,0xBC,0xB7,0xD4,0x2A,0x23,0x41,0xE2,0x40,0xD7,0x5E,0xDC,0xE7,
+    0x03,0x41,0xC2,0x38,0x7A,0xFF,0xB7,0x2F,0x03,0x41,0xE2,0x40,0x05,0x15,0xA9,0x5C,
+    0x03,0x41,0xE2,0x38,0x03,0xCA,0xD5,0x5D,0x03,0x41,0xC2,0x38,0xFE,0xA6,0xD6,0xD6,
+    0x02,0x41,0xC2,0x38,0x3D,0x3B,0xAF,0xBF,0x03,0x41,0xE2,0x38,0x70,0x70,0x5C,0x5D,
+    0xE2,0x40,0x02,0x39,0xE0,0x38,0xAA,0xB2,0x02,0x41,0xE2,0x38,0xF8,0xAB,0xBD,0xDD,
+    0x02,0x41,0xC2,0x40,0xA2,0x22,0x00,0xAC,0x03,0x41,0xC2,0x40,0x2B,0x07,0x0E,0xA8,
+    0x84,0x51,0xE2,0x40,0x35,0x3F,0x9D,0xF5,0x67,0x72,0xA4,0x59,0x2B,0x0B,0x09,0x81,
+    0x67,0x72,0x05,0x62,0x5B,0x71,0xE8,0x6A,0x05,0x62,0xC5,0x59,0x2B,0x08,0x80,0xE8,
+    0x05,0x62,0x63,0x49,0x60,0x7A,0xFA,0x6A,0x64,0x49,0xE2,0x38,0xF0,0xF8,0xF8,0x5A,
+    0x44,0x41,0xE2,0x38,0xFE,0xDF,0xD7,0x3D,0x44,0x41,0x03,0x39,0x75,0xCE,0xA2,0x98,
+    0x23,0x39,0xE2,0x38,0x8B,0xA2,0x03,0x20,0x23,0x39,0xC3,0x30,0x2A,0x6E,0xFE,0xF2,
+    0x44,0x41,0xE3,0x30,0x0A,0x2B,0xBD,0xE7,0x44,0x41,0xE2,0x38,0xAA,0x20,0x8F,0xAD,
+    0x44,0x41,0x23,0x39,0x57,0x18,0xD8,0x71,0x23,0x39,0xC2,0x30,0x5E,0xFC,0xF8,0xA8,
+    0x03,0x39,0xC2,0x30,0xE9,0x7A,0xBA,0xA2,0x03,0x39,0xA1,0x28,0xE2,0xEA,0xF3,0x7B,
+    0xC2,0x30,0xA1,0x28,0xA0,0xE8,0xBC,0xA5,0xE2,0x28,0x81,0x28,0xEA,0xA2,0xA8,0x6A,
+    0xE2,0x30,0xA2,0x20,0xED,0xEF,0xBE,0x7B,0xE3,0x28,0x81,0x20,0x8A,0xA2,0xEA,0xDF,
+    0xE3,0x28,0x82,0x20,0xE2,0x7A,0x77,0xFF,0xC2,0x20,0x61,0x20,0x5E,0x57,0x7F,0xFF,
+    0xA2,0x28,0x61,0x20,0x7D,0xF3,0x8B,0x03,0xE3,0x30,0x81,0x20,0xD5,0xFD,0xA9,0x0A,
+    0xC3,0x28,0x81,0x20,0xFD,0xFE,0xFC,0xA8,0x02,0x29,0xA2,0x28,0x75,0x7D,0xFF,0xDE,
+    0xC2,0x28,0xA2,0x28,0xCA,0x80,0x8E,0xBA,0x03,0x31,0xC2,0x28,0xFD,0xED,0xD5,0x95,
+    0x03,0x31,0xC2,0x28,0xF7,0x7F,0x7B,0xEA,0x03,0x29,0xA2,0x28,0xDF,0x5F,0xFE,0xFF,
+    0x03,0x31,0xA2,0x28,0xDD,0x5D,0x5B,0xFB,0xE2,0x28,0xA2,0x28,0xED,0x7F,0xBE,0xEA,
+    0xC2,0x28,0x81,0x20,0x97,0xFC,0x82,0xE0,0x81,0x28,0xC2,0x20,0xA7,0xBF,0xBA,0xEA,
+    0xE3,0x30,0x81,0x20,0xBF,0x2F,0xFD,0xB7,0xC2,0x28,0x81,0x20,0x54,0x5E,0x58,0xFE,
+    0xC2,0x28,0x81,0x20,0xFF,0x5F,0xFE,0x38,0xC2,0x28,0x81,0x20,0xEB,0x72,0x7A,0xF8,
+    0xC2,0x28,0x81,0x20,0xDF,0xAB,0x83,0xEB,0xE2,0x30,0xA2,0x28,0x52,0x6B,0x7B,0x75,
+    0xC2,0x30,0x81,0x20,0xAA,0xFE,0x75,0x57,0xC2,0x30,0x81,0x20,0x08,0x2F,0xAD,0xED,
+    0x03,0x39,0x81,0x28,0x00,0xAA,0xAF,0xF5,0x23,0x41,0xC2,0x30,0x20,0x08,0x2D,0x9F,
+    0x65,0x49,0x24,0x41,0x41,0xA2,0xBB,0xEB,0x44,0x41,0xA2,0x28,0x7A,0xF8,0xCA,0x78,
+    0xC2,0x30,0x61,0x20,0xD6,0xFE,0xB8,0xAA,0xA2,0x30,0x82,0x20,0x08,0xA0,0x20,0xA0,
+    0xC3,0x30,0x82,0x28,0xEA,0xEB,0xEB,0xFD,0xC2,0x30,0x81,0x28,0xB2,0x9F,0x7F,0xAF,
+    0xC2,0x30,0x82,0x28,0x8A,0xAE,0xBD,0xFA,0x03,0x39,0xA2,0x28,0xD9,0xAF,0xAF,0xBD,
+    0x03,0x39,0xA2,0x28,0xD5,0xBF,0x2E,0x0A,0x24,0x39,0xA2,0x30,0xD5,0xFB,0xAA,0xAA,
+    0x03,0x39,0xA2,0x30,0xF7,0xFF,0xFE,0x22,0xE2,0x30,0xA2,0x28,0xFF,0xDF,0x53,0xC0,
+    0xC2,0x30,0x82,0x28,0xBC,0x7E,0xBE,0xA2,0xE3,0x28,0x81,0x28,0xBD,0xF7,0x57,0xFF,
+    0x03,0x31,0x82,0x28,0x3F,0xAF,0xBD,0xBD,0x03,0x39,0xC2,0x28,0x68,0xE0,0xC2,0x83,
+    0xE3,0x30,0xA2,0x28,0x58,0xEA,0xC0,0xB0,0xE2,0x30,0xA2,0x28,0x27,0xF7,0xDF,0x7F,
+    0xC2,0x30,0xA2,0x28,0x80,0xBA,0x59,0xA3,0xE3,0x30,0x81,0x28,0x0A,0xCA,0xDA,0xDF,
+    0xC2,0x28,0x81,0x28,0x88,0x2A,0x0A,0xAD,0xC2,0x28,0xA2,0x28,0x77,0xB9,0xE2,0x22,
+    0xC2,0x28,0x81,0x20,0x3E,0xEA,0xFE,0xF2,0xC3,0x30,0x81,0x20,0x02,0xAB,0xEE,0x6F,
+    0xE3,0x30,0x81,0x20,0xA2,0xBB,0xBD,0xA5,0xE3,0x30,0xC2,0x28,0xA7,0xF7,0x65,0x75,
+    0x03,0x39,0xC2,0x28,0x3B,0x3D,0x75,0xAD,0x02,0x39,0xA2,0x28,0x28,0xFF,0xBF,0xFF,
+    0x03,0x39,0xA1,0x28,0xA0,0x8B,0xA9,0xAA,0x44,0x41,0xC1,0x30,0x29,0xFB,0x7D,0xF5,
+    0x44,0x41,0xE2,0x38,0xDA,0x5B,0xD7,0x3D,0x84,0x49,0x03,0x39,0x5D,0xFF,0xC1,0xCA,
+    0x44,0x49,0x03,0x41,0xAD,0xA5,0x25,0xFF,0x85,0x51,0x23,0x41,0xFD,0xBF,0x2F,0x0B,
+    0xC6,0x59,0x64,0x49,0xA5,0xB5,0x3F,0x0F,0x27,0x6A,0xC5,0x59,0xAD,0x35,0xF5,0x2B,
+    0xEA,0x82,0x48,0x6A,0x2D,0x2D,0x2D,0x09,0x2A,0x83,0xEA,0x7A,0xE9,0x7F,0x76,0x6A,
+    0x2B,0x83,0xC9,0x7A,0xAE,0xAF,0xB5,0xBF,0x2A,0x8B,0xC9,0x7A,0x2F,0xE6,0xA6,0xAE,
+    0x8C,0x9B,0xE9,0x7A,0x2B,0xBF,0xD7,0xFF,0xED,0xA3,0x2A,0x83,0x0B,0xB7,0xFD,0x55,
+    0xAF,0xBC,0x2B,0x83,0x02,0xAF,0xFD,0xD5,0xF0,0xBC,0xAC,0x9B,0x00,0x02,0xAD,0x55,
+    0xF0,0xBC,0x4D,0xAC,0x00,0x00,0x0A,0xE5,0xF0,0xBC,0xAF,0xB4,0x72,0xA2,0x0A,0x2F,
+    0x11,0xC5,0xD0,0xBC,0xFD,0x7B,0xCA,0xEF,0x10,0xC5,0xD0,0xBC,0x7E,0x7F,0x6B,0xEA,
+    0x10,0xC5,0xD0,0xBC,0xE5,0xFF,0xAF,0x6B,0xF0,0xBC,0x6E,0xAC,0xE8,0xA8,0xE0,0x60,
+    0x8F,0xAC,0x0D,0xA4,0x74,0xDC,0xDA,0xFA,0x4E,0xAC,0x2D,0xA4,0x5E,0x5E,0x67,0x24,
+    0x2D,0xA4,0xEC,0x9B,0x18,0x2E,0x00,0x00,0x2D,0xA4,0x0D,0xA4,0x50,0x08,0x9D,0x0A,
+    0x4E,0xAC,0x0D,0x9C,0xFD,0x96,0xAE,0xDA,0x4E,0xA4,0x0D,0xA4,0xEA,0xAB,0xA7,0x9F,
+    0x6E,0xA4,0x2D,0xA4,0x7D,0xE9,0x7D,0xB5,0x4E,0xA4,0xEC,0x9B,0x9E,0x22,0x80,0x0A,
+    0x6E,0xAC,0x0D,0x9C,0xD7,0xB8,0x2A,0x02,0x6F,0xAC,0x0D,0x9C,0x7F,0xCF,0xAA,0xEE,
+    0x4E,0xA4,0xAB,0x8B,0x57,0xA8,0xC0,0x02,0x4E,0xA4,0x2A,0x83,0x57,0xFE,0xAA,0xA0,
+    0x44,0x49,0xE2,0x40,0xA5,0x6F,0x5A,0xFC,0x23,0x49,0xC2,0x38,0x88,0xEA,0xEA,0x7A,
+    0x23,0x49,0xC2,0x38,0xE2,0xFA,0xFA,0xAD,0x23,0x49,0xE3,0x40,0x8A,0xEA,0xFA,0xBF,
+    0x23,0x49,0xE3,0x40,0x9A,0xBB,0xE9,0xF0,0x23,0x49,0xE3,0x40,0x96,0x25,0xBF,0x9B,
+    0x23,0x49,0xE2,0x40,0x82,0xA0,0x2E,0x7A,0x23,0x41,0xE2,0x40,0xAA,0x36,0xD7,0xF5,
+    0x03,0x41,0xC1,0x38,0xF8,0xE8,0xA8,0x3E,0x02,0x41,0xA1,0x38,0xDA,0xF8,0xBA,0xEE,
+    0x03,0x41,0xA2,0x38,0x03,0xAB,0xEF,0xFA,0x03,0x41,0xC2,0x38,0x88,0x9E,0x57,0x5F,
+    0x03,0x41,0xC2,0x38,0x2F,0xFA,0xB9,0xF9,0x02,0x41,0xC2,0x38,0xEA,0xEB,0x6A,0xEF,
+    0x23,0x49,0xC2,0x38,0xDA,0xFE,0xDC,0x7A,0xE2,0x40,0xC2,0x38,0x98,0x78,0x68,0xA8,
+    0x02,0x41,0xC2,0x38,0xFF,0xFE,0xB3,0x03,0x02,0x41,0xC2,0x38,0xFE,0xB7,0xBA,0xB8,
+    0x03,0x41,0xE2,0x40,0x95,0xF5,0xCD,0x06,0x03,0x41,0xE2,0x40,0xFF,0xF8,0x70,0x5C,
+    0x02,0x41,0xC2,0x38,0x97,0xFE,0xAE,0xAA,0x03,0x41,0xA1,0x38,0x18,0x3A,0x0A,0x82,
+    0x23,0x49,0xA0,0x38,0x2E,0xA8,0x2E,0x2D,0x66,0x72,0x84,0x51,0x0B,0x0B,0x09,0xA9,
+    0x46,0x6A,0xE5,0x61,0xAA,0x9C,0x80,0x8A,0x27,0x6A,0xC5,0x59,0x6F,0xB7,0xAF,0xAC,
+    0x06,0x62,0x63,0x49,0xFE,0x58,0x78,0x78,0x44,0x49,0xE2,0x38,0x7E,0x5E,0x5E,0x7C,
+    0x44,0x41,0xE2,0x38,0xBD,0xD5,0xB5,0xCD,0x43,0x41,0x03,0x39,0x74,0x5F,0x5F,0x5F,
+    0x23,0x39,0xE3,0x38,0x2A,0x57,0x5A,0xAB,0x24,0x39,0x03,0x39,0x81,0xD3,0x7F,0xD7,
+    0x24,0x41,0xE3,0x30,0xBA,0xAA,0xED,0x6E,0x03,0x39,0xE3,0x30,0x2D,0xEF,0x7E,0xA2,
+    0x23,0x39,0xE3,0x38,0x00,0x2A,0xBD,0x9F,0x43,0x41,0x03,0x39,0x4A,0x69,0xFF,0x7F,
+    0x44,0x41,0xE2,0x30,0xFB,0x7A,0xEF,0xE3,0x23,0x39,0xC1,0x30,0x7F,0xFD,0xFB,0x28,
+    0x03,0x39,0xA1,0x28,0x5F,0x56,0xDE,0xA8,0xC2,0x28,0x81,0x20,0x7A,0xBA,0xA3,0x02,
+    0xE3,0x30,0x81,0x20,0x6D,0xBF,0xFC,0xEA,0xE3,0x30,0x81,0x20,0x5F,0xFF,0x8A,0x2A,
+    0x03,0x31,0xA2,0x28,0xD5,0xF7,0xBE,0xA8,0xE2,0x30,0x82,0x20,0x5F,0xAE,0x2E,0x22,
+    0xE3,0x30,0xA2,0x28,0xE5,0xFF,0x2F,0x28,0xE3,0x30,0xC2,0x28,0x6B,0x69,0x6F,0x55,
+    0xE3,0x30,0xA2,0x28,0xEB,0xA9,0xEB,0xFA,0xE3,0x30,0xA2,0x28,0xAA,0xA9,0xAB,0xB8,
+    0x03,0x31,0xC2,0x28,0xF7,0xF7,0xF5,0xB5,0xE3,0x30,0xA2,0x28,0xF2,0xBA,0xFE,0xA8,
+    0x03,0x31,0xC2,0x28,0xEA,0x6B,0x7F,0xFB,0xE3,0x30,0xC2,0x28,0x9A,0x27,0x23,0x8B,
+    0x03,0x31,0xA2,0x28,0xAA,0xFA,0xF8,0xDE,0xE3,0x28,0xA2,0x28,0xBA,0xBB,0xAE,0xAE,
+    0xE2,0x28,0xA2,0x28,0x5E,0xFA,0xAA,0x0E,0xE3,0x28,0xA2,0x28,0xD5,0xDE,0xD6,0xEE,
+    0xA2,0x28,0x61,0x20,0x8A,0xE8,0xD8,0x98,0xC2,0x28,0x81,0x20,0x2B,0xB9,0xED,0x5D,
+    0xE2,0x28,0xA2,0x20,0xDE,0xF2,0x5D,0x55,0xC2,0x28,0x82,0x20,0xC2,0x62,0xFA,0x68,
+    0xA2,0x20,0x61,0x20,0x00,0x82,0xB8,0x3A,0xC2,0x28,0x81,0x20,0xEA,0xFF,0xD7,0x57,
+    0xA2,0x28,0x61,0x20,0xFA,0xFA,0x7A,0xF2,0xA2,0x28,0x81,0x20,0x3F,0x97,0x95,0x3F,
+    0xC2,0x30,0x61,0x20,0x2F,0xFA,0x6E,0xBA,0xC2,0x30,0x81,0x28,0x28,0xF7,0xB5,0xED,
+    0x44,0x41,0xC2,0x30,0x0B,0xAD,0xBD,0xDD,0x24,0x39,0xC2,0x30,0xD8,0xBA,0xAA,0xFE,
+    0xE3,0x30,0xA2,0x30,0x97,0xA8,0xA0,0xA2,0xE3,0x38,0xA2,0x30,0x5E,0x5F,0xDE,0xB8,
+    0xE2,0x30,0x81,0x28,0x7F,0xEE,0xAA,0xA2,0xE3,0x30,0xA2,0x28,0x95,0x37,0x2E,0xAB,
+    0x03,0x39,0xA2,0x28,0xDF,0xB6,0xEA,0x8A,0xE2,0x30,0xA2,0x30,0x01,0x0A,0x2A,0x9A,
+    0x03,0x39,0xC2,0x30,0xFA,0xBF,0xAE,0x0F,0x43,0x41,0xE3,0x38,0xFB,0x7D,0x78,0xEA,
+    0x44,0x41,0x03,0x39,0xF5,0x2D,0xF9,0xA2,0x64,0x41,0xE3,0x38,0x57,0xA8,0x8A,0x2A,
+    0x44,0x41,0xC2,0x30,0x5D,0x5F,0xEC,0xAA,0x24,0x41,0xA2,0x28,0xD5,0xF7,0xAA,0xE8,
+    0xE3,0x30,0xA2,0x28,0x83,0x08,0x2E,0xA7,0xE3,0x30,0xC2,0x28,0x00,0xE8,0xB8,0x7E,
+    0xE3,0x30,0xA2,0x28,0xA0,0xBC,0x3E,0xFA,0xC2,0x30,0xA2,0x28,0x5E,0x5E,0x7C,0xFE,
+    0xE2,0x28,0x82,0x28,0xC7,0xFF,0xFB,0xBE,0xA2,0x28,0x81,0x20,0xA8,0x6E,0x36,0x32,
+    0xC2,0x28,0x61,0x20,0x2F,0xBF,0xD7,0xBB,0xC2,0x28,0x81,0x28,0x02,0x8A,0xF2,0xE8,
+    0xC2,0x28,0xA2,0x28,0x3E,0x27,0xB9,0x0D,0xC2,0x30,0x82,0x28,0x6E,0xA8,0xFA,0xC0,
+    0xC2,0x28,0x81,0x28,0xB5,0x97,0x9F,0xBE,0xE2,0x30,0xA2,0x28,0xBF,0x9F,0x9F,0x95,
+    0x03,0x31,0xC2,0x28,0xFB,0xFF,0xEF,0x2B,0x03,0x39,0xC2,0x30,0x5F,0x5A,0xF8,0xC0,
+    0xE2,0x30,0xA2,0x30,0x88,0xBB,0xBB,0xA2,0x03,0x39,0xC1,0x30,0xBD,0xBF,0xAB,0xA3,
+    0x23,0x41,0xE2,0x38,0xAD,0xE7,0xF7,0xBF,0x64,0x49,0x03,0x39,0x80,0xE3,0xFB,0xED,
+    0x64,0x49,0x02,0x39,0x7E,0xFA,0xA9,0x8B,0xC5,0x51,0x43,0x41,0xBD,0x0F,0xAF,0xFF,
+    0xE6,0x59,0x64,0x51,0xA5,0xBE,0xEA,0x37,0x68,0x6A,0xC6,0x59,0xBD,0x2B,0x3D,0x2B,
+    0xEA,0x82,0x68,0x6A,0x29,0x2B,0x0D,0x2F,0x2A,0x83,0xCA,0x7A,0xAA,0xA8,0xBB,0xB6,
+    0x2A,0x83,0xEA,0x7A,0xEE,0x62,0x6A,0xFB,0x2A,0x83,0xEA,0x7A,0xDE,0xFF,0xDD,0xC9,
+    0x2B,0x83,0xC8,0x7A,0xAB,0x2B,0xA5,0x77,0x2A,0x83,0xC9,0x7A,0x0F,0xBC,0xFE,0x6F,
+    0x6B,0x8B,0xC9,0x7A,0x2F,0xAF,0xED,0xFD,0x8C,0x93,0xEA,0x7A,0x00,0x02,0xEB,0xF5,
+    0x0D,0xA4,0x0A,0x83,0x02,0xAE,0xFD,0x7D,0xEF,0xBC,0x6B,0x8B,0x0A,0xAB,0xF5,0xD5,
+    0xF0,0xBC,0x8C,0x93,0x00,0x00,0xAB,0xBD,0xF0,0xBC,0x90,0xB4,0x20,0x02,0x03,0xFD,
+    0x30,0xC5,0xCF,0xBC,0xEF,0xBB,0xBA,0xF1,0x10,0xC5,0x8F,0xB4,0x6C,0xF8,0xE8,0xE8,
+    0xAF,0xB4,0x2D,0xA4,0xDA,0xE8,0xE8,0xFB,0x6E,0xAC,0x0C,0xA4,0xA6,0x23,0x2F,0x88,
+    0x6E,0xAC,0x2E,0xA4,0x7E,0xE0,0xF3,0x80,0x6F,0xAC,0x2E,0xA4,0x7F,0x57,0xD7,0xFE,
+    0x6E,0xAC,0x0D,0xA4,0x76,0x7F,0xBF,0xCA,0x4E,0xAC,0x0D,0x9C,0xAD,0xE3,0x02,0x8A,
+    0x4E,0xAC,0x0D,0xA4,0x2B,0x3B,0xCA,0xA0,0x6E,0xAC,0x0D,0xA4,0xAD,0xFA,0x22,0x2E,
+    0x8F,0xB4,0x2D,0xAC,0xBA,0xE6,0xBB,0xAA,0x6E,0xAC,0x2E,0xA4,0x6A,0xEA,0x6E,0x3A,
+    0x6E,0xAC,0x2E,0xA4,0xEF,0xBF,0xAA,0xA8,0x4E,0xA4,0x0D,0x9C,0xF0,0x68,0xF8,0x00,
+    0x23,0x49,0xC2,0x38,0x88,0xFA,0xFB,0x68,0x02,0x41,0xC2,0x38,0x7B,0xFD,0xFD,0xB7,
+    0x03,0x41,0xC2,0x38,0xB2,0xEA,0xBC,0x0E,0x23,0x41,0xC2,0x40,0x7E,0xFA,0xA2,0xAA,
+    0x23,0x49,0xE3,0x40,0x23,0x0B,0xAF,0xF7,0x23,0x49,0xE3,0x40,0x3B,0x28,0x8F,0x8C,
+    0x23,0x41,0xE2,0x40,0xDF,0x20,0x88,0x77,0x03,0x41,0xE2,0x38,0xAF,0xF0,0xEB,0x89,
+    0x02,0x41,0xC2,0x38,0xAF,0xEF,0xC7,0xFB,0xE2,0x40,0xC2,0x38,0x36,0x9F,0xE7,0x77,
+    0x03,0x41,0xC2,0x38,0xC2,0xE3,0xB5,0xB5,0x04,0x41,0xC2,0x38,0xE2,0xFA,0x76,0x57,
+    0x03,0x41,0xC2,0x38,0xBF,0xB6,0xBE,0xAF,0x23,0x41,0xE2,0x40,0xED,0xFD,0x95,0x8B,
+    0x23,0x49,0xC2,0x38,0xDE,0xFF,0xDF,0x35,0x03,0x41,0xC2,0x38,0xFA,0xAE,0xFF,0xAA,
+    0x03,0x41,0xE2,0x38,0xFB,0x6B,0x8A,0x25,0x23,0x41,0xC2,0x38,0xA7,0x2F,0x8B,0xFB,
+    0x02,0x41,0xC2,0x38,0xA8,0x9A,0xFF,0xDB,0x23,0x41,0xC2,0x38,0xFA,0xFD,0xFD,0x35,
+    0x03,0x41,0xE2,0x38,0xEF,0x42,0x6F,0x8E,0x03,0x41,0xA1,0x38,0x88,0xA2,0xBF,0x27,
+    0x23,0x49,0xC2,0x40,0xB5,0x17,0x9E,0xBF,0x66,0x72,0x44,0x51,0x2B,0xA9,0x2D,0x0D,
+    0x87,0x72,0x06,0x62,0xFF,0x7A,0x78,0xFC,0x26,0x6A,0xE5,0x59,0xEA,0x98,0xAA,0x8A,
+    0x06,0x62,0x64,0x49,0x68,0x70,0x6C,0xFA,0x44,0x41,0xE3,0x38,0x7E,0x7C,0xFF,0xDF,
+    0x03,0x39,0xC2,0x30,0x03,0x0A,0x02,0xAB,0x03,0x39,0xE2,0x30,0x00,0x20,0x0F,0x03,
+    0x23,0x39,0xE3,0x38,0x01,0x2B,0xFE,0x5F,0x24,0x41,0x03,0x39,0x56,0x77,0x73,0x57,
+    0x23,0x41,0xE3,0x30,0x8E,0xFD,0xB2,0xAA,0x24,0x39,0x03,0x39,0x42,0x5F,0xA9,0x7E,
+    0x44,0x41,0x03,0x39,0x5F,0x4B,0x82,0x03,0x44,0x41,0xE2,0x30,0x5F,0x7F,0xE2,0xE0,
+    0x23,0x39,0xE3,0x38,0xF5,0x7D,0xFF,0x82,0x23,0x39,0xE3,0x38,0x02,0x02,0xFE,0xF9,
+    0x44,0x39,0xE3,0x30,0xFF,0xFF,0xAF,0x89,0x24,0x39,0xC2,0x30,0xDF,0xFA,0xE8,0x2A,
+    0x03,0x31,0xC2,0x28,0xD5,0xFD,0xBA,0x80,0x03,0x31,0xC2,0x28,0xBF,0xFF,0x6A,0x60,
+    0x03,0x31,0xE3,0x30,0x6D,0xAD,0xFE,0xF9,0x03,0x31,0xC2,0x28,0xEE,0xAF,0x0A,0xC2,
+    0x03,0x31,0xC2,0x28,0xB9,0x88,0x00,0x00,0x24,0x39,0xC2,0x30,0x77,0xF2,0xA2,0xE2,
+    0x24,0x31,0xC2,0x30,0x7F,0xEF,0xAE,0xA2,0xE3,0x30,0xC2,0x30,0xDB,0xAB,0x20,0x82,
+    0x03,0x39,0xA2,0x28,0xFF,0xF7,0xA8,0xCA,0x24,0x39,0xC2,0x30,0x7C,0xF5,0x75,0xFD,
+    0x23,0x31,0xE3,0x30,0x5D,0xDB,0x7B,0x5D,0x03,0x31,0xC2,0x28,0xBF,0x2E,0xFF,0xF5,
+    0x03,0x31,0xA2,0x28,0xFE,0xB8,0xFA,0xA9,0xE3,0x30,0xA2,0x28,0xAA,0xEA,0x40,0x82,
+    0xE3,0x30,0xC2,0x28,0x9D,0x9F,0xAD,0x0D,0xA2,0x30,0xE3,0x28,0xB9,0x79,0x7D,0xFD,
+    0xE3,0x28,0x82,0x20,0xDF,0x9E,0x88,0x08,0xC3,0x28,0x81,0x20,0x5B,0xF3,0xE2,0xA8,
+    0xC3,0x28,0x82,0x20,0xFB,0xFF,0xFA,0x6B,0xC2,0x28,0x82,0x20,0x7E,0x5F,0x7E,0x7A,
+    0xA2,0x28,0x82,0x20,0x55,0xD9,0xB6,0xAA,0x61,0x28,0xA2,0x20,0xBF,0xA5,0xBD,0xFD,
+    0xA2,0x20,0x61,0x20,0xB8,0xBF,0xDE,0xF8,0xA2,0x28,0x82,0x20,0x2A,0xF3,0x59,0xD5,
+    0xA2,0x28,0x82,0x20,0xAE,0x97,0xDF,0x7B,0xA2,0x28,0x82,0x20,0x0B,0x0D,0x02,0xC2,
+    0xE3,0x30,0x82,0x28,0x2F,0x3F,0x3D,0x3D,0x23,0x39,0xC2,0x30,0x7A,0xEB,0xFA,0xF8,
+    0xE3,0x30,0xA2,0x28,0xAE,0xBF,0xF7,0xE0,0xE3,0x30,0xA2,0x28,0x82,0x3E,0x2F,0x2F,
+    0x23,0x39,0xC2,0x30,0xDF,0x9F,0x7E,0xFC,0xE2,0x30,0xC1,0x30,0x80,0x80,0xA7,0x56,
+    0x03,0x39,0xC2,0x30,0xAB,0xAA,0xAB,0x0F,0x23,0x39,0xC2,0x30,0xDF,0xBE,0xEA,0xE8,
+    0x23,0x39,0xC2,0x30,0x23,0x09,0xAB,0xF7,0x44,0x41,0xE2,0x38,0x3A,0xBE,0xFE,0xBD,
+    0x64,0x49,0x24,0x41,0x8E,0xAD,0xAD,0xA5,0x64,0x41,0x24,0x41,0xBF,0x8B,0x88,0xC0,
+    0x64,0x41,0xE3,0x30,0xFE,0x7C,0x7A,0xF0,0x24,0x39,0xC2,0x30,0x62,0xFF,0x77,0x77,
+    0xE2,0x30,0x82,0x28,0x2E,0xAE,0xE7,0xFE,0xE3,0x30,0xA1,0x28,0xD7,0xBD,0xEB,0x0B,
+    0x03,0x39,0xA2,0x28,0xAD,0x8B,0xBF,0xCB,0xE3,0x30,0xA2,0x28,0xAF,0x2E,0x3A,0x9C,
+    0xC2,0x30,0x82,0x28,0xEE,0xFC,0xB8,0xBA,0xA2,0x28,0x81,0x20,0x30,0xF8,0x3E,0x06,
+    0xC2,0x28,0x81,0x20,0xAA,0x1B,0xDE,0x2E,0xC2,0x28,0x61,0x28,0xE8,0x2A,0xA0,0xA8,
+    0x02,0x31,0xA2,0x28,0x35,0xF5,0xFF,0xFF,0xE2,0x30,0xA2,0x28,0x7A,0x5A,0x78,0x5A,
+    0xC2,0x28,0x81,0x20,0xB6,0xEE,0xAF,0x0D,0x03,0x31,0x82,0x28,0xFF,0xBE,0xEB,0x8D,
+    0x23,0x39,0xC2,0x30,0x2D,0x0F,0x89,0xAF,0x23,0x39,0xE3,0x30,0xC0,0x80,0x01,0x0F,
+    0x23,0x39,0xE2,0x30,0x57,0xFA,0xFE,0x28,0x44,0x41,0xE2,0x38,0x7B,0xE8,0x83,0x82,
+    0x23,0x41,0xE2,0x38,0x6F,0xFA,0x22,0x00,0x64,0x49,0x02,0x39,0xCD,0xBD,0xBF,0xFF,
+    0x85,0x51,0x23,0x41,0xA9,0x8B,0x8B,0x2A,0x85,0x51,0x64,0x49,0x09,0xCA,0xF2,0x2E,
+    0x06,0x62,0x64,0x51,0xAF,0x39,0xAD,0x2F,0xC9,0x7A,0x26,0x62,0xBD,0xA5,0xAD,0x2D,
+    0xE9,0x7A,0xA9,0x72,0x25,0x21,0xAA,0xAC,0x0A,0x83,0xA9,0x7A,0x28,0xA2,0x5A,0x6A,
+    0x0A,0x83,0xC9,0x7A,0xB0,0xA1,0xB5,0xBD,0x0A,0x83,0xC9,0x7A,0xAB,0xFF,0xEB,0x7F,
+    0x0A,0x83,0xC9,0x7A,0xEC,0x02,0x23,0x2D,0x2B,0x83,0xC9,0x7A,0xAF,0xFF,0xA0,0xA0,
+    0x2B,0x83,0xA9,0x7A,0x8B,0xFA,0x7A,0xF0,0x0A,0x83,0xC9,0x7A,0x6E,0xBA,0x01,0x29,
+    0x2A,0x83,0xEA,0x82,0x8D,0x8D,0xA2,0xF0,0x6C,0x8B,0x0A,0x83,0x09,0xB5,0xBD,0xB7,
+    0xAD,0x93,0x0A,0x83,0x0A,0xAF,0x9F,0xD7,0x6F,0xAC,0x0A,0x83,0x02,0xAF,0xFF,0xFD,
+    0xD0,0xBC,0x4B,0x8B,0x00,0x2A,0xAF,0xF5,0x10,0xBD,0x0D,0xA4,0x20,0xA8,0xCB,0xF5,
+    0xCF,0xB4,0x4E,0xAC,0x5C,0x7C,0xFA,0x7F,0x8F,0xB4,0x4E,0xAC,0x69,0xB1,0x2F,0xD7,
+    0xAF,0xB4,0x4E,0xAC,0x7F,0x9B,0xD3,0xB3,0x8F,0xB4,0x4E,0xAC,0xD7,0x7F,0xBE,0x88,
+    0x8F,0xB4,0x4E,0xAC,0x57,0x3A,0x8A,0xCA,0x6E,0xAC,0x2D,0xA4,0xB6,0xBC,0x2C,0x2A,
+    0x8F,0xAC,0x4E,0xAC,0x5E,0x7F,0x6B,0xAF,0xAE,0xAC,0x4E,0xAC,0x5D,0xFD,0x7D,0xFE,
+    0x8F,0xB4,0x2D,0xA4,0xBA,0xB9,0xAB,0xA0,0xAF,0xAC,0x4D,0xAC,0x9F,0xF5,0xF7,0xFF,
+    0x6E,0xB4,0x4E,0xA4,0x2A,0xEA,0xF8,0xF8,0x8F,0xAC,0x4E,0xAC,0x5E,0x5D,0xF9,0x6A,
+    0x23,0x49,0xC2,0x40,0xFE,0xBA,0xFE,0xE7,0x02,0x41,0xC2,0x38,0xBF,0xEE,0xBF,0xBA,
+    0x03,0x41,0xE2,0x40,0x0B,0x01,0x81,0xAA,0x23,0x41,0xE2,0x40,0x27,0xB9,0x0F,0xFD,
+    0x23,0x49,0xE2,0x40,0xBF,0x2F,0x87,0x39,0x23,0x49,0xE2,0x38,0xE8,0x58,0xDF,0x96,
+    0x23,0x41,0xC2,0x40,0xB9,0xAB,0xBA,0xB8,0x03,0x41,0xC2,0x38,0xAB,0x7F,0xD8,0x5C,
+    0x03,0x41,0xC2,0x38,0x8B,0xC1,0xF3,0x5E,0x03,0x41,0xA1,0x38,0xAF,0xA8,0x02,0x2F,
+    0x03,0x41,0xC2,0x38,0xEF,0xA2,0x60,0xAA,0x03,0x41,0xC2,0x38,0x37,0x82,0xC3,0xAF,
+    0x03,0x41,0xC2,0x38,0x3E,0xFA,0xF9,0xBF,0x03,0x41,0xC2,0x38,0xC2,0x68,0x4E,0xFF,
+    0x02,0x41,0xA1,0x38,0x3D,0xAE,0xAE,0xAA,0x03,0x41,0xC2,0x38,0x02,0xB2,0xAD,0x8E,
+    0x03,0x41,0xE2,0x38,0x7F,0x7F,0xED,0xAD,0x02,0x41,0xC1,0x38,0xE9,0x38,0xF2,0xEB,
+    0xE2,0x40,0xC2,0x38,0xDA,0xF0,0x02,0x0B,0x02,0x41,0xC2,0x38,0xEE,0xF7,0x5E,0x9A,
+    0xE2,0x40,0xC2,0x38,0x08,0x2C,0x1B,0x02,0xE2,0x40,0xC2,0x38,0x27,0xA2,0xE0,0xCA,
+    0x03,0x49,0xE2,0x38,0xB6,0xB7,0xBF,0xAD,0x46,0x6A,0x43,0x49,0x0B,0x09,0x0D,0x0D,
+    0x86,0x72,0x25,0x6A,0xFE,0xFE,0x6A,0x60,0x26,0x6A,0xE5,0x61,0xF8,0x7C,0x70,0x12,
+    0x05,0x62,0x23,0x41,0x70,0xE0,0xE8,0xA0,0x23,0x41,0xC2,0x30,0xAA,0x98,0xD8,0xF8,
+    0x03,0x39,0xE2,0x30,0xEF,0xEA,0x7A,0x5B,0x03,0x39,0xE2,0x30,0xAB,0x2D,0x35,0x95,
+    0x24,0x39,0xC3,0x30,0xFE,0x9E,0xF2,0xFA,0x03,0x39,0xE3,0x30,0xE8,0x6E,0xE3,0xEE,
+    0x23,0x39,0xE3,0x38,0x2B,0xBD,0xEF,0xFD,0x23,0x39,0xE2,0x38,0xA8,0x08,0xBE,0x7F,
+    0x23,0x39,0xE2,0x38,0x02,0x0E,0xAF,0xAB,0x44,0x39,0xE3,0x30,0xCA,0x8A,0xF7,0xBE,
+    0x44,0x41,0xE3,0x30,0xE2,0xAA,0x3A,0xBF,0x64,0x41,0xE3,0x30,0x7D,0x7B,0xF0,0xE2,
+    0x44,0x41,0xE3,0x30,0xF5,0x55,0xFB,0xA2,0x24,0x39,0xE3,0x30,0x2B,0x87,0x5B,0x7B,
+    0x24,0x39,0xE3,0x30,0xA0,0xA8,0xEB,0xB9,0x24,0x39,0xE3,0x30,0x7A,0xFA,0xBE,0xB2,
+    0x24,0x39,0xE3,0x30,0xE7,0xFE,0xBA,0xBA,0x23,0x39,0xE3,0x30,0x1F,0xBB,0xA2,0x80,
+    0x44,0x39,0xE3,0x30,0xFC,0xDF,0xD5,0xFB,0x24,0x39,0xE3,0x30,0x82,0xAA,0xBD,0xAE,
+    0x23,0x39,0xE2,0x30,0x8A,0x3A,0xAB,0xED,0x24,0x39,0xE3,0x30,0x7F,0xFC,0xFC,0xFE,
+    0x24,0x39,0xC2,0x30,0x4B,0x8A,0x8A,0xAE,0x03,0x39,0xE3,0x30,0x59,0x82,0x06,0x25,
+    0x24,0x39,0xC2,0x28,0x5B,0xFB,0xA2,0xE2,0x03,0x31,0xC2,0x28,0xF5,0xFF,0xEE,0xA8,
+    0xE3,0x30,0xC2,0x28,0xBA,0xEA,0xE7,0xA8,0x03,0x31,0xC2,0x28,0x4B,0xBD,0xB5,0xAF,
+    0x03,0x31,0xC2,0x28,0xAF,0xDE,0x94,0xF8,0x03,0x31,0xC3,0x28,0x5A,0xFA,0xFE,0xBE,
+    0x03,0x31,0xC3,0x28,0x75,0x55,0xDE,0x6B,0xE3,0x28,0xA2,0x20,0xDE,0xBE,0xBA,0xAA,
+    0xC3,0x28,0x82,0x20,0x8A,0xE0,0x40,0x80,0xC2,0x28,0x82,0x20,0x7A,0xAA,0xAA,0x30,
+    0xC2,0x28,0xA2,0x20,0x7D,0x35,0xAB,0xEC,0xC3,0x28,0x82,0x20,0x57,0xDC,0xD8,0x7B,
+    0xC3,0x28,0x82,0x20,0x5E,0x5F,0xFB,0x2A,0xC2,0x28,0x62,0x18,0xAF,0xAB,0xEA,0xA8,
+    0xA2,0x28,0x62,0x20,0x3A,0xF8,0xBE,0xBE,0xA2,0x28,0x82,0x20,0xA0,0xEE,0xEF,0xDF,
+    0xC3,0x30,0x81,0x20,0x0B,0x2B,0xBF,0xED,0x03,0x31,0xA2,0x28,0x80,0x22,0xFB,0x55,
+    0xE3,0x30,0xA2,0x28,0xC0,0xC0,0xE3,0xA5,0xE3,0x30,0xA2,0x28,0x9F,0xFB,0x6B,0xEE,
+    0x03,0x39,0xA2,0x28,0x2B,0x2F,0xAD,0xEF,0x03,0x39,0xC2,0x30,0xFA,0x8A,0x8B,0xAB,
+    0x03,0x39,0xE3,0x30,0xFD,0xAE,0x23,0x02,0x03,0x39,0xA2,0x28,0xA2,0xEA,0xEA,0x7E,
+    0xC2,0x30,0x81,0x28,0x08,0x8A,0xEB,0xEA,0x03,0x39,0xA1,0x30,0xAA,0x2F,0xEB,0xAD,
+    0x44,0x41,0xC2,0x30,0x02,0x2B,0xEF,0xD7,0x65,0x49,0xE2,0x30,0xA0,0xA2,0xAF,0xD5,
+    0x65,0x49,0x03,0x39,0xF2,0xF2,0x8B,0xE9,0x24,0x41,0xA2,0x30,0x72,0xE8,0xE8,0xFA,
+    0xE3,0x30,0x82,0x28,0xFE,0xDF,0xFA,0xB8,0xE3,0x30,0x81,0x28,0x09,0xAF,0xBB,0xAE,
+    0x03,0x39,0xA2,0x28,0x8B,0xBB,0xF6,0xBF,0x03,0x39,0xA2,0x28,0xFE,0xAE,0xFA,0x72,
+    0xC2,0x30,0x82,0x28,0xFE,0xEC,0x98,0xF8,0xC2,0x30,0x81,0x28,0x37,0xF6,0xE2,0xA0,
+    0xE2,0x30,0xA2,0x28,0xA6,0xAB,0x89,0xAD,0xE2,0x30,0xA1,0x28,0xF5,0xF5,0xEE,0xA8,
+    0xE2,0x30,0x82,0x28,0xB9,0xEA,0xBA,0x02,0xE3,0x30,0xA1,0x28,0x5A,0xB3,0xEA,0xEA,
+    0xC2,0x28,0x81,0x28,0x05,0xAF,0xBF,0xBE,0x23,0x39,0xC2,0x28,0x25,0xF5,0x5D,0xD7,
+    0x24,0x39,0xC3,0x30,0x36,0xAB,0xE9,0xEE,0x23,0x39,0xC2,0x30,0x0F,0xF9,0x5F,0xEF,
+    0x23,0x39,0xE2,0x30,0x38,0x0D,0x2B,0x03,0x64,0x49,0x23,0x41,0xB5,0x05,0xA5,0xD5,
+    0x63,0x49,0x03,0x39,0xFF,0xFF,0xEF,0xFC,0x44,0x49,0x03,0x41,0xF5,0x05,0xFD,0x97,
+    0xA5,0x51,0x23,0x41,0x2F,0x2F,0x2D,0x35,0x47,0x6A,0x84,0x49,0xF5,0xBD,0xA7,0x0F,
+    0x68,0x6A,0xC5,0x59,0xF5,0x2D,0x02,0x08,0xC9,0x7A,0x68,0x6A,0x1D,0x9D,0xA9,0x8F,
+    0xE9,0x7A,0xA9,0x72,0xB6,0x27,0xCD,0x0B,0x0A,0x83,0xC9,0x7A,0x5A,0x62,0x59,0x55,
+    0xE9,0x7A,0xA9,0x7A,0x8A,0x8E,0xAA,0xFE,0x0A,0x83,0xA9,0x72,0x3D,0xAF,0x03,0xB8,
+    0x0A,0x83,0xA9,0x72,0x89,0x8E,0xBB,0xEB,0x2A,0x83,0xC8,0x7A,0x20,0xEA,0xAB,0x2D,
+    0x4B,0x8B,0xEA,0x7A,0xE3,0xEE,0xDE,0xFA,0x2A,0x83,0xEA,0x7A,0xBF,0xBE,0x8B,0xAB,
+    0x4B,0x8B,0xEA,0x7A,0xBF,0x8F,0xEE,0x57,0x2A,0x83,0xE9,0x7A,0x28,0x2A,0xEE,0xB7,
+    0x4A,0x8B,0xE9,0x7A,0xF8,0xFB,0xF3,0xFB,0x4B,0x8B,0xEA,0x7A,0x01,0xBB,0x3A,0xB8,
+    0x6B,0x8B,0x0A,0x83,0x02,0xFE,0xD7,0xDE,0xEC,0x9B,0x2A,0x83,0x0A,0xBB,0x9D,0x75,
+    0x2D,0xA4,0x29,0x83,0x00,0x2A,0xFF,0x55,0x4E,0xAC,0x6B,0x8B,0x00,0x00,0x2B,0xDD,
+    0x8F,0xB4,0xCD,0x9B,0x00,0x0A,0x0A,0xA9,0xAF,0xB4,0x4E,0xAC,0xEE,0x8A,0xAA,0x7F,
+    0x8F,0xB4,0x6E,0xAC,0x7D,0xAD,0xA2,0x6E,0x8F,0xB4,0x2D,0xA4,0xDA,0xAA,0xA8,0xB2,
+    0x8F,0xB4,0x6E,0xAC,0xD6,0xBC,0xE5,0x3E,0x8F,0xB4,0x4E,0xAC,0x0A,0xAE,0x8E,0xA4,
+    0xAF,0xB4,0x6E,0xAC,0xFF,0x75,0xE7,0xFA,0xAF,0xB4,0x4D,0xAC,0x37,0xA7,0x2A,0xAA,
+    0xAF,0xB4,0x4D,0xAC,0xF7,0x6E,0x28,0x28,0xD0,0xB4,0x6E,0xAC,0x77,0x7E,0xEA,0xAA,
+    0x23,0x41,0xE2,0x40,0x75,0xBD,0xCB,0xA2,0x23,0x41,0xE2,0x40,0x7F,0xEF,0x6C,0xFB,
+    0x03,0x41,0xE2,0x40,0x4B,0xF3,0x53,0x73,0x23,0x49,0xC2,0x38,0xFF,0xFF,0xFF,0x3E,
+    0x23,0x41,0xC2,0x38,0x2B,0x7F,0xEA,0xEF,0x23,0x41,0xC2,0x40,0x3C,0xAF,0xED,0xAD,
+    0x23,0x49,0xC2,0x38,0xFE,0xFF,0xEB,0xE2,0xE2,0x40,0xC2,0x38,0x9C,0xAC,0xEA,0x56,
+    0x02,0x41,0xC2,0x38,0xD5,0xFD,0xEF,0x2F,0x03,0x41,0xA1,0x30,0x35,0xBF,0x2B,0x0A,
+    0x03,0x41,0xE2,0x38,0xEC,0xFE,0xFE,0xF8,0x23,0x41,0xC2,0x38,0xBD,0x37,0xDE,0xBB,
+    0x03,0x41,0xC2,0x38,0xEF,0x8A,0xA2,0xE8,0xE2,0x40,0xC2,0x38,0x27,0x8F,0x02,0x00,
+    0xE2,0x40,0xC2,0x38,0x22,0xAA,0xFE,0xEE,0x03,0x41,0xC2,0x38,0xBB,0xE2,0xDF,0x55,
+    0x03,0x41,0xC2,0x38,0x02,0xCA,0x55,0x79,0x03,0x41,0xA1,0x30,0x8A,0xFF,0xBF,0xAA,
+    0x03,0x41,0xE2,0x38,0x57,0xEC,0xD2,0x5A,0x03,0x41,0xC2,0x38,0xB2,0x82,0x09,0x2D,
+    0x03,0x41,0xC2,0x38,0x8B,0xAF,0xCE,0x62,0xE2,0x40,0xA2,0x38,0xC2,0xE0,0xC8,0x9A,
+    0x02,0x41,0xC2,0x38,0x0D,0x95,0xBF,0x2F,0xA7,0x7A,0x43,0x49,0x29,0xAD,0x2D,0x2D,
+    0x86,0x72,0x46,0x6A,0x6A,0x92,0xE2,0xF6,0x26,0x6A,0x05,0x62,0x90,0xD2,0x70,0x50,
+    0x05,0x62,0x63,0x49,0x60,0x78,0xE0,0x60,0x63,0x49,0xC2,0x30,0x7B,0x7E,0xFC,0x7E,
+    0xE2,0x38,0xC2,0x30,0xBA,0xEF,0x76,0xA2,0x03,0x39,0xC2,0x30,0x97,0xFE,0xAD,0xA7,
+    0x23,0x39,0xE2,0x38,0x55,0x79,0xCB,0x6A,0x23,0x39,0xE2,0x30,0x5D,0xFE,0x2F,0xAA,
+    0x23,0x39,0xE3,0x38,0xEF,0xAF,0x2D,0xEF,0x23,0x39,0xC2,0x38,0x63,0xAA,0xAA,0xAE,
+    0x43,0x41,0x03,0x39,0xF9,0xEF,0x78,0xFE,0x24,0x39,0x03,0x39,0xBC,0x27,0xA5,0x95,
+    0x44,0x41,0x03,0x39,0x06,0x3F,0xBE,0xEA,0x65,0x41,0x03,0x39,0xE3,0xAA,0x2F,0xFA,
+    0x44,0x41,0x03,0x39,0xBA,0xF8,0xFE,0xEE,0x44,0x41,0x03,0x31,0x7B,0xBA,0xE3,0xA0,
+    0x44,0x39,0x03,0x31,0x5D,0x92,0x00,0x88,0x44,0x39,0x03,0x31,0x5D,0x57,0x57,0x78,
+    0x24,0x39,0xE2,0x30,0xAA,0xAA,0xA7,0x9F,0x44,0x39,0xE2,0x30,0xA2,0xAA,0xFF,0xDF,
+    0x23,0x39,0x03,0x39,0xB2,0x22,0xC1,0x79,0x24,0x39,0xE3,0x38,0xEA,0x78,0x70,0xA2,
+    0x03,0x39,0xA2,0x28,0x82,0xA2,0xAC,0xAA,0x24,0x39,0xC3,0x30,0xBF,0xFD,0xBF,0xA8,
+    0x03,0x39,0xE3,0x30,0xAB,0xB0,0xA0,0xA0,0x23,0x39,0xE3,0x30,0xAD,0xAF,0xEF,0xD7,
+    0x24,0x39,0xE3,0x30,0x8A,0xAB,0xDF,0x57,0x23,0x39,0xE3,0x30,0xFE,0xFF,0xA3,0xBF,
+    0x03,0x31,0xE3,0x30,0xDA,0x78,0x5E,0xFE,0x03,0x31,0xA2,0x28,0xAA,0xEA,0xAA,0x08,
+    0x24,0x39,0xC2,0x28,0x7F,0x7F,0xDB,0x62,0x23,0x31,0xE3,0x30,0xF5,0x7F,0xFF,0x73,
+    0x24,0x31,0xC2,0x28,0xEC,0xE2,0xEB,0x7F,0xE3,0x28,0xC3,0x28,0xD7,0xBE,0x5E,0x57,
+    0x04,0x31,0xC3,0x28,0x7F,0x5E,0xEB,0x2C,0xE3,0x28,0xC3,0x28,0x5F,0xC8,0x62,0x80,
+    0xE3,0x28,0xA2,0x20,0xBF,0x8E,0x8A,0x82,0xE3,0x28,0xA2,0x20,0x6B,0xB2,0xF2,0xAA,
+    0xC2,0x28,0x82,0x20,0xAB,0xF0,0xBA,0xA8,0xC2,0x28,0xA1,0x28,0x6E,0x53,0xB7,0x02,
+    0xC2,0x28,0x82,0x20,0x7F,0x76,0xFE,0x6E,0xC2,0x28,0x82,0x20,0xD5,0xF5,0xBF,0xAB,
+    0xC3,0x28,0x82,0x20,0x6F,0xFA,0xFE,0x5A,0xA2,0x28,0x82,0x20,0xBF,0xAF,0xF6,0xA5,
+    0xC2,0x28,0x82,0x20,0x0E,0xFB,0xFA,0xD5,0xC2,0x30,0xA2,0x28,0x89,0x2B,0x97,0x5B,
+    0xE3,0x30,0xA2,0x28,0xBE,0xBC,0xAF,0x9B,0x03,0x31,0xC2,0x30,0x29,0x29,0x05,0xAB,
+    0x03,0x39,0xE3,0x30,0xFF,0x7C,0xFE,0xFF,0x44,0x41,0x81,0x28,0x7F,0x7F,0x7A,0xEC,
+    0x03,0x31,0xA2,0x30,0x7D,0xFD,0xF5,0xBF,0xE2,0x30,0xA2,0x28,0xA1,0xA7,0xB7,0xFE,
+    0xE3,0x30,0xA2,0x30,0xFF,0xBF,0xAE,0xE2,0x82,0x38,0xE3,0x30,0x77,0xFD,0xF7,0xBF,
+    0x03,0x39,0xC2,0x30,0xA2,0xF2,0x59,0xDD,0xE2,0x30,0xA1,0x30,0xA0,0xF0,0x5A,0x6A,
+    0xC2,0x30,0x81,0x28,0xB8,0x5C,0xFE,0x0F,0xE2,0x30,0xC2,0x30,0xF5,0x6D,0xAD,0xAB,
+    0xE3,0x30,0xA2,0x30,0x1A,0x0E,0x08,0x2A,0xE3,0x30,0xC2,0x30,0x7A,0x72,0x45,0xCA,
+    0xC2,0x30,0xA2,0x28,0xDF,0x66,0xFF,0x48,0xC2,0x28,0xA2,0x28,0x3B,0x8A,0x8B,0xFE,
+    0xE2,0x30,0xA2,0x28,0x2F,0xAD,0x75,0x29,0x23,0x39,0xC2,0x28,0xFF,0xDF,0xB9,0xA2,
+    0x03,0x39,0xC2,0x28,0xAE,0x7E,0xB8,0x28,0x23,0x39,0xC2,0x28,0x5F,0x6A,0xA8,0xA0,
+    0x03,0x31,0xA1,0x28,0x75,0x5F,0xBC,0xAA,0xE3,0x30,0xA2,0x28,0x2B,0x8B,0xAA,0x88,
+    0x03,0x39,0xC3,0x30,0xAA,0xBD,0xFA,0xBE,0x43,0x41,0xE2,0x30,0xB5,0x95,0xFF,0xAA,
+    0x44,0x41,0x02,0x39,0xCE,0x80,0xCA,0xEB,0x64,0x49,0x03,0x39,0xBF,0xCF,0x7B,0x55,
+    0x44,0x49,0xE2,0x38,0xB8,0xAA,0xA5,0x35,0xA5,0x51,0x03,0x41,0x55,0x5D,0xBB,0x2A,
+    0x67,0x6A,0x23,0x41,0xF5,0xBD,0xAF,0x2A,0x67,0x6A,0xC5,0x51,0x25,0x2F,0xAB,0x00,
+    0xA8,0x72,0x47,0x6A,0xBD,0x3F,0xFF,0xEF,0xE9,0x7A,0x67,0x72,0xAB,0x0F,0xE9,0xEF,
+    0xC9,0x7A,0x88,0x72,0x08,0xA8,0x2A,0xBF,0xC9,0x7A,0xA9,0x72,0xC5,0x61,0xFA,0x5C,
+    0xEA,0x7A,0x89,0x72,0x2F,0x3D,0xA5,0xAF,0x0A,0x83,0xA9,0x7A,0x3A,0xB8,0xFA,0xFF,
+    0xE9,0x7A,0xA8,0x7A,0x7A,0x40,0xEE,0x3F,0xE9,0x7A,0xA9,0x72,0x01,0xEF,0xA4,0xB8,
+    0x0A,0x83,0xC9,0x7A,0x8F,0xB5,0xBF,0xFF,0x2A,0x83,0xC9,0x7A,0xAA,0x2A,0x0B,0x25,
+    0x2A,0x83,0xC9,0x7A,0x5E,0xFC,0xEE,0xE2,0x2A,0x83,0xE9,0x7A,0x76,0xD5,0xCD,0xAD,
+    0x0A,0x83,0xEA,0x7A,0xEA,0x02,0x32,0x5F,0x29,0x83,0xEA,0x7A,0xD8,0xEC,0x82,0x03,
+    0x4B,0x8B,0xA8,0x72,0xA0,0x80,0xA2,0xFE,0x4B,0x8B,0xC9,0x72,0x2B,0x3E,0x3F,0xFD,
+    0x4A,0x8B,0x0A,0x83,0xFC,0xEE,0xD5,0xDD,0x8B,0x93,0xE9,0x7A,0x2B,0xAB,0xFF,0x7D,
+    0x0D,0xA4,0x2A,0x83,0x0A,0xBD,0xF5,0x55,0x4E,0xAC,0x2A,0x8B,0x02,0xAB,0xBF,0xF5,
+    0x8F,0xAC,0xAC,0x93,0x00,0x8A,0xA9,0xB5,0x8F,0xAC,0x4E,0xAC,0xA5,0xF5,0xFF,0x55,
+    0x8E,0xB4,0x4E,0xAC,0xAC,0x8B,0xB2,0xFF,0x8E,0xB4,0x4D,0xA4,0xBF,0x1D,0x07,0xAE,
+    0xAF,0xB4,0x6E,0xAC,0x9A,0x2A,0x2B,0x02,0xCF,0xBC,0x6E,0xAC,0xFE,0xFF,0x9F,0xF7,
+    0xAF,0xB4,0x8F,0xAC,0x1B,0x2E,0xE0,0xC0,0xCF,0xB4,0x8F,0xB4,0xCA,0xC0,0xAB,0xF2,
+    0x23,0x49,0xC2,0x38,0xAA,0xFE,0xDD,0xBF,0x23,0x41,0xE2,0x40,0x7B,0x7F,0x9D,0xA7,
+    0x03,0x41,0xE2,0x38,0x95,0x92,0xEA,0xA3,0x23,0x41,0xE2,0x38,0xDA,0x7F,0x5A,0x78,
+    0x02,0x41,0xA2,0x30,0xAE,0xAA,0x2D,0xAE,0x03,0x41,0xA1,0x30,0x0A,0xAC,0xDA,0xFA,
+    0x03,0x41,0xA1,0x30,0xB0,0xA2,0xAF,0xAF,0x03,0x41,0xA1,0x30,0xEF,0xFE,0xBA,0x08,
+    0x03,0x41,0xC2,0x38,0xAB,0xEF,0xAF,0x37,0x03,0x41,0xA2,0x38,0x48,0xBA,0x2B,0x20,
+    0x03,0x41,0xE2,0x38,0xB3,0x5A,0x76,0xAE,0x03,0x41,0xC2,0x38,0xB0,0xB8,0x6E,0x7E,
+    0x03,0x41,0xE2,0x38,0x62,0xCB,0x85,0xAD,0x24,0x41,0xC2,0x38,0xD7,0xD6,0x7F,0xFB,
+    0xE2,0x38,0xC2,0x38,0xFC,0x16,0x15,0x2B,0x23,0x41,0xC2,0x38,0xFF,0x8B,0xBE,0x5F,
+    0x03,0x41,0xA1,0x30,0xE2,0xAB,0xDE,0xAF,0x03,0x41,0xE2,0x38,0xC3,0x63,0x50,0xDC,
+    0x02,0x41,0xE2,0x38,0x5F,0x7D,0x38,0xB9,0x03,0x41,0xC2,0x38,0xB3,0xDB,0x9A,0xAA,
+    0x03,0x41,0xC2,0x38,0xF0,0xC2,0xEE,0xDE,0x03,0x41,0xC2,0x38,0x55,0xED,0x2F,0xAF,
+    0x03,0x41,0xC2,0x38,0xF3,0xE3,0xEA,0xFA,0x67,0x72,0x02,0x41,0x2D,0x2D,0x2D,0x2D,
+    0x87,0x72,0x05,0x62,0xA8,0xE0,0x78,0xFA,0x46,0x72,0xE5,0x61,0xDF,0xB6,0xFF,0xFC,
+    0x05,0x62,0x43,0x49,0xE0,0xE0,0x60,0xE0,0x63,0x41,0xE2,0x38,0x7F,0x5F,0x5E,0xDC,
+    0x03,0x39,0xC2,0x30,0x2A,0x2A,0x8A,0x27,0x03,0x39,0xE3,0x30,0x7B,0xE2,0xBC,0xAE,
+    0x03,0x39,0xE3,0x30,0x1E,0x6E,0x73,0x58,0x23,0x39,0xE2,0x30,0xC0,0xCB,0xE3,0xFA,
+    0x23,0x39,0xE2,0x30,0x6B,0xAA,0x3D,0x95,0x23,0x39,0xE3,0x38,0xD7,0xD7,0xFC,0xD5,
+    0x23,0x39,0xE2,0x30,0x82,0xEA,0xAE,0x7B,0x44,0x41,0xE3,0x30,0xAB,0xAE,0xE7,0xFB,
+    0x23,0x39,0x03,0x39,0x01,0x42,0xC2,0x66,0x44,0x41,0x03,0x39,0xFA,0xAB,0xEB,0xD5,
+    0x44,0x41,0x03,0x39,0x27,0x0F,0xAB,0xAB,0x44,0x41,0xE3,0x30,0x80,0x28,0x36,0xEE,
+    0x44,0x41,0x03,0x39,0xA8,0xE2,0x7A,0xAA,0x44,0x41,0xE2,0x30,0xFE,0xFF,0x6B,0x62,
+    0xE3,0x38,0x03,0x31,0xFF,0x2A,0xAA,0x9E,0x03,0x39,0xE3,0x30,0xFF,0x23,0xAF,0x7E,
+    0x03,0x39,0xC2,0x30,0x0A,0x0E,0x03,0x2B,0x44,0x41,0xE2,0x30,0xAB,0x2F,0xFD,0xE5,
+    0x24,0x39,0xE3,0x38,0x8F,0x8B,0x0F,0xFD,0x44,0x41,0x04,0x39,0xFF,0xE6,0x5A,0x58,
+    0x44,0x41,0xE3,0x30,0xFF,0x7F,0xFA,0xAB,0x24,0x41,0xE3,0x38,0xBF,0xB6,0xF8,0xF8,
+    0x03,0x39,0xC2,0x30,0xE0,0xCA,0xAA,0xA0,0x23,0x39,0xC2,0x30,0x2B,0x2F,0xFF,0x7F,
+    0x23,0x39,0xC2,0x28,0xBA,0x3E,0xF7,0x95,0x03,0x31,0xE3,0x30,0x80,0x78,0xDF,0x75,
+    0x24,0x39,0xE3,0x30,0x7A,0x7B,0xFD,0x65,0x03,0x31,0xC3,0x28,0xBA,0xAF,0xBE,0xB2,
+    0x24,0x39,0xC2,0x28,0x7F,0xFF,0xEF,0xAE,0x03,0x31,0xC2,0x28,0xFF,0xE9,0xCD,0xCA,
+    0x04,0x31,0xC2,0x28,0x2A,0xEF,0xE5,0xEE,0x04,0x31,0xC3,0x28,0x68,0x63,0x69,0xFD,
+    0xE3,0x30,0xC3,0x28,0xDA,0x7D,0x59,0x57,0x03,0x31,0xC3,0x28,0x75,0xDD,0xFD,0xAD,
+    0xE3,0x30,0xA2,0x28,0xF6,0xF7,0x0A,0x0A,0xE3,0x30,0xA2,0x28,0xEF,0xFF,0xFA,0xB8,
+    0xE3,0x30,0xA2,0x28,0x67,0xFD,0xDC,0x38,0xC3,0x28,0xA2,0x28,0x51,0x6B,0x7A,0xC3,
+    0xC3,0x28,0x82,0x20,0x7E,0xFF,0xBF,0xAF,0xA2,0x28,0x82,0x20,0x26,0x26,0x38,0xA8,
+    0xA2,0x20,0x61,0x20,0xFE,0xFA,0xDA,0xAA,0xA2,0x28,0x61,0x18,0x38,0xBF,0x9F,0xFA,
+    0xC2,0x28,0x81,0x20,0xB8,0x37,0xDF,0xDE,0x03,0x31,0xC2,0x28,0xAD,0xE9,0xAD,0x7D,
+    0x23,0x39,0xC2,0x28,0xBF,0xBD,0xAF,0xAF,0x44,0x41,0xA2,0x30,0xFC,0x7E,0x7F,0xFE,
+    0xE2,0x30,0x82,0x30,0x22,0x0A,0xAB,0x22,0xC2,0x30,0xC2,0x28,0x08,0x00,0xA0,0x2A,
+    0x03,0x39,0xA2,0x30,0xEF,0xFD,0xBB,0x2B,0xE2,0x30,0xA1,0x30,0x7F,0xAB,0x00,0xA0,
+    0xE2,0x30,0xC2,0x30,0x1B,0x2F,0x1B,0xD7,0x03,0x39,0xC2,0x30,0x7F,0xF3,0xAB,0x2D,
+    0x02,0x39,0xA2,0x30,0xFF,0xDA,0xE0,0xA0,0x03,0x39,0xC2,0x30,0x7F,0x6E,0xEB,0xDD,
+    0x03,0x39,0xA2,0x28,0xBF,0x1F,0x3F,0xAF,0x03,0x39,0xC2,0x28,0xFE,0xFB,0xF4,0x5F,
+    0xE3,0x30,0xA2,0x28,0xBA,0xF2,0xD7,0xB5,0x03,0x31,0xA1,0x28,0xFE,0x7C,0xEB,0xEA,
+    0x03,0x31,0xA1,0x28,0xA9,0xBF,0x2F,0xAA,0x44,0x41,0xE2,0x30,0xAB,0x0D,0x2D,0xAD,
+    0x44,0x41,0x03,0x39,0x5E,0x5C,0x78,0x3E,0x85,0x49,0x03,0x39,0x5D,0xED,0xA7,0x8E,
+    0x44,0x41,0xE2,0x30,0x55,0x5F,0x78,0xE8,0x44,0x41,0xE3,0x30,0x57,0xFF,0xEB,0x0B,
+    0x23,0x39,0xE3,0x30,0xD5,0xE7,0xA3,0x88,0x43,0x41,0x03,0x39,0xFE,0xAB,0xAF,0xE7,
+    0x43,0x41,0x03,0x39,0xA2,0x02,0x0B,0x0D,0x64,0x49,0x02,0x39,0xD7,0x97,0xA3,0xEF,
+    0xC5,0x51,0x23,0x41,0xD5,0xAF,0x2F,0x2B,0x06,0x5A,0x64,0x51,0xB5,0x8F,0xAE,0x03,
+    0x67,0x6A,0x06,0x5A,0xB5,0xBF,0xFB,0xBD,0x67,0x6A,0x27,0x62,0x28,0x08,0x88,0x2F,
+    0xA9,0x6A,0x47,0x6A,0xFA,0xB6,0x3F,0xAF,0xC9,0x72,0x67,0x6A,0x8D,0xB7,0xEE,0x8B,
+    0xC9,0x7A,0x68,0x6A,0x1F,0xEB,0x8A,0x2E,0xC9,0x72,0x68,0x72,0xEA,0xAF,0x4A,0xAA,
+    0xEA,0x7A,0x68,0x72,0x2A,0x02,0x2B,0xD7,0xE9,0x7A,0xA9,0x7A,0xB7,0xFD,0xED,0x29,
+    0x0A,0x7B,0x88,0x72,0xDF,0x5F,0xFE,0xA8,0x2A,0x83,0xA8,0x72,0xFF,0x35,0xDD,0xFF,
+    0x0A,0x83,0xA9,0x72,0x2A,0x2A,0xAB,0xDE,0x0A,0x83,0xC9,0x7A,0xB7,0xB0,0x80,0x8D,
+    0x2B,0x83,0xC9,0x7A,0x7E,0x6D,0x5C,0xFB,0x0A,0x83,0xA9,0x72,0xAB,0xDB,0xDE,0x2A,
+    0x0A,0x83,0xA8,0x7A,0x4A,0xF9,0xBF,0xF8,0x09,0x7B,0xA9,0x7A,0x82,0xAA,0x2A,0x9E,
+    0x2A,0x83,0xC9,0x7A,0x5F,0xA8,0xA2,0xAB,0x2A,0x83,0xC9,0x7A,0x75,0xD7,0xAA,0xAC,
+    0x2B,0x83,0xE9,0x7A,0x9B,0xA6,0xFF,0x22,0x2A,0x83,0xC9,0x7A,0xE8,0xEE,0x7A,0x62,
+    0x0A,0x83,0xC9,0x7A,0x08,0xE2,0x0D,0xAF,0x4B,0x8B,0xC9,0x7A,0x02,0xDD,0x7E,0x76,
+    0xAC,0x9B,0x0A,0x7B,0x2A,0xBD,0x75,0xD5,0x2D,0xA4,0x0A,0x83,0x02,0xAF,0xFF,0x5D,
+    0x6E,0xAC,0x4B,0x8B,0x02,0x0A,0xBD,0xF5,0x8E,0xAC,0xAC,0x93,0x20,0x00,0xAA,0xFD,
+    0x8F,0xB4,0x2D,0xA4,0xA8,0x2A,0x2B,0x09,0xAF,0xB4,0x6E,0xAC,0xF7,0xBA,0xB8,0xAB,
+    0xF0,0xB4,0x8F,0xB4,0xDB,0xF7,0xD7,0xFD,0xAF,0xB4,0x8F,0xB4,0x20,0x88,0x0E,0x02,
+    0x44,0x41,0xE2,0x40,0xFD,0xBD,0xF7,0xDF,0x23,0x49,0xC2,0x38,0xAB,0xA7,0xEA,0x8A,
+    0x43,0x49,0xC2,0x38,0xFB,0xF7,0x9E,0xE3,0x03,0x41,0xC2,0x38,0x78,0x6A,0xCA,0xCC,
+    0x22,0x39,0xC2,0x38,0xDF,0x79,0xFF,0xD7,0xE2,0x38,0xC2,0x38,0x1F,0xAF,0x36,0xB0,
+    0x03,0x41,0xC2,0x38,0xCB,0x96,0x52,0x7F,0x03,0x41,0xC2,0x38,0x0F,0x2E,0xEA,0xEE,
+    0x03,0x41,0xA1,0x30,0x36,0xBE,0xAB,0xA2,0x02,0x41,0xC2,0x38,0x38,0xF8,0xEB,0xEA,
+    0x22,0x39,0xC2,0x38,0xF7,0xF6,0xFC,0xFA,0x02,0x39,0xC2,0x38,0x96,0xDE,0xD4,0xBE,
+    0x02,0x41,0xC2,0x38,0xA6,0x25,0x8A,0xAA,0x03,0x41,0xC2,0x38,0xA7,0xB7,0xF7,0xBF,
+    0x03,0x41,0xC2,0x38,0xA2,0x60,0x6E,0xFA,0x03,0x41,0xA1,0x30,0x9E,0xFB,0xE2,0xEA,
+    0x03,0x39,0xC2,0x38,0xDB,0x27,0x03,0xBF,0x23,0x39,0xC2,0x38,0xFE,0x5F,0xF7,0xFD,
+    0x03,0x41,0xE2,0x38,0x9A,0xB5,0xA9,0x47,0x03,0x41,0xC2,0x38,0xCF,0xEF,0x8A,0x8F,
+    0xE2,0x38,0xC2,0x30,0x88,0x2E,0x1A,0x2E,0x03,0x41,0xC2,0x38,0x2F,0xB5,0xDE,0xEF,
+    0xE2,0x40,0xA2,0x38,0x00,0xB8,0xFA,0xBE,0x66,0x72,0x23,0x49,0x2D,0x2D,0x2D,0x2D,
+    0x66,0x72,0x05,0x62,0xF0,0x42,0x4A,0xE8,0x26,0x6A,0x06,0x62,0x54,0x5E,0xFE,0x80,
+    0x46,0x6A,0x84,0x51,0xFE,0x58,0xFA,0xFA,0x64,0x49,0xE2,0x38,0xDE,0x5A,0x7E,0x58,
+    0x03,0x39,0xC2,0x30,0x03,0x02,0xB8,0xD8,0x23,0x39,0xC2,0x30,0xBF,0xF8,0x7C,0x5A,
+    0x03,0x39,0xC2,0x30,0x5A,0x5F,0x55,0xD5,0x03,0x39,0xC2,0x30,0xED,0xAF,0xEB,0xEB,
+    0x24,0x39,0xC2,0x30,0x36,0xBF,0xFB,0xBF,0x03,0x39,0xE2,0x30,0xEF,0xF0,0xBD,0x97,
+    0x03,0x39,0xA1,0x28,0xA2,0xAA,0xBC,0x78,0x23,0x39,0xC2,0x30,0xE2,0xA2,0xFF,0x6D,
+    0x03,0x39,0xC2,0x30,0xAA,0x22,0x2A,0xFD,0x23,0x39,0xC2,0x30,0x8A,0x00,0x2A,0x2B,
+    0x44,0x41,0x03,0x39,0xA2,0xED,0x7E,0xB3,0x24,0x39,0xE2,0x38,0xF2,0x22,0xB0,0x88,
+    0x44,0x41,0xE3,0x38,0xA0,0xA0,0xBB,0xF6,0x44,0x41,0xE3,0x38,0x6A,0x6A,0x2A,0xBB,
+    0x23,0x39,0xE3,0x38,0xF5,0xE5,0x7F,0xA2,0x03,0x39,0xC2,0x30,0x0E,0x2A,0x80,0x6A,
+    0x24,0x39,0xC2,0x30,0x2D,0x2E,0xAF,0x3F,0x44,0x41,0xE3,0x30,0xE7,0xFF,0xFD,0xA5,
+    0x24,0x39,0xC2,0x30,0xFF,0x7F,0xFF,0xAA,0x03,0x39,0xE3,0x30,0x03,0x09,0x81,0x0B,
+    0x44,0x41,0xC2,0x30,0x0A,0xAF,0xFE,0x7F,0x44,0x41,0x04,0x39,0x5A,0x32,0xCF,0xAF,
+    0x44,0x41,0xE3,0x38,0x56,0x7E,0xE8,0xEE,0x23,0x39,0xE3,0x30,0x7F,0xD7,0xFD,0xAA,
+    0x03,0x39,0xC2,0x28,0x2B,0x08,0x70,0xA0,0x23,0x39,0xE3,0x30,0x5F,0x7E,0x6C,0xAD,
+    0x03,0x31,0xC3,0x30,0xBB,0x3E,0x22,0xA0,0x23,0x39,0xE3,0x30,0xBF,0x3F,0xDF,0xAF,
+    0x24,0x39,0x03,0x31,0x55,0x5C,0xFE,0x8B,0x23,0x31,0xE3,0x30,0x67,0xCD,0xEB,0xE0,
+    0x04,0x31,0xE3,0x30,0x7D,0xB7,0x28,0xD6,0x03,0x31,0xC2,0x28,0x5A,0xF8,0xEC,0xAE,
+    0xE3,0x30,0xC2,0x28,0x57,0x56,0x5A,0x0A,0xE3,0x30,0xC2,0x28,0xAF,0x0D,0xED,0x28,
+    0x03,0x31,0xC2,0x28,0x97,0xDC,0xEF,0xFA,0xE3,0x30,0xC2,0x30,0xF0,0x72,0xAA,0xE3,
+    0xE3,0x30,0xC2,0x28,0xB4,0x67,0xFF,0x2B,0xE3,0x30,0xA2,0x28,0xFF,0xFB,0xEB,0xE8,
+    0xE2,0x28,0xA2,0x20,0xF7,0xEB,0xEA,0xAA,0x82,0x28,0xA2,0x20,0xDF,0xFD,0xFD,0x5F,
+    0xC2,0x28,0xA2,0x20,0x5D,0xA5,0xD5,0x5C,0xC2,0x28,0x81,0x20,0x6E,0xF2,0x68,0xA7,
+    0xC2,0x28,0x81,0x20,0xDF,0xD7,0x7E,0x80,0xC2,0x28,0x81,0x20,0x23,0xBF,0x5F,0x7F,
+    0x03,0x39,0x81,0x20,0x0A,0x22,0xAD,0xB5,0x24,0x39,0xC2,0x30,0xEC,0xAA,0x2F,0xBD,
+    0x24,0x39,0xC2,0x30,0x5D,0x75,0xEE,0x68,0xE2,0x30,0x82,0x28,0x7F,0xFE,0xAA,0x00,
+    0xE3,0x38,0xC2,0x28,0x2B,0xA9,0x0B,0xAB,0x03,0x39,0xE2,0x30,0x9E,0xAE,0xBF,0x5D,
+    0xE2,0x30,0xC2,0x30,0x57,0xFD,0xAF,0x9A,0x02,0x39,0xC2,0x30,0x3D,0xAD,0xA3,0xBF,
+    0x03,0x39,0xC2,0x30,0xFA,0x5E,0xEF,0xAE,0xE3,0x30,0xC2,0x30,0x57,0x9F,0xD5,0x57,
+    0x23,0x39,0xC2,0x30,0xFF,0x77,0x5D,0xB5,0x03,0x31,0xA2,0x28,0xF2,0x7A,0xF2,0xF8,
+    0xE3,0x30,0xA2,0x28,0x9F,0xB5,0x0F,0x8A,0x03,0x31,0xC2,0x30,0x83,0xAA,0x82,0x0B,
+    0x03,0x39,0xE2,0x30,0x5C,0x99,0xB6,0xD7,0x23,0x39,0xE2,0x30,0xB5,0xF7,0x87,0xAB,
+    0x43,0x39,0xE2,0x30,0x2A,0xBE,0xBE,0xFA,0x64,0x41,0x03,0x39,0x80,0xFB,0x7F,0x7B,
+    0x44,0x41,0xE2,0x30,0xE8,0xAE,0xFE,0xFF,0x44,0x39,0xE2,0x30,0x8F,0xFE,0x29,0xB7,
+    0x23,0x39,0xC2,0x30,0x00,0x88,0x70,0xAA,0x23,0x39,0xE2,0x30,0xE7,0xD4,0xA6,0x0E,
+    0x64,0x41,0x03,0x39,0xF1,0x7B,0x75,0x55,0x64,0x49,0xE2,0x38,0x2D,0xAF,0xA9,0x2F,
+    0xE6,0x59,0x64,0x49,0xA9,0xAD,0xCF,0x29,0x26,0x62,0xC5,0x51,0xD9,0xF9,0xE2,0xFA,
+    0x47,0x62,0xE6,0x59,0x3F,0xB7,0x97,0xB5,0x68,0x6A,0xE6,0x59,0x22,0x03,0xB7,0xAE,
+    0xA9,0x72,0x47,0x6A,0xB5,0x9F,0xBF,0x2D,0xC9,0x72,0x68,0x6A,0xAA,0xFA,0xEA,0x6B,
+    0xC9,0x72,0x88,0x6A,0xB5,0xDA,0xBA,0x4E,0xC9,0x7A,0x88,0x6A,0xEE,0xEB,0x0F,0x35,
+    0xC9,0x7A,0x88,0x72,0xD7,0xED,0xE2,0x30,0xEA,0x82,0x88,0x72,0x2D,0xA7,0xB7,0xF7,
+    0x0A,0x83,0xA9,0x72,0x0A,0xAF,0xB7,0xFD,0xE9,0x7A,0xA9,0x72,0xF2,0x40,0x6A,0xFD,
+    0xC9,0x7A,0x88,0x72,0x38,0x3A,0x8B,0xC3,0x0A,0x83,0xC9,0x7A,0xA7,0xE7,0x66,0xD5,
+    0xEA,0x82,0x88,0x72,0x08,0xAA,0x5E,0xAB,0x2B,0x8B,0xC9,0x7A,0xBF,0xAF,0x35,0x2D,
+    0x2A,0x83,0xEA,0x7A,0x58,0x5E,0x58,0x57,0x0A,0x83,0xC9,0x7A,0x55,0x5B,0x90,0xF0,
+    0x0A,0x83,0xA9,0x72,0x02,0xBE,0x37,0xB5,0x2B,0x83,0xC9,0x7A,0xA2,0xA8,0xE2,0x5E,
+    0x0A,0x83,0xEA,0x7A,0xC3,0x57,0x57,0x7E,0x2B,0x83,0xEA,0x82,0x83,0x3D,0x09,0xEB,
+    0x2A,0x83,0xC9,0x7A,0x7B,0xFA,0xFC,0x6A,0x0A,0x83,0xC9,0x7A,0xFC,0xCA,0xAA,0xE8,
+    0x2A,0x83,0xEA,0x7A,0x9D,0xB5,0x5F,0x5F,0x2A,0x83,0xEA,0x7A,0xAA,0xB7,0x69,0x7F,
+    0x6B,0x8B,0xE9,0x7A,0x0B,0x2F,0xF5,0x5F,0xAC,0x93,0xE9,0x7A,0x00,0x2A,0xAD,0x55,
+    0x4E,0xAC,0x4B,0x8B,0x0A,0xAB,0xFD,0x55,0x6E,0xAC,0x8C,0x93,0x00,0x0A,0x2F,0xD5,
+    0x8F,0xB4,0xED,0x9B,0x00,0x00,0x02,0xBD,0xF0,0xBC,0x6F,0xAC,0xAA,0x8B,0xEB,0xFD,
+    0x23,0x41,0xE2,0x40,0xFD,0xDB,0x0B,0x80,0x23,0x49,0xE2,0x40,0xA2,0x5E,0x58,0x50,
+    0x03,0x41,0xC2,0x38,0x00,0xA2,0xEE,0x0A,0x03,0x41,0xA1,0x30,0xF8,0x62,0xA0,0xB0,
+    0x03,0x41,0xC2,0x38,0x95,0x2D,0xEB,0xFE,0x23,0x41,0xE2,0x38,0xD7,0xF5,0x65,0xBB,
+    0x03,0x41,0xE2,0x38,0xD7,0x35,0x1B,0xC1,0x23,0x41,0xE2,0x38,0x77,0x6A,0xEF,0x6F,
+    0x03,0x41,0xC2,0x38,0xA3,0xBF,0xFB,0x7A,0x02,0x39,0xC2,0x38,0xAA,0xBA,0x20,0xBD,
+    0x03,0x41,0xC2,0x38,0x78,0xD4,0x7E,0xFE,0xE2,0x38,0xC2,0x38,0x3E,0xBD,0x33,0x6E,
+    0x03,0x41,0xC2,0x38,0xAA,0xA2,0x82,0xBD,0xE2,0x38,0xC2,0x38,0xCA,0xC0,0x00,0x02,
+    0x23,0x41,0xC2,0x38,0xFF,0xFB,0x5F,0x75,0x02,0x39,0xC2,0x38,0x55,0xF7,0xBF,0x8F,
+    0x03,0x41,0xC2,0x38,0xF4,0x7C,0x7B,0xA2,0x23,0x39,0xC2,0x38,0xB5,0xF5,0xFF,0xFF,
+    0xE2,0x38,0xA1,0x30,0x20,0x04,0x8A,0x28,0x03,0x39,0xC2,0x38,0xFF,0x2F,0x0F,0xCD,
+    0x02,0x41,0xE3,0x38,0xD7,0x55,0x5B,0x5D,0x03,0x41,0xA2,0x30,0x8D,0xAF,0x7E,0xEB,
+    0xE3,0x40,0xA2,0x38,0xBF,0xA8,0x22,0x0D,0x67,0x72,0x23,0x49,0x2D,0x2D,0x2D,0x09,
+    0x66,0x72,0x26,0x6A,0x55,0xE8,0x80,0x12,0x66,0x72,0x06,0x62,0xFA,0xDA,0xB8,0xFA,
+    0x46,0x6A,0x64,0x49,0xF8,0x7A,0x7E,0xDA,0x64,0x49,0xE2,0x38,0x5C,0x76,0x7E,0x5F,
+    0x23,0x39,0xE2,0x30,0xD5,0x97,0xFA,0x7F,0x23,0x39,0xA2,0x30,0xBA,0xA8,0xAE,0x7F,
+    0x03,0x39,0xE3,0x30,0x57,0x62,0xA2,0x0B,0x03,0x31,0xA2,0x30,0xAB,0x2A,0x02,0x2A,
+    0x03,0x31,0xC2,0x30,0xFE,0xE7,0x96,0xFE,0x24,0x39,0xE3,0x30,0xFB,0xBF,0xBD,0xFD,
+    0x03,0x39,0xC2,0x30,0x78,0x66,0xD4,0xFE,0x03,0x39,0xC2,0x30,0x27,0x2B,0x0F,0x8A,
+    0x03,0x39,0xC2,0x30,0xCA,0x6B,0xAA,0x80,0x03,0x39,0xC2,0x30,0x29,0xAF,0xBA,0x2A,
+    0x44,0x41,0xE2,0x30,0x8B,0xC7,0xD5,0x55,0x23,0x39,0xE3,0x38,0xCB,0xFE,0xBC,0xFC,
+    0x23,0x39,0xE3,0x38,0xFE,0xA7,0xEB,0xBA,0x03,0x39,0xE3,0x30,0x00,0xA2,0x22,0x20,
+    0x24,0x39,0xE3,0x38,0x3A,0x8A,0xDA,0x58,0x44,0x41,0xE3,0x30,0x74,0x7F,0x5F,0xFB,
+    0x23,0x39,0xC2,0x30,0x2F,0xFF,0xFF,0xFE,0x24,0x41,0xE2,0x30,0x27,0xE1,0xFF,0xBF,
+    0x44,0x41,0x03,0x39,0x53,0x7F,0xD5,0xF7,0x44,0x41,0x04,0x39,0x55,0x5F,0xE8,0xAA,
+    0x24,0x39,0xE3,0x38,0x6B,0x82,0xF8,0xBC,0x23,0x39,0xE3,0x38,0xAB,0xF7,0xBF,0x8F,
+    0x23,0x39,0xC2,0x30,0x8A,0x3E,0x26,0xAA,0x23,0x39,0xE3,0x38,0xAA,0xAA,0xFE,0x56,
+    0x24,0x39,0x03,0x39,0x55,0xBE,0x3B,0x95,0x24,0x39,0xE2,0x30,0xAA,0x20,0x2C,0x9E,
+    0x24,0x39,0xE3,0x30,0x5A,0xD8,0xFE,0xBF,0x24,0x39,0xE3,0x30,0xDF,0x7F,0xDF,0x60,
+    0x03,0x31,0xC2,0x30,0x02,0x2A,0xAA,0xF7,0x24,0x31,0xC2,0x30,0xB8,0xBA,0xBD,0xBF,
+    0x23,0x39,0xC2,0x28,0xFB,0xBF,0xAA,0xA3,0x23,0x31,0xE3,0x30,0xD5,0x75,0xDE,0xBE,
+    0x03,0x31,0xC2,0x28,0xBF,0xBF,0xAB,0xAA,0x03,0x31,0xC2,0x28,0x9E,0xDF,0xE8,0xA8,
+    0x03,0x31,0xC2,0x30,0xAA,0x2D,0xEB,0xFA,0x04,0x31,0xA2,0x28,0xE2,0xEC,0x6F,0xEF,
+    0xE3,0x30,0xC2,0x28,0xAF,0xBA,0x2D,0x95,0xE3,0x30,0xC2,0x28,0x6E,0xD7,0x76,0xFC,
+    0xE2,0x30,0xC2,0x28,0x7F,0x67,0x77,0x7D,0xE3,0x30,0xA2,0x28,0x8F,0x82,0xFB,0x9F,
+    0xE2,0x28,0x82,0x20,0xFC,0x7F,0xBF,0xEE,0xC2,0x28,0x82,0x20,0xEF,0xBF,0xAA,0xA2,
+    0x03,0x29,0xA2,0x28,0xF9,0xEF,0xFD,0xDF,0xC2,0x28,0x81,0x20,0x7E,0xFC,0xFF,0xEE,
+    0xA2,0x28,0x81,0x20,0x27,0x95,0xDF,0x7A,0xE3,0x30,0x81,0x20,0x02,0xAF,0xFF,0x5D,
+    0x24,0x39,0x81,0x20,0x8A,0xEB,0xB9,0xF5,0x03,0x31,0xA2,0x28,0xAB,0x2A,0xAA,0xDB,
+    0x23,0x39,0xE2,0x30,0xF5,0x0E,0xB2,0xFB,0x23,0x39,0xC2,0x28,0x5A,0x68,0xEA,0xBA,
+    0x03,0x31,0xA1,0x30,0xBA,0x82,0x82,0xAA,0x02,0x31,0xC2,0x28,0xBD,0xBD,0x7D,0xFE,
+    0x02,0x39,0xA1,0x28,0xAA,0xA8,0xFA,0xE9,0x03,0x39,0xC2,0x30,0xEF,0x7A,0x52,0x5F,
+    0x03,0x31,0xC2,0x30,0x2D,0x07,0x0A,0x02,0x24,0x39,0xC2,0x30,0x7C,0xBA,0xAA,0xF2,
+    0xE3,0x30,0xA2,0x28,0xEA,0x80,0xFA,0x96,0x24,0x39,0xC2,0x28,0xAF,0xA7,0xA7,0x0F,
+    0x03,0x39,0xE3,0x30,0x9F,0xBE,0xB8,0x70,0x03,0x39,0xE3,0x30,0x00,0x0A,0x03,0xBF,
+    0x44,0x41,0x03,0x39,0x5F,0xBF,0x08,0x38,0x65,0x41,0xE3,0x30,0x6F,0xF6,0x5E,0x54,
+    0x03,0x31,0xC2,0x28,0xB0,0xEA,0xF8,0x57,0x03,0x31,0xC2,0x30,0xBF,0xBF,0xDF,0xF9,
+    0x23,0x39,0xC2,0x28,0x2E,0xAE,0x4B,0x5F,0x03,0x31,0xA2,0x28,0x00,0x8A,0xAB,0xA7,
+    0x64,0x41,0xC2,0x30,0xBF,0xBF,0xBD,0x3F,0x85,0x49,0xE2,0x38,0xB9,0x2F,0xA2,0x02,
+    0x07,0x62,0x85,0x49,0xBD,0xAF,0xAB,0xBB,0x47,0x6A,0xE5,0x59,0x5F,0xFF,0xB7,0xBF,
+    0x48,0x6A,0xC6,0x59,0xBF,0x2F,0x25,0x2F,0x68,0x6A,0x27,0x62,0x29,0x0E,0x22,0x02,
+    0xA9,0x72,0x47,0x62,0xA7,0xEE,0xAA,0xAB,0xA8,0x72,0x68,0x6A,0xFF,0x0F,0xE7,0x9B,
+    0xA9,0x72,0x67,0x6A,0x8E,0xBB,0x9A,0x08,0xA9,0x72,0x88,0x6A,0x16,0x0E,0x2E,0x4A,
+    0xC9,0x7A,0x88,0x6A,0xA8,0xBE,0xEF,0xFD,0xA9,0x72,0x68,0x6A,0x8A,0xA0,0x9E,0x2A,
+    0xEA,0x82,0x68,0x6A,0xAE,0xEB,0xEF,0x73,0xE9,0x7A,0x88,0x72,0xFA,0xCA,0xDA,0xFD,
+    0xC9,0x7A,0x88,0x72,0x0A,0x3F,0x2F,0xA3,0x0A,0x83,0x88,0x72,0x30,0xA2,0x6A,0xDF,
+    0xEA,0x7A,0x88,0x72,0xA8,0xBB,0xFB,0x9E,0x0A,0x83,0xA8,0x72,0x2F,0xAF,0xAF,0xD5,
+    0x0A,0x83,0xA9,0x72,0xA2,0xBA,0xDF,0x5F,0x2B,0x83,0xC9,0x7A,0xEA,0xBF,0x15,0x5D,
+    0x0B,0x83,0xCA,0x7A,0xDD,0xFF,0x7E,0xAF,0x0A,0x83,0xC9,0x7A,0x6C,0xFF,0xFF,0x8A,
+    0x2B,0x83,0xC9,0x7A,0x3F,0xED,0xBB,0x71,0x0A,0x83,0xA9,0x7A,0x28,0xBE,0x2B,0x6D,
+    0x4B,0x8B,0xCA,0x7A,0x2A,0x2A,0xEB,0xF5,0x2B,0x8B,0xC9,0x7A,0x60,0x76,0xF2,0xFE,
+    0x0A,0x83,0xC9,0x7A,0x88,0xEE,0xAF,0x9A,0x4B,0x8B,0xE9,0x7A,0x7D,0xFD,0xB3,0x2A,
+    0x2A,0x83,0xC9,0x7A,0xBE,0x77,0xFC,0xD8,0x0A,0x83,0xA8,0x72,0x3F,0x2D,0x8B,0xAE,
+    0x4B,0x8B,0xEA,0x7A,0x0B,0xA7,0xE7,0xBF,0x8C,0x93,0xE9,0x7A,0x2A,0xBB,0xAF,0x7E,
+    0xCD,0x9B,0x0A,0x83,0x02,0xAA,0xBF,0x7D,0x8F,0xB4,0x4B,0x8B,0x2A,0xAB,0xFD,0x55,
+    0x03,0x41,0x23,0x39,0x82,0x00,0x08,0x23,0x23,0x41,0xA2,0x38,0xE8,0x7A,0xF8,0xFE,
+    0x02,0x41,0xC2,0x38,0xBA,0xB9,0x69,0xEA,0xE2,0x38,0xC2,0x38,0xF8,0xBB,0x0B,0x0F,
+    0x02,0x41,0xA2,0x30,0xCA,0xAB,0x83,0x82,0x23,0x41,0xE2,0x38,0xEB,0x6D,0xFC,0xFB,
+    0x23,0x41,0xE2,0x38,0x65,0xD5,0x57,0x95,0x23,0x41,0xC2,0x38,0xFB,0x3B,0xDF,0x5B,
+    0x03,0x41,0xC2,0x38,0xFC,0x58,0x6E,0xFF,0x02,0x39,0xC2,0x30,0xAE,0x3B,0xFB,0xDE,
+    0x03,0x41,0xC2,0x38,0xDE,0xB8,0x20,0x3B,0x23,0x41,0xC2,0x38,0x56,0xDF,0xFE,0xFC,
+    0x03,0x41,0xA2,0x30,0xAB,0xEB,0xE7,0xB0,0x03,0x41,0xE2,0x38,0xE1,0x09,0x9D,0x55,
+    0x03,0x41,0xC2,0x38,0x77,0xC4,0x8A,0x8A,0x03,0x41,0xC2,0x38,0x4D,0x59,0x5B,0xE2,
+    0x03,0x41,0xE2,0x38,0xFC,0xDF,0x57,0x56,0x03,0x39,0xC2,0x38,0xAE,0xF0,0x5A,0x5D,
+    0x03,0x39,0xC1,0x30,0xEF,0xBD,0xBE,0x8B,0x03,0x41,0xC2,0x38,0xB5,0xBF,0x5F,0xCE,
+    0x03,0x39,0xC2,0x38,0xFA,0x8A,0x7F,0xF7,0xE3,0x38,0xC2,0x38,0x6C,0x7E,0x7F,0xF7,
+    0x03,0x41,0xA1,0x30,0x25,0xAF,0xAB,0xFE,0x88,0x72,0x64,0x49,0x0D,0x2D,0x2D,0x2D,
+    0x87,0x72,0x47,0x6A,0xB8,0x3A,0xB6,0xF3,0x66,0x72,0xC4,0x59,0xE2,0x7A,0x78,0x7E,
+    0xE5,0x59,0x44,0x49,0xF8,0x7E,0x5E,0x7A,0x43,0x41,0xE2,0x38,0x5C,0x7E,0xEF,0x78,
+    0x03,0x39,0xC2,0x30,0x6A,0xA0,0xA2,0xBA,0x03,0x39,0xA2,0x30,0x7A,0xBA,0xAA,0x80,
+    0x03,0x39,0xC2,0x30,0x88,0xE2,0x62,0x5A,0x03,0x31,0xC2,0x30,0x23,0x8A,0x2F,0x2A,
+    0x03,0x39,0xA2,0x28,0xAA,0xBA,0x60,0xE0,0x03,0x31,0xC2,0x28,0x2E,0xBD,0x95,0x9D,
+    0x03,0x31,0xC2,0x28,0xAA,0x2C,0x9C,0xF6,0x03,0x31,0xC2,0x30,0xEE,0xAA,0xFA,0x68,
+    0x03,0x31,0xE2,0x30,0xBF,0x5F,0x97,0xE9,0x23,0x31,0xC2,0x28,0xEA,0xCA,0xFF,0xF8,
+    0x03,0x39,0xE2,0x30,0xBE,0x6B,0xDE,0x52,0x03,0x39,0xE3,0x30,0x00,0xDE,0x3E,0xAA,
+    0x03,0x39,0xE3,0x30,0x42,0x82,0x3D,0xF7,0x24,0x39,0xC2,0x30,0x82,0xAA,0xAB,0xF7,
+    0x03,0x39,0xE3,0x30,0xA0,0xF0,0x42,0xF0,0x24,0x39,0xC2,0x30,0x8A,0xAB,0xFF,0xDE,
+    0x03,0x39,0xE3,0x30,0xB8,0x28,0xF2,0x92,0x23,0x39,0xE3,0x30,0xBE,0xAE,0xAE,0xBF,
+    0x44,0x41,0x03,0x39,0xDB,0x9F,0x07,0xAF,0x44,0x41,0x03,0x39,0xE7,0xD6,0xBE,0x1E,
+    0x44,0x41,0x04,0x39,0x77,0x1D,0xFB,0xA0,0x44,0x41,0x03,0x39,0xB5,0x6F,0xFE,0xDA,
+    0x24,0x41,0x03,0x39,0x55,0x95,0xBF,0xBC,0x24,0x39,0xC2,0x30,0xBB,0xA2,0x80,0x22,
+    0x24,0x39,0xC2,0x30,0xFF,0x5F,0x5A,0xF8,0x03,0x39,0xC2,0x30,0x2A,0x8F,0xF7,0xBA,
+    0x24,0x39,0xE3,0x30,0x8F,0xA9,0xFF,0xBF,0x24,0x39,0xE3,0x30,0x62,0xC0,0xDE,0xFE,
+    0x24,0x39,0xC2,0x30,0xFD,0xAA,0xAA,0xEB,0x03,0x31,0xC2,0x30,0xAF,0x0F,0x28,0xA0,
+    0x03,0x31,0xA2,0x30,0xA2,0xE8,0x22,0x2A,0x24,0x39,0xE3,0x30,0x2E,0x0F,0x9F,0xDE,
+    0x24,0x39,0xE3,0x30,0x6F,0xEA,0xF2,0xEB,0x03,0x31,0xE3,0x30,0x62,0x7F,0x5F,0xB2,
+    0x23,0x39,0xE3,0x30,0xD5,0x55,0xC5,0xF3,0x24,0x39,0xC2,0x30,0x77,0x7F,0x7B,0xEA,
+    0x03,0x31,0xC3,0x30,0xF5,0xED,0x8F,0x8D,0xE3,0x30,0xC2,0x28,0x7E,0x78,0x74,0x70,
+    0xE3,0x30,0xC2,0x28,0x55,0xFB,0xBB,0xFF,0xE2,0x28,0x82,0x28,0x2E,0xAA,0x28,0x02,
+    0xE3,0x30,0xA2,0x20,0xBF,0xEE,0xBC,0xF4,0x03,0x31,0xC2,0x28,0x7D,0x7F,0x53,0xDD,
+    0xC2,0x28,0xA2,0x20,0x3A,0xAF,0x2A,0x0E,0xE2,0x28,0xA2,0x20,0x57,0x5E,0x5F,0x7C,
+    0x81,0x28,0xA2,0x20,0xFF,0x9F,0xFF,0xFD,0xC2,0x28,0x81,0x20,0xFB,0xEF,0xAA,0x2D,
+    0xA2,0x28,0x81,0x20,0xB7,0xAE,0xA0,0xC8,0xC2,0x28,0x61,0x20,0x2A,0xBA,0xFF,0xFF,
+    0x03,0x31,0x81,0x20,0x0A,0xB9,0xFF,0x75,0x03,0x31,0xA2,0x28,0x28,0xBA,0x7F,0x55,
+    0x03,0x31,0xC2,0x30,0x22,0xAA,0x2F,0xA5,0x03,0x39,0xE2,0x30,0xDE,0x2A,0x02,0x9F,
+    0x23,0x39,0xC2,0x28,0x75,0xB7,0xAA,0x3A,0x24,0x31,0xC2,0x30,0x7D,0xAB,0xBA,0xF8,
+    0x24,0x39,0xE3,0x30,0xEB,0xEE,0xA5,0xE1,0x24,0x39,0xC2,0x28,0xFA,0x7A,0x68,0x7B,
+    0xE3,0x30,0xA2,0x28,0x17,0xBF,0xB6,0xA8,0x03,0x39,0xA1,0x28,0x0E,0x2E,0x9F,0xBF,
+    0x23,0x39,0xC2,0x30,0x62,0xAA,0x8E,0x83,0x24,0x39,0xE3,0x38,0xAD,0xBD,0x37,0xAD,
+    0x44,0x41,0xE2,0x30,0xAA,0xAF,0xEA,0x62,0x24,0x39,0xC3,0x28,0xF8,0x7E,0xFB,0xFE,
+    0xE3,0x30,0xA2,0x28,0xD6,0x5C,0xEE,0xB8,0x03,0x31,0xA2,0x28,0xAD,0xAF,0xAA,0x2E,
+    0x03,0x31,0xA1,0x28,0xFE,0xFF,0xDC,0x0E,0x03,0x31,0xC2,0x28,0xA5,0xA5,0xA3,0x08,
+    0x64,0x41,0xE2,0x30,0xBD,0xBD,0xAB,0x2B,0xA5,0x49,0x64,0x49,0x21,0x2F,0xAD,0x33,
+    0xE6,0x59,0xA5,0x51,0xB1,0xA5,0xAD,0x0B,0x48,0x62,0x06,0x5A,0xE7,0x55,0x9F,0x49,
+    0x68,0x6A,0x06,0x5A,0x3D,0xB5,0xDE,0xF7,0x68,0x6A,0xE6,0x59,0x08,0x0A,0x2A,0xA7,
+    0xA9,0x72,0x48,0x6A,0x5C,0xFE,0xE0,0x3D,0xA9,0x72,0x48,0x6A,0x22,0xBA,0xF7,0xFE,
+    0xC9,0x72,0x68,0x6A,0xB8,0xBB,0xBA,0x9F,0xCA,0x7A,0x27,0x62,0xBA,0x82,0x86,0x08,
+    0xA9,0x72,0x68,0x6A,0x0E,0x03,0xBF,0x98,0xA9,0x72,0x88,0x6A,0xF4,0xA7,0x94,0x24,
+    0xC9,0x7A,0x88,0x72,0x70,0x6F,0xDA,0xB2,0xE9,0x7A,0x88,0x72,0xD9,0xF5,0xA2,0xB3,
+    0xE9,0x7A,0xA9,0x72,0xCD,0xF6,0xDC,0x5F,0xE9,0x7A,0xA9,0x72,0xFD,0x80,0xE2,0x6E,
+    0xE9,0x7A,0x89,0x72,0xBA,0x92,0x2B,0xBA,0xE9,0x7A,0xA8,0x72,0xDF,0x72,0x73,0xDA,
+    0x0A,0x7B,0x88,0x6A,0xEE,0xBF,0xB5,0x2F,0x2A,0x83,0xC9,0x72,0xD7,0x3F,0xF5,0xFE,
+    0x2A,0x83,0xC9,0x7A,0xFD,0xB4,0xAA,0xDD,0x2A,0x8B,0xA8,0x7A,0x2F,0xEE,0x7A,0x76,
+    0x0A,0x83,0xA9,0x7A,0xE2,0xAB,0x89,0xEB,0xEA,0x7A,0xA9,0x7A,0xED,0x5D,0xA8,0xA8,
+    0x0A,0x83,0xA9,0x72,0xA5,0xAD,0xAE,0xAE,0x0B,0x83,0xCA,0x7A,0xBF,0x95,0xAF,0x6B,
+    0x0B,0x83,0xCA,0x7A,0xDE,0xD7,0xDE,0x79,0x4B,0x8B,0xC9,0x7A,0x2B,0xAF,0xF5,0xFD,
+    0x2A,0x83,0xC9,0x7A,0xF0,0xA2,0xA6,0x0E,0x2A,0x83,0xC9,0x7A,0xD7,0xE8,0xC0,0xA8,
+    0x0A,0x83,0xC9,0x7A,0x28,0x09,0xED,0x83,0x4B,0x8B,0xE9,0x7A,0xA8,0x8B,0xBD,0x8D,
+    0x4A,0x83,0x09,0x7B,0x8E,0x6F,0xCB,0xAF,0x4B,0x8B,0xE9,0x7A,0x0A,0x3B,0x9E,0x7F,
+    0x03,0x41,0xC2,0x38,0x06,0xAA,0xC3,0xE0,0x03,0x41,0xA2,0x30,0x78,0xEA,0xBE,0xEF,
+    0x03,0x41,0xA2,0x38,0xAB,0xBB,0xEB,0xCD,0xE2,0x38,0xA1,0x30,0x08,0x0A,0x08,0xC8,
+    0x03,0x41,0xC2,0x38,0xBA,0xA5,0x97,0x17,0x23,0x41,0xE2,0x38,0x6F,0x75,0xFE,0xFE,
+    0x23,0x41,0xC2,0x38,0xB7,0xEF,0xE0,0x53,0x03,0x41,0xC2,0x38,0xE0,0xFA,0x57,0x73,
+    0x03,0x41,0xE2,0x38,0x55,0x56,0xFF,0x6F,0x23,0x41,0xC1,0x30,0xDF,0xD7,0xBF,0xBB,
+    0x03,0x41,0xC2,0x38,0xAF,0xA7,0x2A,0x3C,0x03,0x41,0xC2,0x38,0xEB,0xAF,0x27,0xB7,
+    0x03,0x41,0xC2,0x38,0xA0,0xDA,0xF0,0xA0,0x03,0x39,0xC2,0x38,0xEF,0xEA,0x6A,0xFB,
+    0x03,0x39,0xC2,0x38,0x37,0xD7,0xAF,0xEB,0x03,0x41,0xC2,0x38,0xE8,0xC0,0xC2,0xDE,
+    0x03,0x41,0xC2,0x38,0xEB,0xD3,0x7B,0xDA,0x03,0x41,0xA1,0x30,0x7F,0xFA,0xFD,0xCA,
+    0xE2,0x38,0xC2,0x38,0x8D,0x0D,0xC5,0x2E,0xE2,0x38,0xC2,0x38,0x84,0x74,0x95,0xA4,
+    0xE2,0x38,0xC2,0x38,0xC1,0xF2,0x00,0x08,0x03,0x41,0xA2,0x38,0xB7,0xBF,0xBB,0xA2,
+    0x03,0x41,0xC2,0x38,0x57,0x7F,0xEB,0x4B,0x67,0x72,0x03,0x41,0x29,0x0D,0x0D,0x0D,
+    0x87,0x72,0x26,0x6A,0xA0,0xAA,0x7A,0x78,0x47,0x6A,0x64,0x51,0xE8,0x68,0xF8,0xFA,
+    0xA4,0x51,0x03,0x41,0xFC,0xDE,0x7E,0xFA,0x44,0x49,0xC2,0x30,0xE8,0xBE,0xFF,0xFE,
+    0x03,0x39,0xC2,0x30,0x28,0xF8,0xF8,0xE0,0x03,0x39,0xC2,0x30,0xAA,0xA7,0xE5,0xF5,
+    0x23,0x39,0xC2,0x30,0xDF,0xBE,0xAB,0x2F,0x03,0x31,0xA2,0x30,0x0A,0xAA,0x88,0xE2,
+    0x03,0x31,0xC2,0x30,0xC2,0xBA,0xBA,0x6E,0x03,0x31,0xC2,0x28,0xAA,0xBA,0x7F,0x5F,
+    0x03,0x31,0xC2,0x28,0x7E,0x2A,0x88,0x02,0x03,0x31,0xC2,0x30,0x6A,0xE2,0x7C,0xB8,
+    0x03,0x31,0xC2,0x28,0x8B,0xCB,0xF9,0x8E,0x23,0x39,0xC3,0x30,0xBC,0xFF,0x7F,0x5F,
+    0x03,0x31,0xC2,0x30,0xE2,0x3F,0x8B,0xAB,0x03,0x31,0xC2,0x28,0x02,0x02,0x23,0x7B,
+    0x03,0x39,0xE3,0x30,0xFA,0xEF,0x1E,0xDB,0x24,0x39,0xC2,0x30,0xB9,0xF7,0xFC,0xE0,
+    0x03,0x39,0xC2,0x30,0xA2,0xEB,0xAB,0xAA,0xE3,0x30,0xA2,0x30,0x08,0x28,0x2A,0x8F,
+    0x24,0x41,0xE3,0x30,0xD7,0xAC,0xAA,0x80,0x24,0x39,0xE3,0x30,0x7B,0xBB,0xAE,0xAF,
+    0x24,0x39,0xE3,0x30,0x03,0x2A,0x5F,0x9F,0x44,0x41,0xE3,0x30,0x2A,0x2A,0xA7,0x95,
+    0x64,0x41,0x03,0x39,0xFA,0xD8,0x5F,0xF7,0x24,0x39,0x03,0x39,0x74,0xF4,0x54,0x57,
+    0x23,0x39,0xC3,0x30,0xE2,0x9A,0xEE,0xBB,0x24,0x39,0xE3,0x38,0x27,0xAF,0xAA,0xAA,
+    0x24,0x39,0xE3,0x38,0xFA,0xA2,0xEB,0xFF,0x44,0x39,0xE3,0x38,0x5F,0xFF,0x7E,0xFD,
+    0x24,0x39,0x03,0x39,0x54,0x6D,0xF9,0xDD,0x23,0x39,0xE3,0x30,0xFE,0xD8,0xA8,0xB6,
+    0x03,0x39,0xE3,0x30,0xA9,0xE5,0x17,0x74,0x24,0x39,0xE3,0x30,0x5E,0x15,0x0F,0xB5,
+    0x44,0x39,0xE3,0x30,0xF5,0xE9,0xFF,0xE3,0x24,0x39,0xC2,0x28,0x3A,0xB8,0xAE,0x9A,
+    0x23,0x39,0xC3,0x28,0xDF,0xFF,0x2A,0x0A,0x23,0x39,0xE3,0x30,0xFF,0xFB,0xFC,0x68,
+    0xE4,0x38,0x23,0x31,0xEF,0xEA,0xFB,0xAB,0x23,0x39,0xE3,0x30,0xD7,0xFF,0xEC,0xBB,
+    0x23,0x39,0xC2,0x30,0x8D,0xAE,0xEE,0xFE,0x03,0x31,0xC3,0x30,0xF8,0xF8,0xBB,0x87,
+    0x03,0x31,0xC2,0x28,0xF7,0xA7,0x09,0x03,0x03,0x31,0xC2,0x28,0xF7,0xFE,0x0A,0xF8,
+    0xE2,0x30,0xC2,0x28,0x56,0xD7,0xD7,0x57,0xE2,0x28,0xA2,0x28,0xAB,0x80,0xEA,0x8A,
+    0x03,0x31,0xC2,0x28,0xD9,0xFB,0x6F,0x75,0x03,0x31,0x81,0x20,0x72,0xE2,0xEA,0xAB,
+    0xC2,0x28,0x81,0x20,0x78,0x3E,0x2A,0x00,0xE3,0x30,0x81,0x20,0xA9,0x63,0xCA,0xBB,
+    0xA2,0x28,0x81,0x20,0xEB,0x2B,0xEA,0xA0,0xA2,0x28,0x82,0x20,0x3F,0xAF,0xBA,0xFA,
+    0xA2,0x28,0x61,0x20,0xAF,0xD7,0xFF,0xF2,0xC2,0x28,0x61,0x20,0x8A,0xBB,0xF7,0x7F,
+    0xE3,0x30,0x81,0x20,0x2B,0xB7,0xBD,0xD5,0xE3,0x30,0xA2,0x28,0x20,0x02,0xDB,0x5F,
+    0x03,0x31,0xA2,0x28,0x2A,0xAA,0x9F,0xF5,0x24,0x39,0xC2,0x28,0x3A,0xBA,0xED,0xD5,
+    0x24,0x39,0xE3,0x30,0x67,0xF7,0x35,0xFF,0x04,0x31,0xE3,0x30,0x7D,0x67,0x1D,0x57,
+    0x03,0x31,0xC2,0x28,0x7E,0xA8,0xAE,0xB5,0x03,0x31,0xC2,0x28,0xF5,0xAF,0x2A,0x88,
+    0x44,0x39,0xE2,0x30,0xCF,0xBD,0x8F,0x2D,0x23,0x39,0xE2,0x30,0xAF,0xAE,0xCA,0x28,
+    0x24,0x39,0xC2,0x28,0x80,0xE2,0xEA,0x60,0x03,0x39,0x82,0x28,0x02,0x80,0xAB,0xB5,
+    0x03,0x31,0xC2,0x28,0x5E,0x27,0xA5,0x95,0x03,0x31,0xC2,0x28,0x2F,0x9F,0xF7,0xFE,
+    0x03,0x31,0xC2,0x28,0x88,0x2E,0x3E,0x3F,0x44,0x39,0xE3,0x30,0xBF,0xFD,0xAF,0x2F,
+    0xA5,0x49,0x23,0x39,0xBD,0x2D,0x2F,0x2B,0xC5,0x51,0x85,0x49,0xB1,0x0B,0xA8,0x02,
+    0x06,0x5A,0xC6,0x51,0x9D,0xB5,0x23,0x32,0x27,0x62,0xC6,0x59,0x0B,0xFB,0x6A,0xBA,
+    0x27,0x62,0xC6,0x51,0x80,0xB8,0xEA,0x2A,0x47,0x62,0x07,0x62,0xAA,0xAE,0x2F,0x39,
+    0x68,0x6A,0x27,0x62,0x0E,0xBE,0xDF,0xAA,0x88,0x6A,0x48,0x6A,0xDC,0xEE,0x97,0xBD,
+    0xC9,0x72,0x48,0x6A,0xBF,0x2F,0xBF,0xDF,0xEA,0x7A,0xA9,0x72,0xBB,0xEB,0x7F,0xD6,
+    0xEA,0x7A,0x88,0x6A,0x5E,0x7B,0x7F,0x2B,0xE9,0x7A,0x88,0x6A,0xE5,0x89,0xE0,0xAE,
+    0xE9,0x7A,0x88,0x72,0xF2,0xE5,0xB5,0xAC,0xEA,0x7A,0x89,0x72,0x5B,0xFF,0xBE,0x8E,
+    0xC9,0x7A,0x88,0x72,0xB0,0xFA,0xD2,0xA0,0xE9,0x7A,0x88,0x72,0xAE,0xAD,0xBF,0xFF,
+    0xEA,0x7A,0x88,0x72,0xAB,0xEA,0x72,0x62,0xE9,0x7A,0xA8,0x72,0xFA,0xEE,0xF9,0x29,
+    0x0A,0x83,0xA9,0x72,0x29,0xCB,0xA2,0xEB,0x2A,0x83,0xC9,0x7A,0xEB,0xAA,0x2F,0xBD,
+    0x0A,0x83,0xC9,0x7A,0x54,0x3A,0xAA,0xFA,0x0A,0x83,0xC9,0x7A,0x57,0xA8,0xA8,0xF7,
+    0x2A,0x83,0xA9,0x7A,0xB7,0xA3,0xAA,0xB2,0x2A,0x83,0xC9,0x7A,0x75,0xFF,0xA2,0xA2,
+    0x0A,0x83,0xA9,0x72,0xBE,0xBA,0x5E,0x7C,0x0A,0x83,0xA9,0x72,0xFF,0xA2,0xFA,0x5B,
+    0x0B,0x83,0xCA,0x7A,0xEA,0xFF,0xFD,0xFD,0xEA,0x7A,0xA9,0x72,0x20,0x22,0xDA,0xA0,
+    0x2A,0x83,0xA9,0x72,0x8A,0xEF,0x7F,0x7E,0x2B,0x83,0xA9,0x72,0xAA,0x2D,0xBF,0xF7,
+    0x2A,0x83,0xC9,0x7A,0xB2,0xB8,0xFE,0xDF,0x4B,0x8B,0xEA,0x7A,0xCB,0x21,0x8E,0x5D,
+    0x4B,0x83,0xE9,0x7A,0xFE,0xDE,0xAB,0x7B,0x0A,0x83,0xC9,0x7A,0xB0,0xFF,0xBA,0xF6,
+    0x03,0x41,0xA1,0x30,0xB0,0xF2,0xBA,0x8B,0xE2,0x38,0xA1,0x30,0xBC,0xFB,0x28,0xBC,
+    0x03,0x41,0xC2,0x38,0x55,0x5E,0xEA,0xAF,0x23,0x41,0xC2,0x38,0x75,0x3D,0xBD,0x9E,
+    0x23,0x41,0xC2,0x38,0xAD,0xE7,0x26,0xAF,0x23,0x41,0xE2,0x38,0xD7,0xD7,0x5E,0xB8,
+    0x02,0x39,0xC2,0x38,0x6A,0xEA,0x68,0xA8,0x02,0x39,0xC2,0x38,0xFF,0x6F,0x5A,0x7C,
+    0x22,0x41,0xC2,0x38,0x5B,0x5D,0x7D,0x7F,0x03,0x41,0xA1,0x30,0x8B,0xAB,0xFD,0xE5,
+    0x03,0x41,0xC2,0x38,0xF4,0x5A,0x5B,0x7A,0x23,0x39,0xC2,0x38,0xBD,0xD7,0xFD,0x5F,
+    0x03,0x39,0xA1,0x30,0x2A,0xAF,0xE6,0xEA,0xE2,0x38,0xC2,0x38,0x08,0x2A,0xCA,0x7B,
+    0x02,0x39,0xC2,0x38,0xFB,0xF7,0x7F,0xEB,0xE2,0x38,0xC2,0x30,0xAC,0x0E,0xC9,0x4F,
+    0xE2,0x38,0xC2,0x38,0x08,0x02,0xA2,0x20,0x03,0x41,0xC2,0x38,0xAA,0xDE,0xF9,0x4F,
+    0x03,0x41,0xC2,0x38,0xFC,0xF8,0xFA,0xFD,0x03,0x39,0xC2,0x38,0xFA,0xBB,0xDF,0xD5,
+    0x03,0x41,0xA2,0x38,0xFA,0x7A,0xFE,0xB8,0xE2,0x38,0xA2,0x30,0xA2,0x9B,0xBC,0x3C,
+    0x03,0x41,0xC2,0x38,0xAB,0xAA,0xBA,0xE7,0x67,0x72,0x02,0x41,0x0D,0x2D,0xAD,0x35,
+    0x87,0x72,0x06,0x62,0x78,0x68,0x6A,0xEA,0x06,0x6A,0x63,0x49,0xE0,0xE8,0xFC,0x7E,
+    0x84,0x51,0x23,0x41,0x7C,0xFE,0x7E,0xCB,0x23,0x41,0xE2,0x30,0xFE,0xFC,0x7C,0x5C,
+    0x03,0x39,0xC2,0x30,0xA0,0xFE,0xAF,0xE7,0x03,0x39,0xC2,0x30,0xF5,0xD5,0xAB,0xBD,
+    0x03,0x39,0xC2,0x30,0xCB,0x6F,0xEA,0xCB,0xE3,0x30,0xC2,0x28,0xE0,0xFC,0xB0,0xE0,
+    0x03,0x31,0xA2,0x28,0xBB,0xAE,0xFE,0x58,0xE3,0x30,0xC2,0x28,0xBC,0xF6,0x3D,0x09,
+    0x24,0x39,0xC2,0x30,0x2A,0x8B,0xE7,0xFF,0x23,0x39,0xA2,0x28,0xA2,0xFB,0xF7,0xF7,
+    0x03,0x31,0xC2,0x30,0xA6,0xAE,0x8B,0xAB,0x03,0x31,0xC2,0x30,0xDA,0x50,0xF2,0xAA,
+    0xE3,0x30,0xC2,0x28,0x2A,0x2F,0xBC,0x28,0x23,0x39,0xC2,0x28,0xFF,0xFF,0xFB,0xA2,
+    0x03,0x31,0xC2,0x30,0x0B,0x2B,0x2F,0x0A,0x23,0x39,0xE3,0x30,0x7A,0x7A,0xDF,0xD7,
+    0x03,0x39,0xE3,0x30,0x8B,0xEB,0xF2,0xD2,0x03,0x39,0xC2,0x30,0xA8,0x38,0xFF,0x6F,
+    0x24,0x39,0xC2,0x30,0xA0,0xFA,0x7F,0xED,0x24,0x39,0xE3,0x30,0xCF,0xE5,0xFF,0xF7,
+    0x24,0x39,0xE3,0x30,0x8B,0x8B,0x8E,0x9C,0x24,0x39,0xE3,0x30,0x3F,0x2F,0xB3,0xFA,
+    0x44,0x41,0xE2,0x30,0xB2,0xF8,0xEE,0x7D,0x43,0x39,0xE2,0x38,0xFA,0xAA,0xAA,0xBF,
+    0x44,0x41,0x03,0x39,0xBD,0xAB,0xAD,0xF7,0x44,0x41,0x03,0x39,0x77,0x7E,0xB7,0x68,
+    0x44,0x41,0xE3,0x38,0x7F,0x4A,0xEA,0xFF,0xE3,0x38,0x23,0x31,0xEF,0xAA,0xAE,0xAF,
+    0x03,0x39,0xC3,0x30,0x00,0xE2,0xDA,0xA3,0x24,0x41,0xE3,0x30,0xAF,0xBF,0xA9,0x8A,
+    0x24,0x39,0xC2,0x30,0xFA,0xFE,0xBE,0x7C,0x24,0x39,0xC2,0x30,0xAD,0xEB,0xAA,0xE2,
+    0x24,0x39,0xE3,0x30,0x63,0x7B,0x7F,0xED,0x03,0x31,0xC2,0x30,0x00,0xAB,0xAD,0xEA,
+    0x43,0x39,0xE2,0x30,0xBD,0xEA,0xAC,0xEB,0x23,0x39,0x03,0x31,0x4C,0x50,0x70,0x5A,
+    0x24,0x39,0xE3,0x30,0x5F,0xFF,0xEB,0xA8,0x03,0x31,0xE2,0x30,0xC1,0xFA,0xF7,0x5E,
+    0x24,0x39,0xE3,0x30,0xBF,0xFF,0xEB,0xCB,0x03,0x39,0xA2,0x28,0x22,0x28,0x2A,0x2B,
+    0x44,0x39,0xE3,0x30,0x75,0x77,0x7C,0xFA,0x03,0x31,0xC2,0x30,0xC2,0xEE,0xDE,0x8A,
+    0x03,0x31,0xC2,0x28,0x5D,0xFD,0xFF,0xA0,0x03,0x31,0xC2,0x28,0x55,0x57,0xB7,0x1F,
+    0x03,0x31,0xC2,0x28,0xD5,0xF5,0xBA,0x20,0x24,0x31,0xC2,0x28,0x5F,0x5B,0x73,0x6F,
+    0xE3,0x30,0xC2,0x28,0xDD,0xF7,0x55,0x7F,0xE3,0x28,0xA2,0x28,0x7A,0xD8,0xAA,0xAB,
+    0xC2,0x28,0xA2,0x20,0x5A,0xEB,0x0B,0x8F,0xC2,0x28,0xA2,0x20,0x7F,0xEC,0xEB,0xB7,
+    0xC2,0x28,0x82,0x20,0x5A,0x5A,0xDC,0xFA,0xC3,0x28,0x82,0x20,0x5D,0x57,0xFC,0xAA,
+    0xC2,0x20,0x61,0x18,0xF7,0xFF,0xBA,0xA2,0xA2,0x28,0x81,0x20,0x0F,0x15,0xF7,0x78,
+    0xA2,0x28,0x61,0x20,0x2A,0xBA,0xBB,0xBF,0xE2,0x30,0x82,0x20,0xBA,0x2F,0xFB,0xF5,
+    0x03,0x31,0xA2,0x28,0x3A,0xBE,0x5F,0xD5,0x03,0x31,0xA2,0x28,0x22,0x2C,0x2E,0xBD,
+    0xE3,0x30,0xA2,0x28,0xA8,0x80,0xF8,0x5F,0x03,0x31,0xA2,0x28,0x8C,0x8E,0x57,0x55,
+    0x44,0x39,0xA2,0x28,0x2B,0xAF,0xAF,0xFD,0x65,0x41,0x03,0x31,0xBE,0xE8,0xE3,0x7D,
+    0x24,0x39,0xC2,0x28,0xE8,0x78,0x5E,0x5E,0xE3,0x30,0xA2,0x28,0xE3,0xC2,0xBF,0x8B,
+    0x03,0x31,0xC2,0x28,0xEF,0x8A,0xAB,0x3F,0x23,0x39,0xC2,0x28,0xDF,0xF7,0xE2,0xAB,
+    0x23,0x39,0xE3,0x30,0xF7,0xAF,0xAF,0x0D,0xA5,0x49,0x03,0x39,0xA5,0x25,0xAF,0x2B,
+    0x06,0x5A,0x65,0x41,0xAD,0x8B,0xAB,0xEA,0x06,0x5A,0xA5,0x51,0xAB,0x2E,0x09,0xA2,
+    0xC6,0x59,0x05,0x52,0xAB,0xEE,0xFB,0xEA,0x27,0x62,0xC5,0x59,0xA7,0xAD,0x8B,0xA2,
+    0x48,0x6A,0xE6,0x59,0xBA,0xFD,0xDB,0x82,0x88,0x6A,0x06,0x5A,0xD7,0xD7,0xDF,0xAA,
+    0xA9,0x72,0x47,0x62,0xEF,0x2D,0xAD,0x3B,0x89,0x6A,0x48,0x6A,0xFA,0xA0,0x82,0x8B,
+    0x88,0x6A,0x48,0x6A,0xAF,0xAA,0xAA,0xDF,0xCA,0x7A,0x68,0x6A,0x8B,0x03,0x2B,0xBD,
+    0xE9,0x7A,0x68,0x6A,0x22,0xFB,0xFA,0xF7,0xE9,0x7A,0xA9,0x72,0xFD,0xBB,0xAF,0xD5,
+    0xE9,0x7A,0x68,0x6A,0xBA,0x9F,0xFE,0xA8,0xC9,0x7A,0x68,0x6A,0x80,0x28,0xEA,0xFC,
+    0xE9,0x7A,0x88,0x72,0x63,0xB2,0x03,0xAF,0xE9,0x7A,0x88,0x72,0xFF,0xBD,0x2B,0x00,
+    0xEA,0x7A,0x88,0x72,0x8A,0xBA,0x6A,0x7C,0xE9,0x7A,0xA9,0x72,0x82,0x0B,0xAF,0x6D,
+    0xE9,0x7A,0xA8,0x72,0x79,0x7A,0xA2,0xEA,0xE9,0x7A,0xA9,0x72,0xB8,0xE4,0xC0,0xB0,
+    0xC9,0x7A,0x88,0x72,0xBC,0xDB,0xBB,0x7E,0xC9,0x7A,0x88,0x72,0x2B,0x2B,0xAF,0x15,
+    0x0A,0x83,0xA9,0x72,0x22,0xBF,0xF9,0xFF,0x2B,0x83,0x88,0x72,0xA8,0xA3,0xBD,0xDF,
+    0xEA,0x7A,0xA8,0x72,0xB8,0xFE,0xBC,0xAA,0xEA,0x7A,0x88,0x72,0xD2,0xBA,0xAA,0xA8,
+    0x2B,0x83,0xC9,0x7A,0xFD,0x5D,0xB7,0xD5,0x0A,0x83,0xA9,0x72,0x20,0xB6,0x9E,0xA2,
+    0x2B,0x83,0xC9,0x7A,0x5E,0xBF,0x3F,0xAD,0x2B,0x83,0xA8,0x7A,0x7B,0x2A,0x22,0x8A,
+    0x0A,0x83,0xA8,0x72,0x89,0x2F,0xAB,0x8E,0x0A,0x83,0xC9,0x7A,0xC0,0xAA,0x00,0xBE,
+    0xEA,0x82,0x0A,0x7B,0xEF,0xF5,0x6A,0xEF,0x2A,0x83,0xEA,0x7A,0x9E,0xB6,0x76,0x73,
+    0x03,0x41,0xA1,0x30,0xA8,0xBC,0x76,0xD6,0x23,0x41,0xC2,0x38,0xE5,0x5D,0xEF,0xEF,
+    0x03,0x41,0xA1,0x30,0xAF,0x39,0x0E,0x2A,0x03,0x39,0xC2,0x38,0xAA,0x2B,0x3D,0x96,
+    0x03,0x41,0xC2,0x38,0x03,0xAB,0xA8,0x78,0x03,0x41,0xC2,0x38,0x28,0xBA,0x16,0xD5,
+    0x02,0x41,0xE2,0x38,0xB2,0x38,0x5E,0x5E,0x03,0x41,0xA1,0x30,0xFE,0xF8,0xAA,0x2A,
+    0xE2,0x38,0xA1,0x30,0xFF,0xDF,0xBE,0xE8,0x03,0x41,0xA1,0x30,0x29,0xAB,0xEB,0xFB,
+    0xE2,0x38,0xA1,0x30,0xA0,0x2A,0xBE,0x0A,0x02,0x41,0xE2,0x38,0x5F,0x57,0x85,0xDD,
+    0x03,0x41,0xA1,0x30,0xEA,0x7E,0x7A,0x82,0x23,0x41,0xC2,0x38,0x7B,0x5F,0x5D,0x7F,
+    0x22,0x41,0xC2,0x38,0xD5,0xD7,0x77,0x7F,0xE2,0x38,0xA1,0x30,0xFC,0xFE,0xBC,0xA2,
+    0x02,0x41,0xC2,0x38,0x55,0xED,0x83,0x68,0x03,0x39,0xC2,0x38,0xEB,0xEB,0x2B,0x4F,
+    0x03,0x39,0xC2,0x38,0xD7,0xFB,0xAA,0xD6,0x02,0x41,0xA1,0x30,0xFE,0xFA,0xF8,0xB9,
+    0xE2,0x38,0xA2,0x30,0x3A,0xAB,0xEA,0xAC,0xE2,0x38,0xA2,0x30,0x78,0xB9,0xA8,0x8A,
+    0xE2,0x38,0xA1,0x30,0x8A,0x88,0xFF,0x5A,0x26,0x6A,0xC1,0x30,0x3D,0x35,0xB5,0xB5,
+    0x66,0x6A,0xC5,0x59,0xA0,0xE2,0x7A,0x7A,0xE5,0x59,0x84,0x51,0x5C,0x7C,0xF7,0xEB,
+    0xA4,0x51,0x64,0x49,0x6F,0x5E,0x5E,0xE2,0x64,0x49,0xE2,0x30,0x54,0x5E,0xD6,0xDF,
+    0x23,0x39,0xC2,0x30,0xE5,0xC9,0xA8,0xE0,0x03,0x39,0xC2,0x30,0xAE,0xA7,0xCF,0xAF,
+    0x24,0x31,0xC2,0x30,0xE7,0xDD,0xF7,0xDF,0x03,0x31,0xC2,0x30,0xAC,0xF0,0x56,0xD7,
+    0x03,0x31,0xA2,0x28,0xD8,0xBE,0xFF,0xFF,0xE3,0x30,0xC2,0x28,0x2A,0x28,0xAE,0xFD,
+    0xE3,0x30,0xC2,0x28,0x2C,0x2F,0x3A,0xAB,0x02,0x31,0xC2,0x28,0xD7,0xCF,0xEA,0xAB,
+    0x03,0x31,0xE3,0x30,0x55,0xE7,0xBD,0x8D,0x03,0x39,0xA2,0x28,0xAA,0xE3,0xAA,0x82,
+    0x03,0x31,0xE3,0x30,0x15,0x55,0x7D,0x7F,0x23,0x39,0xE3,0x30,0x62,0xF7,0x57,0x55,
+    0x03,0x31,0xC2,0x28,0x08,0xFA,0xF6,0x7D,0x03,0x31,0xE2,0x30,0xD5,0xDE,0xF5,0xE5,
+    0x03,0x31,0xC2,0x30,0xA3,0xA2,0x2A,0x2B,0x03,0x31,0xE2,0x30,0xCF,0xAA,0x0F,0x28,
+    0x03,0x39,0xC3,0x30,0x89,0xC8,0x88,0xE8,0x03,0x39,0xA2,0x28,0x2F,0xBA,0xEE,0x2E,
+    0x03,0x31,0xC2,0x30,0xA8,0x30,0x5F,0xFF,0x03,0x39,0xE3,0x30,0xE2,0xAA,0xED,0x73,
+    0x24,0x39,0xE3,0x30,0xF3,0x79,0xFF,0xBD,0x23,0x39,0xE3,0x30,0xAA,0xF3,0xD7,0xD8,
+    0x23,0x39,0xE3,0x30,0x22,0x2E,0x3F,0x2E,0x24,0x39,0xE2,0x30,0xA0,0x7A,0x7E,0x8A,
+    0x23,0x39,0xE3,0x30,0xE8,0xE3,0x6A,0x6A,0x24,0x39,0xC2,0x38,0xAA,0xA8,0x8A,0xA9,
+    0x23,0x39,0xE3,0x38,0xDF,0x58,0xF8,0xF6,0x24,0x39,0xC3,0x38,0x02,0x8B,0xAA,0x8A,
+    0x44,0x41,0xC3,0x30,0xFE,0xDA,0xFA,0x22,0x24,0x39,0xC2,0x30,0xB3,0xDF,0xBE,0xCC,
+    0x44,0x39,0xE3,0x30,0xED,0xED,0xF5,0x87,0x44,0x39,0x03,0x31,0x7E,0xFA,0xEE,0xAB,
+    0x03,0x31,0xC2,0x30,0xE2,0xA2,0x00,0xA0,0x03,0x31,0xC2,0x30,0x08,0x2A,0x3E,0x3E,
+    0x44,0x39,0xE2,0x30,0xA7,0x2B,0xAB,0xFB,0x24,0x39,0xE2,0x30,0xDC,0xB8,0x28,0xAA,
+    0x24,0x39,0xE3,0x30,0xEA,0xF8,0xA8,0x00,0x24,0x39,0xC2,0x30,0xBD,0x23,0x00,0xA0,
+    0x24,0x39,0xE3,0x30,0x27,0x3C,0xA0,0xAE,0x24,0x39,0xE3,0x30,0xFE,0x5E,0x7A,0xB2,
+    0x23,0x39,0xE3,0x30,0x5E,0xEE,0xF8,0xC8,0x23,0x39,0xC2,0x28,0xFF,0xEF,0xFE,0xD2,
+    0x03,0x31,0xC2,0x28,0xBB,0x3F,0xB6,0x2A,0x24,0x39,0xC2,0x30,0xFE,0xFA,0xF2,0x7A,
+    0xE3,0x30,0xC2,0x28,0x5A,0x2A,0x0D,0x3D,0x03,0x31,0xC2,0x28,0x57,0x7E,0xFE,0x34,
+    0x03,0x31,0xA2,0x20,0x6F,0xFF,0xAB,0xA8,0x03,0x31,0xC2,0x28,0x55,0xDD,0xF7,0x4B,
+    0xE3,0x28,0xA2,0x20,0x57,0x9E,0xEA,0x00,0xE3,0x28,0xA2,0x28,0xFD,0xFF,0xF3,0xF3,
+    0xC2,0x28,0xA2,0x20,0x97,0xA5,0x05,0x0E,0xC3,0x28,0x81,0x20,0xFE,0xE0,0x00,0x80,
+    0xC2,0x28,0x82,0x20,0x55,0xD5,0xDB,0xA8,0xC3,0x28,0x82,0x20,0xFD,0xF5,0xB7,0x2B,
+    0xC2,0x28,0x82,0x20,0xF7,0xD5,0xF7,0xAE,0xC3,0x28,0x81,0x20,0xAA,0x6F,0xBA,0xFC,
+    0xA2,0x28,0x82,0x20,0xDF,0xFF,0xBF,0xBC,0xC2,0x28,0x82,0x20,0xFF,0x2F,0x2F,0x3E,
+    0xE2,0x28,0xA2,0x28,0xAB,0xA7,0xF5,0xD5,0x03,0x31,0xC2,0x28,0x03,0x3B,0xA7,0xBD,
+    0x03,0x31,0xA2,0x28,0x72,0xEA,0xBA,0xFA,0x03,0x31,0xA2,0x28,0xEF,0x35,0x3F,0x3E,
+    0x24,0x39,0xC2,0x28,0xFF,0x9F,0x9F,0x3F,0x24,0x39,0x03,0x31,0x55,0xB5,0x3F,0x2A,
+    0x85,0x41,0xE2,0x30,0xAD,0xA9,0x2F,0x2A,0xC6,0x51,0x63,0x41,0xBF,0xEA,0x09,0x02,
+    0x06,0x5A,0xC6,0x51,0xA9,0xEB,0xB2,0x3E,0x06,0x5A,0xC5,0x51,0xF8,0xAA,0x92,0xE2,
+    0x06,0x5A,0xA5,0x51,0xEB,0xB7,0xBF,0xA8,0x48,0x6A,0xE6,0x59,0xEF,0xB5,0x3B,0xAD,
+    0x68,0x6A,0x06,0x5A,0xE9,0xA5,0xAF,0x2F,0x88,0x72,0x27,0x62,0xAF,0x29,0x25,0xF3,
+    0xA9,0x72,0x68,0x6A,0x2E,0xAA,0xAA,0xF6,0xEA,0x7A,0x68,0x6A,0xFD,0xFF,0xF5,0xE3,
+    0xCA,0x72,0x48,0x6A,0x5E,0x7F,0xEA,0x8A,0xC9,0x72,0x68,0x6A,0x2D,0xAE,0x23,0xC2,
+    0xC9,0x7A,0x68,0x6A,0xEB,0xCA,0xB8,0x9A,0xC9,0x72,0x67,0x6A,0x8B,0xAF,0x57,0xFE,
+    0xEA,0x7A,0x68,0x6A,0x83,0xA5,0xFD,0x7F,0xC9,0x7A,0x67,0x6A,0xB8,0xAF,0x37,0xAD,
+    0xC9,0x7A,0x67,0x6A,0xAC,0x2F,0x6A,0x7E,0x0A,0x83,0xA9,0x72,0x8B,0xEF,0x7F,0xF5,
+    0x0A,0x83,0xA8,0x72,0x78,0xFB,0xB5,0xFD,0x0B,0x83,0x88,0x72,0xFD,0x7F,0x68,0xBB,
+    0xE9,0x7A,0x88,0x72,0xA8,0xF5,0xDD,0x63,0xE9,0x7A,0x88,0x72,0xB0,0xAA,0xAB,0xDF,
+    0xE9,0x7A,0x88,0x72,0x7E,0xFE,0xAF,0x29,0xE9,0x7A,0x88,0x72,0x95,0xF7,0x7C,0x6E,
+    0xEA,0x7A,0xA9,0x72,0xEB,0xCA,0x8D,0x6D,0xC9,0x7A,0x68,0x72,0x9A,0xF2,0xE8,0xAA,
+    0xE9,0x7A,0x88,0x72,0xAB,0xFD,0x2D,0x0D,0xEA,0x7A,0x89,0x72,0xA2,0x82,0xF0,0xD0,
+    0xEA,0x7A,0xA9,0x72,0xBF,0xBE,0xB7,0xF5,0xEA,0x7A,0x88,0x72,0x82,0x5A,0xB6,0xAA,
+    0x0B,0x7B,0xA9,0x72,0xBD,0xDD,0xBE,0xF8,0x2B,0x83,0xA9,0x72,0x2A,0xEE,0xFF,0xFF,
+    0x0A,0x83,0xA9,0x72,0xA2,0xF2,0xFD,0xB5,0x4B,0x83,0xC9,0x7A,0xFD,0xFF,0x35,0xA7,
+    0x2B,0x83,0xE9,0x7A,0xFF,0xF7,0xDC,0x7F,0x2B,0x83,0xE9,0x7A,0xFA,0xF5,0xCD,0x7D,
+    0xE2,0x38,0xA1,0x30,0x98,0x08,0x02,0x8A,0x03,0x41,0xC2,0x38,0xA9,0xF8,0x0A,0xAB,
+    0x03,0x41,0xC2,0x38,0xFF,0xFF,0x0F,0x8B,0x03,0x41,0xA1,0x30,0xE6,0xBA,0xAA,0xA2,
+    0x03,0x41,0xC2,0x38,0x7E,0x7F,0xCF,0xCB,0x02,0x39,0xA2,0x30,0x27,0x3B,0xAF,0x2F,
+    0x03,0x41,0xC2,0x38,0xFA,0xFE,0xFC,0xF6,0x03,0x41,0xC2,0x38,0xB7,0x95,0x2F,0xAB,
+    0x23,0x41,0xC2,0x38,0x5A,0x78,0xA8,0xFA,0xE2,0x38,0xA1,0x30,0x21,0xA0,0x8A,0x82,
+    0x03,0x41,0xA1,0x30,0x2C,0xA2,0xAE,0xFD,0x23,0x39,0xC2,0x38,0xDF,0xFF,0xF5,0x45,
+    0xE2,0x38,0xC2,0x38,0x00,0x0A,0x9E,0x7F,0x03,0x41,0xC2,0x38,0xDB,0x7B,0xAB,0xFF,
+    0x23,0x41,0xC1,0x30,0x7B,0xFF,0xFF,0xBD,0x03,0x39,0xC2,0x38,0x5A,0x7E,0x06,0x8F,
+    0x02,0x39,0xA1,0x30,0x62,0xFA,0xD2,0x7A,0xE2,0x38,0xC1,0x38,0xA9,0x43,0xCD,0x27,
+    0xA2,0x38,0xE3,0x30,0xBA,0xFB,0xEA,0xAA,0x03,0x41,0xA1,0x30,0xBD,0x97,0xAE,0x2E,
+    0x03,0x41,0xC2,0x38,0x5F,0x7B,0x5E,0x58,0xE2,0x38,0xA2,0x30,0x2E,0xA9,0x43,0x7B,
+    0xC2,0x30,0x81,0x30,0xB8,0xB8,0xFF,0xAB,0x83,0x49,0xC2,0x30,0x25,0x35,0xB5,0x95,
+    0x27,0x62,0xA5,0x59,0xE8,0xE9,0xAE,0xBD,0xE5,0x59,0x84,0x51,0xAA,0x28,0xEA,0x68,
+    0xC5,0x51,0x22,0x41,0xFA,0x78,0xFA,0x82,0x23,0x41,0xC2,0x30,0xAA,0xAF,0xBC,0x98,
+    0x23,0x39,0xC2,0x30,0xEA,0xEA,0x2A,0xFE,0x23,0x39,0xE2,0x30,0x57,0xEE,0xFE,0xBB,
+    0x03,0x31,0xC2,0x28,0xEA,0x5A,0xB8,0xA8,0x03,0x31,0xC2,0x28,0x7E,0xBB,0xBE,0x20,
+    0xE3,0x30,0xC2,0x28,0xD5,0xEF,0xFC,0x5C,0x03,0x31,0xC2,0x28,0xF7,0xEF,0x86,0xAB,
+    0x23,0x39,0xC2,0x28,0x5F,0xFF,0x9F,0x25,0x03,0x31,0xC2,0x28,0xBD,0xB7,0xF8,0xC8,
+    0x03,0x31,0xA2,0x28,0x8A,0x8A,0xBE,0x9E,0x03,0x31,0xA3,0x28,0xA2,0x20,0x80,0xA8,
+    0x03,0x31,0xE3,0x30,0x55,0x5E,0x56,0xD5,0x23,0x31,0xC3,0x30,0xEF,0xEF,0xA7,0x36,
+    0x23,0x39,0xC2,0x28,0xF5,0xFF,0xAE,0xF8,0x03,0x31,0xE3,0x30,0xED,0x33,0x98,0x97,
+    0x03,0x31,0xC2,0x28,0x9A,0xFE,0xEE,0xAE,0x03,0x31,0xC2,0x28,0x00,0xE6,0xEB,0xEE,
+    0x03,0x31,0xC3,0x30,0xAA,0xAB,0xA5,0xAF,0x24,0x39,0xC2,0x30,0x2F,0xBE,0x7A,0x76,
+    0x24,0x39,0xC2,0x28,0xFB,0xB2,0xFB,0xA1,0x24,0x39,0xE3,0x30,0xFA,0xEF,0xCB,0x20,
+    0x44,0x39,0xE3,0x30,0x3D,0xBD,0xFD,0xF7,0x44,0x39,0x03,0x39,0xDF,0xDA,0xDF,0x55,
+    0x23,0x39,0xE3,0x38,0xA8,0xEB,0xEF,0x7F,0x23,0x39,0xE3,0x38,0x8A,0x8F,0x27,0xEF,
+    0x03,0x39,0xC2,0x30,0x8E,0x6C,0xFC,0xE0,0x23,0x41,0xE3,0x30,0x7D,0xFD,0xA8,0xA2,
+    0x03,0x39,0xE2,0x30,0xA7,0x16,0x5C,0xDC,0x64,0x41,0x03,0x39,0x55,0xDC,0x5D,0xED,
+    0x45,0x41,0xE3,0x30,0xAA,0xFA,0x70,0x6A,0x23,0x39,0xE3,0x38,0x7B,0x4B,0x2F,0xBF,
+    0x23,0x39,0xE3,0x30,0x0B,0xE3,0xE8,0xAA,0x23,0x39,0xE2,0x30,0x82,0x02,0x23,0xB5,
+    0x24,0x39,0xE3,0x30,0x8F,0xC0,0x80,0xAA,0x23,0x39,0xE2,0x30,0xB7,0xFF,0xD9,0x6D,
+    0x03,0x39,0xE2,0x30,0xF8,0xC0,0x78,0x4F,0x03,0x39,0xE3,0x30,0x95,0xD5,0xF5,0xEF,
+    0x45,0x41,0xC2,0x30,0x08,0x8A,0x9F,0x57,0x24,0x39,0xE3,0x38,0x80,0xAA,0xFE,0x6F,
+    0x24,0x39,0xE3,0x30,0xAA,0x62,0x7A,0xBA,0x23,0x39,0xE3,0x30,0xAF,0xA2,0xBA,0x98,
+    0x23,0x39,0xE2,0x30,0xBE,0xDA,0x78,0xFA,0x24,0x39,0xE2,0x30,0x7A,0x7E,0xF7,0xA6,
+    0x23,0x39,0xE3,0x30,0xFB,0xCA,0xA7,0x6C,0x03,0x31,0xC2,0x28,0xE0,0xC2,0x1A,0x22,
+    0x44,0x39,0xE2,0x28,0xD5,0xFA,0xEA,0xFE,0x03,0x31,0xC2,0x28,0x37,0xE6,0xAA,0x83,
+    0x03,0x31,0xC2,0x28,0xF6,0x8A,0x3A,0xAA,0x03,0x31,0xC2,0x28,0xE3,0xFE,0xBA,0x22,
+    0x03,0x31,0xC3,0x28,0x7A,0xFD,0xFF,0xEA,0xE3,0x30,0xA2,0x28,0xFB,0x3E,0xEF,0xF7,
+    0xE3,0x30,0xA2,0x28,0xBA,0xB2,0x2B,0x83,0xE3,0x30,0xA2,0x28,0x7A,0xBC,0xEA,0x83,
+    0xE3,0x28,0x82,0x28,0xBA,0xED,0xCD,0x8A,0xC2,0x28,0xA2,0x28,0x4E,0x20,0x03,0x8A,
+    0xE3,0x30,0xA3,0x28,0xFB,0xF2,0xA8,0x2E,0x03,0x31,0xA2,0x28,0xDF,0xBA,0xFF,0x8B,
+    0xE2,0x28,0xA2,0x28,0x57,0xBF,0x0A,0x82,0xE3,0x30,0xA2,0x28,0x59,0x8F,0x00,0x0A,
+    0x03,0x31,0xA2,0x28,0xD5,0x9D,0xAE,0x0A,0x03,0x31,0xC2,0x28,0x9F,0x2F,0x85,0x2A,
+    0x24,0x39,0xE3,0x30,0x57,0x7F,0x4F,0xFF,0x03,0x39,0xE3,0x30,0x09,0x69,0x5D,0xB5,
+    0x44,0x39,0xE3,0x30,0xBF,0xAD,0xB3,0x3F,0x65,0x41,0x24,0x39,0xA9,0x03,0x0B,0xA5,
+    0x07,0x5A,0x65,0x49,0x7F,0xAF,0xAF,0x0F,0x06,0x5A,0xA5,0x49,0xBD,0xE9,0xEC,0x00,
+    0x06,0x5A,0xC6,0x51,0xBF,0x06,0x83,0x0E,0x27,0x62,0xC5,0x51,0x2F,0xF7,0xCE,0xA2,
+    0x26,0x62,0xC5,0x51,0xBE,0x9E,0xAB,0xAB,0x47,0x62,0x07,0x62,0xF3,0xEA,0x6E,0xDD,
+    0x68,0x6A,0x07,0x62,0xB5,0x25,0x07,0x22,0xA9,0x72,0x48,0x6A,0x6B,0xA2,0xFF,0xAB,
+    0xA9,0x72,0x48,0x6A,0x3A,0x3D,0xFF,0xFB,0xEA,0x7A,0x68,0x6A,0xFC,0xFB,0x7B,0x7D,
+    0xEA,0x7A,0x89,0x72,0x2B,0xAA,0xFD,0xF5,0xC9,0x7A,0x88,0x6A,0x0B,0xAF,0x7F,0x6E,
+    0xC9,0x7A,0x47,0x62,0x6A,0xA8,0x02,0x2B,0xE9,0x7A,0x68,0x6A,0x57,0xBF,0xEE,0x0A,
+    0xC9,0x72,0x88,0x72,0xE8,0xEE,0x1F,0xFA,0xEA,0x7A,0x87,0x6A,0x75,0x77,0xAA,0x2F,
+    0xC8,0x7A,0x67,0x6A,0x0A,0x8D,0xA8,0xA8,0xE9,0x7A,0x68,0x72,0x23,0xAA,0xAE,0xDE,
+    0xE9,0x7A,0xA9,0x72,0xF1,0x42,0x80,0xA9,0xEA,0x7A,0x88,0x72,0x3F,0xE6,0xFC,0xAF,
+    0xEA,0x7A,0xA9,0x7A,0xC2,0xA3,0xA9,0x58,0x0A,0x83,0xA8,0x72,0x7F,0x7A,0x62,0xC9,
+    0xE9,0x7A,0x88,0x72,0x0B,0x37,0x97,0xA3,0x09,0x7B,0xA9,0x72,0xA4,0xF2,0xEB,0xD4,
+    0xC9,0x7A,0x88,0x72,0xF8,0xCE,0x6A,0x63,0xEA,0x7A,0x88,0x72,0xCB,0xBF,0xAD,0x82,
+    0x0A,0x7B,0xA8,0x72,0xED,0xA7,0x8B,0xA3,0x0A,0x7B,0xC9,0x7A,0xFB,0xAA,0xEA,0xFC,
+    0xEA,0x7A,0x88,0x6A,0xFA,0xF6,0x8A,0x08,0xEA,0x7A,0x68,0x6A,0x8F,0xA7,0xB7,0xEA,
+    0xEA,0x7A,0xA9,0x72,0x20,0x10,0xBF,0x5E,0xEA,0x7A,0xA9,0x72,0x85,0x02,0xB2,0xFD,
+    0x0A,0x83,0xA9,0x72,0x5D,0xFD,0x7F,0x8E,0x0A,0x83,0xA9,0x72,0x27,0xB7,0xDD,0xEF,
+    0x2A,0x83,0xC9,0x7A,0x8E,0xCB,0xA5,0xD5,0x0A,0x83,0xC9,0x7A,0x38,0x7E,0x7E,0xBA,
+    0xE2,0x38,0xC2,0x38,0x5B,0x5B,0x0A,0xC8,0x23,0x39,0xC2,0x38,0xE7,0x26,0xEF,0xAA,
+    0x23,0x39,0xC2,0x38,0xFD,0xFF,0xF3,0xFB,0x02,0x39,0xC2,0x38,0xEF,0xF8,0xEA,0x9F,
+    0x03,0x41,0xA1,0x30,0xA2,0xAA,0xBA,0xFE,0x03,0x41,0xC2,0x38,0xA7,0x78,0x5A,0xD7,
+    0xE2,0x38,0xC2,0x38,0xD0,0xBF,0x0F,0x21,0x23,0x41,0xC2,0x38,0x6D,0xFD,0xCF,0xE3,
+    0x02,0x39,0xC2,0x38,0xFA,0x4A,0xE3,0xFF,0xE2,0x38,0xA1,0x30,0x20,0xB2,0x2F,0x2E,
+    0x03,0x41,0xA1,0x30,0xB7,0x8A,0xEA,0xBA,0x02,0x39,0xC2,0x38,0xAB,0x8B,0x4B,0x78,
+    0xE2,0x38,0xA1,0x30,0x88,0x20,0x02,0x0B,0xE2,0x38,0xA1,0x30,0xA0,0xA0,0x60,0xE8,
+    0x03,0x41,0xC2,0x38,0xEF,0xD9,0xFF,0x2F,0x02,0x39,0xC2,0x38,0xB7,0xFF,0xFF,0x68,
+    0x02,0x39,0xC2,0x38,0xF6,0xDA,0xF7,0xDD,0xE2,0x38,0xA2,0x30,0x8E,0x00,0x28,0x0C,
+    0x03,0x41,0xC2,0x38,0x49,0xE7,0xF5,0xD7,0x03,0x39,0xC2,0x38,0x1D,0x2F,0x29,0x08,
+    0x03,0x41,0xC2,0x38,0x6E,0x7A,0x78,0x78,0xC2,0x38,0xA1,0x30,0xC0,0xFA,0xFE,0x50,
+    0xE2,0x38,0xA1,0x30,0x5F,0xE5,0x25,0x35,0x85,0x51,0xA1,0x30,0xB5,0xB5,0xB7,0x37,
+    0xA8,0x72,0x43,0x49,0xBD,0xEF,0xEA,0xA2,0xE5,0x59,0x84,0x51,0x68,0xCB,0x0A,0x08,
+    0xC5,0x51,0x84,0x49,0x42,0x62,0xFE,0x7E,0x23,0x41,0xC2,0x30,0xF8,0x50,0xF8,0xF8,
+    0x03,0x39,0xC2,0x30,0xAF,0x6F,0x5F,0x80,0x03,0x31,0xC2,0x28,0x02,0x23,0x22,0x1F,
+    0x03,0x31,0xE3,0x30,0xBE,0x5C,0x57,0x5F,0x24,0x39,0xE3,0x30,0x5A,0x7F,0xFD,0x6B,
+    0x23,0x31,0xC2,0x30,0x77,0xFE,0x5F,0xBF,0x03,0x39,0xC2,0x28,0xFF,0x7B,0xAB,0xF2,
+    0x03,0x31,0xC2,0x30,0x87,0xFD,0xEA,0xEA,0x03,0x31,0xA2,0x28,0xCA,0xEE,0x6B,0xBF,
+    0x03,0x31,0xC2,0x30,0xD7,0xF5,0xB9,0x8B,0x03,0x31,0xC2,0x30,0xEA,0x78,0x7A,0x62,
+    0x03,0x31,0xC2,0x30,0x83,0xBB,0xFB,0xF5,0x03,0x31,0xA2,0x30,0x28,0xAA,0xAE,0x8A,
+    0x03,0x31,0xC2,0x30,0xE8,0xBA,0xE2,0x6A,0x03,0x31,0xC2,0x28,0x8A,0x0B,0xA9,0x3D,
+    0x24,0x39,0xC2,0x30,0xFF,0x8E,0x2B,0x9F,0xE3,0x30,0xC2,0x28,0xEA,0xAE,0xEC,0xFE,
+    0x24,0x39,0xE3,0x30,0x79,0xEA,0x7F,0x55,0x03,0x31,0xA2,0x30,0xBA,0xAE,0x2A,0x22,
+    0x24,0x39,0xE3,0x30,0x89,0x5D,0x55,0x57,0x24,0x39,0xC2,0x30,0x82,0xEA,0xB7,0xBF,
+    0x24,0x39,0xE2,0x30,0xFE,0x7A,0x6B,0x5F,0x03,0x39,0xC2,0x30,0xA2,0xBB,0xEB,0xCF,
+    0x03,0x39,0xE3,0x30,0xA8,0x2E,0x2B,0x95,0x24,0x39,0xE2,0x30,0xEB,0xAA,0xFA,0x7F,
+    0x03,0x39,0xE3,0x30,0xC1,0x68,0x78,0xF3,0x03,0x39,0xE3,0x30,0xC3,0xC7,0xEE,0x8B,
+    0x44,0x41,0xC2,0x30,0xDF,0x2E,0xFF,0x7D,0x24,0x39,0xE3,0x38,0xE0,0xFA,0xEB,0xEB,
+    0x44,0x41,0xE3,0x30,0xA3,0xEB,0x7F,0x5F,0x03,0x39,0xE3,0x38,0x9C,0xB8,0x5B,0x1B,
+    0x24,0x39,0xE3,0x38,0xEB,0x8B,0xFD,0xD7,0x03,0x39,0xE3,0x30,0x20,0x00,0x82,0x83,
+    0x44,0x41,0x03,0x39,0x55,0xAF,0xAD,0x6D,0x23,0x39,0xE3,0x30,0x0B,0x89,0xAA,0xB7,
+    0x23,0x39,0xE2,0x38,0xCB,0xC2,0xC2,0xFA,0x24,0x39,0xE3,0x30,0xBD,0x6D,0xBF,0x17,
+    0x24,0x39,0xC2,0x30,0xF7,0xAE,0xEC,0xB8,0x03,0x39,0xE3,0x30,0xFE,0x7D,0x9E,0x23,
+    0x24,0x39,0xC3,0x30,0xAA,0xB5,0xBA,0xF8,0x23,0x39,0xC4,0x30,0x0A,0x2A,0xB2,0xAA,
+    0x23,0x39,0x03,0x31,0x7F,0x7E,0xB6,0x95,0x23,0x39,0xE2,0x30,0xE7,0x2F,0x2C,0x32,
+    0x44,0x39,0xE2,0x30,0xFB,0x7E,0xFA,0x8A,0x23,0x39,0xC2,0x28,0xAA,0x9A,0xBE,0x2A,
+    0x23,0x39,0xE3,0x30,0x5A,0xFF,0xBE,0xAA,0x03,0x31,0xE3,0x30,0x29,0xFD,0xD7,0x2C,
+    0x24,0x39,0xE3,0x30,0xF8,0xFF,0xFA,0xE2,0x24,0x39,0xE3,0x28,0xDF,0xDF,0xBA,0xB3,
+    0x24,0x39,0xE3,0x30,0x73,0xFA,0xA0,0xAA,0x04,0x31,0xC3,0x28,0xD7,0xD7,0xBC,0x30,
+    0x04,0x31,0xE3,0x30,0x55,0xF5,0xEB,0x70,0x24,0x31,0xE3,0x30,0x7F,0x8F,0xEF,0x97,
+    0x03,0x31,0xC2,0x28,0xEF,0xE0,0xE8,0xA0,0x03,0x31,0xA2,0x28,0xB7,0xEA,0xA2,0xA0,
+    0x03,0x31,0xC2,0x28,0x36,0xA2,0x03,0xA2,0x23,0x31,0xE3,0x30,0xD5,0xF7,0xFD,0xFA,
+    0xE3,0x30,0x03,0x29,0x2F,0x2B,0xB0,0x20,0x24,0x39,0xC2,0x28,0xDF,0xFA,0xE2,0x22,
+    0x24,0x39,0xE3,0x30,0xBF,0x83,0x81,0xAA,0x24,0x39,0x03,0x31,0x57,0x57,0xFF,0x3F,
+    0x44,0x41,0xE3,0x30,0x7D,0xF8,0xEE,0xFE,0x24,0x39,0xE3,0x30,0x37,0xAA,0x22,0x20,
+    0x64,0x41,0x03,0x31,0x27,0x2D,0xAB,0x2A,0xC5,0x51,0x43,0x39,0xD5,0xBF,0xAF,0x2A,
+    0x07,0x5A,0xA5,0x49,0xB5,0xBF,0xBF,0x3F,0x27,0x62,0xE6,0x59,0xC8,0xAE,0x05,0x27,
+    0x27,0x62,0xE6,0x59,0x2F,0xBC,0xD6,0x78,0x47,0x62,0xE5,0x59,0x6A,0xA2,0xBD,0x2D,
+    0x27,0x62,0xC5,0x59,0x6E,0xC0,0xC8,0xE0,0x68,0x6A,0xE6,0x59,0x3D,0xAD,0x35,0xA5,
+    0x88,0x6A,0x27,0x62,0xBF,0xD7,0xDF,0x87,0xA9,0x6A,0x48,0x6A,0xEF,0xAE,0xCB,0xE7,
+    0xA8,0x6A,0x48,0x6A,0x7B,0x7F,0x77,0xDF,0x68,0x6A,0x47,0x62,0x8B,0xE3,0xF2,0xE1,
+    0xA9,0x72,0x27,0x62,0x2F,0xBB,0xB7,0xEB,0xA9,0x72,0x68,0x6A,0x2C,0x8F,0x3D,0xBD,
+    0xA9,0x72,0x48,0x6A,0x0B,0x02,0x72,0xF0,0xC9,0x7A,0x67,0x6A,0x2A,0xBB,0xEB,0xFD,
+    0xE9,0x7A,0x88,0x72,0x78,0x2E,0xD9,0x55,0xC9,0x7A,0x47,0x62,0x2F,0x94,0xBA,0xAA,
+    0xC9,0x7A,0x88,0x72,0xBA,0xBA,0x2A,0xEF,0xC9,0x7A,0x67,0x6A,0xEA,0xA2,0x00,0x8A,
+    0xC9,0x7A,0xA8,0x72,0x8A,0xE9,0x72,0xFC,0xE9,0x7A,0x88,0x72,0xE3,0xEE,0x77,0x5F,
+    0xEA,0x7A,0xA9,0x72,0x62,0xEB,0x9D,0x5F,0x0A,0x7B,0xA8,0x72,0xEF,0xFD,0xFF,0x9F,
+    0x0A,0x7B,0xA8,0x72,0xCB,0xF3,0x6B,0xAB,0xE9,0x7A,0xA8,0x72,0xEC,0xAD,0x8F,0x7F,
+    0x0A,0x7B,0xA8,0x72,0xD7,0xA7,0x0E,0x3B,0x0A,0x83,0xA9,0x6A,0xEE,0xD7,0xF7,0xE2,
+    0xEA,0x7A,0xA9,0x72,0xE8,0x47,0xBF,0x5F,0xEA,0x7A,0xA9,0x72,0xBF,0xFA,0xFB,0x7E,
+    0xEA,0x7A,0xA9,0x72,0x3C,0xAA,0xBC,0x4F,0xEA,0x7A,0x89,0x72,0x9A,0xFE,0x0E,0x06,
+    0xEA,0x7A,0xA9,0x72,0x7E,0xB3,0xAE,0xFF,0xEA,0x7A,0x88,0x6A,0xEF,0x58,0xA2,0x00,
+    0x0B,0x83,0xA9,0x72,0x82,0xBD,0x97,0xBF,0x0A,0x7B,0xC9,0x7A,0xFC,0xAB,0x62,0xCE,
+    0x0A,0x7B,0xA8,0x72,0xDF,0xBE,0x3B,0xA3,0x0A,0x83,0xC9,0x7A,0x83,0x01,0xC0,0xFE,
+    0x23,0x41,0xC2,0x38,0xFE,0xBC,0xFF,0x7F,0x02,0x39,0xC2,0x38,0xA0,0xBE,0xBF,0x7D,
+    0x23,0x41,0xC2,0x38,0x5E,0xFA,0xBB,0xCF,0xC2,0x40,0x03,0x39,0xFB,0xEF,0xAB,0x9F,
+    0x03,0x41,0xC2,0x38,0x5E,0xAC,0xA9,0xBD,0x03,0x41,0xC2,0x38,0xD5,0xFF,0xEA,0xC0,
+    0x23,0x41,0xC2,0x38,0xBD,0xD5,0xD7,0x7F,0x03,0x41,0xC2,0x38,0x98,0x9D,0xF7,0xD5,
+    0x03,0x41,0xA1,0x30,0x9A,0xE2,0x88,0xAF,0x03,0x39,0xC2,0x38,0xFF,0xAF,0x0A,0x2B,
+    0x03,0x41,0xC2,0x38,0xDB,0xF8,0x7A,0xF6,0xE2,0x38,0xC1,0x30,0x78,0x18,0x00,0x82,
+    0xE2,0x38,0xC2,0x38,0x7F,0x70,0x60,0x0F,0x03,0x41,0xA1,0x30,0x7E,0xEF,0xAB,0xAA,
+    0x03,0x41,0xC2,0x38,0x8B,0x79,0x7E,0xFE,0xE2,0x38,0xA2,0x30,0x00,0x8A,0xF0,0x20,
+    0xE2,0x38,0xC2,0x38,0x73,0xEB,0x00,0xE0,0xE3,0x38,0xC2,0x38,0x2C,0xDE,0xD4,0xF0,
+    0xE2,0x38,0xC2,0x38,0x0B,0xE2,0x6B,0xED,0x03,0x41,0xC2,0x38,0xDE,0x55,0xFB,0xE3,
+    0x03,0x39,0xA2,0x30,0xE2,0x6A,0xFA,0xDE,0xC2,0x38,0x81,0x30,0xBE,0xAA,0x28,0x37,
+    0xE2,0x38,0xA2,0x30,0x25,0x3F,0x0A,0x03,0x26,0x62,0xE2,0x38,0xBD,0x35,0x2D,0x2D,
+    0xC8,0x7A,0x47,0x6A,0x7F,0xEA,0xE2,0xC0,0x47,0x6A,0xE5,0x59,0x7B,0x78,0x7A,0xEA,
+    0xE6,0x59,0x64,0x49,0xFC,0x7E,0x72,0x7A,0x43,0x41,0xC2,0x30,0xDE,0xDE,0xFE,0xF2,
+    0x23,0x39,0xE2,0x30,0xF3,0x59,0xDE,0xFF,0x03,0x39,0xC2,0x28,0x7B,0xEB,0xAE,0xF0,
+    0x03,0x31,0xE3,0x30,0x40,0x7A,0xDF,0xD7,0x03,0x31,0xC3,0x30,0x82,0x8A,0x3E,0xDE,
+    0x03,0x31,0xE3,0x30,0x35,0xD7,0x57,0x59,0x03,0x31,0xC3,0x30,0xE0,0xF2,0xB0,0xB0,
+    0x03,0x31,0xE3,0x30,0xB5,0x65,0x65,0xBD,0x03,0x31,0xC2,0x28,0xFF,0xFE,0xFA,0xA2,
+    0xE2,0x30,0xC2,0x28,0x02,0x09,0x0B,0x30,0x03,0x31,0xC2,0x30,0xAB,0xD7,0xFF,0xFB,
+    0xE3,0x30,0xC3,0x28,0x3A,0xAC,0x08,0xAA,0x03,0x31,0xC3,0x30,0xA2,0x8B,0x0A,0xA9,
+    0xE3,0x30,0xC2,0x30,0x00,0x0C,0x83,0xD8,0xE3,0x30,0xC2,0x28,0x08,0x8C,0xB8,0x60,
+    0x03,0x31,0xC2,0x28,0xBE,0xFB,0xA9,0xEB,0x03,0x39,0xC3,0x28,0xB7,0xF7,0xAA,0xEB,
+    0x03,0x31,0xC2,0x30,0x9F,0x0E,0xEA,0xEB,0x03,0x31,0xC3,0x30,0x0F,0x2B,0x2F,0xAF,
+    0x03,0x31,0xE3,0x30,0x86,0xE7,0x77,0xBD,0xA2,0x38,0x03,0x31,0xDF,0x7F,0xFF,0xBD,
+    0x03,0x39,0xC2,0x30,0xB8,0xD8,0xDE,0xC2,0x03,0x39,0xC2,0x30,0x2F,0x1D,0x9F,0xDF,
+    0x03,0x31,0xC2,0x30,0x97,0x08,0x0C,0x2A,0x03,0x39,0xE2,0x30,0xC0,0xE3,0xB6,0xA8,
+    0x03,0x39,0xE2,0x30,0x32,0xBF,0xFF,0xA3,0x24,0x39,0xC2,0x30,0xA8,0xF7,0x9D,0xFF,
+    0xE3,0x38,0xA2,0x30,0xB8,0xBE,0xBE,0xEE,0x03,0x39,0xC2,0x30,0xA2,0xA3,0xB9,0x0D,
+    0x03,0x39,0xC3,0x30,0xB0,0xC8,0xAA,0xEA,0x24,0x39,0xC2,0x30,0x2B,0xFF,0x67,0xFE,
+    0x03,0x39,0xE3,0x30,0x1B,0x15,0x2D,0x01,0x03,0x39,0xC3,0x30,0x00,0x0A,0xAE,0x3E,
+    0x23,0x39,0xE3,0x30,0x8E,0x27,0x97,0x35,0x23,0x39,0xE3,0x38,0x7F,0xB0,0xAF,0xB7,
+    0x03,0x39,0xC3,0x30,0x3B,0x07,0xFF,0x20,0x24,0x39,0xE3,0x30,0x7F,0x6E,0xAB,0xB8,
+    0x44,0x41,0xE3,0x30,0xEB,0xEA,0x6A,0xDB,0x24,0x39,0xC2,0x30,0xBA,0xB6,0xBB,0x2A,
+    0x03,0x39,0xE3,0x38,0x28,0x20,0xA0,0x28,0x24,0x41,0xE3,0x30,0xFE,0xDE,0xAB,0x03,
+    0x24,0x39,0xE3,0x30,0x9F,0xD5,0x2E,0xAC,0x23,0x39,0xE2,0x30,0x2B,0x20,0x20,0x7A,
+    0x44,0x39,0xE2,0x30,0x2E,0xAA,0xFE,0xF5,0x44,0x39,0xE2,0x30,0xAA,0xA8,0xA7,0xBD,
+    0x44,0x39,0x03,0x31,0x2D,0x2B,0x9F,0x2E,0x44,0x39,0x03,0x39,0x57,0xFE,0xEB,0xA2,
+    0x44,0x39,0xE3,0x30,0xEF,0x76,0xA8,0xE0,0x24,0x39,0x03,0x31,0xF9,0xF5,0x8B,0x03,
+    0x44,0x39,0x03,0x31,0xB5,0xAA,0xEA,0x08,0x24,0x39,0xE3,0x30,0xBE,0xBC,0xA8,0x8A,
+    0x24,0x39,0xC2,0x30,0xBF,0xF6,0x2E,0xA8,0x24,0x39,0xE3,0x30,0xB8,0x5A,0xFE,0xCA,
+    0x24,0x39,0xE3,0x30,0xDA,0xBF,0xBD,0x23,0x24,0x39,0xE3,0x30,0x56,0xBE,0xFD,0xCE,
+    0x24,0x39,0xE3,0x30,0xBA,0xCE,0x6B,0xCB,0x24,0x39,0xE3,0x30,0xB0,0xAB,0x69,0x6A,
+    0x45,0x41,0xC2,0x30,0xF7,0xF7,0xAF,0xA8,0x24,0x39,0x03,0x31,0x9D,0xF5,0x96,0xA6,
+    0x24,0x39,0xE3,0x30,0xEB,0xEA,0xEA,0x8B,0x24,0x39,0xE3,0x30,0x20,0x02,0x07,0x89,
+    0x65,0x41,0x03,0x39,0x5C,0xF5,0xF7,0xF5,0x65,0x49,0x03,0x39,0xF7,0xFA,0xA3,0x8A,
+    0xA6,0x49,0x44,0x41,0x7D,0x75,0x7F,0x0B,0xE7,0x51,0x65,0x41,0x3D,0xAD,0x2B,0x8A,
+    0x06,0x5A,0xA5,0x51,0x9A,0xAB,0x2A,0x8A,0x07,0x62,0xA5,0x51,0xFE,0x9B,0xC2,0xE0,
+    0x27,0x62,0xC6,0x59,0xC0,0xFE,0x5F,0x95,0x47,0x62,0xE6,0x59,0x3F,0xBD,0xBB,0x8F,
+    0x88,0x6A,0xE6,0x59,0xD7,0xFB,0xA2,0xEA,0x68,0x62,0x06,0x5A,0xB7,0x3E,0x8A,0xEA,
+    0x89,0x6A,0x27,0x62,0x89,0x0D,0xE9,0xEF,0x88,0x72,0x47,0x62,0xCA,0x79,0xFB,0xFE,
+    0xA9,0x72,0x48,0x62,0xFE,0x6A,0x7B,0x7C,0x88,0x6A,0x48,0x6A,0xFF,0xAF,0xF5,0xFF,
+    0x88,0x72,0x48,0x6A,0xE8,0x7E,0xFF,0x2F,0xA9,0x72,0x68,0x6A,0xDD,0xD5,0xE9,0x8A,
+    0xA9,0x72,0x68,0x6A,0x76,0x9C,0xFE,0xBB,0xA9,0x72,0x47,0x6A,0xEC,0x98,0x37,0xB7,
+    0xC9,0x72,0x88,0x6A,0x55,0x53,0x2A,0x8D,0xC9,0x72,0x88,0x72,0xED,0xAE,0xB8,0xB6,
+    0xE9,0x7A,0x88,0x72,0x6F,0xFF,0x5E,0xF8,0xC9,0x7A,0x88,0x72,0x6F,0xAF,0xDA,0x8B,
+    0xA8,0x72,0x48,0x6A,0x08,0x0A,0xDC,0xF8,0xC9,0x7A,0x68,0x6A,0x2A,0xBC,0xF7,0xFA,
+    0xE9,0x7A,0x88,0x72,0x7A,0xE6,0x0F,0xAB,0xC9,0x72,0x68,0x6A,0x32,0x76,0xFF,0xBC,
+    0xE9,0x7A,0x88,0x72,0xA8,0x2B,0xF2,0xB5,0x0A,0x7B,0xA8,0x72,0x5F,0x77,0xC3,0x3A,
+    0xEA,0x72,0x88,0x6A,0x3F,0xFE,0x6A,0xEC,0x0A,0x7B,0xA9,0x72,0x8A,0xAF,0xF7,0x7F,
+    0xEA,0x7A,0x88,0x6A,0xBA,0x22,0x7A,0xEB,0xEA,0x7A,0xA9,0x72,0x5B,0xA0,0xA9,0x29,
+    0xEA,0x7A,0x88,0x6A,0x0F,0xAB,0xA7,0x0F,0x0B,0x83,0x67,0x6A,0x0A,0xC2,0xFE,0x97,
+    0xE9,0x7A,0xA9,0x72,0xDF,0xBE,0xA3,0x4F,0x2A,0x7B,0xCA,0x7A,0xED,0x7D,0xFF,0x6F,
+    0x0A,0x7B,0xC9,0x7A,0x72,0xBF,0x2F,0x2F,0x2A,0x83,0xC9,0x72,0xF5,0xCF,0xC3,0xEB,
+    0xE9,0x7A,0x87,0x6A,0xC0,0x40,0xAA,0xA8,0x0A,0x7B,0xA9,0x72,0xE5,0x25,0xAC,0xEF,
+    0x03,0x41,0xC2,0x38,0xEE,0xC8,0xF6,0xE6,0x03,0x41,0xC2,0x38,0xA9,0xCB,0xCF,0xEF,
+    0x03,0x41,0xE2,0x38,0xE7,0x55,0x85,0xA9,0x03,0x41,0xC2,0x38,0x8B,0xFB,0x7A,0x68,
+    0x03,0x41,0xC2,0x38,0xBA,0xFB,0xA1,0xCB,0x23,0x41,0xC2,0x38,0xEA,0x3B,0xDE,0x9A,
+    0xC3,0x40,0x02,0x39,0xFF,0xBF,0xF5,0xDF,0x03,0x41,0xC2,0x38,0xD7,0x2D,0xE2,0xFA,
+    0x03,0x41,0xA2,0x30,0xBF,0xFF,0x62,0xCA,0xE3,0x38,0xA1,0x30,0xB0,0x9F,0xAD,0x3D,
+    0xE2,0x38,0xC2,0x30,0x2F,0x7C,0x20,0x80,0x03,0x41,0xC2,0x38,0x3F,0x2D,0x8B,0xBF,
+    0x03,0x41,0xA1,0x30,0xBE,0xB6,0xAE,0x82,0x03,0x41,0xC2,0x38,0xF6,0xFF,0x26,0xBA,
+    0x03,0x41,0xC2,0x38,0xFF,0xDF,0x7A,0x8F,0xC2,0x38,0xE2,0x30,0x3A,0xA2,0x20,0x2B,
+    0xC2,0x38,0xE2,0x30,0xAA,0x80,0x20,0xAB,0x03,0x41,0xA1,0x30,0xEB,0xEF,0xF9,0x8E,
+    0x03,0x39,0xC2,0x38,0x7F,0x7F,0x7E,0xFE,0x03,0x39,0xA2,0x30,0xE3,0xE3,0xEB,0x7A,
+    0xE2,0x38,0x81,0x30,0x62,0x5E,0xBA,0xAF,0xE3,0x38,0x81,0x28,0x97,0xA7,0x82,0x88,
+    0x03,0x39,0xA2,0x30,0xE1,0xEB,0xFD,0xB5,0xC7,0x7A,0xE2,0x38,0x2D,0x2D,0x2D,0x25,
+    0x08,0x83,0x67,0x6A,0xE2,0x6A,0xFA,0xEA,0x67,0x6A,0x64,0x49,0xA8,0xE8,0xE0,0x78,
+    0xC5,0x59,0x03,0x39,0xF0,0xFE,0xD6,0x57,0x44,0x41,0xE2,0x30,0xEB,0xF2,0x72,0xEA,
+    0x23,0x39,0xC2,0x28,0x2A,0xFA,0x6F,0xEE,0x03,0x31,0xC2,0x28,0xB0,0xA9,0xFD,0xE9,
+    0x03,0x31,0xC2,0x28,0xAB,0xEE,0xAF,0xAF,0x03,0x31,0xC2,0x30,0xF2,0x82,0xB2,0xA1,
+    0x03,0x31,0xC3,0x30,0xEB,0x01,0x2F,0xBA,0x03,0x31,0xC2,0x28,0xE2,0xE8,0x80,0x42,
+    0x03,0x31,0xC2,0x28,0x3E,0x2B,0x2A,0xAD,0x03,0x31,0xC3,0x30,0x0E,0x0B,0xE8,0xF8,
+    0xE3,0x30,0xC2,0x28,0xEC,0xCE,0xA7,0x02,0x03,0x31,0xC3,0x30,0xBD,0x9D,0xD7,0xBF,
+    0xE3,0x30,0xC2,0x28,0xA2,0xEA,0xF0,0xE7,0xE3,0x30,0xC2,0x28,0x02,0x01,0x6A,0x86,
+    0x03,0x31,0xC3,0x30,0xFA,0x2E,0x63,0x63,0x03,0x31,0xC2,0x28,0xFA,0x92,0xDB,0xBF,
+    0x03,0x31,0xC2,0x30,0xFE,0xFE,0xAB,0x8E,0x03,0x31,0xC3,0x30,0x7B,0xFF,0x2A,0x0E,
+    0x03,0x31,0xA2,0x28,0xFA,0xD6,0xFE,0xCC,0xE3,0x30,0xA2,0x28,0x22,0xFA,0xA1,0x0B,
+    0x03,0x31,0xC2,0x28,0x2A,0xA9,0x5F,0x7E,0x03,0x31,0xC2,0x30,0x7C,0xF7,0x65,0x73,
+    0xE3,0x30,0xC2,0x28,0x00,0x2B,0x95,0xDA,0x23,0x39,0xC2,0x28,0xF2,0xCB,0xF7,0xB7,
+    0x03,0x31,0xE2,0x30,0xC3,0xC2,0xCF,0x57,0x23,0x31,0xC2,0x30,0xA7,0x6E,0xE3,0xE3,
+    0x03,0x31,0xC2,0x30,0x02,0x20,0xEC,0x68,0x03,0x39,0xC2,0x30,0x88,0x00,0xF8,0x0B,
+    0x03,0x39,0xC2,0x30,0x7E,0xEA,0xA2,0x0A,0x03,0x39,0xC3,0x30,0x2A,0x37,0xAB,0xDB,
+    0x24,0x39,0xE3,0x30,0xEE,0xAA,0xAE,0xF5,0x24,0x39,0xC3,0x30,0xC2,0x7A,0xB8,0xB2,
+    0x24,0x39,0xE3,0x30,0xA9,0xAF,0xAB,0xB7,0x24,0x39,0xE3,0x30,0x55,0xDE,0xF7,0x7A,
+    0x24,0x41,0xE3,0x30,0x09,0xBE,0xBD,0x65,0x24,0x39,0xE3,0x38,0xB4,0x36,0xF4,0xD7,
+    0x24,0x41,0xC3,0x30,0x8A,0x88,0xE3,0xDA,0x24,0x39,0xE3,0x38,0x57,0xFB,0xE2,0x2F,
+    0x24,0x39,0xE3,0x38,0x6D,0x7A,0x72,0xEC,0x24,0x39,0xE3,0x38,0x33,0x3B,0x39,0xB7,
+    0x24,0x39,0xE3,0x30,0xBF,0xB6,0xA2,0xA2,0x24,0x39,0x03,0x39,0xBE,0x55,0x5F,0x55,
+    0x23,0x39,0xE4,0x30,0xFA,0xEA,0xEB,0xA2,0x03,0x39,0xC2,0x30,0x3F,0xBF,0xEE,0x02,
+    0x24,0x39,0xE3,0x30,0xDF,0xD7,0xFC,0xAB,0x03,0x31,0xC2,0x30,0x22,0xBF,0x2E,0x00,
+    0x24,0x39,0xE2,0x30,0x3A,0xBF,0x78,0xA8,0x65,0x41,0xE3,0x30,0xE3,0xBB,0xA5,0xA7,
+    0x64,0x41,0x04,0x31,0x7B,0xEE,0xF0,0xAB,0x44,0x39,0x03,0x31,0xAA,0xE2,0xE8,0x70,
+    0x44,0x41,0x24,0x39,0xCB,0x79,0x55,0x35,0x44,0x39,0x04,0x39,0x6A,0x6B,0x7A,0xBA,
+    0x24,0x41,0x03,0x31,0xF7,0xBE,0xA7,0x0E,0x64,0x41,0x03,0x39,0xFD,0xF7,0xE5,0xFF,
+    0x44,0x41,0xE3,0x30,0xF2,0xE2,0xC2,0xAA,0x44,0x39,0xE3,0x30,0x62,0x62,0xBB,0xAB,
+    0x44,0x41,0xE3,0x30,0xEB,0x73,0xBA,0xB2,0x24,0x41,0x03,0x31,0x7F,0xAF,0xBB,0x08,
+    0x44,0x41,0xE3,0x30,0xB7,0xFB,0xBA,0xA8,0x44,0x41,0x03,0x39,0x7E,0xFA,0x2F,0x01,
+    0x65,0x41,0x03,0x39,0xDD,0xF7,0xCA,0x23,0x65,0x41,0x04,0x39,0x75,0xF7,0x2E,0x0C,
+    0xC6,0x51,0xE3,0x38,0x5F,0x5F,0xAF,0x2B,0xC6,0x51,0x24,0x39,0xBD,0xFD,0x2B,0x00,
+    0x27,0x62,0x85,0x49,0xF5,0xBD,0xA3,0xA2,0x27,0x62,0xA5,0x49,0xBD,0xFE,0xAE,0x0A,
+    0x27,0x62,0xC6,0x51,0xED,0xEF,0xFA,0xA8,0x07,0x62,0xE6,0x59,0xBA,0x95,0xB5,0x2F,
+    0x47,0x6A,0xE6,0x59,0xBD,0xAB,0x02,0x80,0x47,0x62,0x07,0x62,0x3D,0x62,0x02,0x00,
+    0x88,0x6A,0x27,0x62,0xD2,0x42,0x7D,0x5F,0x68,0x6A,0x07,0x62,0xAE,0xAA,0x1F,0xBD,
+    0xA8,0x72,0x47,0x6A,0x7D,0xAA,0xAF,0xDF,0xA9,0x72,0x47,0x62,0xA7,0xBF,0xB8,0xFA,
+    0xA8,0x72,0x48,0x62,0xEF,0x5E,0xFE,0xA8,0xA9,0x72,0x27,0x62,0xAA,0x3E,0xA7,0x2A,
+    0xA9,0x72,0x68,0x6A,0xD6,0x77,0xCF,0x9E,0xCA,0x72,0x48,0x6A,0xAD,0xAB,0xAB,0x78,
+    0xA8,0x72,0x47,0x62,0xAA,0x2E,0xFF,0xB8,0xA9,0x72,0x67,0x6A,0xEE,0x46,0xA0,0x02,
+    0xA8,0x72,0x47,0x62,0x0B,0x89,0x27,0x02,0xC9,0x7A,0x88,0x6A,0xAA,0x9B,0x6F,0xE1,
+    0xEA,0x7A,0x67,0x6A,0xF8,0xB6,0xBF,0xFD,0xC9,0x72,0xA8,0x72,0xAD,0x15,0xBF,0x7A,
+    0xC9,0x72,0x68,0x6A,0x7C,0xFB,0xC9,0xAB,0xC9,0x72,0x89,0x72,0x43,0x89,0xBF,0xAA,
+    0xEB,0x7A,0xA9,0x72,0xD5,0xD5,0xF3,0xAF,0xC9,0x72,0x88,0x6A,0xF5,0xF5,0x96,0xE2,
+    0xC8,0x72,0x68,0x6A,0xFE,0xFA,0x2B,0x1F,0xC9,0x72,0x67,0x6A,0x30,0xAE,0xEA,0xAA,
+    0xC9,0x72,0x88,0x72,0x00,0x0B,0x3D,0x9A,0xE9,0x7A,0x68,0x6A,0x68,0xEA,0xBC,0xFA,
+    0xEA,0x7A,0x88,0x6A,0xD5,0xBB,0xA3,0xAD,0xEA,0x7A,0xA9,0x72,0x81,0x02,0x7E,0xAD,
+    0xEA,0x7A,0xA9,0x72,0x39,0x28,0x03,0x2A,0x0A,0x7B,0xA8,0x72,0x56,0x8E,0x2C,0xBE,
+    0x0A,0x7B,0xA9,0x72,0x57,0xF5,0x70,0xA0,0x0B,0x83,0x89,0x72,0x8F,0x6F,0x6F,0x9F,
+    0xE9,0x7A,0xA9,0x72,0x0C,0x23,0x6E,0xD6,0x0A,0x7B,0xC9,0x72,0xE3,0xBD,0xBF,0xAD,
+    0x2B,0x83,0xC9,0x72,0x5F,0x77,0xD7,0x2A,0x2B,0x83,0xA8,0x72,0xAF,0xAB,0xA6,0xF0,
+    0x23,0x41,0xC2,0x38,0x54,0x5E,0x5E,0x5E,0x03,0x41,0xC2,0x38,0xBF,0x81,0xF9,0xA3,
+    0x02,0x41,0xC2,0x38,0x8A,0x2A,0xBA,0xB5,0x03,0x41,0xE2,0x38,0xF3,0xD5,0xF7,0x56,
+    0x03,0x41,0xC2,0x38,0x7C,0xE8,0xAA,0xF7,0x23,0x41,0xE2,0x38,0x73,0xEB,0xF5,0x55,
+    0x03,0x39,0xC2,0x38,0x76,0xDE,0x90,0xDA,0x03,0x41,0xC2,0x38,0x6E,0x6E,0xFA,0xAA,
+    0xE2,0x38,0xC2,0x30,0x0B,0x8D,0x27,0xDE,0x02,0x41,0xA1,0x30,0xB7,0xBA,0xAE,0xA8,
+    0xE2,0x38,0xC1,0x38,0x40,0xFA,0x4B,0x7C,0xE2,0x38,0xC1,0x30,0x6E,0x37,0x22,0x01,
+    0x02,0x41,0xA2,0x30,0xAA,0x86,0x22,0xE2,0x03,0x41,0xC2,0x38,0x7F,0xFA,0xF8,0xDF,
+    0xE2,0x38,0xC2,0x38,0x29,0xB5,0xD8,0x3B,0xE2,0x38,0xC2,0x38,0xAF,0xBA,0x58,0xDF,
+    0x03,0x39,0xC2,0x38,0xFB,0xD7,0x95,0xBA,0x03,0x39,0xC2,0x38,0xFE,0xBB,0x6A,0x58,
+    0xE2,0x38,0xA2,0x30,0xAA,0xB8,0xFA,0xEE,0xC2,0x30,0x82,0x30,0xB0,0xF8,0xBA,0xB2,
+    0x03,0x39,0xA2,0x30,0xF5,0xA5,0x2F,0xAF,0xE2,0x38,0xC2,0x30,0x0B,0x2C,0xF6,0x74,
+    0xE2,0x38,0xA2,0x30,0xDF,0x5E,0x7A,0xFB,0x87,0x72,0xE2,0x38,0x0D,0x2D,0xBD,0xD5,
+    0xA7,0x72,0x64,0x49,0x00,0xA8,0x7F,0x55,0x26,0x62,0x23,0x41,0x78,0x5E,0x7F,0x75,
+    0x24,0x41,0xE3,0x38,0x1F,0xFB,0xE8,0xA0,0x23,0x39,0xE2,0x30,0xF8,0xD7,0xDF,0xEE,
+    0x24,0x39,0xE2,0x30,0xFF,0x89,0x66,0x7E,0x03,0x31,0xC2,0x30,0xA8,0x33,0xBB,0xEA,
+    0x23,0x39,0xE3,0x30,0xD5,0x75,0x75,0xDE,0x03,0x31,0xC3,0x30,0x0B,0xB7,0xF3,0xB0,
+    0x03,0x31,0xC2,0x28,0xAF,0x7E,0xAB,0xC8,0x03,0x31,0xC3,0x30,0xF6,0xEE,0xAE,0xA7,
+    0x23,0x39,0xC2,0x30,0x3D,0xFF,0xD7,0xDB,0x03,0x31,0xC2,0x30,0xFE,0xEE,0xAE,0xEA,
+    0xE3,0x30,0xC2,0x28,0x2D,0x35,0x28,0x08,0x03,0x31,0xC2,0x30,0xE5,0x5E,0xAC,0xEB,
+    0xE2,0x30,0xA2,0x28,0xA9,0xA7,0x2A,0x00,0xE2,0x30,0xC2,0x28,0x2F,0x0B,0xA8,0xA0,
+    0x23,0x31,0xC2,0x30,0x6B,0xFF,0x7D,0x5F,0x03,0x31,0xC2,0x30,0xEF,0x2F,0x2F,0x3A,
+    0x03,0x39,0xE3,0x30,0x55,0x55,0xB7,0x5E,0x24,0x39,0xE3,0x30,0xBF,0xDF,0xEF,0xED,
+    0x03,0x39,0xC2,0x30,0xFE,0xFE,0xF8,0xF8,0x03,0x31,0xC2,0x28,0x97,0xD5,0xE6,0x0F,
+    0x24,0x39,0xC2,0x28,0xF7,0xBF,0xB5,0xAF,0x03,0x31,0xC2,0x30,0xF2,0xC8,0xAA,0xCA,
+    0xE3,0x30,0xC2,0x28,0xA2,0x7F,0xE6,0x20,0x03,0x31,0xC2,0x28,0xB6,0xAF,0xF7,0x7E,
+    0x03,0x31,0xC2,0x30,0xFF,0xB6,0xBF,0xAD,0x04,0x31,0xE2,0x30,0xFD,0xF3,0x1E,0x25,
+    0x03,0x31,0xC2,0x28,0xDF,0x7F,0x70,0x80,0x03,0x31,0xC2,0x30,0xAB,0xEB,0xFD,0xEA,
+    0x03,0x31,0xE3,0x30,0x09,0x7B,0x7A,0x55,0x03,0x39,0xC3,0x30,0xB2,0xBE,0xA8,0xF7,
+    0x03,0x39,0xE3,0x30,0xF5,0xBE,0x1B,0xBE,0x24,0x39,0xE3,0x30,0x7F,0xBF,0xFB,0xB2,
+    0x24,0x39,0xE3,0x30,0xD6,0x7E,0xDA,0x7A,0x24,0x41,0x03,0x31,0xFF,0xEB,0xE3,0x8D,
+    0x03,0x39,0xE3,0x30,0x55,0x77,0xE0,0xF8,0x24,0x41,0xE3,0x38,0xF5,0xBD,0xBD,0xD2,
+    0x24,0x39,0xE3,0x30,0x57,0xAE,0x3A,0xAA,0x24,0x39,0xC3,0x38,0x0B,0xAA,0xBE,0xAA,
+    0xE3,0x38,0x24,0x31,0xEA,0xAA,0xAE,0xA6,0x24,0x41,0xE3,0x30,0xEF,0x8A,0x88,0xAD,
+    0x44,0x39,0xE3,0x38,0x7D,0xFD,0xF9,0xBF,0x24,0x39,0xC3,0x38,0xBA,0xAA,0x82,0x20,
+    0x24,0x39,0x03,0x39,0x3E,0x6E,0xA0,0x5C,0x23,0x39,0xE3,0x30,0x09,0x2A,0xBA,0xDB,
+    0x24,0x39,0x03,0x31,0x5A,0xB2,0x8B,0x7D,0x23,0x39,0xE3,0x30,0x00,0xF0,0x6A,0xAF,
+    0x44,0x39,0x03,0x31,0xFD,0x8F,0xCF,0x67,0x65,0x41,0xE3,0x30,0xCF,0xEF,0x79,0xBF,
+    0x44,0x39,0xE3,0x30,0x2B,0xAF,0xFF,0xF7,0x23,0x39,0xE3,0x30,0x00,0xB8,0xEE,0x7E,
+    0x64,0x41,0xC2,0x30,0x2A,0xAF,0xFF,0x77,0x44,0x41,0x04,0x39,0x2C,0x20,0xAA,0x15,
+    0x65,0x49,0x24,0x41,0x7E,0xEE,0xFB,0x0A,0x64,0x41,0x03,0x39,0x5A,0xFA,0xEA,0x28,
+    0x64,0x41,0x03,0x39,0xFF,0xA5,0xAE,0x3C,0x86,0x49,0x03,0x39,0xF7,0xAD,0x8A,0x88,
+    0x65,0x41,0x04,0x39,0xDF,0xEB,0x38,0x00,0x85,0x49,0x24,0x39,0xD5,0xBF,0xBB,0x02,
+    0x85,0x49,0x24,0x39,0x7D,0xFF,0xB8,0xE0,0xA6,0x51,0x23,0x39,0xF9,0xEB,0x8A,0xAA,
+    0x85,0x49,0x24,0x41,0xF7,0x0A,0x02,0x8E,0xA5,0x51,0x44,0x41,0xD5,0xAE,0xFE,0x0B,
+    0xE6,0x59,0x85,0x49,0x95,0x3D,0x3F,0xDF,0x06,0x5A,0xC6,0x51,0xBF,0x3F,0xE3,0x9B,
+    0x27,0x62,0xC5,0x51,0x20,0x08,0xA9,0x29,0x47,0x62,0x06,0x5A,0xD5,0xF5,0x7D,0xBD,
+    0x48,0x6A,0x07,0x5A,0xFF,0xAF,0xA5,0x27,0x48,0x62,0xE6,0x59,0xF7,0xBA,0x2F,0x87,
+    0x68,0x6A,0x06,0x5A,0xFA,0xEA,0x8B,0x87,0x67,0x6A,0x27,0x62,0x4A,0xB0,0x3E,0xBF,
+    0x68,0x6A,0x06,0x5A,0x2A,0xBE,0x7C,0x7B,0x88,0x6A,0x27,0x62,0x97,0xD9,0xBD,0x0F,
+    0xA8,0x72,0x47,0x62,0xDF,0xBF,0xCA,0x82,0xC9,0x72,0x67,0x6A,0x2B,0x35,0xD5,0x57,
+    0xA8,0x72,0x68,0x6A,0xBB,0xE8,0xA8,0xFF,0xA9,0x72,0x47,0x62,0xDF,0x55,0x6B,0x2A,
+    0xA9,0x72,0x47,0x62,0x9E,0xB5,0x27,0xBE,0xC9,0x72,0x88,0x6A,0x7A,0xEA,0x6A,0xCF,
+    0xA9,0x72,0x47,0x62,0xEA,0x22,0x09,0x02,0xC9,0x72,0x88,0x6A,0x39,0x96,0x5F,0x57,
+    0xC9,0x72,0x88,0x72,0x80,0xEA,0xBE,0xFD,0xC9,0x7A,0x68,0x6A,0xC9,0xAB,0xAA,0xB7,
+    0xC9,0x72,0x67,0x6A,0xC9,0xE0,0xA8,0xDA,0xA8,0x72,0x68,0x6A,0x70,0x9F,0xDF,0xEA,
+    0xC9,0x7A,0x68,0x6A,0xFA,0xBF,0xB3,0xA5,0xA9,0x72,0x68,0x6A,0x2E,0xAA,0x98,0xDB,
+    0xCA,0x7A,0x68,0x6A,0x28,0xBF,0xFE,0xEF,0xC9,0x72,0x68,0x6A,0xE0,0xAE,0x89,0xB9,
+    0xC9,0x7A,0x68,0x6A,0xB7,0x05,0x8E,0xEA,0xE9,0x7A,0x88,0x6A,0xBB,0xBA,0xA2,0xD5,
+    0xEA,0x7A,0x88,0x6A,0x7A,0xE8,0x5A,0x79,0xCA,0x7A,0x67,0x6A,0x8A,0xC1,0x2B,0x0A,
+    0xC9,0x72,0x89,0x72,0x99,0xB7,0x26,0xB2,0xC9,0x72,0x68,0x6A,0x28,0xAB,0xF7,0xFC,
+    0xC9,0x72,0x26,0x62,0x00,0x00,0x02,0xA6,0xE9,0x7A,0x87,0x6A,0xBA,0xEE,0xA3,0xA7,
+    0xEA,0x7A,0x88,0x6A,0x02,0xAB,0xFB,0xFA,0xCA,0x7A,0x68,0x6A,0x39,0xFA,0x2A,0x0F,
+    0xCA,0x7A,0x68,0x6A,0x0A,0x8D,0x2A,0xAB,0x0A,0x83,0xA9,0x72,0x2B,0xAF,0xF5,0x56,
+    0x0A,0x7B,0xC9,0x72,0xEA,0xF8,0xFB,0x95,0x0A,0x7B,0xA8,0x72,0xA0,0x7E,0xDA,0x7F,
+    0x03,0x41,0xC2,0x38,0xFF,0x9B,0x73,0xDB,0x03,0x41,0xC2,0x38,0x6A,0x50,0xF2,0xE2,
+    0x03,0x41,0xA2,0x38,0xEF,0xF2,0x7A,0x6B,0x02,0x39,0xA1,0x30,0xAB,0xA3,0xF9,0xFB,
+    0x02,0x41,0xA2,0x30,0xBE,0xAA,0x26,0x8F,0x03,0x39,0xC2,0x38,0xFF,0xE8,0xBC,0xF6,
+    0xE2,0x38,0xA1,0x30,0xA0,0xFA,0xD7,0xD7,0xE3,0x38,0xA1,0x30,0x02,0x83,0xBE,0x16,
+    0xE2,0x38,0xA2,0x30,0xAA,0xA3,0x8A,0x00,0x02,0x39,0xC2,0x38,0xAE,0xD6,0xAF,0x99,
+    0xE2,0x38,0xA1,0x30,0xA0,0xF0,0xDE,0xAA,0x03,0x41,0xC2,0x38,0xDF,0xAF,0x2F,0x79,
+    0x03,0x39,0xC2,0x38,0x9A,0xEC,0xFE,0xEF,0x02,0x39,0xA1,0x38,0xEA,0xA8,0x6A,0xBA,
+    0xE2,0x38,0xA2,0x30,0xFA,0xAB,0xA3,0xA0,0xE2,0x38,0xC2,0x38,0x05,0xA3,0xC2,0x60,
+    0xE2,0x38,0xC2,0x30,0x02,0x8F,0xBF,0xEF,0xE2,0x38,0x81,0x30,0xB0,0xDB,0xD3,0x7A,
+    0xE3,0x38,0xA2,0x30,0x4A,0x7A,0xDD,0xFD,0x03,0x39,0xA2,0x30,0x5D,0x9D,0x35,0xDD,
+    0x03,0x39,0xC2,0x30,0x9A,0xEA,0xEA,0xDF,0x03,0x39,0xA2,0x28,0xBC,0x18,0xEE,0xEB,
+    0x03,0x39,0x81,0x30,0xBE,0xEC,0xBF,0x7D,0xE3,0x38,0xA1,0x30,0x0B,0xAB,0xFF,0x75,
+    0x23,0x41,0xA2,0x30,0x0B,0xEF,0x7D,0xDF,0x24,0x41,0x81,0x30,0x82,0xAE,0xFF,0xD7,
+    0x24,0x41,0xA1,0x30,0xA0,0xBA,0xFF,0xD5,0x23,0x39,0xE3,0x30,0xAE,0xAA,0x7B,0x69,
+    0x03,0x39,0xC2,0x30,0xFA,0xF2,0xFF,0xFF,0x03,0x31,0xC2,0x30,0x29,0x35,0xBF,0xFF,
+    0x03,0x31,0xC2,0x28,0x80,0xBE,0xFB,0xFD,0x24,0x39,0xC3,0x28,0xDA,0x7B,0xCF,0xFA,
+    0x24,0x39,0xC2,0x30,0x73,0x6D,0xDD,0x97,0xE3,0x30,0xC3,0x28,0x0B,0xE3,0xA2,0xE8,
+    0x03,0x31,0xC3,0x30,0xBA,0x3E,0xAA,0xAB,0x03,0x31,0xC2,0x28,0xA8,0xE0,0x6A,0xFA,
+    0xE3,0x30,0xC2,0x28,0x18,0x1F,0x8F,0xBF,0x03,0x31,0xC2,0x30,0xE7,0xFE,0xBF,0xFD,
+    0x03,0x31,0xC2,0x28,0xEB,0xE7,0xDE,0x73,0x03,0x31,0xC2,0x28,0xEA,0xAB,0xEC,0xDD,
+    0xE3,0x30,0xC2,0x28,0xB2,0xD7,0x80,0x3A,0x24,0x39,0xC2,0x30,0x2B,0xEB,0xB9,0x5B,
+    0x23,0x39,0xC3,0x30,0xFE,0xF9,0xEA,0xE2,0x24,0x39,0xC2,0x30,0x82,0x7B,0xFD,0xD7,
+    0x03,0x39,0xE3,0x30,0xE7,0x75,0x55,0x54,0x04,0x39,0xE3,0x30,0x09,0x55,0x55,0x55,
+    0xE3,0x30,0xC2,0x30,0x08,0xA0,0xB0,0x00,0x03,0x31,0xC2,0x28,0x8F,0x8A,0x2A,0xA7,
+    0x03,0x31,0xC2,0x30,0x80,0xAA,0xB5,0x36,0x03,0x31,0xC3,0x30,0xFE,0xF0,0xFE,0xEE,
+    0x03,0x39,0xA2,0x30,0xAB,0xFA,0xED,0xBE,0x24,0x39,0xC2,0x30,0x0F,0x0F,0xBB,0xF7,
+    0x24,0x39,0xC2,0x30,0xA7,0x3E,0xBF,0xEF,0x03,0x39,0xC3,0x30,0x76,0xEE,0xCA,0x80,
+    0x03,0x31,0xA2,0x30,0xAA,0x22,0xAA,0xB2,0x03,0x31,0xC2,0x30,0xDE,0xBA,0x2B,0x3A,
+    0x03,0x31,0xC2,0x30,0xAA,0xB8,0x70,0x70,0x03,0x31,0xC2,0x28,0x00,0x20,0xBF,0x2D,
+    0x03,0x39,0xE3,0x30,0xE8,0xA6,0x5E,0x5F,0x24,0x39,0xE3,0x30,0x2F,0x2F,0x77,0x75,
+    0x03,0x39,0xE3,0x30,0x8B,0x20,0x20,0x3A,0x24,0x39,0x03,0x39,0x7F,0x6F,0x25,0xF5,
+    0x24,0x41,0x03,0x39,0x63,0x5B,0x5E,0x56,0x44,0x39,0xE3,0x38,0xFD,0xFF,0x7F,0xA5,
+    0x24,0x39,0xE3,0x38,0x7F,0x7F,0xFA,0xA3,0x24,0x39,0xE3,0x38,0xA5,0x37,0xBE,0xFF,
+    0x03,0x39,0xC3,0x30,0x00,0x00,0xE2,0xE2,0x24,0x39,0xC3,0x38,0xA0,0x2A,0xB2,0xA2,
+    0x44,0x41,0xE3,0x38,0xDE,0xAE,0x3E,0x37,0x44,0x41,0xE3,0x30,0xDF,0xBB,0xEE,0x2E,
+    0x44,0x41,0xE3,0x30,0xEA,0x53,0x6E,0xE8,0x44,0x41,0xE3,0x30,0xBA,0x0A,0xAD,0xEF,
+    0x24,0x39,0x03,0x39,0x80,0x98,0x95,0x15,0x44,0x39,0x03,0x39,0xFF,0x97,0xAF,0xA8,
+    0x65,0x41,0xE3,0x30,0xD7,0x7E,0x2A,0x2E,0x24,0x41,0x03,0x39,0x5D,0x79,0x6F,0x48,
+    0x44,0x41,0xC3,0x30,0x7F,0x7B,0xAB,0x02,0x45,0x41,0x03,0x39,0x15,0xD5,0x7D,0xAF,
+    0x65,0x41,0xE2,0x30,0x28,0x2F,0xBD,0xF7,0x85,0x49,0x23,0x39,0x0A,0x80,0xAA,0x6D,
+    0x85,0x49,0x44,0x41,0xBE,0x32,0x82,0x09,0xA5,0x49,0x44,0x41,0xFE,0xFA,0xAA,0x3E,
+    0xA6,0x49,0x45,0x41,0xB6,0xB6,0x9E,0xFE,0xC6,0x51,0x65,0x49,0xEA,0x8A,0xE7,0x97,
+    0xA5,0x51,0x65,0x49,0xAB,0x22,0xAA,0x3F,0xC6,0x51,0x85,0x49,0x7D,0xE6,0x1E,0xAB,
+    0xC6,0x51,0x65,0x49,0x77,0x9F,0xB6,0x0E,0x06,0x5A,0x44,0x41,0xAD,0xAB,0xAA,0x2A,
+    0x27,0x62,0x85,0x49,0xAD,0x3F,0x2F,0x2E,0x47,0x62,0xC6,0x59,0xF6,0x8A,0xAA,0xAE,
+    0x27,0x62,0xE6,0x59,0x25,0x3B,0xF2,0xC8,0x47,0x62,0x06,0x5A,0xE2,0xBF,0xA9,0x57,
+    0x47,0x62,0x07,0x62,0xBF,0xF2,0x22,0x8E,0x88,0x6A,0x06,0x5A,0xAD,0xFF,0xFF,0x3B,
+    0x67,0x6A,0x06,0x62,0xAE,0xFD,0xFB,0x60,0x67,0x6A,0xE6,0x59,0x3A,0xAF,0xCD,0x27,
+    0x67,0x6A,0x26,0x62,0x7A,0xB2,0xFB,0xB8,0x88,0x6A,0x27,0x62,0xBF,0xA2,0x9A,0xD5,
+    0xA8,0x72,0x68,0x6A,0x3B,0xBF,0xFF,0xF5,0x88,0x6A,0x27,0x62,0x80,0x2E,0xA7,0xBE,
+    0x88,0x6A,0x27,0x62,0xD2,0x7A,0xBA,0xBA,0xA8,0x72,0x07,0x62,0x2B,0xF7,0xD7,0xFE,
+    0xA8,0x72,0x47,0x62,0xEA,0xC8,0xAB,0x2D,0xC9,0x72,0x68,0x6A,0x2A,0x23,0xFF,0x55,
+    0xC9,0x72,0x68,0x6A,0x2A,0xAA,0x2B,0x25,0x0A,0x83,0x88,0x6A,0xFF,0x7F,0x7A,0xA2,
+    0xC9,0x72,0x68,0x6A,0x78,0xEA,0xEA,0xA0,0xEA,0x7A,0x68,0x6A,0xF5,0x9E,0x2F,0xFF,
+    0xC9,0x72,0x88,0x6A,0xD6,0x9F,0xF8,0x9B,0xA9,0x72,0x68,0x6A,0xE2,0x66,0xFE,0xFA,
+    0xA9,0x6A,0x48,0x6A,0xBF,0xDF,0xFF,0x3B,0x89,0x6A,0x48,0x6A,0x68,0x4A,0xBE,0x28,
+    0xC9,0x72,0x48,0x62,0x8A,0xAF,0xE7,0xFF,0xC9,0x72,0x68,0x6A,0xA8,0xE8,0x7F,0x5F,
+    0xCA,0x7A,0x68,0x6A,0xCA,0x8A,0x3B,0x29,0xE9,0x7A,0x88,0x6A,0xEF,0xF9,0x2A,0x83,
+    0xC9,0x7A,0x67,0x6A,0x81,0xC3,0xCA,0xA6,0xEA,0x7A,0xA9,0x72,0xA1,0x85,0xAD,0x56,
+    0xEA,0x7A,0x88,0x6A,0x7E,0x7A,0x68,0xE0,0xA9,0x72,0x47,0x62,0x02,0xE9,0xBF,0xAE,
+    0xA8,0x72,0x47,0x62,0x8E,0x80,0x80,0xE8,0xE9,0x7A,0x88,0x6A,0x1D,0xFD,0x7D,0x1B,
+    0xE9,0x7A,0x89,0x6A,0xFB,0x7E,0xEA,0xE2,0xEA,0x7A,0x88,0x6A,0xAB,0x8B,0xEF,0x37,
+    0x0A,0x7B,0x89,0x6A,0x7B,0x7E,0xB0,0x22,0xC9,0x72,0x68,0x6A,0x0E,0x0A,0x2C,0x26,
+    0x0A,0x7B,0xA9,0x72,0x8B,0xA2,0xD5,0xDD,0x09,0x7B,0xA9,0x72,0xAE,0x8F,0xAD,0xBF,
+};
+
+static const size_t pixel_1_width = 256;
+static const size_t pixel_1_height = 256;
+static const size_t pixel_1_size = 32768;
+static const unsigned char pixel_1_data[32768] =
+{
+    0xA8,0x6A,0x84,0x49,0x5B,0x55,0xAD,0x0D,0x46,0x62,0x23,0x39,0xD6,0xDF,0xFE,0xF8,
+    0x06,0x5A,0x02,0x39,0xA2,0x57,0x7E,0xAE,0x67,0x62,0xE2,0x30,0xDF,0xFF,0x0B,0xFF,
+    0xC5,0x49,0xE2,0x30,0xA2,0x5A,0xE8,0xBE,0x88,0x62,0x02,0x31,0x5F,0xAF,0x2F,0xD5,
+    0xC5,0x49,0x03,0x39,0x5F,0x78,0x68,0xEF,0x67,0x5A,0xE2,0x30,0xFF,0x8B,0xBD,0x57,
+    0xA5,0x49,0xE2,0x30,0xDE,0x70,0xBA,0x0A,0x47,0x62,0x23,0x39,0xEF,0x0F,0x55,0x57,
+    0xE5,0x51,0xC2,0x30,0xDE,0x7A,0xFF,0x8A,0x26,0x5A,0x03,0x39,0x8B,0xAD,0x55,0x5F,
+    0x06,0x5A,0x23,0x39,0x97,0xFF,0xF5,0x8F,0x47,0x62,0x64,0x49,0x82,0x7B,0x55,0xDF,
+    0x47,0x62,0x43,0x41,0x5E,0x5F,0xEB,0x8F,0x27,0x5A,0x03,0x39,0x82,0x55,0xD7,0x7E,
+    0x07,0x5A,0x23,0x41,0xDF,0x7D,0xCA,0xEF,0xC5,0x51,0x03,0x39,0xA2,0xF5,0x9E,0x5F,
+    0x89,0x6A,0x44,0x41,0x55,0x5D,0xE3,0x5D,0xC5,0x51,0x02,0x31,0xEF,0xB5,0x1C,0x7B,
+    0x27,0x5A,0x03,0x39,0x5F,0xFA,0xE2,0x57,0xC5,0x51,0x24,0x39,0xF5,0x25,0x97,0xFD,
+    0xE5,0x51,0x03,0x39,0x7E,0xA8,0xEA,0xDF,0x26,0x5A,0x23,0x39,0xAD,0x0D,0xD7,0x8A,
+    0xE5,0x51,0x03,0x39,0x7E,0xE8,0xFE,0xDF,0x67,0x62,0x44,0x41,0x2D,0xAD,0xD5,0x03,
+    0x27,0x62,0x64,0x49,0xF0,0xF0,0x55,0xE8,0xE6,0x59,0x64,0x41,0xAB,0x7F,0x95,0x02,
+    0x46,0x5A,0x84,0x49,0xF7,0x05,0x2D,0xFF,0x68,0x6A,0xE5,0x51,0xB5,0xAE,0xA8,0x2B,
+    0x87,0x6A,0x06,0x5A,0xA7,0x2B,0xCB,0x8A,0x87,0x6A,0x23,0x41,0x20,0xA2,0xBF,0xF7,
+    0x47,0x62,0xA5,0x51,0x00,0x02,0x8C,0xD7,0x87,0x6A,0x26,0x5A,0x6E,0x2E,0x88,0xFF,
+    0xA7,0x6A,0x43,0x41,0x55,0x5E,0x7A,0x6A,0x27,0x5A,0x03,0x39,0xFF,0x83,0x8B,0xF5,
+    0xA5,0x49,0x23,0x39,0xBD,0xB4,0x5E,0xF0,0x47,0x5A,0x02,0x31,0x7E,0xE0,0xFB,0xFF,
+    0x26,0x52,0x03,0x39,0x2D,0x2D,0xD7,0x7F,0x26,0x52,0x23,0x39,0xDE,0x78,0x77,0xBD,
+    0x26,0x5A,0x23,0x39,0x02,0xAB,0xF5,0xD7,0x54,0xE6,0xA5,0x51,0x0D,0xB5,0x55,0x55,
+    0x96,0xEE,0x26,0x5A,0x00,0x00,0x03,0x2D,0xB6,0xF6,0x96,0xEE,0xBF,0xAF,0x8B,0xAD,
+    0xD6,0xF6,0x96,0xEE,0xDF,0xFD,0xBD,0x2F,0xD7,0xF6,0x96,0xEE,0x0B,0x82,0x70,0x5E,
+    0xD7,0xF6,0x96,0xEE,0x2E,0xAE,0x3D,0xB7,0xD7,0xF6,0x75,0xE6,0x78,0xBC,0xAA,0xFA,
+    0xF7,0xF6,0xB6,0xEE,0xD5,0xED,0x8A,0xE5,0xF8,0xFE,0xB6,0xEE,0xF6,0xBF,0x02,0xDF,
+    0xF7,0xF6,0xD7,0xF6,0x29,0x02,0x02,0x09,0x18,0xFF,0xF7,0xF6,0xBA,0x3E,0xF7,0x55,
+    0x18,0xFF,0xF8,0xF6,0xEA,0xA0,0xAB,0x55,0x18,0xFF,0xF8,0xF6,0x55,0xD7,0xFE,0xB9,
+    0x18,0xF7,0xD7,0xF6,0xAA,0xFA,0xDA,0xA0,0x18,0xF7,0xD7,0xF6,0x5F,0x7F,0xFF,0x6A,
+    0xD7,0xF6,0x97,0xEE,0x20,0x0E,0xF8,0xC0,0xF7,0xF6,0x96,0xEE,0x22,0xAB,0xFA,0xAD,
+    0xF7,0xF6,0x96,0xEE,0x5E,0x72,0xEB,0xBF,0x96,0xEE,0x51,0xC5,0x70,0x68,0xE0,0xE8,
+    0x34,0xE6,0x10,0xC5,0x80,0x03,0x89,0x0D,0x14,0xDE,0xF3,0xDD,0x76,0x7C,0x5F,0x76,
+    0x14,0xDE,0xF3,0xDD,0x7E,0xBF,0x8D,0x8B,0x14,0xDE,0xD3,0xDD,0xA9,0xAF,0xEB,0xFE,
+    0x47,0x5A,0x23,0x41,0xF5,0x3D,0xA7,0xDE,0x88,0x6A,0x43,0x41,0x5D,0x80,0xA2,0x5D,
+    0x86,0x62,0x22,0x39,0xFD,0xF8,0xFE,0xD7,0xC5,0x49,0xC2,0x30,0x5E,0xFA,0xAA,0x2E,
+    0x27,0x5A,0x02,0x31,0xAF,0x0B,0xFD,0xFE,0xA5,0x49,0xE2,0x30,0xF8,0xE0,0xBD,0xAD,
+    0x67,0x62,0x23,0x39,0x2F,0xB5,0x55,0xF2,0xA5,0x49,0x02,0x31,0x68,0x7E,0xB5,0x37,
+    0x68,0x62,0xE2,0x30,0x0B,0xF5,0xFF,0xA0,0xC5,0x49,0xE2,0x30,0x70,0x7E,0xB5,0xBE,
+    0x06,0x52,0xC2,0x30,0x0B,0xFD,0xB0,0xA2,0x85,0x49,0xE2,0x30,0xE0,0xAD,0x2E,0x98,
+    0x07,0x62,0x03,0x41,0xAD,0xFD,0xE0,0xEB,0xC5,0x61,0x64,0x49,0x67,0xAD,0xAB,0x0F,
+    0xE6,0x61,0x44,0x41,0xDF,0xF8,0xF0,0x6A,0xA5,0x49,0xE2,0x30,0xFD,0x27,0x36,0xFA,
+    0x48,0x62,0x24,0x39,0x75,0xF0,0xFA,0xFF,0x27,0x5A,0xE2,0x30,0xBD,0x27,0xFF,0xFE,
+    0xC8,0x6A,0x03,0x39,0x5F,0xF0,0x7F,0xFF,0x27,0x52,0xE2,0x30,0x2D,0xAF,0xFF,0xAA,
+    0x06,0x52,0x24,0x41,0x7C,0xF8,0xFF,0xAA,0x68,0x62,0x23,0x39,0x2D,0xF5,0x57,0x5F,
+    0x06,0x52,0x23,0x39,0x7A,0xFB,0x0A,0x0B,0x27,0x5A,0x02,0x31,0x0B,0xFD,0xDE,0xFE,
+    0x06,0x52,0x42,0x39,0x7E,0xFF,0x02,0xBF,0x67,0x62,0x84,0x41,0xAD,0x55,0xE0,0x55,
+    0xE6,0x51,0x03,0x31,0x80,0x5E,0x68,0xFE,0x46,0x62,0x43,0x39,0xFF,0x0F,0xAD,0x55,
+    0x05,0x52,0x43,0x39,0xFE,0xA8,0xFC,0x55,0x27,0x62,0x23,0x31,0x03,0x0A,0xBF,0xD5,
+    0x27,0x62,0xE2,0x38,0x00,0x2B,0xBF,0x5E,0x26,0x5A,0x02,0x39,0xDC,0x68,0xFA,0xD5,
+    0x26,0x5A,0x23,0x41,0xFF,0x0B,0xF5,0x56,0x06,0x5A,0x44,0x41,0xB0,0x58,0xD5,0x25,
+    0xC5,0x51,0x02,0x39,0x02,0x02,0xED,0xF0,0xC5,0x51,0x23,0x39,0xDE,0x5C,0x55,0xEB,
+    0x68,0x62,0x02,0x39,0xA2,0xFF,0x55,0xAF,0xC6,0x51,0x23,0x39,0xA2,0x57,0x55,0x00,
+    0x26,0x5A,0x03,0x39,0xFF,0x55,0xF7,0x82,0x26,0x5A,0x03,0x39,0xBD,0x55,0xFF,0x02,
+    0x26,0x62,0x02,0x39,0x7E,0x55,0xAF,0x00,0x27,0x62,0x02,0x39,0xDD,0xDD,0xAE,0x00,
+    0xF0,0xBC,0x44,0x49,0x35,0xF5,0xBF,0x2F,0xD7,0xF6,0xD2,0xD5,0x22,0x89,0x29,0x0B,
+    0xD7,0xF6,0x96,0xEE,0x8B,0x43,0x68,0x78,0xB6,0xEE,0x76,0xEE,0xB6,0x9F,0x95,0x56,
+    0xB6,0xF6,0x34,0xE6,0x02,0x22,0xAA,0xF5,0x96,0xEE,0xF3,0xDD,0xF0,0x9C,0xD6,0x97,
+    0xF7,0xF6,0xD3,0xD5,0x2A,0xAA,0xBF,0x5F,0xF7,0xF6,0xD3,0xD5,0x88,0x0A,0x2A,0xB5,
+    0x18,0xFF,0x75,0xE6,0xF7,0x5E,0xE8,0xBB,0xF7,0xF6,0x55,0xE6,0x02,0xB5,0x5F,0xFA,
+    0xF7,0xF6,0x55,0xE6,0x20,0x00,0x2D,0x97,0x18,0xF7,0xD7,0xF6,0xF7,0xFF,0x8A,0xE9,
+    0x18,0xFF,0xD7,0xEE,0xAA,0xFD,0xEA,0xEB,0x18,0xF7,0xD7,0xF6,0xE2,0xAA,0x57,0x5C,
+    0xF7,0xF6,0xB7,0xEE,0xF8,0xA8,0xFF,0xFE,0xD7,0xF6,0x75,0xEE,0x2E,0xF0,0x40,0x82,
+    0xD7,0xF6,0x55,0xE6,0xA0,0xE2,0xE2,0xC1,0x96,0xEE,0xD3,0xD5,0x60,0xE0,0xC0,0xC2,
+    0x14,0xDE,0x51,0xCD,0x25,0x35,0xBF,0xFF,0x14,0xDE,0xF3,0xDD,0xD4,0xBE,0xBC,0xBA,
+    0x34,0xE6,0xF3,0xDD,0xEB,0xEA,0xE2,0xFA,0x14,0xDE,0xF3,0xDD,0xB7,0xED,0xDB,0xF5,
+    0x05,0x5A,0x43,0x41,0xD8,0x50,0x72,0xC0,0x47,0x62,0x63,0x41,0x03,0xAB,0x55,0x25,
+    0x67,0x62,0x84,0x41,0x57,0x77,0x55,0x78,0xA5,0x49,0x63,0x41,0x00,0x6A,0xEB,0xFE,
+    0xA5,0x49,0x02,0x39,0xA0,0x7B,0xA0,0xAA,0xA5,0x49,0x02,0x31,0x3E,0xB3,0x8F,0x9A,
+    0xCA,0x8B,0xA4,0x49,0x55,0x7D,0xC9,0x55,0x85,0x41,0xE2,0x28,0x9E,0xBE,0xF8,0x58,
+    0x47,0x5A,0x02,0x31,0xFF,0x0F,0xAF,0x75,0xA5,0x49,0x02,0x31,0x5E,0xC8,0xCA,0xFF,
+    0x84,0x49,0xE2,0x30,0xAA,0x02,0xA9,0x77,0x84,0x49,0xE2,0x30,0xAB,0x22,0xA8,0x55,
+    0xA4,0x51,0x02,0x39,0xAF,0xAE,0xBA,0x95,0x26,0x72,0x84,0x51,0xED,0xBD,0xAB,0x8B,
+    0x06,0x6A,0x84,0x51,0x7E,0x7A,0x78,0x40,0x85,0x51,0xE3,0x38,0x80,0xAA,0x7E,0x5C,
+    0x85,0x49,0xC2,0x30,0x00,0x2A,0x5D,0xFD,0x85,0x49,0xC3,0x30,0x00,0xAA,0x57,0xAF,
+    0x85,0x49,0xE2,0x30,0x88,0xEE,0x55,0xAA,0xC5,0x51,0xE3,0x30,0xAA,0x7F,0x55,0x2A,
+    0xC5,0x49,0x03,0x39,0xAA,0x55,0x55,0x28,0x06,0x52,0x03,0x39,0x5B,0xD5,0xB5,0x00,
+    0x06,0x5A,0xE2,0x30,0xFF,0x55,0xAE,0x00,0x06,0x5A,0xE2,0x30,0xFF,0xB5,0x2B,0x00,
+    0x27,0x5A,0x02,0x39,0x75,0x57,0xAA,0x00,0x06,0x5A,0x23,0x39,0x55,0x55,0x2A,0x00,
+    0x05,0x5A,0xE2,0x30,0xD7,0xBF,0x00,0x20,0x07,0x5A,0xC2,0x30,0xD6,0xA8,0x80,0x22,
+    0x07,0x62,0xE2,0x30,0x55,0xAA,0x00,0xAA,0x06,0x5A,0x03,0x31,0xD5,0x0A,0x20,0x00,
+    0xC8,0x72,0x64,0x49,0x5B,0xFF,0xFA,0x0A,0xAC,0x93,0x84,0x49,0x55,0xFD,0x55,0x02,
+    0xD0,0xB4,0xE6,0x59,0x55,0x55,0x55,0x0A,0x32,0xC5,0x06,0x5A,0x55,0x55,0x55,0x00,
+    0xB4,0xD5,0x06,0x5A,0x55,0x55,0xF5,0x00,0x36,0xE6,0x06,0x5A,0x55,0x55,0xFF,0x00,
+    0x55,0xE6,0x06,0x5A,0x55,0x55,0xAB,0x00,0x97,0xEE,0x27,0x62,0x55,0x55,0xAA,0x00,
+    0x35,0xDE,0x26,0x62,0x55,0xD5,0x00,0x00,0x75,0xE6,0xE5,0x59,0x55,0xFF,0x00,0x00,
+    0x75,0xE6,0x06,0x5A,0x55,0xAF,0x00,0x00,0x96,0xEE,0x27,0x62,0x55,0xAA,0x00,0x00,
+    0xB6,0xEE,0xE8,0x7A,0xBD,0x0A,0x00,0x00,0xD7,0xF6,0x75,0xEE,0x0D,0x89,0xA2,0xA0,
+    0xB6,0xF6,0x76,0xEE,0xE0,0x68,0x78,0xEA,0x96,0xEE,0xF4,0xDD,0xE8,0xE0,0x7A,0x7A,
+    0xB6,0xF6,0xD3,0xD5,0xBF,0xBD,0xB5,0x2F,0xD7,0xF6,0x14,0xDE,0xF5,0xAB,0x82,0x00,
+    0xB7,0xF6,0x55,0xE6,0x5D,0xBF,0xFE,0xE0,0xB6,0xEE,0x51,0xCD,0x5F,0x80,0x08,0x22,
+    0x96,0xEE,0x92,0xCD,0x0B,0xB5,0xF8,0x80,0xF7,0xF6,0x34,0xDE,0xAA,0xAB,0xB5,0xF5,
+    0xD7,0xF6,0x14,0xDE,0x6A,0xC0,0x02,0x0A,0xD7,0xF6,0x92,0xCD,0x02,0x2D,0xBE,0x80,
+    0x18,0xFF,0x96,0xE6,0xAA,0x20,0x29,0x95,0x18,0xF7,0xD7,0xF6,0xEA,0xBA,0xAA,0xEA,
+    0xF7,0xF6,0xB7,0xEE,0xEE,0xEC,0xF0,0xC0,0xD7,0xF6,0x96,0xEE,0xAA,0xBC,0xFA,0x6A,
+    0xB6,0xEE,0x34,0xDE,0x8B,0x27,0xB4,0xBE,0x96,0xEE,0x34,0xE6,0xCB,0xEB,0xFD,0xB7,
+    0xF3,0xDD,0x71,0xCD,0xDF,0xD6,0x5C,0x5C,0x34,0xE6,0xD3,0xDD,0xAF,0xA9,0x39,0xA9,
+    0x34,0xE6,0x14,0xDE,0x78,0x53,0x5F,0x5E,0x34,0xE6,0xF3,0xDD,0xD5,0xB5,0xDF,0xFF,
+    0x2A,0x83,0xC5,0x51,0x57,0x5E,0x5E,0x7C,0x84,0x49,0xE1,0x30,0x2B,0xD6,0x5C,0x00,
+    0x67,0x62,0x22,0x39,0xFF,0x77,0x55,0x2B,0xA8,0x6A,0x23,0x39,0xFF,0x55,0xFF,0x00,
+    0x27,0x62,0x02,0x31,0xFF,0x55,0xAA,0x00,0x27,0x5A,0x02,0x31,0x5F,0x7D,0x8A,0x80,
+    0x06,0x5A,0x02,0x31,0x55,0x55,0xAA,0x00,0xE6,0x51,0xC2,0x28,0x5D,0xFF,0x00,0x20,
+    0x07,0x5A,0xC1,0x30,0x55,0xFF,0x00,0xA2,0x06,0x5A,0xE2,0x30,0xD5,0xFF,0x00,0xAA,
+    0x07,0x5A,0xC1,0x30,0x56,0xA2,0x00,0xAA,0x06,0x5A,0xE2,0x30,0x55,0x22,0x80,0xAE,
+    0xC5,0x59,0x02,0x39,0xB5,0x00,0x00,0x00,0x26,0x72,0xC5,0x61,0x09,0xA9,0xEF,0xED,
+    0x26,0x72,0xE5,0x69,0x4A,0xBF,0xFB,0x8B,0xAB,0xA3,0xC5,0x59,0x55,0x57,0x5D,0x2F,
+    0x11,0xC5,0xC6,0x59,0x55,0x55,0x55,0x02,0x72,0xCD,0xE5,0x51,0x55,0x55,0x75,0x00,
+    0xF3,0xD5,0xC5,0x51,0x55,0x55,0xFF,0x00,0x35,0xE6,0xE6,0x59,0x55,0x55,0xBF,0x00,
+    0x55,0xE6,0xE6,0x59,0x55,0x55,0xAA,0x00,0xB6,0xEE,0x26,0x62,0x55,0x55,0xAA,0x00,
+    0x34,0xDE,0xC6,0x51,0x55,0xFD,0x00,0x00,0x76,0xEE,0xE6,0x59,0x55,0xFF,0x00,0x00,
+    0x76,0xE6,0xC5,0x59,0x55,0xAA,0x00,0x00,0x96,0xEE,0x26,0x62,0x55,0xAA,0x00,0x00,
+    0xB7,0xF6,0xA8,0x7A,0x55,0x2A,0x00,0x00,0x76,0xEE,0xE9,0x7A,0xF5,0x20,0x00,0x00,
+    0x76,0xEE,0x2E,0xA4,0xD5,0x00,0x00,0x00,0xD3,0xDD,0x26,0x6A,0xAA,0xC0,0xE0,0x78,
+    0x4E,0xAC,0x06,0x62,0x3E,0xB7,0x55,0x55,0xB7,0xF6,0x8F,0xB4,0xAA,0x03,0x09,0x09,
+    0xF8,0xFE,0x55,0xE6,0xD5,0xAE,0xAA,0x00,0x18,0xFF,0x76,0xEE,0x75,0xBF,0xA2,0x08,
+    0xF7,0xF6,0x96,0xEE,0x5D,0xAE,0xA8,0xAC,0xD7,0xF6,0x96,0xEE,0xBD,0xAA,0x08,0x00,
+    0xD7,0xF6,0xB7,0xEE,0x5D,0xEF,0xEC,0x8A,0xD7,0xF6,0x96,0xEE,0xEF,0xAA,0x82,0x82,
+    0xD7,0xF6,0xB7,0xEE,0xF7,0xE7,0xEA,0xA8,0xD7,0xF6,0xB6,0xEE,0xEB,0xEB,0xFF,0xAA,
+    0xB6,0xF6,0xD7,0xEE,0x8A,0x22,0xFA,0xEB,0xF7,0xF6,0xB6,0xEE,0x77,0x5F,0xFD,0xBB,
+    0xF7,0xF6,0x96,0xEE,0x2A,0x8B,0x62,0x58,0xD7,0xF6,0x76,0xEE,0xE8,0xBB,0xFD,0x5D,
+    0x96,0xEE,0x14,0xE6,0x00,0xE8,0xF8,0x7E,0xB6,0xF6,0x14,0xDE,0x5F,0xFD,0x2F,0x2D,
+    0xF7,0xF6,0x55,0xE6,0xAD,0x0A,0xAA,0xAA,0xF7,0xF6,0xB7,0xF6,0x8A,0xA2,0xAA,0xAD,
+    0xF7,0xF6,0xB6,0xEE,0x5E,0xFA,0xA8,0xAB,0xD7,0xF6,0x75,0xE6,0xDF,0xFA,0xAA,0x80,
+    0xB6,0xEE,0x76,0xEE,0x37,0xBF,0xAA,0x00,0xD7,0xF6,0x55,0xE6,0xD6,0xA8,0x0A,0x2A,
+    0xF7,0xF6,0x76,0xEE,0xBD,0xBF,0xAE,0xA8,0x38,0xFF,0xD7,0xF6,0xFF,0xED,0xBD,0x2F,
+    0x18,0xFF,0xB7,0xEE,0x7E,0xAE,0xEA,0xA0,0x18,0xF7,0xB7,0xEE,0xA3,0xAD,0xDE,0xFA,
+    0x18,0xF7,0xD7,0xF6,0x6A,0xEA,0xEB,0xFF,0xB7,0xEE,0x75,0xE6,0xA0,0x60,0x60,0x60,
+    0x96,0xEE,0x92,0xD5,0xA8,0xB8,0xFA,0x5A,0x75,0xEE,0x14,0xDE,0xB6,0xF4,0xDE,0x56,
+    0x55,0xE6,0x71,0xCD,0x5E,0x5C,0x5C,0x58,0x34,0xE6,0xB3,0xD5,0x8B,0x89,0x0B,0x01,
+    0x34,0xE6,0xF3,0xDD,0xDA,0x5A,0x5E,0x5F,0x14,0xDE,0xD3,0xDD,0x0B,0xA2,0xEA,0x6F,
+    0x35,0xE6,0xE5,0x59,0x56,0x7A,0xA0,0x00,0xF4,0xD5,0xA4,0x51,0x55,0x55,0xBA,0x00,
+    0xF4,0xD5,0xC5,0x51,0x55,0x55,0xAA,0x00,0x35,0xE6,0x06,0x5A,0x55,0x55,0xAA,0x00,
+    0x35,0xE6,0x26,0x62,0x55,0x55,0x8A,0x00,0x35,0xE6,0xA5,0x51,0x55,0xFF,0x00,0x00,
+    0x35,0xE6,0xC5,0x51,0x55,0xBB,0x00,0x00,0x55,0xE6,0xC5,0x51,0x55,0xAA,0x00,0x00,
+    0x75,0xEE,0x67,0x6A,0x55,0xAA,0x00,0x00,0x55,0xE6,0xE9,0x7A,0x55,0x22,0x00,0x00,
+    0x55,0xE6,0xCC,0x93,0x55,0x02,0x00,0x00,0x76,0xEE,0x2E,0xA4,0xF5,0x20,0x00,0x00,
+    0x55,0xEE,0xAC,0x9B,0x7B,0xC0,0xC0,0xC0,0x67,0x72,0xA4,0x61,0xF7,0xD6,0x54,0x5C,
+    0x26,0x72,0xA4,0x61,0xAB,0x8B,0xA9,0x0F,0x2D,0xAC,0x26,0x72,0x35,0xB5,0x55,0x55,
+    0x55,0xEE,0xE9,0x8A,0x02,0x03,0x0B,0x2D,0xB6,0xF6,0x75,0xEE,0xD5,0xAB,0xAA,0x8B,
+    0xB6,0xF6,0x75,0xEE,0xFD,0xAB,0xA2,0x82,0xB6,0xF6,0x96,0xEE,0x55,0xEA,0xEA,0xEA,
+    0xB6,0xF6,0x96,0xEE,0xA5,0x2B,0xBE,0x8F,0xB6,0xF6,0x96,0xEE,0xF3,0x88,0x32,0x0F,
+    0xB6,0xF6,0x96,0xEE,0x2E,0x82,0x2A,0x08,0xB6,0xF6,0xD7,0xEE,0x22,0xC8,0x88,0xFC,
+    0xF7,0xF6,0xB6,0xF6,0xE7,0xAA,0x0A,0x02,0xF8,0xFE,0xD7,0xEE,0xF5,0xEA,0x8A,0xAA,
+    0xF7,0xF6,0xD7,0xF6,0xD5,0x0A,0x02,0x00,0xF7,0xFE,0xD7,0xF6,0xD7,0xFC,0xEA,0x7E,
+    0xB6,0xF6,0xCB,0xA3,0x80,0xA0,0xE0,0x78,0xCF,0xBC,0x67,0x72,0x58,0x56,0x57,0x55,
+    0x67,0x7A,0xC5,0x61,0xDE,0xFA,0xB8,0x30,0xD7,0xF6,0x2D,0xAC,0x09,0x09,0x09,0x09,
+    0x18,0xFF,0xF7,0xF6,0xDF,0xBF,0xBD,0xFF,0x17,0xFF,0xF7,0xF6,0xEB,0xBB,0x82,0xAB,
+    0xF7,0xF6,0xD7,0xF6,0x6C,0x5A,0xD0,0x30,0xF7,0xF6,0xD7,0xF6,0x55,0xFE,0xFF,0xEF,
+    0xD7,0xF6,0xB6,0xEE,0x0B,0x2B,0x00,0x00,0xB7,0xF6,0xF7,0xEE,0xAA,0xEA,0xAE,0xEF,
+    0xD7,0xF6,0xB7,0xEE,0x88,0x0A,0x02,0x80,0xF7,0xF6,0xB6,0xEE,0xFF,0xBE,0xAE,0xAE,
+    0xB6,0xF6,0xF7,0xEE,0xAA,0xBA,0xBB,0xEE,0xF7,0xF6,0xB6,0xEE,0x0E,0x82,0xC2,0x78,
+    0xD7,0xF6,0x96,0xEE,0x78,0x54,0x76,0x57,0x96,0xEE,0xF4,0xDD,0xA0,0xE8,0x6A,0x78,
+    0x35,0xE6,0x91,0xCD,0xE0,0x70,0x5F,0x16,0x96,0xF6,0xF3,0xDD,0xAD,0xFD,0x03,0x00,
+    0xB6,0xF6,0xB3,0xD5,0x0A,0xF7,0xFE,0xA8,0xD7,0xF6,0xF4,0xDD,0x02,0xAF,0xFD,0xFF,
+    0xD7,0xF6,0x55,0xE6,0x00,0x0A,0x3D,0xD5,0xF7,0xF6,0xB6,0xEE,0xAA,0xAA,0x83,0xB5,
+    0xD7,0xF6,0x96,0xEE,0xFE,0xF8,0x28,0x00,0xD7,0xF6,0x96,0xEE,0x0A,0xAE,0x9E,0xF8,
+    0x18,0xF7,0xD7,0xF6,0xFF,0xFD,0xB5,0xA5,0x38,0xFF,0xF8,0xF6,0xA5,0xB5,0xDD,0xD7,
+    0x38,0xFF,0xF8,0xF6,0xFA,0xE8,0x82,0x0B,0x18,0xFF,0xB7,0xF6,0xEA,0xFA,0xFA,0xDC,
+    0xF7,0xF6,0x76,0xEE,0x82,0xAB,0xAF,0xB7,0xD7,0xF6,0x75,0xE6,0x7A,0x78,0x78,0xDA,
+    0x55,0xE6,0x10,0xC5,0xF8,0xF8,0x58,0x58,0x55,0xEE,0xD3,0xDD,0xFA,0xF3,0xF2,0xE1,
+    0x14,0xE6,0x10,0xC5,0xF0,0x60,0x60,0x40,0xD7,0xF6,0x92,0xD5,0xFD,0xBD,0xA9,0x2D,
+    0x75,0xEE,0xF3,0xDD,0x7F,0x77,0x7E,0x80,0x34,0xE6,0x92,0xCD,0x6A,0x7A,0x6A,0x88,
+    0xD6,0xF6,0x96,0xEE,0x5F,0x5E,0xEA,0xAE,0xB6,0xEE,0x75,0xE6,0x55,0xBB,0x02,0x00,
+    0xB6,0xEE,0x75,0xE6,0xD5,0xAA,0x02,0x00,0xD7,0xF6,0x75,0xE6,0x55,0xEF,0xAA,0xA2,
+    0xB6,0xEE,0x75,0xE6,0xFD,0xAA,0x20,0x00,0xB6,0xEE,0x75,0xEE,0xFF,0x22,0x00,0x00,
+    0xD5,0xEE,0x76,0xEE,0xF7,0xFF,0xFF,0xFE,0x96,0xEE,0x75,0xEE,0x8B,0xC8,0x0A,0x08,
+    0xB7,0xF6,0x75,0xEE,0xFF,0xFF,0xBE,0xAA,0xD6,0xF6,0x96,0xEE,0xF7,0xBF,0xAB,0xAA,
+    0xD7,0xF6,0x96,0xEE,0xFF,0x2F,0x8A,0xA2,0xD7,0xF6,0x96,0xF6,0xDB,0xAA,0xAA,0xA8,
+    0xB6,0xF6,0x6D,0xB4,0x60,0x40,0x60,0xC0,0x66,0x7A,0x84,0x61,0x7E,0xFE,0xFA,0xEC,
+    0x27,0x7A,0x84,0x61,0x2D,0xBF,0xFF,0xDE,0x26,0x72,0xE6,0x71,0x25,0x2E,0xBF,0x6D,
+    0xD3,0xDD,0x67,0x7A,0x25,0xB5,0xD5,0xD5,0x96,0xF6,0x8F,0xBC,0x00,0x02,0x02,0x09,
+    0xB6,0xF6,0x96,0xEE,0x28,0x02,0x8A,0x0A,0xD6,0xF6,0x96,0xEE,0xFE,0xEA,0xAA,0xEA,
+    0xB6,0xF6,0x96,0xEE,0x2A,0x02,0x22,0x00,0xB6,0xF6,0x96,0xEE,0xAA,0x82,0x20,0x08,
+    0xD6,0xF6,0xB6,0xF6,0x5D,0xD5,0x6D,0xA5,0xD7,0xF6,0xB6,0xEE,0x2B,0x2B,0x2E,0x3A,
+    0xD7,0xFE,0xF7,0xF6,0x75,0x57,0xD7,0x55,0x17,0xFF,0xF7,0xF6,0x5D,0xDF,0x7F,0x5B,
+    0xD6,0xFE,0xF7,0xF6,0xD7,0xD7,0x55,0xA7,0xD6,0xF6,0xAF,0xBC,0x00,0x80,0xE0,0x78,
+    0x35,0xEE,0x87,0x7A,0x78,0x5E,0x57,0x57,0xC7,0x8A,0x47,0x7A,0xFF,0xFF,0xAD,0x2F,
+    0xAB,0xA3,0x46,0x72,0xD5,0x97,0x97,0x1F,0xF7,0xFE,0x8F,0xBC,0x09,0x0B,0x03,0x02,
+    0x17,0xFF,0xF8,0xF6,0xEA,0x2E,0x2A,0xAA,0x18,0xFF,0xF7,0xF6,0x0A,0xA8,0xA2,0xCA,
+    0xF7,0xF6,0xD7,0xF6,0xA8,0xA8,0xA8,0x82,0xF7,0xF6,0xD7,0xF6,0xFF,0x9F,0xFA,0x5A,
+    0xD7,0xF6,0xD6,0xEE,0x82,0xA8,0x22,0x8A,0xF7,0xF6,0xD7,0xF6,0xDF,0x7B,0xD5,0x9D,
+    0xF7,0xF6,0xB7,0xEE,0xAF,0xBA,0xEA,0xAA,0xF7,0xF6,0xD7,0xF6,0x5D,0xDD,0xF7,0x2B,
+    0x17,0xFF,0xB7,0xEE,0xAF,0xAB,0xEA,0x78,0xF8,0xF6,0x96,0xEE,0xFC,0x7E,0x5F,0x5F,
+    0x96,0xEE,0x34,0xE6,0x80,0xC8,0x68,0x5C,0x55,0xE6,0xB2,0xD5,0xE8,0xFA,0xFE,0x97,
+    0xB7,0xF6,0xF3,0xDD,0x35,0x2D,0x0B,0x02,0xD7,0xF6,0xB6,0xF6,0xAD,0xA0,0x82,0xA2,
+    0xD7,0xF6,0x96,0xEE,0x7E,0xAE,0xBA,0xA8,0xD7,0xF6,0x55,0xE6,0xD7,0x8A,0x22,0x2A,
+    0xD7,0xF6,0x75,0xE6,0x5F,0xAF,0x28,0xA8,0xF7,0xF6,0x75,0xE6,0xBD,0xFF,0xFE,0x82,
+    0xF7,0xF6,0x96,0xEE,0xA2,0x83,0x89,0x2F,0xF7,0xF6,0xB7,0xEE,0x5E,0xFA,0xB0,0xA0,
+    0xF8,0xF6,0xB7,0xEE,0x0B,0x0B,0x8A,0xA2,0x18,0xF7,0xD7,0xEE,0x20,0x8A,0xAF,0xB7,
+    0x38,0xFF,0xF8,0xF6,0x8F,0xB5,0xDF,0x57,0x38,0xFF,0x96,0xEE,0xF8,0x78,0x72,0x6A,
+    0xD7,0xF6,0x35,0xE6,0x2E,0x3F,0xBE,0xDF,0xB6,0xF6,0x14,0xDE,0xB8,0xFC,0xDC,0x7C,
+    0x34,0xE6,0x10,0xBD,0x58,0x5C,0x5C,0x5C,0x34,0xE6,0x92,0xCD,0x83,0xC1,0xC9,0xC9,
+    0xF4,0xDD,0x51,0xC5,0x40,0x42,0x42,0x8B,0x76,0xEE,0xCF,0xB4,0x0B,0x2D,0xB5,0x25,
+    0x95,0xEE,0x55,0xE6,0xEC,0x5E,0x5F,0xDC,0x96,0xEE,0x55,0xE6,0xD7,0xFB,0xAD,0xA9,
+    0xD6,0xF6,0xB6,0xEE,0xB5,0xFD,0xFD,0xDD,0xD6,0xF6,0xB6,0xEE,0xF5,0xDF,0xF6,0xF9,
+    0xD6,0xF6,0xB6,0xEE,0xAD,0xFF,0xBB,0xBB,0xD6,0xF6,0xB6,0xEE,0xFF,0xDF,0xBF,0xFF,
+    0xD7,0xF6,0xB6,0xEE,0x77,0xFF,0xBA,0xFA,0xB6,0xF6,0xD6,0xEE,0x28,0xBA,0xAF,0xBA,
+    0xB7,0xEE,0x95,0xEE,0x56,0xDF,0x57,0x76,0xB7,0xFE,0x95,0xEE,0xD5,0xD5,0x7F,0xF5,
+    0xB5,0xF6,0x96,0xEE,0xAF,0xEE,0xFB,0xBF,0xD7,0xF6,0xB6,0xEE,0xAB,0x2B,0x8B,0x29,
+    0xD7,0xF6,0xB6,0xEE,0xAE,0x28,0x02,0x80,0xD7,0xF6,0xB6,0xEE,0xBA,0xAA,0xA0,0x00,
+    0xB6,0xF6,0x86,0x7A,0x80,0xE0,0x60,0x70,0x47,0x72,0x63,0x61,0xA8,0xAE,0xBA,0xDC,
+    0x26,0x72,0x84,0x61,0x7A,0x70,0xF8,0xEA,0x07,0x72,0x64,0x61,0x0A,0xAB,0xBF,0xF7,
+    0xA7,0x7A,0xA5,0x61,0x2F,0xBF,0xBD,0xF5,0x75,0xEE,0xA7,0x82,0x0B,0x2D,0x35,0xB5,
+    0xD7,0xF6,0x75,0xF6,0xAA,0x2A,0xAA,0x81,0xD6,0xF6,0xB6,0xF6,0xDB,0xEE,0xB9,0xA3,
+    0xD6,0xF6,0xB6,0xF6,0x5D,0x76,0x78,0xFF,0xB6,0xF6,0xB7,0xEE,0x88,0x22,0x88,0x20,
+    0xD6,0xF6,0xB6,0xF6,0x37,0xBD,0xB7,0x9D,0xF7,0xF6,0xB6,0xEE,0xBB,0xBE,0xAF,0xAF,
+    0xD6,0xFE,0xF7,0xF6,0xD5,0xDF,0x77,0x55,0xD7,0xFE,0xF7,0xF6,0x7D,0x55,0xF5,0xED,
+    0xF7,0xFE,0x51,0xD5,0x00,0xA0,0xE0,0x78,0xF3,0xE5,0x46,0x72,0xE0,0x78,0x5E,0x57,
+    0x67,0x7A,0x26,0x7A,0x89,0xFA,0x7A,0xFE,0xA7,0x8A,0x47,0x82,0x3B,0x0A,0xAF,0x8D,
+    0xB2,0xDD,0x87,0x82,0x95,0x95,0xB5,0x35,0xF7,0xFE,0x55,0xEE,0x01,0x01,0x03,0x02,
+    0x18,0xFF,0xF7,0xF6,0x3A,0x2A,0x2A,0x2A,0x37,0xFF,0xF8,0xF6,0xFE,0xFA,0xEE,0xAE,
+    0xF7,0xF6,0xD7,0xF6,0xA0,0xE0,0xA8,0xBC,0xF7,0xF6,0xD7,0xF6,0x7A,0x6F,0xFE,0xDB,
+    0xD7,0xF6,0xF7,0xEE,0x08,0x88,0x0A,0x22,0xF7,0xF6,0xD7,0xF6,0xD7,0xB5,0xB5,0xD5,
+    0xF7,0xF6,0xD7,0xF6,0xDD,0xFD,0x3D,0x2B,0x18,0xFF,0xD7,0xF6,0x2D,0x8F,0x63,0x58,
+    0xF7,0xF6,0x96,0xEE,0xF8,0xF8,0x7F,0x5F,0xB7,0xF6,0x35,0xE6,0xA8,0xEA,0x7A,0x7A,
+    0x55,0xEE,0x92,0xCD,0xE0,0xE8,0x5A,0xDE,0xD7,0xF6,0x71,0xCD,0xB7,0x2D,0x0B,0x02,
+    0xD7,0xF6,0xB6,0xF6,0x8D,0x0B,0x00,0x00,0xD7,0xF6,0xB7,0xEE,0xA8,0xAA,0x00,0x80,
+    0xD7,0xF6,0xB7,0xEE,0xE8,0x8A,0xF8,0xFC,0xD7,0xF6,0xB6,0xEE,0x55,0x7F,0x8F,0x23,
+    0xD7,0xF6,0xB6,0xEE,0x5D,0x55,0x77,0x6E,0xF7,0xF6,0x96,0xEE,0x2B,0x2F,0xBD,0xFF,
+    0x18,0xFF,0xD7,0xF6,0xFF,0xAA,0x2B,0x2D,0x39,0xFF,0xF7,0xF6,0x5F,0x7F,0xEA,0xAA,
+    0xF7,0xF6,0xD7,0xEE,0x2C,0x2E,0x02,0x00,0xF8,0xF6,0xD7,0xF6,0xA4,0xEC,0xDA,0xB8,
+    0xF7,0xF6,0xB7,0xEE,0xA0,0xA2,0xC2,0xE0,0xD7,0xF6,0xB7,0xEE,0x40,0x6A,0xA2,0x22,
+    0xB7,0xEE,0x14,0xDE,0x9E,0xDE,0xD8,0x58,0xD7,0xF6,0x34,0xE6,0x58,0x7A,0x72,0x62,
+    0x14,0xDE,0x10,0xC5,0x5C,0xF8,0xF8,0xF8,0x34,0xE6,0x71,0xCD,0x89,0xA9,0xAD,0xAD,
+    0xD3,0xDD,0x51,0xC5,0x8B,0x0B,0x0F,0xA5,0xB6,0xF6,0x10,0xC5,0x25,0x2D,0x2F,0x2F,
+    0xB6,0xF6,0x34,0xE6,0xDA,0x58,0xF8,0x70,0x96,0xEE,0x35,0xE6,0x3F,0xB5,0xBD,0xBD,
+    0xD6,0xF6,0xB6,0xEE,0x5B,0xF7,0xFD,0xBD,0xD6,0xF6,0xB6,0xEE,0x6F,0xBE,0xBA,0xB6,
+    0xD6,0xF6,0xB6,0xEE,0xBF,0xE3,0xAD,0xA7,0xD6,0xF6,0xB6,0xEE,0xAF,0x6E,0xFF,0xEC,
+    0xD6,0xF6,0xB6,0xEE,0xAD,0xBF,0xE3,0xEF,0xD6,0xF6,0xB6,0xEE,0x3F,0xEE,0xEE,0xFD,
+    0xB6,0xF6,0x95,0xEE,0xFA,0xF6,0xFC,0xBE,0xB6,0xF6,0x96,0xEE,0xA5,0xED,0x7E,0xFE,
+    0x96,0xF6,0xB6,0xEE,0x9F,0x6E,0x7F,0x7A,0xF6,0xF6,0xB6,0xEE,0xFD,0xBF,0xFF,0xAB,
+    0xD7,0xF6,0xB6,0xEE,0xE0,0xE0,0x0A,0x08,0xB6,0xF6,0xF7,0xEE,0xAF,0xAF,0xAB,0xAB,
+    0x55,0xEE,0xC4,0x61,0x70,0x70,0x70,0x70,0xE6,0x69,0x23,0x51,0x58,0x5E,0x5E,0x7F,
+    0xE6,0x71,0x03,0x51,0x02,0x03,0x09,0xAD,0xA5,0x61,0x44,0x59,0xFA,0xBE,0x5C,0x58,
+    0xC5,0x69,0x44,0x51,0x2F,0xAD,0xB5,0xF5,0xAB,0x9B,0xE6,0x69,0x2D,0xBD,0xB5,0xD5,
+    0xB6,0xF6,0x6A,0x93,0x02,0x0B,0x09,0x25,0xD6,0xFE,0xD7,0xF6,0xFF,0xFF,0xDF,0xBE,
+    0xD7,0xF6,0xB6,0xF6,0xBC,0xFE,0xEC,0xB8,0xD7,0xF6,0xB6,0xF6,0xD5,0xB7,0xBF,0xAB,
+    0xD6,0xF6,0xB6,0xF6,0xFE,0xBE,0xAC,0xA0,0xF7,0xFE,0xB6,0xF6,0xBD,0xEF,0xBF,0xBE,
+    0xD7,0xFE,0xF7,0xF6,0x55,0x57,0xFF,0xEF,0xD7,0xF6,0xB2,0xDD,0x00,0x00,0x80,0x60,
+    0x76,0xEE,0x66,0x7A,0xE0,0x78,0x5E,0x5F,0x67,0x82,0x05,0x72,0xE8,0xFD,0xBF,0x2B,
+    0x87,0x8A,0x05,0x7A,0xA7,0xAD,0x2F,0xEA,0x87,0x8A,0x25,0x7A,0x02,0xEA,0xFE,0xDF,
+    0x76,0xEE,0x66,0x82,0x35,0x25,0x25,0x2D,0x18,0xFF,0xF7,0xFE,0x2D,0x09,0x29,0x01,
+    0x38,0xFF,0x17,0xF7,0x57,0xDD,0x7F,0xFE,0x18,0xFF,0xF7,0xEE,0x88,0xE2,0xA0,0xC0,
+    0xF7,0xF6,0xD7,0xF6,0xAC,0x2E,0xB8,0xAA,0xF7,0xF6,0xD7,0xF6,0xFF,0xFA,0x7A,0xBA,
+    0xF7,0xF6,0xD7,0xF6,0x5A,0xF7,0x95,0xAA,0xF7,0xF6,0xD7,0xF6,0xD7,0x5E,0x5F,0x23,
+    0x18,0xFF,0xB6,0xF6,0x2B,0x2B,0xA2,0x72,0x17,0xFF,0xB6,0xF6,0x5C,0x5F,0x57,0x55,
+    0xB6,0xF6,0x54,0xE6,0xE0,0xA8,0xE8,0x78,0x75,0xEE,0x92,0xD5,0xA0,0xE8,0x78,0xFA,
+    0xB7,0xF6,0x92,0xCD,0xB7,0x25,0x0B,0x02,0xF7,0xF6,0xB6,0xF6,0xAD,0xBB,0xAA,0xAB,
+    0xF7,0xF6,0xD7,0xF6,0x5F,0xD5,0xFD,0x75,0xD7,0xF6,0xB7,0xEE,0xA8,0x00,0x00,0x00,
+    0xD7,0xF6,0xB7,0xEE,0x3A,0xAA,0x0A,0xA8,0xD7,0xF6,0xB6,0xEE,0x28,0xFA,0xB8,0xFB,
+    0xD7,0xF6,0xB7,0xEE,0xFE,0xBE,0x2F,0xB8,0xD7,0xF6,0xB7,0xEE,0x5F,0xFC,0xA2,0xA0,
+    0xF7,0xF6,0xB7,0xEE,0x2D,0x3D,0xFF,0xFF,0x38,0xFF,0xF7,0xF6,0x2A,0xAB,0xAD,0xB5,
+    0x39,0xFF,0xF7,0xF6,0x5E,0x58,0x60,0xC0,0xF7,0xF6,0xD8,0xF6,0xAA,0xAA,0x8B,0x78,
+    0xF7,0xF6,0x96,0xEE,0x8A,0xE8,0x68,0x5F,0xD7,0xF6,0x96,0xEE,0x2A,0x2A,0x2F,0x2D,
+    0xB7,0xF6,0x91,0xCD,0xB8,0xB8,0xE8,0xD8,0xD6,0xF6,0x54,0xE6,0x62,0xE2,0xA3,0xA9,
+    0x14,0xDE,0x71,0xCD,0x74,0xFC,0x74,0xFC,0x34,0xE6,0x92,0xCD,0xAD,0xA5,0xB5,0xB5,
+    0x71,0xCD,0xAF,0xB4,0xA8,0xAC,0xBE,0xD4,0xB6,0xF6,0x71,0xCD,0x0D,0x09,0x0B,0x2D,
+    0xD7,0xF6,0x34,0xE6,0xF8,0xF8,0x78,0x7A,0x75,0xEE,0x34,0xE6,0x27,0xA7,0xBF,0xEF,
+    0xD6,0xF6,0xB6,0xEE,0xFF,0xEA,0xBA,0xAB,0xD6,0xF6,0xB6,0xEE,0x29,0xAB,0xEC,0xEA,
+    0xD6,0xF6,0xB6,0xEE,0xAA,0xAA,0x0A,0x0E,0xD6,0xF6,0xB6,0xEE,0xAA,0xAA,0xAA,0xA2,
+    0xD6,0xF6,0xB6,0xEE,0xAA,0x86,0x7F,0x4A,0xD6,0xF6,0xB6,0xEE,0xFE,0xEA,0xBB,0xBA,
+    0x96,0xF6,0xB6,0xEE,0xF9,0xFD,0xBD,0xED,0xB6,0xF6,0x96,0xEE,0xEE,0xAA,0xEE,0xCA,
+    0x95,0xF6,0xB6,0xEE,0xDF,0x7F,0xDD,0x55,0xD6,0xF6,0xB6,0xEE,0x82,0x03,0x23,0x03,
+    0xD6,0xF6,0xF7,0xEE,0x00,0x20,0x22,0xA0,0xD6,0xF6,0xB7,0xEE,0xA2,0x82,0x00,0x00,
+    0xB6,0xF6,0xC4,0x59,0x70,0x70,0x70,0x60,0x85,0x59,0x23,0x49,0xE3,0xAE,0x5E,0xF7,
+    0x85,0x59,0x23,0x51,0x2D,0xAE,0x7F,0x7F,0x85,0x61,0xE3,0x40,0xE0,0xF8,0xFB,0x5F,
+    0x64,0x51,0xE3,0x40,0x2A,0x2F,0x2F,0x3D,0x87,0x72,0x84,0x59,0x3D,0xBD,0xBD,0x2D,
+    0xCF,0xBC,0xA8,0x7A,0x2D,0xBD,0xF5,0xF5,0x96,0xF6,0x8B,0x93,0x00,0x0B,0xF5,0x55,
+    0xB6,0xF6,0x8B,0x93,0x00,0x28,0xFF,0x55,0xB6,0xF6,0xAB,0x93,0x00,0x00,0x2A,0xD5,
+    0xB6,0xF6,0xCF,0xBC,0x00,0x00,0x00,0xF5,0xD7,0xF6,0x31,0xCD,0x00,0x00,0x0A,0xB5,
+    0xD7,0xFE,0x92,0xD5,0x00,0x00,0x00,0x7A,0x35,0xE6,0xE5,0x69,0x80,0xE0,0x78,0x5E,
+    0xE8,0x8A,0xE5,0x71,0xDC,0xF7,0xFD,0xF5,0x87,0x8A,0x26,0x7A,0x29,0xA9,0xCA,0xEB,
+    0x67,0x8A,0x06,0x7A,0x60,0xFC,0x9A,0x97,0xC8,0x92,0x06,0x7A,0xF5,0xBD,0x2F,0x0A,
+    0xB6,0xF6,0x88,0x8A,0x0D,0x09,0x0B,0x0B,0x38,0xFF,0xF8,0xFE,0xBF,0xBD,0xBF,0xF7,
+    0x18,0xFF,0x38,0xF7,0xAE,0xBA,0xAA,0xA8,0x38,0xFF,0xF7,0xF6,0xFA,0x7A,0xFA,0xF8,
+    0xF7,0xF6,0xD7,0xF6,0xCE,0x32,0xA0,0x20,0xF7,0xF6,0xD7,0xF6,0xAC,0xBA,0xC2,0x00,
+    0xF7,0xF6,0xD7,0xF6,0xA0,0xAA,0x8A,0x23,0x18,0xFF,0xD6,0xF6,0xBF,0x2F,0x8A,0x72,
+    0x17,0xFF,0x96,0xEE,0xF8,0x7E,0xD7,0x57,0xB6,0xF6,0x55,0xE6,0x82,0xAA,0xE2,0x62,
+    0x96,0xEE,0xB3,0xD5,0xA0,0xA8,0xFA,0xDF,0xD7,0xF6,0x14,0xDE,0xB5,0x0B,0x2B,0x02,
+    0xF7,0xF6,0xD7,0xF6,0xD5,0x96,0xAF,0xFF,0xD7,0xF6,0xF6,0xEE,0x02,0x82,0x0A,0x00,
+    0xF7,0xF6,0xB6,0xEE,0xEA,0xEA,0x7A,0xEA,0xD7,0xF6,0xB7,0xEE,0x80,0xC2,0xFB,0xAC,
+    0xD7,0xF6,0xB7,0xEE,0xAA,0xEA,0x00,0x00,0xB7,0xF6,0xD7,0xEE,0xEA,0xFF,0xFF,0xAE,
+    0xD7,0xF6,0xB7,0xEE,0x88,0x0A,0x2B,0xFF,0xD7,0xF6,0xB7,0xEE,0x88,0xA0,0x80,0xA0,
+    0xD7,0xF6,0xF7,0xEE,0x88,0xA0,0x88,0xA0,0x18,0xFF,0xD7,0xF6,0x3D,0xBF,0xBD,0xF5,
+    0x38,0xFF,0xF7,0xF6,0x82,0x8A,0xAB,0xBD,0x39,0xFF,0x97,0xEE,0xFE,0xFE,0x7C,0x78,
+    0xB7,0xF6,0x76,0xE6,0xE8,0xE8,0xFF,0xFE,0xD7,0xF6,0x76,0xEE,0xAF,0xBF,0xBF,0xB5,
+    0xB7,0xF6,0x30,0xC5,0xD8,0xD8,0xD8,0xF8,0xB7,0xF6,0x34,0xE6,0x83,0x8B,0x23,0x89,
+    0x55,0xEE,0x92,0xCD,0x56,0x7C,0x5C,0xFC,0xF4,0xDD,0x71,0xCD,0x2D,0x2D,0x2F,0x2F,
+    0x92,0xCD,0x4D,0xAC,0xFE,0xDC,0xD4,0x5C,0x35,0xE6,0x10,0xC5,0x2B,0x2D,0xBD,0xAD,
+    0x96,0xEE,0x34,0xE6,0xE0,0xE2,0xA9,0xE9,0x55,0xE6,0x34,0xE6,0x92,0x1C,0x28,0x80,
+    0xD6,0xF6,0xB6,0xEE,0xAB,0xEE,0xAE,0x2A,0xD6,0xF6,0xB6,0xEE,0x8A,0xAB,0xBA,0xA0,
+    0xD6,0xF6,0xB7,0xEE,0xAA,0x03,0x28,0xAC,0xF7,0xF6,0xB6,0xEE,0xAB,0xEA,0xBB,0xEF,
+    0xD6,0xF6,0xD7,0xEE,0x8A,0x8A,0xA2,0xAA,0xD6,0xF6,0xB6,0xEE,0x72,0xE0,0x80,0x80,
+    0xD6,0xF6,0x96,0xEE,0xFF,0xFE,0xFE,0xEA,0x95,0xF6,0xD6,0xEE,0xBA,0xEA,0xF6,0xFF,
+    0xD6,0xF6,0xB6,0xEE,0xF5,0xF7,0xFD,0xFF,0xD6,0xF6,0xF7,0xEE,0x28,0xA8,0x80,0x20,
+    0xD6,0xF6,0xF7,0xEE,0x80,0x08,0x28,0x82,0xF6,0xF6,0xD7,0xF6,0x77,0x5F,0xFF,0xFE,
+    0xD6,0xF6,0x4A,0x8B,0x60,0xC0,0x80,0x80,0x47,0x6A,0x03,0x41,0x77,0xD7,0x56,0xD4,
+    0x44,0x49,0xE3,0x40,0xAB,0xA8,0xA0,0x60,0x23,0x49,0xE3,0x40,0x7A,0x68,0x5E,0x56,
+    0x64,0x51,0xE3,0x40,0x3D,0xB5,0x35,0x3D,0xC8,0x7A,0xA5,0x59,0x2D,0x2D,0x2D,0xBD,
+    0x4A,0x93,0xA8,0x7A,0x2F,0x2D,0x8B,0xCD,0x4B,0x93,0xA8,0x7A,0x80,0xE8,0x5E,0x57,
+    0x09,0x83,0x47,0x72,0x00,0xAA,0xFF,0xD7,0x4A,0x8B,0x87,0x72,0x02,0xAF,0xF5,0xD5,
+    0x0C,0xA4,0xE8,0x82,0x2A,0xAF,0xBD,0xBD,0x6E,0xB4,0x09,0x8B,0x2A,0xFA,0x7B,0x5F,
+    0x6E,0xB4,0x05,0x6A,0x80,0x7A,0x5F,0x57,0xA8,0x82,0xC4,0x61,0xFC,0xBE,0xAF,0xAD,
+    0x46,0x7A,0xC5,0x69,0xBC,0xFE,0xFE,0xD6,0x47,0x82,0xE5,0x79,0xE2,0xAF,0xB5,0x35,
+    0xA8,0x92,0x06,0x7A,0xA7,0x89,0x8B,0x8B,0x2A,0x9B,0x67,0x8A,0x25,0x3D,0x2B,0x0B,
+    0xF7,0xFE,0x0D,0xB4,0x09,0x03,0x01,0x09,0x38,0xFF,0xF7,0xF6,0xBF,0xFF,0xBF,0xFF,
+    0x38,0xFF,0x17,0xF7,0xFF,0xBF,0xFD,0xFB,0x38,0xFF,0x17,0xF7,0x5E,0x5F,0xF7,0x7F,
+    0x38,0xFF,0xF7,0xF6,0x57,0x5F,0x7F,0xFA,0x18,0xFF,0xF7,0xF6,0x77,0x5D,0xB5,0xAE,
+    0x17,0xFF,0xB6,0xEE,0x2A,0x0A,0xC0,0x60,0xF7,0xFE,0x55,0xE6,0xA0,0xFC,0xFF,0xFF,
+    0xB6,0xF6,0x75,0xEE,0x82,0x02,0xAB,0x57,0xB6,0xF6,0x55,0xE6,0x70,0x7A,0xBA,0xDF,
+    0xF7,0xFE,0xB3,0xD5,0x97,0x0F,0x02,0xAA,0xF7,0xFE,0xD7,0xF6,0xD5,0x7A,0xEA,0xAB,
+    0xF7,0xF6,0xD7,0xF6,0xE3,0xEF,0xE3,0xF9,0xF7,0xF6,0xD7,0xF6,0x55,0x5F,0x76,0xEA,
+    0xF7,0xF6,0xB6,0xEE,0xAB,0xBF,0xBB,0xB2,0xD7,0xF6,0xB7,0xEE,0x08,0x80,0xE8,0x80,
+    0xD7,0xF6,0xB7,0xEE,0xA0,0xA8,0xE8,0xA6,0xB6,0xF6,0xD7,0xEE,0xAB,0xAB,0xAF,0xFA,
+    0xD7,0xF6,0xB7,0xEE,0xFF,0xBB,0xAA,0xEA,0xB7,0xF6,0xF7,0xEE,0xAA,0xAA,0xAA,0x6E,
+    0xF8,0xF6,0xD7,0xF6,0xD5,0x55,0xFD,0x2B,0xF8,0xF6,0xD7,0xF6,0x0F,0x0B,0x0A,0x0A,
+    0x18,0xFF,0xD7,0xF6,0x2A,0x2B,0xBB,0xFF,0x39,0xFF,0x97,0xEE,0x78,0x7A,0x72,0x6A,
+    0x96,0xEE,0x76,0xE6,0xB8,0x80,0xA8,0xBD,0xB7,0xF6,0x56,0xEE,0x3F,0xBF,0xAF,0xAE,
+    0xB7,0xF6,0x30,0xC5,0xD8,0xD8,0xF8,0x58,0xB7,0xF6,0x34,0xE6,0x09,0x89,0x29,0x89,
+    0x76,0xEE,0x72,0xCD,0xF8,0xF8,0x78,0x58,0xD3,0xD5,0x71,0xCD,0x2B,0xAE,0xFE,0xD5,
+    0x92,0xD5,0x6D,0xAC,0xD4,0x96,0x16,0x36,0x34,0xE6,0x92,0xD5,0xBD,0xAF,0x2B,0x0F,
+    0x96,0xEE,0x34,0xE6,0xE1,0xEB,0xCB,0x8B,0x55,0xE6,0x35,0xE6,0xA2,0xBE,0xFA,0xAC,
+    0xD6,0xF6,0xB6,0xEE,0xAA,0xAA,0xAA,0x02,0xD7,0xF6,0xB6,0xEE,0xAA,0xA8,0xBA,0x28,
+    0xD6,0xF6,0xB7,0xE6,0x20,0x02,0xC0,0xA2,0xD6,0xF6,0xB6,0xEE,0x8A,0x2A,0x0B,0x02,
+    0xD7,0xF6,0xD6,0xEE,0xAA,0x2A,0xB2,0x22,0xF8,0xF6,0xD6,0xF6,0x7D,0x5F,0x77,0xDD,
+    0xD6,0xF6,0xB6,0xEE,0x56,0xF7,0x5E,0x9E,0xD6,0xF6,0xB6,0xEE,0x75,0xF5,0xD5,0xB6,
+    0xD6,0xF6,0xB6,0xEE,0x9D,0xD7,0xFD,0xBB,0xF8,0xF6,0xD7,0xF6,0x5D,0xF5,0xFF,0xBD,
+    0xF6,0xF6,0xD7,0xF6,0x55,0xDD,0xFC,0xFE,0xF6,0xF6,0xD7,0xF6,0xFD,0x75,0x5F,0x6E,
+    0xF8,0xFE,0x76,0xE6,0x6A,0xE8,0xCA,0xAA,0x51,0xC5,0x02,0x41,0x56,0x56,0x54,0x5C,
+    0x84,0x51,0x23,0x41,0xF7,0xFD,0x8D,0x9D,0x44,0x49,0x03,0x41,0x56,0x94,0xF4,0x36,
+    0x06,0x62,0x03,0x41,0xB5,0xBF,0x2B,0x23,0x67,0x72,0xC5,0x59,0x29,0x0B,0x2A,0xD7,
+    0x09,0x83,0x46,0x6A,0x2A,0xAB,0xFF,0xFD,0xA8,0x7A,0x27,0x6A,0xA8,0xE8,0xFE,0xFB,
+    0x88,0x72,0x26,0x6A,0xA8,0x2E,0xEB,0x6F,0xA7,0x7A,0x26,0x6A,0x2F,0xBF,0xB7,0xD5,
+    0x6A,0x93,0xA7,0x7A,0x29,0xBD,0xD5,0x55,0x6A,0x93,0x47,0x72,0xA0,0xA2,0xEA,0x7F,
+    0x88,0x7A,0xA4,0x61,0x78,0x78,0x5E,0xDF,0x68,0x7A,0xE5,0x69,0x0D,0x2D,0xED,0xED,
+    0x47,0x7A,0x23,0x59,0xB8,0xF8,0xDE,0xDE,0x26,0x82,0x84,0x69,0x2B,0x0B,0x0B,0x2D,
+    0x67,0x8A,0x26,0x82,0x02,0xDA,0x7A,0xDD,0x49,0x9B,0x67,0x8A,0x2D,0x35,0xBD,0xE9,
+    0xF7,0xFE,0x0C,0xB4,0x09,0x09,0x09,0x09,0x18,0xFF,0xF7,0xF6,0x2A,0x2A,0xBA,0xAA,
+    0x38,0xFF,0xF7,0xF6,0x3B,0xAE,0xFB,0xEF,0x18,0xFF,0x38,0xF7,0xEB,0xAA,0xAA,0xA8,
+    0x38,0xFF,0x18,0xFF,0xBA,0xAA,0x8A,0xFA,0x38,0xFF,0xD7,0xF6,0xAA,0xAA,0xCA,0x6A,
+    0x18,0xFF,0xB6,0xEE,0x58,0x5E,0xF7,0xFF,0xD6,0xF6,0x96,0xEE,0xFF,0xFF,0x68,0x7A,
+    0x95,0xEE,0x91,0xD5,0xA0,0xE0,0x70,0x88,0x76,0xEE,0xF0,0xC4,0xA2,0xB7,0x2D,0x02,
+    0x55,0xEE,0x51,0xCD,0x2F,0xD7,0xF8,0xF0,0xD7,0xF6,0xD4,0xDD,0x02,0x03,0x0F,0x2D,
+    0xF7,0xF6,0xD7,0xF6,0xA9,0x2B,0xBA,0xAD,0xD8,0xFE,0xF7,0xF6,0xD5,0x75,0x77,0xDD,
+    0xF7,0xF6,0xD7,0xF6,0x5E,0xA7,0x88,0x56,0xF7,0xF6,0xB7,0xEE,0xAA,0xE8,0xEA,0xFF,
+    0xF7,0xF6,0xB7,0xEE,0xFF,0xDE,0xF5,0xAB,0xF7,0xF6,0xB7,0xF6,0xFF,0xAB,0xAA,0x08,
+    0xF7,0xF6,0xB7,0xEE,0xBF,0xAB,0x00,0x00,0xF8,0xF6,0xD7,0xF6,0x8A,0xEA,0xA0,0xAA,
+    0xF8,0xF6,0xD7,0xF6,0x2A,0x0A,0xA2,0x6E,0xF7,0xF6,0xD8,0xF6,0x02,0x00,0xF8,0xFB,
+    0xD7,0xF6,0xF8,0xEE,0xAA,0x82,0x22,0x0A,0x18,0xFF,0xB7,0xEE,0x4A,0xEA,0xEB,0xEF,
+    0xB6,0xEE,0x76,0xEE,0x77,0x5F,0x5E,0x74,0x96,0xEE,0x55,0xEE,0x22,0x2A,0x2A,0x37,
+    0xB6,0xF6,0x31,0xC5,0xD8,0xD8,0xD8,0xD8,0x96,0xEE,0x14,0xE6,0x01,0x09,0x0B,0x09,
+    0x96,0xEE,0x72,0xCD,0x58,0x78,0x78,0x68,0x72,0xCD,0x51,0xC5,0x2A,0x9B,0xC2,0x7B,
+    0xD3,0xD5,0xCF,0xBC,0x37,0x2F,0x2A,0x0B,0x34,0xE6,0xD3,0xD5,0x3D,0x39,0x3B,0xAF,
+    0x96,0xEE,0x55,0xE6,0xCF,0xAB,0xA1,0xAB,0x76,0xEE,0x55,0xE6,0x57,0x57,0x9C,0x1E,
+    0xD6,0xF6,0xB7,0xEE,0x80,0xA8,0xE8,0xA2,0xD7,0xF6,0xF6,0xEE,0x88,0xA0,0x00,0x00,
+    0xD7,0xF6,0xD6,0xEE,0xAA,0xA8,0xAA,0xAA,0xD7,0xF6,0xF6,0xEE,0x20,0x2A,0xA8,0x80,
+    0xF7,0xF6,0xD7,0xF6,0x59,0xD5,0xFD,0xBD,0xF7,0xF6,0xD7,0xF6,0xFF,0xDF,0xAF,0xA3,
+    0xD6,0xF6,0xB7,0xEE,0xA8,0xEA,0xA0,0xB0,0xD6,0xF6,0xB6,0xEE,0xDB,0xFE,0xB2,0x82,
+    0xD7,0xF6,0xB6,0xEE,0xBF,0xBE,0x6E,0xAE,0xF8,0xF6,0xD7,0xF6,0xBF,0x55,0xDD,0xD9,
+    0xF7,0xF6,0xD7,0xF6,0x5F,0xFF,0xBF,0xEF,0xF7,0xF6,0xD7,0xF6,0xAA,0xAA,0xAE,0xE2,
+    0xF7,0xF6,0xD7,0xF6,0x76,0x76,0x76,0xDD,0x54,0xE6,0x23,0x41,0x5C,0x5C,0x5C,0x58,
+    0xC5,0x59,0xA2,0x38,0xBF,0xBD,0xBD,0x2B,0x06,0x62,0x23,0x49,0xF5,0xBF,0x0B,0x00,
+    0x26,0x6A,0xA5,0x59,0xFD,0xFB,0xA0,0x80,0xE5,0x61,0xA5,0x59,0xBF,0x65,0xE6,0x38,
+    0x47,0x6A,0xE6,0x61,0x2F,0xA5,0xFF,0x0B,0x47,0x72,0xE5,0x61,0x2A,0x3E,0xD7,0x5E,
+    0x68,0x72,0xE5,0x61,0xE8,0xFE,0x55,0x55,0x46,0x6A,0xE5,0x61,0x8E,0xBF,0xBD,0x55,
+    0xA8,0x7A,0xC5,0x61,0x02,0xAA,0xFF,0x5D,0x68,0x72,0xC4,0x61,0xE0,0x7A,0x57,0x55,
+    0x88,0x82,0xA4,0x61,0xD5,0xAD,0x8F,0x0B,0xA8,0x82,0xA5,0x69,0xFE,0xFA,0x6A,0x70,
+    0x85,0x61,0xE3,0x58,0xB8,0xFE,0xBF,0xAF,0x67,0x82,0x64,0x61,0xBD,0xB5,0xA5,0x25,
+    0xA8,0x8A,0x26,0x82,0x7D,0xFD,0xAB,0x02,0x6A,0x9B,0x46,0x82,0xFD,0xBD,0xBF,0x17,
+    0xF7,0xFE,0x8F,0xBC,0x09,0x09,0x03,0x03,0xF7,0xFE,0x17,0xF7,0xFA,0xEE,0xAE,0xEF,
+    0x18,0xFF,0xF7,0xF6,0x2F,0xAB,0x82,0xAA,0x17,0xFF,0xF7,0xF6,0xAA,0xFA,0x5E,0x76,
+    0x17,0xFF,0xD7,0xF6,0x20,0x0A,0x0B,0x42,0x17,0xFF,0xB6,0xEE,0xE0,0x7C,0xDF,0x75,
+    0x18,0xFF,0xB6,0xEE,0x7D,0xF7,0xFD,0x2B,0xF8,0xFE,0xF3,0xDD,0xEA,0x7A,0x7A,0xC0,
+    0xF8,0xFE,0xD3,0xD5,0x0B,0x09,0x0B,0x02,0xF7,0xFE,0x76,0xEE,0x7E,0x70,0x60,0xC0,
+    0x76,0xEE,0xF4,0xDD,0x70,0x48,0x88,0x88,0x76,0xEE,0xD3,0xD5,0x2D,0x2D,0x2F,0xBE,
+    0xF7,0xFE,0x96,0xEE,0xAA,0x8B,0x29,0x29,0xF7,0xF6,0xD7,0xF6,0xEB,0xEC,0xFA,0xA0,
+    0xF7,0xF6,0xD7,0xF6,0xF5,0xF3,0xB9,0xD1,0xF7,0xF6,0xD7,0xF6,0xB5,0x2B,0xEF,0x75,
+    0xF7,0xF6,0xD7,0xF6,0xD6,0xF6,0xF7,0xFF,0xF7,0xF6,0xD7,0xF6,0xAA,0xBE,0xBF,0xF9,
+    0xF7,0xF6,0xD7,0xF6,0xA6,0xAF,0xBA,0xCA,0xF7,0xF6,0xD7,0xF6,0x80,0xA2,0x0A,0xAA,
+    0xF7,0xF6,0xD7,0xF6,0x8E,0x82,0x88,0xB5,0xF7,0xF6,0xD7,0xF6,0x08,0x00,0xC8,0x72,
+    0xF8,0xF6,0xB7,0xEE,0xFA,0x78,0xFE,0x5F,0xF8,0xF6,0xB7,0xEE,0x8B,0x8B,0xAB,0xB5,
+    0xB6,0xEE,0x76,0xE6,0x76,0xF6,0xBE,0xAC,0x96,0xEE,0x76,0xEE,0x35,0x88,0xD8,0xD6,
+    0x96,0xF6,0x51,0xCD,0xD8,0xD8,0xF8,0xD8,0x96,0xEE,0x14,0xDE,0x89,0x8B,0x8B,0xAB,
+    0x55,0xEE,0x72,0xCD,0x60,0x60,0x40,0x60,0x51,0xCD,0xAF,0xB4,0xA0,0xE8,0xF8,0x7E,
+    0x34,0xE6,0xF0,0xBC,0xA9,0x2D,0x29,0x09,0x54,0xE6,0x14,0xE6,0xD7,0xDF,0xBA,0x9A,
+    0x96,0xEE,0x55,0xE6,0xA9,0x2B,0x03,0x0F,0xB6,0xEE,0x55,0xE6,0xF7,0xFF,0xF7,0x27,
+    0xD7,0xF6,0xB6,0xEE,0xAA,0xA8,0x0A,0x02,0xD7,0xF6,0xB6,0xEE,0xAA,0xAA,0xAA,0xA8,
+    0xD6,0xF6,0xB7,0xEE,0xA2,0x22,0x22,0x02,0xF7,0xF6,0xB6,0xEE,0xAA,0xBA,0xEB,0xBB,
+    0xD7,0xF6,0xF7,0xEE,0xA0,0x80,0x28,0x8A,0xF7,0xF6,0xD7,0xF6,0xEB,0x6D,0x56,0x5E,
+    0xF7,0xF6,0xB6,0xEE,0xEA,0xAA,0xAF,0xFF,0xD7,0xF6,0xF6,0xEE,0x88,0x80,0xA2,0x80,
+    0xF7,0xF6,0xB6,0xEE,0xF6,0xFA,0xFA,0xAA,0xF7,0xF6,0xD7,0xF6,0xE9,0xFD,0xE0,0x8A,
+    0xF7,0xF6,0xD7,0xF6,0xAA,0xAA,0xBE,0xAE,0xF7,0xF6,0xD7,0xF6,0xA9,0xAF,0xEB,0xAA,
+    0xF7,0xF6,0x97,0xF6,0x22,0xA8,0xC8,0x6A,0x75,0xEE,0xA4,0x59,0x78,0x78,0x7C,0xFE,
+    0xA7,0x7A,0x83,0x51,0xF5,0xBF,0x2A,0x08,0x09,0x8B,0x06,0x6A,0x55,0xFF,0xEB,0x02,
+    0xE9,0x82,0x26,0x6A,0x55,0x7F,0xFA,0x88,0x87,0x72,0xC4,0x59,0x7F,0x57,0x7E,0x70,
+    0xC8,0x7A,0xA4,0x59,0xAF,0x2B,0x25,0xAD,0x88,0x72,0xE5,0x61,0x58,0x58,0x78,0x5C,
+    0x05,0x62,0xA4,0x59,0xBF,0x2F,0x27,0xFF,0x27,0x6A,0xE5,0x61,0x55,0xD5,0x70,0x55,
+    0x06,0x62,0x84,0x59,0x62,0x78,0xAA,0x08,0xC8,0x82,0xA4,0x59,0x95,0x25,0x2F,0x0A,
+    0xAC,0xA3,0x87,0x7A,0xF5,0xAB,0x2A,0x02,0x6B,0xA3,0xE6,0x71,0x7A,0xEA,0xAC,0x28,
+    0x2A,0x9B,0xC5,0x69,0x55,0x7B,0xE0,0x00,0x8B,0xA3,0xE5,0x71,0xB5,0xB5,0xBF,0xF0,
+    0xC9,0x92,0xC5,0x69,0xA0,0xE8,0xFA,0x7E,0x76,0xF6,0x46,0x72,0x95,0xB5,0x25,0x0D,
+    0xF7,0xFE,0x35,0xEE,0x01,0x02,0x00,0x00,0xF8,0xFE,0x17,0xF7,0xF9,0xFB,0xCE,0xBE,
+    0x17,0xFF,0xF7,0xF6,0xCA,0xEA,0xEA,0xDA,0x17,0xFF,0xD7,0xF6,0xEA,0xAE,0x8A,0x6A,
+    0x18,0xFF,0x96,0xE6,0xE2,0xB8,0xFE,0x7F,0xD7,0xF6,0x14,0xDE,0x00,0x20,0xEA,0x7E,
+    0x38,0xFF,0x34,0xDE,0x02,0x0A,0x29,0x09,0x38,0xFF,0x55,0xE6,0x70,0xE8,0xA8,0xA0,
+    0x18,0xFF,0xB7,0xEE,0x2D,0x29,0xAA,0x0F,0x18,0xFF,0xD7,0xF6,0x6A,0xEA,0xAA,0x88,
+    0xD7,0xF6,0x55,0xE6,0xD7,0x5E,0x7C,0x78,0x76,0xEE,0x14,0xE6,0xDE,0x5A,0xEA,0xEA,
+    0xF8,0xFE,0x55,0xE6,0x89,0x2D,0x2D,0xA5,0x18,0xFF,0xD7,0xF6,0xA9,0xBD,0xBF,0xFF,
+    0x18,0xFF,0xD7,0xF6,0x5F,0x7E,0xFA,0xAB,0xF7,0xF6,0xD7,0xF6,0x75,0x55,0x57,0xF8,
+    0xF7,0xF6,0xD7,0xF6,0xA7,0x6D,0x6D,0xAB,0x17,0xF7,0xD7,0xF6,0x7D,0xD5,0xFD,0xAA,
+    0xF8,0xFE,0xD7,0xEE,0x7F,0xBF,0xAA,0x28,0x18,0xFF,0xD7,0xF6,0xFD,0xFA,0xAB,0xFA,
+    0xD8,0xFE,0xF7,0xF6,0x55,0x55,0xF5,0xDD,0xF7,0xF6,0xB7,0xEE,0xE8,0xE8,0xFA,0x7A,
+    0xB6,0xEE,0x56,0xE6,0xA0,0xA8,0x28,0x2C,0xD7,0xF6,0x96,0xEE,0x07,0x03,0x02,0x00,
+    0xB6,0xF6,0x56,0xEE,0xBA,0x7E,0xEA,0xEE,0x96,0xEE,0x35,0xE6,0x88,0x2B,0x2A,0x2A,
+    0x76,0xEE,0x72,0xCD,0xD8,0xD0,0xD8,0xF8,0x96,0xEE,0x15,0xE6,0x8B,0x89,0xAF,0xE9,
+    0x56,0xEE,0xB3,0xD5,0x60,0x60,0x6A,0x6A,0xF1,0xC4,0x6E,0xAC,0xE8,0xF8,0x7E,0xDC,
+    0x34,0xE6,0xEF,0xC4,0x29,0x09,0x0B,0x0B,0x55,0xE6,0x14,0xDE,0xBE,0x97,0xFE,0x3E,
+    0x96,0xEE,0x35,0xE6,0x0B,0x3B,0x57,0x5F,0xD7,0xF6,0x35,0xE6,0x2F,0x2F,0x8D,0x2B,
+    0xD6,0xF6,0xB6,0xEE,0x02,0x00,0xE2,0x02,0xD6,0xF6,0xB6,0xEE,0x22,0xCA,0x88,0xA8,
+    0xD6,0xF6,0xB6,0xEE,0x02,0x2B,0xAA,0x88,0xD7,0xF6,0xD6,0xEE,0xAA,0xA2,0xAA,0x2A,
+    0xD7,0xF6,0xF6,0xEE,0x82,0x0A,0x80,0x0A,0xD6,0xF6,0xF7,0xEE,0x08,0x82,0x82,0x08,
+    0xD6,0xF6,0xB6,0xEE,0xBA,0xBE,0xFE,0xFC,0xD6,0xF6,0xB6,0xEE,0x02,0x23,0xAB,0xAA,
+    0xD6,0xF6,0xF7,0xEE,0xA8,0xA2,0xA0,0x08,0xF7,0xF6,0xD6,0xF6,0x08,0x02,0x8F,0xFD,
+    0xF7,0xF6,0xD6,0xF6,0xB8,0x02,0x00,0xAB,0xD7,0xFE,0xF7,0xF6,0xBD,0xF7,0xD5,0xF5,
+    0xD7,0xF6,0x13,0xE6,0xC0,0xC0,0x40,0x40,0x8D,0xB4,0x86,0x72,0x5C,0x5C,0x56,0x56,
+    0xA8,0x7A,0x06,0x6A,0x2A,0xEF,0xFF,0x5C,0xE8,0x8A,0xE5,0x61,0x02,0xAA,0x5F,0x75,
+    0xC8,0x82,0x05,0x62,0xA8,0xFE,0xF5,0xDD,0x87,0x72,0x84,0x51,0xE8,0x7A,0x7E,0x7E,
+    0xE5,0x61,0x43,0x49,0x02,0xAB,0xD7,0xDF,0xE6,0x61,0x84,0x51,0xAA,0xAB,0xE5,0x29,
+    0x26,0x6A,0xA5,0x59,0x5F,0xBF,0xAF,0x3F,0x67,0x72,0xC5,0x59,0xF5,0xFD,0xA7,0x2B,
+    0x29,0x93,0xE5,0x61,0xD5,0xFF,0x2B,0x0B,0x4A,0x9B,0x66,0x7A,0xAD,0x2B,0x8A,0x02,
+    0x2E,0xBC,0x4A,0x9B,0x2D,0x2D,0x2D,0x3D,0x8F,0xC4,0x2A,0x9B,0x5F,0xE8,0x80,0x00,
+    0xEC,0xAB,0xC9,0x8A,0x9D,0xD7,0xFE,0xF8,0xAC,0xAB,0x05,0x6A,0xE0,0xE8,0xFA,0x5F,
+    0x30,0xCD,0x26,0x72,0x55,0xD5,0xB5,0x2D,0xD7,0xFE,0x2A,0x93,0x09,0x0B,0x02,0x00,
+    0x18,0xFF,0xF7,0xF6,0xEE,0xEB,0x83,0xAB,0x17,0xFF,0xF7,0xF6,0xAB,0xBF,0xAE,0xEA,
+    0x17,0xFF,0xD7,0xF6,0xBA,0xBE,0xAE,0xFA,0x18,0xF7,0x95,0xEE,0x60,0x7C,0x5E,0xB5,
+    0x17,0xFF,0x75,0xE6,0x77,0xF7,0xAB,0x00,0x17,0xFF,0xB3,0xD5,0x7E,0xFA,0xA8,0xA0,
+    0x18,0xFF,0x75,0xE6,0x01,0x02,0x00,0x00,0x39,0xFF,0xD7,0xF6,0x70,0xF0,0xE8,0xE0,
+    0x18,0xFF,0xD7,0xF6,0xAD,0x2F,0xAF,0xEF,0x18,0xFF,0xF8,0xF6,0xEE,0xDD,0xAB,0xBB,
+    0xF8,0xFE,0x55,0xE6,0x78,0x60,0xC0,0x80,0x75,0xEE,0x34,0xE6,0x6A,0xEA,0xEA,0xF8,
+    0xD7,0xF6,0x34,0xE6,0x2F,0x35,0xBD,0xBF,0xF7,0xF6,0xB7,0xF6,0x20,0xAA,0xAB,0xAB,
+    0x18,0xFF,0xF8,0xF6,0xF5,0xD5,0xBF,0x55,0xF8,0xF6,0xD7,0xF6,0x3A,0xBC,0xE0,0x00,
+    0x18,0xFF,0xF8,0xF6,0x57,0x6B,0xD5,0x55,0xF8,0xFE,0xF7,0xF6,0xD5,0xD5,0x5F,0x5F,
+    0x18,0xFF,0xF7,0xF6,0x75,0xF7,0xFD,0xD5,0xF7,0xF6,0xD8,0xF6,0x00,0x00,0xA8,0xE8,
+    0xF7,0xF6,0xD7,0xF6,0xE8,0x7A,0xFA,0x7A,0xD7,0xF6,0x96,0xEE,0xB0,0xE8,0xF2,0x7A,
+    0xD7,0xEE,0x75,0xEE,0x2F,0xBF,0x37,0xB7,0xD7,0xF6,0xB6,0xEE,0x00,0x00,0xBE,0xEA,
+    0x96,0xEE,0x35,0xE6,0x2A,0xAC,0xA6,0x96,0x76,0xEE,0x55,0xE6,0x08,0x2E,0x38,0x0A,
+    0x76,0xEE,0x92,0xCD,0xD8,0xD8,0xD8,0xD8,0x76,0xEE,0x14,0xDE,0xC9,0xC1,0xA9,0xEB,
+    0x35,0xE6,0xB3,0xD5,0x68,0x6A,0x6E,0x7E,0x51,0xCD,0xEC,0xA3,0xBE,0x96,0x97,0x36,
+    0x95,0xEE,0x72,0xD5,0xAD,0xA9,0x8F,0x0B,0xB7,0xF6,0x14,0xDE,0xB7,0x37,0x2F,0xA8,
+    0xB7,0xF6,0x35,0xE6,0xFF,0xF8,0xBE,0x57,0xB6,0xEE,0x55,0xEE,0x03,0x8A,0xAA,0x7B,
+    0xF7,0xF6,0xB6,0xEE,0x8F,0xEF,0xEF,0xAB,0xD7,0xF6,0xD6,0xEE,0xAA,0xAA,0xAA,0xAA,
+    0xD6,0xF6,0xF6,0xEE,0x00,0xA0,0xA0,0x82,0xD7,0xF6,0xD6,0xEE,0xAA,0xAA,0x2A,0x2A,
+    0xD6,0xF6,0xD7,0xEE,0x2A,0xA2,0xAA,0x8A,0xD6,0xF6,0xD6,0xEE,0x8A,0xAA,0x2A,0xA2,
+    0xD6,0xF6,0xB6,0xEE,0xAE,0xDC,0xFB,0xBA,0xD6,0xF6,0xB6,0xEE,0xEF,0xBA,0xEE,0xBB,
+    0xD6,0xF6,0xB6,0xEE,0x0A,0x83,0xBA,0xAE,0xD6,0xF6,0xB6,0xEE,0x00,0x82,0x80,0xAA,
+    0xD6,0xF6,0xF7,0xEE,0xA8,0xAA,0x80,0x00,0xD7,0xFE,0xF6,0xEE,0xAB,0xAB,0x3E,0x2A,
+    0xB6,0xF6,0x49,0x8B,0x80,0xE0,0x60,0x60,0x49,0x8B,0x43,0x49,0xA8,0xFE,0x5F,0x5F,
+    0x87,0x72,0xE2,0x38,0xA8,0xAE,0xDF,0x55,0x06,0x62,0x23,0x41,0x00,0x2A,0xFF,0x55,
+    0x05,0x62,0xE2,0x38,0xA0,0xEE,0xDF,0x55,0xA4,0x59,0x02,0x39,0x80,0xAA,0xBD,0xB5,
+    0xA8,0x7A,0x44,0x51,0xF5,0xAD,0x0B,0x0B,0x87,0x7A,0xE5,0x61,0x55,0x7E,0xF8,0x78,
+    0x27,0x6A,0xE5,0x61,0xDC,0x70,0xD7,0xB7,0xCC,0xA3,0x26,0x6A,0xF5,0xAD,0x2D,0xAD,
+    0x2D,0xB4,0x29,0x93,0x55,0xFF,0x82,0x0A,0x4D,0xBC,0x29,0x9B,0xD5,0xD5,0x7E,0xF8,
+    0x0D,0xB4,0x29,0x93,0x2B,0x3F,0xF5,0x5F,0xAF,0xCC,0x8B,0xA3,0x82,0xAB,0xDD,0x55,
+    0xEC,0xAB,0x67,0x7A,0xF8,0x78,0x58,0x5E,0xEC,0xAB,0x06,0x72,0x57,0x55,0xD5,0x3F,
+    0xD7,0xFE,0xE8,0x82,0x2D,0x29,0x0B,0x02,0x18,0xFF,0xF7,0xFE,0xBD,0xAF,0x09,0x01,
+    0x17,0xFF,0xF8,0xF6,0xA2,0x08,0xA2,0xA8,0x17,0xFF,0xF7,0xF6,0x7A,0xFA,0xAE,0x6A,
+    0x18,0xFF,0xB7,0xEE,0x78,0xDA,0xBE,0xAF,0x39,0xFF,0xD6,0xF6,0xF5,0xAF,0xAB,0x0A,
+    0x59,0xFF,0xD7,0xFE,0xAA,0xAA,0x8A,0x60,0xF8,0xFE,0xF4,0xDD,0xB8,0x1C,0x36,0x2F,
+    0x38,0xFF,0x18,0xFF,0xBD,0xBD,0xBD,0xFD,0x39,0xFF,0xF8,0xF6,0xE8,0x78,0x7A,0x5A,
+    0x18,0xFF,0xF8,0xF6,0xA5,0xA5,0xED,0xED,0x18,0xFF,0xF8,0xF6,0xFF,0xAB,0x0B,0xAD,
+    0x18,0xFF,0xD7,0xF6,0xE2,0xA2,0xA2,0xA0,0xF7,0xF6,0x55,0xE6,0x57,0x7E,0xF8,0xE8,
+    0xB6,0xF6,0x55,0xE6,0x35,0xB7,0xBB,0xAE,0xF7,0xF6,0xB7,0xF6,0x8B,0x89,0x0D,0x2B,
+    0xF7,0xF6,0xD7,0xF6,0x00,0x0B,0x2B,0x0A,0xD7,0xFE,0xF8,0xF6,0x7D,0xDF,0x5D,0x55,
+    0xF7,0xF6,0xD7,0xF6,0x88,0x02,0x00,0x82,0xF7,0xF6,0xD7,0xF6,0x08,0x2B,0x5F,0x78,
+    0xF7,0xF6,0xD7,0xF6,0x38,0xAA,0xFA,0xEA,0xF7,0xF6,0xD7,0xF6,0xF8,0x7A,0x7B,0x7F,
+    0xF7,0xF6,0xB6,0xEE,0xB2,0xFA,0xFB,0x7F,0xD7,0xF6,0x55,0xE6,0xE8,0x7A,0x7A,0x5F,
+    0xD7,0xF6,0x55,0xEE,0x2D,0x2D,0x2D,0x2B,0xD7,0xF6,0x96,0xF6,0xAA,0xE8,0xA8,0x6A,
+    0x75,0xEE,0xD3,0xD5,0x2C,0xBC,0xB6,0xF6,0x96,0xEE,0x55,0xE6,0xAB,0xBF,0xAB,0xAD,
+    0x55,0xE6,0x92,0xD5,0xD8,0xF8,0xD8,0xD8,0x76,0xEE,0xF3,0xDD,0x8B,0xAB,0xAB,0xA9,
+    0x34,0xEE,0xB3,0xDD,0xFE,0x6A,0x7E,0x7C,0x72,0xD5,0x6E,0xAC,0x37,0x3F,0x2E,0x2A,
+    0x96,0xF6,0x31,0xCD,0x0B,0xAF,0xFF,0x77,0x55,0xEE,0x31,0xCD,0xA0,0xFA,0xFF,0x55,
+    0xF3,0xDD,0x51,0xCD,0xA8,0x2F,0xAD,0x2B,0x75,0xEE,0xF4,0xDD,0x81,0xBB,0xF9,0xAF,
+    0xD6,0xF6,0xF2,0xDD,0x00,0x00,0x08,0xAD,0xF7,0xF6,0xB6,0xEE,0xAB,0xAB,0xAF,0xFF,
+    0xD6,0xF6,0xB7,0xEE,0x08,0x02,0x0A,0x08,0xD6,0xF6,0xF7,0xEE,0xA0,0x02,0x82,0x2C,
+    0xD6,0xF6,0xF6,0xEE,0x00,0x0A,0x88,0x00,0xD6,0xF6,0xF7,0xEE,0x28,0x00,0x88,0x28,
+    0xF6,0xF6,0xB6,0xEE,0x7F,0xBB,0xAA,0xBA,0xD6,0xF6,0xB6,0xEE,0xEF,0x88,0x00,0x00,
+    0xD6,0xF6,0xB6,0xEE,0xFF,0x3B,0x20,0x80,0xD6,0xF6,0xB6,0xEE,0xAB,0xFB,0xA2,0xA0,
+    0xD6,0xF6,0xB6,0xEE,0x02,0x02,0x00,0x2A,0xD6,0xF6,0xB6,0xF6,0xA0,0xE0,0xC8,0xE8,
+    0x75,0xEE,0x86,0x72,0xE0,0x60,0x60,0x70,0x05,0x62,0xC2,0x30,0xE8,0xEC,0xFA,0x7E,
+    0x02,0x39,0xA1,0x28,0x7C,0xFF,0x7E,0x56,0x03,0x39,0xA1,0x28,0xAB,0xFF,0x3F,0xF5,
+    0x23,0x41,0xC2,0x30,0xEF,0x29,0x29,0xAF,0xE5,0x69,0x23,0x41,0xF5,0xB5,0x35,0x3D,
+    0x09,0x93,0x06,0x6A,0xAD,0xAB,0x82,0x02,0x87,0x7A,0x23,0x41,0xE8,0xFA,0x5E,0x5C,
+    0xC5,0x61,0x03,0x41,0x00,0x0F,0xB5,0xD5,0x29,0x93,0x84,0x51,0x2B,0xAB,0xBF,0xFD,
+    0xCC,0xAB,0x47,0x72,0x0A,0xAB,0xB7,0xF5,0x0D,0xB4,0x2A,0x93,0x80,0x82,0xAB,0xAD,
+    0xAB,0xAB,0x09,0x8B,0x78,0xE0,0xE2,0x60,0x29,0x93,0x67,0x7A,0x80,0xEE,0x5E,0x57,
+    0xEC,0xAB,0x67,0x7A,0x57,0xFF,0xAD,0x2D,0x8E,0xBC,0xA8,0x82,0x35,0x3D,0xBF,0xBF,
+    0xD7,0xFE,0xEF,0xC4,0x02,0x03,0x03,0x2D,0x18,0xFF,0xF7,0xFE,0x2E,0xA6,0xAE,0xBD,
+    0x18,0xFF,0xF7,0xF6,0xA2,0x82,0x02,0xCA,0x18,0xFF,0xB6,0xEE,0xE0,0xB8,0xFE,0x7E,
+    0x38,0xFF,0xB6,0xEE,0xBF,0xEF,0xBF,0x35,0x59,0xFF,0x18,0xFF,0xA5,0xA9,0xAA,0x8A,
+    0x39,0xFF,0x96,0xEE,0xE0,0x60,0x78,0x58,0x18,0xFF,0x55,0xE6,0x37,0xA7,0x27,0x2D,
+    0x39,0xFF,0x18,0xFF,0xF5,0xBD,0xD5,0xD5,0x39,0xFF,0xF8,0xF6,0xFA,0xFA,0xFC,0xFA,
+    0x18,0xFF,0xF8,0xF6,0x7E,0x7F,0x57,0x96,0x18,0xFF,0xF8,0xF6,0x2B,0xEB,0xEE,0xAB,
+    0x18,0xFF,0xF8,0xF6,0x62,0xEA,0xCA,0xEA,0xF7,0xF6,0x96,0xEE,0x5A,0xFA,0xF8,0xB8,
+    0xD7,0xF6,0x75,0xEE,0xDF,0xFE,0xB8,0xA0,0xF8,0xF6,0xB6,0xF6,0x09,0x0D,0x25,0x37,
+    0x18,0xFF,0xD7,0xF6,0xAF,0xBF,0x3E,0xBF,0x18,0xFF,0xF7,0xF6,0x57,0x7E,0x80,0xAA,
+    0x18,0xFF,0xD7,0xF6,0xDF,0xAB,0xBA,0xAA,0xF8,0xFE,0xF7,0xF6,0x7F,0xFF,0xFD,0xFF,
+    0xF7,0xF6,0xB6,0xF6,0xA2,0x68,0x7A,0x5A,0xD7,0xF6,0x76,0xEE,0x80,0xEB,0x7E,0x7A,
+    0xB6,0xF6,0x55,0xE6,0x88,0x7E,0x7F,0xFB,0x96,0xEE,0x55,0xE6,0xD6,0xA5,0x2D,0x02,
+    0xD7,0xF6,0x76,0xEE,0x8D,0x8F,0x2F,0xAF,0xB6,0xF6,0x96,0xEE,0x5E,0xEF,0x2B,0xE5,
+    0x55,0xE6,0xB3,0xD5,0xB4,0xBE,0xF4,0xBE,0x75,0xEE,0x35,0xE6,0x83,0x8D,0xF9,0xAD,
+    0x55,0xEE,0x92,0xD5,0xFC,0xDC,0xDC,0xDE,0x55,0xEE,0x51,0xCD,0x02,0xA2,0xFA,0x5A,
+    0x14,0xE6,0x72,0xCD,0xA0,0x80,0x82,0xA9,0x51,0xCD,0x6E,0xB4,0x28,0x2E,0x2E,0x36,
+    0x72,0xCD,0x31,0xC5,0x80,0xE0,0x5C,0x5C,0x92,0xD5,0x30,0xC5,0x37,0x2D,0x0F,0x2D,
+    0xF4,0xDD,0x92,0xD5,0xBD,0xA5,0xA5,0x2D,0x55,0xE6,0xD3,0xDD,0x2B,0xA7,0xB7,0x75,
+    0x92,0xD5,0xE8,0x82,0x2F,0xD5,0x55,0x55,0x95,0xEE,0x08,0x83,0x00,0xAD,0xD5,0x55,
+    0xB5,0xF6,0x28,0x83,0x00,0x00,0x2F,0xD5,0xB6,0xF6,0x6D,0xB4,0x00,0x00,0x00,0x2D,
+    0xF7,0xF6,0x95,0xF6,0xAA,0x2B,0xAA,0xBD,0xF7,0xF6,0xD6,0xF6,0xDD,0x9F,0x5D,0x75,
+    0xF7,0xF6,0xB6,0xF6,0xAA,0x38,0xBB,0x7F,0xF6,0xF6,0xD6,0xF6,0xF5,0x7E,0xF7,0x5D,
+    0xF6,0xF6,0xD6,0xF6,0x7B,0x57,0x56,0x57,0xF7,0xFE,0xD6,0xF6,0x5F,0xFB,0x55,0x57,
+    0xD6,0xF6,0xB6,0xF6,0x3A,0xA2,0x00,0x00,0xF7,0xF6,0xB6,0xF6,0xFF,0xFF,0xEA,0xAA,
+    0x75,0xEE,0x26,0x62,0x70,0x70,0x70,0x60,0x84,0x49,0xE2,0x30,0xF8,0x7C,0x7E,0xFE,
+    0x03,0x39,0x61,0x20,0xFE,0x5E,0xDA,0x80,0x02,0x39,0x81,0x20,0xAD,0xBD,0x2B,0x2A,
+    0x02,0x39,0xC2,0x30,0xBE,0x2F,0xBB,0xF0,0x46,0x7A,0x03,0x41,0xBD,0x35,0x3D,0x2D,
+    0x09,0x93,0x67,0x7A,0x83,0x83,0xCB,0x7F,0x47,0x72,0xE2,0x38,0x78,0x5C,0x7C,0x5E,
+    0x44,0x49,0xC2,0x30,0x3F,0x35,0xBD,0xBD,0xE5,0x61,0xA1,0x30,0x02,0x0A,0xAA,0x55,
+    0xE8,0x82,0xE3,0x40,0x2A,0x0A,0xAF,0xD5,0x8A,0xA3,0xE5,0x61,0x0A,0xAA,0xAB,0xBD,
+    0xAB,0xA3,0xC8,0x82,0xE0,0xFA,0x7B,0x55,0xE9,0x8A,0x46,0x7A,0x9F,0xB7,0xAF,0x2F,
+    0xEB,0xA3,0xE9,0x8A,0x2D,0x2D,0xF7,0xD7,0xEC,0xAB,0x88,0x7A,0xF8,0x70,0x6A,0xFE,
+    0xEF,0xC4,0x06,0x6A,0x2F,0xF5,0x55,0x57,0xB6,0xF6,0x25,0x6A,0x00,0x2D,0x35,0xB5,
+    0x18,0xFF,0x75,0xEE,0xA0,0xE2,0xFF,0xFD,0xD6,0xF6,0x96,0xEE,0xAA,0xAE,0xCF,0x38,
+    0x59,0xFF,0xB7,0xEE,0xAD,0x0D,0x8B,0x22,0x59,0xFF,0x18,0xFF,0xEA,0xE8,0xFE,0x7A,
+    0xF7,0xFE,0x55,0xE6,0xF0,0x7C,0x5C,0x5F,0xF8,0xFE,0x55,0xE6,0x0D,0x2D,0x0D,0x0D,
+    0x39,0xFF,0xF8,0xF6,0xAB,0xAB,0x29,0xAF,0x39,0xFF,0xF8,0xF6,0xEA,0xFA,0x6A,0xEA,
+    0x18,0xFF,0xF8,0xF6,0x7D,0xB7,0x5E,0xDB,0x18,0xFF,0xF8,0xF6,0xAF,0xFB,0xFD,0xF7,
+    0x18,0xFF,0xF8,0xF6,0xFA,0x6A,0xEF,0x5F,0xF7,0xF6,0x97,0xEE,0xA8,0xA8,0xAA,0xA2,
+    0xF7,0xF6,0xD7,0xF6,0x55,0x5F,0xAB,0xAA,0xF8,0xF6,0xB7,0xF6,0x37,0x3B,0x2A,0x22,
+    0x18,0xFF,0xF7,0xF6,0x5F,0xDF,0x5A,0x7B,0x18,0xFF,0xF8,0xF6,0xBB,0xAA,0xBF,0xEF,
+    0xF7,0xFE,0x18,0xF7,0xAF,0xBD,0xAF,0xFF,0xF7,0xF6,0xD7,0xF6,0xA0,0x00,0xE0,0x58,
+    0xD7,0xF6,0x96,0xEE,0xE0,0xEC,0x7A,0x76,0xB7,0xF6,0x76,0xEE,0xF8,0xFA,0x5E,0x55,
+    0x96,0xEE,0x55,0xE6,0xEA,0x7A,0xFA,0x5B,0x76,0xEE,0x55,0xE6,0x8B,0x2D,0xB9,0x2F,
+    0xB6,0xF6,0x76,0xEE,0xA3,0xEB,0xEA,0xAA,0xB6,0xF6,0x76,0xEE,0xAB,0x8F,0xEB,0xCB,
+    0x14,0xE6,0x72,0xCD,0xAC,0xBC,0xB4,0xD6,0x75,0xEE,0xF4,0xE5,0x2B,0x8B,0xAB,0xA9,
+    0x34,0xE6,0xB3,0xD5,0xDC,0xDC,0xD4,0xDE,0x14,0xE6,0x30,0xC5,0x58,0x58,0x68,0xE0,
+    0xB3,0xD5,0x10,0xC5,0x09,0x2D,0x35,0x9F,0x31,0xC5,0x4D,0xAC,0x26,0x26,0xA6,0x36,
+    0x31,0xCD,0xF0,0xBC,0x3C,0x3F,0x37,0xEA,0x92,0xD5,0x31,0xC5,0x2F,0xAF,0xA7,0xA5,
+    0xF3,0xDD,0x72,0xD5,0x2F,0xAF,0xAD,0xAD,0xD3,0xDD,0x51,0xCD,0x82,0xEA,0x72,0x58,
+    0xE8,0x82,0xC7,0x7A,0x00,0x8E,0xFE,0x98,0x08,0x83,0xC7,0x7A,0xFE,0xA2,0xFB,0xDB,
+    0x08,0x83,0xC7,0x82,0x2B,0x2E,0xFE,0xFD,0xEB,0x9B,0xE8,0x82,0x3F,0x75,0x55,0x55,
+    0x55,0xEE,0xE8,0x82,0x0A,0xF5,0x55,0x55,0xB5,0xF6,0xE7,0x82,0x00,0x0A,0xBD,0x55,
+    0xB6,0xF6,0x8A,0x9B,0x00,0x00,0x02,0xF5,0xD6,0xF6,0xF4,0xE5,0x00,0x08,0x02,0x2D,
+    0xF6,0xFE,0xB6,0xF6,0xAE,0xAF,0xFF,0xD5,0xF8,0xFE,0xD6,0xF6,0xDF,0x5F,0xD5,0x55,
+    0xD7,0xFE,0xD6,0xF6,0xD5,0x7F,0x7F,0xFF,0xF6,0xFE,0xD7,0xF6,0x7E,0x5D,0x7B,0x7A,
+    0xB6,0xF6,0x86,0x72,0x60,0x60,0xC0,0xC0,0xE6,0x59,0x23,0x41,0x55,0x57,0x5E,0xE8,
+    0x84,0x49,0x23,0x41,0x7F,0xFB,0x55,0x3A,0x64,0x49,0xE2,0x30,0xD7,0xEC,0xBA,0xF8,
+    0x23,0x41,0xE2,0x38,0x7F,0xF6,0xBB,0x29,0x46,0x7A,0x44,0x49,0x2D,0x2D,0x0D,0x2F,
+    0x66,0x7A,0x84,0x59,0xA0,0xE8,0x7A,0x5A,0x64,0x51,0xE3,0x38,0x5C,0x78,0x6E,0xE8,
+    0xE2,0x38,0xA2,0x30,0x62,0xE2,0x80,0x08,0xC2,0x30,0x81,0x28,0x97,0xBE,0xEA,0xF8,
+    0x23,0x41,0x82,0x28,0x2F,0x2F,0xAF,0x35,0x88,0x82,0x43,0x49,0x2D,0xB5,0x35,0x35,
+    0xE9,0x8A,0x67,0x7A,0xAB,0x3D,0x3F,0x7A,0x09,0x8B,0x88,0x7A,0xFB,0xDE,0xD8,0xDF,
+    0x29,0x93,0x87,0x7A,0x2B,0xB7,0xFF,0x6F,0x09,0x8B,0xA5,0x59,0xA8,0xF8,0x7A,0x5F,
+    0xE8,0x82,0xC5,0x61,0xEE,0xAF,0x2D,0x09,0xCC,0xA3,0xC5,0x61,0x35,0xF7,0xFB,0xFE,
+    0xB6,0xF6,0xE9,0x8A,0x02,0x0B,0x2D,0xD5,0x38,0xFF,0x75,0xEE,0xBE,0x2F,0x0A,0x01,
+    0x39,0xFF,0x19,0xFF,0x00,0x80,0x20,0xE0,0x39,0xFF,0x96,0xF6,0xC0,0xC8,0x60,0x78,
+    0x76,0xEE,0x35,0xE6,0xC8,0x68,0x6E,0x7A,0xF8,0xFE,0x55,0xE6,0x09,0x09,0x09,0x0B,
+    0x39,0xFF,0xF8,0xFE,0xAF,0xAF,0xAD,0xAD,0x18,0xFF,0xF8,0xF6,0xE0,0xC0,0xA0,0xA0,
+    0x18,0xFF,0xF8,0xF6,0xF7,0xFF,0xDD,0xFE,0x19,0xFF,0xF7,0xF6,0xDF,0xFF,0xFD,0x57,
+    0xF8,0xFE,0x17,0xF7,0x2A,0xA2,0x2A,0x2A,0xF7,0xF6,0xD7,0xF6,0x9C,0xFA,0xAA,0xA2,
+    0xF8,0xF6,0xD7,0xF6,0xBA,0x3F,0x27,0x2D,0x17,0xFF,0xF8,0xF6,0xDD,0xF7,0x7F,0xFD,
+    0x18,0xFF,0xF7,0xF6,0x7F,0xEB,0xE9,0xEB,0x18,0xFF,0xD7,0xF6,0x2A,0xAA,0x2F,0x8F,
+    0x18,0xFF,0xF8,0xF6,0xEA,0x6A,0x6F,0x7D,0xF7,0xF6,0xB7,0xEE,0x78,0x78,0x7A,0x5A,
+    0xB7,0xF6,0x76,0xEE,0xF8,0x76,0x5E,0x75,0x96,0xEE,0x55,0xE6,0x5F,0x7E,0x8A,0x97,
+    0x96,0xEE,0x35,0xE6,0x77,0xF7,0xFA,0x28,0x96,0xEE,0x35,0xE6,0xBF,0xAF,0xB7,0x3F,
+    0xB7,0xF6,0x76,0xEE,0xCA,0xFA,0x7E,0x5E,0xB6,0xF6,0x55,0xE6,0xE2,0xEA,0xEA,0x6A,
+    0xD3,0xDD,0x31,0xCD,0x3C,0xAC,0xBC,0xB6,0x35,0xE6,0xB3,0xD5,0x02,0x0B,0x0B,0x09,
+    0x14,0xE6,0xB3,0xD5,0x9E,0xFC,0x9C,0xBC,0x14,0xE6,0xD3,0xDD,0x7A,0x6C,0xDC,0xF4,
+    0xD3,0xDD,0x31,0xC5,0x5E,0x78,0x40,0x40,0x31,0xCD,0x4E,0xAC,0x37,0x37,0x37,0x17,
+    0x31,0xCD,0xCF,0xBC,0xA8,0x28,0xBC,0x5E,0x71,0xCD,0x11,0xC5,0x2F,0xAF,0xAF,0xA7,
+    0x14,0xE6,0x31,0xC5,0x2B,0x0F,0xBF,0x5F,0xD3,0xDD,0xF0,0xBC,0xF8,0x7C,0xF7,0xB5,
+    0xE8,0x82,0xA7,0x7A,0xEF,0x3F,0xAB,0xEA,0xE8,0x82,0xA7,0x7A,0x2C,0xBF,0xDD,0xFF,
+    0xE8,0x82,0xC7,0x82,0x2B,0xCA,0x5E,0x7B,0xE8,0x82,0xA7,0x7A,0x8A,0xAA,0xFE,0x2D,
+    0xE8,0x82,0xC7,0x82,0xEF,0x2A,0xCB,0xC4,0x08,0x8B,0xC8,0x82,0xAD,0xAD,0x9F,0x56,
+    0x49,0x8B,0xC7,0x82,0x3F,0xFF,0x7D,0x55,0xB3,0xDD,0x08,0x83,0x2F,0x55,0x55,0x55,
+    0x75,0xEE,0x28,0x8B,0x00,0x2F,0x55,0x55,0x96,0xF6,0x08,0x83,0x00,0x00,0x2B,0xD5,
+    0xB6,0xF6,0x8E,0xB4,0x00,0x00,0x00,0x2D,0x95,0xFE,0xD6,0xF6,0x55,0x75,0xFF,0xBA,
+    0xB6,0xF6,0x51,0xC5,0x40,0xC0,0x00,0x00,0x13,0xE6,0x84,0x51,0x57,0x57,0x5E,0x58,
+    0xC5,0x59,0x64,0x49,0xAA,0x8F,0xAA,0xF5,0x85,0x51,0x23,0x41,0x58,0x5C,0xF8,0xAA,
+    0x66,0x7A,0x23,0x49,0x55,0xD5,0xBD,0x2F,0x29,0x93,0x06,0x6A,0xF5,0xED,0xAB,0x8A,
+    0x88,0x82,0x84,0x59,0x78,0x68,0xF0,0xE8,0xA5,0x61,0x03,0x41,0x7F,0x7F,0xBA,0xA0,
+    0xC6,0x59,0xA2,0x30,0xF5,0xD7,0xFE,0xA2,0x24,0x41,0x81,0x28,0x5E,0x5E,0xFA,0x2A,
+    0x64,0x49,0xA1,0x28,0xB5,0xB5,0xAD,0x02,0x67,0x7A,0x43,0x49,0x25,0x2D,0xAD,0xFF,
+    0xA8,0x7A,0xA4,0x59,0xC0,0xFA,0x5F,0xF5,0x88,0x7A,0xE5,0x61,0x0B,0xB5,0x55,0xD5,
+    0xA8,0x7A,0x23,0x49,0x00,0xE0,0xEA,0x72,0x26,0x6A,0x02,0x49,0xBA,0xB7,0xB5,0x25,
+    0xA7,0x7A,0xC5,0x61,0x29,0x2F,0xAE,0xFA,0x09,0x93,0x06,0x72,0xEA,0xEA,0xEB,0x89,
+    0x4A,0x93,0x26,0x72,0x2F,0x3F,0xBD,0xB5,0x18,0xFF,0x6A,0x93,0x03,0x09,0x25,0x25,
+    0x38,0xFF,0x18,0xFF,0xE2,0xA2,0x79,0x5D,0x18,0xFF,0x75,0xEE,0x70,0x70,0x58,0x5C,
+    0x75,0xEE,0x35,0xE6,0x7E,0xEB,0xFA,0xBA,0x18,0xFF,0x96,0xEE,0xA9,0x89,0x89,0x8B,
+    0x39,0xFF,0xF8,0xF6,0xAF,0xA9,0xAF,0xEF,0x18,0xFF,0xF8,0xF6,0xA8,0xAE,0xAA,0xEA,
+    0x18,0xFF,0xF8,0xF6,0xFF,0xDA,0xF6,0x7F,0x17,0xFF,0xF8,0xF6,0x5F,0x56,0x57,0xD5,
+    0xD8,0xFE,0xF7,0xF6,0xDF,0x5D,0x7D,0xDD,0xD7,0xFE,0xF7,0xF6,0xD7,0x7D,0x5E,0xDF,
+    0xF7,0xF6,0xD7,0xF6,0x3F,0x98,0xE0,0x2A,0x18,0xFF,0xF8,0xF6,0xF7,0xDD,0xB5,0xBF,
+    0x18,0xFF,0xF8,0xF6,0xE3,0xAB,0xFE,0xFE,0xD8,0xFE,0xF7,0xF6,0x55,0x6F,0x7D,0xFF,
+    0xF7,0xF6,0xB7,0xF6,0x88,0xE8,0xE8,0xEA,0xD7,0xF6,0x76,0xEE,0xE0,0xF8,0x5E,0xDE,
+    0x96,0xEE,0x76,0xEE,0x67,0x77,0x55,0x57,0x76,0xEE,0x35,0xE6,0xEA,0xFB,0xFE,0xEA,
+    0x75,0xEE,0x34,0xE6,0xA2,0xFE,0xFA,0x82,0xB6,0xF6,0x55,0xE6,0xA5,0x2F,0xAD,0xBD,
+    0xB6,0xF6,0x55,0xEE,0xBC,0xAE,0xBE,0xBF,0xB6,0xF6,0x35,0xE6,0xC2,0xF0,0x62,0xEA,
+    0xD3,0xDD,0x31,0xCD,0xBC,0xF6,0xFE,0x7C,0x34,0xE6,0x72,0xCD,0x0B,0xAB,0xAD,0xA9,
+    0x14,0xE6,0xB3,0xD5,0xBC,0x3E,0x3F,0xB6,0x14,0xE6,0x10,0xC5,0x88,0x88,0x68,0x56,
+    0xD3,0xDD,0xF0,0xC4,0xE0,0x7E,0x55,0x55,0x31,0xC5,0x2D,0xAC,0xB7,0x96,0xDE,0x98,
+    0x11,0xC5,0x6E,0xB4,0xB8,0xF8,0xD8,0x50,0x72,0xCD,0xF0,0xC4,0x2F,0xA9,0xA9,0xBB,
+    0x51,0xCD,0xF0,0xBC,0x60,0x78,0xDC,0x97,0x71,0xD5,0xF0,0xBC,0x2D,0x0F,0x2B,0x2A,
+    0xC8,0x82,0x45,0x72,0x0A,0xAD,0xD7,0xD7,0xE8,0x82,0x45,0x6A,0x0A,0x0A,0xAF,0x5D,
+    0xE8,0x82,0x66,0x72,0xA2,0x02,0x8A,0xAD,0xE8,0x82,0xA7,0x7A,0xF2,0xAE,0xB4,0xAA,
+    0xE8,0x82,0xA7,0x82,0xAE,0xC2,0x42,0xFE,0xE8,0x82,0xC8,0x82,0x5E,0x7F,0xF5,0xD5,
+    0xE8,0x82,0xA7,0x82,0x0B,0x02,0x8B,0x2F,0xC8,0x8A,0xE8,0x82,0xED,0x7D,0x5D,0xEF,
+    0x08,0x8B,0xC8,0x82,0xAF,0xEB,0xF6,0xBB,0x08,0x8B,0xC8,0x82,0x2F,0xBF,0x9D,0xBB,
+    0x2D,0xAC,0xE8,0x8A,0x2D,0x55,0x55,0x55,0x75,0xF6,0x09,0x8B,0x0A,0xF5,0x55,0x55,
+    0xB6,0xF6,0x29,0x8B,0x00,0x0A,0xFD,0x55,0x35,0xEE,0xE5,0x59,0x70,0x70,0x60,0x7F,
+    0x64,0x49,0x02,0x41,0xAE,0x3F,0xB5,0xAF,0xA5,0x59,0x43,0x49,0xBA,0xBF,0xAB,0x3D,
+    0xC8,0x8A,0xA5,0x59,0x2D,0x2D,0x2F,0xBD,0x29,0x9B,0xC8,0x8A,0x40,0x40,0xAA,0x29,
+    0xC9,0x92,0xE5,0x69,0xFA,0x7A,0xD8,0xF8,0x67,0x7A,0xC5,0x61,0xD7,0xBF,0xFF,0xF8,
+    0x67,0x7A,0xA5,0x59,0x7F,0xEA,0x80,0xA2,0x06,0x62,0xE2,0x38,0xFF,0xFA,0x7E,0xF8,
+    0x85,0x51,0x03,0x41,0x02,0xEA,0xB5,0xFF,0x85,0x59,0x23,0x41,0xA8,0x2F,0x25,0x2B,
+    0x47,0x72,0xA4,0x59,0xED,0x0F,0x0B,0x0F,0x88,0x72,0xC5,0x61,0xB5,0xB7,0xAA,0xA0,
+    0x46,0x6A,0xE2,0x38,0x70,0x78,0x7C,0x7E,0x67,0x72,0x02,0x41,0x2D,0x2D,0x29,0xAF,
+    0x67,0x7A,0xC5,0x61,0x80,0xE8,0x5F,0xDF,0x09,0x8B,0x26,0x72,0x09,0x29,0x0B,0x8B,
+    0xC9,0x82,0x67,0x7A,0x2E,0xE0,0xBE,0xF9,0x93,0xDD,0xC8,0x82,0x35,0xB5,0x55,0x55,
+    0xF7,0xFE,0x8B,0x9B,0x00,0x02,0x03,0x2D,0xF7,0xFE,0x55,0xEE,0x5C,0xDC,0x5E,0x56,
+    0x96,0xEE,0x55,0xEE,0xD7,0xDD,0xB7,0x17,0x18,0xFF,0xB7,0xF6,0xA9,0x89,0xAF,0x89,
+    0x39,0xFF,0xF8,0xF6,0xAF,0xE9,0xAF,0xAB,0x18,0xFF,0xF8,0xF6,0xFA,0xFE,0xEA,0x68,
+    0x18,0xFF,0xF8,0xF6,0x77,0xDB,0x57,0x5F,0xD7,0xFE,0xF8,0xF6,0x57,0x5D,0xFF,0xFF,
+    0xF7,0xF6,0xD6,0xF6,0x2E,0xAE,0x22,0x0A,0x18,0xFF,0xF7,0xF6,0x57,0xFB,0xDA,0xFB,
+    0x18,0xFF,0xF7,0xF6,0xEF,0xFF,0x5F,0x55,0x18,0xFF,0xF8,0xF6,0xE7,0xE5,0xDF,0xFF,
+    0x18,0xFF,0xF8,0xF6,0x5F,0x7F,0x5E,0xDF,0xF7,0xF6,0xD7,0xF6,0xAA,0xEA,0xE2,0xF8,
+    0xF8,0xF6,0x96,0xEE,0xE8,0xFA,0x5E,0x7E,0x96,0xEE,0x76,0xEE,0xD8,0x5C,0x5C,0x57,
+    0x76,0xEE,0x56,0xEE,0x72,0x4D,0xF0,0xFA,0x76,0xEE,0x14,0xE6,0xAA,0xA8,0xFA,0x6C,
+    0x76,0xEE,0x14,0xE6,0x0E,0xAB,0x0B,0xA9,0x96,0xEE,0x76,0xEE,0x65,0xF5,0xBF,0xBD,
+    0x96,0xEE,0x76,0xEE,0x5D,0xF7,0xEF,0xFE,0x96,0xEE,0x35,0xE6,0xCA,0xEA,0x60,0xE0,
+    0x14,0xE6,0x72,0xCD,0x76,0xFA,0x88,0x00,0xF4,0xDD,0x72,0xD5,0x09,0x2B,0x0A,0x20,
+    0xF4,0xE5,0x31,0xC5,0xA8,0xA8,0xE8,0x60,0x50,0xCD,0xAF,0xB4,0xF8,0xEE,0x7F,0xD7,
+    0xF0,0xC4,0x6D,0xAC,0x02,0xA8,0xEA,0x5E,0x71,0xCD,0x8E,0xB4,0x7A,0x62,0xE3,0x8B,
+    0x10,0xC5,0x2D,0xA4,0xF0,0x72,0x72,0x62,0x51,0xCD,0xD0,0xBC,0x0B,0x01,0xA9,0x89,
+    0x72,0xCD,0xF0,0xBC,0xB7,0xAF,0x2B,0x0B,0x71,0xCD,0x51,0xCD,0xF7,0xEE,0xBF,0xF8,
+    0xA7,0x7A,0x66,0x72,0xFD,0xF7,0xEE,0xBA,0xA6,0x7A,0x66,0x72,0x75,0x76,0x79,0xEA,
+    0x86,0x72,0x46,0x72,0xA5,0xAE,0x80,0x20,0xC8,0x82,0x25,0x6A,0x0A,0xD7,0xFF,0xFF,
+    0xC8,0x82,0x46,0x72,0x00,0x0A,0x95,0x55,0xE8,0x8A,0x46,0x72,0x0A,0x88,0x8A,0xB5,
+    0xE8,0x82,0xA7,0x7A,0xEA,0x8A,0xEB,0x2D,0xE8,0x82,0xC8,0x82,0xBF,0xFD,0x51,0x55,
+    0xE8,0x82,0xC8,0x82,0xAB,0x62,0x9C,0xCF,0x09,0x8B,0xA7,0x82,0xEA,0xB8,0xFE,0xF6,
+    0xE8,0x8A,0xC8,0x82,0xC0,0xC8,0xEE,0xFB,0x08,0x8B,0xC8,0x82,0xF2,0x0B,0xFF,0x6E,
+    0xC8,0x8A,0x09,0x83,0xDF,0xBB,0xA2,0xA8,0x08,0x8B,0xC5,0x59,0x60,0x68,0x72,0x78,
+    0x84,0x51,0x43,0x49,0xB5,0xF7,0x94,0x55,0xA5,0x59,0x44,0x49,0x3D,0x2F,0x08,0x02,
+    0xA8,0x8A,0xC5,0x61,0xB5,0x35,0x2D,0x2F,0xE9,0x92,0x67,0x82,0x0A,0xA2,0x62,0x78,
+    0xA8,0x8A,0x26,0x72,0xF0,0x78,0x56,0x57,0x67,0x7A,0xE5,0x69,0xF0,0xEA,0xFF,0x77,
+    0x67,0x72,0xA4,0x59,0xEA,0xE0,0xFF,0x57,0x05,0x62,0x44,0x51,0x78,0x7A,0x57,0x57,
+    0x64,0x51,0x03,0x41,0xF7,0xB7,0xEB,0xE8,0xA5,0x59,0x23,0x49,0xFD,0xAF,0x35,0x37,
+    0x67,0x72,0xC5,0x59,0x3D,0xB5,0xA5,0xED,0x88,0x72,0xE5,0x61,0x68,0x70,0x7E,0xF7,
+    0xA4,0x59,0x02,0x41,0x78,0xFA,0xFC,0x3C,0x47,0x72,0x43,0x49,0xF5,0x3D,0x2F,0xAF,
+    0xE9,0x8A,0xE6,0x69,0xD5,0xBD,0x3F,0x2B,0x29,0x93,0x47,0x7A,0x6F,0x7A,0xF8,0x78,
+    0xE9,0x8A,0x47,0x7A,0x2D,0x35,0xF9,0xC1,0x4A,0x93,0x26,0x6A,0xF8,0xFA,0xFF,0x57,
+    0xD3,0xDD,0xC8,0x82,0x2D,0xD5,0xD5,0x55,0x55,0xEE,0x6B,0x9B,0x00,0x02,0x0B,0x0D,
+    0xB6,0xF6,0x55,0xEE,0xB7,0x37,0x15,0xB5,0x18,0xFF,0xD7,0xF6,0xE9,0xEB,0xF9,0xE9,
+    0x38,0xFF,0xF8,0xF6,0xAB,0xAB,0xEB,0xB9,0x18,0xFF,0xF8,0xF6,0xEA,0xF8,0xF8,0xFA,
+    0x18,0xFF,0xD8,0xF6,0xEA,0xFA,0xBE,0xFA,0xF7,0xF6,0xD8,0xF6,0xAA,0xBA,0x2A,0xA2,
+    0xD8,0xFE,0xF7,0xF6,0x5F,0xF7,0x57,0x5F,0x18,0xFF,0xF7,0xF6,0x6D,0xBD,0xAD,0xEB,
+    0x18,0xFF,0xF8,0xF6,0x75,0xFF,0xFB,0xEA,0x17,0xFF,0xF8,0xF6,0xFA,0xAF,0xFF,0x7F,
+    0x18,0xFF,0xB7,0xF6,0xA8,0xEA,0xEE,0x7B,0xD7,0xF6,0x96,0xEE,0x20,0xFE,0x5E,0x5E,
+    0xB7,0xF6,0x55,0xE6,0xE0,0xE8,0xFF,0xFF,0x96,0xEE,0x55,0xE6,0xAF,0xBB,0xEA,0xFA,
+    0x76,0xEE,0x56,0xEE,0xDE,0xBE,0xBA,0x8C,0x76,0xEE,0x35,0xE6,0x7E,0xE8,0xA0,0x82,
+    0x76,0xEE,0x14,0xE6,0x2F,0x3F,0xFE,0xFA,0x96,0xEE,0x35,0xE6,0x02,0x08,0x0A,0x7F,
+    0x96,0xEE,0x55,0xEE,0xBE,0x2A,0x82,0xD5,0x96,0xEE,0x34,0xE6,0xC8,0x48,0x62,0x42,
+    0x34,0xE6,0xF4,0xDD,0xBC,0x5D,0x55,0x5D,0x14,0xE6,0xD3,0xDD,0xBA,0x7F,0xA5,0xAB,
+    0xF4,0xE5,0xAF,0xBC,0xE0,0x60,0x78,0x58,0xCF,0xBC,0x6E,0xB4,0xE8,0x7B,0x7A,0x80,
+    0xAF,0xBC,0x0D,0xA4,0xBA,0xDF,0xDF,0xE8,0x51,0xCD,0xAF,0xBC,0x09,0x2D,0x95,0x55,
+    0x51,0xCD,0x0D,0xAC,0x68,0x60,0xE0,0xDE,0x31,0xCD,0xAF,0xBC,0x81,0x09,0x0B,0xA3,
+    0x92,0xD5,0x31,0xCD,0xA9,0xA9,0xAB,0xA9,0x91,0xD5,0x52,0xCD,0xFA,0xFE,0xEB,0xEA,
+    0xA7,0x7A,0x45,0x6A,0x02,0x8A,0x0A,0x8D,0xA7,0x7A,0x86,0x72,0xD4,0x56,0xFE,0xAD,
+    0x86,0x7A,0xA7,0x72,0xEA,0xEF,0xEB,0xA7,0xC8,0x82,0x66,0x7A,0xFF,0xDF,0x9E,0xAB,
+    0xA7,0x7A,0x66,0x72,0x55,0xFB,0x8B,0xA8,0x87,0x7A,0x66,0x72,0xBD,0xF0,0xC2,0x2C,
+    0xA6,0x7A,0x46,0x72,0x2F,0xF7,0xFE,0xEE,0xE8,0x82,0x45,0x72,0x08,0xAF,0x5D,0xD5,
+    0xE9,0x8A,0x46,0x72,0x02,0x88,0x2B,0xFD,0xE8,0x8A,0x87,0x7A,0xA8,0x82,0xA8,0xAD,
+    0xE8,0x82,0xA7,0x82,0x02,0x8A,0x9D,0xAA,0xE8,0x8A,0xC8,0x82,0xF6,0x2C,0x2F,0x9E,
+    0xE8,0x8A,0xA7,0x7A,0xA2,0x82,0x6A,0xAE,0xE8,0x82,0xA4,0x59,0x78,0x78,0x72,0x68,
+    0x23,0x49,0xE2,0x38,0x08,0xF8,0xFC,0x5C,0x84,0x59,0xC2,0x30,0x02,0x3F,0xB5,0xD5,
+    0xC7,0x8A,0x63,0x51,0x2B,0xAB,0xBF,0xF5,0x09,0x93,0x47,0x7A,0xE2,0x82,0xEA,0x75,
+    0x68,0x7A,0x06,0x72,0xA8,0xBC,0xFF,0x68,0x47,0x72,0x64,0x59,0xFE,0x78,0xFA,0xAB,
+    0xC5,0x61,0x24,0x51,0xF0,0x7B,0xEB,0xE8,0x64,0x51,0x23,0x49,0x2A,0xD5,0xD7,0xF5,
+    0x84,0x51,0x23,0x49,0x5E,0xDE,0x2F,0x7B,0xC5,0x59,0x03,0x41,0x2F,0x0A,0xFA,0xDF,
+    0xE6,0x61,0x43,0x41,0x00,0xBA,0xF5,0x55,0xC5,0x59,0x23,0x41,0x00,0x00,0xCA,0x55,
+    0x47,0x72,0x64,0x51,0xD5,0xF5,0x2D,0x0D,0x88,0x82,0xC5,0x61,0x75,0xB5,0x2E,0x0A,
+    0xC9,0x8A,0x06,0x72,0x0B,0xBE,0xFC,0x78,0xC9,0x8A,0x06,0x6A,0xE0,0xE8,0xBA,0xD5,
+    0x87,0x7A,0x64,0x51,0x02,0x8A,0xE8,0x7E,0xC5,0x61,0x03,0x49,0x20,0x9E,0xB7,0xB7,
+    0x87,0x7A,0x64,0x51,0x0A,0x3F,0xAD,0xAF,0x15,0xEE,0x67,0x72,0x2F,0xBD,0xD5,0x55,
+    0x76,0xEE,0x09,0x8B,0x00,0x02,0xAF,0x55,0xD8,0xFE,0x0D,0xAC,0x00,0x00,0x22,0xF5,
+    0x18,0xFF,0x34,0xE6,0x00,0x02,0x02,0x29,0x18,0xFF,0xF8,0xF6,0xFA,0xFA,0xFA,0xAF,
+    0xF7,0xFE,0xF8,0xF6,0xFF,0xFF,0xEF,0xFF,0xF7,0xF6,0xD8,0xF6,0x2A,0xA8,0xAE,0x2A,
+    0x18,0xFF,0xF7,0xF6,0x57,0xFD,0xF5,0xBF,0xF8,0xFE,0x17,0xF7,0xAA,0xEA,0xBB,0x8E,
+    0x18,0xFF,0xF8,0xF6,0xFE,0xFF,0xEE,0xFE,0x18,0xFF,0xD7,0xF6,0xEA,0xEE,0xFB,0x7A,
+    0x17,0xF7,0xB7,0xF6,0x7F,0xFE,0x5F,0x5D,0xB7,0xF6,0x76,0xEE,0xF8,0x58,0xF8,0xFE,
+    0x75,0xEE,0x35,0xE6,0xAE,0xFE,0xFA,0xF0,0x76,0xEE,0x55,0xEE,0xFE,0xDD,0x1E,0x02,
+    0x76,0xEE,0x55,0xEE,0xF9,0xDC,0x58,0xF8,0x76,0xEE,0x55,0xEE,0xE9,0xAE,0xEE,0xAB,
+    0x75,0xEE,0x35,0xE6,0x6E,0x68,0xE8,0xAA,0x56,0xEE,0x14,0xE6,0x7F,0xFF,0xBE,0xAE,
+    0x96,0xF6,0x35,0xE6,0xB5,0x05,0x3D,0xBF,0x96,0xF6,0xD3,0xDD,0xE0,0x60,0x68,0x7A,
+    0x14,0xE6,0xD3,0xDD,0x0B,0x0D,0x09,0x25,0x14,0xE6,0xD3,0xDD,0x80,0x20,0x5C,0xD8,
+    0xD4,0xDD,0xF0,0xC4,0x58,0x78,0x78,0x7C,0xF0,0xC4,0xAF,0xBC,0xB0,0xFA,0xDA,0xAA,
+    0xF0,0xC4,0x4D,0xAC,0x6A,0x62,0xE0,0x00,0xD0,0xBC,0x6A,0x93,0xA2,0xAA,0xFB,0x5C,
+    0x8E,0xB4,0x4B,0x93,0x28,0x2A,0x3F,0x35,0x31,0xC5,0xF0,0xC4,0xA9,0x8B,0xF9,0x75,
+    0x72,0xD5,0x10,0xC5,0x23,0xAF,0xAD,0xFD,0x72,0xD5,0x31,0xCD,0x00,0xBA,0xAA,0x57,
+    0x45,0x6A,0x05,0x62,0x3A,0xEA,0x7D,0xE6,0x86,0x72,0xE5,0x61,0x02,0xAF,0x6F,0xFE,
+    0xA7,0x7A,0x05,0x62,0x80,0x0A,0xAF,0xD5,0xA7,0x7A,0x46,0x72,0x80,0xA8,0x0A,0x95,
+    0xA7,0x7A,0x86,0x7A,0xF9,0xB9,0xBB,0xAB,0xA7,0x7A,0x66,0x7A,0xBD,0xB8,0xAA,0xB8,
+    0xA7,0x7A,0x46,0x72,0xE8,0xA2,0xA2,0x02,0xA7,0x7A,0x66,0x7A,0x7E,0x3B,0x2A,0x22,
+    0xA7,0x7A,0x66,0x7A,0x77,0x5E,0xB8,0x20,0xA7,0x7A,0x66,0x7A,0xE5,0x5D,0xFF,0xE8,
+    0xE8,0x82,0x45,0x72,0x02,0xBD,0xD7,0xFE,0xE8,0x82,0x66,0x72,0xA2,0x2A,0xB5,0x55,
+    0x08,0x8B,0x87,0x7A,0x2A,0xC8,0xA2,0xBD,0xC7,0x82,0x05,0x62,0x60,0x80,0x00,0x00,
+    0xC7,0x82,0xE2,0x40,0x57,0x57,0x5E,0x78,0xE2,0x38,0xA1,0x38,0xFC,0x5E,0x7A,0xE8,
+    0x64,0x59,0xA2,0x38,0x0B,0xFD,0xBD,0x3D,0x26,0x72,0x23,0x51,0x2F,0x3D,0x2D,0x2F,
+    0x88,0x82,0xE6,0x69,0x6A,0x02,0x00,0x2A,0x88,0x82,0x05,0x6A,0x55,0xFB,0x02,0x96,
+    0xE9,0x8A,0x84,0x51,0x7F,0xEA,0xF0,0xEA,0x27,0x6A,0x02,0x41,0xFF,0x7F,0x58,0x5F,
+    0x44,0x49,0xC2,0x38,0xE0,0x68,0xFE,0xD7,0x44,0x41,0xE2,0x38,0x2B,0xA9,0xED,0x7F,
+    0x44,0x41,0xA2,0x30,0xE0,0x7A,0x5F,0x5F,0xA5,0x59,0x81,0x30,0xFF,0xBD,0xAD,0x2B,
+    0x47,0x72,0x43,0x51,0x0D,0x0D,0xAF,0xBF,0x88,0x7A,0x06,0x6A,0xCA,0xEF,0x8B,0xAD,
+    0x27,0x72,0x84,0x59,0xE0,0xF8,0x68,0x5A,0xE6,0x61,0x84,0x59,0x09,0x6F,0xAD,0xEB,
+    0xC6,0x61,0x23,0x41,0x70,0x72,0x7A,0x7E,0xA5,0x59,0x03,0x41,0xB5,0xB5,0x35,0x35,
+    0x47,0x72,0xC5,0x61,0xE9,0x63,0xFB,0x3A,0xE9,0x8A,0x06,0x72,0x29,0x0D,0xAB,0xEA,
+    0xC8,0x82,0x26,0x72,0xBC,0x5C,0xFE,0x2F,0x8B,0x9B,0x67,0x7A,0x2B,0xBD,0xBD,0xEF,
+    0xF8,0xFE,0xC8,0x82,0x02,0xAB,0xFD,0x55,0xD7,0xFE,0x6A,0x93,0x00,0x02,0xAF,0xD5,
+    0xF7,0xFE,0x72,0xD5,0x00,0x00,0x22,0xFD,0xF8,0xFE,0x56,0xEE,0x08,0x08,0x22,0xBD,
+    0xF8,0xFE,0xD7,0xF6,0x00,0xAA,0xA8,0xFE,0x18,0xFF,0xD7,0xF6,0xAA,0xAA,0xAB,0xFF,
+    0x18,0xFF,0xD8,0xF6,0xAA,0xAF,0xFF,0xEF,0xF8,0xFE,0xB7,0xF6,0x60,0xF2,0xF8,0x5E,
+    0xD7,0xF6,0x76,0xEE,0xA0,0xEC,0xFA,0x7E,0xB6,0xF6,0x55,0xEE,0xAA,0xFA,0xFA,0xF5,
+    0x96,0xF6,0x55,0xEE,0x7A,0x8A,0xAB,0xEF,0x76,0xEE,0x55,0xEE,0xFB,0x7C,0x98,0x0B,
+    0x97,0xF6,0x56,0xEE,0xDE,0x9F,0xE6,0xFA,0x97,0xF6,0x56,0xEE,0x7D,0xFF,0xFA,0xEA,
+    0x76,0xEE,0x55,0xEE,0x36,0xEA,0xBA,0xAE,0x75,0xEE,0x35,0xEE,0xB7,0xAE,0x88,0x0A,
+    0x76,0xEE,0x34,0xE6,0x5A,0x70,0x7A,0x5F,0x55,0xEE,0xB3,0xD5,0xF0,0x68,0x70,0x78,
+    0x14,0xE6,0xB3,0xD5,0x2D,0x2F,0x2B,0xAD,0x75,0xEE,0x14,0xE6,0x7D,0xFF,0xBF,0x2D,
+    0x55,0xEE,0x31,0xCD,0x56,0x7C,0xE0,0x80,0xD3,0xDD,0xD0,0xBC,0x55,0xF7,0xDE,0xE8,
+    0x72,0xCD,0xF0,0xC4,0xFD,0xAF,0x2B,0xAA,0x31,0xCD,0x09,0x83,0x70,0x70,0xC0,0x80,
+    0xAF,0xB4,0xA8,0x7A,0x2D,0x2D,0x35,0xF7,0xF0,0xC4,0x0C,0xA4,0x00,0x0A,0xAA,0xB5,
+    0x31,0xCD,0xAF,0xBC,0x0A,0xAB,0x37,0xF5,0x31,0xCD,0xCF,0xBC,0x00,0xEA,0xEB,0xDF,
+    0x46,0x72,0x26,0x6A,0xED,0xDE,0x18,0x88,0x46,0x72,0x26,0x6A,0xE5,0x6B,0x08,0x22,
+    0x46,0x72,0x05,0x6A,0xBF,0xAA,0xFE,0xDA,0x46,0x72,0x05,0x6A,0xFF,0x6E,0xD7,0xBA,
+    0xA7,0x7A,0x05,0x6A,0x2F,0x7D,0xDF,0xFF,0xA7,0x7A,0x26,0x6A,0x00,0x2B,0xD7,0x55,
+    0xA7,0x82,0x25,0x6A,0x08,0xA0,0x2A,0x95,0xA7,0x7A,0x87,0x7A,0xAF,0xFA,0xFF,0xA5,
+    0xA7,0x7A,0x87,0x7A,0x8B,0x0F,0x2D,0xFC,0xC7,0x82,0x66,0x72,0x7F,0xFF,0x3A,0xF8,
+    0xA7,0x82,0x87,0x7A,0xFF,0xBD,0xFF,0x0C,0xA7,0x82,0x66,0x7A,0xE6,0xFA,0xAA,0x08,
+    0xC7,0x82,0x66,0x72,0xD5,0xBB,0xFE,0x8B,0xC8,0x82,0x66,0x72,0x0B,0xF7,0xFF,0xAA,
+    0xC7,0x82,0x84,0x59,0x70,0xC2,0xA2,0x28,0x46,0x72,0xE3,0x40,0x55,0x57,0xFC,0xE8,
+    0x64,0x59,0xE2,0x40,0xAD,0x2D,0x8E,0x88,0xA5,0x61,0x03,0x49,0x2F,0x57,0x5F,0x5F,
+    0x27,0x72,0xE3,0x48,0x0A,0xAF,0xF5,0xF5,0x67,0x7A,0x44,0x51,0x00,0xAA,0xFD,0x5D,
+    0x47,0x7A,0xE3,0x40,0xA0,0xFA,0xFF,0x7F,0x44,0x51,0xA2,0x30,0xE0,0xBA,0xFE,0xD7,
+    0x44,0x41,0xC2,0x38,0xF7,0xEF,0xBB,0x2A,0x44,0x41,0xE3,0x38,0x7F,0xEF,0xEA,0x83,
+    0x23,0x41,0xA2,0x30,0xDE,0xDE,0xBE,0x2A,0xA5,0x59,0x03,0x41,0x2D,0x0D,0x2D,0x03,
+    0x06,0x72,0x84,0x59,0x35,0xFD,0xCA,0xA2,0x06,0x6A,0xA4,0x61,0x2A,0xFD,0xD5,0xDE,
+    0xE5,0x69,0x24,0x49,0xB8,0xFA,0xFE,0x5E,0xE5,0x61,0x23,0x49,0x8B,0x2A,0xAF,0xB5,
+    0x84,0x51,0x03,0x41,0xF8,0xF8,0xD6,0xF6,0xC6,0x59,0x02,0x41,0x2D,0x2D,0xAA,0xE3,
+    0x88,0x7A,0x44,0x51,0x2A,0x0B,0x2F,0xB5,0x88,0x82,0xE5,0x69,0x4A,0xF8,0x58,0xA0,
+    0xC9,0x8A,0x05,0x6A,0x2D,0x2F,0xBF,0xEF,0x0A,0x93,0x67,0x7A,0xA0,0xE2,0x7F,0x5D,
+    0x88,0x7A,0x26,0x72,0x26,0x3D,0xBD,0x01,0x2A,0x93,0x26,0x72,0x3E,0xB7,0xD7,0xFF,
+    0xEC,0xA3,0x88,0x7A,0xF8,0x57,0x55,0x55,0xD3,0xDD,0x68,0x7A,0x0B,0xFD,0xD5,0x55,
+    0x34,0xE6,0x88,0x7A,0x00,0xBF,0xD5,0x55,0x96,0xF6,0xA8,0x7A,0x00,0x02,0xFF,0x55,
+    0xB7,0xF6,0x6A,0x93,0x00,0x00,0x03,0xBD,0xD7,0xF6,0x35,0xE6,0x88,0xA8,0xAA,0xFD,
+    0x96,0xEE,0x55,0xEE,0xC0,0xE8,0xAE,0xFF,0x96,0xF6,0x35,0xE6,0xAE,0x8A,0x7E,0xD7,
+    0x76,0xEE,0x34,0xE6,0x28,0xAE,0xBF,0x55,0x76,0xEE,0x35,0xEE,0x00,0x00,0xA0,0xFB,
+    0x97,0xF6,0x35,0xE6,0xAA,0xA2,0xAA,0xD5,0x96,0xF6,0x35,0xE6,0x22,0x02,0xF8,0xDF,
+    0x76,0xEE,0x55,0xEE,0xD4,0x57,0xE5,0x25,0x96,0xF6,0x55,0xEE,0xD5,0xFD,0xEB,0x2A,
+    0x76,0xEE,0x35,0xE6,0xFB,0xF8,0x70,0x70,0x35,0xEE,0x92,0xD5,0x70,0x78,0x78,0x70,
+    0x15,0xE6,0x92,0xD5,0x25,0x3D,0xAD,0xA9,0x35,0xE6,0xF4,0xE5,0x0A,0xDF,0x85,0x0D,
+    0x96,0xEE,0x35,0xE6,0xED,0x89,0x29,0x2B,0x76,0xEE,0x92,0xD5,0x6A,0x00,0x00,0x00,
+    0x75,0xEE,0x51,0xCD,0x55,0x57,0xFC,0xF0,0xB2,0xD5,0x10,0xC5,0x7B,0xEF,0xAE,0xA8,
+    0x72,0xCD,0x47,0x6A,0x57,0x5C,0x78,0xF0,0x0D,0xA4,0x06,0x62,0x0B,0xB5,0xD5,0x5F,
+    0xAF,0xBC,0x88,0x72,0x00,0x22,0xAD,0x55,0xCF,0xBC,0x2B,0x8B,0x00,0x02,0x0B,0x0D,
+    0x66,0x72,0x26,0x6A,0xBA,0x7E,0x8C,0x0C,0x46,0x72,0x25,0x6A,0x20,0x08,0x00,0x30,
+    0x66,0x72,0x26,0x6A,0x7F,0xB1,0xBB,0x2A,0x66,0x72,0x25,0x6A,0xFD,0xEE,0xFE,0x3C,
+    0x66,0x72,0x25,0x6A,0x6F,0xAE,0xAF,0x1F,0x46,0x72,0x26,0x6A,0xB9,0x29,0x3B,0x00,
+    0x46,0x72,0x26,0x6A,0x95,0xCC,0xAB,0x80,0x87,0x7A,0x25,0x6A,0x29,0xDF,0x7D,0x7D,
+    0xA7,0x7A,0x25,0x6A,0x20,0x2D,0xD5,0x57,0xC7,0x82,0x25,0x6A,0xAA,0xA8,0x2F,0xFD,
+    0xA7,0x82,0x67,0x7A,0xA8,0x80,0xA8,0xBD,0xA7,0x82,0x87,0x7A,0x28,0xE0,0x8A,0xC8,
+    0xC7,0x8A,0xA7,0x7A,0x55,0x7D,0xFD,0xEF,0xC7,0x82,0x86,0x7A,0xAE,0xA9,0x82,0xA2,
+    0xC8,0x82,0x86,0x7A,0x7F,0xBB,0xBB,0x3E,0xC8,0x82,0x64,0x59,0x7A,0x68,0xA8,0x20,
+    0xC8,0x8A,0x64,0x59,0x55,0xDD,0xFA,0xA0,0x67,0x72,0x44,0x59,0x55,0xFF,0xFA,0xE0,
+    0xA5,0x59,0x24,0x49,0xBF,0xE8,0xF8,0x5E,0x85,0x51,0xE2,0x38,0xA0,0xAA,0xFE,0x5E,
+    0x64,0x51,0xC2,0x30,0x68,0x5A,0x5F,0x7D,0x03,0x39,0xA2,0x30,0xB5,0xEF,0xAF,0x03,
+    0x44,0x41,0xC2,0x30,0x83,0xAA,0x7E,0x7A,0x44,0x49,0xC2,0x38,0xAE,0xBF,0xBD,0x3D,
+    0x64,0x51,0x03,0x41,0x35,0x8F,0xC8,0xA0,0xA5,0x59,0x23,0x49,0x0F,0x3D,0xBD,0xAF,
+    0x47,0x7A,0xA5,0x59,0xB2,0x2B,0x29,0xA5,0x67,0x7A,0x44,0x51,0xFA,0x68,0x70,0x7A,
+    0xA5,0x59,0xC2,0x38,0xB8,0xFA,0xF7,0xD7,0xA5,0x59,0x23,0x41,0xFB,0x6B,0xE9,0x09,
+    0xA5,0x51,0x03,0x41,0xDE,0xFF,0xB5,0xFC,0xA5,0x51,0x23,0x49,0xEB,0xBB,0xE8,0x5F,
+    0x68,0x7A,0x03,0x41,0x2F,0xAD,0x2D,0x25,0x4B,0x93,0xA7,0x82,0xA9,0x8D,0xAE,0x5D,
+    0xE9,0x8A,0xA5,0x59,0xFA,0xF8,0x7E,0x5E,0x67,0x7A,0xE6,0x61,0x2B,0x2B,0xAF,0xBD,
+    0xC9,0x8A,0x27,0x72,0x2F,0xAA,0xBF,0x35,0x09,0x93,0xA8,0x82,0x5F,0x7A,0x2E,0xBF,
+    0xE9,0x8A,0x47,0x7A,0x55,0x5F,0xF8,0xE8,0x67,0x7A,0xE5,0x69,0x7F,0xAA,0x8A,0xF8,
+    0x87,0x7A,0xE5,0x69,0xAD,0xAB,0x02,0xAB,0x87,0x72,0x26,0x6A,0x78,0xEA,0xDF,0x5A,
+    0x4E,0xAC,0x47,0x6A,0x25,0xD5,0x55,0x55,0x55,0xEE,0x88,0x72,0x02,0x03,0xF5,0x55,
+    0x35,0xE6,0x6A,0x93,0x00,0x00,0x0A,0xB5,0x55,0xEE,0xD3,0xDD,0xA8,0xA2,0xAA,0xA9,
+    0x34,0xE6,0xF4,0xE5,0xA0,0xA8,0xFA,0xDE,0x35,0xE6,0xF4,0xE5,0x02,0x8E,0x2F,0xDD,
+    0x34,0xE6,0xF4,0xDD,0xFE,0x57,0xFC,0xEF,0x35,0xE6,0xD3,0xDD,0x2F,0x29,0xBB,0xAF,
+    0x96,0xF6,0x34,0xE6,0xAD,0xAF,0x37,0xB5,0x96,0xF6,0x35,0xE6,0x82,0xA8,0x72,0x5F,
+    0x55,0xEE,0x35,0xE6,0xC0,0x2A,0xAD,0xF5,0x35,0xE6,0x72,0xD5,0x78,0xA0,0x00,0x00,
+    0x35,0xEE,0x92,0xD5,0xB5,0xBD,0xA8,0x80,0x34,0xE6,0xF4,0xDD,0x0B,0xBA,0xDF,0xDB,
+    0x96,0xEE,0x14,0xE6,0x8B,0x0B,0x0F,0x2D,0x96,0xEE,0x76,0xEE,0xE8,0xF8,0x8A,0xA8,
+    0x76,0xEE,0xD3,0xDD,0x70,0xC0,0x00,0x00,0x55,0xEE,0x72,0xD5,0x7F,0x7F,0x7A,0xE0,
+    0xF3,0xDD,0xF1,0xC4,0x62,0x0A,0x0A,0x0A,0xB3,0xDD,0xE9,0x82,0x57,0xE0,0x00,0x00,
+    0x72,0xD5,0x67,0x72,0x55,0xFF,0xA8,0x80,0xCF,0xBC,0xE9,0x82,0x09,0x03,0x02,0x28,
+    0x66,0x72,0x46,0x72,0x25,0xD6,0x9C,0xBE,0x66,0x72,0x25,0x72,0xAE,0x89,0xA8,0xA0,
+    0x67,0x72,0x46,0x72,0xD9,0xA3,0x66,0xB6,0x66,0x7A,0x46,0x72,0xAF,0xCF,0x7C,0xB2,
+    0x66,0x72,0x46,0x72,0xFE,0xF4,0xBD,0x5D,0x66,0x72,0x46,0x72,0x5E,0x16,0xF8,0xF3,
+    0x67,0x7A,0x26,0x72,0x7F,0x8F,0x2D,0xA8,0x66,0x7A,0x26,0x6A,0xDF,0xEF,0xA8,0xC3,
+    0x66,0x72,0x25,0x72,0xE2,0xAB,0xEA,0xEE,0x66,0x72,0x25,0x6A,0x6F,0xDF,0x9A,0xBA,
+    0x66,0x72,0x25,0x6A,0x2F,0x7F,0x67,0xA8,0xC7,0x82,0x26,0x6A,0x8A,0xAD,0x7D,0xFF,
+    0xC8,0x8A,0x46,0x72,0xAA,0x8A,0x9D,0xD5,0xC7,0x82,0x66,0x7A,0x22,0x0A,0xAA,0xB5,
+    0xC7,0x82,0xA7,0x82,0x09,0x02,0x0A,0x07,0xE8,0x8A,0x87,0x7A,0x7A,0xEA,0x00,0x0A,
+    0x09,0x93,0x46,0x72,0x7A,0xEB,0xE8,0x68,0x87,0x7A,0x23,0x49,0xE0,0xF8,0xFA,0x7E,
+    0x65,0x51,0xC2,0x30,0x88,0xFA,0x5E,0x57,0x23,0x41,0x81,0x28,0xF8,0xDF,0xDF,0xD5,
+    0xE3,0x30,0xA2,0x28,0x02,0xAA,0xAF,0xBF,0x03,0x39,0xA2,0x28,0xA2,0xA2,0xEA,0xDE,
+    0xE3,0x30,0xA2,0x30,0x00,0xAA,0xFA,0xFF,0x84,0x51,0xC2,0x30,0xB7,0xBF,0x25,0x0D,
+    0x84,0x51,0xE3,0x40,0xE0,0xAE,0xB6,0xD7,0xA5,0x59,0x44,0x51,0xF5,0x2F,0x2F,0xFB,
+    0x27,0x72,0x85,0x59,0x35,0x35,0xA7,0xA5,0xE6,0x61,0x03,0x41,0xF8,0xF8,0x7A,0x7C,
+    0x44,0x49,0xC3,0x38,0xEE,0x7A,0x7C,0xBA,0xC6,0x59,0xE3,0x38,0x2D,0x0D,0x0B,0xAB,
+    0xC6,0x59,0x44,0x49,0xF0,0x5C,0x70,0x7A,0x44,0x49,0xE3,0x38,0xE8,0xFE,0x76,0xAE,
+    0xA5,0x59,0xE3,0x38,0x25,0xB5,0xFD,0xFB,0x67,0x72,0x44,0x49,0x82,0xFA,0x7F,0x75,
+    0xE5,0x61,0x44,0x49,0xE0,0xBF,0xF5,0x55,0xE6,0x61,0x43,0x51,0x2B,0xBF,0xBF,0xB5,
+    0x67,0x7A,0x84,0x59,0x0B,0x2D,0x2F,0x3F,0xE9,0x8A,0x06,0x72,0x2A,0xBE,0xDA,0x5F,
+    0xE9,0x92,0x67,0x7A,0x78,0xEF,0xAD,0xE9,0xC9,0x8A,0x27,0x72,0x5E,0xF0,0xC0,0x88,
+    0x87,0x7A,0xC4,0x61,0xAB,0x7F,0xFA,0xA8,0x47,0x72,0x84,0x59,0x00,0x0B,0xFF,0x5E,
+    0x26,0x6A,0x84,0x51,0x80,0xA0,0xFB,0x55,0x67,0x72,0xA5,0x59,0x2A,0xFD,0xF5,0xD5,
+    0x0C,0xA4,0x26,0x6A,0x2F,0xBD,0xD5,0x55,0x34,0xEE,0x0A,0x8B,0x02,0x0A,0x2D,0xD5,
+    0x35,0xEE,0x31,0xCD,0xA0,0xA8,0x22,0xAD,0x14,0xE6,0xB3,0xDD,0xEA,0x6B,0xA2,0x88,
+    0x14,0xE6,0xB3,0xDD,0xCA,0xAF,0xFA,0x6A,0xF4,0xE5,0xD3,0xDD,0x2E,0x9F,0x97,0xD5,
+    0x55,0xE6,0xF4,0xDD,0x0B,0xAB,0xAF,0xEF,0x34,0xE6,0xF4,0xDD,0x80,0x2A,0xAF,0xD5,
+    0x55,0xEE,0x14,0xE6,0xAA,0xAF,0xAF,0xCD,0x34,0xE6,0xF4,0xDD,0xD6,0x5E,0x7A,0x67,
+    0x34,0xE6,0xF4,0xDD,0xBF,0xAF,0xB5,0xFD,0x14,0xE6,0xF4,0xDD,0x20,0x28,0x82,0x02,
+    0x96,0xEE,0x14,0xE6,0x2F,0x0D,0x2D,0x25,0x76,0xFE,0x96,0xEE,0x77,0xDD,0x75,0x5D,
+    0x96,0xEE,0x76,0xEE,0xF8,0xC2,0x8A,0xA0,0x96,0xEE,0x35,0xE6,0x7A,0x88,0xA2,0xE2,
+    0x76,0xEE,0x93,0xD5,0xD7,0xF8,0xE0,0xFA,0x15,0xE6,0xB3,0xD5,0xAA,0x8B,0xAF,0xD7,
+    0xF4,0xDD,0x92,0xD5,0x7A,0x80,0x0A,0xAA,0xD3,0xDD,0xCC,0x9B,0x5A,0xE0,0x80,0x00,
+    0x66,0x72,0x45,0x72,0xC3,0x2B,0x02,0x83,0x66,0x7A,0x46,0x72,0xBA,0xB4,0xFD,0x42,
+    0x87,0x7A,0x46,0x72,0xEA,0xBA,0xDB,0x7F,0x87,0x7A,0x46,0x72,0xFD,0xED,0xBA,0xBB,
+    0x66,0x72,0x25,0x72,0x1A,0xAA,0x88,0x82,0x87,0x7A,0x46,0x72,0xF5,0xFE,0xB3,0xEA,
+    0x86,0x7A,0x46,0x72,0x7D,0xFD,0xEE,0xFC,0x87,0x7A,0x25,0x6A,0xEF,0xAF,0xAA,0x88,
+    0x66,0x7A,0x46,0x72,0x79,0xB8,0x76,0xC2,0x66,0x7A,0x46,0x72,0xEC,0x4C,0x6C,0xC4,
+    0x66,0x7A,0x46,0x72,0x17,0x72,0x8F,0xC6,0x87,0x7A,0x46,0x72,0x77,0x7D,0xBE,0xEA,
+    0x87,0x7A,0x46,0x72,0x5F,0x7D,0xB5,0x8A,0x87,0x7A,0x25,0x72,0xFD,0xAF,0xEB,0x8A,
+    0xA7,0x82,0x46,0x72,0x0A,0xBF,0x7D,0x6F,0xE8,0x8A,0x46,0x72,0x0A,0x0F,0xB7,0x1F,
+    0x09,0x8B,0xE5,0x69,0x70,0x70,0x78,0x78,0xA4,0x59,0xC2,0x38,0xF8,0x5E,0x7C,0x78,
+    0xC2,0x30,0x82,0x28,0x60,0xF0,0xC8,0xC0,0xE2,0x30,0x82,0x20,0xD5,0x7F,0xBF,0xAE,
+    0xC2,0x28,0xA2,0x28,0xFF,0xFF,0x52,0x3A,0xC2,0x30,0xA2,0x28,0x0A,0xA3,0x7B,0x5C,
+    0x03,0x39,0xA2,0x28,0x97,0xBD,0x25,0x2D,0x65,0x49,0xE2,0x38,0xCD,0xFB,0x62,0x62,
+    0x24,0x41,0xC2,0x38,0x3F,0x27,0xB7,0x2F,0x64,0x51,0x03,0x41,0xA0,0x0F,0x01,0x83,
+    0xC5,0x59,0x23,0x49,0x2D,0xFF,0x7A,0x6A,0x85,0x51,0xE3,0x38,0x78,0x5A,0xFB,0xFE,
+    0x24,0x41,0xE2,0x38,0x32,0xF5,0xB5,0xAA,0x65,0x49,0xE3,0x38,0xA2,0xA3,0xFF,0x55,
+    0x64,0x49,0x03,0x41,0xF3,0x5F,0xDD,0x39,0x64,0x49,0xE3,0x38,0xBE,0xFF,0x7A,0x60,
+    0x24,0x49,0xA2,0x30,0x00,0xAB,0xB7,0xA7,0xC5,0x59,0x44,0x49,0xED,0xAD,0xAB,0x09,
+    0x84,0x51,0x02,0x41,0xEA,0xE8,0x7A,0x7C,0x85,0x51,0xE2,0x38,0x2F,0x2F,0xBF,0xAD,
+    0x26,0x72,0x85,0x59,0x95,0xD5,0xAB,0x03,0x06,0x6A,0xC5,0x69,0x2B,0x8D,0xE2,0x60,
+    0xA8,0x82,0xC5,0x61,0x02,0x82,0xFD,0x55,0xA8,0x82,0xC5,0x69,0x08,0x8A,0xAF,0xAD,
+    0x88,0x7A,0xA5,0x61,0xE8,0xFE,0xFA,0x7E,0x06,0x6A,0x43,0x51,0xFE,0xA8,0x80,0x82,
+    0xC6,0x59,0x64,0x51,0xBD,0xAA,0x80,0x68,0xE6,0x61,0x85,0x51,0xAA,0xBA,0xF0,0xFD,
+    0x06,0x6A,0x84,0x51,0x2A,0x2F,0x35,0xB5,0x4B,0x93,0xE5,0x61,0x2B,0xAF,0xBD,0xD5,
+    0x72,0xD5,0xA8,0x82,0x2F,0xB5,0xD5,0x55,0xF4,0xE5,0xCC,0xA3,0x00,0x02,0x0B,0x29,
+    0xF4,0xE5,0xB3,0xDD,0xF0,0xD0,0x78,0xBB,0xD3,0xDD,0x72,0xD5,0x20,0x28,0xA0,0x78,
+    0x14,0xE6,0x93,0xD5,0x82,0x2A,0xAF,0xB5,0x35,0xE6,0xD3,0xDD,0xDF,0xB7,0x37,0x2F,
+    0x55,0xEE,0xB3,0xDD,0x82,0x80,0xA8,0x7A,0x35,0xE6,0xD3,0xDD,0xF7,0xBE,0x00,0x03,
+    0x35,0xE6,0xF4,0xDD,0xB5,0xFE,0xBE,0xC0,0x35,0xE6,0xD3,0xDD,0x7A,0xFA,0x8A,0x20,
+    0x96,0xEE,0xF4,0xDD,0x2D,0x25,0x2F,0x2F,0xB7,0xF6,0x96,0xEE,0xF7,0xFF,0x5F,0xDF,
+    0x96,0xEE,0x76,0xEE,0xF0,0xF0,0xE8,0xA0,0x75,0xEE,0xB3,0xD5,0xE8,0x7C,0x78,0x60,
+    0xD3,0xDD,0x92,0xD5,0xA8,0x7E,0xEF,0x6A,0xB3,0xD5,0x52,0xD5,0x02,0xA2,0xEA,0xAA,
+    0xB3,0xD5,0x72,0xD5,0x00,0x8A,0xFF,0x5F,0x92,0xD5,0x51,0xCD,0x00,0xAC,0x7E,0xB7,
+    0x67,0x7A,0xE5,0x69,0x80,0x22,0x22,0x3D,0x67,0x7A,0x47,0x72,0xE8,0x22,0x3F,0x4D,
+    0x87,0x7A,0x46,0x72,0xEF,0xA7,0xBF,0xDF,0x47,0x7A,0x66,0x72,0x7D,0xF7,0x56,0x77,
+    0x87,0x82,0x66,0x72,0x5D,0x5D,0xD7,0xDA,0x87,0x7A,0x46,0x72,0xEA,0xAF,0x3E,0xFE,
+    0x86,0x7A,0x66,0x72,0x7E,0xED,0xCB,0xA1,0x86,0x7A,0x46,0x72,0xBD,0xAA,0xAA,0x2A,
+    0x86,0x7A,0x66,0x72,0x7D,0x79,0xF0,0xB4,0x87,0x7A,0x46,0x72,0xEA,0xF0,0xEA,0xF8,
+    0x87,0x7A,0x46,0x72,0xFB,0xFE,0xB2,0x2B,0x87,0x7A,0x46,0x72,0xAE,0xCE,0xBE,0xBE,
+    0xA7,0x82,0x46,0x72,0xFE,0xBF,0x9F,0x2A,0xA7,0x82,0x66,0x7A,0x75,0x57,0xBF,0xFF,
+    0x87,0x7A,0x45,0x7A,0xAF,0x2B,0x20,0xA0,0xEC,0xAB,0x87,0x7A,0x95,0xB5,0x2D,0x0D,
+    0xCB,0xA3,0xE5,0x69,0x7E,0x7C,0x78,0x78,0xA5,0x59,0xE2,0x38,0x5C,0x58,0x58,0xF8,
+    0xE3,0x38,0xA2,0x28,0x7D,0x5B,0xFE,0xF8,0xE3,0x30,0xA2,0x28,0xBF,0x8B,0xAA,0xFD,
+    0xE3,0x30,0xA2,0x28,0xBE,0xF8,0xF8,0xFE,0xE2,0x30,0x81,0x28,0xFA,0xFF,0x3E,0x2D,
+    0x44,0x41,0xA2,0x28,0xBD,0x2F,0x2B,0x02,0x85,0x49,0xE3,0x38,0x63,0x7E,0x5F,0x57,
+    0x85,0x51,0xE3,0x38,0x25,0x2D,0x0F,0xAD,0x85,0x51,0xE2,0x38,0xAA,0xB8,0xF8,0x7A,
+    0x85,0x51,0xE2,0x38,0x80,0xFA,0x55,0x55,0x24,0x39,0xC2,0x38,0xBE,0xD4,0xBB,0x5F,
+    0x44,0x41,0xE3,0x38,0x0B,0xCF,0xD5,0x5F,0x44,0x49,0xE2,0x38,0x5C,0xDA,0xE9,0x97,
+    0x85,0x49,0x03,0x41,0x3D,0xB5,0xDF,0x5F,0x85,0x51,0xE3,0x38,0x58,0xFE,0xAA,0xAA,
+    0x45,0x49,0xC3,0x38,0xF5,0xFF,0xEE,0x08,0xA5,0x51,0x03,0x39,0x29,0xBD,0xFD,0xBE,
+    0x85,0x51,0x03,0x41,0x78,0xFA,0xFA,0xAA,0xE5,0x61,0x03,0x41,0xBD,0xAD,0x2F,0x2B,
+    0x47,0x72,0xA4,0x59,0x0D,0xBF,0xFB,0x7F,0x26,0x6A,0x64,0x51,0xF8,0x7C,0x7F,0xF5,
+    0xC6,0x61,0x43,0x51,0x8A,0xAD,0x85,0x2E,0x06,0x6A,0x85,0x59,0xAF,0xCD,0x8F,0x02,
+    0xE6,0x69,0x64,0x51,0xC0,0xE2,0xF7,0xDD,0xA5,0x59,0x44,0x49,0x0B,0x77,0xDF,0xFB,
+    0xA5,0x59,0x44,0x49,0xF2,0x7F,0xFD,0x55,0xC6,0x59,0x44,0x49,0xBD,0x35,0x35,0xBB,
+    0xE6,0x59,0x85,0x59,0xF6,0xC0,0x80,0xB2,0xE6,0x61,0xA5,0x59,0xE2,0xF5,0xDF,0xF9,
+    0xC9,0x82,0xA5,0x59,0x2B,0xAD,0xB7,0xAF,0x10,0xCD,0xA8,0x82,0x0B,0x2D,0xBD,0xF5,
+    0xD3,0xDD,0x4E,0xB4,0x00,0x00,0x03,0x2D,0xB3,0xDD,0x72,0xD5,0xDC,0x57,0x96,0xFE,
+    0xF4,0xDD,0x72,0xD5,0x2D,0xAB,0x2B,0x2B,0x35,0xE6,0xD3,0xDD,0x8B,0x7A,0x55,0xBF,
+    0xF4,0xDD,0x10,0xC5,0xA0,0xE0,0xE0,0x70,0x14,0xE6,0x10,0xC5,0x02,0x02,0x0B,0x2D,
+    0x76,0xEE,0x14,0xE6,0xE9,0x2A,0xAA,0xFA,0x55,0xEE,0x14,0xE6,0xEA,0xF8,0xFE,0x7F,
+    0xB7,0xF6,0x14,0xE6,0xBD,0x25,0x25,0x2D,0xB7,0xF6,0x76,0xEE,0xF8,0xBA,0xFA,0x5E,
+    0x96,0xEE,0x55,0xEE,0x20,0xCA,0xBA,0xFD,0x76,0xEE,0xF4,0xDD,0x60,0x80,0xA0,0xA2,
+    0x55,0xEE,0xB3,0xD5,0x57,0x5F,0x78,0x78,0xB2,0xD5,0x73,0xCD,0xBA,0xFE,0xEA,0x32,
+    0x92,0xD5,0x72,0xCD,0xF8,0xEC,0x68,0xFA,0x92,0xD5,0x31,0xC5,0xFF,0xFE,0x7A,0x72,
+    0xC4,0x61,0x42,0x59,0x3F,0xFF,0xBF,0xFF,0x66,0x72,0x64,0x59,0x0A,0xBD,0xD5,0x55,
+    0x86,0x7A,0x44,0x59,0x82,0x22,0xAF,0xF5,0x87,0x7A,0xC4,0x61,0x0A,0x80,0xAA,0xAD,
+    0x86,0x7A,0x26,0x72,0x28,0xAA,0xAA,0xA9,0x87,0x7A,0x25,0x72,0xAA,0xA2,0xAA,0x8B,
+    0x87,0x7A,0x66,0x72,0xA1,0x0D,0xBB,0x63,0x86,0x7A,0x66,0x72,0x27,0xC0,0xB8,0x2C,
+    0x87,0x7A,0x66,0x72,0xBB,0x28,0x02,0xAC,0x86,0x7A,0x46,0x72,0xB8,0xC0,0x08,0xB8,
+    0x87,0x7A,0x25,0x7A,0xA2,0xA2,0xC2,0x22,0xA7,0x7A,0x46,0x7A,0x7A,0xBF,0xBB,0x2E,
+    0x87,0x7A,0x66,0x7A,0x32,0x08,0xB0,0xD3,0xA7,0x82,0x66,0x7A,0x67,0xBE,0xBF,0xAE,
+    0x6A,0x9B,0x87,0x7A,0x55,0xD5,0xD5,0x15,0x2E,0xB4,0x08,0x8B,0x2D,0x89,0x83,0x22,
+    0x8A,0x9B,0x05,0x6A,0x78,0x58,0x5C,0x7C,0xE6,0x61,0x02,0x41,0xFA,0x78,0x78,0x78,
+    0x23,0x41,0xA2,0x28,0x78,0x7A,0xFA,0x6A,0xC2,0x30,0xA2,0x28,0x9B,0x3E,0x57,0x7D,
+    0xC2,0x28,0x81,0x28,0xF8,0xEA,0xB6,0xBB,0xE3,0x38,0x82,0x28,0x37,0xAF,0xAF,0xAF,
+    0x24,0x41,0xA2,0x30,0x80,0xAA,0xFF,0xD7,0x44,0x41,0xC2,0x30,0xF7,0xFD,0x8B,0xC9,
+    0x24,0x41,0xC2,0x38,0x2B,0xA9,0xEF,0x2B,0x44,0x49,0xC2,0x38,0x68,0xFE,0xF7,0xBE,
+    0x24,0x41,0xC2,0x30,0xE5,0xB7,0xA7,0x0C,0x04,0x41,0xA2,0x30,0xF8,0xC0,0x00,0xA8,
+    0xE3,0x30,0x82,0x30,0xA3,0xEF,0xDF,0xBE,0x23,0x41,0xC2,0x38,0x2B,0x29,0xAB,0x2A,
+    0x44,0x41,0x03,0x41,0xEB,0x72,0x82,0x0A,0x44,0x49,0xE3,0x38,0x0A,0x83,0xAE,0x7F,
+    0x86,0x49,0x03,0x41,0xAF,0x27,0x2D,0xFD,0x85,0x51,0x03,0x41,0xE0,0xF8,0xDC,0x5F,
+    0x85,0x51,0x24,0x41,0x8D,0xEF,0xEB,0x7F,0x06,0x62,0x04,0x41,0x2F,0x3F,0xB5,0xF5,
+    0xE5,0x61,0x44,0x49,0xE8,0xEE,0xDF,0x57,0xA5,0x59,0x23,0x49,0x0A,0x28,0xBF,0x95,
+    0xE6,0x61,0x85,0x59,0x3F,0xBA,0xAA,0x7F,0x27,0x72,0xA5,0x59,0xE0,0x8B,0xAF,0xDD,
+    0xE6,0x61,0x03,0x41,0xFE,0x5E,0xF8,0xA2,0x85,0x51,0x23,0x49,0x88,0x83,0x35,0xFE,
+    0x64,0x49,0x44,0x49,0xA8,0x81,0x83,0x3D,0xC6,0x59,0x64,0x49,0xF9,0xE2,0x01,0x5F,
+    0xA5,0x59,0x44,0x49,0x88,0xFA,0x9A,0x5E,0xE5,0x61,0x43,0x49,0x83,0xAD,0xFF,0xED,
+    0x67,0x72,0xC5,0x59,0x09,0x0B,0x2D,0x25,0x29,0x8B,0x87,0x7A,0x2B,0xAF,0xFD,0xFD,
+    0x11,0xCD,0xC8,0x82,0x0B,0x25,0xBD,0xD5,0x14,0xE6,0xD0,0xC4,0xAA,0xA2,0x0A,0x09,
+    0x56,0xEE,0xB3,0xD5,0xAD,0xAF,0xAA,0x0A,0x55,0xEE,0xF3,0xDD,0xDF,0xBF,0xCA,0xA0,
+    0x14,0xE6,0xF0,0xC4,0x58,0x58,0xDC,0xFE,0x14,0xE6,0xF0,0xC4,0x2D,0x2F,0x3F,0x3F,
+    0x76,0xEE,0x14,0xE6,0xF8,0x6A,0xFA,0xEA,0x96,0xEE,0x14,0xE6,0xD7,0xD5,0xBD,0x2F,
+    0x96,0xEE,0x35,0xE6,0x09,0x0A,0x02,0xA0,0x96,0xEE,0x55,0xE6,0xF8,0x5E,0xDE,0x5F,
+    0x75,0xEE,0x55,0xE6,0xEF,0xBF,0xBE,0x5E,0x75,0xEE,0x55,0xE6,0xCB,0xEB,0xFA,0xBD,
+    0x76,0xEE,0xD3,0xDD,0x7A,0xAA,0xA0,0xA0,0x55,0xEE,0x92,0xD5,0x57,0x5E,0xE8,0x80,
+    0x14,0xE6,0x92,0xD5,0x75,0x55,0x5F,0x7C,0xB2,0xD5,0x51,0xCD,0xDE,0xDE,0xF8,0xEA,
+    0x84,0x61,0x43,0x59,0xBB,0xFA,0xBE,0x7A,0x84,0x61,0x43,0x59,0xCA,0x66,0x8F,0xED,
+    0x43,0x61,0x84,0x59,0xDE,0xDD,0xFF,0xFA,0xC4,0x61,0x63,0x59,0x35,0xBD,0xF5,0x7D,
+    0x46,0x72,0x43,0x51,0x02,0xFF,0xD5,0x55,0x66,0x72,0x43,0x51,0x00,0x0A,0xBF,0x55,
+    0xC7,0x7A,0xA5,0x61,0xA8,0xAA,0xAA,0xF5,0x87,0x7A,0x46,0x72,0xA0,0xC2,0x80,0x89,
+    0x87,0x7A,0x66,0x7A,0xBE,0xAE,0xA6,0xAD,0x87,0x7A,0x66,0x7A,0x9E,0xBE,0xAF,0x47,
+    0x87,0x7A,0x66,0x7A,0xAE,0x68,0x8F,0xA0,0xA8,0x82,0x67,0x7A,0xFB,0xAF,0xAF,0xBB,
+    0xA7,0x82,0x67,0x7A,0xFD,0xFB,0xEA,0xBF,0xA7,0x82,0x67,0x7A,0xAE,0xEF,0xEF,0xEE,
+    0xCB,0xA3,0x87,0x82,0x35,0x2D,0x09,0x03,0x0D,0xAC,0xCC,0xAB,0xFA,0x5D,0xF6,0x55,
+    0xAA,0xA3,0xA4,0x59,0x7C,0x78,0x78,0x70,0xA5,0x59,0x02,0x41,0x78,0xFA,0xFA,0x6A,
+    0x02,0x41,0xC2,0x30,0x7A,0x5A,0x5A,0x78,0xC2,0x30,0x82,0x28,0xAB,0xAF,0x02,0x08,
+    0xE2,0x30,0xA2,0x28,0xD5,0xB5,0xAA,0xA8,0x44,0x41,0xA2,0x28,0xDD,0xFD,0xAF,0x03,
+    0x23,0x41,0xA1,0x30,0xD7,0xEF,0x2A,0x00,0x24,0x41,0xE3,0x38,0xAF,0x0A,0x00,0x22,
+    0x24,0x41,0xE3,0x38,0x0B,0x0A,0x02,0x80,0x44,0x41,0xE3,0x38,0xBA,0x60,0x5F,0xD7,
+    0x64,0x49,0x24,0x41,0x66,0xCB,0x41,0x4D,0x44,0x41,0xC3,0x38,0x77,0x77,0xBF,0xA0,
+    0x23,0x41,0xA2,0x30,0xB5,0xBF,0xAA,0x00,0x65,0x49,0xE3,0x38,0xAF,0x0A,0x2D,0xB5,
+    0x23,0x41,0xE3,0x38,0xA8,0xA8,0xCC,0x72,0x24,0x41,0xE3,0x38,0xFF,0x2F,0x2F,0x3D,
+    0x24,0x41,0xE3,0x38,0x8B,0xF7,0xBA,0xE0,0x64,0x49,0x03,0x41,0x5D,0xFD,0xBD,0x03,
+    0x65,0x51,0x03,0x41,0xDF,0xE9,0xEF,0xE8,0x44,0x49,0xE3,0x40,0x27,0xEF,0xAB,0x2E,
+    0x23,0x49,0xE3,0x40,0x80,0xE2,0x50,0xF8,0x85,0x51,0xE2,0x40,0xA7,0xB7,0xBD,0xB5,
+    0xA5,0x59,0x44,0x49,0x02,0xAA,0xEA,0x7A,0xA5,0x59,0x03,0x41,0xA2,0xEA,0x77,0xD5,
+    0xA5,0x59,0x03,0x39,0x82,0xAE,0xFF,0xD5,0x64,0x49,0x03,0x41,0x2A,0x2C,0x36,0x9D,
+    0x64,0x49,0x24,0x41,0x2E,0xB7,0xDB,0xE8,0x85,0x49,0x23,0x41,0x02,0xAE,0xBF,0x77,
+    0x64,0x49,0x03,0x41,0xE8,0xE8,0xDF,0x7F,0x84,0x51,0x23,0x41,0x25,0x25,0xBD,0x29,
+    0x47,0x72,0xA4,0x51,0xAD,0xA5,0xAF,0x2D,0x87,0x7A,0xC6,0x61,0x0B,0xB5,0xBF,0xBA,
+    0xE8,0x82,0x67,0x7A,0x22,0x8A,0xA9,0xA9,0xD3,0xDD,0x09,0x8B,0x09,0x0D,0x2D,0x35,
+    0x55,0xEE,0xF4,0xE5,0x2D,0x0D,0xA2,0xFF,0x35,0xEE,0x92,0xD5,0x00,0xE0,0x78,0x7F,
+    0x92,0xD5,0xF0,0xC4,0xDC,0xFE,0xF7,0xFF,0xD3,0xDD,0x10,0xC5,0x35,0xBD,0xBF,0xBD,
+    0x76,0xEE,0xD4,0xDD,0x22,0x23,0x0B,0x09,0xB7,0xF6,0x76,0xEE,0xB5,0xAF,0xBF,0xAB,
+    0x96,0xEE,0x76,0xEE,0x7C,0x58,0x5C,0x7E,0x75,0xEE,0x55,0xE6,0xBE,0xF0,0xFB,0xFE,
+    0x75,0xEE,0x55,0xE6,0xFC,0x5F,0xFD,0x57,0x75,0xEE,0x34,0xE6,0x0F,0xAE,0xAE,0xFA,
+    0x76,0xEE,0x55,0xE6,0x7E,0x5A,0xFF,0xEB,0x76,0xEE,0x55,0xE6,0x77,0x7F,0x5D,0x08,
+    0x76,0xEE,0x14,0xE6,0x57,0xBE,0xAE,0x00,0x56,0xEE,0xB3,0xD5,0x57,0xBA,0x80,0x00,
+    0x63,0x59,0x23,0x51,0xE2,0x3B,0x3A,0x3C,0x84,0x61,0x43,0x59,0xBE,0xDB,0xE8,0x6A,
+    0x84,0x59,0x43,0x59,0xFA,0xEA,0x0A,0x83,0x84,0x61,0x22,0x51,0xE0,0x7A,0xDE,0xBB,
+    0x43,0x51,0x22,0x51,0x4B,0x8C,0x6C,0x1A,0x64,0x59,0x02,0x49,0xFF,0x97,0xAF,0xA2,
+    0x84,0x61,0x23,0x51,0xAD,0xB7,0x27,0x2B,0x26,0x72,0x84,0x59,0x0A,0xD5,0x55,0x55,
+    0x66,0x7A,0x84,0x61,0x00,0x0B,0xD5,0x55,0x67,0x7A,0x84,0x61,0x00,0x00,0x02,0xB5,
+    0xA7,0x82,0x47,0x7A,0xAA,0x2A,0xBB,0xBD,0xA7,0x82,0x67,0x7A,0xEB,0xAF,0xB7,0xBB,
+    0xA7,0x82,0x87,0x7A,0xFA,0xF3,0x1F,0xF5,0xAB,0xA3,0x87,0x82,0xD5,0x95,0x3D,0x2D,
+    0xEC,0xAB,0x8A,0x9B,0xA9,0xE3,0xFA,0xFA,0xCB,0xA3,0xAB,0xA3,0x0D,0xFA,0xFD,0xFD,
+    0xAB,0xA3,0x05,0x6A,0x70,0x78,0x70,0xE0,0xC5,0x59,0xE2,0x40,0xFE,0xDE,0x78,0x78,
+    0x44,0x41,0xC2,0x38,0x5A,0x72,0xFB,0x5F,0xE3,0x38,0xA2,0x30,0xEF,0xCD,0xFD,0xAA,
+    0x03,0x39,0xA2,0x30,0xAF,0xAF,0x25,0x0E,0x64,0x49,0x03,0x41,0xA7,0xAF,0x8B,0x0B,
+    0x65,0x49,0x03,0x41,0xFE,0x7A,0xAA,0x2A,0x65,0x49,0x03,0x41,0xFF,0xFB,0xF8,0xDC,
+    0x24,0x41,0xE3,0x38,0x40,0xF7,0x9C,0xA0,0x85,0x51,0xE3,0x38,0xDD,0xAD,0xC2,0x02,
+    0x85,0x51,0x03,0x41,0xE7,0xB7,0xFF,0x2F,0x85,0x51,0x24,0x49,0xFB,0x7B,0xC2,0x00,
+    0x84,0x51,0x24,0x49,0x7E,0xA9,0x2D,0x2E,0x65,0x49,0xE3,0x38,0xB5,0xB7,0xFE,0x5C,
+    0x23,0x41,0xE3,0x38,0xE0,0xE0,0xFB,0xDD,0x24,0x41,0xE3,0x38,0x2F,0x26,0xEF,0xFE,
+    0x24,0x41,0xE3,0x38,0xF8,0x9E,0xFA,0xFA,0xA5,0x51,0x03,0x41,0x29,0x09,0x0D,0x2D,
+    0x85,0x51,0xE2,0x38,0x78,0xFA,0xF8,0xFA,0x65,0x51,0xE3,0x38,0xAF,0x0F,0xBF,0xFD,
+    0x85,0x59,0x03,0x41,0x7E,0xFE,0xBF,0x2B,0x64,0x49,0x03,0x41,0x2D,0x2E,0x30,0x2C,
+    0x85,0x51,0x23,0x41,0x58,0x7A,0xE2,0xF3,0x44,0x49,0x03,0x41,0xE2,0x00,0x37,0x1B,
+    0x43,0x41,0xE3,0x38,0xFA,0xFB,0xEA,0xEE,0x23,0x41,0xC2,0x38,0x2A,0xBF,0x29,0x2B,
+    0x64,0x49,0x23,0x41,0xA2,0xEB,0xD5,0x5D,0x44,0x49,0xE2,0x38,0x28,0xFA,0xDF,0xDF,
+    0x44,0x41,0x03,0x41,0xAE,0x1F,0x2B,0xAF,0xA5,0x51,0x44,0x49,0x3D,0x0B,0x2F,0xED,
+    0x47,0x6A,0xA5,0x59,0x2B,0x2D,0x95,0xFD,0xC8,0x82,0x06,0x62,0xFF,0xAA,0x03,0xA5,
+    0xC8,0x82,0x67,0x7A,0x27,0x3F,0x96,0x5F,0x4D,0xAC,0xE8,0x82,0x35,0xB5,0xD5,0x55,
+    0xF4,0xE5,0x8B,0x9B,0x00,0x03,0x0B,0x09,0x15,0xE6,0x10,0xC5,0xE8,0x60,0x70,0x78,
+    0x31,0xCD,0xF0,0xC4,0xAA,0xBF,0x95,0x95,0x51,0xCD,0x10,0xC5,0x0A,0x2A,0x3F,0x3F,
+    0x96,0xF6,0x72,0xCD,0x2B,0x0D,0x2D,0x25,0xB6,0xF6,0x76,0xEE,0xAB,0xEF,0x02,0xFA,
+    0xB7,0xF6,0x55,0xE6,0xEB,0xBA,0x80,0x7F,0xB7,0xF6,0x35,0xE6,0xFB,0x8A,0xAA,0x55,
+    0xB6,0xF6,0x14,0xDE,0xAE,0x08,0xAA,0x55,0x96,0xEE,0x92,0xCD,0x00,0x00,0xA0,0x5F,
+    0x76,0xEE,0xF0,0xBC,0x00,0x00,0xAA,0x5F,0x96,0xF6,0xD0,0xBC,0x00,0x88,0xFE,0x55,
+    0x76,0xEE,0x8F,0xAC,0x00,0xAA,0xFF,0xF5,0x36,0xE6,0x32,0xC5,0xE8,0xFF,0xFF,0x7F,
+    0x84,0x59,0x23,0x59,0xB7,0xBF,0x2B,0x8B,0x84,0x59,0x44,0x59,0xF6,0xAA,0xA8,0xC2,
+    0x84,0x59,0x23,0x51,0x6A,0xF8,0xAB,0xFF,0x84,0x59,0x23,0x51,0xF1,0xFD,0x7F,0xAF,
+    0x63,0x59,0x23,0x51,0x6A,0x72,0xDF,0x77,0x84,0x61,0x23,0x51,0x7D,0xF5,0x2D,0xAF,
+    0x84,0x61,0x43,0x59,0xA9,0x8A,0x88,0x08,0xA4,0x61,0x63,0x59,0xFE,0xBA,0x2F,0xAF,
+    0xA4,0x61,0x43,0x59,0xEA,0x7C,0xFE,0xFF,0x64,0x59,0x43,0x59,0x1E,0x58,0x7E,0x57,
+    0x47,0x7A,0x23,0x51,0x2B,0xF5,0xDD,0x55,0x67,0x7A,0x23,0x51,0x00,0x0A,0xF5,0x55,
+    0x87,0x7A,0x23,0x51,0x00,0x00,0x0A,0x35,0xEB,0xAB,0xC8,0x82,0x2D,0x09,0x83,0xA2,
+    0xCB,0xA3,0x6A,0x9B,0xA8,0xDF,0x5F,0xDD,0xAB,0xA3,0x6A,0x9B,0x2A,0xEB,0xED,0xA9,
+    0xAB,0xA3,0x46,0x72,0x60,0x7A,0x6A,0xF0,0x66,0x7A,0x23,0x49,0x7E,0x7A,0x7A,0xF8,
+    0x23,0x49,0xC2,0x38,0x57,0x57,0x7C,0xD8,0x04,0x41,0xC2,0x38,0xAD,0x2D,0xBD,0x9F,
+    0x64,0x49,0xE3,0x38,0xF5,0xFF,0xEE,0xCA,0x84,0x49,0xE2,0x38,0x2D,0xAF,0xBF,0xF7,
+    0x64,0x49,0x03,0x41,0xB0,0x58,0xDE,0x5E,0x44,0x49,0x03,0x39,0xD6,0x7F,0x7A,0xA2,
+    0x44,0x41,0xE2,0x40,0xDE,0xBE,0x8A,0xF2,0xA6,0x51,0x43,0x49,0xAB,0xEA,0xE3,0x79,
+    0xC6,0x59,0x44,0x49,0xF5,0xAD,0xED,0x8D,0xA5,0x59,0x44,0x51,0x3E,0x1F,0x15,0xF7,
+    0x06,0x6A,0x85,0x51,0x57,0x7A,0xC0,0x83,0xA5,0x51,0xE2,0x38,0x5C,0x5A,0x7A,0x68,
+    0x03,0x39,0xA2,0x30,0xBF,0xAD,0x2B,0x2B,0x23,0x41,0xE3,0x38,0xDE,0x7D,0xAA,0x82,
+    0x23,0x41,0xE2,0x38,0xE7,0x3B,0xBB,0xA8,0x64,0x51,0x03,0x41,0x29,0x8F,0xD7,0xDD,
+    0x64,0x51,0x03,0x41,0x70,0xBA,0xEA,0xAB,0x64,0x49,0x03,0x49,0xDD,0x2E,0x3E,0x32,
+    0xA6,0x59,0x43,0x49,0xAF,0x8F,0xFB,0x57,0x84,0x49,0x23,0x41,0x97,0xFE,0xFB,0xAA,
+    0x64,0x49,0xE3,0x38,0xEE,0xEC,0x7A,0x5A,0x23,0x41,0xC2,0x30,0x80,0x8A,0x26,0x2A,
+    0x64,0x49,0xE2,0x38,0x77,0xFD,0x0E,0x2A,0x64,0x49,0xE3,0x38,0x25,0xBD,0xAE,0xE0,
+    0x64,0x41,0x03,0x41,0xAA,0xA8,0xFE,0x67,0x64,0x49,0x03,0x39,0xD5,0xB7,0x2B,0x2E,
+    0x64,0x49,0x23,0x41,0xFD,0x7F,0x57,0x58,0x64,0x49,0x03,0x41,0xBE,0xEA,0xC0,0x81,
+    0xE6,0x61,0x44,0x49,0x2B,0xAD,0x25,0xF5,0x66,0x72,0xC5,0x59,0x0F,0xAD,0xAF,0xAB,
+    0x67,0x72,0xE5,0x69,0xE8,0xEA,0xFA,0xE2,0xC8,0x82,0x26,0x6A,0x03,0x0D,0xED,0xB5,
+    0x72,0xD5,0xC8,0x82,0x0D,0x2D,0x35,0xB5,0xD3,0xDD,0xF0,0xC4,0x70,0x58,0x78,0x5E,
+    0x10,0xC5,0xD0,0xBC,0x2E,0x2F,0xBF,0x15,0x51,0xCD,0x10,0xC5,0xBB,0xBF,0xED,0xFD,
+    0x14,0xE6,0x31,0xCD,0x3D,0x35,0xB5,0xD5,0xF4,0xDD,0xAF,0xBC,0x00,0xFE,0x5E,0x56,
+    0xB3,0xD5,0x8F,0xB4,0x00,0xFF,0x75,0x55,0x72,0xCD,0x2D,0xAC,0x00,0xEA,0x77,0x57,
+    0x52,0xCD,0x2D,0xA4,0x00,0xFF,0x5F,0x55,0x11,0xC5,0x2E,0xA4,0xA0,0xFE,0x55,0x3D,
+    0x32,0xC5,0x4E,0xAC,0x7E,0x55,0xB5,0x00,0xB3,0xD5,0x8F,0xAC,0xB5,0x0D,0x0A,0x22,
+    0xB4,0xD5,0x11,0xBD,0xBD,0xE8,0xF8,0x5A,0x72,0xC5,0x6F,0xAC,0xA8,0xEA,0x5A,0x7E,
+    0x84,0x59,0x43,0x51,0x2E,0xCE,0x77,0x6F,0x64,0x59,0x23,0x51,0xA0,0x7A,0x77,0x5F,
+    0x63,0x59,0x23,0x51,0xBE,0x8F,0xEF,0xF5,0x22,0x59,0x63,0x51,0xFF,0xEF,0xBB,0xAB,
+    0x63,0x59,0x23,0x51,0xFB,0xAF,0x07,0x0F,0x84,0x61,0x43,0x59,0x39,0xDF,0xBE,0xFF,
+    0x84,0x61,0x63,0x59,0x0A,0xAA,0x9F,0xC7,0xA4,0x61,0x43,0x59,0x6A,0x6C,0x5F,0xD7,
+    0x63,0x59,0x23,0x51,0x08,0xAB,0xF8,0xFA,0x43,0x59,0x23,0x51,0x0A,0x8A,0x80,0x5C,
+    0x23,0x59,0x02,0x49,0xD8,0xFA,0xBE,0xE7,0x23,0x51,0x03,0x49,0xC0,0xC8,0x88,0x8A,
+    0xAB,0xA3,0x43,0x59,0x95,0x35,0x25,0x09,0xCB,0xA3,0x4A,0x9B,0xC2,0xF0,0x58,0x7E,
+    0x8B,0x9B,0x49,0x93,0x28,0x02,0x0B,0xEF,0xAC,0xA3,0x6A,0x9B,0x0E,0xAF,0xFF,0xD5,
+    0xCC,0xAB,0xC7,0x82,0x78,0x52,0x5A,0x5E,0xA7,0x7A,0x64,0x51,0x7E,0x58,0x78,0x60,
+    0x44,0x49,0x03,0x41,0x58,0xA0,0x28,0xBE,0x23,0x41,0xE3,0x38,0x57,0xDC,0x9E,0xF8,
+    0x84,0x51,0x23,0x41,0x89,0xAB,0x8B,0x8B,0x44,0x49,0xE2,0x38,0xFE,0x58,0xF8,0xBA,
+    0x44,0x49,0x03,0x41,0x72,0xE3,0x7B,0x58,0x65,0x49,0xE3,0x38,0xE2,0xDA,0xFF,0x7A,
+    0x23,0x41,0x02,0x41,0xE0,0xA0,0xDE,0x09,0xE3,0x40,0x23,0x39,0xB7,0x0B,0xAA,0xAD,
+    0xC6,0x61,0x03,0x41,0x0D,0x8D,0x2D,0x09,0xA5,0x59,0x03,0x49,0xE8,0xFE,0xF6,0x56,
+    0xC6,0x61,0x23,0x49,0x0B,0x3F,0xDF,0xDD,0x85,0x51,0xC2,0x38,0x78,0x70,0x60,0x60,
+    0x03,0x39,0xA2,0x30,0x2F,0x2D,0xBF,0x97,0x23,0x41,0xE3,0x38,0x22,0x2B,0xFF,0x57,
+    0x64,0x49,0x04,0x41,0xFA,0xAA,0x89,0xAB,0x85,0x51,0x23,0x49,0x57,0xE7,0x2B,0x0A,
+    0xA5,0x59,0x44,0x49,0xED,0x82,0x88,0x8B,0x85,0x51,0x03,0x41,0xFA,0x58,0xFE,0xDC,
+    0x43,0x49,0xE2,0x38,0xE0,0xEA,0xEA,0xF8,0x64,0x49,0x02,0x39,0x0B,0xAD,0xFD,0xF5,
+    0x23,0x41,0x03,0x39,0x60,0xC0,0xF0,0xAA,0x24,0x41,0xE3,0x38,0x2B,0xF8,0x76,0x76,
+    0x65,0x49,0xE2,0x38,0x0A,0x2B,0xAF,0xBD,0xA5,0x51,0x23,0x41,0x7A,0xE2,0xEF,0x7F,
+    0x44,0x41,0x03,0x39,0xDF,0x57,0xA8,0xEA,0x85,0x49,0x03,0x39,0x2B,0x29,0xAD,0xF7,
+    0x64,0x49,0x24,0x41,0x00,0x20,0x94,0xAF,0xA6,0x59,0x23,0x41,0xDD,0x7A,0xEA,0x2F,
+    0x84,0x51,0x44,0x49,0xEF,0xF5,0xA7,0xF8,0x67,0x72,0x84,0x51,0x2D,0xB5,0x55,0x55,
+    0xA8,0x7A,0xA5,0x59,0xA0,0xAA,0xAD,0xB5,0xC9,0x82,0x26,0x6A,0xAD,0xAB,0x0F,0xB5,
+    0xEC,0xA3,0xC8,0x82,0x15,0xB5,0x95,0xD5,0xB3,0xDD,0x8F,0xB4,0xFA,0xF3,0xE2,0xE9,
+    0xF0,0xC4,0xAF,0xBC,0x2E,0x2F,0xAF,0x95,0x31,0xCD,0xF0,0xC4,0xA9,0x0B,0x29,0xF5,
+    0x51,0xCD,0xF0,0xBC,0x3A,0xAB,0x6A,0x7F,0x71,0xD5,0x2D,0xAC,0xF8,0x5E,0x5F,0x57,
+    0xCF,0xBC,0x2D,0xA4,0xFF,0x5F,0xF5,0x25,0x93,0xCD,0x2D,0xA4,0x55,0x55,0xBF,0x02,
+    0xB3,0xD5,0x0D,0xA4,0xD5,0x2F,0x02,0x00,0xB4,0xD5,0x11,0xBD,0xA9,0xEC,0xFC,0x5C,
+    0x73,0xCD,0xF0,0xB4,0xA0,0x3E,0x3F,0x35,0x93,0xCD,0xF1,0xBC,0x60,0x60,0xE0,0x78,
+    0x32,0xBD,0xB0,0xB4,0xB0,0xA5,0xA7,0x67,0xF1,0xBC,0x8F,0xAC,0x5A,0x5C,0xD7,0xF5,
+    0x64,0x51,0x23,0x51,0xF0,0x96,0xFF,0xF5,0x43,0x51,0x23,0x51,0x3C,0x84,0x77,0xBB,
+    0x64,0x59,0x23,0x51,0xB7,0xED,0xCE,0xAB,0x63,0x59,0x23,0x51,0xFF,0xAE,0x2E,0x8E,
+    0x84,0x61,0x43,0x59,0xCB,0xEA,0x8E,0xFF,0x84,0x61,0x43,0x59,0x2B,0xAD,0xF6,0x7F,
+    0x84,0x59,0x23,0x51,0xB8,0xFA,0xEE,0x7F,0x63,0x59,0x23,0x51,0xA8,0xBA,0xEA,0xE9,
+    0x63,0x59,0x23,0x51,0xCF,0xE5,0xFF,0x77,0x23,0x51,0x03,0x49,0x6C,0xD8,0xCE,0x0F,
+    0x23,0x51,0x03,0x49,0x4D,0x72,0xFF,0xEB,0xE8,0x8A,0x02,0x51,0x55,0xD5,0xB5,0x35,
+    0xAB,0xA3,0x26,0x72,0x09,0x03,0x02,0x00,0x8B,0xA3,0x29,0x93,0xA0,0xE0,0xEA,0xDE,
+    0x8A,0x9B,0x09,0x93,0xF8,0xFE,0xDB,0x7F,0x8B,0x9B,0x29,0x93,0xAB,0xAF,0xAD,0x2D,
+    0x6A,0x9B,0x87,0x7A,0x78,0xD8,0x78,0x5C,0xE8,0x82,0x06,0x6A,0x62,0xE2,0xEA,0xAA,
+    0x88,0x7A,0x23,0x49,0x55,0x57,0x5E,0x78,0x64,0x49,0xE3,0x40,0xFB,0x8B,0x2D,0xBF,
+    0x64,0x49,0x03,0x41,0xAF,0x9E,0xD6,0x5C,0x23,0x41,0xE3,0x38,0xBC,0xDC,0x5F,0x57,
+    0x44,0x49,0x03,0x41,0x82,0x09,0x0D,0x27,0x44,0x49,0xE3,0x38,0x7A,0x78,0x7B,0x7A,
+    0x23,0x41,0xE3,0x38,0xA9,0xBD,0xFD,0xF5,0x24,0x41,0xE2,0x38,0x9A,0x2F,0x0E,0xAA,
+    0xE7,0x61,0x44,0x49,0x2D,0xAD,0xF5,0x55,0xC6,0x61,0x24,0x49,0x5C,0xF8,0x2F,0xB7,
+    0xA6,0x59,0x44,0x49,0xD5,0xB7,0x96,0xB0,0x85,0x51,0xE3,0x38,0x7A,0x78,0x58,0x58,
+    0x04,0x39,0xA2,0x30,0xDF,0xD5,0xFD,0x35,0x24,0x41,0xC2,0x30,0xD7,0x9D,0xAA,0xB2,
+    0x85,0x51,0x23,0x41,0xED,0xF9,0xEB,0x82,0x85,0x59,0x44,0x51,0x09,0xED,0xCB,0x0A,
+    0x85,0x59,0x03,0x49,0xA2,0x8A,0x57,0xD6,0x64,0x51,0xE3,0x38,0xF8,0xEE,0x7E,0x7E,
+    0x23,0x41,0xC3,0x38,0x88,0xBE,0xBF,0xED,0x65,0x49,0xE2,0x38,0xFD,0xFD,0xEF,0x8A,
+    0x85,0x49,0x02,0x39,0xD5,0x7F,0xCB,0xEF,0x23,0x41,0xE2,0x38,0xEA,0x80,0xBE,0xFB,
+    0x43,0x41,0x03,0x39,0x35,0x95,0xD5,0xDF,0x43,0x41,0xE2,0x38,0xC8,0xE0,0xF2,0x6E,
+    0x23,0x39,0xE2,0x38,0xBF,0x6D,0xAF,0xAD,0x23,0x41,0xE2,0x30,0x08,0x0A,0xA3,0xAD,
+    0x64,0x49,0x03,0x39,0x2F,0xD7,0xD5,0xFE,0x85,0x51,0x23,0x49,0xBE,0xEA,0x8F,0x2F,
+    0x85,0x51,0x44,0x49,0x02,0x2E,0x1F,0x5E,0x47,0x6A,0x84,0x51,0x55,0xBF,0x3D,0xF5,
+    0x67,0x72,0xC5,0x61,0x75,0x97,0x58,0xA3,0xA8,0x82,0x06,0x62,0x95,0xD5,0x37,0x3D,
+    0xC9,0x82,0x46,0x72,0x22,0xBF,0xDE,0xE0,0x31,0xCD,0xC9,0x82,0x03,0x09,0x0D,0x25,
+    0xF0,0xC4,0x6E,0xB4,0xAE,0xFC,0x58,0x70,0xF0,0xC4,0x8F,0xB4,0x2A,0xAB,0xED,0x55,
+    0x10,0xC5,0x6E,0xB4,0xE8,0x7A,0xB7,0x25,0x31,0xCD,0x2E,0xAC,0x55,0xFD,0x2A,0x00,
+    0xB3,0xD5,0x4E,0xAC,0xB5,0xAF,0x0A,0x0A,0xD4,0xD5,0x11,0xBD,0x2B,0xBF,0xDF,0x7E,
+    0xD5,0xD5,0x32,0xC5,0xB0,0xEA,0x2F,0xF5,0x73,0xCD,0xD0,0xB4,0x58,0x5C,0x5C,0x40,
+    0x73,0xC5,0x8F,0xAC,0x25,0x35,0xA5,0xE5,0x73,0xC5,0x0D,0x9C,0xE0,0xFA,0xFF,0x95,
+    0xD0,0xB4,0xB0,0xAC,0xC3,0x43,0xE2,0x7B,0xF1,0xB4,0x8F,0xAC,0x95,0x2D,0x3F,0xA7,
+    0x43,0x51,0x02,0x49,0xEF,0xF6,0x88,0xE0,0x64,0x59,0x23,0x51,0xED,0xAB,0xAB,0xFF,
+    0x84,0x59,0x23,0x51,0x97,0xAF,0x8E,0xEF,0x64,0x59,0x43,0x59,0xC2,0x72,0x5D,0x30,
+    0xA4,0x61,0x43,0x59,0xBF,0xF9,0xEB,0xCB,0x64,0x61,0x43,0x51,0xE0,0x5E,0xE7,0xF6,
+    0x43,0x59,0x64,0x51,0x00,0x20,0xA8,0xC0,0x64,0x59,0x23,0x51,0xE9,0xE7,0xFC,0xFC,
+    0x44,0x59,0x03,0x49,0xC2,0xFA,0x6E,0x7F,0x23,0x51,0x03,0x49,0xBF,0x5E,0x68,0xA8,
+    0x44,0x59,0x03,0x49,0xFD,0xBF,0x3D,0x3F,0x8B,0xA3,0x43,0x59,0x25,0x2D,0x0B,0x03,
+    0xCC,0xA3,0x4A,0x9B,0xF0,0x7C,0x7A,0x82,0x8A,0x9B,0x29,0x93,0x7F,0x5E,0xFF,0x70,
+    0x4A,0x93,0x09,0x93,0x0F,0x0B,0xFE,0xA0,0x6B,0x9B,0x29,0x93,0x09,0x2F,0xD7,0xDD,
+    0x4A,0x93,0x87,0x7A,0x7C,0x7C,0x58,0x58,0xA8,0x7A,0x27,0x72,0x88,0xAA,0xF8,0x6F,
+    0x67,0x72,0x85,0x59,0x78,0xE0,0xA0,0xA0,0xE6,0x61,0x03,0x49,0xD5,0x77,0x78,0xE0,
+    0x64,0x51,0xE2,0x38,0x70,0x7A,0xEF,0xD7,0x03,0x39,0xC2,0x38,0x8B,0xBA,0xFF,0x5E,
+    0x85,0x51,0xE2,0x38,0xBF,0x2D,0x3D,0x95,0x85,0x51,0xE2,0x38,0x7A,0x78,0x78,0x5A,
+    0x24,0x41,0xE3,0x38,0xA5,0xF6,0x76,0xF0,0x24,0x41,0xE3,0x38,0xAA,0xAE,0xED,0x27,
+    0x65,0x51,0x03,0x41,0xBF,0xAD,0xCD,0x8F,0xA6,0x59,0x23,0x49,0xAF,0xAB,0x0B,0xA5,
+    0xC6,0x59,0x65,0x51,0xB8,0xAE,0x6F,0xBF,0x65,0x51,0xC2,0x38,0x70,0x70,0x5A,0x56,
+    0x03,0x39,0xA2,0x30,0x27,0xBF,0xD7,0xF5,0x03,0x39,0xA2,0x30,0x00,0x00,0xBF,0xF7,
+    0xC6,0x61,0x23,0x41,0x89,0x09,0x0D,0xA5,0xE6,0x61,0x85,0x59,0xD7,0x78,0x70,0x49,
+    0x85,0x51,0x03,0x41,0xDC,0x5C,0x5E,0xFE,0x24,0x41,0xE3,0x38,0x78,0x78,0x7B,0x76,
+    0x24,0x41,0xE3,0x38,0xA9,0x3B,0xDD,0x57,0x64,0x49,0x23,0x41,0xBB,0x29,0xC3,0x81,
+    0x64,0x49,0x03,0x41,0xEF,0xFA,0xF2,0xF7,0x23,0x41,0xE2,0x38,0x5F,0x5B,0x58,0xEC,
+    0x44,0x41,0xE2,0x38,0xF3,0xF5,0xF5,0x95,0x24,0x41,0x03,0x39,0x76,0x8D,0xBE,0xB9,
+    0x44,0x39,0xE2,0x38,0xFD,0xFF,0xD6,0x7E,0x23,0x39,0xE2,0x38,0xF7,0x9F,0x93,0xBB,
+    0x64,0x49,0x03,0x39,0xE3,0xA9,0x2D,0xBF,0x64,0x49,0x23,0x41,0xAE,0x0B,0x0F,0xAB,
+    0x64,0x49,0x23,0x49,0xBE,0xDF,0xDF,0xF8,0xC5,0x61,0x44,0x49,0x2D,0xBD,0xF5,0xAD,
+    0x26,0x6A,0x64,0x51,0x0A,0x2D,0xB7,0x77,0x88,0x7A,0xC5,0x61,0x3F,0xAB,0xBF,0xD5,
+    0x09,0x8B,0x68,0x7A,0xE0,0x8A,0x03,0x0D,0x11,0xC5,0xE9,0x82,0x35,0x35,0x15,0x95,
+    0x35,0xEE,0x6F,0xB4,0x7F,0xFE,0xAA,0x02,0x35,0xE6,0x6E,0xB4,0x55,0xFF,0x02,0x00,
+    0xF4,0xDD,0x6E,0xB4,0xB5,0xB7,0x00,0x00,0x14,0xE6,0x52,0xCD,0xF5,0xEB,0x5A,0x60,
+    0xB3,0xD5,0x52,0xC5,0x27,0xCF,0xA9,0x2B,0xB4,0xCD,0x32,0xC5,0x78,0x7A,0x7B,0x6E,
+    0x52,0xC5,0xF1,0xBC,0xAB,0xBA,0x7C,0x7A,0x93,0xCD,0xF1,0xBC,0x02,0x2A,0xAD,0xF5,
+    0x73,0xCD,0x0E,0x9C,0xE8,0x60,0x78,0x7A,0xB0,0xB4,0xCC,0x93,0x25,0x0D,0x0B,0x03,
+    0xD0,0xB4,0x90,0xAC,0xEC,0x7E,0x7E,0xDE,0xD0,0xB4,0x90,0xAC,0xA9,0x29,0xF7,0xD7,
+    0x84,0x59,0x43,0x51,0x77,0xB5,0xEB,0xFA,0x64,0x59,0x23,0x51,0xF6,0xBC,0xFA,0xB8,
+    0x64,0x59,0x43,0x59,0x55,0xDF,0x0A,0x11,0x84,0x61,0x43,0x59,0x2F,0x83,0xE8,0xF0,
+    0x84,0x61,0x43,0x59,0xE2,0xF2,0xDC,0xD5,0x64,0x59,0x23,0x51,0xEA,0xFA,0xAB,0xAA,
+    0x64,0x59,0x23,0x51,0xFA,0x7F,0x7F,0x6F,0x44,0x59,0xE2,0x48,0x88,0xE2,0xEE,0x8A,
+    0x23,0x51,0xE2,0x48,0xEA,0xEA,0x7E,0xFC,0x23,0x51,0xE2,0x48,0xCE,0x2E,0xA8,0x9A,
+    0xE9,0x8A,0x23,0x51,0xD5,0x95,0x35,0x25,0xCC,0xA3,0xC9,0x8A,0xA9,0x2A,0x2A,0x02,
+    0xEC,0xAB,0x8B,0xA3,0xA3,0x0A,0xAA,0xFC,0xAB,0xA3,0x4A,0x93,0x78,0x68,0xE0,0xAA,
+    0x8B,0x9B,0x29,0x93,0x5D,0x7F,0xFE,0x2A,0x6A,0x9B,0x2A,0x93,0x9F,0x2A,0xAA,0xF0,
+    0x2A,0x93,0x47,0x72,0x78,0x78,0x78,0x78,0x67,0x72,0x26,0x72,0x60,0xF2,0xA2,0xFE,
+    0x47,0x72,0x06,0x6A,0xBC,0xFE,0x8E,0x4C,0x26,0x6A,0xA5,0x59,0x70,0x88,0x20,0x20,
+    0xE6,0x61,0xE3,0x40,0x57,0xDE,0x78,0xE0,0x23,0x41,0xC2,0x38,0x7F,0x5E,0x58,0xFA,
+    0x24,0x41,0xE2,0x38,0xB5,0xB5,0x3D,0x2D,0x44,0x41,0xE3,0x38,0x7A,0xDE,0xF6,0x78,
+    0x24,0x41,0xC2,0x38,0x8A,0xAB,0xBE,0xDF,0x24,0x41,0xE2,0x38,0xFF,0xAF,0xAB,0x09,
+    0x44,0x49,0xE3,0x38,0xAE,0xBD,0xEA,0xAA,0xA6,0x59,0x03,0x41,0xB7,0xBD,0xA7,0x2D,
+    0xA6,0x59,0x44,0x49,0xFA,0x72,0x7A,0x58,0x44,0x49,0xA2,0x30,0x5C,0xF8,0xFA,0xFB,
+    0x03,0x39,0xA2,0x30,0xBF,0x0D,0x07,0x37,0x03,0x39,0xC3,0x30,0xD5,0xBE,0x2F,0x3A,
+    0x85,0x51,0xE3,0x38,0x2D,0xB5,0xBF,0xAF,0xE6,0x61,0x44,0x49,0x0B,0x2F,0xD7,0x5D,
+    0xA6,0x59,0x04,0x41,0x7A,0xF8,0x7E,0x5F,0x04,0x41,0xE3,0x38,0xE8,0x60,0x6B,0x49,
+    0x23,0x39,0xC3,0x38,0xFF,0xBF,0xED,0xD3,0x64,0x49,0xE3,0x38,0xE2,0xAB,0xE9,0xAD,
+    0x44,0x41,0x03,0x41,0x25,0x2E,0x2B,0x7E,0x64,0x49,0xC2,0x30,0xA8,0xF8,0xFA,0x7A,
+    0x03,0x39,0xE2,0x30,0x96,0xE2,0x58,0x7D,0x23,0x39,0xE3,0x38,0xCB,0xED,0x75,0xD5,
+    0x03,0x39,0xE3,0x30,0xC0,0xB7,0x75,0x3E,0x23,0x41,0xE3,0x38,0x89,0x09,0xAD,0xBE,
+    0xA6,0x51,0x24,0x41,0xFD,0xAD,0x0F,0xA9,0xA5,0x51,0x44,0x49,0x75,0xEF,0xB0,0xE8,
+    0xE6,0x61,0x44,0x49,0x5D,0xFF,0x2F,0xB5,0xE6,0x61,0x64,0x51,0xBD,0xBF,0xA8,0x00,
+    0x07,0x6A,0xA5,0x59,0x7D,0x5D,0xA7,0xAC,0x88,0x7A,0x84,0x59,0xD5,0xFF,0xAB,0x2D,
+    0xE8,0x82,0x26,0x6A,0x2D,0xBD,0x35,0xB5,0xAC,0x9B,0xE8,0x82,0x35,0x15,0x95,0x95,
+    0x55,0xEE,0x6E,0xB4,0x02,0x03,0x01,0x09,0x76,0xEE,0x35,0xE6,0xEF,0xCA,0xEA,0x7B,
+    0x55,0xEE,0xF4,0xDD,0xA8,0xA8,0xE2,0xFF,0x35,0xE6,0x32,0xC5,0x60,0x68,0x78,0xDA,
+    0xB3,0xD5,0x52,0xC5,0xAB,0xE9,0xFB,0x68,0x93,0xCD,0x52,0xC5,0xE8,0xB8,0xAB,0x2D,
+    0x73,0xCD,0x11,0xBD,0x7E,0xDE,0xFA,0xD8,0x11,0xBD,0x4F,0xA4,0x08,0x80,0xC0,0x60,
+    0xB0,0xB4,0xEA,0x7A,0xA0,0xB7,0x37,0xAF,0xB0,0xB4,0x6F,0xAC,0x01,0x8B,0x21,0x29,
+    0xD1,0xB4,0x6F,0xAC,0xAB,0x8A,0xCA,0x78,0xD1,0xB4,0x6F,0xAC,0x8A,0xEA,0xFA,0x55,
+    0x63,0x59,0x23,0x51,0xBA,0x26,0x17,0x89,0x84,0x59,0x43,0x51,0xFF,0xED,0xFB,0xAE,
+    0xA4,0x61,0x64,0x59,0xD7,0xDD,0x19,0xDF,0x84,0x61,0x43,0x59,0xEA,0xF8,0x7C,0x7E,
+    0x63,0x59,0x22,0x51,0xAA,0x68,0xEA,0xB6,0x63,0x59,0x22,0x51,0x82,0xAB,0xFB,0xEE,
+    0x43,0x59,0x23,0x49,0xA8,0xF8,0xDE,0xD7,0x44,0x59,0x03,0x49,0xE6,0xFE,0xFC,0xB6,
+    0x23,0x51,0xE3,0x48,0xAB,0xAF,0xEA,0xAA,0x44,0x59,0xE2,0x48,0xFF,0x57,0x27,0x0E,
+    0x6A,0x9B,0x23,0x51,0x25,0x0D,0x0D,0x09,0xCC,0xAB,0x8B,0x9B,0xFF,0x7B,0xAE,0x0B,
+    0xCB,0xA3,0x49,0x93,0x5E,0x77,0xF6,0xE0,0x8A,0x9B,0x29,0x93,0x0A,0xAA,0x6A,0x6E,
+    0x8B,0xA3,0x09,0x8B,0xA8,0xFE,0x55,0x57,0x6A,0x9B,0xC8,0x8A,0xA0,0xEA,0xFF,0x7F,
+    0xE9,0x8A,0x46,0x72,0x78,0x58,0x7C,0x78,0x86,0x72,0x26,0x72,0x57,0xFF,0x7F,0x6F,
+    0x26,0x72,0x06,0x6A,0xC0,0xE0,0x1C,0x90,0x47,0x72,0x06,0x6A,0xBD,0x25,0x1F,0x0E,
+    0x87,0x7A,0x85,0x51,0x7A,0xC8,0xA2,0x08,0xE6,0x61,0xC3,0x38,0x77,0x7F,0x5E,0x78,
+    0x23,0x41,0xC2,0x38,0x2A,0xBF,0xFD,0xA5,0x44,0x49,0xE3,0x38,0x70,0xFB,0xDF,0x7F,
+    0x03,0x41,0xC2,0x38,0x9A,0xFA,0x7F,0xAF,0x64,0x49,0xE2,0x38,0xBD,0x3D,0xED,0xBD,
+    0x44,0x49,0x03,0x41,0xB8,0xBC,0x5C,0x5C,0xA6,0x59,0x04,0x41,0x2F,0xBF,0xBD,0xF5,
+    0xA6,0x59,0x44,0x49,0x70,0xF8,0xE8,0xFD,0x44,0x41,0xA2,0x38,0xFF,0xEE,0xBE,0xF8,
+    0xE3,0x38,0xA2,0x30,0x37,0x2A,0x2A,0xAA,0x24,0x41,0xC2,0x30,0xB8,0xB0,0xAA,0xB5,
+    0x44,0x49,0xE3,0x38,0x27,0x2F,0x2F,0x3A,0x65,0x51,0x24,0x41,0xFA,0x7A,0xFB,0x7B,
+    0x24,0x41,0xE3,0x38,0xC2,0xE3,0xFA,0xD6,0x24,0x41,0xE3,0x38,0xF5,0x7F,0xA7,0x2F,
+    0x24,0x41,0xE3,0x38,0xE2,0xEE,0xBE,0xDC,0x44,0x41,0xE3,0x38,0x8D,0x0F,0xAE,0x8D,
+    0x44,0x41,0xE2,0x38,0x7A,0xC2,0x60,0xFE,0x03,0x39,0xC2,0x30,0x78,0xF4,0xB7,0xBE,
+    0x23,0x39,0xC2,0x30,0xD9,0xBB,0xAB,0xA2,0x24,0x41,0xE3,0x30,0xF5,0xFB,0xEA,0x2B,
+    0x23,0x39,0xC2,0x30,0x2F,0xBA,0xFE,0x7E,0x44,0x41,0xC2,0x30,0xFE,0xAA,0xAB,0x25,
+    0x64,0x49,0xE3,0x38,0x09,0xA7,0xD5,0xFF,0x84,0x51,0x03,0x41,0x82,0xBD,0x55,0x5D,
+    0x85,0x51,0x23,0x41,0x36,0x3F,0x37,0x95,0x47,0x72,0xA5,0x59,0xEF,0xBF,0xA9,0x0D,
+    0x47,0x72,0xA5,0x59,0xAB,0x0F,0x37,0xFE,0x67,0x7A,0xE5,0x61,0x3D,0xB5,0x5E,0xD7,
+    0x67,0x72,0xE5,0x61,0x2C,0x9E,0xF3,0xAB,0x29,0x8B,0x67,0x72,0x23,0xA9,0xBD,0xBD,
+    0x35,0xE6,0x29,0x8B,0x0B,0x09,0x2D,0x2D,0x55,0xEE,0x14,0xE6,0xAA,0xEA,0x7F,0x55,
+    0x35,0xE6,0xB3,0xD5,0xE8,0xF8,0x6A,0x7A,0xB3,0xD5,0xF1,0xBC,0xB0,0x3C,0xBE,0xB6,
+    0xB4,0xD5,0x52,0xC5,0xE8,0xEA,0xEA,0x5A,0x73,0xCD,0x32,0xC5,0x2F,0xE7,0xEE,0xFF,
+    0x52,0xC5,0xD1,0xB4,0xE0,0xA8,0xF8,0x78,0x11,0xBD,0xEE,0x9B,0xE8,0xEA,0x68,0x7A,
+    0x6F,0xAC,0xCD,0x93,0x2D,0xAF,0x2F,0x25,0xB0,0xB4,0x4F,0xA4,0x2B,0x8B,0xEA,0x7E,
+    0xB0,0xB4,0x2E,0xA4,0xFC,0xFE,0x97,0xBF,0xB0,0xB4,0x4F,0xA4,0x9F,0x3F,0xAA,0x4E,
+    0x63,0x59,0x22,0x51,0x0B,0x8A,0xA0,0xC9,0x84,0x59,0x43,0x59,0x9E,0x17,0x6D,0xFD,
+    0x83,0x61,0x23,0x51,0xEA,0x7A,0xFF,0x7D,0x63,0x59,0x23,0x51,0x8A,0x2B,0xAE,0xF6,
+    0x63,0x59,0x23,0x51,0x3E,0x78,0xEE,0x77,0x43,0x51,0x02,0x49,0xAA,0xBC,0x9A,0x2E,
+    0x43,0x51,0x02,0x49,0xAE,0x23,0xA0,0x5E,0x44,0x51,0x03,0x49,0xFA,0xDC,0xD7,0xFB,
+    0x44,0x59,0x02,0x49,0xE7,0xB7,0x3F,0x0A,0x64,0x59,0x23,0x51,0xA9,0xAF,0xBE,0xDC,
+    0x8B,0x9B,0xE6,0x69,0x0D,0x09,0x09,0x0B,0xEC,0xAB,0x8B,0x9B,0x0B,0x2F,0x89,0x2F,
+    0x0D,0xAC,0x8B,0xA3,0x7A,0x7E,0xBA,0x82,0xCC,0xAB,0x49,0x93,0xDF,0x7B,0x58,0x78,
+    0x6A,0x93,0xC8,0x82,0xA0,0xFA,0xFE,0x7F,0x29,0x93,0xC8,0x8A,0x78,0x56,0xDD,0xB7,
+    0xE9,0x8A,0x66,0x72,0x5C,0x5C,0x58,0x58,0x66,0x72,0x26,0x72,0xEA,0xBA,0xBA,0xFA,
+    0x46,0x72,0x06,0x6A,0xFC,0xB8,0x28,0xE2,0x67,0x7A,0x26,0x72,0xD5,0xBD,0xFD,0x2D,
+    0xC8,0x82,0x46,0x72,0xA9,0x2B,0x2B,0x8A,0xA7,0x7A,0x03,0x49,0x5E,0x78,0x70,0xE0,
+    0xE3,0x38,0xA2,0x30,0x38,0x3A,0xFE,0x60,0x03,0x41,0xA2,0x30,0x82,0xEA,0xFB,0x7D,
+    0x24,0x41,0xC2,0x30,0xA5,0x25,0xBD,0xF5,0x24,0x41,0xC3,0x38,0x2E,0xEE,0xFE,0xFE,
+    0x44,0x41,0xE3,0x38,0x7C,0xFB,0xAD,0xF5,0x44,0x49,0xE3,0x40,0xDF,0x57,0x7F,0x0A,
+    0x65,0x49,0xE3,0x40,0x2F,0xBD,0xFF,0xFA,0x64,0x49,0xC2,0x30,0x78,0x6A,0xFA,0xF2,
+    0x03,0x39,0xA2,0x30,0x7D,0x57,0x5C,0xDA,0xE3,0x38,0xA2,0x28,0x2D,0x2D,0x8D,0x0A,
+    0xA5,0x51,0x03,0x39,0xF5,0xB5,0xB5,0x35,0x85,0x51,0x23,0x41,0xDF,0x5F,0x7E,0x70,
+    0x44,0x49,0xE3,0x38,0x5E,0x7A,0x7A,0x5A,0x24,0x39,0xC2,0x30,0x8E,0xBB,0xFE,0xDF,
+    0x03,0x39,0xC2,0x30,0xBA,0x56,0xD5,0xF5,0x23,0x39,0xC2,0x30,0x02,0xEA,0x77,0x77,
+    0x03,0x39,0xC2,0x30,0xBC,0xAA,0x7E,0xAB,0x03,0x41,0xE2,0x30,0xFE,0xF5,0x7D,0x5F,
+    0x24,0x39,0xC3,0x30,0x0B,0xBA,0xEB,0x7E,0x24,0x39,0xC2,0x30,0x2A,0xAA,0xE2,0xA9,
+    0x03,0x39,0xE3,0x30,0xC0,0x08,0x88,0xEE,0x23,0x41,0xC2,0x30,0xB5,0xBF,0x3E,0xBE,
+    0x23,0x41,0x03,0x39,0x50,0xB0,0xE3,0x2F,0x23,0x41,0xE3,0x38,0x76,0xE5,0xE7,0xA8,
+    0x64,0x49,0x03,0x39,0x2B,0x2B,0x0D,0xB5,0x47,0x72,0x64,0x51,0x27,0xF5,0xF5,0x55,
+    0x87,0x7A,0xA5,0x59,0xE8,0x82,0x09,0xB5,0x47,0x72,0xA5,0x59,0xBF,0x2F,0xD4,0x58,
+    0x87,0x7A,0x05,0x62,0xAF,0x0A,0x2A,0xA9,0xA8,0x7A,0x67,0x72,0x3F,0xBA,0xE8,0x80,
+    0x93,0xD5,0xC9,0x82,0x09,0x0D,0x2D,0x2D,0x14,0xE6,0x72,0xCD,0x88,0xAA,0xFF,0x5D,
+    0xF4,0xDD,0x32,0xC5,0xA0,0xE8,0xEA,0x7A,0x93,0xCD,0xF1,0xBC,0x07,0x0F,0x09,0xA9,
+    0x73,0xCD,0x11,0xBD,0xA0,0x60,0x40,0xA0,0x73,0xCD,0xD0,0xB4,0x0B,0x2F,0xB5,0xFF,
+    0x52,0xC5,0xB0,0xB4,0xE8,0x78,0xDE,0x77,0x90,0xAC,0x2B,0x7B,0xE0,0xF0,0x78,0x58,
+    0x70,0xAC,0x8C,0x8B,0x2F,0x2D,0x09,0xAB,0x90,0xAC,0x0E,0x9C,0xF8,0xDF,0xFF,0xA7,
+    0x8F,0xAC,0x4F,0xA4,0x0D,0x6D,0xFD,0xD8,0xD0,0xB4,0x0E,0x9C,0xFF,0xBD,0xBD,0x2A,
+    0x84,0x59,0x43,0x51,0xD5,0xED,0x2E,0x3A,0x63,0x59,0x22,0x51,0x83,0x42,0x62,0xFE,
+    0x43,0x51,0x02,0x49,0xA8,0x2A,0x3A,0xB7,0x43,0x51,0x22,0x51,0x04,0x02,0xC2,0x4C,
+    0x43,0x51,0x02,0x49,0xFE,0x7A,0xBA,0xB4,0x44,0x51,0x02,0x49,0xAB,0xEB,0xBA,0xBA,
+    0x43,0x51,0x03,0x49,0xDC,0xBF,0x8B,0xA7,0x44,0x59,0x03,0x49,0x5E,0xFF,0xBF,0x27,
+    0x64,0x59,0x03,0x51,0xAD,0xAF,0xA2,0xEA,0xA4,0x61,0x24,0x51,0x97,0x9F,0xBF,0x17,
+    0xAB,0xA3,0x47,0x7A,0x09,0x0B,0x0B,0x0B,0x0D,0xAC,0xAB,0xA3,0xAD,0x3D,0xF5,0xFD,
+    0x2D,0xB4,0xEC,0xAB,0x7A,0xF2,0x65,0x55,0xEC,0xAB,0x4A,0x93,0x7A,0x7C,0xA8,0x80,
+    0x8B,0xA3,0xC8,0x82,0x7E,0x7E,0xE2,0xA0,0x29,0x8B,0xC8,0x82,0xBF,0x7D,0xDF,0x78,
+    0xC8,0x82,0x26,0x6A,0xF8,0x68,0x78,0x78,0x46,0x72,0x26,0x6A,0x60,0xF0,0x8B,0xAE,
+    0x46,0x72,0x25,0x6A,0xEB,0xAB,0xFB,0x3E,0xC8,0x82,0x26,0x72,0xBD,0xAF,0xAF,0x0B,
+    0xC9,0x82,0x88,0x82,0xBB,0x6A,0x8A,0x0A,0xA8,0x82,0x26,0x6A,0x68,0x68,0xE8,0xE0,
+    0xE5,0x61,0xC2,0x38,0x56,0x7E,0x7C,0x78,0xA2,0x30,0x61,0x28,0x08,0x2A,0x3C,0xAE,
+    0xE3,0x38,0xA2,0x30,0x2E,0xED,0xD5,0x5D,0x03,0x39,0xA2,0x30,0xE2,0xEB,0x7D,0x5D,
+    0x03,0x41,0xA1,0x30,0x0E,0xAA,0xE9,0xBD,0x44,0x49,0xE3,0x38,0x0E,0x25,0xBD,0xFD,
+    0x65,0x49,0x03,0x41,0x70,0xE2,0xBF,0xDD,0x24,0x41,0xE3,0x38,0xE0,0xBE,0x76,0xDC,
+    0x03,0x39,0x82,0x28,0xEA,0xFA,0xFC,0x58,0xE3,0x38,0xA2,0x30,0x22,0x03,0x0B,0xCD,
+    0x65,0x49,0xC2,0x30,0x2B,0x09,0x29,0xED,0xA5,0x51,0x03,0x41,0xE8,0xEA,0x6F,0x55,
+    0x24,0x41,0xC2,0x30,0xE0,0xE8,0xEA,0x7E,0xE3,0x38,0xC2,0x30,0x72,0xFC,0x37,0x29,
+    0xE3,0x38,0xC3,0x28,0xAA,0x0B,0x08,0xA8,0x03,0x39,0xC2,0x30,0x7E,0x7A,0x2A,0xEA,
+    0xE3,0x38,0xC2,0x30,0xAB,0x42,0xDB,0x95,0x03,0x39,0xC2,0x30,0xFA,0xF7,0xF7,0xD4,
+    0x03,0x39,0xE3,0x30,0x7D,0xD7,0xD6,0x2D,0x03,0x39,0xC2,0x30,0x8F,0xEE,0xB6,0x8A,
+    0x03,0x39,0xC2,0x30,0xFD,0x57,0x5E,0xA8,0x03,0x39,0xC2,0x30,0xBB,0xBF,0x2D,0x2A,
+    0x44,0x41,0x03,0x39,0xBF,0xED,0x0D,0x09,0x44,0x41,0x03,0x39,0xFA,0x6B,0x78,0xFC,
+    0x23,0x41,0xE2,0x38,0x70,0x60,0xEA,0xB2,0x64,0x49,0x03,0x41,0x23,0x29,0xD5,0x55,
+    0xA5,0x59,0x44,0x49,0xAA,0xE9,0xFF,0xF9,0xE6,0x61,0x43,0x49,0xA0,0xA3,0xBF,0xB5,
+    0x88,0x7A,0xA5,0x59,0x2D,0x2D,0x2D,0x27,0xE8,0x82,0x67,0x7A,0xEE,0xE7,0xB6,0xD8,
+    0x31,0xC5,0xC8,0x82,0x2D,0xA5,0x35,0xB5,0x92,0xD5,0xD0,0xBC,0xA2,0x8B,0x2B,0xAD,
+    0x72,0xCD,0xF1,0xBC,0x40,0x72,0xFA,0xF2,0x94,0xCD,0x11,0xBD,0xE9,0xE3,0xC2,0xC2,
+    0x52,0xC5,0xD0,0xB4,0x0A,0xBF,0xFE,0x7E,0x32,0xC5,0x8F,0xAC,0xE0,0x70,0x7A,0x7F,
+    0xB0,0xB4,0x4F,0xA4,0x0C,0x8F,0xEF,0xAB,0xB0,0xAC,0xEA,0x7A,0xDE,0x96,0x26,0x00,
+    0xF1,0xBC,0x4E,0xA4,0x55,0x39,0x00,0x08,0x32,0xBD,0x8F,0xAC,0xD5,0xFA,0xE0,0x80,
+    0xF1,0xBC,0x6F,0xAC,0xFB,0x7F,0xFE,0xA8,0xB0,0xAC,0x6F,0xAC,0xFE,0xDE,0xDF,0x78,
+    0x63,0x59,0x23,0x51,0x42,0xFE,0xFE,0x75,0x44,0x59,0x23,0x49,0xFA,0xA2,0xBB,0xF7,
+    0x43,0x51,0x23,0x51,0xB5,0x6F,0x8B,0x76,0x43,0x51,0x03,0x49,0xA2,0x7A,0x7A,0x76,
+    0x44,0x51,0x02,0x49,0x35,0xD5,0xBF,0xAB,0x43,0x51,0x03,0x49,0x9A,0xF7,0xA7,0xAB,
+    0x63,0x59,0x03,0x51,0xDF,0x5F,0xD7,0xFF,0x64,0x59,0x03,0x51,0x8D,0xAF,0xAA,0x2C,
+    0x64,0x59,0x23,0x51,0x5C,0xF6,0xBE,0xAF,0x67,0x7A,0x43,0x59,0xD5,0x95,0x15,0x15,
+    0xAB,0xA3,0x29,0x93,0x29,0x29,0x09,0x0B,0xEC,0xAB,0x8B,0x9B,0x2B,0xBE,0xFE,0x7F,
+    0x0D,0xAC,0x6B,0x9B,0x02,0x0A,0xDF,0x55,0xEC,0xAB,0x2A,0x93,0x00,0x00,0xAA,0xDF,
+    0xEC,0xAB,0xE8,0x8A,0xA8,0xA0,0xFA,0x5F,0x8B,0x9B,0x87,0x7A,0xF8,0x78,0x56,0x57,
+    0xA8,0x7A,0x46,0x72,0x5C,0x5F,0x57,0x57,0x46,0x72,0x26,0x6A,0x98,0x88,0xF8,0xDF,
+    0xC8,0x82,0x26,0x6A,0xF5,0xFD,0xB5,0x0D,0xC8,0x82,0x87,0x7A,0x89,0xE3,0xAA,0x7C,
+    0xA8,0x82,0x05,0x6A,0x00,0xE8,0x7C,0x57,0x87,0x7A,0xC4,0x61,0xA8,0xEE,0xD5,0x55,
+    0x26,0x6A,0x03,0x41,0x58,0x78,0x72,0xE2,0xE3,0x40,0x61,0x28,0xFF,0xFE,0xB6,0x9C,
+    0xE3,0x38,0xA2,0x30,0x57,0x7F,0xFE,0x8B,0xE3,0x38,0xA2,0x30,0xD5,0xB7,0xBA,0xE2,
+    0x03,0x41,0xA2,0x30,0x3D,0xAA,0x0B,0x02,0x24,0x41,0xC2,0x38,0xBF,0xD7,0x9E,0x0F,
+    0x44,0x49,0xE3,0x38,0xA9,0x03,0x03,0x82,0x44,0x49,0xE3,0x38,0x57,0xEA,0xAA,0xAA,
+    0x24,0x41,0xA2,0x28,0x7B,0x6F,0xE8,0xA0,0xC3,0x30,0x81,0x28,0x8F,0xEF,0x2F,0x2C,
+    0x24,0x41,0xA2,0x30,0xBF,0xB5,0x3F,0x2F,0x45,0x41,0xC3,0x38,0xFE,0xE8,0xE2,0x72,
+    0xE3,0x30,0xA2,0x30,0xFE,0x55,0x5F,0xEB,0xE3,0x30,0xA2,0x30,0xBF,0xFF,0xFF,0x2A,
+    0xE3,0x38,0xA2,0x28,0x0A,0xBB,0xFE,0xBF,0x24,0x39,0xC2,0x30,0xFF,0xF5,0xFD,0x2F,
+    0x03,0x39,0xC2,0x30,0xD7,0xBF,0xBE,0xE2,0xE3,0x38,0xC2,0x30,0x98,0xD8,0x72,0xFD,
+    0x04,0x41,0xE2,0x30,0xFD,0xFF,0x2B,0x0B,0x44,0x41,0xE3,0x38,0x77,0xFF,0x7F,0xF2,
+    0x24,0x41,0xE2,0x38,0xDF,0x7A,0x20,0x20,0x24,0x41,0xE2,0x38,0xDD,0xBB,0xAB,0x08,
+    0x84,0x49,0x03,0x41,0xFF,0x69,0xE3,0xFF,0x23,0x41,0xE3,0x38,0xA2,0xF0,0xF8,0xB8,
+    0x44,0x41,0x03,0x39,0xFF,0x5D,0xAF,0xA0,0x23,0x41,0xE2,0x38,0x02,0x89,0xAE,0x2A,
+    0xA5,0x51,0x23,0x41,0xA9,0xAD,0xBD,0xF5,0xC5,0x59,0x64,0x51,0x9F,0xB0,0xBF,0xAD,
+    0x67,0x72,0xE6,0x61,0x2D,0x27,0x2B,0xA9,0xC8,0x82,0x26,0x6A,0xE8,0x82,0x8A,0x9D,
+    0x6E,0xAC,0x67,0x72,0x25,0xB5,0x35,0x95,0x93,0xCD,0xAF,0xBC,0xBD,0x2D,0x0B,0x0B,
+    0x93,0xCD,0x6F,0xAC,0xB0,0xF8,0x9C,0xBE,0x94,0xCD,0xF1,0xBC,0xA2,0xA2,0xE2,0x58,
+    0x53,0xC5,0xB0,0xB4,0x7A,0x78,0x62,0x7F,0x90,0xAC,0xEE,0x9B,0x28,0x0A,0xA0,0x7C,
+    0xD0,0xB4,0xCD,0x93,0x02,0x80,0xEA,0xF5,0xB0,0xB4,0x0E,0x9C,0xA0,0xFF,0xD7,0x75,
+    0x6F,0xAC,0xCC,0x93,0x00,0xAA,0x5F,0x77,0x11,0xBD,0xCD,0x9B,0x02,0xAF,0xFD,0xD5,
+    0x11,0xBD,0x4F,0xA4,0x00,0x8A,0x2F,0xD5,0x32,0xC5,0xB0,0xB4,0x7F,0x2A,0x80,0x09,
+    0x43,0x51,0x23,0x51,0xAE,0xB0,0x3C,0x94,0x43,0x51,0x03,0x49,0x2F,0x36,0xBC,0x5A,
+    0x43,0x51,0xE2,0x40,0x00,0xA2,0xF0,0xFE,0x44,0x51,0x03,0x49,0x57,0xD5,0xA5,0xBD,
+    0x43,0x51,0x23,0x49,0x65,0xBF,0x3A,0xE8,0x43,0x51,0x23,0x51,0xB5,0x7E,0x9B,0x9D,
+    0x44,0x59,0x23,0x51,0x0F,0xA3,0x40,0x02,0x64,0x59,0x23,0x51,0xB4,0xE7,0x6F,0xF7,
+    0x43,0x59,0x03,0x51,0xA2,0xA3,0xA2,0x68,0x29,0x93,0x43,0x51,0xB5,0x35,0x35,0x25,
+    0xAB,0xA3,0x4A,0x93,0x09,0xAB,0x82,0xEB,0xCB,0xA3,0xA8,0x82,0xA0,0xA8,0xFA,0x7E,
+    0x4B,0x9B,0x87,0x7A,0x00,0xAA,0x7E,0x55,0x09,0x8B,0x67,0x72,0x00,0xEE,0x77,0x55,
+    0xE9,0x8A,0x67,0x72,0xF0,0x7E,0xD5,0x55,0x87,0x7A,0x46,0x72,0xE8,0x7F,0x5A,0x5F,
+    0x86,0x72,0x26,0x72,0xDD,0x7B,0xF7,0xDF,0x87,0x72,0x25,0x6A,0xF7,0xBB,0xBB,0x2A,
+    0xC8,0x82,0x46,0x72,0x8F,0x0B,0xA2,0x72,0x87,0x7A,0x05,0x6A,0xC0,0x68,0x7E,0x77,
+    0x26,0x6A,0xC4,0x61,0x58,0xF6,0xAA,0xEA,0x06,0x6A,0xC4,0x61,0x55,0xBF,0xBA,0x20,
+    0x06,0x6A,0xA5,0x59,0x6B,0xEF,0xC8,0x80,0xA5,0x59,0xC2,0x38,0x57,0x5E,0x58,0x78,
+    0x04,0x41,0x81,0x28,0x0B,0xF5,0x75,0xFF,0x24,0x41,0xA2,0x30,0xEA,0x0B,0xAD,0xBD,
+    0x03,0x39,0xA2,0x30,0xBA,0xFF,0x5C,0x5A,0x44,0x49,0xC2,0x30,0xAB,0x2B,0x29,0x89,
+    0x65,0x49,0x24,0x41,0x6E,0x70,0x78,0xB7,0x44,0x49,0x03,0x41,0xDD,0xAE,0x7C,0xF8,
+    0x44,0x41,0xE3,0x38,0x76,0xBF,0xAF,0x2F,0x04,0x39,0xA2,0x28,0xDE,0xF8,0x7C,0x5C,
+    0x24,0x41,0x82,0x28,0x0B,0x2B,0xE7,0xD5,0x04,0x41,0xA2,0x28,0xE0,0xB8,0xBF,0xBD,
+    0x04,0x39,0xC3,0x30,0xBF,0xEA,0x5A,0x57,0x03,0x39,0xA2,0x28,0xB3,0xFA,0xF7,0xFF,
+    0x03,0x39,0xA2,0x28,0xBD,0xB7,0x3F,0xAF,0x24,0x41,0xC3,0x30,0x22,0x02,0xCA,0xFF,
+    0x03,0x39,0xC2,0x30,0x70,0x50,0xEE,0xB7,0x03,0x39,0xC3,0x30,0xB5,0x3E,0xFE,0x9D,
+    0x65,0x49,0x03,0x39,0xFD,0xAF,0x2D,0x29,0x64,0x49,0x03,0x39,0x5F,0xEE,0xE8,0x70,
+    0x65,0x49,0x02,0x41,0xAA,0xAA,0x82,0xA9,0x64,0x49,0xE3,0x38,0xAC,0xEA,0xEE,0x5E,
+    0x44,0x49,0xC2,0x30,0xA2,0xAE,0xD6,0x5F,0x23,0x41,0xC1,0x30,0x28,0xA0,0x7A,0xFD,
+    0x44,0x41,0xC2,0x30,0xA0,0xEB,0xBF,0xB5,0x44,0x41,0x03,0x39,0x9B,0xD9,0x6B,0xED,
+    0x64,0x49,0x03,0x41,0xA0,0xAB,0xB9,0xFB,0xA5,0x59,0x03,0x41,0x0B,0xAE,0x2B,0x05,
+    0x26,0x6A,0xA5,0x59,0x2D,0x25,0x39,0x3B,0x67,0x72,0xE5,0x61,0x97,0x96,0xFC,0xF0,
+    0x6B,0x93,0x26,0x6A,0x35,0x3D,0x15,0x1D,0x72,0xCD,0xD0,0xBC,0x03,0x01,0x01,0x81,
+    0x53,0xC5,0x6F,0xAC,0x2E,0x2E,0x27,0xFD,0x93,0xCD,0x4E,0xA4,0xE0,0xE8,0x7E,0x57,
+    0xD0,0xB4,0xAD,0x93,0xA0,0xEA,0x7F,0x5F,0x2E,0xA4,0x8C,0x8B,0xF8,0x5F,0x77,0x75,
+    0xEE,0x9B,0x8C,0x8B,0x0B,0xAD,0xA5,0x9D,0x0E,0x9C,0xAD,0x93,0x2A,0xF5,0x2D,0xFF,
+    0x2E,0x9C,0x8C,0x8B,0x8A,0xA2,0xFA,0x7A,0x2E,0xA4,0x6C,0x83,0x2F,0x37,0x37,0x95,
+    0x8F,0xAC,0x2F,0xA4,0xBF,0x2B,0x27,0x2B,0x32,0xC5,0x8F,0xAC,0xDD,0xAB,0x2B,0x0B,
+    0x43,0x51,0x23,0x51,0xF6,0x39,0x96,0xD5,0x23,0x51,0x02,0x49,0xC8,0x6A,0x78,0x54,
+    0x23,0x49,0xE2,0x48,0xE7,0x2F,0x82,0x2A,0x64,0x51,0x02,0x49,0xED,0xED,0xAF,0xCF,
+    0x44,0x51,0x02,0x49,0x80,0xB0,0xFF,0xA6,0x44,0x59,0x22,0x49,0x3F,0x29,0x81,0xB8,
+    0x44,0x59,0x23,0x51,0x00,0x20,0xDB,0xF1,0x64,0x59,0x03,0x51,0xA2,0xB2,0x7A,0xFB,
+    0x43,0x59,0x03,0x51,0xDE,0xFE,0xF6,0x75,0x6A,0x9B,0x43,0x59,0x25,0x25,0x25,0x2D,
+    0x6A,0x9B,0xC8,0x82,0x00,0x80,0xE8,0x7A,0x29,0x93,0x67,0x72,0xE8,0x5E,0x57,0x5F,
+    0x87,0x7A,0x46,0x72,0xFC,0x72,0xEE,0x9E,0x87,0x7A,0x46,0x72,0xAB,0xBE,0x3A,0xBE,
+    0x87,0x7A,0x46,0x72,0xBA,0xBC,0xEF,0xBF,0x87,0x7A,0x46,0x72,0x7A,0xDA,0x9E,0x7E,
+    0x67,0x7A,0x46,0x72,0x57,0x7A,0xB5,0xAD,0xA8,0x7A,0x46,0x72,0x35,0x2F,0xAF,0xFB,
+    0xA8,0x7A,0x05,0x6A,0x60,0x5F,0x57,0x57,0x05,0x6A,0xC5,0x61,0xC0,0x98,0xEA,0x5F,
+    0x05,0x6A,0xC5,0x61,0xE2,0xBE,0xB8,0xFF,0x26,0x6A,0xE5,0x69,0xAF,0x0A,0x0D,0x0F,
+    0x47,0x72,0x06,0x6A,0x7B,0xAB,0x8F,0x2A,0x26,0x6A,0xE3,0x38,0x5A,0x7C,0x78,0xE0,
+    0xC2,0x38,0x81,0x28,0xF0,0xFC,0xFC,0xFC,0x03,0x39,0x81,0x28,0x2D,0xAD,0xA9,0xAB,
+    0x03,0x39,0xA2,0x38,0x7A,0xE8,0xFA,0xAA,0x65,0x49,0xC2,0x38,0xE9,0xCB,0xCB,0xE3,
+    0x44,0x41,0xC2,0x38,0x0F,0xBF,0xF7,0xD7,0x24,0x41,0xC2,0x30,0x00,0xFA,0x7A,0x55,
+    0x23,0x41,0xC3,0x30,0x2B,0xAB,0x63,0x7B,0xE3,0x38,0x82,0x20,0xFC,0xFE,0x5E,0x5E,
+    0xC3,0x28,0x61,0x20,0xFE,0xBE,0x3F,0x2F,0x03,0x31,0x81,0x28,0xAF,0xEB,0xF8,0xFC,
+    0xC2,0x28,0x61,0x20,0x2A,0x22,0x2B,0xAA,0xE3,0x38,0xC2,0x28,0x5F,0xDD,0x95,0xFD,
+    0xE3,0x30,0xC2,0x30,0x02,0xA9,0x93,0x5E,0x03,0x39,0xC3,0x30,0x7E,0x37,0xAF,0xAD,
+    0x04,0x39,0xC3,0x30,0xF5,0x7F,0xAF,0xDF,0xE3,0x38,0xC2,0x30,0x1F,0x8B,0x0B,0xB9,
+    0x85,0x51,0x03,0x39,0x29,0x89,0xFD,0x55,0x85,0x49,0x03,0x41,0xF8,0x7A,0x5F,0x57,
+    0x44,0x41,0xE3,0x38,0x8B,0xAD,0xB5,0xF7,0x24,0x41,0xE2,0x38,0x57,0x7F,0xBF,0x2F,
+    0x03,0x39,0xC2,0x30,0xF9,0xEF,0xC6,0xDC,0x03,0x39,0xC2,0x30,0xAB,0x03,0x8E,0x2D,
+    0x23,0x39,0xC2,0x30,0x3F,0x3E,0x36,0xBE,0x44,0x41,0x03,0x39,0x7F,0x77,0x7A,0xE2,
+    0x44,0x49,0xC2,0x30,0xAA,0xAB,0x0B,0x2F,0xA5,0x51,0x03,0x41,0xAD,0xBF,0xAB,0x0A,
+    0x47,0x6A,0xA5,0x51,0x2D,0x2D,0xAD,0x75,0x67,0x72,0xA5,0x59,0x80,0x80,0xFB,0xF5,
+    0xC8,0x7A,0x84,0x59,0x2E,0x3F,0xBF,0xBD,0x72,0xCD,0x8C,0x93,0x83,0x82,0xA3,0x89,
+    0x90,0xB4,0xAD,0x93,0x82,0xE8,0xF8,0x70,0x2F,0xA4,0x8C,0x8B,0xA0,0xEA,0x5F,0xD5,
+    0xEE,0x93,0x8C,0x8B,0x7A,0x7E,0xFF,0xBD,0xCD,0x93,0x8D,0x8B,0xF7,0x79,0xFD,0x3B,
+    0xCD,0x93,0x6C,0x83,0x3F,0xAA,0xFA,0x70,0xEE,0x9B,0x0A,0x7B,0xA0,0xFA,0x7E,0x7F,
+    0xAD,0x93,0xEA,0x72,0xE0,0xFE,0xFD,0x5D,0x8C,0x8B,0xEB,0x72,0x3B,0xEF,0xFF,0x77,
+    0x2E,0xA4,0x2B,0x7B,0x02,0x2B,0xFD,0xFD,0x32,0xBD,0xAD,0x93,0x0A,0x2B,0xBD,0xFD,
+    0x43,0x51,0x03,0x49,0xBB,0xAF,0xBC,0xD6,0x23,0x49,0x02,0x49,0x3D,0x77,0x58,0x58,
+    0x43,0x51,0x02,0x49,0x33,0xBD,0xFD,0xDD,0x43,0x49,0xE2,0x48,0xA2,0xEE,0xEA,0x6A,
+    0x64,0x59,0x02,0x49,0xBF,0xAD,0x29,0xAA,0x43,0x51,0x03,0x51,0x80,0x28,0xA8,0xB2,
+    0x44,0x51,0x23,0x51,0x73,0x63,0x08,0x7A,0x43,0x51,0x02,0x49,0xAE,0xEE,0x5C,0xDA,
+    0x23,0x51,0x03,0x49,0xD5,0x65,0x5E,0x13,0x0A,0x93,0x23,0x51,0x0D,0x0D,0x09,0x09,
+    0x2A,0x93,0x87,0x7A,0xF8,0x78,0xFE,0x7E,0xA7,0x7A,0x67,0x7A,0xFC,0xEE,0xBF,0x5E,
+    0x87,0x7A,0x67,0x7A,0x56,0x5F,0xDA,0x83,0x87,0x7A,0x47,0x72,0x8E,0xB8,0xBA,0x08,
+    0x87,0x7A,0x46,0x72,0xAE,0xBB,0x5B,0xA2,0x66,0x72,0x46,0x72,0x64,0xD6,0x5C,0xF7,
+    0x87,0x7A,0x46,0x72,0xD5,0xF7,0x35,0xB9,0x87,0x7A,0x46,0x72,0xE9,0x60,0x70,0x7A,
+    0x26,0x72,0xC5,0x61,0xF0,0xF8,0x6E,0x5A,0xE5,0x61,0xA4,0x61,0x9F,0x17,0x35,0xAD,
+    0xE5,0x69,0xC5,0x61,0xBB,0xF8,0x5C,0x94,0x26,0x6A,0xC4,0x61,0x23,0x2B,0x25,0x2F,
+    0x67,0x7A,0x26,0x72,0xFF,0xDD,0xFD,0x87,0x46,0x6A,0xE2,0x38,0xE0,0xE8,0x78,0x70,
+    0xE2,0x38,0x61,0x28,0xFC,0xFE,0xD7,0xF7,0x23,0x41,0xA1,0x28,0xFD,0xBF,0xAF,0xA3,
+    0x64,0x49,0xE3,0x38,0x5D,0xB9,0x2F,0x35,0x64,0x49,0xC2,0x30,0xEB,0x6A,0x78,0x78,
+    0xE3,0x38,0x81,0x28,0xA8,0xFE,0x5F,0x7E,0xC3,0x30,0x82,0x20,0x20,0x2B,0xBE,0xF5,
+    0xE3,0x30,0x62,0x20,0x80,0xE2,0xE2,0x7A,0xC2,0x28,0x61,0x20,0x7E,0xDF,0x75,0x77,
+    0xC3,0x28,0x61,0x20,0x2F,0x2F,0xBF,0xF5,0xC3,0x30,0x82,0x20,0x58,0xF8,0xB7,0xAF,
+    0xE3,0x30,0xA2,0x28,0x55,0x69,0xCB,0xAF,0xE3,0x30,0xA2,0x28,0xEB,0xEA,0xA8,0xFE,
+    0xE3,0x30,0xA2,0x28,0x7E,0xF5,0xDF,0xAA,0x03,0x39,0xA2,0x30,0xAB,0xAB,0xFB,0x5E,
+    0xE3,0x30,0xA2,0x30,0x3C,0xCE,0xE9,0xAF,0x03,0x39,0xA2,0x30,0xFB,0xAD,0x09,0xAA,
+    0x03,0x39,0xE3,0x30,0x3E,0x8A,0xAC,0x57,0x03,0x39,0xE2,0x38,0xFB,0x57,0x58,0xB0,
+    0x03,0x39,0xE2,0x38,0x00,0x30,0xBF,0xC3,0x23,0x41,0xE2,0x38,0xAE,0xF5,0x7E,0x78,
+    0x23,0x41,0xC2,0x30,0xF8,0xFF,0xB7,0x29,0x44,0x41,0xE2,0x38,0xBD,0xDD,0xFF,0xA8,
+    0x23,0x39,0xE2,0x30,0xF8,0xB2,0xBA,0xFB,0x23,0x39,0xE2,0x30,0x03,0x2D,0xB5,0x9D,
+    0x23,0x41,0xC1,0x30,0x2A,0xF6,0xEE,0xFA,0xC5,0x51,0x02,0x39,0x8E,0xFD,0xB5,0xB5,
+    0xC5,0x51,0x43,0x49,0x2D,0xAD,0xFF,0xA0,0x46,0x6A,0xA5,0x51,0xA5,0xAD,0x0D,0xF5,
+    0x47,0x6A,0xA4,0x51,0x3B,0xA2,0x2F,0xB7,0x90,0xB4,0x88,0x72,0x03,0x2D,0x2D,0x0D,
+    0x90,0xB4,0xAD,0x8B,0x60,0xE0,0xE0,0xC0,0x8C,0x8B,0x2B,0x83,0x0A,0x3E,0x2E,0x34,
+    0xCD,0x93,0x6C,0x83,0x29,0x3A,0xAA,0xBA,0xCD,0x93,0x0A,0x73,0x80,0xC0,0xF8,0x5E,
+    0x8C,0x8B,0xA9,0x6A,0xA0,0xEF,0xF7,0x57,0x2B,0x7B,0xCA,0x6A,0x80,0x82,0xFB,0xDF,
+    0x2A,0x73,0xCA,0x72,0xFF,0xD6,0xF7,0xDE,0x4C,0x83,0xEA,0x72,0xB7,0xAB,0xAB,0x2A,
+    0xCD,0x93,0x2B,0x7B,0xA5,0xA5,0x37,0x2F,0x0E,0x9C,0x6C,0x83,0x09,0x37,0x97,0xD4,
+    0x43,0x51,0xE2,0x40,0x6E,0xD2,0xF2,0xBA,0x43,0x51,0xE2,0x40,0xB5,0xAB,0xAE,0xEA,
+    0x23,0x51,0x02,0x41,0xBF,0x38,0xE0,0xDB,0x43,0x51,0x02,0x49,0xD6,0xD6,0xED,0xEB,
+    0x43,0x51,0x03,0x51,0xA8,0xBB,0xAA,0xFB,0x43,0x51,0x23,0x51,0x30,0xBC,0xA9,0x41,
+    0x43,0x51,0x03,0x49,0xF8,0xAA,0xAB,0x6B,0x23,0x51,0xE2,0x48,0xA8,0xB8,0x9C,0xBE,
+    0x23,0x51,0xE2,0x48,0xBA,0xBF,0xBF,0x3F,0x09,0x8B,0x84,0x59,0x09,0x09,0x01,0x0B,
+    0xC8,0x82,0x87,0x7A,0x78,0xF8,0x78,0x5E,0xA7,0x7A,0x67,0x7A,0x5E,0xFF,0xEF,0xEE,
+    0xA8,0x82,0x67,0x72,0xFF,0xAE,0xE6,0xBC,0xA8,0x7A,0x67,0x7A,0xFF,0xB8,0xBA,0xDE,
+    0x87,0x7A,0x67,0x72,0x9A,0x62,0x78,0x6A,0x66,0x72,0x46,0x72,0xE6,0x56,0xFD,0xD5,
+    0x87,0x7A,0x46,0x72,0xB6,0x37,0xA9,0xBD,0x87,0x7A,0x05,0x6A,0xE0,0xFA,0x7A,0x7E,
+    0x06,0x6A,0xA4,0x61,0x78,0x7A,0x76,0x9E,0x87,0x7A,0xC4,0x61,0x55,0xBD,0xB5,0x2B,
+    0x67,0x7A,0x05,0x6A,0xB5,0x0B,0x00,0xBE,0xA8,0x7A,0x46,0x72,0x5F,0x8A,0xFB,0x55,
+    0x87,0x7A,0x26,0x6A,0x0B,0x80,0x7F,0xD7,0x46,0x6A,0x03,0x41,0x60,0x60,0x60,0xE0,
+    0xE2,0x38,0x81,0x30,0xB5,0xBF,0x3E,0x08,0x44,0x41,0xE2,0x38,0x82,0xA2,0x2B,0x3D,
+    0x44,0x49,0xC2,0x30,0x2F,0xBE,0x7E,0x5C,0x44,0x49,0xC2,0x30,0xF0,0x62,0x6B,0x7F,
+    0xC2,0x30,0x82,0x20,0xAA,0xA2,0xFA,0x76,0xA2,0x28,0x62,0x20,0xC8,0xCA,0xEA,0x7F,
+    0xA2,0x20,0x61,0x20,0x78,0xF7,0xF5,0xEF,0xC3,0x28,0x62,0x20,0xFF,0xBD,0xB7,0xAB,
+    0xA2,0x28,0x61,0x20,0xD7,0xAE,0xA8,0xA0,0xC2,0x28,0x82,0x20,0xFD,0xBF,0xAB,0xAD,
+    0xC2,0x28,0xA2,0x28,0x4B,0xF6,0xE0,0xEB,0xE3,0x30,0xA2,0x28,0x5F,0xAD,0xA7,0x2D,
+    0xE3,0x30,0xA2,0x28,0x02,0xE3,0xE2,0x7A,0xE3,0x38,0xA2,0x28,0xBA,0xE2,0xB7,0xF5,
+    0xC2,0x30,0xA2,0x28,0x82,0xB0,0x00,0x2B,0x04,0x39,0xC3,0x30,0xE3,0x7D,0xE5,0xFD,
+    0x03,0x39,0xC3,0x30,0x22,0xAF,0xEF,0x57,0x23,0x39,0xC2,0x30,0x2A,0xEA,0xEF,0xBF,
+    0x03,0x39,0xE2,0x30,0x8B,0x7F,0x57,0x3A,0x23,0x39,0xE2,0x38,0x4A,0x45,0xFF,0xAE,
+    0x23,0x41,0xE3,0x38,0x25,0xB5,0x35,0x2A,0x84,0x49,0x24,0x41,0x6F,0xEF,0x3B,0xAF,
+    0x64,0x49,0x03,0x39,0x55,0xF7,0xBF,0x88,0x43,0x49,0xC1,0x30,0xF7,0xDF,0xFA,0xA2,
+    0x43,0x41,0xE2,0x38,0xFE,0x8D,0xBB,0xBF,0x84,0x49,0xE2,0x38,0x25,0xB7,0xFF,0x9F,
+    0xA4,0x51,0x43,0x49,0xE0,0x57,0xF5,0x05,0x06,0x62,0x63,0x49,0xB5,0xFD,0xAD,0x2B,
+    0x27,0x62,0x84,0x51,0x97,0xBF,0xBA,0x88,0xF1,0xBC,0x27,0x62,0x0D,0x2D,0x2D,0x2D,
+    0x73,0xC5,0xED,0x9B,0x7F,0x7F,0xEA,0x80,0x70,0xAC,0x48,0x62,0xFE,0xD6,0x5A,0xE0,
+    0x4C,0x83,0xC7,0x51,0x00,0xEA,0xFE,0x5E,0x0B,0x73,0xA6,0x51,0xA0,0xAA,0xFF,0xF5,
+    0xA9,0x6A,0x27,0x5A,0x08,0xAE,0xAB,0xF5,0xEA,0x72,0x68,0x62,0x32,0xAA,0xAF,0xBD,
+    0x6C,0x8B,0xA9,0x6A,0xFF,0xBF,0x3D,0x2F,0x2E,0x9C,0x0B,0x7B,0xFD,0xAF,0x8A,0x00,
+    0x0E,0x9C,0x6C,0x83,0x95,0xD7,0xE8,0xE0,0x4F,0xA4,0x6B,0x8B,0x5A,0x72,0x62,0x8A,
+    0x23,0x49,0x02,0x49,0xE4,0xB9,0x0D,0x09,0x23,0x49,0x03,0x49,0x0D,0x25,0x2F,0xA0,
+    0x43,0x51,0x02,0x49,0x5E,0x16,0xAE,0xBB,0x43,0x51,0x23,0x51,0x56,0x74,0xD2,0x01,
+    0x43,0x51,0x03,0x49,0x0A,0xB2,0x9E,0x92,0x43,0x51,0x02,0x49,0xE2,0xEC,0x72,0xDD,
+    0x23,0x51,0x03,0x49,0xD3,0x63,0x02,0xDE,0x23,0x51,0xE2,0x48,0x7B,0x60,0xEE,0xFE,
+    0xE9,0x82,0xE2,0x48,0xD5,0xD5,0xB5,0x2D,0xE8,0x8A,0x26,0x6A,0x81,0x82,0x80,0xA0,
+    0xC8,0x7A,0x66,0x72,0xB8,0xFE,0xFE,0xE3,0xA7,0x7A,0x66,0x72,0xFA,0xFE,0xBE,0x8B,
+    0xA7,0x7A,0x66,0x7A,0xAF,0xFF,0xFB,0xA2,0x87,0x7A,0x66,0x72,0x00,0x0A,0x0A,0xA0,
+    0xA7,0x7A,0x46,0x72,0xFE,0x5C,0x5F,0x7F,0x49,0x8B,0x46,0x72,0x55,0x55,0x95,0x0D,
+    0x8A,0x9B,0x67,0x7A,0x55,0xD5,0xAA,0x20,0x29,0x8B,0x06,0x6A,0xFF,0x82,0xE0,0x5E,
+    0x67,0x7A,0x06,0x6A,0xAE,0x70,0x57,0x55,0x26,0x6A,0xC5,0x59,0xA0,0xA2,0x02,0x7E,
+    0x46,0x72,0xC4,0x59,0xFF,0xAA,0x00,0xD5,0x67,0x72,0xC5,0x61,0x2E,0xA2,0x00,0x55,
+    0xA8,0x7A,0x84,0x51,0xAA,0xA2,0xA2,0x57,0x66,0x72,0x44,0x49,0x78,0x68,0x7A,0x7F,
+    0x44,0x41,0xC2,0x38,0xD7,0x77,0xBE,0xE0,0x03,0x39,0xC2,0x38,0xBB,0xBF,0xAF,0x60,
+    0x24,0x41,0x81,0x28,0xA0,0xA8,0xEF,0xDF,0x03,0x31,0x61,0x18,0xEA,0xF8,0xFE,0x7F,
+    0xA2,0x20,0x61,0x18,0x7C,0xEC,0xEF,0xFF,0xA2,0x20,0x61,0x18,0xF5,0xAD,0xAB,0x0F,
+    0xE3,0x30,0x82,0x20,0xF5,0xF5,0xBD,0xB2,0xE3,0x30,0xA2,0x28,0x5B,0xEF,0xAA,0x0A,
+    0xE2,0x30,0x81,0x20,0x77,0x7F,0xFE,0xA8,0xA2,0x28,0x81,0x20,0xAB,0x67,0xEE,0x00,
+    0xE2,0x30,0x82,0x20,0xBF,0xFD,0xFD,0xA2,0xC2,0x28,0x81,0x28,0x08,0xA7,0xA5,0x0B,
+    0xC2,0x30,0xA2,0x28,0x62,0x6A,0xFB,0xD7,0x03,0x31,0xA2,0x28,0xB5,0xED,0x2B,0x2D,
+    0x03,0x39,0xC2,0x30,0xD5,0xBF,0x8A,0x2B,0x24,0x39,0xC2,0x38,0x6B,0xCA,0x0B,0xAB,
+    0x03,0x39,0xC2,0x30,0xF7,0xFD,0x22,0x32,0x23,0x39,0xE3,0x30,0xAD,0x3D,0x79,0xEF,
+    0x23,0x39,0xC2,0x30,0x2A,0xAA,0xFA,0x5A,0x23,0x39,0xE2,0x30,0xFC,0xD5,0xD7,0x55,
+    0x23,0x41,0xE3,0x38,0xA2,0xA9,0xBD,0x95,0x64,0x49,0x03,0x39,0x2B,0xFF,0xF5,0xB7,
+    0x85,0x51,0x44,0x49,0xAE,0x73,0x63,0xEF,0x44,0x49,0x23,0x41,0x40,0x5E,0xE6,0x0F,
+    0x43,0x41,0x03,0x39,0xD7,0x55,0xFF,0xAE,0x43,0x41,0x03,0x39,0x35,0xAF,0x7E,0xE2,
+    0x84,0x51,0x03,0x39,0x02,0xFF,0xFD,0xEF,0xC5,0x59,0x43,0x41,0x0A,0x99,0x7D,0xDD,
+    0x06,0x62,0x64,0x49,0x02,0xBF,0xF5,0xBF,0xD1,0xB4,0x06,0x62,0x2D,0x25,0x25,0xB5,
+    0x93,0xCD,0xD1,0xBC,0xAA,0xAA,0xAB,0xBD,0x53,0xC5,0x2F,0xA4,0x7E,0xFE,0xF8,0xE0,
+    0xB0,0xAC,0xEB,0x7A,0x7E,0xAA,0x20,0x00,0x8F,0xAC,0xE6,0x51,0x57,0xFA,0x00,0x00,
+    0x6F,0xA4,0x07,0x5A,0x55,0xFF,0x00,0x00,0x4F,0xA4,0xA9,0x6A,0x55,0xFD,0x00,0x00,
+    0x2E,0x9C,0xCA,0x72,0xAD,0xAB,0x00,0x00,0x6F,0xAC,0xED,0x93,0x2D,0xA9,0x8B,0xAB,
+    0x4F,0xA4,0xAC,0x8B,0x70,0xF8,0xE0,0xA2,0x6F,0xAC,0xCC,0x93,0xAD,0x8D,0x0D,0x0D,
+    0x23,0x51,0x02,0x41,0xA0,0x43,0xFF,0xFF,0x23,0x51,0xE2,0x40,0xA2,0x1A,0x2F,0x0F,
+    0x43,0x51,0x23,0x51,0xFD,0x8B,0xA0,0x03,0x43,0x51,0x23,0x51,0x58,0x74,0x65,0x54,
+    0x43,0x51,0x03,0x49,0xF3,0xBA,0xFE,0xDE,0x23,0x51,0x02,0x41,0xFC,0xA7,0x5F,0x7B,
+    0x23,0x49,0x03,0x49,0x54,0x28,0x7E,0xF9,0xC4,0x61,0xA1,0x40,0xFF,0xFF,0xBF,0x3D,
+    0x09,0x8B,0x43,0x51,0x0D,0x09,0x02,0x00,0x09,0x8B,0xA7,0x82,0x78,0xEC,0xFA,0x7A,
+    0xE8,0x82,0x86,0x7A,0x57,0xDF,0xFF,0xF8,0xA7,0x7A,0x87,0x7A,0xDE,0x5E,0x5E,0x08,
+    0xA7,0x7A,0x66,0x72,0xB2,0xEA,0x60,0x78,0x29,0x93,0x66,0x72,0x57,0x55,0x55,0x15,
+    0xAB,0xA3,0x87,0x7A,0x55,0xB5,0x0B,0x00,0x8A,0x9B,0x25,0x6A,0x02,0x00,0xC0,0x78,
+    0x8A,0x9B,0xC5,0x61,0xE0,0x5A,0x57,0x55,0x26,0x6A,0xA4,0x61,0xB8,0xFB,0xD7,0xAF,
+    0x06,0x6A,0x44,0x49,0x00,0x68,0x5E,0x5E,0xA4,0x59,0x03,0x41,0xEC,0x77,0xF5,0xEF,
+    0x43,0x49,0x23,0x41,0x0B,0xA2,0xE2,0xD8,0x43,0x49,0x03,0x41,0xE2,0xA8,0xEA,0xF7,
+    0x43,0x49,0x03,0x41,0x67,0x9E,0xDE,0xD7,0x85,0x51,0x23,0x41,0xC9,0xEB,0xEF,0xD9,
+    0x44,0x49,0xC2,0x30,0xA0,0xBA,0xFE,0x5E,0x03,0x39,0x82,0x20,0xE0,0xF0,0x5E,0x7E,
+    0xA2,0x28,0x81,0x20,0x62,0xE2,0xAA,0xDD,0xA2,0x20,0x61,0x18,0x6A,0xE8,0xF8,0xFE,
+    0xA2,0x28,0x61,0x18,0xD5,0xD5,0xA7,0xA9,0xE3,0x30,0x82,0x20,0xA5,0xF5,0xBD,0x2F,
+    0x24,0x39,0xA1,0x28,0xAF,0x3D,0x37,0x3E,0x24,0x39,0xC2,0x30,0xF6,0xF7,0xA4,0xFC,
+    0xE2,0x30,0x81,0x28,0xBA,0x78,0xFC,0xF8,0xE3,0x30,0xA1,0x28,0xBB,0x02,0x29,0xF5,
+    0xE2,0x30,0xA2,0x28,0xE2,0xF0,0xE8,0xFE,0xE3,0x28,0x81,0x28,0xFB,0xDE,0x7E,0xFE,
+    0xC2,0x28,0x81,0x20,0xEA,0xEF,0xBF,0x27,0xC2,0x28,0xA2,0x28,0x09,0x05,0x59,0x5B,
+    0xE3,0x30,0xA2,0x28,0x0A,0xFF,0xF7,0xF7,0x03,0x39,0xA2,0x28,0x2B,0x2D,0xFF,0xDF,
+    0x03,0x39,0xC2,0x30,0xE0,0xF0,0xFF,0x57,0x24,0x39,0xC2,0x30,0xA3,0xAF,0xED,0x95,
+    0x23,0x39,0xE2,0x30,0x68,0x7E,0xEB,0xFA,0x23,0x39,0xE2,0x38,0xB5,0xB7,0x35,0xB5,
+    0x23,0x41,0xC2,0x30,0xF4,0x7A,0xF8,0xFB,0x64,0x49,0xC2,0x38,0xBF,0x3F,0x2F,0x2D,
+    0x85,0x49,0x23,0x41,0xAB,0xD6,0x7C,0xF0,0x44,0x49,0xE2,0x38,0x0A,0x2A,0xBF,0xF6,
+    0x23,0x41,0xC2,0x38,0x00,0x02,0xFC,0xFF,0x64,0x49,0xE3,0x38,0x8B,0xAF,0xDF,0xDD,
+    0x85,0x49,0xE2,0x38,0x82,0xAB,0xD5,0xF5,0xC5,0x51,0x23,0x41,0xAB,0x2B,0xA7,0x75,
+    0x06,0x62,0x63,0x49,0x2B,0x2A,0xAF,0xD5,0xAC,0x93,0x64,0x51,0x2F,0x2F,0x25,0x35,
+    0x11,0xBD,0x2E,0xA4,0x2B,0xAF,0xBD,0xFD,0x52,0xC5,0xB0,0xB4,0x20,0x2B,0xBF,0x7D,
+    0x73,0xCD,0xF0,0xBC,0x7B,0xA8,0xA2,0xA9,0x32,0xC5,0x6F,0xAC,0xFE,0xFE,0xDC,0x68,
+    0xAF,0xB4,0x4F,0xA4,0xC0,0xF8,0x5B,0xFF,0x6F,0xAC,0x2E,0xA4,0xE8,0xBA,0x55,0x7F,
+    0x8F,0xAC,0x0E,0x9C,0x5E,0xE2,0xAA,0x23,0x6F,0xAC,0x0E,0x9C,0xEF,0xF7,0xFA,0xE0,
+    0x6F,0xA4,0x2E,0xA4,0x4F,0xD5,0x55,0x5F,0x90,0xAC,0xED,0x9B,0x2D,0x37,0xBF,0xBF,
+    0x43,0x51,0xE2,0x40,0xFF,0x9F,0x25,0x3D,0x64,0x59,0x02,0x49,0xAD,0x2B,0xA2,0xAA,
+    0x83,0x51,0x23,0x51,0xF7,0xDE,0x77,0x7F,0x63,0x51,0x02,0x49,0xE8,0xFA,0xEE,0x7F,
+    0x23,0x49,0x03,0x49,0xDA,0x23,0x03,0x79,0x23,0x49,0xE2,0x40,0xF8,0x2A,0x9E,0xA2,
+    0x23,0x49,0x02,0x41,0x56,0x24,0xCF,0x67,0xCB,0xA3,0x03,0x49,0xB5,0x25,0x0D,0x0D,
+    0x8B,0x9B,0xC8,0x82,0x7E,0xFF,0xFC,0xC8,0x08,0x8B,0xA7,0x82,0xFB,0xDE,0xFA,0xE8,
+    0xA7,0x82,0xE7,0x7A,0x2A,0xAA,0x22,0xBE,0xC7,0x82,0x86,0x7A,0xFB,0x76,0x7E,0x54,
+    0xAB,0xA3,0x46,0x72,0x57,0xF5,0xB7,0x2B,0xCB,0xA3,0x67,0x7A,0x2D,0x0A,0x00,0x80,
+    0xAB,0xA3,0x26,0x6A,0x00,0xC0,0x78,0x56,0xE9,0x8A,0xA4,0x59,0xF8,0x5E,0x5F,0x5F,
+    0xE6,0x61,0x84,0x59,0xAE,0x3D,0x2B,0x2F,0x06,0x6A,0x64,0x51,0x22,0xE8,0xE8,0x7A,
+    0x84,0x51,0x23,0x49,0xA8,0xE8,0xDC,0xF7,0x64,0x49,0x23,0x41,0xFE,0x7B,0x6F,0xB2,
+    0x64,0x49,0x03,0x41,0xBB,0xFF,0xE7,0x2E,0xE5,0x61,0x03,0x41,0x55,0x5D,0xD7,0x2A,
+    0xC5,0x59,0x03,0x41,0x55,0x55,0xFF,0x80,0x64,0x49,0xE2,0x38,0xE8,0x5A,0x7E,0x7A,
+    0xE3,0x38,0xA1,0x28,0xF8,0xBE,0xAE,0xF6,0xE3,0x30,0x81,0x20,0x72,0x70,0x78,0x7A,
+    0x81,0x20,0x61,0x18,0x00,0xAA,0x08,0x80,0x82,0x20,0x61,0x18,0xB8,0xBF,0x55,0xB5,
+    0xC3,0x28,0x61,0x18,0xAF,0xAF,0xAA,0x8A,0xC3,0x30,0x82,0x20,0x0F,0xBF,0xF7,0xED,
+    0x04,0x39,0xA2,0x28,0x3A,0xBB,0xDF,0xD5,0x03,0x39,0xA2,0x28,0xEC,0xE6,0xFF,0x79,
+    0x03,0x39,0xA2,0x30,0xFE,0xA9,0x0F,0x2F,0xE2,0x30,0xA1,0x28,0x57,0xF8,0xF8,0xC0,
+    0xE3,0x30,0x81,0x28,0xFF,0xD6,0xFA,0x80,0xC2,0x30,0xA2,0x28,0xD6,0x95,0xAB,0x8E,
+    0xC2,0x30,0xA2,0x28,0x55,0xBF,0x2A,0x8B,0xC2,0x30,0xA2,0x28,0x5F,0xF4,0xAD,0x5B,
+    0xC2,0x28,0x82,0x28,0x00,0x0A,0xAA,0xEF,0xE2,0x30,0xA2,0x28,0xAF,0x0B,0xAF,0x3D,
+    0xE2,0x30,0xA2,0x28,0xEF,0x8E,0x28,0x0A,0x24,0x39,0xC2,0x30,0xBF,0x37,0xD5,0xFF,
+    0x44,0x41,0xE3,0x38,0xFA,0xC2,0xAD,0xAD,0x23,0x39,0xE2,0x30,0xAD,0x85,0xAD,0xD5,
+    0x03,0x39,0xC2,0x30,0xEC,0xAA,0x8E,0xEE,0x64,0x49,0xC2,0x30,0xB5,0x35,0x37,0x2F,
+    0xA5,0x51,0x24,0x41,0x68,0x60,0xE0,0xF6,0x24,0x41,0xC2,0x30,0xE8,0x9C,0xBA,0xFC,
+    0x44,0x41,0xE2,0x38,0xBD,0x35,0xB7,0xF5,0x23,0x41,0xC2,0x30,0xBA,0xA8,0xBA,0x7E,
+    0x65,0x41,0xE3,0x38,0xF5,0xAD,0xAF,0x2B,0xC6,0x59,0x23,0x49,0xFD,0xBF,0xAB,0x2A,
+    0xE6,0x59,0x43,0x41,0xF5,0xB7,0x0F,0x88,0x0A,0x7B,0x64,0x49,0x35,0x3F,0x27,0x3F,
+    0x6F,0xAC,0xCD,0x93,0x0A,0xAB,0xBD,0xB5,0xF1,0xBC,0x0E,0xA4,0x0B,0x3F,0xFF,0xF5,
+    0x32,0xBD,0x4E,0xAC,0x02,0x80,0xAB,0xB5,0x32,0xC5,0x8F,0xAC,0x78,0x7A,0xEA,0xAB,
+    0xD0,0xB4,0x6F,0xAC,0x57,0x6F,0xFA,0xF8,0x8F,0xAC,0x4F,0xA4,0xDE,0xFF,0xF7,0xCC,
+    0x8F,0xAC,0x4F,0xA4,0xBF,0xBA,0xAB,0xDC,0x90,0xAC,0x4E,0xA4,0x6F,0xBA,0xB2,0xA9,
+    0x8F,0xAC,0x4F,0xA4,0x5F,0x7E,0xDA,0x6F,0x6F,0xAC,0x2E,0xA4,0xFD,0x88,0xB2,0x5A,
+    0x64,0x59,0x03,0x49,0xBD,0xAA,0x2A,0x8A,0x64,0x59,0x43,0x51,0x6E,0x08,0x82,0xAF,
+    0x63,0x51,0x22,0x49,0x77,0x78,0x7F,0x5A,0x43,0x49,0x02,0x49,0x5A,0x5C,0xAA,0x9F,
+    0x23,0x49,0x02,0x49,0xC0,0xC0,0x80,0xD5,0x23,0x49,0x02,0x41,0xB3,0xD5,0xED,0x66,
+    0x63,0x51,0x02,0x49,0x5D,0xD5,0xD7,0x95,0xAB,0x9B,0x84,0x59,0x09,0x09,0x03,0x03,
+    0x8A,0x9B,0x08,0x8B,0xE8,0xEA,0xE0,0x7A,0x08,0x8B,0xC8,0x82,0x58,0xFA,0xE8,0xEC,
+    0x08,0x8B,0xA7,0x82,0x5F,0xDF,0x7F,0x2A,0xCB,0xA3,0xA7,0x82,0x55,0xB5,0x2D,0x02,
+    0xCB,0xA3,0xC8,0x82,0x03,0x00,0x80,0x60,0xAB,0xA3,0x26,0x72,0xC0,0x58,0x56,0x55,
+    0x67,0x72,0x05,0x6A,0x9E,0xB7,0x2E,0xF3,0x26,0x6A,0x63,0x51,0x78,0xDC,0xFE,0xBE,
+    0xE6,0x61,0x63,0x49,0x0B,0x08,0xC8,0x52,0xC5,0x59,0x23,0x41,0xE8,0xFE,0x7F,0xFF,
+    0x64,0x49,0x03,0x41,0x0E,0x2A,0x29,0xA2,0x85,0x51,0x23,0x49,0x7F,0xFE,0x3E,0x37,
+    0x06,0x6A,0x64,0x49,0xAD,0x02,0xA0,0xE2,0xC5,0x61,0xE2,0x40,0x00,0xA8,0xFE,0x5F,
+    0xC5,0x59,0x02,0x41,0xC0,0xFA,0xFF,0x55,0x23,0x41,0xC2,0x30,0xE0,0xFE,0x5E,0x5E,
+    0xC2,0x30,0x81,0x20,0xEC,0x68,0x68,0xD8,0xA2,0x28,0x61,0x20,0xE0,0x7A,0x7A,0xE8,
+    0x81,0x20,0x41,0x18,0x20,0xEA,0xFF,0xEE,0xC2,0x28,0x40,0x18,0xB7,0xAF,0x0B,0x0A,
+    0xC3,0x30,0xA1,0x20,0x7E,0xFA,0xCA,0xAA,0xC2,0x30,0x81,0x20,0xFF,0xAF,0xEB,0xB8,
+    0x03,0x39,0xA2,0x28,0xD5,0xBD,0xAF,0x8B,0x03,0x31,0xC2,0x30,0xD7,0xA8,0xF0,0x7D,
+    0xE2,0x30,0x82,0x28,0xAE,0xB6,0xDE,0x8E,0x03,0x39,0xA2,0x30,0xAE,0xA5,0xA5,0xBF,
+    0x02,0x39,0xC3,0x30,0xEE,0x7A,0x7B,0xDE,0xE3,0x30,0xA2,0x28,0xBF,0xBE,0xB7,0xB4,
+    0xE3,0x30,0x81,0x28,0x7E,0xFA,0xF8,0xFE,0xC2,0x30,0xA2,0x28,0xA5,0x35,0xFB,0xAA,
+    0xA2,0x30,0xC2,0x28,0x97,0xF5,0xFF,0x97,0xC2,0x30,0xA2,0x28,0x2F,0xAD,0xAA,0xE9,
+    0xE3,0x30,0xA2,0x28,0xEA,0x2A,0xA3,0x5B,0x03,0x39,0xC3,0x30,0xBF,0xF2,0xE3,0xA9,
+    0x03,0x39,0xC2,0x30,0x2F,0x2D,0xE5,0xB5,0x03,0x39,0xA2,0x30,0x2A,0x83,0xA7,0xEF,
+    0x03,0x39,0xE2,0x30,0x7F,0xFE,0xDB,0x95,0x23,0x39,0xE3,0x30,0x0A,0x02,0xEA,0xE9,
+    0x64,0x41,0xC3,0x30,0xA8,0x7F,0xFD,0xFF,0x03,0x39,0xC2,0x30,0xF8,0xEE,0xAB,0xAB,
+    0x03,0x39,0xC2,0x30,0x23,0xAB,0xAA,0x23,0x24,0x39,0xC2,0x30,0x7A,0xDE,0xAF,0x2F,
+    0x44,0x41,0xE3,0x30,0x9D,0xB5,0xBF,0x09,0xA5,0x51,0x23,0x41,0x22,0x3D,0xFD,0xF5,
+    0xC5,0x59,0x44,0x49,0xA0,0xBB,0xAD,0x2D,0x2A,0x83,0xC5,0x51,0xB5,0xB5,0x35,0x35,
+    0xED,0x9B,0x8C,0x8B,0x09,0xBF,0xFA,0x62,0x2E,0xA4,0x8C,0x8B,0x0A,0xAF,0xFF,0xD5,
+    0x6F,0xAC,0xCD,0x93,0x0A,0xEF,0xFD,0xDD,0xF0,0xB4,0x0D,0x9C,0x0A,0x0B,0xBD,0xD5,
+    0xF1,0xBC,0x8F,0xAC,0xFC,0xE2,0xE2,0xB5,0xD1,0xB4,0x70,0xAC,0x7E,0xEF,0xAE,0xB8,
+    0xB0,0xB4,0x4F,0xA4,0xDF,0xFA,0x8A,0x8A,0x8F,0xAC,0x2D,0xA4,0xF6,0xFE,0xE8,0x28,
+    0x6F,0xAC,0x2E,0xA4,0xAA,0xCF,0xEA,0xFE,0x4F,0xA4,0x0E,0x9C,0x7E,0xBE,0xFB,0x5A,
+    0x64,0x59,0x23,0x51,0x27,0xA7,0xE7,0xAE,0x64,0x59,0x43,0x51,0x2F,0x80,0x60,0x72,
+    0x64,0x51,0x02,0x49,0xFA,0x78,0xFE,0x5E,0x22,0x49,0xE1,0x40,0xA8,0xA0,0x82,0xFB,
+    0x23,0x49,0xE2,0x40,0xAB,0xEC,0x7A,0xAE,0x23,0x49,0xE2,0x40,0xFA,0x9B,0x29,0x2F,
+    0x25,0x6A,0xE2,0x40,0xF5,0xBD,0x35,0x37,0x8A,0x9B,0xE8,0x82,0x81,0x81,0x03,0x82,
+    0x69,0x9B,0x09,0x8B,0xEA,0xEA,0x6A,0xEA,0x49,0x93,0xE8,0x8A,0x6F,0x7E,0xBF,0x2A,
+    0xCB,0xA3,0xE8,0x8A,0xBD,0x0F,0x02,0x0A,0xEB,0xA3,0x86,0x7A,0x00,0x80,0xE0,0x78,
+    0xAA,0x9B,0x46,0x72,0x78,0x5E,0x55,0x55,0x67,0x7A,0x26,0x6A,0xED,0x3B,0x8B,0x8B,
+    0x46,0x72,0xA4,0x59,0xE0,0xE0,0x70,0x5C,0xC5,0x61,0x22,0x41,0x82,0xA2,0xFA,0x77,
+    0xA5,0x51,0x23,0x41,0xF8,0x3F,0xAD,0x8B,0x84,0x51,0x44,0x49,0xF4,0xB6,0xAF,0xEF,
+    0x64,0x49,0x23,0x41,0xA2,0xB6,0xAE,0xBF,0x84,0x51,0xE3,0x38,0x3F,0x2E,0xBE,0xDF,
+    0x06,0x62,0x84,0x59,0xEA,0x88,0xEA,0xE9,0xA5,0x59,0x02,0x41,0x5E,0x5E,0x5C,0x78,
+    0x03,0x41,0xC2,0x38,0x80,0xE0,0x60,0xE0,0x02,0x39,0xC3,0x30,0xE8,0xFF,0xDF,0x75,
+    0xE3,0x30,0x81,0x20,0xDA,0xBA,0xF0,0xC0,0xC2,0x28,0x61,0x18,0xF8,0x7A,0x56,0x57,
+    0xC2,0x28,0x61,0x18,0xD7,0xB5,0x0D,0xAB,0x03,0x31,0xC2,0x28,0x75,0xDD,0xDD,0x29,
+    0x44,0x39,0xA2,0x28,0xDD,0xF7,0xBF,0x02,0x23,0x39,0xC2,0x30,0x75,0x6A,0x58,0xE8,
+    0xE3,0x30,0x81,0x30,0xA2,0x78,0xEE,0xE8,0xE3,0x38,0xA2,0x28,0xEF,0xF5,0xED,0xA2,
+    0x03,0x39,0xC2,0x30,0xED,0xBD,0xAB,0x8D,0x03,0x39,0xC2,0x30,0xB7,0xEB,0x02,0xAB,
+    0x23,0x39,0xC2,0x30,0xFB,0xFB,0x68,0x7A,0x04,0x39,0xA2,0x28,0xE8,0xA0,0xFA,0xED,
+    0xE3,0x30,0xA2,0x28,0x5E,0xFC,0xFE,0xB3,0xC2,0x30,0x81,0x28,0x2F,0xFF,0x7A,0x20,
+    0xC2,0x28,0x82,0x28,0x00,0x80,0xAD,0xFA,0xA2,0x28,0x81,0x20,0x08,0x28,0x3E,0xF5,
+    0xE2,0x30,0xA2,0x28,0x5F,0xE5,0xBD,0xAD,0xE3,0x30,0xA2,0x28,0x83,0xFB,0x8E,0x83,
+    0xE3,0x30,0xA2,0x28,0xAE,0xAF,0x8F,0x0E,0x02,0x39,0xA2,0x28,0xB8,0xEE,0xFF,0xFD,
+    0x03,0x31,0xA1,0x28,0x2F,0xAF,0xBD,0x2F,0x24,0x31,0xC2,0x30,0xF6,0xFF,0xAB,0x2F,
+    0x03,0x31,0xA2,0x30,0xAB,0xAA,0x28,0xA0,0xE3,0x30,0xC2,0x28,0xC8,0x88,0x8A,0x83,
+    0x04,0x31,0xC2,0x30,0xBB,0x5D,0x5F,0xFF,0x24,0x39,0xC3,0x28,0x27,0xB7,0xBF,0xEB,
+    0x23,0x39,0xE3,0x30,0x27,0xB5,0x37,0xBF,0x85,0x49,0x23,0x41,0xBF,0xA7,0x2B,0xF5,
+    0x06,0x5A,0x64,0x49,0x0D,0xA5,0xF7,0xF5,0x8C,0x8B,0x06,0x5A,0x95,0x35,0x35,0x25,
+    0xED,0x9B,0xAD,0x93,0x73,0xFB,0xD7,0x62,0xAC,0x93,0x6B,0x8B,0x2B,0x58,0xF0,0x68,
+    0xED,0x9B,0x6B,0x8B,0xA2,0x8B,0xA5,0xD5,0x0E,0x9C,0xAC,0x93,0x02,0x2D,0xA7,0xA7,
+    0x8F,0xAC,0xED,0x9B,0x2B,0xBF,0x55,0x55,0x90,0xAC,0xED,0x9B,0x28,0xAA,0xDF,0x77,
+    0x90,0xAC,0xED,0x9B,0xA0,0xBB,0x7F,0x5D,0x6E,0xAC,0xCC,0x93,0xA0,0xFA,0x5F,0x57,
+    0x2E,0xA4,0xCC,0x93,0x88,0xFF,0xF5,0xD5,0x2E,0xA4,0xED,0x9B,0xEC,0x2D,0x2F,0xFD,
+    0x63,0x51,0x23,0x49,0xED,0xFF,0xD7,0xD5,0x43,0x51,0x23,0x49,0x00,0xAA,0xF8,0x77,
+    0x22,0x49,0x02,0x41,0x78,0xDC,0xF2,0xAA,0x23,0x49,0xE2,0x40,0xBF,0x7F,0x7E,0xB6,
+    0x23,0x49,0xE2,0x40,0xAA,0xFF,0xDF,0xDF,0x23,0x49,0xE3,0x40,0xAF,0x3F,0xCB,0xEB,
+    0x49,0x93,0x23,0x49,0x15,0x35,0x35,0x25,0x8A,0x9B,0x69,0x93,0x62,0x58,0x7C,0x5E,
+    0x8A,0x9B,0x28,0x93,0xFF,0x9F,0x3F,0x2F,0x8A,0x9B,0x29,0x93,0xF7,0xFC,0xA0,0xAA,
+    0xAB,0x9B,0x67,0x7A,0x02,0xA2,0xEA,0x58,0x49,0x8B,0x46,0x72,0x78,0x76,0xD7,0x75,
+    0x87,0x72,0x46,0x72,0xB7,0xEB,0xEA,0x2F,0xA7,0x7A,0xA5,0x59,0x8A,0xA8,0xE2,0x78,
+    0x05,0x62,0x02,0x41,0xF8,0xDE,0x77,0xD7,0x84,0x51,0x23,0x41,0xF5,0xBD,0x29,0x0F,
+    0xA4,0x51,0x64,0x49,0x7B,0x5A,0xDA,0xD7,0x84,0x49,0x44,0x49,0xB7,0xED,0xB4,0xB8,
+    0x64,0x49,0x24,0x41,0xFE,0xDE,0x7A,0x58,0x23,0x41,0xE3,0x38,0xBA,0xF0,0xF0,0xA0,
+    0xA5,0x51,0xA2,0x38,0x03,0x2B,0xBF,0xD7,0x84,0x51,0x23,0x41,0x78,0xF8,0xF8,0x79,
+    0x03,0x41,0xC2,0x38,0xBC,0xD6,0xF7,0xB8,0xE3,0x30,0xA2,0x30,0x02,0x0E,0xE8,0x70,
+    0xE3,0x30,0x61,0x18,0xA2,0xFA,0x7F,0x5F,0x81,0x20,0x41,0x18,0xB8,0xBC,0x3F,0x3D,
+    0xE3,0x30,0x81,0x20,0x2D,0x29,0x2B,0xFF,0x24,0x39,0x61,0x20,0x02,0x80,0xFB,0xFF,
+    0x44,0x41,0xA2,0x28,0x80,0xFE,0x55,0x55,0x43,0x41,0xA2,0x28,0xAA,0xAB,0xEF,0xB5,
+    0x03,0x39,0xC2,0x30,0xDE,0xA8,0xF8,0xEA,0x03,0x39,0xC2,0x30,0xFA,0xEF,0xD5,0x77,
+    0x03,0x39,0xA2,0x28,0xAB,0x8F,0xFF,0xB5,0xE3,0x38,0xC2,0x28,0xE2,0xEC,0xFE,0xE2,
+    0xE3,0x30,0x81,0x28,0xA2,0x62,0x5E,0x7E,0xE3,0x30,0x81,0x20,0x2B,0xBF,0xB5,0xA5,
+    0xE3,0x30,0xC3,0x28,0xA2,0x82,0x0F,0x0D,0x03,0x31,0xA2,0x30,0x7A,0xB2,0xEA,0x6A,
+    0xE3,0x30,0xA2,0x28,0x6D,0xFE,0xBA,0xAF,0x03,0x39,0x81,0x20,0x55,0xEE,0xA8,0x80,
+    0x03,0x39,0xA1,0x28,0xAD,0x2F,0xA2,0x82,0xE3,0x30,0xC2,0x28,0x1C,0x2E,0x9F,0xDF,
+    0xE3,0x30,0xA2,0x28,0x2A,0xEE,0xBE,0xE7,0xE3,0x30,0xA2,0x28,0xAF,0xAF,0xF5,0xDD,
+    0x03,0x31,0xC2,0x30,0xBE,0x8E,0x09,0xED,0x03,0x31,0xC2,0x28,0x08,0x78,0x72,0xE0,
+    0x03,0x39,0xC2,0x28,0x6C,0x5F,0x57,0xEF,0xE3,0x30,0xA2,0x28,0x21,0x3F,0xB8,0xA8,
+    0x23,0x31,0xC2,0x30,0xDD,0x5D,0xFF,0xF6,0x23,0x39,0xE2,0x30,0xFF,0xFD,0x7D,0x8D,
+    0x03,0x39,0xA1,0x28,0x22,0x3E,0xB8,0x9E,0x84,0x51,0x03,0x39,0xBF,0xFD,0xBF,0x09,
+    0xE5,0x59,0x44,0x41,0xB5,0xB7,0x2F,0x2B,0xAC,0x93,0x25,0x62,0x25,0x2D,0x0D,0x29,
+    0xEE,0x9B,0xAC,0x93,0x82,0x80,0x80,0xF7,0xCD,0x93,0x6B,0x8B,0x7C,0x50,0x78,0x5E,
+    0x6B,0x8B,0x0A,0x7B,0x20,0xB8,0xE8,0x62,0xED,0x9B,0x4B,0x83,0x0A,0x2B,0x29,0xAD,
+    0x0D,0x9C,0xAC,0x93,0xA0,0x8B,0xAA,0x7F,0xED,0x9B,0xCD,0x93,0x88,0x02,0xA8,0xFD,
+    0xED,0x9B,0xAC,0x93,0xF8,0xAB,0x7B,0x5F,0xCD,0x93,0x8C,0x8B,0x28,0x80,0x08,0x2F,
+    0xCD,0x93,0x8C,0x8B,0x28,0xBA,0xEF,0xEB,0x0E,0x9C,0xAC,0x93,0x0B,0xBF,0xB5,0xF5,
+    0x43,0x49,0x02,0x49,0xAA,0xFE,0x57,0xD7,0x23,0x49,0x02,0x41,0x81,0x7A,0xFB,0xE9,
+    0x23,0x49,0xE2,0x40,0xE3,0xCB,0x98,0x56,0x02,0x41,0xE2,0x38,0x08,0xCC,0x72,0x72,
+    0x02,0x41,0xC2,0x38,0x2A,0x0A,0x23,0x3B,0x23,0x49,0xE2,0x40,0xEF,0xFB,0xAB,0x2B,
+    0x6A,0x93,0x03,0x49,0x25,0x25,0x25,0xB5,0x8A,0x9B,0xE8,0x82,0x20,0x20,0xA2,0x55,
+    0x8A,0x9B,0xE8,0x82,0xE2,0x7A,0x7E,0x55,0x6A,0x93,0x87,0x7A,0x0A,0xAF,0xFF,0x7F,
+    0x29,0x93,0xE5,0x61,0x70,0xDC,0x5E,0x57,0x46,0x6A,0xE5,0x61,0x00,0x2B,0xAA,0xFD,
+    0xC8,0x7A,0x84,0x59,0x2A,0xAA,0xFA,0x5F,0x67,0x72,0x43,0x49,0x70,0x5E,0x77,0xD5,
+    0x63,0x49,0x02,0x41,0xFE,0x6A,0xDC,0x3E,0xA5,0x51,0x02,0x41,0x8B,0xAD,0xAD,0xB8,
+    0x84,0x51,0x64,0x49,0xA7,0x09,0x79,0x6B,0x84,0x51,0x24,0x41,0xF0,0x7A,0xFE,0xEE,
+    0x64,0x49,0x03,0x41,0xA8,0xEA,0xEE,0x5E,0x64,0x41,0x03,0x41,0x7B,0xFF,0x7F,0x5D,
+    0x23,0x41,0xC2,0x38,0x5A,0x6A,0xEA,0xA8,0x44,0x49,0xC2,0x38,0x0D,0x2D,0x0B,0xAA,
+    0x43,0x49,0xC2,0x30,0xFE,0xF8,0xDE,0xDE,0x03,0x39,0x81,0x28,0x68,0x78,0x78,0xFA,
+    0xA2,0x28,0x61,0x20,0x57,0x5E,0xF6,0xB6,0xC2,0x28,0x41,0x18,0xBD,0xAF,0x8B,0x2A,
+    0xA2,0x28,0x81,0x20,0x9D,0xCD,0xA1,0xBA,0xC2,0x28,0x81,0x20,0xAF,0xBF,0xFE,0xDF,
+    0xA2,0x28,0x81,0x20,0xA2,0xFF,0xFB,0x5B,0xE3,0x30,0x81,0x28,0x25,0xB5,0xF5,0xD5,
+    0x03,0x39,0xC2,0x30,0xBA,0xFB,0xF5,0xB9,0xE2,0x30,0xA2,0x28,0x78,0x7C,0xF8,0xCA,
+    0xE3,0x30,0xA2,0x30,0x35,0xB5,0xE7,0xAF,0xE3,0x30,0xA1,0x28,0x88,0xAA,0xFB,0x59,
+    0xE3,0x30,0x81,0x28,0xFE,0xE0,0xFB,0x7F,0xC2,0x28,0x61,0x20,0x8B,0xAA,0x02,0x0A,
+    0xE3,0x30,0xA2,0x28,0xBF,0xAB,0xAD,0x27,0x03,0x39,0xA2,0x30,0xF2,0xEB,0xEF,0xAF,
+    0x03,0x39,0xA2,0x28,0xEF,0xAD,0xBF,0x23,0x03,0x39,0xA2,0x28,0xEB,0xB2,0xA8,0xD8,
+    0x23,0x39,0xC2,0x30,0xB9,0xEF,0x1F,0xBF,0x23,0x39,0xC2,0x30,0xDF,0x57,0x76,0xF2,
+    0x03,0x31,0xA1,0x28,0xB7,0x3F,0x2E,0xAF,0x03,0x31,0xA2,0x28,0x7F,0xDE,0x58,0xEA,
+    0x04,0x31,0xA2,0x28,0xAA,0xB7,0xD7,0x57,0x04,0x31,0xC2,0x30,0xFA,0x7A,0xF6,0xDD,
+    0x03,0x31,0xA2,0x28,0x8A,0xE6,0xFB,0xAB,0x03,0x31,0xC2,0x28,0xDF,0xDD,0xFF,0x2B,
+    0x03,0x31,0xE2,0x30,0x85,0x8B,0xE2,0x58,0x23,0x39,0xE2,0x30,0x87,0x2F,0xF5,0xD5,
+    0x23,0x39,0xE2,0x30,0x5E,0xFB,0xFF,0x3B,0xA5,0x51,0x02,0x39,0xAD,0xAD,0xAF,0x0F,
+    0x88,0x72,0x63,0x49,0x95,0xF5,0xB5,0x2F,0x8C,0x93,0xA9,0x7A,0x09,0x01,0xF9,0x7E,
+    0x8C,0x8B,0x68,0x6A,0x00,0x80,0xDF,0x57,0x8C,0x8B,0x06,0x62,0x80,0xA8,0x5F,0xF7,
+    0x2A,0x7B,0x06,0x5A,0x00,0xFA,0x55,0xFF,0x8B,0x8B,0x27,0x62,0x0A,0xAF,0xD5,0xFF,
+    0x8C,0x93,0x27,0x62,0xA0,0x7E,0x5F,0x7F,0xCD,0x93,0x47,0x62,0x2B,0xD5,0x55,0x55,
+    0xAD,0x93,0x47,0x62,0x00,0x02,0xAD,0x95,0xAC,0x93,0x4B,0x83,0x02,0xAB,0x23,0xBD,
+    0xAC,0x93,0x6C,0x8B,0x00,0x00,0x8B,0xE9,0xCD,0x93,0x6B,0x8B,0x2E,0xAB,0xB7,0xFF,
+    0x03,0x49,0x22,0x41,0x80,0xAA,0xAA,0x82,0x23,0x49,0xE2,0x40,0xB0,0xAB,0xCE,0xBF,
+    0x23,0x41,0xE2,0x40,0x95,0xFA,0x12,0xE2,0x23,0x41,0xE2,0x40,0xDB,0xBB,0xAA,0xA2,
+    0x23,0x49,0xE2,0x40,0xD7,0xBF,0xEA,0xBA,0x43,0x49,0x02,0x41,0xEF,0xFE,0x7F,0x5B,
+    0x63,0x51,0xE2,0x40,0x2F,0xFD,0x57,0x5F,0x66,0x72,0x22,0x49,0x0B,0x25,0xB5,0xB5,
+    0xA7,0x7A,0xE4,0x61,0x00,0xAE,0xFD,0x5D,0xC7,0x82,0x64,0x51,0xA0,0xE2,0x7B,0x7F,
+    0xC5,0x61,0xC2,0x40,0x00,0xAA,0x7E,0x5F,0xC4,0x61,0x03,0x49,0x00,0x82,0x09,0x2D,
+    0xA4,0x59,0x43,0x49,0x58,0x7C,0xE8,0x80,0x84,0x51,0x23,0x49,0xAD,0xBD,0x0B,0x82,
+    0xA5,0x51,0x43,0x49,0x95,0x3F,0x8D,0xCA,0xA5,0x51,0x44,0x49,0xA0,0xAE,0xBE,0x77,
+    0x84,0x49,0x23,0x41,0xE8,0xAA,0xFA,0xDE,0x64,0x51,0x44,0x49,0xEB,0x55,0x79,0x8D,
+    0xE6,0x61,0x23,0x49,0x55,0x95,0x2D,0x02,0x06,0x6A,0x23,0x41,0x75,0x2A,0xA0,0xAA,
+    0xA5,0x59,0x23,0x41,0x55,0x58,0xE0,0x60,0x64,0x49,0xE2,0x38,0xFE,0x78,0xFA,0x7F,
+    0x23,0x41,0xC2,0x30,0xDE,0xF8,0xE2,0xFA,0x03,0x39,0xA2,0x28,0x78,0x60,0x42,0x4B,
+    0x03,0x31,0x61,0x20,0xF7,0xAF,0x0D,0x2D,0xE3,0x30,0x81,0x20,0xF7,0xA0,0xE0,0xE8,
+    0xC2,0x28,0x82,0x20,0xF8,0xE0,0xE8,0xBA,0xC2,0x28,0x81,0x20,0xDD,0xDD,0x9F,0x3F,
+    0x24,0x39,0x81,0x28,0x75,0x5D,0xED,0x80,0xC2,0x30,0x61,0x28,0xBF,0xBD,0xBF,0xE0,
+    0x24,0x41,0xA2,0x30,0xE9,0x89,0x0B,0x09,0x43,0x41,0xA1,0x30,0x7F,0xFA,0xFA,0xE8,
+    0xE2,0x38,0xA2,0x30,0xF7,0x57,0x57,0x5A,0x03,0x31,0xA1,0x28,0x75,0xF5,0xAD,0x0F,
+    0x24,0x39,0x81,0x28,0xD5,0x7F,0xAA,0x00,0x03,0x39,0x81,0x28,0xFD,0x5D,0xFF,0xA8,
+    0x04,0x31,0x82,0x28,0x2F,0x35,0x3F,0xAB,0x03,0x31,0xC2,0x30,0xFA,0x92,0xB0,0x62,
+    0xE3,0x30,0xA2,0x30,0x00,0x00,0xBB,0xDA,0x03,0x39,0xA2,0x30,0x6A,0xB8,0xFA,0xFA,
+    0x03,0x31,0xA2,0x30,0xBF,0x3D,0xBF,0xBB,0x24,0x39,0xE3,0x30,0xDE,0xFA,0xFE,0xFA,
+    0x02,0x31,0xA1,0x28,0xEE,0xFA,0xF2,0xF8,0xE2,0x30,0xC2,0x28,0xF8,0xDC,0xD5,0x7D,
+    0xC2,0x28,0xA2,0x28,0x38,0x00,0x02,0xE9,0xE3,0x30,0xA1,0x28,0xA2,0x03,0x2E,0xE7,
+    0x03,0x31,0xE3,0x30,0x55,0xDF,0x97,0x95,0x03,0x31,0xC2,0x28,0x2B,0xAF,0xAE,0xFE,
+    0x03,0x31,0xE2,0x30,0x6A,0x4A,0xB7,0x75,0x03,0x39,0xC2,0x30,0xAE,0x3F,0x1E,0x1C,
+    0x64,0x49,0x03,0x39,0xE7,0xAF,0x27,0x25,0xA5,0x51,0x03,0x41,0x09,0xAF,0xBE,0x22,
+    0x4E,0xA4,0xC5,0x59,0xB5,0xB5,0x25,0x2D,0xAF,0xB4,0xCC,0x9B,0xFD,0xAB,0xA2,0x80,
+    0xAF,0xB4,0x8B,0x93,0x57,0xEA,0x88,0x02,0x8F,0xB4,0x2A,0x83,0x55,0xEA,0x00,0x00,
+    0x2E,0xAC,0xE9,0x7A,0x55,0x7F,0x7E,0x78,0x0A,0x7B,0xA8,0x72,0xDA,0xF8,0xE8,0x78,
+    0xE9,0x7A,0x67,0x62,0xFA,0xA0,0xBB,0xD7,0xE9,0x72,0x67,0x6A,0xF7,0xF6,0xFE,0xB2,
+    0xC9,0x72,0x46,0x62,0x5D,0x7F,0xFE,0xE8,0x6B,0x83,0x27,0x62,0x03,0x2F,0xD5,0x57,
+    0x6B,0x8B,0x47,0x62,0x00,0x00,0x00,0x09,0x8C,0x8B,0x4B,0x83,0x0D,0x8B,0xEC,0xE8,
+    0x03,0x49,0xE2,0x40,0x10,0x82,0x52,0x7F,0x03,0x41,0xE2,0x40,0x26,0x26,0x86,0x3C,
+    0x23,0x49,0xE2,0x40,0x7F,0xAE,0xAA,0xAE,0x23,0x49,0x02,0x41,0xD5,0x3F,0x7C,0xE7,
+    0x43,0x49,0x02,0x41,0xD7,0xD4,0x7A,0xE8,0x23,0x49,0x03,0x41,0x29,0x02,0x77,0x5F,
+    0x23,0x49,0xC2,0x38,0xF8,0xE2,0xCA,0x8F,0x84,0x59,0xC2,0x40,0x2F,0x3D,0xFF,0xFF,
+    0x26,0x6A,0x43,0x49,0x8A,0xA2,0xFD,0x55,0xC5,0x59,0xC2,0x40,0xA8,0xFE,0x7F,0x5F,
+    0x03,0x41,0xC2,0x40,0x8A,0xCE,0xBF,0xEF,0x05,0x62,0x03,0x49,0xAD,0x2D,0x8D,0x2D,
+    0xE5,0x61,0x84,0x59,0x7E,0x7A,0x6A,0xEC,0xE6,0x59,0x64,0x51,0xF5,0xDD,0xFF,0xEB,
+    0xA5,0x51,0x64,0x49,0xE2,0x60,0x78,0x5A,0x85,0x51,0x22,0x39,0xEA,0xAA,0xAA,0xA0,
+    0x64,0x49,0x23,0x41,0xFA,0xE8,0xA8,0x22,0x66,0x72,0x43,0x49,0xAD,0x2B,0x8A,0xA2,
+    0x46,0x6A,0x22,0x49,0xA0,0xEC,0xFA,0x7A,0xA4,0x59,0xE2,0x38,0xA8,0xF8,0xDE,0x55,
+    0xA4,0x51,0x03,0x41,0x70,0x7A,0xFA,0x6F,0x23,0x41,0xC2,0x30,0xEE,0x96,0xFF,0x2A,
+    0x03,0x39,0xA2,0x30,0x6A,0xFE,0xF8,0xFE,0xC2,0x30,0x82,0x28,0xBB,0xD7,0xEC,0xEA,
+    0xE3,0x30,0x82,0x20,0x25,0xA7,0xAD,0xAD,0xC3,0x30,0xA2,0x28,0x7C,0xA8,0x8B,0xFB,
+    0x44,0x41,0xA2,0x28,0xD5,0xB5,0x25,0x0D,0x64,0x49,0xC3,0x30,0xAD,0xAA,0x28,0x82,
+    0x45,0x41,0xE3,0x38,0xB8,0x54,0x56,0x5E,0x23,0x41,0xC2,0x38,0xDE,0xA8,0xA2,0xFA,
+    0x23,0x41,0xE2,0x38,0x3D,0x97,0xBB,0x7F,0x64,0x49,0x03,0x41,0xFA,0x82,0x0B,0x95,
+    0x44,0x49,0xA1,0x28,0x7E,0x58,0x70,0xE8,0xE3,0x30,0x81,0x28,0x0B,0xBA,0xD7,0xAE,
+    0x44,0x39,0xA2,0x30,0x2A,0xBF,0xAD,0xF7,0x24,0x39,0xC2,0x28,0xE8,0xBE,0xFF,0x7B,
+    0xE3,0x30,0x81,0x28,0x08,0x08,0xBE,0xFD,0xE3,0x30,0xA2,0x28,0x40,0xF8,0xEA,0xFF,
+    0xC2,0x30,0xA2,0x28,0x92,0xF6,0xAF,0x58,0x03,0x39,0xC2,0x28,0xAB,0x8E,0xED,0x5D,
+    0xE2,0x30,0xA2,0x28,0xB8,0xBE,0xFA,0xAF,0x03,0x31,0xC2,0x28,0x8F,0x2F,0x97,0xD7,
+    0xE3,0x30,0xC2,0x28,0xEC,0x62,0xAC,0xEF,0xE2,0x30,0xA1,0x28,0xBE,0x3F,0xBA,0xEA,
+    0xE2,0x30,0xA2,0x28,0x62,0x8E,0xAA,0x8B,0x03,0x31,0xA1,0x28,0xFD,0xAF,0x8B,0x2B,
+    0x03,0x31,0xC2,0x30,0x8E,0x2E,0x37,0x57,0x03,0x39,0xC2,0x30,0xFA,0x80,0x0A,0xAF,
+    0x03,0x39,0xC2,0x30,0xD7,0xBE,0xB8,0xAA,0x03,0x39,0xC2,0x30,0xBF,0xDB,0x72,0x62,
+    0x64,0x49,0xA2,0x30,0x2F,0x2F,0x3F,0xBF,0xE9,0x7A,0x23,0x41,0xFF,0xFF,0xBD,0x35,
+    0x11,0xC5,0xA9,0x72,0x25,0x2D,0x03,0x02,0x30,0xCD,0x8E,0xB4,0x7F,0xFF,0x7E,0xE8,
+    0xAF,0xBC,0x6E,0xAC,0x2B,0x28,0xEF,0x94,0xD0,0xBC,0x6E,0xB4,0xAA,0x88,0xEB,0x77,
+    0x8F,0xB4,0x2B,0x83,0x78,0xE0,0xA0,0x88,0x2D,0xA4,0xA9,0x72,0x77,0x7F,0xFE,0x60,
+    0xC9,0x72,0x46,0x62,0xDF,0x7C,0x6A,0xA8,0xE9,0x72,0x67,0x6A,0xAF,0xA9,0xAD,0x2F,
+    0x0A,0x7B,0xA8,0x6A,0x7F,0xE2,0x8A,0x0A,0xE9,0x7A,0x06,0x5A,0x7A,0xFA,0xC8,0xA8,
+    0xEA,0x7A,0xE6,0x59,0x35,0xD5,0x5F,0x7E,0x6B,0x83,0xA5,0x49,0x00,0x03,0xBD,0x55,
+    0x23,0x49,0xE2,0x40,0xFB,0xE8,0xAA,0x79,0x23,0x49,0xE2,0x40,0xCB,0x5B,0x56,0xB7,
+    0x23,0x49,0xE2,0x40,0x8A,0xAA,0x7B,0xDC,0x23,0x49,0xE2,0x40,0xAF,0x00,0xAA,0xEB,
+    0x23,0x41,0xE2,0x40,0x80,0x00,0xA2,0x68,0x23,0x49,0xC2,0x38,0xE0,0xFE,0xBF,0xAE,
+    0x03,0x41,0xE2,0x40,0x09,0x43,0x5E,0xBD,0x23,0x49,0xE2,0x40,0xAA,0xBB,0xFF,0xE5,
+    0x02,0x41,0xE2,0x40,0x23,0xAF,0x09,0x9D,0x23,0x49,0xC2,0x38,0x7A,0xDC,0xEE,0xFF,
+    0x03,0x49,0xE2,0x40,0x05,0xBF,0x97,0x7D,0x26,0x6A,0x03,0x49,0x2D,0x29,0x0D,0x0D,
+    0x06,0x62,0xA4,0x59,0x7C,0xD8,0xE8,0xAA,0xE5,0x61,0x84,0x51,0x5D,0xF8,0x6A,0x7C,
+    0x84,0x51,0x03,0x41,0xA0,0xBA,0xDE,0xFE,0x64,0x49,0x23,0x41,0x80,0x80,0x9A,0xD5,
+    0x64,0x49,0x03,0x41,0xAA,0xE2,0x6A,0xC7,0x26,0x6A,0x03,0x49,0x03,0x0B,0xAD,0xA5,
+    0xE5,0x61,0x61,0x28,0xE0,0x78,0x7E,0x7A,0xC2,0x38,0x61,0x28,0x8A,0xA5,0xD5,0xAC,
+    0x23,0x41,0xC2,0x30,0xC3,0xF9,0x7D,0xD5,0x23,0x39,0xC2,0x30,0x22,0xA2,0xF2,0x52,
+    0x03,0x39,0x82,0x20,0xA0,0x8A,0xEA,0x7F,0xC2,0x28,0x61,0x20,0xA2,0xA8,0xBF,0xF5,
+    0xC2,0x28,0x82,0x20,0x2A,0x0F,0x0D,0x2F,0xE2,0x28,0x81,0x28,0xEE,0x9A,0xBC,0xFA,
+    0x44,0x41,0xC2,0x30,0x25,0x25,0x2D,0xAD,0x44,0x49,0x81,0x28,0x00,0xA0,0x5A,0x5E,
+    0x44,0x49,0x61,0x20,0xA8,0xAA,0xF7,0xFD,0x03,0x41,0x81,0x28,0xA8,0xAA,0xAA,0x7D,
+    0x03,0x41,0xC2,0x38,0xF0,0xC0,0x02,0x89,0x23,0x41,0xC2,0x38,0x37,0xBF,0x3F,0xEB,
+    0x23,0x41,0xE2,0x38,0xE0,0xFF,0xBE,0xFE,0x03,0x41,0xA2,0x28,0x5F,0x7E,0xF8,0xF8,
+    0xE3,0x30,0x61,0x28,0xAA,0xBC,0x7B,0xEA,0xE3,0x30,0x81,0x28,0xE8,0xF7,0xD5,0xF5,
+    0xC2,0x28,0x82,0x28,0xDA,0x82,0x03,0xB5,0xE3,0x30,0xA2,0x28,0x75,0xEA,0x82,0x3F,
+    0x03,0x31,0x82,0x28,0x7F,0x7E,0xE8,0xA2,0xC2,0x28,0x81,0x28,0xE3,0xAD,0xFF,0xA0,
+    0xE3,0x30,0xA2,0x28,0x9D,0x77,0xAF,0xAF,0x03,0x31,0xC2,0x30,0x67,0xEF,0xCA,0xFB,
+    0x03,0x31,0xC2,0x28,0xD5,0xD5,0x8F,0x0E,0x02,0x31,0xC2,0x28,0xA5,0x95,0xFF,0xDB,
+    0x03,0x31,0xC2,0x28,0xEE,0xB8,0x6E,0xEE,0x24,0x39,0xC2,0x30,0x3B,0x2B,0x2B,0xED,
+    0x23,0x39,0xC2,0x30,0x56,0xDE,0xDE,0x3F,0x23,0x39,0xE2,0x30,0x55,0x5D,0xD5,0xBC,
+    0x24,0x39,0xC2,0x30,0xFD,0xB7,0xFF,0xFC,0x03,0x41,0xE3,0x30,0x77,0xEA,0xAA,0x2F,
+    0x64,0x49,0xC2,0x38,0xFD,0xA5,0xAB,0x2F,0x0C,0xA4,0x85,0x51,0xB5,0x35,0x3D,0x2D,
+    0x31,0xCD,0xAF,0xB4,0x03,0x89,0x29,0xA9,0x31,0xC5,0xD0,0xBC,0x80,0x00,0xAA,0xF9,
+    0x10,0xC5,0x8E,0xB4,0x7E,0xE0,0x00,0x08,0x10,0xC5,0x4D,0xAC,0xD7,0x5E,0xF8,0x80,
+    0xD0,0xBC,0x4E,0xAC,0x57,0xF5,0xF5,0xFC,0x6E,0xAC,0x6B,0x8B,0x78,0xE8,0xE0,0x80,
+    0xCC,0x9B,0x88,0x6A,0x5F,0x7E,0xF8,0x88,0x0A,0x7B,0x87,0x6A,0xBD,0xBF,0xBF,0xA8,
+    0x2A,0x83,0xC8,0x72,0x29,0x2F,0x2E,0x2F,0x4B,0x83,0xA9,0x6A,0x7A,0xAA,0xA0,0x82,
+    0x2A,0x83,0x27,0x5A,0x7F,0xFA,0xE8,0xA0,0x88,0x6A,0x64,0x41,0x5F,0x7A,0xE8,0xE0,
+    0x23,0x49,0xE2,0x40,0xDD,0xFB,0xAF,0xBB,0x23,0x49,0xE2,0x40,0xAF,0xFF,0xFA,0xA8,
+    0x23,0x49,0xE2,0x40,0xFF,0xEF,0xCB,0xCB,0x23,0x49,0x02,0x41,0x6F,0xF5,0x91,0x87,
+    0x03,0x41,0xC2,0x38,0xA8,0xA0,0xE0,0xBC,0x03,0x41,0xE2,0x40,0x2C,0x33,0x87,0xFF,
+    0x03,0x41,0xE2,0x38,0x0A,0x0E,0xB5,0xDE,0x03,0x41,0xE2,0x40,0x6B,0xB3,0x20,0xBB,
+    0x03,0x41,0xC1,0x38,0xAE,0x00,0x88,0xCF,0x23,0x41,0xE2,0x40,0xF5,0xEF,0xBF,0xFD,
+    0x02,0x41,0xC2,0x40,0xA0,0x80,0xB8,0xF8,0x46,0x6A,0x02,0x41,0x8D,0x2D,0x0D,0x2D,
+    0x26,0x6A,0xC5,0x59,0xDE,0xD8,0xD8,0xFA,0x05,0x62,0x03,0x41,0xE8,0xF8,0x7A,0x7C,
+    0x44,0x49,0xE2,0x38,0x0A,0xA8,0xFD,0x7F,0x44,0x41,0x03,0x39,0x2E,0x2A,0x0D,0x89,
+    0x44,0x41,0x03,0x41,0xEA,0xEA,0x62,0xAA,0x64,0x49,0xC2,0x30,0x2F,0xFA,0x5E,0x5E,
+    0xE5,0x59,0xE3,0x38,0x82,0x8A,0xFD,0x75,0x03,0x39,0x81,0x20,0x78,0xE8,0xFC,0x7A,
+    0xC2,0x30,0xA1,0x20,0xA7,0xAF,0x8B,0xAD,0xE3,0x30,0x81,0x20,0xF0,0xFA,0x6F,0x7A,
+    0xC2,0x28,0x61,0x20,0x72,0x57,0x55,0xD5,0xA2,0x28,0x61,0x20,0xA5,0x2F,0x3B,0x2A,
+    0xE3,0x30,0x81,0x28,0xBB,0xAB,0xAD,0x2F,0xC2,0x28,0xA2,0x28,0x00,0x33,0x1A,0xC0,
+    0x24,0x39,0xA2,0x28,0x0D,0xF7,0x7F,0x57,0xE3,0x30,0x81,0x20,0x78,0xB8,0xFF,0xF5,
+    0xC2,0x28,0x61,0x20,0xA9,0x88,0x00,0xA0,0xA1,0x28,0x61,0x20,0xFE,0xAE,0xEE,0xAA,
+    0xE3,0x38,0x81,0x28,0x03,0x29,0xB5,0xBD,0x03,0x41,0xC2,0x30,0x0B,0xA2,0x22,0xB5,
+    0x23,0x41,0xE2,0x38,0x5A,0xAA,0x88,0x08,0x23,0x41,0xA2,0x30,0xFE,0x5A,0x58,0xF8,
+    0xC2,0x30,0x82,0x28,0xA8,0xA8,0xAA,0x2D,0xE3,0x30,0x81,0x28,0x6A,0xCA,0x0B,0xAF,
+    0xE3,0x30,0x81,0x28,0x55,0x55,0xFE,0x62,0xC2,0x28,0x82,0x28,0x2F,0xED,0x95,0xBD,
+    0x03,0x39,0xA2,0x28,0xCB,0xED,0xEF,0xEB,0xC2,0x28,0x81,0x28,0xAA,0xFE,0x7E,0xEE,
+    0xE3,0x30,0x81,0x20,0xAB,0xBF,0x95,0xAF,0xE3,0x30,0xA2,0x28,0xBE,0x9F,0xD7,0xB7,
+    0x03,0x39,0xA2,0x28,0x2A,0x8B,0xAD,0xAF,0x03,0x31,0xA2,0x28,0xEA,0xAE,0x8D,0x79,
+    0x03,0x31,0xC2,0x28,0xAB,0x5B,0x7E,0x7D,0xC2,0x30,0xE3,0x28,0xBA,0xE8,0x0A,0xA2,
+    0x23,0x41,0xC2,0x30,0xF9,0xAF,0x09,0xAF,0x23,0x41,0x03,0x39,0x5E,0x67,0x96,0x16,
+    0x23,0x41,0xE3,0x38,0x72,0x22,0x0B,0x3E,0x44,0x49,0xE2,0x38,0xF5,0x2B,0x23,0xA2,
+    0xC6,0x59,0x23,0x41,0xB5,0x2F,0x3B,0x0B,0xEE,0xA3,0xE6,0x59,0x2D,0xA5,0xBF,0xEF,
+    0xF0,0xBC,0x2B,0x8B,0x00,0x0B,0xBD,0x55,0xF0,0xBC,0xAB,0x93,0x00,0x00,0x02,0xA5,
+    0x10,0xC5,0xF0,0xBC,0x8D,0xA7,0xAF,0xBD,0x10,0xC5,0xCF,0xBC,0xA8,0xA0,0xBE,0x7E,
+    0xF0,0xBC,0x8F,0xB4,0x78,0x08,0x22,0x0A,0xF0,0xBC,0x4E,0xAC,0x77,0x78,0x60,0x80,
+    0x4E,0xAC,0xAC,0x93,0x5F,0xFA,0xEA,0xA8,0x2D,0xA4,0x09,0x7B,0x5F,0xE8,0x02,0x80,
+    0x2D,0x9C,0x0A,0x7B,0x55,0x5F,0xE2,0x00,0xCC,0x93,0x2A,0x7B,0xF5,0x7D,0xFF,0xA0,
+    0xCB,0x93,0xEA,0x7A,0x7F,0xFE,0xFB,0x80,0x8B,0x8B,0x27,0x5A,0x7F,0x7A,0xFA,0xA8,
+    0x23,0x49,0xE2,0x38,0xBF,0x8B,0xAB,0x6C,0x23,0x49,0xE3,0x40,0x8A,0xAA,0xA6,0xED,
+    0x23,0x49,0xE3,0x40,0xA2,0xEE,0xBE,0xFE,0x23,0x49,0xE2,0x40,0xF0,0x60,0xA8,0xDA,
+    0x03,0x41,0xC2,0x38,0x7A,0x9C,0x6C,0xFA,0x03,0x41,0xC2,0x38,0xAB,0x0E,0xA3,0x77,
+    0x03,0x41,0xC2,0x38,0x3E,0xAB,0xEB,0xEF,0x03,0x41,0xC2,0x38,0xB2,0xFE,0xFC,0xEC,
+    0xE2,0x40,0x03,0x31,0x28,0x08,0x80,0x2A,0x03,0x41,0xE2,0x40,0xED,0x59,0xED,0xC3,
+    0x03,0x41,0xC2,0x40,0x3A,0x28,0xEF,0x2A,0x67,0x72,0x02,0x41,0x2D,0x25,0x25,0x25,
+    0x46,0x6A,0xE5,0x61,0xDC,0x78,0x5A,0xF8,0xE5,0x59,0x03,0x41,0x78,0x78,0x5C,0x58,
+    0x44,0x41,0xE3,0x38,0xAF,0x8F,0xED,0xF9,0x23,0x39,0xE3,0x38,0xF2,0x78,0x8F,0xAE,
+    0x43,0x41,0xE3,0x30,0x82,0xBF,0xDF,0x7F,0x44,0x41,0xE2,0x30,0x7A,0xF8,0xAA,0xED,
+    0x23,0x39,0xC2,0x30,0x7F,0x7F,0x78,0xA2,0xE2,0x30,0xA1,0x28,0xEE,0xFF,0x57,0xF8,
+    0xE3,0x28,0xA2,0x28,0xAF,0x7F,0x55,0xA6,0xE2,0x28,0x81,0x20,0x5E,0x5F,0xFB,0x20,
+    0xE3,0x30,0x81,0x20,0xD5,0xAD,0x2A,0xAA,0xE3,0x30,0xA2,0x28,0xD5,0xE5,0xBB,0xAE,
+    0xE3,0x30,0xA2,0x28,0x2F,0xBF,0xEA,0xA3,0xE3,0x30,0xA2,0x28,0x6A,0xE8,0x20,0x28,
+    0xE3,0x30,0xA2,0x28,0xDF,0xEE,0xB8,0xEC,0xE2,0x28,0xA2,0x28,0x55,0x57,0xF6,0xF2,
+    0xC2,0x28,0x81,0x20,0x63,0x6B,0xAF,0xD7,0xC2,0x28,0x82,0x20,0xEF,0xEE,0xC8,0xCE,
+    0xC2,0x28,0x82,0x20,0x8B,0x8A,0xBB,0x57,0xC2,0x30,0x61,0x20,0x2A,0xBF,0xBF,0xF6,
+    0x24,0x41,0x81,0x20,0x0A,0xAF,0xDD,0xD7,0x44,0x41,0xC2,0x30,0x60,0xE0,0xE3,0xFD,
+    0xE3,0x30,0x81,0x28,0xF5,0xFF,0xEA,0x88,0xE2,0x30,0xA2,0x28,0x5D,0x55,0xD7,0xAA,
+    0xE3,0x30,0xA2,0x28,0xBF,0x35,0x2B,0xA0,0x23,0x39,0xA2,0x28,0xFD,0xAA,0x8E,0x0B,
+    0x44,0x41,0xA2,0x30,0x5D,0x7F,0xA2,0x02,0x24,0x39,0x81,0x28,0xD7,0x5F,0xFE,0x88,
+    0x03,0x31,0xA2,0x28,0x89,0x0D,0xEB,0xAF,0xE3,0x30,0xA2,0x28,0xBE,0x78,0x78,0xFE,
+    0xC2,0x28,0x82,0x28,0x00,0xEA,0xEB,0xFA,0xC2,0x28,0x81,0x28,0xA2,0x83,0x0D,0xC5,
+    0xC2,0x30,0xA2,0x28,0xB5,0x57,0x7F,0xE9,0xC2,0x28,0x82,0x28,0x00,0x0B,0x0D,0x2E,
+    0x03,0x39,0xC2,0x28,0xBB,0xDD,0x6F,0x8A,0x02,0x39,0xC2,0x30,0x2A,0xBD,0xFD,0xA7,
+    0x64,0x49,0xE2,0x38,0xB7,0x8F,0x8D,0xBD,0xA5,0x51,0x03,0x41,0xFD,0x3D,0x27,0xAF,
+    0x47,0x6A,0x64,0x51,0xBD,0xAD,0x2F,0x2F,0x0A,0x83,0x68,0x6A,0x09,0x09,0x0B,0x0B,
+    0x0A,0x83,0xE9,0x7A,0x33,0x3D,0xA8,0x30,0xAC,0x9B,0xE9,0x7A,0x2B,0xB7,0xDD,0x55,
+    0xD0,0xBC,0xEA,0x82,0x0A,0xBF,0xFD,0xD5,0xCF,0xBC,0x4B,0x8B,0x00,0x00,0x2F,0xD5,
+    0xF0,0xBC,0x0E,0xA4,0x00,0x00,0x00,0x2D,0x10,0xC5,0xAE,0xB4,0x7A,0x6A,0xEA,0xC8,
+    0x8E,0xB4,0x2D,0xA4,0x77,0xD6,0xDC,0xB8,0x6E,0xAC,0x0D,0xA4,0xF5,0xDE,0xFA,0xE8,
+    0x4E,0xAC,0x0D,0xA4,0xAD,0x9E,0xFE,0x0A,0x4E,0xAC,0x2D,0x9C,0x7A,0xBB,0xAB,0x0A,
+    0x6E,0xAC,0x2D,0xA4,0x55,0xF2,0xE2,0xA8,0x4E,0xA4,0x6B,0x83,0x7E,0xA0,0x80,0x00,
+    0x03,0x41,0xC1,0x38,0xF0,0x98,0xF8,0xAA,0x43,0x41,0xE2,0x40,0x77,0xF5,0xFF,0x9F,
+    0x23,0x49,0xE3,0x40,0xA2,0x2F,0xEB,0x7B,0x03,0x41,0xC2,0x38,0x80,0xA0,0xF2,0x60,
+    0x02,0x41,0xC2,0x38,0xFB,0xDB,0xF3,0x3E,0x03,0x41,0xC2,0x38,0xEA,0x79,0xBA,0xAE,
+    0x03,0x41,0xE2,0x38,0x3D,0x2D,0xEF,0x55,0x03,0x41,0xC2,0x38,0xEE,0xEB,0x8D,0x3B,
+    0x03,0x41,0xE2,0x38,0x1E,0xB3,0xFF,0x6F,0x02,0x41,0xC2,0x38,0xAA,0x9F,0xBE,0xFB,
+    0x03,0x41,0xC1,0x38,0xAA,0x9A,0xFA,0xEF,0x46,0x6A,0xE2,0x40,0x25,0x35,0x25,0x35,
+    0x66,0x72,0xE5,0x61,0xFA,0xFC,0x78,0xE8,0x05,0x62,0xE2,0x38,0x58,0x7A,0x5C,0x78,
+    0x03,0x39,0xE2,0x30,0x02,0x2B,0xBE,0x97,0x24,0x39,0xE3,0x38,0xE2,0xAF,0xF7,0x76,
+    0x23,0x39,0x03,0x39,0x6D,0xF6,0xAD,0x55,0x44,0x41,0xE2,0x30,0xFE,0x82,0xAA,0xFF,
+    0x43,0x39,0xE3,0x38,0xAD,0x7F,0xFA,0x8A,0x24,0x39,0xE3,0x30,0x7B,0xA2,0xBD,0xF8,
+    0x24,0x39,0xC2,0x28,0x7D,0xEE,0xA8,0x8A,0x23,0x39,0xE3,0x30,0x5D,0xD7,0xAF,0xAA,
+    0x23,0x39,0xE3,0x30,0x5D,0xCE,0xAE,0xBF,0x24,0x39,0xC2,0x30,0xDF,0xFA,0xE2,0xAA,
+    0x03,0x39,0xC2,0x28,0xE5,0xFA,0x20,0x20,0x03,0x31,0xC2,0x28,0xB8,0xDA,0xDC,0xA0,
+    0xE3,0x30,0xC2,0x28,0xF4,0xCA,0x2E,0x3A,0xE3,0x30,0xC2,0x28,0xFF,0xBB,0xC2,0x08,
+    0xE3,0x28,0x82,0x20,0x7F,0xE8,0xAA,0xA0,0xC2,0x28,0x82,0x20,0x7F,0xEE,0xE8,0x88,
+    0xC3,0x28,0x82,0x20,0x75,0x7F,0x6B,0xE2,0xA2,0x28,0x81,0x20,0xA7,0x55,0x16,0x80,
+    0xA2,0x28,0x82,0x20,0x3B,0x07,0xAE,0xFD,0x03,0x39,0x82,0x28,0x8F,0x89,0x0F,0xFD,
+    0xC2,0x30,0xE3,0x28,0xA0,0x82,0x0B,0x08,0x03,0x39,0xC2,0x30,0xEF,0x5C,0xAB,0x3D,
+    0x03,0x39,0xC2,0x30,0xEA,0x83,0xEA,0x70,0x23,0x41,0xA2,0x28,0x02,0xAB,0xBD,0xF5,
+    0x64,0x49,0xE3,0x38,0xA2,0x03,0x8B,0xD5,0x64,0x41,0xC2,0x30,0xFE,0x7C,0x78,0x6A,
+    0xE3,0x30,0xA2,0x28,0xFB,0xB5,0xB5,0xFE,0xE3,0x38,0xC2,0x28,0xD1,0xEA,0xB3,0x4F,
+    0xC2,0x30,0x81,0x28,0xFE,0xDA,0xBE,0x8A,0xE2,0x30,0xA2,0x28,0x55,0xF5,0xDB,0xA3,
+    0xE2,0x30,0xA2,0x28,0x69,0x6B,0xEF,0xAA,0xE3,0x30,0x81,0x20,0xAF,0x39,0x2B,0xAF,
+    0x23,0x39,0xE2,0x30,0x09,0x29,0x9D,0x5F,0x64,0x49,0xE2,0x30,0xE7,0xBF,0x2F,0xBF,
+    0x43,0x41,0x03,0x39,0x35,0xAE,0x9B,0xF8,0x26,0x62,0x23,0x41,0xFD,0xFF,0xBF,0x2D,
+    0xA8,0x72,0x84,0x51,0x2D,0x2D,0x2B,0x0A,0x0A,0x83,0xA8,0x7A,0x29,0xEB,0xCD,0xFB,
+    0x0A,0x83,0xC9,0x7A,0xAA,0xF9,0xDD,0xA5,0x2B,0x83,0xCA,0x7A,0xFB,0x8B,0xA9,0xB7,
+    0x2A,0x83,0xC9,0x7A,0xFB,0xB6,0xB0,0x28,0x4B,0x8B,0xEA,0x7A,0x39,0x2E,0xBB,0xDF,
+    0x2E,0xA4,0x2A,0x83,0x2F,0xF5,0x55,0x55,0xF0,0xBC,0x4A,0x8B,0x02,0xAF,0xD5,0x55,
+    0xD0,0xB4,0x8B,0x93,0xA8,0xAA,0xAB,0xD5,0xB0,0xB4,0x2E,0xA4,0xFE,0xAA,0xAA,0xA9,
+    0x8F,0xB4,0x4E,0xAC,0x5F,0xFA,0x7A,0xCA,0x8F,0xB4,0x4E,0xAC,0xD7,0xEB,0x3A,0xB2,
+    0x8F,0xB4,0x4E,0xAC,0xFD,0xBE,0x3A,0x00,0xAF,0xB4,0x4E,0xAC,0x5F,0xF7,0xAF,0x80,
+    0x43,0x41,0xE2,0x40,0x7D,0xEF,0x7F,0xD5,0x03,0x41,0xE2,0x38,0x7A,0xB6,0x4E,0xCA,
+    0x03,0x41,0xC2,0x38,0x0A,0xBA,0xBB,0x69,0x02,0x41,0xC2,0x38,0x6E,0xF8,0x5A,0xAD,
+    0x03,0x39,0xA1,0x38,0x9B,0x2A,0xAA,0x23,0xE2,0x40,0x03,0x39,0x8B,0xAB,0x3B,0x2B,
+    0x03,0x41,0xC2,0x38,0x9A,0xAA,0x78,0xE3,0x02,0x41,0xC2,0x38,0xEB,0x77,0xAF,0xED,
+    0x03,0x41,0xC2,0x38,0xFA,0xDF,0xAE,0x8D,0x03,0x41,0xE2,0x38,0xCF,0x96,0x55,0xFA,
+    0x03,0x41,0xC2,0x38,0x73,0x7E,0xFC,0xBE,0x46,0x6A,0xE2,0x40,0x25,0x35,0x35,0x35,
+    0x87,0x72,0x05,0x62,0x78,0x7A,0x58,0x7E,0x05,0x62,0xE2,0x38,0x58,0x78,0x58,0x78,
+    0x03,0x39,0xC2,0x30,0xFF,0x9F,0x8A,0x23,0x23,0x39,0xE3,0x30,0xF7,0xBA,0x87,0xE7,
+    0x23,0x39,0xE2,0x30,0xEB,0xBB,0x7A,0xFD,0x23,0x39,0x03,0x39,0xB2,0x98,0x36,0x55,
+    0x44,0x41,0x03,0x39,0x8B,0x2A,0xEF,0xFF,0x44,0x41,0x03,0x39,0x6E,0x8E,0x8B,0xDA,
+    0x44,0x39,0x03,0x39,0x5F,0x60,0x5A,0x6E,0x24,0x39,0xE2,0x30,0x0A,0xEF,0xFF,0xDF,
+    0x24,0x39,0xE3,0x38,0xE0,0xCA,0x2D,0x99,0x44,0x41,0xE3,0x30,0x57,0xF5,0xAB,0xED,
+    0x24,0x41,0xE3,0x30,0xBF,0xDE,0xBE,0xCA,0x03,0x39,0xE2,0x30,0x80,0x2E,0x3E,0x5E,
+    0x03,0x31,0xA2,0x30,0xA8,0x2A,0x80,0xAB,0x03,0x31,0xE3,0x30,0xB5,0xC6,0x7C,0x5B,
+    0x03,0x31,0xC3,0x28,0x78,0x5A,0xBE,0xB2,0x03,0x31,0xC3,0x28,0xF7,0x6A,0xEA,0xFF,
+    0xE3,0x30,0xC3,0x28,0x55,0x7F,0xFF,0xB7,0x03,0x31,0xA2,0x20,0x77,0xF7,0xFF,0xFB,
+    0xE3,0x28,0x81,0x20,0xD7,0xFF,0xFA,0xAA,0xA2,0x28,0x82,0x20,0xB8,0xFC,0x3A,0xA2,
+    0xC2,0x30,0x81,0x20,0x2B,0xAF,0x55,0x57,0xE3,0x30,0x81,0x28,0x0A,0x2A,0x0F,0x27,
+    0x03,0x39,0xA2,0x30,0x6A,0x48,0xC3,0xE2,0xE3,0x30,0xA2,0x30,0xBF,0xFB,0xEA,0xAB,
+    0xE2,0x30,0xC2,0x30,0xF5,0x77,0x5D,0xA2,0x02,0x39,0xA1,0x28,0xE8,0x6F,0xEA,0x2F,
+    0x03,0x39,0xA2,0x28,0xF7,0xB5,0xEF,0xA8,0xE3,0x30,0xC2,0x30,0xEF,0xB3,0x8D,0xC1,
+    0xE3,0x30,0xA2,0x28,0xF7,0xFF,0xCE,0xAD,0x44,0x41,0xA1,0x28,0xFD,0xED,0x2F,0x3F,
+    0x64,0x41,0xC2,0x28,0x77,0xEF,0xAE,0x2A,0x24,0x39,0xA1,0x28,0xF5,0xFE,0xAA,0x08,
+    0x23,0x39,0xE3,0x30,0xB5,0xA5,0x0F,0x0A,0x43,0x41,0x03,0x39,0x2A,0xFA,0xD2,0x23,
+    0xC5,0x51,0xC2,0x38,0xFF,0xAF,0x2B,0x02,0x67,0x6A,0x63,0x49,0x3D,0x8B,0x0A,0x02,
+    0xC9,0x7A,0x68,0x6A,0x2D,0xB5,0xB7,0xBD,0xC9,0x7A,0x88,0x72,0xA8,0x8B,0xFD,0xEB,
+    0xEA,0x7A,0x88,0x72,0x0B,0x89,0xA2,0xBF,0xE9,0x7A,0xA9,0x72,0xBC,0xAB,0xB7,0xAE,
+    0x2A,0x83,0xC9,0x7A,0xA9,0x3F,0xFB,0xB5,0x0A,0x83,0xC9,0x7A,0xAC,0x28,0x7F,0xFC,
+    0x2A,0x83,0xC9,0x7A,0xAA,0x8F,0xB7,0x77,0x2A,0x8B,0xC9,0x7A,0x20,0xFC,0xDE,0xAA,
+    0x4B,0x8B,0xEA,0x7A,0x2A,0xBB,0x7F,0x7F,0xED,0x9B,0xC9,0x7A,0x02,0xAF,0xF7,0x5D,
+    0x4E,0xAC,0xEA,0x82,0x00,0x02,0xAF,0xFD,0x6E,0xAC,0x6B,0x8B,0x00,0x00,0x02,0xAD,
+    0xAF,0xB4,0x4E,0xAC,0xAA,0xA2,0xAB,0xA9,0xD0,0xB4,0x8F,0xB4,0xAF,0xEF,0xEE,0xBF,
+    0x23,0x41,0xE2,0x40,0xDB,0xEF,0xAF,0x42,0x02,0x41,0xC2,0x38,0xEA,0xA0,0x48,0xCA,
+    0x03,0x39,0xC2,0x38,0xDE,0xFF,0xAB,0x2E,0x03,0x41,0xC2,0x38,0x3F,0xA6,0x8A,0x02,
+    0x03,0x41,0xC2,0x38,0xCD,0xAE,0xAB,0xBE,0x03,0x41,0xC2,0x38,0xFF,0xEC,0xDE,0xFE,
+    0x02,0x41,0xC2,0x38,0xBB,0xFA,0xFA,0xBA,0x03,0x41,0xC2,0x38,0x78,0xEF,0x5E,0xBF,
+    0xE2,0x38,0xC2,0x38,0x82,0x00,0x30,0x00,0x03,0x39,0xC2,0x38,0xBA,0x32,0xBF,0xBF,
+    0x03,0x41,0xC2,0x38,0xBF,0xF7,0x9E,0x7E,0x46,0x6A,0xE2,0x38,0x35,0x35,0x35,0x35,
+    0x67,0x72,0x06,0x62,0x7C,0x7A,0xEE,0xE8,0x05,0x62,0xE2,0x38,0x78,0x78,0x78,0x58,
+    0x03,0x39,0xC2,0x30,0x82,0x4C,0x8A,0xF8,0x03,0x39,0xC2,0x30,0xB6,0xE5,0xBA,0xA2,
+    0x03,0x39,0xE2,0x28,0xAB,0xBB,0x2D,0xA7,0x03,0x39,0xC2,0x30,0x0E,0xB6,0xBE,0x2E,
+    0x23,0x39,0xC2,0x30,0x2A,0xAD,0xFF,0xEE,0x23,0x41,0xE3,0x30,0xA0,0x88,0xB3,0xED,
+    0x44,0x41,0x03,0x39,0x78,0xBD,0x55,0x55,0x23,0x39,0xE3,0x38,0x9D,0x7A,0x6A,0xE6,
+    0x23,0x39,0xE3,0x30,0xA9,0x99,0xBD,0xBD,0x44,0x41,0xE3,0x30,0xF5,0xDF,0xFE,0x8B,
+    0x44,0x41,0xE3,0x30,0x8B,0xA7,0xDE,0xBE,0x24,0x41,0xE3,0x38,0x76,0xB8,0xBB,0x6F,
+    0x23,0x39,0xE3,0x30,0x7B,0xB7,0x8A,0xAA,0x24,0x39,0xE3,0x30,0xB5,0xFF,0xF4,0xEF,
+    0x23,0x31,0xE3,0x30,0xBE,0xA2,0x6F,0xD5,0x03,0x31,0xC3,0x28,0xEA,0xAA,0xAA,0x00,
+    0x03,0x31,0xC2,0x28,0xB5,0xFF,0xFF,0xAA,0xE3,0x30,0xC2,0x28,0xCE,0xA8,0x00,0xF0,
+    0xC3,0x30,0xE2,0x28,0x0E,0xBE,0xAE,0xB8,0xE2,0x30,0xA2,0x20,0x5F,0x5A,0xAA,0xFE,
+    0xC2,0x28,0x82,0x20,0xEB,0xEE,0xBA,0xAA,0xC2,0x28,0x81,0x20,0xBF,0xFE,0xE0,0xB0,
+    0x03,0x39,0x81,0x20,0x02,0x29,0xBD,0x75,0x03,0x31,0xA2,0x28,0x7F,0xF0,0xAA,0xED,
+    0x03,0x31,0xC2,0x30,0xAF,0xAB,0xC0,0x80,0x23,0x31,0xC2,0x30,0xF5,0xF7,0xDF,0x7B,
+    0x03,0x31,0xC2,0x30,0x5E,0x5B,0xEE,0x6F,0x03,0x31,0xC2,0x30,0x6F,0x6F,0x83,0x82,
+    0x03,0x39,0xA2,0x28,0x2D,0x2B,0x2E,0x27,0x03,0x39,0xE2,0x30,0x16,0x29,0x0F,0xAC,
+    0x44,0x41,0xE2,0x30,0x0A,0xEE,0xFB,0x60,0x23,0x39,0xC2,0x28,0x20,0x2A,0xFE,0xF7,
+    0x23,0x39,0xC2,0x30,0xE0,0x2E,0xBA,0xDF,0x84,0x51,0xE2,0x30,0xBF,0xBF,0xBD,0x2D,
+    0x27,0x62,0x84,0x49,0xAD,0xA9,0xAF,0x2B,0x68,0x6A,0xE6,0x59,0x2F,0xBD,0x2D,0x09,
+    0xA8,0x72,0x68,0x6A,0x85,0x8D,0xBD,0xFB,0xC9,0x7A,0x88,0x6A,0xEF,0x1B,0xDD,0xF7,
+    0xC9,0x7A,0x88,0x72,0x3F,0xB8,0xFA,0x5D,0xEA,0x7A,0xA9,0x72,0xC0,0xFB,0xE5,0x55,
+    0x0A,0x83,0xA9,0x72,0xA7,0xBD,0xCD,0x7D,0x0A,0x83,0xA9,0x72,0x2E,0x3D,0xBF,0x97,
+    0x0A,0x83,0xA9,0x72,0xE8,0x88,0x2A,0xB7,0x2A,0x83,0xC9,0x7A,0x8F,0xE5,0xFD,0xFF,
+    0x2B,0x83,0xC9,0x7A,0xAB,0x2F,0xFB,0xDF,0x2B,0x8B,0xEA,0x7A,0x77,0x76,0x62,0xFF,
+    0x2A,0x83,0xE9,0x7A,0xAD,0xF7,0xFF,0x05,0xAC,0x93,0xE9,0x7A,0x2B,0xDD,0x55,0x57,
+    0x6E,0xAC,0x0A,0x83,0x0A,0xBF,0xF5,0x55,0xAF,0xB4,0x4A,0x8B,0x00,0x0A,0xAF,0x55,
+    0x03,0x41,0xC2,0x38,0xC0,0xC0,0x72,0x7C,0xE2,0x40,0xC2,0x30,0xF2,0x38,0xAA,0xA9,
+    0x03,0x41,0xC2,0x38,0xAB,0x0A,0xAB,0x0F,0x03,0x39,0xC2,0x38,0x2A,0xEB,0xCA,0x68,
+    0x22,0x39,0xC2,0x38,0xF6,0x7F,0x7F,0xBF,0x03,0x39,0xC2,0x38,0x6E,0xC2,0xBB,0xB2,
+    0x03,0x41,0xC2,0x38,0x2F,0xBF,0xEC,0xEC,0x03,0x41,0xC2,0x38,0x7F,0xE2,0x8F,0xEB,
+    0x22,0x39,0xC2,0x38,0xFE,0x7F,0x5F,0xDF,0xE2,0x38,0xC2,0x38,0x33,0x00,0xB3,0xB1,
+    0xE2,0x38,0xC2,0x38,0xE0,0xF8,0xDA,0x28,0x47,0x6A,0xE2,0x38,0x35,0x25,0x35,0x35,
+    0x67,0x72,0xC5,0x59,0xE0,0xE0,0x60,0x78,0xA5,0x59,0x02,0x39,0x78,0x5C,0x7E,0x56,
+    0x03,0x39,0xC2,0x30,0x7C,0x8A,0xB8,0x9C,0x03,0x39,0xE3,0x30,0xBE,0xD7,0xD7,0xF1,
+    0x03,0x31,0xC2,0x28,0xBE,0xDC,0xA2,0x7E,0x03,0x31,0xE2,0x30,0x7F,0x65,0x75,0x72,
+    0x03,0x31,0xC2,0x30,0x8A,0xAA,0x8B,0xFA,0x03,0x31,0xE3,0x30,0x8E,0x24,0x2D,0x59,
+    0x23,0x39,0xE3,0x30,0xAF,0xDD,0xDF,0xE7,0x03,0x39,0xC2,0x30,0x08,0xE8,0xFA,0xDA,
+    0x24,0x39,0xE3,0x30,0xAF,0xBF,0xFE,0x38,0x44,0x41,0xE3,0x30,0xBA,0xA3,0xAB,0xF7,
+    0x44,0x41,0x03,0x39,0xFF,0xEE,0x78,0x5F,0x24,0x39,0xE3,0x38,0xFB,0x88,0xBE,0xAF,
+    0x24,0x39,0xC2,0x30,0xBF,0xF6,0xE8,0xAA,0x23,0x39,0xE2,0x30,0xC3,0xFF,0xEA,0xAA,
+    0x23,0x39,0xE3,0x30,0xDF,0xFF,0xFD,0x9F,0x23,0x39,0xE3,0x30,0x37,0xFD,0xEB,0xFA,
+    0x23,0x39,0xE3,0x30,0x7E,0xFE,0xF5,0xA3,0x03,0x31,0xC2,0x30,0xFB,0xC0,0x20,0x00,
+    0x03,0x31,0xC2,0x28,0x79,0x73,0xC2,0xBA,0x03,0x31,0xC2,0x28,0x55,0xFF,0xFF,0x83,
+    0xE3,0x28,0xC2,0x28,0x65,0xC5,0xF7,0xBD,0xE2,0x28,0xA2,0x20,0x7F,0x7B,0x88,0xA2,
+    0xC2,0x28,0x81,0x20,0xBF,0xAF,0x2E,0x80,0xA2,0x28,0x81,0x20,0x2B,0xD8,0xBB,0xE8,
+    0xE3,0x30,0x61,0x20,0x02,0xAF,0xFF,0xF7,0x03,0x39,0x82,0x20,0x82,0x22,0xAF,0xFD,
+    0x03,0x39,0xC2,0x28,0xA9,0x88,0x8B,0x95,0x03,0x39,0xE3,0x30,0x42,0x62,0x5B,0x53,
+    0x03,0x31,0xA2,0x28,0x2D,0xFB,0xBA,0x0B,0x23,0x39,0xE3,0x30,0xBE,0xBB,0xBA,0x83,
+    0x23,0x39,0xA1,0x28,0xE0,0xA0,0xA8,0xDC,0xE3,0x30,0xA2,0x28,0x27,0x2A,0x20,0x83,
+    0x44,0x41,0xC2,0x28,0xD5,0xFF,0xBF,0xAD,0xC5,0x51,0x02,0x31,0xAD,0xAD,0x0B,0x0B,
+    0x27,0x62,0xA5,0x51,0x2D,0x0F,0xAF,0xAA,0x68,0x6A,0x07,0x5A,0x29,0x9F,0xB7,0xF5,
+    0x88,0x6A,0x48,0x6A,0x0C,0xA2,0x6D,0xD5,0xC9,0x7A,0x68,0x6A,0xEE,0x3E,0x09,0xAD,
+    0xC9,0x72,0x89,0x72,0xD9,0xF5,0x36,0x0A,0xC9,0x7A,0x88,0x72,0xFE,0x0E,0xEA,0x2B,
+    0xE9,0x7A,0xA9,0x72,0xEB,0xE7,0x97,0xD6,0xC9,0x7A,0xA9,0x72,0xCC,0xC2,0x88,0x24,
+    0x0A,0x83,0xA8,0x72,0xAD,0xB9,0x0B,0x2A,0x0A,0x83,0xC9,0x7A,0x3B,0x6A,0xFE,0xAE,
+    0x0A,0x83,0xA9,0x7A,0xDA,0xFB,0xAA,0x08,0xEA,0x7A,0xA9,0x7A,0x21,0x00,0x8A,0x44,
+    0x2B,0x83,0xC9,0x7A,0x27,0xD7,0xFF,0x7D,0x2A,0x83,0xA9,0x72,0xE8,0x8A,0x3A,0xFF,
+    0x2A,0x83,0xE9,0x7A,0x09,0x3D,0x2E,0x27,0x2A,0x83,0xE9,0x7A,0x00,0xE0,0x7E,0x5A,
+    0x03,0x41,0xC2,0x38,0x54,0x7F,0xDE,0x35,0x03,0x39,0xC2,0x38,0xB7,0xBA,0xA9,0xBB,
+    0x23,0x41,0xC2,0x38,0xF9,0x8B,0xFA,0xFF,0x03,0x41,0xC2,0x38,0xFE,0xEC,0x68,0xBE,
+    0x02,0x39,0xA1,0x30,0xBE,0xFA,0x37,0xEF,0x02,0x39,0xC2,0x38,0xBE,0xF6,0xEF,0x3D,
+    0xE2,0x38,0xC2,0x38,0x23,0xEB,0xC4,0xC8,0xE2,0x38,0xC2,0x38,0x2A,0xD8,0x7B,0x7C,
+    0x03,0x39,0xC2,0x38,0xEB,0xFF,0xBF,0xBA,0x03,0x39,0xC2,0x38,0xEE,0x7E,0x7F,0xFF,
+    0xE2,0x38,0xC2,0x30,0x6C,0xFC,0x7B,0xFF,0x25,0x62,0xC2,0x38,0x3D,0x35,0x95,0x95,
+    0x66,0x6A,0xA4,0x51,0xF8,0x78,0x78,0x5E,0x84,0x51,0xE2,0x30,0x7A,0x7A,0x70,0x78,
+    0x23,0x39,0xC2,0x30,0xDF,0xFF,0x9B,0xFA,0x03,0x31,0xC2,0x28,0xFA,0xEA,0xAB,0x7F,
+    0xE3,0x30,0xC2,0x28,0xBA,0x34,0x24,0xF7,0x03,0x39,0xC2,0x28,0xA2,0x5A,0xFF,0xAF,
+    0x03,0x31,0xC2,0x30,0x4B,0xEA,0xEB,0xA2,0x03,0x39,0xC2,0x28,0xEF,0x8F,0x8B,0xAA,
+    0x03,0x31,0xC2,0x30,0x83,0xA2,0xAA,0xBF,0x03,0x39,0xE3,0x30,0xEB,0x5C,0xFF,0x39,
+    0x24,0x39,0xC2,0x30,0xAC,0xBF,0xFF,0xDA,0x23,0x39,0xC2,0x30,0xA2,0xAA,0xAE,0xE7,
+    0x23,0x39,0xE3,0x30,0x88,0x2A,0xAE,0x6D,0x24,0x39,0x03,0x39,0x42,0x03,0x63,0x7D,
+    0x23,0x39,0x03,0x39,0x76,0x5E,0x77,0x57,0x23,0x39,0xE3,0x38,0xBF,0x37,0x26,0xBE,
+    0x23,0x39,0xE3,0x30,0xD7,0xE6,0x76,0xE8,0x44,0x39,0xE3,0x30,0x7F,0x5D,0xEF,0x29,
+    0x24,0x39,0xE2,0x30,0x8A,0xE2,0xF7,0xDE,0x24,0x39,0xE2,0x30,0xFF,0x7E,0xE3,0x88,
+    0x23,0x39,0xC2,0x30,0xAA,0x9A,0xB8,0x00,0x24,0x39,0xE3,0x30,0x5F,0x7C,0xF3,0xEA,
+    0x24,0x39,0xC2,0x28,0x55,0xFF,0xFA,0xE8,0x03,0x31,0xC2,0x28,0x6D,0xEA,0x8B,0xCA,
+    0xA2,0x30,0xE2,0x28,0xBF,0xFB,0xDD,0x77,0xE3,0x28,0xA2,0x20,0xF7,0x7B,0xAB,0x00,
+    0xE3,0x28,0x82,0x20,0x57,0xFE,0xAF,0xA0,0xC3,0x28,0x81,0x20,0x95,0x7F,0xEA,0x02,
+    0xC2,0x28,0x82,0x20,0x2F,0xB5,0xD5,0xBA,0x03,0x31,0x82,0x20,0x8A,0x3F,0x7D,0xF7,
+    0xE3,0x30,0x81,0x20,0x20,0xEE,0xF7,0x9D,0x44,0x39,0xA2,0x28,0x0B,0xAB,0xBD,0xF5,
+    0x03,0x39,0xC2,0x28,0x78,0xD6,0xD6,0xDF,0x23,0x39,0xE2,0x30,0x5D,0xF5,0xB5,0x2D,
+    0xE6,0x51,0x03,0x31,0x95,0xB5,0xAD,0x2F,0x06,0x5A,0xA5,0x51,0x39,0xAF,0xAA,0x8A,
+    0x27,0x62,0xC5,0x51,0xBF,0xAF,0xAD,0x27,0x68,0x6A,0x07,0x62,0x75,0xAF,0x29,0x2B,
+    0xA9,0x72,0x68,0x6A,0x7D,0xFD,0xBA,0x8E,0xC9,0x72,0x48,0x6A,0x2F,0xA7,0x3F,0x2A,
+    0xC9,0x7A,0x68,0x6A,0x88,0x2B,0xBA,0x7E,0xC9,0x7A,0x67,0x6A,0x8A,0xE8,0xA3,0x9F,
+    0xEA,0x7A,0x88,0x72,0xFE,0x22,0x2F,0xB7,0xE9,0x7A,0xA9,0x72,0x2A,0xF7,0x5C,0x8B,
+    0xE9,0x7A,0xA9,0x72,0xEE,0x8A,0xED,0xD7,0xC9,0x7A,0x88,0x72,0x3E,0xBF,0xDC,0xC3,
+    0x0B,0x83,0x88,0x72,0x8A,0xFE,0x7B,0x7B,0xEA,0x7A,0xA9,0x72,0x6E,0xAA,0x8D,0x69,
+    0xEA,0x7A,0xA9,0x72,0x02,0x02,0x6B,0xFD,0x0A,0x83,0xA9,0x72,0xAA,0x02,0x0D,0xFE,
+    0x2A,0x83,0xA8,0x72,0xAB,0xAB,0xAE,0x3D,0x0A,0x83,0xE9,0x7A,0x28,0xCB,0xAA,0x9C,
+    0x03,0x39,0xC2,0x38,0xAF,0x2F,0x37,0xAB,0x03,0x41,0xC2,0x38,0xFF,0xE3,0xEF,0xFA,
+    0x22,0x39,0xC2,0x38,0xD7,0xDB,0xFF,0x77,0x03,0x41,0xC2,0x38,0xDE,0xAE,0xB7,0xAF,
+    0x03,0x41,0xC2,0x38,0xDC,0xF8,0x7E,0xDE,0x02,0x39,0xC2,0x38,0xFA,0x9D,0xA9,0xEF,
+    0xE2,0x38,0xC2,0x38,0xC0,0x0F,0xCA,0x43,0x03,0x41,0xC2,0x38,0x6E,0x3F,0xDF,0xEB,
+    0x02,0x39,0xA1,0x30,0xAE,0xB4,0xBA,0xBB,0x02,0x41,0xA2,0x30,0xDF,0xAF,0x3B,0x2B,
+    0x03,0x41,0xA1,0x30,0xFE,0xFE,0xF8,0x7E,0x23,0x49,0xA1,0x30,0x37,0xB5,0x95,0x3D,
+    0x47,0x6A,0xA4,0x51,0xFE,0x7F,0x7D,0xF8,0xA4,0x51,0xE2,0x30,0xD8,0x78,0x70,0x70,
+    0x03,0x39,0xC2,0x30,0xA8,0x08,0x2F,0xAA,0x03,0x31,0xA3,0x30,0xAE,0x88,0x88,0x0A,
+    0x23,0x31,0xC2,0x30,0x75,0xB7,0x7F,0xF7,0x03,0x31,0xC2,0x28,0xFF,0x8B,0xFB,0xDA,
+    0x03,0x31,0xC2,0x28,0x8A,0x87,0xED,0xCA,0x03,0x31,0xA2,0x30,0x2A,0x2A,0xA2,0xAE,
+    0x03,0x31,0xA2,0x30,0x2A,0x88,0x28,0x3A,0x03,0x31,0xC2,0x28,0xAE,0xEB,0xF2,0xF2,
+    0x03,0x39,0xE3,0x30,0x3D,0x7D,0x5A,0xD7,0x23,0x39,0xE3,0x30,0xE7,0xAF,0xAF,0xD5,
+    0x23,0x39,0xE3,0x30,0x83,0xAD,0x7E,0x5F,0x23,0x39,0xE3,0x30,0x3A,0xBF,0xAB,0xFD,
+    0x23,0x39,0xE3,0x38,0xD7,0x87,0xDF,0xF7,0x24,0x41,0xE3,0x38,0xCD,0x27,0xE9,0xE5,
+    0x44,0x41,0xE3,0x38,0x7A,0xF4,0xDB,0x77,0x23,0x39,0x03,0x39,0x29,0xDF,0x57,0x55,
+    0x24,0x41,0xE3,0x30,0xFA,0xDA,0x3A,0xB2,0x23,0x39,0xE3,0x30,0x5E,0xD7,0xFA,0xFA,
+    0x44,0x41,0xC3,0x30,0xA2,0xF7,0xFF,0xFE,0x24,0x39,0xE3,0x30,0xAE,0xEA,0x2D,0xEE,
+    0x23,0x39,0xE3,0x30,0x6E,0xFE,0xBA,0x2B,0x24,0x39,0xE2,0x30,0x7A,0xDB,0xFE,0xB8,
+    0x23,0x31,0xE3,0x30,0x5B,0xDC,0xDE,0x7A,0x03,0x39,0xE3,0x28,0x7F,0xFF,0xF8,0x08,
+    0x24,0x39,0xC3,0x28,0x57,0x5F,0x5A,0xE8,0x03,0x31,0xC3,0x28,0x77,0x7D,0x2A,0x08,
+    0x03,0x31,0xA2,0x28,0x7D,0xFD,0xFA,0x88,0x03,0x31,0xC3,0x28,0x57,0x9F,0xAA,0x02,
+    0x23,0x31,0xA2,0x28,0xDD,0xEF,0xAA,0xAA,0x24,0x39,0xA2,0x28,0xBD,0xBB,0xA2,0x08,
+    0x23,0x39,0xE3,0x30,0xF7,0xDF,0xBA,0x0A,0xA5,0x49,0x03,0x31,0xBD,0xB5,0xB9,0x0F,
+    0x27,0x62,0xA5,0x49,0xF5,0xAD,0x8D,0x2F,0x26,0x62,0xE6,0x59,0xD5,0xBD,0x8A,0x36,
+    0x47,0x62,0xE6,0x59,0x85,0xBF,0xBF,0x1E,0x89,0x72,0x27,0x62,0x8D,0x29,0x2F,0xAF,
+    0xA9,0x72,0x48,0x6A,0x8B,0x8E,0x77,0x77,0xC9,0x72,0x68,0x6A,0x20,0xAA,0xBD,0xD5,
+    0xC9,0x7A,0x67,0x6A,0xFE,0x22,0xAB,0xF6,0xC9,0x7A,0x88,0x72,0x5E,0x2F,0x58,0x77,
+    0xC9,0x7A,0x88,0x72,0x21,0xEE,0xEA,0x2B,0xE9,0x7A,0x88,0x72,0xBA,0xB2,0xBA,0x7E,
+    0xE9,0x7A,0xA9,0x72,0xEA,0x8E,0xBE,0xB7,0xE9,0x7A,0xA8,0x72,0x89,0xAF,0xB8,0xBA,
+    0x0A,0x7B,0xA9,0x72,0xD7,0xF5,0xDF,0xE3,0x0A,0x7B,0xA9,0x72,0xA9,0xA2,0xFF,0xF7,
+    0xEA,0x7A,0x89,0x72,0x9F,0xF2,0xE8,0x3A,0xEA,0x7A,0xA9,0x72,0x38,0xEF,0x7E,0x8B,
+    0xEA,0x7A,0xA9,0x72,0x3D,0xBA,0x00,0x0B,0x0A,0x7B,0xC9,0x7A,0xA0,0xE9,0x25,0x8B,
+    0x03,0x41,0xC2,0x38,0xAA,0xDB,0xBA,0xAF,0x03,0x41,0xE2,0x38,0xD6,0x5B,0x7D,0x6B,
+    0x03,0x41,0xC2,0x38,0xDE,0x8F,0x8E,0xEB,0x03,0x41,0xC2,0x38,0xED,0xDF,0xDA,0xAA,
+    0x03,0x41,0xA2,0x30,0xAE,0x2A,0xEF,0xDA,0x23,0x39,0xC2,0x38,0x7F,0xFF,0x9D,0xFF,
+    0x23,0x39,0xC2,0x38,0x57,0xFF,0xF5,0xFB,0xE2,0x38,0xC2,0x38,0x00,0xE8,0xD8,0xE0,
+    0xE2,0x38,0xC2,0x38,0xAE,0xC8,0xBF,0xB7,0xE2,0x38,0xC2,0x38,0xEA,0x0F,0x8A,0x4C,
+    0xE2,0x38,0x81,0x30,0xE8,0xF8,0x9E,0xAB,0x67,0x6A,0xC2,0x30,0xF5,0xB5,0x35,0x35,
+    0xE8,0x7A,0xA5,0x59,0xFA,0xF8,0xE8,0x70,0xC5,0x59,0xE2,0x30,0x58,0x78,0xFA,0x7F,
+    0x03,0x39,0xE2,0x30,0x5C,0x7C,0x5A,0x5F,0x03,0x31,0xE3,0x30,0x2C,0x5D,0x65,0xFD,
+    0x03,0x31,0xE3,0x30,0x4D,0x47,0x69,0xCD,0x03,0x31,0xE3,0x30,0x59,0x7D,0x1D,0x6D,
+    0xE3,0x30,0xC2,0x30,0x22,0x82,0x3A,0xA3,0x03,0x31,0xC2,0x30,0x2F,0x3F,0xBF,0xFF,
+    0x03,0x31,0xC2,0x28,0xEE,0xFF,0xEA,0xEE,0x03,0x31,0xC2,0x30,0x9F,0xEA,0xFE,0x2B,
+    0x03,0x31,0xA2,0x30,0x2A,0xAA,0xE6,0xBE,0x03,0x31,0xC2,0x30,0xAA,0xEA,0xFB,0xFF,
+    0x03,0x31,0xC2,0x30,0xBE,0xFA,0x0B,0xF5,0x03,0x39,0xE3,0x30,0x8D,0xAB,0xDA,0xED,
+    0x03,0x39,0xE2,0x30,0xAA,0xDF,0xA2,0xB7,0x03,0x39,0xC2,0x30,0x87,0xB5,0x3E,0xF2,
+    0x24,0x39,0xE3,0x30,0xFF,0x57,0xEA,0xCF,0xE3,0x38,0x03,0x31,0xFE,0xAE,0xA7,0xF7,
+    0x23,0x39,0xE3,0x30,0xEB,0xB9,0xB3,0xF9,0x24,0x39,0xE3,0x38,0xFD,0xBD,0xF2,0xA6,
+    0x24,0x39,0xE3,0x38,0xFA,0xBC,0xAF,0xBE,0x24,0x39,0xE3,0x38,0x6B,0xAF,0xAF,0xA8,
+    0x24,0x39,0xC2,0x30,0x2B,0x8A,0xFA,0xEA,0x23,0x39,0xE2,0x30,0x00,0x1B,0xDF,0xFE,
+    0x44,0x39,0x03,0x31,0xF3,0xAB,0xA5,0x97,0x65,0x41,0x03,0x31,0x55,0xFE,0xFE,0xEA,
+    0x44,0x39,0x03,0x39,0x5F,0xF2,0xEA,0xEA,0x24,0x39,0xE3,0x30,0xE5,0xEA,0x2A,0x02,
+    0x24,0x39,0xE3,0x30,0xFF,0xBB,0x80,0x20,0x24,0x41,0x03,0x31,0xFD,0x7D,0xFE,0xAC,
+    0x44,0x41,0xE3,0x30,0xF5,0xEE,0xAF,0x2A,0x64,0x41,0x04,0x39,0xF5,0x55,0xDF,0x2A,
+    0xC5,0x51,0x24,0x39,0x55,0xF5,0xD5,0x2F,0x06,0x5A,0x65,0x41,0x95,0xA5,0xAB,0x00,
+    0x07,0x5A,0xC6,0x59,0x7F,0xCB,0x2B,0xA0,0x47,0x6A,0xC6,0x59,0xBE,0xAD,0xAB,0x00,
+    0x68,0x6A,0x06,0x5A,0xB7,0xA8,0xA8,0xBE,0x88,0x6A,0x47,0x62,0xA9,0xED,0x3A,0x8A,
+    0x88,0x6A,0x48,0x6A,0xBC,0x74,0xAE,0x38,0xA9,0x72,0x68,0x6A,0x55,0xA5,0x37,0xCE,
+    0xA9,0x72,0x68,0x6A,0x6E,0xDF,0xFB,0x0F,0xA8,0x72,0x68,0x6A,0x2A,0x00,0x01,0x03,
+    0xC9,0x7A,0x88,0x6A,0xBE,0xAC,0x3E,0xA9,0xCA,0x72,0x68,0x6A,0xAB,0xE7,0xAE,0xAB,
+    0xEA,0x7A,0x88,0x6A,0x7E,0x7B,0xDB,0xFA,0xE9,0x7A,0x88,0x6A,0xEA,0x0B,0xF7,0xFD,
+    0xE9,0x72,0x88,0x6A,0x0F,0xAC,0xEB,0xEF,0xEA,0x7A,0x88,0x72,0x8A,0x3E,0x0D,0xBA,
+    0xEA,0x7A,0xA8,0x72,0x09,0x59,0xAA,0x02,0x0A,0x7B,0xA9,0x72,0xBF,0xAF,0xFD,0xDC,
+    0x0A,0x7B,0xA9,0x72,0x3A,0x02,0xAB,0xB7,0x0A,0x7B,0xA9,0x72,0x9E,0xAF,0xAE,0x22,
+    0x02,0x39,0xC2,0x38,0xB6,0xA4,0xEF,0xCE,0x03,0x41,0xC2,0x38,0xAA,0xEB,0xFF,0x57,
+    0x03,0x39,0xC2,0x38,0x0E,0xAE,0xEF,0xE9,0x03,0x39,0xA1,0x30,0xAE,0xA8,0xAE,0xF5,
+    0xE2,0x38,0xC2,0x38,0xD3,0x0D,0x0B,0x28,0xE2,0x38,0xC2,0x30,0xF8,0x2E,0x04,0x27,
+    0x02,0x41,0xC2,0x38,0xEB,0x6A,0xFE,0xEF,0xE2,0x38,0xC2,0x38,0xAB,0xEE,0x35,0xCE,
+    0xE2,0x38,0xA1,0x30,0x08,0x82,0x60,0x6A,0xE2,0x38,0xA2,0x30,0x7A,0x7E,0xFE,0x9F,
+    0xE2,0x38,0xA2,0x30,0x09,0xA2,0x80,0x88,0x46,0x6A,0xC2,0x30,0x35,0x95,0x55,0x55,
+    0xA7,0x72,0xC3,0x38,0xE8,0xFF,0x5D,0x55,0x24,0x41,0xC2,0x30,0xEA,0xE8,0xAE,0xA5,
+    0x03,0x39,0xC2,0x30,0xA2,0xE8,0xBC,0xFF,0x03,0x31,0xA2,0x30,0x2A,0x88,0xCA,0x2A,
+    0x03,0x31,0xC2,0x28,0xBE,0xBA,0xFA,0xFF,0x03,0x31,0xC2,0x30,0xE3,0xBE,0x8A,0xFA,
+    0xE3,0x30,0xC2,0x28,0xE9,0x00,0xAA,0xAB,0xE3,0x30,0xC2,0x28,0x2D,0xA8,0x02,0x8C,
+    0x03,0x31,0xC2,0x28,0xBA,0x27,0x07,0xEE,0x23,0x39,0xC3,0x30,0xEF,0xBF,0xAF,0xD8,
+    0x03,0x39,0xC2,0x28,0xDE,0xBC,0xAA,0xEE,0xA2,0x38,0x03,0x31,0xDF,0x76,0x7F,0xFF,
+    0x02,0x39,0xC3,0x30,0xB7,0x7F,0xEA,0xFB,0x24,0x39,0xC2,0x28,0xBF,0xBD,0x3F,0xBD,
+    0x03,0x39,0xC2,0x28,0xA7,0xFC,0xE3,0x8A,0x03,0x31,0xE3,0x30,0xFB,0xDF,0x77,0x95,
+    0xC3,0x38,0x03,0x31,0xDF,0x57,0x5F,0xE9,0x24,0x39,0xE3,0x30,0xAF,0x2E,0xBF,0xD7,
+    0x24,0x39,0xE3,0x30,0xF5,0xEE,0xAF,0x2E,0x24,0x39,0xE3,0x38,0xBF,0xEA,0xBC,0xBA,
+    0x24,0x39,0xE3,0x38,0xAF,0xAE,0x9F,0xBA,0x24,0x39,0xE3,0x38,0xEF,0x2B,0xCE,0xA7,
+    0x24,0x41,0x03,0x31,0x9A,0x7A,0xFE,0xA3,0x45,0x39,0x03,0x39,0xF7,0x5D,0xB6,0x97,
+    0x23,0x39,0x03,0x39,0x23,0xB2,0xA8,0x0D,0x64,0x41,0x03,0x39,0xFD,0x55,0x55,0x73,
+    0x44,0x41,0xE3,0x30,0x22,0xA5,0xB7,0xAA,0x85,0x41,0xE3,0x38,0xEA,0xAA,0x0B,0xAD,
+    0x85,0x49,0x24,0x39,0xD5,0x2F,0x8A,0x20,0xA6,0x51,0x24,0x39,0xD5,0xAE,0x0B,0xAE,
+    0xA5,0x51,0x24,0x39,0xB7,0xAE,0x00,0x0A,0xC6,0x51,0x44,0x41,0xDD,0xBF,0x2B,0x0A,
+    0x27,0x62,0x85,0x49,0xAD,0xBF,0x89,0x0A,0x27,0x62,0xE6,0x59,0xB8,0x29,0x03,0xAA,
+    0x48,0x6A,0x06,0x62,0x5F,0x99,0x3E,0x22,0x67,0x6A,0x06,0x5A,0x8E,0xA3,0xBB,0x9E,
+    0x68,0x6A,0x06,0x62,0xAA,0x26,0x2A,0xAA,0xA8,0x6A,0x47,0x62,0x2F,0xB2,0xBA,0xDB,
+    0xA9,0x72,0x27,0x62,0xF8,0xAA,0xF6,0x7F,0xA8,0x72,0x68,0x6A,0x05,0x0D,0x0E,0xF9,
+    0xEA,0x7A,0x88,0x6A,0xF5,0x7D,0xFB,0x8D,0xC9,0x72,0x88,0x72,0x98,0xFF,0xD6,0xBE,
+    0xA8,0x72,0x68,0x6A,0xE0,0xF8,0xEA,0xE0,0xA9,0x72,0x68,0x6A,0xAA,0xEA,0x75,0x7D,
+    0xC9,0x72,0x68,0x6A,0xAA,0xBB,0xAB,0x7D,0xE9,0x7A,0x89,0x6A,0xAD,0xFF,0xFB,0x2F,
+    0xC9,0x72,0x88,0x72,0xBC,0x24,0x2B,0x0B,0xC9,0x7A,0x67,0x6A,0xAB,0xF2,0xFC,0xD8,
+    0xC9,0x72,0x88,0x6A,0x80,0x29,0x9D,0xEF,0xEA,0x72,0x88,0x6A,0xD2,0xBE,0xBE,0xBE,
+    0xEA,0x7A,0x88,0x72,0x29,0xAF,0x9E,0xF0,0xE9,0x7A,0xA9,0x72,0x80,0xE2,0x20,0xBD,
+};
+
+static const size_t pixel_2_width = 128;
+static const size_t pixel_2_height = 128;
+static const size_t pixel_2_size = 8192;
+static const unsigned char pixel_2_data[8192] =
+{
+    0x87,0x62,0x23,0x41,0x7F,0xE3,0xAD,0xFF,0xE5,0x51,0xE2,0x30,0xEE,0x3A,0x68,0xBA,
+    0xE6,0x51,0x02,0x31,0xA6,0xBE,0xE3,0xDB,0x06,0x52,0x23,0x39,0xB7,0xDF,0x73,0xDE,
+    0xE6,0x51,0x23,0x39,0x37,0x7F,0x73,0xD8,0xE6,0x51,0x02,0x39,0x37,0x5B,0xFB,0xF8,
+    0xE6,0x59,0x43,0x41,0x0D,0xF9,0xBD,0xAC,0xE5,0x59,0x23,0x39,0xBE,0x72,0xDE,0x5C,
+    0xC6,0x51,0x23,0x39,0xFF,0x72,0x1C,0xFC,0x27,0x5A,0x24,0x39,0xD7,0x7A,0x9C,0xFF,
+    0xE6,0x51,0x03,0x39,0x9E,0xFE,0x3C,0xFA,0x26,0x52,0x44,0x41,0x17,0xF7,0x9F,0x73,
+    0x26,0x5A,0x64,0x41,0x17,0xB5,0x97,0xEB,0x27,0x5A,0x44,0x41,0xF8,0xBF,0xB6,0xD7,
+    0x47,0x62,0x43,0x39,0x2B,0x0B,0x2E,0x57,0x66,0x62,0x43,0x41,0x82,0xF0,0x6A,0x55,
+    0x46,0x62,0x43,0x41,0x00,0x0A,0xEB,0xD5,0x67,0x62,0x44,0x41,0xF7,0xDC,0x7F,0x57,
+    0xE6,0x51,0x43,0x39,0xCD,0xF7,0xF8,0xFD,0xC5,0x51,0x23,0x39,0xC1,0xBF,0x57,0x0A,
+    0x4E,0xA4,0x02,0x39,0x3F,0xF5,0x55,0xFF,0x96,0xEE,0xE6,0x59,0x00,0x03,0x0D,0x0D,
+    0xD7,0xF6,0x75,0xEE,0x2B,0xCA,0xD2,0x7C,0xF7,0xF6,0x34,0xE6,0xAA,0xAA,0x7A,0x5F,
+    0xD7,0xF6,0x14,0xDE,0x00,0x00,0x0A,0x95,0x18,0xFF,0x75,0xE6,0x0A,0xA2,0xB7,0x7A,
+    0x18,0xFF,0x96,0xE6,0xA0,0x0A,0xAA,0xAD,0x18,0xF7,0xD7,0xF6,0x7E,0xEA,0xAB,0x7A,
+    0xD7,0xF6,0xB7,0xEE,0x0A,0xBE,0x70,0xE8,0xD7,0xF6,0xB2,0xD5,0x68,0xE0,0xC8,0xA8,
+    0x14,0xE6,0x71,0xCD,0x82,0x81,0x29,0x0D,0x34,0xDE,0xF3,0xDD,0x5F,0x5D,0xDE,0x5A,
+    0xA8,0x72,0x63,0x41,0xB7,0xDF,0x5E,0x5C,0x27,0x5A,0x43,0x39,0xFF,0xFC,0x57,0x0B,
+    0xE6,0x51,0x23,0x39,0xFF,0xFE,0x75,0x00,0x67,0x62,0x03,0x31,0x7E,0x72,0x55,0xAA,
+    0xC6,0x51,0x23,0x39,0x62,0xF9,0x55,0x00,0xC6,0x51,0x23,0x39,0xFF,0x55,0xF6,0x00,
+    0xE6,0x69,0x43,0x41,0x2D,0x25,0x09,0x0A,0x68,0x7A,0x03,0x39,0xFE,0x5A,0xAA,0x0A,
+    0x0D,0x9C,0x24,0x39,0x75,0x55,0x77,0x02,0xAF,0xAC,0x23,0x39,0x55,0x55,0xFF,0x00,
+    0xD3,0xD5,0x85,0x49,0x55,0x55,0x55,0x00,0x35,0xE6,0x64,0x41,0x55,0x55,0xFF,0x00,
+    0x96,0xEE,0x84,0x49,0x55,0x55,0xBF,0x00,0x75,0xEE,0x84,0x49,0x55,0x55,0xAA,0x00,
+    0xD7,0xFE,0xA5,0x51,0x55,0x55,0xAA,0xE0,0x55,0xEE,0xE6,0x59,0x55,0xD5,0x0F,0x25,
+    0xB7,0xF6,0xE6,0x59,0x55,0xFF,0x00,0x00,0xB6,0xEE,0x06,0x5A,0x55,0xAB,0x00,0x00,
+    0xB7,0xF6,0x26,0x62,0x55,0x2A,0x00,0x00,0x96,0xEE,0x87,0x6A,0x55,0x00,0x00,0x00,
+    0xB6,0xEE,0x2A,0x83,0xD5,0x00,0x00,0x00,0xB6,0xF6,0x8E,0xAC,0x09,0x00,0x00,0x00,
+    0xB6,0xF6,0x14,0xDE,0xE8,0x68,0xFA,0xB6,0xD7,0xF6,0x14,0xDE,0xFD,0x0D,0x02,0x08,
+    0xD7,0xF6,0xF3,0xD5,0x7A,0xAA,0xA0,0x00,0xD7,0xF6,0xD3,0xD5,0x0D,0xBE,0xA2,0x08,
+    0x18,0xF7,0x35,0xDE,0x9E,0xFA,0x8B,0x2A,0x18,0xF7,0x96,0xEE,0x88,0x29,0xAA,0xE8,
+    0x18,0xF7,0x96,0xE6,0xFE,0xF8,0x7A,0x7A,0x75,0xEE,0xD3,0xD5,0x00,0xA0,0xAC,0xE6,
+    0x34,0xE6,0x92,0xCD,0xA5,0xA7,0x36,0x26,0x34,0xE6,0xF3,0xDD,0xDA,0xFE,0xD6,0x56,
+    0x96,0xEE,0xE5,0x51,0x56,0xA8,0x00,0x00,0xB6,0xEE,0x06,0x5A,0x55,0xAA,0x00,0x00,
+    0x96,0xEE,0x47,0x62,0x55,0x02,0x00,0x00,0x75,0xEE,0xC9,0x72,0xD5,0x00,0x00,0x00,
+    0x96,0xEE,0x8B,0x93,0xF5,0x00,0x00,0x00,0xB6,0xEE,0x10,0xBD,0xD5,0x02,0x00,0x00,
+    0xD7,0xF6,0xE5,0x69,0x5A,0x58,0x58,0x58,0x0A,0x8B,0xC5,0x69,0x3D,0xDD,0xF5,0xD5,
+    0x96,0xEE,0x46,0x72,0x02,0x03,0x09,0x25,0xB6,0xF6,0x96,0xEE,0xF5,0xAA,0x82,0x02,
+    0xB6,0xF6,0x96,0xEE,0xAB,0xAB,0x02,0x20,0xB6,0xF6,0xD6,0xEE,0x20,0xC0,0x60,0xFC,
+    0xF7,0xF6,0xD7,0xF6,0xF5,0x82,0x02,0x00,0xF7,0xF6,0x71,0xCD,0x00,0x00,0x80,0x60,
+    0x55,0xEE,0x87,0x7A,0x70,0x58,0x56,0x55,0xB7,0xF6,0x46,0x72,0x25,0x25,0x25,0x0D,
+    0xF8,0xFE,0x17,0xF7,0xFA,0xFE,0xFF,0xF7,0xF7,0xF6,0xD7,0xF6,0x7E,0xFC,0xF8,0x62,
+    0xD7,0xF6,0xF7,0xEE,0x00,0x00,0x28,0x80,0xD7,0xF6,0xF7,0xEE,0x00,0xA0,0x08,0xA8,
+    0xF7,0xF6,0x96,0xEE,0x2A,0x8A,0xE2,0x78,0x96,0xEE,0xF3,0xDD,0x80,0xE0,0x70,0x5C,
+    0xB7,0xF6,0xD2,0xD5,0xB7,0x25,0x0B,0x02,0xD7,0xF6,0x34,0xE6,0xBD,0x57,0xAA,0x28,
+    0xF8,0xF6,0x55,0xE6,0x0A,0x2D,0xFB,0xAA,0xF7,0xF6,0xB7,0xEE,0xD7,0x7E,0x6A,0x89,
+    0x18,0xF7,0xD7,0xF6,0x3F,0xA9,0x29,0xFF,0x39,0xFF,0xB6,0xEE,0xE8,0xF2,0x62,0xEE,
+    0xD7,0xF6,0x34,0xE6,0xC0,0x8A,0x6B,0x6F,0x34,0xE6,0x10,0xC5,0x8C,0x04,0xA6,0x26,
+    0x76,0xEE,0xCF,0xBC,0xAE,0x2A,0x3E,0x9A,0x96,0xEE,0xD3,0xD5,0x7F,0x7A,0xA8,0x2A,
+    0xD6,0xF6,0xB6,0xEE,0xFD,0xF7,0xFF,0xAD,0xD6,0xF6,0xB6,0xEE,0xFB,0xFA,0xBA,0xE9,
+    0xD6,0xF6,0xB6,0xEE,0xDF,0xEE,0xBB,0xFA,0xB5,0xF6,0x96,0xEE,0xD7,0xDD,0xBE,0xFE,
+    0xD7,0xF6,0x96,0xEE,0x2F,0x27,0x2F,0x2F,0xD7,0xF6,0xB6,0xEE,0xCA,0x08,0x08,0x82,
+    0x95,0xF6,0xA5,0x61,0x58,0x7C,0x5C,0x54,0x06,0x72,0x44,0x59,0x2C,0xB8,0x7A,0x79,
+    0x92,0xD5,0x84,0x59,0x2D,0xB5,0xF5,0xD5,0xD6,0xF6,0xEC,0xA3,0x00,0x00,0x02,0x09,
+    0xD7,0xF6,0xB6,0xF6,0x77,0xDE,0xDE,0xB8,0xD6,0xF6,0xB6,0xF6,0x0B,0x2D,0x2E,0x08,
+    0xF7,0xF6,0x55,0xEE,0x00,0x00,0x80,0x40,0x17,0xFF,0x46,0x7A,0xE0,0x78,0x5E,0x57,
+    0x87,0x8A,0x26,0x7A,0x0F,0x27,0xA9,0xFB,0xF7,0xFE,0x87,0x82,0x0D,0x0D,0x09,0x09,
+    0x18,0xFF,0x17,0xF7,0xEE,0xBB,0xEE,0xEA,0xF7,0xF6,0xD7,0xF6,0xE8,0xE8,0xEA,0xEA,
+    0xF7,0xF6,0xD7,0xF6,0xF5,0xD7,0x7F,0xEB,0x17,0xFF,0xB7,0xEE,0xAF,0xCB,0x6A,0x5A,
+    0xD6,0xF6,0xD3,0xD5,0xA0,0xA8,0xE8,0x7A,0xD7,0xF6,0x92,0xD5,0x9E,0x27,0x09,0x02,
+    0xF7,0xF6,0xB6,0xEE,0xBF,0xAA,0xEE,0xEA,0xD7,0xF6,0xB6,0xEE,0xD8,0xAE,0x8A,0xE8,
+    0xF7,0xF6,0xB6,0xEE,0x15,0x57,0x77,0xEF,0x38,0xFF,0xD7,0xEE,0xEF,0xAB,0x2D,0xB5,
+    0x39,0xFF,0xD7,0xF6,0xDF,0x7F,0xDE,0x78,0xF8,0xF6,0xB6,0xEE,0xF8,0xF8,0xFE,0xD7,
+    0xB6,0xEE,0xF3,0xD5,0xCE,0x8E,0x8C,0x26,0xF3,0xDD,0x30,0xC5,0x24,0x3C,0x2A,0x3A,
+    0x96,0xF6,0x30,0xC5,0x1F,0x3D,0x35,0x35,0xB6,0xF6,0x34,0xE6,0xDE,0xDC,0xDC,0xFC,
+    0xB6,0xF6,0xD6,0xEE,0xEB,0xFF,0xFB,0xFF,0xD6,0xF6,0xB7,0xEE,0xAA,0x82,0x0A,0x22,
+    0xD6,0xF6,0xB6,0xEE,0xEA,0xAE,0xC0,0x80,0xD6,0xF6,0x96,0xEE,0xFF,0xFF,0xBB,0xBE,
+    0xF7,0xF6,0xB6,0xEE,0xB5,0xB5,0xBD,0xA7,0xD6,0xF6,0xF7,0xEE,0x00,0x08,0xA2,0xA8,
+    0x95,0xEE,0x43,0x51,0x5C,0x5C,0x58,0x50,0x85,0x59,0xE2,0x40,0xC2,0xFE,0x7B,0x76,
+    0x67,0x72,0x03,0x41,0x3D,0xAD,0x25,0x25,0x34,0xE6,0x09,0x83,0x0D,0xF5,0x55,0x55,
+    0x95,0xEE,0xC8,0x7A,0x00,0xBF,0xD5,0x55,0xB6,0xF6,0x09,0x8B,0x00,0x22,0x7D,0x55,
+    0x76,0xF6,0x46,0x72,0x80,0x60,0x5F,0x55,0x67,0x82,0xE5,0x71,0x2C,0x0B,0xE7,0xD7,
+    0x29,0x9B,0x26,0x82,0xD7,0xF5,0xBD,0x2D,0xF7,0xFE,0x4B,0xA3,0x01,0x03,0x02,0x02,
+    0x38,0xFF,0x18,0xF7,0x7E,0x6B,0x7F,0xFF,0x17,0xF7,0xD7,0xF6,0xFF,0xEE,0xEE,0xA0,
+    0x18,0xFF,0x75,0xEE,0x2A,0x82,0xE2,0x58,0xF7,0xFE,0x55,0xEE,0xF8,0xEE,0x6E,0x7F,
+    0xD7,0xF6,0xF4,0xDD,0xBE,0x27,0x09,0x02,0xF7,0xF6,0xD7,0xF6,0x7D,0x7B,0x5A,0xEE,
+    0xD7,0xF6,0xB6,0xEE,0x00,0xA0,0x80,0x80,0xD7,0xF6,0xB6,0xEE,0xAA,0xA0,0xE8,0xAA,
+    0xD7,0xF6,0xB7,0xEE,0x80,0x0B,0xAF,0x0A,0xF8,0xF6,0xD7,0xF6,0x2D,0x3D,0x25,0xAB,
+    0x39,0xFF,0x97,0xEE,0xE0,0x6A,0x4A,0xEA,0xB6,0xEE,0x76,0xEE,0x38,0xBF,0x9F,0xFF,
+    0xB7,0xF6,0x71,0xCD,0x24,0x06,0x24,0x26,0x35,0xE6,0x92,0xCD,0xD6,0x9E,0xDC,0x54,
+    0xF3,0xDD,0x8E,0xB4,0x27,0x37,0x07,0x09,0x96,0xEE,0x34,0xE6,0xD8,0xFB,0xDB,0xFB,
+    0xD6,0xF6,0xB7,0xEE,0xAA,0x8A,0x00,0x2A,0xD7,0xF6,0xD6,0xEE,0xAA,0xAA,0xAA,0x0A,
+    0xF7,0xF6,0xD7,0xF6,0x75,0x77,0xF5,0xAD,0xD6,0xF6,0xB6,0xEE,0xDF,0xD6,0xEA,0xA8,
+    0xF7,0xF6,0xB6,0xEE,0xAD,0xA7,0xAF,0xAF,0xF7,0xF6,0xD7,0xF6,0xF5,0x7E,0xA7,0xAB,
+    0xD7,0xF6,0x02,0x41,0x70,0x70,0x60,0x60,0xE5,0x61,0xE2,0x40,0x7F,0xFF,0xBD,0x09,
+    0x67,0x72,0x44,0x49,0x2D,0xAF,0xFB,0xEA,0xA8,0x7A,0xE5,0x61,0x80,0xA2,0xFD,0x5F,
+    0x88,0x72,0xE5,0x61,0x22,0xBA,0xFE,0xD5,0x2A,0x8B,0xE5,0x61,0x02,0xAA,0x7B,0x55,
+    0x67,0x7A,0xC5,0x61,0x34,0xB7,0xED,0xC3,0x26,0x7A,0x43,0x59,0x2C,0x26,0xB5,0x15,
+    0xE9,0x92,0x47,0x82,0x35,0x25,0xB5,0x3F,0xF7,0xFE,0x10,0xCD,0x01,0x01,0x03,0x03,
+    0x38,0xFF,0xF7,0xF6,0xAA,0xAF,0xFF,0x5B,0x38,0xFF,0xD6,0xF6,0xA8,0xE0,0x6B,0x5B,
+    0xD7,0xF6,0x54,0xE6,0xA8,0x80,0x60,0x40,0xF8,0xFE,0xD3,0xDD,0x5E,0xD6,0x83,0x82,
+    0xD7,0xF6,0xB2,0xD5,0x25,0x37,0xBE,0xFA,0xF7,0xF6,0xB6,0xF6,0x02,0x02,0xAB,0x09,
+    0xF7,0xF6,0xD7,0xF6,0x7F,0x5A,0xBF,0xDF,0xF7,0xF6,0x97,0xEE,0xAA,0x0E,0x22,0x8A,
+    0xF7,0xF6,0xD7,0xF6,0x85,0xC2,0x8B,0xAA,0xF8,0xF6,0xD7,0xF6,0x02,0xEA,0x0A,0xCA,
+    0xF8,0xF6,0xB7,0xEE,0x8A,0x2A,0xBE,0xB7,0x96,0xEE,0x76,0xEE,0xAE,0x9C,0xBE,0xE0,
+    0x96,0xEE,0x51,0xCD,0x24,0x24,0x2E,0x2C,0x55,0xEE,0xF0,0xBC,0xFC,0xF8,0x78,0x58,
+    0x34,0xE6,0x10,0xC5,0x2D,0x2B,0x01,0x0B,0x96,0xEE,0x55,0xE6,0x5B,0xFA,0xF3,0x33,
+    0xD6,0xF6,0xB6,0xE6,0x28,0x82,0x20,0x88,0xD7,0xF6,0xD6,0xEE,0x8A,0xAA,0x2B,0xAA,
+    0xF6,0xF6,0xD7,0xF6,0xFD,0x7F,0x77,0x7D,0xD6,0xF6,0xB7,0xEE,0x00,0x08,0x2A,0xAE,
+    0xF7,0xF6,0xD7,0xF6,0xD5,0xA7,0x2D,0xA5,0xF7,0xF6,0xD6,0xF6,0xBA,0xAA,0xCA,0x02,
+    0xB6,0xF6,0x66,0x72,0x60,0x60,0x70,0x70,0xC8,0x82,0xC5,0x59,0xE5,0x0A,0x2A,0xFE,
+    0xA8,0x7A,0xA4,0x59,0x7A,0xE0,0x68,0x7B,0x67,0x72,0x64,0x51,0x82,0xC3,0xFF,0xF5,
+    0x46,0x72,0xC5,0x59,0xFD,0xE5,0xD5,0x39,0x2A,0x93,0xC5,0x61,0xD5,0xB5,0x2F,0x0A,
+    0x8E,0xC4,0x88,0x82,0x7D,0xDB,0xEB,0x0A,0x8B,0xA3,0xC5,0x69,0x97,0xEA,0x8A,0xE8,
+    0xD7,0xFE,0x67,0x7A,0xD5,0x15,0x25,0x0D,0x17,0xFF,0xB8,0xF6,0x21,0x22,0x22,0x20,
+    0x18,0xFF,0xB6,0xEE,0x28,0x88,0x6A,0x5A,0x17,0xFF,0x34,0xE6,0xA8,0x7A,0x7F,0xA2,
+    0x39,0xFF,0x96,0xEE,0xE2,0xC1,0x83,0x88,0x18,0xFF,0xD8,0xF6,0xE9,0x89,0xAB,0xAB,
+    0x18,0xFF,0x14,0xE6,0x7F,0x7E,0xFC,0x78,0x18,0xFF,0x55,0xE6,0x2B,0x29,0xAD,0xAD,
+    0x38,0xFF,0xD7,0xF6,0x57,0x7F,0xFF,0xFB,0xF7,0xF6,0xD7,0xF6,0xD9,0x0B,0x00,0x00,
+    0x18,0xFF,0xD7,0xF6,0xFD,0xAE,0xBB,0xFA,0xF7,0xF6,0x95,0xEE,0x80,0xA0,0xE8,0xE8,
+    0xD7,0xF6,0x96,0xEE,0x37,0x0D,0x09,0xAD,0x96,0xEE,0x55,0xE6,0xA8,0xA8,0xBB,0xBD,
+    0x55,0xEE,0xB3,0xD5,0x04,0x24,0x04,0x24,0x55,0xEE,0x6E,0xB4,0x78,0x78,0x58,0x5A,
+    0x76,0xEE,0x92,0xD5,0xA9,0xA9,0x29,0x03,0xB6,0xF6,0x34,0xE6,0x3B,0x25,0x2E,0xAF,
+    0xD6,0xF6,0x55,0xEE,0x00,0x00,0x00,0x09,0xD6,0xF6,0xF7,0xEE,0x20,0x88,0x88,0x20,
+    0xD6,0xF6,0xD7,0xEE,0x8A,0xAA,0x88,0x22,0xD6,0xF6,0xB6,0xEE,0xEE,0xBE,0xAA,0x00,
+    0xD6,0xF6,0xB6,0xEE,0x02,0x8A,0xBB,0x80,0xF7,0xF6,0xB6,0xEE,0xAA,0xAB,0xEB,0xFE,
+    0x75,0xEE,0x63,0x49,0x78,0x58,0x58,0x5C,0xE5,0x61,0xA1,0x28,0x00,0xEF,0xD7,0xD5,
+    0xC5,0x59,0xE2,0x38,0xA8,0xB7,0xBD,0x35,0x09,0x93,0x84,0x51,0xFD,0xEB,0x7A,0x72,
+    0x2A,0x8B,0x23,0x49,0x2F,0x2B,0x3F,0xB5,0xEC,0xAB,0x87,0x82,0xBA,0x80,0x0B,0x2D,
+    0x4E,0xBC,0x47,0x7A,0x0A,0xAE,0xFE,0x7A,0xEC,0xAB,0x26,0x72,0x5C,0xD6,0x3F,0x2B,
+    0xF8,0xFE,0xCB,0xA3,0x09,0x02,0x02,0x02,0x18,0xFF,0xD6,0xF6,0xA0,0xA2,0xE0,0x70,
+    0x59,0xFF,0xD6,0xF6,0xD7,0xA5,0xAD,0x0D,0x38,0xFF,0x75,0xE6,0x70,0xD0,0xDC,0x9C,
+    0x38,0xFF,0xF9,0xF6,0xCA,0x6A,0xEA,0xEE,0x18,0xFF,0xF8,0xF6,0xB9,0xBF,0xAF,0xA7,
+    0x18,0xFF,0x55,0xEE,0x78,0xE0,0xE0,0xA8,0xF7,0xF6,0x55,0xEE,0x2D,0x2F,0x0F,0x2A,
+    0x18,0xFF,0xF7,0xF6,0x55,0x55,0xFD,0xA5,0xF7,0xF6,0xD7,0xF6,0x28,0x62,0x00,0x00,
+    0xF7,0xF6,0x96,0xEE,0x80,0x28,0xF8,0x7A,0xD7,0xF6,0x55,0xE6,0xE0,0xF0,0xDE,0xF7,
+    0xD7,0xF6,0x76,0xEE,0x89,0x89,0xF3,0xBB,0x75,0xEE,0xF4,0xDD,0x0A,0x07,0x25,0xA7,
+    0x56,0xEE,0x92,0xCD,0x2C,0x2E,0x2E,0x66,0x14,0xE6,0xAF,0xBC,0xD8,0xF8,0xF0,0xD2,
+    0x34,0xE6,0x31,0xCD,0x82,0x7F,0xD7,0xD7,0x35,0xE6,0x92,0xD5,0x0F,0x0D,0x2D,0xBD,
+    0x34,0xE6,0xE8,0x82,0x2D,0x55,0x55,0x55,0xB6,0xF6,0x08,0x83,0x00,0x2F,0x55,0x55,
+    0xB6,0xF6,0xE8,0x82,0x00,0x00,0x0B,0xD5,0xD6,0xF6,0xF0,0xC4,0x00,0x00,0x00,0x2D,
+    0xB7,0xFE,0xF6,0xF6,0xFF,0xFF,0xBF,0xEA,0xF7,0xFE,0xB6,0xF6,0xFF,0xAE,0xEE,0xAA,
+    0x95,0xEE,0x43,0x41,0x5C,0x5C,0x5C,0x58,0x44,0x41,0xA1,0x28,0xD5,0xF7,0xA0,0x80,
+    0x06,0x72,0xE2,0x38,0xB5,0x35,0x35,0x2D,0xC8,0x82,0xE3,0x40,0x60,0x70,0x7A,0x5E,
+    0xE6,0x61,0x81,0x28,0x2F,0xFF,0x77,0x5F,0x09,0x93,0xC2,0x30,0x0A,0x2F,0xB5,0xB5,
+    0x6B,0x9B,0x67,0x7A,0xD8,0xDE,0xFF,0xFF,0xCB,0xA3,0x06,0x6A,0xC2,0xAA,0xFB,0x7F,
+    0x34,0xE6,0x67,0x72,0x2D,0x95,0x55,0x55,0xD7,0xF6,0x4B,0x93,0x00,0x00,0x02,0x0D,
+    0x79,0xFF,0xD7,0xF6,0xA9,0xEB,0xEA,0x6E,0xF7,0xFE,0x35,0xE6,0x3C,0x3F,0x37,0x27,
+    0x38,0xFF,0xF7,0xF6,0xE3,0xEB,0xEB,0xEB,0xF8,0xFE,0x18,0xF7,0xEA,0xAB,0xAA,0xAA,
+    0x18,0xFF,0xD7,0xF6,0x7A,0x5A,0xFE,0xFA,0xF8,0xF6,0xD7,0xF6,0xD5,0xBA,0x0A,0x0B,
+    0x18,0xFF,0xF7,0xF6,0xA7,0xF6,0xBF,0x9B,0x18,0xFF,0xB7,0xF6,0xA8,0xE2,0x68,0x7A,
+    0xD7,0xF6,0x55,0xE6,0xE8,0xFA,0x7E,0xFF,0x75,0xEE,0x35,0xE6,0x20,0xA8,0xAF,0x38,
+    0xB7,0xF6,0x76,0xEE,0x3E,0xAA,0xEE,0x7F,0x75,0xEE,0x92,0xD5,0x2F,0x25,0xA5,0xB5,
+    0xF4,0xDD,0x51,0xCD,0x48,0xC8,0x00,0x00,0xD3,0xDD,0x6E,0xB4,0xFA,0xDA,0xDA,0xD8,
+    0x72,0xD5,0xF0,0xC4,0x2F,0x2D,0xAF,0xB7,0xD3,0xDD,0x30,0xC5,0x22,0xE2,0x62,0x5F,
+    0xE8,0x82,0x65,0x72,0x2A,0xA8,0x2B,0x55,0xE8,0x82,0xA7,0x7A,0xA2,0xBA,0xEA,0xAD,
+    0xE8,0x82,0xC8,0x82,0x23,0xAA,0xFF,0x57,0x4D,0xAC,0xE8,0x82,0x35,0x55,0x55,0x55,
+    0x75,0xEE,0xE8,0x82,0x02,0xB5,0x55,0x55,0xB6,0xF6,0x09,0x8B,0x00,0x02,0xB5,0x55,
+    0x75,0xEE,0x63,0x51,0x70,0x60,0xC0,0xEF,0xA5,0x51,0x23,0x41,0x60,0xE2,0xAD,0xA5,
+    0x09,0x93,0x64,0x51,0xB5,0x2D,0x0B,0x0B,0x87,0x82,0x24,0x49,0x5C,0xF8,0xB8,0x88,
+    0x47,0x7A,0xC2,0x30,0x55,0x5F,0xE8,0x60,0x06,0x72,0xA2,0x30,0x3D,0x2F,0xEE,0xBF,
+    0x88,0x7A,0xC5,0x61,0xBC,0xD5,0x99,0xAB,0xA8,0x7A,0x22,0x41,0xF8,0xDE,0x96,0xB7,
+    0x09,0x8B,0xC5,0x61,0xAF,0xAF,0x2F,0x27,0xB6,0xF6,0xA8,0x82,0x25,0x35,0xD5,0x55,
+    0x18,0xFF,0xF0,0xCC,0x80,0x80,0xA0,0x89,0xF8,0xFE,0x55,0xEE,0x25,0x25,0x25,0x0D,
+    0x18,0xFF,0xF8,0xF6,0x82,0xE2,0xE2,0xC2,0x18,0xFF,0xF8,0xF6,0x7E,0x5F,0xF7,0x57,
+    0x18,0xFF,0xD7,0xF6,0xFF,0xBB,0xEF,0xAB,0x18,0xFF,0xD7,0xF6,0xAF,0xBF,0xAA,0xAE,
+    0x18,0xFF,0xD7,0xF6,0xBA,0xFA,0xFA,0xFE,0xF8,0xF6,0x76,0xEE,0xE8,0x78,0x7A,0x5E,
+    0x76,0xEE,0x35,0xE6,0xE0,0xE0,0xE8,0x68,0x96,0xEE,0x35,0xE6,0x3F,0x2E,0xAB,0x2D,
+    0x96,0xEE,0x55,0xEE,0x88,0xC2,0xEE,0x4A,0x14,0xE6,0x71,0xCD,0x27,0xB5,0xBE,0xA8,
+    0xD3,0xDD,0xCF,0xBC,0x00,0x80,0x70,0x58,0x92,0xD5,0x6E,0xB4,0x58,0x7B,0xEF,0xA7,
+    0x51,0xCD,0x4E,0xAC,0x2E,0x0E,0x26,0x26,0x72,0xCD,0x10,0xC5,0x16,0xB5,0x0D,0xA3,
+    0xA7,0x7A,0x66,0x72,0xDD,0xFA,0xAA,0xAB,0xA7,0x7A,0x46,0x72,0xBF,0xDA,0xA2,0x08,
+    0xE8,0x82,0x46,0x72,0x0A,0xBD,0xF7,0xFB,0xE8,0x8A,0x66,0x72,0x22,0xAA,0x3D,0x55,
+    0xE8,0x82,0x87,0x7A,0x08,0xA0,0x82,0xA5,0x08,0x8B,0xC8,0x82,0xAE,0xFF,0xFF,0xF5,
+    0x08,0x8B,0xC4,0x59,0xC0,0xE2,0x68,0xE2,0xA4,0x59,0xC2,0x30,0x2A,0x0A,0xBF,0xDF,
+    0xE8,0x92,0xA4,0x59,0x09,0x8B,0x0B,0xAD,0xA8,0x8A,0xA5,0x61,0xE8,0xFE,0x7A,0x7E,
+    0x46,0x72,0x23,0x49,0xE8,0x7A,0x5F,0x5F,0xA5,0x51,0x23,0x41,0xB5,0xB7,0x3F,0xEF,
+    0x88,0x72,0x64,0x49,0x8B,0xAB,0xFF,0x55,0x47,0x72,0x03,0x49,0xB7,0xBF,0x2F,0x03,
+    0xE9,0x92,0x06,0x6A,0xAD,0x8B,0xEB,0xFE,0xE9,0x8A,0x23,0x49,0x82,0xA2,0x7A,0x5E,
+    0x14,0xE6,0xE5,0x61,0x0B,0x2D,0xB5,0xD5,0xD7,0xFE,0x0D,0xAC,0x08,0x02,0x02,0xB5,
+    0x18,0xFF,0xB7,0xF6,0x80,0x80,0x82,0x89,0xD7,0xFE,0xF8,0xF6,0xF5,0x7D,0xD7,0xF5,
+    0x18,0xFF,0xF7,0xF6,0xDD,0xB5,0xFF,0xED,0x18,0xFF,0xD7,0xF6,0x8E,0xAA,0xAA,0x6A,
+    0xF8,0xFE,0x96,0xEE,0xF0,0x7A,0x7A,0x5E,0xB6,0xF6,0x55,0xE6,0xFC,0xEF,0x75,0xF7,
+    0x76,0xEE,0x35,0xEE,0xEA,0x88,0x2A,0xA8,0x76,0xEE,0x14,0xE6,0x0B,0x0E,0x7A,0xF8,
+    0x96,0xF6,0xF4,0xE5,0x82,0x8A,0xC3,0x6A,0x14,0xE6,0xD3,0xDD,0xEA,0xBE,0x03,0x61,
+    0xD3,0xDD,0x8E,0xB4,0x58,0x5C,0xFC,0x7E,0x51,0xCD,0xCC,0x9B,0x2F,0xAF,0xFE,0x7A,
+    0x10,0xC5,0xAB,0x9B,0x08,0x08,0x0F,0x0D,0x72,0xCD,0x11,0xC5,0x02,0x00,0x03,0xAF,
+    0x67,0x72,0x25,0x6A,0x25,0x55,0xDD,0xBE,0xA8,0x7A,0x25,0x6A,0x82,0xBD,0x55,0x55,
+    0xA7,0x7A,0x26,0x72,0xA2,0x80,0x2D,0x55,0xA7,0x7A,0x46,0x7A,0xA8,0x0A,0xA0,0x2D,
+    0xA7,0x7A,0x66,0x7A,0xD7,0xE8,0xE2,0x8A,0xC8,0x82,0x66,0x72,0x0A,0xD7,0xFB,0xAA,
+    0xE8,0x82,0x86,0x7A,0x60,0x22,0xD5,0x77,0x86,0x7A,0xA2,0x38,0x57,0x5C,0xF8,0xE0,
+    0xE6,0x69,0xC2,0x40,0x2D,0x2D,0xFF,0xFF,0x67,0x7A,0x03,0x49,0x20,0x00,0x8B,0xF5,
+    0xA8,0x82,0xC2,0x38,0xFA,0xF8,0x7A,0x5F,0x44,0x49,0xE2,0x38,0xBC,0xF7,0xFD,0xAB,
+    0xA4,0x59,0xA2,0x30,0xDF,0xB7,0x37,0x2F,0x67,0x7A,0x84,0x59,0x09,0x2D,0xFD,0xFF,
+    0x06,0x6A,0x44,0x51,0xA8,0xB8,0xBE,0xD7,0xA5,0x59,0x03,0x41,0x9C,0x9C,0x3E,0xA7,
+    0xE9,0x8A,0xA5,0x59,0x3F,0xAF,0xEB,0xED,0x4A,0x93,0x67,0x7A,0x37,0xB5,0xED,0x55,
+    0x96,0xF6,0x67,0x7A,0x02,0xB7,0x55,0x55,0x97,0xF6,0x67,0x7A,0x00,0x00,0xB7,0x55,
+    0xD7,0xFE,0x67,0x72,0x00,0x00,0x0A,0x75,0xD7,0xFE,0xB0,0xBC,0x00,0x00,0x00,0x29,
+    0xD7,0xF6,0x55,0xEE,0xE8,0x7E,0xFF,0x5F,0x96,0xF6,0x35,0xE6,0xEA,0xAA,0xAB,0xE5,
+    0x96,0xF6,0x55,0xEE,0x7F,0xEE,0x2A,0x7D,0x76,0xEE,0x55,0xEE,0x5A,0x3A,0xD7,0x09,
+    0x75,0xEE,0xB3,0xD5,0xE8,0x62,0x68,0x68,0x75,0xEE,0xB3,0xD5,0xAD,0xAF,0xAD,0xBD,
+    0x75,0xEE,0x10,0xC5,0x56,0x78,0x82,0x00,0x35,0xE6,0x8B,0x93,0x6A,0xEA,0xAA,0xA8,
+    0x30,0xC5,0x68,0x72,0x0B,0xAD,0xD7,0x5C,0xF0,0xC4,0xC9,0x7A,0x00,0x00,0x02,0x35,
+    0x66,0x72,0x46,0x72,0xD7,0x5B,0xDD,0xAE,0x67,0x7A,0x46,0x6A,0x55,0xFF,0xAA,0xAB,
+    0x66,0x72,0x26,0x6A,0xFE,0xEB,0xAA,0x8A,0x66,0x72,0x26,0x72,0x3D,0xFF,0xFB,0xAA,
+    0xA7,0x7A,0x25,0x6A,0x0A,0xBD,0x5F,0xFF,0xA7,0x82,0x46,0x72,0x08,0x0A,0xB5,0x55,
+    0xC7,0x82,0x46,0x72,0x2A,0x88,0x0A,0xAD,0xE8,0x8A,0xE5,0x69,0x6A,0xEA,0x80,0x02,
+    0xE8,0x8A,0x84,0x59,0x55,0xFA,0x68,0x78,0x85,0x51,0xA2,0x30,0x20,0xE8,0x7A,0x57,
+    0x44,0x49,0xA2,0x28,0xDC,0xBF,0xFF,0xFD,0x64,0x49,0xC2,0x30,0xFA,0xB7,0xB7,0x15,
+    0x85,0x59,0x23,0x41,0x3D,0xAF,0x2E,0x25,0x27,0x72,0x44,0x49,0xC0,0xC3,0x6B,0x7B,
+    0xA5,0x59,0xE2,0x38,0xAE,0xA5,0x37,0x27,0xA5,0x59,0x03,0x41,0xAF,0xEF,0x78,0x5C,
+    0xC8,0x82,0xE3,0x40,0x0B,0x09,0xAD,0xFD,0x67,0x7A,0x44,0x51,0x28,0xA8,0xFF,0xD5,
+    0xE9,0x8A,0xE5,0x61,0x8A,0x0B,0xAD,0xFD,0xC9,0x8A,0x27,0x72,0x5F,0x78,0x68,0x8A,
+    0x67,0x72,0xA5,0x59,0x02,0x80,0xAA,0x58,0x55,0xEE,0x06,0x62,0x2D,0xF5,0x55,0x55,
+    0x34,0xEE,0x47,0x72,0x00,0x0A,0x2D,0xB5,0x35,0xE6,0x93,0xDD,0x20,0x2A,0xE8,0xA9,
+    0x14,0xE6,0xD3,0xDD,0x3A,0x20,0xFF,0x56,0x96,0xF6,0xF4,0xE5,0x8A,0xAB,0xFB,0x5D,
+    0x55,0xEE,0xD3,0xDD,0x60,0xAA,0xF2,0xF2,0x55,0xE6,0xB3,0xD5,0xAD,0xEA,0xAA,0xBB,
+    0x96,0xEE,0x14,0xE6,0x82,0x0B,0x03,0x01,0x76,0xEE,0x92,0xD5,0x78,0xE0,0x00,0x00,
+    0x35,0xE6,0x0D,0xA4,0x7A,0xA2,0x08,0x20,0xB2,0xD5,0xC9,0x7A,0xB5,0xA8,0xC0,0x00,
+    0x66,0x72,0x27,0x72,0x82,0xA0,0x02,0xA9,0x47,0x7A,0x66,0x72,0xF5,0x5F,0xDF,0x7F,
+    0x86,0x7A,0x46,0x72,0xF7,0xEF,0xBB,0xBA,0x86,0x7A,0x46,0x72,0xDF,0xEE,0xBA,0xA2,
+    0x86,0x7A,0x46,0x72,0xFF,0xFF,0xEA,0xA8,0x66,0x7A,0x46,0x72,0xBF,0x0A,0x08,0x00,
+    0x87,0x7A,0x45,0x7A,0xD7,0xFB,0xAA,0x82,0xAB,0xA3,0x66,0x7A,0xDD,0xD5,0x95,0x35,
+    0x09,0x93,0xC2,0x38,0x78,0x78,0x78,0x78,0xC2,0x30,0x81,0x28,0x7C,0xA8,0x08,0x08,
+    0xC2,0x30,0xA2,0x28,0xAF,0xEE,0x68,0x18,0x44,0x41,0xA2,0x28,0x2D,0x89,0x8B,0xE2,
+    0x64,0x51,0xE2,0x38,0x2D,0x2D,0x81,0x43,0x85,0x51,0xE3,0x38,0x62,0xE8,0x5A,0x55,
+    0x44,0x41,0xE3,0x38,0x0F,0x7F,0x63,0xB5,0x65,0x49,0x03,0x41,0xF6,0x6F,0x61,0x27,
+    0x85,0x51,0xE3,0x38,0x2F,0x05,0x35,0xAF,0xA5,0x59,0x03,0x41,0xFE,0xD6,0x36,0x2E,
+    0x26,0x6A,0x84,0x59,0xAD,0xA2,0x63,0xDE,0x87,0x82,0x64,0x59,0x00,0x3B,0xFD,0xFD,
+    0x47,0x72,0x64,0x51,0xF8,0xA8,0x5F,0x5D,0xC5,0x59,0x44,0x49,0x0A,0x88,0x9F,0xB5,
+    0xC8,0x7A,0x64,0x49,0x0F,0xBD,0xFF,0x7F,0xD3,0xE5,0x26,0x72,0x0B,0x2D,0xB5,0xF5,
+    0xD4,0xDD,0x10,0xC5,0x00,0x80,0xA0,0xA9,0x14,0xE6,0x93,0xD5,0xA2,0x2F,0x09,0xAB,
+    0x35,0xEE,0x51,0xCD,0xA0,0x08,0x2E,0x16,0x55,0xEE,0xF4,0xDD,0x7D,0xBE,0x82,0xE8,
+    0xB6,0xF6,0x14,0xE6,0x29,0x29,0x89,0x8B,0x96,0xF6,0xF4,0xDD,0x70,0x60,0xC8,0xAA,
+    0x35,0xE6,0x92,0xD5,0x5F,0x5D,0x5F,0x5C,0xB3,0xD5,0x51,0xCD,0xA0,0x7E,0x5E,0x7E,
+    0x25,0x72,0x64,0x59,0x3D,0xD5,0x55,0x55,0x66,0x72,0x63,0x59,0x00,0x29,0xD5,0x55,
+    0x66,0x72,0x63,0x51,0x00,0x00,0x0B,0xD5,0x87,0x7A,0xE5,0x69,0x00,0x08,0x80,0x0D,
+    0x87,0x7A,0x66,0x7A,0xEA,0xA2,0xEE,0xBB,0x66,0x82,0x87,0x7A,0xBB,0xFB,0x7F,0x7F,
+    0x66,0x8A,0x87,0x7A,0x75,0x5F,0xDD,0xDD,0xEC,0xAB,0x87,0x82,0x25,0x05,0x09,0x02,
+    0x69,0x9B,0x43,0x49,0x7C,0x7E,0x5C,0x5C,0x02,0x39,0xA2,0x28,0x7C,0x5C,0xDE,0xF8,
+    0x23,0x41,0xA2,0x28,0xD5,0xD5,0xDD,0x2F,0x24,0x41,0xC2,0x30,0xFA,0x25,0x2D,0x02,
+    0x23,0x41,0xE3,0x38,0xCB,0xF9,0x82,0xE0,0x44,0x49,0xC2,0x30,0x6D,0xFB,0xF0,0xE0,
+    0x64,0x49,0xA2,0x30,0xB5,0xBD,0x2D,0xBA,0x44,0x49,0xE3,0x38,0x2A,0xF0,0xFF,0x9E,
+    0x65,0x51,0x03,0x39,0x83,0xEB,0xF5,0xB7,0xA5,0x59,0x03,0x41,0x2B,0x9F,0x57,0xDF,
+    0xA5,0x59,0x03,0x41,0x20,0xBE,0xD7,0xD7,0x06,0x6A,0x23,0x49,0x0A,0xAA,0xFB,0x5F,
+    0xC6,0x59,0x23,0x41,0xB6,0xF8,0xDB,0x55,0xA5,0x51,0x44,0x49,0x8F,0x25,0xF5,0x55,
+    0xC5,0x59,0x23,0x41,0x2A,0xBE,0xD7,0xF5,0x09,0x8B,0xC5,0x59,0x0F,0xAD,0xFD,0xFD,
+    0xB3,0xDD,0xC8,0x82,0x0B,0x0D,0x35,0x15,0x35,0xE6,0xB3,0xD5,0x8B,0x00,0x82,0x60,
+    0xF3,0xDD,0xF0,0xC4,0x34,0xBE,0xB7,0xFF,0x96,0xEE,0x15,0xE6,0x5E,0xBE,0x2B,0x09,
+    0x96,0xEE,0x55,0xEE,0x63,0x7A,0xFC,0xF8,0x75,0xEE,0x55,0xE6,0xAF,0xFE,0x9F,0xF7,
+    0x55,0xEE,0x92,0xD5,0x78,0x80,0x00,0x00,0x76,0xEE,0x51,0xCD,0x5F,0x7F,0xEA,0x00,
+    0x84,0x59,0x43,0x59,0xE7,0xC5,0xAD,0xAB,0x84,0x61,0x43,0x51,0x6E,0x72,0xD6,0x5F,
+    0x63,0x59,0x23,0x51,0x5F,0xF7,0xFE,0x3F,0xE5,0x69,0x43,0x59,0x25,0xFD,0xFF,0xBF,
+    0x87,0x7A,0x43,0x59,0x02,0xBD,0x57,0x5D,0x87,0x7A,0x43,0x59,0x00,0x00,0x2D,0x55,
+    0xCB,0xA3,0xE5,0x69,0xFF,0x3F,0x2F,0x0D,0xCB,0xAB,0x6A,0x9B,0x22,0xA8,0xBE,0xF7,
+    0x8A,0x9B,0x43,0x49,0x5C,0x78,0x58,0xF8,0x23,0x41,0xC2,0x30,0x5C,0x56,0xB7,0xFE,
+    0x64,0x49,0xC2,0x30,0xAD,0x2D,0x3F,0xAA,0x64,0x49,0x03,0x41,0xFE,0xEA,0x7C,0xF6,
+    0x85,0x51,0x03,0x39,0xD5,0x27,0x05,0xAF,0xA5,0x59,0x24,0x41,0xFD,0xAD,0xAB,0xB2,
+    0x06,0x62,0xE3,0x38,0xDF,0x7B,0x7A,0xF0,0x24,0x41,0xC2,0x30,0x28,0xAE,0xED,0x29,
+    0xA5,0x51,0x03,0x41,0x35,0x15,0xF5,0xD5,0x64,0x51,0x03,0x41,0x94,0xDE,0xFE,0xAA,
+    0x85,0x49,0x23,0x49,0xD7,0xFB,0xE2,0xEE,0x64,0x51,0xE3,0x38,0xA8,0xB8,0xFE,0xDE,
+    0x64,0x49,0xE3,0x38,0xDF,0xDF,0x9F,0xA2,0x64,0x49,0xE3,0x38,0xE8,0x7B,0xF8,0x2B,
+    0x85,0x51,0x23,0x41,0x25,0x25,0xF7,0xF7,0xA8,0x7A,0x44,0x49,0x8B,0x2F,0xAF,0xBD,
+    0x8A,0x9B,0x26,0x72,0x2F,0xBF,0xF5,0xD5,0xD3,0xDD,0x29,0x8B,0x00,0x83,0x81,0x8D,
+    0x51,0xD5,0xD0,0xC4,0x2B,0xAF,0x2D,0xAD,0x96,0xEE,0xAF,0xBC,0x02,0x03,0xFB,0x7F,
+    0x76,0xEE,0x8E,0xB4,0x00,0x00,0xFB,0x55,0x75,0xEE,0x4E,0xAC,0x00,0x80,0x7F,0x55,
+    0x76,0xEE,0x8F,0xB4,0x00,0xFE,0xD5,0xBD,0x15,0xDE,0xB0,0xB4,0x80,0xED,0xFE,0x7E,
+    0x64,0x59,0x23,0x51,0xC0,0x7A,0xFE,0xDF,0x63,0x59,0x23,0x51,0xAB,0xFF,0xB9,0xAA,
+    0x84,0x61,0x43,0x59,0xF5,0xFD,0xBE,0xFB,0x84,0x61,0x43,0x59,0xC2,0x6A,0x5E,0x55,
+    0x63,0x59,0x03,0x49,0xA2,0xEC,0x73,0xDE,0x25,0x72,0x23,0x51,0x55,0x55,0x55,0x95,
+    0x8B,0x9B,0x02,0x51,0x09,0x03,0x02,0x00,0x8B,0x9B,0x29,0x93,0x00,0x0A,0xB6,0xB7,
+    0x49,0x93,0xA4,0x59,0x78,0x60,0xE8,0xE8,0xE5,0x69,0xE3,0x40,0x5F,0x5F,0xF7,0xDC,
+    0x85,0x51,0xE3,0x38,0xFA,0xF2,0x7B,0x5E,0x44,0x49,0xE3,0x38,0x8C,0xEA,0x62,0xE3,
+    0x23,0x41,0xE3,0x38,0xE0,0xEA,0xAB,0xAD,0xC6,0x61,0x23,0x49,0xF1,0x71,0xE3,0xBD,
+    0x85,0x59,0xE3,0x38,0x42,0x4A,0xEA,0x60,0x24,0x41,0xA2,0x30,0x2B,0xAD,0xFD,0xAD,
+    0x85,0x59,0x23,0x41,0xFF,0xAD,0xAF,0x2A,0xA5,0x59,0xE3,0x38,0xE2,0xE8,0xFA,0x7F,
+    0x44,0x49,0xE2,0x38,0x2C,0xBA,0xDF,0x2D,0x44,0x41,0xE3,0x38,0xFA,0xFE,0xEB,0xF0,
+    0x85,0x51,0x03,0x39,0x8B,0xAD,0x7D,0x75,0x64,0x49,0xE3,0x38,0x2F,0xBE,0xBD,0xFD,
+    0x85,0x51,0x23,0x41,0xEA,0x2F,0xE5,0x35,0xE6,0x61,0x44,0x49,0x2D,0xF7,0xAF,0x3D,
+    0xA8,0x7A,0xE5,0x61,0x2A,0x3D,0xF5,0x9F,0x11,0xC5,0xA8,0x7A,0x0D,0x0D,0x25,0x15,
+    0x31,0xCD,0x8E,0xB4,0x2B,0x2F,0xFF,0xD7,0x11,0xC5,0x2E,0xAC,0xC0,0x70,0x7C,0x0B,
+    0x93,0xCD,0x2D,0xAC,0x55,0xAD,0x0B,0x82,0xB4,0xCD,0x6F,0xAC,0x2D,0xA0,0xE0,0xE2,
+    0x94,0xCD,0x2E,0xA4,0x88,0x8A,0xEB,0xDB,0xF1,0xBC,0x8F,0xAC,0x60,0xF2,0x9E,0xBF,
+    0x63,0x59,0x03,0x49,0xBF,0xAE,0xA2,0xA0,0x84,0x59,0x43,0x59,0xFD,0x7D,0x2D,0xCF,
+    0x84,0x61,0x43,0x59,0x7E,0x52,0x7A,0x5F,0x64,0x59,0x23,0x51,0x9B,0xEB,0x7E,0x5F,
+    0x44,0x51,0xE2,0x40,0xE8,0xAA,0xBF,0xFE,0x6B,0x9B,0x03,0x49,0x35,0x25,0x0D,0x09,
+    0xED,0xAB,0x4A,0x93,0x5E,0x7E,0x72,0xE8,0x6A,0x9B,0x29,0x93,0x3D,0xF7,0xB7,0x80,
+    0x09,0x8B,0x47,0x72,0xFC,0x78,0x5C,0x5C,0x67,0x72,0x24,0x49,0x58,0x68,0xA2,0xA8,
+    0xC5,0x61,0xC2,0x38,0x76,0x5F,0x5F,0x78,0x64,0x49,0xE3,0x38,0xCB,0x49,0xFD,0xFD,
+    0x23,0x41,0xE3,0x38,0xAF,0x9E,0xBB,0x25,0x85,0x59,0x03,0x41,0x2F,0x29,0x95,0xBF,
+    0x85,0x59,0xC3,0x38,0x40,0x70,0x70,0x78,0x04,0x41,0xA2,0x30,0x0B,0xF5,0xBB,0xA1,
+    0xA6,0x59,0xE3,0x38,0x02,0x03,0x09,0xAF,0x85,0x51,0xE3,0x38,0x7E,0x5E,0xFC,0x5E,
+    0x64,0x49,0xE3,0x38,0x2F,0x25,0xA5,0xB5,0x44,0x41,0xE2,0x38,0x78,0x6A,0x82,0xEA,
+    0x24,0x41,0xE2,0x38,0xAE,0x2D,0xBF,0x55,0x23,0x39,0xE2,0x30,0xFB,0xAE,0x3F,0xBD,
+    0xA5,0x59,0x23,0x41,0xFD,0xDD,0xB9,0xA3,0xE6,0x61,0x44,0x49,0x95,0xD5,0xB7,0x0B,
+    0x47,0x72,0x84,0x59,0x2B,0xA5,0xFF,0x3F,0x4E,0xB4,0x26,0x72,0x3F,0x3F,0xBD,0xF5,
+    0x55,0xEE,0xD0,0xBC,0x57,0x2A,0x02,0x03,0x35,0xE6,0xD0,0xBC,0xBD,0xC8,0xC0,0xE0,
+    0x93,0xCD,0x52,0xC5,0x43,0x62,0xC2,0xBC,0x93,0xCD,0xB0,0xB4,0x0E,0xBE,0xFA,0x7A,
+    0x52,0xC5,0x4C,0x8B,0xB8,0xAC,0xAF,0xAD,0xD0,0xB4,0x90,0xAC,0xBE,0xF6,0xEA,0x56,
+    0x63,0x59,0x43,0x51,0xAD,0x0D,0x29,0x3B,0x84,0x61,0x43,0x51,0xAA,0xE2,0xD6,0x55,
+    0x63,0x59,0x23,0x51,0xAA,0xEF,0x5A,0x5F,0x43,0x51,0x04,0x49,0xB8,0xEA,0xEA,0xFE,
+    0x44,0x59,0xE2,0x48,0x7F,0x3E,0x0B,0x02,0xAB,0xA3,0xA5,0x61,0x09,0x01,0x03,0x03,
+    0xCC,0xAB,0x49,0x93,0xF7,0x7E,0xF8,0x60,0x6A,0x9B,0xC8,0x82,0x88,0xFB,0x7A,0xDF,
+    0xC8,0x82,0x26,0x72,0x5C,0x7C,0xFC,0x7C,0x46,0x72,0x06,0x6A,0x9E,0xA6,0x2E,0x28,
+    0xA8,0x82,0x03,0x41,0x5A,0x78,0x60,0xC0,0x24,0x41,0xC2,0x30,0x8B,0xAB,0xFD,0x57,
+    0x44,0x49,0xC2,0x30,0x3F,0xBF,0xBD,0x6D,0x65,0x51,0xE3,0x38,0x2E,0xBE,0x7F,0xFD,
+    0xA6,0x59,0xE3,0x38,0x58,0x7A,0x7F,0xFF,0x03,0x39,0xA2,0x30,0x0B,0x2B,0x97,0xB6,
+    0x65,0x49,0x03,0x41,0xCD,0xE9,0xE9,0x81,0x24,0x41,0xE3,0x38,0xFA,0xB6,0xFC,0x54,
+    0x44,0x41,0xE3,0x30,0x3F,0x3F,0xF5,0x55,0x44,0x41,0xC2,0x30,0x7A,0xD8,0xFF,0xF7,
+    0x23,0x39,0xE2,0x30,0xFD,0xAE,0xAB,0xF7,0x23,0x39,0xC3,0x38,0xAB,0x3E,0x9A,0xBA,
+    0x64,0x49,0x03,0x39,0x29,0x75,0x57,0x5F,0x47,0x6A,0x03,0x41,0xAF,0x2D,0xBD,0xFD,
+    0x47,0x72,0xA5,0x59,0x33,0xEF,0xB0,0x63,0x09,0x83,0x26,0x6A,0x25,0xB5,0xEF,0xED,
+    0x15,0xE6,0x8B,0x93,0x03,0x01,0x09,0xA9,0x14,0xE6,0x32,0xC5,0xF8,0xD8,0xDA,0xDE,
+    0x93,0xCD,0xF1,0xBC,0xA0,0xE8,0xBC,0xDA,0x52,0xC5,0x6C,0x8B,0xA0,0xE8,0xE8,0x6A,
+    0x90,0xAC,0xEE,0x9B,0x09,0x89,0xED,0xB9,0x8F,0xAC,0x4F,0xA4,0x3E,0x89,0x59,0x1E,
+    0x63,0x59,0x23,0x51,0xAA,0xC0,0xFE,0xDF,0x43,0x51,0x03,0x49,0x02,0x2B,0xCA,0xFA,
+    0x43,0x51,0x02,0x49,0xBE,0xAE,0xED,0xBB,0x44,0x59,0x03,0x51,0x7F,0xBB,0x3F,0x0F,
+    0xC6,0x69,0x03,0x51,0xFD,0xBF,0xBF,0x3F,0xEC,0xAB,0xE9,0x8A,0x29,0x09,0x2B,0x8A,
+    0x2D,0xB4,0x8B,0x9B,0x78,0xFA,0xAA,0x55,0xAB,0xA3,0x87,0x7A,0xFE,0xFA,0xE0,0x7A,
+    0xA7,0x82,0x25,0x6A,0x7C,0xDC,0x7E,0x5F,0xA8,0x82,0x25,0x6A,0xBD,0x27,0x0D,0x03,
+    0xA8,0x82,0xE5,0x69,0xC0,0x80,0xE8,0x56,0xE5,0x61,0xA2,0x30,0x5F,0x54,0x5C,0x58,
+    0xE3,0x38,0xA2,0x30,0x8B,0xF5,0xD7,0xAA,0x24,0x49,0xC2,0x30,0x2F,0xAD,0xFD,0xBB,
+    0x65,0x49,0x03,0x39,0x7C,0x5F,0x5B,0xFB,0x03,0x41,0xA2,0x28,0xBE,0xB6,0x5E,0xD8,
+    0x65,0x49,0xC2,0x30,0x03,0xAB,0xED,0xED,0x23,0x41,0xA2,0x28,0xF8,0xBE,0x77,0xF7,
+    0x03,0x39,0xC3,0x30,0xEF,0xAB,0x9F,0x35,0x03,0x39,0xC2,0x30,0xBF,0x7D,0xFF,0xFE,
+    0x23,0x41,0xE3,0x38,0x55,0x55,0xFD,0xCB,0x23,0x41,0xC2,0x30,0xF5,0xBE,0xAE,0x20,
+    0x44,0x49,0x03,0x39,0xEF,0xE3,0x7A,0x78,0x44,0x49,0x03,0x41,0x27,0xD5,0xD7,0x5A,
+    0xC5,0x61,0x23,0x41,0x0E,0xBB,0xAF,0xAD,0xA8,0x7A,0xC5,0x61,0x09,0x09,0x0B,0xAB,
+    0x52,0xCD,0xA8,0x7A,0x09,0x09,0x0D,0x2D,0x73,0xCD,0xD0,0xB4,0x8C,0x0C,0x0C,0xC7,
+    0x32,0xC5,0x2E,0xA4,0x80,0xEA,0xF8,0x78,0xF1,0xBC,0xAD,0x93,0x5A,0xBA,0xA8,0xFF,
+    0x31,0xBD,0xED,0x9B,0xAF,0x02,0xBF,0xD5,0x32,0xC5,0x8F,0xAC,0x55,0x5F,0xAA,0x25,
+    0x43,0x51,0x02,0x49,0xB8,0xE0,0xFA,0x6A,0x43,0x51,0x02,0x49,0xD8,0x96,0xB5,0x2D,
+    0x43,0x51,0x23,0x51,0xDD,0xFA,0x3C,0x25,0x44,0x59,0x23,0x51,0xAA,0xA8,0x80,0x4E,
+    0x29,0x93,0x23,0x51,0x95,0x95,0x15,0x35,0xAB,0xA3,0x87,0x7A,0x82,0xE0,0x7A,0x5E,
+    0x0A,0x93,0x67,0x72,0xA0,0x7E,0x55,0x55,0xC8,0x82,0x46,0x72,0x78,0x7F,0x7F,0x77,
+    0x87,0x7A,0x26,0x6A,0xFF,0xAF,0x3F,0x2B,0xC8,0x82,0xC5,0x61,0xA2,0xF8,0x7E,0x5F,
+    0x26,0x6A,0xC4,0x61,0xDE,0xEA,0x2F,0x3F,0x06,0x6A,0x82,0x30,0x78,0xE0,0xC0,0x80,
+    0x03,0x39,0x81,0x28,0x0B,0x3D,0x9F,0xBF,0x44,0x49,0xA2,0x30,0xAF,0x37,0xAF,0x2F,
+    0x65,0x49,0xC3,0x30,0xA8,0xAA,0xEB,0x77,0x24,0x41,0x82,0x20,0xE8,0xE2,0xF2,0x7A,
+    0x24,0x41,0x82,0x20,0xA3,0xBF,0xF5,0xED,0xE3,0x30,0xA2,0x28,0x80,0xF8,0xED,0xB5,
+    0x24,0x41,0xA2,0x30,0x0D,0xAF,0xFF,0xBF,0x04,0x39,0xC2,0x30,0xB4,0xFF,0xFF,0xFF,
+    0x85,0x49,0x03,0x39,0xFF,0xE9,0xE3,0x7D,0x44,0x49,0xE3,0x38,0x80,0xE0,0x5B,0xFD,
+    0x23,0x41,0xE2,0x38,0x82,0x57,0xD5,0x55,0x43,0x41,0xC2,0x30,0xAA,0xA9,0xAF,0x8F,
+    0x85,0x51,0x02,0x39,0x2E,0x3F,0x3D,0x29,0x67,0x72,0xC5,0x59,0xBD,0xCD,0x89,0xDD,
+    0x31,0xC5,0x06,0x62,0x0D,0x0D,0x05,0x25,0x53,0xCD,0x8C,0x8B,0x02,0xEA,0xFF,0x5E,
+    0x90,0xAC,0xAD,0x93,0x78,0x5F,0x55,0x55,0xEE,0x9B,0x4B,0x83,0x22,0x2B,0xEB,0x7E,
+    0x0E,0x9C,0x2B,0x7B,0x30,0xB8,0xD7,0x55,0xF1,0xBC,0x4B,0x83,0x0A,0x0A,0x2B,0xB5,
+    0x23,0x51,0x02,0x41,0xF2,0xEC,0x9E,0xAC,0x23,0x49,0x02,0x49,0x80,0xCB,0xEA,0x0C,
+    0x43,0x51,0x23,0x51,0xA1,0xE3,0x8F,0xA7,0x44,0x51,0x02,0x49,0xB8,0x68,0xFA,0x5E,
+    0x09,0x8B,0x03,0x49,0x35,0x35,0x25,0x25,0xE9,0x8A,0x47,0x72,0xF8,0xF8,0xFA,0xFE,
+    0x87,0x7A,0x67,0x72,0xFF,0xAA,0x80,0x00,0x87,0x7A,0x46,0x72,0x7E,0x7E,0xD8,0x5A,
+    0x87,0x7A,0x26,0x6A,0xAB,0xCB,0xCA,0x7A,0x26,0x72,0xA4,0x61,0x7C,0xDE,0xB6,0x2F,
+    0x87,0x7A,0xE5,0x61,0xD5,0xD5,0x8B,0xAA,0x87,0x7A,0x23,0x41,0xEA,0x60,0xC0,0xEA,
+    0x23,0x41,0x81,0x28,0xB7,0xA5,0x0D,0x0B,0x44,0x49,0xE2,0x38,0xEF,0x43,0x4F,0x57,
+    0xC2,0x30,0x82,0x20,0x20,0xFE,0x7A,0x5F,0xE3,0x30,0x61,0x20,0x78,0xDE,0xF7,0xFD,
+    0xC3,0x28,0x82,0x20,0xC9,0xBD,0xD5,0xB7,0xE3,0x30,0xA2,0x28,0xA7,0xEB,0xFF,0xBF,
+    0xE3,0x30,0xA2,0x28,0x0F,0xEB,0xA8,0x9E,0x03,0x39,0xC3,0x30,0xDD,0xB5,0xF5,0x95,
+    0x03,0x39,0xC2,0x30,0xA2,0x8A,0x0A,0xA7,0x03,0x41,0xE2,0x30,0xA2,0xCE,0xBF,0x2F,
+    0x65,0x49,0xE2,0x38,0xD7,0xFD,0xAD,0x0F,0x43,0x49,0xE3,0x30,0xB6,0xDF,0x5B,0xE0,
+    0x84,0x49,0xE2,0x38,0x2D,0x97,0xBD,0xFF,0x06,0x62,0x63,0x49,0x2D,0x3F,0xD5,0xB5,
+    0x6F,0xAC,0xE6,0x59,0x25,0x35,0x35,0x35,0xD0,0xB4,0xCA,0x72,0xF8,0xF8,0x5A,0x60,
+    0xAD,0x8B,0x07,0x5A,0x00,0x80,0xFA,0x57,0x4B,0x7B,0x68,0x5A,0x20,0xEB,0xFD,0xF5,
+    0xED,0x93,0xEA,0x72,0xD5,0xF5,0xB5,0x0D,0x0E,0x9C,0x4B,0x83,0x3D,0xFD,0xCF,0x08,
+    0x23,0x49,0x03,0x49,0x1B,0xA3,0xE8,0x97,0x43,0x51,0x23,0x51,0x75,0xA5,0x6B,0xF8,
+    0x43,0x51,0x03,0x49,0xA2,0x7E,0xDE,0x7F,0x64,0x51,0xE2,0x48,0xFF,0xFF,0xFF,0x1F,
+    0xE8,0x82,0x02,0x49,0x05,0x09,0x03,0x00,0xC7,0x82,0x87,0x7A,0x57,0x5F,0x77,0xF8,
+    0xA7,0x7A,0x66,0x72,0xEB,0xBA,0x7A,0x1C,0xAA,0x9B,0x67,0x72,0x55,0xD5,0x2D,0xC2,
+    0x49,0x93,0xE5,0x61,0xAF,0xE0,0x5C,0x55,0x67,0x7A,0x23,0x49,0xA8,0xAA,0x5A,0xD7,
+    0x46,0x72,0x43,0x41,0x02,0x2A,0x55,0x55,0x47,0x72,0x03,0x41,0xC0,0xE8,0xF5,0xD5,
+    0x23,0x41,0x81,0x28,0xAA,0xA8,0xE0,0x7A,0x23,0x39,0x81,0x20,0x68,0x7F,0x57,0x5D,
+    0xC3,0x28,0x61,0x18,0xDF,0xBF,0xB5,0x29,0x03,0x39,0x82,0x20,0xFD,0xAF,0xA3,0x02,
+    0xE2,0x30,0x82,0x20,0xD7,0xFA,0x2E,0xAC,0xE2,0x30,0xA2,0x28,0xD5,0xDF,0x5C,0x7A,
+    0xE3,0x30,0x81,0x28,0x3E,0x2B,0xBF,0xED,0x04,0x39,0xA2,0x28,0x8B,0x22,0x3F,0xFD,
+    0x24,0x39,0xC3,0x30,0x3D,0xEA,0xAE,0xD5,0x03,0x39,0xE2,0x30,0xA0,0x54,0x38,0x38,
+    0x44,0x41,0xE2,0x38,0x0F,0xBD,0xB7,0x17,0x64,0x49,0x03,0x41,0xE0,0xB0,0xB2,0x58,
+    0x44,0x41,0xE2,0x38,0x3F,0xCA,0x2A,0xF5,0xA5,0x51,0xE2,0x38,0x2A,0xAF,0x2A,0xBD,
+    0x0E,0xA4,0xC5,0x59,0x35,0x15,0x95,0x95,0x52,0xC5,0x6F,0xAC,0x70,0xC2,0x29,0xB5,
+    0x52,0xC5,0xEA,0x72,0x5F,0xAA,0xA0,0x80,0x6F,0xA4,0x89,0x62,0xD5,0x00,0x00,0x00,
+    0x6F,0xA4,0x6B,0x83,0x2D,0x2A,0x28,0x80,0x6F,0xAC,0xCD,0x93,0xB6,0x3E,0x3A,0xAA,
+    0x64,0x59,0xE2,0x40,0x3F,0xA9,0x0A,0x02,0x43,0x51,0x02,0x49,0x88,0xA8,0x68,0xF8,
+    0x22,0x49,0x03,0x49,0xFE,0x5A,0xF8,0x7F,0xCB,0xA3,0x03,0x49,0x95,0x35,0x35,0x25,
+    0x6A,0x9B,0xC7,0x82,0x5F,0x78,0x78,0xF8,0x8A,0x9B,0x86,0x7A,0x77,0x57,0x9F,0x2F,
+    0xCB,0xA3,0x66,0x7A,0x35,0x0B,0xE2,0x58,0x8A,0x9B,0xA4,0x59,0x70,0x7E,0x5F,0x5F,
+    0xE5,0x61,0x43,0x49,0x0A,0x82,0x62,0x5C,0x84,0x51,0x24,0x41,0x78,0xFF,0xFB,0xBF,
+    0x06,0x62,0x03,0x41,0x5D,0xFD,0xA2,0x78,0xA4,0x51,0xC2,0x38,0xEF,0xFA,0x70,0x7F,
+    0xE3,0x38,0x61,0x18,0xC8,0xEA,0xFE,0x6E,0xC2,0x30,0x61,0x18,0xDF,0x5F,0xD7,0x25,
+    0xC2,0x28,0x81,0x20,0x3D,0xFA,0xB8,0xA2,0xE3,0x30,0xA2,0x28,0xA0,0xE7,0x0B,0x82,
+    0xE2,0x30,0xA2,0x28,0xF2,0xC2,0x39,0x3F,0xE3,0x30,0xA2,0x28,0xD5,0xFA,0xF0,0xB8,
+    0xC2,0x30,0xA2,0x28,0xFD,0xFA,0x96,0xA4,0xE2,0x30,0xA2,0x28,0xAF,0xB5,0xFF,0xFF,
+    0x03,0x31,0xC2,0x30,0x35,0xFF,0xE7,0xB5,0x23,0x39,0xC2,0x30,0xB0,0xB2,0xF9,0xDD,
+    0x44,0x41,0xC2,0x30,0x9F,0x3F,0xAF,0xBF,0x85,0x51,0xE3,0x30,0x78,0x78,0x5F,0xD5,
+    0x24,0x39,0xC3,0x28,0xA2,0xEB,0xEB,0xBE,0xA5,0x51,0x03,0x39,0xBD,0x0D,0xA5,0xF5,
+    0x88,0x6A,0x64,0x49,0x35,0x3F,0x37,0x3D,0xD0,0xB4,0xAD,0x93,0x2B,0xBF,0xF5,0x55,
+    0x31,0xBD,0xED,0x9B,0x80,0xAB,0xAF,0xD5,0xF0,0xB4,0x4F,0xA4,0xDF,0xFE,0xF8,0xAA,
+    0xB0,0xAC,0x4E,0xA4,0xFF,0xFF,0x5F,0xE2,0x6F,0xAC,0x0E,0x9C,0xA8,0xA0,0xFA,0x7A,
+    0x64,0x51,0x23,0x49,0x0B,0x8B,0xEF,0xDD,0x43,0x51,0x02,0x49,0xFC,0x5E,0x57,0x57,
+    0x23,0x49,0xE2,0x40,0xEA,0xBE,0xBB,0xA7,0x6A,0x93,0x23,0x49,0x05,0x0D,0x0D,0x09,
+    0x6A,0x9B,0x08,0x8B,0x5A,0xFE,0xAA,0x02,0xCB,0xA3,0x66,0x72,0x02,0xC2,0x72,0x5E,
+    0x29,0x93,0x05,0x62,0xFC,0xDF,0xFF,0x7F,0x46,0x72,0x43,0x49,0xF8,0x7C,0x57,0x55,
+    0x84,0x51,0x44,0x49,0xFE,0xB3,0x98,0xE8,0x64,0x51,0x03,0x39,0x3A,0xFA,0x7E,0x7A,
+    0xC5,0x61,0xE2,0x40,0x60,0xE0,0xEB,0xE5,0x03,0x41,0xC2,0x30,0xE8,0x7C,0xFE,0x7E,
+    0xE2,0x30,0x61,0x18,0x6A,0x58,0x7A,0x57,0x24,0x39,0x61,0x18,0xBD,0xAD,0x0B,0xFF,
+    0x23,0x39,0xA2,0x28,0xFF,0x82,0xA8,0xB5,0x03,0x39,0xA2,0x28,0xDF,0xFF,0xAA,0xB8,
+    0x03,0x39,0xA2,0x28,0xAB,0x8A,0xA3,0xEF,0x03,0x31,0x82,0x20,0x88,0xA8,0xBA,0xD7,
+    0xE3,0x30,0xA2,0x28,0x56,0x7E,0x80,0x82,0xE3,0x30,0x81,0x28,0xFA,0x5F,0xFE,0x0A,
+    0x03,0x39,0xA2,0x28,0xFD,0xBD,0xBB,0xF8,0xE2,0x30,0xA1,0x28,0x8B,0xE2,0xBA,0xFF,
+    0x03,0x31,0xC2,0x28,0xB9,0x0D,0x8A,0xEB,0x03,0x31,0xC3,0x30,0xFB,0xF8,0xD6,0x7D,
+    0x03,0x31,0xC2,0x30,0x1F,0xAF,0x27,0x2E,0x64,0x49,0xC2,0x28,0x2F,0x0F,0xAF,0x25,
+    0x4B,0x8B,0x64,0x49,0xBD,0x35,0x25,0x2D,0xEE,0x9B,0x6B,0x8B,0xFA,0xFA,0x60,0x6A,
+    0xED,0x9B,0x2A,0x83,0x02,0x2B,0x2F,0xB7,0x6F,0xA4,0xCD,0x93,0x02,0xF7,0xFF,0x55,
+    0x6F,0xAC,0xCD,0x93,0xC8,0x7F,0x55,0x55,0x2E,0x9C,0xAC,0x93,0x2A,0xAF,0xB5,0xD5,
+    0x23,0x49,0x02,0x41,0xE0,0xEE,0xEF,0xDF,0x23,0x49,0xE2,0x40,0xFA,0x76,0xFF,0xAE,
+    0x23,0x49,0xE2,0x40,0xFF,0xAD,0x8F,0xAA,0x49,0x93,0x03,0x49,0x01,0x09,0xF5,0xD5,
+    0x29,0x93,0x84,0x59,0x00,0xA8,0xEA,0x7F,0xC8,0x82,0x03,0x41,0xA8,0xAA,0xFF,0xD5,
+    0x67,0x72,0x43,0x51,0x60,0x7E,0x57,0xDF,0x85,0x51,0x22,0x41,0x37,0xB7,0x03,0xA2,
+    0x84,0x49,0x44,0x49,0x62,0x7A,0x7E,0xD7,0xE6,0x61,0x23,0x41,0x57,0x55,0xBD,0x82,
+    0xC4,0x59,0x03,0x39,0x55,0xD5,0x7F,0x5C,0x23,0x41,0xA2,0x28,0x68,0x6E,0x6A,0xEC,
+    0x03,0x31,0x61,0x20,0xD5,0xF7,0xEB,0xAB,0x81,0x28,0xC2,0x20,0xE8,0xAA,0x8F,0xAB,
+    0xE3,0x30,0x81,0x28,0x97,0xD5,0xDF,0x70,0x23,0x41,0xA1,0x28,0x7E,0xFB,0xEB,0x83,
+    0xE3,0x30,0xA2,0x28,0x29,0xFB,0xDF,0x37,0x03,0x39,0x81,0x28,0xDE,0xFF,0xF7,0xE0,
+    0x03,0x31,0xA2,0x28,0xEF,0xB9,0xA9,0x89,0x03,0x39,0xC2,0x30,0xFD,0x69,0xEE,0x75,
+    0x03,0x39,0xC2,0x30,0xF3,0xEB,0x0D,0x8D,0xE3,0x30,0xC2,0x28,0x71,0x4B,0xEE,0x54,
+    0xE3,0x30,0xA1,0x28,0x02,0x87,0x8F,0xBF,0x03,0x31,0xC2,0x28,0xFB,0xB7,0xBA,0xEB,
+    0x23,0x39,0xE2,0x30,0xBD,0xDF,0x57,0xDD,0x84,0x51,0xE2,0x30,0x37,0x2D,0x3B,0x8B,
+    0x2D,0xA4,0x84,0x51,0xA5,0xED,0x09,0x0B,0x8F,0xB4,0xA8,0x72,0xFF,0x55,0xEA,0x00,
+    0xCD,0x9B,0x67,0x62,0xBF,0x55,0xFF,0xF8,0x4B,0x83,0x47,0x62,0xBC,0x57,0xFF,0xFF,
+    0xAC,0x8B,0x67,0x62,0x00,0x2D,0xB5,0x57,0xAD,0x93,0x09,0x7B,0x00,0x22,0xAA,0xA9,
+    0x02,0x41,0xE3,0x40,0x30,0xAE,0x00,0xB0,0x23,0x49,0xE2,0x40,0xAF,0xAA,0x22,0xE6,
+    0x23,0x41,0xE2,0x40,0x0A,0xE0,0xE0,0x9C,0x44,0x49,0xE2,0x40,0x36,0xBD,0xFF,0xF5,
+    0xE5,0x61,0x02,0x41,0xE0,0x5F,0x55,0x55,0x06,0x62,0xE2,0x40,0xB5,0x35,0x35,0x35,
+    0xE5,0x61,0x84,0x51,0x5E,0xFE,0x78,0xE0,0xA5,0x51,0x23,0x41,0xE8,0xE8,0xEF,0xD7,
+    0x26,0x6A,0x44,0x49,0x35,0x05,0x25,0xD5,0xE4,0x61,0x82,0x30,0xA0,0xF8,0x5C,0x56,
+    0x84,0x51,0xC2,0x30,0x78,0xDA,0xFF,0xF5,0x03,0x39,0x81,0x20,0x7A,0xFA,0xF8,0x5F,
+    0xC2,0x28,0x82,0x28,0x81,0x83,0xA2,0x8B,0x64,0x49,0xA2,0x28,0xAD,0x89,0x8B,0x7B,
+    0x24,0x41,0x81,0x28,0x88,0xA8,0xAA,0xFD,0x44,0x49,0xE2,0x38,0x0D,0x2F,0xD7,0xDD,
+    0x44,0x41,0xA1,0x28,0xDE,0x5C,0x7A,0xFA,0x04,0x39,0x81,0x28,0x00,0xA3,0xFF,0xD7,
+    0xE3,0x30,0xA2,0x28,0xC0,0xF5,0xF7,0xAD,0xE3,0x30,0xA2,0x28,0x0F,0xAF,0x57,0x78,
+    0x03,0x31,0xA2,0x28,0x2F,0xFF,0xAD,0xAF,0x03,0x31,0xC2,0x28,0x5F,0x7F,0xD5,0xE3,
+    0x23,0x39,0xC2,0x28,0xD5,0xFD,0xAF,0xBF,0x03,0x39,0xC2,0x30,0x8B,0xBF,0xA6,0xAA,
+    0x03,0x39,0xC2,0x30,0xFF,0xCA,0xAB,0x2A,0x4A,0x8B,0x03,0x39,0xF5,0xB5,0xB5,0x35,
+    0x31,0xC5,0x4A,0x83,0xA9,0x82,0x02,0x00,0x10,0xC5,0x6E,0xAC,0xBF,0xF7,0x7C,0xA0,
+    0x6E,0xAC,0x0A,0x83,0x5C,0x70,0x80,0x80,0x6B,0x93,0x67,0x6A,0xD5,0xF7,0xDE,0xE8,
+    0x4A,0x83,0x47,0x62,0x7E,0xEA,0xAA,0x02,0x4B,0x83,0xA5,0x49,0x0F,0xDF,0x7E,0xF8,
+    0x23,0x49,0xE3,0x40,0xBF,0xAB,0xAB,0xBE,0x23,0x49,0x03,0x41,0xF5,0xBF,0x4F,0x77,
+    0x03,0x41,0xC2,0x38,0x28,0x2C,0xAE,0xFE,0x03,0x41,0xE2,0x38,0xA2,0xAF,0x79,0x65,
+    0x02,0x41,0xE2,0x38,0x32,0x2B,0xFD,0xAF,0x26,0x6A,0xE2,0x40,0x35,0x35,0x35,0x15,
+    0x26,0x6A,0x23,0x41,0xE8,0x68,0x68,0x68,0x44,0x41,0x03,0x39,0xA2,0x35,0x7D,0x5D,
+    0x44,0x41,0xE2,0x30,0xBA,0x68,0x4A,0xBF,0xA4,0x51,0xA2,0x28,0x70,0x7B,0x57,0x7F,
+    0xC2,0x28,0x81,0x20,0x83,0xC2,0x60,0x0A,0xE3,0x28,0x61,0x20,0xD7,0xF5,0xAB,0x22,
+    0xE3,0x30,0xA2,0x28,0xFF,0xF9,0xAB,0x8A,0x03,0x31,0xA2,0x28,0x73,0x57,0x5F,0xFE,
+    0xC2,0x28,0x81,0x20,0x5B,0x78,0xBE,0xAF,0x03,0x41,0x81,0x20,0x0B,0xAD,0xFF,0x57,
+    0x44,0x41,0xA2,0x28,0xFA,0xEA,0x8B,0xE5,0xE2,0x30,0x81,0x28,0xEE,0x3B,0xFD,0xA8,
+    0x03,0x39,0x81,0x20,0xF5,0xDE,0xAF,0x2A,0x24,0x41,0xA2,0x28,0x5F,0x5F,0x5F,0xE0,
+    0x03,0x39,0x82,0x28,0xFF,0xBD,0xE3,0xEA,0x03,0x31,0x81,0x28,0xA2,0xB3,0xFF,0xDF,
+    0xE2,0x30,0xA2,0x28,0x28,0xA8,0x95,0xDF,0x23,0x39,0xC2,0x30,0xAB,0x23,0xF7,0xFF,
+    0x65,0x51,0x03,0x39,0xD7,0xBD,0xBD,0x39,0x6C,0x93,0x85,0x51,0x35,0xB5,0xAD,0xAD,
+    0xF0,0xBC,0x0A,0x83,0x02,0x2D,0xD5,0x55,0xF0,0xBC,0xE9,0x7A,0x00,0x00,0x03,0xFD,
+    0x10,0xC5,0x6E,0xAC,0x7A,0xEA,0xA2,0x8B,0x6E,0xAC,0x6B,0x8B,0x7E,0xAA,0xA8,0x80,
+    0x2D,0xA4,0x0A,0x7B,0x75,0xE8,0x00,0x00,0x4E,0xA4,0x68,0x62,0x7F,0xFA,0x80,0x00,
+    0x03,0x41,0xE2,0x40,0x34,0x27,0xF8,0xBB,0x23,0x49,0xE2,0x38,0xEA,0x7E,0x7F,0x55,
+    0x03,0x41,0xC2,0x38,0xFF,0xAA,0xAF,0xAB,0x03,0x41,0xC2,0x38,0xA3,0xBB,0xFE,0xBA,
+    0x03,0x41,0xE2,0x38,0xFA,0x5F,0xF5,0xFD,0x05,0x62,0xE2,0x40,0x15,0x15,0x15,0x95,
+    0x46,0x6A,0x03,0x39,0x68,0x60,0x60,0x68,0x03,0x39,0xE2,0x30,0x02,0xAB,0x25,0x3B,
+    0x23,0x39,0xE3,0x38,0x8A,0x2B,0x8B,0xBF,0x44,0x41,0xE3,0x30,0x6F,0xFA,0xA2,0xAA,
+    0x44,0x39,0xE3,0x30,0x55,0xBF,0xFC,0xFA,0x24,0x41,0xE3,0x30,0x7F,0xFF,0xFA,0x3B,
+    0x23,0x39,0xE3,0x30,0x55,0x7F,0xFE,0xFA,0x03,0x31,0xC3,0x28,0xFF,0xFF,0x2A,0xCA,
+    0x03,0x31,0xA2,0x20,0x57,0x7E,0xAA,0xAA,0xE3,0x28,0x82,0x20,0x5D,0xF6,0xAA,0xA2,
+    0x03,0x39,0x82,0x20,0x3D,0xBD,0x77,0x7F,0xE3,0x30,0x82,0x20,0x02,0x0A,0x2B,0x35,
+    0x23,0x41,0xA2,0x30,0xAA,0xDE,0xFE,0xFE,0x44,0x41,0xC2,0x30,0xE0,0xCA,0x75,0xDD,
+    0xE2,0x30,0xA2,0x30,0x8F,0xAF,0xA9,0x22,0x22,0x39,0xA2,0x28,0x55,0xF5,0xFD,0x3F,
+    0x44,0x41,0xA1,0x28,0xD7,0xDD,0xFE,0xA2,0x43,0x41,0xE3,0x30,0xBB,0x35,0xA9,0x8B,
+    0x47,0x62,0x23,0x41,0xF5,0x95,0x25,0x2B,0xE9,0x7A,0xC5,0x59,0x09,0x2B,0x8A,0x2A,
+    0x0A,0x83,0xA9,0x72,0x2A,0x2B,0xFB,0xFF,0x2B,0x83,0xC9,0x7A,0x2F,0x28,0xEB,0xFF,
+    0xCF,0xB4,0x0A,0x83,0x2D,0xDD,0x55,0x55,0x6E,0xAC,0x0A,0x83,0x00,0x0A,0xB5,0x55,
+    0x6E,0xAC,0x4A,0x8B,0x00,0x00,0x00,0x25,0xAF,0xB4,0x4E,0xAC,0x7F,0xAB,0x0A,0x0B,
+    0x03,0x41,0xC2,0x38,0xA0,0xC0,0xE8,0xFE,0x03,0x41,0xE2,0x38,0xD5,0xAD,0xD1,0x79,
+    0x02,0x41,0xE2,0x38,0x7D,0x5D,0x55,0xF5,0x03,0x41,0xE2,0x38,0x77,0x57,0x5D,0xD7,
+    0xE2,0x38,0xC2,0x38,0x00,0x00,0x00,0xA8,0x06,0x62,0xE2,0x38,0x95,0x15,0x95,0x15,
+    0x67,0x72,0x03,0x41,0x68,0x68,0x78,0x78,0x03,0x39,0xE2,0x30,0x5E,0xEE,0xDF,0xF7,
+    0x02,0x39,0xE3,0x30,0xDF,0x99,0x55,0x75,0x23,0x39,0xE3,0x30,0x0B,0xA7,0xFF,0xD5,
+    0x24,0x39,0xE3,0x38,0x68,0xBB,0xFF,0x5F,0x24,0x41,0xE3,0x30,0xFF,0x29,0x8F,0xAE,
+    0x24,0x41,0x03,0x39,0x71,0x57,0x7A,0x5C,0x24,0x39,0xE2,0x30,0xFF,0xFA,0xBD,0xAE,
+    0x03,0x31,0xE3,0x30,0x60,0xAE,0x2E,0x03,0x03,0x31,0xC2,0x28,0xFF,0xEB,0xC8,0x00,
+    0x03,0x31,0xA2,0x20,0x7E,0xFB,0xBA,0xA8,0xE2,0x28,0xA2,0x28,0x55,0x67,0x73,0xAA,
+    0x03,0x31,0x81,0x20,0xA2,0xAD,0xDF,0x7F,0x03,0x39,0x82,0x20,0xA2,0xA8,0x0B,0xF5,
+    0x03,0x31,0xC2,0x30,0xF7,0x2E,0x82,0xA9,0x23,0x39,0xC2,0x28,0xB9,0xA9,0xAD,0x2F,
+    0x23,0x41,0xC2,0x28,0xA0,0xF8,0xDC,0xFE,0xA5,0x51,0xC2,0x28,0xFF,0xB7,0x3D,0x2F,
+    0x68,0x6A,0xC5,0x51,0xBD,0x3D,0xA9,0xBF,0xC9,0x72,0x48,0x6A,0xAB,0xAB,0xAF,0x3D,
+    0xE9,0x7A,0x89,0x72,0x8F,0xFF,0xB5,0xBB,0xEA,0x82,0xA9,0x7A,0x3B,0xB9,0xFB,0xF7,
+    0x0A,0x83,0xC9,0x72,0x3A,0xBF,0xE9,0xAB,0x0A,0x83,0xC9,0x7A,0xA2,0x0E,0xF7,0xDA,
+    0x4B,0x8B,0xEA,0x7A,0x2F,0x5D,0xFD,0x55,0x8F,0xAC,0x0A,0x83,0x0B,0xBD,0x55,0x55,
+    0x03,0x39,0xC2,0x38,0xE7,0xBF,0xEB,0xEB,0x03,0x41,0xE2,0x38,0x5B,0x7F,0x55,0xD5,
+    0x22,0x39,0xC2,0x38,0xF7,0xDD,0xF6,0xFF,0xE2,0x38,0xC2,0x38,0xAA,0xEA,0x02,0x0A,
+    0xE2,0x38,0xC2,0x38,0x80,0xC0,0xDA,0x2A,0x84,0x51,0xC2,0x30,0x35,0x95,0xD7,0x57,
+    0x26,0x6A,0x03,0x39,0x78,0x78,0x7A,0x68,0x03,0x39,0xE3,0x30,0x57,0x56,0x5A,0xBD,
+    0xE2,0x30,0xC3,0x30,0x0F,0x23,0x03,0x82,0x03,0x31,0xE3,0x30,0xDD,0x97,0xF9,0x55,
+    0x03,0x31,0xA2,0x30,0x82,0x2A,0xA2,0xCA,0x03,0x39,0xC3,0x30,0x0A,0xAE,0x2A,0x2A,
+    0x23,0x39,0xE3,0x30,0x82,0xAF,0xAA,0xF7,0xE3,0x38,0x24,0x31,0xAB,0xEB,0xEE,0xCA,
+    0x23,0x39,0xE3,0x38,0xFF,0x2E,0xAE,0xFE,0x23,0x39,0xE2,0x30,0xFA,0x8F,0x7E,0xE8,
+    0x23,0x39,0xE3,0x30,0x7F,0xA8,0xAA,0xBF,0x23,0x39,0xC2,0x28,0xF7,0xBA,0xEA,0x8A,
+    0x03,0x31,0xA2,0x20,0x7F,0xBA,0x88,0x00,0x03,0x31,0x81,0x20,0xD7,0xFE,0xAA,0x08,
+    0xE3,0x30,0x82,0x20,0x2D,0xFF,0xAE,0x00,0x24,0x39,0xA2,0x20,0x2F,0xF5,0xBF,0x2A,
+    0x65,0x41,0xC2,0x28,0xF7,0xF5,0xAF,0x2E,0x27,0x62,0x03,0x31,0xAD,0x2B,0x2A,0x02,
+    0x68,0x6A,0xE6,0x59,0xBD,0xAD,0x2D,0x0F,0xC9,0x72,0x48,0x6A,0xBF,0xBA,0x8B,0xB7,
+    0xC9,0x72,0x88,0x72,0xAA,0xFF,0xBE,0x6D,0xC9,0x7A,0xA8,0x72,0x28,0x81,0x8F,0x7B,
+    0xC9,0x7A,0xA9,0x72,0xD0,0x6B,0x20,0x02,0xE9,0x7A,0xA9,0x72,0xAA,0xB6,0x2D,0xBA,
+    0x0A,0x83,0xA9,0x72,0x2A,0xB7,0xF7,0xFF,0x0A,0x83,0xC9,0x7A,0x8B,0x8B,0xA5,0x9B,
+    0x03,0x41,0xC2,0x38,0xAE,0xAE,0xEB,0xFB,0x03,0x41,0xC2,0x38,0xFB,0xEA,0xBB,0xDE,
+    0xE2,0x38,0xC2,0x38,0x80,0x26,0xAB,0x32,0xE2,0x38,0xC2,0x38,0x8A,0xE0,0xB0,0xB0,
+    0xE2,0x38,0xA2,0x30,0x08,0x2A,0x62,0xFC,0xE5,0x59,0xC2,0x38,0x95,0x15,0x95,0x55,
+    0xA8,0x72,0xE3,0x38,0x78,0x78,0x5E,0x55,0x03,0x39,0xE3,0x30,0xF6,0xD7,0xFC,0xD5,
+    0x03,0x31,0xE3,0x30,0x7D,0xFB,0xD7,0x55,0xE3,0x30,0xC2,0x28,0x20,0x2A,0xB2,0x0B,
+    0x03,0x31,0xE3,0x30,0x55,0x55,0xB5,0xED,0x03,0x31,0xC2,0x30,0xAA,0xF7,0xAE,0xBA,
+    0x03,0x31,0xC2,0x30,0x2E,0x8B,0xBF,0x3E,0x03,0x31,0xC3,0x30,0x9A,0xA8,0xAB,0xAA,
+    0xE3,0x38,0x24,0x31,0xAA,0xAA,0xEE,0xAA,0x24,0x39,0xE3,0x30,0xFB,0xEE,0xAF,0xEB,
+    0x24,0x39,0x03,0x39,0x57,0x75,0xDD,0xD5,0x24,0x39,0xE2,0x30,0xA3,0xF6,0xA8,0x0A,
+    0x03,0x39,0x64,0x31,0xAA,0xA8,0x8A,0x2A,0x64,0x41,0x03,0x39,0x57,0xFF,0xAF,0x3D,
+    0x85,0x49,0x03,0x31,0x55,0xDF,0xAB,0x08,0xC6,0x51,0x03,0x31,0x55,0xFD,0xBB,0x22,
+    0x07,0x62,0x44,0x41,0x95,0xAD,0x0B,0x00,0x47,0x62,0xE6,0x59,0x95,0xAD,0x0E,0x82,
+    0x88,0x72,0x27,0x62,0xBD,0x2F,0x2F,0x8F,0xA8,0x72,0x48,0x62,0xBF,0xAE,0x3E,0x27,
+    0xC9,0x72,0x88,0x6A,0xB5,0x9D,0xED,0xF2,0xA9,0x72,0x68,0x6A,0xA0,0x20,0xA8,0x7C,
+    0xC9,0x72,0x89,0x72,0x0E,0xFE,0xBF,0x2D,0xC9,0x7A,0x88,0x6A,0x02,0x2A,0xFE,0x63,
+    0xEA,0x7A,0xA9,0x72,0x2F,0xE2,0x7D,0xF5,0x0A,0x7B,0xA9,0x72,0xB2,0xAB,0xED,0xBF,
+};
+
+static const size_t pixel_3_width = 64;
+static const size_t pixel_3_height = 64;
+static const size_t pixel_3_size = 2048;
+static const unsigned char pixel_3_data[2048] =
+{
+    0x26,0x5A,0x43,0x41,0xFE,0x7B,0xFA,0xB4,0x05,0x52,0x23,0x39,0xFF,0xFF,0x4F,0xFE,
+    0xA5,0x49,0x43,0x39,0xDB,0x64,0x5E,0x8B,0x26,0x6A,0x44,0x41,0xFF,0x7F,0x69,0x03,
+    0x2A,0x83,0x44,0x41,0x55,0x77,0x55,0x02,0x6E,0xA4,0x84,0x49,0x55,0x55,0x55,0x0A,
+    0x52,0xC5,0xA5,0x49,0x55,0x55,0x55,0x00,0xF4,0xE5,0xC5,0x51,0x75,0x55,0x55,0x38,
+    0x97,0xEE,0x64,0x49,0x5D,0x55,0xFF,0x00,0xB6,0xEE,0x84,0x49,0x55,0x55,0xBB,0x00,
+    0x75,0xEE,0x64,0x49,0x0D,0x35,0x0A,0x00,0xD7,0xF6,0x34,0xE6,0xA2,0x6C,0x9E,0x27,
+    0xF7,0xF6,0x55,0xE6,0x02,0xED,0xD7,0xBA,0x38,0xFF,0x76,0xEE,0xAA,0xAB,0xA7,0xAB,
+    0xD7,0xF6,0x34,0xE6,0x60,0xE0,0xF8,0x50,0x14,0xDE,0x92,0xD5,0xA2,0x01,0x01,0x83,
+    0xB6,0xEE,0x8B,0x8B,0x57,0x00,0x00,0x00,0xB6,0xEE,0xED,0x9B,0xF5,0x00,0x00,0x00,
+    0xB6,0xF6,0x51,0xC5,0xF5,0x00,0x00,0x00,0xB3,0xD5,0xC5,0x69,0xD4,0x54,0x54,0x56,
+    0xB6,0xF6,0xE5,0x69,0x02,0x03,0x0D,0x05,0xD6,0xF6,0xB6,0xF6,0xD5,0x15,0x37,0xAE,
+    0xD7,0xF6,0x46,0x7A,0x00,0x00,0xC0,0x70,0xF7,0xFE,0x67,0x7A,0x96,0x17,0x35,0x35,
+    0x18,0xF7,0xD7,0xF6,0x72,0xF8,0xF0,0xF0,0xF7,0xF6,0xB6,0xF6,0xEB,0xAA,0x2E,0xCA,
+    0xD7,0xF6,0x14,0xDE,0xE0,0x60,0xDC,0x36,0xD7,0xF6,0xD3,0xDD,0xB9,0x82,0x00,0x00,
+    0x18,0xFF,0xB6,0xEE,0x7D,0xF5,0x25,0x3F,0x38,0xFF,0xB7,0xEE,0xCB,0xEB,0xFF,0x7C,
+    0xB6,0xEE,0x71,0xCD,0xF0,0xD8,0xD2,0xF2,0x96,0xEE,0x31,0xC5,0xAB,0x8F,0x8B,0x89,
+    0xD6,0xF6,0xB6,0xE6,0x8A,0x22,0x88,0x02,0xF7,0xF6,0xB6,0xEE,0x5F,0x5E,0x7A,0xFA,
+    0xF7,0xF6,0xB6,0xEE,0xED,0xAB,0xA9,0x2B,0x96,0xEE,0x44,0x51,0x56,0x54,0x54,0x5C,
+    0x6E,0xB4,0x23,0x49,0x2D,0xAD,0xFD,0xFF,0x14,0xE6,0x06,0x6A,0x02,0xF7,0xFD,0x55,
+    0x55,0xEE,0xE6,0x71,0x58,0x57,0x55,0x55,0x17,0xFF,0x87,0x8A,0x25,0x25,0x25,0x05,
+    0x38,0xFF,0xD7,0xF6,0xFA,0xEA,0xA2,0x6E,0xF7,0xF6,0xF3,0xDD,0xA0,0xA8,0x78,0x28,
+    0xF7,0xF6,0xD3,0xDD,0x0B,0x02,0x09,0x2F,0xF7,0xF6,0xB7,0xEE,0xFE,0xEE,0xBA,0x2A,
+    0xF7,0xF6,0xD7,0xF6,0x15,0xB5,0x8B,0xA2,0x18,0xFF,0x76,0xEE,0xF8,0x58,0x5A,0x7A,
+    0x75,0xEE,0x10,0xC5,0xE2,0xE2,0xE2,0x62,0x55,0xEE,0xEF,0xBC,0x0D,0x09,0x0B,0x02,
+    0xD6,0xF6,0xB6,0xEE,0x22,0x08,0x00,0x01,0xF7,0xF6,0xB6,0xEE,0xAA,0xFA,0xFE,0xBA,
+    0xF7,0xF6,0x96,0xEE,0x22,0x02,0xAA,0xAA,0x34,0xEE,0x02,0x41,0xF8,0xFC,0x5C,0x56,
+    0xA8,0x82,0xE2,0x38,0xA8,0xBA,0xAF,0xCD,0xAB,0xA3,0x43,0x49,0xFF,0xBF,0x0B,0x2D,
+    0x0D,0xB4,0x87,0x82,0x5F,0xF2,0x72,0xB6,0xF7,0xFE,0xA8,0x82,0x0D,0x09,0x02,0x00,
+    0x38,0xFF,0x96,0xEE,0x7A,0x7E,0x4A,0x63,0x18,0xFF,0xF8,0xF6,0xDD,0x90,0xB0,0xB0,
+    0x18,0xFF,0x55,0xE6,0xB7,0xB6,0xBC,0xB8,0x18,0xFF,0xD7,0xF6,0xDF,0xEE,0xFB,0xBA,
+    0xF7,0xF6,0x75,0xEE,0x80,0x80,0x60,0x5E,0xD7,0xF6,0xF4,0xDD,0xA2,0xE2,0xB2,0xD8,
+    0x76,0xEE,0xAE,0xBC,0x62,0x62,0xE2,0x6A,0x96,0xEE,0x52,0xCD,0x0B,0x22,0xBF,0xB5,
+    0x95,0xEE,0xE8,0x82,0x2D,0x55,0x55,0x55,0xD6,0xF6,0xE8,0x82,0x00,0x0F,0x55,0x55,
+    0xD6,0xF6,0xE8,0x8A,0x00,0x00,0x0B,0xD5,0x96,0xF6,0x23,0x41,0x56,0x56,0x5C,0x5A,
+    0xE8,0x92,0xE3,0x38,0xCD,0x6D,0xE3,0xE2,0xC8,0x82,0xE2,0x38,0x2D,0xD5,0xD5,0xDE,
+    0x4A,0x93,0x84,0x59,0x08,0xEA,0x7F,0x5F,0xD7,0xF6,0x88,0x7A,0x0D,0x25,0x95,0xD5,
+    0x38,0xFF,0x55,0xEE,0xF0,0x98,0x9C,0x9D,0x18,0xFF,0xF8,0xF6,0xF0,0xF8,0xF8,0x58,
+    0x18,0xFF,0xD7,0xF6,0x76,0xBE,0xBF,0xAB,0x18,0xFF,0x96,0xEE,0x82,0xC8,0x68,0x7A,
+    0xB6,0xF6,0x55,0xE6,0xF8,0x76,0xF7,0xD7,0x96,0xEE,0x92,0xD5,0xB0,0xD0,0xD0,0xF8,
+    0xD3,0xDD,0xAF,0xBC,0x60,0x60,0x70,0xDC,0x92,0xD5,0xAF,0xBC,0x03,0x8B,0xA9,0xAD,
+    0xA7,0x7A,0x25,0x6A,0xAA,0xA2,0x3D,0x57,0xC7,0x82,0x45,0x72,0x0A,0xBB,0xEE,0xBD,
+    0xE8,0x8A,0x87,0x7A,0x02,0xAB,0xD5,0x77,0xE8,0x82,0xC2,0x38,0xF8,0x78,0x70,0xE2,
+    0xC8,0x8A,0x44,0x51,0xA2,0xE3,0xAD,0xD5,0x06,0x6A,0x03,0x41,0xFC,0xFF,0x5C,0x56,
+    0x26,0x72,0x03,0x41,0xB0,0x2F,0x25,0xAD,0xA8,0x82,0x44,0x49,0x02,0x68,0x5F,0x5F,
+    0x96,0xF6,0x47,0x7A,0x0B,0x2D,0x55,0x55,0xF7,0xF6,0x88,0x7A,0x00,0x00,0x0B,0xD5,
+    0xF8,0xFE,0xEC,0xA3,0x00,0x00,0x00,0x2D,0xF7,0xF6,0x55,0xEE,0xF8,0x5E,0x7E,0x57,
+    0x76,0xEE,0x35,0xE6,0x38,0x6A,0x80,0x20,0x76,0xEE,0xD3,0xDD,0xF0,0xF8,0x9E,0xD4,
+    0x75,0xEE,0x4D,0xAC,0xD6,0x7F,0x7E,0xA0,0x31,0xCD,0xC8,0x7A,0x00,0x03,0x0B,0xB7,
+    0x66,0x72,0x46,0x72,0x57,0xAE,0x0A,0x29,0x66,0x72,0x26,0x72,0xFE,0xAA,0x82,0x00,
+    0xA7,0x82,0x46,0x72,0x29,0xD5,0xDF,0xFF,0x09,0x8B,0x66,0x7A,0x7F,0xAF,0xD5,0x15,
+    0x87,0x82,0xA2,0x30,0xFA,0x78,0x5C,0x5C,0x23,0x41,0xA2,0x28,0xAE,0x3B,0x35,0x87,
+    0x06,0x6A,0xE3,0x38,0x0F,0xEB,0xFD,0x7F,0x85,0x51,0x03,0x39,0xAB,0x49,0xFD,0xF5,
+    0xC8,0x8A,0x23,0x41,0xA3,0xFD,0x5D,0xD5,0xC9,0x8A,0xC5,0x61,0xE2,0x8B,0xB5,0x57,
+    0xEC,0xAB,0x84,0x51,0x3F,0xDF,0x57,0x55,0xF4,0xE5,0x06,0x6A,0x00,0x09,0x35,0xD5,
+    0x55,0xEE,0x92,0xD5,0x0A,0xAF,0xBF,0xB5,0x55,0xEE,0xB3,0xDD,0xB8,0xBA,0xAA,0xAD,
+    0xB6,0xF6,0xD3,0xDD,0x6A,0xA2,0xC3,0xAA,0xF3,0xDD,0x2D,0xAC,0x5C,0x80,0xA8,0x88,
+    0x46,0x72,0x63,0x59,0x2D,0xD5,0x55,0x55,0x66,0x7A,0x43,0x51,0x00,0x0B,0xD5,0xD5,
+    0x87,0x7A,0x64,0x59,0x00,0x00,0x0B,0xD5,0xCC,0xAB,0x87,0x7A,0x15,0x25,0x0D,0xA9,
+    0x29,0x93,0xC2,0x38,0x5E,0x5E,0x5C,0x5C,0x44,0x49,0xC2,0x30,0xF5,0xB5,0x81,0x8A,
+    0x84,0x51,0xE2,0x38,0x57,0xEF,0xBB,0x03,0xC6,0x61,0xA2,0x30,0xFD,0xFF,0xFE,0xD8,
+    0x65,0x49,0x03,0x41,0x2A,0xF9,0xE1,0xED,0xC6,0x61,0x03,0x41,0x0A,0xE5,0xFF,0x5E,
+    0xA5,0x51,0x03,0x39,0xAA,0xBE,0x75,0xFF,0xA8,0x82,0x23,0x41,0x2F,0xA5,0x3D,0xB5,
+    0x14,0xE6,0x87,0x7A,0x03,0x09,0x85,0xB5,0x96,0xEE,0x10,0xC5,0xAF,0x0D,0x25,0x75,
+    0x75,0xEE,0x8F,0xB4,0x00,0x00,0x00,0x57,0x55,0xEE,0xF1,0xBC,0xE8,0x80,0xBA,0x7D,
+    0x84,0x59,0x23,0x51,0xFE,0xF7,0xAD,0x3E,0x84,0x59,0x23,0x51,0x8B,0xEA,0xFC,0x7E,
+    0x6B,0x9B,0x23,0x51,0x55,0x55,0x95,0x35,0xAB,0xA3,0x67,0x7A,0x21,0xAA,0xA8,0xA0,
+    0xE8,0x8A,0x03,0x41,0x58,0x78,0xE8,0xE8,0x64,0x51,0xE2,0x38,0xEC,0xE6,0xB7,0xF4,
+    0x85,0x51,0x03,0x41,0x85,0x85,0x35,0x95,0xA5,0x59,0xC3,0x30,0xDA,0xDE,0x5C,0xDE,
+    0xA5,0x59,0x03,0x39,0xEB,0xFB,0x70,0x7B,0x44,0x41,0xE3,0x38,0xEA,0xEB,0xC1,0xA1,
+    0x65,0x41,0xE3,0x38,0xB2,0xFF,0xFF,0xDD,0xC5,0x59,0x23,0x41,0x3F,0x3D,0xFD,0x3B,
+    0x31,0xCD,0x06,0x6A,0x35,0xB5,0xF5,0xD5,0x35,0xE6,0xAF,0xBC,0x7D,0x55,0xAE,0x82,
+    0x93,0xCD,0x4E,0xAC,0x2D,0x8A,0xA0,0xA0,0x32,0xC5,0x0E,0x9C,0xA0,0xAA,0xBE,0xED,
+    0x84,0x59,0x23,0x51,0x8B,0xFE,0xFE,0x57,0x43,0x59,0x23,0x49,0xF0,0x7C,0xDD,0xBD,
+    0xAB,0xA3,0x44,0x59,0x35,0x25,0x05,0x05,0x0C,0xAC,0xE8,0x8A,0x7B,0x7E,0x78,0x6A,
+    0xA7,0x82,0x26,0x6A,0x54,0xFE,0x9E,0x3F,0x67,0x7A,0xA2,0x30,0xDC,0x58,0x70,0x60,
+    0x44,0x49,0xC2,0x30,0x2B,0xAF,0x95,0xF5,0x65,0x51,0xA2,0x30,0xFC,0xDA,0xFE,0x7A,
+    0x44,0x49,0xC3,0x30,0xE2,0xE2,0xF2,0x5B,0x24,0x39,0xC2,0x30,0xC2,0xFF,0xFF,0xFD,
+    0x03,0x41,0xE3,0x30,0xBB,0xEA,0xDF,0x0A,0xE6,0x59,0x03,0x41,0x3D,0xB5,0x55,0x77,
+    0x88,0x7A,0x64,0x51,0x2A,0x0E,0x2D,0x25,0x15,0xDE,0x6B,0x93,0x82,0xA3,0xA9,0xA9,
+    0x73,0xCD,0xED,0x9B,0xE0,0x68,0x7A,0xFE,0x11,0xBD,0x2E,0xA4,0xFD,0xF5,0xEA,0x2D,
+    0x44,0x51,0x03,0x49,0xEC,0x9E,0xFF,0xFF,0x43,0x51,0x03,0x49,0x0A,0x82,0xA2,0x62,
+    0x6A,0x93,0x23,0x51,0x0D,0x8D,0xA9,0xA9,0xE9,0x8A,0x46,0x72,0xF8,0xDF,0x5F,0x7F,
+    0xA7,0x7A,0xC4,0x61,0x8A,0x7A,0x7A,0xDA,0x67,0x72,0x03,0x49,0x6A,0xCA,0xCA,0x80,
+    0x23,0x41,0xA2,0x30,0xB9,0x3D,0x0D,0xA1,0x24,0x41,0x81,0x20,0xC0,0xEA,0x7F,0x57,
+    0xE3,0x38,0x82,0x20,0xA2,0xBB,0xAD,0xBD,0x04,0x39,0xC3,0x30,0xB1,0xFB,0xD5,0xD5,
+    0x44,0x49,0xE2,0x30,0x82,0xFA,0xFF,0xF5,0x44,0x41,0xE2,0x38,0xBF,0x95,0xFD,0xC3,
+    0x26,0x6A,0x03,0x39,0x2F,0x2D,0xBD,0xB5,0xF1,0xBC,0x06,0x62,0x03,0xA1,0xA9,0xC9,
+    0x2F,0xA4,0x89,0x62,0x28,0xAA,0xFA,0x55,0x11,0xBD,0x0B,0x7B,0x2F,0xB5,0xF5,0xFD,
+    0x64,0x59,0x02,0x49,0xF7,0xE7,0xE9,0xF2,0x09,0x8B,0x23,0x49,0x55,0x55,0x95,0x15,
+    0x49,0x93,0x84,0x59,0xA9,0xAA,0xA8,0x28,0xAB,0xA3,0xE5,0x61,0xFF,0xAF,0x62,0x7C,
+    0xC7,0x82,0x44,0x49,0xE0,0x7E,0x5F,0x57,0x06,0x6A,0xE2,0x38,0x00,0xFF,0x7F,0x7A,
+    0x03,0x41,0x61,0x18,0xA8,0xF8,0x7E,0xDF,0xE3,0x30,0x81,0x20,0xB5,0x0D,0xAF,0x2E,
+    0xE2,0x30,0xA2,0x28,0x55,0x6B,0xF8,0xCB,0x03,0x39,0xA2,0x28,0x2F,0xF5,0xDD,0xF7,
+    0x23,0x39,0xC2,0x30,0xEB,0xAF,0x8D,0xFD,0x64,0x49,0xE2,0x30,0x8B,0xCD,0xCD,0x7D,
+    0x84,0x51,0xE2,0x30,0x2F,0xBF,0x37,0xBD,0xD1,0xB4,0x85,0x51,0x09,0x0D,0x2D,0xA5,
+    0x11,0xBD,0xAC,0x8B,0x57,0xF0,0xA8,0xAB,0x6F,0xAC,0xCD,0x93,0xB9,0xA8,0x80,0xA0,
+    0x64,0x59,0x02,0x41,0xF2,0x5B,0x57,0x5D,0x69,0x93,0x02,0x41,0x15,0x35,0x35,0xD5,
+    0x69,0x93,0x84,0x59,0x08,0x80,0xF8,0x5F,0x66,0x72,0x43,0x49,0xE0,0x50,0x5E,0x77,
+    0xA5,0x51,0x03,0x41,0xFA,0x7A,0x7A,0x2E,0xC5,0x59,0xC2,0x30,0x58,0xDB,0x7F,0x5E,
+    0xE3,0x30,0x61,0x20,0x3E,0x27,0xFF,0xEA,0x03,0x39,0x81,0x20,0xB2,0xA2,0xAD,0x06,
+    0xE3,0x30,0xA2,0x28,0x00,0xF2,0x7B,0xEF,0xE3,0x30,0x82,0x28,0xFE,0xA0,0x2A,0x02,
+    0x03,0x39,0xC2,0x30,0xD5,0x5F,0x5E,0x73,0x03,0x31,0xC2,0x28,0xEB,0xFA,0xF9,0xAD,
+    0x64,0x49,0xE3,0x30,0xB5,0x95,0x3D,0x25,0x0D,0xA4,0xA5,0x51,0x8D,0x29,0xE9,0x03,
+    0x6F,0xAC,0xA9,0x72,0x2A,0xAB,0x55,0x57,0x2E,0x9C,0xA8,0x72,0x20,0xAA,0xAB,0xB5,
+    0x23,0x49,0x03,0x41,0xD5,0xF5,0xDD,0xFD,0x23,0x49,0xE2,0x40,0x38,0xFE,0xDF,0x55,
+    0xA4,0x59,0xE2,0x40,0x1C,0x15,0x1D,0x15,0xE5,0x61,0x23,0x39,0xEA,0x78,0x58,0x5C,
+    0xE5,0x61,0xA2,0x30,0xC2,0x73,0x6F,0x7F,0x44,0x49,0x81,0x20,0xF8,0x7A,0x57,0xFF,
+    0x24,0x41,0xA2,0x28,0x3D,0xA5,0x7F,0x7F,0x23,0x49,0x81,0x20,0x2A,0xAA,0xB7,0xDD,
+    0x03,0x39,0xA2,0x28,0xAC,0x7C,0xD8,0xF3,0x03,0x39,0xA2,0x28,0xBF,0x7D,0x75,0xCB,
+    0xE2,0x30,0xA2,0x28,0x8A,0xA3,0x8D,0x7C,0x03,0x39,0xA1,0x28,0xAB,0xA2,0x0F,0xA7,
+    0xC9,0x7A,0x03,0x39,0xD5,0x15,0x35,0x3D,0x10,0xC5,0x2A,0x83,0x2A,0x80,0x0A,0xB5,
+    0xD0,0xBC,0xA8,0x72,0x5E,0x58,0xA0,0xA0,0x2D,0xA4,0x06,0x5A,0xDF,0x7B,0xEA,0x00,
+    0x03,0x41,0xE2,0x38,0x03,0x7A,0xFC,0x77,0x03,0x49,0xE2,0x38,0xFD,0x7D,0x55,0xDD,
+    0x84,0x59,0xE2,0x38,0x15,0x95,0x95,0x95,0x46,0x6A,0x03,0x39,0x5C,0x5C,0x5C,0x54,
+    0x24,0x39,0xE3,0x30,0xCA,0x0B,0xA7,0xF5,0x23,0x39,0xE2,0x30,0xFF,0xAC,0xBA,0x3F,
+    0x23,0x39,0xE3,0x30,0x57,0x5E,0xEE,0xB8,0x03,0x31,0xA2,0x20,0x57,0xFA,0xA0,0x00,
+    0xE3,0x30,0x81,0x20,0x2B,0xBF,0xFA,0xA0,0x44,0x41,0xA2,0x28,0xAB,0xFF,0xFF,0xD5,
+    0x03,0x39,0xA2,0x28,0xDF,0xBB,0xAA,0x2A,0x64,0x49,0xC2,0x28,0xB5,0xBF,0xBE,0x37,
+    0xA9,0x72,0x44,0x49,0x25,0x09,0x0B,0x2A,0x0A,0x83,0xA9,0x72,0x0A,0x8F,0xFD,0xF5,
+    0x6F,0xAC,0xEA,0x7A,0x2B,0xF5,0x55,0x55,0x6E,0xAC,0x0A,0x83,0x00,0x02,0x35,0x55,
+    0x03,0x41,0xE2,0x38,0xF5,0x55,0x7F,0x55,0xE2,0x38,0xC2,0x38,0xA3,0x20,0xA2,0x8A,
+    0x43,0x49,0xA2,0x30,0xBF,0xFF,0x1F,0xF7,0x66,0x6A,0xE3,0x30,0x5E,0x5E,0x5C,0x57,
+    0xE3,0x30,0xC3,0x30,0x03,0x02,0x00,0x80,0x03,0x31,0xE3,0x30,0x3F,0xBF,0xD5,0x7F,
+    0x23,0x39,0xE3,0x30,0xEA,0xBB,0x7D,0xD5,0x03,0x39,0x04,0x31,0xBA,0xA0,0x0A,0x2B,
+    0x24,0x39,0xE3,0x30,0x5E,0xEB,0xBA,0x2A,0x44,0x41,0xA2,0x20,0x5F,0xFB,0xA2,0x0A,
+    0x65,0x49,0xA2,0x28,0xD5,0xFF,0xAB,0x00,0x48,0x6A,0x03,0x31,0xB5,0xA5,0x2B,0x0A,
+    0xA9,0x72,0x06,0x62,0x2D,0x29,0xAB,0xAB,0xC9,0x7A,0x88,0x6A,0x2B,0xAB,0xED,0x7E,
+    0xE9,0x7A,0x88,0x72,0xAE,0x2A,0xBB,0xED,0x0A,0x83,0xA9,0x72,0x2B,0xAF,0xEF,0xFD,
+};
+
+static const size_t pixel_4_width = 32;
+static const size_t pixel_4_height = 32;
+static const size_t pixel_4_size = 512;
+static const unsigned char pixel_4_data[512] =
+{
+    0xD7,0xF6,0xA4,0x49,0x55,0x55,0xAA,0x00,0x75,0xEE,0xA5,0x51,0x55,0x55,0x70,0x70,
+    0xB6,0xF6,0x85,0x49,0x55,0xDD,0x02,0x03,0xF7,0xFE,0xE6,0x59,0x55,0xFF,0xF0,0x9C,
+    0xF7,0xF6,0x85,0x49,0x55,0xAA,0x00,0x00,0x96,0xEE,0x46,0x5A,0x09,0x02,0x00,0x00,
+    0xF8,0xF6,0x75,0xEE,0x0B,0x27,0x0A,0x82,0xD7,0xEE,0xB2,0xD5,0xF8,0xD8,0xD6,0x96,
+    0xD6,0xF6,0xB6,0xEE,0x4A,0x82,0x00,0x02,0xD6,0xF6,0x43,0x49,0x70,0x60,0xE0,0x70,
+    0x8F,0xBC,0x02,0x41,0x09,0xFF,0xFF,0xBD,0xB6,0xF6,0x47,0x82,0x17,0x15,0x37,0x07,
+    0x18,0xFF,0x95,0xEE,0x68,0x70,0xAE,0x0C,0xF7,0xF6,0x35,0xE6,0x83,0x21,0x0B,0x08,
+    0xF7,0xF6,0x55,0xE6,0xC2,0xC0,0x60,0x6E,0x75,0xEE,0x51,0xCD,0x1C,0x3E,0x26,0xB6,
+    0xB6,0xF6,0xA7,0x7A,0x2F,0x55,0x55,0x55,0x95,0xF6,0x02,0x49,0x70,0x6A,0x7F,0x7F,
+    0x47,0x7A,0xE3,0x38,0x9B,0xF8,0xF0,0x6B,0xF3,0xE5,0xA5,0x59,0x3F,0xF5,0x75,0x55,
+    0xD7,0xF6,0x47,0x7A,0x00,0x00,0x0B,0xB5,0xF8,0xF6,0xB3,0xD5,0x00,0x80,0x80,0xA9,
+    0x76,0xEE,0xF4,0xDD,0x40,0x40,0x48,0x70,0xB3,0xD5,0xCC,0x9B,0x28,0xA8,0xAE,0xD8,
+    0x66,0x72,0x43,0x59,0x00,0x00,0x2D,0xD7,0x8A,0xA3,0xE5,0x69,0xFF,0xBF,0x3F,0x25,
+    0x06,0x6A,0xC2,0x30,0xDC,0x54,0xD4,0xF4,0xC5,0x61,0x03,0x39,0xF3,0xDF,0x55,0x7F,
+    0x67,0x7A,0x44,0x49,0x0E,0xA5,0xD5,0x55,0x72,0xDD,0x43,0x49,0x2F,0xB5,0xD5,0x55,
+    0x14,0xE6,0xE8,0x82,0x00,0x00,0x23,0x29,0x55,0xE6,0xF0,0xBC,0x60,0xE0,0x80,0xFE,
+    0x63,0x59,0x23,0x51,0x0A,0xE3,0x72,0x56,0xCB,0xA3,0x44,0x59,0x25,0x8D,0x89,0x81,
+    0x87,0x7A,0x23,0x41,0x54,0x58,0x68,0x60,0x65,0x51,0xC2,0x30,0x43,0x4B,0x6B,0x6D,
+    0x64,0x49,0xE3,0x30,0xE8,0xB8,0x7E,0x57,0x85,0x51,0xE3,0x38,0x2F,0x27,0x3D,0xF5,
+    0x93,0xD5,0x84,0x59,0x8F,0x0D,0x0D,0x2D,0x72,0xCD,0x4E,0xA4,0xEA,0xF8,0x5C,0xF7,
+    0xC5,0x61,0x23,0x49,0xD5,0x75,0x55,0x17,0x29,0x8B,0xC5,0x61,0xE1,0xB9,0xAB,0xC8,
+    0x67,0x7A,0x23,0x41,0xE0,0xAC,0xF8,0x7F,0x03,0x39,0x81,0x20,0x82,0x72,0x9E,0xB7,
+    0xE3,0x30,0xA2,0x28,0x0B,0xAD,0x3F,0xFE,0x44,0x49,0xE2,0x30,0xFA,0xBF,0x3D,0xFD,
+    0xD1,0xBC,0x43,0x41,0x2D,0xB5,0x35,0xB5,0x4F,0xA4,0xEA,0x72,0x3A,0xB5,0x88,0x00,
+    0x87,0x7A,0x02,0x41,0x17,0x95,0x55,0x55,0x29,0x93,0x23,0x49,0xE0,0x7E,0x75,0x75,
+    0x64,0x51,0xA2,0x28,0xC8,0xE0,0x68,0x5E,0x03,0x41,0x82,0x20,0xAD,0xBF,0x23,0xFF,
+    0xE3,0x38,0xC2,0x28,0x7E,0xB7,0x5E,0xFC,0xE3,0x30,0xC2,0x28,0x0F,0x38,0x0A,0x15,
+    0xAF,0xB4,0x03,0x39,0xB5,0xA5,0x05,0x2D,0xAF,0xB4,0x27,0x5A,0xAA,0xBF,0x7E,0xA8,
+    0x03,0x41,0xE2,0x38,0xFA,0x7F,0x5D,0x55,0xA5,0x51,0xE2,0x38,0xCD,0x4D,0x45,0x45,
+    0x24,0x39,0xE3,0x30,0xE2,0xBD,0xF5,0x55,0x03,0x39,0xC2,0x28,0x5A,0xA0,0x00,0x0A,
+    0x24,0x39,0xA2,0x28,0xBD,0xDF,0xEA,0x08,0x27,0x62,0xC2,0x28,0xD5,0xDD,0xB5,0x2F,
+    0x0A,0x83,0xA5,0x51,0x09,0xAB,0x2B,0xAB,0x6E,0xAC,0xC9,0x7A,0x0B,0xD5,0xD5,0x55,
+};
+
+static const size_t pixel_5_width = 16;
+static const size_t pixel_5_height = 16;
+static const size_t pixel_5_size = 128;
+static const unsigned char pixel_5_data[128] =
+{
+    0x96,0xEE,0x64,0x49,0x55,0xC0,0xC0,0xC0,0x55,0xEE,0x47,0x6A,0x55,0xC2,0x9D,0x35,
+    0xD7,0xF6,0x8B,0x8B,0x35,0x00,0x00,0x00,0xD7,0xF6,0xB2,0xD5,0xE0,0xF0,0xF0,0xD8,
+    0x71,0xCD,0x43,0x59,0xC3,0x7F,0xFF,0xF5,0x6A,0x9B,0xE3,0x38,0x2F,0xFF,0xD7,0x57,
+    0xF7,0xF6,0xC5,0x59,0x00,0x0B,0xD5,0x55,0x76,0xEE,0xAF,0xB4,0xF0,0x78,0xC2,0xAD,
+    0x49,0x93,0x43,0x51,0x15,0x25,0xB5,0xA5,0x26,0x6A,0xC2,0x30,0xFC,0x58,0x50,0x5A,
+    0x64,0x51,0xC2,0x28,0x2C,0xBF,0xFD,0xB5,0xD0,0xB4,0x43,0x49,0x03,0x03,0xA9,0x89,
+    0xC8,0x82,0x02,0x41,0xCD,0xD5,0xD5,0x55,0x44,0x41,0xA2,0x28,0xD8,0xFC,0xFA,0xAF,
+    0x85,0x49,0xC2,0x30,0xD5,0x55,0xF5,0x3F,0x0D,0xA4,0x64,0x49,0xA9,0x81,0x2B,0xEF,
+};
+
+static const size_t pixel_6_width = 8;
+static const size_t pixel_6_height = 8;
+static const size_t pixel_6_size = 32;
+static const unsigned char pixel_6_data[32] =
+{
+    0x34,0xE6,0x64,0x51,0xEF,0xB8,0xDB,0x5D,0xB7,0xF6,0x47,0x6A,0x02,0x80,0x82,0xA5,
+    0x67,0x7A,0xC2,0x30,0xE3,0x63,0x7B,0x5D,0xF1,0xBC,0x03,0x39,0x25,0xB5,0xB5,0xB5,
+};
+
+static const size_t pixel_7_width = 4;
+static const size_t pixel_7_height = 4;
+static const size_t pixel_7_size = 8;
+static const unsigned char pixel_7_data[8] =
+{
+    0x14,0xDE,0x44,0x49,0x0A,0x27,0xD5,0xD5,
+};
+
+static const size_t pixel_8_width = 2;
+static const size_t pixel_8_height = 2;
+static const size_t pixel_8_size = 8;
+static const unsigned char pixel_8_data[8] =
+{
+    0x92,0xCD,0x44,0x49,0x33,0xDD,0x33,0xDD,
+};
+
+static const size_t pixel_9_width = 1;
+static const size_t pixel_9_height = 1;
+static const size_t pixel_9_size = 8;
+static const unsigned char pixel_9_data[8] =
+{
+    0x2A,0x83,0x0A,0x83,0xFB,0xEF,0xEE,0xEF,
+};
diff --git a/src/third_party/angle/src/tests/gles_conformance_tests/generate_gles_conformance_tests.py b/src/third_party/angle/src/tests/gles_conformance_tests/generate_gles_conformance_tests.py
new file mode 100644
index 0000000..8ed313a
--- /dev/null
+++ b/src/third_party/angle/src/tests/gles_conformance_tests/generate_gles_conformance_tests.py
@@ -0,0 +1,68 @@
+import os
+import re
+import sys
+
+def ReadFileAsLines(filename):
+    """Reads a file, removing blank lines and lines that start with #"""
+    file = open(filename, "r")
+    raw_lines = file.readlines()
+    file.close()
+    lines = []
+    for line in raw_lines:
+        line = line.strip()
+        if len(line) > 0 and not line.startswith("#"):
+            lines.append(line)
+    return lines
+
+def GetSuiteName(testName):
+    return testName[:testName.find("/")]
+
+def GetTestName(testName):
+    replacements = { ".test": "", ".": "_" }
+    splitTestName = testName.split("/")
+    cleanName = splitTestName[-2] + "_" + splitTestName[-1]
+    for replaceKey in replacements:
+        cleanName = cleanName.replace(replaceKey, replacements[replaceKey])
+    return cleanName
+
+def GenerateTests(outFile, testNames):
+    # Remove duplicate tests
+    testNames = list(set(testNames))
+    testSuites = []
+
+    outFile.write("#include \"gles_conformance_tests.h\"\n\n")
+
+    for test in testNames:
+        testSuite = GetSuiteName(test)
+        if not testSuite in testSuites:
+            outFile.write("DEFINE_CONFORMANCE_TEST_CLASS(" + testSuite + ");\n\n")
+            testSuites.append(testSuite)
+
+        outFile.write("TYPED_TEST(" + testSuite + ", " + GetTestName(test) + ")\n")
+        outFile.write("{\n")
+        outFile.write("    run(\"" + test + "\");\n")
+        outFile.write("}\n\n")
+
+def GenerateTestList(sourceFile, rootDir):
+    tests = [ ]
+    fileName, fileExtension = os.path.splitext(sourceFile)
+    if fileExtension == ".run":
+        lines = ReadFileAsLines(sourceFile)
+        for line in lines:
+            tests += GenerateTestList(os.path.join(os.path.dirname(sourceFile), line), rootDir)
+    elif fileExtension == ".test":
+        tests.append(os.path.relpath(os.path.realpath(sourceFile), rootDir).replace("\\", "/"))
+    return tests;
+
+def main(argv):
+    tests = GenerateTestList(argv[0], argv[1])
+    tests.sort()
+
+    output = open(argv[2], 'wb')
+    GenerateTests(output, tests)
+    output.close()
+
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
diff --git a/src/third_party/angle/src/tests/gles_conformance_tests/gles_conformance_tests.cpp b/src/third_party/angle/src/tests/gles_conformance_tests/gles_conformance_tests.cpp
new file mode 100644
index 0000000..10565e1
--- /dev/null
+++ b/src/third_party/angle/src/tests/gles_conformance_tests/gles_conformance_tests.cpp
@@ -0,0 +1,93 @@
+#include "gles_conformance_tests.h"
+#include "GTFMain.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+#include <sstream>
+#include <stdarg.h>
+
+static std::vector<char> FormatArg(const char* fmt, ...)
+{
+    va_list vararg;
+    va_start(vararg, fmt);
+    int len = vsnprintf(nullptr, 0, fmt, vararg);
+    va_end(vararg);
+
+    std::vector<char> buf(len + 1);
+
+    va_start(vararg, fmt);
+    vsnprintf(buf.data(), buf.size(), fmt, vararg);
+    va_end(vararg);
+
+    return buf;
+}
+
+static std::string GetExecutableDirectory()
+{
+    std::vector<char> executableFileBuf(MAX_PATH);
+    DWORD executablePathLen =
+        GetModuleFileNameA(nullptr, executableFileBuf.data(), executableFileBuf.size());
+    if (executablePathLen == 0)
+    {
+        return false;
+    }
+
+    std::string executableLocation = executableFileBuf.data();
+    size_t lastPathSepLoc = executableLocation.find_last_of("\\/");
+    if (lastPathSepLoc != std::string::npos)
+    {
+        executableLocation = executableLocation.substr(0, lastPathSepLoc);
+    }
+    else
+    {
+        executableLocation = "";
+    }
+
+    return executableLocation;
+}
+
+void RunConformanceTest(const std::string &testPath, EGLNativeDisplayType nativeDisplay)
+{
+    std::vector<char*> args;
+
+    // Empty first argument for the program name
+    args.push_back("");
+
+    std::vector<char> widthArg = FormatArg("-width=%u", 64);
+    args.push_back(widthArg.data());
+
+    std::vector<char> heightArg = FormatArg("-height=%u", 64);
+    args.push_back(heightArg.data());
+
+    std::vector<char> displayArg = FormatArg("-d=%llu", nativeDisplay);
+    args.push_back(displayArg.data());
+
+    std::vector<char> runArg = FormatArg("-run=%s/conformance_tests/%s", GetExecutableDirectory().c_str(), testPath.c_str());
+    args.push_back(runArg.data());
+
+    // Redirect cout
+    std::streambuf* oldCoutStreamBuf = std::cout.rdbuf();
+    std::ostringstream strCout;
+    std::cout.rdbuf(strCout.rdbuf());
+
+    if (GTFMain(args.size(), args.data()) != 0)
+    {
+        FAIL() << "GTFMain failed.";
+    }
+
+    // Restore old cout
+    std::cout.rdbuf(oldCoutStreamBuf);
+    std::string log = strCout.str();
+
+    // Look for failures
+    size_t offset = 0;
+    std::string offsetSearchString = "failure = ";
+    while ((offset = log.find("failure = ", offset)) != std::string::npos)
+    {
+        offset += offsetSearchString.length();
+
+        size_t failureCount = atoll(log.c_str() + offset);
+        EXPECT_EQ(0, failureCount) << log;
+    }
+}
diff --git a/src/third_party/angle/src/tests/gles_conformance_tests/gles_conformance_tests.h b/src/third_party/angle/src/tests/gles_conformance_tests/gles_conformance_tests.h
new file mode 100644
index 0000000..df911b0
--- /dev/null
+++ b/src/third_party/angle/src/tests/gles_conformance_tests/gles_conformance_tests.h
@@ -0,0 +1,69 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef CONFORMANCE_TESTS_CONFORMANCE_TEST_H_
+#define CONFORMANCE_TESTS_CONFORMANCE_TEST_H_
+
+#include "gtest/gtest.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <string>
+
+struct D3D9
+{
+    static EGLNativeDisplayType GetNativeDisplay()
+    {
+        return EGL_DEFAULT_DISPLAY;
+    }
+};
+
+struct D3D11
+{
+    static EGLNativeDisplayType GetNativeDisplay()
+    {
+        return EGL_D3D11_ONLY_DISPLAY_ANGLE;
+    }
+};
+
+#define CONFORMANCE_TESTS_ES2 2
+#define CONFORMANCE_TESTS_ES3 3
+
+#if CONFORMANCE_TESTS_TYPE == CONFORMANCE_TESTS_ES2
+    typedef testing::Types<D3D9, D3D11> ConformanceTestTypes;
+#elif CONFORMANCE_TESTS_TYPE == CONFORMANCE_TESTS_ES3
+    typedef testing::Types<D3D11> ConformanceTestTypes;
+#else
+#   error "Unknown CONFORMANCE_TESTS_TYPE"
+#endif
+
+#define DEFINE_CONFORMANCE_TEST_CLASS(name) \
+    template <typename T> class name : public ConformanceTest<T> { }; \
+    TYPED_TEST_CASE(name, ConformanceTestTypes);
+
+template <typename T>
+class ConformanceTest : public testing::Test
+{
+  public:
+    ConformanceTest()
+        : mNativeDisplay(T::GetNativeDisplay())
+    {
+    }
+
+  protected:
+    void run(const std::string &testPath)
+    {
+        RunConformanceTest(testPath, mNativeDisplay);
+    }
+
+  private:
+    EGLNativeDisplayType mNativeDisplay;
+};
+
+void RunConformanceTest(const std::string &testPath, EGLNativeDisplayType nativeDisplay);
+
+#endif // CONFORMANCE_TESTS_CONFORMANCE_TEST_H_
diff --git a/src/third_party/angle/src/tests/gles_conformance_tests/gles_conformance_tests_main.cpp b/src/third_party/angle/src/tests/gles_conformance_tests/gles_conformance_tests_main.cpp
new file mode 100644
index 0000000..0b95d5c
--- /dev/null
+++ b/src/third_party/angle/src/tests/gles_conformance_tests/gles_conformance_tests_main.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gles_conformance_tests.h"
+
+#include "gtest/gtest.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+int main(int argc, char** argv)
+{
+    testing::InitGoogleTest(&argc, argv);
+    int rt = RUN_ALL_TESTS();
+    return rt;
+}
diff --git a/src/third_party/angle/src/tests/perf_tests/ANGLEPerfTest.cpp b/src/third_party/angle/src/tests/perf_tests/ANGLEPerfTest.cpp
new file mode 100644
index 0000000..e1de4af
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/ANGLEPerfTest.cpp
@@ -0,0 +1,196 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLEPerfTests:
+//   Base class for google test performance tests
+//
+
+#include "ANGLEPerfTest.h"
+
+#include "third_party/perf/perf_test.h"
+
+#include <cassert>
+#include <cmath>
+#include <iostream>
+
+ANGLEPerfTest::ANGLEPerfTest(const std::string &name, const std::string &suffix)
+    : mName(name),
+      mSuffix(suffix),
+      mTimer(nullptr),
+      mRunTimeSeconds(5.0),
+      mNumStepsPerformed(0),
+      mRunning(true)
+{
+    mTimer = CreateTimer();
+}
+
+ANGLEPerfTest::~ANGLEPerfTest()
+{
+    SafeDelete(mTimer);
+}
+
+void ANGLEPerfTest::run()
+{
+    mTimer->start();
+    while (mRunning)
+    {
+        step();
+        if (mRunning)
+        {
+            ++mNumStepsPerformed;
+        }
+        if (mTimer->getElapsedTime() > mRunTimeSeconds)
+        {
+            mRunning = false;
+        }
+    }
+    finishTest();
+    mTimer->stop();
+}
+
+void ANGLEPerfTest::printResult(const std::string &trace, double value, const std::string &units, bool important) const
+{
+    perf_test::PrintResult(mName, mSuffix, trace, value, units, important);
+}
+
+void ANGLEPerfTest::printResult(const std::string &trace, size_t value, const std::string &units, bool important) const
+{
+    perf_test::PrintResult(mName, mSuffix, trace, value, units, important);
+}
+
+void ANGLEPerfTest::SetUp()
+{
+}
+
+void ANGLEPerfTest::TearDown()
+{
+    double relativeScore = static_cast<double>(mNumStepsPerformed) / mTimer->getElapsedTime();
+    printResult("score", static_cast<size_t>(std::round(relativeScore)), "score", true);
+}
+
+double ANGLEPerfTest::normalizedTime(size_t value) const
+{
+    return static_cast<double>(value) / static_cast<double>(mNumStepsPerformed);
+}
+
+std::string RenderTestParams::suffix() const
+{
+    switch (getRenderer())
+    {
+        case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+            return "_d3d11";
+        case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+            return "_d3d9";
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+            return "_gl";
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+            return "_gles";
+        case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+            return "_default";
+        case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+            return "_vulkan";
+        default:
+            assert(0);
+            return "_unk";
+    }
+}
+
+ANGLERenderTest::ANGLERenderTest(const std::string &name, const RenderTestParams &testParams)
+    : ANGLEPerfTest(name, testParams.suffix()),
+      mTestParams(testParams),
+      mEGLWindow(nullptr),
+      mOSWindow(nullptr)
+{
+}
+
+ANGLERenderTest::~ANGLERenderTest()
+{
+    SafeDelete(mOSWindow);
+    SafeDelete(mEGLWindow);
+}
+
+void ANGLERenderTest::SetUp()
+{
+    mOSWindow = CreateOSWindow();
+    mEGLWindow = new EGLWindow(mTestParams.majorVersion, mTestParams.minorVersion,
+                               mTestParams.eglParameters);
+    mEGLWindow->setSwapInterval(0);
+
+    if (!mOSWindow->initialize(mName, mTestParams.windowWidth, mTestParams.windowHeight))
+    {
+        FAIL() << "Failed initializing OSWindow";
+        return;
+    }
+
+    if (!mEGLWindow->initializeGL(mOSWindow))
+    {
+        FAIL() << "Failed initializing EGLWindow";
+        return;
+    }
+
+    initializeBenchmark();
+
+    ANGLEPerfTest::SetUp();
+}
+
+void ANGLERenderTest::TearDown()
+{
+    ANGLEPerfTest::TearDown();
+
+    destroyBenchmark();
+
+    mEGLWindow->destroyGL();
+    mOSWindow->destroy();
+}
+
+void ANGLERenderTest::step()
+{
+    // Clear events that the application did not process from this frame
+    Event event;
+    bool closed = false;
+    while (popEvent(&event))
+    {
+        // If the application did not catch a close event, close now
+        if (event.Type == Event::EVENT_CLOSED)
+        {
+            closed = true;
+        }
+    }
+
+    if (closed)
+    {
+        abortTest();
+    }
+    else
+    {
+        drawBenchmark();
+        // Swap is needed so that the GPU driver will occasionally flush its internal command queue
+        // to the GPU. The null device benchmarks are only testing CPU overhead, so they don't need
+        // to swap.
+        if (mTestParams.eglParameters.deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
+        {
+            mEGLWindow->swap();
+        }
+        mOSWindow->messageLoop();
+    }
+}
+
+void ANGLERenderTest::finishTest()
+{
+    if (mTestParams.eglParameters.deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
+    {
+        glFinish();
+    }
+}
+
+bool ANGLERenderTest::popEvent(Event *event)
+{
+    return mOSWindow->popEvent(event);
+}
+
+OSWindow *ANGLERenderTest::getWindow()
+{
+    return mOSWindow;
+}
diff --git a/src/third_party/angle/src/tests/perf_tests/ANGLEPerfTest.h b/src/third_party/angle/src/tests/perf_tests/ANGLEPerfTest.h
new file mode 100644
index 0000000..0bdb9f9
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/ANGLEPerfTest.h
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLEPerfTests:
+//   Base class for google test performance tests
+//
+
+#ifndef PERF_TESTS_ANGLE_PERF_TEST_H_
+#define PERF_TESTS_ANGLE_PERF_TEST_H_
+
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "EGLWindow.h"
+#include "OSWindow.h"
+#include "test_utils/angle_test_configs.h"
+#include "test_utils/angle_test_instantiate.h"
+#include "Timer.h"
+
+class Event;
+
+#if !defined(ASSERT_GL_NO_ERROR)
+#define ASSERT_GL_NO_ERROR() ASSERT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError())
+#endif  // !defined(ASSERT_GL_NO_ERROR)
+
+#if !defined(ASSERT_GLENUM_EQ)
+#define ASSERT_GLENUM_EQ(expected, actual) \
+    ASSERT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
+#endif  // !defined(ASSERT_GLENUM_EQ)
+
+class ANGLEPerfTest : public testing::Test, angle::NonCopyable
+{
+  public:
+    ANGLEPerfTest(const std::string &name, const std::string &suffix);
+    virtual ~ANGLEPerfTest();
+
+    virtual void step() = 0;
+
+    // Called right before timer is stopped to let the test wait for asynchronous operations.
+    virtual void finishTest() {}
+
+  protected:
+    void run();
+    void printResult(const std::string &trace, double value, const std::string &units, bool important) const;
+    void printResult(const std::string &trace, size_t value, const std::string &units, bool important) const;
+    void SetUp() override;
+    void TearDown() override;
+
+    // Normalize a time value according to the number of test loop iterations (mFrameCount)
+    double normalizedTime(size_t value) const;
+
+    // Call if the test step was aborted and the test should stop running.
+    void abortTest() { mRunning = false; }
+
+    unsigned int getNumStepsPerformed() const { return mNumStepsPerformed; }
+
+    std::string mName;
+    std::string mSuffix;
+    Timer *mTimer;
+    double mRunTimeSeconds;
+
+  private:
+    unsigned int mNumStepsPerformed;
+    bool mRunning;
+};
+
+struct RenderTestParams : public angle::PlatformParameters
+{
+    virtual std::string suffix() const;
+
+    EGLint windowWidth;
+    EGLint windowHeight;
+};
+
+class ANGLERenderTest : public ANGLEPerfTest
+{
+  public:
+    ANGLERenderTest(const std::string &name, const RenderTestParams &testParams);
+    ~ANGLERenderTest();
+
+    virtual void initializeBenchmark() { }
+    virtual void destroyBenchmark() { }
+
+    virtual void drawBenchmark() = 0;
+
+    bool popEvent(Event *event);
+
+    OSWindow *getWindow();
+
+  protected:
+    const RenderTestParams &mTestParams;
+
+  private:
+    void SetUp() override;
+    void TearDown() override;
+
+    void step() override;
+    void finishTest() override;
+
+    EGLWindow *mEGLWindow;
+    OSWindow *mOSWindow;
+};
+
+#endif // PERF_TESTS_ANGLE_PERF_TEST_H_
diff --git a/src/third_party/angle/src/tests/perf_tests/BindingPerf.cpp b/src/third_party/angle/src/tests/perf_tests/BindingPerf.cpp
new file mode 100644
index 0000000..329a95d
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/BindingPerf.cpp
@@ -0,0 +1,208 @@
+//
+// Copyright (c) 2016 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.
+//
+// BindingPerf:
+//   Performance test for binding objects
+//
+
+#include "ANGLEPerfTest.h"
+
+#include <iostream>
+#include <random>
+#include <sstream>
+
+#include "shader_utils.h"
+
+namespace angle
+{
+
+enum AllocationStyle
+{
+    EVERY_ITERATION,
+    AT_INITIALIZATION
+};
+
+struct BindingsParams final : public RenderTestParams
+{
+    BindingsParams()
+    {
+        // Common default params
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth  = 720;
+        windowHeight = 720;
+        iterations   = 128;
+
+        numObjects      = 100;
+        allocationStyle = EVERY_ITERATION;
+    }
+
+    std::string suffix() const override;
+    size_t numObjects;
+    AllocationStyle allocationStyle;
+
+    // static parameters
+    size_t iterations;
+};
+
+std::ostream &operator<<(std::ostream &os, const BindingsParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+std::string BindingsParams::suffix() const
+{
+    std::stringstream strstr;
+
+    strstr << RenderTestParams::suffix();
+    strstr << "_" << numObjects << "_objects";
+
+    switch (allocationStyle)
+    {
+        case EVERY_ITERATION:
+            strstr << "_allocated_every_iteration";
+            break;
+        case AT_INITIALIZATION:
+            strstr << "_allocated_at_initialization";
+            break;
+        default:
+            UNREACHABLE();
+    }
+
+    return strstr.str();
+}
+
+class BindingsBenchmark : public ANGLERenderTest,
+                          public ::testing::WithParamInterface<BindingsParams>
+{
+  public:
+    BindingsBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    // TODO: Test binding perf of more than just buffers
+    std::vector<GLuint> mBuffers;
+    std::vector<GLenum> mBindingPoints;
+};
+
+BindingsBenchmark::BindingsBenchmark() : ANGLERenderTest("Bindings", GetParam())
+{
+}
+
+void BindingsBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+    ASSERT_GT(params.iterations, 0u);
+
+    mBuffers.resize(params.numObjects, 0);
+    if (params.allocationStyle == AT_INITIALIZATION)
+    {
+        glGenBuffers(static_cast<GLsizei>(mBuffers.size()), mBuffers.data());
+        for (size_t bufferIdx = 0; bufferIdx < mBuffers.size(); bufferIdx++)
+        {
+            glBindBuffer(GL_ARRAY_BUFFER, mBuffers[bufferIdx]);
+        }
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+    }
+
+    mBindingPoints.push_back(GL_ARRAY_BUFFER);
+    mBindingPoints.push_back(GL_ELEMENT_ARRAY_BUFFER);
+    if (params.majorVersion >= 3)
+    {
+        mBindingPoints.push_back(GL_PIXEL_PACK_BUFFER);
+        mBindingPoints.push_back(GL_PIXEL_UNPACK_BUFFER);
+        mBindingPoints.push_back(GL_COPY_READ_BUFFER);
+        mBindingPoints.push_back(GL_COPY_WRITE_BUFFER);
+        mBindingPoints.push_back(GL_TRANSFORM_FEEDBACK_BUFFER);
+        mBindingPoints.push_back(GL_UNIFORM_BUFFER);
+    }
+    if (params.majorVersion > 3 || (params.majorVersion == 3 && params.minorVersion >= 1))
+    {
+        mBindingPoints.push_back(GL_ATOMIC_COUNTER_BUFFER);
+        mBindingPoints.push_back(GL_SHADER_STORAGE_BUFFER);
+        mBindingPoints.push_back(GL_DRAW_INDIRECT_BUFFER);
+        mBindingPoints.push_back(GL_DISPATCH_INDIRECT_BUFFER);
+    }
+}
+
+void BindingsBenchmark::destroyBenchmark()
+{
+    const auto &params = GetParam();
+    if (params.allocationStyle == AT_INITIALIZATION)
+    {
+        glDeleteBuffers(static_cast<GLsizei>(mBuffers.size()), mBuffers.data());
+    }
+}
+
+void BindingsBenchmark::drawBenchmark()
+{
+    const auto &params = GetParam();
+
+    for (size_t it = 0; it < params.iterations; ++it)
+    {
+        // Generate a buffer (if needed) and bind it to a "random" binding point
+        if (params.allocationStyle == EVERY_ITERATION)
+        {
+            glGenBuffers(static_cast<GLsizei>(mBuffers.size()), mBuffers.data());
+        }
+
+        for (size_t bufferIdx = 0; bufferIdx < mBuffers.size(); bufferIdx++)
+        {
+            GLenum binding = mBindingPoints[(bufferIdx + it) % mBindingPoints.size()];
+            glBindBuffer(binding, mBuffers[bufferIdx]);
+        }
+
+        // Delete all the buffers
+        if (params.allocationStyle == EVERY_ITERATION)
+        {
+            glDeleteBuffers(static_cast<GLsizei>(mBuffers.size()), mBuffers.data());
+        }
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+BindingsParams D3D11Params(AllocationStyle allocationStyle)
+{
+    BindingsParams params;
+    params.eglParameters   = egl_platform::D3D11_NULL();
+    params.allocationStyle = allocationStyle;
+    return params;
+}
+
+BindingsParams D3D9Params(AllocationStyle allocationStyle)
+{
+    BindingsParams params;
+    params.eglParameters   = egl_platform::D3D9_NULL();
+    params.allocationStyle = allocationStyle;
+    return params;
+}
+
+BindingsParams OpenGLParams(AllocationStyle allocationStyle)
+{
+    BindingsParams params;
+    params.eglParameters   = egl_platform::OPENGL_NULL();
+    params.allocationStyle = allocationStyle;
+    return params;
+}
+
+TEST_P(BindingsBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(BindingsBenchmark,
+                       D3D11Params(EVERY_ITERATION),
+                       D3D11Params(AT_INITIALIZATION),
+                       D3D9Params(EVERY_ITERATION),
+                       D3D9Params(AT_INITIALIZATION),
+                       OpenGLParams(EVERY_ITERATION),
+                       OpenGLParams(AT_INITIALIZATION));
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/perf_tests/BitSetIteratorPerf.cpp b/src/third_party/angle/src/tests/perf_tests/BitSetIteratorPerf.cpp
new file mode 100644
index 0000000..e88b4a3
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/BitSetIteratorPerf.cpp
@@ -0,0 +1,64 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IndexDataManagerPerfTest:
+//   Performance test for index buffer management.
+//
+
+#include "ANGLEPerfTest.h"
+
+#include <gmock/gmock.h>
+
+#include "angle_unittests_utils.h"
+#include "common/bitset_utils.h"
+
+using namespace testing;
+
+namespace
+{
+
+template <typename T>
+class BitSetIteratorPerfTest : public ANGLEPerfTest
+{
+  public:
+    BitSetIteratorPerfTest();
+
+    void step() override;
+
+    T mBits;
+};
+
+template <typename T>
+BitSetIteratorPerfTest<T>::BitSetIteratorPerfTest() : ANGLEPerfTest("BitSetIteratorPerf", "_run")
+{
+}
+
+template <typename T>
+void BitSetIteratorPerfTest<T>::step()
+{
+    mBits.flip();
+
+    for (size_t bit : mBits)
+    {
+        UNUSED_VARIABLE(bit);
+    }
+
+    mBits.reset();
+}
+
+// These type names unfortunately don't get printed correctly in Gtest.
+#if defined(ANGLE_X64_CPU)
+using TestTypes = Types<angle::IterableBitSet<32>, angle::BitSet32<32>, angle::BitSet64<32>>;
+#else
+using TestTypes = Types<angle::IterableBitSet<32>, angle::BitSet32<32>>;
+#endif  // defined(ANGLE_X64_CPU)
+TYPED_TEST_CASE(BitSetIteratorPerfTest, TestTypes);
+
+TYPED_TEST(BitSetIteratorPerfTest, Run)
+{
+    this->run();
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/BlitFramebufferPerf.cpp b/src/third_party/angle/src/tests/perf_tests/BlitFramebufferPerf.cpp
new file mode 100644
index 0000000..a2f6938
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/BlitFramebufferPerf.cpp
@@ -0,0 +1,250 @@
+//
+// Copyright 2017 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.
+//
+// BlitFramebufferPerf:
+//   Performance tests for glBlitFramebuffer in ES3. Includes tests for
+//   color, depth, and stencil blit, as well as the mutlisample versions.
+//   The test works by clearing a framebuffer, then blitting it to a second.
+
+#include "ANGLEPerfTest.h"
+
+namespace
+{
+
+enum class BufferType
+{
+    COLOR,
+    DEPTH,
+    STENCIL,
+    DEPTH_STENCIL
+};
+
+const char *BufferTypeString(BufferType type)
+{
+    switch (type)
+    {
+        case BufferType::COLOR:
+            return "color";
+        case BufferType::DEPTH:
+            return "depth";
+        case BufferType::STENCIL:
+            return "stencil";
+        case BufferType::DEPTH_STENCIL:
+            return "depth_stencil";
+        default:
+            return "error";
+    }
+}
+
+GLbitfield BufferTypeMask(BufferType type)
+{
+    switch (type)
+    {
+        case BufferType::COLOR:
+            return GL_COLOR_BUFFER_BIT;
+        case BufferType::DEPTH:
+            return GL_DEPTH_BUFFER_BIT;
+        case BufferType::STENCIL:
+            return GL_STENCIL_BUFFER_BIT;
+        case BufferType::DEPTH_STENCIL:
+            return (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+        default:
+            return 0;
+    }
+}
+
+GLenum BufferTypeFormat(BufferType type)
+{
+    switch (type)
+    {
+        case BufferType::COLOR:
+            return GL_RGBA8;
+        case BufferType::DEPTH:
+            return GL_DEPTH_COMPONENT24;
+        case BufferType::STENCIL:
+            return GL_STENCIL_INDEX8;
+        case BufferType::DEPTH_STENCIL:
+            return GL_DEPTH24_STENCIL8;
+        default:
+            return GL_NONE;
+    }
+}
+
+GLenum BufferTypeAttachment(BufferType type)
+{
+    switch (type)
+    {
+        case BufferType::COLOR:
+            return GL_COLOR_ATTACHMENT0;
+        case BufferType::DEPTH:
+            return GL_DEPTH_ATTACHMENT;
+        case BufferType::STENCIL:
+            return GL_STENCIL_ATTACHMENT;
+        case BufferType::DEPTH_STENCIL:
+            return GL_DEPTH_STENCIL_ATTACHMENT;
+        default:
+            return GL_NONE;
+    }
+}
+
+struct BlitFramebufferParams final : public RenderTestParams
+{
+    BlitFramebufferParams()
+    {
+        majorVersion = 3;
+        minorVersion = 0;
+        windowWidth  = 256;
+        windowHeight = 256;
+    }
+
+    std::string suffix() const override
+    {
+        std::stringstream suffixStr;
+        suffixStr << RenderTestParams::suffix();
+        suffixStr << "_" << BufferTypeString(type);
+        if (samples > 1)
+        {
+            suffixStr << "_" << samples << "_samples";
+        }
+        return suffixStr.str();
+    }
+
+    BufferType type              = BufferType::COLOR;
+    unsigned int framebufferSize = 512;
+    unsigned int samples         = 0;
+    unsigned int iterations      = 5;
+};
+
+std::ostream &operator<<(std::ostream &os, const BlitFramebufferParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+class BlitFramebufferPerf : public ANGLERenderTest,
+                            public ::testing::WithParamInterface<BlitFramebufferParams>
+{
+  public:
+    BlitFramebufferPerf() : ANGLERenderTest("BlitFramebufferPerf", GetParam()) {}
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    GLuint mReadFramebuffer  = 0;
+    GLuint mReadRenderbuffer = 0;
+    GLuint mDrawFramebuffer  = 0;
+    GLuint mDrawRenderbuffer = 0;
+};
+
+void BlitFramebufferPerf::initializeBenchmark()
+{
+    const auto &param = GetParam();
+
+    glGenFramebuffers(1, &mReadFramebuffer);
+    glGenFramebuffers(1, &mDrawFramebuffer);
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
+
+    // Create source and destination Renderbuffers.
+    glGenRenderbuffers(1, &mReadRenderbuffer);
+    glGenRenderbuffers(1, &mDrawRenderbuffer);
+
+    ASSERT_GL_NO_ERROR();
+
+    GLenum format     = BufferTypeFormat(param.type);
+    GLuint size       = param.framebufferSize;
+    GLenum attachment = BufferTypeAttachment(param.type);
+
+    glBindRenderbuffer(GL_RENDERBUFFER, mReadRenderbuffer);
+    glRenderbufferStorageMultisample(GL_RENDERBUFFER, param.samples, format, size, size);
+    glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, attachment, GL_RENDERBUFFER, mReadRenderbuffer);
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
+
+    glBindRenderbuffer(GL_RENDERBUFFER, mDrawRenderbuffer);
+    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, size, size);
+    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, mDrawRenderbuffer);
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void BlitFramebufferPerf::destroyBenchmark()
+{
+    glDeleteFramebuffers(1, &mReadFramebuffer);
+    glDeleteRenderbuffers(1, &mReadRenderbuffer);
+    glDeleteFramebuffers(1, &mDrawFramebuffer);
+    glDeleteRenderbuffers(1, &mDrawRenderbuffer);
+}
+
+void BlitFramebufferPerf::drawBenchmark()
+{
+    const auto &param = GetParam();
+    auto size         = param.framebufferSize;
+    auto mask         = BufferTypeMask(param.type);
+
+    // We don't read from the draw buffer (ie rendering) to simplify the test, but we could.
+    // This might trigger a flush, or we could trigger a flush manually to ensure the blit happens.
+    // TODO(jmadill): Investigate performance on Vulkan, and placement of Clear call.
+
+    switch (param.type)
+    {
+        case BufferType::COLOR:
+        {
+            GLfloat clearValues[4] = {1.0f, 0.0f, 0.0f, 1.0f};
+            glClearBufferfv(GL_COLOR, 0, clearValues);
+            break;
+        }
+        case BufferType::DEPTH:
+        {
+            GLfloat clearDepthValue = 0.5f;
+            glClearBufferfv(GL_DEPTH, 0, &clearDepthValue);
+            break;
+        }
+        case BufferType::STENCIL:
+        {
+            GLint clearStencilValue = 1;
+            glClearBufferiv(GL_STENCIL, 0, &clearStencilValue);
+            break;
+        }
+        case BufferType::DEPTH_STENCIL:
+            glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.5f, 1);
+            break;
+    }
+
+    for (unsigned int iteration = 0; iteration < param.iterations; ++iteration)
+    {
+        glBlitFramebuffer(0, 0, size, size, 0, 0, size, size, mask, GL_NEAREST);
+    }
+}
+
+TEST_P(BlitFramebufferPerf, Run)
+{
+    run();
+}
+
+BlitFramebufferParams D3D11(BufferType type, unsigned int samples)
+{
+    BlitFramebufferParams params;
+    params.eglParameters = angle::egl_platform::D3D11();
+    params.type          = type;
+    params.samples       = samples;
+    return params;
+}
+
+}  // anonymous namespace
+
+// TODO(jmadill): Programatically generate these combinations.
+ANGLE_INSTANTIATE_TEST(BlitFramebufferPerf,
+                       D3D11(BufferType::COLOR, 0),
+                       D3D11(BufferType::DEPTH, 0),
+                       D3D11(BufferType::STENCIL, 0),
+                       D3D11(BufferType::DEPTH_STENCIL, 0),
+                       D3D11(BufferType::COLOR, 2),
+                       D3D11(BufferType::DEPTH, 2),
+                       D3D11(BufferType::STENCIL, 2),
+                       D3D11(BufferType::DEPTH_STENCIL, 2))
diff --git a/src/third_party/angle/src/tests/perf_tests/BufferSubData.cpp b/src/third_party/angle/src/tests/perf_tests/BufferSubData.cpp
new file mode 100644
index 0000000..b73ceb0
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/BufferSubData.cpp
@@ -0,0 +1,390 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// BufferSubDataBenchmark:
+//   Performance test for ANGLE buffer updates.
+//
+
+#include <sstream>
+
+#include "ANGLEPerfTest.h"
+#include "test_utils/draw_call_perf_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct BufferSubDataParams final : public RenderTestParams
+{
+    BufferSubDataParams()
+    {
+        // Common default values
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth = 512;
+        windowHeight = 512;
+        updateSize = 3000;
+        bufferSize = 40000000;
+        iterations   = 4;
+        updateRate = 1;
+    }
+
+    std::string suffix() const override;
+
+    GLboolean vertexNormalized;
+    GLenum vertexType;
+    GLint vertexComponentCount;
+    unsigned int updateRate;
+
+    // static parameters
+    GLsizeiptr updateSize;
+    GLsizeiptr bufferSize;
+    unsigned int iterations;
+};
+
+std::ostream &operator<<(std::ostream &os, const BufferSubDataParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+class BufferSubDataBenchmark : public ANGLERenderTest,
+                               public ::testing::WithParamInterface<BufferSubDataParams>
+{
+  public:
+    BufferSubDataBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    GLuint mProgram;
+    GLuint mBuffer;
+    uint8_t *mUpdateData;
+    int mNumTris;
+};
+
+GLfloat *GetFloatData(GLint componentCount)
+{
+    static GLfloat vertices2[] =
+    {
+        1, 2,
+        0, 0,
+        2, 0,
+    };
+
+    static GLfloat vertices3[] =
+    {
+        1, 2, 1,
+        0, 0, 1,
+        2, 0, 1,
+    };
+
+    static GLfloat vertices4[] =
+    {
+        1, 2, 1, 3,
+        0, 0, 1, 3,
+        2, 0, 1, 3,
+    };
+
+    switch (componentCount)
+    {
+        case 2:
+            return vertices2;
+        case 3:
+            return vertices3;
+        case 4:
+            return vertices4;
+        default:
+            return nullptr;
+    }
+}
+
+template <class T>
+GLsizeiptr GetNormalizedData(GLsizeiptr numElements, GLfloat *floatData, std::vector<uint8_t> *data)
+{
+    GLsizeiptr triDataSize = sizeof(T) * numElements;
+    data->resize(triDataSize);
+
+    T *destPtr = reinterpret_cast<T*>(data->data());
+
+    for (GLsizeiptr dataIndex = 0; dataIndex < numElements; dataIndex++)
+    {
+        GLfloat scaled = floatData[dataIndex] * 0.25f;
+        destPtr[dataIndex] = static_cast<T>(scaled * static_cast<GLfloat>(std::numeric_limits<T>::max()));
+    }
+
+    return triDataSize;
+}
+
+template <class T>
+GLsizeiptr GetIntData(GLsizeiptr numElements, GLfloat *floatData, std::vector<uint8_t> *data)
+{
+    GLsizeiptr triDataSize = sizeof(T) * numElements;
+    data->resize(triDataSize);
+
+    T *destPtr = reinterpret_cast<T*>(data->data());
+
+    for (GLsizeiptr dataIndex = 0; dataIndex < numElements; dataIndex++)
+    {
+        destPtr[dataIndex] = static_cast<T>(floatData[dataIndex]);
+    }
+
+    return triDataSize;
+}
+
+GLsizeiptr GetVertexData(GLenum type, GLint componentCount, GLboolean normalized, std::vector<uint8_t> *data)
+{
+    GLsizeiptr triDataSize = 0;
+    GLfloat *floatData = GetFloatData(componentCount);
+
+    if (type == GL_FLOAT)
+    {
+        triDataSize = sizeof(GLfloat) * componentCount * 3;
+        data->resize(triDataSize);
+        memcpy(data->data(), floatData, triDataSize);
+    }
+    else if (normalized == GL_TRUE)
+    {
+        GLsizeiptr numElements = componentCount * 3;
+
+        switch (type)
+        {
+            case GL_BYTE:
+                triDataSize = GetNormalizedData<GLbyte>(numElements, floatData, data);
+                break;
+            case GL_SHORT:
+                triDataSize = GetNormalizedData<GLshort>(numElements, floatData, data);
+                break;
+            case GL_INT:
+                triDataSize = GetNormalizedData<GLint>(numElements, floatData, data);
+                break;
+            case GL_UNSIGNED_BYTE:
+                triDataSize = GetNormalizedData<GLubyte>(numElements, floatData, data);
+                break;
+            case GL_UNSIGNED_SHORT:
+                triDataSize = GetNormalizedData<GLushort>(numElements, floatData, data);
+                break;
+            case GL_UNSIGNED_INT:
+                triDataSize = GetNormalizedData<GLuint>(numElements, floatData, data);
+                break;
+            default:
+                assert(0);
+        }
+    }
+    else
+    {
+        GLsizeiptr numElements = componentCount * 3;
+
+        switch (type)
+        {
+            case GL_BYTE:
+                triDataSize = GetIntData<GLbyte>(numElements, floatData, data);
+                break;
+            case GL_SHORT:
+                triDataSize = GetIntData<GLshort>(numElements, floatData, data);
+                break;
+            case GL_INT:
+                triDataSize = GetIntData<GLint>(numElements, floatData, data);
+                break;
+            case GL_UNSIGNED_BYTE:
+                triDataSize = GetIntData<GLubyte>(numElements, floatData, data);
+                break;
+            case GL_UNSIGNED_SHORT:
+                triDataSize = GetIntData<GLushort>(numElements, floatData, data);
+                break;
+            case GL_UNSIGNED_INT:
+                triDataSize = GetIntData<GLuint>(numElements, floatData, data);
+                break;
+            default:
+                assert(0);
+        }
+    }
+
+    return triDataSize;
+}
+
+std::string BufferSubDataParams::suffix() const
+{
+    std::stringstream strstr;
+
+    strstr << RenderTestParams::suffix();
+
+    if (vertexNormalized)
+    {
+        strstr << "_norm";
+    }
+
+    switch (vertexType)
+    {
+        case GL_FLOAT:
+            strstr << "_float";
+            break;
+        case GL_INT:
+            strstr << "_int";
+            break;
+        case GL_BYTE:
+            strstr << "_byte";
+            break;
+        case GL_SHORT:
+            strstr << "_short";
+            break;
+        case GL_UNSIGNED_INT:
+            strstr << "_uint";
+            break;
+        case GL_UNSIGNED_BYTE:
+            strstr << "_ubyte";
+            break;
+        case GL_UNSIGNED_SHORT:
+            strstr << "_ushort";
+            break;
+        default:
+            strstr << "_vunk_" << vertexType << "_";
+            break;
+    }
+
+    strstr << vertexComponentCount;
+    strstr << "_every" << updateRate;
+
+    return strstr.str();
+}
+
+BufferSubDataBenchmark::BufferSubDataBenchmark()
+    : ANGLERenderTest("BufferSubData", GetParam()),
+      mProgram(0),
+      mBuffer(0),
+      mUpdateData(nullptr),
+      mNumTris(0)
+{
+}
+
+void BufferSubDataBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    ASSERT_LT(1, params.vertexComponentCount);
+    ASSERT_LT(0u, params.iterations);
+
+    mProgram = SetupSimpleScaleAndOffsetProgram();
+    ASSERT_NE(0u, mProgram);
+
+    if (params.vertexNormalized == GL_TRUE)
+    {
+        GLfloat scale  = 2.0f;
+        GLfloat offset = -0.5f;
+        glUniform1f(glGetUniformLocation(mProgram, "uScale"), scale);
+        glUniform1f(glGetUniformLocation(mProgram, "uOffset"), offset);
+    }
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    std::vector<uint8_t> zeroData(params.bufferSize);
+    memset(&zeroData[0], 0, zeroData.size());
+
+    glGenBuffers(1, &mBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    glBufferData(GL_ARRAY_BUFFER, params.bufferSize, &zeroData[0], GL_DYNAMIC_DRAW);
+
+    glVertexAttribPointer(0, params.vertexComponentCount, params.vertexType,
+                          params.vertexNormalized, 0, 0);
+    glEnableVertexAttribArray(0);
+
+    if (params.updateSize > 0)
+    {
+        mUpdateData = new uint8_t[params.updateSize];
+    }
+
+    std::vector<uint8_t> data;
+    GLsizei triDataSize = static_cast<GLsizei>(GetVertexData(params.vertexType,
+                                                             params.vertexComponentCount,
+                                                             params.vertexNormalized, &data));
+
+    mNumTris = static_cast<int>(params.updateSize / triDataSize);
+    for (int i = 0, offset = 0; i < mNumTris; ++i)
+    {
+        memcpy(mUpdateData + offset, &data[0], triDataSize);
+        offset += triDataSize;
+    }
+
+    if (params.updateSize == 0)
+    {
+        mNumTris = 1;
+        glBufferSubData(GL_ARRAY_BUFFER, 0, data.size(), &data[0]);
+    }
+
+    // Set the viewport
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void BufferSubDataBenchmark::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+    glDeleteBuffers(1, &mBuffer);
+    SafeDeleteArray(mUpdateData);
+}
+
+void BufferSubDataBenchmark::drawBenchmark()
+{
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    const auto &params = GetParam();
+
+    for (unsigned int it = 0; it < params.iterations; it++)
+    {
+        if (params.updateSize > 0 && ((getNumStepsPerformed() % params.updateRate) == 0))
+        {
+            glBufferSubData(GL_ARRAY_BUFFER, 0, params.updateSize, mUpdateData);
+        }
+
+        glDrawArrays(GL_TRIANGLES, 0, 3 * mNumTris);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+BufferSubDataParams BufferUpdateD3D11Params()
+{
+    BufferSubDataParams params;
+    params.eglParameters = egl_platform::D3D11();
+    params.vertexType = GL_FLOAT;
+    params.vertexComponentCount = 4;
+    params.vertexNormalized = GL_FALSE;
+    return params;
+}
+
+BufferSubDataParams BufferUpdateD3D9Params()
+{
+    BufferSubDataParams params;
+    params.eglParameters = egl_platform::D3D9();
+    params.vertexType = GL_FLOAT;
+    params.vertexComponentCount = 4;
+    params.vertexNormalized = GL_FALSE;
+    return params;
+}
+
+BufferSubDataParams BufferUpdateOpenGLParams()
+{
+    BufferSubDataParams params;
+    params.eglParameters = egl_platform::OPENGL();
+    params.vertexType = GL_FLOAT;
+    params.vertexComponentCount = 4;
+    params.vertexNormalized = GL_FALSE;
+    return params;
+}
+
+TEST_P(BufferSubDataBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(BufferSubDataBenchmark,
+                       BufferUpdateD3D11Params(), BufferUpdateD3D9Params(),
+                       BufferUpdateOpenGLParams());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/DrawCallPerf.cpp b/src/third_party/angle/src/tests/perf_tests/DrawCallPerf.cpp
new file mode 100644
index 0000000..860c558
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/DrawCallPerf.cpp
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DrawCallPerf:
+//   Performance tests for ANGLE draw call overhead.
+//
+
+#include "ANGLEPerfTest.h"
+#include "DrawCallPerfParams.h"
+#include "test_utils/draw_call_perf_utils.h"
+
+namespace
+{
+
+class DrawCallPerfBenchmark : public ANGLERenderTest,
+                              public ::testing::WithParamInterface<DrawCallPerfParams>
+{
+  public:
+    DrawCallPerfBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    GLuint mProgram = 0;
+    GLuint mBuffer  = 0;
+    GLuint mFBO     = 0;
+    GLuint mTexture = 0;
+    int mNumTris    = GetParam().numTris;
+};
+
+DrawCallPerfBenchmark::DrawCallPerfBenchmark() : ANGLERenderTest("DrawCallPerf", GetParam())
+{
+    mRunTimeSeconds = GetParam().runTimeSeconds;
+}
+
+void DrawCallPerfBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    ASSERT_LT(0u, params.iterations);
+
+    mProgram = SetupSimpleDrawProgram();
+    ASSERT_NE(0u, mProgram);
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    mBuffer = Create2DTriangleBuffer(mNumTris, GL_STATIC_DRAW);
+
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(0);
+
+    // Set the viewport
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    if (params.useFBO)
+    {
+        CreateColorFBO(getWindow()->getWidth(), getWindow()->getHeight(), &mTexture, &mFBO);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void DrawCallPerfBenchmark::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+    glDeleteBuffers(1, &mBuffer);
+    glDeleteTextures(1, &mTexture);
+    glDeleteFramebuffers(1, &mFBO);
+}
+
+void DrawCallPerfBenchmark::drawBenchmark()
+{
+    // This workaround fixes a huge queue of graphics commands accumulating on the GL
+    // back-end. The GL back-end doesn't have a proper NULL device at the moment.
+    // TODO(jmadill): Remove this when/if we ever get a proper OpenGL NULL device.
+    const auto &eglParams = GetParam().eglParameters;
+    if (eglParams.deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE ||
+        (eglParams.renderer != EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE &&
+         eglParams.renderer != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE))
+    {
+        glClear(GL_COLOR_BUFFER_BIT);
+    }
+
+    const auto &params = GetParam();
+
+    for (unsigned int it = 0; it < params.iterations; it++)
+    {
+        glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(3 * mNumTris));
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+TEST_P(DrawCallPerfBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(DrawCallPerfBenchmark,
+                       DrawCallPerfD3D9Params(false, false),
+                       DrawCallPerfD3D9Params(true, false),
+                       DrawCallPerfD3D11Params(false, false),
+                       DrawCallPerfD3D11Params(true, false),
+                       DrawCallPerfD3D11Params(true, true),
+                       DrawCallPerfOpenGLParams(false, false),
+                       DrawCallPerfOpenGLParams(true, false),
+                       DrawCallPerfOpenGLParams(true, true),
+                       DrawCallPerfValidationOnly(),
+                       DrawCallPerfVulkanParams(false));
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/DrawCallPerfParams.cpp b/src/third_party/angle/src/tests/perf_tests/DrawCallPerfParams.cpp
new file mode 100644
index 0000000..d09667d
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/DrawCallPerfParams.cpp
@@ -0,0 +1,86 @@
+//
+// Copyright (c) 2017 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.
+//
+// DrawCallPerfParams.cpp:
+//   Parametrization for performance tests for ANGLE draw call overhead.
+//
+
+#include "DrawCallPerfParams.h"
+
+#include <sstream>
+
+std::ostream &operator<<(std::ostream &os, const DrawCallPerfParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+std::string DrawCallPerfParams::suffix() const
+{
+    std::stringstream strstr;
+
+    strstr << RenderTestParams::suffix();
+
+    if (numTris == 0)
+    {
+        strstr << "_validation_only";
+    }
+
+    if (useFBO)
+    {
+        strstr << "_render_to_texture";
+    }
+
+    if (eglParameters.deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
+    {
+        strstr << "_null";
+    }
+
+    return strstr.str();
+}
+
+using namespace angle::egl_platform;
+
+DrawCallPerfParams DrawCallPerfD3D11Params(bool useNullDevice, bool renderToTexture)
+{
+    DrawCallPerfParams params;
+    params.eglParameters = useNullDevice ? D3D11_NULL() : D3D11();
+    params.useFBO        = renderToTexture;
+    return params;
+}
+
+DrawCallPerfParams DrawCallPerfD3D9Params(bool useNullDevice, bool renderToTexture)
+{
+    DrawCallPerfParams params;
+    params.eglParameters = useNullDevice ? D3D9_NULL() : D3D9();
+    params.useFBO        = renderToTexture;
+    return params;
+}
+
+DrawCallPerfParams DrawCallPerfOpenGLParams(bool useNullDevice, bool renderToTexture)
+{
+    DrawCallPerfParams params;
+    params.eglParameters = useNullDevice ? OPENGL_NULL() : OPENGL();
+    params.useFBO        = renderToTexture;
+    return params;
+}
+
+DrawCallPerfParams DrawCallPerfValidationOnly()
+{
+    DrawCallPerfParams params;
+    params.eglParameters  = DEFAULT();
+    params.iterations     = 10000;
+    params.numTris        = 0;
+    params.runTimeSeconds = 5.0;
+    return params;
+}
+
+DrawCallPerfParams DrawCallPerfVulkanParams(bool renderToTexture)
+{
+    DrawCallPerfParams params;
+    params.eglParameters = VULKAN();
+    params.useFBO        = renderToTexture;
+    return params;
+}
diff --git a/src/third_party/angle/src/tests/perf_tests/DrawCallPerfParams.h b/src/third_party/angle/src/tests/perf_tests/DrawCallPerfParams.h
new file mode 100644
index 0000000..7aae9ad
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/DrawCallPerfParams.h
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2017 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.
+//
+// DrawCallPerfParams.h:
+//   Parametrization for performance tests for ANGLE draw call overhead.
+//
+
+#ifndef TESTS_PERF_TESTS_DRAW_CALL_PERF_PARAMS_H_
+#define TESTS_PERF_TESTS_DRAW_CALL_PERF_PARAMS_H_
+
+#include <ostream>
+
+#include "ANGLEPerfTest.h"
+
+struct DrawCallPerfParams final : public RenderTestParams
+{
+    // Common default options
+    DrawCallPerfParams()
+    {
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth  = 256;
+        windowHeight = 256;
+    }
+
+    std::string suffix() const override;
+
+    unsigned int iterations = 50;
+    double runTimeSeconds   = 10.0;
+    int numTris             = 1;
+    bool useFBO             = false;
+};
+
+std::ostream &operator<<(std::ostream &os, const DrawCallPerfParams &params);
+
+DrawCallPerfParams DrawCallPerfD3D11Params(bool useNullDevice, bool renderToTexture);
+
+DrawCallPerfParams DrawCallPerfD3D9Params(bool useNullDevice, bool renderToTexture);
+
+DrawCallPerfParams DrawCallPerfOpenGLParams(bool useNullDevice, bool renderToTexture);
+
+DrawCallPerfParams DrawCallPerfValidationOnly();
+
+DrawCallPerfParams DrawCallPerfVulkanParams(bool renderToTexture);
+
+#endif  // TESTS_PERF_TESTS_DRAW_CALL_PERF_PARAMS_H_
diff --git a/src/third_party/angle/src/tests/perf_tests/DynamicPromotionPerfTest.cpp b/src/third_party/angle/src/tests/perf_tests/DynamicPromotionPerfTest.cpp
new file mode 100644
index 0000000..10dd483
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/DynamicPromotionPerfTest.cpp
@@ -0,0 +1,189 @@
+//
+// Copyright 2016 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.
+//
+// DynamicPromotionPerfTest:
+//   Tests that ANGLE will promote buffer specfied with DYNAMIC usage to static after a number of
+//   iterations without changing the data. It specifically affects the D3D back-end, which treats
+//   dynamic and static buffers quite differently.
+//
+
+#include "ANGLEPerfTest.h"
+#include "common/vector_utils.h"
+#include "random_utils.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct DynamicPromotionParams final : public RenderTestParams
+{
+    DynamicPromotionParams();
+    std::string suffix() const override;
+
+    size_t vertexCount;
+    unsigned int iterations;
+};
+
+DynamicPromotionParams::DynamicPromotionParams() : vertexCount(1024), iterations(4)
+{
+}
+
+std::string DynamicPromotionParams::suffix() const
+{
+    return RenderTestParams::suffix();
+}
+
+std::ostream &operator<<(std::ostream &os, const DynamicPromotionParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+class DynamicPromotionPerfTest : public ANGLERenderTest,
+                                 public testing::WithParamInterface<DynamicPromotionParams>
+{
+  public:
+    DynamicPromotionPerfTest();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    GLuint mProgram;
+    GLuint mElementArrayBuffer;
+    GLuint mArrayBuffer;
+};
+
+DynamicPromotionPerfTest::DynamicPromotionPerfTest()
+    : ANGLERenderTest("DynamicPromotion", GetParam()),
+      mProgram(0),
+      mElementArrayBuffer(0),
+      mArrayBuffer(0)
+{
+}
+
+void DynamicPromotionPerfTest::initializeBenchmark()
+{
+    const std::string &vertexShaderSource =
+        "attribute vec2 position;\n"
+        "attribute vec3 color;\n"
+        "varying vec3 vColor;\n"
+        "void main()\n"
+        "{\n"
+        "    vColor = color;\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "varying mediump vec3 vColor;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(vColor, 1);\n"
+        "}";
+
+    mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    ASSERT_NE(0u, mProgram);
+
+    const size_t vertexCount = GetParam().vertexCount;
+
+    std::vector<GLushort> indexData;
+    std::vector<Vector2> positionData;
+    std::vector<Vector3> colorData;
+
+    ASSERT_GE(static_cast<size_t>(std::numeric_limits<GLushort>::max()), vertexCount);
+
+    RNG rng(1);
+
+    for (size_t index = 0; index < vertexCount; ++index)
+    {
+        indexData.push_back(static_cast<GLushort>(index));
+
+        Vector2 position(rng.randomNegativeOneToOne(), rng.randomNegativeOneToOne());
+        positionData.push_back(position);
+
+        Vector3 color(rng.randomFloat(), rng.randomFloat(), rng.randomFloat());
+        colorData.push_back(color);
+    }
+
+    glGenBuffers(1, &mElementArrayBuffer);
+    glGenBuffers(1, &mArrayBuffer);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementArrayBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, mArrayBuffer);
+
+    GLsizeiptr elementArraySize  = sizeof(GLushort) * vertexCount;
+    GLsizeiptr positionArraySize = sizeof(Vector2) * vertexCount;
+    GLsizeiptr colorArraySize    = sizeof(Vector3) * vertexCount;
+
+    // The DYNAMIC_DRAW usage is the key to the test.
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementArraySize, indexData.data(), GL_DYNAMIC_DRAW);
+    glBufferData(GL_ARRAY_BUFFER, positionArraySize + colorArraySize, nullptr, GL_DYNAMIC_DRAW);
+    glBufferSubData(GL_ARRAY_BUFFER, 0, positionArraySize, positionData.data());
+    glBufferSubData(GL_ARRAY_BUFFER, positionArraySize, colorArraySize, colorData.data());
+
+    glUseProgram(mProgram);
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    ASSERT_NE(-1, positionLocation);
+    GLint colorLocation = glGetAttribLocation(mProgram, "color");
+    ASSERT_NE(-1, colorLocation);
+
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 0,
+                          reinterpret_cast<const void *>(positionArraySize));
+
+    glEnableVertexAttribArray(positionLocation);
+    glEnableVertexAttribArray(colorLocation);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void DynamicPromotionPerfTest::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+    glDeleteBuffers(1, &mElementArrayBuffer);
+    glDeleteBuffers(1, &mArrayBuffer);
+}
+
+void DynamicPromotionPerfTest::drawBenchmark()
+{
+    unsigned int iterations = GetParam().iterations;
+    size_t vertexCount      = GetParam().vertexCount;
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    for (unsigned int count = 0; count < iterations; ++count)
+    {
+        glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(vertexCount), GL_UNSIGNED_SHORT, nullptr);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+DynamicPromotionParams DynamicPromotionD3D11Params()
+{
+    DynamicPromotionParams params;
+    params.eglParameters = egl_platform::D3D11();
+    return params;
+}
+
+DynamicPromotionParams DynamicPromotionD3D9Params()
+{
+    DynamicPromotionParams params;
+    params.eglParameters = egl_platform::D3D9();
+    return params;
+}
+
+TEST_P(DynamicPromotionPerfTest, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(DynamicPromotionPerfTest,
+                       DynamicPromotionD3D11Params(),
+                       DynamicPromotionD3D9Params());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/EGLInitializePerf.cpp b/src/third_party/angle/src/tests/perf_tests/EGLInitializePerf.cpp
new file mode 100644
index 0000000..8564c94
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/EGLInitializePerf.cpp
@@ -0,0 +1,159 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// EGLInitializePerfTest:
+//   Performance test for device creation.
+//
+
+#include "ANGLEPerfTest.h"
+#include "Timer.h"
+#include "test_utils/angle_test_configs.h"
+#include "test_utils/angle_test_instantiate.h"
+#include "platform/Platform.h"
+
+using namespace testing;
+
+namespace
+{
+// Only applies to D3D11
+struct Captures final : private angle::NonCopyable
+{
+    Timer *timer           = CreateTimer();
+    size_t loadDLLsMS      = 0;
+    size_t createDeviceMS  = 0;
+    size_t initResourcesMS = 0;
+};
+
+double CapturePlatform_currentTime(angle::PlatformMethods *platformMethods)
+{
+    Captures *captures = static_cast<Captures *>(platformMethods->context);
+    return captures->timer->getElapsedTime();
+}
+
+void CapturePlatform_histogramCustomCounts(angle::PlatformMethods *platformMethods,
+                                           const char *name,
+                                           int sample,
+                                           int /*min*/,
+                                           int /*max*/,
+                                           int /*bucketCount*/)
+{
+    Captures *captures = static_cast<Captures *>(platformMethods->context);
+
+    // These must match the names of the histograms.
+    if (strcmp(name, "GPU.ANGLE.Renderer11InitializeDLLsMS") == 0)
+    {
+        captures->loadDLLsMS += static_cast<size_t>(sample);
+    }
+    // Note: not captured in debug, due to creating a debug device
+    else if (strcmp(name, "GPU.ANGLE.D3D11CreateDeviceMS") == 0)
+    {
+        captures->createDeviceMS += static_cast<size_t>(sample);
+    }
+    else if (strcmp(name, "GPU.ANGLE.Renderer11InitializeDeviceMS") == 0)
+    {
+        captures->initResourcesMS += static_cast<size_t>(sample);
+    }
+}
+
+class EGLInitializePerfTest : public ANGLEPerfTest,
+                              public WithParamInterface<angle::PlatformParameters>
+{
+  public:
+    EGLInitializePerfTest();
+    ~EGLInitializePerfTest();
+
+    void step() override;
+    void SetUp() override;
+    void TearDown() override;
+
+  private:
+    OSWindow *mOSWindow;
+    EGLDisplay mDisplay;
+    Captures mCaptures;
+};
+
+EGLInitializePerfTest::EGLInitializePerfTest()
+    : ANGLEPerfTest("EGLInitialize", "_run"),
+      mOSWindow(nullptr),
+      mDisplay(EGL_NO_DISPLAY)
+{
+    auto platform = GetParam().eglParameters;
+
+    std::vector<EGLint> displayAttributes;
+    displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+    displayAttributes.push_back(platform.renderer);
+    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
+    displayAttributes.push_back(platform.majorVersion);
+    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
+    displayAttributes.push_back(platform.minorVersion);
+
+    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE ||
+        platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+        displayAttributes.push_back(platform.deviceType);
+    }
+    displayAttributes.push_back(EGL_NONE);
+
+    mOSWindow = CreateOSWindow();
+    mOSWindow->initialize("EGLInitialize Test", 64, 64);
+
+    auto eglGetPlatformDisplayEXT =
+        reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+    if (eglGetPlatformDisplayEXT == nullptr)
+    {
+        std::cerr << "Error getting platform display!" << std::endl;
+        return;
+    }
+
+    mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
+                                        reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
+                                        &displayAttributes[0]);
+}
+
+void EGLInitializePerfTest::SetUp()
+{
+    ANGLEPerfTest::SetUp();
+
+    angle::PlatformMethods *platformMethods = nullptr;
+    ASSERT_TRUE(ANGLEGetDisplayPlatform(mDisplay, angle::g_PlatformMethodNames,
+                                        angle::g_NumPlatformMethods, &mCaptures, &platformMethods));
+
+    platformMethods->currentTime           = CapturePlatform_currentTime;
+    platformMethods->histogramCustomCounts = CapturePlatform_histogramCustomCounts;
+}
+
+EGLInitializePerfTest::~EGLInitializePerfTest()
+{
+    SafeDelete(mOSWindow);
+}
+
+void EGLInitializePerfTest::step()
+{
+    ASSERT_NE(EGL_NO_DISPLAY, mDisplay);
+
+    EGLint majorVersion, minorVersion;
+    ASSERT_EQ(static_cast<EGLBoolean>(EGL_TRUE), eglInitialize(mDisplay, &majorVersion, &minorVersion));
+    ASSERT_EQ(static_cast<EGLBoolean>(EGL_TRUE), eglTerminate(mDisplay));
+}
+
+void EGLInitializePerfTest::TearDown()
+{
+    ANGLEPerfTest::TearDown();
+    printResult("LoadDLLs", normalizedTime(mCaptures.loadDLLsMS), "ms", true);
+    printResult("D3D11CreateDevice", normalizedTime(mCaptures.createDeviceMS), "ms", true);
+    printResult("InitResources", normalizedTime(mCaptures.initResourcesMS), "ms", true);
+
+    ANGLEResetDisplayPlatform(mDisplay);
+}
+
+TEST_P(EGLInitializePerfTest, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(EGLInitializePerfTest, angle::ES2_D3D11());
+
+} // namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/IndexConversionPerf.cpp b/src/third_party/angle/src/tests/perf_tests/IndexConversionPerf.cpp
new file mode 100644
index 0000000..202c9c0
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/IndexConversionPerf.cpp
@@ -0,0 +1,227 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IndexConversionPerf:
+//   Performance tests for ANGLE index conversion in D3D11.
+//
+
+#include <sstream>
+
+#include "ANGLEPerfTest.h"
+#include "tests/test_utils/draw_call_perf_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct IndexConversionPerfParams final : public RenderTestParams
+{
+    std::string suffix() const override
+    {
+        std::stringstream strstr;
+
+        if (indexRangeOffset > 0)
+        {
+            strstr << "_index_range";
+        }
+
+        strstr << RenderTestParams::suffix();
+
+        return strstr.str();
+    }
+
+    unsigned int iterations;
+    unsigned int numIndexTris;
+
+    // A second test, which covers using index ranges with an offset.
+    unsigned int indexRangeOffset;
+};
+
+// Provide a custom gtest parameter name function for IndexConversionPerfParams.
+std::ostream &operator<<(std::ostream &stream, const IndexConversionPerfParams &param)
+{
+    stream << param.suffix().substr(1);
+    return stream;
+}
+
+class IndexConversionPerfTest : public ANGLERenderTest,
+                                public ::testing::WithParamInterface<IndexConversionPerfParams>
+{
+  public:
+    IndexConversionPerfTest();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    void updateBufferData();
+    void drawConversion();
+    void drawIndexRange();
+
+    GLuint mProgram;
+    GLuint mVertexBuffer;
+    GLuint mIndexBuffer;
+    std::vector<GLushort> mIndexData;
+};
+
+IndexConversionPerfTest::IndexConversionPerfTest()
+    : ANGLERenderTest("IndexConversionPerfTest", GetParam()),
+      mProgram(0),
+      mVertexBuffer(0),
+      mIndexBuffer(0)
+{
+    mRunTimeSeconds = 3.0;
+}
+
+void IndexConversionPerfTest::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    ASSERT_LT(0u, params.iterations);
+    ASSERT_LT(0u, params.numIndexTris);
+
+    mProgram = SetupSimpleScaleAndOffsetProgram();
+    ASSERT_NE(0u, mProgram);
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    // Initialize the vertex data
+    size_t numTris = std::numeric_limits<GLushort>::max() / 3 + 1;
+    mVertexBuffer  = Create2DTriangleBuffer(numTris, GL_STATIC_DRAW);
+
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
+    glEnableVertexAttribArray(0);
+
+    // Initialize the index buffer
+    for (unsigned int triIndex = 0; triIndex < params.numIndexTris; ++triIndex)
+    {
+        // Handle two different types of tests, one with index conversion triggered by a -1 index.
+        if (params.indexRangeOffset == 0)
+        {
+            mIndexData.push_back(std::numeric_limits<GLushort>::max());
+        }
+        else
+        {
+            mIndexData.push_back(0);
+        }
+
+        mIndexData.push_back(1);
+        mIndexData.push_back(2);
+    }
+
+    glGenBuffers(1, &mIndexBuffer);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+    updateBufferData();
+
+    // Set the viewport
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void IndexConversionPerfTest::updateBufferData()
+{
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndexData.size() * sizeof(mIndexData[0]), &mIndexData[0],
+                 GL_STATIC_DRAW);
+}
+
+void IndexConversionPerfTest::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+    glDeleteBuffers(1, &mVertexBuffer);
+    glDeleteBuffers(1, &mIndexBuffer);
+}
+
+void IndexConversionPerfTest::drawBenchmark()
+{
+    const auto &params = GetParam();
+
+    if (params.indexRangeOffset == 0)
+    {
+        drawConversion();
+    }
+    else
+    {
+        drawIndexRange();
+    }
+}
+
+void IndexConversionPerfTest::drawConversion()
+{
+    const auto &params = GetParam();
+
+    // Trigger an update to ensure we convert once a frame
+    updateBufferData();
+
+    for (unsigned int it = 0; it < params.iterations; it++)
+    {
+        glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(params.numIndexTris * 3 - 1),
+                       GL_UNSIGNED_SHORT, reinterpret_cast<void *>(0));
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void IndexConversionPerfTest::drawIndexRange()
+{
+    const auto &params = GetParam();
+
+    unsigned int indexCount = 3;
+    size_t offset           = static_cast<size_t>(indexCount * getNumStepsPerformed());
+
+    offset %= (params.numIndexTris * 3);
+
+    // This test increments an offset each step. Drawing repeatedly may cause the system memory
+    // to release. Then, using a fresh offset will require index range validation, which pages
+    // it back in. The performance should be good even if the data is was used quite a bit.
+    for (unsigned int it = 0; it < params.iterations; it++)
+    {
+        glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indexCount), GL_UNSIGNED_SHORT,
+                       reinterpret_cast<void *>(offset));
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+IndexConversionPerfParams IndexConversionPerfD3D11Params()
+{
+    IndexConversionPerfParams params;
+    params.eglParameters    = egl_platform::D3D11_NULL();
+    params.majorVersion     = 2;
+    params.minorVersion     = 0;
+    params.windowWidth      = 256;
+    params.windowHeight     = 256;
+    params.iterations       = 225;
+    params.numIndexTris     = 3000;
+    params.indexRangeOffset = 0;
+    return params;
+}
+
+IndexConversionPerfParams IndexRangeOffsetPerfD3D11Params()
+{
+    IndexConversionPerfParams params;
+    params.eglParameters    = egl_platform::D3D11_NULL();
+    params.majorVersion     = 2;
+    params.minorVersion     = 0;
+    params.windowWidth      = 256;
+    params.windowHeight     = 256;
+    params.iterations       = 16;
+    params.numIndexTris     = 50000;
+    params.indexRangeOffset = 64;
+    return params;
+}
+
+TEST_P(IndexConversionPerfTest, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(IndexConversionPerfTest,
+                       IndexConversionPerfD3D11Params(),
+                       IndexRangeOffsetPerfD3D11Params());
+
+}  // namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/IndexDataManagerTest.cpp b/src/third_party/angle/src/tests/perf_tests/IndexDataManagerTest.cpp
new file mode 100644
index 0000000..8a37ece
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/IndexDataManagerTest.cpp
@@ -0,0 +1,191 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IndexDataManagerPerfTest:
+//   Performance test for index buffer management.
+//
+
+#include "ANGLEPerfTest.h"
+
+#include <gmock/gmock.h>
+
+#include "angle_unittests_utils.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+
+using namespace testing;
+
+namespace
+{
+
+class MockIndexBuffer : public rx::IndexBuffer
+{
+  public:
+    MockIndexBuffer(unsigned int bufferSize, GLenum indexType)
+        : mBufferSize(bufferSize), mIndexType(indexType)
+    {
+    }
+
+    MOCK_METHOD3(initialize, gl::Error(unsigned int, GLenum, bool));
+    MOCK_METHOD3(mapBuffer, gl::Error(unsigned int, unsigned int, void **));
+    MOCK_METHOD0(unmapBuffer, gl::Error());
+    MOCK_METHOD0(discard, gl::Error());
+    MOCK_METHOD2(setSize, gl::Error(unsigned int, GLenum));
+
+    // inlined for speed
+    GLenum getIndexType() const override { return mIndexType; }
+    unsigned int getBufferSize() const override { return mBufferSize; }
+
+  private:
+    unsigned int mBufferSize;
+    GLenum mIndexType;
+};
+
+class MockBufferFactoryD3D : public rx::BufferFactoryD3D
+{
+  public:
+    MockBufferFactoryD3D(unsigned int bufferSize, GLenum indexType)
+        : mBufferSize(bufferSize), mIndexType(indexType)
+    {
+    }
+
+    MOCK_METHOD0(createVertexBuffer, rx::VertexBuffer *());
+    MOCK_CONST_METHOD1(getVertexConversionType, rx::VertexConversionType(gl::VertexFormatType));
+    MOCK_CONST_METHOD1(getVertexComponentType, GLenum(gl::VertexFormatType));
+    MOCK_CONST_METHOD4(getVertexSpaceRequired,
+                       gl::ErrorOrResult<unsigned int>(const gl::VertexAttribute &,
+                                                       const gl::VertexBinding &,
+                                                       GLsizei,
+                                                       GLsizei));
+
+    // Dependency injection
+    rx::IndexBuffer *createIndexBuffer() override
+    {
+        return new MockIndexBuffer(mBufferSize, mIndexType);
+    }
+
+  private:
+    unsigned int mBufferSize;
+    GLenum mIndexType;
+};
+
+class MockBufferD3D : public rx::BufferD3D
+{
+  public:
+    MockBufferD3D(rx::BufferFactoryD3D *factory) : BufferD3D(mockState, factory), mData() {}
+
+    // BufferImpl
+    gl::Error setData(rx::ContextImpl *context,
+                      GLenum target,
+                      const void *data,
+                      size_t size,
+                      GLenum) override
+    {
+        mData.resize(size);
+        if (data && size > 0)
+        {
+            memcpy(&mData[0], data, size);
+        }
+        return gl::NoError();
+    }
+
+    MOCK_METHOD5(setSubData, gl::Error(rx::ContextImpl *, GLenum, const void *, size_t, size_t));
+    MOCK_METHOD5(copySubData,
+                 gl::Error(rx::ContextImpl *context, BufferImpl *, GLintptr, GLintptr, GLsizeiptr));
+    MOCK_METHOD3(map, gl::Error(rx::ContextImpl *context, GLenum, void **));
+    MOCK_METHOD5(mapRange,
+                 gl::Error(rx::ContextImpl *context, size_t, size_t, GLbitfield, void **));
+    MOCK_METHOD2(unmap, gl::Error(rx::ContextImpl *context, GLboolean *));
+
+    // BufferD3D
+    MOCK_METHOD0(markTransformFeedbackUsage, gl::Error());
+
+    // inlined for speed
+    bool supportsDirectBinding() const override { return false; }
+    size_t getSize() const override { return mData.size(); }
+
+    gl::Error getData(const uint8_t **outData) override
+    {
+        *outData = &mData[0];
+        return gl::NoError();
+    }
+
+  private:
+    gl::BufferState mockState;
+    std::vector<uint8_t> mData;
+};
+
+class MockGLFactoryD3D : public rx::MockGLFactory
+{
+  public:
+    MockGLFactoryD3D(MockBufferFactoryD3D *bufferFactory) : mBufferFactory(bufferFactory) {}
+
+    rx::BufferImpl *createBuffer(const gl::BufferState &state) override
+    {
+        MockBufferD3D *mockBufferD3D = new MockBufferD3D(mBufferFactory);
+
+        EXPECT_CALL(*mBufferFactory, createVertexBuffer())
+            .WillOnce(Return(nullptr))
+            .RetiresOnSaturation();
+        mockBufferD3D->initializeStaticData();
+
+        return mockBufferD3D;
+    }
+
+    MockBufferFactoryD3D *mBufferFactory;
+};
+
+class IndexDataManagerPerfTest : public ANGLEPerfTest
+{
+  public:
+    IndexDataManagerPerfTest();
+
+    void step() override;
+
+    rx::IndexDataManager mIndexDataManager;
+    GLsizei mIndexCount;
+    unsigned int mBufferSize;
+    MockBufferFactoryD3D mMockBufferFactory;
+    MockGLFactoryD3D mMockGLFactory;
+    gl::Buffer mIndexBuffer;
+};
+
+IndexDataManagerPerfTest::IndexDataManagerPerfTest()
+    : ANGLEPerfTest("IndexDataManger", "_run"),
+      mIndexDataManager(&mMockBufferFactory, rx::RENDERER_D3D11),
+      mIndexCount(4000),
+      mBufferSize(mIndexCount * sizeof(GLushort)),
+      mMockBufferFactory(mBufferSize, GL_UNSIGNED_SHORT),
+      mMockGLFactory(&mMockBufferFactory),
+      mIndexBuffer(&mMockGLFactory, 1)
+{
+    std::vector<GLushort> indexData(mIndexCount);
+    for (GLsizei index = 0; index < mIndexCount; ++index)
+    {
+        indexData[index] = static_cast<GLushort>(index);
+    }
+    mIndexBuffer.bufferData(nullptr, GL_ARRAY_BUFFER, &indexData[0],
+                            indexData.size() * sizeof(GLushort), GL_STATIC_DRAW);
+}
+
+void IndexDataManagerPerfTest::step()
+{
+    rx::TranslatedIndexData translatedIndexData;
+    for (unsigned int iteration = 0; iteration < 100; ++iteration)
+    {
+        mIndexBuffer.getIndexRange(GL_UNSIGNED_SHORT, 0, mIndexCount, false,
+                                   &translatedIndexData.indexRange);
+        mIndexDataManager.prepareIndexData(GL_UNSIGNED_SHORT, mIndexCount, &mIndexBuffer, nullptr,
+                                           &translatedIndexData, false);
+    }
+}
+
+TEST_F(IndexDataManagerPerfTest, Run)
+{
+    run();
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/InstancingPerf.cpp b/src/third_party/angle/src/tests/perf_tests/InstancingPerf.cpp
new file mode 100644
index 0000000..3d21607
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/InstancingPerf.cpp
@@ -0,0 +1,364 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// InstancingPerf:
+//   Performance tests for ANGLE instanced draw calls.
+//
+
+#include <cmath>
+#include <sstream>
+
+#include "ANGLEPerfTest.h"
+#include "Matrix.h"
+#include "random_utils.h"
+#include "shader_utils.h"
+
+using namespace angle;
+using namespace egl_platform;
+
+namespace
+{
+
+float AnimationSignal(float t)
+{
+    float l = t / 2.0f;
+    float f = l - std::floor(l);
+    return (f > 0.5f ? 1.0f - f : f) * 4.0f - 1.0f;
+}
+
+template <typename T>
+size_t VectorSizeBytes(const std::vector<T> &vec)
+{
+    return sizeof(T) * vec.size();
+}
+
+Vector3 RandomVector3(RNG *rng)
+{
+    return Vector3(rng->randomNegativeOneToOne(), rng->randomNegativeOneToOne(),
+                   rng->randomNegativeOneToOne());
+}
+
+struct InstancingPerfParams final : public RenderTestParams
+{
+    // Common default options
+    InstancingPerfParams()
+    {
+        majorVersion      = 2;
+        minorVersion      = 0;
+        windowWidth       = 256;
+        windowHeight      = 256;
+        iterations        = 1;
+        runTimeSeconds    = 10.0;
+        animationEnabled  = false;
+        instancingEnabled = true;
+    }
+
+    std::string suffix() const override
+    {
+        std::stringstream strstr;
+
+        strstr << RenderTestParams::suffix();
+
+        if (!instancingEnabled)
+        {
+            strstr << "_billboards";
+        }
+
+        return strstr.str();
+    }
+
+    unsigned int iterations;
+    double runTimeSeconds;
+    bool animationEnabled;
+    bool instancingEnabled;
+};
+
+std::ostream &operator<<(std::ostream &os, const InstancingPerfParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+class InstancingPerfBenchmark : public ANGLERenderTest,
+                                public ::testing::WithParamInterface<InstancingPerfParams>
+{
+  public:
+    InstancingPerfBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    GLuint mProgram;
+    std::vector<GLuint> mBuffers;
+    GLuint mNumPoints;
+    std::vector<Vector3> mTranslateData;
+    std::vector<float> mSizeData;
+    std::vector<Vector3> mColorData;
+    angle::RNG mRNG;
+};
+
+InstancingPerfBenchmark::InstancingPerfBenchmark()
+    : ANGLERenderTest("InstancingPerf", GetParam()), mProgram(0), mNumPoints(75000)
+{
+    mRunTimeSeconds = GetParam().runTimeSeconds;
+}
+
+void InstancingPerfBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    ASSERT_LT(0u, params.iterations);
+
+    const std::string vs =
+        "attribute vec2 aPosition;\n"
+        "attribute vec3 aTranslate;\n"
+        "attribute float aScale;\n"
+        "attribute vec3 aColor;\n"
+        "uniform mat4 uWorldMatrix;\n"
+        "uniform mat4 uProjectionMatrix;\n"
+        "varying vec3 vColor;\n"
+        "void main()\n"
+        "{\n"
+        "    vec4 position = uWorldMatrix * vec4(aTranslate, 1.0);\n"
+        "    position.xy += aPosition * aScale;\n"
+        "    gl_Position = uProjectionMatrix * position;\n"
+        "    vColor = aColor;\n"
+        "}\n";
+
+    const std::string fs =
+        "precision mediump float;\n"
+        "varying vec3 vColor;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(vColor, 1.0);\n"
+        "}\n";
+
+    mProgram = CompileProgram(vs, fs);
+    ASSERT_NE(0u, mProgram);
+
+    glUseProgram(mProgram);
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    GLuint baseIndexData[6]     = {0, 1, 2, 1, 3, 2};
+    Vector2 basePositionData[4] = {Vector2(-1.0f, 1.0f), Vector2(1.0f, 1.0f), Vector2(-1.0f, -1.0f),
+                                   Vector2(1.0f, -1.0f)};
+
+    std::vector<GLuint> indexData;
+    std::vector<Vector2> positionData;
+
+    if (!params.instancingEnabled)
+    {
+        GLuint pointVertexStride = 4;
+        for (GLuint pointIndex = 0; pointIndex < mNumPoints; ++pointIndex)
+        {
+            for (GLuint indexIndex = 0; indexIndex < 6; ++indexIndex)
+            {
+                indexData.push_back(baseIndexData[indexIndex] + pointIndex * pointVertexStride);
+            }
+
+            Vector3 randVec = RandomVector3(&mRNG);
+            for (GLuint vertexIndex = 0; vertexIndex < 4; ++vertexIndex)
+            {
+                positionData.push_back(basePositionData[vertexIndex]);
+                mTranslateData.push_back(randVec);
+            }
+        }
+
+        mSizeData.resize(mNumPoints * 4, 0.012f);
+        mColorData.resize(mNumPoints * 4, Vector3(1.0f, 0.0f, 0.0f));
+    }
+    else
+    {
+        for (GLuint index : baseIndexData)
+        {
+            indexData.push_back(index);
+        }
+
+        for (const Vector2 &position : basePositionData)
+        {
+            positionData.push_back(position);
+        }
+
+        for (GLuint pointIndex = 0; pointIndex < mNumPoints; ++pointIndex)
+        {
+            Vector3 randVec = RandomVector3(&mRNG);
+            mTranslateData.push_back(randVec);
+        }
+
+        mSizeData.resize(mNumPoints, 0.012f);
+        mColorData.resize(mNumPoints, Vector3(1.0f, 0.0f, 0.0f));
+    }
+
+    mBuffers.resize(5, 0);
+    glGenBuffers(static_cast<GLsizei>(mBuffers.size()), &mBuffers[0]);
+
+    // Index Data
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffers[0]);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, VectorSizeBytes(indexData), &indexData[0],
+                 GL_STATIC_DRAW);
+
+    // Position Data
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[1]);
+    glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(positionData), &positionData[0], GL_STATIC_DRAW);
+    GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");
+    ASSERT_NE(-1, positionLocation);
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 8, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+
+    // Translate Data
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[2]);
+    glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(mTranslateData), &mTranslateData[0],
+                 GL_STATIC_DRAW);
+    GLint translateLocation = glGetAttribLocation(mProgram, "aTranslate");
+    ASSERT_NE(-1, translateLocation);
+    glVertexAttribPointer(translateLocation, 3, GL_FLOAT, GL_FALSE, 12, nullptr);
+    glEnableVertexAttribArray(translateLocation);
+    glVertexAttribDivisorANGLE(translateLocation, 1);
+
+    // Scale Data
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[3]);
+    glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(mSizeData), nullptr, GL_DYNAMIC_DRAW);
+    GLint scaleLocation = glGetAttribLocation(mProgram, "aScale");
+    ASSERT_NE(-1, scaleLocation);
+    glVertexAttribPointer(scaleLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
+    glEnableVertexAttribArray(scaleLocation);
+    glVertexAttribDivisorANGLE(scaleLocation, 1);
+
+    // Color Data
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[4]);
+    glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(mColorData), nullptr, GL_DYNAMIC_DRAW);
+    GLint colorLocation = glGetAttribLocation(mProgram, "aColor");
+    ASSERT_NE(-1, colorLocation);
+    glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 12, nullptr);
+    glEnableVertexAttribArray(colorLocation);
+    glVertexAttribDivisorANGLE(colorLocation, 1);
+
+    // Set the viewport
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    // Init matrices
+    GLint worldMatrixLocation = glGetUniformLocation(mProgram, "uWorldMatrix");
+    ASSERT_NE(-1, worldMatrixLocation);
+    Matrix4 worldMatrix = Matrix4::translate(Vector3(0, 0, -3.0f));
+    worldMatrix *= Matrix4::rotate(25.0f, Vector3(0.6f, 1.0f, 0.0f));
+    glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, &worldMatrix.data[0]);
+
+    GLint projectionMatrixLocation = glGetUniformLocation(mProgram, "uProjectionMatrix");
+    ASSERT_NE(-1, projectionMatrixLocation);
+    float fov =
+        static_cast<float>(getWindow()->getWidth()) / static_cast<float>(getWindow()->getHeight());
+    Matrix4 projectionMatrix = Matrix4::perspective(60.0f, fov, 1.0f, 300.0f);
+    glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix.data[0]);
+
+    getWindow()->setVisible(true);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void InstancingPerfBenchmark::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+
+    if (!mBuffers.empty())
+    {
+        glDeleteBuffers(static_cast<GLsizei>(mBuffers.size()), &mBuffers[0]);
+        mBuffers.clear();
+    }
+}
+
+void InstancingPerfBenchmark::drawBenchmark()
+{
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    const auto &params = GetParam();
+
+    // Animatino makes the test more interesting visually, but also eats up many CPU cycles.
+    if (params.animationEnabled)
+    {
+        // Not implemented for billboards.
+        ASSERT(params.instancingEnabled);
+
+        float time = static_cast<float>(mTimer->getElapsedTime());
+
+        for (size_t pointIndex = 0; pointIndex < mTranslateData.size(); ++pointIndex)
+        {
+            const Vector3 &translate = mTranslateData[pointIndex];
+
+            float tx = translate.x() + time;
+            float ty = translate.y() + time;
+            float tz = translate.z() + time;
+
+            float scale           = AnimationSignal(tx) * 0.01f + 0.01f;
+            mSizeData[pointIndex] = scale;
+
+            Vector3 color =
+                Vector3(AnimationSignal(tx), AnimationSignal(ty), AnimationSignal(tz)) * 0.5f +
+                Vector3(0.5f);
+
+            mColorData[pointIndex] = color;
+        }
+    }
+
+    // Update scales and colors.
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[3]);
+    glBufferSubData(GL_ARRAY_BUFFER, 0, VectorSizeBytes(mSizeData), &mSizeData[0]);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[4]);
+    glBufferSubData(GL_ARRAY_BUFFER, 0, VectorSizeBytes(mColorData), &mColorData[0]);
+
+    // Render the instances/billboards.
+    if (params.instancingEnabled)
+    {
+        for (unsigned int it = 0; it < params.iterations; it++)
+        {
+            glDrawElementsInstancedANGLE(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, mNumPoints);
+        }
+    }
+    else
+    {
+        for (unsigned int it = 0; it < params.iterations; it++)
+        {
+            glDrawElements(GL_TRIANGLES, 6 * mNumPoints, GL_UNSIGNED_INT, nullptr);
+        }
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+InstancingPerfParams InstancingPerfD3D11Params()
+{
+    InstancingPerfParams params;
+    params.eglParameters = D3D11();
+    return params;
+}
+
+InstancingPerfParams InstancingPerfD3D9Params()
+{
+    InstancingPerfParams params;
+    params.eglParameters = D3D9();
+    return params;
+}
+
+InstancingPerfParams InstancingPerfOpenGLParams()
+{
+    InstancingPerfParams params;
+    params.eglParameters = OPENGL();
+    return params;
+}
+
+TEST_P(InstancingPerfBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(InstancingPerfBenchmark,
+                       InstancingPerfD3D11Params(),
+                       InstancingPerfD3D9Params(),
+                       InstancingPerfOpenGLParams());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/InterleavedAttributeData.cpp b/src/third_party/angle/src/tests/perf_tests/InterleavedAttributeData.cpp
new file mode 100644
index 0000000..15e2a5b
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/InterleavedAttributeData.cpp
@@ -0,0 +1,231 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// InterleavedAttributeData:
+//   Performance test for draws using interleaved attribute data in vertex buffers.
+//
+
+#include <sstream>
+
+#include "ANGLEPerfTest.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct InterleavedAttributeDataParams final : public RenderTestParams
+{
+    InterleavedAttributeDataParams()
+    {
+        // Common default values
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth  = 512;
+        windowHeight = 512;
+        numSprites   = 3000;
+    }
+
+    // static parameters
+    unsigned int numSprites;
+};
+
+std::ostream &operator<<(std::ostream &os, const InterleavedAttributeDataParams &params)
+{
+    os << params.suffix().substr(1);
+
+    if (params.eglParameters.majorVersion != EGL_DONT_CARE)
+    {
+        os << "_" << params.eglParameters.majorVersion << "_" << params.eglParameters.minorVersion;
+    }
+
+    return os;
+}
+
+class InterleavedAttributeDataBenchmark
+    : public ANGLERenderTest,
+      public ::testing::WithParamInterface<InterleavedAttributeDataParams>
+{
+  public:
+    InterleavedAttributeDataBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    GLuint mPointSpriteProgram;
+    GLuint mPositionColorBuffer[2];
+
+    // The buffers contain two floats and 3 unsigned bytes per point sprite
+    const size_t mBytesPerSprite = 2 * sizeof(float) + 3;
+};
+
+InterleavedAttributeDataBenchmark::InterleavedAttributeDataBenchmark()
+    : ANGLERenderTest("InterleavedAttributeData", GetParam()), mPointSpriteProgram(0)
+{
+}
+
+void InterleavedAttributeDataBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    // Compile point sprite shaders
+    const std::string vs =
+        "attribute vec4 aPosition;"
+        "attribute vec4 aColor;"
+        "varying vec4 vColor;"
+        "void main()"
+        "{"
+        "    gl_PointSize = 25.0;"
+        "    gl_Position  = aPosition;"
+        "    vColor = aColor;"
+        "}";
+
+    const std::string fs =
+        "precision mediump float;"
+        "varying vec4 vColor;"
+        "void main()"
+        "{"
+        "    gl_FragColor = vColor;"
+        "}";
+
+    mPointSpriteProgram = CompileProgram(vs, fs);
+    ASSERT_NE(0u, mPointSpriteProgram);
+
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+
+    for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
+    {
+        // Set up initial data for pointsprite positions and colors
+        std::vector<uint8_t> positionColorData(mBytesPerSprite * params.numSprites);
+        for (unsigned int j = 0; j < params.numSprites; j++)
+        {
+            float pointSpriteX =
+                (static_cast<float>(rand() % getWindow()->getWidth()) / getWindow()->getWidth()) *
+                    2.0f - 1.0f;
+            float pointSpriteY =
+                (static_cast<float>(rand() % getWindow()->getHeight()) / getWindow()->getHeight()) *
+                    2.0f - 1.0f;
+            GLubyte pointSpriteRed   = static_cast<GLubyte>(rand() % 255);
+            GLubyte pointSpriteGreen = static_cast<GLubyte>(rand() % 255);
+            GLubyte pointSpriteBlue  = static_cast<GLubyte>(rand() % 255);
+
+            // Add position data for the pointsprite
+            *reinterpret_cast<float *>(
+                &(positionColorData[j * mBytesPerSprite + 0 * sizeof(float) + 0])) =
+                pointSpriteX;  // X
+            *reinterpret_cast<float *>(
+                &(positionColorData[j * mBytesPerSprite + 1 * sizeof(float) + 0])) =
+                pointSpriteY;  // Y
+
+            // Add color data for the pointsprite
+            positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 0] = pointSpriteRed;    // R
+            positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 1] = pointSpriteGreen;  // G
+            positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 2] = pointSpriteBlue;   // B
+        }
+
+        // Generate the GL buffer with the position/color data
+        glGenBuffers(1, &mPositionColorBuffer[i]);
+        glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
+        glBufferData(GL_ARRAY_BUFFER, params.numSprites * mBytesPerSprite, &(positionColorData[0]),
+                     GL_STATIC_DRAW);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void InterleavedAttributeDataBenchmark::destroyBenchmark()
+{
+    glDeleteProgram(mPointSpriteProgram);
+
+    for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
+    {
+        glDeleteBuffers(1, &mPositionColorBuffer[i]);
+    }
+}
+
+void InterleavedAttributeDataBenchmark::drawBenchmark()
+{
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    for (size_t k = 0; k < 20; k++)
+    {
+        for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
+        {
+            // Firstly get the attribute locations for the program
+            glUseProgram(mPointSpriteProgram);
+            GLint positionLocation = glGetAttribLocation(mPointSpriteProgram, "aPosition");
+            ASSERT_NE(positionLocation, -1);
+            GLint colorLocation = glGetAttribLocation(mPointSpriteProgram, "aColor");
+            ASSERT_NE(colorLocation, -1);
+
+            // Bind the position data from one buffer
+            glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
+            glEnableVertexAttribArray(positionLocation);
+            glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE,
+                                  static_cast<GLsizei>(mBytesPerSprite), 0);
+
+            // But bind the color data from the other buffer.
+            glBindBuffer(GL_ARRAY_BUFFER,
+                         mPositionColorBuffer[(i + 1) % ArraySize(mPositionColorBuffer)]);
+            glEnableVertexAttribArray(colorLocation);
+            glVertexAttribPointer(colorLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE,
+                                  static_cast<GLsizei>(mBytesPerSprite),
+                                  reinterpret_cast<void *>(2 * sizeof(float)));
+
+            // Then draw the colored pointsprites
+            glDrawArrays(GL_POINTS, 0, GetParam().numSprites);
+            glFlush();
+
+            glDisableVertexAttribArray(positionLocation);
+            glDisableVertexAttribArray(colorLocation);
+        }
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+TEST_P(InterleavedAttributeDataBenchmark, Run)
+{
+    run();
+}
+
+InterleavedAttributeDataParams D3D11Params()
+{
+    InterleavedAttributeDataParams params;
+    params.eglParameters = egl_platform::D3D11();
+    return params;
+}
+
+InterleavedAttributeDataParams D3D11_9_3Params()
+{
+    InterleavedAttributeDataParams params;
+    params.eglParameters = egl_platform::D3D11_FL9_3();
+    return params;
+}
+
+InterleavedAttributeDataParams D3D9Params()
+{
+    InterleavedAttributeDataParams params;
+    params.eglParameters = egl_platform::D3D9();
+    return params;
+}
+
+InterleavedAttributeDataParams OpenGLParams()
+{
+    InterleavedAttributeDataParams params;
+    params.eglParameters = egl_platform::OPENGL();
+    return params;
+}
+
+ANGLE_INSTANTIATE_TEST(InterleavedAttributeDataBenchmark,
+                       D3D11Params(),
+                       D3D11_9_3Params(),
+                       D3D9Params(),
+                       OpenGLParams());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/LinkProgramPerfTest.cpp b/src/third_party/angle/src/tests/perf_tests/LinkProgramPerfTest.cpp
new file mode 100644
index 0000000..5a6ebcc
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/LinkProgramPerfTest.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright (c) 2016 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.
+//
+// LinkProgramPerfTest:
+//   Performance tests compiling a lot of shaders.
+//
+
+#include "ANGLEPerfTest.h"
+
+#include <array>
+
+#include "common/vector_utils.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct LinkProgramParams final : public RenderTestParams
+{
+    LinkProgramParams()
+    {
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth  = 256;
+        windowHeight = 256;
+    }
+
+    std::string suffix() const override
+    {
+        std::stringstream strstr;
+        strstr << RenderTestParams::suffix();
+
+        if (eglParameters.deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
+        {
+            strstr << "_null";
+        }
+
+        return strstr.str();
+    }
+};
+
+std::ostream &operator<<(std::ostream &os, const LinkProgramParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+class LinkProgramBenchmark : public ANGLERenderTest,
+                             public ::testing::WithParamInterface<LinkProgramParams>
+{
+  public:
+    LinkProgramBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  protected:
+    GLuint mVertexBuffer = 0;
+};
+
+LinkProgramBenchmark::LinkProgramBenchmark() : ANGLERenderTest("LinkProgram", GetParam())
+{
+}
+
+void LinkProgramBenchmark::initializeBenchmark()
+{
+    std::array<Vector3, 6> vertices = {{Vector3(-1.0f, 1.0f, 0.5f), Vector3(-1.0f, -1.0f, 0.5f),
+                                        Vector3(1.0f, -1.0f, 0.5f), Vector3(-1.0f, 1.0f, 0.5f),
+                                        Vector3(1.0f, -1.0f, 0.5f), Vector3(1.0f, 1.0f, 0.5f)}};
+
+    glGenBuffers(1, &mVertexBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vector3), vertices.data(),
+                 GL_STATIC_DRAW);
+};
+
+void LinkProgramBenchmark::destroyBenchmark()
+{
+    glDeleteBuffers(1, &mVertexBuffer);
+}
+
+void LinkProgramBenchmark::drawBenchmark()
+{
+    static const char *vertexShader =
+        "attribute vec2 position;\n"
+        "void main() {\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "}";
+    static const char *fragmentShader =
+        "precision mediump float;\n"
+        "void main() {\n"
+        "    gl_FragColor = vec4(1, 0, 0, 1);\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShader, fragmentShader);
+    ASSERT_NE(0u, program);
+
+    glUseProgram(program);
+
+    GLint positionLoc = glGetAttribLocation(program, "position");
+    glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 8, nullptr);
+    glEnableVertexAttribArray(positionLoc);
+
+    // Draw with the program to ensure the shader gets compiled and used.
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+
+    glDeleteProgram(program);
+}
+
+using namespace egl_platform;
+
+LinkProgramParams LinkProgramD3D11Params()
+{
+    LinkProgramParams params;
+    params.eglParameters = D3D11();
+    return params;
+}
+
+LinkProgramParams LinkProgramD3D9Params()
+{
+    LinkProgramParams params;
+    params.eglParameters = D3D9();
+    return params;
+}
+
+LinkProgramParams LinkProgramOpenGLParams()
+{
+    LinkProgramParams params;
+    params.eglParameters = OPENGL();
+    return params;
+}
+
+TEST_P(LinkProgramBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(LinkProgramBenchmark,
+                       LinkProgramD3D11Params(),
+                       LinkProgramD3D9Params(),
+                       LinkProgramOpenGLParams());
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/tests/perf_tests/PointSprites.cpp b/src/third_party/angle/src/tests/perf_tests/PointSprites.cpp
new file mode 100644
index 0000000..b0b2310
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/PointSprites.cpp
@@ -0,0 +1,230 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PointSpritesBenchmark:
+//   Performance test for ANGLE point sprites.
+//
+//
+#include "ANGLEPerfTest.h"
+
+#include <iostream>
+#include <sstream>
+
+#include "shader_utils.h"
+#include "random_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct PointSpritesParams final : public RenderTestParams
+{
+    PointSpritesParams()
+    {
+        // Common default params
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth = 1280;
+        windowHeight = 720;
+        iterations   = 100;
+        count = 10;
+        size = 3.0f;
+        numVaryings = 3;
+    }
+
+    std::string suffix() const override;
+
+    unsigned int count;
+    float size;
+    unsigned int numVaryings;
+
+    // static parameters
+    unsigned int iterations;
+};
+
+std::ostream &operator<<(std::ostream &os, const PointSpritesParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+class PointSpritesBenchmark : public ANGLERenderTest,
+                              public ::testing::WithParamInterface<PointSpritesParams>
+{
+  public:
+    PointSpritesBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    GLuint mProgram;
+    GLuint mBuffer;
+    RNG mRNG;
+};
+
+std::string PointSpritesParams::suffix() const
+{
+    std::stringstream strstr;
+
+    strstr << RenderTestParams::suffix()
+           << "_" << count << "_" << size << "px"
+           << "_" << numVaryings << "vars";
+
+    return strstr.str();
+}
+
+PointSpritesBenchmark::PointSpritesBenchmark()
+    : ANGLERenderTest("PointSprites", GetParam()), mRNG(1)
+{
+}
+
+void PointSpritesBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    ASSERT_LT(0u, params.iterations);
+
+    std::stringstream vstrstr;
+
+    // Verify "numVaryings" is within MAX_VARYINGS limit
+    GLint maxVaryings;
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
+
+    if (params.numVaryings > static_cast<unsigned int>(maxVaryings))
+    {
+        FAIL() << "Varying count (" << params.numVaryings << ")"
+               << " exceeds maximum varyings: " << maxVaryings << std::endl;
+    }
+
+    vstrstr << "attribute vec2 vPosition;\n"
+               "uniform float uPointSize;\n";
+
+    for (unsigned int varCount = 0; varCount < params.numVaryings; varCount++)
+    {
+        vstrstr << "varying vec4 v" << varCount << ";\n";
+    }
+
+    vstrstr << "void main()\n"
+               "{\n";
+
+    for (unsigned int varCount = 0; varCount < params.numVaryings; varCount++)
+    {
+        vstrstr << "    v" << varCount << " = vec4(1.0);\n";
+    }
+
+    vstrstr << "    gl_Position = vec4(vPosition, 0, 1.0);\n"
+               "    gl_PointSize = uPointSize;\n"
+               "}";
+
+    std::stringstream fstrstr;
+
+    fstrstr << "precision mediump float;\n";
+
+    for (unsigned int varCount = 0; varCount < params.numVaryings; varCount++)
+    {
+        fstrstr << "varying vec4 v" << varCount << ";\n";
+    }
+
+    fstrstr << "void main()\n"
+               "{\n"
+               "    vec4 colorOut = vec4(1.0, 0.0, 0.0, 1.0);\n";
+
+    for (unsigned int varCount = 0; varCount < params.numVaryings; varCount++)
+    {
+        fstrstr << "    colorOut.r += v" << varCount << ".r;\n";
+    }
+
+    fstrstr << "    gl_FragColor = colorOut;\n"
+               "}\n";
+
+    mProgram = CompileProgram(vstrstr.str(), fstrstr.str());
+    ASSERT_NE(0u, mProgram);
+
+    // Use the program object
+    glUseProgram(mProgram);
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    std::vector<float> vertexPositions(params.count * 2);
+    for (size_t pointIndex = 0; pointIndex < vertexPositions.size(); ++pointIndex)
+    {
+        vertexPositions[pointIndex] = mRNG.randomNegativeOneToOne();
+    }
+
+    glGenBuffers(1, &mBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    glBufferData(GL_ARRAY_BUFFER, vertexPositions.size() * sizeof(float), &vertexPositions[0], GL_STATIC_DRAW);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "vPosition");
+    ASSERT_NE(-1, positionLocation);
+
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+
+    // Set the viewport
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    GLint pointSizeLocation = glGetUniformLocation(mProgram, "uPointSize");
+    ASSERT_NE(-1, pointSizeLocation);
+
+    glUniform1f(pointSizeLocation, params.size);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void PointSpritesBenchmark::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+    glDeleteBuffers(1, &mBuffer);
+}
+
+void PointSpritesBenchmark::drawBenchmark()
+{
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    const auto &params = GetParam();
+
+    for (unsigned int it = 0; it < params.iterations; it++)
+    {
+        //TODO(jmadill): Indexed point rendering. ANGLE is bad at this.
+        glDrawArrays(GL_POINTS, 0, params.count);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+PointSpritesParams D3D11Params()
+{
+    PointSpritesParams params;
+    params.eglParameters = egl_platform::D3D11();
+    return params;
+}
+
+PointSpritesParams D3D9Params()
+{
+    PointSpritesParams params;
+    params.eglParameters = egl_platform::D3D9();
+    return params;
+}
+
+PointSpritesParams OpenGLParams()
+{
+    PointSpritesParams params;
+    params.eglParameters = egl_platform::OPENGL();
+    return params;
+}
+
+} // namespace
+
+TEST_P(PointSpritesBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(PointSpritesBenchmark,
+                       D3D11Params(), D3D9Params(), OpenGLParams());
diff --git a/src/third_party/angle/src/tests/perf_tests/TexSubImage.cpp b/src/third_party/angle/src/tests/perf_tests/TexSubImage.cpp
new file mode 100644
index 0000000..b66aab4
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/TexSubImage.cpp
@@ -0,0 +1,282 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TexSubImageBenchmark:
+//   Performace test for ANGLE texture updates.
+//
+
+#include <sstream>
+
+#include "ANGLEPerfTest.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct TexSubImageParams final : public RenderTestParams
+{
+    TexSubImageParams()
+    {
+        // Common default parameters
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth  = 512;
+        windowHeight = 512;
+
+        imageWidth     = 1024;
+        imageHeight    = 1024;
+        subImageWidth  = 64;
+        subImageHeight = 64;
+        iterations     = 9;
+    }
+
+    std::string suffix() const override;
+
+    // Static parameters
+    int imageWidth;
+    int imageHeight;
+    int subImageWidth;
+    int subImageHeight;
+    unsigned int iterations;
+};
+
+std::ostream &operator<<(std::ostream &os, const TexSubImageParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+class TexSubImageBenchmark : public ANGLERenderTest,
+                             public ::testing::WithParamInterface<TexSubImageParams>
+{
+  public:
+    TexSubImageBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    GLuint createTexture();
+
+    // Handle to a program object
+    GLuint mProgram;
+
+    // Attribute locations
+    GLint mPositionLoc;
+    GLint mTexCoordLoc;
+
+    // Sampler location
+    GLint mSamplerLoc;
+
+    // Texture handle
+    GLuint mTexture;
+
+    // Buffer handle
+    GLuint mVertexBuffer;
+    GLuint mIndexBuffer;
+
+    GLubyte *mPixels;
+};
+
+std::string TexSubImageParams::suffix() const
+{
+    // TODO(jmadill)
+    return RenderTestParams::suffix();
+}
+
+TexSubImageBenchmark::TexSubImageBenchmark()
+    : ANGLERenderTest("TexSubImage", GetParam()),
+      mProgram(0),
+      mPositionLoc(-1),
+      mTexCoordLoc(-1),
+      mSamplerLoc(-1),
+      mTexture(0),
+      mVertexBuffer(0),
+      mIndexBuffer(0),
+      mPixels(nullptr)
+{
+}
+
+GLuint TexSubImageBenchmark::createTexture()
+{
+    const auto &params = GetParam();
+
+    assert(params.iterations > 0);
+
+    // Use tightly packed data
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+    // Generate a texture object
+    GLuint texture;
+    glGenTextures(1, &texture);
+
+    // Bind the texture object
+    glBindTexture(GL_TEXTURE_2D, texture);
+
+    glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.imageWidth, params.imageHeight);
+
+    // Set the filtering mode
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    return texture;
+}
+
+void TexSubImageBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    const std::string vs = SHADER_SOURCE(attribute vec4 a_position; attribute vec2 a_texCoord;
+                                         varying vec2 v_texCoord; void main() {
+                                             gl_Position = a_position;
+                                             v_texCoord  = a_texCoord;
+                                         });
+
+    const std::string fs =
+        SHADER_SOURCE(precision mediump float; varying vec2 v_texCoord; uniform sampler2D s_texture;
+                      void main() { gl_FragColor = texture2D(s_texture, v_texCoord); });
+
+    mProgram = CompileProgram(vs, fs);
+    ASSERT_NE(0u, mProgram);
+
+    // Get the attribute locations
+    mPositionLoc = glGetAttribLocation(mProgram, "a_position");
+    mTexCoordLoc = glGetAttribLocation(mProgram, "a_texCoord");
+
+    // Get the sampler location
+    mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
+
+    // Build the vertex buffer
+    GLfloat vertices[] = {
+        -0.5f, 0.5f,  0.0f,  // Position 0
+        0.0f,  0.0f,         // TexCoord 0
+        -0.5f, -0.5f, 0.0f,  // Position 1
+        0.0f,  1.0f,         // TexCoord 1
+        0.5f,  -0.5f, 0.0f,  // Position 2
+        1.0f,  1.0f,         // TexCoord 2
+        0.5f,  0.5f,  0.0f,  // Position 3
+        1.0f,  0.0f          // TexCoord 3
+    };
+
+    glGenBuffers(1, &mVertexBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+    GLushort indices[] = {0, 1, 2, 0, 2, 3};
+    glGenBuffers(1, &mIndexBuffer);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+
+    // Load the texture
+    mTexture = createTexture();
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    mPixels = new GLubyte[params.subImageWidth * params.subImageHeight * 4];
+
+    // Fill the pixels structure with random data:
+    for (int y = 0; y < params.subImageHeight; ++y)
+    {
+        for (int x = 0; x < params.subImageWidth; ++x)
+        {
+            int offset          = (x + (y * params.subImageWidth)) * 4;
+            mPixels[offset + 0] = rand() % 255;  // Red
+            mPixels[offset + 1] = rand() % 255;  // Green
+            mPixels[offset + 2] = rand() % 255;  // Blue
+            mPixels[offset + 3] = 255;           // Alpha
+        }
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void TexSubImageBenchmark::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+    glDeleteBuffers(1, &mVertexBuffer);
+    glDeleteBuffers(1, &mIndexBuffer);
+    glDeleteTextures(1, &mTexture);
+    delete[] mPixels;
+}
+
+void TexSubImageBenchmark::drawBenchmark()
+{
+    // Set the viewport
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    // Clear the color buffer
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // Use the program object
+    glUseProgram(mProgram);
+
+    // Bind the buffers
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+
+    // Load the vertex position
+    glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
+    // Load the texture coordinate
+    glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat),
+                          reinterpret_cast<void *>(3 * sizeof(GLfloat)));
+
+    glEnableVertexAttribArray(mPositionLoc);
+    glEnableVertexAttribArray(mTexCoordLoc);
+
+    // Bind the texture
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+
+    // Set the texture sampler to texture unit to 0
+    glUniform1i(mSamplerLoc, 0);
+
+    ASSERT_GL_NO_ERROR();
+
+    const auto &params = GetParam();
+
+    for (unsigned int iteration = 0; iteration < params.iterations; ++iteration)
+    {
+        glTexSubImage2D(GL_TEXTURE_2D, 0, rand() % (params.imageWidth - params.subImageWidth),
+                        rand() % (params.imageHeight - params.subImageHeight), params.subImageWidth,
+                        params.subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, mPixels);
+
+        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+TexSubImageParams D3D11Params()
+{
+    TexSubImageParams params;
+    params.eglParameters = egl_platform::D3D11();
+    return params;
+}
+
+TexSubImageParams D3D9Params()
+{
+    TexSubImageParams params;
+    params.eglParameters = egl_platform::D3D9();
+    return params;
+}
+
+TexSubImageParams OpenGLParams()
+{
+    TexSubImageParams params;
+    params.eglParameters = egl_platform::OPENGL();
+    return params;
+}
+
+}  // namespace
+
+TEST_P(TexSubImageBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(TexSubImageBenchmark, D3D11Params(), D3D9Params(), OpenGLParams());
diff --git a/src/third_party/angle/src/tests/perf_tests/TextureSampling.cpp b/src/third_party/angle/src/tests/perf_tests/TextureSampling.cpp
new file mode 100644
index 0000000..bc00acd
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/TextureSampling.cpp
@@ -0,0 +1,288 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TextureSamplingBenchmark:
+//   Performance test for texture sampling. The test generates a texture containing random data
+//   and then blurs it in a fragment shader using nearest neighbor sampling. The test is
+//   specifically designed to test overhead of GLSL's builtin texture*() functions that may result
+//   from how ANGLE translates them on each backend.
+//
+
+#include "ANGLEPerfTest.h"
+
+#include <iostream>
+#include <random>
+#include <sstream>
+
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct TextureSamplingParams final : public RenderTestParams
+{
+    TextureSamplingParams()
+    {
+        // Common default params
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth  = 720;
+        windowHeight = 720;
+        iterations   = 4;
+
+        numSamplers = 2;
+        textureSize = 32;
+        kernelSize  = 3;
+    }
+
+    std::string suffix() const override;
+    unsigned int numSamplers;
+    unsigned int textureSize;
+    unsigned int kernelSize;
+
+    // static parameters
+    unsigned int iterations;
+};
+
+std::ostream &operator<<(std::ostream &os, const TextureSamplingParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+std::string TextureSamplingParams::suffix() const
+{
+    std::stringstream strstr;
+
+    strstr << RenderTestParams::suffix() << "_" << numSamplers << "samplers";
+
+    return strstr.str();
+}
+
+class TextureSamplingBenchmark : public ANGLERenderTest,
+                                 public ::testing::WithParamInterface<TextureSamplingParams>
+{
+  public:
+    TextureSamplingBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    void initShaders();
+    void initVertexBuffer();
+    void initTextures();
+
+    GLuint mProgram;
+    GLuint mBuffer;
+    std::vector<GLuint> mTextures;
+};
+
+TextureSamplingBenchmark::TextureSamplingBenchmark()
+    : ANGLERenderTest("TextureSampling", GetParam()), mProgram(0u), mBuffer(0u)
+{
+}
+
+void TextureSamplingBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    ASSERT_LT(0u, params.iterations);
+
+    // Verify "numSamplers" is within MAX_TEXTURE_IMAGE_UNITS limit
+    GLint maxTextureImageUnits;
+    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
+
+    if (params.numSamplers > static_cast<unsigned int>(maxTextureImageUnits))
+    {
+        FAIL() << "Sampler count (" << params.numSamplers << ")"
+               << " exceeds maximum texture count: " << maxTextureImageUnits << std::endl;
+    }
+    initShaders();
+    initVertexBuffer();
+    initTextures();
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    ASSERT_GL_NO_ERROR();
+}
+
+void TextureSamplingBenchmark::initShaders()
+{
+    const auto &params = GetParam();
+
+    std::stringstream vstrstr;
+    vstrstr << "attribute vec2 aPosition;\n"
+               "varying vec2 vTextureCoordinates;\n"
+               "void main()\n"
+               "{\n"
+               "    vTextureCoordinates = (aPosition + vec2(1.0)) * 0.5;\n"
+               "    gl_Position = vec4(aPosition, 0, 1.0);\n"
+               "}";
+
+    std::stringstream fstrstr;
+    fstrstr << "precision mediump float;\n"
+               "varying vec2 vTextureCoordinates;\n";
+    for (unsigned int count = 0; count < params.numSamplers; count++)
+    {
+        fstrstr << "uniform sampler2D uSampler" << count << ";\n";
+    }
+    fstrstr << "void main()\n"
+               "{\n"
+               "    const float inverseTextureSize = 1.0 / "
+            << params.textureSize << ".0;\n"
+                                     "    vec4 colorOut = vec4(0.0, 0.0, 0.0, 1.0);\n";
+    for (unsigned int count = 0; count < params.numSamplers; count++)
+    {
+        fstrstr << "    for (int x = 0; x < " << params.kernelSize << "; ++x)\n"
+                   "    {\n"
+                   "        for (int y = 0; y < " << params.kernelSize << "; ++y)\n"
+                   "        {\n"
+                   "            colorOut += texture2D(uSampler" << count
+                   << ", vTextureCoordinates + vec2(x, y) * inverseTextureSize) * 0.1;\n"
+                   "        }\n"
+                   "    }\n";
+    }
+    fstrstr << "    gl_FragColor = colorOut;\n"
+               "}\n";
+
+    mProgram = CompileProgram(vstrstr.str(), fstrstr.str());
+    ASSERT_NE(0u, mProgram);
+
+    // Use the program object
+    glUseProgram(mProgram);
+}
+
+void TextureSamplingBenchmark::initVertexBuffer()
+{
+    std::vector<float> vertexPositions(12);
+    {
+        // Bottom left triangle
+        vertexPositions[0] = -1.0f;
+        vertexPositions[1] = -1.0f;
+        vertexPositions[2] = 1.0f;
+        vertexPositions[3] = -1.0f;
+        vertexPositions[4] = -1.0f;
+        vertexPositions[5] = 1.0f;
+
+        // Top right triangle
+        vertexPositions[6]  = -1.0f;
+        vertexPositions[7]  = 1.0f;
+        vertexPositions[8]  = 1.0f;
+        vertexPositions[9]  = -1.0f;
+        vertexPositions[10] = 1.0f;
+        vertexPositions[11] = 1.0f;
+    }
+
+    glGenBuffers(1, &mBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    glBufferData(GL_ARRAY_BUFFER, vertexPositions.size() * sizeof(float), &vertexPositions[0],
+                 GL_STATIC_DRAW);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");
+    ASSERT_NE(-1, positionLocation);
+
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+}
+
+void TextureSamplingBenchmark::initTextures()
+{
+    const auto &params = GetParam();
+
+    unsigned int dataSize = params.textureSize * params.textureSize;
+    std::vector<unsigned int> randomTextureData;
+    randomTextureData.resize(dataSize);
+
+    unsigned int pseudoRandom = 1u;
+    for (unsigned int i = 0; i < dataSize; ++i)
+    {
+        pseudoRandom         = pseudoRandom * 1664525u + 1013904223u;
+        randomTextureData[i] = pseudoRandom;
+    }
+
+    mTextures.resize(params.numSamplers);
+    glGenTextures(params.numSamplers, mTextures.data());
+    for (unsigned int i = 0; i < params.numSamplers; ++i)
+    {
+        glActiveTexture(GL_TEXTURE0 + i);
+        glBindTexture(GL_TEXTURE_2D, mTextures[i]);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, params.textureSize, params.textureSize, 0, GL_RGBA,
+                     GL_UNSIGNED_BYTE, randomTextureData.data());
+    }
+
+    for (unsigned int count = 0; count < params.numSamplers; count++)
+    {
+        std::stringstream samplerstrstr;
+        samplerstrstr << "uSampler" << count;
+        GLint samplerLocation = glGetUniformLocation(mProgram, samplerstrstr.str().c_str());
+        ASSERT_NE(-1, samplerLocation);
+
+        glUniform1i(samplerLocation, count);
+    }
+}
+
+void TextureSamplingBenchmark::destroyBenchmark()
+{
+    const auto &params = GetParam();
+
+    glDeleteProgram(mProgram);
+    glDeleteBuffers(1, &mBuffer);
+    if (!mTextures.empty())
+    {
+        glDeleteTextures(params.numSamplers, mTextures.data());
+    }
+}
+
+void TextureSamplingBenchmark::drawBenchmark()
+{
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    const auto &params = GetParam();
+
+    for (unsigned int it = 0; it < params.iterations; ++it)
+    {
+        glDrawArrays(GL_TRIANGLES, 0, 6);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+TextureSamplingParams D3D11Params()
+{
+    TextureSamplingParams params;
+    params.eglParameters = egl_platform::D3D11();
+    return params;
+}
+
+TextureSamplingParams D3D9Params()
+{
+    TextureSamplingParams params;
+    params.eglParameters = egl_platform::D3D9();
+    return params;
+}
+
+TextureSamplingParams OpenGLParams()
+{
+    TextureSamplingParams params;
+    params.eglParameters = egl_platform::OPENGL();
+    return params;
+}
+
+}  // anonymous namespace
+
+TEST_P(TextureSamplingBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(TextureSamplingBenchmark, D3D11Params(), D3D9Params(), OpenGLParams());
diff --git a/src/third_party/angle/src/tests/perf_tests/TexturesPerf.cpp b/src/third_party/angle/src/tests/perf_tests/TexturesPerf.cpp
new file mode 100644
index 0000000..58e1a9b
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/TexturesPerf.cpp
@@ -0,0 +1,293 @@
+//
+// Copyright (c) 2016 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.
+//
+// TexturesPerf:
+//   Performance test for setting texture state.
+//
+
+#include "ANGLEPerfTest.h"
+
+#include <iostream>
+#include <random>
+#include <sstream>
+
+#include "shader_utils.h"
+
+namespace angle
+{
+
+struct TexturesParams final : public RenderTestParams
+{
+    TexturesParams()
+    {
+        // Common default params
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth  = 720;
+        windowHeight = 720;
+        iterations   = 256;
+
+        numTextures                 = 8;
+        textureRebindFrequency      = 5;
+        textureStateUpdateFrequency = 3;
+        textureMipCount             = 8;
+    }
+
+    std::string suffix() const override;
+    size_t numTextures;
+    size_t textureRebindFrequency;
+    size_t textureStateUpdateFrequency;
+    size_t textureMipCount;
+
+    // static parameters
+    size_t iterations;
+};
+
+std::ostream &operator<<(std::ostream &os, const TexturesParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+std::string TexturesParams::suffix() const
+{
+    std::stringstream strstr;
+
+    strstr << RenderTestParams::suffix();
+    strstr << "_" << numTextures << "_textures";
+    strstr << "_" << textureRebindFrequency << "_rebind";
+    strstr << "_" << textureStateUpdateFrequency << "_state";
+    strstr << "_" << textureMipCount << "_mips";
+
+    return strstr.str();
+}
+
+class TexturesBenchmark : public ANGLERenderTest,
+                          public ::testing::WithParamInterface<TexturesParams>
+{
+  public:
+    TexturesBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    void initShaders();
+    void initTextures();
+
+    std::vector<GLuint> mTextures;
+
+    GLuint mProgram;
+    std::vector<GLuint> mUniformLocations;
+};
+
+TexturesBenchmark::TexturesBenchmark() : ANGLERenderTest("Textures", GetParam()), mProgram(0u)
+{
+}
+
+void TexturesBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    ASSERT_GT(params.iterations, 0u);
+
+    // Verify the uniform counts are within the limits
+    GLint maxTextureUnits;
+    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+    if (params.numTextures > static_cast<size_t>(maxTextureUnits))
+    {
+        FAIL() << "Texture count (" << params.numTextures << ")"
+               << " exceeds maximum texture unit count: " << maxTextureUnits << std::endl;
+    }
+
+    initShaders();
+    initTextures();
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    ASSERT_GL_NO_ERROR();
+}
+
+std::string GetUniformLocationName(size_t idx, bool vertexShader)
+{
+    std::stringstream strstr;
+    strstr << (vertexShader ? "vs" : "fs") << "_u_" << idx;
+    return strstr.str();
+}
+
+void TexturesBenchmark::initShaders()
+{
+    const auto &params = GetParam();
+
+    std::string vs =
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0, 0, 0, 0);\n"
+        "}\n";
+
+    std::stringstream fstrstr;
+    for (size_t i = 0; i < params.numTextures; i++)
+    {
+        fstrstr << "uniform sampler2D tex" << i << ";";
+    }
+    fstrstr << "void main()\n"
+               "{\n"
+               "    gl_FragColor = vec4(0, 0, 0, 0)";
+    for (size_t i = 0; i < params.numTextures; i++)
+    {
+        fstrstr << "+ texture2D(tex" << i << ", vec2(0, 0))";
+    }
+    fstrstr << ";\n"
+               "}\n";
+
+    mProgram = CompileProgram(vs, fstrstr.str());
+    ASSERT_NE(0u, mProgram);
+
+    for (size_t i = 0; i < params.numTextures; ++i)
+    {
+        std::stringstream uniformName;
+        uniformName << "tex" << i;
+
+        GLint location = glGetUniformLocation(mProgram, uniformName.str().c_str());
+        ASSERT_NE(-1, location);
+        mUniformLocations.push_back(location);
+    }
+
+    // Use the program object
+    glUseProgram(mProgram);
+}
+
+void TexturesBenchmark::initTextures()
+{
+    const auto &params = GetParam();
+
+    size_t textureSize = static_cast<size_t>(1) << params.textureMipCount;
+    std::vector<GLubyte> textureData(textureSize * textureSize * 4);
+    for (auto &byte : textureData)
+    {
+        byte = rand() % 255u;
+    }
+
+    for (size_t texIndex = 0; texIndex < params.numTextures; texIndex++)
+    {
+        GLuint tex = 0;
+        glGenTextures(1, &tex);
+
+        glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + texIndex));
+        glBindTexture(GL_TEXTURE_2D, tex);
+        for (size_t mip = 0; mip < params.textureMipCount; mip++)
+        {
+            GLsizei levelSize = static_cast<GLsizei>(textureSize >> mip);
+            glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(mip), GL_RGBA, levelSize, levelSize, 0,
+                         GL_RGBA, GL_UNSIGNED_BYTE, textureData.data());
+        }
+        mTextures.push_back(tex);
+
+        glUniform1i(mUniformLocations[texIndex], static_cast<GLint>(texIndex));
+    }
+}
+
+void TexturesBenchmark::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+}
+
+void TexturesBenchmark::drawBenchmark()
+{
+    const auto &params = GetParam();
+
+    for (size_t it = 0; it < params.iterations; ++it)
+    {
+        if (it % params.textureRebindFrequency == 0)
+        {
+            // Swap two textures
+            size_t swapTexture = (it / params.textureRebindFrequency) % (params.numTextures - 1);
+
+            glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + swapTexture));
+            glBindTexture(GL_TEXTURE_2D, mTextures[swapTexture]);
+            glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + swapTexture + 1));
+            glBindTexture(GL_TEXTURE_2D, mTextures[swapTexture + 1]);
+            std::swap(mTextures[swapTexture], mTextures[swapTexture + 1]);
+        }
+
+        if (it % params.textureStateUpdateFrequency == 0)
+        {
+            // Update a texture's state
+            size_t stateUpdateCount = it / params.textureStateUpdateFrequency;
+
+            const size_t numUpdateTextures = 4;
+            ASSERT_LE(numUpdateTextures, params.numTextures);
+
+            size_t firstTexture = stateUpdateCount % (params.numTextures - numUpdateTextures);
+
+            for (size_t updateTextureIdx = 0; updateTextureIdx < numUpdateTextures;
+                 updateTextureIdx++)
+            {
+                size_t updateTexture = firstTexture + updateTextureIdx;
+                glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + updateTexture));
+
+                const GLenum minFilters[] = {
+                    GL_NEAREST,
+                    GL_LINEAR,
+                    GL_NEAREST_MIPMAP_NEAREST,
+                    GL_LINEAR_MIPMAP_NEAREST,
+                    GL_NEAREST_MIPMAP_LINEAR,
+                    GL_LINEAR_MIPMAP_LINEAR,
+                };
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+                                minFilters[stateUpdateCount % ArraySize(minFilters)]);
+
+                const GLenum magFilters[] = {
+                    GL_NEAREST, GL_LINEAR,
+                };
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+                                magFilters[stateUpdateCount % ArraySize(magFilters)]);
+
+                const GLenum wrapParameters[] = {
+                    GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT,
+                };
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
+                                wrapParameters[stateUpdateCount % ArraySize(wrapParameters)]);
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
+                                wrapParameters[stateUpdateCount % ArraySize(wrapParameters)]);
+            }
+        }
+
+        glDrawArrays(GL_TRIANGLES, 0, 3);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+TexturesParams D3D11Params()
+{
+    TexturesParams params;
+    params.eglParameters = egl_platform::D3D11_NULL();
+    return params;
+}
+
+TexturesParams D3D9Params()
+{
+    TexturesParams params;
+    params.eglParameters = egl_platform::D3D9_NULL();
+    return params;
+}
+
+TexturesParams OpenGLParams()
+{
+    TexturesParams params;
+    params.eglParameters = egl_platform::OPENGL_NULL();
+    return params;
+}
+
+TEST_P(TexturesBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(TexturesBenchmark, D3D11Params(), D3D9Params(), OpenGLParams());
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/perf_tests/UniformsPerf.cpp b/src/third_party/angle/src/tests/perf_tests/UniformsPerf.cpp
new file mode 100644
index 0000000..dc4d23e
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/UniformsPerf.cpp
@@ -0,0 +1,353 @@
+//
+// Copyright (c) 2016 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.
+//
+// UniformsBenchmark:
+//   Performance test for setting uniform data.
+//
+
+#include "ANGLEPerfTest.h"
+
+#include <iostream>
+#include <random>
+#include <sstream>
+
+#include "Matrix.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+// Controls when we call glUniform, if the data is the same as last frame.
+enum DataMode
+{
+    UPDATE,
+    REPEAT,
+};
+
+// TODO(jmadill): Use an ANGLE enum for this?
+enum DataType
+{
+    VEC4,
+    MAT4,
+};
+
+struct UniformsParams final : public RenderTestParams
+{
+    UniformsParams()
+    {
+        // Common default params
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth  = 720;
+        windowHeight = 720;
+    }
+
+    std::string suffix() const override;
+    size_t numVertexUniforms   = 200;
+    size_t numFragmentUniforms = 200;
+
+    DataType dataType = DataType::VEC4;
+    DataMode dataMode = DataMode::REPEAT;
+
+    // static parameters
+    size_t iterations = 4;
+};
+
+std::ostream &operator<<(std::ostream &os, const UniformsParams &params)
+{
+    os << params.suffix().substr(1);
+    return os;
+}
+
+std::string UniformsParams::suffix() const
+{
+    std::stringstream strstr;
+
+    strstr << RenderTestParams::suffix();
+
+    if (dataType == DataType::VEC4)
+    {
+        strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_vec4";
+    }
+    else
+    {
+        ASSERT(dataType == DataType::MAT4);
+        strstr << "_matrix";
+    }
+
+    if (dataMode == DataMode::REPEAT)
+    {
+        strstr << "_repeating";
+    }
+
+    return strstr.str();
+}
+
+class UniformsBenchmark : public ANGLERenderTest,
+                          public ::testing::WithParamInterface<UniformsParams>
+{
+  public:
+    UniformsBenchmark();
+
+    void initializeBenchmark() override;
+    void destroyBenchmark() override;
+    void drawBenchmark() override;
+
+  private:
+    void initShaders();
+
+    GLuint mProgram;
+    std::vector<GLuint> mUniformLocations;
+    std::vector<Matrix4> mMatrixData[2];
+};
+
+std::vector<Matrix4> GenMatrixData(size_t count, int parity)
+{
+    std::vector<Matrix4> data;
+
+    // Very simple matrix data allocation scheme.
+    for (size_t index = 0; index < count; ++index)
+    {
+        Matrix4 mat;
+        for (int row = 0; row < 4; ++row)
+        {
+            for (int col = 0; col < 4; ++col)
+            {
+                mat.data[row * 4 + col] = (row * col + parity) % 2 == 0 ? 1.0f : -1.0f;
+            }
+        }
+
+        data.push_back(mat);
+    }
+
+    return data;
+}
+
+UniformsBenchmark::UniformsBenchmark() : ANGLERenderTest("Uniforms", GetParam()), mProgram(0u)
+{
+}
+
+void UniformsBenchmark::initializeBenchmark()
+{
+    const auto &params = GetParam();
+
+    ASSERT_GT(params.iterations, 0u);
+
+    // Verify the uniform counts are within the limits
+    GLint maxVertexUniformVectors, maxFragmentUniformVectors;
+    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniformVectors);
+    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniformVectors);
+
+    bool isMatrix = params.dataType == DataType::MAT4;
+
+    GLint numVertexUniformVectors =
+        static_cast<GLint>(params.numVertexUniforms) * (isMatrix ? 4 : 1);
+    GLint numFragmentUniformVectors =
+        static_cast<GLint>(params.numFragmentUniforms) * (isMatrix ? 4 : 1);
+
+    if (numVertexUniformVectors > maxVertexUniformVectors)
+    {
+        FAIL() << "Vertex uniform vector count (" << numVertexUniformVectors << ")"
+               << " exceeds maximum vertex uniform vector count: " << maxVertexUniformVectors
+               << std::endl;
+    }
+    if (numFragmentUniformVectors > maxFragmentUniformVectors)
+    {
+        FAIL() << "Fragment uniform vector count (" << numFragmentUniformVectors << ")"
+               << " exceeds maximum fragment uniform vector count: " << maxFragmentUniformVectors
+               << std::endl;
+    }
+
+    initShaders();
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    if (isMatrix)
+    {
+        size_t count = params.numVertexUniforms + params.numFragmentUniforms;
+
+        mMatrixData[0] = GenMatrixData(count, 0);
+        if (params.dataMode == DataMode::REPEAT)
+        {
+            mMatrixData[1] = GenMatrixData(count, 0);
+        }
+        else
+        {
+            mMatrixData[1] = GenMatrixData(count, 1);
+        }
+    }
+
+    GLint attribLocation = glGetAttribLocation(mProgram, "pos");
+    ASSERT_NE(-1, attribLocation);
+    glVertexAttrib4f(attribLocation, 1.0f, 0.0f, 0.0f, 1.0f);
+
+    ASSERT_GL_NO_ERROR();
+}
+
+std::string GetUniformLocationName(size_t idx, bool vertexShader)
+{
+    std::stringstream strstr;
+    strstr << (vertexShader ? "vs" : "fs") << "_u_" << idx;
+    return strstr.str();
+}
+
+void UniformsBenchmark::initShaders()
+{
+    const auto &params = GetParam();
+    bool isMatrix      = (params.dataType == DataType::MAT4);
+
+    std::stringstream vstrstr;
+    vstrstr << "precision mediump float;\n";
+    std::string typeString  = isMatrix ? "mat4" : "vec4";
+    std::string constVector = "const vec4 one = vec4(1, 1, 1, 1);\n";
+
+    vstrstr << "attribute vec4 pos;\n";
+
+    if (isMatrix)
+    {
+        vstrstr << constVector;
+    }
+
+    for (size_t i = 0; i < params.numVertexUniforms; i++)
+    {
+        vstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, true) << ";\n";
+    }
+
+    vstrstr << "void main()\n"
+               "{\n"
+               "    gl_Position = pos;\n";
+    for (size_t i = 0; i < params.numVertexUniforms; i++)
+    {
+        vstrstr << "    gl_Position += " << GetUniformLocationName(i, true);
+        if (isMatrix)
+        {
+            vstrstr << " * one";
+        }
+        vstrstr << ";\n";
+    }
+    vstrstr << "}";
+
+    std::stringstream fstrstr;
+    fstrstr << "precision mediump float;\n";
+
+    if (isMatrix)
+    {
+        fstrstr << constVector;
+    }
+
+    for (size_t i = 0; i < params.numFragmentUniforms; i++)
+    {
+        fstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, false) << ";\n";
+    }
+    fstrstr << "void main()\n"
+               "{\n"
+               "    gl_FragColor = vec4(0, 0, 0, 0);\n";
+    for (size_t i = 0; i < params.numFragmentUniforms; i++)
+    {
+        fstrstr << "    gl_FragColor += " << GetUniformLocationName(i, false);
+        if (isMatrix)
+        {
+            fstrstr << " * one";
+        }
+        fstrstr << ";\n";
+    }
+    fstrstr << "}";
+
+    mProgram = CompileProgram(vstrstr.str(), fstrstr.str());
+    ASSERT_NE(0u, mProgram);
+
+    for (size_t i = 0; i < params.numVertexUniforms; ++i)
+    {
+        GLint location = glGetUniformLocation(mProgram, GetUniformLocationName(i, true).c_str());
+        ASSERT_NE(-1, location);
+        mUniformLocations.push_back(location);
+    }
+    for (size_t i = 0; i < params.numFragmentUniforms; ++i)
+    {
+        GLint location = glGetUniformLocation(mProgram, GetUniformLocationName(i, false).c_str());
+        ASSERT_NE(-1, location);
+        mUniformLocations.push_back(location);
+    }
+
+    // Use the program object
+    glUseProgram(mProgram);
+}
+
+void UniformsBenchmark::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+}
+
+void UniformsBenchmark::drawBenchmark()
+{
+    const auto &params = GetParam();
+
+    size_t frameIndex = 0;
+
+    for (size_t it = 0; it < params.iterations; ++it, frameIndex = (frameIndex == 0 ? 1 : 0))
+    {
+        for (size_t uniform = 0; uniform < mUniformLocations.size(); ++uniform)
+        {
+            if (params.dataType == DataType::MAT4)
+            {
+                glUniformMatrix4fv(mUniformLocations[uniform], 1, GL_FALSE,
+                                   mMatrixData[frameIndex][uniform].data);
+            }
+            else
+            {
+                float value = static_cast<float>(uniform);
+                glUniform4f(mUniformLocations[uniform], value, value, value, value);
+            }
+        }
+
+        glDrawArrays(GL_TRIANGLES, 0, 3);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+using namespace egl_platform;
+
+UniformsParams VectorUniforms(const EGLPlatformParameters &egl, DataMode dataMode)
+{
+    UniformsParams params;
+    params.eglParameters = egl;
+    params.dataMode      = dataMode;
+    return params;
+}
+
+UniformsParams MatrixUniforms(const EGLPlatformParameters &egl, DataMode dataMode)
+{
+    UniformsParams params;
+    params.eglParameters = egl;
+    params.dataType      = DataType::MAT4;
+    params.dataMode      = dataMode;
+
+    // Reduce the number of uniforms to fit within smaller upper limits on some configs.
+    params.numVertexUniforms   = 100;
+    params.numFragmentUniforms = 100;
+
+    return params;
+}
+
+}  // anonymous namespace
+
+TEST_P(UniformsBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(UniformsBenchmark,
+                       VectorUniforms(D3D9(), DataMode::UPDATE),
+                       VectorUniforms(D3D11(), DataMode::REPEAT),
+                       VectorUniforms(D3D11(), DataMode::UPDATE),
+                       VectorUniforms(OPENGL(), DataMode::REPEAT),
+                       VectorUniforms(OPENGL(), DataMode::UPDATE),
+                       MatrixUniforms(D3D11(), DataMode::REPEAT),
+                       MatrixUniforms(D3D11(), DataMode::UPDATE),
+                       MatrixUniforms(OPENGL(), DataMode::REPEAT),
+                       MatrixUniforms(OPENGL(), DataMode::UPDATE));
diff --git a/src/third_party/angle/src/tests/perf_tests/third_party/perf/angle-mods.patch b/src/third_party/angle/src/tests/perf_tests/third_party/perf/angle-mods.patch
new file mode 100644
index 0000000..d0b6402
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/third_party/perf/angle-mods.patch
@@ -0,0 +1,61 @@
+diff --git a/tests/perf_tests/third_party/perf/perf_test.cc b/tests/perf_tests/third_party/perf/perf_test.cc
+index 0d5abc0..7364330 100644
+--- a/tests/perf_tests/third_party/perf/perf_test.cc
++++ b/tests/perf_tests/third_party/perf/perf_test.cc
+@@ -2,16 +2,51 @@
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ 
+-#include "testing/perf/perf_test.h"
++#include "perf_test.h"
+ 
+ #include <stdio.h>
+-
+-#include "base/logging.h"
+-#include "base/strings/string_number_conversions.h"
+-#include "base/strings/stringprintf.h"
++#include <stdarg.h>
++#include <vector>
+ 
+ namespace {
+ 
++namespace base {
++
++std::string FormatString(const char *fmt, va_list vararg) {
++  static std::vector<char> buffer(512);
++
++  // Attempt to just print to the current buffer
++  int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg);
++  if (len < 0 || static_cast<size_t>(len) >= buffer.size()) {
++    // 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);
++}
++
++std::string StringPrintf(const char *fmt, ...) {
++  va_list vararg;
++  va_start(vararg, fmt);
++  std::string result = FormatString(fmt, vararg);
++  va_end(vararg);
++  return result;
++}
++
++std::string UintToString(unsigned int value) {
++  return StringPrintf("%u", value);
++}
++
++std::string DoubleToString(double value) {
++  return StringPrintf("%.10lf", value);
++}
++
++}
++
+ std::string ResultsToString(const std::string& measurement,
+                             const std::string& modifier,
+                             const std::string& trace,
diff --git a/src/third_party/angle/src/tests/perf_tests/third_party/perf/perf_test.cc b/src/third_party/angle/src/tests/perf_tests/third_party/perf/perf_test.cc
new file mode 100644
index 0000000..7364330
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/third_party/perf/perf_test.cc
@@ -0,0 +1,239 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "perf_test.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <vector>
+
+namespace {
+
+namespace base {
+
+std::string FormatString(const char *fmt, va_list vararg) {
+  static std::vector<char> buffer(512);
+
+  // Attempt to just print to the current buffer
+  int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg);
+  if (len < 0 || static_cast<size_t>(len) >= buffer.size()) {
+    // 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);
+}
+
+std::string StringPrintf(const char *fmt, ...) {
+  va_list vararg;
+  va_start(vararg, fmt);
+  std::string result = FormatString(fmt, vararg);
+  va_end(vararg);
+  return result;
+}
+
+std::string UintToString(unsigned int value) {
+  return StringPrintf("%u", value);
+}
+
+std::string DoubleToString(double value) {
+  return StringPrintf("%.10lf", value);
+}
+
+}
+
+std::string ResultsToString(const std::string& measurement,
+                            const std::string& modifier,
+                            const std::string& trace,
+                            const std::string& values,
+                            const std::string& prefix,
+                            const std::string& suffix,
+                            const std::string& units,
+                            bool important) {
+  // <*>RESULT <graph_name>: <trace_name>= <value> <units>
+  // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units>
+  // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units>
+  return base::StringPrintf("%sRESULT %s%s: %s= %s%s%s %s\n",
+         important ? "*" : "", measurement.c_str(), modifier.c_str(),
+         trace.c_str(), prefix.c_str(), values.c_str(), suffix.c_str(),
+         units.c_str());
+}
+
+void PrintResultsImpl(const std::string& measurement,
+                      const std::string& modifier,
+                      const std::string& trace,
+                      const std::string& values,
+                      const std::string& prefix,
+                      const std::string& suffix,
+                      const std::string& units,
+                      bool important) {
+  fflush(stdout);
+  printf("%s", ResultsToString(measurement, modifier, trace, values,
+                               prefix, suffix, units, important).c_str());
+  fflush(stdout);
+}
+
+}  // namespace
+
+namespace perf_test {
+
+void PrintResult(const std::string& measurement,
+                 const std::string& modifier,
+                 const std::string& trace,
+                 size_t value,
+                 const std::string& units,
+                 bool important) {
+  PrintResultsImpl(measurement,
+                   modifier,
+                   trace,
+                   base::UintToString(static_cast<unsigned int>(value)),
+                   std::string(),
+                   std::string(),
+                   units,
+                   important);
+}
+
+void PrintResult(const std::string& measurement,
+                 const std::string& modifier,
+                 const std::string& trace,
+                 double value,
+                 const std::string& units,
+                 bool important) {
+  PrintResultsImpl(measurement,
+                   modifier,
+                   trace,
+                   base::DoubleToString(value),
+                   std::string(),
+                   std::string(),
+                   units,
+                   important);
+}
+
+void AppendResult(std::string& output,
+                  const std::string& measurement,
+                  const std::string& modifier,
+                  const std::string& trace,
+                  size_t value,
+                  const std::string& units,
+                  bool important) {
+  output += ResultsToString(
+      measurement,
+      modifier,
+      trace,
+      base::UintToString(static_cast<unsigned int>(value)),
+      std::string(),
+      std::string(),
+      units,
+      important);
+}
+
+void PrintResult(const std::string& measurement,
+                 const std::string& modifier,
+                 const std::string& trace,
+                 const std::string& value,
+                 const std::string& units,
+                 bool important) {
+  PrintResultsImpl(measurement,
+                   modifier,
+                   trace,
+                   value,
+                   std::string(),
+                   std::string(),
+                   units,
+                   important);
+}
+
+void AppendResult(std::string& output,
+                  const std::string& measurement,
+                  const std::string& modifier,
+                  const std::string& trace,
+                  const std::string& value,
+                  const std::string& units,
+                  bool important) {
+  output += ResultsToString(measurement,
+                            modifier,
+                            trace,
+                            value,
+                            std::string(),
+                            std::string(),
+                            units,
+                            important);
+}
+
+void PrintResultMeanAndError(const std::string& measurement,
+                             const std::string& modifier,
+                             const std::string& trace,
+                             const std::string& mean_and_error,
+                             const std::string& units,
+                             bool important) {
+  PrintResultsImpl(measurement, modifier, trace, mean_and_error,
+                   "{", "}", units, important);
+}
+
+void AppendResultMeanAndError(std::string& output,
+                              const std::string& measurement,
+                              const std::string& modifier,
+                              const std::string& trace,
+                              const std::string& mean_and_error,
+                              const std::string& units,
+                              bool important) {
+  output += ResultsToString(measurement, modifier, trace, mean_and_error,
+                            "{", "}", units, important);
+}
+
+void PrintResultList(const std::string& measurement,
+                     const std::string& modifier,
+                     const std::string& trace,
+                     const std::string& values,
+                     const std::string& units,
+                     bool important) {
+  PrintResultsImpl(measurement, modifier, trace, values,
+                   "[", "]", units, important);
+}
+
+void AppendResultList(std::string& output,
+                      const std::string& measurement,
+                      const std::string& modifier,
+                      const std::string& trace,
+                      const std::string& values,
+                      const std::string& units,
+                      bool important) {
+  output += ResultsToString(measurement, modifier, trace, values,
+                            "[", "]", units, important);
+}
+
+void PrintSystemCommitCharge(const std::string& test_name,
+                             size_t charge,
+                             bool important) {
+  PrintSystemCommitCharge(stdout, test_name, charge, important);
+}
+
+void PrintSystemCommitCharge(FILE* target,
+                             const std::string& test_name,
+                             size_t charge,
+                             bool important) {
+  fprintf(target, "%s", SystemCommitChargeToString(test_name, charge,
+                                                   important).c_str());
+}
+
+std::string SystemCommitChargeToString(const std::string& test_name,
+                                       size_t charge,
+                                       bool important) {
+  std::string trace_name(test_name);
+  std::string output;
+  AppendResult(output,
+               "commit_charge",
+               std::string(),
+               "cc" + trace_name,
+               charge,
+               "kb",
+               important);
+  return output;
+}
+
+}  // namespace perf_test
diff --git a/src/third_party/angle/src/tests/perf_tests/third_party/perf/perf_test.h b/src/third_party/angle/src/tests/perf_tests/third_party/perf/perf_test.h
new file mode 100644
index 0000000..36e2916
--- /dev/null
+++ b/src/third_party/angle/src/tests/perf_tests/third_party/perf/perf_test.h
@@ -0,0 +1,116 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TESTING_PERF_PERF_TEST_H_
+#define TESTING_PERF_PERF_TEST_H_
+
+#include <string>
+
+namespace perf_test {
+
+// Prints numerical information to stdout in a controlled format, for
+// post-processing. |measurement| is a description of the quantity being
+// measured, e.g. "vm_peak"; |modifier| is provided as a convenience and
+// will be appended directly to the name of the |measurement|, e.g.
+// "_browser"; |trace| is a description of the particular data point, e.g.
+// "reference"; |value| is the measured value; and |units| is a description
+// of the units of measure, e.g. "bytes". If |important| is true, the output
+// line will be specially marked, to notify the post-processor. The strings
+// may be empty.  They should not contain any colons (:) or equals signs (=).
+// A typical post-processing step would be to produce graphs of the data
+// produced for various builds, using the combined |measurement| + |modifier|
+// string to specify a particular graph and the |trace| to identify a trace
+// (i.e., data series) on that graph.
+void PrintResult(const std::string& measurement,
+                 const std::string& modifier,
+                 const std::string& trace,
+                 size_t value,
+                 const std::string& units,
+                 bool important);
+void PrintResult(const std::string& measurement,
+                 const std::string& modifier,
+                 const std::string& trace,
+                 double value,
+                 const std::string& units,
+                 bool important);
+
+void AppendResult(std::string& output,
+                  const std::string& measurement,
+                  const std::string& modifier,
+                  const std::string& trace,
+                  size_t value,
+                  const std::string& units,
+                  bool important);
+
+// Like the above version of PrintResult(), but takes a std::string value
+// instead of a size_t.
+void PrintResult(const std::string& measurement,
+                 const std::string& modifier,
+                 const std::string& trace,
+                 const std::string& value,
+                 const std::string& units,
+                 bool important);
+
+void AppendResult(std::string& output,
+                  const std::string& measurement,
+                  const std::string& modifier,
+                  const std::string& trace,
+                  const std::string& value,
+                  const std::string& units,
+                  bool important);
+
+// Like PrintResult(), but prints a (mean, standard deviation) result pair.
+// The |<values>| should be two comma-separated numbers, the mean and
+// standard deviation (or other error metric) of the measurement.
+void PrintResultMeanAndError(const std::string& measurement,
+                             const std::string& modifier,
+                             const std::string& trace,
+                             const std::string& mean_and_error,
+                             const std::string& units,
+                             bool important);
+
+void AppendResultMeanAndError(std::string& output,
+                              const std::string& measurement,
+                              const std::string& modifier,
+                              const std::string& trace,
+                              const std::string& mean_and_error,
+                              const std::string& units,
+                              bool important);
+
+// Like PrintResult(), but prints an entire list of results. The |values|
+// will generally be a list of comma-separated numbers. A typical
+// post-processing step might produce plots of their mean and standard
+// deviation.
+void PrintResultList(const std::string& measurement,
+                     const std::string& modifier,
+                     const std::string& trace,
+                     const std::string& values,
+                     const std::string& units,
+                     bool important);
+
+void AppendResultList(std::string& output,
+                      const std::string& measurement,
+                      const std::string& modifier,
+                      const std::string& trace,
+                      const std::string& values,
+                      const std::string& units,
+                      bool important);
+
+// Prints memory commit charge stats for use by perf graphs.
+void PrintSystemCommitCharge(const std::string& test_name,
+                             size_t charge,
+                             bool important);
+
+void PrintSystemCommitCharge(FILE* target,
+                             const std::string& test_name,
+                             size_t charge,
+                             bool important);
+
+std::string SystemCommitChargeToString(const std::string& test_name,
+                                       size_t charge,
+                                       bool important);
+
+}  // namespace perf_test
+
+#endif  // TESTING_PERF_PERF_TEST_H_
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/MockDiagnostics.h b/src/third_party/angle/src/tests/preprocessor_tests/MockDiagnostics.h
new file mode 100644
index 0000000..3976178
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/MockDiagnostics.h
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef PREPROCESSOR_TESTS_MOCK_DIAGNOSTICS_H_
+#define PREPROCESSOR_TESTS_MOCK_DIAGNOSTICS_H_
+
+#include "gmock/gmock.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+
+class MockDiagnostics : public pp::Diagnostics
+{
+  public:
+    MOCK_METHOD3(print,
+        void(ID id, const pp::SourceLocation& loc, const std::string& text));
+};
+
+#endif  // PREPROCESSOR_TESTS_MOCK_DIAGNOSTICS_H_
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/MockDirectiveHandler.h b/src/third_party/angle/src/tests/preprocessor_tests/MockDirectiveHandler.h
new file mode 100644
index 0000000..7560add
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/MockDirectiveHandler.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef PREPROCESSOR_TESTS_MOCK_DIRECTIVE_HANDLER_H_
+#define PREPROCESSOR_TESTS_MOCK_DIRECTIVE_HANDLER_H_
+
+#include "gmock/gmock.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
+
+class MockDirectiveHandler : public pp::DirectiveHandler
+{
+  public:
+    MOCK_METHOD2(handleError,
+        void(const pp::SourceLocation& loc, const std::string& msg));
+
+    MOCK_METHOD4(handlePragma,
+        void(const pp::SourceLocation& loc,
+             const std::string& name,
+             const std::string& value,
+             bool stdgl));
+
+    MOCK_METHOD3(handleExtension,
+        void(const pp::SourceLocation& loc,
+             const std::string& name,
+             const std::string& behavior));
+
+    MOCK_METHOD2(handleVersion,
+        void(const pp::SourceLocation& loc, int version));
+};
+
+#endif  // PREPROCESSOR_TESTS_MOCK_DIRECTIVE_HANDLER_H_
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/PreprocessorTest.cpp b/src/third_party/angle/src/tests/preprocessor_tests/PreprocessorTest.cpp
new file mode 100644
index 0000000..ccb21a5
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/PreprocessorTest.cpp
@@ -0,0 +1,67 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+void SimplePreprocessorTest::preprocess(const char *input,
+                                        std::stringstream *output,
+                                        pp::Preprocessor *preprocessor)
+{
+    ASSERT_TRUE(preprocessor->init(1, &input, nullptr));
+
+    int line = 1;
+    pp::Token token;
+    do
+    {
+        preprocessor->lex(&token);
+        if (output)
+        {
+            for (; line < token.location.line; ++line)
+            {
+                *output << "\n";
+            }
+            *output << token;
+        }
+    } while (token.type != pp::Token::LAST);
+}
+
+void SimplePreprocessorTest::preprocess(const char *input, const pp::PreprocessorSettings &settings)
+{
+    pp::Preprocessor preprocessor(&mDiagnostics, &mDirectiveHandler, settings);
+    preprocess(input, nullptr, &preprocessor);
+}
+
+void SimplePreprocessorTest::preprocess(const char *input)
+{
+    preprocess(input, pp::PreprocessorSettings());
+}
+
+void SimplePreprocessorTest::preprocess(const char *input, const char *expected)
+{
+    pp::Preprocessor preprocessor(&mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings());
+    std::stringstream output;
+    preprocess(input, &output, &preprocessor);
+
+    std::string actual = output.str();
+    EXPECT_STREQ(expected, actual.c_str());
+}
+
+void SimplePreprocessorTest::lexSingleToken(const char *input, pp::Token *token)
+{
+    pp::Preprocessor preprocessor(&mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings());
+    ASSERT_TRUE(preprocessor.init(1, &input, nullptr));
+    preprocessor.lex(token);
+}
+
+void SimplePreprocessorTest::lexSingleToken(size_t count,
+                                            const char *const input[],
+                                            pp::Token *token)
+{
+    pp::Preprocessor preprocessor(&mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings());
+    ASSERT_TRUE(preprocessor.init(count, input, nullptr));
+    preprocessor.lex(token);
+}
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/PreprocessorTest.h b/src/third_party/angle/src/tests/preprocessor_tests/PreprocessorTest.h
new file mode 100644
index 0000000..ead16f7
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/PreprocessorTest.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gtest/gtest.h"
+
+#include "MockDiagnostics.h"
+#include "MockDirectiveHandler.h"
+#include "compiler/preprocessor/Preprocessor.h"
+
+#ifndef PREPROCESSOR_TESTS_PREPROCESSOR_TEST_H_
+#define PREPROCESSOR_TESTS_PREPROCESSOR_TEST_H_
+
+class PreprocessorTest : public testing::Test
+{
+  protected:
+    PreprocessorTest()
+        : mPreprocessor(&mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings())
+    {
+    }
+
+    MockDiagnostics mDiagnostics;
+    MockDirectiveHandler mDirectiveHandler;
+    pp::Preprocessor mPreprocessor;
+};
+
+class SimplePreprocessorTest : public testing::Test
+{
+  protected:
+    // Preprocesses the input string.
+    void preprocess(const char *input);
+    void preprocess(const char *input, const pp::PreprocessorSettings &settings);
+
+    // Preprocesses the input string and verifies that it matches expected output.
+    void preprocess(const char *input, const char *expected);
+
+    // Lexes a single token from input and writes it to token.
+    void lexSingleToken(const char *input, pp::Token *token);
+    void lexSingleToken(size_t count, const char *const input[], pp::Token *token);
+
+    MockDiagnostics mDiagnostics;
+    MockDirectiveHandler mDirectiveHandler;
+
+  private:
+    void preprocess(const char *input, std::stringstream *output, pp::Preprocessor *preprocessor);
+};
+
+#endif  // PREPROCESSOR_TESTS_PREPROCESSOR_TEST_H_
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/char_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/char_test.cpp
new file mode 100644
index 0000000..641ef2c
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/char_test.cpp
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include <algorithm>
+#include <climits>
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+class CharTest : public PreprocessorTest,
+                 public testing::WithParamInterface<int>
+{
+};
+
+static const char kPunctuators[] = {
+    '.', '+', '-', '/', '*', '%', '<', '>', '[', ']', '(', ')', '{', '}',
+    '^', '|', '&', '~', '=', '!', ':', ';', ',', '?'};
+static const int kNumPunctuators =
+    sizeof(kPunctuators) / sizeof(kPunctuators[0]);
+
+bool isPunctuator(char c)
+{
+    static const char* kPunctuatorBeg = kPunctuators;
+    static const char* kPunctuatorEnd = kPunctuators + kNumPunctuators;
+    return std::find(kPunctuatorBeg, kPunctuatorEnd, c) != kPunctuatorEnd;
+}
+
+static const char kWhitespaces[] = {' ', '\t', '\v', '\f', '\n', '\r'};
+static const int kNumWhitespaces =
+    sizeof(kWhitespaces) / sizeof(kWhitespaces[0]);
+
+bool isWhitespace(char c)
+{
+    static const char* kWhitespaceBeg = kWhitespaces;
+    static const char* kWhitespaceEnd = kWhitespaces + kNumWhitespaces;
+    return std::find(kWhitespaceBeg, kWhitespaceEnd, c) != kWhitespaceEnd;
+}
+
+TEST_P(CharTest, Identified)
+{
+    std::string str(1, static_cast<char>(GetParam()));
+    const char* cstr = str.c_str();
+    int length = 1;
+
+    // Note that we pass the length param as well because the invalid
+    // string may contain the null character.
+    ASSERT_TRUE(mPreprocessor.init(1, &cstr, &length));
+
+    int expectedType = pp::Token::LAST;
+    std::string expectedValue;
+
+    if (str[0] == '#')
+    {
+        // Lone '#' is ignored.
+    }
+    else if ((str[0] == '_') ||
+             ((str[0] >= 'a') && (str[0] <= 'z')) ||
+             ((str[0] >= 'A') && (str[0] <= 'Z')))
+    {
+        expectedType = pp::Token::IDENTIFIER;
+        expectedValue = str;
+    }
+    else if (str[0] >= '0' && str[0] <= '9')
+    {
+        expectedType = pp::Token::CONST_INT;
+        expectedValue = str;
+    }
+    else if (isPunctuator(str[0]))
+    {
+        expectedType = str[0];
+        expectedValue = str;
+    }
+    else if (isWhitespace(str[0]))
+    {
+        // Whitespace is ignored.
+    }
+    else
+    {
+        // Everything else is invalid.
+        using testing::_;
+        EXPECT_CALL(mDiagnostics,
+            print(pp::Diagnostics::PP_INVALID_CHARACTER, _, str));
+    }
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(expectedType, token.type);
+    EXPECT_EQ(expectedValue, token.text);
+};
+
+// Note +1 for the max-value in range. It is there because the max-value
+// not included in the range.
+INSTANTIATE_TEST_CASE_P(All, CharTest,
+                        testing::Range(CHAR_MIN, CHAR_MAX + 1));
+
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/comment_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/comment_test.cpp
new file mode 100644
index 0000000..2501896
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/comment_test.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+class CommentTest : public SimplePreprocessorTest, public testing::WithParamInterface<const char *>
+{
+};
+
+TEST_P(CommentTest, CommentIgnored)
+{
+    const char* str = GetParam();
+
+    pp::Token token;
+    lexSingleToken(str, &token);
+    EXPECT_EQ(pp::Token::LAST, token.type);
+}
+
+INSTANTIATE_TEST_CASE_P(LineComment, CommentTest,
+                        testing::Values("//foo\n", // With newline.
+                                        "//foo",   // Without newline.
+                                        "//**/",   // Nested block comment.
+                                        "////",    // Nested line comment.
+                                        "//\""));  // Invalid character.  
+
+INSTANTIATE_TEST_CASE_P(BlockComment, CommentTest,
+                        testing::Values("/*foo*/",
+                                        "/*foo\n*/", // With newline.
+                                        "/*//*/",    // Nested line comment.
+                                        "/*/**/",    // Nested block comment.
+                                        "/***/",     // With lone '*'.
+                                        "/*\"*/"));  // Invalid character.
+
+class BlockCommentTest : public SimplePreprocessorTest
+{
+};
+
+TEST_F(BlockCommentTest, CommentReplacedWithSpace)
+{
+    const char* str = "/*foo*/bar";
+
+    pp::Token token;
+    lexSingleToken(str, &token);
+    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+    EXPECT_EQ("bar", token.text);
+    EXPECT_TRUE(token.hasLeadingSpace());
+}
+
+TEST_F(BlockCommentTest, UnterminatedComment)
+{
+    const char* str = "/*foo";
+
+    using testing::_;
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_EOF_IN_COMMENT, _, _));
+
+    preprocess(str);
+}
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/define_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/define_test.cpp
new file mode 100644
index 0000000..d5e7ac7
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/define_test.cpp
@@ -0,0 +1,1031 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include <sstream>
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+using testing::_;
+
+class DefineTest : public SimplePreprocessorTest
+{
+};
+
+TEST_F(DefineTest, NonIdentifier)
+{
+    const char* input = "#define 2 foo\n"
+                        "2\n";
+    const char* expected = "\n"
+                           "2\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_UNEXPECTED_TOKEN,
+                      pp::SourceLocation(0, 1),
+                      "2"));
+
+    preprocess(input, expected);
+};
+
+TEST_F(DefineTest, RedefinePredefined)
+{
+    const char* input = "#define __LINE__ 10\n"
+                        "__LINE__\n"
+                        "#define __FILE__ 20\n"
+                        "__FILE__\n"
+                        "#define __VERSION__ 200\n"
+                        "__VERSION__\n"
+                        "#define GL_ES 0\n"
+                        "GL_ES\n";
+    const char* expected = "\n"
+                           "2\n"
+                           "\n"
+                           "0\n"
+                           "\n"
+                           "100\n"
+                           "\n"
+                           "1\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
+                      pp::SourceLocation(0, 1),
+                      "__LINE__"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
+                      pp::SourceLocation(0, 3),
+                      "__FILE__"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
+                      pp::SourceLocation(0, 5),
+                      "__VERSION__"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
+                      pp::SourceLocation(0, 7),
+                      "GL_ES"));
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ReservedUnderScore1)
+{
+    const char* input = "#define __foo bar\n"
+                        "__foo\n";
+    const char* expected = "\n"
+                           "bar\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_WARNING_MACRO_NAME_RESERVED,
+                                    pp::SourceLocation(0, 1), "__foo"));
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ReservedUnderScore2)
+{
+    const char* input = "#define foo__bar baz\n"
+                        "foo__bar\n";
+    const char* expected = "\n"
+                           "baz\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_WARNING_MACRO_NAME_RESERVED,
+                                    pp::SourceLocation(0, 1), "foo__bar"));
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ReservedGL)
+{
+    const char* input = "#define GL_foo bar\n"
+                        "GL_foo\n";
+    const char* expected = "\n"
+                           "GL_foo\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_NAME_RESERVED,
+                      pp::SourceLocation(0, 1),
+                      "GL_foo"));
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjRedefineValid)
+{
+    const char* input = "#define foo (1-1)\n"
+                        "#define foo /* whitespace */ (1-1) /* other */ \n"
+                        "foo\n";
+    const char* expected = "\n"
+                           "\n"
+                           "(1-1)\n";
+    // No error or warning.
+    using testing::_;
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjRedefineInvalid)
+{
+    const char* input = "#define foo (0)\n"
+                        "#define foo (1-1)\n"
+                        "foo\n";
+    const char* expected = "\n"
+                           "\n"
+                           "(0)\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_REDEFINED,
+                      pp::SourceLocation(0, 2),
+                      "foo"));
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncRedefineValid)
+{
+    const char* input = "#define foo(a) ( a )\n"
+                        "#define foo( a )( /* whitespace */ a /* other */ )\n"
+                        "foo(b)\n";
+    const char* expected = "\n"
+                           "\n"
+                           "( b )\n";
+    // No error or warning.
+    using testing::_;
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncRedefineInvalid)
+{
+    const char* input = "#define foo(b) ( a )\n"
+                        "#define foo(b) ( b )\n"
+                        "foo(1)\n";
+    const char* expected = "\n"
+                           "\n"
+                           "( a )\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_REDEFINED,
+                      pp::SourceLocation(0, 2),
+                      "foo"));
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjBasic)
+{
+    const char* input = "#define foo 1\n"
+                        "foo\n";
+    const char* expected = "\n"
+                           "1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjEmpty)
+{
+    const char* input = "#define foo\n"
+                        "foo\n";
+    const char* expected = "\n"
+                           "\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjChain)
+{
+    const char* input = "#define foo 1\n"
+                        "#define bar foo\n"
+                        "bar\n";
+    const char* expected = "\n"
+                           "\n"
+                           "1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjChainReverse)
+{
+    const char* input = "#define bar foo\n"
+                        "#define foo 1\n"
+                        "bar\n";
+    const char* expected = "\n"
+                           "\n"
+                           "1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjRecursive)
+{
+    const char* input = "#define foo bar\n"
+                        "#define bar baz\n"
+                        "#define baz foo\n"
+                        "foo\n"
+                        "bar\n"
+                        "baz\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "foo\n"
+                           "bar\n"
+                           "baz\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjCompositeChain)
+{
+    const char* input = "#define foo 1\n"
+                        "#define bar a foo\n"
+                        "bar\n";
+    const char* expected = "\n"
+                           "\n"
+                           "a 1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjCompositeChainReverse)
+{
+    const char* input = "#define bar a foo\n"
+                        "#define foo 1\n"
+                        "bar\n";
+    const char* expected = "\n"
+                           "\n"
+                           "a 1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjCompositeRecursive)
+{
+    const char* input = "#define foo a bar\n"
+                        "#define bar b baz\n"
+                        "#define baz c foo\n"
+                        "foo\n"
+                        "bar\n"
+                        "baz\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "a b c foo\n"
+                           "b c a bar\n"
+                           "c a b baz\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjChainSelfRecursive)
+{
+    const char* input = "#define foo foo\n"
+                        "#define bar foo\n"
+                        "bar\n";
+    const char* expected = "\n"
+                           "\n"
+                           "foo\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjectLikeWithParens)
+{
+    const char* input = "#define foo ()1\n"
+                        "foo()\n"
+                        "#define bar ()2\n"
+                        "bar()\n";
+    const char* expected = "\n"
+                           "()1()\n"
+                           "\n"
+                           "()2()\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncEmpty)
+{
+    const char* input = "#define foo()\n"
+                        "foo()\n";
+    const char* expected = "\n"
+                           "\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncNoArgs)
+{
+    const char* input = "#define foo() bar\n"
+                        "foo()\n";
+    const char* expected = "\n"
+                           "bar\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncOneArgUnused)
+{
+    const char* input = "#define foo(x) 1\n"
+                        "foo(bar)\n";
+    const char* expected = "\n"
+                           "1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncTwoArgsUnused)
+{
+    const char* input = "#define foo(x,y) 1\n"
+                        "foo(bar,baz)\n";
+    const char* expected = "\n"
+                           "1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncOneArg)
+{
+    const char* input = "#define foo(x) ((x)+1)\n"
+                        "foo(bar)\n";
+    const char* expected = "\n"
+                           "((bar)+1)\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncTwoArgs)
+{
+    const char* input = "#define foo(x,y) ((x)*(y))\n"
+                        "foo(bar,baz)\n";
+    const char* expected = "\n"
+                           "((bar)*(baz))\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncEmptyArgs)
+{
+    const char* input = "#define zero() pass\n"
+                        "#define one(x) pass\n"
+                        "#define two(x,y) pass\n"
+                        "zero()\n"
+                        "one()\n"
+                        "two(,)\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "pass\n"
+                           "pass\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncMacroAsParam)
+{
+    const char* input = "#define x 0\n"
+                        "#define foo(x) x\n"
+                        "foo(1)\n";
+    const char* expected = "\n"
+                           "\n"
+                           "1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncOneArgMulti)
+{
+    const char* input = "#define foo(x) (x)\n"
+                        "foo(this is a multi-word argument)\n";
+    const char* expected = "\n"
+                           "(this is a multi-word argument)\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncTwoArgsMulti)
+{
+    const char* input = "#define foo(x,y) x,two fish,red fish,y\n"
+                        "foo(one fish, blue fish)\n";
+    const char* expected = "\n"
+                           "one fish,two fish,red fish,blue fish\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncCompose)
+{
+    const char* input = "#define bar(x) (1+(x))\n"
+                        "#define foo(y) (2*(y))\n"
+                        "foo(bar(3))\n";
+    const char* expected = "\n"
+                           "\n"
+                           "(2*((1+(3))))\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncArgWithParens)
+{
+    const char* input = "#define foo(x) (x)\n"
+                        "foo(argument(with parens) FTW)\n";
+    const char* expected = "\n"
+                           "(argument(with parens) FTW)\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncMacroAsNonMacro)
+{
+    const char* input = "#define foo(bar) bar\n"
+                        "foo bar\n";
+    const char* expected = "\n"
+                           "foo bar\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncExtraNewlines)
+{
+    const char* input = "#define foo(a) (a)\n"
+                        "foo\n"
+                        "(\n"
+                        "1\n"
+                        ")\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "(1)\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFunc)
+{
+    const char* input = "#define foo() pass\n"
+                        "#define bar foo()\n"
+                        "bar\n";
+    const char* expected = "\n"
+                           "\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToNonFunc)
+{
+    const char* input = "#define pass() fail\n"
+                        "#define bar pass\n"
+                        "bar\n";
+    const char* expected = "\n"
+                           "\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncWithArgs)
+{
+    const char* input = "#define foo(fail) fail\n"
+                        "#define bar foo(pass)\n"
+                        "bar\n";
+    const char* expected = "\n"
+                           "\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncCompose)
+{
+    const char* input = "#define baz(fail) fail\n"
+                        "#define bar(fail) fail\n"
+                        "#define foo bar(baz(pass))\n"
+                        "foo\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncParensInText1)
+{
+    const char* input = "#define fail() pass\n"
+                        "#define foo fail\n"
+                        "foo()\n";
+    const char* expected = "\n"
+                           "\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncParensInText2)
+{
+    const char* input = "#define bar with,embedded,commas\n"
+                        "#define func(x) pass\n"
+                        "#define foo func\n"
+                        "foo(bar)\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncMultiLevel)
+{
+    const char* input = "#define foo(x) pass\n"
+                        "#define bar foo\n"
+                        "#define baz bar\n"
+                        "#define joe baz\n"
+                        "joe (fail)\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjToFuncRecursive)
+{
+    const char* input = "#define A(a,b) B(a,b)\n"
+                        "#define C A(0,C)\n"
+                        "C\n";
+    const char* expected = "\n"
+                           "\n"
+                           "B(0,C)\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainFuncToFuncCompose)
+{
+    const char* input = "#define baz(fail) fail\n"
+                        "#define bar(fail) fail\n"
+                        "#define foo() bar(baz(pass))\n"
+                        "foo()\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncSelfRecursive)
+{
+    const char* input = "#define foo(a) foo(2*(a))\n"
+                        "foo(3)\n";
+    const char* expected = "\n"
+                           "foo(2*(3))\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncSelfCompose)
+{
+    const char* input = "#define foo(a) foo(2*(a))\n"
+                        "foo(foo(3))\n";
+    const char* expected = "\n"
+                           "foo(2*(foo(2*(3))))\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncSelfComposeNonFunc)
+{
+    const char* input = "#define foo(bar) bar\n"
+                        "foo(foo)\n";
+    const char* expected = "\n"
+                           "foo\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncSelfComposeNonFuncMultiTokenArg)
+{
+    const char* input = "#define foo(bar) bar\n"
+                        "foo(1+foo)\n";
+    const char* expected = "\n"
+                           "1+foo\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FinalizeUnexpandedMacro)
+{
+    const char* input = "#define expand(x) expand(x once)\n"
+                        "#define foo(x) x\n"
+                        "foo(expand(just))\n";
+    const char* expected = "\n"
+                           "\n"
+                           "expand(just once)\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncArgWithCommas)
+{
+    const char* input = "#define foo(x) pass\n"
+                        "foo(argument (with,embedded, commas) -- baz)\n";
+    const char* expected = "\n"
+                           "pass\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncArgObjMaroWithComma)
+{
+    const char* input = "#define foo(a) (a)\n"
+                        "#define bar two,words\n"
+                        "foo(bar)\n";
+    const char* expected = "\n"
+                           "\n"
+                           "(two,words)\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncLeftParenInMacroRightParenInText)
+{
+    const char* input = "#define bar(a) a*2\n"
+                        "#define foo bar(\n"
+                        "foo b)\n";
+    const char* expected = "\n"
+                           "\n"
+                           "b*2\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, RepeatedArg)
+{
+    const char* input = "#define double(x) x x\n"
+                        "double(1)\n";
+    const char* expected = "\n"
+                           "1 1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncMissingRightParen)
+{
+    const char* input = "#define foo(x) (2*(x))\n"
+                        "foo(3\n";
+    const char* expected = "\n"
+                           "\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION,
+                      pp::SourceLocation(0, 2),
+                      "foo"));
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncIncorrectArgCount)
+{
+    const char* input = "#define foo(x,y) ((x)+(y))\n"
+                        "foo()\n"
+                        "foo(1)\n"
+                        "foo(1,2,3)\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_TOO_FEW_ARGS,
+                      pp::SourceLocation(0, 2),
+                      "foo"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_TOO_FEW_ARGS,
+                      pp::SourceLocation(0, 3),
+                      "foo"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_TOO_MANY_ARGS,
+                      pp::SourceLocation(0, 4),
+                      "foo"));
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, Undef)
+{
+    const char* input = "#define foo 1\n"
+                        "foo\n"
+                        "#undef foo\n"
+                        "foo\n";
+    const char* expected = "\n"
+                           "1\n"
+                           "\n"
+                           "foo\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, UndefPredefined)
+{
+    const char* input = "#undef __LINE__\n"
+                        "__LINE__\n"
+                        "#undef __FILE__\n"
+                        "__FILE__\n"
+                        "#undef __VERSION__\n"
+                        "__VERSION__\n"
+                        "#undef GL_ES\n"
+                        "GL_ES\n";
+    const char* expected = "\n"
+                           "2\n"
+                           "\n"
+                           "0\n"
+                           "\n"
+                           "100\n"
+                           "\n"
+                           "1\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
+                      pp::SourceLocation(0, 1),
+                      "__LINE__"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
+                      pp::SourceLocation(0, 3),
+                      "__FILE__"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
+                      pp::SourceLocation(0, 5),
+                      "__VERSION__"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
+                      pp::SourceLocation(0, 7),
+                      "GL_ES"));
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, UndefRedefine)
+{
+    const char* input = "#define foo 1\n"
+                        "foo\n"
+                        "#undef foo\n"
+                        "foo\n"
+                        "#define foo 2\n"
+                        "foo\n";
+    const char* expected = "\n"
+                           "1\n"
+                           "\n"
+                           "foo\n"
+                           "\n"
+                           "2\n";
+
+    preprocess(input, expected);
+}
+
+// Example from C99 standard section 6.10.3.5 Scope of macro definitions
+TEST_F(DefineTest, C99Example)
+{
+    const char* input =
+        "#define x    3          \n"
+        "#define f(a) f(x * (a)) \n"
+        "#undef  x               \n"
+        "#define x    2          \n"
+        "#define g    f          \n"
+        "#define z    z[0]       \n"
+        "#define h    g(~        \n"
+        "#define m(a) a(w)       \n"
+        "#define w    0,1        \n"
+        "#define t(a) a          \n"
+        "#define p()  int        \n"
+        "#define q(x) x          \n"
+        "                        \n"
+        "f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);\n"
+        "g(x+(3,4)-w) | h 5) & m\n"
+        "    (f)^m(m);\n"
+        "p() i[q()] = { q(1), 23, 4, 5, };\n";
+    const char* expected = 
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);\n"
+        "f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) &\n"
+        " f(2 * (0,1))^m(0,1);\n"
+        "int i[] = { 1, 23, 4, 5, };\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, Predefined_GL_ES)
+{
+    const char* input = "GL_ES\n";
+    const char* expected = "1\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, Predefined_VERSION)
+{
+    const char* input = "__VERSION__\n";
+    const char* expected = "100\n";
+
+    preprocess(input, expected);
+}
+
+TEST_F(DefineTest, Predefined_LINE1)
+{
+    const char* str = "\n\n__LINE__";
+
+    pp::Token token;
+    lexSingleToken(str, &token);
+    EXPECT_EQ(pp::Token::CONST_INT, token.type);
+    EXPECT_EQ("3", token.text);
+}
+
+TEST_F(DefineTest, Predefined_LINE2)
+{
+    const char* str = "#line 10\n"
+                      "__LINE__\n";
+
+    pp::Token token;
+    lexSingleToken(str, &token);
+    EXPECT_EQ(pp::Token::CONST_INT, token.type);
+    EXPECT_EQ("10", token.text);
+}
+
+TEST_F(DefineTest, Predefined_FILE1)
+{
+    const char* const str[] = {"", "", "__FILE__"};
+
+    pp::Token token;
+    lexSingleToken(3, str, &token);
+    EXPECT_EQ(pp::Token::CONST_INT, token.type);
+    EXPECT_EQ("2", token.text);
+}
+
+TEST_F(DefineTest, Predefined_FILE2)
+{
+    const char* const str[] = {"#line 10 20\n", "__FILE__"};
+
+    pp::Token token;
+    lexSingleToken(2, str, &token);
+    EXPECT_EQ(pp::Token::CONST_INT, token.type);
+    EXPECT_EQ("21", token.text);
+}
+
+// Defined operator produced by macro expansion should be parsed inside #if directives
+TEST_F(DefineTest, ExpandedDefinedParsedInsideIf)
+{
+    const char *input =
+        "#define bar 1\n"
+        "#define foo defined(bar)\n"
+        "#if foo\n"
+        "bar\n"
+        "#endif\n";
+    const char *expected =
+        "\n"
+        "\n"
+        "\n"
+        "1\n"
+        "\n";
+    preprocess(input, expected);
+}
+
+// Defined operator produced by macro expansion should not be parsed outside #if directives
+TEST_F(DefineTest, ExpandedDefinedNotParsedOutsideIf)
+{
+    const char *input =
+        "#define foo defined(bar)\n"
+        "foo\n";
+    const char *expected =
+        "\n"
+        "defined(bar)\n";
+    preprocess(input, expected);
+}
+
+// Test that line directive expressions give errors on negative or undefined shifts.
+TEST_F(DefineTest, NegativeShiftInLineDirective)
+{
+    const char *input =
+        "#line 1 << -1\n"
+        "#line 1 >> -1\n"
+        "#line 1 << x\n"
+        "#line 1 >> x\n";
+    const char *expected =
+        "\n"
+        "\n"
+        "\n"
+        "\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_UNDEFINED_SHIFT, _, _)).Times(4);
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_LINE_NUMBER, _, _)).Times(2);
+    preprocess(input, expected);
+}
+
+// Undefining a macro in its invocation parameters produces and error
+TEST_F(DefineTest, UndefineInInvocation)
+{
+    const char *input =
+        "#define G(a, b) a b\n"
+        "G(\n"
+        "#undef G\n"
+        "1, 2)\n";
+    const char *expected = "\n\n\n1 2\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED,
+                                    pp::SourceLocation(0, 3), _));
+
+    preprocess(input, expected);
+}
+
+// Undefining a macro before its invocation parameters produces and error
+TEST_F(DefineTest, UndefineInInvocationPreLParen)
+{
+    const char *input =
+        "#define G(a, b) a b\n"
+        "G\n"
+        "#undef G\n"
+        "(1, 2)\n";
+    const char *expected = "\n\n\n1 2\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED,
+                                    pp::SourceLocation(0, 3), _));
+
+    preprocess(input, expected);
+}
+
+// The name of the macro "a" is inside an incomplete macro invocation of macro "m()" in its own
+// expansion. This should not result in infinite recursion.
+TEST_F(DefineTest, RecursiveMacroNameInsideIncompleteMacroInvocationInMacroExpansion)
+{
+    const char *input =
+        "#define m(a)\n"
+        "#define a m((a)\n"
+        "a)\n";
+    const char *expected =
+        "\n"
+        "\n"
+        "\n";
+    preprocess(input, expected);
+}
+
+// The name of the macro "a" is inside an incomplete macro invocation of macro "m()" in its own
+// expansion. Then the macro "a" is undef'd. This is a regression test for a memory management bug
+// where macro "a" would be freed on undef even though cleaning up the recursive macro invocation
+// would still need to refer to macro "a".
+TEST_F(DefineTest, UndefInsideRecursiveMacroInvocation)
+{
+    const char *input =
+        "#define m(a)\n"
+        "#define a m((a)\n"
+        "a\n"
+        "#undef a\n"
+        ")\n";
+    const char *expected =
+        "\n"
+        "\n"
+        "\n"
+        "\n"
+        "\n";
+    preprocess(input, expected);
+}
+
+// The macro invocations form a long chain. The macro expander should protect against stack overflow
+// and generate an error in this case.
+TEST_F(DefineTest, LongMacroInvocationChain)
+{
+    std::stringstream inputStream;
+    std::stringstream expectedStream;
+
+    inputStream << "#define b(x) x\n";
+    inputStream << "#define a0(x) foo x\n";
+    for (int i = 1; i < 20; ++i)
+    {
+        inputStream << "#define a" << i << "(x) b(a" << (i - 1) << "(x))\n";
+    }
+    inputStream << "a19(y)\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_MACRO_INVOCATION_CHAIN_TOO_DEEP,
+                                    pp::SourceLocation(0, 22), _));
+
+    pp::PreprocessorSettings settings;
+    settings.maxMacroExpansionDepth = 19;
+
+    preprocess(inputStream.str().c_str(), settings);
+}
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/error_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/error_test.cpp
new file mode 100644
index 0000000..ab2e7ab
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/error_test.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+class ErrorTest : public SimplePreprocessorTest
+{
+};
+
+TEST_F(ErrorTest, Empty)
+{
+    const char* str = "#error\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler, handleError(pp::SourceLocation(0, 1), ""));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(ErrorTest, OneTokenMessage)
+{
+    const char* str = "#error foo\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handleError(pp::SourceLocation(0, 1), " foo"));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(ErrorTest, TwoTokenMessage)
+{
+    const char* str = "#error foo bar\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handleError(pp::SourceLocation(0, 1), " foo bar"));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(ErrorTest, Comments)
+{
+    const char* str = "/*foo*/"
+                      "#"
+                      "/*foo*/"
+                      "error"
+                      "/*foo*/"
+                      "foo"
+                      "/*foo*/"
+                      "bar"
+                      "/*foo*/"
+                      "//foo"
+                      "\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handleError(pp::SourceLocation(0, 1), " foo bar"));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(ErrorTest, MissingNewline)
+{
+    const char* str = "#error foo";
+    const char* expected = "";
+
+    using testing::_;
+    // Directive successfully parsed.
+    EXPECT_CALL(mDirectiveHandler,
+                handleError(pp::SourceLocation(0, 1), " foo"));
+    // Error reported about EOF.
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_EOF_IN_DIRECTIVE, _, _));
+
+    preprocess(str, expected);
+}
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/extension_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/extension_test.cpp
new file mode 100644
index 0000000..78c8fe2
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/extension_test.cpp
@@ -0,0 +1,136 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+class ExtensionTest : public SimplePreprocessorTest
+{
+};
+
+TEST_F(ExtensionTest, Valid)
+{
+    const char* str = "#extension foo : bar\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handleExtension(pp::SourceLocation(0, 1), "foo", "bar"));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(ExtensionTest, Comments)
+{
+    const char* str = "/*foo*/"
+                      "#"
+                      "/*foo*/"
+                      "extension"
+                      "/*foo*/"
+                      "foo"
+                      "/*foo*/"
+                      ":"
+                      "/*foo*/"
+                      "bar"
+                      "/*foo*/"
+                      "//foo"
+                      "\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handleExtension(pp::SourceLocation(0, 1), "foo", "bar"));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(ExtensionTest, MissingNewline)
+{
+    const char* str = "#extension foo : bar";
+    const char* expected = "";
+
+    using testing::_;
+    // Directive successfully parsed.
+    EXPECT_CALL(mDirectiveHandler,
+                handleExtension(pp::SourceLocation(0, 1), "foo", "bar"));
+    // Error reported about EOF.
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_EOF_IN_DIRECTIVE, _, _));
+
+    preprocess(str, expected);
+}
+
+TEST_F(ExtensionTest, ExtensionAfterNonPreProcessorTokenESSL1)
+{
+    const char *str = "int baz = 1;\n"
+                      "#extension foo : bar\n";
+    const char *expected = "int baz = 1;\n\n";
+
+    using testing::_;
+    // Directive successfully parsed.
+    EXPECT_CALL(mDirectiveHandler,
+        handleExtension(pp::SourceLocation(0, 2), "foo", "bar"));
+    // Expect a warning about extension pragmas after non-preprocessor tokens.
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1, _, _));
+
+    preprocess(str, expected);
+}
+
+TEST_F(ExtensionTest, ExtensionAfterNonPreProcessorTokenESSL3)
+{
+    const char *str = "#version 300 es\n"
+                      "int baz = 1;\n"
+                      "#extension foo : bar\n";
+    const char *expected = "\nint baz = 1;\n\n";
+
+    using testing::_;
+    // Directive successfully parsed.
+    EXPECT_CALL(mDirectiveHandler,
+        handleVersion(pp::SourceLocation(0, 1), 300));
+    // Expect a error about extension pragmas after non-preprocessor tokens.
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3, _, _));
+
+    preprocess(str, expected);
+}
+
+struct ExtensionTestParam
+{
+    const char* str;
+    pp::Diagnostics::ID id;
+};
+
+using testing::WithParamInterface;
+class InvalidExtensionTest : public ExtensionTest,
+                             public WithParamInterface<ExtensionTestParam>
+{
+};
+
+TEST_P(InvalidExtensionTest, Identified)
+{
+    ExtensionTestParam param = GetParam();
+    const char* expected = "\n";
+
+    using testing::_;
+    // No handleExtension call.
+    EXPECT_CALL(mDirectiveHandler, handleExtension(_, _, _)).Times(0);
+    // Invalid extension directive call.
+    EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
+
+    preprocess(param.str, expected);
+}
+
+static const ExtensionTestParam kParams[] = {
+    {"#extension\n", pp::Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE},
+    {"#extension 1\n", pp::Diagnostics::PP_INVALID_EXTENSION_NAME},
+    {"#extension foo bar\n", pp::Diagnostics::PP_UNEXPECTED_TOKEN},
+    {"#extension foo : \n", pp::Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE},
+    {"#extension foo : 1\n", pp::Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR},
+    {"#extension foo : bar baz\n", pp::Diagnostics::PP_UNEXPECTED_TOKEN}
+};
+INSTANTIATE_TEST_CASE_P(All, InvalidExtensionTest, testing::ValuesIn(kParams));
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/identifier_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/identifier_test.cpp
new file mode 100644
index 0000000..ea341b2
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/identifier_test.cpp
@@ -0,0 +1,161 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+#define CLOSED_RANGE(x, y) testing::Range(x, static_cast<char>((y) + 1))
+
+class IdentifierTest : public SimplePreprocessorTest
+{
+protected:
+    void expectIdentifier(const std::string& str)
+    {
+        const char* cstr = str.c_str();
+
+        pp::Token token;
+        lexSingleToken(cstr, &token);
+        EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+        EXPECT_EQ(str, token.text);
+    }
+};
+
+class SingleLetterIdentifierTest : public IdentifierTest,
+                                   public testing::WithParamInterface<char>
+{
+};
+
+// This test covers identifier names of form [_a-zA-Z].
+TEST_P(SingleLetterIdentifierTest, Identified)
+{
+    std::string str(1, GetParam());
+    expectIdentifier(str);
+}
+
+// Test string: '_'
+INSTANTIATE_TEST_CASE_P(Underscore,
+                        SingleLetterIdentifierTest,
+                        testing::Values('_'));
+
+// Test string: [a-z]
+INSTANTIATE_TEST_CASE_P(a_z,
+                        SingleLetterIdentifierTest,
+                        CLOSED_RANGE('a', 'z'));
+
+// Test string: [A-Z]
+INSTANTIATE_TEST_CASE_P(A_Z,
+                        SingleLetterIdentifierTest,
+                        CLOSED_RANGE('A', 'Z'));
+
+typedef std::tr1::tuple<char, char> IdentifierParams;
+class DoubleLetterIdentifierTest :
+    public IdentifierTest,
+    public testing::WithParamInterface<IdentifierParams>
+{
+};
+
+// This test covers identifier names of form [_a-zA-Z][_a-zA-Z0-9].
+TEST_P(DoubleLetterIdentifierTest, Identified)
+{
+    std::string str;
+    str.push_back(std::tr1::get<0>(GetParam()));
+    str.push_back(std::tr1::get<1>(GetParam()));
+
+    expectIdentifier(str);
+}
+
+// Test string: "__"
+INSTANTIATE_TEST_CASE_P(Underscore_Underscore,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(testing::Values('_'),
+                                         testing::Values('_')));
+
+// Test string: "_"[a-z]
+INSTANTIATE_TEST_CASE_P(Underscore_a_z,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(testing::Values('_'),
+                                         CLOSED_RANGE('a', 'z')));
+
+// Test string: "_"[A-Z]
+INSTANTIATE_TEST_CASE_P(Underscore_A_Z,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(testing::Values('_'),
+                                         CLOSED_RANGE('A', 'Z')));
+
+// Test string: "_"[0-9]
+INSTANTIATE_TEST_CASE_P(Underscore_0_9,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(testing::Values('_'),
+                                         CLOSED_RANGE('0', '9')));
+
+// Test string: [a-z]"_"
+INSTANTIATE_TEST_CASE_P(a_z_Underscore,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(CLOSED_RANGE('a', 'z'),
+                                         testing::Values('_')));
+
+// Test string: [a-z][a-z]
+INSTANTIATE_TEST_CASE_P(a_z_a_z,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(CLOSED_RANGE('a', 'z'),
+                                         CLOSED_RANGE('a', 'z')));
+
+// Test string: [a-z][A-Z]
+INSTANTIATE_TEST_CASE_P(a_z_A_Z,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(CLOSED_RANGE('a', 'z'),
+                                         CLOSED_RANGE('A', 'Z')));
+
+// Test string: [a-z][0-9]
+INSTANTIATE_TEST_CASE_P(a_z_0_9,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(CLOSED_RANGE('a', 'z'),
+                                         CLOSED_RANGE('0', '9')));
+
+// Test string: [A-Z]"_"
+INSTANTIATE_TEST_CASE_P(A_Z_Underscore,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(CLOSED_RANGE('A', 'Z'),
+                                         testing::Values('_')));
+
+// Test string: [A-Z][a-z]
+INSTANTIATE_TEST_CASE_P(A_Z_a_z,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(CLOSED_RANGE('A', 'Z'),
+                                         CLOSED_RANGE('a', 'z')));
+
+// Test string: [A-Z][A-Z]
+INSTANTIATE_TEST_CASE_P(A_Z_A_Z,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(CLOSED_RANGE('A', 'Z'),
+                                         CLOSED_RANGE('A', 'Z')));
+
+// Test string: [A-Z][0-9]
+INSTANTIATE_TEST_CASE_P(A_Z_0_9,
+                        DoubleLetterIdentifierTest,
+                        testing::Combine(CLOSED_RANGE('A', 'Z'),
+                                         CLOSED_RANGE('0', '9')));
+
+// The tests above cover one-letter and various combinations of two-letter
+// identifier names. This test covers all characters in a single string.
+TEST_F(IdentifierTest, AllLetters)
+{
+    std::string str;
+    for (char c = 'a'; c <= 'z'; ++c)
+        str.push_back(c);
+
+    str.push_back('_');
+
+    for (char c = 'A'; c <= 'Z'; ++c)
+        str.push_back(c);
+
+    str.push_back('_');
+
+    for (char c = '0'; c <= '9'; ++c)
+        str.push_back(c);
+
+    expectIdentifier(str);
+}
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/if_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/if_test.cpp
new file mode 100644
index 0000000..ecec2d8
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/if_test.cpp
@@ -0,0 +1,1002 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+class IfTest : public SimplePreprocessorTest
+{
+};
+
+TEST_F(IfTest, If_0)
+{
+    const char* str = "pass_1\n"
+                      "#if 0\n"
+                      "fail\n"
+                      "#endif\n"
+                      "pass_2\n";
+    const char* expected = "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, If_1)
+{
+    const char* str = "pass_1\n"
+                      "#if 1\n"
+                      "pass_2\n"
+                      "#endif\n"
+                      "pass_3\n";
+    const char* expected = "pass_1\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "pass_3\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, If_0_Else)
+{
+    const char* str = "pass_1\n"
+                      "#if 0\n"
+                      "fail\n"
+                      "#else\n"
+                      "pass_2\n"
+                      "#endif\n"
+                      "pass_3\n";
+    const char* expected = "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "pass_3\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, If_1_Else)
+{
+    const char* str = "pass_1\n"
+                      "#if 1\n"
+                      "pass_2\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n"
+                      "pass_3\n";
+    const char* expected = "pass_1\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_3\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, If_0_Elif)
+{
+    const char* str = "pass_1\n"
+                      "#if 0\n"
+                      "fail_1\n"
+                      "#elif 0\n"
+                      "fail_2\n"
+                      "#elif 1\n"
+                      "pass_2\n"
+                      "#elif 1\n"
+                      "fail_3\n"
+                      "#else\n"
+                      "fail_4\n"
+                      "#endif\n"
+                      "pass_3\n";
+    const char* expected = "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_3\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, If_1_Elif)
+{
+    const char* str = "pass_1\n"
+                      "#if 1\n"
+                      "pass_2\n"
+                      "#elif 0\n"
+                      "fail_1\n"
+                      "#elif 1\n"
+                      "fail_2\n"
+                      "#else\n"
+                      "fail_4\n"
+                      "#endif\n"
+                      "pass_3\n";
+    const char* expected = "pass_1\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_3\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, If_Elif_Else)
+{
+    const char* str = "pass_1\n"
+                      "#if 0\n"
+                      "fail_1\n"
+                      "#elif 0\n"
+                      "fail_2\n"
+                      "#elif 0\n"
+                      "fail_3\n"
+                      "#else\n"
+                      "pass_2\n"
+                      "#endif\n"
+                      "pass_3\n";
+    const char* expected = "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "pass_3\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, If_0_Nested)
+{
+    const char* str = "pass_1\n"
+                      "#if 0\n"
+                      "fail_1\n"
+                      "#if 1\n"
+                      "fail_2\n"
+                      "#else\n"
+                      "fail_3\n"
+                      "#endif\n"
+                      "#else\n"
+                      "pass_2\n"
+                      "#endif\n"
+                      "pass_3\n";
+    const char* expected = "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "pass_3\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, If_1_Nested)
+{
+    const char* str = "pass_1\n"
+                      "#if 1\n"
+                      "pass_2\n"
+                      "#if 1\n"
+                      "pass_3\n"
+                      "#else\n"
+                      "fail_1\n"
+                      "#endif\n"
+                      "#else\n"
+                      "fail_2\n"
+                      "#endif\n"
+                      "pass_4\n";
+    const char* expected = "pass_1\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "pass_3\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_4\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorPrecedence)
+{
+    const char* str = "#if 1 + 2 * 3 + - (26 % 17 - + 4 / 2)\n"
+                      "fail_1\n"
+                      "#else\n"
+                      "pass_1\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "pass_1\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorDefined)
+{
+    const char* str = "#if defined foo\n"
+                      "fail_1\n"
+                      "#else\n"
+                      "pass_1\n"
+                      "#endif\n"
+                      "#define foo\n"
+                      "#if defined(foo)\n"
+                      "pass_2\n"
+                      "#else\n"
+                      "fail_2\n"
+                      "#endif\n"
+                      "#undef foo\n"
+                      "#if defined ( foo ) \n"
+                      "fail_3\n"
+                      "#else\n"
+                      "pass_3\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_3\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorEQ)
+{
+    const char* str = "#if 4 - 1 == 2 + 1\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorNE)
+{
+    const char* str = "#if 1 != 2\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorLess)
+{
+    const char* str = "#if 1 < 2\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorGreater)
+{
+    const char* str = "#if 2 > 1\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorLE)
+{
+    const char* str = "#if 1 <= 2\n"
+                      "pass_1\n"
+                      "#else\n"
+                      "fail_1\n"
+                      "#endif\n"
+                      "#if 2 <= 2\n"
+                      "pass_2\n"
+                      "#else\n"
+                      "fail_2\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorGE)
+{
+    const char* str = "#if 2 >= 1\n"
+                      "pass_1\n"
+                      "#else\n"
+                      "fail_1\n"
+                      "#endif\n"
+                      "#if 2 >= 2\n"
+                      "pass_2\n"
+                      "#else\n"
+                      "fail_2\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorBitwiseOR)
+{
+    const char* str = "#if (0xaaaaaaaa | 0x55555555) == 0xffffffff\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorBitwiseAND)
+{
+    const char* str = "#if (0xaaaaaaa & 0x5555555) == 0\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorBitwiseXOR)
+{
+    const char* str = "#if (0xaaaaaaa ^ 0x5555555) == 0xfffffff\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorBitwiseComplement)
+{
+    const char* str = "#if (~ 0xdeadbeef) == -3735928560\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorLeft)
+{
+    const char* str = "#if (1 << 12) == 4096\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, OperatorRight)
+{
+    const char* str = "#if (31762 >> 8) == 124\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, ExpressionWithMacros)
+{
+    const char* str = "#define one 1\n"
+                      "#define two 2\n"
+                      "#define three 3\n"
+                      "#if one + two == three\n"
+                      "pass\n"
+                      "#else\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, JunkInsideExcludedBlockIgnored)
+{
+    const char* str = "#if 0\n"
+                      "foo !@#$%^&* .1bar\n"
+                      "#foo\n"
+                      "#if bar\n"
+                      "fail\n"
+                      "#endif\n"
+                      "#else\n"
+                      "pass\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, Ifdef)
+{
+    const char* str = "#define foo\n"
+                      "#ifdef foo\n"
+                      "pass_1\n"
+                      "#else\n"
+                      "fail_1\n"
+                      "#endif\n"
+                      "#undef foo\n"
+                      "#ifdef foo\n"
+                      "fail_2\n"
+                      "#else\n"
+                      "pass_2\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "\n"
+                           "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, Ifndef)
+{
+    const char* str = "#define foo\n"
+                      "#ifndef foo\n"
+                      "fail_1\n"
+                      "#else\n"
+                      "pass_1\n"
+                      "#endif\n"
+                      "#undef foo\n"
+                      "#ifndef foo\n"
+                      "pass_2\n"
+                      "#else\n"
+                      "fail_2\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_1\n"
+                           "\n"
+                           "\n"
+                           "\n"
+                           "pass_2\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, MissingExpression)
+{
+    const char* str = "#if\n"
+                      "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_INVALID_EXPRESSION,
+                      pp::SourceLocation(0, 1),
+                      "syntax error"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, DivisionByZero)
+{
+    const char* str = "#if 1 / (3 - (1 + 2))\n"
+                      "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                      pp::SourceLocation(0, 1), "1 / 0"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, ModuloByZero)
+{
+    const char* str = "#if 1 % (3 - (1 + 2))\n"
+                      "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                      pp::SourceLocation(0, 1), "1 % 0"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, DecIntegerOverflow)
+{
+    const char* str = "#if 4294967296\n"
+                      "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_INTEGER_OVERFLOW,
+                      pp::SourceLocation(0, 1), "4294967296"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, OctIntegerOverflow)
+{
+    const char* str = "#if 077777777777\n"
+                      "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_INTEGER_OVERFLOW,
+                      pp::SourceLocation(0, 1), "077777777777"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, HexIntegerOverflow)
+{
+    const char* str = "#if 0xfffffffff\n"
+                      "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_INTEGER_OVERFLOW,
+                      pp::SourceLocation(0, 1), "0xfffffffff"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, UndefinedMacro)
+{
+    const char* str = "#if UNDEFINED\n"
+                      "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+                      pp::SourceLocation(0, 1),
+                      "UNDEFINED"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, InvalidExpressionIgnoredForExcludedElif)
+{
+    const char* str = "#if 1\n"
+                      "pass\n"
+                      "#elif UNDEFINED\n"
+                      "fail\n"
+                      "#endif\n";
+    const char* expected = "\n"
+                           "pass\n"
+                           "\n"
+                           "\n"
+                           "\n";
+
+    // No error or warning.
+    using testing::_;
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(IfTest, ElseWithoutIf)
+{
+    const char* str = "#else\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF,
+                      pp::SourceLocation(0, 1),
+                      "else"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, ElifWithoutIf)
+{
+    const char* str = "#elif 1\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF,
+                      pp::SourceLocation(0, 1),
+                      "elif"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, EndifWithoutIf)
+{
+    const char* str = "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF,
+                      pp::SourceLocation(0, 1),
+                      "endif"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, ElseAfterElse)
+{
+    const char* str = "#if 1\n"
+                      "#else\n"
+                      "#else\n"
+                      "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE,
+                      pp::SourceLocation(0, 3),
+                      "else"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, ElifAfterElse)
+{
+    const char* str = "#if 1\n"
+                      "#else\n"
+                      "#elif 0\n"
+                      "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE,
+                      pp::SourceLocation(0, 3),
+                      "elif"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, UnterminatedIf)
+{
+    const char* str = "#if 1\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_CONDITIONAL_UNTERMINATED,
+                      pp::SourceLocation(0, 1),
+                      "if"));
+
+    preprocess(str);
+}
+
+TEST_F(IfTest, UnterminatedIfdef)
+{
+    const char* str = "#ifdef foo\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_CONDITIONAL_UNTERMINATED,
+                      pp::SourceLocation(0, 1),
+                      "ifdef"));
+
+    preprocess(str);
+}
+
+// The preprocessor only allows one expression to follow an #if directive.
+// Supplying two integer expressions should be an error.
+TEST_F(IfTest, ExtraIntExpression)
+{
+    const char *str =
+        "#if 1 1\n"
+        "#endif\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+                                    pp::SourceLocation(0, 1), "1"));
+
+    preprocess(str);
+}
+
+// The preprocessor only allows one expression to follow an #if directive.
+// Supplying two expressions where one uses a preprocessor define should be an error.
+TEST_F(IfTest, ExtraIdentifierExpression)
+{
+    const char *str =
+        "#define one 1\n"
+        "#if 1 one\n"
+        "#endif\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+                                    pp::SourceLocation(0, 2), "1"));
+
+    preprocess(str);
+}
+
+// Divide by zero that's not evaluated because of short-circuiting should not cause an error.
+TEST_F(IfTest, ShortCircuitedDivideByZero)
+{
+    const char *str =
+        "#if 1 || (2 / 0)\n"
+        "pass\n"
+        "#endif\n";
+    const char *expected =
+        "\n"
+        "pass\n"
+        "\n";
+
+    preprocess(str, expected);
+}
+
+// Undefined identifier that's not evaluated because of short-circuiting should not cause an error.
+TEST_F(IfTest, ShortCircuitedUndefined)
+{
+    const char *str =
+        "#if 1 || UNDEFINED\n"
+        "pass\n"
+        "#endif\n";
+    const char *expected =
+        "\n"
+        "pass\n"
+        "\n";
+
+    preprocess(str, expected);
+}
+
+// Defined operator produced by macro expansion has undefined behavior according to C++ spec,
+// which the GLSL spec references (see C++14 draft spec section 16.1.4), but this behavior is
+// needed for passing dEQP tests, which enforce stricter compatibility between implementations.
+TEST_F(IfTest, DefinedOperatorValidAfterMacroExpansion)
+{
+    const char *str =
+        "#define foo defined\n"
+        "#if !foo bar\n"
+        "pass\n"
+        "#endif\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+                                    pp::SourceLocation(0, 2), "defined"));
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+                                    pp::SourceLocation(0, 2), "bar"));
+
+    preprocess(str);
+}
+
+// Defined operator produced by macro expansion has undefined behavior according to C++ spec,
+// which the GLSL spec references (see C++14 draft spec section 16.1.4), but this behavior is
+// needed for passing dEQP tests, which enforce stricter compatibility between implementations.
+TEST_F(IfTest, UnterminatedDefinedInMacro)
+{
+    const char *str =
+        "#define foo defined(\n"
+        "#if foo\n"
+        "#endif\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+                                    pp::SourceLocation(0, 2), "defined"));
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+                                    pp::SourceLocation(0, 2), "("));
+
+    preprocess(str);
+}
+
+// Defined operator produced by macro expansion has undefined behavior according to C++ spec,
+// which the GLSL spec references (see C++14 draft spec section 16.1.4), but this behavior is
+// needed for passing dEQP tests, which enforce stricter compatibility between implementations.
+TEST_F(IfTest, UnterminatedDefinedInMacro2)
+{
+    const char *str =
+        "#define foo defined(bar\n"
+        "#if foo\n"
+        "#endif\n";
+
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+                                    pp::SourceLocation(0, 2), "defined"));
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+                                    pp::SourceLocation(0, 2), "("));
+
+    preprocess(str);
+}
+
+// Undefined shift: negative shift offset.
+TEST_F(IfTest, BitShiftLeftOperatorNegativeOffset)
+{
+    const char *str =
+        "#if 2 << -1 == 1\n"
+        "foo\n"
+        "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 << -1"));
+
+    preprocess(str);
+}
+
+// Undefined shift: shift offset is out of range.
+TEST_F(IfTest, BitShiftLeftOperatorOffset32)
+{
+    const char *str =
+        "#if 2 << 32 == 1\n"
+        "foo\n"
+        "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 << 32"));
+
+    preprocess(str);
+}
+
+// Left hand side of shift is negative.
+TEST_F(IfTest, BitShiftLeftOperatorNegativeLHS)
+{
+    const char *str =
+        "#if (-2) << 1 == -4\n"
+        "pass\n"
+        "#endif\n";
+    const char *expected =
+        "\n"
+        "pass\n"
+        "\n";
+
+    preprocess(str, expected);
+}
+
+// Undefined shift: shift offset is out of range.
+TEST_F(IfTest, BitShiftRightOperatorNegativeOffset)
+{
+    const char *str =
+        "#if 2 >> -1 == 4\n"
+        "foo\n"
+        "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 >> -1"));
+
+    preprocess(str);
+}
+
+// Undefined shift: shift offset is out of range.
+TEST_F(IfTest, BitShiftRightOperatorOffset32)
+{
+    const char *str =
+        "#if 2 >> 32 == 0\n"
+        "foo\n"
+        "#endif\n";
+
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 >> 32"));
+
+    preprocess(str);
+}
+
+// Left hand side of shift is negative.
+TEST_F(IfTest, BitShiftRightOperatorNegativeLHS)
+{
+    const char *str =
+        "#if (-2) >> 1 == 0x7fffffff\n"
+        "pass\n"
+        "#endif\n";
+    const char *expected =
+        "\n"
+        "pass\n"
+        "\n";
+
+    preprocess(str, expected);
+}
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/input_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/input_test.cpp
new file mode 100644
index 0000000..1aec284
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/input_test.cpp
@@ -0,0 +1,178 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Input.h"
+#include "compiler/preprocessor/Token.h"
+
+class InitTest : public PreprocessorTest
+{
+};
+
+TEST_F(InitTest, ZeroCount)
+{
+    EXPECT_TRUE(mPreprocessor.init(0, nullptr, nullptr));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(pp::Token::LAST, token.type);
+}
+
+TEST_F(InitTest, NullString)
+{
+    EXPECT_FALSE(mPreprocessor.init(1, nullptr, nullptr));
+}
+
+TEST(InputTest, DefaultConstructor)
+{
+    pp::Input input;
+    EXPECT_EQ(0u, input.count());
+    int lineNo = 0;
+    EXPECT_EQ(0u, input.read(nullptr, 1, &lineNo));
+}
+
+TEST(InputTest, NullLength)
+{
+    const char* str[] = {"foo"};
+    pp::Input input(1, str, nullptr);
+    EXPECT_EQ(3u, input.length(0));
+}
+
+TEST(InputTest, NegativeLength)
+{
+    const char* str[] = {"foo"};
+    int length[] = {-1};
+    pp::Input input(1, str, length);
+    EXPECT_EQ(3u, input.length(0));
+}
+
+TEST(InputTest, ActualLength)
+{
+    const char* str[] = {"foobar"};
+    int length[] = {3};
+    pp::Input input(1, str, length);
+    // Note that strlen(str[0]) != length[0].
+    // Even then Input should just accept any non-negative number.
+    EXPECT_EQ(static_cast<size_t>(length[0]), input.length(0));
+}
+
+TEST(InputTest, String)
+{
+    const char* str[] = {"foo"};
+    pp::Input input(1, str, nullptr);
+    EXPECT_STREQ(str[0], input.string(0));
+}
+
+TEST(InputTest, ReadSingleString)
+{
+    int count = 1;
+    const char* str[] = {"foo"};
+    char buf[4] = {'\0', '\0', '\0', '\0'};
+
+    int maxSize = 1;
+    int lineNo = 0;
+    pp::Input input1(count, str, nullptr);
+    EXPECT_EQ(1u, input1.read(buf, maxSize, &lineNo));
+    EXPECT_EQ('f', buf[0]);
+    EXPECT_EQ(1u, input1.read(buf, maxSize, &lineNo));
+    EXPECT_EQ('o', buf[0]);
+    EXPECT_EQ(1u, input1.read(buf, maxSize, &lineNo));
+    EXPECT_EQ('o', buf[0]);
+    EXPECT_EQ(0u, input1.read(buf, maxSize, &lineNo));
+
+    maxSize = 2;
+    pp::Input input2(count, str, nullptr);
+    EXPECT_EQ(2u, input2.read(buf, maxSize, &lineNo));
+    EXPECT_STREQ("fo", buf);
+    EXPECT_EQ(1u, input2.read(buf, maxSize, &lineNo));
+    EXPECT_EQ('o', buf[0]);
+    EXPECT_EQ(0u, input2.read(buf, maxSize, &lineNo));
+
+    maxSize = 3;
+    pp::Input input3(count, str, nullptr);
+    EXPECT_EQ(3u, input3.read(buf, maxSize, &lineNo));
+    EXPECT_STREQ("foo", buf);
+    EXPECT_EQ(0u, input3.read(buf, maxSize, &lineNo));
+
+    maxSize = 4;
+    pp::Input input4(count, str, nullptr);
+    EXPECT_EQ(3u, input4.read(buf, maxSize, &lineNo));
+    EXPECT_STREQ("foo", buf);
+    EXPECT_EQ(0u, input4.read(buf, maxSize, &lineNo));
+}
+
+TEST(InputTest, ReadMultipleStrings)
+{
+    int count = 3;
+    const char* str[] = {"f", "o", "o"};
+    char buf[4] = {'\0', '\0', '\0', '\0'};
+
+    int maxSize = 1;
+    int lineNo = 0;
+    pp::Input input1(count, str, nullptr);
+    EXPECT_EQ(1u, input1.read(buf, maxSize, &lineNo));
+    EXPECT_EQ('f', buf[0]);
+    EXPECT_EQ(1u, input1.read(buf, maxSize, &lineNo));
+    EXPECT_EQ('o', buf[0]);
+    EXPECT_EQ(1u, input1.read(buf, maxSize, &lineNo));
+    EXPECT_EQ('o', buf[0]);
+    EXPECT_EQ(0u, input1.read(buf, maxSize, &lineNo));
+
+    maxSize = 2;
+    pp::Input input2(count, str, nullptr);
+    EXPECT_EQ(2u, input2.read(buf, maxSize, &lineNo));
+    EXPECT_STREQ("fo", buf);
+    EXPECT_EQ(1u, input2.read(buf, maxSize, &lineNo));
+    EXPECT_EQ('o', buf[0]);
+    EXPECT_EQ(0u, input2.read(buf, maxSize, &lineNo));
+
+    maxSize = 3;
+    pp::Input input3(count, str, nullptr);
+    EXPECT_EQ(3u, input3.read(buf, maxSize, &lineNo));
+    EXPECT_STREQ("foo", buf);
+    EXPECT_EQ(0u, input3.read(buf, maxSize, &lineNo));
+
+    maxSize = 4;
+    pp::Input input4(count, str, nullptr);
+    EXPECT_EQ(3u, input4.read(buf, maxSize, &lineNo));
+    EXPECT_STREQ("foo", buf);
+    EXPECT_EQ(0u, input4.read(buf, maxSize, &lineNo));
+}
+
+TEST(InputTest, ReadStringsWithLength)
+{
+    int count = 2;
+    const char* str[] = {"foo", "bar"};
+    // Note that the length for the first string is 2 which is less than
+    // strlen(str[0]. We want to make sure that the last character is ignored.
+    int length[] = {2, 3};
+    char buf[6] = {'\0', '\0', '\0', '\0', '\0', '\0'};
+    size_t maxSize = 5;
+    int lineNo = 0;
+
+    pp::Input input(count, str, length);
+    EXPECT_EQ(maxSize, input.read(buf, maxSize, &lineNo));
+    EXPECT_STREQ("fobar", buf);
+}
+
+TEST(InputTest, ReadStringsWithLineContinuation)
+{
+    int count = 2;
+    const char* str[] = {"foo\\", "\nba\\\r\nr"};
+    int length[] = {4, 7};
+    char buf[11] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
+    size_t maxSize = 11;
+    int lineNo = 0;
+
+    pp::Input input(count, str, length);
+    EXPECT_EQ(3u, input.read(buf, maxSize, &lineNo));
+    EXPECT_EQ(0, lineNo);
+    EXPECT_EQ(2u, input.read(buf + 3, maxSize - 3, &lineNo));
+    EXPECT_EQ(1, lineNo);
+    EXPECT_EQ(1u, input.read(buf + 5, maxSize - 5, &lineNo));
+    EXPECT_EQ(2, lineNo);
+    EXPECT_STREQ("foobar", buf);
+}
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/location_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/location_test.cpp
new file mode 100644
index 0000000..e1a4d6c
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/location_test.cpp
@@ -0,0 +1,351 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+class LocationTest : public PreprocessorTest
+{
+protected:
+    void expectLocation(int count,
+                        const char* const string[],
+                        const int length[],
+                        const pp::SourceLocation& location)
+    {
+        ASSERT_TRUE(mPreprocessor.init(count, string, length));
+
+        pp::Token token;
+        mPreprocessor.lex(&token);
+        EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+        EXPECT_EQ("foo", token.text);
+
+        EXPECT_EQ(location.file, token.location.file);
+        EXPECT_EQ(location.line, token.location.line);
+    }
+};
+
+TEST_F(LocationTest, String0_Line1)
+{
+    const char* str = "foo";
+    pp::SourceLocation loc(0, 1);
+
+    SCOPED_TRACE("String0_Line1");
+    expectLocation(1, &str, nullptr, loc);
+}
+
+TEST_F(LocationTest, String0_Line2)
+{
+    const char* str = "\nfoo";
+    pp::SourceLocation loc(0, 2);
+
+    SCOPED_TRACE("String0_Line2");
+    expectLocation(1, &str, nullptr, loc);
+}
+
+TEST_F(LocationTest, String1_Line1)
+{
+    const char* const str[] = {"\n\n", "foo"};
+    pp::SourceLocation loc(1, 1);
+
+    SCOPED_TRACE("String1_Line1");
+    expectLocation(2, str, nullptr, loc);
+}
+
+TEST_F(LocationTest, String1_Line2)
+{
+    const char* const str[] = {"\n\n", "\nfoo"};
+    pp::SourceLocation loc(1, 2);
+
+    SCOPED_TRACE("String1_Line2");
+    expectLocation(2, str, nullptr, loc);
+}
+
+TEST_F(LocationTest, NewlineInsideCommentCounted)
+{
+    const char* str = "/*\n\n*/foo";
+    pp::SourceLocation loc(0, 3);
+
+    SCOPED_TRACE("NewlineInsideCommentCounted");
+    expectLocation(1, &str, nullptr, loc);
+}
+
+TEST_F(LocationTest, ErrorLocationAfterComment)
+{
+    const char* str = "/*\n\n*/@";
+
+    ASSERT_TRUE(mPreprocessor.init(1, &str, nullptr));
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_CHARACTER,
+                                    pp::SourceLocation(0, 3),
+                                    "@"));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+}
+
+// The location of a token straddling two or more strings is that of the
+// first character of the token.
+
+TEST_F(LocationTest, TokenStraddlingTwoStrings)
+{
+    const char* const str[] = {"f", "oo"};
+    pp::SourceLocation loc(0, 1);
+
+    SCOPED_TRACE("TokenStraddlingTwoStrings");
+    expectLocation(2, str, nullptr, loc);
+}
+
+TEST_F(LocationTest, TokenStraddlingThreeStrings)
+{
+    const char* const str[] = {"f", "o", "o"};
+    pp::SourceLocation loc(0, 1);
+
+    SCOPED_TRACE("TokenStraddlingThreeStrings");
+    expectLocation(3, str, nullptr, loc);
+}
+
+TEST_F(LocationTest, EndOfFileWithoutNewline)
+{
+    const char* const str[] = {"foo"};
+    ASSERT_TRUE(mPreprocessor.init(1, str, nullptr));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+    EXPECT_EQ("foo", token.text);
+    EXPECT_EQ(0, token.location.file);
+    EXPECT_EQ(1, token.location.line);
+
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(pp::Token::LAST, token.type);
+    EXPECT_EQ(0, token.location.file);
+    EXPECT_EQ(1, token.location.line);
+}
+
+TEST_F(LocationTest, EndOfFileAfterNewline)
+{
+    const char* const str[] = {"foo\n"};
+    ASSERT_TRUE(mPreprocessor.init(1, str, nullptr));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+    EXPECT_EQ("foo", token.text);
+    EXPECT_EQ(0, token.location.file);
+    EXPECT_EQ(1, token.location.line);
+
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(pp::Token::LAST, token.type);
+    EXPECT_EQ(0, token.location.file);
+    EXPECT_EQ(2, token.location.line);
+}
+
+TEST_F(LocationTest, EndOfFileAfterEmptyString)
+{
+    const char* const str[] = {"foo\n", "\n", ""};
+    ASSERT_TRUE(mPreprocessor.init(3, str, nullptr));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+    EXPECT_EQ("foo", token.text);
+    EXPECT_EQ(0, token.location.file);
+    EXPECT_EQ(1, token.location.line);
+
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(pp::Token::LAST, token.type);
+    EXPECT_EQ(2, token.location.file);
+    EXPECT_EQ(1, token.location.line);
+}
+
+TEST_F(LocationTest, ValidLineDirective1)
+{
+    const char* str = "#line 10\n"
+                      "foo";
+    pp::SourceLocation loc(0, 10);
+
+    SCOPED_TRACE("ValidLineDirective1");
+    expectLocation(1, &str, nullptr, loc);
+}
+
+TEST_F(LocationTest, ValidLineDirective2)
+{
+    const char* str = "#line 10 20\n"
+                      "foo";
+    pp::SourceLocation loc(20, 10);
+
+    SCOPED_TRACE("ValidLineDirective2");
+    expectLocation(1, &str, nullptr, loc);
+}
+
+TEST_F(LocationTest, LineDirectiveCommentsIgnored)
+{
+    const char* str = "/* bar */"
+                      "#"
+                      "/* bar */"
+                      "line"
+                      "/* bar */"
+                      "10"
+                      "/* bar */"
+                      "20"
+                      "/* bar */"
+                      "// bar   "
+                      "\n"
+                      "foo";
+    pp::SourceLocation loc(20, 10);
+
+    SCOPED_TRACE("LineDirectiveCommentsIgnored");
+    expectLocation(1, &str, nullptr, loc);
+}
+
+TEST_F(LocationTest, LineDirectiveWithMacro1)
+{
+    const char* str = "#define L 10\n"
+                      "#define F(x) x\n"
+                      "#line L F(20)\n"
+                      "foo";
+    pp::SourceLocation loc(20, 10);
+
+    SCOPED_TRACE("LineDirectiveWithMacro1");
+    expectLocation(1, &str, nullptr, loc);
+}
+
+TEST_F(LocationTest, LineDirectiveWithMacro2)
+{
+    const char* str = "#define LOC 10 20\n"
+                      "#line LOC\n"
+                      "foo";
+    pp::SourceLocation loc(20, 10);
+
+    SCOPED_TRACE("LineDirectiveWithMacro2");
+    expectLocation(1, &str, nullptr, loc);
+}
+
+TEST_F(LocationTest, LineDirectiveWithPredefinedMacro)
+{
+    const char* str = "#line __LINE__ __FILE__\n"
+                      "foo";
+    pp::SourceLocation loc(0, 1);
+
+    SCOPED_TRACE("LineDirectiveWithMacro");
+    expectLocation(1, &str, nullptr, loc);
+}
+
+TEST_F(LocationTest, LineDirectiveNewlineBeforeStringBreak)
+{
+    const char* const str[] = {"#line 10 20\n", "foo"};
+    // String number is incremented after it is set by the line directive.
+    // Also notice that line number is reset after the string break.
+    pp::SourceLocation loc(21, 1);
+
+    SCOPED_TRACE("LineDirectiveNewlineBeforeStringBreak");
+    expectLocation(2, str, nullptr, loc);
+}
+
+TEST_F(LocationTest, LineDirectiveNewlineAfterStringBreak)
+{
+    const char* const str[] = {"#line 10 20", "\nfoo"};
+    // String number is incremented before it is set by the line directive.
+    pp::SourceLocation loc(20, 10);
+
+    SCOPED_TRACE("LineDirectiveNewlineAfterStringBreak");
+    expectLocation(2, str, nullptr, loc);
+}
+
+TEST_F(LocationTest, LineDirectiveMissingNewline)
+{
+    const char* str = "#line 10";
+    ASSERT_TRUE(mPreprocessor.init(1, &str, nullptr));
+
+    using testing::_;
+    // Error reported about EOF.
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_EOF_IN_DIRECTIVE, _, _));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+}
+
+struct LineTestParam
+{
+    const char* str;
+    pp::Diagnostics::ID id;
+};
+
+class InvalidLineTest : public LocationTest,
+                        public testing::WithParamInterface<LineTestParam>
+{
+};
+
+TEST_P(InvalidLineTest, Identified)
+{
+    LineTestParam param = GetParam();
+    ASSERT_TRUE(mPreprocessor.init(1, &param.str, nullptr));
+
+    using testing::_;
+    // Invalid line directive call.
+    EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+}
+
+static const LineTestParam kParams[] = {
+    {"#line\n", pp::Diagnostics::PP_INVALID_LINE_DIRECTIVE},
+    {"#line foo\n", pp::Diagnostics::PP_INVALID_LINE_NUMBER},
+    {"#line defined(foo)\n", pp::Diagnostics::PP_INVALID_LINE_NUMBER},
+    {"#line 10 foo\n", pp::Diagnostics::PP_INVALID_FILE_NUMBER},
+    {"#line 10 20 foo\n", pp::Diagnostics::PP_UNEXPECTED_TOKEN},
+    {"#line 0xffffffff\n", pp::Diagnostics::PP_INTEGER_OVERFLOW},
+    {"#line 10 0xffffffff\n", pp::Diagnostics::PP_INTEGER_OVERFLOW}};
+
+INSTANTIATE_TEST_CASE_P(All, InvalidLineTest, testing::ValuesIn(kParams));
+
+struct LineExpressionTestParam
+{
+    const char *expression;
+    int expectedLine;
+};
+
+class LineExpressionTest : public LocationTest,
+                           public testing::WithParamInterface<LineExpressionTestParam>
+{
+};
+
+TEST_P(LineExpressionTest, ExpressionEvaluation)
+{
+    LineExpressionTestParam param = GetParam();
+    const char *strs[3] = {"#line ", param.expression, "\nfoo"};
+
+    pp::SourceLocation loc(2, param.expectedLine);
+
+    expectLocation(3, strs, nullptr, loc);
+}
+
+static const LineExpressionTestParam kParamsLineExpressionTest[] = {
+    {"1 + 2", 3},
+    {"5 - 3", 2},
+    {"7 * 11", 77},
+    {"20 / 10", 2},
+    {"10 % 5", 0},
+    {"7 && 3", 1},
+    {"7 || 0", 1},
+    {"11 == 11", 1},
+    {"11 != 11", 0},
+    {"11 > 7", 1},
+    {"11 < 7", 0},
+    {"11 >= 7", 1},
+    {"11 <= 7", 0},
+    {"!11", 0},
+    {"-1", -1},
+    {"+9", 9},
+    {"(1 + 2) * 4", 12},
+    {"3 | 5", 7},
+    {"3 ^ 5", 6},
+    {"3 & 5", 1},
+    {"~5", ~5},
+    {"2 << 3", 16},
+    {"16 >> 2", 4}};
+
+INSTANTIATE_TEST_CASE_P(All, LineExpressionTest, testing::ValuesIn(kParamsLineExpressionTest));
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/number_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/number_test.cpp
new file mode 100644
index 0000000..6644120
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/number_test.cpp
@@ -0,0 +1,164 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+#define CLOSED_RANGE(x, y) testing::Range(x, static_cast<char>((y) + 1))
+
+class InvalidNumberTest : public SimplePreprocessorTest,
+                          public testing::WithParamInterface<const char *>
+{
+};
+
+TEST_P(InvalidNumberTest, InvalidNumberIdentified)
+{
+    const char* str = GetParam();
+
+    using testing::_;
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_NUMBER, _, str));
+
+    preprocess(str);
+}
+
+INSTANTIATE_TEST_CASE_P(InvalidIntegers, InvalidNumberTest,
+                        testing::Values("1a", "08", "0xG"));
+
+
+INSTANTIATE_TEST_CASE_P(InvalidFloats, InvalidNumberTest,
+                        testing::Values("1eg", "0.a", "0.1.2", ".0a", ".0.1"));
+
+typedef std::tr1::tuple<const char*, char> IntegerParams;
+class IntegerTest : public SimplePreprocessorTest, public testing::WithParamInterface<IntegerParams>
+{
+};
+
+TEST_P(IntegerTest, Identified)
+{
+    std::string str(std::tr1::get<0>(GetParam()));  // prefix.
+    str.push_back(std::tr1::get<1>(GetParam()));  // digit.
+    const char* cstr = str.c_str();
+
+    pp::Token token;
+    lexSingleToken(cstr, &token);
+    EXPECT_EQ(pp::Token::CONST_INT, token.type);
+    EXPECT_EQ(str, token.text);
+}
+
+INSTANTIATE_TEST_CASE_P(DecimalInteger,
+                        IntegerTest,
+                        testing::Combine(testing::Values(""),
+                                         CLOSED_RANGE('0', '9')));
+
+INSTANTIATE_TEST_CASE_P(OctalInteger,
+                        IntegerTest,
+                        testing::Combine(testing::Values("0"),
+                                         CLOSED_RANGE('0', '7')));
+
+INSTANTIATE_TEST_CASE_P(HexadecimalInteger_0_9,
+                        IntegerTest,
+                        testing::Combine(testing::Values("0x", "0X"),
+                                         CLOSED_RANGE('0', '9')));
+
+INSTANTIATE_TEST_CASE_P(HexadecimalInteger_a_f,
+                        IntegerTest,
+                        testing::Combine(testing::Values("0x", "0X"),
+                                         CLOSED_RANGE('a', 'f')));
+
+INSTANTIATE_TEST_CASE_P(HexadecimalInteger_A_F,
+                        IntegerTest,
+                        testing::Combine(testing::Values("0x", "0X"),
+                                         CLOSED_RANGE('A', 'F')));
+
+class FloatTest : public SimplePreprocessorTest
+{
+  protected:
+    void expectFloat(const std::string& str)
+    {
+        const char* cstr = str.c_str();
+
+        pp::Token token;
+        lexSingleToken(cstr, &token);
+        EXPECT_EQ(pp::Token::CONST_FLOAT, token.type);
+        EXPECT_EQ(str, token.text);
+    }
+};
+
+typedef std::tr1::tuple<char, char, const char*, char> FloatScientificParams;
+class FloatScientificTest :
+    public FloatTest,
+    public testing::WithParamInterface<FloatScientificParams>
+{
+};
+
+// This test covers floating point numbers of form [0-9][eE][+-]?[0-9].
+TEST_P(FloatScientificTest, FloatIdentified)
+{
+    std::string str;
+    str.push_back(std::tr1::get<0>(GetParam()));  // significand [0-9].
+    str.push_back(std::tr1::get<1>(GetParam()));  // separator [eE].
+    str.append(std::tr1::get<2>(GetParam()));  // sign [" " "+" "-"].
+    str.push_back(std::tr1::get<3>(GetParam()));  // exponent [0-9].
+
+    SCOPED_TRACE("FloatScientificTest");
+    expectFloat(str);
+}
+
+INSTANTIATE_TEST_CASE_P(FloatScientific,
+                        FloatScientificTest,
+                        testing::Combine(CLOSED_RANGE('0', '9'),
+                                         testing::Values('e', 'E'),
+                                         testing::Values("", "+", "-"),
+                                         CLOSED_RANGE('0', '9')));
+
+typedef std::tr1::tuple<char, char> FloatFractionParams;
+class FloatFractionTest :
+    public FloatTest,
+    public testing::WithParamInterface<FloatFractionParams>
+{
+};
+
+// This test covers floating point numbers of form [0-9]"." and [0-9]?"."[0-9].
+TEST_P(FloatFractionTest, FloatIdentified)
+{
+    std::string str;
+
+    char significand = std::tr1::get<0>(GetParam());
+    if (significand != '\0')
+        str.push_back(significand);
+
+    str.push_back('.');
+
+    char fraction = std::tr1::get<1>(GetParam());
+    if (fraction != '\0')
+        str.push_back(fraction);
+
+    SCOPED_TRACE("FloatFractionTest");
+    expectFloat(str);
+}
+
+INSTANTIATE_TEST_CASE_P(FloatFraction_X_X,
+                        FloatFractionTest,
+                        testing::Combine(CLOSED_RANGE('0', '9'),
+                                         CLOSED_RANGE('0', '9')));
+
+INSTANTIATE_TEST_CASE_P(FloatFraction_0_X,
+                        FloatFractionTest,
+                        testing::Combine(testing::Values('\0'),
+                                         CLOSED_RANGE('0', '9')));
+
+INSTANTIATE_TEST_CASE_P(FloatFraction_X_0,
+                        FloatFractionTest,
+                        testing::Combine(CLOSED_RANGE('0', '9'),
+                                         testing::Values('\0')));
+
+// In the tests above we have tested individual parts of a float separately.
+// This test has all parts of a float.
+TEST_F(FloatTest, FractionScientific)
+{
+    SCOPED_TRACE("FractionScientific");
+    expectFloat("0.1e+2");
+}
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/operator_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/operator_test.cpp
new file mode 100644
index 0000000..a6d9f83
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/operator_test.cpp
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+struct OperatorTestParam
+{
+    const char* str;
+    int op;
+};
+
+class OperatorTest : public SimplePreprocessorTest,
+                     public testing::WithParamInterface<OperatorTestParam>
+{
+};
+
+TEST_P(OperatorTest, Identified)
+{
+    OperatorTestParam param = GetParam();
+
+    pp::Token token;
+    lexSingleToken(param.str, &token);
+    EXPECT_EQ(param.op, token.type);
+    EXPECT_EQ(param.str, token.text);
+}
+
+static const OperatorTestParam kOperators[] = {
+    {"(", '('},
+    {")", ')'},
+    {"[", '['},
+    {"]", ']'},
+    {".", '.'},
+    {"+", '+'},
+    {"-", '-'},
+    {"~", '~'},
+    {"!", '!'},
+    {"*", '*'},
+    {"/", '/'},
+    {"%", '%'},
+    {"<", '<'},
+    {">", '>'},
+    {"&", '&'},
+    {"^", '^'},
+    {"|", '|'},
+    {"?", '?'},
+    {":", ':'},
+    {"=", '='},
+    {",", ','},
+    {"++",  pp::Token::OP_INC},
+    {"--",  pp::Token::OP_DEC},
+    {"<<",  pp::Token::OP_LEFT},
+    {">>",  pp::Token::OP_RIGHT},
+    {"<=",  pp::Token::OP_LE},
+    {">=",  pp::Token::OP_GE},
+    {"==",  pp::Token::OP_EQ},
+    {"!=",  pp::Token::OP_NE},
+    {"&&",  pp::Token::OP_AND},
+    {"^^",  pp::Token::OP_XOR},
+    {"||",  pp::Token::OP_OR},
+    {"+=",  pp::Token::OP_ADD_ASSIGN},
+    {"-=",  pp::Token::OP_SUB_ASSIGN},
+    {"*=",  pp::Token::OP_MUL_ASSIGN},
+    {"/=",  pp::Token::OP_DIV_ASSIGN},
+    {"%=",  pp::Token::OP_MOD_ASSIGN},
+    {"<<=", pp::Token::OP_LEFT_ASSIGN},
+    {">>=", pp::Token::OP_RIGHT_ASSIGN},
+    {"&=",  pp::Token::OP_AND_ASSIGN},
+    {"^=",  pp::Token::OP_XOR_ASSIGN},
+    {"|=",  pp::Token::OP_OR_ASSIGN}
+};
+
+INSTANTIATE_TEST_CASE_P(All, OperatorTest,
+                        testing::ValuesIn(kOperators));
+
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/pragma_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/pragma_test.cpp
new file mode 100644
index 0000000..dad88cb
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/pragma_test.cpp
@@ -0,0 +1,154 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+class PragmaTest : public SimplePreprocessorTest
+{
+};
+
+TEST_F(PragmaTest, EmptyName)
+{
+    const char* str = "#pragma\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    // No handlePragma calls.
+    EXPECT_CALL(mDirectiveHandler, handlePragma(_, _, _, false)).Times(0);
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(PragmaTest, EmptyValue)
+{
+    const char* str = "#pragma foo\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handlePragma(pp::SourceLocation(0, 1), "foo", "", false));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(PragmaTest, NameValue)
+{
+    const char* str = "#pragma foo(bar)\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handlePragma(pp::SourceLocation(0, 1), "foo", "bar", false));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(PragmaTest, STDGL)
+{
+    const char* str = "#pragma STDGL\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handlePragma(_, _, _, _)).Times(0);
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(PragmaTest, STDGLInvariantAll)
+{
+    const char* str = "#pragma STDGL invariant(all)\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handlePragma(pp::SourceLocation(0, 1), "invariant", "all", true));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(PragmaTest, Comments)
+{
+    const char* str = "/*foo*/"
+                      "#"
+                      "/*foo*/"
+                      "pragma"
+                      "/*foo*/"
+                      "foo"
+                      "/*foo*/"
+                      "("
+                      "/*foo*/"
+                      "bar"
+                      "/*foo*/"
+                      ")"
+                      "/*foo*/"
+                      "//foo"
+                      "\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handlePragma(pp::SourceLocation(0, 1), "foo", "bar", false));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(PragmaTest, MissingNewline)
+{
+    const char* str = "#pragma foo(bar)";
+    const char* expected = "";
+
+    using testing::_;
+    // Pragma successfully parsed.
+    EXPECT_CALL(mDirectiveHandler,
+                handlePragma(pp::SourceLocation(0, 1), "foo", "bar", false));
+    // Error reported about EOF.
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_EOF_IN_DIRECTIVE, _, _));
+
+    preprocess(str, expected);
+}
+
+class InvalidPragmaTest : public PragmaTest,
+                          public testing::WithParamInterface<const char*>
+{
+};
+
+TEST_P(InvalidPragmaTest, Identified)
+{
+    const char* str = GetParam();
+    const char* expected = "\n";
+
+    using testing::_;
+    // No handlePragma calls.
+    EXPECT_CALL(mDirectiveHandler, handlePragma(_, _, _, false)).Times(0);
+    // Unrecognized pragma warning.
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA,
+                      pp::SourceLocation(0, 1), _));
+
+    preprocess(str, expected);
+}
+
+INSTANTIATE_TEST_CASE_P(All, InvalidPragmaTest, testing::Values(
+    "#pragma 1\n",               // Invalid name.
+    "#pragma foo()\n",           // Missing value.
+    "#pragma foo bar)\n",        // Missing left paren,
+    "#pragma foo(bar\n",         // Missing right paren.
+    "#pragma foo bar\n",         // Missing parens.
+    "#pragma foo(bar) baz\n"));  // Extra tokens.
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/space_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/space_test.cpp
new file mode 100644
index 0000000..0c3494b
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/space_test.cpp
@@ -0,0 +1,106 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+class SpaceTest : public PreprocessorTest
+{
+  protected:
+    void expectSpace(const std::string& str)
+    {
+        const char* cstr = str.c_str();
+        ASSERT_TRUE(mPreprocessor.init(1, &cstr, 0));
+
+        pp::Token token;
+        // "foo" is returned after ignoring the whitespace characters.
+        mPreprocessor.lex(&token);
+        EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+        EXPECT_EQ("foo", token.text);
+        // The whitespace character is however recorded with the next token.
+        EXPECT_TRUE(token.hasLeadingSpace());
+    }
+};
+
+// Whitespace characters allowed in GLSL.
+// Note that newline characters (\n) will be tested separately.
+static const char kSpaceChars[] = {' ', '\t', '\v', '\f'};
+
+// This test fixture tests the processing of a single whitespace character.
+// All tests in this fixture are ran with all possible whitespace character
+// allowed in GLSL.
+class SpaceCharTest : public SpaceTest,
+                      public testing::WithParamInterface<char>
+{
+};
+
+TEST_P(SpaceCharTest, SpaceIgnored)
+{
+    // Construct test string with the whitespace char before "foo".
+    std::string str(1, GetParam());
+    str.append("foo");
+
+    expectSpace(str);
+}
+
+INSTANTIATE_TEST_CASE_P(SingleSpaceChar,
+                        SpaceCharTest,
+                        testing::ValuesIn(kSpaceChars));
+
+// This test fixture tests the processing of a string containing consecutive
+// whitespace characters. All tests in this fixture are ran with all possible
+// combinations of whitespace characters allowed in GLSL.
+typedef std::tr1::tuple<char, char, char> SpaceStringParams;
+class SpaceStringTest : public SpaceTest,
+                        public testing::WithParamInterface<SpaceStringParams>
+{
+};
+
+TEST_P(SpaceStringTest, SpaceIgnored)
+{
+    // Construct test string with the whitespace char before "foo".
+    std::string str;
+    str.push_back(std::tr1::get<0>(GetParam()));
+    str.push_back(std::tr1::get<1>(GetParam()));
+    str.push_back(std::tr1::get<2>(GetParam()));
+    str.append("foo");
+
+    expectSpace(str);
+}
+
+INSTANTIATE_TEST_CASE_P(SpaceCharCombination,
+                        SpaceStringTest,
+                        testing::Combine(testing::ValuesIn(kSpaceChars),
+                                         testing::ValuesIn(kSpaceChars),
+                                         testing::ValuesIn(kSpaceChars)));
+
+// The tests above make sure that the space char is recorded in the
+// next token. This test makes sure that a token is not incorrectly marked
+// to have leading space.
+TEST_F(SpaceTest, LeadingSpace)
+{
+    const char* str = " foo+ -bar";
+    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+    EXPECT_EQ("foo", token.text);
+    EXPECT_TRUE(token.hasLeadingSpace());
+
+    mPreprocessor.lex(&token);
+    EXPECT_EQ('+', token.type);
+    EXPECT_FALSE(token.hasLeadingSpace());
+
+    mPreprocessor.lex(&token);
+    EXPECT_EQ('-', token.type);
+    EXPECT_TRUE(token.hasLeadingSpace());
+
+    mPreprocessor.lex(&token);
+    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+    EXPECT_EQ("bar", token.text);
+    EXPECT_FALSE(token.hasLeadingSpace());
+}
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/token_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/token_test.cpp
new file mode 100644
index 0000000..106647c
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/token_test.cpp
@@ -0,0 +1,90 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gtest/gtest.h"
+
+#include "compiler/preprocessor/Token.h"
+
+TEST(TokenTest, DefaultConstructor)
+{
+    pp::Token token;
+    EXPECT_EQ(0, token.type);
+    EXPECT_EQ(0u, token.flags);
+    EXPECT_EQ(0, token.location.line);
+    EXPECT_EQ(0, token.location.file);
+    EXPECT_EQ("", token.text);
+}
+
+TEST(TokenTest, Assignment)
+{
+    pp::Token token;
+    token.type = 1;
+    token.flags = 1;
+    token.location.line = 1;
+    token.location.file = 1;
+    token.text.assign("foo");
+
+    token = pp::Token();
+    EXPECT_EQ(0, token.type);
+    EXPECT_EQ(0u, token.flags);
+    EXPECT_EQ(0, token.location.line);
+    EXPECT_EQ(0, token.location.file);
+    EXPECT_EQ("", token.text);
+}
+
+TEST(TokenTest, Equals)
+{
+    pp::Token token;
+    EXPECT_TRUE(token.equals(pp::Token()));
+
+    token.type = 1;
+    EXPECT_FALSE(token.equals(pp::Token()));
+    token.type = 0;
+
+    token.flags = 1;
+    EXPECT_FALSE(token.equals(pp::Token()));
+    token.flags = 0;
+
+    token.location.line = 1;
+    EXPECT_FALSE(token.equals(pp::Token()));
+    token.location.line = 0;
+
+    token.location.file = 1;
+    EXPECT_FALSE(token.equals(pp::Token()));
+    token.location.file = 0;
+
+    token.text.assign("foo");
+    EXPECT_FALSE(token.equals(pp::Token()));
+    token.text.clear();
+
+    EXPECT_TRUE(token.equals(pp::Token()));
+}
+
+TEST(TokenTest, HasLeadingSpace)
+{
+    pp::Token token;
+    EXPECT_FALSE(token.hasLeadingSpace());
+    token.setHasLeadingSpace(true);
+    EXPECT_TRUE(token.hasLeadingSpace());
+    token.setHasLeadingSpace(false);
+    EXPECT_FALSE(token.hasLeadingSpace());
+}
+
+TEST(TokenTest, Write)
+{
+    pp::Token token;
+    token.text.assign("foo");
+    std::stringstream out1;
+    out1 << token;
+    EXPECT_TRUE(out1.good());
+    EXPECT_EQ("foo", out1.str());
+
+    token.setHasLeadingSpace(true);
+    std::stringstream out2;
+    out2 << token;
+    EXPECT_TRUE(out2.good());
+    EXPECT_EQ(" foo", out2.str());
+}
diff --git a/src/third_party/angle/src/tests/preprocessor_tests/version_test.cpp b/src/third_party/angle/src/tests/preprocessor_tests/version_test.cpp
new file mode 100644
index 0000000..780c534
--- /dev/null
+++ b/src/third_party/angle/src/tests/preprocessor_tests/version_test.cpp
@@ -0,0 +1,204 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PreprocessorTest.h"
+#include "compiler/preprocessor/Token.h"
+
+class VersionTest : public SimplePreprocessorTest
+{
+};
+
+TEST_F(VersionTest, Valid)
+{
+    const char* str = "#version 200\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handleVersion(pp::SourceLocation(0, 1), 200));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(VersionTest, CommentsIgnored)
+{
+    const char* str = "/*foo*/"
+                      "#"
+                      "/*foo*/"
+                      "version"
+                      "/*foo*/"
+                      "200"
+                      "/*foo*/"
+                      "//foo"
+                      "\n";
+    const char* expected = "\n";
+
+    using testing::_;
+    EXPECT_CALL(mDirectiveHandler,
+                handleVersion(pp::SourceLocation(0, 1), 200));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+    preprocess(str, expected);
+}
+
+TEST_F(VersionTest, MissingNewline)
+{
+    const char* str = "#version 200";
+    const char* expected = "";
+
+    using testing::_;
+    // Directive successfully parsed.
+    EXPECT_CALL(mDirectiveHandler,
+                handleVersion(pp::SourceLocation(0, 1), 200));
+    // Error reported about EOF.
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_EOF_IN_DIRECTIVE, _, _));
+
+    preprocess(str, expected);
+}
+
+TEST_F(VersionTest, AfterComments)
+{
+    const char* str = "/* block comment acceptable */\n"
+                      "// line comment acceptable\n"
+                      "#version 200\n";
+    const char* expected = "\n\n\n";
+
+    using testing::_;
+    // Directive successfully parsed.
+    EXPECT_CALL(mDirectiveHandler,
+                handleVersion(pp::SourceLocation(0, 3), 200));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+    
+    preprocess(str, expected);
+}
+
+TEST_F(VersionTest, AfterWhitespace)
+{
+    const char* str = "\n"
+                      "\n"
+                      "#version 200\n";
+    const char* expected = "\n\n\n";
+
+    using testing::_;
+    // Directive successfully parsed.
+    EXPECT_CALL(mDirectiveHandler,
+                handleVersion(pp::SourceLocation(0, 3), 200));
+    // No error or warning.
+    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+    
+    preprocess(str, expected);
+}
+
+TEST_F(VersionTest, AfterValidToken)
+{
+    const char* str = "foo\n"
+                      "#version 200\n";
+
+    using testing::_;
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
+                      pp::SourceLocation(0, 2), _));
+
+    preprocess(str);
+}
+
+TEST_F(VersionTest, AfterInvalidToken)
+{
+    const char* str = "$\n"
+                      "#version 200\n";
+
+    using testing::_;
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_INVALID_CHARACTER,
+                      pp::SourceLocation(0, 1), "$"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
+                      pp::SourceLocation(0, 2), _));
+
+    preprocess(str);
+}
+
+TEST_F(VersionTest, AfterValidDirective)
+{
+    const char* str = "#\n"
+                      "#version 200\n";
+
+    using testing::_;
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
+                      pp::SourceLocation(0, 2), _));
+
+    preprocess(str);
+}
+
+TEST_F(VersionTest, AfterInvalidDirective)
+{
+    const char* str = "#foo\n"
+                      "#version 200\n";
+
+    using testing::_;
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_DIRECTIVE_INVALID_NAME,
+                      pp::SourceLocation(0, 1), "foo"));
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
+                      pp::SourceLocation(0, 2), _));
+
+    preprocess(str);
+}
+
+TEST_F(VersionTest, AfterExcludedBlock)
+{
+    const char* str = "#if 0\n"
+                      "foo\n"
+                      "#endif\n"
+                      "#version 200\n";
+
+    using testing::_;
+    EXPECT_CALL(mDiagnostics,
+                print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
+                      pp::SourceLocation(0, 4), _));
+
+    preprocess(str);
+}
+
+struct VersionTestParam
+{
+    const char* str;
+    pp::Diagnostics::ID id;
+};
+
+class InvalidVersionTest : public VersionTest,
+                           public testing::WithParamInterface<VersionTestParam>
+{
+};
+
+TEST_P(InvalidVersionTest, Identified)
+{
+    VersionTestParam param = GetParam();
+    const char* expected = "\n";
+
+    using testing::_;
+    // No handleVersion call.
+    EXPECT_CALL(mDirectiveHandler, handleVersion(_, _)).Times(0);
+    // Invalid version directive call.
+    EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
+
+    preprocess(param.str, expected);
+}
+
+static const VersionTestParam kParams[] = {
+    {"#version\n", pp::Diagnostics::PP_INVALID_VERSION_DIRECTIVE},
+    {"#version foo\n", pp::Diagnostics::PP_INVALID_VERSION_NUMBER},
+    {"#version 100 foo\n", pp::Diagnostics::PP_UNEXPECTED_TOKEN},
+    {"#version 0xffffffff\n", pp::Diagnostics::PP_INTEGER_OVERFLOW}
+};
+
+INSTANTIATE_TEST_CASE_P(All, InvalidVersionTest, testing::ValuesIn(kParams));
diff --git a/src/third_party/angle/src/tests/test_utils/ANGLETest.cpp b/src/third_party/angle/src/tests/test_utils/ANGLETest.cpp
new file mode 100644
index 0000000..5d6e504
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/ANGLETest.cpp
@@ -0,0 +1,968 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLETest:
+//   Implementation of common ANGLE testing fixture.
+//
+
+#include "ANGLETest.h"
+#include "EGLWindow.h"
+#include "OSWindow.h"
+#include "platform/Platform.h"
+
+namespace angle
+{
+
+const GLColorRGB GLColorRGB::black(0u, 0u, 0u);
+const GLColorRGB GLColorRGB::blue(0u, 0u, 255u);
+const GLColorRGB GLColorRGB::green(0u, 255u, 0u);
+const GLColorRGB GLColorRGB::red(255u, 0u, 0u);
+const GLColorRGB GLColorRGB::yellow(255u, 255u, 0);
+
+const GLColor GLColor::black            = GLColor(0u, 0u, 0u, 255u);
+const GLColor GLColor::blue             = GLColor(0u, 0u, 255u, 255u);
+const GLColor GLColor::cyan             = GLColor(0u, 255u, 255u, 255u);
+const GLColor GLColor::green            = GLColor(0u, 255u, 0u, 255u);
+const GLColor GLColor::red              = GLColor(255u, 0u, 0u, 255u);
+const GLColor GLColor::transparentBlack = GLColor(0u, 0u, 0u, 0u);
+const GLColor GLColor::white            = GLColor(255u, 255u, 255u, 255u);
+const GLColor GLColor::yellow           = GLColor(255u, 255u, 0, 255u);
+const GLColor GLColor::magenta          = GLColor(255u, 0u, 255u, 255u);
+
+namespace
+{
+float ColorNorm(GLubyte channelValue)
+{
+    return static_cast<float>(channelValue) / 255.0f;
+}
+
+GLubyte ColorDenorm(float colorValue)
+{
+    return static_cast<GLubyte>(colorValue * 255.0f);
+}
+
+void TestPlatform_logError(angle::PlatformMethods *platform, const char *errorMessage)
+{
+    auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
+    if (testPlatformContext->ignoreMessages)
+        return;
+
+    FAIL() << errorMessage;
+}
+
+void TestPlatform_logWarning(angle::PlatformMethods *platform, const char *warningMessage)
+{
+    auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
+    if (testPlatformContext->ignoreMessages)
+        return;
+
+    std::cerr << "Warning: " << warningMessage << std::endl;
+}
+
+void TestPlatform_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
+{
+    auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
+    if (testPlatformContext->ignoreMessages)
+        return;
+
+    angle::WriteDebugMessage("%s\n", infoMessage);
+}
+
+void TestPlatform_overrideWorkaroundsD3D(angle::PlatformMethods *platform,
+                                         WorkaroundsD3D *workaroundsD3D)
+{
+    auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
+    if (testPlatformContext->currentTest)
+    {
+        testPlatformContext->currentTest->overrideWorkaroundsD3D(workaroundsD3D);
+    }
+}
+
+std::array<angle::Vector3, 4> GetIndexedQuadVertices()
+{
+    std::array<angle::Vector3, 4> vertices;
+    vertices[0] = angle::Vector3(-1.0f, 1.0f, 0.5f);
+    vertices[1] = angle::Vector3(-1.0f, -1.0f, 0.5f);
+    vertices[2] = angle::Vector3(1.0f, -1.0f, 0.5f);
+    vertices[3] = angle::Vector3(1.0f, 1.0f, 0.5f);
+    return vertices;
+}
+
+}  // anonymous namespace
+
+GLColorRGB::GLColorRGB() : R(0), G(0), B(0)
+{
+}
+
+GLColorRGB::GLColorRGB(GLubyte r, GLubyte g, GLubyte b) : R(r), G(g), B(b)
+{
+}
+
+GLColorRGB::GLColorRGB(const angle::Vector3 &floatColor)
+    : R(ColorDenorm(floatColor.x())), G(ColorDenorm(floatColor.y())), B(ColorDenorm(floatColor.z()))
+{
+}
+
+GLColor::GLColor() : R(0), G(0), B(0), A(0)
+{
+}
+
+GLColor::GLColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a) : R(r), G(g), B(b), A(a)
+{
+}
+
+GLColor::GLColor(const angle::Vector4 &floatColor)
+    : R(ColorDenorm(floatColor.x())),
+      G(ColorDenorm(floatColor.y())),
+      B(ColorDenorm(floatColor.z())),
+      A(ColorDenorm(floatColor.w()))
+{
+}
+
+GLColor::GLColor(GLuint colorValue) : R(0), G(0), B(0), A(0)
+{
+    memcpy(&R, &colorValue, sizeof(GLuint));
+}
+
+angle::Vector4 GLColor::toNormalizedVector() const
+{
+    return angle::Vector4(ColorNorm(R), ColorNorm(G), ColorNorm(B), ColorNorm(A));
+}
+
+GLColor32F::GLColor32F() : GLColor32F(0.0f, 0.0f, 0.0f, 0.0f)
+{
+}
+
+GLColor32F::GLColor32F(GLfloat r, GLfloat g, GLfloat b, GLfloat a) : R(r), G(g), B(b), A(a)
+{
+}
+
+GLColor ReadColor(GLint x, GLint y)
+{
+    GLColor actual;
+    glReadPixels((x), (y), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &actual.R);
+    EXPECT_GL_NO_ERROR();
+    return actual;
+}
+
+bool operator==(const GLColor &a, const GLColor &b)
+{
+    return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
+}
+
+std::ostream &operator<<(std::ostream &ostream, const GLColor &color)
+{
+    ostream << "(" << static_cast<unsigned int>(color.R) << ", "
+            << static_cast<unsigned int>(color.G) << ", " << static_cast<unsigned int>(color.B)
+            << ", " << static_cast<unsigned int>(color.A) << ")";
+    return ostream;
+}
+
+bool operator==(const GLColor32F &a, const GLColor32F &b)
+{
+    return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
+}
+
+std::ostream &operator<<(std::ostream &ostream, const GLColor32F &color)
+{
+    ostream << "(" << color.R << ", " << color.G << ", " << color.B << ", " << color.A << ")";
+    return ostream;
+}
+
+GLColor32F ReadColor32F(GLint x, GLint y)
+{
+    GLColor32F actual;
+    glReadPixels((x), (y), 1, 1, GL_RGBA, GL_FLOAT, &actual.R);
+    EXPECT_GL_NO_ERROR();
+    return actual;
+}
+
+}  // namespace angle
+
+// static
+std::array<angle::Vector3, 6> ANGLETest::GetQuadVertices()
+{
+    std::array<angle::Vector3, 6> vertices;
+    vertices[0] = angle::Vector3(-1.0f, 1.0f, 0.5f);
+    vertices[1] = angle::Vector3(-1.0f, -1.0f, 0.5f);
+    vertices[2] = angle::Vector3(1.0f, -1.0f, 0.5f);
+    vertices[3] = angle::Vector3(-1.0f, 1.0f, 0.5f);
+    vertices[4] = angle::Vector3(1.0f, -1.0f, 0.5f);
+    vertices[5] = angle::Vector3(1.0f, 1.0f, 0.5f);
+    return vertices;
+}
+
+ANGLETest::ANGLETest()
+    : mEGLWindow(nullptr),
+      mWidth(16),
+      mHeight(16),
+      mIgnoreD3D11SDKLayersWarnings(false),
+      mQuadVertexBuffer(0),
+      mDeferContextInit(false)
+{
+    mEGLWindow =
+        new EGLWindow(GetParam().majorVersion, GetParam().minorVersion, GetParam().eglParameters);
+
+    // Default vulkan layers to enabled.
+    EGLint renderer = GetParam().getRenderer();
+    if (renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
+    {
+        mEGLWindow->setVulkanLayersEnabled(true);
+    }
+
+    // Workaround for NVIDIA not being able to share OpenGL and Vulkan contexts.
+    bool needsWindowSwap = mLastRendererType.valid() &&
+                           ((renderer != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) !=
+                            (mLastRendererType.value() != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE));
+
+    if (needsWindowSwap)
+    {
+        DestroyTestWindow();
+        if (!InitTestWindow())
+        {
+            std::cerr << "Failed to create ANGLE test window.";
+        }
+    }
+    mLastRendererType = renderer;
+}
+
+ANGLETest::~ANGLETest()
+{
+    if (mQuadVertexBuffer)
+    {
+        glDeleteBuffers(1, &mQuadVertexBuffer);
+    }
+    SafeDelete(mEGLWindow);
+}
+
+void ANGLETest::SetUp()
+{
+    mPlatformContext.ignoreMessages = false;
+    mPlatformContext.currentTest    = this;
+
+    // Resize the window before creating the context so that the first make current
+    // sets the viewport and scissor box to the right size.
+    bool needSwap = false;
+    if (mOSWindow->getWidth() != mWidth || mOSWindow->getHeight() != mHeight)
+    {
+        if (!mOSWindow->resize(mWidth, mHeight))
+        {
+            FAIL() << "Failed to resize ANGLE test window.";
+        }
+        needSwap = true;
+    }
+
+    if (!mEGLWindow->initializeDisplayAndSurface(mOSWindow))
+    {
+        FAIL() << "egl display or surface init failed.";
+    }
+
+    if (!mDeferContextInit && !mEGLWindow->initializeContext())
+    {
+        FAIL() << "GL Context init failed.";
+    }
+
+    if (mGLESLibrary)
+    {
+        auto initFunc = reinterpret_cast<angle::GetDisplayPlatformFunc>(
+            mGLESLibrary->getSymbol("ANGLEGetDisplayPlatform"));
+        if (initFunc)
+        {
+            angle::PlatformMethods *platformMethods = nullptr;
+            initFunc(mEGLWindow->getDisplay(), angle::g_PlatformMethodNames,
+                     angle::g_NumPlatformMethods, &mPlatformContext, &platformMethods);
+            platformMethods->overrideWorkaroundsD3D = angle::TestPlatform_overrideWorkaroundsD3D;
+            platformMethods->logError               = angle::TestPlatform_logError;
+            platformMethods->logWarning             = angle::TestPlatform_logWarning;
+            platformMethods->logInfo                = angle::TestPlatform_logInfo;
+        }
+    }
+
+    if (needSwap)
+    {
+        // Swap the buffers so that the default framebuffer picks up the resize
+        // which will allow follow-up test code to assume the framebuffer covers
+        // the whole window.
+        swapBuffers();
+    }
+
+    // This Viewport command is not strictly necessary but we add it so that programs
+    // taking OpenGL traces can guess the size of the default framebuffer and show it
+    // in their UIs
+    glViewport(0, 0, mWidth, mHeight);
+
+    const auto &info = testing::UnitTest::GetInstance()->current_test_info();
+    angle::WriteDebugMessage("Entering %s.%s\n", info->test_case_name(), info->name());
+}
+
+void ANGLETest::TearDown()
+{
+    mPlatformContext.currentTest = nullptr;
+    checkD3D11SDKLayersMessages();
+
+    const auto &info = testing::UnitTest::GetInstance()->current_test_info();
+    angle::WriteDebugMessage("Exiting %s.%s\n", info->test_case_name(), info->name());
+
+    swapBuffers();
+
+    if (eglGetError() != EGL_SUCCESS)
+    {
+        FAIL() << "egl error during swap.";
+    }
+
+    mOSWindow->messageLoop();
+
+    if (!destroyEGLContext())
+    {
+        FAIL() << "egl context destruction failed.";
+    }
+
+    // Check for quit message
+    Event myEvent;
+    while (mOSWindow->popEvent(&myEvent))
+    {
+        if (myEvent.Type == Event::EVENT_CLOSED)
+        {
+            exit(0);
+        }
+    }
+}
+
+void ANGLETest::swapBuffers()
+{
+    if (mEGLWindow->isGLInitialized())
+    {
+        mEGLWindow->swap();
+    }
+}
+
+void ANGLETest::setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)
+{
+    if (mQuadVertexBuffer == 0)
+    {
+        glGenBuffers(1, &mQuadVertexBuffer);
+    }
+
+    auto quadVertices = GetQuadVertices();
+    for (angle::Vector3 &vertex : quadVertices)
+    {
+        vertex.x() *= positionAttribXYScale;
+        vertex.y() *= positionAttribXYScale;
+        vertex.z() = positionAttribZ;
+    }
+
+    glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, quadVertices.data(), GL_STATIC_DRAW);
+}
+
+void ANGLETest::setupIndexedQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)
+{
+    if (mQuadVertexBuffer == 0)
+    {
+        glGenBuffers(1, &mQuadVertexBuffer);
+    }
+
+    auto quadVertices = angle::GetIndexedQuadVertices();
+    for (angle::Vector3 &vertex : quadVertices)
+    {
+        vertex.x() *= positionAttribXYScale;
+        vertex.y() *= positionAttribXYScale;
+        vertex.z() = positionAttribZ;
+    }
+
+    glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 4, quadVertices.data(), GL_STATIC_DRAW);
+}
+
+// static
+void ANGLETest::drawQuad(GLuint program,
+                         const std::string &positionAttribName,
+                         GLfloat positionAttribZ)
+{
+    drawQuad(program, positionAttribName, positionAttribZ, 1.0f);
+}
+
+// static
+void ANGLETest::drawQuad(GLuint program,
+                         const std::string &positionAttribName,
+                         GLfloat positionAttribZ,
+                         GLfloat positionAttribXYScale)
+{
+    drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);
+}
+
+void ANGLETest::drawQuad(GLuint program,
+                         const std::string &positionAttribName,
+                         GLfloat positionAttribZ,
+                         GLfloat positionAttribXYScale,
+                         bool useVertexBuffer)
+{
+    GLint previousProgram = 0;
+    glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgram);
+    if (previousProgram != static_cast<GLint>(program))
+    {
+        glUseProgram(program);
+    }
+
+    GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
+
+    if (useVertexBuffer)
+    {
+        setupQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
+        glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+    }
+    else
+    {
+        auto quadVertices = GetQuadVertices();
+        for (angle::Vector3 &vertex : quadVertices)
+        {
+            vertex.x() *= positionAttribXYScale;
+            vertex.y() *= positionAttribXYScale;
+            vertex.z() = positionAttribZ;
+        }
+
+        glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
+    }
+    glEnableVertexAttribArray(positionLocation);
+
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+
+    glDisableVertexAttribArray(positionLocation);
+    glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+    if (previousProgram != static_cast<GLint>(program))
+    {
+        glUseProgram(previousProgram);
+    }
+}
+
+void ANGLETest::drawIndexedQuad(GLuint program,
+                                const std::string &positionAttribName,
+                                GLfloat positionAttribZ)
+{
+    drawIndexedQuad(program, positionAttribName, positionAttribZ, 1.0f);
+}
+
+void ANGLETest::drawIndexedQuad(GLuint program,
+                                const std::string &positionAttribName,
+                                GLfloat positionAttribZ,
+                                GLfloat positionAttribXYScale)
+{
+    GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
+
+    GLint activeProgram = 0;
+    glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
+    if (static_cast<GLuint>(activeProgram) != program)
+    {
+        glUseProgram(program);
+    }
+
+    GLuint prevBinding = 0;
+    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, reinterpret_cast<GLint *>(&prevBinding));
+
+    setupIndexedQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
+
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+    glBindBuffer(GL_ARRAY_BUFFER, prevBinding);
+
+    const GLushort indices[] = {
+        0, 1, 2, 0, 2, 3,
+    };
+
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+    glDisableVertexAttribArray(positionLocation);
+    glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+    if (static_cast<GLuint>(activeProgram) != program)
+    {
+        glUseProgram(static_cast<GLuint>(activeProgram));
+    }
+}
+
+GLuint ANGLETest::compileShader(GLenum type, const std::string &source)
+{
+    GLuint shader = glCreateShader(type);
+
+    const char *sourceArray[1] = { source.c_str() };
+    glShaderSource(shader, 1, sourceArray, nullptr);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+
+    if (compileResult == 0)
+    {
+        GLint infoLogLength;
+        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+        if (infoLogLength == 0)
+        {
+            std::cerr << "shader compilation failed with empty log." << std::endl;
+        }
+        else
+        {
+            std::vector<GLchar> infoLog(infoLogLength);
+            glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
+
+            std::cerr << "shader compilation failed: " << &infoLog[0];
+        }
+
+        glDeleteShader(shader);
+        shader = 0;
+    }
+
+    return shader;
+}
+
+void ANGLETest::checkD3D11SDKLayersMessages()
+{
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(NDEBUG)
+    // In debug D3D11 mode, check ID3D11InfoQueue to see if any D3D11 SDK Layers messages
+    // were outputted by the test
+    if (mIgnoreD3D11SDKLayersWarnings ||
+        mEGLWindow->getPlatform().renderer != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
+        mEGLWindow->getDisplay() == EGL_NO_DISPLAY)
+    {
+        return;
+    }
+
+    const char *extensionString =
+        static_cast<const char *>(eglQueryString(mEGLWindow->getDisplay(), EGL_EXTENSIONS));
+    if (!extensionString)
+    {
+        std::cout << "Error getting extension string from EGL Window." << std::endl;
+        return;
+    }
+
+    if (!strstr(extensionString, "EGL_EXT_device_query"))
+    {
+        return;
+    }
+
+    EGLAttrib device      = 0;
+    EGLAttrib angleDevice = 0;
+
+    PFNEGLQUERYDISPLAYATTRIBEXTPROC queryDisplayAttribEXT;
+    PFNEGLQUERYDEVICEATTRIBEXTPROC queryDeviceAttribEXT;
+
+    queryDisplayAttribEXT = reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
+        eglGetProcAddress("eglQueryDisplayAttribEXT"));
+    queryDeviceAttribEXT = reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(
+        eglGetProcAddress("eglQueryDeviceAttribEXT"));
+    ASSERT_NE(nullptr, queryDisplayAttribEXT);
+    ASSERT_NE(nullptr, queryDeviceAttribEXT);
+
+    ASSERT_EGL_TRUE(queryDisplayAttribEXT(mEGLWindow->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
+    ASSERT_EGL_TRUE(queryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
+                                         EGL_D3D11_DEVICE_ANGLE, &device));
+    ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);
+
+    ID3D11InfoQueue *infoQueue = nullptr;
+    HRESULT hr =
+        d3d11Device->QueryInterface(__uuidof(infoQueue), reinterpret_cast<void **>(&infoQueue));
+    if (SUCCEEDED(hr))
+    {
+        UINT64 numStoredD3DDebugMessages =
+            infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();
+
+        if (numStoredD3DDebugMessages > 0)
+        {
+            for (UINT64 i = 0; i < numStoredD3DDebugMessages; i++)
+            {
+                SIZE_T messageLength = 0;
+                hr                   = infoQueue->GetMessage(i, nullptr, &messageLength);
+
+                if (SUCCEEDED(hr))
+                {
+                    D3D11_MESSAGE *pMessage =
+                        reinterpret_cast<D3D11_MESSAGE *>(malloc(messageLength));
+                    infoQueue->GetMessage(i, pMessage, &messageLength);
+
+                    std::cout << "Message " << i << ":"
+                              << " " << pMessage->pDescription << "\n";
+                    free(pMessage);
+                }
+            }
+
+            FAIL() << numStoredD3DDebugMessages
+                   << " D3D11 SDK Layers message(s) detected! Test Failed.\n";
+        }
+    }
+
+    SafeRelease(infoQueue);
+#endif
+}
+
+static bool checkExtensionExists(const char *allExtensions, const std::string &extName)
+{
+    const std::string paddedExtensions = std::string(" ") + allExtensions + std::string(" ");
+    return paddedExtensions.find(std::string(" ") + extName + std::string(" ")) !=
+           std::string::npos;
+}
+
+bool ANGLETest::extensionEnabled(const std::string &extName)
+{
+    return checkExtensionExists(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
+                                extName);
+}
+
+bool ANGLETest::extensionRequestable(const std::string &extName)
+{
+    return checkExtensionExists(
+        reinterpret_cast<const char *>(glGetString(GL_REQUESTABLE_EXTENSIONS_ANGLE)), extName);
+}
+
+bool ANGLETest::eglDisplayExtensionEnabled(EGLDisplay display, const std::string &extName)
+{
+    return checkExtensionExists(eglQueryString(display, EGL_EXTENSIONS), extName);
+}
+
+bool ANGLETest::eglClientExtensionEnabled(const std::string &extName)
+{
+    return checkExtensionExists(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS), extName);
+}
+
+bool ANGLETest::eglDeviceExtensionEnabled(EGLDeviceEXT device, const std::string &extName)
+{
+    PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT =
+        reinterpret_cast<PFNEGLQUERYDEVICESTRINGEXTPROC>(
+            eglGetProcAddress("eglQueryDeviceStringEXT"));
+    return checkExtensionExists(eglQueryDeviceStringEXT(device, EGL_EXTENSIONS), extName);
+}
+
+void ANGLETest::setWindowWidth(int width)
+{
+    mWidth = width;
+}
+
+void ANGLETest::setWindowHeight(int height)
+{
+    mHeight = height;
+}
+
+void ANGLETest::setConfigRedBits(int bits)
+{
+    mEGLWindow->setConfigRedBits(bits);
+}
+
+void ANGLETest::setConfigGreenBits(int bits)
+{
+    mEGLWindow->setConfigGreenBits(bits);
+}
+
+void ANGLETest::setConfigBlueBits(int bits)
+{
+    mEGLWindow->setConfigBlueBits(bits);
+}
+
+void ANGLETest::setConfigAlphaBits(int bits)
+{
+    mEGLWindow->setConfigAlphaBits(bits);
+}
+
+void ANGLETest::setConfigDepthBits(int bits)
+{
+    mEGLWindow->setConfigDepthBits(bits);
+}
+
+void ANGLETest::setConfigStencilBits(int bits)
+{
+    mEGLWindow->setConfigStencilBits(bits);
+}
+
+void ANGLETest::setConfigComponentType(EGLenum componentType)
+{
+    mEGLWindow->setConfigComponentType(componentType);
+}
+
+void ANGLETest::setMultisampleEnabled(bool enabled)
+{
+    mEGLWindow->setMultisample(enabled);
+}
+
+void ANGLETest::setSamples(EGLint samples)
+{
+    mEGLWindow->setSamples(samples);
+}
+
+void ANGLETest::setDebugEnabled(bool enabled)
+{
+    mEGLWindow->setDebugEnabled(enabled);
+}
+
+void ANGLETest::setNoErrorEnabled(bool enabled)
+{
+    mEGLWindow->setNoErrorEnabled(enabled);
+}
+
+void ANGLETest::setWebGLCompatibilityEnabled(bool webglCompatibility)
+{
+    mEGLWindow->setWebGLCompatibilityEnabled(webglCompatibility);
+}
+
+void ANGLETest::setBindGeneratesResource(bool bindGeneratesResource)
+{
+    mEGLWindow->setBindGeneratesResource(bindGeneratesResource);
+}
+
+void ANGLETest::setVulkanLayersEnabled(bool enabled)
+{
+    mEGLWindow->setVulkanLayersEnabled(enabled);
+}
+
+void ANGLETest::setClientArraysEnabled(bool enabled)
+{
+    mEGLWindow->setClientArraysEnabled(enabled);
+}
+
+void ANGLETest::setRobustResourceInit(bool enabled)
+{
+    mEGLWindow->setRobustResourceInit(enabled);
+}
+
+void ANGLETest::setDeferContextInit(bool enabled)
+{
+    mDeferContextInit = enabled;
+}
+
+int ANGLETest::getClientMajorVersion() const
+{
+    return mEGLWindow->getClientMajorVersion();
+}
+
+int ANGLETest::getClientMinorVersion() const
+{
+    return mEGLWindow->getClientMinorVersion();
+}
+
+EGLWindow *ANGLETest::getEGLWindow() const
+{
+    return mEGLWindow;
+}
+
+int ANGLETest::getWindowWidth() const
+{
+    return mWidth;
+}
+
+int ANGLETest::getWindowHeight() const
+{
+    return mHeight;
+}
+
+bool ANGLETest::isMultisampleEnabled() const
+{
+    return mEGLWindow->isMultisample();
+}
+
+bool ANGLETest::destroyEGLContext()
+{
+    mEGLWindow->destroyGL();
+    return true;
+}
+
+// static
+bool ANGLETest::InitTestWindow()
+{
+    mOSWindow = CreateOSWindow();
+    if (!mOSWindow->initialize("ANGLE_TEST", 128, 128))
+    {
+        return false;
+    }
+
+    mOSWindow->setVisible(true);
+
+    mGLESLibrary.reset(angle::loadLibrary("libGLESv2"));
+
+    return true;
+}
+
+// static
+bool ANGLETest::DestroyTestWindow()
+{
+    if (mOSWindow)
+    {
+        mOSWindow->destroy();
+        delete mOSWindow;
+        mOSWindow = nullptr;
+    }
+
+    mGLESLibrary.reset(nullptr);
+
+    return true;
+}
+
+void ANGLETest::SetWindowVisible(bool isVisible)
+{
+    mOSWindow->setVisible(isVisible);
+}
+
+bool IsIntel()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("Intel") != std::string::npos);
+}
+
+bool IsAdreno()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("Adreno") != std::string::npos);
+}
+
+bool IsAMD()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("AMD") != std::string::npos) ||
+           (rendererString.find("ATI") != std::string::npos);
+}
+
+bool IsNVIDIA()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("NVIDIA") != std::string::npos);
+}
+
+bool IsD3D11()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("Direct3D11 vs_5_0") != std::string::npos);
+}
+
+bool IsD3D11_FL93()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("Direct3D11 vs_4_0_") != std::string::npos);
+}
+
+bool IsD3D9()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("Direct3D9") != std::string::npos);
+}
+
+bool IsD3DSM3()
+{
+    return IsD3D9() || IsD3D11_FL93();
+}
+
+bool IsDesktopOpenGL()
+{
+    return IsOpenGL() && !IsOpenGLES();
+}
+
+bool IsOpenGLES()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("OpenGL ES") != std::string::npos);
+}
+
+bool IsOpenGL()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("OpenGL") != std::string::npos);
+}
+
+bool IsNULL()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("NULL") != std::string::npos);
+}
+
+bool IsAndroid()
+{
+#if defined(ANGLE_PLATFORM_ANDROID)
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool IsVulkan()
+{
+    std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+    return (rendererString.find("Vulkan") != std::string::npos);
+}
+
+bool IsOzone()
+{
+#if defined(USE_OZONE)
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool IsLinux()
+{
+#if defined(ANGLE_PLATFORM_LINUX)
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool IsOSX()
+{
+#if defined(ANGLE_PLATFORM_APPLE)
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool IsWindows()
+{
+#if defined(ANGLE_PLATFORM_WINDOWS)
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool IsDebug()
+{
+#if !defined(NDEBUG)
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool IsRelease()
+{
+    return !IsDebug();
+}
+
+EGLint ANGLETest::getPlatformRenderer() const
+{
+    assert(mEGLWindow);
+    return mEGLWindow->getPlatform().renderer;
+}
+
+void ANGLETest::ignoreD3D11SDKLayersWarnings()
+{
+    // Some tests may need to disable the D3D11 SDK Layers Warnings checks
+    mIgnoreD3D11SDKLayersWarnings = true;
+}
+
+OSWindow *ANGLETest::mOSWindow = nullptr;
+Optional<EGLint> ANGLETest::mLastRendererType;
+std::unique_ptr<angle::Library> ANGLETest::mGLESLibrary;
+
+void ANGLETestEnvironment::SetUp()
+{
+    if (!ANGLETest::InitTestWindow())
+    {
+        FAIL() << "Failed to create ANGLE test window.";
+    }
+}
+
+void ANGLETestEnvironment::TearDown()
+{
+    ANGLETest::DestroyTestWindow();
+}
diff --git a/src/third_party/angle/src/tests/test_utils/ANGLETest.h b/src/third_party/angle/src/tests/test_utils/ANGLETest.h
new file mode 100644
index 0000000..c8b5935
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/ANGLETest.h
@@ -0,0 +1,356 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLETest:
+//   Implementation of common ANGLE testing fixture.
+//
+
+#ifndef ANGLE_TESTS_ANGLE_TEST_H_
+#define ANGLE_TESTS_ANGLE_TEST_H_
+
+#include <gtest/gtest.h>
+#include <algorithm>
+#include <array>
+
+#include "angle_gl.h"
+#include "angle_test_configs.h"
+#include "common/angleutils.h"
+#include "common/vector_utils.h"
+#include "shader_utils.h"
+#include "system_utils.h"
+
+#define ASSERT_GL_TRUE(a) ASSERT_EQ(static_cast<GLboolean>(GL_TRUE), (a))
+#define ASSERT_GL_FALSE(a) ASSERT_EQ(static_cast<GLboolean>(GL_FALSE), (a))
+#define EXPECT_GL_TRUE(a) EXPECT_EQ(static_cast<GLboolean>(GL_TRUE), (a))
+#define EXPECT_GL_FALSE(a) EXPECT_EQ(static_cast<GLboolean>(GL_FALSE), (a))
+
+#define EXPECT_GL_ERROR(err) EXPECT_EQ(static_cast<GLenum>(err), glGetError())
+#define EXPECT_GL_NO_ERROR() EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError())
+
+#define ASSERT_GL_ERROR(err) ASSERT_EQ(static_cast<GLenum>(err), glGetError())
+#define ASSERT_GL_NO_ERROR() ASSERT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError())
+
+#define EXPECT_EGL_ERROR(err) EXPECT_EQ((err), eglGetError())
+#define EXPECT_EGL_SUCCESS() EXPECT_EGL_ERROR(EGL_SUCCESS)
+
+// EGLBoolean is |unsigned int| but EGL_TRUE is 0, not 0u.
+#define ASSERT_EGL_TRUE(a) ASSERT_EQ(static_cast<EGLBoolean>(EGL_TRUE), (a))
+#define ASSERT_EGL_FALSE(a) ASSERT_EQ(static_cast<EGLBoolean>(EGL_FALSE), (a))
+#define EXPECT_EGL_TRUE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_TRUE), (a))
+#define EXPECT_EGL_FALSE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_FALSE), (a))
+
+#define ASSERT_EGL_ERROR(err) ASSERT_EQ((err), eglGetError())
+#define ASSERT_EGL_SUCCESS() ASSERT_EGL_ERROR(EGL_SUCCESS)
+
+#define ASSERT_GLENUM_EQ(expected, actual) ASSERT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
+#define EXPECT_GLENUM_EQ(expected, actual) EXPECT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
+#define ASSERT_GLENUM_NE(expected, actual) \
+    ASSERT_NE(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
+#define EXPECT_GLENUM_NE(expected, actual) \
+    EXPECT_NE(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
+
+namespace angle
+{
+struct GLColorRGB
+{
+    GLColorRGB();
+    GLColorRGB(GLubyte r, GLubyte g, GLubyte b);
+    GLColorRGB(const angle::Vector3 &floatColor);
+
+    GLubyte R, G, B;
+
+    static const GLColorRGB black;
+    static const GLColorRGB blue;
+    static const GLColorRGB green;
+    static const GLColorRGB red;
+    static const GLColorRGB yellow;
+};
+
+struct GLColor
+{
+    GLColor();
+    GLColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a);
+    GLColor(const angle::Vector4 &floatColor);
+    GLColor(GLuint colorValue);
+
+    angle::Vector4 toNormalizedVector() const;
+
+    GLubyte R, G, B, A;
+
+    static const GLColor black;
+    static const GLColor blue;
+    static const GLColor cyan;
+    static const GLColor green;
+    static const GLColor red;
+    static const GLColor transparentBlack;
+    static const GLColor white;
+    static const GLColor yellow;
+    static const GLColor magenta;
+};
+
+struct GLColor32F
+{
+    GLColor32F();
+    GLColor32F(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+
+    GLfloat R, G, B, A;
+};
+
+struct WorkaroundsD3D;
+
+// Useful to cast any type to GLubyte.
+template <typename TR, typename TG, typename TB, typename TA>
+GLColor MakeGLColor(TR r, TG g, TB b, TA a)
+{
+    return GLColor(static_cast<GLubyte>(r), static_cast<GLubyte>(g), static_cast<GLubyte>(b),
+                   static_cast<GLubyte>(a));
+}
+
+bool operator==(const GLColor &a, const GLColor &b);
+std::ostream &operator<<(std::ostream &ostream, const GLColor &color);
+GLColor ReadColor(GLint x, GLint y);
+
+// Useful to cast any type to GLfloat.
+template <typename TR, typename TG, typename TB, typename TA>
+GLColor32F MakeGLColor32F(TR r, TG g, TB b, TA a)
+{
+    return GLColor32F(static_cast<GLfloat>(r), static_cast<GLfloat>(g), static_cast<GLfloat>(b),
+                      static_cast<GLfloat>(a));
+}
+
+bool operator==(const GLColor32F &a, const GLColor32F &b);
+std::ostream &operator<<(std::ostream &ostream, const GLColor32F &color);
+GLColor32F ReadColor32F(GLint x, GLint y);
+
+}  // namespace angle
+
+#define EXPECT_PIXEL_EQ(x, y, r, g, b, a) \
+    EXPECT_EQ(angle::MakeGLColor(r, g, b, a), angle::ReadColor(x, y))
+
+#define EXPECT_PIXEL_32F_EQ(x, y, r, g, b, a) \
+    EXPECT_EQ(angle::MakeGLColor32F(r, g, b, a), angle::ReadColor32F(x, y))
+
+#define EXPECT_PIXEL_ALPHA_EQ(x, y, a) EXPECT_EQ(a, angle::ReadColor(x, y).A)
+
+#define EXPECT_PIXEL_ALPHA32F_EQ(x, y, a) EXPECT_EQ(a, angle::ReadColor32F(x, y).A)
+
+#define EXPECT_PIXEL_COLOR_EQ(x, y, angleColor) EXPECT_EQ(angleColor, angle::ReadColor(x, y))
+#define EXPECT_PIXEL_COLOR_EQ_VEC2(vec2, angleColor) \
+    EXPECT_EQ(angleColor,                            \
+              angle::ReadColor(static_cast<GLint>(vec2.x()), static_cast<GLint>(vec2.y())))
+
+#define EXPECT_PIXEL_COLOR32F_EQ(x, y, angleColor) EXPECT_EQ(angleColor, angle::ReadColor32F(x, y))
+
+#define EXPECT_PIXEL_NEAR(x, y, r, g, b, a, abs_error) \
+{ \
+    GLubyte pixel[4]; \
+    glReadPixels((x), (y), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); \
+    EXPECT_GL_NO_ERROR(); \
+    EXPECT_NEAR((r), pixel[0], abs_error); \
+    EXPECT_NEAR((g), pixel[1], abs_error); \
+    EXPECT_NEAR((b), pixel[2], abs_error); \
+    EXPECT_NEAR((a), pixel[3], abs_error); \
+}
+
+#define EXPECT_PIXEL32F_NEAR(x, y, r, g, b, a, abs_error)       \
+                                                                \
+    {                                                           \
+        GLfloat pixel[4];                                       \
+        glReadPixels((x), (y), 1, 1, GL_RGBA, GL_FLOAT, pixel); \
+        EXPECT_GL_NO_ERROR();                                   \
+        EXPECT_NEAR((r), pixel[0], abs_error);                  \
+        EXPECT_NEAR((g), pixel[1], abs_error);                  \
+        EXPECT_NEAR((b), pixel[2], abs_error);                  \
+        EXPECT_NEAR((a), pixel[3], abs_error);                  \
+    }
+
+// TODO(jmadill): Figure out how we can use GLColor's nice printing with EXPECT_NEAR.
+#define EXPECT_PIXEL_COLOR_NEAR(x, y, angleColor, abs_error) \
+    EXPECT_PIXEL_NEAR(x, y, angleColor.R, angleColor.G, angleColor.B, angleColor.A, abs_error)
+
+#define EXPECT_PIXEL_COLOR32F_NEAR(x, y, angleColor, abs_error) \
+    EXPECT_PIXEL32F_NEAR(x, y, angleColor.R, angleColor.G, angleColor.B, angleColor.A, abs_error)
+
+#define EXPECT_COLOR_NEAR(expected, actual, abs_error) \
+    \
+{                                               \
+        EXPECT_NEAR(expected.R, actual.R, abs_error);  \
+        EXPECT_NEAR(expected.G, actual.G, abs_error);  \
+        EXPECT_NEAR(expected.B, actual.B, abs_error);  \
+        EXPECT_NEAR(expected.A, actual.A, abs_error);  \
+    \
+}
+
+class EGLWindow;
+class OSWindow;
+class ANGLETest;
+
+struct TestPlatformContext final : private angle::NonCopyable
+{
+    bool ignoreMessages    = false;
+    ANGLETest *currentTest = nullptr;
+};
+
+class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
+{
+  protected:
+    ANGLETest();
+    ~ANGLETest();
+
+  public:
+    static bool InitTestWindow();
+    static bool DestroyTestWindow();
+    static void SetWindowVisible(bool isVisible);
+    static bool eglDisplayExtensionEnabled(EGLDisplay display, const std::string &extName);
+
+    virtual void overrideWorkaroundsD3D(angle::WorkaroundsD3D *workaroundsD3D) {}
+
+  protected:
+    virtual void SetUp();
+    virtual void TearDown();
+
+    virtual void swapBuffers();
+
+    void setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale);
+    void setupIndexedQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale);
+
+    void drawQuad(GLuint program, const std::string &positionAttribName, GLfloat positionAttribZ);
+    void drawQuad(GLuint program,
+                  const std::string &positionAttribName,
+                  GLfloat positionAttribZ,
+                  GLfloat positionAttribXYScale);
+    void drawQuad(GLuint program,
+                  const std::string &positionAttribName,
+                  GLfloat positionAttribZ,
+                  GLfloat positionAttribXYScale,
+                  bool useVertexBuffer);
+    static std::array<angle::Vector3, 6> GetQuadVertices();
+    void drawIndexedQuad(GLuint program,
+                         const std::string &positionAttribName,
+                         GLfloat positionAttribZ);
+    void drawIndexedQuad(GLuint program,
+                         const std::string &positionAttribName,
+                         GLfloat positionAttribZ,
+                         GLfloat positionAttribXYScale);
+
+    static GLuint compileShader(GLenum type, const std::string &source);
+    static bool extensionEnabled(const std::string &extName);
+    static bool extensionRequestable(const std::string &extName);
+    static bool eglClientExtensionEnabled(const std::string &extName);
+    static bool eglDeviceExtensionEnabled(EGLDeviceEXT device, const std::string &extName);
+
+    void setWindowWidth(int width);
+    void setWindowHeight(int height);
+    void setConfigRedBits(int bits);
+    void setConfigGreenBits(int bits);
+    void setConfigBlueBits(int bits);
+    void setConfigAlphaBits(int bits);
+    void setConfigDepthBits(int bits);
+    void setConfigStencilBits(int bits);
+    void setConfigComponentType(EGLenum componentType);
+    void setMultisampleEnabled(bool enabled);
+    void setSamples(EGLint samples);
+    void setDebugEnabled(bool enabled);
+    void setNoErrorEnabled(bool enabled);
+    void setWebGLCompatibilityEnabled(bool webglCompatibility);
+    void setBindGeneratesResource(bool bindGeneratesResource);
+    void setVulkanLayersEnabled(bool enabled);
+    void setClientArraysEnabled(bool enabled);
+    void setRobustResourceInit(bool enabled);
+
+    // Some EGL extension tests would like to defer the Context init until the test body.
+    void setDeferContextInit(bool enabled);
+
+    int getClientMajorVersion() const;
+    int getClientMinorVersion() const;
+
+    EGLWindow *getEGLWindow() const;
+    int getWindowWidth() const;
+    int getWindowHeight() const;
+    bool isMultisampleEnabled() const;
+
+    EGLint getPlatformRenderer() const;
+
+    void ignoreD3D11SDKLayersWarnings();
+
+    static OSWindow *GetOSWindow() { return mOSWindow; }
+
+  private:
+    bool destroyEGLContext();
+
+    void checkD3D11SDKLayersMessages();
+
+    EGLWindow *mEGLWindow;
+    int mWidth;
+    int mHeight;
+
+    bool mIgnoreD3D11SDKLayersWarnings;
+
+    // Used for indexed quad rendering
+    GLuint mQuadVertexBuffer;
+
+    TestPlatformContext mPlatformContext;
+
+    bool mDeferContextInit;
+
+    static OSWindow *mOSWindow;
+
+    // Workaround for NVIDIA not being able to share a window with OpenGL and Vulkan.
+    static Optional<EGLint> mLastRendererType;
+
+    // For loading and freeing platform
+    static std::unique_ptr<angle::Library> mGLESLibrary;
+};
+
+class ANGLETestEnvironment : public testing::Environment
+{
+  public:
+    void SetUp() override;
+    void TearDown() override;
+};
+
+// Driver vendors
+bool IsIntel();
+bool IsAdreno();
+bool IsAMD();
+bool IsNVIDIA();
+
+// Renderer back-ends
+// Note: FL9_3 is explicitly *not* considered D3D11.
+bool IsD3D11();
+bool IsD3D11_FL93();
+// Is a D3D9-class renderer.
+bool IsD3D9();
+// Is D3D9 or SM9_3 renderer.
+bool IsD3DSM3();
+bool IsDesktopOpenGL();
+bool IsOpenGLES();
+bool IsOpenGL();
+bool IsOzone();
+bool IsNULL();
+
+// Operating systems
+bool IsAndroid();
+bool IsLinux();
+bool IsOSX();
+bool IsWindows();
+bool IsVulkan();
+
+// Debug/Release
+bool IsDebug();
+bool IsRelease();
+
+// Note: git cl format messes up this formatting.
+#define ANGLE_SKIP_TEST_IF(COND)                              \
+    \
+if(COND)                                                      \
+    \
+{                                                      \
+        std::cout << "Test skipped: " #COND "." << std::endl; \
+        return;                                               \
+    \
+}
+
+#endif  // ANGLE_TESTS_ANGLE_TEST_H_
diff --git a/src/third_party/angle/src/tests/test_utils/ConstantFoldingTest.cpp b/src/third_party/angle/src/tests/test_utils/ConstantFoldingTest.cpp
new file mode 100644
index 0000000..b9b508b
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/ConstantFoldingTest.cpp
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2016 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.
+//
+// ConstantFoldingTest.cpp:
+//   Utilities for constant folding tests.
+//
+
+#include "tests/test_utils/ConstantFoldingTest.h"
+
+#include "angle_gl.h"
+#include "compiler/translator/TranslatorESSL.h"
+#include "GLSLANG/ShaderLang.h"
+
+using namespace sh;
+
+void ConstantFoldingExpressionTest::evaluateFloat(const std::string &floatExpression)
+{
+    std::stringstream shaderStream;
+    shaderStream << "#version 310 es\n"
+                    "precision mediump float;\n"
+                    "out float my_FragColor;\n"
+                    "void main()\n"
+                    "{\n"
+                 << "    my_FragColor = " << floatExpression << ";\n"
+                 << "}\n";
+    compileAssumeSuccess(shaderStream.str());
+}
+
+void ConstantFoldingExpressionTest::evaluateInt(const std::string &intExpression)
+{
+    std::stringstream shaderStream;
+    shaderStream << "#version 310 es\n"
+                    "precision mediump int;\n"
+                    "out int my_FragColor;\n"
+                    "void main()\n"
+                    "{\n"
+                 << "    my_FragColor = " << intExpression << ";\n"
+                 << "}\n";
+    compileAssumeSuccess(shaderStream.str());
+}
+
+void ConstantFoldingExpressionTest::evaluateUint(const std::string &uintExpression)
+{
+    std::stringstream shaderStream;
+    shaderStream << "#version 310 es\n"
+                    "precision mediump int;\n"
+                    "out uint my_FragColor;\n"
+                    "void main()\n"
+                    "{\n"
+                 << "    my_FragColor = " << uintExpression << ";\n"
+                 << "}\n";
+    compileAssumeSuccess(shaderStream.str());
+}
diff --git a/src/third_party/angle/src/tests/test_utils/ConstantFoldingTest.h b/src/third_party/angle/src/tests/test_utils/ConstantFoldingTest.h
new file mode 100644
index 0000000..a627b5c
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/ConstantFoldingTest.h
@@ -0,0 +1,186 @@
+//
+// Copyright (c) 2016 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.
+//
+// ConstantFoldingTest.h:
+//   Utilities for constant folding tests.
+//
+
+#ifndef TESTS_TEST_UTILS_CONSTANTFOLDINGTEST_H_
+#define TESTS_TEST_UTILS_CONSTANTFOLDINGTEST_H_
+
+#include <vector>
+
+#include "common/mathutil.h"
+#include "compiler/translator/IntermNode.h"
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+
+namespace sh
+{
+
+class TranslatorESSL;
+
+template <typename T>
+class ConstantFinder : public TIntermTraverser
+{
+  public:
+    ConstantFinder(const std::vector<T> &constantVector)
+        : TIntermTraverser(true, false, false),
+          mConstantVector(constantVector),
+          mFaultTolerance(T()),
+          mFound(false)
+    {
+    }
+
+    ConstantFinder(const std::vector<T> &constantVector, const T &faultTolerance)
+        : TIntermTraverser(true, false, false),
+          mConstantVector(constantVector),
+          mFaultTolerance(faultTolerance),
+          mFound(false)
+    {
+    }
+
+    ConstantFinder(const T &value)
+        : TIntermTraverser(true, false, false), mFaultTolerance(T()), mFound(false)
+    {
+        mConstantVector.push_back(value);
+    }
+
+    void visitConstantUnion(TIntermConstantUnion *node)
+    {
+        if (node->getType().getObjectSize() == mConstantVector.size())
+        {
+            bool found = true;
+            for (size_t i = 0; i < mConstantVector.size(); i++)
+            {
+                if (!isEqual(node->getUnionArrayPointer()[i], mConstantVector[i]))
+                {
+                    found = false;
+                    break;
+                }
+            }
+            if (found)
+            {
+                mFound = found;
+            }
+        }
+    }
+
+    bool found() const { return mFound; }
+
+  private:
+    bool isEqual(const TConstantUnion &node, const float &value) const
+    {
+        if (node.getType() != EbtFloat)
+        {
+            return false;
+        }
+        if (value == std::numeric_limits<float>::infinity())
+        {
+            return gl::isInf(node.getFConst()) && node.getFConst() > 0;
+        }
+        else if (value == -std::numeric_limits<float>::infinity())
+        {
+            return gl::isInf(node.getFConst()) && node.getFConst() < 0;
+        }
+        else if (gl::isNaN(value))
+        {
+            // All NaNs are treated as equal.
+            return gl::isNaN(node.getFConst());
+        }
+        return mFaultTolerance >= fabsf(node.getFConst() - value);
+    }
+
+    bool isEqual(const TConstantUnion &node, const int &value) const
+    {
+        if (node.getType() != EbtInt)
+        {
+            return false;
+        }
+        ASSERT(mFaultTolerance < std::numeric_limits<int>::max());
+        // abs() returns 0 at least on some platforms when the minimum int value is passed in (it
+        // doesn't have a positive counterpart).
+        return mFaultTolerance >= abs(node.getIConst() - value) &&
+               (node.getIConst() - value) != std::numeric_limits<int>::min();
+    }
+
+    bool isEqual(const TConstantUnion &node, const unsigned int &value) const
+    {
+        if (node.getType() != EbtUInt)
+        {
+            return false;
+        }
+        ASSERT(mFaultTolerance < static_cast<unsigned int>(std::numeric_limits<int>::max()));
+        return static_cast<int>(mFaultTolerance) >=
+                   abs(static_cast<int>(node.getUConst() - value)) &&
+               static_cast<int>(node.getUConst() - value) != std::numeric_limits<int>::min();
+    }
+
+    bool isEqual(const TConstantUnion &node, const bool &value) const
+    {
+        if (node.getType() != EbtBool)
+        {
+            return false;
+        }
+        return node.getBConst() == value;
+    }
+
+    std::vector<T> mConstantVector;
+    T mFaultTolerance;
+    bool mFound;
+};
+
+class ConstantFoldingTest : public ShaderCompileTreeTest
+{
+  public:
+    ConstantFoldingTest() {}
+
+  protected:
+    ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
+
+    template <typename T>
+    bool constantFoundInAST(T constant)
+    {
+        ConstantFinder<T> finder(constant);
+        mASTRoot->traverse(&finder);
+        return finder.found();
+    }
+
+    template <typename T>
+    bool constantVectorFoundInAST(const std::vector<T> &constantVector)
+    {
+        ConstantFinder<T> finder(constantVector);
+        mASTRoot->traverse(&finder);
+        return finder.found();
+    }
+
+    template <typename T>
+    bool constantColumnMajorMatrixFoundInAST(const std::vector<T> &constantMatrix)
+    {
+        return constantVectorFoundInAST(constantMatrix);
+    }
+
+    template <typename T>
+    bool constantVectorNearFoundInAST(const std::vector<T> &constantVector, const T &faultTolerance)
+    {
+        ConstantFinder<T> finder(constantVector, faultTolerance);
+        mASTRoot->traverse(&finder);
+        return finder.found();
+    }
+};
+
+class ConstantFoldingExpressionTest : public ConstantFoldingTest
+{
+  public:
+    ConstantFoldingExpressionTest() {}
+
+    void evaluateFloat(const std::string &floatExpression);
+    void evaluateInt(const std::string &intExpression);
+    void evaluateUint(const std::string &uintExpression);
+};
+
+}  // namespace sh
+
+#endif  // TESTS_TEST_UTILS_CONSTANTFOLDINGTEST_H_
diff --git a/src/third_party/angle/src/tests/test_utils/ShaderCompileTreeTest.cpp b/src/third_party/angle/src/tests/test_utils/ShaderCompileTreeTest.cpp
new file mode 100644
index 0000000..a1a0dbb
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/ShaderCompileTreeTest.cpp
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2016 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.
+//
+// ShaderCompileTreeTest.cpp:
+//   Test that shader validation results in the correct compile status.
+//
+
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+
+#include "compiler/translator/TranslatorESSL.h"
+
+using namespace sh;
+
+void ShaderCompileTreeTest::SetUp()
+{
+    mAllocator.push();
+    SetGlobalPoolAllocator(&mAllocator);
+
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+
+    initResources(&resources);
+
+    mTranslator = new TranslatorESSL(getShaderType(), getShaderSpec());
+    ASSERT_TRUE(mTranslator->Init(resources));
+}
+
+void ShaderCompileTreeTest::TearDown()
+{
+    delete mTranslator;
+
+    SetGlobalPoolAllocator(nullptr);
+    mAllocator.pop();
+}
+
+bool ShaderCompileTreeTest::compile(const std::string &shaderString)
+{
+    const char *shaderStrings[] = {shaderString.c_str()};
+    mASTRoot = mTranslator->compileTreeForTesting(shaderStrings, 1, mExtraCompileOptions);
+    TInfoSink &infoSink = mTranslator->getInfoSink();
+    mInfoLog            = infoSink.info.c_str();
+    return mASTRoot != nullptr;
+}
+
+void ShaderCompileTreeTest::compileAssumeSuccess(const std::string &shaderString)
+{
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation into ESSL failed, log:\n" << mInfoLog;
+    }
+}
+
+bool ShaderCompileTreeTest::hasWarning() const
+{
+    return mInfoLog.find("WARNING: ") != std::string::npos;
+}
+
+const std::vector<sh::Uniform> ShaderCompileTreeTest::getUniforms()
+{
+    ASSERT(mExtraCompileOptions & SH_VARIABLES);
+    return mTranslator->getUniforms();
+}
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/test_utils/ShaderCompileTreeTest.h b/src/third_party/angle/src/tests/test_utils/ShaderCompileTreeTest.h
new file mode 100644
index 0000000..dc5eac6
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/ShaderCompileTreeTest.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2016 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.
+//
+// ShaderCompileTreeTest.h:
+//   Test that shader validation results in the correct compile status.
+//
+
+#ifndef TESTS_TEST_UTILS_SHADER_COMPILE_TREE_TEST_H_
+#define TESTS_TEST_UTILS_SHADER_COMPILE_TREE_TEST_H_
+
+#include "angle_gl.h"
+#include "compiler/translator/PoolAlloc.h"
+#include "gtest/gtest.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+
+class TIntermBlock;
+class TranslatorESSL;
+
+class ShaderCompileTreeTest : public testing::Test
+{
+  public:
+    ShaderCompileTreeTest() : mExtraCompileOptions(0) {}
+
+  protected:
+    void SetUp() override;
+
+    void TearDown() override;
+
+    // Return true when compilation succeeds
+    bool compile(const std::string &shaderString);
+    void compileAssumeSuccess(const std::string &shaderString);
+
+    bool hasWarning() const;
+
+    const std::vector<sh::Uniform> getUniforms();
+
+    virtual void initResources(ShBuiltInResources *resources) {}
+    virtual ::GLenum getShaderType() const     = 0;
+    virtual ShShaderSpec getShaderSpec() const = 0;
+
+    std::string mInfoLog;
+    ShCompileOptions mExtraCompileOptions;
+
+    TIntermBlock *mASTRoot;
+
+  private:
+    TranslatorESSL *mTranslator;
+
+    TPoolAllocator mAllocator;
+};
+
+}  // namespace sh
+
+#endif  // TESTS_TEST_UTILS_SHADER_COMPILE_TREE_TEST_H_
diff --git a/src/third_party/angle/src/tests/test_utils/angle_test_configs.cpp b/src/third_party/angle/src/tests/test_utils/angle_test_configs.cpp
new file mode 100644
index 0000000..0e7e138
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/angle_test_configs.cpp
@@ -0,0 +1,629 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/angle_test_configs.h"
+
+namespace angle
+{
+
+PlatformParameters::PlatformParameters()
+    : PlatformParameters(2, 0, EGLPlatformParameters())
+{
+}
+
+PlatformParameters::PlatformParameters(EGLint majorVersion, EGLint minorVersion,
+                                       const EGLPlatformParameters &eglPlatformParameters)
+    : majorVersion(majorVersion),
+      minorVersion(minorVersion),
+      eglParameters(eglPlatformParameters)
+{
+}
+
+EGLint PlatformParameters::getRenderer() const
+{
+    return eglParameters.renderer;
+}
+
+bool operator<(const PlatformParameters &a, const PlatformParameters &b)
+{
+    if (a.majorVersion != b.majorVersion)
+    {
+        return a.majorVersion < b.majorVersion;
+    }
+
+    if (a.minorVersion != b.minorVersion)
+    {
+        return a.minorVersion < b.minorVersion;
+    }
+
+    return a.eglParameters < b.eglParameters;
+}
+
+bool operator==(const PlatformParameters &a, const PlatformParameters &b)
+{
+    return (a.majorVersion == b.majorVersion) &&
+           (a.minorVersion == b.minorVersion) &&
+           (a.eglParameters == b.eglParameters);
+}
+
+std::ostream &operator<<(std::ostream& stream, const PlatformParameters &pp)
+{
+    stream << "ES" << pp.majorVersion << "_" ;
+    if (pp.minorVersion != 0)
+    {
+        stream << pp.minorVersion << "_";
+    }
+
+    switch (pp.eglParameters.renderer)
+    {
+        case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+            stream << "DEFAULT";
+            break;
+        case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+            stream << "D3D9";
+            break;
+        case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+            stream << "D3D11";
+            break;
+        case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
+            stream << "NULL";
+            break;
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+            stream << "OPENGL";
+            break;
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+            stream << "OPENGLES";
+            break;
+        case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+            stream << "VULKAN";
+            break;
+        default:
+            stream << "UNDEFINED";
+            break;
+    }
+
+    if (pp.eglParameters.majorVersion != EGL_DONT_CARE)
+    {
+        stream << "_" << pp.eglParameters.majorVersion;
+    }
+
+    if (pp.eglParameters.minorVersion != EGL_DONT_CARE)
+    {
+        stream << "_" << pp.eglParameters.minorVersion;
+    }
+
+    switch (pp.eglParameters.deviceType)
+    {
+      case EGL_DONT_CARE:
+      case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+        // default
+        break;
+
+      case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+          stream << "_NULL";
+          break;
+
+      case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+        stream << "_REFERENCE";
+        break;
+
+      case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
+        stream << "_WARP";
+        break;
+
+      default:
+        UNREACHABLE();
+        break;
+    }
+
+    switch (pp.eglParameters.presentPath)
+    {
+        case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
+            stream << "_PRESENT_PATH_COPY";
+            break;
+
+        case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
+            stream << "_PRESENT_PATH_FAST";
+            break;
+
+        case EGL_DONT_CARE:
+            // default
+            break;
+
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    return stream;
+}
+
+// EGL platforms
+namespace egl_platform
+{
+
+EGLPlatformParameters DEFAULT()
+{
+    return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+}
+
+EGLPlatformParameters DEFAULT_NULL()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE,
+        EGL_DONT_CARE, EGL_DONT_CARE,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+}
+
+EGLPlatformParameters D3D9()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
+        EGL_DONT_CARE, EGL_DONT_CARE,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D9_NULL()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
+        EGL_DONT_CARE, EGL_DONT_CARE,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+}
+
+EGLPlatformParameters D3D9_REFERENCE()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
+        EGL_DONT_CARE, EGL_DONT_CARE,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        EGL_DONT_CARE, EGL_DONT_CARE,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11(EGLenum presentPath)
+{
+    return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_DONT_CARE, EGL_DONT_CARE,
+                                 EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, presentPath);
+}
+
+EGLPlatformParameters D3D11_FL11_1()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        11, 1,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_0()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        11, 0,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_1()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        10, 1,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_0()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        10, 0,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL9_3()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        9, 3,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_NULL()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        EGL_DONT_CARE, EGL_DONT_CARE,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+}
+
+EGLPlatformParameters D3D11_WARP()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        EGL_DONT_CARE, EGL_DONT_CARE,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_1_WARP()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        11, 1,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_0_WARP()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        11, 0,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_1_WARP()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        10, 1,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_0_WARP()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        10, 0,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL9_3_WARP()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        9, 3,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_REFERENCE()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        EGL_DONT_CARE, EGL_DONT_CARE,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_1_REFERENCE()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        11, 1,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_0_REFERENCE()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        11, 0,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_1_REFERENCE()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        10, 1,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_0_REFERENCE()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        10, 0,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL9_3_REFERENCE()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+        9, 3,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters OPENGL()
+{
+    return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE);
+}
+
+
+EGLPlatformParameters OPENGL(EGLint major, EGLint minor)
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
+        major, minor,
+        EGL_DONT_CARE);
+}
+
+EGLPlatformParameters OPENGL_NULL()
+{
+    return EGLPlatformParameters(
+        EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
+        0, 0,
+        EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+}
+
+EGLPlatformParameters OPENGLES()
+{
+    return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE);
+}
+
+EGLPlatformParameters OPENGLES(EGLint major, EGLint minor)
+{
+    return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, major, minor,
+                                 EGL_DONT_CARE);
+}
+
+EGLPlatformParameters VULKAN()
+{
+    return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
+}
+
+}  // namespace egl_platform
+
+// ANGLE tests platforms
+PlatformParameters ES2_D3D9()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D9());
+}
+
+PlatformParameters ES2_D3D9_REFERENCE()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D9_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11());
+}
+
+PlatformParameters ES2_D3D11(EGLenum presentPath)
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11(presentPath));
+}
+
+PlatformParameters ES2_D3D11_FL11_0()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL11_0());
+}
+
+PlatformParameters ES2_D3D11_FL10_1()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL10_1());
+}
+
+PlatformParameters ES2_D3D11_FL10_0()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL10_0());
+}
+
+PlatformParameters ES2_D3D11_FL9_3()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL9_3());
+}
+
+PlatformParameters ES2_D3D11_WARP()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_WARP());
+}
+
+PlatformParameters ES2_D3D11_FL11_0_WARP()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL11_0_WARP());
+}
+
+PlatformParameters ES2_D3D11_FL10_1_WARP()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL10_1_WARP());
+}
+
+PlatformParameters ES2_D3D11_FL10_0_WARP()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL10_0_WARP());
+}
+
+PlatformParameters ES2_D3D11_FL9_3_WARP()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL9_3_WARP());
+}
+
+PlatformParameters ES2_D3D11_REFERENCE()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11_FL11_0_REFERENCE()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL11_0_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11_FL10_1_REFERENCE()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL10_1_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11_FL10_0_REFERENCE()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL10_0_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11_FL9_3_REFERENCE()
+{
+    return PlatformParameters(2, 0, egl_platform::D3D11_FL9_3_REFERENCE());
+}
+
+PlatformParameters ES3_D3D11()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11());
+}
+
+PlatformParameters ES3_D3D11_FL11_1()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_FL11_1());
+}
+
+PlatformParameters ES3_D3D11_FL11_0()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_FL11_0());
+}
+
+PlatformParameters ES3_D3D11_FL10_1()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_FL10_1());
+}
+
+PlatformParameters ES31_D3D11()
+{
+    return PlatformParameters(3, 1, egl_platform::D3D11());
+}
+
+PlatformParameters ES31_D3D11_FL11_1()
+{
+    return PlatformParameters(3, 1, egl_platform::D3D11_FL11_1());
+}
+
+PlatformParameters ES31_D3D11_FL11_0()
+{
+    return PlatformParameters(3, 1, egl_platform::D3D11_FL11_0());
+}
+
+PlatformParameters ES3_D3D11_WARP()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_WARP());
+}
+
+PlatformParameters ES3_D3D11_FL11_1_WARP()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_FL11_1_WARP());
+}
+
+PlatformParameters ES3_D3D11_FL11_0_WARP()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_FL11_0_WARP());
+}
+
+PlatformParameters ES3_D3D11_FL10_1_WARP()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_FL10_1_WARP());
+}
+
+PlatformParameters ES3_D3D11_REFERENCE()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_REFERENCE());
+}
+
+PlatformParameters ES3_D3D11_FL11_1_REFERENCE()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_FL11_1_REFERENCE());
+}
+
+PlatformParameters ES3_D3D11_FL11_0_REFERENCE()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_FL11_0_REFERENCE());
+}
+
+PlatformParameters ES3_D3D11_FL10_1_REFERENCE()
+{
+    return PlatformParameters(3, 0, egl_platform::D3D11_FL10_1_REFERENCE());
+}
+
+PlatformParameters ES2_OPENGLES()
+{
+    return PlatformParameters(2, 0, egl_platform::OPENGLES());
+}
+
+PlatformParameters ES2_OPENGLES(EGLint major, EGLint minor)
+{
+    return PlatformParameters(2, 0, egl_platform::OPENGLES(major, minor));
+}
+
+PlatformParameters ES3_OPENGLES()
+{
+    return PlatformParameters(3, 0, egl_platform::OPENGLES());
+}
+
+PlatformParameters ES3_OPENGLES(EGLint major, EGLint minor)
+{
+    return PlatformParameters(3, 0, egl_platform::OPENGLES(major, minor));
+}
+
+PlatformParameters ES31_OPENGLES()
+{
+    return PlatformParameters(3, 1, egl_platform::OPENGLES());
+}
+
+PlatformParameters ES31_OPENGLES(EGLint major, EGLint minor)
+{
+    return PlatformParameters(3, 1, egl_platform::OPENGLES(major, minor));
+}
+
+PlatformParameters ES2_OPENGL()
+{
+    return PlatformParameters(2, 0, egl_platform::OPENGL());
+}
+
+PlatformParameters ES2_OPENGL(EGLint major, EGLint minor)
+{
+    return PlatformParameters(2, 0, egl_platform::OPENGL(major, minor));
+}
+
+PlatformParameters ES3_OPENGL()
+{
+    return PlatformParameters(3, 0, egl_platform::OPENGL());
+}
+
+PlatformParameters ES3_OPENGL(EGLint major, EGLint minor)
+{
+    return PlatformParameters(3, 0, egl_platform::OPENGL(major, minor));
+}
+
+PlatformParameters ES31_OPENGL()
+{
+    return PlatformParameters(3, 1, egl_platform::OPENGL());
+}
+
+PlatformParameters ES31_OPENGL(EGLint major, EGLint minor)
+{
+    return PlatformParameters(3, 1, egl_platform::OPENGL(major, minor));
+}
+
+PlatformParameters ES2_NULL()
+{
+    return PlatformParameters(2, 0, EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE));
+}
+
+PlatformParameters ES3_NULL()
+{
+    return PlatformParameters(3, 0, EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE));
+}
+
+PlatformParameters ES31_NULL()
+{
+    return PlatformParameters(3, 1, EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE));
+}
+
+PlatformParameters ES2_VULKAN()
+{
+    return PlatformParameters(2, 0, egl_platform::VULKAN());
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/test_utils/angle_test_configs.h b/src/third_party/angle/src/tests/test_utils/angle_test_configs.h
new file mode 100644
index 0000000..5d8e6d0
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/angle_test_configs.h
@@ -0,0 +1,152 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef ANGLE_TEST_CONFIGS_H_
+#define ANGLE_TEST_CONFIGS_H_
+
+// On Linux EGL/egl.h includes X.h which does defines for some very common
+// names that are used by gtest (like None and Bool) and causes a lot of
+// compilation errors. To work around this, even if this file doesn't use it,
+// we include gtest before EGL so that it compiles fine in other files that
+// want to use gtest.
+#include <gtest/gtest.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "angle_test_instantiate.h"
+#include "EGLWindow.h"
+
+namespace angle
+{
+
+struct PlatformParameters
+{
+    PlatformParameters();
+    PlatformParameters(EGLint majorVersion, EGLint minorVersion,
+                       const EGLPlatformParameters &eglPlatformParameters);
+
+    EGLint getRenderer() const;
+
+    EGLint majorVersion;
+    EGLint minorVersion;
+    EGLPlatformParameters eglParameters;
+};
+
+bool operator<(const PlatformParameters &a, const PlatformParameters &b);
+bool operator==(const PlatformParameters &a, const PlatformParameters &b);
+std::ostream &operator<<(std::ostream& stream, const PlatformParameters &pp);
+
+// EGL platforms
+namespace egl_platform
+{
+
+EGLPlatformParameters DEFAULT();
+EGLPlatformParameters DEFAULT_NULL();
+
+EGLPlatformParameters D3D9();
+EGLPlatformParameters D3D9_NULL();
+EGLPlatformParameters D3D9_REFERENCE();
+
+EGLPlatformParameters D3D11();
+EGLPlatformParameters D3D11(EGLenum presentPath);
+EGLPlatformParameters D3D11_FL11_1();
+EGLPlatformParameters D3D11_FL11_0();
+EGLPlatformParameters D3D11_FL10_1();
+EGLPlatformParameters D3D11_FL10_0();
+EGLPlatformParameters D3D11_FL9_3();
+
+EGLPlatformParameters D3D11_NULL();
+
+EGLPlatformParameters D3D11_WARP();
+EGLPlatformParameters D3D11_FL11_1_WARP();
+EGLPlatformParameters D3D11_FL11_0_WARP();
+EGLPlatformParameters D3D11_FL10_1_WARP();
+EGLPlatformParameters D3D11_FL10_0_WARP();
+EGLPlatformParameters D3D11_FL9_3_WARP();
+
+EGLPlatformParameters D3D11_REFERENCE();
+EGLPlatformParameters D3D11_FL11_1_REFERENCE();
+EGLPlatformParameters D3D11_FL11_0_REFERENCE();
+EGLPlatformParameters D3D11_FL10_1_REFERENCE();
+EGLPlatformParameters D3D11_FL10_0_REFERENCE();
+EGLPlatformParameters D3D11_FL9_3_REFERENCE();
+
+EGLPlatformParameters OPENGL();
+EGLPlatformParameters OPENGL(EGLint major, EGLint minor);
+EGLPlatformParameters OPENGL_NULL();
+
+EGLPlatformParameters OPENGLES();
+EGLPlatformParameters OPENGLES(EGLint major, EGLint minor);
+
+EGLPlatformParameters VULKAN();
+
+}  // namespace egl_platform
+
+// ANGLE tests platforms
+PlatformParameters ES2_D3D9();
+PlatformParameters ES2_D3D9_REFERENCE();
+
+PlatformParameters ES2_D3D11();
+PlatformParameters ES2_D3D11(EGLenum presentPath);
+PlatformParameters ES2_D3D11_FL11_0();
+PlatformParameters ES2_D3D11_FL10_1();
+PlatformParameters ES2_D3D11_FL10_0();
+PlatformParameters ES2_D3D11_FL9_3();
+
+PlatformParameters ES2_D3D11_WARP();
+PlatformParameters ES2_D3D11_FL11_0_WARP();
+PlatformParameters ES2_D3D11_FL10_1_WARP();
+PlatformParameters ES2_D3D11_FL10_0_WARP();
+PlatformParameters ES2_D3D11_FL9_3_WARP();
+
+PlatformParameters ES2_D3D11_REFERENCE();
+PlatformParameters ES2_D3D11_FL11_0_REFERENCE();
+PlatformParameters ES2_D3D11_FL10_1_REFERENCE();
+PlatformParameters ES2_D3D11_FL10_0_REFERENCE();
+PlatformParameters ES2_D3D11_FL9_3_REFERENCE();
+
+PlatformParameters ES3_D3D11();
+PlatformParameters ES3_D3D11_FL11_1();
+PlatformParameters ES3_D3D11_FL11_0();
+PlatformParameters ES3_D3D11_FL10_1();
+PlatformParameters ES31_D3D11();
+PlatformParameters ES31_D3D11_FL11_1();
+PlatformParameters ES31_D3D11_FL11_0();
+
+PlatformParameters ES3_D3D11_WARP();
+PlatformParameters ES3_D3D11_FL11_1_WARP();
+PlatformParameters ES3_D3D11_FL11_0_WARP();
+PlatformParameters ES3_D3D11_FL10_1_WARP();
+
+PlatformParameters ES3_D3D11_REFERENCE();
+PlatformParameters ES3_D3D11_FL11_1_REFERENCE();
+PlatformParameters ES3_D3D11_FL11_0_REFERENCE();
+PlatformParameters ES3_D3D11_FL10_1_REFERENCE();
+
+PlatformParameters ES2_OPENGL();
+PlatformParameters ES2_OPENGL(EGLint major, EGLint minor);
+PlatformParameters ES3_OPENGL();
+PlatformParameters ES3_OPENGL(EGLint major, EGLint minor);
+PlatformParameters ES31_OPENGL();
+PlatformParameters ES31_OPENGL(EGLint major, EGLint minor);
+
+PlatformParameters ES2_OPENGLES();
+PlatformParameters ES2_OPENGLES(EGLint major, EGLint minor);
+PlatformParameters ES3_OPENGLES();
+PlatformParameters ES3_OPENGLES(EGLint major, EGLint minor);
+PlatformParameters ES31_OPENGLES();
+PlatformParameters ES31_OPENGLES(EGLint major, EGLint minor);
+
+PlatformParameters ES2_NULL();
+PlatformParameters ES3_NULL();
+PlatformParameters ES31_NULL();
+
+PlatformParameters ES2_VULKAN();
+
+}  // namespace angle
+
+#endif // ANGLE_TEST_CONFIGS_H_
diff --git a/src/third_party/angle/src/tests/test_utils/angle_test_instantiate.cpp b/src/third_party/angle/src/tests/test_utils/angle_test_instantiate.cpp
new file mode 100644
index 0000000..69fc227
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/angle_test_instantiate.cpp
@@ -0,0 +1,104 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angle_test_instantiate.cpp: Adds support for filtering parameterized
+// tests by platform, so we skip unsupported configs.
+
+#include "test_utils/angle_test_instantiate.h"
+
+#include <map>
+#include <iostream>
+
+#include "EGLWindow.h"
+#include "OSWindow.h"
+#include "test_utils/angle_test_configs.h"
+
+namespace angle
+{
+
+bool IsPlatformAvailable(const PlatformParameters &param)
+{
+    switch (param.getRenderer())
+    {
+        case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+            break;
+
+        case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+#if !defined(ANGLE_ENABLE_D3D9)
+            return false;
+#else
+            break;
+#endif
+
+        case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+#if !defined(ANGLE_ENABLE_D3D11)
+            return false;
+#else
+            break;
+#endif
+
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+        case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+#if !defined(ANGLE_ENABLE_OPENGL)
+            return false;
+#else
+            break;
+#endif
+
+        case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+#if !defined(ANGLE_ENABLE_VULKAN)
+            return false;
+#else
+            break;
+#endif
+
+      case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
+#ifndef ANGLE_ENABLE_NULL
+          return false;
+#endif
+          break;
+
+      default:
+          std::cout << "Unknown test platform: " << param << std::endl;
+          return false;
+    }
+
+    static std::map<PlatformParameters, bool> paramAvailabilityCache;
+    auto iter = paramAvailabilityCache.find(param);
+    if (iter != paramAvailabilityCache.end())
+    {
+        return iter->second;
+    }
+    else
+    {
+        OSWindow *osWindow = CreateOSWindow();
+        bool result = osWindow->initialize("CONFIG_TESTER", 1, 1);
+
+        if (result)
+        {
+            EGLWindow *eglWindow =
+                new EGLWindow(param.majorVersion, param.minorVersion, param.eglParameters);
+            result = eglWindow->initializeGL(osWindow);
+
+            eglWindow->destroyGL();
+            SafeDelete(eglWindow);
+        }
+
+        osWindow->destroy();
+        SafeDelete(osWindow);
+
+        paramAvailabilityCache[param] = result;
+
+        if (!result)
+        {
+            std::cout << "Skipping tests using configuration " << param << " because it is not available." << std::endl;
+        }
+
+        return result;
+    }
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/src/tests/test_utils/angle_test_instantiate.h b/src/third_party/angle/src/tests/test_utils/angle_test_instantiate.h
new file mode 100644
index 0000000..a7b6a81
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/angle_test_instantiate.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angle_test_instantiate.h: Adds support for filtering parameterized
+// tests by platform, so we skip unsupported configs.
+
+#ifndef ANGLE_TEST_INSTANTIATE_H_
+#define ANGLE_TEST_INSTANTIATE_H_
+
+#include <gtest/gtest.h>
+
+#include "common/debug.h"
+
+namespace angle
+{
+
+struct PlatformParameters;
+
+bool IsPlatformAvailable(const PlatformParameters &param);
+
+// This functions is used to filter which tests should be registered,
+// T must be or inherit from angle::PlatformParameters.
+template <typename T>
+std::vector<T> FilterTestParams(const T *params, size_t numParams)
+{
+    std::vector<T> filtered;
+
+    for (size_t i = 0; i < numParams; i++)
+    {
+        if (IsPlatformAvailable(params[i]))
+        {
+            filtered.push_back(params[i]);
+        }
+    }
+
+    return filtered;
+}
+
+// Instantiate the test once for each extra argument. The types of all the
+// arguments must match, and getRenderer must be implemented for that type.
+#define ANGLE_INSTANTIATE_TEST(testName, firstParam, ...) \
+    const decltype(firstParam) testName##params[] = { firstParam, ##__VA_ARGS__ }; \
+    INSTANTIATE_TEST_CASE_P(, testName, \
+                              testing::ValuesIn(::angle::FilterTestParams(testName##params, ArraySize(testName##params))), \
+                              testing::PrintToStringParamName());
+
+} // namespace angle
+
+#endif // ANGLE_TEST_INSTANTIATE_H_
diff --git a/src/third_party/angle/src/tests/test_utils/compiler_test.cpp b/src/third_party/angle/src/tests/test_utils/compiler_test.cpp
new file mode 100644
index 0000000..e5d48e6
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/compiler_test.cpp
@@ -0,0 +1,220 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// compiler_test.cpp:
+//     utilities for compiler unit tests.
+
+#include "tests/test_utils/compiler_test.h"
+
+#include "angle_gl.h"
+#include "compiler/translator/Compiler.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class FunctionCallFinder : public TIntermTraverser
+{
+  public:
+    FunctionCallFinder(const TString &functionMangledName)
+        : TIntermTraverser(true, false, false),
+          mFunctionMangledName(functionMangledName),
+          mNodeFound(nullptr)
+    {
+    }
+
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override
+    {
+        if (node->isFunctionCall() && node->getSymbolTableMangledName() == mFunctionMangledName)
+        {
+            mNodeFound = node;
+            return false;
+        }
+        return true;
+    }
+
+    bool isFound() const { return mNodeFound != nullptr; }
+    const TIntermAggregate *getNode() const { return mNodeFound; }
+
+  private:
+    TString mFunctionMangledName;
+    TIntermAggregate *mNodeFound;
+};
+
+}  // anonymous namespace
+
+bool compileTestShader(GLenum type,
+                       ShShaderSpec spec,
+                       ShShaderOutput output,
+                       const std::string &shaderString,
+                       ShBuiltInResources *resources,
+                       ShCompileOptions compileOptions,
+                       std::string *translatedCode,
+                       std::string *infoLog)
+{
+    sh::TCompiler *translator = sh::ConstructCompiler(type, spec, output);
+    if (!translator->Init(*resources))
+    {
+        SafeDelete(translator);
+        return false;
+    }
+
+    const char *shaderStrings[] = { shaderString.c_str() };
+
+    bool compilationSuccess = translator->compile(shaderStrings, 1, SH_OBJECT_CODE | compileOptions);
+    TInfoSink &infoSink = translator->getInfoSink();
+    if (translatedCode)
+        *translatedCode = infoSink.obj.c_str();
+    if (infoLog)
+        *infoLog = infoSink.info.c_str();
+    SafeDelete(translator);
+    return compilationSuccess;
+}
+
+bool compileTestShader(GLenum type,
+                       ShShaderSpec spec,
+                       ShShaderOutput output,
+                       const std::string &shaderString,
+                       ShCompileOptions compileOptions,
+                       std::string *translatedCode,
+                       std::string *infoLog)
+{
+    ShBuiltInResources resources;
+    sh::InitBuiltInResources(&resources);
+    return compileTestShader(type, spec, output, shaderString, &resources, compileOptions, translatedCode, infoLog);
+}
+
+MatchOutputCodeTest::MatchOutputCodeTest(GLenum shaderType,
+                                         ShCompileOptions defaultCompileOptions,
+                                         ShShaderOutput outputType)
+    : mShaderType(shaderType), mDefaultCompileOptions(defaultCompileOptions)
+{
+    sh::InitBuiltInResources(&mResources);
+    mOutputCode[outputType] = std::string();
+}
+
+void MatchOutputCodeTest::addOutputType(const ShShaderOutput outputType)
+{
+    mOutputCode[outputType] = std::string();
+}
+
+ShBuiltInResources *MatchOutputCodeTest::getResources()
+{
+    return &mResources;
+}
+
+void MatchOutputCodeTest::compile(const std::string &shaderString)
+{
+    compile(shaderString, mDefaultCompileOptions);
+}
+
+void MatchOutputCodeTest::compile(const std::string &shaderString,
+                                  const ShCompileOptions compileOptions)
+{
+    std::string infoLog;
+    for (auto &code : mOutputCode)
+    {
+        bool compilationSuccess =
+            compileWithSettings(code.first, shaderString, compileOptions, &code.second, &infoLog);
+        if (!compilationSuccess)
+        {
+            FAIL() << "Shader compilation failed:\n" << infoLog;
+        }
+    }
+}
+
+bool MatchOutputCodeTest::compileWithSettings(ShShaderOutput output,
+                                              const std::string &shaderString,
+                                              const ShCompileOptions compileOptions,
+                                              std::string *translatedCode,
+                                              std::string *infoLog)
+{
+    return compileTestShader(mShaderType, SH_GLES3_SPEC, output, shaderString, &mResources,
+                             compileOptions, translatedCode, infoLog);
+}
+
+bool MatchOutputCodeTest::foundInCode(ShShaderOutput output, const char *stringToFind) const
+{
+    const auto code = mOutputCode.find(output);
+    EXPECT_NE(mOutputCode.end(), code);
+    if (code == mOutputCode.end())
+    {
+        return false;
+    }
+
+    return code->second.find(stringToFind) != std::string::npos;
+}
+
+bool MatchOutputCodeTest::foundInCode(ShShaderOutput output,
+                                      const char *stringToFind,
+                                      const int expectedOccurrences) const
+{
+    const auto code = mOutputCode.find(output);
+    EXPECT_NE(mOutputCode.end(), code);
+    if (code == mOutputCode.end())
+    {
+        return false;
+    }
+
+    size_t currentPos  = 0;
+    int occurencesLeft = expectedOccurrences;
+    while (occurencesLeft-- > 0)
+    {
+        auto position = code->second.find(stringToFind, currentPos);
+        if (position == std::string::npos)
+        {
+            return false;
+        }
+        currentPos = position + 1;
+    }
+    return code->second.find(stringToFind, currentPos) == std::string::npos;
+}
+
+bool MatchOutputCodeTest::foundInCode(const char *stringToFind) const
+{
+    for (auto &code : mOutputCode)
+    {
+        if (!foundInCode(code.first, stringToFind))
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool MatchOutputCodeTest::foundInCode(const char *stringToFind, const int expectedOccurrences) const
+{
+    for (auto &code : mOutputCode)
+    {
+        if (!foundInCode(code.first, stringToFind, expectedOccurrences))
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool MatchOutputCodeTest::notFoundInCode(const char *stringToFind) const
+{
+    for (auto &code : mOutputCode)
+    {
+        if (foundInCode(code.first, stringToFind))
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+const TIntermAggregate *FindFunctionCallNode(TIntermNode *root, const TString &functionMangledName)
+{
+    FunctionCallFinder finder(functionMangledName);
+    root->traverse(&finder);
+    return finder.getNode();
+}
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/tests/test_utils/compiler_test.h b/src/third_party/angle/src/tests/test_utils/compiler_test.h
new file mode 100644
index 0000000..feb4dea
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/compiler_test.h
@@ -0,0 +1,100 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// compiler_test.h:
+//     utilities for compiler unit tests.
+
+#ifndef TESTS_TEST_UTILS_COMPILER_TEST_H_
+#define TESTS_TEST_UTILS_COMPILER_TEST_H_
+
+#include <map>
+
+#include "gtest/gtest.h"
+
+#include "angle_gl.h"
+#include "compiler/translator/TranslatorESSL.h"
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/FindSymbolNode.h"
+
+namespace sh
+{
+
+bool compileTestShader(GLenum type,
+                       ShShaderSpec spec,
+                       ShShaderOutput output,
+                       const std::string &shaderString,
+                       ShBuiltInResources *resources,
+                       ShCompileOptions compileOptions,
+                       std::string *translatedCode,
+                       std::string *infoLog);
+
+bool compileTestShader(GLenum type,
+                       ShShaderSpec spec,
+                       ShShaderOutput output,
+                       const std::string &shaderString,
+                       ShCompileOptions compileOptions,
+                       std::string *translatedCode,
+                       std::string *infoLog);
+
+class MatchOutputCodeTest : public testing::Test
+{
+  protected:
+    MatchOutputCodeTest(GLenum shaderType,
+                        ShCompileOptions defaultCompileOptions,
+                        ShShaderOutput outputType);
+
+    void addOutputType(const ShShaderOutput outputType);
+
+    ShBuiltInResources *getResources();
+
+    // Compile functions clear any results from earlier calls to them.
+    void compile(const std::string &shaderString);
+    void compile(const std::string &shaderString, const ShCompileOptions compileOptions);
+
+    bool foundInESSLCode(const char *stringToFind) const
+    {
+        return foundInCode(SH_ESSL_OUTPUT, stringToFind);
+    }
+
+    bool foundInGLSLCode(const char *stringToFind) const
+    {
+        return foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, stringToFind);
+    }
+
+    bool foundInCode(ShShaderOutput output, const char *stringToFind) const;
+
+    // Test that the string occurs for exactly expectedOccurrences times
+    bool foundInCode(ShShaderOutput output,
+                     const char *stringToFind,
+                     const int expectedOccurrences) const;
+
+    // Test that the string is found in all outputs
+    bool foundInCode(const char *stringToFind) const;
+
+    // Test that the string occurs for exactly expectedOccurrences times in all outputs
+    bool foundInCode(const char *stringToFind, const int expectedOccurrences) const;
+
+    // Test that the string is found in none of the outputs
+    bool notFoundInCode(const char *stringToFind) const;
+
+  private:
+    bool compileWithSettings(ShShaderOutput output,
+                             const std::string &shaderString,
+                             ShCompileOptions compileOptions,
+                             std::string *translatedCode,
+                             std::string *infoLog);
+
+    GLenum mShaderType;
+    ShCompileOptions mDefaultCompileOptions;
+    ShBuiltInResources mResources;
+
+    std::map<ShShaderOutput, std::string> mOutputCode;
+};
+
+// Returns a pointer to a function call node with a mangled name functionName.
+const TIntermAggregate *FindFunctionCallNode(TIntermNode *root, const TString &functionName);
+}
+
+#endif // TESTS_TEST_UTILS_COMPILER_TEST_H_
diff --git a/src/third_party/angle/src/tests/test_utils/draw_call_perf_utils.cpp b/src/third_party/angle/src/tests/test_utils/draw_call_perf_utils.cpp
new file mode 100644
index 0000000..e6c316c
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/draw_call_perf_utils.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright (c) 2017 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.
+//
+// draw_call_perf_utils.cpp:
+//   Common utilities for performance tests that need to do a large amount of draw calls.
+//
+
+#include "draw_call_perf_utils.h"
+
+#include <vector>
+
+#include "shader_utils.h"
+
+namespace
+{
+
+const char *SimpleScaleAndOffsetVertexShaderSource()
+{
+    // clang-format off
+    return SHADER_SOURCE
+    (
+        attribute vec2 vPosition;
+        uniform float uScale;
+        uniform float uOffset;
+        void main()
+        {
+            gl_Position = vec4(vPosition * vec2(uScale) + vec2(uOffset), 0, 1);
+        }
+    );
+    // clang-format on
+}
+
+const char *SimpleDrawVertexShaderSource()
+{
+    // clang-format off
+    return SHADER_SOURCE
+    (
+        attribute vec2 vPosition;
+        const float scale = 0.5;
+        const float offset = -0.5;
+
+        void main()
+        {
+            gl_Position = vec4(vPosition * vec2(scale) + vec2(offset), 0, 1);
+        }
+    );
+    // clang-format on
+}
+
+const char *SimpleFragmentShaderSource()
+{
+    // clang-format off
+    return SHADER_SOURCE
+    (
+        precision mediump float;
+        void main()
+        {
+            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+        }
+    );
+    // clang-format on
+}
+
+void Generate2DTriangleData(size_t numTris, std::vector<float> *floatData)
+{
+    for (size_t triIndex = 0; triIndex < numTris; ++triIndex)
+    {
+        floatData->push_back(1.0f);
+        floatData->push_back(2.0f);
+
+        floatData->push_back(0.0f);
+        floatData->push_back(0.0f);
+
+        floatData->push_back(2.0f);
+        floatData->push_back(0.0f);
+    }
+}
+
+}  // anonymous namespace
+
+GLuint SetupSimpleScaleAndOffsetProgram()
+{
+    const std::string vs = SimpleScaleAndOffsetVertexShaderSource();
+    const std::string fs = SimpleFragmentShaderSource();
+    GLuint program       = CompileProgram(vs, fs);
+    if (program == 0u)
+    {
+        return program;
+    }
+
+    // Use the program object
+    glUseProgram(program);
+
+    GLfloat scale  = 0.5f;
+    GLfloat offset = -0.5f;
+
+    glUniform1f(glGetUniformLocation(program, "uScale"), scale);
+    glUniform1f(glGetUniformLocation(program, "uOffset"), offset);
+    return program;
+}
+
+GLuint SetupSimpleDrawProgram()
+{
+    const std::string vs = SimpleDrawVertexShaderSource();
+    const std::string fs = SimpleFragmentShaderSource();
+    GLuint program       = CompileProgram(vs, fs);
+    if (program == 0u)
+    {
+        return program;
+    }
+
+    // Use the program object
+    glUseProgram(program);
+
+    return program;
+}
+
+GLuint Create2DTriangleBuffer(size_t numTris, GLenum usage)
+{
+    GLuint buffer = 0u;
+    glGenBuffers(1, &buffer);
+    glBindBuffer(GL_ARRAY_BUFFER, buffer);
+
+    std::vector<GLfloat> floatData;
+    Generate2DTriangleData(numTris, &floatData);
+
+    // To avoid generating GL errors when testing validation-only with zero triangles.
+    if (floatData.empty())
+    {
+        floatData.push_back(0.0f);
+    }
+
+    glBufferData(GL_ARRAY_BUFFER, floatData.size() * sizeof(GLfloat), &floatData[0], usage);
+
+    return buffer;
+}
+
+void CreateColorFBO(GLsizei width, GLsizei height, GLuint *fbo, GLuint *texture)
+{
+    glGenFramebuffers(1, fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
+    glGenTextures(1, texture);
+    glBindTexture(GL_TEXTURE_2D, *texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texture, 0);
+}
diff --git a/src/third_party/angle/src/tests/test_utils/draw_call_perf_utils.h b/src/third_party/angle/src/tests/test_utils/draw_call_perf_utils.h
new file mode 100644
index 0000000..f8c83f9
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/draw_call_perf_utils.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2017 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.
+//
+// draw_call_perf_utils.h:
+//   Common utilities for performance tests that need to do a large amount of draw calls.
+//
+
+#ifndef TESTS_TEST_UTILS_DRAW_CALL_PERF_UTILS_H_
+#define TESTS_TEST_UTILS_DRAW_CALL_PERF_UTILS_H_
+
+#include <stddef.h>
+
+#include "angle_gl.h"
+
+// Returns program ID. The program is left in use, no uniforms.
+GLuint SetupSimpleDrawProgram();
+
+// Returns program ID. The program is left in use and the uniforms are set to default values:
+// uScale = 0.5, uOffset = -0.5
+GLuint SetupSimpleScaleAndOffsetProgram();
+
+// Returns buffer ID filled with 2-component triangle coordinates. The buffer is left as bound.
+// Generates triangles like this with 2-component coordinates:
+//    A
+//   / \.
+//  /   \.
+// B-----C
+GLuint Create2DTriangleBuffer(size_t numTris, GLenum usage);
+
+// Creates an FBO with a texture color attachment. The texture is GL_RGBA and has dimensions
+// width/height. The FBO and texture ids are written to the out parameters.
+void CreateColorFBO(GLsizei width, GLsizei height, GLuint *fbo, GLuint *texture);
+
+#endif  // TESTS_TEST_UTILS_DRAW_CALL_PERF_UTILS_H_
diff --git a/src/third_party/angle/src/tests/test_utils/gl_raii.h b/src/third_party/angle/src/tests/test_utils/gl_raii.h
new file mode 100644
index 0000000..01a6530
--- /dev/null
+++ b/src/third_party/angle/src/tests/test_utils/gl_raii.h
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2016 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.
+//
+// gl_raii:
+//   Helper methods for containing GL objects like buffers and textures.
+
+#ifndef ANGLE_TESTS_GL_RAII_H_
+#define ANGLE_TESTS_GL_RAII_H_
+
+#include <functional>
+
+#include "angle_gl.h"
+
+namespace angle
+{
+
+// This is a bit of hack to work around a bug in MSVS intellisense, and make it very easy to
+// use the correct function pointer type without worrying about the various definitions of
+// GL_APICALL.
+using GLGen    = decltype(glGenBuffers);
+using GLDelete = decltype(glDeleteBuffers);
+
+template <GLGen GenF, GLDelete DeleteF>
+class GLWrapper
+{
+  public:
+    GLWrapper() {}
+    ~GLWrapper() { DeleteF(1, &mHandle); }
+
+    GLuint get()
+    {
+        if (!mHandle)
+        {
+            GenF(1, &mHandle);
+        }
+        return mHandle;
+    }
+
+    operator GLuint() { return get(); }
+
+  private:
+    GLuint mHandle = 0;
+};
+
+using GLBuffer       = GLWrapper<glGenBuffers, glDeleteBuffers>;
+using GLTexture      = GLWrapper<glGenTextures, glDeleteTextures>;
+using GLFramebuffer  = GLWrapper<glGenFramebuffers, glDeleteFramebuffers>;
+using GLRenderbuffer = GLWrapper<glGenRenderbuffers, glDeleteRenderbuffers>;
+using GLSampler      = GLWrapper<glGenSamplers, glDeleteSamplers>;
+
+// Don't use GLProgram directly, use ANGLE_GL_PROGRAM.
+namespace priv
+{
+class GLProgram
+{
+  public:
+    GLProgram() : mHandle(0) {}
+
+    ~GLProgram() { glDeleteProgram(mHandle); }
+
+    void makeCompute(const std::string &computeShader)
+    {
+        mHandle = CompileComputeProgram(computeShader);
+    }
+
+    void makeRaster(const std::string &vertexShader, const std::string &fragmentShader)
+    {
+        mHandle = CompileProgram(vertexShader, fragmentShader);
+    }
+
+    void makeBinaryOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
+    {
+        mHandle = LoadBinaryProgramOES(binary, binaryFormat);
+    }
+
+    void makeBinaryES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
+    {
+        mHandle = LoadBinaryProgramES3(binary, binaryFormat);
+    }
+
+    bool valid() const { return mHandle != 0; }
+
+    GLuint get()
+    {
+        ASSERT(valid());
+        return mHandle;
+    }
+
+    operator GLuint() { return get(); }
+
+  private:
+    GLuint mHandle;
+};
+}  // namespace priv
+
+#define ANGLE_GL_PROGRAM(name, vertex, fragment) \
+    priv::GLProgram name;                        \
+    name.makeRaster(vertex, fragment);           \
+    ASSERT_TRUE(name.valid());
+
+#define ANGLE_GL_COMPUTE_PROGRAM(name, compute) \
+    priv::GLProgram name;                       \
+    name.makeCompute(compute);                  \
+    ASSERT_TRUE(name.valid());
+
+#define ANGLE_GL_BINARY_OES_PROGRAM(name, binary, binaryFormat) \
+    priv::GLProgram name;                                       \
+    name.makeBinaryOES(binary, binaryFormat);                   \
+    ASSERT_TRUE(name.valid());
+
+#define ANGLE_GL_BINARY_ES3_PROGRAM(name, binary, binaryFormat) \
+    priv::GLProgram name;                                       \
+    name.makeBinaryES3(binary, binaryFormat);                   \
+    ASSERT_TRUE(name.valid());
+
+}  // namespace angle
+
+#endif  // ANGLE_TESTS_GL_RAII_H_
diff --git a/src/third_party/angle/src/tests/tests.gyp b/src/third_party/angle/src/tests/tests.gyp
new file mode 100644
index 0000000..854ba8e
--- /dev/null
+++ b/src/third_party/angle/src/tests/tests.gyp
@@ -0,0 +1,362 @@
+# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    'includes':
+    [
+        'deqp.gypi',
+        '../../gyp/common_defines.gypi',
+    ],
+    'variables':
+    {
+        'angle_build_conformance_tests%': '0',
+
+        'rapidjson_include_dir': 'third_party/rapidjson/include',
+        'rapidjson_headers':
+        [
+            'third_party/rapidjson/include/rapidjson/allocators.h',
+            'third_party/rapidjson/include/rapidjson/document.h',
+            'third_party/rapidjson/include/rapidjson/encodedstream.h',
+            'third_party/rapidjson/include/rapidjson/encodings.h',
+            'third_party/rapidjson/include/rapidjson/filereadstream.h',
+            'third_party/rapidjson/include/rapidjson/filestream.h',
+            'third_party/rapidjson/include/rapidjson/filewritestream.h',
+            'third_party/rapidjson/include/rapidjson/memorybuffer.h',
+            'third_party/rapidjson/include/rapidjson/memorystream.h',
+            'third_party/rapidjson/include/rapidjson/prettywriter.h',
+            'third_party/rapidjson/include/rapidjson/rapidjson.h',
+            'third_party/rapidjson/include/rapidjson/reader.h',
+            'third_party/rapidjson/include/rapidjson/stringbuffer.h',
+            'third_party/rapidjson/include/rapidjson/writer.h',
+            'third_party/rapidjson/include/rapidjson/error/en.h',
+            'third_party/rapidjson/include/rapidjson/error/error.h',
+            'third_party/rapidjson/include/rapidjson/internal/dtoa.h',
+            'third_party/rapidjson/include/rapidjson/internal/itoa.h',
+            'third_party/rapidjson/include/rapidjson/internal/meta.h',
+            'third_party/rapidjson/include/rapidjson/internal/pow10.h',
+            'third_party/rapidjson/include/rapidjson/internal/stack.h',
+            'third_party/rapidjson/include/rapidjson/internal/strfunc.h',
+            'third_party/rapidjson/include/rapidjson/msinttypes/inttypes.h',
+            'third_party/rapidjson/include/rapidjson/msinttypes/stdint.h',
+        ],
+    },
+    'conditions':
+    [
+        # GoogleTest doesn't support WinRT
+        ['angle_build_winrt==0',
+        {
+            'targets':
+            [
+                {
+                    'target_name': 'angle_test_support',
+                    'type': 'none',
+                    'dependencies':
+                    [
+                        'angle_internal_gmock',
+                        'angle_internal_gtest',
+                    ],
+                },
+            ],
+        }],
+        ['angle_build_winrt==0',
+        {
+            'targets':
+            [
+                # Hide these targets from Chromium, because it can't
+                # find our standalone copy of the gtest/gmock sources.
+                {
+                    'target_name': 'angle_internal_gtest',
+                    'type': 'static_library',
+                    'includes': [ '../../gyp/common_defines.gypi', ],
+                    'include_dirs':
+                    [
+                        '<(angle_path)/testing/gtest',
+                        '<(angle_path)/testing/gtest/include',
+                    ],
+                    'sources':
+                    [
+                        '<(angle_path)/testing/gtest/src/gtest-all.cc',
+                    ],
+                    'defines':
+                    [
+                        '_VARIADIC_MAX=10',
+                    ],
+                    'all_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            '_VARIADIC_MAX=10',
+                        ],
+                        'include_dirs':
+                        [
+                            '<(angle_path)/testing/gtest',
+                            '<(angle_path)/testing/gtest/include',
+                        ],
+                    },
+                },
+
+                {
+                    'target_name': 'angle_internal_gmock',
+                    'type': 'static_library',
+                    'includes': [ '../../gyp/common_defines.gypi', ],
+                    'include_dirs':
+                    [
+                        '<(angle_path)/testing/gmock',
+                        '<(angle_path)/testing/gmock/include',
+                        '<(angle_path)/testing/gtest/include',
+                    ],
+                    'sources':
+                    [
+                        '<(angle_path)/testing/gmock/src/gmock-all.cc',
+                    ],
+                    'defines':
+                    [
+                        '_VARIADIC_MAX=10',
+                    ],
+                    'all_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            '_VARIADIC_MAX=10',
+                        ],
+                        'include_dirs':
+                        [
+                            '<(angle_path)/testing/gmock',
+                            '<(angle_path)/testing/gmock/include',
+                            '<(angle_path)/testing/gtest/include',
+                        ],
+                    },
+                },
+
+                # These same target names exist on the Chromium side,
+                # which is forbidden, so we make them conditional on
+                # ANGLE's standalone build.
+                {
+                    'target_name': 'angle_unittests',
+                    'type': 'executable',
+                    'includes':
+                    [
+                        '../../gyp/common_defines.gypi',
+                        'angle_unittests.gypi',
+                    ],
+                    'sources':
+                    [
+                        'angle_unittests_main.cpp',
+                    ],
+                    'msvs_settings':
+                    {
+                        'VCLinkerTool':
+                        {
+                            'conditions':
+                            [
+                                ['angle_build_winrt==1',
+                                {
+                                    'AdditionalDependencies':
+                                    [
+                                        'runtimeobject.lib',
+                                    ],
+                                }],
+                            ],
+                        },
+                    },
+                    'msvs_disabled_warnings':
+                    [
+                        4244, # Conversion from 'type1' to 'type2', possible loss of data
+                    ],
+                },
+                {
+                    'target_name': 'angle_end2end_tests',
+                    'type': 'executable',
+                    'includes':
+                    [
+                        '../../gyp/common_defines.gypi',
+                        'angle_end2end_tests.gypi',
+                    ],
+                    'sources':
+                    [
+                        'angle_end2end_tests_main.cpp',
+                    ],
+                },
+                {
+                    'target_name': 'angle_white_box_tests',
+                    'type': 'executable',
+                    'includes':
+                    [
+                        '../../gyp/common_defines.gypi',
+                        'angle_white_box_tests.gypi',
+                    ],
+                    'sources':
+                    [
+                        'angle_white_box_tests_main.cpp',
+                    ],
+                },
+                {
+                    'target_name': 'angle_perftests',
+                    'type': 'executable',
+                    'includes':
+                    [
+                        '../../gyp/common_defines.gypi',
+                        'angle_perftests.gypi',
+                    ],
+                    'sources':
+                    [
+                        'angle_perftests_main.cpp',
+                    ],
+                },
+            ],
+        }],
+        ['OS=="win"',
+        {
+            'conditions':
+            [
+                ['angle_build_conformance_tests',
+                {
+                    'variables':
+                    {
+                        'gles_conformance_tests_output_dir': '<(SHARED_INTERMEDIATE_DIR)/conformance_tests',
+                        'gles_conformance_tests_input_dir': 'third_party/gles_conformance_tests/conform/GTF_ES/glsl/GTF',
+                        'gles_conformance_tests_generator_script': 'gles_conformance_tests/generate_gles_conformance_tests.py',
+                    },
+                    'targets':
+                    [
+                        {
+                            'target_name': 'angle_gles2_conformance_tests',
+                            'type': 'executable',
+                            'includes': [ '../../gyp/common_defines.gypi', ],
+                            'dependencies':
+                            [
+                                '<(angle_path)/src/angle.gyp:libGLESv2',
+                                '<(angle_path)/src/angle.gyp:libEGL',
+                                'third_party/gles_conformance_tests/conform/GTF_ES/glsl/GTF/es_cts.gyp:es_cts_test_data',
+                                'third_party/gles_conformance_tests/conform/GTF_ES/glsl/GTF/es_cts.gyp:es2_cts',
+                                'angle_test_support',
+                            ],
+                            'variables':
+                            {
+                                'gles2_conformance_tests_input_file': '<(gles_conformance_tests_input_dir)/mustpass_es20.run',
+                                'gles2_conformance_tests_generated_file': '<(gles_conformance_tests_output_dir)/generated_gles2_conformance_tests.cpp',
+                            },
+                            'sources':
+                            [
+                                'gles_conformance_tests/gles_conformance_tests.cpp',
+                                'gles_conformance_tests/gles_conformance_tests.h',
+                                'gles_conformance_tests/gles_conformance_tests_main.cpp',
+                                '<(gles2_conformance_tests_generated_file)',
+                            ],
+                            'include_dirs':
+                            [
+                                '<(angle_path)/include',
+                                'gles_conformance_tests',
+                            ],
+                            'defines':
+                            [
+                                'CONFORMANCE_TESTS_TYPE=CONFORMANCE_TESTS_ES2',
+                            ],
+                            'msvs_settings':
+                            {
+                                'VCCLCompilerTool':
+                                {
+                                    # MSVS has trouble compiling this due to the obj files becoming too large.
+                                    'AdditionalOptions': [ '/bigobj' ],
+                                },
+                            },
+                            'actions':
+                            [
+                                {
+                                    'action_name': 'generate_gles2_conformance_tests',
+                                    'message': 'Generating ES2 conformance tests...',
+                                    'msvs_cygwin_shell': 0,
+                                    'inputs':
+                                    [
+                                        '<(gles_conformance_tests_generator_script)',
+                                        '<(gles2_conformance_tests_input_file)',
+                                    ],
+                                    'outputs':
+                                    [
+                                        '<(gles2_conformance_tests_generated_file)',
+                                    ],
+                                    'action':
+                                    [
+                                        'python',
+                                        '<(gles_conformance_tests_generator_script)',
+                                        '<(gles2_conformance_tests_input_file)',
+                                        '<(gles_conformance_tests_input_dir)',
+                                        '<(gles2_conformance_tests_generated_file)',
+                                    ],
+                                },
+                            ],
+                        },
+                        {
+                            'target_name': 'angle_gles3_conformance_tests',
+                            'type': 'executable',
+                            'includes': [ '../../gyp/common_defines.gypi', ],
+                            'dependencies':
+                            [
+                                '<(angle_path)/src/angle.gyp:libGLESv2',
+                                '<(angle_path)/src/angle.gyp:libEGL',
+                                'third_party/gles_conformance_tests/conform/GTF_ES/glsl/GTF/es_cts.gyp:es_cts_test_data',
+                                'third_party/gles_conformance_tests/conform/GTF_ES/glsl/GTF/es_cts.gyp:es3_cts',
+                                'angle_test_support',
+                            ],
+                            'variables':
+                            {
+                                'gles3_conformance_tests_input_file': '<(gles_conformance_tests_input_dir)/mustpass_es30.run',
+                                'gles3_conformance_tests_generated_file': '<(gles_conformance_tests_output_dir)/generated_gles3_conformance_tests.cpp',
+                            },
+                            'sources':
+                            [
+                                'gles_conformance_tests/gles_conformance_tests.cpp',
+                                'gles_conformance_tests/gles_conformance_tests.h',
+                                'gles_conformance_tests/gles_conformance_tests_main.cpp',
+                                '<(gles3_conformance_tests_generated_file)',
+                            ],
+                            'include_dirs':
+                            [
+                                '<(angle_path)/include',
+                                'gles_conformance_tests',
+                            ],
+                            'defines':
+                            [
+                                'CONFORMANCE_TESTS_TYPE=CONFORMANCE_TESTS_ES3',
+                            ],
+                            'msvs_settings':
+                            {
+                                'VCCLCompilerTool':
+                                {
+                                    # MSVS has trouble compiling this due to the obj files becoming too large.
+                                    'AdditionalOptions': [ '/bigobj' ],
+                                },
+                            },
+                            'actions':
+                            [
+                                {
+                                    'action_name': 'generate_gles3_conformance_tests',
+                                    'message': 'Generating ES3 conformance tests...',
+                                    'msvs_cygwin_shell': 0,
+                                    'inputs':
+                                    [
+                                        '<(gles_conformance_tests_generator_script)',
+                                        '<(gles3_conformance_tests_input_file)',
+                                    ],
+                                    'outputs':
+                                    [
+                                        '<(gles3_conformance_tests_generated_file)',
+                                    ],
+                                    'action':
+                                    [
+                                        'python',
+                                        '<(gles_conformance_tests_generator_script)',
+                                        '<(gles3_conformance_tests_input_file)',
+                                        '<(gles_conformance_tests_input_dir)',
+                                        '<(gles3_conformance_tests_generated_file)',
+                                    ],
+                                },
+                            ],
+                        },
+                    ],
+                }],
+            ],
+        }],
+    ],
+}
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/HowToMakeChanges.md b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/HowToMakeChanges.md
new file mode 100644
index 0000000..190a3e9
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/HowToMakeChanges.md
@@ -0,0 +1,22 @@
+Because the ```gpu_test_expectations``` directory is based on parts of Chromium's ```gpu/config```
+directory, we want to keep a patch of the changes added to make it compile with ANGLE. This
+will allow us to merge Chromium changes easily in our ```gpu_test_expectations```.
+
+In order to make a change to this directory, do the following:
+
+ * copy the directory somewhere like in ```gpu_test_expectations_reverted```
+ * in ```gpu_test_expectations_reverted``` run ```patch -p 1 -R < angle-mods.patch```
+ * do your changes in ```gpu_test_expectations```
+ * delete angle-mods.patch in both directories
+ * run ```diff -rupN gpu_test_expectations_reverted gpu_test_expectations > angle-mods.patch```
+ * copy ```angle-mods.patch``` in ```gpu_test_expectations```
+
+How to update from Chromium:
+
+ * ```git apply -R angle-mods.patch```, ```git add . -u```, ```git commit```
+ * Copy over Chromium files, ```git add . -u```, ```git commit```
+ * ```git revert HEAD~```
+ * ```rm angle-mods.patch```
+ * ```git diff HEAD~ (`)ls(`) > angle-mods.patch```,```git add angle-mods.patch```, ```git commit --amend```
+ * ```git rebase -i``` to squash the three patches into one.
+
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/angle-mods.patch b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/angle-mods.patch
new file mode 100644
index 0000000..f04df78
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/angle-mods.patch
@@ -0,0 +1,876 @@
+diff -u -rupN gpu_test_expectations_reverted/angle_config.h gpu_test_expectations/angle_config.h
+--- gpu_test_expectations_reverted/angle_config.h	1969-12-31 19:00:00.000000000 -0500
++++ gpu_test_expectations/angle_config.h	2016-08-24 13:18:58.877015665 -0400
+@@ -0,0 +1,66 @@
++//
++// Copyright 2015 The ANGLE Project Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++//
++// angle_config.h:
++//   Helpers for importing the gpu test expectations package from Chrome.
++//
++
++#ifndef GPU_TEST_EXPECTATIONS_ANGLE_CONFIG_H_
++#define GPU_TEST_EXPECTATIONS_ANGLE_CONFIG_H_
++
++#include <stdint.h>
++
++#include <iostream>
++
++#include "common/debug.h"
++#include "common/string_utils.h"
++
++#define DCHECK_EQ(A,B) ASSERT((A) == (B))
++#define DCHECK_NE(A,B) ASSERT((A) != (B))
++#define DCHECK(X) ASSERT(X)
++#define LOG(X) std::cerr
++
++#define GPU_EXPORT
++
++typedef int32_t int32;
++typedef uint32_t uint32;
++typedef int64_t int64;
++typedef uint64_t uint64;
++
++// Shim Chromium's base by importing functions in the base namespace.
++namespace base
++{
++    using angle::kWhitespaceASCII;
++    using angle::TRIM_WHITESPACE;
++    using angle::KEEP_WHITESPACE;
++    using angle::SPLIT_WANT_ALL;
++    using angle::SPLIT_WANT_NONEMPTY;
++    using angle::SplitString;
++    using angle::SplitStringAlongWhitespace;
++    using angle::HexStringToUInt;
++    using angle::ReadFileToString;
++
++    // StringPrintf is called differently in ANGLE but using cannot change
++    // the name of the imported function. Use a define to change the name.
++    using ::FormatString;
++    #define StringPrintf FormatString
++}
++
++// TODO(jmadill): other platforms
++// clang-format off
++#if defined(_WIN32) || defined(_WIN64)
++#    define OS_WIN
++#elif defined(ANDROID)
++#    define OS_ANDROID
++#elif defined(__linux__)
++#    define OS_LINUX
++#elif defined(__APPLE__)
++#    define OS_MACOSX
++#else
++#    error "Unsupported platform"
++#endif
++// clang-format on
++
++#endif
+diff -u -rupN gpu_test_expectations_reverted/gpu_info.cc gpu_test_expectations/gpu_info.cc
+--- gpu_test_expectations_reverted/gpu_info.cc	2017-02-13 11:15:30.922221193 -0500
++++ gpu_test_expectations/gpu_info.cc	2015-11-25 15:47:24.575592261 -0500
+@@ -2,7 +2,7 @@
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ 
+-#include "gpu/config/gpu_info.h"
++#include "gpu_info.h"
+ 
+ namespace {
+ 
+@@ -17,31 +17,6 @@ void EnumerateGPUDevice(const gpu::GPUIn
+   enumerator->EndGPUDevice();
+ }
+ 
+-void EnumerateVideoDecodeAcceleratorSupportedProfile(
+-    const gpu::VideoDecodeAcceleratorSupportedProfile& profile,
+-    gpu::GPUInfo::Enumerator* enumerator) {
+-  enumerator->BeginVideoDecodeAcceleratorSupportedProfile();
+-  enumerator->AddInt("profile", profile.profile);
+-  enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width());
+-  enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height());
+-  enumerator->AddInt("minResolutionWidth", profile.min_resolution.width());
+-  enumerator->AddInt("minResolutionHeight", profile.min_resolution.height());
+-  enumerator->EndVideoDecodeAcceleratorSupportedProfile();
+-}
+-
+-void EnumerateVideoEncodeAcceleratorSupportedProfile(
+-    const gpu::VideoEncodeAcceleratorSupportedProfile& profile,
+-    gpu::GPUInfo::Enumerator* enumerator) {
+-  enumerator->BeginVideoEncodeAcceleratorSupportedProfile();
+-  enumerator->AddInt("profile", profile.profile);
+-  enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width());
+-  enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height());
+-  enumerator->AddInt("maxFramerateNumerator", profile.max_framerate_numerator);
+-  enumerator->AddInt("maxFramerateDenominator",
+-                     profile.max_framerate_denominator);
+-  enumerator->EndVideoEncodeAcceleratorSupportedProfile();
+-}
+-
+ }  // namespace
+ 
+ namespace gpu {
+@@ -68,9 +43,6 @@ GPUInfo::GPUInfo()
+       in_process_gpu(true),
+       basic_info_state(kCollectInfoNone),
+       context_info_state(kCollectInfoNone),
+-#if defined(OS_WIN)
+-      dx_diagnostics_info_state(kCollectInfoNone),
+-#endif
+       jpeg_decode_accelerator_supported(false) {
+ }
+ 
+@@ -78,11 +50,9 @@ GPUInfo::~GPUInfo() { }
+ 
+ void GPUInfo::EnumerateFields(Enumerator* enumerator) const {
+   struct GPUInfoKnownFields {
+-    base::TimeDelta initialization_time;
+     bool optimus;
+     bool amd_switchable;
+     bool lenovo_dcute;
+-    Version display_link_version;
+     GPUDevice gpu;
+     std::vector<GPUDevice> secondary_gpus;
+     uint64 adapter_luid;
+@@ -110,14 +80,6 @@ void GPUInfo::EnumerateFields(Enumerator
+     bool in_process_gpu;
+     CollectInfoResult basic_info_state;
+     CollectInfoResult context_info_state;
+-#if defined(OS_WIN)
+-    CollectInfoResult dx_diagnostics_info_state;
+-    DxDiagNode dx_diagnostics;
+-#endif
+-    VideoDecodeAcceleratorSupportedProfiles
+-        video_decode_accelerator_supported_profiles;
+-    VideoEncodeAcceleratorSupportedProfiles
+-        video_encode_accelerator_supported_profiles;
+     bool jpeg_decode_accelerator_supported;
+   };
+ 
+@@ -136,15 +98,9 @@ void GPUInfo::EnumerateFields(Enumerator
+     EnumerateGPUDevice(secondary_gpu, enumerator);
+ 
+   enumerator->BeginAuxAttributes();
+-  enumerator->AddTimeDeltaInSecondsF("initializationTime",
+-                                     initialization_time);
+   enumerator->AddBool("optimus", optimus);
+   enumerator->AddBool("amdSwitchable", amd_switchable);
+   enumerator->AddBool("lenovoDcute", lenovo_dcute);
+-  if (display_link_version.IsValid()) {
+-    enumerator->AddString("displayLinkVersion",
+-                          display_link_version.GetString());
+-  }
+   enumerator->AddInt64("adapterLuid", adapter_luid);
+   enumerator->AddString("driverVendor", driver_vendor);
+   enumerator->AddString("driverVersion", driver_version);
+@@ -171,14 +127,7 @@ void GPUInfo::EnumerateFields(Enumerator
+   enumerator->AddBool("inProcessGpu", in_process_gpu);
+   enumerator->AddInt("basicInfoState", basic_info_state);
+   enumerator->AddInt("contextInfoState", context_info_state);
+-#if defined(OS_WIN)
+-  enumerator->AddInt("DxDiagnosticsInfoState", dx_diagnostics_info_state);
+-#endif
+   // TODO(kbr): add dx_diagnostics on Windows.
+-  for (const auto& profile : video_decode_accelerator_supported_profiles)
+-    EnumerateVideoDecodeAcceleratorSupportedProfile(profile, enumerator);
+-  for (const auto& profile : video_encode_accelerator_supported_profiles)
+-    EnumerateVideoEncodeAcceleratorSupportedProfile(profile, enumerator);
+   enumerator->AddBool("jpegDecodeAcceleratorSupported",
+       jpeg_decode_accelerator_supported);
+   enumerator->EndAuxAttributes();
+diff -u -rupN gpu_test_expectations_reverted/gpu_info.h gpu_test_expectations/gpu_info.h
+--- gpu_test_expectations_reverted/gpu_info.h	2017-02-13 11:15:30.922221193 -0500
++++ gpu_test_expectations/gpu_info.h	2015-11-25 15:47:24.575592261 -0500
+@@ -11,13 +11,7 @@
+ #include <string>
+ #include <vector>
+ 
+-#include "base/basictypes.h"
+-#include "base/time/time.h"
+-#include "base/version.h"
+-#include "build/build_config.h"
+-#include "gpu/config/dx_diag_node.h"
+-#include "gpu/gpu_export.h"
+-#include "ui/gfx/geometry/size.h"
++#include "angle_config.h"
+ 
+ namespace gpu {
+ 
+@@ -54,25 +48,6 @@ enum VideoCodecProfile {
+   VIDEO_CODEC_PROFILE_MAX = VP9PROFILE_ANY,
+ };
+ 
+-// Specification of a decoding profile supported by a hardware decoder.
+-struct GPU_EXPORT VideoDecodeAcceleratorSupportedProfile {
+-  VideoCodecProfile profile;
+-  gfx::Size max_resolution;
+-  gfx::Size min_resolution;
+-};
+-using VideoDecodeAcceleratorSupportedProfiles =
+-    std::vector<VideoDecodeAcceleratorSupportedProfile>;
+-
+-// Specification of an encoding profile supported by a hardware encoder.
+-struct GPU_EXPORT VideoEncodeAcceleratorSupportedProfile {
+-  VideoCodecProfile profile;
+-  gfx::Size max_resolution;
+-  uint32 max_framerate_numerator;
+-  uint32 max_framerate_denominator;
+-};
+-using VideoEncodeAcceleratorSupportedProfiles =
+-    std::vector<VideoEncodeAcceleratorSupportedProfile>;
+-
+ struct GPU_EXPORT GPUInfo {
+   struct GPU_EXPORT GPUDevice {
+     GPUDevice();
+@@ -104,10 +79,6 @@ struct GPU_EXPORT GPUInfo {
+     return !can_lose_context && !software_rendering;
+   }
+ 
+-  // The amount of time taken to get from the process starting to the message
+-  // loop being pumped.
+-  base::TimeDelta initialization_time;
+-
+   // Computer has NVIDIA Optimus
+   bool optimus;
+ 
+@@ -117,10 +88,6 @@ struct GPU_EXPORT GPUInfo {
+   // Lenovo dCute is installed. http://crbug.com/181665.
+   bool lenovo_dcute;
+ 
+-  // Version of DisplayLink driver installed. Zero if not installed.
+-  // http://crbug.com/177611.
+-  Version display_link_version;
+-
+   // Primary GPU, for exmaple, the discrete GPU in a dual GPU machine.
+   GPUDevice gpu;
+ 
+@@ -213,17 +180,7 @@ struct GPU_EXPORT GPUInfo {
+   // if the collection fails or not.
+   CollectInfoResult basic_info_state;
+   CollectInfoResult context_info_state;
+-#if defined(OS_WIN)
+-  CollectInfoResult dx_diagnostics_info_state;
+ 
+-  // The information returned by the DirectX Diagnostics Tool.
+-  DxDiagNode dx_diagnostics;
+-#endif
+-
+-  VideoDecodeAcceleratorSupportedProfiles
+-      video_decode_accelerator_supported_profiles;
+-  VideoEncodeAcceleratorSupportedProfiles
+-      video_encode_accelerator_supported_profiles;
+   bool jpeg_decode_accelerator_supported;
+ 
+   // Note: when adding new members, please remember to update EnumerateFields
+@@ -243,8 +200,6 @@ struct GPU_EXPORT GPUInfo {
+     virtual void AddInt(const char* name, int value) = 0;
+     virtual void AddString(const char* name, const std::string& value) = 0;
+     virtual void AddBool(const char* name, bool value) = 0;
+-    virtual void AddTimeDeltaInSecondsF(const char* name,
+-                                        const base::TimeDelta& value) = 0;
+ 
+     // Markers indicating that a GPUDevice is being described.
+     virtual void BeginGPUDevice() = 0;
+diff -u -rupN gpu_test_expectations_reverted/gpu_test_config.cc gpu_test_expectations/gpu_test_config.cc
+--- gpu_test_expectations_reverted/gpu_test_config.cc	2017-02-13 11:15:30.922221193 -0500
++++ gpu_test_expectations/gpu_test_config.cc	2016-09-14 14:55:40.134685526 -0400
+@@ -2,20 +2,205 @@
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ 
+-#include "gpu/config/gpu_test_config.h"
++#include "gpu_test_config.h"
+ 
+-#include "base/logging.h"
+-#include "base/sys_info.h"
+-#include "gpu/config/gpu_info.h"
+-#include "gpu/config/gpu_info_collector.h"
+-#include "gpu/config/gpu_test_expectations_parser.h"
++#include "gpu_info.h"
++#include "gpu_test_expectations_parser.h"
++
++#if defined(OS_LINUX)
++extern "C" {
++#   include <pci/pci.h>
++}
++#endif
+ 
+ #if defined(OS_MACOSX)
+-#include "base/mac/mac_util.h"
+-#elif defined(OS_WIN)
+-#include "base/win/windows_version.h"
++#include "gpu_test_config_mac.h"
++#endif
++
++using namespace gpu;
++
++#if defined(OS_WIN)
++
++namespace base {
++
++namespace {
++
++// Disable the deprecated function warning for GetVersionEx
++#pragma warning(disable: 4996)
++
++class SysInfo
++{
++  public:
++    static void OperatingSystemVersionNumbers(
++        int32 *major_version, int32 *minor_version, int32 *bugfix_version);
++};
++
++// static
++void SysInfo::OperatingSystemVersionNumbers(
++    int32 *major_version, int32 *minor_version, int32 *bugfix_version)
++{
++  OSVERSIONINFOEX version_info = { sizeof version_info };
++  ::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info));
++  *major_version = version_info.dwMajorVersion;
++  *minor_version = version_info.dwMinorVersion;
++  *bugfix_version = version_info.dwBuildNumber;
++}
++
++} // anonymous namespace
++
++} // namespace base
++
++void DeviceIDToVendorAndDevice(const std::string& id,
++                               uint32* vendor_id,
++                               uint32* device_id) {
++  *vendor_id = 0;
++  *device_id = 0;
++  if (id.length() < 21)
++    return;
++  std::string vendor_id_string = id.substr(8, 4);
++  std::string device_id_string = id.substr(17, 4);
++  base::HexStringToUInt(vendor_id_string, vendor_id);
++  base::HexStringToUInt(device_id_string, device_id);
++}
++
++CollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
++  DCHECK(vendor_id && device_id);
++  *vendor_id = 0;
++  *device_id = 0;
++
++  // Taken from http://developer.nvidia.com/object/device_ids.html
++  DISPLAY_DEVICEA dd;
++  dd.cb = sizeof(DISPLAY_DEVICEA);
++  std::string id;
++  for (int i = 0; EnumDisplayDevicesA(NULL, i, &dd, 0); ++i) {
++    if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
++      id = dd.DeviceID;
++      break;
++    }
++  }
++
++  if (id.length() > 20) {
++    DeviceIDToVendorAndDevice(id, vendor_id, device_id);
++    if (*vendor_id != 0 && *device_id != 0)
++      return kCollectInfoSuccess;
++  }
++  return kCollectInfoNonFatalFailure;
++}
++
++#endif // defined(OS_WIN)
++
++#if defined(OS_LINUX)
++
++const uint32 kVendorIDIntel = 0x8086;
++const uint32 kVendorIDNVidia = 0x10de;
++const uint32 kVendorIDAMD = 0x1002;
++
++CollectInfoResult CollectPCIVideoCardInfo(GPUInfo* gpu_info) {
++  DCHECK(gpu_info);
++
++  struct pci_access* access = pci_alloc();
++  DCHECK(access != NULL);
++  pci_init(access);
++  pci_scan_bus(access);
++
++  bool primary_gpu_identified = false;
++  for (pci_dev* device = access->devices;
++       device != NULL; device = device->next) {
++    pci_fill_info(device, 33);
++    bool is_gpu = false;
++    switch (device->device_class) {
++      case PCI_CLASS_DISPLAY_VGA:
++      case PCI_CLASS_DISPLAY_XGA:
++      case PCI_CLASS_DISPLAY_3D:
++        is_gpu = true;
++        break;
++      case PCI_CLASS_DISPLAY_OTHER:
++      default:
++        break;
++    }
++    if (!is_gpu)
++      continue;
++    if (device->vendor_id == 0 || device->device_id == 0)
++      continue;
++
++    GPUInfo::GPUDevice gpu;
++    gpu.vendor_id = device->vendor_id;
++    gpu.device_id = device->device_id;
++
++    if (!primary_gpu_identified) {
++      primary_gpu_identified = true;
++      gpu_info->gpu = gpu;
++    } else {
++      // TODO(zmo): if there are multiple GPUs, we assume the non Intel
++      // one is primary. Revisit this logic because we actually don't know
++      // which GPU we are using at this point.
++      if (gpu_info->gpu.vendor_id == kVendorIDIntel &&
++          gpu.vendor_id != kVendorIDIntel) {
++        gpu_info->secondary_gpus.push_back(gpu_info->gpu);
++        gpu_info->gpu = gpu;
++      } else {
++        gpu_info->secondary_gpus.push_back(gpu);
++      }
++    }
++  }
++
++  // Detect Optimus or AMD Switchable GPU.
++  if (gpu_info->secondary_gpus.size() == 1 &&
++      gpu_info->secondary_gpus[0].vendor_id == kVendorIDIntel) {
++    if (gpu_info->gpu.vendor_id == kVendorIDNVidia)
++      gpu_info->optimus = true;
++    if (gpu_info->gpu.vendor_id == kVendorIDAMD)
++      gpu_info->amd_switchable = true;
++  }
++
++  pci_cleanup(access);
++  if (!primary_gpu_identified)
++    return kCollectInfoNonFatalFailure;
++  return kCollectInfoSuccess;
++}
++
++CollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
++  DCHECK(vendor_id && device_id);
++  *vendor_id = 0;
++  *device_id = 0;
++
++  GPUInfo gpu_info;
++  CollectInfoResult result = CollectPCIVideoCardInfo(&gpu_info);
++  if (result == kCollectInfoSuccess) {
++    *vendor_id = gpu_info.gpu.vendor_id;
++    *device_id = gpu_info.gpu.device_id;
++  }
++  return result;
++}
++
++#endif // defined(OS_LINUX)
++
++#if defined(OS_MACOSX)
++
++CollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
++  DCHECK(vendor_id && device_id);
++
++  GPUInfo::GPUDevice gpu = GetActiveGPU();
++  *vendor_id = gpu.vendor_id;
++  *device_id = gpu.device_id;
++
++  if (*vendor_id != 0 && *device_id != 0)
++    return kCollectInfoSuccess;
++  return kCollectInfoNonFatalFailure;
++}
++
+ #endif
+ 
++#if defined(OS_ANDROID)
++CollectInfoResult CollectGpuID(uint32 *vendor_id, uint32 *device_id)
++{
++    DCHECK(vendor_id && device_id);
++    *vendor_id = 0;
++    *device_id = 0;
++    return kCollectInfoNonFatalFailure;
++}
++#endif  // defined(OS_ANDROID)
++
+ namespace gpu {
+ 
+ namespace {
+@@ -245,33 +430,41 @@ bool GPUTestBotConfig::Matches(const std
+   return Matches(config);
+ }
+ 
+-bool GPUTestBotConfig::LoadCurrentConfig(const GPUInfo* gpu_info) {
+-  bool rt;
+-  if (gpu_info == NULL) {
+-    GPUInfo my_gpu_info;
+-    CollectInfoResult result = CollectGpuID(
+-        &my_gpu_info.gpu.vendor_id, &my_gpu_info.gpu.device_id);
+-    if (result != kCollectInfoSuccess) {
+-      LOG(ERROR) << "Fail to identify GPU";
+-      DisableGPUInfoValidation();
+-      rt = true;
+-    } else {
+-      rt = SetGPUInfo(my_gpu_info);
++bool GPUTestBotConfig::LoadCurrentConfig(const GPUInfo *gpu_info)
++{
++    bool rt;
++    if (gpu_info == NULL)
++    {
++        GPUInfo my_gpu_info;
++        CollectInfoResult result =
++            CollectGpuID(&my_gpu_info.gpu.vendor_id, &my_gpu_info.gpu.device_id);
++        if (result != kCollectInfoSuccess)
++        {
++            LOG(ERROR) << "Fail to identify GPU\n";
++            DisableGPUInfoValidation();
++            rt = true;
++        }
++        else
++        {
++            rt = SetGPUInfo(my_gpu_info);
++        }
++    }
++    else
++    {
++        rt = SetGPUInfo(*gpu_info);
++    }
++    set_os(GetCurrentOS());
++    if (os() == kOsUnknown)
++    {
++        LOG(ERROR) << "Unknown OS\n";
++        rt = false;
+     }
+-  } else {
+-    rt = SetGPUInfo(*gpu_info);
+-  }
+-  set_os(GetCurrentOS());
+-  if (os() == kOsUnknown) {
+-    LOG(ERROR) << "Unknown OS";
+-    rt = false;
+-  }
+ #if defined(NDEBUG)
+-  set_build_type(kBuildTypeRelease);
++    set_build_type(kBuildTypeRelease);
+ #else
+-  set_build_type(kBuildTypeDebug);
++    set_build_type(kBuildTypeDebug);
+ #endif
+-  return rt;
++    return rt;
+ }
+ 
+ // static
+@@ -295,21 +488,5 @@ bool GPUTestBotConfig::CurrentConfigMatc
+   return false;
+ }
+ 
+-// static
+-bool GPUTestBotConfig::GpuBlacklistedOnBot() {
+-#if defined(OS_MACOSX)
+-  // Blacklist rule #81 disables all Gpu acceleration on Mac < 10.8 bots.
+-  if (CurrentConfigMatches("MAC VMWARE") && base::mac::IsOSLionOrEarlier()) {
+-    return true;
+-  }
+-#elif defined(OS_WIN)
+-  // Blacklist rule #79 disables all Gpu acceleration before Windows 7.
+-  if (base::win::GetVersion() <= base::win::VERSION_VISTA) {
+-    return true;
+-  }
+-#endif
+-  return false;
+-}
+-
+ }  // namespace gpu
+ 
+diff -u -rupN gpu_test_expectations_reverted/gpu_test_config.h gpu_test_expectations/gpu_test_config.h
+--- gpu_test_expectations_reverted/gpu_test_config.h	2017-02-13 11:15:30.922221193 -0500
++++ gpu_test_expectations/gpu_test_config.h	2015-11-25 15:47:24.575592261 -0500
+@@ -8,9 +8,7 @@
+ #include <string>
+ #include <vector>
+ 
+-#include "base/basictypes.h"
+-#include "base/compiler_specific.h"
+-#include "gpu/gpu_export.h"
++#include "angle_config.h"
+ 
+ namespace gpu {
+ 
+@@ -134,9 +132,6 @@ class GPU_EXPORT GPUTestBotConfig : publ
+   // Check if this bot's config matches |config_data| or any of the |configs|.
+   static bool CurrentConfigMatches(const std::string& config_data);
+   static bool CurrentConfigMatches(const std::vector<std::string>& configs);
+-
+-  // Check if the bot has blacklisted all GPU features.
+-  static bool GpuBlacklistedOnBot();
+ };
+ 
+ }  // namespace gpu
+diff -u -rupN gpu_test_expectations_reverted/gpu_test_config_mac.h gpu_test_expectations/gpu_test_config_mac.h
+--- gpu_test_expectations_reverted/gpu_test_config_mac.h	1969-12-31 19:00:00.000000000 -0500
++++ gpu_test_expectations/gpu_test_config_mac.h	2015-09-16 16:05:45.788950024 -0400
+@@ -0,0 +1,28 @@
++//
++// Copyright 2015 The ANGLE Project Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++//
++// gpu_test_config_mac.h:
++//   Helper functions for gpu_test_config that have to be compiled in ObjectiveC++
++//
++
++#ifndef GPU_TEST_EXPECTATIONS_GPU_TEST_CONFIG_MAC_H_
++#define GPU_TEST_EXPECTATIONS_GPU_TEST_CONFIG_MAC_H_
++
++#include "gpu_info.h"
++
++namespace base {
++
++class SysInfo
++{
++  public:
++    static void OperatingSystemVersionNumbers(
++        int32 *major_version, int32 *minor_version, int32 *bugfix_version);
++};
++
++} // namespace base
++
++gpu::GPUInfo::GPUDevice GetActiveGPU();
++
++#endif // GPU_TEST_EXPECTATIONS_GPU_TEST_CONFIG_MAC_H_
+diff -u -rupN gpu_test_expectations_reverted/gpu_test_config_mac.mm gpu_test_expectations/gpu_test_config_mac.mm
+--- gpu_test_expectations_reverted/gpu_test_config_mac.mm	1969-12-31 19:00:00.000000000 -0500
++++ gpu_test_expectations/gpu_test_config_mac.mm	2017-02-13 11:20:54.656424702 -0500
+@@ -0,0 +1,75 @@
++// Copyright (c) 2012 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++// gpu_test_config_mac.mm:
++//   Helper functions for gpu_test_config that have to be compiled in ObjectiveC++
++
++#include "gpu_test_config_mac.h"
++
++#import <Cocoa/Cocoa.h>
++
++namespace base {
++
++// OSX 10.8 deprecates Gestalt but doesn't make the operatingSystemVersion property part of the
++// public interface of NSProcessInfo until 10.10. Add a forward declaration.
++#if !defined(MAC_OS_X_VERSION_10_10) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10
++@interface NSProcessInfo (YosemiteSDK)
++@property(readonly) NSOperatingSystemVersion operatingSystemVersion;
++@end
++#endif
++
++void SysInfo::OperatingSystemVersionNumbers(
++    int32 *major_version, int32 *minor_version, int32 *bugfix_version)
++{
++#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
++  Gestalt(gestaltSystemVersionMajor, reinterpret_cast<SInt32*>(major_version));
++  Gestalt(gestaltSystemVersionMinor, reinterpret_cast<SInt32*>(minor_version));
++  Gestalt(gestaltSystemVersionBugFix, reinterpret_cast<SInt32*>(bugfix_version));
++#else
++  NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
++  *major_version = version.majorVersion;
++  *minor_version = version.minorVersion;
++  *bugfix_version = version.patchVersion;
++#endif
++}
++
++} // namespace base
++
++UInt32 GetEntryProperty(io_registry_entry_t entry, CFStringRef property_name) {
++  CFTypeRef type = IORegistryEntrySearchCFProperty(entry,
++                                                   kIOServicePlane,
++                                                   property_name,
++                                                   kCFAllocatorDefault,
++                                                   kIORegistryIterateRecursively | kIORegistryIterateParents);
++  CFDataRef data = reinterpret_cast<CFDataRef>(type);
++  if (!data) {
++    CFRelease(data);
++    return 0;
++  }
++
++  UInt32 value = 0;
++  const uint32_t* valuePointer = reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(data));
++  if (valuePointer != NULL) {
++    value = *valuePointer;
++  }
++  CFRelease(data);
++  return value;
++}
++
++gpu::GPUInfo::GPUDevice GetActiveGPU() {
++  gpu::GPUInfo::GPUDevice gpu;
++
++  // Ignore the fact that CGDisplayIOServicePort is deprecated as Apple
++  // did not provide a good replacement for it as of 10.10.
++  // TODO(cwallez) revisit with later systems
++  #pragma clang diagnostic push
++  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
++    io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
++  #pragma clang diagnostic pop
++
++  gpu.vendor_id = GetEntryProperty(dsp_port, CFSTR("vendor-id"));
++  gpu.device_id = GetEntryProperty(dsp_port, CFSTR("device-id"));
++  return gpu;
++}
++
+diff -u -rupN gpu_test_expectations_reverted/gpu_test_expectations_parser.cc gpu_test_expectations/gpu_test_expectations_parser.cc
+--- gpu_test_expectations_reverted/gpu_test_expectations_parser.cc	2017-02-13 11:15:30.922221193 -0500
++++ gpu_test_expectations/gpu_test_expectations_parser.cc	2015-11-25 15:47:24.575592261 -0500
+@@ -2,14 +2,43 @@
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ 
+-#include "gpu/config/gpu_test_expectations_parser.h"
++#include "gpu_test_expectations_parser.h"
+ 
+-#include "base/files/file_util.h"
+-#include "base/logging.h"
+-#include "base/strings/string_number_conversions.h"
+-#include "base/strings/string_split.h"
+-#include "base/strings/string_util.h"
+-#include "base/strings/stringprintf.h"
++#include "common/angleutils.h"
++
++namespace base {
++
++namespace {
++
++bool StartsWithASCII(const std::string& str,
++                     const std::string& search,
++                     bool case_sensitive) {
++  ASSERT(!case_sensitive);
++  return str.compare(0, search.length(), search) == 0;
++}
++
++template <class Char> inline Char ToLowerASCII(Char c) {
++  return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
++}
++
++template<typename Iter>
++static inline bool DoLowerCaseEqualsASCII(Iter a_begin,
++                                          Iter a_end,
++                                          const char* b) {
++  for (Iter it = a_begin; it != a_end; ++it, ++b) {
++    if (!*b || base::ToLowerASCII(*it) != *b)
++      return false;
++  }
++  return *b == 0;
++}
++
++bool LowerCaseEqualsASCII(const std::string& a, const char* b) {
++  return DoLowerCaseEqualsASCII(a.begin(), a.end(), b);
++}
++
++} // anonymous namespace
++
++} // namespace base
+ 
+ namespace gpu {
+ 
+@@ -146,9 +175,9 @@ const char* kErrorMessage[] = {
+ };
+ 
+ Token ParseToken(const std::string& word) {
+-  if (base::StartsWith(word, "//", base::CompareCase::INSENSITIVE_ASCII))
++  if (base::StartsWithASCII(word, "//", false))
+     return kTokenComment;
+-  if (base::StartsWith(word, "0x", base::CompareCase::INSENSITIVE_ASCII))
++  if (base::StartsWithASCII(word, "0x", false))
+     return kConfigGPUDeviceID;
+ 
+   for (int32 i = 0; i < kNumberOfExactMatchTokens; ++i) {
+@@ -176,10 +205,10 @@ bool NamesMatching(const std::string& re
+ 
+ GPUTestExpectationsParser::GPUTestExpectationsParser() {
+   // Some sanity check.
+-  DCHECK_EQ(static_cast<unsigned int>(kNumberOfExactMatchTokens),
+-            sizeof(kTokenData) / sizeof(kTokenData[0]));
+-  DCHECK_EQ(static_cast<unsigned int>(kNumberOfErrors),
+-            sizeof(kErrorMessage) / sizeof(kErrorMessage[0]));
++  static_assert(static_cast<unsigned int>(kNumberOfExactMatchTokens) ==
++                sizeof(kTokenData) / sizeof(kTokenData[0]), "sanity check");
++  static_assert(static_cast<unsigned int>(kNumberOfErrors) ==
++                sizeof(kErrorMessage) / sizeof(kErrorMessage[0]), "sanity check");
+ }
+ 
+ GPUTestExpectationsParser::~GPUTestExpectationsParser() {
+@@ -204,8 +233,8 @@ bool GPUTestExpectationsParser::LoadTest
+   return rt;
+ }
+ 
+-bool GPUTestExpectationsParser::LoadTestExpectations(
+-    const base::FilePath& path) {
++bool GPUTestExpectationsParser::LoadTestExpectationsFromFile(
++    const std::string& path) {
+   entries_.clear();
+   error_messages_.clear();
+ 
+@@ -399,7 +428,7 @@ bool GPUTestExpectationsParser::ParseLin
+           stage++;
+         break;
+       default:
+-        DCHECK(false);
++        UNREACHABLE();
+         break;
+     }
+   }
+@@ -488,7 +517,7 @@ bool GPUTestExpectationsParser::UpdateTe
+       config->set_api(config->api() | kTokenData[token].flag);
+       break;
+     default:
+-      DCHECK(false);
++      UNREACHABLE();
+       break;
+   }
+   return true;
+diff -u -rupN gpu_test_expectations_reverted/gpu_test_expectations_parser.h gpu_test_expectations/gpu_test_expectations_parser.h
+--- gpu_test_expectations_reverted/gpu_test_expectations_parser.h	2017-02-13 11:15:30.922221193 -0500
++++ gpu_test_expectations/gpu_test_expectations_parser.h	2015-06-30 09:40:06.654788989 -0400
+@@ -8,10 +8,8 @@
+ #include <string>
+ #include <vector>
+ 
+-#include "base/basictypes.h"
+-#include "base/files/file_path.h"
+-#include "gpu/config/gpu_test_config.h"
+-#include "gpu/gpu_export.h"
++#include "angle_config.h"
++#include "gpu_test_config.h"
+ 
+ namespace gpu {
+ 
+@@ -32,7 +30,7 @@ class GPU_EXPORT GPUTestExpectationsPars
+   // save all the entries. Otherwise, generate error messages.
+   // Return true if parsing succeeds.
+   bool LoadTestExpectations(const std::string& data);
+-  bool LoadTestExpectations(const base::FilePath& path);
++  bool LoadTestExpectationsFromFile(const std::string& path);
+ 
+   // Query error messages from the last LoadTestExpectations() call.
+   const std::vector<std::string>& GetErrorMessages() const;
+diff -u -rupN gpu_test_expectations_reverted/HowToMakeChanges.md gpu_test_expectations/HowToMakeChanges.md
+--- gpu_test_expectations_reverted/HowToMakeChanges.md	1969-12-31 19:00:00.000000000 -0500
++++ gpu_test_expectations/HowToMakeChanges.md	2016-09-14 14:55:40.134685526 -0400
+@@ -0,0 +1,22 @@
++Because the ```gpu_test_expectations``` directory is based on parts of Chromium's ```gpu/config```
++directory, we want to keep a patch of the changes added to make it compile with ANGLE. This
++will allow us to merge Chromium changes easily in our ```gpu_test_expectations```.
++
++In order to make a change to this directory, do the following:
++
++ * copy the directory somewhere like in ```gpu_test_expectations_reverted```
++ * in ```gpu_test_expectations_reverted``` run ```patch -p 1 -R < angle-mods.patch```
++ * do your changes in ```gpu_test_expectations```
++ * delete angle-mods.patch in both directories
++ * run ```diff -rupN gpu_test_expectations_reverted gpu_test_expectations > angle-mods.patch```
++ * copy ```angle-mods.patch``` in ```gpu_test_expectations```
++
++How to update from Chromium:
++
++ * ```git apply -R angle-mods.patch```, ```git add . -u```, ```git commit```
++ * Copy over Chromium files, ```git add . -u```, ```git commit```
++ * ```git revert HEAD~```
++ * ```rm angle-mods.patch```
++ * ```git diff HEAD~ (`)ls(`) > angle-mods.patch```,```git add angle-mods.patch```, ```git commit --amend```
++ * ```git rebase -i``` to squash the three patches into one.
++
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/angle_config.h b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/angle_config.h
new file mode 100644
index 0000000..4e46f98
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/angle_config.h
@@ -0,0 +1,66 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_config.h:
+//   Helpers for importing the gpu test expectations package from Chrome.
+//
+
+#ifndef GPU_TEST_EXPECTATIONS_ANGLE_CONFIG_H_
+#define GPU_TEST_EXPECTATIONS_ANGLE_CONFIG_H_
+
+#include <stdint.h>
+
+#include <iostream>
+
+#include "common/debug.h"
+#include "common/string_utils.h"
+
+#define DCHECK_EQ(A,B) ASSERT((A) == (B))
+#define DCHECK_NE(A,B) ASSERT((A) != (B))
+#define DCHECK(X) ASSERT(X)
+#define LOG(X) std::cerr
+
+#define GPU_EXPORT
+
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+
+// Shim Chromium's base by importing functions in the base namespace.
+namespace base
+{
+    using angle::kWhitespaceASCII;
+    using angle::TRIM_WHITESPACE;
+    using angle::KEEP_WHITESPACE;
+    using angle::SPLIT_WANT_ALL;
+    using angle::SPLIT_WANT_NONEMPTY;
+    using angle::SplitString;
+    using angle::SplitStringAlongWhitespace;
+    using angle::HexStringToUInt;
+    using angle::ReadFileToString;
+
+    // StringPrintf is called differently in ANGLE but using cannot change
+    // the name of the imported function. Use a define to change the name.
+    using ::FormatString;
+    #define StringPrintf FormatString
+}
+
+// TODO(jmadill): other platforms
+// clang-format off
+#if defined(_WIN32) || defined(_WIN64)
+#    define OS_WIN
+#elif defined(ANDROID)
+#    define OS_ANDROID
+#elif defined(__linux__)
+#    define OS_LINUX
+#elif defined(__APPLE__)
+#    define OS_MACOSX
+#else
+#    error "Unsupported platform"
+#endif
+// clang-format on
+
+#endif
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_info.cc b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_info.cc
new file mode 100644
index 0000000..4f279a4
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_info.cc
@@ -0,0 +1,136 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu_info.h"
+
+namespace {
+
+void EnumerateGPUDevice(const gpu::GPUInfo::GPUDevice& device,
+                        gpu::GPUInfo::Enumerator* enumerator) {
+  enumerator->BeginGPUDevice();
+  enumerator->AddInt("vendorId", device.vendor_id);
+  enumerator->AddInt("deviceId", device.device_id);
+  enumerator->AddBool("active", device.active);
+  enumerator->AddString("vendorString", device.vendor_string);
+  enumerator->AddString("deviceString", device.device_string);
+  enumerator->EndGPUDevice();
+}
+
+}  // namespace
+
+namespace gpu {
+
+GPUInfo::GPUDevice::GPUDevice()
+    : vendor_id(0),
+      device_id(0),
+      active(false) {
+}
+
+GPUInfo::GPUDevice::~GPUDevice() { }
+
+GPUInfo::GPUInfo()
+    : optimus(false),
+      amd_switchable(false),
+      lenovo_dcute(false),
+      adapter_luid(0),
+      gl_reset_notification_strategy(0),
+      can_lose_context(false),
+      software_rendering(false),
+      direct_rendering(true),
+      sandboxed(false),
+      process_crash_count(0),
+      in_process_gpu(true),
+      basic_info_state(kCollectInfoNone),
+      context_info_state(kCollectInfoNone),
+      jpeg_decode_accelerator_supported(false) {
+}
+
+GPUInfo::~GPUInfo() { }
+
+void GPUInfo::EnumerateFields(Enumerator* enumerator) const {
+  struct GPUInfoKnownFields {
+    bool optimus;
+    bool amd_switchable;
+    bool lenovo_dcute;
+    GPUDevice gpu;
+    std::vector<GPUDevice> secondary_gpus;
+    uint64 adapter_luid;
+    std::string driver_vendor;
+    std::string driver_version;
+    std::string driver_date;
+    std::string pixel_shader_version;
+    std::string vertex_shader_version;
+    std::string max_msaa_samples;
+    std::string machine_model_name;
+    std::string machine_model_version;
+    std::string gl_version_string;
+    std::string gl_vendor;
+    std::string gl_renderer;
+    std::string gl_extensions;
+    std::string gl_ws_vendor;
+    std::string gl_ws_version;
+    std::string gl_ws_extensions;
+    uint32 gl_reset_notification_strategy;
+    bool can_lose_context;
+    bool software_rendering;
+    bool direct_rendering;
+    bool sandboxed;
+    int process_crash_count;
+    bool in_process_gpu;
+    CollectInfoResult basic_info_state;
+    CollectInfoResult context_info_state;
+    bool jpeg_decode_accelerator_supported;
+  };
+
+  // If this assert fails then most likely something below needs to be updated.
+  // Note that this assert is only approximate. If a new field is added to
+  // GPUInfo which fits within the current padding then it will not be caught.
+  static_assert(
+      sizeof(GPUInfo) == sizeof(GPUInfoKnownFields),
+      "fields have changed in GPUInfo, GPUInfoKnownFields must be updated");
+
+  // Required fields (according to DevTools protocol) first.
+  enumerator->AddString("machineModelName", machine_model_name);
+  enumerator->AddString("machineModelVersion", machine_model_version);
+  EnumerateGPUDevice(gpu, enumerator);
+  for (const auto& secondary_gpu: secondary_gpus)
+    EnumerateGPUDevice(secondary_gpu, enumerator);
+
+  enumerator->BeginAuxAttributes();
+  enumerator->AddBool("optimus", optimus);
+  enumerator->AddBool("amdSwitchable", amd_switchable);
+  enumerator->AddBool("lenovoDcute", lenovo_dcute);
+  enumerator->AddInt64("adapterLuid", adapter_luid);
+  enumerator->AddString("driverVendor", driver_vendor);
+  enumerator->AddString("driverVersion", driver_version);
+  enumerator->AddString("driverDate", driver_date);
+  enumerator->AddString("pixelShaderVersion", pixel_shader_version);
+  enumerator->AddString("vertexShaderVersion", vertex_shader_version);
+  enumerator->AddString("maxMsaaSamples", max_msaa_samples);
+  enumerator->AddString("glVersion", gl_version);
+  enumerator->AddString("glVendor", gl_vendor);
+  enumerator->AddString("glRenderer", gl_renderer);
+  enumerator->AddString("glExtensions", gl_extensions);
+  enumerator->AddString("glWsVendor", gl_ws_vendor);
+  enumerator->AddString("glWsVersion", gl_ws_version);
+  enumerator->AddString("glWsExtensions", gl_ws_extensions);
+  enumerator->AddInt(
+      "glResetNotificationStrategy",
+      static_cast<int>(gl_reset_notification_strategy));
+  enumerator->AddBool("can_lose_context", can_lose_context);
+  // TODO(kbr): add performance_stats.
+  enumerator->AddBool("softwareRendering", software_rendering);
+  enumerator->AddBool("directRendering", direct_rendering);
+  enumerator->AddBool("sandboxed", sandboxed);
+  enumerator->AddInt("processCrashCount", process_crash_count);
+  enumerator->AddBool("inProcessGpu", in_process_gpu);
+  enumerator->AddInt("basicInfoState", basic_info_state);
+  enumerator->AddInt("contextInfoState", context_info_state);
+  // TODO(kbr): add dx_diagnostics on Windows.
+  enumerator->AddBool("jpegDecodeAcceleratorSupported",
+      jpeg_decode_accelerator_supported);
+  enumerator->EndAuxAttributes();
+}
+
+}  // namespace gpu
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_info.h b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_info.h
new file mode 100644
index 0000000..0a7f9aa
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_info.h
@@ -0,0 +1,233 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_INFO_H_
+#define GPU_CONFIG_GPU_INFO_H_
+
+// Provides access to the GPU information for the system
+// on which chrome is currently running.
+
+#include <string>
+#include <vector>
+
+#include "angle_config.h"
+
+namespace gpu {
+
+// Result for the various Collect*Info* functions below.
+// Fatal failures are for cases where we can't create a context at all or
+// something, making the use of the GPU impossible.
+// Non-fatal failures are for cases where we could gather most info, but maybe
+// some is missing (e.g. unable to parse a version string or to detect the exact
+// model).
+enum CollectInfoResult {
+  kCollectInfoNone = 0,
+  kCollectInfoSuccess = 1,
+  kCollectInfoNonFatalFailure = 2,
+  kCollectInfoFatalFailure = 3
+};
+
+// Video profile.  This *must* match media::VideoCodecProfile.
+enum VideoCodecProfile {
+  VIDEO_CODEC_PROFILE_UNKNOWN = -1,
+  VIDEO_CODEC_PROFILE_MIN = VIDEO_CODEC_PROFILE_UNKNOWN,
+  H264PROFILE_BASELINE = 0,
+  H264PROFILE_MAIN = 1,
+  H264PROFILE_EXTENDED = 2,
+  H264PROFILE_HIGH = 3,
+  H264PROFILE_HIGH10PROFILE = 4,
+  H264PROFILE_HIGH422PROFILE = 5,
+  H264PROFILE_HIGH444PREDICTIVEPROFILE = 6,
+  H264PROFILE_SCALABLEBASELINE = 7,
+  H264PROFILE_SCALABLEHIGH = 8,
+  H264PROFILE_STEREOHIGH = 9,
+  H264PROFILE_MULTIVIEWHIGH = 10,
+  VP8PROFILE_ANY = 11,
+  VP9PROFILE_ANY = 12,
+  VIDEO_CODEC_PROFILE_MAX = VP9PROFILE_ANY,
+};
+
+struct GPU_EXPORT GPUInfo {
+  struct GPU_EXPORT GPUDevice {
+    GPUDevice();
+    ~GPUDevice();
+
+    // The DWORD (uint32) representing the graphics card vendor id.
+    uint32 vendor_id;
+
+    // The DWORD (uint32) representing the graphics card device id.
+    // Device ids are unique to vendor, not to one another.
+    uint32 device_id;
+
+    // Whether this GPU is the currently used one.
+    // Currently this field is only supported and meaningful on OS X.
+    bool active;
+
+    // The strings that describe the GPU.
+    // In Linux these strings are obtained through libpci.
+    // In Win/MacOSX, these two strings are not filled at the moment.
+    // In Android, these are respectively GL_VENDOR and GL_RENDERER.
+    std::string vendor_string;
+    std::string device_string;
+  };
+
+  GPUInfo();
+  ~GPUInfo();
+
+  bool SupportsAccelerated2dCanvas() const {
+    return !can_lose_context && !software_rendering;
+  }
+
+  // Computer has NVIDIA Optimus
+  bool optimus;
+
+  // Computer has AMD Dynamic Switchable Graphics
+  bool amd_switchable;
+
+  // Lenovo dCute is installed. http://crbug.com/181665.
+  bool lenovo_dcute;
+
+  // Primary GPU, for exmaple, the discrete GPU in a dual GPU machine.
+  GPUDevice gpu;
+
+  // Secondary GPUs, for example, the integrated GPU in a dual GPU machine.
+  std::vector<GPUDevice> secondary_gpus;
+
+  // On Windows, the unique identifier of the adapter the GPU process uses.
+  // The default is zero, which makes the browser process create its D3D device
+  // on the primary adapter. Note that the primary adapter can change at any
+  // time so it is better to specify a particular LUID. Note that valid LUIDs
+  // are always non-zero.
+  uint64 adapter_luid;
+
+  // The vendor of the graphics driver currently installed.
+  std::string driver_vendor;
+
+  // The version of the graphics driver currently installed.
+  std::string driver_version;
+
+  // The date of the graphics driver currently installed.
+  std::string driver_date;
+
+  // The version of the pixel/fragment shader used by the gpu.
+  std::string pixel_shader_version;
+
+  // The version of the vertex shader used by the gpu.
+  std::string vertex_shader_version;
+
+  // The maximum multisapling sample count, either through ES3 or
+  // EXT_multisampled_render_to_texture MSAA.
+  std::string max_msaa_samples;
+
+  // The machine model identifier. They can contain any character, including
+  // whitespaces.  Currently it is supported on MacOSX and Android.
+  // Android examples: "Naxus 5", "XT1032".
+  // On MacOSX, the version is stripped out of the model identifier, for
+  // example, the original identifier is "MacBookPro7,2", and we put
+  // "MacBookPro" as machine_model_name, and "7.2" as machine_model_version.
+  std::string machine_model_name;
+
+  // The version of the machine model. Currently it is supported on MacOSX.
+  // See machine_model_name's comment.
+  std::string machine_model_version;
+
+  // The GL_VERSION string.
+  std::string gl_version;
+
+  // The GL_VENDOR string.
+  std::string gl_vendor;
+
+  // The GL_RENDERER string.
+  std::string gl_renderer;
+
+  // The GL_EXTENSIONS string.
+  std::string gl_extensions;
+
+  // GL window system binding vendor.  "" if not available.
+  std::string gl_ws_vendor;
+
+  // GL window system binding version.  "" if not available.
+  std::string gl_ws_version;
+
+  // GL window system binding extensions.  "" if not available.
+  std::string gl_ws_extensions;
+
+  // GL reset notification strategy as defined by GL_ARB_robustness. 0 if GPU
+  // reset detection or notification not available.
+  uint32 gl_reset_notification_strategy;
+
+  // The device semantics, i.e. whether the Vista and Windows 7 specific
+  // semantics are available.
+  bool can_lose_context;
+
+  bool software_rendering;
+
+  // Whether the driver uses direct rendering. True on most platforms, false on
+  // X11 when using remote X.
+  bool direct_rendering;
+
+  // Whether the gpu process is running in a sandbox.
+  bool sandboxed;
+
+  // Number of GPU process crashes recorded.
+  int process_crash_count;
+
+  // True if the GPU is running in the browser process instead of its own.
+  bool in_process_gpu;
+
+  // The state of whether the basic/context/DxDiagnostics info is collected and
+  // if the collection fails or not.
+  CollectInfoResult basic_info_state;
+  CollectInfoResult context_info_state;
+
+  bool jpeg_decode_accelerator_supported;
+
+  // Note: when adding new members, please remember to update EnumerateFields
+  // in gpu_info.cc.
+
+  // In conjunction with EnumerateFields, this allows the embedder to
+  // enumerate the values in this structure without having to embed
+  // references to its specific member variables. This simplifies the
+  // addition of new fields to this type.
+  class Enumerator {
+   public:
+    // The following methods apply to the "current" object. Initially this
+    // is the root object, but calls to BeginGPUDevice/EndGPUDevice and
+    // BeginAuxAttributes/EndAuxAttributes change the object to which these
+    // calls should apply.
+    virtual void AddInt64(const char* name, int64 value) = 0;
+    virtual void AddInt(const char* name, int value) = 0;
+    virtual void AddString(const char* name, const std::string& value) = 0;
+    virtual void AddBool(const char* name, bool value) = 0;
+
+    // Markers indicating that a GPUDevice is being described.
+    virtual void BeginGPUDevice() = 0;
+    virtual void EndGPUDevice() = 0;
+
+    // Markers indicating that a VideoDecodeAcceleratorSupportedProfile is
+    // being described.
+    virtual void BeginVideoDecodeAcceleratorSupportedProfile() = 0;
+    virtual void EndVideoDecodeAcceleratorSupportedProfile() = 0;
+
+    // Markers indicating that a VideoEncodeAcceleratorSupportedProfile is
+    // being described.
+    virtual void BeginVideoEncodeAcceleratorSupportedProfile() = 0;
+    virtual void EndVideoEncodeAcceleratorSupportedProfile() = 0;
+
+    // Markers indicating that "auxiliary" attributes of the GPUInfo
+    // (according to the DevTools protocol) are being described.
+    virtual void BeginAuxAttributes() = 0;
+    virtual void EndAuxAttributes() = 0;
+
+   protected:
+    virtual ~Enumerator() {}
+  };
+
+  // Outputs the fields in this structure to the provided enumerator.
+  void EnumerateFields(Enumerator* enumerator) const;
+};
+
+}  // namespace gpu
+
+#endif  // GPU_CONFIG_GPU_INFO_H_
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config.cc b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config.cc
new file mode 100644
index 0000000..f0bf6f0
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config.cc
@@ -0,0 +1,492 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu_test_config.h"
+
+#include "gpu_info.h"
+#include "gpu_test_expectations_parser.h"
+
+#if defined(OS_LINUX)
+extern "C" {
+#   include <pci/pci.h>
+}
+#endif
+
+#if defined(OS_MACOSX)
+#include "gpu_test_config_mac.h"
+#endif
+
+using namespace gpu;
+
+#if defined(OS_WIN)
+
+namespace base {
+
+namespace {
+
+// Disable the deprecated function warning for GetVersionEx
+#pragma warning(disable: 4996)
+
+class SysInfo
+{
+  public:
+    static void OperatingSystemVersionNumbers(
+        int32 *major_version, int32 *minor_version, int32 *bugfix_version);
+};
+
+// static
+void SysInfo::OperatingSystemVersionNumbers(
+    int32 *major_version, int32 *minor_version, int32 *bugfix_version)
+{
+  OSVERSIONINFOEX version_info = { sizeof version_info };
+  ::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info));
+  *major_version = version_info.dwMajorVersion;
+  *minor_version = version_info.dwMinorVersion;
+  *bugfix_version = version_info.dwBuildNumber;
+}
+
+} // anonymous namespace
+
+} // namespace base
+
+void DeviceIDToVendorAndDevice(const std::string& id,
+                               uint32* vendor_id,
+                               uint32* device_id) {
+  *vendor_id = 0;
+  *device_id = 0;
+  if (id.length() < 21)
+    return;
+  std::string vendor_id_string = id.substr(8, 4);
+  std::string device_id_string = id.substr(17, 4);
+  base::HexStringToUInt(vendor_id_string, vendor_id);
+  base::HexStringToUInt(device_id_string, device_id);
+}
+
+CollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
+  DCHECK(vendor_id && device_id);
+  *vendor_id = 0;
+  *device_id = 0;
+
+  // Taken from http://developer.nvidia.com/object/device_ids.html
+  DISPLAY_DEVICEA dd;
+  dd.cb = sizeof(DISPLAY_DEVICEA);
+  std::string id;
+  for (int i = 0; EnumDisplayDevicesA(NULL, i, &dd, 0); ++i) {
+    if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
+      id = dd.DeviceID;
+      break;
+    }
+  }
+
+  if (id.length() > 20) {
+    DeviceIDToVendorAndDevice(id, vendor_id, device_id);
+    if (*vendor_id != 0 && *device_id != 0)
+      return kCollectInfoSuccess;
+  }
+  return kCollectInfoNonFatalFailure;
+}
+
+#endif // defined(OS_WIN)
+
+#if defined(OS_LINUX)
+
+const uint32 kVendorIDIntel = 0x8086;
+const uint32 kVendorIDNVidia = 0x10de;
+const uint32 kVendorIDAMD = 0x1002;
+
+CollectInfoResult CollectPCIVideoCardInfo(GPUInfo* gpu_info) {
+  DCHECK(gpu_info);
+
+  struct pci_access* access = pci_alloc();
+  DCHECK(access != NULL);
+  pci_init(access);
+  pci_scan_bus(access);
+
+  bool primary_gpu_identified = false;
+  for (pci_dev* device = access->devices;
+       device != NULL; device = device->next) {
+    pci_fill_info(device, 33);
+    bool is_gpu = false;
+    switch (device->device_class) {
+      case PCI_CLASS_DISPLAY_VGA:
+      case PCI_CLASS_DISPLAY_XGA:
+      case PCI_CLASS_DISPLAY_3D:
+        is_gpu = true;
+        break;
+      case PCI_CLASS_DISPLAY_OTHER:
+      default:
+        break;
+    }
+    if (!is_gpu)
+      continue;
+    if (device->vendor_id == 0 || device->device_id == 0)
+      continue;
+
+    GPUInfo::GPUDevice gpu;
+    gpu.vendor_id = device->vendor_id;
+    gpu.device_id = device->device_id;
+
+    if (!primary_gpu_identified) {
+      primary_gpu_identified = true;
+      gpu_info->gpu = gpu;
+    } else {
+      // TODO(zmo): if there are multiple GPUs, we assume the non Intel
+      // one is primary. Revisit this logic because we actually don't know
+      // which GPU we are using at this point.
+      if (gpu_info->gpu.vendor_id == kVendorIDIntel &&
+          gpu.vendor_id != kVendorIDIntel) {
+        gpu_info->secondary_gpus.push_back(gpu_info->gpu);
+        gpu_info->gpu = gpu;
+      } else {
+        gpu_info->secondary_gpus.push_back(gpu);
+      }
+    }
+  }
+
+  // Detect Optimus or AMD Switchable GPU.
+  if (gpu_info->secondary_gpus.size() == 1 &&
+      gpu_info->secondary_gpus[0].vendor_id == kVendorIDIntel) {
+    if (gpu_info->gpu.vendor_id == kVendorIDNVidia)
+      gpu_info->optimus = true;
+    if (gpu_info->gpu.vendor_id == kVendorIDAMD)
+      gpu_info->amd_switchable = true;
+  }
+
+  pci_cleanup(access);
+  if (!primary_gpu_identified)
+    return kCollectInfoNonFatalFailure;
+  return kCollectInfoSuccess;
+}
+
+CollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
+  DCHECK(vendor_id && device_id);
+  *vendor_id = 0;
+  *device_id = 0;
+
+  GPUInfo gpu_info;
+  CollectInfoResult result = CollectPCIVideoCardInfo(&gpu_info);
+  if (result == kCollectInfoSuccess) {
+    *vendor_id = gpu_info.gpu.vendor_id;
+    *device_id = gpu_info.gpu.device_id;
+  }
+  return result;
+}
+
+#endif // defined(OS_LINUX)
+
+#if defined(OS_MACOSX)
+
+CollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
+  DCHECK(vendor_id && device_id);
+
+  GPUInfo::GPUDevice gpu = GetActiveGPU();
+  *vendor_id = gpu.vendor_id;
+  *device_id = gpu.device_id;
+
+  if (*vendor_id != 0 && *device_id != 0)
+    return kCollectInfoSuccess;
+  return kCollectInfoNonFatalFailure;
+}
+
+#endif
+
+#if defined(OS_ANDROID)
+CollectInfoResult CollectGpuID(uint32 *vendor_id, uint32 *device_id)
+{
+    DCHECK(vendor_id && device_id);
+    *vendor_id = 0;
+    *device_id = 0;
+    return kCollectInfoNonFatalFailure;
+}
+#endif  // defined(OS_ANDROID)
+
+namespace gpu {
+
+namespace {
+
+GPUTestConfig::OS GetCurrentOS() {
+#if defined(OS_CHROMEOS)
+  return GPUTestConfig::kOsChromeOS;
+#elif defined(OS_LINUX) || defined(OS_OPENBSD)
+  return GPUTestConfig::kOsLinux;
+#elif defined(OS_WIN)
+  int32 major_version = 0;
+  int32 minor_version = 0;
+  int32 bugfix_version = 0;
+  base::SysInfo::OperatingSystemVersionNumbers(
+      &major_version, &minor_version, &bugfix_version);
+  if (major_version == 5)
+    return GPUTestConfig::kOsWinXP;
+  if (major_version == 6 && minor_version == 0)
+    return GPUTestConfig::kOsWinVista;
+  if (major_version == 6 && minor_version == 1)
+    return GPUTestConfig::kOsWin7;
+  if (major_version == 6 && (minor_version == 2 || minor_version == 3))
+    return GPUTestConfig::kOsWin8;
+  if (major_version == 10)
+    return GPUTestConfig::kOsWin10;
+#elif defined(OS_MACOSX)
+  int32 major_version = 0;
+  int32 minor_version = 0;
+  int32 bugfix_version = 0;
+  base::SysInfo::OperatingSystemVersionNumbers(
+      &major_version, &minor_version, &bugfix_version);
+  if (major_version == 10) {
+    switch (minor_version) {
+      case 5:
+        return GPUTestConfig::kOsMacLeopard;
+      case 6:
+        return GPUTestConfig::kOsMacSnowLeopard;
+      case 7:
+        return GPUTestConfig::kOsMacLion;
+      case 8:
+        return GPUTestConfig::kOsMacMountainLion;
+      case 9:
+        return GPUTestConfig::kOsMacMavericks;
+      case 10:
+        return GPUTestConfig::kOsMacYosemite;
+      case 11:
+        return GPUTestConfig::kOsMacElCapitan;
+    }
+  }
+#elif defined(OS_ANDROID)
+  return GPUTestConfig::kOsAndroid;
+#endif
+  return GPUTestConfig::kOsUnknown;
+}
+
+}  // namespace anonymous
+
+GPUTestConfig::GPUTestConfig()
+    : validate_gpu_info_(true),
+      os_(kOsUnknown),
+      gpu_device_id_(0),
+      build_type_(kBuildTypeUnknown),
+      api_(kAPIUnknown) {}
+
+GPUTestConfig::~GPUTestConfig() {
+}
+
+void GPUTestConfig::set_os(int32 os) {
+  DCHECK_EQ(0, os & ~(kOsAndroid | kOsWin | kOsMac | kOsLinux | kOsChromeOS));
+  os_ = os;
+}
+
+void GPUTestConfig::AddGPUVendor(uint32 gpu_vendor) {
+  DCHECK_NE(0u, gpu_vendor);
+  for (size_t i = 0; i < gpu_vendor_.size(); ++i)
+    DCHECK_NE(gpu_vendor_[i], gpu_vendor);
+  gpu_vendor_.push_back(gpu_vendor);
+}
+
+void GPUTestConfig::set_gpu_device_id(uint32 id) {
+  gpu_device_id_ = id;
+}
+
+void GPUTestConfig::set_build_type(int32 build_type) {
+  DCHECK_EQ(0, build_type & ~(kBuildTypeRelease | kBuildTypeDebug));
+  build_type_ = build_type;
+}
+
+void GPUTestConfig::set_api(int32 api) {
+  DCHECK_EQ(0, api & ~(kAPID3D9 | kAPID3D11 | kAPIGLDesktop | kAPIGLES));
+  api_ = api;
+}
+
+bool GPUTestConfig::IsValid() const {
+  if (!validate_gpu_info_)
+    return true;
+  if (gpu_device_id_ != 0 && (gpu_vendor_.size() != 1 || gpu_vendor_[0] == 0))
+    return false;
+  return true;
+}
+
+bool GPUTestConfig::OverlapsWith(const GPUTestConfig& config) const {
+  DCHECK(IsValid());
+  DCHECK(config.IsValid());
+  if (config.os_ != kOsUnknown && os_ != kOsUnknown &&
+      (os_ & config.os_) == 0)
+    return false;
+  if (config.gpu_vendor_.size() > 0 && gpu_vendor_.size() > 0) {
+    bool shared = false;
+    for (size_t i = 0; i < config.gpu_vendor_.size() && !shared; ++i) {
+      for (size_t j = 0; j < gpu_vendor_.size(); ++j) {
+        if (config.gpu_vendor_[i] == gpu_vendor_[j]) {
+          shared = true;
+          break;
+        }
+      }
+    }
+    if (!shared)
+      return false;
+  }
+  if (config.gpu_device_id_ != 0 && gpu_device_id_ != 0 &&
+      gpu_device_id_ != config.gpu_device_id_)
+    return false;
+  if (config.build_type_ != kBuildTypeUnknown &&
+      build_type_ != kBuildTypeUnknown &&
+      (build_type_ & config.build_type_) == 0)
+    return false;
+  return true;
+}
+
+void GPUTestConfig::DisableGPUInfoValidation() {
+  validate_gpu_info_ = false;
+}
+
+void GPUTestConfig::ClearGPUVendor() {
+  gpu_vendor_.clear();
+}
+
+GPUTestBotConfig::~GPUTestBotConfig() {
+}
+
+void GPUTestBotConfig::AddGPUVendor(uint32 gpu_vendor) {
+  DCHECK_EQ(0u, GPUTestConfig::gpu_vendor().size());
+  GPUTestConfig::AddGPUVendor(gpu_vendor);
+}
+
+bool GPUTestBotConfig::SetGPUInfo(const GPUInfo& gpu_info) {
+  DCHECK(validate_gpu_info_);
+  if (gpu_info.gpu.device_id == 0 || gpu_info.gpu.vendor_id == 0)
+    return false;
+  ClearGPUVendor();
+  AddGPUVendor(gpu_info.gpu.vendor_id);
+  set_gpu_device_id(gpu_info.gpu.device_id);
+  return true;
+}
+
+bool GPUTestBotConfig::IsValid() const {
+  switch (os()) {
+    case kOsWinXP:
+    case kOsWinVista:
+    case kOsWin7:
+    case kOsWin8:
+    case kOsWin10:
+    case kOsMacLeopard:
+    case kOsMacSnowLeopard:
+    case kOsMacLion:
+    case kOsMacMountainLion:
+    case kOsMacMavericks:
+    case kOsMacYosemite:
+    case kOsMacElCapitan:
+    case kOsLinux:
+    case kOsChromeOS:
+    case kOsAndroid:
+      break;
+    default:
+      return false;
+  }
+  if (validate_gpu_info_) {
+    if (gpu_vendor().size() != 1 || gpu_vendor()[0] == 0)
+      return false;
+    if (gpu_device_id() == 0)
+      return false;
+  }
+  switch (build_type()) {
+    case kBuildTypeRelease:
+    case kBuildTypeDebug:
+      break;
+    default:
+      return false;
+  }
+  return true;
+}
+
+bool GPUTestBotConfig::Matches(const GPUTestConfig& config) const {
+  DCHECK(IsValid());
+  DCHECK(config.IsValid());
+  if (config.os() != kOsUnknown && (os() & config.os()) == 0)
+    return false;
+  if (config.gpu_vendor().size() > 0) {
+    bool contained = false;
+    for (size_t i = 0; i < config.gpu_vendor().size(); ++i) {
+      if (config.gpu_vendor()[i] == gpu_vendor()[0]) {
+        contained = true;
+        break;
+      }
+    }
+    if (!contained)
+      return false;
+  }
+  if (config.gpu_device_id() != 0 &&
+      gpu_device_id() != config.gpu_device_id())
+    return false;
+  if (config.build_type() != kBuildTypeUnknown &&
+      (build_type() & config.build_type()) == 0)
+    return false;
+  if (config.api() != 0 && (api() & config.api()) == 0)
+    return false;
+  return true;
+}
+
+bool GPUTestBotConfig::Matches(const std::string& config_data) const {
+  GPUTestExpectationsParser parser;
+  GPUTestConfig config;
+
+  if (!parser.ParseConfig(config_data, &config))
+    return false;
+  return Matches(config);
+}
+
+bool GPUTestBotConfig::LoadCurrentConfig(const GPUInfo *gpu_info)
+{
+    bool rt;
+    if (gpu_info == NULL)
+    {
+        GPUInfo my_gpu_info;
+        CollectInfoResult result =
+            CollectGpuID(&my_gpu_info.gpu.vendor_id, &my_gpu_info.gpu.device_id);
+        if (result != kCollectInfoSuccess)
+        {
+            LOG(ERROR) << "Fail to identify GPU\n";
+            DisableGPUInfoValidation();
+            rt = true;
+        }
+        else
+        {
+            rt = SetGPUInfo(my_gpu_info);
+        }
+    }
+    else
+    {
+        rt = SetGPUInfo(*gpu_info);
+    }
+    set_os(GetCurrentOS());
+    if (os() == kOsUnknown)
+    {
+        LOG(ERROR) << "Unknown OS\n";
+        rt = false;
+    }
+#if defined(NDEBUG)
+    set_build_type(kBuildTypeRelease);
+#else
+    set_build_type(kBuildTypeDebug);
+#endif
+    return rt;
+}
+
+// static
+bool GPUTestBotConfig::CurrentConfigMatches(const std::string& config_data) {
+  GPUTestBotConfig my_config;
+  if (!my_config.LoadCurrentConfig(NULL))
+    return false;
+  return my_config.Matches(config_data);
+}
+
+// static
+bool GPUTestBotConfig::CurrentConfigMatches(
+    const std::vector<std::string>& configs) {
+  GPUTestBotConfig my_config;
+  if (!my_config.LoadCurrentConfig(NULL))
+    return false;
+  for (size_t i = 0 ; i < configs.size(); ++i) {
+    if (my_config.Matches(configs[i]))
+      return true;
+  }
+  return false;
+}
+
+}  // namespace gpu
+
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config.h b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config.h
new file mode 100644
index 0000000..4cbc2c0
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config.h
@@ -0,0 +1,140 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_TEST_CONFIG_H_
+#define GPU_CONFIG_GPU_TEST_CONFIG_H_
+
+#include <string>
+#include <vector>
+
+#include "angle_config.h"
+
+namespace gpu {
+
+struct GPUInfo;
+
+class GPU_EXPORT GPUTestConfig {
+ public:
+  enum OS {
+    kOsUnknown = 0,
+    kOsWinXP = 1 << 0,
+    kOsWinVista = 1 << 1,
+    kOsWin7 = 1 << 2,
+    kOsWin8 = 1 << 3,
+    kOsMacLeopard = 1 << 4,
+    kOsMacSnowLeopard = 1 << 5,
+    kOsMacLion = 1 << 6,
+    kOsMacMountainLion = 1 << 7,
+    kOsMacMavericks = 1 << 8,
+    kOsMacYosemite = 1 << 9,
+    kOsMacElCapitan = 1 << 10,
+    kOsMac = kOsMacLeopard | kOsMacSnowLeopard | kOsMacLion |
+             kOsMacMountainLion | kOsMacMavericks | kOsMacYosemite |
+             kOsMacElCapitan,
+    kOsLinux = 1 << 11,
+    kOsChromeOS = 1 << 12,
+    kOsAndroid = 1 << 13,
+    kOsWin10 = 1 << 14,
+    kOsWin = kOsWinXP | kOsWinVista | kOsWin7 | kOsWin8 | kOsWin10,
+  };
+
+  enum BuildType {
+    kBuildTypeUnknown = 0,
+    kBuildTypeRelease = 1 << 0,
+    kBuildTypeDebug = 1 << 1,
+  };
+
+  enum API {
+    kAPIUnknown = 0,
+    kAPID3D9 = 1 << 0,
+    kAPID3D11 = 1 << 1,
+    kAPIGLDesktop = 1 << 2,
+    kAPIGLES = 1 << 3,
+  };
+
+  GPUTestConfig();
+  virtual ~GPUTestConfig();
+
+  void set_os(int32 os);
+  void set_gpu_device_id(uint32 id);
+  void set_build_type(int32 build_type);
+  void set_api(int32 api);
+
+  virtual void AddGPUVendor(uint32 gpu_vendor);
+
+  int32 os() const { return os_; }
+  const std::vector<uint32>& gpu_vendor() const { return gpu_vendor_; }
+  uint32 gpu_device_id() const { return gpu_device_id_; }
+  int32 build_type() const { return build_type_; }
+  int32 api() const { return api_; }
+
+  // Check if the config is valid. For example, if gpu_device_id_ is set, but
+  // gpu_vendor_ is unknown, then it's invalid.
+  virtual bool IsValid() const;
+
+  // Check if two configs overlap, i.e., if there exists a config that matches
+  // both configs.
+  bool OverlapsWith(const GPUTestConfig& config) const;
+
+  // Disable validation of GPU vendor and device ids.
+  void DisableGPUInfoValidation();
+
+ protected:
+  void ClearGPUVendor();
+
+  // Indicates that the OS has the notion of a numeric GPU vendor and device id
+  // and this data should be validated.
+  bool validate_gpu_info_;
+
+ private:
+  // operating system.
+  int32 os_;
+
+  // GPU vendor.
+  std::vector<uint32> gpu_vendor_;
+
+  // GPU device id (unique to each vendor).
+  uint32 gpu_device_id_;
+
+  // Release or Debug.
+  int32 build_type_;
+
+  // Back-end rendering APIs.
+  int32 api_;
+};
+
+class GPU_EXPORT GPUTestBotConfig : public GPUTestConfig {
+ public:
+  GPUTestBotConfig() { }
+  ~GPUTestBotConfig() override;
+
+  // This should only be called when no gpu_vendor is added.
+  void AddGPUVendor(uint32 gpu_vendor) override;
+
+  // Return false if gpu_info does not have valid vendor_id and device_id.
+  bool SetGPUInfo(const GPUInfo& gpu_info);
+
+  // Check if the bot config is valid, i.e., if it is one valid test-bot
+  // environment. For example, if a field is unknown, or if OS is not one
+  // fully defined OS, then it's valid.
+  bool IsValid() const override;
+
+  // Check if a bot config matches a test config, i.e., the test config is a
+  // superset of the bot config.
+  bool Matches(const GPUTestConfig& config) const;
+  bool Matches(const std::string& config_data) const;
+
+  // Setup the config with the current gpu testing environment.
+  // If gpu_info is NULL, collect GPUInfo first.
+  bool LoadCurrentConfig(const GPUInfo* gpu_info);
+
+  // Check if this bot's config matches |config_data| or any of the |configs|.
+  static bool CurrentConfigMatches(const std::string& config_data);
+  static bool CurrentConfigMatches(const std::vector<std::string>& configs);
+};
+
+}  // namespace gpu
+
+#endif  // GPU_CONFIG_GPU_TEST_CONFIG_H_
+
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config_mac.h b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config_mac.h
new file mode 100644
index 0000000..da22bd6
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config_mac.h
@@ -0,0 +1,28 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gpu_test_config_mac.h:
+//   Helper functions for gpu_test_config that have to be compiled in ObjectiveC++
+//
+
+#ifndef GPU_TEST_EXPECTATIONS_GPU_TEST_CONFIG_MAC_H_
+#define GPU_TEST_EXPECTATIONS_GPU_TEST_CONFIG_MAC_H_
+
+#include "gpu_info.h"
+
+namespace base {
+
+class SysInfo
+{
+  public:
+    static void OperatingSystemVersionNumbers(
+        int32 *major_version, int32 *minor_version, int32 *bugfix_version);
+};
+
+} // namespace base
+
+gpu::GPUInfo::GPUDevice GetActiveGPU();
+
+#endif // GPU_TEST_EXPECTATIONS_GPU_TEST_CONFIG_MAC_H_
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config_mac.mm b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config_mac.mm
new file mode 100644
index 0000000..e33804b
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_config_mac.mm
@@ -0,0 +1,75 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// gpu_test_config_mac.mm:
+//   Helper functions for gpu_test_config that have to be compiled in ObjectiveC++
+
+#include "gpu_test_config_mac.h"
+
+#import <Cocoa/Cocoa.h>
+
+namespace base {
+
+// OSX 10.8 deprecates Gestalt but doesn't make the operatingSystemVersion property part of the
+// public interface of NSProcessInfo until 10.10. Add a forward declaration.
+#if !defined(MAC_OS_X_VERSION_10_10) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10
+@interface NSProcessInfo (YosemiteSDK)
+@property(readonly) NSOperatingSystemVersion operatingSystemVersion;
+@end
+#endif
+
+void SysInfo::OperatingSystemVersionNumbers(
+    int32 *major_version, int32 *minor_version, int32 *bugfix_version)
+{
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
+  Gestalt(gestaltSystemVersionMajor, reinterpret_cast<SInt32*>(major_version));
+  Gestalt(gestaltSystemVersionMinor, reinterpret_cast<SInt32*>(minor_version));
+  Gestalt(gestaltSystemVersionBugFix, reinterpret_cast<SInt32*>(bugfix_version));
+#else
+  NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
+  *major_version = version.majorVersion;
+  *minor_version = version.minorVersion;
+  *bugfix_version = version.patchVersion;
+#endif
+}
+
+} // namespace base
+
+UInt32 GetEntryProperty(io_registry_entry_t entry, CFStringRef property_name) {
+  CFTypeRef type = IORegistryEntrySearchCFProperty(entry,
+                                                   kIOServicePlane,
+                                                   property_name,
+                                                   kCFAllocatorDefault,
+                                                   kIORegistryIterateRecursively | kIORegistryIterateParents);
+  CFDataRef data = reinterpret_cast<CFDataRef>(type);
+  if (!data) {
+    CFRelease(data);
+    return 0;
+  }
+
+  UInt32 value = 0;
+  const uint32_t* valuePointer = reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(data));
+  if (valuePointer != NULL) {
+    value = *valuePointer;
+  }
+  CFRelease(data);
+  return value;
+}
+
+gpu::GPUInfo::GPUDevice GetActiveGPU() {
+  gpu::GPUInfo::GPUDevice gpu;
+
+  // Ignore the fact that CGDisplayIOServicePort is deprecated as Apple
+  // did not provide a good replacement for it as of 10.10.
+  // TODO(cwallez) revisit with later systems
+  #pragma clang diagnostic push
+  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
+  #pragma clang diagnostic pop
+
+  gpu.vendor_id = GetEntryProperty(dsp_port, CFSTR("vendor-id"));
+  gpu.device_id = GetEntryProperty(dsp_port, CFSTR("device-id"));
+  return gpu;
+}
+
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_expectations_parser.cc b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_expectations_parser.cc
new file mode 100644
index 0000000..23c4d8c
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_expectations_parser.cc
@@ -0,0 +1,583 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu_test_expectations_parser.h"
+
+#include "common/angleutils.h"
+
+namespace base {
+
+namespace {
+
+bool StartsWithASCII(const std::string& str,
+                     const std::string& search,
+                     bool case_sensitive) {
+  ASSERT(!case_sensitive);
+  return str.compare(0, search.length(), search) == 0;
+}
+
+template <class Char> inline Char ToLowerASCII(Char c) {
+  return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
+}
+
+template<typename Iter>
+static inline bool DoLowerCaseEqualsASCII(Iter a_begin,
+                                          Iter a_end,
+                                          const char* b) {
+  for (Iter it = a_begin; it != a_end; ++it, ++b) {
+    if (!*b || base::ToLowerASCII(*it) != *b)
+      return false;
+  }
+  return *b == 0;
+}
+
+bool LowerCaseEqualsASCII(const std::string& a, const char* b) {
+  return DoLowerCaseEqualsASCII(a.begin(), a.end(), b);
+}
+
+} // anonymous namespace
+
+} // namespace base
+
+namespace gpu {
+
+namespace {
+
+enum LineParserStage {
+  kLineParserBegin = 0,
+  kLineParserBugID,
+  kLineParserConfigs,
+  kLineParserColon,
+  kLineParserTestName,
+  kLineParserEqual,
+  kLineParserExpectations,
+};
+
+enum Token {
+  // os
+  kConfigWinXP = 0,
+  kConfigWinVista,
+  kConfigWin7,
+  kConfigWin8,
+  kConfigWin10,
+  kConfigWin,
+  kConfigMacLeopard,
+  kConfigMacSnowLeopard,
+  kConfigMacLion,
+  kConfigMacMountainLion,
+  kConfigMacMavericks,
+  kConfigMacYosemite,
+  kConfigMacElCapitan,
+  kConfigMac,
+  kConfigLinux,
+  kConfigChromeOS,
+  kConfigAndroid,
+  // gpu vendor
+  kConfigNVidia,
+  kConfigAMD,
+  kConfigIntel,
+  kConfigVMWare,
+  // build type
+  kConfigRelease,
+  kConfigDebug,
+  // ANGLE renderer
+  kConfigD3D9,
+  kConfigD3D11,
+  kConfigGLDesktop,
+  kConfigGLES,
+  // expectation
+  kExpectationPass,
+  kExpectationFail,
+  kExpectationFlaky,
+  kExpectationTimeout,
+  kExpectationSkip,
+  // separator
+  kSeparatorColon,
+  kSeparatorEqual,
+
+  kNumberOfExactMatchTokens,
+
+  // others
+  kConfigGPUDeviceID,
+  kTokenComment,
+  kTokenWord,
+};
+
+struct TokenInfo {
+  const char* name;
+  int32 flag;
+};
+
+const TokenInfo kTokenData[] = {
+    {"xp", GPUTestConfig::kOsWinXP},
+    {"vista", GPUTestConfig::kOsWinVista},
+    {"win7", GPUTestConfig::kOsWin7},
+    {"win8", GPUTestConfig::kOsWin8},
+    {"win10", GPUTestConfig::kOsWin10},
+    {"win", GPUTestConfig::kOsWin},
+    {"leopard", GPUTestConfig::kOsMacLeopard},
+    {"snowleopard", GPUTestConfig::kOsMacSnowLeopard},
+    {"lion", GPUTestConfig::kOsMacLion},
+    {"mountainlion", GPUTestConfig::kOsMacMountainLion},
+    {"mavericks", GPUTestConfig::kOsMacMavericks},
+    {"yosemite", GPUTestConfig::kOsMacYosemite},
+    {"elcapitan", GPUTestConfig::kOsMacElCapitan},
+    {"mac", GPUTestConfig::kOsMac},
+    {"linux", GPUTestConfig::kOsLinux},
+    {"chromeos", GPUTestConfig::kOsChromeOS},
+    {"android", GPUTestConfig::kOsAndroid},
+    {"nvidia", 0x10DE},
+    {"amd", 0x1002},
+    {"intel", 0x8086},
+    {"vmware", 0x15ad},
+    {"release", GPUTestConfig::kBuildTypeRelease},
+    {"debug", GPUTestConfig::kBuildTypeDebug},
+    {"d3d9", GPUTestConfig::kAPID3D9},
+    {"d3d11", GPUTestConfig::kAPID3D11},
+    {"opengl", GPUTestConfig::kAPIGLDesktop},
+    {"gles", GPUTestConfig::kAPIGLES},
+    {"pass", GPUTestExpectationsParser::kGpuTestPass},
+    {"fail", GPUTestExpectationsParser::kGpuTestFail},
+    {"flaky", GPUTestExpectationsParser::kGpuTestFlaky},
+    {"timeout", GPUTestExpectationsParser::kGpuTestTimeout},
+    {"skip", GPUTestExpectationsParser::kGpuTestSkip},
+    {":", 0},
+    {"=", 0},
+};
+
+enum ErrorType {
+  kErrorFileIO = 0,
+  kErrorIllegalEntry,
+  kErrorInvalidEntry,
+  kErrorEntryWithOsConflicts,
+  kErrorEntryWithGpuVendorConflicts,
+  kErrorEntryWithBuildTypeConflicts,
+  kErrorEntryWithAPIConflicts,
+  kErrorEntryWithGpuDeviceIdConflicts,
+  kErrorEntryWithExpectationConflicts,
+  kErrorEntriesOverlap,
+
+  kNumberOfErrors,
+};
+
+const char* kErrorMessage[] = {
+    "file IO failed",
+    "entry with wrong format",
+    "entry invalid, likely wrong modifiers combination",
+    "entry with OS modifier conflicts",
+    "entry with GPU vendor modifier conflicts",
+    "entry with GPU build type conflicts",
+    "entry with GPU API conflicts",
+    "entry with GPU device id conflicts or malformat",
+    "entry with expectation modifier conflicts",
+    "two entries' configs overlap",
+};
+
+Token ParseToken(const std::string& word) {
+  if (base::StartsWithASCII(word, "//", false))
+    return kTokenComment;
+  if (base::StartsWithASCII(word, "0x", false))
+    return kConfigGPUDeviceID;
+
+  for (int32 i = 0; i < kNumberOfExactMatchTokens; ++i) {
+    if (base::LowerCaseEqualsASCII(word, kTokenData[i].name))
+      return static_cast<Token>(i);
+  }
+  return kTokenWord;
+}
+
+// reference name can have the last character as *.
+bool NamesMatching(const std::string& ref, const std::string& test_name) {
+  size_t len = ref.length();
+  if (len == 0)
+    return false;
+  if (ref[len - 1] == '*') {
+    if (test_name.length() > len -1 &&
+        ref.compare(0, len - 1, test_name, 0, len - 1) == 0)
+      return true;
+    return false;
+  }
+  return (ref == test_name);
+}
+
+}  // namespace anonymous
+
+GPUTestExpectationsParser::GPUTestExpectationsParser() {
+  // Some sanity check.
+  static_assert(static_cast<unsigned int>(kNumberOfExactMatchTokens) ==
+                sizeof(kTokenData) / sizeof(kTokenData[0]), "sanity check");
+  static_assert(static_cast<unsigned int>(kNumberOfErrors) ==
+                sizeof(kErrorMessage) / sizeof(kErrorMessage[0]), "sanity check");
+}
+
+GPUTestExpectationsParser::~GPUTestExpectationsParser() {
+}
+
+bool GPUTestExpectationsParser::LoadTestExpectations(const std::string& data) {
+  entries_.clear();
+  error_messages_.clear();
+
+  std::vector<std::string> lines = base::SplitString(
+      data, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+  bool rt = true;
+  for (size_t i = 0; i < lines.size(); ++i) {
+    if (!ParseLine(lines[i], i + 1))
+      rt = false;
+  }
+  if (DetectConflictsBetweenEntries()) {
+    entries_.clear();
+    rt = false;
+  }
+
+  return rt;
+}
+
+bool GPUTestExpectationsParser::LoadTestExpectationsFromFile(
+    const std::string& path) {
+  entries_.clear();
+  error_messages_.clear();
+
+  std::string data;
+  if (!base::ReadFileToString(path, &data)) {
+    error_messages_.push_back(kErrorMessage[kErrorFileIO]);
+    return false;
+  }
+  return LoadTestExpectations(data);
+}
+
+int32 GPUTestExpectationsParser::GetTestExpectation(
+    const std::string& test_name,
+    const GPUTestBotConfig& bot_config) const {
+  for (size_t i = 0; i < entries_.size(); ++i) {
+    if (NamesMatching(entries_[i].test_name, test_name) &&
+        bot_config.Matches(entries_[i].test_config))
+      return entries_[i].test_expectation;
+  }
+  return kGpuTestPass;
+}
+
+const std::vector<std::string>&
+GPUTestExpectationsParser::GetErrorMessages() const {
+  return error_messages_;
+}
+
+bool GPUTestExpectationsParser::ParseConfig(
+    const std::string& config_data, GPUTestConfig* config) {
+  DCHECK(config);
+  std::vector<std::string> tokens = base::SplitString(
+      config_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
+      base::SPLIT_WANT_NONEMPTY);
+
+  for (size_t i = 0; i < tokens.size(); ++i) {
+    Token token = ParseToken(tokens[i]);
+    switch (token) {
+      case kConfigWinXP:
+      case kConfigWinVista:
+      case kConfigWin7:
+      case kConfigWin8:
+      case kConfigWin10:
+      case kConfigWin:
+      case kConfigMacLeopard:
+      case kConfigMacSnowLeopard:
+      case kConfigMacLion:
+      case kConfigMacMountainLion:
+      case kConfigMacMavericks:
+      case kConfigMacYosemite:
+      case kConfigMacElCapitan:
+      case kConfigMac:
+      case kConfigLinux:
+      case kConfigChromeOS:
+      case kConfigAndroid:
+      case kConfigNVidia:
+      case kConfigAMD:
+      case kConfigIntel:
+      case kConfigVMWare:
+      case kConfigRelease:
+      case kConfigDebug:
+      case kConfigD3D9:
+      case kConfigD3D11:
+      case kConfigGLDesktop:
+      case kConfigGLES:
+      case kConfigGPUDeviceID:
+        if (token == kConfigGPUDeviceID) {
+          if (!UpdateTestConfig(config, tokens[i], 0))
+            return false;
+        } else {
+          if (!UpdateTestConfig(config, token, 0))
+            return false;
+        }
+        break;
+      default:
+        return false;
+    }
+  }
+  return true;
+}
+
+bool GPUTestExpectationsParser::ParseLine(
+    const std::string& line_data, size_t line_number) {
+  std::vector<std::string> tokens = base::SplitString(
+      line_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
+      base::SPLIT_WANT_NONEMPTY);
+  int32 stage = kLineParserBegin;
+  GPUTestExpectationEntry entry;
+  entry.line_number = line_number;
+  GPUTestConfig& config = entry.test_config;
+  bool comments_encountered = false;
+  for (size_t i = 0; i < tokens.size() && !comments_encountered; ++i) {
+    Token token = ParseToken(tokens[i]);
+    switch (token) {
+      case kTokenComment:
+        comments_encountered = true;
+        break;
+      case kConfigWinXP:
+      case kConfigWinVista:
+      case kConfigWin7:
+      case kConfigWin8:
+      case kConfigWin10:
+      case kConfigWin:
+      case kConfigMacLeopard:
+      case kConfigMacSnowLeopard:
+      case kConfigMacLion:
+      case kConfigMacMountainLion:
+      case kConfigMacMavericks:
+      case kConfigMacYosemite:
+      case kConfigMacElCapitan:
+      case kConfigMac:
+      case kConfigLinux:
+      case kConfigChromeOS:
+      case kConfigAndroid:
+      case kConfigNVidia:
+      case kConfigAMD:
+      case kConfigIntel:
+      case kConfigVMWare:
+      case kConfigRelease:
+      case kConfigDebug:
+      case kConfigD3D9:
+      case kConfigD3D11:
+      case kConfigGLDesktop:
+      case kConfigGLES:
+      case kConfigGPUDeviceID:
+        // MODIFIERS, could be in any order, need at least one.
+        if (stage != kLineParserConfigs && stage != kLineParserBugID) {
+          PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+                           line_number);
+          return false;
+        }
+        if (token == kConfigGPUDeviceID) {
+          if (!UpdateTestConfig(&config, tokens[i], line_number))
+            return false;
+        } else {
+          if (!UpdateTestConfig(&config, token, line_number))
+            return false;
+        }
+        if (stage == kLineParserBugID)
+          stage++;
+        break;
+      case kSeparatorColon:
+        // :
+        if (stage != kLineParserConfigs) {
+          PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+                           line_number);
+          return false;
+        }
+        stage++;
+        break;
+      case kSeparatorEqual:
+        // =
+        if (stage != kLineParserTestName) {
+          PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+                           line_number);
+          return false;
+        }
+        stage++;
+        break;
+      case kTokenWord:
+        // BUG_ID or TEST_NAME
+        if (stage == kLineParserBegin) {
+          // Bug ID is not used for anything; ignore it.
+        } else if (stage == kLineParserColon) {
+          entry.test_name = tokens[i];
+        } else {
+          PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+                           line_number);
+          return false;
+        }
+        stage++;
+        break;
+      case kExpectationPass:
+      case kExpectationFail:
+      case kExpectationFlaky:
+      case kExpectationTimeout:
+      case kExpectationSkip:
+        // TEST_EXPECTATIONS
+        if (stage != kLineParserEqual && stage != kLineParserExpectations) {
+          PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+                           line_number);
+          return false;
+        }
+        if ((kTokenData[token].flag & entry.test_expectation) != 0) {
+          PushErrorMessage(kErrorMessage[kErrorEntryWithExpectationConflicts],
+                           line_number);
+          return false;
+        }
+        entry.test_expectation =
+            (kTokenData[token].flag | entry.test_expectation);
+        if (stage == kLineParserEqual)
+          stage++;
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+  if (stage == kLineParserBegin) {
+    // The whole line is empty or all comments
+    return true;
+  }
+  if (stage == kLineParserExpectations) {
+    if (!config.IsValid()) {
+        PushErrorMessage(kErrorMessage[kErrorInvalidEntry], line_number);
+        return false;
+    }
+    entries_.push_back(entry);
+    return true;
+  }
+  PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
+  return false;
+}
+
+bool GPUTestExpectationsParser::UpdateTestConfig(
+    GPUTestConfig* config, int32 token, size_t line_number) {
+  DCHECK(config);
+  switch (token) {
+    case kConfigWinXP:
+    case kConfigWinVista:
+    case kConfigWin7:
+    case kConfigWin8:
+    case kConfigWin10:
+    case kConfigWin:
+    case kConfigMacLeopard:
+    case kConfigMacSnowLeopard:
+    case kConfigMacLion:
+    case kConfigMacMountainLion:
+    case kConfigMacMavericks:
+    case kConfigMacYosemite:
+    case kConfigMacElCapitan:
+    case kConfigMac:
+    case kConfigLinux:
+    case kConfigChromeOS:
+    case kConfigAndroid:
+      if ((config->os() & kTokenData[token].flag) != 0) {
+        PushErrorMessage(kErrorMessage[kErrorEntryWithOsConflicts],
+                         line_number);
+        return false;
+      }
+      config->set_os(config->os() | kTokenData[token].flag);
+      break;
+    case kConfigNVidia:
+    case kConfigAMD:
+    case kConfigIntel:
+    case kConfigVMWare:
+      {
+        uint32 gpu_vendor =
+            static_cast<uint32>(kTokenData[token].flag);
+        for (size_t i = 0; i < config->gpu_vendor().size(); ++i) {
+          if (config->gpu_vendor()[i] == gpu_vendor) {
+            PushErrorMessage(
+                kErrorMessage[kErrorEntryWithGpuVendorConflicts],
+                line_number);
+            return false;
+          }
+        }
+        config->AddGPUVendor(gpu_vendor);
+      }
+      break;
+    case kConfigRelease:
+    case kConfigDebug:
+      if ((config->build_type() & kTokenData[token].flag) != 0) {
+        PushErrorMessage(
+            kErrorMessage[kErrorEntryWithBuildTypeConflicts],
+            line_number);
+        return false;
+      }
+      config->set_build_type(
+          config->build_type() | kTokenData[token].flag);
+      break;
+    case kConfigD3D9:
+    case kConfigD3D11:
+    case kConfigGLDesktop:
+    case kConfigGLES:
+      if ((config->api() & kTokenData[token].flag) != 0) {
+        PushErrorMessage(kErrorMessage[kErrorEntryWithAPIConflicts],
+                         line_number);
+        return false;
+      }
+      config->set_api(config->api() | kTokenData[token].flag);
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  return true;
+}
+
+bool GPUTestExpectationsParser::UpdateTestConfig(
+    GPUTestConfig* config,
+    const std::string& gpu_device_id,
+    size_t line_number) {
+  DCHECK(config);
+  uint32 device_id = 0;
+  if (config->gpu_device_id() != 0 ||
+      !base::HexStringToUInt(gpu_device_id, &device_id) ||
+      device_id == 0) {
+    PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts],
+                     line_number);
+    return false;
+  }
+  config->set_gpu_device_id(device_id);
+  return true;
+}
+
+bool GPUTestExpectationsParser::DetectConflictsBetweenEntries() {
+  bool rt = false;
+  for (size_t i = 0; i < entries_.size(); ++i) {
+    for (size_t j = i + 1; j < entries_.size(); ++j) {
+      if (entries_[i].test_name == entries_[j].test_name &&
+          entries_[i].test_config.OverlapsWith(entries_[j].test_config)) {
+        PushErrorMessage(kErrorMessage[kErrorEntriesOverlap],
+                         entries_[i].line_number,
+                         entries_[j].line_number);
+        rt = true;
+      }
+    }
+  }
+  return rt;
+}
+
+void GPUTestExpectationsParser::PushErrorMessage(
+    const std::string& message, size_t line_number) {
+  error_messages_.push_back(
+      base::StringPrintf("Line %d : %s",
+                         static_cast<int>(line_number), message.c_str()));
+}
+
+void GPUTestExpectationsParser::PushErrorMessage(
+    const std::string& message,
+    size_t entry1_line_number,
+    size_t entry2_line_number) {
+  error_messages_.push_back(
+      base::StringPrintf("Line %d and %d : %s",
+                         static_cast<int>(entry1_line_number),
+                         static_cast<int>(entry2_line_number),
+                         message.c_str()));
+}
+
+GPUTestExpectationsParser:: GPUTestExpectationEntry::GPUTestExpectationEntry()
+    : test_expectation(0),
+      line_number(0) {
+}
+
+}  // namespace gpu
+
diff --git a/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_expectations_parser.h b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_expectations_parser.h
new file mode 100644
index 0000000..a112700
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/gpu_test_expectations/gpu_test_expectations_parser.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
+#define GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
+
+#include <string>
+#include <vector>
+
+#include "angle_config.h"
+#include "gpu_test_config.h"
+
+namespace gpu {
+
+class GPU_EXPORT GPUTestExpectationsParser {
+ public:
+  enum GPUTestExpectation {
+    kGpuTestPass = 1 << 0,
+    kGpuTestFail = 1 << 1,
+    kGpuTestFlaky = 1 << 2,
+    kGpuTestTimeout = 1 << 3,
+    kGpuTestSkip = 1 << 4,
+  };
+
+  GPUTestExpectationsParser();
+  ~GPUTestExpectationsParser();
+
+  // Parse the text expectations, and if no error is encountered,
+  // save all the entries. Otherwise, generate error messages.
+  // Return true if parsing succeeds.
+  bool LoadTestExpectations(const std::string& data);
+  bool LoadTestExpectationsFromFile(const std::string& path);
+
+  // Query error messages from the last LoadTestExpectations() call.
+  const std::vector<std::string>& GetErrorMessages() const;
+
+  // Get the test expectation of a given test on a given bot.
+  int32 GetTestExpectation(const std::string& test_name,
+                           const GPUTestBotConfig& bot_config) const;
+
+  // Parse a list of config modifiers. If we have a valid entry with no
+  // conflicts, | config | stores it, and the function returns true.
+  bool ParseConfig(const std::string& config_data, GPUTestConfig* config);
+
+ private:
+  struct GPUTestExpectationEntry {
+    GPUTestExpectationEntry();
+
+    std::string test_name;
+    GPUTestConfig test_config;
+    int32 test_expectation;
+    size_t line_number;
+  };
+
+  // Parse a line of text. If we have a valid entry, save it; otherwise,
+  // generate error messages.
+  bool ParseLine(const std::string& line_data, size_t line_number);
+
+  // Update OS/GPUVendor/BuildType modifiers. May generate an error message.
+  bool UpdateTestConfig(
+      GPUTestConfig* config, int32 token, size_t line_number);
+
+  // Update GPUDeviceID modifier. May generate an error message.
+  bool UpdateTestConfig(GPUTestConfig* config,
+                        const std::string & gpu_device_id,
+                        size_t line_number);
+
+  // Check if two entries' config overlap with each other. May generate an
+  // error message.
+  bool DetectConflictsBetweenEntries();
+
+  // Save an error message, which can be queried later.
+  void PushErrorMessage(const std::string& message, size_t line_number);
+  void PushErrorMessage(const std::string& message,
+                        size_t entry1_line_number,
+                        size_t entry2_line_number);
+
+  std::vector<GPUTestExpectationEntry> entries_;
+  std::vector<std::string> error_messages_;
+};
+
+}  // namespace gpu
+
+#endif  // GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
+
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/LICENSE b/src/third_party/angle/src/tests/third_party/rapidjson/LICENSE
new file mode 100644
index 0000000..03d97d1
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2011 Milo Yip
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/README.chromium b/src/third_party/angle/src/tests/third_party/rapidjson/README.chromium
new file mode 100644
index 0000000..466659a
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/README.chromium
@@ -0,0 +1,8 @@
+Name: RapidJSON
+URL: https://github.com/miloyip/rapidjson
+Version: 24dd7ef839b79941d129e833368e913aa9c045da
+License: Custom
+License File: LICENSE
+
+Description:
+RapidJSON is a JSON parser and generator for C++.
\ No newline at end of file
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/allocators.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/allocators.h
new file mode 100644
index 0000000..0bd2d28
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/allocators.h
@@ -0,0 +1,245 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ALLOCATORS_H_
+#define RAPIDJSON_ALLOCATORS_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocator
+
+/*! \class rapidjson::Allocator
+    \brief Concept for allocating, resizing and freeing memory block.
+    
+    Note that Malloc() and Realloc() are non-static but Free() is static.
+    
+    So if an allocator need to support Free(), it needs to put its pointer in 
+    the header of memory block.
+
+\code
+concept Allocator {
+    static const bool kNeedFree;    //!< Whether this allocator needs to call Free().
+
+    // Allocate a memory block.
+    // \param size of the memory block in bytes.
+    // \returns pointer to the memory block.
+    void* Malloc(size_t size);
+
+    // Resize a memory block.
+    // \param originalPtr The pointer to current memory block. Null pointer is permitted.
+    // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
+    // \param newSize the new size in bytes.
+    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
+
+    // Free a memory block.
+    // \param pointer to the memory block. Null pointer is permitted.
+    static void Free(void *ptr);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// CrtAllocator
+
+//! C-runtime library allocator.
+/*! This class is just wrapper for standard C library memory routines.
+    \note implements Allocator concept
+*/
+class CrtAllocator {
+public:
+    static const bool kNeedFree = true;
+    void* Malloc(size_t size) { return std::malloc(size); }
+    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); }
+    static void Free(void *ptr) { std::free(ptr); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MemoryPoolAllocator
+
+//! Default memory allocator used by the parser and DOM.
+/*! This allocator allocate memory blocks from pre-allocated memory chunks. 
+
+    It does not free memory blocks. And Realloc() only allocate new memory.
+
+    The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
+
+    User may also supply a buffer as the first chunk.
+
+    If the user-buffer is full then additional chunks are allocated by BaseAllocator.
+
+    The user-buffer is not deallocated by this allocator.
+
+    \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
+    \note implements Allocator concept
+*/
+template <typename BaseAllocator = CrtAllocator>
+class MemoryPoolAllocator {
+public:
+    static const bool kNeedFree = false;    //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
+
+    //! Constructor with chunkSize.
+    /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+        \param baseAllocator The allocator for allocating memory chunks.
+    */
+    MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : 
+        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+    {
+    }
+
+    //! Constructor with user-supplied buffer.
+    /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
+
+        The user buffer will not be deallocated when this allocator is destructed.
+
+        \param buffer User supplied buffer.
+        \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
+        \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+        \param baseAllocator The allocator for allocating memory chunks.
+    */
+    MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+    {
+        RAPIDJSON_ASSERT(buffer != 0);
+        RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
+        chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
+        chunkHead_->capacity = size - sizeof(ChunkHeader);
+        chunkHead_->size = 0;
+        chunkHead_->next = 0;
+    }
+
+    //! Destructor.
+    /*! This deallocates all memory chunks, excluding the user-supplied buffer.
+    */
+    ~MemoryPoolAllocator() {
+        Clear();
+        RAPIDJSON_DELETE(ownBaseAllocator_);
+    }
+
+    //! Deallocates all memory chunks, excluding the user-supplied buffer.
+    void Clear() {
+        while(chunkHead_ != 0 && chunkHead_ != userBuffer_) {
+            ChunkHeader* next = chunkHead_->next;
+            baseAllocator_->Free(chunkHead_);
+            chunkHead_ = next;
+        }
+    }
+
+    //! Computes the total capacity of allocated memory chunks.
+    /*! \return total capacity in bytes.
+    */
+    size_t Capacity() const {
+        size_t capacity = 0;
+        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+            capacity += c->capacity;
+        return capacity;
+    }
+
+    //! Computes the memory blocks allocated.
+    /*! \return total used bytes.
+    */
+    size_t Size() const {
+        size_t size = 0;
+        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+            size += c->size;
+        return size;
+    }
+
+    //! Allocates a memory block. (concept Allocator)
+    void* Malloc(size_t size) {
+        size = RAPIDJSON_ALIGN(size);
+        if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
+            AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
+
+        void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size;
+        chunkHead_->size += size;
+        return buffer;
+    }
+
+    //! Resizes a memory block (concept Allocator)
+    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+        if (originalPtr == 0)
+            return Malloc(newSize);
+
+        // Do not shrink if new size is smaller than original
+        if (originalSize >= newSize)
+            return originalPtr;
+
+        // Simply expand it if it is the last allocation and there is sufficient space
+        if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
+            size_t increment = static_cast<size_t>(newSize - originalSize);
+            increment = RAPIDJSON_ALIGN(increment);
+            if (chunkHead_->size + increment <= chunkHead_->capacity) {
+                chunkHead_->size += increment;
+                return originalPtr;
+            }
+        }
+
+        // Realloc process: allocate and copy memory, do not free original buffer.
+        void* newBuffer = Malloc(newSize);
+        RAPIDJSON_ASSERT(newBuffer != 0);   // Do not handle out-of-memory explicitly.
+        return std::memcpy(newBuffer, originalPtr, originalSize);
+    }
+
+    //! Frees a memory block (concept Allocator)
+    static void Free(void *ptr) { (void)ptr; } // Do nothing
+
+private:
+    //! Copy constructor is not permitted.
+    MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
+    //! Copy assignment operator is not permitted.
+    MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
+
+    //! Creates a new chunk.
+    /*! \param capacity Capacity of the chunk in bytes.
+    */
+    void AddChunk(size_t capacity) {
+        if (!baseAllocator_)
+            ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
+        ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
+        chunk->capacity = capacity;
+        chunk->size = 0;
+        chunk->next = chunkHead_;
+        chunkHead_ =  chunk;
+    }
+
+    static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
+
+    //! Chunk header for perpending to each chunk.
+    /*! Chunks are stored as a singly linked list.
+    */
+    struct ChunkHeader {
+        size_t capacity;    //!< Capacity of the chunk in bytes (excluding the header itself).
+        size_t size;        //!< Current size of allocated memory in bytes.
+        ChunkHeader *next;  //!< Next chunk in the linked list.
+    };
+
+    ChunkHeader *chunkHead_;    //!< Head of the chunk linked-list. Only the head chunk serves allocation.
+    size_t chunk_capacity_;     //!< The minimum capacity of chunk when they are allocated.
+    void *userBuffer_;          //!< User supplied buffer.
+    BaseAllocator* baseAllocator_;  //!< base allocator for allocating memory chunks.
+    BaseAllocator* ownBaseAllocator_;   //!< base allocator created by this object.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/document.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/document.h
new file mode 100644
index 0000000..94d6e53
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/document.h
@@ -0,0 +1,1932 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_DOCUMENT_H_
+#define RAPIDJSON_DOCUMENT_H_
+
+/*! \file document.h */
+
+#include "reader.h"
+#include "internal/meta.h"
+#include "internal/strfunc.h"
+#include <new>      // placement new
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#elif defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_HAS_STDSTRING
+
+#ifndef RAPIDJSON_HAS_STDSTRING
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
+#else
+#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
+#endif
+/*! \def RAPIDJSON_HAS_STDSTRING
+    \ingroup RAPIDJSON_CONFIG
+    \brief Enable RapidJSON support for \c std::string
+
+    By defining this preprocessor symbol to \c 1, several convenience functions for using
+    \ref rapidjson::GenericValue with \c std::string are enabled, especially
+    for construction and comparison.
+
+    \hideinitializer
+*/
+#include <string>
+#endif // RAPIDJSON_HAS_STDSTRING
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+#include <iterator> // std::iterator, std::random_access_iterator_tag
+#endif
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+// Forward declaration.
+template <typename Encoding, typename Allocator>
+class GenericValue;
+
+//! Name-value pair in a JSON object value.
+/*!
+    This class was internal to GenericValue. It used to be a inner struct.
+    But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
+    https://code.google.com/p/rapidjson/issues/detail?id=64
+*/
+template <typename Encoding, typename Allocator> 
+struct GenericMember { 
+    GenericValue<Encoding, Allocator> name;     //!< name of member (must be a string)
+    GenericValue<Encoding, Allocator> value;    //!< value of member.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericMemberIterator
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+
+//! (Constant) member iterator for a JSON object value
+/*!
+    \tparam Const Is this a constant iterator?
+    \tparam Encoding    Encoding of the value. (Even non-string values need to have the same encoding in a document)
+    \tparam Allocator   Allocator type for allocating memory of object, array and string.
+
+    This class implements a Random Access Iterator for GenericMember elements
+    of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
+
+    \note This iterator implementation is mainly intended to avoid implicit
+        conversions from iterator values to \c NULL,
+        e.g. from GenericValue::FindMember.
+
+    \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
+        pointer-based implementation, if your platform doesn't provide
+        the C++ <iterator> header.
+
+    \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
+ */
+template <bool Const, typename Encoding, typename Allocator>
+class GenericMemberIterator
+    : public std::iterator<std::random_access_iterator_tag
+        , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
+
+    friend class GenericValue<Encoding,Allocator>;
+    template <bool, typename, typename> friend class GenericMemberIterator;
+
+    typedef GenericMember<Encoding,Allocator> PlainType;
+    typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+    typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
+
+public:
+    //! Iterator type itself
+    typedef GenericMemberIterator Iterator;
+    //! Constant iterator type
+    typedef GenericMemberIterator<true,Encoding,Allocator>  ConstIterator;
+    //! Non-constant iterator type
+    typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
+
+    //! Pointer to (const) GenericMember
+    typedef typename BaseType::pointer         Pointer;
+    //! Reference to (const) GenericMember
+    typedef typename BaseType::reference       Reference;
+    //! Signed integer type (e.g. \c ptrdiff_t)
+    typedef typename BaseType::difference_type DifferenceType;
+
+    //! Default constructor (singular value)
+    /*! Creates an iterator pointing to no element.
+        \note All operations, except for comparisons, are undefined on such values.
+     */
+    GenericMemberIterator() : ptr_() {}
+
+    //! Iterator conversions to more const
+    /*!
+        \param it (Non-const) iterator to copy from
+
+        Allows the creation of an iterator from another GenericMemberIterator
+        that is "less const".  Especially, creating a non-constant iterator
+        from a constant iterator are disabled:
+        \li const -> non-const (not ok)
+        \li const -> const (ok)
+        \li non-const -> const (ok)
+        \li non-const -> non-const (ok)
+
+        \note If the \c Const template parameter is already \c false, this
+            constructor effectively defines a regular copy-constructor.
+            Otherwise, the copy constructor is implicitly defined.
+    */
+    GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
+
+    //! @name stepping
+    //@{
+    Iterator& operator++(){ ++ptr_; return *this; }
+    Iterator& operator--(){ --ptr_; return *this; }
+    Iterator  operator++(int){ Iterator old(*this); ++ptr_; return old; }
+    Iterator  operator--(int){ Iterator old(*this); --ptr_; return old; }
+    //@}
+
+    //! @name increment/decrement
+    //@{
+    Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
+    Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
+
+    Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
+    Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
+    //@}
+
+    //! @name relations
+    //@{
+    bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
+    bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
+    bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
+    bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
+    bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
+    bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
+    //@}
+
+    //! @name dereference
+    //@{
+    Reference operator*() const { return *ptr_; }
+    Pointer   operator->() const { return ptr_; }
+    Reference operator[](DifferenceType n) const { return ptr_[n]; }
+    //@}
+
+    //! Distance
+    DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
+
+private:
+    //! Internal constructor from plain pointer
+    explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
+
+    Pointer ptr_; //!< raw pointer
+};
+
+#else // RAPIDJSON_NOMEMBERITERATORCLASS
+
+// class-based member iterator implementation disabled, use plain pointers
+
+template <bool Const, typename Encoding, typename Allocator>
+struct GenericMemberIterator;
+
+//! non-const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<false,Encoding,Allocator> {
+    //! use plain pointer as iterator type
+    typedef GenericMember<Encoding,Allocator>* Iterator;
+};
+//! const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<true,Encoding,Allocator> {
+    //! use plain const pointer as iterator type
+    typedef const GenericMember<Encoding,Allocator>* Iterator;
+};
+
+#endif // RAPIDJSON_NOMEMBERITERATORCLASS
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericStringRef
+
+//! Reference to a constant string (not taking a copy)
+/*!
+    \tparam CharType character type of the string
+
+    This helper class is used to automatically infer constant string
+    references for string literals, especially from \c const \b (!)
+    character arrays.
+
+    The main use is for creating JSON string values without copying the
+    source string via an \ref Allocator.  This requires that the referenced
+    string pointers have a sufficient lifetime, which exceeds the lifetime
+    of the associated GenericValue.
+
+    \b Example
+    \code
+    Value v("foo");   // ok, no need to copy & calculate length
+    const char foo[] = "foo";
+    v.SetString(foo); // ok
+
+    const char* bar = foo;
+    // Value x(bar); // not ok, can't rely on bar's lifetime
+    Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
+    Value y(StringRef(bar, 3));  // ok, explicitly pass length
+    \endcode
+
+    \see StringRef, GenericValue::SetString
+*/
+template<typename CharType>
+struct GenericStringRef {
+    typedef CharType Ch; //!< character type of the string
+
+    //! Create string reference from \c const character array
+    /*!
+        This constructor implicitly creates a constant string reference from
+        a \c const character array.  It has better performance than
+        \ref StringRef(const CharType*) by inferring the string \ref length
+        from the array length, and also supports strings containing null
+        characters.
+
+        \tparam N length of the string, automatically inferred
+
+        \param str Constant character array, lifetime assumed to be longer
+            than the use of the string in e.g. a GenericValue
+
+        \post \ref s == str
+
+        \note Constant complexity.
+        \note There is a hidden, private overload to disallow references to
+            non-const character arrays to be created via this constructor.
+            By this, e.g. function-scope arrays used to be filled via
+            \c snprintf are excluded from consideration.
+            In such cases, the referenced string should be \b copied to the
+            GenericValue instead.
+     */
+    template<SizeType N>
+    GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
+        : s(str), length(N-1) {}
+
+    //! Explicitly create string reference from \c const character pointer
+    /*!
+        This constructor can be used to \b explicitly  create a reference to
+        a constant string pointer.
+
+        \see StringRef(const CharType*)
+
+        \param str Constant character pointer, lifetime assumed to be longer
+            than the use of the string in e.g. a GenericValue
+
+        \post \ref s == str
+
+        \note There is a hidden, private overload to disallow references to
+            non-const character arrays to be created via this constructor.
+            By this, e.g. function-scope arrays used to be filled via
+            \c snprintf are excluded from consideration.
+            In such cases, the referenced string should be \b copied to the
+            GenericValue instead.
+     */
+    explicit GenericStringRef(const CharType* str)
+        : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
+
+    //! Create constant string reference from pointer and length
+    /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+        \param len length of the string, excluding the trailing NULL terminator
+
+        \post \ref s == str && \ref length == len
+        \note Constant complexity.
+     */
+    GenericStringRef(const CharType* str, SizeType len)
+        : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
+
+    //! implicit conversion to plain CharType pointer
+    operator const Ch *() const { return s; }
+
+    const Ch* const s; //!< plain CharType pointer
+    const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
+
+private:
+    //! Disallow copy-assignment
+    GenericStringRef operator=(const GenericStringRef&);
+    //! Disallow construction from non-const array
+    template<SizeType N>
+    GenericStringRef(CharType (&str)[N]) /* = delete */;
+};
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal".  This function
+    can be used to avoid copying a character string to be referenced as a
+    value in a JSON GenericValue object, if the string's lifetime is known
+    to be valid long enough.
+    \tparam CharType Character type of the string
+    \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+    \return GenericStringRef string reference object
+    \relatesalso GenericStringRef
+
+    \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str) {
+    return GenericStringRef<CharType>(str, internal::StrLen(str));
+}
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal".  This function
+    can be used to avoid copying a character string to be referenced as a
+    value in a JSON GenericValue object, if the string's lifetime is known
+    to be valid long enough.
+
+    This version has better performance with supplied length, and also
+    supports string containing null characters.
+
+    \tparam CharType character type of the string
+    \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+    \param length The length of source string.
+    \return GenericStringRef string reference object
+    \relatesalso GenericStringRef
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
+    return GenericStringRef<CharType>(str, SizeType(length));
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+//! Mark a string object as constant string
+/*! Mark a string object (e.g. \c std::string) as a "string literal".
+    This function can be used to avoid copying a string to be referenced as a
+    value in a JSON GenericValue object, if the string's lifetime is known
+    to be valid long enough.
+
+    \tparam CharType character type of the string
+    \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+    \return GenericStringRef string reference object
+    \relatesalso GenericStringRef
+    \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
+    return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue type traits
+namespace internal {
+
+template <typename T, typename Encoding = void, typename Allocator = void>
+struct IsGenericValueImpl : FalseType {};
+
+// select candidates according to nested encoding and allocator types
+template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
+    : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
+
+// helper to match arbitrary GenericValue instantiations, including derived classes
+template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue
+
+//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
+/*!
+    A JSON value can be one of 7 types. This class is a variant type supporting
+    these types.
+
+    Use the Value if UTF8 and default allocator
+
+    \tparam Encoding    Encoding of the value. (Even non-string values need to have the same encoding in a document)
+    \tparam Allocator   Allocator type for allocating memory of object, array and string.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > 
+class GenericValue {
+public:
+    //! Name-value pair in an object.
+    typedef GenericMember<Encoding, Allocator> Member;
+    typedef Encoding EncodingType;                  //!< Encoding type from template parameter.
+    typedef Allocator AllocatorType;                //!< Allocator type from template parameter.
+    typedef typename Encoding::Ch Ch;               //!< Character type derived from Encoding.
+    typedef GenericStringRef<Ch> StringRefType;     //!< Reference to a constant string
+    typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator;  //!< Member iterator for iterating in object.
+    typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator;  //!< Constant member iterator for iterating in object.
+    typedef GenericValue* ValueIterator;            //!< Value iterator for iterating in array.
+    typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
+
+    //!@name Constructors and destructor.
+    //@{
+
+    //! Default constructor creates a null value.
+    GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    //! Move constructor in C++11
+    GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) {
+        rhs.flags_ = kNullFlag; // give up contents
+    }
+#endif
+
+private:
+    //! Copy constructor is not permitted.
+    GenericValue(const GenericValue& rhs);
+
+public:
+
+    //! Constructor with JSON value type.
+    /*! This creates a Value of specified type with default content.
+        \param type Type of the value.
+        \note Default content for number is zero.
+    */
+    explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
+        static const unsigned defaultFlags[7] = {
+            kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
+            kNumberAnyFlag
+        };
+        RAPIDJSON_ASSERT(type <= kNumberType);
+        flags_ = defaultFlags[type];
+
+        // Use ShortString to store empty string.
+        if (type == kStringType)
+            data_.ss.SetLength(0);
+    }
+
+    //! Explicit copy constructor (with allocator)
+    /*! Creates a copy of a Value by using the given Allocator
+        \tparam SourceAllocator allocator of \c rhs
+        \param rhs Value to copy from (read-only)
+        \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
+        \see CopyFrom()
+    */
+    template< typename SourceAllocator >
+    GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
+
+    //! Constructor for boolean value.
+    /*! \param b Boolean value
+        \note This constructor is limited to \em real boolean values and rejects
+            implicitly converted types like arbitrary pointers.  Use an explicit cast
+            to \c bool, if you want to construct a boolean JSON value in such cases.
+     */
+#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
+    template <typename T>
+    explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
+#else
+    explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
+#endif
+        : data_(), flags_(b ? kTrueFlag : kFalseFlag) {
+            // safe-guard against failing SFINAE
+            RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
+    }
+
+    //! Constructor for int value.
+    explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) {
+        data_.n.i64 = i;
+        if (i >= 0)
+            flags_ |= kUintFlag | kUint64Flag;
+    }
+
+    //! Constructor for unsigned value.
+    explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) {
+        data_.n.u64 = u; 
+        if (!(u & 0x80000000))
+            flags_ |= kIntFlag | kInt64Flag;
+    }
+
+    //! Constructor for int64_t value.
+    explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) {
+        data_.n.i64 = i64;
+        if (i64 >= 0) {
+            flags_ |= kNumberUint64Flag;
+            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+                flags_ |= kUintFlag;
+            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+                flags_ |= kIntFlag;
+        }
+        else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+            flags_ |= kIntFlag;
+    }
+
+    //! Constructor for uint64_t value.
+    explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
+        data_.n.u64 = u64;
+        if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
+            flags_ |= kInt64Flag;
+        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+            flags_ |= kUintFlag;
+        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+            flags_ |= kIntFlag;
+    }
+
+    //! Constructor for double value.
+    explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
+
+    //! Constructor for constant string (i.e. do not make a copy of string)
+    GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); }
+
+    //! Constructor for constant string (i.e. do not make a copy of string)
+    explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); }
+
+    //! Constructor for copy-string (i.e. do make a copy of string)
+    GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); }
+
+    //! Constructor for copy-string (i.e. do make a copy of string)
+    GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+    //! Constructor for copy-string from a string object (i.e. do make a copy of string)
+    /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+     */
+    GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
+#endif
+
+    //! Destructor.
+    /*! Need to destruct elements of array, members of object, or copy-string.
+    */
+    ~GenericValue() {
+        if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
+            switch(flags_) {
+            case kArrayFlag:
+                for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+                    v->~GenericValue();
+                Allocator::Free(data_.a.elements);
+                break;
+
+            case kObjectFlag:
+                for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+                    m->~Member();
+                Allocator::Free(data_.o.members);
+                break;
+
+            case kCopyStringFlag:
+                Allocator::Free(const_cast<Ch*>(data_.s.str));
+                break;
+
+            default:
+                break;  // Do nothing for other types.
+            }
+        }
+    }
+
+    //@}
+
+    //!@name Assignment operators
+    //@{
+
+    //! Assignment with move semantics.
+    /*! \param rhs Source of the assignment. It will become a null value after assignment.
+    */
+    GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+        RAPIDJSON_ASSERT(this != &rhs);
+        this->~GenericValue();
+        RawAssign(rhs);
+        return *this;
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    //! Move assignment in C++11
+    GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
+        return *this = rhs.Move();
+    }
+#endif
+
+    //! Assignment of constant string reference (no copy)
+    /*! \param str Constant string reference to be assigned
+        \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
+        \see GenericStringRef, operator=(T)
+    */
+    GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
+        GenericValue s(str);
+        return *this = s;
+    }
+
+    //! Assignment with primitive types.
+    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+        \param value The value to be assigned.
+
+        \note The source type \c T explicitly disallows all pointer types,
+            especially (\c const) \ref Ch*.  This helps avoiding implicitly
+            referencing character strings with insufficient lifetime, use
+            \ref SetString(const Ch*, Allocator&) (for copying) or
+            \ref StringRef() (to explicitly mark the pointer as constant) instead.
+            All other pointer types would implicitly convert to \c bool,
+            use \ref SetBool() instead.
+    */
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
+    operator=(T value) {
+        GenericValue v(value);
+        return *this = v;
+    }
+
+    //! Deep-copy assignment from Value
+    /*! Assigns a \b copy of the Value to the current Value object
+        \tparam SourceAllocator Allocator type of \c rhs
+        \param rhs Value to copy from (read-only)
+        \param allocator Allocator to use for copying
+     */
+    template <typename SourceAllocator>
+    GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
+        RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
+        this->~GenericValue();
+        new (this) GenericValue(rhs, allocator);
+        return *this;
+    }
+
+    //! Exchange the contents of this value with those of other.
+    /*!
+        \param other Another value.
+        \note Constant complexity.
+    */
+    GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
+        GenericValue temp;
+        temp.RawAssign(*this);
+        RawAssign(other);
+        other.RawAssign(temp);
+        return *this;
+    }
+
+    //! Prepare Value for move semantics
+    /*! \return *this */
+    GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
+    //@}
+
+    //!@name Equal-to and not-equal-to operators
+    //@{
+    //! Equal-to operator
+    /*!
+        \note If an object contains duplicated named member, comparing equality with any object is always \c false.
+        \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
+    */
+    template <typename SourceAllocator>
+    bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+        typedef GenericValue<Encoding, SourceAllocator> RhsType;
+        if (GetType() != rhs.GetType())
+            return false;
+
+        switch (GetType()) {
+        case kObjectType: // Warning: O(n^2) inner-loop
+            if (data_.o.size != rhs.data_.o.size)
+                return false;           
+            for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
+                typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
+                if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
+                    return false;
+            }
+            return true;
+            
+        case kArrayType:
+            if (data_.a.size != rhs.data_.a.size)
+                return false;
+            for (SizeType i = 0; i < data_.a.size; i++)
+                if ((*this)[i] != rhs[i])
+                    return false;
+            return true;
+
+        case kStringType:
+            return StringEqual(rhs);
+
+        case kNumberType:
+            if (IsDouble() || rhs.IsDouble())
+                return GetDouble() == rhs.GetDouble(); // May convert one operand from integer to double.
+            else
+                return data_.n.u64 == rhs.data_.n.u64;
+
+        default: // kTrueType, kFalseType, kNullType
+            return true;
+        }
+    }
+
+    //! Equal-to operator with const C-string pointer
+    bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
+
+#if RAPIDJSON_HAS_STDSTRING
+    //! Equal-to operator with string object
+    /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+     */
+    bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
+#endif
+
+    //! Equal-to operator with primitive types
+    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
+    */
+    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
+
+    //! Not-equal-to operator
+    /*! \return !(*this == rhs)
+     */
+    template <typename SourceAllocator>
+    bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
+
+    //! Not-equal-to operator with const C-string pointer
+    bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
+
+    //! Not-equal-to operator with arbitrary types
+    /*! \return !(*this == rhs)
+     */
+    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
+
+    //! Equal-to operator with arbitrary types (symmetric version)
+    /*! \return (rhs == lhs)
+     */
+    template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
+
+    //! Not-Equal-to operator with arbitrary types (symmetric version)
+    /*! \return !(rhs == lhs)
+     */
+    template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
+    //@}
+
+    //!@name Type
+    //@{
+
+    Type GetType()  const { return static_cast<Type>(flags_ & kTypeMask); }
+    bool IsNull()   const { return flags_ == kNullFlag; }
+    bool IsFalse()  const { return flags_ == kFalseFlag; }
+    bool IsTrue()   const { return flags_ == kTrueFlag; }
+    bool IsBool()   const { return (flags_ & kBoolFlag) != 0; }
+    bool IsObject() const { return flags_ == kObjectFlag; }
+    bool IsArray()  const { return flags_ == kArrayFlag; }
+    bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
+    bool IsInt()    const { return (flags_ & kIntFlag) != 0; }
+    bool IsUint()   const { return (flags_ & kUintFlag) != 0; }
+    bool IsInt64()  const { return (flags_ & kInt64Flag) != 0; }
+    bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
+    bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
+    bool IsString() const { return (flags_ & kStringFlag) != 0; }
+
+    //@}
+
+    //!@name Null
+    //@{
+
+    GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
+
+    //@}
+
+    //!@name Bool
+    //@{
+
+    bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
+    //!< Set boolean value
+    /*! \post IsBool() == true */
+    GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
+
+    //@}
+
+    //!@name Object
+    //@{
+
+    //! Set this value as an empty object.
+    /*! \post IsObject() == true */
+    GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
+
+    //! Get the number of members in the object.
+    SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
+
+    //! Check whether the object is empty.
+    bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
+
+    //! Get a value from an object associated with the name.
+    /*! \pre IsObject() == true
+        \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
+        \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
+        Since 0.2, if the name is not correct, it will assert.
+        If user is unsure whether a member exists, user should use HasMember() first.
+        A better approach is to use FindMember().
+        \note Linear time complexity.
+    */
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
+        GenericValue n(StringRef(name));
+        return (*this)[n];
+    }
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+    //! Get a value from an object associated with the name.
+    /*! \pre IsObject() == true
+        \tparam SourceAllocator Allocator of the \c name value
+
+        \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
+        And it can also handle strings with embedded null characters.
+
+        \note Linear time complexity.
+    */
+    template <typename SourceAllocator>
+    GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
+        MemberIterator member = FindMember(name);
+        if (member != MemberEnd())
+            return member->value;
+        else {
+            RAPIDJSON_ASSERT(false);    // see above note
+            static GenericValue NullValue;
+            return NullValue;
+        }
+    }
+    template <typename SourceAllocator>
+    const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+    //! Const member iterator
+    /*! \pre IsObject() == true */
+    ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
+    //! Const \em past-the-end member iterator
+    /*! \pre IsObject() == true */
+    ConstMemberIterator MemberEnd() const   { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); }
+    //! Member iterator
+    /*! \pre IsObject() == true */
+    MemberIterator MemberBegin()            { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); }
+    //! \em Past-the-end member iterator
+    /*! \pre IsObject() == true */
+    MemberIterator MemberEnd()              { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); }
+
+    //! Check whether a member exists in the object.
+    /*!
+        \param name Member name to be searched.
+        \pre IsObject() == true
+        \return Whether a member with that name exists.
+        \note It is better to use FindMember() directly if you need the obtain the value as well.
+        \note Linear time complexity.
+    */
+    bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
+
+    //! Check whether a member exists in the object with GenericValue name.
+    /*!
+        This version is faster because it does not need a StrLen(). It can also handle string with null character.
+        \param name Member name to be searched.
+        \pre IsObject() == true
+        \return Whether a member with that name exists.
+        \note It is better to use FindMember() directly if you need the obtain the value as well.
+        \note Linear time complexity.
+    */
+    template <typename SourceAllocator>
+    bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
+
+    //! Find member by name.
+    /*!
+        \param name Member name to be searched.
+        \pre IsObject() == true
+        \return Iterator to member, if it exists.
+            Otherwise returns \ref MemberEnd().
+
+        \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+            the requested member doesn't exist. For consistency with e.g.
+            \c std::map, this has been changed to MemberEnd() now.
+        \note Linear time complexity.
+    */
+    MemberIterator FindMember(const Ch* name) {
+        GenericValue n(StringRef(name));
+        return FindMember(n);
+    }
+
+    ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+    //! Find member by name.
+    /*!
+        This version is faster because it does not need a StrLen(). It can also handle string with null character.
+        \param name Member name to be searched.
+        \pre IsObject() == true
+        \return Iterator to member, if it exists.
+            Otherwise returns \ref MemberEnd().
+
+        \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+            the requested member doesn't exist. For consistency with e.g.
+            \c std::map, this has been changed to MemberEnd() now.
+        \note Linear time complexity.
+    */
+    template <typename SourceAllocator>
+    MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
+        RAPIDJSON_ASSERT(IsObject());
+        RAPIDJSON_ASSERT(name.IsString());
+        MemberIterator member = MemberBegin();
+        for ( ; member != MemberEnd(); ++member)
+            if (name.StringEqual(member->name))
+                break;
+        return member;
+    }
+    template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+    //! Add a member (name-value pair) to the object.
+    /*! \param name A string value as name of member.
+        \param value Value of any type.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \note The ownership of \c name and \c value will be transferred to this object on success.
+        \pre  IsObject() && name.IsString()
+        \post name.IsNull() && value.IsNull()
+        \note Amortized Constant time complexity.
+    */
+    GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
+        RAPIDJSON_ASSERT(IsObject());
+        RAPIDJSON_ASSERT(name.IsString());
+
+        Object& o = data_.o;
+        if (o.size >= o.capacity) {
+            if (o.capacity == 0) {
+                o.capacity = kDefaultObjectCapacity;
+                o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)));
+            }
+            else {
+                SizeType oldCapacity = o.capacity;
+                o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
+                o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)));
+            }
+        }
+        o.members[o.size].name.RawAssign(name);
+        o.members[o.size].value.RawAssign(value);
+        o.size++;
+        return *this;
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
+        return AddMember(name, value, allocator);
+    }
+    GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
+        return AddMember(name, value, allocator);
+    }
+    GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
+        return AddMember(name, value, allocator);
+    }
+    GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
+        GenericValue n(name);
+        return AddMember(n, value, allocator);
+    }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+
+    //! Add a member (name-value pair) to the object.
+    /*! \param name A constant string reference as name of member.
+        \param value Value of any type.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \note The ownership of \c value will be transferred to this object on success.
+        \pre  IsObject()
+        \post value.IsNull()
+        \note Amortized Constant time complexity.
+    */
+    GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
+        GenericValue n(name);
+        return AddMember(n, value, allocator);
+    }
+
+    //! Add a constant string value as member (name-value pair) to the object.
+    /*! \param name A constant string reference as name of member.
+        \param value constant string reference as value of member.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \pre  IsObject()
+        \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
+        \note Amortized Constant time complexity.
+    */
+    GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
+        GenericValue v(value);
+        return AddMember(name, v, allocator);
+    }
+
+    //! Add any primitive value as member (name-value pair) to the object.
+    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+        \param name A constant string reference as name of member.
+        \param value Value of primitive type \c T as value of member
+        \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \pre  IsObject()
+
+        \note The source type \c T explicitly disallows all pointer types,
+            especially (\c const) \ref Ch*.  This helps avoiding implicitly
+            referencing character strings with insufficient lifetime, use
+            \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+            AddMember(StringRefType, StringRefType, Allocator&).
+            All other pointer types would implicitly convert to \c bool,
+            use an explicit cast instead, if needed.
+        \note Amortized Constant time complexity.
+    */
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+    AddMember(StringRefType name, T value, Allocator& allocator) {
+        GenericValue n(name);
+        GenericValue v(value);
+        return AddMember(n, v, allocator);
+    }
+
+    //! Remove all members in the object.
+    /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
+        \note Linear time complexity.
+    */
+    void RemoveAllMembers() {
+        RAPIDJSON_ASSERT(IsObject()); 
+        for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+            m->~Member();
+        data_.o.size = 0;
+    }
+
+    //! Remove a member in object by its name.
+    /*! \param name Name of member to be removed.
+        \return Whether the member existed.
+        \note This function may reorder the object members. Use \ref
+            EraseMember(ConstMemberIterator) if you need to preserve the
+            relative order of the remaining members.
+        \note Linear time complexity.
+    */
+    bool RemoveMember(const Ch* name) {
+        GenericValue n(StringRef(name));
+        return RemoveMember(n);
+    }
+
+    template <typename SourceAllocator>
+    bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
+        MemberIterator m = FindMember(name);
+        if (m != MemberEnd()) {
+            RemoveMember(m);
+            return true;
+        }
+        else
+            return false;
+    }
+
+    //! Remove a member in object by iterator.
+    /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
+        \return the new iterator after removal.
+        \note This function may reorder the object members. Use \ref
+            EraseMember(ConstMemberIterator) if you need to preserve the
+            relative order of the remaining members.
+        \note Constant time complexity.
+    */
+    MemberIterator RemoveMember(MemberIterator m) {
+        RAPIDJSON_ASSERT(IsObject());
+        RAPIDJSON_ASSERT(data_.o.size > 0);
+        RAPIDJSON_ASSERT(data_.o.members != 0);
+        RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
+
+        MemberIterator last(data_.o.members + (data_.o.size - 1));
+        if (data_.o.size > 1 && m != last) {
+            // Move the last one to this place
+            *m = *last;
+        }
+        else {
+            // Only one left, just destroy
+            m->~Member();
+        }
+        --data_.o.size;
+        return m;
+    }
+
+    //! Remove a member from an object by iterator.
+    /*! \param pos iterator to the member to remove
+        \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
+        \return Iterator following the removed element.
+            If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
+        \note This function preserves the relative order of the remaining object
+            members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
+        \note Linear time complexity.
+    */
+    MemberIterator EraseMember(ConstMemberIterator pos) {
+        return EraseMember(pos, pos +1);
+    }
+
+    //! Remove members in the range [first, last) from an object.
+    /*! \param first iterator to the first member to remove
+        \param last  iterator following the last member to remove
+        \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
+        \return Iterator following the last removed element.
+        \note This function preserves the relative order of the remaining object
+            members.
+        \note Linear time complexity.
+    */
+    MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
+        RAPIDJSON_ASSERT(IsObject());
+        RAPIDJSON_ASSERT(data_.o.size > 0);
+        RAPIDJSON_ASSERT(data_.o.members != 0);
+        RAPIDJSON_ASSERT(first >= MemberBegin());
+        RAPIDJSON_ASSERT(first <= last);
+        RAPIDJSON_ASSERT(last <= MemberEnd());
+
+        MemberIterator pos = MemberBegin() + (first - MemberBegin());
+        for (MemberIterator itr = pos; itr != last; ++itr)
+            itr->~Member();
+        std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member));
+        data_.o.size -= (last - first);
+        return pos;
+    }
+
+    //@}
+
+    //!@name Array
+    //@{
+
+    //! Set this value as an empty array.
+    /*! \post IsArray == true */
+    GenericValue& SetArray() {  this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
+
+    //! Get the number of elements in array.
+    SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
+
+    //! Get the capacity of array.
+    SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
+
+    //! Check whether the array is empty.
+    bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
+
+    //! Remove all elements in the array.
+    /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
+        \note Linear time complexity.
+    */
+    void Clear() {
+        RAPIDJSON_ASSERT(IsArray()); 
+        for (SizeType i = 0; i < data_.a.size; ++i)
+            data_.a.elements[i].~GenericValue();
+        data_.a.size = 0;
+    }
+
+    //! Get an element from array by index.
+    /*! \pre IsArray() == true
+        \param index Zero-based index of element.
+        \see operator[](T*)
+    */
+    GenericValue& operator[](SizeType index) {
+        RAPIDJSON_ASSERT(IsArray());
+        RAPIDJSON_ASSERT(index < data_.a.size);
+        return data_.a.elements[index];
+    }
+    const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
+
+    //! Element iterator
+    /*! \pre IsArray() == true */
+    ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
+    //! \em Past-the-end element iterator
+    /*! \pre IsArray() == true */
+    ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
+    //! Constant element iterator
+    /*! \pre IsArray() == true */
+    ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
+    //! Constant \em past-the-end element iterator
+    /*! \pre IsArray() == true */
+    ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
+
+    //! Request the array to have enough capacity to store elements.
+    /*! \param newCapacity  The capacity that the array at least need to have.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \note Linear time complexity.
+    */
+    GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
+        RAPIDJSON_ASSERT(IsArray());
+        if (newCapacity > data_.a.capacity) {
+            data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
+            data_.a.capacity = newCapacity;
+        }
+        return *this;
+    }
+
+    //! Append a GenericValue at the end of the array.
+    /*! \param value        Value to be appended.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \pre IsArray() == true
+        \post value.IsNull() == true
+        \return The value itself for fluent API.
+        \note The ownership of \c value will be transferred to this array on success.
+        \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+        \note Amortized constant time complexity.
+    */
+    GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
+        RAPIDJSON_ASSERT(IsArray());
+        if (data_.a.size >= data_.a.capacity)
+            Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
+        data_.a.elements[data_.a.size++].RawAssign(value);
+        return *this;
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
+        return PushBack(value, allocator);
+    }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+    //! Append a constant string reference at the end of the array.
+    /*! \param value        Constant string reference to be appended.
+        \param allocator    Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
+        \pre IsArray() == true
+        \return The value itself for fluent API.
+        \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+        \note Amortized constant time complexity.
+        \see GenericStringRef
+    */
+    GenericValue& PushBack(StringRefType value, Allocator& allocator) {
+        return (*this).template PushBack<StringRefType>(value, allocator);
+    }
+
+    //! Append a primitive value at the end of the array.
+    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+        \param value Value of primitive type T to be appended.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \pre IsArray() == true
+        \return The value itself for fluent API.
+        \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+
+        \note The source type \c T explicitly disallows all pointer types,
+            especially (\c const) \ref Ch*.  This helps avoiding implicitly
+            referencing character strings with insufficient lifetime, use
+            \ref PushBack(GenericValue&, Allocator&) or \ref
+            PushBack(StringRefType, Allocator&).
+            All other pointer types would implicitly convert to \c bool,
+            use an explicit cast instead, if needed.
+        \note Amortized constant time complexity.
+    */
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+    PushBack(T value, Allocator& allocator) {
+        GenericValue v(value);
+        return PushBack(v, allocator);
+    }
+
+    //! Remove the last element in the array.
+    /*!
+        \note Constant time complexity.
+    */
+    GenericValue& PopBack() {
+        RAPIDJSON_ASSERT(IsArray());
+        RAPIDJSON_ASSERT(!Empty());
+        data_.a.elements[--data_.a.size].~GenericValue();
+        return *this;
+    }
+
+    //! Remove an element of array by iterator.
+    /*!
+        \param pos iterator to the element to remove
+        \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
+        \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
+        \note Linear time complexity.
+    */
+    ValueIterator Erase(ConstValueIterator pos) {
+        return Erase(pos, pos + 1);
+    }
+
+    //! Remove elements in the range [first, last) of the array.
+    /*!
+        \param first iterator to the first element to remove
+        \param last  iterator following the last element to remove
+        \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
+        \return Iterator following the last removed element.
+        \note Linear time complexity.
+    */
+    ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
+        RAPIDJSON_ASSERT(IsArray());
+        RAPIDJSON_ASSERT(data_.a.size > 0);
+        RAPIDJSON_ASSERT(data_.a.elements != 0);
+        RAPIDJSON_ASSERT(first >= Begin());
+        RAPIDJSON_ASSERT(first <= last);
+        RAPIDJSON_ASSERT(last <= End());
+        ValueIterator pos = Begin() + (first - Begin());
+        for (ValueIterator itr = pos; itr != last; ++itr)
+            itr->~GenericValue();       
+        std::memmove(pos, last, (End() - last) * sizeof(GenericValue));
+        data_.a.size -= (last - first);
+        return pos;
+    }
+
+    //@}
+
+    //!@name Number
+    //@{
+
+    int GetInt() const          { RAPIDJSON_ASSERT(flags_ & kIntFlag);   return data_.n.i.i;   }
+    unsigned GetUint() const    { RAPIDJSON_ASSERT(flags_ & kUintFlag);  return data_.n.u.u;   }
+    int64_t GetInt64() const    { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
+    uint64_t GetUint64() const  { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
+
+    double GetDouble() const {
+        RAPIDJSON_ASSERT(IsNumber());
+        if ((flags_ & kDoubleFlag) != 0)                return data_.n.d;   // exact type, no conversion.
+        if ((flags_ & kIntFlag) != 0)                   return data_.n.i.i; // int -> double
+        if ((flags_ & kUintFlag) != 0)                  return data_.n.u.u; // unsigned -> double
+        if ((flags_ & kInt64Flag) != 0)                 return (double)data_.n.i64; // int64_t -> double (may lose precision)
+        RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0);  return (double)data_.n.u64; // uint64_t -> double (may lose precision)
+    }
+
+    GenericValue& SetInt(int i)             { this->~GenericValue(); new (this) GenericValue(i);    return *this; }
+    GenericValue& SetUint(unsigned u)       { this->~GenericValue(); new (this) GenericValue(u);    return *this; }
+    GenericValue& SetInt64(int64_t i64)     { this->~GenericValue(); new (this) GenericValue(i64);  return *this; }
+    GenericValue& SetUint64(uint64_t u64)   { this->~GenericValue(); new (this) GenericValue(u64);  return *this; }
+    GenericValue& SetDouble(double d)       { this->~GenericValue(); new (this) GenericValue(d);    return *this; }
+
+    //@}
+
+    //!@name String
+    //@{
+
+    const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); }
+
+    //! Get the length of string.
+    /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
+    */
+    SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
+
+    //! Set this value as a string without copying source string.
+    /*! This version has better performance with supplied length, and also support string containing null character.
+        \param s source string pointer. 
+        \param length The length of source string, excluding the trailing null terminator.
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() == s && GetStringLength() == length
+        \see SetString(StringRefType)
+    */
+    GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
+
+    //! Set this value as a string without copying source string.
+    /*! \param s source string reference
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() == s && GetStringLength() == s.length
+    */
+    GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
+
+    //! Set this value as a string by copying from source string.
+    /*! This version has better performance with supplied length, and also support string containing null character.
+        \param s source string. 
+        \param length The length of source string, excluding the trailing null terminator.
+        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+    */
+    GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
+
+    //! Set this value as a string by copying from source string.
+    /*! \param s source string. 
+        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+    */
+    GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+    //! Set this value as a string by copying from source string.
+    /*! \param s source string.
+        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
+        \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+    */
+    GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); }
+#endif
+
+    //@}
+
+    //! Generate events of this value to a Handler.
+    /*! This function adopts the GoF visitor pattern.
+        Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
+        It can also be used to deep clone this value via GenericDocument, which is also a Handler.
+        \tparam Handler type of handler.
+        \param handler An object implementing concept Handler.
+    */
+    template <typename Handler>
+    bool Accept(Handler& handler) const {
+        switch(GetType()) {
+        case kNullType:     return handler.Null();
+        case kFalseType:    return handler.Bool(false);
+        case kTrueType:     return handler.Bool(true);
+
+        case kObjectType:
+            if (!handler.StartObject())
+                return false;
+            for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
+                RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
+                if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
+                    return false;
+                if (!m->value.Accept(handler))
+                    return false;
+            }
+            return handler.EndObject(data_.o.size);
+
+        case kArrayType:
+            if (!handler.StartArray())
+                return false;
+            for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+                if (!v->Accept(handler))
+                    return false;
+            return handler.EndArray(data_.a.size);
+    
+        case kStringType:
+            return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
+    
+        case kNumberType:
+            if (IsInt())            return handler.Int(data_.n.i.i);
+            else if (IsUint())      return handler.Uint(data_.n.u.u);
+            else if (IsInt64())     return handler.Int64(data_.n.i64);
+            else if (IsUint64())    return handler.Uint64(data_.n.u64);
+            else                    return handler.Double(data_.n.d);
+    
+        default:
+            RAPIDJSON_ASSERT(false);
+        }
+        return false;
+    }
+
+private:
+    template <typename, typename> friend class GenericValue;
+    template <typename, typename, typename> friend class GenericDocument;
+
+    enum {
+        kBoolFlag = 0x100,
+        kNumberFlag = 0x200,
+        kIntFlag = 0x400,
+        kUintFlag = 0x800,
+        kInt64Flag = 0x1000,
+        kUint64Flag = 0x2000,
+        kDoubleFlag = 0x4000,
+        kStringFlag = 0x100000,
+        kCopyFlag = 0x200000,
+        kInlineStrFlag = 0x400000,
+
+        // Initial flags of different types.
+        kNullFlag = kNullType,
+        kTrueFlag = kTrueType | kBoolFlag,
+        kFalseFlag = kFalseType | kBoolFlag,
+        kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
+        kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
+        kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
+        kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
+        kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
+        kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
+        kConstStringFlag = kStringType | kStringFlag,
+        kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
+        kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
+        kObjectFlag = kObjectType,
+        kArrayFlag = kArrayType,
+
+        kTypeMask = 0xFF    // bitwise-and with mask of 0xFF can be optimized by compiler
+    };
+
+    static const SizeType kDefaultArrayCapacity = 16;
+    static const SizeType kDefaultObjectCapacity = 16;
+
+    struct String {
+        const Ch* str;
+        SizeType length;
+        unsigned hashcode;  //!< reserved
+    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
+    // (excluding the terminating zero) and store a value to determine the length of the contained
+    // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
+    // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
+    // the string terminator as well. For getting the string length back from that value just use
+    // "MaxSize - str[LenPos]".
+    // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode
+    // inline (for `UTF8`-encoded strings).
+    struct ShortString {
+        enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
+        Ch str[MaxChars];
+
+        inline static bool Usable(SizeType len) { return            (MaxSize >= len); }
+        inline void     SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize -  len); }
+        inline SizeType GetLength() const       { return  (SizeType)(MaxSize -  str[LenPos]); }
+    };  // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    // By using proper binary layout, retrieval of different integer types do not need conversions.
+    union Number {
+#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
+        struct I {
+            int i;
+            char padding[4];
+        }i;
+        struct U {
+            unsigned u;
+            char padding2[4];
+        }u;
+#else
+        struct I {
+            char padding[4];
+            int i;
+        }i;
+        struct U {
+            char padding2[4];
+            unsigned u;
+        }u;
+#endif
+        int64_t i64;
+        uint64_t u64;
+        double d;
+    };  // 8 bytes
+
+    struct Object {
+        Member* members;
+        SizeType size;
+        SizeType capacity;
+    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    struct Array {
+        GenericValue* elements;
+        SizeType size;
+        SizeType capacity;
+    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    union Data {
+        String s;
+        ShortString ss;
+        Number n;
+        Object o;
+        Array a;
+    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    // Initialize this value as array with initial data, without calling destructor.
+    void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
+        flags_ = kArrayFlag;
+        data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
+        std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
+        data_.a.size = data_.a.capacity = count;
+    }
+
+    //! Initialize this value as object with initial data, without calling destructor.
+    void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
+        flags_ = kObjectFlag;
+        data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
+        std::memcpy(data_.o.members, members, count * sizeof(Member));
+        data_.o.size = data_.o.capacity = count;
+    }
+
+    //! Initialize this value as constant string, without calling destructor.
+    void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
+        flags_ = kConstStringFlag;
+        data_.s.str = s;
+        data_.s.length = s.length;
+    }
+
+    //! Initialize this value as copy string with initial data, without calling destructor.
+    void SetStringRaw(StringRefType s, Allocator& allocator) {
+        Ch* str = NULL;
+        if(ShortString::Usable(s.length)) {
+            flags_ = kShortStringFlag;
+            data_.ss.SetLength(s.length);
+            str = data_.ss.str;
+        } else {
+            flags_ = kCopyStringFlag;
+            data_.s.length = s.length;
+            str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
+            data_.s.str = str;
+        }
+        std::memcpy(str, s, s.length * sizeof(Ch));
+        str[s.length] = '\0';
+    }
+
+    //! Assignment without calling destructor
+    void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+        data_ = rhs.data_;
+        flags_ = rhs.flags_;
+        rhs.flags_ = kNullFlag;
+    }
+
+    template <typename SourceAllocator>
+    bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+        RAPIDJSON_ASSERT(IsString());
+        RAPIDJSON_ASSERT(rhs.IsString());
+
+        const SizeType len1 = GetStringLength();
+        const SizeType len2 = rhs.GetStringLength();
+        if(len1 != len2) { return false; }
+
+        const Ch* const str1 = GetString();
+        const Ch* const str2 = rhs.GetString();
+        if(str1 == str2) { return true; } // fast path for constant string
+
+        return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
+    }
+
+    Data data_;
+    unsigned flags_;
+};
+
+//! GenericValue with UTF8 encoding
+typedef GenericValue<UTF8<> > Value;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericDocument 
+
+//! A document for parsing JSON text as DOM.
+/*!
+    \note implements Handler concept
+    \tparam Encoding Encoding for both parsing and string storage.
+    \tparam Allocator Allocator for allocating memory for the DOM
+    \tparam StackAllocator Allocator for allocating memory for stack during parsing.
+    \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor.  To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
+class GenericDocument : public GenericValue<Encoding, Allocator> {
+public:
+    typedef typename Encoding::Ch Ch;                       //!< Character type derived from Encoding.
+    typedef GenericValue<Encoding, Allocator> ValueType;    //!< Value type of the document.
+    typedef Allocator AllocatorType;                        //!< Allocator type from template parameter.
+
+    //! Constructor
+    /*! \param allocator        Optional allocator for allocating memory.
+        \param stackCapacity    Optional initial capacity of stack in bytes.
+        \param stackAllocator   Optional allocator for allocating memory for stack.
+    */
+    GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : 
+        allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
+    {
+        if (!allocator_)
+            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    //! Move constructor in C++11
+    GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+        : ValueType(std::move(rhs)),
+          allocator_(rhs.allocator_),
+          ownAllocator_(rhs.ownAllocator_),
+          stack_(std::move(rhs.stack_)),
+          parseResult_(rhs.parseResult_)
+    {
+        rhs.allocator_ = 0;
+        rhs.ownAllocator_ = 0;
+        rhs.parseResult_ = ParseResult();
+    }
+#endif
+
+    ~GenericDocument() {
+        Destroy();
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    //! Move assignment in C++11
+    GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+    {
+        // The cast to ValueType is necessary here, because otherwise it would
+        // attempt to call GenericValue's templated assignment operator.
+        ValueType::operator=(std::forward<ValueType>(rhs));
+
+        // Calling the destructor here would prematurely call stack_'s destructor
+        Destroy();
+
+        allocator_ = rhs.allocator_;
+        ownAllocator_ = rhs.ownAllocator_;
+        stack_ = std::move(rhs.stack_);
+        parseResult_ = rhs.parseResult_;
+
+        rhs.allocator_ = 0;
+        rhs.ownAllocator_ = 0;
+        rhs.parseResult_ = ParseResult();
+
+        return *this;
+    }
+#endif
+
+    //!@name Parse from stream
+    //!@{
+
+    //! Parse JSON text from an input stream (with Encoding conversion)
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \tparam SourceEncoding Encoding of input stream
+        \tparam InputStream Type of input stream, implementing Stream concept
+        \param is Input stream to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
+    GenericDocument& ParseStream(InputStream& is) {
+        ValueType::SetNull(); // Remove existing root if exist
+        GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
+        ClearStackOnExit scope(*this);
+        parseResult_ = reader.template Parse<parseFlags>(is, *this);
+        if (parseResult_) {
+            RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
+            this->RawAssign(*stack_.template Pop<ValueType>(1));    // Add this-> to prevent issue 13.
+        }
+        return *this;
+    }
+
+    //! Parse JSON text from an input stream
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \tparam InputStream Type of input stream, implementing Stream concept
+        \param is Input stream to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <unsigned parseFlags, typename InputStream>
+    GenericDocument& ParseStream(InputStream& is) {
+        return ParseStream<parseFlags,Encoding,InputStream>(is);
+    }
+
+    //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
+    /*! \tparam InputStream Type of input stream, implementing Stream concept
+        \param is Input stream to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <typename InputStream>
+    GenericDocument& ParseStream(InputStream& is) {
+        return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
+    }
+    //!@}
+
+    //!@name Parse in-place from mutable string
+    //!@{
+
+    //! Parse JSON text from a mutable string (with Encoding conversion)
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \tparam SourceEncoding Transcoding from input Encoding
+        \param str Mutable zero-terminated string to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <unsigned parseFlags, typename SourceEncoding>
+    GenericDocument& ParseInsitu(Ch* str) {
+        GenericInsituStringStream<Encoding> s(str);
+        return ParseStream<parseFlags | kParseInsituFlag, SourceEncoding>(s);
+    }
+
+    //! Parse JSON text from a mutable string
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \param str Mutable zero-terminated string to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <unsigned parseFlags>
+    GenericDocument& ParseInsitu(Ch* str) {
+        return ParseInsitu<parseFlags, Encoding>(str);
+    }
+
+    //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
+    /*! \param str Mutable zero-terminated string to be parsed.
+        \return The document itself for fluent API.
+    */
+    GenericDocument& ParseInsitu(Ch* str) {
+        return ParseInsitu<kParseDefaultFlags, Encoding>(str);
+    }
+    //!@}
+
+    //!@name Parse from read-only string
+    //!@{
+
+    //! Parse JSON text from a read-only string (with Encoding conversion)
+    /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+        \tparam SourceEncoding Transcoding from input Encoding
+        \param str Read-only zero-terminated string to be parsed.
+    */
+    template <unsigned parseFlags, typename SourceEncoding>
+    GenericDocument& Parse(const Ch* str) {
+        RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+        GenericStringStream<SourceEncoding> s(str);
+        return ParseStream<parseFlags, SourceEncoding>(s);
+    }
+
+    //! Parse JSON text from a read-only string
+    /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+        \param str Read-only zero-terminated string to be parsed.
+    */
+    template <unsigned parseFlags>
+    GenericDocument& Parse(const Ch* str) {
+        return Parse<parseFlags, Encoding>(str);
+    }
+
+    //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
+    /*! \param str Read-only zero-terminated string to be parsed.
+    */
+    GenericDocument& Parse(const Ch* str) {
+        return Parse<kParseDefaultFlags>(str);
+    }
+    //!@}
+
+    //!@name Handling parse errors
+    //!@{
+
+    //! Whether a parse error has occured in the last parsing.
+    bool HasParseError() const { return parseResult_.IsError(); }
+
+    //! Get the \ref ParseErrorCode of last parsing.
+    ParseErrorCode GetParseError() const { return parseResult_.Code(); }
+
+    //! Get the position of last parsing error in input, 0 otherwise.
+    size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+    //!@}
+
+    //! Get the allocator of this document.
+    Allocator& GetAllocator() { return *allocator_; }
+
+    //! Get the capacity of stack in bytes.
+    size_t GetStackCapacity() const { return stack_.GetCapacity(); }
+
+private:
+    // clear stack on any exit from ParseStream, e.g. due to exception
+    struct ClearStackOnExit {
+        explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
+        ~ClearStackOnExit() { d_.ClearStack(); }
+    private:
+        ClearStackOnExit(const ClearStackOnExit&);
+        ClearStackOnExit& operator=(const ClearStackOnExit&);
+        GenericDocument& d_;
+    };
+
+    // callers of the following private Handler functions
+    template <typename,typename,typename> friend class GenericReader; // for parsing
+    template <typename, typename> friend class GenericValue; // for deep copying
+
+    // Implementation of Handler
+    bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
+    bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
+    bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+    bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+    bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+    bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+    bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
+
+    bool String(const Ch* str, SizeType length, bool copy) { 
+        if (copy) 
+            new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
+        else
+            new (stack_.template Push<ValueType>()) ValueType(str, length);
+        return true;
+    }
+
+    bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
+    
+    bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
+
+    bool EndObject(SizeType memberCount) {
+        typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
+        stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
+        return true;
+    }
+
+    bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
+    
+    bool EndArray(SizeType elementCount) {
+        ValueType* elements = stack_.template Pop<ValueType>(elementCount);
+        stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
+        return true;
+    }
+
+private:
+    //! Prohibit copying
+    GenericDocument(const GenericDocument&);
+    //! Prohibit assignment
+    GenericDocument& operator=(const GenericDocument&);
+
+    void ClearStack() {
+        if (Allocator::kNeedFree)
+            while (stack_.GetSize() > 0)    // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
+                (stack_.template Pop<ValueType>(1))->~ValueType();
+        else
+            stack_.Clear();
+        stack_.ShrinkToFit();
+    }
+
+    void Destroy() {
+        RAPIDJSON_DELETE(ownAllocator_);
+    }
+
+    static const size_t kDefaultStackCapacity = 1024;
+    Allocator* allocator_;
+    Allocator* ownAllocator_;
+    internal::Stack<StackAllocator> stack_;
+    ParseResult parseResult_;
+};
+
+//! GenericDocument with UTF8 encoding
+typedef GenericDocument<UTF8<> > Document;
+
+// defined here due to the dependency on GenericDocument
+template <typename Encoding, typename Allocator>
+template <typename SourceAllocator>
+inline
+GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
+{
+    switch (rhs.GetType()) {
+    case kObjectType:
+    case kArrayType: { // perform deep copy via SAX Handler
+            GenericDocument<Encoding,Allocator> d(&allocator);
+            rhs.Accept(d);
+            RawAssign(*d.stack_.template Pop<GenericValue>(1));
+        }
+        break;
+    case kStringType:
+        if (rhs.flags_ == kConstStringFlag) {
+            flags_ = rhs.flags_;
+            data_  = *reinterpret_cast<const Data*>(&rhs.data_);
+        } else {
+            SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
+        }
+        break;
+    default: // kNumberType, kTrueType, kFalseType, kNullType
+        flags_ = rhs.flags_;
+        data_  = *reinterpret_cast<const Data*>(&rhs.data_);
+    }
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(_MSC_VER) || defined(__GNUC__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_DOCUMENT_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/encodedstream.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/encodedstream.h
new file mode 100644
index 0000000..ee8caa0
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/encodedstream.h
@@ -0,0 +1,290 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ENCODEDSTREAM_H_
+#define RAPIDJSON_ENCODEDSTREAM_H_
+
+#include "rapidjson.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Input byte stream wrapper with a statically bound encoding.
+/*!
+    \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+    \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
+*/
+template <typename Encoding, typename InputByteStream>
+class EncodedInputStream {
+    RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+    typedef typename Encoding::Ch Ch;
+
+    EncodedInputStream(InputByteStream& is) : is_(is) { 
+        current_ = Encoding::TakeBOM(is_);
+    }
+
+    Ch Peek() const { return current_; }
+    Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
+    size_t Tell() const { return is_.Tell(); }
+
+    // Not implemented
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); } 
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    EncodedInputStream(const EncodedInputStream&);
+    EncodedInputStream& operator=(const EncodedInputStream&);
+
+    InputByteStream& is_;
+    Ch current_;
+};
+
+//! Output byte stream wrapper with statically bound encoding.
+/*!
+    \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+    \tparam InputByteStream Type of input byte stream. For example, FileWriteStream.
+*/
+template <typename Encoding, typename OutputByteStream>
+class EncodedOutputStream {
+    RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+    typedef typename Encoding::Ch Ch;
+
+    EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { 
+        if (putBOM)
+            Encoding::PutBOM(os_);
+    }
+
+    void Put(Ch c) { Encoding::Put(os_, c);  }
+    void Flush() { os_.Flush(); }
+
+    // Not implemented
+    Ch Peek() const { RAPIDJSON_ASSERT(false); }
+    Ch Take() { RAPIDJSON_ASSERT(false);  }
+    size_t Tell() const { RAPIDJSON_ASSERT(false);  return 0; }
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    EncodedOutputStream(const EncodedOutputStream&);
+    EncodedOutputStream& operator=(const EncodedOutputStream&);
+
+    OutputByteStream& os_;
+};
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+    \tparam CharType Type of character for reading.
+    \tparam InputByteStream type of input byte stream to be wrapped.
+*/
+template <typename CharType, typename InputByteStream>
+class AutoUTFInputStream {
+    RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+    typedef CharType Ch;
+
+    //! Constructor.
+    /*!
+        \param is input stream to be wrapped.
+        \param type UTF encoding type if it is not detected from the stream.
+    */
+    AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
+        DetectType();
+        static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
+        takeFunc_ = f[type_];
+        current_ = takeFunc_(*is_);
+    }
+
+    UTFType GetType() const { return type_; }
+    bool HasBOM() const { return hasBOM_; }
+
+    Ch Peek() const { return current_; }
+    Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
+    size_t Tell() const { return is_->Tell(); }
+
+    // Not implemented
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); } 
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    AutoUTFInputStream(const AutoUTFInputStream&);
+    AutoUTFInputStream& operator=(const AutoUTFInputStream&);
+
+    // Detect encoding type with BOM or RFC 4627
+    void DetectType() {
+        // BOM (Byte Order Mark):
+        // 00 00 FE FF  UTF-32BE
+        // FF FE 00 00  UTF-32LE
+        // FE FF        UTF-16BE
+        // FF FE        UTF-16LE
+        // EF BB BF     UTF-8
+
+        const unsigned char* c = (const unsigned char *)is_->Peek4();
+        if (!c)
+            return;
+
+        unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
+        hasBOM_ = false;
+        if (bom == 0xFFFE0000)                  { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+        else if (bom == 0x0000FEFF)             { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+        else if ((bom & 0xFFFF) == 0xFFFE)      { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take();                           }
+        else if ((bom & 0xFFFF) == 0xFEFF)      { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take();                           }
+        else if ((bom & 0xFFFFFF) == 0xBFBBEF)  { type_ = kUTF8;    hasBOM_ = true; is_->Take(); is_->Take(); is_->Take();              }
+
+        // RFC 4627: Section 3
+        // "Since the first two characters of a JSON text will always be ASCII
+        // characters [RFC0020], it is possible to determine whether an octet
+        // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
+        // at the pattern of nulls in the first four octets."
+        // 00 00 00 xx  UTF-32BE
+        // 00 xx 00 xx  UTF-16BE
+        // xx 00 00 00  UTF-32LE
+        // xx 00 xx 00  UTF-16LE
+        // xx xx xx xx  UTF-8
+
+        if (!hasBOM_) {
+            unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
+            switch (pattern) {
+            case 0x08: type_ = kUTF32BE; break;
+            case 0x0A: type_ = kUTF16BE; break;
+            case 0x01: type_ = kUTF32LE; break;
+            case 0x05: type_ = kUTF16LE; break;
+            case 0x0F: type_ = kUTF8;    break;
+            default: break; // Use type defined by user.
+            }
+        }
+
+        // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
+        switch (type_) {
+        case kUTF8:
+            // Do nothing
+            break;
+        case kUTF16LE:
+        case kUTF16BE:
+            RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+            break;
+        case kUTF32LE:
+        case kUTF32BE:
+            RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+            break;
+        default:
+            RAPIDJSON_ASSERT(false);    // Invalid type
+        }
+    }
+
+    typedef Ch (*TakeFunc)(InputByteStream& is);
+    InputByteStream* is_;
+    UTFType type_;
+    Ch current_;
+    TakeFunc takeFunc_;
+    bool hasBOM_;
+};
+
+//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+    \tparam CharType Type of character for writing.
+    \tparam InputByteStream type of output byte stream to be wrapped.
+*/
+template <typename CharType, typename OutputByteStream>
+class AutoUTFOutputStream {
+    RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+    typedef CharType Ch;
+
+    //! Constructor.
+    /*!
+        \param os output stream to be wrapped.
+        \param type UTF encoding type.
+        \param putBOM Whether to write BOM at the beginning of the stream.
+    */
+    AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
+        // RUntime check whether the size of character type is sufficient. It only perform checks with assertion.
+        switch (type_) {
+        case kUTF16LE:
+        case kUTF16BE:
+            RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+            break;
+        case kUTF32LE:
+        case kUTF32BE:
+            RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+            break;
+        case kUTF8:
+            // Do nothing
+            break;
+        default:
+            RAPIDJSON_ASSERT(false);    // Invalid UTFType
+        }
+
+        static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
+        putFunc_ = f[type_];
+
+        if (putBOM)
+            PutBOM();
+    }
+
+    UTFType GetType() const { return type_; }
+
+    void Put(Ch c) { putFunc_(*os_, c); }
+    void Flush() { os_->Flush(); } 
+
+    // Not implemented
+    Ch Peek() const { RAPIDJSON_ASSERT(false); }
+    Ch Take() { RAPIDJSON_ASSERT(false); }
+    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    AutoUTFOutputStream(const AutoUTFOutputStream&);
+    AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
+
+    void PutBOM() { 
+        typedef void (*PutBOMFunc)(OutputByteStream&);
+        static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
+        f[type_](*os_);
+    }
+
+    typedef void (*PutFunc)(OutputByteStream&, Ch);
+
+    OutputByteStream* os_;
+    UTFType type_;
+    PutFunc putFunc_;
+};
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/encodings.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/encodings.h
new file mode 100644
index 0000000..71595f7
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/encodings.h
@@ -0,0 +1,630 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ENCODINGS_H_
+#define RAPIDJSON_ENCODINGS_H_
+
+#include "rapidjson.h"
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
+RAPIDJSON_DIAG_OFF(4702)  // unreachable code
+#elif defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Encoding
+
+/*! \class rapidjson::Encoding
+    \brief Concept for encoding of Unicode characters.
+
+\code
+concept Encoding {
+    typename Ch;    //! Type of character. A "character" is actually a code unit in unicode's definition.
+
+    enum { supportUnicode = 1 }; // or 0 if not supporting unicode
+
+    //! \brief Encode a Unicode codepoint to an output stream.
+    //! \param os Output stream.
+    //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint);
+
+    //! \brief Decode a Unicode codepoint from an input stream.
+    //! \param is Input stream.
+    //! \param codepoint Output of the unicode codepoint.
+    //! \return true if a valid codepoint can be decoded from the stream.
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint);
+
+    //! \brief Validate one Unicode codepoint from an encoded stream.
+    //! \param is Input stream to obtain codepoint.
+    //! \param os Output for copying one codepoint.
+    //! \return true if it is valid.
+    //! \note This function just validating and copying the codepoint without actually decode it.
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os);
+
+    // The following functions are deal with byte streams.
+
+    //! Take a character from input byte stream, skip BOM if exist.
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is);
+
+    //! Take a character from input byte stream.
+    template <typename InputByteStream>
+    static Ch Take(InputByteStream& is);
+
+    //! Put BOM to output byte stream.
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os);
+
+    //! Put a character to output byte stream.
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, Ch c);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF8
+
+//! UTF-8 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-8
+    http://tools.ietf.org/html/rfc3629
+    \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
+    \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct UTF8 {
+    typedef CharType Ch;
+
+    enum { supportUnicode = 1 };
+
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint) {
+        if (codepoint <= 0x7F) 
+            os.Put(static_cast<Ch>(codepoint & 0xFF));
+        else if (codepoint <= 0x7FF) {
+            os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
+            os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
+        }
+        else if (codepoint <= 0xFFFF) {
+            os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
+            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+        }
+        else {
+            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+            os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
+            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
+            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+        }
+    }
+
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint) {
+#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
+#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+        Ch c = is.Take();
+        if (!(c & 0x80)) {
+            *codepoint = (unsigned char)c;
+            return true;
+        }
+
+        unsigned char type = GetRange((unsigned char)c);
+        *codepoint = (0xFF >> type) & (unsigned char)c;
+        bool result = true;
+        switch (type) {
+        case 2: TAIL(); return result;
+        case 3: TAIL(); TAIL(); return result;
+        case 4: COPY(); TRANS(0x50); TAIL(); return result;
+        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+        case 6: TAIL(); TAIL(); TAIL(); return result;
+        case 10: COPY(); TRANS(0x20); TAIL(); return result;
+        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+        default: return false;
+        }
+#undef COPY
+#undef TRANS
+#undef TAIL
+    }
+
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os) {
+#define COPY() os.Put(c = is.Take())
+#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+        Ch c;
+        COPY();
+        if (!(c & 0x80))
+            return true;
+
+        bool result = true;
+        switch (GetRange((unsigned char)c)) {
+        case 2: TAIL(); return result;
+        case 3: TAIL(); TAIL(); return result;
+        case 4: COPY(); TRANS(0x50); TAIL(); return result;
+        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+        case 6: TAIL(); TAIL(); TAIL(); return result;
+        case 10: COPY(); TRANS(0x20); TAIL(); return result;
+        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+        default: return false;
+        }
+#undef COPY
+#undef TRANS
+#undef TAIL
+    }
+
+    static unsigned char GetRange(unsigned char c) {
+        // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+        // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
+        static const unsigned char type[] = {
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+            0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+            0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+            0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+            8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+            10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
+        };
+        return type[c];
+    }
+
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        Ch c = Take(is);
+        if ((unsigned char)c != 0xEFu) return c;
+        c = is.Take();
+        if ((unsigned char)c != 0xBBu) return c;
+        c = is.Take();
+        if ((unsigned char)c != 0xBFu) return c;
+        c = is.Take();
+        return c;
+    }
+
+    template <typename InputByteStream>
+    static Ch Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        return is.Take();
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, Ch c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(static_cast<typename OutputByteStream::Ch>(c));
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF16
+
+//! UTF-16 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-16
+    http://tools.ietf.org/html/rfc2781
+    \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
+    \note implements Encoding concept
+
+    \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+    For streaming, use UTF16LE and UTF16BE, which handle endianness.
+*/
+template<typename CharType = wchar_t>
+struct UTF16 {
+    typedef CharType Ch;
+    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
+
+    enum { supportUnicode = 1 };
+
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+        if (codepoint <= 0xFFFF) {
+            RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair 
+            os.Put(static_cast<typename OutputStream::Ch>(codepoint));
+        }
+        else {
+            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+            unsigned v = codepoint - 0x10000;
+            os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
+            os.Put((v & 0x3FF) | 0xDC00);
+        }
+    }
+
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+        Ch c = is.Take();
+        if (c < 0xD800 || c > 0xDFFF) {
+            *codepoint = c;
+            return true;
+        }
+        else if (c <= 0xDBFF) {
+            *codepoint = (c & 0x3FF) << 10;
+            c = is.Take();
+            *codepoint |= (c & 0x3FF);
+            *codepoint += 0x10000;
+            return c >= 0xDC00 && c <= 0xDFFF;
+        }
+        return false;
+    }
+
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+        Ch c;
+        os.Put(c = is.Take());
+        if (c < 0xD800 || c > 0xDFFF)
+            return true;
+        else if (c <= 0xDBFF) {
+            os.Put(c = is.Take());
+            return c >= 0xDC00 && c <= 0xDFFF;
+        }
+        return false;
+    }
+};
+
+//! UTF-16 little endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16LE : UTF16<CharType> {
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = Take(is);
+        return (unsigned short)c == 0xFEFFu ? Take(is) : c;
+    }
+
+    template <typename InputByteStream>
+    static CharType Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = (unsigned char)is.Take();
+        c |= (unsigned char)is.Take() << 8;
+        return c;
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0xFFu); os.Put(0xFEu);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, CharType c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(c & 0xFFu);
+        os.Put((c >> 8) & 0xFFu);
+    }
+};
+
+//! UTF-16 big endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16BE : UTF16<CharType> {
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = Take(is);
+        return (unsigned short)c == 0xFEFFu ? Take(is) : c;
+    }
+
+    template <typename InputByteStream>
+    static CharType Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = (unsigned char)is.Take() << 8;
+        c |= (unsigned char)is.Take();
+        return c;
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0xFEu); os.Put(0xFFu);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, CharType c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put((c >> 8) & 0xFFu);
+        os.Put(c & 0xFFu);
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF32
+
+//! UTF-32 encoding. 
+/*! http://en.wikipedia.org/wiki/UTF-32
+    \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
+    \note implements Encoding concept
+
+    \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+    For streaming, use UTF32LE and UTF32BE, which handle endianness.
+*/
+template<typename CharType = unsigned>
+struct UTF32 {
+    typedef CharType Ch;
+    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
+
+    enum { supportUnicode = 1 };
+
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
+        RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+        os.Put(codepoint);
+    }
+
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+        Ch c = is.Take();
+        *codepoint = c;
+        return c <= 0x10FFFF;
+    }
+
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+        Ch c;
+        os.Put(c = is.Take());
+        return c <= 0x10FFFF;
+    }
+};
+
+//! UTF-32 little endian enocoding.
+template<typename CharType = unsigned>
+struct UTF32LE : UTF32<CharType> {
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = Take(is);
+        return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
+    }
+
+    template <typename InputByteStream>
+    static CharType Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = (unsigned char)is.Take();
+        c |= (unsigned char)is.Take() << 8;
+        c |= (unsigned char)is.Take() << 16;
+        c |= (unsigned char)is.Take() << 24;
+        return c;
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, CharType c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(c & 0xFFu);
+        os.Put((c >> 8) & 0xFFu);
+        os.Put((c >> 16) & 0xFFu);
+        os.Put((c >> 24) & 0xFFu);
+    }
+};
+
+//! UTF-32 big endian encoding.
+template<typename CharType = unsigned>
+struct UTF32BE : UTF32<CharType> {
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = Take(is);
+        return (unsigned)c == 0x0000FEFFu ? Take(is) : c; 
+    }
+
+    template <typename InputByteStream>
+    static CharType Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = (unsigned char)is.Take() << 24;
+        c |= (unsigned char)is.Take() << 16;
+        c |= (unsigned char)is.Take() << 8;
+        c |= (unsigned char)is.Take();
+        return c;
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, CharType c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put((c >> 24) & 0xFFu);
+        os.Put((c >> 16) & 0xFFu);
+        os.Put((c >> 8) & 0xFFu);
+        os.Put(c & 0xFFu);
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ASCII
+
+//! ASCII encoding.
+/*! http://en.wikipedia.org/wiki/ASCII
+    \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
+    \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct ASCII {
+    typedef CharType Ch;
+
+    enum { supportUnicode = 0 };
+
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint) {
+        RAPIDJSON_ASSERT(codepoint <= 0x7F);
+        os.Put(static_cast<Ch>(codepoint & 0xFF));
+    }
+
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint) {
+        unsigned char c = static_cast<unsigned char>(is.Take());
+        *codepoint = c;
+        return c <= 0X7F;
+    }
+
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os) {
+        unsigned char c = is.Take();
+        os.Put(c);
+        return c <= 0x7F;
+    }
+
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        Ch c = Take(is);
+        return c;
+    }
+
+    template <typename InputByteStream>
+    static Ch Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        return is.Take();
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        (void)os;
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, Ch c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(static_cast<typename OutputByteStream::Ch>(c));
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// AutoUTF
+
+//! Runtime-specified UTF encoding type of a stream.
+enum UTFType {
+    kUTF8 = 0,      //!< UTF-8.
+    kUTF16LE = 1,   //!< UTF-16 little endian.
+    kUTF16BE = 2,   //!< UTF-16 big endian.
+    kUTF32LE = 3,   //!< UTF-32 little endian.
+    kUTF32BE = 4    //!< UTF-32 big endian.
+};
+
+//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
+/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
+*/
+template<typename CharType>
+struct AutoUTF {
+    typedef CharType Ch;
+
+    enum { supportUnicode = 1 };
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+    template<typename OutputStream>
+    RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
+        typedef void (*EncodeFunc)(OutputStream&, unsigned);
+        static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
+        (*f[os.GetType()])(os, codepoint);
+    }
+
+    template <typename InputStream>
+    RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
+        typedef bool (*DecodeFunc)(InputStream&, unsigned*);
+        static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
+        return (*f[is.GetType()])(is, codepoint);
+    }
+
+    template <typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+        typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
+        static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
+        return (*f[is.GetType()])(is, os);
+    }
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Transcoder
+
+//! Encoding conversion.
+template<typename SourceEncoding, typename TargetEncoding>
+struct Transcoder {
+    //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
+    template<typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+        unsigned codepoint;
+        if (!SourceEncoding::Decode(is, &codepoint))
+            return false;
+        TargetEncoding::Encode(os, codepoint);
+        return true;
+    }
+
+    //! Validate one Unicode codepoint from an encoded stream.
+    template<typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+        return Transcode(is, os);   // Since source/target encoding is different, must transcode.
+    }
+};
+
+//! Specialization of Transcoder with same source and target encoding.
+template<typename Encoding>
+struct Transcoder<Encoding, Encoding> {
+    template<typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+        os.Put(is.Take());  // Just copy one code unit. This semantic is different from primary template class.
+        return true;
+    }
+    
+    template<typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+        return Encoding::Validate(is, os);  // source/target encoding are the same
+    }
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__GNUC__) || defined(_MSV_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/error/en.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/error/en.h
new file mode 100644
index 0000000..0171183
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/error/en.h
@@ -0,0 +1,71 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ERROR_EN_H__
+#define RAPIDJSON_ERROR_EN_H__
+
+#include "error.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Maps error code of parsing into error message.
+/*!
+    \ingroup RAPIDJSON_ERRORS
+    \param parseErrorCode Error code obtained in parsing.
+    \return the error message.
+    \note User can make a copy of this function for localization.
+        Using switch-case is safer for future modification of error codes.
+*/
+inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
+    switch (parseErrorCode) {
+        case kParseErrorNone:                           return RAPIDJSON_ERROR_STRING("No error.");
+
+        case kParseErrorDocumentEmpty:                  return RAPIDJSON_ERROR_STRING("The document is empty.");
+        case kParseErrorDocumentRootNotSingular:        return RAPIDJSON_ERROR_STRING("The document root must not follow by other values.");
+    
+        case kParseErrorValueInvalid:                   return RAPIDJSON_ERROR_STRING("Invalid value.");
+    
+        case kParseErrorObjectMissName:                 return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
+        case kParseErrorObjectMissColon:                return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
+        case kParseErrorObjectMissCommaOrCurlyBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
+    
+        case kParseErrorArrayMissCommaOrSquareBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
+
+        case kParseErrorStringUnicodeEscapeInvalidHex:  return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
+        case kParseErrorStringUnicodeSurrogateInvalid:  return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
+        case kParseErrorStringEscapeInvalid:            return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
+        case kParseErrorStringMissQuotationMark:        return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
+        case kParseErrorStringInvalidEncoding:          return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
+
+        case kParseErrorNumberTooBig:                   return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
+        case kParseErrorNumberMissFraction:             return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
+        case kParseErrorNumberMissExponent:             return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
+
+        case kParseErrorTermination:                    return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
+        case kParseErrorUnspecificSyntaxError:          return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
+
+        default:
+            return RAPIDJSON_ERROR_STRING("Unknown error.");
+    }
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ERROR_EN_H__
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/error/error.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/error/error.h
new file mode 100644
index 0000000..161ef87
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/error/error.h
@@ -0,0 +1,150 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ERROR_ERROR_H__
+#define RAPIDJSON_ERROR_ERROR_H__
+
+/*! \file error.h */
+
+/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_CHARTYPE
+
+//! Character type of error messages.
+/*! \ingroup RAPIDJSON_ERRORS
+    The default character type is \c char.
+    On Windows, user can define this macro as \c TCHAR for supporting both
+    unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_CHARTYPE
+#define RAPIDJSON_ERROR_CHARTYPE char
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_STRING
+
+//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
+/*! \ingroup RAPIDJSON_ERRORS
+    By default this conversion macro does nothing.
+    On Windows, user can define this macro as \c _T(x) for supporting both
+    unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_STRING
+#define RAPIDJSON_ERROR_STRING(x) x
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseErrorCode
+
+//! Error code of parsing.
+/*! \ingroup RAPIDJSON_ERRORS
+    \see GenericReader::Parse, GenericReader::GetParseErrorCode
+*/
+enum ParseErrorCode {
+    kParseErrorNone = 0,                        //!< No error.
+
+    kParseErrorDocumentEmpty,                   //!< The document is empty.
+    kParseErrorDocumentRootNotSingular,         //!< The document root must not follow by other values.
+
+    kParseErrorValueInvalid,                    //!< Invalid value.
+
+    kParseErrorObjectMissName,                  //!< Missing a name for object member.
+    kParseErrorObjectMissColon,                 //!< Missing a colon after a name of object member.
+    kParseErrorObjectMissCommaOrCurlyBracket,   //!< Missing a comma or '}' after an object member.
+
+    kParseErrorArrayMissCommaOrSquareBracket,   //!< Missing a comma or ']' after an array element.
+
+    kParseErrorStringUnicodeEscapeInvalidHex,   //!< Incorrect hex digit after \\u escape in string.
+    kParseErrorStringUnicodeSurrogateInvalid,   //!< The surrogate pair in string is invalid.
+    kParseErrorStringEscapeInvalid,             //!< Invalid escape character in string.
+    kParseErrorStringMissQuotationMark,         //!< Missing a closing quotation mark in string.
+    kParseErrorStringInvalidEncoding,           //!< Invalid encoding in string.
+
+    kParseErrorNumberTooBig,                    //!< Number too big to be stored in double.
+    kParseErrorNumberMissFraction,              //!< Miss fraction part in number.
+    kParseErrorNumberMissExponent,              //!< Miss exponent in number.
+
+    kParseErrorTermination,                     //!< Parsing was terminated.
+    kParseErrorUnspecificSyntaxError,           //!< Unspecific syntax error.
+};
+
+//! Result of parsing (wraps ParseErrorCode)
+/*!
+    \ingroup RAPIDJSON_ERRORS
+    \code
+        Document doc;
+        ParseResult ok = doc.Parse("[42]");
+        if (!ok) {
+            fprintf(stderr, "JSON parse error: %s (%u)",
+                    GetParseError_En(ok.Code()), ok.Offset());
+            exit(EXIT_FAILURE);
+        }
+    \endcode
+    \see GenericReader::Parse, GenericDocument::Parse
+*/
+struct ParseResult {
+
+    //! Default constructor, no error.
+    ParseResult() : code_(kParseErrorNone), offset_(0) {}
+    //! Constructor to set an error.
+    ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
+
+    //! Get the error code.
+    ParseErrorCode Code() const { return code_; }
+    //! Get the error offset, if \ref IsError(), 0 otherwise.
+    size_t Offset() const { return offset_; }
+
+    //! Conversion to \c bool, returns \c true, iff !\ref IsError().
+    operator bool() const { return !IsError(); }
+    //! Whether the result is an error.
+    bool IsError() const { return code_ != kParseErrorNone; }
+
+    bool operator==(const ParseResult& that) const { return code_ == that.code_; }
+    bool operator==(ParseErrorCode code) const { return code_ == code; }
+    friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
+
+    //! Reset error code.
+    void Clear() { Set(kParseErrorNone); }
+    //! Update error code and offset.
+    void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
+
+private:
+    ParseErrorCode code_;
+    size_t offset_;
+};
+
+//! Function pointer type of GetParseError().
+/*! \ingroup RAPIDJSON_ERRORS
+
+    This is the prototype for \c GetParseError_X(), where \c X is a locale.
+    User can dynamically change locale in runtime, e.g.:
+\code
+    GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
+    const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
+\endcode
+*/
+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ERROR_ERROR_H__
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/filereadstream.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/filereadstream.h
new file mode 100644
index 0000000..5af9be5
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/filereadstream.h
@@ -0,0 +1,94 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_FILEREADSTREAM_H_
+#define RAPIDJSON_FILEREADSTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! File byte stream for input using fread().
+/*!
+    \note implements Stream concept
+*/
+class FileReadStream {
+public:
+    typedef char Ch;    //!< Character type (byte).
+
+    //! Constructor.
+    /*!
+        \param fp File pointer opened for read.
+        \param buffer user-supplied buffer.
+        \param bufferSize size of buffer in bytes. Must >=4 bytes.
+    */
+    FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 
+        RAPIDJSON_ASSERT(fp_ != 0);
+        RAPIDJSON_ASSERT(bufferSize >= 4);
+        Read();
+    }
+
+    Ch Peek() const { return *current_; }
+    Ch Take() { Ch c = *current_; Read(); return c; }
+    size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
+
+    // Not implemented
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); } 
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+    // For encoding detection only.
+    const Ch* Peek4() const {
+        return (current_ + 4 <= bufferLast_) ? current_ : 0;
+    }
+
+private:
+    void Read() {
+        if (current_ < bufferLast_)
+            ++current_;
+        else if (!eof_) {
+            count_ += readCount_;
+            readCount_ = fread(buffer_, 1, bufferSize_, fp_);
+            bufferLast_ = buffer_ + readCount_ - 1;
+            current_ = buffer_;
+
+            if (readCount_ < bufferSize_) {
+                buffer_[readCount_] = '\0';
+                ++bufferLast_;
+                eof_ = true;
+            }
+        }
+    }
+
+    std::FILE* fp_;
+    Ch *buffer_;
+    size_t bufferSize_;
+    Ch *bufferLast_;
+    Ch *current_;
+    size_t readCount_;
+    size_t count_;  //!< Number of characters read
+    bool eof_;
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/filestream.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/filestream.h
new file mode 100644
index 0000000..a370c60
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/filestream.h
@@ -0,0 +1,73 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_FILESTREAM_H_
+#define RAPIDJSON_FILESTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! (Deprecated) Wrapper of C file stream for input or output.
+/*!
+    This simple wrapper does not check the validity of the stream.
+    \note implements Stream concept
+    \note deprecated: This was only for basic testing in version 0.1, it is found that the performance is very low by using fgetc(). Use FileReadStream instead.
+*/
+class FileStream {
+public:
+    typedef char Ch;    //!< Character type. Only support char.
+
+    FileStream(std::FILE* fp) : fp_(fp), current_('\0'), count_(0) { Read(); }
+    char Peek() const { return current_; }
+    char Take() { char c = current_; Read(); return c; }
+    size_t Tell() const { return count_; }
+    void Put(char c) { fputc(c, fp_); }
+    void Flush() { fflush(fp_); }
+
+    // Not implemented
+    char* PutBegin() { return 0; }
+    size_t PutEnd(char*) { return 0; }
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    FileStream(const FileStream&);
+    FileStream& operator=(const FileStream&);
+
+    void Read() {
+        RAPIDJSON_ASSERT(fp_ != 0);
+        int c = fgetc(fp_);
+        if (c != EOF) {
+            current_ = (char)c;
+            count_++;
+        }
+        else if (current_ != '\0')
+            current_ = '\0';
+    }
+
+    std::FILE* fp_;
+    char current_;
+    size_t count_;
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/filewritestream.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/filewritestream.h
new file mode 100644
index 0000000..4352c8f
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/filewritestream.h
@@ -0,0 +1,97 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_FILEWRITESTREAM_H_
+#define RAPIDJSON_FILEWRITESTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of C file stream for input using fread().
+/*!
+    \note implements Stream concept
+*/
+class FileWriteStream {
+public:
+    typedef char Ch;    //!< Character type. Only support char.
+
+    FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 
+        RAPIDJSON_ASSERT(fp_ != 0);
+    }
+
+    void Put(char c) { 
+        if (current_ >= bufferEnd_)
+            Flush();
+
+        *current_++ = c;
+    }
+
+    void PutN(char c, size_t n) {
+        size_t avail = static_cast<size_t>(bufferEnd_ - current_);
+        while (n > avail) {
+            std::memset(current_, c, avail);
+            current_ += avail;
+            Flush();
+            n -= avail;
+            avail = static_cast<size_t>(bufferEnd_ - current_);
+        }
+
+        if (n > 0) {
+            std::memset(current_, c, n);
+            current_ += n;
+        }
+    }
+
+    void Flush() {
+        if (current_ != buffer_) {
+            fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
+            current_ = buffer_;
+        }
+    }
+
+    // Not implemented
+    char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
+    char Take() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+    char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    FileWriteStream(const FileWriteStream&);
+    FileWriteStream& operator=(const FileWriteStream&);
+
+    std::FILE* fp_;
+    char *buffer_;
+    char *bufferEnd_;
+    char *current_;
+};
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(FileWriteStream& stream, char c, size_t n) {
+    stream.PutN(c, n);
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/biginteger.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/biginteger.h
new file mode 100644
index 0000000..72acfc3
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/biginteger.h
@@ -0,0 +1,294 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_BIGINTEGER_H_
+#define RAPIDJSON_BIGINTEGER_H_
+
+#include "../rapidjson.h"
+
+#if defined(_MSC_VER) && defined(_M_AMD64)
+#include <intrin.h> // for _umul128
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class BigInteger {
+public:
+    typedef uint64_t Type;
+
+    BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
+        std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
+    }
+
+    explicit BigInteger(uint64_t u) : count_(1) {
+        digits_[0] = u;
+    }
+
+    BigInteger(const char* decimals, size_t length) : count_(1) {
+        RAPIDJSON_ASSERT(length > 0);
+        digits_[0] = 0;
+        size_t i = 0;
+        const size_t kMaxDigitPerIteration = 19;  // 2^64 = 18446744073709551616 > 10^19
+        while (length >= kMaxDigitPerIteration) {
+            AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
+            length -= kMaxDigitPerIteration;
+            i += kMaxDigitPerIteration;
+        }
+
+        if (length > 0)
+            AppendDecimal64(decimals + i, decimals + i + length);
+    }
+
+    BigInteger& operator=(uint64_t u) {
+        digits_[0] = u;            
+        count_ = 1;
+        return *this;
+    }
+
+    BigInteger& operator+=(uint64_t u) {
+        Type backup = digits_[0];
+        digits_[0] += u;
+        for (size_t i = 0; i < count_ - 1; i++) {
+            if (digits_[i] >= backup)
+                return *this; // no carry
+            backup = digits_[i + 1];
+            digits_[i + 1] += 1;
+        }
+
+        // Last carry
+        if (digits_[count_ - 1] < backup)
+            PushBack(1);
+
+        return *this;
+    }
+
+    BigInteger& operator*=(uint64_t u) {
+        if (u == 0) return *this = 0;
+        if (u == 1) return *this;
+        if (*this == 1) return *this = u;
+
+        uint64_t k = 0;
+        for (size_t i = 0; i < count_; i++) {
+            uint64_t hi;
+            digits_[i] = MulAdd64(digits_[i], u, k, &hi);
+            k = hi;
+        }
+        
+        if (k > 0)
+            PushBack(k);
+
+        return *this;
+    }
+
+    BigInteger& operator*=(uint32_t u) {
+        if (u == 0) return *this = 0;
+        if (u == 1) return *this;
+        if (*this == 1) return *this = u;
+
+        uint32_t k = 0;
+        for (size_t i = 0; i < count_; i++) {
+            const uint64_t c = digits_[i] >> 32;
+            const uint64_t d = digits_[i] & 0xFFFFFFFF;
+            const uint64_t uc = u * c;
+            const uint64_t ud = u * d;
+            const uint64_t p0 = ud + k;
+            const uint64_t p1 = uc + (p0 >> 32);
+            digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
+            k = p1 >> 32;
+        }
+        
+        if (k > 0)
+            PushBack(k);
+
+        return *this;
+    }
+
+    BigInteger& operator<<=(size_t shift) {
+        if (IsZero() || shift == 0) return *this;
+
+        size_t offset = shift / kTypeBit;
+        size_t interShift = shift % kTypeBit;
+        RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
+
+        if (interShift == 0) {
+            std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
+            count_ += offset;
+        }
+        else {
+            digits_[count_] = 0;
+            for (size_t i = count_; i > 0; i--)
+                digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
+            digits_[offset] = digits_[0] << interShift;
+            count_ += offset;
+            if (digits_[count_])
+                count_++;
+        }
+
+        std::memset(digits_, 0, offset * sizeof(Type));
+
+        return *this;
+    }
+
+    bool operator==(const BigInteger& rhs) const {
+        return count_ == rhs.count_ && memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
+    }
+
+    bool operator==(const Type rhs) const {
+        return count_ == 1 && digits_[0] == rhs;
+    }
+
+    BigInteger& MultiplyPow5(unsigned exp) {
+        static const uint32_t kPow5[12] = {
+            5,
+            5 * 5,
+            5 * 5 * 5,
+            5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+        };
+        if (exp == 0) return *this;
+        for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
+        for (; exp >= 13; exp -= 13) *this *= 1220703125u; // 5^13
+        if (exp > 0)                 *this *= kPow5[exp - 1];
+        return *this;
+    }
+
+    // Compute absolute difference of this and rhs.
+    // Return false if this < rhs
+    bool Difference(const BigInteger& rhs, BigInteger* out) const {
+        int cmp = Compare(rhs);
+        if (cmp == 0) {
+            *out = BigInteger(0);
+            return false;
+        }
+        const BigInteger *a, *b;  // Makes a > b
+        bool ret;
+        if (cmp < 0) { a = &rhs; b = this; ret = true; }
+        else         { a = this; b = &rhs; ret = false; }
+
+        Type borrow = 0;
+        for (size_t i = 0; i < a->count_; i++) {
+            Type d = a->digits_[i] - borrow;
+            if (i < b->count_)
+                d -= b->digits_[i];
+            borrow = (d > a->digits_[i]) ? 1 : 0;
+            out->digits_[i] = d;
+            if (d != 0)
+                out->count_ = i + 1;
+        }
+
+        return ret;
+    }
+
+    int Compare(const BigInteger& rhs) const {
+        if (count_ != rhs.count_)
+            return count_ < rhs.count_ ? -1 : 1;
+
+        for (size_t i = count_; i-- > 0;)
+            if (digits_[i] != rhs.digits_[i])
+                return digits_[i] < rhs.digits_[i] ? -1 : 1;
+
+        return 0;
+    }
+
+    size_t GetCount() const { return count_; }
+    Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
+    bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
+
+private:
+    void AppendDecimal64(const char* begin, const char* end) {
+        uint64_t u = ParseUint64(begin, end);
+        if (IsZero())
+            *this = u;
+        else {
+            unsigned exp = static_cast<unsigned>(end - begin);
+            (MultiplyPow5(exp) <<= exp) += u;   // *this = *this * 10^exp + u
+        }
+    }
+
+    void PushBack(Type digit) {
+        RAPIDJSON_ASSERT(count_ < kCapacity);
+        digits_[count_++] = digit;
+    }
+
+    static uint64_t ParseUint64(const char* begin, const char* end) {
+        uint64_t r = 0;
+        for (const char* p = begin; p != end; ++p) {
+            RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
+            r = r * 10 + (*p - '0');
+        }
+        return r;
+    }
+
+    // Assume a * b + k < 2^128
+    static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+        uint64_t low = _umul128(a, b, outHigh) + k;
+        if (low < k)
+            (*outHigh)++;
+        return low;
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+        unsigned __int128 p = static_cast<unsigned __int128>(a) * static_cast<unsigned __int128>(b);
+        p += k;
+        *outHigh = p >> 64;
+        return static_cast<uint64_t>(p);
+#else
+        const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
+        uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
+        x1 += (x0 >> 32); // can't give carry
+        x1 += x2;
+        if (x1 < x2)
+            x3 += (static_cast<uint64_t>(1) << 32);
+        uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
+        uint64_t hi = x3 + (x1 >> 32);
+
+        lo += k;
+        if (lo < k)
+            hi++;
+        *outHigh = hi;
+        return lo;
+#endif
+    }
+
+    static Type FullAdd(Type a, Type b, bool inCarry, bool* outCarry) {
+        Type c = a + b + (inCarry ? 1 : 0);
+        *outCarry = c < a;
+        return c;
+    }
+
+    static const size_t kBitCount = 3328;  // 64bit * 54 > 10^1000
+    static const size_t kCapacity = kBitCount / sizeof(Type);
+    static const size_t kTypeBit = sizeof(Type) * 8;
+
+    Type digits_[kCapacity];
+    size_t count_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_BIGINTEGER_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/diyfp.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/diyfp.h
new file mode 100644
index 0000000..174b9fa
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/diyfp.h
@@ -0,0 +1,268 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DIYFP_H_
+#define RAPIDJSON_DIYFP_H_
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+#if defined(_M_AMD64)
+#pragma intrinsic(_BitScanReverse64)
+#endif
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+struct DiyFp {
+    DiyFp() {}
+
+    DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
+
+    explicit DiyFp(double d) {
+        union {
+            double d;
+            uint64_t u64;
+        } u = { d };
+
+        int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize;
+        uint64_t significand = (u.u64 & kDpSignificandMask);
+        if (biased_e != 0) {
+            f = significand + kDpHiddenBit;
+            e = biased_e - kDpExponentBias;
+        } 
+        else {
+            f = significand;
+            e = kDpMinExponent + 1;
+        }
+    }
+
+    DiyFp operator-(const DiyFp& rhs) const {
+        return DiyFp(f - rhs.f, e);
+    }
+
+    DiyFp operator*(const DiyFp& rhs) const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+        uint64_t h;
+        uint64_t l = _umul128(f, rhs.f, &h);
+        if (l & (uint64_t(1) << 63)) // rounding
+            h++;
+        return DiyFp(h, e + rhs.e + 64);
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+        unsigned __int128 p = static_cast<unsigned __int128>(f) * static_cast<unsigned __int128>(rhs.f);
+        uint64_t h = p >> 64;
+        uint64_t l = static_cast<uint64_t>(p);
+        if (l & (uint64_t(1) << 63)) // rounding
+            h++;
+        return DiyFp(h, e + rhs.e + 64);
+#else
+        const uint64_t M32 = 0xFFFFFFFF;
+        const uint64_t a = f >> 32;
+        const uint64_t b = f & M32;
+        const uint64_t c = rhs.f >> 32;
+        const uint64_t d = rhs.f & M32;
+        const uint64_t ac = a * c;
+        const uint64_t bc = b * c;
+        const uint64_t ad = a * d;
+        const uint64_t bd = b * d;
+        uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
+        tmp += 1U << 31;  /// mult_round
+        return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
+#endif
+    }
+
+    DiyFp Normalize() const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+        unsigned long index;
+        _BitScanReverse64(&index, f);
+        return DiyFp(f << (63 - index), e - (63 - index));
+#elif defined(__GNUC__) && __GNUC__ >= 4
+        int s = __builtin_clzll(f);
+        return DiyFp(f << s, e - s);
+#else
+        DiyFp res = *this;
+        while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
+            res.f <<= 1;
+            res.e--;
+        }
+        return res;
+#endif
+    }
+
+    DiyFp NormalizeBoundary() const {
+        DiyFp res = *this;
+        while (!(res.f & (kDpHiddenBit << 1))) {
+            res.f <<= 1;
+            res.e--;
+        }
+        res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
+        res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
+        return res;
+    }
+
+    void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
+        DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
+        DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
+        mi.f <<= mi.e - pl.e;
+        mi.e = pl.e;
+        *plus = pl;
+        *minus = mi;
+    }
+
+    double ToDouble() const {
+        union {
+            double d;
+            uint64_t u64;
+        }u;
+        uint64_t significand = f;
+        int exponent = e;
+        while (significand > kDpHiddenBit + kDpSignificandMask) {
+            significand >>= 1;
+            exponent++;
+        }
+        while (exponent > kDpDenormalExponent && (significand & kDpHiddenBit) == 0) {
+            significand <<= 1;
+            exponent--;
+        }
+        if (exponent >= kDpMaxExponent) {
+            u.u64 = kDpExponentMask;    // Infinity
+            return u.d;
+        }
+        else if (exponent < kDpDenormalExponent)
+            return 0.0;
+        const uint64_t be = (exponent == kDpDenormalExponent && (significand & kDpHiddenBit) == 0) ? 0 : 
+            static_cast<uint64_t>(exponent + kDpExponentBias);
+        u.u64 = (significand & kDpSignificandMask) | (be << kDpSignificandSize);
+        return u.d;
+    }
+
+    static const int kDiySignificandSize = 64;
+    static const int kDpSignificandSize = 52;
+    static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
+    static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
+    static const int kDpMinExponent = -kDpExponentBias;
+    static const int kDpDenormalExponent = -kDpExponentBias + 1;
+    static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+    static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+    static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+    uint64_t f;
+    int e;
+};
+
+inline DiyFp GetCachedPowerByIndex(size_t index) {
+    // 10^-348, 10^-340, ..., 10^340
+    static const uint64_t kCachedPowers_F[] = {
+        RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
+        RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
+        RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
+        RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
+        RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
+        RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
+        RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
+        RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
+        RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
+        RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
+        RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
+        RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
+        RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
+        RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
+        RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
+        RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
+        RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
+        RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
+        RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
+        RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
+        RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
+        RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
+        RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
+        RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
+        RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
+        RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
+        RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
+        RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
+        RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
+        RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
+        RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
+        RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
+        RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
+        RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
+        RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
+        RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
+        RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
+        RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
+        RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
+        RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
+        RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
+        RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
+        RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
+        RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
+    };
+    static const int16_t kCachedPowers_E[] = {
+        -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007,  -980,
+        -954,  -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,
+        -688,  -661,  -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,
+        -422,  -396,  -369,  -343,  -316,  -289,  -263,  -236,  -210,  -183,
+        -157,  -130,  -103,   -77,   -50,   -24,     3,    30,    56,    83,
+        109,   136,   162,   189,   216,   242,   269,   295,   322,   348,
+        375,   402,   428,   455,   481,   508,   534,   561,   588,   614,
+        641,   667,   694,   720,   747,   774,   800,   827,   853,   880,
+        907,   933,   960,   986,  1013,  1039,  1066
+    };
+    return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
+}
+    
+inline DiyFp GetCachedPower(int e, int* K) {
+
+    //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
+    double dk = (-61 - e) * 0.30102999566398114 + 347;  // dk must be positive, so can do ceiling in positive
+    int k = static_cast<int>(dk);
+    if (k != dk)
+        k++;
+
+    unsigned index = static_cast<unsigned>((k >> 3) + 1);
+    *K = -(-348 + static_cast<int>(index << 3));    // decimal exponent no need lookup table
+
+    return GetCachedPowerByIndex(index);
+}
+
+inline DiyFp GetCachedPower10(int exp, int *outExp) {
+     unsigned index = (exp + 348) / 8;
+     *outExp = -348 + index * 8;
+     return GetCachedPowerByIndex(index);
+ }
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DIYFP_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/dtoa.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/dtoa.h
new file mode 100644
index 0000000..c0fa2b8
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/dtoa.h
@@ -0,0 +1,225 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DTOA_
+#define RAPIDJSON_DTOA_
+
+#include "itoa.h" // GetDigitsLut()
+#include "diyfp.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
+    while (rest < wp_w && delta - rest >= ten_kappa &&
+           (rest + ten_kappa < wp_w ||  /// closer
+            wp_w - rest > rest + ten_kappa - wp_w)) {
+        buffer[len - 1]--;
+        rest += ten_kappa;
+    }
+}
+
+inline unsigned CountDecimalDigit32(uint32_t n) {
+    // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
+    if (n < 10) return 1;
+    if (n < 100) return 2;
+    if (n < 1000) return 3;
+    if (n < 10000) return 4;
+    if (n < 100000) return 5;
+    if (n < 1000000) return 6;
+    if (n < 10000000) return 7;
+    if (n < 100000000) return 8;
+    if (n < 1000000000) return 9;
+    return 10;
+}
+
+inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
+    static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
+    const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
+    const DiyFp wp_w = Mp - W;
+    uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
+    uint64_t p2 = Mp.f & (one.f - 1);
+    int kappa = CountDecimalDigit32(p1);
+    *len = 0;
+
+    while (kappa > 0) {
+        uint32_t d;
+        switch (kappa) {
+            case 10: d = p1 / 1000000000; p1 %= 1000000000; break;
+            case  9: d = p1 /  100000000; p1 %=  100000000; break;
+            case  8: d = p1 /   10000000; p1 %=   10000000; break;
+            case  7: d = p1 /    1000000; p1 %=    1000000; break;
+            case  6: d = p1 /     100000; p1 %=     100000; break;
+            case  5: d = p1 /      10000; p1 %=      10000; break;
+            case  4: d = p1 /       1000; p1 %=       1000; break;
+            case  3: d = p1 /        100; p1 %=        100; break;
+            case  2: d = p1 /         10; p1 %=         10; break;
+            case  1: d = p1;              p1 =           0; break;
+            default: 
+#if defined(_MSC_VER)
+                __assume(0);
+#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+                __builtin_unreachable();
+#else
+                d = 0;
+#endif
+        }
+        if (d || *len)
+            buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
+        kappa--;
+        uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
+        if (tmp <= delta) {
+            *K += kappa;
+            GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
+            return;
+        }
+    }
+
+    // kappa = 0
+    for (;;) {
+        p2 *= 10;
+        delta *= 10;
+        char d = static_cast<char>(p2 >> -one.e);
+        if (d || *len)
+            buffer[(*len)++] = static_cast<char>('0' + d);
+        p2 &= one.f - 1;
+        kappa--;
+        if (p2 < delta) {
+            *K += kappa;
+            GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]);
+            return;
+        }
+    }
+}
+
+inline void Grisu2(double value, char* buffer, int* length, int* K) {
+    const DiyFp v(value);
+    DiyFp w_m, w_p;
+    v.NormalizedBoundaries(&w_m, &w_p);
+
+    const DiyFp c_mk = GetCachedPower(w_p.e, K);
+    const DiyFp W = v.Normalize() * c_mk;
+    DiyFp Wp = w_p * c_mk;
+    DiyFp Wm = w_m * c_mk;
+    Wm.f++;
+    Wp.f--;
+    DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
+}
+
+inline char* WriteExponent(int K, char* buffer) {
+    if (K < 0) {
+        *buffer++ = '-';
+        K = -K;
+    }
+
+    if (K >= 100) {
+        *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
+        K %= 100;
+        const char* d = GetDigitsLut() + K * 2;
+        *buffer++ = d[0];
+        *buffer++ = d[1];
+    }
+    else if (K >= 10) {
+        const char* d = GetDigitsLut() + K * 2;
+        *buffer++ = d[0];
+        *buffer++ = d[1];
+    }
+    else
+        *buffer++ = static_cast<char>('0' + static_cast<char>(K));
+
+    return buffer;
+}
+
+inline char* Prettify(char* buffer, int length, int k) {
+    const int kk = length + k;  // 10^(kk-1) <= v < 10^kk
+
+    if (length <= kk && kk <= 21) {
+        // 1234e7 -> 12340000000
+        for (int i = length; i < kk; i++)
+            buffer[i] = '0';
+        buffer[kk] = '.';
+        buffer[kk + 1] = '0';
+        return &buffer[kk + 2];
+    }
+    else if (0 < kk && kk <= 21) {
+        // 1234e-2 -> 12.34
+        std::memmove(&buffer[kk + 1], &buffer[kk], length - kk);
+        buffer[kk] = '.';
+        return &buffer[length + 1];
+    }
+    else if (-6 < kk && kk <= 0) {
+        // 1234e-6 -> 0.001234
+        const int offset = 2 - kk;
+        std::memmove(&buffer[offset], &buffer[0], length);
+        buffer[0] = '0';
+        buffer[1] = '.';
+        for (int i = 2; i < offset; i++)
+            buffer[i] = '0';
+        return &buffer[length + offset];
+    }
+    else if (length == 1) {
+        // 1e30
+        buffer[1] = 'e';
+        return WriteExponent(kk - 1, &buffer[2]);
+    }
+    else {
+        // 1234e30 -> 1.234e33
+        std::memmove(&buffer[2], &buffer[1], length - 1);
+        buffer[1] = '.';
+        buffer[length + 1] = 'e';
+        return WriteExponent(kk - 1, &buffer[0 + length + 2]);
+    }
+}
+
+inline char* dtoa(double value, char* buffer) {
+    if (value == 0) {
+        buffer[0] = '0';
+        buffer[1] = '.';
+        buffer[2] = '0';
+        return &buffer[3];
+    }
+    else {
+        if (value < 0) {
+            *buffer++ = '-';
+            value = -value;
+        }
+        int length, K;
+        Grisu2(value, buffer, &length, &K);
+        return Prettify(buffer, length, K);
+    }
+}
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DTOA_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/ieee754.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/ieee754.h
new file mode 100644
index 0000000..ab65cc9
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/ieee754.h
@@ -0,0 +1,90 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_IEEE754_
+#define RAPIDJSON_IEEE754_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class Double {
+public:
+    Double() {}
+    Double(double d) : d(d) {}
+    Double(uint64_t u) : u(u) {}
+
+    double Value() const { return d; }
+    uint64_t Uint64Value() const { return u; }
+
+    double NextPositiveDouble() const {
+        RAPIDJSON_ASSERT(!Sign());
+        return Double(u + 1).Value();
+    }
+
+    double PreviousPositiveDouble() const {
+        RAPIDJSON_ASSERT(!Sign());
+        if (d == 0.0)
+            return 0.0;
+        else
+            return Double(u - 1).Value();
+    }
+
+    bool Sign() const { return (u & kSignMask) != 0; }
+    uint64_t Significand() const { return u & kSignificandMask; }
+    int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; }
+
+    bool IsNan() const { return (u & kExponentMask) == kExponentMask && Significand() != 0; }
+    bool IsInf() const { return (u & kExponentMask) == kExponentMask && Significand() == 0; }
+    bool IsNormal() const { return (u & kExponentMask) != 0 || Significand() == 0; }
+
+    uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
+    int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
+    uint64_t ToBias() const { return (u & kSignMask) ? ~u + 1 : u | kSignMask; }
+
+    static unsigned EffectiveSignificandSize(int order) {
+        if (order >= -1021)
+            return 53;
+        else if (order <= -1074)
+            return 0;
+        else
+            return order + 1074;
+    }
+
+private:
+    static const int kSignificandSize = 52;
+    static const int kExponentBias = 0x3FF;
+    static const int kDenormalExponent = 1 - kExponentBias;
+    static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
+    static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+    static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+    static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+    union {
+        double d;
+        uint64_t u;
+    };
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_IEEE754_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/itoa.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/itoa.h
new file mode 100644
index 0000000..3684f07
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/itoa.h
@@ -0,0 +1,306 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ITOA_
+#define RAPIDJSON_ITOA_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline const char* GetDigitsLut() {
+    static const char cDigitsLut[200] = {
+        '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
+        '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
+        '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
+        '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
+        '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
+        '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
+        '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
+        '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
+        '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
+        '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
+    };
+    return cDigitsLut;
+}
+
+inline char* u32toa(uint32_t value, char* buffer) {
+    const char* cDigitsLut = GetDigitsLut();
+
+    if (value < 10000) {
+        const uint32_t d1 = (value / 100) << 1;
+        const uint32_t d2 = (value % 100) << 1;
+        
+        if (value >= 1000)
+            *buffer++ = cDigitsLut[d1];
+        if (value >= 100)
+            *buffer++ = cDigitsLut[d1 + 1];
+        if (value >= 10)
+            *buffer++ = cDigitsLut[d2];
+        *buffer++ = cDigitsLut[d2 + 1];
+    }
+    else if (value < 100000000) {
+        // value = bbbbcccc
+        const uint32_t b = value / 10000;
+        const uint32_t c = value % 10000;
+        
+        const uint32_t d1 = (b / 100) << 1;
+        const uint32_t d2 = (b % 100) << 1;
+        
+        const uint32_t d3 = (c / 100) << 1;
+        const uint32_t d4 = (c % 100) << 1;
+        
+        if (value >= 10000000)
+            *buffer++ = cDigitsLut[d1];
+        if (value >= 1000000)
+            *buffer++ = cDigitsLut[d1 + 1];
+        if (value >= 100000)
+            *buffer++ = cDigitsLut[d2];
+        *buffer++ = cDigitsLut[d2 + 1];
+        
+        *buffer++ = cDigitsLut[d3];
+        *buffer++ = cDigitsLut[d3 + 1];
+        *buffer++ = cDigitsLut[d4];
+        *buffer++ = cDigitsLut[d4 + 1];
+    }
+    else {
+        // value = aabbbbcccc in decimal
+        
+        const uint32_t a = value / 100000000; // 1 to 42
+        value %= 100000000;
+        
+        if (a >= 10) {
+            const unsigned i = a << 1;
+            *buffer++ = cDigitsLut[i];
+            *buffer++ = cDigitsLut[i + 1];
+        }
+        else
+            *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+
+        const uint32_t b = value / 10000; // 0 to 9999
+        const uint32_t c = value % 10000; // 0 to 9999
+        
+        const uint32_t d1 = (b / 100) << 1;
+        const uint32_t d2 = (b % 100) << 1;
+        
+        const uint32_t d3 = (c / 100) << 1;
+        const uint32_t d4 = (c % 100) << 1;
+        
+        *buffer++ = cDigitsLut[d1];
+        *buffer++ = cDigitsLut[d1 + 1];
+        *buffer++ = cDigitsLut[d2];
+        *buffer++ = cDigitsLut[d2 + 1];
+        *buffer++ = cDigitsLut[d3];
+        *buffer++ = cDigitsLut[d3 + 1];
+        *buffer++ = cDigitsLut[d4];
+        *buffer++ = cDigitsLut[d4 + 1];
+    }
+    return buffer;
+}
+
+inline char* i32toa(int32_t value, char* buffer) {
+    if (value < 0) {
+        *buffer++ = '-';
+        value = -value;
+    }
+
+    return u32toa(static_cast<uint32_t>(value), buffer);
+}
+
+inline char* u64toa(uint64_t value, char* buffer) {
+    const char* cDigitsLut = GetDigitsLut();
+    const uint64_t  kTen8 = 100000000;
+    const uint64_t  kTen9 = kTen8 * 10;
+    const uint64_t kTen10 = kTen8 * 100;
+    const uint64_t kTen11 = kTen8 * 1000;
+    const uint64_t kTen12 = kTen8 * 10000;
+    const uint64_t kTen13 = kTen8 * 100000;
+    const uint64_t kTen14 = kTen8 * 1000000;
+    const uint64_t kTen15 = kTen8 * 10000000;
+    const uint64_t kTen16 = kTen8 * kTen8;
+    
+    if (value < kTen8) {
+        uint32_t v = static_cast<uint32_t>(value);
+        if (v < 10000) {
+            const uint32_t d1 = (v / 100) << 1;
+            const uint32_t d2 = (v % 100) << 1;
+            
+            if (v >= 1000)
+                *buffer++ = cDigitsLut[d1];
+            if (v >= 100)
+                *buffer++ = cDigitsLut[d1 + 1];
+            if (v >= 10)
+                *buffer++ = cDigitsLut[d2];
+            *buffer++ = cDigitsLut[d2 + 1];
+        }
+        else {
+            // value = bbbbcccc
+            const uint32_t b = v / 10000;
+            const uint32_t c = v % 10000;
+            
+            const uint32_t d1 = (b / 100) << 1;
+            const uint32_t d2 = (b % 100) << 1;
+            
+            const uint32_t d3 = (c / 100) << 1;
+            const uint32_t d4 = (c % 100) << 1;
+            
+            if (value >= 10000000)
+                *buffer++ = cDigitsLut[d1];
+            if (value >= 1000000)
+                *buffer++ = cDigitsLut[d1 + 1];
+            if (value >= 100000)
+                *buffer++ = cDigitsLut[d2];
+            *buffer++ = cDigitsLut[d2 + 1];
+            
+            *buffer++ = cDigitsLut[d3];
+            *buffer++ = cDigitsLut[d3 + 1];
+            *buffer++ = cDigitsLut[d4];
+            *buffer++ = cDigitsLut[d4 + 1];
+        }
+    }
+    else if (value < kTen16) {
+        const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+        const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+        
+        const uint32_t b0 = v0 / 10000;
+        const uint32_t c0 = v0 % 10000;
+        
+        const uint32_t d1 = (b0 / 100) << 1;
+        const uint32_t d2 = (b0 % 100) << 1;
+        
+        const uint32_t d3 = (c0 / 100) << 1;
+        const uint32_t d4 = (c0 % 100) << 1;
+
+        const uint32_t b1 = v1 / 10000;
+        const uint32_t c1 = v1 % 10000;
+        
+        const uint32_t d5 = (b1 / 100) << 1;
+        const uint32_t d6 = (b1 % 100) << 1;
+        
+        const uint32_t d7 = (c1 / 100) << 1;
+        const uint32_t d8 = (c1 % 100) << 1;
+
+        if (value >= kTen15)
+            *buffer++ = cDigitsLut[d1];
+        if (value >= kTen14)
+            *buffer++ = cDigitsLut[d1 + 1];
+        if (value >= kTen13)
+            *buffer++ = cDigitsLut[d2];
+        if (value >= kTen12)
+            *buffer++ = cDigitsLut[d2 + 1];
+        if (value >= kTen11)
+            *buffer++ = cDigitsLut[d3];
+        if (value >= kTen10)
+            *buffer++ = cDigitsLut[d3 + 1];
+        if (value >= kTen9)
+            *buffer++ = cDigitsLut[d4];
+        if (value >= kTen8)
+            *buffer++ = cDigitsLut[d4 + 1];
+        
+        *buffer++ = cDigitsLut[d5];
+        *buffer++ = cDigitsLut[d5 + 1];
+        *buffer++ = cDigitsLut[d6];
+        *buffer++ = cDigitsLut[d6 + 1];
+        *buffer++ = cDigitsLut[d7];
+        *buffer++ = cDigitsLut[d7 + 1];
+        *buffer++ = cDigitsLut[d8];
+        *buffer++ = cDigitsLut[d8 + 1];
+    }
+    else {
+        const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
+        value %= kTen16;
+        
+        if (a < 10)
+            *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+        else if (a < 100) {
+            const uint32_t i = a << 1;
+            *buffer++ = cDigitsLut[i];
+            *buffer++ = cDigitsLut[i + 1];
+        }
+        else if (a < 1000) {
+            *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
+            
+            const uint32_t i = (a % 100) << 1;
+            *buffer++ = cDigitsLut[i];
+            *buffer++ = cDigitsLut[i + 1];
+        }
+        else {
+            const uint32_t i = (a / 100) << 1;
+            const uint32_t j = (a % 100) << 1;
+            *buffer++ = cDigitsLut[i];
+            *buffer++ = cDigitsLut[i + 1];
+            *buffer++ = cDigitsLut[j];
+            *buffer++ = cDigitsLut[j + 1];
+        }
+        
+        const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+        const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+        
+        const uint32_t b0 = v0 / 10000;
+        const uint32_t c0 = v0 % 10000;
+        
+        const uint32_t d1 = (b0 / 100) << 1;
+        const uint32_t d2 = (b0 % 100) << 1;
+        
+        const uint32_t d3 = (c0 / 100) << 1;
+        const uint32_t d4 = (c0 % 100) << 1;
+        
+        const uint32_t b1 = v1 / 10000;
+        const uint32_t c1 = v1 % 10000;
+        
+        const uint32_t d5 = (b1 / 100) << 1;
+        const uint32_t d6 = (b1 % 100) << 1;
+        
+        const uint32_t d7 = (c1 / 100) << 1;
+        const uint32_t d8 = (c1 % 100) << 1;
+        
+        *buffer++ = cDigitsLut[d1];
+        *buffer++ = cDigitsLut[d1 + 1];
+        *buffer++ = cDigitsLut[d2];
+        *buffer++ = cDigitsLut[d2 + 1];
+        *buffer++ = cDigitsLut[d3];
+        *buffer++ = cDigitsLut[d3 + 1];
+        *buffer++ = cDigitsLut[d4];
+        *buffer++ = cDigitsLut[d4 + 1];
+        *buffer++ = cDigitsLut[d5];
+        *buffer++ = cDigitsLut[d5 + 1];
+        *buffer++ = cDigitsLut[d6];
+        *buffer++ = cDigitsLut[d6 + 1];
+        *buffer++ = cDigitsLut[d7];
+        *buffer++ = cDigitsLut[d7 + 1];
+        *buffer++ = cDigitsLut[d8];
+        *buffer++ = cDigitsLut[d8 + 1];
+    }
+    
+    return buffer;
+}
+
+inline char* i64toa(int64_t value, char* buffer) {
+    if (value < 0) {
+        *buffer++ = '-';
+        value = -value;
+    }
+
+    return u64toa(static_cast<uint64_t>(value), buffer);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ITOA_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/meta.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/meta.h
new file mode 100644
index 0000000..c33f607
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/meta.h
@@ -0,0 +1,189 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_INTERNAL_META_H_
+#define RAPIDJSON_INTERNAL_META_H_
+
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#error <rapidjson.h> not yet included. Do not include this file directly.
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+#if defined(_MSC_VER)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(6334)
+#endif
+
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+#include <type_traits>
+#endif
+
+//@cond RAPIDJSON_INTERNAL
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
+template <typename T> struct Void { typedef void Type; };
+
+///////////////////////////////////////////////////////////////////////////////
+// BoolType, TrueType, FalseType
+//
+template <bool Cond> struct BoolType {
+    static const bool Value = Cond;
+    typedef BoolType Type;
+};
+typedef BoolType<true> TrueType;
+typedef BoolType<false> FalseType;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
+//
+
+template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
+template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
+template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
+template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
+
+template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
+template <> struct AndExprCond<true, true> : TrueType {};
+template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
+template <> struct OrExprCond<false, false> : FalseType {};
+
+template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
+template <typename C> struct NotExpr  : SelectIf<C,FalseType,TrueType>::Type {};
+template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
+template <typename C1, typename C2> struct OrExpr  : OrExprCond<C1::Value, C2::Value>::Type {};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// AddConst, MaybeAddConst, RemoveConst
+template <typename T> struct AddConst { typedef const T Type; };
+template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
+template <typename T> struct RemoveConst { typedef T Type; };
+template <typename T> struct RemoveConst<const T> { typedef T Type; };
+
+
+///////////////////////////////////////////////////////////////////////////////
+// IsSame, IsConst, IsMoreConst, IsPointer
+//
+template <typename T, typename U> struct IsSame : FalseType {};
+template <typename T> struct IsSame<T, T> : TrueType {};
+
+template <typename T> struct IsConst : FalseType {};
+template <typename T> struct IsConst<const T> : TrueType {};
+
+template <typename CT, typename T>
+struct IsMoreConst
+    : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
+              BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
+
+template <typename T> struct IsPointer : FalseType {};
+template <typename T> struct IsPointer<T*> : TrueType {};
+
+///////////////////////////////////////////////////////////////////////////////
+// IsBaseOf
+//
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+template <typename B, typename D> struct IsBaseOf
+    : BoolType< ::std::is_base_of<B,D>::value> {};
+
+#else // simplified version adopted from Boost
+
+template<typename B, typename D> struct IsBaseOfImpl {
+    RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
+    RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
+
+    typedef char (&Yes)[1];
+    typedef char (&No) [2];
+
+    template <typename T>
+    static Yes Check(const D*, T);
+    static No  Check(const B*, int);
+
+    struct Host {
+        operator const B*() const;
+        operator const D*();
+    };
+
+    enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
+};
+
+template <typename B, typename D> struct IsBaseOf
+    : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
+
+#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+
+//////////////////////////////////////////////////////////////////////////
+// EnableIf / DisableIf
+//
+template <bool Condition, typename T = void> struct EnableIfCond  { typedef T Type; };
+template <typename T> struct EnableIfCond<false, T> { /* empty */ };
+
+template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
+template <typename T> struct DisableIfCond<true, T> { /* empty */ };
+
+template <typename Condition, typename T = void>
+struct EnableIf : EnableIfCond<Condition::Value, T> {};
+
+template <typename Condition, typename T = void>
+struct DisableIf : DisableIfCond<Condition::Value, T> {};
+
+// SFINAE helpers
+struct SfinaeTag {};
+template <typename T> struct RemoveSfinaeTag;
+template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
+
+#define RAPIDJSON_REMOVEFPTR_(type) \
+    typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
+        < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
+
+#define RAPIDJSON_ENABLEIF(cond) \
+    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_DISABLEIF(cond) \
+    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
+    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+        <RAPIDJSON_REMOVEFPTR_(cond), \
+         RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
+    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+        <RAPIDJSON_REMOVEFPTR_(cond), \
+         RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+//@endcond
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_META_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/pow10.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/pow10.h
new file mode 100644
index 0000000..91cf647
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/pow10.h
@@ -0,0 +1,59 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_POW10_
+#define RAPIDJSON_POW10_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Computes integer powers of 10 in double (10.0^n).
+/*! This function uses lookup table for fast and accurate results.
+    \param n non-negative exponent. Must <= 308.
+    \return 10.0^n
+*/
+inline double Pow10(int n) {
+    static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
+        1e+0,  
+        1e+1,  1e+2,  1e+3,  1e+4,  1e+5,  1e+6,  1e+7,  1e+8,  1e+9,  1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 
+        1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
+        1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
+        1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
+        1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
+        1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
+        1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
+        1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
+        1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
+        1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
+        1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
+        1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
+        1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
+        1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
+        1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
+        1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
+    };
+    RAPIDJSON_ASSERT(n >= 0 && n <= 308);
+    return e[n];
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_POW10_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/stack.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/stack.h
new file mode 100644
index 0000000..62ae7aa
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/stack.h
@@ -0,0 +1,183 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_INTERNAL_STACK_H_
+#define RAPIDJSON_INTERNAL_STACK_H_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// Stack
+
+//! A type-unsafe stack for storing different types of data.
+/*! \tparam Allocator Allocator for allocating stack memory.
+*/
+template <typename Allocator>
+class Stack {
+public:
+    // Optimization note: Do not allocate memory for stack_ in constructor.
+    // Do it lazily when first Push() -> Expand() -> Resize().
+    Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
+        RAPIDJSON_ASSERT(stackCapacity > 0);
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    Stack(Stack&& rhs)
+        : allocator_(rhs.allocator_),
+          ownAllocator_(rhs.ownAllocator_),
+          stack_(rhs.stack_),
+          stackTop_(rhs.stackTop_),
+          stackEnd_(rhs.stackEnd_),
+          initialCapacity_(rhs.initialCapacity_)
+    {
+        rhs.allocator_ = 0;
+        rhs.ownAllocator_ = 0;
+        rhs.stack_ = 0;
+        rhs.stackTop_ = 0;
+        rhs.stackEnd_ = 0;
+        rhs.initialCapacity_ = 0;
+    }
+#endif
+
+    ~Stack() {
+        Destroy();
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    Stack& operator=(Stack&& rhs) {
+        if (&rhs != this)
+        {
+            Destroy();
+
+            allocator_ = rhs.allocator_;
+            ownAllocator_ = rhs.ownAllocator_;
+            stack_ = rhs.stack_;
+            stackTop_ = rhs.stackTop_;
+            stackEnd_ = rhs.stackEnd_;
+            initialCapacity_ = rhs.initialCapacity_;
+
+            rhs.allocator_ = 0;
+            rhs.ownAllocator_ = 0;
+            rhs.stack_ = 0;
+            rhs.stackTop_ = 0;
+            rhs.stackEnd_ = 0;
+            rhs.initialCapacity_ = 0;
+        }
+        return *this;
+    }
+#endif
+
+    void Clear() { stackTop_ = stack_; }
+
+    void ShrinkToFit() { 
+        if (Empty()) {
+            // If the stack is empty, completely deallocate the memory.
+            Allocator::Free(stack_);
+            stack_ = 0;
+            stackTop_ = 0;
+            stackEnd_ = 0;
+        }
+        else
+            Resize(GetSize());
+    }
+
+    // Optimization note: try to minimize the size of this function for force inline.
+    // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
+    template<typename T>
+    RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
+         // Expand the stack if needed
+        if (stackTop_ + sizeof(T) * count >= stackEnd_)
+            Expand<T>(count);
+
+        T* ret = reinterpret_cast<T*>(stackTop_);
+        stackTop_ += sizeof(T) * count;
+        return ret;
+    }
+
+    template<typename T>
+    T* Pop(size_t count) {
+        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
+        stackTop_ -= count * sizeof(T);
+        return reinterpret_cast<T*>(stackTop_);
+    }
+
+    template<typename T>
+    T* Top() { 
+        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+        return reinterpret_cast<T*>(stackTop_ - sizeof(T));
+    }
+
+    template<typename T>
+    T* Bottom() { return (T*)stack_; }
+
+    Allocator& GetAllocator() { return *allocator_; }
+    bool Empty() const { return stackTop_ == stack_; }
+    size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
+    size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
+
+private:
+    template<typename T>
+    void Expand(size_t count) {
+        // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
+        size_t newCapacity;
+        if (stack_ == 0) {
+            if (!allocator_)
+                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+            newCapacity = initialCapacity_;
+        } else {
+            newCapacity = GetCapacity();
+            newCapacity += (newCapacity + 1) / 2;
+        }
+        size_t newSize = GetSize() + sizeof(T) * count;
+        if (newCapacity < newSize)
+            newCapacity = newSize;
+
+        Resize(newCapacity);
+    }
+
+    void Resize(size_t newCapacity) {
+        const size_t size = GetSize();  // Backup the current size
+        stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity);
+        stackTop_ = stack_ + size;
+        stackEnd_ = stack_ + newCapacity;
+    }
+
+    void Destroy() {
+        Allocator::Free(stack_);
+        RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
+    }
+
+    // Prohibit copy constructor & assignment operator.
+    Stack(const Stack&);
+    Stack& operator=(const Stack&);
+
+    Allocator* allocator_;
+    Allocator* ownAllocator_;
+    char *stack_;
+    char *stackTop_;
+    char *stackEnd_;
+    size_t initialCapacity_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STACK_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/strfunc.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/strfunc.h
new file mode 100644
index 0000000..734adc3
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/strfunc.h
@@ -0,0 +1,43 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
+#define RAPIDJSON_INTERNAL_STRFUNC_H_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Custom strlen() which works on different character types.
+/*! \tparam Ch Character type (e.g. char, wchar_t, short)
+    \param s Null-terminated input string.
+    \return Number of characters in the string. 
+    \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
+*/
+template <typename Ch>
+inline SizeType StrLen(const Ch* s) {
+    const Ch* p = s;
+    while (*p) ++p;
+    return SizeType(p - s);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/strtod.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/strtod.h
new file mode 100644
index 0000000..1fc6050
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/internal/strtod.h
@@ -0,0 +1,285 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_STRTOD_
+#define RAPIDJSON_STRTOD_
+
+#include "../rapidjson.h"
+#include "ieee754.h"
+#include "biginteger.h"
+#include "diyfp.h"
+#include "pow10.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline double FastPath(double significand, int exp) {
+    if (exp < -308)
+        return 0.0;
+    else if (exp >= 0)
+        return significand * internal::Pow10(exp);
+    else
+        return significand / internal::Pow10(-exp);
+}
+
+inline double StrtodNormalPrecision(double d, int p) {
+    if (p < -308) {
+        // Prevent expSum < -308, making Pow10(p) = 0
+        d = FastPath(d, -308);
+        d = FastPath(d, p + 308);
+    }
+    else
+        d = FastPath(d, p);
+    return d;
+}
+
+template <typename T>
+inline T Min3(T a, T b, T c) {
+    T m = a;
+    if (m > b) m = b;
+    if (m > c) m = c;
+    return m;
+}
+
+inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adjustToNegative) {
+    const Double db(b);
+    const uint64_t bInt = db.IntegerSignificand();
+    const int bExp = db.IntegerExponent();
+    const int hExp = bExp - 1;
+
+    int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
+
+    // Adjust for decimal exponent
+    if (dExp >= 0) {
+        dS_Exp2 += dExp;
+        dS_Exp5 += dExp;
+    }
+    else {
+        bS_Exp2 -= dExp;
+        bS_Exp5 -= dExp;
+        hS_Exp2 -= dExp;
+        hS_Exp5 -= dExp;
+    }
+
+    // Adjust for binary exponent
+    if (bExp >= 0)
+        bS_Exp2 += bExp;
+    else {
+        dS_Exp2 -= bExp;
+        hS_Exp2 -= bExp;
+    }
+
+    // Adjust for half ulp exponent
+    if (hExp >= 0)
+        hS_Exp2 += hExp;
+    else {
+        dS_Exp2 -= hExp;
+        bS_Exp2 -= hExp;
+    }
+
+    // Remove common power of two factor from all three scaled values
+    int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
+    dS_Exp2 -= common_Exp2;
+    bS_Exp2 -= common_Exp2;
+    hS_Exp2 -= common_Exp2;
+
+    BigInteger dS = d;
+    dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2;
+
+    BigInteger bS(bInt);
+    bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2;
+
+    BigInteger hS(1);
+    hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2;
+
+    BigInteger delta(0);
+    *adjustToNegative = dS.Difference(bS, &delta);
+
+    int cmp = delta.Compare(hS);
+    // If delta is within 1/2 ULP, check for special case when significand is power of two.
+    // In this case, need to compare with 1/2h in the lower bound.
+    if (cmp < 0 && *adjustToNegative && // within and dS < bS
+        db.IsNormal() && (bInt & (bInt - 1)) == 0 && // Power of 2
+        db.Uint64Value() != RAPIDJSON_UINT64_C2(0x00100000, 0x00000000)) // minimum normal number must not do this
+    {
+        delta <<= 1;
+        return delta.Compare(hS);
+    }
+    return cmp;
+}
+
+inline bool StrtodFast(double d, int p, double* result) {
+    // Use fast path for string-to-double conversion if possible
+    // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
+    if (p > 22  && p < 22 + 16) {
+        // Fast Path Cases In Disguise
+        d *= internal::Pow10(p - 22);
+        p = 22;
+    }
+
+    if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
+        *result = FastPath(d, p);
+        return true;
+    }
+    else
+        return false;
+}
+
+// Compute an approximation and see if it is within 1/2 ULP
+inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
+    uint64_t significand = 0;
+    size_t i = 0;   // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999    
+    for (; i < length; i++) {
+        if (significand  >  RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
+            (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
+            break;
+        significand = significand * 10 + (decimals[i] - '0');
+    }
+    
+    if (i < length && decimals[i] >= '5') // Rounding
+        significand++;
+
+    size_t remaining = length - i;
+    const unsigned kUlpShift = 3;
+    const unsigned kUlp = 1 << kUlpShift;
+    int error = (remaining == 0) ? 0 : kUlp / 2;
+
+    DiyFp v(significand, 0);
+    v = v.Normalize();
+    error <<= -v.e;
+
+    const int dExp = (int)decimalPosition - (int)i + exp;
+
+    int actualExp;
+    DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
+    if (actualExp != dExp) {
+        static const DiyFp kPow10[] = {
+            DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60),  // 10^1
+            DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57),  // 10^2
+            DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54),  // 10^3
+            DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50),  // 10^4
+            DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47),  // 10^5
+            DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44),  // 10^6
+            DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40)   // 10^7
+        };
+        int adjustment = dExp - actualExp - 1;
+        RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
+        v = v * kPow10[adjustment];
+        if (length + adjustment > 19) // has more digits than decimal digits in 64-bit
+            error += kUlp / 2;
+    }
+
+    v = v * cachedPower;
+
+    error += kUlp + (error == 0 ? 0 : 1);
+
+    const int oldExp = v.e;
+    v = v.Normalize();
+    error <<= oldExp - v.e;
+
+    const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
+    unsigned precisionSize = 64 - effectiveSignificandSize;
+    if (precisionSize + kUlpShift >= 64) {
+        unsigned scaleExp = (precisionSize + kUlpShift) - 63;
+        v.f >>= scaleExp;
+        v.e += scaleExp; 
+        error = (error >> scaleExp) + 1 + kUlp;
+        precisionSize -= scaleExp;
+    }
+
+    DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
+    const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
+    const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
+    if (precisionBits >= halfWay + error)
+        rounded.f++;
+
+    *result = rounded.ToDouble();
+
+    return halfWay - error >= precisionBits || precisionBits >= halfWay + error;
+}
+
+inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+    const BigInteger dInt(decimals, length);
+    const int dExp = (int)decimalPosition - (int)length + exp;
+    Double a(approx);
+    for (int i = 0; i < 10; i++) {
+        bool adjustToNegative;
+        int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp, &adjustToNegative);
+        if (cmp < 0)
+            return a.Value();  // within half ULP
+        else if (cmp == 0) {
+            // Round towards even
+            if (a.Significand() & 1)
+                return adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble();
+            else
+                return a.Value();
+        }
+        else // adjustment
+            a = adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble();
+    }
+
+    // This should not happen, but in case there is really a bug, break the infinite-loop
+    return a.Value();
+}
+
+inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+    RAPIDJSON_ASSERT(d >= 0.0);
+    RAPIDJSON_ASSERT(length >= 1);
+
+    double result;
+    if (StrtodFast(d, p, &result))
+        return result;
+
+    // Trim leading zeros
+    while (*decimals == '0' && length > 1) {
+        length--;
+        decimals++;
+        decimalPosition--;
+    }
+
+    // Trim trailing zeros
+    while (decimals[length - 1] == '0' && length > 1) {
+        length--;
+        decimalPosition--;
+        exp++;
+    }
+
+    // Trim right-most digits
+    const int kMaxDecimalDigit = 780;
+    if ((int)length > kMaxDecimalDigit) {
+        exp += (int(length) - kMaxDecimalDigit);
+        length = kMaxDecimalDigit;
+    }
+
+    // If too small, underflow to zero
+    if (int(length) + exp < -324)
+        return 0.0;
+
+    if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
+        return result;
+
+    // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
+    return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STRTOD_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/memorybuffer.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/memorybuffer.h
new file mode 100644
index 0000000..95c68a3
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/memorybuffer.h
@@ -0,0 +1,76 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_MEMORYBUFFER_H_
+#define RAPIDJSON_MEMORYBUFFER_H_
+
+#include "rapidjson.h"
+#include "internal/stack.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output byte stream.
+/*!
+    This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream.
+
+    It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.
+
+    Differences between MemoryBuffer and StringBuffer:
+    1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 
+    2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.
+
+    \tparam Allocator type for allocating memory buffer.
+    \note implements Stream concept
+*/
+template <typename Allocator = CrtAllocator>
+struct GenericMemoryBuffer {
+    typedef char Ch; // byte
+
+    GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+    void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+    void Flush() {}
+
+    void Clear() { stack_.Clear(); }
+    void ShrinkToFit() { stack_.ShrinkToFit(); }
+    Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+    void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+    const Ch* GetBuffer() const {
+        return stack_.template Bottom<Ch>();
+    }
+
+    size_t GetSize() const { return stack_.GetSize(); }
+
+    static const size_t kDefaultCapacity = 256;
+    mutable internal::Stack<Allocator> stack_;
+};
+
+typedef GenericMemoryBuffer<> MemoryBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
+    std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/memorystream.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/memorystream.h
new file mode 100644
index 0000000..f994a12
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/memorystream.h
@@ -0,0 +1,67 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_MEMORYSTREAM_H_
+#define RAPIDJSON_MEMORYSTREAM_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory input byte stream.
+/*!
+    This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream.
+
+    It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file.
+
+    Differences between MemoryStream and StringStream:
+    1. StringStream has encoding but MemoryStream is a byte stream.
+    2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source.
+    3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
+    \note implements Stream concept
+*/
+struct MemoryStream {
+    typedef char Ch; // byte
+
+    MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
+
+    Ch Peek() const { return (src_ == end_) ? '\0' : *src_; }
+    Ch Take() { return (src_ == end_) ? '\0' : *src_++; }
+    size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
+
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+    // For encoding detection only.
+    const Ch* Peek4() const {
+        return Tell() + 4 <= size_ ? src_ : 0;
+    }
+
+    const Ch* src_;     //!< Current read position.
+    const Ch* begin_;   //!< Original head of the string.
+    const Ch* end_;     //!< End of stream.
+    size_t size_;       //!< Size of the stream.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/msinttypes/inttypes.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/msinttypes/inttypes.h
new file mode 100644
index 0000000..af713c9
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/msinttypes/inttypes.h
@@ -0,0 +1,312 @@
+// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2013 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. Neither the name of the product nor the names of its contributors may
+//      be used to endorse or promote products derived from this software
+//      without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// miloyip: VC supports inttypes.h since VC2013
+#if _MSC_VER >= 1800
+#include <inttypes.h>
+#else
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+   intmax_t quot;
+   intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8       "d"
+#define SCNi8       "i"
+#define SCNdLEAST8  "d"
+#define SCNiLEAST8  "i"
+#define SCNdFAST8   "d"
+#define SCNiFAST8   "i"
+
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64 // [
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else  // _WIN64 ][
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif  // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8       "o"
+#define SCNu8       "u"
+#define SCNx8       "x"
+#define SCNX8       "X"
+#define SCNoLEAST8  "o"
+#define SCNuLEAST8  "u"
+#define SCNxLEAST8  "x"
+#define SCNXLEAST8  "X"
+#define SCNoFAST8   "o"
+#define SCNuFAST8   "u"
+#define SCNxFAST8   "x"
+#define SCNXFAST8   "X"
+
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64 // [
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else  // _WIN64 ][
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif  // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+   imaxdiv_t result;
+
+   result.quot = numer / denom;
+   result.rem = numer % denom;
+
+   if (numer < 0 && result.rem > 0) {
+      // did division wrong; must fix up
+      ++result.quot;
+      result.rem -= denom;
+   }
+
+   return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+#endif // _MSC_VER >= 1800
+
+#endif // _MSC_INTTYPES_H_ ]
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/msinttypes/stdint.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/msinttypes/stdint.h
new file mode 100644
index 0000000..bbad95a
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/msinttypes/stdint.h
@@ -0,0 +1,296 @@
+// ISO C9x  compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2013 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. Neither the name of the product nor the names of its contributors may
+//      be used to endorse or promote products derived from this software
+//      without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.
+#if _MSC_VER >= 1600 // [
+#include <stdint.h>
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+#undef INT8_C
+#undef INT16_C
+#undef INT32_C
+#undef INT64_C
+#undef UINT8_C
+#undef UINT16_C
+#undef UINT32_C
+#undef UINT64_C
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C //   [
+#  define INTMAX_C   INT64_C
+#endif // INTMAX_C    ]
+#ifndef UINTMAX_C //  [
+#  define UINTMAX_C  UINT64_C
+#endif // UINTMAX_C   ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#else // ] _MSC_VER >= 1700 [
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+#  include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#     define _W64 __w64
+#  else
+#     define _W64
+#  endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+   typedef signed char       int8_t;
+   typedef signed short      int16_t;
+   typedef signed int        int32_t;
+   typedef unsigned char     uint8_t;
+   typedef unsigned short    uint16_t;
+   typedef unsigned int      uint32_t;
+#else
+   typedef signed __int8     int8_t;
+   typedef signed __int16    int16_t;
+   typedef signed __int32    int32_t;
+   typedef unsigned __int8   uint8_t;
+   typedef unsigned __int16  uint16_t;
+   typedef unsigned __int32  uint32_t;
+#endif
+typedef signed __int64       int64_t;
+typedef unsigned __int64     uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int16_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint16_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+   typedef signed __int64    intptr_t;
+   typedef unsigned __int64  uintptr_t;
+#else // _WIN64 ][
+   typedef _W64 signed int   intptr_t;
+   typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     ((int8_t)_I8_MIN)
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    ((int16_t)_I16_MIN)
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C //   [
+#  define INTMAX_C   INT64_C
+#endif // INTMAX_C    ]
+#ifndef UINTMAX_C //  [
+#  define UINTMAX_C  UINT64_C
+#endif // UINTMAX_C   ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#endif // _MSC_VER >= 1600 ]
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/prettywriter.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/prettywriter.h
new file mode 100644
index 0000000..ce2dac5
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/prettywriter.h
@@ -0,0 +1,205 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_PRETTYWRITER_H_
+#define RAPIDJSON_PRETTYWRITER_H_
+
+#include "writer.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Writer with indentation and spacing.
+/*!
+    \tparam OutputStream Type of ouptut os.
+    \tparam SourceEncoding Encoding of source string.
+    \tparam TargetEncoding Encoding of output stream.
+    \tparam StackAllocator Type of allocator for allocating memory of stack.
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
+class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> {
+public:
+    typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
+    typedef typename Base::Ch Ch;
+
+    //! Constructor
+    /*! \param os Output stream.
+        \param allocator User supplied allocator. If it is null, it will create a private one.
+        \param levelDepth Initial capacity of stack.
+    */
+    PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 
+        Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
+
+    //! Set custom indentation.
+    /*! \param indentChar       Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
+        \param indentCharCount  Number of indent characters for each indentation level.
+        \note The default indentation is 4 spaces.
+    */
+    PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
+        RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
+        indentChar_ = indentChar;
+        indentCharCount_ = indentCharCount;
+        return *this;
+    }
+
+    /*! @name Implementation of Handler
+        \see Handler
+    */
+    //@{
+
+    bool Null()                 { PrettyPrefix(kNullType);   return Base::WriteNull(); }
+    bool Bool(bool b)           { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
+    bool Int(int i)             { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
+    bool Uint(unsigned u)       { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
+    bool Int64(int64_t i64)     { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
+    bool Uint64(uint64_t u64)   { PrettyPrefix(kNumberType); return Base::WriteUint64(u64);  }
+    bool Double(double d)       { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
+
+    bool String(const Ch* str, SizeType length, bool copy = false) {
+        (void)copy;
+        PrettyPrefix(kStringType);
+        return Base::WriteString(str, length);
+    }
+
+    bool StartObject() {
+        PrettyPrefix(kObjectType);
+        new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
+        return Base::WriteStartObject();
+    }
+
+    bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+	
+    bool EndObject(SizeType memberCount = 0) {
+        (void)memberCount;
+        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+        RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
+        bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+        if (!empty) {
+            Base::os_->Put('\n');
+            WriteIndent();
+        }
+        if (!Base::WriteEndObject())
+            return false;
+        if (Base::level_stack_.Empty()) // end of json text
+            Base::os_->Flush();
+        return true;
+    }
+
+    bool StartArray() {
+        PrettyPrefix(kArrayType);
+        new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
+        return Base::WriteStartArray();
+    }
+
+    bool EndArray(SizeType memberCount = 0) {
+        (void)memberCount;
+        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+        RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
+        bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+        if (!empty) {
+            Base::os_->Put('\n');
+            WriteIndent();
+        }
+        if (!Base::WriteEndArray())
+            return false;
+        if (Base::level_stack_.Empty()) // end of json text
+            Base::os_->Flush();
+        return true;
+    }
+
+    //@}
+
+    /*! @name Convenience extensions */
+    //@{
+
+    //! Simpler but slower overload.
+    bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+    bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+    //@}
+protected:
+    void PrettyPrefix(Type type) {
+        (void)type;
+        if (Base::level_stack_.GetSize() != 0) { // this value is not at root
+            typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
+
+            if (level->inArray) {
+                if (level->valueCount > 0) {
+                    Base::os_->Put(','); // add comma if it is not the first element in array
+                    Base::os_->Put('\n');
+                }
+                else
+                    Base::os_->Put('\n');
+                WriteIndent();
+            }
+            else {  // in object
+                if (level->valueCount > 0) {
+                    if (level->valueCount % 2 == 0) {
+                        Base::os_->Put(',');
+                        Base::os_->Put('\n');
+                    }
+                    else {
+                        Base::os_->Put(':');
+                        Base::os_->Put(' ');
+                    }
+                }
+                else
+                    Base::os_->Put('\n');
+
+                if (level->valueCount % 2 == 0)
+                    WriteIndent();
+            }
+            if (!level->inArray && level->valueCount % 2 == 0)
+                RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
+            level->valueCount++;
+        }
+        else {
+            RAPIDJSON_ASSERT(!Base::hasRoot_);  // Should only has one and only one root.
+            Base::hasRoot_ = true;
+        }
+    }
+
+    void WriteIndent()  {
+        size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
+        PutN(*Base::os_, indentChar_, count);
+    }
+
+    Ch indentChar_;
+    unsigned indentCharCount_;
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    PrettyWriter(const PrettyWriter&);
+    PrettyWriter& operator=(const PrettyWriter&);
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/rapidjson.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/rapidjson.h
new file mode 100644
index 0000000..e9bfdba
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/rapidjson.h
@@ -0,0 +1,628 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#define RAPIDJSON_RAPIDJSON_H_
+
+// Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
+// Version 0.1
+
+/*!\file rapidjson.h
+    \brief common definitions and configuration
+
+    \see RAPIDJSON_CONFIG
+ */
+
+/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration
+    \brief Configuration macros for library features
+
+    Some RapidJSON features are configurable to adapt the library to a wide
+    variety of platforms, environments and usage scenarios.  Most of the
+    features can be configured in terms of overriden or predefined
+    preprocessor macros at compile-time.
+
+    Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
+
+    \note These macros should be given on the compiler command-line
+          (where applicable)  to avoid inconsistent values when compiling
+          different translation units of a single application.
+ */
+
+#include <cstdlib>  // malloc(), realloc(), free(), size_t
+#include <cstring>  // memset(), memcpy(), memmove(), memcmp()
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NAMESPACE_(BEGIN|END)
+/*! \def RAPIDJSON_NAMESPACE
+    \ingroup RAPIDJSON_CONFIG
+    \brief   provide custom rapidjson namespace
+
+    In order to avoid symbol clashes and/or "One Definition Rule" errors
+    between multiple inclusions of (different versions of) RapidJSON in
+    a single binary, users can customize the name of the main RapidJSON
+    namespace.
+
+    In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE
+    to a custom name (e.g. \c MyRapidJSON) is sufficient.  If multiple
+    levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref
+    RAPIDJSON_NAMESPACE_END need to be defined as well:
+
+    \code
+    // in some .cpp file
+    #define RAPIDJSON_NAMESPACE my::rapidjson
+    #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
+    #define RAPIDJSON_NAMESPACE_END   } }
+    #include "rapidjson/..."
+    \endcode
+
+    \see rapidjson
+ */
+/*! \def RAPIDJSON_NAMESPACE_BEGIN
+    \ingroup RAPIDJSON_CONFIG
+    \brief   provide custom rapidjson namespace (opening expression)
+    \see RAPIDJSON_NAMESPACE
+*/
+/*! \def RAPIDJSON_NAMESPACE_END
+    \ingroup RAPIDJSON_CONFIG
+    \brief   provide custom rapidjson namespace (closing expression)
+    \see RAPIDJSON_NAMESPACE
+*/
+#ifndef RAPIDJSON_NAMESPACE
+#define RAPIDJSON_NAMESPACE rapidjson
+#endif
+#ifndef RAPIDJSON_NAMESPACE_BEGIN
+#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
+#endif
+#ifndef RAPIDJSON_NAMESPACE_END
+#define RAPIDJSON_NAMESPACE_END }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_INT64DEFINE
+
+/*! \def RAPIDJSON_NO_INT64DEFINE
+    \ingroup RAPIDJSON_CONFIG
+    \brief Use external 64-bit integer types.
+
+    RapidJSON requires the 64-bit integer types \c int64_t and  \c uint64_t types
+    to be available at global scope.
+
+    If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to
+    prevent RapidJSON from defining its own types.
+*/
+#ifndef RAPIDJSON_NO_INT64DEFINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#ifdef _MSC_VER
+#include "msinttypes/stdint.h"
+#include "msinttypes/inttypes.h"
+#else
+// Other compilers should have this.
+#include <stdint.h>
+#include <inttypes.h>
+#endif
+//!@endcond
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_INT64DEFINE
+#endif
+#endif // RAPIDJSON_NO_INT64TYPEDEF
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_FORCEINLINE
+
+#ifndef RAPIDJSON_FORCEINLINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#ifdef _MSC_VER
+#define RAPIDJSON_FORCEINLINE __forceinline
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
+#else
+#define RAPIDJSON_FORCEINLINE
+#endif
+//!@endcond
+#endif // RAPIDJSON_FORCEINLINE
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ENDIAN
+#define RAPIDJSON_LITTLEENDIAN  0   //!< Little endian machine
+#define RAPIDJSON_BIGENDIAN     1   //!< Big endian machine
+
+//! Endianness of the machine.
+/*!
+    \def RAPIDJSON_ENDIAN
+    \ingroup RAPIDJSON_CONFIG
+
+    GCC 4.6 provided macro for detecting endianness of the target machine. But other
+    compilers may not have this. User can define RAPIDJSON_ENDIAN to either
+    \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN.
+
+    Default detection implemented with reference to
+    \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html
+    \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp
+*/
+#ifndef RAPIDJSON_ENDIAN
+// Detect with GCC 4.6's macro
+#  ifdef __BYTE_ORDER__
+#    if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+#    elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+#    else
+#      error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+#    endif // __BYTE_ORDER__
+// Detect with GLIBC's endian.h
+#  elif defined(__GLIBC__)
+#    include <endian.h>
+#    if (__BYTE_ORDER == __LITTLE_ENDIAN)
+#      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+#    elif (__BYTE_ORDER == __BIG_ENDIAN)
+#      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+#    else
+#      error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+#   endif // __GLIBC__
+// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
+#  elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
+#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+#  elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
+#    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+// Detect with architecture macros
+#  elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
+#    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+#  elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
+#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+#  elif defined(RAPIDJSON_DOXYGEN_RUNNING)
+#    define RAPIDJSON_ENDIAN
+#  else
+#    error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.   
+#  endif
+#endif // RAPIDJSON_ENDIAN
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_64BIT
+
+//! Whether using 64-bit architecture
+#ifndef RAPIDJSON_64BIT
+#if defined(__LP64__) || defined(_WIN64)
+#define RAPIDJSON_64BIT 1
+#else
+#define RAPIDJSON_64BIT 0
+#endif
+#endif // RAPIDJSON_64BIT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ALIGN
+
+//! Data alignment of the machine.
+/*! \ingroup RAPIDJSON_CONFIG
+    \param x pointer to align
+
+    Some machines require strict data alignment. Currently the default uses 4 bytes
+    alignment. User can customize by defining the RAPIDJSON_ALIGN function macro.,
+*/
+#ifndef RAPIDJSON_ALIGN
+#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_UINT64_C2
+
+//! Construct a 64-bit literal by a pair of 32-bit integer.
+/*!
+    64-bit literal with or without ULL suffix is prone to compiler warnings.
+    UINT64_C() is C macro which cause compilation problems.
+    Use this macro to define 64-bit constants by a pair of 32-bit integer.
+*/
+#ifndef RAPIDJSON_UINT64_C2
+#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
+
+/*! \def RAPIDJSON_SIMD
+    \ingroup RAPIDJSON_CONFIG
+    \brief Enable SSE2/SSE4.2 optimization.
+
+    RapidJSON supports optimized implementations for some parsing operations
+    based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
+    processors.
+
+    To enable these optimizations, two different symbols can be defined;
+    \code
+    // Enable SSE2 optimization.
+    #define RAPIDJSON_SSE2
+
+    // Enable SSE4.2 optimization.
+    #define RAPIDJSON_SSE42
+    \endcode
+
+    \c RAPIDJSON_SSE42 takes precedence, if both are defined.
+
+    If any of these symbols is defined, RapidJSON defines the macro
+    \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
+*/
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
+    || defined(RAPIDJSON_DOXYGEN_RUNNING)
+#define RAPIDJSON_SIMD
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_SIZETYPEDEFINE
+
+#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
+/*! \def RAPIDJSON_NO_SIZETYPEDEFINE
+    \ingroup RAPIDJSON_CONFIG
+    \brief User-provided \c SizeType definition.
+
+    In order to avoid using 32-bit size types for indexing strings and arrays,
+    define this preprocessor symbol and provide the type rapidjson::SizeType
+    before including RapidJSON:
+    \code
+    #define RAPIDJSON_NO_SIZETYPEDEFINE
+    namespace rapidjson { typedef ::std::size_t SizeType; }
+    #include "rapidjson/..."
+    \endcode
+
+    \see rapidjson::SizeType
+*/
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_SIZETYPEDEFINE
+#endif
+RAPIDJSON_NAMESPACE_BEGIN
+//! Size type (for string lengths, array sizes, etc.)
+/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
+    instead of using \c size_t. Users may override the SizeType by defining
+    \ref RAPIDJSON_NO_SIZETYPEDEFINE.
+*/
+typedef unsigned SizeType;
+RAPIDJSON_NAMESPACE_END
+#endif
+
+// always import std::size_t to rapidjson namespace
+RAPIDJSON_NAMESPACE_BEGIN
+using std::size_t;
+RAPIDJSON_NAMESPACE_END
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ASSERT
+
+//! Assertion.
+/*! \ingroup RAPIDJSON_CONFIG
+    By default, rapidjson uses C \c assert() for internal assertions.
+    User can override it by defining RAPIDJSON_ASSERT(x) macro.
+
+    \note Parsing errors are handled and can be customized by the
+          \ref RAPIDJSON_ERRORS APIs.
+*/
+#ifndef RAPIDJSON_ASSERT
+#include <cassert>
+#define RAPIDJSON_ASSERT(x) assert(x)
+#endif // RAPIDJSON_ASSERT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_STATIC_ASSERT
+
+// Adopt from boost
+#ifndef RAPIDJSON_STATIC_ASSERT
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+RAPIDJSON_NAMESPACE_BEGIN
+template <bool x> struct STATIC_ASSERTION_FAILURE;
+template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
+template<int x> struct StaticAssertTest {};
+RAPIDJSON_NAMESPACE_END
+
+#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
+#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
+#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
+
+#if defined(__GNUC__)
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
+#else
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE 
+#endif
+//!@endcond
+
+/*! \def RAPIDJSON_STATIC_ASSERT
+    \brief (Internal) macro to check for conditions at compile-time
+    \param x compile-time condition
+    \hideinitializer
+ */
+#define RAPIDJSON_STATIC_ASSERT(x) \
+    typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
+      sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
+    RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+
+#define RAPIDJSON_MULTILINEMACRO_BEGIN do {  
+#define RAPIDJSON_MULTILINEMACRO_END \
+} while((void)0, 0)
+
+// adopted from Boost
+#define RAPIDJSON_VERSION_CODE(x,y,z) \
+  (((x)*100000) + ((y)*100) + (z))
+
+// token stringification
+#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
+#define RAPIDJSON_DO_STRINGIFY(x) #x
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
+
+#if defined(__GNUC__)
+#define RAPIDJSON_GNUC \
+    RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
+#endif
+
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
+
+#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
+#define RAPIDJSON_DIAG_OFF(x) \
+    RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
+
+// push/pop support in Clang and GCC>=4.6
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop)
+#else // GCC >= 4.2, < 4.6
+#define RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+#endif
+
+#elif defined(_MSC_VER)
+
+// pragma (MSVC specific)
+#define RAPIDJSON_PRAGMA(x) __pragma(x)
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
+
+#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop)
+
+#else
+
+#define RAPIDJSON_DIAG_OFF(x) /* ignored */
+#define RAPIDJSON_DIAG_PUSH   /* ignored */
+#define RAPIDJSON_DIAG_POP    /* ignored */
+
+#endif // RAPIDJSON_DIAG_*
+
+///////////////////////////////////////////////////////////////////////////////
+// C++11 features
+
+#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
+      (defined(_MSC_VER) && _MSC_VER >= 1600)
+
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#else
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
+#endif
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
+//    (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
+#else
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
+#endif
+#endif
+#if RAPIDJSON_HAS_CXX11_NOEXCEPT
+#define RAPIDJSON_NOEXCEPT noexcept
+#else
+#define RAPIDJSON_NOEXCEPT /* noexcept */
+#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
+
+// no automatic detection, yet
+#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
+#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
+#endif
+
+//!@endcond
+
+///////////////////////////////////////////////////////////////////////////////
+// new/delete
+
+#ifndef RAPIDJSON_NEW
+///! customization point for global \c new
+#define RAPIDJSON_NEW(x) new x
+#endif
+#ifndef RAPIDJSON_DELETE
+///! customization point for global \c delete
+#define RAPIDJSON_DELETE(x) delete x
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocators and Encodings
+
+#include "allocators.h"
+#include "encodings.h"
+
+/*! \namespace rapidjson
+    \brief main RapidJSON namespace
+    \see RAPIDJSON_NAMESPACE
+*/
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+//  Stream
+
+/*! \class rapidjson::Stream
+    \brief Concept for reading and writing characters.
+
+    For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().
+
+    For write-only stream, only need to implement Put() and Flush().
+
+\code
+concept Stream {
+    typename Ch;    //!< Character type of the stream.
+
+    //! Read the current character from stream without moving the read cursor.
+    Ch Peek() const;
+
+    //! Read the current character from stream and moving the read cursor to next character.
+    Ch Take();
+
+    //! Get the current read cursor.
+    //! \return Number of characters read from start.
+    size_t Tell();
+
+    //! Begin writing operation at the current read pointer.
+    //! \return The begin writer pointer.
+    Ch* PutBegin();
+
+    //! Write a character.
+    void Put(Ch c);
+
+    //! Flush the buffer.
+    void Flush();
+
+    //! End the writing operation.
+    //! \param begin The begin write pointer returned by PutBegin().
+    //! \return Number of characters written.
+    size_t PutEnd(Ch* begin);
+}
+\endcode
+*/
+
+//! Provides additional information for stream.
+/*!
+    By using traits pattern, this type provides a default configuration for stream.
+    For custom stream, this type can be specialized for other configuration.
+    See TEST(Reader, CustomStringStream) in readertest.cpp for example.
+*/
+template<typename Stream>
+struct StreamTraits {
+    //! Whether to make local copy of stream for optimization during parsing.
+    /*!
+        By default, for safety, streams do not use local copy optimization.
+        Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
+    */
+    enum { copyOptimization = 0 };
+};
+
+//! Put N copies of a character to a stream.
+template<typename Stream, typename Ch>
+inline void PutN(Stream& stream, Ch c, size_t n) {
+    for (size_t i = 0; i < n; i++)
+        stream.Put(c);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StringStream
+
+//! Read-only string stream.
+/*! \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericStringStream {
+    typedef typename Encoding::Ch Ch;
+
+    GenericStringStream(const Ch *src) : src_(src), head_(src) {}
+
+    Ch Peek() const { return *src_; }
+    Ch Take() { return *src_++; }
+    size_t Tell() const { return static_cast<size_t>(src_ - head_); }
+
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+    const Ch* src_;     //!< Current read position.
+    const Ch* head_;    //!< Original head of the string.
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericStringStream<Encoding> > {
+    enum { copyOptimization = 1 };
+};
+
+//! String stream with UTF8 encoding.
+typedef GenericStringStream<UTF8<> > StringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// InsituStringStream
+
+//! A read-write string stream.
+/*! This string stream is particularly designed for in-situ parsing.
+    \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericInsituStringStream {
+    typedef typename Encoding::Ch Ch;
+
+    GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
+
+    // Read
+    Ch Peek() { return *src_; }
+    Ch Take() { return *src_++; }
+    size_t Tell() { return static_cast<size_t>(src_ - head_); }
+
+    // Write
+    void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
+
+    Ch* PutBegin() { return dst_ = src_; }
+    size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
+    void Flush() {}
+
+    Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
+    void Pop(size_t count) { dst_ -= count; }
+
+    Ch* src_;
+    Ch* dst_;
+    Ch* head_;
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericInsituStringStream<Encoding> > {
+    enum { copyOptimization = 1 };
+};
+
+//! Insitu string stream with UTF8 encoding.
+typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// Type
+
+//! Type of JSON value
+enum Type {
+    kNullType = 0,      //!< null
+    kFalseType = 1,     //!< false
+    kTrueType = 2,      //!< true
+    kObjectType = 3,    //!< object
+    kArrayType = 4,     //!< array 
+    kStringType = 5,    //!< string
+    kNumberType = 6     //!< number
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/reader.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/reader.h
new file mode 100644
index 0000000..08425eb
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/reader.h
@@ -0,0 +1,1444 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_READER_H_
+#define RAPIDJSON_READER_H_
+
+/*! \file reader.h */
+
+#include "rapidjson.h"
+#include "encodings.h"
+#include "internal/meta.h"
+#include "internal/stack.h"
+#include "internal/strtod.h"
+
+#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
+#include <intrin.h>
+#pragma intrinsic(_BitScanForward)
+#endif
+#ifdef RAPIDJSON_SSE42
+#include <nmmintrin.h>
+#elif defined(RAPIDJSON_SSE2)
+#include <emmintrin.h>
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127)  // conditional expression is constant
+RAPIDJSON_DIAG_OFF(4702)  // unreachable code
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define RAPIDJSON_NOTHING /* deliberately empty */
+#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
+    RAPIDJSON_MULTILINEMACRO_BEGIN \
+    if (HasParseError()) { return value; } \
+    RAPIDJSON_MULTILINEMACRO_END
+#endif
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
+    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
+//!@endcond
+
+/*! \def RAPIDJSON_PARSE_ERROR_NORETURN
+    \ingroup RAPIDJSON_ERRORS
+    \brief Macro to indicate a parse error.
+    \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+    \param offset  position of the error in JSON input (\c size_t)
+
+    This macros can be used as a customization point for the internal
+    error handling mechanism of RapidJSON.
+
+    A common usage model is to throw an exception instead of requiring the
+    caller to explicitly check the \ref rapidjson::GenericReader::Parse's
+    return value:
+
+    \code
+    #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
+       throw ParseException(parseErrorCode, #parseErrorCode, offset)
+
+    #include <stdexcept>               // std::runtime_error
+    #include "rapidjson/error/error.h" // rapidjson::ParseResult
+
+    struct ParseException : std::runtime_error, rapidjson::ParseResult {
+      ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
+        : std::runtime_error(msg), ParseResult(code, offset) {}
+    };
+
+    #include "rapidjson/reader.h"
+    \endcode
+
+    \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
+ */
+#ifndef RAPIDJSON_PARSE_ERROR_NORETURN
+#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
+    RAPIDJSON_MULTILINEMACRO_BEGIN \
+    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
+    SetParseError(parseErrorCode, offset); \
+    RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+/*! \def RAPIDJSON_PARSE_ERROR
+    \ingroup RAPIDJSON_ERRORS
+    \brief (Internal) macro to indicate and handle a parse error.
+    \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+    \param offset  position of the error in JSON input (\c size_t)
+
+    Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
+
+    \see RAPIDJSON_PARSE_ERROR_NORETURN
+    \hideinitializer
+ */
+#ifndef RAPIDJSON_PARSE_ERROR
+#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
+    RAPIDJSON_MULTILINEMACRO_BEGIN \
+    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
+    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
+    RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+#include "error/error.h" // ParseErrorCode, ParseResult
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseFlag
+
+/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS 
+    \ingroup RAPIDJSON_CONFIG
+    \brief User-defined kParseDefaultFlags definition.
+
+    User can define this as any \c ParseFlag combinations.
+*/
+#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
+#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
+#endif
+
+//! Combination of parseFlags
+/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
+ */
+enum ParseFlag {
+    kParseNoFlags = 0,              //!< No flags are set.
+    kParseInsituFlag = 1,           //!< In-situ(destructive) parsing.
+    kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
+    kParseIterativeFlag = 4,        //!< Iterative(constant complexity in terms of function call stack size) parsing.
+    kParseStopWhenDoneFlag = 8,     //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
+    kParseFullPrecisionFlag = 16,   //!< Parse number in full precision (but slower).
+    kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS  //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Handler
+
+/*! \class rapidjson::Handler
+    \brief Concept for receiving events from GenericReader upon parsing.
+    The functions return true if no error occurs. If they return false, 
+    the event publisher should terminate the process.
+\code
+concept Handler {
+    typename Ch;
+
+    bool Null();
+    bool Bool(bool b);
+    bool Int(int i);
+    bool Uint(unsigned i);
+    bool Int64(int64_t i);
+    bool Uint64(uint64_t i);
+    bool Double(double d);
+    bool String(const Ch* str, SizeType length, bool copy);
+    bool StartObject();
+    bool Key(const Ch* str, SizeType length, bool copy);
+    bool EndObject(SizeType memberCount);
+    bool StartArray();
+    bool EndArray(SizeType elementCount);
+};
+\endcode
+*/
+///////////////////////////////////////////////////////////////////////////////
+// BaseReaderHandler
+
+//! Default implementation of Handler.
+/*! This can be used as base class of any reader handler.
+    \note implements Handler concept
+*/
+template<typename Encoding = UTF8<>, typename Derived = void>
+struct BaseReaderHandler {
+    typedef typename Encoding::Ch Ch;
+
+    typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
+
+    bool Default() { return true; }
+    bool Null() { return static_cast<Override&>(*this).Default(); }
+    bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
+    bool Int(int) { return static_cast<Override&>(*this).Default(); }
+    bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
+    bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
+    bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
+    bool Double(double) { return static_cast<Override&>(*this).Default(); }
+    bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
+    bool StartObject() { return static_cast<Override&>(*this).Default(); }
+    bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
+    bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
+    bool StartArray() { return static_cast<Override&>(*this).Default(); }
+    bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamLocalCopy
+
+namespace internal {
+
+template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
+class StreamLocalCopy;
+
+//! Do copy optimization.
+template<typename Stream>
+class StreamLocalCopy<Stream, 1> {
+public:
+    StreamLocalCopy(Stream& original) : s(original), original_(original) {}
+    ~StreamLocalCopy() { original_ = s; }
+
+    Stream s;
+
+private:
+    StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+
+    Stream& original_;
+};
+
+//! Keep reference.
+template<typename Stream>
+class StreamLocalCopy<Stream, 0> {
+public:
+    StreamLocalCopy(Stream& original) : s(original) {}
+
+    Stream& s;
+
+private:
+    StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// SkipWhitespace
+
+//! Skip the JSON white spaces in a stream.
+/*! \param is A input stream for skipping white spaces.
+    \note This function has SSE2/SSE4.2 specialization.
+*/
+template<typename InputStream>
+void SkipWhitespace(InputStream& is) {
+    internal::StreamLocalCopy<InputStream> copy(is);
+    InputStream& s(copy.s);
+
+    while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
+        s.Take();
+}
+
+#ifdef RAPIDJSON_SSE42
+//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+	// Fast return for single non-whitespace
+	if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+		++p;
+	else
+		return p;
+
+	// 16-byte align to the next boundary
+	const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+	while (p != nextAligned)
+		if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+			++p;
+		else
+			return p;
+
+    // The rest of string using SIMD
+	static const char whitespace[16] = " \n\r\t";
+	const __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]);
+
+    for (;; p += 16) {
+        const __m128i s = _mm_load_si128((const __m128i *)p);
+        const unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
+        if (r != 0) {   // some of characters is non-whitespace
+#ifdef _MSC_VER         // Find the index of first non-whitespace
+            unsigned long offset;
+            _BitScanForward(&offset, r);
+            return p + offset;
+#else
+            return p + __builtin_ffs(r) - 1;
+#endif
+        }
+    }
+}
+
+#elif defined(RAPIDJSON_SSE2)
+
+//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+	// Fast return for single non-whitespace
+	if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+		++p;
+	else
+		return p;
+
+    // 16-byte align to the next boundary
+	const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+	while (p != nextAligned)
+		if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+			++p;
+		else
+			return p;
+
+    // The rest of string
+	static const char whitespaces[4][17] = {
+		"                ",
+		"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
+		"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
+		"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
+
+		const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
+		const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
+		const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
+		const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
+
+    for (;; p += 16) {
+        const __m128i s = _mm_load_si128((const __m128i *)p);
+        __m128i x = _mm_cmpeq_epi8(s, w0);
+        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
+        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
+        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
+        unsigned short r = (unsigned short)~_mm_movemask_epi8(x);
+        if (r != 0) {   // some of characters may be non-whitespace
+#ifdef _MSC_VER         // Find the index of first non-whitespace
+            unsigned long offset;
+            _BitScanForward(&offset, r);
+            return p + offset;
+#else
+            return p + __builtin_ffs(r) - 1;
+#endif
+        }
+    }
+}
+
+#endif // RAPIDJSON_SSE2
+
+#ifdef RAPIDJSON_SIMD
+//! Template function specialization for InsituStringStream
+template<> inline void SkipWhitespace(InsituStringStream& is) { 
+    is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
+}
+
+//! Template function specialization for StringStream
+template<> inline void SkipWhitespace(StringStream& is) {
+    is.src_ = SkipWhitespace_SIMD(is.src_);
+}
+#endif // RAPIDJSON_SIMD
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericReader
+
+//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
+/*! GenericReader parses JSON text from a stream, and send events synchronously to an 
+    object implementing Handler concept.
+
+    It needs to allocate a stack for storing a single decoded string during 
+    non-destructive parsing.
+
+    For in-situ parsing, the decoded string is directly written to the source 
+    text string, no temporary buffer is required.
+
+    A GenericReader object can be reused for parsing multiple JSON text.
+    
+    \tparam SourceEncoding Encoding of the input stream.
+    \tparam TargetEncoding Encoding of the parse output.
+    \tparam StackAllocator Allocator type for stack.
+*/
+template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
+class GenericReader {
+public:
+    typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
+
+    //! Constructor.
+    /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
+        \param stackCapacity stack capacity in bytes for storing a single decoded string.  (Only use for non-destructive parsing)
+    */
+    GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
+
+    //! Parse JSON text.
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \tparam InputStream Type of input stream, implementing Stream concept.
+        \tparam Handler Type of handler, implementing Handler concept.
+        \param is Input stream to be parsed.
+        \param handler The handler to receive events.
+        \return Whether the parsing is successful.
+    */
+    template <unsigned parseFlags, typename InputStream, typename Handler>
+    ParseResult Parse(InputStream& is, Handler& handler) {
+        if (parseFlags & kParseIterativeFlag)
+            return IterativeParse<parseFlags>(is, handler);
+
+        parseResult_.Clear();
+
+        ClearStackOnExit scope(*this);
+
+        SkipWhitespace(is);
+
+        if (is.Peek() == '\0') {
+            RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+        }
+        else {
+            ParseValue<parseFlags>(is, handler);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+            if (!(parseFlags & kParseStopWhenDoneFlag)) {
+                SkipWhitespace(is);
+
+                if (is.Peek() != '\0') {
+                    RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
+                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+                }
+            }
+        }
+
+        return parseResult_;
+    }
+
+    //! Parse JSON text (with \ref kParseDefaultFlags)
+    /*! \tparam InputStream Type of input stream, implementing Stream concept
+        \tparam Handler Type of handler, implementing Handler concept.
+        \param is Input stream to be parsed.
+        \param handler The handler to receive events.
+        \return Whether the parsing is successful.
+    */
+    template <typename InputStream, typename Handler>
+    ParseResult Parse(InputStream& is, Handler& handler) {
+        return Parse<kParseDefaultFlags>(is, handler);
+    }
+
+    //! Whether a parse error has occured in the last parsing.
+    bool HasParseError() const { return parseResult_.IsError(); }
+    
+    //! Get the \ref ParseErrorCode of last parsing.
+    ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
+
+    //! Get the position of last parsing error in input, 0 otherwise.
+    size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+protected:
+    void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    GenericReader(const GenericReader&);
+    GenericReader& operator=(const GenericReader&);
+
+    void ClearStack() { stack_.Clear(); }
+
+    // clear stack on any exit from ParseStream, e.g. due to exception
+    struct ClearStackOnExit {
+        explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
+        ~ClearStackOnExit() { r_.ClearStack(); }
+    private:
+        GenericReader& r_;
+        ClearStackOnExit(const ClearStackOnExit&);
+        ClearStackOnExit& operator=(const ClearStackOnExit&);
+    };
+
+    // Parse object: { string : value, ... }
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseObject(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == '{');
+        is.Take();  // Skip '{'
+        
+        if (!handler.StartObject())
+            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+        SkipWhitespace(is);
+
+        if (is.Peek() == '}') {
+            is.Take();
+            if (!handler.EndObject(0))  // empty object
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+            return;
+        }
+
+        for (SizeType memberCount = 0;;) {
+            if (is.Peek() != '"')
+                RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
+
+            ParseString<parseFlags>(is, handler, true);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+            SkipWhitespace(is);
+
+            if (is.Take() != ':')
+                RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
+
+            SkipWhitespace(is);
+
+            ParseValue<parseFlags>(is, handler);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+            SkipWhitespace(is);
+
+            ++memberCount;
+
+            switch (is.Take()) {
+                case ',': SkipWhitespace(is); break;
+                case '}': 
+                    if (!handler.EndObject(memberCount))
+                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+                    return;
+                default:  RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
+            }
+        }
+    }
+
+    // Parse array: [ value, ... ]
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseArray(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == '[');
+        is.Take();  // Skip '['
+        
+        if (!handler.StartArray())
+            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+        
+        SkipWhitespace(is);
+
+        if (is.Peek() == ']') {
+            is.Take();
+            if (!handler.EndArray(0)) // empty array
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+            return;
+        }
+
+        for (SizeType elementCount = 0;;) {
+            ParseValue<parseFlags>(is, handler);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+            ++elementCount;
+            SkipWhitespace(is);
+
+            switch (is.Take()) {
+                case ',': SkipWhitespace(is); break;
+                case ']': 
+                    if (!handler.EndArray(elementCount))
+                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+                    return;
+                default:  RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+            }
+        }
+    }
+
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseNull(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == 'n');
+        is.Take();
+
+        if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') {
+            if (!handler.Null())
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+        }
+        else
+            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+    }
+
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseTrue(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == 't');
+        is.Take();
+
+        if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') {
+            if (!handler.Bool(true))
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+        }
+        else
+            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+    }
+
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseFalse(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == 'f');
+        is.Take();
+
+        if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') {
+            if (!handler.Bool(false))
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+        }
+        else
+            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+    }
+
+    // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
+    template<typename InputStream>
+    unsigned ParseHex4(InputStream& is) {
+        unsigned codepoint = 0;
+        for (int i = 0; i < 4; i++) {
+            Ch c = is.Take();
+            codepoint <<= 4;
+            codepoint += static_cast<unsigned>(c);
+            if (c >= '0' && c <= '9')
+                codepoint -= '0';
+            else if (c >= 'A' && c <= 'F')
+                codepoint -= 'A' - 10;
+            else if (c >= 'a' && c <= 'f')
+                codepoint -= 'a' - 10;
+            else {
+                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1);
+                RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
+            }
+        }
+        return codepoint;
+    }
+
+    template <typename CharType>
+    class StackStream {
+    public:
+        typedef CharType Ch;
+
+        StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
+        RAPIDJSON_FORCEINLINE void Put(Ch c) {
+            *stack_.template Push<Ch>() = c;
+            ++length_;
+        }
+        size_t Length() const { return length_; }
+        Ch* Pop() {
+            return stack_.template Pop<Ch>(length_);
+        }
+
+    private:
+        StackStream(const StackStream&);
+        StackStream& operator=(const StackStream&);
+
+        internal::Stack<StackAllocator>& stack_;
+        SizeType length_;
+    };
+
+    // Parse string and generate String event. Different code paths for kParseInsituFlag.
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
+        internal::StreamLocalCopy<InputStream> copy(is);
+        InputStream& s(copy.s);
+
+        bool success = false;
+        if (parseFlags & kParseInsituFlag) {
+            typename InputStream::Ch *head = s.PutBegin();
+            ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+            size_t length = s.PutEnd(head) - 1;
+            RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+            const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head;
+            success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
+        }
+        else {
+            StackStream<typename TargetEncoding::Ch> stackStream(stack_);
+            ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+            SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
+            const typename TargetEncoding::Ch* const str = stackStream.Pop();
+            success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
+        }
+        if (!success)
+            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+    }
+
+    // Parse string to an output is
+    // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
+    template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+        static const char escape[256] = {
+            Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', 
+            Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, 
+            0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, 
+            0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
+        };
+#undef Z16
+//!@endcond
+
+        RAPIDJSON_ASSERT(is.Peek() == '\"');
+        is.Take();  // Skip '\"'
+
+        for (;;) {
+            Ch c = is.Peek();
+            if (c == '\\') {    // Escape
+                is.Take();
+                Ch e = is.Take();
+                if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) {
+                    os.Put(escape[(unsigned char)e]);
+                }
+                else if (e == 'u') {    // Unicode
+                    unsigned codepoint = ParseHex4(is);
+                    if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
+                        // Handle UTF-16 surrogate pair
+                        if (is.Take() != '\\' || is.Take() != 'u')
+                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
+                        unsigned codepoint2 = ParseHex4(is);
+                        if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
+                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
+                        codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
+                    }
+                    TEncoding::Encode(os, codepoint);
+                }
+                else
+                    RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
+            }
+            else if (c == '"') {    // Closing double quote
+                is.Take();
+                os.Put('\0');   // null-terminate the string
+                return;
+            }
+            else if (c == '\0')
+                RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1);
+            else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
+                RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
+            else {
+                if (parseFlags & kParseValidateEncodingFlag ? 
+                    !Transcoder<SEncoding, TEncoding>::Validate(is, os) : 
+                    !Transcoder<SEncoding, TEncoding>::Transcode(is, os))
+                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
+            }
+        }
+    }
+
+    template<typename InputStream, bool backup>
+    class NumberStream {};
+
+    template<typename InputStream>
+    class NumberStream<InputStream, false> {
+    public:
+        NumberStream(GenericReader& reader, InputStream& is) : is(is) { (void)reader;  }
+        ~NumberStream() {}
+
+        RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
+        RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
+        RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
+        size_t Tell() { return is.Tell(); }
+        size_t Length() { return 0; }
+        const char* Pop() { return 0; }
+
+    protected:
+        NumberStream& operator=(const NumberStream&);
+
+        InputStream& is;
+    };
+
+    template<typename InputStream>
+    class NumberStream<InputStream, true> : public NumberStream<InputStream, false> {
+        typedef NumberStream<InputStream, false> Base;
+    public:
+        NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {}
+        ~NumberStream() {}
+
+        RAPIDJSON_FORCEINLINE Ch TakePush() {
+            stackStream.Put((char)Base::is.Peek());
+            return Base::is.Take();
+        }
+
+        size_t Length() { return stackStream.Length(); }
+
+        const char* Pop() {
+            stackStream.Put('\0');
+            return stackStream.Pop();
+        }
+
+    private:
+        StackStream<char> stackStream;
+    };
+
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseNumber(InputStream& is, Handler& handler) {
+        internal::StreamLocalCopy<InputStream> copy(is);
+        NumberStream<InputStream, (parseFlags & kParseFullPrecisionFlag) != 0> s(*this, copy.s);
+
+        // Parse minus
+        bool minus = false;
+        if (s.Peek() == '-') {
+            minus = true;
+            s.Take();
+        }
+
+        // Parse int: zero / ( digit1-9 *DIGIT )
+        unsigned i = 0;
+        uint64_t i64 = 0;
+        bool use64bit = false;
+        int significandDigit = 0;
+        if (s.Peek() == '0') {
+            i = 0;
+            s.TakePush();
+        }
+        else if (s.Peek() >= '1' && s.Peek() <= '9') {
+            i = static_cast<unsigned>(s.TakePush() - '0');
+
+            if (minus)
+                while (s.Peek() >= '0' && s.Peek() <= '9') {
+                    if (i >= 214748364) { // 2^31 = 2147483648
+                        if (i != 214748364 || s.Peek() > '8') {
+                            i64 = i;
+                            use64bit = true;
+                            break;
+                        }
+                    }
+                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                    significandDigit++;
+                }
+            else
+                while (s.Peek() >= '0' && s.Peek() <= '9') {
+                    if (i >= 429496729) { // 2^32 - 1 = 4294967295
+                        if (i != 429496729 || s.Peek() > '5') {
+                            i64 = i;
+                            use64bit = true;
+                            break;
+                        }
+                    }
+                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                    significandDigit++;
+                }
+        }
+        else
+            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+
+        // Parse 64bit int
+        bool useDouble = false;
+        double d = 0.0;
+        if (use64bit) {
+            if (minus) 
+                while (s.Peek() >= '0' && s.Peek() <= '9') {                    
+                     if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808
+                        if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') {
+                            d = i64;
+                            useDouble = true;
+                            break;
+                        }
+                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                    significandDigit++;
+                }
+            else
+                while (s.Peek() >= '0' && s.Peek() <= '9') {                    
+                    if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615
+                        if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') {
+                            d = i64;
+                            useDouble = true;
+                            break;
+                        }
+                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                    significandDigit++;
+                }
+        }
+
+        // Force double for big integer
+        if (useDouble) {
+            while (s.Peek() >= '0' && s.Peek() <= '9') {
+                if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
+                    RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
+                d = d * 10 + (s.TakePush() - '0');
+            }
+        }
+
+        // Parse frac = decimal-point 1*DIGIT
+        int expFrac = 0;
+        size_t decimalPosition;
+        if (s.Peek() == '.') {
+            s.Take();
+            decimalPosition = s.Length();
+
+            if (!(s.Peek() >= '0' && s.Peek() <= '9'))
+                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
+
+            if (!useDouble) {
+#if RAPIDJSON_64BIT
+                // Use i64 to store significand in 64-bit architecture
+                if (!use64bit)
+                    i64 = i;
+        
+                while (s.Peek() >= '0' && s.Peek() <= '9') {
+                    if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
+                        break;
+                    else {
+                        i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                        --expFrac;
+                        if (i64 != 0)
+                            significandDigit++;
+                    }
+                }
+
+                d = (double)i64;
+#else
+                // Use double to store significand in 32-bit architecture
+                d = use64bit ? (double)i64 : (double)i;
+#endif
+                useDouble = true;
+            }
+
+            while (s.Peek() >= '0' && s.Peek() <= '9') {
+                if (significandDigit < 17) {
+                    d = d * 10.0 + (s.TakePush() - '0');
+                    --expFrac;
+                    if (d != 0.0)
+                        significandDigit++;
+                }
+                else
+                    s.TakePush();
+            }
+        }
+        else
+            decimalPosition = s.Length(); // decimal position at the end of integer.
+
+        // Parse exp = e [ minus / plus ] 1*DIGIT
+        int exp = 0;
+        if (s.Peek() == 'e' || s.Peek() == 'E') {
+            if (!useDouble) {
+                d = use64bit ? i64 : i;
+                useDouble = true;
+            }
+            s.Take();
+
+            bool expMinus = false;
+            if (s.Peek() == '+')
+                s.Take();
+            else if (s.Peek() == '-') {
+                s.Take();
+                expMinus = true;
+            }
+
+            if (s.Peek() >= '0' && s.Peek() <= '9') {
+                exp = s.Take() - '0';
+                while (s.Peek() >= '0' && s.Peek() <= '9') {
+                    exp = exp * 10 + (s.Take() - '0');
+                    if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first.
+                        RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
+                }
+            }
+            else
+                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
+
+            if (expMinus)
+                exp = -exp;
+        }
+
+        // Finish parsing, call event according to the type of number.
+        bool cont = true;
+        size_t length = s.Length();
+        const char* decimal = s.Pop();  // Pop stack no matter if it will be used or not.
+
+        if (useDouble) {
+            int p = exp + expFrac;
+            if (parseFlags & kParseFullPrecisionFlag)
+                d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
+            else
+                d = internal::StrtodNormalPrecision(d, p);
+
+            cont = handler.Double(minus ? -d : d);
+        }
+        else {
+            if (use64bit) {
+                if (minus)
+                    cont = handler.Int64(-(int64_t)i64);
+                else
+                    cont = handler.Uint64(i64);
+            }
+            else {
+                if (minus)
+                    cont = handler.Int(-(int)i);
+                else
+                    cont = handler.Uint(i);
+            }
+        }
+        if (!cont)
+            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+    }
+
+    // Parse any JSON value
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseValue(InputStream& is, Handler& handler) {
+        switch (is.Peek()) {
+            case 'n': ParseNull  <parseFlags>(is, handler); break;
+            case 't': ParseTrue  <parseFlags>(is, handler); break;
+            case 'f': ParseFalse <parseFlags>(is, handler); break;
+            case '"': ParseString<parseFlags>(is, handler); break;
+            case '{': ParseObject<parseFlags>(is, handler); break;
+            case '[': ParseArray <parseFlags>(is, handler); break;
+            default : ParseNumber<parseFlags>(is, handler);
+        }
+    }
+
+    // Iterative Parsing
+
+    // States
+    enum IterativeParsingState {
+        IterativeParsingStartState = 0,
+        IterativeParsingFinishState,
+        IterativeParsingErrorState,
+
+        // Object states
+        IterativeParsingObjectInitialState,
+        IterativeParsingMemberKeyState,
+        IterativeParsingKeyValueDelimiterState,
+        IterativeParsingMemberValueState,
+        IterativeParsingMemberDelimiterState,
+        IterativeParsingObjectFinishState,
+
+        // Array states
+        IterativeParsingArrayInitialState,
+        IterativeParsingElementState,
+        IterativeParsingElementDelimiterState,
+        IterativeParsingArrayFinishState,
+
+        // Single value state
+        IterativeParsingValueState,
+
+        cIterativeParsingStateCount
+    };
+
+    // Tokens
+    enum Token {
+        LeftBracketToken = 0,
+        RightBracketToken,
+
+        LeftCurlyBracketToken,
+        RightCurlyBracketToken,
+
+        CommaToken,
+        ColonToken,
+
+        StringToken,
+        FalseToken,
+        TrueToken,
+        NullToken,
+        NumberToken,
+
+        kTokenCount
+    };
+
+    RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define N NumberToken
+#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
+        // Maps from ASCII to Token
+        static const unsigned char tokenMap[256] = {
+            N16, // 00~0F
+            N16, // 10~1F
+            N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
+            N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
+            N16, // 40~4F
+            N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
+            N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
+            N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
+            N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
+        };
+#undef N
+#undef N16
+//!@endcond
+        
+        if (sizeof(Ch) == 1 || unsigned(c) < 256)
+            return (Token)tokenMap[(unsigned char)c];
+        else
+            return NumberToken;
+    }
+
+    RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
+        // current state x one lookahead token -> new state
+        static const char G[cIterativeParsingStateCount][kTokenCount] = {
+            // Start
+            {
+                IterativeParsingArrayInitialState,  // Left bracket
+                IterativeParsingErrorState,         // Right bracket
+                IterativeParsingObjectInitialState, // Left curly bracket
+                IterativeParsingErrorState,         // Right curly bracket
+                IterativeParsingErrorState,         // Comma
+                IterativeParsingErrorState,         // Colon
+                IterativeParsingValueState,         // String
+                IterativeParsingValueState,         // False
+                IterativeParsingValueState,         // True
+                IterativeParsingValueState,         // Null
+                IterativeParsingValueState          // Number
+            },
+            // Finish(sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            },
+            // Error(sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            },
+            // ObjectInitial
+            {
+                IterativeParsingErrorState,         // Left bracket
+                IterativeParsingErrorState,         // Right bracket
+                IterativeParsingErrorState,         // Left curly bracket
+                IterativeParsingObjectFinishState,  // Right curly bracket
+                IterativeParsingErrorState,         // Comma
+                IterativeParsingErrorState,         // Colon
+                IterativeParsingMemberKeyState,     // String
+                IterativeParsingErrorState,         // False
+                IterativeParsingErrorState,         // True
+                IterativeParsingErrorState,         // Null
+                IterativeParsingErrorState          // Number
+            },
+            // MemberKey
+            {
+                IterativeParsingErrorState,             // Left bracket
+                IterativeParsingErrorState,             // Right bracket
+                IterativeParsingErrorState,             // Left curly bracket
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingErrorState,             // Comma
+                IterativeParsingKeyValueDelimiterState, // Colon
+                IterativeParsingErrorState,             // String
+                IterativeParsingErrorState,             // False
+                IterativeParsingErrorState,             // True
+                IterativeParsingErrorState,             // Null
+                IterativeParsingErrorState              // Number
+            },
+            // KeyValueDelimiter
+            {
+                IterativeParsingArrayInitialState,      // Left bracket(push MemberValue state)
+                IterativeParsingErrorState,             // Right bracket
+                IterativeParsingObjectInitialState,     // Left curly bracket(push MemberValue state)
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingErrorState,             // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingMemberValueState,       // String
+                IterativeParsingMemberValueState,       // False
+                IterativeParsingMemberValueState,       // True
+                IterativeParsingMemberValueState,       // Null
+                IterativeParsingMemberValueState        // Number
+            },
+            // MemberValue
+            {
+                IterativeParsingErrorState,             // Left bracket
+                IterativeParsingErrorState,             // Right bracket
+                IterativeParsingErrorState,             // Left curly bracket
+                IterativeParsingObjectFinishState,      // Right curly bracket
+                IterativeParsingMemberDelimiterState,   // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingErrorState,             // String
+                IterativeParsingErrorState,             // False
+                IterativeParsingErrorState,             // True
+                IterativeParsingErrorState,             // Null
+                IterativeParsingErrorState              // Number
+            },
+            // MemberDelimiter
+            {
+                IterativeParsingErrorState,         // Left bracket
+                IterativeParsingErrorState,         // Right bracket
+                IterativeParsingErrorState,         // Left curly bracket
+                IterativeParsingErrorState,         // Right curly bracket
+                IterativeParsingErrorState,         // Comma
+                IterativeParsingErrorState,         // Colon
+                IterativeParsingMemberKeyState,     // String
+                IterativeParsingErrorState,         // False
+                IterativeParsingErrorState,         // True
+                IterativeParsingErrorState,         // Null
+                IterativeParsingErrorState          // Number
+            },
+            // ObjectFinish(sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            },
+            // ArrayInitial
+            {
+                IterativeParsingArrayInitialState,      // Left bracket(push Element state)
+                IterativeParsingArrayFinishState,       // Right bracket
+                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingErrorState,             // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingElementState,           // String
+                IterativeParsingElementState,           // False
+                IterativeParsingElementState,           // True
+                IterativeParsingElementState,           // Null
+                IterativeParsingElementState            // Number
+            },
+            // Element
+            {
+                IterativeParsingErrorState,             // Left bracket
+                IterativeParsingArrayFinishState,       // Right bracket
+                IterativeParsingErrorState,             // Left curly bracket
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingElementDelimiterState,  // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingErrorState,             // String
+                IterativeParsingErrorState,             // False
+                IterativeParsingErrorState,             // True
+                IterativeParsingErrorState,             // Null
+                IterativeParsingErrorState              // Number
+            },
+            // ElementDelimiter
+            {
+                IterativeParsingArrayInitialState,      // Left bracket(push Element state)
+                IterativeParsingErrorState,             // Right bracket
+                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingErrorState,             // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingElementState,           // String
+                IterativeParsingElementState,           // False
+                IterativeParsingElementState,           // True
+                IterativeParsingElementState,           // Null
+                IterativeParsingElementState            // Number
+            },
+            // ArrayFinish(sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            },
+            // Single Value (sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            }
+        }; // End of G
+
+        return (IterativeParsingState)G[state][token];
+    }
+
+    // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
+    // May return a new state on state pop.
+    template <unsigned parseFlags, typename InputStream, typename Handler>
+    RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
+        switch (dst) {
+        case IterativeParsingStartState:
+            RAPIDJSON_ASSERT(false);
+            return IterativeParsingErrorState;
+
+        case IterativeParsingFinishState:
+            return dst;
+
+        case IterativeParsingErrorState:
+            return dst;
+
+        case IterativeParsingObjectInitialState:
+        case IterativeParsingArrayInitialState:
+        {
+            // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
+            // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
+            IterativeParsingState n = src;
+            if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
+                n = IterativeParsingElementState;
+            else if (src == IterativeParsingKeyValueDelimiterState)
+                n = IterativeParsingMemberValueState;
+            // Push current state.
+            *stack_.template Push<SizeType>(1) = n;
+            // Initialize and push the member/element count.
+            *stack_.template Push<SizeType>(1) = 0;
+            // Call handler
+            bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
+            // On handler short circuits the parsing.
+            if (!hr) {
+                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+                return IterativeParsingErrorState;
+            }
+            else {
+                is.Take();
+                return dst;
+            }
+        }
+
+        case IterativeParsingMemberKeyState:
+            ParseString<parseFlags>(is, handler, true);
+            if (HasParseError())
+                return IterativeParsingErrorState;
+            else
+                return dst;
+
+        case IterativeParsingKeyValueDelimiterState:
+            if (token == ColonToken) {
+                is.Take();
+                return dst;
+            }
+            else
+                return IterativeParsingErrorState;
+
+        case IterativeParsingMemberValueState:
+            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+            ParseValue<parseFlags>(is, handler);
+            if (HasParseError()) {
+                return IterativeParsingErrorState;
+            }
+            return dst;
+
+        case IterativeParsingElementState:
+            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+            ParseValue<parseFlags>(is, handler);
+            if (HasParseError()) {
+                return IterativeParsingErrorState;
+            }
+            return dst;
+
+        case IterativeParsingMemberDelimiterState:
+        case IterativeParsingElementDelimiterState:
+            is.Take();
+            // Update member/element count.
+            *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
+            return dst;
+
+        case IterativeParsingObjectFinishState:
+        {
+            // Get member count.
+            SizeType c = *stack_.template Pop<SizeType>(1);
+            // If the object is not empty, count the last member.
+            if (src == IterativeParsingMemberValueState)
+                ++c;
+            // Restore the state.
+            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+            // Transit to Finish state if this is the topmost scope.
+            if (n == IterativeParsingStartState)
+                n = IterativeParsingFinishState;
+            // Call handler
+            bool hr = handler.EndObject(c);
+            // On handler short circuits the parsing.
+            if (!hr) {
+                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+                return IterativeParsingErrorState;
+            }
+            else {
+                is.Take();
+                return n;
+            }
+        }
+
+        case IterativeParsingArrayFinishState:
+        {
+            // Get element count.
+            SizeType c = *stack_.template Pop<SizeType>(1);
+            // If the array is not empty, count the last element.
+            if (src == IterativeParsingElementState)
+                ++c;
+            // Restore the state.
+            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+            // Transit to Finish state if this is the topmost scope.
+            if (n == IterativeParsingStartState)
+                n = IterativeParsingFinishState;
+            // Call handler
+            bool hr = handler.EndArray(c);
+            // On handler short circuits the parsing.
+            if (!hr) {
+                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+                return IterativeParsingErrorState;
+            }
+            else {
+                is.Take();
+                return n;
+            }
+        }
+
+        case IterativeParsingValueState:
+            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+            ParseValue<parseFlags>(is, handler);
+            if (HasParseError()) {
+                return IterativeParsingErrorState;
+            }
+            return IterativeParsingFinishState;
+
+        default:
+            RAPIDJSON_ASSERT(false);
+            return IterativeParsingErrorState;
+        }
+    }
+
+    template <typename InputStream>
+    void HandleError(IterativeParsingState src, InputStream& is) {
+        if (HasParseError()) {
+            // Error flag has been set.
+            return;
+        }
+        
+        switch (src) {
+        case IterativeParsingStartState:            RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell());
+        case IterativeParsingFinishState:           RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
+        case IterativeParsingObjectInitialState:
+        case IterativeParsingMemberDelimiterState:  RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
+        case IterativeParsingMemberKeyState:        RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
+        case IterativeParsingMemberValueState:      RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
+        case IterativeParsingElementState:          RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+        default:                                    RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+        }       
+    }
+
+    template <unsigned parseFlags, typename InputStream, typename Handler>
+    ParseResult IterativeParse(InputStream& is, Handler& handler) {
+        parseResult_.Clear();
+        ClearStackOnExit scope(*this);
+        IterativeParsingState state = IterativeParsingStartState;
+
+        SkipWhitespace(is);
+        while (is.Peek() != '\0') {
+            Token t = Tokenize(is.Peek());
+            IterativeParsingState n = Predict(state, t);
+            IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
+
+            if (d == IterativeParsingErrorState) {
+                HandleError(state, is);
+                break;
+            }
+
+            state = d;
+
+            // Do not further consume streams if a root JSON has been parsed.
+            if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
+                break;
+
+            SkipWhitespace(is);
+        }
+
+        // Handle the end of file.
+        if (state != IterativeParsingFinishState)
+            HandleError(state, is);
+
+        return parseResult_;
+    }
+
+    static const size_t kDefaultStackCapacity = 256;    //!< Default stack capacity in bytes for storing a single decoded string.
+    internal::Stack<StackAllocator> stack_;  //!< A stack for storing decoded string temporarily during non-destructive parsing.
+    ParseResult parseResult_;
+}; // class GenericReader
+
+//! Reader with UTF8 encoding and default allocator.
+typedef GenericReader<UTF8<>, UTF8<> > Reader;
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_READER_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/stringbuffer.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/stringbuffer.h
new file mode 100644
index 0000000..009a518
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/stringbuffer.h
@@ -0,0 +1,99 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_STRINGBUFFER_H_
+#define RAPIDJSON_STRINGBUFFER_H_
+
+#include "rapidjson.h"
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+#include "internal/stack.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output stream.
+/*!
+    \tparam Encoding Encoding of the stream.
+    \tparam Allocator type for allocating memory buffer.
+    \note implements Stream concept
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+class GenericStringBuffer {
+public:
+    typedef typename Encoding::Ch Ch;
+
+    GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
+    GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
+        if (&rhs != this)
+            stack_ = std::move(rhs.stack_);
+        return *this;
+    }
+#endif
+
+    void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+    void Flush() {}
+
+    void Clear() { stack_.Clear(); }
+    void ShrinkToFit() {
+        // Push and pop a null terminator. This is safe.
+        *stack_.template Push<Ch>() = '\0';
+        stack_.ShrinkToFit();
+        stack_.template Pop<Ch>(1);
+    }
+    Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+    void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+    const Ch* GetString() const {
+        // Push and pop a null terminator. This is safe.
+        *stack_.template Push<Ch>() = '\0';
+        stack_.template Pop<Ch>(1);
+
+        return stack_.template Bottom<Ch>();
+    }
+
+    size_t GetSize() const { return stack_.GetSize(); }
+
+    static const size_t kDefaultCapacity = 256;
+    mutable internal::Stack<Allocator> stack_;
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    GenericStringBuffer(const GenericStringBuffer&);
+    GenericStringBuffer& operator=(const GenericStringBuffer&);
+};
+
+//! String buffer with UTF8 encoding
+typedef GenericStringBuffer<UTF8<> > StringBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
+    std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STRINGBUFFER_H_
diff --git a/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/writer.h b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/writer.h
new file mode 100644
index 0000000..6daa783
--- /dev/null
+++ b/src/third_party/angle/src/tests/third_party/rapidjson/include/rapidjson/writer.h
@@ -0,0 +1,391 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_WRITER_H_
+#define RAPIDJSON_WRITER_H_
+
+#include "rapidjson.h"
+#include "internal/stack.h"
+#include "internal/strfunc.h"
+#include "internal/dtoa.h"
+#include "internal/itoa.h"
+#include "stringbuffer.h"
+#include <new>      // placement new
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! JSON writer
+/*! Writer implements the concept Handler.
+    It generates JSON text by events to an output os.
+
+    User may programmatically calls the functions of a writer to generate JSON text.
+
+    On the other side, a writer can also be passed to objects that generates events, 
+
+    for example Reader::Parse() and Document::Accept().
+
+    \tparam OutputStream Type of output stream.
+    \tparam SourceEncoding Encoding of source string.
+    \tparam TargetEncoding Encoding of output stream.
+    \tparam StackAllocator Type of allocator for allocating memory of stack.
+    \note implements Handler concept
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
+class Writer {
+public:
+    typedef typename SourceEncoding::Ch Ch;
+
+    //! Constructor
+    /*! \param os Output stream.
+        \param stackAllocator User supplied allocator. If it is null, it will create a private one.
+        \param levelDepth Initial capacity of stack.
+    */
+    explicit
+    Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : 
+        os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+
+    explicit
+    Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+        os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+
+    //! Reset the writer with a new stream.
+    /*!
+        This function reset the writer with a new stream and default settings,
+        in order to make a Writer object reusable for output multiple JSONs.
+
+        \param os New output stream.
+        \code
+        Writer<OutputStream> writer(os1);
+        writer.StartObject();
+        // ...
+        writer.EndObject();
+
+        writer.Reset(os2);
+        writer.StartObject();
+        // ...
+        writer.EndObject();
+        \endcode
+    */
+    void Reset(OutputStream& os) {
+        os_ = &os;
+        hasRoot_ = false;
+        level_stack_.Clear();
+    }
+
+    //! Checks whether the output is a complete JSON.
+    /*!
+        A complete JSON has a complete root object or array.
+    */
+    bool IsComplete() const {
+        return hasRoot_ && level_stack_.Empty();
+    }
+
+    /*!@name Implementation of Handler
+        \see Handler
+    */
+    //@{
+
+    bool Null()                 { Prefix(kNullType);   return WriteNull(); }
+    bool Bool(bool b)           { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
+    bool Int(int i)             { Prefix(kNumberType); return WriteInt(i); }
+    bool Uint(unsigned u)       { Prefix(kNumberType); return WriteUint(u); }
+    bool Int64(int64_t i64)     { Prefix(kNumberType); return WriteInt64(i64); }
+    bool Uint64(uint64_t u64)   { Prefix(kNumberType); return WriteUint64(u64); }
+
+    //! Writes the given \c double value to the stream
+    /*!
+        \param d The value to be written.
+        \return Whether it is succeed.
+    */
+    bool Double(double d)       { Prefix(kNumberType); return WriteDouble(d); }
+
+    bool String(const Ch* str, SizeType length, bool copy = false) {
+        (void)copy;
+        Prefix(kStringType);
+        return WriteString(str, length);
+    }
+
+    bool StartObject() {
+        Prefix(kObjectType);
+        new (level_stack_.template Push<Level>()) Level(false);
+        return WriteStartObject();
+    }
+
+    bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+	
+    bool EndObject(SizeType memberCount = 0) {
+        (void)memberCount;
+        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+        RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
+        level_stack_.template Pop<Level>(1);
+        bool ret = WriteEndObject();
+        if (level_stack_.Empty())   // end of json text
+            os_->Flush();
+        return ret;
+    }
+
+    bool StartArray() {
+        Prefix(kArrayType);
+        new (level_stack_.template Push<Level>()) Level(true);
+        return WriteStartArray();
+    }
+
+    bool EndArray(SizeType elementCount = 0) {
+        (void)elementCount;
+        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+        RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
+        level_stack_.template Pop<Level>(1);
+        bool ret = WriteEndArray();
+        if (level_stack_.Empty())   // end of json text
+            os_->Flush();
+        return ret;
+    }
+    //@}
+
+    /*! @name Convenience extensions */
+    //@{
+
+    //! Simpler but slower overload.
+    bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+    bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+    //@}
+
+protected:
+    //! Information for each nested level
+    struct Level {
+        Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
+        size_t valueCount;  //!< number of values in this level
+        bool inArray;       //!< true if in array, otherwise in object
+    };
+
+    static const size_t kDefaultLevelDepth = 32;
+
+    bool WriteNull()  {
+        os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
+    }
+
+    bool WriteBool(bool b)  {
+        if (b) {
+            os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
+        }
+        else {
+            os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
+        }
+        return true;
+    }
+
+    bool WriteInt(int i) {
+        char buffer[11];
+        const char* end = internal::i32toa(i, buffer);
+        for (const char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteUint(unsigned u) {
+        char buffer[10];
+        const char* end = internal::u32toa(u, buffer);
+        for (const char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteInt64(int64_t i64) {
+        char buffer[21];
+        const char* end = internal::i64toa(i64, buffer);
+        for (const char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteUint64(uint64_t u64) {
+        char buffer[20];
+        char* end = internal::u64toa(u64, buffer);
+        for (char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteDouble(double d) {
+        char buffer[25];
+        char* end = internal::dtoa(d, buffer);
+        for (char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteString(const Ch* str, SizeType length)  {
+        static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+        static const char escape[256] = {
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+            //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
+            'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
+            'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
+              0,   0, '"',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20
+            Z16, Z16,                                                                       // 30~4F
+              0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0,   0,   0, // 50
+            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16                                // 60~FF
+#undef Z16
+        };
+
+        os_->Put('\"');
+        GenericStringStream<SourceEncoding> is(str);
+        while (is.Tell() < length) {
+            const Ch c = is.Peek();
+            if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
+                // Unicode escaping
+                unsigned codepoint;
+                if (!SourceEncoding::Decode(is, &codepoint))
+                    return false;
+                os_->Put('\\');
+                os_->Put('u');
+                if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
+                    os_->Put(hexDigits[(codepoint >> 12) & 15]);
+                    os_->Put(hexDigits[(codepoint >>  8) & 15]);
+                    os_->Put(hexDigits[(codepoint >>  4) & 15]);
+                    os_->Put(hexDigits[(codepoint      ) & 15]);
+                }
+                else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF)    {
+                    // Surrogate pair
+                    unsigned s = codepoint - 0x010000;
+                    unsigned lead = (s >> 10) + 0xD800;
+                    unsigned trail = (s & 0x3FF) + 0xDC00;
+                    os_->Put(hexDigits[(lead >> 12) & 15]);
+                    os_->Put(hexDigits[(lead >>  8) & 15]);
+                    os_->Put(hexDigits[(lead >>  4) & 15]);
+                    os_->Put(hexDigits[(lead      ) & 15]);
+                    os_->Put('\\');
+                    os_->Put('u');
+                    os_->Put(hexDigits[(trail >> 12) & 15]);
+                    os_->Put(hexDigits[(trail >>  8) & 15]);
+                    os_->Put(hexDigits[(trail >>  4) & 15]);
+                    os_->Put(hexDigits[(trail      ) & 15]);                    
+                }
+                else
+                    return false;   // invalid code point
+            }
+            else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c])  {
+                is.Take();
+                os_->Put('\\');
+                os_->Put(escape[(unsigned char)c]);
+                if (escape[(unsigned char)c] == 'u') {
+                    os_->Put('0');
+                    os_->Put('0');
+                    os_->Put(hexDigits[(unsigned char)c >> 4]);
+                    os_->Put(hexDigits[(unsigned char)c & 0xF]);
+                }
+            }
+            else
+                Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_);
+        }
+        os_->Put('\"');
+        return true;
+    }
+
+    bool WriteStartObject() { os_->Put('{'); return true; }
+    bool WriteEndObject()   { os_->Put('}'); return true; }
+    bool WriteStartArray()  { os_->Put('['); return true; }
+    bool WriteEndArray()    { os_->Put(']'); return true; }
+
+    void Prefix(Type type) {
+        (void)type;
+        if (level_stack_.GetSize() != 0) { // this value is not at root
+            Level* level = level_stack_.template Top<Level>();
+            if (level->valueCount > 0) {
+                if (level->inArray) 
+                    os_->Put(','); // add comma if it is not the first element in array
+                else  // in object
+                    os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
+            }
+            if (!level->inArray && level->valueCount % 2 == 0)
+                RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
+            level->valueCount++;
+        }
+        else {
+            RAPIDJSON_ASSERT(!hasRoot_);    // Should only has one and only one root.
+            hasRoot_ = true;
+        }
+    }
+
+    OutputStream* os_;
+    internal::Stack<StackAllocator> level_stack_;
+    bool hasRoot_;
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    Writer(const Writer&);
+    Writer& operator=(const Writer&);
+};
+
+// Full specialization for StringStream to prevent memory copying
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt(int i) {
+    char *buffer = os_->Push(11);
+    const char* end = internal::i32toa(i, buffer);
+    os_->Pop(11 - (end - buffer));
+    return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
+    char *buffer = os_->Push(10);
+    const char* end = internal::u32toa(u, buffer);
+    os_->Pop(10 - (end - buffer));
+    return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
+    char *buffer = os_->Push(21);
+    const char* end = internal::i64toa(i64, buffer);
+    os_->Pop(21 - (end - buffer));
+    return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
+    char *buffer = os_->Push(20);
+    const char* end = internal::u64toa(u, buffer);
+    os_->Pop(20 - (end - buffer));
+    return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteDouble(double d) {
+    char *buffer = os_->Push(25);
+    char* end = internal::dtoa(d, buffer);
+    os_->Pop(25 - (end - buffer));
+    return true;
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/src/third_party/angle/src/tests/util_tests/PrintSystemInfoTest.cpp b/src/third_party/angle/src/tests/util_tests/PrintSystemInfoTest.cpp
new file mode 100644
index 0000000..f9093e3
--- /dev/null
+++ b/src/third_party/angle/src/tests/util_tests/PrintSystemInfoTest.cpp
@@ -0,0 +1,97 @@
+//
+// Copyright 2017 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.
+//
+
+// PrintSystemInfoTest.cpp:
+//     prints the information gathered about the system so that it appears in the test logs
+
+#include <gtest/gtest.h>
+
+#include <iostream>
+
+#include "common/platform.h"
+#include "gpu_info_util/SystemInfo.h"
+
+using namespace angle;
+
+namespace
+{
+
+#if defined(ANGLE_PLATFORM_WINDOWS) || defined(ANGLE_PLATFORM_LINUX) || \
+    defined(ANGLE_PLATFORM_APPLE)
+#define SYSTEM_INFO_IMPLEMENTED
+#endif
+
+#if defined(SYSTEM_INFO_IMPLEMENTED)
+std::string VendorName(VendorID vendor)
+{
+    switch (vendor)
+    {
+        case kVendorID_AMD:
+            return "AMD";
+        case kVendorID_Intel:
+            return "Intel";
+        case kVendorID_Nvidia:
+            return "Nvidia";
+        case kVendorID_Qualcomm:
+            return "Qualcomm";
+        default:
+            return "Unknown (" + std::to_string(vendor) + ")";
+    }
+}
+#endif
+
+// Prints the information gathered about the system
+TEST(PrintSystemInfoTest, Print)
+{
+#if defined(SYSTEM_INFO_IMPLEMENTED)
+    SystemInfo info;
+
+    ASSERT_TRUE(GetSystemInfo(&info));
+    ASSERT_GT(info.gpus.size(), 0u);
+
+    std::cout << info.gpus.size() << " GPUs:\n";
+
+    for (size_t i = 0; i < info.gpus.size(); i++)
+    {
+        const auto &gpu = info.gpus[i];
+
+        std::cout << "  " << i << " - " << VendorName(gpu.vendorId) << " device " << gpu.deviceId
+                  << "\n";
+        if (!gpu.driverVendor.empty())
+        {
+            std::cout << "       Driver Vendor: " << gpu.driverVendor << "\n";
+        }
+        if (!gpu.driverVersion.empty())
+        {
+            std::cout << "       Driver Version: " << gpu.driverVersion << "\n";
+        }
+        if (!gpu.driverDate.empty())
+        {
+            std::cout << "       Driver Date: " << gpu.driverDate << "\n";
+        }
+    }
+
+    std::cout << "\n";
+    std::cout << "Active GPU: " << info.activeGPUIndex << "\n";
+    std::cout << "Primary GPU: " << info.primaryGPUIndex << "\n";
+
+    std::cout << "\n";
+    std::cout << "Optimus: " << (info.isOptimus ? "true" : "false") << "\n";
+    std::cout << "AMD Switchable: " << (info.isAMDSwitchable ? "true" : "false") << "\n";
+
+    std::cout << "\n";
+    if (!info.machineModelName.empty() || !info.machineModelVersion.empty())
+    {
+        std::cout << "Machine Model: " << info.machineModelName << " version "
+                  << info.machineModelVersion << "\n";
+    }
+    std::cout << std::endl;
+#else
+    std::cerr << "GetSystemInfo not implemented, skipping" << std::endl;
+#endif
+}
+
+}  // anonymous namespace
diff --git a/src/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.cpp b/src/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.cpp
index 288f552..aadb875 100644
--- a/src/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.cpp
+++ b/src/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.cpp
@@ -38,16 +38,21 @@
 const char* kIntClampEnd = "// END: Generated code for array bounds clamping\n\n";
 const char* kIntClampDefinition = "int webgl_int_clamp(int value, int minValue, int maxValue) { return ((value < minValue) ? minValue : ((value > maxValue) ? maxValue : value)); }\n\n";
 
-namespace {
+namespace sh
+{
+
+namespace
+{
 
 class ArrayBoundsClamperMarker : public TIntermTraverser {
 public:
     ArrayBoundsClamperMarker()
-        : mNeedsClamp(false)
+        : TIntermTraverser(true, false, false),
+          mNeedsClamp(false)
    {
    }
 
-   virtual bool visitBinary(Visit visit, TIntermBinary* node)
+    bool visitBinary(Visit visit, TIntermBinary *node) override
    {
        if (node->getOp() == EOpIndexIndirect)
        {
@@ -104,3 +109,5 @@
     }
     out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
 }
+
+}  // namespace sh
diff --git a/src/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.h
index 0d4e1a3..a4c407f 100644
--- a/src/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.h
+++ b/src/third_party/angle/src/third_party/compiler/ArrayBoundsClamper.h
@@ -23,16 +23,18 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_
-#define THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_
+#ifndef THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_
+#define THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_
 
-#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
 
-#include "compiler/InfoSink.h"
-#include "compiler/intermediate.h"
+namespace sh
+{
 
-class ArrayBoundsClamper {
-public:
+class ArrayBoundsClamper
+{
+  public:
     ArrayBoundsClamper();
 
     // Must be set before compiling any shaders to ensure consistency
@@ -59,4 +61,6 @@
     bool mArrayBoundsClampDefinitionNeeded;
 };
 
-#endif // THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_
+}  // namespace sh
+
+#endif // THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_
diff --git a/src/third_party/angle/src/third_party/khronos/GL/wglext.h b/src/third_party/angle/src/third_party/khronos/GL/wglext.h
new file mode 100644
index 0000000..daba410
--- /dev/null
+++ b/src/third_party/angle/src/third_party/khronos/GL/wglext.h
@@ -0,0 +1,840 @@
+#ifndef __wglext_h_
+#define __wglext_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/
+**
+** Khronos $Revision: 27684 $ on $Date: 2014-08-11 01:21:35 -0700 (Mon, 11 Aug 2014) $
+*/
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#define WGL_WGLEXT_VERSION 20140810
+
+/* Generated C header for:
+ * API: wgl
+ * Versions considered: .*
+ * Versions emitted: _nomatch_^
+ * Default extensions included: wgl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef WGL_ARB_buffer_region
+#define WGL_ARB_buffer_region 1
+#define WGL_FRONT_COLOR_BUFFER_BIT_ARB    0x00000001
+#define WGL_BACK_COLOR_BUFFER_BIT_ARB     0x00000002
+#define WGL_DEPTH_BUFFER_BIT_ARB          0x00000004
+#define WGL_STENCIL_BUFFER_BIT_ARB        0x00000008
+typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);
+typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);
+typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);
+typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+#ifdef WGL_WGLEXT_PROTOTYPES
+HANDLE WINAPI wglCreateBufferRegionARB (HDC hDC, int iLayerPlane, UINT uType);
+VOID WINAPI wglDeleteBufferRegionARB (HANDLE hRegion);
+BOOL WINAPI wglSaveBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height);
+BOOL WINAPI wglRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+#endif
+#endif /* WGL_ARB_buffer_region */
+
+#ifndef WGL_ARB_context_flush_control
+#define WGL_ARB_context_flush_control 1
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB  0x2097
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#endif /* WGL_ARB_context_flush_control */
+
+#ifndef WGL_ARB_create_context
+#define WGL_ARB_create_context 1
+#define WGL_CONTEXT_DEBUG_BIT_ARB         0x00000001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB     0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB     0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB       0x2093
+#define WGL_CONTEXT_FLAGS_ARB             0x2094
+#define ERROR_INVALID_VERSION_ARB         0x2095
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
+#ifdef WGL_WGLEXT_PROTOTYPES
+HGLRC WINAPI wglCreateContextAttribsARB (HDC hDC, HGLRC hShareContext, const int *attribList);
+#endif
+#endif /* WGL_ARB_create_context */
+
+#ifndef WGL_ARB_create_context_profile
+#define WGL_ARB_create_context_profile 1
+#define WGL_CONTEXT_PROFILE_MASK_ARB      0x9126
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB  0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define ERROR_INVALID_PROFILE_ARB         0x2096
+#endif /* WGL_ARB_create_context_profile */
+
+#ifndef WGL_ARB_create_context_robustness
+#define WGL_ARB_create_context_robustness 1
+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define WGL_LOSE_CONTEXT_ON_RESET_ARB     0x8252
+#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define WGL_NO_RESET_NOTIFICATION_ARB     0x8261
+#endif /* WGL_ARB_create_context_robustness */
+
+#ifndef WGL_ARB_extensions_string
+#define WGL_ARB_extensions_string 1
+typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
+#ifdef WGL_WGLEXT_PROTOTYPES
+const char *WINAPI wglGetExtensionsStringARB (HDC hdc);
+#endif
+#endif /* WGL_ARB_extensions_string */
+
+#ifndef WGL_ARB_framebuffer_sRGB
+#define WGL_ARB_framebuffer_sRGB 1
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB  0x20A9
+#endif /* WGL_ARB_framebuffer_sRGB */
+
+#ifndef WGL_ARB_make_current_read
+#define WGL_ARB_make_current_read 1
+#define ERROR_INVALID_PIXEL_TYPE_ARB      0x2043
+#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglMakeContextCurrentARB (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+HDC WINAPI wglGetCurrentReadDCARB (void);
+#endif
+#endif /* WGL_ARB_make_current_read */
+
+#ifndef WGL_ARB_multisample
+#define WGL_ARB_multisample 1
+#define WGL_SAMPLE_BUFFERS_ARB            0x2041
+#define WGL_SAMPLES_ARB                   0x2042
+#endif /* WGL_ARB_multisample */
+
+#ifndef WGL_ARB_pbuffer
+#define WGL_ARB_pbuffer 1
+DECLARE_HANDLE(HPBUFFERARB);
+#define WGL_DRAW_TO_PBUFFER_ARB           0x202D
+#define WGL_MAX_PBUFFER_PIXELS_ARB        0x202E
+#define WGL_MAX_PBUFFER_WIDTH_ARB         0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_ARB        0x2030
+#define WGL_PBUFFER_LARGEST_ARB           0x2033
+#define WGL_PBUFFER_WIDTH_ARB             0x2034
+#define WGL_PBUFFER_HEIGHT_ARB            0x2035
+#define WGL_PBUFFER_LOST_ARB              0x2036
+typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
+#ifdef WGL_WGLEXT_PROTOTYPES
+HPBUFFERARB WINAPI wglCreatePbufferARB (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
+HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB hPbuffer);
+int WINAPI wglReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC);
+BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB hPbuffer);
+BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
+#endif
+#endif /* WGL_ARB_pbuffer */
+
+#ifndef WGL_ARB_pixel_format
+#define WGL_ARB_pixel_format 1
+#define WGL_NUMBER_PIXEL_FORMATS_ARB      0x2000
+#define WGL_DRAW_TO_WINDOW_ARB            0x2001
+#define WGL_DRAW_TO_BITMAP_ARB            0x2002
+#define WGL_ACCELERATION_ARB              0x2003
+#define WGL_NEED_PALETTE_ARB              0x2004
+#define WGL_NEED_SYSTEM_PALETTE_ARB       0x2005
+#define WGL_SWAP_LAYER_BUFFERS_ARB        0x2006
+#define WGL_SWAP_METHOD_ARB               0x2007
+#define WGL_NUMBER_OVERLAYS_ARB           0x2008
+#define WGL_NUMBER_UNDERLAYS_ARB          0x2009
+#define WGL_TRANSPARENT_ARB               0x200A
+#define WGL_TRANSPARENT_RED_VALUE_ARB     0x2037
+#define WGL_TRANSPARENT_GREEN_VALUE_ARB   0x2038
+#define WGL_TRANSPARENT_BLUE_VALUE_ARB    0x2039
+#define WGL_TRANSPARENT_ALPHA_VALUE_ARB   0x203A
+#define WGL_TRANSPARENT_INDEX_VALUE_ARB   0x203B
+#define WGL_SHARE_DEPTH_ARB               0x200C
+#define WGL_SHARE_STENCIL_ARB             0x200D
+#define WGL_SHARE_ACCUM_ARB               0x200E
+#define WGL_SUPPORT_GDI_ARB               0x200F
+#define WGL_SUPPORT_OPENGL_ARB            0x2010
+#define WGL_DOUBLE_BUFFER_ARB             0x2011
+#define WGL_STEREO_ARB                    0x2012
+#define WGL_PIXEL_TYPE_ARB                0x2013
+#define WGL_COLOR_BITS_ARB                0x2014
+#define WGL_RED_BITS_ARB                  0x2015
+#define WGL_RED_SHIFT_ARB                 0x2016
+#define WGL_GREEN_BITS_ARB                0x2017
+#define WGL_GREEN_SHIFT_ARB               0x2018
+#define WGL_BLUE_BITS_ARB                 0x2019
+#define WGL_BLUE_SHIFT_ARB                0x201A
+#define WGL_ALPHA_BITS_ARB                0x201B
+#define WGL_ALPHA_SHIFT_ARB               0x201C
+#define WGL_ACCUM_BITS_ARB                0x201D
+#define WGL_ACCUM_RED_BITS_ARB            0x201E
+#define WGL_ACCUM_GREEN_BITS_ARB          0x201F
+#define WGL_ACCUM_BLUE_BITS_ARB           0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB          0x2021
+#define WGL_DEPTH_BITS_ARB                0x2022
+#define WGL_STENCIL_BITS_ARB              0x2023
+#define WGL_AUX_BUFFERS_ARB               0x2024
+#define WGL_NO_ACCELERATION_ARB           0x2025
+#define WGL_GENERIC_ACCELERATION_ARB      0x2026
+#define WGL_FULL_ACCELERATION_ARB         0x2027
+#define WGL_SWAP_EXCHANGE_ARB             0x2028
+#define WGL_SWAP_COPY_ARB                 0x2029
+#define WGL_SWAP_UNDEFINED_ARB            0x202A
+#define WGL_TYPE_RGBA_ARB                 0x202B
+#define WGL_TYPE_COLORINDEX_ARB           0x202C
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglGetPixelFormatAttribivARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
+BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
+BOOL WINAPI wglChoosePixelFormatARB (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+#endif
+#endif /* WGL_ARB_pixel_format */
+
+#ifndef WGL_ARB_pixel_format_float
+#define WGL_ARB_pixel_format_float 1
+#define WGL_TYPE_RGBA_FLOAT_ARB           0x21A0
+#endif /* WGL_ARB_pixel_format_float */
+
+#ifndef WGL_ARB_render_texture
+#define WGL_ARB_render_texture 1
+#define WGL_BIND_TO_TEXTURE_RGB_ARB       0x2070
+#define WGL_BIND_TO_TEXTURE_RGBA_ARB      0x2071
+#define WGL_TEXTURE_FORMAT_ARB            0x2072
+#define WGL_TEXTURE_TARGET_ARB            0x2073
+#define WGL_MIPMAP_TEXTURE_ARB            0x2074
+#define WGL_TEXTURE_RGB_ARB               0x2075
+#define WGL_TEXTURE_RGBA_ARB              0x2076
+#define WGL_NO_TEXTURE_ARB                0x2077
+#define WGL_TEXTURE_CUBE_MAP_ARB          0x2078
+#define WGL_TEXTURE_1D_ARB                0x2079
+#define WGL_TEXTURE_2D_ARB                0x207A
+#define WGL_MIPMAP_LEVEL_ARB              0x207B
+#define WGL_CUBE_MAP_FACE_ARB             0x207C
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
+#define WGL_FRONT_LEFT_ARB                0x2083
+#define WGL_FRONT_RIGHT_ARB               0x2084
+#define WGL_BACK_LEFT_ARB                 0x2085
+#define WGL_BACK_RIGHT_ARB                0x2086
+#define WGL_AUX0_ARB                      0x2087
+#define WGL_AUX1_ARB                      0x2088
+#define WGL_AUX2_ARB                      0x2089
+#define WGL_AUX3_ARB                      0x208A
+#define WGL_AUX4_ARB                      0x208B
+#define WGL_AUX5_ARB                      0x208C
+#define WGL_AUX6_ARB                      0x208D
+#define WGL_AUX7_ARB                      0x208E
+#define WGL_AUX8_ARB                      0x208F
+#define WGL_AUX9_ARB                      0x2090
+typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer);
+BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer);
+BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB hPbuffer, const int *piAttribList);
+#endif
+#endif /* WGL_ARB_render_texture */
+
+#ifndef WGL_ARB_robustness_application_isolation
+#define WGL_ARB_robustness_application_isolation 1
+#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+#endif /* WGL_ARB_robustness_application_isolation */
+
+#ifndef WGL_ARB_robustness_share_group_isolation
+#define WGL_ARB_robustness_share_group_isolation 1
+#endif /* WGL_ARB_robustness_share_group_isolation */
+
+#ifndef WGL_3DFX_multisample
+#define WGL_3DFX_multisample 1
+#define WGL_SAMPLE_BUFFERS_3DFX           0x2060
+#define WGL_SAMPLES_3DFX                  0x2061
+#endif /* WGL_3DFX_multisample */
+
+#ifndef WGL_3DL_stereo_control
+#define WGL_3DL_stereo_control 1
+#define WGL_STEREO_EMITTER_ENABLE_3DL     0x2055
+#define WGL_STEREO_EMITTER_DISABLE_3DL    0x2056
+#define WGL_STEREO_POLARITY_NORMAL_3DL    0x2057
+#define WGL_STEREO_POLARITY_INVERT_3DL    0x2058
+typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglSetStereoEmitterState3DL (HDC hDC, UINT uState);
+#endif
+#endif /* WGL_3DL_stereo_control */
+
+#ifndef WGL_AMD_gpu_association
+#define WGL_AMD_gpu_association 1
+#define WGL_GPU_VENDOR_AMD                0x1F00
+#define WGL_GPU_RENDERER_STRING_AMD       0x1F01
+#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+#define WGL_GPU_FASTEST_TARGET_GPUS_AMD   0x21A2
+#define WGL_GPU_RAM_AMD                   0x21A3
+#define WGL_GPU_CLOCK_AMD                 0x21A4
+#define WGL_GPU_NUM_PIPES_AMD             0x21A5
+#define WGL_GPU_NUM_SIMD_AMD              0x21A6
+#define WGL_GPU_NUM_RB_AMD                0x21A7
+#define WGL_GPU_NUM_SPI_AMD               0x21A8
+typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT *ids);
+typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, int property, GLenum dataType, UINT size, void *data);
+typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc);
+typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id);
+typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int *attribList);
+typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc);
+typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc);
+typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void);
+typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#ifdef WGL_WGLEXT_PROTOTYPES
+UINT WINAPI wglGetGPUIDsAMD (UINT maxCount, UINT *ids);
+INT WINAPI wglGetGPUInfoAMD (UINT id, int property, GLenum dataType, UINT size, void *data);
+UINT WINAPI wglGetContextGPUIDAMD (HGLRC hglrc);
+HGLRC WINAPI wglCreateAssociatedContextAMD (UINT id);
+HGLRC WINAPI wglCreateAssociatedContextAttribsAMD (UINT id, HGLRC hShareContext, const int *attribList);
+BOOL WINAPI wglDeleteAssociatedContextAMD (HGLRC hglrc);
+BOOL WINAPI wglMakeAssociatedContextCurrentAMD (HGLRC hglrc);
+HGLRC WINAPI wglGetCurrentAssociatedContextAMD (void);
+VOID WINAPI wglBlitContextFramebufferAMD (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+#endif /* WGL_AMD_gpu_association */
+
+#ifndef WGL_ATI_pixel_format_float
+#define WGL_ATI_pixel_format_float 1
+#define WGL_TYPE_RGBA_FLOAT_ATI           0x21A0
+#endif /* WGL_ATI_pixel_format_float */
+
+#ifndef WGL_EXT_create_context_es2_profile
+#define WGL_EXT_create_context_es2_profile 1
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT   0x00000004
+#endif /* WGL_EXT_create_context_es2_profile */
+
+#ifndef WGL_EXT_create_context_es_profile
+#define WGL_EXT_create_context_es_profile 1
+#define WGL_CONTEXT_ES_PROFILE_BIT_EXT    0x00000004
+#endif /* WGL_EXT_create_context_es_profile */
+
+#ifndef WGL_EXT_depth_float
+#define WGL_EXT_depth_float 1
+#define WGL_DEPTH_FLOAT_EXT               0x2040
+#endif /* WGL_EXT_depth_float */
+
+#ifndef WGL_EXT_display_color_table
+#define WGL_EXT_display_color_table 1
+typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length);
+typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+#ifdef WGL_WGLEXT_PROTOTYPES
+GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort id);
+GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *table, GLuint length);
+GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort id);
+VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort id);
+#endif
+#endif /* WGL_EXT_display_color_table */
+
+#ifndef WGL_EXT_extensions_string
+#define WGL_EXT_extensions_string 1
+typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);
+#ifdef WGL_WGLEXT_PROTOTYPES
+const char *WINAPI wglGetExtensionsStringEXT (void);
+#endif
+#endif /* WGL_EXT_extensions_string */
+
+#ifndef WGL_EXT_framebuffer_sRGB
+#define WGL_EXT_framebuffer_sRGB 1
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT  0x20A9
+#endif /* WGL_EXT_framebuffer_sRGB */
+
+#ifndef WGL_EXT_make_current_read
+#define WGL_EXT_make_current_read 1
+#define ERROR_INVALID_PIXEL_TYPE_EXT      0x2043
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglMakeContextCurrentEXT (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+HDC WINAPI wglGetCurrentReadDCEXT (void);
+#endif
+#endif /* WGL_EXT_make_current_read */
+
+#ifndef WGL_EXT_multisample
+#define WGL_EXT_multisample 1
+#define WGL_SAMPLE_BUFFERS_EXT            0x2041
+#define WGL_SAMPLES_EXT                   0x2042
+#endif /* WGL_EXT_multisample */
+
+#ifndef WGL_EXT_pbuffer
+#define WGL_EXT_pbuffer 1
+DECLARE_HANDLE(HPBUFFEREXT);
+#define WGL_DRAW_TO_PBUFFER_EXT           0x202D
+#define WGL_MAX_PBUFFER_PIXELS_EXT        0x202E
+#define WGL_MAX_PBUFFER_WIDTH_EXT         0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_EXT        0x2030
+#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT     0x2031
+#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT    0x2032
+#define WGL_PBUFFER_LARGEST_EXT           0x2033
+#define WGL_PBUFFER_WIDTH_EXT             0x2034
+#define WGL_PBUFFER_HEIGHT_EXT            0x2035
+typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue);
+#ifdef WGL_WGLEXT_PROTOTYPES
+HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
+HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT hPbuffer);
+int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT hPbuffer, HDC hDC);
+BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT hPbuffer);
+BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue);
+#endif
+#endif /* WGL_EXT_pbuffer */
+
+#ifndef WGL_EXT_pixel_format
+#define WGL_EXT_pixel_format 1
+#define WGL_NUMBER_PIXEL_FORMATS_EXT      0x2000
+#define WGL_DRAW_TO_WINDOW_EXT            0x2001
+#define WGL_DRAW_TO_BITMAP_EXT            0x2002
+#define WGL_ACCELERATION_EXT              0x2003
+#define WGL_NEED_PALETTE_EXT              0x2004
+#define WGL_NEED_SYSTEM_PALETTE_EXT       0x2005
+#define WGL_SWAP_LAYER_BUFFERS_EXT        0x2006
+#define WGL_SWAP_METHOD_EXT               0x2007
+#define WGL_NUMBER_OVERLAYS_EXT           0x2008
+#define WGL_NUMBER_UNDERLAYS_EXT          0x2009
+#define WGL_TRANSPARENT_EXT               0x200A
+#define WGL_TRANSPARENT_VALUE_EXT         0x200B
+#define WGL_SHARE_DEPTH_EXT               0x200C
+#define WGL_SHARE_STENCIL_EXT             0x200D
+#define WGL_SHARE_ACCUM_EXT               0x200E
+#define WGL_SUPPORT_GDI_EXT               0x200F
+#define WGL_SUPPORT_OPENGL_EXT            0x2010
+#define WGL_DOUBLE_BUFFER_EXT             0x2011
+#define WGL_STEREO_EXT                    0x2012
+#define WGL_PIXEL_TYPE_EXT                0x2013
+#define WGL_COLOR_BITS_EXT                0x2014
+#define WGL_RED_BITS_EXT                  0x2015
+#define WGL_RED_SHIFT_EXT                 0x2016
+#define WGL_GREEN_BITS_EXT                0x2017
+#define WGL_GREEN_SHIFT_EXT               0x2018
+#define WGL_BLUE_BITS_EXT                 0x2019
+#define WGL_BLUE_SHIFT_EXT                0x201A
+#define WGL_ALPHA_BITS_EXT                0x201B
+#define WGL_ALPHA_SHIFT_EXT               0x201C
+#define WGL_ACCUM_BITS_EXT                0x201D
+#define WGL_ACCUM_RED_BITS_EXT            0x201E
+#define WGL_ACCUM_GREEN_BITS_EXT          0x201F
+#define WGL_ACCUM_BLUE_BITS_EXT           0x2020
+#define WGL_ACCUM_ALPHA_BITS_EXT          0x2021
+#define WGL_DEPTH_BITS_EXT                0x2022
+#define WGL_STENCIL_BITS_EXT              0x2023
+#define WGL_AUX_BUFFERS_EXT               0x2024
+#define WGL_NO_ACCELERATION_EXT           0x2025
+#define WGL_GENERIC_ACCELERATION_EXT      0x2026
+#define WGL_FULL_ACCELERATION_EXT         0x2027
+#define WGL_SWAP_EXCHANGE_EXT             0x2028
+#define WGL_SWAP_COPY_EXT                 0x2029
+#define WGL_SWAP_UNDEFINED_EXT            0x202A
+#define WGL_TYPE_RGBA_EXT                 0x202B
+#define WGL_TYPE_COLORINDEX_EXT           0x202C
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues);
+BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues);
+BOOL WINAPI wglChoosePixelFormatEXT (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+#endif
+#endif /* WGL_EXT_pixel_format */
+
+#ifndef WGL_EXT_pixel_format_packed_float
+#define WGL_EXT_pixel_format_packed_float 1
+#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT  0x20A8
+#endif /* WGL_EXT_pixel_format_packed_float */
+
+#ifndef WGL_EXT_swap_control
+#define WGL_EXT_swap_control 1
+typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
+typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglSwapIntervalEXT (int interval);
+int WINAPI wglGetSwapIntervalEXT (void);
+#endif
+#endif /* WGL_EXT_swap_control */
+
+#ifndef WGL_EXT_swap_control_tear
+#define WGL_EXT_swap_control_tear 1
+#endif /* WGL_EXT_swap_control_tear */
+
+#ifndef WGL_I3D_digital_video_control
+#define WGL_I3D_digital_video_control 1
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051
+#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052
+#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053
+typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);
+typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC hDC, int iAttribute, int *piValue);
+BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC hDC, int iAttribute, const int *piValue);
+#endif
+#endif /* WGL_I3D_digital_video_control */
+
+#ifndef WGL_I3D_gamma
+#define WGL_I3D_gamma 1
+#define WGL_GAMMA_TABLE_SIZE_I3D          0x204E
+#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D     0x204F
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglGetGammaTableParametersI3D (HDC hDC, int iAttribute, int *piValue);
+BOOL WINAPI wglSetGammaTableParametersI3D (HDC hDC, int iAttribute, const int *piValue);
+BOOL WINAPI wglGetGammaTableI3D (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue);
+BOOL WINAPI wglSetGammaTableI3D (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue);
+#endif
+#endif /* WGL_I3D_gamma */
+
+#ifndef WGL_I3D_genlock
+#define WGL_I3D_genlock 1
+#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D  0x2044
+#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045
+#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046
+#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047
+#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
+#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
+#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
+#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
+#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D  0x204C
+typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay);
+typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglEnableGenlockI3D (HDC hDC);
+BOOL WINAPI wglDisableGenlockI3D (HDC hDC);
+BOOL WINAPI wglIsEnabledGenlockI3D (HDC hDC, BOOL *pFlag);
+BOOL WINAPI wglGenlockSourceI3D (HDC hDC, UINT uSource);
+BOOL WINAPI wglGetGenlockSourceI3D (HDC hDC, UINT *uSource);
+BOOL WINAPI wglGenlockSourceEdgeI3D (HDC hDC, UINT uEdge);
+BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC hDC, UINT *uEdge);
+BOOL WINAPI wglGenlockSampleRateI3D (HDC hDC, UINT uRate);
+BOOL WINAPI wglGetGenlockSampleRateI3D (HDC hDC, UINT *uRate);
+BOOL WINAPI wglGenlockSourceDelayI3D (HDC hDC, UINT uDelay);
+BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC hDC, UINT *uDelay);
+BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay);
+#endif
+#endif /* WGL_I3D_genlock */
+
+#ifndef WGL_I3D_image_buffer
+#define WGL_I3D_image_buffer 1
+#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D   0x00000001
+#define WGL_IMAGE_BUFFER_LOCK_I3D         0x00000002
+typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags);
+typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress);
+typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count);
+typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count);
+#ifdef WGL_WGLEXT_PROTOTYPES
+LPVOID WINAPI wglCreateImageBufferI3D (HDC hDC, DWORD dwSize, UINT uFlags);
+BOOL WINAPI wglDestroyImageBufferI3D (HDC hDC, LPVOID pAddress);
+BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count);
+BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC hDC, const LPVOID *pAddress, UINT count);
+#endif
+#endif /* WGL_I3D_image_buffer */
+
+#ifndef WGL_I3D_swap_frame_lock
+#define WGL_I3D_swap_frame_lock 1
+typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglEnableFrameLockI3D (void);
+BOOL WINAPI wglDisableFrameLockI3D (void);
+BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *pFlag);
+BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *pFlag);
+#endif
+#endif /* WGL_I3D_swap_frame_lock */
+
+#ifndef WGL_I3D_swap_frame_usage
+#define WGL_I3D_swap_frame_usage 1
+typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage);
+typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglGetFrameUsageI3D (float *pUsage);
+BOOL WINAPI wglBeginFrameTrackingI3D (void);
+BOOL WINAPI wglEndFrameTrackingI3D (void);
+BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
+#endif
+#endif /* WGL_I3D_swap_frame_usage */
+
+#ifndef WGL_NV_DX_interop
+#define WGL_NV_DX_interop 1
+#define WGL_ACCESS_READ_ONLY_NV           0x00000000
+#define WGL_ACCESS_READ_WRITE_NV          0x00000001
+#define WGL_ACCESS_WRITE_DISCARD_NV       0x00000002
+typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void *dxObject, HANDLE shareHandle);
+typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void *dxDevice);
+typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice);
+typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
+typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject);
+typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access);
+typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);
+typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglDXSetResourceShareHandleNV (void *dxObject, HANDLE shareHandle);
+HANDLE WINAPI wglDXOpenDeviceNV (void *dxDevice);
+BOOL WINAPI wglDXCloseDeviceNV (HANDLE hDevice);
+HANDLE WINAPI wglDXRegisterObjectNV (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
+BOOL WINAPI wglDXUnregisterObjectNV (HANDLE hDevice, HANDLE hObject);
+BOOL WINAPI wglDXObjectAccessNV (HANDLE hObject, GLenum access);
+BOOL WINAPI wglDXLockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects);
+BOOL WINAPI wglDXUnlockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects);
+#endif
+#endif /* WGL_NV_DX_interop */
+
+#ifndef WGL_NV_DX_interop2
+#define WGL_NV_DX_interop2 1
+#endif /* WGL_NV_DX_interop2 */
+
+#ifndef WGL_NV_copy_image
+#define WGL_NV_copy_image 1
+typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglCopyImageSubDataNV (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+#endif /* WGL_NV_copy_image */
+
+#ifndef WGL_NV_delay_before_swap
+#define WGL_NV_delay_before_swap 1
+typedef BOOL (WINAPI * PFNWGLDELAYBEFORESWAPNVPROC) (HDC hDC, GLfloat seconds);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglDelayBeforeSwapNV (HDC hDC, GLfloat seconds);
+#endif
+#endif /* WGL_NV_delay_before_swap */
+
+#ifndef WGL_NV_float_buffer
+#define WGL_NV_float_buffer 1
+#define WGL_FLOAT_COMPONENTS_NV           0x20B0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
+#define WGL_TEXTURE_FLOAT_R_NV            0x20B5
+#define WGL_TEXTURE_FLOAT_RG_NV           0x20B6
+#define WGL_TEXTURE_FLOAT_RGB_NV          0x20B7
+#define WGL_TEXTURE_FLOAT_RGBA_NV         0x20B8
+#endif /* WGL_NV_float_buffer */
+
+#ifndef WGL_NV_gpu_affinity
+#define WGL_NV_gpu_affinity 1
+DECLARE_HANDLE(HGPUNV);
+struct _GPU_DEVICE {
+    DWORD  cb;
+    CHAR   DeviceName[32];
+    CHAR   DeviceString[128];
+    DWORD  Flags;
+    RECT   rcVirtualScreen;
+};
+typedef struct _GPU_DEVICE *PGPU_DEVICE;
+#define ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0
+#define ERROR_MISSING_AFFINITY_MASK_NV    0x20D1
+typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu);
+typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
+typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList);
+typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu);
+typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglEnumGpusNV (UINT iGpuIndex, HGPUNV *phGpu);
+BOOL WINAPI wglEnumGpuDevicesNV (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
+HDC WINAPI wglCreateAffinityDCNV (const HGPUNV *phGpuList);
+BOOL WINAPI wglEnumGpusFromAffinityDCNV (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu);
+BOOL WINAPI wglDeleteDCNV (HDC hdc);
+#endif
+#endif /* WGL_NV_gpu_affinity */
+
+#ifndef WGL_NV_multisample_coverage
+#define WGL_NV_multisample_coverage 1
+#define WGL_COVERAGE_SAMPLES_NV           0x2042
+#define WGL_COLOR_SAMPLES_NV              0x20B9
+#endif /* WGL_NV_multisample_coverage */
+
+#ifndef WGL_NV_present_video
+#define WGL_NV_present_video 1
+DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);
+#define WGL_NUM_VIDEO_SLOTS_NV            0x20F0
+typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);
+typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList);
+typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue);
+#ifdef WGL_WGLEXT_PROTOTYPES
+int WINAPI wglEnumerateVideoDevicesNV (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);
+BOOL WINAPI wglBindVideoDeviceNV (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList);
+BOOL WINAPI wglQueryCurrentContextNV (int iAttribute, int *piValue);
+#endif
+#endif /* WGL_NV_present_video */
+
+#ifndef WGL_NV_render_depth_texture
+#define WGL_NV_render_depth_texture 1
+#define WGL_BIND_TO_TEXTURE_DEPTH_NV      0x20A3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
+#define WGL_DEPTH_TEXTURE_FORMAT_NV       0x20A5
+#define WGL_TEXTURE_DEPTH_COMPONENT_NV    0x20A6
+#define WGL_DEPTH_COMPONENT_NV            0x20A7
+#endif /* WGL_NV_render_depth_texture */
+
+#ifndef WGL_NV_render_texture_rectangle
+#define WGL_NV_render_texture_rectangle 1
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
+#define WGL_TEXTURE_RECTANGLE_NV          0x20A2
+#endif /* WGL_NV_render_texture_rectangle */
+
+#ifndef WGL_NV_swap_group
+#define WGL_NV_swap_group 1
+typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group);
+typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier);
+typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier);
+typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count);
+typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglJoinSwapGroupNV (HDC hDC, GLuint group);
+BOOL WINAPI wglBindSwapBarrierNV (GLuint group, GLuint barrier);
+BOOL WINAPI wglQuerySwapGroupNV (HDC hDC, GLuint *group, GLuint *barrier);
+BOOL WINAPI wglQueryMaxSwapGroupsNV (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers);
+BOOL WINAPI wglQueryFrameCountNV (HDC hDC, GLuint *count);
+BOOL WINAPI wglResetFrameCountNV (HDC hDC);
+#endif
+#endif /* WGL_NV_swap_group */
+
+#ifndef WGL_NV_vertex_array_range
+#define WGL_NV_vertex_array_range 1
+typedef void *(WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
+typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer);
+#ifdef WGL_WGLEXT_PROTOTYPES
+void *WINAPI wglAllocateMemoryNV (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
+void WINAPI wglFreeMemoryNV (void *pointer);
+#endif
+#endif /* WGL_NV_vertex_array_range */
+
+#ifndef WGL_NV_video_capture
+#define WGL_NV_video_capture 1
+DECLARE_HANDLE(HVIDEOINPUTDEVICENV);
+#define WGL_UNIQUE_ID_NV                  0x20CE
+#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV    0x20CF
+typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
+typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList);
+typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglBindVideoCaptureDeviceNV (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
+UINT WINAPI wglEnumerateVideoCaptureDevicesNV (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList);
+BOOL WINAPI wglLockVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+BOOL WINAPI wglQueryVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue);
+BOOL WINAPI wglReleaseVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+#endif
+#endif /* WGL_NV_video_capture */
+
+#ifndef WGL_NV_video_output
+#define WGL_NV_video_output 1
+DECLARE_HANDLE(HPVIDEODEV);
+#define WGL_BIND_TO_VIDEO_RGB_NV          0x20C0
+#define WGL_BIND_TO_VIDEO_RGBA_NV         0x20C1
+#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2
+#define WGL_VIDEO_OUT_COLOR_NV            0x20C3
+#define WGL_VIDEO_OUT_ALPHA_NV            0x20C4
+#define WGL_VIDEO_OUT_DEPTH_NV            0x20C5
+#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV  0x20C6
+#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV  0x20C7
+#define WGL_VIDEO_OUT_FRAME               0x20C8
+#define WGL_VIDEO_OUT_FIELD_1             0x20C9
+#define WGL_VIDEO_OUT_FIELD_2             0x20CA
+#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2  0x20CB
+#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1  0x20CC
+typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice);
+typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer);
+typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock);
+typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglGetVideoDeviceNV (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice);
+BOOL WINAPI wglReleaseVideoDeviceNV (HPVIDEODEV hVideoDevice);
+BOOL WINAPI wglBindVideoImageNV (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
+BOOL WINAPI wglReleaseVideoImageNV (HPBUFFERARB hPbuffer, int iVideoBuffer);
+BOOL WINAPI wglSendPbufferToVideoNV (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock);
+BOOL WINAPI wglGetVideoInfoNV (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
+#endif
+#endif /* WGL_NV_video_output */
+
+#ifndef WGL_OML_sync_control
+#define WGL_OML_sync_control 1
+typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);
+typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator);
+typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);
+typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);
+#ifdef WGL_WGLEXT_PROTOTYPES
+BOOL WINAPI wglGetSyncValuesOML (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);
+BOOL WINAPI wglGetMscRateOML (HDC hdc, INT32 *numerator, INT32 *denominator);
+INT64 WINAPI wglSwapBuffersMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
+INT64 WINAPI wglSwapLayerBuffersMscOML (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
+BOOL WINAPI wglWaitForMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);
+BOOL WINAPI wglWaitForSbcOML (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);
+#endif
+#endif /* WGL_OML_sync_control */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/third_party/angle/src/third_party/libXNVCtrl/BUILD.gn b/src/third_party/angle/src/third_party/libXNVCtrl/BUILD.gn
new file mode 100644
index 0000000..b58a542
--- /dev/null
+++ b/src/third_party/angle/src/third_party/libXNVCtrl/BUILD.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2016 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.
+
+# This warning disable must be appended to the command line after the general
+# warnings setup, so must be in a config.
+config("libXNVCtrl_config") {
+  # This will build under most configurations with this warning enabled, but
+  # some older system headers are missing a "const" on the third parameter of
+  # XextAddDisplay which will cause a failure.
+  cflags = [
+    "-Wno-incompatible-pointer-types-discards-qualifiers",
+  ]
+}
+
+source_set("libXNVCtrl") {
+  sources = [
+    "NVCtrl.c",
+    "NVCtrl.h",
+    "NVCtrlLib.h",
+    "nv_control.h",
+  ]
+
+  configs += [
+    ":libXNVCtrl_config",
+    "//build/config/linux:x11",
+  ]
+}
diff --git a/src/third_party/angle/src/third_party/libXNVCtrl/LICENSE b/src/third_party/angle/src/third_party/libXNVCtrl/LICENSE
new file mode 100644
index 0000000..74324c0
--- /dev/null
+++ b/src/third_party/angle/src/third_party/libXNVCtrl/LICENSE
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2008 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
\ No newline at end of file
diff --git a/src/third_party/angle/src/third_party/libXNVCtrl/NVCtrl.c b/src/third_party/angle/src/third_party/libXNVCtrl/NVCtrl.c
new file mode 100644
index 0000000..e984373
--- /dev/null
+++ b/src/third_party/angle/src/third_party/libXNVCtrl/NVCtrl.c
@@ -0,0 +1,1240 @@
+/*
+ * Copyright (c) 2008 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Make sure that XTHREADS is defined, so that the
+ * LockDisplay/UnlockDisplay macros are expanded properly and the
+ * libXNVCtrl library properly protects the Display connection.
+ */
+
+#if !defined(XTHREADS)
+#define XTHREADS
+#endif /* XTHREADS */
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <stdint.h>
+#include <stdlib.h>
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include "NVCtrlLib.h"
+#include "nv_control.h"
+
+#define NVCTRL_EXT_EXISTS              1
+#define NVCTRL_EXT_NEED_TARGET_SWAP    2
+#define NVCTRL_EXT_64_BIT_ATTRIBUTES   4
+#define NVCTRL_EXT_NEED_CHECK          (1 << (sizeof(XPointer) - 1))
+
+static XExtensionInfo _nvctrl_ext_info_data;
+static XExtensionInfo *nvctrl_ext_info = &_nvctrl_ext_info_data;
+static const char *nvctrl_extension_name = NV_CONTROL_NAME;
+
+#define XNVCTRLCheckExtension(dpy,i,val) \
+  XextCheckExtension (dpy, i, nvctrl_extension_name, val)
+#define XNVCTRLSimpleCheckExtension(dpy,i) \
+  XextSimpleCheckExtension (dpy, i, nvctrl_extension_name)
+
+static int close_display();
+static uintptr_t version_flags(Display *dpy, XExtDisplayInfo *info);
+static Bool wire_to_event();
+static /* const */ XExtensionHooks nvctrl_extension_hooks = {
+    NULL,                               /* create_gc */
+    NULL,                               /* copy_gc */
+    NULL,                               /* flush_gc */
+    NULL,                               /* free_gc */
+    NULL,                               /* create_font */
+    NULL,                               /* free_font */
+    close_display,                      /* close_display */
+    wire_to_event,                      /* wire_to_event */
+    NULL,                               /* event_to_wire */
+    NULL,                               /* error */
+    NULL,                               /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (find_display, nvctrl_ext_info,
+                                   nvctrl_extension_name,
+                                   &nvctrl_extension_hooks,
+                                   NV_CONTROL_EVENTS,
+                                   (XPointer)NVCTRL_EXT_NEED_CHECK)
+
+static XEXT_GENERATE_CLOSE_DISPLAY (close_display, nvctrl_ext_info)
+
+/*
+ * NV-CONTROL versions 1.8 and 1.9 pack the target_type and target_id
+ * fields in reversed order.  In order to talk to one of these servers,
+ * we need to swap these fields.
+ */
+
+static void XNVCTRLCheckTargetData(Display *dpy, XExtDisplayInfo *info,
+                                   int *target_type, int *target_id)
+{
+    uintptr_t flags = version_flags(dpy, info);
+
+    /* We need to swap the target_type and target_id */
+    if (flags & NVCTRL_EXT_NEED_TARGET_SWAP) {
+        int tmp;
+        tmp = *target_type;
+        *target_type = *target_id;
+        *target_id = tmp;
+    }
+}
+
+
+Bool XNVCTRLQueryExtension (
+    Display *dpy,
+    int *event_basep,
+    int *error_basep
+){
+    XExtDisplayInfo *info = find_display (dpy);
+
+    if (XextHasExtension(info)) {
+        if (event_basep) *event_basep = info->codes->first_event;
+        if (error_basep) *error_basep = info->codes->first_error;
+        return True;
+    } else {
+        return False;
+    }
+}
+
+/*
+ * Retrieve any cached flags that depend on the version of the NV-CONTROL
+ * extension.
+ */
+
+static uintptr_t version_flags(Display *dpy, XExtDisplayInfo *info)
+{
+    uintptr_t data = (uintptr_t)info->data;
+
+    /* If necessary, determine the NV-CONTROL version */
+    if (data & NVCTRL_EXT_NEED_CHECK) {
+        int major, minor;
+        data = 0;
+        if (XNVCTRLQueryVersion(dpy, &major, &minor)) {
+            data |= NVCTRL_EXT_EXISTS;
+            if (major == 1 && (minor == 8 || minor == 9)) {
+                data |= NVCTRL_EXT_NEED_TARGET_SWAP;
+            }
+            if ((major > 1) || ((major == 1) && (minor > 20))) {
+                data |= NVCTRL_EXT_64_BIT_ATTRIBUTES;
+            }
+        }
+
+        info->data = (XPointer)data;
+    }
+
+    return data;
+}
+
+Bool XNVCTRLQueryVersion (
+    Display *dpy,
+    int *major,
+    int *minor
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlQueryExtensionReply rep;
+    xnvCtrlQueryExtensionReq   *req;
+
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlQueryExtension, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryExtension;
+    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+    if (major) *major = rep.major;
+    if (minor) *minor = rep.minor;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+    return True;
+}
+
+
+Bool XNVCTRLIsNvScreen (
+    Display *dpy,
+    int screen
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlIsNvReply rep;
+    xnvCtrlIsNvReq   *req;
+    Bool isnv;
+
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlIsNv, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlIsNv;
+    req->screen = screen;
+    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+    isnv = rep.isnv;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+    return isnv;
+}
+
+
+Bool XNVCTRLQueryTargetCount (
+    Display *dpy,
+    int target_type,
+    int *value
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlQueryTargetCountReply  rep;
+    xnvCtrlQueryTargetCountReq   *req;
+
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlQueryTargetCount, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryTargetCount;
+    req->target_type = target_type;
+    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+    if (value) *value = rep.count;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+    return True;
+}
+
+
+void XNVCTRLSetTargetAttribute (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    int value
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlSetAttributeReq *req;
+
+    XNVCTRLSimpleCheckExtension (dpy, info);
+    XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlSetAttribute, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlSetAttribute;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    req->value = value;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+}
+
+void XNVCTRLSetAttribute (
+    Display *dpy,
+    int screen,
+    unsigned int display_mask,
+    unsigned int attribute,
+    int value
+){
+    XNVCTRLSetTargetAttribute (dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen,
+                               display_mask, attribute, value);
+}
+
+
+Bool XNVCTRLSetTargetAttributeAndGetStatus (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    int value
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlSetAttributeAndGetStatusReq *req;
+    xnvCtrlSetAttributeAndGetStatusReply rep;
+    Bool success;
+
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlSetAttributeAndGetStatus, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlSetAttributeAndGetStatus;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    req->value = value;
+    if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+    UnlockDisplay (dpy);
+    SyncHandle ();
+    
+    success = rep.flags;
+    return success;
+}
+
+Bool XNVCTRLSetAttributeAndGetStatus (
+    Display *dpy,
+    int screen,
+    unsigned int display_mask,
+    unsigned int attribute,
+    int value
+){
+    return XNVCTRLSetTargetAttributeAndGetStatus(dpy,
+                                                 NV_CTRL_TARGET_TYPE_X_SCREEN,
+                                                 screen, display_mask,
+                                                 attribute, value);
+}
+
+
+Bool XNVCTRLQueryTargetAttribute (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    int *value
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlQueryAttributeReply rep;
+    xnvCtrlQueryAttributeReq   *req;
+    Bool exists;
+
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+    XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlQueryAttribute, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryAttribute;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+    exists = rep.flags;
+    if (exists && value) *value = rep.value;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+    return exists;
+}
+
+Bool XNVCTRLQueryAttribute (
+    Display *dpy,
+    int screen,
+    unsigned int display_mask,
+    unsigned int attribute,
+    int *value
+){
+    return XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
+                                       screen, display_mask, attribute, value);
+}
+
+
+Bool XNVCTRLQueryTargetAttribute64 (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    int64_t *value
+){
+    XExtDisplayInfo *info = find_display(dpy);
+    xnvCtrlQueryAttribute64Reply rep;
+    xnvCtrlQueryAttributeReq *req;
+    Bool exists;
+
+    if (!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension(dpy, info, False);
+    XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+    LockDisplay(dpy);
+    GetReq(nvCtrlQueryAttribute, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryAttribute64;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xTrue)) {
+        UnlockDisplay(dpy);
+        SyncHandle();
+        return False;
+    }
+    exists = rep.flags;
+    if (exists && value) *value = rep.value_64;
+    UnlockDisplay(dpy);
+    SyncHandle();
+    return exists;
+}
+
+
+Bool XNVCTRLQueryTargetStringAttribute (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    char **ptr
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlQueryStringAttributeReply rep;
+    xnvCtrlQueryStringAttributeReq   *req;
+    Bool exists;
+    int length, numbytes, slop;
+
+    if (!ptr) return False;
+
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+    XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlQueryStringAttribute, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryStringAttribute;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+    length = rep.length;
+    numbytes = rep.n;
+    slop = numbytes & 3;
+    exists = rep.flags;
+    if (exists) {
+        *ptr = (char *) Xmalloc(numbytes);
+    }
+    if (!exists || !*ptr) {
+        _XEatData(dpy, length);
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    } else {
+        _XRead(dpy, (char *) *ptr, numbytes);
+        if (slop) _XEatData(dpy, 4-slop);
+    }
+    UnlockDisplay (dpy);
+    SyncHandle ();
+    return exists;
+}
+
+Bool XNVCTRLQueryStringAttribute (
+    Display *dpy,
+    int screen,
+    unsigned int display_mask,
+    unsigned int attribute,
+    char **ptr
+){
+    return XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
+                                             screen, display_mask,
+                                             attribute, ptr);
+}
+
+
+Bool XNVCTRLSetTargetStringAttribute (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    char *ptr
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlSetStringAttributeReq *req;
+    xnvCtrlSetStringAttributeReply rep;
+    int size;
+    Bool success;
+    
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+
+    size = strlen(ptr)+1;
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlSetStringAttribute, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlSetStringAttribute;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    req->length += ((size + 3) & ~3) >> 2;
+    req->num_bytes = size;
+    Data(dpy, ptr, size);
+    
+    if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+    UnlockDisplay (dpy);
+    SyncHandle ();
+    
+    success = rep.flags;
+    return success;
+}
+
+Bool XNVCTRLSetStringAttribute (
+    Display *dpy,
+    int screen,
+    unsigned int display_mask,
+    unsigned int attribute,
+    char *ptr
+){
+    return XNVCTRLSetTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
+                                           screen, display_mask,
+                                           attribute, ptr);
+}
+
+
+static Bool XNVCTRLQueryValidTargetAttributeValues32 (
+    Display *dpy,
+    XExtDisplayInfo *info,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,                                 
+    NVCTRLAttributeValidValuesRec *values
+){
+    xnvCtrlQueryValidAttributeValuesReply rep;
+    xnvCtrlQueryValidAttributeValuesReq   *req;
+    Bool exists;
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlQueryValidAttributeValues, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryValidAttributeValues;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+    exists = rep.flags;
+    if (exists) {
+        values->type = rep.attr_type;
+        if (rep.attr_type == ATTRIBUTE_TYPE_RANGE) {
+            values->u.range.min = rep.min;
+            values->u.range.max = rep.max;
+        }
+        if (rep.attr_type == ATTRIBUTE_TYPE_INT_BITS) {
+            values->u.bits.ints = rep.bits;
+        }
+        values->permissions = rep.perms;
+    }
+    UnlockDisplay (dpy);
+    SyncHandle ();
+    return exists;
+}
+
+
+Bool XNVCTRLQueryValidTargetStringAttributeValues (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    NVCTRLAttributeValidValuesRec *values
+){
+    XExtDisplayInfo *info = find_display(dpy);
+    Bool exists;
+    xnvCtrlQueryValidAttributeValuesReply rep;
+    xnvCtrlQueryValidAttributeValuesReq   *req;
+
+    if (!values) return False;
+
+    if (!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension(dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq (nvCtrlQueryValidAttributeValues, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryValidStringAttributeValues;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xTrue)) {
+        UnlockDisplay(dpy);
+        SyncHandle();
+        return False;
+    }
+    exists = rep.flags;
+    if (exists) {
+        values->type = rep.attr_type;
+        values->permissions = rep.perms;
+    }
+    UnlockDisplay(dpy);
+    SyncHandle();
+    return exists;
+}
+
+
+static Bool XNVCTRLQueryValidTargetAttributeValues64 (
+    Display *dpy,
+    XExtDisplayInfo *info,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    NVCTRLAttributeValidValuesRec *values
+){
+    xnvCtrlQueryValidAttributeValues64Reply rep;
+    xnvCtrlQueryValidAttributeValuesReq *req;
+    Bool exists;
+
+    LockDisplay(dpy);
+    GetReq(nvCtrlQueryValidAttributeValues, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryValidAttributeValues64;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    if (!_XReply(dpy, (xReply *)&rep,
+                 sz_xnvCtrlQueryValidAttributeValues64Reply_extra,
+                 xTrue)) {
+        UnlockDisplay(dpy);
+        SyncHandle();
+        return False;
+    }
+    exists = rep.flags;
+    if (exists) {
+        values->type = rep.attr_type;
+        if (rep.attr_type == ATTRIBUTE_TYPE_RANGE) {
+            values->u.range.min = rep.min_64;
+            values->u.range.max = rep.max_64;
+        }
+        if (rep.attr_type == ATTRIBUTE_TYPE_INT_BITS) {
+            values->u.bits.ints = rep.bits_64;
+        }
+        values->permissions = rep.perms;
+    }
+    UnlockDisplay(dpy);
+    SyncHandle();
+    return exists;
+}
+
+Bool XNVCTRLQueryValidTargetAttributeValues (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    NVCTRLAttributeValidValuesRec *values
+){
+    XExtDisplayInfo *info = find_display(dpy);
+    Bool exists;
+    uintptr_t flags;
+
+    if (!values) return False;
+
+    if (!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension(dpy, info, False);
+    XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+    flags = version_flags(dpy,info);
+
+    if (!(flags & NVCTRL_EXT_EXISTS))
+        return False;
+
+    if (flags & NVCTRL_EXT_64_BIT_ATTRIBUTES) {
+        exists = XNVCTRLQueryValidTargetAttributeValues64(dpy, info,
+                                                          target_type,
+                                                          target_id,
+                                                          display_mask,
+                                                          attribute,
+                                                          values);
+    } else {
+        exists = XNVCTRLQueryValidTargetAttributeValues32(dpy, info,
+                                                          target_type,
+                                                          target_id,
+                                                          display_mask,
+                                                          attribute,
+                                                          values);
+    }
+    return exists;
+}
+
+
+Bool XNVCTRLQueryValidAttributeValues (
+    Display *dpy,
+    int screen,
+    unsigned int display_mask,
+    unsigned int attribute,
+    NVCTRLAttributeValidValuesRec *values
+){
+    return XNVCTRLQueryValidTargetAttributeValues(dpy,
+                                                  NV_CTRL_TARGET_TYPE_X_SCREEN,
+                                                  screen, display_mask,
+                                                  attribute, values);
+}
+
+
+static Bool QueryAttributePermissionsInternal (
+    Display *dpy,
+    unsigned int attribute,
+    NVCTRLAttributePermissionsRec *permissions,
+    unsigned int reqType
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlQueryAttributePermissionsReply rep;
+    xnvCtrlQueryAttributePermissionsReq *req;
+    Bool exists;
+
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(nvCtrlQueryAttributePermissions, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = reqType;
+    req->attribute = attribute;
+    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+        UnlockDisplay (dpy);
+        SyncHandle();
+        return False;
+    }
+    exists = rep.flags;
+    if (exists && permissions) {
+        permissions->type = rep.attr_type;
+        permissions->permissions = rep.perms;
+    }
+    UnlockDisplay(dpy);
+    SyncHandle();
+    return exists;
+}
+
+
+Bool XNVCTRLQueryAttributePermissions (
+    Display *dpy,
+    unsigned int attribute,
+    NVCTRLAttributePermissionsRec *permissions
+){
+    return QueryAttributePermissionsInternal(dpy,
+                                             attribute,
+                                             permissions,
+                                             X_nvCtrlQueryAttributePermissions);
+}
+
+
+Bool XNVCTRLQueryStringAttributePermissions (
+    Display *dpy,
+    unsigned int attribute,
+    NVCTRLAttributePermissionsRec *permissions
+){
+    return QueryAttributePermissionsInternal(dpy,
+                                             attribute,
+                                             permissions,
+                                             X_nvCtrlQueryStringAttributePermissions);
+}
+
+
+Bool XNVCTRLQueryBinaryDataAttributePermissions (
+    Display *dpy,
+    unsigned int attribute,
+    NVCTRLAttributePermissionsRec *permissions
+){
+    return QueryAttributePermissionsInternal(dpy,
+                                             attribute,
+                                             permissions,
+                                             X_nvCtrlQueryBinaryDataAttributePermissions);
+}
+
+
+Bool XNVCTRLQueryStringOperationAttributePermissions (
+    Display *dpy,
+    unsigned int attribute,
+    NVCTRLAttributePermissionsRec *permissions
+){
+    return QueryAttributePermissionsInternal(dpy,
+                                             attribute,
+                                             permissions,
+                                             X_nvCtrlQueryStringOperationAttributePermissions);
+}
+
+
+void XNVCTRLSetGvoColorConversion (
+    Display *dpy,
+    int screen,
+    float colorMatrix[3][3],
+    float colorOffset[3],
+    float colorScale[3]
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlSetGvoColorConversionReq *req;
+
+    XNVCTRLSimpleCheckExtension (dpy, info);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlSetGvoColorConversion, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlSetGvoColorConversion;
+    req->screen = screen;
+
+    req->cscMatrix_y_r = colorMatrix[0][0];
+    req->cscMatrix_y_g = colorMatrix[0][1];
+    req->cscMatrix_y_b = colorMatrix[0][2];
+
+    req->cscMatrix_cr_r = colorMatrix[1][0];
+    req->cscMatrix_cr_g = colorMatrix[1][1];
+    req->cscMatrix_cr_b = colorMatrix[1][2];
+
+    req->cscMatrix_cb_r = colorMatrix[2][0];
+    req->cscMatrix_cb_g = colorMatrix[2][1];
+    req->cscMatrix_cb_b = colorMatrix[2][2];
+
+    req->cscOffset_y  = colorOffset[0];
+    req->cscOffset_cr = colorOffset[1];
+    req->cscOffset_cb = colorOffset[2];
+
+    req->cscScale_y  = colorScale[0];
+    req->cscScale_cr = colorScale[1];
+    req->cscScale_cb = colorScale[2];
+
+    UnlockDisplay (dpy);
+    SyncHandle ();
+}
+
+
+Bool XNVCTRLQueryGvoColorConversion (
+    Display *dpy,
+    int screen,
+    float colorMatrix[3][3],
+    float colorOffset[3],
+    float colorScale[3]
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlQueryGvoColorConversionReply rep;
+    xnvCtrlQueryGvoColorConversionReq *req;
+
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+
+    LockDisplay (dpy);
+
+    GetReq (nvCtrlQueryGvoColorConversion, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryGvoColorConversion;
+    req->screen = screen;
+
+    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+
+    _XRead(dpy, (char *)(colorMatrix), 36);
+    _XRead(dpy, (char *)(colorOffset), 12);
+    _XRead(dpy, (char *)(colorScale), 12);
+
+    UnlockDisplay (dpy);
+    SyncHandle ();
+
+    return True;
+}
+
+
+Bool XNVCtrlSelectTargetNotify (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    int notify_type,
+    Bool onoff
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlSelectTargetNotifyReq *req;
+
+    if(!XextHasExtension (info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlSelectTargetNotify, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlSelectTargetNotify;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->notifyType = notify_type;
+    req->onoff = onoff;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+
+    return True;
+}
+
+
+Bool XNVCtrlSelectNotify (
+    Display *dpy,
+    int screen,
+    int type,
+    Bool onoff
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlSelectNotifyReq *req;
+
+    if(!XextHasExtension (info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlSelectNotify, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlSelectNotify;
+    req->screen = screen;
+    req->notifyType = type;
+    req->onoff = onoff;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+
+    return True;
+}
+
+Bool XNVCTRLQueryTargetBinaryData (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    unsigned char **ptr,
+    int *len
+){
+    XExtDisplayInfo *info = find_display (dpy);
+    xnvCtrlQueryBinaryDataReply rep;
+    xnvCtrlQueryBinaryDataReq   *req;
+    Bool exists;
+    int length, numbytes, slop;
+
+    if (!ptr) return False;
+
+    if(!XextHasExtension(info))
+        return False;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+    XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+    LockDisplay (dpy);
+    GetReq (nvCtrlQueryBinaryData, req);
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlQueryBinaryData;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+    if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    }
+    length = rep.length;
+    numbytes = rep.n;
+    slop = numbytes & 3;
+    exists = rep.flags;
+    if (exists) {
+        *ptr = (unsigned char *) Xmalloc(numbytes);
+    }
+    if (!exists || !*ptr) {
+        _XEatData(dpy, length);
+        UnlockDisplay (dpy);
+        SyncHandle ();
+        return False;
+    } else {
+        _XRead(dpy, (char *) *ptr, numbytes);
+        if (slop) _XEatData(dpy, 4-slop);
+    }
+    if (len) *len = numbytes;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+    return exists;
+}
+
+Bool XNVCTRLQueryBinaryData (
+    Display *dpy,
+    int screen,
+    unsigned int display_mask,
+    unsigned int attribute,
+    unsigned char **ptr,
+    int *len
+){
+    return XNVCTRLQueryTargetBinaryData(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
+                                        screen, display_mask,
+                                        attribute, ptr, len);
+}
+
+Bool XNVCTRLStringOperation (
+    Display *dpy,
+    int target_type,
+    int target_id,
+    unsigned int display_mask,
+    unsigned int attribute,
+    char *pIn,
+    char **ppOut
+) {
+    XExtDisplayInfo *info = find_display(dpy);
+    xnvCtrlStringOperationReq *req;
+    xnvCtrlStringOperationReply rep;
+    Bool ret;
+    int inSize, outSize, length, slop;
+
+    if (!XextHasExtension(info))
+        return False;
+    
+    if (!ppOut)
+        return False;
+
+    *ppOut = NULL;
+    
+    XNVCTRLCheckExtension(dpy, info, False);
+    XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+    
+    if (pIn) {
+        inSize = strlen(pIn) + 1;
+    } else {
+        inSize = 0;
+    }
+    
+    LockDisplay(dpy);
+    GetReq(nvCtrlStringOperation, req);
+    
+    req->reqType = info->codes->major_opcode;
+    req->nvReqType = X_nvCtrlStringOperation;
+    req->target_type = target_type;
+    req->target_id = target_id;
+    req->display_mask = display_mask;
+    req->attribute = attribute;
+
+    req->length += ((inSize + 3) & ~3) >> 2;
+    req->num_bytes = inSize;
+    
+    if (pIn) {
+        Data(dpy, pIn, inSize);
+    }
+    
+    if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+        UnlockDisplay(dpy);
+        SyncHandle();
+        return False;
+    }
+    
+    length = rep.length;
+    outSize = rep.num_bytes;
+    slop = outSize & 3;
+
+    if (outSize) *ppOut = (char *) Xmalloc(outSize);
+    
+    if (!*ppOut) {
+        _XEatData(dpy, length);
+    } else {
+        _XRead(dpy, (char *) *ppOut, outSize);
+        if (slop) _XEatData(dpy, 4-slop);
+    }
+    
+    ret = rep.ret;
+    
+    UnlockDisplay(dpy);
+    SyncHandle();
+    
+    return ret;
+}
+
+
+static Bool wire_to_event (Display *dpy, XEvent *host, xEvent *wire)
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    XNVCtrlEvent *re;
+    xnvctrlEvent *event;
+    XNVCtrlEventTarget *reTarget;
+    xnvctrlEventTarget *eventTarget;
+    XNVCtrlEventTargetAvailability *reTargetAvailability;
+    XNVCtrlStringEventTarget *reTargetString;
+    XNVCtrlBinaryEventTarget *reTargetBinary;
+
+    XNVCTRLCheckExtension (dpy, info, False);
+    
+    switch ((wire->u.u.type & 0x7F) - info->codes->first_event) {
+    case ATTRIBUTE_CHANGED_EVENT:
+        re = (XNVCtrlEvent *) host;
+        event = (xnvctrlEvent *) wire;
+        re->attribute_changed.type = event->u.u.type & 0x7F;
+        re->attribute_changed.serial =
+            _XSetLastRequestRead(dpy, (xGenericReply*) event);
+        re->attribute_changed.send_event = ((event->u.u.type & 0x80) != 0);
+        re->attribute_changed.display = dpy;
+        re->attribute_changed.time = event->u.attribute_changed.time;
+        re->attribute_changed.screen = event->u.attribute_changed.screen;
+        re->attribute_changed.display_mask =
+            event->u.attribute_changed.display_mask;
+        re->attribute_changed.attribute = event->u.attribute_changed.attribute;
+        re->attribute_changed.value = event->u.attribute_changed.value;
+        break;
+    case TARGET_ATTRIBUTE_CHANGED_EVENT:
+        reTarget = (XNVCtrlEventTarget *) host;
+        eventTarget = (xnvctrlEventTarget *) wire;
+        reTarget->attribute_changed.type = eventTarget->u.u.type & 0x7F;
+        reTarget->attribute_changed.serial =
+            _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
+        reTarget->attribute_changed.send_event =
+            ((eventTarget->u.u.type & 0x80) != 0);
+        reTarget->attribute_changed.display = dpy;
+        reTarget->attribute_changed.time =
+            eventTarget->u.attribute_changed.time;
+        reTarget->attribute_changed.target_type =
+            eventTarget->u.attribute_changed.target_type;
+        reTarget->attribute_changed.target_id =
+            eventTarget->u.attribute_changed.target_id;
+        reTarget->attribute_changed.display_mask =
+            eventTarget->u.attribute_changed.display_mask;
+        reTarget->attribute_changed.attribute =
+            eventTarget->u.attribute_changed.attribute;
+        reTarget->attribute_changed.value =
+            eventTarget->u.attribute_changed.value;
+        break;
+    case TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT:
+        reTargetAvailability = (XNVCtrlEventTargetAvailability *) host;
+        eventTarget = (xnvctrlEventTarget *) wire;
+        reTargetAvailability->attribute_changed.type =
+            eventTarget->u.u.type & 0x7F;
+        reTargetAvailability->attribute_changed.serial =
+            _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
+        reTargetAvailability->attribute_changed.send_event =
+            ((eventTarget->u.u.type & 0x80) != 0);
+        reTargetAvailability->attribute_changed.display = dpy;
+        reTargetAvailability->attribute_changed.time =
+            eventTarget->u.availability_changed.time;
+        reTargetAvailability->attribute_changed.target_type =
+            eventTarget->u.availability_changed.target_type;
+        reTargetAvailability->attribute_changed.target_id =
+            eventTarget->u.availability_changed.target_id;
+        reTargetAvailability->attribute_changed.display_mask =
+            eventTarget->u.availability_changed.display_mask;
+        reTargetAvailability->attribute_changed.attribute =
+            eventTarget->u.availability_changed.attribute;
+        reTargetAvailability->attribute_changed.availability =
+            eventTarget->u.availability_changed.availability;
+        reTargetAvailability->attribute_changed.value =
+            eventTarget->u.availability_changed.value;
+        break;
+    case TARGET_STRING_ATTRIBUTE_CHANGED_EVENT:
+        reTargetString = (XNVCtrlStringEventTarget *) host;
+        eventTarget = (xnvctrlEventTarget *) wire;
+        reTargetString->attribute_changed.type = eventTarget->u.u.type & 0x7F;
+        reTargetString->attribute_changed.serial =
+            _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
+        reTargetString->attribute_changed.send_event =
+            ((eventTarget->u.u.type & 0x80) != 0);
+        reTargetString->attribute_changed.display = dpy;
+        reTargetString->attribute_changed.time =
+            eventTarget->u.attribute_changed.time;
+        reTargetString->attribute_changed.target_type =
+            eventTarget->u.attribute_changed.target_type;
+        reTargetString->attribute_changed.target_id =
+            eventTarget->u.attribute_changed.target_id;
+        reTargetString->attribute_changed.display_mask =
+            eventTarget->u.attribute_changed.display_mask;
+        reTargetString->attribute_changed.attribute =
+            eventTarget->u.attribute_changed.attribute;
+        break;
+    case TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT:
+        reTargetBinary = (XNVCtrlBinaryEventTarget *) host;
+        eventTarget = (xnvctrlEventTarget *) wire;
+        reTargetBinary->attribute_changed.type = eventTarget->u.u.type & 0x7F;
+        reTargetBinary->attribute_changed.serial =
+            _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
+        reTargetBinary->attribute_changed.send_event =
+            ((eventTarget->u.u.type & 0x80) != 0);
+        reTargetBinary->attribute_changed.display = dpy;
+        reTargetBinary->attribute_changed.time =
+            eventTarget->u.attribute_changed.time;
+        reTargetBinary->attribute_changed.target_type =
+            eventTarget->u.attribute_changed.target_type;
+        reTargetBinary->attribute_changed.target_id =
+            eventTarget->u.attribute_changed.target_id;
+        reTargetBinary->attribute_changed.display_mask =
+            eventTarget->u.attribute_changed.display_mask;
+        reTargetBinary->attribute_changed.attribute =
+            eventTarget->u.attribute_changed.attribute;
+        break;
+
+    default:
+        return False;
+    }
+
+    return True;
+}
+
diff --git a/src/third_party/angle/src/third_party/libXNVCtrl/NVCtrl.h b/src/third_party/angle/src/third_party/libXNVCtrl/NVCtrl.h
new file mode 100644
index 0000000..7bd7ab7
--- /dev/null
+++ b/src/third_party/angle/src/third_party/libXNVCtrl/NVCtrl.h
@@ -0,0 +1,4365 @@
+/*
+ * Copyright (c) 2010 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NVCTRL_H
+#define __NVCTRL_H
+
+#include <stdint.h>
+
+/**************************************************************************/
+
+/*
+ * Attribute Targets
+ *
+ * Targets define attribute groups.  For example, some attributes are only
+ * valid to set on a GPU, others are only valid when talking about an
+ * X Screen.  Target types are then what is used to identify the target
+ * group of the attribute you wish to set/query.
+ *
+ * Here are the supported target types:
+ */
+
+#define NV_CTRL_TARGET_TYPE_X_SCREEN 0
+#define NV_CTRL_TARGET_TYPE_GPU 1
+#define NV_CTRL_TARGET_TYPE_FRAMELOCK 2
+#define NV_CTRL_TARGET_TYPE_VCSC 3 /* Visual Computing System */
+#define NV_CTRL_TARGET_TYPE_GVI 4
+#define NV_CTRL_TARGET_TYPE_COOLER 5 /* e.g., fan */
+#define NV_CTRL_TARGET_TYPE_THERMAL_SENSOR 6
+#define NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER 7
+#define NV_CTRL_TARGET_TYPE_DISPLAY 8
+
+/**************************************************************************/
+
+/*
+ * Attributes
+ *
+ * Some attributes may only be read; some may require a display_mask
+ * argument and others may be valid only for specific target types.
+ * This information is encoded in the "permission" comment after each
+ * attribute #define, and can be queried at run time with
+ * XNVCTRLQueryValidAttributeValues() and/or
+ * XNVCTRLQueryValidTargetAttributeValues()
+ *
+ * Key to Integer Attribute "Permissions":
+ *
+ * R: The attribute is readable (in general, all attributes will be
+ *    readable)
+ *
+ * W: The attribute is writable (attributes may not be writable for
+ *    various reasons: they represent static system information, they
+ *    can only be changed by changing an XF86Config option, etc).
+ *
+ * D: The attribute requires the display mask argument.  The
+ *    attributes NV_CTRL_CONNECTED_DISPLAYS and NV_CTRL_ENABLED_DISPLAYS
+ *    will be a bitmask of what display devices are connected and what
+ *    display devices are enabled for use in X, respectively.  Each bit
+ *    in the bitmask represents a display device; it is these bits which
+ *    should be used as the display_mask when dealing with attributes
+ *    designated with "D" below.  For attributes that do not require the
+ *    display mask, the argument is ignored.
+ *
+ *    Alternatively, NV-CONTROL versions 1.27 and greater allow these
+ *    attributes to be accessed via display target types, in which case
+ *    the display_mask is ignored.
+ *
+ * G: The attribute may be queried using an NV_CTRL_TARGET_TYPE_GPU
+ *    target type via XNVCTRLQueryTargetAttribute().
+ *
+ * F: The attribute may be queried using an NV_CTRL_TARGET_TYPE_FRAMELOCK
+ *    target type via XNVCTRLQueryTargetAttribute().
+ *
+ * X: When Xinerama is enabled, this attribute is kept consistent across
+ *    all Physical X Screens;  assignment of this attribute will be
+ *    broadcast by the NVIDIA X Driver to all X Screens.
+ *
+ * V: The attribute may be queried using an NV_CTRL_TARGET_TYPE_VCSC
+ *    target type via XNVCTRLQueryTargetAttribute().
+ *
+ * I: The attribute may be queried using an NV_CTRL_TARGET_TYPE_GVI target type
+ *    via XNVCTRLQueryTargetAttribute().
+ *
+ * Q: The attribute is a 64-bit integer attribute;  use the 64-bit versions
+ *    of the appropriate query interfaces.
+ *
+ * C: The attribute may be queried using an NV_CTRL_TARGET_TYPE_COOLER target
+ *    type via XNVCTRLQueryTargetAttribute().
+ *
+ * S: The attribute may be queried using an NV_CTRL_TARGET_TYPE_THERMAL_SENSOR
+ *    target type via XNVCTRLQueryTargetAttribute().
+ *
+ * T: The attribute may be queried using an
+ *    NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER target type
+ *    via XNVCTRLQueryTargetAttribute().
+ *
+ * NOTE: Unless mentioned otherwise, all attributes may be queried using
+ *       an NV_CTRL_TARGET_TYPE_X_SCREEN target type via
+ *       XNVCTRLQueryTargetAttribute().
+ */
+
+/**************************************************************************/
+
+/*
+ * Integer attributes:
+ *
+ * Integer attributes can be queried through the XNVCTRLQueryAttribute() and
+ * XNVCTRLQueryTargetAttribute() function calls.
+ *
+ * Integer attributes can be set through the XNVCTRLSetAttribute() and
+ * XNVCTRLSetTargetAttribute() function calls.
+ *
+ * Unless otherwise noted, all integer attributes can be queried/set
+ * using an NV_CTRL_TARGET_TYPE_X_SCREEN target.  Attributes that cannot
+ * take an NV_CTRL_TARGET_TYPE_X_SCREEN also cannot be queried/set through
+ * XNVCTRLQueryAttribute()/XNVCTRLSetAttribute() (Since these assume
+ * an X Screen target).
+ */
+
+/*
+ * NV_CTRL_FLATPANEL_SCALING - not supported
+ */
+
+#define NV_CTRL_FLATPANEL_SCALING 2 /* RWDG */
+#define NV_CTRL_FLATPANEL_SCALING_DEFAULT 0
+#define NV_CTRL_FLATPANEL_SCALING_NATIVE 1
+#define NV_CTRL_FLATPANEL_SCALING_SCALED 2
+#define NV_CTRL_FLATPANEL_SCALING_CENTERED 3
+#define NV_CTRL_FLATPANEL_SCALING_ASPECT_SCALED 4
+
+/*
+ * NV_CTRL_FLATPANEL_DITHERING is deprecated; NV_CTRL_DITHERING should
+ * be used instead.
+ */
+
+#define NV_CTRL_FLATPANEL_DITHERING 3 /* RWDG */
+#define NV_CTRL_FLATPANEL_DITHERING_DEFAULT 0
+#define NV_CTRL_FLATPANEL_DITHERING_ENABLED 1
+#define NV_CTRL_FLATPANEL_DITHERING_DISABLED 2
+
+/*
+ * NV_CTRL_DITHERING - the requested dithering configuration;
+ * possible values are:
+ *
+ * 0: auto     (the driver will decide when to dither)
+ * 1: enabled  (the driver will always dither when possible)
+ * 2: disabled (the driver will never dither)
+ */
+
+#define NV_CTRL_DITHERING 3 /* RWDG */
+#define NV_CTRL_DITHERING_AUTO 0
+#define NV_CTRL_DITHERING_ENABLED 1
+#define NV_CTRL_DITHERING_DISABLED 2
+
+/*
+ * NV_CTRL_DIGITAL_VIBRANCE - sets the digital vibrance level for the
+ * specified display device.
+ */
+
+#define NV_CTRL_DIGITAL_VIBRANCE 4 /* RWDG */
+
+/*
+ * NV_CTRL_BUS_TYPE - returns the bus type through which the specified device
+ * is connected to the computer.
+ * When this attribute is queried on an X screen target, the bus type of the
+ * GPU driving the X screen is returned.
+ */
+
+#define NV_CTRL_BUS_TYPE 5 /* R--GI */
+#define NV_CTRL_BUS_TYPE_AGP 0
+#define NV_CTRL_BUS_TYPE_PCI 1
+#define NV_CTRL_BUS_TYPE_PCI_EXPRESS 2
+#define NV_CTRL_BUS_TYPE_INTEGRATED 3
+
+/*
+ * NV_CTRL_VIDEO_RAM - returns the total amount of memory available
+ * to the specified GPU (or the GPU driving the specified X
+ * screen).  Note: if the GPU supports TurboCache(TM), the value
+ * reported may exceed the amount of video memory installed on the
+ * GPU.  The value reported for integrated GPUs may likewise exceed
+ * the amount of dedicated system memory set aside by the system
+ * BIOS for use by the integrated GPU.
+ */
+
+#define NV_CTRL_VIDEO_RAM 6 /* R--G */
+
+/*
+ * NV_CTRL_IRQ - returns the interrupt request line used by the specified
+ * device.
+ * When this attribute is queried on an X screen target, the IRQ of the GPU
+ * driving the X screen is returned.
+ */
+
+#define NV_CTRL_IRQ 7 /* R--GI */
+
+/*
+ * NV_CTRL_OPERATING_SYSTEM - returns the operating system on which
+ * the X server is running.
+ */
+
+#define NV_CTRL_OPERATING_SYSTEM 8 /* R--G */
+#define NV_CTRL_OPERATING_SYSTEM_LINUX 0
+#define NV_CTRL_OPERATING_SYSTEM_FREEBSD 1
+#define NV_CTRL_OPERATING_SYSTEM_SUNOS 2
+
+/*
+ * NV_CTRL_SYNC_TO_VBLANK - enables sync to vblank for OpenGL clients.
+ * This setting is only applied to OpenGL clients that are started
+ * after this setting is applied.
+ */
+
+#define NV_CTRL_SYNC_TO_VBLANK 9 /* RW-X */
+#define NV_CTRL_SYNC_TO_VBLANK_OFF 0
+#define NV_CTRL_SYNC_TO_VBLANK_ON 1
+
+/*
+ * NV_CTRL_LOG_ANISO - enables anisotropic filtering for OpenGL
+ * clients; on some NVIDIA hardware, this can only be enabled or
+ * disabled; on other hardware different levels of anisotropic
+ * filtering can be specified.  This setting is only applied to OpenGL
+ * clients that are started after this setting is applied.
+ */
+
+#define NV_CTRL_LOG_ANISO 10 /* RW-X */
+
+/*
+ * NV_CTRL_FSAA_MODE - the FSAA setting for OpenGL clients; possible
+ * FSAA modes:
+ *
+ * NV_CTRL_FSAA_MODE_2x     "2x Bilinear Multisampling"
+ * NV_CTRL_FSAA_MODE_2x_5t  "2x Quincunx Multisampling"
+ * NV_CTRL_FSAA_MODE_15x15  "1.5 x 1.5 Supersampling"
+ * NV_CTRL_FSAA_MODE_2x2    "2 x 2 Supersampling"
+ * NV_CTRL_FSAA_MODE_4x     "4x Bilinear Multisampling"
+ * NV_CTRL_FSAA_MODE_4x_9t  "4x Gaussian Multisampling"
+ * NV_CTRL_FSAA_MODE_8x     "2x Bilinear Multisampling by 4x Supersampling"
+ * NV_CTRL_FSAA_MODE_16x    "4x Bilinear Multisampling by 4x Supersampling"
+ * NV_CTRL_FSAA_MODE_8xS    "4x Multisampling by 2x Supersampling"
+ *
+ * This setting is only applied to OpenGL clients that are started
+ * after this setting is applied.
+ */
+
+#define NV_CTRL_FSAA_MODE 11 /* RW-X */
+#define NV_CTRL_FSAA_MODE_NONE 0
+#define NV_CTRL_FSAA_MODE_2x 1
+#define NV_CTRL_FSAA_MODE_2x_5t 2
+#define NV_CTRL_FSAA_MODE_15x15 3
+#define NV_CTRL_FSAA_MODE_2x2 4
+#define NV_CTRL_FSAA_MODE_4x 5
+#define NV_CTRL_FSAA_MODE_4x_9t 6
+#define NV_CTRL_FSAA_MODE_8x 7
+#define NV_CTRL_FSAA_MODE_16x 8
+#define NV_CTRL_FSAA_MODE_8xS 9
+#define NV_CTRL_FSAA_MODE_8xQ 10
+#define NV_CTRL_FSAA_MODE_16xS 11
+#define NV_CTRL_FSAA_MODE_16xQ 12
+#define NV_CTRL_FSAA_MODE_32xS 13
+#define NV_CTRL_FSAA_MODE_32x 14
+#define NV_CTRL_FSAA_MODE_64xS 15
+#define NV_CTRL_FSAA_MODE_MAX NV_CTRL_FSAA_MODE_64xS
+
+/*
+ * NV_CTRL_TEXTURE_SHARPEN - enables texture sharpening for OpenGL
+ * clients.  This setting is only applied to OpenGL clients that are
+ * started after this setting is applied.
+ */
+
+#define NV_CTRL_TEXTURE_SHARPEN 12 /* RW-X */
+#define NV_CTRL_TEXTURE_SHARPEN_OFF 0
+#define NV_CTRL_TEXTURE_SHARPEN_ON 1
+
+/*
+ * NV_CTRL_UBB - returns whether UBB is enabled for the specified X
+ * screen.
+ */
+
+#define NV_CTRL_UBB 13 /* R-- */
+#define NV_CTRL_UBB_OFF 0
+#define NV_CTRL_UBB_ON 1
+
+/*
+ * NV_CTRL_OVERLAY - returns whether the RGB overlay is enabled for
+ * the specified X screen.
+ */
+
+#define NV_CTRL_OVERLAY 14 /* R-- */
+#define NV_CTRL_OVERLAY_OFF 0
+#define NV_CTRL_OVERLAY_ON 1
+
+/*
+ * NV_CTRL_STEREO - returns whether stereo (and what type) is enabled
+ * for the specified X screen.
+ */
+
+#define NV_CTRL_STEREO 16 /* R-- */
+#define NV_CTRL_STEREO_OFF 0
+#define NV_CTRL_STEREO_DDC 1
+#define NV_CTRL_STEREO_BLUELINE 2
+#define NV_CTRL_STEREO_DIN 3
+#define NV_CTRL_STEREO_PASSIVE_EYE_PER_DPY 4
+#define NV_CTRL_STEREO_VERTICAL_INTERLACED 5
+#define NV_CTRL_STEREO_COLOR_INTERLACED 6
+#define NV_CTRL_STEREO_HORIZONTAL_INTERLACED 7
+#define NV_CTRL_STEREO_CHECKERBOARD_PATTERN 8
+#define NV_CTRL_STEREO_INVERSE_CHECKERBOARD_PATTERN 9
+#define NV_CTRL_STEREO_3D_VISION 10
+#define NV_CTRL_STEREO_3D_VISION_PRO 11
+
+/*
+ * NV_CTRL_EMULATE - controls OpenGL software emulation of future
+ * NVIDIA GPUs.
+ */
+
+#define NV_CTRL_EMULATE 17 /* RW- */
+#define NV_CTRL_EMULATE_NONE 0
+
+/*
+ * NV_CTRL_TWINVIEW - returns whether TwinView is enabled for the
+ * specified X screen.
+ */
+
+#define NV_CTRL_TWINVIEW 18 /* R-- */
+#define NV_CTRL_TWINVIEW_NOT_ENABLED 0
+#define NV_CTRL_TWINVIEW_ENABLED 1
+
+/*
+ * NV_CTRL_CONNECTED_DISPLAYS - returns a display mask indicating the last
+ * cached state of the display devices connected to the GPU or GPU driving
+ * the specified X screen.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_CONNECTED_DISPLAYS 19 /* R--G */
+
+/*
+ * NV_CTRL_ENABLED_DISPLAYS - returns a display mask indicating what
+ * display devices are enabled for use on the specified X screen or
+ * GPU.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_ENABLED_DISPLAYS 20 /* R--G */
+
+/**************************************************************************/
+/*
+ * Integer attributes specific to configuring Frame Lock on boards that
+ * support it.
+ */
+
+/*
+ * NV_CTRL_FRAMELOCK - returns whether the underlying GPU supports
+ * Frame Lock.  All of the other frame lock attributes are only
+ * applicable if NV_CTRL_FRAMELOCK is _SUPPORTED.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_FRAMELOCK 21 /* R--G */
+#define NV_CTRL_FRAMELOCK_NOT_SUPPORTED 0
+#define NV_CTRL_FRAMELOCK_SUPPORTED 1
+
+/*
+ * NV_CTRL_FRAMELOCK_MASTER - get/set which display device to use
+ * as the frame lock master for the entire sync group.  Note that only
+ * one node in the sync group should be configured as the master.
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_FRAMELOCK_MASTER 22 /* RW-G */
+
+/* These are deprecated.  NV_CTRL_FRAMELOCK_MASTER now takes and
+   returns a display mask as value. */
+#define NV_CTRL_FRAMELOCK_MASTER_FALSE 0
+#define NV_CTRL_FRAMELOCK_MASTER_TRUE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_POLARITY - sync either to the rising edge of the
+ * frame lock pulse, the falling edge of the frame lock pulse or both.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_POLARITY 23 /* RW-F */
+#define NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE 0x1
+#define NV_CTRL_FRAMELOCK_POLARITY_FALLING_EDGE 0x2
+#define NV_CTRL_FRAMELOCK_POLARITY_BOTH_EDGES 0x3
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY - delay between the frame lock pulse
+ * and the GPU sync.  This value must be multiplied by
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION to determine the sync delay in
+ * nanoseconds.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ *
+ * USAGE NODE: NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX and
+ *             NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR are deprecated.
+ *             The Sync Delay _MAX and _FACTOR are different for different
+ *             GSync products and so, to be correct, the valid values for
+ *             NV_CTRL_FRAMELOCK_SYNC_DELAY must be queried to get the range
+ *             of acceptable sync delay values, and
+ *             NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION must be queried to
+ *             obtain the correct factor.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY 24           /* RW-F */
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX 2047     // deprecated
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR 7.81  // deprecated
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_INTERVAL - how many house sync pulses
+ * between the frame lock sync generation (0 == sync every house sync);
+ * this only applies to the master when receiving house sync.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_INTERVAL 25 /* RW-F */
+
+/*
+ * NV_CTRL_FRAMELOCK_PORT0_STATUS - status of the rj45 port0.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_PORT0_STATUS 26 /* R--F */
+#define NV_CTRL_FRAMELOCK_PORT0_STATUS_INPUT 0
+#define NV_CTRL_FRAMELOCK_PORT0_STATUS_OUTPUT 1
+
+/*
+ * NV_CTRL_FRAMELOCK_PORT1_STATUS - status of the rj45 port1.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_PORT1_STATUS 27 /* R--F */
+#define NV_CTRL_FRAMELOCK_PORT1_STATUS_INPUT 0
+#define NV_CTRL_FRAMELOCK_PORT1_STATUS_OUTPUT 1
+
+/*
+ * NV_CTRL_FRAMELOCK_HOUSE_STATUS - returns whether or not the house
+ * sync signal was detected on the BNC connector of the frame lock
+ * board.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_HOUSE_STATUS 28 /* R--F */
+#define NV_CTRL_FRAMELOCK_HOUSE_STATUS_NOT_DETECTED 0
+#define NV_CTRL_FRAMELOCK_HOUSE_STATUS_DETECTED 1
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC - enable/disable the syncing of display
+ * devices to the frame lock pulse as specified by previous calls to
+ * NV_CTRL_FRAMELOCK_MASTER and NV_CTRL_FRAMELOCK_SLAVES.
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC 29 /* RW-G */
+#define NV_CTRL_FRAMELOCK_SYNC_DISABLE 0
+#define NV_CTRL_FRAMELOCK_SYNC_ENABLE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_READY - reports whether a frame lock
+ * board is receiving sync (regardless of whether or not any display
+ * devices are using the sync).
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_READY 30 /* R--F */
+#define NV_CTRL_FRAMELOCK_SYNC_READY_FALSE 0
+#define NV_CTRL_FRAMELOCK_SYNC_READY_TRUE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_STEREO_SYNC - this indicates that the GPU stereo
+ * signal is in sync with the frame lock stereo signal.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_STEREO_SYNC 31 /* R--G */
+#define NV_CTRL_FRAMELOCK_STEREO_SYNC_FALSE 0
+#define NV_CTRL_FRAMELOCK_STEREO_SYNC_TRUE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_TEST_SIGNAL - to test the connections in the sync
+ * group, tell the master to enable a test signal, then query port[01]
+ * status and sync_ready on all slaves.  When done, tell the master to
+ * disable the test signal.  Test signal should only be manipulated
+ * while NV_CTRL_FRAMELOCK_SYNC is enabled.
+ *
+ * The TEST_SIGNAL is also used to reset the Universal Frame Count (as
+ * returned by the glXQueryFrameCountNV() function in the
+ * GLX_NV_swap_group extension).  Note: for best accuracy of the
+ * Universal Frame Count, it is recommended to toggle the TEST_SIGNAL
+ * on and off after enabling frame lock.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_FRAMELOCK_TEST_SIGNAL 32 /* RW-G */
+#define NV_CTRL_FRAMELOCK_TEST_SIGNAL_DISABLE 0
+#define NV_CTRL_FRAMELOCK_TEST_SIGNAL_ENABLE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_ETHERNET_DETECTED - The frame lock boards are
+ * cabled together using regular cat5 cable, connecting to rj45 ports
+ * on the backplane of the card.  There is some concern that users may
+ * think these are ethernet ports and connect them to a
+ * router/hub/etc.  The hardware can detect this and will shut off to
+ * prevent damage (either to itself or to the router).
+ * NV_CTRL_FRAMELOCK_ETHERNET_DETECTED may be called to find out if
+ * ethernet is connected to one of the rj45 ports.  An appropriate
+ * error message should then be displayed.  The _PORT0 and _PORT1
+ * values may be or'ed together.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED 33 /* R--F */
+#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_NONE 0
+#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_PORT0 0x1
+#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_PORT1 0x2
+
+/*
+ * NV_CTRL_FRAMELOCK_VIDEO_MODE - get/set what video mode is used
+ * to interperate the house sync signal.  This should only be set
+ * on the master.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE 34 /* RW-F */
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_NONE 0
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL 1
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_NTSCPALSECAM 2
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_HDTV 3
+
+/*
+ * During FRAMELOCK bring-up, the above values were redefined to
+ * these:
+ */
+
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_AUTO 0
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL 1
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_BI_LEVEL 2
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_TRI_LEVEL 3
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_RATE - this is the refresh rate that the
+ * frame lock board is sending to the GPU, in milliHz.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_RATE 35 /* R--F */
+
+/**************************************************************************/
+
+/*
+ * NV_CTRL_FORCE_GENERIC_CPU - inhibit the use of CPU specific
+ * features such as MMX, SSE, or 3DNOW! for OpenGL clients; this
+ * option may result in performance loss, but may be useful in
+ * conjunction with software such as the Valgrind memory debugger.
+ * This setting is only applied to OpenGL clients that are started
+ * after this setting is applied.
+ *
+ * USAGE NOTE: This attribute is deprecated. CPU compatibility is now
+ *             checked each time during initialization.
+ */
+
+#define NV_CTRL_FORCE_GENERIC_CPU 37 /* RW-X */
+#define NV_CTRL_FORCE_GENERIC_CPU_DISABLE 0
+#define NV_CTRL_FORCE_GENERIC_CPU_ENABLE 1
+
+/*
+ * NV_CTRL_OPENGL_AA_LINE_GAMMA - for OpenGL clients, allow
+ * Gamma-corrected antialiased lines to consider variances in the
+ * color display capabilities of output devices when rendering smooth
+ * lines.  Only available on recent Quadro GPUs.  This setting is only
+ * applied to OpenGL clients that are started after this setting is
+ * applied.
+ */
+
+#define NV_CTRL_OPENGL_AA_LINE_GAMMA 38 /* RW-X */
+#define NV_CTRL_OPENGL_AA_LINE_GAMMA_DISABLE 0
+#define NV_CTRL_OPENGL_AA_LINE_GAMMA_ENABLE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_TIMING - this is TRUE when the gpu is both receiving
+ * and locked to an input timing signal. Timing information may come from
+ * the following places: Another frame lock device that is set to master,
+ * the house sync signal, or the GPU's internal timing from a display
+ * device.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_FRAMELOCK_TIMING 39 /* R--G */
+#define NV_CTRL_FRAMELOCK_TIMING_FALSE 0
+#define NV_CTRL_FRAMELOCK_TIMING_TRUE 1
+
+/*
+ * NV_CTRL_FLIPPING_ALLOWED - when TRUE, OpenGL will swap by flipping
+ * when possible; when FALSE, OpenGL will alway swap by blitting.
+ */
+
+#define NV_CTRL_FLIPPING_ALLOWED 40 /* RW-X */
+#define NV_CTRL_FLIPPING_ALLOWED_FALSE 0
+#define NV_CTRL_FLIPPING_ALLOWED_TRUE 1
+
+/*
+ * NV_CTRL_ARCHITECTURE - returns the architecture on which the X server is
+ * running.
+ */
+
+#define NV_CTRL_ARCHITECTURE 41 /* R-- */
+#define NV_CTRL_ARCHITECTURE_X86 0
+#define NV_CTRL_ARCHITECTURE_X86_64 1
+#define NV_CTRL_ARCHITECTURE_IA64 2
+
+/*
+ * NV_CTRL_TEXTURE_CLAMPING - texture clamping mode in OpenGL.  By
+ * default, _SPEC is used, which forces OpenGL texture clamping to
+ * conform with the OpenGL specification.  _EDGE forces NVIDIA's
+ * OpenGL implementation to remap GL_CLAMP to GL_CLAMP_TO_EDGE,
+ * which is not strictly conformant, but some applications rely on
+ * the non-conformant behavior.
+ */
+
+#define NV_CTRL_TEXTURE_CLAMPING 42 /* RW-X */
+#define NV_CTRL_TEXTURE_CLAMPING_EDGE 0
+#define NV_CTRL_TEXTURE_CLAMPING_SPEC 1
+
+#define NV_CTRL_CURSOR_SHADOW 43 /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_DISABLE 0
+#define NV_CTRL_CURSOR_SHADOW_ENABLE 1
+
+#define NV_CTRL_CURSOR_SHADOW_ALPHA 44 /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_RED 45   /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_GREEN 46 /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_BLUE 47  /* RW- */
+
+#define NV_CTRL_CURSOR_SHADOW_X_OFFSET 48 /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_Y_OFFSET 49 /* RW- */
+
+/*
+ * When Application Control for FSAA is enabled, then what the
+ * application requests is used, and NV_CTRL_FSAA_MODE is ignored.  If
+ * this is disabled, then any application setting is overridden with
+ * NV_CTRL_FSAA_MODE
+ */
+
+#define NV_CTRL_FSAA_APPLICATION_CONTROLLED 50 /* RW-X */
+#define NV_CTRL_FSAA_APPLICATION_CONTROLLED_ENABLED 1
+#define NV_CTRL_FSAA_APPLICATION_CONTROLLED_DISABLED 0
+
+/*
+ * When Application Control for LogAniso is enabled, then what the
+ * application requests is used, and NV_CTRL_LOG_ANISO is ignored.  If
+ * this is disabled, then any application setting is overridden with
+ * NV_CTRL_LOG_ANISO
+ */
+
+#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED 51 /* RW-X */
+#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_ENABLED 1
+#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_DISABLED 0
+
+/*
+ * IMAGE_SHARPENING adjusts the sharpness of the display's image
+ * quality by amplifying high frequency content.  Valid values will
+ * normally be in the range [0,32).  Only available on GeForceFX or
+ * newer.
+ */
+
+#define NV_CTRL_IMAGE_SHARPENING 52 /* RWDG */
+
+/*
+ * NV_CTRL_TV_OVERSCAN adjusts the amount of overscan on the specified
+ * display device.
+ */
+
+#define NV_CTRL_TV_OVERSCAN 53 /* RWDG */
+
+/*
+ * NV_CTRL_TV_FLICKER_FILTER adjusts the amount of flicker filter on
+ * the specified display device.
+ */
+
+#define NV_CTRL_TV_FLICKER_FILTER 54 /* RWDG */
+
+/*
+ * NV_CTRL_TV_BRIGHTNESS adjusts the amount of brightness on the
+ * specified display device.
+ */
+
+#define NV_CTRL_TV_BRIGHTNESS 55 /* RWDG */
+
+/*
+ * NV_CTRL_TV_HUE adjusts the amount of hue on the specified display
+ * device.
+ */
+
+#define NV_CTRL_TV_HUE 56 /* RWDG */
+
+/*
+ * NV_CTRL_TV_CONTRAST adjusts the amount of contrast on the specified
+ * display device.
+ */
+
+#define NV_CTRL_TV_CONTRAST 57 /* RWDG */
+
+/*
+ * NV_CTRL_TV_SATURATION adjusts the amount of saturation on the
+ * specified display device.
+ */
+
+#define NV_CTRL_TV_SATURATION 58 /* RWDG */
+
+/*
+ * NV_CTRL_TV_RESET_SETTINGS - this write-only attribute can be used
+ * to request that all TV Settings be reset to their default values;
+ * typical usage would be that this attribute be sent, and then all
+ * the TV attributes be queried to retrieve their new values.
+ */
+
+#define NV_CTRL_TV_RESET_SETTINGS 59 /* -WDG */
+
+/*
+ * NV_CTRL_GPU_CORE_TEMPERATURE reports the current core temperature
+ * of the GPU driving the X screen.
+ */
+
+#define NV_CTRL_GPU_CORE_TEMPERATURE 60 /* R--G */
+
+/*
+ * NV_CTRL_GPU_CORE_THRESHOLD reports the current GPU core slowdown
+ * threshold temperature, NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD and
+ * NV_CTRL_GPU_MAX_CORE_THRESHOLD report the default and MAX core
+ * slowdown threshold temperatures.
+ *
+ * NV_CTRL_GPU_CORE_THRESHOLD reflects the temperature at which the
+ * GPU is throttled to prevent overheating.
+ */
+
+#define NV_CTRL_GPU_CORE_THRESHOLD 61         /* R--G */
+#define NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD 62 /* R--G */
+#define NV_CTRL_GPU_MAX_CORE_THRESHOLD 63     /* R--G */
+
+/*
+ * NV_CTRL_AMBIENT_TEMPERATURE reports the current temperature in the
+ * immediate neighbourhood of the GPU driving the X screen.
+ */
+
+#define NV_CTRL_AMBIENT_TEMPERATURE 64 /* R--G */
+
+/*
+ * NV_CTRL_PBUFFER_SCANOUT_SUPPORTED - returns whether this X screen
+ * supports scanout of FP pbuffers;
+ *
+ * if this screen does not support PBUFFER_SCANOUT, then all other
+ * PBUFFER_SCANOUT attributes are unavailable.
+ *
+ * PBUFFER_SCANOUT is supported if and only if:
+ * - Twinview is configured with clone mode.  The secondary screen is used to
+ *   scanout the pbuffer.
+ * - The desktop is running in with 16 bits per pixel.
+ */
+#define NV_CTRL_PBUFFER_SCANOUT_SUPPORTED 65 /* R-- */
+#define NV_CTRL_PBUFFER_SCANOUT_FALSE 0
+#define NV_CTRL_PBUFFER_SCANOUT_TRUE 1
+
+/*
+ * NV_CTRL_PBUFFER_SCANOUT_XID indicates the XID of the pbuffer used for
+ * scanout.
+ */
+#define NV_CTRL_PBUFFER_SCANOUT_XID 66 /* RW- */
+
+/**************************************************************************/
+/*
+ * The NV_CTRL_GVO_* integer attributes are used to configure GVO
+ * (Graphics to Video Out).  This functionality is available, for
+ * example, on the Quadro FX 4000 SDI graphics board.
+ *
+ * The following is a typical usage pattern for the GVO attributes:
+ *
+ * - query NV_CTRL_GVO_SUPPORTED to determine if the X screen supports GV0.
+ *
+ * - specify NV_CTRL_GVO_SYNC_MODE (one of FREE_RUNNING, GENLOCK, or
+ * FRAMELOCK); if you specify GENLOCK or FRAMELOCK, you should also
+ * specify NV_CTRL_GVO_SYNC_SOURCE.
+ *
+ * - Use NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED and
+ * NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED to detect what input syncs are
+ * present.
+ *
+ * (If no analog sync is detected but it is known that a valid
+ * bi-level or tri-level sync is connected set
+ * NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE appropriately and
+ * retest with NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED).
+ *
+ * - if syncing to input sync, query the
+ * NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT attribute; note that Input video
+ * format can only be queried after SYNC_SOURCE is specified.
+ *
+ * - specify the NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT
+ *
+ * - specify the NV_CTRL_GVO_DATA_FORMAT
+ *
+ * - specify any custom Color Space Conversion (CSC) matrix, offset,
+ * and scale with XNVCTRLSetGvoColorConversion().
+ *
+ * - if using the GLX_NV_video_out extension to display one or more
+ * pbuffers, call glXGetVideoDeviceNV() to lock the GVO output for use
+ * by the GLX client; then bind the pbuffer(s) to the GVO output with
+ * glXBindVideoImageNV() and send pbuffers to the GVO output with
+ * glXSendPbufferToVideoNV(); see the GLX_NV_video_out spec for more
+ * details.
+ *
+ * - if using the GLX_NV_present_video extension, call
+ * glXBindVideoDeviceNV() to bind the GVO video device to current
+ * OpenGL context.
+ *
+ * Note that setting most GVO attributes only causes the value to be
+ * cached in the X server.  The values will be flushed to the hardware
+ * either when the next MetaMode is set that uses the GVO display
+ * device, or when a GLX pbuffer is bound to the GVO output (with
+ * glXBindVideoImageNV()).
+ *
+ * Note that GLX_NV_video_out/GLX_NV_present_video and X screen use
+ * are mutually exclusive.  If a MetaMode is currently using the GVO
+ * device, then glXGetVideoDeviceNV and glXBindVideoImageNV() will
+ * fail.  Similarly, if a GLX client has locked the GVO output (via
+ * glXGetVideoDeviceNV or glXBindVideoImageNV), then setting a
+ * MetaMode that uses the GVO device will fail.  The
+ * NV_CTRL_GVO_GLX_LOCKED event will be sent when a GLX client locks
+ * the GVO output.
+ *
+ */
+
+/*
+ * NV_CTRL_GVO_SUPPORTED - returns whether this X screen supports GVO;
+ * if this screen does not support GVO output, then all other GVO
+ * attributes are unavailable.
+ */
+
+#define NV_CTRL_GVO_SUPPORTED 67 /* R-- */
+#define NV_CTRL_GVO_SUPPORTED_FALSE 0
+#define NV_CTRL_GVO_SUPPORTED_TRUE 1
+
+/*
+ * NV_CTRL_GVO_SYNC_MODE - selects the GVO sync mode; possible values
+ * are:
+ *
+ * FREE_RUNNING - GVO does not sync to any external signal
+ *
+ * GENLOCK - the GVO output is genlocked to an incoming sync signal;
+ * genlocking locks at hsync.  This requires that the output video
+ * format exactly match the incoming sync video format.
+ *
+ * FRAMELOCK - the GVO output is frame locked to an incoming sync
+ * signal; frame locking locks at vsync.  This requires that the output
+ * video format have the same refresh rate as the incoming sync video
+ * format.
+ */
+
+#define NV_CTRL_GVO_SYNC_MODE 68 /* RW- */
+#define NV_CTRL_GVO_SYNC_MODE_FREE_RUNNING 0
+#define NV_CTRL_GVO_SYNC_MODE_GENLOCK 1
+#define NV_CTRL_GVO_SYNC_MODE_FRAMELOCK 2
+
+/*
+ * NV_CTRL_GVO_SYNC_SOURCE - if NV_CTRL_GVO_SYNC_MODE is set to either
+ * GENLOCK or FRAMELOCK, this controls which sync source is used as
+ * the incoming sync signal (either Composite or SDI).  If
+ * NV_CTRL_GVO_SYNC_MODE is FREE_RUNNING, this attribute has no
+ * effect.
+ */
+
+#define NV_CTRL_GVO_SYNC_SOURCE 69 /* RW- */
+#define NV_CTRL_GVO_SYNC_SOURCE_COMPOSITE 0
+#define NV_CTRL_GVO_SYNC_SOURCE_SDI 1
+
+/*
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT - specifies the desired output video
+ * format for GVO devices or the desired input video format for GVI devices.
+ *
+ * Note that for GVO, the valid video formats may vary depending on
+ * the NV_CTRL_GVO_SYNC_MODE and the incoming sync video format.  See
+ * the definition of NV_CTRL_GVO_SYNC_MODE.
+ *
+ * Note that when querying the ValidValues for this data type, the
+ * values are reported as bits within a bitmask
+ * (ATTRIBUTE_TYPE_INT_BITS); unfortunately, there are more valid
+ * value bits than will fit in a single 32-bit value.  To solve this,
+ * query the ValidValues for NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT to
+ * check which of the first 31 VIDEO_FORMATS are valid, query the
+ * ValidValues for NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 to check which
+ * of the 32-63 VIDEO_FORMATS are valid, and query the ValidValues of
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3 to check which of the 64-95
+ * VIDEO_FORMATS are valid.
+ *
+ * Note: Setting this attribute on a GVI device may also result in the
+ *       following NV-CONTROL attributes being reset on that device (to
+ *       ensure the configuration remains valid):
+ *           NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT
+ *           NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING
+ */
+
+#define NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT 70 /* RW--I */
+
+#define NV_CTRL_GVIO_VIDEO_FORMAT_NONE 0
+#define NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC 1
+#define NV_CTRL_GVIO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL 2
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_59_94_SMPTE296 3
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296 4
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1035I_59_94_SMPTE260 5
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1035I_60_00_SMPTE260 6
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE295 7
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE274 8
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_59_94_SMPTE274 9
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_60_00_SMPTE274 10
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_23_976_SMPTE274 11
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_24_00_SMPTE274 12
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_25_00_SMPTE274 13
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_29_97_SMPTE274 14
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_30_00_SMPTE274 15
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_50_00_SMPTE296 16
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_48_00_SMPTE274 17
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_47_96_SMPTE274 18
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_30_00_SMPTE296 19
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_29_97_SMPTE296 20
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_25_00_SMPTE296 21
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_24_00_SMPTE296 22
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_23_98_SMPTE296 23
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274 24
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274 25
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274 26
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274 27
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274 28
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_30_00_SMPTE372 29
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_29_97_SMPTE372 30
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_60_00_SMPTE372 31
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_59_94_SMPTE372 32
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_25_00_SMPTE372 33
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_50_00_SMPTE372 34
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_24_00_SMPTE372 35
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_23_98_SMPTE372 36
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_48_00_SMPTE372 37
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_47_96_SMPTE372 38
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_50_00_3G_LEVEL_A_SMPTE274 39
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_59_94_3G_LEVEL_A_SMPTE274 40
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_60_00_3G_LEVEL_A_SMPTE274 41
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_60_00_3G_LEVEL_B_SMPTE274 42
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_60_00_3G_LEVEL_B_SMPTE274 43
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_60_00_3G_LEVEL_B_SMPTE372 44
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_50_00_3G_LEVEL_B_SMPTE274 45
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_3G_LEVEL_B_SMPTE274 46
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_50_00_3G_LEVEL_B_SMPTE372 47
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_30_00_3G_LEVEL_B_SMPTE274 48
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_30_00_3G_LEVEL_B_SMPTE372 49
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_25_00_3G_LEVEL_B_SMPTE274 50
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_25_00_3G_LEVEL_B_SMPTE372 51
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_24_00_3G_LEVEL_B_SMPTE274 52
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_24_00_3G_LEVEL_B_SMPTE372 53
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_48_00_3G_LEVEL_B_SMPTE274 54
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_48_00_3G_LEVEL_B_SMPTE372 55
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_59_94_3G_LEVEL_B_SMPTE274 56
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_59_94_3G_LEVEL_B_SMPTE274 57
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_59_94_3G_LEVEL_B_SMPTE372 58
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_29_97_3G_LEVEL_B_SMPTE274 59
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_29_97_3G_LEVEL_B_SMPTE372 60
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_23_98_3G_LEVEL_B_SMPTE274 61
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_23_98_3G_LEVEL_B_SMPTE372 62
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_47_96_3G_LEVEL_B_SMPTE274 63
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_47_96_3G_LEVEL_B_SMPTE372 64
+
+/*
+ * The following are deprecated; NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT and the
+ * corresponding NV_CTRL_GVIO_* formats should be used instead.
+ */
+#define NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT 70 /* RW- */
+
+#define NV_CTRL_GVO_VIDEO_FORMAT_NONE 0
+#define NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC 1
+#define NV_CTRL_GVO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL 2
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_59_94_SMPTE296 3
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_60_00_SMPTE296 4
+#define NV_CTRL_GVO_VIDEO_FORMAT_1035I_59_94_SMPTE260 5
+#define NV_CTRL_GVO_VIDEO_FORMAT_1035I_60_00_SMPTE260 6
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE295 7
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE274 8
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_59_94_SMPTE274 9
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_60_00_SMPTE274 10
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_976_SMPTE274 11
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE274 12
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE274 13
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE274 14
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE274 15
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_50_00_SMPTE296 16
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_48_00_SMPTE274 17
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_47_96_SMPTE274 18
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_30_00_SMPTE296 19
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_29_97_SMPTE296 20
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_25_00_SMPTE296 21
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_24_00_SMPTE296 22
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_23_98_SMPTE296 23
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274 24
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274 25
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274 26
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274 27
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274 28
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_30_00_SMPTE372 29
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_29_97_SMPTE372 30
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_60_00_SMPTE372 31
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_59_94_SMPTE372 32
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_25_00_SMPTE372 33
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_50_00_SMPTE372 34
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_24_00_SMPTE372 35
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_23_98_SMPTE372 36
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_48_00_SMPTE372 37
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_47_96_SMPTE372 38
+
+/*
+ * NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT - indicates the input video format
+ * detected for GVO or GVI devices; the possible values are the
+ * NV_CTRL_GVIO_VIDEO_FORMAT constants.
+ *
+ * For GVI devices, the jack number should be specified in the lower
+ * 16 bits of the "display_mask" parameter, while the channel number should be
+ * specified in the upper 16 bits.
+ */
+
+#define NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT 71 /* R--I */
+
+/*
+ * The following is deprecated.  Use NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT,
+ * instead.
+ */
+#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT 71 /* R-- */
+
+/*
+ * NV_CTRL_GVO_DATA_FORMAT - This controls how the data in the source
+ * (either the X screen or the GLX pbuffer) is interpretted and
+ * displayed.
+ *
+ * Note: some of the below DATA_FORMATS have been renamed.  For
+ * example, R8G8B8_TO_RGB444 has been renamed to X8X8X8_444_PASSTHRU.
+ * This is to more accurately reflect DATA_FORMATS where the
+ * per-channel data could be either RGB or YCrCb -- the point is that
+ * the driver and GVO hardware do not perform any implicit color space
+ * conversion on the data; it is passed through to the SDI out.
+ */
+
+#define NV_CTRL_GVO_DATA_FORMAT 72 /* RW- */
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB444 0
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_YCRCBA4444 1
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_YCRCBZ4444 2
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB422 3
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_YCRCBA4224 4
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_YCRCBZ4224 5
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_RGB444 6  // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8_444_PASSTHRU 6
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_RGBA4444 7  // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8A8_4444_PASSTHRU 7
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_RGBZ4444 8  // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8Z8_4444_PASSTHRU 8
+#define NV_CTRL_GVO_DATA_FORMAT_Y10CR10CB10_TO_YCRCB444 9  // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X10X10X10_444_PASSTHRU 9
+#define NV_CTRL_GVO_DATA_FORMAT_Y10CR8CB8_TO_YCRCB444 10  // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8_444_PASSTHRU 10
+#define NV_CTRL_GVO_DATA_FORMAT_Y10CR8CB8A10_TO_YCRCBA4444 11  // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8A10_4444_PASSTHRU 11
+#define NV_CTRL_GVO_DATA_FORMAT_Y10CR8CB8Z10_TO_YCRCBZ4444 12  // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8Z10_4444_PASSTHRU 12
+#define NV_CTRL_GVO_DATA_FORMAT_DUAL_R8G8B8_TO_DUAL_YCRCB422 13
+#define NV_CTRL_GVO_DATA_FORMAT_DUAL_Y8CR8CB8_TO_DUAL_YCRCB422 14  // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_DUAL_X8X8X8_TO_DUAL_422_PASSTHRU 14
+#define NV_CTRL_GVO_DATA_FORMAT_R10G10B10_TO_YCRCB422 15
+#define NV_CTRL_GVO_DATA_FORMAT_R10G10B10_TO_YCRCB444 16
+#define NV_CTRL_GVO_DATA_FORMAT_Y12CR12CB12_TO_YCRCB444 17  // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X12X12X12_444_PASSTHRU 17
+#define NV_CTRL_GVO_DATA_FORMAT_R12G12B12_TO_YCRCB444 18
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8_422_PASSTHRU 19
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8A8_4224_PASSTHRU 20
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8Z8_4224_PASSTHRU 21
+#define NV_CTRL_GVO_DATA_FORMAT_X10X10X10_422_PASSTHRU 22
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8_422_PASSTHRU 23
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8A10_4224_PASSTHRU 24
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8Z10_4224_PASSTHRU 25
+#define NV_CTRL_GVO_DATA_FORMAT_X12X12X12_422_PASSTHRU 26
+#define NV_CTRL_GVO_DATA_FORMAT_R12G12B12_TO_YCRCB422 27
+
+/*
+ * NV_CTRL_GVO_DISPLAY_X_SCREEN - no longer supported
+ */
+
+#define NV_CTRL_GVO_DISPLAY_X_SCREEN 73 /* RW- */
+#define NV_CTRL_GVO_DISPLAY_X_SCREEN_ENABLE 1
+#define NV_CTRL_GVO_DISPLAY_X_SCREEN_DISABLE 0
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED - indicates whether
+ * Composite Sync input is detected.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED 74 /* R-- */
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED_FALSE 0
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED_TRUE 1
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE - get/set the
+ * Composite Sync input detect mode.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE 75 /* RW- */
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE_AUTO 0
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE_BI_LEVEL 1
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE_TRI_LEVEL 2
+
+/*
+ * NV_CTRL_GVO_SYNC_INPUT_DETECTED - indicates whether SDI Sync input
+ * is detected, and what type.
+ */
+
+#define NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED 76 /* R-- */
+#define NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_NONE 0
+#define NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_HD 1
+#define NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_SD 2
+
+/*
+ * NV_CTRL_GVO_VIDEO_OUTPUTS - indicates which GVO video output
+ * connectors are currently outputing data.
+ */
+
+#define NV_CTRL_GVO_VIDEO_OUTPUTS 77 /* R-- */
+#define NV_CTRL_GVO_VIDEO_OUTPUTS_NONE 0
+#define NV_CTRL_GVO_VIDEO_OUTPUTS_VIDEO1 1
+#define NV_CTRL_GVO_VIDEO_OUTPUTS_VIDEO2 2
+#define NV_CTRL_GVO_VIDEO_OUTPUTS_VIDEO_BOTH 3
+
+/*
+ * NV_CTRL_GVO_FPGA_VERSION - indicates the version of the Firmware on
+ * the GVO device.  Deprecated; use
+ * NV_CTRL_STRING_GVIO_FIRMWARE_VERSION instead.
+ */
+
+#define NV_CTRL_GVO_FIRMWARE_VERSION 78 /* R-- */
+
+/*
+ * NV_CTRL_GVO_SYNC_DELAY_PIXELS - controls the delay between the
+ * input sync and the output sync in numbers of pixels from hsync;
+ * this is a 12 bit value.
+ *
+ * If the NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW bit is set,
+ * then setting this value will set an advance instead of a delay.
+ */
+
+#define NV_CTRL_GVO_SYNC_DELAY_PIXELS 79 /* RW- */
+
+/*
+ * NV_CTRL_GVO_SYNC_DELAY_LINES - controls the delay between the input
+ * sync and the output sync in numbers of lines from vsync; this is a
+ * 12 bit value.
+ *
+ * If the NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW bit is set,
+ * then setting this value will set an advance instead of a delay.
+ */
+
+#define NV_CTRL_GVO_SYNC_DELAY_LINES 80 /* RW- */
+
+/*
+ * NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE - must be set for a period
+ * of about 2 seconds for the new InputVideoFormat to be properly
+ * locked to.  In nvidia-settings, we do a reacquire whenever genlock
+ * or frame lock mode is entered into, when the user clicks the
+ * "detect" button.  This value can be written, but always reads back
+ * _FALSE.
+ */
+
+#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE 81 /* -W- */
+#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE_FALSE 0
+#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE_TRUE 1
+
+/*
+ * NV_CTRL_GVO_GLX_LOCKED - indicates that GVO configurability is
+ * locked by GLX; this occurs when either glXGetVideoDeviceNV (part of
+ * GLX_NV_video_out) or glXBindVideoDeviceNV (part of
+ * GLX_NV_present_video) is called.  All GVO output resources are
+ * locked until released by the GLX_NV_video_out/GLX_NV_present_video
+ * client.
+ *
+ * When GVO is locked, setting of the following GVO NV-CONTROL attributes will
+ * not happen immediately and will instead be cached.  The GVO resource will
+ * need to be disabled/released and re-enabled/claimed for the values to be
+ * flushed. These attributes are:
+ *    NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT
+ *    NV_CTRL_GVO_DATA_FORMAT
+ *    NV_CTRL_GVO_FLIP_QUEUE_SIZE
+ *
+ * This attribute is deprecated and may be removed in a future release.  Its
+ * functionality has been replaced by NV_CTRL_GVO_LOCK_OWNER.
+ */
+
+#define NV_CTRL_GVO_GLX_LOCKED 82 /* R-- */
+#define NV_CTRL_GVO_GLX_LOCKED_FALSE 0
+#define NV_CTRL_GVO_GLX_LOCKED_TRUE 1
+
+/*
+ * NV_CTRL_GVIO_VIDEO_FORMAT_{WIDTH,HEIGHT,REFRESH_RATE} - query the
+ * width, height, and refresh rate for the specified
+ * NV_CTRL_GVIO_VIDEO_FORMAT_*.  So that this can be queried with
+ * existing interfaces, XNVCTRLQueryAttribute() should be used, and
+ * the video format specified in the display_mask field; eg:
+ *
+ * XNVCTRLQueryAttribute (dpy,
+ *                        screen,
+ *                        NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC,
+ *                        NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH,
+ *                        &value);
+ *
+ * Note that Refresh Rate is in milliHertz values
+ */
+
+#define NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH 83        /* R--I */
+#define NV_CTRL_GVIO_VIDEO_FORMAT_HEIGHT 84       /* R--I */
+#define NV_CTRL_GVIO_VIDEO_FORMAT_REFRESH_RATE 85 /* R--I */
+
+/* The following are deprecated; use the NV_CTRL_GVIO_* versions, instead */
+#define NV_CTRL_GVO_VIDEO_FORMAT_WIDTH 83        /* R-- */
+#define NV_CTRL_GVO_VIDEO_FORMAT_HEIGHT 84       /* R-- */
+#define NV_CTRL_GVO_VIDEO_FORMAT_REFRESH_RATE 85 /* R-- */
+
+/*
+ * NV_CTRL_GVO_X_SCREEN_PAN_[XY] - no longer supported
+ */
+
+#define NV_CTRL_GVO_X_SCREEN_PAN_X 86 /* RW- */
+#define NV_CTRL_GVO_X_SCREEN_PAN_Y 87 /* RW- */
+
+/*
+ * NV_CTRL_GPU_OVERCLOCKING_STATE - query the current or set a new
+ * overclocking state; the value of this attribute controls the
+ * availability of additional overclocking attributes (see below).
+ *
+ * Note: this attribute is unavailable unless overclocking support
+ * has been enabled in the X server (by the user).
+ */
+
+#define NV_CTRL_GPU_OVERCLOCKING_STATE 88 /* RW-G */
+#define NV_CTRL_GPU_OVERCLOCKING_STATE_NONE 0
+#define NV_CTRL_GPU_OVERCLOCKING_STATE_MANUAL 1
+
+/*
+ * NV_CTRL_GPU_{2,3}D_CLOCK_FREQS - query or set the GPU and memory
+ * clocks of the device driving the X screen.  New clock frequencies
+ * are tested before being applied, and may be rejected.
+ *
+ * Note: if the target clocks are too aggressive, their testing may
+ * render the system unresponsive.
+ *
+ * Note: while this attribute can always be queried, it can't be set
+ * unless NV_CTRL_GPU_OVERCLOCKING_STATE is set to _MANUAL.  Since
+ * the target clocks may be rejected, the requester should read this
+ * attribute after the set to determine success or failure.
+ *
+ * NV_CTRL_GPU_{2,3}D_CLOCK_FREQS are "packed" integer attributes; the
+ * GPU clock is stored in the upper 16 bits of the integer, and the
+ * memory clock is stored in the lower 16 bits of the integer.  All
+ * clock values are in MHz.
+ */
+
+#define NV_CTRL_GPU_2D_CLOCK_FREQS 89 /* RW-G */
+#define NV_CTRL_GPU_3D_CLOCK_FREQS 90 /* RW-G */
+
+/*
+ * NV_CTRL_GPU_DEFAULT_{2,3}D_CLOCK_FREQS - query the default memory
+ * and GPU core clocks of the device driving the X screen.
+ *
+ * NV_CTRL_GPU_DEFAULT_{2,3}D_CLOCK_FREQS are "packed" integer
+ * attributes; the GPU clock is stored in the upper 16 bits of the
+ * integer, and the memory clock is stored in the lower 16 bits of the
+ * integer.  All clock values are in MHz.
+ */
+
+#define NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS 91 /* R--G */
+#define NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS 92 /* R--G */
+
+/*
+ * NV_CTRL_GPU_CURRENT_CLOCK_FREQS - query the current GPU and memory
+ * clocks of the graphics device driving the X screen.
+ *
+ * NV_CTRL_GPU_CURRENT_CLOCK_FREQS is a "packed" integer attribute;
+ * the GPU clock is stored in the upper 16 bits of the integer, and
+ * the memory clock is stored in the lower 16 bits of the integer.
+ * All clock values are in MHz.  All clock values are in MHz.
+ */
+
+#define NV_CTRL_GPU_CURRENT_CLOCK_FREQS 93 /* R--G */
+
+/*
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS - Holds the last calculated
+ * optimal 3D clock frequencies found by the
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION process.  Querying this
+ * attribute before having probed for the optimal clocks will return
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_INVALID
+ *
+ * Note: unless NV_CTRL_GPU_OVERCLOCKING_STATE is set to _MANUAL, the
+ * optimal clock detection process is unavailable.
+ */
+
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS 94 /* R--G */
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_INVALID 0
+
+/*
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION - set to _START to
+ * initiate testing for the optimal 3D clock frequencies.  Once
+ * found, the optimal clock frequencies will be returned by the
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS attribute asynchronously
+ * (using an X event, see XNVCtrlSelectNotify).
+ *
+ * To cancel an ongoing test for the optimal clocks, set the
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION attribute to _CANCEL
+ *
+ * Note: unless NV_CTRL_GPU_OVERCLOCKING_STATE is set to _MANUAL, the
+ * optimal clock detection process is unavailable.
+ */
+
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION 95 /* -W-G */
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_START 0
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_CANCEL 1
+
+/*
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE - query this
+ * variable to know if a test is currently being run to
+ * determine the optimal 3D clock frequencies.  _BUSY means a
+ * test is currently running, _IDLE means the test is not running.
+ *
+ * Note: unless NV_CTRL_GPU_OVERCLOCKING_STATE is set to _MANUAL, the
+ * optimal clock detection process is unavailable.
+ */
+
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE 96 /* R--G */
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_IDLE 0
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_BUSY 1
+
+/*
+ * NV_CTRL_FLATPANEL_CHIP_LOCATION - for the specified display device,
+ * report whether the flat panel is driven by the on-chip controller,
+ * or a separate controller chip elsewhere on the graphics board.
+ * This attribute is only available for flat panels.
+ */
+
+#define NV_CTRL_FLATPANEL_CHIP_LOCATION 215 /* R-DG */
+#define NV_CTRL_FLATPANEL_CHIP_LOCATION_INTERNAL 0
+#define NV_CTRL_FLATPANEL_CHIP_LOCATION_EXTERNAL 1
+
+/*
+ * NV_CTRL_FLATPANEL_LINK - report the number of links for a DVI connection, or
+ * the main link's active lane count for DisplayPort.
+ * This attribute is only available for flat panels.
+ */
+
+#define NV_CTRL_FLATPANEL_LINK 216 /* R-DG */
+#define NV_CTRL_FLATPANEL_LINK_SINGLE 0
+#define NV_CTRL_FLATPANEL_LINK_DUAL 1
+#define NV_CTRL_FLATPANEL_LINK_QUAD 3
+
+/*
+ * NV_CTRL_FLATPANEL_SIGNAL - for the specified display device, report
+ * whether the flat panel is driven by an LVDS, TMDS, or DisplayPort signal.
+ * This attribute is only available for flat panels.
+ */
+
+#define NV_CTRL_FLATPANEL_SIGNAL 217 /* R-DG */
+#define NV_CTRL_FLATPANEL_SIGNAL_LVDS 0
+#define NV_CTRL_FLATPANEL_SIGNAL_TMDS 1
+#define NV_CTRL_FLATPANEL_SIGNAL_DISPLAYPORT 2
+
+/*
+ * NV_CTRL_USE_HOUSE_SYNC - when TRUE, the server (master) frame lock
+ * device will propagate the incoming house sync signal as the outgoing
+ * frame lock sync signal.  If the frame lock device cannot detect a
+ * frame lock sync signal, it will default to using the internal timings
+ * from the GPU connected to the primary connector.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_USE_HOUSE_SYNC 218 /* RW-F */
+#define NV_CTRL_USE_HOUSE_SYNC_FALSE 0
+#define NV_CTRL_USE_HOUSE_SYNC_TRUE 1
+
+/*
+ * NV_CTRL_EDID_AVAILABLE - report if an EDID is available for the
+ * specified display device.
+ *
+ * This attribute may also be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_EDID_AVAILABLE 219 /* R-DG */
+#define NV_CTRL_EDID_AVAILABLE_FALSE 0
+#define NV_CTRL_EDID_AVAILABLE_TRUE 1
+
+/*
+ * NV_CTRL_FORCE_STEREO - when TRUE, OpenGL will force stereo flipping
+ * even when no stereo drawables are visible (if the device is configured
+ * to support it, see the "Stereo" X config option).
+ * When false, fall back to the default behavior of only flipping when a
+ * stereo drawable is visible.
+ */
+
+#define NV_CTRL_FORCE_STEREO 220 /* RW- */
+#define NV_CTRL_FORCE_STEREO_FALSE 0
+#define NV_CTRL_FORCE_STEREO_TRUE 1
+
+/*
+ * NV_CTRL_IMAGE_SETTINGS - the image quality setting for OpenGL clients.
+ *
+ * This setting is only applied to OpenGL clients that are started
+ * after this setting is applied.
+ */
+
+#define NV_CTRL_IMAGE_SETTINGS 221 /* RW-X */
+#define NV_CTRL_IMAGE_SETTINGS_HIGH_QUALITY 0
+#define NV_CTRL_IMAGE_SETTINGS_QUALITY 1
+#define NV_CTRL_IMAGE_SETTINGS_PERFORMANCE 2
+#define NV_CTRL_IMAGE_SETTINGS_HIGH_PERFORMANCE 3
+
+/*
+ * NV_CTRL_XINERAMA - return whether xinerama is enabled
+ */
+
+#define NV_CTRL_XINERAMA 222 /* R--G */
+#define NV_CTRL_XINERAMA_OFF 0
+#define NV_CTRL_XINERAMA_ON 1
+
+/*
+ * NV_CTRL_XINERAMA_STEREO - when TRUE, OpenGL will allow stereo flipping
+ * on multiple X screens configured with Xinerama.
+ * When FALSE, flipping is allowed only on one X screen at a time.
+ */
+
+#define NV_CTRL_XINERAMA_STEREO 223 /* RW- */
+#define NV_CTRL_XINERAMA_STEREO_FALSE 0
+#define NV_CTRL_XINERAMA_STEREO_TRUE 1
+
+/*
+ * NV_CTRL_BUS_RATE - if the bus type of the specified device is AGP, then
+ * NV_CTRL_BUS_RATE returns the configured AGP transfer rate.  If the bus type
+ * is PCI Express, then this attribute returns the maximum link width.
+ * When this attribute is queried on an X screen target, the bus rate of the
+ * GPU driving the X screen is returned.
+ */
+
+#define NV_CTRL_BUS_RATE 224 /* R--GI */
+
+/*
+ * NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH - returns the maximum
+ * PCIe link width, in number of lanes.
+ */
+#define NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH NV_CTRL_BUS_RATE
+
+/*
+ * NV_CTRL_SHOW_SLI_HUD - when TRUE, OpenGL will draw information about the
+ * current SLI mode.
+ * Renamed this attribute to NV_CTRL_SHOW_SLI_VISUAL_INDICATOR
+ */
+
+#define NV_CTRL_SHOW_SLI_HUD NV_CTRL_SHOW_SLI_VISUAL_INDICATOR
+#define NV_CTRL_SHOW_SLI_HUD_FALSE NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_FALSE
+#define NV_CTRL_SHOW_SLI_HUD_TRUE NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_TRUE
+
+/*
+ * NV_CTRL_SHOW_SLI_VISUAL_INDICATOR - when TRUE, OpenGL will draw information
+ * about the current SLI mode.
+ */
+
+#define NV_CTRL_SHOW_SLI_VISUAL_INDICATOR 225 /* RW-X */
+#define NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_FALSE 0
+#define NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_TRUE 1
+
+/*
+ * NV_CTRL_XV_SYNC_TO_DISPLAY - this control is valid when TwinView and
+ * XVideo Sync To VBlank are enabled.
+ * It controls which display device will be synched to.
+ */
+
+#define NV_CTRL_XV_SYNC_TO_DISPLAY 226 /* RW- */
+
+/*
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 - this attribute is only
+ * intended to be used to query the ValidValues for
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for VIDEO_FORMAT values between
+ * 31 and 63.  See NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for details.
+ */
+
+#define NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 227 /* ---GI */
+
+/*
+ * The following is deprecated; use NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2,
+ * instead
+ */
+#define NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2 227 /* --- */
+
+/*
+ * NV_CTRL_GVO_OVERRIDE_HW_CSC - Override the SDI hardware's Color Space
+ * Conversion with the values controlled through
+ * XNVCTRLSetGvoColorConversion() and XNVCTRLGetGvoColorConversion().  If
+ * this attribute is FALSE, then the values specified through
+ * XNVCTRLSetGvoColorConversion() are ignored.
+ */
+
+#define NV_CTRL_GVO_OVERRIDE_HW_CSC 228 /* RW- */
+#define NV_CTRL_GVO_OVERRIDE_HW_CSC_FALSE 0
+#define NV_CTRL_GVO_OVERRIDE_HW_CSC_TRUE 1
+
+/*
+ * NV_CTRL_GVO_CAPABILITIES - this read-only attribute describes GVO
+ * capabilities that differ between NVIDIA SDI products.  This value
+ * is a bitmask where each bit indicates whether that capability is
+ * available.
+ *
+ * APPLY_CSC_IMMEDIATELY - whether the CSC matrix, offset, and scale
+ * specified through XNVCTRLSetGvoColorConversion() will take affect
+ * immediately, or only after SDI output is disabled and enabled
+ * again.
+ *
+ * APPLY_CSC_TO_X_SCREEN - whether the CSC matrix, offset, and scale
+ * specified through XNVCTRLSetGvoColorConversion() will also apply
+ * to GVO output of an X screen, or only to OpenGL GVO output, as
+ * enabled through the GLX_NV_video_out extension.
+ *
+ * COMPOSITE_TERMINATION - whether the 75 ohm termination of the
+ * SDI composite input signal can be programmed through the
+ * NV_CTRL_GVO_COMPOSITE_TERMINATION attribute.
+ *
+ * SHARED_SYNC_BNC - whether the SDI device has a single BNC
+ * connector used for both (SDI & Composite) incoming signals.
+ *
+ * MULTIRATE_SYNC - whether the SDI device supports synchronization
+ * of input and output video modes that match in being odd or even
+ * modes (ie, AA.00 Hz modes can be synched to other BB.00 Hz modes and
+ * AA.XX Hz can match to BB.YY Hz where .XX and .YY are not .00)
+ */
+
+#define NV_CTRL_GVO_CAPABILITIES 229 /* R-- */
+#define NV_CTRL_GVO_CAPABILITIES_APPLY_CSC_IMMEDIATELY 0x00000001
+#define NV_CTRL_GVO_CAPABILITIES_APPLY_CSC_TO_X_SCREEN 0x00000002
+#define NV_CTRL_GVO_CAPABILITIES_COMPOSITE_TERMINATION 0x00000004
+#define NV_CTRL_GVO_CAPABILITIES_SHARED_SYNC_BNC 0x00000008
+#define NV_CTRL_GVO_CAPABILITIES_MULTIRATE_SYNC 0x00000010
+#define NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW 0x00000020
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_TERMINATION - enable or disable 75 ohm
+ * termination of the SDI composite input signal.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_TERMINATION 230 /* RW- */
+#define NV_CTRL_GVO_COMPOSITE_TERMINATION_ENABLE 1
+#define NV_CTRL_GVO_COMPOSITE_TERMINATION_DISABLE 0
+
+/*
+ * NV_CTRL_ASSOCIATED_DISPLAY_DEVICES - display device mask indicating
+ * which display devices are "associated" with the specified X screen
+ * (ie: are available to the X screen for displaying the X screen).
+ */
+
+#define NV_CTRL_ASSOCIATED_DISPLAY_DEVICES 231 /* RW- */
+
+/*
+ * NV_CTRL_FRAMELOCK_SLAVES - get/set whether the display device(s)
+ * given should listen or ignore the master's sync signal.
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_FRAMELOCK_SLAVES 232 /* RW-G */
+
+/*
+ * NV_CTRL_FRAMELOCK_MASTERABLE - Can any of the given display devices
+ * be set as master of the frame lock group.  Returns a bitmask of the
+ * corresponding display devices that can be set as master.
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_FRAMELOCK_MASTERABLE 233 /* R-DG */
+
+/*
+ * NV_CTRL_PROBE_DISPLAYS - re-probes the hardware to detect what
+ * display devices are connected to the GPU or GPU driving the
+ * specified X screen.  Returns a display mask.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_PROBE_DISPLAYS 234 /* R--G */
+
+/*
+ * NV_CTRL_REFRESH_RATE - Returns the refresh rate of the specified
+ * display device in 100 * Hz (ie. to get the refresh rate in Hz, divide
+ * the returned value by 100.)
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_REFRESH_RATE 235 /* R-DG */
+
+/*
+ * NV_CTRL_GVO_FLIP_QUEUE_SIZE - The Graphics to Video Out interface
+ * exposed through NV-CONTROL and the GLX_NV_video_out extension uses
+ * an internal flip queue when pbuffers are sent to the video device
+ * (via glXSendPbufferToVideoNV()).  The NV_CTRL_GVO_FLIP_QUEUE_SIZE
+ * can be used to query and assign the flip queue size.  This
+ * attribute is applied to GLX when glXGetVideoDeviceNV() is called by
+ * the application.
+ */
+
+#define NV_CTRL_GVO_FLIP_QUEUE_SIZE 236 /* RW- */
+
+/*
+ * NV_CTRL_CURRENT_SCANLINE - query the current scanline for the
+ * specified display device.
+ */
+
+#define NV_CTRL_CURRENT_SCANLINE 237 /* R-DG */
+
+/*
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT - Controls where X pixmaps are initially
+ * created.
+ *
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_FORCE_SYSMEM causes pixmaps to stay in
+ * system memory. These pixmaps can't be accelerated by the NVIDIA driver; this
+ * will cause blank windows if used with an OpenGL compositing manager.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_SYSMEM creates pixmaps in system memory
+ * initially, but allows them to migrate to video memory.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_VIDMEM creates pixmaps in video memory
+ * when enough resources are available.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_RESERVED is currently reserved for future
+ * use.  Behavior is undefined.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_GPU_SYSMEM creates pixmaps in GPU accessible
+ * system memory when enough resources are available.
+ */
+
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT 238 /* RW- */
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_FORCE_SYSMEM 0
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_SYSMEM 1
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_VIDMEM 2
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_RESERVED 3
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_GPU_SYSMEM 4
+
+/*
+ * NV_CTRL_PCI_BUS - Returns the PCI bus number the specified device is using.
+ */
+
+#define NV_CTRL_PCI_BUS 239 /* R--GI */
+
+/*
+ * NV_CTRL_PCI_DEVICE - Returns the PCI device number the specified device is
+ * using.
+ */
+
+#define NV_CTRL_PCI_DEVICE 240 /* R--GI */
+
+/*
+ * NV_CTRL_PCI_FUNCTION - Returns the PCI function number the specified device
+ * is using.
+ */
+
+#define NV_CTRL_PCI_FUNCTION 241 /* R--GI */
+
+/*
+ * NV_CTRL_FRAMELOCK_FPGA_REVISION - Querys the FPGA revision of the
+ * Frame Lock device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK target.
+ */
+
+#define NV_CTRL_FRAMELOCK_FPGA_REVISION 242 /* R--F */
+
+/*
+ * NV_CTRL_MAX_SCREEN_{WIDTH,HEIGHT} - the maximum allowable size, in
+ * pixels, of either the specified X screen (if the target_type of the
+ * query is an X screen), or any X screen on the specified GPU (if the
+ * target_type of the query is a GPU).
+ */
+
+#define NV_CTRL_MAX_SCREEN_WIDTH 243  /* R--G */
+#define NV_CTRL_MAX_SCREEN_HEIGHT 244 /* R--G */
+
+/*
+ * NV_CTRL_MAX_DISPLAYS - the maximum number of display devices that
+ * can be driven simultaneously on a GPU (e.g., that can be used in a
+ * MetaMode at once).  Note that this does not indicate the maximum
+ * number of bits that can be set in NV_CTRL_CONNECTED_DISPLAYS,
+ * because more display devices can be connected than are actively in
+ * use.
+ */
+
+#define NV_CTRL_MAX_DISPLAYS 245 /* R--G */
+
+/*
+ * NV_CTRL_DYNAMIC_TWINVIEW - Returns whether or not the screen
+ * supports dynamic twinview.
+ */
+
+#define NV_CTRL_DYNAMIC_TWINVIEW 246 /* R-- */
+
+/*
+ * NV_CTRL_MULTIGPU_DISPLAY_OWNER - Returns the (NV-CONTROL) GPU ID of
+ * the GPU that has the display device(s) used for showing the X Screen.
+ */
+
+#define NV_CTRL_MULTIGPU_DISPLAY_OWNER 247 /* R-- */
+
+/*
+ * NV_CTRL_GPU_SCALING - not supported
+ */
+
+#define NV_CTRL_GPU_SCALING 248 /* RWDG */
+
+#define NV_CTRL_GPU_SCALING_TARGET_INVALID 0
+#define NV_CTRL_GPU_SCALING_TARGET_FLATPANEL_BEST_FIT 1
+#define NV_CTRL_GPU_SCALING_TARGET_FLATPANEL_NATIVE 2
+
+#define NV_CTRL_GPU_SCALING_METHOD_INVALID 0
+#define NV_CTRL_GPU_SCALING_METHOD_STRETCHED 1
+#define NV_CTRL_GPU_SCALING_METHOD_CENTERED 2
+#define NV_CTRL_GPU_SCALING_METHOD_ASPECT_SCALED 3
+
+/*
+ * NV_CTRL_FRONTEND_RESOLUTION - not supported
+ */
+
+#define NV_CTRL_FRONTEND_RESOLUTION 249 /* R-DG */
+
+/*
+ * NV_CTRL_BACKEND_RESOLUTION - not supported
+ */
+
+#define NV_CTRL_BACKEND_RESOLUTION 250 /* R-DG */
+
+/*
+ * NV_CTRL_FLATPANEL_NATIVE_RESOLUTION - Returns the dimensions of the
+ * native resolution of the flat panel as determined by the
+ * NVIDIA X Driver.
+ *
+ * The native resolution is the resolution at which a flat panel
+ * must display any image.  All other resolutions must be scaled to this
+ * resolution through GPU scaling or the DFP's native scaling capabilities
+ * in order to be displayed.
+ *
+ * This attribute is only valid for flat panel (DFP) display devices.
+ *
+ * This attribute is a packed integer; the width is packed in the upper
+ * 16-bits and the height is packed in the lower 16-bits.
+ */
+
+#define NV_CTRL_FLATPANEL_NATIVE_RESOLUTION 251 /* R-DG */
+
+/*
+ * NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION - not supported
+ */
+
+#define NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION 252 /* R-DG */
+
+/*
+ * NV_CTRL_GPU_SCALING_ACTIVE - not supported
+ */
+
+#define NV_CTRL_GPU_SCALING_ACTIVE 253 /* R-DG */
+
+/*
+ * NV_CTRL_DFP_SCALING_ACTIVE - not supported
+ */
+
+#define NV_CTRL_DFP_SCALING_ACTIVE 254 /* R-DG */
+
+/*
+ * NV_CTRL_FSAA_APPLICATION_ENHANCED - Controls how the NV_CTRL_FSAA_MODE
+ * is applied when NV_CTRL_FSAA_APPLICATION_CONTROLLED is set to
+ * NV_CTRL_APPLICATION_CONTROLLED_DISABLED.  When
+ * NV_CTRL_FSAA_APPLICATION_ENHANCED is _DISABLED, OpenGL applications will
+ * be forced to use the FSAA mode specified by NV_CTRL_FSAA_MODE.  when set
+ * to _ENABLED, only those applications that have selected a multisample
+ * FBConfig will be made to use the NV_CTRL_FSAA_MODE specified.
+ *
+ * This attribute is ignored when NV_CTRL_FSAA_APPLICATION_CONTROLLED is
+ * set to NV_CTRL_FSAA_APPLICATION_CONTROLLED_ENABLED.
+ */
+
+#define NV_CTRL_FSAA_APPLICATION_ENHANCED 255 /* RW-X */
+#define NV_CTRL_FSAA_APPLICATION_ENHANCED_ENABLED 1
+#define NV_CTRL_FSAA_APPLICATION_ENHANCED_DISABLED 0
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_RATE_4 - This is the refresh rate that the
+ * frame lock board is sending to the GPU with 4 digits of precision.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_RATE_4 256 /* R--F */
+
+/*
+ * NV_CTRL_GVO_LOCK_OWNER - indicates that the GVO device is available
+ * or in use (by GLX or an X screen).
+ *
+ * The GVO device is locked by GLX when either glXGetVideoDeviceNV
+ * (part of GLX_NV_video_out) or glXBindVideoDeviceNV (part of
+ * GLX_NV_present_video) is called.  All GVO output resources are
+ * locked until released by the GLX_NV_video_out/GLX_NV_present_video
+ * client.
+ *
+ * The GVO device is locked/unlocked by an X screen, when the GVO device is
+ * used in a MetaMode on an X screen.
+ *
+ * When the GVO device is locked, setting of the following GVO NV-CONTROL
+ * attributes will not happen immediately and will instead be cached.  The
+ * GVO resource will need to be disabled/released and re-enabled/claimed for
+ * the values to be flushed. These attributes are:
+ *
+ *    NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT
+ *    NV_CTRL_GVO_DATA_FORMAT
+ *    NV_CTRL_GVO_FLIP_QUEUE_SIZE
+ */
+
+#define NV_CTRL_GVO_LOCK_OWNER 257 /* R-- */
+#define NV_CTRL_GVO_LOCK_OWNER_NONE 0
+#define NV_CTRL_GVO_LOCK_OWNER_GLX 1
+#define NV_CTRL_GVO_LOCK_OWNER_CLONE /* no longer supported */ 2
+#define NV_CTRL_GVO_LOCK_OWNER_X_SCREEN 3
+
+/*
+ * NV_CTRL_HWOVERLAY - when a workstation overlay is in use, reports
+ * whether the hardware overlay is used, or if the overlay is emulated.
+ */
+
+#define NV_CTRL_HWOVERLAY 258 /* R-- */
+#define NV_CTRL_HWOVERLAY_FALSE 0
+#define NV_CTRL_HWOVERLAY_TRUE 1
+
+/*
+ * NV_CTRL_NUM_GPU_ERRORS_RECOVERED - Returns the number of GPU errors
+ * occured. This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_NUM_GPU_ERRORS_RECOVERED 259 /* R--- */
+
+/*
+ * NV_CTRL_REFRESH_RATE_3 - Returns the refresh rate of the specified
+ * display device in 1000 * Hz (ie. to get the refresh rate in Hz, divide
+ * the returned value by 1000.)
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_REFRESH_RATE_3 260 /* R-DG */
+
+/*
+ * NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS - if the OnDemandVBlankInterrupts
+ * X driver option is set to true, this attribute can be used to
+ * determine if on-demand VBlank interrupt control is enabled on the
+ * specified GPU, as well as to enable or disable this feature.
+ */
+
+#define NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS 261 /* RW-G */
+#define NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS_OFF 0
+#define NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS_ON 1
+
+/*
+ * NV_CTRL_GPU_POWER_SOURCE reports the type of power source
+ * of the GPU driving the X screen.
+ */
+
+#define NV_CTRL_GPU_POWER_SOURCE 262 /* R--G */
+#define NV_CTRL_GPU_POWER_SOURCE_AC 0
+#define NV_CTRL_GPU_POWER_SOURCE_BATTERY 1
+
+/*
+ * NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE is deprecated
+ */
+
+#define NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE 263 /* R--G */
+#define NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE_DESKTOP 0
+#define NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE_MAXPERF 1
+
+/* NV_CTRL_GLYPH_CACHE - Enables RENDER Glyph Caching to VRAM */
+
+#define NV_CTRL_GLYPH_CACHE 264 /* RW- */
+#define NV_CTRL_GLYPH_CACHE_DISABLED 0
+#define NV_CTRL_GLYPH_CACHE_ENABLED 1
+
+/*
+ * NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL reports the current
+ * Performance level of the GPU driving the X screen.  Each
+ * Performance level has associated NVClock and Mem Clock values.
+ */
+
+#define NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL 265 /* R--G */
+
+/*
+ * NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE reports if Adaptive Clocking
+ * is Enabled on the GPU driving the X screen.
+ */
+
+#define NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE 266 /* R--G */
+#define NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE_DISABLED 0
+#define NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE_ENABLED 1
+
+/*
+ * NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED - Returns whether or not the GVO output
+ * video is locked to the GPU.
+ */
+
+#define NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED 267 /* R--- */
+#define NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED_FALSE 0
+#define NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED_TRUE 1
+
+/*
+ * NV_CTRL_GVO_SYNC_LOCK_STATUS - Returns whether or not the GVO device
+ * is locked to the input ref signal.  If the sync mode is set to
+ * NV_CTRL_GVO_SYNC_MODE_GENLOCK, then this returns the genlock
+ * sync status, and if the sync mode is set to NV_CTRL_GVO_SYNC_MODE_FRAMELOCK,
+ * then this reports the frame lock status.
+ */
+
+#define NV_CTRL_GVO_SYNC_LOCK_STATUS 268 /* R--- */
+#define NV_CTRL_GVO_SYNC_LOCK_STATUS_UNLOCKED 0
+#define NV_CTRL_GVO_SYNC_LOCK_STATUS_LOCKED 1
+
+/*
+ * NV_CTRL_GVO_ANC_TIME_CODE_GENERATION - Allows SDI device to generate
+ * time codes in the ANC region of the SDI video output stream.
+ */
+
+#define NV_CTRL_GVO_ANC_TIME_CODE_GENERATION 269 /* RW-- */
+#define NV_CTRL_GVO_ANC_TIME_CODE_GENERATION_DISABLE 0
+#define NV_CTRL_GVO_ANC_TIME_CODE_GENERATION_ENABLE 1
+
+/*
+ * NV_CTRL_GVO_COMPOSITE - Enables/Disables SDI compositing.  This attribute
+ * is only available when an SDI input source is detected and is in genlock
+ * mode.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE 270 /* RW-- */
+#define NV_CTRL_GVO_COMPOSITE_DISABLE 0
+#define NV_CTRL_GVO_COMPOSITE_ENABLE 1
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_ALPHA_KEY - When compositing is enabled, this
+ * enables/disables alpha blending.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_ALPHA_KEY 271 /* RW-- */
+#define NV_CTRL_GVO_COMPOSITE_ALPHA_KEY_DISABLE 0
+#define NV_CTRL_GVO_COMPOSITE_ALPHA_KEY_ENABLE 1
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_LUMA_KEY_RANGE - Set the values of a luma
+ * channel range.  This is a packed int that has the following format
+ * (in order of high-bits to low bits):
+ *
+ * Range # (11 bits), (Enabled 1 bit), min value (10 bits), max value (10 bits)
+ *
+ * To query the current values, pass the range # throught the display_mask
+ * variable.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_LUMA_KEY_RANGE 272 /* RW-- */
+
+#define NV_CTRL_GVO_COMPOSITE_MAKE_RANGE(range, enable, min, max)            \
+    ((((min)&0x3FF) << 0) | (((max)&0x3FF) << 10) | (((enable)&0x1) << 20) | \
+     (((range)&0x7FF) << 21))
+
+#define NV_CTRL_GVO_COMPOSITE_GET_RANGE(val, range, enable, min, max) \
+    (min) = ((val) >> 0) & 0x3FF;                                     \
+    (max) = ((val) >> 10) & 0x3FF;                                    \
+    (enable) = ((val) >> 20) & 0x1;                                   \
+    (range) = ((val) >> 21) & 0x7FF;
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_CR_KEY_RANGE - Set the values of a CR
+ * channel range.  This is a packed int that has the following format
+ * (in order of high-bits to low bits):
+ *
+ * Range # (11 bits), (Enabled 1 bit), min value (10 bits), max value (10 bits)
+ *
+ * To query the current values, pass the range # throught he display_mask
+ * variable.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_CR_KEY_RANGE 273 /* RW-- */
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_CB_KEY_RANGE - Set the values of a CB
+ * channel range.  This is a packed int that has the following format
+ * (in order of high-bits to low bits):
+ *
+ * Range # (11 bits), (Enabled 1 bit), min value (10 bits), max value (10 bits)
+ *
+ * To query the current values, pass the range # throught he display_mask
+ * variable.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_CB_KEY_RANGE 274 /* RW-- */
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_NUM_KEY_RANGES - Returns the number of ranges
+ * available for each channel (Y/Luma, Cr, and Cb.)
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_NUM_KEY_RANGES 275 /* R--- */
+
+/*
+ * NV_CTRL_SWITCH_TO_DISPLAYS - Can be used to select which displays
+ * to switch to (as a hotkey event).
+ */
+
+#define NV_CTRL_SWITCH_TO_DISPLAYS 276 /* -W- */
+
+/*
+ * NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT - Event that notifies
+ * when a notebook lid change occurs (i.e. when the lid is opened or
+ * closed.)  This attribute can be queried to retrieve the current
+ * notebook lid status (opened/closed.)
+ */
+
+#define NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT 277 /* RW- */
+#define NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT_CLOSE 0
+#define NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT_OPEN 1
+
+/*
+ * NV_CTRL_NOTEBOOK_INTERNAL_LCD - Returns the display device mask of
+ * the intenal LCD of a notebook.
+ */
+
+#define NV_CTRL_NOTEBOOK_INTERNAL_LCD 278 /* R-- */
+
+/*
+ * NV_CTRL_DEPTH_30_ALLOWED - returns whether the NVIDIA X driver supports
+ * depth 30 on the specified X screen or GPU.
+ */
+
+#define NV_CTRL_DEPTH_30_ALLOWED 279 /* R--G */
+
+/*
+ * NV_CTRL_MODE_SET_EVENT This attribute is sent as an event
+ * when hotkey, ctrl-alt-+/- or randr event occurs.  Note that
+ * This attribute cannot be set or queried and is meant to
+ * be received by clients that wish to be notified of when
+ * mode set events occur.
+ */
+
+#define NV_CTRL_MODE_SET_EVENT 280 /* --- */
+
+/*
+ * NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE - the gamma value used by
+ * OpenGL when NV_CTRL_OPENGL_AA_LINE_GAMMA is enabled
+ */
+
+#define NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE 281 /* RW-X */
+
+/*
+ * NV_CTRL_VCSC_HIGH_PERF_MODE - Is used to both query High Performance Mode
+ * status on the Visual Computing System, and also to enable or disable High
+ * Performance Mode.
+ */
+
+#define NV_CTRL_VCSC_HIGH_PERF_MODE 282 /* RW-V */
+#define NV_CTRL_VCSC_HIGH_PERF_MODE_DISABLE 0
+#define NV_CTRL_VCSC_HIGH_PERF_MODE_ENABLE 1
+
+/*
+ * NV_CTRL_DISPLAYPORT_LINK_RATE - returns the negotiated lane bandwidth of the
+ * DisplayPort main link.
+ * This attribute is only available for DisplayPort flat panels.
+ */
+
+#define NV_CTRL_DISPLAYPORT_LINK_RATE 291 /* R-DG */
+#define NV_CTRL_DISPLAYPORT_LINK_RATE_DISABLED 0x0
+#define NV_CTRL_DISPLAYPORT_LINK_RATE_1_62GBPS 0x6
+#define NV_CTRL_DISPLAYPORT_LINK_RATE_2_70GBPS 0xA
+
+/*
+ * NV_CTRL_STEREO_EYES_EXCHANGE - Controls whether or not the left and right
+ * eyes of a stereo image are flipped.
+ */
+
+#define NV_CTRL_STEREO_EYES_EXCHANGE 292 /* RW-X */
+#define NV_CTRL_STEREO_EYES_EXCHANGE_OFF 0
+#define NV_CTRL_STEREO_EYES_EXCHANGE_ON 1
+
+/*
+ * NV_CTRL_NO_SCANOUT - returns whether the special "NoScanout" mode is
+ * enabled on the specified X screen or GPU; for details on this mode,
+ * see the description of the "none" value for the "UseDisplayDevice"
+ * X configuration option in the NVIDIA driver README.
+ */
+
+#define NV_CTRL_NO_SCANOUT 293 /* R--G */
+#define NV_CTRL_NO_SCANOUT_DISABLED 0
+#define NV_CTRL_NO_SCANOUT_ENABLED 1
+
+/*
+ * NV_CTRL_GVO_CSC_CHANGED_EVENT This attribute is sent as an event
+ * when the color space conversion matrix has been altered by another
+ * client.
+ */
+
+#define NV_CTRL_GVO_CSC_CHANGED_EVENT 294 /* --- */
+
+/*
+ * NV_CTRL_FRAMELOCK_SLAVEABLE - Returns a bitmask of the display devices
+ * that are (currently) allowed to be selected as slave devices for the
+ * given GPU
+ */
+
+#define NV_CTRL_FRAMELOCK_SLAVEABLE 295 /* R-DG */
+
+/*
+ * NV_CTRL_GVO_SYNC_TO_DISPLAY This attribute controls whether or not
+ * the non-SDI display device will be sync'ed to the SDI display device
+ * (when configured in TwinView, Clone Mode or when using the SDI device
+ * with OpenGL).
+ */
+
+#define NV_CTRL_GVO_SYNC_TO_DISPLAY 296 /* --- */
+#define NV_CTRL_GVO_SYNC_TO_DISPLAY_DISABLE 0
+#define NV_CTRL_GVO_SYNC_TO_DISPLAY_ENABLE 1
+
+/*
+ * NV_CTRL_X_SERVER_UNIQUE_ID - returns a pseudo-unique identifier for this
+ * X server. Intended for use in cases where an NV-CONTROL client communicates
+ * with multiple X servers, and wants some level of confidence that two
+ * X Display connections correspond to the same or different X servers.
+ */
+
+#define NV_CTRL_X_SERVER_UNIQUE_ID 297 /* R--- */
+
+/*
+ * NV_CTRL_PIXMAP_CACHE - This attribute controls whether the driver attempts to
+ * store video memory pixmaps in a cache.  The cache speeds up allocation and
+ * deallocation of pixmaps, but could use more memory than when the cache is
+ * disabled.
+ */
+
+#define NV_CTRL_PIXMAP_CACHE 298 /* RW-X */
+#define NV_CTRL_PIXMAP_CACHE_DISABLE 0
+#define NV_CTRL_PIXMAP_CACHE_ENABLE 1
+
+/*
+ * NV_CTRL_PIXMAP_CACHE_ROUNDING_SIZE_KB - When the pixmap cache is enabled and
+ * there is not enough free space in the cache to fit a new pixmap, the driver
+ * will round up to the next multiple of this number of kilobytes when
+ * allocating more memory for the cache.
+ */
+
+#define NV_CTRL_PIXMAP_CACHE_ROUNDING_SIZE_KB 299 /* RW-X */
+
+/*
+ * NV_CTRL_IS_GVO_DISPLAY - returns whether or not a given display is an
+ * SDI device.
+ */
+
+#define NV_CTRL_IS_GVO_DISPLAY 300 /* R-D */
+#define NV_CTRL_IS_GVO_DISPLAY_FALSE 0
+#define NV_CTRL_IS_GVO_DISPLAY_TRUE 1
+
+/*
+ * NV_CTRL_PCI_ID - Returns the PCI vendor and device ID of the specified
+ * device.
+ *
+ * NV_CTRL_PCI_ID is a "packed" integer attribute; the PCI vendor ID is stored
+ * in the upper 16 bits of the integer, and the PCI device ID is stored in the
+ * lower 16 bits of the integer.
+ */
+
+#define NV_CTRL_PCI_ID 301 /* R--GI */
+
+/*
+ * NV_CTRL_GVO_FULL_RANGE_COLOR - Allow full range color data [4-1019]
+ * without clamping to [64-940].
+ */
+
+#define NV_CTRL_GVO_FULL_RANGE_COLOR 302 /* RW- */
+#define NV_CTRL_GVO_FULL_RANGE_COLOR_DISABLED 0
+#define NV_CTRL_GVO_FULL_RANGE_COLOR_ENABLED 1
+
+/*
+ * NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE - Returns whether or not
+ * SLI Mosaic Mode supported.
+ */
+
+#define NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE 303 /* R-- */
+#define NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_FALSE 0
+#define NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_TRUE 1
+
+/*
+ * NV_CTRL_GVO_ENABLE_RGB_DATA - Allows clients to specify when
+ * the GVO board should process colors as RGB when the output data
+ * format is one of the NV_CTRL_GVO_DATA_FORMAT_???_PASSTRHU modes.
+ */
+
+#define NV_CTRL_GVO_ENABLE_RGB_DATA 304 /* RW- */
+#define NV_CTRL_GVO_ENABLE_RGB_DATA_DISABLE 0
+#define NV_CTRL_GVO_ENABLE_RGB_DATA_ENABLE 1
+
+/*
+ * NV_CTRL_IMAGE_SHARPENING_DEFAULT - Returns default value of
+ * Image Sharpening.
+ */
+
+#define NV_CTRL_IMAGE_SHARPENING_DEFAULT 305 /* R-- */
+
+/*
+ * NV_CTRL_PCI_DOMAIN - Returns the PCI domain number the specified device is
+ * using.
+ */
+
+#define NV_CTRL_PCI_DOMAIN 306 /* R--GI */
+
+/*
+ * NV_CTRL_GVI_NUM_JACKS - Returns the number of input BNC jacks available
+ * on a GVI device.
+ */
+
+#define NV_CTRL_GVI_NUM_JACKS 307 /* R--I */
+
+/*
+ * NV_CTRL_GVI_MAX_LINKS_PER_STREAM - Returns the maximum supported number of
+ * links that can be tied to one stream.
+ */
+
+#define NV_CTRL_GVI_MAX_LINKS_PER_STREAM 308 /* R--I */
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_BITS_PER_COMPONENT - Returns the detected
+ * number of bits per component (BPC) of data on the given input jack+
+ * channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_BITS_PER_COMPONENT 309 /* R--I */
+#define NV_CTRL_GVI_BITS_PER_COMPONENT_UNKNOWN 0
+#define NV_CTRL_GVI_BITS_PER_COMPONENT_8 1
+#define NV_CTRL_GVI_BITS_PER_COMPONENT_10 2
+#define NV_CTRL_GVI_BITS_PER_COMPONENT_12 3
+
+/*
+ * NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT - Specify the number of
+ * bits per component (BPC) of data for the captured stream.
+ * The stream number should be specified in the "display_mask" parameter.
+ *
+ * Note: Setting this attribute may also result in the following
+ *       NV-CONTROL attributes being reset on the GVI device (to ensure
+ *       the configuration remains valid):
+ *           NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING
+ */
+
+#define NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT 310 /* RW-I */
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_COMPONENT_SAMPLING - Returns the detected
+ * sampling format for the input jack+channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_COMPONENT_SAMPLING 311 /* R--I */
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_UNKNOWN 0
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_4444 1
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_4224 2
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_444 3
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_422 4
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_420 5
+
+/*
+ * NV_CTRL_GVI_REQUESTED_COMPONENT_SAMPLING - Specify the sampling format for
+ * the captured stream.
+ * The possible values are the NV_CTRL_GVI_DETECTED_COMPONENT_SAMPLING
+ * constants.
+ * The stream number should be specified in the "display_mask" parameter.
+ */
+
+#define NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING 312 /* RW-I */
+
+/*
+ * NV_CTRL_GVI_CHROMA_EXPAND - Enable or disable 4:2:2 -> 4:4:4 chroma
+ * expansion for the captured stream.  This value is ignored when a
+ * COMPONENT_SAMPLING format is selected that does not use chroma subsampling,
+ * or if a BITS_PER_COMPONENT value is selected that is not supported.
+ * The stream number should be specified in the "display_mask" parameter.
+ */
+
+#define NV_CTRL_GVI_REQUESTED_STREAM_CHROMA_EXPAND 313 /* RW-I */
+#define NV_CTRL_GVI_CHROMA_EXPAND_FALSE 0
+#define NV_CTRL_GVI_CHROMA_EXPAND_TRUE 1
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_COLOR_SPACE - Returns the detected color space
+ * of the input jack+channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_COLOR_SPACE 314 /* R--I */
+#define NV_CTRL_GVI_COLOR_SPACE_UNKNOWN 0
+#define NV_CTRL_GVI_COLOR_SPACE_GBR 1
+#define NV_CTRL_GVI_COLOR_SPACE_GBRA 2
+#define NV_CTRL_GVI_COLOR_SPACE_GBRD 3
+#define NV_CTRL_GVI_COLOR_SPACE_YCBCR 4
+#define NV_CTRL_GVI_COLOR_SPACE_YCBCRA 5
+#define NV_CTRL_GVI_COLOR_SPACE_YCBCRD 6
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_LINK_ID - Returns the detected link identifier
+ * for the given input jack+channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_LINK_ID 315 /* R--I */
+#define NV_CTRL_GVI_LINK_ID_UNKNOWN 0xFFFF
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_SMPTE352_IDENTIFIER - Returns the 4-byte
+ * SMPTE 352 identifier from the given input jack+channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_SMPTE352_IDENTIFIER 316 /* R--I */
+
+/*
+ * NV_CTRL_GVI_GLOBAL_IDENTIFIER - Returns a global identifier for the
+ * GVI device.  This identifier can be used to relate GVI devices named
+ * in NV-CONTROL with those enumerated in OpenGL.
+ */
+
+#define NV_CTRL_GVI_GLOBAL_IDENTIFIER 317 /* R--I */
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION - Returns the number of nanoseconds
+ * that one unit of NV_CTRL_FRAMELOCK_SYNC_DELAY corresponds to.
+ */
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION 318 /* R-- */
+
+/*
+ * NV_CTRL_GPU_COOLER_MANUAL_CONTROL - Query the current or set a new
+ * cooler control state; the value of this attribute controls the
+ * availability of additional cooler control attributes (see below).
+ *
+ * Note: this attribute is unavailable unless cooler control support
+ * has been enabled in the X server (by the user).
+ */
+
+#define NV_CTRL_GPU_COOLER_MANUAL_CONTROL 319 /* RW-G */
+#define NV_CTRL_GPU_COOLER_MANUAL_CONTROL_FALSE 0
+#define NV_CTRL_GPU_COOLER_MANUAL_CONTROL_TRUE 1
+
+/*
+ * NV_CTRL_THERMAL_COOLER_LEVEL - Returns cooler's current operating
+ * level.
+ */
+
+#define NV_CTRL_THERMAL_COOLER_LEVEL 320 /* RW-C */
+
+/* NV_CTRL_THERMAL_COOLER_LEVEL_SET_DEFAULT - Sets default values of
+ * cooler.
+ */
+
+#define NV_CTRL_THERMAL_COOLER_LEVEL_SET_DEFAULT 321 /* -W-C */
+
+/*
+ * NV_CTRL_THERMAL_COOLER_CONTROL_TYPE -
+ * Returns a cooler's control signal characteristics.
+ * The possible types are restricted, Variable and Toggle.
+ */
+
+#define NV_CTRL_THERMAL_COOLER_CONTROL_TYPE 322 /* R--C */
+#define NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_NONE 0
+#define NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_TOGGLE 1
+#define NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_VARIABLE 2
+
+/*
+ * NV_CTRL_THERMAL_COOLER_TARGET - Returns objects that cooler cools.
+ * Targets may be GPU, Memory, Power Supply or All of these.
+ * GPU_RELATED = GPU | MEMORY | POWER_SUPPLY
+ *
+ */
+
+#define NV_CTRL_THERMAL_COOLER_TARGET 323 /* R--C */
+#define NV_CTRL_THERMAL_COOLER_TARGET_NONE 0
+#define NV_CTRL_THERMAL_COOLER_TARGET_GPU 1
+#define NV_CTRL_THERMAL_COOLER_TARGET_MEMORY 2
+#define NV_CTRL_THERMAL_COOLER_TARGET_POWER_SUPPLY 4
+#define NV_CTRL_THERMAL_COOLER_TARGET_GPU_RELATED                               \
+    (NV_CTRL_THERMAL_COOLER_TARGET_GPU | NV_CTRL_THERMAL_COOLER_TARGET_MEMORY | \
+     NV_CTRL_THERMAL_COOLER_TARGET_POWER_SUPPLY)
+
+/*
+ * NV_CTRL_GPU_ECC_SUPPORTED - Reports whether ECC is supported by the
+ * targeted GPU.
+ */
+#define NV_CTRL_GPU_ECC_SUPPORTED 324 /* R--G */
+#define NV_CTRL_GPU_ECC_SUPPORTED_FALSE 0
+#define NV_CTRL_GPU_ECC_SUPPORTED_TRUE 1
+
+/*
+ * NV_CTRL_GPU_ECC_STATUS - Returns the current hardware ECC setting
+ * for the targeted GPU.
+ */
+#define NV_CTRL_GPU_ECC_STATUS 325 /* R--G */
+#define NV_CTRL_GPU_ECC_STATUS_DISABLED 0
+#define NV_CTRL_GPU_ECC_STATUS_ENABLED 1
+
+/*
+ * NV_CTRL_GPU_ECC_CONFIGURATION - Reports whether ECC can be configured
+ * dynamically for the GPU in question.
+ */
+#define NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED 326 /* R--G */
+#define NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_FALSE 0
+#define NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_TRUE 1
+
+/*
+ * NV_CTRL_GPU_ECC_CONFIGURATION_SETTING - Returns the current ECC
+ * configuration setting or specifies new settings.  New settings do not
+ * take effect until the next POST.
+ */
+#define NV_CTRL_GPU_ECC_CONFIGURATION 327 /* RW-G */
+#define NV_CTRL_GPU_ECC_CONFIGURATION_DISABLED 0
+#define NV_CTRL_GPU_ECC_CONFIGURATION_ENABLED 1
+
+/*
+ * NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_SETTING - Returns the default
+ * ECC configuration setting.
+ */
+#define NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION 328 /* R--G */
+#define NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_DISABLED 0
+#define NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_ENABLED 1
+
+/*
+ * NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS - Returns the number of single-bit
+ * ECC errors detected by the targeted GPU since the last POST.
+ * Note: this attribute is a 64-bit integer attribute.
+ */
+#define NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS 329 /* R--GQ */
+
+/*
+ * NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS - Returns the number of double-bit
+ * ECC errors detected by the targeted GPU since the last POST.
+ * Note: this attribute is a 64-bit integer attribute.
+ */
+#define NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS 330 /* R--GQ */
+
+/*
+ * NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS - Returns the number of
+ * single-bit ECC errors detected by the targeted GPU since the
+ * last counter reset.
+ * Note: this attribute is a 64-bit integer attribute.
+ */
+#define NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS 331 /* R--GQ */
+
+/*
+ * NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS - Returns the number of
+ * double-bit ECC errors detected by the targeted GPU since the
+ * last counter reset.
+ * Note: this attribute is a 64-bit integer attribute.
+ */
+#define NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS 332 /* R--GQ */
+
+/*
+ * NV_CTRL_GPU_ECC_RESET_ERROR_STATUS - Resets the volatile/aggregate
+ * single-bit and double-bit error counters.  This attribute is a
+ * bitmask attribute.
+ */
+#define NV_CTRL_GPU_ECC_RESET_ERROR_STATUS 333 /* -W-G */
+#define NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_VOLATILE 0x00000001
+#define NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_AGGREGATE 0x00000002
+
+/*
+ * NV_CTRL_GPU_POWER_MIZER_MODE - Provides a hint to the driver
+ * as to how to manage the performance of the GPU.
+ *
+ * ADAPTIVE                     - adjust GPU clocks based on GPU
+ *                                utilization
+ * PREFER_MAXIMUM_PERFORMANCE   - raise GPU clocks to favor
+ *                                maximum performance, to the extent
+ *                                that thermal and other constraints
+ *                                allow
+ */
+#define NV_CTRL_GPU_POWER_MIZER_MODE 334 /* RW-G */
+#define NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE 0
+#define NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE 1
+
+/*
+ * NV_CTRL_GVI_SYNC_OUTPUT_FORMAT - Returns the output sync signal
+ * from the GVI device.
+ */
+
+#define NV_CTRL_GVI_SYNC_OUTPUT_FORMAT 335 /* R--I */
+
+/*
+ * NV_CTRL_GVI_MAX_CHANNELS_PER_JACK  - Returns the maximum
+ * supported number of (logical) channels within a single physical jack of
+ * a GVI device.  For most SDI video formats, there is only one channel
+ * (channel 0).  But for 3G video formats (as specified in SMPTE 425),
+ * as an example, there are two channels (channel 0 and channel 1) per
+ * physical jack.
+ */
+
+#define NV_CTRL_GVI_MAX_CHANNELS_PER_JACK 336 /* R--I */
+
+/*
+ * NV_CTRL_GVI_MAX_STREAMS  - Returns the maximum number of streams
+ * that can be configured on the GVI device.
+ */
+
+#define NV_CTRL_GVI_MAX_STREAMS 337 /* R--I */
+
+/*
+ * NV_CTRL_GVI_NUM_CAPTURE_SURFACES - The GVI interface exposed through
+ * NV-CONTROL and the GLX_NV_video_input extension uses internal capture
+ * surfaces when frames are read from the GVI device.  The
+ * NV_CTRL_GVI_NUM_CAPTURE_SURFACES can be used to query and assign the
+ * number of capture surfaces.  This attribute is applied when
+ * glXBindVideoCaptureDeviceNV() is called by the application.
+ *
+ * A lower number of capture surfaces will mean less video memory is used,
+ * but can result in frames being dropped if the application cannot keep up
+ * with the capture device.  A higher number will prevent frames from being
+ * dropped, making capture more reliable but will consume move video memory.
+ */
+#define NV_CTRL_GVI_NUM_CAPTURE_SURFACES 338 /* RW-I */
+
+/*
+ * NV_CTRL_OVERSCAN_COMPENSATION - not supported
+ */
+#define NV_CTRL_OVERSCAN_COMPENSATION 339 /* RWDG */
+
+/*
+ * NV_CTRL_GPU_PCIE_GENERATION - Reports the current PCIe generation.
+ */
+#define NV_CTRL_GPU_PCIE_GENERATION 341 /* R--GI */
+#define NV_CTRL_GPU_PCIE_GENERATION1 0x00000001
+#define NV_CTRL_GPU_PCIE_GENERATION2 0x00000002
+#define NV_CTRL_GPU_PCIE_GENERATION3 0x00000003
+
+/*
+ * NV_CTRL_GVI_BOUND_GPU - Returns the NV_CTRL_TARGET_TYPE_GPU target_id of
+ * the GPU currently bound to the GVI device.  Returns -1 if no GPU is
+ * currently bound to the GVI device.
+ */
+#define NV_CTRL_GVI_BOUND_GPU 342 /* R--I */
+
+/*
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3 - this attribute is only
+ * intended to be used to query the ValidValues for
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for VIDEO_FORMAT values between
+ * 64 and 95.  See NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for details.
+ */
+
+#define NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3 343 /* ---GI */
+
+/*
+ * NV_CTRL_ACCELERATE_TRAPEZOIDS - Toggles RENDER Trapezoid acceleration
+ */
+
+#define NV_CTRL_ACCELERATE_TRAPEZOIDS 344 /* RW- */
+#define NV_CTRL_ACCELERATE_TRAPEZOIDS_DISABLE 0
+#define NV_CTRL_ACCELERATE_TRAPEZOIDS_ENABLE 1
+
+/*
+ * NV_CTRL_GPU_CORES - Returns number of GPU cores supported by the graphics
+ * pipeline.
+ */
+
+#define NV_CTRL_GPU_CORES 345 /* R--G */
+
+/*
+ * NV_CTRL_GPU_MEMORY_BUS_WIDTH - Returns memory bus bandwidth on the associated
+ * subdevice.
+ */
+
+#define NV_CTRL_GPU_MEMORY_BUS_WIDTH 346 /* R--G */
+
+/*
+ * NV_CTRL_GVI_TEST_MODE - This attribute controls the GVI test mode.  When
+ * enabled, the GVI device will generate fake data as quickly as possible.  All
+ * GVI settings are still valid when this is enabled (e.g., the requested video
+ * format is honored and sets the video size).
+ * This may be used to test the pipeline.
+ */
+
+#define NV_CTRL_GVI_TEST_MODE 347 /* R--I */
+#define NV_CTRL_GVI_TEST_MODE_DISABLE 0
+#define NV_CTRL_GVI_TEST_MODE_ENABLE 1
+
+/*
+ * NV_CTRL_COLOR_SPACE - This option sets color space of the video
+ * signal.
+ */
+#define NV_CTRL_COLOR_SPACE 348 /* RWDG */
+#define NV_CTRL_COLOR_SPACE_RGB 0
+#define NV_CTRL_COLOR_SPACE_YCbCr422 1
+#define NV_CTRL_COLOR_SPACE_YCbCr444 2
+
+/*
+ * NV_CTRL_COLOR_RANGE - This option sets color range of the video
+ * signal.
+ */
+#define NV_CTRL_COLOR_RANGE 349 /* RWDG */
+#define NV_CTRL_COLOR_RANGE_FULL 0
+#define NV_CTRL_COLOR_RANGE_LIMITED 1
+
+/*
+ * NV_CTRL_GPU_SCALING_DEFAULT_TARGET - not supported
+ *
+ * NV_CTRL_GPU_SCALING_DEFAULT_METHOD - not supported
+ */
+#define NV_CTRL_GPU_SCALING_DEFAULT_TARGET 350 /* R-DG */
+#define NV_CTRL_GPU_SCALING_DEFAULT_METHOD 351 /* R-DG */
+
+/*
+ * NV_CTRL_DITHERING_MODE - Controls the dithering mode, when
+ * NV_CTRL_CURRENT_DITHERING is Enabled.
+ *
+ * AUTO: allow the driver to choose the dithering mode automatically.
+ *
+ * DYNAMIC_2X2: use a 2x2 matrix to dither from the GPU's pixel
+ * pipeline to the bit depth of the flat panel.  The matrix values
+ * are changed from frame to frame.
+ *
+ * STATIC_2X2: use a 2x2 matrix to dither from the GPU's pixel
+ * pipeline to the bit depth of the flat panel.  The matrix values
+ * do not change from frame to frame.
+ *
+ * TEMPORAL: use a pseudorandom value from a uniform distribution calculated at
+ * every pixel to achieve stochastic dithering.  This method produces a better
+ * visual result than 2x2 matrix approaches.
+ */
+#define NV_CTRL_DITHERING_MODE 352 /* RWDG */
+#define NV_CTRL_DITHERING_MODE_AUTO 0
+#define NV_CTRL_DITHERING_MODE_DYNAMIC_2X2 1
+#define NV_CTRL_DITHERING_MODE_STATIC_2X2 2
+#define NV_CTRL_DITHERING_MODE_TEMPORAL 3
+
+/*
+ * NV_CTRL_CURRENT_DITHERING - Returns the current dithering state.
+ */
+#define NV_CTRL_CURRENT_DITHERING 353 /* R-DG */
+#define NV_CTRL_CURRENT_DITHERING_DISABLED 0
+#define NV_CTRL_CURRENT_DITHERING_ENABLED 1
+
+/*
+ * NV_CTRL_CURRENT_DITHERING_MODE - Returns the current dithering
+ * mode.
+ */
+#define NV_CTRL_CURRENT_DITHERING_MODE 354 /* R-DG */
+#define NV_CTRL_CURRENT_DITHERING_MODE_NONE 0
+#define NV_CTRL_CURRENT_DITHERING_MODE_DYNAMIC_2X2 1
+#define NV_CTRL_CURRENT_DITHERING_MODE_STATIC_2X2 2
+#define NV_CTRL_CURRENT_DITHERING_MODE_TEMPORAL 3
+
+/*
+ * NV_CTRL_THERMAL_SENSOR_READING - Returns the thermal sensor's current
+ * reading.
+ */
+#define NV_CTRL_THERMAL_SENSOR_READING 355 /* R--S */
+
+/*
+ * NV_CTRL_THERMAL_SENSOR_PROVIDER - Returns the hardware device that
+ * provides the thermal sensor.
+ */
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER 356 /* R--S */
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_NONE 0
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_GPU_INTERNAL 1
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_ADM1032 2
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_ADT7461 3
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_MAX6649 4
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_MAX1617 5
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_LM99 6
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_LM89 7
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_LM64 8
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_G781 9
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_ADT7473 10
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_SBMAX6649 11
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_VBIOSEVT 12
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_OS 13
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_UNKNOWN 0xFFFFFFFF
+
+/*
+ * NV_CTRL_THERMAL_SENSOR_TARGET - Returns what hardware component
+ * the thermal sensor is measuring.
+ */
+#define NV_CTRL_THERMAL_SENSOR_TARGET 357 /* R--S */
+#define NV_CTRL_THERMAL_SENSOR_TARGET_NONE 0
+#define NV_CTRL_THERMAL_SENSOR_TARGET_GPU 1
+#define NV_CTRL_THERMAL_SENSOR_TARGET_MEMORY 2
+#define NV_CTRL_THERMAL_SENSOR_TARGET_POWER_SUPPLY 4
+#define NV_CTRL_THERMAL_SENSOR_TARGET_BOARD 8
+#define NV_CTRL_THERMAL_SENSOR_TARGET_UNKNOWN 0xFFFFFFFF
+
+/*
+ * NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR - when TRUE, OpenGL will
+ * draw information about the current MULTIGPU mode.
+ */
+#define NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR 358 /* RW-X */
+#define NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR_FALSE 0
+#define NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR_TRUE 1
+
+/*
+ * NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS - Returns GPU's processor
+ * clock freqs.
+ */
+#define NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS 359 /* RW-G */
+
+/*
+ * NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS - query the flags (various information
+ * for the specified NV_CTRL_GVIO_VIDEO_FORMAT_*.  So that this can be
+ * queried with existing interfaces, the video format should be specified
+ * in the display_mask field; eg:
+ *
+ * XNVCTRLQueryTargetAttribute(dpy,
+ *                             NV_CTRL_TARGET_TYPE_GVI,
+ *                             gvi,
+ *                             NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296,
+ *                             NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS,
+ *                             &flags);
+ *
+ * Note: The NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_1080P_NO_12BPC flag is set
+ *       for those 1080P 3G modes (level A and B) that do not support
+ *       12 bits per component (when configuring a GVI stream.)
+ */
+
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS 360 /* R--I */
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_NONE 0x00000000
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_INTERLACED 0x00000001
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PROGRESSIVE 0x00000002
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PSF 0x00000004
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_A 0x00000008
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_B 0x00000010
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G \
+    ((NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_A) | (NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_B))
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_1080P_NO_12BPC 0x00000020
+
+/*
+ * NV_CTRL_GPU_PCIE_MAX_LINK_SPEED - returns maximum PCIe link speed,
+ * in gigatransfers per second (GT/s).
+ */
+
+#define NV_CTRL_GPU_PCIE_MAX_LINK_SPEED 361 /* R--GI */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_RESET_TRANSCEIVER_TO_FACTORY_SETTINGS - Resets the
+ * 3D Vision Pro transceiver to its factory settings.
+ */
+#define NV_CTRL_3D_VISION_PRO_RESET_TRANSCEIVER_TO_FACTORY_SETTINGS 363 /* -W-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL - Controls the channel that is
+ * currently used by the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL 364 /* RW-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE - Controls the mode in which the
+ * 3D Vision Pro transceiver operates.
+ * NV_CTRL_3D_VISION_PRO_TM_LOW_RANGE is bidirectional
+ * NV_CTRL_3D_VISION_PRO_TM_MEDIUM_RANGE is bidirectional
+ * NV_CTRL_3D_VISION_PRO_TM_HIGH_RANGE may be bidirectional just up to a
+ *     given range, and unidirectional beyond it
+ * NV_CTRL_3D_VISION_PRO_TM_COUNT is the total number of
+ *     3D Vision Pro transceiver modes
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE 365 /* RW-T */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_INVALID 0
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_LOW_RANGE 1
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_MEDIUM_RANGE 2
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_HIGH_RANGE 3
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_COUNT 4
+
+/*
+ * NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES - controls whether updates to the color
+ * lookup table (LUT) are synchronous with respect to X rendering.  For example,
+ * if an X client sends XStoreColors followed by XFillRectangle, the driver will
+ * guarantee that the FillRectangle request is not processed until after the
+ * updated LUT colors are actually visible on the screen if
+ * NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES is enabled.  Otherwise, the rendering may
+ * occur first.
+ *
+ * This makes a difference for applications that use the LUT to animate, such as
+ * XPilot.  If you experience flickering in applications that use LUT
+ * animations, try enabling this attribute.
+ *
+ * When synchronous updates are enabled, XStoreColors requests will be processed
+ * at your screen's refresh rate.
+ */
+
+#define NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES 367 /* RWDG */
+#define NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES_DISABLE 0
+#define NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES_ENABLE 1
+
+/*
+ * NV_CTRL_DITHERING_DEPTH - Controls the dithering depth when
+ * NV_CTRL_CURRENT_DITHERING is ENABLED.  Some displays connected
+ * to the GPU via the DVI or LVDS interfaces cannot display the
+ * full color range of ten bits per channel, so the GPU will
+ * dither to either 6 or 8 bits per channel.
+ */
+#define NV_CTRL_DITHERING_DEPTH 368 /* RWDG */
+#define NV_CTRL_DITHERING_DEPTH_AUTO 0
+#define NV_CTRL_DITHERING_DEPTH_6_BITS 1
+#define NV_CTRL_DITHERING_DEPTH_8_BITS 2
+
+/*
+ * NV_CTRL_CURRENT_DITHERING_DEPTH - Returns the current dithering
+ * depth value.
+ */
+#define NV_CTRL_CURRENT_DITHERING_DEPTH 369 /* R-DG */
+#define NV_CTRL_CURRENT_DITHERING_DEPTH_NONE 0
+#define NV_CTRL_CURRENT_DITHERING_DEPTH_6_BITS 1
+#define NV_CTRL_CURRENT_DITHERING_DEPTH_8_BITS 2
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_FREQUENCY - Returns the
+ * frequency of the channel(in kHz) of the 3D Vision Pro transceiver.
+ * Use the display_mask parameter to specify the channel number.
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_FREQUENCY 370 /* R--T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_QUALITY - Returns the
+ * quality of the channel(in percentage) of the 3D Vision Pro transceiver.
+ * Use the display_mask parameter to specify the channel number.
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_QUALITY 371 /* R--T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_COUNT - Returns the number of
+ * channels on the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_COUNT 372 /* R--T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_PAIR_GLASSES - Puts the 3D Vision Pro
+ * transceiver into pairing mode to gather additional glasses.
+ * NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_STOP - stops any pairing
+ * NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_BEACON - starts continuous
+ *     pairing via beacon mode
+ * Any other value, N - Puts the 3D Vision Pro transceiver into
+ *     authenticated pairing mode for N seconds.
+ */
+#define NV_CTRL_3D_VISION_PRO_PAIR_GLASSES 373 /* -W-T */
+#define NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_STOP 0
+#define NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_BEACON 0xFFFFFFFF
+
+/*
+ * NV_CTRL_3D_VISION_PRO_UNPAIR_GLASSES - Tells a specific pair
+ * of glasses to unpair. The glasses will "forget" the address
+ * of the 3D Vision Pro transceiver to which they have been paired.
+ * To unpair all the currently paired glasses, specify
+ * the glasses id as 0.
+ */
+#define NV_CTRL_3D_VISION_PRO_UNPAIR_GLASSES 374 /* -W-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_DISCOVER_GLASSES - Tells the 3D Vision Pro
+ * transceiver about the glasses that have been paired using
+ * NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_BEACON. Unless this is done,
+ * the 3D Vision Pro transceiver will not know about glasses paired in
+ * beacon mode.
+ */
+#define NV_CTRL_3D_VISION_PRO_DISCOVER_GLASSES 375 /* -W-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_IDENTIFY_GLASSES - Causes glasses LEDs to
+ * flash for a short period of time.
+ */
+#define NV_CTRL_3D_VISION_PRO_IDENTIFY_GLASSES 376 /* -W-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_SYNC_CYCLE - Controls the
+ * sync cycle duration(in milliseconds) of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_SYNC_CYCLE 378 /* RW-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_MISSED_SYNC_CYCLES - Returns the
+ * number of state sync cycles recently missed by the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_MISSED_SYNC_CYCLES 379 /* R--T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_BATTERY_LEVEL - Returns the
+ * battery level(in percentage) of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_BATTERY_LEVEL 380 /* R--T */
+
+/*
+ * NV_CTRL_GVO_ANC_PARITY_COMPUTATION - Controls the SDI device's computation
+ * of the parity bit (bit 8) for ANC data words.
+ */
+
+#define NV_CTRL_GVO_ANC_PARITY_COMPUTATION 381 /* RW--- */
+#define NV_CTRL_GVO_ANC_PARITY_COMPUTATION_AUTO 0
+#define NV_CTRL_GVO_ANC_PARITY_COMPUTATION_ON 1
+#define NV_CTRL_GVO_ANC_PARITY_COMPUTATION_OFF 2
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_PAIR_EVENT - This attribute is sent
+ * as an event when glasses get paired in response to pair command
+ * from any of the clients.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_PAIR_EVENT 382 /* ---T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_UNPAIR_EVENT - This attribute is sent
+ * as an event when glasses get unpaired in response to unpair command
+ * from any of the clients.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_UNPAIR_EVENT 383 /* ---T */
+
+/*
+ * NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH - returns the current
+ * PCIe link width, in number of lanes.
+ */
+#define NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH 384 /* R--GI */
+
+/*
+ * NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED - returns the current
+ * PCIe link speed, in megatransfers per second (GT/s).
+ */
+#define NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED 385 /* R--GI */
+
+/*
+ * NV_CTRL_GVO_AUDIO_BLANKING - specifies whether the GVO device should delete
+ * audio ancillary data packets when frames are repeated.
+ *
+ * When a new frame is not ready in time, the current frame, including all
+ * ancillary data packets, is repeated.  When this data includes audio packets,
+ * this can result in stutters or clicks.  When this option is enabled, the GVO
+ * device will detect when frames are repeated, identify audio ancillary data
+ * packets, and mark them for deletion.
+ *
+ * This option is applied when the GVO device is bound.
+ */
+#define NV_CTRL_GVO_AUDIO_BLANKING 386 /* RW- */
+#define NV_CTRL_GVO_AUDIO_BLANKING_DISABLE 0
+#define NV_CTRL_GVO_AUDIO_BLANKING_ENABLE 1
+
+/*
+ * NV_CTRL_CURRENT_METAMODE_ID - switch modes to the MetaMode with
+ * the specified ID.
+ */
+#define NV_CTRL_CURRENT_METAMODE_ID 387 /* RW- */
+
+/*
+ * NV_CTRL_DISPLAY_ENABLED - Returns whether or not the display device
+ * is currently enabled.
+ */
+#define NV_CTRL_DISPLAY_ENABLED 388 /* R-D */
+#define NV_CTRL_DISPLAY_ENABLED_TRUE 1
+#define NV_CTRL_DISPLAY_ENABLED_FALSE 0
+
+#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_DISPLAY_ENABLED
+
+/**************************************************************************/
+
+/*
+ * String Attributes:
+ *
+ * String attributes can be queryied through the XNVCTRLQueryStringAttribute()
+ * and XNVCTRLQueryTargetStringAttribute() function calls.
+ *
+ * String attributes can be set through the XNVCTRLSetStringAttribute()
+ * function call.  (There are currently no string attributes that can be
+ * set on non-X Screen targets.)
+ *
+ * Unless otherwise noted, all string attributes can be queried/set using an
+ * NV_CTRL_TARGET_TYPE_X_SCREEN target.  Attributes that cannot take an
+ * NV_CTRL_TARGET_TYPE_X_SCREEN target also cannot be queried/set through
+ * XNVCTRLQueryStringAttribute()/XNVCTRLSetStringAttribute() (Since
+ * these assume an X Screen target).
+ */
+
+/*
+ * NV_CTRL_STRING_PRODUCT_NAME - the GPU product name on which the
+ * specified X screen is running.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_STRING_PRODUCT_NAME 0 /* R--G */
+
+/*
+ * NV_CTRL_STRING_VBIOS_VERSION - the video bios version on the GPU on
+ * which the specified X screen is running.
+ */
+
+#define NV_CTRL_STRING_VBIOS_VERSION 1 /* R--G */
+
+/*
+ * NV_CTRL_STRING_NVIDIA_DRIVER_VERSION - string representation of the
+ * NVIDIA driver version number for the NVIDIA X driver in use.
+ */
+
+#define NV_CTRL_STRING_NVIDIA_DRIVER_VERSION 3 /* R--G */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_DEVICE_NAME - name of the display device
+ * specified in the display_mask argument.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_STRING_DISPLAY_DEVICE_NAME 4 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_TV_ENCODER_NAME - name of the TV encoder used by the
+ * specified display device; only valid if the display device is a TV.
+ */
+
+#define NV_CTRL_STRING_TV_ENCODER_NAME 5 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_GVIO_FIRMWARE_VERSION - indicates the version of the
+ * Firmware on the GVIO device.
+ */
+
+#define NV_CTRL_STRING_GVIO_FIRMWARE_VERSION 8 /* R--I */
+
+/*
+ * The following is deprecated; use NV_CTRL_STRING_GVIO_FIRMWARE_VERSION,
+ * instead
+ */
+#define NV_CTRL_STRING_GVO_FIRMWARE_VERSION 8 /* R-- */
+
+/*
+ * NV_CTRL_STRING_CURRENT_MODELINE - Return the ModeLine currently
+ * being used by the specified display device.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ *
+ * The ModeLine string may be prepended with a comma-separated list of
+ * "token=value" pairs, separated from the ModeLine string by "::".
+ * This "token=value" syntax is the same as that used in
+ * NV_CTRL_BINARY_DATA_MODELINES
+ */
+
+#define NV_CTRL_STRING_CURRENT_MODELINE 9 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_ADD_MODELINE - Adds a ModeLine to the specified
+ * display device.  The ModeLine is not added if validation fails.
+ *
+ * The ModeLine string should have the same syntax as a ModeLine in
+ * the X configuration file; e.g.,
+ *
+ * "1600x1200"  229.5  1600 1664 1856 2160  1200 1201 1204 1250  +HSync +VSync
+ */
+
+#define NV_CTRL_STRING_ADD_MODELINE 10 /* -WDG */
+
+/*
+ * NV_CTRL_STRING_DELETE_MODELINE - Deletes an existing ModeLine
+ * from the specified display device.  The currently selected
+ * ModeLine cannot be deleted.  (This also means you cannot delete
+ * the last ModeLine.)
+ *
+ * The ModeLine string should have the same syntax as a ModeLine in
+ * the X configuration file; e.g.,
+ *
+ * "1600x1200"  229.5  1600 1664 1856 2160  1200 1201 1204 1250  +HSync +VSync
+ */
+
+#define NV_CTRL_STRING_DELETE_MODELINE 11 /* -WDG */
+
+/*
+ * NV_CTRL_STRING_CURRENT_METAMODE - Returns the metamode currently
+ * being used by the specified X screen.  The MetaMode string has the
+ * same syntax as the MetaMode X configuration option, as documented
+ * in the NVIDIA driver README.
+ *
+ * The returned string may be prepended with a comma-separated list of
+ * "token=value" pairs, separated from the MetaMode string by "::".
+ * This "token=value" syntax is the same as that used in
+ * NV_CTRL_BINARY_DATA_METAMODES.
+ */
+
+#define NV_CTRL_STRING_CURRENT_METAMODE 12 /* RW-- */
+#define NV_CTRL_STRING_CURRENT_METAMODE_VERSION_1 NV_CTRL_STRING_CURRENT_METAMODE
+
+/*
+ * NV_CTRL_STRING_ADD_METAMODE - Adds a MetaMode to the specified
+ * X Screen.
+ *
+ * It is recommended to not use this attribute, but instead use
+ * NV_CTRL_STRING_OPERATION_ADD_METAMODE.
+ */
+
+#define NV_CTRL_STRING_ADD_METAMODE 13 /* -W-- */
+
+/*
+ * NV_CTRL_STRING_DELETE_METAMODE - Deletes an existing MetaMode from
+ * the specified X Screen.  The currently selected MetaMode cannot be
+ * deleted.  (This also means you cannot delete the last MetaMode).
+ * The MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+ */
+
+#define NV_CTRL_STRING_DELETE_METAMODE 14 /* -WD-- */
+
+/*
+ * NV_CTRL_STRING_VCSC_PRODUCT_NAME - Querys the product name of the
+ * VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_PRODUCT_NAME 15 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_PRODUCT_ID - Querys the product ID of the VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_PRODUCT_ID 16 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_SERIAL_NUMBER - Querys the unique serial number
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_SERIAL_NUMBER 17 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_BUILD_DATE - Querys the date of the VCS device.
+ * the returned string is in the following format: "Week.Year"
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_BUILD_DATE 18 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_FIRMWARE_VERSION - Querys the firmware version
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_FIRMWARE_VERSION 19 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_FIRMWARE_REVISION - Querys the firmware revision
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCS target.
+ */
+
+#define NV_CTRL_STRING_VCSC_FIRMWARE_REVISION 20 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_HARDWARE_VERSION - Querys the hardware version
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_HARDWARE_VERSION 21 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_HARDWARE_REVISION - Querys the hardware revision
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_HARDWARE_REVISION 22 /* R---V */
+
+/*
+ * NV_CTRL_STRING_MOVE_METAMODE - Moves a MetaMode to the specified
+ * index location.  The MetaMode must already exist in the X Screen's
+ * list of MetaModes (as returned by the NV_CTRL_BINARY_DATA_METAMODES
+ * attribute).  If the index is larger than the number of MetaModes in
+ * the list, the MetaMode is moved to the end of the list.  The
+ * MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+
+ * The MetaMode string must be prepended with a comma-separated list
+ * of "token=value" pairs, separated from the MetaMode string by "::".
+ * Currently, the only valid token is "index", which indicates where
+ * in the MetaMode list the MetaMode should be moved to.
+ *
+ * Other tokens may be added in the future.
+ *
+ * E.g.,
+ *  "index=5 :: CRT-0: 1024x768 @1024x768 +0+0"
+ */
+
+#define NV_CTRL_STRING_MOVE_METAMODE 23 /* -W-- */
+
+/*
+ * NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES - returns the valid
+ * horizontal sync ranges used to perform mode validation for the
+ * specified display device.  The ranges are in the same format as the
+ * "HorizSync" X config option:
+ *
+ *   "horizsync-range may be a comma separated list of either discrete
+ *   values or ranges of values.  A range of values is two values
+ *   separated by a dash."
+ *
+ * The values are in kHz.
+ *
+ * Additionally, the string may be prepended with a comma-separated
+ * list of "token=value" pairs, separated from the HorizSync string by
+ * "::".  Valid tokens:
+ *
+ *    Token     Value
+ *   "source"  "edid"     - HorizSync is from the display device's EDID
+ *             "xconfig"  - HorizSync is from the "HorizSync" entry in
+ *                          the Monitor section of the X config file
+ *             "option"   - HorizSync is from the "HorizSync" NVIDIA X
+ *                          config option
+ *             "twinview" - HorizSync is from the "SecondMonitorHorizSync"
+ *                          NVIDIA X config option
+ *             "builtin"  - HorizSync is from NVIDIA X driver builtin
+ *                          default values
+ *
+ * Additional tokens and/or values may be added in the future.
+ *
+ * Example: "source=edid :: 30.000-62.000"
+ */
+
+#define NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES 24 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES - returns the valid
+ * vertical refresh ranges used to perform mode validation for the
+ * specified display device.  The ranges are in the same format as the
+ * "VertRefresh" X config option:
+ *
+ *   "vertrefresh-range may be a comma separated list of either discrete
+ *    values or ranges of values.  A range of values is two values
+ *    separated by a dash."
+ *
+ * The values are in Hz.
+ *
+ * Additionally, the string may be prepended with a comma-separated
+ * list of "token=value" pairs, separated from the VertRefresh string by
+ * "::".  Valid tokens:
+ *
+ *    Token     Value
+ *   "source"  "edid"     - VertRefresh is from the display device's EDID
+ *             "xconfig"  - VertRefresh is from the "VertRefresh" entry in
+ *                          the Monitor section of the X config file
+ *             "option"   - VertRefresh is from the "VertRefresh" NVIDIA X
+ *                          config option
+ *             "twinview" - VertRefresh is from the "SecondMonitorVertRefresh"
+ *                          NVIDIA X config option
+ *             "builtin"  - VertRefresh is from NVIDIA X driver builtin
+ *                          default values
+ *
+ * Additional tokens and/or values may be added in the future.
+ *
+ * Example: "source=edid :: 50.000-75.000"
+ */
+
+#define NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES 25 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_XINERAMA_SCREEN_INFO - returns the physical X Screen's
+ * initial position and size (in absolute coordinates) within the Xinerama
+ * desktop as the "token=value" string:  "x=#, y=#, width=#, height=#"
+ *
+ * Querying this attribute returns FALSE if NV_CTRL_XINERAMA is not
+ * NV_CTRL_XINERAMA_ON.
+ */
+
+#define NV_CTRL_STRING_XINERAMA_SCREEN_INFO 26 /* R--- */
+
+/*
+ * NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER - used to specify the
+ * order that display devices will be returned via Xinerama when
+ * nvidiaXineramaInfo is enabled.  Follows the same syntax as the
+ * nvidiaXineramaInfoOrder X config option.
+ */
+
+#define NV_CTRL_STRING_NVIDIA_XINERAMA_INFO_ORDER 27 /* RW-- */
+
+#define NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER \
+    NV_CTRL_STRING_NVIDIA_XINERAMA_INFO_ORDER /* for backwards compatibility: */
+
+/*
+ * NV_CTRL_STRING_SLI_MODE - returns a string describing the current
+ * SLI mode, if any, or FALSE if SLI is not currently enabled.
+ *
+ * This string should be used for informational purposes only, and
+ * should not be used to distinguish between SLI modes, other than to
+ * recognize when SLI is disabled (FALSE is returned) or
+ * enabled (the returned string is non-NULL and describes the current
+ * SLI configuration).
+ */
+
+#define NV_CTRL_STRING_SLI_MODE 28 /* R---*/
+
+/*
+ * NV_CTRL_STRING_PERFORMANCE_MODES - returns a string with all the
+ * performance modes defined for this GPU along with their associated
+ * NV Clock and Memory Clock values.
+ *
+ * Each performance modes are returned as a comma-separated list of
+ * "token=value" pairs.  Each set of performance mode tokens are separated
+ * by a ";".  Valid tokens:
+ *
+ *    Token      Value
+ *   "perf"      integer   - the Performance level
+ *   "nvclock"   integer   - the GPU clocks (in MHz) for the perf level
+ *   "memclock"  integer   - the memory clocks (in MHz) for the perf level
+ *
+ *
+ * Example:
+ *
+ *   perf=0, nvclock=500, memclock=505 ; perf=1, nvclock=650, memclock=505
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_STRING_PERFORMANCE_MODES 29 /* R--G */
+
+/*
+ * NV_CTRL_STRING_VCSC_FAN_STATUS - returns a string with status of all the
+ * fans in the Visual Computing System, if such a query is supported.  Fan
+ * information is reported along with its tachometer reading (in RPM) and a
+ * flag indicating whether the fan has failed or not.
+ *
+ * Valid tokens:
+ *
+ *    Token      Value
+ *   "fan"       integer   - the Fan index
+ *   "speed"     integer   - the tachometer reading of the fan in rpm
+ *   "fail"      integer   - flag to indicate whether the fan has failed
+ *
+ * Example:
+ *
+ *   fan=0, speed=694, fail=0 ; fan=1, speed=693, fail=0
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ *
+ */
+
+#define NV_CTRL_STRING_VCSC_FAN_STATUS 30 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_TEMPERATURES - returns a string with all Temperature
+ * readings in the Visual Computing System, if such a query is supported.
+ * Intake, Exhaust and Board Temperature values are reported in Celcius.
+ *
+ * Valid tokens:
+ *
+ *    Token      Value
+ *   "intake"    integer   - the intake temperature for the VCS
+ *   "exhaust"   integer   - the exhaust temperature for the VCS
+ *   "board"     integer   - the board temperature of the VCS
+ *
+ * Example:
+ *
+ *   intake=29, exhaust=46, board=41
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ *
+ */
+
+#define NV_CTRL_STRING_VCSC_TEMPERATURES 31 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_PSU_INFO - returns a string with all Power Supply Unit
+ * related readings in the Visual Computing System, if such a query is
+ * supported.  Current in amperes, Power in watts, Voltage in volts and PSU
+ * state may be reported.  Not all PSU types support all of these values, and
+ * therefore some readings may be unknown.
+ *
+ * Valid tokens:
+ *
+ *    Token      Value
+ *   "current"   integer   - the current drawn in amperes by the VCS
+ *   "power"     integer   - the power drawn in watts by the VCS
+ *   "voltage"   integer   - the voltage reading of the VCS
+ *   "state"     integer   - flag to indicate whether PSU is operating normally
+ *
+ * Example:
+ *
+ *   current=10, power=15, voltage=unknown, state=normal
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ *
+ */
+
+#define NV_CTRL_STRING_VCSC_PSU_INFO 32 /* R---V */
+
+/*
+ * NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME - query the name for the specified
+ * NV_CTRL_GVIO_VIDEO_FORMAT_*.  So that this can be queried with existing
+ * interfaces, XNVCTRLQueryStringAttribute() should be used, and the video
+ * format specified in the display_mask field; eg:
+ *
+ * XNVCTRLQueryStringAttribute(dpy,
+ *                             screen,
+ *                             NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296,
+ *                             NV_CTRL_GVIO_VIDEO_FORMAT_NAME,
+ *                             &name);
+ */
+
+#define NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME 33 /* R--GI */
+
+/*
+ * The following is deprecated; use NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME,
+ * instead
+ */
+#define NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME 33 /* R--- */
+
+/*
+ * NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS - returns a string with the
+ * associated NV Clock, Memory Clock and Processor Clock values.
+ *
+ * Current valid tokens are "nvclock", "memclock", and "processorclock".
+ * Not all tokens will be reported on all GPUs, and additional tokens
+ * may be added in the future.
+ *
+ * Clock values are returned as a comma-separated list of
+ * "token=value" pairs.
+ * Valid tokens:
+ *
+ *    Token           Value
+ *   "nvclock"        integer - the GPU clocks (in MHz) for the current
+ *                              perf level
+ *   "memclock"       integer - the memory clocks (in MHz) for the current
+ *                              perf level
+ *   "processorclock" integer - the processor clocks (in MHz) for the perf level
+ *
+ *
+ * Example:
+ *
+ *    nvclock=459, memclock=400, processorclock=918
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS 34 /* RW-G */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_HARDWARE_REVISION - Returns the
+ * hardware revision of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_HARDWARE_REVISION 35 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_A - Returns the
+ * firmware version of chip A of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_A 36 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_A - Returns the
+ * date of the firmware of chip A of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_A 37 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_B - Returns the
+ * firmware version of chip B of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_B 38 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_B - Returns the
+ * date of the firmware of chip B of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_B 39 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_ADDRESS - Returns the RF address
+ * of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_ADDRESS 40 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_VERSION_A - Returns the
+ * firmware version of chip A of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_VERSION_A 41 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_DATE_A - Returns the
+ * date of the firmware of chip A of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_DATE_A 42 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_GLASSES_ADDRESS - Returns the RF address
+ * of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_GLASSES_ADDRESS 43 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_GLASSES_NAME - Controls the name the
+ * glasses should use.
+ * Use the display_mask parameter to specify the glasses id.
+ * Glasses' name should start and end with an alpha-numeric character.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_GLASSES_NAME 44 /* RW-T */
+
+/*
+ * NV_CTRL_STRING_CURRENT_METAMODE_VERSION_2 - Returns the metamode currently
+ * being used by the specified X screen.  The MetaMode string has the same
+ * syntax as the MetaMode X configuration option, as documented in the NVIDIA
+ * driver README.  Also, see NV_CTRL_BINARY_DATA_METAMODES_VERSION_2 for more
+ * details on the base syntax.
+ *
+ * The returned string may also be prepended with a comma-separated list of
+ * "token=value" pairs, separated from the MetaMode string by "::".
+ */
+#define NV_CTRL_STRING_CURRENT_METAMODE_VERSION_2 45 /* RW-- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME - Returns a type name for the
+ * display device ("CRT", "DFP", or "TV").  However, note that the determination
+ * of the name is based on the protocol through which the X driver communicates
+ * to the display device.  E.g., if the driver communicates using VGA ,then the
+ * basename is "CRT"; if the driver communicates using TMDS, LVDS, or DP, then
+ * the name is "DFP".
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME 46 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_TYPE_ID - Returns the type-based name + ID for
+ * the display device, e.g. "CRT-0", "DFP-1", "TV-2".  If this device is a
+ * DisplayPort 1.2 device, then this name will also be prepended with the
+ * device's port address like so: "DFP-1.0.1.2.3".  See
+ * NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME for more information about the
+ * construction of type-based names.
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_TYPE_ID 47 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_DP_GUID - Returns the GUID of the DisplayPort
+ * display device.  e.g. "DP-GUID-f16a5bde-79f3-11e1-b2ae-8b5a8969ba9c"
+ *
+ * The display device must be a DisplayPort 1.2 device.
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_DP_GUID 48 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_EDID_HASH - Returns the SHA-1 hash of the
+ * display device's EDID in 8-4-4-4-12 UID format. e.g.
+ * "DPY-EDID-f16a5bde-79f3-11e1-b2ae-8b5a8969ba9c"
+ *
+ * The display device must have a valid EDID.
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_EDID_HASH 49 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_TARGET_INDEX - Returns the current NV-CONTROL
+ * target ID (name) of the display device.  e.g. "DPY-1", "DPY-4"
+ *
+ * This name for the display device is not guarenteed to be the same between
+ * different runs of the X server.
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_TARGET_INDEX 50 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_RANDR - Returns the RandR output name for the
+ * display device.  e.g.  "VGA-1", "DVI-I-0", "DVI-D-3", "LVDS-1", "DP-2",
+ * "HDMI-3", "eDP-6".  This name should match  If this device is a DisplayPort
+ * 1.2 device, then this name will also be prepended with the device's port
+ * address like so: "DVI-I-3.0.1.2.3"
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_RANDR 51 /* R-D- */
+
+#define NV_CTRL_STRING_LAST_ATTRIBUTE NV_CTRL_STRING_DISPLAY_NAME_RANDR
+
+/**************************************************************************/
+
+/*
+ * Binary Data Attributes:
+ *
+ * Binary data attributes can be queryied through the XNVCTRLQueryBinaryData()
+ * and XNVCTRLQueryTargetBinaryData() function calls.
+ *
+ * There are currently no binary data attributes that can be set.
+ *
+ * Unless otherwise noted, all Binary data attributes can be queried
+ * using an NV_CTRL_TARGET_TYPE_X_SCREEN target.  Attributes that cannot take
+ * an NV_CTRL_TARGET_TYPE_X_SCREEN target also cannot be queried through
+ * XNVCTRLQueryBinaryData() (Since an X Screen target is assumed).
+ */
+
+/*
+ * NV_CTRL_BINARY_DATA_EDID - Returns a display device's EDID information
+ * data.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_BINARY_DATA_EDID 0 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_MODELINES - Returns a display device's supported
+ * ModeLines.  ModeLines are returned in a buffer, separated by a single
+ * '\0' and terminated by two consecutive '\0' s like so:
+ *
+ *  "ModeLine 1\0ModeLine 2\0ModeLine 3\0Last ModeLine\0\0"
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ *
+ * Each ModeLine string may be prepended with a comma-separated list
+ * of "token=value" pairs, separated from the ModeLine string with a
+ * "::".  Valid tokens:
+ *
+ *    Token    Value
+ *   "source" "xserver"    - the ModeLine is from the core X server
+ *            "xconfig"    - the ModeLine was specified in the X config file
+ *            "builtin"    - the NVIDIA driver provided this builtin ModeLine
+ *            "vesa"       - this is a VESA standard ModeLine
+ *            "edid"       - the ModeLine was in the display device's EDID
+ *            "nv-control" - the ModeLine was specified via NV-CONTROL
+ *
+ *   "xconfig-name"        - for ModeLines that were specified in the X config
+ *                           file, this is the name the X config file
+ *                           gave for the ModeLine.
+ *
+ * Note that a ModeLine can have several sources; the "source" token
+ * can appear multiple times in the "token=value" pairs list.
+ * Additional source values may be specified in the future.
+ *
+ * Additional tokens may be added in the future, so it is recommended
+ * that any token parser processing the returned string from
+ * NV_CTRL_BINARY_DATA_MODELINES be implemented to gracefully ignore
+ * unrecognized tokens.
+ *
+ * E.g.,
+ *
+ * "source=xserver, source=vesa, source=edid :: "1024x768_70"  75.0  1024 1048 1184 1328  768 771
+ * 777 806  -HSync -VSync"
+ * "source=xconfig, xconfig-name=1600x1200_60.00 :: "1600x1200_60_0"  161.0  1600 1704 1880 2160
+ * 1200 1201 1204 1242  -HSync +VSync"
+ */
+
+#define NV_CTRL_BINARY_DATA_MODELINES 1 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_METAMODES - Returns an X Screen's supported
+ * MetaModes.  MetaModes are returned in a buffer separated by a
+ * single '\0' and terminated by two consecutive '\0' s like so:
+ *
+ *  "MetaMode 1\0MetaMode 2\0MetaMode 3\0Last MetaMode\0\0"
+ *
+ * The MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+
+ * Each MetaMode string may be prepended with a comma-separated list
+ * of "token=value" pairs, separated from the MetaMode string with
+ * "::".  Currently, valid tokens are:
+ *
+ *    Token        Value
+ *   "id"         <number>     - the id of this MetaMode; this is stored in
+ *                               the Vertical Refresh field, as viewed
+ *                               by the XRandR and XF86VidMode X *
+ *                               extensions.
+ *
+ *   "switchable" "yes"/"no"   - whether this MetaMode may be switched to via
+ *                               ctrl-alt-+/-; Implicit MetaModes (see
+ *                               the "IncludeImplicitMetaModes" X
+ *                               config option), for example, are not
+ *                               normally made available through
+ *                               ctrl-alt-+/-.
+ *
+ *   "source"     "xconfig"    - the MetaMode was specified in the X
+ *                               config file.
+ *                "implicit"   - the MetaMode was implicitly added; see the
+ *                               "IncludeImplicitMetaModes" X config option
+ *                               for details.
+ *                "nv-control" - the MetaMode was added via the NV-CONTROL X
+ *                               extension to the currently running X server.
+ *                "RandR"      - the MetaMode was modified in response to an
+ *                               RandR RRSetCrtcConfig request.
+ *
+ * Additional tokens may be added in the future, so it is recommended
+ * that any token parser processing the returned string from
+ * NV_CTRL_BINARY_DATA_METAMODES be implemented to gracefully ignore
+ * unrecognized tokens.
+ *
+ * E.g.,
+ *
+ *   "id=50, switchable=yes, source=xconfig :: CRT-0: 1024x768 @1024x768 +0+0"
+ */
+
+#define NV_CTRL_BINARY_DATA_METAMODES 2 /* R-D- */
+#define NV_CTRL_BINARY_DATA_METAMODES_VERSION_1 NV_CTRL_BINARY_DATA_METAMODES
+
+/*
+ * NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU - Returns the list of X
+ * screens currently driven by the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of screens
+ *     4 * n   CARD32 screen indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU 3 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN - Returns the list of GPUs
+ * currently in use by the given X screen.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of GPUs
+ *     4 * n   CARD32 GPU indices
+ */
+
+#define NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN 4 /* R--- */
+
+/*
+ * NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK - Returns the list of
+ * GPUs currently connected to the given frame lock board.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of GPUs
+ *     4 * n   CARD32 GPU indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK 5 /* R-DF */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAY_VIEWPORT - Returns the Display Device's
+ * viewport box into the given X Screen (in X Screen coordinates.)
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 Offset X
+ *     4       CARD32 Offset Y
+ *     4       CARD32 Width
+ *     4       CARD32 Height
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAY_VIEWPORT 6 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU - Returns the list of
+ * Framelock devices currently connected to the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of Framelocks
+ *     4 * n   CARD32 Framelock indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU 7 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_GPUS_USING_VCSC - Returns the list of
+ * GPU devices connected to the given VCS.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of GPUs
+ *     4 * n   CARD32 GPU indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN and cannot be queried using
+ * a  NV_CTRL_TARGET_TYPE_X_GPU
+ */
+
+#define NV_CTRL_BINARY_DATA_GPUS_USING_VCSC 8 /* R-DV */
+
+/*
+ * NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU - Returns the VCSC device
+ * that is controlling the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of VCS (always 1)
+ *     4 * n   CARD32 VCS indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN
+ */
+
+#define NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU 9 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU - Returns the coolers that
+ * are cooling the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of COOLER
+ *     4 * n   CARD32 COOLER indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN
+ */
+
+#define NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU 10 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN - Returns the list of
+ * GPUs currently driving the given X screen.  If Xinerama is enabled, this
+ * will return all GPUs that are driving any X screen.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of GPUs
+ *     4 * n   CARD32 GPU indices
+ */
+
+#define NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN 11 /* R--- */
+
+/*
+ * NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU - Returns the sensors that
+ * are attached to the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of SENSOR
+ *     4 * n   CARD32 SENSOR indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.  This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN
+ */
+
+#define NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU 12 /* R--G */
+
+/*
+ * NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER - Returns
+ * the id of the glasses that are currently paired to the given
+ * 3D Vision Pro transceiver.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of glasses
+ *     4 * n   CARD32 id of glasses
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER target.
+ */
+#define NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER 13 /* R--T */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAY_TARGETS - Returns all the display devices
+ * currently connected to any GPU on the X server.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of display devices
+ *     4 * n   CARD32 display device indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData().
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAY_TARGETS 14 /* R--- */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU - Returns the list of
+ * display devices that are connected to the GPU target.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of display devices
+ *     4 * n   CARD32 display device indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU 15 /* R--G */
+
+/*
+ * NV_CTRL_BINARY_DATA_METAMODES_VERSION_2  - Returns values similar to
+ * NV_CTRL_BINARY_DATA_METAMODES(_VERSION_1) but also returns extended syntax
+ * information to indicate a specific display device, as well as other per-
+ * display deviceflags as "token=value" pairs.  For example:
+ *
+ *   "DPY-1: 1280x1024 {Stereo=PassiveLeft},
+ *    DPY-2: 1280x1024 {Stereo=PassiveRight},"
+ *
+ * The display device names have the form "DPY-%d", where the integer
+ * part of the name is the NV-CONTROL target ID for that display device
+ * for this instance of the X server.  Note that display device NV-CONTROL
+ * target IDs are not guaranteed to be the same from one run of the X
+ * server to the next.
+ */
+
+#define NV_CTRL_BINARY_DATA_METAMODES_VERSION_2 16 /* R-D- */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN - Returns the list of
+ * display devices that are currently scanning out the X screen target.
+ *
+ * The format of the returned data is:
+ *
+ *     4       CARD32 number of display devices
+ *     4 * n   CARD32 display device indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN 17 /* R--- */
+
+#define NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN
+
+/**************************************************************************/
+
+/*
+ * String Operation Attributes:
+ *
+ * These attributes are used with the XNVCTRLStringOperation()
+ * function; a string is specified as input, and a string is returned
+ * as output.
+ *
+ * Unless otherwise noted, all attributes can be operated upon using
+ * an NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+/*
+ * NV_CTRL_STRING_OPERATION_ADD_METAMODE - provide a MetaMode string
+ * as input, and returns a string containing comma-separated list of
+ * "token=value" pairs as output.  Currently, the only output token is
+ * "id", which indicates the id that was assigned to the MetaMode.
+ *
+ * All ModeLines referenced in the MetaMode must already exist for
+ * each display device (as returned by the
+ * NV_CTRL_BINARY_DATA_MODELINES attribute).
+ *
+ * The MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+ *
+ * The input string can optionally be prepended with a string of
+ * comma-separated "token=value" pairs, separated from the MetaMode
+ * string by "::".  Currently, the only valid token is "index" which
+ * indicates the insertion index for the MetaMode.
+ *
+ * E.g.,
+ *
+ * Input: "index=5 :: 1600x1200+0+0, 1600x1200+1600+0"
+ * Output: "id=58"
+ *
+ * which causes the MetaMode to be inserted at position 5 in the
+ * MetaMode list (all entries after 5 will be shifted down one slot in
+ * the list), and the X server's containing mode stores 58 as the
+ * VRefresh, so that the MetaMode can be uniquely identifed through
+ * XRandR and XF86VidMode.
+ */
+
+#define NV_CTRL_STRING_OPERATION_ADD_METAMODE 0
+
+/*
+ * NV_CTRL_STRING_OPERATION_GTF_MODELINE - provide as input a string
+ * of comma-separated "token=value" pairs, and returns a ModeLine
+ * string, computed using the GTF formula using the parameters from
+ * the input string.  Valid tokens for the input string are "width",
+ * "height", and "refreshrate".
+ *
+ * E.g.,
+ *
+ * Input: "width=1600, height=1200, refreshrate=60"
+ * Output: "160.96  1600 1704 1880 2160  1200 1201 1204 1242  -HSync +VSync"
+ *
+ * This operation does not have any impact on any display device's
+ * modePool, and the ModeLine is not validated; it is simply intended
+ * for generating ModeLines.
+ */
+
+#define NV_CTRL_STRING_OPERATION_GTF_MODELINE 1
+
+/*
+ * NV_CTRL_STRING_OPERATION_CVT_MODELINE - provide as input a string
+ * of comma-separated "token=value" pairs, and returns a ModeLine
+ * string, computed using the CVT formula using the parameters from
+ * the input string.  Valid tokens for the input string are "width",
+ * "height", "refreshrate", and "reduced-blanking".  The
+ * "reduced-blanking" argument can be "0" or "1", to enable or disable
+ * use of reduced blanking for the CVT formula.
+ *
+ * E.g.,
+ *
+ * Input: "width=1600, height=1200, refreshrate=60, reduced-blanking=1"
+ * Output: "130.25  1600 1648 1680 1760  1200 1203 1207 1235  +HSync -VSync"
+ *
+ * This operation does not have any impact on any display device's
+ * modePool, and the ModeLine is not validated; it is simply intended
+ * for generating ModeLines.
+ */
+
+#define NV_CTRL_STRING_OPERATION_CVT_MODELINE 2
+
+/*
+ * NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL - build a ModePool for the
+ * specified display device on the specified target (either an X
+ * screen or a GPU).  This is typically used to generate a ModePool
+ * for a display device on a GPU on which no X screens are present.
+ *
+ * Currently, a display device's ModePool is static for the life of
+ * the X server, so XNVCTRLStringOperation will return FALSE if
+ * requested to build a ModePool on a display device that already has
+ * a ModePool.
+ *
+ * The string input to BUILD_MODEPOOL may be NULL.  If it is not NULL,
+ * then it is interpreted as a double-colon ("::") separated list
+ * of "option=value" pairs, where the options and the syntax of their
+ * values are the X configuration options that impact the behavior of
+ * modePool construction; namely:
+ *
+ *    "ModeValidation"
+ *    "HorizSync"
+ *    "VertRefresh"
+ *    "FlatPanelProperties"
+ *    "TVStandard"
+ *    "ExactModeTimingsDVI"
+ *    "UseEdidFreqs"
+ *
+ * An example input string might look like:
+ *
+ *   "ModeValidation=NoVesaModes :: HorizSync=50-110 :: VertRefresh=50-150"
+ *
+ * This request currently does not return a string.
+ */
+
+#define NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL 3 /* DG */
+
+/*
+ * NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS - Configure the streams-
+ * to-jack+channel topology for a GVI (Graphics capture board).
+ *
+ * The string input to GVI_CONFIGURE_STREAMS may be NULL.  If this is the
+ * case, then the current topology is returned.
+ *
+ * If the input string to GVI_CONFIGURE_STREAMS is not NULL, the string
+ * is interpreted as a semicolon (";") separated list of comma-separated
+ * lists of "option=value" pairs that define a stream's composition.  The
+ * available options and their values are:
+ *
+ *   "stream": Defines which stream this comma-separated list describes.
+ *             Valid values are the integers between 0 and
+ *             NV_CTRL_GVI_NUM_STREAMS-1 (inclusive).
+ *
+ *   "linkN":  Defines a jack+channel pair to use for the given link N.
+ *             Valid options are the string "linkN", where N is an integer
+ *             between 0 and NV_CTRL_GVI_MAX_LINKS_PER_STREAM-1 (inclusive).
+ *             Valid values for these options are strings of the form
+ *             "jackX" and/or "jackX.Y", where X is an integer between 0 and
+ *             NV_CTRL_GVI_NUM_JACKS-1 (inclusive), and Y (optional) is an
+ *             integer between 0 and NV_CTRL_GVI_MAX_CHANNELS_PER_JACK-1
+ *             (inclusive).
+ *
+ * An example input string might look like:
+ *
+ *   "stream=0, link0=jack0, link1=jack1; stream=1, link0=jack2.1"
+ *
+ *   This example specifies two streams, stream 0 and stream 1.  Stream 0
+ *   is defined to capture link0 data from the first channel (channel 0) of
+ *   BNC jack 0 and link1 data from the first channel of BNC jack 1.  The
+ *   second stream (Stream 1) is defined to capture link0 data from channel 1
+ *   (second channel) of BNC jack 2.
+ *
+ * This example shows a possible configuration for capturing 3G input:
+ *
+ *   "stream=0, link0=jack0.0, link1=jack0.1"
+ *
+ * Applications should query the following attributes to determine
+ * possible combinations:
+ *
+ *   NV_CTRL_GVI_MAX_STREAMS
+ *   NV_CTRL_GVI_MAX_LINKS_PER_STREAM
+ *   NV_CTRL_GVI_NUM_JACKS
+ *   NV_CTRL_GVI_MAX_CHANNELS_PER_JACK
+ *
+ * Note: A jack+channel pair can only be tied to one link/stream.
+ *
+ * Upon successful configuration or querying of this attribute, a string
+ * representing the current topology for all known streams on the device
+ * will be returned.  On failure, NULL is returned.
+ *
+ * Note: Setting this attribute may also result in the following
+ *       NV-CONTROL attributes being reset on the GVI device (to ensure
+ *       the configuration remains valid):
+ *           NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT
+ *           NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT
+ *           NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING
+ */
+
+#define NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS 4 /* RW-I */
+
+#define NV_CTRL_STRING_OPERATION_LAST_ATTRIBUTE NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS
+
+/**************************************************************************/
+
+/*
+ * CTRLAttributeValidValuesRec -
+ *
+ * structure and related defines used by
+ * XNVCTRLQueryValidAttributeValues() to describe the valid values of
+ * a particular attribute.  The type field will be one of:
+ *
+ * ATTRIBUTE_TYPE_INTEGER : the attribute is an integer value; there
+ * is no fixed range of valid values.
+ *
+ * ATTRIBUTE_TYPE_BITMASK : the attribute is an integer value,
+ * interpretted as a bitmask.
+ *
+ * ATTRIBUTE_TYPE_BOOL : the attribute is a boolean, valid values are
+ * either 1 (on/true) or 0 (off/false).
+ *
+ * ATTRIBUTE_TYPE_RANGE : the attribute can have any integer value
+ * between NVCTRLAttributeValidValues.u.range.min and
+ * NVCTRLAttributeValidValues.u.range.max (inclusive).
+ *
+ * ATTRIBUTE_TYPE_INT_BITS : the attribute can only have certain
+ * integer values, indicated by which bits in
+ * NVCTRLAttributeValidValues.u.bits.ints are on (for example: if bit
+ * 0 is on, then 0 is a valid value; if bit 5 is on, then 5 is a valid
+ * value, etc).  This is useful for attributes like NV_CTRL_FSAA_MODE,
+ * which can only have certain values, depending on GPU.
+ *
+ * ATTRIBUTE_TYPE_64BIT_INTEGER : the attribute is a 64 bit integer value;
+ * there is no fixed range of valid values.
+ *
+ * ATTRIBUTE_TYPE_STRING : the attribute is a string value; there is no fixed
+ * range of valid values.
+ *
+ * ATTRIBUTE_TYPE_BINARY_DATA : the attribute is binary data; there is
+ * no fixed range of valid values.
+ *
+ * ATTRIBUTE_TYPE_STRING_OPERATION : the attribute is a string; there is
+ * no fixed range of valid values.
+ *
+ *
+ * The permissions field of NVCTRLAttributeValidValuesRec is a bitmask
+ * that may contain:
+ *
+ * ATTRIBUTE_TYPE_READ      - Attribute may be read (queried.)
+ * ATTRIBUTE_TYPE_WRITE     - Attribute may be written to (set.)
+ * ATTRIBUTE_TYPE_DISPLAY   - Attribute is valid for display target types
+ *                            (requires a display_mask if queried via
+ *                            a GPU or X screen.)
+ * ATTRIBUTE_TYPE_GPU       - Attribute is valid for GPU target types.
+ * ATTRIBUTE_TYPE_FRAMELOCK - Attribute is valid for Frame Lock target types.
+ * ATTRIBUTE_TYPE_X_SCREEN  - Attribute is valid for X Screen target types.
+ * ATTRIBUTE_TYPE_XINERAMA  - Attribute will be made consistent for all
+ *                            X Screens when the Xinerama extension is enabled.
+ * ATTRIBUTE_TYPE_VCSC      - Attribute is valid for Visual Computing System
+ *                            target types.
+ * ATTRIBUTE_TYPE_GVI       - Attribute is valid for Graphics Video In target
+ *                            types.
+ * ATTRIBUTE_TYPE_COOLER    - Attribute is valid for Cooler target types.
+ * ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER - Attribute is valid for 3D Vision
+ *                                            Pro Transceiver target types.
+ *
+ * See 'Key to Integer Attribute "Permissions"' at the top of this
+ * file for a description of what these permission bits mean.
+ */
+
+#define ATTRIBUTE_TYPE_UNKNOWN 0
+#define ATTRIBUTE_TYPE_INTEGER 1
+#define ATTRIBUTE_TYPE_BITMASK 2
+#define ATTRIBUTE_TYPE_BOOL 3
+#define ATTRIBUTE_TYPE_RANGE 4
+#define ATTRIBUTE_TYPE_INT_BITS 5
+#define ATTRIBUTE_TYPE_64BIT_INTEGER 6
+#define ATTRIBUTE_TYPE_STRING 7
+#define ATTRIBUTE_TYPE_BINARY_DATA 8
+#define ATTRIBUTE_TYPE_STRING_OPERATION 9
+
+#define ATTRIBUTE_TYPE_READ 0x001
+#define ATTRIBUTE_TYPE_WRITE 0x002
+#define ATTRIBUTE_TYPE_DISPLAY 0x004
+#define ATTRIBUTE_TYPE_GPU 0x008
+#define ATTRIBUTE_TYPE_FRAMELOCK 0x010
+#define ATTRIBUTE_TYPE_X_SCREEN 0x020
+#define ATTRIBUTE_TYPE_XINERAMA 0x040
+#define ATTRIBUTE_TYPE_VCSC 0x080
+#define ATTRIBUTE_TYPE_GVI 0x100
+#define ATTRIBUTE_TYPE_COOLER 0x200
+#define ATTRIBUTE_TYPE_THERMAL_SENSOR 0x400
+#define ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER 0x800
+
+#define ATTRIBUTE_TYPE_ALL_TARGETS                                                  \
+    ((ATTRIBUTE_TYPE_DISPLAY) | (ATTRIBUTE_TYPE_GPU) | (ATTRIBUTE_TYPE_FRAMELOCK) | \
+     (ATTRIBUTE_TYPE_X_SCREEN) | (ATTRIBUTE_TYPE_VCSC) | (ATTRIBUTE_TYPE_GVI) |     \
+     (ATTRIBUTE_TYPE_COOLER) | (ATTRIBUTE_TYPE_THERMAL_SENSOR) |                    \
+     (ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER))
+
+typedef struct _NVCTRLAttributeValidValues
+{
+    int type;
+    union
+    {
+        struct
+        {
+            int64_t min;
+            int64_t max;
+        } range;
+        struct
+        {
+            unsigned int ints;
+        } bits;
+    } u;
+    unsigned int permissions;
+} NVCTRLAttributeValidValuesRec;
+
+typedef struct _NVCTRLAttributePermissions
+{
+    int type;
+    unsigned int permissions;
+} NVCTRLAttributePermissionsRec;
+
+/**************************************************************************/
+
+/*
+ * NV-CONTROL X event notification.
+ *
+ * To receive X event notifications dealing with NV-CONTROL, you should
+ * call XNVCtrlSelectNotify() with one of the following set as the type
+ * of event to receive (see NVCtrlLib.h for more information):
+ */
+
+#define ATTRIBUTE_CHANGED_EVENT 0
+#define TARGET_ATTRIBUTE_CHANGED_EVENT 1
+#define TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT 2
+#define TARGET_STRING_ATTRIBUTE_CHANGED_EVENT 3
+#define TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT 4
+
+#endif /* __NVCTRL_H */
diff --git a/src/third_party/angle/src/third_party/libXNVCtrl/NVCtrlLib.h b/src/third_party/angle/src/third_party/libXNVCtrl/NVCtrlLib.h
new file mode 100644
index 0000000..1a5d5de
--- /dev/null
+++ b/src/third_party/angle/src/third_party/libXNVCtrl/NVCtrlLib.h
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 2008 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NVCTRLLIB_H
+#define __NVCTRLLIB_H
+
+#include "NVCtrl.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  XNVCTRLQueryExtension -
+ *
+ *  Returns True if the extension exists, returns False otherwise.
+ *  event_basep and error_basep are the extension event and error
+ *  bases.  Currently, no extension specific errors or events are
+ *  defined.
+ */
+
+Bool XNVCTRLQueryExtension(Display *dpy, int *event_basep, int *error_basep);
+
+/*
+ *  XNVCTRLQueryVersion -
+ *
+ *  Returns True if the extension exists, returns False otherwise.
+ *  major and minor are the extension's major and minor version
+ *  numbers.
+ */
+
+Bool XNVCTRLQueryVersion(Display *dpy, int *major, int *minor);
+
+/*
+ *  XNVCTRLIsNvScreen
+ *
+ *  Returns True is the specified screen is controlled by the NVIDIA
+ *  driver.  Returns False otherwise.
+ */
+
+Bool XNVCTRLIsNvScreen(Display *dpy, int screen);
+
+/*
+ *  XNVCTRLQueryTargetCount -
+ *
+ *  Returns True if the target type exists.  Returns False otherwise.
+ *  If XNVCTRLQueryTargetCount returns True, value will contain the
+ *  count of existing targets on the server of the specified target
+ *  type.
+ *
+ *  Please see "Attribute Targets" in NVCtrl.h for the list of valid
+ *  target types.
+ *
+ *  Possible errors:
+ *     BadValue - The target doesn't exist.
+ */
+
+Bool XNVCTRLQueryTargetCount(Display *dpy, int target_type, int *value);
+
+/*
+ *  XNVCTRLSetAttribute -
+ *
+ *  Sets the attribute to the given value.  The attributes and their
+ *  possible values are listed in NVCtrl.h.
+ *
+ *  Not all attributes require the display_mask parameter; see
+ *  NVCtrl.h for details.
+ *
+ *  Calling this function is equivalent to calling XNVCTRLSetTargetAttribute()
+ *  with the target_type set to NV_CTRL_TARGET_TYPE_X_SCREEN and
+ *  target_id set to 'screen'.
+ *
+ *  Possible errors:
+ *     BadValue - The screen or attribute doesn't exist.
+ *     BadMatch - The NVIDIA driver is not present on that screen.
+ */
+
+void XNVCTRLSetAttribute(Display *dpy,
+                         int screen,
+                         unsigned int display_mask,
+                         unsigned int attribute,
+                         int value);
+
+/*
+ *  XNVCTRLSetTargetAttribute -
+ *
+ *  Sets the attribute to the given value.  The attributes and their
+ *  possible values are listed in NVCtrl.h.
+ *
+ *  Not all attributes require the display_mask parameter; see
+ *  NVCtrl.h for details.
+ *
+ *  Possible errors:
+ *     BadValue - The target or attribute doesn't exist.
+ *     BadMatch - The NVIDIA driver is not present on that target.
+ */
+
+void XNVCTRLSetTargetAttribute(Display *dpy,
+                               int target_type,
+                               int target_id,
+                               unsigned int display_mask,
+                               unsigned int attribute,
+                               int value);
+
+/*
+ *  XNVCTRLSetAttributeAndGetStatus -
+ *
+ * Same as XNVCTRLSetAttribute().
+ * In addition, XNVCTRLSetAttributeAndGetStatus() returns
+ * True if the operation succeeds, False otherwise.
+ *
+ */
+
+Bool XNVCTRLSetAttributeAndGetStatus(Display *dpy,
+                                     int screen,
+                                     unsigned int display_mask,
+                                     unsigned int attribute,
+                                     int value);
+
+/*
+ *  XNVCTRLSetTargetAttributeAndGetStatus -
+ *
+ * Same as XNVCTRLSetTargetAttribute().
+ * In addition, XNVCTRLSetTargetAttributeAndGetStatus() returns
+ * True if the operation succeeds, False otherwise.
+ *
+ */
+
+Bool XNVCTRLSetTargetAttributeAndGetStatus(Display *dpy,
+                                           int target_type,
+                                           int target_id,
+                                           unsigned int display_mask,
+                                           unsigned int attribute,
+                                           int value);
+
+/*
+ *  XNVCTRLQueryAttribute -
+ *
+ *  Returns True if the attribute exists.  Returns False otherwise.
+ *  If XNVCTRLQueryAttribute returns True, value will contain the
+ *  value of the specified attribute.
+ *
+ *  Not all attributes require the display_mask parameter; see
+ *  NVCtrl.h for details.
+ *
+ *  Calling this function is equivalent to calling
+ *  XNVCTRLQueryTargetAttribute() with the target_type set to
+ *  NV_CTRL_TARGET_TYPE_X_SCREEN and target_id set to 'screen'.
+ *
+ *  Possible errors:
+ *     BadValue - The screen doesn't exist.
+ *     BadMatch - The NVIDIA driver is not present on that screen.
+ */
+
+Bool XNVCTRLQueryAttribute(Display *dpy,
+                           int screen,
+                           unsigned int display_mask,
+                           unsigned int attribute,
+                           int *value);
+
+/*
+ * XNVCTRLQueryTargetAttribute -
+ *
+ *  Returns True if the attribute exists.  Returns False otherwise.
+ *  If XNVCTRLQueryTargetAttribute returns True, value will contain the
+ *  value of the specified attribute.
+ *
+ *  Not all attributes require the display_mask parameter; see
+ *  NVCtrl.h for details.
+ *
+ *  Possible errors:
+ *     BadValue - The target doesn't exist.
+ *     BadMatch - The NVIDIA driver does not control the target.
+ */
+
+Bool XNVCTRLQueryTargetAttribute(Display *dpy,
+                                 int target_Type,
+                                 int target_id,
+                                 unsigned int display_mask,
+                                 unsigned int attribute,
+                                 int *value);
+
+/*
+ * XNVCTRLQueryTargetAttribute64 -
+ *
+ *  Returns True if the attribute exists.  Returns False otherwise.
+ *  If XNVCTRLQueryTargetAttribute returns True, value will contain the
+ *  value of the specified attribute.
+ *
+ *  Not all attributes require the display_mask parameter; see
+ *  NVCtrl.h for details.
+ *
+ *  Note: this function behaves like XNVCTRLQueryTargetAttribute(),
+ *  but supports 64-bit integer attributes.
+ *
+ *  Possible errors:
+ *     BadValue - The target doesn't exist.
+ *     BadMatch - The NVIDIA driver does not control the target.
+ */
+
+Bool XNVCTRLQueryTargetAttribute64(Display *dpy,
+                                   int target_Type,
+                                   int target_id,
+                                   unsigned int display_mask,
+                                   unsigned int attribute,
+                                   int64_t *value);
+
+/*
+ *  XNVCTRLQueryStringAttribute -
+ *
+ *  Returns True if the attribute exists.  Returns False otherwise.
+ *  If XNVCTRLQueryStringAttribute returns True, *ptr will point to an
+ *  allocated string containing the string attribute requested.  It is
+ *  the caller's responsibility to free the string when done.
+ *
+ *  Calling this function is equivalent to calling
+ *  XNVCTRLQueryTargetStringAttribute() with the target_type set to
+ *  NV_CTRL_TARGET_TYPE_X_SCREEN and target_id set to 'screen'.
+ *
+ *  Possible errors:
+ *     BadValue - The screen doesn't exist.
+ *     BadMatch - The NVIDIA driver is not present on that screen.
+ *     BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLQueryStringAttribute(Display *dpy,
+                                 int screen,
+                                 unsigned int display_mask,
+                                 unsigned int attribute,
+                                 char **ptr);
+
+/*
+ *  XNVCTRLQueryTargetStringAttribute -
+ *
+ *  Returns True if the attribute exists.  Returns False otherwise.
+ *  If XNVCTRLQueryTargetStringAttribute returns True, *ptr will point
+ *  to an allocated string containing the string attribute requested.
+ *  It is the caller's responsibility to free the string when done.
+ *
+ *  Possible errors:
+ *     BadValue - The target doesn't exist.
+ *     BadMatch - The NVIDIA driver does not control the target.
+ *     BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLQueryTargetStringAttribute(Display *dpy,
+                                       int target_type,
+                                       int target_id,
+                                       unsigned int display_mask,
+                                       unsigned int attribute,
+                                       char **ptr);
+
+/*
+ *  XNVCTRLSetStringAttribute -
+ *
+ *  Returns True if the operation succeded.  Returns False otherwise.
+ *
+ *  Possible X errors:
+ *     BadValue - The screen doesn't exist.
+ *     BadMatch - The NVIDIA driver is not present on that screen.
+ *     BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLSetStringAttribute(Display *dpy,
+                               int screen,
+                               unsigned int display_mask,
+                               unsigned int attribute,
+                               char *ptr);
+
+/*
+ *  XNVCTRLSetTargetStringAttribute -
+ *
+ *  Returns True if the operation succeded.  Returns False otherwise.
+ *
+ *  Possible X errors:
+ *     BadValue - The screen doesn't exist.
+ *     BadMatch - The NVIDIA driver is not present on that screen.
+ *     BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLSetTargetStringAttribute(Display *dpy,
+                                     int target_type,
+                                     int target_id,
+                                     unsigned int display_mask,
+                                     unsigned int attribute,
+                                     char *ptr);
+
+/*
+ * XNVCTRLQueryValidAttributeValues -
+ *
+ * Returns True if the attribute exists.  Returns False otherwise.  If
+ * XNVCTRLQueryValidAttributeValues returns True, values will indicate
+ * the valid values for the specified attribute; see the description
+ * of NVCTRLAttributeValidValues in NVCtrl.h.
+ *
+ *  Calling this function is equivalent to calling
+ *  XNVCTRLQueryValidTargetAttributeValues() with the target_type set to
+ *  NV_CTRL_TARGET_TYPE_X_SCREEN and target_id set to 'screen'.
+ */
+
+Bool XNVCTRLQueryValidAttributeValues(Display *dpy,
+                                      int screen,
+                                      unsigned int display_mask,
+                                      unsigned int attribute,
+                                      NVCTRLAttributeValidValuesRec *values);
+
+/*
+ * XNVCTRLQueryValidTargetAttributeValues -
+ *
+ * Returns True if the attribute exists.  Returns False otherwise.  If
+ * XNVCTRLQueryValidTargetAttributeValues returns True, values will indicate
+ * the valid values for the specified attribute.
+ */
+
+Bool XNVCTRLQueryValidTargetAttributeValues(Display *dpy,
+                                            int target_type,
+                                            int target_id,
+                                            unsigned int display_mask,
+                                            unsigned int attribute,
+                                            NVCTRLAttributeValidValuesRec *values);
+
+/*
+ * XNVCTRLQueryValidTargetStringAttributeValues -
+ *
+ * Returns True if the attribute exists.  Returns False otherwise.  If
+ * XNVCTRLQueryValidTargetStringAttributeValues returns True, values will
+ * indicate the valid values for the specified attribute.
+ */
+
+Bool XNVCTRLQueryValidTargetStringAttributeValues(Display *dpy,
+                                                  int target_type,
+                                                  int target_id,
+                                                  unsigned int display_mask,
+                                                  unsigned int attribute,
+                                                  NVCTRLAttributeValidValuesRec *values);
+
+/*
+ * XNVCTRLQueryAttributePermissions -
+ *
+ * Returns True if the attribute exists.  Returns False otherwise.  If
+ * XNVCTRLQueryAttributePermissions returns True, permissions will
+ * indicate the permission flags for the attribute.
+ */
+
+Bool XNVCTRLQueryAttributePermissions(Display *dpy,
+                                      unsigned int attribute,
+                                      NVCTRLAttributePermissionsRec *permissions);
+
+/*
+ * XNVCTRLQueryStringAttributePermissions -
+ *
+ * Returns True if the attribute exists.  Returns False otherwise.  If
+ * XNVCTRLQueryStringAttributePermissions returns True, permissions will
+ * indicate the permission flags for the attribute.
+ */
+
+Bool XNVCTRLQueryStringAttributePermissions(Display *dpy,
+                                            unsigned int attribute,
+                                            NVCTRLAttributePermissionsRec *permissions);
+
+/*
+ * XNVCTRLQueryBinaryDataAttributePermissions -
+ *
+ * Returns True if the attribute exists.  Returns False otherwise.  If
+ * XNVCTRLQueryBinaryDataAttributePermissions returns True, permissions
+ * will indicate the permission flags for the attribute.
+ */
+
+Bool XNVCTRLQueryBinaryDataAttributePermissions(Display *dpy,
+                                                unsigned int attribute,
+                                                NVCTRLAttributePermissionsRec *permissions);
+
+/*
+ * XNVCTRLQueryStringOperationAttributePermissions -
+ *
+ * Returns True if the attribute exists.  Returns False otherwise.  If
+ * XNVCTRLQueryStringOperationAttributePermissions returns True,
+ * permissions will indicate the permission flags for the attribute.
+ */
+
+Bool XNVCTRLQueryStringOperationAttributePermissions(Display *dpy,
+                                                     unsigned int attribute,
+                                                     NVCTRLAttributePermissionsRec *permissions);
+
+/*
+ *  XNVCTRLSetGvoColorConversion -
+ *
+ *  Sets the color conversion matrix, offset, and scale that should be
+ *  used for GVO (Graphic to Video Out).
+ *
+ *  The Color Space Conversion data is ordered like this:
+ *
+ *   colorMatrix[0][0] // r.Y
+ *   colorMatrix[0][1] // g.Y
+ *   colorMatrix[0][2] // b.Y
+ *
+ *   colorMatrix[1][0] // r.Cr
+ *   colorMatrix[1][1] // g.Cr
+ *   colorMatrix[1][2] // b.Cr
+ *
+ *   colorMatrix[2][0] // r.Cb
+ *   colorMatrix[2][1] // g.Cb
+ *   colorMatrix[2][2] // b.Cb
+ *
+ *   colorOffset[0]    // Y
+ *   colorOffset[1]    // Cr
+ *   colorOffset[2]    // Cb
+ *
+ *   colorScale[0]     // Y
+ *   colorScale[1]     // Cr
+ *   colorScale[2]     // Cb
+ *
+ *  where the data is used according to the following formulae:
+ *
+ *   Y  =  colorOffset[0] + colorScale[0] *
+ *           (R * colorMatrix[0][0] +
+ *            G * colorMatrix[0][1] +
+ *            B * colorMatrix[0][2]);
+ *
+ *   Cr =  colorOffset[1] + colorScale[1] *
+ *           (R * colorMatrix[1][0] +
+ *            G * colorMatrix[1][1] +
+ *            B * colorMatrix[1][2]);
+ *
+ *   Cb =  colorOffset[2] + colorScale[2] *
+ *           (R * colorMatrix[2][0] +
+ *            G * colorMatrix[2][1] +
+ *            B * colorMatrix[2][2]);
+ *
+ *  Possible errors:
+ *     BadMatch - The NVIDIA driver is not present on that screen.
+ *     BadImplementation - GVO is not available on that screen.
+ */
+
+void XNVCTRLSetGvoColorConversion(Display *dpy,
+                                  int screen,
+                                  float colorMatrix[3][3],
+                                  float colorOffset[3],
+                                  float colorScale[3]);
+
+/*
+ *  XNVCTRLQueryGvoColorConversion -
+ *
+ *  Retrieves the color conversion matrix and color offset
+ *  that are currently being used for GVO (Graphic to Video Out).
+ *
+ *  The values are ordered within the arrays according to the comments
+ *  for XNVCTRLSetGvoColorConversion().
+ *
+ *  Possible errors:
+ *     BadMatch - The NVIDIA driver is not present on that screen.
+ *     BadImplementation - GVO is not available on that screen.
+ */
+
+Bool XNVCTRLQueryGvoColorConversion(Display *dpy,
+                                    int screen,
+                                    float colorMatrix[3][3],
+                                    float colorOffset[3],
+                                    float colorScale[3]);
+
+/*
+ *  XNVCTRLQueryBinaryData -
+ *
+ *  Returns True if the attribute exists.  Returns False otherwise.
+ *  If XNVCTRLQueryBinaryData returns True, *ptr will point to an
+ *  allocated block of memory containing the binary data attribute
+ *  requested.  It is the caller's responsibility to free the data
+ *  when done.  len will list the length of the binary data.
+ *
+ *  Calling this function is equivalent to calling
+ *  XNVCTRLQueryTargetBinaryData() with the target_type set to
+ *  NV_CTRL_TARGET_TYPE_X_SCREEN and target_id set to 'screen'.
+ *
+ *  Possible errors:
+ *     BadValue - The screen doesn't exist.
+ *     BadMatch - The NVIDIA driver is not present on that screen.
+ *     BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLQueryBinaryData(Display *dpy,
+                            int screen,
+                            unsigned int display_mask,
+                            unsigned int attribute,
+                            unsigned char **ptr,
+                            int *len);
+
+/*
+ * XNVCTRLQueryTargetBinaryData -
+ *
+ *  Returns True if the attribute exists.  Returns False otherwise.
+ *  If XNVCTRLQueryTargetBinaryData returns True, *ptr will point to an
+ *  allocated block of memory containing the binary data attribute
+ *  requested.  It is the caller's responsibility to free the data
+ *  when done.  len will list the length of the binary data.
+ *
+ *  Possible errors:
+ *     BadValue - The target doesn't exist.
+ *     BadMatch - The NVIDIA driver does not control the target.
+ *     BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLQueryTargetBinaryData(Display *dpy,
+                                  int target_type,
+                                  int target_id,
+                                  unsigned int display_mask,
+                                  unsigned int attribute,
+                                  unsigned char **ptr,
+                                  int *len);
+
+/*
+ * XNVCTRLStringOperation -
+ *
+ * Takes a string as input and returns a Xmalloc'ed string as output.
+ * Returns True on success and False on failure.
+ */
+
+Bool XNVCTRLStringOperation(Display *dpy,
+                            int target_type,
+                            int target_id,
+                            unsigned int display_mask,
+                            unsigned int attribute,
+                            char *pIn,
+                            char **ppOut);
+
+/*
+ * XNVCtrlSelectNotify -
+ *
+ * This enables/disables receiving of NV-CONTROL events.  The type
+ * specifies the type of event to enable (currently, the only
+ * type that can be requested per-screen with XNVCtrlSelectNotify()
+ * is ATTRIBUTE_CHANGED_EVENT); onoff controls whether receiving this
+ * type of event should be enabled (True) or disabled (False).
+ *
+ * Returns True if successful, or False if the screen is not
+ * controlled by the NVIDIA driver.
+ */
+
+Bool XNVCtrlSelectNotify(Display *dpy, int screen, int type, Bool onoff);
+
+/*
+ * XNVCtrlSelectTargetNotify -
+ *
+ * This enables/disables receiving of NV-CONTROL events that happen on
+ * the specified target.  The notify_type specifies the type of event to
+ * enable (currently, the only type that can be requested per-target with
+ * XNVCtrlSelectTargetNotify() is TARGET_ATTRIBUTE_CHANGED_EVENT); onoff
+ * controls whether receiving this type of event should be enabled (True)
+ * or disabled (False).
+ *
+ * Returns True if successful, or False if the target is not
+ * controlled by the NVIDIA driver.
+ */
+
+Bool XNVCtrlSelectTargetNotify(Display *dpy,
+                               int target_type,
+                               int target_id,
+                               int notify_type,
+                               Bool onoff);
+
+/*
+ * XNVCtrlEvent structure
+ */
+
+typedef struct
+{
+    int type;
+    unsigned long serial;
+    Bool send_event; /* always FALSE, we don't allow send_events */
+    Display *display;
+    Time time;
+    int screen;
+    unsigned int display_mask;
+    unsigned int attribute;
+    int value;
+} XNVCtrlAttributeChangedEvent;
+
+typedef union
+{
+    int type;
+    XNVCtrlAttributeChangedEvent attribute_changed;
+    long pad[24];
+} XNVCtrlEvent;
+
+/*
+ * XNVCtrlEventTarget structure
+ */
+
+typedef struct
+{
+    int type;
+    unsigned long serial;
+    Bool send_event; /* always FALSE, we don't allow send_events */
+    Display *display;
+    Time time;
+    int target_type;
+    int target_id;
+    unsigned int display_mask;
+    unsigned int attribute;
+    int value;
+} XNVCtrlAttributeChangedEventTarget;
+
+typedef union
+{
+    int type;
+    XNVCtrlAttributeChangedEventTarget attribute_changed;
+    long pad[24];
+} XNVCtrlEventTarget;
+
+/*
+ * XNVCtrlEventTargetAvailability structure
+ */
+
+typedef struct
+{
+    int type;
+    unsigned long serial;
+    Bool send_event; /* always FALSE, we don't allow send_events */
+    Display *display;
+    Time time;
+    int target_type;
+    int target_id;
+    unsigned int display_mask;
+    unsigned int attribute;
+    int value;
+    Bool availability;
+} XNVCtrlAttributeChangedEventTargetAvailability;
+
+typedef union
+{
+    int type;
+    XNVCtrlAttributeChangedEventTargetAvailability attribute_changed;
+    long pad[24];
+} XNVCtrlEventTargetAvailability;
+
+/*
+ * XNVCtrlStringEventTarget structure
+ */
+
+typedef struct
+{
+    int type;
+    unsigned long serial;
+    Bool send_event; /* always FALSE, we don't allow send_events */
+    Display *display;
+    Time time;
+    int target_type;
+    int target_id;
+    unsigned int display_mask;
+    unsigned int attribute;
+} XNVCtrlStringAttributeChangedEventTarget;
+
+typedef union
+{
+    int type;
+    XNVCtrlStringAttributeChangedEventTarget attribute_changed;
+    long pad[24];
+} XNVCtrlStringEventTarget;
+
+/*
+ * XNVCtrlBinaryEventTarget structure
+ */
+
+typedef struct
+{
+    int type;
+    unsigned long serial;
+    Bool send_event; /* always FALSE, we don't allow send_events */
+    Display *display;
+    Time time;
+    int target_type;
+    int target_id;
+    unsigned int display_mask;
+    unsigned int attribute;
+} XNVCtrlBinaryAttributeChangedEventTarget;
+
+typedef union
+{
+    int type;
+    XNVCtrlBinaryAttributeChangedEventTarget attribute_changed;
+    long pad[24];
+} XNVCtrlBinaryEventTarget;
+
+#if defined __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __NVCTRLLIB_H */
diff --git a/src/third_party/angle/src/third_party/libXNVCtrl/README.angle b/src/third_party/angle/src/third_party/libXNVCtrl/README.angle
new file mode 100644
index 0000000..22b9bd0
--- /dev/null
+++ b/src/third_party/angle/src/third_party/libXNVCtrl/README.angle
@@ -0,0 +1,14 @@
+Name: NVidia Control X Extension Library
+Short Name: libXNVCtrl
+URL: http://cgit.freedesktop.org/~aplattner/nvidia-settings/
+Version: unknown
+Date: 2008
+License: MIT
+Security Critical: no
+
+Description:
+This package provides access to NVidia Control X Extension. It is used to determine the version of the NVIDIA driver in use.
+
+The current version is pulled from nvidia-settings-302.17.
+
+Local Modifications:
diff --git a/src/third_party/angle/src/third_party/libXNVCtrl/libXNVCtrl.gyp b/src/third_party/angle/src/third_party/libXNVCtrl/libXNVCtrl.gyp
new file mode 100644
index 0000000..6f0ee2f
--- /dev/null
+++ b/src/third_party/angle/src/third_party/libXNVCtrl/libXNVCtrl.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2016 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.
+
+{
+    'targets':
+    [{
+        'target_name': 'libXNVCtrl',
+        'type': 'static_library',
+        'sources':
+        [
+            'NVCtrl.c',
+            'NVCtrl.h',
+            'NVCtrlLib.h',
+            'nv_control.h',
+        ],
+    }],
+}
diff --git a/src/third_party/angle/src/third_party/libXNVCtrl/nv_control.h b/src/third_party/angle/src/third_party/libXNVCtrl/nv_control.h
new file mode 100644
index 0000000..5023c9b
--- /dev/null
+++ b/src/third_party/angle/src/third_party/libXNVCtrl/nv_control.h
@@ -0,0 +1,652 @@
+/*
+ * Copyright (c) 2008 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *
+ * NV-CONTROL Protocol Version History
+ *
+ * 1.0 - 1.5   NVIDIA Internal development versions
+ * 1.6         Initial public version
+ * 1.7         Added QueryBinaryData request
+ * 1.8         Added TargetTypes
+ * 1.9         Added QueryTargetCount request
+ * 1.10        Fixed target type/id byte ordering for compatibility with
+ *             pre-1.8 NV-CONTROL clients
+ * 1.11        NVIDIA Internal development version
+ * 1.12        Added StringOperation request
+ * 1.13        NVIDIA Internal development version
+ * 1.14        Fixed an NV_CTRL_BINARY_DATA_MODELINES double scan modeline
+ *             reporting bug (vsyncstart, vsyncend, and vtotal were incorrectly
+ *             doubled)
+ * 1.15        Added AVAILABILITY_TARGET_ATTRIBUTE_CHANGED_EVENT
+ * 1.16        Added TARGET_STRING_ATTRIBUTE_CHANGED_EVENT
+ * 1.17        Added TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT
+ * 1.18        Updated QueryTargetCount to return a count of 0, rather than
+ *             BadMatch, if an unknown TargetType is specified
+ * 1.19        Added TargetType support for SetAttributeAndGetStatus and
+ *             SetStringAttribute requests
+ * 1.20        Added COOLER TargetType
+ * 1.21        Added initial 64-bit integer attribute support (read-only)
+ * 1.22        Added X_nvCtrlQueryValidStringAttributeValues to check
+ *             string attribute permissions.
+ * 1.23        Added SENSOR TargetType
+ * 1.24        Fixed a bug where SLI_MOSAIC_MODE_AVAILABLE attribute would
+ *             report false positives via the GPU and X screen target types
+ * 1.25        Added 3D_VISION_PRO_TRANSCEIVER TargetType
+ * 1.26        Added XNVCTRLQueryXXXAttributePermissions.
+ * 1.27        Added DISPLAY TargetType
+ * 1.28        Added NV_CTRL_CURRENT_METAMODE_ID: clients should use this
+ *             attribute to switch MetaModes, rather than pass the MetaMode ID
+ *             through the RRSetScreenConfig protocol request.
+ */
+
+#ifndef __NVCONTROL_H
+#define __NVCONTROL_H
+
+#define NV_CONTROL_ERRORS 0
+#define NV_CONTROL_EVENTS 5
+#define NV_CONTROL_NAME "NV-CONTROL"
+
+#define NV_CONTROL_MAJOR 1
+#define NV_CONTROL_MINOR 28
+
+#define X_nvCtrlQueryExtension 0
+#define X_nvCtrlIsNv 1
+#define X_nvCtrlQueryAttribute 2
+#define X_nvCtrlSetAttribute 3
+#define X_nvCtrlQueryStringAttribute 4
+#define X_nvCtrlQueryValidAttributeValues 5
+#define X_nvCtrlSelectNotify 6
+#define X_nvCtrlSetGvoColorConversionDeprecated 7
+#define X_nvCtrlQueryGvoColorConversionDeprecated 8
+#define X_nvCtrlSetStringAttribute 9
+/* STUB X_nvCtrlQueryDDCCILutSize                   10 */
+/* STUB X_nvCtrlQueryDDCCISinglePointLutOperation   11 */
+/* STUB X_nvCtrlSetDDCCISinglePointLutOperation     12 */
+/* STUB X_nvCtrlQueryDDCCIBlockLutOperation         13 */
+/* STUB X_nvCtrlSetDDCCIBlockLutOperation           14 */
+/* STUB X_nvCtrlSetDDCCIRemoteProcedureCall         15 */
+/* STUB X_nvCtrlQueryDDCCIDisplayControllerType     16 */
+/* STUB X_nvCtrlQueryDDCCICapabilities              17 */
+/* STUB X_nvCtrlQueryDDCCITimingReport              18 */
+#define X_nvCtrlSetAttributeAndGetStatus 19
+#define X_nvCtrlQueryBinaryData 20
+#define X_nvCtrlSetGvoColorConversion 21
+#define X_nvCtrlQueryGvoColorConversion 22
+#define X_nvCtrlSelectTargetNotify 23
+#define X_nvCtrlQueryTargetCount 24
+#define X_nvCtrlStringOperation 25
+#define X_nvCtrlQueryValidAttributeValues64 26
+#define X_nvCtrlQueryAttribute64 27
+#define X_nvCtrlQueryValidStringAttributeValues 28
+#define X_nvCtrlQueryAttributePermissions 29
+#define X_nvCtrlQueryStringAttributePermissions 30
+#define X_nvCtrlQueryBinaryDataAttributePermissions 31
+#define X_nvCtrlQueryStringOperationAttributePermissions 32
+
+#define X_nvCtrlLastRequest (X_nvCtrlQueryStringOperationAttributePermissions + 1)
+
+/* Define 32 bit floats */
+typedef float FLOAT32;
+#ifndef F32
+#define F32
+#endif
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+} xnvCtrlQueryExtensionReq;
+#define sz_xnvCtrlQueryExtensionReq 4
+
+typedef struct
+{
+    BYTE type; /* X_Reply */
+    CARD8 padb1;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD16 major B16;
+    CARD16 minor B16;
+    CARD32 padl4 B32;
+    CARD32 padl5 B32;
+    CARD32 padl6 B32;
+    CARD32 padl7 B32;
+    CARD32 padl8 B32;
+} xnvCtrlQueryExtensionReply;
+#define sz_xnvCtrlQueryExtensionReply 32
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD32 screen B32;
+} xnvCtrlIsNvReq;
+#define sz_xnvCtrlIsNvReq 8
+
+typedef struct
+{
+    BYTE type; /* X_Reply */
+    CARD8 padb1;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 isnv B32;
+    CARD32 padl4 B32;
+    CARD32 padl5 B32;
+    CARD32 padl6 B32;
+    CARD32 padl7 B32;
+    CARD32 padl8 B32;
+} xnvCtrlIsNvReply;
+#define sz_xnvCtrlIsNvReply 32
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD32 target_type B32;
+} xnvCtrlQueryTargetCountReq;
+#define sz_xnvCtrlQueryTargetCountReq 8
+
+typedef struct
+{
+    BYTE type; /* X_Reply */
+    CARD8 padb1;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 count B32;
+    CARD32 padl4 B32;
+    CARD32 padl5 B32;
+    CARD32 padl6 B32;
+    CARD32 padl7 B32;
+    CARD32 padl8 B32;
+} xnvCtrlQueryTargetCountReply;
+#define sz_xnvCtrlQueryTargetCountReply 32
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD16 target_id B16;   /* X screen number or GPU number */
+    CARD16 target_type B16; /* X screen or GPU */
+    CARD32 display_mask B32;
+    CARD32 attribute B32;
+} xnvCtrlQueryAttributeReq;
+#define sz_xnvCtrlQueryAttributeReq 16
+
+typedef struct
+{
+    BYTE type;
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 flags B32;
+    INT32 value B32;
+    CARD32 pad4 B32;
+    CARD32 pad5 B32;
+    CARD32 pad6 B32;
+    CARD32 pad7 B32;
+} xnvCtrlQueryAttributeReply;
+#define sz_xnvCtrlQueryAttributeReply 32
+
+typedef struct
+{
+    BYTE type;
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 flags B32;
+    CARD32 pad3 B32;
+    int64_t value_64;
+    CARD32 pad6 B32;
+    CARD32 pad7 B32;
+} xnvCtrlQueryAttribute64Reply;
+#define sz_xnvCtrlQueryAttribute64Reply 32
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD16 target_id B16;
+    CARD16 target_type B16;
+    CARD32 display_mask B32;
+    CARD32 attribute B32;
+    INT32 value B32;
+} xnvCtrlSetAttributeReq;
+#define sz_xnvCtrlSetAttributeReq 20
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD16 target_id B16;
+    CARD16 target_type B16;
+    CARD32 display_mask B32;
+    CARD32 attribute B32;
+    INT32 value B32;
+} xnvCtrlSetAttributeAndGetStatusReq;
+#define sz_xnvCtrlSetAttributeAndGetStatusReq 20
+
+typedef struct
+{
+    BYTE type;
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 flags B32;
+    CARD32 pad3 B32;
+    CARD32 pad4 B32;
+    CARD32 pad5 B32;
+    CARD32 pad6 B32;
+    CARD32 pad7 B32;
+} xnvCtrlSetAttributeAndGetStatusReply;
+#define sz_xnvCtrlSetAttributeAndGetStatusReply 32
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD16 target_id B16;   /* X screen number or GPU number */
+    CARD16 target_type B16; /* X screen or GPU */
+    CARD32 display_mask B32;
+    CARD32 attribute B32;
+} xnvCtrlQueryStringAttributeReq;
+#define sz_xnvCtrlQueryStringAttributeReq 16
+
+typedef struct
+{
+    BYTE type;
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 flags B32;
+    CARD32 n B32; /* Length of string */
+    CARD32 pad4 B32;
+    CARD32 pad5 B32;
+    CARD32 pad6 B32;
+    CARD32 pad7 B32;
+} xnvCtrlQueryStringAttributeReply;
+#define sz_xnvCtrlQueryStringAttributeReply 32
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD16 target_id B16;
+    CARD16 target_type B16;
+    CARD32 display_mask B32;
+    CARD32 attribute B32;
+    CARD32 num_bytes B32;
+} xnvCtrlSetStringAttributeReq;
+#define sz_xnvCtrlSetStringAttributeReq 20
+
+typedef struct
+{
+    BYTE type;
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 flags B32;
+    CARD32 pad3 B32;
+    CARD32 pad4 B32;
+    CARD32 pad5 B32;
+    CARD32 pad6 B32;
+    CARD32 pad7 B32;
+} xnvCtrlSetStringAttributeReply;
+#define sz_xnvCtrlSetStringAttributeReply 32
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD16 target_id B16;   /* X screen number or GPU number */
+    CARD16 target_type B16; /* X screen or GPU */
+    CARD32 display_mask B32;
+    CARD32 attribute B32;
+} xnvCtrlQueryValidAttributeValuesReq;
+#define sz_xnvCtrlQueryValidAttributeValuesReq 16
+
+typedef struct
+{
+    BYTE type;
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 flags B32;
+    INT32 attr_type B32;
+    INT32 min B32;
+    INT32 max B32;
+    CARD32 bits B32;
+    CARD32 perms B32;
+} xnvCtrlQueryValidAttributeValuesReply;
+#define sz_xnvCtrlQueryValidAttributeValuesReply 32
+
+typedef struct
+{
+    BYTE type;
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 flags B32;
+    INT32 attr_type B32;
+    int64_t min_64;
+    int64_t max_64;
+    CARD64 bits_64;
+    CARD32 perms B32;
+    CARD32 pad1 B32;
+} xnvCtrlQueryValidAttributeValues64Reply;
+#define sz_xnvCtrlQueryValidAttributeValues64Reply 48
+#define sz_xnvCtrlQueryValidAttributeValues64Reply_extra ((48 - 32) >> 2)
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD32 attribute B32;
+} xnvCtrlQueryAttributePermissionsReq;
+#define sz_xnvCtrlQueryAttributePermissionsReq 8
+
+typedef struct
+{
+    BYTE type;
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 flags B32;
+    INT32 attr_type B32;
+    CARD32 perms B32;
+    CARD32 pad5 B32;
+    CARD32 pad6 B32;
+    CARD32 pad7 B32;
+    CARD32 pad8 B32;
+} xnvCtrlQueryAttributePermissionsReply;
+#define sz_xnvCtrlQueryAttributePermissionsReply 32
+
+/* Set GVO Color Conversion request (deprecated) */
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD32 screen B32;
+    FLOAT32 row1_col1 F32;
+    FLOAT32 row1_col2 F32;
+    FLOAT32 row1_col3 F32;
+    FLOAT32 row1_col4 F32;
+    FLOAT32 row2_col1 F32;
+    FLOAT32 row2_col2 F32;
+    FLOAT32 row2_col3 F32;
+    FLOAT32 row2_col4 F32;
+    FLOAT32 row3_col1 F32;
+    FLOAT32 row3_col2 F32;
+    FLOAT32 row3_col3 F32;
+    FLOAT32 row3_col4 F32;
+} xnvCtrlSetGvoColorConversionDeprecatedReq;
+#define sz_xnvCtrlSetGvoColorConversionDeprecatedReq 56
+
+/* Query GVO Color Conversion request (deprecated) */
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD32 screen B32;
+} xnvCtrlQueryGvoColorConversionDeprecatedReq;
+#define sz_xnvCtrlQueryGvoColorConversionDeprecatedReq 8
+
+/* Query GVO Color Conversion reply (deprecated) */
+typedef struct
+{
+    BYTE type; /* X_Reply */
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 pad3 B32;
+    CARD32 pad4 B32;
+    CARD32 pad5 B32;
+    CARD32 pad6 B32;
+    CARD32 pad7 B32;
+    CARD32 pad8 B32;
+} xnvCtrlQueryGvoColorConversionDeprecatedReply;
+#define sz_xnvCtrlQueryGvoColorConversionDeprecatedReply 32
+
+/* Set GVO Color Conversion request */
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD32 screen B32;
+
+    FLOAT32 cscMatrix_y_r F32;
+    FLOAT32 cscMatrix_y_g F32;
+    FLOAT32 cscMatrix_y_b F32;
+
+    FLOAT32 cscMatrix_cr_r F32;
+    FLOAT32 cscMatrix_cr_g F32;
+    FLOAT32 cscMatrix_cr_b F32;
+
+    FLOAT32 cscMatrix_cb_r F32;
+    FLOAT32 cscMatrix_cb_g F32;
+    FLOAT32 cscMatrix_cb_b F32;
+
+    FLOAT32 cscOffset_y F32;
+    FLOAT32 cscOffset_cr F32;
+    FLOAT32 cscOffset_cb F32;
+
+    FLOAT32 cscScale_y F32;
+    FLOAT32 cscScale_cr F32;
+    FLOAT32 cscScale_cb F32;
+
+} xnvCtrlSetGvoColorConversionReq;
+#define sz_xnvCtrlSetGvoColorConversionReq 68
+
+/* Query GVO Color Conversion request */
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD32 screen B32;
+} xnvCtrlQueryGvoColorConversionReq;
+#define sz_xnvCtrlQueryGvoColorConversionReq 8
+
+/* Query GVO Color Conversion reply */
+typedef struct
+{
+    BYTE type; /* X_Reply */
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 pad3 B32;
+    CARD32 pad4 B32;
+    CARD32 pad5 B32;
+    CARD32 pad6 B32;
+    CARD32 pad7 B32;
+    CARD32 pad8 B32;
+} xnvCtrlQueryGvoColorConversionReply;
+#define sz_xnvCtrlQueryGvoColorConversionReply 32
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD16 target_id B16;   /* X screen number or GPU number */
+    CARD16 target_type B16; /* X screen or GPU */
+    CARD32 display_mask B32;
+    CARD32 attribute B32;
+} xnvCtrlQueryBinaryDataReq;
+#define sz_xnvCtrlQueryBinaryDataReq 16
+
+typedef struct
+{
+    BYTE type;
+    BYTE pad0;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 flags B32;
+    CARD32 n B32;
+    CARD32 pad4 B32;
+    CARD32 pad5 B32;
+    CARD32 pad6 B32;
+    CARD32 pad7 B32;
+} xnvCtrlQueryBinaryDataReply;
+#define sz_xnvCtrlQueryBinaryDataReply 32
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD32 screen B32;
+    CARD16 notifyType B16;
+    CARD16 onoff B16;
+} xnvCtrlSelectNotifyReq;
+#define sz_xnvCtrlSelectNotifyReq 12
+
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD16 target_id B16;   /* X screen number or GPU number */
+    CARD16 target_type B16; /* X screen or GPU */
+    CARD32 display_mask B32;
+    CARD32 attribute B32;
+    CARD32 num_bytes B32; /* Length of string */
+} xnvCtrlStringOperationReq;
+#define sz_xnvCtrlStringOperationReq 20
+
+typedef struct
+{
+    BYTE type; /* X_Reply */
+    CARD8 padb1;
+    CARD16 sequenceNumber B16;
+    CARD32 length B32;
+    CARD32 ret B32;
+    CARD32 num_bytes B32; /* Length of string */
+    CARD32 padl4 B32;
+    CARD32 padl5 B32;
+    CARD32 padl6 B32;
+    CARD32 padl7 B32;
+} xnvCtrlStringOperationReply;
+#define sz_xnvCtrlStringOperationReply 32
+
+typedef struct
+{
+    union
+    {
+        struct
+        {
+            BYTE type;
+            BYTE detail;
+            CARD16 sequenceNumber B16;
+        } u;
+        struct
+        {
+            BYTE type;
+            BYTE detail;
+            CARD16 sequenceNumber B16;
+            CARD32 time B32;
+            CARD32 screen B32;
+            CARD32 display_mask B32;
+            CARD32 attribute B32;
+            CARD32 value B32;
+            CARD32 pad0 B32;
+            CARD32 pad1 B32;
+        } attribute_changed;
+    } u;
+} xnvctrlEvent;
+
+/*
+ * Leave target_type before target_id for the
+ * xnvCtrlSelectTargetNotifyReq and xnvctrlEventTarget
+ * structures, even though other request protocol structures
+ * store target_id in the bottom 16-bits of the second DWORD of the
+ * structures.  The event-related structures were added in version
+ * 1.8, and so there is no prior version with which to maintain
+ * compatibility.
+ */
+typedef struct
+{
+    CARD8 reqType;
+    CARD8 nvReqType;
+    CARD16 length B16;
+    CARD16 target_type B16; /* Don't swap these */
+    CARD16 target_id B16;
+    CARD16 notifyType B16;
+    CARD16 onoff B16;
+} xnvCtrlSelectTargetNotifyReq;
+#define sz_xnvCtrlSelectTargetNotifyReq 12
+
+typedef struct
+{
+    union
+    {
+        struct
+        {
+            BYTE type;
+            BYTE detail;
+            CARD16 sequenceNumber B16;
+        } u;
+        struct
+        {
+            BYTE type;
+            BYTE detail;
+            CARD16 sequenceNumber B16;
+            CARD32 time B32;
+            CARD16 target_type B16; /* Don't swap these */
+            CARD16 target_id B16;
+            CARD32 display_mask B32;
+            CARD32 attribute B32;
+            CARD32 value B32;
+            CARD32 pad0 B32;
+            CARD32 pad1 B32;
+        } attribute_changed;
+        struct
+        {
+            BYTE type;
+            BYTE detail;
+            CARD16 sequenceNumber B16;
+            CARD32 time B32;
+            CARD16 target_type B16; /* Don't swap these */
+            CARD16 target_id B16;
+            CARD32 display_mask B32;
+            CARD32 attribute B32;
+            CARD32 value B32;
+            CARD8 availability;
+            CARD8 pad0;
+            CARD16 pad1 B16;
+            CARD32 pad2 B32;
+        } availability_changed;
+    } u;
+} xnvctrlEventTarget;
+
+#endif /* __NVCONTROL_H */
diff --git a/src/third_party/angle/src/third_party/murmurhash/MurmurHash3.cpp b/src/third_party/angle/src/third_party/murmurhash/MurmurHash3.cpp
index 94a18a5..aa7982d 100644
--- a/src/third_party/angle/src/third_party/murmurhash/MurmurHash3.cpp
+++ b/src/third_party/angle/src/third_party/murmurhash/MurmurHash3.cpp
@@ -1,334 +1,335 @@
-//-----------------------------------------------------------------------------

-// MurmurHash3 was written by Austin Appleby, and is placed in the public

-// domain. The author hereby disclaims copyright to this source code.

-

-// Note - The x86 and x64 versions do _not_ produce the same results, as the

-// algorithms are optimized for their respective platforms. You can still

-// compile and run any of them on any platform, but your performance with the

-// non-native version will be less than optimal.

-

-#include "MurmurHash3.h"

-

-//-----------------------------------------------------------------------------

-// Platform-specific functions and macros

-

-// Microsoft Visual Studio

-

-#if defined(_MSC_VER)

-

-#define FORCE_INLINE	__forceinline

-

-#include <stdlib.h>

-

-#define ROTL32(x,y)	_rotl(x,y)

-#define ROTL64(x,y)	_rotl64(x,y)

-

-#define BIG_CONSTANT(x) (x)

-

-// Other compilers

-

-#else	// defined(_MSC_VER)

-

-#define	FORCE_INLINE __attribute__((always_inline))

-

-inline uint32_t rotl32 ( uint32_t x, int8_t r )

-{

-  return (x << r) | (x >> (32 - r));

-}

-

-inline uint64_t rotl64 ( uint64_t x, int8_t r )

-{

-  return (x << r) | (x >> (64 - r));

-}

-

-#define	ROTL32(x,y)	rotl32(x,y)

-#define ROTL64(x,y)	rotl64(x,y)

-

-#define BIG_CONSTANT(x) (x##LLU)

-

-#endif // !defined(_MSC_VER)

-

-//-----------------------------------------------------------------------------

-// Block read - if your platform needs to do endian-swapping or can only

-// handle aligned reads, do the conversion here

-

-FORCE_INLINE uint32_t getblock ( const uint32_t * p, int i )

-{

-  return p[i];

-}

-

-FORCE_INLINE uint64_t getblock ( const uint64_t * p, int i )

-{

-  return p[i];

-}

-

-//-----------------------------------------------------------------------------

-// Finalization mix - force all bits of a hash block to avalanche

-

-FORCE_INLINE uint32_t fmix ( uint32_t h )

-{

-  h ^= h >> 16;

-  h *= 0x85ebca6b;

-  h ^= h >> 13;

-  h *= 0xc2b2ae35;

-  h ^= h >> 16;

-

-  return h;

-}

-

-//----------

-

-FORCE_INLINE uint64_t fmix ( uint64_t k )

-{

-  k ^= k >> 33;

-  k *= BIG_CONSTANT(0xff51afd7ed558ccd);

-  k ^= k >> 33;

-  k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);

-  k ^= k >> 33;

-

-  return k;

-}

-

-//-----------------------------------------------------------------------------

-

-void MurmurHash3_x86_32 ( const void * key, int len,

-                          uint32_t seed, void * out )

-{

-  const uint8_t * data = (const uint8_t*)key;

-  const int nblocks = len / 4;

-

-  uint32_t h1 = seed;

-

-  const uint32_t c1 = 0xcc9e2d51;

-  const uint32_t c2 = 0x1b873593;

-

-  //----------

-  // body

-

-  const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);

-

-  for(int i = -nblocks; i; i++)

-  {

-    uint32_t k1 = getblock(blocks,i);

-

-    k1 *= c1;

-    k1 = ROTL32(k1,15);

-    k1 *= c2;

-    

-    h1 ^= k1;

-    h1 = ROTL32(h1,13); 

-    h1 = h1*5+0xe6546b64;

-  }

-

-  //----------

-  // tail

-

-  const uint8_t * tail = (const uint8_t*)(data + nblocks*4);

-

-  uint32_t k1 = 0;

-

-  switch(len & 3)

-  {

-  case 3: k1 ^= tail[2] << 16;

-  case 2: k1 ^= tail[1] << 8;

-  case 1: k1 ^= tail[0];

-          k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;

-  };

-

-  //----------

-  // finalization

-

-  h1 ^= len;

-

-  h1 = fmix(h1);

-

-  *(uint32_t*)out = h1;

-} 

-

-//-----------------------------------------------------------------------------

-

-void MurmurHash3_x86_128 ( const void * key, const int len,

-                           uint32_t seed, void * out )

-{

-  const uint8_t * data = (const uint8_t*)key;

-  const int nblocks = len / 16;

-

-  uint32_t h1 = seed;

-  uint32_t h2 = seed;

-  uint32_t h3 = seed;

-  uint32_t h4 = seed;

-

-  const uint32_t c1 = 0x239b961b; 

-  const uint32_t c2 = 0xab0e9789;

-  const uint32_t c3 = 0x38b34ae5; 

-  const uint32_t c4 = 0xa1e38b93;

-

-  //----------

-  // body

-

-  const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);

-

-  for(int i = -nblocks; i; i++)

-  {

-    uint32_t k1 = getblock(blocks,i*4+0);

-    uint32_t k2 = getblock(blocks,i*4+1);

-    uint32_t k3 = getblock(blocks,i*4+2);

-    uint32_t k4 = getblock(blocks,i*4+3);

-

-    k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;

-

-    h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;

-

-    k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;

-

-    h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;

-

-    k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;

-

-    h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;

-

-    k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;

-

-    h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;

-  }

-

-  //----------

-  // tail

-

-  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);

-

-  uint32_t k1 = 0;

-  uint32_t k2 = 0;

-  uint32_t k3 = 0;

-  uint32_t k4 = 0;

-

-  switch(len & 15)

-  {

-  case 15: k4 ^= tail[14] << 16;

-  case 14: k4 ^= tail[13] << 8;

-  case 13: k4 ^= tail[12] << 0;

-           k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;

-

-  case 12: k3 ^= tail[11] << 24;

-  case 11: k3 ^= tail[10] << 16;

-  case 10: k3 ^= tail[ 9] << 8;

-  case  9: k3 ^= tail[ 8] << 0;

-           k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;

-

-  case  8: k2 ^= tail[ 7] << 24;

-  case  7: k2 ^= tail[ 6] << 16;

-  case  6: k2 ^= tail[ 5] << 8;

-  case  5: k2 ^= tail[ 4] << 0;

-           k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;

-

-  case  4: k1 ^= tail[ 3] << 24;

-  case  3: k1 ^= tail[ 2] << 16;

-  case  2: k1 ^= tail[ 1] << 8;

-  case  1: k1 ^= tail[ 0] << 0;

-           k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;

-  };

-

-  //----------

-  // finalization

-

-  h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;

-

-  h1 += h2; h1 += h3; h1 += h4;

-  h2 += h1; h3 += h1; h4 += h1;

-

-  h1 = fmix(h1);

-  h2 = fmix(h2);

-  h3 = fmix(h3);

-  h4 = fmix(h4);

-

-  h1 += h2; h1 += h3; h1 += h4;

-  h2 += h1; h3 += h1; h4 += h1;

-

-  ((uint32_t*)out)[0] = h1;

-  ((uint32_t*)out)[1] = h2;

-  ((uint32_t*)out)[2] = h3;

-  ((uint32_t*)out)[3] = h4;

-}

-

-//-----------------------------------------------------------------------------

-

-void MurmurHash3_x64_128 ( const void * key, const int len,

-                           const uint32_t seed, void * out )

-{

-  const uint8_t * data = (const uint8_t*)key;

-  const int nblocks = len / 16;

-

-  uint64_t h1 = seed;

-  uint64_t h2 = seed;

-

-  const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);

-  const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);

-

-  //----------

-  // body

-

-  const uint64_t * blocks = (const uint64_t *)(data);

-

-  for(int i = 0; i < nblocks; i++)

-  {

-    uint64_t k1 = getblock(blocks,i*2+0);

-    uint64_t k2 = getblock(blocks,i*2+1);

-

-    k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;

-

-    h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;

-

-    k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;

-

-    h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;

-  }

-

-  //----------

-  // tail

-

-  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);

-

-  uint64_t k1 = 0;

-  uint64_t k2 = 0;

-

-  switch(len & 15)

-  {

-  case 15: k2 ^= uint64_t(tail[14]) << 48;

-  case 14: k2 ^= uint64_t(tail[13]) << 40;

-  case 13: k2 ^= uint64_t(tail[12]) << 32;

-  case 12: k2 ^= uint64_t(tail[11]) << 24;

-  case 11: k2 ^= uint64_t(tail[10]) << 16;

-  case 10: k2 ^= uint64_t(tail[ 9]) << 8;

-  case  9: k2 ^= uint64_t(tail[ 8]) << 0;

-           k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;

-

-  case  8: k1 ^= uint64_t(tail[ 7]) << 56;

-  case  7: k1 ^= uint64_t(tail[ 6]) << 48;

-  case  6: k1 ^= uint64_t(tail[ 5]) << 40;

-  case  5: k1 ^= uint64_t(tail[ 4]) << 32;

-  case  4: k1 ^= uint64_t(tail[ 3]) << 24;

-  case  3: k1 ^= uint64_t(tail[ 2]) << 16;

-  case  2: k1 ^= uint64_t(tail[ 1]) << 8;

-  case  1: k1 ^= uint64_t(tail[ 0]) << 0;

-           k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;

-  };

-

-  //----------

-  // finalization

-

-  h1 ^= len; h2 ^= len;

-

-  h1 += h2;

-  h2 += h1;

-

-  h1 = fmix(h1);

-  h2 = fmix(h2);

-

-  h1 += h2;

-  h2 += h1;

-

-  ((uint64_t*)out)[0] = h1;

-  ((uint64_t*)out)[1] = h2;

-}

-

-//-----------------------------------------------------------------------------

+//-----------------------------------------------------------------------------
+// MurmurHash3 was written by Austin Appleby, and is placed in the public
+// domain. The author hereby disclaims copyright to this source code.
+
+// Note - The x86 and x64 versions do _not_ produce the same results, as the
+// algorithms are optimized for their respective platforms. You can still
+// compile and run any of them on any platform, but your performance with the
+// non-native version will be less than optimal.
+
+#include "MurmurHash3.h"
+
+//-----------------------------------------------------------------------------
+// Platform-specific functions and macros
+
+// Microsoft Visual Studio
+
+#if defined(_MSC_VER)
+
+#define FORCE_INLINE	__forceinline
+
+#include <stdlib.h>
+
+#define ROTL32(x,y)	_rotl(x,y)
+#define ROTL64(x,y)	_rotl64(x,y)
+
+#define BIG_CONSTANT(x) (x)
+
+// Other compilers
+
+#else	// defined(_MSC_VER)
+
+#define	FORCE_INLINE inline __attribute__((always_inline))
+
+inline uint32_t rotl32 ( uint32_t x, int8_t r )
+{
+  return (x << r) | (x >> (32 - r));
+}
+
+inline uint64_t rotl64 ( uint64_t x, int8_t r )
+{
+  return (x << r) | (x >> (64 - r));
+}
+
+#define	ROTL32(x,y)	rotl32(x,y)
+#define ROTL64(x,y)	rotl64(x,y)
+
+#define BIG_CONSTANT(x) (x##LLU)
+
+#endif // !defined(_MSC_VER)
+
+//-----------------------------------------------------------------------------
+// Block read - if your platform needs to do endian-swapping or can only
+// handle aligned reads, do the conversion here
+
+FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i )
+{
+  return p[i];
+}
+
+FORCE_INLINE uint64_t getblock64 ( const uint64_t * p, int i )
+{
+  return p[i];
+}
+
+//-----------------------------------------------------------------------------
+// Finalization mix - force all bits of a hash block to avalanche
+
+FORCE_INLINE uint32_t fmix32 ( uint32_t h )
+{
+  h ^= h >> 16;
+  h *= 0x85ebca6b;
+  h ^= h >> 13;
+  h *= 0xc2b2ae35;
+  h ^= h >> 16;
+
+  return h;
+}
+
+//----------
+
+FORCE_INLINE uint64_t fmix64 ( uint64_t k )
+{
+  k ^= k >> 33;
+  k *= BIG_CONSTANT(0xff51afd7ed558ccd);
+  k ^= k >> 33;
+  k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
+  k ^= k >> 33;
+
+  return k;
+}
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_32 ( const void * key, int len,
+                          uint32_t seed, void * out )
+{
+  const uint8_t * data = (const uint8_t*)key;
+  const int nblocks = len / 4;
+
+  uint32_t h1 = seed;
+
+  const uint32_t c1 = 0xcc9e2d51;
+  const uint32_t c2 = 0x1b873593;
+
+  //----------
+  // body
+
+  const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
+
+  for(int i = -nblocks; i; i++)
+  {
+    uint32_t k1 = getblock32(blocks,i);
+
+    k1 *= c1;
+    k1 = ROTL32(k1,15);
+    k1 *= c2;
+    
+    h1 ^= k1;
+    h1 = ROTL32(h1,13); 
+    h1 = h1*5+0xe6546b64;
+  }
+
+  //----------
+  // tail
+
+  const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
+
+  uint32_t k1 = 0;
+
+  switch(len & 3)
+  {
+  case 3: k1 ^= tail[2] << 16;
+  case 2: k1 ^= tail[1] << 8;
+  case 1: k1 ^= tail[0];
+          k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+  };
+
+  //----------
+  // finalization
+
+  h1 ^= len;
+
+  h1 = fmix32(h1);
+
+  *(uint32_t*)out = h1;
+} 
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_128 ( const void * key, const int len,
+                           uint32_t seed, void * out )
+{
+  const uint8_t * data = (const uint8_t*)key;
+  const int nblocks = len / 16;
+
+  uint32_t h1 = seed;
+  uint32_t h2 = seed;
+  uint32_t h3 = seed;
+  uint32_t h4 = seed;
+
+  const uint32_t c1 = 0x239b961b; 
+  const uint32_t c2 = 0xab0e9789;
+  const uint32_t c3 = 0x38b34ae5; 
+  const uint32_t c4 = 0xa1e38b93;
+
+  //----------
+  // body
+
+  const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
+
+  for(int i = -nblocks; i; i++)
+  {
+    uint32_t k1 = getblock32(blocks,i*4+0);
+    uint32_t k2 = getblock32(blocks,i*4+1);
+    uint32_t k3 = getblock32(blocks,i*4+2);
+    uint32_t k4 = getblock32(blocks,i*4+3);
+
+    k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+
+    h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
+
+    k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
+
+    h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
+
+    k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
+
+    h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
+
+    k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
+
+    h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
+  }
+
+  //----------
+  // tail
+
+  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
+
+  uint32_t k1 = 0;
+  uint32_t k2 = 0;
+  uint32_t k3 = 0;
+  uint32_t k4 = 0;
+
+  switch(len & 15)
+  {
+  case 15: k4 ^= tail[14] << 16;
+  case 14: k4 ^= tail[13] << 8;
+  case 13: k4 ^= tail[12] << 0;
+           k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
+
+  case 12: k3 ^= tail[11] << 24;
+  case 11: k3 ^= tail[10] << 16;
+  case 10: k3 ^= tail[ 9] << 8;
+  case  9: k3 ^= tail[ 8] << 0;
+           k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
+
+  case  8: k2 ^= tail[ 7] << 24;
+  case  7: k2 ^= tail[ 6] << 16;
+  case  6: k2 ^= tail[ 5] << 8;
+  case  5: k2 ^= tail[ 4] << 0;
+           k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
+
+  case  4: k1 ^= tail[ 3] << 24;
+  case  3: k1 ^= tail[ 2] << 16;
+  case  2: k1 ^= tail[ 1] << 8;
+  case  1: k1 ^= tail[ 0] << 0;
+           k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+  };
+
+  //----------
+  // finalization
+
+  h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
+
+  h1 += h2; h1 += h3; h1 += h4;
+  h2 += h1; h3 += h1; h4 += h1;
+
+  h1 = fmix32(h1);
+  h2 = fmix32(h2);
+  h3 = fmix32(h3);
+  h4 = fmix32(h4);
+
+  h1 += h2; h1 += h3; h1 += h4;
+  h2 += h1; h3 += h1; h4 += h1;
+
+  ((uint32_t*)out)[0] = h1;
+  ((uint32_t*)out)[1] = h2;
+  ((uint32_t*)out)[2] = h3;
+  ((uint32_t*)out)[3] = h4;
+}
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x64_128 ( const void * key, const int len,
+                           const uint32_t seed, void * out )
+{
+  const uint8_t * data = (const uint8_t*)key;
+  const int nblocks = len / 16;
+
+  uint64_t h1 = seed;
+  uint64_t h2 = seed;
+
+  const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
+  const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
+
+  //----------
+  // body
+
+  const uint64_t * blocks = (const uint64_t *)(data);
+
+  for(int i = 0; i < nblocks; i++)
+  {
+    uint64_t k1 = getblock64(blocks,i*2+0);
+    uint64_t k2 = getblock64(blocks,i*2+1);
+
+    k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
+
+    h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
+
+    k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
+
+    h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
+  }
+
+  //----------
+  // tail
+
+  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
+
+  uint64_t k1 = 0;
+  uint64_t k2 = 0;
+
+  switch(len & 15)
+  {
+  case 15: k2 ^= ((uint64_t)tail[14]) << 48;
+  case 14: k2 ^= ((uint64_t)tail[13]) << 40;
+  case 13: k2 ^= ((uint64_t)tail[12]) << 32;
+  case 12: k2 ^= ((uint64_t)tail[11]) << 24;
+  case 11: k2 ^= ((uint64_t)tail[10]) << 16;
+  case 10: k2 ^= ((uint64_t)tail[ 9]) << 8;
+  case  9: k2 ^= ((uint64_t)tail[ 8]) << 0;
+           k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
+
+  case  8: k1 ^= ((uint64_t)tail[ 7]) << 56;
+  case  7: k1 ^= ((uint64_t)tail[ 6]) << 48;
+  case  6: k1 ^= ((uint64_t)tail[ 5]) << 40;
+  case  5: k1 ^= ((uint64_t)tail[ 4]) << 32;
+  case  4: k1 ^= ((uint64_t)tail[ 3]) << 24;
+  case  3: k1 ^= ((uint64_t)tail[ 2]) << 16;
+  case  2: k1 ^= ((uint64_t)tail[ 1]) << 8;
+  case  1: k1 ^= ((uint64_t)tail[ 0]) << 0;
+           k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
+  };
+
+  //----------
+  // finalization
+
+  h1 ^= len; h2 ^= len;
+
+  h1 += h2;
+  h2 += h1;
+
+  h1 = fmix64(h1);
+  h2 = fmix64(h2);
+
+  h1 += h2;
+  h2 += h1;
+
+  ((uint64_t*)out)[0] = h1;
+  ((uint64_t*)out)[1] = h2;
+}
+
+//-----------------------------------------------------------------------------
+
diff --git a/src/third_party/angle/src/third_party/murmurhash/MurmurHash3.h b/src/third_party/angle/src/third_party/murmurhash/MurmurHash3.h
index 50acc00..e1c6d34 100644
--- a/src/third_party/angle/src/third_party/murmurhash/MurmurHash3.h
+++ b/src/third_party/angle/src/third_party/murmurhash/MurmurHash3.h
@@ -1,38 +1,37 @@
-//-----------------------------------------------------------------------------

-// MurmurHash3 was written by Austin Appleby, and is placed in the public

-// domain. The author hereby disclaims copyright to this source code.

-

-#ifndef _MURMURHASH3_H_

-#define _MURMURHASH3_H_

-

-//-----------------------------------------------------------------------------

-// Platform-specific functions and macros

-

-// Microsoft Visual Studio

-#if defined(__LB_SHELL__)

-

-// Already POSIX compliant

-

-#elif defined(_MSC_VER) 

-

-typedef unsigned char uint8_t;

-typedef unsigned long uint32_t;

-typedef unsigned __int64 uint64_t;

-

-#else	// defined(_MSC_VER)

-

-#include <stdint.h>

-

-#endif // !defined(_MSC_VER)

-

-//-----------------------------------------------------------------------------

-

-void MurmurHash3_x86_32  ( const void * key, int len, uint32_t seed, void * out );

-

-void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out );

-

-void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out );

-

-//-----------------------------------------------------------------------------

-

-#endif // _MURMURHASH3_H_
\ No newline at end of file
+//-----------------------------------------------------------------------------
+// MurmurHash3 was written by Austin Appleby, and is placed in the public
+// domain. The author hereby disclaims copyright to this source code.
+
+#ifndef _MURMURHASH3_H_
+#define _MURMURHASH3_H_
+
+//-----------------------------------------------------------------------------
+// Platform-specific functions and macros
+
+// Microsoft Visual Studio
+
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+typedef unsigned __int64 uint64_t;
+
+// Other compilers
+
+#else	// defined(_MSC_VER)
+
+#include <stdint.h>
+
+#endif // !defined(_MSC_VER)
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_32  ( const void * key, int len, uint32_t seed, void * out );
+
+void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out );
+
+void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out );
+
+//-----------------------------------------------------------------------------
+
+#endif // _MURMURHASH3_H_
diff --git a/src/third_party/angle/src/third_party/systeminfo/SystemInfo.cpp b/src/third_party/angle/src/third_party/systeminfo/SystemInfo.cpp
new file mode 100644
index 0000000..97dfcaa
--- /dev/null
+++ b/src/third_party/angle/src/third_party/systeminfo/SystemInfo.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <windows.h>
+#include "common/platform.h"
+
+#if _WIN32_WINNT_WINBLUE
+#include <versionhelpers.h>
+#endif
+
+namespace rx {
+
+#ifndef _WIN32_WINNT_WINBLUE
+static bool IsWindowsVistaOrGreater()
+{
+    OSVERSIONINFOEXW osvi = { };
+    osvi.dwOSVersionInfoSize = sizeof(osvi);
+    osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_VISTA);
+    osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_VISTA);
+    DWORDLONG condition = 0;
+    VER_SET_CONDITION(condition, VER_MAJORVERSION, VER_GREATER_EQUAL);
+    VER_SET_CONDITION(condition, VER_MINORVERSION, VER_GREATER_EQUAL);
+    return !!::VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, condition);
+}
+#endif
+
+bool isWindowsVistaOrGreater()
+{
+    static bool initialized = false;
+    static bool cachedIsWindowsVistaOrGreater;
+
+    if (!initialized) {
+        initialized = true;
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+        cachedIsWindowsVistaOrGreater = true;
+#else
+        cachedIsWindowsVistaOrGreater = IsWindowsVistaOrGreater();
+#endif
+    }
+    return cachedIsWindowsVistaOrGreater;
+}
+
+} // namespace rx
diff --git a/src/third_party/angle/src/third_party/systeminfo/SystemInfo.h b/src/third_party/angle/src/third_party/systeminfo/SystemInfo.h
new file mode 100644
index 0000000..226085f
--- /dev/null
+++ b/src/third_party/angle/src/third_party/systeminfo/SystemInfo.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_
+#define THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_
+
+namespace rx {
+
+bool isWindowsVistaOrGreater();
+
+} // namespace rx
+
+#endif // THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_
diff --git a/src/third_party/angle/src/third_party/trace_event/trace_event.h b/src/third_party/angle/src/third_party/trace_event/trace_event.h
new file mode 100644
index 0000000..bdb8804
--- /dev/null
+++ b/src/third_party/angle/src/third_party/trace_event/trace_event.h
@@ -0,0 +1,798 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Trace events are for tracking application performance and resource usage.
+// Macros are provided to track:
+//    Begin and end of function calls
+//    Counters
+//
+// Events are issued against categories. Whereas LOG's
+// categories are statically defined, TRACE categories are created
+// implicitly with a string. For example:
+//   TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
+//
+// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
+//   TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
+//   doSomethingCostly()
+//   TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
+// Note: our tools can't always determine the correct BEGIN/END pairs unless
+// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them
+// to be in separate scopes.
+//
+// A common use case is to trace entire function scopes. This
+// issues a trace BEGIN and END automatically:
+//   void doSomethingCostly() {
+//     TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
+//     ...
+//   }
+//
+// Additional parameters can be associated with an event:
+//   void doSomethingCostly2(int howMuch) {
+//     TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
+//         "howMuch", howMuch);
+//     ...
+//   }
+//
+// The trace system will automatically add to this information the
+// current process id, thread id, and a timestamp in microseconds.
+//
+// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and
+// ASYNC_END:
+//   [single threaded sender code]
+//     static int send_count = 0;
+//     ++send_count;
+//     TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
+//     Send(new MyMessage(send_count));
+//   [receive code]
+//     void OnMyMessage(send_count) {
+//       TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
+//     }
+// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
+// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can
+// be used for the ID parameter, and they will be mangled internally so that
+// the same pointer on two different processes will not match. For example:
+//   class MyTracedClass {
+//    public:
+//     MyTracedClass() {
+//       TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
+//     }
+//     ~MyTracedClass() {
+//       TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
+//     }
+//   }
+//
+// Trace event also supports counters, which is a way to track a quantity
+// as it varies over time. Counters are created with the following macro:
+//   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
+//
+// Counters are process-specific. The macro itself can be issued from any
+// thread, however.
+//
+// Sometimes, you want to track two counters at once. You can do this with two
+// counter macros:
+//   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
+//   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
+// Or you can do it with a combined macro:
+//   TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
+//       "bytesPinned", g_myCounterValue[0],
+//       "bytesAllocated", g_myCounterValue[1]);
+// This indicates to the tracing UI that these counters should be displayed
+// in a single graph, as a summed area chart.
+//
+// Since counters are in a global namespace, you may want to disembiguate with a
+// unique ID, by using the TRACE_COUNTER_ID* variations.
+//
+// By default, trace collection is compiled in, but turned off at runtime.
+// Collecting trace data is the responsibility of the embedding
+// application. In Chrome's case, navigating to about:tracing will turn on
+// tracing and display data collected across all active processes.
+//
+//
+// Memory scoping note:
+// Tracing copies the pointers, not the string content, of the strings passed
+// in for category, name, and arg_names. Thus, the following code will
+// cause problems:
+//     char* str = strdup("impprtantName");
+//     TRACE_EVENT_INSTANT0("SUBSYSTEM", str);  // BAD!
+//     free(str);                   // Trace system now has dangling pointer
+//
+// To avoid this issue with the |name| and |arg_name| parameters, use the
+// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.
+// Notes: The category must always be in a long-lived char* (i.e. static const).
+//        The |arg_values|, when used, are always deep copied with the _COPY
+//        macros.
+//
+// When are string argument values copied:
+// const char* arg_values are only referenced by default:
+//     TRACE_EVENT1("category", "name",
+//                  "arg1", "literal string is only referenced");
+// Use TRACE_STR_COPY to force copying of a const char*:
+//     TRACE_EVENT1("category", "name",
+//                  "arg1", TRACE_STR_COPY("string will be copied"));
+// std::string arg_values are always copied:
+//     TRACE_EVENT1("category", "name",
+//                  "arg1", std::string("string will be copied"));
+//
+//
+// Thread Safety:
+// A thread safe singleton and mutex are used for thread safety. Category
+// enabled flags are used to limit the performance impact when the system
+// is not enabled.
+//
+// TRACE_EVENT macros first cache a pointer to a category. The categories are
+// statically allocated and safe at all times, even after exit. Fetching a
+// category is protected by the TraceLog::lock_. Multiple threads initializing
+// the static variable is safe, as they will be serialized by the lock and
+// multiple calls will return the same pointer to the category.
+//
+// Then the category_enabled flag is checked. This is a unsigned char, and
+// not intended to be multithread safe. It optimizes access to addTraceEvent
+// which is threadsafe internally via TraceLog::lock_. The enabled flag may
+// cause some threads to incorrectly call or skip calling addTraceEvent near
+// the time of the system being enabled or disabled. This is acceptable as
+// we tolerate some data loss while the system is being enabled/disabled and
+// because addTraceEvent is threadsafe internally and checks the enabled state
+// again under lock.
+//
+// Without the use of these static category pointers and enabled flags all
+// trace points would carry a significant performance cost of aquiring a lock
+// and resolving the category.
+
+#ifndef COMMON_TRACE_EVENT_H_
+#define COMMON_TRACE_EVENT_H_
+
+#include <string>
+
+#include "common/event_tracer.h"
+
+// By default, const char* argument values are assumed to have long-lived scope
+// and will not be copied. Use this macro to force a const char* to be copied.
+#define TRACE_STR_COPY(str) \
+    WebCore::TraceEvent::TraceStringWithCopy(str)
+
+// Records a pair of begin and end events called "name" for the current
+// scope, with 0, 1 or 2 associated arguments. If the category is not
+// enabled, then this does nothing.
+// - category and name strings must have application lifetime (statics or
+//   literals). They may not include " chars.
+#define TRACE_EVENT0(category, name) \
+    INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name)
+#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val)
+#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \
+        arg2_name, arg2_val)
+
+// Records a single event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+//   literals). They may not include " chars.
+#define TRACE_EVENT_INSTANT0(category, name) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+        category, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+        arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_INSTANT0(category, name) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+        category, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+        arg2_name, arg2_val)
+
+// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+//   literals). They may not include " chars.
+#define TRACE_EVENT_BEGIN0(category, name) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+        category, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+        arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_BEGIN0(category, name) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+        category, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+        arg2_name, arg2_val)
+
+// Records a single END event for "name" immediately. If the category
+// is not enabled, then this does nothing.
+// - category and name strings must have application lifetime (statics or
+//   literals). They may not include " chars.
+#define TRACE_EVENT_END0(category, name) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+        category, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+        arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_END0(category, name) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+        category, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+        arg2_name, arg2_val)
+
+// Records the value of a counter called "name" immediately. Value
+// must be representable as a 32 bit integer.
+// - category and name strings must have application lifetime (statics or
+//   literals). They may not include " chars.
+#define TRACE_COUNTER1(category, name, value) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+        category, name, TRACE_EVENT_FLAG_NONE, \
+        "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER1(category, name, value) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+        category, name, TRACE_EVENT_FLAG_COPY, \
+        "value", static_cast<int>(value))
+
+// Records the values of a multi-parted counter called "name" immediately.
+// The UI will treat value1 and value2 as parts of a whole, displaying their
+// values as a stacked-bar chart.
+// - category and name strings must have application lifetime (statics or
+//   literals). They may not include " chars.
+#define TRACE_COUNTER2(category, name, value1_name, value1_val, \
+        value2_name, value2_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+        category, name, TRACE_EVENT_FLAG_NONE, \
+        value1_name, static_cast<int>(value1_val), \
+        value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \
+        value2_name, value2_val) \
+    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+        category, name, TRACE_EVENT_FLAG_COPY, \
+        value1_name, static_cast<int>(value1_val), \
+        value2_name, static_cast<int>(value2_val))
+
+// Records the value of a counter called "name" immediately. Value
+// must be representable as a 32 bit integer.
+// - category and name strings must have application lifetime (statics or
+//   literals). They may not include " chars.
+// - |id| is used to disambiguate counters with the same name. It must either
+//   be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
+//   will be xored with a hash of the process ID so that the same pointer on
+//   two different processes will not collide.
+#define TRACE_COUNTER_ID1(category, name, id, value) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+        category, name, id, TRACE_EVENT_FLAG_NONE, \
+        "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+        category, name, id, TRACE_EVENT_FLAG_COPY, \
+        "value", static_cast<int>(value))
+
+// Records the values of a multi-parted counter called "name" immediately.
+// The UI will treat value1 and value2 as parts of a whole, displaying their
+// values as a stacked-bar chart.
+// - category and name strings must have application lifetime (statics or
+//   literals). They may not include " chars.
+// - |id| is used to disambiguate counters with the same name. It must either
+//   be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
+//   will be xored with a hash of the process ID so that the same pointer on
+//   two different processes will not collide.
+#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
+        value2_name, value2_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+        category, name, id, TRACE_EVENT_FLAG_NONE, \
+        value1_name, static_cast<int>(value1_val), \
+        value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \
+        value2_name, value2_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+        category, name, id, TRACE_EVENT_FLAG_COPY, \
+        value1_name, static_cast<int>(value1_val), \
+        value2_name, static_cast<int>(value2_val))
+
+// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+//   literals). They may not include " chars.
+// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC
+//   events are considered to match if their category, name and id values all
+//   match. |id| must either be a pointer or an integer value up to 64 bits. If
+//   it's a pointer, the bits will be xored with a hash of the process ID so
+//   that the same pointer on two different processes will not collide.
+// An asynchronous operation can consist of multiple phases. The first phase is
+// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
+// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
+// An async operation can span threads and processes, but all events in that
+// operation must use the same |name| and |id|. Each event can have its own
+// args.
+#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+        category, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+        category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+        category, name, id, TRACE_EVENT_FLAG_NONE, \
+        arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+        category, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+        category, name, id, TRACE_EVENT_FLAG_COPY, \
+        arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+        category, name, id, TRACE_EVENT_FLAG_COPY, \
+        arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Records a single ASYNC_STEP event for |step| immediately. If the category
+// is not enabled, then this does nothing. The |name| and |id| must match the
+// ASYNC_BEGIN event above. The |step| param identifies this step within the
+// async event. This should be called at the beginning of the next phase of an
+// asynchronous operation.
+#define TRACE_EVENT_ASYNC_STEP0(category, name, id, step) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+        category, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_STEP1(category, name, id, step, \
+                                      arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+        category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
+        arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_STEP0(category, name, id, step) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+        category, name, id, TRACE_EVENT_FLAG_COPY, "step", step)
+#define TRACE_EVENT_COPY_ASYNC_STEP1(category, name, id, step, \
+        arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+        category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \
+        arg1_name, arg1_val)
+
+// Records a single ASYNC_END event for "name" immediately. If the category
+// is not enabled, then this does nothing.
+#define TRACE_EVENT_ASYNC_END0(category, name, id) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+        category, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+        category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+        category, name, id, TRACE_EVENT_FLAG_NONE, \
+        arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+        category, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+        category, name, id, TRACE_EVENT_FLAG_COPY, \
+        arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
+        arg2_name, arg2_val) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+        category, name, id, TRACE_EVENT_FLAG_COPY, \
+        arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Creates a scope of a sampling state with the given category and name (both must
+// be constant strings). These states are intended for a sampling profiler.
+// Implementation note: we store category and name together because we don't
+// want the inconsistency/expense of storing two pointers.
+// |thread_bucket| is [0..2] and is used to statically isolate samples in one
+// thread from others.
+//
+// {  // The sampling state is set within this scope.
+//    TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name");
+//    ...;
+// }
+#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
+    TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(category "\0" name);
+
+// Returns a current sampling state of the given bucket.
+// The format of the returned string is "category\0name".
+#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \
+    TraceEvent::SamplingStateScope<bucket_number>::current()
+
+// Sets a current sampling state of the given bucket.
+// |category| and |name| have to be constant strings.
+#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
+    TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name)
+
+// Sets a current sampling state of the given bucket.
+// |categoryAndName| doesn't need to be a constant string.
+// The format of the string is "category\0name".
+#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \
+    TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName)
+
+// Syntactic sugars for the sampling tracing in the main thread.
+#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \
+    TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name)
+#define TRACE_EVENT_GET_SAMPLING_STATE() \
+    TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0)
+#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \
+    TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name)
+#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \
+    TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName)
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation specific tracing API definitions.
+
+// Get a pointer to the enabled state of the given trace category. Only
+// long-lived literal strings should be given as the category name. The returned
+// pointer can be held permanently in a local static for example. If the
+// unsigned char is non-zero, tracing is enabled. If tracing is enabled,
+// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
+// between the load of the tracing state and the call to
+// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
+// for best performance when tracing is disabled.
+// const unsigned char*
+//     TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name)
+#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \
+    angle::GetTraceCategoryEnabledFlag
+
+// Add a trace event to the platform tracing system.
+// void TRACE_EVENT_API_ADD_TRACE_EVENT(
+//                    char phase,
+//                    const unsigned char* category_enabled,
+//                    const char* name,
+//                    unsigned long long id,
+//                    int num_args,
+//                    const char** arg_names,
+//                    const unsigned char* arg_types,
+//                    const unsigned long long* arg_values,
+//                    unsigned char flags)
+#define TRACE_EVENT_API_ADD_TRACE_EVENT \
+    angle::AddTraceEvent
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Implementation detail: trace event macros create temporary variables
+// to keep instrumentation overhead low. These macros give each temporary
+// variable a unique name based on the line number to prevent name collissions.
+#define INTERNAL_TRACE_EVENT_UID3(a, b) \
+    trace_event_unique_##a##b
+#define INTERNAL_TRACE_EVENT_UID2(a, b) \
+    INTERNAL_TRACE_EVENT_UID3(a, b)
+#define INTERNALTRACEEVENTUID(name_prefix) \
+    INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
+
+// Implementation detail: internal macro to create static category.
+#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \
+    static const unsigned char* INTERNALTRACEEVENTUID(catstatic) = 0; \
+    if (!INTERNALTRACEEVENTUID(catstatic)) \
+      INTERNALTRACEEVENTUID(catstatic) = \
+          TRACE_EVENT_API_GET_CATEGORY_ENABLED(category);
+
+// Implementation detail: internal macro to create static category and add
+// event if the category is enabled.
+#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
+    do { \
+        INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+        if (*INTERNALTRACEEVENTUID(catstatic)) { \
+            gl::TraceEvent::addTraceEvent( \
+                phase, INTERNALTRACEEVENTUID(catstatic), name, \
+                gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \
+        } \
+    } while (0)
+
+// Implementation detail: internal macro to create static category and add begin
+// event if the category is enabled. Also adds the end event when the scope
+// ends.
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
+    INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+    gl::TraceEvent::TraceEndOnScopeClose \
+        INTERNALTRACEEVENTUID(profileScope); \
+    if (*INTERNALTRACEEVENTUID(catstatic)) { \
+      gl::TraceEvent::addTraceEvent( \
+          TRACE_EVENT_PHASE_BEGIN, \
+          INTERNALTRACEEVENTUID(catstatic), \
+          name, gl::TraceEvent::noEventId, \
+          TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
+      INTERNALTRACEEVENTUID(profileScope).initialize( \
+          INTERNALTRACEEVENTUID(catstatic), name); \
+    }
+
+// Implementation detail: internal macro to create static category and add
+// event if the category is enabled.
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
+                                         ...) \
+    do { \
+        INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+        if (*INTERNALTRACEEVENTUID(catstatic)) { \
+            unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \
+            gl::TraceEvent::TraceID traceEventTraceID( \
+                id, &traceEventFlags); \
+            gl::TraceEvent::addTraceEvent( \
+                phase, INTERNALTRACEEVENTUID(catstatic), \
+                name, traceEventTraceID.data(), traceEventFlags, \
+                ##__VA_ARGS__); \
+        } \
+    } while (0)
+
+// Notes regarding the following definitions:
+// New values can be added and propagated to third party libraries, but existing
+// definitions must never be changed, because third party libraries may use old
+// definitions.
+
+// Phase indicates the nature of an event entry. E.g. part of a begin/end pair.
+#define TRACE_EVENT_PHASE_BEGIN    ('B')
+#define TRACE_EVENT_PHASE_END      ('E')
+#define TRACE_EVENT_PHASE_INSTANT  ('I')
+#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')
+#define TRACE_EVENT_PHASE_ASYNC_STEP  ('T')
+#define TRACE_EVENT_PHASE_ASYNC_END   ('F')
+#define TRACE_EVENT_PHASE_METADATA ('M')
+#define TRACE_EVENT_PHASE_COUNTER  ('C')
+#define TRACE_EVENT_PHASE_SAMPLE  ('P')
+
+// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
+#define TRACE_EVENT_FLAG_NONE        (static_cast<unsigned char>(0))
+#define TRACE_EVENT_FLAG_COPY        (static_cast<unsigned char>(1 << 0))
+#define TRACE_EVENT_FLAG_HAS_ID      (static_cast<unsigned char>(1 << 1))
+#define TRACE_EVENT_FLAG_MANGLE_ID   (static_cast<unsigned char>(1 << 2))
+
+// Type values for identifying types in the TraceValue union.
+#define TRACE_VALUE_TYPE_BOOL         (static_cast<unsigned char>(1))
+#define TRACE_VALUE_TYPE_UINT         (static_cast<unsigned char>(2))
+#define TRACE_VALUE_TYPE_INT          (static_cast<unsigned char>(3))
+#define TRACE_VALUE_TYPE_DOUBLE       (static_cast<unsigned char>(4))
+#define TRACE_VALUE_TYPE_POINTER      (static_cast<unsigned char>(5))
+#define TRACE_VALUE_TYPE_STRING       (static_cast<unsigned char>(6))
+#define TRACE_VALUE_TYPE_COPY_STRING  (static_cast<unsigned char>(7))
+
+
+namespace gl {
+
+namespace TraceEvent {
+
+// Specify these values when the corresponding argument of addTraceEvent is not
+// used.
+const int zeroNumArgs = 0;
+const unsigned long long noEventId = 0;
+
+// TraceID encapsulates an ID that can either be an integer or pointer. Pointers
+// are mangled with the Process ID so that they are unlikely to collide when the
+// same pointer is used on different processes.
+class TraceID {
+public:
+    explicit TraceID(const void* id, unsigned char* flags) :
+        m_data(static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(id)))
+    {
+        *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
+    }
+    explicit TraceID(unsigned long long id, unsigned char* flags) : m_data(id) { (void)flags; }
+    explicit TraceID(unsigned long id, unsigned char* flags) : m_data(id) { (void)flags; }
+    explicit TraceID(unsigned int id, unsigned char* flags) : m_data(id) { (void)flags; }
+    explicit TraceID(unsigned short id, unsigned char* flags) : m_data(id) { (void)flags; }
+    explicit TraceID(unsigned char id, unsigned char* flags) : m_data(id) { (void)flags; }
+    explicit TraceID(long long id, unsigned char* flags) :
+        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+    explicit TraceID(long id, unsigned char* flags) :
+        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+    explicit TraceID(int id, unsigned char* flags) :
+        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+    explicit TraceID(short id, unsigned char* flags) :
+        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+    explicit TraceID(signed char id, unsigned char* flags) :
+        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+
+    unsigned long long data() const { return m_data; }
+
+private:
+    unsigned long long m_data;
+};
+
+// Simple union to store various types as unsigned long long.
+union TraceValueUnion {
+    bool m_bool;
+    unsigned long long m_uint;
+    long long m_int;
+    double m_double;
+    const void* m_pointer;
+    const char* m_string;
+};
+
+// Simple container for const char* that should be copied instead of retained.
+class TraceStringWithCopy {
+public:
+    explicit TraceStringWithCopy(const char* str) : m_str(str) { }
+    operator const char* () const { return m_str; }
+private:
+    const char* m_str;
+};
+
+// Define setTraceValue for each allowed type. It stores the type and
+// value in the return arguments. This allows this API to avoid declaring any
+// structures so that it is portable to third_party libraries.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
+                                         union_member, \
+                                         value_type_id) \
+    static inline void setTraceValue(actual_type arg, \
+                                     unsigned char* type, \
+                                     unsigned long long* value) { \
+        TraceValueUnion typeValue; \
+        typeValue.union_member = arg; \
+        *type = value_type_id; \
+        *value = typeValue.m_uint; \
+    }
+// Simpler form for int types that can be safely casted.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
+                                             value_type_id) \
+    static inline void setTraceValue(actual_type arg, \
+                                     unsigned char* type, \
+                                     unsigned long long* value) { \
+        *type = value_type_id; \
+        *value = static_cast<unsigned long long>(arg); \
+    }
+
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL)
+INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer,
+                                 TRACE_VALUE_TYPE_POINTER)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string,
+                                 TRACE_VALUE_TYPE_STRING)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, m_string,
+                                 TRACE_VALUE_TYPE_COPY_STRING)
+
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
+
+static inline void setTraceValue(const std::string& arg,
+                                 unsigned char* type,
+                                 unsigned long long* value) {
+    TraceValueUnion typeValue;
+    typeValue.m_string = arg.data();
+    *type = TRACE_VALUE_TYPE_COPY_STRING;
+    *value = typeValue.m_uint;
+}
+
+// These addTraceEvent template functions are defined here instead of in the
+// macro, because the arg values could be temporary string objects. In order to
+// store pointers to the internal c_str and pass through to the tracing API, the
+// arg values must live throughout these procedures.
+
+static inline angle::TraceEventHandle addTraceEvent(char phase,
+                                                    const unsigned char *categoryEnabled,
+                                                    const char *name,
+                                                    unsigned long long id,
+                                                    unsigned char flags)
+{
+    return TRACE_EVENT_API_ADD_TRACE_EVENT(
+        phase, categoryEnabled, name, id,
+        zeroNumArgs, 0, 0, 0,
+        flags);
+}
+
+template <class ARG1_TYPE>
+static inline angle::TraceEventHandle addTraceEvent(char phase,
+                                                    const unsigned char *categoryEnabled,
+                                                    const char *name,
+                                                    unsigned long long id,
+                                                    unsigned char flags,
+                                                    const char *arg1Name,
+                                                    const ARG1_TYPE &arg1Val)
+{
+    const int numArgs = 1;
+    unsigned char argTypes[1];
+    unsigned long long argValues[1];
+    setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
+    return TRACE_EVENT_API_ADD_TRACE_EVENT(
+        phase, categoryEnabled, name, id,
+        numArgs, &arg1Name, argTypes, argValues,
+        flags);
+}
+
+template <class ARG1_TYPE, class ARG2_TYPE>
+static inline angle::TraceEventHandle addTraceEvent(char phase,
+                                                    const unsigned char *categoryEnabled,
+                                                    const char *name,
+                                                    unsigned long long id,
+                                                    unsigned char flags,
+                                                    const char *arg1Name,
+                                                    const ARG1_TYPE &arg1Val,
+                                                    const char *arg2Name,
+                                                    const ARG2_TYPE &arg2Val)
+{
+    const int numArgs = 2;
+    const char* argNames[2] = { arg1Name, arg2Name };
+    unsigned char argTypes[2];
+    unsigned long long argValues[2];
+    setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
+    setTraceValue(arg2Val, &argTypes[1], &argValues[1]);
+    return TRACE_EVENT_API_ADD_TRACE_EVENT(
+        phase, categoryEnabled, name, id,
+        numArgs, argNames, argTypes, argValues,
+        flags);
+}
+
+// Used by TRACE_EVENTx macro. Do not use directly.
+class TraceEndOnScopeClose {
+public:
+    // Note: members of m_data intentionally left uninitialized. See initialize.
+    TraceEndOnScopeClose() : m_pdata(0) { }
+    ~TraceEndOnScopeClose()
+    {
+        if (m_pdata)
+            addEventIfEnabled();
+    }
+
+    void initialize(const unsigned char* categoryEnabled,
+                    const char* name)
+    {
+        m_data.categoryEnabled = categoryEnabled;
+        m_data.name = name;
+        m_pdata = &m_data;
+    }
+
+private:
+    // Add the end event if the category is still enabled.
+    void addEventIfEnabled()
+    {
+        // Only called when m_pdata is non-null.
+        if (*m_pdata->categoryEnabled) {
+            TRACE_EVENT_API_ADD_TRACE_EVENT(
+                TRACE_EVENT_PHASE_END,
+                m_pdata->categoryEnabled,
+                m_pdata->name, noEventId,
+                zeroNumArgs, 0, 0, 0,
+                TRACE_EVENT_FLAG_NONE);
+        }
+    }
+
+    // This Data struct workaround is to avoid initializing all the members
+    // in Data during construction of this object, since this object is always
+    // constructed, even when tracing is disabled. If the members of Data were
+    // members of this class instead, compiler warnings occur about potential
+    // uninitialized accesses.
+    struct Data {
+        const unsigned char* categoryEnabled;
+        const char* name;
+    };
+    Data* m_pdata;
+    Data m_data;
+};
+
+} // namespace TraceEvent
+
+} // namespace gl
+
+#endif
diff --git a/src/third_party/angle/src/vulkan_support/BUILD.gn b/src/third_party/angle/src/vulkan_support/BUILD.gn
new file mode 100644
index 0000000..4daf4a2
--- /dev/null
+++ b/src/third_party/angle/src/vulkan_support/BUILD.gn
@@ -0,0 +1,501 @@
+# Copyright 2016 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.
+
+# TODO(jmadill): Redo the file entirely when we have standalone GN ANGLE.
+
+third_party_dir = "../../../../third_party"
+glslang_dir = "$third_party_dir/glslang-angle/src"
+spirv_headers_dir = "$third_party_dir/spirv-headers/src"
+spirv_tools_dir = "$third_party_dir/spirv-tools-angle/src"
+vulkan_layers_dir = "$third_party_dir/vulkan-validation-layers/src"
+raw_vulkan_layers_dir = rebase_path(vulkan_layers_dir)
+
+vulkan_gypi =
+    exec_script("//build/gypi_to_gn.py",
+                [
+                  rebase_path("vulkan.gypi"),
+                  "--replace=<(angle_gen_path)=$target_gen_dir/angle",
+                  "--replace=<(glslang_path)=../$glslang_dir",
+                  "--replace=<(spirv_headers_path)=../$spirv_headers_dir",
+                  "--replace=<(spirv_tools_path)=../$spirv_tools_dir",
+                  "--replace=<(vulkan_layers_path)=../$vulkan_layers_dir",
+                ],
+                "scope",
+                [ "vulkan.gypi" ])
+
+# Subdirectory to place data files (e.g. layer JSON files).
+data_dir = "angledata"
+
+vulkan_gen_json_files_outputs = [
+  "$root_out_dir/$data_dir/VkLayer_core_validation.json",
+  "$root_out_dir/$data_dir/VkLayer_object_tracker.json",
+  "$root_out_dir/$data_dir/VkLayer_parameter_validation.json",
+  "$root_out_dir/$data_dir/VkLayer_swapchain.json",
+  "$root_out_dir/$data_dir/VkLayer_threading.json",
+  "$root_out_dir/$data_dir/VkLayer_unique_objects.json",
+]
+
+vulkan_undefine_configs = []
+if (is_win) {
+  vulkan_undefine_configs += [
+    "//build/config/win:nominmax",
+    "//build/config/win:unicode",
+  ]
+}
+
+vulkan_gen_dir = "$target_gen_dir/angle/vulkan"
+raw_vulkan_gen_dir = rebase_path(vulkan_gen_dir)
+
+# Vulkan helper scripts
+# ---------------------
+
+helper_script_and_deps = [
+  [
+    "vulkan_gen_dispatch_table_helper_h",
+    "vk_dispatch_table_helper.h",
+    "dispatch_table_helper_generator.py",
+  ],
+  [
+    "vulkan_gen_enum_string_helper",
+    "vk_enum_string_helper.h",
+    "helper_file_generator.py",
+  ],
+  [
+    "vulkan_gen_layer_dispatch_table_h",
+    "vk_layer_dispatch_table.h",
+    "loader_extension_generator.py",
+  ],
+  [
+    "vulkan_gen_loader_extensions_c",
+    "vk_loader_extensions.c",
+    "loader_extension_generator.py",
+  ],
+  [
+    "vulkan_gen_loader_extensions_h",
+    "vk_loader_extensions.h",
+    "loader_extension_generator.py",
+  ],
+  [
+    "vulkan_gen_safe_struct_cpp",
+    "vk_safe_struct.cpp",
+    "helper_file_generator.py",
+  ],
+  [
+    "vulkan_gen_safe_struct_h",
+    "vk_safe_struct.h",
+    "helper_file_generator.py",
+  ],
+  [
+    "vulkan_gen_struct_size_helper_c",
+    "vk_struct_size_helper.c",
+    "helper_file_generator.py",
+  ],
+  [
+    "vulkan_gen_struct_size_helper_h",
+    "vk_struct_size_helper.h",
+    "helper_file_generator.py",
+  ],
+  [
+    "vulkan_gen_thread_check_helper",
+    "thread_check.h",
+    "threading_generator.py",
+  ],
+  [
+    "vulkan_gen_parameter_validation_helper",
+    "parameter_validation.h",
+    "parameter_validation_generator.py",
+  ],
+  [
+    "vulkan_gen_unique_objects_wrappers_helper",
+    "unique_objects_wrappers.h",
+    "unique_objects_generator.py",
+  ],
+]
+
+foreach(script_and_dep, helper_script_and_deps) {
+  target_name = script_and_dep[0]
+  file = script_and_dep[1]
+  dep = script_and_dep[2]
+  target("action", target_name) {
+    script = "$vulkan_layers_dir/scripts/lvl_genvk.py"
+    inputs = [
+      "$vulkan_layers_dir/scripts/$dep",
+      "$vulkan_layers_dir/scripts/generator.py",
+      "$vulkan_layers_dir/scripts/reg.py",
+      "$vulkan_layers_dir/scripts/vk.xml",
+    ]
+    outputs = [
+      "$vulkan_gen_dir/$file",
+    ]
+    args = [
+      "-o",
+      raw_vulkan_gen_dir,
+      "-registry",
+      "$raw_vulkan_layers_dir/scripts/vk.xml",
+      "$file",
+      "-quiet",
+    ]
+  }
+}
+
+config("vulkan_generate_helper_files_config") {
+  include_dirs = [
+    vulkan_gen_dir,
+    "$vulkan_layers_dir/include",
+  ]
+}
+
+group("vulkan_generate_helper_files") {
+  public_deps = []
+  public_configs = [ ":vulkan_generate_helper_files_config" ]
+  foreach(script_and_dep, helper_script_and_deps) {
+    target_name = script_and_dep[0]
+    public_deps += [ ":$target_name" ]
+  }
+}
+
+config("vulkan_config") {
+  if (is_win) {
+    defines = [
+      "VK_USE_PLATFORM_WIN32_KHR",
+      "VK_USE_PLATFORM_WIN32_KHX",
+    ]
+  }
+  if (is_linux) {
+    defines = [
+      "VK_USE_PLATFORM_XCB_KHR",
+      "VK_USE_PLATFORM_XCB_KHX",
+    ]
+  }
+}
+
+config("vulkan_internal_config") {
+  defines = [ "VULKAN_NON_CMAKE_BUILD" ]
+  if (is_clang || !is_win) {
+    cflags = [ "-Wno-unused-function" ]
+
+    # See https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/1649
+    # TODO(jmadill): Lift this once github issue is fixed.
+    cflags += [ "-Wno-ignored-attributes" ]
+  }
+  if (is_linux) {
+    defines += [
+      "SYSCONFDIR=\"/etc\"",
+      "FALLBACK_CONFIG_DIRS=\"/etc/xdg\"",
+      "FALLBACK_DATA_DIRS=\"/usr/local/share:/usr/share\"",
+    ]
+  }
+}
+
+# Vulkan loader
+# -------------
+
+config("vulkan_loader_config") {
+  include_dirs = rebase_path(vulkan_gypi.vulkan_loader_include_dirs, ".", "src")
+  include_dirs += [ vulkan_gen_dir ]
+  defines = [
+    "LAYERS_SOURCE_PATH=\"$data_dir\"",
+    "DEFAULT_VK_LAYERS_PATH=\".\"",
+    "API_NAME=\"Vulkan\"",
+  ]
+
+  if (is_win) {
+    cflags = [ "/wd4201" ]
+  }
+  if (is_linux) {
+    # assume secure_getenv() is available
+    defines += [ "HAVE_SECURE_GETENV" ]
+  }
+}
+
+static_library("vulkan_loader") {
+  sources = rebase_path(vulkan_gypi.vulkan_loader_sources, ".", "src")
+  if (is_win) {
+    sources += rebase_path(vulkan_gypi.vulkan_loader_win_sources, ".", "src")
+    if (!is_clang) {
+      cflags = vulkan_gypi.vulkan_loader_cflags_win
+    }
+  }
+  deps = [
+    ":vulkan_generate_helper_files",
+  ]
+  configs += [ ":vulkan_internal_config" ]
+  public_configs = [
+    ":vulkan_config",
+    ":vulkan_loader_config",
+  ]
+  configs -= vulkan_undefine_configs
+}
+
+# SPIRV-tools
+# -----------
+
+spirv_source_dir = "$spirv_tools_dir/source"
+spirv_include_dir = "$spirv_headers_dir/include/spirv"
+raw_spirv_source_dir = rebase_path(spirv_source_dir)
+raw_spirv_include_dir = rebase_path(spirv_include_dir)
+raw_spirv_headers_dir = rebase_path(spirv_headers_dir)
+
+action("spirv_tools_gen_tables_1_0") {
+  script = "$spirv_tools_dir/utils/generate_grammar_tables.py"
+  sources = [
+    "$spirv_include_dir/1.0/extinst.glsl.std.450.grammar.json",
+    "$spirv_include_dir/1.0/spirv.core.grammar.json",
+    "$spirv_source_dir/extinst-1.0.opencl.std.grammar.json",
+  ]
+  outputs = [
+    "$vulkan_gen_dir/core.insts-1.0.inc",
+    "$vulkan_gen_dir/glsl.std.450.insts-1.0.inc",
+    "$vulkan_gen_dir/opencl.std.insts-1.0.inc",
+    "$vulkan_gen_dir/operand.kinds-1.0.inc",
+  ]
+  args = [
+    "--spirv-core-grammar=$raw_spirv_include_dir/1.0/spirv.core.grammar.json",
+    "--extinst-glsl-grammar=$raw_spirv_include_dir/1.0/extinst.glsl.std.450.grammar.json",
+    "--extinst-opencl-grammar=$raw_spirv_source_dir/extinst-1.0.opencl.std.grammar.json",
+    "--core-insts-output=$raw_vulkan_gen_dir/core.insts-1.0.inc",
+    "--glsl-insts-output=$raw_vulkan_gen_dir/glsl.std.450.insts-1.0.inc",
+    "--opencl-insts-output=$raw_vulkan_gen_dir/opencl.std.insts-1.0.inc",
+    "--operand-kinds-output=$raw_vulkan_gen_dir/operand.kinds-1.0.inc",
+  ]
+}
+
+action("spirv_tools_gen_tables_1_1") {
+  script = "$spirv_tools_dir/utils/generate_grammar_tables.py"
+  sources = [
+    "$spirv_include_dir/1.1/spirv.core.grammar.json",
+  ]
+  outputs = [
+    "$vulkan_gen_dir/core.insts-1.1.inc",
+    "$vulkan_gen_dir/operand.kinds-1.1.inc",
+  ]
+  args = [
+    "--spirv-core-grammar=$raw_spirv_include_dir/1.1/spirv.core.grammar.json",
+    "--core-insts-output=$raw_vulkan_gen_dir/core.insts-1.1.inc",
+    "--operand-kinds-output=$raw_vulkan_gen_dir/operand.kinds-1.1.inc",
+  ]
+}
+
+action("spirv_tools_gen_generators_inc") {
+  script = "$spirv_tools_dir/utils/generate_registry_tables.py"
+  sources = [
+    "$spirv_headers_dir/include/spirv/spir-v.xml",
+  ]
+  outputs = [
+    "$vulkan_gen_dir/generators.inc",
+  ]
+  args = [
+    "--xml=$raw_spirv_headers_dir/include/spirv/spir-v.xml",
+    "--generator-output=$raw_vulkan_gen_dir/generators.inc",
+  ]
+}
+
+config("spirv_tools_config") {
+  include_dirs = [ "$spirv_tools_dir/include" ]
+  if (is_win) {
+    cflags = [
+      "/wd4706",
+
+      # These are triggered in higher optimization levels. Disable for now until
+      # fixes are landed upstream. See https://crbug.com/677837.
+      "/wd4701",
+      "/wd4703",
+    ]
+  }
+}
+
+static_library("spirv_tools") {
+  deps = [
+    ":spirv_tools_gen_generators_inc",
+    ":spirv_tools_gen_tables_1_0",
+    ":spirv_tools_gen_tables_1_1",
+  ]
+  include_dirs = [
+    vulkan_gen_dir,
+    "$spirv_headers_dir/include",
+    "$spirv_tools_dir/source",
+  ]
+  sources = rebase_path(vulkan_gypi.spirv_tools_sources, ".", "src")
+  public_configs = [ ":spirv_tools_config" ]
+}
+
+# glslang
+# -------
+
+config("glslang_config") {
+  include_dirs = [
+    glslang_dir,
+    "$glslang_dir/glslang/Public",
+  ]
+}
+
+config("glslang_internal_config") {
+  if (is_clang || !is_win) {
+    cflags = [
+      "-Wno-ignored-qualifiers",
+      "-Wno-reorder",
+    ]
+  }
+}
+
+static_library("glslang") {
+  sources = rebase_path(vulkan_gypi.glslang_sources, ".", "src")
+  public_configs = [ ":glslang_config" ]
+  configs += [ ":glslang_internal_config" ]
+
+  if (is_win) {
+    cflags = [
+      "/wd4100",  # Unreferenced formal parameter
+      "/wd4456",  # Declaration hides previous local declaration
+      "/wd4457",  # Declaration hides function parameter
+      "/wd4458",  # Declaration hides class member
+      "/wd4702",  # Unreachable code (from glslang_tab.cpp)
+      "/wd4718",  # Recursive call has no side effects (from PpContext.cpp)
+    ]
+
+    sources += rebase_path(vulkan_gypi.glslang_win_sources, ".", "src")
+  }
+  if (is_linux) {
+    sources += rebase_path(vulkan_gypi.glslang_unix_sources, ".", "src")
+  }
+}
+
+# The validation layers
+# ---------------------
+
+config("vulkan_layer_config") {
+  include_dirs = [ "$vulkan_layers_dir/layers" ]
+}
+
+source_set("vulkan_layer_table") {
+  configs -= vulkan_undefine_configs
+  public_deps = [
+    ":vulkan_generate_helper_files",
+  ]
+  public_configs = [
+    ":vulkan_config",
+    ":vulkan_layer_config",
+    ":vulkan_internal_config",
+  ]
+  sources = [
+    "$target_gen_dir/angle/vulkan/vk_dispatch_table_helper.h",
+    "$target_gen_dir/angle/vulkan/vk_enum_string_helper.h",
+    "$vulkan_layers_dir/layers/vk_layer_table.cpp",
+    "$vulkan_layers_dir/layers/vk_layer_table.h",
+  ]
+}
+
+layers = [
+  [
+    "core_validation",
+    vulkan_gypi.VkLayer_core_validation_sources,
+    ":vulkan_core_validation_glslang",
+  ],
+  [
+    "object_tracker",
+    vulkan_gypi.VkLayer_object_tracker_sources,
+    "",
+  ],
+  [
+    "unique_objects",
+    vulkan_gypi.VkLayer_unique_objects_sources,
+    ":vulkan_gen_unique_objects_wrappers_helper",
+  ],
+  [
+    "parameter_validation",
+    vulkan_gypi.VkLayer_parameter_validation_sources,
+    ":vulkan_gen_parameter_validation_helper",
+  ],
+  [
+    "swapchain",
+    vulkan_gypi.VkLayer_swapchain_sources,
+    "",
+  ],
+  [
+    "threading",
+    vulkan_gypi.VkLayer_threading_sources,
+    ":vulkan_gen_thread_check_helper",
+  ],
+]
+
+action("vulkan_gen_json_files") {
+  script = "$third_party_dir/angle/scripts/generate_vulkan_layers_json.py"
+  if (is_win) {
+    sources =
+        rebase_path(vulkan_gypi.vulkan_gen_json_files_sources_win, ".", "src")
+    args = [ "$raw_vulkan_layers_dir/layers/windows" ]
+  }
+  if (is_linux) {
+    sources =
+        rebase_path(vulkan_gypi.vulkan_gen_json_files_sources_linux, ".", "src")
+    args = [ "$raw_vulkan_layers_dir/layers/linux" ]
+  }
+
+  # The layer JSON files are part of the necessary data deps.
+  outputs = vulkan_gen_json_files_outputs
+  data = vulkan_gen_json_files_outputs
+  args += [ rebase_path("$root_out_dir/$data_dir") ]
+}
+
+source_set("vulkan_layer_utils") {
+  sources = rebase_path(vulkan_gypi.vulkan_layer_utils_sources, ".", "src")
+  public_configs = [
+    ":vulkan_config",
+    ":vulkan_loader_config",
+    ":vulkan_internal_config",
+  ]
+  public_deps = [
+    ":vulkan_generate_helper_files",
+  ]
+  configs -= vulkan_undefine_configs
+}
+
+config("vulkan_core_validation_config") {
+  include_dirs = [ glslang_dir ]
+}
+
+source_set("vulkan_core_validation_glslang") {
+  public_deps = [
+    ":spirv_tools",
+  ]
+  public_configs = [ ":vulkan_core_validation_config" ]
+}
+
+foreach(layer_info, layers) {
+  name = layer_info[0]
+  shared_library("VkLayer_$name") {
+    configs -= vulkan_undefine_configs
+    deps = [
+      ":vulkan_layer_table",
+      ":vulkan_layer_utils",
+    ]
+    if (layer_info[2] != "") {
+      deps += [ layer_info[2] ]
+    }
+    sources = rebase_path(layer_info[1], ".", "src")
+    if (is_win) {
+      sources += [ "$vulkan_layers_dir/layers/VKLayer_$name.def" ]
+    }
+  }
+}
+
+# Use this target to include everything ANGLE needs for Vulkan.
+group("angle_vulkan") {
+  deps = [
+    ":glslang",
+    ":vulkan_loader",
+  ]
+  data_deps = [
+    ":vulkan_gen_json_files",
+  ]
+  foreach(layer_info, layers) {
+    name = layer_info[0]
+    data_deps += [ ":VkLayer_$name" ]
+  }
+  public_configs = [
+    ":vulkan_config",
+    ":vulkan_loader_config",
+    ":glslang_config",
+  ]
+}
diff --git a/src/third_party/angle/src/vulkan_support/vulkan.gypi b/src/third_party/angle/src/vulkan_support/vulkan.gypi
new file mode 100644
index 0000000..57d77a3
--- /dev/null
+++ b/src/third_party/angle/src/vulkan_support/vulkan.gypi
@@ -0,0 +1,1352 @@
+# Copyright 2016 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.
+
+{
+    'variables':
+    {
+        'glslang_path': '../../third_party/glslang-angle/src',
+        'spirv_headers_path': '../../third_party/spirv-headers/src',
+        'spirv_tools_path': '../../third_party/spirv-tools-angle/src',
+        'vulkan_layers_path': '../../third_party/vulkan-validation-layers/src',
+        'vulkan_json': 'angledata',
+        'vulkan_loader_sources':
+        [
+            '<(vulkan_layers_path)/loader/cJSON.c',
+            '<(vulkan_layers_path)/loader/cJSON.h',
+            '<(vulkan_layers_path)/loader/debug_report.c',
+            '<(vulkan_layers_path)/loader/debug_report.h',
+            '<(vulkan_layers_path)/loader/dev_ext_trampoline.c',
+            '<(vulkan_layers_path)/loader/extension_manual.c',
+            '<(vulkan_layers_path)/loader/extension_manual.h',
+            '<(vulkan_layers_path)/loader/gpa_helper.h',
+            '<(vulkan_layers_path)/loader/loader.c',
+            '<(vulkan_layers_path)/loader/loader.h',
+            '<(vulkan_layers_path)/loader/murmurhash.c',
+            '<(vulkan_layers_path)/loader/murmurhash.h',
+            '<(vulkan_layers_path)/loader/phys_dev_ext.c',
+            '<(vulkan_layers_path)/loader/trampoline.c',
+            '<(vulkan_layers_path)/loader/vk_loader_platform.h',
+            '<(vulkan_layers_path)/loader/wsi.c',
+            '<(vulkan_layers_path)/loader/wsi.h',
+        ],
+        'vulkan_loader_win_sources':
+        [
+            '<(vulkan_layers_path)/loader/dirent_on_windows.c',
+            '<(vulkan_layers_path)/loader/dirent_on_windows.h',
+        ],
+        'vulkan_loader_include_dirs':
+        [
+            '<(vulkan_layers_path)/include',
+            '<(vulkan_layers_path)/loader',
+        ],
+        'vulkan_loader_cflags_win':
+        [
+            '/wd4054', # Type cast from function pointer
+            '/wd4055', # Type cast from data pointer
+            '/wd4100', # Unreferenced formal parameter
+            '/wd4152', # Nonstandard extension used (pointer conversion)
+            '/wd4201', # Nonstandard extension used: nameless struct/union
+            '/wd4214', # Nonstandard extension used: bit field types other than int
+            '/wd4232', # Nonstandard extension used: address of dllimport is not static
+            '/wd4305', # Type cast truncation
+            '/wd4706', # Assignment within conditional expression
+            '/wd4996', # Unsafe stdlib function
+        ],
+        'vulkan_layer_generated_files':
+        [
+            '<(angle_gen_path)/vulkan/vk_enum_string_helper.h',
+            '<(angle_gen_path)/vulkan/vk_struct_size_helper.h',
+            '<(angle_gen_path)/vulkan/vk_struct_size_helper.c',
+            '<(angle_gen_path)/vulkan/vk_safe_struct.h',
+            '<(angle_gen_path)/vulkan/vk_safe_struct.cpp',
+            '<(angle_gen_path)/vulkan/vk_layer_dispatch_table.h',
+            '<(angle_gen_path)/vulkan/vk_dispatch_table_helper.h',
+            '<(angle_gen_path)/vulkan/vk_loader_extensions.h',
+            '<(angle_gen_path)/vulkan/vk_loader_extensions.c',
+            '<@(vulkan_gen_json_files_outputs)',
+        ],
+        'glslang_sources':
+        [
+            '<(glslang_path)/glslang/GenericCodeGen/CodeGen.cpp',
+            '<(glslang_path)/glslang/GenericCodeGen/Link.cpp',
+            '<(glslang_path)/glslang/Include/arrays.h',
+            '<(glslang_path)/glslang/Include/BaseTypes.h',
+            '<(glslang_path)/glslang/Include/Common.h',
+            '<(glslang_path)/glslang/Include/ConstantUnion.h',
+            '<(glslang_path)/glslang/Include/InfoSink.h',
+            '<(glslang_path)/glslang/Include/InitializeGlobals.h',
+            '<(glslang_path)/glslang/Include/intermediate.h',
+            '<(glslang_path)/glslang/Include/PoolAlloc.h',
+            '<(glslang_path)/glslang/Include/ResourceLimits.h',
+            '<(glslang_path)/glslang/Include/revision.h',
+            '<(glslang_path)/glslang/Include/ShHandle.h',
+            '<(glslang_path)/glslang/Include/Types.h',
+            '<(glslang_path)/glslang/MachineIndependent/Constant.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/gl_types.h',
+            '<(glslang_path)/glslang/MachineIndependent/glslang.y',
+            '<(glslang_path)/glslang/MachineIndependent/glslang_tab.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/glslang_tab.cpp.h',
+            '<(glslang_path)/glslang/MachineIndependent/InfoSink.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/Initialize.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/Initialize.h',
+            '<(glslang_path)/glslang/MachineIndependent/Intermediate.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/intermOut.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/IntermTraverse.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/iomapper.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/iomapper.h',
+            '<(glslang_path)/glslang/MachineIndependent/limits.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/linkValidate.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/LiveTraverser.h',
+            '<(glslang_path)/glslang/MachineIndependent/localintermediate.h',
+            '<(glslang_path)/glslang/MachineIndependent/parseConst.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/ParseContextBase.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/ParseHelper.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/ParseHelper.h',
+            '<(glslang_path)/glslang/MachineIndependent/parseVersions.h',
+            '<(glslang_path)/glslang/MachineIndependent/PoolAlloc.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/preprocessor/Pp.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/preprocessor/PpAtom.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/preprocessor/PpContext.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/preprocessor/PpContext.h',
+            '<(glslang_path)/glslang/MachineIndependent/preprocessor/PpMemory.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/preprocessor/PpScanner.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/preprocessor/PpSymbols.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/preprocessor/PpTokens.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/preprocessor/PpTokens.h',
+            '<(glslang_path)/glslang/MachineIndependent/propagateNoContraction.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/propagateNoContraction.h',
+            '<(glslang_path)/glslang/MachineIndependent/reflection.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/reflection.h',
+            '<(glslang_path)/glslang/MachineIndependent/RemoveTree.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/RemoveTree.h',
+            '<(glslang_path)/glslang/MachineIndependent/Scan.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/Scan.h',
+            '<(glslang_path)/glslang/MachineIndependent/ScanContext.h',
+            '<(glslang_path)/glslang/MachineIndependent/ShaderLang.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/SymbolTable.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/SymbolTable.h',
+            '<(glslang_path)/glslang/MachineIndependent/Versions.cpp',
+            '<(glslang_path)/glslang/MachineIndependent/Versions.h',
+            '<(glslang_path)/glslang/OSDependent/osinclude.h',
+            '<(glslang_path)/glslang/Public/ShaderLang.h',
+            '<(glslang_path)/hlsl/hlslAttributes.cpp',
+            '<(glslang_path)/hlsl/hlslAttributes.h',
+            '<(glslang_path)/hlsl/hlslGrammar.cpp',
+            '<(glslang_path)/hlsl/hlslGrammar.h',
+            '<(glslang_path)/hlsl/hlslOpMap.cpp',
+            '<(glslang_path)/hlsl/hlslOpMap.h',
+            '<(glslang_path)/hlsl/hlslParseables.cpp',
+            '<(glslang_path)/hlsl/hlslParseables.h',
+            '<(glslang_path)/hlsl/hlslParseHelper.cpp',
+            '<(glslang_path)/hlsl/hlslParseHelper.h',
+            '<(glslang_path)/hlsl/hlslScanContext.cpp',
+            '<(glslang_path)/hlsl/hlslScanContext.h',
+            '<(glslang_path)/hlsl/hlslTokens.h',
+            '<(glslang_path)/hlsl/hlslTokenStream.cpp',
+            '<(glslang_path)/hlsl/hlslTokenStream.h',
+            '<(glslang_path)/OGLCompilersDLL/InitializeDll.cpp',
+            '<(glslang_path)/OGLCompilersDLL/InitializeDll.h',
+            '<(glslang_path)/SPIRV/bitutils.h',
+            '<(glslang_path)/SPIRV/disassemble.cpp',
+            '<(glslang_path)/SPIRV/disassemble.h',
+            '<(glslang_path)/SPIRV/doc.cpp',
+            '<(glslang_path)/SPIRV/doc.h',
+            '<(glslang_path)/SPIRV/GLSL.ext.KHR.h',
+            '<(glslang_path)/SPIRV/GLSL.std.450.h',
+            '<(glslang_path)/SPIRV/GlslangToSpv.cpp',
+            '<(glslang_path)/SPIRV/GlslangToSpv.h',
+            '<(glslang_path)/SPIRV/hex_float.h',
+            '<(glslang_path)/SPIRV/InReadableOrder.cpp',
+            '<(glslang_path)/SPIRV/Logger.cpp',
+            '<(glslang_path)/SPIRV/Logger.h',
+            '<(glslang_path)/SPIRV/spirv.hpp',
+            '<(glslang_path)/SPIRV/SpvBuilder.cpp',
+            '<(glslang_path)/SPIRV/SpvBuilder.h',
+            '<(glslang_path)/SPIRV/spvIR.h',
+            '<(glslang_path)/StandAlone/ResourceLimits.cpp',
+            '<(glslang_path)/StandAlone/ResourceLimits.h',
+        ],
+        'glslang_win_sources':
+        [
+            '<(glslang_path)/glslang/OSDependent/Windows/ossource.cpp',
+        ],
+        'glslang_unix_sources':
+        [
+            '<(glslang_path)/glslang/OSDependent/Unix/ossource.cpp',
+        ],
+        'spirv_tools_sources':
+        [
+            '<(angle_gen_path)/vulkan/core.insts-1.0.inc',
+            '<(angle_gen_path)/vulkan/core.insts-1.1.inc',
+            '<(angle_gen_path)/vulkan/generators.inc',
+            '<(angle_gen_path)/vulkan/glsl.std.450.insts-1.0.inc',
+            '<(angle_gen_path)/vulkan/opencl.std.insts-1.0.inc',
+            '<(angle_gen_path)/vulkan/operand.kinds-1.0.inc',
+            '<(angle_gen_path)/vulkan/operand.kinds-1.1.inc',
+            '<(spirv_tools_path)/source/assembly_grammar.cpp',
+            '<(spirv_tools_path)/source/assembly_grammar.h',
+            '<(spirv_tools_path)/source/binary.cpp',
+            '<(spirv_tools_path)/source/binary.h',
+            '<(spirv_tools_path)/source/diagnostic.cpp',
+            '<(spirv_tools_path)/source/diagnostic.h',
+            '<(spirv_tools_path)/source/disassemble.cpp',
+            '<(spirv_tools_path)/source/enum_set.h',
+            '<(spirv_tools_path)/source/ext_inst.cpp',
+            '<(spirv_tools_path)/source/ext_inst.h',
+            '<(spirv_tools_path)/source/instruction.h',
+            '<(spirv_tools_path)/source/libspirv.cpp',
+            '<(spirv_tools_path)/source/macro.h',
+            '<(spirv_tools_path)/source/message.cpp',
+            '<(spirv_tools_path)/source/name_mapper.cpp',
+            '<(spirv_tools_path)/source/name_mapper.h',
+            '<(spirv_tools_path)/source/opcode.cpp',
+            '<(spirv_tools_path)/source/opcode.h',
+            '<(spirv_tools_path)/source/operand.cpp',
+            '<(spirv_tools_path)/source/operand.h',
+            '<(spirv_tools_path)/source/parsed_operand.cpp',
+            '<(spirv_tools_path)/source/parsed_operand.h',
+            '<(spirv_tools_path)/source/print.cpp',
+            '<(spirv_tools_path)/source/print.h',
+            # TODO(jmadill): Determine if this is ever needed.
+            #'<(spirv_tools_path)/source/software_version.cpp',
+            '<(spirv_tools_path)/source/spirv_constant.h',
+            '<(spirv_tools_path)/source/spirv_definition.h',
+            '<(spirv_tools_path)/source/spirv_endian.cpp',
+            '<(spirv_tools_path)/source/spirv_endian.h',
+            '<(spirv_tools_path)/source/spirv_target_env.cpp',
+            '<(spirv_tools_path)/source/spirv_target_env.h',
+            '<(spirv_tools_path)/source/table.cpp',
+            '<(spirv_tools_path)/source/table.h',
+            '<(spirv_tools_path)/source/text.cpp',
+            '<(spirv_tools_path)/source/text.h',
+            '<(spirv_tools_path)/source/text_handler.cpp',
+            '<(spirv_tools_path)/source/text_handler.h',
+            '<(spirv_tools_path)/source/util/bitutils.h',
+            '<(spirv_tools_path)/source/util/hex_float.h',
+            '<(spirv_tools_path)/source/util/parse_number.cpp',
+            '<(spirv_tools_path)/source/util/parse_number.h',
+            '<(spirv_tools_path)/source/val/basic_block.cpp',
+            '<(spirv_tools_path)/source/val/construct.cpp',
+            '<(spirv_tools_path)/source/val/function.cpp',
+            '<(spirv_tools_path)/source/val/instruction.cpp',
+            '<(spirv_tools_path)/source/val/validation_state.cpp',
+            '<(spirv_tools_path)/source/validate.cpp',
+            '<(spirv_tools_path)/source/validate.h',
+            '<(spirv_tools_path)/source/validate_cfg.cpp',
+            '<(spirv_tools_path)/source/validate_datarules.cpp',
+            '<(spirv_tools_path)/source/validate_id.cpp',
+            '<(spirv_tools_path)/source/validate_instruction.cpp',
+            '<(spirv_tools_path)/source/validate_layout.cpp',
+        ],
+        'vulkan_layer_utils_sources':
+        [
+            '<(vulkan_layers_path)/layers/vk_layer_config.cpp',
+            '<(vulkan_layers_path)/layers/vk_layer_config.h',
+            '<(vulkan_layers_path)/layers/vk_layer_extension_utils.cpp',
+            '<(vulkan_layers_path)/layers/vk_layer_extension_utils.h',
+            '<(vulkan_layers_path)/layers/vk_layer_utils.cpp',
+            '<(vulkan_layers_path)/layers/vk_layer_utils.h',
+        ],
+        'vulkan_struct_wrappers_outputs':
+        [
+            '<(angle_gen_path)/vulkan/vk_safe_struct.cpp',
+            '<(angle_gen_path)/vulkan/vk_safe_struct.h',
+            '<(angle_gen_path)/vulkan/vk_struct_size_helper.c',
+            '<(angle_gen_path)/vulkan/vk_struct_size_helper.h',
+            '<(angle_gen_path)/vulkan/vk_struct_string_helper.h',
+            '<(angle_gen_path)/vulkan/vk_struct_string_helper_cpp.h',
+        ],
+        'VkLayer_core_validation_sources':
+        [
+            # This file is manually included in the layer
+            # '<(angle_gen_path)/vulkan/vk_safe_struct.cpp',
+            '<(angle_gen_path)/vulkan/vk_safe_struct.h',
+            '<(vulkan_layers_path)/layers/buffer_validation.cpp',
+            '<(vulkan_layers_path)/layers/buffer_validation.h',
+            '<(vulkan_layers_path)/layers/core_validation.cpp',
+            '<(vulkan_layers_path)/layers/core_validation.h',
+            '<(vulkan_layers_path)/layers/descriptor_sets.cpp',
+            '<(vulkan_layers_path)/layers/descriptor_sets.h',
+        ],
+        'VkLayer_swapchain_sources':
+        [
+            '<(vulkan_layers_path)/layers/swapchain.cpp',
+            '<(vulkan_layers_path)/layers/swapchain.h',
+        ],
+        'VkLayer_object_tracker_sources':
+        [
+            '<(vulkan_layers_path)/layers/object_tracker.cpp',
+            '<(vulkan_layers_path)/layers/object_tracker.h',
+        ],
+        'VkLayer_unique_objects_sources':
+        [
+            '<(angle_gen_path)/vulkan/unique_objects_wrappers.h',
+            # This file is manually included in the layer
+            # '<(angle_gen_path)/vulkan/vk_safe_struct.cpp',
+            '<(angle_gen_path)/vulkan/vk_safe_struct.h',
+            '<(vulkan_layers_path)/layers/unique_objects.cpp',
+            '<(vulkan_layers_path)/layers/unique_objects.h',
+        ],
+        'VkLayer_threading_sources':
+        [
+            '<(angle_gen_path)/vulkan/thread_check.h',
+            '<(vulkan_layers_path)/layers/threading.cpp',
+            '<(vulkan_layers_path)/layers/threading.h',
+        ],
+        'VkLayer_parameter_validation_sources':
+        [
+            '<(angle_gen_path)/vulkan/parameter_validation.h',
+            '<(vulkan_layers_path)/layers/parameter_validation.cpp',
+        ],
+        'vulkan_gen_json_files_sources_win':
+        [
+            '<(vulkan_layers_path)/layers/windows/VkLayer_core_validation.json',
+            '<(vulkan_layers_path)/layers/windows/VkLayer_object_tracker.json',
+            '<(vulkan_layers_path)/layers/windows/VkLayer_parameter_validation.json',
+            '<(vulkan_layers_path)/layers/windows/VkLayer_swapchain.json',
+            '<(vulkan_layers_path)/layers/windows/VkLayer_threading.json',
+            '<(vulkan_layers_path)/layers/windows/VkLayer_unique_objects.json',
+        ],
+        'vulkan_gen_json_files_sources_linux':
+        [
+            '<(vulkan_layers_path)/layers/linux/VkLayer_core_validation.json',
+            '<(vulkan_layers_path)/layers/linux/VkLayer_object_tracker.json',
+            '<(vulkan_layers_path)/layers/linux/VkLayer_parameter_validation.json',
+            '<(vulkan_layers_path)/layers/linux/VkLayer_swapchain.json',
+            '<(vulkan_layers_path)/layers/linux/VkLayer_threading.json',
+            '<(vulkan_layers_path)/layers/linux/VkLayer_unique_objects.json',
+        ],
+        'vulkan_gen_json_files_outputs':
+        [
+            '<(PRODUCT_DIR)/<(vulkan_json)/VkLayer_core_validation.json',
+            '<(PRODUCT_DIR)/<(vulkan_json)/VkLayer_object_tracker.json',
+            '<(PRODUCT_DIR)/<(vulkan_json)/VkLayer_parameter_validation.json',
+            '<(PRODUCT_DIR)/<(vulkan_json)/VkLayer_swapchain.json',
+            '<(PRODUCT_DIR)/<(vulkan_json)/VkLayer_threading.json',
+            '<(PRODUCT_DIR)/<(vulkan_json)/VkLayer_unique_objects.json',
+        ],
+    },
+    'conditions':
+    [
+        ['angle_enable_vulkan==1',
+        {
+            'targets':
+            [
+                {
+                    'target_name': 'glslang',
+                    'type': 'static_library',
+                    'sources':
+                    [
+                        '<@(glslang_sources)',
+                    ],
+                    'include_dirs':
+                    [
+                        '<(glslang_path)',
+                    ],
+                    'msvs_settings':
+                    {
+                        'VCCLCompilerTool':
+                        {
+                            'PreprocessorDefinitions':
+                            [
+                                '_HAS_EXCEPTIONS=0',
+                            ],
+                            'AdditionalOptions':
+                            [
+                                '/wd4100', # Unreferenced formal parameter
+                                '/wd4456', # Declaration hides previous local declaration
+                                '/wd4457', # Declaration hides function parameter
+                                '/wd4458', # Declaration hides class member
+                                '/wd4702', # Unreachable code (from glslang_tab.cpp)
+                                '/wd4718', # Recursive call has no side effects (from PpContext.cpp)
+                            ],
+                        },
+                    },
+                    'direct_dependent_settings':
+                    {
+                        'include_dirs':
+                        [
+                            '<(glslang_path)/glslang/Public',
+                            '<(glslang_path)',
+                        ],
+                    },
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<@(glslang_win_sources)',
+                            ],
+                        }],
+                        ['OS=="linux"',
+                        {
+                            'sources':
+                            [
+                                '<@(glslang_unix_sources)',
+                            ],
+                        }],
+                    ],
+                },
+
+                {
+                    'target_name': 'spirv_tools',
+                    'type': 'static_library',
+                    'sources':
+                    [
+                        '<@(spirv_tools_sources)',
+                    ],
+                    'include_dirs':
+                    [
+                        '<(angle_gen_path)/vulkan',
+                        '<(spirv_headers_path)/include',
+                        '<(spirv_tools_path)/include',
+                        '<(spirv_tools_path)/source',
+                    ],
+                    'msvs_settings':
+                    {
+                        'VCCLCompilerTool':
+                        {
+                            'PreprocessorDefinitions':
+                            [
+                                '_HAS_EXCEPTIONS=0',
+                            ],
+                            'AdditionalOptions':
+                            [
+                                '/wd4127', # Conditional expression is constant, happens in a template in hex_float.h.
+                                '/wd4706', # Assignment within conditional expression
+                                '/wd4996', # Unsafe stdlib function
+                            ],
+                        },
+                    },
+                    'actions':
+                    [
+                        {
+                            'action_name': 'spirv_tools_gen_build_tables_1_0',
+                            'message': 'generating info tables for SPIR-V 1.0 instructions and operands',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(spirv_headers_path)/include/spirv/1.0/extinst.glsl.std.450.grammar.json',
+                                '<(spirv_headers_path)/include/spirv/1.0/spirv.core.grammar.json',
+                                '<(spirv_tools_path)/source/extinst-1.0.opencl.std.grammar.json',
+                                '<(spirv_tools_path)/utils/generate_grammar_tables.py',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/core.insts-1.0.inc',
+                                '<(angle_gen_path)/vulkan/glsl.std.450.insts-1.0.inc',
+                                '<(angle_gen_path)/vulkan/opencl.std.insts-1.0.inc',
+                                '<(angle_gen_path)/vulkan/operand.kinds-1.0.inc',
+                            ],
+                            'action':
+                            [
+                                'python', '<(spirv_tools_path)/utils/generate_grammar_tables.py',
+                                '--spirv-core-grammar=<(spirv_headers_path)/include/spirv/1.0/spirv.core.grammar.json',
+                                '--extinst-glsl-grammar=<(spirv_headers_path)/include/spirv/1.0/extinst.glsl.std.450.grammar.json',
+                                '--extinst-opencl-grammar=<(spirv_tools_path)/source/extinst-1.0.opencl.std.grammar.json',
+                                '--core-insts-output=<(angle_gen_path)/vulkan/core.insts-1.0.inc',
+                                '--glsl-insts-output=<(angle_gen_path)/vulkan/glsl.std.450.insts-1.0.inc',
+                                '--opencl-insts-output=<(angle_gen_path)/vulkan/opencl.std.insts-1.0.inc',
+                                '--operand-kinds-output=<(angle_gen_path)/vulkan/operand.kinds-1.0.inc',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'spirv_tools_gen_build_tables_1_1',
+                            'message': 'generating info tables for SPIR-V 1.1 instructions and operands',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(spirv_tools_path)/utils/generate_grammar_tables.py',
+                                '<(spirv_headers_path)/include/spirv/1.1/spirv.core.grammar.json',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/core.insts-1.1.inc',
+                                '<(angle_gen_path)/vulkan/operand.kinds-1.1.inc',
+                            ],
+                            'action':
+                            [
+                                'python', '<(spirv_tools_path)/utils/generate_grammar_tables.py',
+                                '--spirv-core-grammar=<(spirv_headers_path)/include/spirv/1.1/spirv.core.grammar.json',
+                                '--core-insts-output=<(angle_gen_path)/vulkan/core.insts-1.1.inc',
+                                '--operand-kinds-output=<(angle_gen_path)/vulkan/operand.kinds-1.1.inc',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'spirv_tools_gen_generators_inc',
+                            'message': 'generating generators.inc for SPIRV-Tools',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(spirv_tools_path)/utils/generate_registry_tables.py',
+                                '<(spirv_headers_path)/include/spirv/spir-v.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/generators.inc',
+                            ],
+                            'action':
+                            [
+                                'python', '<(spirv_tools_path)/utils/generate_registry_tables.py',
+                                '--xml=<(spirv_headers_path)/include/spirv/spir-v.xml',
+                                '--generator-output=<(angle_gen_path)/vulkan/generators.inc',
+                            ],
+                        },
+                    ],
+
+                    'direct_dependent_settings':
+                    {
+                        'include_dirs':
+                        [
+                            '<(spirv_headers_path)/include',
+                            '<(spirv_tools_path)/include',
+                        ],
+                    },
+                },
+
+                {
+                    'target_name': 'vulkan_layer_utils_static',
+                    'type': 'static_library',
+                    'msvs_cygwin_shell': 0,
+                    'sources':
+                    [
+                        '<@(vulkan_layer_utils_sources)',
+                    ],
+                    'include_dirs':
+                    [
+                        '<(angle_gen_path)/vulkan',
+                        '<@(vulkan_loader_include_dirs)',
+                    ],
+                    'msvs_settings':
+                    {
+                        'VCCLCompilerTool':
+                        {
+                            'PreprocessorDefinitions':
+                            [
+                                '_HAS_EXCEPTIONS=0',
+                            ],
+                            'AdditionalOptions':
+                            [
+                                '/wd4100', # Unreferenced formal parameter
+                                '/wd4309', # Truncation of constant value
+                                '/wd4505', # Unreferenced local function has been removed
+                                '/wd4996', # Unsafe stdlib function
+                            ],
+                        },
+                    },
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'defines':
+                            [
+                                'WIN32',
+                                'WIN32_LEAN_AND_MEAN',
+                                'VK_USE_PLATFORM_WIN32_KHR',
+                                'VK_USE_PLATFORM_WIN32_KHX',
+                            ],
+                        }],
+                        ['OS=="linux"',
+                        {
+                            'defines':
+                            [
+                                'VK_USE_PLATFORM_XCB_KHR',
+                                'VK_USE_PLATFORM_XCB_KHX',
+                            ],
+                        }],
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'msvs_cygwin_shell': 0,
+                        'sources':
+                        [
+                            '<(vulkan_layers_path)/layers/vk_layer_table.cpp',
+                            '<(vulkan_layers_path)/layers/vk_layer_table.h',
+                        ],
+                        'include_dirs':
+                        [
+                            '<(angle_gen_path)/vulkan',
+                            '<(glslang_path)',
+                            '<(vulkan_layers_path)/layers',
+                            '<@(vulkan_loader_include_dirs)',
+                        ],
+                        'msvs_settings':
+                        {
+                            'VCCLCompilerTool':
+                            {
+                                'PreprocessorDefinitions':
+                                [
+                                    '_HAS_EXCEPTIONS=0',
+                                ],
+                                'AdditionalOptions':
+                                [
+                                    '/wd4100', # Unreferenced local parameter
+                                    '/wd4201', # Nonstandard extension used: nameless struct/union
+                                    '/wd4456', # declaration hides previous local declaration
+                                    '/wd4505', # Unreferenced local function has been removed
+                                    '/wd4996', # Unsafe stdlib function
+                                ],
+                            }
+                        },
+                        'conditions':
+                        [
+                            ['OS=="win"',
+                            {
+                                'defines':
+                                [
+                                    'WIN32_LEAN_AND_MEAN',
+                                    'VK_USE_PLATFORM_WIN32_KHR',
+                                    'VK_USE_PLATFORM_WIN32_KHX',
+                                ],
+                                'configurations':
+                                {
+                                    'Debug_Base':
+                                    {
+                                        'msvs_settings':
+                                        {
+                                            'VCCLCompilerTool':
+                                            {
+                                                'AdditionalOptions':
+                                                [
+                                                    '/bigobj',
+                                                ],
+                                            },
+                                        },
+                                    },
+                                },
+                            }],
+                            ['OS=="linux"',
+                            {
+                                'defines':
+                                [
+                                    'VK_USE_PLATFORM_XCB_KHR',
+                                    'VK_USE_PLATFORM_XCB_KHX',
+                                ],
+                            }],
+                        ],
+                    },
+
+                    'actions':
+                    [
+                        # Duplicate everything because of GYP limitations.
+                        {
+                            'action_name': 'vulkan_run_vk_xml_generate_vk_enum_string_helper_h',
+                            'message': 'generating vk_enum_string_helper.h',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/helper_file_generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/vk_enum_string_helper.h'
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                 '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml',
+                                'vk_enum_string_helper.h', '-quiet',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'vulkan_run_vk_xml_generate_vk_struct_size_helper_h',
+                            'message': 'generating vk_struct_size_helper.h',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/helper_file_generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/vk_struct_size_helper.h'
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                 '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml',
+                                'vk_struct_size_helper.h', '-quiet',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'vulkan_run_vk_xml_generate_vk_struct_size_helper_c',
+                            'message': 'generating vk_struct_size_helper.c',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/helper_file_generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/vk_struct_size_helper.c'
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                 '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml',
+                                'vk_struct_size_helper.c', '-quiet',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'vulkan_run_vk_xml_generate_vk_safe_struct_h',
+                            'message': 'generating vk_safe_struct.h',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/helper_file_generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/vk_safe_struct.h'
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                 '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml',
+                                'vk_safe_struct.h', '-quiet',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'vulkan_run_vk_xml_generate_vk_safe_struct_cpp',
+                            'message': 'generating vk_safe_struct.cpp',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/helper_file_generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/vk_safe_struct.cpp'
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                 '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml',
+                                'vk_safe_struct.cpp', '-quiet',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'vulkan_run_vk_xml_generate_vk_layer_dispatch_table_h',
+                            'message': 'generating vk_layer_dispatch_table.h',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/loader_extension_generator.py',
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/vk_layer_dispatch_table.h',
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py', '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml', 'vk_layer_dispatch_table.h', '-quiet',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'vulkan_run_vk_xml_generate_vk_dispatch_table_helper_h',
+                            'message': 'generating vk_dispatch_table_helper.h',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/dispatch_table_helper_generator.py',
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/vk_dispatch_table_helper.h',
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py', '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml', 'vk_dispatch_table_helper.h', '-quiet',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'vulkan_run_vk_xml_generate_vk_loader_extensions_h',
+                            'message': 'generating vk_loader_extensions.h',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/loader_extension_generator.py',
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/vk_loader_extensions.h',
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py', '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml', 'vk_loader_extensions.h', '-quiet',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'vulkan_run_vk_xml_generate_vk_loader_extensions_c',
+                            'message': 'generating vk_loader_extensions.c',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/loader_extension_generator.py',
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/vk_loader_extensions.c',
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py', '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml', 'vk_loader_extensions.c', '-quiet',
+                            ],
+                        },
+
+                        {
+                            'action_name': 'vulkan_generate_json_files',
+                            'message': 'generating Vulkan json files',
+                            'inputs':
+                            [
+                                '<(angle_path)/scripts/generate_vulkan_layers_json.py',
+                            ],
+                            'outputs':
+                            [
+                                '<@(vulkan_gen_json_files_outputs)',
+                            ],
+                            'conditions':
+                            [
+                                ['OS=="win"',
+                                {
+                                    'inputs':
+                                    [
+                                        '<@(vulkan_gen_json_files_sources_win)',
+                                    ],
+                                    'action':
+                                    [
+                                        'python', '<(angle_path)/scripts/generate_vulkan_layers_json.py',
+                                        '<(vulkan_layers_path)/layers/windows', '<(PRODUCT_DIR)/<(vulkan_json)',
+                                    ],
+                                }],
+                                ['OS=="linux"',
+                                {
+                                    'inputs':
+                                    [
+                                        '<@(vulkan_gen_json_files_sources_linux)',
+                                    ],
+                                    'action':
+                                    [
+                                        'python', '<(angle_path)/scripts/generate_vulkan_layers_json.py',
+                                        '<(vulkan_layers_path)/layers/linux', '<(PRODUCT_DIR)/<(vulkan_json)',
+                                    ],
+                                }],
+                            ],
+                        },
+                    ],
+                },
+
+                {
+                    'target_name': 'vulkan_loader',
+                    'type': 'static_library',
+                    'sources':
+                    [
+                        '<@(vulkan_loader_sources)',
+                    ],
+                    'include_dirs':
+                    [
+                        '<@(vulkan_loader_include_dirs)',
+                        '<(angle_gen_path)/vulkan',
+                    ],
+                    'defines':
+                    [
+                        'API_NAME="Vulkan"',
+                        'VULKAN_NON_CMAKE_BUILD',
+                    ],
+                    'msvs_settings':
+                    {
+                        'VCCLCompilerTool':
+                        {
+                            'AdditionalOptions':
+                            [
+                                # TODO(jmadill): Force include header on other platforms.
+                                '<@(vulkan_loader_cflags_win)',
+                                '/FIangle_loader.h'
+                            ],
+                        },
+                        'VCLinkerTool':
+                        {
+                            'AdditionalDependencies':
+                            [
+                                'shlwapi.lib',
+                            ],
+                        },
+                    },
+                    'direct_dependent_settings':
+                    {
+                        'include_dirs':
+                        [
+                            '<@(vulkan_loader_include_dirs)',
+                        ],
+                        'msvs_settings':
+                        {
+                            'VCLinkerTool':
+                            {
+                                'AdditionalDependencies':
+                                [
+                                    'shlwapi.lib',
+                                ],
+                            },
+                        },
+                        'conditions':
+                        [
+                            ['OS=="win"',
+                            {
+                                'defines':
+                                [
+                                    'VK_USE_PLATFORM_WIN32_KHR',
+                                    'VK_USE_PLATFORM_WIN32_KHX',
+                                ],
+                            }],
+                            ['OS=="linux"',
+                            {
+                                'defines':
+                                [
+                                    'VK_USE_PLATFORM_XCB_KHR',
+                                    'VK_USE_PLATFORM_XCB_KHX',
+                                ],
+                            }],
+                        ],
+                    },
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<(angle_gen_path)/vulkan/angle_loader.h',
+                                '<@(vulkan_loader_win_sources)',
+                            ],
+                            'defines':
+                            [
+                                'VK_USE_PLATFORM_WIN32_KHR',
+                                'VK_USE_PLATFORM_WIN32_KHX',
+                            ],
+                        }],
+                        ['OS=="linux"',
+                        {
+                            'defines':
+                            [
+                                'DEFAULT_VK_LAYERS_PATH="."',
+                                'HAVE_SECURE_GETENV',
+                                'LAYERS_SOURCE_PATH="<(vulkan_json)"',
+                                'VK_USE_PLATFORM_XCB_KHR',
+                                'VK_USE_PLATFORM_XCB_KHX',
+                            ],
+                        }],
+                    ],
+                    'actions':
+                    [
+                        {
+                            # The loader header is force included into the loader and layers. Because
+                            # of issues with GYP, we can't use a normal header file, we hav to force
+                            # inclue this using compiler-specific flags.
+                            'action_name': 'vulkan_loader_gen_angle_header',
+                            'message': 'generating Vulkan loader ANGLE header',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(angle_path)/scripts/generate_vulkan_header.py',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/angle_loader.h',
+                            ],
+                            'action':
+                            [
+                                # TODO(jmadill): Use correct platform path
+                                'python', '<(angle_path)/scripts/generate_vulkan_header.py', '<(PRODUCT_DIR)/<(vulkan_json)',
+                                '<(angle_gen_path)/vulkan/angle_loader.h', '<(PRODUCT_DIR)',
+                            ],
+                        },
+                        {
+                            'action_name': 'vulkan_loader_order_deps',
+                            'message': 'stamping for vulkan_loader_order_deps',
+                            'msvs_cygwin_shell': 0,
+                            'inputs': [ '<@(vulkan_layer_generated_files)' ],
+                            'outputs': [ '<(angle_gen_path)/vulkan/vulkan_loader_order_deps.stamp' ],
+                            'action':
+                            [
+                                'python', '<(angle_path)/gyp/touch_stamp.py',
+                                '<(angle_gen_path)/vulkan/vulkan_loader_order_deps.stamp',
+                            ]
+                        },
+                    ],
+                },
+
+                {
+                    'target_name': 'VkLayer_core_validation',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'spirv_tools',
+                        'vulkan_layer_utils_static',
+                    ],
+                    'sources':
+                    [
+                        '<@(VkLayer_core_validation_sources)',
+                    ],
+                    'actions':
+                    [
+                        {
+                            'action_name': 'layer_core_validation_order_deps',
+                            'message': 'stamping for layer_core_validation_order_deps',
+                            'msvs_cygwin_shell': 0,
+                            'inputs': [ '<@(vulkan_layer_generated_files)' ],
+                            'outputs': [ '<(angle_gen_path)/vulkan/layer_core_validation_order_deps.stamp' ],
+                            'action':
+                            [
+                                'python', '<(angle_path)/gyp/touch_stamp.py',
+                                '<(angle_gen_path)/vulkan/layer_core_validation_order_deps.stamp',
+                            ]
+                        },
+                    ],
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<(vulkan_layers_path)/layers/VkLayer_core_validation.def',
+                            ]
+                        }],
+                    ],
+                },
+
+                {
+                    'target_name': 'VkLayer_swapchain',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'vulkan_layer_utils_static',
+                    ],
+                    'sources':
+                    [
+                        '<@(VkLayer_swapchain_sources)',
+                    ],
+                    'actions':
+                    [
+                        {
+                            'action_name': 'layer_swapchain_order_deps',
+                            'message': 'stamping for layer_swapchain_order_deps',
+                            'msvs_cygwin_shell': 0,
+                            'inputs': [ '<@(vulkan_layer_generated_files)' ],
+                            'outputs': [ '<(angle_gen_path)/vulkan/layer_swapchain_order_deps.stamp' ],
+                            'action':
+                            [
+                                'python', '<(angle_path)/gyp/touch_stamp.py',
+                                '<(angle_gen_path)/vulkan/layer_swapchain_order_deps.stamp',
+                            ]
+                        },
+                    ],
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<(vulkan_layers_path)/layers/VkLayer_swapchain.def',
+                            ]
+                        }],
+                    ],
+                },
+
+                {
+                    'target_name': 'VkLayer_object_tracker',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'vulkan_layer_utils_static',
+                    ],
+                    'sources':
+                    [
+                        '<@(VkLayer_object_tracker_sources)',
+                    ],
+                    'actions':
+                    [
+                        {
+                            'action_name': 'layer_object_tracker_order_deps',
+                            'message': 'stamping for layer_object_tracker_order_deps',
+                            'msvs_cygwin_shell': 0,
+                            'inputs': [ '<@(vulkan_layer_generated_files)' ],
+                            'outputs': [ '<(angle_gen_path)/vulkan/layer_object_tracker_order_deps.stamp' ],
+                            'action':
+                            [
+                                'python', '<(angle_path)/gyp/touch_stamp.py',
+                                '<(angle_gen_path)/vulkan/layer_object_tracker_order_deps.stamp',
+                            ]
+                        },
+                    ],
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<(vulkan_layers_path)/layers/VkLayer_object_tracker.def',
+                            ]
+                        }],
+                    ],
+                },
+
+                {
+                    'target_name': 'VkLayer_unique_objects',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'vulkan_layer_utils_static',
+                    ],
+                    'sources':
+                    [
+                        '<@(VkLayer_unique_objects_sources)',
+                    ],
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<(vulkan_layers_path)/layers/VkLayer_unique_objects.def',
+                            ]
+                        }],
+                    ],
+                    'actions':
+                    [
+                        {
+                            'action_name': 'layer_unique_objects_order_deps',
+                            'message': 'stamping for layer_unique_objects_order_deps',
+                            'msvs_cygwin_shell': 0,
+                            'inputs': [ '<@(vulkan_layer_generated_files)' ],
+                            'outputs': [ '<(angle_gen_path)/vulkan/layer_unique_objects_order_deps.stamp' ],
+                            'action':
+                            [
+                                'python', '<(angle_path)/gyp/touch_stamp.py',
+                                '<(angle_gen_path)/vulkan/layer_unique_objects_order_deps.stamp',
+                            ]
+                        },
+                        {
+                            'action_name': 'vulkan_layer_unique_objects_generate',
+                            'message': 'generating Vulkan unique_objects helpers',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/unique_objects_generator.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/unique_objects_wrappers.h',
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py', '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml', 'unique_objects_wrappers.h', '-quiet',
+                            ],
+                        },
+                    ],
+                },
+
+                {
+                    'target_name': 'VkLayer_threading',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'vulkan_layer_utils_static',
+                    ],
+                    'sources':
+                    [
+                        '<@(VkLayer_threading_sources)',
+                    ],
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<(vulkan_layers_path)/layers/VkLayer_threading.def',
+                            ]
+                        }],
+                    ],
+                    'actions':
+                    [
+                        {
+                            'action_name': 'layer_threading_order_deps',
+                            'message': 'stamping for layer_threading_order_deps',
+                            'msvs_cygwin_shell': 0,
+                            'inputs': [ '<@(vulkan_layer_generated_files)' ],
+                            'outputs': [ '<(angle_gen_path)/vulkan/layer_threading_order_deps.stamp' ],
+                            'action':
+                            [
+                                'python', '<(angle_path)/gyp/touch_stamp.py',
+                                '<(angle_gen_path)/vulkan/layer_threading_order_deps.stamp',
+                            ]
+                        },
+                        {
+                            'action_name': 'vulkan_layer_threading_generate',
+                            'message': 'generating Vulkan threading header',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/thread_check.h',
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py', '-o',
+                                '<(angle_gen_path)/vulkan', '-registry', '<(vulkan_layers_path)/scripts/vk.xml',
+                                'thread_check.h', '-quiet',
+                            ],
+                        },
+                    ],
+                },
+
+                {
+                    'target_name': 'VkLayer_parameter_validation',
+                    'type': 'shared_library',
+                    'dependencies':
+                    [
+                        'vulkan_layer_utils_static',
+                    ],
+                    'sources':
+                    [
+                        '<@(VkLayer_parameter_validation_sources)',
+                    ],
+                    'conditions':
+                    [
+                        ['OS=="win"',
+                        {
+                            'sources':
+                            [
+                                '<(vulkan_layers_path)/layers/VkLayer_parameter_validation.def',
+                            ]
+                        }],
+                    ],
+                    'actions':
+                    [
+                        {
+                            'action_name': 'layer_parameter_validation_order_deps',
+                            'message': 'stamping for layer_parameter_validation_order_deps',
+                            'msvs_cygwin_shell': 0,
+                            'inputs': [ '<@(vulkan_layer_generated_files)' ],
+                            'outputs': [ '<(angle_gen_path)/vulkan/layer_parameter_validation_order_deps.stamp' ],
+                            'action':
+                            [
+                                'python', '<(angle_path)/gyp/touch_stamp.py',
+                                '<(angle_gen_path)/vulkan/layer_parameter_validation_order_deps.stamp',
+                            ]
+                        },
+                        {
+                            'action_name': 'vulkan_layer_parameter_validation_generate',
+                            'message': 'generating Vulkan parameter_validation header',
+                            'msvs_cygwin_shell': 0,
+                            'inputs':
+                            [
+                                '<(vulkan_layers_path)/scripts/generator.py',
+                                '<(vulkan_layers_path)/scripts/lvl_genvk.py',
+                                '<(vulkan_layers_path)/scripts/reg.py',
+                                '<(vulkan_layers_path)/scripts/vk.xml',
+                            ],
+                            'outputs':
+                            [
+                                '<(angle_gen_path)/vulkan/parameter_validation.h',
+                            ],
+                            'action':
+                            [
+                                'python', '<(vulkan_layers_path)/scripts/lvl_genvk.py', '-o', '<(angle_gen_path)/vulkan',
+                                '-registry', '<(vulkan_layers_path)/scripts/vk.xml', 'parameter_validation.h', '-quiet',
+                            ],
+                        },
+                    ],
+                },
+
+                {
+                    'target_name': 'angle_vulkan',
+                    'type': 'none',
+                    'dependencies':
+                    [
+                        'glslang',
+                        # Need to disable these to prevent multiply defined symbols with ninja.
+                        # TODO(jmadill): Figure out how to implement data_deps in gyp.
+                        # 'VkLayer_core_validation',
+                        # 'VkLayer_object_tracker',
+                        # 'VkLayer_parameter_validation',
+                        # 'VkLayer_swapchain',
+                        # 'VkLayer_threading',
+                        # 'VkLayer_unique_objects',
+                        'vulkan_loader',
+                    ],
+                    'export_dependent_settings':
+                    [
+                        'glslang',
+                        'vulkan_loader',
+                    ],
+                }
+            ],
+        }],
+    ],
+}
diff --git a/src/third_party/angle/tests/build_tests.gyp b/src/third_party/angle/tests/build_tests.gyp
deleted file mode 100644
index c80a444..0000000
--- a/src/third_party/angle/tests/build_tests.gyp
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'targets': [
-    {
-      'target_name': 'gtest',
-      'type': 'static_library',
-      'include_dirs': [
-        '../third_party/googletest',
-        '../third_party/googletest/include',
-      ],
-      'sources': [
-        '../third_party/googletest/src/gtest-all.cc',
-      ],
-    },
-    {
-      'target_name': 'gmock',
-      'type': 'static_library',
-      'include_dirs': [
-        '../third_party/googlemock',
-        '../third_party/googlemock/include',
-        '../third_party/googletest/include',
-      ],
-      'sources': [
-        '../third_party/googlemock/src/gmock-all.cc',
-      ],
-    },
-    {
-      'target_name': 'preprocessor_tests',
-      'type': 'executable',
-      'dependencies': [
-        '../src/build_angle.gyp:preprocessor',
-        'gtest',
-        'gmock',
-      ],
-      'include_dirs': [
-        '../src/compiler/preprocessor',
-        '../third_party/googletest/include',
-        '../third_party/googlemock/include',
-      ],
-      'sources': [
-        '../third_party/googlemock/src/gmock_main.cc',
-        'preprocessor_tests/char_test.cpp',
-        'preprocessor_tests/comment_test.cpp',
-        'preprocessor_tests/define_test.cpp',
-        'preprocessor_tests/error_test.cpp',
-        'preprocessor_tests/extension_test.cpp',
-        'preprocessor_tests/identifier_test.cpp',
-        'preprocessor_tests/if_test.cpp',
-        'preprocessor_tests/input_test.cpp',
-        'preprocessor_tests/location_test.cpp',
-        'preprocessor_tests/MockDiagnostics.h',
-        'preprocessor_tests/MockDirectiveHandler.h',
-        'preprocessor_tests/number_test.cpp',
-        'preprocessor_tests/operator_test.cpp',
-        'preprocessor_tests/pragma_test.cpp',
-        'preprocessor_tests/PreprocessorTest.cpp',
-        'preprocessor_tests/PreprocessorTest.h',
-        'preprocessor_tests/space_test.cpp',
-        'preprocessor_tests/token_test.cpp',
-        'preprocessor_tests/version_test.cpp',
-      ],
-    },
-    {
-      'target_name': 'compiler_tests',
-      'type': 'executable',
-      'dependencies': [
-        '../src/build_angle.gyp:translator_glsl',
-        'gtest',
-        'gmock',
-      ],
-      'include_dirs': [
-        '../include',
-        '../src',
-        '../third_party/googletest/include',
-        '../third_party/googlemock/include',
-      ],
-      'sources': [
-        '../third_party/googlemock/src/gmock_main.cc',
-        'compiler_tests/ExpressionLimit_test.cpp',
-        'compiler_tests/VariablePacker_test.cpp',
-      ],
-    },
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/src/third_party/angle/tests/compiler_tests/ExpressionLimit_test.cpp b/src/third_party/angle/tests/compiler_tests/ExpressionLimit_test.cpp
deleted file mode 100644
index 3af099d..0000000
--- a/src/third_party/angle/tests/compiler_tests/ExpressionLimit_test.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-#include <sstream>
-#include <string>
-#include <vector>
-#include "GLSLANG/ShaderLang.h"
-#include "gtest/gtest.h"
-
-#define SHADER(Src) #Src
-
-class ExpressionLimitTest : public testing::Test {
-protected:
-    static const int kMaxExpressionComplexity = 16;
-    static const int kMaxCallStackDepth = 16;
-    static const char* kExpressionTooComplex;
-    static const char* kCallStackTooDeep;
-    static const char* kHasRecursion;
-
-    virtual void SetUp()
-    {
-        memset(&resources, 0, sizeof(resources));
-
-        ASSERT_TRUE(ShInitialize() != 0) << "Could not ShInitialize";
-
-        GenerateResources(&resources);
-    }
-
-    virtual void TearDown()
-    {
-        ASSERT_TRUE(ShFinalize() != 0);
-    }
-
-    // Set up the per compile resources
-    void GenerateResources(ShBuiltInResources* resources)
-    {
-        ShInitBuiltInResources(resources);
-
-        resources->MaxVertexAttribs = 8;
-        resources->MaxVertexUniformVectors = 128;
-        resources->MaxVaryingVectors = 8;
-        resources->MaxVertexTextureImageUnits = 0;
-        resources->MaxCombinedTextureImageUnits = 8;
-        resources->MaxTextureImageUnits = 8;
-        resources->MaxFragmentUniformVectors = 16;
-        resources->MaxDrawBuffers = 1;
-
-        resources->OES_standard_derivatives = 0;
-        resources->OES_EGL_image_external = 0;
-
-        resources->MaxExpressionComplexity = kMaxExpressionComplexity;
-        resources->MaxCallStackDepth = kMaxCallStackDepth;
-    }
-
-    void GenerateLongExpression(int length, std::stringstream* ss)
-    {
-        for (int ii = 0; ii < length; ++ii) {
-          *ss << "+ vec4(" << ii << ")";
-        }
-    }
-
-    std::string GenerateShaderWithLongExpression(int length)
-    {
-        static const char* shaderStart = SHADER(
-            precision mediump float;
-            uniform vec4 u_color;
-            void main()
-            {
-               gl_FragColor = u_color
-        );
-
-        std::stringstream ss;
-        ss << shaderStart;
-        GenerateLongExpression(length, &ss);
-        ss << "; }";
-
-        return ss.str();
-    }
-
-    std::string GenerateShaderWithUnusedLongExpression(int length)
-    {
-        static const char* shaderStart = SHADER(
-            precision mediump float;
-            uniform vec4 u_color;
-            void main()
-            {
-               gl_FragColor = u_color;
-            }
-            vec4 someFunction() {
-              return u_color
-        );
-
-        std::stringstream ss;
-
-        ss << shaderStart;
-        GenerateLongExpression(length, &ss);
-        ss << "; }";
-
-        return ss.str();
-    }
-
-    void GenerateDeepFunctionStack(int length, std::stringstream* ss)
-    {
-        static const char* shaderStart = SHADER(
-            precision mediump float;
-            uniform vec4 u_color;
-            vec4 function0()  {
-              return u_color;
-            }
-        );
-
-        *ss << shaderStart;
-        for (int ii = 0; ii < length; ++ii) {
-          *ss << "vec4 function" << (ii + 1) << "() {\n"
-              << "  return function" << ii << "();\n"
-              << "}\n";
-        }
-    }
-
-    std::string GenerateShaderWithDeepFunctionStack(int length)
-    {
-        std::stringstream ss;
-
-        GenerateDeepFunctionStack(length, &ss);
-
-        ss << "void main() {\n"
-           << "  gl_FragColor = function" << length << "();\n"
-           << "}";
-
-        return ss.str();
-    }
-
-    std::string GenerateShaderWithUnusedDeepFunctionStack(int length)
-    {
-        std::stringstream ss;
-
-        GenerateDeepFunctionStack(length, &ss);
-
-        ss << "void main() {\n"
-           << "  gl_FragColor = vec4(0,0,0,0);\n"
-           << "}";
-
-
-        return ss.str();
-    }
-
-    // Compiles a shader and if there's an error checks for a specific
-    // substring in the error log. This way we know the error is specific
-    // to the issue we are testing.
-    bool CheckShaderCompilation(ShHandle compiler,
-                                const char* source,
-                                int compileOptions,
-                                const char* expected_error) {
-        bool success = ShCompile(compiler, &source, 1, compileOptions);
-        if (success) {
-            success = !expected_error;
-        } else {
-            size_t bufferLen = 0;
-            ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &bufferLen);
-            char* buffer(new char [bufferLen]);
-            ShGetInfoLog(compiler, buffer);
-            std::string log(buffer, buffer + bufferLen);
-            delete [] buffer;
-            if (expected_error)
-                success = log.find(expected_error) != std::string::npos;
-
-            EXPECT_TRUE(success) << log << "\n----shader----\n" << source;
-        }
-        return success;
-    }
-
-    ShBuiltInResources resources;
-};
-
-const char* ExpressionLimitTest::kExpressionTooComplex =
-    "Expression too complex";
-const char* ExpressionLimitTest::kCallStackTooDeep =
-    "call stack too deep";
-const char* ExpressionLimitTest::kHasRecursion =
-    "Function recursion detected";
-
-TEST_F(ExpressionLimitTest, ExpressionComplexity)
-{
-    ShShaderSpec spec = SH_WEBGL_SPEC;
-    ShShaderOutput output = SH_ESSL_OUTPUT;
-    ShHandle vertexCompiler = ShConstructCompiler(
-        SH_FRAGMENT_SHADER, spec, output, &resources);
-    int compileOptions = SH_LIMIT_EXPRESSION_COMPLEXITY;
-
-    // Test expression under the limit passes.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithLongExpression(
-            kMaxExpressionComplexity - 10).c_str(),
-        compileOptions, NULL));
-    // Test expression over the limit fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithLongExpression(
-            kMaxExpressionComplexity + 10).c_str(),
-        compileOptions, kExpressionTooComplex));
-    // Test expression over the limit without a limit does not fail.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithLongExpression(
-            kMaxExpressionComplexity + 10).c_str(),
-        compileOptions & ~SH_LIMIT_EXPRESSION_COMPLEXITY, NULL));
-}
-
-TEST_F(ExpressionLimitTest, UnusedExpressionComplexity)
-{
-    ShShaderSpec spec = SH_WEBGL_SPEC;
-    ShShaderOutput output = SH_ESSL_OUTPUT;
-    ShHandle vertexCompiler = ShConstructCompiler(
-        SH_FRAGMENT_SHADER, spec, output, &resources);
-    int compileOptions = SH_LIMIT_EXPRESSION_COMPLEXITY;
-
-    // Test expression under the limit passes.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithUnusedLongExpression(
-            kMaxExpressionComplexity - 10).c_str(),
-        compileOptions, NULL));
-    // Test expression over the limit fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithUnusedLongExpression(
-            kMaxExpressionComplexity + 10).c_str(),
-        compileOptions, kExpressionTooComplex));
-    // Test expression over the limit without a limit does not fail.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithUnusedLongExpression(
-            kMaxExpressionComplexity + 10).c_str(),
-        compileOptions & ~SH_LIMIT_EXPRESSION_COMPLEXITY, NULL));
-}
-
-TEST_F(ExpressionLimitTest, CallStackDepth)
-{
-    ShShaderSpec spec = SH_WEBGL_SPEC;
-    ShShaderOutput output = SH_ESSL_OUTPUT;
-    ShHandle vertexCompiler = ShConstructCompiler(
-        SH_FRAGMENT_SHADER, spec, output, &resources);
-    int compileOptions = SH_LIMIT_CALL_STACK_DEPTH;
-
-    // Test call stack under the limit passes.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithDeepFunctionStack(
-            kMaxCallStackDepth - 10).c_str(),
-        compileOptions, NULL));
-    // Test call stack over the limit fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithDeepFunctionStack(
-            kMaxCallStackDepth + 10).c_str(),
-        compileOptions, kCallStackTooDeep));
-    // Test call stack over the limit without limit does not fail.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithDeepFunctionStack(
-            kMaxCallStackDepth + 10).c_str(),
-        compileOptions & ~SH_LIMIT_CALL_STACK_DEPTH, NULL));
-}
-
-TEST_F(ExpressionLimitTest, UnusedCallStackDepth)
-{
-    ShShaderSpec spec = SH_WEBGL_SPEC;
-    ShShaderOutput output = SH_ESSL_OUTPUT;
-    ShHandle vertexCompiler = ShConstructCompiler(
-        SH_FRAGMENT_SHADER, spec, output, &resources);
-    int compileOptions = SH_LIMIT_CALL_STACK_DEPTH;
-
-    // Test call stack under the limit passes.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithUnusedDeepFunctionStack(
-            kMaxCallStackDepth - 10).c_str(),
-        compileOptions, NULL));
-    // Test call stack over the limit fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithUnusedDeepFunctionStack(
-            kMaxCallStackDepth + 10).c_str(),
-        compileOptions, kCallStackTooDeep));
-    // Test call stack over the limit without limit does not fail.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler,
-        GenerateShaderWithUnusedDeepFunctionStack(
-            kMaxCallStackDepth + 10).c_str(),
-        compileOptions & ~SH_LIMIT_CALL_STACK_DEPTH, NULL));
-}
-
-TEST_F(ExpressionLimitTest, Recursion)
-{
-    ShShaderSpec spec = SH_WEBGL_SPEC;
-    ShShaderOutput output = SH_ESSL_OUTPUT;
-    ShHandle vertexCompiler = ShConstructCompiler(
-        SH_FRAGMENT_SHADER, spec, output, &resources);
-    int compileOptions = 0;
-
-    static const char* shaderWithRecursion0 = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-        vec4 someFunc()  {
-            return someFunc();
-        }
-
-        void main() {
-            gl_FragColor = u_color * someFunc();
-        }
-    );
-
-    static const char* shaderWithRecursion1 = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-
-        vec4 someFunc();
-
-        vec4 someFunc1()  {
-            return someFunc();
-        }
-
-        vec4 someFunc()  {
-            return someFunc1();
-        }
-
-        void main() {
-            gl_FragColor = u_color * someFunc();
-        }
-    );
-
-    static const char* shaderWithRecursion2 = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-        vec4 someFunc()  {
-            if (u_color.x > 0.5) {
-                return someFunc();
-            } else {
-                return vec4(1);
-            }
-        }
-
-        void main() {
-            gl_FragColor = someFunc();
-        }
-    );
-
-    static const char* shaderWithRecursion3 = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-        vec4 someFunc()  {
-            if (u_color.x > 0.5) {
-                return vec4(1);
-            } else {
-                return someFunc();
-            }
-        }
-
-        void main() {
-            gl_FragColor = someFunc();
-        }
-    );
-
-    static const char* shaderWithRecursion4 = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-        vec4 someFunc()  {
-            return (u_color.x > 0.5) ? vec4(1) : someFunc();
-        }
-
-        void main() {
-            gl_FragColor = someFunc();
-        }
-    );
-
-    static const char* shaderWithRecursion5 = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-        vec4 someFunc()  {
-            return (u_color.x > 0.5) ? someFunc() : vec4(1);
-        }
-
-        void main() {
-            gl_FragColor = someFunc();
-        }
-    );
-
-    static const char* shaderWithRecursion6 = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-        vec4 someFunc()  {
-            return someFunc();
-        }
-
-        void main() {
-            gl_FragColor = u_color;
-        }
-    );
-
-    static const char* shaderWithNoRecursion = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-
-        vec3 rgb(int r, int g, int b) {
-            return vec3(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0);
-        }
-
-        // these external calls used to incorrectly trigger
-        // recursion detection.
-        vec3 hairColor0 = rgb(151, 200, 234);
-        vec3 faceColor2 = rgb(183, 148, 133);
-
-        void main() {
-            gl_FragColor = u_color + vec4(hairColor0 + faceColor2, 0);
-        }
-    );
-
-    static const char* shaderWithRecursion7 = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-
-        vec4 function2() {
-            return u_color;
-        }
-
-        vec4 function1() {
-            vec4 a = function2();
-            vec4 b = function1();
-            return a + b;
-        }
-
-        void main() {
-            gl_FragColor = function1();
-        }
-    );
-
-    static const char* shaderWithRecursion8 = SHADER(
-        precision mediump float;
-        uniform vec4 u_color;
-
-        vec4 function1();
-
-        vec4 function3() {
-            return function1();
-        }
-
-        vec4 function2() {
-            return function3();
-        }
-
-        vec4 function1() {
-            return function2();
-        }
-
-        void main() {
-            gl_FragColor = function1();
-        }
-    );
-
-    // Check simple recursions fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion0,
-        compileOptions, kHasRecursion));
-    // Check simple recursions fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion1,
-        compileOptions, kHasRecursion));
-    // Check if recursions fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion2,
-        compileOptions, kHasRecursion));
-    // Check if recursions fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion3,
-        compileOptions, kHasRecursion));
-    // Check ternary recursions fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion4,
-        compileOptions, kHasRecursion));
-    // Check ternary recursions fails.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion5,
-        compileOptions, kHasRecursion));
-    // Check unused recursions passes.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion6,
-        compileOptions, NULL));
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion7,
-        compileOptions, kHasRecursion));
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion8,
-        compileOptions, kHasRecursion));
-    // Check unused recursions fails if limiting call stack
-    // since we check all paths.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithRecursion6,
-        compileOptions | SH_LIMIT_CALL_STACK_DEPTH, kHasRecursion));
-
-    // Check unused recursions passes.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithNoRecursion,
-        compileOptions, NULL));
-    // Check unused recursions passes if limiting call stack.
-    EXPECT_TRUE(CheckShaderCompilation(
-        vertexCompiler, shaderWithNoRecursion,
-        compileOptions | SH_LIMIT_CALL_STACK_DEPTH, NULL));
-}
-
diff --git a/src/third_party/angle/tests/compiler_tests/VariablePacker_test.cpp b/src/third_party/angle/tests/compiler_tests/VariablePacker_test.cpp
deleted file mode 100644
index 6405ea7..0000000
--- a/src/third_party/angle/tests/compiler_tests/VariablePacker_test.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-#include "compiler/VariablePacker.h"
-#include "gtest/gtest.h"
-
-TEST(VariablePacking, Pack) {
-  VariablePacker packer;
-  TVariableInfoList vars;
-  const int kMaxRows = 16;
-  // test no vars.
-  EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
-
-  ShDataType types[] = {
-    SH_FLOAT_MAT4,            // 0
-    SH_FLOAT_MAT2,            // 1
-    SH_FLOAT_VEC4,            // 2
-    SH_INT_VEC4,              // 3
-    SH_BOOL_VEC4,             // 4
-    SH_FLOAT_MAT3,            // 5
-    SH_FLOAT_VEC3,            // 6
-    SH_INT_VEC3,              // 7
-    SH_BOOL_VEC3,             // 8
-    SH_FLOAT_VEC2,            // 9
-    SH_INT_VEC2,              // 10
-    SH_BOOL_VEC2,             // 11
-    SH_FLOAT,                 // 12
-    SH_INT,                   // 13
-    SH_BOOL,                  // 14
-    SH_SAMPLER_2D,            // 15
-    SH_SAMPLER_CUBE,          // 16
-    SH_SAMPLER_EXTERNAL_OES,  // 17
-    SH_SAMPLER_2D_RECT_ARB,   // 18
-  };
-
-  for (size_t tt = 0; tt < sizeof(types) / sizeof(types[0]); ++tt) {
-    ShDataType type = types[tt];
-    int num_rows = VariablePacker::GetNumRows(type);
-    int num_components_per_row = VariablePacker::GetNumComponentsPerRow(type);
-    // Check 1 of the type.
-    vars.clear();
-    vars.push_back(TVariableInfo(type, 1));
-    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
-
-    // Check exactly the right amount of 1 type as an array.
-    int num_vars = kMaxRows / num_rows;
-    vars.clear();
-    vars.push_back(TVariableInfo(type, num_vars));
-    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
-
-    // test too many
-    vars.clear();
-    vars.push_back(TVariableInfo(type, num_vars + 1));
-    EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
-
-    // Check exactly the right amount of 1 type as individual vars.
-    num_vars = kMaxRows / num_rows *
-        ((num_components_per_row > 2) ? 1 : (4 / num_components_per_row));
-    vars.clear();
-    for (int ii = 0; ii < num_vars; ++ii) {
-      vars.push_back(TVariableInfo(type, 1));
-    }
-    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
-
-    // Check 1 too many.
-    vars.push_back(TVariableInfo( type, 1));
-    EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
-  }
-
-  // Test example from GLSL ES 3.0 spec chapter 11.
-  vars.clear();
-  vars.push_back(TVariableInfo(SH_FLOAT_VEC4, 1));
-  vars.push_back(TVariableInfo(SH_FLOAT_MAT3, 1));
-  vars.push_back(TVariableInfo(SH_FLOAT_MAT3, 1));
-  vars.push_back(TVariableInfo(SH_FLOAT_VEC2, 6));
-  vars.push_back(TVariableInfo(SH_FLOAT_VEC2, 4));
-  vars.push_back(TVariableInfo(SH_FLOAT_VEC2, 1));
-  vars.push_back(TVariableInfo(SH_FLOAT, 3));
-  vars.push_back(TVariableInfo(SH_FLOAT, 2));
-  vars.push_back(TVariableInfo(SH_FLOAT, 1));
-  EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
-}
-
diff --git a/src/third_party/angle/tests/preprocessor_tests/MockDiagnostics.h b/src/third_party/angle/tests/preprocessor_tests/MockDiagnostics.h
deleted file mode 100644
index 1fcedb4..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/MockDiagnostics.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef PREPROCESSOR_TESTS_MOCK_DIAGNOSTICS_H_
-#define PREPROCESSOR_TESTS_MOCK_DIAGNOSTICS_H_
-
-#include "gmock/gmock.h"
-#include "DiagnosticsBase.h"
-
-class MockDiagnostics : public pp::Diagnostics
-{
-  public:
-    MOCK_METHOD3(print,
-        void(ID id, const pp::SourceLocation& loc, const std::string& text));
-};
-
-#endif  // PREPROCESSOR_TESTS_MOCK_DIAGNOSTICS_H_
diff --git a/src/third_party/angle/tests/preprocessor_tests/MockDirectiveHandler.h b/src/third_party/angle/tests/preprocessor_tests/MockDirectiveHandler.h
deleted file mode 100644
index f2893fd..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/MockDirectiveHandler.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef PREPROCESSOR_TESTS_MOCK_DIRECTIVE_HANDLER_H_
-#define PREPROCESSOR_TESTS_MOCK_DIRECTIVE_HANDLER_H_
-
-#include "gmock/gmock.h"
-#include "DirectiveHandlerBase.h"
-
-class MockDirectiveHandler : public pp::DirectiveHandler
-{
-  public:
-    MOCK_METHOD2(handleError,
-        void(const pp::SourceLocation& loc, const std::string& msg));
-
-    MOCK_METHOD3(handlePragma,
-        void(const pp::SourceLocation& loc,
-             const std::string& name,
-             const std::string& value));
-
-    MOCK_METHOD3(handleExtension,
-        void(const pp::SourceLocation& loc,
-             const std::string& name,
-             const std::string& behavior));
-
-    MOCK_METHOD2(handleVersion,
-        void(const pp::SourceLocation& loc, int version));
-};
-
-#endif  // PREPROCESSOR_TESTS_MOCK_DIRECTIVE_HANDLER_H_
diff --git a/src/third_party/angle/tests/preprocessor_tests/PreprocessorTest.cpp b/src/third_party/angle/tests/preprocessor_tests/PreprocessorTest.cpp
deleted file mode 100644
index 9f90484..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/PreprocessorTest.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-void PreprocessorTest::preprocess(const char* input, const char* expected)
-{
-    ASSERT_TRUE(mPreprocessor.init(1, &input, NULL));
-
-    int line = 1;
-    pp::Token token;
-    std::stringstream stream;
-    do
-    {
-        mPreprocessor.lex(&token);
-        for (; line < token.location.line; ++line)
-        {
-            stream << "\n";
-        }
-        stream << token;
-    } while (token.type != pp::Token::LAST);
-
-    std::string actual = stream.str();
-    EXPECT_STREQ(expected, actual.c_str());
-}
diff --git a/src/third_party/angle/tests/preprocessor_tests/PreprocessorTest.h b/src/third_party/angle/tests/preprocessor_tests/PreprocessorTest.h
deleted file mode 100644
index e8184de..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/PreprocessorTest.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
-
-#ifndef PREPROCESSOR_TESTS_PREPROCESSOR_TEST_H_
-#define PREPROCESSOR_TESTS_PREPROCESSOR_TEST_H_
-
-class PreprocessorTest : public testing::Test
-{
-  protected:
-    PreprocessorTest() : mPreprocessor(&mDiagnostics, &mDirectiveHandler) { }
-
-    // Preprocesses the input string and verifies that it matches
-    // expected output.
-    void preprocess(const char* input, const char* expected);
-
-    MockDiagnostics mDiagnostics;
-    MockDirectiveHandler mDirectiveHandler;
-    pp::Preprocessor mPreprocessor;
-};
-
-#endif  // PREPROCESSOR_TESTS_PREPROCESSOR_TEST_H_
diff --git a/src/third_party/angle/tests/preprocessor_tests/char_test.cpp b/src/third_party/angle/tests/preprocessor_tests/char_test.cpp
deleted file mode 100644
index e6576a0..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/char_test.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include <algorithm>
-#include <climits>
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class CharTest : public PreprocessorTest,
-                 public testing::WithParamInterface<int>
-{
-};
-
-static const char kPunctuators[] = {
-    '.', '+', '-', '/', '*', '%', '<', '>', '[', ']', '(', ')', '{', '}',
-    '^', '|', '&', '~', '=', '!', ':', ';', ',', '?'};
-static const int kNumPunctuators =
-    sizeof(kPunctuators) / sizeof(kPunctuators[0]);
-
-bool isPunctuator(char c)
-{
-    static const char* kPunctuatorBeg = kPunctuators;
-    static const char* kPunctuatorEnd = kPunctuators + kNumPunctuators;
-    return std::find(kPunctuatorBeg, kPunctuatorEnd, c) != kPunctuatorEnd;
-}
-
-static const char kWhitespaces[] = {' ', '\t', '\v', '\f', '\n', '\r'};
-static const int kNumWhitespaces =
-    sizeof(kWhitespaces) / sizeof(kWhitespaces[0]);
-
-bool isWhitespace(char c)
-{
-    static const char* kWhitespaceBeg = kWhitespaces;
-    static const char* kWhitespaceEnd = kWhitespaces + kNumWhitespaces;
-    return std::find(kWhitespaceBeg, kWhitespaceEnd, c) != kWhitespaceEnd;
-}
-
-TEST_P(CharTest, Identified)
-{
-    std::string str(1, GetParam());
-    const char* cstr = str.c_str();
-    int length = 1;
-
-    // Note that we pass the length param as well because the invalid
-    // string may contain the null character.
-    ASSERT_TRUE(mPreprocessor.init(1, &cstr, &length));
-
-    int expectedType = pp::Token::LAST;
-    std::string expectedValue;
-
-    if (str[0] == '#')
-    {
-        // Lone '#' is ignored.
-    }
-    else if ((str[0] == '_') ||
-             ((str[0] >= 'a') && (str[0] <= 'z')) ||
-             ((str[0] >= 'A') && (str[0] <= 'Z')))
-    {
-        expectedType = pp::Token::IDENTIFIER;
-        expectedValue = str;
-    }
-    else if (str[0] >= '0' && str[0] <= '9')
-    {
-        expectedType = pp::Token::CONST_INT;
-        expectedValue = str;
-    }
-    else if (isPunctuator(str[0]))
-    {
-        expectedType = str[0];
-        expectedValue = str;
-    }
-    else if (isWhitespace(str[0]))
-    {
-        // Whitespace is ignored.
-    }
-    else
-    {
-        // Everything else is invalid.
-        using testing::_;
-        EXPECT_CALL(mDiagnostics,
-            print(pp::Diagnostics::INVALID_CHARACTER, _, str));
-    }
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(expectedType, token.type);
-    EXPECT_EQ(expectedValue, token.text);
-};
-
-// Note +1 for the max-value in range. It is there because the max-value
-// not included in the range.
-INSTANTIATE_TEST_CASE_P(All, CharTest,
-                        testing::Range(CHAR_MIN, CHAR_MAX + 1));
-
diff --git a/src/third_party/angle/tests/preprocessor_tests/comment_test.cpp b/src/third_party/angle/tests/preprocessor_tests/comment_test.cpp
deleted file mode 100644
index 27f78cf..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/comment_test.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class CommentTest : public PreprocessorTest,
-                    public testing::WithParamInterface<const char*>
-{
-};
-
-TEST_P(CommentTest, CommentIgnored)
-{
-    const char* str = GetParam();
-
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::LAST, token.type);
-}
-
-INSTANTIATE_TEST_CASE_P(LineComment, CommentTest,
-                        testing::Values("//foo\n", // With newline.
-                                        "//foo",   // Without newline.
-                                        "//**/",   // Nested block comment.
-                                        "////",    // Nested line comment.
-                                        "//\""));  // Invalid character.  
-
-INSTANTIATE_TEST_CASE_P(BlockComment, CommentTest,
-                        testing::Values("/*foo*/",
-                                        "/*foo\n*/", // With newline.
-                                        "/*//*/",    // Nested line comment.
-                                        "/*/**/",    // Nested block comment.
-                                        "/***/",     // With lone '*'.
-                                        "/*\"*/"));  // Invalid character.
-
-class BlockCommentTest : public PreprocessorTest
-{
-};
-
-TEST_F(BlockCommentTest, CommentReplacedWithSpace)
-{
-    const char* str = "/*foo*/bar";
-
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ("bar", token.text);
-    EXPECT_TRUE(token.hasLeadingSpace());
-}
-
-TEST_F(BlockCommentTest, UnterminatedComment)
-{
-    const char* str = "/*foo";
-
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    using testing::_;
-    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_COMMENT, _, _));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
diff --git a/src/third_party/angle/tests/preprocessor_tests/define_test.cpp b/src/third_party/angle/tests/preprocessor_tests/define_test.cpp
deleted file mode 100644
index bb72016..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/define_test.cpp
+++ /dev/null
@@ -1,893 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class DefineTest : public PreprocessorTest
-{
-};
-
-TEST_F(DefineTest, NonIdentifier)
-{
-    const char* input = "#define 2 foo\n"
-                        "2\n";
-    const char* expected = "\n"
-                           "2\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::UNEXPECTED_TOKEN,
-                      pp::SourceLocation(0, 1),
-                      "2"));
-
-    preprocess(input, expected);
-};
-
-TEST_F(DefineTest, RedefinePredefined)
-{
-    const char* input = "#define __LINE__ 10\n"
-                        "__LINE__\n"
-                        "#define __FILE__ 20\n"
-                        "__FILE__\n"
-                        "#define __VERSION__ 200\n"
-                        "__VERSION__\n"
-                        "#define GL_ES 0\n"
-                        "GL_ES\n";
-    const char* expected = "\n"
-                           "2\n"
-                           "\n"
-                           "0\n"
-                           "\n"
-                           "100\n"
-                           "\n"
-                           "1\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_PREDEFINED_REDEFINED,
-                      pp::SourceLocation(0, 1),
-                      "__LINE__"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_PREDEFINED_REDEFINED,
-                      pp::SourceLocation(0, 3),
-                      "__FILE__"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_PREDEFINED_REDEFINED,
-                      pp::SourceLocation(0, 5),
-                      "__VERSION__"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_PREDEFINED_REDEFINED,
-                      pp::SourceLocation(0, 7),
-                      "GL_ES"));
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ReservedUnderScore1)
-{
-    const char* input = "#define __foo bar\n"
-                        "__foo\n";
-    const char* expected = "\n"
-                           "__foo\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_NAME_RESERVED,
-                      pp::SourceLocation(0, 1),
-                      "__foo"));
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ReservedUnderScore2)
-{
-    const char* input = "#define foo__bar baz\n"
-                        "foo__bar\n";
-    const char* expected = "\n"
-                           "foo__bar\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_NAME_RESERVED,
-                      pp::SourceLocation(0, 1),
-                      "foo__bar"));
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ReservedGL)
-{
-    const char* input = "#define GL_foo bar\n"
-                        "GL_foo\n";
-    const char* expected = "\n"
-                           "GL_foo\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_NAME_RESERVED,
-                      pp::SourceLocation(0, 1),
-                      "GL_foo"));
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjRedefineValid)
-{
-    const char* input = "#define foo (1-1)\n"
-                        "#define foo /* whitespace */ (1-1) /* other */ \n"
-                        "foo\n";
-    const char* expected = "\n"
-                           "\n"
-                           "(1-1)\n";
-    // No error or warning.
-    using testing::_;
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjRedefineInvalid)
-{
-    const char* input = "#define foo (0)\n"
-                        "#define foo (1-1)\n"
-                        "foo\n";
-    const char* expected = "\n"
-                           "\n"
-                           "(0)\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_REDEFINED,
-                      pp::SourceLocation(0, 2),
-                      "foo"));
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncRedefineValid)
-{
-    const char* input = "#define foo(a) ( a )\n"
-                        "#define foo( a )( /* whitespace */ a /* other */ )\n"
-                        "foo(b)\n";
-    const char* expected = "\n"
-                           "\n"
-                           "( b )\n";
-    // No error or warning.
-    using testing::_;
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncRedefineInvalid)
-{
-    const char* input = "#define foo(b) ( a )\n"
-                        "#define foo(b) ( b )\n"
-                        "foo(1)\n";
-    const char* expected = "\n"
-                           "\n"
-                           "( a )\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_REDEFINED,
-                      pp::SourceLocation(0, 2),
-                      "foo"));
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjBasic)
-{
-    const char* input = "#define foo 1\n"
-                        "foo\n";
-    const char* expected = "\n"
-                           "1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjEmpty)
-{
-    const char* input = "#define foo\n"
-                        "foo\n";
-    const char* expected = "\n"
-                           "\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjChain)
-{
-    const char* input = "#define foo 1\n"
-                        "#define bar foo\n"
-                        "bar\n";
-    const char* expected = "\n"
-                           "\n"
-                           "1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjChainReverse)
-{
-    const char* input = "#define bar foo\n"
-                        "#define foo 1\n"
-                        "bar\n";
-    const char* expected = "\n"
-                           "\n"
-                           "1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjRecursive)
-{
-    const char* input = "#define foo bar\n"
-                        "#define bar baz\n"
-                        "#define baz foo\n"
-                        "foo\n"
-                        "bar\n"
-                        "baz\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "foo\n"
-                           "bar\n"
-                           "baz\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjCompositeChain)
-{
-    const char* input = "#define foo 1\n"
-                        "#define bar a foo\n"
-                        "bar\n";
-    const char* expected = "\n"
-                           "\n"
-                           "a 1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjCompositeChainReverse)
-{
-    const char* input = "#define bar a foo\n"
-                        "#define foo 1\n"
-                        "bar\n";
-    const char* expected = "\n"
-                           "\n"
-                           "a 1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjCompositeRecursive)
-{
-    const char* input = "#define foo a bar\n"
-                        "#define bar b baz\n"
-                        "#define baz c foo\n"
-                        "foo\n"
-                        "bar\n"
-                        "baz\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "a b c foo\n"
-                           "b c a bar\n"
-                           "c a b baz\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjChainSelfRecursive)
-{
-    const char* input = "#define foo foo\n"
-                        "#define bar foo\n"
-                        "bar\n";
-    const char* expected = "\n"
-                           "\n"
-                           "foo\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjectLikeWithParens)
-{
-    const char* input = "#define foo ()1\n"
-                        "foo()\n"
-                        "#define bar ()2\n"
-                        "bar()\n";
-    const char* expected = "\n"
-                           "()1()\n"
-                           "\n"
-                           "()2()\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncEmpty)
-{
-    const char* input = "#define foo()\n"
-                        "foo()\n";
-    const char* expected = "\n"
-                           "\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncNoArgs)
-{
-    const char* input = "#define foo() bar\n"
-                        "foo()\n";
-    const char* expected = "\n"
-                           "bar\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncOneArgUnused)
-{
-    const char* input = "#define foo(x) 1\n"
-                        "foo(bar)\n";
-    const char* expected = "\n"
-                           "1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncTwoArgsUnused)
-{
-    const char* input = "#define foo(x,y) 1\n"
-                        "foo(bar,baz)\n";
-    const char* expected = "\n"
-                           "1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncOneArg)
-{
-    const char* input = "#define foo(x) ((x)+1)\n"
-                        "foo(bar)\n";
-    const char* expected = "\n"
-                           "((bar)+1)\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncTwoArgs)
-{
-    const char* input = "#define foo(x,y) ((x)*(y))\n"
-                        "foo(bar,baz)\n";
-    const char* expected = "\n"
-                           "((bar)*(baz))\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncEmptyArgs)
-{
-    const char* input = "#define zero() pass\n"
-                        "#define one(x) pass\n"
-                        "#define two(x,y) pass\n"
-                        "zero()\n"
-                        "one()\n"
-                        "two(,)\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "pass\n"
-                           "pass\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncMacroAsParam)
-{
-    const char* input = "#define x 0\n"
-                        "#define foo(x) x\n"
-                        "foo(1)\n";
-    const char* expected = "\n"
-                           "\n"
-                           "1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncOneArgMulti)
-{
-    const char* input = "#define foo(x) (x)\n"
-                        "foo(this is a multi-word argument)\n";
-    const char* expected = "\n"
-                           "(this is a multi-word argument)\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncTwoArgsMulti)
-{
-    const char* input = "#define foo(x,y) x,two fish,red fish,y\n"
-                        "foo(one fish, blue fish)\n";
-    const char* expected = "\n"
-                           "one fish,two fish,red fish,blue fish\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncCompose)
-{
-    const char* input = "#define bar(x) (1+(x))\n"
-                        "#define foo(y) (2*(y))\n"
-                        "foo(bar(3))\n";
-    const char* expected = "\n"
-                           "\n"
-                           "(2*((1+(3))))\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncArgWithParens)
-{
-    const char* input = "#define foo(x) (x)\n"
-                        "foo(argument(with parens) FTW)\n";
-    const char* expected = "\n"
-                           "(argument(with parens) FTW)\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncMacroAsNonMacro)
-{
-    const char* input = "#define foo(bar) bar\n"
-                        "foo bar\n";
-    const char* expected = "\n"
-                           "foo bar\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncExtraNewlines)
-{
-    const char* input = "#define foo(a) (a)\n"
-                        "foo\n"
-                        "(\n"
-                        "1\n"
-                        ")\n";
-    const char* expected = "\n"
-                           "(1)\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ChainObjToFunc)
-{
-    const char* input = "#define foo() pass\n"
-                        "#define bar foo()\n"
-                        "bar\n";
-    const char* expected = "\n"
-                           "\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ChainObjToNonFunc)
-{
-    const char* input = "#define pass() fail\n"
-                        "#define bar pass\n"
-                        "bar\n";
-    const char* expected = "\n"
-                           "\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ChainObjToFuncWithArgs)
-{
-    const char* input = "#define foo(fail) fail\n"
-                        "#define bar foo(pass)\n"
-                        "bar\n";
-    const char* expected = "\n"
-                           "\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ChainObjToFuncCompose)
-{
-    const char* input = "#define baz(fail) fail\n"
-                        "#define bar(fail) fail\n"
-                        "#define foo bar(baz(pass))\n"
-                        "foo\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ChainObjToFuncParensInText1)
-{
-    const char* input = "#define fail() pass\n"
-                        "#define foo fail\n"
-                        "foo()\n";
-    const char* expected = "\n"
-                           "\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ChainObjToFuncParensInText2)
-{
-    const char* input = "#define bar with,embedded,commas\n"
-                        "#define func(x) pass\n"
-                        "#define foo func\n"
-                        "foo(bar)\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ChainObjToFuncMultiLevel)
-{
-    const char* input = "#define foo(x) pass\n"
-                        "#define bar foo\n"
-                        "#define baz bar\n"
-                        "#define joe baz\n"
-                        "joe (fail)\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ObjToFuncRecursive)
-{
-    const char* input = "#define A(a,b) B(a,b)\n"
-                        "#define C A(0,C)\n"
-                        "C\n";
-    const char* expected = "\n"
-                           "\n"
-                           "B(0,C)\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, ChainFuncToFuncCompose)
-{
-    const char* input = "#define baz(fail) fail\n"
-                        "#define bar(fail) fail\n"
-                        "#define foo() bar(baz(pass))\n"
-                        "foo()\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncSelfRecursive)
-{
-    const char* input = "#define foo(a) foo(2*(a))\n"
-                        "foo(3)\n";
-    const char* expected = "\n"
-                           "foo(2*(3))\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncSelfCompose)
-{
-    const char* input = "#define foo(a) foo(2*(a))\n"
-                        "foo(foo(3))\n";
-    const char* expected = "\n"
-                           "foo(2*(foo(2*(3))))\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncSelfComposeNonFunc)
-{
-    const char* input = "#define foo(bar) bar\n"
-                        "foo(foo)\n";
-    const char* expected = "\n"
-                           "foo\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncSelfComposeNonFuncMultiTokenArg)
-{
-    const char* input = "#define foo(bar) bar\n"
-                        "foo(1+foo)\n";
-    const char* expected = "\n"
-                           "1+foo\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FinalizeUnexpandedMacro)
-{
-    const char* input = "#define expand(x) expand(x once)\n"
-                        "#define foo(x) x\n"
-                        "foo(expand(just))\n";
-    const char* expected = "\n"
-                           "\n"
-                           "expand(just once)\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncArgWithCommas)
-{
-    const char* input = "#define foo(x) pass\n"
-                        "foo(argument (with,embedded, commas) -- baz)\n";
-    const char* expected = "\n"
-                           "pass\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncArgObjMaroWithComma)
-{
-    const char* input = "#define foo(a) (a)\n"
-                        "#define bar two,words\n"
-                        "foo(bar)\n";
-    const char* expected = "\n"
-                           "\n"
-                           "(two,words)\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncLeftParenInMacroRightParenInText)
-{
-    const char* input = "#define bar(a) a*2\n"
-                        "#define foo bar(\n"
-                        "foo b)\n";
-    const char* expected = "\n"
-                           "\n"
-                           "b*2\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, RepeatedArg)
-{
-    const char* input = "#define double(x) x x\n"
-                        "double(1)\n";
-    const char* expected = "\n"
-                           "1 1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncMissingRightParen)
-{
-    const char* input = "#define foo(x) (2*(x))\n"
-                        "foo(3\n";
-    const char* expected = "\n"
-                           "\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_UNTERMINATED_INVOCATION,
-                      pp::SourceLocation(0, 2),
-                      "foo"));
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, FuncIncorrectArgCount)
-{
-    const char* input = "#define foo(x,y) ((x)+(y))\n"
-                        "foo()\n"
-                        "foo(1)\n"
-                        "foo(1,2,3)\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_TOO_FEW_ARGS,
-                      pp::SourceLocation(0, 2),
-                      "foo"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_TOO_FEW_ARGS,
-                      pp::SourceLocation(0, 3),
-                      "foo"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_TOO_MANY_ARGS,
-                      pp::SourceLocation(0, 4),
-                      "foo"));
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, Undef)
-{
-    const char* input = "#define foo 1\n"
-                        "foo\n"
-                        "#undef foo\n"
-                        "foo\n";
-    const char* expected = "\n"
-                           "1\n"
-                           "\n"
-                           "foo\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, UndefPredefined)
-{
-    const char* input = "#undef __LINE__\n"
-                        "__LINE__\n"
-                        "#undef __FILE__\n"
-                        "__FILE__\n"
-                        "#undef __VERSION__\n"
-                        "__VERSION__\n"
-                        "#undef GL_ES\n"
-                        "GL_ES\n";
-    const char* expected = "\n"
-                           "2\n"
-                           "\n"
-                           "0\n"
-                           "\n"
-                           "100\n"
-                           "\n"
-                           "1\n";
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_PREDEFINED_UNDEFINED,
-                      pp::SourceLocation(0, 1),
-                      "__LINE__"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_PREDEFINED_UNDEFINED,
-                      pp::SourceLocation(0, 3),
-                      "__FILE__"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_PREDEFINED_UNDEFINED,
-                      pp::SourceLocation(0, 5),
-                      "__VERSION__"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::MACRO_PREDEFINED_UNDEFINED,
-                      pp::SourceLocation(0, 7),
-                      "GL_ES"));
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, UndefRedefine)
-{
-    const char* input = "#define foo 1\n"
-                        "foo\n"
-                        "#undef foo\n"
-                        "foo\n"
-                        "#define foo 2\n"
-                        "foo\n";
-    const char* expected = "\n"
-                           "1\n"
-                           "\n"
-                           "foo\n"
-                           "\n"
-                           "2\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, C99Example)
-{
-    const char* input =
-        "#define x    3          \n"
-        "#define f(a) f(x * (a)) \n"
-        "#undef  x               \n"
-        "#define x    2          \n"
-        "#define g    f          \n"
-        "#define z    z[0]       \n"
-        "#define h    g(~        \n"
-        "#define m(a) a(w)       \n"
-        "#define w    0,1        \n"
-        "#define t(a) a          \n"
-        "#define p()  int        \n"
-        "#define q(x) x          \n"
-        "                        \n"
-        "f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);\n"
-        "g(x+(3,4)-w) | h 5) & m\n"
-        "    (f)^m(m);\n"
-        "p() i[q()] = { q(1), 23, 4, 5, };\n";
-    const char* expected = 
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);\n"
-        "f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))\n"
-        "^m(0,1);\n"
-        "int i[] = { 1, 23, 4, 5, };\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, Predefined_GL_ES)
-{
-    const char* input = "GL_ES\n";
-    const char* expected = "1\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, Predefined_VERSION)
-{
-    const char* input = "__VERSION__\n";
-    const char* expected = "100\n";
-
-    preprocess(input, expected);
-}
-
-TEST_F(DefineTest, Predefined_LINE1)
-{
-    const char* str = "\n\n__LINE__";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::CONST_INT, token.type);
-    EXPECT_EQ("3", token.text);
-}
-
-TEST_F(DefineTest, Predefined_LINE2)
-{
-    const char* str = "#line 10\n"
-                      "__LINE__\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::CONST_INT, token.type);
-    EXPECT_EQ("10", token.text);
-}
-
-TEST_F(DefineTest, Predefined_FILE1)
-{
-    const char* const str[] = {"", "", "__FILE__"};
-    ASSERT_TRUE(mPreprocessor.init(3, str, NULL));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::CONST_INT, token.type);
-    EXPECT_EQ("2", token.text);
-}
-
-TEST_F(DefineTest, Predefined_FILE2)
-{
-    const char* const str[] = {"#line 10 20\n", "__FILE__"};
-    ASSERT_TRUE(mPreprocessor.init(2, str, NULL));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::CONST_INT, token.type);
-    EXPECT_EQ("21", token.text);
-}
diff --git a/src/third_party/angle/tests/preprocessor_tests/error_test.cpp b/src/third_party/angle/tests/preprocessor_tests/error_test.cpp
deleted file mode 100644
index c9e0c40..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/error_test.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class ErrorTest : public PreprocessorTest
-{
-};
-
-TEST_F(ErrorTest, Empty)
-{
-    const char* str = "#error\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler, handleError(pp::SourceLocation(0, 1), ""));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(ErrorTest, OneTokenMessage)
-{
-    const char* str = "#error foo\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handleError(pp::SourceLocation(0, 1), " foo"));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(ErrorTest, TwoTokenMessage)
-{
-    const char* str = "#error foo bar\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handleError(pp::SourceLocation(0, 1), " foo bar"));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(ErrorTest, Comments)
-{
-    const char* str = "/*foo*/"
-                      "#"
-                      "/*foo*/"
-                      "error"
-                      "/*foo*/"
-                      "foo"
-                      "/*foo*/"
-                      "bar"
-                      "/*foo*/"
-                      "//foo"
-                      "\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handleError(pp::SourceLocation(0, 1), " foo bar"));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(ErrorTest, MissingNewline)
-{
-    const char* str = "#error foo";
-    const char* expected = "";
-
-    using testing::_;
-    // Directive successfully parsed.
-    EXPECT_CALL(mDirectiveHandler,
-                handleError(pp::SourceLocation(0, 1), " foo"));
-    // Error reported about EOF.
-    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
-
-    preprocess(str, expected);
-}
diff --git a/src/third_party/angle/tests/preprocessor_tests/extension_test.cpp b/src/third_party/angle/tests/preprocessor_tests/extension_test.cpp
deleted file mode 100644
index 94b7eb7..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/extension_test.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class ExtensionTest : public PreprocessorTest
-{
-};
-
-TEST_F(ExtensionTest, Valid)
-{
-    const char* str = "#extension foo : bar\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handleExtension(pp::SourceLocation(0, 1), "foo", "bar"));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(ExtensionTest, Comments)
-{
-    const char* str = "/*foo*/"
-                      "#"
-                      "/*foo*/"
-                      "extension"
-                      "/*foo*/"
-                      "foo"
-                      "/*foo*/"
-                      ":"
-                      "/*foo*/"
-                      "bar"
-                      "/*foo*/"
-                      "//foo"
-                      "\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handleExtension(pp::SourceLocation(0, 1), "foo", "bar"));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(ExtensionTest, MissingNewline)
-{
-    const char* str = "#extension foo : bar";
-    const char* expected = "";
-
-    using testing::_;
-    // Directive successfully parsed.
-    EXPECT_CALL(mDirectiveHandler,
-                handleExtension(pp::SourceLocation(0, 1), "foo", "bar"));
-    // Error reported about EOF.
-    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
-
-    preprocess(str, expected);
-}
-
-struct ExtensionTestParam
-{
-    const char* str;
-    pp::Diagnostics::ID id;
-};
-
-using testing::WithParamInterface;
-class InvalidExtensionTest : public ExtensionTest,
-                             public WithParamInterface<ExtensionTestParam>
-{
-};
-
-TEST_P(InvalidExtensionTest, Identified)
-{
-    ExtensionTestParam param = GetParam();
-    const char* expected = "\n";
-
-    using testing::_;
-    // No handleExtension call.
-    EXPECT_CALL(mDirectiveHandler, handleExtension(_, _, _)).Times(0);
-    // Invalid extension directive call.
-    EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
-
-    preprocess(param.str, expected);
-}
-
-static const ExtensionTestParam kParams[] = {
-    {"#extension\n", pp::Diagnostics::INVALID_EXTENSION_DIRECTIVE},
-    {"#extension 1\n", pp::Diagnostics::INVALID_EXTENSION_NAME},
-    {"#extension foo bar\n", pp::Diagnostics::UNEXPECTED_TOKEN},
-    {"#extension foo : \n", pp::Diagnostics::INVALID_EXTENSION_DIRECTIVE},
-    {"#extension foo : 1\n", pp::Diagnostics::INVALID_EXTENSION_BEHAVIOR},
-    {"#extension foo : bar baz\n", pp::Diagnostics::UNEXPECTED_TOKEN}
-};
-INSTANTIATE_TEST_CASE_P(All, InvalidExtensionTest, testing::ValuesIn(kParams));
diff --git a/src/third_party/angle/tests/preprocessor_tests/identifier_test.cpp b/src/third_party/angle/tests/preprocessor_tests/identifier_test.cpp
deleted file mode 100644
index f2653b8..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/identifier_test.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-#define CLOSED_RANGE(x, y) testing::Range(x, static_cast<char>((y) + 1))
-
-class IdentifierTest : public PreprocessorTest
-{
-protected:
-    void expectIdentifier(const std::string& str)
-    {
-        const char* cstr = str.c_str();
-        ASSERT_TRUE(mPreprocessor.init(1, &cstr, 0));
-
-        pp::Token token;
-        mPreprocessor.lex(&token);
-        EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-        EXPECT_EQ(str, token.text);
-    }
-};
-
-class SingleLetterIdentifierTest : public IdentifierTest,
-                                   public testing::WithParamInterface<char>
-{
-};
-
-// This test covers identifier names of form [_a-zA-Z].
-TEST_P(SingleLetterIdentifierTest, Identified)
-{
-    std::string str(1, GetParam());
-    expectIdentifier(str);
-}
-
-// Test string: '_'
-INSTANTIATE_TEST_CASE_P(Underscore,
-                        SingleLetterIdentifierTest,
-                        testing::Values('_'));
-
-// Test string: [a-z]
-INSTANTIATE_TEST_CASE_P(a_z,
-                        SingleLetterIdentifierTest,
-                        CLOSED_RANGE('a', 'z'));
-
-// Test string: [A-Z]
-INSTANTIATE_TEST_CASE_P(A_Z,
-                        SingleLetterIdentifierTest,
-                        CLOSED_RANGE('A', 'Z'));
-
-typedef std::tr1::tuple<char, char> IdentifierParams;
-class DoubleLetterIdentifierTest :
-    public IdentifierTest,
-    public testing::WithParamInterface<IdentifierParams>
-{
-};
-
-// This test covers identifier names of form [_a-zA-Z][_a-zA-Z0-9].
-TEST_P(DoubleLetterIdentifierTest, Identified)
-{
-    std::string str;
-    str.push_back(std::tr1::get<0>(GetParam()));
-    str.push_back(std::tr1::get<1>(GetParam()));
-
-    expectIdentifier(str);
-}
-
-// Test string: "__"
-INSTANTIATE_TEST_CASE_P(Underscore_Underscore,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(testing::Values('_'),
-                                         testing::Values('_')));
-
-// Test string: "_"[a-z]
-INSTANTIATE_TEST_CASE_P(Underscore_a_z,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(testing::Values('_'),
-                                         CLOSED_RANGE('a', 'z')));
-
-// Test string: "_"[A-Z]
-INSTANTIATE_TEST_CASE_P(Underscore_A_Z,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(testing::Values('_'),
-                                         CLOSED_RANGE('A', 'Z')));
-
-// Test string: "_"[0-9]
-INSTANTIATE_TEST_CASE_P(Underscore_0_9,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(testing::Values('_'),
-                                         CLOSED_RANGE('0', '9')));
-
-// Test string: [a-z]"_"
-INSTANTIATE_TEST_CASE_P(a_z_Underscore,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(CLOSED_RANGE('a', 'z'),
-                                         testing::Values('_')));
-
-// Test string: [a-z][a-z]
-INSTANTIATE_TEST_CASE_P(a_z_a_z,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(CLOSED_RANGE('a', 'z'),
-                                         CLOSED_RANGE('a', 'z')));
-
-// Test string: [a-z][A-Z]
-INSTANTIATE_TEST_CASE_P(a_z_A_Z,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(CLOSED_RANGE('a', 'z'),
-                                         CLOSED_RANGE('A', 'Z')));
-
-// Test string: [a-z][0-9]
-INSTANTIATE_TEST_CASE_P(a_z_0_9,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(CLOSED_RANGE('a', 'z'),
-                                         CLOSED_RANGE('0', '9')));
-
-// Test string: [A-Z]"_"
-INSTANTIATE_TEST_CASE_P(A_Z_Underscore,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(CLOSED_RANGE('A', 'Z'),
-                                         testing::Values('_')));
-
-// Test string: [A-Z][a-z]
-INSTANTIATE_TEST_CASE_P(A_Z_a_z,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(CLOSED_RANGE('A', 'Z'),
-                                         CLOSED_RANGE('a', 'z')));
-
-// Test string: [A-Z][A-Z]
-INSTANTIATE_TEST_CASE_P(A_Z_A_Z,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(CLOSED_RANGE('A', 'Z'),
-                                         CLOSED_RANGE('A', 'Z')));
-
-// Test string: [A-Z][0-9]
-INSTANTIATE_TEST_CASE_P(A_Z_0_9,
-                        DoubleLetterIdentifierTest,
-                        testing::Combine(CLOSED_RANGE('A', 'Z'),
-                                         CLOSED_RANGE('0', '9')));
-
-// The tests above cover one-letter and various combinations of two-letter
-// identifier names. This test covers all characters in a single string.
-TEST_F(IdentifierTest, AllLetters)
-{
-    std::string str;
-    for (int c = 'a'; c <= 'z'; ++c)
-        str.push_back(c);
-
-    str.push_back('_');
-
-    for (int c = 'A'; c <= 'Z'; ++c)
-        str.push_back(c);
-
-    str.push_back('_');
-
-    for (int c = '0'; c <= '9'; ++c)
-        str.push_back(c);
-
-    expectIdentifier(str);
-}
diff --git a/src/third_party/angle/tests/preprocessor_tests/if_test.cpp b/src/third_party/angle/tests/preprocessor_tests/if_test.cpp
deleted file mode 100644
index 7a7548f..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/if_test.cpp
+++ /dev/null
@@ -1,835 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class IfTest : public PreprocessorTest
-{
-};
-
-TEST_F(IfTest, If_0)
-{
-    const char* str = "pass_1\n"
-                      "#if 0\n"
-                      "fail\n"
-                      "#endif\n"
-                      "pass_2\n";
-    const char* expected = "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, If_1)
-{
-    const char* str = "pass_1\n"
-                      "#if 1\n"
-                      "pass_2\n"
-                      "#endif\n"
-                      "pass_3\n";
-    const char* expected = "pass_1\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "pass_3\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, If_0_Else)
-{
-    const char* str = "pass_1\n"
-                      "#if 0\n"
-                      "fail\n"
-                      "#else\n"
-                      "pass_2\n"
-                      "#endif\n"
-                      "pass_3\n";
-    const char* expected = "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "pass_3\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, If_1_Else)
-{
-    const char* str = "pass_1\n"
-                      "#if 1\n"
-                      "pass_2\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n"
-                      "pass_3\n";
-    const char* expected = "pass_1\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_3\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, If_0_Elif)
-{
-    const char* str = "pass_1\n"
-                      "#if 0\n"
-                      "fail_1\n"
-                      "#elif 0\n"
-                      "fail_2\n"
-                      "#elif 1\n"
-                      "pass_2\n"
-                      "#elif 1\n"
-                      "fail_3\n"
-                      "#else\n"
-                      "fail_4\n"
-                      "#endif\n"
-                      "pass_3\n";
-    const char* expected = "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_3\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, If_1_Elif)
-{
-    const char* str = "pass_1\n"
-                      "#if 1\n"
-                      "pass_2\n"
-                      "#elif 0\n"
-                      "fail_1\n"
-                      "#elif 1\n"
-                      "fail_2\n"
-                      "#else\n"
-                      "fail_4\n"
-                      "#endif\n"
-                      "pass_3\n";
-    const char* expected = "pass_1\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_3\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, If_Elif_Else)
-{
-    const char* str = "pass_1\n"
-                      "#if 0\n"
-                      "fail_1\n"
-                      "#elif 0\n"
-                      "fail_2\n"
-                      "#elif 0\n"
-                      "fail_3\n"
-                      "#else\n"
-                      "pass_2\n"
-                      "#endif\n"
-                      "pass_3\n";
-    const char* expected = "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "pass_3\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, If_0_Nested)
-{
-    const char* str = "pass_1\n"
-                      "#if 0\n"
-                      "fail_1\n"
-                      "#if 1\n"
-                      "fail_2\n"
-                      "#else\n"
-                      "fail_3\n"
-                      "#endif\n"
-                      "#else\n"
-                      "pass_2\n"
-                      "#endif\n"
-                      "pass_3\n";
-    const char* expected = "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "pass_3\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, If_1_Nested)
-{
-    const char* str = "pass_1\n"
-                      "#if 1\n"
-                      "pass_2\n"
-                      "#if 1\n"
-                      "pass_3\n"
-                      "#else\n"
-                      "fail_1\n"
-                      "#endif\n"
-                      "#else\n"
-                      "fail_2\n"
-                      "#endif\n"
-                      "pass_4\n";
-    const char* expected = "pass_1\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "pass_3\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_4\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorPrecedence)
-{
-    const char* str = "#if 1 + 2 * 3 + - (26 % 17 - + 4 / 2)\n"
-                      "fail_1\n"
-                      "#else\n"
-                      "pass_1\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "pass_1\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorDefined)
-{
-    const char* str = "#if defined foo\n"
-                      "fail_1\n"
-                      "#else\n"
-                      "pass_1\n"
-                      "#endif\n"
-                      "#define foo\n"
-                      "#if defined(foo)\n"
-                      "pass_2\n"
-                      "#else\n"
-                      "fail_2\n"
-                      "#endif\n"
-                      "#undef foo\n"
-                      "#if defined ( foo ) \n"
-                      "fail_3\n"
-                      "#else\n"
-                      "pass_3\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_3\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorEQ)
-{
-    const char* str = "#if 4 - 1 == 2 + 1\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorNE)
-{
-    const char* str = "#if 1 != 2\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorLess)
-{
-    const char* str = "#if 1 < 2\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorGreater)
-{
-    const char* str = "#if 2 > 1\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorLE)
-{
-    const char* str = "#if 1 <= 2\n"
-                      "pass_1\n"
-                      "#else\n"
-                      "fail_1\n"
-                      "#endif\n"
-                      "#if 2 <= 2\n"
-                      "pass_2\n"
-                      "#else\n"
-                      "fail_2\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorGE)
-{
-    const char* str = "#if 2 >= 1\n"
-                      "pass_1\n"
-                      "#else\n"
-                      "fail_1\n"
-                      "#endif\n"
-                      "#if 2 >= 2\n"
-                      "pass_2\n"
-                      "#else\n"
-                      "fail_2\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorBitwiseOR)
-{
-    const char* str = "#if (0xaaaaaaaa | 0x55555555) == 0xffffffff\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorBitwiseAND)
-{
-    const char* str = "#if (0xaaaaaaa & 0x5555555) == 0\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorBitwiseXOR)
-{
-    const char* str = "#if (0xaaaaaaa ^ 0x5555555) == 0xfffffff\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorBitwiseComplement)
-{
-    const char* str = "#if (~ 0xdeadbeef) == -3735928560\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorLeft)
-{
-    const char* str = "#if (1 << 12) == 4096\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, OperatorRight)
-{
-    const char* str = "#if (31762 >> 8) == 124\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, ExpressionWithMacros)
-{
-    const char* str = "#define one 1\n"
-                      "#define two 2\n"
-                      "#define three 3\n"
-                      "#if one + two == three\n"
-                      "pass\n"
-                      "#else\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, JunkInsideExcludedBlockIgnored)
-{
-    const char* str = "#if 0\n"
-                      "foo !@#$%^&* .1bar\n"
-                      "#foo\n"
-                      "#if bar\n"
-                      "fail\n"
-                      "#endif\n"
-                      "#else\n"
-                      "pass\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, Ifdef)
-{
-    const char* str = "#define foo\n"
-                      "#ifdef foo\n"
-                      "pass_1\n"
-                      "#else\n"
-                      "fail_1\n"
-                      "#endif\n"
-                      "#undef foo\n"
-                      "#ifdef foo\n"
-                      "fail_2\n"
-                      "#else\n"
-                      "pass_2\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "\n"
-                           "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, Ifndef)
-{
-    const char* str = "#define foo\n"
-                      "#ifndef foo\n"
-                      "fail_1\n"
-                      "#else\n"
-                      "pass_1\n"
-                      "#endif\n"
-                      "#undef foo\n"
-                      "#ifndef foo\n"
-                      "pass_2\n"
-                      "#else\n"
-                      "fail_2\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_1\n"
-                           "\n"
-                           "\n"
-                           "\n"
-                           "pass_2\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, MissingExpression)
-{
-    const char* str = "#if\n"
-                      "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::INVALID_EXPRESSION,
-                      pp::SourceLocation(0, 1),
-                      "syntax error"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, DivisionByZero)
-{
-    const char* str = "#if 1 / (3 - (1 + 2))\n"
-                      "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::DIVISION_BY_ZERO,
-                      pp::SourceLocation(0, 1), "1 / 0"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, ModuloByZero)
-{
-    const char* str = "#if 1 % (3 - (1 + 2))\n"
-                      "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::DIVISION_BY_ZERO,
-                      pp::SourceLocation(0, 1), "1 % 0"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, DecIntegerOverflow)
-{
-    const char* str = "#if 4294967296\n"
-                      "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::INTEGER_OVERFLOW,
-                      pp::SourceLocation(0, 1), "4294967296"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, OctIntegerOverflow)
-{
-    const char* str = "#if 077777777777\n"
-                      "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::INTEGER_OVERFLOW,
-                      pp::SourceLocation(0, 1), "077777777777"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, HexIntegerOverflow)
-{
-    const char* str = "#if 0xfffffffff\n"
-                      "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::INTEGER_OVERFLOW,
-                      pp::SourceLocation(0, 1), "0xfffffffff"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, UndefinedMacro)
-{
-    const char* str = "#if UNDEFINED\n"
-                      "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::INVALID_EXPRESSION,
-                      pp::SourceLocation(0, 1),
-                      "syntax error"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
-                      pp::SourceLocation(0, 1),
-                      "UNDEFINED"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, InvalidExpressionIgnoredForExcludedElif)
-{
-    const char* str = "#if 1\n"
-                      "pass\n"
-                      "#elif UNDEFINED\n"
-                      "fail\n"
-                      "#endif\n";
-    const char* expected = "\n"
-                           "pass\n"
-                           "\n"
-                           "\n"
-                           "\n";
-
-    // No error or warning.
-    using testing::_;
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(IfTest, ElseWithoutIf)
-{
-    const char* str = "#else\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF,
-                      pp::SourceLocation(0, 1),
-                      "else"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, ElifWithoutIf)
-{
-    const char* str = "#elif 1\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF,
-                      pp::SourceLocation(0, 1),
-                      "elif"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, EndifWithoutIf)
-{
-    const char* str = "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF,
-                      pp::SourceLocation(0, 1),
-                      "endif"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, ElseAfterElse)
-{
-    const char* str = "#if 1\n"
-                      "#else\n"
-                      "#else\n"
-                      "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE,
-                      pp::SourceLocation(0, 3),
-                      "else"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, ElifAfterElse)
-{
-    const char* str = "#if 1\n"
-                      "#else\n"
-                      "#elif 0\n"
-                      "#endif\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE,
-                      pp::SourceLocation(0, 3),
-                      "elif"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, UnterminatedIf)
-{
-    const char* str = "#if 1\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::CONDITIONAL_UNTERMINATED,
-                      pp::SourceLocation(0, 1),
-                      "if"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-TEST_F(IfTest, UnterminatedIfdef)
-{
-    const char* str = "#ifdef foo\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::CONDITIONAL_UNTERMINATED,
-                      pp::SourceLocation(0, 1),
-                      "ifdef"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
diff --git a/src/third_party/angle/tests/preprocessor_tests/input_test.cpp b/src/third_party/angle/tests/preprocessor_tests/input_test.cpp
deleted file mode 100644
index b6a132a..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/input_test.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Input.h"
-#include "Token.h"
-
-class InitTest : public PreprocessorTest
-{
-};
-
-TEST_F(InitTest, NegativeCount)
-{
-    EXPECT_FALSE(mPreprocessor.init(-1, NULL, NULL));
-}
-
-TEST_F(InitTest, ZeroCount)
-{
-    EXPECT_TRUE(mPreprocessor.init(0, NULL, NULL));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::LAST, token.type);
-}
-
-TEST_F(InitTest, NullString)
-{
-    EXPECT_FALSE(mPreprocessor.init(1, NULL, NULL));
-}
-
-TEST(InputTest, DefaultConstructor)
-{
-    pp::Input input;
-    EXPECT_EQ(0, input.count());
-    EXPECT_EQ(0, input.read(NULL, 1));
-}
-
-TEST(InputTest, NullLength)
-{
-    const char* str[] = {"foo"};
-    pp::Input input(1, str, NULL);
-    EXPECT_EQ(3, input.length(0));
-}
-
-TEST(InputTest, NegativeLength)
-{
-    const char* str[] = {"foo"};
-    int length[] = {-1};
-    pp::Input input(1, str, length);
-    EXPECT_EQ(3, input.length(0));
-}
-
-TEST(InputTest, ActualLength)
-{
-    const char* str[] = {"foobar"};
-    int length[] = {3};
-    pp::Input input(1, str, length);
-    // Note that strlen(str[0]) != length[0].
-    // Even then Input should just accept any non-negative number.
-    EXPECT_EQ(length[0], input.length(0));
-}
-
-TEST(InputTest, String)
-{
-    const char* str[] = {"foo"};
-    pp::Input input(1, str, NULL);
-    EXPECT_STREQ(str[0], input.string(0));
-}
-
-TEST(InputTest, ReadSingleString)
-{
-    int count = 1;
-    const char* str[] = {"foo"};
-    char buf[4] = {'\0', '\0', '\0', '\0'};
-
-    int maxSize = 1;
-    pp::Input input1(count, str, NULL);
-    EXPECT_EQ(1, input1.read(buf, maxSize));
-    EXPECT_EQ('f', buf[0]);
-    EXPECT_EQ(1, input1.read(buf, maxSize));
-    EXPECT_EQ('o', buf[0]);
-    EXPECT_EQ(1, input1.read(buf, maxSize));
-    EXPECT_EQ('o', buf[0]);
-    EXPECT_EQ(0, input1.read(buf, maxSize));
-
-    maxSize = 2;
-    pp::Input input2(count, str, NULL);
-    EXPECT_EQ(2, input2.read(buf, maxSize));
-    EXPECT_STREQ("fo", buf);
-    EXPECT_EQ(1, input2.read(buf, maxSize));
-    EXPECT_EQ('o', buf[0]);
-    EXPECT_EQ(0, input2.read(buf, maxSize));
-
-    maxSize = 3;
-    pp::Input input3(count, str, NULL);
-    EXPECT_EQ(3, input3.read(buf, maxSize));
-    EXPECT_STREQ("foo", buf);
-    EXPECT_EQ(0, input3.read(buf, maxSize));
-
-    maxSize = 4;
-    pp::Input input4(count, str, NULL);
-    EXPECT_EQ(3, input4.read(buf, maxSize));
-    EXPECT_STREQ("foo", buf);
-    EXPECT_EQ(0, input4.read(buf, maxSize));
-}
-
-TEST(InputTest, ReadMultipleStrings)
-{
-    int count = 3;
-    const char* str[] = {"f", "o", "o"};
-    char buf[4] = {'\0', '\0', '\0', '\0'};
-
-    int maxSize = 1;
-    pp::Input input1(count, str, NULL);
-    EXPECT_EQ(1, input1.read(buf, maxSize));
-    EXPECT_EQ('f', buf[0]);
-    EXPECT_EQ(1, input1.read(buf, maxSize));
-    EXPECT_EQ('o', buf[0]);
-    EXPECT_EQ(1, input1.read(buf, maxSize));
-    EXPECT_EQ('o', buf[0]);
-    EXPECT_EQ(0, input1.read(buf, maxSize));
-
-    maxSize = 2;
-    pp::Input input2(count, str, NULL);
-    EXPECT_EQ(2, input2.read(buf, maxSize));
-    EXPECT_STREQ("fo", buf);
-    EXPECT_EQ(1, input2.read(buf, maxSize));
-    EXPECT_EQ('o', buf[0]);
-    EXPECT_EQ(0, input2.read(buf, maxSize));
-
-    maxSize = 3;
-    pp::Input input3(count, str, NULL);
-    EXPECT_EQ(3, input3.read(buf, maxSize));
-    EXPECT_STREQ("foo", buf);
-    EXPECT_EQ(0, input3.read(buf, maxSize));
-
-    maxSize = 4;
-    pp::Input input4(count, str, NULL);
-    EXPECT_EQ(3, input4.read(buf, maxSize));
-    EXPECT_STREQ("foo", buf);
-    EXPECT_EQ(0, input4.read(buf, maxSize));
-}
-
-TEST(InputTest, ReadStringsWithLength)
-{
-    int count = 2;
-    const char* str[] = {"foo", "bar"};
-    // Note that the length for the first string is 2 which is less than
-    // strlen(str[0]. We want to make sure that the last character is ignored.
-    int length[] = {2, 3};
-    char buf[6] = {'\0', '\0', '\0', '\0', '\0', '\0'};
-    int maxSize = 5;
-
-    pp::Input input(count, str, length);
-    EXPECT_EQ(maxSize, input.read(buf, maxSize));
-    EXPECT_STREQ("fobar", buf);
-}
-
diff --git a/src/third_party/angle/tests/preprocessor_tests/location_test.cpp b/src/third_party/angle/tests/preprocessor_tests/location_test.cpp
deleted file mode 100644
index b615f99..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/location_test.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class LocationTest : public PreprocessorTest
-{
-protected:
-    void expectLocation(int count,
-                        const char* const string[],
-                        const int length[],
-                        const pp::SourceLocation& location)
-    {
-        ASSERT_TRUE(mPreprocessor.init(count, string, length));
-
-        pp::Token token;
-        mPreprocessor.lex(&token);
-        EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-        EXPECT_EQ("foo", token.text);
-
-        EXPECT_EQ(location.file, token.location.file);
-        EXPECT_EQ(location.line, token.location.line);
-    }
-};
-
-TEST_F(LocationTest, String0_Line1)
-{
-    const char* str = "foo";
-    pp::SourceLocation loc(0, 1);
-
-    SCOPED_TRACE("String0_Line1");
-    expectLocation(1, &str, NULL, loc);
-}
-
-TEST_F(LocationTest, String0_Line2)
-{
-    const char* str = "\nfoo";
-    pp::SourceLocation loc(0, 2);
-
-    SCOPED_TRACE("String0_Line2");
-    expectLocation(1, &str, NULL, loc);
-}
-
-TEST_F(LocationTest, String1_Line1)
-{
-    const char* const str[] = {"\n\n", "foo"};
-    pp::SourceLocation loc(1, 1);
-
-    SCOPED_TRACE("String1_Line1");
-    expectLocation(2, str, NULL, loc);
-}
-
-TEST_F(LocationTest, String1_Line2)
-{
-    const char* const str[] = {"\n\n", "\nfoo"};
-    pp::SourceLocation loc(1, 2);
-
-    SCOPED_TRACE("String1_Line2");
-    expectLocation(2, str, NULL, loc);
-}
-
-TEST_F(LocationTest, NewlineInsideCommentCounted)
-{
-    const char* str = "/*\n\n*/foo";
-    pp::SourceLocation loc(0, 3);
-
-    SCOPED_TRACE("NewlineInsideCommentCounted");
-    expectLocation(1, &str, NULL, loc);
-}
-
-TEST_F(LocationTest, ErrorLocationAfterComment)
-{
-    const char* str = "/*\n\n*/@";
-
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
-    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::INVALID_CHARACTER,
-                                    pp::SourceLocation(0, 3),
-                                    "@"));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-// The location of a token straddling two or more strings is that of the
-// first character of the token.
-
-TEST_F(LocationTest, TokenStraddlingTwoStrings)
-{
-    const char* const str[] = {"f", "oo"};
-    pp::SourceLocation loc(0, 1);
-
-    SCOPED_TRACE("TokenStraddlingTwoStrings");
-    expectLocation(2, str, NULL, loc);
-}
-
-TEST_F(LocationTest, TokenStraddlingThreeStrings)
-{
-    const char* const str[] = {"f", "o", "o"};
-    pp::SourceLocation loc(0, 1);
-
-    SCOPED_TRACE("TokenStraddlingThreeStrings");
-    expectLocation(3, str, NULL, loc);
-}
-
-TEST_F(LocationTest, EndOfFileWithoutNewline)
-{
-    const char* const str[] = {"foo"};
-    ASSERT_TRUE(mPreprocessor.init(1, str, NULL));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ("foo", token.text);
-    EXPECT_EQ(0, token.location.file);
-    EXPECT_EQ(1, token.location.line);
-
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::LAST, token.type);
-    EXPECT_EQ(0, token.location.file);
-    EXPECT_EQ(1, token.location.line);
-}
-
-TEST_F(LocationTest, EndOfFileAfterNewline)
-{
-    const char* const str[] = {"foo\n"};
-    ASSERT_TRUE(mPreprocessor.init(1, str, NULL));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ("foo", token.text);
-    EXPECT_EQ(0, token.location.file);
-    EXPECT_EQ(1, token.location.line);
-
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::LAST, token.type);
-    EXPECT_EQ(0, token.location.file);
-    EXPECT_EQ(2, token.location.line);
-}
-
-TEST_F(LocationTest, EndOfFileAfterEmptyString)
-{
-    const char* const str[] = {"foo\n", "\n", ""};
-    ASSERT_TRUE(mPreprocessor.init(3, str, NULL));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ("foo", token.text);
-    EXPECT_EQ(0, token.location.file);
-    EXPECT_EQ(1, token.location.line);
-
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::LAST, token.type);
-    EXPECT_EQ(2, token.location.file);
-    EXPECT_EQ(1, token.location.line);
-}
-
-TEST_F(LocationTest, ValidLineDirective1)
-{
-    const char* str = "#line 10\n"
-                      "foo";
-    pp::SourceLocation loc(0, 10);
-
-    SCOPED_TRACE("ValidLineDirective1");
-    expectLocation(1, &str, NULL, loc);
-}
-
-TEST_F(LocationTest, ValidLineDirective2)
-{
-    const char* str = "#line 10 20\n"
-                      "foo";
-    pp::SourceLocation loc(20, 10);
-
-    SCOPED_TRACE("ValidLineDirective2");
-    expectLocation(1, &str, NULL, loc);
-}
-
-TEST_F(LocationTest, LineDirectiveCommentsIgnored)
-{
-    const char* str = "/* bar */"
-                      "#"
-                      "/* bar */"
-                      "line"
-                      "/* bar */"
-                      "10"
-                      "/* bar */"
-                      "20"
-                      "/* bar */"
-                      "// bar   "
-                      "\n"
-                      "foo";
-    pp::SourceLocation loc(20, 10);
-
-    SCOPED_TRACE("LineDirectiveCommentsIgnored");
-    expectLocation(1, &str, NULL, loc);
-}
-
-TEST_F(LocationTest, LineDirectiveWithMacro1)
-{
-    const char* str = "#define L 10\n"
-                      "#define F(x) x\n"
-                      "#line L F(20)\n"
-                      "foo";
-    pp::SourceLocation loc(20, 10);
-
-    SCOPED_TRACE("LineDirectiveWithMacro1");
-    expectLocation(1, &str, NULL, loc);
-}
-
-TEST_F(LocationTest, LineDirectiveWithMacro2)
-{
-    const char* str = "#define LOC 10 20\n"
-                      "#line LOC\n"
-                      "foo";
-    pp::SourceLocation loc(20, 10);
-
-    SCOPED_TRACE("LineDirectiveWithMacro2");
-    expectLocation(1, &str, NULL, loc);
-}
-
-TEST_F(LocationTest, LineDirectiveWithPredefinedMacro)
-{
-    const char* str = "#line __LINE__ __FILE__\n"
-                      "foo";
-    pp::SourceLocation loc(0, 1);
-
-    SCOPED_TRACE("LineDirectiveWithMacro");
-    expectLocation(1, &str, NULL, loc);
-}
-
-TEST_F(LocationTest, LineDirectiveNewlineBeforeStringBreak)
-{
-    const char* const str[] = {"#line 10 20\n", "foo"};
-    // String number is incremented after it is set by the line directive.
-    // Also notice that line number is reset after the string break.
-    pp::SourceLocation loc(21, 1);
-
-    SCOPED_TRACE("LineDirectiveNewlineBeforeStringBreak");
-    expectLocation(2, str, NULL, loc);
-}
-
-TEST_F(LocationTest, LineDirectiveNewlineAfterStringBreak)
-{
-    const char* const str[] = {"#line 10 20", "\nfoo"};
-    // String number is incremented before it is set by the line directive.
-    pp::SourceLocation loc(20, 10);
-
-    SCOPED_TRACE("LineDirectiveNewlineAfterStringBreak");
-    expectLocation(2, str, NULL, loc);
-}
-
-TEST_F(LocationTest, LineDirectiveMissingNewline)
-{
-    const char* str = "#line 10";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
-
-    using testing::_;
-    // Error reported about EOF.
-    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-struct LineTestParam
-{
-    const char* str;
-    pp::Diagnostics::ID id;
-};
-
-class InvalidLineTest : public LocationTest,
-                        public testing::WithParamInterface<LineTestParam>
-{
-};
-
-TEST_P(InvalidLineTest, Identified)
-{
-    LineTestParam param = GetParam();
-    ASSERT_TRUE(mPreprocessor.init(1, &param.str, NULL));
-
-    using testing::_;
-    // Invalid line directive call.
-    EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-static const LineTestParam kParams[] = {
-    {"#line\n", pp::Diagnostics::INVALID_LINE_DIRECTIVE},
-    {"#line foo\n", pp::Diagnostics::INVALID_LINE_NUMBER},
-    {"#line 10 foo\n", pp::Diagnostics::INVALID_FILE_NUMBER},
-    {"#line 10 20 foo\n", pp::Diagnostics::UNEXPECTED_TOKEN},
-    {"#line 0xffffffff\n", pp::Diagnostics::INTEGER_OVERFLOW},
-    {"#line 10 0xffffffff\n", pp::Diagnostics::INTEGER_OVERFLOW}
-};
-
-INSTANTIATE_TEST_CASE_P(All, InvalidLineTest, testing::ValuesIn(kParams));
diff --git a/src/third_party/angle/tests/preprocessor_tests/number_test.cpp b/src/third_party/angle/tests/preprocessor_tests/number_test.cpp
deleted file mode 100644
index 1367321..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/number_test.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-#define CLOSED_RANGE(x, y) testing::Range(x, static_cast<char>((y) + 1))
-
-class InvalidNumberTest : public PreprocessorTest,
-                          public testing::WithParamInterface<const char*>
-{
-};
-
-TEST_P(InvalidNumberTest, InvalidNumberIdentified)
-{
-    const char* str = GetParam();
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    using testing::_;
-    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::INVALID_NUMBER, _, str));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-}
-
-INSTANTIATE_TEST_CASE_P(InvalidIntegers, InvalidNumberTest,
-                        testing::Values("1a", "08", "0xG"));
-
-
-INSTANTIATE_TEST_CASE_P(InvalidFloats, InvalidNumberTest,
-                        testing::Values("1eg", "0.a", "0.1.2", ".0a", ".0.1"));
-
-typedef std::tr1::tuple<const char*, char> IntegerParams;
-class IntegerTest : public PreprocessorTest,
-                    public testing::WithParamInterface<IntegerParams>
-{
-};
-
-TEST_P(IntegerTest, Identified)
-{
-    std::string str(std::tr1::get<0>(GetParam()));  // prefix.
-    str.push_back(std::tr1::get<1>(GetParam()));  // digit.
-    const char* cstr = str.c_str();
-
-    ASSERT_TRUE(mPreprocessor.init(1, &cstr, 0));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::CONST_INT, token.type);
-    EXPECT_EQ(str, token.text);
-}
-
-INSTANTIATE_TEST_CASE_P(DecimalInteger,
-                        IntegerTest,
-                        testing::Combine(testing::Values(""),
-                                         CLOSED_RANGE('0', '9')));
-
-INSTANTIATE_TEST_CASE_P(OctalInteger,
-                        IntegerTest,
-                        testing::Combine(testing::Values("0"),
-                                         CLOSED_RANGE('0', '7')));
-
-INSTANTIATE_TEST_CASE_P(HexadecimalInteger_0_9,
-                        IntegerTest,
-                        testing::Combine(testing::Values("0x", "0X"),
-                                         CLOSED_RANGE('0', '9')));
-
-INSTANTIATE_TEST_CASE_P(HexadecimalInteger_a_f,
-                        IntegerTest,
-                        testing::Combine(testing::Values("0x", "0X"),
-                                         CLOSED_RANGE('a', 'f')));
-
-INSTANTIATE_TEST_CASE_P(HexadecimalInteger_A_F,
-                        IntegerTest,
-                        testing::Combine(testing::Values("0x", "0X"),
-                                         CLOSED_RANGE('A', 'F')));
-
-class FloatTest : public PreprocessorTest
-{
-  protected:
-    void expectFloat(const std::string& str)
-    {
-        const char* cstr = str.c_str();
-        ASSERT_TRUE(mPreprocessor.init(1, &cstr, 0));
-
-        pp::Token token;
-        mPreprocessor.lex(&token);
-        EXPECT_EQ(pp::Token::CONST_FLOAT, token.type);
-        EXPECT_EQ(str, token.text);
-    }
-};
-
-typedef std::tr1::tuple<char, char, const char*, char> FloatScientificParams;
-class FloatScientificTest :
-    public FloatTest,
-    public testing::WithParamInterface<FloatScientificParams>
-{
-};
-
-// This test covers floating point numbers of form [0-9][eE][+-]?[0-9].
-TEST_P(FloatScientificTest, FloatIdentified)
-{
-    std::string str;
-    str.push_back(std::tr1::get<0>(GetParam()));  // significand [0-9].
-    str.push_back(std::tr1::get<1>(GetParam()));  // separator [eE].
-    str.append(std::tr1::get<2>(GetParam()));  // sign [" " "+" "-"].
-    str.push_back(std::tr1::get<3>(GetParam()));  // exponent [0-9].
-
-    SCOPED_TRACE("FloatScientificTest");
-    expectFloat(str);
-}
-
-INSTANTIATE_TEST_CASE_P(FloatScientific,
-                        FloatScientificTest,
-                        testing::Combine(CLOSED_RANGE('0', '9'),
-                                         testing::Values('e', 'E'),
-                                         testing::Values("", "+", "-"),
-                                         CLOSED_RANGE('0', '9')));
-
-typedef std::tr1::tuple<char, char> FloatFractionParams;
-class FloatFractionTest :
-    public FloatTest,
-    public testing::WithParamInterface<FloatFractionParams>
-{
-};
-
-// This test covers floating point numbers of form [0-9]"." and [0-9]?"."[0-9].
-TEST_P(FloatFractionTest, FloatIdentified)
-{
-    std::string str;
-
-    char significand = std::tr1::get<0>(GetParam());
-    if (significand != '\0')
-        str.push_back(significand);
-
-    str.push_back('.');
-
-    char fraction = std::tr1::get<1>(GetParam());
-    if (fraction != '\0')
-        str.push_back(fraction);
-
-    SCOPED_TRACE("FloatFractionTest");
-    expectFloat(str);
-}
-
-INSTANTIATE_TEST_CASE_P(FloatFraction_X_X,
-                        FloatFractionTest,
-                        testing::Combine(CLOSED_RANGE('0', '9'),
-                                         CLOSED_RANGE('0', '9')));
-
-INSTANTIATE_TEST_CASE_P(FloatFraction_0_X,
-                        FloatFractionTest,
-                        testing::Combine(testing::Values('\0'),
-                                         CLOSED_RANGE('0', '9')));
-
-INSTANTIATE_TEST_CASE_P(FloatFraction_X_0,
-                        FloatFractionTest,
-                        testing::Combine(CLOSED_RANGE('0', '9'),
-                                         testing::Values('\0')));
-
-// In the tests above we have tested individual parts of a float separately.
-// This test has all parts of a float.
-TEST_F(FloatTest, FractionScientific)
-{
-    SCOPED_TRACE("FractionScientific");
-    expectFloat("0.1e+2");
-}
diff --git a/src/third_party/angle/tests/preprocessor_tests/operator_test.cpp b/src/third_party/angle/tests/preprocessor_tests/operator_test.cpp
deleted file mode 100644
index d73bec6..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/operator_test.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-struct OperatorTestParam
-{
-    const char* str;
-    int op;
-};
-
-class OperatorTest : public PreprocessorTest,
-                     public testing::WithParamInterface<OperatorTestParam>
-{
-};
-
-TEST_P(OperatorTest, Identified)
-{
-    OperatorTestParam param = GetParam();
-
-    ASSERT_TRUE(mPreprocessor.init(1, &param.str, 0));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(param.op, token.type);
-    EXPECT_EQ(param.str, token.text);
-}
-
-static const OperatorTestParam kOperators[] = {
-    {"(", '('},
-    {")", ')'},
-    {"[", '['},
-    {"]", ']'},
-    {".", '.'},
-    {"+", '+'},
-    {"-", '-'},
-    {"~", '~'},
-    {"!", '!'},
-    {"*", '*'},
-    {"/", '/'},
-    {"%", '%'},
-    {"<", '<'},
-    {">", '>'},
-    {"&", '&'},
-    {"^", '^'},
-    {"|", '|'},
-    {"?", '?'},
-    {":", ':'},
-    {"=", '='},
-    {",", ','},
-    {"++",  pp::Token::OP_INC},
-    {"--",  pp::Token::OP_DEC},
-    {"<<",  pp::Token::OP_LEFT},
-    {">>",  pp::Token::OP_RIGHT},
-    {"<=",  pp::Token::OP_LE},
-    {">=",  pp::Token::OP_GE},
-    {"==",  pp::Token::OP_EQ},
-    {"!=",  pp::Token::OP_NE},
-    {"&&",  pp::Token::OP_AND},
-    {"^^",  pp::Token::OP_XOR},
-    {"||",  pp::Token::OP_OR},
-    {"+=",  pp::Token::OP_ADD_ASSIGN},
-    {"-=",  pp::Token::OP_SUB_ASSIGN},
-    {"*=",  pp::Token::OP_MUL_ASSIGN},
-    {"/=",  pp::Token::OP_DIV_ASSIGN},
-    {"%=",  pp::Token::OP_MOD_ASSIGN},
-    {"<<=", pp::Token::OP_LEFT_ASSIGN},
-    {">>=", pp::Token::OP_RIGHT_ASSIGN},
-    {"&=",  pp::Token::OP_AND_ASSIGN},
-    {"^=",  pp::Token::OP_XOR_ASSIGN},
-    {"|=",  pp::Token::OP_OR_ASSIGN}
-};
-
-INSTANTIATE_TEST_CASE_P(All, OperatorTest,
-                        testing::ValuesIn(kOperators));
-
diff --git a/src/third_party/angle/tests/preprocessor_tests/pragma_test.cpp b/src/third_party/angle/tests/preprocessor_tests/pragma_test.cpp
deleted file mode 100644
index a76fada..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/pragma_test.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class PragmaTest : public PreprocessorTest
-{
-};
-
-TEST_F(PragmaTest, EmptyName)
-{
-    const char* str = "#pragma\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    // No handlePragma calls.
-    EXPECT_CALL(mDirectiveHandler, handlePragma(_, _, _)).Times(0);
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(PragmaTest, EmptyValue)
-{
-    const char* str = "#pragma foo\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handlePragma(pp::SourceLocation(0, 1), "foo", ""));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(PragmaTest, NameValue)
-{
-    const char* str = "#pragma foo(bar)\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handlePragma(pp::SourceLocation(0, 1), "foo", "bar"));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(PragmaTest, Comments)
-{
-    const char* str = "/*foo*/"
-                      "#"
-                      "/*foo*/"
-                      "pragma"
-                      "/*foo*/"
-                      "foo"
-                      "/*foo*/"
-                      "("
-                      "/*foo*/"
-                      "bar"
-                      "/*foo*/"
-                      ")"
-                      "/*foo*/"
-                      "//foo"
-                      "\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handlePragma(pp::SourceLocation(0, 1), "foo", "bar"));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(PragmaTest, MissingNewline)
-{
-    const char* str = "#pragma foo(bar)";
-    const char* expected = "";
-
-    using testing::_;
-    // Pragma successfully parsed.
-    EXPECT_CALL(mDirectiveHandler,
-                handlePragma(pp::SourceLocation(0, 1), "foo", "bar"));
-    // Error reported about EOF.
-    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
-
-    preprocess(str, expected);
-}
-
-class InvalidPragmaTest : public PragmaTest,
-                          public testing::WithParamInterface<const char*>
-{
-};
-
-TEST_P(InvalidPragmaTest, Identified)
-{
-    const char* str = GetParam();
-    const char* expected = "\n";
-
-    using testing::_;
-    // No handlePragma calls.
-    EXPECT_CALL(mDirectiveHandler, handlePragma(_, _, _)).Times(0);
-    // Unrecognized pragma warning.
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::UNRECOGNIZED_PRAGMA,
-                      pp::SourceLocation(0, 1), _));
-
-    preprocess(str, expected);
-}
-
-INSTANTIATE_TEST_CASE_P(All, InvalidPragmaTest, testing::Values(
-    "#pragma 1\n",               // Invalid name.
-    "#pragma foo()\n",           // Missing value.
-    "#pragma foo bar)\n",        // Missing left paren,
-    "#pragma foo(bar\n",         // Missing right paren.
-    "#pragma foo bar\n",         // Missing parens.
-    "#pragma foo(bar) baz\n"));  // Extra tokens.
diff --git a/src/third_party/angle/tests/preprocessor_tests/space_test.cpp b/src/third_party/angle/tests/preprocessor_tests/space_test.cpp
deleted file mode 100644
index c6b70c5..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/space_test.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class SpaceTest : public PreprocessorTest
-{
-  protected:
-    void expectSpace(const std::string& str)
-    {
-        const char* cstr = str.c_str();
-        ASSERT_TRUE(mPreprocessor.init(1, &cstr, 0));
-
-        pp::Token token;
-        // "foo" is returned after ignoring the whitespace characters.
-        mPreprocessor.lex(&token);
-        EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-        EXPECT_EQ("foo", token.text);
-        // The whitespace character is however recorded with the next token.
-        EXPECT_TRUE(token.hasLeadingSpace());
-    }
-};
-
-// Whitespace characters allowed in GLSL.
-// Note that newline characters (\n) will be tested separately.
-static const char kSpaceChars[] = {' ', '\t', '\v', '\f'};
-
-// This test fixture tests the processing of a single whitespace character.
-// All tests in this fixture are ran with all possible whitespace character
-// allowed in GLSL.
-class SpaceCharTest : public SpaceTest,
-                      public testing::WithParamInterface<char>
-{
-};
-
-TEST_P(SpaceCharTest, SpaceIgnored)
-{
-    // Construct test string with the whitespace char before "foo".
-    std::string str(1, GetParam());
-    str.append("foo");
-
-    expectSpace(str);
-}
-
-INSTANTIATE_TEST_CASE_P(SingleSpaceChar,
-                        SpaceCharTest,
-                        testing::ValuesIn(kSpaceChars));
-
-// This test fixture tests the processing of a string containing consecutive
-// whitespace characters. All tests in this fixture are ran with all possible
-// combinations of whitespace characters allowed in GLSL.
-typedef std::tr1::tuple<char, char, char> SpaceStringParams;
-class SpaceStringTest : public SpaceTest,
-                        public testing::WithParamInterface<SpaceStringParams>
-{
-};
-
-TEST_P(SpaceStringTest, SpaceIgnored)
-{
-    // Construct test string with the whitespace char before "foo".
-    std::string str;
-    str.push_back(std::tr1::get<0>(GetParam()));
-    str.push_back(std::tr1::get<1>(GetParam()));
-    str.push_back(std::tr1::get<2>(GetParam()));
-    str.append("foo");
-
-    expectSpace(str);
-}
-
-INSTANTIATE_TEST_CASE_P(SpaceCharCombination,
-                        SpaceStringTest,
-                        testing::Combine(testing::ValuesIn(kSpaceChars),
-                                         testing::ValuesIn(kSpaceChars),
-                                         testing::ValuesIn(kSpaceChars)));
-
-// The tests above make sure that the space char is recorded in the
-// next token. This test makes sure that a token is not incorrectly marked
-// to have leading space.
-TEST_F(SpaceTest, LeadingSpace)
-{
-    const char* str = " foo+ -bar";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
-
-    pp::Token token;
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ("foo", token.text);
-    EXPECT_TRUE(token.hasLeadingSpace());
-
-    mPreprocessor.lex(&token);
-    EXPECT_EQ('+', token.type);
-    EXPECT_FALSE(token.hasLeadingSpace());
-
-    mPreprocessor.lex(&token);
-    EXPECT_EQ('-', token.type);
-    EXPECT_TRUE(token.hasLeadingSpace());
-
-    mPreprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ("bar", token.text);
-    EXPECT_FALSE(token.hasLeadingSpace());
-}
diff --git a/src/third_party/angle/tests/preprocessor_tests/token_test.cpp b/src/third_party/angle/tests/preprocessor_tests/token_test.cpp
deleted file mode 100644
index 323d468..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/token_test.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "gtest/gtest.h"
-
-#include "Token.h"
-
-TEST(TokenTest, DefaultConstructor)
-{
-    pp::Token token;
-    EXPECT_EQ(0, token.type);
-    EXPECT_EQ(0, token.flags);
-    EXPECT_EQ(0, token.location.line);
-    EXPECT_EQ(0, token.location.file);
-    EXPECT_EQ("", token.text);
-}
-
-TEST(TokenTest, Assignment)
-{
-    pp::Token token;
-    token.type = 1;
-    token.flags = 1;
-    token.location.line = 1;
-    token.location.file = 1;
-    token.text.assign("foo");
-
-    token = pp::Token();
-    EXPECT_EQ(0, token.type);
-    EXPECT_EQ(0, token.flags);
-    EXPECT_EQ(0, token.location.line);
-    EXPECT_EQ(0, token.location.file);
-    EXPECT_EQ("", token.text);
-}
-
-TEST(TokenTest, Equals)
-{
-    pp::Token token;
-    EXPECT_TRUE(token.equals(pp::Token()));
-
-    token.type = 1;
-    EXPECT_FALSE(token.equals(pp::Token()));
-    token.type = 0;
-
-    token.flags = 1;
-    EXPECT_FALSE(token.equals(pp::Token()));
-    token.flags = 0;
-
-    token.location.line = 1;
-    EXPECT_FALSE(token.equals(pp::Token()));
-    token.location.line = 0;
-
-    token.location.file = 1;
-    EXPECT_FALSE(token.equals(pp::Token()));
-    token.location.file = 0;
-
-    token.text.assign("foo");
-    EXPECT_FALSE(token.equals(pp::Token()));
-    token.text.clear();
-
-    EXPECT_TRUE(token.equals(pp::Token()));
-}
-
-TEST(TokenTest, HasLeadingSpace)
-{
-    pp::Token token;
-    EXPECT_FALSE(token.hasLeadingSpace());
-    token.setHasLeadingSpace(true);
-    EXPECT_TRUE(token.hasLeadingSpace());
-    token.setHasLeadingSpace(false);
-    EXPECT_FALSE(token.hasLeadingSpace());
-}
-
-TEST(TokenTest, Write)
-{
-    pp::Token token;
-    token.text.assign("foo");
-    std::stringstream out1;
-    out1 << token;
-    EXPECT_TRUE(out1.good());
-    EXPECT_EQ("foo", out1.str());
-
-    token.setHasLeadingSpace(true);
-    std::stringstream out2;
-    out2 << token;
-    EXPECT_TRUE(out2.good());
-    EXPECT_EQ(" foo", out2.str());
-}
diff --git a/src/third_party/angle/tests/preprocessor_tests/version_test.cpp b/src/third_party/angle/tests/preprocessor_tests/version_test.cpp
deleted file mode 100644
index 0db2fad..0000000
--- a/src/third_party/angle/tests/preprocessor_tests/version_test.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "PreprocessorTest.h"
-#include "Token.h"
-
-class VersionTest : public PreprocessorTest
-{
-};
-
-TEST_F(VersionTest, Valid)
-{
-    const char* str = "#version 200\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handleVersion(pp::SourceLocation(0, 1), 200));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(VersionTest, CommentsIgnored)
-{
-    const char* str = "/*foo*/"
-                      "#"
-                      "/*foo*/"
-                      "version"
-                      "/*foo*/"
-                      "200"
-                      "/*foo*/"
-                      "//foo"
-                      "\n";
-    const char* expected = "\n";
-
-    using testing::_;
-    EXPECT_CALL(mDirectiveHandler,
-                handleVersion(pp::SourceLocation(0, 1), 200));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-
-    preprocess(str, expected);
-}
-
-TEST_F(VersionTest, MissingNewline)
-{
-    const char* str = "#version 200";
-    const char* expected = "";
-
-    using testing::_;
-    // Directive successfully parsed.
-    EXPECT_CALL(mDirectiveHandler,
-                handleVersion(pp::SourceLocation(0, 1), 200));
-    // Error reported about EOF.
-    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
-
-    preprocess(str, expected);
-}
-
-TEST_F(VersionTest, AfterComments)
-{
-    const char* str = "/* block comment acceptable */\n"
-                      "// line comment acceptable\n"
-                      "#version 200\n";
-    const char* expected = "\n\n\n";
-
-    using testing::_;
-    // Directive successfully parsed.
-    EXPECT_CALL(mDirectiveHandler,
-                handleVersion(pp::SourceLocation(0, 3), 200));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-    
-    preprocess(str, expected);
-}
-
-TEST_F(VersionTest, AfterWhitespace)
-{
-    const char* str = "\n"
-                      "\n"
-                      "#version 200\n";
-    const char* expected = "\n\n\n";
-
-    using testing::_;
-    // Directive successfully parsed.
-    EXPECT_CALL(mDirectiveHandler,
-                handleVersion(pp::SourceLocation(0, 3), 200));
-    // No error or warning.
-    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
-    
-    preprocess(str, expected);
-}
-
-TEST_F(VersionTest, AfterValidToken)
-{
-    const char* str = "foo\n"
-                      "#version 200\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
-
-    using testing::_;
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::VERSION_NOT_FIRST_STATEMENT,
-                      pp::SourceLocation(0, 2), _));
-
-    pp::Token token;
-    do
-    {
-        mPreprocessor.lex(&token);
-    } while (token.type != pp::Token::LAST);
-}
-
-TEST_F(VersionTest, AfterInvalidToken)
-{
-    const char* str = "$\n"
-                      "#version 200\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
-
-    using testing::_;
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::INVALID_CHARACTER,
-                      pp::SourceLocation(0, 1), "$"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::VERSION_NOT_FIRST_STATEMENT,
-                      pp::SourceLocation(0, 2), _));
-
-    pp::Token token;
-    do
-    {
-        mPreprocessor.lex(&token);
-    } while (token.type != pp::Token::LAST);
-}
-
-TEST_F(VersionTest, AfterValidDirective)
-{
-    const char* str = "#\n"
-                      "#version 200\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
-
-    using testing::_;
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::VERSION_NOT_FIRST_STATEMENT,
-                      pp::SourceLocation(0, 2), _));
-
-    pp::Token token;
-    do
-    {
-        mPreprocessor.lex(&token);
-    } while (token.type != pp::Token::LAST);
-}
-
-TEST_F(VersionTest, AfterInvalidDirective)
-{
-    const char* str = "#foo\n"
-                      "#version 200\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
-
-    using testing::_;
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::DIRECTIVE_INVALID_NAME,
-                      pp::SourceLocation(0, 1), "foo"));
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::VERSION_NOT_FIRST_STATEMENT,
-                      pp::SourceLocation(0, 2), _));
-
-    pp::Token token;
-    do
-    {
-        mPreprocessor.lex(&token);
-    } while (token.type != pp::Token::LAST);
-}
-
-TEST_F(VersionTest, AfterExcludedBlock)
-{
-    const char* str = "#if 0\n"
-                      "foo\n"
-                      "#endif\n"
-                      "#version 200\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
-
-    using testing::_;
-    EXPECT_CALL(mDiagnostics,
-                print(pp::Diagnostics::VERSION_NOT_FIRST_STATEMENT,
-                      pp::SourceLocation(0, 4), _));
-
-    pp::Token token;
-    do
-    {
-        mPreprocessor.lex(&token);
-    } while (token.type != pp::Token::LAST);
-}
-
-struct VersionTestParam
-{
-    const char* str;
-    pp::Diagnostics::ID id;
-};
-
-class InvalidVersionTest : public VersionTest,
-                           public testing::WithParamInterface<VersionTestParam>
-{
-};
-
-TEST_P(InvalidVersionTest, Identified)
-{
-    VersionTestParam param = GetParam();
-    const char* expected = "\n";
-
-    using testing::_;
-    // No handleVersion call.
-    EXPECT_CALL(mDirectiveHandler, handleVersion(_, _)).Times(0);
-    // Invalid version directive call.
-    EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
-
-    preprocess(param.str, expected);
-}
-
-static const VersionTestParam kParams[] = {
-    {"#version\n", pp::Diagnostics::INVALID_VERSION_DIRECTIVE},
-    {"#version foo\n", pp::Diagnostics::INVALID_VERSION_NUMBER},
-    {"#version 100 foo\n", pp::Diagnostics::UNEXPECTED_TOKEN},
-    {"#version 0xffffffff\n", pp::Diagnostics::INTEGER_OVERFLOW}
-};
-
-INSTANTIATE_TEST_CASE_P(All, InvalidVersionTest, testing::ValuesIn(kParams));
diff --git a/src/third_party/angle/third_party/deqp/README.angle b/src/third_party/angle/third_party/deqp/README.angle
new file mode 100644
index 0000000..40bc066
--- /dev/null
+++ b/src/third_party/angle/third_party/deqp/README.angle
@@ -0,0 +1,13 @@
+Name: drawElements Quality Program
+Short Name: dEQP
+Version: 1.0
+URL: https://source.android.com/devices/graphics/testing.html
+SOURCE CODE: git clone -b deqp-dev https://android.googlesource.com/platform/external/deqp/
+Date: 20/06/2016
+Revision: f4f3d8079e7a37d7675ab93583e6438d0bca0e58
+Security Critical: no
+License: Apache 2.0
+License File: LICENSE
+
+Description:
+dEQP is a set of tests and testing tools for GPUs and their drivers. It currently supports OpenGL ES 2.0 - 3.1 & AEP and EGL. The dEQP has been part of the Android CTS since the L release.
diff --git a/src/third_party/angle/third_party/glslang-angle/README.angle b/src/third_party/angle/third_party/glslang-angle/README.angle
new file mode 100644
index 0000000..9424a69
--- /dev/null
+++ b/src/third_party/angle/third_party/glslang-angle/README.angle
@@ -0,0 +1,10 @@
+Name: Khronos reference front-end for GLSL and ESSL
+Short Name: glslang
+URL: https://github.com/google/glslang
+Version: N/A
+Security Critical: yes
+License: MIT
+License File: LICENSE
+
+Description:
+An OpenGL and OpenGL ES shader front end and validator.
diff --git a/src/third_party/angle/third_party/spirv-headers/README.angle b/src/third_party/angle/third_party/spirv-headers/README.angle
new file mode 100644
index 0000000..835bdbc
--- /dev/null
+++ b/src/third_party/angle/third_party/spirv-headers/README.angle
@@ -0,0 +1,14 @@
+Name: SPIR-V Headers
+Short Name: spirv-headers
+URL: https://github.com/KhronosGroup/SPIRV-Headers.git
+Version: Unknown
+Security Critical: yes
+License: MIT
+License File: LICENSE
+
+Description:
+This repository contains machine-readable files from the SPIR-V Registry. This includes:
+
+* Header files for various languages.
+* JSON files describing the grammar for the SPIR-V core instruction set, and for the GLSL.std.450 extended instruction set.
+* The XML registry file.
diff --git a/src/third_party/angle/third_party/spirv-tools-angle/README.angle b/src/third_party/angle/third_party/spirv-tools-angle/README.angle
new file mode 100644
index 0000000..fc648cc
--- /dev/null
+++ b/src/third_party/angle/third_party/spirv-tools-angle/README.angle
@@ -0,0 +1,11 @@
+Name: SPIR-V Tools
+Short Name: SPIRV-Tools
+URL: https://github.com/KhronosGroup/SPIRV-Tools.git
+Version: Unknown
+Security Critical: yes
+License: MIT
+License File: LICENSE
+
+Description:
+The SPIR-V Tools project provides an API and commands for processing
+SPIR-V modules.
diff --git a/src/third_party/angle/third_party/vulkan-validation-layers/README.angle b/src/third_party/angle/third_party/vulkan-validation-layers/README.angle
new file mode 100644
index 0000000..b0cb0db
--- /dev/null
+++ b/src/third_party/angle/third_party/vulkan-validation-layers/README.angle
@@ -0,0 +1,17 @@
+Name: Vulkan Ecosystem Components
+Short Name: Vulkan Layers SDK
+Version: N/A
+URL: https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers
+SOURCE CODE: git clone https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers.git
+Date: 06/07/2016
+Revision: d9da90d92748c37962766868f8b0354637672c2a
+Security Critical: no
+License: Apache 2.0
+License File: LICENSE.txt
+
+Description:
+The Vulkan Ecosystem Components consist of the Vulkan loader and Validation Layers SDK. The layers help
+validate Vulkan programs at runtime for development, and the loader is a utility for loading the Vulkan
+entry points and hooking them into the correct layers. These are essential for developing Vulkan
+applications.
+
diff --git a/src/third_party/angle/util/EGLWindow.cpp b/src/third_party/angle/util/EGLWindow.cpp
new file mode 100644
index 0000000..7cb191d
--- /dev/null
+++ b/src/third_party/angle/util/EGLWindow.cpp
@@ -0,0 +1,473 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include <string.h>
+#include <cassert>
+#include <vector>
+
+#include "EGLWindow.h"
+#include "OSWindow.h"
+#include "common/debug.h"
+
+EGLPlatformParameters::EGLPlatformParameters()
+    : renderer(EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE),
+      majorVersion(EGL_DONT_CARE),
+      minorVersion(EGL_DONT_CARE),
+      deviceType(EGL_DONT_CARE),
+      presentPath(EGL_DONT_CARE)
+{
+}
+
+EGLPlatformParameters::EGLPlatformParameters(EGLint renderer)
+    : renderer(renderer),
+      majorVersion(EGL_DONT_CARE),
+      minorVersion(EGL_DONT_CARE),
+      deviceType(EGL_DONT_CARE),
+      presentPath(EGL_DONT_CARE)
+{
+    if (renderer == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE ||
+        renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+    {
+        deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
+    }
+}
+
+EGLPlatformParameters::EGLPlatformParameters(EGLint renderer,
+                                             EGLint majorVersion,
+                                             EGLint minorVersion,
+                                             EGLint useWarp)
+    : renderer(renderer),
+      majorVersion(majorVersion),
+      minorVersion(minorVersion),
+      deviceType(useWarp),
+      presentPath(EGL_DONT_CARE)
+{
+}
+
+EGLPlatformParameters::EGLPlatformParameters(EGLint renderer,
+                                             EGLint majorVersion,
+                                             EGLint minorVersion,
+                                             EGLint useWarp,
+                                             EGLint presentPath)
+    : renderer(renderer),
+      majorVersion(majorVersion),
+      minorVersion(minorVersion),
+      deviceType(useWarp),
+      presentPath(presentPath)
+{
+}
+
+bool operator<(const EGLPlatformParameters &a, const EGLPlatformParameters &b)
+{
+    if (a.renderer != b.renderer)
+    {
+        return a.renderer < b.renderer;
+    }
+
+    if (a.majorVersion != b.majorVersion)
+    {
+        return a.majorVersion < b.majorVersion;
+    }
+
+    if (a.minorVersion != b.minorVersion)
+    {
+        return a.minorVersion < b.minorVersion;
+    }
+
+    if (a.deviceType != b.deviceType)
+    {
+        return a.deviceType < b.deviceType;
+    }
+
+    return a.presentPath < b.presentPath;
+}
+
+bool operator==(const EGLPlatformParameters &a, const EGLPlatformParameters &b)
+{
+    return (a.renderer == b.renderer) && (a.majorVersion == b.majorVersion) &&
+           (a.minorVersion == b.minorVersion) && (a.deviceType == b.deviceType) &&
+           (a.presentPath == b.presentPath);
+}
+
+EGLWindow::EGLWindow(EGLint glesMajorVersion,
+                     EGLint glesMinorVersion,
+                     const EGLPlatformParameters &platform)
+    : mDisplay(EGL_NO_DISPLAY),
+      mSurface(EGL_NO_SURFACE),
+      mContext(EGL_NO_CONTEXT),
+      mClientMajorVersion(glesMajorVersion),
+      mClientMinorVersion(glesMinorVersion),
+      mEGLMajorVersion(0),
+      mEGLMinorVersion(0),
+      mPlatform(platform),
+      mRedBits(-1),
+      mGreenBits(-1),
+      mBlueBits(-1),
+      mAlphaBits(-1),
+      mDepthBits(-1),
+      mStencilBits(-1),
+      mComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT),
+      mMultisample(false),
+      mDebug(false),
+      mNoError(false),
+      mWebGLCompatibility(false),
+      mBindGeneratesResource(true),
+      mClientArraysEnabled(true),
+      mRobustResourceInit(false),
+      mSwapInterval(-1),
+      mSamples(-1)
+{
+}
+
+EGLWindow::~EGLWindow()
+{
+    destroyGL();
+}
+
+void EGLWindow::swap()
+{
+    eglSwapBuffers(mDisplay, mSurface);
+}
+
+EGLConfig EGLWindow::getConfig() const
+{
+    return mConfig;
+}
+
+EGLDisplay EGLWindow::getDisplay() const
+{
+    return mDisplay;
+}
+
+EGLSurface EGLWindow::getSurface() const
+{
+    return mSurface;
+}
+
+EGLContext EGLWindow::getContext() const
+{
+    return mContext;
+}
+
+bool EGLWindow::initializeGL(OSWindow *osWindow)
+{
+    if (!initializeDisplayAndSurface(osWindow))
+        return false;
+    return initializeContext();
+}
+
+bool EGLWindow::initializeDisplayAndSurface(OSWindow *osWindow)
+{
+    PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+    if (!eglGetPlatformDisplayEXT)
+    {
+        return false;
+    }
+
+    std::vector<EGLint> displayAttributes;
+    displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+    displayAttributes.push_back(mPlatform.renderer);
+    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
+    displayAttributes.push_back(mPlatform.majorVersion);
+    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
+    displayAttributes.push_back(mPlatform.minorVersion);
+
+    if (mPlatform.deviceType != EGL_DONT_CARE)
+    {
+        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+        displayAttributes.push_back(mPlatform.deviceType);
+    }
+
+    if (mPlatform.presentPath != EGL_DONT_CARE)
+    {
+        const char *extensionString =
+            static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
+        if (strstr(extensionString, "EGL_ANGLE_experimental_present_path") == nullptr)
+        {
+            destroyGL();
+            return false;
+        }
+
+        displayAttributes.push_back(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE);
+        displayAttributes.push_back(mPlatform.presentPath);
+    }
+
+    // Set vulkan validation layer settings if requested.
+    if (mVulkanLayersEnabled.valid())
+    {
+        displayAttributes.push_back(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE);
+        displayAttributes.push_back(mVulkanLayersEnabled.value() ? EGL_TRUE : EGL_FALSE);
+    }
+
+    displayAttributes.push_back(EGL_NONE);
+
+    mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
+                                        reinterpret_cast<void *>(osWindow->getNativeDisplay()),
+                                        &displayAttributes[0]);
+    if (mDisplay == EGL_NO_DISPLAY)
+    {
+        destroyGL();
+        return false;
+    }
+
+    if (eglInitialize(mDisplay, &mEGLMajorVersion, &mEGLMinorVersion) == EGL_FALSE)
+    {
+        destroyGL();
+        return false;
+    }
+
+    const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
+
+    std::vector<EGLint> configAttributes = {
+        EGL_RED_SIZE,       (mRedBits >= 0) ? mRedBits : EGL_DONT_CARE,
+        EGL_GREEN_SIZE,     (mGreenBits >= 0) ? mGreenBits : EGL_DONT_CARE,
+        EGL_BLUE_SIZE,      (mBlueBits >= 0) ? mBlueBits : EGL_DONT_CARE,
+        EGL_ALPHA_SIZE,     (mAlphaBits >= 0) ? mAlphaBits : EGL_DONT_CARE,
+        EGL_DEPTH_SIZE,     (mDepthBits >= 0) ? mDepthBits : EGL_DONT_CARE,
+        EGL_STENCIL_SIZE,   (mStencilBits >= 0) ? mStencilBits : EGL_DONT_CARE,
+        EGL_SAMPLE_BUFFERS, mMultisample ? 1 : 0,
+        EGL_SAMPLES,        (mSamples >= 0) ? mSamples : EGL_DONT_CARE,
+    };
+
+    // Add dynamic attributes
+    bool hasPixelFormatFloat = strstr(displayExtensions, "EGL_EXT_pixel_format_float") != nullptr;
+    if (!hasPixelFormatFloat && mComponentType != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)
+    {
+        destroyGL();
+        return false;
+    }
+    if (hasPixelFormatFloat)
+    {
+        configAttributes.push_back(EGL_COLOR_COMPONENT_TYPE_EXT);
+        configAttributes.push_back(mComponentType);
+    }
+
+    // Finish the attribute list
+    configAttributes.push_back(EGL_NONE);
+
+    if (!FindEGLConfig(mDisplay, configAttributes.data(), &mConfig))
+    {
+        destroyGL();
+        return false;
+    }
+
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &mRedBits);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &mGreenBits);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &mBlueBits);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &mAlphaBits);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_DEPTH_SIZE, &mDepthBits);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_STENCIL_SIZE, &mStencilBits);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_SAMPLES, &mSamples);
+
+    std::vector<EGLint> surfaceAttributes;
+    if (strstr(displayExtensions, "EGL_NV_post_sub_buffer") != nullptr)
+    {
+        surfaceAttributes.push_back(EGL_POST_SUB_BUFFER_SUPPORTED_NV);
+        surfaceAttributes.push_back(EGL_TRUE);
+    }
+
+    surfaceAttributes.push_back(EGL_NONE);
+
+    mSurface = eglCreateWindowSurface(mDisplay, mConfig, osWindow->getNativeWindow(), &surfaceAttributes[0]);
+    if (eglGetError() != EGL_SUCCESS)
+    {
+        destroyGL();
+        return false;
+    }
+    ASSERT(mSurface != EGL_NO_SURFACE);
+    return true;
+}
+
+bool EGLWindow::initializeContext()
+{
+    const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
+
+    // EGL_KHR_create_context is required to request a ES3+ context.
+    bool hasKHRCreateContext = strstr(displayExtensions, "EGL_KHR_create_context") != nullptr;
+    if (mClientMajorVersion > 2 && !(mEGLMajorVersion > 1 || mEGLMinorVersion >= 5) &&
+        !hasKHRCreateContext)
+    {
+        destroyGL();
+        return false;
+    }
+
+    bool hasWebGLCompatibility =
+        strstr(displayExtensions, "EGL_ANGLE_create_context_webgl_compatibility") != nullptr;
+    if (mWebGLCompatibility && !hasWebGLCompatibility)
+    {
+        destroyGL();
+        return false;
+    }
+
+    bool hasBindGeneratesResource =
+        strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr;
+    if (!mBindGeneratesResource && !hasBindGeneratesResource)
+    {
+        destroyGL();
+        return false;
+    }
+
+    bool hasClientArraysExtension =
+        strstr(displayExtensions, "EGL_ANGLE_create_context_client_arrays") != nullptr;
+    if (!mClientArraysEnabled && !hasClientArraysExtension)
+    {
+        // Non-default state requested without the extension present
+        destroyGL();
+        return false;
+    }
+
+    bool hasRobustResourceInit =
+        strstr(displayExtensions, "EGL_ANGLE_create_context_robust_resource_initialization") !=
+        nullptr;
+    if (mRobustResourceInit && !hasRobustResourceInit)
+    {
+        // Non-default state requested without the extension present
+        destroyGL();
+        return false;
+    }
+
+    eglBindAPI(EGL_OPENGL_ES_API);
+    if (eglGetError() != EGL_SUCCESS)
+    {
+        destroyGL();
+        return false;
+    }
+
+    std::vector<EGLint> contextAttributes;
+    if (hasKHRCreateContext)
+    {
+        contextAttributes.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
+        contextAttributes.push_back(mClientMajorVersion);
+
+        contextAttributes.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
+        contextAttributes.push_back(mClientMinorVersion);
+
+        contextAttributes.push_back(EGL_CONTEXT_OPENGL_DEBUG);
+        contextAttributes.push_back(mDebug ? EGL_TRUE : EGL_FALSE);
+
+        // TODO(jmadill): Check for the extension string.
+        // bool hasKHRCreateContextNoError = strstr(displayExtensions,
+        // "EGL_KHR_create_context_no_error") != nullptr;
+
+        contextAttributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
+        contextAttributes.push_back(mNoError ? EGL_TRUE : EGL_FALSE);
+
+        if (hasWebGLCompatibility)
+        {
+            contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
+            contextAttributes.push_back(mWebGLCompatibility ? EGL_TRUE : EGL_FALSE);
+        }
+
+        if (hasBindGeneratesResource)
+        {
+            contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
+            contextAttributes.push_back(mBindGeneratesResource ? EGL_TRUE : EGL_FALSE);
+        }
+
+        if (hasClientArraysExtension)
+        {
+            contextAttributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE);
+            contextAttributes.push_back(mClientArraysEnabled ? EGL_TRUE : EGL_FALSE);
+        }
+
+        if (hasRobustResourceInit)
+        {
+            contextAttributes.push_back(EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
+            contextAttributes.push_back(mRobustResourceInit ? EGL_TRUE : EGL_FALSE);
+        }
+    }
+    contextAttributes.push_back(EGL_NONE);
+
+    mContext = eglCreateContext(mDisplay, mConfig, nullptr, &contextAttributes[0]);
+    if (eglGetError() != EGL_SUCCESS)
+    {
+        destroyGL();
+        return false;
+    }
+
+    eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
+    if (eglGetError() != EGL_SUCCESS)
+    {
+        destroyGL();
+        return false;
+    }
+
+    if (mSwapInterval != -1)
+    {
+        eglSwapInterval(mDisplay, mSwapInterval);
+    }
+
+    return true;
+}
+
+void EGLWindow::destroyGL()
+{
+    if (mSurface != EGL_NO_SURFACE)
+    {
+        assert(mDisplay != EGL_NO_DISPLAY);
+        eglDestroySurface(mDisplay, mSurface);
+        mSurface = EGL_NO_SURFACE;
+    }
+
+    if (mContext != EGL_NO_CONTEXT)
+    {
+        assert(mDisplay != EGL_NO_DISPLAY);
+        eglDestroyContext(mDisplay, mContext);
+        mContext = EGL_NO_CONTEXT;
+    }
+
+    if (mDisplay != EGL_NO_DISPLAY)
+    {
+        eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        eglTerminate(mDisplay);
+        mDisplay = EGL_NO_DISPLAY;
+    }
+}
+
+bool EGLWindow::isGLInitialized() const
+{
+    return mSurface != EGL_NO_SURFACE &&
+           mContext != EGL_NO_CONTEXT &&
+           mDisplay != EGL_NO_DISPLAY;
+}
+
+// Find an EGLConfig that is an exact match for the specified attributes. EGL_FALSE is returned if
+// the EGLConfig is found.  This indicates that the EGLConfig is not supported.
+EGLBoolean EGLWindow::FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config)
+{
+    EGLint numConfigs = 0;
+    eglGetConfigs(dpy, nullptr, 0, &numConfigs);
+    std::vector<EGLConfig> allConfigs(numConfigs);
+    eglGetConfigs(dpy, allConfigs.data(), static_cast<EGLint>(allConfigs.size()), &numConfigs);
+
+    for (size_t i = 0; i < allConfigs.size(); i++)
+    {
+        bool matchFound = true;
+        for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
+        {
+            if (curAttrib[1] == EGL_DONT_CARE)
+            {
+                continue;
+            }
+
+            EGLint actualValue = EGL_DONT_CARE;
+            eglGetConfigAttrib(dpy, allConfigs[i], curAttrib[0], &actualValue);
+            if (curAttrib[1] != actualValue)
+            {
+                matchFound = false;
+                break;
+            }
+        }
+
+        if (matchFound)
+        {
+            *config = allConfigs[i];
+            return EGL_TRUE;
+        }
+    }
+
+    return EGL_FALSE;
+}
diff --git a/src/third_party/angle/util/EGLWindow.h b/src/third_party/angle/util/EGLWindow.h
new file mode 100644
index 0000000..dbb3d05
--- /dev/null
+++ b/src/third_party/angle/util/EGLWindow.h
@@ -0,0 +1,150 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef UTIL_EGLWINDOW_H_
+#define UTIL_EGLWINDOW_H_
+
+#include <list>
+#include <memory>
+#include <stdint.h>
+#include <string>
+
+#include <export.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES3/gl3.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "common/angleutils.h"
+#include "common/Optional.h"
+
+class OSWindow;
+
+// A hidden define used in some renderers (currently D3D-only)
+// to init a no-op renderer. Useful for performance testing.
+#ifndef EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0
+#endif
+
+struct ANGLE_EXPORT EGLPlatformParameters
+{
+    EGLint renderer;
+    EGLint majorVersion;
+    EGLint minorVersion;
+    EGLint deviceType;
+    EGLint presentPath;
+
+    EGLPlatformParameters();
+    explicit EGLPlatformParameters(EGLint renderer);
+    EGLPlatformParameters(EGLint renderer, EGLint majorVersion, EGLint minorVersion, EGLint deviceType);
+    EGLPlatformParameters(EGLint renderer,
+                          EGLint majorVersion,
+                          EGLint minorVersion,
+                          EGLint deviceType,
+                          EGLint presentPath);
+};
+
+ANGLE_EXPORT bool operator<(const EGLPlatformParameters &a, const EGLPlatformParameters &b);
+ANGLE_EXPORT bool operator==(const EGLPlatformParameters &a, const EGLPlatformParameters &b);
+
+class ANGLE_EXPORT EGLWindow : angle::NonCopyable
+{
+  public:
+    EGLWindow(EGLint glesMajorVersion,
+              EGLint glesMinorVersion,
+              const EGLPlatformParameters &platform);
+
+    ~EGLWindow();
+
+    void setConfigRedBits(int bits) { mRedBits = bits; }
+    void setConfigGreenBits(int bits) { mGreenBits = bits; }
+    void setConfigBlueBits(int bits) { mBlueBits = bits; }
+    void setConfigAlphaBits(int bits) { mAlphaBits = bits; }
+    void setConfigDepthBits(int bits) { mDepthBits = bits; }
+    void setConfigStencilBits(int bits) { mStencilBits = bits; }
+    void setConfigComponentType(EGLenum componentType) { mComponentType = componentType; }
+    void setMultisample(bool multisample) { mMultisample = multisample; }
+    void setSamples(EGLint samples) { mSamples = samples; }
+    void setDebugEnabled(bool debug) { mDebug = debug; }
+    void setNoErrorEnabled(bool noError) { mNoError = noError; }
+    void setWebGLCompatibilityEnabled(bool webglCompatibility)
+    {
+        mWebGLCompatibility = webglCompatibility;
+    }
+    void setBindGeneratesResource(bool bindGeneratesResource)
+    {
+        mBindGeneratesResource = bindGeneratesResource;
+    }
+    void setVulkanLayersEnabled(bool enabled) { mVulkanLayersEnabled = enabled; }
+    void setClientArraysEnabled(bool enabled) { mClientArraysEnabled = enabled; }
+    void setRobustResourceInit(bool enabled) { mRobustResourceInit = enabled; }
+    void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
+
+    static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
+
+    void swap();
+
+    EGLint getClientMajorVersion() const { return mClientMajorVersion; }
+    EGLint getClientMinorVersion() const { return mClientMinorVersion; }
+    const EGLPlatformParameters &getPlatform() const { return mPlatform; }
+    EGLConfig getConfig() const;
+    EGLDisplay getDisplay() const;
+    EGLSurface getSurface() const;
+    EGLContext getContext() const;
+    int getConfigRedBits() const { return mRedBits; }
+    int getConfigGreenBits() const { return mGreenBits; }
+    int getConfigBlueBits() const { return mBlueBits; }
+    int getConfigAlphaBits() const { return mAlphaBits; }
+    int getConfigDepthBits() const { return mDepthBits; }
+    int getConfigStencilBits() const { return mStencilBits; }
+    bool isMultisample() const { return mMultisample; }
+    bool isDebugEnabled() const { return mDebug; }
+    EGLint getSwapInterval() const { return mSwapInterval; }
+
+    // Internally initializes the Display, Surface and Context.
+    bool initializeGL(OSWindow *osWindow);
+
+    // Only initializes the Display and Surface.
+    bool initializeDisplayAndSurface(OSWindow *osWindow);
+
+    // Only initializes the Context.
+    bool initializeContext();
+
+    void destroyGL();
+    bool isGLInitialized() const;
+
+  private:
+    EGLConfig mConfig;
+    EGLDisplay mDisplay;
+    EGLSurface mSurface;
+    EGLContext mContext;
+
+    EGLint mClientMajorVersion;
+    EGLint mClientMinorVersion;
+    EGLint mEGLMajorVersion;
+    EGLint mEGLMinorVersion;
+    EGLPlatformParameters mPlatform;
+    int mRedBits;
+    int mGreenBits;
+    int mBlueBits;
+    int mAlphaBits;
+    int mDepthBits;
+    int mStencilBits;
+    EGLenum mComponentType;
+    bool mMultisample;
+    bool mDebug;
+    bool mNoError;
+    bool mWebGLCompatibility;
+    bool mBindGeneratesResource;
+    bool mClientArraysEnabled;
+    bool mRobustResourceInit;
+    EGLint mSwapInterval;
+    EGLint mSamples;
+    Optional<bool> mVulkanLayersEnabled;
+};
+
+#endif // UTIL_EGLWINDOW_H_
diff --git a/src/third_party/angle/util/Event.h b/src/third_party/angle/util/Event.h
new file mode 100644
index 0000000..7dd9cb3
--- /dev/null
+++ b/src/third_party/angle/util/Event.h
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef SAMPLE_UTIL_EVENT_H
+#define SAMPLE_UTIL_EVENT_H
+
+#include "keyboard.h"
+#include "mouse.h"
+
+class Event
+{
+  public:
+    struct MoveEvent
+    {
+        int X;
+        int Y;
+    };
+
+    struct SizeEvent
+    {
+        int Width;
+        int Height;
+    };
+
+    struct KeyEvent
+    {
+        Key Code;
+        bool Alt;
+        bool Control;
+        bool Shift;
+        bool System;
+    };
+
+    struct MouseMoveEvent
+    {
+        int X;
+        int Y;
+    };
+
+    struct MouseButtonEvent
+    {
+        MouseButton Button;
+        int X;
+        int Y;
+    };
+
+    struct MouseWheelEvent
+    {
+        int Delta;
+    };
+
+    enum EventType
+    {
+        EVENT_CLOSED,                // The window requested to be closed
+        EVENT_MOVED,                 // The window has moved
+        EVENT_RESIZED,               // The window was resized
+        EVENT_LOST_FOCUS,            // The window lost the focus
+        EVENT_GAINED_FOCUS,          // The window gained the focus
+        EVENT_TEXT_ENTERED,          // A character was entered
+        EVENT_KEY_PRESSED,           // A key was pressed
+        EVENT_KEY_RELEASED,          // A key was released
+        EVENT_MOUSE_WHEEL_MOVED,     // The mouse wheel was scrolled
+        EVENT_MOUSE_BUTTON_PRESSED,  // A mouse button was pressed
+        EVENT_MOUSE_BUTTON_RELEASED, // A mouse button was released
+        EVENT_MOUSE_MOVED,           // The mouse cursor moved
+        EVENT_MOUSE_ENTERED,         // The mouse cursor entered the area of the window
+        EVENT_MOUSE_LEFT,            // The mouse cursor left the area of the window
+        EVENT_TEST,                  // Event for testing purposes
+    };
+
+    EventType Type;
+
+    union
+    {
+        MoveEvent               Move;               // Move event parameters
+        SizeEvent               Size;               // Size event parameters
+        KeyEvent                Key;                // Key event parameters
+        MouseMoveEvent          MouseMove;          // Mouse move event parameters
+        MouseButtonEvent        MouseButton;        // Mouse button event parameters
+        MouseWheelEvent         MouseWheel;         // Mouse wheel event parameters
+    };
+};
+
+#endif // SAMPLE_UTIL_EVENT_H
diff --git a/src/third_party/angle/util/Matrix.cpp b/src/third_party/angle/util/Matrix.cpp
new file mode 100644
index 0000000..34af434
--- /dev/null
+++ b/src/third_party/angle/util/Matrix.cpp
@@ -0,0 +1,306 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Matrix:
+//   Helper class for doing matrix math.
+//
+
+#include "Matrix.h"
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+#include <cstddef>
+
+using namespace angle;
+
+Matrix4::Matrix4()
+{
+    data[0]  = 1.0f;
+    data[4]  = 0.0f;
+    data[8]  = 0.0f;
+    data[12] = 0.0f;
+    data[1]  = 0.0f;
+    data[5]  = 1.0f;
+    data[9]  = 0.0f;
+    data[13] = 0.0f;
+    data[2]  = 0.0f;
+    data[6]  = 0.0f;
+    data[10] = 1.0f;
+    data[14] = 0.0f;
+    data[3]  = 0.0f;
+    data[7]  = 0.0f;
+    data[11] = 0.0f;
+    data[15] = 1.0f;
+}
+
+Matrix4::Matrix4(float m00,
+                 float m01,
+                 float m02,
+                 float m03,
+                 float m10,
+                 float m11,
+                 float m12,
+                 float m13,
+                 float m20,
+                 float m21,
+                 float m22,
+                 float m23,
+                 float m30,
+                 float m31,
+                 float m32,
+                 float m33)
+{
+    data[0]  = m00;
+    data[4]  = m01;
+    data[8]  = m02;
+    data[12] = m03;
+    data[1]  = m10;
+    data[5]  = m11;
+    data[9]  = m12;
+    data[13] = m13;
+    data[2]  = m20;
+    data[6]  = m21;
+    data[10] = m22;
+    data[14] = m23;
+    data[3]  = m30;
+    data[7]  = m31;
+    data[11] = m32;
+    data[15] = m33;
+}
+
+Matrix4 Matrix4::identity()
+{
+    return Matrix4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+                   0.0f, 0.0f, 1.0f);
+}
+
+Matrix4 Matrix4::rotate(float angle, const Vector3 &p)
+{
+    Vector3 u   = p.normalized();
+    float theta = static_cast<float>(angle * (M_PI / 180.0f));
+    float cos_t = cosf(theta);
+    float sin_t = sinf(theta);
+
+    return Matrix4(cos_t + (u.x() * u.x() * (1.0f - cos_t)),
+                   (u.x() * u.y() * (1.0f - cos_t)) - (u.z() * sin_t),
+                   (u.x() * u.z() * (1.0f - cos_t)) + (u.y() * sin_t), 0.0f,
+                   (u.y() * u.x() * (1.0f - cos_t)) + (u.z() * sin_t),
+                   cos_t + (u.y() * u.y() * (1.0f - cos_t)),
+                   (u.y() * u.z() * (1.0f - cos_t)) - (u.x() * sin_t), 0.0f,
+                   (u.z() * u.x() * (1.0f - cos_t)) - (u.y() * sin_t),
+                   (u.z() * u.y() * (1.0f - cos_t)) + (u.x() * sin_t),
+                   cos_t + (u.z() * u.z() * (1.0f - cos_t)), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
+}
+
+Matrix4 Matrix4::translate(const Vector3 &t)
+{
+    return Matrix4(1.0f, 0.0f, 0.0f, t.x(), 0.0f, 1.0f, 0.0f, t.y(), 0.0f, 0.0f, 1.0f, t.z(), 0.0f,
+                   0.0f, 0.0f, 1.0f);
+}
+
+Matrix4 Matrix4::scale(const Vector3 &s)
+{
+    return Matrix4(s.x(), 0.0f, 0.0f, 0.0f, 0.0f, s.y(), 0.0f, 0.0f, 0.0f, 0.0f, s.z(), 0.0f, 0.0f,
+                   0.0f, 0.0f, 1.0f);
+}
+
+Matrix4 Matrix4::frustum(float l, float r, float b, float t, float n, float f)
+{
+    return Matrix4((2.0f * n) / (r - l), 0.0f, (r + l) / (r - l), 0.0f, 0.0f, (2.0f * n) / (t - b),
+                   (t + b) / (t - b), 0.0f, 0.0f, 0.0f, -(f + n) / (f - n),
+                   -(2.0f * f * n) / (f - n), 0.0f, 0.0f, -1.0f, 0.0f);
+}
+
+Matrix4 Matrix4::perspective(float fovY, float aspectRatio, float nearZ, float farZ)
+{
+    const float frustumHeight = tanf(static_cast<float>(fovY / 360.0f * M_PI)) * nearZ;
+    const float frustumWidth = frustumHeight * aspectRatio;
+    return frustum(-frustumWidth, frustumWidth, -frustumHeight, frustumHeight, nearZ, farZ);
+}
+
+Matrix4 Matrix4::ortho(float l, float r, float b, float t, float n, float f)
+{
+    return Matrix4(2.0f / (r - l), 0.0f, 0.0f, -(r + l) / (r - l), 0.0f, 2.0f / (t - b), 0.0f,
+                   -(t + b) / (t - b), 0.0f, 0.0f, -2.0f / (f - n), -(f + n) / (f - n), 0.0f, 0.0f,
+                   0.0f, 1.0f);
+}
+
+Matrix4 Matrix4::rollPitchYaw(float roll, float pitch, float yaw)
+{
+    return rotate(yaw, Vector3(0, 0, 1)) * rotate(pitch, Vector3(0, 1, 0)) *
+           rotate(roll, Vector3(1, 0, 0));
+}
+
+Matrix4 Matrix4::invert(const Matrix4 &mat)
+{
+    Matrix4 inverted(
+        mat.data[5] * mat.data[10] * mat.data[15] - mat.data[5] * mat.data[11] * mat.data[14] -
+            mat.data[9] * mat.data[6] * mat.data[15] + mat.data[9] * mat.data[7] * mat.data[14] +
+            mat.data[13] * mat.data[6] * mat.data[11] - mat.data[13] * mat.data[7] * mat.data[10],
+        -mat.data[4] * mat.data[10] * mat.data[15] + mat.data[4] * mat.data[11] * mat.data[14] +
+            mat.data[8] * mat.data[6] * mat.data[15] - mat.data[8] * mat.data[7] * mat.data[14] -
+            mat.data[12] * mat.data[6] * mat.data[11] + mat.data[12] * mat.data[7] * mat.data[10],
+        mat.data[4] * mat.data[9] * mat.data[15] - mat.data[4] * mat.data[11] * mat.data[13] -
+            mat.data[8] * mat.data[5] * mat.data[15] + mat.data[8] * mat.data[7] * mat.data[13] +
+            mat.data[12] * mat.data[5] * mat.data[11] - mat.data[12] * mat.data[7] * mat.data[9],
+        -mat.data[4] * mat.data[9] * mat.data[14] + mat.data[4] * mat.data[10] * mat.data[13] +
+            mat.data[8] * mat.data[5] * mat.data[14] - mat.data[8] * mat.data[6] * mat.data[13] -
+            mat.data[12] * mat.data[5] * mat.data[10] + mat.data[12] * mat.data[6] * mat.data[9],
+        -mat.data[1] * mat.data[10] * mat.data[15] + mat.data[1] * mat.data[11] * mat.data[14] +
+            mat.data[9] * mat.data[2] * mat.data[15] - mat.data[9] * mat.data[3] * mat.data[14] -
+            mat.data[13] * mat.data[2] * mat.data[11] + mat.data[13] * mat.data[3] * mat.data[10],
+        mat.data[0] * mat.data[10] * mat.data[15] - mat.data[0] * mat.data[11] * mat.data[14] -
+            mat.data[8] * mat.data[2] * mat.data[15] + mat.data[8] * mat.data[3] * mat.data[14] +
+            mat.data[12] * mat.data[2] * mat.data[11] - mat.data[12] * mat.data[3] * mat.data[10],
+        -mat.data[0] * mat.data[9] * mat.data[15] + mat.data[0] * mat.data[11] * mat.data[13] +
+            mat.data[8] * mat.data[1] * mat.data[15] - mat.data[8] * mat.data[3] * mat.data[13] -
+            mat.data[12] * mat.data[1] * mat.data[11] + mat.data[12] * mat.data[3] * mat.data[9],
+        mat.data[0] * mat.data[9] * mat.data[14] - mat.data[0] * mat.data[10] * mat.data[13] -
+            mat.data[8] * mat.data[1] * mat.data[14] + mat.data[8] * mat.data[2] * mat.data[13] +
+            mat.data[12] * mat.data[1] * mat.data[10] - mat.data[12] * mat.data[2] * mat.data[9],
+        mat.data[1] * mat.data[6] * mat.data[15] - mat.data[1] * mat.data[7] * mat.data[14] -
+            mat.data[5] * mat.data[2] * mat.data[15] + mat.data[5] * mat.data[3] * mat.data[14] +
+            mat.data[13] * mat.data[2] * mat.data[7] - mat.data[13] * mat.data[3] * mat.data[6],
+        -mat.data[0] * mat.data[6] * mat.data[15] + mat.data[0] * mat.data[7] * mat.data[14] +
+            mat.data[4] * mat.data[2] * mat.data[15] - mat.data[4] * mat.data[3] * mat.data[14] -
+            mat.data[12] * mat.data[2] * mat.data[7] + mat.data[12] * mat.data[3] * mat.data[6],
+        mat.data[0] * mat.data[5] * mat.data[15] - mat.data[0] * mat.data[7] * mat.data[13] -
+            mat.data[4] * mat.data[1] * mat.data[15] + mat.data[4] * mat.data[3] * mat.data[13] +
+            mat.data[12] * mat.data[1] * mat.data[7] - mat.data[12] * mat.data[3] * mat.data[5],
+        -mat.data[0] * mat.data[5] * mat.data[14] + mat.data[0] * mat.data[6] * mat.data[13] +
+            mat.data[4] * mat.data[1] * mat.data[14] - mat.data[4] * mat.data[2] * mat.data[13] -
+            mat.data[12] * mat.data[1] * mat.data[6] + mat.data[12] * mat.data[2] * mat.data[5],
+        -mat.data[1] * mat.data[6] * mat.data[11] + mat.data[1] * mat.data[7] * mat.data[10] +
+            mat.data[5] * mat.data[2] * mat.data[11] - mat.data[5] * mat.data[3] * mat.data[10] -
+            mat.data[9] * mat.data[2] * mat.data[7] + mat.data[9] * mat.data[3] * mat.data[6],
+        mat.data[0] * mat.data[6] * mat.data[11] - mat.data[0] * mat.data[7] * mat.data[10] -
+            mat.data[4] * mat.data[2] * mat.data[11] + mat.data[4] * mat.data[3] * mat.data[10] +
+            mat.data[8] * mat.data[2] * mat.data[7] - mat.data[8] * mat.data[3] * mat.data[6],
+        -mat.data[0] * mat.data[5] * mat.data[11] + mat.data[0] * mat.data[7] * mat.data[9] +
+            mat.data[4] * mat.data[1] * mat.data[11] - mat.data[4] * mat.data[3] * mat.data[9] -
+            mat.data[8] * mat.data[1] * mat.data[7] + mat.data[8] * mat.data[3] * mat.data[5],
+        mat.data[0] * mat.data[5] * mat.data[10] - mat.data[0] * mat.data[6] * mat.data[9] -
+            mat.data[4] * mat.data[1] * mat.data[10] + mat.data[4] * mat.data[2] * mat.data[9] +
+            mat.data[8] * mat.data[1] * mat.data[6] - mat.data[8] * mat.data[2] * mat.data[5]);
+
+    float determinant = mat.data[0] * inverted.data[0] + mat.data[1] * inverted.data[4] +
+                        mat.data[2] * inverted.data[8] + mat.data[3] * inverted.data[12];
+
+    if (determinant != 0.0f)
+    {
+        inverted *= 1.0f / determinant;
+    }
+    else
+    {
+        inverted = identity();
+    }
+
+    return inverted;
+}
+
+Matrix4 Matrix4::transpose(const Matrix4 &mat)
+{
+    return Matrix4(mat.data[0], mat.data[1], mat.data[2], mat.data[3], mat.data[4], mat.data[5],
+                   mat.data[6], mat.data[7], mat.data[8], mat.data[9], mat.data[10], mat.data[11],
+                   mat.data[12], mat.data[13], mat.data[14], mat.data[15]);
+}
+
+Vector3 Matrix4::transform(const Matrix4 &mat, const Vector3 &pt)
+{
+    Vector4 transformed = (mat * Vector4(pt, 1.0f)).normalized();
+    return Vector3(transformed.x(), transformed.y(), transformed.z());
+}
+
+Vector3 Matrix4::transform(const Matrix4 &mat, const Vector4 &pt)
+{
+    Vector4 transformed = (mat * pt).normalized();
+    return Vector3(transformed.x(), transformed.y(), transformed.z());
+}
+
+Matrix4 operator*(const Matrix4 &a, const Matrix4 &b)
+{
+    return Matrix4(a.data[0] * b.data[0] + a.data[4] * b.data[1] + a.data[8] * b.data[2] +
+                       a.data[12] * b.data[3],
+                   a.data[0] * b.data[4] + a.data[4] * b.data[5] + a.data[8] * b.data[6] +
+                       a.data[12] * b.data[7],
+                   a.data[0] * b.data[8] + a.data[4] * b.data[9] + a.data[8] * b.data[10] +
+                       a.data[12] * b.data[11],
+                   a.data[0] * b.data[12] + a.data[4] * b.data[13] + a.data[8] * b.data[14] +
+                       a.data[12] * b.data[15],
+                   a.data[1] * b.data[0] + a.data[5] * b.data[1] + a.data[9] * b.data[2] +
+                       a.data[13] * b.data[3],
+                   a.data[1] * b.data[4] + a.data[5] * b.data[5] + a.data[9] * b.data[6] +
+                       a.data[13] * b.data[7],
+                   a.data[1] * b.data[8] + a.data[5] * b.data[9] + a.data[9] * b.data[10] +
+                       a.data[13] * b.data[11],
+                   a.data[1] * b.data[12] + a.data[5] * b.data[13] + a.data[9] * b.data[14] +
+                       a.data[13] * b.data[15],
+                   a.data[2] * b.data[0] + a.data[6] * b.data[1] + a.data[10] * b.data[2] +
+                       a.data[14] * b.data[3],
+                   a.data[2] * b.data[4] + a.data[6] * b.data[5] + a.data[10] * b.data[6] +
+                       a.data[14] * b.data[7],
+                   a.data[2] * b.data[8] + a.data[6] * b.data[9] + a.data[10] * b.data[10] +
+                       a.data[14] * b.data[11],
+                   a.data[2] * b.data[12] + a.data[6] * b.data[13] + a.data[10] * b.data[14] +
+                       a.data[14] * b.data[15],
+                   a.data[3] * b.data[0] + a.data[7] * b.data[1] + a.data[11] * b.data[2] +
+                       a.data[15] * b.data[3],
+                   a.data[3] * b.data[4] + a.data[7] * b.data[5] + a.data[11] * b.data[6] +
+                       a.data[15] * b.data[7],
+                   a.data[3] * b.data[8] + a.data[7] * b.data[9] + a.data[11] * b.data[10] +
+                       a.data[15] * b.data[11],
+                   a.data[3] * b.data[12] + a.data[7] * b.data[13] + a.data[11] * b.data[14] +
+                       a.data[15] * b.data[15]);
+}
+
+Matrix4 &operator*=(Matrix4 &a, const Matrix4 &b)
+{
+    a = a * b;
+    return a;
+}
+
+Matrix4 operator*(const Matrix4 &a, float b)
+{
+    Matrix4 ret(a);
+    for (size_t i = 0; i < 16; i++)
+    {
+        ret.data[i] *= b;
+    }
+    return ret;
+}
+
+Matrix4 &operator*=(Matrix4 &a, float b)
+{
+    for (size_t i = 0; i < 16; i++)
+    {
+        a.data[i] *= b;
+    }
+    return a;
+}
+
+Vector4 operator*(const Matrix4 &a, const Vector4 &b)
+{
+    return Vector4(a.data[0] * b.x() + a.data[4] * b.y() + a.data[8] * b.z() + a.data[12] * b.w(),
+                   a.data[1] * b.x() + a.data[5] * b.y() + a.data[9] * b.z() + a.data[13] * b.w(),
+                   a.data[2] * b.x() + a.data[6] * b.y() + a.data[10] * b.z() + a.data[14] * b.w(),
+                   a.data[3] * b.x() + a.data[7] * b.y() + a.data[11] * b.z() + a.data[15] * b.w());
+}
+
+bool operator==(const Matrix4 &a, const Matrix4 &b)
+{
+    for (size_t i = 0; i < 16; i++)
+    {
+        if (a.data[i] != b.data[i])
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool operator!=(const Matrix4 &a, const Matrix4 &b)
+{
+    return !(a == b);
+}
diff --git a/src/third_party/angle/util/Matrix.h b/src/third_party/angle/util/Matrix.h
new file mode 100644
index 0000000..168dc05
--- /dev/null
+++ b/src/third_party/angle/util/Matrix.h
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Matrix:
+//   Helper class for doing matrix math.
+//
+
+#ifndef UTIL_MATRIX_H
+#define UTIL_MATRIX_H
+
+#include <export.h>
+
+#include "common/vector_utils.h"
+
+struct ANGLE_EXPORT Matrix4
+{
+    float data[16];
+
+    Matrix4();
+    Matrix4(float m00,
+            float m01,
+            float m02,
+            float m03,
+            float m10,
+            float m11,
+            float m12,
+            float m13,
+            float m20,
+            float m21,
+            float m22,
+            float m23,
+            float m30,
+            float m31,
+            float m32,
+            float m33);
+
+    static Matrix4 identity();
+    static Matrix4 rotate(float angle, const angle::Vector3 &p);
+    static Matrix4 translate(const angle::Vector3 &t);
+    static Matrix4 scale(const angle::Vector3 &s);
+    static Matrix4 frustum(float l, float r, float b, float t, float n, float f);
+    static Matrix4 perspective(float fov, float aspectRatio, float n, float f);
+    static Matrix4 ortho(float l, float r, float b, float t, float n, float f);
+    static Matrix4 rollPitchYaw(float roll, float pitch, float yaw);
+
+    static Matrix4 invert(const Matrix4 &mat);
+    static Matrix4 transpose(const Matrix4 &mat);
+    static angle::Vector3 transform(const Matrix4 &mat, const angle::Vector3 &pt);
+    static angle::Vector3 transform(const Matrix4 &mat, const angle::Vector4 &pt);
+};
+
+ANGLE_EXPORT Matrix4 operator*(const Matrix4 &a, const Matrix4 &b);
+ANGLE_EXPORT Matrix4 &operator*=(Matrix4 &a, const Matrix4 &b);
+ANGLE_EXPORT Matrix4 operator*(const Matrix4 &a, float b);
+ANGLE_EXPORT Matrix4 &operator*=(Matrix4 &a, float b);
+ANGLE_EXPORT angle::Vector4 operator*(const Matrix4 &a, const angle::Vector4 &b);
+
+ANGLE_EXPORT bool operator==(const Matrix4 &a, const Matrix4 &b);
+ANGLE_EXPORT bool operator!=(const Matrix4 &a, const Matrix4 &b);
+
+#endif  // UTIL_MATRIX_H
diff --git a/src/third_party/angle/util/OSPixmap.h b/src/third_party/angle/util/OSPixmap.h
new file mode 100644
index 0000000..2afcaf0
--- /dev/null
+++ b/src/third_party/angle/util/OSPixmap.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// OSPixmap.h: Definition of an abstract pixmap class
+
+#ifndef SAMPLE_UTIL_PIXMAP_H_
+#define SAMPLE_UTIL_PIXMAP_H_
+
+#include <stdlib.h>
+
+#include <export.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "Event.h"
+
+class ANGLE_EXPORT OSPixmap
+{
+  public:
+    OSPixmap() {}
+    virtual ~OSPixmap() {}
+
+    virtual bool initialize(EGLNativeDisplayType display, size_t width, size_t height, int depth) = 0;
+
+    virtual EGLNativePixmapType getNativePixmap() const = 0;
+};
+
+ANGLE_EXPORT OSPixmap *CreateOSPixmap();
+
+#endif // SAMPLE_UTIL_PIXMAP_H_
diff --git a/src/third_party/angle/util/OSWindow.cpp b/src/third_party/angle/util/OSWindow.cpp
new file mode 100644
index 0000000..abe8607
--- /dev/null
+++ b/src/third_party/angle/util/OSWindow.cpp
@@ -0,0 +1,323 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "OSWindow.h"
+
+#include <iostream>
+#include <sstream>
+
+#include "common/debug.h"
+
+#ifndef DEBUG_EVENTS
+#define DEBUG_EVENTS 0
+#endif
+
+#if DEBUG_EVENTS
+static const char *MouseButtonName(MouseButton button)
+{
+    switch (button)
+    {
+      case MOUSEBUTTON_UNKNOWN:
+        return "Unknown";
+      case MOUSEBUTTON_LEFT:
+        return "Left";
+      case MOUSEBUTTON_RIGHT:
+        return "Right";
+      case MOUSEBUTTON_MIDDLE:
+        return "Middle";
+      case MOUSEBUTTON_BUTTON4:
+        return "Button4";
+      case MOUSEBUTTON_BUTTON5:
+        return "Button5";
+      default:
+        UNREACHABLE();
+        return nullptr;
+    }
+}
+
+static const char *KeyName(Key key)
+{
+    switch (key)
+    {
+      case KEY_UNKNOWN:   return "Unknown";
+      case KEY_A:         return "A";
+      case KEY_B:         return "B";
+      case KEY_C:         return "C";
+      case KEY_D:         return "D";
+      case KEY_E:         return "E";
+      case KEY_F:         return "F";
+      case KEY_G:         return "G";
+      case KEY_H:         return "H";
+      case KEY_I:         return "I";
+      case KEY_J:         return "J";
+      case KEY_K:         return "K";
+      case KEY_L:         return "L";
+      case KEY_M:         return "M";
+      case KEY_N:         return "N";
+      case KEY_O:         return "O";
+      case KEY_P:         return "P";
+      case KEY_Q:         return "Q";
+      case KEY_R:         return "R";
+      case KEY_S:         return "S";
+      case KEY_T:         return "T";
+      case KEY_U:         return "U";
+      case KEY_V:         return "V";
+      case KEY_W:         return "W";
+      case KEY_X:         return "X";
+      case KEY_Y:         return "Y";
+      case KEY_Z:         return "Z";
+      case KEY_NUM0:      return "Num0";
+      case KEY_NUM1:      return "Num1";
+      case KEY_NUM2:      return "Num2";
+      case KEY_NUM3:      return "Num3";
+      case KEY_NUM4:      return "Num4";
+      case KEY_NUM5:      return "Num5";
+      case KEY_NUM6:      return "Num6";
+      case KEY_NUM7:      return "Num7";
+      case KEY_NUM8:      return "Num8";
+      case KEY_NUM9:      return "Num9";
+      case KEY_ESCAPE:    return "Escape";
+      case KEY_LCONTROL:  return "Left Control";
+      case KEY_LSHIFT:    return "Left Shift";
+      case KEY_LALT:      return "Left Alt";
+      case KEY_LSYSTEM:   return "Left System";
+      case KEY_RCONTROL:  return "Right Control";
+      case KEY_RSHIFT:    return "Right Shift";
+      case KEY_RALT:      return "Right Alt";
+      case KEY_RSYSTEM:   return "Right System";
+      case KEY_MENU:      return "Menu";
+      case KEY_LBRACKET:  return "Left Bracket";
+      case KEY_RBRACKET:  return "Right Bracket";
+      case KEY_SEMICOLON: return "Semicolon";
+      case KEY_COMMA:     return "Comma";
+      case KEY_PERIOD:    return "Period";
+      case KEY_QUOTE:     return "Quote";
+      case KEY_SLASH:     return "Slash";
+      case KEY_BACKSLASH: return "Backslash";
+      case KEY_TILDE:     return "Tilde";
+      case KEY_EQUAL:     return "Equal";
+      case KEY_DASH:      return "Dash";
+      case KEY_SPACE:     return "Space";
+      case KEY_RETURN:    return "Return";
+      case KEY_BACK:      return "Back";
+      case KEY_TAB:       return "Tab";
+      case KEY_PAGEUP:    return "Page Up";
+      case KEY_PAGEDOWN:  return "Page Down";
+      case KEY_END:       return "End";
+      case KEY_HOME:      return "Home";
+      case KEY_INSERT:    return "Insert";
+      case KEY_DELETE:    return "Delete";
+      case KEY_ADD:       return "Add";
+      case KEY_SUBTRACT:  return "Substract";
+      case KEY_MULTIPLY:  return "Multiply";
+      case KEY_DIVIDE:    return "Divide";
+      case KEY_LEFT:      return "Left";
+      case KEY_RIGHT:     return "Right";
+      case KEY_UP:        return "Up";
+      case KEY_DOWN:      return "Down";
+      case KEY_NUMPAD0:   return "Numpad 0";
+      case KEY_NUMPAD1:   return "Numpad 1";
+      case KEY_NUMPAD2:   return "Numpad 2";
+      case KEY_NUMPAD3:   return "Numpad 3";
+      case KEY_NUMPAD4:   return "Numpad 4";
+      case KEY_NUMPAD5:   return "Numpad 5";
+      case KEY_NUMPAD6:   return "Numpad 6";
+      case KEY_NUMPAD7:   return "Numpad 7";
+      case KEY_NUMPAD8:   return "Numpad 8";
+      case KEY_NUMPAD9:   return "Numpad 9";
+      case KEY_F1:        return "F1";
+      case KEY_F2:        return "F2";
+      case KEY_F3:        return "F3";
+      case KEY_F4:        return "F4";
+      case KEY_F5:        return "F5";
+      case KEY_F6:        return "F6";
+      case KEY_F7:        return "F7";
+      case KEY_F8:        return "F8";
+      case KEY_F9:        return "F9";
+      case KEY_F10:       return "F10";
+      case KEY_F11:       return "F11";
+      case KEY_F12:       return "F12";
+      case KEY_F13:       return "F13";
+      case KEY_F14:       return "F14";
+      case KEY_F15:       return "F15";
+      case KEY_PAUSE:     return "Pause";
+      default:            return "Unknown Key";
+    }
+}
+
+static std::string KeyState(const Event::KeyEvent &event)
+{
+    if (event.Shift || event.Control || event.Alt || event.System)
+    {
+        std::ostringstream buffer;
+        buffer << " [";
+
+        if (event.Shift)
+        {
+            buffer << "Shift";
+        }
+        if (event.Control)
+        {
+            buffer << "Control";
+        }
+        if (event.Alt)
+        {
+            buffer << "Alt";
+        }
+        if (event.System)
+        {
+            buffer << "System";
+        }
+
+        buffer << "]";
+        return buffer.str();
+    }
+    return "";
+}
+
+static void PrintEvent(const Event& event)
+{
+    switch (event.Type)
+    {
+      case Event::EVENT_CLOSED:
+        std::cout << "Event: Window Closed" << std::endl;
+        break;
+      case Event::EVENT_MOVED:
+        std::cout << "Event: Window Moved (" << event.Move.X
+                  << ", " << event.Move.Y << ")" << std::endl;
+        break;
+      case Event::EVENT_RESIZED:
+        std::cout << "Event: Window Resized (" << event.Size.Width
+                  << ", " << event.Size.Height << ")" << std::endl;
+        break;
+      case Event::EVENT_LOST_FOCUS:
+        std::cout << "Event: Window Lost Focus" << std::endl;
+        break;
+      case Event::EVENT_GAINED_FOCUS:
+        std::cout << "Event: Window Gained Focus" << std::endl;
+        break;
+      case Event::EVENT_TEXT_ENTERED:
+        // TODO(cwallez) show the character
+        std::cout << "Event: Text Entered" << std::endl;
+        break;
+      case Event::EVENT_KEY_PRESSED:
+        std::cout << "Event: Key Pressed (" << KeyName(event.Key.Code) << KeyState(event.Key) << ")" << std::endl;
+        break;
+      case Event::EVENT_KEY_RELEASED:
+        std::cout << "Event: Key Released (" << KeyName(event.Key.Code) << KeyState(event.Key) << ")" << std::endl;
+        break;
+      case Event::EVENT_MOUSE_WHEEL_MOVED:
+        std::cout << "Event: Mouse Wheel (" << event.MouseWheel.Delta << ")" << std::endl;
+        break;
+      case Event::EVENT_MOUSE_BUTTON_PRESSED:
+        std::cout << "Event: Mouse Button Pressed " << MouseButtonName(event.MouseButton.Button) <<
+                  " at (" << event.MouseButton.X << ", " << event.MouseButton.Y << ")" << std::endl;
+        break;
+      case Event::EVENT_MOUSE_BUTTON_RELEASED:
+        std::cout << "Event: Mouse Button Released " << MouseButtonName(event.MouseButton.Button) <<
+                  " at (" << event.MouseButton.X << ", " << event.MouseButton.Y << ")" << std::endl;
+        break;
+      case Event::EVENT_MOUSE_MOVED:
+        std::cout << "Event: Mouse Moved (" << event.MouseMove.X
+                  << ", " << event.MouseMove.Y << ")" << std::endl;
+        break;
+      case Event::EVENT_MOUSE_ENTERED:
+        std::cout << "Event: Mouse Entered Window" << std::endl;
+        break;
+      case Event::EVENT_MOUSE_LEFT:
+        std::cout << "Event: Mouse Left Window" << std::endl;
+        break;
+      case Event::EVENT_TEST:
+        std::cout << "Event: Test" << std::endl;
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+}
+#endif
+
+OSWindow::OSWindow()
+    : mX(0),
+      mY(0),
+      mWidth(0),
+      mHeight(0)
+{
+}
+
+OSWindow::~OSWindow()
+{}
+
+int OSWindow::getX() const
+{
+    return mX;
+}
+
+int OSWindow::getY() const
+{
+    return mY;
+}
+
+int OSWindow::getWidth() const
+{
+    return mWidth;
+}
+
+int OSWindow::getHeight() const
+{
+    return mHeight;
+}
+
+bool OSWindow::popEvent(Event *event)
+{
+    if (mEvents.size() > 0 && event)
+    {
+        *event = mEvents.front();
+        mEvents.pop_front();
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+void OSWindow::pushEvent(Event event)
+{
+    switch (event.Type)
+    {
+      case Event::EVENT_MOVED:
+        mX = event.Move.X;
+        mY = event.Move.Y;
+        break;
+      case Event::EVENT_RESIZED:
+        mWidth = event.Size.Width;
+        mHeight = event.Size.Height;
+        break;
+      default:
+        break;
+    }
+
+    mEvents.push_back(event);
+
+#if DEBUG_EVENTS
+    PrintEvent(event);
+#endif
+}
+
+bool OSWindow::didTestEventFire()
+{
+    Event topEvent;
+    while (popEvent(&topEvent))
+    {
+        if (topEvent.Type == Event::EVENT_TEST)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
diff --git a/src/third_party/angle/util/OSWindow.h b/src/third_party/angle/util/OSWindow.h
new file mode 100644
index 0000000..6cb2391
--- /dev/null
+++ b/src/third_party/angle/util/OSWindow.h
@@ -0,0 +1,69 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef SAMPLE_UTIL_WINDOW_H
+#define SAMPLE_UTIL_WINDOW_H
+
+#include <list>
+#include <stdint.h>
+#include <string>
+
+#include <export.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "Event.h"
+
+class ANGLE_EXPORT OSWindow
+{
+  public:
+    OSWindow();
+    virtual ~OSWindow();
+
+    virtual bool initialize(const std::string &name, size_t width, size_t height) = 0;
+    virtual void destroy() = 0;
+
+    int getX() const;
+    int getY() const;
+    int getWidth() const;
+    int getHeight() const;
+
+    // Takes a screenshot of the window, returning the result as a mWidth * mHeight * 4
+    // normalized unsigned byte BGRA array. Note that it will be used to test the window
+    // manager's behavior so it needs to take an actual screenshot of the screen and not
+    // just grab the pixels of the window. Returns if it was successful.
+    virtual bool takeScreenshot(uint8_t *pixelData) { return false; }
+
+    virtual EGLNativeWindowType getNativeWindow() const = 0;
+    virtual EGLNativeDisplayType getNativeDisplay() const = 0;
+
+    virtual void messageLoop() = 0;
+
+    bool popEvent(Event *event);
+    virtual void pushEvent(Event event);
+
+    virtual void setMousePosition(int x, int y) = 0;
+    virtual bool setPosition(int x, int y) = 0;
+    virtual bool resize(int width, int height) = 0;
+    virtual void setVisible(bool isVisible) = 0;
+
+    virtual void signalTestEvent() = 0;
+
+    // Pops events look for the test event
+    bool didTestEventFire();
+
+  protected:
+    int mX;
+    int mY;
+    int mWidth;
+    int mHeight;
+
+    std::list<Event> mEvents;
+};
+
+ANGLE_EXPORT OSWindow *CreateOSWindow();
+
+#endif // SAMPLE_UTIL_WINDOW_H
diff --git a/src/third_party/angle/util/Timer.h b/src/third_party/angle/util/Timer.h
new file mode 100644
index 0000000..b563131
--- /dev/null
+++ b/src/third_party/angle/util/Timer.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef SAMPLE_UTIL_TIMER_H
+#define SAMPLE_UTIL_TIMER_H
+
+#include <export.h>
+
+class ANGLE_EXPORT Timer
+{
+  public:
+    virtual ~Timer() {}
+    virtual void start() = 0;
+    virtual void stop() = 0;
+    virtual double getElapsedTime() const = 0;
+};
+
+ANGLE_EXPORT Timer *CreateTimer();
+
+#endif // SAMPLE_UTIL_TIMER_H
diff --git a/src/third_party/angle/util/android/AndroidPixmap.cpp b/src/third_party/angle/util/android/AndroidPixmap.cpp
new file mode 100644
index 0000000..077ebb5
--- /dev/null
+++ b/src/third_party/angle/util/android/AndroidPixmap.cpp
@@ -0,0 +1,14 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// AndroidPixmap.cpp: Implementation of OSPixmap for Android
+
+#include "OSPixmap.h"
+
+OSPixmap *CreateOSPixmap()
+{
+    return nullptr;
+}
diff --git a/src/third_party/angle/util/android/AndroidWindow.cpp b/src/third_party/angle/util/android/AndroidWindow.cpp
new file mode 100644
index 0000000..e759cda
--- /dev/null
+++ b/src/third_party/angle/util/android/AndroidWindow.cpp
@@ -0,0 +1,154 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// AndroidWindow.cpp: Implementation of OSWindow for Android
+
+#include "android/AndroidWindow.h"
+
+#include <pthread.h>
+
+#include "android/third_party/android_native_app_glue.h"
+#include "common/debug.h"
+
+namespace
+{
+    struct android_app *sApp = nullptr;
+    pthread_mutex_t sInitWindowMutex;
+    pthread_cond_t sInitWindowCond;
+    bool sInitWindowDone = false;
+}  // namespace
+
+AndroidWindow::AndroidWindow()
+{
+}
+
+AndroidWindow::~AndroidWindow()
+{
+}
+
+bool AndroidWindow::initialize(const std::string &name, size_t width, size_t height)
+{
+    return resize(width, height);
+}
+void AndroidWindow::destroy()
+{
+}
+
+EGLNativeWindowType AndroidWindow::getNativeWindow() const
+{
+    // Return the entire Activity Surface for now
+    // sApp->window is valid only after sInitWindowDone, which is true after initialize()
+    return sApp->window;
+}
+
+EGLNativeDisplayType AndroidWindow::getNativeDisplay() const
+{
+    return EGL_DEFAULT_DISPLAY;
+}
+
+void AndroidWindow::messageLoop()
+{
+    // TODO: accumulate events in the real message loop of android_main,
+    // and process them here
+}
+
+void AndroidWindow::setMousePosition(int x, int y)
+{
+    UNIMPLEMENTED();
+}
+
+bool AndroidWindow::setPosition(int x, int y)
+{
+    UNIMPLEMENTED();
+    return false;
+}
+
+bool AndroidWindow::resize(int width, int height)
+{
+    mWidth = width;
+    mHeight = height;
+
+    // sApp->window used below is valid only after Activity Surface is created
+    pthread_mutex_lock(&sInitWindowMutex);
+    while (!sInitWindowDone)
+    {
+        pthread_cond_wait(&sInitWindowCond, &sInitWindowMutex);
+    }
+    pthread_mutex_unlock(&sInitWindowMutex);
+
+    // TODO: figure out a way to set the format as well,
+    // which is available only after EGLWindow initialization
+    int32_t err = ANativeWindow_setBuffersGeometry(sApp->window, mWidth, mHeight, 0);
+    return err == 0;
+}
+
+void AndroidWindow::setVisible(bool isVisible)
+{
+}
+
+void AndroidWindow::signalTestEvent()
+{
+    UNIMPLEMENTED();
+}
+
+OSWindow *CreateOSWindow()
+{
+    // There should be only one live instance of AndroidWindow at a time,
+    // as there is only one Activity Surface behind it.
+    // Creating a new AndroidWindow each time works for ANGLETest,
+    // as it destroys an old window before creating a new one.
+    // TODO: use GLSurfaceView to support multiple windows
+    return new AndroidWindow();
+}
+
+static void onAppCmd(struct android_app *app, int32_t cmd)
+{
+    switch (cmd)
+    {
+        case APP_CMD_INIT_WINDOW:
+            pthread_mutex_lock(&sInitWindowMutex);
+            sInitWindowDone = true;
+            pthread_cond_broadcast(&sInitWindowCond);
+            pthread_mutex_unlock(&sInitWindowMutex);
+            break;
+        // TODO: process other commands and pass them to AndroidWindow for handling
+        // TODO: figure out how to handle APP_CMD_PAUSE,
+        // which should immediately halt all the rendering,
+        // since Activity Surface is no longer available.
+        // Currently tests crash when paused, for example, due to device changing orientation
+    }
+}
+
+static int32_t onInputEvent(struct android_app *app, AInputEvent *event)
+{
+    // TODO: Handle input events
+    return 0;  // 0 == not handled
+}
+
+void android_main(struct android_app *app)
+{
+    int events;
+    struct android_poll_source *source;
+
+    sApp = app;
+    pthread_mutex_init(&sInitWindowMutex, nullptr);
+    pthread_cond_init(&sInitWindowCond, nullptr);
+
+    // Event handlers, invoked from source->process()
+    app->onAppCmd = onAppCmd;
+    app->onInputEvent = onInputEvent;
+
+    // Message loop, polling for events indefinitely (due to -1 timeout)
+    // Must be here in order to handle APP_CMD_INIT_WINDOW event,
+    // which occurs after AndroidWindow::initialize(), but before AndroidWindow::messageLoop
+    while (ALooper_pollAll(-1, nullptr, &events, reinterpret_cast<void **>(&source)) >= 0)
+    {
+        if (source != nullptr)
+        {
+            source->process(app, source);
+        }
+    }
+}
diff --git a/src/third_party/angle/util/android/AndroidWindow.h b/src/third_party/angle/util/android/AndroidWindow.h
new file mode 100644
index 0000000..d660057
--- /dev/null
+++ b/src/third_party/angle/util/android/AndroidWindow.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// AndroidWindow.h: Definition of the implementation of OSWindow for Android
+
+#ifndef UTIL_ANDROID_WINDOW_H_
+#define UTIL_ANDROID_WINDOW_H_
+
+#include "OSWindow.h"
+
+class AndroidWindow : public OSWindow
+{
+  public:
+    AndroidWindow();
+    ~AndroidWindow() override;
+
+    bool initialize(const std::string &name, size_t width, size_t height) override;
+    void destroy() override;
+
+    EGLNativeWindowType getNativeWindow() const override;
+    EGLNativeDisplayType getNativeDisplay() const override;
+
+    void messageLoop() override;
+
+    void setMousePosition(int x, int y) override;
+    bool setPosition(int x, int y) override;
+    bool resize(int width, int height) override;
+    void setVisible(bool isVisible) override;
+
+    void signalTestEvent() override;
+};
+
+#endif /* UTIL_ANDROID_WINDOW_H_ */
diff --git a/src/third_party/angle/util/android/third_party/README.angle b/src/third_party/angle/util/android/third_party/README.angle
new file mode 100644
index 0000000..29547a9
--- /dev/null
+++ b/src/third_party/angle/util/android/third_party/README.angle
@@ -0,0 +1,8 @@
+Name: android_native_app_glue
+URL: https://android.googlesource.com/platform/ndk/+/65966d5033af36134135d1308bdc62b216a5a414/sources/android/native_app_glue
+Version: 65966d5033af36134135d1308bdc62b216a5a414
+License: Apache License, Version 2.0
+License File: http://www.apache.org/licenses/LICENSE-2.0
+
+Description:
+Helper glue code for ANativeActivity implementations
\ No newline at end of file
diff --git a/src/third_party/angle/util/android/third_party/android_native_app_glue.c b/src/third_party/angle/util/android/third_party/android_native_app_glue.c
new file mode 100644
index 0000000..abd51b0
--- /dev/null
+++ b/src/third_party/angle/util/android/third_party/android_native_app_glue.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <jni.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/resource.h>
+
+#include "android_native_app_glue.h"
+#include <android/log.h>
+
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
+
+/* For debug builds, always enable the debug traces in this library */
+#ifndef NDEBUG
+#  define LOGV(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
+#else
+#  define LOGV(...)  ((void)0)
+#endif
+
+static void free_saved_state(struct android_app* android_app) {
+    pthread_mutex_lock(&android_app->mutex);
+    if (android_app->savedState != NULL) {
+        free(android_app->savedState);
+        android_app->savedState = NULL;
+        android_app->savedStateSize = 0;
+    }
+    pthread_mutex_unlock(&android_app->mutex);
+}
+
+int8_t android_app_read_cmd(struct android_app* android_app) {
+    int8_t cmd;
+    if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
+        switch (cmd) {
+            case APP_CMD_SAVE_STATE:
+                free_saved_state(android_app);
+                break;
+        }
+        return cmd;
+    } else {
+        LOGE("No data on command pipe!");
+    }
+    return -1;
+}
+
+static void print_cur_config(struct android_app* android_app) {
+    char lang[2], country[2];
+    AConfiguration_getLanguage(android_app->config, lang);
+    AConfiguration_getCountry(android_app->config, country);
+
+    LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
+            "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
+            "modetype=%d modenight=%d",
+            AConfiguration_getMcc(android_app->config),
+            AConfiguration_getMnc(android_app->config),
+            lang[0], lang[1], country[0], country[1],
+            AConfiguration_getOrientation(android_app->config),
+            AConfiguration_getTouchscreen(android_app->config),
+            AConfiguration_getDensity(android_app->config),
+            AConfiguration_getKeyboard(android_app->config),
+            AConfiguration_getNavigation(android_app->config),
+            AConfiguration_getKeysHidden(android_app->config),
+            AConfiguration_getNavHidden(android_app->config),
+            AConfiguration_getSdkVersion(android_app->config),
+            AConfiguration_getScreenSize(android_app->config),
+            AConfiguration_getScreenLong(android_app->config),
+            AConfiguration_getUiModeType(android_app->config),
+            AConfiguration_getUiModeNight(android_app->config));
+}
+
+void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
+    switch (cmd) {
+        case APP_CMD_INPUT_CHANGED:
+            LOGV("APP_CMD_INPUT_CHANGED\n");
+            pthread_mutex_lock(&android_app->mutex);
+            if (android_app->inputQueue != NULL) {
+                AInputQueue_detachLooper(android_app->inputQueue);
+            }
+            android_app->inputQueue = android_app->pendingInputQueue;
+            if (android_app->inputQueue != NULL) {
+                LOGV("Attaching input queue to looper");
+                AInputQueue_attachLooper(android_app->inputQueue,
+                        android_app->looper, LOOPER_ID_INPUT, NULL,
+                        &android_app->inputPollSource);
+            }
+            pthread_cond_broadcast(&android_app->cond);
+            pthread_mutex_unlock(&android_app->mutex);
+            break;
+
+        case APP_CMD_INIT_WINDOW:
+            LOGV("APP_CMD_INIT_WINDOW\n");
+            pthread_mutex_lock(&android_app->mutex);
+            android_app->window = android_app->pendingWindow;
+            pthread_cond_broadcast(&android_app->cond);
+            pthread_mutex_unlock(&android_app->mutex);
+            break;
+
+        case APP_CMD_TERM_WINDOW:
+            LOGV("APP_CMD_TERM_WINDOW\n");
+            pthread_cond_broadcast(&android_app->cond);
+            break;
+
+        case APP_CMD_RESUME:
+        case APP_CMD_START:
+        case APP_CMD_PAUSE:
+        case APP_CMD_STOP:
+            LOGV("activityState=%d\n", cmd);
+            pthread_mutex_lock(&android_app->mutex);
+            android_app->activityState = cmd;
+            pthread_cond_broadcast(&android_app->cond);
+            pthread_mutex_unlock(&android_app->mutex);
+            break;
+
+        case APP_CMD_CONFIG_CHANGED:
+            LOGV("APP_CMD_CONFIG_CHANGED\n");
+            AConfiguration_fromAssetManager(android_app->config,
+                    android_app->activity->assetManager);
+            print_cur_config(android_app);
+            break;
+
+        case APP_CMD_DESTROY:
+            LOGV("APP_CMD_DESTROY\n");
+            android_app->destroyRequested = 1;
+            break;
+    }
+}
+
+void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
+    switch (cmd) {
+        case APP_CMD_TERM_WINDOW:
+            LOGV("APP_CMD_TERM_WINDOW\n");
+            pthread_mutex_lock(&android_app->mutex);
+            android_app->window = NULL;
+            pthread_cond_broadcast(&android_app->cond);
+            pthread_mutex_unlock(&android_app->mutex);
+            break;
+
+        case APP_CMD_SAVE_STATE:
+            LOGV("APP_CMD_SAVE_STATE\n");
+            pthread_mutex_lock(&android_app->mutex);
+            android_app->stateSaved = 1;
+            pthread_cond_broadcast(&android_app->cond);
+            pthread_mutex_unlock(&android_app->mutex);
+            break;
+
+        case APP_CMD_RESUME:
+            free_saved_state(android_app);
+            break;
+    }
+}
+
+void app_dummy() {
+
+}
+
+static void android_app_destroy(struct android_app* android_app) {
+    LOGV("android_app_destroy!");
+    free_saved_state(android_app);
+    pthread_mutex_lock(&android_app->mutex);
+    if (android_app->inputQueue != NULL) {
+        AInputQueue_detachLooper(android_app->inputQueue);
+    }
+    AConfiguration_delete(android_app->config);
+    android_app->destroyed = 1;
+    pthread_cond_broadcast(&android_app->cond);
+    pthread_mutex_unlock(&android_app->mutex);
+    // Can't touch android_app object after this.
+}
+
+static void process_input(struct android_app* app, struct android_poll_source* source) {
+    AInputEvent* event = NULL;
+    while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
+        LOGV("New input event: type=%d\n", AInputEvent_getType(event));
+        if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
+            continue;
+        }
+        int32_t handled = 0;
+        if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
+        AInputQueue_finishEvent(app->inputQueue, event, handled);
+    }
+}
+
+static void process_cmd(struct android_app* app, struct android_poll_source* source) {
+    int8_t cmd = android_app_read_cmd(app);
+    android_app_pre_exec_cmd(app, cmd);
+    if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
+    android_app_post_exec_cmd(app, cmd);
+}
+
+static void* android_app_entry(void* param) {
+    struct android_app* android_app = (struct android_app*)param;
+
+    android_app->config = AConfiguration_new();
+    AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
+
+    print_cur_config(android_app);
+
+    android_app->cmdPollSource.id = LOOPER_ID_MAIN;
+    android_app->cmdPollSource.app = android_app;
+    android_app->cmdPollSource.process = process_cmd;
+    android_app->inputPollSource.id = LOOPER_ID_INPUT;
+    android_app->inputPollSource.app = android_app;
+    android_app->inputPollSource.process = process_input;
+
+    ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
+    ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
+            &android_app->cmdPollSource);
+    android_app->looper = looper;
+
+    pthread_mutex_lock(&android_app->mutex);
+    android_app->running = 1;
+    pthread_cond_broadcast(&android_app->cond);
+    pthread_mutex_unlock(&android_app->mutex);
+
+    android_main(android_app);
+
+    android_app_destroy(android_app);
+    return NULL;
+}
+
+// --------------------------------------------------------------------
+// Native activity interaction (called from main thread)
+// --------------------------------------------------------------------
+
+static struct android_app* android_app_create(ANativeActivity* activity,
+        void* savedState, size_t savedStateSize) {
+    struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
+    memset(android_app, 0, sizeof(struct android_app));
+    android_app->activity = activity;
+
+    pthread_mutex_init(&android_app->mutex, NULL);
+    pthread_cond_init(&android_app->cond, NULL);
+
+    if (savedState != NULL) {
+        android_app->savedState = malloc(savedStateSize);
+        android_app->savedStateSize = savedStateSize;
+        memcpy(android_app->savedState, savedState, savedStateSize);
+    }
+
+    int msgpipe[2];
+    if (pipe(msgpipe)) {
+        LOGE("could not create pipe: %s", strerror(errno));
+        return NULL;
+    }
+    android_app->msgread = msgpipe[0];
+    android_app->msgwrite = msgpipe[1];
+
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+    pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
+
+    // Wait for thread to start.
+    pthread_mutex_lock(&android_app->mutex);
+    while (!android_app->running) {
+        pthread_cond_wait(&android_app->cond, &android_app->mutex);
+    }
+    pthread_mutex_unlock(&android_app->mutex);
+
+    return android_app;
+}
+
+static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
+    if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+        LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
+    }
+}
+
+static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
+    pthread_mutex_lock(&android_app->mutex);
+    android_app->pendingInputQueue = inputQueue;
+    android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
+    while (android_app->inputQueue != android_app->pendingInputQueue) {
+        pthread_cond_wait(&android_app->cond, &android_app->mutex);
+    }
+    pthread_mutex_unlock(&android_app->mutex);
+}
+
+static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
+    pthread_mutex_lock(&android_app->mutex);
+    if (android_app->pendingWindow != NULL) {
+        android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
+    }
+    android_app->pendingWindow = window;
+    if (window != NULL) {
+        android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
+    }
+    while (android_app->window != android_app->pendingWindow) {
+        pthread_cond_wait(&android_app->cond, &android_app->mutex);
+    }
+    pthread_mutex_unlock(&android_app->mutex);
+}
+
+static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
+    pthread_mutex_lock(&android_app->mutex);
+    android_app_write_cmd(android_app, cmd);
+    while (android_app->activityState != cmd) {
+        pthread_cond_wait(&android_app->cond, &android_app->mutex);
+    }
+    pthread_mutex_unlock(&android_app->mutex);
+}
+
+static void android_app_free(struct android_app* android_app) {
+    pthread_mutex_lock(&android_app->mutex);
+    android_app_write_cmd(android_app, APP_CMD_DESTROY);
+    while (!android_app->destroyed) {
+        pthread_cond_wait(&android_app->cond, &android_app->mutex);
+    }
+    pthread_mutex_unlock(&android_app->mutex);
+
+    close(android_app->msgread);
+    close(android_app->msgwrite);
+    pthread_cond_destroy(&android_app->cond);
+    pthread_mutex_destroy(&android_app->mutex);
+    free(android_app);
+}
+
+static void onDestroy(ANativeActivity* activity) {
+    LOGV("Destroy: %p\n", activity);
+    android_app_free((struct android_app*)activity->instance);
+}
+
+static void onStart(ANativeActivity* activity) {
+    LOGV("Start: %p\n", activity);
+    android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
+}
+
+static void onResume(ANativeActivity* activity) {
+    LOGV("Resume: %p\n", activity);
+    android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
+}
+
+static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
+    struct android_app* android_app = (struct android_app*)activity->instance;
+    void* savedState = NULL;
+
+    LOGV("SaveInstanceState: %p\n", activity);
+    pthread_mutex_lock(&android_app->mutex);
+    android_app->stateSaved = 0;
+    android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
+    while (!android_app->stateSaved) {
+        pthread_cond_wait(&android_app->cond, &android_app->mutex);
+    }
+
+    if (android_app->savedState != NULL) {
+        savedState = android_app->savedState;
+        *outLen = android_app->savedStateSize;
+        android_app->savedState = NULL;
+        android_app->savedStateSize = 0;
+    }
+
+    pthread_mutex_unlock(&android_app->mutex);
+
+    return savedState;
+}
+
+static void onPause(ANativeActivity* activity) {
+    LOGV("Pause: %p\n", activity);
+    android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
+}
+
+static void onStop(ANativeActivity* activity) {
+    LOGV("Stop: %p\n", activity);
+    android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
+}
+
+static void onConfigurationChanged(ANativeActivity* activity) {
+    struct android_app* android_app = (struct android_app*)activity->instance;
+    LOGV("ConfigurationChanged: %p\n", activity);
+    android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
+}
+
+static void onLowMemory(ANativeActivity* activity) {
+    struct android_app* android_app = (struct android_app*)activity->instance;
+    LOGV("LowMemory: %p\n", activity);
+    android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
+}
+
+static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
+    LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
+    android_app_write_cmd((struct android_app*)activity->instance,
+            focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
+}
+
+static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
+    LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
+    android_app_set_window((struct android_app*)activity->instance, window);
+}
+
+static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
+    LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
+    android_app_set_window((struct android_app*)activity->instance, NULL);
+}
+
+static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
+    LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
+    android_app_set_input((struct android_app*)activity->instance, queue);
+}
+
+static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
+    LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
+    android_app_set_input((struct android_app*)activity->instance, NULL);
+}
+
+__attribute__((visibility("default"))) void ANativeActivity_onCreate(ANativeActivity* activity,
+        void* savedState, size_t savedStateSize) {
+    LOGV("Creating: %p\n", activity);
+    activity->callbacks->onDestroy = onDestroy;
+    activity->callbacks->onStart = onStart;
+    activity->callbacks->onResume = onResume;
+    activity->callbacks->onSaveInstanceState = onSaveInstanceState;
+    activity->callbacks->onPause = onPause;
+    activity->callbacks->onStop = onStop;
+    activity->callbacks->onConfigurationChanged = onConfigurationChanged;
+    activity->callbacks->onLowMemory = onLowMemory;
+    activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
+    activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
+    activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
+    activity->callbacks->onInputQueueCreated = onInputQueueCreated;
+    activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
+
+    activity->instance = android_app_create(activity, savedState, savedStateSize);
+}
diff --git a/src/third_party/angle/util/android/third_party/android_native_app_glue.h b/src/third_party/angle/util/android/third_party/android_native_app_glue.h
new file mode 100644
index 0000000..97202e0
--- /dev/null
+++ b/src/third_party/angle/util/android/third_party/android_native_app_glue.h
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _ANDROID_NATIVE_APP_GLUE_H
+#define _ANDROID_NATIVE_APP_GLUE_H
+
+#include <poll.h>
+#include <pthread.h>
+#include <sched.h>
+
+#include <android/configuration.h>
+#include <android/looper.h>
+#include <android/native_activity.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The native activity interface provided by <android/native_activity.h>
+ * is based on a set of application-provided callbacks that will be called
+ * by the Activity's main thread when certain events occur.
+ *
+ * This means that each one of this callbacks _should_ _not_ block, or they
+ * risk having the system force-close the application. This programming
+ * model is direct, lightweight, but constraining.
+ *
+ * The 'android_native_app_glue' static library is used to provide a different
+ * execution model where the application can implement its own main event
+ * loop in a different thread instead. Here's how it works:
+ *
+ * 1/ The application must provide a function named "android_main()" that
+ *    will be called when the activity is created, in a new thread that is
+ *    distinct from the activity's main thread.
+ *
+ * 2/ android_main() receives a pointer to a valid "android_app" structure
+ *    that contains references to other important objects, e.g. the
+ *    ANativeActivity obejct instance the application is running in.
+ *
+ * 3/ the "android_app" object holds an ALooper instance that already
+ *    listens to two important things:
+ *
+ *      - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
+ *        declarations below.
+ *
+ *      - input events coming from the AInputQueue attached to the activity.
+ *
+ *    Each of these correspond to an ALooper identifier returned by
+ *    ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
+ *    respectively.
+ *
+ *    Your application can use the same ALooper to listen to additional
+ *    file-descriptors.  They can either be callback based, or with return
+ *    identifiers starting with LOOPER_ID_USER.
+ *
+ * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
+ *    the returned data will point to an android_poll_source structure.  You
+ *    can call the process() function on it, and fill in android_app->onAppCmd
+ *    and android_app->onInputEvent to be called for your own processing
+ *    of the event.
+ *
+ *    Alternatively, you can call the low-level functions to read and process
+ *    the data directly...  look at the process_cmd() and process_input()
+ *    implementations in the glue to see how to do this.
+ *
+ * See the sample named "native-activity" that comes with the NDK with a
+ * full usage example.  Also look at the JavaDoc of NativeActivity.
+ */
+
+struct android_app;
+
+/**
+ * Data associated with an ALooper fd that will be returned as the "outData"
+ * when that source has data ready.
+ */
+struct android_poll_source {
+    // The identifier of this source.  May be LOOPER_ID_MAIN or
+    // LOOPER_ID_INPUT.
+    int32_t id;
+
+    // The android_app this ident is associated with.
+    struct android_app* app;
+
+    // Function to call to perform the standard processing of data from
+    // this source.
+    void (*process)(struct android_app* app, struct android_poll_source* source);
+};
+
+/**
+ * This is the interface for the standard glue code of a threaded
+ * application.  In this model, the application's code is running
+ * in its own thread separate from the main thread of the process.
+ * It is not required that this thread be associated with the Java
+ * VM, although it will need to be in order to make JNI calls any
+ * Java objects.
+ */
+struct android_app {
+    // The application can place a pointer to its own state object
+    // here if it likes.
+    void* userData;
+
+    // Fill this in with the function to process main app commands (APP_CMD_*)
+    void (*onAppCmd)(struct android_app* app, int32_t cmd);
+
+    // Fill this in with the function to process input events.  At this point
+    // the event has already been pre-dispatched, and it will be finished upon
+    // return.  Return 1 if you have handled the event, 0 for any default
+    // dispatching.
+    int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
+
+    // The ANativeActivity object instance that this app is running in.
+    ANativeActivity* activity;
+
+    // The current configuration the app is running in.
+    AConfiguration* config;
+
+    // This is the last instance's saved state, as provided at creation time.
+    // It is NULL if there was no state.  You can use this as you need; the
+    // memory will remain around until you call android_app_exec_cmd() for
+    // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
+    // These variables should only be changed when processing a APP_CMD_SAVE_STATE,
+    // at which point they will be initialized to NULL and you can malloc your
+    // state and place the information here.  In that case the memory will be
+    // freed for you later.
+    void* savedState;
+    size_t savedStateSize;
+
+    // The ALooper associated with the app's thread.
+    ALooper* looper;
+
+    // When non-NULL, this is the input queue from which the app will
+    // receive user input events.
+    AInputQueue* inputQueue;
+
+    // When non-NULL, this is the window surface that the app can draw in.
+    ANativeWindow* window;
+
+    // Current content rectangle of the window; this is the area where the
+    // window's content should be placed to be seen by the user.
+    ARect contentRect;
+
+    // Current state of the app's activity.  May be either APP_CMD_START,
+    // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
+    int activityState;
+
+    // This is non-zero when the application's NativeActivity is being
+    // destroyed and waiting for the app thread to complete.
+    int destroyRequested;
+
+    // -------------------------------------------------
+    // Below are "private" implementation of the glue code.
+
+    pthread_mutex_t mutex;
+    pthread_cond_t cond;
+
+    int msgread;
+    int msgwrite;
+
+    pthread_t thread;
+
+    struct android_poll_source cmdPollSource;
+    struct android_poll_source inputPollSource;
+
+    int running;
+    int stateSaved;
+    int destroyed;
+    int redrawNeeded;
+    AInputQueue* pendingInputQueue;
+    ANativeWindow* pendingWindow;
+    ARect pendingContentRect;
+};
+
+enum {
+    /**
+     * Looper data ID of commands coming from the app's main thread, which
+     * is returned as an identifier from ALooper_pollOnce().  The data for this
+     * identifier is a pointer to an android_poll_source structure.
+     * These can be retrieved and processed with android_app_read_cmd()
+     * and android_app_exec_cmd().
+     */
+    LOOPER_ID_MAIN = 1,
+
+    /**
+     * Looper data ID of events coming from the AInputQueue of the
+     * application's window, which is returned as an identifier from
+     * ALooper_pollOnce().  The data for this identifier is a pointer to an
+     * android_poll_source structure.  These can be read via the inputQueue
+     * object of android_app.
+     */
+    LOOPER_ID_INPUT = 2,
+
+    /**
+     * Start of user-defined ALooper identifiers.
+     */
+    LOOPER_ID_USER = 3,
+};
+
+enum {
+    /**
+     * Command from main thread: the AInputQueue has changed.  Upon processing
+     * this command, android_app->inputQueue will be updated to the new queue
+     * (or NULL).
+     */
+    APP_CMD_INPUT_CHANGED,
+
+    /**
+     * Command from main thread: a new ANativeWindow is ready for use.  Upon
+     * receiving this command, android_app->window will contain the new window
+     * surface.
+     */
+    APP_CMD_INIT_WINDOW,
+
+    /**
+     * Command from main thread: the existing ANativeWindow needs to be
+     * terminated.  Upon receiving this command, android_app->window still
+     * contains the existing window; after calling android_app_exec_cmd
+     * it will be set to NULL.
+     */
+    APP_CMD_TERM_WINDOW,
+
+    /**
+     * Command from main thread: the current ANativeWindow has been resized.
+     * Please redraw with its new size.
+     */
+    APP_CMD_WINDOW_RESIZED,
+
+    /**
+     * Command from main thread: the system needs that the current ANativeWindow
+     * be redrawn.  You should redraw the window before handing this to
+     * android_app_exec_cmd() in order to avoid transient drawing glitches.
+     */
+    APP_CMD_WINDOW_REDRAW_NEEDED,
+
+    /**
+     * Command from main thread: the content area of the window has changed,
+     * such as from the soft input window being shown or hidden.  You can
+     * find the new content rect in android_app::contentRect.
+     */
+    APP_CMD_CONTENT_RECT_CHANGED,
+
+    /**
+     * Command from main thread: the app's activity window has gained
+     * input focus.
+     */
+    APP_CMD_GAINED_FOCUS,
+
+    /**
+     * Command from main thread: the app's activity window has lost
+     * input focus.
+     */
+    APP_CMD_LOST_FOCUS,
+
+    /**
+     * Command from main thread: the current device configuration has changed.
+     */
+    APP_CMD_CONFIG_CHANGED,
+
+    /**
+     * Command from main thread: the system is running low on memory.
+     * Try to reduce your memory use.
+     */
+    APP_CMD_LOW_MEMORY,
+
+    /**
+     * Command from main thread: the app's activity has been started.
+     */
+    APP_CMD_START,
+
+    /**
+     * Command from main thread: the app's activity has been resumed.
+     */
+    APP_CMD_RESUME,
+
+    /**
+     * Command from main thread: the app should generate a new saved state
+     * for itself, to restore from later if needed.  If you have saved state,
+     * allocate it with malloc and place it in android_app.savedState with
+     * the size in android_app.savedStateSize.  The will be freed for you
+     * later.
+     */
+    APP_CMD_SAVE_STATE,
+
+    /**
+     * Command from main thread: the app's activity has been paused.
+     */
+    APP_CMD_PAUSE,
+
+    /**
+     * Command from main thread: the app's activity has been stopped.
+     */
+    APP_CMD_STOP,
+
+    /**
+     * Command from main thread: the app's activity is being destroyed,
+     * and waiting for the app thread to clean up and exit before proceeding.
+     */
+    APP_CMD_DESTROY,
+};
+
+/**
+ * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
+ * app command message.
+ */
+int8_t android_app_read_cmd(struct android_app* android_app);
+
+/**
+ * Call with the command returned by android_app_read_cmd() to do the
+ * initial pre-processing of the given command.  You can perform your own
+ * actions for the command after calling this function.
+ */
+void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
+
+/**
+ * Call with the command returned by android_app_read_cmd() to do the
+ * final post-processing of the given command.  You must have done your own
+ * actions for the command before calling this function.
+ */
+void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
+
+/**
+ * Dummy function you can call to ensure glue code isn't stripped.
+ */
+void app_dummy();
+
+/**
+ * This is the function that application code must implement, representing
+ * the main entry to the app.
+ */
+extern void android_main(struct android_app* app);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ANDROID_NATIVE_APP_GLUE_H */
diff --git a/src/third_party/angle/util/com_utils.h b/src/third_party/angle/util/com_utils.h
new file mode 100644
index 0000000..225783c
--- /dev/null
+++ b/src/third_party/angle/util/com_utils.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// com_utils.h: Utility functions for working with COM objects
+
+#ifndef UTIL_COM_UTILS_H
+#define UTIL_COM_UTILS_H
+
+template <typename outType>
+inline outType *DynamicCastComObject(IUnknown *object)
+{
+    outType *outObject = nullptr;
+    HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast<void**>(&outObject));
+    if (SUCCEEDED(result))
+    {
+        return outObject;
+    }
+    else
+    {
+        SafeRelease(outObject);
+        return nullptr;
+    }
+}
+
+#endif // UTIL_COM_UTILS_H
diff --git a/src/third_party/angle/util/geometry_utils.cpp b/src/third_party/angle/util/geometry_utils.cpp
new file mode 100644
index 0000000..f14f9d1
--- /dev/null
+++ b/src/third_party/angle/util/geometry_utils.cpp
@@ -0,0 +1,175 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// geometry_utils:
+//   Helper library for generating certain sets of geometry.
+//
+
+#include "geometry_utils.h"
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+using namespace angle;
+
+void CreateSphereGeometry(size_t sliceCount, float radius, SphereGeometry *result)
+{
+    size_t parellelCount = sliceCount / 2;
+    size_t vertexCount   = (parellelCount + 1) * (sliceCount + 1);
+    size_t indexCount    = parellelCount * sliceCount * 6;
+    float angleStep      = static_cast<float>(2.0f * M_PI) / sliceCount;
+
+    result->positions.resize(vertexCount);
+    result->normals.resize(vertexCount);
+    for (size_t i = 0; i < parellelCount + 1; i++)
+    {
+        for (size_t j = 0; j < sliceCount + 1; j++)
+        {
+            Vector3 direction(sinf(angleStep * i) * sinf(angleStep * j), cosf(angleStep * i),
+                              sinf(angleStep * i) * cosf(angleStep * j));
+
+            size_t vertexIdx             = i * (sliceCount + 1) + j;
+            result->positions[vertexIdx] = direction * radius;
+            result->normals[vertexIdx]   = direction;
+        }
+    }
+
+    result->indices.clear();
+    result->indices.reserve(indexCount);
+    for (size_t i = 0; i < parellelCount; i++)
+    {
+        for (size_t j = 0; j < sliceCount; j++)
+        {
+            result->indices.push_back(static_cast<unsigned short>(i * (sliceCount + 1) + j));
+            result->indices.push_back(static_cast<unsigned short>((i + 1) * (sliceCount + 1) + j));
+            result->indices.push_back(
+                static_cast<unsigned short>((i + 1) * (sliceCount + 1) + (j + 1)));
+
+            result->indices.push_back(static_cast<unsigned short>(i * (sliceCount + 1) + j));
+            result->indices.push_back(
+                static_cast<unsigned short>((i + 1) * (sliceCount + 1) + (j + 1)));
+            result->indices.push_back(static_cast<unsigned short>(i * (sliceCount + 1) + (j + 1)));
+        }
+    }
+}
+
+void GenerateCubeGeometry(float radius, CubeGeometry *result)
+{
+    result->positions.resize(24);
+    result->positions[0]  = Vector3(-radius, -radius, -radius);
+    result->positions[1]  = Vector3(-radius, -radius, radius);
+    result->positions[2]  = Vector3(radius, -radius, radius);
+    result->positions[3]  = Vector3(radius, -radius, -radius);
+    result->positions[4]  = Vector3(-radius, radius, -radius);
+    result->positions[5]  = Vector3(-radius, radius, radius);
+    result->positions[6]  = Vector3(radius, radius, radius);
+    result->positions[7]  = Vector3(radius, radius, -radius);
+    result->positions[8]  = Vector3(-radius, -radius, -radius);
+    result->positions[9]  = Vector3(-radius, radius, -radius);
+    result->positions[10] = Vector3(radius, radius, -radius);
+    result->positions[11] = Vector3(radius, -radius, -radius);
+    result->positions[12] = Vector3(-radius, -radius, radius);
+    result->positions[13] = Vector3(-radius, radius, radius);
+    result->positions[14] = Vector3(radius, radius, radius);
+    result->positions[15] = Vector3(radius, -radius, radius);
+    result->positions[16] = Vector3(-radius, -radius, -radius);
+    result->positions[17] = Vector3(-radius, -radius, radius);
+    result->positions[18] = Vector3(-radius, radius, radius);
+    result->positions[19] = Vector3(-radius, radius, -radius);
+    result->positions[20] = Vector3(radius, -radius, -radius);
+    result->positions[21] = Vector3(radius, -radius, radius);
+    result->positions[22] = Vector3(radius, radius, radius);
+    result->positions[23] = Vector3(radius, radius, -radius);
+
+    result->normals.resize(24);
+    result->normals[0]  = Vector3(0.0f, -1.0f, 0.0f);
+    result->normals[1]  = Vector3(0.0f, -1.0f, 0.0f);
+    result->normals[2]  = Vector3(0.0f, -1.0f, 0.0f);
+    result->normals[3]  = Vector3(0.0f, -1.0f, 0.0f);
+    result->normals[4]  = Vector3(0.0f, 1.0f, 0.0f);
+    result->normals[5]  = Vector3(0.0f, 1.0f, 0.0f);
+    result->normals[6]  = Vector3(0.0f, 1.0f, 0.0f);
+    result->normals[7]  = Vector3(0.0f, 1.0f, 0.0f);
+    result->normals[8]  = Vector3(0.0f, 0.0f, -1.0f);
+    result->normals[9]  = Vector3(0.0f, 0.0f, -1.0f);
+    result->normals[10] = Vector3(0.0f, 0.0f, -1.0f);
+    result->normals[11] = Vector3(0.0f, 0.0f, -1.0f);
+    result->normals[12] = Vector3(0.0f, 0.0f, 1.0f);
+    result->normals[13] = Vector3(0.0f, 0.0f, 1.0f);
+    result->normals[14] = Vector3(0.0f, 0.0f, 1.0f);
+    result->normals[15] = Vector3(0.0f, 0.0f, 1.0f);
+    result->normals[16] = Vector3(-1.0f, 0.0f, 0.0f);
+    result->normals[17] = Vector3(-1.0f, 0.0f, 0.0f);
+    result->normals[18] = Vector3(-1.0f, 0.0f, 0.0f);
+    result->normals[19] = Vector3(-1.0f, 0.0f, 0.0f);
+    result->normals[20] = Vector3(1.0f, 0.0f, 0.0f);
+    result->normals[21] = Vector3(1.0f, 0.0f, 0.0f);
+    result->normals[22] = Vector3(1.0f, 0.0f, 0.0f);
+    result->normals[23] = Vector3(1.0f, 0.0f, 0.0f);
+
+    result->texcoords.resize(24);
+    result->texcoords[0]  = Vector2(0.0f, 0.0f);
+    result->texcoords[1]  = Vector2(0.0f, 1.0f);
+    result->texcoords[2]  = Vector2(1.0f, 1.0f);
+    result->texcoords[3]  = Vector2(1.0f, 0.0f);
+    result->texcoords[4]  = Vector2(1.0f, 0.0f);
+    result->texcoords[5]  = Vector2(1.0f, 1.0f);
+    result->texcoords[6]  = Vector2(0.0f, 1.0f);
+    result->texcoords[7]  = Vector2(0.0f, 0.0f);
+    result->texcoords[8]  = Vector2(0.0f, 0.0f);
+    result->texcoords[9]  = Vector2(0.0f, 1.0f);
+    result->texcoords[10] = Vector2(1.0f, 1.0f);
+    result->texcoords[11] = Vector2(1.0f, 0.0f);
+    result->texcoords[12] = Vector2(0.0f, 0.0f);
+    result->texcoords[13] = Vector2(0.0f, 1.0f);
+    result->texcoords[14] = Vector2(1.0f, 1.0f);
+    result->texcoords[15] = Vector2(1.0f, 0.0f);
+    result->texcoords[16] = Vector2(0.0f, 0.0f);
+    result->texcoords[17] = Vector2(0.0f, 1.0f);
+    result->texcoords[18] = Vector2(1.0f, 1.0f);
+    result->texcoords[19] = Vector2(1.0f, 0.0f);
+    result->texcoords[20] = Vector2(0.0f, 0.0f);
+    result->texcoords[21] = Vector2(0.0f, 1.0f);
+    result->texcoords[22] = Vector2(1.0f, 1.0f);
+    result->texcoords[23] = Vector2(1.0f, 0.0f);
+
+    result->indices.resize(36);
+    result->indices[0]  = 0;
+    result->indices[1]  = 2;
+    result->indices[2]  = 1;
+    result->indices[3]  = 0;
+    result->indices[4]  = 3;
+    result->indices[5]  = 2;
+    result->indices[6]  = 4;
+    result->indices[7]  = 5;
+    result->indices[8]  = 6;
+    result->indices[9]  = 4;
+    result->indices[10] = 6;
+    result->indices[11] = 7;
+    result->indices[12] = 8;
+    result->indices[13] = 9;
+    result->indices[14] = 10;
+    result->indices[15] = 8;
+    result->indices[16] = 10;
+    result->indices[17] = 11;
+    result->indices[18] = 12;
+    result->indices[19] = 15;
+    result->indices[20] = 14;
+    result->indices[21] = 12;
+    result->indices[22] = 14;
+    result->indices[23] = 13;
+    result->indices[24] = 16;
+    result->indices[25] = 17;
+    result->indices[26] = 18;
+    result->indices[27] = 16;
+    result->indices[28] = 18;
+    result->indices[29] = 19;
+    result->indices[30] = 20;
+    result->indices[31] = 23;
+    result->indices[32] = 22;
+    result->indices[33] = 20;
+    result->indices[34] = 22;
+    result->indices[35] = 21;
+}
diff --git a/src/third_party/angle/util/geometry_utils.h b/src/third_party/angle/util/geometry_utils.h
new file mode 100644
index 0000000..057dd25
--- /dev/null
+++ b/src/third_party/angle/util/geometry_utils.h
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// geometry_utils:
+//   Helper library for generating certain sets of geometry.
+//
+
+#ifndef UTIL_GEOMETRY_UTILS_H
+#define UTIL_GEOMETRY_UTILS_H
+
+#include <cstddef>
+#include <vector>
+
+#include <export.h>
+#include <GLES2/gl2.h>
+
+#include "common/vector_utils.h"
+
+struct ANGLE_EXPORT SphereGeometry
+{
+    std::vector<angle::Vector3> positions;
+    std::vector<angle::Vector3> normals;
+    std::vector<GLushort> indices;
+};
+
+ANGLE_EXPORT void CreateSphereGeometry(size_t sliceCount, float radius, SphereGeometry *result);
+
+struct ANGLE_EXPORT CubeGeometry
+{
+    std::vector<angle::Vector3> positions;
+    std::vector<angle::Vector3> normals;
+    std::vector<angle::Vector2> texcoords;
+    std::vector<GLushort> indices;
+};
+
+ANGLE_EXPORT void GenerateCubeGeometry(float radius, CubeGeometry *result);
+
+#endif  // UTIL_GEOMETRY_UTILS_H
diff --git a/src/third_party/angle/util/keyboard.h b/src/third_party/angle/util/keyboard.h
new file mode 100644
index 0000000..2718dd5
--- /dev/null
+++ b/src/third_party/angle/util/keyboard.h
@@ -0,0 +1,117 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef SAMPLE_UTIL_KEYBOARD_H
+#define SAMPLE_UTIL_KEYBOARD_H
+
+enum Key
+{
+    KEY_UNKNOWN,
+    KEY_A,            // The A key
+    KEY_B,            // The B key
+    KEY_C,            // The C key
+    KEY_D,            // The D key
+    KEY_E,            // The E key
+    KEY_F,            // The F key
+    KEY_G,            // The G key
+    KEY_H,            // The H key
+    KEY_I,            // The I key
+    KEY_J,            // The J key
+    KEY_K,            // The K key
+    KEY_L,            // The L key
+    KEY_M,            // The M key
+    KEY_N,            // The N key
+    KEY_O,            // The O key
+    KEY_P,            // The P key
+    KEY_Q,            // The Q key
+    KEY_R,            // The R key
+    KEY_S,            // The S key
+    KEY_T,            // The T key
+    KEY_U,            // The U key
+    KEY_V,            // The V key
+    KEY_W,            // The W key
+    KEY_X,            // The X key
+    KEY_Y,            // The Y key
+    KEY_Z,            // The Z key
+    KEY_NUM0,         // The 0 key
+    KEY_NUM1,         // The 1 key
+    KEY_NUM2,         // The 2 key
+    KEY_NUM3,         // The 3 key
+    KEY_NUM4,         // The 4 key
+    KEY_NUM5,         // The 5 key
+    KEY_NUM6,         // The 6 key
+    KEY_NUM7,         // The 7 key
+    KEY_NUM8,         // The 8 key
+    KEY_NUM9,         // The 9 key
+    KEY_ESCAPE,       // The escape key
+    KEY_LCONTROL,     // The left control key
+    KEY_LSHIFT,       // The left shift key
+    KEY_LALT,         // The left alt key
+    KEY_LSYSTEM,      // The left OS specific key: Window (Windows and Linux), Apple (MacOS X), ...
+    KEY_RCONTROL,     // The right control key
+    KEY_RSHIFT,       // The right shift key
+    KEY_RALT,         // The right alt key
+    KEY_RSYSTEM,      // The right OS specific key: Window (Windows and Linux), Apple (MacOS X), ...
+    KEY_MENU,         // The menu key
+    KEY_LBRACKET,     // The [ key
+    KEY_RBRACKET,     // The ] key
+    KEY_SEMICOLON,    // The ; key
+    KEY_COMMA,        // The , key
+    KEY_PERIOD,       // The . key
+    KEY_QUOTE,        // The ' key
+    KEY_SLASH,        // The / key
+    KEY_BACKSLASH,    // The \ key
+    KEY_TILDE,        // The ~ key
+    KEY_EQUAL,        // The = key
+    KEY_DASH,         // The - key
+    KEY_SPACE,        // The space key
+    KEY_RETURN,       // The return key
+    KEY_BACK,         // The backspace key
+    KEY_TAB,          // The tabulation key
+    KEY_PAGEUP,       // The page up key
+    KEY_PAGEDOWN,     // The page down key
+    KEY_END,          // The end key
+    KEY_HOME,         // The home key
+    KEY_INSERT,       // The insert key
+    KEY_DELETE,       // The delete key
+    KEY_ADD,          // +
+    KEY_SUBTRACT,     // -
+    KEY_MULTIPLY,     // *
+    KEY_DIVIDE,       // /
+    KEY_LEFT,         // Left arrow
+    KEY_RIGHT,        // Right arrow
+    KEY_UP,           // Up arrow
+    KEY_DOWN,         // Down arrow
+    KEY_NUMPAD0,      // The numpad 0 key
+    KEY_NUMPAD1,      // The numpad 1 key
+    KEY_NUMPAD2,      // The numpad 2 key
+    KEY_NUMPAD3,      // The numpad 3 key
+    KEY_NUMPAD4,      // The numpad 4 key
+    KEY_NUMPAD5,      // The numpad 5 key
+    KEY_NUMPAD6,      // The numpad 6 key
+    KEY_NUMPAD7,      // The numpad 7 key
+    KEY_NUMPAD8,      // The numpad 8 key
+    KEY_NUMPAD9,      // The numpad 9 key
+    KEY_F1,           // The F1 key
+    KEY_F2,           // The F2 key
+    KEY_F3,           // The F3 key
+    KEY_F4,           // The F4 key
+    KEY_F5,           // The F5 key
+    KEY_F6,           // The F6 key
+    KEY_F7,           // The F7 key
+    KEY_F8,           // The F8 key
+    KEY_F9,           // The F8 key
+    KEY_F10,          // The F10 key
+    KEY_F11,          // The F11 key
+    KEY_F12,          // The F12 key
+    KEY_F13,          // The F13 key
+    KEY_F14,          // The F14 key
+    KEY_F15,          // The F15 key
+    KEY_PAUSE,        // The pause key
+    KEY_COUNT,
+};
+
+#endif // SAMPLE_UTIL_KEYBOARD_H
diff --git a/src/third_party/angle/util/linux/LinuxTimer.cpp b/src/third_party/angle/util/linux/LinuxTimer.cpp
new file mode 100644
index 0000000..1968205
--- /dev/null
+++ b/src/third_party/angle/util/linux/LinuxTimer.cpp
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// LinuxTimer.cpp: Implementation of a high precision timer class on Linux
+
+#include "linux/LinuxTimer.h"
+#include <iostream>
+
+LinuxTimer::LinuxTimer()
+    : mRunning(false)
+{
+}
+
+void LinuxTimer::start()
+{
+    clock_gettime(CLOCK_MONOTONIC, &mStartTime);
+    mRunning = true;
+}
+
+void LinuxTimer::stop()
+{
+    clock_gettime(CLOCK_MONOTONIC, &mStopTime);
+    mRunning = false;
+}
+
+double LinuxTimer::getElapsedTime() const
+{
+    struct timespec endTime;
+    if (mRunning)
+    {
+        clock_gettime(CLOCK_MONOTONIC, &endTime);
+    }
+    else
+    {
+        endTime = mStopTime;
+    }
+
+    double startSeconds = mStartTime.tv_sec + (1.0 / 1000000000) * mStartTime.tv_nsec;
+    double endSeconds = endTime.tv_sec + (1.0 / 1000000000) * endTime.tv_nsec;
+    return endSeconds - startSeconds;
+}
+
+Timer *CreateTimer()
+{
+    return new LinuxTimer();
+}
diff --git a/src/third_party/angle/util/linux/LinuxTimer.h b/src/third_party/angle/util/linux/LinuxTimer.h
new file mode 100644
index 0000000..8e68dd8
--- /dev/null
+++ b/src/third_party/angle/util/linux/LinuxTimer.h
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// LinuxTimer.h: Definition of a high precision timer class on Linux
+
+#ifndef UTIL_LINUX_TIMER_H
+#define UTIL_LINUX_TIMER_H
+
+#include <time.h>
+
+#include "Timer.h"
+
+class LinuxTimer : public Timer
+{
+  public:
+    LinuxTimer();
+
+    void start() override;
+    void stop() override;
+    double getElapsedTime() const override;
+
+  private:
+    bool mRunning;
+    struct timespec mStartTime;
+    struct timespec mStopTime;
+};
+
+#endif // UTIL_LINUX_TIMER_H
diff --git a/src/third_party/angle/util/mouse.h b/src/third_party/angle/util/mouse.h
new file mode 100644
index 0000000..d51b96d
--- /dev/null
+++ b/src/third_party/angle/util/mouse.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef SAMPLE_UTIL_MOUSE_H
+#define SAMPLE_UTIL_MOUSE_H
+
+enum MouseButton
+{
+    MOUSEBUTTON_UNKNOWN,
+    MOUSEBUTTON_LEFT,
+    MOUSEBUTTON_RIGHT,
+    MOUSEBUTTON_MIDDLE,
+    MOUSEBUTTON_BUTTON4,
+    MOUSEBUTTON_BUTTON5,
+    MOUSEBUTTON_COUNT,
+};
+
+#endif // SAMPLE_UTIL_MOUSE_H
diff --git a/src/third_party/angle/util/osx/OSXPixmap.h b/src/third_party/angle/util/osx/OSXPixmap.h
new file mode 100644
index 0000000..f9cdfdc
--- /dev/null
+++ b/src/third_party/angle/util/osx/OSXPixmap.h
@@ -0,0 +1,14 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// OSXPixmap.h: Definition of the implementation of OSPixmap for OSX
+
+#ifndef UTIL_OSX_PIXMAP_H_
+#define UTIL_OSX_PIXMAP_H_
+
+#include "OSPixmap.h"
+
+#endif // UTIL_OSX_PIXMAP_H_
diff --git a/src/third_party/angle/util/osx/OSXPixmap.mm b/src/third_party/angle/util/osx/OSXPixmap.mm
new file mode 100644
index 0000000..16af8bf
--- /dev/null
+++ b/src/third_party/angle/util/osx/OSXPixmap.mm
@@ -0,0 +1,15 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// OSXPixmap.cpp: Implementation of OSPixmap for OSX
+
+#include "osx/OSXPixmap.h"
+
+// TODO(cwallez) find out the native OSX pixmap type and implement this
+OSPixmap *CreateOSPixmap()
+{
+    return nullptr;
+}
diff --git a/src/third_party/angle/util/osx/OSXTimer.cpp b/src/third_party/angle/util/osx/OSXTimer.cpp
new file mode 100644
index 0000000..909155d
--- /dev/null
+++ b/src/third_party/angle/util/osx/OSXTimer.cpp
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// OSXTimer.cpp: Implementation of a high precision timer class on OSX
+
+#include "osx/OSXTimer.h"
+
+#include <CoreServices/CoreServices.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+
+OSXTimer::OSXTimer()
+    : mRunning(false)
+{
+}
+
+void OSXTimer::start()
+{
+    mStartTime = mach_absolute_time();
+    mRunning = true;
+}
+
+void OSXTimer::stop()
+{
+    mStopTime = mach_absolute_time();
+    mRunning = false;
+}
+
+double OSXTimer::getElapsedTime() const
+{
+    // If this is the first time we've run, get the timebase.
+    // We can use denom == 0 to indicate that sTimebaseInfo is
+    // uninitialised because it makes no sense to have a zero
+    // denominator in a fraction.
+    static mach_timebase_info_data_t timebaseInfo;
+    static double secondCoeff;
+
+    if ( timebaseInfo.denom == 0 )
+    {
+        mach_timebase_info(&timebaseInfo);
+        secondCoeff = timebaseInfo.numer * (1.0 / 1000000000) / timebaseInfo.denom;
+    }
+
+    if (mRunning)
+    {
+        return secondCoeff * (mach_absolute_time() - mStartTime);
+    }
+    else
+    {
+        return secondCoeff * (mStopTime - mStartTime);
+    }
+}
+
+Timer *CreateTimer()
+{
+    return new OSXTimer();
+}
diff --git a/src/third_party/angle/util/osx/OSXTimer.h b/src/third_party/angle/util/osx/OSXTimer.h
new file mode 100644
index 0000000..af1c278
--- /dev/null
+++ b/src/third_party/angle/util/osx/OSXTimer.h
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// OSXTimer.h: Definition of a high precision timer class on OSX
+
+#ifndef UTIL_OSX_TIMER_H_
+#define UTIL_OSX_TIMER_H_
+
+#include <stdint.h>
+#include <time.h>
+
+#include "Timer.h"
+
+class OSXTimer : public Timer
+{
+  public:
+    OSXTimer();
+
+    void start() override;
+    void stop() override;
+    double getElapsedTime() const override;
+
+  private:
+    bool mRunning;
+    uint64_t mStartTime;
+    uint64_t mStopTime;
+};
+
+#endif // UTIL_OSX_TIMER_H_
diff --git a/src/third_party/angle/util/osx/OSXWindow.h b/src/third_party/angle/util/osx/OSXWindow.h
new file mode 100644
index 0000000..980f816
--- /dev/null
+++ b/src/third_party/angle/util/osx/OSXWindow.h
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// OSXWindow.h: Definition of the implementation of OSWindow for OSX
+
+#ifndef UTIL_OSX_WINDOW_H_
+#define UTIL_OSX_WINDOW_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include "OSWindow.h"
+
+class OSXWindow;
+
+@interface WindowDelegate : NSObject
+{
+    OSXWindow *mWindow;
+}
+- (id) initWithWindow: (OSXWindow*) window;
+@end
+
+@interface ContentView : NSView
+{
+    OSXWindow *mWindow;
+    NSTrackingArea *mTrackingArea;
+    int mCurrentModifier;
+}
+- (id) initWithWindow: (OSXWindow*) window;
+@end
+
+class OSXWindow : public OSWindow
+{
+  public:
+    OSXWindow();
+    ~OSXWindow();
+
+    bool initialize(const std::string &name, size_t width, size_t height) override;
+    void destroy() override;
+
+    EGLNativeWindowType getNativeWindow() const override;
+    EGLNativeDisplayType getNativeDisplay() const override;
+
+    void messageLoop() override;
+
+    void setMousePosition(int x, int y) override;
+    bool setPosition(int x, int y) override;
+    bool resize(int width, int height) override;
+    void setVisible(bool isVisible) override;
+
+    void signalTestEvent() override;
+
+    NSWindow *getNSWindow() const;
+
+  private:
+    NSWindow *mWindow;
+    WindowDelegate *mDelegate;
+    ContentView *mView;
+};
+
+#endif // UTIL_OSX_WINDOW_H_
diff --git a/src/third_party/angle/util/osx/OSXWindow.mm b/src/third_party/angle/util/osx/OSXWindow.mm
new file mode 100644
index 0000000..98e7124
--- /dev/null
+++ b/src/third_party/angle/util/osx/OSXWindow.mm
@@ -0,0 +1,697 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// OSXWindow.mm: Implementation of OSWindow for OSX
+
+#include "osx/OSXWindow.h"
+
+#include <set>
+// Include Carbon to use the keycode names in Carbon's Event.h
+#include <Carbon/Carbon.h>
+
+#include "common/debug.h"
+
+// On OSX 10.12 a number of AppKit interfaces have been renamed for consistency, and the previous
+// symbols tagged as deprecated. However we can't simply use the new symbols as it would break
+// compilation on our automated testing that doesn't use OSX 10.12 yet. So we just ignore the
+// warnings.
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+// Some events such as "ShouldTerminate" are sent to the whole application so we keep a list of
+// all the windows in order to forward the event to each of them. However this and calling pushEvent
+// in ApplicationDelegate is inherently unsafe in a multithreaded environment.
+static std::set<OSXWindow*> gAllWindows;
+
+@interface Application : NSApplication
+@end
+
+@implementation Application
+    - (void) sendEvent: (NSEvent*) nsEvent
+    {
+        if ([nsEvent type] == NSApplicationDefined)
+        {
+            for (auto window : gAllWindows)
+            {
+                if ([window->getNSWindow() windowNumber] == [nsEvent windowNumber])
+                {
+                    Event event;
+                    event.Type = Event::EVENT_TEST;
+                    window->pushEvent(event);
+                }
+            }
+        }
+        [super sendEvent: nsEvent];
+    }
+@end
+
+// The Delegate receiving application-wide events.
+@interface ApplicationDelegate : NSObject
+@end
+
+@implementation ApplicationDelegate
+    - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication*) sender
+    {
+        Event event;
+        event.Type = Event::EVENT_CLOSED;
+        for (auto window : gAllWindows)
+        {
+            window->pushEvent(event);
+        }
+        return NSTerminateCancel;
+    }
+@end
+static ApplicationDelegate *gApplicationDelegate = nil;
+
+static bool InitializeAppKit()
+{
+    if (NSApp != nil)
+    {
+        return true;
+    }
+
+    // Initialize the global variable "NSApp"
+    [Application sharedApplication];
+
+    // Make us appear in the dock
+    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+    // Register our global event handler
+    gApplicationDelegate = [[ApplicationDelegate alloc] init];
+    if (gApplicationDelegate == nil)
+    {
+        return false;
+    }
+    [NSApp setDelegate: static_cast<id>(gApplicationDelegate)];
+
+    // Set our status to "started" so we are not bouncing in the doc and can activate
+    [NSApp finishLaunching];
+    return true;
+}
+
+// NS's and CG's coordinate systems start at the bottom left, while OSWindow's coordinate
+// system starts at the top left. This function converts the Y coordinate accordingly.
+static float YCoordToFromCG(float y)
+{
+    float screenHeight = CGDisplayBounds(CGMainDisplayID()).size.height;
+    return screenHeight - y;
+}
+
+// Delegate for window-wide events, note that the protocol doesn't contain anything input related.
+@implementation WindowDelegate
+    - (id) initWithWindow: (OSXWindow*) window
+    {
+        self = [super init];
+        if (self != nil)
+        {
+            mWindow = window;
+        }
+        return self;
+    }
+
+    - (void) onOSXWindowDeleted
+    {
+        mWindow = nil;
+    }
+
+    - (BOOL) windowShouldClose: (id) sender
+    {
+        Event event;
+        event.Type = Event::EVENT_CLOSED;
+        mWindow->pushEvent(event);
+        return NO;
+    }
+
+    - (void) windowDidResize: (NSNotification*) notification
+    {
+        NSSize windowSize = [[mWindow->getNSWindow() contentView] frame].size;
+        Event event;
+        event.Type = Event::EVENT_RESIZED;
+        event.Size.Width = windowSize.width;
+        event.Size.Height = windowSize.height;
+        mWindow->pushEvent(event);
+    }
+
+    - (void) windowDidMove: (NSNotification*) notification
+    {
+        NSRect screenspace = [mWindow->getNSWindow() frame];
+        Event event;
+        event.Type = Event::EVENT_MOVED;
+        event.Move.X = screenspace.origin.x;
+        event.Move.Y = YCoordToFromCG(screenspace.origin.y + screenspace.size.height);
+        mWindow->pushEvent(event);
+    }
+
+    - (void) windowDidBecomeKey: (NSNotification*) notification
+    {
+        Event event;
+        event.Type = Event::EVENT_GAINED_FOCUS;
+        mWindow->pushEvent(event);
+        [self retain];
+    }
+
+    - (void) windowDidResignKey: (NSNotification*) notification
+    {
+        if (mWindow != nil)
+        {
+            Event event;
+            event.Type = Event::EVENT_LOST_FOCUS;
+            mWindow->pushEvent(event);
+        }
+        [self release];
+    }
+@end
+
+static Key NSCodeToKey(int keyCode)
+{
+    // Missing KEY_PAUSE
+    switch (keyCode)
+    {
+      case kVK_Shift:               return KEY_LSHIFT;
+      case kVK_RightShift:          return KEY_RSHIFT;
+      case kVK_Option:              return KEY_LALT;
+      case kVK_RightOption:         return KEY_RALT;
+      case kVK_Control:             return KEY_LCONTROL;
+      case kVK_RightControl:        return KEY_RCONTROL;
+      case kVK_Command:             return KEY_LSYSTEM;
+      // Right System doesn't have a name, but shows up as 0x36.
+      case 0x36:                    return KEY_RSYSTEM;
+      case kVK_Function:            return KEY_MENU;
+
+      case kVK_ANSI_Semicolon:      return KEY_SEMICOLON;
+      case kVK_ANSI_Slash:          return KEY_SLASH;
+      case kVK_ANSI_Equal:          return KEY_EQUAL;
+      case kVK_ANSI_Minus:          return KEY_DASH;
+      case kVK_ANSI_LeftBracket:    return KEY_LBRACKET;
+      case kVK_ANSI_RightBracket:   return KEY_RBRACKET;
+      case kVK_ANSI_Comma:          return KEY_COMMA;
+      case kVK_ANSI_Period:         return KEY_PERIOD;
+      case kVK_ANSI_Backslash:      return KEY_BACKSLASH;
+      case kVK_ANSI_Grave:          return KEY_TILDE;
+      case kVK_Escape:              return KEY_ESCAPE;
+      case kVK_Space:               return KEY_SPACE;
+      case kVK_Return:              return KEY_RETURN;
+      case kVK_Delete:              return KEY_BACK;
+      case kVK_Tab:                 return KEY_TAB;
+      case kVK_PageUp:              return KEY_PAGEUP;
+      case kVK_PageDown:            return KEY_PAGEDOWN;
+      case kVK_End:                 return KEY_END;
+      case kVK_Home:                return KEY_HOME;
+      case kVK_Help:                return KEY_INSERT;
+      case kVK_ForwardDelete:       return KEY_DELETE;
+      case kVK_ANSI_KeypadPlus:     return KEY_ADD;
+      case kVK_ANSI_KeypadMinus:    return KEY_SUBTRACT;
+      case kVK_ANSI_KeypadMultiply: return KEY_MULTIPLY;
+      case kVK_ANSI_KeypadDivide:   return KEY_DIVIDE;
+
+      case kVK_F1:                  return KEY_F1;
+      case kVK_F2:                  return KEY_F2;
+      case kVK_F3:                  return KEY_F3;
+      case kVK_F4:                  return KEY_F4;
+      case kVK_F5:                  return KEY_F5;
+      case kVK_F6:                  return KEY_F6;
+      case kVK_F7:                  return KEY_F7;
+      case kVK_F8:                  return KEY_F8;
+      case kVK_F9:                  return KEY_F9;
+      case kVK_F10:                 return KEY_F10;
+      case kVK_F11:                 return KEY_F11;
+      case kVK_F12:                 return KEY_F12;
+      case kVK_F13:                 return KEY_F13;
+      case kVK_F14:                 return KEY_F14;
+      case kVK_F15:                 return KEY_F15;
+
+      case kVK_LeftArrow:           return KEY_LEFT;
+      case kVK_RightArrow:          return KEY_RIGHT;
+      case kVK_DownArrow:           return KEY_DOWN;
+      case kVK_UpArrow:             return KEY_UP;
+
+      case kVK_ANSI_Keypad0:        return KEY_NUMPAD0;
+      case kVK_ANSI_Keypad1:        return KEY_NUMPAD1;
+      case kVK_ANSI_Keypad2:        return KEY_NUMPAD2;
+      case kVK_ANSI_Keypad3:        return KEY_NUMPAD3;
+      case kVK_ANSI_Keypad4:        return KEY_NUMPAD4;
+      case kVK_ANSI_Keypad5:        return KEY_NUMPAD5;
+      case kVK_ANSI_Keypad6:        return KEY_NUMPAD6;
+      case kVK_ANSI_Keypad7:        return KEY_NUMPAD7;
+      case kVK_ANSI_Keypad8:        return KEY_NUMPAD8;
+      case kVK_ANSI_Keypad9:        return KEY_NUMPAD9;
+
+      case kVK_ANSI_A:              return KEY_A;
+      case kVK_ANSI_B:              return KEY_B;
+      case kVK_ANSI_C:              return KEY_C;
+      case kVK_ANSI_D:              return KEY_D;
+      case kVK_ANSI_E:              return KEY_E;
+      case kVK_ANSI_F:              return KEY_F;
+      case kVK_ANSI_G:              return KEY_G;
+      case kVK_ANSI_H:              return KEY_H;
+      case kVK_ANSI_I:              return KEY_I;
+      case kVK_ANSI_J:              return KEY_J;
+      case kVK_ANSI_K:              return KEY_K;
+      case kVK_ANSI_L:              return KEY_L;
+      case kVK_ANSI_M:              return KEY_M;
+      case kVK_ANSI_N:              return KEY_N;
+      case kVK_ANSI_O:              return KEY_O;
+      case kVK_ANSI_P:              return KEY_P;
+      case kVK_ANSI_Q:              return KEY_Q;
+      case kVK_ANSI_R:              return KEY_R;
+      case kVK_ANSI_S:              return KEY_S;
+      case kVK_ANSI_T:              return KEY_T;
+      case kVK_ANSI_U:              return KEY_U;
+      case kVK_ANSI_V:              return KEY_V;
+      case kVK_ANSI_W:              return KEY_W;
+      case kVK_ANSI_X:              return KEY_X;
+      case kVK_ANSI_Y:              return KEY_Y;
+      case kVK_ANSI_Z:              return KEY_Z;
+
+      case kVK_ANSI_1:              return KEY_NUM1;
+      case kVK_ANSI_2:              return KEY_NUM2;
+      case kVK_ANSI_3:              return KEY_NUM3;
+      case kVK_ANSI_4:              return KEY_NUM4;
+      case kVK_ANSI_5:              return KEY_NUM5;
+      case kVK_ANSI_6:              return KEY_NUM6;
+      case kVK_ANSI_7:              return KEY_NUM7;
+      case kVK_ANSI_8:              return KEY_NUM8;
+      case kVK_ANSI_9:              return KEY_NUM9;
+      case kVK_ANSI_0:              return KEY_NUM0;
+    }
+
+    return Key(0);
+}
+
+static void AddNSKeyStateToEvent(Event *event, int state)
+{
+    event->Key.Shift = state & NSShiftKeyMask;
+    event->Key.Control = state & NSControlKeyMask;
+    event->Key.Alt = state & NSAlternateKeyMask;
+    event->Key.System = state & NSCommandKeyMask;
+}
+
+static MouseButton TranslateMouseButton(int button)
+{
+    switch (button)
+    {
+      case 2:
+        return MOUSEBUTTON_MIDDLE;
+      case 3:
+        return MOUSEBUTTON_BUTTON4;
+      case 4:
+        return MOUSEBUTTON_BUTTON5;
+      default:
+        return MOUSEBUTTON_UNKNOWN;
+    }
+}
+
+// Delegate for NSView events, mostly the input events
+@implementation ContentView
+    - (id) initWithWindow: (OSXWindow*) window
+    {
+        self = [super init];
+        if (self != nil)
+        {
+            mWindow = window;
+            mTrackingArea = nil;
+            mCurrentModifier = 0;
+            [self updateTrackingAreas];
+        }
+        return self;
+    }
+
+    - (void) dealloc
+    {
+        [mTrackingArea release];
+        [super dealloc];
+    }
+
+    - (void) updateTrackingAreas
+    {
+        if (mTrackingArea != nil)
+        {
+            [self removeTrackingArea: mTrackingArea];
+            [mTrackingArea release];
+            mTrackingArea = nil;
+        }
+
+        NSRect bounds = [self bounds];
+        NSTrackingAreaOptions flags = NSTrackingMouseEnteredAndExited |
+                                      NSTrackingActiveInKeyWindow |
+                                      NSTrackingCursorUpdate |
+                                      NSTrackingInVisibleRect |
+                                      NSTrackingAssumeInside;
+        mTrackingArea = [[NSTrackingArea alloc] initWithRect: bounds
+                                                    options: flags
+                                                      owner: self
+                                                   userInfo: nil];
+
+        [self addTrackingArea: mTrackingArea];
+        [super updateTrackingAreas];
+    }
+
+    // Helps with performance
+    - (BOOL) isOpaque
+    {
+        return YES;
+    }
+
+    - (BOOL) canBecomeKeyView
+    {
+        return YES;
+    }
+
+    - (BOOL) acceptsFirstResponder
+    {
+        return YES;
+    }
+
+    // Handle mouse events from the NSResponder protocol
+    - (float) translateMouseY: (float) y
+    {
+        return [self frame].size.height - y;
+    }
+
+    - (void) addButtonEvent: (NSEvent*) nsEvent type:(Event::EventType) eventType button:(MouseButton) button
+    {
+        Event event;
+        event.Type = eventType;
+        event.MouseButton.Button = button;
+        event.MouseButton.X = [nsEvent locationInWindow].x;
+        event.MouseButton.Y = [self translateMouseY: [nsEvent locationInWindow].y];
+        mWindow->pushEvent(event);
+    }
+
+    - (void) mouseDown: (NSEvent*) event
+    {
+        [self addButtonEvent: event
+                        type: Event::EVENT_MOUSE_BUTTON_PRESSED
+                      button: MOUSEBUTTON_LEFT];
+    }
+
+    - (void) mouseDragged: (NSEvent*) event
+    {
+        [self mouseMoved: event];
+    }
+
+    - (void) mouseUp: (NSEvent*) event
+    {
+        [self addButtonEvent: event
+                        type: Event::EVENT_MOUSE_BUTTON_RELEASED
+                      button: MOUSEBUTTON_LEFT];
+    }
+
+    - (void) mouseMoved: (NSEvent*) nsEvent
+    {
+        Event event;
+        event.Type = Event::EVENT_MOUSE_MOVED;
+        event.MouseMove.X = [nsEvent locationInWindow].x;
+        event.MouseMove.Y = [self translateMouseY: [nsEvent locationInWindow].y];
+        mWindow->pushEvent(event);
+    }
+
+    - (void) mouseEntered: (NSEvent*) nsEvent
+    {
+        Event event;
+        event.Type = Event::EVENT_MOUSE_ENTERED;
+        mWindow->pushEvent(event);
+    }
+
+    - (void) mouseExited: (NSEvent*) nsEvent
+    {
+        Event event;
+        event.Type = Event::EVENT_MOUSE_LEFT;
+        mWindow->pushEvent(event);
+    }
+
+    - (void)rightMouseDown:(NSEvent *)event
+    {
+        [self addButtonEvent: event
+                        type: Event::EVENT_MOUSE_BUTTON_PRESSED
+                      button: MOUSEBUTTON_RIGHT];
+    }
+
+    - (void) rightMouseDragged: (NSEvent*) event
+    {
+        [self mouseMoved: event];
+    }
+
+    - (void) rightMouseUp: (NSEvent*)event
+    {
+        [self addButtonEvent: event
+                        type: Event::EVENT_MOUSE_BUTTON_RELEASED
+                      button: MOUSEBUTTON_RIGHT];
+    }
+
+    - (void) otherMouseDown: (NSEvent*) event
+    {
+        [self addButtonEvent: event
+                        type: Event::EVENT_MOUSE_BUTTON_PRESSED
+                      button: TranslateMouseButton([event buttonNumber])];
+    }
+
+    - (void) otherMouseDragged: (NSEvent*) event
+    {
+        [self mouseMoved: event];
+    }
+
+    - (void) otherMouseUp: (NSEvent*) event
+    {
+        [self addButtonEvent: event
+                        type: Event::EVENT_MOUSE_BUTTON_RELEASED
+                      button: TranslateMouseButton([event buttonNumber])];
+    }
+
+    - (void) scrollWheel: (NSEvent*) nsEvent
+    {
+        if (static_cast<int>([nsEvent deltaY]) == 0)
+        {
+            return;
+        }
+
+        Event event;
+        event.Type = Event::EVENT_MOUSE_WHEEL_MOVED;
+        event.MouseWheel.Delta = [nsEvent deltaY];
+        mWindow->pushEvent(event);
+    }
+
+    // Handle key events from the NSResponder protocol
+    - (void) keyDown: (NSEvent*) nsEvent
+    {
+        // TODO(cwallez) also send text events
+        Event event;
+        event.Type = Event::EVENT_KEY_PRESSED;
+        event.Key.Code = NSCodeToKey([nsEvent keyCode]);
+        AddNSKeyStateToEvent(&event, [nsEvent modifierFlags]);
+        mWindow->pushEvent(event);
+    }
+
+    - (void) keyUp: (NSEvent*) nsEvent
+    {
+        Event event;
+        event.Type = Event::EVENT_KEY_RELEASED;
+        event.Key.Code = NSCodeToKey([nsEvent keyCode]);
+        AddNSKeyStateToEvent(&event, [nsEvent modifierFlags]);
+        mWindow->pushEvent(event);
+    }
+
+    // Modifier keys do not trigger keyUp/Down events but only flagsChanged events.
+    - (void) flagsChanged: (NSEvent*) nsEvent
+    {
+        Event event;
+
+        // Guess if the key has been pressed or released with the change of modifiers
+        // It currently doesn't work when modifiers are unchanged, such as when pressing
+        // both shift keys. GLFW has a solution for this but it requires tracking the
+        // state of the keys. Implementing this is still TODO(cwallez)
+        int modifier = [nsEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
+        if (modifier < mCurrentModifier)
+        {
+            event.Type = Event::EVENT_KEY_RELEASED;
+        }
+        else
+        {
+            event.Type = Event::EVENT_KEY_PRESSED;
+        }
+        mCurrentModifier = modifier;
+
+        event.Key.Code = NSCodeToKey([nsEvent keyCode]);
+        AddNSKeyStateToEvent(&event, [nsEvent modifierFlags]);
+        mWindow->pushEvent(event);
+    }
+@end
+
+OSXWindow::OSXWindow()
+    : mWindow(nil),
+      mDelegate(nil),
+      mView(nil)
+{
+}
+
+OSXWindow::~OSXWindow()
+{
+    destroy();
+}
+
+bool OSXWindow::initialize(const std::string &name, size_t width, size_t height)
+{
+    if (!InitializeAppKit())
+    {
+        return false;
+    }
+
+    unsigned int styleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask |
+                             NSMiniaturizableWindowMask;
+    mWindow = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, width, height)
+                                          styleMask: styleMask
+                                            backing: NSBackingStoreBuffered
+                                              defer: NO];
+
+    if (mWindow == nil)
+    {
+        return false;
+    }
+
+    mDelegate = [[WindowDelegate alloc] initWithWindow: this];
+    if (mDelegate == nil)
+    {
+        return false;
+    }
+    [mWindow setDelegate: static_cast<id>(mDelegate)];
+
+    mView = [[ContentView alloc] initWithWindow: this];
+    if (mView == nil)
+    {
+        return false;
+    }
+    [mView setWantsLayer:YES];
+
+    [mWindow setContentView: mView];
+    [mWindow setTitle: [NSString stringWithUTF8String: name.c_str()]];
+    [mWindow setAcceptsMouseMovedEvents: YES];
+    [mWindow center];
+
+    [NSApp activateIgnoringOtherApps: YES];
+
+    mX = 0;
+    mY = 0;
+    mWidth = width;
+    mHeight = height;
+
+    gAllWindows.insert(this);
+    return true;
+}
+
+void OSXWindow::destroy()
+{
+    gAllWindows.erase(this);
+
+    [mView release];
+    mView = nil;
+    [mDelegate onOSXWindowDeleted];
+    [mDelegate release];
+    mDelegate = nil;
+    [mWindow release];
+    mWindow = nil;
+}
+
+EGLNativeWindowType OSXWindow::getNativeWindow() const
+{
+    return [mView layer];
+}
+
+EGLNativeDisplayType OSXWindow::getNativeDisplay() const
+{
+    // TODO(cwallez): implement it once we have defined what EGLNativeDisplayType is
+    return static_cast<EGLNativeDisplayType>(0);
+}
+
+void OSXWindow::messageLoop()
+{
+    @autoreleasepool
+    {
+        while (true)
+        {
+            NSEvent* event = [NSApp nextEventMatchingMask: NSAnyEventMask
+                                                untilDate: [NSDate distantPast]
+                                                   inMode: NSDefaultRunLoopMode
+                                                  dequeue: YES];
+            if (event == nil)
+            {
+                break;
+            }
+
+            if ([event type] == NSAppKitDefined)
+            {
+                continue;
+            }
+            [NSApp sendEvent: event];
+        }
+    }
+}
+
+void OSXWindow::setMousePosition(int x, int y)
+{
+    y = [mWindow frame].size.height - y -1;
+    NSPoint screenspace;
+
+    #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
+        screenspace = [mWindow convertBaseToScreen: NSMakePoint(x, y)];
+    #else
+        screenspace = [mWindow convertRectToScreen: NSMakeRect(x, y, 0, 0)].origin;
+    #endif
+    CGWarpMouseCursorPosition(CGPointMake(screenspace.x, YCoordToFromCG(screenspace.y)));
+}
+
+bool OSXWindow::setPosition(int x, int y)
+{
+    // Given CG and NS's coordinate system, the "Y" position of a window is the Y coordinate
+    // of the bottom of the window.
+    int newBottom = [mWindow frame].size.height + y;
+    NSRect emptyRect = NSMakeRect(x, YCoordToFromCG(newBottom), 0, 0);
+    [mWindow setFrameOrigin: [mWindow frameRectForContentRect: emptyRect].origin];
+    return true;
+}
+
+bool OSXWindow::resize(int width, int height)
+{
+    [mWindow setContentSize: NSMakeSize(width, height)];
+    return true;
+}
+
+void OSXWindow::setVisible(bool isVisible)
+{
+    if (isVisible)
+    {
+        [mWindow makeKeyAndOrderFront: nil];
+    }
+    else
+    {
+        [mWindow orderOut: nil];
+    }
+}
+
+void OSXWindow::signalTestEvent()
+{
+    @autoreleasepool
+    {
+        NSEvent *event = [NSEvent otherEventWithType: NSApplicationDefined
+                                            location: NSMakePoint(0, 0)
+                                       modifierFlags: 0
+                                           timestamp: 0.0
+                                        windowNumber: [mWindow windowNumber]
+                                             context: nil
+                                             subtype: 0
+                                               data1: 0
+                                               data2: 0];
+        [NSApp postEvent: event atStart: YES];
+    }
+}
+
+NSWindow* OSXWindow::getNSWindow() const
+{
+    return mWindow;
+}
+
+OSWindow *CreateOSWindow()
+{
+    return new OSXWindow;
+}
diff --git a/src/third_party/angle/util/ozone/OzonePixmap.cpp b/src/third_party/angle/util/ozone/OzonePixmap.cpp
new file mode 100644
index 0000000..cc310a7
--- /dev/null
+++ b/src/third_party/angle/util/ozone/OzonePixmap.cpp
@@ -0,0 +1,12 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "OSPixmap.h"
+
+OSPixmap *CreateOSPixmap()
+{
+    return nullptr;
+}
diff --git a/src/third_party/angle/util/ozone/OzoneWindow.cpp b/src/third_party/angle/util/ozone/OzoneWindow.cpp
new file mode 100644
index 0000000..9feece2
--- /dev/null
+++ b/src/third_party/angle/util/ozone/OzoneWindow.cpp
@@ -0,0 +1,82 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// OzoneWindow.cpp: Implementation of OSWindow for Ozone
+
+#include "ozone/OzoneWindow.h"
+
+int OzoneWindow::sLastDepth = 0;
+
+OzoneWindow::OzoneWindow()
+{
+}
+
+OzoneWindow::~OzoneWindow()
+{
+}
+
+bool OzoneWindow::initialize(const std::string &name, size_t width, size_t height)
+{
+    mNative.x = mX = 0;
+    mNative.y = mY = 0;
+    mNative.width = mWidth = width;
+    mNative.height = mHeight = height;
+    mNative.borderWidth  = 5;
+    mNative.borderHeight = 5;
+    mNative.visible      = 0;
+    mNative.depth        = sLastDepth++;
+    return true;
+}
+
+void OzoneWindow::destroy()
+{
+}
+
+EGLNativeWindowType OzoneWindow::getNativeWindow() const
+{
+    return reinterpret_cast<EGLNativeWindowType>(&mNative);
+}
+
+EGLNativeDisplayType OzoneWindow::getNativeDisplay() const
+{
+    return EGL_DEFAULT_DISPLAY;
+}
+
+void OzoneWindow::messageLoop()
+{
+}
+
+void OzoneWindow::setMousePosition(int x, int y)
+{
+}
+
+bool OzoneWindow::setPosition(int x, int y)
+{
+    mNative.x = mX = x;
+    mNative.y = mY = y;
+    return true;
+}
+
+bool OzoneWindow::resize(int width, int height)
+{
+    mNative.width = mWidth = width;
+    mNative.height = mHeight = height;
+    return true;
+}
+
+void OzoneWindow::setVisible(bool isVisible)
+{
+    mNative.visible = isVisible;
+}
+
+void OzoneWindow::signalTestEvent()
+{
+}
+
+OSWindow *CreateOSWindow()
+{
+    return new OzoneWindow();
+}
diff --git a/src/third_party/angle/util/ozone/OzoneWindow.h b/src/third_party/angle/util/ozone/OzoneWindow.h
new file mode 100644
index 0000000..1a2fed5
--- /dev/null
+++ b/src/third_party/angle/util/ozone/OzoneWindow.h
@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// OzoneWindow.h: Definition of the implementation of OSWindow for Ozone
+
+#ifndef UTIL_OZONE_WINDOW_H
+#define UTIL_OZONE_WINDOW_H
+
+#include <string>
+
+#include "OSWindow.h"
+
+class OzoneWindow : public OSWindow
+{
+  public:
+    OzoneWindow();
+    ~OzoneWindow();
+
+    bool initialize(const std::string &name, size_t width, size_t height) override;
+    void destroy() override;
+
+    EGLNativeWindowType getNativeWindow() const override;
+    EGLNativeDisplayType getNativeDisplay() const override;
+
+    void messageLoop() override;
+
+    void setMousePosition(int x, int y) override;
+    bool setPosition(int x, int y) override;
+    bool resize(int width, int height) override;
+    void setVisible(bool isVisible) override;
+
+    void signalTestEvent() override;
+
+  private:
+    struct Native
+    {
+        int32_t x;
+        int32_t y;
+        int32_t width;
+        int32_t height;
+        int32_t borderWidth;
+        int32_t borderHeight;
+        int32_t visible;
+        int32_t depth;
+    };
+
+    Native mNative;
+    static int sLastDepth;
+};
+
+#endif  // UTIL_OZONE_WINDOW_H
diff --git a/src/third_party/angle/util/posix/Posix_system_utils.cpp b/src/third_party/angle/util/posix/Posix_system_utils.cpp
new file mode 100644
index 0000000..010735b
--- /dev/null
+++ b/src/third_party/angle/util/posix/Posix_system_utils.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Posix_system_utils.cpp: Implementation of OS-specific functions for Posix systems
+
+#include "system_utils.h"
+
+#include <sys/resource.h>
+#include <dlfcn.h>
+#include <sched.h>
+#include <time.h>
+#include <unistd.h>
+
+namespace angle
+{
+
+void Sleep(unsigned int milliseconds)
+{
+    // On Windows Sleep(0) yields while it isn't guaranteed by Posix's sleep
+    // so we replicate Windows' behavior with an explicit yield.
+    if (milliseconds == 0)
+    {
+        sched_yield();
+    }
+    else
+    {
+        timespec sleepTime =
+        {
+            .tv_sec = milliseconds / 1000,
+            .tv_nsec = (milliseconds % 1000) * 1000000,
+        };
+
+        nanosleep(&sleepTime, nullptr);
+    }
+}
+
+void SetLowPriorityProcess()
+{
+    setpriority(PRIO_PROCESS, getpid(), 10);
+}
+
+void WriteDebugMessage(const char *format, ...)
+{
+    // TODO(jmadill): Implement this
+}
+
+class PosixLibrary : public Library
+{
+  public:
+    PosixLibrary(const std::string &libraryName);
+    ~PosixLibrary() override;
+
+    void *getSymbol(const std::string &symbolName) override;
+
+  private:
+    void *mModule;
+};
+
+PosixLibrary::PosixLibrary(const std::string &libraryName) : mModule(nullptr)
+{
+    const auto &fullName = libraryName + "." + GetSharedLibraryExtension();
+    mModule              = dlopen(fullName.c_str(), RTLD_NOW);
+}
+
+PosixLibrary::~PosixLibrary()
+{
+    if (mModule)
+    {
+        dlclose(mModule);
+    }
+}
+
+void *PosixLibrary::getSymbol(const std::string &symbolName)
+{
+    if (!mModule)
+    {
+        return nullptr;
+    }
+
+    return dlsym(mModule, symbolName.c_str());
+}
+
+Library *loadLibrary(const std::string &libraryName)
+{
+    return new PosixLibrary(libraryName);
+}
+
+} // namespace angle
diff --git a/src/third_party/angle/util/random_utils.cpp b/src/third_party/angle/util/random_utils.cpp
new file mode 100644
index 0000000..2968a3f
--- /dev/null
+++ b/src/third_party/angle/util/random_utils.cpp
@@ -0,0 +1,75 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// random_utils:
+//   Helper functions for random number generation.
+//
+
+#include "random_utils.h"
+
+#include <chrono>
+
+#include <cstdlib>
+
+namespace angle
+{
+
+// Seed from clock
+RNG::RNG()
+{
+    long long timeSeed = std::chrono::system_clock::now().time_since_epoch().count();
+    mGenerator.seed(static_cast<unsigned int>(timeSeed));
+}
+
+// Seed from fixed number.
+RNG::RNG(unsigned int seed) : mGenerator(seed)
+{
+}
+
+RNG::~RNG()
+{
+}
+
+void RNG::reseed(unsigned int newSeed)
+{
+    mGenerator.seed(newSeed);
+}
+
+int RNG::randomInt()
+{
+    std::uniform_int_distribution<int> intDistribution;
+    return intDistribution(mGenerator);
+}
+
+int RNG::randomIntBetween(int min, int max)
+{
+    std::uniform_int_distribution<int> intDistribution(min, max);
+    return intDistribution(mGenerator);
+}
+
+unsigned int RNG::randomUInt()
+{
+    std::uniform_int_distribution<unsigned int> uintDistribution;
+    return uintDistribution(mGenerator);
+}
+
+float RNG::randomFloat()
+{
+    std::uniform_real_distribution<float> floatDistribution;
+    return floatDistribution(mGenerator);
+}
+
+float RNG::randomFloatBetween(float min, float max)
+{
+    std::uniform_real_distribution<float> floatDistribution(min, max);
+    return floatDistribution(mGenerator);
+}
+
+float RNG::randomNegativeOneToOne()
+{
+    return randomFloatBetween(-1.0f, 1.0f);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/util/random_utils.h b/src/third_party/angle/util/random_utils.h
new file mode 100644
index 0000000..1128e03
--- /dev/null
+++ b/src/third_party/angle/util/random_utils.h
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// random_utils:
+//   Helper functions for random number generation.
+//
+
+#ifndef UTIL_RANDOM_UTILS_H
+#define UTIL_RANDOM_UTILS_H
+
+// TODO(jmadill): Rework this if Chromium decides to ban <random>
+#include <random>
+
+#include <export.h>
+
+namespace angle
+{
+
+class ANGLE_EXPORT RNG
+{
+  public:
+    // Seed from clock
+    RNG();
+    // Seed from fixed number.
+    RNG(unsigned int seed);
+    ~RNG();
+
+    void reseed(unsigned int newSeed);
+
+    int randomInt();
+    int randomIntBetween(int min, int max);
+    unsigned int randomUInt();
+    float randomFloat();
+    float randomFloatBetween(float min, float max);
+    float randomNegativeOneToOne();
+
+  private:
+    std::default_random_engine mGenerator;
+};
+
+// Implemented htis way because of cross-module allocation issues.
+inline void FillVectorWithRandomUBytes(std::vector<uint8_t> *data)
+{
+    RNG rng;
+    for (size_t i = 0; i < data->size(); ++i)
+    {
+        (*data)[i] = static_cast<uint8_t>(rng.randomIntBetween(0, 255));
+    }
+}
+
+}  // namespace angle
+
+#endif // UTIL_RANDOM_UTILS_H
diff --git a/src/third_party/angle/util/shader_utils.cpp b/src/third_party/angle/util/shader_utils.cpp
new file mode 100644
index 0000000..60fcd60
--- /dev/null
+++ b/src/third_party/angle/util/shader_utils.cpp
@@ -0,0 +1,208 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "shader_utils.h"
+
+#include <vector>
+#include <iostream>
+#include <fstream>
+
+static std::string ReadFileToString(const std::string &source)
+{
+    std::ifstream stream(source.c_str());
+    if (!stream)
+    {
+        std::cerr << "Failed to load shader file: " << source;
+        return "";
+    }
+
+    std::string result;
+
+    stream.seekg(0, std::ios::end);
+    result.reserve(static_cast<unsigned int>(stream.tellg()));
+    stream.seekg(0, std::ios::beg);
+
+    result.assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
+
+    return result;
+}
+
+GLuint CompileShader(GLenum type, const std::string &source)
+{
+    GLuint shader = glCreateShader(type);
+
+    const char *sourceArray[1] = { source.c_str() };
+    glShaderSource(shader, 1, sourceArray, nullptr);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+
+    if (compileResult == 0)
+    {
+        GLint infoLogLength;
+        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+        // Info log length includes the null terminator, so 1 means that the info log is an empty
+        // string.
+        if (infoLogLength > 1)
+        {
+            std::vector<GLchar> infoLog(infoLogLength);
+            glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
+            std::cerr << "shader compilation failed: " << &infoLog[0];
+        }
+        else
+        {
+            std::cerr << "shader compilation failed. <Empty log message>";
+        }
+
+        glDeleteShader(shader);
+        shader = 0;
+    }
+
+    return shader;
+}
+
+GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath)
+{
+    std::string source = ReadFileToString(sourcePath);
+    if (source.empty())
+    {
+        return 0;
+    }
+
+    return CompileShader(type, source);
+}
+
+GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages)
+{
+    if (glGetError() != GL_NO_ERROR)
+        return 0;
+
+    GLint linkStatus;
+    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+    if (linkStatus == 0)
+    {
+        if (outputErrorMessages)
+        {
+            GLint infoLogLength;
+            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+            // Info log length includes the null terminator, so 1 means that the info log is an
+            // empty string.
+            if (infoLogLength > 1)
+            {
+                std::vector<GLchar> infoLog(infoLogLength);
+                glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
+                                    &infoLog[0]);
+
+                std::cerr << "program link failed: " << &infoLog[0];
+            }
+            else
+            {
+                std::cerr << "program link failed. <Empty log message>";
+            }
+        }
+
+        glDeleteProgram(program);
+        return 0;
+    }
+
+    return program;
+}
+
+GLuint CompileProgramWithTransformFeedback(
+    const std::string &vsSource,
+    const std::string &fsSource,
+    const std::vector<std::string> &transformFeedbackVaryings,
+    GLenum bufferMode)
+{
+    GLuint program = glCreateProgram();
+
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+    if (vs == 0 || fs == 0)
+    {
+        glDeleteShader(fs);
+        glDeleteShader(vs);
+        glDeleteProgram(program);
+        return 0;
+    }
+
+    glAttachShader(program, vs);
+    glDeleteShader(vs);
+
+    glAttachShader(program, fs);
+    glDeleteShader(fs);
+
+    if (transformFeedbackVaryings.size() > 0)
+    {
+        std::vector<const char *> constCharTFVaryings;
+
+        for (const std::string &transformFeedbackVarying : transformFeedbackVaryings)
+        {
+            constCharTFVaryings.push_back(transformFeedbackVarying.c_str());
+        }
+
+        glTransformFeedbackVaryings(program, static_cast<GLsizei>(transformFeedbackVaryings.size()),
+                                    &constCharTFVaryings[0], bufferMode);
+    }
+
+    glLinkProgram(program);
+
+    return CheckLinkStatusAndReturnProgram(program, true);
+}
+
+GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource)
+{
+    std::vector<std::string> emptyVector;
+    return CompileProgramWithTransformFeedback(vsSource, fsSource, emptyVector, GL_NONE);
+}
+
+GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath)
+{
+    std::string vsSource = ReadFileToString(vsPath);
+    std::string fsSource = ReadFileToString(fsPath);
+    if (vsSource.empty() || fsSource.empty())
+    {
+        return 0;
+    }
+
+    return CompileProgram(vsSource, fsSource);
+}
+
+GLuint CompileComputeProgram(const std::string &csSource, bool outputErrorMessages)
+{
+    GLuint program = glCreateProgram();
+
+    GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
+    if (cs == 0)
+    {
+        glDeleteProgram(program);
+        return 0;
+    }
+
+    glAttachShader(program, cs);
+
+    glLinkProgram(program);
+
+    return CheckLinkStatusAndReturnProgram(program, outputErrorMessages);
+}
+
+GLuint LoadBinaryProgramOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
+{
+    GLuint program = glCreateProgram();
+    glProgramBinaryOES(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
+    return CheckLinkStatusAndReturnProgram(program, true);
+}
+
+GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
+{
+    GLuint program = glCreateProgram();
+    glProgramBinary(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
+    return CheckLinkStatusAndReturnProgram(program, true);
+}
diff --git a/src/third_party/angle/util/shader_utils.h b/src/third_party/angle/util/shader_utils.h
new file mode 100644
index 0000000..706b6d7
--- /dev/null
+++ b/src/third_party/angle/util/shader_utils.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef SAMPLE_UTIL_SHADER_UTILS_H
+#define SAMPLE_UTIL_SHADER_UTILS_H
+
+#include <export.h>
+#include <GLES3/gl31.h>
+#include <GLES3/gl3.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <string>
+#include <vector>
+
+#define SHADER_SOURCE(...) #__VA_ARGS__
+
+ANGLE_EXPORT GLuint CompileShader(GLenum type, const std::string &source);
+ANGLE_EXPORT GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath);
+
+ANGLE_EXPORT GLuint
+CompileProgramWithTransformFeedback(const std::string &vsSource,
+                                    const std::string &fsSource,
+                                    const std::vector<std::string> &transformFeedbackVaryings,
+                                    GLenum bufferMode);
+ANGLE_EXPORT GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource);
+ANGLE_EXPORT GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath);
+ANGLE_EXPORT GLuint CompileComputeProgram(const std::string &csSource,
+                                          bool outputErrorMessages = true);
+
+ANGLE_EXPORT GLuint LoadBinaryProgramOES(const std::vector<uint8_t> &binary, GLenum binaryFormat);
+ANGLE_EXPORT GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary, GLenum binaryFormat);
+
+#endif // SAMPLE_UTIL_SHADER_UTILS_H
diff --git a/src/third_party/angle/util/system_utils.h b/src/third_party/angle/util/system_utils.h
new file mode 100644
index 0000000..1da43b8
--- /dev/null
+++ b/src/third_party/angle/util/system_utils.h
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils.h: declaration of OS-specific utility functions
+
+#ifndef UTIL_SYSTEM_UTILS_H_
+#define UTIL_SYSTEM_UTILS_H_
+
+#include <string>
+
+#include <export.h>
+
+#include "common/angleutils.h"
+#include "common/system_utils.h"
+
+namespace angle
+{
+
+// Cross platform equivalent of the Windows Sleep function
+ANGLE_EXPORT void Sleep(unsigned int milliseconds);
+
+ANGLE_EXPORT void SetLowPriorityProcess();
+
+// Write a debug message, either to a standard output or Debug window.
+ANGLE_EXPORT void WriteDebugMessage(const char *format, ...);
+
+class ANGLE_EXPORT Library : angle::NonCopyable
+{
+  public:
+    virtual ~Library() {}
+    virtual void *getSymbol(const std::string &symbolName) = 0;
+};
+
+ANGLE_EXPORT Library *loadLibrary(const std::string &libraryName);
+
+} // namespace angle
+
+#endif  // UTIL_SYSTEM_UTILS_H_
diff --git a/src/third_party/angle/util/util.gyp b/src/third_party/angle/util/util.gyp
new file mode 100644
index 0000000..bda8a05
--- /dev/null
+++ b/src/third_party/angle/util/util.gyp
@@ -0,0 +1,251 @@
+# Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+    # Everything below  this is duplicated in the GN build, except Mac support.
+    # If you change anything also change angle/BUILD.gn
+    'variables':
+    {
+        'util_sources':
+        [
+            'com_utils.h',
+            'keyboard.h',
+            'geometry_utils.cpp',
+            'geometry_utils.h',
+            'mouse.h',
+            'random_utils.cpp',
+            'random_utils.h',
+            'shader_utils.cpp',
+            'shader_utils.h',
+            'system_utils.h',
+            'Event.h',
+            'EGLWindow.cpp',
+            'EGLWindow.h',
+            'Matrix.cpp',
+            'Matrix.h',
+            'OSPixmap.h',
+            'OSWindow.cpp',
+            'OSWindow.h',
+            'Timer.h',
+        ],
+        'util_win32_sources':
+        [
+            'windows/win32/Win32_system_utils.cpp',
+            'windows/win32/Win32Pixmap.cpp',
+            'windows/win32/Win32Pixmap.h',
+            'windows/win32/Win32Window.cpp',
+            'windows/win32/Win32Window.h',
+            'windows/Windows_system_utils.cpp',
+            'windows/WindowsTimer.cpp',
+            'windows/WindowsTimer.h',
+        ],
+        'util_winrt_sources':
+        [
+            'windows/winrt/WinRT_system_utils.cpp',
+            'windows/winrt/WinRTPixmap.cpp',
+            'windows/winrt/WinRTWindow.cpp',
+            'windows/winrt/WinRTWindow.h',
+            'windows/Windows_system_utils.cpp',
+            'windows/WindowsTimer.cpp',
+            'windows/WindowsTimer.h',
+        ],
+        'util_linux_sources':
+        [
+            'linux/LinuxTimer.cpp',
+            'linux/LinuxTimer.h',
+            'posix/Posix_system_utils.cpp',
+        ],
+        'util_x11_sources':
+        [
+            'x11/X11Pixmap.cpp',
+            'x11/X11Pixmap.h',
+            'x11/X11Window.cpp',
+            'x11/X11Window.h',
+        ],
+        'util_ozone_sources':
+        [
+            'ozone/OzonePixmap.cpp',
+            'ozone/OzoneWindow.cpp',
+            'ozone/OzoneWindow.h',
+        ],
+        'util_osx_sources':
+        [
+            'osx/OSXTimer.cpp',
+            'osx/OSXTimer.h',
+            'osx/OSXPixmap.mm',
+            'osx/OSXPixmap.h',
+            'osx/OSXWindow.mm',
+            'osx/OSXWindow.h',
+            'posix/Posix_system_utils.cpp',
+        ],
+        'util_android_sources':
+        [
+            'android/AndroidPixmap.cpp',
+            'android/AndroidWindow.cpp',
+            'android/AndroidWindow.h',
+            'android/third_party/android_native_app_glue.c',
+            'android/third_party/android_native_app_glue.h',
+        ],
+    },
+    'targets':
+    [
+        {
+            'target_name': 'angle_util_config',
+            'type': 'none',
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(angle_path)/include',
+                    '<(angle_path)/util',
+                ],
+                'sources':
+                [
+                    '<@(util_sources)',
+                ],
+                'defines':
+                [
+                    'GL_GLEXT_PROTOTYPES',
+                    'EGL_EGLEXT_PROTOTYPES',
+                    'LIBANGLE_UTIL_IMPLEMENTATION',
+                ],
+                'conditions':
+                [
+                    ['OS=="win" and angle_build_winrt==0',
+                    {
+                        'sources':
+                        [
+                            '<@(util_win32_sources)',
+                        ],
+                    }],
+                    ['OS=="win" and angle_build_winrt==1',
+                    {
+                        'sources':
+                        [
+                            '<@(util_winrt_sources)',
+                        ],
+                    }],
+                    ['OS=="linux"',
+                    {
+                        'sources':
+                        [
+                            '<@(util_linux_sources)',
+                        ],
+                        'link_settings':
+                        {
+                            'libraries':
+                            [
+                                '-ldl',
+                            ],
+                        },
+                    }],
+                    ['use_x11==1',
+                    {
+                        'sources':
+                        [
+                            '<@(util_x11_sources)',
+                        ],
+                        'link_settings':
+                        {
+                            'ldflags':
+                            [
+                                '<!@(<(pkg-config) --libs-only-L --libs-only-other x11 xi)',
+                            ],
+                            'libraries':
+                            [
+                                '<!@(<(pkg-config) --libs-only-l x11 xi)',
+                            ],
+                        },
+                    }],
+                    ['use_ozone==1',
+                    {
+                        'sources':
+                        [
+                            '<@(util_ozone_sources)',
+                        ],
+                    }],
+                    ['OS=="mac"',
+                    {
+                        'sources':
+                        [
+                            '<@(util_osx_sources)',
+                        ],
+                        'xcode_settings':
+                        {
+                            'DYLIB_INSTALL_NAME_BASE': '@rpath',
+                        },
+                        'link_settings':
+                        {
+                            'libraries':
+                            [
+                                '$(SDKROOT)/System/Library/Frameworks/AppKit.framework',
+                                '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
+                            ],
+                        },
+                    }],
+                ],
+            },
+        },
+
+        {
+            'target_name': 'angle_util',
+            'type': 'shared_library',
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'dependencies':
+            [
+                'angle_util_config',
+                '<(angle_path)/src/angle.gyp:angle_common',
+                '<(angle_path)/src/angle.gyp:libEGL',
+                '<(angle_path)/src/angle.gyp:libGLESv2',
+            ],
+            'export_dependent_settings':
+            [
+                '<(angle_path)/src/angle.gyp:angle_common',
+            ],
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(angle_path)/include',
+                    '<(angle_path)/util',
+                ],
+                'defines':
+                [
+                    'GL_GLEXT_PROTOTYPES',
+                    'EGL_EGLEXT_PROTOTYPES',
+                ],
+            },
+        },
+
+        {
+            'target_name': 'angle_util_static',
+            'type': 'static_library',
+            'includes': [ '../gyp/common_defines.gypi', ],
+            'dependencies':
+            [
+                'angle_util_config',
+                '<(angle_path)/src/angle.gyp:angle_common',
+                '<(angle_path)/src/angle.gyp:libEGL_static',
+                '<(angle_path)/src/angle.gyp:libGLESv2_static',
+            ],
+            'export_dependent_settings':
+            [
+                '<(angle_path)/src/angle.gyp:angle_common',
+            ],
+            'direct_dependent_settings':
+            {
+                'include_dirs':
+                [
+                    '<(angle_path)/include',
+                    '<(angle_path)/util',
+                ],
+                'defines':
+                [
+                    'GL_GLEXT_PROTOTYPES',
+                    'EGL_EGLEXT_PROTOTYPES',
+                ],
+            },
+        },
+    ],
+}
diff --git a/src/third_party/angle/util/windows/WindowsTimer.cpp b/src/third_party/angle/util/windows/WindowsTimer.cpp
new file mode 100644
index 0000000..c6a9e9d
--- /dev/null
+++ b/src/third_party/angle/util/windows/WindowsTimer.cpp
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowsTimer.cpp: Implementation of a high precision timer class on Windows
+
+#include "windows/WindowsTimer.h"
+
+WindowsTimer::WindowsTimer() : mRunning(false), mStartTime(0), mStopTime(0)
+{
+}
+
+void WindowsTimer::start()
+{
+    LARGE_INTEGER frequency;
+    QueryPerformanceFrequency(&frequency);
+    mFrequency = frequency.QuadPart;
+
+    LARGE_INTEGER curTime;
+    QueryPerformanceCounter(&curTime);
+    mStartTime = curTime.QuadPart;
+
+    mRunning = true;
+}
+
+void WindowsTimer::stop()
+{
+    LARGE_INTEGER curTime;
+    QueryPerformanceCounter(&curTime);
+    mStopTime = curTime.QuadPart;
+
+    mRunning = false;
+}
+
+double WindowsTimer::getElapsedTime() const
+{
+    LONGLONG endTime;
+    if (mRunning)
+    {
+        LARGE_INTEGER curTime;
+        QueryPerformanceCounter(&curTime);
+        endTime = curTime.QuadPart;
+    }
+    else
+    {
+        endTime = mStopTime;
+    }
+
+    return static_cast<double>(endTime - mStartTime) / mFrequency;
+}
+
+Timer *CreateTimer()
+{
+    return new WindowsTimer();
+}
diff --git a/src/third_party/angle/util/windows/WindowsTimer.h b/src/third_party/angle/util/windows/WindowsTimer.h
new file mode 100644
index 0000000..a194300
--- /dev/null
+++ b/src/third_party/angle/util/windows/WindowsTimer.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowsTimer.h: Definition of a high precision timer class on Windows
+
+#ifndef UTIL_WINDOWS_TIMER_H
+#define UTIL_WINDOWS_TIMER_H
+
+#include <windows.h>
+
+#include "Timer.h"
+
+class WindowsTimer : public Timer
+{
+  public:
+    WindowsTimer();
+
+    void start() override;
+    void stop() override;
+    double getElapsedTime() const override;
+
+  private:
+    bool mRunning;
+    LONGLONG mStartTime;
+    LONGLONG mStopTime;
+
+    LONGLONG mFrequency;
+};
+
+#endif  // UTIL_WINDOWS_TIMER_H
diff --git a/src/third_party/angle/util/windows/Windows_system_utils.cpp b/src/third_party/angle/util/windows/Windows_system_utils.cpp
new file mode 100644
index 0000000..36b4f66
--- /dev/null
+++ b/src/third_party/angle/util/windows/Windows_system_utils.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Windows_system_utils.cpp: Implementation of OS-specific functions for Windows
+
+#include "system_utils.h"
+
+#include <stdarg.h>
+#include <windows.h>
+#include <array>
+#include <vector>
+
+namespace angle
+{
+
+void Sleep(unsigned int milliseconds)
+{
+    ::Sleep(static_cast<DWORD>(milliseconds));
+}
+
+void WriteDebugMessage(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    int size = vsnprintf(nullptr, 0, format, args);
+    va_end(args);
+
+    std::vector<char> buffer(size + 2);
+    va_start(args, format);
+    vsnprintf(buffer.data(), size + 1, format, args);
+    va_end(args);
+
+    OutputDebugStringA(buffer.data());
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/util/windows/win32/Win32Pixmap.cpp b/src/third_party/angle/util/windows/win32/Win32Pixmap.cpp
new file mode 100644
index 0000000..8015131
--- /dev/null
+++ b/src/third_party/angle/util/windows/win32/Win32Pixmap.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Win32Pixmap.cpp: Implementation of OSPixmap for Win32 (Windows)
+
+#include "windows/win32/Win32Pixmap.h"
+
+Win32Pixmap::Win32Pixmap() : mBitmap(nullptr)
+{
+}
+
+Win32Pixmap::~Win32Pixmap()
+{
+    if (mBitmap)
+    {
+        DeleteObject(mBitmap);
+    }
+}
+
+bool Win32Pixmap::initialize(EGLNativeDisplayType display, size_t width, size_t height, int depth)
+{
+    BITMAPINFO bitmapInfo;
+    memset(&bitmapInfo, 0, sizeof(bitmapInfo));
+
+    if (depth != 24 && depth != 32)
+    {
+        return false;
+    }
+
+    bitmapInfo.bmiHeader.biSize          = sizeof(bitmapInfo);
+    bitmapInfo.bmiHeader.biWidth         = static_cast<LONG>(width);
+    bitmapInfo.bmiHeader.biHeight        = static_cast<LONG>(height);
+    bitmapInfo.bmiHeader.biPlanes        = 1;
+    bitmapInfo.bmiHeader.biBitCount      = static_cast<WORD>(depth);
+    bitmapInfo.bmiHeader.biCompression   = BI_RGB;
+    bitmapInfo.bmiHeader.biSizeImage     = 0;
+    bitmapInfo.bmiHeader.biXPelsPerMeter = 1;
+    bitmapInfo.bmiHeader.biYPelsPerMeter = 1;
+    bitmapInfo.bmiHeader.biClrUsed       = 0;
+    bitmapInfo.bmiHeader.biClrImportant  = 0;
+
+    void *bitmapPtr = nullptr;
+    mBitmap         = CreateDIBSection(display, &bitmapInfo, DIB_RGB_COLORS, &bitmapPtr, nullptr, 0);
+
+    return mBitmap != nullptr;
+}
+
+EGLNativePixmapType Win32Pixmap::getNativePixmap() const
+{
+    return mBitmap;
+}
+
+OSPixmap *CreateOSPixmap()
+{
+    return new Win32Pixmap();
+}
diff --git a/src/third_party/angle/util/windows/win32/Win32Pixmap.h b/src/third_party/angle/util/windows/win32/Win32Pixmap.h
new file mode 100644
index 0000000..7e14f8a
--- /dev/null
+++ b/src/third_party/angle/util/windows/win32/Win32Pixmap.h
@@ -0,0 +1,30 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Win32Pixmap.h: Definition of the implementation of OSPixmap for Win32 (Windows)
+
+#ifndef UTIL_WIN32_PIXMAP_H_
+#define UTIL_WIN32_PIXMAP_H_
+
+#include <windows.h>
+
+#include "OSPixmap.h"
+
+class Win32Pixmap : public OSPixmap
+{
+  public:
+    Win32Pixmap();
+    ~Win32Pixmap() override;
+
+    bool initialize(EGLNativeDisplayType display, size_t width, size_t height, int depth) override;
+
+    EGLNativePixmapType getNativePixmap() const override;
+
+  private:
+    HBITMAP mBitmap;
+};
+
+#endif  // UTIL_WIN32_PIXMAP_H_
diff --git a/src/third_party/angle/util/windows/win32/Win32Window.cpp b/src/third_party/angle/util/windows/win32/Win32Window.cpp
new file mode 100644
index 0000000..694b431
--- /dev/null
+++ b/src/third_party/angle/util/windows/win32/Win32Window.cpp
@@ -0,0 +1,831 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Win32Window.cpp: Implementation of OSWindow for Win32 (Windows)
+
+#include "windows/win32/Win32Window.h"
+
+#include <sstream>
+
+#include "common/debug.h"
+
+Key VirtualKeyCodeToKey(WPARAM key, LPARAM flags)
+{
+    switch (key)
+    {
+        // Check the scancode to distinguish between left and right shift
+        case VK_SHIFT:
+        {
+            static unsigned int lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
+            unsigned int scancode      = static_cast<unsigned int>((flags & (0xFF << 16)) >> 16);
+            return scancode == lShift ? KEY_LSHIFT : KEY_RSHIFT;
+        }
+
+        // Check the "extended" flag to distinguish between left and right alt
+        case VK_MENU:
+            return (HIWORD(flags) & KF_EXTENDED) ? KEY_RALT : KEY_LALT;
+
+        // Check the "extended" flag to distinguish between left and right control
+        case VK_CONTROL:
+            return (HIWORD(flags) & KF_EXTENDED) ? KEY_RCONTROL : KEY_LCONTROL;
+
+        // Other keys are reported properly
+        case VK_LWIN:
+            return KEY_LSYSTEM;
+        case VK_RWIN:
+            return KEY_RSYSTEM;
+        case VK_APPS:
+            return KEY_MENU;
+        case VK_OEM_1:
+            return KEY_SEMICOLON;
+        case VK_OEM_2:
+            return KEY_SLASH;
+        case VK_OEM_PLUS:
+            return KEY_EQUAL;
+        case VK_OEM_MINUS:
+            return KEY_DASH;
+        case VK_OEM_4:
+            return KEY_LBRACKET;
+        case VK_OEM_6:
+            return KEY_RBRACKET;
+        case VK_OEM_COMMA:
+            return KEY_COMMA;
+        case VK_OEM_PERIOD:
+            return KEY_PERIOD;
+        case VK_OEM_7:
+            return KEY_QUOTE;
+        case VK_OEM_5:
+            return KEY_BACKSLASH;
+        case VK_OEM_3:
+            return KEY_TILDE;
+        case VK_ESCAPE:
+            return KEY_ESCAPE;
+        case VK_SPACE:
+            return KEY_SPACE;
+        case VK_RETURN:
+            return KEY_RETURN;
+        case VK_BACK:
+            return KEY_BACK;
+        case VK_TAB:
+            return KEY_TAB;
+        case VK_PRIOR:
+            return KEY_PAGEUP;
+        case VK_NEXT:
+            return KEY_PAGEDOWN;
+        case VK_END:
+            return KEY_END;
+        case VK_HOME:
+            return KEY_HOME;
+        case VK_INSERT:
+            return KEY_INSERT;
+        case VK_DELETE:
+            return KEY_DELETE;
+        case VK_ADD:
+            return KEY_ADD;
+        case VK_SUBTRACT:
+            return KEY_SUBTRACT;
+        case VK_MULTIPLY:
+            return KEY_MULTIPLY;
+        case VK_DIVIDE:
+            return KEY_DIVIDE;
+        case VK_PAUSE:
+            return KEY_PAUSE;
+        case VK_F1:
+            return KEY_F1;
+        case VK_F2:
+            return KEY_F2;
+        case VK_F3:
+            return KEY_F3;
+        case VK_F4:
+            return KEY_F4;
+        case VK_F5:
+            return KEY_F5;
+        case VK_F6:
+            return KEY_F6;
+        case VK_F7:
+            return KEY_F7;
+        case VK_F8:
+            return KEY_F8;
+        case VK_F9:
+            return KEY_F9;
+        case VK_F10:
+            return KEY_F10;
+        case VK_F11:
+            return KEY_F11;
+        case VK_F12:
+            return KEY_F12;
+        case VK_F13:
+            return KEY_F13;
+        case VK_F14:
+            return KEY_F14;
+        case VK_F15:
+            return KEY_F15;
+        case VK_LEFT:
+            return KEY_LEFT;
+        case VK_RIGHT:
+            return KEY_RIGHT;
+        case VK_UP:
+            return KEY_UP;
+        case VK_DOWN:
+            return KEY_DOWN;
+        case VK_NUMPAD0:
+            return KEY_NUMPAD0;
+        case VK_NUMPAD1:
+            return KEY_NUMPAD1;
+        case VK_NUMPAD2:
+            return KEY_NUMPAD2;
+        case VK_NUMPAD3:
+            return KEY_NUMPAD3;
+        case VK_NUMPAD4:
+            return KEY_NUMPAD4;
+        case VK_NUMPAD5:
+            return KEY_NUMPAD5;
+        case VK_NUMPAD6:
+            return KEY_NUMPAD6;
+        case VK_NUMPAD7:
+            return KEY_NUMPAD7;
+        case VK_NUMPAD8:
+            return KEY_NUMPAD8;
+        case VK_NUMPAD9:
+            return KEY_NUMPAD9;
+        case 'A':
+            return KEY_A;
+        case 'Z':
+            return KEY_Z;
+        case 'E':
+            return KEY_E;
+        case 'R':
+            return KEY_R;
+        case 'T':
+            return KEY_T;
+        case 'Y':
+            return KEY_Y;
+        case 'U':
+            return KEY_U;
+        case 'I':
+            return KEY_I;
+        case 'O':
+            return KEY_O;
+        case 'P':
+            return KEY_P;
+        case 'Q':
+            return KEY_Q;
+        case 'S':
+            return KEY_S;
+        case 'D':
+            return KEY_D;
+        case 'F':
+            return KEY_F;
+        case 'G':
+            return KEY_G;
+        case 'H':
+            return KEY_H;
+        case 'J':
+            return KEY_J;
+        case 'K':
+            return KEY_K;
+        case 'L':
+            return KEY_L;
+        case 'M':
+            return KEY_M;
+        case 'W':
+            return KEY_W;
+        case 'X':
+            return KEY_X;
+        case 'C':
+            return KEY_C;
+        case 'V':
+            return KEY_V;
+        case 'B':
+            return KEY_B;
+        case 'N':
+            return KEY_N;
+        case '0':
+            return KEY_NUM0;
+        case '1':
+            return KEY_NUM1;
+        case '2':
+            return KEY_NUM2;
+        case '3':
+            return KEY_NUM3;
+        case '4':
+            return KEY_NUM4;
+        case '5':
+            return KEY_NUM5;
+        case '6':
+            return KEY_NUM6;
+        case '7':
+            return KEY_NUM7;
+        case '8':
+            return KEY_NUM8;
+        case '9':
+            return KEY_NUM9;
+    }
+
+    return Key(0);
+}
+
+LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    switch (message)
+    {
+        case WM_NCCREATE:
+        {
+            LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
+            SetWindowLongPtr(hWnd, GWLP_USERDATA,
+                             reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));
+            return DefWindowProcA(hWnd, message, wParam, lParam);
+        }
+    }
+
+    Win32Window *window = reinterpret_cast<Win32Window *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
+    if (window)
+    {
+        switch (message)
+        {
+            case WM_DESTROY:
+            case WM_CLOSE:
+            {
+                Event event;
+                event.Type = Event::EVENT_CLOSED;
+                window->pushEvent(event);
+                break;
+            }
+
+            case WM_MOVE:
+            {
+                RECT winRect;
+                GetClientRect(hWnd, &winRect);
+
+                POINT topLeft;
+                topLeft.x = winRect.left;
+                topLeft.y = winRect.top;
+                ClientToScreen(hWnd, &topLeft);
+
+                Event event;
+                event.Type   = Event::EVENT_MOVED;
+                event.Move.X = topLeft.x;
+                event.Move.Y = topLeft.y;
+                window->pushEvent(event);
+
+                break;
+            }
+
+            case WM_SIZE:
+            {
+                RECT winRect;
+                GetClientRect(hWnd, &winRect);
+
+                POINT topLeft;
+                topLeft.x = winRect.left;
+                topLeft.y = winRect.top;
+                ClientToScreen(hWnd, &topLeft);
+
+                POINT botRight;
+                botRight.x = winRect.right;
+                botRight.y = winRect.bottom;
+                ClientToScreen(hWnd, &botRight);
+
+                Event event;
+                event.Type        = Event::EVENT_RESIZED;
+                event.Size.Width  = botRight.x - topLeft.x;
+                event.Size.Height = botRight.y - topLeft.y;
+                window->pushEvent(event);
+
+                break;
+            }
+
+            case WM_SETFOCUS:
+            {
+                Event event;
+                event.Type = Event::EVENT_GAINED_FOCUS;
+                window->pushEvent(event);
+                break;
+            }
+
+            case WM_KILLFOCUS:
+            {
+                Event event;
+                event.Type = Event::EVENT_LOST_FOCUS;
+                window->pushEvent(event);
+                break;
+            }
+
+            case WM_KEYDOWN:
+            case WM_SYSKEYDOWN:
+            case WM_KEYUP:
+            case WM_SYSKEYUP:
+            {
+                bool down = (message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
+
+                Event event;
+                event.Type        = down ? Event::EVENT_KEY_PRESSED : Event::EVENT_KEY_RELEASED;
+                event.Key.Alt     = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
+                event.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
+                event.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
+                event.Key.System =
+                    HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
+                event.Key.Code = VirtualKeyCodeToKey(wParam, lParam);
+                window->pushEvent(event);
+
+                break;
+            }
+
+            case WM_MOUSEWHEEL:
+            {
+                Event event;
+                event.Type             = Event::EVENT_MOUSE_WHEEL_MOVED;
+                event.MouseWheel.Delta = static_cast<short>(HIWORD(wParam)) / 120;
+                window->pushEvent(event);
+                break;
+            }
+
+            case WM_LBUTTONDOWN:
+            case WM_LBUTTONDBLCLK:
+            {
+                Event event;
+                event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
+                event.MouseButton.Button = MOUSEBUTTON_LEFT;
+                event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
+                event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+                window->pushEvent(event);
+                break;
+            }
+
+            case WM_LBUTTONUP:
+            {
+                Event event;
+                event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
+                event.MouseButton.Button = MOUSEBUTTON_LEFT;
+                event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
+                event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+                window->pushEvent(event);
+                break;
+            }
+
+            case WM_RBUTTONDOWN:
+            case WM_RBUTTONDBLCLK:
+            {
+                Event event;
+                event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
+                event.MouseButton.Button = MOUSEBUTTON_RIGHT;
+                event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
+                event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+                window->pushEvent(event);
+                break;
+            }
+
+            // Mouse right button up event
+            case WM_RBUTTONUP:
+            {
+                Event event;
+                event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
+                event.MouseButton.Button = MOUSEBUTTON_RIGHT;
+                event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
+                event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+                window->pushEvent(event);
+                break;
+            }
+
+            // Mouse wheel button down event
+            case WM_MBUTTONDOWN:
+            case WM_MBUTTONDBLCLK:
+            {
+                Event event;
+                event.Type               = Event::EVENT_MOUSE_BUTTON_PRESSED;
+                event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
+                event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
+                event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+                window->pushEvent(event);
+                break;
+            }
+
+            // Mouse wheel button up event
+            case WM_MBUTTONUP:
+            {
+                Event event;
+                event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
+                event.MouseButton.Button = MOUSEBUTTON_MIDDLE;
+                event.MouseButton.X      = static_cast<short>(LOWORD(lParam));
+                event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+                window->pushEvent(event);
+                break;
+            }
+
+            // Mouse X button down event
+            case WM_XBUTTONDOWN:
+            case WM_XBUTTONDBLCLK:
+            {
+                Event event;
+                event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED;
+                event.MouseButton.Button =
+                    (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
+                event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+                event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+                window->pushEvent(event);
+                break;
+            }
+
+            // Mouse X button up event
+            case WM_XBUTTONUP:
+            {
+                Event event;
+                event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
+                event.MouseButton.Button =
+                    (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5;
+                event.MouseButton.X = static_cast<short>(LOWORD(lParam));
+                event.MouseButton.Y = static_cast<short>(HIWORD(lParam));
+                window->pushEvent(event);
+                break;
+            }
+
+            case WM_MOUSEMOVE:
+            {
+                if (!window->mIsMouseInWindow)
+                {
+                    window->mIsMouseInWindow = true;
+                    Event event;
+                    event.Type = Event::EVENT_MOUSE_ENTERED;
+                    window->pushEvent(event);
+                }
+
+                int mouseX = static_cast<short>(LOWORD(lParam));
+                int mouseY = static_cast<short>(HIWORD(lParam));
+
+                Event event;
+                event.Type        = Event::EVENT_MOUSE_MOVED;
+                event.MouseMove.X = mouseX;
+                event.MouseMove.Y = mouseY;
+                window->pushEvent(event);
+                break;
+            }
+
+            case WM_MOUSELEAVE:
+            {
+                Event event;
+                event.Type = Event::EVENT_MOUSE_LEFT;
+                window->pushEvent(event);
+                window->mIsMouseInWindow = false;
+                break;
+            }
+
+            case WM_USER:
+            {
+                Event testEvent;
+                testEvent.Type = Event::EVENT_TEST;
+                window->pushEvent(testEvent);
+                break;
+            }
+        }
+    }
+    return DefWindowProcA(hWnd, message, wParam, lParam);
+}
+
+Win32Window::Win32Window()
+    : mIsVisible(false),
+      mSetVisibleTimer(CreateTimer()),
+      mIsMouseInWindow(false),
+      mNativeWindow(0),
+      mParentWindow(0),
+      mNativeDisplay(0)
+{
+}
+
+Win32Window::~Win32Window()
+{
+    destroy();
+    delete mSetVisibleTimer;
+}
+
+bool Win32Window::initialize(const std::string &name, size_t width, size_t height)
+{
+    destroy();
+
+    // Use a new window class name for ever window to ensure that a new window can be created
+    // even if the last one was not properly destroyed
+    static size_t windowIdx = 0;
+    std::ostringstream nameStream;
+    nameStream << name << "_" << windowIdx++;
+
+    mParentClassName = nameStream.str();
+    mChildClassName  = mParentClassName + "_Child";
+
+    // Work around compile error from not defining "UNICODE" while Chromium does
+    const LPSTR idcArrow = MAKEINTRESOURCEA(32512);
+
+    WNDCLASSEXA parentWindowClass   = {0};
+    parentWindowClass.cbSize        = sizeof(WNDCLASSEXA);
+    parentWindowClass.style         = 0;
+    parentWindowClass.lpfnWndProc   = WndProc;
+    parentWindowClass.cbClsExtra    = 0;
+    parentWindowClass.cbWndExtra    = 0;
+    parentWindowClass.hInstance     = GetModuleHandle(nullptr);
+    parentWindowClass.hIcon         = nullptr;
+    parentWindowClass.hCursor       = LoadCursorA(nullptr, idcArrow);
+    parentWindowClass.hbrBackground = 0;
+    parentWindowClass.lpszMenuName  = nullptr;
+    parentWindowClass.lpszClassName = mParentClassName.c_str();
+    if (!RegisterClassExA(&parentWindowClass))
+    {
+        return false;
+    }
+
+    WNDCLASSEXA childWindowClass   = {0};
+    childWindowClass.cbSize        = sizeof(WNDCLASSEXA);
+    childWindowClass.style         = CS_OWNDC;
+    childWindowClass.lpfnWndProc   = WndProc;
+    childWindowClass.cbClsExtra    = 0;
+    childWindowClass.cbWndExtra    = 0;
+    childWindowClass.hInstance     = GetModuleHandle(nullptr);
+    childWindowClass.hIcon         = nullptr;
+    childWindowClass.hCursor       = LoadCursorA(nullptr, idcArrow);
+    childWindowClass.hbrBackground = 0;
+    childWindowClass.lpszMenuName  = nullptr;
+    childWindowClass.lpszClassName = mChildClassName.c_str();
+    if (!RegisterClassExA(&childWindowClass))
+    {
+        return false;
+    }
+
+    DWORD parentStyle         = WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
+    DWORD parentExtendedStyle = WS_EX_APPWINDOW;
+
+    RECT sizeRect = {0, 0, static_cast<LONG>(width), static_cast<LONG>(height)};
+    AdjustWindowRectEx(&sizeRect, parentStyle, FALSE, parentExtendedStyle);
+
+    mParentWindow = CreateWindowExA(parentExtendedStyle, mParentClassName.c_str(), name.c_str(),
+                                    parentStyle, CW_USEDEFAULT, CW_USEDEFAULT,
+                                    sizeRect.right - sizeRect.left, sizeRect.bottom - sizeRect.top,
+                                    nullptr, nullptr, GetModuleHandle(nullptr), this);
+
+    mNativeWindow = CreateWindowExA(0, mChildClassName.c_str(), name.c_str(), WS_CHILD, 0, 0,
+                                    static_cast<int>(width), static_cast<int>(height),
+                                    mParentWindow, nullptr, GetModuleHandle(nullptr), this);
+
+    mNativeDisplay = GetDC(mNativeWindow);
+    if (!mNativeDisplay)
+    {
+        destroy();
+        return false;
+    }
+
+    return true;
+}
+
+void Win32Window::destroy()
+{
+    if (mNativeDisplay)
+    {
+        ReleaseDC(mNativeWindow, mNativeDisplay);
+        mNativeDisplay = 0;
+    }
+
+    if (mNativeWindow)
+    {
+        DestroyWindow(mNativeWindow);
+        mNativeWindow = 0;
+    }
+
+    if (mParentWindow)
+    {
+        DestroyWindow(mParentWindow);
+        mParentWindow = 0;
+    }
+
+    UnregisterClassA(mParentClassName.c_str(), nullptr);
+    UnregisterClassA(mChildClassName.c_str(), nullptr);
+}
+
+bool Win32Window::takeScreenshot(uint8_t *pixelData)
+{
+    if (mIsVisible)
+    {
+        return false;
+    }
+
+    bool error = false;
+
+    // Hack for DWM: There is no way to wait for DWM animations to finish, so we just have to wait
+    // for a while before issuing screenshot if window was just made visible.
+    {
+        static const double WAIT_WINDOW_VISIBLE_MS = 0.5;  // Half a second for the animation
+        double timeSinceVisible                    = mSetVisibleTimer->getElapsedTime();
+
+        if (timeSinceVisible < WAIT_WINDOW_VISIBLE_MS)
+        {
+            Sleep(static_cast<DWORD>((WAIT_WINDOW_VISIBLE_MS - timeSinceVisible) * 1000));
+        }
+    }
+
+    HDC screenDC      = nullptr;
+    HDC windowDC      = nullptr;
+    HDC tmpDC         = nullptr;
+    HBITMAP tmpBitmap = nullptr;
+
+    if (!error)
+    {
+        screenDC = GetDC(nullptr);
+        error    = screenDC == nullptr;
+    }
+
+    if (!error)
+    {
+        windowDC = GetDC(mNativeWindow);
+        error    = windowDC == nullptr;
+    }
+
+    if (!error)
+    {
+        tmpDC = CreateCompatibleDC(screenDC);
+        error = tmpDC == nullptr;
+    }
+
+    if (!error)
+    {
+        tmpBitmap = CreateCompatibleBitmap(screenDC, mWidth, mHeight);
+        error     = tmpBitmap == nullptr;
+    }
+
+    RECT rect = {0, 0, 0, 0};
+    if (!error)
+    {
+        MapWindowPoints(mNativeWindow, nullptr, reinterpret_cast<LPPOINT>(&rect), 0);
+
+        error = SelectObject(tmpDC, tmpBitmap) == nullptr;
+    }
+
+    if (!error)
+    {
+        error =
+            BitBlt(tmpDC, 0, 0, mWidth, mHeight, screenDC, rect.left, rect.top, SRCCOPY) == TRUE;
+    }
+
+    if (!error)
+    {
+        BITMAPINFOHEADER bitmapInfo;
+        bitmapInfo.biSize          = sizeof(BITMAPINFOHEADER);
+        bitmapInfo.biWidth         = mWidth;
+        bitmapInfo.biHeight        = -mHeight;
+        bitmapInfo.biPlanes        = 1;
+        bitmapInfo.biBitCount      = 32;
+        bitmapInfo.biCompression   = BI_RGB;
+        bitmapInfo.biSizeImage     = 0;
+        bitmapInfo.biXPelsPerMeter = 0;
+        bitmapInfo.biYPelsPerMeter = 0;
+        bitmapInfo.biClrUsed       = 0;
+        bitmapInfo.biClrImportant  = 0;
+        int getBitsResult = GetDIBits(screenDC, tmpBitmap, 0, mHeight, pixelData,
+                                      reinterpret_cast<BITMAPINFO *>(&bitmapInfo), DIB_RGB_COLORS);
+        error = getBitsResult != 0;
+    }
+
+    if (tmpBitmap != nullptr)
+    {
+        DeleteObject(tmpBitmap);
+    }
+    if (tmpDC != nullptr)
+    {
+        DeleteDC(tmpDC);
+    }
+    if (screenDC != nullptr)
+    {
+        ReleaseDC(nullptr, screenDC);
+    }
+    if (windowDC != nullptr)
+    {
+        ReleaseDC(mNativeWindow, windowDC);
+    }
+
+    return !error;
+}
+
+EGLNativeWindowType Win32Window::getNativeWindow() const
+{
+    return mNativeWindow;
+}
+
+EGLNativeDisplayType Win32Window::getNativeDisplay() const
+{
+    return mNativeDisplay;
+}
+
+void Win32Window::messageLoop()
+{
+    MSG msg;
+    while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
+    {
+        TranslateMessage(&msg);
+        DispatchMessage(&msg);
+    }
+}
+
+void Win32Window::setMousePosition(int x, int y)
+{
+    RECT winRect;
+    GetClientRect(mNativeWindow, &winRect);
+
+    POINT topLeft;
+    topLeft.x = winRect.left;
+    topLeft.y = winRect.top;
+    ClientToScreen(mNativeWindow, &topLeft);
+
+    SetCursorPos(topLeft.x + x, topLeft.y + y);
+}
+
+OSWindow *CreateOSWindow()
+{
+    return new Win32Window();
+}
+
+bool Win32Window::setPosition(int x, int y)
+{
+    if (mX == x && mY == y)
+    {
+        return true;
+    }
+
+    RECT windowRect;
+    if (!GetWindowRect(mParentWindow, &windowRect))
+    {
+        return false;
+    }
+
+    if (!MoveWindow(mParentWindow, x, y, windowRect.right - windowRect.left,
+                    windowRect.bottom - windowRect.top, TRUE))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool Win32Window::resize(int width, int height)
+{
+    if (width == mWidth && height == mHeight)
+    {
+        return true;
+    }
+
+    RECT windowRect;
+    if (!GetWindowRect(mParentWindow, &windowRect))
+    {
+        return false;
+    }
+
+    RECT clientRect;
+    if (!GetClientRect(mParentWindow, &clientRect))
+    {
+        return false;
+    }
+
+    LONG diffX = (windowRect.right - windowRect.left) - clientRect.right;
+    LONG diffY = (windowRect.bottom - windowRect.top) - clientRect.bottom;
+    if (!MoveWindow(mParentWindow, windowRect.left, windowRect.top, width + diffX, height + diffY,
+                    TRUE))
+    {
+        return false;
+    }
+
+    if (!MoveWindow(mNativeWindow, 0, 0, width, height, FALSE))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+void Win32Window::setVisible(bool isVisible)
+{
+    int flag = (isVisible ? SW_SHOW : SW_HIDE);
+
+    ShowWindow(mParentWindow, flag);
+    ShowWindow(mNativeWindow, flag);
+
+    if (isVisible)
+    {
+        mSetVisibleTimer->stop();
+        mSetVisibleTimer->start();
+    }
+}
+
+void Win32Window::pushEvent(Event event)
+{
+    OSWindow::pushEvent(event);
+
+    switch (event.Type)
+    {
+        case Event::EVENT_RESIZED:
+            MoveWindow(mNativeWindow, 0, 0, mWidth, mHeight, FALSE);
+            break;
+        default:
+            break;
+    }
+}
+
+void Win32Window::signalTestEvent()
+{
+    PostMessage(mNativeWindow, WM_USER, 0, 0);
+}
diff --git a/src/third_party/angle/util/windows/win32/Win32Window.h b/src/third_party/angle/util/windows/win32/Win32Window.h
new file mode 100644
index 0000000..c0904e9
--- /dev/null
+++ b/src/third_party/angle/util/windows/win32/Win32Window.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Win32Window.h: Definition of the implementation of OSWindow for Win32 (Windows)
+
+#ifndef UTIL_WIN32_WINDOW_H
+#define UTIL_WIN32_WINDOW_H
+
+#include <windows.h>
+#include <string>
+
+#include "OSWindow.h"
+#include "Timer.h"
+
+class Win32Window : public OSWindow
+{
+  public:
+    Win32Window();
+    ~Win32Window() override;
+
+    bool initialize(const std::string &name, size_t width, size_t height) override;
+    void destroy() override;
+
+    bool takeScreenshot(uint8_t *pixelData) override;
+
+    EGLNativeWindowType getNativeWindow() const override;
+    EGLNativeDisplayType getNativeDisplay() const override;
+
+    void messageLoop() override;
+
+    void pushEvent(Event event) override;
+
+    void setMousePosition(int x, int y) override;
+    bool setPosition(int x, int y) override;
+    bool resize(int width, int height) override;
+    void setVisible(bool isVisible) override;
+
+    void signalTestEvent() override;
+
+  private:
+    static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+    std::string mParentClassName;
+    std::string mChildClassName;
+
+    bool mIsVisible;
+    Timer *mSetVisibleTimer;
+
+    bool mIsMouseInWindow;
+
+    EGLNativeWindowType mNativeWindow;
+    EGLNativeWindowType mParentWindow;
+    EGLNativeDisplayType mNativeDisplay;
+};
+
+#endif  // UTIL_WIN32_WINDOW_H
diff --git a/src/third_party/angle/util/windows/win32/Win32_system_utils.cpp b/src/third_party/angle/util/windows/win32/Win32_system_utils.cpp
new file mode 100644
index 0000000..a9fd97f
--- /dev/null
+++ b/src/third_party/angle/util/windows/win32/Win32_system_utils.cpp
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Win32_system_utils.cpp: Implementation of OS-specific functions for Win32 (Windows)
+
+#include "system_utils.h"
+
+#include <windows.h>
+#include <array>
+
+namespace angle
+{
+
+void SetLowPriorityProcess()
+{
+    SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
+}
+
+class Win32Library : public Library
+{
+  public:
+    Win32Library(const std::string &libraryName);
+    ~Win32Library() override;
+
+    void *getSymbol(const std::string &symbolName) override;
+
+  private:
+    HMODULE mModule;
+};
+
+Win32Library::Win32Library(const std::string &libraryName) : mModule(nullptr)
+{
+    const auto &fullName = libraryName + "." + GetSharedLibraryExtension();
+    mModule              = LoadLibraryA(fullName.c_str());
+}
+
+Win32Library::~Win32Library()
+{
+    if (mModule)
+    {
+        FreeLibrary(mModule);
+    }
+}
+
+void *Win32Library::getSymbol(const std::string &symbolName)
+{
+    if (!mModule)
+    {
+        return nullptr;
+    }
+
+    return GetProcAddress(mModule, symbolName.c_str());
+}
+
+Library *loadLibrary(const std::string &libraryName)
+{
+    return new Win32Library(libraryName);
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/util/windows/winrt/WinRTPixmap.cpp b/src/third_party/angle/util/windows/winrt/WinRTPixmap.cpp
new file mode 100644
index 0000000..fdc853a
--- /dev/null
+++ b/src/third_party/angle/util/windows/winrt/WinRTPixmap.cpp
@@ -0,0 +1,17 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WinRTPixmap.cpp: Stub implementation of OSPixmap functions for WinRT (Windows)
+
+#include "OSPixmap.h"
+
+#include "common/debug.h"
+
+OSPixmap *CreateOSPixmap()
+{
+    UNIMPLEMENTED();
+    return nullptr;
+}
\ No newline at end of file
diff --git a/src/third_party/angle/util/windows/winrt/WinRTWindow.cpp b/src/third_party/angle/util/windows/winrt/WinRTWindow.cpp
new file mode 100644
index 0000000..33f76a2
--- /dev/null
+++ b/src/third_party/angle/util/windows/winrt/WinRTWindow.cpp
@@ -0,0 +1,284 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WinRTWindow.cpp: Implementation of OSWindow for WinRT (Windows)
+
+#include "windows/winrt/WinRTWindow.h"
+
+#include <wrl.h>
+#include <windows.applicationmodel.core.h>
+#include <windows.ui.xaml.h>
+
+#include "angle_windowsstore.h"
+#include "common/debug.h"
+
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI::Core;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+WinRTWindow::WinRTWindow() : mNativeWindow(nullptr)
+{
+}
+
+WinRTWindow::~WinRTWindow()
+{
+    destroy();
+}
+
+bool WinRTWindow::initialize(const std::string &name, size_t width, size_t height)
+{
+    ComPtr<ICoreWindowStatic> coreWindowStatic;
+    ComPtr<IActivationFactory> propertySetFactory;
+    ComPtr<IPropertyValueStatics> propertyValueStatics;
+
+    ComPtr<ICoreApplication> coreApplication;
+    ComPtr<IPropertySet> coreApplicationProperties;
+    ComPtr<IMap<HSTRING, IInspectable *>> coreApplicationPropertiesAsMap;
+
+    ComPtr<IMap<HSTRING, IInspectable *>> nativeWindowAsMap;
+    ComPtr<IInspectable> sizeValue;
+
+    HRESULT result           = S_OK;
+    boolean propertyReplaced = false;
+
+    destroy();
+
+    // Get all the relevant activation factories
+    result = GetActivationFactory(
+        HStringReference(RuntimeClass_Windows_UI_Core_CoreWindow).Get(), &coreWindowStatic);
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    result = GetActivationFactory(
+        HStringReference(RuntimeClass_Windows_Foundation_Collections_PropertySet).Get(),
+        &propertySetFactory);
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    result =
+        GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(),
+                             &propertyValueStatics);
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    result = GetActivationFactory(
+        HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+        &coreApplication);
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    // Create a PropertySet to be used as the native window
+    result = propertySetFactory->ActivateInstance(&mNativeWindow);
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    // Get the PropertySet as a map, so we can Insert things into it later
+    ComPtr<IInspectable> tempNativeWindow = mNativeWindow;
+    result = tempNativeWindow.As(&nativeWindowAsMap);
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    // Get the CoreApplication properties
+    result = coreApplication->get_Properties(coreApplicationProperties.GetAddressOf());
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    // Get the CoreApplication properties as a map
+    result = coreApplicationProperties.As(&coreApplicationPropertiesAsMap);
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    // See if the application properties contain an EGLNativeWindowTypeProperty
+    boolean hasEGLNativeWindowTypeProperty;
+    result = coreApplicationPropertiesAsMap->HasKey(
+        HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEGLNativeWindowTypeProperty);
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    // If an EGLNativeWindowTypeProperty is inputted then use it
+    if (hasEGLNativeWindowTypeProperty)
+    {
+        ComPtr<IInspectable> coreApplicationPropertyNativeWindow;
+
+        result = coreApplicationPropertiesAsMap->Lookup(
+            HStringReference(EGLNativeWindowTypeProperty).Get(),
+            &coreApplicationPropertyNativeWindow);
+        if (FAILED(result))
+        {
+            return false;
+        }
+
+        // See if the inputted window was a CoreWindow
+        ComPtr<ICoreWindow> applicationPropertyCoreWindow;
+        if (SUCCEEDED(coreApplicationPropertyNativeWindow.As(&applicationPropertyCoreWindow)))
+        {
+            // Store away the CoreWindow's dispatcher, to be used later to process messages
+            result = applicationPropertyCoreWindow->get_Dispatcher(&mCoreDispatcher);
+            if (FAILED(result))
+            {
+                return false;
+            }
+        }
+        else
+        {
+            ComPtr<IPropertySet> propSet;
+
+            // Disallow Property Sets here, since we want to wrap this window in
+            // a property set with the size property below
+            if (SUCCEEDED(coreApplicationPropertyNativeWindow.As(&propSet)))
+            {
+                return false;
+            }
+        }
+
+        // Add the window to the map
+        result =
+            nativeWindowAsMap->Insert(HStringReference(EGLNativeWindowTypeProperty).Get(),
+                                      coreApplicationPropertyNativeWindow.Get(), &propertyReplaced);
+        if (FAILED(result))
+        {
+            return false;
+        }
+    }
+    else
+    {
+        ComPtr<ICoreWindow> currentThreadCoreWindow;
+
+        // Get the CoreWindow for the current thread
+        result = coreWindowStatic->GetForCurrentThread(&currentThreadCoreWindow);
+        if (FAILED(result))
+        {
+            return false;
+        }
+
+        // By default, just add this thread's CoreWindow to the PropertySet
+        result = nativeWindowAsMap->Insert(HStringReference(EGLNativeWindowTypeProperty).Get(),
+                                           currentThreadCoreWindow.Get(), &propertyReplaced);
+        if (FAILED(result))
+        {
+            return false;
+        }
+
+        // Store away the CoreWindow's dispatcher, to be used later to process messages
+        result = currentThreadCoreWindow->get_Dispatcher(&mCoreDispatcher);
+        if (FAILED(result))
+        {
+            return false;
+        }
+    }
+
+    // Create a Size to represent the Native Window's size
+    Size renderSize;
+    renderSize.Width  = static_cast<float>(width);
+    renderSize.Height = static_cast<float>(height);
+    result = propertyValueStatics->CreateSize(renderSize, sizeValue.GetAddressOf());
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    // Add the Size to the PropertySet
+    result = nativeWindowAsMap->Insert(HStringReference(EGLRenderSurfaceSizeProperty).Get(),
+                                       sizeValue.Get(), &propertyReplaced);
+    if (FAILED(result))
+    {
+        return false;
+    }
+
+    return true;
+};
+
+void WinRTWindow::destroy()
+{
+    SafeRelease(mNativeWindow);
+
+    mCoreDispatcher.Reset();
+}
+
+EGLNativeWindowType WinRTWindow::getNativeWindow() const
+{
+    return mNativeWindow;
+}
+
+EGLNativeDisplayType WinRTWindow::getNativeDisplay() const
+{
+    UNIMPLEMENTED();
+    return static_cast<EGLNativeDisplayType>(0);
+}
+
+void WinRTWindow::messageLoop()
+{
+    // If we have a CoreDispatcher then use it to process events
+    if (mCoreDispatcher)
+    {
+        HRESULT result =
+            mCoreDispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
+        UNUSED_ASSERTION_VARIABLE(result);
+        ASSERT(SUCCEEDED(result));
+    }
+}
+
+void WinRTWindow::setMousePosition(int /* x */, int /* y */)
+{
+    UNIMPLEMENTED();
+}
+
+bool WinRTWindow::setPosition(int /* x */, int /* y */)
+{
+    UNIMPLEMENTED();
+    return false;
+}
+
+bool WinRTWindow::resize(int /* width */, int /* height */)
+{
+    UNIMPLEMENTED();
+    return false;
+}
+
+void WinRTWindow::setVisible(bool isVisible)
+{
+    if (isVisible)
+    {
+        // Already visible by default
+        return;
+    }
+    else
+    {
+        // Not implemented in WinRT
+        UNIMPLEMENTED();
+    }
+}
+
+void WinRTWindow::signalTestEvent()
+{
+    UNIMPLEMENTED();
+}
+
+OSWindow *CreateOSWindow()
+{
+    return new WinRTWindow();
+}
\ No newline at end of file
diff --git a/src/third_party/angle/util/windows/winrt/WinRTWindow.h b/src/third_party/angle/util/windows/winrt/WinRTWindow.h
new file mode 100644
index 0000000..9eabc04
--- /dev/null
+++ b/src/third_party/angle/util/windows/winrt/WinRTWindow.h
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WinRTWindow.h: Definition of the implementation of OSWindow for WinRT (Windows)
+
+#ifndef UTIL_WINRT_WINDOW_H
+#define UTIL_WINRT_WINDOW_H
+
+#include <string>
+#include <windows.h>
+#include <windows.applicationmodel.core.h>
+#include <wrl.h>
+
+#include "OSWindow.h"
+
+class WinRTWindow : public OSWindow
+{
+  public:
+    WinRTWindow();
+    ~WinRTWindow() override;
+
+    bool initialize(const std::string &name, size_t width, size_t height) override;
+    void destroy() override;
+
+    EGLNativeWindowType getNativeWindow() const override;
+    EGLNativeDisplayType getNativeDisplay() const override;
+
+    void messageLoop() override;
+
+    void setMousePosition(int x, int y) override;
+    bool setPosition(int x, int y) override;
+    bool resize(int width, int height) override;
+    void setVisible(bool isVisible) override;
+
+    void signalTestEvent() override;
+
+  private:
+    EGLNativeWindowType mNativeWindow;
+    Microsoft::WRL::ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> mCoreDispatcher;
+};
+
+#endif  // UTIL_WINRT_WINDOW_H
diff --git a/src/third_party/angle/util/windows/winrt/WinRT_system_utils.cpp b/src/third_party/angle/util/windows/winrt/WinRT_system_utils.cpp
new file mode 100644
index 0000000..8513bac
--- /dev/null
+++ b/src/third_party/angle/util/windows/winrt/WinRT_system_utils.cpp
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WinRT_system_utils.cpp: Implementation of OS-specific functions for WinRT (Windows)
+
+#include "system_utils.h"
+
+#include <windows.h>
+#include <array>
+
+namespace angle
+{
+
+void SetLowPriorityProcess()
+{
+    // No equivalent to this in WinRT
+}
+
+Library *loadLibrary(const std::string &libraryName)
+{
+    // WinRT cannot load code dynamically.
+    return nullptr;
+}
+
+}  // namespace angle
diff --git a/src/third_party/angle/util/x11/X11Pixmap.cpp b/src/third_party/angle/util/x11/X11Pixmap.cpp
new file mode 100644
index 0000000..943527a
--- /dev/null
+++ b/src/third_party/angle/util/x11/X11Pixmap.cpp
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// X11Pixmap.cpp: Implementation of OSPixmap for X11
+
+#include "x11/X11Pixmap.h"
+
+X11Pixmap::X11Pixmap()
+  : mPixmap(0),
+    mDisplay(nullptr)
+{
+}
+
+X11Pixmap::~X11Pixmap()
+{
+    if (mPixmap)
+    {
+        XFreePixmap(mDisplay, mPixmap);
+    }
+}
+
+bool X11Pixmap::initialize(EGLNativeDisplayType display, size_t width, size_t height, int depth)
+{
+    mDisplay = display;
+
+    int screen = DefaultScreen(mDisplay);
+    Window root = RootWindow(mDisplay, screen);
+
+    mPixmap = XCreatePixmap(mDisplay, root, width, height, depth);
+
+    return mPixmap != 0;
+}
+
+EGLNativePixmapType X11Pixmap::getNativePixmap() const
+{
+    return mPixmap;
+}
+
+OSPixmap *CreateOSPixmap()
+{
+    return new X11Pixmap();
+}
diff --git a/src/third_party/angle/util/x11/X11Pixmap.h b/src/third_party/angle/util/x11/X11Pixmap.h
new file mode 100644
index 0000000..fd12db6
--- /dev/null
+++ b/src/third_party/angle/util/x11/X11Pixmap.h
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// X11Pixmap.h: Definition of the implementation of OSPixmap for X11
+
+#ifndef UTIL_X11_PIXMAP_H_
+#define UTIL_X11_PIXMAP_H_
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "OSPixmap.h"
+
+class X11Pixmap : public OSPixmap
+{
+  public:
+    X11Pixmap();
+    ~X11Pixmap() override;
+
+    bool initialize(EGLNativeDisplayType display, size_t width, size_t height, int depth) override;
+
+    EGLNativePixmapType getNativePixmap() const override;
+
+  private:
+    Pixmap mPixmap;
+    Display *mDisplay;
+};
+
+#endif // UTIL_X11_PIXMAP_H_
diff --git a/src/third_party/angle/util/x11/X11Window.cpp b/src/third_party/angle/util/x11/X11Window.cpp
new file mode 100644
index 0000000..91461d5
--- /dev/null
+++ b/src/third_party/angle/util/x11/X11Window.cpp
@@ -0,0 +1,608 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// X11Window.cpp: Implementation of OSWindow for X11
+
+#include "x11/X11Window.h"
+
+#include "common/debug.h"
+#include "system_utils.h"
+#include "Timer.h"
+
+namespace {
+
+Bool WaitForMapNotify(Display *dpy, XEvent *event, XPointer window)
+{
+    return event->type == MapNotify && event->xmap.window == reinterpret_cast<Window>(window);
+}
+
+static Key X11CodeToKey(Display *display, unsigned int scancode)
+{
+    int temp;
+    KeySym *keySymbols;
+    keySymbols = XGetKeyboardMapping(display, scancode, 1, &temp);
+
+    unsigned int keySymbol = keySymbols[0];
+    XFree(keySymbols);
+
+    switch (keySymbol)
+    {
+      case XK_Shift_L:     return KEY_LSHIFT;
+      case XK_Shift_R:     return KEY_RSHIFT;
+      case XK_Alt_L:       return KEY_LALT;
+      case XK_Alt_R:       return KEY_RALT;
+      case XK_Control_L:   return KEY_LCONTROL;
+      case XK_Control_R:   return KEY_RCONTROL;
+      case XK_Super_L:     return KEY_LSYSTEM;
+      case XK_Super_R:     return KEY_RSYSTEM;
+      case XK_Menu:        return KEY_MENU;
+
+      case XK_semicolon:   return KEY_SEMICOLON;
+      case XK_slash:       return KEY_SLASH;
+      case XK_equal:       return KEY_EQUAL;
+      case XK_minus:       return KEY_DASH;
+      case XK_bracketleft: return KEY_LBRACKET;
+      case XK_bracketright:return KEY_RBRACKET;
+      case XK_comma:       return KEY_COMMA;
+      case XK_period:      return KEY_PERIOD;
+      case XK_backslash:   return KEY_BACKSLASH;
+      case XK_asciitilde:  return KEY_TILDE;
+      case XK_Escape:      return KEY_ESCAPE;
+      case XK_space:       return KEY_SPACE;
+      case XK_Return:      return KEY_RETURN;
+      case XK_BackSpace:   return KEY_BACK;
+      case XK_Tab:         return KEY_TAB;
+      case XK_Page_Up:     return KEY_PAGEUP;
+      case XK_Page_Down:   return KEY_PAGEDOWN;
+      case XK_End:         return KEY_END;
+      case XK_Home:        return KEY_HOME;
+      case XK_Insert:      return KEY_INSERT;
+      case XK_Delete:      return KEY_DELETE;
+      case XK_KP_Add:      return KEY_ADD;
+      case XK_KP_Subtract: return KEY_SUBTRACT;
+      case XK_KP_Multiply: return KEY_MULTIPLY;
+      case XK_KP_Divide:   return KEY_DIVIDE;
+      case XK_Pause:       return KEY_PAUSE;
+
+      case XK_F1:          return KEY_F1;
+      case XK_F2:          return KEY_F2;
+      case XK_F3:          return KEY_F3;
+      case XK_F4:          return KEY_F4;
+      case XK_F5:          return KEY_F5;
+      case XK_F6:          return KEY_F6;
+      case XK_F7:          return KEY_F7;
+      case XK_F8:          return KEY_F8;
+      case XK_F9:          return KEY_F9;
+      case XK_F10:         return KEY_F10;
+      case XK_F11:         return KEY_F11;
+      case XK_F12:         return KEY_F12;
+      case XK_F13:         return KEY_F13;
+      case XK_F14:         return KEY_F14;
+      case XK_F15:         return KEY_F15;
+
+      case XK_Left:        return KEY_LEFT;
+      case XK_Right:       return KEY_RIGHT;
+      case XK_Down:        return KEY_DOWN;
+      case XK_Up:          return KEY_UP;
+
+      case XK_KP_Insert:   return KEY_NUMPAD0;
+      case XK_KP_End:      return KEY_NUMPAD1;
+      case XK_KP_Down:     return KEY_NUMPAD2;
+      case XK_KP_Page_Down:return KEY_NUMPAD3;
+      case XK_KP_Left:     return KEY_NUMPAD4;
+      case XK_KP_5:        return KEY_NUMPAD5;
+      case XK_KP_Right:    return KEY_NUMPAD6;
+      case XK_KP_Home:     return KEY_NUMPAD7;
+      case XK_KP_Up:       return KEY_NUMPAD8;
+      case XK_KP_Page_Up:  return KEY_NUMPAD9;
+
+      case XK_a:           return KEY_A;
+      case XK_b:           return KEY_B;
+      case XK_c:           return KEY_C;
+      case XK_d:           return KEY_D;
+      case XK_e:           return KEY_E;
+      case XK_f:           return KEY_F;
+      case XK_g:           return KEY_G;
+      case XK_h:           return KEY_H;
+      case XK_i:           return KEY_I;
+      case XK_j:           return KEY_J;
+      case XK_k:           return KEY_K;
+      case XK_l:           return KEY_L;
+      case XK_m:           return KEY_M;
+      case XK_n:           return KEY_N;
+      case XK_o:           return KEY_O;
+      case XK_p:           return KEY_P;
+      case XK_q:           return KEY_Q;
+      case XK_r:           return KEY_R;
+      case XK_s:           return KEY_S;
+      case XK_t:           return KEY_T;
+      case XK_u:           return KEY_U;
+      case XK_v:           return KEY_V;
+      case XK_w:           return KEY_W;
+      case XK_x:           return KEY_X;
+      case XK_y:           return KEY_Y;
+      case XK_z:           return KEY_Z;
+
+      case XK_1:           return KEY_NUM1;
+      case XK_2:           return KEY_NUM2;
+      case XK_3:           return KEY_NUM3;
+      case XK_4:           return KEY_NUM4;
+      case XK_5:           return KEY_NUM5;
+      case XK_6:           return KEY_NUM6;
+      case XK_7:           return KEY_NUM7;
+      case XK_8:           return KEY_NUM8;
+      case XK_9:           return KEY_NUM9;
+      case XK_0:           return KEY_NUM0;
+    }
+
+    return Key(0);
+}
+
+static void AddX11KeyStateToEvent(Event *event, unsigned int state)
+{
+    event->Key.Shift = state & ShiftMask;
+    event->Key.Control = state & ControlMask;
+    event->Key.Alt = state & Mod1Mask;
+    event->Key.System = state & Mod4Mask;
+}
+
+}
+
+X11Window::X11Window()
+    : WM_DELETE_WINDOW(None),
+      WM_PROTOCOLS(None),
+      TEST_EVENT(None),
+      mDisplay(nullptr),
+      mWindow(0),
+      mRequestedVisualId(-1),
+      mVisible(false)
+{
+}
+
+X11Window::X11Window(int visualId)
+    : WM_DELETE_WINDOW(None),
+      WM_PROTOCOLS(None),
+      TEST_EVENT(None),
+      mDisplay(nullptr),
+      mWindow(0),
+      mRequestedVisualId(visualId),
+      mVisible(false)
+{
+}
+
+X11Window::~X11Window()
+{
+    destroy();
+}
+
+bool X11Window::initialize(const std::string &name, size_t width, size_t height)
+{
+    destroy();
+
+    mDisplay = XOpenDisplay(nullptr);
+    if (!mDisplay)
+    {
+        return false;
+    }
+
+    {
+        int screen = DefaultScreen(mDisplay);
+        Window root = RootWindow(mDisplay, screen);
+
+        Visual *visual;
+        if (mRequestedVisualId == -1)
+        {
+            visual = DefaultVisual(mDisplay, screen);
+        }
+        else
+        {
+            XVisualInfo visualTemplate;
+            visualTemplate.visualid = mRequestedVisualId;
+
+            int numVisuals       = 0;
+            XVisualInfo *visuals = XGetVisualInfo(mDisplay, VisualIDMask, &visualTemplate, &numVisuals);
+            if (numVisuals <= 0)
+            {
+                return false;
+            }
+            ASSERT(numVisuals == 1);
+
+            visual = visuals[0].visual;
+            XFree(visuals);
+        }
+
+        int depth = DefaultDepth(mDisplay, screen);
+        Colormap colormap = XCreateColormap(mDisplay, root, visual, AllocNone);
+
+        XSetWindowAttributes attributes;
+        unsigned long attributeMask = CWBorderPixel | CWColormap | CWEventMask;
+
+        attributes.event_mask = StructureNotifyMask | PointerMotionMask | ButtonPressMask |
+                                ButtonReleaseMask | FocusChangeMask | EnterWindowMask |
+                                LeaveWindowMask | KeyPressMask | KeyReleaseMask;
+        attributes.border_pixel = 0;
+        attributes.colormap = colormap;
+
+        mWindow = XCreateWindow(mDisplay, root, 0, 0, width, height, 0, depth, InputOutput,
+                                visual, attributeMask, &attributes);
+        XFreeColormap(mDisplay, colormap);
+    }
+
+    if (!mWindow)
+    {
+        destroy();
+        return false;
+    }
+
+    // Tell the window manager to notify us when the user wants to close the
+    // window so we can do it ourselves.
+    WM_DELETE_WINDOW = XInternAtom(mDisplay, "WM_DELETE_WINDOW", False);
+    WM_PROTOCOLS = XInternAtom(mDisplay, "WM_PROTOCOLS", False);
+    if (WM_DELETE_WINDOW == None || WM_PROTOCOLS == None)
+    {
+        destroy();
+        return false;
+    }
+
+    if(XSetWMProtocols(mDisplay, mWindow, &WM_DELETE_WINDOW, 1) == 0)
+    {
+        destroy();
+        return false;
+    }
+
+    // Create an atom to identify our test event
+    TEST_EVENT = XInternAtom(mDisplay, "ANGLE_TEST_EVENT", False);
+    if (TEST_EVENT == None)
+    {
+        destroy();
+        return false;
+    }
+
+    XFlush(mDisplay);
+
+    mX = 0;
+    mY = 0;
+    mWidth = width;
+    mHeight = height;
+
+    return true;
+}
+
+void X11Window::destroy()
+{
+    if (mWindow)
+    {
+        XDestroyWindow(mDisplay, mWindow);
+        mWindow = 0;
+    }
+    if (mDisplay)
+    {
+        XCloseDisplay(mDisplay);
+        mDisplay = nullptr;
+    }
+    WM_DELETE_WINDOW = None;
+    WM_PROTOCOLS = None;
+}
+
+EGLNativeWindowType X11Window::getNativeWindow() const
+{
+    return mWindow;
+}
+
+EGLNativeDisplayType X11Window::getNativeDisplay() const
+{
+    return mDisplay;
+}
+
+void X11Window::messageLoop()
+{
+    int eventCount = XPending(mDisplay);
+    while (eventCount--)
+    {
+        XEvent event;
+        XNextEvent(mDisplay, &event);
+        processEvent(event);
+    }
+}
+
+void X11Window::setMousePosition(int x, int y)
+{
+    XWarpPointer(mDisplay, None, mWindow, 0, 0, 0, 0, x, y);
+}
+
+OSWindow *CreateOSWindow()
+{
+    return new X11Window();
+}
+
+bool X11Window::setPosition(int x, int y)
+{
+    XMoveWindow(mDisplay, mWindow, x, y);
+    XFlush(mDisplay);
+    return true;
+}
+
+bool X11Window::resize(int width, int height)
+{
+    XResizeWindow(mDisplay, mWindow, width, height);
+    XFlush(mDisplay);
+
+    Timer* timer = CreateTimer();
+    timer->start();
+
+    // Wait until the window as actually been resized so that the code calling resize
+    // can assume the window has been resized.
+    const double kResizeWaitDelay = 0.2;
+    while (mHeight != height && mWidth != width && timer->getElapsedTime() < kResizeWaitDelay)
+    {
+        messageLoop();
+        angle::Sleep(10);
+    }
+
+    delete timer;
+
+    return true;
+}
+
+void X11Window::setVisible(bool isVisible)
+{
+    if (mVisible == isVisible)
+    {
+        return;
+    }
+
+    if (isVisible)
+    {
+        XMapWindow(mDisplay, mWindow);
+
+        // Wait until we get an event saying this window is mapped so that the
+        // code calling setVisible can assume the window is visible.
+        // This is important when creating a framebuffer as the framebuffer content
+        // is undefined when the window is not visible.
+        XEvent dummyEvent;
+        XIfEvent(mDisplay, &dummyEvent, WaitForMapNotify, reinterpret_cast<XPointer>(mWindow));
+    }
+    else
+    {
+        XUnmapWindow(mDisplay, mWindow);
+        XFlush(mDisplay);
+    }
+    mVisible = isVisible;
+}
+
+void X11Window::signalTestEvent()
+{
+    XEvent event;
+    event.type = ClientMessage;
+    event.xclient.message_type = TEST_EVENT;
+    // Format needs to be valid or a BadValue is generated
+    event.xclient.format = 32;
+
+    // Hijack StructureNotifyMask as we know we will be listening for it.
+    XSendEvent(mDisplay, mWindow, False, StructureNotifyMask, &event);
+}
+
+void X11Window::processEvent(const XEvent &xEvent)
+{
+    // TODO(cwallez) text events
+    switch (xEvent.type)
+    {
+      case ButtonPress:
+        {
+            Event event;
+            MouseButton button = MOUSEBUTTON_UNKNOWN;
+            int wheelY = 0;
+
+            // The mouse wheel updates are sent via button events.
+            switch (xEvent.xbutton.button)
+            {
+              case Button4:
+                wheelY = 1;
+                break;
+              case Button5:
+                wheelY = -1;
+                break;
+              case 6:
+                break;
+              case 7:
+                break;
+
+              case Button1:
+                button = MOUSEBUTTON_LEFT;
+                break;
+              case Button2:
+                button = MOUSEBUTTON_MIDDLE;
+                break;
+              case Button3:
+                button = MOUSEBUTTON_RIGHT;
+                break;
+              case 8:
+                button = MOUSEBUTTON_BUTTON4;
+                break;
+              case 9:
+                button = MOUSEBUTTON_BUTTON5;
+                break;
+
+              default:
+                break;
+            }
+
+            if (wheelY != 0)
+            {
+                event.Type = Event::EVENT_MOUSE_WHEEL_MOVED;
+                event.MouseWheel.Delta = wheelY;
+                pushEvent(event);
+            }
+
+            if (button != MOUSEBUTTON_UNKNOWN)
+            {
+                event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
+                event.MouseButton.Button = button;
+                event.MouseButton.X = xEvent.xbutton.x;
+                event.MouseButton.Y = xEvent.xbutton.y;
+                pushEvent(event);
+            }
+        }
+        break;
+
+      case ButtonRelease:
+        {
+            Event event;
+            MouseButton button = MOUSEBUTTON_UNKNOWN;
+
+            switch (xEvent.xbutton.button)
+            {
+              case Button1:
+                button = MOUSEBUTTON_LEFT;
+                break;
+              case Button2:
+                button = MOUSEBUTTON_MIDDLE;
+                break;
+              case Button3:
+                button = MOUSEBUTTON_RIGHT;
+                break;
+              case 8:
+                button = MOUSEBUTTON_BUTTON4;
+                break;
+              case 9:
+                button = MOUSEBUTTON_BUTTON5;
+                break;
+
+              default:
+                break;
+            }
+
+            if (button != MOUSEBUTTON_UNKNOWN)
+            {
+                event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
+                event.MouseButton.Button = button;
+                event.MouseButton.X = xEvent.xbutton.x;
+                event.MouseButton.Y = xEvent.xbutton.y;
+                pushEvent(event);
+            }
+        }
+        break;
+
+      case KeyPress:
+        {
+            Event event;
+            event.Type = Event::EVENT_KEY_PRESSED;
+            event.Key.Code = X11CodeToKey(mDisplay, xEvent.xkey.keycode);
+            AddX11KeyStateToEvent(&event, xEvent.xkey.state);
+            pushEvent(event);
+        }
+        break;
+
+      case KeyRelease:
+        {
+            Event event;
+            event.Type = Event::EVENT_KEY_RELEASED;
+            event.Key.Code = X11CodeToKey(mDisplay, xEvent.xkey.keycode);
+            AddX11KeyStateToEvent(&event, xEvent.xkey.state);
+            pushEvent(event);
+        }
+        break;
+
+      case EnterNotify:
+        {
+            Event event;
+            event.Type = Event::EVENT_MOUSE_ENTERED;
+            pushEvent(event);
+        }
+        break;
+
+      case LeaveNotify:
+        {
+            Event event;
+            event.Type = Event::EVENT_MOUSE_LEFT;
+            pushEvent(event);
+        }
+        break;
+
+      case MotionNotify:
+        {
+            Event event;
+            event.Type = Event::EVENT_MOUSE_MOVED;
+            event.MouseMove.X = xEvent.xmotion.x;
+            event.MouseMove.Y = xEvent.xmotion.y;
+            pushEvent(event);
+        }
+        break;
+
+      case ConfigureNotify:
+        {
+            if (xEvent.xconfigure.width != mWidth || xEvent.xconfigure.height != mHeight)
+            {
+                Event event;
+                event.Type = Event::EVENT_RESIZED;
+                event.Size.Width = xEvent.xconfigure.width;
+                event.Size.Height = xEvent.xconfigure.height;
+                pushEvent(event);
+            }
+            if (xEvent.xconfigure.x != mX || xEvent.xconfigure.y != mY)
+            {
+                // Sometimes, the window manager reparents our window (for example
+                // when resizing) then the X and Y coordinates will be with respect to
+                // the new parent and not what the user wants to know. Use
+                // XTranslateCoordinates to get the coordinates on the screen.
+                int screen = DefaultScreen(mDisplay);
+                Window root = RootWindow(mDisplay, screen);
+
+                int x, y;
+                Window child;
+                XTranslateCoordinates(mDisplay, mWindow, root, 0, 0, &x, &y, &child);
+
+                if (x != mX || y != mY)
+                {
+                    Event event;
+                    event.Type = Event::EVENT_MOVED;
+                    event.Move.X = x;
+                    event.Move.Y = y;
+                    pushEvent(event);
+                }
+            }
+        }
+        break;
+
+      case FocusIn:
+        if (xEvent.xfocus.mode == NotifyNormal || xEvent.xfocus.mode == NotifyWhileGrabbed)
+        {
+            Event event;
+            event.Type = Event::EVENT_GAINED_FOCUS;
+            pushEvent(event);
+        }
+        break;
+
+      case FocusOut:
+        if (xEvent.xfocus.mode == NotifyNormal || xEvent.xfocus.mode == NotifyWhileGrabbed)
+        {
+            Event event;
+            event.Type = Event::EVENT_LOST_FOCUS;
+            pushEvent(event);
+        }
+        break;
+
+      case DestroyNotify:
+        // We already received WM_DELETE_WINDOW
+        break;
+
+      case ClientMessage:
+        if (xEvent.xclient.message_type == WM_PROTOCOLS &&
+            static_cast<Atom>(xEvent.xclient.data.l[0]) == WM_DELETE_WINDOW)
+        {
+            Event event;
+            event.Type = Event::EVENT_CLOSED;
+            pushEvent(event);
+        }
+        else if (xEvent.xclient.message_type == TEST_EVENT)
+        {
+            Event event;
+            event.Type = Event::EVENT_TEST;
+            pushEvent(event);
+        }
+        break;
+    }
+}
diff --git a/src/third_party/angle/util/x11/X11Window.h b/src/third_party/angle/util/x11/X11Window.h
new file mode 100644
index 0000000..ecc1de3
--- /dev/null
+++ b/src/third_party/angle/util/x11/X11Window.h
@@ -0,0 +1,56 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// X11Window.h: Definition of the implementation of OSWindow for X11
+
+#ifndef UTIL_X11_WINDOW_H
+#define UTIL_X11_WINDOW_H
+
+#include <string>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xresource.h>
+
+#include <export.h>
+
+#include "OSWindow.h"
+
+class ANGLE_EXPORT X11Window : public OSWindow
+{
+  public:
+    X11Window();
+    X11Window(int visualId);
+    ~X11Window();
+
+    bool initialize(const std::string &name, size_t width, size_t height) override;
+    void destroy() override;
+
+    EGLNativeWindowType getNativeWindow() const override;
+    EGLNativeDisplayType getNativeDisplay() const override;
+
+    void messageLoop() override;
+
+    void setMousePosition(int x, int y) override;
+    bool setPosition(int x, int y) override;
+    bool resize(int width, int height) override;
+    void setVisible(bool isVisible) override;
+
+    void signalTestEvent() override;
+
+  private:
+    void processEvent(const XEvent &event);
+
+    Atom WM_DELETE_WINDOW;
+    Atom WM_PROTOCOLS;
+    Atom TEST_EVENT;
+
+    Display *mDisplay;
+    Window mWindow;
+    int mRequestedVisualId;
+    bool mVisible;
+};
+
+#endif // UTIL_X11_WINDOW_H
diff --git a/src/third_party/skia/src/gpu/effects/GrOvalEffect.cpp b/src/third_party/skia/src/gpu/effects/GrOvalEffect.cpp
index 10fd8a6..b5f989e 100644
--- a/src/third_party/skia/src/gpu/effects/GrOvalEffect.cpp
+++ b/src/third_party/skia/src/gpu/effects/GrOvalEffect.cpp
@@ -290,6 +290,7 @@
 
 private:
     GrGLProgramDataManager::UniformHandle fEllipseUniform;
+    GrGLProgramDataManager::UniformHandle fScaleUniform;
     SkPoint                               fPrevCenter;
     SkVector                              fPrevRadii;
 
@@ -309,6 +310,15 @@
                                const char* inputColor,
                                const TransformedCoordsArray&,
                                const TextureSamplerArray& samplers) {
+    // If we're on a device with a "real" mediump then we'll do the distance computation in a space
+    // that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The
+    // inverse squared radii uniform values are already in this normalized space. The center is
+    // not.
+    const char* scaleName = NULL;
+    fScaleUniform = builder->addUniform(
+        GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType,
+        "scale", &scaleName);
+
     const EllipseEffect& ee = fp.cast<EllipseEffect>();
     const char *ellipseName;
     // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
@@ -322,6 +332,9 @@
 
     // d is the offset to the ellipse center
     fsBuilder->codeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName);
+    if (scaleName) {
+        fsBuilder->codeAppendf("d *= %s.y;", scaleName);
+    }
     fsBuilder->codeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName);
     // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
     fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n");
@@ -330,6 +343,9 @@
     // avoid calling inversesqrt on zero.
     fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
     fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
+    if (scaleName) {
+        fsBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
+    }
 
     switch (ee.getEdgeType()) {
         case kFillAA_GrProcessorEdgeType:
@@ -361,8 +377,26 @@
 void GLEllipseEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& effect) {
     const EllipseEffect& ee = effect.cast<EllipseEffect>();
     if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
-        SkScalar invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
-        SkScalar invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
+        float invRXSqd;
+        float invRYSqd;
+        // If we're using a scale factor to work around precision issues, choose the larger radius
+        // as the scale factor. The inv radii need to be pre-adjusted by the scale factor.
+        if (fScaleUniform.isValid()) {
+            if (ee.getRadii().fX > ee.getRadii().fY) {
+                invRXSqd = 1.f;
+                invRYSqd = (ee.getRadii().fX * ee.getRadii().fX) /
+                           (ee.getRadii().fY * ee.getRadii().fY);
+                pdman.set2f(fScaleUniform, ee.getRadii().fX, 1.f / ee.getRadii().fX);
+            } else {
+                invRXSqd = (ee.getRadii().fY * ee.getRadii().fY) /
+                           (ee.getRadii().fX * ee.getRadii().fX);
+                invRYSqd = 1.f;
+                pdman.set2f(fScaleUniform, ee.getRadii().fY, 1.f / ee.getRadii().fY);
+            }
+        } else {
+            invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
+            invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
+        }
         pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
         fPrevCenter = ee.getCenter();
         fPrevRadii = ee.getRadii();
diff --git a/src/third_party/skia/src/gpu/effects/GrRRectEffect.cpp b/src/third_party/skia/src/gpu/effects/GrRRectEffect.cpp
index f5131fe..addf9f5 100644
--- a/src/third_party/skia/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/third_party/skia/src/gpu/effects/GrRRectEffect.cpp
@@ -506,6 +506,7 @@
 private:
     GrGLProgramDataManager::UniformHandle fInnerRectUniform;
     GrGLProgramDataManager::UniformHandle fInvRadiiSqdUniform;
+    GrGLProgramDataManager::UniformHandle fScaleUniform;
     SkRRect                               fPrevRRect;
     typedef GrGLFragmentProcessor INHERITED;
 };
@@ -546,6 +547,14 @@
     // need be computed to determine the min alpha.
     fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
     fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
+
+    // If we're on a device with a "real" mediump then we'll do the distance computation in a space
+    // that is normalized by the largest radius. The scale uniform will be scale, 1/scale. The
+    // radii uniform values are already in this normalized space.
+    const char* scaleName = NULL;
+    fScaleUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+                                        kVec2f_GrSLType, "scale", &scaleName);
+
     switch (erre.getRRect().getType()) {
         case SkRRect::kSimple_Type: {
             const char *invRadiiXYSqdName;
@@ -554,7 +563,9 @@
                                                       "invRadiiXY",
                                                       &invRadiiXYSqdName);
             fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
-            // Z is the x/y offsets divided by squared radii.
+            if (scaleName) {
+                fsBuilder->codeAppendf("dxy *= %s.y;", scaleName);
+            }            // Z is the x/y offsets divided by squared radii.
             fsBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName);
             break;
         }
@@ -565,7 +576,10 @@
                                                       "invRadiiLTRB",
                                                       &invRadiiLTRBSqdName);
             fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
-            // Z is the x/y offsets divided by squared radii. We only care about the (at most) one
+            if (scaleName) {
+                fsBuilder->codeAppendf("dxy0 *= %s.y;", scaleName);
+                fsBuilder->codeAppendf("dxy1 *= %s.y;", scaleName);
+            }            // Z is the x/y offsets divided by squared radii. We only care about the (at most) one
             // corner where both the x and y offsets are positive, hence the maxes. (The inverse
             // squared radii will always be positive.)
             fsBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);\n",
@@ -582,6 +596,9 @@
     // avoid calling inversesqrt on zero.
     fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
     fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
+    if (scaleName) {
+        fsBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
+    }
 
     if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) {
         fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
@@ -612,8 +629,18 @@
         switch (erre.getRRect().getType()) {
             case SkRRect::kSimple_Type:
                 rect.inset(r0.fX, r0.fY);
-                pdman.set2f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX),
-                                                1.f / (r0.fY * r0.fY));
+                if (fScaleUniform.isValid()) {
+                    if (r0.fX > r0.fY) {
+                        pdman.set2f(fInvRadiiSqdUniform, 1.f, (r0.fX * r0.fX) / (r0.fY * r0.fY));
+                        pdman.set2f(fScaleUniform, r0.fX, 1.f / r0.fX);
+                    } else {
+                        pdman.set2f(fInvRadiiSqdUniform, (r0.fY * r0.fY) / (r0.fX * r0.fX), 1.f);
+                        pdman.set2f(fScaleUniform, r0.fY, 1.f / r0.fY);
+                    }
+                } else {
+                    pdman.set2f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX),
+                                                     1.f / (r0.fY * r0.fY));
+                }
                 break;
             case SkRRect::kNinePatch_Type: {
                 const SkVector& r1 = rrect.radii(SkRRect::kLowerRight_Corner);
@@ -623,10 +650,20 @@
                 rect.fTop += r0.fY;
                 rect.fRight -= r1.fX;
                 rect.fBottom -= r1.fY;
-                pdman.set4f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX),
-                                                1.f / (r0.fY * r0.fY),
-                                                1.f / (r1.fX * r1.fX),
-                                                1.f / (r1.fY * r1.fY));
+                if (fScaleUniform.isValid()) {
+                    float scale = SkTMax(SkTMax(r0.fX, r0.fY), SkTMax(r1.fX, r1.fY));
+                    float scaleSqd = scale * scale;
+                    pdman.set4f(fInvRadiiSqdUniform, scaleSqd / (r0.fX * r0.fX),
+                                                     scaleSqd / (r0.fY * r0.fY),
+                                                     scaleSqd / (r1.fX * r1.fX),
+                                                     scaleSqd / (r1.fY * r1.fY));
+                    pdman.set2f(fScaleUniform, scale, 1.f / scale);
+                } else {
+                    pdman.set4f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX),
+                                                     1.f / (r0.fY * r0.fY),
+                                                     1.f / (r1.fX * r1.fX),
+                                                     1.f / (r1.fY * r1.fY));
+                }
                 break;
             }
         default:
diff --git a/src/tools/gyp/pylib/gyp/generator/ninja.py b/src/tools/gyp/pylib/gyp/generator/ninja.py
index 53a0081..d8fe41e 100755
--- a/src/tools/gyp/pylib/gyp/generator/ninja.py
+++ b/src/tools/gyp/pylib/gyp/generator/ninja.py
@@ -76,7 +76,7 @@
 is_linux = platform.system() == 'Linux'
 is_windows = platform.system() == 'Windows'
 
-microsoft_flavors = ['win', 'xb1', 'xb1-future']
+microsoft_flavors = ['win', 'win-console', 'xb1', 'xb1-future']
 sony_flavors = ['ps3', 'ps4']
 windows_host_flavors = microsoft_flavors + sony_flavors
 
@@ -1604,14 +1604,14 @@
   # - If there is no 'make_global_settings' for CC.host/CXX.host or
   #   'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set
   #   to cc/cxx.
-  if (flavor == 'win' or (flavor in sony_flavors and is_windows)):
+  if (flavor in sony_flavors and is_windows):
     cc = 'cl.exe'
     cxx = 'cl.exe'
     ld = 'link.exe'
     gyp.msvs_emulation.GenerateEnvironmentFiles(
         toplevel_build, generator_flags, OpenOutput)
     ld_host = '$ld'
-  elif flavor in ['xb1', 'xb1-future']:
+  elif flavor in microsoft_flavors:
     cc = 'cl.exe'
     cxx = 'cl.exe'
     ld = 'link.exe'
@@ -1656,6 +1656,7 @@
   cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx)
   master_ninja.variable('cxx', cxx)
   ld = GetEnvironFallback(['LD_target', 'LD'], ld)
+  rc = GetEnvironFallback(['RC'], 'rc.exe')
 
   if not cc_host:
     cc_host = cc
@@ -1672,7 +1673,7 @@
   if flavor in microsoft_flavors:
     master_ninja.variable('ld', ld)
     master_ninja.variable('ar', os.environ.get('AR', 'ar'))
-    master_ninja.variable('rc', 'rc.exe')
+    master_ninja.variable('rc', rc)
     master_ninja.variable('asm', 'ml.exe')
     master_ninja.variable('mt', 'mt.exe')
     master_ninja.variable('use_dep_database', '1')
@@ -1920,7 +1921,7 @@
     dllcmd = ('%s gyp-win-tool link-wrapper $arch '
               '$ld /nologo $implibflag /DLL /OUT:$dll '
               '/PDB:$dll.pdb @$dll.rsp' % python_exec)
-    if not flavor in ['xb1', 'xb1-future']:
+    if not flavor in microsoft_flavors:
       # XB1 doesn't need a manifest.
       dllcmd += (' && %s gyp-win-tool manifest-wrapper $arch '
                  '$mt -nologo -manifest $manifests -out:$dll.manifest' %
@@ -1942,7 +1943,7 @@
                    '$mt -nologo -manifest $manifests -out:$out.manifest' %
                    (python_exec, python_exec))
     else:
-      assert flavor in ['xb1', 'xb1-future']
+      assert flavor in microsoft_flavors
       # XB1 doesn't need a manifest.
       link_command=('%s gyp-win-tool link-wrapper $arch '
                    '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' %